diff -Nru a/CREDITS b/CREDITS
--- a/CREDITS	2004-10-18 14:56:48 -07:00
+++ b/CREDITS	2004-10-18 14:56:48 -07:00
@@ -281,6 +281,11 @@
 S: Greenbelt, Maryland 20771
 S: USA
 
+N: Adam Belay
+E: ambx1@neo.rr.com
+D: Linux Plug and Play Support
+S: USA
+
 N: Daniele Bellucci
 E: bellucda@tiscali.it
 D: Various Janitor work.
@@ -513,6 +518,14 @@
 S: Oxford
 S: United Kingdom
 
+N: Luiz Fernando N. Capitulino
+E: lcapitulino@terra.com.br
+E: lcapitulino@prefeitura.sp.gov.br
+W: http://www.telecentros.sp.gov.br
+D: Little fixes and a lot of janitorial work
+S: E-GOV Telecentros SP
+S: Brazil
+
 N: Remy Card
 E: Remy.Card@masi.ibp.fr
 E: Remy.Card@linux.org
@@ -625,6 +638,14 @@
 D: Assorted sched/mm titbits
 S: Oxfordshire, UK.
 
+N: Kees Cook
+E: kees@outflux.net
+W: http://outflux.net/
+P: 1024D/17063E6D 9FA3 C49C 23C9 D1BC 2E30  1975 1FFF 4BA9 1706 3E6D
+D: Minor updates to SCSI code for the Communications type
+S: (ask for current address)
+S: USA
+
 N: Mark Corner
 E: mcorner@umich.edu
 W: http://www.eecs.umich.edu/~mcorner/
@@ -639,14 +660,6 @@
 S: Santa Cruz, California
 S: USA
 
-N: Kees Cook
-E: kees@outflux.net
-W: http://outflux.net/
-P: 1024D/17063E6D 9FA3 C49C 23C9 D1BC 2E30  1975 1FFF 4BA9 1706 3E6D
-D: Minor updates to SCSI code for the Communications type
-S: (ask for current address)
-S: USA
-
 N: Alan Cox
 W: http://www.linux.org.uk/diary/
 D: Linux Networking (0.99.10->2.0.29)
@@ -735,6 +748,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 +773,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
@@ -905,6 +924,10 @@
 S: S-114 79 Stockholm
 S: Sweden
 
+N: David Engebretsen
+E: engebret@us.ibm.com
+D: Linux port to 64-bit PowerPC architecture
+
 N: Michael Engel
 E: engel@unix-ag.org
 D: DECstation framebuffer drivers
@@ -1049,6 +1072,12 @@
 S: 80050-430 - Curitiba - Paraná
 S: Brazil
 
+N: Kumar Gala
+E: kumar.gala@freescale.com
+D: Embedded PowerPC 6xx/7xx/74xx/82xx/85xx support
+S: Austin, Texas 78729
+S: USA
+
 N: Nigel Gamble
 E: nigel@nrg.org
 D: Interrupt-driven printer driver
@@ -1060,12 +1089,6 @@
 N: Jeff Garzik
 E: jgarzik@pobox.com
 
-N: Kumar Gala
-E: kumar.gala@freescale.com
-D: Embedded PowerPC 6xx/7xx/74xx/82xx/85xx support
-S: Austin, Texas 78729
-S: USA
-
 N: Jacques Gelinas
 E: jacques@solucorp.qc.ca
 D: Author of the Umsdos file system
@@ -1563,10 +1586,37 @@
 D: Various Janitor work.
 S: United Kingdom
 
+N: Martin Josfsson
+E: gandalf@wlug.westbo.se
+P: 1024D/F6B6D3B1 7610 7CED 5C34 4AA6 DBA2  8BE1 5A6D AF95 F6B6 D3B1
+D: netfilter: SAME target
+D: netfilter: helper target
+D: netfilter: various other hacks
+S: Ronneby
+S: Sweden
+
 N: Ani Joshi
 E: ajoshi@shell.unixbox.com
 D: fbdev hacking
 
+N: Jesper Juhl
+E: juhl-lkml@dif.dk
+D: Various small janitor fixes, cleanups etc.
+S: Lemnosvej 1, 3.tv
+S: 2300 Copenhagen S
+S: Denmark
+
+N: Jozsef Kadlecsik
+E: kadlec@blackhole.kfki.hu
+P: 1024D/470DB964 4CB3 1A05 713E 9BF7 FAC5  5809 DD8C B7B1 470D B964
+D: netfilter: TCP window tracking code
+D: netfilter: raw table
+D: netfilter: iprange match
+D: netfilter: new logging interfaces
+D: netfilter: various other hacks
+S: Tata
+S: Hungary
+
 N: Bernhard Kaindl
 E: bkaindl@netway.at
 E: edv@bartelt.via.at
@@ -1818,11 +1868,6 @@
 S: 370 01  Ceske Budejovice
 S: Czech Republic
 
-N: Adam Belay
-E: ambx1@neo.rr.com
-D: Linux Plug and Play Support
-S: USA
-
 N: Bas Laarhoven
 E: sjml@xs4all.nl
 D: Loadable modules and ftape driver
@@ -1954,12 +1999,6 @@
 S: Niwot, Colorado 80503
 S: USA
 
-N: Pete Popov
-E: pete_popov@yahoo.com
-D: Linux/MIPS AMD/Alchemy Port and mips hacking and debugging
-S: San Jose, CA 95134
-S: USA
-
 N: Robert M. Love
 E: rml@tech9.net
 E: rml@novell.com
@@ -2127,6 +2166,16 @@
 S: (address available on request)
 S: USA
 
+N: Patrick McHardy
+E: kaber@trash.net
+P: 1024D/12155E80 B128 7DE6 FF0A C2B2 48BE  AB4C C9D4 964E 1215 5E80
+D: netfilter: endless number of bugfixes
+D: netfilter: CLASSIFY target
+D: netfilter: addrtype match
+D: tc: HFSC scheduler
+S: Freiburg
+S: Germany
+
 N: Mike McLagan
 E: mike.mclagan@linux.org
 W: http://www.invlogic.com/~mmclagan
@@ -2214,14 +2263,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
@@ -2570,6 +2618,7 @@
 E: nico@cam.org
 D: StrongARM SA1100 support integrator & hacker
 D: Xscale PXA architecture
+D: unified SMC 91C9x/91C11x ethernet driver (smc91x)
 S: Montreal, Quebec, Canada
 
 N: Ken Pizzini
@@ -2582,6 +2631,12 @@
 D: sonypi, meye drivers, mct_u232 usb serial hacks
 S: Paris, France
 
+N: Pete Popov
+E: pete_popov@yahoo.com
+D: Linux/MIPS AMD/Alchemy Port and mips hacking and debugging
+S: San Jose, CA 95134
+S: USA
+
 N: Matt Porter
 E: mporter@kernel.crashing.org
 D: Motorola PowerPC PReP support
@@ -2797,7 +2852,7 @@
 
 N: Paul `Rusty' Russell
 E: rusty@rustcorp.com.au
-W: http://www.samba.org/netfilter
+W: http://ozlabs.org/~rusty
 D: Ruggedly handsome.
 D: netfilter, ipchains with Michael Neuling.
 S: 52 Moore St
@@ -2821,7 +2876,6 @@
 S: Wellington
 S: New Zealand
 
-
 N: Sampo Saaristo
 E: sambo@cs.tut.fi
 D: Co-author of Multi-Protocol Over ATM (MPOA)
@@ -2838,6 +2892,9 @@
 S: 8006 Zuerich
 S: Switzerland
 
+N: Manuel Estrada Sainz
+D: Firmware loader (request_firmware)
+
 N: Wayne Salamon
 E: wsalamon@tislabs.com
 E: wsalamon@nai.com
@@ -3289,14 +3346,6 @@
 S: 10200 Prague 10, Hostivar
 S: Czech Republic
 
-N: James R. Van Zandt
-E: jrv@vanzandt.mv.com
-P: 1024/E298966D F0 37 4F FD E5 7E C5 E6  F1 A0 1E 22 6F 46 DA 0C
-D: Author and maintainer of the Double Talk speech synthesizer driver
-S: 27 Spencer Drive
-S: Nashua, New Hampshire 03062
-S: USA
-
 N: Heikki Vatiainen
 E: hessu@cs.tut.fi
 D: Co-author of Multi-Protocol Over ATM (MPOA), some LANE hacks
@@ -3387,6 +3436,18 @@
 S: Berkeley, CA 94720-1776
 S: USA
 
+N: Harald Welte
+E: laforge@netfilter.org
+P: 1024D/30F48BFF DBDE 6912 8831 9A53 879B  9190 5DA5 C655 30F4 8BFF
+W: http://gnumonks.org/users/laforge
+D: netfilter: new nat helper infrastructure
+D: netfilter: ULOG, ECN, DSCP target
+D: netfilter: TTL match
+D: netfilter: IPv6 mangle table
+D: netfilter: various other hacks
+S: Berlin
+S: Germany
+
 N: Bill Wendling
 E: wendling@ganymede.isdn.uiuc.edu
 W: http://www.ncsa.uiuc.edu/~wendling/
@@ -3578,6 +3639,14 @@
 S: Tokyo 153
 S: Japan
 
+N: James R. Van Zandt
+E: jrv@vanzandt.mv.com
+P: 1024/E298966D F0 37 4F FD E5 7E C5 E6  F1 A0 1E 22 6F 46 DA 0C
+D: Author and maintainer of the Double Talk speech synthesizer driver
+S: 27 Spencer Drive
+S: Nashua, New Hampshire 03062
+S: USA
+
 N: Orest Zborowski
 E: orestz@eskimo.com
 D: XFree86 and kernel development
@@ -3619,13 +3688,6 @@
 D: EISA/sysfs subsystem
 S: France
 
-N: Luiz Fernando N. Capitulino
-E: lcapitulino@terra.com.br
-E: lcapitulino@prefeitura.sp.gov.br
-W: http://www.telecentros.sp.gov.br
-D: Little fixes and a lot of janitorial work
-S: E-GOV Telecentros SP
-S: Brazil
 
 # Don't add your name here, unless you really _are_ after Marc
 # alphabetically. Leonard used to be very proud of being the 
diff -Nru a/Documentation/CodingStyle b/Documentation/CodingStyle
--- a/Documentation/CodingStyle	2004-10-18 14:56:28 -07:00
+++ b/Documentation/CodingStyle	2004-10-18 14:56:28 -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-10-18 14:56:32 -07:00
+++ b/Documentation/DMA-API.txt	2004-10-18 14:56:32 -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/Makefile b/Documentation/DocBook/Makefile
--- a/Documentation/DocBook/Makefile	2004-10-18 14:56:29 -07:00
+++ b/Documentation/DocBook/Makefile	2004-10-18 14:56:29 -07:00
@@ -185,9 +185,7 @@
 	$(patsubst %.sgml, %.9,    $(DOCBOOKS)) \
 	$(C-procfs-example)
 
-ifneq ($(wildcard $(patsubst %.html,%,$(HTML))),)
-clean-rule := rm -rf $(wildcard $(patsubst %.html,%,$(HTML)))
-endif
+clean-dirs := $(patsubst %.sgml,%,$(DOCBOOKS))
 
 #man put files in man subdir - traverse down
 subdir- := man/
diff -Nru a/Documentation/DocBook/gadget.tmpl b/Documentation/DocBook/gadget.tmpl
--- a/Documentation/DocBook/gadget.tmpl	2004-10-18 14:56:31 -07:00
+++ b/Documentation/DocBook/gadget.tmpl	2004-10-18 14:56:31 -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/DocBook/kernel-hacking.tmpl b/Documentation/DocBook/kernel-hacking.tmpl
--- a/Documentation/DocBook/kernel-hacking.tmpl	2004-10-18 14:56:32 -07:00
+++ b/Documentation/DocBook/kernel-hacking.tmpl	2004-10-18 14:56:32 -07:00
@@ -145,7 +145,7 @@
     In user context, the <varname>current</varname> pointer (indicating 
     the task we are currently executing) is valid, and
     <function>in_interrupt()</function>
-    (<filename>include/asm/hardirq.h</filename>) is <returnvalue>false
+    (<filename>include/linux/interrupt.h</filename>) is <returnvalue>false
     </returnvalue>.  
    </para>
 
@@ -241,7 +241,7 @@
    <para>
     You can tell you are in a softirq (or bottom half, or tasklet)
     using the <function>in_softirq()</function> macro 
-    (<filename class="headerfile">include/asm/hardirq.h</filename>).
+    (<filename class="headerfile">include/linux/interrupt.h</filename>).
    </para>
    <caution>
     <para>
diff -Nru a/Documentation/DocBook/mousedrivers.tmpl b/Documentation/DocBook/mousedrivers.tmpl
--- a/Documentation/DocBook/mousedrivers.tmpl	2004-10-18 14:56:49 -07:00
+++ b/Documentation/DocBook/mousedrivers.tmpl	2004-10-18 14:56:49 -07:00
@@ -940,7 +940,6 @@
         if(--mouse_users)
                 return 0;
         free_irq(OURMOUSE_IRQ, NULL);
-        MOD_DEC_USE_COUNT;
         return 0;
 }
   </programlisting>
diff -Nru a/Documentation/DocBook/usb.tmpl b/Documentation/DocBook/usb.tmpl
--- a/Documentation/DocBook/usb.tmpl	2004-10-18 14:57:05 -07:00
+++ b/Documentation/DocBook/usb.tmpl	2004-10-18 14:57:05 -07:00
@@ -251,6 +251,7 @@
 !Edrivers/usb/core/message.c
 !Edrivers/usb/core/file.c
 !Edrivers/usb/core/usb.c
+!Edrivers/usb/core/hub.c
     </chapter>
 
     <chapter><title>Host Controller APIs</title>
diff -Nru a/Documentation/IPMI.txt b/Documentation/IPMI.txt
--- a/Documentation/IPMI.txt	2004-10-18 14:55:54 -07:00
+++ b/Documentation/IPMI.txt	2004-10-18 14:55:54 -07:00
@@ -340,6 +340,8 @@
   modprobe ipmi_si.o type=<type1>,<type2>....
        ports=<port1>,<port2>... addrs=<addr1>,<addr2>...
        irqs=<irq1>,<irq2>... trydefaults=[0|1]
+       regspacings=<sp1>,<sp2>,... regsizes=<size1>,<size2>,...
+       regshifts=<shift1>,<shift2>,...
 
 Each of these except si_trydefaults is a list, the first item for the
 first interface, second item for the second interface, etc.
@@ -361,12 +363,35 @@
 any interfaces specified by ACPE are tried.  By default, the driver
 tries it, set this value to zero to turn this off.
 
+The next three parameters have to do with register layout.  The
+registers used by the interfaces may not appear at successive
+locations and they may not be in 8-bit registers.  These parameters
+allow the layout of the data in the registers to be more precisely
+specified.
+
+The regspacings parameter give the number of bytes between successive
+register start addresses.  For instance, if the regspacing is set to 4
+and the start address is 0xca2, then the address for the second
+register would be 0xca6.  This defaults to 1.
+
+The regsizes parameter gives the size of a register, in bytes.  The
+data used by IPMI is 8-bits wide, but it may be inside a larger
+register.  This parameter allows the read and write type to specified.
+It may be 1, 2, 4, or 8.  The default is 1.
+
+Since the register size may be larger than 32 bits, the IPMI data may not
+be in the lower 8 bits.  The regshifts parameter give the amount to shift
+the data to get to the actual IPMI data.
+
 When compiled into the kernel, the addresses can be specified on the
 kernel command line as:
 
   ipmi_si.type=<type1>,<type2>...
        ipmi_si.ports=<port1>,<port2>... ipmi_si.addrs=<addr1>,<addr2>...
        ipmi_si.irqs=<irq1>,<irq2>... ipmi_si.trydefaults=[0|1]
+       ipmi_si.regspacings=<sp1>,<sp2>,...
+       ipmi_si.regsizes=<size1>,<size2>,...
+       ipmi_si.regshifts=<shift1>,<shift2>,...
 
 It works the same as the module parameters of the same names.
 
@@ -496,3 +521,8 @@
 Note that if you use the NMI preaction for the watchdog, you MUST
 NOT use nmi watchdog mode 1.  If you use the NMI watchdog, you
 must use mode 2.
+
+Once you open the watchdog timer, you must write a 'V' character to the
+device to close it, or the timer will not stop.  This is a new semantic
+for the driver, but makes it consistent with the rest of the watchdog
+drivers in Linux.
diff -Nru a/Documentation/ManagementStyle b/Documentation/ManagementStyle
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/Documentation/ManagementStyle	2004-10-18 14:57:23 -07:00
@@ -0,0 +1,276 @@
+
+                Linux kernel management style
+
+This is a short document describing the preferred (or made up, depending
+on who you ask) management style for the linux kernel.  It's meant to
+mirror the CodingStyle document to some degree, and mainly written to
+avoid answering (*) the same (or similar) questions over and over again. 
+
+Management style is very personal and much harder to quantify than
+simple coding style rules, so this document may or may not have anything
+to do with reality.  It started as a lark, but that doesn't mean that it
+might not actually be true. You'll have to decide for yourself.
+
+Btw, when talking about "kernel manager", it's all about the technical
+lead persons, not the people who do traditional management inside
+companies.  If you sign purchase orders or you have any clue about the
+budget of your group, you're almost certainly not a kernel manager. 
+These suggestions may or may not apply to you. 
+
+First off, I'd suggest buying "Seven Habits of Highly Successful
+People", and NOT read it.  Burn it, it's a great symbolic gesture. 
+
+(*) This document does so not so much by answering the question, but by
+making it painfully obvious to the questioner that we don't have a clue
+to what the answer is. 
+
+Anyway, here goes:
+
+
+		Chapter 1: Decisions
+
+Everybody thinks managers make decisions, and that decision-making is
+important.  The bigger and more painful the decision, the bigger the
+manager must be to make it.  That's very deep and obvious, but it's not
+actually true. 
+
+The name of the game is to _avoid_ having to make a decision.  In
+particular, if somebody tells you "choose (a) or (b), we really need you
+to decide on this", you're in trouble as a manager.  The people you
+manage had better know the details better than you, so if they come to
+you for a technical decision, you're screwed.  You're clearly not
+competent to make that decision for them. 
+
+(Corollary:if the people you manage don't know the details better than
+you, you're also screwed, although for a totally different reason. 
+Namely that you are in the wrong job, and that _they_ should be managing
+your brilliance instead). 
+
+So the name of the game is to _avoid_ decisions, at least the big and
+painful ones.  Making small and non-consequential decisions is fine, and
+makes you look like you know what you're doing, so what a kernel manager
+needs to do is to turn the big and painful ones into small things where
+nobody really cares. 
+
+It helps to realize that the key difference between a big decision and a
+small one is whether you can fix your decision afterwards.  Any decision
+can be made small by just always making sure that if you were wrong (and
+you _will_ be wrong), you can always undo the damage later by
+backtracking.  Suddenly, you get to be doubly managerial for making
+_two_ inconsequential decisions - the wrong one _and_ the right one. 
+
+And people will even see that as true leadership (*cough* bullshit
+*cough*).
+
+Thus the key to avoiding big decisions becomes to just avoiding to do
+things that can't be undone.  Don't get ushered into a corner from which
+you cannot escape.  A cornered rat may be dangerous - a cornered manager
+is just pitiful. 
+
+It turns out that since nobody would be stupid enough to ever really let
+a kernel manager have huge fiscal responsibility _anyway_, it's usually
+fairly easy to backtrack.  Since you're not going to be able to waste
+huge amounts of money that you might not be able to repay, the only
+thing you can backtrack on is a technical decision, and there
+back-tracking is very easy: just tell everybody that you were an
+incompetent nincompoop, say you're sorry, and undo all the worthless
+work you had people work on for the last year.  Suddenly the decision
+you made a year ago wasn't a big decision after all, since it could be
+easily undone. 
+
+It turns out that some people have trouble with this approach, for two
+reasons:
+ - admitting you were an idiot is harder than it looks.  We all like to
+   maintain appearances, and coming out in public to say that you were
+   wrong is sometimes very hard indeed. 
+ - having somebody tell you that what you worked on for the last year
+   wasn't worthwhile after all can be hard on the poor lowly engineers
+   too, and while the actual _work_ was easy enough to undo by just
+   deleting it, you may have irrevocably lost the trust of that
+   engineer.  And remember: "irrevocable" was what we tried to avoid in
+   the first place, and your decision ended up being a big one after
+   all. 
+
+Happily, both of these reasons can be mitigated effectively by just
+admitting up-front that you don't have a friggin' clue, and telling
+people ahead of the fact that your decision is purely preliminary, and
+might be the wrong thing.  You should always reserve the right to change
+your mind, and make people very _aware_ of that.  And it's much easier
+to admit that you are stupid when you haven't _yet_ done the really
+stupid thing.
+
+Then, when it really does turn out to be stupid, people just roll their
+eyes and say "Oops, he did it again".  
+
+This preemptive admission of incompetence might also make the people who
+actually do the work also think twice about whether it's worth doing or
+not.  After all, if _they_ aren't certain whether it's a good idea, you
+sure as hell shouldn't encourage them by promising them that what they
+work on will be included.  Make them at least think twice before they
+embark on a big endeavor. 
+
+Remember: they'd better know more about the details than you do, and
+they usually already think they have the answer to everything.  The best
+thing you can do as a manager is not to instill confidence, but rather a
+healthy dose of critical thinking on what they do. 
+
+Btw, another way to avoid a decision is to plaintively just whine "can't
+we just do both?" and look pitiful.  Trust me, it works.  If it's not
+clear which approach is better, they'll eventually figure it out.  The
+answer may end up being that both teams get so frustrated by the
+situation that they just give up. 
+
+That may sound like a failure, but it's usually a sign that there was
+something wrong with both projects, and the reason the people involved
+couldn't decide was that they were both wrong.  You end up coming up
+smelling like roses, and you avoided yet another decision that you could
+have screwed up on. 
+
+
+		Chapter 2: People
+
+Most people are idiots, and being a manager means you'll have to deal
+with it, and perhaps more importantly, that _they_ have to deal with
+_you_. 
+
+It turns out that while it's easy to undo technical mistakes, it's not
+as easy to undo personality disorders.  You just have to live with
+theirs - and yours. 
+
+However, in order to prepare yourself as a kernel manager, it's best to
+remember not to burn any bridges, bomb any innocent villagers, or
+alienate too many kernel developers. It turns out that alienating people
+is fairly easy, and un-alienating them is hard. Thus "alienating"
+immediately falls under the heading of "not reversible", and becomes a
+no-no according to Chapter 1.
+
+There's just a few simple rules here:
+ (1) don't call people d*ckheads (at least not in public)
+ (2) learn how to apologize when you forgot rule (1)
+
+The problem with #1 is that it's very easy to do, since you can say
+"you're a d*ckhead" in millions of different ways (*), sometimes without
+even realizing it, and almost always with a white-hot conviction that
+you are right. 
+
+And the more convinced you are that you are right (and let's face it,
+you can call just about _anybody_ a d*ckhead, and you often _will_ be
+right), the harder it ends up being to apologize afterwards. 
+
+To solve this problem, you really only have two options:
+ - get really good at apologies
+ - spread the "love" out so evenly that nobody really ends up feeling
+   like they get unfairly targeted.  Make it inventive enough, and they
+   might even be amused. 
+
+The option of being unfailingly polite really doesn't exist. Nobody will
+trust somebody who is so clearly hiding his true character.
+
+(*) Paul Simon sang "Fifty Ways to Lose Your Lover", because quite
+frankly, "A Million Ways to Tell a Developer He Is a D*ckhead" doesn't
+scan nearly as well.  But I'm sure he thought about it. 
+
+
+		Chapter 3: People II - the Good Kind
+
+While it turns out that most people are idiots, the corollary to that is
+sadly that you are one too, and that while we can all bask in the secure
+knowledge that we're better than the average person (let's face it,
+nobody ever believes that they're average or below-average), we should
+also admit that we're not the sharpest knife around, and there will be
+other people that are less of an idiot that you are. 
+
+Some people react badly to smart people.  Others take advantage of them. 
+
+Make sure that you, as a kernel maintainer, are in the second group. 
+Suck up to them, because they are the people who will make your job
+easier. In particular, they'll be able to make your decisions for you,
+which is what the game is all about.
+
+So when you find somebody smarter than you are, just coast along.  Your
+management responsibilities largely become ones of saying "Sounds like a
+good idea - go wild", or "That sounds good, but what about xxx?".  The
+second version in particular is a great way to either learn something
+new about "xxx" or seem _extra_ managerial by pointing out something the
+smarter person hadn't thought about.  In either case, you win.
+
+One thing to look out for is to realize that greatness in one area does
+not necessarily translate to other areas.  So you might prod people in
+specific directions, but let's face it, they might be good at what they
+do, and suck at everything else.  The good news is that people tend to
+naturally gravitate back to what they are good at, so it's not like you
+are doing something irreversible when you _do_ prod them in some
+direction, just don't push too hard.
+
+
+		Chapter 4: Placing blame
+
+Things will go wrong, and people want somebody to blame. Tag, you're it.
+
+It's not actually that hard to accept the blame, especially if people
+kind of realize that it wasn't _all_ your fault.  Which brings us to the
+best way of taking the blame: do it for another guy. You'll feel good
+for taking the fall, he'll feel good about not getting blamed, and the
+guy who lost his whole 36GB porn-collection because of your incompetence
+will grudgingly admit that you at least didn't try to weasel out of it.
+
+Then make the developer who really screwed up (if you can find him) know
+_in_private_ that he screwed up.  Not just so he can avoid it in the
+future, but so that he knows he owes you one.  And, perhaps even more
+importantly, he's also likely the person who can fix it.  Because, let's
+face it, it sure ain't you. 
+
+Taking the blame is also why you get to be manager in the first place. 
+It's part of what makes people trust you, and allow you the potential
+glory, because you're the one who gets to say "I screwed up".  And if
+you've followed the previous rules, you'll be pretty good at saying that
+by now. 
+
+
+		Chapter 5: Things to avoid
+
+There's one thing people hate even more than being called "d*ckhead",
+and that is being called a "d*ckhead" in a sanctimonious voice.  The
+first you can apologize for, the second one you won't really get the
+chance.  They likely will no longer be listening even if you otherwise
+do a good job. 
+
+We all think we're better than anybody else, which means that when
+somebody else puts on airs, it _really_ rubs us the wrong way.  You may
+be morally and intellectually superior to everybody around you, but
+don't try to make it too obvious unless you really _intend_ to irritate
+somebody (*). 
+
+Similarly, don't be too polite or subtle about things. Politeness easily
+ends up going overboard and hiding the problem, and as they say, "On the
+internet, nobody can hear you being subtle". Use a big blunt object to
+hammer the point in, because you can't really depend on people getting
+your point otherwise.
+
+Some humor can help pad both the bluntness and the moralizing.  Going
+overboard to the point of being ridiculous can drive a point home
+without making it painful to the recipient, who just thinks you're being
+silly.  It can thus help get through the personal mental block we all
+have about criticism. 
+
+(*) Hint: internet newsgroups that are not directly related to your work
+are great ways to take out your frustrations at other people. Write
+insulting posts with a sneer just to get into a good flame every once in
+a while, and you'll feel cleansed. Just don't crap too close to home.
+
+
+		Chapter 6: Why me?
+
+Since your main responsibility seems to be to take the blame for other
+peoples mistakes, and make it painfully obvious to everybody else that
+you're incompetent, the obvious question becomes one of why do it in the
+first place?
+
+First off, while you may or may not get screaming teenage girls (or
+boys, let's not be judgmental or sexist here) knocking on your dressing
+room door, you _will_ get an immense feeling of personal accomplishment
+for being "in charge".  Never mind the fact that you're really leading
+by trying to keep up with everybody else and running after them as fast
+as you can.  Everybody will still think you're the person in charge. 
+
+It's a great job if you can hack it.
diff -Nru a/Documentation/RCU/RTFP.txt b/Documentation/RCU/RTFP.txt
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/Documentation/RCU/RTFP.txt	2004-10-18 14:57:24 -07:00
@@ -0,0 +1,387 @@
+Read the F-ing Papers!
+
+
+This document describes RCU-related publications, and is followed by
+the corresponding bibtex entries.
+
+The first thing resembling RCU was published in 1980, when Kung and Lehman
+[Kung80] recommended use of a garbage collector to defer destruction
+of nodes in a parallel binary search tree in order to simplify its
+implementation.  This works well in environments that have garbage
+collectors, but current production garbage collectors incur significant
+read-side overhead.
+
+In 1982, Manber and Ladner [Manber82,Manber84] recommended deferring
+destruction until all threads running at that time have terminated, again
+for a parallel binary search tree.  This approach works well in systems
+with short-lived threads, such as the K42 research operating system.
+However, Linux has long-lived tasks, so more is needed.
+
+In 1986, Hennessy, Osisek, and Seigh [Hennessy89] introduced passive
+serialization, which is an RCU-like mechanism that relies on the presence
+of "quiescent states" in the VM/XA hypervisor that are guaranteed not
+to be referencing the data structure.  However, this mechanism was not
+optimized for modern computer systems, which is not surprising given
+that these overheads were not so expensive in the mid-80s.  Nonetheless,
+passive serialization appears to be the first deferred-destruction
+mechanism to be used in production.  Furthermore, the relevant patent has
+lapsed, so this approach may be used in non-GPL software, if desired.
+(In contrast, use of RCU is permitted only in software licensed under
+GPL.  Sorry!!!)
+
+In 1990, Pugh [Pugh90] noted that explicitly tracking which threads
+were reading a given data structure permitted deferred free to operate
+in the presence of non-terminating threads.  However, this explicit
+tracking imposes significant read-side overhead, which is undesirable
+in read-mostly situations.  This algorithm does take pains to avoid
+write-side contention and parallelize the other write-side overheads by
+providing a fine-grained locking design, however, it would be interesting
+to see how much of the performance advantage reported in 1990 remains
+in 2004.
+
+At about this same time, Adams [Adams91] described ``chaotic relaxation'',
+where the normal barriers between successive iterations of convergent
+numerical algorithms are relaxed, so that iteration $n$ might use
+data from iteration $n-1$ or even $n-2$.  This introduces error,
+which typically slows convergence and thus increases the number of
+iterations required.  However, this increase is sometimes more than made
+up for by a reduction in the number of expensive barrier operations,
+which are otherwise required to synchronize the threads at the end
+of each iteration.  Unfortunately, chaotic relaxation requires highly
+structured data, such as the matrices used in scientific programs, and
+is thus inapplicable to most data structures in operating-system kernels.
+
+In 1993, Jacobson [Jacobson93] verbally described what is perhaps the
+simplest deferred-free technique: simply waiting a fixed amount of time
+before freeing blocks awaiting deferred free.  Jacobson did not describe
+any write-side changes he might have made in this work using SGI's Irix
+kernel.  Aju John published a similar technique in 1995 [AjuJohn95].
+This works well if there is a well-defined upper bound on the length of
+time that reading threads can hold references, as there might well be in
+hard real-time systems.  However, if this time is exceeded, perhaps due
+to preemption, excessive interrupts, or larger-than-anticipated load,
+memory corruption can ensue, with no reasonable means of diagnosis.
+Jacobson's technique is therefore inappropriate for use in production
+operating-system kernels, except when such kernels can provide hard
+real-time response guarantees for all operations.
+
+Also in 1995, Pu et al. [Pu95a] applied a technique similar to that of Pugh's
+read-side-tracking to permit replugging of algorithms within a commercial
+Unix operating system.  However, this replugging permitted only a single
+reader at a time.  The following year, this same group of researchers
+extended their technique to allow for multiple readers [Cowan96a].
+Their approach requires memory barriers (and thus pipeline stalls),
+but reduces memory latency, contention, and locking overheads.
+
+1995 also saw the first publication of DYNIX/ptx's RCU mechanism
+[Slingwine95], which was optimized for modern CPU architectures,
+and was successfully applied to a number of situations within the
+DYNIX/ptx kernel.  The corresponding conference paper appeared in 1998
+[McKenney98].
+
+In 1999, the Tornado and K42 groups described their "generations"
+mechanism, which quite similar to RCU [Gamsa99].  These operating systems
+made pervasive use of RCU in place of "existence locks", which greatly
+simplifies locking hierarchies.
+
+2001 saw the first RCU presentation involving Linux [McKenney01a]
+at OLS.  The resulting abundance of RCU patches was presented the
+following year [McKenney02a], and use of RCU in dcache was first
+described that same year [Linder02a].
+
+Also in 2002, Michael [Michael02b,Michael02a] presented techniques
+that defer the destruction of data structures to simplify non-blocking
+synchronization (wait-free synchronization, lock-free synchronization,
+and obstruction-free synchronization are all examples of non-blocking
+synchronization).  In particular, this technique eliminates locking,
+reduces contention, reduces memory latency for readers, and parallelizes
+pipeline stalls and memory latency for writers.  However, these
+techniques still impose significant read-side overhead in the form of
+memory barriers.  Researchers at Sun worked along similar lines in the
+same timeframe [HerlihyLM02,HerlihyLMS03].
+
+In 2003, the K42 group described how RCU could be used to create
+hot-pluggable implementations of operating-system functions.  Later that
+year saw a paper describing an RCU implementation of System V IPC
+[Arcangeli03], and an introduction to RCU in Linux Journal [McKenney03a].
+
+2004 has seen a Linux-Journal article on use of RCU in dcache
+[McKenney04a], a performance comparison of locking to RCU on several
+different CPUs [McKenney04b], a dissertation describing use of RCU in a
+number of operating-system kernels [PaulEdwardMcKenneyPhD], and a paper
+describing how to make RCU safe for soft-realtime applications [Sarma04c].
+
+
+Bibtex Entries
+
+@article{Kung80
+,author="H. T. Kung and Q. Lehman"
+,title="Concurrent Maintenance of Binary Search Trees"
+,Year="1980"
+,Month="September"
+,journal="ACM Transactions on Database Systems"
+,volume="5"
+,number="3"
+,pages="354-382"
+}
+
+@techreport{Manber82
+,author="Udi Manber and Richard E. Ladner"
+,title="Concurrency Control in a Dynamic Search Structure"
+,institution="Department of Computer Science, University of Washington"
+,address="Seattle, Washington"
+,year="1982"
+,number="82-01-01"
+,month="January"
+,pages="28"
+}
+
+@article{Manber84
+,author="Udi Manber and Richard E. Ladner"
+,title="Concurrency Control in a Dynamic Search Structure"
+,Year="1984"
+,Month="September"
+,journal="ACM Transactions on Database Systems"
+,volume="9"
+,number="3"
+,pages="439-455"
+}
+
+@techreport{Hennessy89
+,author="James P. Hennessy and Damian L. Osisek and Joseph W. {Seigh II}"
+,title="Passive Serialization in a Multitasking Environment"
+,institution="US Patent and Trademark Office"
+,address="Washington, DC"
+,year="1989"
+,number="US Patent 4,809,168 (lapsed)"
+,month="February"
+,pages="11"
+}
+
+@techreport{Pugh90
+,author="William Pugh"
+,title="Concurrent Maintenance of Skip Lists"
+,institution="Institute of Advanced Computer Science Studies, Department of Computer Science, University of Maryland"
+,address="College Park, Maryland"
+,year="1990"
+,number="CS-TR-2222.1"
+,month="June"
+}
+
+@Book{Adams91
+,Author="Gregory R. Adams"
+,title="Concurrent Programming, Principles, and Practices"
+,Publisher="Benjamin Cummins"
+,Year="1991"
+}
+
+@unpublished{Jacobson93
+,author="Van Jacobson"
+,title="Avoid Read-Side Locking Via Delayed Free"
+,year="1993"
+,month="September"
+,note="Verbal discussion"
+}
+
+@Conference{AjuJohn95
+,Author="Aju John"
+,Title="Dynamic vnodes -- Design and Implementation"
+,Booktitle="{USENIX Winter 1995}"
+,Publisher="USENIX Association"
+,Month="January"
+,Year="1995"
+,pages="11-23"
+,Address="New Orleans, LA"
+}
+
+@techreport{Slingwine95
+,author="John D. Slingwine and Paul E. McKenney"
+,title="Apparatus and Method for Achieving Reduced Overhead Mutual
+Exclusion and Maintaining Coherency in a Multiprocessor System
+Utilizing Execution History and Thread Monitoring"
+,institution="US Patent and Trademark Office"
+,address="Washington, DC"
+,year="1995"
+,number="US Patent 5,442,758 (contributed under GPL)"
+,month="August"
+}
+
+@techreport{Slingwine97
+,author="John D. Slingwine and Paul E. McKenney"
+,title="Method for maintaining data coherency using thread
+activity summaries in a multicomputer system"
+,institution="US Patent and Trademark Office"
+,address="Washington, DC"
+,year="1997"
+,number="US Patent 5,608,893 (contributed under GPL)"
+,month="March"
+}
+
+@techreport{Slingwine98
+,author="John D. Slingwine and Paul E. McKenney"
+,title="Apparatus and method for achieving reduced overhead
+mutual exclusion and maintaining coherency in a multiprocessor
+system utilizing execution history and thread monitoring"
+,institution="US Patent and Trademark Office"
+,address="Washington, DC"
+,year="1998"
+,number="US Patent 5,727,209 (contributed under GPL)"
+,month="March"
+}
+
+@Conference{McKenney98
+,Author="Paul E. McKenney and John D. Slingwine"
+,Title="Read-Copy Update: Using Execution History to Solve Concurrency
+Problems"
+,Booktitle="{Parallel and Distributed Computing and Systems}"
+,Month="October"
+,Year="1998"
+,pages="509-518"
+,Address="Las Vegas, NV"
+}
+
+@Conference{Gamsa99
+,Author="Ben Gamsa and Orran Krieger and Jonathan Appavoo and Michael Stumm"
+,Title="Tornado: Maximizing Locality and Concurrency in a Shared Memory
+Multiprocessor Operating System"
+,Booktitle="{Proceedings of the 3\textsuperscript{rd} Symposium on
+Operating System Design and Implementation}"
+,Month="February"
+,Year="1999"
+,pages="87-100"
+,Address="New Orleans, LA"
+}
+
+@techreport{Slingwine01
+,author="John D. Slingwine and Paul E. McKenney"
+,title="Apparatus and method for achieving reduced overhead
+mutual exclusion and maintaining coherency in a multiprocessor
+system utilizing execution history and thread monitoring"
+,institution="US Patent and Trademark Office"
+,address="Washington, DC"
+,year="2001"
+,number="US Patent 5,219,690 (contributed under GPL)"
+,month="April"
+}
+
+@Conference{McKenney01a
+,Author="Paul E. McKenney and Jonathan Appavoo and Andi Kleen and
+Orran Krieger and Rusty Russell and Dipankar Sarma and Maneesh Soni"
+,Title="Read-Copy Update"
+,Booktitle="{Ottawa Linux Symposium}"
+,Month="July"
+,Year="2001"
+,note="Available:
+\url{http://www.linuxsymposium.org/2001/abstracts/readcopy.php}
+\url{http://www.rdrop.com/users/paulmck/rclock/rclock_OLS.2001.05.01c.pdf}
+[Viewed June 23, 2004]"
+annotation="
+Described RCU, and presented some patches implementing and using it in
+the Linux kernel.
+"
+}
+
+@Conference{Linder02a
+,Author="Hanna Linder and Dipankar Sarma and Maneesh Soni"
+,Title="Scalability of the Directory Entry Cache"
+,Booktitle="{Ottawa Linux Symposium}"
+,Month="June"
+,Year="2002"
+,pages="289-300"
+}
+
+@Conference{McKenney02a
+,Author="Paul E. McKenney and Dipankar Sarma and
+Andrea Arcangeli and Andi Kleen and Orran Krieger and Rusty Russell"
+,Title="Read-Copy Update"
+,Booktitle="{Ottawa Linux Symposium}"
+,Month="June"
+,Year="2002"
+,pages="338-367"
+,note="Available:
+\url{http://www.linux.org.uk/~ajh/ols2002_proceedings.pdf.gz}
+[Viewed June 23, 2004]"
+}
+
+@article{Appavoo03a
+,author="J. Appavoo and K. Hui and C. A. N. Soules and R. W. Wisniewski and
+D. M. {Da Silva} and O. Krieger and M. A. Auslander and D. J. Edelsohn and
+B. Gamsa and G. R. Ganger and P. McKenney and M. Ostrowski and
+B. Rosenburg and M. Stumm and J. Xenidis"
+,title="Enabling Autonomic Behavior in Systems Software With Hot Swapping"
+,Year="2003"
+,Month="January"
+,journal="IBM Systems Journal"
+,volume="42"
+,number="1"
+,pages="60-76"
+}
+
+@Conference{Arcangeli03
+,Author="Andrea Arcangeli and Mingming Cao and Paul E. McKenney and
+Dipankar Sarma"
+,Title="Using Read-Copy Update Techniques for {System V IPC} in the
+{Linux} 2.5 Kernel"
+,Booktitle="Proceedings of the 2003 USENIX Annual Technical Conference
+(FREENIX Track)"
+,Publisher="USENIX Association"
+,year="2003"
+,month="June"
+,pages="297-310"
+}
+
+@article{McKenney03a
+,author="Paul E. McKenney"
+,title="Using {RCU} in the {Linux} 2.5 Kernel"
+,Year="2003"
+,Month="October"
+,journal="Linux Journal"
+,volume="1"
+,number="114"
+,pages="18-26"
+}
+
+@article{McKenney04a
+,author="Paul E. McKenney and Dipankar Sarma and Maneesh Soni"
+,title="Scaling dcache with {RCU}"
+,Year="2004"
+,Month="January"
+,journal="Linux Journal"
+,volume="1"
+,number="118"
+,pages="38-46"
+}
+
+@Conference{McKenney04b
+,Author="Paul E. McKenney"
+,Title="{RCU} vs. Locking Performance on Different {CPUs}"
+,Booktitle="{linux.conf.au}"
+,Month="January"
+,Year="2004"
+,Address="Adelaide, Australia"
+,note="Available:
+\url{http://www.linux.org.au/conf/2004/abstracts.html#90}
+\url{http://www.rdrop.com/users/paulmck/rclock/lockperf.2004.01.17a.pdf}
+[Viewed June 23, 2004]"
+}
+
+@phdthesis{PaulEdwardMcKenneyPhD
+,author="Paul E. McKenney"
+,title="Exploiting Deferred Destruction:
+An Analysis of Read-Copy-Update Techniques
+in Operating System Kernels"
+,school="OGI School of Science and Engineering at
+Oregon Health and Sciences University"
+,year="2004"
+}
+
+@Conference{Sarma04c
+,Author="Dipankar Sarma and Paul E. McKenney"
+,Title="Making RCU Safe for Deep Sub-Millisecond Response Realtime Applications"
+,Booktitle="Proceedings of the 2004 USENIX Annual Technical Conference
+(FREENIX Track)"
+,Publisher="USENIX Association"
+,year="2004"
+,month="June"
+,pages="182-191"
+}
diff -Nru a/Documentation/RCU/UP.txt b/Documentation/RCU/UP.txt
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/Documentation/RCU/UP.txt	2004-10-18 14:57:23 -07:00
@@ -0,0 +1,64 @@
+RCU on Uniprocessor Systems
+
+
+A common misconception is that, on UP systems, the call_rcu() primitive
+may immediately invoke its function, and that the synchronize_kernel
+primitive may return immediately.  The basis of this misconception
+is that since there is only one CPU, it should not be necessary to
+wait for anything else to get done, since there are no other CPUs for
+anything else to be happening on.  Although this approach will sort of
+work a surprising amount of the time, it is a very bad idea in general.
+This document presents two examples that demonstrate exactly how bad an
+idea this is.
+
+
+Example 1: softirq Suicide
+
+Suppose that an RCU-based algorithm scans a linked list containing
+elements A, B, and C in process context, and can delete elements from
+this same list in softirq context.  Suppose that the process-context scan
+is referencing element B when it is interrupted by softirq processing,
+which deletes element B, and then invokes call_rcu() to free element B
+after a grace period.
+
+Now, if call_rcu() were to directly invoke its arguments, then upon return
+from softirq, the list scan would find itself referencing a newly freed
+element B.  This situation can greatly decrease the life expectancy of
+your kernel.
+
+
+Example 2: Function-Call Fatality
+
+Of course, one could avert the suicide described in the preceding example
+by having call_rcu() directly invoke its arguments only if it was called
+from process context.  However, this can fail in a similar manner.
+
+Suppose that an RCU-based algorithm again scans a linked list containing
+elements A, B, and C in process contexts, but that it invokes a function
+on each element as it is scanned.  Suppose further that this function
+deletes element B from the list, then passes it to call_rcu() for deferred
+freeing.  This may be a bit unconventional, but it is perfectly legal
+RCU usage, since call_rcu() must wait for a grace period to elapse.
+Therefore, in this case, allowing call_rcu() to immediately invoke
+its arguments would cause it to fail to make the fundamental guarantee
+underlying RCU, namely that call_rcu() defers invoking its arguments until
+all RCU read-side critical sections currently executing have completed.
+
+Quick Quiz: why is it -not- legal to invoke synchronize_kernel() in
+this case?
+
+
+Summary
+
+Permitting call_rcu() to immediately invoke its arguments or permitting
+synchronize_kernel() to immediately return breaks RCU, even on a UP system.
+So do not do it!  Even on a UP system, the RCU infrastructure -must-
+respect grace periods.
+
+
+Answer to Quick Quiz
+
+The calling function is scanning an RCU-protected linked list, and
+is therefore within an RCU read-side critical section.  Therefore,
+the called function has been invoked within an RCU read-side critical
+section, and is not permitted to block.
diff -Nru a/Documentation/RCU/arrayRCU.txt b/Documentation/RCU/arrayRCU.txt
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/Documentation/RCU/arrayRCU.txt	2004-10-18 14:57:21 -07:00
@@ -0,0 +1,141 @@
+Using RCU to Protect Read-Mostly Arrays
+
+
+Although RCU is more commonly used to protect linked lists, it can
+also be used to protect arrays.  Three situations are as follows:
+
+1.  Hash Tables
+
+2.  Static Arrays
+
+3.  Resizeable Arrays
+
+Each of these situations are discussed below.
+
+
+Situation 1: Hash Tables
+
+Hash tables are often implemented as an array, where each array entry
+has a linked-list hash chain.  Each hash chain can be protected by RCU
+as described in the listRCU.txt document.  This approach also applies
+to other array-of-list situations, such as radix trees.
+
+
+Situation 2: Static Arrays
+
+Static arrays, where the data (rather than a pointer to the data) is
+located in each array element, and where the array is never resized,
+have not been used with RCU.  Rik van Riel recommends using seqlock in
+this situation, which would also have minimal read-side overhead as long
+as updates are rare.
+
+Quick Quiz:  Why is it so important that updates be rare when
+	     using seqlock?
+
+
+Situation 3: Resizeable Arrays
+
+Use of RCU for resizeable arrays is demonstrated by the grow_ary()
+function used by the System V IPC code.  The array is used to map from
+semaphore, message-queue, and shared-memory IDs to the data structure
+that represents the corresponding IPC construct.  The grow_ary()
+function does not acquire any locks; instead its caller must hold the
+ids->sem semaphore.
+
+The grow_ary() function, shown below, does some limit checks, allocates a
+new ipc_id_ary, copies the old to the new portion of the new, initializes
+the remainder of the new, updates the ids->entries pointer to point to
+the new array, and invokes ipc_rcu_putref() to free up the old array.
+Note that rcu_assign_pointer() is used to update the ids->entries pointer,
+which includes any memory barriers required on whatever architecture
+you are running on.
+
+	static int grow_ary(struct ipc_ids* ids, int newsize)
+	{
+		struct ipc_id_ary* new;
+		struct ipc_id_ary* old;
+		int i;
+		int size = ids->entries->size;
+
+		if(newsize > IPCMNI)
+			newsize = IPCMNI;
+		if(newsize <= size)
+			return newsize;
+
+		new = ipc_rcu_alloc(sizeof(struct kern_ipc_perm *)*newsize +
+				    sizeof(struct ipc_id_ary));
+		if(new == NULL)
+			return size;
+		new->size = newsize;
+		memcpy(new->p, ids->entries->p,
+		       sizeof(struct kern_ipc_perm *)*size +
+		       sizeof(struct ipc_id_ary));
+		for(i=size;i<newsize;i++) {
+			new->p[i] = NULL;
+		}
+		old = ids->entries;
+
+		/*
+		 * Use rcu_assign_pointer() to make sure the memcpyed
+		 * contents of the new array are visible before the new
+		 * array becomes visible.
+		 */
+		rcu_assign_pointer(ids->entries, new);
+
+		ipc_rcu_putref(old);
+		return newsize;
+	}
+
+The ipc_rcu_putref() function decrements the array's reference count
+and then, if the reference count has dropped to zero, uses call_rcu()
+to free the array after a grace period has elapsed.
+
+The array is traversed by the ipc_lock() function.  This function
+indexes into the array under the protection of rcu_read_lock(),
+using rcu_dereference() to pick up the pointer to the array so
+that it may later safely be dereferenced -- memory barriers are
+required on the Alpha CPU.  Since the size of the array is stored
+with the array itself, there can be no array-size mismatches, so
+a simple check suffices.  The pointer to the structure corresponding
+to the desired IPC object is placed in "out", with NULL indicating
+a non-existent entry.  After acquiring "out->lock", the "out->deleted"
+flag indicates whether the IPC object is in the process of being
+deleted, and, if not, the pointer is returned.
+
+	struct kern_ipc_perm* ipc_lock(struct ipc_ids* ids, int id)
+	{
+		struct kern_ipc_perm* out;
+		int lid = id % SEQ_MULTIPLIER;
+		struct ipc_id_ary* entries;
+
+		rcu_read_lock();
+		entries = rcu_dereference(ids->entries);
+		if(lid >= entries->size) {
+			rcu_read_unlock();
+			return NULL;
+		}
+		out = entries->p[lid];
+		if(out == NULL) {
+			rcu_read_unlock();
+			return NULL;
+		}
+		spin_lock(&out->lock);
+
+		/* ipc_rmid() may have already freed the ID while ipc_lock
+		 * was spinning: here verify that the structure is still valid
+		 */
+		if (out->deleted) {
+			spin_unlock(&out->lock);
+			rcu_read_unlock();
+			return NULL;
+		}
+		return out;
+	}
+
+
+Answer to Quick Quiz:
+
+	The reason that it is important that updates be rare when
+	using seqlock is that frequent updates can livelock readers.
+	One way to avoid this problem is to assign a seqlock for
+	each array entry rather than to the entire array.
diff -Nru a/Documentation/RCU/checklist.txt b/Documentation/RCU/checklist.txt
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/Documentation/RCU/checklist.txt	2004-10-18 14:57:23 -07:00
@@ -0,0 +1,157 @@
+Review Checklist for RCU Patches
+
+
+This document contains a checklist for producing and reviewing patches
+that make use of RCU.  Violating any of the rules listed below will
+result in the same sorts of problems that leaving out a locking primitive
+would cause.  This list is based on experiences reviewing such patches
+over a rather long period of time, but improvements are always welcome!
+
+0.	Is RCU being applied to a read-mostly situation?  If the data
+	structure is updated more than about 10% of the time, then
+	you should strongly consider some other approach, unless
+	detailed performance measurements show that RCU is nonetheless
+	the right tool for the job.
+
+	The other exception would be where performance is not an issue,
+	and RCU provides a simpler implementation.  An example of this
+	situation is the dynamic NMI code in the Linux 2.6 kernel,
+	at least on architectures where NMIs are rare.
+
+1.	Does the update code have proper mutual exclusion?
+
+	RCU does allow -readers- to run (almost) naked, but -writers- must
+	still use some sort of mutual exclusion, such as:
+
+	a.	locking,
+	b.	atomic operations, or
+	c.	restricting updates to a single task.
+
+	If you choose #b, be prepared to describe how you have handled
+	memory barriers on weakly ordered machines (pretty much all of
+	them -- even x86 allows reads to be reordered), and be prepared
+	to explain why this added complexity is worthwhile.  If you
+	choose #c, be prepared to explain how this single task does not
+	become a major bottleneck on big multiprocessor machines.
+
+2.	Do the RCU read-side critical sections make proper use of
+	rcu_read_lock() and friends?  These primitives are needed
+	to suppress preemption (or bottom halves, in the case of
+	rcu_read_lock_bh()) in the read-side critical sections,
+	and are also an excellent aid to readability.
+
+3.	Does the update code tolerate concurrent accesses?
+
+	The whole point of RCU is to permit readers to run without
+	any locks or atomic operations.  This means that readers will
+	be running while updates are in progress.  There are a number
+	of ways to handle this concurrency, depending on the situation:
+
+	a.	Make updates appear atomic to readers.  For example,
+		pointer updates to properly aligned fields will appear
+		atomic, as will individual atomic primitives.  Operations
+		performed under a lock and sequences of multiple atomic
+		primitives will -not- appear to be atomic.
+
+		This is almost always the best approach.
+
+	b.	Carefully order the updates and the reads so that
+		readers see valid data at all phases of the update.
+		This is often more difficult than it sounds, especially
+		given modern CPUs' tendency to reorder memory references.
+		One must usually liberally sprinkle memory barriers
+		(smp_wmb(), smp_rmb(), smp_mb()) through the code,
+		making it difficult to understand and to test.
+
+		It is usually better to group the changing data into
+		a separate structure, so that the change may be made
+		to appear atomic by updating a pointer to reference
+		a new structure containing updated values.
+
+4.	Weakly ordered CPUs pose special challenges.  Almost all CPUs
+	are weakly ordered -- even i386 CPUs allow reads to be reordered.
+	RCU code must take all of the following measures to prevent
+	memory-corruption problems:
+
+	a.	Readers must maintain proper ordering of their memory
+		accesses.  The rcu_dereference() primitive ensures that
+		the CPU picks up the pointer before it picks up the data
+		that the pointer points to.  This really is necessary
+		on Alpha CPUs.	If you don't believe me, see:
+
+			http://www.openvms.compaq.com/wizard/wiz_2637.html
+
+		The rcu_dereference() primitive is also an excellent
+		documentation aid, letting the person reading the code
+		know exactly which pointers are protected by RCU.
+
+		The rcu_dereference() primitive is used by the various
+		"_rcu()" list-traversal primitives, such as the
+		list_for_each_entry_rcu().
+
+	b.	If the list macros are being used, the list_del_rcu(),
+		list_add_tail_rcu(), and list_del_rcu() primitives must
+		be used in order to prevent weakly ordered machines from
+		misordering structure initialization and pointer planting.
+		Similarly, if the hlist macros are being used, the
+		hlist_del_rcu() and hlist_add_head_rcu() primitives
+		are required.
+
+	c.	Updates must ensure that initialization of a given
+		structure happens before pointers to that structure are
+		publicized.  Use the rcu_assign_pointer() primitive
+		when publicizing a pointer to a structure that can
+		be traversed by an RCU read-side critical section.
+
+		[The rcu_assign_pointer() primitive is in process.]
+
+5.	If call_rcu(), or a related primitive such as call_rcu_bh(),
+	is used, the callback function must be written to be called
+	from softirq context.  In particular, it cannot block.
+
+6.	Since synchronize_kernel() blocks, it cannot be called from
+	any sort of irq context.
+
+7.	If the updater uses call_rcu(), then the corresponding readers
+	must use rcu_read_lock() and rcu_read_unlock().  If the updater
+	uses call_rcu_bh(), then the corresponding readers must use
+	rcu_read_lock_bh() and rcu_read_unlock_bh().  Mixing things up
+	will result in confusion and broken kernels.
+
+	One exception to this rule: rcu_read_lock() and rcu_read_unlock()
+	may be substituted for rcu_read_lock_bh() and rcu_read_unlock_bh()
+	in cases where local bottom halves are already known to be
+	disabled, for example, in irq or softirq context.  Commenting
+	such cases is a must, of course!  And the jury is still out on
+	whether the increased speed is worth it.
+
+8.	Although synchronize_kernel() is a bit slower than is call_rcu(),
+	it usually results in simpler code.  So, unless update performance
+	is important or the updaters cannot block, synchronize_kernel()
+	should be used in preference to call_rcu().
+
+9.	All RCU list-traversal primitives, which include
+	list_for_each_rcu(), list_for_each_entry_rcu(),
+	list_for_each_continue_rcu(), and list_for_each_safe_rcu(),
+	must be within an RCU read-side critical section.  RCU
+	read-side critical sections are delimited by rcu_read_lock()
+	and rcu_read_unlock(), or by similar primitives such as
+	rcu_read_lock_bh() and rcu_read_unlock_bh().
+
+	Use of the _rcu() list-traversal primitives outside of an
+	RCU read-side critical section causes no harm other than
+	a slight performance degradation on Alpha CPUs and some
+	confusion on the part of people trying to read the code.
+
+	Another way of thinking of this is "If you are holding the
+	lock that prevents the data structure from changing, why do
+	you also need RCU-based protection?"  That said, there may
+	well be situations where use of the _rcu() list-traversal
+	primitives while the update-side lock is held results in
+	simpler and more maintainable code.  The jury is still out
+	on this question.
+
+10.	Conversely, if you are in an RCU read-side critical section,
+	you -must- use the "_rcu()" variants of the list macros.
+	Failing to do so will break Alpha and confuse people reading
+	your code.
diff -Nru a/Documentation/RCU/listRCU.txt b/Documentation/RCU/listRCU.txt
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/Documentation/RCU/listRCU.txt	2004-10-18 14:57:22 -07:00
@@ -0,0 +1,307 @@
+Using RCU to Protect Read-Mostly Linked Lists
+
+
+One of the best applications of RCU is to protect read-mostly linked lists
+("struct list_head" in list.h).  One big advantage of this approach
+is that all of the required memory barriers are included for you in
+the list macros.  This document describes several applications of RCU,
+with the best fits first.
+
+
+Example 1: Read-Side Action Taken Outside of Lock, No In-Place Updates
+
+The best applications are cases where, if reader-writer locking were
+used, the read-side lock would be dropped before taking any action
+based on the results of the search.  The most celebrated example is
+the routing table.  Because the routing table is tracking the state of
+equipment outside of the computer, it will at times contain stale data.
+Therefore, once the route has been computed, there is no need to hold
+the routing table static during transmission of the packet.  After all,
+you can hold the routing table static all you want, but that won't keep
+the external Internet from changing, and it is the state of the external
+Internet that really matters.  In addition, routing entries are typically
+added or deleted, rather than being modified in place.
+
+A straightforward example of this use of RCU may be found in the
+system-call auditing support.  For example, a reader-writer locked
+implementation of audit_filter_task() might be as follows:
+
+	static enum audit_state audit_filter_task(struct task_struct *tsk)
+	{
+		struct audit_entry *e;
+		enum audit_state   state;
+
+		read_lock(&auditsc_lock);
+		list_for_each_entry(e, &audit_tsklist, list) {
+			if (audit_filter_rules(tsk, &e->rule, NULL, &state)) {
+				read_unlock(&auditsc_lock);
+				return state;
+			}
+		}
+		read_unlock(&auditsc_lock);
+		return AUDIT_BUILD_CONTEXT;
+	}
+
+Here the list is searched under the lock, but the lock is dropped before
+the corresponding value is returned.  By the time that this value is acted
+on, the list may well have been modified.  This makes sense, since if
+you are turning auditing off, it is OK to audit a few extra system calls.
+
+This means that RCU can be easily applied to the read side, as follows:
+
+	static enum audit_state audit_filter_task(struct task_struct *tsk)
+	{
+		struct audit_entry *e;
+		enum audit_state   state;
+
+		rcu_read_lock();
+		list_for_each_entry_rcu(e, &audit_tsklist, list) {
+			if (audit_filter_rules(tsk, &e->rule, NULL, &state)) {
+				rcu_read_unlock();
+				return state;
+			}
+		}
+		rcu_read_unlock();
+		return AUDIT_BUILD_CONTEXT;
+	}
+
+The read_lock() and read_unlock() calls have become rcu_read_lock()
+and rcu_read_unlock(), respectively, and the list_for_each_entry() has
+become list_for_each_entry_rcu().  The _rcu() list-traversal primitives
+insert the read-side memory barriers that are required on DEC Alpha CPUs.
+
+The changes to the update side are also straightforward.  A reader-writer
+lock might be used as follows for deletion and insertion:
+
+	static inline int audit_del_rule(struct audit_rule *rule,
+					 struct list_head *list)
+	{
+		struct audit_entry  *e;
+
+		write_lock(&auditsc_lock);
+		list_for_each_entry(e, list, list) {
+			if (!audit_compare_rule(rule, &e->rule)) {
+				list_del(&e->list);
+				call_rcu(&e->rcu, audit_free_rule, e);
+				return 0;
+			}
+		}
+		write_unlock(&auditsc_lock);
+		return -EFAULT;		/* No matching rule */
+	}
+
+	static inline int audit_add_rule(struct audit_entry *entry,
+					 struct list_head *list)
+	{
+		write_lock(&auditsc_lock);
+		if (entry->rule.flags & AUDIT_PREPEND) {
+			entry->rule.flags &= ~AUDIT_PREPEND;
+			list_add(&entry->list, list);
+		} else {
+			list_add_tail(&entry->list, list);
+		}
+		write_unlock(&auditsc_lock);
+		return 0;
+	}
+
+Following are the RCU equivalents for these two functions:
+
+	static inline int audit_del_rule(struct audit_rule *rule,
+					 struct list_head *list)
+	{
+		struct audit_entry  *e;
+
+		/* Do not use the _rcu iterator here, since this is the only
+		 * deletion routine. */
+		list_for_each_entry(e, list, list) {
+			if (!audit_compare_rule(rule, &e->rule)) {
+				list_del_rcu(&e->list);
+				call_rcu(&e->rcu, audit_free_rule, e);
+				return 0;
+			}
+		}
+		return -EFAULT;		/* No matching rule */
+	}
+
+	static inline int audit_add_rule(struct audit_entry *entry,
+					 struct list_head *list)
+	{
+		if (entry->rule.flags & AUDIT_PREPEND) {
+			entry->rule.flags &= ~AUDIT_PREPEND;
+			list_add_rcu(&entry->list, list);
+		} else {
+			list_add_tail_rcu(&entry->list, list);
+		}
+		return 0;
+	}
+
+Normally, the write_lock() and write_unlock() would be replaced by
+a spin_lock() and a spin_unlock(), but in this case, all callers hold
+audit_netlink_sem, so no additional locking is required.  The auditsc_lock
+can therefore be eliminated, since use of RCU eliminates the need for
+writers to exclude readers.
+
+The list_del(), list_add(), and list_add_tail() primitives have been
+replaced by list_del_rcu(), list_add_rcu(), and list_add_tail_rcu().
+The _rcu() list-manipulation primitives add memory barriers that are
+needed on weakly ordered CPUs (most of them!).
+
+So, when readers can tolerate stale data and when entries are either added
+or deleted, without in-place modification, it is very easy to use RCU!
+
+
+Example 2: Handling In-Place Updates
+
+The system-call auditing code does not update auditing rules in place.
+However, if it did, reader-writer-locked code to do so might look as
+follows (presumably, the field_count is only permitted to decrease,
+otherwise, the added fields would need to be filled in):
+
+	static inline int audit_upd_rule(struct audit_rule *rule,
+					 struct list_head *list,
+					 __u32 newaction,
+					 __u32 newfield_count)
+	{
+		struct audit_entry  *e;
+		struct audit_newentry *ne;
+
+		write_lock(&auditsc_lock);
+		list_for_each_entry(e, list, list) {
+			if (!audit_compare_rule(rule, &e->rule)) {
+				e->rule.action = newaction;
+				e->rule.file_count = newfield_count;
+				write_unlock(&auditsc_lock);
+				return 0;
+			}
+		}
+		write_unlock(&auditsc_lock);
+		return -EFAULT;		/* No matching rule */
+	}
+
+The RCU version creates a copy, updates the copy, then replaces the old
+entry with the newly updated entry.  This sequence of actions, allowing
+concurrent reads while doing a copy to perform an update, is what gives
+RCU ("read-copy update") its name.  The RCU code is as follows:
+
+	static inline int audit_upd_rule(struct audit_rule *rule,
+					 struct list_head *list,
+					 __u32 newaction,
+					 __u32 newfield_count)
+	{
+		struct audit_entry  *e;
+		struct audit_newentry *ne;
+
+		list_for_each_entry(e, list, list) {
+			if (!audit_compare_rule(rule, &e->rule)) {
+				ne = kmalloc(sizeof(*entry), GFP_ATOMIC);
+				if (ne == NULL)
+					return -ENOMEM;
+				audit_copy_rule(&ne->rule, &e->rule);
+				ne->rule.action = newaction;
+				ne->rule.file_count = newfield_count;
+				list_add_rcu(ne, e);
+				list_del(e);
+				call_rcu(&e->rcu, audit_free_rule, e);
+				return 0;
+			}
+		}
+		return -EFAULT;		/* No matching rule */
+	}
+
+Again, this assumes that the caller holds audit_netlink_sem.  Normally,
+the reader-writer lock would become a spinlock in this sort of code.
+
+
+Example 3: Eliminating Stale Data
+
+The auditing examples above tolerate stale data, as do most algorithms
+that are tracking external state.  Because there is a delay from the
+time the external state changes before Linux becomes aware of the change,
+additional RCU-induced staleness is normally not a problem.
+
+However, there are many examples where stale data cannot be tolerated.
+One example in the Linux kernel is the System V IPC (see the ipc_lock()
+function in ipc/util.c).  This code checks a "deleted" flag under a
+per-entry spinlock, and, if the "deleted" flag is set, pretends that the
+entry does not exist.  For this to be helpful, the search function must
+return holding the per-entry spinlock, as ipc_lock() does in fact do.
+
+Quick Quiz:  Why does the search function need to return holding the
+per-entry lock for this deleted-flag technique to be helpful?
+
+If the system-call audit module were to ever need to reject stale data,
+one way to accomplish this would be to add a "deleted" flag and a "lock"
+spinlock to the audit_entry structure, and modify audit_filter_task()
+as follows:
+
+	static enum audit_state audit_filter_task(struct task_struct *tsk)
+	{
+		struct audit_entry *e;
+		enum audit_state   state;
+
+		rcu_read_lock();
+		list_for_each_entry_rcu(e, &audit_tsklist, list) {
+			if (audit_filter_rules(tsk, &e->rule, NULL, &state)) {
+				spin_lock(&e->lock);
+				if (e->deleted) {
+					spin_unlock(&e->lock);
+					rcu_read_unlock();
+					return AUDIT_BUILD_CONTEXT;
+				}
+				rcu_read_unlock();
+				return state;
+			}
+		}
+		rcu_read_unlock();
+		return AUDIT_BUILD_CONTEXT;
+	}
+
+Note that this example assumes that entries are only added and deleted.
+Additional mechanism is required to deal correctly with the
+update-in-place performed by audit_upd_rule().  For one thing,
+audit_upd_rule() would need additional memory barriers to ensure
+that the list_add_rcu() was really executed before the list_del_rcu().
+
+The audit_del_rule() function would need to set the "deleted"
+flag under the spinlock as follows:
+
+	static inline int audit_del_rule(struct audit_rule *rule,
+					 struct list_head *list)
+	{
+		struct audit_entry  *e;
+
+		/* Do not use the _rcu iterator here, since this is the only
+		 * deletion routine. */
+		list_for_each_entry(e, list, list) {
+			if (!audit_compare_rule(rule, &e->rule)) {
+				spin_lock(&e->lock);
+				list_del_rcu(&e->list);
+				e->deleted = 1;
+				spin_unlock(&e->lock);
+				call_rcu(&e->rcu, audit_free_rule, e);
+				return 0;
+			}
+		}
+		return -EFAULT;		/* No matching rule */
+	}
+
+
+Summary
+
+Read-mostly list-based data structures that can tolerate stale data are
+the most amenable to use of RCU.  The simplest case is where entries are
+either added or deleted from the data structure (or atomically modified
+in place), but non-atomic in-place modifications can be handled by making
+a copy, updating the copy, then replacing the original with the copy.
+If stale data cannot be tolerated, then a "deleted" flag may be used
+in conjunction with a per-entry spinlock in order to allow the search
+function to reject newly deleted data.
+
+
+Answer to Quick Quiz
+
+If the search function drops the per-entry lock before returning, then
+the caller will be processing stale data in any case.  If it is really
+OK to be processing stale data, then you don't need a "deleted" flag.
+If processing stale data really is a problem, then you need to hold the
+per-entry lock across all of the code that uses the value looked up.
diff -Nru a/Documentation/RCU/rcu.txt b/Documentation/RCU/rcu.txt
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/Documentation/RCU/rcu.txt	2004-10-18 14:57:21 -07:00
@@ -0,0 +1,67 @@
+RCU Concepts
+
+
+The basic idea behind RCU (read-copy update) is to split destructive
+operations into two parts, one that prevents anyone from seeing the data
+item being destroyed, and one that actually carries out the destruction.
+A "grace period" must elapse between the two parts, and this grace period
+must be long enough that any readers accessing the item being deleted have
+since dropped their references.  For example, an RCU-protected deletion
+from a linked list would first remove the item from the list, wait for
+a grace period to elapse, then free the element.  See the listRCU.txt
+file for more information on using RCU with linked lists.
+
+
+Frequently Asked Questions
+
+o	Why would anyone want to use RCU?
+
+	The advantage of RCU's two-part approach is that RCU readers need
+	not acquire any locks, perform any atomic instructions, write to
+	shared memory, or (on CPUs other than Alpha) execute any memory
+	barriers.  The fact that these operations are quite expensive
+	on modern CPUs is what gives RCU its performance advantages
+	in read-mostly situations.  The fact that RCU readers need not
+	acquire locks can also greatly simplify deadlock-avoidance code.
+
+o	How can the updater tell when a grace period has completed
+	if the RCU readers give no indication when they are done?
+
+	Just as with spinlocks, RCU readers are not permitted to
+	block, switch to user-mode execution, or enter the idle loop.
+	Therefore, as soon as a CPU is seen passing through any of these
+	three states, we know that that CPU has exited any previous RCU
+	read-side critical sections.  So, if we remove an item from a
+	linked list, and then wait until all CPUs have switched context,
+	executed in user mode, or executed in the idle loop, we can
+	safely free up that item.
+
+o	If I am running on a uniprocessor kernel, which can only do one
+	thing at a time, why should I wait for a grace period?
+
+	See the UP.txt file in this directory.
+
+o	How can I see where RCU is currently used in the Linux kernel?
+
+	Search for "rcu_read_lock", "call_rcu", and "synchronize_kernel".
+
+o	What guidelines should I follow when writing code that uses RCU?
+
+	See the checklist.txt file in this directory.
+
+o	Why the name "RCU"?
+
+	"RCU" stands for "read-copy update".  The file listRCU.txt has
+	more information on where this name came from, search for
+	"read-copy update" to find it.
+
+o	I hear that RCU is patented?  What is with that?
+
+	Yes, it is.  There are several known patents related to RCU,
+	search for the string "Patent" in RTFP.txt to find them.
+	Of these, one was allowed to lapse by the assignee, and the
+	others have been contributed to the Linux kernel under GPL.
+
+o	Where can I find more information on RCU?
+
+	See the RTFP.txt file in this directory.
diff -Nru a/Documentation/arm/IXP2000 b/Documentation/arm/IXP2000
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/Documentation/arm/IXP2000	2004-10-18 14:57:24 -07:00
@@ -0,0 +1,69 @@
+
+-------------------------------------------------------------------------
+Release Notes for Linux on Intel's IXP2000 Network Processor
+
+Maintained by Deepak Saxena <dsaxena@plexity.net>
+-------------------------------------------------------------------------
+
+1. Overview
+
+Intel's IXP2000 family of NPUs (IXP2400, IXP2800, IXP2850) is designed
+for high-performance network applications such high-availability
+telecom systems. In addition to an XScale core, it contains up to 8
+"MicroEngines" that run special code, several high-end networking 
+interfaces (UTOPIA, SPI, etc), a PCI host bridge, one serial port,
+flash interface, and some other odds and ends. For more information, see:
+
+http://developer.intel.com/design/network/products/npfamily/ixp2xxx.htm
+
+2. Linux Support
+
+Linux currently supports the following features on the IXP2000 NPUS:
+
+- On-chip serial
+- PCI
+- Flash (MTD/JFFS2)
+- I2C through GPIO
+- Timers (watchdog, OS)
+
+That is about all we can support under Linux ATM b/c the core networking
+components of the chip are accessed via Intel's closed source SDK. 
+Please contact Intel directly on issues with using those. There is
+also a mailing list run by some folks at Princeton University that might
+be of helpful:  https://lists.cs.princeton.edu/mailman/listinfo/ixp2xxx
+
+WHATEVER YOU DO, DO NOT POST EMAIL TO THE LINUX-ARM OR LINUX-ARM-KERNEL
+MAILINNG LISTS REGARDING THE INTEL SDK.
+
+3. Supported Platforms
+
+- Intel IXDP2400 Reference Platform
+- Intel IXDP2800 Reference Platform
+- Intel IXDP2401 Reference Platform
+- Intel IXDP2801 Reference Platform
+- RadiSys ENP-2611
+
+4. Usage Notes
+
+- The IXP2000 platforms ususally have rather complex PCI bus topologies
+  with large memory space requirements. In addition, b/c of the way the
+  Intel SDK is designed, devices are enumerated in a vert specific
+  way. B/c of this this, we use "pci=firmware" option in the kernel
+  command line so that we do not re-enumerate the bus.
+
+- IXDP2x01 systems have variable clock tick rates that we cannot determine 
+  via HW registers. The "ixdp2x01_clk=XXX" cmd line options allows you
+  to pass the clock rate to the board port.
+
+5. Thanks
+
+The IXP2000 work has been funded by Intel Corp. and MontaVista Software, Inc.
+
+The following people have contributed patches/comments/etc:
+
+Naeem F. Afzal
+Lennert Buytenhek
+Jeffrey Daly
+
+-------------------------------------------------------------------------
+Last Update: 8/09/2004
diff -Nru a/Documentation/arm/Samsung-S3C24XX/EB2410ITX.txt b/Documentation/arm/Samsung-S3C24XX/EB2410ITX.txt
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/Documentation/arm/Samsung-S3C24XX/EB2410ITX.txt	2004-10-18 14:57:24 -07:00
@@ -0,0 +1,44 @@
+		Simtec Electronics EB2410ITX (BAST)
+		===================================
+
+	http://www.simtec.co.uk/products/EB2410ITX/
+
+Introduction
+------------
+
+  The EB2410ITX is a S3C2410 based development board with a variety of
+  peripherals and expansion connectors. This board is also known by
+  the shortened name of Bast.
+
+
+Configuration
+-------------
+
+  To set the default configuration, use `make bast_defconfig` which
+  supports the commonly used features of this board
+
+
+Support
+-------
+
+  Official support information can be found on the Simtec Electronics
+  website, at the product page http://www.simtec.co.uk/products/EB2410ITX/
+  and http://www.simtec.co.uk/products/EB2410ITX/resources.html
+
+
+MTD
+---
+
+  The NAND and NOR onboard are currently supported in the linux-mtd cvs,
+  and are awaiting merge in the mainline. see the linux-mtd project at
+  http://www.linux-mtd.infradead.org/ for more information.
+
+
+IDE
+---
+
+  Both onboard IDE ports are supported, however there is no support for
+  changing speed of devices, PIO Mode 4 capable drives should be used.
+
+
+(c) 2004 Ben Dooks, Simtec Electronics
diff -Nru a/Documentation/arm/Samsung-S3C24XX/GPIO.txt b/Documentation/arm/Samsung-S3C24XX/GPIO.txt
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/Documentation/arm/Samsung-S3C24XX/GPIO.txt	2004-10-18 14:57:23 -07:00
@@ -0,0 +1,122 @@
+			S3C2410 GPIO Control
+			====================
+
+Introduction
+------------
+
+  The s3c2410 kernel provides an interface to configure and
+  manipulate the state of the GPIO pins, and find out other
+  information about them.
+
+  There are a number of conditions attached to the configuration
+  of the s3c2410 GPIO system, please read the Samsung provided
+  data-sheet/users manual to find out the complete list.
+
+
+Headers
+-------
+
+  See include/asm-arm/arch-s3c2410/regs-gpio.h for the list
+  of GPIO pins, and the configuration values for them. This
+  is included by using #include <asm/arch/regs-gpio.h>
+
+  The GPIO management functions are defined in the hardware
+  header include/asm-arm/arch-s3c2410/hardware.h which can be
+  included by #include <asm/arch/hardware.h>
+
+  A useful ammount of documentation can be found in the hardware
+  header on how the GPIO functions (and others) work.
+
+  Whilst a number of these functions do make some checks on what
+  is passed to them, for speed of use, they may not always ensure
+  that the user supplied data to them is correct.
+
+
+PIN Numbers
+-----------
+
+  Each pin has an unique number associated with it in regs-gpio.h,
+  eg S3C2410_GPA0 or S3C2410_GPF1. These defines are used to tell
+  the GPIO functions which pin is to be used.
+
+
+Configuring a pin
+-----------------
+
+  The following function allows the configuration of a given pin to
+  be changed.
+
+    void s3c2410_gpio_cfgpin(unsigned int pin, unsigned int function);
+
+  Eg:
+
+     s3c2410_gpio_cfgpin(S3C2410_GPA0, S3C2410_GPA0_ADDR0);
+     s3c2410_gpio_cfgpin(S3C2410_GPE8, S3C2410_GPE8_SDDAT1);
+
+   which would turn GPA0 into the lowest Address line A0, and set
+   GPE8 to be connected to the SDIO/MMC controller's SDDAT1 line.
+
+
+Reading the current configuration
+---------------------------------
+
+  The current configuration of a pin can be read by using:
+
+  s3c2410_gpio_getcfg(unsigned int pin);
+
+  The return value will be from the same set of values which can be
+  passed to s3c2410_gpio_cfgpin().
+
+
+Configuring a pull-up resistor
+------------------------------
+
+  A large proportion of the GPIO pins on the S3C2410 can have weak
+  pull-up resistors enabled. This can be configured by the following
+  function:
+
+    void s3c2410_gpio_pullup(unsigned int pin, unsigned int to);
+
+  Where the to value is zero to set the pull-up off, and 1 to enable
+  the specified pull-up. Any other values are currently undefined.
+
+
+Getting the state of a PIN
+--------------------------
+
+  The state of a pin can be read by using the function:
+
+    unsigned int s3c2410_gpio_getpin(unsigned int pin);
+
+  This will return either zero or non-zero. Do not count on this
+  function returning 1 if the pin is set.
+
+
+Setting the state of a PIN
+--------------------------
+
+  The value an pin is outputing can be modified by using the following:
+
+    void s3c2410_gpio_setpin(unsigned int pin, unsigned int to);
+
+  Which sets the given pin to the value. Use 0 to write 0, and 1 to
+  set the output to 1.
+
+
+Getting the IRQ number associated with a PIN
+--------------------------------------------
+
+  The following function can map the given pin number to an IRQ
+  number to pass to the IRQ system.
+
+   int s3c2410_gpio_getirq(unsigned int pin);
+
+  Note, not all pins have an IRQ.
+
+
+Authour
+-------
+
+
+Ben Dooks, 03 October 2004
+(c) 2004 Ben Dooks, Simtec Electronics
diff -Nru a/Documentation/arm/Samsung-S3C24XX/Overview.txt b/Documentation/arm/Samsung-S3C24XX/Overview.txt
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/Documentation/arm/Samsung-S3C24XX/Overview.txt	2004-10-18 14:57:24 -07:00
@@ -0,0 +1,97 @@
+			S3C24XX ARM Linux Overview
+			==========================
+
+
+
+Introduction
+------------
+
+  The Samsung S3C24XX range of ARM9 System-on-Chip CPUs are supported
+  by the 's3c2410' architecture of ARM Linux. Currently the S3C2410 is
+  the only supported CPU in this range.
+
+
+Configuration
+-------------
+
+  A generic S3C2410 configuration is provided, and can be used as the
+  default by `make s3c2410_defconfig`. This configuration has support
+  for all the machines, and the commonly used features on them.
+
+  Certain machines may have their own default configurations as well,
+  please check the machine specific documentation.
+
+
+Machines
+--------
+
+  The currently supported machines are as follows:
+
+  Simtec Electronics EB2410ITX (BAST)
+
+    A general purpose development board, see EB2410ITX.txt for further
+    details
+
+  Samsung SMDK2410
+
+    Samsung's own development board, geared for PDA work.
+
+  Thorcom VR1000
+
+    Custom embedded board
+
+  HP IPAQ 1940
+
+    Handheld (IPAQ), available in several varieties
+
+
+NAND
+----
+
+  The current kernels do not have direct support for the NAND
+  controller, the latest linux-mtd CVS has support for this.
+  See http://www.linux-mtd.infradead.org/
+
+
+Serial
+------
+
+  The s3c2410 serial driver provides support for the internal
+  serial ports. These devices appear as /dev/ttySAC0 through 3.
+
+  To create device nodes for these, use the following commands
+
+    mknod ttySAC0 c 204 64
+    mknod ttySAC1 c 204 65
+    mknod ttySAC2 c 204 66
+
+
+GPIO
+----
+
+  The core contains support for manipulating the GPIO, see the
+  documentation in GPIO.txt in the same directory as this file.
+
+
+Clock Management
+----------------
+
+  The core provides the interface defined in the header file
+  include/asm-arm/hardware/clock.h, to allow control over the
+  various clock units
+
+
+Port Contributors
+-----------------
+
+  Ben Dooks
+  Vincent Sanders
+  Herbert Potzl
+  Arnaud Patard
+  Roc Wu
+
+
+Document Author
+---------------
+
+Ben Dooks, (c) 2004 Simtec Electronics
diff -Nru a/Documentation/cachetlb.txt b/Documentation/cachetlb.txt
--- a/Documentation/cachetlb.txt	2004-10-18 14:56:28 -07:00
+++ b/Documentation/cachetlb.txt	2004-10-18 14:56:28 -07:00
@@ -354,10 +354,6 @@
 	of arbitrary user pages (f.e. for ptrace()) it will use
 	these two routines.
 
-	The page has been kmap()'d, and flush_cache_page() has
-	just been called for the user mapping of this page (if
-	necessary).
-
 	Any necessary cache flushing or other coherency operations
 	that need to occur should happen here.  If the processor's
 	instruction cache does not snoop cpu stores, it is very
diff -Nru a/Documentation/cdrom/cdrom-standard.tex b/Documentation/cdrom/cdrom-standard.tex
--- a/Documentation/cdrom/cdrom-standard.tex	2004-10-18 14:56:21 -07:00
+++ b/Documentation/cdrom/cdrom-standard.tex	2004-10-18 14:56:21 -07:00
@@ -360,13 +360,11 @@
 
 \subsection{$Void\ release(struct\ cdrom_device_info * cdi)$}
 
-In case of module support, a single call $MOD_DEC_USE_COUNT$ should be
-coded here.  Possibly other device-specific actions should be taken
-such as spinning down the device. However, strategic actions such as
-ejection of the tray, or unlocking the door, should be left over to
-the general routine $cdrom_release()$. Also, the invalidation of the
-allocated buffers in the VFS is taken care of by the routine in
-\cdromc.  This is the only function returning type $void$. 
+
+Device-specific actions should be taken such as spinning down the device.
+However, strategic actions such as ejection of the tray, or unlocking
+the door, should be left over to the general routine $cdrom_release()$.
+This is the only function returning type $void$.
 
 \subsection{$Int\ drive_status(struct\ cdrom_device_info * cdi, int\ slot_nr)$}
 \label{drive status}
diff -Nru a/Documentation/crypto/api-intro.txt b/Documentation/crypto/api-intro.txt
--- a/Documentation/crypto/api-intro.txt	2004-10-18 14:56:48 -07:00
+++ b/Documentation/crypto/api-intro.txt	2004-10-18 14:56:48 -07:00
@@ -227,6 +227,10 @@
 Khazad algorithm contributors:
   Aaron Grothe
 
+Whirlpool algorithm contributors:
+  Aaron Grothe
+  Jean-Luc Cooke
+
 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-10-18 14:56:28 -07:00
+++ b/Documentation/devices.txt	2004-10-18 14:56:28 -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
@@ -1682,11 +1683,16 @@
 		  1 = /dev/dcxx1	Second capture card
 		    ...
 
- 94 block	Inverse NAND Flash Translation Layer
-		  0 = /dev/inftla	First INFTL layer
-		 16 = /dev/inftlb	Second INFTL layer
+ 94 block IBM S/390 DASD block storage
+    		  0 = /dev/dasda First DASD device, major
+    		  1 = /dev/dasda1 First DASD device, block 1
+	    	  2 = /dev/dasda2 First DASD device, block 2
+    		  3 = /dev/dasda3 First DASD device, block 3
+    		  4 = /dev/dasdb Second DASD device, major
+    		  5 = /dev/dasdb1 Second DASD device, block 1
+    		  6 = /dev/dasdb2 Second DASD device, block 2
+    		  7 = /dev/dasdb3 Second DASD device, block 3
 		    ...
-		240 = /dev/inftlp	16th INTFL layer
 
  95 char	IP filter
 		  0 = /dev/ipl		Filter control device/log file
@@ -1695,15 +1701,9 @@
 		  3 = /dev/ipauth	Authentication control device/log file
 		    ...		
 
- 95 block	IBM S/390 DASD block storage
-		  0 = /dev/dasd0	First DASD device, major
-		  1 = /dev/dasd0a	First DASD device, block 1
-		  2 = /dev/dasd0b	First DASD device, block 2
-		  3 = /dev/dasd0c	First DASD device, block 3
-		  4 = /dev/dasd1	Second DASD device, major
-		  5 = /dev/dasd1a	Second DASD device, block 1
-		  6 = /dev/dasd1b	Second DASD device, block 2
-		  7 = /dev/dasd1c	Second DASD device, block 3
+ 95 block	IBM S/390 VM/ESA minidisk
+		  0 = /dev/msd0		First VM/ESA minidisk
+		  1 = /dev/msd1		Second VM/ESA minidisk
 		    ...
 
  96 char	Parallel port ATAPI tape devices
@@ -1714,10 +1714,11 @@
 		129 = /dev/npt1		Second p.p. ATAPI tape, no rewind
 		    ...
 
- 96 block	IBM S/390 VM/ESA minidisk
-		  0 = /dev/msd0		First VM/ESA minidisk
-		  1 = /dev/msd1		Second VM/ESA minidisk
+ 96 block Inverse NAND Flash Translation Layer
+		  0 = /dev/inftla First INFTL layer
+		 16 = /dev/inftlb Second INFTL layer
 		    ...
+		240 = /dev/inftlp	16th INTFL layer
 
  97 char	Parallel port generic ATAPI interface
 		  0 = /dev/pg0		First parallel port ATAPI device
@@ -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,11 @@
 		    ...
 		 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
+		 44 = /dev/ttyMM0		Marvell MPSC - port 0
+		 45 = /dev/ttyMM1		Marvell MPSC - port 1
 
 205 char	Low-density serial ports (alternate device)
 		  0 = /dev/culu0		Callout device for ttyLU0
@@ -2745,6 +2772,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	2004-10-18 14:56:33 -07:00
+++ b/Documentation/driver-model/bus.txt	2004-10-18 14:56:33 -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/Locking b/Documentation/filesystems/Locking
--- a/Documentation/filesystems/Locking	2004-10-18 14:57:03 -07:00
+++ b/Documentation/filesystems/Locking	2004-10-18 14:57:03 -07:00
@@ -90,7 +90,7 @@
 	void (*destroy_inode)(struct inode *);
 	void (*read_inode) (struct inode *);
 	void (*dirty_inode) (struct inode *);
-	void (*write_inode) (struct inode *, int);
+	int (*write_inode) (struct inode *, int);
 	void (*put_inode) (struct inode *);
 	void (*drop_inode) (struct inode *);
 	void (*delete_inode) (struct inode *);
@@ -276,21 +276,34 @@
 internal fs locking and real critical areas are much smaller than the areas
 filesystems protect now.
 
---------------------------- file_lock ------------------------------------
+----------------------- file_lock_operations ------------------------------
 prototypes:
-	void (*fl_notify)(struct file_lock *);	/* unblock callback */
 	void (*fl_insert)(struct file_lock *);	/* lock insertion callback */
 	void (*fl_remove)(struct file_lock *);	/* lock removal callback */
+	void (*fl_copy_lock)(struct file_lock *, struct file_lock *);
+	void (*fl_release_private)(struct file_lock *);
+
 
 locking rules:
-		BKL	may block
-fl_notify:	yes	no
-fl_insert:	yes	no
-fl_remove:	yes	no
+			BKL	may block
+fl_insert:		yes	no
+fl_remove:		yes	no
+fl_copy_lock:		yes	no
+fl_release_private:	yes	yes
+
+----------------------- lock_manager_operations ---------------------------
+prototypes:
+	int (*fl_compare_owner)(struct file_lock *, struct file_lock *);
+	void (*fl_notify)(struct file_lock *);  /* unblock callback */
+
+locking rules:
+			BKL	may block
+fl_compare_owner:	yes	no
+fl_notify:		yes	no
+
 	Currently only NLM provides instances of this class. None of the
 them block. If you have out-of-tree instances - please, show up. Locking
 in that area will change.
-
 --------------------------- buffer_head -----------------------------------
 prototypes:
 	void (*b_end_io)(struct buffer_head *bh, int uptodate);
diff -Nru a/Documentation/filesystems/ext2.txt b/Documentation/filesystems/ext2.txt
--- a/Documentation/filesystems/ext2.txt	2004-10-18 14:56:19 -07:00
+++ b/Documentation/filesystems/ext2.txt	2004-10-18 14:56:19 -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	2004-10-18 14:56:28 -07:00
+++ b/Documentation/filesystems/ext3.txt	2004-10-18 14:56:28 -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/ntfs.txt b/Documentation/filesystems/ntfs.txt
--- a/Documentation/filesystems/ntfs.txt	2004-10-18 14:56:32 -07:00
+++ b/Documentation/filesystems/ntfs.txt	2004-10-18 14:56:32 -07:00
@@ -30,7 +30,7 @@
 support.
 
 For fault tolerance and raid support (i.e. volume and stripe sets), you can
-use the kernel's Software RAID / MD driver. See section "Using Software RAID
+use the kernel's Software RAID / MD driver.  See section "Using Software RAID
 with NTFS" for details.
 
 
@@ -64,14 +64,18 @@
 	time find . -type f -exec md5sum "{}" \;
   run three times in sequence with each driver (after a reboot) on a 1.4GiB
   NTFS partition, showed the new driver to be 20% faster in total time elapsed
-  (from 9:43 minutes on average down to 7:53). The time spent in user space
+  (from 9:43 minutes on average down to 7:53).  The time spent in user space
   was unchanged but the time spent in the kernel was decreased by a factor of
   2.5 (from 85 CPU seconds down to 33).
-- The driver does not support short file names in general. For backwards
+- The driver does not support short file names in general.  For backwards
   compatibility, we implement access to files using their short file names if
-  they exist. The driver will not create short file names however, and a rename
-  will discard any existing short file name.
+  they exist.  The driver will not create short file names however, and a
+  rename will discard any existing short file name.
 - The new driver supports exporting of mounted NTFS volumes via NFS.
+- The new driver supports async io (aio).
+- The new driver supports fsync(2), fdatasync(2), and msync(2).
+- The new driver supports readv(2) and writev(2).
+- The new driver supports access time updates (including mtime and ctime).
 
 
 Supported mount options
@@ -273,6 +277,25 @@
 
 Note, a technical ChangeLog aimed at kernel hackers is in fs/ntfs/ChangeLog.
 
+2.1.20:
+	- Fix two stupid bugs introduced in 2.1.18 release.
+2.1.19:
+	- Minor bugfix in handling of the default upcase table.
+	- Many internal cleanups and improvements.  Many thanks to Linus
+	  Torvalds and Al Viro for the help and advice with the sparse
+	  annotations and cleanups.
+2.1.18:
+	- Fix scheduling latencies at mount time.  (Ingo Molnar)
+	- Fix endianness bug in a little traversed portion of the attribute
+	  lookup code.
+2.1.17:
+	- Fix bugs in mount time error code paths.
+2.1.16:
+	- Implement access time updates (including mtime and ctime).
+	- Implement fsync(2), fdatasync(2), and msync(2) system calls.
+	- Enable the readv(2) and writev(2) system calls.
+	- Enable access via the asynchronous io (aio) API by adding support for
+	  the aio_read(3) and aio_write(3) functions.
 2.1.15:
 	- Invalidate quotas when (re)mounting read-write.
 	  NOTE:  This now only leave user space journalling on the side.  (See
diff -Nru a/Documentation/filesystems/proc.txt b/Documentation/filesystems/proc.txt
--- a/Documentation/filesystems/proc.txt	2004-10-18 14:56:27 -07:00
+++ b/Documentation/filesystems/proc.txt	2004-10-18 14:56:27 -07:00
@@ -55,7 +55,7 @@
 afraid it's still far from complete, but we  hope it will be useful. As far as
 we know, it is the first 'all-in-one' document about the /proc file system. It
 is focused  on the Intel  x86 hardware,  so if you  are looking for  PPC, ARM,
-SPARC, APX, etc., features, you probably  won't find what you are looking for.
+SPARC, AXP, etc., features, you probably  won't find what you are looking for.
 It also only covers IPv4 networking, not IPv6 nor other protocols - sorry. But
 additions and patches  are welcome and will  be added to this  document if you
 mail them to Bodo.
@@ -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
@@ -1109,6 +1111,23 @@
 The location  where  the  modprobe  binary  is  located.  The kernel uses this
 program to load modules on demand.
 
+unknown_nmi_panic
+-----------------
+
+The value in this file affects behavior of handling NMI. When the value is
+non-zero, unknown NMI is trapped and then panic occurs. At that time, kernel
+debugging information is displayed on console.
+
+NMI switch that most IA32 servers have fires unknown NMI up, for example.
+If a system hangs up, try pressing the NMI switch.
+
+[NOTE]
+   This function and oprofile share a NMI callback. Therefore this function
+   cannot be enabled when oprofile is activated.
+   And NMI watchdog will be disabled when the value in this file is set to
+   non-zero.
+
+
 2.4 /proc/sys/vm - The virtual memory subsystem
 -----------------------------------------------
 
@@ -1156,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/filesystems/tmpfs.txt b/Documentation/filesystems/tmpfs.txt
--- a/Documentation/filesystems/tmpfs.txt	2004-10-18 14:55:53 -07:00
+++ b/Documentation/filesystems/tmpfs.txt	2004-10-18 14:55:53 -07:00
@@ -62,13 +62,21 @@
            since the OOM handler will not be able to free that memory.
 nr_blocks: The same as size, but in blocks of PAGE_CACHE_SIZE.
 nr_inodes: The maximum number of inodes for this instance. The default
-           is half of the number of your physical RAM pages.
+           is half of the number of your physical RAM pages, or (on a
+           a machine with highmem) the number of lowmem RAM pages,
+           whichever is the lower.
 
 These parameters accept a suffix k, m or g for kilo, mega and giga and
 can be changed on remount.  The size parameter also accepts a suffix %
 to limit this tmpfs instance to that percentage of your physical RAM:
 the default, when neither size nor nr_blocks is specified, is size=50%
 
+If both nr_blocks (or size) and nr_inodes are set to 0, neither blocks
+nor inodes will be limited in that instance.  It is generally unwise to
+mount with such options, since it allows any user with write access to
+use up all the memory on the machine; but enhances the scalability of
+that instance in a system with many cpus making intensive use of it.
+
 
 To specify the initial root directory you can use the following mount
 options:
@@ -89,4 +97,4 @@
 Author:
    Christoph Rohland <cr@sap.com>, 1.12.01
 Updated:
-   Hugh Dickins <hugh@veritas.com>, 01 April 2003
+   Hugh Dickins <hugh@veritas.com>, 01 September 2004
diff -Nru a/Documentation/filesystems/vfs.txt b/Documentation/filesystems/vfs.txt
--- a/Documentation/filesystems/vfs.txt	2004-10-18 14:56:48 -07:00
+++ b/Documentation/filesystems/vfs.txt	2004-10-18 14:56:48 -07:00
@@ -176,7 +176,7 @@
 
 struct super_operations {
 	void (*read_inode) (struct inode *);
-	void (*write_inode) (struct inode *, int);
+	int (*write_inode) (struct inode *, int);
 	void (*put_inode) (struct inode *);
 	void (*drop_inode) (struct inode *);
 	void (*delete_inode) (struct inode *);
diff -Nru a/Documentation/filesystems/xfs.txt b/Documentation/filesystems/xfs.txt
--- a/Documentation/filesystems/xfs.txt	2004-10-18 14:56:49 -07:00
+++ b/Documentation/filesystems/xfs.txt	2004-10-18 14:56:49 -07:00
@@ -120,12 +120,18 @@
 
   fs.xfs.stats_clear		(Min: 0  Default: 0  Max: 1)
 	Setting this to "1" clears accumulated XFS statistics 
-	in /proc/fs/xfs/stat.  It then immediately reset to "0".
-  	
-  fs.xfs.sync_interval		(Min: HZ  Default: 30*HZ  Max: 60*HZ)
-	The interval at which the xfssyncd thread for xfs filesystems
-	flushes metadata out to disk. This thread will flush log
-	activity out, and do some processing on unlinked inodes
+	in /proc/fs/xfs/stat.  It then immediately resets to "0".
+  
+  fs.xfs.xfssyncd_centisecs	(Min: 100  Default: 3000  Max: 720000)
+  	The interval at which the xfssyncd thread flushes metadata
+  	out to disk.  This thread will flush log activity out, and
+  	do some processing on unlinked inodes.
+
+  fs.xfs.xfsbufd_centisecs	(Min: 50  Default: 100	Max: 3000)
+	The interval at which xfsbufd scans the dirty metadata buffers list.
+
+  fs.xfs.age_buffer_centisecs	(Min: 100  Default: 1500  Max: 720000)
+	The age at which xfsbufd flushes dirty metadata buffers to disk.
 
   fs.xfs.error_level		(Min: 0  Default: 3  Max: 11)
 	A volume knob for error reporting when internal errors occur.
@@ -180,14 +186,3 @@
 	Setting this to "1" will cause the "noatime" flag set 
 	by the chattr(1) command on a directory to be
 	inherited by files in that directory.
-
-  vm.pagebuf.stats_clear	(Min: 0  Default: 0  Max: 1)
-	Setting this to "1" clears accumulated pagebuf statistics 
-	in /proc/fs/pagebuf/stat.  It then immediately reset to "0".
-  	
-  vm.pagebuf.flush_age		(Min: 1*HZ  Default: 15*HZ  Max: 300*HZ)
-	The age at which dirty metadata buffers are flushed to disk
-
-  vm.pagebuf.flush_int		(Min: HZ/2  Default: HZ  Max: 30*HZ)
-	The interval at which the list of dirty metadata buffers is
-	scanned.
diff -Nru a/Documentation/firmware_class/firmware_sample_firmware_class.c b/Documentation/firmware_class/firmware_sample_firmware_class.c
--- a/Documentation/firmware_class/firmware_sample_firmware_class.c	2004-10-18 14:57:03 -07:00
+++ b/Documentation/firmware_class/firmware_sample_firmware_class.c	2004-10-18 14:57:03 -07:00
@@ -14,9 +14,8 @@
 #include <linux/module.h>
 #include <linux/init.h>
 #include <linux/timer.h>
-#include <asm/hardirq.h>
+#include <linux/firmware.h>
 
-#include "linux/firmware.h"
 
 MODULE_AUTHOR("Manuel Estrada Sainz <ranty@debian.org>");
 MODULE_DESCRIPTION("Hackish sample for using firmware class directly");
diff -Nru a/Documentation/firmware_class/hotplug-script b/Documentation/firmware_class/hotplug-script
--- a/Documentation/firmware_class/hotplug-script	2004-10-18 14:56:33 -07:00
+++ b/Documentation/firmware_class/hotplug-script	2004-10-18 14:56:33 -07:00
@@ -7,10 +7,10 @@
 HOTPLUG_FW_DIR=/usr/lib/hotplug/firmware/
 
 echo 1 > /sys/$DEVPATH/loading
-cat $HOTPLUG_FW_DIR/$FIRMWARE > /sysfs/$DEVPATH/data
+cat $HOTPLUG_FW_DIR/$FIRMWARE > /sys/$DEVPATH/data
 echo 0 > /sys/$DEVPATH/loading
 
 # To cancel the load in case of error:
 #
-#	echo -1 > /sysfs/$DEVPATH/loading
+#	echo -1 > /sys/$DEVPATH/loading
 #
diff -Nru a/Documentation/i2c/sysfs-interface b/Documentation/i2c/sysfs-interface
--- a/Documentation/i2c/sysfs-interface	2004-10-18 14:56:13 -07:00
+++ b/Documentation/i2c/sysfs-interface	2004-10-18 14:56:13 -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-10-18 14:57:24 -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-10-18 14:57:23 -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/input/joystick-parport.txt b/Documentation/input/joystick-parport.txt
--- a/Documentation/input/joystick-parport.txt	2004-10-18 14:57:05 -07:00
+++ b/Documentation/input/joystick-parport.txt	2004-10-18 14:57:05 -07:00
@@ -335,6 +335,7 @@
  * Analog PSX Pad (red mode)
  * Analog PSX Pad (green mode)
  * PSX Rumble Pad
+ * PSX DDR Pad
 
 2.4 Sega
 ~~~~~~~~
@@ -452,13 +453,21 @@
 	  5  | Multisystem 2-button joystick
 	  6  | N64 pad
 	  7  | Sony PSX controller
+	  8  | Sony PSX DDR controller
 
-  The exact type of the PSX controller type is autoprobed, so you must have
-your controller plugged in before initializing.
+  The exact type of the PSX controller type is autoprobed when used so
+hot swapping should work (but is not recomended).
 
   Should you want to use more than one of parallel ports at once, you can use
 gamecon.map2 and gamecon.map3 as additional command line parameters for two
 more parallel ports.
+
+  There are two options specific to PSX driver portion.  gamecon.psx_delay sets
+the command delay when talking to the controllers. The default of 25 should
+work but you can try lowering it for better performace. If your pads don't
+respond try raising it untill they work. Setting the type to 8 allows the
+driver to be used with Dance Dance Revolution or similar games. Arrow keys are
+registered as key presses instead of X and Y axes.
 
 3.2 db9.c
 ~~~~~~~~~
diff -Nru a/Documentation/ioctl-number.txt b/Documentation/ioctl-number.txt
--- a/Documentation/ioctl-number.txt	2004-10-18 14:57:04 -07:00
+++ b/Documentation/ioctl-number.txt	2004-10-18 14:57:04 -07:00
@@ -117,6 +117,7 @@
 					<mailto:natalia@nikhefk.nikhef.nl>
 'c'	00-7F	linux/comstats.h	conflict!
 'c'	00-7F	linux/coda.h		conflict!
+'d'	00-FF	linux/char/drm/drm/h	conflict!
 'd'	00-1F	linux/devfs_fs.h	conflict!
 'd'	00-DF	linux/video_decoder.h	conflict!
 'd'	F0-FF	linux/digi1.h
diff -Nru a/Documentation/kbuild/makefiles.txt b/Documentation/kbuild/makefiles.txt
--- a/Documentation/kbuild/makefiles.txt	2004-10-18 14:56:49 -07:00
+++ b/Documentation/kbuild/makefiles.txt	2004-10-18 14:56:49 -07:00
@@ -25,6 +25,7 @@
 	   --- 4.4 Using C++ for host programs
 	   --- 4.5 Controlling compiler options for host programs
 	   --- 4.6 When host programs are actually built
+	   --- 4.7 Using hostprogs-$(CONFIG_FOO)
 
 	=== 5 Kbuild clean infrastructure
 
@@ -36,6 +37,8 @@
 	   --- 6.5 Building non-kbuild targets
 	   --- 6.6 Commands useful for building a boot image
 	   --- 6.7 Custom kbuild commands
+	   --- 6.8 Preprocessing linker scripts
+	   --- 6.9 $(CC) support functions
 
 	=== 7 Kbuild Variables
 	=== 8 Makefile language
@@ -387,7 +390,7 @@
 Two steps are required in order to use a host executable.
 
 The first step is to tell kbuild that a host program exists. This is
-done utilising the variable host-prog.
+done utilising the variable hostprogs-y.
 
 The second step is to add an explicit dependency to the executable.
 This can be done in two ways. Either add the dependency in a rule, 
@@ -402,7 +405,7 @@
 	built on the build host.
 
 	Example:
-		host-progs := bin2hex
+		hostprogs-y := bin2hex
 
 	Kbuild assumes in the above example that bin2hex is made from a single
 	c-source file named bin2hex.c located in the same directory as
@@ -418,7 +421,7 @@
 
 	Example:
 		#scripts/lxdialog/Makefile
-		host-progs    := lxdialog  
+		hostprogs-y   := lxdialog  
 		lxdialog-objs := checklist.o lxdialog.o
 
 	Objects with extension .o are compiled from the corresponding .c
@@ -438,7 +441,7 @@
 
 	Example:
 		#scripts/kconfig/Makefile
-		host-progs      := conf
+		hostprogs-y     := conf
 		conf-objs       := conf.o libkconfig.so
 		libkconfig-objs := expr.o type.o
   
@@ -457,7 +460,7 @@
 
 	Example:
 		#scripts/kconfig/Makefile
-		host-progs    := qconf
+		hostprogs-y   := qconf
 		qconf-cxxobjs := qconf.o
 
 	In the example above the executable is composed of the C++ file
@@ -468,7 +471,7 @@
 
 	Example:
 		#scripts/kconfig/Makefile
-		host-progs    := qconf
+		hostprogs-y   := qconf
 		qconf-cxxobjs := qconf.o
 		qconf-objs    := check.o
 	
@@ -509,7 +512,7 @@
 
 	Example:
 		#drivers/pci/Makefile
-		host-progs := gen-devlist
+		hostprogs-y := gen-devlist
 		$(obj)/devlist.h: $(src)/pci.ids $(obj)/gen-devlist
 			( cd $(obj); ./gen-devlist ) < $<
 
@@ -524,18 +527,32 @@
 
 	Example:
 		#scripts/lxdialog/Makefile
-		host-progs    := lxdialog
-		always        := $(host-progs)
+		hostprogs-y   := lxdialog
+		always        := $(hostprogs-y)
 
 	This will tell kbuild to build lxdialog even if not referenced in
 	any rule.
 
+--- 4.7 Using hostprogs-$(CONFIG_FOO)
+
+	A typcal pattern in a Kbuild file lok like this:
+
+	Example:
+		#scripts/Makefile
+		hostprogs-$(CONFIG_KALLSYMS) += kallsyms
+
+	Kbuild knows about both 'y' for built-in and 'm' for module.
+	So if a config symbol evaluate to 'm', kbuild will still build
+	the binary. In other words Kbuild handle hostprogs-m exactly
+	like hostprogs-y. But only hostprogs-y is recommend used
+	when no CONFIG symbol are involved.
+
 === 5 Kbuild clean infrastructure
 
 "make clean" deletes most generated files in the src tree where the kernel
 is compiled. This includes generated files such as host programs.
-Kbuild knows targets listed in $(host-progs), $(always), $(extra-y) and
-$(targets). They are all deleted during "make clean".
+Kbuild knows targets listed in $(hostprogs-y), $(hostprogs-m), $(always),
+$(extra-y) and $(targets). They are all deleted during "make clean".
 Files matching the patterns "*.[oas]", "*.ko", plus some additional files
 generated by kbuild are deleted all over the kernel src tree when
 "make clean" is executed.
@@ -547,8 +564,17 @@
 		clean-files := devlist.h classlist.h
 
 When executing "make clean", the two files "devlist.h classlist.h" will
-be deleted. Kbuild knows that files specified by $(clean-files) are
-located in the same directory as the makefile.
+be deleted. Kbuild will assume files to be in same relative directory as the
+Makefile except if an absolute path is specified (path starting with '/').
+
+To delete a directory hirachy use:
+	Example:
+		#scripts/package/Makefile
+		clean-dirs := $(objtree)/debian/
+
+This will delete the directory debian, including all subdirectories.
+Kbuild will assume the directories to be in the same relative path as the
+Makefile if no absolute path is specified (path does not start with '/').
 
 Usually kbuild descends down in subdirectories due to "obj-* := dir/",
 but in the architecture makefiles where the kbuild infrastructure
@@ -638,15 +664,6 @@
 		#arch/i386/Makefile
 		LDFLAGS_vmlinux := -e stext
 
-    LDFLAGS_BLOB	Options for $(LD) when linking the initramfs blob
-
-	The image used for initramfs is made during the build process.
-	LDFLAGS_BLOB is used to specify additional flags to be used when
-	creating the initramfs_data.o file.
-	Example:
-		#arch/i386/Makefile
-		LDFLAGS_BLOB := --format binary --oformat elf32-i386
-
     OBJCOPYFLAGS	objcopy flags
 
 	When $(call if_changed,objcopy) is used to translate a .o file,
@@ -912,6 +929,90 @@
 	BUILD    arch/i386/boot/bzImage
 
 	will be displayed with "make KBUILD_VERBOSE=0".
+	
+
+--- 6.8 Preprocessing linker scripts
+
+	When the vmlinux image is build the linker script:
+	arch/$(ARCH)/kernel/vmlinux.lds is used.
+	The script is a preprocessed variant of the file vmlinux.lds.S
+	located in the same directory.
+	kbuild knows .lds file and includes a rule *lds.S -> *lds.
+	
+	Example:
+		#arch/i386/kernel/Makefile
+		always := vmlinux.lds
+	
+		#Makefile
+		export CPPFLAGS_vmlinux.lds += -P -C -U$(ARCH)
+		
+	The assigment to $(always) is used to tell kbuild to build the
+	target: vmlinux.lds.
+	The assignment to $(CPPFLAGS_vmlinux.lds) tell kbuild to use the
+	specified options when building the target vmlinux.lds.
+	
+	When building the *.lds target kbuild used the variakles:
+	CPPFLAGS	: Set in top-level Makefile
+	EXTRA_CPPFLAGS	: May be set in the kbuild makefile
+	CPPFLAGS_$(@F)  : Target specific flags.
+	                  Note that the full filename is used in this
+	                  assignment.
+
+	The kbuild infrastructure for *lds file are used in several
+	architecture specific files.
+
+
+--- 6.9 $(CC) support functions
+
+	The kernel may be build with several different versions of
+	$(CC), each supporting a unique set of features and options.
+	kbuild provide basic support to check for valid options for $(CC).
+	$(CC) is useally the gcc compiler, but other alternatives are
+	available.
+
+    cc-option
+	cc-option is used to check if $(CC) support a given option, and not
+	supported to use an optional second option.
+
+	Example:
+		#arch/i386/Makefile
+		cflags-y += $(call cc-option,-march=pentium-mmx,-march=i586)
+
+	In the above example cflags-y will be assigned the option
+	-march=pentium-mmx if supported by $(CC), otherwise -march-i586.
+	The second argument to cc-option is optional, and if omitted
+	cflags-y will be assigned no value if first option is not supported.
+
+   cc-option-yn
+   	cc-option-yn is used to check if gcc supports a given option
+	and return 'y' if supported, otherwise 'n'.
+
+	Example:
+		#arch/ppc/Makefile
+		biarch := $(call cc-option-yn, -m32)
+		aflags-$(biarch) += -a32
+		cflags-$(biarch) += -m32
+	
+	In the above example $(biarch) is set to y if $(CC) supports the -m32
+	option. When $(biarch) equals to y the expanded variables $(aflags-y)
+	and $(cflags-y) will be assigned the values -a32 and -m32.
+
+    cc-version
+	cc-version return a numerical version of the $(CC) compiler version.
+	The format is <major><minor> where both are two digits. So for example
+	gcc 3.41 would return 0341.
+	cc-version is useful when a specific $(CC) version is faulty in one
+	area, for example the -mregparm=3 were broken in some gcc version
+	even though the option was accepted by gcc.
+
+	Example:
+		#arch/i386/Makefile
+		GCC_VERSION := $(call cc-version)
+		cflags-y += $(shell \
+		if [ $(GCC_VERSION) -ge 0300 ] ; then echo "-mregparm=3"; fi ;)
+
+	In the above example -mregparm=3 is only used for gcc version greater
+	than or equal to gcc 3.0.
 	
 
 === 7 Kbuild Variables
diff -Nru a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt
--- a/Documentation/kernel-parameters.txt	2004-10-18 14:57:18 -07:00
+++ b/Documentation/kernel-parameters.txt	2004-10-18 14:57:18 -07:00
@@ -97,9 +97,6 @@
 			See header of drivers/scsi/53c7xx.c.
 			See also Documentation/scsi/ncr53c7xx.txt.
 
-	98busmouse.irq=	[HW,MOUSE] PC-9801 Bus Mouse Driver
-			Format: <irq>, default is 13
-
 	acpi=		[HW,ACPI] Advanced Configuration and Power Interface 
 			Format: { force | off | ht | strict }
 			force -- enable ACPI if default was off
@@ -138,6 +135,20 @@
 			Recognize and ignore IRQ0/pin2 Interrupt Override.
 			For broken nForce2 BIOS resulting in XT-PIC timer.
 
+	acpi_dbg_layer=	[HW,ACPI]
+			Format: <int>
+			Each bit of the <int> indicates an acpi debug layer,
+			1: enable, 0: disable. It is useful for boot time
+			debugging. After system has booted up, it can be set
+			via /proc/acpi/debug_layer.
+
+	acpi_dbg_level=	[HW,ACPI]
+			Format: <int>
+			Each bit of the <int> indicates an acpi debug level,
+			1: enable, 0: disable. It is useful for boot time
+			debugging. After system has booted up, it can be set
+			via /proc/acpi/debug_level.
+
 	ad1816=		[HW,OSS]
 			Format: <io>,<irq>,<dma>,<dma2>
 			See also Documentation/sound/oss/AD1816.
@@ -189,6 +200,11 @@
 			Disable APC CPU standby support. SPARCstation-Fox does
 			not play well with APC CPU idle - disable it if you have
 			APC and your system crashes randomly.
+
+	apic=		[APIC,i386] Change the output verbosity  whilst booting
+			Format: { quiet (default) | verbose | debug }
+			Change the amount of debugging information output
+			when initialising the APIC and IO-APIC components.
  
 	apm=		[APM] Advanced Power Management
 			See header of arch/i386/kernel/apm.c.
@@ -448,6 +464,11 @@
 	hd?=		[HW] (E)IDE subsystem
 	hd?lun=		See Documentation/ide.txt.
 
+	highmem=nn[KMG]	[KNL,BOOT] forces the highmem zone to have an exact
+			size of <nn>. This works even on boxes that have no
+			highmem otherwise. This also works to reduce highmem
+			size on bigger boxes.
+
 	hisax=		[HW,ISDN]
 			See Documentation/isdn/README.HiSax.
 
@@ -523,6 +544,18 @@
 	isapnp=		[ISAPNP]
 			Format: <RDP>, <reset>, <pci_scan>, <verbosity>
 
+	isolcpus=	[KNL,SMP] Isolate CPUs from the general scheduler.
+			Format: <cpu number>, ..., <cpu number>
+			This option can be used to specify one or more CPUs
+			to isolate from the general SMP balancing and scheduling
+			algorithms. The only way to move a process onto or off
+			an "isolated" CPU is via the CPU affinity syscalls.
+
+			This option is the preferred way to isolate CPUs. The
+			alternative - manually setting the CPU mask of all tasks
+			in the system can cause problems and suboptimal load
+			balancer performance.
+
 	isp16=		[HW,CD]
 			Format: <io>,<irq>,<dma>,<setup>
 
@@ -574,6 +607,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>
 
@@ -650,6 +697,12 @@
 
 	mga=		[HW,DRM]
 
+	mousedev.tap_time=
+			[MOUSE] Maximum time between finger touching and
+			leaving touchpad surface for touch to be considered
+			a tap and be reported as a left button click (for
+			touchpads working in absolute mode only).
+			Format: <msecs>
 	mousedev.xres=	[MOUSE] Horizontal screen resolution, used for devices
 			reporting absolute coordinates, such as tablets
 	mousedev.yres=	[MOUSE] Vertical screen resolution, used for devices
@@ -707,6 +760,9 @@
 	noasync		[HW,M68K] Disables async and sync negotiation for
 			all devices.
 
+	nobats		[PPC] Do not use BATs for mapping kernel lowmem
+			on "Classic" PPC cores.
+
 	nocache		[ARM]
  
 	nodisconnect	[HW,SCSI,M68K] Disables SCSI disconnects.
@@ -739,8 +795,13 @@
 
 	nolapic		[IA-32,APIC] Do not enable or use the local APIC.
 
+	noltlbs		[PPC] Do not use large page/tlb entries for kernel
+			lowmem mapping on PPC40x.
+
 	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.
@@ -852,6 +913,13 @@
 		noacpi			[IA-32] Do not use ACPI for IRQ routing
 					or for PCI scanning.
 
+		firmware		[ARM] Do not re-enumerate the bus but
+					instead just use the configuration
+					from the bootloader. This is currently
+					used on IXP2000 systems where the
+					bus has to be configured a certain way
+					for adjunct CPUs.
+
 	pcmv=		[HW,PCMCIA] BadgePAD 4
 
 	pd.		[PARIDE]
@@ -887,7 +955,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.
@@ -1249,6 +1320,12 @@
 			Use vga=ask for menu.
 			This is actually a boot loader parameter; the value is
 			passed to the kernel using a special protocol.
+
+	vmalloc=nn[KMG]	[KNL,BOOT] forces the vmalloc area to have an exact
+			size of <nn>. This can be used to increase the
+			minimum size (128MB on x86). It can also be used to
+			decrease the size and leave more room for directly
+			mapped kernel RAM.
 
 	vmhalt=		[KNL,S390]
 
diff -Nru a/Documentation/laptop-mode.txt b/Documentation/laptop-mode.txt
--- a/Documentation/laptop-mode.txt	2004-10-18 14:56:49 -07:00
+++ b/Documentation/laptop-mode.txt	2004-10-18 14:56:49 -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/networking/gen_stats.txt b/Documentation/networking/gen_stats.txt
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/Documentation/networking/gen_stats.txt	2004-10-18 14:57:21 -07:00
@@ -0,0 +1,117 @@
+Generic networking statistics for netlink users
+======================================================================
+
+Statistic counters are grouped into structs:
+
+Struct               TLV type              Description
+----------------------------------------------------------------------
+gnet_stats_basic     TCA_STATS_BASIC       Basic statistics
+gnet_stats_rate_est  TCA_STATS_RATE_EST    Rate estimator
+gnet_stats_queue     TCA_STATS_QUEUE       Queue statistics
+none                 TCA_STATS_APP         Application specific
+
+
+Collecting:
+-----------
+
+Declare the statistic structs you need:
+struct mystruct {
+	struct gnet_stats_basic	bstats;
+	struct gnet_stats_queue	qstats;
+	...
+};
+
+Update statistics:
+mystruct->tstats.packet++;
+mystruct->qstats.backlog += skb->pkt_len;
+
+
+Export to userspace (Dump):
+---------------------------
+
+my_dumping_routine(struct sk_buff *skb, ...)
+{
+	struct gnet_dump dump;
+
+	if (gnet_stats_start_copy(skb, TCA_STATS2, &mystruct->lock, &dump) < 0)
+		goto rtattr_failure;
+
+	if (gnet_stats_copy_basic(&dump, &mystruct->bstats) < 0 ||
+	    gnet_stats_copy_queue(&dump, &mystruct->qstats) < 0 ||
+		gnet_stats_copy_app(&dump, &xstats, sizeof(xstats)) < 0)
+		goto rtattr_failure;
+
+	if (gnet_stats_finish_copy(&dump) < 0)
+		goto rtattr_failure;
+	...
+}
+
+TCA_STATS/TCA_XSTATS backward compatibility:
+--------------------------------------------
+
+Prior users of struct tc_stats and xstats can maintain backward
+compatibility by calling the compat wrappers to keep providing the
+existing TLV types.
+
+my_dumping_routine(struct sk_buff *skb, ...)
+{
+    if (gnet_stats_start_copy_compat(skb, TCA_STATS2, TCA_STATS,
+		TCA_XSTATS, &mystruct->lock, &dump) < 0)
+		goto rtattr_failure;
+	...
+}
+
+A struct tc_stats will be filled out during gnet_stats_copy_* calls
+and appended to the skb. TCA_XSTATS is provided if gnet_stats_copy_app
+was called.
+
+
+Locking:
+--------
+
+Locks are taken before writing and released once all statistics have
+been written. Locks are always released in case of an error. You
+are responsible for making sure that the lock is initialized.
+
+
+Rate Estimator:
+--------------
+
+0) Prepare an estimator attribute. Most likely this would be in user
+   space. The value of this TLV should contain a tc_estimator structure.
+   As usual, such a TLV nees to be 32 bit aligned and therefore the
+   length needs to be appropriately set etc. The estimator interval
+   and ewma log need to be converted to the appropriate values.
+   tc_estimator.c::tc_setup_estimator() is advisable to be used as the
+   conversion routine. It does a few clever things. It takes a time
+   interval in microsecs, a time constant also in microsecs and a struct
+   tc_estimator to  be populated. The returned tc_estimator can be
+   transported to the kernel.  Transfer such a structure in a TLV of type
+   TCA_RATE to your code in the kernel.
+
+In the kernel when setting up:
+1) make sure you have basic stats and rate stats setup first.
+2) make sure you have initialized stats lock that is used to setup such
+   stats.
+3) Now initialize a new estimator:
+
+   int ret = gen_new_estimator(my_basicstats,my_rate_est_stats,
+       mystats_lock, attr_with_tcestimator_struct);
+
+   if ret == 0
+       success
+   else
+       failed
+
+From now on, everytime you dump my_rate_est_stats it will contain
+uptodate info.
+
+Once you are done, call gen_kill_estimator(my_basicstats,
+my_rate_est_stats) Make sure that my_basicstats and my_rate_est_stats
+are still valid (i.e still exist) at the time of making this call.
+
+
+Authors:
+--------
+Thomas Graf <tgraf@suug.ch>
+Jamal Hadi Salim <hadi@cyberus.ca>
diff -Nru a/Documentation/networking/ip-sysctl.txt b/Documentation/networking/ip-sysctl.txt
--- a/Documentation/networking/ip-sysctl.txt	2004-10-18 14:56:29 -07:00
+++ b/Documentation/networking/ip-sysctl.txt	2004-10-18 14:56:29 -07:00
@@ -837,6 +837,11 @@
 	0 : disable this.
 	Default: 1
 
+bridge-nf-call-ip6tables - BOOLEAN
+	1 : pass bridged IPv6 traffic to ip6tables' chains.
+	0 : disable this.
+	Default: 1
+
 bridge-nf-filter-vlan-tagged - BOOLEAN
 	1 : pass bridged vlan-tagged ARP/IP traffic to arptables/iptables.
 	0 : disable this.
diff -Nru a/Documentation/networking/netdevices.txt b/Documentation/networking/netdevices.txt
--- a/Documentation/networking/netdevices.txt	2004-10-18 14:56:20 -07:00
+++ b/Documentation/networking/netdevices.txt	2004-10-18 14:56:20 -07:00
@@ -43,8 +43,21 @@
 
 dev->hard_start_xmit:
 	Synchronization: dev->xmit_lock spinlock.
+	When the driver sets NETIF_F_LLTX in dev->features this will be
+	called without holding xmit_lock. In this case the driver 
+	has to lock by itself when needed. It is recommended to use a try lock
+	for this and return -1 when the spin lock fails. 
+	The locking there should also properly protect against 
+	set_multicast_list
 	Context: BHs disabled
 	Notes: netif_queue_stopped() is guaranteed false
+	Return codes: 
+	o NETDEV_TX_OK everything ok. 
+	o NETDEV_TX_BUSY Cannot transmit packet, try later 
+	  Usually a bug, means queue start/stop flow control is broken in
+	  the driver. Note: the driver must NOT put the skb in its DMA ring.
+	o NETDEV_TX_LOCKED Locking failed, please retry quickly.
+	  Only valid when NETIF_F_LLTX is set.
 
 dev->tx_timeout:
 	Synchronization: dev->xmit_lock spinlock.
diff -Nru a/Documentation/pci.txt b/Documentation/pci.txt
--- a/Documentation/pci.txt	2004-10-18 14:56:29 -07:00
+++ b/Documentation/pci.txt	2004-10-18 14:56:29 -07:00
@@ -25,6 +25,7 @@
 	Discover resources (addresses and IRQ numbers) provided by the device
 	Allocate these resources
 	Communicate with the device
+	Disable the device
 
 Most of these topics are covered by the following sections, for the rest
 look at <linux/pci.h>, it's hopefully well commented.
@@ -162,8 +163,8 @@
 count on these devices by calling pci_dev_put().
 
 
-3. Enabling devices
-~~~~~~~~~~~~~~~~~~~
+3. Enabling and disabling devices
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    Before you do anything with the device you've found, you need to enable
 it by calling pci_enable_device() which enables I/O and memory regions of
 the device, allocates an IRQ if necessary, assigns missing resources if
@@ -179,6 +180,12 @@
 and also ensures that the cache line size register is set correctly.
 Make sure to check the return value of pci_set_mwi(), not all architectures
 may support Memory-Write-Invalidate.
+
+   If your driver decides to stop using the device (e.g., there was an
+error while setting it up or the driver module is being unloaded), it
+should call pci_disable_device() to deallocate any IRQ resources, disable
+PCI bus-mastering, etc.  You should not do anything with the device after
+calling pci_disable_device().
 
 4. How to access PCI config space
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
diff -Nru a/Documentation/power/swsusp.txt b/Documentation/power/swsusp.txt
--- a/Documentation/power/swsusp.txt	2004-10-18 14:55:53 -07:00
+++ b/Documentation/power/swsusp.txt	2004-10-18 14:55:53 -07:00
@@ -20,26 +20,6 @@
 You need to append resume=/dev/your_swap_partition to kernel command
 line. Then you suspend by echo 4 > /proc/acpi/sleep.
 
-Pavel's unreliable guide to swsusp mess
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-There are currently two versions of swap suspend in the kernel, the old
-"Pavel's" version in kernel/power/swsusp.c and the new "Patrick's"
-version in kernel/power/pmdisk.c. They provide the same functionality;
-the old version looks ugly but was tested, while the new version looks
-nicer but did not receive so much testing. echo 4 > /proc/acpi/sleep
-calls the old version, echo disk > /sys/power/state calls the new one.
-
-[In the future, when the new version is stable enough, two things can
-happen:
-
-* the new version is moved into swsusp.c, and swsusp is renamed to swap
-  suspend (Pavel prefers this)
-
-* pmdisk is kept as is and swsusp.c is removed from the kernel]
-
-
-
 Article about goals and implementation of Software Suspend for Linux
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 Author: G‚ábor Kuti
@@ -75,10 +55,6 @@
 About the code
 
 Things to implement
-- SMP support. I've done an SMP support but since I don't have access to a kind
-  of this one I cannot test it. Please SMP people test it.  .. Tested it,
-  doesn't work. Had no time to figure out why. There is some mess with
-  interrupts AFAIK..
 - We should only make a copy of data related to kernel segment, since any
   process data won't be changed.
 - Should make more sanity checks. Or are these enough?
@@ -90,11 +66,6 @@
 - We should not free pages at the beginning so aggressively, most of them
   go there anyway..
 
-Drivers that need support
-- pc_keyb -- perhaps we can wait for vojtech's input patches
-- do IDE cdroms need some kind of support?
-- IDE CD-RW -- how to deal with that?
-
 Sleep states summary (thanx, Ducrot)
 ====================================
 
@@ -109,7 +80,8 @@
 echo 4b > /proc/acpi/sleep      # for suspend to disk via s4bios
 
 
-FAQ:
+Frequently Asked Questions
+==========================
 
 Q: well, suspending a server is IMHO a really stupid thing,
 but... (Diego Zuccato):
diff -Nru a/Documentation/powerpc/hvcs.txt b/Documentation/powerpc/hvcs.txt
--- a/Documentation/powerpc/hvcs.txt	2004-10-18 14:56:27 -07:00
+++ b/Documentation/powerpc/hvcs.txt	2004-10-18 14:56:27 -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/powerpc/mpc52xx.txt b/Documentation/powerpc/mpc52xx.txt
--- a/Documentation/powerpc/mpc52xx.txt	2004-10-18 14:56:28 -07:00
+++ b/Documentation/powerpc/mpc52xx.txt	2004-10-18 14:56:28 -07:00
@@ -1,7 +1,7 @@
 Linux 2.6.x on MPC52xx family
 -----------------------------
 
-For the latest info, go to http://www.246tNt.com/mpc52xx/state.txt
+For the latest info, go to http://www.246tNt.com/mpc52xx/
  
 To compile/use :
 
@@ -37,12 +37,3 @@
  - Of course, I inspired myself from the 2.4 port. If you think I forgot to
    mention you/your company in the copyright of some code, I'll correct it
    ASAP.
- - The codes wants the MBAR to be set at 0xf0000000 by the bootloader. It's
-   mapped 1:1 with the MMU. If for whatever reason, you want to change this,
-   beware that some code depends on the 0xf0000000 address and other depends
-   on the 1:1 mapping.
- - Most of the code assumes that port multiplexing, frequency selection, ...
-   has already been done. IMHO this should be done as early as possible, in
-   the bootloader. If for whatever reason you can't do it there, do it in the
-   platform setup code (if U-Boot) or in the arch/ppc/boot/simple/... (if
-   DBug)
diff -Nru a/Documentation/sched-domains.txt b/Documentation/sched-domains.txt
--- a/Documentation/sched-domains.txt	2004-10-18 14:55:55 -07:00
+++ b/Documentation/sched-domains.txt	2004-10-18 14:55:55 -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-10-18 14:57:24 -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-10-18 14:57:04 -07:00
+++ b/Documentation/scsi/ChangeLog.megaraid	2004-10-18 14:57:04 -07:00
@@ -1,42 +1,223 @@
-### 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	: Mon Sep 27 22:15:07 EDT 2004 - Atul Mukker <atulm@lsil.com>
+Current Version	: 2.20.4.0 (scsi module), 2.20.2.0 (cmm module)
+Older Version	: 2.20.3.1 (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.	Fix data corruption. Because of a typo in the driver, the IO packets
+	were wrongly shared by the ioctl path. This causes a whole IO command
+	to be replaced by an incoming ioctl command.
 
-	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
+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)
 
-ii.	Specify the logical drive number while issuing the RESERVATION_STATUS
+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)
 
-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.
+	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
 
-iv.	The max outstanding commands are reduced to 126 because that't the
-	safest value on all FW.
+		- Andrew Morton <akpm@osdl.org>, 08.19.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.
+	"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"
 
-vi.	max_commands is no longer a module parameter because of iv.
+		- Matt Domsch <Matt_Domsch@dell.com>, 07.27.2004
+		linux-scsi mailing list
 
-### Version: 2.00.2
-i.	Intermediate release with kernel specific code
 
+ii.	Display elapsed time (countdown) while waiting for FW to boot.
 
-### 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
+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.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.
+
+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)
+
+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-10-18 14:57:23 -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-10-18 14:56:49 -07:00
+++ b/Documentation/scsi/scsi_mid_low_api.txt	2004-10-18 14:56:49 -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
  **/
@@ -1072,10 +1091,6 @@
  *      mid level does not recognize it, then the LLD that controls
  *      the device receives the ioctl. According to recent Unix standards
  *      unsupported ioctl() 'cmd' numbers should return -ENOTTY.
- *      However the mid level returns -EINVAL for unrecognized 'cmd'
- *      numbers when this function is not supplied by the driver.
- *      Unfortunately some applications expect -EINVAL and react badly
- *      when -ENOTTY is returned; stick with -EINVAL.
  *
  *      Optionally defined in: LLD
  **/
@@ -1110,7 +1125,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 +1135,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 +1332,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 +1348,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 +1358,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 +1371,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 +1499,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-10-18 14:55:54 -07:00
+++ b/Documentation/sound/alsa/ALSA-Configuration.txt	2004-10-18 14:55:54 -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-10-18 14:56:13 -07:00
+++ b/Documentation/sound/alsa/DocBook/alsa-driver-api.tmpl	2004-10-18 14:56:13 -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-10-18 14:56:27 -07:00
+++ b/Documentation/sound/alsa/DocBook/writing-an-alsa-driver.tmpl	2004-10-18 14:56:27 -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-10-18 14:56:32 -07:00
+++ b/Documentation/sysctl/kernel.txt	2004-10-18 14:56:32 -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 ]
 
 ==============================================================
 
@@ -133,8 +131,8 @@
 # echo "darkstar" > /proc/sys/kernel/hostname
 # echo "mydomain" > /proc/sys/kernel/domainname
 has the same effect as
-# hostname "darkstar" > /proc/sys/kernel/hostname
-# domainname "mydomain" > /proc/sys/kernel/domainname
+# hostname "darkstar"
+# domainname "mydomain"
 
 Note, however, that the classic darkstar.frop.org has the
 hostname "darkstar" and DNS (Internet Domain Name Server)
@@ -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/sysctl/vm.txt b/Documentation/sysctl/vm.txt
--- a/Documentation/sysctl/vm.txt	2004-10-18 14:56:49 -07:00
+++ b/Documentation/sysctl/vm.txt	2004-10-18 14:56:49 -07:00
@@ -47,7 +47,7 @@
 When this flag is 1, the kernel pretends there is always enough
 memory until it actually runs out.
 
-When this flag is 2, the kernel uses a "strict overcommit" 
+When this flag is 2, the kernel uses a "never overcommit"
 policy that attempts to prevent any overcommit of memory.  
 
 This feature can be very useful because there are a lot of
diff -Nru a/Documentation/time_interpolators.txt b/Documentation/time_interpolators.txt
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/Documentation/time_interpolators.txt	2004-10-18 14:57:24 -07:00
@@ -0,0 +1,40 @@
+Time Interpolators
+------------------
+
+Time interpolators are a base of time calculation between timer ticks and
+allow an accurate determination of time down to the accuracy of the time
+source in nanoseconds.
+
+The architecture specific code typically provides gettimeofday and
+settimeofday under Linux. The time interpolator provides both if an arch
+defines CONFIG_TIME_INTERPOLATION. The arch still must set up timer tick
+operations and call the necessary functions to advance the clock.
+With the time interpolator a standardized interface exists for time
+interpolation between ticks which also allows the determination
+of time in a hardware independent way. The provided logic is highly scalable
+and has been tested in SMP situations of up to 512 CPUs.
+
+If CONFIG_TIME_INTERPOLATION is defined then the architecture specific code
+(or the device drivers - like HPET) must register time interpolators.
+These are typically defined in the following way:
+
+static struct time_interpolator my_interpolator;
+
+void time_init(void)
+{
+	....
+	/* Initialization of the timer *.
+	my_interpolator.frequency = MY_FREQUENCY;
+	my_interpolator.source = TIME_SOURCE_MMIO32;
+	my_interpolator.address = &my_timer;
+	my_interpolator.shift = 32;		/* increase accuracy of scaling */
+	my_interpolator.drift = -1;		/* Unknown */
+	my_interpolator.jitter = 0;		/* A stable time source */
+	register_time_interpolator(&my_interpolator);
+	....
+}
+
+For more details see include/linux/timex.h.
+
+Christoph Lameter <christoph@lameter.com>, September 8, 2004
+
diff -Nru a/Documentation/tty.txt b/Documentation/tty.txt
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/Documentation/tty.txt	2004-10-18 14:57:24 -07:00
@@ -0,0 +1,194 @@
+
+			The Lockronomicon
+
+Your guide to the ancient and twisted locking policies of the tty layer and
+the warped logic behind them. Beware all ye who read on.
+
+FIXME: still need to work out the full set of BKL assumptions and document
+them so they can eventually be killed off.
+
+
+Line Discipline
+---------------
+
+Line disciplines are registered with tty_register_ldisc() passing the
+discipline number and the ldisc structure. At the point of registration the 
+discipline must be ready to use and it is possible it will get used before
+the call returns success. If the call returns an error then it won't get
+called. Do not re-use ldisc numbers as they are part of the userspace ABI
+and writing over an existing ldisc will cause demons to eat your computer.
+After the return the ldisc data has been copied so you may free your own 
+copy of the structure. You must not re-register over the top of the line
+discipline even with the same data or your computer again will be eaten by
+demons.
+
+In order to remove a line discipline call tty_register_ldisc passing NULL.
+In ancient times this always worked. In modern times the function will
+return -EBUSY if the ldisc is currently in use. Since the ldisc referencing
+code manages the module counts this should not usually be a concern.
+
+Heed this warning: the reference count field of the registered copies of the
+tty_ldisc structure in the ldisc table counts the number of lines using this
+discipline. The reference count of the tty_ldisc structure within a tty 
+counts the number of active users of the ldisc at this instant. In effect it
+counts the number of threads of execution within an ldisc method (plus those
+about to enter and exit although this detail matters not).
+
+Line Discipline Methods
+-----------------------
+
+TTY side interfaces:
+
+close()		-	This is called on a terminal when the line
+			discipline is being unplugged. At the point of
+			execution no further users will enter the
+			ldisc code for this tty. Can sleep.
+
+open()		-	Called when the line discipline is attached to
+			the terminal. No other call into the line
+			discipline for this tty will occur until it
+			completes successfully. Can sleep.
+
+write()		-	A process is writing data from user space
+			through the line discipline. Multiple write calls
+			are serialized by the tty layer for the ldisc. May
+			sleep.
+
+flush_buffer()	-	May be called at any point between open and close.
+
+chars_in_buffer() -	Report the number of bytes in the buffer.
+
+set_termios()	-	Called on termios structure changes. The caller
+			passes the old termios data and the current data
+			is in the tty. Called under the termios semaphore so
+			allowed to sleep. Serialized against itself only.
+
+read()		-	Move data from the line discipline to the user.
+			Multiple read calls may occur in parallel and the
+			ldisc must deal with serialization issues. May 
+			sleep.
+
+poll()		-	Check the status for the poll/select calls. Multiple
+			poll calls may occur in parallel. May sleep.
+
+ioctl()		-	Called when an ioctl is handed to the tty layer
+			that might be for the ldisc. Multiple ioctl calls
+			may occur in parallel. May sleep. 
+
+Driver Side Interfaces:
+
+receive_buf()	-	Hand buffers of bytes from the driver to the ldisc
+			for processing. Semantics currently rather
+			mysterious 8(
+
+receive_room()	-	Can be called by the driver layer at any time when
+			the ldisc is opened. The ldisc must be able to
+			handle the reported amount of data at that instant.
+			Synchronization between active receive_buf and
+			receive_room calls is down to the driver not the
+			ldisc. Must not sleep.
+
+write_wakeup()	-	May be called at any point between open and close.
+			The TTY_DO_WRITE_WAKEUP flag indicates if a call
+			is needed but always races versus calls. Thus the
+			ldisc must be careful about setting order and to
+			handle unexpected calls. Must not sleep.
+
+
+Locking
+
+Callers to the line discipline functions from the tty layer are required to
+take line discipline locks. The same is true of calls from the driver side
+but not yet enforced.
+
+Three calls are now provided
+
+	ldisc = tty_ldisc_ref(tty);
+
+takes a handle to the line discipline in the tty and returns it. If no ldisc
+is currently attached or the ldisc is being closed and re-opened at this
+point then NULL is returned. While this handle is held the ldisc will not
+change or go away.
+
+	tty_ldisc_deref(ldisc)
+
+Returns the ldisc reference and allows the ldisc to be closed. Returning the
+reference takes away your right to call the ldisc functions until you take
+a new reference.
+
+	ldisc = tty_ldisc_ref_wait(tty);
+
+Performs the same function as tty_ldisc_ref except that it will wait for an
+ldisc change to complete and then return a reference to the new ldisc. 
+
+While these functions are slightly slower than the old code they should have
+minimal impact as most receive logic uses the flip buffers and they only
+need to take a reference when they push bits up through the driver.
+
+A caution: The ldisc->open(), ldisc->close() and driver->set_ldisc 
+functions are called with the ldisc unavailable. Thus tty_ldisc_ref will
+fail in this situation if used within these functions. Ldisc and driver
+code calling its own functions must be careful in this case. 
+
+
+Driver Interface
+----------------
+
+open()		-	Called when a device is opened. May sleep
+
+close()		-	Called when a device is closed. At the point of
+			return from this call the driver must make no 
+			further ldisc calls of any kind. May sleep
+
+write()		-	Called to write bytes to the device. May not
+			sleep. May occur in parallel in special cases. 
+			Because this includes panic paths drivers generally
+			shouldn't try and do clever locking here.
+
+put_char()	-	Stuff a single character onto the queue. The
+			driver is guaranteed following up calls to
+			flush_chars.
+
+flush_chars()	-	Ask the kernel to write put_char queue
+
+write_room()	-	Return the number of characters tht can be stuffed
+			into the port buffers without overflow (or less).
+			The ldisc is responsible for being intelligent
+ 			about multi-threading of write_room/write calls
+
+ioctl()		-	Called when an ioctl may be for the driver
+
+set_termios()	-	Called on termios change, serialized against
+			itself by a semaphore. May sleep.
+
+set_ldisc()	-	Notifier for discipline change. At the point this 
+			is done the discipline is not yet usable. Can now
+			sleep (I think)
+
+throttle()	-	Called by the ldisc to ask the driver to do flow
+			control.  Serialization including with unthrottle
+			is the job of the ldisc layer.
+
+unthrottle()	-	Called by the ldisc to ask the driver to stop flow
+			control.
+
+stop()		-	Ldisc notifier to the driver to stop output. As with
+			throttle the serializations with start() are down
+			to the ldisc layer.
+
+start()		-	Ldisc notifier to the driver to start output.
+
+hangup()	-	Ask the tty driver to cause a hangup initiated
+			from the host side. [Can sleep ??]
+
+break_ctl()	-	Send RS232 break. Can sleep. Can get called in
+			parallel, driver must serialize (for now), and
+			with write calls.
+
+wait_until_sent() -	Wait for characters to exit the hardware queue
+			of the driver. Can sleep
+
+send_xchar()	  -	Send XON/XOFF and if possible jump the queue with
+			it in order to get fast flow control responses.
+			Cannot sleep ??
+
diff -Nru a/Documentation/usb/philips.txt b/Documentation/usb/philips.txt
--- a/Documentation/usb/philips.txt	2004-10-18 14:56:49 -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-10-18 14:56:50 -07:00
+++ b/Documentation/usb/sn9c102.txt	2004-10-18 14:56:50 -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
 
@@ -142,23 +142,21 @@
                 1 = critical errors
                 2 = significant informations
                 3 = more verbose messages
-                Level 3 is useful for testing only, when just one device
+                Level 3 is useful for testing only, when only one device
                 is used.
 Default:        2
 -------------------------------------------------------------------------------
 
 
-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.
 
-Every time a supported device is recognized, read-only files named "redblue"
-and "green" are created in the /sys/class/video4linux/videoX directory. You can
-set the red, blue and green channel's gain by writing the desired value to
-them. The value may range from 0 to 15 for each channel; this means that
-"redblue" accepts 8-bit values, where the low 4 bits are reserved for red and
-the others for blue.
+Every time a supported device is recognized, a read-only file named "green" is
+created in the /sys/class/video4linux/videoX directory. You can set the green
+channel's gain by writing the desired value to it. The value may range from 0
+to 15.
 
 There are other four entries in the directory above for each registered camera:
 "reg", "val", "i2c_reg" and "i2c_val". The first two files control the
@@ -208,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.
@@ -217,6 +215,7 @@
 Model       Manufacturer
 -----       ------------
 PAS106B     PixArt Imaging Inc.
+PAS202BCB   PixArt Imaging Inc.
 TAS5110C1B  Taiwan Advanced Sensor Corporation
 TAS5130D1B  Taiwan Advanced Sensor Corporation
 
@@ -239,23 +238,31 @@
 (documentation is included there). As an example, have a look at the code in
 "sn9c102_pas106b.c", which uses the mentioned interface.
 
-At the moment, not yet supported image sensors are: PAS202B (VGA),
-HV7131[D|E1] (VGA), MI03 (VGA), OV7620 (VGA).
+At the moment, not yet supported image sensors are: HV7131[D|E1] (VGA),
+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
@@ -273,4 +280,6 @@
 
 - Stefano Mozzi, who donated 45 EU;
 - Luca Capello for the donation of a webcam;
-- Mizuno Takafumi for the donation of a webcam.
+- Mizuno Takafumi for the donation of a webcam;
+- Carlos Eduardo Medaglia Dyonisio, who added the support for the PAS202BCB
+  image sensor.
diff -Nru a/Documentation/vm/overcommit-accounting b/Documentation/vm/overcommit-accounting
--- a/Documentation/vm/overcommit-accounting	2004-10-18 14:57:19 -07:00
+++ b/Documentation/vm/overcommit-accounting	2004-10-18 14:57:19 -07:00
@@ -1,4 +1,4 @@
-The Linux kernel supports three overcommit handling modes
+The Linux kernel supports the following overcommit handling modes
 
 0	-	Heuristic overcommit handling. Obvious overcommits of
 		address space are refused. Used for a typical system. It
@@ -7,10 +7,10 @@
 		allocate slighly more memory in this mode. This is the 
 		default.
 
-1	-	No overcommit handling. Appropriate for some scientific
+1	-	Always overcommit. Appropriate for some scientific
 		applications.
 
-2	-	(NEW) strict overcommit. The total address space commit
+2	-	Don't overcommit. The total address space commit
 		for the system is not permitted to exceed swap + a
 		configurable percentage (default is 50) of physical RAM.
 		Depending on the percentage you use, in most situations
@@ -27,7 +27,7 @@
 
 The C language stack growth does an implicit mremap. If you want absolute
 guarantees and run close to the edge you MUST mmap your stack for the 
-largest size you think you will need. For typical stack usage is does
+largest size you think you will need. For typical stack usage this does
 not matter much but it's a corner case if you really really care
 
 In mode 2 the MAP_NORESERVE flag is ignored. 
diff -Nru a/Documentation/watchdog/pcwd-watchdog.txt b/Documentation/watchdog/pcwd-watchdog.txt
--- a/Documentation/watchdog/pcwd-watchdog.txt	2004-10-18 14:56:29 -07:00
+++ b/Documentation/watchdog/pcwd-watchdog.txt	2004-10-18 14:56:29 -07:00
@@ -35,7 +35,8 @@
 #include <unistd.h>
 #include <fcntl.h>
 #include <sys/ioctl.h>
-#include <linux/pcwd.h>
+#include <linux/types.h>
+#include <linux/watchdog.h>
 
 int fd;
 
diff -Nru a/Documentation/x86_64/boot-options.txt b/Documentation/x86_64/boot-options.txt
--- a/Documentation/x86_64/boot-options.txt	2004-10-18 14:57:04 -07:00
+++ b/Documentation/x86_64/boot-options.txt	2004-10-18 14:57:04 -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-10-18 14:56:33 -07:00
+++ b/MAINTAINERS	2004-10-18 14:56:33 -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,12 +627,14 @@
 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
-P:	Steven Whitehouse
-M:	SteveW@ACM.org
-W:	http://www.sucs.swan.ac.uk/~rohan/DECnet/index.html
+P:	Patrick Caulfield
+M:	patrick@tykepenguin.com
+W:	http://linux-decnet.sourceforge.net
 L:	linux-decnet-user@lists.sourceforge.net
 S:	Maintained
 
@@ -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,12 +771,17 @@
 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
 
+EPSON 1355 FRAMEBUFFER DRIVER
+P:	Christopher Hoover
+M:	ch@murgatroid.com, ch@hpl.hp.com
+S:	Maintained
+
 ETHEREXPRESS-16 NETWORK DRIVER
 P:	Philip Blundell
 M:	Philip.Blundell@pobox.com
@@ -822,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
@@ -905,18 +917,18 @@
 S:	Maintained
 
 HEWLETT-PACKARD FIBRE CHANNEL 64-bit/66MHz PCI non-intelligent HBA
-P:	Chase Maupin
-M:	chase.maupin@hp.com
+P:	Chirag Kantharia
+M:	chirag.kantharia@hp.com
 L:	iss_storagedev@hp.com
 S:	Maintained
  
 HEWLETT-PACKARD SMART2 RAID DRIVER
-P:	Francis Wiran
-M:	francis.wiran@hp.com
+P:	Chirag Kantharia
+M:	chirag.kantharia@hp.com
 L:	iss_storagedev@hp.com
 S:	Maintained
  
-HEWLETT-PACKARD SMART CISS RAID DRIVER 
+HEWLETT-PACKARD SMART CISS RAID DRIVER (cciss)
 P:	Mike Miller
 M:	mike.miller@hp.com
 L:	iss_storagedev@hp.com
@@ -947,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
@@ -1060,6 +1078,19 @@
 L:	linux-fbdev-devel@lists.sourceforge.net
 S:	Maintained
 
+INPUT (KEYBOARD, MOUSE, JOYSTICK) DRIVERS
+P:	Vojtech Pavlik
+M:	vojtech@suse.cz
+L:	linux-input@atrey.karlin.mff.cuni.cz
+L:	linux-joystick@atrey.karlin.mff.cuni.cz
+S:	Maintained
+
+INTEL 810/815 FRAMEBUFFER DRIVER
+P:      Antonino Daplas
+M:      adaplas@pol.net
+L:      linux-fbdev-devel@lists.sourceforge.net
+S:      Maintained
+
 INTEL APIC/IOAPIC, LOWLEVEL X86 SMP SUPPORT
 P:	Ingo Molnar
 M:	mingo@redhat.com
@@ -1178,13 +1209,6 @@
 W:	http://oss.software.ibm.com/jfs/
 S:	Supported
 
-JOYSTICK DRIVER
-P:	Vojtech Pavlik
-M:	vojtech@suse.cz
-L:	linux-joystick@atrey.karlin.mff.cuni.cz
-W:	http://www.suse.cz/development/joystick/
-S:	Maintained
-
 KCONFIG
 P:	Roman Zippel
 M:	zippel@linux-m68k.org
@@ -1266,16 +1290,26 @@
 LINUX FOR POWERPC
 P:	Paul Mackerras
 M:	paulus@samba.org
-W:	http://www.fsmlabs.com/linuxppcbk.html
+W:	http://www.penguinppc.org/
+L:	linuxppc-dev@lists.linuxppc.org
 S:	Supported
 
 LINUX FOR POWER MACINTOSH
 P:	Benjamin Herrenschmidt
 M:	benh@kernel.crashing.org
-W:	http://www.linuxppc.org/
+W:	http://www.penguinppc.org/
 L:	linuxppc-dev@lists.linuxppc.org
 S:	Maintained
 
+LINUX FOR POWERPC EMBEDDED MPC52XX
+P:	Sylvain Munaut
+M:	tnt@246tNt.com
+W:	http://www.246tNt.com/mpc52xx/
+W:	http://www.penguinppc.org/
+L:	linuxppc-dev@ozlabs.org
+L:	linuxppc-embedded@ozlabs.org
+S:	Maintained
+
 LINUX FOR POWERPC EMBEDDED PPC4XX
 P:	Matt Porter
 M:	mporter@kernel.crashing.org
@@ -1303,9 +1337,11 @@
 S:	Maintained
 
 LINUX FOR 64BIT POWERPC
-P:	David Engebretsen (stable kernel)
-M:	engebret@us.ibm.com
-P:	Anton Blanchard (development kernel)
+P:	Paul Mackerras
+M:	paulus@samba.org
+M:	paulus@au.ibm.com
+P:	Anton Blanchard
+M:	anton@samba.org
 M:	anton@au.ibm.com
 W:	http://linuxppc64.org
 L:	linuxppc64-dev@lists.linuxppc.org
@@ -1318,6 +1354,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
@@ -1495,7 +1543,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)
@@ -1509,6 +1557,14 @@
 L:	netdev@oss.sgi.com
 S:	Maintained
 
+IPVS
+P:	Wensong Zhang
+M:	wensong@linux-vs.org
+P:	Julian Anastasov
+M:	ja@ssi.bg
+L:	lvs-users@linuxvirtualserver.org
+S:	Maintained
+
 NFS CLIENT
 P:	Trond Myklebust
 M:	trond.myklebust@fys.uio.no
@@ -1586,6 +1642,8 @@
 S:	Maintained
 
 ORINOCO DRIVER
+P:	Pavel Roskin
+M:	proski@gnu.org
 P:	David Gibson
 M:	hermes@gibson.dropbear.id.au
 W:	http://www.ozlabs.org/people/dgibson/dldwd
@@ -1600,14 +1658,14 @@
 M:	campbell@torque.net
 P:	Andrea Arcangeli
 M:	andrea@e-mind.com
-L:	linux-parport@torque.net
+L:	linux-parport@lists.infradead.org
 W:	http://people.redhat.com/twaugh/parport/
 S:	Maintained
 
 PARIDE DRIVERS FOR PARALLEL PORT IDE DEVICES
 P:	Tim Waugh
 M:	tim@cyberelk.net
-L:	linux-parport@torque.net
+L:	linux-parport@lists.infradead.org
 W:	http://www.torque.net/linux-pp.html
 S:	Maintained
 
@@ -1708,6 +1766,12 @@
 W:	http://www.pnd-pc.demon.co.uk/promise/
 S:	Maintained
 
+PXA2xx SUPPORT
+P:	Nicolas Pitre
+M:	nico@cam.org
+L:	linux-arm-kernel@lists.arm.linux.org.uk
+S:	Maintained
+
 QNX4 FILESYSTEM
 P:	Anders Larsen
 M:	al@alarsen.net
@@ -1784,12 +1848,6 @@
 W:	http://www.mihu.de/linux/saa7146
 S:	Maintained
 
-SA1100 SUPPORT
-P:	Nicolas Pitre
-M:	nico@cam.org
-L:	linux-arm@lists.arm.linux.org.uk
-S:	Maintained
-
 SBPCD CDROM DRIVER
 P:	Eberhard Moenkeberg
 M:	emoenke@gwdg.de
@@ -1895,6 +1953,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
@@ -1902,6 +1966,11 @@
 L:	samba@samba.org
 S:	Maintained
 
+SMC91x ETHERNET DRIVER
+P:	Nicolas Pitre
+M:	nico@cam.org
+S:	Maintained
+
 SNA NETWORK LAYER
 P:	Jay Schulist
 M:	jschlst@samba.org
@@ -1945,7 +2014,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
@@ -2165,12 +2234,11 @@
 L:	linux-usb-devel@lists.sourceforge.net
 S:	Maintained
 
-USB HID/HIDBP/INPUT DRIVERS
+USB HID/HIDBP DRIVERS
 P:	Vojtech Pavlik
 M:	vojtech@suse.cz
 L:	linux-usb-users@lists.sourceforge.net
 L:	linux-usb-devel@lists.sourceforge.net
-W:	http://www.suse.cz/development/input/
 S:	Maintained
 
 USB HUB DRIVER
@@ -2299,6 +2367,13 @@
 W:	http://www.connecttech.com
 S:	Supported
 
+USB SN9C10[12] DRIVER
+P:	Luca Risolia
+M:	luca.risolia@studio.unibo.it
+L:	linux-usb-devel@lists.sourceforge.net
+W:	http://go.lamarinapunto.com
+S:	Maintained
+
 USB SUBSYSTEM
 P:	Greg Kroah-Hartman
 M:	greg@kroah.com
@@ -2391,6 +2466,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-10-18 14:56:33 -07:00
+++ b/Makefile	2004-10-18 14:56:34 -07:00
@@ -1,6 +1,6 @@
 VERSION = 2
 PATCHLEVEL = 6
-SUBLEVEL = 8
+SUBLEVEL = 9
 EXTRAVERSION =
 NAME=Zonked Quokka
 
@@ -102,7 +102,7 @@
 # check that the output directory actually exists
 saved-output := $(KBUILD_OUTPUT)
 KBUILD_OUTPUT := $(shell cd $(KBUILD_OUTPUT) && /bin/pwd)
-$(if $(wildcard $(KBUILD_OUTPUT)),, \
+$(if $(KBUILD_OUTPUT),, \
      $(error output directory "$(saved-output)" does not exist))
 
 .PHONY: $(MAKECMDGOALS)
@@ -141,7 +141,25 @@
 
 export srctree objtree VPATH TOPDIR
 
-KERNELRELEASE=$(VERSION).$(PATCHLEVEL).$(SUBLEVEL)$(EXTRAVERSION)
+nullstring :=
+space      := $(nullstring) # end of line
+
+# Take the contents of any files called localversion* and the config
+# variable CONFIG_LOCALVERSION and append them to KERNELRELEASE. Be
+# careful not to include files twice if building in the source
+# directory. LOCALVERSION from the command line override all of this
+
+ifeq ($(objtree),$(srctree))
+localversion-files := $(wildcard $(srctree)/localversion*)
+else
+localversion-files := $(wildcard $(objtree)/localversion* $(srctree)/localversion*)
+endif
+
+LOCALVERSION = $(subst $(space),, \
+	       $(shell cat /dev/null $(localversion-files)) \
+	       $(subst ",,$(CONFIG_LOCALVERSION)))
+
+KERNELRELEASE=$(VERSION).$(PATCHLEVEL).$(SUBLEVEL)$(EXTRAVERSION)$(LOCALVERSION)
 
 # SUBARCH tells the usermode build what the underlying arch is.  That is set
 # first, and if a usermode build is happening, the "ARCH=um" on the command
@@ -256,9 +274,32 @@
   quiet=silent_
 endif
 
-check_gcc = $(shell if $(CC) $(CFLAGS) $(1) -S -o /dev/null -xc /dev/null > /dev/null 2>&1; then echo "$(1)"; else echo "$(2)"; fi ;)
+export quiet Q KBUILD_VERBOSE
+
+######
+# cc support functions to be used (only) in arch/$(ARCH)/Makefile
+# See documentation in Documentation/kbuild/makefiles.txt
+
+# cc-option
+# Usage: cflags-y += $(call gcc-option, -march=winchip-c6, -march=i586)
+
+cc-option = $(shell if $(CC) $(CFLAGS) $(1) -S -o /dev/null -xc /dev/null \
+             > /dev/null 2>&1; then echo "$(1)"; else echo "$(2)"; fi ;)
+
+# For backward compatibility
+check_gcc = $(warning check_gcc is deprecated - use cc-option) \
+            $(call cc-option, $(1),$(2))
+
+# cc-option-yn
+# Usage: flag := $(call gcc-option-yn, -march=winchip-c6)
+cc-option-yn = $(shell if $(CC) $(CFLAGS) $(1) -S -o /dev/null -xc /dev/null \
+                > /dev/null 2>&1; then echo "y"; else echo "n"; fi;)
+
+# cc-version
+# Usage gcc-ver := $(call cc-version $(CC))
+cc-version = $(shell $(CONFIG_SHELL) $(srctree)/scripts/gcc-version.sh \
+              $(if $(1), $(1), $(CC)))
 
-export quiet Q KBUILD_VERBOSE check_gcc
 
 # Look for make include files relative to root of kernel src
 MAKEFLAGS += --include-dir=$(srctree)
@@ -285,6 +326,7 @@
 KALLSYMS	= scripts/kallsyms
 PERL		= perl
 CHECK		= sparse
+CHECKFLAGS     := -D__linux__ -Dlinux -D__STDC__ -Dunix -D__unix__
 MODFLAGS	= -DMODULE
 CFLAGS_MODULE   = $(MODFLAGS)
 AFLAGS_MODULE   = $(MODFLAGS)
@@ -294,19 +336,23 @@
 
 NOSTDINC_FLAGS  = -nostdinc -iwithprefix include
 
-CPPFLAGS        := -D__KERNEL__ -Iinclude \
-		   $(if $(KBUILD_SRC),-Iinclude2 -I$(srctree)/include)
+# Use LINUXINCLUDE when you must reference the include/ directory.
+# Needed to be compatible with the O= option
+LINUXINCLUDE    := -Iinclude \
+                   $(if $(KBUILD_SRC),-Iinclude2 -I$(srctree)/include)
+
+CPPFLAGS        := -D__KERNEL__ $(LINUXINCLUDE)
 
 CFLAGS 		:= -Wall -Wstrict-prototypes -Wno-trigraphs \
 	  	   -fno-strict-aliasing -fno-common
 AFLAGS		:= -D__ASSEMBLY__
 
-export	VERSION PATCHLEVEL SUBLEVEL EXTRAVERSION KERNELRELEASE ARCH \
-	CONFIG_SHELL HOSTCC HOSTCFLAGS CROSS_COMPILE AS LD CC \
+export	VERSION PATCHLEVEL SUBLEVEL EXTRAVERSION LOCALVERSION KERNELRELEASE \
+	ARCH CONFIG_SHELL HOSTCC HOSTCFLAGS CROSS_COMPILE AS LD CC \
 	CPP AR NM STRIP OBJCOPY OBJDUMP MAKE AWK GENKSYMS PERL UTS_MACHINE \
-	HOSTCXX HOSTCXXFLAGS LDFLAGS_BLOB LDFLAGS_MODULE CHECK
+	HOSTCXX HOSTCXXFLAGS LDFLAGS_MODULE CHECK CHECKFLAGS
 
-export CPPFLAGS NOSTDINC_FLAGS OBJCOPYFLAGS LDFLAGS
+export CPPFLAGS NOSTDINC_FLAGS LINUXINCLUDE OBJCOPYFLAGS LDFLAGS
 export CFLAGS CFLAGS_KERNEL CFLAGS_MODULE 
 export AFLAGS AFLAGS_KERNEL AFLAGS_MODULE
 
@@ -428,15 +474,6 @@
 include/linux/autoconf.h: ;
 endif
 
-include $(srctree)/arch/$(ARCH)/Makefile
-
-# Default kernel image to build when no specific target is given.
-# KBUILD_IMAGE may be overruled on the commandline or
-# set in the environment
-# Also any assingments in arch/$(ARCH)/Makefiel take precedence over
-# this default value
-export KBUILD_IMAGE ?= vmlinux
-
 # The all: target is the default when no target is given on the
 # command line.
 # This allow a user to issue only 'make' to build a kernel including modules
@@ -458,7 +495,16 @@
 endif
 
 # warn about C99 declaration after statement
-CFLAGS += $(call check_gcc,-Wdeclaration-after-statement,)
+CFLAGS += $(call cc-option,-Wdeclaration-after-statement,)
+
+include $(srctree)/arch/$(ARCH)/Makefile
+
+# Default kernel image to build when no specific target is given.
+# KBUILD_IMAGE may be overruled on the commandline or
+# set in the environment
+# Also any assingments in arch/$(ARCH)/Makefiel take precedence over
+# this default value
+export KBUILD_IMAGE ?= vmlinux
 
 #
 # INSTALL_PATH specifies where to place the updated kernel and system map
@@ -499,67 +545,93 @@
 
 # Build vmlinux
 # ---------------------------------------------------------------------------
+# vmlinux is build from the objects selected by $(vmlinux-init) and
+# $(vmlinux-main). Most are built-in.o files from top-level directories
+# in the kernel tree, others are specified in arch/$(ARCH)Makefile.
+# Ordering when linking is important, and $(vmlinux-init) must be first.
+#
+# vmlinux
+#   ^
+#   |
+#   +-< $(vmlinux-init)
+#   |   +--< init/version.o + more
+#   |
+#   +--< $(vmlinux-main)
+#   |    +--< driver/built-in.o mm/built-in.o + more
+#   |
+#   +-< kallsyms.o (see description in CONFIG_KALLSYMS section)
+#
+# vmlinux version (uname -v) cannot be updated during normal
+# descending-into-subdirs phase since we do not yet know if we need to
+# update vmlinux.
+# Therefore this step is delayed until just before final link of vmlinux -
+# except in the kallsyms case where it is done just before adding the
+# symbols to the kernel.
+#
+# System.map is generated to document addresses of all kernel symbols
 
-#	This is a bit tricky: If we need to relink vmlinux, we want
-#	the version number incremented, which means recompile init/version.o
-#	and relink init/init.o. However, we cannot do this during the
-#       normal descending-into-subdirs phase, since at that time
-#       we cannot yet know if we will need to relink vmlinux.
-#	So we descend into init/ inside the rule for vmlinux again.
-head-y += $(HEAD)
-vmlinux-objs := $(head-y) $(init-y) $(core-y) $(libs-y) $(drivers-y) $(net-y)
-
-quiet_cmd_vmlinux__ = LD      $@
-define cmd_vmlinux__
-	$(LD) $(LDFLAGS) $(LDFLAGS_vmlinux) $(head-y) $(init-y) \
-	--start-group \
-	$(core-y) \
-	$(libs-y) \
-	$(drivers-y) \
-	$(net-y) \
-	--end-group \
-	$(filter .tmp_kallsyms%,$^) \
-	-o $@
-endef
-
-#	set -e makes the rule exit immediately on error
+vmlinux-init := $(head-y) $(init-y)
+vmlinux-main := $(core-y) $(libs-y) $(drivers-y) $(net-y)
+vmlinux-all  := $(vmlinux-init) $(vmlinux-main)
+vmlinux-lds  := arch/$(ARCH)/kernel/vmlinux.lds
+
+# Rule to link vmlinux - also used during CONFIG_KALLSYMS
+# May be overridden by arch/$(ARCH)/Makefile
+quiet_cmd_vmlinux__ ?= LD      $@
+      cmd_vmlinux__ ?= $(LD) $(LDFLAGS) $(LDFLAGS_vmlinux) -o $@ \
+      -T $(vmlinux-lds) $(vmlinux-init)                          \
+      --start-group $(vmlinux-main) --end-group                  \
+      $(filter-out $(vmlinux-lds) $(vmlinux-init) $(vmlinux-main) FORCE ,$^)
+
+# Generate new vmlinux version
+quiet_cmd_vmlinux_version = GEN     .version
+      cmd_vmlinux_version = set -e;                     \
+	. $(srctree)/scripts/mkversion > .tmp_version;	\
+	mv -f .tmp_version .version;			\
+	$(MAKE) $(build)=init
+
+# Generate System.map
+quiet_cmd_sysmap = SYSMAP 
+      cmd_sysmap = $(CONFIG_SHELL) $(srctree)/scripts/mksysmap
+
+# Link of vmlinux
+# If CONFIG_KALLSYMS is set .version is already updated
+# Generate System.map and verify that the content is consistent
 
 define rule_vmlinux__
-	+set -e;							\
-	$(if $(filter .tmp_kallsyms%,$^),,				\
-	  echo '  GEN     .version';					\
-	  . $(srctree)/scripts/mkversion > .tmp_version;		\
-	  mv -f .tmp_version .version;					\
-	  $(MAKE) $(build)=init;					\
-	)								\
-	$(if $($(quiet)cmd_vmlinux__),					\
-	  echo '  $($(quiet)cmd_vmlinux__)' &&) 			\
-	$(cmd_vmlinux__);						\
-	echo 'cmd_$@ := $(cmd_vmlinux__)' > $(@D)/.$(@F).cmd
-endef
+	$(if $(CONFIG_KALLSYMS),,+$(call cmd,vmlinux_version))
 
-do_system_map = $(NM) $(1) | grep -v '\(compiled\)\|\(\.o$$\)\|\( [aUw] \)\|\(\.\.ng$$\)\|\(LASH[RL]DI\)' | sort > $(2)
+	$(call cmd,vmlinux__)
+	$(Q)echo 'cmd_$@ := $(cmd_vmlinux__)' > $(@D)/.$(@F).cmd
 
-LDFLAGS_vmlinux += -T arch/$(ARCH)/kernel/vmlinux.lds.s
+	$(Q)$(if $($(quiet)cmd_sysmap),                 \
+	  echo '  $($(quiet)cmd_sysmap) System.map' &&) \
+	$(cmd_sysmap) $@ System.map;                    \
+	if [ $$? -ne 0 ]; then                          \
+		rm -f $@;                               \
+		/bin/false;                             \
+	fi;
+	$(verify_kallsyms)
+endef
 
-#	Generate section listing all symbols and add it into vmlinux
-#	It's a three stage process:
-#	o .tmp_vmlinux1 has all symbols and sections, but __kallsyms is
-#	  empty
-#	  Running kallsyms on that gives us .tmp_kallsyms1.o with
-#	  the right size
-#	o .tmp_vmlinux2 now has a __kallsyms section of the right size,
-#	  but due to the added section, some addresses have shifted
-#	  From here, we generate a correct .tmp_kallsyms2.o
-#	o The correct .tmp_kallsyms2.o is linked into the final vmlinux.
-#	o Verify that the System.map from vmlinux matches the map from
-#	  .tmp_vmlinux2, just in case we did not generate kallsyms correctly.
-#	o If CONFIG_KALLSYMS_EXTRA_PASS is set, do an extra pass using
-#	  .tmp_vmlinux3 and .tmp_kallsyms3.o.  This is only meant as a
-#	  temporary bypass to allow the kernel to be built while the
-#	  maintainers work out what went wrong with kallsyms.
 
 ifdef CONFIG_KALLSYMS
+# Generate section listing all symbols and add it into vmlinux $(kallsyms.o)
+# It's a three stage process:
+# o .tmp_vmlinux1 has all symbols and sections, but __kallsyms is
+#   empty
+#   Running kallsyms on that gives us .tmp_kallsyms1.o with
+#   the right size - vmlinux version (uname -v) is updated during this step
+# o .tmp_vmlinux2 now has a __kallsyms section of the right size,
+#   but due to the added section, some addresses have shifted.
+#   From here, we generate a correct .tmp_kallsyms2.o
+# o The correct .tmp_kallsyms2.o is linked into the final vmlinux.
+# o Verify that the System.map from vmlinux matches the map from
+#   .tmp_vmlinux2, just in case we did not generate kallsyms correctly.
+# o If CONFIG_KALLSYMS_EXTRA_PASS is set, do an extra pass using
+#   .tmp_vmlinux3 and .tmp_kallsyms3.o.  This is only meant as a
+#   temporary bypass to allow the kernel to be built while the
+#   maintainers work out what went wrong with kallsyms.
 
 ifdef CONFIG_KALLSYMS_EXTRA_PASS
 last_kallsyms := 3
@@ -569,47 +641,58 @@
 
 kallsyms.o := .tmp_kallsyms$(last_kallsyms).o
 
-define rule_verify_kallsyms
-	@$(call do_system_map, .tmp_vmlinux$(last_kallsyms), .tmp_System.map)
-	@cmp -s System.map .tmp_System.map || \
-		(echo Inconsistent kallsyms data, try setting CONFIG_KALLSYMS_EXTRA_PASS ; rm .tmp_kallsyms* ; false)
+define verify_kallsyms
+	$(Q)$(if $($(quiet)cmd_sysmap),                       \
+	  echo '  $($(quiet)cmd_sysmap) .tmp_System.map' &&)  \
+	  $(cmd_sysmap) .tmp_vmlinux$(last_kallsyms) .tmp_System.map
+	$(Q)cmp -s System.map .tmp_System.map ||              \
+		(echo Inconsistent kallsyms data;             \
+		 echo Try setting CONFIG_KALLSYMS_EXTRA_PASS; \
+		 rm .tmp_kallsyms* ; /bin/false )
+endef
+
+# Update vmlinux version before link
+# Use + in front of this rule to silent warning about make -j1
+cmd_ksym_ld = $(cmd_vmlinux__)
+define rule_ksym_ld
+	+$(call cmd,vmlinux_version)
+	$(call cmd,vmlinux__)
+	$(Q)echo 'cmd_$@ := $(cmd_vmlinux__)' > $(@D)/.$(@F).cmd
 endef
 
+# Generate .S file with all kernel symbols
 quiet_cmd_kallsyms = KSYM    $@
-cmd_kallsyms = $(NM) -n $< | $(KALLSYMS) $(foreach x,$(CONFIG_KALLSYMS_ALL),--all-symbols) > $@
+      cmd_kallsyms = $(NM) -n $< | $(KALLSYMS) \
+                     $(if $(CONFIG_KALLSYMS_ALL),--all-symbols) > $@
 
 .tmp_kallsyms1.o .tmp_kallsyms2.o .tmp_kallsyms3.o: %.o: %.S scripts FORCE
 	$(call if_changed_dep,as_o_S)
 
-.tmp_kallsyms%.S: .tmp_vmlinux%
+.tmp_kallsyms%.S: .tmp_vmlinux% $(KALLSYMS)
 	$(call cmd,kallsyms)
 
-.tmp_vmlinux1: $(vmlinux-objs) arch/$(ARCH)/kernel/vmlinux.lds.s FORCE
-	$(call if_changed_rule,vmlinux__)
-
-.tmp_vmlinux2: $(vmlinux-objs) .tmp_kallsyms1.o arch/$(ARCH)/kernel/vmlinux.lds.s FORCE
-	$(call if_changed_rule,vmlinux__)
+# .tmp_vmlinux1 must be complete except kallsyms, so update vmlinux version
+.tmp_vmlinux1: $(vmlinux-lds) $(vmlinux-all) FORCE
+	$(call if_changed_rule,ksym_ld)
 
-.tmp_vmlinux3: $(vmlinux-objs) .tmp_kallsyms2.o arch/$(ARCH)/kernel/vmlinux.lds.s FORCE
-	$(call if_changed_rule,vmlinux__)
-
-endif
+.tmp_vmlinux2: $(vmlinux-lds) $(vmlinux-all) .tmp_kallsyms1.o FORCE
+	$(call if_changed,vmlinux__)
 
-#	Finally the vmlinux rule
+.tmp_vmlinux3: $(vmlinux-lds) $(vmlinux-all) .tmp_kallsyms2.o FORCE
+	$(call if_changed,vmlinux__)
 
-define rule_vmlinux
-	$(rule_vmlinux__); \
-	$(call do_system_map, $@, System.map)
-	$(rule_verify_kallsyms)
-endef
+# Needs to visit scripts/ before $(KALLSYMS) can be used.
+$(KALLSYMS): scripts ;
 
-vmlinux: $(vmlinux-objs) $(kallsyms.o) arch/$(ARCH)/kernel/vmlinux.lds.s FORCE
-	$(call if_changed_rule,vmlinux)
+endif # ifdef CONFIG_KALLSYMS
 
-#	The actual objects are generated when descending, 
-#	make sure no implicit rule kicks in
+# vmlinux image - including updated kernel symbols
+vmlinux: $(vmlinux-lds) $(vmlinux-init) $(vmlinux-main) $(kallsyms.o) FORCE
+	$(call if_changed_rule,vmlinux__)
 
-$(sort $(vmlinux-objs)) arch/$(ARCH)/kernel/vmlinux.lds.s: $(vmlinux-dirs) ;
+# The actual objects are generated when descending, 
+# make sure no implicit rule kicks in
+$(sort $(vmlinux-init) $(vmlinux-main)) $(vmlinux-lds): $(vmlinux-dirs) ;
 
 # Handle descending into subdirectories listed in $(vmlinux-dirs)
 # Preset locale variables to speed up the build process. Limit locale
@@ -632,10 +715,10 @@
 # using a seperate output directory. This allows convinient use
 # of make in output directory
 prepare2:
-	$(Q)if [ ! $(srctree) -ef $(objtree) ]; then       \
-	$(CONFIG_SHELL) $(srctree)/scripts/mkmakefile      \
-	    $(srctree) $(objtree) $(VERSION) $(PATCHLEVEL) \
-	    > $(objtree)/Makefile;                         \
+	$(Q)if /usr/bin/env test ! $(srctree) -ef $(objtree); then \
+	$(CONFIG_SHELL) $(srctree)/scripts/mkmakefile              \
+	    $(srctree) $(objtree) $(VERSION) $(PATCHLEVEL)         \
+	    > $(objtree)/Makefile;                                 \
 	fi
 
 # prepare1 is used to check if we are building in a separate output directory,
@@ -667,7 +750,7 @@
 #	Leave this as default for preprocessing vmlinux.lds.S, which is now
 #	done in arch/$(ARCH)/kernel/Makefile
 
-export AFLAGS_vmlinux.lds.o += -P -C -U$(ARCH)
+export CPPFLAGS_vmlinux.lds += -P -C -U$(ARCH)
 
 # Single targets
 # ---------------------------------------------------------------------------
@@ -706,8 +789,8 @@
 # Generate some files
 # ---------------------------------------------------------------------------
 
-#	version.h changes when $(KERNELRELEASE) etc change, as defined in
-#	this Makefile
+# KERNELRELEASE can change from a few different places, meaning version.h
+# needs to be updated, so this check is forced on all builds
 
 uts_len := 64
 
@@ -722,7 +805,7 @@
 	)
 endef
 
-include/linux/version.h: Makefile
+include/linux/version.h: $(srctree)/Makefile FORCE
 	$(call filechk,version.h)
 
 # ---------------------------------------------------------------------------
@@ -922,7 +1005,13 @@
 	@echo  '  rpm		  - Build a kernel as an RPM package'
 	@echo  '  tags/TAGS	  - Generate tags file for editors'
 	@echo  '  cscope	  - Generate cscope index'
+	@echo  ''
+	@echo  'Static analysers'
+	@echo  '  buildcheck      - List dangling references to vmlinux discarded sections'
+	@echo  '                    and init sections from non-init sections'
 	@echo  '  checkstack      - Generate a list of stack hogs'
+	@echo  '  namespacecheck  - Name space analysis on compiled kernel'
+	@echo  ''
 	@echo  'Kernel packaging:'
 	@$(MAKE) -f $(package-dir)/Makefile help
 	@echo  ''
@@ -940,7 +1029,8 @@
 
 	@echo  '  make V=0|1 [targets] 0 => quiet build (default), 1 => verbose build'
 	@echo  '  make O=dir [targets] Locate all output files in "dir", including .config'
-	@echo  '  make C=1   [targets] Check all c source with checker tool'
+	@echo  '  make C=1   [targets] Check all c source with $$CHECK (sparse)'
+	@echo  '  make C=2   [targets] Force check of all c source with $$CHECK (sparse)'
 	@echo  ''
 	@echo  'Execute "make" or "make all" to build all targets marked with [*] '
 	@echo  'For further info see the ./README file'
@@ -1081,8 +1171,11 @@
 		| xargs $(PERL) -w scripts/checkversion.pl
 
 buildcheck:
-	$(PERL) scripts/reference_discarded.pl
-	$(PERL) scripts/reference_init.pl
+	$(PERL) $(srctree)/scripts/reference_discarded.pl
+	$(PERL) $(srctree)/scripts/reference_init.pl
+
+namespacecheck:
+	$(PERL) $(srctree)/scripts/namespace.pl
 
 endif #ifeq ($(config-targets),1)
 endif #ifeq ($(mixed-targets),1)
@@ -1119,13 +1212,22 @@
   include $(cmd_files)
 endif
 
+# Execute command and generate cmd file
+if_changed = $(if $(strip $? \
+		          $(filter-out $(cmd_$(1)),$(cmd_$@))\
+			  $(filter-out $(cmd_$@),$(cmd_$(1)))),\
+	@set -e; \
+	$(if $($(quiet)cmd_$(1)),echo '  $(subst ','\'',$($(quiet)cmd_$(1)))';) \
+	$(cmd_$(1)); \
+	echo 'cmd_$@ := $(subst $$,$$$$,$(subst ','\'',$(cmd_$(1))))' > $(@D)/.$(@F).cmd)
+
+
 # execute the command and also postprocess generated .d dependencies
 # file
-
 if_changed_dep = $(if $(strip $? $(filter-out FORCE $(wildcard $^),$^)\
 		          $(filter-out $(cmd_$(1)),$(cmd_$@))\
 			  $(filter-out $(cmd_$@),$(cmd_$(1)))),\
-	@set -e; \
+	$(Q)set -e; \
 	$(if $($(quiet)cmd_$(1)),echo '  $(subst ','\'',$($(quiet)cmd_$(1)))';) \
 	$(cmd_$(1)); \
 	scripts/basic/fixdep $(depfile) $@ '$(subst $$,$$$$,$(subst ','\'',$(cmd_$(1))))' > $(@D)/.$(@F).tmp; \
@@ -1139,7 +1241,7 @@
 if_changed_rule = $(if $(strip $? \
 		               $(filter-out $(cmd_$(1)),$(cmd_$(@F)))\
 			       $(filter-out $(cmd_$(@F)),$(cmd_$(1)))),\
-	               @$(rule_$(1)))
+	               $(Q)$(rule_$(1)))
 
 # If quiet is set, only print short version of command
 
diff -Nru a/arch/alpha/Kconfig b/arch/alpha/Kconfig
--- a/arch/alpha/Kconfig	2004-10-18 14:56:49 -07:00
+++ b/arch/alpha/Kconfig	2004-10-18 14:56:49 -07:00
@@ -32,6 +32,10 @@
 	bool
 	default y
 
+config GENERIC_IOMAP
+	bool
+	default n
+
 source "init/Kconfig"
 
 
@@ -462,11 +466,6 @@
 
 	  If unsure, say N.
 
-config EARLY_PRINTK
-	bool
-	depends on ALPHA_GENERIC || ALPHA_SRM
-	default y
-
 config EISA
 	bool
 	depends on ALPHA_GENERIC || ALPHA_JENSEN || ALPHA_ALCOR || ALPHA_MIKASA || ALPHA_SABLE || ALPHA_LYNX || ALPHA_NORITAKE || ALPHA_RAWHIDE
@@ -593,104 +592,7 @@
 
 source "arch/alpha/oprofile/Kconfig"
 
-menu "Kernel hacking"
-
-config ALPHA_LEGACY_START_ADDRESS
-	bool "Legacy kernel start address"
-	depends on ALPHA_GENERIC
-	default n
-	---help---
-	  The 2.4 kernel changed the kernel start address from 0x310000
-	  to 0x810000 to make room for the Wildfire's larger SRM console.
-	  Recent consoles on Titan and Marvel machines also require the
-	  extra room.
-
-	  If you're using aboot 0.7 or later, the bootloader will examine the
-	  ELF headers to determine where to transfer control. Unfortunately,
-	  most older bootloaders -- APB or MILO -- hardcoded the kernel start
-	  address rather than examining the ELF headers, and the result is a
-	  hard lockup.
-
-	  Say Y if you have a broken bootloader.  Say N if you do not, or if
-	  you wish to run on Wildfire, Titan, or Marvel.
-
-config ALPHA_LEGACY_START_ADDRESS
-	bool
-	depends on !ALPHA_GENERIC && !ALPHA_TITAN && !ALPHA_MARVEL && !ALPHA_WILDFIRE
-	default y
-
-config DEBUG_KERNEL
-	bool "Kernel debugging"
-	help
-	  Say Y here if you are developing drivers or trying to debug and
-	  identify kernel problems.
-
-config MATHEMU
-	tristate "Kernel FP software completion" if DEBUG_KERNEL && !SMP
-	default y if !DEBUG_KERNEL || SMP
-	help
-	  This option is required for IEEE compliant floating point arithmetic
-	  on the Alpha. The only time you would ever not say Y is to say M in
-	  order to debug the code. Say Y unless you know what you are doing.
-
-config DEBUG_SLAB
-	bool "Debug memory allocations"
-	depends on DEBUG_KERNEL
-	help
-	  Say Y here to have the kernel do limited verification on memory
-	  allocation as well as poisoning memory on free to catch use of freed
-	  memory.
-
-config MAGIC_SYSRQ
-	bool "Magic SysRq key"
-	depends on DEBUG_KERNEL
-	help
-	  If you say Y here, you will have some control over the system even
-	  if the system crashes for example during kernel debugging (e.g., you
-	  will be able to flush the buffer cache to disk, reboot the system
-	  immediately or dump some status information). This is accomplished
-	  by pressing various keys while holding SysRq (Alt+PrintScreen). It
-	  also works on a serial console (on PC hardware at least), if you
-	  send a BREAK and then within 5 seconds a command keypress. The
-	  keys are documented in <file:Documentation/sysrq.txt>. Don't say Y
-	  unless you really know what this hack does.
-
-config DEBUG_SPINLOCK
-	bool "Spinlock debugging"
-	depends on DEBUG_KERNEL
-	help
-	  Say Y here and build SMP to catch missing spinlock initialization
-	  and certain other kinds of spinlock errors commonly made.  This is
-	  best used in conjunction with the NMI watchdog so that spinlock
-	  deadlocks are also debuggable.
-
-config DEBUG_RWLOCK
-	bool "Read-write spinlock debugging"
-	depends on DEBUG_KERNEL
-	help
-	  If you say Y here then read-write lock processing will count how many
-	  times it has tried to get the lock and issue an error message after
-	  too many attempts.  If you suspect a rwlock problem or a kernel
-	  hacker asks for this option then say Y.  Otherwise say N.
-
-config DEBUG_SEMAPHORE
-	bool "Semaphore debugging"
-	depends on DEBUG_KERNEL
-	help
-	  If you say Y here then semaphore processing will issue lots of
-	  verbose debugging messages.  If you suspect a semaphore problem or a
-	  kernel hacker asks for this option then say Y.  Otherwise say N.
-
-config DEBUG_INFO
-	bool "Compile the kernel with debug info"
-	depends on DEBUG_KERNEL
-	help
-          If you say Y here the resulting kernel image will include
-	  debugging info resulting in a larger kernel image.
-	  Say Y here only if you plan to use gdb to debug the kernel.
-	  If you don't debug the kernel, you can say N.
-
-endmenu
+source "arch/alpha/Kconfig.debug"
 
 source "security/Kconfig"
 
diff -Nru a/arch/alpha/Kconfig.debug b/arch/alpha/Kconfig.debug
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/arch/alpha/Kconfig.debug	2004-10-18 14:57:23 -07:00
@@ -0,0 +1,59 @@
+menu "Kernel hacking"
+
+source "lib/Kconfig.debug"
+
+config EARLY_PRINTK
+	bool
+	depends on ALPHA_GENERIC || ALPHA_SRM
+	default y
+
+config DEBUG_RWLOCK
+	bool "Read-write spinlock debugging"
+	depends on DEBUG_KERNEL
+	help
+	  If you say Y here then read-write lock processing will count how many
+	  times it has tried to get the lock and issue an error message after
+	  too many attempts.  If you suspect a rwlock problem or a kernel
+	  hacker asks for this option then say Y.  Otherwise say N.
+
+config DEBUG_SEMAPHORE
+	bool "Semaphore debugging"
+	depends on DEBUG_KERNEL
+	help
+	  If you say Y here then semaphore processing will issue lots of
+	  verbose debugging messages.  If you suspect a semaphore problem or a
+	  kernel hacker asks for this option then say Y.  Otherwise say N.
+
+config ALPHA_LEGACY_START_ADDRESS
+	bool "Legacy kernel start address"
+	depends on ALPHA_GENERIC
+	default n
+	---help---
+	  The 2.4 kernel changed the kernel start address from 0x310000
+	  to 0x810000 to make room for the Wildfire's larger SRM console.
+	  Recent consoles on Titan and Marvel machines also require the
+	  extra room.
+
+	  If you're using aboot 0.7 or later, the bootloader will examine the
+	  ELF headers to determine where to transfer control. Unfortunately,
+	  most older bootloaders -- APB or MILO -- hardcoded the kernel start
+	  address rather than examining the ELF headers, and the result is a
+	  hard lockup.
+
+	  Say Y if you have a broken bootloader.  Say N if you do not, or if
+	  you wish to run on Wildfire, Titan, or Marvel.
+
+config ALPHA_LEGACY_START_ADDRESS
+	bool
+	depends on !ALPHA_GENERIC && !ALPHA_TITAN && !ALPHA_MARVEL && !ALPHA_WILDFIRE
+	default y
+
+config MATHEMU
+	tristate "Kernel FP software completion" if DEBUG_KERNEL && !SMP
+	default y if !DEBUG_KERNEL || SMP
+	help
+	  This option is required for IEEE compliant floating point arithmetic
+	  on the Alpha. The only time you would ever not say Y is to say M in
+	  order to debug the code. Say Y unless you know what you are doing.
+
+endmenu
diff -Nru a/arch/alpha/Makefile b/arch/alpha/Makefile
--- a/arch/alpha/Makefile	2004-10-18 14:56:33 -07:00
+++ b/arch/alpha/Makefile	2004-10-18 14:56:33 -07:00
@@ -11,7 +11,7 @@
 NM := $(NM) -B
 
 LDFLAGS_vmlinux	:= -static -N #-relax
-CHECK		:= $(CHECK) -D__alpha__=1
+CHECKFLAGS	+= -D__alpha__
 cflags-y	:= -pipe -mno-fp-regs -ffixed-8
 
 # Determine if we can use the BWX instructions with GAS.
@@ -22,15 +22,11 @@
 endif
 
 # Determine if GCC understands the -mcpu= option.
-have_mcpu := $(shell if $(CC) -mcpu=ev5 -S -o /dev/null -xc /dev/null > /dev/null 2>&1; then echo y; else echo n; fi)
-
-have_mcpu_pca56 := $(shell if $(CC) -mcpu=pca56 -S -o /dev/null -xc /dev/null > /dev/null 2>&1; then echo y; else echo n; fi)
-
-have_mcpu_ev6 := $(shell if $(CC) -mcpu=ev6 -S -o /dev/null -xc /dev/null > /dev/null 2>&1; then echo y; else echo n; fi)
-
-have_mcpu_ev67 := $(shell if $(CC) -mcpu=ev67 -S -o /dev/null -xc /dev/null > /dev/null 2>&1; then echo y; else echo n; fi)
-
-have_msmall_data := $(shell if $(CC) -msmall-data -S -o /dev/null -xc /dev/null > /dev/null 2>&1; then echo y; else echo n; fi)
+have_mcpu        := $(call cc-option-yn, -mcpu=ev5)
+have_mcpu_pca56  := $(call cc-option-yn, -mcpu=pca56)
+have_mcpu_ev6    := $(call cc-option-yn, -mcpu=ev6)
+have_mcpu_ev67   := $(call cc-option-yn, -mcpu=ev67)
+have_msmall_data := $(call cc-option-yn, -msmall-data)
 
 cflags-$(have_msmall_data) += -msmall-data
 
diff -Nru a/arch/alpha/boot/Makefile b/arch/alpha/boot/Makefile
--- a/arch/alpha/boot/Makefile	2004-10-18 14:56:17 -07:00
+++ b/arch/alpha/boot/Makefile	2004-10-18 14:56:17 -07:00
@@ -8,7 +8,7 @@
 # Copyright (C) 1994 by Linus Torvalds
 #
 
-host-progs	:= tools/mkbb tools/objstrip
+hostprogs-y	:= tools/mkbb tools/objstrip
 targets		:= vmlinux.gz vmlinux \
 		   vmlinux.nh tools/lxboot tools/bootlx tools/bootph \
 		   tools/bootpzh bootloader bootpheader bootpzheader 
diff -Nru a/arch/alpha/defconfig b/arch/alpha/defconfig
--- a/arch/alpha/defconfig	2004-10-18 14:56:32 -07:00
+++ b/arch/alpha/defconfig	2004-10-18 14:56:32 -07:00
@@ -1,38 +1,48 @@
 #
 # Automatically generated make config: don't edit
+# Linux kernel version: 2.6.9-rc2
+# Sat Sep 25 15:38:35 2004
 #
 CONFIG_ALPHA=y
 CONFIG_64BIT=y
 CONFIG_MMU=y
 CONFIG_RWSEM_XCHGADD_ALGORITHM=y
 CONFIG_GENERIC_ISA_DMA=y
+# CONFIG_GENERIC_IOMAP is not set
 
 #
 # Code maturity level options
 #
 CONFIG_EXPERIMENTAL=y
 CONFIG_CLEAN_COMPILE=y
-CONFIG_STANDALONE=y
 CONFIG_BROKEN_ON_SMP=y
 
 #
 # General setup
 #
+CONFIG_LOCALVERSION=""
 CONFIG_SWAP=y
 CONFIG_SYSVIPC=y
+CONFIG_POSIX_MQUEUE=y
 # 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_ALL=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
+CONFIG_SHMEM=y
+# CONFIG_TINY_SHMEM is not set
 
 #
 # Loadable module support
@@ -84,7 +94,6 @@
 CONFIG_PCI_DOMAINS=y
 CONFIG_ALPHA_CORE_AGP=y
 CONFIG_ALPHA_BROKEN_IRQ_MASK=y
-CONFIG_EARLY_PRINTK=y
 CONFIG_EISA=y
 # CONFIG_SMP is not set
 # CONFIG_DISCONTIGMEM is not set
@@ -108,6 +117,8 @@
 #
 # Generic Driver Options
 #
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
 # CONFIG_DEBUG_DRIVER is not set
 
 #
@@ -130,7 +141,6 @@
 # Protocols
 #
 CONFIG_ISAPNP=y
-# CONFIG_PNPBIOS is not set
 
 #
 # Block devices
@@ -144,7 +154,7 @@
 CONFIG_BLK_DEV_LOOP=m
 # 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 is not set
 
 #
@@ -157,9 +167,9 @@
 #
 # Please see Documentation/ide.txt for help/info on IDE drives
 #
+# CONFIG_BLK_DEV_IDE_SATA 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
@@ -181,7 +191,6 @@
 # CONFIG_BLK_DEV_IDEDMA_FORCED is not set
 CONFIG_IDEDMA_PCI_AUTO=y
 # CONFIG_IDEDMA_ONLYDISK is not set
-CONFIG_BLK_DEV_ADMA=y
 # CONFIG_BLK_DEV_AEC62XX is not set
 CONFIG_BLK_DEV_ALI15X3=y
 # CONFIG_WDC_ALI15X3 is not set
@@ -203,6 +212,7 @@
 # CONFIG_BLK_DEV_SLC90E66 is not set
 # CONFIG_BLK_DEV_TRM290 is not set
 # CONFIG_BLK_DEV_VIA82CXXX is not set
+# CONFIG_IDE_ARM is not set
 # CONFIG_IDE_CHIPSETS is not set
 CONFIG_BLK_DEV_IDEDMA=y
 # CONFIG_IDEDMA_IVB is not set
@@ -229,7 +239,6 @@
 # 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
 
@@ -243,6 +252,7 @@
 # SCSI low-level drivers
 #
 # CONFIG_BLK_DEV_3W_XXXX_RAID is not set
+# CONFIG_SCSI_3W_9XXX is not set
 # CONFIG_SCSI_7000FASST is not set
 # CONFIG_SCSI_ACARD is not set
 # CONFIG_SCSI_AHA1542 is not set
@@ -252,18 +262,16 @@
 CONFIG_AIC7XXX_CMDS_PER_DEVICE=253
 CONFIG_AIC7XXX_RESET_DELAY_MS=5000
 # CONFIG_AIC7XXX_PROBE_EISA_VL is not set
-# CONFIG_AIC7XXX_BUILD_FIRMWARE is not set
 # CONFIG_AIC7XXX_DEBUG_ENABLE is not set
 CONFIG_AIC7XXX_DEBUG_MASK=0
 CONFIG_AIC7XXX_REG_PRETTY_PRINT=y
 # CONFIG_SCSI_AIC7XXX_OLD is not set
 # CONFIG_SCSI_AIC79XX is not set
-# CONFIG_SCSI_ADVANSYS is not set
 # CONFIG_SCSI_IN2000 is not set
-# CONFIG_SCSI_MEGARAID is not set
+# CONFIG_MEGARAID_NEWGEN is not set
+# CONFIG_MEGARAID_LEGACY 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_DTC3280 is not set
 # CONFIG_SCSI_EATA is not set
@@ -276,6 +284,7 @@
 # CONFIG_SCSI_INIA100 is not set
 # CONFIG_SCSI_NCR53C406A is not set
 # CONFIG_SCSI_SYM53C8XX_2 is not set
+# CONFIG_SCSI_IPR is not set
 # CONFIG_SCSI_PAS16 is not set
 # CONFIG_SCSI_PSI240I is not set
 # CONFIG_SCSI_QLOGIC_FAS is not set
@@ -320,6 +329,7 @@
 #
 # I2O device support
 #
+# CONFIG_I2O is not set
 
 #
 # Networking support
@@ -342,19 +352,17 @@
 # CONFIG_NET_IPGRE is not set
 # CONFIG_IP_MROUTE is not set
 # CONFIG_ARPD is not set
-CONFIG_INET_ECN=y
 # CONFIG_SYN_COOKIES is not set
 CONFIG_INET_AH=m
 CONFIG_INET_ESP=m
 # CONFIG_INET_IPCOMP is not set
+# CONFIG_INET_TUNNEL is not set
 
 #
 # IP: Virtual Server Configuration
 #
 # CONFIG_IP_VS is not set
 # CONFIG_IPV6 is not set
-# CONFIG_DECNET is not set
-# CONFIG_BRIDGE is not set
 CONFIG_NETFILTER=y
 # CONFIG_NETFILTER_DEBUG is not set
 
@@ -362,6 +370,8 @@
 # IP: Netfilter Configuration
 #
 CONFIG_IP_NF_CONNTRACK=m
+# CONFIG_IP_NF_CT_ACCT is not set
+# CONFIG_IP_NF_CT_PROTO_SCTP is not set
 CONFIG_IP_NF_FTP=m
 CONFIG_IP_NF_IRC=m
 # CONFIG_IP_NF_TFTP is not set
@@ -386,8 +396,15 @@
 # CONFIG_IP_NF_MATCH_STATE is not set
 # CONFIG_IP_NF_MATCH_CONNTRACK is not set
 # CONFIG_IP_NF_MATCH_OWNER is not set
+# CONFIG_IP_NF_MATCH_ADDRTYPE is not set
+# CONFIG_IP_NF_MATCH_REALM is not set
+# CONFIG_IP_NF_MATCH_SCTP is not set
+# CONFIG_IP_NF_MATCH_COMMENT is not set
 CONFIG_IP_NF_FILTER=m
 # CONFIG_IP_NF_TARGET_REJECT is not set
+# CONFIG_IP_NF_TARGET_LOG is not set
+# CONFIG_IP_NF_TARGET_ULOG is not set
+# CONFIG_IP_NF_TARGET_TCPMSS is not set
 CONFIG_IP_NF_NAT=m
 CONFIG_IP_NF_NAT_NEEDED=y
 CONFIG_IP_NF_TARGET_MASQUERADE=m
@@ -399,9 +416,7 @@
 CONFIG_IP_NF_NAT_IRC=m
 CONFIG_IP_NF_NAT_FTP=m
 # CONFIG_IP_NF_MANGLE is not set
-# CONFIG_IP_NF_TARGET_LOG is not set
-# CONFIG_IP_NF_TARGET_ULOG is not set
-# CONFIG_IP_NF_TARGET_TCPMSS is not set
+# CONFIG_IP_NF_RAW is not set
 # CONFIG_IP_NF_ARPTABLES is not set
 CONFIG_IP_NF_COMPAT_IPCHAINS=y
 CONFIG_XFRM=y
@@ -410,10 +425,11 @@
 #
 # 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=m
+# CONFIG_DECNET is not set
 # CONFIG_LLC2 is not set
 # CONFIG_IPX is not set
 # CONFIG_ATALK is not set
@@ -428,17 +444,18 @@
 # 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
-
-#
-# ARCnet devices
-#
-# CONFIG_ARCNET is not set
 CONFIG_DUMMY=m
 # CONFIG_BONDING is not set
 # CONFIG_EQUALIZER is not set
@@ -447,6 +464,11 @@
 # CONFIG_NET_SB1000 is not set
 
 #
+# ARCnet devices
+#
+# CONFIG_ARCNET is not set
+
+#
 # Ethernet (10 or 100Mbit)
 #
 CONFIG_NET_ETHERNET=y
@@ -506,6 +528,7 @@
 # CONFIG_EPIC100 is not set
 # CONFIG_SUNDANCE is not set
 # CONFIG_VIA_RHINE is not set
+# CONFIG_VIA_VELOCITY is not set
 # CONFIG_NET_POCKET is not set
 
 #
@@ -518,7 +541,6 @@
 # CONFIG_HAMACHI is not set
 CONFIG_YELLOWFIN=y
 # CONFIG_R8169 is not set
-# CONFIG_SIS190 is not set
 # CONFIG_SK98LIN is not set
 # CONFIG_TIGON3 is not set
 
@@ -526,45 +548,29 @@
 # 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
-
-#
-# Wireless LAN (non-hamradio)
-#
-# CONFIG_NET_RADIO is not set
+# CONFIG_S2IO is not set
 
 #
 # Token Ring devices
 #
 # CONFIG_TR is not set
-# CONFIG_NET_FC is not set
-# CONFIG_SHAPER is not set
-# CONFIG_NETCONSOLE is not set
-
-#
-# Wan interfaces
-#
-# CONFIG_WAN is not set
 
 #
-# Amateur Radio support
-#
-# CONFIG_HAMRADIO is not set
-
-#
-# IrDA (infrared) support
+# Wireless LAN (non-hamradio)
 #
-# CONFIG_IRDA is not set
+# CONFIG_NET_RADIO is not set
 
 #
-# Bluetooth support
+# Wan interfaces
 #
-# CONFIG_BT is not set
-# CONFIG_NETPOLL is not set
-# CONFIG_NET_POLL_CONTROLLER is not set
+# CONFIG_WAN 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
@@ -603,6 +609,7 @@
 CONFIG_SERIO_SERPORT=y
 # CONFIG_SERIO_CT82C710 is not set
 # CONFIG_SERIO_PCIPS2 is not set
+# CONFIG_SERIO_RAW is not set
 
 #
 # Input Device Drivers
@@ -648,7 +655,6 @@
 CONFIG_UNIX98_PTYS=y
 CONFIG_LEGACY_PTYS=y
 CONFIG_LEGACY_PTY_COUNT=256
-# CONFIG_QIC02_TAPE is not set
 
 #
 # IPMI
@@ -678,6 +684,11 @@
 # CONFIG_I2C is not set
 
 #
+# Dallas's 1-wire bus
+#
+# CONFIG_W1 is not set
+
+#
 # Misc devices
 #
 
@@ -728,6 +739,7 @@
 CONFIG_REISERFS_FS=m
 # 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 is not set
@@ -750,6 +762,8 @@
 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
 
 #
@@ -757,6 +771,7 @@
 #
 CONFIG_PROC_FS=y
 CONFIG_PROC_KCORE=y
+CONFIG_SYSFS=y
 # CONFIG_DEVFS_FS is not set
 # CONFIG_DEVPTS_FS_XATTR is not set
 CONFIG_TMPFS=y
@@ -796,11 +811,11 @@
 CONFIG_EXPORTFS=m
 CONFIG_SUNRPC=m
 # CONFIG_RPCSEC_GSS_KRB5 is not set
+# CONFIG_RPCSEC_GSS_SPKM3 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
 
 #
@@ -838,6 +853,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
@@ -861,15 +877,16 @@
 #
 # Kernel hacking
 #
-CONFIG_ALPHA_LEGACY_START_ADDRESS=y
 CONFIG_DEBUG_KERNEL=y
-CONFIG_MATHEMU=y
-# CONFIG_DEBUG_SLAB is not set
 CONFIG_MAGIC_SYSRQ=y
+# CONFIG_DEBUG_SLAB is not set
 # CONFIG_DEBUG_SPINLOCK is not set
+CONFIG_DEBUG_INFO=y
+CONFIG_EARLY_PRINTK=y
 # CONFIG_DEBUG_RWLOCK is not set
 # CONFIG_DEBUG_SEMAPHORE is not set
-CONFIG_DEBUG_INFO=y
+CONFIG_ALPHA_LEGACY_START_ADDRESS=y
+CONFIG_MATHEMU=y
 
 #
 # Security options
@@ -887,6 +904,7 @@
 CONFIG_CRYPTO_SHA1=m
 # CONFIG_CRYPTO_SHA256 is not set
 # CONFIG_CRYPTO_SHA512 is not set
+# CONFIG_CRYPTO_WHIRLPOOL is not set
 CONFIG_CRYPTO_DES=m
 # CONFIG_CRYPTO_BLOWFISH is not set
 # CONFIG_CRYPTO_TWOFISH is not set
@@ -894,11 +912,17 @@
 # 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
 # CONFIG_CRYPTO_TEST is not set
 
 #
 # Library routines
 #
+# CONFIG_CRC_CCITT is not set
 CONFIG_CRC32=y
+# CONFIG_LIBCRC32C is not set
diff -Nru a/arch/alpha/kernel/Makefile b/arch/alpha/kernel/Makefile
--- a/arch/alpha/kernel/Makefile	2004-10-18 14:56:29 -07:00
+++ b/arch/alpha/kernel/Makefile	2004-10-18 14:56:29 -07:00
@@ -2,13 +2,13 @@
 # Makefile for the linux kernel.
 #
 
-extra-y		:= head.o vmlinux.lds.s
+extra-y		:= head.o vmlinux.lds
 EXTRA_AFLAGS	:= $(CFLAGS)
 EXTRA_CFLAGS	:= -Werror -Wno-sign-compare
 
 obj-y    := entry.o traps.o process.o init_task.o osf_sys.o irq.o \
 	    irq_alpha.o signal.o setup.o ptrace.o time.o semaphore.o \
-	    alpha_ksyms.o systbls.o err_common.o
+	    alpha_ksyms.o systbls.o err_common.o io.o
 
 obj-$(CONFIG_VGA_HOSE)	+= console.o
 obj-$(CONFIG_SMP)	+= smp.o
diff -Nru a/arch/alpha/kernel/alpha_ksyms.c b/arch/alpha/kernel/alpha_ksyms.c
--- a/arch/alpha/kernel/alpha_ksyms.c	2004-10-18 14:55:54 -07:00
+++ b/arch/alpha/kernel/alpha_ksyms.c	2004-10-18 14:55:54 -07:00
@@ -18,6 +18,7 @@
 #include <linux/tty.h>
 #include <linux/mm.h>
 #include <linux/delay.h>
+#include <linux/dma-mapping.h>
 
 #include <asm/io.h>
 #include <asm/console.h>
@@ -67,36 +68,6 @@
 #endif /* CONFIG_ALPHA_GENERIC */
 
 /* platform dependent support */
-EXPORT_SYMBOL(_inb);
-EXPORT_SYMBOL(_inw);
-EXPORT_SYMBOL(_inl);
-EXPORT_SYMBOL(_outb);
-EXPORT_SYMBOL(_outw);
-EXPORT_SYMBOL(_outl);
-EXPORT_SYMBOL(_readb);
-EXPORT_SYMBOL(_readw);
-EXPORT_SYMBOL(_readl);
-EXPORT_SYMBOL(_writeb);
-EXPORT_SYMBOL(_writew);
-EXPORT_SYMBOL(_writel);
-EXPORT_SYMBOL(___raw_readb); 
-EXPORT_SYMBOL(___raw_readw); 
-EXPORT_SYMBOL(___raw_readl); 
-EXPORT_SYMBOL(___raw_readq); 
-EXPORT_SYMBOL(___raw_writeb); 
-EXPORT_SYMBOL(___raw_writew); 
-EXPORT_SYMBOL(___raw_writel); 
-EXPORT_SYMBOL(___raw_writeq); 
-EXPORT_SYMBOL(_memcpy_fromio);
-EXPORT_SYMBOL(_memcpy_toio);
-EXPORT_SYMBOL(_memset_c_io);
-EXPORT_SYMBOL(scr_memcpyw);
-EXPORT_SYMBOL(insb);
-EXPORT_SYMBOL(insw);
-EXPORT_SYMBOL(insl);
-EXPORT_SYMBOL(outsb);
-EXPORT_SYMBOL(outsw);
-EXPORT_SYMBOL(outsl);
 EXPORT_SYMBOL(strcat);
 EXPORT_SYMBOL(strcmp);
 EXPORT_SYMBOL(strcpy);
@@ -136,7 +107,9 @@
 EXPORT_SYMBOL(pci_dac_page_to_dma);
 EXPORT_SYMBOL(pci_dac_dma_to_page);
 EXPORT_SYMBOL(pci_dac_dma_to_offset);
+EXPORT_SYMBOL(alpha_gendev_to_pci);
 #endif
+EXPORT_SYMBOL(dma_set_mask);
 
 EXPORT_SYMBOL(dump_thread);
 EXPORT_SYMBOL(dump_elf_thread);
@@ -183,8 +156,8 @@
 /*
  * The following are specially called from the uaccess assembly stubs.
  */
-EXPORT_SYMBOL_NOVERS(__copy_user);
-EXPORT_SYMBOL_NOVERS(__do_clear_user);
+EXPORT_SYMBOL(__copy_user);
+EXPORT_SYMBOL(__do_clear_user);
 EXPORT_SYMBOL(__strncpy_from_user);
 EXPORT_SYMBOL(__strnlen_user);
 
@@ -243,17 +216,17 @@
  */
 # undef memcpy
 # undef memset
-EXPORT_SYMBOL_NOVERS(__divl);
-EXPORT_SYMBOL_NOVERS(__divlu);
-EXPORT_SYMBOL_NOVERS(__divq);
-EXPORT_SYMBOL_NOVERS(__divqu);
-EXPORT_SYMBOL_NOVERS(__reml);
-EXPORT_SYMBOL_NOVERS(__remlu);
-EXPORT_SYMBOL_NOVERS(__remq);
-EXPORT_SYMBOL_NOVERS(__remqu);
-EXPORT_SYMBOL_NOVERS(memcpy);
-EXPORT_SYMBOL_NOVERS(memset);
-EXPORT_SYMBOL_NOVERS(memchr);
+EXPORT_SYMBOL(__divl);
+EXPORT_SYMBOL(__divlu);
+EXPORT_SYMBOL(__divq);
+EXPORT_SYMBOL(__divqu);
+EXPORT_SYMBOL(__reml);
+EXPORT_SYMBOL(__remlu);
+EXPORT_SYMBOL(__remq);
+EXPORT_SYMBOL(__remqu);
+EXPORT_SYMBOL(memcpy);
+EXPORT_SYMBOL(memset);
+EXPORT_SYMBOL(memchr);
 
 EXPORT_SYMBOL(get_wchan);
 
diff -Nru a/arch/alpha/kernel/core_cia.c b/arch/alpha/kernel/core_cia.c
--- a/arch/alpha/kernel/core_cia.c	2004-10-18 14:56:33 -07:00
+++ b/arch/alpha/kernel/core_cia.c	2004-10-18 14:56:33 -07:00
@@ -282,7 +282,7 @@
 cia_pci_tbi_try2(struct pci_controller *hose,
 		 dma_addr_t start, dma_addr_t end)
 {
-	unsigned long bus_addr;
+	void __iomem *bus_addr;
 	int ctrl;
 
 	/* Put the chip into PCI loopback mode.  */
@@ -351,7 +351,7 @@
 	struct pci_iommu_arena *arena = pci_isa_hose->sg_isa;
 	int ctrl, addr0, tag0, pte0, data0;
 	int temp, use_tbia_try2 = 0;
-	unsigned long bus_addr;
+	void __iomem *bus_addr;
 
 	/* pyxis -- tbia is broken */
 	if (pci_isa_hose->dense_io_base)
diff -Nru a/arch/alpha/kernel/core_irongate.c b/arch/alpha/kernel/core_irongate.c
--- a/arch/alpha/kernel/core_irongate.c	2004-10-18 14:56:48 -07:00
+++ b/arch/alpha/kernel/core_irongate.c	2004-10-18 14:56:48 -07:00
@@ -310,7 +310,7 @@
 #define GET_GATT_OFF(addr) ((addr & 0x003ff000) >> 12) 
 #define GET_GATT(addr) (gatt_pages[GET_PAGE_DIR_IDX(addr)])
 
-unsigned long
+void __iomem *
 irongate_ioremap(unsigned long addr, unsigned long size)
 {
 	struct vm_struct *area;
@@ -320,7 +320,7 @@
 	unsigned long gart_bus_addr;
 
 	if (!alpha_agpgart_size)
-		return addr + IRONGATE_MEM;
+		return (void __iomem *)(addr + IRONGATE_MEM);
 
 	gart_bus_addr = (unsigned long)IRONGATE0->bar0 &
 			PCI_BASE_ADDRESS_MEM_MASK; 
@@ -339,7 +339,7 @@
 		/*
 		 * Not found - assume legacy ioremap
 		 */
-		return addr + IRONGATE_MEM;
+		return (void __iomem *)(addr + IRONGATE_MEM);
 	} while(0);
 
 	mmio_regs = (u32 *)(((unsigned long)IRONGATE0->bar1 &
@@ -353,7 +353,7 @@
 	if (addr & ~PAGE_MASK) {
 		printk("AGP ioremap failed... addr not page aligned (0x%lx)\n",
 		       addr);
-		return addr + IRONGATE_MEM;
+		return (void __iomem *)(addr + IRONGATE_MEM);
 	}
 	last = addr + size - 1;
 	size = PAGE_ALIGN(last) - addr;
@@ -378,7 +378,7 @@
 	 * Map it
 	 */
 	area = get_vm_area(size, VM_IOREMAP);
-	if (!area) return (unsigned long)NULL;
+	if (!area) return NULL;
 
 	for(baddr = addr, vaddr = (unsigned long)area->addr; 
 	    baddr <= last; 
@@ -391,7 +391,7 @@
 					     pte, PAGE_SIZE, 0)) {
 			printk("AGP ioremap: FAILED to map...\n");
 			vfree(area->addr);
-			return (unsigned long)NULL;
+			return NULL;
 		}
 	}
 
@@ -402,13 +402,15 @@
 	printk("irongate_ioremap(0x%lx, 0x%lx) returning 0x%lx\n",
 	       addr, size, vaddr);
 #endif
-	return vaddr;
+	return (void __iomem *)vaddr;
 }
 
 void
-irongate_iounmap(unsigned long addr)
+irongate_iounmap(volatile void __iomem *xaddr)
 {
+	unsigned long addr = (unsigned long) xaddr;
 	if (((long)addr >> 41) == -2)
 		return;	/* kseg map, nothing to do */
-	if (addr) return vfree((void *)(PAGE_MASK & addr)); 
+	if (addr)
+		return vfree((void *)(PAGE_MASK & addr)); 
 }
diff -Nru a/arch/alpha/kernel/core_marvel.c b/arch/alpha/kernel/core_marvel.c
--- a/arch/alpha/kernel/core_marvel.c	2004-10-18 14:55:54 -07:00
+++ b/arch/alpha/kernel/core_marvel.c	2004-10-18 14:55:54 -07:00
@@ -611,10 +611,83 @@
 }
 
 
+
+/*
+ * RTC Support
+ */
+struct marvel_rtc_access_info {
+	unsigned long function;
+	unsigned long index;
+	unsigned long data;
+};
+
+static void
+__marvel_access_rtc(void *info)
+{
+	struct marvel_rtc_access_info *rtc_access = info;
+
+	register unsigned long __r0 __asm__("$0");
+	register unsigned long __r16 __asm__("$16") = rtc_access->function;
+	register unsigned long __r17 __asm__("$17") = rtc_access->index;
+	register unsigned long __r18 __asm__("$18") = rtc_access->data;
+	
+	__asm__ __volatile__(
+		"call_pal %4 # cserve rtc"
+		: "=r"(__r16), "=r"(__r17), "=r"(__r18), "=r"(__r0)
+		: "i"(PAL_cserve), "0"(__r16), "1"(__r17), "2"(__r18)
+		: "$1", "$22", "$23", "$24", "$25");
+
+	rtc_access->data = __r0;
+}
+
+static u8
+__marvel_rtc_io(u8 b, unsigned long addr, int write)
+{
+	static u8 index = 0;
+
+	struct marvel_rtc_access_info rtc_access;
+	u8 ret = 0;
+
+	switch(addr) {
+	case 0x70:					/* RTC_PORT(0) */
+		if (write) index = b;
+		ret = index;
+		break;
+
+	case 0x71:					/* RTC_PORT(1) */
+		rtc_access.index = index;
+		rtc_access.data = BCD_TO_BIN(b);
+		rtc_access.function = 0x48 + !write;	/* GET/PUT_TOY */
+
+#ifdef CONFIG_SMP
+		if (smp_processor_id() != boot_cpuid)
+			smp_call_function_on_cpu(__marvel_access_rtc,
+						 &rtc_access, 1, 1,
+						 cpumask_of_cpu(boot_cpuid));
+		else
+			__marvel_access_rtc(&rtc_access);
+#else
+		__marvel_access_rtc(&rtc_access);
+#endif
+		ret = BIN_TO_BCD(rtc_access.data);
+		break;
+
+	default:
+		printk(KERN_WARNING "Illegal RTC port %lx\n", addr);
+		break;
+	}
+
+	return ret;
+}
+
+
 /*
  * IO map support.
  */
-unsigned long
+
+#define __marvel_is_mem_vga(a)	(((a) >= 0xa0000) && ((a) <= 0xc0000))
+
+void __iomem *
 marvel_ioremap(unsigned long addr, unsigned long size)
 {
 	struct pci_controller *hose;
@@ -633,8 +706,6 @@
 	}
 #endif
 
-	if (!marvel_is_ioaddr(addr)) return 0UL;
-
 	/*
 	 * Find the hose.
 	 */
@@ -643,7 +714,7 @@
 			break; 
 	}
 	if (!hose)
-		return 0UL;
+		return NULL;
 
 	/*
 	 * We have the hose - calculate the bus limits.
@@ -655,15 +726,17 @@
 	 * Is it direct-mapped?
 	 */
 	if ((baddr >= __direct_map_base) && 
-	    ((baddr + size - 1) < __direct_map_base + __direct_map_size)) 
-		return IDENT_ADDR | (baddr - __direct_map_base);
+	    ((baddr + size - 1) < __direct_map_base + __direct_map_size)) {
+		addr = IDENT_ADDR | (baddr - __direct_map_base);
+		return (void __iomem *) addr;
+	}
 
 	/* 
 	 * Check the scatter-gather arena.
 	 */
 	if (hose->sg_pci &&
 	    baddr >= (unsigned long)hose->sg_pci->dma_base &&
-	    last < (unsigned long)hose->sg_pci->dma_base + hose->sg_pci->size){
+	    last < (unsigned long)hose->sg_pci->dma_base + hose->sg_pci->size) {
 
 		/*
 		 * Adjust the limits (mappings must be page aligned)
@@ -677,7 +750,9 @@
 		 * Map it.
 		 */
 		area = get_vm_area(size, VM_IOREMAP);
-		if (!area) return (unsigned long)NULL;
+		if (!area)
+			return NULL;
+
 		ptes = hose->sg_pci->ptes;
 		for (vaddr = (unsigned long)area->addr; 
 		    baddr <= last; 
@@ -686,7 +761,7 @@
 			if (!(pfn & 1)) {
 				printk("ioremap failed... pte not valid...\n");
 				vfree(area->addr);
-				return 0UL;
+				return NULL;
 			}
 			pfn >>= 1;	/* make it a true pfn */
 			
@@ -695,7 +770,7 @@
 						     PAGE_SIZE, 0)) {
 				printk("FAILED to map...\n");
 				vfree(area->addr);
-				return 0UL;
+				return NULL;
 			}
 		}
 
@@ -703,101 +778,81 @@
 
 		vaddr = (unsigned long)area->addr + (addr & ~PAGE_MASK);
 
-		return vaddr;
+		return (void __iomem *) vaddr;
 	}
 
-	/*
-	 * Not found - assume legacy ioremap.
-	 */
-	return addr;
+	return NULL;
 }
 
 void
-marvel_iounmap(unsigned long addr)
+marvel_iounmap(volatile void __iomem *xaddr)
 {
-	if (((long)addr >> 41) == -2)
-		return;	/* kseg map, nothing to do */
-	if (addr)
+	unsigned long addr = (unsigned long) xaddr;
+	if (addr >= VMALLOC_START)
 		vfree((void *)(PAGE_MASK & addr)); 
 }
 
-#ifndef CONFIG_ALPHA_GENERIC
-EXPORT_SYMBOL(marvel_ioremap);
-EXPORT_SYMBOL(marvel_iounmap);
-#endif
-
-
-/*
- * RTC Support
- */
-struct marvel_rtc_access_info {
-	unsigned long function;
-	unsigned long index;
-	unsigned long data;
-};
-
-static void
-__marvel_access_rtc(void *info)
+int
+marvel_is_mmio(const volatile void __iomem *xaddr)
 {
-	struct marvel_rtc_access_info *rtc_access = info;
+	unsigned long addr = (unsigned long) xaddr;
 
-	register unsigned long __r0 __asm__("$0");
-	register unsigned long __r16 __asm__("$16") = rtc_access->function;
-	register unsigned long __r17 __asm__("$17") = rtc_access->index;
-	register unsigned long __r18 __asm__("$18") = rtc_access->data;
-	
-	__asm__ __volatile__(
-		"call_pal %4 # cserve rtc"
-		: "=r"(__r16), "=r"(__r17), "=r"(__r18), "=r"(__r0)
-		: "i"(PAL_cserve), "0"(__r16), "1"(__r17), "2"(__r18)
-		: "$1", "$22", "$23", "$24", "$25");
-
-	rtc_access->data = __r0;
+	if (addr >= VMALLOC_START)
+		return 1;
+	else
+		return (addr & 0xFF000000UL) == 0;
 }
 
-u8
-__marvel_rtc_io(int write, u8 b, unsigned long addr)
-{
-	struct marvel_rtc_access_info rtc_access = {0, };
-	static u8 index = 0;
-	u8 ret = 0;
+#define __marvel_is_port_vga(a)	\
+  (((a) >= 0x3b0) && ((a) < 0x3e0) && ((a) != 0x3b3) && ((a) != 0x3d3))
+#define __marvel_is_port_kbd(a)	(((a) == 0x60) || ((a) == 0x64))
+#define __marvel_is_port_rtc(a)	(((a) == 0x70) || ((a) == 0x71))
 
-	switch(addr) {
-	case 0x70:					/* RTC_PORT(0) */
-		if (write) index = b;
-		ret = index;
-		break;
-
-	case 0x71:					/* RTC_PORT(1) */
-		rtc_access.index = index;
-		rtc_access.data = BCD_TO_BIN(b);
-		rtc_access.function = 0x49;		/* GET_TOY */
-		if (write) rtc_access.function = 0x48;	/* PUT_TOY */
-
-#ifdef CONFIG_SMP
-		if (smp_processor_id() != boot_cpuid)
-			smp_call_function_on_cpu(__marvel_access_rtc,
-						 &rtc_access,
-						 1,	/* retry */
-						 1,	/* wait  */
-						 1UL << boot_cpuid);
-		else
-			__marvel_access_rtc(&rtc_access);
-#else
-		__marvel_access_rtc(&rtc_access);
+void __iomem *marvel_ioportmap (unsigned long addr)
+{
+	if (__marvel_is_port_rtc (addr) || __marvel_is_port_kbd(addr))
+		;
+#ifdef CONFIG_VGA_HOSE
+	else if (__marvel_is_port_vga (addr) && pci_vga_hose)
+		addr += pci_vga_hose->io_space->start;
 #endif
-		ret = BIN_TO_BCD(rtc_access.data);
-		
-		break;
+	else
+		return NULL;
+	return (void __iomem *)addr;
+}
 
-	default:
-		printk(KERN_WARNING "Illegal RTC port %lx\n", addr);
-		break;
-	}
+unsigned int
+marvel_ioread8(void __iomem *xaddr)
+{
+	unsigned long addr = (unsigned long) xaddr;
+	if (__marvel_is_port_kbd(addr))
+		return 0;
+	else if (__marvel_is_port_rtc(addr))
+		return __marvel_rtc_io(0, addr, 0);
+	else
+		return __kernel_ldbu(*(vucp)addr);
+}
 
-	return ret;
+void
+marvel_iowrite8(u8 b, void __iomem *xaddr)
+{
+	unsigned long addr = (unsigned long) xaddr;
+	if (__marvel_is_port_kbd(addr))
+		return;
+	else if (__marvel_is_port_rtc(addr)) 
+		__marvel_rtc_io(b, addr, 1);
+	else
+		__kernel_stb(b, *(vucp)addr);
 }
 
+#ifndef CONFIG_ALPHA_GENERIC
+EXPORT_SYMBOL(marvel_ioremap);
+EXPORT_SYMBOL(marvel_iounmap);
+EXPORT_SYMBOL(marvel_is_mmio);
+EXPORT_SYMBOL(marvel_ioportmap);
+EXPORT_SYMBOL(marvel_ioread8);
+EXPORT_SYMBOL(marvel_iowrite8);
+#endif
 
 /*
  * NUMA Support
diff -Nru a/arch/alpha/kernel/core_titan.c b/arch/alpha/kernel/core_titan.c
--- a/arch/alpha/kernel/core_titan.c	2004-10-18 14:56:27 -07:00
+++ b/arch/alpha/kernel/core_titan.c	2004-10-18 14:56:27 -07:00
@@ -461,7 +461,8 @@
 /*
  * IO map support.
  */
-unsigned long
+
+void __iomem *
 titan_ioremap(unsigned long addr, unsigned long size)
 {
 	int h = (addr & TITAN_HOSE_MASK) >> TITAN_HOSE_SHIFT;
@@ -487,15 +488,19 @@
 	 * Find the hose.
 	 */
 	for (hose = hose_head; hose; hose = hose->next)
-		if (hose->index == h) break;
-	if (!hose) return (unsigned long)NULL;
+		if (hose->index == h)
+			break;
+	if (!hose)
+		return NULL;
 
 	/*
 	 * Is it direct-mapped?
 	 */
 	if ((baddr >= __direct_map_base) && 
-	    ((baddr + size - 1) < __direct_map_base + __direct_map_size)) 
-		return addr - __direct_map_base + TITAN_MEM_BIAS;
+	    ((baddr + size - 1) < __direct_map_base + __direct_map_size)) {
+		vaddr = addr - __direct_map_base + TITAN_MEM_BIAS;
+		return (void __iomem *) vaddr;
+	}
 
 	/* 
 	 * Check the scatter-gather arena.
@@ -516,7 +521,9 @@
 		 * Map it
 		 */
 		area = get_vm_area(size, VM_IOREMAP);
-		if (!area) return (unsigned long)NULL;
+		if (!area)
+			return NULL;
+
 		ptes = hose->sg_pci->ptes;
 		for (vaddr = (unsigned long)area->addr; 
 		    baddr <= last; 
@@ -525,7 +532,7 @@
 			if (!(pfn & 1)) {
 				printk("ioremap failed... pte not valid...\n");
 				vfree(area->addr);
-				return (unsigned long)NULL;
+				return NULL;
 			}
 			pfn >>= 1;	/* make it a true pfn */
 			
@@ -534,35 +541,42 @@
 						     PAGE_SIZE, 0)) {
 				printk("FAILED to map...\n");
 				vfree(area->addr);
-				return (unsigned long)NULL;
+				return NULL;
 			}
 		}
 
 		flush_tlb_all();
 
 		vaddr = (unsigned long)area->addr + (addr & ~PAGE_MASK);
-		return vaddr;
+		return (void __iomem *) vaddr;
 	}
 
-	/*
-	 * Not found - assume legacy ioremap.
-	 */
-	return addr + TITAN_MEM_BIAS;
-
+	return NULL;
 }
 
 void
-titan_iounmap(unsigned long addr)
+titan_iounmap(volatile void __iomem *xaddr)
 {
-	if (((long)addr >> 41) == -2)
-		return;	/* kseg map, nothing to do */
-	if (addr)
+	unsigned long addr = (unsigned long) xaddr;
+	if (addr >= VMALLOC_START)
 		vfree((void *)(PAGE_MASK & addr)); 
 }
 
+int
+titan_is_mmio(const volatile void __iomem *xaddr)
+{
+	unsigned long addr = (unsigned long) xaddr;
+
+	if (addr >= VMALLOC_START)
+		return 1;
+	else
+		return (addr & 0x100000000UL) == 0;
+}
+
 #ifndef CONFIG_ALPHA_GENERIC
 EXPORT_SYMBOL(titan_ioremap);
 EXPORT_SYMBOL(titan_iounmap);
+EXPORT_SYMBOL(titan_is_mmio);
 #endif
 
 /*
diff -Nru a/arch/alpha/kernel/err_titan.c b/arch/alpha/kernel/err_titan.c
--- a/arch/alpha/kernel/err_titan.c	2004-10-18 14:57:03 -07:00
+++ b/arch/alpha/kernel/err_titan.c	2004-10-18 14:57:03 -07:00
@@ -177,7 +177,7 @@
 #define TITAN__PCHIP_PERROR__CMD__S	(52)
 #define TITAN__PCHIP_PERROR__CMD__M	(0x0f)
 #define TITAN__PCHIP_PERROR__ADDR__S	(14)
-#define TITAN__PCHIP_PERROR__ADDR__M	(0x1ffffffff)
+#define TITAN__PCHIP_PERROR__ADDR__M	(0x1fffffffful)
 
 	if (!(perror & TITAN__PCHIP_PERROR__ERRMASK))
 		return MCHK_DISPOSITION_UNKNOWN_ERROR;
diff -Nru a/arch/alpha/kernel/io.c b/arch/alpha/kernel/io.c
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/arch/alpha/kernel/io.c	2004-10-18 14:56:49 -07:00
@@ -0,0 +1,630 @@
+/*
+ * Alpha IO and memory functions.
+ */
+
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/string.h>
+#include <linux/module.h>
+#include <asm/io.h>
+
+/* Out-of-line versions of the i/o routines that redirect into the 
+   platform-specific version.  Note that "platform-specific" may mean
+   "generic", which bumps through the machine vector.  */
+
+unsigned int
+ioread8(void __iomem *addr)
+{
+	unsigned int ret = IO_CONCAT(__IO_PREFIX,ioread8)(addr);
+	mb();
+	return ret;
+}
+
+unsigned int ioread16(void __iomem *addr)
+{
+	unsigned int ret = IO_CONCAT(__IO_PREFIX,ioread16)(addr);
+	mb();
+	return ret;
+}
+
+unsigned int ioread32(void __iomem *addr)
+{
+	unsigned int ret = IO_CONCAT(__IO_PREFIX,ioread32)(addr);
+	mb();
+	return ret;
+}
+
+void iowrite8(u8 b, void __iomem *addr)
+{
+	IO_CONCAT(__IO_PREFIX,iowrite8)(b, addr);
+	mb();
+}
+
+void iowrite16(u16 b, void __iomem *addr)
+{
+	IO_CONCAT(__IO_PREFIX,iowrite16)(b, addr);
+	mb();
+}
+
+void iowrite32(u32 b, void __iomem *addr)
+{
+	IO_CONCAT(__IO_PREFIX,iowrite32)(b, addr);
+	mb();
+}
+
+EXPORT_SYMBOL(ioread8);
+EXPORT_SYMBOL(ioread16);
+EXPORT_SYMBOL(ioread32);
+EXPORT_SYMBOL(iowrite8);
+EXPORT_SYMBOL(iowrite16);
+EXPORT_SYMBOL(iowrite32);
+
+u8 inb(unsigned long port)
+{
+	return ioread8(ioport_map(port, 1));
+}
+
+u16 inw(unsigned long port)
+{
+	return ioread16(ioport_map(port, 2));
+}
+
+u32 inl(unsigned long port)
+{
+	return ioread32(ioport_map(port, 4));
+}
+
+void outb(u8 b, unsigned long port)
+{
+	iowrite8(b, ioport_map(port, 1));
+}
+
+void outw(u16 b, unsigned long port)
+{
+	iowrite16(b, ioport_map(port, 2));
+}
+
+void outl(u32 b, unsigned long port)
+{
+	iowrite32(b, ioport_map(port, 4));
+}
+
+EXPORT_SYMBOL(inb);
+EXPORT_SYMBOL(inw);
+EXPORT_SYMBOL(inl);
+EXPORT_SYMBOL(outb);
+EXPORT_SYMBOL(outw);
+EXPORT_SYMBOL(outl);
+
+u8 __raw_readb(const volatile void __iomem *addr)
+{
+	return IO_CONCAT(__IO_PREFIX,readb)(addr);
+}
+
+u16 __raw_readw(const volatile void __iomem *addr)
+{
+	return IO_CONCAT(__IO_PREFIX,readw)(addr);
+}
+
+u32 __raw_readl(const volatile void __iomem *addr)
+{
+	return IO_CONCAT(__IO_PREFIX,readl)(addr);
+}
+
+u64 __raw_readq(const volatile void __iomem *addr)
+{
+	return IO_CONCAT(__IO_PREFIX,readq)(addr);
+}
+
+void __raw_writeb(u8 b, volatile void __iomem *addr)
+{
+	IO_CONCAT(__IO_PREFIX,writeb)(b, addr);
+}
+
+void __raw_writew(u16 b, volatile void __iomem *addr)
+{
+	IO_CONCAT(__IO_PREFIX,writew)(b, addr);
+}
+
+void __raw_writel(u32 b, volatile void __iomem *addr)
+{
+	IO_CONCAT(__IO_PREFIX,writel)(b, addr);
+}
+
+void __raw_writeq(u64 b, volatile void __iomem *addr)
+{
+	IO_CONCAT(__IO_PREFIX,writeq)(b, addr);
+}
+
+EXPORT_SYMBOL(__raw_readb); 
+EXPORT_SYMBOL(__raw_readw); 
+EXPORT_SYMBOL(__raw_readl); 
+EXPORT_SYMBOL(__raw_readq); 
+EXPORT_SYMBOL(__raw_writeb); 
+EXPORT_SYMBOL(__raw_writew); 
+EXPORT_SYMBOL(__raw_writel); 
+EXPORT_SYMBOL(__raw_writeq); 
+
+u8 readb(const volatile void __iomem *addr)
+{
+	u8 ret = __raw_readb(addr);
+	mb();
+	return ret;
+}
+
+u16 readw(const volatile void __iomem *addr)
+{
+	u16 ret = __raw_readw(addr);
+	mb();
+	return ret;
+}
+
+u32 readl(const volatile void __iomem *addr)
+{
+	u32 ret = __raw_readl(addr);
+	mb();
+	return ret;
+}
+
+u64 readq(const volatile void __iomem *addr)
+{
+	u64 ret = __raw_readq(addr);
+	mb();
+	return ret;
+}
+
+void writeb(u8 b, volatile void __iomem *addr)
+{
+	__raw_writeb(b, addr);
+	mb();
+}
+
+void writew(u16 b, volatile void __iomem *addr)
+{
+	__raw_writew(b, addr);
+	mb();
+}
+
+void writel(u32 b, volatile void __iomem *addr)
+{
+	__raw_writel(b, addr);
+	mb();
+}
+
+void writeq(u64 b, volatile void __iomem *addr)
+{
+	__raw_writeq(b, addr);
+	mb();
+}
+
+EXPORT_SYMBOL(readb);
+EXPORT_SYMBOL(readw);
+EXPORT_SYMBOL(readl);
+EXPORT_SYMBOL(readq);
+EXPORT_SYMBOL(writeb);
+EXPORT_SYMBOL(writew);
+EXPORT_SYMBOL(writel);
+EXPORT_SYMBOL(writeq);
+
+
+/*
+ * Read COUNT 8-bit bytes from port PORT into memory starting at SRC.
+ */
+void ioread8_rep(void __iomem *port, void *dst, unsigned long count)
+{
+	while ((unsigned long)dst & 0x3) {
+		if (!count)
+			return;
+		count--;
+		*(unsigned char *)dst = ioread8(port);
+		dst += 1;
+	}
+
+	while (count >= 4) {
+		unsigned int w;
+		count -= 4;
+		w = ioread8(port);
+		w |= ioread8(port) << 8;
+		w |= ioread8(port) << 16;
+		w |= ioread8(port) << 24;
+		*(unsigned int *)dst = w;
+		dst += 4;
+	}
+
+	while (count) {
+		--count;
+		*(unsigned char *)dst = ioread8(port);
+		dst += 1;
+	}
+}
+
+void insb(unsigned long port, void *dst, unsigned long count)
+{
+	ioread8_rep(ioport_map(port, 1), dst, count);
+}
+
+EXPORT_SYMBOL(ioread8_rep);
+EXPORT_SYMBOL(insb);
+
+/*
+ * Read COUNT 16-bit words from port PORT into memory starting at
+ * SRC.  SRC must be at least short aligned.  This is used by the
+ * IDE driver to read disk sectors.  Performance is important, but
+ * the interfaces seems to be slow: just using the inlined version
+ * of the inw() breaks things.
+ */
+void ioread16_rep(void __iomem *port, void *dst, unsigned long count)
+{
+	if (unlikely((unsigned long)dst & 0x3)) {
+		if (!count)
+			return;
+		BUG_ON((unsigned long)dst & 0x1);
+		count--;
+		*(unsigned short *)dst = ioread16(port);
+		dst += 2;
+	}
+
+	while (count >= 2) {
+		unsigned int w;
+		count -= 2;
+		w = ioread16(port);
+		w |= ioread16(port) << 16;
+		*(unsigned int *)dst = w;
+		dst += 4;
+	}
+
+	if (count) {
+		*(unsigned short*)dst = ioread16(port);
+	}
+}
+
+void insw(unsigned long port, void *dst, unsigned long count)
+{
+	ioread16_rep(ioport_map(port, 2), dst, count);
+}
+
+EXPORT_SYMBOL(ioread16_rep);
+EXPORT_SYMBOL(insw);
+
+
+/*
+ * Read COUNT 32-bit words from port PORT into memory starting at
+ * SRC. Now works with any alignment in SRC. Performance is important,
+ * but the interfaces seems to be slow: just using the inlined version
+ * of the inl() breaks things.
+ */
+void ioread32_rep(void __iomem *port, void *dst, unsigned long count)
+{
+	if (unlikely((unsigned long)dst & 0x3)) {
+		while (count--) {
+			struct S { int x __attribute__((packed)); };
+			((struct S *)dst)->x = ioread32(port);
+			dst += 4;
+		}
+	} else {
+		/* Buffer 32-bit aligned.  */
+		while (count--) {
+			*(unsigned int *)dst = ioread32(port);
+			dst += 4;
+		}
+	}
+}
+
+void insl(unsigned long port, void *dst, unsigned long count)
+{
+	ioread32_rep(ioport_map(port, 4), dst, count);
+}
+
+EXPORT_SYMBOL(ioread32_rep);
+EXPORT_SYMBOL(insl);
+
+
+/*
+ * Like insb but in the opposite direction.
+ * Don't worry as much about doing aligned memory transfers:
+ * doing byte reads the "slow" way isn't nearly as slow as
+ * doing byte writes the slow way (no r-m-w cycle).
+ */
+void iowrite8_rep(void __iomem *port, const void *xsrc, unsigned long count)
+{
+	const unsigned char *src = xsrc;
+	while (count--)
+		iowrite8(*src++, port);
+}
+
+void outsb(unsigned long port, const void *src, unsigned long count)
+{
+	iowrite8_rep(ioport_map(port, 1), src, count);
+}
+
+EXPORT_SYMBOL(iowrite8_rep);
+EXPORT_SYMBOL(outsb);
+
+
+/*
+ * Like insw but in the opposite direction.  This is used by the IDE
+ * driver to write disk sectors.  Performance is important, but the
+ * interfaces seems to be slow: just using the inlined version of the
+ * outw() breaks things.
+ */
+void iowrite16_rep(void __iomem *port, const void *src, unsigned long count)
+{
+	if (unlikely((unsigned long)src & 0x3)) {
+		if (!count)
+			return;
+		BUG_ON((unsigned long)src & 0x1);
+		iowrite16(*(unsigned short *)src, port);
+		src += 2;
+		--count;
+	}
+
+	while (count >= 2) {
+		unsigned int w;
+		count -= 2;
+		w = *(unsigned int *)src;
+		src += 4;
+		iowrite16(w >>  0, port);
+		iowrite16(w >> 16, port);
+	}
+
+	if (count) {
+		iowrite16(*(unsigned short *)src, port);
+	}
+}
+
+void outsw(unsigned long port, const void *src, unsigned long count)
+{
+	iowrite16_rep(ioport_map(port, 2), src, count);
+}
+
+EXPORT_SYMBOL(iowrite16_rep);
+EXPORT_SYMBOL(outsw);
+
+
+/*
+ * Like insl but in the opposite direction.  This is used by the IDE
+ * driver to write disk sectors.  Works with any alignment in SRC.
+ * Performance is important, but the interfaces seems to be slow:
+ * just using the inlined version of the outl() breaks things.
+ */
+void iowrite32_rep(void __iomem *port, const void *src, unsigned long count)
+{
+	if (unlikely((unsigned long)src & 0x3)) {
+		while (count--) {
+			struct S { int x __attribute__((packed)); };
+			iowrite32(((struct S *)src)->x, port);
+			src += 4;
+		}
+	} else {
+		/* Buffer 32-bit aligned.  */
+		while (count--) {
+			iowrite32(*(unsigned int *)src, port);
+			src += 4;
+		}
+	}
+}
+
+void outsl(unsigned long port, const void *src, unsigned long count)
+{
+	iowrite32_rep(ioport_map(port, 4), src, count);
+}
+
+EXPORT_SYMBOL(iowrite32_rep);
+EXPORT_SYMBOL(outsl);
+
+
+/*
+ * Copy data from IO memory space to "real" memory space.
+ * This needs to be optimized.
+ */
+void memcpy_fromio(void *to, const volatile void __iomem *from, long count)
+{
+	/* Optimize co-aligned transfers.  Everything else gets handled
+	   a byte at a time. */
+
+	if (count >= 8 && ((u64)to & 7) == ((u64)from & 7)) {
+		count -= 8;
+		do {
+			*(u64 *)to = __raw_readq(from);
+			count -= 8;
+			to += 8;
+			from += 8;
+		} while (count >= 0);
+		count += 8;
+	}
+
+	if (count >= 4 && ((u64)to & 3) == ((u64)from & 3)) {
+		count -= 4;
+		do {
+			*(u32 *)to = __raw_readl(from);
+			count -= 4;
+			to += 4;
+			from += 4;
+		} while (count >= 0);
+		count += 4;
+	}
+
+	if (count >= 2 && ((u64)to & 1) == ((u64)from & 1)) {
+		count -= 2;
+		do {
+			*(u16 *)to = __raw_readw(from);
+			count -= 2;
+			to += 2;
+			from += 2;
+		} while (count >= 0);
+		count += 2;
+	}
+
+	while (count > 0) {
+		*(u8 *) to = __raw_readb(from);
+		count--;
+		to++;
+		from++;
+	}
+	mb();
+}
+
+EXPORT_SYMBOL(memcpy_fromio);
+
+
+/*
+ * Copy data from "real" memory space to IO memory space.
+ * This needs to be optimized.
+ */
+void memcpy_toio(volatile void __iomem *to, const void *from, long count)
+{
+	/* Optimize co-aligned transfers.  Everything else gets handled
+	   a byte at a time. */
+	/* FIXME -- align FROM.  */
+
+	if (count >= 8 && ((u64)to & 7) == ((u64)from & 7)) {
+		count -= 8;
+		do {
+			__raw_writeq(*(const u64 *)from, to);
+			count -= 8;
+			to += 8;
+			from += 8;
+		} while (count >= 0);
+		count += 8;
+	}
+
+	if (count >= 4 && ((u64)to & 3) == ((u64)from & 3)) {
+		count -= 4;
+		do {
+			__raw_writel(*(const u32 *)from, to);
+			count -= 4;
+			to += 4;
+			from += 4;
+		} while (count >= 0);
+		count += 4;
+	}
+
+	if (count >= 2 && ((u64)to & 1) == ((u64)from & 1)) {
+		count -= 2;
+		do {
+			__raw_writew(*(const u16 *)from, to);
+			count -= 2;
+			to += 2;
+			from += 2;
+		} while (count >= 0);
+		count += 2;
+	}
+
+	while (count > 0) {
+		__raw_writeb(*(const u8 *) from, to);
+		count--;
+		to++;
+		from++;
+	}
+	mb();
+}
+
+EXPORT_SYMBOL(memcpy_toio);
+
+
+/*
+ * "memset" on IO memory space.
+ */
+void _memset_c_io(volatile void __iomem *to, unsigned long c, long count)
+{
+	/* Handle any initial odd byte */
+	if (count > 0 && ((u64)to & 1)) {
+		__raw_writeb(c, to);
+		to++;
+		count--;
+	}
+
+	/* Handle any initial odd halfword */
+	if (count >= 2 && ((u64)to & 2)) {
+		__raw_writew(c, to);
+		to += 2;
+		count -= 2;
+	}
+
+	/* Handle any initial odd word */
+	if (count >= 4 && ((u64)to & 4)) {
+		__raw_writel(c, to);
+		to += 4;
+		count -= 4;
+	}
+
+	/* Handle all full-sized quadwords: we're aligned
+	   (or have a small count) */
+	count -= 8;
+	if (count >= 0) {
+		do {
+			__raw_writeq(c, to);
+			to += 8;
+			count -= 8;
+		} while (count >= 0);
+	}
+	count += 8;
+
+	/* The tail is word-aligned if we still have count >= 4 */
+	if (count >= 4) {
+		__raw_writel(c, to);
+		to += 4;
+		count -= 4;
+	}
+
+	/* The tail is half-word aligned if we have count >= 2 */
+	if (count >= 2) {
+		__raw_writew(c, to);
+		to += 2;
+		count -= 2;
+	}
+
+	/* And finally, one last byte.. */
+	if (count) {
+		__raw_writeb(c, to);
+	}
+	mb();
+}
+
+EXPORT_SYMBOL(_memset_c_io);
+
+/* A version of memcpy used by the vga console routines to move data around
+   arbitrarily between screen and main memory.  */
+
+void
+scr_memcpyw(u16 *d, const u16 *s, unsigned int count)
+{
+	const u16 __iomem *ios = (const u16 __iomem *) s;
+	u16 __iomem *iod = (u16 __iomem *) d;
+	int s_isio = __is_ioaddr(s);
+	int d_isio = __is_ioaddr(d);
+
+	if (s_isio) {
+		if (d_isio) {
+			/* FIXME: Should handle unaligned ops and
+			   operation widening.  */
+
+			count /= 2;
+			while (count--) {
+				u16 tmp = __raw_readw(ios++);
+				__raw_writew(tmp, iod++);
+			}
+		}
+		else
+			memcpy_fromio(d, ios, count);
+	} else {
+		if (d_isio)
+			memcpy_toio(iod, s, count);
+		else
+			memcpy(d, s, count);
+	}
+}
+
+EXPORT_SYMBOL(scr_memcpyw);
+
+void __iomem *ioport_map(unsigned long port, unsigned int size)
+{
+	return IO_CONCAT(__IO_PREFIX,ioportmap) (port);
+}
+
+void ioport_unmap(void __iomem *addr)
+{
+}
+
+EXPORT_SYMBOL(ioport_map);
+EXPORT_SYMBOL(ioport_unmap);
diff -Nru a/arch/alpha/kernel/irq.c b/arch/alpha/kernel/irq.c
--- a/arch/alpha/kernel/irq.c	2004-10-18 14:56:49 -07:00
+++ b/arch/alpha/kernel/irq.c	2004-10-18 14:56:49 -07:00
@@ -25,6 +25,7 @@
 #include <linux/irq.h>
 #include <linux/proc_fs.h>
 #include <linux/seq_file.h>
+#include <linux/profile.h>
 
 #include <asm/system.h>
 #include <asm/io.h>
@@ -83,6 +84,7 @@
 		 struct irqaction *action)
 {
 	int status = 1;	/* Force the "do bottom halves" bit */
+	int ret;
 
 	do {
 		if (!(action->flags & SA_INTERRUPT))
@@ -90,8 +92,9 @@
 		else
 			local_irq_disable();
 
-		status |= action->flags;
-		action->handler(irq, action->dev_id, regs);
+		ret = action->handler(irq, action->dev_id, regs);
+		if (ret == IRQ_HANDLED)
+			status |= action->flags;
 		action = action->next;
 	} while (action);
 	if (status & SA_SAMPLE_RANDOM)
@@ -288,31 +291,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,14 +328,9 @@
 #endif
 }
 
-unsigned long prof_cpu_mask = ~0UL;
-
 void
 init_irq_proc (void)
 {
-#ifdef CONFIG_SMP
-	struct proc_dir_entry *entry;
-#endif
 	int i;
 
 	/* create /proc/irq */
@@ -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	2004-10-18 14:57:05 -07:00
+++ b/arch/alpha/kernel/irq_impl.h	2004-10-18 14:57:05 -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/machvec_impl.h b/arch/alpha/kernel/machvec_impl.h
--- a/arch/alpha/kernel/machvec_impl.h	2004-10-18 14:57:20 -07:00
+++ b/arch/alpha/kernel/machvec_impl.h	2004-10-18 14:57:20 -07:00
@@ -44,56 +44,60 @@
 #define DO_DEFAULT_RTC rtc_port: 0x70
 
 #define DO_EV4_MMU							\
-	max_asn:			EV4_MAX_ASN,			\
-	mv_switch_mm:			ev4_switch_mm,			\
-	mv_activate_mm:			ev4_activate_mm,		\
-	mv_flush_tlb_current:		ev4_flush_tlb_current,		\
-	mv_flush_tlb_current_page:	ev4_flush_tlb_current_page
+	.max_asn =			EV4_MAX_ASN,			\
+	.mv_switch_mm =			ev4_switch_mm,			\
+	.mv_activate_mm =		ev4_activate_mm,		\
+	.mv_flush_tlb_current =		ev4_flush_tlb_current,		\
+	.mv_flush_tlb_current_page =	ev4_flush_tlb_current_page
 
 #define DO_EV5_MMU							\
-	max_asn:			EV5_MAX_ASN,			\
-	mv_switch_mm:			ev5_switch_mm,			\
-	mv_activate_mm:			ev5_activate_mm,		\
-	mv_flush_tlb_current:		ev5_flush_tlb_current,		\
-	mv_flush_tlb_current_page:	ev5_flush_tlb_current_page
+	.max_asn =			EV5_MAX_ASN,			\
+	.mv_switch_mm =			ev5_switch_mm,			\
+	.mv_activate_mm =		ev5_activate_mm,		\
+	.mv_flush_tlb_current =		ev5_flush_tlb_current,		\
+	.mv_flush_tlb_current_page =	ev5_flush_tlb_current_page
 
 #define DO_EV6_MMU							\
-	max_asn:			EV6_MAX_ASN,			\
-	mv_switch_mm:			ev5_switch_mm,			\
-	mv_activate_mm:			ev5_activate_mm,		\
-	mv_flush_tlb_current:		ev5_flush_tlb_current,		\
-	mv_flush_tlb_current_page:	ev5_flush_tlb_current_page
+	.max_asn =			EV6_MAX_ASN,			\
+	.mv_switch_mm =			ev5_switch_mm,			\
+	.mv_activate_mm =		ev5_activate_mm,		\
+	.mv_flush_tlb_current =		ev5_flush_tlb_current,		\
+	.mv_flush_tlb_current_page =	ev5_flush_tlb_current_page
 
 #define DO_EV7_MMU							\
-	max_asn:			EV6_MAX_ASN,			\
-	mv_switch_mm:			ev5_switch_mm,			\
-	mv_activate_mm:			ev5_activate_mm,		\
-	mv_flush_tlb_current:		ev5_flush_tlb_current,		\
-	mv_flush_tlb_current_page:	ev5_flush_tlb_current_page
+	.max_asn =			EV6_MAX_ASN,			\
+	.mv_switch_mm =			ev5_switch_mm,			\
+	.mv_activate_mm =		ev5_activate_mm,		\
+	.mv_flush_tlb_current =		ev5_flush_tlb_current,		\
+	.mv_flush_tlb_current_page =	ev5_flush_tlb_current_page
 
 #define IO_LITE(UP,low)							\
-	hae_register:		(unsigned long *) CAT(UP,_HAE_ADDRESS),	\
-	iack_sc:		CAT(UP,_IACK_SC),			\
-	mv_inb:			CAT(low,_inb),				\
-	mv_inw:			CAT(low,_inw),				\
-	mv_inl:			CAT(low,_inl),				\
-	mv_outb:		CAT(low,_outb),				\
-	mv_outw:		CAT(low,_outw),				\
-	mv_outl:		CAT(low,_outl),				\
-	mv_readb:		CAT(low,_readb),			\
-	mv_readw:		CAT(low,_readw),			\
-	mv_readl:		CAT(low,_readl),			\
-	mv_readq:		CAT(low,_readq),			\
-	mv_writeb:		CAT(low,_writeb),			\
-	mv_writew:		CAT(low,_writew),			\
-	mv_writel:		CAT(low,_writel),			\
-	mv_writeq:		CAT(low,_writeq),			\
-	mv_ioremap:		CAT(low,_ioremap),			\
-	mv_iounmap:		CAT(low,_iounmap)			\
+	.hae_register =		(unsigned long *) CAT(UP,_HAE_ADDRESS),	\
+	.iack_sc =		CAT(UP,_IACK_SC),			\
+	.mv_ioread8 =		CAT(low,_ioread8),			\
+	.mv_ioread16 =		CAT(low,_ioread16),			\
+	.mv_ioread32 =		CAT(low,_ioread32),			\
+	.mv_iowrite8 =		CAT(low,_iowrite8),			\
+	.mv_iowrite16 =		CAT(low,_iowrite16),			\
+	.mv_iowrite32 =		CAT(low,_iowrite32),			\
+	.mv_readb =		CAT(low,_readb),			\
+	.mv_readw =		CAT(low,_readw),			\
+	.mv_readl =		CAT(low,_readl),			\
+	.mv_readq =		CAT(low,_readq),			\
+	.mv_writeb =		CAT(low,_writeb),			\
+	.mv_writew =		CAT(low,_writew),			\
+	.mv_writel =		CAT(low,_writel),			\
+	.mv_writeq =		CAT(low,_writeq),			\
+	.mv_ioportmap =		CAT(low,_ioportmap),			\
+	.mv_ioremap =		CAT(low,_ioremap),			\
+	.mv_iounmap =		CAT(low,_iounmap),			\
+	.mv_is_ioaddr =		CAT(low,_is_ioaddr),			\
+	.mv_is_mmio =		CAT(low,_is_mmio)			\
 
 #define IO(UP,low)							\
 	IO_LITE(UP,low),						\
-	pci_ops:		&CAT(low,_pci_ops)
+	.pci_ops =		&CAT(low,_pci_ops),			\
+	.mv_pci_tbi =		CAT(low,_pci_tbi)
 
 #define DO_APECS_IO	IO(APECS,apecs)
 #define DO_CIA_IO	IO(CIA,cia)
@@ -108,23 +112,8 @@
 #define DO_WILDFIRE_IO	IO(WILDFIRE,wildfire)
 
 #define DO_PYXIS_IO	IO_LITE(CIA,cia_bwx), \
-			pci_ops: &CAT(cia,_pci_ops)
-
-#define BUS(which)					\
-	mv_is_ioaddr:	CAT(which,_is_ioaddr),		\
-	mv_pci_tbi:	CAT(which,_pci_tbi)
-
-#define DO_APECS_BUS	BUS(apecs)
-#define DO_CIA_BUS	BUS(cia)
-#define DO_IRONGATE_BUS	BUS(irongate)
-#define DO_LCA_BUS	BUS(lca)
-#define DO_MARVEL_BUS	BUS(marvel)
-#define DO_MCPCIA_BUS	BUS(mcpcia)
-#define DO_POLARIS_BUS	BUS(polaris)
-#define DO_T2_BUS	BUS(t2)
-#define DO_TSUNAMI_BUS	BUS(tsunami)
-#define DO_TITAN_BUS	BUS(titan)
-#define DO_WILDFIRE_BUS	BUS(wildfire)
+			.pci_ops = &cia_pci_ops, \
+			.mv_pci_tbi = cia_pci_tbi
 
 /*
  * In a GENERIC kernel, we have lots of these vectors floating about,
diff -Nru a/arch/alpha/kernel/osf_sys.c b/arch/alpha/kernel/osf_sys.c
--- a/arch/alpha/kernel/osf_sys.c	2004-10-18 14:55:46 -07:00
+++ b/arch/alpha/kernel/osf_sys.c	2004-10-18 14:55:46 -07:00
@@ -91,8 +91,8 @@
  * braindamage (it can't really handle filesystems where the directory
  * offset differences aren't the same as "d_reclen").
  */
-#define NAME_OFFSET(de) ((int) ((de)->d_name - (char __user *) (de)))
-#define ROUND_UP(x) (((x)+3) & ~3)
+#define NAME_OFFSET	offsetof (struct osf_dirent, d_name)
+#define ROUND_UP(x)	(((x)+3) & ~3)
 
 struct osf_dirent {
 	unsigned int d_ino;
@@ -114,7 +114,7 @@
 {
 	struct osf_dirent __user *dirent;
 	struct osf_dirent_callback *buf = (struct osf_dirent_callback *) __buf;
-	unsigned int reclen = ROUND_UP(NAME_OFFSET(dirent) + namlen + 1);
+	unsigned int reclen = ROUND_UP(NAME_OFFSET + namlen + 1);
 
 	buf->error = -EINVAL;	/* only used if we fail */
 	if (reclen > buf->count)
@@ -723,7 +723,8 @@
 {
 	switch (op) {
 	case SSI_IEEE_FP_CONTROL: {
-		unsigned long swcr, fpcr, fex;
+		unsigned long swcr, fpcr;
+		unsigned int *state;
 
 		/* 
 		 * Alpha Architecture Handbook 4.7.7.3:
@@ -732,22 +733,42 @@
 		 * set in the trap shadow of a software-complete insn.
 		 */
 
-		/* Update softare trap enable bits.  */
 		if (get_user(swcr, (unsigned long __user *)buffer))
 			return -EFAULT;
-		current_thread_info()->ieee_state
-		  = ((current_thread_info()->ieee_state & ~IEEE_SW_MASK)
-		     | (swcr & IEEE_SW_MASK));
+		state = &current_thread_info()->ieee_state;
+
+		/* Update softare trap enable bits.  */
+		*state = (*state & ~IEEE_SW_MASK) | (swcr & IEEE_SW_MASK);
+
+		/* Update the real fpcr.  */
+		fpcr = rdfpcr() & FPCR_DYN_MASK;
+		fpcr |= ieee_swcr_to_fpcr(swcr);
+		wrfpcr(fpcr);
+
+		return 0;
+	}
+
+	case SSI_IEEE_RAISE_EXCEPTION: {
+		unsigned long exc, swcr, fpcr, fex;
+		unsigned int *state;
+
+		if (get_user(exc, (unsigned long __user *)buffer))
+			return -EFAULT;
+		state = &current_thread_info()->ieee_state;
+		exc &= IEEE_STATUS_MASK;
+
+		/* Update softare trap enable bits.  */
+ 		swcr = (*state & IEEE_SW_MASK) | exc;
+		*state |= exc;
 
 		/* Update the real fpcr.  */
 		fpcr = rdfpcr();
-		fpcr &= FPCR_DYN_MASK;
 		fpcr |= ieee_swcr_to_fpcr(swcr);
 		wrfpcr(fpcr);
 
- 		/* If any exceptions are now unmasked, send a signal.  */
-		fex = ((swcr & IEEE_STATUS_MASK)
-		       >> IEEE_STATUS_TO_EXCSUM_SHIFT) & swcr;
+ 		/* If any exceptions set by this call, and are unmasked,
+		   send a signal.  Old exceptions are not signaled.  */
+		fex = (exc >> IEEE_STATUS_TO_EXCSUM_SHIFT) & swcr;
  		if (fex) {
 			siginfo_t info;
 			int si_code = 0;
@@ -765,7 +786,6 @@
 			info.si_addr = NULL;  /* FIXME */
  			send_sig_info(SIGFPE, &info, current);
  		}
-
 		return 0;
 	}
 
@@ -969,7 +989,7 @@
 	fd_set_bits fds;
 	char *bits;
 	size_t size;
-	unsigned long timeout;
+	long timeout;
 	int ret;
 
 	timeout = MAX_SCHEDULE_TIMEOUT;
@@ -1033,9 +1053,10 @@
 		ret = 0;
 	}
 
-	set_fd_set(n, inp->fds_bits, fds.res_in);
-	set_fd_set(n, outp->fds_bits, fds.res_out);
-	set_fd_set(n, exp->fds_bits, fds.res_ex);
+	if (set_fd_set(n, inp->fds_bits, fds.res_in) ||
+	    set_fd_set(n, outp->fds_bits, fds.res_out) ||
+	    set_fd_set(n, exp->fds_bits, fds.res_ex))
+		ret = -EFAULT;
 
  out:
 	kfree(bits);
@@ -1079,64 +1100,57 @@
 		r.ru_majflt = current->maj_flt;
 		break;
 	case RUSAGE_CHILDREN:
-		jiffies_to_timeval32(current->cutime, &r.ru_utime);
-		jiffies_to_timeval32(current->cstime, &r.ru_stime);
-		r.ru_minflt = current->cmin_flt;
-		r.ru_majflt = current->cmaj_flt;
-		break;
-	default:
-		jiffies_to_timeval32(current->utime + current->cutime,
-				   &r.ru_utime);
-		jiffies_to_timeval32(current->stime + current->cstime,
-				   &r.ru_stime);
-		r.ru_minflt = current->min_flt + current->cmin_flt;
-		r.ru_majflt = current->maj_flt + current->cmaj_flt;
+		jiffies_to_timeval32(current->signal->cutime, &r.ru_utime);
+		jiffies_to_timeval32(current->signal->cstime, &r.ru_stime);
+		r.ru_minflt = current->signal->cmin_flt;
+		r.ru_majflt = current->signal->cmaj_flt;
 		break;
 	}
 
 	return copy_to_user(ru, &r, sizeof(r)) ? -EFAULT : 0;
 }
 
-asmlinkage int
-osf_wait4(pid_t pid, int __user *ustatus, int options, struct rusage32 __user *ur)
+asmlinkage long
+osf_wait4(pid_t pid, int __user *ustatus, int options,
+	  struct rusage32 __user *ur)
 {
-	if (!ur) {
+	struct rusage r;
+	long ret, err;
+	mm_segment_t old_fs;
+
+	if (!ur)
 		return sys_wait4(pid, ustatus, options, NULL);
-	} else {
-		struct rusage r;
-		int ret, status;
-		mm_segment_t old_fs = get_fs();
+
+	old_fs = get_fs();
 		
-		set_fs (KERNEL_DS);
-		ret = sys_wait4(pid, &status, options, &r);
-		set_fs (old_fs);
+	set_fs (KERNEL_DS);
+	ret = sys_wait4(pid, ustatus, options, (struct rusage __user *) &r);
+	set_fs (old_fs);
 
-		if (!access_ok(VERIFY_WRITE, ur, sizeof(*ur)))
-			return -EFAULT;
-		__put_user(r.ru_utime.tv_sec, &ur->ru_utime.tv_sec);
-		__put_user(r.ru_utime.tv_usec, &ur->ru_utime.tv_usec);
-		__put_user(r.ru_stime.tv_sec, &ur->ru_stime.tv_sec);
-		__put_user(r.ru_stime.tv_usec, &ur->ru_stime.tv_usec);
-		__put_user(r.ru_maxrss, &ur->ru_maxrss);
-		__put_user(r.ru_ixrss, &ur->ru_ixrss);
-		__put_user(r.ru_idrss, &ur->ru_idrss);
-		__put_user(r.ru_isrss, &ur->ru_isrss);
-		__put_user(r.ru_minflt, &ur->ru_minflt);
-		__put_user(r.ru_majflt, &ur->ru_majflt);
-		__put_user(r.ru_nswap, &ur->ru_nswap);
-		__put_user(r.ru_inblock, &ur->ru_inblock);
-		__put_user(r.ru_oublock, &ur->ru_oublock);
-		__put_user(r.ru_msgsnd, &ur->ru_msgsnd);
-		__put_user(r.ru_msgrcv, &ur->ru_msgrcv);
-		__put_user(r.ru_nsignals, &ur->ru_nsignals);
-		__put_user(r.ru_nvcsw, &ur->ru_nvcsw);
-		if (__put_user(r.ru_nivcsw, &ur->ru_nivcsw))
-			return -EFAULT;
+	if (!access_ok(VERIFY_WRITE, ur, sizeof(*ur)))
+		return -EFAULT;
 
-		if (ustatus && put_user(status, ustatus))
-			return -EFAULT;
-		return ret;
-	}
+	err = 0;
+	err |= __put_user(r.ru_utime.tv_sec, &ur->ru_utime.tv_sec);
+	err |= __put_user(r.ru_utime.tv_usec, &ur->ru_utime.tv_usec);
+	err |= __put_user(r.ru_stime.tv_sec, &ur->ru_stime.tv_sec);
+	err |= __put_user(r.ru_stime.tv_usec, &ur->ru_stime.tv_usec);
+	err |= __put_user(r.ru_maxrss, &ur->ru_maxrss);
+	err |= __put_user(r.ru_ixrss, &ur->ru_ixrss);
+	err |= __put_user(r.ru_idrss, &ur->ru_idrss);
+	err |= __put_user(r.ru_isrss, &ur->ru_isrss);
+	err |= __put_user(r.ru_minflt, &ur->ru_minflt);
+	err |= __put_user(r.ru_majflt, &ur->ru_majflt);
+	err |= __put_user(r.ru_nswap, &ur->ru_nswap);
+	err |= __put_user(r.ru_inblock, &ur->ru_inblock);
+	err |= __put_user(r.ru_oublock, &ur->ru_oublock);
+	err |= __put_user(r.ru_msgsnd, &ur->ru_msgsnd);
+	err |= __put_user(r.ru_msgrcv, &ur->ru_msgrcv);
+	err |= __put_user(r.ru_nsignals, &ur->ru_nsignals);
+	err |= __put_user(r.ru_nvcsw, &ur->ru_nvcsw);
+	err |= __put_user(r.ru_nivcsw, &ur->ru_nivcsw);
+
+	return err ? err : ret;
 }
 
 /*
diff -Nru a/arch/alpha/kernel/pci-noop.c b/arch/alpha/kernel/pci-noop.c
--- a/arch/alpha/kernel/pci-noop.c	2004-10-18 14:56:29 -07:00
+++ b/arch/alpha/kernel/pci-noop.c	2004-10-18 14:56:29 -07:00
@@ -7,8 +7,10 @@
 #include <linux/pci.h>
 #include <linux/init.h>
 #include <linux/bootmem.h>
+#include <linux/mm.h>
 #include <linux/errno.h>
 #include <linux/sched.h>
+#include <linux/dma-mapping.h>
 
 #include "proto.h"
 
@@ -101,41 +103,112 @@
 	else
 		return -ENODEV;
 }
-/* stubs for the routines in pci_iommu.c */
+
+/* Stubs for the routines in pci_iommu.c: */
+
 void *
 pci_alloc_consistent(struct pci_dev *pdev, size_t size, dma_addr_t *dma_addrp)
 {
 	return NULL;
 }
+
 void
 pci_free_consistent(struct pci_dev *pdev, size_t size, void *cpu_addr,
 		    dma_addr_t dma_addr)
 {
 }
+
 dma_addr_t
 pci_map_single(struct pci_dev *pdev, void *cpu_addr, size_t size,
 	       int direction)
 {
 	return (dma_addr_t) 0;
 }
+
 void
 pci_unmap_single(struct pci_dev *pdev, dma_addr_t dma_addr, size_t size,
 		 int direction)
 {
 }
+
 int
 pci_map_sg(struct pci_dev *pdev, struct scatterlist *sg, int nents,
 	   int direction)
 {
 	return 0;
 }
+
 void
 pci_unmap_sg(struct pci_dev *pdev, struct scatterlist *sg, int nents,
 	     int direction)
 {
 }
+
 int
 pci_dma_supported(struct pci_dev *hwdev, dma_addr_t mask)
 {
 	return 0;
 }
+
+/* Generic DMA mapping functions: */
+
+void *
+dma_alloc_coherent(struct device *dev, size_t size,
+		   dma_addr_t *dma_handle, int gfp)
+{
+	void *ret;
+
+	if (!dev || *dev->dma_mask >= 0xffffffffUL)
+		gfp &= ~GFP_DMA;
+	ret = (void *)__get_free_pages(gfp, get_order(size));
+	if (ret) {
+		memset(ret, 0, size);
+		*dma_handle = virt_to_bus(ret);
+	}
+	return ret;
+}
+
+EXPORT_SYMBOL(dma_alloc_coherent);
+
+int
+dma_map_sg(struct device *dev, struct scatterlist *sg, int nents,
+	   enum dma_data_direction direction)
+{
+	int i;
+
+	for (i = 0; i < nents; i++ ) {
+		void *va;
+
+		BUG_ON(!sg[i].page);
+		va = page_address(sg[i].page) + sg[i].offset;
+		sg_dma_address(sg + i) = (dma_addr_t)virt_to_bus(va);
+		sg_dma_len(sg + i) = sg[i].length;
+	}
+
+	return nents;
+}
+
+EXPORT_SYMBOL(dma_map_sg);
+
+int
+dma_set_mask(struct device *dev, u64 mask)
+{
+	if (!dev->dma_mask || !dma_supported(dev, mask))
+		return -EIO;
+
+	*dev->dma_mask = mask;
+
+	return 0;
+}
+
+void __iomem *pci_iomap(struct pci_dev *dev, int bar, unsigned long maxlen)
+{
+	return NULL;
+}
+
+void pci_iounmap(struct pci_dev *dev, void __iomem * addr)
+{
+}
+
+EXPORT_SYMBOL(pci_iomap);
+EXPORT_SYMBOL(pci_iounmap);
diff -Nru a/arch/alpha/kernel/pci.c b/arch/alpha/kernel/pci.c
--- a/arch/alpha/kernel/pci.c	2004-10-18 14:55:54 -07:00
+++ b/arch/alpha/kernel/pci.c	2004-10-18 14:55:54 -07:00
@@ -67,6 +67,7 @@
 {
 	dev->class = PCI_CLASS_BRIDGE_ISA << 8;
 }
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82378, quirk_isa_bridge);
 
 static void __init
 quirk_cypress(struct pci_dev *dev)
@@ -100,6 +101,7 @@
 		}
 	}
 }
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_CONTAQ, PCI_DEVICE_ID_CONTAQ_82C693, quirk_cypress);
 
 /* Called for each device after PCI setup is done. */
 static void __init
@@ -112,17 +114,10 @@
 		isa_bridge = dev;
 	}
 }
+DECLARE_PCI_FIXUP_FINAL(PCI_ANY_ID, PCI_ANY_ID, pcibios_fixup_final);
 
-struct pci_fixup pcibios_fixups[] __initdata = {
-	{ PCI_FIXUP_HEADER, PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82378,
-	  quirk_isa_bridge },
-	{ PCI_FIXUP_HEADER, PCI_VENDOR_ID_CONTAQ, PCI_DEVICE_ID_CONTAQ_82C693,
-	  quirk_cypress },
-	{ PCI_FIXUP_FINAL,  PCI_ANY_ID,	PCI_ANY_ID,
-	  pcibios_fixup_final },
-	{ 0 }
-};
-
+/* Just declaring that the power-of-ten prefixes are actually the
+   power-of-two ones doesn't make it true :) */
 #define KB			1024
 #define MB			(1024*KB)
 #define GB			(1024*MB)
@@ -536,3 +531,37 @@
 
 	return -EOPNOTSUPP;
 }
+
+/* Create an __iomem token from a PCI BAR.  Copied from lib/iomap.c with
+   no changes, since we don't want the other things in that object file.  */
+
+void __iomem *pci_iomap(struct pci_dev *dev, int bar, unsigned long maxlen)
+{
+	unsigned long start = pci_resource_start(dev, bar);
+	unsigned long len = pci_resource_len(dev, bar);
+	unsigned long flags = pci_resource_flags(dev, bar);
+
+	if (!len || !start)
+		return NULL;
+	if (maxlen && len > maxlen)
+		len = maxlen;
+	if (flags & IORESOURCE_IO)
+		return ioport_map(start, len);
+	if (flags & IORESOURCE_MEM) {
+		/* Not checking IORESOURCE_CACHEABLE because alpha does
+		   not distinguish between ioremap and ioremap_nocache.  */
+		return ioremap(start, len);
+	}
+	return NULL;
+}
+
+/* Destroy that token.  Not copied from lib/iomap.c.  */
+
+void pci_iounmap(struct pci_dev *dev, void __iomem * addr)
+{
+	if (__is_mmio(addr))
+		iounmap(addr);
+}
+
+EXPORT_SYMBOL(pci_iomap);
+EXPORT_SYMBOL(pci_iounmap);
diff -Nru a/arch/alpha/kernel/pci_iommu.c b/arch/alpha/kernel/pci_iommu.c
--- a/arch/alpha/kernel/pci_iommu.c	2004-10-18 14:57:04 -07:00
+++ b/arch/alpha/kernel/pci_iommu.c	2004-10-18 14:57:04 -07:00
@@ -930,3 +930,42 @@
 {
 	return (dma_addr & ~PAGE_MASK);
 }
+
+
+/* Helper for generic DMA-mapping functions. */
+
+struct pci_dev *
+alpha_gendev_to_pci(struct device *dev)
+{
+	if (dev && dev->bus == &pci_bus_type)
+		return to_pci_dev(dev);
+
+	/* Assume that non-PCI devices asking for DMA are either ISA or EISA,
+	   BUG() otherwise. */
+	BUG_ON(!isa_bridge);
+
+	/* Assume non-busmaster ISA DMA when dma_mask is not set (the ISA
+	   bridge is bus master then). */
+	if (!dev || !dev->dma_mask || !*dev->dma_mask)
+		return isa_bridge;
+
+	/* For EISA bus masters, return isa_bridge (it might have smaller
+	   dma_mask due to wiring limitations). */
+	if (*dev->dma_mask >= isa_bridge->dma_mask)
+		return isa_bridge;
+
+	/* This assumes ISA bus master with dma_mask 0xffffff. */
+	return NULL;
+}
+
+int
+dma_set_mask(struct device *dev, u64 mask)
+{
+	if (!dev->dma_mask ||
+	    !pci_dma_supported(alpha_gendev_to_pci(dev), mask))
+		return -EIO;
+
+	*dev->dma_mask = mask;
+
+	return 0;
+}
diff -Nru a/arch/alpha/kernel/process.c b/arch/alpha/kernel/process.c
--- a/arch/alpha/kernel/process.c	2004-10-18 14:56:50 -07:00
+++ b/arch/alpha/kernel/process.c	2004-10-18 14:56:50 -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/ptrace.c b/arch/alpha/kernel/ptrace.c
--- a/arch/alpha/kernel/ptrace.c	2004-10-18 14:57:03 -07:00
+++ b/arch/alpha/kernel/ptrace.c	2004-10-18 14:57:03 -07:00
@@ -91,15 +91,15 @@
 	PT_REG(	   pc)
 };
 
-static long zero;
+static unsigned long zero;
 
 /*
  * Get address of register REGNO in task TASK.
  */
-static long *
+static unsigned long *
 get_reg_addr(struct task_struct * task, unsigned long regno)
 {
-	long *addr;
+	unsigned long *addr;
 
 	if (regno == 30) {
 		addr = &task->thread_info->pcb.usp;
@@ -109,7 +109,7 @@
 		zero = 0;
 		addr = &zero;
 	} else {
-		addr = (long *)((long)task->thread_info + regoff[regno]);
+		addr = (void *)task->thread_info + regoff[regno];
 	}
 	return addr;
 }
@@ -117,7 +117,7 @@
 /*
  * Get contents of register REGNO in task TASK.
  */
-static long
+static unsigned long
 get_reg(struct task_struct * task, unsigned long regno)
 {
 	/* Special hack for fpcr -- combine hardware and software bits.  */
@@ -135,7 +135,7 @@
  * Write contents of register REGNO in task TASK.
  */
 static int
-put_reg(struct task_struct *task, unsigned long regno, long data)
+put_reg(struct task_struct *task, unsigned long regno, unsigned long data)
 {
 	if (regno == 63) {
 		task->thread_info->ieee_state
@@ -168,11 +168,11 @@
 ptrace_set_bpt(struct task_struct * child)
 {
 	int displ, i, res, reg_b, nsaved = 0;
-	u32 insn, op_code;
+	unsigned int insn, op_code;
 	unsigned long pc;
 
 	pc  = get_reg(child, REG_PC);
-	res = read_int(child, pc, &insn);
+	res = read_int(child, pc, (int *) &insn);
 	if (res < 0)
 		return res;
 
@@ -203,7 +203,8 @@
 
 	/* install breakpoints: */
 	for (i = 0; i < nsaved; ++i) {
-		res = read_int(child, child->thread_info->bpt_addr[i], &insn);
+		res = read_int(child, child->thread_info->bpt_addr[i],
+			       (int *) &insn);
 		if (res < 0)
 			return res;
 		child->thread_info->bpt_insn[i] = insn;
diff -Nru a/arch/alpha/kernel/signal.c b/arch/alpha/kernel/signal.c
--- a/arch/alpha/kernel/signal.c	2004-10-18 14:56:29 -07:00
+++ b/arch/alpha/kernel/signal.c	2004-10-18 14:56:29 -07:00
@@ -145,7 +145,7 @@
  * Atomically swap in the new signal mask, and wait for a signal.
  */
 asmlinkage int
-do_sigsuspend(old_sigset_t mask, struct pt_regs *reg, struct switch_stack *sw)
+do_sigsuspend(old_sigset_t mask, struct pt_regs *regs, struct switch_stack *sw)
 {
 	sigset_t oldset;
 
@@ -156,17 +156,22 @@
 	recalc_sigpending();
 	spin_unlock_irq(&current->sighand->siglock);
 
+	/* Indicate EINTR on return from any possible signal handler,
+	   which will not come back through here, but via sigreturn.  */
+	regs->r0 = EINTR;
+	regs->r19 = 1;
+
 	while (1) {
 		current->state = TASK_INTERRUPTIBLE;
 		schedule();
-		if (do_signal(&oldset, reg, sw, 0, 0))
+		if (do_signal(&oldset, regs, sw, 0, 0))
 			return -EINTR;
 	}
 }
 
 asmlinkage int
 do_rt_sigsuspend(sigset_t __user *uset, size_t sigsetsize,
-		 struct pt_regs *reg, struct switch_stack *sw)
+		 struct pt_regs *regs, struct switch_stack *sw)
 {
 	sigset_t oldset, set;
 
@@ -183,10 +188,15 @@
 	recalc_sigpending();
 	spin_unlock_irq(&current->sighand->siglock);
 
+	/* Indicate EINTR on return from any possible signal handler,
+	   which will not come back through here, but via sigreturn.  */
+	regs->r0 = EINTR;
+	regs->r19 = 1;
+
 	while (1) {
 		current->state = TASK_INTERRUPTIBLE;
 		schedule();
-		if (do_signal(&oldset, reg, sw, 0, 0))
+		if (do_signal(&oldset, regs, sw, 0, 0))
 			return -EINTR;
 	}
 }
@@ -218,6 +228,12 @@
 	unsigned int retcode[3];
 };
 
+/* If this changes, userland unwinders that Know Things about our signal
+   frame will break.  Do not undertake lightly.  It also implies an ABI
+   change wrt the size of siginfo_t, which may cause some pain.  */
+extern char compile_time_assert
+        [offsetof(struct rt_sigframe, uc.uc_mcontext) == 176 ? 1 : -1];
+
 #define INSN_MOV_R30_R16	0x47fe0410
 #define INSN_LDI_R0		0x201f0000
 #define INSN_CALLSYS		0x00000083
@@ -469,9 +485,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 +547,7 @@
 	return;
 
 give_sigsegv:
-	if (sig == SIGSEGV)
-		ka->sa.sa_handler = SIG_DFL;
-	force_sig(SIGSEGV, current);
+	force_sigsegv(sig, current);
 }
 
 
@@ -608,21 +620,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-10-18 14:56:27 -07:00
+++ b/arch/alpha/kernel/smp.c	2004-10-18 14:56:27 -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>
@@ -35,7 +36,6 @@
 #include <asm/bitops.h>
 #include <asm/pgtable.h>
 #include <asm/pgalloc.h>
-#include <asm/hardirq.h>
 #include <asm/mmu_context.h>
 #include <asm/tlbflush.h>
 
@@ -411,15 +411,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 +426,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 +599,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/srmcons.c b/arch/alpha/kernel/srmcons.c
--- a/arch/alpha/kernel/srmcons.c	2004-10-18 14:57:03 -07:00
+++ b/arch/alpha/kernel/srmcons.c	2004-10-18 14:57:03 -07:00
@@ -91,15 +91,15 @@
 
 /* called with callback_lock held */
 static int
-srmcons_do_write(struct tty_struct *tty, const unsigned char *buf, int count)
+srmcons_do_write(struct tty_struct *tty, const char *buf, int count)
 {
-	unsigned char *str_cr = "\r";
+	static char str_cr[1] = "\r";
 	long c, remaining = count;
 	srmcons_result result;
-	unsigned char *cur;
+	char *cur;
 	int need_cr;
 
-	for (cur = (unsigned char *)buf; remaining > 0; ) {
+	for (cur = (char *)buf; remaining > 0; ) {
 		need_cr = 0;
 		/* 
 		 * Break it up into reasonable size chunks to allow a chance
@@ -138,7 +138,7 @@
 	unsigned long flags;
 
 	if (from_user) {
-		unsigned char tmp[512];
+		char tmp[512];
 		int ret = 0;
 		size_t c;
 
@@ -146,7 +146,7 @@
 			if (c > sizeof(tmp))
 				c = sizeof(tmp);
 			
-			c -= copy_from_user(tmp, buf, c);
+			c -= copy_from_user(tmp, (const char __user *) buf, c);
 
 			if (!c) { 
 				printk("%s: EFAULT (count %d)\n",
@@ -167,7 +167,7 @@
 	}
 
 	spin_lock_irqsave(&srmcons_callback_lock, flags);
-	srmcons_do_write(tty, buf, count);
+	srmcons_do_write(tty, (const char *) buf, count);
 	spin_unlock_irqrestore(&srmcons_callback_lock, flags);
 
 	return count;
diff -Nru a/arch/alpha/kernel/sys_alcor.c b/arch/alpha/kernel/sys_alcor.c
--- a/arch/alpha/kernel/sys_alcor.c	2004-10-18 14:57:04 -07:00
+++ b/arch/alpha/kernel/sys_alcor.c	2004-10-18 14:57:04 -07:00
@@ -274,7 +274,6 @@
 	DO_EV5_MMU,
 	DO_DEFAULT_RTC,
 	DO_CIA_IO,
-	DO_CIA_BUS,
 	.machine_check		= cia_machine_check,
 	.max_isa_dma_address	= ALPHA_ALCOR_MAX_ISA_DMA_ADDRESS,
 	.min_io_address		= EISA_DEFAULT_IO_BASE,
@@ -292,7 +291,7 @@
 	.pci_swizzle		= common_swizzle,
 
 	.sys = { .cia = {
-	    .gru_int_req_bits	= ALCOR_GRU_INT_REQ_BITS
+		.gru_int_req_bits = ALCOR_GRU_INT_REQ_BITS
 	}}
 };
 ALIAS_MV(alcor)
@@ -302,7 +301,6 @@
 	DO_EV5_MMU,
 	DO_DEFAULT_RTC,
 	DO_CIA_IO,
-	DO_CIA_BUS,
 	.machine_check		= cia_machine_check,
 	.max_isa_dma_address	= ALPHA_MAX_ISA_DMA_ADDRESS,
 	.min_io_address		= EISA_DEFAULT_IO_BASE,
@@ -320,7 +318,7 @@
 	.pci_swizzle		= common_swizzle,
 
 	.sys = { .cia = {
-	    .gru_int_req_bits	= XLT_GRU_INT_REQ_BITS
+		.gru_int_req_bits = XLT_GRU_INT_REQ_BITS
 	}}
 };
 
diff -Nru a/arch/alpha/kernel/sys_cabriolet.c b/arch/alpha/kernel/sys_cabriolet.c
--- a/arch/alpha/kernel/sys_cabriolet.c	2004-10-18 14:56:27 -07:00
+++ b/arch/alpha/kernel/sys_cabriolet.c	2004-10-18 14:56:27 -07:00
@@ -327,7 +327,6 @@
 	DO_EV4_MMU,
 	DO_DEFAULT_RTC,
 	DO_APECS_IO,
-	DO_APECS_BUS,
 	.machine_check		= apecs_machine_check,
 	.max_isa_dma_address	= ALPHA_MAX_ISA_DMA_ADDRESS,
 	.min_io_address		= DEFAULT_IO_BASE,
@@ -354,7 +353,6 @@
 	DO_EV5_MMU,
 	DO_DEFAULT_RTC,
 	DO_CIA_IO,
-	DO_CIA_BUS,
 	.machine_check		= cia_machine_check,
 	.max_isa_dma_address	= ALPHA_MAX_ISA_DMA_ADDRESS,
 	.min_io_address		= DEFAULT_IO_BASE,
@@ -380,7 +378,6 @@
 	DO_EV4_MMU,
 	DO_DEFAULT_RTC,
 	DO_LCA_IO,
-	DO_LCA_BUS,
 	.machine_check		= lca_machine_check,
 	.max_isa_dma_address	= ALPHA_MAX_ISA_DMA_ADDRESS,
 	.min_io_address		= DEFAULT_IO_BASE,
@@ -405,7 +402,6 @@
 	DO_EV5_MMU,
 	DO_DEFAULT_RTC,
 	DO_PYXIS_IO,
-	DO_CIA_BUS,
 	.machine_check		= cia_machine_check,
 	.max_isa_dma_address	= ALPHA_MAX_ISA_DMA_ADDRESS,
 	.min_io_address		= DEFAULT_IO_BASE,
@@ -432,7 +428,6 @@
 	DO_EV5_MMU,
 	DO_DEFAULT_RTC,
 	DO_CIA_IO,
-	DO_CIA_BUS,
 	.machine_check		= cia_machine_check,
 	.max_isa_dma_address	= ALPHA_MAX_ISA_DMA_ADDRESS,
 	.min_io_address		= DEFAULT_IO_BASE,
diff -Nru a/arch/alpha/kernel/sys_dp264.c b/arch/alpha/kernel/sys_dp264.c
--- a/arch/alpha/kernel/sys_dp264.c	2004-10-18 14:56:17 -07:00
+++ b/arch/alpha/kernel/sys_dp264.c	2004-10-18 14:56:17 -07:00
@@ -71,10 +71,10 @@
 	dim1 = &cchip->dim1.csr;
 	dim2 = &cchip->dim2.csr;
 	dim3 = &cchip->dim3.csr;
-	if (cpu_possible(0)) dim0 = &dummy;
-	if (cpu_possible(1)) dim1 = &dummy;
-	if (cpu_possible(2)) dim2 = &dummy;
-	if (cpu_possible(3)) dim3 = &dummy;
+	if (!cpu_possible(0)) dim0 = &dummy;
+	if (!cpu_possible(1)) dim1 = &dummy;
+	if (!cpu_possible(2)) dim2 = &dummy;
+	if (!cpu_possible(3)) dim3 = &dummy;
 
 	*dim0 = mask0;
 	*dim1 = mask1;
@@ -569,7 +569,6 @@
 	DO_EV6_MMU,
 	DO_DEFAULT_RTC,
 	DO_TSUNAMI_IO,
-	DO_TSUNAMI_BUS,
 	.machine_check		= tsunami_machine_check,
 	.max_isa_dma_address	= ALPHA_MAX_ISA_DMA_ADDRESS,
 	.min_io_address		= DEFAULT_IO_BASE,
@@ -594,7 +593,6 @@
 	DO_EV6_MMU,
 	DO_DEFAULT_RTC,
 	DO_TSUNAMI_IO,
-	DO_TSUNAMI_BUS,
 	.machine_check		= tsunami_machine_check,
 	.max_isa_dma_address	= ALPHA_MAX_ISA_DMA_ADDRESS,
 	.min_io_address		= DEFAULT_IO_BASE,
@@ -618,7 +616,6 @@
 	DO_EV6_MMU,
 	DO_DEFAULT_RTC,
 	DO_TSUNAMI_IO,
-	DO_TSUNAMI_BUS,
 	.machine_check		= tsunami_machine_check,
 	.max_isa_dma_address	= ALPHA_MAX_ISA_DMA_ADDRESS,
 	.min_io_address		= DEFAULT_IO_BASE,
@@ -642,7 +639,6 @@
 	DO_EV6_MMU,
 	DO_DEFAULT_RTC,
 	DO_TSUNAMI_IO,
-	DO_TSUNAMI_BUS,
 	.machine_check		= tsunami_machine_check,
 	.max_isa_dma_address	= ALPHA_MAX_ISA_DMA_ADDRESS,
 	.min_io_address		= DEFAULT_IO_BASE,
@@ -671,7 +667,6 @@
 	DO_EV6_MMU,
 	DO_DEFAULT_RTC,
 	DO_TSUNAMI_IO,
-	DO_TSUNAMI_BUS,
 	.machine_check		= tsunami_machine_check,
 	.max_isa_dma_address	= ALPHA_MAX_ISA_DMA_ADDRESS,
 	.min_io_address		= DEFAULT_IO_BASE,
diff -Nru a/arch/alpha/kernel/sys_eb64p.c b/arch/alpha/kernel/sys_eb64p.c
--- a/arch/alpha/kernel/sys_eb64p.c	2004-10-18 14:57:20 -07:00
+++ b/arch/alpha/kernel/sys_eb64p.c	2004-10-18 14:57:20 -07:00
@@ -212,7 +212,6 @@
 	DO_EV4_MMU,
 	DO_DEFAULT_RTC,
 	DO_APECS_IO,
-	DO_APECS_BUS,
 	.machine_check		= apecs_machine_check,
 	.max_isa_dma_address	= ALPHA_MAX_ISA_DMA_ADDRESS,
 	.min_io_address		= DEFAULT_IO_BASE,
@@ -238,7 +237,6 @@
 	DO_EV4_MMU,
 	DO_DEFAULT_RTC,
 	DO_LCA_IO,
-	DO_LCA_BUS,
 	.machine_check		= lca_machine_check,
 	.max_isa_dma_address	= ALPHA_MAX_ISA_DMA_ADDRESS,
 	.min_io_address		= DEFAULT_IO_BASE,
diff -Nru a/arch/alpha/kernel/sys_eiger.c b/arch/alpha/kernel/sys_eiger.c
--- a/arch/alpha/kernel/sys_eiger.c	2004-10-18 14:55:54 -07:00
+++ b/arch/alpha/kernel/sys_eiger.c	2004-10-18 14:55:54 -07:00
@@ -222,7 +222,6 @@
 	DO_EV6_MMU,
 	DO_DEFAULT_RTC,
 	DO_TSUNAMI_IO,
-	DO_TSUNAMI_BUS,
 	.machine_check		= tsunami_machine_check,
 	.max_isa_dma_address	= ALPHA_MAX_ISA_DMA_ADDRESS,
 	.min_io_address		= DEFAULT_IO_BASE,
diff -Nru a/arch/alpha/kernel/sys_jensen.c b/arch/alpha/kernel/sys_jensen.c
--- a/arch/alpha/kernel/sys_jensen.c	2004-10-18 14:56:33 -07:00
+++ b/arch/alpha/kernel/sys_jensen.c	2004-10-18 14:56:33 -07:00
@@ -249,8 +249,6 @@
 	printk(KERN_CRIT "Machine check\n");
 }
 
-#define jensen_pci_tbi	((void*)0)
-
 
 /*
  * The System Vector
@@ -260,7 +258,6 @@
 	.vector_name		= "Jensen",
 	DO_EV4_MMU,
 	IO_LITE(JENSEN,jensen),
-	BUS(jensen),
 	.machine_check		= jensen_machine_check,
 	.max_isa_dma_address	= ALPHA_MAX_ISA_DMA_ADDRESS,
 	.rtc_port		= 0x170,
diff -Nru a/arch/alpha/kernel/sys_marvel.c b/arch/alpha/kernel/sys_marvel.c
--- a/arch/alpha/kernel/sys_marvel.c	2004-10-18 14:56:49 -07:00
+++ b/arch/alpha/kernel/sys_marvel.c	2004-10-18 14:56:49 -07:00
@@ -471,7 +471,6 @@
 	DO_EV7_MMU,
 	DO_DEFAULT_RTC,
 	DO_MARVEL_IO,
-	DO_MARVEL_BUS,
 	.machine_check		= marvel_machine_check,
 	.max_isa_dma_address	= ALPHA_MAX_ISA_DMA_ADDRESS,
 	.min_io_address		= DEFAULT_IO_BASE,
diff -Nru a/arch/alpha/kernel/sys_miata.c b/arch/alpha/kernel/sys_miata.c
--- a/arch/alpha/kernel/sys_miata.c	2004-10-18 14:56:32 -07:00
+++ b/arch/alpha/kernel/sys_miata.c	2004-10-18 14:56:32 -07:00
@@ -269,7 +269,6 @@
 	DO_EV5_MMU,
 	DO_DEFAULT_RTC,
 	DO_PYXIS_IO,
-	DO_CIA_BUS,
 	.machine_check		= cia_machine_check,
 	.max_isa_dma_address	= ALPHA_MAX_ISA_DMA_ADDRESS,
 	.min_io_address		= DEFAULT_IO_BASE,
diff -Nru a/arch/alpha/kernel/sys_mikasa.c b/arch/alpha/kernel/sys_mikasa.c
--- a/arch/alpha/kernel/sys_mikasa.c	2004-10-18 14:56:49 -07:00
+++ b/arch/alpha/kernel/sys_mikasa.c	2004-10-18 14:56:49 -07:00
@@ -221,7 +221,6 @@
 	DO_EV4_MMU,
 	DO_DEFAULT_RTC,
 	DO_APECS_IO,
-	DO_APECS_BUS,
 	.machine_check		= mikasa_apecs_machine_check,
 	.max_isa_dma_address	= ALPHA_MAX_ISA_DMA_ADDRESS,
 	.min_io_address		= DEFAULT_IO_BASE,
@@ -246,7 +245,6 @@
 	DO_EV5_MMU,
 	DO_DEFAULT_RTC,
 	DO_CIA_IO,
-	DO_CIA_BUS,
 	.machine_check		= cia_machine_check,
 	.max_isa_dma_address	= ALPHA_MAX_ISA_DMA_ADDRESS,
 	.min_io_address		= DEFAULT_IO_BASE,
diff -Nru a/arch/alpha/kernel/sys_nautilus.c b/arch/alpha/kernel/sys_nautilus.c
--- a/arch/alpha/kernel/sys_nautilus.c	2004-10-18 14:56:28 -07:00
+++ b/arch/alpha/kernel/sys_nautilus.c	2004-10-18 14:56:28 -07:00
@@ -250,7 +250,6 @@
 	DO_EV6_MMU,
 	DO_DEFAULT_RTC,
 	DO_IRONGATE_IO,
-	DO_IRONGATE_BUS,
 	.machine_check		= nautilus_machine_check,
 	.max_isa_dma_address	= ALPHA_MAX_ISA_DMA_ADDRESS,
 	.min_io_address		= DEFAULT_IO_BASE,
diff -Nru a/arch/alpha/kernel/sys_noritake.c b/arch/alpha/kernel/sys_noritake.c
--- a/arch/alpha/kernel/sys_noritake.c	2004-10-18 14:56:18 -07:00
+++ b/arch/alpha/kernel/sys_noritake.c	2004-10-18 14:56:18 -07:00
@@ -303,7 +303,6 @@
 	DO_EV4_MMU,
 	DO_DEFAULT_RTC,
 	DO_APECS_IO,
-	DO_APECS_BUS,
 	.machine_check		= noritake_apecs_machine_check,
 	.max_isa_dma_address	= ALPHA_MAX_ISA_DMA_ADDRESS,
 	.min_io_address		= EISA_DEFAULT_IO_BASE,
@@ -328,7 +327,6 @@
 	DO_EV5_MMU,
 	DO_DEFAULT_RTC,
 	DO_CIA_IO,
-	DO_CIA_BUS,
 	.machine_check		= cia_machine_check,
 	.max_isa_dma_address	= ALPHA_MAX_ISA_DMA_ADDRESS,
 	.min_io_address		= EISA_DEFAULT_IO_BASE,
diff -Nru a/arch/alpha/kernel/sys_rawhide.c b/arch/alpha/kernel/sys_rawhide.c
--- a/arch/alpha/kernel/sys_rawhide.c	2004-10-18 14:57:03 -07:00
+++ b/arch/alpha/kernel/sys_rawhide.c	2004-10-18 14:57:03 -07:00
@@ -250,7 +250,6 @@
 	DO_EV5_MMU,
 	DO_DEFAULT_RTC,
 	DO_MCPCIA_IO,
-	DO_MCPCIA_BUS,
 	.machine_check		= mcpcia_machine_check,
 	.max_isa_dma_address	= ALPHA_MAX_ISA_DMA_ADDRESS,
 	.min_io_address		= DEFAULT_IO_BASE,
diff -Nru a/arch/alpha/kernel/sys_ruffian.c b/arch/alpha/kernel/sys_ruffian.c
--- a/arch/alpha/kernel/sys_ruffian.c	2004-10-18 14:56:33 -07:00
+++ b/arch/alpha/kernel/sys_ruffian.c	2004-10-18 14:56:33 -07:00
@@ -220,7 +220,6 @@
 	DO_EV5_MMU,
 	DO_DEFAULT_RTC,
 	DO_PYXIS_IO,
-	DO_CIA_BUS,
 	.machine_check		= cia_machine_check,
 	.max_isa_dma_address	= ALPHA_RUFFIAN_MAX_ISA_DMA_ADDRESS,
 	.min_io_address		= DEFAULT_IO_BASE,
diff -Nru a/arch/alpha/kernel/sys_rx164.c b/arch/alpha/kernel/sys_rx164.c
--- a/arch/alpha/kernel/sys_rx164.c	2004-10-18 14:55:53 -07:00
+++ b/arch/alpha/kernel/sys_rx164.c	2004-10-18 14:55:53 -07:00
@@ -201,7 +201,6 @@
 	DO_EV5_MMU,
 	DO_DEFAULT_RTC,
 	DO_POLARIS_IO,
-	DO_POLARIS_BUS,
 	.machine_check		= polaris_machine_check,
 	.max_isa_dma_address	= ALPHA_MAX_ISA_DMA_ADDRESS,
 	.min_io_address		= DEFAULT_IO_BASE,
diff -Nru a/arch/alpha/kernel/sys_sable.c b/arch/alpha/kernel/sys_sable.c
--- a/arch/alpha/kernel/sys_sable.c	2004-10-18 14:55:54 -07:00
+++ b/arch/alpha/kernel/sys_sable.c	2004-10-18 14:55:54 -07:00
@@ -566,7 +566,6 @@
 	DO_EV4_MMU,
 	DO_DEFAULT_RTC,
 	DO_T2_IO,
-	DO_T2_BUS,
 	.machine_check		= t2_machine_check,
 	.max_isa_dma_address	= ALPHA_SABLE_MAX_ISA_DMA_ADDRESS,
 	.min_io_address		= EISA_DEFAULT_IO_BASE,
@@ -599,7 +598,6 @@
 	DO_EV5_MMU,
 	DO_DEFAULT_RTC,
 	DO_T2_IO,
-	DO_T2_BUS,
 	.machine_check		= t2_machine_check,
 	.max_isa_dma_address	= ALPHA_SABLE_MAX_ISA_DMA_ADDRESS,
 	.min_io_address		= EISA_DEFAULT_IO_BASE,
@@ -631,7 +629,6 @@
 	DO_EV4_MMU,
 	DO_DEFAULT_RTC,
 	DO_T2_IO,
-	DO_T2_BUS,
 	.machine_check		= t2_machine_check,
 	.max_isa_dma_address	= ALPHA_SABLE_MAX_ISA_DMA_ADDRESS,
 	.min_io_address		= EISA_DEFAULT_IO_BASE,
diff -Nru a/arch/alpha/kernel/sys_sio.c b/arch/alpha/kernel/sys_sio.c
--- a/arch/alpha/kernel/sys_sio.c	2004-10-18 14:55:54 -07:00
+++ b/arch/alpha/kernel/sys_sio.c	2004-10-18 14:55:54 -07:00
@@ -288,7 +288,6 @@
 	DO_EV4_MMU,
 	DO_DEFAULT_RTC,
 	DO_LCA_IO,
-	DO_LCA_BUS,
 	.machine_check		= lca_machine_check,
 	.max_isa_dma_address	= ALPHA_MAX_ISA_DMA_ADDRESS,
 	.min_io_address		= DEFAULT_IO_BASE,
@@ -319,7 +318,6 @@
 	DO_EV4_MMU,
 	DO_DEFAULT_RTC,
 	DO_APECS_IO,
-	DO_APECS_BUS,
 	.machine_check		= apecs_machine_check,
 	.max_isa_dma_address	= ALPHA_MAX_ISA_DMA_ADDRESS,
 	.min_io_address		= DEFAULT_IO_BASE,
@@ -349,7 +347,6 @@
 	DO_EV4_MMU,
 	DO_DEFAULT_RTC,
 	DO_LCA_IO,
-	DO_LCA_BUS,
 	.machine_check		= lca_machine_check,
 	.max_isa_dma_address	= ALPHA_MAX_ISA_DMA_ADDRESS,
 	.min_io_address		= DEFAULT_IO_BASE,
@@ -388,7 +385,6 @@
 	DO_EV4_MMU,
 	DO_DEFAULT_RTC,
 	DO_LCA_IO,
-	DO_LCA_BUS,
 	.machine_check		= lca_machine_check,
 	.max_isa_dma_address	= ALPHA_MAX_ISA_DMA_ADDRESS,
 	.min_io_address		= DEFAULT_IO_BASE,
@@ -418,7 +414,6 @@
 	DO_EV4_MMU,
 	DO_DEFAULT_RTC,
 	DO_APECS_IO,
-	BUS(apecs),
 	.machine_check		= apecs_machine_check,
 	.max_isa_dma_address	= ALPHA_XL_MAX_ISA_DMA_ADDRESS,
 	.min_io_address		= DEFAULT_IO_BASE,
diff -Nru a/arch/alpha/kernel/sys_sx164.c b/arch/alpha/kernel/sys_sx164.c
--- a/arch/alpha/kernel/sys_sx164.c	2004-10-18 14:56:29 -07:00
+++ b/arch/alpha/kernel/sys_sx164.c	2004-10-18 14:56:29 -07:00
@@ -158,7 +158,6 @@
 	DO_EV5_MMU,
 	DO_DEFAULT_RTC,
 	DO_PYXIS_IO,
-	DO_CIA_BUS,
 	.machine_check		= cia_machine_check,
 	.max_isa_dma_address	= ALPHA_MAX_ISA_DMA_ADDRESS,
 	.min_io_address		= DEFAULT_IO_BASE,
diff -Nru a/arch/alpha/kernel/sys_takara.c b/arch/alpha/kernel/sys_takara.c
--- a/arch/alpha/kernel/sys_takara.c	2004-10-18 14:57:19 -07:00
+++ b/arch/alpha/kernel/sys_takara.c	2004-10-18 14:57:19 -07:00
@@ -277,7 +277,6 @@
 	DO_EV5_MMU,
 	DO_DEFAULT_RTC,
 	DO_CIA_IO,
-	DO_CIA_BUS,
 	.machine_check		= cia_machine_check,
 	.max_isa_dma_address	= ALPHA_MAX_ISA_DMA_ADDRESS,
 	.min_io_address		= DEFAULT_IO_BASE,
diff -Nru a/arch/alpha/kernel/sys_titan.c b/arch/alpha/kernel/sys_titan.c
--- a/arch/alpha/kernel/sys_titan.c	2004-10-18 14:57:03 -07:00
+++ b/arch/alpha/kernel/sys_titan.c	2004-10-18 14:57:03 -07:00
@@ -66,7 +66,7 @@
 	register int bcpu = boot_cpuid;
 
 #ifdef CONFIG_SMP
-	register unsigned long cpm = cpu_present_mask;
+	cpumask_t cpm = cpu_present_mask;
 	volatile unsigned long *dim0, *dim1, *dim2, *dim3;
 	unsigned long mask0, mask1, mask2, mask3, dummy;
 
@@ -85,10 +85,10 @@
 	dim1 = &cchip->dim1.csr;
 	dim2 = &cchip->dim2.csr;
 	dim3 = &cchip->dim3.csr;
-	if ((cpm & 1) == 0) dim0 = &dummy;
-	if ((cpm & 2) == 0) dim1 = &dummy;
-	if ((cpm & 4) == 0) dim2 = &dummy;
-	if ((cpm & 8) == 0) dim3 = &dummy;
+	if (!cpu_isset(0, cpm)) dim0 = &dummy;
+	if (!cpu_isset(1, cpm)) dim1 = &dummy;
+	if (!cpu_isset(2, cpm)) dim2 = &dummy;
+	if (!cpu_isset(3, cpm)) dim3 = &dummy;
 
 	*dim0 = mask0;
 	*dim1 = mask1;
@@ -145,12 +145,12 @@
 }
 
 static void
-titan_cpu_set_irq_affinity(unsigned int irq, unsigned long affinity)
+titan_cpu_set_irq_affinity(unsigned int irq, cpumask_t affinity)
 {
 	int cpu;
 
 	for (cpu = 0; cpu < 4; cpu++) {
-		if (affinity & (1UL << cpu))
+		if (cpu_isset(cpu, affinity))
 			titan_cpu_irq_affinity[cpu] |= 1UL << irq;
 		else
 			titan_cpu_irq_affinity[cpu] &= ~(1UL << irq);
@@ -159,7 +159,7 @@
 }
 
 static void
-titan_set_irq_affinity(unsigned int irq, unsigned long affinity)
+titan_set_irq_affinity(unsigned int irq, cpumask_t affinity)
 { 
 	spin_lock(&titan_irq_lock);
 	titan_cpu_set_irq_affinity(irq - 16, affinity);
@@ -369,7 +369,6 @@
 	DO_EV6_MMU,
 	DO_DEFAULT_RTC,
 	DO_TITAN_IO,
-	DO_TITAN_BUS,
 	.machine_check		= titan_machine_check,
 	.max_isa_dma_address	= ALPHA_MAX_ISA_DMA_ADDRESS,
 	.min_io_address		= DEFAULT_IO_BASE,
@@ -397,7 +396,6 @@
 	DO_EV6_MMU,
 	DO_DEFAULT_RTC,
 	DO_TITAN_IO,
-	DO_TITAN_BUS,
 	.machine_check		= privateer_machine_check,
 	.max_isa_dma_address	= ALPHA_MAX_ISA_DMA_ADDRESS,
 	.min_io_address		= DEFAULT_IO_BASE,
diff -Nru a/arch/alpha/kernel/sys_wildfire.c b/arch/alpha/kernel/sys_wildfire.c
--- a/arch/alpha/kernel/sys_wildfire.c	2004-10-18 14:56:29 -07:00
+++ b/arch/alpha/kernel/sys_wildfire.c	2004-10-18 14:56:29 -07:00
@@ -337,7 +337,6 @@
 	DO_EV6_MMU,
 	DO_DEFAULT_RTC,
 	DO_WILDFIRE_IO,
-	DO_WILDFIRE_BUS,
 	.machine_check		= wildfire_machine_check,
 	.max_isa_dma_address	= ALPHA_MAX_ISA_DMA_ADDRESS,
 	.min_io_address		= DEFAULT_IO_BASE,
diff -Nru a/arch/alpha/kernel/systbls.S b/arch/alpha/kernel/systbls.S
--- a/arch/alpha/kernel/systbls.S	2004-10-18 14:56:33 -07:00
+++ b/arch/alpha/kernel/systbls.S	2004-10-18 14:56:33 -07:00
@@ -457,6 +457,7 @@
 	.quad sys_mq_timedreceive		/* 435 */
 	.quad sys_mq_notify
 	.quad sys_mq_getsetattr
+	.quad sys_waitid
 
 	.size sys_call_table, . - sys_call_table
 	.type sys_call_table, @object
diff -Nru a/arch/alpha/kernel/time.c b/arch/alpha/kernel/time.c
--- a/arch/alpha/kernel/time.c	2004-10-18 14:56:32 -07:00
+++ b/arch/alpha/kernel/time.c	2004-10-18 14:56:32 -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/traps.c b/arch/alpha/kernel/traps.c
--- a/arch/alpha/kernel/traps.c	2004-10-18 14:56:49 -07:00
+++ b/arch/alpha/kernel/traps.c	2004-10-18 14:56:49 -07:00
@@ -65,6 +65,8 @@
 {
 	printk("pc = [<%016lx>]  ra = [<%016lx>]  ps = %04lx    %s\n",
 	       regs->pc, regs->r26, regs->ps, print_tainted());
+	print_symbol("pc is at %s\n", regs->pc);
+	print_symbol("ra is at %s\n", regs->r26 );
 	printk("v0 = %016lx  t0 = %016lx  t1 = %016lx\n",
 	       regs->r0, regs->r1, regs->r2);
 	printk("t2 = %016lx  t3 = %016lx  t4 = %016lx\n",
@@ -109,7 +111,7 @@
 	printk("Code:");
 	for (i = -6; i < 2; i++) {
 		unsigned int insn;
-		if (__get_user(insn, pc+i))
+		if (__get_user(insn, (unsigned int __user *)pc + i))
 			break;
 		printk("%c%08x%c", i ? ' ' : '<', insn, i ? ' ' : '>');
 	}
diff -Nru a/arch/alpha/kernel/vmlinux.lds.S b/arch/alpha/kernel/vmlinux.lds.S
--- a/arch/alpha/kernel/vmlinux.lds.S	2004-10-18 14:56:32 -07:00
+++ b/arch/alpha/kernel/vmlinux.lds.S	2004-10-18 14:56:32 -07:00
@@ -18,6 +18,7 @@
   .text : { 
 	*(.text) 
 	SCHED_TEXT
+	LOCK_TEXT
 	*(.fixup)
 	*(.gnu.warning)
   } :kernel
@@ -44,11 +45,6 @@
   __setup_start = .;
   .init.setup : { *(.init.setup) }
   __setup_end = .;
-
-  . = ALIGN(8);
-  __start___param = .;
-  __param : { *(__param) }
-  __stop___param = .;
 
   . = ALIGN(8);
   __initcall_start = .;
diff -Nru a/arch/alpha/lib/Makefile b/arch/alpha/lib/Makefile
--- a/arch/alpha/lib/Makefile	2004-10-18 14:57:04 -07:00
+++ b/arch/alpha/lib/Makefile	2004-10-18 14:57:04 -07:00
@@ -17,7 +17,6 @@
 	$(ev6-y)memset.o \
 	$(ev6-y)memcpy.o \
 	memmove.o \
-	io.o \
 	checksum.o \
 	csum_partial_copy.o \
 	$(ev67-y)strlen.o \
diff -Nru a/arch/alpha/lib/csum_partial_copy.c b/arch/alpha/lib/csum_partial_copy.c
--- a/arch/alpha/lib/csum_partial_copy.c	2004-10-18 14:56:31 -07:00
+++ b/arch/alpha/lib/csum_partial_copy.c	2004-10-18 14:56:31 -07:00
@@ -193,7 +193,8 @@
  * This is slightly less fun than the above..
  */
 static inline unsigned long
-csum_partial_cfu_src_aligned(const unsigned long *src, unsigned long *dst,
+csum_partial_cfu_src_aligned(const unsigned long __user *src,
+			     unsigned long *dst,
 			     unsigned long doff,
 			     long len, unsigned long checksum,
 			     unsigned long partial_dest,
@@ -372,7 +373,7 @@
 csum_partial_copy_from_user(const char __user *src, char *dst, int len,
 			    unsigned int sum, int *errp)
 {
-	if (!access_ok(src, len, VERIFY_READ)) {
+	if (!access_ok(VERIFY_READ, src, len)) {
 		*errp = -EFAULT;
 		memset(dst, 0, len);
 		return sum;
diff -Nru a/arch/alpha/lib/io.c b/arch/alpha/lib/io.c
--- a/arch/alpha/lib/io.c	2004-10-18 14:56:49 -07:00
+++ /dev/null	Wed Dec 31 16:00:00 196900
@@ -1,594 +0,0 @@
-/*
- * Alpha IO and memory functions.. Just expand the inlines in the header
- * files..
- */
-
-#include <linux/kernel.h>
-#include <linux/types.h>
-#include <linux/string.h>
-
-#include <asm/io.h>
-
-u8 _inb(unsigned long addr)
-{
-	return __inb(addr);
-}
-
-u16 _inw(unsigned long addr)
-{
-	return __inw(addr);
-}
-
-u32 _inl(unsigned long addr)
-{
-	return __inl(addr);
-}
-
-
-void _outb(u8 b, unsigned long addr)
-{
-	__outb(b, addr);
-}
-
-void _outw(u16 b, unsigned long addr)
-{
-	__outw(b, addr);
-}
-
-void _outl(u32 b, unsigned long addr)
-{
-	__outl(b, addr);
-}
-
-u8 ___raw_readb(unsigned long addr)
-{
-	return __readb(addr);
-}
-
-u16 ___raw_readw(unsigned long addr)
-{
-	return __readw(addr);
-}
-
-u32 ___raw_readl(unsigned long addr)
-{
-	return __readl(addr);
-}
-
-u64 ___raw_readq(unsigned long addr)
-{
-	return __readq(addr);
-}
-
-u8 _readb(unsigned long addr)
-{
-	unsigned long r = __readb(addr);
-	mb();
-	return r;
-}
-
-u16 _readw(unsigned long addr)
-{
-	unsigned long r = __readw(addr);
-	mb();
-	return r;
-}
-
-u32 _readl(unsigned long addr)
-{
-	unsigned long r = __readl(addr);
-	mb();
-	return r;
-}
-
-u64 _readq(unsigned long addr)
-{
-	unsigned long r = __readq(addr);
-	mb();
-	return r;
-}
-
-void ___raw_writeb(u8 b, unsigned long addr)
-{
-	__writeb(b, addr);
-}
-
-void ___raw_writew(u16 b, unsigned long addr)
-{
-	__writew(b, addr);
-}
-
-void ___raw_writel(u32 b, unsigned long addr)
-{
-	__writel(b, addr);
-}
-
-void ___raw_writeq(u64 b, unsigned long addr)
-{
-	__writeq(b, addr);
-}
-
-void _writeb(u8 b, unsigned long addr)
-{
-	__writeb(b, addr);
-	mb();
-}
-
-void _writew(u16 b, unsigned long addr)
-{
-	__writew(b, addr);
-	mb();
-}
-
-void _writel(u32 b, unsigned long addr)
-{
-	__writel(b, addr);
-	mb();
-}
-
-void _writeq(u64 b, unsigned long addr)
-{
-	__writeq(b, addr);
-	mb();
-}
-
-/*
- * Read COUNT 8-bit bytes from port PORT into memory starting at
- * SRC.
- */
-void insb (unsigned long port, void *dst, unsigned long count)
-{
-	while (((unsigned long)dst) & 0x3) {
-		if (!count)
-			return;
-		count--;
-		*(unsigned char *) dst = inb(port);
-		dst += 1;
-	}
-
-	while (count >= 4) {
-		unsigned int w;
-		count -= 4;
-		w = inb(port);
-		w |= inb(port) << 8;
-		w |= inb(port) << 16;
-		w |= inb(port) << 24;
-		*(unsigned int *) dst = w;
-		dst += 4;
-	}
-
-	while (count) {
-		--count;
-		*(unsigned char *) dst = inb(port);
-		dst += 1;
-	}
-}
-
-
-/*
- * Read COUNT 16-bit words from port PORT into memory starting at
- * SRC.  SRC must be at least short aligned.  This is used by the
- * IDE driver to read disk sectors.  Performance is important, but
- * the interfaces seems to be slow: just using the inlined version
- * of the inw() breaks things.
- */
-void insw (unsigned long port, void *dst, unsigned long count)
-{
-	if (((unsigned long)dst) & 0x3) {
-		if (((unsigned long)dst) & 0x1) {
-			panic("insw: memory not short aligned");
-		}
-		if (!count)
-			return;
-		count--;
-		*(unsigned short *) dst = inw(port);
-		dst += 2;
-	}
-
-	while (count >= 2) {
-		unsigned int w;
-		count -= 2;
-		w = inw(port);
-		w |= inw(port) << 16;
-		*(unsigned int *) dst = w;
-		dst += 4;
-	}
-
-	if (count) {
-		*(unsigned short*) dst = inw(port);
-	}
-}
-
-
-/*
- * Read COUNT 32-bit words from port PORT into memory starting at
- * SRC. Now works with any alignment in SRC. Performance is important,
- * but the interfaces seems to be slow: just using the inlined version
- * of the inl() breaks things.
- */
-void insl (unsigned long port, void *dst, unsigned long count)
-{
-	unsigned int l = 0, l2;
-
-	if (!count)
-		return;
-
-	switch (((unsigned long) dst) & 0x3)
-	{
-	 case 0x00:			/* Buffer 32-bit aligned */
-		while (count--)
-		{
-			*(unsigned int *) dst = inl(port);
-			dst += 4;
-		}
-		break;
-
-	/* Assuming little endian Alphas in cases 0x01 -- 0x03 ... */
-
-	 case 0x02:			/* Buffer 16-bit aligned */
-		--count;
-
-		l = inl(port);
-		*(unsigned short *) dst = l;
-		dst += 2;
-
-		while (count--)
-		{
-			l2 = inl(port);
-			*(unsigned int *) dst = l >> 16 | l2 << 16;
-			dst += 4;
-			l = l2;
-		}
-		*(unsigned short *) dst = l >> 16;
-		break;
-
-	 case 0x01:			/* Buffer 8-bit aligned */
-		--count;
-
-		l = inl(port);
-		*(unsigned char *) dst = l;
-		dst += 1;
-		*(unsigned short *) dst = l >> 8;
-		dst += 2;
-		while (count--)
-		{
-			l2 = inl(port);
-			*(unsigned int *) dst = l >> 24 | l2 << 8;
-			dst += 4;
-			l = l2;
-		}
-		*(unsigned char *) dst = l >> 24;
-		break;
-
-	 case 0x03:			/* Buffer 8-bit aligned */
-		--count;
-
-		l = inl(port);
-		*(unsigned char *) dst = l;
-		dst += 1;
-		while (count--)
-		{
-			l2 = inl(port);
-			*(unsigned int *) dst = l << 24 | l2 >> 8;
-			dst += 4;
-			l = l2;
-		}
-		*(unsigned short *) dst = l >> 8;
-		dst += 2;
-		*(unsigned char *) dst = l >> 24;
-		break;
-	}
-}
-
-
-/*
- * Like insb but in the opposite direction.
- * Don't worry as much about doing aligned memory transfers:
- * doing byte reads the "slow" way isn't nearly as slow as
- * doing byte writes the slow way (no r-m-w cycle).
- */
-void outsb(unsigned long port, const void * src, unsigned long count)
-{
-	while (count) {
-		count--;
-		outb(*(char *)src, port);
-		src += 1;
-	}
-}
-
-/*
- * Like insw but in the opposite direction.  This is used by the IDE
- * driver to write disk sectors.  Performance is important, but the
- * interfaces seems to be slow: just using the inlined version of the
- * outw() breaks things.
- */
-void outsw (unsigned long port, const void *src, unsigned long count)
-{
-	if (((unsigned long)src) & 0x3) {
-		if (((unsigned long)src) & 0x1) {
-			panic("outsw: memory not short aligned");
-		}
-		outw(*(unsigned short*)src, port);
-		src += 2;
-		--count;
-	}
-
-	while (count >= 2) {
-		unsigned int w;
-		count -= 2;
-		w = *(unsigned int *) src;
-		src += 4;
-		outw(w >>  0, port);
-		outw(w >> 16, port);
-	}
-
-	if (count) {
-		outw(*(unsigned short *) src, port);
-	}
-}
-
-
-/*
- * Like insl but in the opposite direction.  This is used by the IDE
- * driver to write disk sectors.  Works with any alignment in SRC.
- *  Performance is important, but the interfaces seems to be slow:
- * just using the inlined version of the outl() breaks things.
- */
-void outsl (unsigned long port, const void *src, unsigned long count)
-{
-	unsigned int l = 0, l2;
-
-	if (!count)
-		return;
-
-	switch (((unsigned long) src) & 0x3)
-	{
-	 case 0x00:			/* Buffer 32-bit aligned */
-		while (count--)
-		{
-			outl(*(unsigned int *) src, port);
-			src += 4;
-		}
-		break;
-
-	 case 0x02:			/* Buffer 16-bit aligned */
-		--count;
-
-		l = *(unsigned short *) src << 16;
-		src += 2;
-
-		while (count--)
-		{
-			l2 = *(unsigned int *) src;
-			src += 4;
-			outl (l >> 16 | l2 << 16, port);
-			l = l2;
-		}
-		l2 = *(unsigned short *) src;
-		outl (l >> 16 | l2 << 16, port);
-		break;
-
-	 case 0x01:			/* Buffer 8-bit aligned */
-		--count;
-
-		l  = *(unsigned char *) src << 8;
-		src += 1;
-		l |= *(unsigned short *) src << 16;
-		src += 2;
-		while (count--)
-		{
-			l2 = *(unsigned int *) src;
-			src += 4;
-			outl (l >> 8 | l2 << 24, port);
-			l = l2;
-		}
-		l2 = *(unsigned char *) src;
-		outl (l >> 8 | l2 << 24, port);
-		break;
-
-	 case 0x03:			/* Buffer 8-bit aligned */
-		--count;
-
-		l  = *(unsigned char *) src << 24;
-		src += 1;
-		while (count--)
-		{
-			l2 = *(unsigned int *) src;
-			src += 4;
-			outl (l >> 24 | l2 << 8, port);
-			l = l2;
-		}
-		l2  = *(unsigned short *) src;
-		src += 2;
-		l2 |= *(unsigned char *) src << 16;
-		outl (l >> 24 | l2 << 8, port);
-		break;
-	}
-}
-
-
-/*
- * Copy data from IO memory space to "real" memory space.
- * This needs to be optimized.
- */
-void _memcpy_fromio(void * to, unsigned long from, long count)
-{
-	/* Optimize co-aligned transfers.  Everything else gets handled
-	   a byte at a time. */
-
-	if (count >= 8 && ((unsigned long)to & 7) == (from & 7)) {
-		count -= 8;
-		do {
-			*(u64 *)to = __raw_readq(from);
-			count -= 8;
-			to += 8;
-			from += 8;
-		} while (count >= 0);
-		count += 8;
-	}
-
-	if (count >= 4 && ((unsigned long)to & 3) == (from & 3)) {
-		count -= 4;
-		do {
-			*(u32 *)to = __raw_readl(from);
-			count -= 4;
-			to += 4;
-			from += 4;
-		} while (count >= 0);
-		count += 4;
-	}
-
-	if (count >= 2 && ((unsigned long)to & 1) == (from & 1)) {
-		count -= 2;
-		do {
-			*(u16 *)to = __raw_readw(from);
-			count -= 2;
-			to += 2;
-			from += 2;
-		} while (count >= 0);
-		count += 2;
-	}
-
-	while (count > 0) {
-		*(u8 *) to = __raw_readb(from);
-		count--;
-		to++;
-		from++;
-	}
-}
-
-/*
- * Copy data from "real" memory space to IO memory space.
- * This needs to be optimized.
- */
-void _memcpy_toio(unsigned long to, const void * from, long count)
-{
-	/* Optimize co-aligned transfers.  Everything else gets handled
-	   a byte at a time. */
-	/* FIXME -- align FROM.  */
-
-	if (count >= 8 && (to & 7) == ((unsigned long)from & 7)) {
-		count -= 8;
-		do {
-			__raw_writeq(*(const u64 *)from, to);
-			count -= 8;
-			to += 8;
-			from += 8;
-		} while (count >= 0);
-		count += 8;
-	}
-
-	if (count >= 4 && (to & 3) == ((unsigned long)from & 3)) {
-		count -= 4;
-		do {
-			__raw_writel(*(const u32 *)from, to);
-			count -= 4;
-			to += 4;
-			from += 4;
-		} while (count >= 0);
-		count += 4;
-	}
-
-	if (count >= 2 && (to & 1) == ((unsigned long)from & 1)) {
-		count -= 2;
-		do {
-			__raw_writew(*(const u16 *)from, to);
-			count -= 2;
-			to += 2;
-			from += 2;
-		} while (count >= 0);
-		count += 2;
-	}
-
-	while (count > 0) {
-		__raw_writeb(*(const u8 *) from, to);
-		count--;
-		to++;
-		from++;
-	}
-	mb();
-}
-
-/*
- * "memset" on IO memory space.
- */
-void _memset_c_io(unsigned long to, unsigned long c, long count)
-{
-	/* Handle any initial odd byte */
-	if (count > 0 && (to & 1)) {
-		__raw_writeb(c, to);
-		to++;
-		count--;
-	}
-
-	/* Handle any initial odd halfword */
-	if (count >= 2 && (to & 2)) {
-		__raw_writew(c, to);
-		to += 2;
-		count -= 2;
-	}
-
-	/* Handle any initial odd word */
-	if (count >= 4 && (to & 4)) {
-		__raw_writel(c, to);
-		to += 4;
-		count -= 4;
-	}
-
-	/* Handle all full-sized quadwords: we're aligned
-	   (or have a small count) */
-	count -= 8;
-	if (count >= 0) {
-		do {
-			__raw_writeq(c, to);
-			to += 8;
-			count -= 8;
-		} while (count >= 0);
-	}
-	count += 8;
-
-	/* The tail is word-aligned if we still have count >= 4 */
-	if (count >= 4) {
-		__raw_writel(c, to);
-		to += 4;
-		count -= 4;
-	}
-
-	/* The tail is half-word aligned if we have count >= 2 */
-	if (count >= 2) {
-		__raw_writew(c, to);
-		to += 2;
-		count -= 2;
-	}
-
-	/* And finally, one last byte.. */
-	if (count) {
-		__raw_writeb(c, to);
-	}
-	mb();
-}
-
-void
-scr_memcpyw(u16 *d, const u16 *s, unsigned int count)
-{
-	if (! __is_ioaddr((unsigned long) s)) {
-		/* Source is memory.  */
-		if (! __is_ioaddr((unsigned long) d))
-			memcpy(d, s, count);
-		else
-			memcpy_toio(d, s, count);
-	} else {
-		/* Source is screen.  */
-		if (! __is_ioaddr((unsigned long) d))
-			memcpy_fromio(d, s, count);
-		else {
-			/* FIXME: Should handle unaligned ops and
-			   operation widening.  */
-			count /= 2;
-			while (count--) {
-				u16 tmp = __raw_readw((unsigned long)(s++));
-				__raw_writew(tmp, (unsigned long)(d++));
-			}
-		}
-	}
-}
diff -Nru a/arch/alpha/mm/fault.c b/arch/alpha/mm/fault.c
--- a/arch/alpha/mm/fault.c	2004-10-18 14:56:27 -07:00
+++ b/arch/alpha/mm/fault.c	2004-10-18 14:56:27 -07:00
@@ -98,7 +98,7 @@
 	   by ignoring such an instruction.  */
 	if (cause == 0) {
 		unsigned int insn;
-		__get_user(insn, (unsigned int *)regs->pc);
+		__get_user(insn, (unsigned int __user *)regs->pc);
 		if ((insn >> 21 & 0x1f) == 0x1f &&
 		    /* ldq ldl ldt lds ldg ldf ldwu ldbu */
 		    (1ul << (insn >> 26) & 0x30f00001400ul)) {
diff -Nru a/arch/alpha/mm/numa.c b/arch/alpha/mm/numa.c
--- a/arch/alpha/mm/numa.c	2004-10-18 14:55:54 -07:00
+++ b/arch/alpha/mm/numa.c	2004-10-18 14:55:54 -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-10-18 14:56:32 -07:00
+++ b/arch/arm/Kconfig	2004-10-18 14:56:32 -07:00
@@ -63,8 +63,11 @@
 config GENERIC_ISA_DMA
 	bool
 
-source "init/Kconfig"
+config GENERIC_IOMAP
+	bool
+	default y
 
+source "init/Kconfig"
 
 menu "System Type"
 
@@ -108,6 +111,9 @@
 config ARCH_IXP4XX
 	bool "IXP4xx-based"
 
+config ARCH_IXP2000
+	bool "IXP2400/2800-based"
+
 config ARCH_L7200
 	bool "LinkUp-L7200"
 	help
@@ -158,6 +164,14 @@
 	help
 	  This enables support for ARM Ltd Versatile PB board.
 
+config ARCH_IMX
+	bool "IMX"
+
+config ARCH_H720X
+	bool "Hynix-HMS720x-based"
+	help
+	  This enables support for systems based on the Hynix HMS720x
+
 endchoice
 
 source "arch/arm/mach-clps711x/Kconfig"
@@ -172,6 +186,8 @@
 
 source "arch/arm/mach-ixp4xx/Kconfig"
 
+source "arch/arm/mach-ixp2000/Kconfig"
+
 source "arch/arm/mach-pxa/Kconfig"
 
 source "arch/arm/mach-sa1100/Kconfig"
@@ -182,6 +198,10 @@
 
 source "arch/arm/mach-lh7a40x/Kconfig"
 
+source "arch/arm/mach-imx/Kconfig"
+
+source "arch/arm/mach-h720x/Kconfig"
+
 # Definitions to make life easier
 config ARCH_ACORN
 	bool
@@ -247,7 +267,6 @@
 
 endmenu
 
-
 menu "General setup"
 
 # Select various configuration options depending on the machine type
@@ -264,7 +283,7 @@
 # Now handle the bus types
 config PCI
 	bool "PCI support" if ARCH_INTEGRATOR_AP
-	default y if ARCH_SHARK || FOOTBRIDGE_HOST || ARCH_IOP3XX || ARCH_IXP4XX
+	default y if ARCH_SHARK || FOOTBRIDGE_HOST || ARCH_IOP3XX || ARCH_IXP4XX || ARCH_IXP2000
 	help
 	  Find out whether you have a PCI motherboard. PCI is the name of a
 	  bus system, i.e. the way the CPU talks to the other stuff inside
@@ -294,7 +313,7 @@
 
 config ISA
 	bool
-	depends on FOOTBRIDGE_HOST || ARCH_SHARK || ARCH_CLPS7500 || ARCH_EBSA110 || ARCH_CDB89712 || ARCH_EDB7211 || ARCH_SA1100
+	depends on FOOTBRIDGE_HOST || ARCH_SHARK || ARCH_CLPS7500 || ARCH_EBSA110 || ARCH_CDB89712 || ARCH_EDB7211 || ARCH_SA1100 || ARCH_MX1ADS
 	default y
 	help
 	  Find out whether you have ISA slots on your motherboard.  ISA is the
@@ -399,7 +418,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.
@@ -425,6 +444,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.
@@ -552,7 +572,7 @@
 
 config LEDS
 	bool "Timer and CPU usage LEDs"
-	depends on ARCH_NETWINDER || ARCH_EBSA110 || ARCH_EBSA285 || ARCH_SHARK || ARCH_CO285 || ARCH_SA1100 || ARCH_LUBBOCK || MACH_MAINSTONE || ARCH_PXA_IDP || ARCH_INTEGRATOR || ARCH_CDB89712 || ARCH_P720T || ARCH_OMAP || ARCH_VERSATILE_PB
+	depends on ARCH_NETWINDER || ARCH_EBSA110 || ARCH_EBSA285 || ARCH_SHARK || ARCH_CO285 || ARCH_SA1100 || ARCH_LUBBOCK || MACH_MAINSTONE || ARCH_PXA_IDP || ARCH_INTEGRATOR || ARCH_CDB89712 || ARCH_P720T || ARCH_OMAP || ARCH_VERSATILE_PB || ARCH_IMX
 	help
 	  If you say Y here, the LEDs on your machine will be used
 	  to provide useful information about your current system status.
@@ -565,8 +585,8 @@
 	  system, but the driver will do nothing.
 
 config LEDS_TIMER
-	bool "Timer LED" if LEDS && (ARCH_NETWINDER || ARCH_EBSA285 || ARCH_SHARK || MACH_MAINSTONE || ARCH_CO285 || ARCH_SA1100 || ARCH_LUBBOCK || ARCH_PXA_IDP || ARCH_INTEGRATOR || ARCH_P720T || ARCH_VERSATILE_PB)
-	depends on ARCH_NETWINDER || ARCH_EBSA110 || ARCH_EBSA285 || ARCH_SHARK || ARCH_CO285 || ARCH_SA1100 || ARCH_LUBBOCK || MACH_MAINSTONE || ARCH_PXA_IDP || ARCH_INTEGRATOR || ARCH_CDB89712 || ARCH_P720T || ARCH_OMAP || ARCH_VERSATILE_PB
+	bool "Timer LED" if LEDS && (ARCH_NETWINDER || ARCH_EBSA285 || ARCH_SHARK || MACH_MAINSTONE || ARCH_CO285 || ARCH_SA1100 || ARCH_LUBBOCK || ARCH_PXA_IDP || ARCH_INTEGRATOR || ARCH_P720T || ARCH_VERSATILE_PB || ARCH_IMX)
+	depends on ARCH_NETWINDER || ARCH_EBSA110 || ARCH_EBSA285 || ARCH_SHARK || ARCH_CO285 || ARCH_SA1100 || ARCH_LUBBOCK || MACH_MAINSTONE || ARCH_PXA_IDP || ARCH_INTEGRATOR || ARCH_CDB89712 || ARCH_P720T || ARCH_OMAP || ARCH_VERSATILE_PB || ARCH_IMX
 	default y if ARCH_EBSA110
 	help
 	  If you say Y here, one of the system LEDs (the green one on the
@@ -581,7 +601,7 @@
 
 config LEDS_CPU
 	bool "CPU usage LED"
-	depends on LEDS && (ARCH_NETWINDER || ARCH_EBSA285 || ARCH_SHARK || ARCH_CO285 || ARCH_SA1100 || ARCH_LUBBOCK || MACH_MAINSTONE || ARCH_PXA_IDP || ARCH_INTEGRATOR || ARCH_P720T || ARCH_VERSATILE_PB)
+	depends on LEDS && (ARCH_NETWINDER || ARCH_EBSA285 || ARCH_SHARK || ARCH_CO285 || ARCH_SA1100 || ARCH_LUBBOCK || MACH_MAINSTONE || ARCH_PXA_IDP || ARCH_INTEGRATOR || ARCH_P720T || ARCH_VERSATILE_PB || ARCH_IMX)
 	help
 	  If you say Y here, the red LED will be used to give a good real
 	  time indication of CPU usage, by lighting whenever the idle task
@@ -661,169 +681,12 @@
 
 source "drivers/usb/Kconfig"
 
+source "drivers/mmc/Kconfig"
 
-menu "Kernel hacking"
-
-# RMK wants arm kernels compiled with frame pointers so hardwire this to y.
-# If you know what you are doing and are willing to live without stack
-# traces, you can get a slightly smaller kernel by setting this option to
-# n, but then RMK will have to kill you ;).
-config FRAME_POINTER
-	bool
-	default y
-	help
-	  If you say N here, the resulting kernel will be slightly smaller and
-	  faster. However, when a problem occurs with the kernel, the
-	  information that is reported is severely limited. Most people
-	  should say Y here.
-
-config DEBUG_USER
-	bool "Verbose user fault messages"
-	help
-	  When a user program crashes due to an exception, the kernel can
-	  print a brief message explaining what the problem was. This is
-	  sometimes helpful for debugging but serves no purpose on a
-	  production system. Most people should say N here.
-
-	  In addition, you need to pass user_debug=N on the kernel command
-	  line to enable this feature.  N consists of the sum of:
-
-	      1 - undefined instruction events
-	      2 - system calls
-	      4 - invalid data aborts
-	      8 - SIGSEGV faults
-	     16 - SIGBUS faults
-
-config DEBUG_INFO
-	bool "Include GDB debugging information in kernel binary"
-	help
-	  Say Y here to include source-level debugging information in the
-	  `vmlinux' binary image. This is handy if you want to use gdb or
-	  addr2line to debug the kernel. It has no impact on the in-memory
-	  footprint of the running kernel but it can increase the amount of
-	  time and disk space needed for compilation of the kernel. If in
-	  doubt say N.
-
-config DEBUG_KERNEL
-	bool "Kernel debugging"
-	help
-	  Say Y here if you are developing drivers or trying to debug and
-	  identify kernel problems.
-
-config DEBUG_SLAB
-	bool "Debug memory allocations"
-	depends on DEBUG_KERNEL
-	help
-	  Say Y here to have the kernel do limited verification on memory
-	  allocation as well as poisoning memory on free to catch use of freed
-	  memory.
-
-config MAGIC_SYSRQ
-	bool "Magic SysRq key"
-	depends on DEBUG_KERNEL
-	help
-	  If you say Y here, you will have some control over the system even
-	  if the system crashes for example during kernel debugging (e.g., you
-	  will be able to flush the buffer cache to disk, reboot the system
-	  immediately or dump some status information). This is accomplished
-	  by pressing various keys while holding SysRq (Alt+PrintScreen). It
-	  also works on a serial console (on PC hardware at least), if you
-	  send a BREAK and then within 5 seconds a command keypress. The
-	  keys are documented in <file:Documentation/sysrq.txt>. Don't say Y
-	  unless you really know what this hack does.
-
-config DEBUG_SPINLOCK
-	bool "Spinlock debugging"
-	depends on DEBUG_KERNEL
-	help
-	  Say Y here and build SMP to catch missing spinlock initialization
-	  and certain other kinds of spinlock errors commonly made.  This is
-	  best used in conjunction with the NMI watchdog so that spinlock
-	  deadlocks are also debuggable.
-
-config DEBUG_WAITQ
-	bool "Wait queue debugging"
-	depends on DEBUG_KERNEL
-
-config DEBUG_BUGVERBOSE
-	bool "Verbose BUG() reporting (adds 70K)"
-	depends on DEBUG_KERNEL
-	help
-	  Say Y here to make BUG() panics output the file name and line number
-	  of the BUG call as well as the EIP and oops trace.  This aids
-	  debugging but costs about 70-100K of memory.
-
-config DEBUG_ERRORS
-	bool "Verbose kernel error messages"
-	depends on DEBUG_KERNEL
-	help
-	  This option controls verbose debugging information which can be
-	  printed when the kernel detects an internal error. This debugging
-	  information is useful to kernel hackers when tracking down problems,
-	  but mostly meaningless to other people. It's safe to say Y unless
-	  you are concerned with the code size or don't want to see these
-	  messages.
-
-# These options are only for real kernel hackers who want to get their hands dirty. 
-config DEBUG_LL
-	bool "Kernel low-level debugging functions"
-	depends on DEBUG_KERNEL
-	help
-	  Say Y here to include definitions of printascii, printchar, printhex
-	  in the kernel.  This is helpful if you are debugging code that
-	  executes before the console is initialized.
-
-config DEBUG_ICEDCC
-	bool "Kernel low-level debugging via EmbeddedICE DCC channel"
-	depends on DEBUG_LL
-	help
-	  Say Y here if you want the debug print routines to direct their
-	  output to the EmbeddedICE macrocell's DCC channel using
-	  co-processor 14. This is known to work on the ARM9 style ICE
-	  channel.
-
-	  It does include a timeout to ensure that the system does not
-	  totally freeze when there is nothing connected to read.
-
-config DEBUG_DC21285_PORT
-	bool "Kernel low-level debugging messages via footbridge serial port"
-	depends on DEBUG_LL && FOOTBRIDGE
-	help
-	  Say Y here if you want the debug print routines to direct their
-	  output to the serial port in the DC21285 (Footbridge). Saying N
-	  will cause the debug messages to appear on the first 16550
-	  serial port.
-
-config DEBUG_CLPS711X_UART2
-	bool "Kernel low-level debugging messages via UART2"
-	depends on DEBUG_LL && ARCH_CLPS711X
-	help
-	  Say Y here if you want the debug print routines to direct their
-	  output to the second serial port on these devices.  Saying N will
-	  cause the debug messages to appear on the first serial port.
-
-config DEBUG_S3C2410_PORT
-	depends on DEBUG_LL && ARCH_S3C2410
-	bool "Kernel low-level debugging messages via S3C2410 UART"
-	help
-	  Say Y here if you want debug print routines to go to one of the
-	  S3C2410 internal UARTs. The chosen UART must have been configured
-	  before it is used.
-
-config DEBUG_S3C2410_UART
-	depends on DEBUG_LL && ARCH_S3C2410
-	int "S3C2410 UART to use for low-level debug"
-	default "0"
-	help
-	  Choice for UART for kernel low-level using S3C2410 UARTS,
-	  should be between zero and two. The port must have been
-	  initalised by the boot-loader before use.
-
-endmenu
+source "arch/arm/Kconfig.debug"
 
 source "security/Kconfig"
 
 source "crypto/Kconfig"
 
 source "lib/Kconfig"
-
diff -Nru a/arch/arm/Kconfig.debug b/arch/arm/Kconfig.debug
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/arch/arm/Kconfig.debug	2004-10-18 14:57:24 -07:00
@@ -0,0 +1,115 @@
+menu "Kernel hacking"
+
+source "lib/Kconfig.debug"
+
+# RMK wants arm kernels compiled with frame pointers so hardwire this to y.
+# If you know what you are doing and are willing to live without stack
+# traces, you can get a slightly smaller kernel by setting this option to
+# n, but then RMK will have to kill you ;).
+config FRAME_POINTER
+	bool
+	default y
+	help
+	  If you say N here, the resulting kernel will be slightly smaller and
+	  faster. However, when a problem occurs with the kernel, the
+	  information that is reported is severely limited. Most people
+	  should say Y here.
+
+config DEBUG_USER
+	bool "Verbose user fault messages"
+	help
+	  When a user program crashes due to an exception, the kernel can
+	  print a brief message explaining what the problem was. This is
+	  sometimes helpful for debugging but serves no purpose on a
+	  production system. Most people should say N here.
+
+	  In addition, you need to pass user_debug=N on the kernel command
+	  line to enable this feature.  N consists of the sum of:
+
+	      1 - undefined instruction events
+	      2 - system calls
+	      4 - invalid data aborts
+	      8 - SIGSEGV faults
+	     16 - SIGBUS faults
+
+config DEBUG_WAITQ
+	bool "Wait queue debugging"
+	depends on DEBUG_KERNEL
+
+config DEBUG_ERRORS
+	bool "Verbose kernel error messages"
+	depends on DEBUG_KERNEL
+	help
+	  This option controls verbose debugging information which can be
+	  printed when the kernel detects an internal error. This debugging
+	  information is useful to kernel hackers when tracking down problems,
+	  but mostly meaningless to other people. It's safe to say Y unless
+	  you are concerned with the code size or don't want to see these
+	  messages.
+
+config DEBUG_INFO
+	bool "Include GDB debugging information in kernel binary"
+	help
+	  Say Y here to include source-level debugging information in the
+	  `vmlinux' binary image. This is handy if you want to use gdb or
+	  addr2line to debug the kernel. It has no impact on the in-memory
+	  footprint of the running kernel but it can increase the amount of
+	  time and disk space needed for compilation of the kernel. If in
+	  doubt say N.
+
+# These options are only for real kernel hackers who want to get their hands dirty.
+config DEBUG_LL
+	bool "Kernel low-level debugging functions"
+	depends on DEBUG_KERNEL
+	help
+	  Say Y here to include definitions of printascii, printchar, printhex
+	  in the kernel.  This is helpful if you are debugging code that
+	  executes before the console is initialized.
+
+config DEBUG_ICEDCC
+	bool "Kernel low-level debugging via EmbeddedICE DCC channel"
+	depends on DEBUG_LL
+	help
+	  Say Y here if you want the debug print routines to direct their
+	  output to the EmbeddedICE macrocell's DCC channel using
+	  co-processor 14. This is known to work on the ARM9 style ICE
+	  channel.
+
+	  It does include a timeout to ensure that the system does not
+	  totally freeze when there is nothing connected to read.
+
+config DEBUG_DC21285_PORT
+	bool "Kernel low-level debugging messages via footbridge serial port"
+	depends on DEBUG_LL && FOOTBRIDGE
+	help
+	  Say Y here if you want the debug print routines to direct their
+	  output to the serial port in the DC21285 (Footbridge). Saying N
+	  will cause the debug messages to appear on the first 16550
+	  serial port.
+
+config DEBUG_CLPS711X_UART2
+	bool "Kernel low-level debugging messages via UART2"
+	depends on DEBUG_LL && ARCH_CLPS711X
+	help
+	  Say Y here if you want the debug print routines to direct their
+	  output to the second serial port on these devices.  Saying N will
+	  cause the debug messages to appear on the first serial port.
+
+config DEBUG_S3C2410_PORT
+	depends on DEBUG_LL && ARCH_S3C2410
+	bool "Kernel low-level debugging messages via S3C2410 UART"
+	help
+	  Say Y here if you want debug print routines to go to one of the
+	  S3C2410 internal UARTs. The chosen UART must have been configured
+	  before it is used.
+
+config DEBUG_S3C2410_UART
+	depends on DEBUG_LL && ARCH_S3C2410
+	int "S3C2410 UART to use for low-level debug"
+	default "0"
+	help
+	  Choice for UART for kernel low-level using S3C2410 UARTS,
+	  should be between zero and two. The port must have been
+	  initalised by the boot-loader before use.
+
+endmenu
diff -Nru a/arch/arm/Makefile b/arch/arm/Makefile
--- a/arch/arm/Makefile	2004-10-18 14:56:28 -07:00
+++ b/arch/arm/Makefile	2004-10-18 14:56:28 -07:00
@@ -8,8 +8,7 @@
 # Copyright (C) 1995-2001 by Russell King
 
 LDFLAGS_vmlinux	:=-p --no-undefined -X
-LDFLAGS_BLOB	:=--format binary
-AFLAGS_vmlinux.lds.o = -DTEXTADDR=$(TEXTADDR) -DDATAADDR=$(DATAADDR)
+CPPFLAGS_vmlinux.lds = -DTEXTADDR=$(TEXTADDR) -DDATAADDR=$(DATAADDR)
 OBJCOPYFLAGS	:=-O binary -R .note -R .comment -S
 GZFLAGS		:=-9
 #CFLAGS		+=-pipe
@@ -36,8 +35,8 @@
 # Note that GCC does not numerically define an architecture version
 # macro, but instead defines a whole series of macros which makes
 # testing for a specific architecture or later rather impossible.
-arch-$(CONFIG_CPU_32v6)		:=-D__LINUX_ARM_ARCH__=6 $(call check_gcc,-march=armv6,-march=armv5t -Wa$(comma)-march=armv6)
-arch-$(CONFIG_CPU_32v5)		:=-D__LINUX_ARM_ARCH__=5 $(call check_gcc,-march=armv5te,-march=armv4)
+arch-$(CONFIG_CPU_32v6)		:=-D__LINUX_ARM_ARCH__=6 $(call cc-option,-march=armv6,-march=armv5t -Wa$(comma)-march=armv6)
+arch-$(CONFIG_CPU_32v5)		:=-D__LINUX_ARM_ARCH__=5 $(call cc-option,-march=armv5te,-march=armv4)
 arch-$(CONFIG_CPU_32v4)		:=-D__LINUX_ARM_ARCH__=4 -march=armv4
 arch-$(CONFIG_CPU_32v3)		:=-D__LINUX_ARM_ARCH__=3 -march=armv3
 
@@ -51,14 +50,14 @@
 tune-$(CONFIG_CPU_ARM926T)	:=-mtune=arm9tdmi
 tune-$(CONFIG_CPU_SA110)	:=-mtune=strongarm110
 tune-$(CONFIG_CPU_SA1100)	:=-mtune=strongarm1100
-tune-$(CONFIG_CPU_XSCALE)	:=$(call check_gcc,-mtune=xscale,-mtune=strongarm110) -Wa,-mcpu=xscale
+tune-$(CONFIG_CPU_XSCALE)	:=$(call cc-option,-mtune=xscale,-mtune=strongarm110) -Wa,-mcpu=xscale
 tune-$(CONFIG_CPU_V6)		:=-mtune=strongarm
 
 # Need -Uarm for gcc < 3.x
-CFLAGS		+=-mapcs-32 $(arch-y) $(tune-y) $(call check_gcc,-malignment-traps,-mshort-load-bytes) -msoft-float -Wa,-mno-fpu -Uarm
-AFLAGS		+=-mapcs-32 $(arch-y) $(tune-y) -msoft-float -Wa,-mno-fpu
+CFLAGS		+=-mapcs-32 $(arch-y) $(tune-y) $(call cc-option,-malignment-traps,-mshort-load-bytes) -msoft-float -Uarm
+AFLAGS		+=-mapcs-32 $(arch-y) $(tune-y) -msoft-float
 
-CHECK		:= $(CHECK) -D__arm__=1
+CHECKFLAGS	+= -D__arm__
 
 #Default value
 DATAADDR	:= .
@@ -90,10 +89,13 @@
 textaddr-$(CONFIG_ARCH_FORTUNET)   := 0xc0008000
  machine-$(CONFIG_ARCH_IOP3XX)	   := iop3xx
  machine-$(CONFIG_ARCH_IXP4XX)	   := ixp4xx
+ machine-$(CONFIG_ARCH_IXP2000)    := ixp2000
  machine-$(CONFIG_ARCH_OMAP)	   := omap
  machine-$(CONFIG_ARCH_S3C2410)	   := s3c2410
  machine-$(CONFIG_ARCH_LH7A40X)	   := lh7a40x
  machine-$(CONFIG_ARCH_VERSATILE_PB) := versatile
+ machine-$(CONFIG_ARCH_IMX)	   := imx
+ machine-$(CONFIG_ARCH_H720X)	   := h720x
 
 ifeq ($(CONFIG_ARCH_EBSA110),y)
 # This is what happens if you forget the IOCS16 line.
diff -Nru a/arch/arm/boot/Makefile b/arch/arm/boot/Makefile
--- a/arch/arm/boot/Makefile	2004-10-18 14:55:55 -07:00
+++ b/arch/arm/boot/Makefile	2004-10-18 14:55:55 -07:00
@@ -47,10 +47,19 @@
 params_phys-$(CONFIG_ARCH_SA1100)	:= 0xc0000100
 initrd_phys-$(CONFIG_ARCH_SA1100)	:= 0xc0800000
    zreladdr-$(CONFIG_ARCH_PXA)		:= 0xa0008000
+   zreladdr-$(CONFIG_ARCH_MX1ADS)	:= 0x08008000
    zreladdr-$(CONFIG_ARCH_IOP3XX)	:= 0xa0008000
 params_phys-$(CONFIG_ARCH_IOP3XX)	:= 0xa0000100
+initrd_phys-$(CONFIG_ARCH_IOP3XX)   	:= 0xa0800000
+ifeq ($(CONFIG_ARCH_IOP331),y)
+   zreladdr-$(CONFIG_ARCH_IOP3XX)      	:= 0x00008000
+params_phys-$(CONFIG_ARCH_IOP3XX)      	:= 0x00000100
+initrd_phys-$(CONFIG_ARCH_IOP3XX)      	:= 0x00800000
+endif
    zreladdr-$(CONFIG_ARCH_IXP4XX)	:= 0x00008000
 params-phys-$(CONFIG_ARCH_IXP4XX)	:= 0x00000100
+   zreladdr-$(CONFIG_ARCH_IXP2000)	:= 0x00008000
+params-phys-$(CONFIG_ARCH_IXP2000)	:= 0x00000100
    zreladdr-$(CONFIG_ARCH_OMAP)		:= 0x10008000
 params_phys-$(CONFIG_ARCH_OMAP)		:= 0x10000100
 initrd_phys-$(CONFIG_ARCH_OMAP)		:= 0x10800000
@@ -62,6 +71,7 @@
    zreladdr-$(CONFIG_ARCH_VERSATILE_PB)	:= 0x00008000
 params_phys-$(CONFIG_ARCH_VERSATILE_PB)	:= 0x00000100
 initrd_phys-$(CONFIG_ARCH_VERSATILE_PB)	:= 0x00800000
+   zreladdr-$(CONFIG_ARCH_H720X)	:= 0x40008000
 
 ZRELADDR    := $(zreladdr-y)
 PARAMS_PHYS := $(params_phys-y)
diff -Nru a/arch/arm/boot/compressed/Makefile b/arch/arm/boot/compressed/Makefile
--- a/arch/arm/boot/compressed/Makefile	2004-10-18 14:55:55 -07:00
+++ b/arch/arm/boot/compressed/Makefile	2004-10-18 14:55:55 -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)
@@ -51,6 +53,10 @@
 OBJS            += ice-dcc.o
 endif
 
+ifeq ($(CONFIG_CPU_BIG_ENDIAN),y)
+OBJS		+= big-endian.o
+endif
+
 #
 # We now have a PIC decompressor implementation.  Decompressors running
 # from RAM should not define ZTEXTADDR.  Decompressors running directly
@@ -66,7 +72,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 +104,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/boot/compressed/big-endian.S b/arch/arm/boot/compressed/big-endian.S
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/arch/arm/boot/compressed/big-endian.S	2004-10-18 14:57:23 -07:00
@@ -0,0 +1,13 @@
+/*
+ *  linux/arch/arm/boot/compressed/big-endian.S
+ *
+ *  Switch CPU into big endian mode.
+ *  Author: Nicolas Pitre
+ */
+
+	.section ".start", #alloc, #execinstr
+
+	mrc	p15, 0, r0, c1, c0, 0	@ read control reg
+	orr	r0, r0, #(1 << 7)	@ enable big endian mode
+	mcr	p15, 0, r0, c1, c0, 0	@ write control reg
+
diff -Nru a/arch/arm/boot/compressed/head-xscale.S b/arch/arm/boot/compressed/head-xscale.S
--- a/arch/arm/boot/compressed/head-xscale.S	2004-10-18 14:56:27 -07:00
+++ b/arch/arm/boot/compressed/head-xscale.S	2004-10-18 14:56:27 -07:00
@@ -35,11 +35,19 @@
 		mcr	p15, 0, r0, c1, c0, 0
 
 #ifdef	CONFIG_ARCH_IQ80321
-		orr	pc, pc, #PHYS_OFFSET	@ jump to physical memory if we are not there.
-		nop
 		mov	r7, #MACH_TYPE_IQ80321
 #endif
 
+#ifdef  CONFIG_ARCH_IQ31244
+		mov	r7, #(MACH_TYPE_IQ31244 & 0xff)
+		orr	r7, r7, #(MACH_TYPE_IQ31244 & 0xff00)
+#endif
+
+#ifdef  CONFIG_ARCH_IQ80331
+		mov	r7, #(MACH_TYPE_IQ80331 & 0xff)
+		orr	r7, r7, #(MACH_TYPE_IQ80331 & 0xff00)
+#endif
+
 #ifdef CONFIG_ARCH_LUBBOCK
 		mov	r7, #MACH_TYPE_LUBBOCK
 #endif
@@ -47,23 +55,4 @@
 #ifdef CONFIG_ARCH_COTULLA_IDP
 		mov	r7, #MACH_TYPE_COTULLA_IDP
 #endif
-
-#ifdef CONFIG_ARCH_IQ80310
-		/*
-		 * Crank the CPU up to 733MHz
-		 */
-		mov	r1, #9
-		mcr	p14, 0, r1, c6, c0, 0
-
-		/*
-		 * Disable ECC error notification
-		 * At some point, we should add an ECC handler to Linux
-		 */
-		mov	r1, #0x1500
-		mov	r0, #0x4
-		str	r0, [r1, #0x34]
-
-		mov	r7, #MACH_TYPE_IQ80310
-#endif
-
 
diff -Nru a/arch/arm/boot/compressed/head.S b/arch/arm/boot/compressed/head.S
--- a/arch/arm/boot/compressed/head.S	2004-10-18 14:57:03 -07:00
+++ b/arch/arm/boot/compressed/head.S	2004-10-18 14:57:03 -07:00
@@ -79,6 +79,14 @@
 		.endm
 		.macro	writeb, rb
 		str	\rb, [r3, #0]
+#elif defined(CONFIG_ARCH_IXP2000)
+		.macro	loadsp, rb
+		mov	\rb, #0xc0000000
+		orr	\rb, \rb, #0x00030000
+		.endm
+		.macro	writeb, rb
+		str	\rb, [r3, #0]
+		.endm
 #elif defined(CONFIG_ARCH_LH7A40X)
 		.macro	loadsp, rb
 		ldr	\rb, =0x80000700	@ UART2 UARTBASE
@@ -100,6 +108,15 @@
 		.macro	writeb, rb
 		strb	\rb, [r3]
 		.endm
+#elif defined(CONFIG_ARCH_IOP331)
+		.macro loadsp, rb
+                mov   	\rb, #0xff000000
+                orr     \rb, \rb, #0x00ff0000
+                orr     \rb, \rb, #0x0000f700   @ location of the UART
+		.endm
+		.macro	writeb, rb
+		str	\rb, [r3, #0]
+		.endm
 #else
 #error no serial architecture defined
 #endif
@@ -332,6 +349,14 @@
 LC1:		.word	reloc_end - reloc_start
 		.size	LC0, . - LC0
 
+#ifdef CONFIG_ARCH_RPC
+		.globl	params
+params:		ldr	r0, =params_phys
+		mov	pc, lr
+		.ltorg
+		.align
+#endif
+
 /*
  * Turn on the cache.  We need to setup some page tables so that we
  * can have both the I and D caches on.
@@ -568,6 +593,12 @@
 		b	__armv4_cache_off
 		b	__armv4_cache_flush
 
+		.word	0x00070000		@ ARMv6
+		.word	0x000f0000
+		b	__armv4_cache_on
+		b	__armv4_cache_off
+		b	__armv6_cache_flush
+
 		.word	0			@ unrecognised type
 		.word	0
 		mov	pc, lr
@@ -626,6 +657,14 @@
 cache_clean_flush:
 		mov	r3, #16
 		b	call_cache_fn
+
+__armv6_cache_flush:
+		mov	r1, #0
+		mcr	p15, 0, r1, c7, c14, 0	@ clean+invalidate D
+		mcr	p15, 0, r1, c7, c5, 0	@ invalidate I+BTB
+		mcr	p15, 0, r1, c7, c15, 0	@ clean+invalidate unified
+		mcr	p15, 0, r1, c7, c10, 4	@ drain WB
+		mov	pc, lr
 
 __armv4_cache_flush:
 		mov	r2, #64*1024		@ default: 32K dcache size (*2)
diff -Nru a/arch/arm/boot/compressed/misc.c b/arch/arm/boot/compressed/misc.c
--- a/arch/arm/boot/compressed/misc.c	2004-10-18 14:56:48 -07:00
+++ b/arch/arm/boot/compressed/misc.c	2004-10-18 14:56:48 -07:00
@@ -23,17 +23,17 @@
 #include <asm/arch/uncompress.h>
 
 #ifdef STANDALONE_DEBUG
-#define puts printf
+#define putstr printf
 #endif
 
 #ifdef CONFIG_DEBUG_ICEDCC
-#define puts icedcc_puts
+#define putstr icedcc_putstr
 #define putc icedcc_putc
 
 extern void idedcc_putc(int ch);
 
 static void
-icedcc_puts(const char *ptr)
+icedcc_putstr(const char *ptr)
 {
 	for (; *ptr != '\0'; ptr++) {
 		icedcc_putc(*ptr);
@@ -191,7 +191,7 @@
 static void gzip_mark(void **);
 static void gzip_release(void **);
 
-static void puts(const char *);
+static void putstr(const char *);
 
 extern int end;
 static ulg free_mem_ptr;
@@ -280,14 +280,14 @@
 	bytes_out += (ulg)outcnt;
 	output_ptr += (ulg)outcnt;
 	outcnt = 0;
-	puts(".");
+	putstr(".");
 }
 
 static void error(char *x)
 {
-	puts("\n\n");
-	puts(x);
-	puts("\n\n -- System halted");
+	putstr("\n\n");
+	putstr(x);
+	putstr("\n\n -- System halted");
 
 	while(1);	/* Halt */
 }
@@ -306,9 +306,9 @@
 	arch_decomp_setup();
 
 	makecrc();
-	puts("Uncompressing Linux...");
+	putstr("Uncompressing Linux...");
 	gunzip();
-	puts(" done, booting the kernel.\n");
+	putstr(" done, booting the kernel.\n");
 	return output_ptr;
 }
 #else
@@ -320,9 +320,9 @@
 	output_data = output_buffer;
 
 	makecrc();
-	puts("Uncompressing Linux...");
+	putstr("Uncompressing Linux...");
 	gunzip();
-	puts("done.\n");
+	putstr("done.\n");
 	return 0;
 }
 #endif
diff -Nru a/arch/arm/common/dmabounce.c b/arch/arm/common/dmabounce.c
--- a/arch/arm/common/dmabounce.c	2004-10-18 14:55:53 -07:00
+++ b/arch/arm/common/dmabounce.c	2004-10-18 14:55:53 -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-10-18 14:57:03 -07:00
+++ b/arch/arm/common/sa1111.c	2004-10-18 14:57:03 -07:00
@@ -35,6 +35,10 @@
 
 #include <asm/hardware/sa1111.h>
 
+#ifdef CONFIG_ARCH_PXA
+#include <asm/arch/pxa-regs.h>
+#endif
+
 extern void __init sa1110_mb_enable(void);
 
 /*
@@ -761,9 +765,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 +772,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/configs/ebsa110_defconfig b/arch/arm/configs/ebsa110_defconfig
--- a/arch/arm/configs/ebsa110_defconfig	2004-10-18 14:55:54 -07:00
+++ b/arch/arm/configs/ebsa110_defconfig	2004-10-18 14:55:54 -07:00
@@ -176,7 +176,6 @@
 CONFIG_IP_ROUTE_FWMARK=y
 CONFIG_IP_ROUTE_NAT=y
 # CONFIG_IP_ROUTE_MULTIPATH is not set
-# CONFIG_IP_ROUTE_TOS is not set
 CONFIG_IP_ROUTE_VERBOSE=y
 CONFIG_IP_PNP=y
 # CONFIG_IP_PNP_DHCP is not set
diff -Nru a/arch/arm/configs/enp2611_defconfig b/arch/arm/configs/enp2611_defconfig
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/arch/arm/configs/enp2611_defconfig	2004-10-18 14:57:24 -07:00
@@ -0,0 +1,795 @@
+#
+# Automatically generated make config: don't edit
+#
+CONFIG_ARM=y
+CONFIG_MMU=y
+CONFIG_UID16=y
+CONFIG_RWSEM_GENERIC_SPINLOCK=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=y
+CONFIG_KALLSYMS=y
+# CONFIG_KALLSYMS_ALL is not set
+# 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=y
+
+#
+# Loadable module support
+#
+# CONFIG_MODULES is not set
+
+#
+# System Type
+#
+# CONFIG_ARCH_CLPS7500 is not set
+# CONFIG_ARCH_CLPS711X is not set
+# CONFIG_ARCH_CO285 is not set
+# CONFIG_ARCH_EBSA110 is not set
+# CONFIG_ARCH_CAMELOT is not set
+# CONFIG_ARCH_FOOTBRIDGE is not set
+# CONFIG_ARCH_INTEGRATOR is not set
+# CONFIG_ARCH_IOP3XX is not set
+# CONFIG_ARCH_IXP4XX is not set
+CONFIG_ARCH_IXP2000=y
+# CONFIG_ARCH_L7200 is not set
+# CONFIG_ARCH_PXA is not set
+# CONFIG_ARCH_RPC is not set
+# CONFIG_ARCH_SA1100 is not set
+# CONFIG_ARCH_S3C2410 is not set
+# CONFIG_ARCH_SHARK is not set
+# CONFIG_ARCH_LH7A40X is not set
+# CONFIG_ARCH_OMAP is not set
+# CONFIG_ARCH_VERSATILE_PB is not set
+CONFIG_ARCH_SUPPORTS_BIG_ENDIAN=y
+
+#
+# Intel IXP2400/2800 Implementation Options
+#
+
+#
+# IXP2400/2800 Platforms
+#
+CONFIG_ARCH_ENP2611=y
+# CONFIG_ARCH_IXDP2400 is not set
+# CONFIG_ARCH_IXDP2800 is not set
+# CONFIG_ARCH_IXDP2401 is not set
+# CONFIG_ARCH_IXDP2801 is not set
+
+#
+# Processor Type
+#
+CONFIG_CPU_32=y
+CONFIG_CPU_XSCALE=y
+CONFIG_CPU_32v5=y
+CONFIG_CPU_ABRT_EV5T=y
+CONFIG_CPU_TLB_V4WBI=y
+CONFIG_CPU_MINICACHE=y
+
+#
+# Processor Features
+#
+# CONFIG_ARM_THUMB is not set
+CONFIG_CPU_BIG_ENDIAN=y
+CONFIG_XSCALE_PMU=y
+
+#
+# General setup
+#
+CONFIG_PCI=y
+# CONFIG_ZBOOT_ROM is not set
+CONFIG_ZBOOT_ROM_TEXT=0x0
+CONFIG_ZBOOT_ROM_BSS=0x0
+CONFIG_PCI_LEGACY_PROC=y
+CONFIG_PCI_NAMES=y
+
+#
+# At least one math emulation must be selected
+#
+CONFIG_FPE_NWFPE=y
+# CONFIG_FPE_NWFPE_XP is not set
+# CONFIG_FPE_FASTFPE is not set
+# CONFIG_VFP is not set
+CONFIG_BINFMT_ELF=y
+# CONFIG_BINFMT_AOUT is not set
+# CONFIG_BINFMT_MISC is not set
+
+#
+# Generic Driver Options
+#
+CONFIG_STANDALONE=y
+# CONFIG_PREVENT_FIRMWARE_BUILD is not set
+# CONFIG_DEBUG_DRIVER is not set
+# CONFIG_PM is not set
+# CONFIG_PREEMPT is not set
+# CONFIG_ARTHUR is not set
+CONFIG_CMDLINE="console=ttyS0,57600 root=/dev/nfs ip=bootp mem=64M@0x0 pci=firmware"
+CONFIG_ALIGNMENT_TRAP=y
+
+#
+# Parallel port support
+#
+# CONFIG_PARPORT is not set
+
+#
+# Memory Technology Devices (MTD)
+#
+CONFIG_MTD=y
+# CONFIG_MTD_DEBUG is not set
+CONFIG_MTD_PARTITIONS=y
+# CONFIG_MTD_CONCAT is not set
+CONFIG_MTD_REDBOOT_PARTS=y
+CONFIG_MTD_REDBOOT_PARTS_UNALLOCATED=y
+CONFIG_MTD_REDBOOT_PARTS_READONLY=y
+# CONFIG_MTD_CMDLINE_PARTS is not set
+# CONFIG_MTD_AFS_PARTS is not set
+
+#
+# User Modules And Translation Layers
+#
+CONFIG_MTD_CHAR=y
+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=y
+# CONFIG_MTD_JEDECPROBE is not set
+CONFIG_MTD_GEN_PROBE=y
+# CONFIG_MTD_CFI_ADV_OPTIONS 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_CFI_INTELEXT=y
+# CONFIG_MTD_CFI_AMDSTD is not set
+# CONFIG_MTD_CFI_STAA is not set
+CONFIG_MTD_CFI_UTIL=y
+# CONFIG_MTD_RAM is not set
+# CONFIG_MTD_ROM is not set
+# CONFIG_MTD_ABSENT is not set
+
+#
+# Mapping drivers for chip access
+#
+CONFIG_MTD_COMPLEX_MAPPINGS=y
+# CONFIG_MTD_PHYSMAP is not set
+# CONFIG_MTD_ARM_INTEGRATOR is not set
+CONFIG_MTD_IXP2000=y
+# CONFIG_MTD_EDB7312 is not set
+# CONFIG_MTD_PCI is not set
+
+#
+# Self-contained MTD device drivers
+#
+# CONFIG_MTD_PMC551 is not set
+# CONFIG_MTD_SLRAM is not set
+# CONFIG_MTD_PHRAM is not set
+# CONFIG_MTD_MTDRAM is not set
+# CONFIG_MTD_BLKMTD is not set
+
+#
+# Disk-On-Chip Device Drivers
+#
+# CONFIG_MTD_DOC2000 is not set
+# CONFIG_MTD_DOC2001 is not set
+# CONFIG_MTD_DOC2001PLUS is not set
+
+#
+# NAND Flash Device Drivers
+#
+# CONFIG_MTD_NAND is not set
+
+#
+# Plug and Play support
+#
+
+#
+# Block devices
+#
+# CONFIG_BLK_DEV_FD is not set
+# CONFIG_BLK_CPQ_DA is not set
+# CONFIG_BLK_CPQ_CISS_DA is not set
+# CONFIG_BLK_DEV_DAC960 is not set
+# CONFIG_BLK_DEV_UMEM is not set
+CONFIG_BLK_DEV_LOOP=y
+# CONFIG_BLK_DEV_CRYPTOLOOP 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=8192
+CONFIG_BLK_DEV_INITRD=y
+
+#
+# Multi-device support (RAID and LVM)
+#
+# CONFIG_MD is not set
+
+#
+# Networking support
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+CONFIG_PACKET=y
+CONFIG_PACKET_MMAP=y
+# CONFIG_NETLINK_DEV is not set
+CONFIG_UNIX=y
+# CONFIG_NET_KEY is not set
+CONFIG_INET=y
+# CONFIG_IP_MULTICAST is not set
+# CONFIG_IP_ADVANCED_ROUTER is not set
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_DHCP=y
+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_ARPD is not set
+CONFIG_SYN_COOKIES=y
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+# CONFIG_IPV6 is not set
+# CONFIG_NETFILTER is not set
+
+#
+# SCTP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_SCTP is not set
+# CONFIG_ATM is not set
+# CONFIG_BRIDGE is not set
+# CONFIG_VLAN_8021Q is not set
+# CONFIG_DECNET 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
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+# CONFIG_NET_FASTROUTE is not set
+# CONFIG_NET_HW_FLOWCONTROL is not set
+
+#
+# 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=y
+# CONFIG_BONDING is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
+
+#
+# ARCnet devices
+#
+# CONFIG_ARCNET is not set
+
+#
+# Ethernet (10 or 100Mbit)
+#
+CONFIG_NET_ETHERNET=y
+CONFIG_MII=y
+# CONFIG_HAPPYMEAL is not set
+# CONFIG_SUNGEM is not set
+# CONFIG_NET_VENDOR_3COM is not set
+# CONFIG_SMC91X is not set
+
+#
+# Tulip family network device support
+#
+# CONFIG_NET_TULIP is not set
+# CONFIG_HP100 is not set
+CONFIG_NET_PCI=y
+# CONFIG_PCNET32 is not set
+# 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_FEALNX is not set
+# CONFIG_NATSEMI is not set
+# CONFIG_NE2K_PCI 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_TLAN is not set
+# CONFIG_VIA_RHINE is not set
+# CONFIG_VIA_VELOCITY is not set
+
+#
+# Ethernet (1000 Mbit)
+#
+# CONFIG_ACENIC is not set
+# CONFIG_DL2K is not set
+# CONFIG_E1000 is not set
+# CONFIG_NS83820 is not set
+# CONFIG_HAMACHI is not set
+# CONFIG_YELLOWFIN is not set
+# CONFIG_R8169 is not set
+# CONFIG_SK98LIN is not set
+# CONFIG_TIGON3 is not set
+
+#
+# Ethernet (10000 Mbit)
+#
+# CONFIG_IXGB is not set
+# CONFIG_S2IO is not set
+
+#
+# Token Ring devices
+#
+# CONFIG_TR is not set
+
+#
+# Wireless LAN (non-hamradio)
+#
+# CONFIG_NET_RADIO is not set
+
+#
+# Wan interfaces
+#
+CONFIG_WAN=y
+# CONFIG_LANMEDIA is not set
+# CONFIG_SYNCLINK_SYNCPPP is not set
+CONFIG_HDLC=y
+CONFIG_HDLC_RAW=y
+# CONFIG_HDLC_RAW_ETH is not set
+CONFIG_HDLC_CISCO=y
+CONFIG_HDLC_FR=y
+CONFIG_HDLC_PPP=y
+
+#
+# X.25/LAPB support is disabled
+#
+# CONFIG_PCI200SYN is not set
+# CONFIG_WANXL is not set
+# CONFIG_PC300 is not set
+# CONFIG_FARSYNC is not set
+CONFIG_DLCI=y
+CONFIG_DLCI_COUNT=24
+CONFIG_DLCI_MAX=8
+# CONFIG_FDDI is not set
+# CONFIG_HIPPI is not set
+# CONFIG_PPP is not set
+# CONFIG_SLIP is not set
+# CONFIG_SHAPER is not set
+# CONFIG_NETCONSOLE is not set
+
+#
+# SCSI device support
+#
+# CONFIG_SCSI is not set
+
+#
+# Fusion MPT device support
+#
+
+#
+# IEEE 1394 (FireWire) support
+#
+# CONFIG_IEEE1394 is not set
+
+#
+# I2O device support
+#
+# CONFIG_I2O is not set
+
+#
+# ISDN subsystem
+#
+# CONFIG_ISDN is not set
+
+#
+# Input device support
+#
+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_I8042 is not set
+
+#
+# Input Device Drivers
+#
+# CONFIG_INPUT_KEYBOARD is not set
+# CONFIG_INPUT_MOUSE 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 is not set
+# CONFIG_SERIAL_NONSTANDARD is not set
+
+#
+# Serial drivers
+#
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_NR_UARTS=2
+# CONFIG_SERIAL_8250_EXTENDED is not set
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+CONFIG_UNIX98_PTYS=y
+CONFIG_LEGACY_PTYS=y
+CONFIG_LEGACY_PTY_COUNT=256
+# CONFIG_QIC02_TAPE is not set
+
+#
+# IPMI
+#
+# CONFIG_IPMI_HANDLER is not set
+
+#
+# Watchdog Cards
+#
+CONFIG_WATCHDOG=y
+# CONFIG_WATCHDOG_NOWAYOUT is not set
+
+#
+# Watchdog Device Drivers
+#
+# CONFIG_SOFT_WATCHDOG is not set
+CONFIG_IXP2000_WATCHDOG=y
+
+#
+# PCI-based Watchdog Cards
+#
+# CONFIG_PCIPCWATCHDOG is not set
+# CONFIG_WDTPCI is not set
+# CONFIG_NVRAM is not set
+# CONFIG_RTC is not set
+# CONFIG_GEN_RTC is not set
+# CONFIG_DTLK is not set
+# CONFIG_R3964 is not set
+# CONFIG_APPLICOM is not set
+
+#
+# Ftape, the floppy tape device driver
+#
+# CONFIG_AGP is not set
+# CONFIG_DRM is not set
+# CONFIG_RAW_DRIVER is not set
+
+#
+# I2C support
+#
+CONFIG_I2C=y
+CONFIG_I2C_CHARDEV=y
+
+#
+# I2C Algorithms
+#
+CONFIG_I2C_ALGOBIT=y
+# CONFIG_I2C_ALGOPCF is not set
+
+#
+# I2C Hardware Bus support
+#
+# CONFIG_I2C_ALI1535 is not set
+# CONFIG_I2C_ALI1563 is not set
+# CONFIG_I2C_ALI15X3 is not set
+# CONFIG_I2C_AMD756 is not set
+# CONFIG_I2C_AMD8111 is not set
+# CONFIG_I2C_I801 is not set
+# CONFIG_I2C_I810 is not set
+# CONFIG_I2C_ISA is not set
+# CONFIG_I2C_IXP2000 is not set
+# CONFIG_I2C_NFORCE2 is not set
+# CONFIG_I2C_PARPORT_LIGHT is not set
+# CONFIG_I2C_PIIX4 is not set
+# CONFIG_I2C_PROSAVAGE is not set
+# CONFIG_I2C_SAVAGE4 is not set
+# CONFIG_SCx200_ACB is not set
+# CONFIG_I2C_SIS5595 is not set
+# CONFIG_I2C_SIS630 is not set
+# CONFIG_I2C_SIS96X is not set
+# CONFIG_I2C_VIA is not set
+# CONFIG_I2C_VIAPRO is not set
+# CONFIG_I2C_VOODOO3 is not set
+
+#
+# Hardware Sensors Chip support
+#
+CONFIG_I2C_SENSOR=y
+# CONFIG_SENSORS_ADM1021 is not set
+# CONFIG_SENSORS_ADM1025 is not set
+# CONFIG_SENSORS_ADM1031 is not set
+# CONFIG_SENSORS_ASB100 is not set
+# CONFIG_SENSORS_DS1621 is not set
+# CONFIG_SENSORS_FSCHER is not set
+# CONFIG_SENSORS_GL518SM is not set
+# CONFIG_SENSORS_IT87 is not set
+# CONFIG_SENSORS_LM75 is not set
+# CONFIG_SENSORS_LM77 is not set
+# CONFIG_SENSORS_LM78 is not set
+# CONFIG_SENSORS_LM80 is not set
+# CONFIG_SENSORS_LM83 is not set
+# CONFIG_SENSORS_LM85 is not set
+# CONFIG_SENSORS_LM90 is not set
+# CONFIG_SENSORS_MAX1619 is not set
+# CONFIG_SENSORS_VIA686A is not set
+# CONFIG_SENSORS_W83781D is not set
+# CONFIG_SENSORS_W83L785TS is not set
+# CONFIG_SENSORS_W83627HF is not set
+
+#
+# Other I2C Chip support
+#
+CONFIG_SENSORS_EEPROM=y
+# CONFIG_SENSORS_PCF8574 is not set
+# CONFIG_SENSORS_PCF8591 is not set
+# CONFIG_SENSORS_RTC8564 is not set
+# CONFIG_I2C_DEBUG_CORE is not set
+# CONFIG_I2C_DEBUG_ALGO is not set
+# CONFIG_I2C_DEBUG_BUS is not set
+# CONFIG_I2C_DEBUG_CHIP is not set
+
+#
+# Multimedia devices
+#
+# CONFIG_VIDEO_DEV is not set
+
+#
+# Digital Video Broadcasting Devices
+#
+# CONFIG_DVB is not set
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+CONFIG_EXT2_FS_XATTR=y
+CONFIG_EXT2_FS_POSIX_ACL=y
+# CONFIG_EXT2_FS_SECURITY is not set
+CONFIG_EXT3_FS=y
+CONFIG_EXT3_FS_XATTR=y
+CONFIG_EXT3_FS_POSIX_ACL=y
+# CONFIG_EXT3_FS_SECURITY is not set
+CONFIG_JBD=y
+# CONFIG_JBD_DEBUG is not set
+CONFIG_FS_MBCACHE=y
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+CONFIG_FS_POSIX_ACL=y
+# CONFIG_XFS_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_ROMFS_FS is not set
+# CONFIG_QUOTA is not set
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_AUTOFS4_FS is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+# CONFIG_ISO9660_FS is not set
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+# 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_SYSFS=y
+# CONFIG_DEVFS_FS 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_EFS_FS is not set
+# CONFIG_JFFS_FS is not set
+CONFIG_JFFS2_FS=y
+CONFIG_JFFS2_FS_DEBUG=0
+# CONFIG_JFFS2_FS_NAND is not set
+# CONFIG_JFFS2_COMPRESSION_OPTIONS is not set
+CONFIG_JFFS2_ZLIB=y
+CONFIG_JFFS2_RTIME=y
+# CONFIG_JFFS2_RUBIN is not set
+# CONFIG_CRAMFS is not set
+# CONFIG_VXFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+
+#
+# Network File Systems
+#
+CONFIG_NFS_FS=y
+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_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_AFS_FS is not set
+
+#
+# Partition Types
+#
+CONFIG_PARTITION_ADVANCED=y
+# CONFIG_ACORN_PARTITION is not set
+# CONFIG_OSF_PARTITION is not set
+# CONFIG_AMIGA_PARTITION is not set
+# CONFIG_ATARI_PARTITION is not set
+# CONFIG_MAC_PARTITION is not set
+CONFIG_MSDOS_PARTITION=y
+# CONFIG_BSD_DISKLABEL is not set
+# CONFIG_MINIX_SUBPARTITION is not set
+# CONFIG_SOLARIS_X86_PARTITION is not set
+# CONFIG_UNIXWARE_DISKLABEL is not set
+# CONFIG_LDM_PARTITION is not set
+# CONFIG_SGI_PARTITION is not set
+# CONFIG_ULTRIX_PARTITION is not set
+# CONFIG_SUN_PARTITION is not set
+# CONFIG_EFI_PARTITION is not set
+
+#
+# Native Language Support
+#
+# CONFIG_NLS is not set
+
+#
+# Profiling support
+#
+# CONFIG_PROFILING is not set
+
+#
+# Graphics support
+#
+# CONFIG_FB is not set
+
+#
+# Sound
+#
+# CONFIG_SOUND is not set
+
+#
+# Misc devices
+#
+
+#
+# USB support
+#
+# CONFIG_USB is not set
+
+#
+# USB Gadget Support
+#
+# CONFIG_USB_GADGET is not set
+
+#
+# Kernel hacking
+#
+CONFIG_FRAME_POINTER=y
+CONFIG_DEBUG_USER=y
+# CONFIG_DEBUG_INFO is not set
+CONFIG_DEBUG_KERNEL=y
+# CONFIG_DEBUG_SLAB is not set
+CONFIG_MAGIC_SYSRQ=y
+# CONFIG_DEBUG_SPINLOCK is not set
+# CONFIG_DEBUG_WAITQ is not set
+CONFIG_DEBUG_BUGVERBOSE=y
+CONFIG_DEBUG_ERRORS=y
+CONFIG_DEBUG_LL=y
+# CONFIG_DEBUG_ICEDCC is not set
+# CONFIG_DEBUG_BDI2000_XSCALE is not set
+
+#
+# Security options
+#
+# CONFIG_SECURITY is not set
+
+#
+# Cryptographic options
+#
+# CONFIG_CRYPTO is not set
+
+#
+# Library routines
+#
+# CONFIG_CRC_CCITT is not set
+CONFIG_CRC32=y
+# CONFIG_LIBCRC32C is not set
+CONFIG_ZLIB_INFLATE=y
+CONFIG_ZLIB_DEFLATE=y
diff -Nru a/arch/arm/configs/ep80219_defconfig b/arch/arm/configs/ep80219_defconfig
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/arch/arm/configs/ep80219_defconfig	2004-10-18 14:57:23 -07:00
@@ -0,0 +1,849 @@
+#
+# Automatically generated make config: don't edit
+#
+CONFIG_ARM=y
+CONFIG_MMU=y
+CONFIG_UID16=y
+CONFIG_RWSEM_GENERIC_SPINLOCK=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_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=y
+
+#
+# Loadable module support
+#
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+# CONFIG_MODULE_FORCE_UNLOAD is not set
+CONFIG_OBSOLETE_MODPARM=y
+# CONFIG_MODVERSIONS is not set
+CONFIG_KMOD=y
+
+#
+# System Type
+#
+# CONFIG_ARCH_CLPS7500 is not set
+# CONFIG_ARCH_CLPS711X is not set
+# CONFIG_ARCH_CO285 is not set
+# CONFIG_ARCH_EBSA110 is not set
+# CONFIG_ARCH_CAMELOT is not set
+# CONFIG_ARCH_FOOTBRIDGE is not set
+# CONFIG_ARCH_INTEGRATOR is not set
+CONFIG_ARCH_IOP3XX=y
+# CONFIG_ARCH_IXP4XX is not set
+# CONFIG_ARCH_L7200 is not set
+# CONFIG_ARCH_PXA is not set
+# CONFIG_ARCH_RPC is not set
+# CONFIG_ARCH_SA1100 is not set
+# CONFIG_ARCH_S3C2410 is not set
+# CONFIG_ARCH_SHARK is not set
+# CONFIG_ARCH_LH7A40X is not set
+# CONFIG_ARCH_OMAP is not set
+# CONFIG_ARCH_VERSATILE_PB is not set
+
+#
+# IOP3xx Implementation Options
+#
+
+#
+# IOP3xx Platform Types
+#
+# CONFIG_ARCH_IQ80321 is not set
+CONFIG_ARCH_IQ31244=y
+# CONFIG_ARCH_IQ80331 is not set
+CONFIG_ARCH_EP80219=y
+CONFIG_ARCH_IOP321=y
+# CONFIG_ARCH_IOP331 is not set
+
+#
+# IOP3xx Chipset Features
+#
+
+#
+# Processor Type
+#
+CONFIG_CPU_32=y
+CONFIG_CPU_XSCALE=y
+CONFIG_CPU_32v5=y
+CONFIG_CPU_ABRT_EV5T=y
+CONFIG_CPU_TLB_V4WBI=y
+CONFIG_CPU_MINICACHE=y
+
+#
+# Processor Features
+#
+# CONFIG_ARM_THUMB is not set
+CONFIG_XSCALE_PMU=y
+
+#
+# General setup
+#
+CONFIG_PCI=y
+# CONFIG_ZBOOT_ROM is not set
+CONFIG_ZBOOT_ROM_TEXT=0x0
+CONFIG_ZBOOT_ROM_BSS=0x0
+# CONFIG_PCI_LEGACY_PROC is not set
+CONFIG_PCI_NAMES=y
+
+#
+# At least one math emulation must be selected
+#
+CONFIG_FPE_NWFPE=y
+# CONFIG_FPE_NWFPE_XP is not set
+# CONFIG_FPE_FASTFPE is not set
+# CONFIG_VFP is not set
+CONFIG_BINFMT_ELF=y
+CONFIG_BINFMT_AOUT=y
+# CONFIG_BINFMT_MISC is not set
+
+#
+# Generic Driver Options
+#
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+# CONFIG_PM is not set
+# CONFIG_PREEMPT is not set
+# CONFIG_ARTHUR is not set
+CONFIG_CMDLINE="ip=boot root=nfs console=ttyS0,115200 mem=128M@0xa0000000"
+CONFIG_ALIGNMENT_TRAP=y
+
+#
+# Parallel port support
+#
+# CONFIG_PARPORT is not set
+
+#
+# Memory Technology Devices (MTD)
+#
+CONFIG_MTD=y
+# CONFIG_MTD_DEBUG is not set
+CONFIG_MTD_PARTITIONS=y
+# CONFIG_MTD_CONCAT is not set
+CONFIG_MTD_REDBOOT_PARTS=y
+# CONFIG_MTD_REDBOOT_PARTS_UNALLOCATED is not set
+# CONFIG_MTD_REDBOOT_PARTS_READONLY is not set
+# CONFIG_MTD_CMDLINE_PARTS is not set
+# CONFIG_MTD_AFS_PARTS is not set
+
+#
+# User Modules And Translation Layers
+#
+CONFIG_MTD_CHAR=y
+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=y
+# CONFIG_MTD_JEDECPROBE is not set
+CONFIG_MTD_GEN_PROBE=y
+# CONFIG_MTD_CFI_ADV_OPTIONS 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_CFI_INTELEXT=y
+# CONFIG_MTD_CFI_AMDSTD is not set
+# CONFIG_MTD_CFI_STAA is not set
+CONFIG_MTD_CFI_UTIL=y
+# CONFIG_MTD_RAM is not set
+# CONFIG_MTD_ROM is not set
+# CONFIG_MTD_ABSENT is not set
+
+#
+# Mapping drivers for chip access
+#
+# CONFIG_MTD_COMPLEX_MAPPINGS is not set
+# CONFIG_MTD_PHYSMAP is not set
+# CONFIG_MTD_ARM_INTEGRATOR is not set
+# CONFIG_MTD_EDB7312 is not set
+
+#
+# Self-contained MTD device drivers
+#
+# CONFIG_MTD_PMC551 is not set
+# CONFIG_MTD_SLRAM is not set
+# CONFIG_MTD_PHRAM is not set
+# CONFIG_MTD_MTDRAM is not set
+# CONFIG_MTD_BLKMTD is not set
+
+#
+# Disk-On-Chip Device Drivers
+#
+# CONFIG_MTD_DOC2000 is not set
+# CONFIG_MTD_DOC2001 is not set
+# CONFIG_MTD_DOC2001PLUS is not set
+
+#
+# NAND Flash Device Drivers
+#
+# CONFIG_MTD_NAND is not set
+
+#
+# Plug and Play support
+#
+
+#
+# Block devices
+#
+# CONFIG_BLK_DEV_FD is not set
+# CONFIG_BLK_CPQ_DA is not set
+# CONFIG_BLK_CPQ_CISS_DA is not set
+# CONFIG_BLK_DEV_DAC960 is not set
+# 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=8192
+# CONFIG_BLK_DEV_INITRD is not set
+
+#
+# Multi-device support (RAID and LVM)
+#
+CONFIG_MD=y
+CONFIG_BLK_DEV_MD=y
+# CONFIG_MD_LINEAR is not set
+CONFIG_MD_RAID0=y
+CONFIG_MD_RAID1=y
+CONFIG_MD_RAID5=y
+# CONFIG_MD_RAID6 is not set
+# CONFIG_MD_MULTIPATH is not set
+CONFIG_BLK_DEV_DM=y
+# CONFIG_DM_CRYPT is not set
+# CONFIG_DM_SNAPSHOT is not set
+# CONFIG_DM_MIRROR is not set
+# CONFIG_DM_ZERO is not set
+
+#
+# Networking support
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+CONFIG_PACKET=y
+CONFIG_PACKET_MMAP=y
+# CONFIG_NETLINK_DEV 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 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_SYN_COOKIES is not set
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+# CONFIG_IPV6 is not set
+# CONFIG_NETFILTER is not set
+
+#
+# SCTP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_SCTP is not set
+# CONFIG_ATM is not set
+# CONFIG_BRIDGE is not set
+# CONFIG_VLAN_8021Q is not set
+# CONFIG_DECNET 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
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+# CONFIG_NET_HW_FLOWCONTROL is not set
+
+#
+# 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
+
+#
+# Ethernet (10 or 100Mbit)
+#
+CONFIG_NET_ETHERNET=y
+CONFIG_MII=y
+# CONFIG_HAPPYMEAL is not set
+# CONFIG_SUNGEM is not set
+# CONFIG_NET_VENDOR_3COM is not set
+# CONFIG_SMC91X is not set
+
+#
+# Tulip family network device support
+#
+# CONFIG_NET_TULIP is not set
+# CONFIG_HP100 is not set
+CONFIG_NET_PCI=y
+# CONFIG_PCNET32 is not set
+# 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 is not set
+CONFIG_E100=y
+CONFIG_E100_NAPI=y
+# CONFIG_FEALNX is not set
+# CONFIG_NATSEMI is not set
+# CONFIG_NE2K_PCI 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_TLAN is not set
+# CONFIG_VIA_RHINE is not set
+# CONFIG_VIA_VELOCITY is not set
+
+#
+# Ethernet (1000 Mbit)
+#
+# CONFIG_ACENIC is not set
+# CONFIG_DL2K is not set
+# CONFIG_E1000 is not set
+# CONFIG_NS83820 is not set
+# CONFIG_HAMACHI is not set
+# CONFIG_YELLOWFIN is not set
+# CONFIG_R8169 is not set
+# CONFIG_SK98LIN is not set
+# CONFIG_TIGON3 is not set
+
+#
+# Ethernet (10000 Mbit)
+#
+# CONFIG_IXGB is not set
+# CONFIG_S2IO is not set
+
+#
+# Token Ring devices
+#
+# CONFIG_TR is not set
+
+#
+# Wireless LAN (non-hamradio)
+#
+# CONFIG_NET_RADIO is not set
+
+#
+# Wan interfaces
+#
+# CONFIG_WAN 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
+
+#
+# ATA/ATAPI/MFM/RLL support
+#
+# CONFIG_IDE is not set
+
+#
+# SCSI device support
+#
+CONFIG_SCSI=y
+CONFIG_SCSI_PROC_FS=y
+
+#
+# SCSI support type (disk, tape, CD-ROM)
+#
+CONFIG_BLK_DEV_SD=y
+# CONFIG_CHR_DEV_ST is not set
+# CONFIG_CHR_DEV_OSST is not set
+# CONFIG_BLK_DEV_SR is not set
+CONFIG_CHR_DEV_SG=y
+
+#
+# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
+#
+# CONFIG_SCSI_MULTI_LUN is not set
+# CONFIG_SCSI_CONSTANTS is not set
+# CONFIG_SCSI_LOGGING is not set
+
+#
+# SCSI Transport Attributes
+#
+# CONFIG_SCSI_SPI_ATTRS is not set
+# 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_MEGARAID is not set
+# CONFIG_SCSI_SATA is not set
+# CONFIG_SCSI_BUSLOGIC 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_IPS is not set
+# CONFIG_SCSI_INIA100 is not set
+# CONFIG_SCSI_SYM53C8XX_2 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_NSP32 is not set
+# CONFIG_SCSI_DEBUG is not set
+
+#
+# Fusion MPT device support
+#
+# CONFIG_FUSION is not set
+
+#
+# IEEE 1394 (FireWire) support
+#
+# CONFIG_IEEE1394 is not set
+
+#
+# I2O device support
+#
+# CONFIG_I2O is not set
+
+#
+# ISDN subsystem
+#
+# CONFIG_ISDN is not set
+
+#
+# Input device support
+#
+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_I8042 is not set
+
+#
+# Input Device Drivers
+#
+# CONFIG_INPUT_KEYBOARD is not set
+# CONFIG_INPUT_MOUSE 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
+
+#
+# Serial drivers
+#
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_NR_UARTS=4
+# CONFIG_SERIAL_8250_EXTENDED is not set
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+CONFIG_UNIX98_PTYS=y
+CONFIG_LEGACY_PTYS=y
+CONFIG_LEGACY_PTY_COUNT=256
+# CONFIG_QIC02_TAPE is not set
+
+#
+# IPMI
+#
+# CONFIG_IPMI_HANDLER is not set
+
+#
+# Watchdog Cards
+#
+# CONFIG_WATCHDOG is not set
+# CONFIG_NVRAM is not set
+# CONFIG_RTC is not set
+# CONFIG_GEN_RTC is not set
+# CONFIG_DTLK is not set
+# CONFIG_R3964 is not set
+# CONFIG_APPLICOM is not set
+
+#
+# Ftape, the floppy tape device driver
+#
+# CONFIG_AGP is not set
+# CONFIG_DRM is not set
+# CONFIG_RAW_DRIVER is not set
+
+#
+# I2C support
+#
+CONFIG_I2C=y
+CONFIG_I2C_CHARDEV=y
+
+#
+# I2C Algorithms
+#
+# CONFIG_I2C_ALGOBIT is not set
+# CONFIG_I2C_ALGOPCF is not set
+
+#
+# I2C Hardware Bus support
+#
+# CONFIG_I2C_ALI1535 is not set
+# CONFIG_I2C_ALI1563 is not set
+# CONFIG_I2C_ALI15X3 is not set
+# CONFIG_I2C_AMD756 is not set
+# CONFIG_I2C_AMD8111 is not set
+# CONFIG_I2C_I801 is not set
+# CONFIG_I2C_I810 is not set
+CONFIG_I2C_IOP3XX=y
+# CONFIG_I2C_ISA is not set
+# CONFIG_I2C_NFORCE2 is not set
+# CONFIG_I2C_PARPORT_LIGHT is not set
+# CONFIG_I2C_PIIX4 is not set
+# CONFIG_I2C_PROSAVAGE is not set
+# CONFIG_I2C_SAVAGE4 is not set
+# CONFIG_SCx200_ACB is not set
+# CONFIG_I2C_SIS5595 is not set
+# CONFIG_I2C_SIS630 is not set
+# CONFIG_I2C_SIS96X is not set
+# CONFIG_I2C_VIA is not set
+# CONFIG_I2C_VIAPRO is not set
+# CONFIG_I2C_VOODOO3 is not set
+
+#
+# Hardware Sensors Chip support
+#
+# CONFIG_I2C_SENSOR is not set
+# CONFIG_SENSORS_ADM1021 is not set
+# CONFIG_SENSORS_ADM1025 is not set
+# CONFIG_SENSORS_ADM1031 is not set
+# CONFIG_SENSORS_ASB100 is not set
+# CONFIG_SENSORS_DS1621 is not set
+# CONFIG_SENSORS_FSCHER is not set
+# CONFIG_SENSORS_GL518SM is not set
+# CONFIG_SENSORS_IT87 is not set
+# CONFIG_SENSORS_LM75 is not set
+# CONFIG_SENSORS_LM77 is not set
+# CONFIG_SENSORS_LM78 is not set
+# CONFIG_SENSORS_LM80 is not set
+# CONFIG_SENSORS_LM83 is not set
+# CONFIG_SENSORS_LM85 is not set
+# CONFIG_SENSORS_LM90 is not set
+# CONFIG_SENSORS_MAX1619 is not set
+# CONFIG_SENSORS_VIA686A is not set
+# CONFIG_SENSORS_W83781D is not set
+# CONFIG_SENSORS_W83L785TS is not set
+# CONFIG_SENSORS_W83627HF is not set
+
+#
+# Other I2C Chip support
+#
+# CONFIG_SENSORS_EEPROM is not set
+# CONFIG_SENSORS_PCF8574 is not set
+# CONFIG_SENSORS_PCF8591 is not set
+# CONFIG_SENSORS_RTC8564 is not set
+# CONFIG_I2C_DEBUG_CORE is not set
+# CONFIG_I2C_DEBUG_ALGO is not set
+# CONFIG_I2C_DEBUG_BUS is not set
+# CONFIG_I2C_DEBUG_CHIP is not set
+
+#
+# Multimedia devices
+#
+# CONFIG_VIDEO_DEV is not set
+
+#
+# Digital Video Broadcasting Devices
+#
+# CONFIG_DVB is not set
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+# CONFIG_EXT2_FS_XATTR is not set
+CONFIG_EXT3_FS=y
+CONFIG_EXT3_FS_XATTR=y
+# CONFIG_EXT3_FS_POSIX_ACL is not set
+# CONFIG_EXT3_FS_SECURITY is not set
+CONFIG_JBD=y
+# CONFIG_JBD_DEBUG is not set
+CONFIG_FS_MBCACHE=y
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+CONFIG_XFS_FS=y
+# CONFIG_XFS_RT is not set
+# CONFIG_XFS_QUOTA is not set
+CONFIG_XFS_SECURITY=y
+CONFIG_XFS_POSIX_ACL=y
+# CONFIG_MINIX_FS is not set
+# CONFIG_ROMFS_FS is not set
+# CONFIG_QUOTA is not set
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_AUTOFS4_FS is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+# CONFIG_ISO9660_FS is not set
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+# 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_SYSFS=y
+# CONFIG_DEVFS_FS 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_EFS_FS is not set
+# CONFIG_JFFS_FS is not set
+CONFIG_JFFS2_FS=y
+CONFIG_JFFS2_FS_DEBUG=0
+# CONFIG_JFFS2_FS_NAND is not set
+# CONFIG_JFFS2_COMPRESSION_OPTIONS is not set
+CONFIG_JFFS2_ZLIB=y
+CONFIG_JFFS2_RTIME=y
+# CONFIG_JFFS2_RUBIN is not set
+# CONFIG_CRAMFS is not set
+# CONFIG_VXFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+
+#
+# Network File Systems
+#
+CONFIG_NFS_FS=y
+CONFIG_NFS_V3=y
+# CONFIG_NFS_V4 is not set
+# CONFIG_NFS_DIRECTIO is not set
+CONFIG_NFSD=y
+CONFIG_NFSD_V3=y
+# CONFIG_NFSD_V4 is not set
+# CONFIG_NFSD_TCP is not set
+CONFIG_ROOT_NFS=y
+CONFIG_LOCKD=y
+CONFIG_LOCKD_V4=y
+CONFIG_EXPORTFS=y
+CONFIG_SUNRPC=y
+# 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_AFS_FS is not set
+
+#
+# Partition Types
+#
+CONFIG_PARTITION_ADVANCED=y
+# CONFIG_ACORN_PARTITION is not set
+# CONFIG_OSF_PARTITION is not set
+# CONFIG_AMIGA_PARTITION is not set
+# CONFIG_ATARI_PARTITION is not set
+# CONFIG_MAC_PARTITION is not set
+CONFIG_MSDOS_PARTITION=y
+# CONFIG_BSD_DISKLABEL is not set
+# CONFIG_MINIX_SUBPARTITION is not set
+# CONFIG_SOLARIS_X86_PARTITION is not set
+# CONFIG_UNIXWARE_DISKLABEL is not set
+# CONFIG_LDM_PARTITION is not set
+# CONFIG_SGI_PARTITION is not set
+# CONFIG_ULTRIX_PARTITION is not set
+# CONFIG_SUN_PARTITION is not set
+# CONFIG_EFI_PARTITION is not set
+
+#
+# Native Language Support
+#
+# CONFIG_NLS is not set
+
+#
+# Profiling support
+#
+# CONFIG_PROFILING is not set
+
+#
+# Graphics support
+#
+# CONFIG_FB is not set
+
+#
+# Console display driver support
+#
+# CONFIG_VGA_CONSOLE is not set
+# CONFIG_MDA_CONSOLE is not set
+CONFIG_DUMMY_CONSOLE=y
+
+#
+# Sound
+#
+# CONFIG_SOUND is not set
+
+#
+# Misc devices
+#
+
+#
+# USB support
+#
+# CONFIG_USB is not set
+
+#
+# USB Gadget Support
+#
+# CONFIG_USB_GADGET is not set
+
+#
+# Kernel hacking
+#
+CONFIG_FRAME_POINTER=y
+CONFIG_DEBUG_USER=y
+# CONFIG_DEBUG_INFO is not set
+# CONFIG_DEBUG_KERNEL is not set
+
+#
+# Security options
+#
+# CONFIG_SECURITY is not set
+
+#
+# Cryptographic options
+#
+# CONFIG_CRYPTO is not set
+
+#
+# Library routines
+#
+# CONFIG_CRC_CCITT is not set
+CONFIG_CRC32=y
+# CONFIG_LIBCRC32C is not set
+CONFIG_ZLIB_INFLATE=y
+CONFIG_ZLIB_DEFLATE=y
diff -Nru a/arch/arm/configs/h7201_defconfig b/arch/arm/configs/h7201_defconfig
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/arch/arm/configs/h7201_defconfig	2004-10-18 14:57:24 -07:00
@@ -0,0 +1,511 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.9-rc1
+# Thu Sep  2 11:04:11 2004
+#
+CONFIG_ARM=y
+CONFIG_MMU=y
+CONFIG_UID16=y
+CONFIG_RWSEM_GENERIC_SPINLOCK=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_BSD_PROCESS_ACCT is not set
+CONFIG_SYSCTL=y
+# CONFIG_AUDIT is not set
+CONFIG_LOG_BUF_SHIFT=14
+CONFIG_HOTPLUG=y
+# 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=y
+
+#
+# Loadable module support
+#
+CONFIG_MODULES=y
+# CONFIG_MODULE_UNLOAD is not set
+CONFIG_OBSOLETE_MODPARM=y
+# CONFIG_MODVERSIONS is not set
+CONFIG_KMOD=y
+
+#
+# System Type
+#
+# CONFIG_ARCH_CLPS7500 is not set
+# CONFIG_ARCH_CLPS711X is not set
+# CONFIG_ARCH_CO285 is not set
+# CONFIG_ARCH_EBSA110 is not set
+# CONFIG_ARCH_CAMELOT is not set
+# CONFIG_ARCH_FOOTBRIDGE is not set
+# CONFIG_ARCH_INTEGRATOR is not set
+# CONFIG_ARCH_IOP3XX is not set
+# CONFIG_ARCH_IXP4XX is not set
+# CONFIG_ARCH_L7200 is not set
+# CONFIG_ARCH_PXA is not set
+# CONFIG_ARCH_RPC is not set
+# CONFIG_ARCH_SA1100 is not set
+# CONFIG_ARCH_S3C2410 is not set
+# CONFIG_ARCH_SHARK is not set
+# CONFIG_ARCH_LH7A40X is not set
+# CONFIG_ARCH_OMAP is not set
+# CONFIG_ARCH_VERSATILE_PB is not set
+# CONFIG_ARCH_IMX is not set
+CONFIG_ARCH_H720X=y
+
+#
+# h720x Implementations
+#
+CONFIG_ARCH_H7201=y
+# CONFIG_ARCH_H7202 is not set
+CONFIG_CPU_H7201=y
+
+#
+# Processor Type
+#
+CONFIG_CPU_32=y
+CONFIG_CPU_ARM720T=y
+CONFIG_CPU_32v4=y
+CONFIG_CPU_ABRT_LV4T=y
+CONFIG_CPU_CACHE_V4=y
+CONFIG_CPU_COPY_V4WT=y
+CONFIG_CPU_TLB_V4WT=y
+
+#
+# Processor Features
+#
+CONFIG_ARM_THUMB=y
+
+#
+# General setup
+#
+# CONFIG_ZBOOT_ROM is not set
+CONFIG_ZBOOT_ROM_TEXT=0x0
+CONFIG_ZBOOT_ROM_BSS=0x0
+
+#
+# PCMCIA/CardBus support
+#
+CONFIG_PCMCIA=y
+# CONFIG_PCMCIA_DEBUG is not set
+# CONFIG_TCIC is not set
+
+#
+# At least one math emulation must be selected
+#
+CONFIG_FPE_NWFPE=y
+# CONFIG_FPE_NWFPE_XP is not set
+# CONFIG_FPE_FASTFPE is not set
+# CONFIG_VFP is not set
+CONFIG_BINFMT_ELF=y
+# CONFIG_BINFMT_AOUT is not set
+# CONFIG_BINFMT_MISC is not set
+
+#
+# Generic Driver Options
+#
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+# CONFIG_FW_LOADER is not set
+# CONFIG_PM is not set
+# CONFIG_PREEMPT is not set
+# CONFIG_ARTHUR is not set
+CONFIG_CMDLINE=""
+CONFIG_ALIGNMENT_TRAP=y
+
+#
+# Parallel port support
+#
+# CONFIG_PARPORT is not set
+
+#
+# Memory Technology Devices (MTD)
+#
+CONFIG_MTD=y
+CONFIG_MTD_DEBUG=y
+CONFIG_MTD_DEBUG_VERBOSE=0
+CONFIG_MTD_PARTITIONS=y
+# CONFIG_MTD_CONCAT is not set
+# CONFIG_MTD_REDBOOT_PARTS is not set
+# CONFIG_MTD_CMDLINE_PARTS is not set
+# CONFIG_MTD_AFS_PARTS is not set
+
+#
+# User Modules And Translation Layers
+#
+CONFIG_MTD_CHAR=y
+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=y
+# CONFIG_MTD_JEDECPROBE is not set
+CONFIG_MTD_GEN_PROBE=y
+CONFIG_MTD_CFI_ADV_OPTIONS=y
+CONFIG_MTD_CFI_NOSWAP=y
+# CONFIG_MTD_CFI_BE_BYTE_SWAP is not set
+# CONFIG_MTD_CFI_LE_BYTE_SWAP is not set
+# CONFIG_MTD_CFI_GEOMETRY 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_CFI_INTELEXT=y
+# CONFIG_MTD_CFI_AMDSTD is not set
+# CONFIG_MTD_CFI_STAA is not set
+CONFIG_MTD_CFI_UTIL=y
+# CONFIG_MTD_RAM is not set
+# CONFIG_MTD_ROM is not set
+# CONFIG_MTD_ABSENT is not set
+
+#
+# Mapping drivers for chip access
+#
+# CONFIG_MTD_COMPLEX_MAPPINGS is not set
+# CONFIG_MTD_PHYSMAP is not set
+# CONFIG_MTD_ARM_INTEGRATOR is not set
+# CONFIG_MTD_EDB7312 is not set
+# CONFIG_MTD_H720X 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 is not set
+
+#
+# Disk-On-Chip Device Drivers
+#
+# CONFIG_MTD_DOC2000 is not set
+# CONFIG_MTD_DOC2001 is not set
+# CONFIG_MTD_DOC2001PLUS is not set
+
+#
+# NAND Flash Device Drivers
+#
+# CONFIG_MTD_NAND is not set
+
+#
+# Plug and Play support
+#
+
+#
+# Block devices
+#
+# CONFIG_BLK_DEV_FD is not set
+# CONFIG_BLK_DEV_LOOP is not set
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_SIZE=8192
+CONFIG_BLK_DEV_INITRD=y
+
+#
+# Multi-device support (RAID and LVM)
+#
+# CONFIG_MD is not set
+
+#
+# Networking support
+#
+# CONFIG_NET is not set
+# CONFIG_NETPOLL is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
+
+#
+# SCSI device support
+#
+# CONFIG_SCSI is not set
+
+#
+# Fusion MPT device support
+#
+
+#
+# IEEE 1394 (FireWire) support
+#
+
+#
+# I2O device support
+#
+
+#
+# ISDN subsystem
+#
+
+#
+# Input device support
+#
+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=y
+# CONFIG_SERIO_I8042 is not set
+CONFIG_SERIO_SERPORT=y
+# CONFIG_SERIO_CT82C710 is not set
+
+#
+# Input Device Drivers
+#
+# CONFIG_INPUT_KEYBOARD is not set
+# CONFIG_INPUT_MOUSE 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
+
+#
+# Serial drivers
+#
+# CONFIG_SERIAL_8250 is not set
+
+#
+# Non-8250 serial port support
+#
+CONFIG_UNIX98_PTYS=y
+CONFIG_LEGACY_PTYS=y
+CONFIG_LEGACY_PTY_COUNT=256
+# CONFIG_QIC02_TAPE is not set
+
+#
+# IPMI
+#
+# CONFIG_IPMI_HANDLER is not set
+
+#
+# Watchdog Cards
+#
+# CONFIG_WATCHDOG is not set
+# CONFIG_NVRAM is not set
+# CONFIG_RTC is not set
+# CONFIG_GEN_RTC is not set
+# CONFIG_DTLK is not set
+# CONFIG_R3964 is not set
+
+#
+# Ftape, the floppy tape device driver
+#
+# CONFIG_AGP is not set
+# CONFIG_DRM is not set
+
+#
+# PCMCIA character devices
+#
+# CONFIG_SYNCLINK_CS is not set
+# CONFIG_RAW_DRIVER is not set
+
+#
+# I2C support
+#
+# CONFIG_I2C is not set
+
+#
+# Multimedia devices
+#
+# CONFIG_VIDEO_DEV is not set
+
+#
+# Digital Video Broadcasting Devices
+#
+
+#
+# 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_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+# CONFIG_XFS_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_ROMFS_FS is not set
+# CONFIG_QUOTA is not set
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_AUTOFS4_FS is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+# CONFIG_ISO9660_FS is not set
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+# 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_SYSFS=y
+# CONFIG_DEVFS_FS is not set
+# CONFIG_DEVPTS_FS_XATTR is not set
+# CONFIG_TMPFS is not set
+# 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_EFS_FS is not set
+# CONFIG_JFFS_FS is not set
+CONFIG_JFFS2_FS=y
+CONFIG_JFFS2_FS_DEBUG=0
+# CONFIG_JFFS2_FS_NAND is not set
+# CONFIG_JFFS2_COMPRESSION_OPTIONS is not set
+CONFIG_JFFS2_ZLIB=y
+CONFIG_JFFS2_RTIME=y
+# CONFIG_JFFS2_RUBIN is not set
+# CONFIG_CRAMFS is not set
+# CONFIG_VXFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+
+#
+# Partition Types
+#
+# CONFIG_PARTITION_ADVANCED is not set
+
+#
+# Native Language Support
+#
+# CONFIG_NLS is not set
+
+#
+# Profiling support
+#
+# CONFIG_PROFILING is not set
+
+#
+# Graphics support
+#
+# CONFIG_FB is not set
+
+#
+# Console display driver support
+#
+# CONFIG_VGA_CONSOLE is not set
+# CONFIG_MDA_CONSOLE is not set
+CONFIG_DUMMY_CONSOLE=y
+
+#
+# Sound
+#
+CONFIG_SOUND=m
+
+#
+# Advanced Linux Sound Architecture
+#
+# CONFIG_SND is not set
+
+#
+# Open Sound System
+#
+# CONFIG_SOUND_PRIME is not set
+
+#
+# Misc devices
+#
+
+#
+# USB support
+#
+
+#
+# USB Gadget Support
+#
+# CONFIG_USB_GADGET is not set
+
+#
+# MMC/SD Card support
+#
+# CONFIG_MMC is not set
+
+#
+# Kernel hacking
+#
+# CONFIG_DEBUG_KERNEL is not set
+# CONFIG_DEBUG_INFO is not set
+CONFIG_FRAME_POINTER=y
+CONFIG_DEBUG_USER=y
+
+#
+# Security options
+#
+# CONFIG_SECURITY is not set
+
+#
+# Cryptographic options
+#
+# CONFIG_CRYPTO is not set
+
+#
+# Library routines
+#
+# CONFIG_CRC_CCITT is not set
+CONFIG_CRC32=y
+# CONFIG_LIBCRC32C is not set
+CONFIG_ZLIB_INFLATE=y
+CONFIG_ZLIB_DEFLATE=y
diff -Nru a/arch/arm/configs/h7202_defconfig b/arch/arm/configs/h7202_defconfig
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/arch/arm/configs/h7202_defconfig	2004-10-18 14:57:24 -07:00
@@ -0,0 +1,652 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.9-rc1
+# Thu Sep 30 10:30:42 2004
+#
+CONFIG_ARM=y
+CONFIG_MMU=y
+CONFIG_UID16=y
+CONFIG_RWSEM_GENERIC_SPINLOCK=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_ALL is not set
+# 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=y
+
+#
+# Loadable module support
+#
+CONFIG_MODULES=y
+# CONFIG_MODULE_UNLOAD is not set
+CONFIG_OBSOLETE_MODPARM=y
+# CONFIG_MODVERSIONS is not set
+CONFIG_KMOD=y
+
+#
+# System Type
+#
+# CONFIG_ARCH_CLPS7500 is not set
+# CONFIG_ARCH_CLPS711X is not set
+# CONFIG_ARCH_CO285 is not set
+# CONFIG_ARCH_EBSA110 is not set
+# CONFIG_ARCH_CAMELOT is not set
+# CONFIG_ARCH_FOOTBRIDGE is not set
+# CONFIG_ARCH_INTEGRATOR is not set
+# CONFIG_ARCH_IOP3XX is not set
+# CONFIG_ARCH_IXP4XX is not set
+# CONFIG_ARCH_L7200 is not set
+# CONFIG_ARCH_PXA is not set
+# CONFIG_ARCH_RPC is not set
+# CONFIG_ARCH_SA1100 is not set
+# CONFIG_ARCH_S3C2410 is not set
+# CONFIG_ARCH_SHARK is not set
+# CONFIG_ARCH_LH7A40X is not set
+# CONFIG_ARCH_OMAP is not set
+# CONFIG_ARCH_VERSATILE_PB is not set
+# CONFIG_ARCH_IMX is not set
+CONFIG_ARCH_H720X=y
+
+#
+# h720x Implementations
+#
+# CONFIG_ARCH_H7201 is not set
+CONFIG_ARCH_H7202=y
+# CONFIG_ARCH_FU7202 is not set
+CONFIG_CPU_H7202=y
+
+#
+# Processor Type
+#
+CONFIG_CPU_32=y
+CONFIG_CPU_ARM720T=y
+CONFIG_CPU_32v4=y
+CONFIG_CPU_ABRT_LV4T=y
+CONFIG_CPU_CACHE_V4=y
+CONFIG_CPU_COPY_V4WT=y
+CONFIG_CPU_TLB_V4WT=y
+
+#
+# Processor Features
+#
+# CONFIG_ARM_THUMB is not set
+
+#
+# General setup
+#
+# CONFIG_ZBOOT_ROM is not set
+CONFIG_ZBOOT_ROM_TEXT=0x0
+CONFIG_ZBOOT_ROM_BSS=0x0
+
+#
+# At least one math emulation must be selected
+#
+CONFIG_FPE_NWFPE=y
+CONFIG_FPE_NWFPE_XP=y
+# CONFIG_FPE_FASTFPE is not set
+# CONFIG_VFP is not set
+CONFIG_BINFMT_ELF=y
+# CONFIG_BINFMT_AOUT is not set
+# CONFIG_BINFMT_MISC is not set
+
+#
+# Generic Driver Options
+#
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+# CONFIG_DEBUG_DRIVER is not set
+# CONFIG_PM is not set
+# CONFIG_PREEMPT is not set
+# CONFIG_ARTHUR is not set
+CONFIG_CMDLINE="console=ttyS0,19200"
+CONFIG_ALIGNMENT_TRAP=y
+
+#
+# Parallel port support
+#
+# CONFIG_PARPORT is not set
+
+#
+# Memory Technology Devices (MTD)
+#
+CONFIG_MTD=y
+# CONFIG_MTD_DEBUG is not set
+CONFIG_MTD_PARTITIONS=y
+# CONFIG_MTD_CONCAT is not set
+# CONFIG_MTD_REDBOOT_PARTS is not set
+CONFIG_MTD_CMDLINE_PARTS=y
+# CONFIG_MTD_AFS_PARTS is not set
+
+#
+# User Modules And Translation Layers
+#
+CONFIG_MTD_CHAR=y
+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=y
+# CONFIG_MTD_JEDECPROBE is not set
+CONFIG_MTD_GEN_PROBE=y
+# CONFIG_MTD_CFI_ADV_OPTIONS 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_CFI_INTELEXT=y
+# CONFIG_MTD_CFI_AMDSTD is not set
+# CONFIG_MTD_CFI_STAA is not set
+CONFIG_MTD_CFI_UTIL=y
+# CONFIG_MTD_RAM is not set
+# CONFIG_MTD_ROM is not set
+# CONFIG_MTD_ABSENT is not set
+
+#
+# Mapping drivers for chip access
+#
+# CONFIG_MTD_COMPLEX_MAPPINGS is not set
+# CONFIG_MTD_PHYSMAP is not set
+# CONFIG_MTD_ARM_INTEGRATOR is not set
+# CONFIG_MTD_EDB7312 is not set
+CONFIG_MTD_H720X=y
+
+#
+# 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 is not set
+
+#
+# Disk-On-Chip Device Drivers
+#
+# CONFIG_MTD_DOC2000 is not set
+# CONFIG_MTD_DOC2001 is not set
+# CONFIG_MTD_DOC2001PLUS is not set
+
+#
+# NAND Flash Device Drivers
+#
+# CONFIG_MTD_NAND is not set
+
+#
+# Plug and Play support
+#
+
+#
+# Block devices
+#
+# CONFIG_BLK_DEV_FD is not set
+# CONFIG_BLK_DEV_LOOP is not set
+# CONFIG_BLK_DEV_NBD is not set
+# CONFIG_BLK_DEV_RAM is not set
+
+#
+# Multi-device support (RAID and LVM)
+#
+# CONFIG_MD is not set
+
+#
+# Networking support
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+# CONFIG_PACKET is not set
+# CONFIG_NETLINK_DEV is not set
+CONFIG_UNIX=y
+# CONFIG_NET_KEY is not set
+CONFIG_INET=y
+# CONFIG_IP_MULTICAST is not set
+# CONFIG_IP_ADVANCED_ROUTER is not set
+CONFIG_IP_PNP=y
+# 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_ARPD 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
+# CONFIG_INET_TUNNEL is not set
+# CONFIG_IPV6 is not set
+# CONFIG_NETFILTER is not set
+
+#
+# SCTP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_SCTP is not set
+# CONFIG_ATM is not set
+# CONFIG_BRIDGE is not set
+# CONFIG_VLAN_8021Q is not set
+# CONFIG_DECNET 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
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+# CONFIG_NET_HW_FLOWCONTROL is not set
+
+#
+# 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
+
+#
+# Ethernet (10 or 100Mbit)
+#
+CONFIG_NET_ETHERNET=y
+# CONFIG_MII is not set
+# CONFIG_SMC91X is not set
+# CONFIG_CS89x0 is not set
+CONFIG_CIRRUS=y
+
+#
+# Ethernet (1000 Mbit)
+#
+
+#
+# Ethernet (10000 Mbit)
+#
+
+#
+# Token Ring devices
+#
+
+#
+# Wireless LAN (non-hamradio)
+#
+# CONFIG_NET_RADIO is not set
+
+#
+# Wan interfaces
+#
+# CONFIG_WAN is not set
+# CONFIG_PPP is not set
+# CONFIG_SLIP is not set
+# CONFIG_SHAPER is not set
+# CONFIG_NETCONSOLE is not set
+
+#
+# SCSI device support
+#
+# CONFIG_SCSI is not set
+
+#
+# Fusion MPT device support
+#
+
+#
+# IEEE 1394 (FireWire) support
+#
+
+#
+# I2O device support
+#
+
+#
+# ISDN subsystem
+#
+# CONFIG_ISDN is not set
+
+#
+# Input device support
+#
+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=y
+# CONFIG_SERIO_I8042 is not set
+CONFIG_SERIO_SERPORT=y
+# CONFIG_SERIO_CT82C710 is not set
+CONFIG_SERIO_H7202=y
+
+#
+# Input 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
+
+#
+# Serial drivers
+#
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_NR_UARTS=4
+# CONFIG_SERIAL_8250_EXTENDED is not set
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+CONFIG_UNIX98_PTYS=y
+CONFIG_LEGACY_PTYS=y
+CONFIG_LEGACY_PTY_COUNT=256
+# CONFIG_QIC02_TAPE is not set
+
+#
+# IPMI
+#
+# CONFIG_IPMI_HANDLER is not set
+
+#
+# Watchdog Cards
+#
+# CONFIG_WATCHDOG is not set
+# CONFIG_NVRAM is not set
+# CONFIG_RTC is not set
+# CONFIG_GEN_RTC is not set
+# CONFIG_DTLK is not set
+# CONFIG_R3964 is not set
+
+#
+# Ftape, the floppy tape device driver
+#
+# CONFIG_AGP is not set
+# CONFIG_DRM is not set
+# CONFIG_RAW_DRIVER is not set
+
+#
+# I2C support
+#
+# CONFIG_I2C is not set
+
+#
+# Multimedia devices
+#
+# CONFIG_VIDEO_DEV is not set
+
+#
+# Digital Video Broadcasting Devices
+#
+# CONFIG_DVB 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_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+# CONFIG_XFS_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_ROMFS_FS is not set
+# CONFIG_QUOTA is not set
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_AUTOFS4_FS is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+# CONFIG_ISO9660_FS is not set
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+# 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_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_EFS_FS is not set
+# CONFIG_JFFS_FS is not set
+CONFIG_JFFS2_FS=y
+CONFIG_JFFS2_FS_DEBUG=0
+# CONFIG_JFFS2_FS_NAND is not set
+# CONFIG_JFFS2_COMPRESSION_OPTIONS is not set
+CONFIG_JFFS2_ZLIB=y
+CONFIG_JFFS2_RTIME=y
+# CONFIG_JFFS2_RUBIN is not set
+# CONFIG_CRAMFS is not set
+# CONFIG_VXFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+
+#
+# Network File Systems
+#
+CONFIG_NFS_FS=y
+CONFIG_NFS_V3=y
+# CONFIG_NFS_V4 is not set
+# CONFIG_NFS_DIRECTIO is not set
+# CONFIG_NFSD is not set
+# CONFIG_ROOT_NFS is not set
+CONFIG_LOCKD=y
+CONFIG_LOCKD_V4=y
+# CONFIG_EXPORTFS is not set
+CONFIG_SUNRPC=y
+# CONFIG_RPCSEC_GSS_KRB5 is not set
+# CONFIG_RPCSEC_GSS_SPKM3 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
+
+#
+# Partition Types
+#
+# CONFIG_PARTITION_ADVANCED is not set
+
+#
+# Native Language Support
+#
+# CONFIG_NLS is not set
+
+#
+# Profiling support
+#
+# CONFIG_PROFILING is not set
+
+#
+# Graphics support
+#
+CONFIG_FB=y
+CONFIG_FB_MODE_HELPERS=y
+# CONFIG_FB_VIRTUAL is not set
+
+#
+# Console display driver support
+#
+# CONFIG_VGA_CONSOLE is not set
+# CONFIG_MDA_CONSOLE is not set
+CONFIG_DUMMY_CONSOLE=y
+# CONFIG_FRAMEBUFFER_CONSOLE is not set
+
+#
+# Logo configuration
+#
+# CONFIG_LOGO is not set
+
+#
+# Sound
+#
+# CONFIG_SOUND is not set
+
+#
+# Misc devices
+#
+
+#
+# USB support
+#
+
+#
+# USB Gadget Support
+#
+CONFIG_USB_GADGET=m
+# CONFIG_USB_GADGET_NET2280 is not set
+# CONFIG_USB_GADGET_PXA2XX is not set
+# CONFIG_USB_GADGET_GOKU is not set
+# CONFIG_USB_GADGET_SA1100 is not set
+CONFIG_USB_GADGET_H7202=y
+CONFIG_USB_H7202=m
+# CONFIG_USB_GADGET_DUMMY_HCD is not set
+# CONFIG_USB_GADGET_DUALSPEED is not set
+CONFIG_USB_ZERO=m
+# CONFIG_USB_ETH is not set
+CONFIG_USB_GADGETFS=m
+CONFIG_USB_FILE_STORAGE=m
+CONFIG_USB_FILE_STORAGE_TEST=y
+CONFIG_USB_G_SERIAL=m
+CONFIG_USB_G_MULTISER=m
+
+#
+# MMC/SD Card support
+#
+# CONFIG_MMC is not set
+
+#
+# Kernel hacking
+#
+CONFIG_DEBUG_KERNEL=y
+CONFIG_MAGIC_SYSRQ=y
+# CONFIG_DEBUG_SLAB is not set
+# CONFIG_DEBUG_SPINLOCK is not set
+# CONFIG_DEBUG_BUGVERBOSE is not set
+CONFIG_DEBUG_INFO=y
+CONFIG_FRAME_POINTER=y
+CONFIG_DEBUG_USER=y
+# CONFIG_DEBUG_WAITQ is not set
+# CONFIG_DEBUG_ERRORS is not set
+# CONFIG_DEBUG_LL is not set
+
+#
+# Security options
+#
+# CONFIG_SECURITY is not set
+
+#
+# Cryptographic options
+#
+# CONFIG_CRYPTO is not set
+
+#
+# Library routines
+#
+# CONFIG_CRC_CCITT is not set
+CONFIG_CRC32=y
+# CONFIG_LIBCRC32C is not set
+CONFIG_ZLIB_INFLATE=y
+CONFIG_ZLIB_DEFLATE=y
diff -Nru a/arch/arm/configs/iq31244_defconfig b/arch/arm/configs/iq31244_defconfig
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/arch/arm/configs/iq31244_defconfig	2004-10-18 14:57:24 -07:00
@@ -0,0 +1,818 @@
+#
+# Automatically generated make config: don't edit
+#
+CONFIG_ARM=y
+CONFIG_MMU=y
+CONFIG_UID16=y
+CONFIG_RWSEM_GENERIC_SPINLOCK=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_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=y
+
+#
+# Loadable module support
+#
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+# CONFIG_MODULE_FORCE_UNLOAD is not set
+CONFIG_OBSOLETE_MODPARM=y
+# CONFIG_MODVERSIONS is not set
+CONFIG_KMOD=y
+
+#
+# System Type
+#
+# CONFIG_ARCH_CLPS7500 is not set
+# CONFIG_ARCH_CLPS711X is not set
+# CONFIG_ARCH_CO285 is not set
+# CONFIG_ARCH_EBSA110 is not set
+# CONFIG_ARCH_CAMELOT is not set
+# CONFIG_ARCH_FOOTBRIDGE is not set
+# CONFIG_ARCH_INTEGRATOR is not set
+CONFIG_ARCH_IOP3XX=y
+# CONFIG_ARCH_IXP4XX is not set
+# CONFIG_ARCH_L7200 is not set
+# CONFIG_ARCH_PXA is not set
+# CONFIG_ARCH_RPC is not set
+# CONFIG_ARCH_SA1100 is not set
+# CONFIG_ARCH_S3C2410 is not set
+# CONFIG_ARCH_SHARK is not set
+# CONFIG_ARCH_LH7A40X is not set
+# CONFIG_ARCH_OMAP is not set
+# CONFIG_ARCH_VERSATILE_PB is not set
+
+#
+# IOP3xx Implementation Options
+#
+
+#
+# IOP3xx Platform Types
+#
+# CONFIG_ARCH_IQ80321 is not set
+CONFIG_ARCH_IQ31244=y
+# CONFIG_ARCH_IQ80331 is not set
+# CONFIG_ARCH_EP80219 is not set
+CONFIG_ARCH_IOP321=y
+# CONFIG_ARCH_IOP331 is not set
+
+#
+# IOP3xx Chipset Features
+#
+
+#
+# Processor Type
+#
+CONFIG_CPU_32=y
+CONFIG_CPU_XSCALE=y
+CONFIG_CPU_32v5=y
+CONFIG_CPU_ABRT_EV5T=y
+CONFIG_CPU_TLB_V4WBI=y
+CONFIG_CPU_MINICACHE=y
+
+#
+# Processor Features
+#
+# CONFIG_ARM_THUMB is not set
+CONFIG_XSCALE_PMU=y
+
+#
+# General setup
+#
+CONFIG_PCI=y
+# CONFIG_ZBOOT_ROM is not set
+CONFIG_ZBOOT_ROM_TEXT=0x0
+CONFIG_ZBOOT_ROM_BSS=0x0
+# CONFIG_PCI_LEGACY_PROC is not set
+CONFIG_PCI_NAMES=y
+
+#
+# At least one math emulation must be selected
+#
+CONFIG_FPE_NWFPE=y
+# CONFIG_FPE_NWFPE_XP is not set
+# CONFIG_FPE_FASTFPE is not set
+# CONFIG_VFP is not set
+CONFIG_BINFMT_ELF=y
+CONFIG_BINFMT_AOUT=y
+# CONFIG_BINFMT_MISC is not set
+
+#
+# Generic Driver Options
+#
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+# CONFIG_PM is not set
+# CONFIG_PREEMPT is not set
+# CONFIG_ARTHUR is not set
+CONFIG_CMDLINE="ip=boot root=nfs console=ttyS0,115200 mem=256M@0xa0000000"
+CONFIG_ALIGNMENT_TRAP=y
+
+#
+# Parallel port support
+#
+# CONFIG_PARPORT is not set
+
+#
+# Memory Technology Devices (MTD)
+#
+CONFIG_MTD=y
+# CONFIG_MTD_DEBUG is not set
+CONFIG_MTD_PARTITIONS=y
+# CONFIG_MTD_CONCAT is not set
+CONFIG_MTD_REDBOOT_PARTS=y
+# CONFIG_MTD_REDBOOT_PARTS_UNALLOCATED is not set
+# CONFIG_MTD_REDBOOT_PARTS_READONLY is not set
+# CONFIG_MTD_CMDLINE_PARTS is not set
+# CONFIG_MTD_AFS_PARTS is not set
+
+#
+# User Modules And Translation Layers
+#
+CONFIG_MTD_CHAR=y
+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=y
+# CONFIG_MTD_JEDECPROBE is not set
+CONFIG_MTD_GEN_PROBE=y
+# CONFIG_MTD_CFI_ADV_OPTIONS 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_CFI_INTELEXT=y
+# CONFIG_MTD_CFI_AMDSTD is not set
+# CONFIG_MTD_CFI_STAA is not set
+CONFIG_MTD_CFI_UTIL=y
+# CONFIG_MTD_RAM is not set
+# CONFIG_MTD_ROM is not set
+# CONFIG_MTD_ABSENT is not set
+
+#
+# Mapping drivers for chip access
+#
+# CONFIG_MTD_COMPLEX_MAPPINGS is not set
+# CONFIG_MTD_PHYSMAP is not set
+# CONFIG_MTD_ARM_INTEGRATOR is not set
+# CONFIG_MTD_EDB7312 is not set
+
+#
+# Self-contained MTD device drivers
+#
+# CONFIG_MTD_PMC551 is not set
+# CONFIG_MTD_SLRAM is not set
+# CONFIG_MTD_PHRAM is not set
+# CONFIG_MTD_MTDRAM is not set
+# CONFIG_MTD_BLKMTD is not set
+
+#
+# Disk-On-Chip Device Drivers
+#
+# CONFIG_MTD_DOC2000 is not set
+# CONFIG_MTD_DOC2001 is not set
+# CONFIG_MTD_DOC2001PLUS is not set
+
+#
+# NAND Flash Device Drivers
+#
+# CONFIG_MTD_NAND is not set
+
+#
+# Plug and Play support
+#
+
+#
+# Block devices
+#
+# CONFIG_BLK_DEV_FD is not set
+# CONFIG_BLK_CPQ_DA is not set
+# CONFIG_BLK_CPQ_CISS_DA is not set
+# CONFIG_BLK_DEV_DAC960 is not set
+# 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=8192
+# CONFIG_BLK_DEV_INITRD is not set
+
+#
+# Multi-device support (RAID and LVM)
+#
+CONFIG_MD=y
+CONFIG_BLK_DEV_MD=y
+# CONFIG_MD_LINEAR is not set
+CONFIG_MD_RAID0=y
+CONFIG_MD_RAID1=y
+CONFIG_MD_RAID5=y
+# CONFIG_MD_RAID6 is not set
+# CONFIG_MD_MULTIPATH is not set
+CONFIG_BLK_DEV_DM=y
+# CONFIG_DM_CRYPT is not set
+# CONFIG_DM_SNAPSHOT is not set
+# CONFIG_DM_MIRROR is not set
+# CONFIG_DM_ZERO is not set
+
+#
+# Networking support
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+CONFIG_PACKET=y
+CONFIG_PACKET_MMAP=y
+# CONFIG_NETLINK_DEV 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 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_SYN_COOKIES is not set
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+# CONFIG_IPV6 is not set
+# CONFIG_NETFILTER is not set
+
+#
+# SCTP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_SCTP is not set
+# CONFIG_ATM is not set
+# CONFIG_BRIDGE is not set
+# CONFIG_VLAN_8021Q is not set
+# CONFIG_DECNET 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
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+# CONFIG_NET_HW_FLOWCONTROL is not set
+
+#
+# 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
+
+#
+# Ethernet (10 or 100Mbit)
+#
+# CONFIG_NET_ETHERNET is not set
+
+#
+# Ethernet (1000 Mbit)
+#
+# CONFIG_ACENIC is not set
+# CONFIG_DL2K is not set
+CONFIG_E1000=y
+CONFIG_E1000_NAPI=y
+# CONFIG_NS83820 is not set
+# CONFIG_HAMACHI is not set
+# CONFIG_YELLOWFIN is not set
+# CONFIG_R8169 is not set
+# CONFIG_SK98LIN is not set
+# CONFIG_TIGON3 is not set
+
+#
+# Ethernet (10000 Mbit)
+#
+# CONFIG_IXGB is not set
+# CONFIG_S2IO is not set
+
+#
+# Token Ring devices
+#
+# CONFIG_TR is not set
+
+#
+# Wireless LAN (non-hamradio)
+#
+# CONFIG_NET_RADIO is not set
+
+#
+# Wan interfaces
+#
+# CONFIG_WAN 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
+
+#
+# ATA/ATAPI/MFM/RLL support
+#
+# CONFIG_IDE is not set
+
+#
+# SCSI device support
+#
+CONFIG_SCSI=y
+CONFIG_SCSI_PROC_FS=y
+
+#
+# SCSI support type (disk, tape, CD-ROM)
+#
+CONFIG_BLK_DEV_SD=y
+# CONFIG_CHR_DEV_ST is not set
+# CONFIG_CHR_DEV_OSST is not set
+# CONFIG_BLK_DEV_SR is not set
+CONFIG_CHR_DEV_SG=y
+
+#
+# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
+#
+# CONFIG_SCSI_MULTI_LUN is not set
+# CONFIG_SCSI_CONSTANTS is not set
+# CONFIG_SCSI_LOGGING is not set
+
+#
+# SCSI Transport Attributes
+#
+# CONFIG_SCSI_SPI_ATTRS is not set
+# 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_MEGARAID is not set
+# CONFIG_SCSI_SATA is not set
+# CONFIG_SCSI_BUSLOGIC 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_IPS is not set
+# CONFIG_SCSI_INIA100 is not set
+# CONFIG_SCSI_SYM53C8XX_2 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_NSP32 is not set
+# CONFIG_SCSI_DEBUG is not set
+
+#
+# Fusion MPT device support
+#
+# CONFIG_FUSION is not set
+
+#
+# IEEE 1394 (FireWire) support
+#
+# CONFIG_IEEE1394 is not set
+
+#
+# I2O device support
+#
+# CONFIG_I2O is not set
+
+#
+# ISDN subsystem
+#
+# CONFIG_ISDN is not set
+
+#
+# Input device support
+#
+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_I8042 is not set
+
+#
+# Input Device Drivers
+#
+# CONFIG_INPUT_KEYBOARD is not set
+# CONFIG_INPUT_MOUSE 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
+
+#
+# Serial drivers
+#
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_NR_UARTS=4
+# CONFIG_SERIAL_8250_EXTENDED is not set
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+CONFIG_UNIX98_PTYS=y
+CONFIG_LEGACY_PTYS=y
+CONFIG_LEGACY_PTY_COUNT=256
+# CONFIG_QIC02_TAPE is not set
+
+#
+# IPMI
+#
+# CONFIG_IPMI_HANDLER is not set
+
+#
+# Watchdog Cards
+#
+# CONFIG_WATCHDOG is not set
+# CONFIG_NVRAM is not set
+# CONFIG_RTC is not set
+# CONFIG_GEN_RTC is not set
+# CONFIG_DTLK is not set
+# CONFIG_R3964 is not set
+# CONFIG_APPLICOM is not set
+
+#
+# Ftape, the floppy tape device driver
+#
+# CONFIG_AGP is not set
+# CONFIG_DRM is not set
+# CONFIG_RAW_DRIVER is not set
+
+#
+# I2C support
+#
+CONFIG_I2C=y
+CONFIG_I2C_CHARDEV=y
+
+#
+# I2C Algorithms
+#
+# CONFIG_I2C_ALGOBIT is not set
+# CONFIG_I2C_ALGOPCF is not set
+
+#
+# I2C Hardware Bus support
+#
+# CONFIG_I2C_ALI1535 is not set
+# CONFIG_I2C_ALI1563 is not set
+# CONFIG_I2C_ALI15X3 is not set
+# CONFIG_I2C_AMD756 is not set
+# CONFIG_I2C_AMD8111 is not set
+# CONFIG_I2C_I801 is not set
+# CONFIG_I2C_I810 is not set
+CONFIG_I2C_IOP3XX=y
+# CONFIG_I2C_ISA is not set
+# CONFIG_I2C_NFORCE2 is not set
+# CONFIG_I2C_PARPORT_LIGHT is not set
+# CONFIG_I2C_PIIX4 is not set
+# CONFIG_I2C_PROSAVAGE is not set
+# CONFIG_I2C_SAVAGE4 is not set
+# CONFIG_SCx200_ACB is not set
+# CONFIG_I2C_SIS5595 is not set
+# CONFIG_I2C_SIS630 is not set
+# CONFIG_I2C_SIS96X is not set
+# CONFIG_I2C_VIA is not set
+# CONFIG_I2C_VIAPRO is not set
+# CONFIG_I2C_VOODOO3 is not set
+
+#
+# Hardware Sensors Chip support
+#
+# CONFIG_I2C_SENSOR is not set
+# CONFIG_SENSORS_ADM1021 is not set
+# CONFIG_SENSORS_ADM1025 is not set
+# CONFIG_SENSORS_ADM1031 is not set
+# CONFIG_SENSORS_ASB100 is not set
+# CONFIG_SENSORS_DS1621 is not set
+# CONFIG_SENSORS_FSCHER is not set
+# CONFIG_SENSORS_GL518SM is not set
+# CONFIG_SENSORS_IT87 is not set
+# CONFIG_SENSORS_LM75 is not set
+# CONFIG_SENSORS_LM77 is not set
+# CONFIG_SENSORS_LM78 is not set
+# CONFIG_SENSORS_LM80 is not set
+# CONFIG_SENSORS_LM83 is not set
+# CONFIG_SENSORS_LM85 is not set
+# CONFIG_SENSORS_LM90 is not set
+# CONFIG_SENSORS_MAX1619 is not set
+# CONFIG_SENSORS_VIA686A is not set
+# CONFIG_SENSORS_W83781D is not set
+# CONFIG_SENSORS_W83L785TS is not set
+# CONFIG_SENSORS_W83627HF is not set
+
+#
+# Other I2C Chip support
+#
+# CONFIG_SENSORS_EEPROM is not set
+# CONFIG_SENSORS_PCF8574 is not set
+# CONFIG_SENSORS_PCF8591 is not set
+# CONFIG_SENSORS_RTC8564 is not set
+# CONFIG_I2C_DEBUG_CORE is not set
+# CONFIG_I2C_DEBUG_ALGO is not set
+# CONFIG_I2C_DEBUG_BUS is not set
+# CONFIG_I2C_DEBUG_CHIP is not set
+
+#
+# Multimedia devices
+#
+# CONFIG_VIDEO_DEV is not set
+
+#
+# Digital Video Broadcasting Devices
+#
+# CONFIG_DVB is not set
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+# CONFIG_EXT2_FS_XATTR is not set
+CONFIG_EXT3_FS=y
+CONFIG_EXT3_FS_XATTR=y
+# CONFIG_EXT3_FS_POSIX_ACL is not set
+# CONFIG_EXT3_FS_SECURITY is not set
+CONFIG_JBD=y
+# CONFIG_JBD_DEBUG is not set
+CONFIG_FS_MBCACHE=y
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+CONFIG_XFS_FS=y
+# CONFIG_XFS_RT is not set
+# CONFIG_XFS_QUOTA is not set
+CONFIG_XFS_SECURITY=y
+CONFIG_XFS_POSIX_ACL=y
+# CONFIG_MINIX_FS is not set
+# CONFIG_ROMFS_FS is not set
+# CONFIG_QUOTA is not set
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_AUTOFS4_FS is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+# CONFIG_ISO9660_FS is not set
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+# 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_SYSFS=y
+# CONFIG_DEVFS_FS 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_EFS_FS is not set
+# CONFIG_JFFS_FS is not set
+CONFIG_JFFS2_FS=y
+CONFIG_JFFS2_FS_DEBUG=0
+# CONFIG_JFFS2_FS_NAND is not set
+# CONFIG_JFFS2_COMPRESSION_OPTIONS is not set
+CONFIG_JFFS2_ZLIB=y
+CONFIG_JFFS2_RTIME=y
+# CONFIG_JFFS2_RUBIN is not set
+# CONFIG_CRAMFS is not set
+# CONFIG_VXFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+
+#
+# Network File Systems
+#
+CONFIG_NFS_FS=y
+CONFIG_NFS_V3=y
+# CONFIG_NFS_V4 is not set
+# CONFIG_NFS_DIRECTIO is not set
+CONFIG_NFSD=y
+CONFIG_NFSD_V3=y
+# CONFIG_NFSD_V4 is not set
+# CONFIG_NFSD_TCP is not set
+CONFIG_ROOT_NFS=y
+CONFIG_LOCKD=y
+CONFIG_LOCKD_V4=y
+CONFIG_EXPORTFS=y
+CONFIG_SUNRPC=y
+# 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_AFS_FS is not set
+
+#
+# Partition Types
+#
+CONFIG_PARTITION_ADVANCED=y
+# CONFIG_ACORN_PARTITION is not set
+# CONFIG_OSF_PARTITION is not set
+# CONFIG_AMIGA_PARTITION is not set
+# CONFIG_ATARI_PARTITION is not set
+# CONFIG_MAC_PARTITION is not set
+CONFIG_MSDOS_PARTITION=y
+# CONFIG_BSD_DISKLABEL is not set
+# CONFIG_MINIX_SUBPARTITION is not set
+# CONFIG_SOLARIS_X86_PARTITION is not set
+# CONFIG_UNIXWARE_DISKLABEL is not set
+# CONFIG_LDM_PARTITION is not set
+# CONFIG_SGI_PARTITION is not set
+# CONFIG_ULTRIX_PARTITION is not set
+# CONFIG_SUN_PARTITION is not set
+# CONFIG_EFI_PARTITION is not set
+
+#
+# Native Language Support
+#
+# CONFIG_NLS is not set
+
+#
+# Profiling support
+#
+# CONFIG_PROFILING is not set
+
+#
+# Graphics support
+#
+# CONFIG_FB is not set
+
+#
+# Console display driver support
+#
+# CONFIG_VGA_CONSOLE is not set
+# CONFIG_MDA_CONSOLE is not set
+CONFIG_DUMMY_CONSOLE=y
+
+#
+# Sound
+#
+# CONFIG_SOUND is not set
+
+#
+# Misc devices
+#
+
+#
+# USB support
+#
+# CONFIG_USB is not set
+
+#
+# USB Gadget Support
+#
+# CONFIG_USB_GADGET is not set
+
+#
+# Kernel hacking
+#
+CONFIG_FRAME_POINTER=y
+CONFIG_DEBUG_USER=y
+# CONFIG_DEBUG_INFO is not set
+# CONFIG_DEBUG_KERNEL is not set
+
+#
+# Security options
+#
+# CONFIG_SECURITY is not set
+
+#
+# Cryptographic options
+#
+# CONFIG_CRYPTO is not set
+
+#
+# Library routines
+#
+# CONFIG_CRC_CCITT is not set
+CONFIG_CRC32=y
+# CONFIG_LIBCRC32C is not set
+CONFIG_ZLIB_INFLATE=y
+CONFIG_ZLIB_DEFLATE=y
diff -Nru a/arch/arm/configs/iq80310_defconfig b/arch/arm/configs/iq80310_defconfig
--- a/arch/arm/configs/iq80310_defconfig	2004-10-18 14:56:14 -07:00
+++ /dev/null	Wed Dec 31 16:00:00 196900
@@ -1,768 +0,0 @@
-#
-# Automatically generated make config: don't edit
-#
-CONFIG_ARM=y
-CONFIG_MMU=y
-CONFIG_UID16=y
-CONFIG_RWSEM_GENERIC_SPINLOCK=y
-
-#
-# Code maturity level options
-#
-CONFIG_EXPERIMENTAL=y
-
-#
-# General setup
-#
-CONFIG_SWAP=y
-CONFIG_SYSVIPC=y
-# CONFIG_BSD_PROCESS_ACCT is not set
-CONFIG_SYSCTL=y
-CONFIG_LOG_BUF_SHIFT=14
-# CONFIG_EMBEDDED is not set
-CONFIG_KALLSYMS=y
-CONFIG_FUTEX=y
-CONFIG_EPOLL=y
-CONFIG_IOSCHED_AS=y
-CONFIG_IOSCHED_DEADLINE=y
-
-#
-# Loadable module support
-#
-CONFIG_MODULES=y
-# CONFIG_MODULE_UNLOAD is not set
-CONFIG_OBSOLETE_MODPARM=y
-# CONFIG_MODVERSIONS is not set
-CONFIG_KMOD=y
-
-#
-# System Type
-#
-# CONFIG_ARCH_ADIFCC is not set
-# CONFIG_ARCH_CLPS7500 is not set
-# CONFIG_ARCH_CLPS711X is not set
-# CONFIG_ARCH_CO285 is not set
-# CONFIG_ARCH_PXA is not set
-# CONFIG_ARCH_EBSA110 is not set
-# CONFIG_ARCH_CAMELOT is not set
-# CONFIG_ARCH_FOOTBRIDGE is not set
-# CONFIG_ARCH_INTEGRATOR is not set
-CONFIG_ARCH_IOP3XX=y
-# CONFIG_ARCH_L7200 is not set
-# CONFIG_ARCH_RPC is not set
-# CONFIG_ARCH_SA1100 is not set
-# CONFIG_ARCH_SHARK is not set
-
-#
-# CLPS711X/EP721X Implementations
-#
-
-#
-# Epxa10db
-#
-
-#
-# Footbridge Implementations
-#
-
-#
-# IOP3xx Implementation Options
-#
-CONFIG_ARCH_IQ80310=y
-# CONFIG_ARCH_IQ80321 is not set
-CONFIG_ARCH_IOP310=y
-# CONFIG_ARCH_IOP321 is not set
-
-#
-# IOP3xx Chipset Features
-#
-# CONFIG_IOP3XX_AAU is not set
-# CONFIG_IOP3XX_DMA is not set
-# CONFIG_IOP3XX_MU is not set
-# CONFIG_IOP3XX_PMON is not set
-
-#
-# ADIFCC Implementation Options
-#
-
-#
-# ADI Board Types
-#
-
-#
-# Intel PXA250/210 Implementations
-#
-
-#
-# SA11x0 Implementations
-#
-
-#
-# Processor Type
-#
-CONFIG_CPU_32=y
-CONFIG_CPU_XSCALE=y
-CONFIG_XS80200=y
-CONFIG_CPU_32v5=y
-
-#
-# Processor Features
-#
-CONFIG_ARM_THUMB=y
-CONFIG_XSCALE_PMU=y
-
-#
-# General setup
-#
-CONFIG_PCI=y
-# CONFIG_ZBOOT_ROM is not set
-CONFIG_ZBOOT_ROM_TEXT=0x00060000
-CONFIG_ZBOOT_ROM_BSS=0xa1008000
-# CONFIG_PCI_LEGACY_PROC is not set
-CONFIG_PCI_NAMES=y
-# CONFIG_HOTPLUG is not set
-
-#
-# MMC/SD Card support
-#
-# CONFIG_MMC is not set
-
-#
-# At least one math emulation must be selected
-#
-CONFIG_FPE_NWFPE=y
-# CONFIG_FPE_NWFPE_XP is not set
-# CONFIG_FPE_FASTFPE is not set
-CONFIG_KCORE_ELF=y
-# CONFIG_KCORE_AOUT is not set
-CONFIG_BINFMT_AOUT=y
-CONFIG_BINFMT_ELF=y
-# CONFIG_BINFMT_MISC is not set
-# CONFIG_PM is not set
-# CONFIG_PREEMPT is not set
-# CONFIG_ARTHUR is not set
-CONFIG_CMDLINE="console=ttyS0,115200 ip=bootp mem=32M root=/dev/nfs initrd=0xc0800000,4M"
-CONFIG_ALIGNMENT_TRAP=y
-
-#
-# Parallel port support
-#
-# CONFIG_PARPORT is not set
-
-#
-# Memory Technology Devices (MTD)
-#
-CONFIG_MTD=y
-# CONFIG_MTD_DEBUG is not set
-CONFIG_MTD_PARTITIONS=y
-# CONFIG_MTD_CONCAT is not set
-CONFIG_MTD_REDBOOT_PARTS=y
-# CONFIG_MTD_CMDLINE_PARTS is not set
-# CONFIG_MTD_AFS_PARTS is not set
-
-#
-# User Modules And Translation Layers
-#
-CONFIG_MTD_CHAR=y
-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=y
-# CONFIG_MTD_JEDECPROBE is not set
-CONFIG_MTD_GEN_PROBE=y
-# CONFIG_MTD_CFI_ADV_OPTIONS is not set
-CONFIG_MTD_CFI_INTELEXT=y
-# CONFIG_MTD_CFI_AMDSTD is not set
-# CONFIG_MTD_CFI_STAA 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
-# CONFIG_MTD_PHYSMAP is not set
-# CONFIG_MTD_ARM_INTEGRATOR is not set
-CONFIG_MTD_IQ80310=y
-# CONFIG_MTD_EDB7312 is not set
-
-#
-# Self-contained MTD device drivers
-#
-# CONFIG_MTD_PMC551 is not set
-# CONFIG_MTD_SLRAM is not set
-# CONFIG_MTD_MTDRAM is not set
-# CONFIG_MTD_BLKMTD is not set
-
-#
-# Disk-On-Chip Device Drivers
-#
-# CONFIG_MTD_DOC2000 is not set
-# CONFIG_MTD_DOC2001 is not set
-# CONFIG_MTD_DOC2001PLUS is not set
-
-#
-# NAND Flash Device Drivers
-#
-# CONFIG_MTD_NAND is not set
-
-#
-# Plug and Play support
-#
-# CONFIG_PNP is not set
-
-#
-# Block devices
-#
-# CONFIG_BLK_DEV_FD is not set
-# CONFIG_BLK_CPQ_DA is not set
-# CONFIG_BLK_CPQ_CISS_DA is not set
-# CONFIG_BLK_DEV_DAC960 is not set
-# CONFIG_BLK_DEV_UMEM is not set
-# CONFIG_BLK_DEV_LOOP is not set
-# CONFIG_BLK_DEV_NBD is not set
-CONFIG_BLK_DEV_RAM=y
-CONFIG_BLK_DEV_RAM_SIZE=8192
-CONFIG_BLK_DEV_INITRD=y
-
-#
-# Multi-device support (RAID and LVM)
-#
-# CONFIG_MD is not set
-
-#
-# Networking support
-#
-CONFIG_NET=y
-
-#
-# Networking options
-#
-# CONFIG_PACKET 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 is not set
-# CONFIG_IP_ADVANCED_ROUTER is not set
-CONFIG_IP_PNP=y
-# 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_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: Netfilter Configuration
-#
-# CONFIG_IP_NF_CONNTRACK is not set
-# CONFIG_IP_NF_QUEUE is not set
-# CONFIG_IP_NF_IPTABLES is not set
-# CONFIG_IP_NF_ARPTABLES is not set
-# CONFIG_IP_NF_COMPAT_IPCHAINS is not set
-# CONFIG_IP_NF_COMPAT_IPFWADM is not set
-
-#
-# IP: Virtual Server Configuration
-#
-# CONFIG_IP_VS is not set
-# CONFIG_IPV6 is not set
-# CONFIG_XFRM_USER is not set
-
-#
-# SCTP Configuration (EXPERIMENTAL)
-#
-CONFIG_IPV6_SCTP__=y
-# CONFIG_IP_SCTP is not set
-# CONFIG_ATM 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_X25 is not set
-# CONFIG_LAPB is not set
-# CONFIG_NET_DIVERT is not set
-# CONFIG_ECONET is not set
-# CONFIG_WAN_ROUTER is not set
-# CONFIG_NET_HW_FLOWCONTROL is not set
-
-#
-# QoS and/or fair queueing
-#
-# CONFIG_NET_SCHED is not set
-
-#
-# Network testing
-#
-# CONFIG_NET_PKTGEN is not set
-CONFIG_NETDEVICES=y
-
-#
-# 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_SMC91X is not set
-# CONFIG_HAPPYMEAL is not set
-# CONFIG_SUNGEM is not set
-# CONFIG_NET_VENDOR_3COM is not set
-
-#
-# Tulip family network device support
-#
-# CONFIG_NET_TULIP is not set
-# CONFIG_HP100 is not set
-CONFIG_NET_PCI=y
-# CONFIG_PCNET32 is not set
-# CONFIG_AMD8111_ETH is not set
-# CONFIG_ADAPTEC_STARFIRE is not set
-# CONFIG_B44 is not set
-# CONFIG_DGRS is not set
-CONFIG_EEPRO100=y
-# CONFIG_EEPRO100_PIO is not set
-# CONFIG_E100 is not set
-# CONFIG_FEALNX is not set
-# CONFIG_NATSEMI is not set
-# CONFIG_NE2K_PCI 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_TLAN is not set
-# CONFIG_VIA_RHINE is not set
-
-#
-# Ethernet (1000 Mbit)
-#
-# CONFIG_ACENIC is not set
-# CONFIG_DL2K is not set
-# CONFIG_E1000 is not set
-# CONFIG_NS83820 is not set
-# CONFIG_HAMACHI is not set
-# CONFIG_YELLOWFIN is not set
-# CONFIG_R8169 is not set
-# CONFIG_SK98LIN is not set
-# CONFIG_TIGON3 is not set
-
-#
-# 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
-
-#
-# Wireless LAN (non-hamradio)
-#
-# CONFIG_NET_RADIO is not set
-
-#
-# Token Ring devices (depends on LLC=y)
-#
-# CONFIG_RCPCI is not set
-# CONFIG_SHAPER is not set
-
-#
-# Wan interfaces
-#
-# CONFIG_WAN is not set
-
-#
-# IrDA (infrared) support
-#
-# CONFIG_IRDA is not set
-
-#
-# Amateur Radio support
-#
-# CONFIG_HAMRADIO is not set
-
-#
-# 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_IDEDISK=y
-# CONFIG_IDEDISK_MULTI_MODE is not set
-# CONFIG_IDEDISK_STROKE is not set
-CONFIG_BLK_DEV_IDECD=y
-# CONFIG_BLK_DEV_IDEFLOPPY is not set
-# CONFIG_IDE_TASK_IOCTL is not set
-# CONFIG_IDE_TASKFILE_IO is not set
-
-#
-# IDE chipset support/bugfixes
-#
-# CONFIG_BLK_DEV_IDEPCI is not set
-
-#
-# SCSI device support
-#
-# CONFIG_SCSI is not set
-
-#
-# IEEE 1394 (FireWire) support (EXPERIMENTAL)
-#
-# CONFIG_IEEE1394 is not set
-
-#
-# I2O device support
-#
-# CONFIG_I2O is not set
-
-#
-# ISDN subsystem
-#
-# CONFIG_ISDN_BOOL is not set
-
-#
-# Input device support
-#
-# CONFIG_INPUT is not set
-
-#
-# Userland interfaces
-#
-
-#
-# Input I/O drivers
-#
-# CONFIG_GAMEPORT is not set
-CONFIG_SOUND_GAMEPORT=y
-# CONFIG_SERIO is not set
-
-#
-# Input Device Drivers
-#
-
-#
-# Character devices
-#
-# CONFIG_SERIAL_NONSTANDARD is not set
-
-#
-# Serial drivers
-#
-CONFIG_SERIAL_8250=y
-CONFIG_SERIAL_8250_CONSOLE=y
-# CONFIG_SERIAL_8250_EXTENDED is not set
-
-#
-# Non-8250 serial port support
-#
-# CONFIG_SERIAL_DZ is not set
-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
-
-#
-# L3 serial bus support
-#
-# CONFIG_L3 is not set
-
-#
-# Mice
-#
-# CONFIG_BUSMOUSE is not set
-# CONFIG_QIC02_TAPE is not set
-
-#
-# IPMI
-#
-# CONFIG_IPMI_HANDLER is not set
-
-#
-# Watchdog Cards
-#
-# CONFIG_WATCHDOG is not set
-# CONFIG_NVRAM is not set
-# CONFIG_RTC is not set
-# CONFIG_GEN_RTC is not set
-# CONFIG_DTLK is not set
-# CONFIG_R3964 is not set
-# CONFIG_APPLICOM is not set
-
-#
-# 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
-
-#
-# Multimedia devices
-#
-CONFIG_VIDEO_DEV=y
-
-#
-# Video For Linux
-#
-# CONFIG_VIDEO_PROC_FS is not set
-
-#
-# Video Adapters
-#
-# CONFIG_VIDEO_PMS is not set
-# CONFIG_VIDEO_CPIA is not set
-# CONFIG_VIDEO_STRADIS is not set
-# CONFIG_VIDEO_HEXIUM_ORION is not set
-# CONFIG_VIDEO_HEXIUM_GEMINI is not set
-
-#
-# Radio Adapters
-#
-# CONFIG_RADIO_GEMTEK_PCI is not set
-# CONFIG_RADIO_MAXIRADIO is not set
-# CONFIG_RADIO_MAESTRO is not set
-
-#
-# Digital Video Broadcasting Devices
-#
-CONFIG_DVB=y
-CONFIG_DVB_CORE=y
-
-#
-# Supported Frontend Modules
-#
-# CONFIG_DVB_STV0299 is not set
-# CONFIG_DVB_ALPS_BSRV2 is not set
-# CONFIG_DVB_ALPS_TDLB7 is not set
-# CONFIG_DVB_ALPS_TDMB7 is not set
-# CONFIG_DVB_ATMEL_AT76C651 is not set
-# CONFIG_DVB_CX24110 is not set
-# CONFIG_DVB_GRUNDIG_29504_491 is not set
-# CONFIG_DVB_GRUNDIG_29504_401 is not set
-# CONFIG_DVB_MT312 is not set
-# CONFIG_DVB_VES1820 is not set
-# CONFIG_DVB_TDA1004X is not set
-
-#
-# Supported SAA7146 based PCI Adapters
-#
-# CONFIG_DVB_AV7110 is not set
-# CONFIG_DVB_BUDGET is not set
-
-#
-# Supported FlexCopII (B2C2) Adapters
-#
-# CONFIG_DVB_B2C2_SKYSTAR is not set
-# CONFIG_VIDEO_BTCX 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_REISERFS_FS is not set
-# CONFIG_JFS_FS is not set
-# CONFIG_XFS_FS is not set
-# CONFIG_MINIX_FS is not set
-# CONFIG_ROMFS_FS is not set
-# CONFIG_QUOTA is not set
-# CONFIG_AUTOFS_FS is not set
-# CONFIG_AUTOFS4_FS is not set
-
-#
-# CD-ROM/DVD Filesystems
-#
-# CONFIG_ISO9660_FS is not set
-# CONFIG_UDF_FS is not set
-
-#
-# DOS/FAT/NT Filesystems
-#
-# CONFIG_FAT_FS is not set
-# CONFIG_NTFS_FS is not set
-
-#
-# Pseudo filesystems
-#
-CONFIG_PROC_FS=y
-# CONFIG_DEVFS_FS is not set
-CONFIG_DEVPTS_FS=y
-# CONFIG_DEVPTS_FS_XATTR is not set
-CONFIG_TMPFS=y
-CONFIG_RAMFS=y
-
-#
-# Miscellaneous filesystems
-#
-# CONFIG_ADFS_FS is not set
-# CONFIG_AFFS_FS is not set
-# CONFIG_HFS_FS is not set
-# CONFIG_BEFS_FS is not set
-# CONFIG_BFS_FS is not set
-# CONFIG_EFS_FS is not set
-# CONFIG_JFFS_FS is not set
-CONFIG_JFFS2_FS=y
-CONFIG_JFFS2_FS_DEBUG=0
-# CONFIG_JFFS2_FS_NAND is not set
-# CONFIG_CRAMFS is not set
-# CONFIG_VXFS_FS is not set
-# CONFIG_HPFS_FS is not set
-# CONFIG_QNX4FS_FS is not set
-# CONFIG_SYSV_FS is not set
-# CONFIG_UFS_FS is not set
-
-#
-# Network File Systems
-#
-CONFIG_NFS_FS=y
-# CONFIG_NFS_V3 is not set
-# CONFIG_NFS_V4 is not set
-# CONFIG_NFSD is not set
-CONFIG_ROOT_NFS=y
-CONFIG_LOCKD=y
-# CONFIG_EXPORTFS is not set
-CONFIG_SUNRPC=y
-# CONFIG_SUNRPC_GSS 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
-
-#
-# Partition Types
-#
-CONFIG_PARTITION_ADVANCED=y
-# CONFIG_ACORN_PARTITION is not set
-# CONFIG_OSF_PARTITION is not set
-# CONFIG_AMIGA_PARTITION is not set
-# CONFIG_ATARI_PARTITION is not set
-# CONFIG_MAC_PARTITION is not set
-CONFIG_MSDOS_PARTITION=y
-# CONFIG_BSD_DISKLABEL is not set
-# CONFIG_MINIX_SUBPARTITION is not set
-# CONFIG_SOLARIS_X86_PARTITION is not set
-# CONFIG_UNIXWARE_DISKLABEL is not set
-# CONFIG_LDM_PARTITION is not set
-# CONFIG_NEC98_PARTITION is not set
-# CONFIG_SGI_PARTITION is not set
-# CONFIG_ULTRIX_PARTITION is not set
-# CONFIG_SUN_PARTITION is not set
-# CONFIG_EFI_PARTITION is not set
-
-#
-# Graphics support
-#
-# CONFIG_FB is not set
-
-#
-# Sound
-#
-# CONFIG_SOUND is not set
-
-#
-# Misc devices
-#
-
-#
-# Multimedia Capabilities Port drivers
-#
-# CONFIG_MCP is not set
-
-#
-# Console Switches
-#
-# CONFIG_SWITCHES is not set
-
-#
-# USB support
-#
-# CONFIG_USB is not set
-# CONFIG_USB_GADGET is not set
-
-#
-# Bluetooth support
-#
-# CONFIG_BT is not set
-
-#
-# Kernel hacking
-#
-CONFIG_FRAME_POINTER=y
-CONFIG_DEBUG_USER=y
-# CONFIG_DEBUG_INFO is not set
-CONFIG_DEBUG_KERNEL=y
-# CONFIG_DEBUG_SLAB is not set
-# CONFIG_MAGIC_SYSRQ is not set
-# CONFIG_DEBUG_SPINLOCK is not set
-# CONFIG_DEBUG_WAITQ is not set
-CONFIG_DEBUG_BUGVERBOSE=y
-CONFIG_DEBUG_ERRORS=y
-CONFIG_DEBUG_LL=y
-
-#
-# Security options
-#
-# CONFIG_SECURITY is not set
-
-#
-# Cryptographic options
-#
-# CONFIG_CRYPTO is not set
-
-#
-# Library routines
-#
-# CONFIG_CRC32 is not set
-CONFIG_ZLIB_INFLATE=y
-CONFIG_ZLIB_DEFLATE=y
diff -Nru a/arch/arm/configs/iq80321_defconfig b/arch/arm/configs/iq80321_defconfig
--- a/arch/arm/configs/iq80321_defconfig	2004-10-18 14:56:20 -07:00
+++ b/arch/arm/configs/iq80321_defconfig	2004-10-18 14:56:20 -07:00
@@ -10,27 +10,39 @@
 # 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_BSD_PROCESS_ACCT is not set
+# 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_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=y
 
 #
 # Loadable module support
 #
 CONFIG_MODULES=y
-# CONFIG_MODULE_UNLOAD is not set
+CONFIG_MODULE_UNLOAD=y
+# CONFIG_MODULE_FORCE_UNLOAD is not set
 CONFIG_OBSOLETE_MODPARM=y
 # CONFIG_MODVERSIONS is not set
 CONFIG_KMOD=y
@@ -38,64 +50,42 @@
 #
 # System Type
 #
-# CONFIG_ARCH_ADIFCC is not set
 # CONFIG_ARCH_CLPS7500 is not set
 # CONFIG_ARCH_CLPS711X is not set
 # CONFIG_ARCH_CO285 is not set
-# CONFIG_ARCH_PXA is not set
 # CONFIG_ARCH_EBSA110 is not set
 # CONFIG_ARCH_CAMELOT is not set
 # CONFIG_ARCH_FOOTBRIDGE is not set
 # CONFIG_ARCH_INTEGRATOR is not set
 CONFIG_ARCH_IOP3XX=y
+# CONFIG_ARCH_IXP4XX is not set
 # CONFIG_ARCH_L7200 is not set
+# CONFIG_ARCH_PXA is not set
 # CONFIG_ARCH_RPC is not set
 # CONFIG_ARCH_SA1100 is not set
+# CONFIG_ARCH_S3C2410 is not set
 # CONFIG_ARCH_SHARK is not set
+# CONFIG_ARCH_LH7A40X is not set
+# CONFIG_ARCH_OMAP is not set
+# CONFIG_ARCH_VERSATILE_PB is not set
 
 #
-# CLPS711X/EP721X Implementations
-#
-
-#
-# Epxa10db
-#
-
-#
-# Footbridge Implementations
+# IOP3xx Implementation Options
 #
 
 #
-# IOP3xx Implementation Options
+# IOP3xx Platform Types
 #
-# CONFIG_ARCH_IQ80310 is not set
 CONFIG_ARCH_IQ80321=y
-# CONFIG_ARCH_IOP310 is not set
+# CONFIG_ARCH_IQ31244 is not set
+# CONFIG_ARCH_IQ80331 is not set
+# CONFIG_ARCH_EP80219 is not set
 CONFIG_ARCH_IOP321=y
+# CONFIG_ARCH_IOP331 is not set
 
 #
 # IOP3xx Chipset Features
 #
-# CONFIG_IOP3XX_AAU is not set
-# CONFIG_IOP3XX_DMA is not set
-# CONFIG_IOP3XX_MU is not set
-# CONFIG_IOP3XX_PMON is not set
-
-#
-# ADIFCC Implementation Options
-#
-
-#
-# ADI Board Types
-#
-
-#
-# Intel PXA250/210 Implementations
-#
-
-#
-# SA11x0 Implementations
-#
 
 #
 # Processor Type
@@ -103,6 +93,9 @@
 CONFIG_CPU_32=y
 CONFIG_CPU_XSCALE=y
 CONFIG_CPU_32v5=y
+CONFIG_CPU_ABRT_EV5T=y
+CONFIG_CPU_TLB_V4WBI=y
+CONFIG_CPU_MINICACHE=y
 
 #
 # Processor Features
@@ -119,12 +112,6 @@
 CONFIG_ZBOOT_ROM_BSS=0x0
 # CONFIG_PCI_LEGACY_PROC is not set
 CONFIG_PCI_NAMES=y
-# CONFIG_HOTPLUG is not set
-
-#
-# MMC/SD Card support
-#
-# CONFIG_MMC is not set
 
 #
 # At least one math emulation must be selected
@@ -132,11 +119,16 @@
 CONFIG_FPE_NWFPE=y
 # CONFIG_FPE_NWFPE_XP is not set
 # CONFIG_FPE_FASTFPE is not set
-CONFIG_KCORE_ELF=y
-# CONFIG_KCORE_AOUT is not set
-CONFIG_BINFMT_AOUT=y
+# CONFIG_VFP is not set
 CONFIG_BINFMT_ELF=y
+CONFIG_BINFMT_AOUT=y
 # CONFIG_BINFMT_MISC is not set
+
+#
+# Generic Driver Options
+#
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
 # CONFIG_PM is not set
 # CONFIG_PREEMPT is not set
 # CONFIG_ARTHUR is not set
@@ -156,6 +148,8 @@
 CONFIG_MTD_PARTITIONS=y
 # CONFIG_MTD_CONCAT is not set
 CONFIG_MTD_REDBOOT_PARTS=y
+# CONFIG_MTD_REDBOOT_PARTS_UNALLOCATED is not set
+# CONFIG_MTD_REDBOOT_PARTS_READONLY is not set
 # CONFIG_MTD_CMDLINE_PARTS is not set
 # CONFIG_MTD_AFS_PARTS is not set
 
@@ -175,13 +169,23 @@
 # CONFIG_MTD_JEDECPROBE is not set
 CONFIG_MTD_GEN_PROBE=y
 # CONFIG_MTD_CFI_ADV_OPTIONS 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_CFI_INTELEXT=y
 # CONFIG_MTD_CFI_AMDSTD is not set
 # CONFIG_MTD_CFI_STAA is not set
+CONFIG_MTD_CFI_UTIL=y
 # 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
@@ -196,6 +200,7 @@
 #
 # CONFIG_MTD_PMC551 is not set
 # CONFIG_MTD_SLRAM is not set
+# CONFIG_MTD_PHRAM is not set
 # CONFIG_MTD_MTDRAM is not set
 # CONFIG_MTD_BLKMTD is not set
 
@@ -214,7 +219,6 @@
 #
 # Plug and Play support
 #
-# CONFIG_PNP is not set
 
 #
 # Block devices
@@ -226,6 +230,7 @@
 # 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=8192
 # CONFIG_BLK_DEV_INITRD is not set
@@ -243,14 +248,13 @@
 #
 # Networking options
 #
-# CONFIG_PACKET is not set
+CONFIG_PACKET=y
+CONFIG_PACKET_MMAP=y
 # 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 is not set
+CONFIG_IP_MULTICAST=y
 # CONFIG_IP_ADVANCED_ROUTER is not set
 CONFIG_IP_PNP=y
 # CONFIG_IP_PNP_DHCP is not set
@@ -258,40 +262,26 @@
 # 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: Netfilter Configuration
-#
-# CONFIG_IP_NF_CONNTRACK is not set
-# CONFIG_IP_NF_QUEUE is not set
-# CONFIG_IP_NF_IPTABLES is not set
-# CONFIG_IP_NF_ARPTABLES is not set
-# CONFIG_IP_NF_COMPAT_IPCHAINS is not set
-# CONFIG_IP_NF_COMPAT_IPFWADM is not set
-
-#
-# IP: Virtual Server Configuration
-#
-# CONFIG_IP_VS is not set
 # CONFIG_IPV6 is not set
-# CONFIG_XFRM_USER 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
@@ -303,57 +293,32 @@
 # 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 is not set
-# CONFIG_SMC91X is not set
-# CONFIG_HAPPYMEAL is not set
-# CONFIG_SUNGEM is not set
-# CONFIG_NET_VENDOR_3COM is not set
-
-#
-# Tulip family network device support
-#
-# CONFIG_NET_TULIP is not set
-# CONFIG_HP100 is not set
-CONFIG_NET_PCI=y
-# CONFIG_PCNET32 is not set
-# CONFIG_AMD8111_ETH is not set
-# CONFIG_ADAPTEC_STARFIRE is not set
-# CONFIG_B44 is not set
-# CONFIG_DGRS is not set
-CONFIG_EEPRO100=y
-# CONFIG_EEPRO100_PIO is not set
-# CONFIG_E100 is not set
-# CONFIG_FEALNX is not set
-# CONFIG_NATSEMI is not set
-# CONFIG_NE2K_PCI 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_TLAN is not set
-# CONFIG_VIA_RHINE is not set
+# CONFIG_NET_ETHERNET is not set
 
 #
 # Ethernet (1000 Mbit)
@@ -373,104 +338,45 @@
 # 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_RCPCI is not set
-# CONFIG_SHAPER is not set
+# CONFIG_NET_RADIO is not set
 
 #
 # Wan interfaces
 #
 # CONFIG_WAN is not set
-
-#
-# IrDA (infrared) support
-#
-# CONFIG_IRDA is not set
-
-#
-# Amateur Radio support
-#
-# CONFIG_HAMRADIO is not set
+# CONFIG_FDDI is not set
+# CONFIG_HIPPI is not set
+# CONFIG_PPP is not set
+# CONFIG_SLIP is not set
+# CONFIG_SHAPER is not set
+# CONFIG_NETCONSOLE is not set
 
 #
 # ATA/ATAPI/MFM/RLL support
 #
-CONFIG_IDE=y
+# CONFIG_IDE is not set
 
 #
-# IDE, ATA and ATAPI Block devices
+# SCSI device support
 #
-CONFIG_BLK_DEV_IDE=y
+# CONFIG_SCSI is not set
 
 #
-# Please see Documentation/ide.txt for help/info on IDE drives
-#
-# CONFIG_BLK_DEV_HD 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=y
-# CONFIG_BLK_DEV_IDEFLOPPY is not set
-# CONFIG_IDE_TASK_IOCTL is not set
-# CONFIG_IDE_TASKFILE_IO is not set
-
-#
-# IDE chipset support/bugfixes
-#
-CONFIG_BLK_DEV_IDEPCI=y
-# CONFIG_BLK_DEV_GENERIC is not set
-# CONFIG_IDEPCI_SHARE_IRQ is not set
-CONFIG_BLK_DEV_IDEDMA_PCI=y
-# CONFIG_BLK_DEV_IDE_TCQ is not set
-# CONFIG_BLK_DEV_OFFBOARD is not set
-# CONFIG_BLK_DEV_IDEDMA_FORCED is not set
-CONFIG_IDEDMA_PCI_AUTO=y
-# CONFIG_IDEDMA_ONLYDISK is not set
-CONFIG_BLK_DEV_IDEDMA=y
-CONFIG_BLK_DEV_ADMA=y
-# CONFIG_BLK_DEV_AEC62XX is not set
-# CONFIG_BLK_DEV_ALI15X3 is not set
-# CONFIG_BLK_DEV_AMD74XX is not set
-CONFIG_BLK_DEV_CMD64X=y
-# CONFIG_BLK_DEV_TRIFLEX is not set
-# CONFIG_BLK_DEV_CY82C693 is not set
-# CONFIG_BLK_DEV_CS5520 is not set
-# CONFIG_BLK_DEV_HPT34X is not set
-# CONFIG_BLK_DEV_HPT366 is not set
-# CONFIG_BLK_DEV_SC1200 is not set
-# CONFIG_BLK_DEV_PIIX is not set
-# CONFIG_BLK_DEV_NS87415 is not set
-# CONFIG_BLK_DEV_OPTI621 is not set
-# CONFIG_BLK_DEV_PDC202XX_OLD is not set
-# CONFIG_BLK_DEV_PDC202XX_NEW is not set
-# CONFIG_BLK_DEV_SVWKS is not set
-# CONFIG_BLK_DEV_SIIMAGE 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_SL82C105 is not set
-CONFIG_IDEDMA_AUTO=y
-# CONFIG_IDEDMA_IVB is not set
-
+# Fusion MPT device support
 #
-# SCSI device support
-#
-# CONFIG_SCSI is not set
 
 #
-# IEEE 1394 (FireWire) support (EXPERIMENTAL)
+# IEEE 1394 (FireWire) support
 #
 # CONFIG_IEEE1394 is not set
 
@@ -482,16 +388,24 @@
 #
 # ISDN subsystem
 #
-# CONFIG_ISDN_BOOL is not set
+# CONFIG_ISDN 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
@@ -499,14 +413,23 @@
 # CONFIG_GAMEPORT is not set
 CONFIG_SOUND_GAMEPORT=y
 # CONFIG_SERIO is not set
+# CONFIG_SERIO_I8042 is not set
 
 #
 # Input Device Drivers
 #
+# CONFIG_INPUT_KEYBOARD is not set
+# CONFIG_INPUT_MOUSE 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
 
 #
@@ -514,40 +437,17 @@
 #
 CONFIG_SERIAL_8250=y
 CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_NR_UARTS=4
 # CONFIG_SERIAL_8250_EXTENDED is not set
 
 #
 # Non-8250 serial port support
 #
-# CONFIG_SERIAL_DZ is not set
 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
-
-#
-# L3 serial bus support
-#
-# CONFIG_L3 is not set
-
-#
-# Mice
-#
-# CONFIG_BUSMOUSE is not set
+CONFIG_LEGACY_PTYS=y
+CONFIG_LEGACY_PTY_COUNT=256
 # CONFIG_QIC02_TAPE is not set
 
 #
@@ -569,54 +469,44 @@
 #
 # 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
-
-#
-# Multimedia devices
-#
-CONFIG_VIDEO_DEV=y
 
 #
-# Video For Linux
-#
-# CONFIG_VIDEO_PROC_FS is not set
-
-#
-# Video Adapters
+# I2C support
 #
-# CONFIG_VIDEO_PMS is not set
-# CONFIG_VIDEO_CPIA is not set
-# CONFIG_VIDEO_STRADIS is not set
-# CONFIG_VIDEO_HEXIUM_ORION is not set
-# CONFIG_VIDEO_HEXIUM_GEMINI is not set
+# CONFIG_I2C is not set
 
 #
-# Radio Adapters
+# Multimedia devices
 #
-# CONFIG_RADIO_GEMTEK_PCI is not set
-# CONFIG_RADIO_MAXIRADIO is not set
-# CONFIG_RADIO_MAESTRO is not set
+# CONFIG_VIDEO_DEV is not set
 
 #
 # Digital Video Broadcasting Devices
 #
 # CONFIG_DVB is not set
-# CONFIG_VIDEO_BTCX 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_EXT3_FS=y
+CONFIG_EXT3_FS_XATTR=y
+# CONFIG_EXT3_FS_POSIX_ACL is not set
+# CONFIG_EXT3_FS_SECURITY is not set
+CONFIG_JBD=y
+# CONFIG_JBD_DEBUG is not set
+CONFIG_FS_MBCACHE=y
 # CONFIG_REISERFS_FS is not set
 # CONFIG_JFS_FS is not set
-# CONFIG_XFS_FS is not set
+CONFIG_XFS_FS=y
+# CONFIG_XFS_RT is not set
+# CONFIG_XFS_QUOTA is not set
+CONFIG_XFS_SECURITY=y
+CONFIG_XFS_POSIX_ACL=y
 # CONFIG_MINIX_FS is not set
 # CONFIG_ROMFS_FS is not set
 # CONFIG_QUOTA is not set
@@ -632,17 +522,19 @@
 #
 # 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_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
 
 #
@@ -651,6 +543,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
@@ -658,6 +551,10 @@
 CONFIG_JFFS2_FS=y
 CONFIG_JFFS2_FS_DEBUG=0
 # CONFIG_JFFS2_FS_NAND is not set
+# CONFIG_JFFS2_COMPRESSION_OPTIONS is not set
+CONFIG_JFFS2_ZLIB=y
+CONFIG_JFFS2_RTIME=y
+# CONFIG_JFFS2_RUBIN is not set
 # CONFIG_CRAMFS is not set
 # CONFIG_VXFS_FS is not set
 # CONFIG_HPFS_FS is not set
@@ -669,19 +566,23 @@
 # Network File Systems
 #
 CONFIG_NFS_FS=y
-# CONFIG_NFS_V3 is not set
+CONFIG_NFS_V3=y
 # CONFIG_NFS_V4 is not set
-# CONFIG_NFSD is not set
+# CONFIG_NFS_DIRECTIO is not set
+CONFIG_NFSD=y
+CONFIG_NFSD_V3=y
+# CONFIG_NFSD_V4 is not set
+# CONFIG_NFSD_TCP is not set
 CONFIG_ROOT_NFS=y
 CONFIG_LOCKD=y
-# CONFIG_EXPORTFS is not set
+CONFIG_LOCKD_V4=y
+CONFIG_EXPORTFS=y
 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
 
 #
@@ -699,46 +600,51 @@
 # CONFIG_SOLARIS_X86_PARTITION is not set
 # CONFIG_UNIXWARE_DISKLABEL is not set
 # CONFIG_LDM_PARTITION is not set
-# CONFIG_NEC98_PARTITION is not set
 # CONFIG_SGI_PARTITION is not set
 # CONFIG_ULTRIX_PARTITION is not set
 # CONFIG_SUN_PARTITION is not set
 # CONFIG_EFI_PARTITION is not set
 
 #
-# Graphics support
+# Native Language Support
 #
-# CONFIG_FB is not set
+# CONFIG_NLS is not set
 
 #
-# Sound
+# Profiling support
 #
-# CONFIG_SOUND is not set
+# CONFIG_PROFILING is not set
 
 #
-# Misc devices
+# Graphics support
 #
+# CONFIG_FB is not set
 
 #
-# Multimedia Capabilities Port drivers
+# Console display driver support
 #
-# CONFIG_MCP is not set
+# CONFIG_VGA_CONSOLE is not set
+# CONFIG_MDA_CONSOLE is not set
+CONFIG_DUMMY_CONSOLE=y
 
 #
-# Console Switches
+# Sound
+#
+# CONFIG_SOUND is not set
+
+#
+# Misc devices
 #
-# CONFIG_SWITCHES is not set
 
 #
 # USB support
 #
 # CONFIG_USB is not set
-# CONFIG_USB_GADGET is not set
 
 #
-# Bluetooth support
+# USB Gadget Support
 #
-# CONFIG_BT is not set
+# CONFIG_USB_GADGET is not set
 
 #
 # Kernel hacking
@@ -746,14 +652,7 @@
 CONFIG_FRAME_POINTER=y
 # CONFIG_DEBUG_USER is not set
 # CONFIG_DEBUG_INFO is not set
-CONFIG_DEBUG_KERNEL=y
-# CONFIG_DEBUG_SLAB is not set
-# CONFIG_MAGIC_SYSRQ is not set
-# CONFIG_DEBUG_SPINLOCK is not set
-# CONFIG_DEBUG_WAITQ is not set
-CONFIG_DEBUG_BUGVERBOSE=y
-CONFIG_DEBUG_ERRORS=y
-CONFIG_DEBUG_LL=y
+# CONFIG_DEBUG_KERNEL is not set
 
 #
 # Security options
@@ -768,6 +667,8 @@
 #
 # Library routines
 #
-# CONFIG_CRC32 is not set
+# CONFIG_CRC_CCITT is not set
+CONFIG_CRC32=y
+# CONFIG_LIBCRC32C is not set
 CONFIG_ZLIB_INFLATE=y
 CONFIG_ZLIB_DEFLATE=y
diff -Nru a/arch/arm/configs/iq80331_defconfig b/arch/arm/configs/iq80331_defconfig
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/arch/arm/configs/iq80331_defconfig	2004-10-18 14:57:21 -07:00
@@ -0,0 +1,753 @@
+#
+# Automatically generated make config: don't edit
+#
+CONFIG_ARM=y
+CONFIG_MMU=y
+CONFIG_UID16=y
+CONFIG_RWSEM_GENERIC_SPINLOCK=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_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
+
+#
+# Loadable module support
+#
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+# CONFIG_MODULE_FORCE_UNLOAD is not set
+CONFIG_OBSOLETE_MODPARM=y
+# CONFIG_MODVERSIONS is not set
+CONFIG_KMOD=y
+
+#
+# System Type
+#
+# CONFIG_ARCH_CLPS7500 is not set
+# CONFIG_ARCH_CLPS711X is not set
+# CONFIG_ARCH_CO285 is not set
+# CONFIG_ARCH_EBSA110 is not set
+# CONFIG_ARCH_CAMELOT is not set
+# CONFIG_ARCH_FOOTBRIDGE is not set
+# CONFIG_ARCH_INTEGRATOR is not set
+CONFIG_ARCH_IOP3XX=y
+# CONFIG_ARCH_IXP4XX is not set
+# CONFIG_ARCH_L7200 is not set
+# CONFIG_ARCH_PXA is not set
+# CONFIG_ARCH_RPC is not set
+# CONFIG_ARCH_SA1100 is not set
+# CONFIG_ARCH_S3C2410 is not set
+# CONFIG_ARCH_SHARK is not set
+# CONFIG_ARCH_LH7A40X is not set
+# CONFIG_ARCH_OMAP is not set
+# CONFIG_ARCH_VERSATILE_PB is not set
+
+#
+# IOP3xx Implementation Options
+#
+
+#
+# IOP3xx Platform Types
+#
+# CONFIG_ARCH_IQ80321 is not set
+# CONFIG_ARCH_IQ31244 is not set
+CONFIG_ARCH_IQ80331=y
+# CONFIG_ARCH_EP80219 is not set
+CONFIG_ARCH_IOP331=y
+
+#
+# IOP3xx Chipset Features
+#
+
+#
+# Processor Type
+#
+CONFIG_CPU_32=y
+CONFIG_CPU_XSCALE=y
+CONFIG_CPU_32v5=y
+CONFIG_CPU_ABRT_EV5T=y
+CONFIG_CPU_TLB_V4WBI=y
+CONFIG_CPU_MINICACHE=y
+
+#
+# Processor Features
+#
+# CONFIG_ARM_THUMB is not set
+CONFIG_XSCALE_PMU=y
+
+#
+# General setup
+#
+CONFIG_PCI=y
+# CONFIG_ZBOOT_ROM is not set
+CONFIG_ZBOOT_ROM_TEXT=0x0
+CONFIG_ZBOOT_ROM_BSS=0x0
+# CONFIG_PCI_LEGACY_PROC is not set
+CONFIG_PCI_NAMES=y
+
+#
+# At least one math emulation must be selected
+#
+CONFIG_FPE_NWFPE=y
+# CONFIG_FPE_NWFPE_XP is not set
+# CONFIG_FPE_FASTFPE is not set
+# CONFIG_VFP is not set
+CONFIG_BINFMT_ELF=y
+CONFIG_BINFMT_AOUT=y
+# CONFIG_BINFMT_MISC is not set
+
+#
+# Generic Driver Options
+#
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+# CONFIG_DEBUG_DRIVER is not set
+# CONFIG_PM is not set
+# CONFIG_PREEMPT is not set
+# CONFIG_ARTHUR is not set
+CONFIG_CMDLINE="ip=boot root=nfs console=ttyS0,115200 mem=128M@0x00000000"
+CONFIG_ALIGNMENT_TRAP=y
+
+#
+# Parallel port support
+#
+# CONFIG_PARPORT is not set
+
+#
+# Memory Technology Devices (MTD)
+#
+CONFIG_MTD=y
+# CONFIG_MTD_DEBUG is not set
+CONFIG_MTD_PARTITIONS=y
+# CONFIG_MTD_CONCAT is not set
+CONFIG_MTD_REDBOOT_PARTS=y
+# CONFIG_MTD_REDBOOT_PARTS_UNALLOCATED is not set
+# CONFIG_MTD_REDBOOT_PARTS_READONLY is not set
+# CONFIG_MTD_CMDLINE_PARTS is not set
+# CONFIG_MTD_AFS_PARTS is not set
+
+#
+# User Modules And Translation Layers
+#
+CONFIG_MTD_CHAR=y
+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=y
+# CONFIG_MTD_JEDECPROBE is not set
+CONFIG_MTD_GEN_PROBE=y
+CONFIG_MTD_CFI_ADV_OPTIONS=y
+CONFIG_MTD_CFI_NOSWAP=y
+# CONFIG_MTD_CFI_BE_BYTE_SWAP is not set
+# CONFIG_MTD_CFI_LE_BYTE_SWAP is not set
+# CONFIG_MTD_CFI_GEOMETRY 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_CFI_INTELEXT=y
+# CONFIG_MTD_CFI_AMDSTD is not set
+# CONFIG_MTD_CFI_STAA is not set
+CONFIG_MTD_CFI_UTIL=y
+# CONFIG_MTD_RAM is not set
+# CONFIG_MTD_ROM is not set
+# CONFIG_MTD_ABSENT is not set
+
+#
+# Mapping drivers for chip access
+#
+# CONFIG_MTD_COMPLEX_MAPPINGS is not set
+# CONFIG_MTD_PHYSMAP is not set
+# CONFIG_MTD_ARM_INTEGRATOR is not set
+# CONFIG_MTD_EDB7312 is not set
+
+#
+# Self-contained MTD device drivers
+#
+# CONFIG_MTD_PMC551 is not set
+# CONFIG_MTD_SLRAM is not set
+# CONFIG_MTD_PHRAM is not set
+# CONFIG_MTD_MTDRAM is not set
+# CONFIG_MTD_BLKMTD is not set
+
+#
+# Disk-On-Chip Device Drivers
+#
+# CONFIG_MTD_DOC2000 is not set
+# CONFIG_MTD_DOC2001 is not set
+# CONFIG_MTD_DOC2001PLUS is not set
+
+#
+# NAND Flash Device Drivers
+#
+# CONFIG_MTD_NAND is not set
+
+#
+# Plug and Play support
+#
+
+#
+# Block devices
+#
+# CONFIG_BLK_DEV_FD is not set
+# CONFIG_BLK_CPQ_DA is not set
+# CONFIG_BLK_CPQ_CISS_DA is not set
+# CONFIG_BLK_DEV_DAC960 is not set
+# 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=8192
+# CONFIG_BLK_DEV_INITRD is not set
+
+#
+# Multi-device support (RAID and LVM)
+#
+CONFIG_MD=y
+CONFIG_BLK_DEV_MD=y
+CONFIG_MD_LINEAR=y
+CONFIG_MD_RAID0=y
+CONFIG_MD_RAID1=y
+CONFIG_MD_RAID5=y
+# CONFIG_MD_RAID6 is not set
+# CONFIG_MD_MULTIPATH is not set
+CONFIG_BLK_DEV_DM=y
+# CONFIG_DM_CRYPT is not set
+# CONFIG_DM_SNAPSHOT is not set
+# CONFIG_DM_MIRROR is not set
+# CONFIG_DM_ZERO is not set
+
+#
+# Networking support
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+CONFIG_PACKET=y
+CONFIG_PACKET_MMAP=y
+# CONFIG_NETLINK_DEV 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 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_SYN_COOKIES is not set
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+# CONFIG_IPV6 is not set
+# CONFIG_NETFILTER is not set
+
+#
+# SCTP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_SCTP is not set
+# CONFIG_ATM is not set
+# CONFIG_BRIDGE is not set
+# CONFIG_VLAN_8021Q is not set
+# CONFIG_DECNET 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
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+# CONFIG_NET_HW_FLOWCONTROL is not set
+
+#
+# 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
+
+#
+# Ethernet (10 or 100Mbit)
+#
+# CONFIG_NET_ETHERNET is not set
+
+#
+# Ethernet (1000 Mbit)
+#
+# CONFIG_ACENIC is not set
+# CONFIG_DL2K is not set
+CONFIG_E1000=y
+CONFIG_E1000_NAPI=y
+# CONFIG_NS83820 is not set
+# CONFIG_HAMACHI is not set
+# CONFIG_YELLOWFIN is not set
+# CONFIG_R8169 is not set
+# CONFIG_SK98LIN is not set
+# CONFIG_TIGON3 is not set
+
+#
+# Ethernet (10000 Mbit)
+#
+# CONFIG_IXGB is not set
+# CONFIG_S2IO is not set
+
+#
+# Token Ring devices
+#
+# CONFIG_TR is not set
+
+#
+# Wireless LAN (non-hamradio)
+#
+# CONFIG_NET_RADIO is not set
+
+#
+# Wan interfaces
+#
+# CONFIG_WAN 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
+
+#
+# ATA/ATAPI/MFM/RLL support
+#
+# CONFIG_IDE is not set
+
+#
+# SCSI device support
+#
+CONFIG_SCSI=y
+CONFIG_SCSI_PROC_FS=y
+
+#
+# SCSI support type (disk, tape, CD-ROM)
+#
+CONFIG_BLK_DEV_SD=y
+# CONFIG_CHR_DEV_ST is not set
+# CONFIG_CHR_DEV_OSST is not set
+# CONFIG_BLK_DEV_SR is not set
+CONFIG_CHR_DEV_SG=y
+
+#
+# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
+#
+# CONFIG_SCSI_MULTI_LUN is not set
+# CONFIG_SCSI_CONSTANTS is not set
+# CONFIG_SCSI_LOGGING is not set
+
+#
+# SCSI Transport Attributes
+#
+# CONFIG_SCSI_SPI_ATTRS is not set
+# 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_MEGARAID is not set
+# CONFIG_SCSI_SATA is not set
+# CONFIG_SCSI_BUSLOGIC 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_IPS is not set
+# CONFIG_SCSI_INIA100 is not set
+# CONFIG_SCSI_SYM53C8XX_2 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_NSP32 is not set
+# CONFIG_SCSI_DEBUG is not set
+
+#
+# Fusion MPT device support
+#
+# CONFIG_FUSION is not set
+
+#
+# IEEE 1394 (FireWire) support
+#
+# CONFIG_IEEE1394 is not set
+
+#
+# I2O device support
+#
+# CONFIG_I2O is not set
+
+#
+# ISDN subsystem
+#
+# CONFIG_ISDN is not set
+
+#
+# Input device support
+#
+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_I8042 is not set
+
+#
+# Input Device Drivers
+#
+# CONFIG_INPUT_KEYBOARD is not set
+# CONFIG_INPUT_MOUSE 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
+
+#
+# Serial drivers
+#
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_NR_UARTS=4
+# CONFIG_SERIAL_8250_EXTENDED is not set
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+CONFIG_UNIX98_PTYS=y
+CONFIG_LEGACY_PTYS=y
+CONFIG_LEGACY_PTY_COUNT=256
+# CONFIG_QIC02_TAPE is not set
+
+#
+# IPMI
+#
+# CONFIG_IPMI_HANDLER is not set
+
+#
+# Watchdog Cards
+#
+# CONFIG_WATCHDOG is not set
+# CONFIG_NVRAM is not set
+# CONFIG_RTC is not set
+# CONFIG_GEN_RTC is not set
+# CONFIG_DTLK is not set
+# CONFIG_R3964 is not set
+# CONFIG_APPLICOM is not set
+
+#
+# Ftape, the floppy tape device driver
+#
+# CONFIG_AGP is not set
+# CONFIG_DRM is not set
+# CONFIG_RAW_DRIVER is not set
+
+#
+# I2C support
+#
+# CONFIG_I2C is not set
+
+#
+# Multimedia devices
+#
+# CONFIG_VIDEO_DEV is not set
+
+#
+# Digital Video Broadcasting Devices
+#
+# CONFIG_DVB is not set
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+# CONFIG_EXT2_FS_XATTR is not set
+CONFIG_EXT3_FS=y
+CONFIG_EXT3_FS_XATTR=y
+# CONFIG_EXT3_FS_POSIX_ACL is not set
+# CONFIG_EXT3_FS_SECURITY is not set
+CONFIG_JBD=y
+# CONFIG_JBD_DEBUG is not set
+CONFIG_FS_MBCACHE=y
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+CONFIG_XFS_FS=y
+# CONFIG_XFS_RT is not set
+# CONFIG_XFS_QUOTA is not set
+CONFIG_XFS_SECURITY=y
+CONFIG_XFS_POSIX_ACL=y
+# CONFIG_MINIX_FS is not set
+# CONFIG_ROMFS_FS is not set
+# CONFIG_QUOTA is not set
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_AUTOFS4_FS is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+# CONFIG_ISO9660_FS is not set
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+# 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_SYSFS=y
+# CONFIG_DEVFS_FS 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_EFS_FS is not set
+# CONFIG_JFFS_FS is not set
+# CONFIG_JFFS2_FS is not set
+# CONFIG_CRAMFS is not set
+# CONFIG_VXFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+
+#
+# Network File Systems
+#
+CONFIG_NFS_FS=y
+CONFIG_NFS_V3=y
+# CONFIG_NFS_V4 is not set
+# CONFIG_NFS_DIRECTIO is not set
+CONFIG_NFSD=y
+CONFIG_NFSD_V3=y
+# CONFIG_NFSD_V4 is not set
+# CONFIG_NFSD_TCP is not set
+CONFIG_ROOT_NFS=y
+CONFIG_LOCKD=y
+CONFIG_LOCKD_V4=y
+CONFIG_EXPORTFS=y
+CONFIG_SUNRPC=y
+# 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_AFS_FS is not set
+
+#
+# Partition Types
+#
+CONFIG_PARTITION_ADVANCED=y
+# CONFIG_ACORN_PARTITION is not set
+# CONFIG_OSF_PARTITION is not set
+# CONFIG_AMIGA_PARTITION is not set
+# CONFIG_ATARI_PARTITION is not set
+# CONFIG_MAC_PARTITION is not set
+CONFIG_MSDOS_PARTITION=y
+# CONFIG_BSD_DISKLABEL is not set
+# CONFIG_MINIX_SUBPARTITION is not set
+# CONFIG_SOLARIS_X86_PARTITION is not set
+# CONFIG_UNIXWARE_DISKLABEL is not set
+# CONFIG_LDM_PARTITION is not set
+# CONFIG_SGI_PARTITION is not set
+# CONFIG_ULTRIX_PARTITION is not set
+# CONFIG_SUN_PARTITION is not set
+# CONFIG_EFI_PARTITION is not set
+
+#
+# Native Language Support
+#
+# CONFIG_NLS is not set
+
+#
+# Profiling support
+#
+# CONFIG_PROFILING is not set
+
+#
+# Graphics support
+#
+# CONFIG_FB is not set
+
+#
+# Console display driver support
+#
+# CONFIG_VGA_CONSOLE is not set
+# CONFIG_MDA_CONSOLE is not set
+CONFIG_DUMMY_CONSOLE=y
+
+#
+# Sound
+#
+# CONFIG_SOUND is not set
+
+#
+# Misc devices
+#
+
+#
+# USB support
+#
+# CONFIG_USB is not set
+
+#
+# USB Gadget Support
+#
+# CONFIG_USB_GADGET is not set
+
+#
+# Kernel hacking
+#
+CONFIG_FRAME_POINTER=y
+CONFIG_DEBUG_USER=y
+# CONFIG_DEBUG_INFO is not set
+CONFIG_DEBUG_KERNEL=y
+# CONFIG_DEBUG_SLAB is not set
+# CONFIG_MAGIC_SYSRQ is not set
+# CONFIG_DEBUG_SPINLOCK is not set
+# CONFIG_DEBUG_WAITQ is not set
+CONFIG_DEBUG_BUGVERBOSE=y
+CONFIG_DEBUG_ERRORS=y
+# CONFIG_DEBUG_LL is not set
+
+#
+# Security options
+#
+# CONFIG_SECURITY is not set
+
+#
+# Cryptographic options
+#
+# CONFIG_CRYPTO is not set
+
+#
+# Library routines
+#
+# CONFIG_CRC_CCITT is not set
+CONFIG_CRC32=y
+# CONFIG_LIBCRC32C is not set
diff -Nru a/arch/arm/configs/ixdp2400_defconfig b/arch/arm/configs/ixdp2400_defconfig
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/arch/arm/configs/ixdp2400_defconfig	2004-10-18 14:57:23 -07:00
@@ -0,0 +1,796 @@
+#
+# Automatically generated make config: don't edit
+#
+CONFIG_ARM=y
+CONFIG_MMU=y
+CONFIG_UID16=y
+CONFIG_RWSEM_GENERIC_SPINLOCK=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=y
+CONFIG_KALLSYMS=y
+# CONFIG_KALLSYMS_ALL is not set
+# 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=y
+
+#
+# Loadable module support
+#
+# CONFIG_MODULES is not set
+
+#
+# System Type
+#
+# CONFIG_ARCH_CLPS7500 is not set
+# CONFIG_ARCH_CLPS711X is not set
+# CONFIG_ARCH_CO285 is not set
+# CONFIG_ARCH_EBSA110 is not set
+# CONFIG_ARCH_CAMELOT is not set
+# CONFIG_ARCH_FOOTBRIDGE is not set
+# CONFIG_ARCH_INTEGRATOR is not set
+# CONFIG_ARCH_IOP3XX is not set
+# CONFIG_ARCH_IXP4XX is not set
+CONFIG_ARCH_IXP2000=y
+# CONFIG_ARCH_L7200 is not set
+# CONFIG_ARCH_PXA is not set
+# CONFIG_ARCH_RPC is not set
+# CONFIG_ARCH_SA1100 is not set
+# CONFIG_ARCH_S3C2410 is not set
+# CONFIG_ARCH_SHARK is not set
+# CONFIG_ARCH_LH7A40X is not set
+# CONFIG_ARCH_OMAP is not set
+# CONFIG_ARCH_VERSATILE_PB is not set
+CONFIG_ARCH_SUPPORTS_BIG_ENDIAN=y
+
+#
+# Intel IXP2400/2800 Implementation Options
+#
+
+#
+# IXP2400/2800 Platforms
+#
+# CONFIG_ARCH_ENP2611 is not set
+CONFIG_ARCH_IXDP2400=y
+# CONFIG_ARCH_IXDP2800 is not set
+CONFIG_ARCH_IXDP2X00=y
+# CONFIG_ARCH_IXDP2401 is not set
+# CONFIG_ARCH_IXDP2801 is not set
+
+#
+# Processor Type
+#
+CONFIG_CPU_32=y
+CONFIG_CPU_XSCALE=y
+CONFIG_CPU_32v5=y
+CONFIG_CPU_ABRT_EV5T=y
+CONFIG_CPU_TLB_V4WBI=y
+CONFIG_CPU_MINICACHE=y
+
+#
+# Processor Features
+#
+# CONFIG_ARM_THUMB is not set
+CONFIG_CPU_BIG_ENDIAN=y
+CONFIG_XSCALE_PMU=y
+
+#
+# General setup
+#
+CONFIG_PCI=y
+# CONFIG_ZBOOT_ROM is not set
+CONFIG_ZBOOT_ROM_TEXT=0x0
+CONFIG_ZBOOT_ROM_BSS=0x0
+CONFIG_PCI_LEGACY_PROC=y
+CONFIG_PCI_NAMES=y
+
+#
+# At least one math emulation must be selected
+#
+CONFIG_FPE_NWFPE=y
+# CONFIG_FPE_NWFPE_XP is not set
+# CONFIG_FPE_FASTFPE is not set
+# CONFIG_VFP is not set
+CONFIG_BINFMT_ELF=y
+# CONFIG_BINFMT_AOUT is not set
+# CONFIG_BINFMT_MISC is not set
+
+#
+# Generic Driver Options
+#
+CONFIG_STANDALONE=y
+# CONFIG_PREVENT_FIRMWARE_BUILD is not set
+# CONFIG_DEBUG_DRIVER is not set
+# CONFIG_PM is not set
+# CONFIG_PREEMPT is not set
+# CONFIG_ARTHUR is not set
+CONFIG_CMDLINE="console=ttyS0,57600 root=/dev/nfs ip=bootp mem=64M@0x0 pci=firmware"
+CONFIG_ALIGNMENT_TRAP=y
+
+#
+# Parallel port support
+#
+# CONFIG_PARPORT is not set
+
+#
+# Memory Technology Devices (MTD)
+#
+CONFIG_MTD=y
+# CONFIG_MTD_DEBUG is not set
+CONFIG_MTD_PARTITIONS=y
+# CONFIG_MTD_CONCAT is not set
+CONFIG_MTD_REDBOOT_PARTS=y
+CONFIG_MTD_REDBOOT_PARTS_UNALLOCATED=y
+CONFIG_MTD_REDBOOT_PARTS_READONLY=y
+# CONFIG_MTD_CMDLINE_PARTS is not set
+# CONFIG_MTD_AFS_PARTS is not set
+
+#
+# User Modules And Translation Layers
+#
+CONFIG_MTD_CHAR=y
+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=y
+# CONFIG_MTD_JEDECPROBE is not set
+CONFIG_MTD_GEN_PROBE=y
+# CONFIG_MTD_CFI_ADV_OPTIONS 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_CFI_INTELEXT=y
+# CONFIG_MTD_CFI_AMDSTD is not set
+# CONFIG_MTD_CFI_STAA is not set
+CONFIG_MTD_CFI_UTIL=y
+# CONFIG_MTD_RAM is not set
+# CONFIG_MTD_ROM is not set
+# CONFIG_MTD_ABSENT is not set
+
+#
+# Mapping drivers for chip access
+#
+CONFIG_MTD_COMPLEX_MAPPINGS=y
+# CONFIG_MTD_PHYSMAP is not set
+# CONFIG_MTD_ARM_INTEGRATOR is not set
+CONFIG_MTD_IXP2000=y
+# CONFIG_MTD_EDB7312 is not set
+# CONFIG_MTD_PCI is not set
+
+#
+# Self-contained MTD device drivers
+#
+# CONFIG_MTD_PMC551 is not set
+# CONFIG_MTD_SLRAM is not set
+# CONFIG_MTD_PHRAM is not set
+# CONFIG_MTD_MTDRAM is not set
+# CONFIG_MTD_BLKMTD is not set
+
+#
+# Disk-On-Chip Device Drivers
+#
+# CONFIG_MTD_DOC2000 is not set
+# CONFIG_MTD_DOC2001 is not set
+# CONFIG_MTD_DOC2001PLUS is not set
+
+#
+# NAND Flash Device Drivers
+#
+# CONFIG_MTD_NAND is not set
+
+#
+# Plug and Play support
+#
+
+#
+# Block devices
+#
+# CONFIG_BLK_DEV_FD is not set
+# CONFIG_BLK_CPQ_DA is not set
+# CONFIG_BLK_CPQ_CISS_DA is not set
+# CONFIG_BLK_DEV_DAC960 is not set
+# CONFIG_BLK_DEV_UMEM is not set
+CONFIG_BLK_DEV_LOOP=y
+# CONFIG_BLK_DEV_CRYPTOLOOP 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=8192
+CONFIG_BLK_DEV_INITRD=y
+
+#
+# Multi-device support (RAID and LVM)
+#
+# CONFIG_MD is not set
+
+#
+# Networking support
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+CONFIG_PACKET=y
+CONFIG_PACKET_MMAP=y
+# CONFIG_NETLINK_DEV is not set
+CONFIG_UNIX=y
+# CONFIG_NET_KEY is not set
+CONFIG_INET=y
+# CONFIG_IP_MULTICAST is not set
+# CONFIG_IP_ADVANCED_ROUTER is not set
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_DHCP=y
+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_ARPD is not set
+CONFIG_SYN_COOKIES=y
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+# CONFIG_IPV6 is not set
+# CONFIG_NETFILTER is not set
+
+#
+# SCTP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_SCTP is not set
+# CONFIG_ATM is not set
+# CONFIG_BRIDGE is not set
+# CONFIG_VLAN_8021Q is not set
+# CONFIG_DECNET 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
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+# CONFIG_NET_FASTROUTE is not set
+# CONFIG_NET_HW_FLOWCONTROL is not set
+
+#
+# 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=y
+# CONFIG_BONDING is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
+
+#
+# ARCnet devices
+#
+# CONFIG_ARCNET is not set
+
+#
+# Ethernet (10 or 100Mbit)
+#
+CONFIG_NET_ETHERNET=y
+CONFIG_MII=y
+# CONFIG_HAPPYMEAL is not set
+# CONFIG_SUNGEM is not set
+# CONFIG_NET_VENDOR_3COM is not set
+# CONFIG_SMC91X is not set
+
+#
+# Tulip family network device support
+#
+# CONFIG_NET_TULIP is not set
+# CONFIG_HP100 is not set
+CONFIG_NET_PCI=y
+# CONFIG_PCNET32 is not set
+# 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_FEALNX is not set
+# CONFIG_NATSEMI is not set
+# CONFIG_NE2K_PCI 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_TLAN is not set
+# CONFIG_VIA_RHINE is not set
+# CONFIG_VIA_VELOCITY is not set
+
+#
+# Ethernet (1000 Mbit)
+#
+# CONFIG_ACENIC is not set
+# CONFIG_DL2K is not set
+# CONFIG_E1000 is not set
+# CONFIG_NS83820 is not set
+# CONFIG_HAMACHI is not set
+# CONFIG_YELLOWFIN is not set
+# CONFIG_R8169 is not set
+# CONFIG_SK98LIN is not set
+# CONFIG_TIGON3 is not set
+
+#
+# Ethernet (10000 Mbit)
+#
+# CONFIG_IXGB is not set
+# CONFIG_S2IO is not set
+
+#
+# Token Ring devices
+#
+# CONFIG_TR is not set
+
+#
+# Wireless LAN (non-hamradio)
+#
+# CONFIG_NET_RADIO is not set
+
+#
+# Wan interfaces
+#
+CONFIG_WAN=y
+# CONFIG_LANMEDIA is not set
+# CONFIG_SYNCLINK_SYNCPPP is not set
+CONFIG_HDLC=y
+CONFIG_HDLC_RAW=y
+# CONFIG_HDLC_RAW_ETH is not set
+CONFIG_HDLC_CISCO=y
+CONFIG_HDLC_FR=y
+CONFIG_HDLC_PPP=y
+
+#
+# X.25/LAPB support is disabled
+#
+# CONFIG_PCI200SYN is not set
+# CONFIG_WANXL is not set
+# CONFIG_PC300 is not set
+# CONFIG_FARSYNC is not set
+CONFIG_DLCI=y
+CONFIG_DLCI_COUNT=24
+CONFIG_DLCI_MAX=8
+# CONFIG_FDDI is not set
+# CONFIG_HIPPI is not set
+# CONFIG_PPP is not set
+# CONFIG_SLIP is not set
+# CONFIG_SHAPER is not set
+# CONFIG_NETCONSOLE is not set
+
+#
+# SCSI device support
+#
+# CONFIG_SCSI is not set
+
+#
+# Fusion MPT device support
+#
+
+#
+# IEEE 1394 (FireWire) support
+#
+# CONFIG_IEEE1394 is not set
+
+#
+# I2O device support
+#
+# CONFIG_I2O is not set
+
+#
+# ISDN subsystem
+#
+# CONFIG_ISDN is not set
+
+#
+# Input device support
+#
+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_I8042 is not set
+
+#
+# Input Device Drivers
+#
+# CONFIG_INPUT_KEYBOARD is not set
+# CONFIG_INPUT_MOUSE 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 is not set
+# CONFIG_SERIAL_NONSTANDARD is not set
+
+#
+# Serial drivers
+#
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_NR_UARTS=2
+# CONFIG_SERIAL_8250_EXTENDED is not set
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+CONFIG_UNIX98_PTYS=y
+CONFIG_LEGACY_PTYS=y
+CONFIG_LEGACY_PTY_COUNT=256
+# CONFIG_QIC02_TAPE is not set
+
+#
+# IPMI
+#
+# CONFIG_IPMI_HANDLER is not set
+
+#
+# Watchdog Cards
+#
+CONFIG_WATCHDOG=y
+# CONFIG_WATCHDOG_NOWAYOUT is not set
+
+#
+# Watchdog Device Drivers
+#
+# CONFIG_SOFT_WATCHDOG is not set
+CONFIG_IXP2000_WATCHDOG=y
+
+#
+# PCI-based Watchdog Cards
+#
+# CONFIG_PCIPCWATCHDOG is not set
+# CONFIG_WDTPCI is not set
+# CONFIG_NVRAM is not set
+# CONFIG_RTC is not set
+# CONFIG_GEN_RTC is not set
+# CONFIG_DTLK is not set
+# CONFIG_R3964 is not set
+# CONFIG_APPLICOM is not set
+
+#
+# Ftape, the floppy tape device driver
+#
+# CONFIG_AGP is not set
+# CONFIG_DRM is not set
+# CONFIG_RAW_DRIVER is not set
+
+#
+# I2C support
+#
+CONFIG_I2C=y
+CONFIG_I2C_CHARDEV=y
+
+#
+# I2C Algorithms
+#
+CONFIG_I2C_ALGOBIT=y
+# CONFIG_I2C_ALGOPCF is not set
+
+#
+# I2C Hardware Bus support
+#
+# CONFIG_I2C_ALI1535 is not set
+# CONFIG_I2C_ALI1563 is not set
+# CONFIG_I2C_ALI15X3 is not set
+# CONFIG_I2C_AMD756 is not set
+# CONFIG_I2C_AMD8111 is not set
+# CONFIG_I2C_I801 is not set
+# CONFIG_I2C_I810 is not set
+# CONFIG_I2C_ISA is not set
+# CONFIG_I2C_IXP2000 is not set
+# CONFIG_I2C_NFORCE2 is not set
+# CONFIG_I2C_PARPORT_LIGHT is not set
+# CONFIG_I2C_PIIX4 is not set
+# CONFIG_I2C_PROSAVAGE is not set
+# CONFIG_I2C_SAVAGE4 is not set
+# CONFIG_SCx200_ACB is not set
+# CONFIG_I2C_SIS5595 is not set
+# CONFIG_I2C_SIS630 is not set
+# CONFIG_I2C_SIS96X is not set
+# CONFIG_I2C_VIA is not set
+# CONFIG_I2C_VIAPRO is not set
+# CONFIG_I2C_VOODOO3 is not set
+
+#
+# Hardware Sensors Chip support
+#
+CONFIG_I2C_SENSOR=y
+# CONFIG_SENSORS_ADM1021 is not set
+# CONFIG_SENSORS_ADM1025 is not set
+# CONFIG_SENSORS_ADM1031 is not set
+# CONFIG_SENSORS_ASB100 is not set
+# CONFIG_SENSORS_DS1621 is not set
+# CONFIG_SENSORS_FSCHER is not set
+# CONFIG_SENSORS_GL518SM is not set
+# CONFIG_SENSORS_IT87 is not set
+# CONFIG_SENSORS_LM75 is not set
+# CONFIG_SENSORS_LM77 is not set
+# CONFIG_SENSORS_LM78 is not set
+# CONFIG_SENSORS_LM80 is not set
+# CONFIG_SENSORS_LM83 is not set
+# CONFIG_SENSORS_LM85 is not set
+# CONFIG_SENSORS_LM90 is not set
+# CONFIG_SENSORS_MAX1619 is not set
+# CONFIG_SENSORS_VIA686A is not set
+# CONFIG_SENSORS_W83781D is not set
+# CONFIG_SENSORS_W83L785TS is not set
+# CONFIG_SENSORS_W83627HF is not set
+
+#
+# Other I2C Chip support
+#
+CONFIG_SENSORS_EEPROM=y
+# CONFIG_SENSORS_PCF8574 is not set
+# CONFIG_SENSORS_PCF8591 is not set
+# CONFIG_SENSORS_RTC8564 is not set
+# CONFIG_I2C_DEBUG_CORE is not set
+# CONFIG_I2C_DEBUG_ALGO is not set
+# CONFIG_I2C_DEBUG_BUS is not set
+# CONFIG_I2C_DEBUG_CHIP is not set
+
+#
+# Multimedia devices
+#
+# CONFIG_VIDEO_DEV is not set
+
+#
+# Digital Video Broadcasting Devices
+#
+# CONFIG_DVB is not set
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+CONFIG_EXT2_FS_XATTR=y
+CONFIG_EXT2_FS_POSIX_ACL=y
+# CONFIG_EXT2_FS_SECURITY is not set
+CONFIG_EXT3_FS=y
+CONFIG_EXT3_FS_XATTR=y
+CONFIG_EXT3_FS_POSIX_ACL=y
+# CONFIG_EXT3_FS_SECURITY is not set
+CONFIG_JBD=y
+# CONFIG_JBD_DEBUG is not set
+CONFIG_FS_MBCACHE=y
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+CONFIG_FS_POSIX_ACL=y
+# CONFIG_XFS_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_ROMFS_FS is not set
+# CONFIG_QUOTA is not set
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_AUTOFS4_FS is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+# CONFIG_ISO9660_FS is not set
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+# 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_SYSFS=y
+# CONFIG_DEVFS_FS 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_EFS_FS is not set
+# CONFIG_JFFS_FS is not set
+CONFIG_JFFS2_FS=y
+CONFIG_JFFS2_FS_DEBUG=0
+# CONFIG_JFFS2_FS_NAND is not set
+# CONFIG_JFFS2_COMPRESSION_OPTIONS is not set
+CONFIG_JFFS2_ZLIB=y
+CONFIG_JFFS2_RTIME=y
+# CONFIG_JFFS2_RUBIN is not set
+# CONFIG_CRAMFS is not set
+# CONFIG_VXFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+
+#
+# Network File Systems
+#
+CONFIG_NFS_FS=y
+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_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_AFS_FS is not set
+
+#
+# Partition Types
+#
+CONFIG_PARTITION_ADVANCED=y
+# CONFIG_ACORN_PARTITION is not set
+# CONFIG_OSF_PARTITION is not set
+# CONFIG_AMIGA_PARTITION is not set
+# CONFIG_ATARI_PARTITION is not set
+# CONFIG_MAC_PARTITION is not set
+CONFIG_MSDOS_PARTITION=y
+# CONFIG_BSD_DISKLABEL is not set
+# CONFIG_MINIX_SUBPARTITION is not set
+# CONFIG_SOLARIS_X86_PARTITION is not set
+# CONFIG_UNIXWARE_DISKLABEL is not set
+# CONFIG_LDM_PARTITION is not set
+# CONFIG_SGI_PARTITION is not set
+# CONFIG_ULTRIX_PARTITION is not set
+# CONFIG_SUN_PARTITION is not set
+# CONFIG_EFI_PARTITION is not set
+
+#
+# Native Language Support
+#
+# CONFIG_NLS is not set
+
+#
+# Profiling support
+#
+# CONFIG_PROFILING is not set
+
+#
+# Graphics support
+#
+# CONFIG_FB is not set
+
+#
+# Sound
+#
+# CONFIG_SOUND is not set
+
+#
+# Misc devices
+#
+
+#
+# USB support
+#
+# CONFIG_USB is not set
+
+#
+# USB Gadget Support
+#
+# CONFIG_USB_GADGET is not set
+
+#
+# Kernel hacking
+#
+CONFIG_FRAME_POINTER=y
+CONFIG_DEBUG_USER=y
+# CONFIG_DEBUG_INFO is not set
+CONFIG_DEBUG_KERNEL=y
+# CONFIG_DEBUG_SLAB is not set
+CONFIG_MAGIC_SYSRQ=y
+# CONFIG_DEBUG_SPINLOCK is not set
+# CONFIG_DEBUG_WAITQ is not set
+CONFIG_DEBUG_BUGVERBOSE=y
+CONFIG_DEBUG_ERRORS=y
+CONFIG_DEBUG_LL=y
+# CONFIG_DEBUG_ICEDCC is not set
+# CONFIG_DEBUG_BDI2000_XSCALE is not set
+
+#
+# Security options
+#
+# CONFIG_SECURITY is not set
+
+#
+# Cryptographic options
+#
+# CONFIG_CRYPTO is not set
+
+#
+# Library routines
+#
+# CONFIG_CRC_CCITT is not set
+CONFIG_CRC32=y
+# CONFIG_LIBCRC32C is not set
+CONFIG_ZLIB_INFLATE=y
+CONFIG_ZLIB_DEFLATE=y
diff -Nru a/arch/arm/configs/ixdp2401_defconfig b/arch/arm/configs/ixdp2401_defconfig
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/arch/arm/configs/ixdp2401_defconfig	2004-10-18 14:57:24 -07:00
@@ -0,0 +1,797 @@
+#
+# Automatically generated make config: don't edit
+#
+CONFIG_ARM=y
+CONFIG_MMU=y
+CONFIG_UID16=y
+CONFIG_RWSEM_GENERIC_SPINLOCK=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=y
+CONFIG_KALLSYMS=y
+# CONFIG_KALLSYMS_ALL is not set
+# 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=y
+
+#
+# Loadable module support
+#
+# CONFIG_MODULES is not set
+
+#
+# System Type
+#
+# CONFIG_ARCH_CLPS7500 is not set
+# CONFIG_ARCH_CLPS711X is not set
+# CONFIG_ARCH_CO285 is not set
+# CONFIG_ARCH_EBSA110 is not set
+# CONFIG_ARCH_CAMELOT is not set
+# CONFIG_ARCH_FOOTBRIDGE is not set
+# CONFIG_ARCH_INTEGRATOR is not set
+# CONFIG_ARCH_IOP3XX is not set
+# CONFIG_ARCH_IXP4XX is not set
+CONFIG_ARCH_IXP2000=y
+# CONFIG_ARCH_L7200 is not set
+# CONFIG_ARCH_PXA is not set
+# CONFIG_ARCH_RPC is not set
+# CONFIG_ARCH_SA1100 is not set
+# CONFIG_ARCH_S3C2410 is not set
+# CONFIG_ARCH_SHARK is not set
+# CONFIG_ARCH_LH7A40X is not set
+# CONFIG_ARCH_OMAP is not set
+# CONFIG_ARCH_VERSATILE_PB is not set
+CONFIG_ARCH_SUPPORTS_BIG_ENDIAN=y
+
+#
+# Intel IXP2400/2800 Implementation Options
+#
+
+#
+# IXP2400/2800 Platforms
+#
+# CONFIG_ARCH_ENP2611 is not set
+# CONFIG_ARCH_IXDP2400 is not set
+# CONFIG_ARCH_IXDP2800 is not set
+CONFIG_ARCH_IXDP2401=y
+# CONFIG_ARCH_IXDP2801 is not set
+CONFIG_ARCH_IXDP2X01=y
+
+#
+# Processor Type
+#
+CONFIG_CPU_32=y
+CONFIG_CPU_XSCALE=y
+CONFIG_CPU_32v5=y
+CONFIG_CPU_ABRT_EV5T=y
+CONFIG_CPU_TLB_V4WBI=y
+CONFIG_CPU_MINICACHE=y
+
+#
+# Processor Features
+#
+# CONFIG_ARM_THUMB is not set
+CONFIG_CPU_BIG_ENDIAN=y
+CONFIG_XSCALE_PMU=y
+
+#
+# General setup
+#
+CONFIG_PCI=y
+# CONFIG_ZBOOT_ROM is not set
+CONFIG_ZBOOT_ROM_TEXT=0x0
+CONFIG_ZBOOT_ROM_BSS=0x0
+CONFIG_PCI_LEGACY_PROC=y
+CONFIG_PCI_NAMES=y
+
+#
+# At least one math emulation must be selected
+#
+CONFIG_FPE_NWFPE=y
+# CONFIG_FPE_NWFPE_XP is not set
+# CONFIG_FPE_FASTFPE is not set
+# CONFIG_VFP is not set
+CONFIG_BINFMT_ELF=y
+# CONFIG_BINFMT_AOUT is not set
+# CONFIG_BINFMT_MISC is not set
+
+#
+# Generic Driver Options
+#
+CONFIG_STANDALONE=y
+# CONFIG_PREVENT_FIRMWARE_BUILD is not set
+# CONFIG_DEBUG_DRIVER is not set
+# CONFIG_PM is not set
+# CONFIG_PREEMPT is not set
+# CONFIG_ARTHUR is not set
+CONFIG_CMDLINE="console=ttyS0,57600 root=/dev/nfs ip=bootp mem=64M@0x0 pci=firmware"
+CONFIG_ALIGNMENT_TRAP=y
+
+#
+# Parallel port support
+#
+# CONFIG_PARPORT is not set
+
+#
+# Memory Technology Devices (MTD)
+#
+CONFIG_MTD=y
+# CONFIG_MTD_DEBUG is not set
+CONFIG_MTD_PARTITIONS=y
+# CONFIG_MTD_CONCAT is not set
+CONFIG_MTD_REDBOOT_PARTS=y
+CONFIG_MTD_REDBOOT_PARTS_UNALLOCATED=y
+CONFIG_MTD_REDBOOT_PARTS_READONLY=y
+# CONFIG_MTD_CMDLINE_PARTS is not set
+# CONFIG_MTD_AFS_PARTS is not set
+
+#
+# User Modules And Translation Layers
+#
+CONFIG_MTD_CHAR=y
+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=y
+# CONFIG_MTD_JEDECPROBE is not set
+CONFIG_MTD_GEN_PROBE=y
+# CONFIG_MTD_CFI_ADV_OPTIONS 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_CFI_INTELEXT=y
+# CONFIG_MTD_CFI_AMDSTD is not set
+# CONFIG_MTD_CFI_STAA is not set
+CONFIG_MTD_CFI_UTIL=y
+# CONFIG_MTD_RAM is not set
+# CONFIG_MTD_ROM is not set
+# CONFIG_MTD_ABSENT is not set
+
+#
+# Mapping drivers for chip access
+#
+CONFIG_MTD_COMPLEX_MAPPINGS=y
+# CONFIG_MTD_PHYSMAP is not set
+# CONFIG_MTD_ARM_INTEGRATOR is not set
+CONFIG_MTD_IXP2000=y
+# CONFIG_MTD_EDB7312 is not set
+# CONFIG_MTD_PCI is not set
+
+#
+# Self-contained MTD device drivers
+#
+# CONFIG_MTD_PMC551 is not set
+# CONFIG_MTD_SLRAM is not set
+# CONFIG_MTD_PHRAM is not set
+# CONFIG_MTD_MTDRAM is not set
+# CONFIG_MTD_BLKMTD is not set
+
+#
+# Disk-On-Chip Device Drivers
+#
+# CONFIG_MTD_DOC2000 is not set
+# CONFIG_MTD_DOC2001 is not set
+# CONFIG_MTD_DOC2001PLUS is not set
+
+#
+# NAND Flash Device Drivers
+#
+# CONFIG_MTD_NAND is not set
+
+#
+# Plug and Play support
+#
+
+#
+# Block devices
+#
+# CONFIG_BLK_DEV_FD is not set
+# CONFIG_BLK_CPQ_DA is not set
+# CONFIG_BLK_CPQ_CISS_DA is not set
+# CONFIG_BLK_DEV_DAC960 is not set
+# CONFIG_BLK_DEV_UMEM is not set
+CONFIG_BLK_DEV_LOOP=y
+# CONFIG_BLK_DEV_CRYPTOLOOP 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=8192
+CONFIG_BLK_DEV_INITRD=y
+
+#
+# Multi-device support (RAID and LVM)
+#
+# CONFIG_MD is not set
+
+#
+# Networking support
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+CONFIG_PACKET=y
+CONFIG_PACKET_MMAP=y
+# CONFIG_NETLINK_DEV is not set
+CONFIG_UNIX=y
+# CONFIG_NET_KEY is not set
+CONFIG_INET=y
+# CONFIG_IP_MULTICAST is not set
+# CONFIG_IP_ADVANCED_ROUTER is not set
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_DHCP=y
+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_ARPD is not set
+CONFIG_SYN_COOKIES=y
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+# CONFIG_IPV6 is not set
+# CONFIG_NETFILTER is not set
+
+#
+# SCTP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_SCTP is not set
+# CONFIG_ATM is not set
+# CONFIG_BRIDGE is not set
+# CONFIG_VLAN_8021Q is not set
+# CONFIG_DECNET 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
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+# CONFIG_NET_FASTROUTE is not set
+# CONFIG_NET_HW_FLOWCONTROL is not set
+
+#
+# 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=y
+# CONFIG_BONDING is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
+
+#
+# ARCnet devices
+#
+# CONFIG_ARCNET is not set
+
+#
+# Ethernet (10 or 100Mbit)
+#
+CONFIG_NET_ETHERNET=y
+CONFIG_MII=y
+# CONFIG_HAPPYMEAL is not set
+# CONFIG_SUNGEM is not set
+# CONFIG_NET_VENDOR_3COM is not set
+# CONFIG_SMC91X is not set
+
+#
+# Tulip family network device support
+#
+# CONFIG_NET_TULIP is not set
+# CONFIG_HP100 is not set
+CONFIG_NET_PCI=y
+# CONFIG_PCNET32 is not set
+# CONFIG_AMD8111_ETH is not set
+# CONFIG_ADAPTEC_STARFIRE is not set
+# CONFIG_B44 is not set
+# CONFIG_FORCEDETH is not set
+CONFIG_CS89x0=y
+# CONFIG_DGRS is not set
+CONFIG_EEPRO100=y
+# CONFIG_EEPRO100_PIO is not set
+# CONFIG_E100 is not set
+# CONFIG_FEALNX is not set
+# CONFIG_NATSEMI is not set
+# CONFIG_NE2K_PCI 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_TLAN is not set
+# CONFIG_VIA_RHINE is not set
+# CONFIG_VIA_VELOCITY is not set
+
+#
+# Ethernet (1000 Mbit)
+#
+# CONFIG_ACENIC is not set
+# CONFIG_DL2K is not set
+# CONFIG_E1000 is not set
+# CONFIG_NS83820 is not set
+# CONFIG_HAMACHI is not set
+# CONFIG_YELLOWFIN is not set
+# CONFIG_R8169 is not set
+# CONFIG_SK98LIN is not set
+# CONFIG_TIGON3 is not set
+
+#
+# Ethernet (10000 Mbit)
+#
+# CONFIG_IXGB is not set
+# CONFIG_S2IO is not set
+
+#
+# Token Ring devices
+#
+# CONFIG_TR is not set
+
+#
+# Wireless LAN (non-hamradio)
+#
+# CONFIG_NET_RADIO is not set
+
+#
+# Wan interfaces
+#
+CONFIG_WAN=y
+# CONFIG_LANMEDIA is not set
+# CONFIG_SYNCLINK_SYNCPPP is not set
+CONFIG_HDLC=y
+CONFIG_HDLC_RAW=y
+# CONFIG_HDLC_RAW_ETH is not set
+CONFIG_HDLC_CISCO=y
+CONFIG_HDLC_FR=y
+CONFIG_HDLC_PPP=y
+
+#
+# X.25/LAPB support is disabled
+#
+# CONFIG_PCI200SYN is not set
+# CONFIG_WANXL is not set
+# CONFIG_PC300 is not set
+# CONFIG_FARSYNC is not set
+CONFIG_DLCI=y
+CONFIG_DLCI_COUNT=24
+CONFIG_DLCI_MAX=8
+# CONFIG_FDDI is not set
+# CONFIG_HIPPI is not set
+# CONFIG_PPP is not set
+# CONFIG_SLIP is not set
+# CONFIG_SHAPER is not set
+# CONFIG_NETCONSOLE is not set
+
+#
+# SCSI device support
+#
+# CONFIG_SCSI is not set
+
+#
+# Fusion MPT device support
+#
+
+#
+# IEEE 1394 (FireWire) support
+#
+# CONFIG_IEEE1394 is not set
+
+#
+# I2O device support
+#
+# CONFIG_I2O is not set
+
+#
+# ISDN subsystem
+#
+# CONFIG_ISDN is not set
+
+#
+# Input device support
+#
+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_I8042 is not set
+
+#
+# Input Device Drivers
+#
+# CONFIG_INPUT_KEYBOARD is not set
+# CONFIG_INPUT_MOUSE 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 is not set
+# CONFIG_SERIAL_NONSTANDARD is not set
+
+#
+# Serial drivers
+#
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_NR_UARTS=2
+# CONFIG_SERIAL_8250_EXTENDED is not set
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+CONFIG_UNIX98_PTYS=y
+CONFIG_LEGACY_PTYS=y
+CONFIG_LEGACY_PTY_COUNT=256
+# CONFIG_QIC02_TAPE is not set
+
+#
+# IPMI
+#
+# CONFIG_IPMI_HANDLER is not set
+
+#
+# Watchdog Cards
+#
+CONFIG_WATCHDOG=y
+# CONFIG_WATCHDOG_NOWAYOUT is not set
+
+#
+# Watchdog Device Drivers
+#
+# CONFIG_SOFT_WATCHDOG is not set
+CONFIG_IXP2000_WATCHDOG=y
+
+#
+# PCI-based Watchdog Cards
+#
+# CONFIG_PCIPCWATCHDOG is not set
+# CONFIG_WDTPCI is not set
+# CONFIG_NVRAM is not set
+# CONFIG_RTC is not set
+# CONFIG_GEN_RTC is not set
+# CONFIG_DTLK is not set
+# CONFIG_R3964 is not set
+# CONFIG_APPLICOM is not set
+
+#
+# Ftape, the floppy tape device driver
+#
+# CONFIG_AGP is not set
+# CONFIG_DRM is not set
+# CONFIG_RAW_DRIVER is not set
+
+#
+# I2C support
+#
+CONFIG_I2C=y
+CONFIG_I2C_CHARDEV=y
+
+#
+# I2C Algorithms
+#
+CONFIG_I2C_ALGOBIT=y
+# CONFIG_I2C_ALGOPCF is not set
+
+#
+# I2C Hardware Bus support
+#
+# CONFIG_I2C_ALI1535 is not set
+# CONFIG_I2C_ALI1563 is not set
+# CONFIG_I2C_ALI15X3 is not set
+# CONFIG_I2C_AMD756 is not set
+# CONFIG_I2C_AMD8111 is not set
+# CONFIG_I2C_I801 is not set
+# CONFIG_I2C_I810 is not set
+# CONFIG_I2C_ISA is not set
+# CONFIG_I2C_IXP2000 is not set
+# CONFIG_I2C_NFORCE2 is not set
+# CONFIG_I2C_PARPORT_LIGHT is not set
+# CONFIG_I2C_PIIX4 is not set
+# CONFIG_I2C_PROSAVAGE is not set
+# CONFIG_I2C_SAVAGE4 is not set
+# CONFIG_SCx200_ACB is not set
+# CONFIG_I2C_SIS5595 is not set
+# CONFIG_I2C_SIS630 is not set
+# CONFIG_I2C_SIS96X is not set
+# CONFIG_I2C_VIA is not set
+# CONFIG_I2C_VIAPRO is not set
+# CONFIG_I2C_VOODOO3 is not set
+
+#
+# Hardware Sensors Chip support
+#
+CONFIG_I2C_SENSOR=y
+# CONFIG_SENSORS_ADM1021 is not set
+# CONFIG_SENSORS_ADM1025 is not set
+# CONFIG_SENSORS_ADM1031 is not set
+# CONFIG_SENSORS_ASB100 is not set
+# CONFIG_SENSORS_DS1621 is not set
+# CONFIG_SENSORS_FSCHER is not set
+# CONFIG_SENSORS_GL518SM is not set
+# CONFIG_SENSORS_IT87 is not set
+# CONFIG_SENSORS_LM75 is not set
+# CONFIG_SENSORS_LM77 is not set
+# CONFIG_SENSORS_LM78 is not set
+# CONFIG_SENSORS_LM80 is not set
+# CONFIG_SENSORS_LM83 is not set
+# CONFIG_SENSORS_LM85 is not set
+# CONFIG_SENSORS_LM90 is not set
+# CONFIG_SENSORS_MAX1619 is not set
+# CONFIG_SENSORS_VIA686A is not set
+# CONFIG_SENSORS_W83781D is not set
+# CONFIG_SENSORS_W83L785TS is not set
+# CONFIG_SENSORS_W83627HF is not set
+
+#
+# Other I2C Chip support
+#
+CONFIG_SENSORS_EEPROM=y
+# CONFIG_SENSORS_PCF8574 is not set
+# CONFIG_SENSORS_PCF8591 is not set
+# CONFIG_SENSORS_RTC8564 is not set
+# CONFIG_I2C_DEBUG_CORE is not set
+# CONFIG_I2C_DEBUG_ALGO is not set
+# CONFIG_I2C_DEBUG_BUS is not set
+# CONFIG_I2C_DEBUG_CHIP is not set
+
+#
+# Multimedia devices
+#
+# CONFIG_VIDEO_DEV is not set
+
+#
+# Digital Video Broadcasting Devices
+#
+# CONFIG_DVB is not set
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+CONFIG_EXT2_FS_XATTR=y
+CONFIG_EXT2_FS_POSIX_ACL=y
+# CONFIG_EXT2_FS_SECURITY is not set
+CONFIG_EXT3_FS=y
+CONFIG_EXT3_FS_XATTR=y
+CONFIG_EXT3_FS_POSIX_ACL=y
+# CONFIG_EXT3_FS_SECURITY is not set
+CONFIG_JBD=y
+# CONFIG_JBD_DEBUG is not set
+CONFIG_FS_MBCACHE=y
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+CONFIG_FS_POSIX_ACL=y
+# CONFIG_XFS_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_ROMFS_FS is not set
+# CONFIG_QUOTA is not set
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_AUTOFS4_FS is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+# CONFIG_ISO9660_FS is not set
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+# 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_SYSFS=y
+# CONFIG_DEVFS_FS 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_EFS_FS is not set
+# CONFIG_JFFS_FS is not set
+CONFIG_JFFS2_FS=y
+CONFIG_JFFS2_FS_DEBUG=0
+# CONFIG_JFFS2_FS_NAND is not set
+# CONFIG_JFFS2_COMPRESSION_OPTIONS is not set
+CONFIG_JFFS2_ZLIB=y
+CONFIG_JFFS2_RTIME=y
+# CONFIG_JFFS2_RUBIN is not set
+# CONFIG_CRAMFS is not set
+# CONFIG_VXFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+
+#
+# Network File Systems
+#
+CONFIG_NFS_FS=y
+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_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_AFS_FS is not set
+
+#
+# Partition Types
+#
+CONFIG_PARTITION_ADVANCED=y
+# CONFIG_ACORN_PARTITION is not set
+# CONFIG_OSF_PARTITION is not set
+# CONFIG_AMIGA_PARTITION is not set
+# CONFIG_ATARI_PARTITION is not set
+# CONFIG_MAC_PARTITION is not set
+CONFIG_MSDOS_PARTITION=y
+# CONFIG_BSD_DISKLABEL is not set
+# CONFIG_MINIX_SUBPARTITION is not set
+# CONFIG_SOLARIS_X86_PARTITION is not set
+# CONFIG_UNIXWARE_DISKLABEL is not set
+# CONFIG_LDM_PARTITION is not set
+# CONFIG_SGI_PARTITION is not set
+# CONFIG_ULTRIX_PARTITION is not set
+# CONFIG_SUN_PARTITION is not set
+# CONFIG_EFI_PARTITION is not set
+
+#
+# Native Language Support
+#
+# CONFIG_NLS is not set
+
+#
+# Profiling support
+#
+# CONFIG_PROFILING is not set
+
+#
+# Graphics support
+#
+# CONFIG_FB is not set
+
+#
+# Sound
+#
+# CONFIG_SOUND is not set
+
+#
+# Misc devices
+#
+
+#
+# USB support
+#
+# CONFIG_USB is not set
+
+#
+# USB Gadget Support
+#
+# CONFIG_USB_GADGET is not set
+
+#
+# Kernel hacking
+#
+CONFIG_FRAME_POINTER=y
+CONFIG_DEBUG_USER=y
+# CONFIG_DEBUG_INFO is not set
+CONFIG_DEBUG_KERNEL=y
+# CONFIG_DEBUG_SLAB is not set
+CONFIG_MAGIC_SYSRQ=y
+# CONFIG_DEBUG_SPINLOCK is not set
+# CONFIG_DEBUG_WAITQ is not set
+CONFIG_DEBUG_BUGVERBOSE=y
+CONFIG_DEBUG_ERRORS=y
+CONFIG_DEBUG_LL=y
+# CONFIG_DEBUG_ICEDCC is not set
+# CONFIG_DEBUG_BDI2000_XSCALE is not set
+
+#
+# Security options
+#
+# CONFIG_SECURITY is not set
+
+#
+# Cryptographic options
+#
+# CONFIG_CRYPTO is not set
+
+#
+# Library routines
+#
+# CONFIG_CRC_CCITT is not set
+CONFIG_CRC32=y
+# CONFIG_LIBCRC32C is not set
+CONFIG_ZLIB_INFLATE=y
+CONFIG_ZLIB_DEFLATE=y
diff -Nru a/arch/arm/configs/ixdp2800_defconfig b/arch/arm/configs/ixdp2800_defconfig
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/arch/arm/configs/ixdp2800_defconfig	2004-10-18 14:57:24 -07:00
@@ -0,0 +1,796 @@
+#
+# Automatically generated make config: don't edit
+#
+CONFIG_ARM=y
+CONFIG_MMU=y
+CONFIG_UID16=y
+CONFIG_RWSEM_GENERIC_SPINLOCK=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=y
+CONFIG_KALLSYMS=y
+# CONFIG_KALLSYMS_ALL is not set
+# 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=y
+
+#
+# Loadable module support
+#
+# CONFIG_MODULES is not set
+
+#
+# System Type
+#
+# CONFIG_ARCH_CLPS7500 is not set
+# CONFIG_ARCH_CLPS711X is not set
+# CONFIG_ARCH_CO285 is not set
+# CONFIG_ARCH_EBSA110 is not set
+# CONFIG_ARCH_CAMELOT is not set
+# CONFIG_ARCH_FOOTBRIDGE is not set
+# CONFIG_ARCH_INTEGRATOR is not set
+# CONFIG_ARCH_IOP3XX is not set
+# CONFIG_ARCH_IXP4XX is not set
+CONFIG_ARCH_IXP2000=y
+# CONFIG_ARCH_L7200 is not set
+# CONFIG_ARCH_PXA is not set
+# CONFIG_ARCH_RPC is not set
+# CONFIG_ARCH_SA1100 is not set
+# CONFIG_ARCH_S3C2410 is not set
+# CONFIG_ARCH_SHARK is not set
+# CONFIG_ARCH_LH7A40X is not set
+# CONFIG_ARCH_OMAP is not set
+# CONFIG_ARCH_VERSATILE_PB is not set
+CONFIG_ARCH_SUPPORTS_BIG_ENDIAN=y
+
+#
+# Intel IXP2400/2800 Implementation Options
+#
+
+#
+# IXP2400/2800 Platforms
+#
+# CONFIG_ARCH_ENP2611 is not set
+# CONFIG_ARCH_IXDP2400 is not set
+CONFIG_ARCH_IXDP2800=y
+CONFIG_ARCH_IXDP2X00=y
+# CONFIG_ARCH_IXDP2401 is not set
+# CONFIG_ARCH_IXDP2801 is not set
+
+#
+# Processor Type
+#
+CONFIG_CPU_32=y
+CONFIG_CPU_XSCALE=y
+CONFIG_CPU_32v5=y
+CONFIG_CPU_ABRT_EV5T=y
+CONFIG_CPU_TLB_V4WBI=y
+CONFIG_CPU_MINICACHE=y
+
+#
+# Processor Features
+#
+# CONFIG_ARM_THUMB is not set
+CONFIG_CPU_BIG_ENDIAN=y
+CONFIG_XSCALE_PMU=y
+
+#
+# General setup
+#
+CONFIG_PCI=y
+# CONFIG_ZBOOT_ROM is not set
+CONFIG_ZBOOT_ROM_TEXT=0x0
+CONFIG_ZBOOT_ROM_BSS=0x0
+CONFIG_PCI_LEGACY_PROC=y
+CONFIG_PCI_NAMES=y
+
+#
+# At least one math emulation must be selected
+#
+CONFIG_FPE_NWFPE=y
+# CONFIG_FPE_NWFPE_XP is not set
+# CONFIG_FPE_FASTFPE is not set
+# CONFIG_VFP is not set
+CONFIG_BINFMT_ELF=y
+# CONFIG_BINFMT_AOUT is not set
+# CONFIG_BINFMT_MISC is not set
+
+#
+# Generic Driver Options
+#
+CONFIG_STANDALONE=y
+# CONFIG_PREVENT_FIRMWARE_BUILD is not set
+# CONFIG_DEBUG_DRIVER is not set
+# CONFIG_PM is not set
+# CONFIG_PREEMPT is not set
+# CONFIG_ARTHUR is not set
+CONFIG_CMDLINE="console=ttyS0,9600 root=/dev/nfs ip=bootp mem=64M@0x0 pci=firmware"
+CONFIG_ALIGNMENT_TRAP=y
+
+#
+# Parallel port support
+#
+# CONFIG_PARPORT is not set
+
+#
+# Memory Technology Devices (MTD)
+#
+CONFIG_MTD=y
+# CONFIG_MTD_DEBUG is not set
+CONFIG_MTD_PARTITIONS=y
+# CONFIG_MTD_CONCAT is not set
+CONFIG_MTD_REDBOOT_PARTS=y
+CONFIG_MTD_REDBOOT_PARTS_UNALLOCATED=y
+CONFIG_MTD_REDBOOT_PARTS_READONLY=y
+# CONFIG_MTD_CMDLINE_PARTS is not set
+# CONFIG_MTD_AFS_PARTS is not set
+
+#
+# User Modules And Translation Layers
+#
+CONFIG_MTD_CHAR=y
+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=y
+# CONFIG_MTD_JEDECPROBE is not set
+CONFIG_MTD_GEN_PROBE=y
+# CONFIG_MTD_CFI_ADV_OPTIONS 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_CFI_INTELEXT=y
+# CONFIG_MTD_CFI_AMDSTD is not set
+# CONFIG_MTD_CFI_STAA is not set
+CONFIG_MTD_CFI_UTIL=y
+# CONFIG_MTD_RAM is not set
+# CONFIG_MTD_ROM is not set
+# CONFIG_MTD_ABSENT is not set
+
+#
+# Mapping drivers for chip access
+#
+CONFIG_MTD_COMPLEX_MAPPINGS=y
+# CONFIG_MTD_PHYSMAP is not set
+# CONFIG_MTD_ARM_INTEGRATOR is not set
+CONFIG_MTD_IXP2000=y
+# CONFIG_MTD_EDB7312 is not set
+# CONFIG_MTD_PCI is not set
+
+#
+# Self-contained MTD device drivers
+#
+# CONFIG_MTD_PMC551 is not set
+# CONFIG_MTD_SLRAM is not set
+# CONFIG_MTD_PHRAM is not set
+# CONFIG_MTD_MTDRAM is not set
+# CONFIG_MTD_BLKMTD is not set
+
+#
+# Disk-On-Chip Device Drivers
+#
+# CONFIG_MTD_DOC2000 is not set
+# CONFIG_MTD_DOC2001 is not set
+# CONFIG_MTD_DOC2001PLUS is not set
+
+#
+# NAND Flash Device Drivers
+#
+# CONFIG_MTD_NAND is not set
+
+#
+# Plug and Play support
+#
+
+#
+# Block devices
+#
+# CONFIG_BLK_DEV_FD is not set
+# CONFIG_BLK_CPQ_DA is not set
+# CONFIG_BLK_CPQ_CISS_DA is not set
+# CONFIG_BLK_DEV_DAC960 is not set
+# CONFIG_BLK_DEV_UMEM is not set
+CONFIG_BLK_DEV_LOOP=y
+# CONFIG_BLK_DEV_CRYPTOLOOP 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=8192
+CONFIG_BLK_DEV_INITRD=y
+
+#
+# Multi-device support (RAID and LVM)
+#
+# CONFIG_MD is not set
+
+#
+# Networking support
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+CONFIG_PACKET=y
+CONFIG_PACKET_MMAP=y
+# CONFIG_NETLINK_DEV is not set
+CONFIG_UNIX=y
+# CONFIG_NET_KEY is not set
+CONFIG_INET=y
+# CONFIG_IP_MULTICAST is not set
+# CONFIG_IP_ADVANCED_ROUTER is not set
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_DHCP=y
+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_ARPD is not set
+CONFIG_SYN_COOKIES=y
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+# CONFIG_IPV6 is not set
+# CONFIG_NETFILTER is not set
+
+#
+# SCTP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_SCTP is not set
+# CONFIG_ATM is not set
+# CONFIG_BRIDGE is not set
+# CONFIG_VLAN_8021Q is not set
+# CONFIG_DECNET 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
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+# CONFIG_NET_FASTROUTE is not set
+# CONFIG_NET_HW_FLOWCONTROL is not set
+
+#
+# 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=y
+# CONFIG_BONDING is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
+
+#
+# ARCnet devices
+#
+# CONFIG_ARCNET is not set
+
+#
+# Ethernet (10 or 100Mbit)
+#
+CONFIG_NET_ETHERNET=y
+CONFIG_MII=y
+# CONFIG_HAPPYMEAL is not set
+# CONFIG_SUNGEM is not set
+# CONFIG_NET_VENDOR_3COM is not set
+# CONFIG_SMC91X is not set
+
+#
+# Tulip family network device support
+#
+# CONFIG_NET_TULIP is not set
+# CONFIG_HP100 is not set
+CONFIG_NET_PCI=y
+# CONFIG_PCNET32 is not set
+# 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_FEALNX is not set
+# CONFIG_NATSEMI is not set
+# CONFIG_NE2K_PCI 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_TLAN is not set
+# CONFIG_VIA_RHINE is not set
+# CONFIG_VIA_VELOCITY is not set
+
+#
+# Ethernet (1000 Mbit)
+#
+# CONFIG_ACENIC is not set
+# CONFIG_DL2K is not set
+# CONFIG_E1000 is not set
+# CONFIG_NS83820 is not set
+# CONFIG_HAMACHI is not set
+# CONFIG_YELLOWFIN is not set
+# CONFIG_R8169 is not set
+# CONFIG_SK98LIN is not set
+# CONFIG_TIGON3 is not set
+
+#
+# Ethernet (10000 Mbit)
+#
+# CONFIG_IXGB is not set
+# CONFIG_S2IO is not set
+
+#
+# Token Ring devices
+#
+# CONFIG_TR is not set
+
+#
+# Wireless LAN (non-hamradio)
+#
+# CONFIG_NET_RADIO is not set
+
+#
+# Wan interfaces
+#
+CONFIG_WAN=y
+# CONFIG_LANMEDIA is not set
+# CONFIG_SYNCLINK_SYNCPPP is not set
+CONFIG_HDLC=y
+CONFIG_HDLC_RAW=y
+# CONFIG_HDLC_RAW_ETH is not set
+CONFIG_HDLC_CISCO=y
+CONFIG_HDLC_FR=y
+CONFIG_HDLC_PPP=y
+
+#
+# X.25/LAPB support is disabled
+#
+# CONFIG_PCI200SYN is not set
+# CONFIG_WANXL is not set
+# CONFIG_PC300 is not set
+# CONFIG_FARSYNC is not set
+CONFIG_DLCI=y
+CONFIG_DLCI_COUNT=24
+CONFIG_DLCI_MAX=8
+# CONFIG_FDDI is not set
+# CONFIG_HIPPI is not set
+# CONFIG_PPP is not set
+# CONFIG_SLIP is not set
+# CONFIG_SHAPER is not set
+# CONFIG_NETCONSOLE is not set
+
+#
+# SCSI device support
+#
+# CONFIG_SCSI is not set
+
+#
+# Fusion MPT device support
+#
+
+#
+# IEEE 1394 (FireWire) support
+#
+# CONFIG_IEEE1394 is not set
+
+#
+# I2O device support
+#
+# CONFIG_I2O is not set
+
+#
+# ISDN subsystem
+#
+# CONFIG_ISDN is not set
+
+#
+# Input device support
+#
+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_I8042 is not set
+
+#
+# Input Device Drivers
+#
+# CONFIG_INPUT_KEYBOARD is not set
+# CONFIG_INPUT_MOUSE 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 is not set
+# CONFIG_SERIAL_NONSTANDARD is not set
+
+#
+# Serial drivers
+#
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_NR_UARTS=2
+# CONFIG_SERIAL_8250_EXTENDED is not set
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+CONFIG_UNIX98_PTYS=y
+CONFIG_LEGACY_PTYS=y
+CONFIG_LEGACY_PTY_COUNT=256
+# CONFIG_QIC02_TAPE is not set
+
+#
+# IPMI
+#
+# CONFIG_IPMI_HANDLER is not set
+
+#
+# Watchdog Cards
+#
+CONFIG_WATCHDOG=y
+# CONFIG_WATCHDOG_NOWAYOUT is not set
+
+#
+# Watchdog Device Drivers
+#
+# CONFIG_SOFT_WATCHDOG is not set
+CONFIG_IXP2000_WATCHDOG=y
+
+#
+# PCI-based Watchdog Cards
+#
+# CONFIG_PCIPCWATCHDOG is not set
+# CONFIG_WDTPCI is not set
+# CONFIG_NVRAM is not set
+# CONFIG_RTC is not set
+# CONFIG_GEN_RTC is not set
+# CONFIG_DTLK is not set
+# CONFIG_R3964 is not set
+# CONFIG_APPLICOM is not set
+
+#
+# Ftape, the floppy tape device driver
+#
+# CONFIG_AGP is not set
+# CONFIG_DRM is not set
+# CONFIG_RAW_DRIVER is not set
+
+#
+# I2C support
+#
+CONFIG_I2C=y
+CONFIG_I2C_CHARDEV=y
+
+#
+# I2C Algorithms
+#
+CONFIG_I2C_ALGOBIT=y
+# CONFIG_I2C_ALGOPCF is not set
+
+#
+# I2C Hardware Bus support
+#
+# CONFIG_I2C_ALI1535 is not set
+# CONFIG_I2C_ALI1563 is not set
+# CONFIG_I2C_ALI15X3 is not set
+# CONFIG_I2C_AMD756 is not set
+# CONFIG_I2C_AMD8111 is not set
+# CONFIG_I2C_I801 is not set
+# CONFIG_I2C_I810 is not set
+# CONFIG_I2C_ISA is not set
+# CONFIG_I2C_IXP2000 is not set
+# CONFIG_I2C_NFORCE2 is not set
+# CONFIG_I2C_PARPORT_LIGHT is not set
+# CONFIG_I2C_PIIX4 is not set
+# CONFIG_I2C_PROSAVAGE is not set
+# CONFIG_I2C_SAVAGE4 is not set
+# CONFIG_SCx200_ACB is not set
+# CONFIG_I2C_SIS5595 is not set
+# CONFIG_I2C_SIS630 is not set
+# CONFIG_I2C_SIS96X is not set
+# CONFIG_I2C_VIA is not set
+# CONFIG_I2C_VIAPRO is not set
+# CONFIG_I2C_VOODOO3 is not set
+
+#
+# Hardware Sensors Chip support
+#
+CONFIG_I2C_SENSOR=y
+# CONFIG_SENSORS_ADM1021 is not set
+# CONFIG_SENSORS_ADM1025 is not set
+# CONFIG_SENSORS_ADM1031 is not set
+# CONFIG_SENSORS_ASB100 is not set
+# CONFIG_SENSORS_DS1621 is not set
+# CONFIG_SENSORS_FSCHER is not set
+# CONFIG_SENSORS_GL518SM is not set
+# CONFIG_SENSORS_IT87 is not set
+# CONFIG_SENSORS_LM75 is not set
+# CONFIG_SENSORS_LM77 is not set
+# CONFIG_SENSORS_LM78 is not set
+# CONFIG_SENSORS_LM80 is not set
+# CONFIG_SENSORS_LM83 is not set
+# CONFIG_SENSORS_LM85 is not set
+# CONFIG_SENSORS_LM90 is not set
+# CONFIG_SENSORS_MAX1619 is not set
+# CONFIG_SENSORS_VIA686A is not set
+# CONFIG_SENSORS_W83781D is not set
+# CONFIG_SENSORS_W83L785TS is not set
+# CONFIG_SENSORS_W83627HF is not set
+
+#
+# Other I2C Chip support
+#
+CONFIG_SENSORS_EEPROM=y
+# CONFIG_SENSORS_PCF8574 is not set
+# CONFIG_SENSORS_PCF8591 is not set
+# CONFIG_SENSORS_RTC8564 is not set
+# CONFIG_I2C_DEBUG_CORE is not set
+# CONFIG_I2C_DEBUG_ALGO is not set
+# CONFIG_I2C_DEBUG_BUS is not set
+# CONFIG_I2C_DEBUG_CHIP is not set
+
+#
+# Multimedia devices
+#
+# CONFIG_VIDEO_DEV is not set
+
+#
+# Digital Video Broadcasting Devices
+#
+# CONFIG_DVB is not set
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+CONFIG_EXT2_FS_XATTR=y
+CONFIG_EXT2_FS_POSIX_ACL=y
+# CONFIG_EXT2_FS_SECURITY is not set
+CONFIG_EXT3_FS=y
+CONFIG_EXT3_FS_XATTR=y
+CONFIG_EXT3_FS_POSIX_ACL=y
+# CONFIG_EXT3_FS_SECURITY is not set
+CONFIG_JBD=y
+# CONFIG_JBD_DEBUG is not set
+CONFIG_FS_MBCACHE=y
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+CONFIG_FS_POSIX_ACL=y
+# CONFIG_XFS_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_ROMFS_FS is not set
+# CONFIG_QUOTA is not set
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_AUTOFS4_FS is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+# CONFIG_ISO9660_FS is not set
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+# 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_SYSFS=y
+# CONFIG_DEVFS_FS 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_EFS_FS is not set
+# CONFIG_JFFS_FS is not set
+CONFIG_JFFS2_FS=y
+CONFIG_JFFS2_FS_DEBUG=0
+# CONFIG_JFFS2_FS_NAND is not set
+# CONFIG_JFFS2_COMPRESSION_OPTIONS is not set
+CONFIG_JFFS2_ZLIB=y
+CONFIG_JFFS2_RTIME=y
+# CONFIG_JFFS2_RUBIN is not set
+# CONFIG_CRAMFS is not set
+# CONFIG_VXFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+
+#
+# Network File Systems
+#
+CONFIG_NFS_FS=y
+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_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_AFS_FS is not set
+
+#
+# Partition Types
+#
+CONFIG_PARTITION_ADVANCED=y
+# CONFIG_ACORN_PARTITION is not set
+# CONFIG_OSF_PARTITION is not set
+# CONFIG_AMIGA_PARTITION is not set
+# CONFIG_ATARI_PARTITION is not set
+# CONFIG_MAC_PARTITION is not set
+CONFIG_MSDOS_PARTITION=y
+# CONFIG_BSD_DISKLABEL is not set
+# CONFIG_MINIX_SUBPARTITION is not set
+# CONFIG_SOLARIS_X86_PARTITION is not set
+# CONFIG_UNIXWARE_DISKLABEL is not set
+# CONFIG_LDM_PARTITION is not set
+# CONFIG_SGI_PARTITION is not set
+# CONFIG_ULTRIX_PARTITION is not set
+# CONFIG_SUN_PARTITION is not set
+# CONFIG_EFI_PARTITION is not set
+
+#
+# Native Language Support
+#
+# CONFIG_NLS is not set
+
+#
+# Profiling support
+#
+# CONFIG_PROFILING is not set
+
+#
+# Graphics support
+#
+# CONFIG_FB is not set
+
+#
+# Sound
+#
+# CONFIG_SOUND is not set
+
+#
+# Misc devices
+#
+
+#
+# USB support
+#
+# CONFIG_USB is not set
+
+#
+# USB Gadget Support
+#
+# CONFIG_USB_GADGET is not set
+
+#
+# Kernel hacking
+#
+CONFIG_FRAME_POINTER=y
+CONFIG_DEBUG_USER=y
+# CONFIG_DEBUG_INFO is not set
+CONFIG_DEBUG_KERNEL=y
+# CONFIG_DEBUG_SLAB is not set
+CONFIG_MAGIC_SYSRQ=y
+# CONFIG_DEBUG_SPINLOCK is not set
+# CONFIG_DEBUG_WAITQ is not set
+CONFIG_DEBUG_BUGVERBOSE=y
+CONFIG_DEBUG_ERRORS=y
+CONFIG_DEBUG_LL=y
+# CONFIG_DEBUG_ICEDCC is not set
+# CONFIG_DEBUG_BDI2000_XSCALE is not set
+
+#
+# Security options
+#
+# CONFIG_SECURITY is not set
+
+#
+# Cryptographic options
+#
+# CONFIG_CRYPTO is not set
+
+#
+# Library routines
+#
+# CONFIG_CRC_CCITT is not set
+CONFIG_CRC32=y
+# CONFIG_LIBCRC32C is not set
+CONFIG_ZLIB_INFLATE=y
+CONFIG_ZLIB_DEFLATE=y
diff -Nru a/arch/arm/configs/ixdp2801_defconfig b/arch/arm/configs/ixdp2801_defconfig
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/arch/arm/configs/ixdp2801_defconfig	2004-10-18 14:57:22 -07:00
@@ -0,0 +1,797 @@
+#
+# Automatically generated make config: don't edit
+#
+CONFIG_ARM=y
+CONFIG_MMU=y
+CONFIG_UID16=y
+CONFIG_RWSEM_GENERIC_SPINLOCK=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=y
+CONFIG_KALLSYMS=y
+# CONFIG_KALLSYMS_ALL is not set
+# 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=y
+
+#
+# Loadable module support
+#
+# CONFIG_MODULES is not set
+
+#
+# System Type
+#
+# CONFIG_ARCH_CLPS7500 is not set
+# CONFIG_ARCH_CLPS711X is not set
+# CONFIG_ARCH_CO285 is not set
+# CONFIG_ARCH_EBSA110 is not set
+# CONFIG_ARCH_CAMELOT is not set
+# CONFIG_ARCH_FOOTBRIDGE is not set
+# CONFIG_ARCH_INTEGRATOR is not set
+# CONFIG_ARCH_IOP3XX is not set
+# CONFIG_ARCH_IXP4XX is not set
+CONFIG_ARCH_IXP2000=y
+# CONFIG_ARCH_L7200 is not set
+# CONFIG_ARCH_PXA is not set
+# CONFIG_ARCH_RPC is not set
+# CONFIG_ARCH_SA1100 is not set
+# CONFIG_ARCH_S3C2410 is not set
+# CONFIG_ARCH_SHARK is not set
+# CONFIG_ARCH_LH7A40X is not set
+# CONFIG_ARCH_OMAP is not set
+# CONFIG_ARCH_VERSATILE_PB is not set
+CONFIG_ARCH_SUPPORTS_BIG_ENDIAN=y
+
+#
+# Intel IXP2400/2800 Implementation Options
+#
+
+#
+# IXP2400/2800 Platforms
+#
+# CONFIG_ARCH_ENP2611 is not set
+# CONFIG_ARCH_IXDP2400 is not set
+# CONFIG_ARCH_IXDP2800 is not set
+# CONFIG_ARCH_IXDP2401 is not set
+CONFIG_ARCH_IXDP2801=y
+CONFIG_ARCH_IXDP2X01=y
+
+#
+# Processor Type
+#
+CONFIG_CPU_32=y
+CONFIG_CPU_XSCALE=y
+CONFIG_CPU_32v5=y
+CONFIG_CPU_ABRT_EV5T=y
+CONFIG_CPU_TLB_V4WBI=y
+CONFIG_CPU_MINICACHE=y
+
+#
+# Processor Features
+#
+# CONFIG_ARM_THUMB is not set
+CONFIG_CPU_BIG_ENDIAN=y
+CONFIG_XSCALE_PMU=y
+
+#
+# General setup
+#
+CONFIG_PCI=y
+# CONFIG_ZBOOT_ROM is not set
+CONFIG_ZBOOT_ROM_TEXT=0x0
+CONFIG_ZBOOT_ROM_BSS=0x0
+CONFIG_PCI_LEGACY_PROC=y
+CONFIG_PCI_NAMES=y
+
+#
+# At least one math emulation must be selected
+#
+CONFIG_FPE_NWFPE=y
+# CONFIG_FPE_NWFPE_XP is not set
+# CONFIG_FPE_FASTFPE is not set
+# CONFIG_VFP is not set
+CONFIG_BINFMT_ELF=y
+# CONFIG_BINFMT_AOUT is not set
+# CONFIG_BINFMT_MISC is not set
+
+#
+# Generic Driver Options
+#
+CONFIG_STANDALONE=y
+# CONFIG_PREVENT_FIRMWARE_BUILD is not set
+# CONFIG_DEBUG_DRIVER is not set
+# CONFIG_PM is not set
+# CONFIG_PREEMPT is not set
+# CONFIG_ARTHUR is not set
+CONFIG_CMDLINE="console=ttyS0,115200 root=/dev/nfs ip=bootp mem=64M@0x0 pci=firmware ixdp2x01_clock=50000000"
+CONFIG_ALIGNMENT_TRAP=y
+
+#
+# Parallel port support
+#
+# CONFIG_PARPORT is not set
+
+#
+# Memory Technology Devices (MTD)
+#
+CONFIG_MTD=y
+# CONFIG_MTD_DEBUG is not set
+CONFIG_MTD_PARTITIONS=y
+# CONFIG_MTD_CONCAT is not set
+CONFIG_MTD_REDBOOT_PARTS=y
+CONFIG_MTD_REDBOOT_PARTS_UNALLOCATED=y
+CONFIG_MTD_REDBOOT_PARTS_READONLY=y
+# CONFIG_MTD_CMDLINE_PARTS is not set
+# CONFIG_MTD_AFS_PARTS is not set
+
+#
+# User Modules And Translation Layers
+#
+CONFIG_MTD_CHAR=y
+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=y
+# CONFIG_MTD_JEDECPROBE is not set
+CONFIG_MTD_GEN_PROBE=y
+# CONFIG_MTD_CFI_ADV_OPTIONS 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_CFI_INTELEXT=y
+# CONFIG_MTD_CFI_AMDSTD is not set
+# CONFIG_MTD_CFI_STAA is not set
+CONFIG_MTD_CFI_UTIL=y
+# CONFIG_MTD_RAM is not set
+# CONFIG_MTD_ROM is not set
+# CONFIG_MTD_ABSENT is not set
+
+#
+# Mapping drivers for chip access
+#
+CONFIG_MTD_COMPLEX_MAPPINGS=y
+# CONFIG_MTD_PHYSMAP is not set
+# CONFIG_MTD_ARM_INTEGRATOR is not set
+CONFIG_MTD_IXP2000=y
+# CONFIG_MTD_EDB7312 is not set
+# CONFIG_MTD_PCI is not set
+
+#
+# Self-contained MTD device drivers
+#
+# CONFIG_MTD_PMC551 is not set
+# CONFIG_MTD_SLRAM is not set
+# CONFIG_MTD_PHRAM is not set
+# CONFIG_MTD_MTDRAM is not set
+# CONFIG_MTD_BLKMTD is not set
+
+#
+# Disk-On-Chip Device Drivers
+#
+# CONFIG_MTD_DOC2000 is not set
+# CONFIG_MTD_DOC2001 is not set
+# CONFIG_MTD_DOC2001PLUS is not set
+
+#
+# NAND Flash Device Drivers
+#
+# CONFIG_MTD_NAND is not set
+
+#
+# Plug and Play support
+#
+
+#
+# Block devices
+#
+# CONFIG_BLK_DEV_FD is not set
+# CONFIG_BLK_CPQ_DA is not set
+# CONFIG_BLK_CPQ_CISS_DA is not set
+# CONFIG_BLK_DEV_DAC960 is not set
+# CONFIG_BLK_DEV_UMEM is not set
+CONFIG_BLK_DEV_LOOP=y
+# CONFIG_BLK_DEV_CRYPTOLOOP 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=8192
+CONFIG_BLK_DEV_INITRD=y
+
+#
+# Multi-device support (RAID and LVM)
+#
+# CONFIG_MD is not set
+
+#
+# Networking support
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+CONFIG_PACKET=y
+CONFIG_PACKET_MMAP=y
+# CONFIG_NETLINK_DEV is not set
+CONFIG_UNIX=y
+# CONFIG_NET_KEY is not set
+CONFIG_INET=y
+# CONFIG_IP_MULTICAST is not set
+# CONFIG_IP_ADVANCED_ROUTER is not set
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_DHCP=y
+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_ARPD is not set
+CONFIG_SYN_COOKIES=y
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+# CONFIG_IPV6 is not set
+# CONFIG_NETFILTER is not set
+
+#
+# SCTP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_SCTP is not set
+# CONFIG_ATM is not set
+# CONFIG_BRIDGE is not set
+# CONFIG_VLAN_8021Q is not set
+# CONFIG_DECNET 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
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+# CONFIG_NET_FASTROUTE is not set
+# CONFIG_NET_HW_FLOWCONTROL is not set
+
+#
+# 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=y
+# CONFIG_BONDING is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
+
+#
+# ARCnet devices
+#
+# CONFIG_ARCNET is not set
+
+#
+# Ethernet (10 or 100Mbit)
+#
+CONFIG_NET_ETHERNET=y
+CONFIG_MII=y
+# CONFIG_HAPPYMEAL is not set
+# CONFIG_SUNGEM is not set
+# CONFIG_NET_VENDOR_3COM is not set
+# CONFIG_SMC91X is not set
+
+#
+# Tulip family network device support
+#
+# CONFIG_NET_TULIP is not set
+# CONFIG_HP100 is not set
+CONFIG_NET_PCI=y
+# CONFIG_PCNET32 is not set
+# CONFIG_AMD8111_ETH is not set
+# CONFIG_ADAPTEC_STARFIRE is not set
+# CONFIG_B44 is not set
+# CONFIG_FORCEDETH is not set
+CONFIG_CS89x0=y
+# CONFIG_DGRS is not set
+CONFIG_EEPRO100=y
+# CONFIG_EEPRO100_PIO is not set
+# CONFIG_E100 is not set
+# CONFIG_FEALNX is not set
+# CONFIG_NATSEMI is not set
+# CONFIG_NE2K_PCI 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_TLAN is not set
+# CONFIG_VIA_RHINE is not set
+# CONFIG_VIA_VELOCITY is not set
+
+#
+# Ethernet (1000 Mbit)
+#
+# CONFIG_ACENIC is not set
+# CONFIG_DL2K is not set
+# CONFIG_E1000 is not set
+# CONFIG_NS83820 is not set
+# CONFIG_HAMACHI is not set
+# CONFIG_YELLOWFIN is not set
+# CONFIG_R8169 is not set
+# CONFIG_SK98LIN is not set
+# CONFIG_TIGON3 is not set
+
+#
+# Ethernet (10000 Mbit)
+#
+# CONFIG_IXGB is not set
+# CONFIG_S2IO is not set
+
+#
+# Token Ring devices
+#
+# CONFIG_TR is not set
+
+#
+# Wireless LAN (non-hamradio)
+#
+# CONFIG_NET_RADIO is not set
+
+#
+# Wan interfaces
+#
+CONFIG_WAN=y
+# CONFIG_LANMEDIA is not set
+# CONFIG_SYNCLINK_SYNCPPP is not set
+CONFIG_HDLC=y
+CONFIG_HDLC_RAW=y
+# CONFIG_HDLC_RAW_ETH is not set
+CONFIG_HDLC_CISCO=y
+CONFIG_HDLC_FR=y
+CONFIG_HDLC_PPP=y
+
+#
+# X.25/LAPB support is disabled
+#
+# CONFIG_PCI200SYN is not set
+# CONFIG_WANXL is not set
+# CONFIG_PC300 is not set
+# CONFIG_FARSYNC is not set
+CONFIG_DLCI=y
+CONFIG_DLCI_COUNT=24
+CONFIG_DLCI_MAX=8
+# CONFIG_FDDI is not set
+# CONFIG_HIPPI is not set
+# CONFIG_PPP is not set
+# CONFIG_SLIP is not set
+# CONFIG_SHAPER is not set
+# CONFIG_NETCONSOLE is not set
+
+#
+# SCSI device support
+#
+# CONFIG_SCSI is not set
+
+#
+# Fusion MPT device support
+#
+
+#
+# IEEE 1394 (FireWire) support
+#
+# CONFIG_IEEE1394 is not set
+
+#
+# I2O device support
+#
+# CONFIG_I2O is not set
+
+#
+# ISDN subsystem
+#
+# CONFIG_ISDN is not set
+
+#
+# Input device support
+#
+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_I8042 is not set
+
+#
+# Input Device Drivers
+#
+# CONFIG_INPUT_KEYBOARD is not set
+# CONFIG_INPUT_MOUSE 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 is not set
+# CONFIG_SERIAL_NONSTANDARD is not set
+
+#
+# Serial drivers
+#
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_NR_UARTS=2
+# CONFIG_SERIAL_8250_EXTENDED is not set
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+CONFIG_UNIX98_PTYS=y
+CONFIG_LEGACY_PTYS=y
+CONFIG_LEGACY_PTY_COUNT=256
+# CONFIG_QIC02_TAPE is not set
+
+#
+# IPMI
+#
+# CONFIG_IPMI_HANDLER is not set
+
+#
+# Watchdog Cards
+#
+CONFIG_WATCHDOG=y
+# CONFIG_WATCHDOG_NOWAYOUT is not set
+
+#
+# Watchdog Device Drivers
+#
+# CONFIG_SOFT_WATCHDOG is not set
+CONFIG_IXP2000_WATCHDOG=y
+
+#
+# PCI-based Watchdog Cards
+#
+# CONFIG_PCIPCWATCHDOG is not set
+# CONFIG_WDTPCI is not set
+# CONFIG_NVRAM is not set
+# CONFIG_RTC is not set
+# CONFIG_GEN_RTC is not set
+# CONFIG_DTLK is not set
+# CONFIG_R3964 is not set
+# CONFIG_APPLICOM is not set
+
+#
+# Ftape, the floppy tape device driver
+#
+# CONFIG_AGP is not set
+# CONFIG_DRM is not set
+# CONFIG_RAW_DRIVER is not set
+
+#
+# I2C support
+#
+CONFIG_I2C=y
+CONFIG_I2C_CHARDEV=y
+
+#
+# I2C Algorithms
+#
+CONFIG_I2C_ALGOBIT=y
+# CONFIG_I2C_ALGOPCF is not set
+
+#
+# I2C Hardware Bus support
+#
+# CONFIG_I2C_ALI1535 is not set
+# CONFIG_I2C_ALI1563 is not set
+# CONFIG_I2C_ALI15X3 is not set
+# CONFIG_I2C_AMD756 is not set
+# CONFIG_I2C_AMD8111 is not set
+# CONFIG_I2C_I801 is not set
+# CONFIG_I2C_I810 is not set
+# CONFIG_I2C_ISA is not set
+# CONFIG_I2C_IXP2000 is not set
+# CONFIG_I2C_NFORCE2 is not set
+# CONFIG_I2C_PARPORT_LIGHT is not set
+# CONFIG_I2C_PIIX4 is not set
+# CONFIG_I2C_PROSAVAGE is not set
+# CONFIG_I2C_SAVAGE4 is not set
+# CONFIG_SCx200_ACB is not set
+# CONFIG_I2C_SIS5595 is not set
+# CONFIG_I2C_SIS630 is not set
+# CONFIG_I2C_SIS96X is not set
+# CONFIG_I2C_VIA is not set
+# CONFIG_I2C_VIAPRO is not set
+# CONFIG_I2C_VOODOO3 is not set
+
+#
+# Hardware Sensors Chip support
+#
+CONFIG_I2C_SENSOR=y
+# CONFIG_SENSORS_ADM1021 is not set
+# CONFIG_SENSORS_ADM1025 is not set
+# CONFIG_SENSORS_ADM1031 is not set
+# CONFIG_SENSORS_ASB100 is not set
+# CONFIG_SENSORS_DS1621 is not set
+# CONFIG_SENSORS_FSCHER is not set
+# CONFIG_SENSORS_GL518SM is not set
+# CONFIG_SENSORS_IT87 is not set
+# CONFIG_SENSORS_LM75 is not set
+# CONFIG_SENSORS_LM77 is not set
+# CONFIG_SENSORS_LM78 is not set
+# CONFIG_SENSORS_LM80 is not set
+# CONFIG_SENSORS_LM83 is not set
+# CONFIG_SENSORS_LM85 is not set
+# CONFIG_SENSORS_LM90 is not set
+# CONFIG_SENSORS_MAX1619 is not set
+# CONFIG_SENSORS_VIA686A is not set
+# CONFIG_SENSORS_W83781D is not set
+# CONFIG_SENSORS_W83L785TS is not set
+# CONFIG_SENSORS_W83627HF is not set
+
+#
+# Other I2C Chip support
+#
+CONFIG_SENSORS_EEPROM=y
+# CONFIG_SENSORS_PCF8574 is not set
+# CONFIG_SENSORS_PCF8591 is not set
+# CONFIG_SENSORS_RTC8564 is not set
+# CONFIG_I2C_DEBUG_CORE is not set
+# CONFIG_I2C_DEBUG_ALGO is not set
+# CONFIG_I2C_DEBUG_BUS is not set
+# CONFIG_I2C_DEBUG_CHIP is not set
+
+#
+# Multimedia devices
+#
+# CONFIG_VIDEO_DEV is not set
+
+#
+# Digital Video Broadcasting Devices
+#
+# CONFIG_DVB is not set
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+CONFIG_EXT2_FS_XATTR=y
+CONFIG_EXT2_FS_POSIX_ACL=y
+# CONFIG_EXT2_FS_SECURITY is not set
+CONFIG_EXT3_FS=y
+CONFIG_EXT3_FS_XATTR=y
+CONFIG_EXT3_FS_POSIX_ACL=y
+# CONFIG_EXT3_FS_SECURITY is not set
+CONFIG_JBD=y
+# CONFIG_JBD_DEBUG is not set
+CONFIG_FS_MBCACHE=y
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+CONFIG_FS_POSIX_ACL=y
+# CONFIG_XFS_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_ROMFS_FS is not set
+# CONFIG_QUOTA is not set
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_AUTOFS4_FS is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+# CONFIG_ISO9660_FS is not set
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+# 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_SYSFS=y
+# CONFIG_DEVFS_FS 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_EFS_FS is not set
+# CONFIG_JFFS_FS is not set
+CONFIG_JFFS2_FS=y
+CONFIG_JFFS2_FS_DEBUG=0
+# CONFIG_JFFS2_FS_NAND is not set
+# CONFIG_JFFS2_COMPRESSION_OPTIONS is not set
+CONFIG_JFFS2_ZLIB=y
+CONFIG_JFFS2_RTIME=y
+# CONFIG_JFFS2_RUBIN is not set
+# CONFIG_CRAMFS is not set
+# CONFIG_VXFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+
+#
+# Network File Systems
+#
+CONFIG_NFS_FS=y
+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_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_AFS_FS is not set
+
+#
+# Partition Types
+#
+CONFIG_PARTITION_ADVANCED=y
+# CONFIG_ACORN_PARTITION is not set
+# CONFIG_OSF_PARTITION is not set
+# CONFIG_AMIGA_PARTITION is not set
+# CONFIG_ATARI_PARTITION is not set
+# CONFIG_MAC_PARTITION is not set
+CONFIG_MSDOS_PARTITION=y
+# CONFIG_BSD_DISKLABEL is not set
+# CONFIG_MINIX_SUBPARTITION is not set
+# CONFIG_SOLARIS_X86_PARTITION is not set
+# CONFIG_UNIXWARE_DISKLABEL is not set
+# CONFIG_LDM_PARTITION is not set
+# CONFIG_SGI_PARTITION is not set
+# CONFIG_ULTRIX_PARTITION is not set
+# CONFIG_SUN_PARTITION is not set
+# CONFIG_EFI_PARTITION is not set
+
+#
+# Native Language Support
+#
+# CONFIG_NLS is not set
+
+#
+# Profiling support
+#
+# CONFIG_PROFILING is not set
+
+#
+# Graphics support
+#
+# CONFIG_FB is not set
+
+#
+# Sound
+#
+# CONFIG_SOUND is not set
+
+#
+# Misc devices
+#
+
+#
+# USB support
+#
+# CONFIG_USB is not set
+
+#
+# USB Gadget Support
+#
+# CONFIG_USB_GADGET is not set
+
+#
+# Kernel hacking
+#
+CONFIG_FRAME_POINTER=y
+CONFIG_DEBUG_USER=y
+# CONFIG_DEBUG_INFO is not set
+CONFIG_DEBUG_KERNEL=y
+# CONFIG_DEBUG_SLAB is not set
+CONFIG_MAGIC_SYSRQ=y
+# CONFIG_DEBUG_SPINLOCK is not set
+# CONFIG_DEBUG_WAITQ is not set
+CONFIG_DEBUG_BUGVERBOSE=y
+CONFIG_DEBUG_ERRORS=y
+CONFIG_DEBUG_LL=y
+# CONFIG_DEBUG_ICEDCC is not set
+# CONFIG_DEBUG_BDI2000_XSCALE is not set
+
+#
+# Security options
+#
+# CONFIG_SECURITY is not set
+
+#
+# Cryptographic options
+#
+# CONFIG_CRYPTO is not set
+
+#
+# Library routines
+#
+# CONFIG_CRC_CCITT is not set
+CONFIG_CRC32=y
+# CONFIG_LIBCRC32C is not set
+CONFIG_ZLIB_INFLATE=y
+CONFIG_ZLIB_DEFLATE=y
diff -Nru a/arch/arm/configs/ixp4xx_defconfig b/arch/arm/configs/ixp4xx_defconfig
--- a/arch/arm/configs/ixp4xx_defconfig	2004-10-18 14:56:21 -07:00
+++ b/arch/arm/configs/ixp4xx_defconfig	2004-10-18 14:56:21 -07:00
@@ -308,7 +308,6 @@
 CONFIG_IP_ROUTE_FWMARK=y
 CONFIG_IP_ROUTE_NAT=y
 CONFIG_IP_ROUTE_MULTIPATH=y
-CONFIG_IP_ROUTE_TOS=y
 CONFIG_IP_ROUTE_VERBOSE=y
 CONFIG_IP_PNP=y
 CONFIG_IP_PNP_DHCP=y
diff -Nru a/arch/arm/configs/mx1ads_defconfig b/arch/arm/configs/mx1ads_defconfig
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/arch/arm/configs/mx1ads_defconfig	2004-10-18 14:57:24 -07:00
@@ -0,0 +1,652 @@
+#
+# Automatically generated make config: don't edit
+#
+CONFIG_ARM=y
+CONFIG_MMU=y
+CONFIG_UID16=y
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+
+#
+# Code maturity level options
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_CLEAN_COMPILE=y
+CONFIG_STANDALONE=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 is not set
+# CONFIG_AUDIT is not set
+CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_HOTPLUG is not set
+# CONFIG_IKCONFIG is not set
+CONFIG_EMBEDDED=y
+# CONFIG_KALLSYMS is not set
+CONFIG_FUTEX=y
+CONFIG_EPOLL=y
+# CONFIG_IOSCHED_NOOP is not set
+# CONFIG_IOSCHED_AS is not set
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
+
+#
+# Loadable module support
+#
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+# CONFIG_MODULE_FORCE_UNLOAD is not set
+CONFIG_OBSOLETE_MODPARM=y
+# CONFIG_MODVERSIONS is not set
+CONFIG_KMOD=y
+
+#
+# System Type
+#
+# CONFIG_ARCH_CLPS7500 is not set
+# CONFIG_ARCH_CLPS711X is not set
+# CONFIG_ARCH_CO285 is not set
+# CONFIG_ARCH_EBSA110 is not set
+# CONFIG_ARCH_CAMELOT is not set
+# CONFIG_ARCH_FOOTBRIDGE is not set
+# CONFIG_ARCH_INTEGRATOR is not set
+# CONFIG_ARCH_IOP3XX is not set
+# CONFIG_ARCH_IXP4XX is not set
+# CONFIG_ARCH_L7200 is not set
+# CONFIG_ARCH_PXA is not set
+# CONFIG_ARCH_RPC is not set
+# CONFIG_ARCH_SA1100 is not set
+# CONFIG_ARCH_S3C2410 is not set
+# CONFIG_ARCH_SHARK is not set
+# CONFIG_ARCH_LH7A40X is not set
+# CONFIG_ARCH_OMAP is not set
+# CONFIG_ARCH_VERSATILE_PB is not set
+CONFIG_ARCH_IMX=y
+
+#
+# IMX Implementations
+#
+CONFIG_ARCH_MX1ADS=y
+
+#
+# Processor Type
+#
+CONFIG_CPU_32=y
+CONFIG_CPU_ARM920T=y
+CONFIG_CPU_32v4=y
+CONFIG_CPU_ABRT_EV4T=y
+CONFIG_CPU_CACHE_V4WT=y
+CONFIG_CPU_COPY_V4WB=y
+CONFIG_CPU_TLB_V4WBI=y
+
+#
+# Processor Features
+#
+# CONFIG_ARM_THUMB is not set
+# CONFIG_CPU_ICACHE_DISABLE is not set
+# CONFIG_CPU_DCACHE_DISABLE is not set
+# CONFIG_CPU_DCACHE_WRITETHROUGH is not set
+
+#
+# General setup
+#
+CONFIG_ISA=y
+# CONFIG_ZBOOT_ROM is not set
+CONFIG_ZBOOT_ROM_TEXT=0x0
+CONFIG_ZBOOT_ROM_BSS=0x0
+# CONFIG_CPU_FREQ is not set
+
+#
+# At least one math emulation must be selected
+#
+CONFIG_FPE_NWFPE=y
+CONFIG_FPE_NWFPE_XP=y
+CONFIG_FPE_FASTFPE=y
+# CONFIG_VFP is not set
+CONFIG_BINFMT_ELF=y
+# CONFIG_BINFMT_AOUT is not set
+# CONFIG_BINFMT_MISC is not set
+
+#
+# Generic Driver Options
+#
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+# CONFIG_DEBUG_DRIVER is not set
+# CONFIG_PM is not set
+CONFIG_PREEMPT=y
+# CONFIG_ARTHUR is not set
+CONFIG_CMDLINE="console=ttySMX0,57600n8 ip=bootp root=/dev/nfs"
+# CONFIG_LEDS is not set
+CONFIG_ALIGNMENT_TRAP=y
+
+#
+# Parallel port support
+#
+# CONFIG_PARPORT is not set
+
+#
+# Memory Technology Devices (MTD)
+#
+CONFIG_MTD=y
+# CONFIG_MTD_DEBUG is not set
+CONFIG_MTD_PARTITIONS=y
+# CONFIG_MTD_CONCAT is not set
+# CONFIG_MTD_REDBOOT_PARTS is not set
+# CONFIG_MTD_CMDLINE_PARTS is not set
+# CONFIG_MTD_AFS_PARTS is not set
+
+#
+# User Modules And Translation Layers
+#
+CONFIG_MTD_CHAR=y
+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_RAM is not set
+CONFIG_MTD_ROM=y
+# 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
+CONFIG_MTD_MX1ADS=y
+
+#
+# Self-contained MTD device drivers
+#
+# CONFIG_MTD_SLRAM is not set
+# CONFIG_MTD_MTDRAM is not set
+# CONFIG_MTD_BLKMTD is not set
+
+#
+# Disk-On-Chip Device Drivers
+#
+# CONFIG_MTD_DOC2000 is not set
+# CONFIG_MTD_DOC2001 is not set
+# CONFIG_MTD_DOC2001PLUS is not set
+
+#
+# NAND Flash Device Drivers
+#
+# CONFIG_MTD_NAND is not set
+
+#
+# Plug and Play support
+#
+# CONFIG_PNP is not set
+
+#
+# Block devices
+#
+# CONFIG_BLK_DEV_FD is not set
+# CONFIG_BLK_DEV_XD is not set
+CONFIG_BLK_DEV_LOOP=y
+# CONFIG_BLK_DEV_CRYPTOLOOP is not set
+# CONFIG_BLK_DEV_NBD is not set
+# CONFIG_BLK_DEV_RAM is not set
+
+#
+# Multi-device support (RAID and LVM)
+#
+# CONFIG_MD is not set
+
+#
+# Networking support
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+CONFIG_PACKET=m
+CONFIG_PACKET_MMAP=y
+# CONFIG_NETLINK_DEV is not set
+CONFIG_UNIX=y
+# CONFIG_NET_KEY is not set
+CONFIG_INET=y
+# CONFIG_IP_MULTICAST is not set
+# CONFIG_IP_ADVANCED_ROUTER is not set
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_DHCP=y
+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_ARPD 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
+# CONFIG_IPV6 is not set
+# CONFIG_NETFILTER is not set
+
+#
+# SCTP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_SCTP is not set
+# CONFIG_ATM is not set
+# CONFIG_BRIDGE is not set
+# CONFIG_VLAN_8021Q is not set
+# CONFIG_DECNET 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
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+# CONFIG_NET_FASTROUTE is not set
+# CONFIG_NET_HW_FLOWCONTROL is not set
+
+#
+# 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
+
+#
+# Ethernet (10 or 100Mbit)
+#
+CONFIG_NET_ETHERNET=y
+CONFIG_MII=y
+# CONFIG_SMC91X is not set
+# CONFIG_NET_VENDOR_3COM is not set
+# CONFIG_LANCE is not set
+# CONFIG_NET_VENDOR_SMC is not set
+# CONFIG_NET_VENDOR_RACAL is not set
+# CONFIG_AT1700 is not set
+# CONFIG_DEPCA is not set
+# CONFIG_HP100 is not set
+# CONFIG_NET_ISA is not set
+# CONFIG_NET_PCI is not set
+# CONFIG_NET_POCKET is not set
+
+#
+# Ethernet (1000 Mbit)
+#
+
+#
+# Ethernet (10000 Mbit)
+#
+
+#
+# Token Ring devices
+#
+# CONFIG_TR 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=y
+CONFIG_PPP_ASYNC=y
+# CONFIG_PPP_SYNC_TTY is not set
+CONFIG_PPP_DEFLATE=y
+CONFIG_PPP_BSDCOMP=y
+# CONFIG_PPPOE is not set
+# CONFIG_SLIP is not set
+# CONFIG_SHAPER is not set
+# CONFIG_NETCONSOLE is not set
+
+#
+# SCSI device support
+#
+# CONFIG_SCSI is not set
+
+#
+# Fusion MPT device support
+#
+
+#
+# IEEE 1394 (FireWire) support
+#
+# CONFIG_IEEE1394 is not set
+
+#
+# I2O device support
+#
+
+#
+# ISDN subsystem
+#
+# CONFIG_ISDN is not set
+
+#
+# Input device support
+#
+# CONFIG_INPUT is not set
+
+#
+# Userland interfaces
+#
+
+#
+# Input I/O drivers
+#
+# CONFIG_GAMEPORT is not set
+CONFIG_SOUND_GAMEPORT=y
+# CONFIG_SERIO is not set
+# CONFIG_SERIO_I8042 is not set
+
+#
+# Input Device Drivers
+#
+
+#
+# Character devices
+#
+# CONFIG_VT is not set
+# CONFIG_SERIAL_NONSTANDARD is not set
+
+#
+# Serial drivers
+#
+# CONFIG_SERIAL_8250 is not set
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_IMX=y
+CONFIG_SERIAL_IMX_CONSOLE=y
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+CONFIG_UNIX98_PTYS=y
+# CONFIG_LEGACY_PTYS is not set
+# CONFIG_QIC02_TAPE is not set
+
+#
+# IPMI
+#
+# CONFIG_IPMI_HANDLER is not set
+
+#
+# Watchdog Cards
+#
+# CONFIG_WATCHDOG is not set
+# CONFIG_NVRAM is not set
+CONFIG_RTC=m
+# CONFIG_GEN_RTC is not set
+# CONFIG_DTLK is not set
+# CONFIG_R3964 is not set
+# CONFIG_APPLICOM is not set
+
+#
+# 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
+
+#
+# I2C support
+#
+# CONFIG_I2C is not set
+
+#
+# Multimedia devices
+#
+# CONFIG_VIDEO_DEV is not set
+
+#
+# Digital Video Broadcasting Devices
+#
+# CONFIG_DVB is not set
+
+#
+# File systems
+#
+# CONFIG_EXT2_FS is not set
+# CONFIG_EXT3_FS is not set
+# CONFIG_JBD is not set
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+# CONFIG_XFS_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_ROMFS_FS is not set
+# CONFIG_QUOTA is not set
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_AUTOFS4_FS is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+# CONFIG_ISO9660_FS 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_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_EFS_FS is not set
+# CONFIG_JFFS_FS is not set
+CONFIG_JFFS2_FS=y
+CONFIG_JFFS2_FS_DEBUG=0
+# CONFIG_JFFS2_FS_NAND is not set
+CONFIG_CRAMFS=y
+# CONFIG_VXFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+
+#
+# Network File Systems
+#
+CONFIG_NFS_FS=y
+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_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_AFS_FS is not set
+
+#
+# Partition Types
+#
+# CONFIG_PARTITION_ADVANCED is not set
+
+#
+# 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
+# CONFIG_NLS_CODEPAGE_775 is not set
+# CONFIG_NLS_CODEPAGE_850 is not set
+# CONFIG_NLS_CODEPAGE_852 is not set
+# CONFIG_NLS_CODEPAGE_855 is not set
+# CONFIG_NLS_CODEPAGE_857 is not set
+# CONFIG_NLS_CODEPAGE_860 is not set
+# CONFIG_NLS_CODEPAGE_861 is not set
+# CONFIG_NLS_CODEPAGE_862 is not set
+# CONFIG_NLS_CODEPAGE_863 is not set
+# CONFIG_NLS_CODEPAGE_864 is not set
+# CONFIG_NLS_CODEPAGE_865 is not set
+# CONFIG_NLS_CODEPAGE_866 is not set
+# CONFIG_NLS_CODEPAGE_869 is not set
+# CONFIG_NLS_CODEPAGE_936 is not set
+# CONFIG_NLS_CODEPAGE_950 is not set
+# CONFIG_NLS_CODEPAGE_932 is not set
+# CONFIG_NLS_CODEPAGE_949 is not set
+# CONFIG_NLS_CODEPAGE_874 is not set
+# 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
+# CONFIG_NLS_ISO8859_4 is not set
+# CONFIG_NLS_ISO8859_5 is not set
+# CONFIG_NLS_ISO8859_6 is not set
+# CONFIG_NLS_ISO8859_7 is not set
+# CONFIG_NLS_ISO8859_9 is not set
+# CONFIG_NLS_ISO8859_13 is not set
+# CONFIG_NLS_ISO8859_14 is not set
+# CONFIG_NLS_ISO8859_15 is not set
+# CONFIG_NLS_KOI8_R is not set
+# CONFIG_NLS_KOI8_U is not set
+# CONFIG_NLS_UTF8 is not set
+
+#
+# Profiling support
+#
+# CONFIG_PROFILING is not set
+
+#
+# Graphics support
+#
+# CONFIG_FB is not set
+
+#
+# Sound
+#
+# CONFIG_SOUND is not set
+
+#
+# Misc devices
+#
+
+#
+# USB support
+#
+
+#
+# USB Gadget Support
+#
+# CONFIG_USB_GADGET is not set
+
+#
+# Kernel hacking
+#
+CONFIG_FRAME_POINTER=y
+CONFIG_DEBUG_USER=y
+CONFIG_DEBUG_INFO=y
+CONFIG_DEBUG_KERNEL=y
+# CONFIG_DEBUG_SLAB is not set
+CONFIG_MAGIC_SYSRQ=y
+# CONFIG_DEBUG_SPINLOCK is not set
+# CONFIG_DEBUG_WAITQ is not set
+CONFIG_DEBUG_BUGVERBOSE=y
+CONFIG_DEBUG_ERRORS=y
+# CONFIG_DEBUG_LL is not set
+
+#
+# Security options
+#
+# CONFIG_SECURITY is not set
+
+#
+# Cryptographic options
+#
+CONFIG_CRYPTO=y
+# CONFIG_CRYPTO_HMAC is not set
+# CONFIG_CRYPTO_NULL is not set
+# CONFIG_CRYPTO_MD4 is not set
+# CONFIG_CRYPTO_MD5 is not set
+# CONFIG_CRYPTO_SHA1 is not set
+# CONFIG_CRYPTO_SHA256 is not set
+# CONFIG_CRYPTO_SHA512 is not set
+# CONFIG_CRYPTO_DES is not set
+# CONFIG_CRYPTO_BLOWFISH is not set
+# CONFIG_CRYPTO_TWOFISH is not set
+# CONFIG_CRYPTO_SERPENT is not set
+# CONFIG_CRYPTO_AES is not set
+# CONFIG_CRYPTO_CAST5 is not set
+# CONFIG_CRYPTO_CAST6 is not set
+# CONFIG_CRYPTO_ARC4 is not set
+# CONFIG_CRYPTO_DEFLATE is not set
+# CONFIG_CRYPTO_MICHAEL_MIC is not set
+# CONFIG_CRYPTO_CRC32C is not set
+# CONFIG_CRYPTO_TEST is not set
+
+#
+# Library routines
+#
+CONFIG_CRC16=y
+CONFIG_CRC32=y
+# CONFIG_LIBCRC32C is not set
+CONFIG_ZLIB_INFLATE=y
+CONFIG_ZLIB_DEFLATE=y
diff -Nru a/arch/arm/configs/s3c2410_defconfig b/arch/arm/configs/s3c2410_defconfig
--- a/arch/arm/configs/s3c2410_defconfig	2004-10-18 14:56:28 -07:00
+++ b/arch/arm/configs/s3c2410_defconfig	2004-10-18 14:56:28 -07:00
@@ -78,6 +78,12 @@
 CONFIG_MACH_VR1000=y
 
 #
+# S3C2410 Setup
+#
+CONFIG_S3C2410_DMA=y
+# CONFIG_S3C2410_DMA_DEBUG is not set
+
+#
 # Processor Type
 #
 CONFIG_CPU_32=y
@@ -601,6 +607,8 @@
 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
 
 #
diff -Nru a/arch/arm/kernel/Makefile b/arch/arm/kernel/Makefile
--- a/arch/arm/kernel/Makefile	2004-10-18 14:57:03 -07:00
+++ b/arch/arm/kernel/Makefile	2004-10-18 14:57:03 -07:00
@@ -19,6 +19,9 @@
 obj-$(CONFIG_ISA_DMA)		+= dma-isa.o
 obj-$(CONFIG_PCI)		+= bios32.o
 
+obj-$(CONFIG_IWMMXT)		+= iwmmxt.o
+AFLAGS_iwmmxt.o			:= -Wa,-mcpu=iwmmxt
+
 ifneq ($(CONFIG_ARCH_EBSA110),y)
   obj-y		+= io.o
 endif
@@ -26,7 +29,7 @@
 head-y			:= head.o
 obj-$(CONFIG_DEBUG_LL)	+= debug.o
 
-extra-y := $(head-y) init_task.o vmlinux.lds.s
+extra-y := $(head-y) init_task.o vmlinux.lds
 
 # Spell out some dependencies that aren't automatically figured out
 $(obj)/entry-armv.o: 	$(obj)/entry-header.S include/asm-arm/constants.h
diff -Nru a/arch/arm/kernel/apm.c b/arch/arm/kernel/apm.c
--- a/arch/arm/kernel/apm.c	2004-10-18 14:57:04 -07:00
+++ b/arch/arm/kernel/apm.c	2004-10-18 14:57:04 -07:00
@@ -46,7 +46,13 @@
 /*
  * Maximum number of events stored
  */
-#define APM_MAX_EVENTS		20
+#define APM_MAX_EVENTS		16
+
+struct apm_queue {
+	unsigned int		event_head;
+	unsigned int		event_tail;
+	apm_event_t		events[APM_MAX_EVENTS];
+};
 
 /*
  * The per-file APM data
@@ -54,27 +60,25 @@
 struct apm_user {
 	struct list_head	list;
 
-	int			suser: 1;
-	int			writer: 1;
-	int			reader: 1;
-	int			suspend_wait: 1;
-	int			suspend_result;
+	unsigned int		suser: 1;
+	unsigned int		writer: 1;
+	unsigned int		reader: 1;
 
-	int			suspends_pending;
-	int			standbys_pending;
-	unsigned int		suspends_read;
-	unsigned int		standbys_read;
+	int			suspend_result;
+	unsigned int		suspend_state;
+#define SUSPEND_NONE	0		/* no suspend pending */
+#define SUSPEND_PENDING	1		/* suspend pending read */
+#define SUSPEND_READ	2		/* suspend read, pending ack */
+#define SUSPEND_ACKED	3		/* suspend acked */
+#define SUSPEND_DONE	4		/* suspend completed */
 
-	int			event_head;
-	int			event_tail;
-	apm_event_t		events[APM_MAX_EVENTS];
+	struct apm_queue	queue;
 };
 
 /*
  * Local variables
  */
 static int suspends_pending;
-static int standbys_pending;
 static int apm_disabled;
 
 static DECLARE_WAIT_QUEUE_HEAD(apm_waitqueue);
@@ -83,14 +87,19 @@
 /*
  * This is a list of everyone who has opened /dev/apm_bios
  */
-static spinlock_t user_list_lock = SPIN_LOCK_UNLOCKED;
+static DECLARE_RWSEM(user_list_lock);
 static LIST_HEAD(apm_user_list);
 
 /*
- * The kapmd info.
+ * kapmd info.  kapmd provides us a process context to handle
+ * "APM" events within - specifically necessary if we're going
+ * to be suspending the system.
  */
-static struct task_struct *kapmd;
+static DECLARE_WAIT_QUEUE_HEAD(kapmd_wait);
 static DECLARE_COMPLETION(kapmd_exit);
+static spinlock_t kapmd_queue_lock = SPIN_LOCK_UNLOCKED;
+static struct apm_queue kapmd_queue;
+
 
 static const char driver_version[] = "1.13";	/* no spaces */
 
@@ -102,19 +111,6 @@
  */
 static void __apm_get_power_status(struct apm_power_info *info)
 {
-#if 0 && defined(CONFIG_SA1100_H3600) && defined(CONFIG_TOUCHSCREEN_H3600)
-	extern int h3600_apm_get_power_status(u_char *, u_char *, u_char *,
-					      u_char *, u_short *);
-
-	if (machine_is_h3600()) {
-		int dx;
-		h3600_apm_get_power_status(&info->ac_line_status,
-				&info->battery_status, &info->battery_flag,
-				&info->battery_life, &dx);
-		info->time = dx & 0x7fff;
-		info->units = dx & 0x8000 ? 0 : 1;
-	}
-#endif
 }
 
 /*
@@ -123,65 +119,71 @@
 void (*apm_get_power_status)(struct apm_power_info *) = __apm_get_power_status;
 EXPORT_SYMBOL(apm_get_power_status);
 
-static int queue_empty(struct apm_user *as)
+
+/*
+ * APM event queue management.
+ */
+static inline int queue_empty(struct apm_queue *q)
 {
-	return as->event_head == as->event_tail;
+	return q->event_head == q->event_tail;
 }
 
-static apm_event_t get_queued_event(struct apm_user *as)
+static inline apm_event_t queue_get_event(struct apm_queue *q)
 {
-	as->event_tail = (as->event_tail + 1) % APM_MAX_EVENTS;
-	return as->events[as->event_tail];
+	q->event_tail = (q->event_tail + 1) % APM_MAX_EVENTS;
+	return q->events[q->event_tail];
 }
 
-static void queue_event_one_user(struct apm_user *as, apm_event_t event)
+static void queue_add_event(struct apm_queue *q, apm_event_t event)
 {
-	as->event_head = (as->event_head + 1) % APM_MAX_EVENTS;
-	if (as->event_head == as->event_tail) {
+	q->event_head = (q->event_head + 1) % APM_MAX_EVENTS;
+	if (q->event_head == q->event_tail) {
 		static int notified;
 
 		if (notified++ == 0)
 		    printk(KERN_ERR "apm: an event queue overflowed\n");
-		as->event_tail = (as->event_tail + 1) % APM_MAX_EVENTS;
+		q->event_tail = (q->event_tail + 1) % APM_MAX_EVENTS;
 	}
-	as->events[as->event_head] = event;
-
-	if (!as->suser || !as->writer)
-		return;
+	q->events[q->event_head] = event;
+}
 
-	switch (event) {
-	case APM_SYS_SUSPEND:
-	case APM_USER_SUSPEND:
-		as->suspends_pending++;
-		suspends_pending++;
-		break;
+static void queue_event_one_user(struct apm_user *as, apm_event_t event)
+{
+	if (as->suser && as->writer) {
+		switch (event) {
+		case APM_SYS_SUSPEND:
+		case APM_USER_SUSPEND:
+			/*
+			 * If this user already has a suspend pending,
+			 * don't queue another one.
+			 */
+			if (as->suspend_state != SUSPEND_NONE)
+				return;
 
-	case APM_SYS_STANDBY:
-	case APM_USER_STANDBY:
-		as->standbys_pending++;
-		standbys_pending++;
-		break;
+			as->suspend_state = SUSPEND_PENDING;
+			suspends_pending++;
+			break;
+		}
 	}
+	queue_add_event(&as->queue, event);
 }
 
 static void queue_event(apm_event_t event, struct apm_user *sender)
 {
-	struct list_head *l;
-
-	spin_lock(&user_list_lock);
-	list_for_each(l, &apm_user_list) {
-		struct apm_user *as = list_entry(l, struct apm_user, list);
+	struct apm_user *as;
 
+	down_read(&user_list_lock);
+	list_for_each_entry(as, &apm_user_list, list) {
 		if (as != sender && as->reader)
 			queue_event_one_user(as, event);
 	}
-	spin_unlock(&user_list_lock);
+	up_read(&user_list_lock);
 	wake_up_interruptible(&apm_waitqueue);
 }
 
-static int apm_suspend(void)
+static void apm_suspend(void)
 {
-	struct list_head *l;
+	struct apm_user *as;
 	int err = pm_suspend(PM_SUSPEND_MEM);
 
 	/*
@@ -193,52 +195,39 @@
 	/*
 	 * Finally, wake up anyone who is sleeping on the suspend.
 	 */
-	spin_lock(&user_list_lock);
-	list_for_each(l, &apm_user_list) {
-		struct apm_user *as = list_entry(l, struct apm_user, list);
-
+	down_read(&user_list_lock);
+	list_for_each_entry(as, &apm_user_list, list) {
 		as->suspend_result = err;
-		as->suspend_wait = 0;
+		as->suspend_state = SUSPEND_DONE;
 	}
-	spin_unlock(&user_list_lock);
+	up_read(&user_list_lock);
 
-	wake_up_interruptible(&apm_suspend_waitqueue);
-	return err;
+	wake_up(&apm_suspend_waitqueue);
 }
 
 static ssize_t apm_read(struct file *fp, char __user *buf, size_t count, loff_t *ppos)
 {
 	struct apm_user *as = fp->private_data;
 	apm_event_t event;
-	int i = count, ret = 0, nonblock = fp->f_flags & O_NONBLOCK;
+	int i = count, ret = 0;
 
 	if (count < sizeof(apm_event_t))
 		return -EINVAL;
 
-	if (queue_empty(as) && nonblock)
+	if (queue_empty(&as->queue) && fp->f_flags & O_NONBLOCK)
 		return -EAGAIN;
 
-	wait_event_interruptible(apm_waitqueue, !queue_empty(as));
+	wait_event_interruptible(apm_waitqueue, !queue_empty(&as->queue));
 
-	while ((i >= sizeof(event)) && !queue_empty(as)) {
-		event = get_queued_event(as);
-		printk("  apm_read: event=%d\n", event);
+	while ((i >= sizeof(event)) && !queue_empty(&as->queue)) {
+		event = queue_get_event(&as->queue);
 
 		ret = -EFAULT;
 		if (copy_to_user(buf, &event, sizeof(event)))
 			break;
 
-		switch (event) {
-		case APM_SYS_SUSPEND:
-		case APM_USER_SUSPEND:
-			as->suspends_read++;
-			break;
-
-		case APM_SYS_STANDBY:
-		case APM_USER_STANDBY:
-			as->standbys_read++;
-			break;
-		}
+		if (event == APM_SYS_SUSPEND || event == APM_USER_SUSPEND)
+			as->suspend_state = SUSPEND_READ;
 
 		buf += sizeof(event);
 		i -= sizeof(event);
@@ -252,10 +241,10 @@
 
 static unsigned int apm_poll(struct file *fp, poll_table * wait)
 {
-	struct apm_user * as = fp->private_data;
+	struct apm_user *as = fp->private_data;
 
 	poll_wait(fp, &apm_waitqueue, wait);
-	return queue_empty(as) ? 0 : POLLIN | POLLRDNORM;
+	return queue_empty(&as->queue) ? 0 : POLLIN | POLLRDNORM;
 }
 
 /*
@@ -272,43 +261,65 @@
 apm_ioctl(struct inode * inode, struct file *filp, u_int cmd, u_long arg)
 {
 	struct apm_user *as = filp->private_data;
+	unsigned long flags;
 	int err = -EINVAL;
 
 	if (!as->suser || !as->writer)
 		return -EPERM;
 
 	switch (cmd) {
-	case APM_IOC_STANDBY:
-		break;
-
 	case APM_IOC_SUSPEND:
-		/*
-		 * If we read a suspend command from /dev/apm_bios,
-		 * then the corresponding APM_IOC_SUSPEND ioctl is
-		 * interpreted as an acknowledge.
-		 */
-		if (as->suspends_read > 0) {
-			as->suspends_read--;
-			as->suspends_pending--;
+		as->suspend_result = -EINTR;
+
+		if (as->suspend_state == SUSPEND_READ) {
+			/*
+			 * If we read a suspend command from /dev/apm_bios,
+			 * then the corresponding APM_IOC_SUSPEND ioctl is
+			 * interpreted as an acknowledge.
+			 */
+			as->suspend_state = SUSPEND_ACKED;
 			suspends_pending--;
 		} else {
+			/*
+			 * Otherwise it is a request to suspend the system.
+			 * Queue an event for all readers, and expect an
+			 * acknowledge from all writers who haven't already
+			 * acknowledged.
+			 */
 			queue_event(APM_USER_SUSPEND, as);
 		}
 
 		/*
-		 * If there are outstanding suspend requests for other
-		 * people on /dev/apm_bios, we must sleep for them.
-		 * Last one to bed turns the lights out.
+		 * If there are no further acknowledges required, suspend
+		 * the system.
 		 */
-		if (suspends_pending > 0) {
-			as->suspend_wait = 1;
-			err = wait_event_interruptible(apm_suspend_waitqueue,
-						 as->suspend_wait == 0);
-			if (err == 0)
-				err = as->suspend_result;
-		} else {			
-			err = apm_suspend();
-		}
+		if (suspends_pending == 0)
+			apm_suspend();
+
+		/*
+		 * Wait for the suspend/resume to complete.  If there are
+		 * pending acknowledges, we wait here for them.
+		 *
+		 * Note that we need to ensure that the PM subsystem does
+		 * not kick us out of the wait when it suspends the threads.
+		 */
+		flags = current->flags;
+		current->flags |= PF_NOFREEZE;
+
+		/*
+		 * Note: do not allow a thread which is acking the suspend
+		 * to escape until the resume is complete.
+		 */
+		if (as->suspend_state == SUSPEND_ACKED)
+			wait_event(apm_suspend_waitqueue,
+					 as->suspend_state == SUSPEND_DONE);
+		else
+			wait_event_interruptible(apm_suspend_waitqueue,
+					 as->suspend_state == SUSPEND_DONE);
+
+		current->flags = flags;
+		err = as->suspend_result;
+		as->suspend_state = SUSPEND_NONE;
 		break;
 	}
 
@@ -320,24 +331,19 @@
 	struct apm_user *as = filp->private_data;
 	filp->private_data = NULL;
 
-	spin_lock(&user_list_lock);
+	down_write(&user_list_lock);
 	list_del(&as->list);
-	spin_unlock(&user_list_lock);
+	up_write(&user_list_lock);
 
 	/*
 	 * We are now unhooked from the chain.  As far as new
 	 * events are concerned, we no longer exist.  However, we
-	 * need to balance standbys_pending and suspends_pending,
-	 * which means the possibility of sleeping.
+	 * need to balance suspends_pending, which means the
+	 * possibility of sleeping.
 	 */
-	if (as->standbys_pending > 0) {
-		standbys_pending -= as->standbys_pending;
-//		if (standbys_pending <= 0)
-//			standby();
-	}
-	if (as->suspends_pending > 0) {
-		suspends_pending -= as->suspends_pending;
-		if (suspends_pending <= 0)
+	if (as->suspend_state != SUSPEND_NONE) {
+		suspends_pending -= 1;
+		if (suspends_pending == 0)
 			apm_suspend();
 	}
 
@@ -364,9 +370,9 @@
 		as->writer = (filp->f_mode & FMODE_WRITE) == FMODE_WRITE;
 		as->reader = (filp->f_mode & FMODE_READ) == FMODE_READ;
 
-		spin_lock(&user_list_lock);
+		down_write(&user_list_lock);
 		list_add(&as->list, &apm_user_list);
-		spin_unlock(&user_list_lock);
+		up_write(&user_list_lock);
 
 		filp->private_data = as;
 	}
@@ -438,7 +444,7 @@
 	info.ac_line_status = 0xff;
 	info.battery_status = 0xff;
 	info.battery_flag   = 0xff;
-	info.battery_life   = 255;
+	info.battery_life   = -1;
 	info.time	    = -1;
 	info.units	    = -1;
 
@@ -461,34 +467,53 @@
 }
 #endif
 
-#if 0
-static int kapmd(void *startup)
+static int kapmd(void *arg)
 {
-	struct task_struct *tsk = current;
+	daemonize("kapmd");
+	current->flags |= PF_NOFREEZE;
 
-	daemonize();
-	strcpy(tsk->comm, "kapmd");
-	kapmd = tsk;
+	do {
+		apm_event_t event;
 
-	spin_lock_irq(&tsk->sigmask_lock);
-	siginitsetinv(&tsk->blocked, sigmask(SIGQUIT));
-	recalc_sigpending(tsk);
-	spin_unlock_irq(&tsk->sigmask_lock);
+		wait_event_interruptible(kapmd_wait,
+				!queue_empty(&kapmd_queue) || !pm_active);
 
-	complete((struct completion *)startup);
+		if (!pm_active)
+			break;
 
-	do {
-		set_task_state(tsk, TASK_INTERRUPTIBLE);
-		schedule();
-	} while (!signal_pending(tsk));
+		spin_lock_irq(&kapmd_queue_lock);
+		event = 0;
+		if (!queue_empty(&kapmd_queue))
+			event = queue_get_event(&kapmd_queue);
+		spin_unlock_irq(&kapmd_queue_lock);
+
+		switch (event) {
+		case 0:
+			break;
+
+		case APM_LOW_BATTERY:
+		case APM_POWER_STATUS_CHANGE:
+			queue_event(event, NULL);
+			break;
+
+		case APM_USER_SUSPEND:
+		case APM_SYS_SUSPEND:
+			queue_event(event, NULL);
+			if (suspends_pending == 0)
+				apm_suspend();
+			break;
+
+		case APM_CRITICAL_SUSPEND:
+			apm_suspend();
+			break;
+		}
+	} while (1);
 
 	complete_and_exit(&kapmd_exit, 0);
 }
-#endif
 
 static int __init apm_init(void)
 {
-//	struct completion startup = COMPLETION_INITIALIZER(startup);
 	int ret;
 
 	if (apm_disabled) {
@@ -501,22 +526,24 @@
 		return -EINVAL;
 	}
 
-//	ret = kernel_thread(kapmd, &startup, CLONE_FS | CLONE_FILES);
-//	if (ret)
-//		return ret;
-//	wait_for_completion(&startup);
-
 	pm_active = 1;
 
+	ret = kernel_thread(kapmd, NULL, CLONE_KERNEL);
+	if (ret < 0) {
+		pm_active = 0;
+		return ret;
+	}
+
 #ifdef CONFIG_PROC_FS
 	create_proc_info_entry("apm", 0, NULL, apm_get_info);
 #endif
 
 	ret = misc_register(&apm_device);
 	if (ret != 0) {
-		pm_active = 0;
 		remove_proc_entry("apm", NULL);
-		send_sig(SIGQUIT, kapmd, 1);
+
+		pm_active = 0;
+		wake_up(&kapmd_wait);
 		wait_for_completion(&kapmd_exit);
 	}
 
@@ -527,9 +554,10 @@
 {
 	misc_deregister(&apm_device);
 	remove_proc_entry("apm", NULL);
+
 	pm_active = 0;
-//	send_sig(SIGQUIT, kapmd, 1);
-//	wait_for_completion(&kapmd_exit);
+	wake_up(&kapmd_wait);
+	wait_for_completion(&kapmd_exit);
 }
 
 module_init(apm_init);
@@ -556,3 +584,27 @@
 
 __setup("apm=", apm_setup);
 #endif
+
+/**
+ * apm_queue_event - queue an APM event for kapmd
+ * @event: APM event
+ *
+ * Queue an APM event for kapmd to process and ultimately take the
+ * appropriate action.  Only a subset of events are handled:
+ *   %APM_LOW_BATTERY
+ *   %APM_POWER_STATUS_CHANGE
+ *   %APM_USER_SUSPEND
+ *   %APM_SYS_SUSPEND
+ *   %APM_CRITICAL_SUSPEND
+ */
+void apm_queue_event(apm_event_t event)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&kapmd_queue_lock, flags);
+	queue_add_event(&kapmd_queue, event);
+	spin_unlock_irqrestore(&kapmd_queue_lock, flags);
+
+	wake_up_interruptible(&kapmd_wait);
+}
+EXPORT_SYMBOL(apm_queue_event);
diff -Nru a/arch/arm/kernel/armksyms.c b/arch/arm/kernel/armksyms.c
--- a/arch/arm/kernel/armksyms.c	2004-10-18 14:56:28 -07:00
+++ b/arch/arm/kernel/armksyms.c	2004-10-18 14:56:28 -07:00
@@ -57,7 +57,7 @@
 EXPORT_SYMBOL_ALIAS(fp_printk,printk);
 EXPORT_SYMBOL_ALIAS(fp_send_sig,send_sig);
 
-EXPORT_SYMBOL_NOVERS(__backtrace);
+EXPORT_SYMBOL(__backtrace);
 
 	/* platform dependent support */
 EXPORT_SYMBOL(udelay);
@@ -69,43 +69,44 @@
 
 	/* io */
 #ifndef __raw_readsb
-EXPORT_SYMBOL_NOVERS(__raw_readsb);
+EXPORT_SYMBOL(__raw_readsb);
 #endif
 #ifndef __raw_readsw
-EXPORT_SYMBOL_NOVERS(__raw_readsw);
+EXPORT_SYMBOL(__raw_readsw);
 #endif
 #ifndef __raw_readsl
-EXPORT_SYMBOL_NOVERS(__raw_readsl);
+EXPORT_SYMBOL(__raw_readsl);
 #endif
 #ifndef __raw_writesb
-EXPORT_SYMBOL_NOVERS(__raw_writesb);
+EXPORT_SYMBOL(__raw_writesb);
 #endif
 #ifndef __raw_writesw
-EXPORT_SYMBOL_NOVERS(__raw_writesw);
+EXPORT_SYMBOL(__raw_writesw);
 #endif
 #ifndef __raw_writesl
-EXPORT_SYMBOL_NOVERS(__raw_writesl);
+EXPORT_SYMBOL(__raw_writesl);
 #endif
 
 	/* string / mem functions */
-EXPORT_SYMBOL_NOVERS(strcpy);
-EXPORT_SYMBOL_NOVERS(strncpy);
-EXPORT_SYMBOL_NOVERS(strcat);
-EXPORT_SYMBOL_NOVERS(strncat);
-EXPORT_SYMBOL_NOVERS(strcmp);
-EXPORT_SYMBOL_NOVERS(strncmp);
-EXPORT_SYMBOL_NOVERS(strchr);
-EXPORT_SYMBOL_NOVERS(strlen);
-EXPORT_SYMBOL_NOVERS(strnlen);
-EXPORT_SYMBOL_NOVERS(strpbrk);
-EXPORT_SYMBOL_NOVERS(strrchr);
-EXPORT_SYMBOL_NOVERS(strstr);
-EXPORT_SYMBOL_NOVERS(memset);
-EXPORT_SYMBOL_NOVERS(memcpy);
-EXPORT_SYMBOL_NOVERS(memmove);
-EXPORT_SYMBOL_NOVERS(memcmp);
-EXPORT_SYMBOL_NOVERS(memscan);
-EXPORT_SYMBOL_NOVERS(__memzero);
+EXPORT_SYMBOL(strcpy);
+EXPORT_SYMBOL(strncpy);
+EXPORT_SYMBOL(strcat);
+EXPORT_SYMBOL(strncat);
+EXPORT_SYMBOL(strcmp);
+EXPORT_SYMBOL(strncmp);
+EXPORT_SYMBOL(strchr);
+EXPORT_SYMBOL(strlen);
+EXPORT_SYMBOL(strnlen);
+EXPORT_SYMBOL(strpbrk);
+EXPORT_SYMBOL(strrchr);
+EXPORT_SYMBOL(strstr);
+EXPORT_SYMBOL(memset);
+EXPORT_SYMBOL(memcpy);
+EXPORT_SYMBOL(memmove);
+EXPORT_SYMBOL(memcmp);
+EXPORT_SYMBOL(memscan);
+EXPORT_SYMBOL(memchr);
+EXPORT_SYMBOL(__memzero);
 
 	/* user mem (segment) */
 EXPORT_SYMBOL(__arch_copy_from_user);
@@ -114,30 +115,30 @@
 EXPORT_SYMBOL(__arch_strnlen_user);
 EXPORT_SYMBOL(__arch_strncpy_from_user);
 
-EXPORT_SYMBOL_NOVERS(__get_user_1);
-EXPORT_SYMBOL_NOVERS(__get_user_2);
-EXPORT_SYMBOL_NOVERS(__get_user_4);
-EXPORT_SYMBOL_NOVERS(__get_user_8);
-
-EXPORT_SYMBOL_NOVERS(__put_user_1);
-EXPORT_SYMBOL_NOVERS(__put_user_2);
-EXPORT_SYMBOL_NOVERS(__put_user_4);
-EXPORT_SYMBOL_NOVERS(__put_user_8);
+EXPORT_SYMBOL(__get_user_1);
+EXPORT_SYMBOL(__get_user_2);
+EXPORT_SYMBOL(__get_user_4);
+EXPORT_SYMBOL(__get_user_8);
+
+EXPORT_SYMBOL(__put_user_1);
+EXPORT_SYMBOL(__put_user_2);
+EXPORT_SYMBOL(__put_user_4);
+EXPORT_SYMBOL(__put_user_8);
 
 	/* gcc lib functions */
-EXPORT_SYMBOL_NOVERS(__ashldi3);
-EXPORT_SYMBOL_NOVERS(__ashrdi3);
-EXPORT_SYMBOL_NOVERS(__divsi3);
-EXPORT_SYMBOL_NOVERS(__lshrdi3);
-EXPORT_SYMBOL_NOVERS(__modsi3);
-EXPORT_SYMBOL_NOVERS(__muldi3);
-EXPORT_SYMBOL_NOVERS(__ucmpdi2);
-EXPORT_SYMBOL_NOVERS(__udivdi3);
-EXPORT_SYMBOL_NOVERS(__umoddi3);
-EXPORT_SYMBOL_NOVERS(__udivmoddi4);
-EXPORT_SYMBOL_NOVERS(__udivsi3);
-EXPORT_SYMBOL_NOVERS(__umodsi3);
-EXPORT_SYMBOL_NOVERS(__do_div64);
+EXPORT_SYMBOL(__ashldi3);
+EXPORT_SYMBOL(__ashrdi3);
+EXPORT_SYMBOL(__divsi3);
+EXPORT_SYMBOL(__lshrdi3);
+EXPORT_SYMBOL(__modsi3);
+EXPORT_SYMBOL(__muldi3);
+EXPORT_SYMBOL(__ucmpdi2);
+EXPORT_SYMBOL(__udivdi3);
+EXPORT_SYMBOL(__umoddi3);
+EXPORT_SYMBOL(__udivmoddi4);
+EXPORT_SYMBOL(__udivsi3);
+EXPORT_SYMBOL(__umodsi3);
+EXPORT_SYMBOL(__do_div64);
 
 	/* bitops */
 EXPORT_SYMBOL(_set_bit_le);
diff -Nru a/arch/arm/kernel/asm-offsets.c b/arch/arm/kernel/asm-offsets.c
--- a/arch/arm/kernel/asm-offsets.c	2004-10-18 14:55:55 -07:00
+++ b/arch/arm/kernel/asm-offsets.c	2004-10-18 14:55:55 -07:00
@@ -13,6 +13,7 @@
 #include <linux/sched.h>
 #include <linux/mm.h>
 #include <asm/mach/arch.h>
+#include <asm/thread_info.h>
 
 /*
  * Make sure that the compiler and target are compatible.
@@ -48,10 +49,23 @@
 {
   DEFINE(TSK_ACTIVE_MM,		offsetof(struct task_struct, active_mm));
   BLANK();
+  DEFINE(TI_FLAGS,		offsetof(struct thread_info, flags));
+  DEFINE(TI_PREEMPT,		offsetof(struct thread_info, preempt_count));
+  DEFINE(TI_ADDR_LIMIT,		offsetof(struct thread_info, addr_limit));
+  DEFINE(TI_TASK,		offsetof(struct thread_info, task));
+  DEFINE(TI_EXEC_DOMAIN,	offsetof(struct thread_info, exec_domain));
+  DEFINE(TI_CPU,		offsetof(struct thread_info, cpu));
+  DEFINE(TI_CPU_DOMAIN,		offsetof(struct thread_info, cpu_domain));
+  DEFINE(TI_CPU_SAVE,		offsetof(struct thread_info, cpu_context));
+  DEFINE(TI_USED_CP,		offsetof(struct thread_info, used_cp));
+  DEFINE(TI_FPSTATE,		offsetof(struct thread_info, fpstate));
+  DEFINE(TI_VFPSTATE,		offsetof(struct thread_info, vfpstate));
+  DEFINE(TI_IWMMXT_STATE,	(offsetof(struct thread_info, fpstate)+4)&~7);
+  BLANK();
 #if __LINUX_ARM_ARCH__ >= 6
   DEFINE(MM_CONTEXT_ID,		offsetof(struct mm_struct, context.id));
-#endif
   BLANK();
+#endif
   DEFINE(VMA_VM_MM,		offsetof(struct vm_area_struct, vm_mm));
   DEFINE(VMA_VM_FLAGS,		offsetof(struct vm_area_struct, vm_flags));
   BLANK();
diff -Nru a/arch/arm/kernel/bios32.c b/arch/arm/kernel/bios32.c
--- a/arch/arm/kernel/bios32.c	2004-10-18 14:56:28 -07:00
+++ b/arch/arm/kernel/bios32.c	2004-10-18 14:56:28 -07:00
@@ -17,6 +17,7 @@
 #include <asm/mach/pci.h>
 
 static int debug_pci;
+static int use_firmware;
 
 /*
  * We can't use pci_find_device() here since we are
@@ -128,12 +129,14 @@
 	pci_write_config_word(dev, 0x44, 0xb000);
 	outb(0x08, 0x4d1);
 }
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_WINBOND, PCI_DEVICE_ID_WINBOND_83C553, pci_fixup_83c553);
 
 static void __devinit pci_fixup_unassign(struct pci_dev *dev)
 {
 	dev->resource[0].end -= dev->resource[0].start;
 	dev->resource[0].start = 0;
 }
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_WINBOND2, PCI_DEVICE_ID_WINBOND2_89C940F, pci_fixup_unassign);
 
 /*
  * Prevent the PCI layer from seeing the resources allocated to this device
@@ -154,6 +157,7 @@
 		}
 	}
 }
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_DEC, PCI_DEVICE_ID_DEC_21285, pci_fixup_dec21285);
 
 /*
  * Same as above. The PrPMC800 carrier board for the PrPMC1100 
@@ -178,6 +182,7 @@
 		}
 	}
 }
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_IXP4XX, pci_fixup_prpmc1100);
 
 /*
  * PCI IDE controllers use non-standard I/O port decoding, respect it.
@@ -198,6 +203,7 @@
 		}
 	}
 }
+DECLARE_PCI_FIXUP_HEADER(PCI_ANY_ID, PCI_ANY_ID, pci_fixup_ide_bases);
 
 /*
  * Put the DEC21142 to sleep
@@ -206,6 +212,7 @@
 {
 	pci_write_config_dword(dev, 0x40, 0x80000000);
 }
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_DEC, PCI_DEVICE_ID_DEC_21142, pci_fixup_dec21142);
 
 /*
  * The CY82C693 needs some rather major fixups to ensure that it does
@@ -271,38 +278,7 @@
 		pci_write_config_byte(dev, 0x45, 0x03);
 	}
 }
-
-struct pci_fixup pcibios_fixups[] = {
-	{
-		PCI_FIXUP_HEADER,
-		PCI_VENDOR_ID_CONTAQ,	PCI_DEVICE_ID_CONTAQ_82C693,
-		pci_fixup_cy82c693
-	}, {
-		PCI_FIXUP_HEADER,
-		PCI_VENDOR_ID_DEC,	PCI_DEVICE_ID_DEC_21142,
-		pci_fixup_dec21142
-	}, {
-		PCI_FIXUP_HEADER,
-		PCI_VENDOR_ID_DEC,	PCI_DEVICE_ID_DEC_21285,
-		pci_fixup_dec21285
-	}, {
-		PCI_FIXUP_HEADER,
-		PCI_VENDOR_ID_WINBOND,	PCI_DEVICE_ID_WINBOND_83C553,
-		pci_fixup_83c553
-	}, {
-		PCI_FIXUP_HEADER,
-		PCI_VENDOR_ID_WINBOND2,	PCI_DEVICE_ID_WINBOND2_89C940F,
-		pci_fixup_unassign
-	}, {
-		PCI_FIXUP_HEADER,
-		PCI_ANY_ID,		PCI_ANY_ID,
-		pci_fixup_ide_bases
-	}, {
-		PCI_FIXUP_HEADER,
-		PCI_VENDOR_ID_INTEL,	PCI_DEVICE_ID_INTEL_IXP4XX,
-		pci_fixup_prpmc1100
-	}, { 0 }
-};
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_CONTAQ, PCI_DEVICE_ID_CONTAQ_82C693, pci_fixup_cy82c693);
 
 void __devinit pcibios_update_irq(struct pci_dev *dev, int irq)
 {
@@ -596,15 +572,17 @@
 	list_for_each_entry(sys, &hw->buses, node) {
 		struct pci_bus *bus = sys->bus;
 
-		/*
-		 * Size the bridge windows.
-		 */
-		pci_bus_size_bridges(bus);
+		if (!use_firmware) {
+			/*
+		 	 * Size the bridge windows.
+		 	 */
+			pci_bus_size_bridges(bus);
 
-		/*
-		 * Assign resources.
-		 */
-		pci_bus_assign_resources(bus);
+			/*
+		 	 * Assign resources.
+		 	 */
+			pci_bus_assign_resources(bus);
+		}
 
 		/*
 		 * Tell drivers about devices found.
@@ -617,6 +595,9 @@
 {
 	if (!strcmp(str, "debug")) {
 		debug_pci = 1;
+		return NULL;
+	} else if (!strcmp(str, "firmware")) {
+		use_firmware = 1;
 		return NULL;
 	}
 	return str;
diff -Nru a/arch/arm/kernel/calls.S b/arch/arm/kernel/calls.S
--- a/arch/arm/kernel/calls.S	2004-10-18 14:57:05 -07:00
+++ b/arch/arm/kernel/calls.S	2004-10-18 14:57:05 -07:00
@@ -1,7 +1,7 @@
 /*
  *  linux/arch/arm/kernel/calls.S
  *
- *  Copyright (C) 1995-2003 Russell King
+ *  Copyright (C) 1995-2004 Russell King
  *
  * 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
@@ -288,6 +288,13 @@
 		.long	sys_pciconfig_iobase
 		.long	sys_pciconfig_read
 		.long	sys_pciconfig_write
+		.long	sys_mq_open
+/* 275 */	.long	sys_mq_unlink
+		.long	sys_mq_timedsend
+		.long	sys_mq_timedreceive
+		.long	sys_mq_notify
+		.long	sys_mq_getsetattr
+/* 280 */	.long	sys_waitid
 __syscall_end:
 
 		.rept	NR_syscalls - (__syscall_end - __syscall_start) / 4
diff -Nru a/arch/arm/kernel/debug.S b/arch/arm/kernel/debug.S
--- a/arch/arm/kernel/debug.S	2004-10-18 14:56:28 -07:00
+++ b/arch/arm/kernel/debug.S	2004-10-18 14:56:28 -07:00
@@ -411,10 +411,16 @@
 
 		.macro	addruart,rx
 		mov	\rx, #0xfe000000	@ physical
-#ifdef CONFIG_ARCH_IQ80310
-		orr	\rx, \rx, #0x00810000	@ location of the UART
-#elif defined(CONFIG_ARCH_IQ80321)
+#if defined(CONFIG_ARCH_IQ80321) || defined(CONFIG_ARCH_IQ31244)
 		orr	\rx, \rx, #0x00800000	@ location of the UART
+#elif defined(CONFIG_ARCH_IOP331)
+		mrc	p15, 0, \rx, c1, c0
+		tst	\rx, #1			@ MMU enabled?
+		moveq	\rx, #0x000fe000	@ Physical Base
+		movne	\rx, #0
+		orr	\rx, \rx, #0xfe000000
+		orr	\rx, \rx, #0x00f00000	@ Virtual Base
+		orr	\rx, \rx, #0x00001700   @ location of the UART
 #else
 #error Unknown IOP3XX implementation
 #endif
@@ -432,7 +438,7 @@
 		.endm
 
 		.macro	waituart,rd,rx
-#ifndef	CONFIG_ARCH_IQ80321
+#if !defined(CONFIG_ARCH_IQ80321) || !defined(CONFIG_ARCH_IQ31244) || !defined(CONFIG_ARCH_IQ80331)
 1001:		ldrb	\rd, [\rx, #0x6]
 		tst	\rd, #0x10
 		beq	1001b
@@ -464,6 +470,36 @@
                 .macro  busyuart,rd,rx
                 .endm
 
+#elif defined(CONFIG_ARCH_IXP2000)
+
+		.macro  addruart,rx
+		mrc	p15, 0, \rx, c1, c0
+		tst	\rx, #1			@ MMU enabled?
+		moveq	\rx, #0xc0000000	@ Physical base
+		movne	\rx, #0xfe000000	@ virtual base
+		orrne	\rx, \rx, #0x00f00000
+		orr	\rx, \rx, #0x00030000
+#ifdef	__ARMEB__
+		orr	\rx, \rx, #0x00000003
+#endif
+		.endm 
+		
+		.macro	senduart,rd,rx
+		strb	\rd, [\rx]
+		.endm
+
+		.macro	busyuart,rd,rx
+1002:		ldrb	\rd, [\rx, #0x14]
+		tst	\rd, #0x20       
+		beq	1002b
+		.endm
+
+		.macro	waituart,rd,rx
+		nop
+		nop
+		nop
+		.endm
+
 #elif defined(CONFIG_ARCH_OMAP)
 
 		.macro	addruart,rx
@@ -614,6 +650,60 @@
 1001:		ldr	\rd, [\rx, #0x18]	@ UARTFLG
 		tst	\rd, #1 << 3		@ UARTFLGUBUSY - 1 when busy
 		bne	1001b
+		.endm
+
+#elif defined(CONFIG_ARCH_IMX)
+
+		.macro	addruart,rx
+		mrc	p15, 0, \rx, c1, c0
+		tst	\rx, #1			@ MMU enabled?
+		moveq	\rx, #0x00000000	@ physical
+		movne	\rx, #0xe0000000	@ virtual
+		orr	\rx, \rx, #0x00200000
+		orr	\rx, \rx, #0x00006000	@ UART1 offset
+		.endm
+
+		.macro	senduart,rd,rx
+		str	\rd, [\rx, #0x40]	@ TXDATA
+		.endm
+
+		.macro	waituart,rd,rx
+		.endm
+
+		.macro	busyuart,rd,rx
+1002:		ldr	\rd, [\rx, #0x98]	@ SR2
+		tst	\rd, #1 << 3		@ TXDC
+		beq	1002b			@ wait until transmit done
+		.endm
+
+#elif defined(CONFIG_ARCH_H720X)
+
+		.equ    io_virt, IO_BASE
+		.equ    io_phys, IO_START
+
+		.macro  addruart,rx
+		mrc     p15, 0, \rx, c1, c0
+		tst     \rx, #1  	       @ MMU enabled?
+		moveq   \rx, #io_phys	       @ physical base address
+		movne   \rx, #io_virt	       @ virtual address
+		add     \rx, \rx, #0x00020000   @ UART1
+		.endm
+
+		.macro  senduart,rd,rx
+		str     \rd, [\rx, #0x0]        @ UARTDR
+
+		.endm
+
+		.macro  waituart,rd,rx
+1001:		ldr     \rd, [\rx, #0x18]       @ UARTFLG
+		tst     \rd, #1 << 5	       @ UARTFLGUTXFF - 1 when full
+		bne     1001b
+		.endm
+
+		.macro  busyuart,rd,rx
+1001:		ldr     \rd, [\rx, #0x18]       @ UARTFLG
+		tst     \rd, #1 << 3	       @ UARTFLGUBUSY - 1 when busy
+		bne     1001b
 		.endm
 #else
 #error Unknown architecture
diff -Nru a/arch/arm/kernel/ecard.c b/arch/arm/kernel/ecard.c
--- a/arch/arm/kernel/ecard.c	2004-10-18 14:56:49 -07:00
+++ b/arch/arm/kernel/ecard.c	2004-10-18 14:56:49 -07:00
@@ -33,6 +33,7 @@
 #include <linux/types.h>
 #include <linux/sched.h>
 #include <linux/interrupt.h>
+#include <linux/completion.h>
 #include <linux/reboot.h>
 #include <linux/mm.h>
 #include <linux/slab.h>
@@ -53,18 +54,14 @@
 #define HAVE_EXPMASK
 #endif
 
-enum req {
-	req_readbytes,
-	req_reset
-};
-
 struct ecard_request {
-	enum req	req;
+	void		(*fn)(struct ecard_request *);
 	ecard_t		*ec;
 	unsigned int	address;
 	unsigned int	length;
 	unsigned int	use_loader;
 	void		*buffer;
+	struct completion *complete;
 };
 
 struct expcard_blacklist {
@@ -129,15 +126,14 @@
 #define POD_INT_ADDR(x)	((volatile unsigned char *)\
 			 ((BUS_ADDR((x)) - IO_BASE) + IO_START))
 
-static inline void ecard_task_reset(struct ecard_request *req)
+static void ecard_task_reset(struct ecard_request *req)
 {
 	struct expansion_card *ec = req->ec;
 	if (ec->loader)
 		ecard_loader_reset(POD_INT_ADDR(ec->podaddr), ec->loader);
 }
 
-static void
-ecard_task_readbytes(struct ecard_request *req)
+static void ecard_task_readbytes(struct ecard_request *req)
 {
 	unsigned char *buf = (unsigned char *)req->buffer;
 	volatile unsigned char *base_addr =
@@ -206,26 +202,9 @@
 
 }
 
-static void ecard_do_request(struct ecard_request *req)
-{
-	switch (req->req) {
-	case req_readbytes:
-		ecard_task_readbytes(req);
-		break;
-
-	case req_reset:
-		ecard_task_reset(req);
-		break;
-	}
-}
-
-#include <linux/completion.h>
-
-static pid_t ecard_pid;
-static wait_queue_head_t ecard_wait;
+static DECLARE_WAIT_QUEUE_HEAD(ecard_wait);
 static struct ecard_request *ecard_req;
-
-static DECLARE_COMPLETION(ecard_completion);
+static DECLARE_MUTEX(ecard_sem);
 
 /*
  * Set up the expansion card daemon's page tables.
@@ -282,8 +261,6 @@
 static int
 ecard_task(void * unused)
 {
-	struct task_struct *tsk = current;
-
 	daemonize("kecardd");
 
 	/*
@@ -298,17 +275,13 @@
 	while (1) {
 		struct ecard_request *req;
 
-		do {
-			req = xchg(&ecard_req, NULL);
-
-			if (req == NULL) {
-				sigemptyset(&tsk->pending.signal);
-				interruptible_sleep_on(&ecard_wait);
-			}
-		} while (req == NULL);
+		wait_event_interruptible(ecard_wait, ecard_req != NULL);
 
-		ecard_do_request(req);
-		complete(&ecard_completion);
+		req = xchg(&ecard_req, NULL);
+		if (req != NULL) {
+			req->fn(req);
+			complete(req->complete);
+		}
 	}
 }
 
@@ -318,25 +291,21 @@
  * FIXME: The test here is not sufficient to detect if the
  * kcardd is running.
  */
-static void
-ecard_call(struct ecard_request *req)
+static void ecard_call(struct ecard_request *req)
 {
-	/*
-	 * Make sure we have a context that is able to sleep.
-	 */
-	if (current == &init_task || in_interrupt())
-		BUG();
+	DECLARE_COMPLETION(completion);
 
-	if (ecard_pid <= 0)
-		ecard_pid = kernel_thread(ecard_task, NULL, CLONE_KERNEL);
+	req->complete = &completion;
 
+	down(&ecard_sem);
 	ecard_req = req;
 	wake_up(&ecard_wait);
 
 	/*
 	 * Now wait for kecardd to run.
 	 */
-	wait_for_completion(&ecard_completion);
+	wait_for_completion(&completion);
+	up(&ecard_sem);
 }
 
 /* ======================= Mid-level card control ===================== */
@@ -346,7 +315,7 @@
 {
 	struct ecard_request req;
 
-	req.req		= req_readbytes;
+	req.fn		= ecard_task_readbytes;
 	req.ec		= ec;
 	req.address	= off;
 	req.length	= len;
@@ -1066,9 +1035,14 @@
  */
 static int __init ecard_init(void)
 {
-	int slot, irqhw;
+	int slot, irqhw, ret;
 
-	init_waitqueue_head(&ecard_wait);
+	ret = kernel_thread(ecard_task, NULL, CLONE_KERNEL);
+	if (ret < 0) {
+		printk(KERN_ERR "Ecard: unable to create kernel thread: %d\n",
+		       ret);
+		return ret;
+	}
 
 	printk("Probing expansion cards\n");
 
@@ -1151,7 +1125,7 @@
 	if (drv->shutdown)
 		drv->shutdown(ec);
 	ecard_release(ec);
-	req.req = req_reset;
+	req.fn = ecard_task_reset;
 	req.ec = ec;
 	ecard_call(&req);
 }
diff -Nru a/arch/arm/kernel/entry-armv.S b/arch/arm/kernel/entry-armv.S
--- a/arch/arm/kernel/entry-armv.S	2004-10-18 14:56:28 -07:00
+++ b/arch/arm/kernel/entry-armv.S	2004-10-18 14:56:28 -07:00
@@ -562,40 +562,6 @@
 		.macro	irq_prio_table
 		.endm
 
-#elif defined(CONFIG_ARCH_IOP310)
-
-		.macro	disable_fiq
-		.endm
-
-        	.macro  get_irqnr_and_base, irqnr, irqstat, base, tmp
-        	mrc p13, 0, \irqstat, c4, c0, 0 @ get INTSRC
-        	mrc p13, 0, \base, c0, c0, 0    @ get INTCTL
-
-        	tst \irqstat, #(1<<29)      @ if INTSRC_BI
-        	tstne   \base, #(1<<3)          @ and INTCTL_BM
-        	movne   \irqnr, #IRQ_XS80200_BCU
-        	bne 1001f
-
-        	tst \irqstat, #(1<<28)      @ if INTSRC_PI
-        	tstne   \base, #(1<<2)          @ and INTCTL_PM
-        	movne   \irqnr, #IRQ_XS80200_PMU
-        	bne 1001f
-
-        	tst \irqstat, #(1<<31)      @ if INTSRC_FI
-        	tstne   \base, #(1<<0)          @ and INTCTL_FM
-        	movne   \irqnr, #IRQ_XS80200_EXTFIQ
-        	bne 1001f
-
-        	tst \irqstat, #(1<<30)      @ if INTSRC_II
-        	tstne   \base, #(1<<1)          @ and INTCTL_IM
-        	movne   \irqnr, #IRQ_XS80200_EXTIRQ
-
-1001:
-  		.endm
-
-  		.macro	irq_prio_table
- 		.endm
-
 #elif defined(CONFIG_ARCH_IOP321)
 		.macro  disable_fiq
 		.endm
@@ -618,6 +584,39 @@
 		.macro  irq_prio_table
 		.endm
 
+#elif defined(CONFIG_ARCH_IOP331)
+		.macro  disable_fiq
+		.endm
+
+		/*
+		 * Note: only deal with normal interrupts, not FIQ
+		 */
+		.macro  get_irqnr_and_base, irqnr, irqstat, base, tmp
+		mov     \irqnr, #0
+		mrc     p6, 0, \irqstat, c4, c0, 0      @ Read IINTSRC0
+		cmp     \irqstat, #0
+		bne     1002f
+		mrc     p6, 0, \irqstat, c5, c0, 0      @ Read IINTSRC1
+		cmp	\irqstat, #0
+		beq	1001f
+		clz	\irqnr, \irqstat
+/*
+ *		mov	\base, #31
+ *		subs	\irqnr,\base,\irqnr
+ */
+        rsbs    \irqnr,\irqnr,#31   @ recommend by RMK
+		add	\irqnr,\irqnr,#IRQ_IOP331_XINT8
+		b	1001f
+1002:		clz     \irqnr, \irqstat
+		mov     \base, #31
+		subs    \irqnr,\base,\irqnr
+		add     \irqnr,\irqnr,#IRQ_IOP331_DMA0_EOT
+1001:
+		.endm
+
+		.macro  irq_prio_table
+		.endm
+
 #elif defined(CONFIG_ARCH_PXA)
 
 		.macro	disable_fiq
@@ -645,6 +644,60 @@
 		.macro	irq_prio_table
 		.endm
 
+#elif defined(CONFIG_ARCH_IXP2000)
+
+		.macro  disable_fiq
+		.endm
+
+		.macro  get_irqnr_and_base, irqnr, irqstat, base, tmp
+		
+		mov	\irqnr, #0x0              @clear out irqnr as default
+                mov	\base, #0xfe000000        
+		orr	\base, \base, #0x00ff0000
+		orr	\base, \base, #0x0000a000
+		orr	\base, \base, #0x08
+		ldr	\irqstat, [\base]         @ get interrupts 
+		mov	\tmp, #IXP2000_VALID_IRQ_MASK & 0xff000000
+		orr	\tmp, \tmp, #IXP2000_VALID_IRQ_MASK & 0x00ff0000
+		orr	\tmp, \tmp, #IXP2000_VALID_IRQ_MASK & 0x0000ff00
+		orr	\tmp, \tmp, #IXP2000_VALID_IRQ_MASK & 0x000000ff
+		and	\irqstat, \irqstat, \tmp
+
+		cmp	\irqstat, #0
+		beq	1001f	
+
+		clz     \irqnr, \irqstat
+		mov     \base, #31
+		subs    \irqnr, \base, \irqnr
+		
+		/*
+		 * We handle PCIA and PCIB here so we don't have an
+		 * extra layer of code just to check these two bits.
+		 */
+		cmp	\irqnr, #IRQ_IXP2000_PCI
+		bne	1001f
+
+		mov	\base, #0xfe000000
+		orr	\base, \base, #0x00fd0000
+		orr	\base, \base, #0x0000e100
+		orr	\base, \base, #0x00000058
+		ldr	\irqstat, [\base]
+
+		mov	\tmp, #(1<<26)
+		tst	\irqstat, \tmp
+		movne	\irqnr, #IRQ_IXP2000_PCIA
+		bne	1001f
+
+		mov	\tmp, #(1<<27)
+		tst	\irqstat, \tmp
+		movne	\irqnr, #IRQ_IXP2000_PCIB
+
+1001:
+		.endm 
+		
+		.macro  irq_prio_table
+		.endm
+
 #elif defined (CONFIG_ARCH_IXP4XX)
 
 		.macro	disable_fiq
@@ -884,6 +937,82 @@
                .macro  irq_prio_table
                .endm
 
+#elif defined(CONFIG_ARCH_IMX)
+
+		.macro	disable_fiq
+		.endm
+#define AITC_NIVECSR   0x40
+		.macro	get_irqnr_and_base, irqnr, irqstat, base, tmp
+		ldr	\irqstat, =IO_ADDRESS(IMX_AITC_BASE)
+		@ Load offset & priority of the highest priority
+		@ interrupt pending.
+		ldr	\irqnr, [\irqstat, #AITC_NIVECSR]
+		@ Shift off the priority leaving the offset or
+		@ "interrupt number"
+		mov	\irqnr, \irqnr, lsr #16
+ 		ldr	\irqstat, =1	@ dummy compare
+		ldr	\base, =0xFFFF		// invalid interrupt
+		cmp	\irqnr, \base
+		bne	1001f
+		ldr	\irqstat, =0
+1001:
+		tst	\irqstat, #1	@ to make the condition code = TRUE
+		.endm
+
+		.macro	irq_prio_table
+		.endm
+
+#elif defined(CONFIG_ARCH_H720X)
+
+		.macro  disable_fiq
+		.endm
+
+		.macro  get_irqnr_and_base, irqnr, irqstat, base, tmp
+#if defined (CONFIG_CPU_H7201) || defined (CONFIG_CPU_H7202)
+		@ we could use the id register on H7202, but this is not
+		@ properly updated when we come back from asm_do_irq
+		@ without a previous return from interrupt
+		@ (see loops below in irq_svc, irq_usr)
+		@ We see unmasked pending ints only, as the masked pending ints
+		@ are not visible here
+
+		mov     \base, #0xf0000000	       @ base register
+		orr     \base, \base, #0x24000	       @ irqbase
+		ldr     \irqstat, [\base, #0x04]        @ get interrupt status
+#if defined (CONFIG_CPU_H7201)
+		ldr	\tmp, =0x001fffff
+#else
+		mvn     \tmp, #0xc0000000
+#endif
+		and     \irqstat, \irqstat, \tmp        @ mask out unused ints
+		mov     \irqnr, #0
+
+		mov     \tmp, #0xff00
+		orr     \tmp, \tmp, #0xff
+		tst     \irqstat, \tmp
+		addeq   \irqnr, \irqnr, #16
+		moveq   \irqstat, \irqstat, lsr #16
+		tst     \irqstat, #255
+		addeq   \irqnr, \irqnr, #8
+		moveq   \irqstat, \irqstat, lsr #8
+		tst     \irqstat, #15
+		addeq   \irqnr, \irqnr, #4
+		moveq   \irqstat, \irqstat, lsr #4
+		tst     \irqstat, #3
+		addeq   \irqnr, \irqnr, #2
+		moveq   \irqstat, \irqstat, lsr #2
+		tst     \irqstat, #1
+		addeq   \irqnr, \irqnr, #1
+		moveq   \irqstat, \irqstat, lsr #1
+		tst     \irqstat, #1		       @ bit 0 should be set
+		.endm
+
+		.macro  irq_prio_table
+		.endm
+
+#else
+#error hynix processor selection missmatch
+#endif
 #else
 #error Unknown architecture
 #endif
@@ -1174,7 +1303,7 @@
  *  r0  - instruction opcode.
  *  r10 - this threads thread_info structure.
  */
-call_fpe:	enable_irq r10				@ Enable interrupts
+call_fpe:
 		tst	r0, #0x08000000			@ only CDP/CPRT/LDC/STC have bit 27
 #if defined(CONFIG_CPU_ARM610) || defined(CONFIG_CPU_ARM710)
 		and	r8, r0, #0x0f000000		@ mask out op-code bits
@@ -1186,6 +1315,14 @@
 		mov	r7, #1
 		add	r6, r10, #TI_USED_CP
 		strb	r7, [r6, r8, lsr #8]		@ set appropriate used_cp[]
+#ifdef CONFIG_IWMMXT
+		@ Test if we need to give access to iWMMXt coprocessors
+		ldr	r5, [r10, #TI_FLAGS]
+		rsbs	r7, r8, #(1 << 8)		@ CP 0 or 1 only
+		movcss	r7, r5, lsr #(TIF_USING_IWMMXT + 1)
+		bcs	iwmmxt_task_enable
+#endif
+		enable_irq r7
 		add	pc, pc, r8, lsr #6
 		mov	r0, r0
 
@@ -1264,7 +1401,11 @@
 ENTRY(__switch_to)
 		add	ip, r1, #TI_CPU_SAVE
 		ldr	r3, [r2, #TI_CPU_DOMAIN]!
-		stmia	ip, {r4 - sl, fp, sp, lr}	@ Store most regs on stack
+		stmia	ip!, {r4 - sl, fp, sp, lr}	@ Store most regs on stack
+#if defined(CONFIG_CPU_XSCALE) && !defined(CONFIG_IWMMXT)
+		mra	r4, r5, acc0
+		stmia   ip, {r4, r5}
+#endif
 		mcr	p15, 0, r3, c3, c0, 0		@ Set domain register
 #ifdef CONFIG_VFP
 		@ Always disable VFP so we can lazily save/restore the old
@@ -1272,6 +1413,13 @@
 		VFPFMRX	r4, FPEXC
 		bic	r4, r4, #FPEXC_ENABLE
 		VFPFMXR	FPEXC, r4
+#endif
+#if defined(CONFIG_IWMMXT)
+		bl	iwmmxt_task_switch
+#elif defined(CONFIG_CPU_XSCALE)
+		add	r4, r2, #40			@ cpu_context_save->extra
+		ldmib	r4, {r4, r5}
+		mar	acc0, r4, r5
 #endif
 		ldmib	r2, {r4 - sl, fp, sp, pc}	@ Load all regs saved previously
 
diff -Nru a/arch/arm/kernel/irq.c b/arch/arm/kernel/irq.c
--- a/arch/arm/kernel/irq.c	2004-10-18 14:55:46 -07:00
+++ b/arch/arm/kernel/irq.c	2004-10-18 14:55:46 -07:00
@@ -46,6 +46,7 @@
  */
 #define MAX_IRQ_CNT	100000
 
+static int noirqdebug;
 static volatile unsigned long irq_err_count;
 static spinlock_t irq_controller_lock = SPIN_LOCK_UNLOCKED;
 static LIST_HEAD(irq_pending);
@@ -235,7 +236,7 @@
 	static int count = 100;
 	struct irqaction *action;
 
-	if (!count)
+	if (!count || noirqdebug)
 		return;
 
 	count--;
@@ -261,7 +262,7 @@
 __do_irq(unsigned int irq, struct irqaction *action, struct pt_regs *regs)
 {
 	unsigned int status;
-	int retval = 0;
+	int ret, retval = 0;
 
 	spin_unlock(&irq_controller_lock);
 
@@ -270,8 +271,10 @@
 
 	status = 0;
 	do {
-		status |= action->flags;
-		retval |= action->handler(irq, action->dev_id, regs);
+		ret = action->handler(irq, action->dev_id, regs);
+		if (ret == IRQ_HANDLED)
+			status |= action->flags;
+		retval |= ret;
 		action = action->next;
 	} while (action);
 
@@ -861,3 +864,11 @@
 	init_arch_irq();
 	init_dma();
 }
+
+static int __init noirqdebug_setup(char *str)
+{
+	noirqdebug = 1;
+	return 1;
+}
+
+__setup("noirqdebug", noirqdebug_setup);
diff -Nru a/arch/arm/kernel/iwmmxt.S b/arch/arm/kernel/iwmmxt.S
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/arch/arm/kernel/iwmmxt.S	2004-10-18 14:57:21 -07:00
@@ -0,0 +1,320 @@
+/*
+ *  linux/arch/arm/kernel/iwmmxt.S
+ *
+ *  XScale iWMMXt (Concan) context switching and handling
+ *
+ *  Initial code:
+ *  Copyright (c) 2003, Intel Corporation
+ *
+ *  Full lazy switching support, optimizations and more, by Nicolas Pitre
+*   Copyright (c) 2003-2004, 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 version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/linkage.h>
+#include <asm/ptrace.h>
+#include <asm/thread_info.h>
+#include <asm/constants.h>
+
+#define MMX_WR0		 	(0x00)
+#define MMX_WR1		 	(0x08)
+#define MMX_WR2		 	(0x10)
+#define MMX_WR3			(0x18)
+#define MMX_WR4		 	(0x20)
+#define MMX_WR5		 	(0x28)
+#define MMX_WR6		 	(0x30)
+#define MMX_WR7		 	(0x38)
+#define MMX_WR8		 	(0x40)
+#define MMX_WR9		 	(0x48)
+#define MMX_WR10		(0x50)
+#define MMX_WR11		(0x58)
+#define MMX_WR12		(0x60)
+#define MMX_WR13		(0x68)
+#define MMX_WR14		(0x70)
+#define MMX_WR15		(0x78)
+#define MMX_WCSSF		(0x80)
+#define MMX_WCASF		(0x84)
+#define MMX_WCGR0		(0x88)
+#define MMX_WCGR1		(0x8C)
+#define MMX_WCGR2		(0x90)
+#define MMX_WCGR3		(0x94)
+
+#define MMX_SIZE		(0x98)
+
+	.text
+
+/*
+ * Lazy switching of Concan coprocessor context
+ *
+ * r10 = struct thread_info pointer
+ * r9  = ret_from_exception
+ * lr  = undefined instr exit
+ *
+ * called from prefetch exception handler with interrupts disabled
+ */
+
+ENTRY(iwmmxt_task_enable)
+
+	mrc	p15, 0, r2, c15, c1, 0
+	tst	r2, #0x3			@ CP0 and CP1 accessible?
+	movne	pc, lr				@ if so no business here
+	orr	r2, r2, #0x3			@ enable access to CP0 and CP1
+	mcr	p15, 0, r2, c15, c1, 0
+
+	ldr	r3, =concan_owner
+	add	r0, r10, #TI_IWMMXT_STATE	@ get task Concan save area
+	ldr	r2, [sp, #60]			@ current task pc value
+	ldr	r1, [r3]			@ get current Concan owner
+	str	r0, [r3]			@ this task now owns Concan regs
+	sub	r2, r2, #4			@ adjust pc back
+	str	r2, [sp, #60]
+
+	mrc	p15, 0, r2, c2, c0, 0
+	mov	r2, r2				@ cpwait
+
+	teq	r1, #0				@ test for last ownership
+	mov	lr, r9				@ normal exit from exception
+	beq	concan_load			@ no owner, skip save
+
+concan_save:
+
+	tmrc	r2, wCon
+
+	@ CUP? wCx
+	tst	r2, #0x1
+	beq 	1f
+
+concan_dump:
+
+	wstrw	wCSSF, [r1, #MMX_WCSSF]
+	wstrw	wCASF, [r1, #MMX_WCASF]
+	wstrw	wCGR0, [r1, #MMX_WCGR0]
+	wstrw	wCGR1, [r1, #MMX_WCGR1]
+	wstrw	wCGR2, [r1, #MMX_WCGR2]
+	wstrw	wCGR3, [r1, #MMX_WCGR3]
+
+1:	@ MUP? wRn
+	tst	r2, #0x2
+	beq	2f
+
+	wstrd	wR0,  [r1, #MMX_WR0]
+	wstrd	wR1,  [r1, #MMX_WR1]
+	wstrd	wR2,  [r1, #MMX_WR2]
+	wstrd	wR3,  [r1, #MMX_WR3]
+	wstrd	wR4,  [r1, #MMX_WR4]
+	wstrd	wR5,  [r1, #MMX_WR5]
+	wstrd	wR6,  [r1, #MMX_WR6]
+	wstrd	wR7,  [r1, #MMX_WR7]
+	wstrd	wR8,  [r1, #MMX_WR8]
+	wstrd	wR9,  [r1, #MMX_WR9]
+	wstrd	wR10, [r1, #MMX_WR10]
+	wstrd	wR11, [r1, #MMX_WR11]
+	wstrd	wR12, [r1, #MMX_WR12]
+	wstrd	wR13, [r1, #MMX_WR13]
+	wstrd	wR14, [r1, #MMX_WR14]
+	wstrd	wR15, [r1, #MMX_WR15]
+
+2:	teq	r0, #0				@ anything to load?
+	moveq	pc, lr
+
+concan_load:
+
+	@ Load wRn
+	wldrd	wR0,  [r0, #MMX_WR0]
+	wldrd	wR1,  [r0, #MMX_WR1]
+	wldrd	wR2,  [r0, #MMX_WR2]
+	wldrd	wR3,  [r0, #MMX_WR3]
+	wldrd	wR4,  [r0, #MMX_WR4]
+	wldrd	wR5,  [r0, #MMX_WR5]
+	wldrd	wR6,  [r0, #MMX_WR6]
+	wldrd	wR7,  [r0, #MMX_WR7]
+	wldrd	wR8,  [r0, #MMX_WR8]
+	wldrd	wR9,  [r0, #MMX_WR9]
+	wldrd	wR10, [r0, #MMX_WR10]
+	wldrd	wR11, [r0, #MMX_WR11]
+	wldrd	wR12, [r0, #MMX_WR12]
+	wldrd	wR13, [r0, #MMX_WR13]
+	wldrd	wR14, [r0, #MMX_WR14]
+	wldrd	wR15, [r0, #MMX_WR15]
+
+	@ Load wCx
+	wldrw	wCSSF, [r0, #MMX_WCSSF]
+	wldrw	wCASF, [r0, #MMX_WCASF]
+	wldrw	wCGR0, [r0, #MMX_WCGR0]
+	wldrw	wCGR1, [r0, #MMX_WCGR1]
+	wldrw	wCGR2, [r0, #MMX_WCGR2]
+	wldrw	wCGR3, [r0, #MMX_WCGR3]
+
+	@ clear CUP/MUP (only if r1 != 0)
+	teq	r1, #0
+	mov 	r2, #0
+	moveq	pc, lr
+	tmcr	wCon, r2
+	mov	pc, lr
+
+/*
+ * Back up Concan regs to save area and disable access to them
+ * (mainly for gdb or sleep mode usage)
+ *
+ * r0 = struct thread_info pointer of target task or NULL for any
+ */
+
+ENTRY(iwmmxt_task_disable)
+
+	stmfd	sp!, {r4, lr}
+
+	mrs	ip, cpsr
+	orr	r2, ip, #PSR_I_BIT		@ disable interrupts
+	msr	cpsr_c, r2
+
+	ldr	r3, =concan_owner
+	add	r2, r0, #TI_IWMMXT_STATE	@ get task Concan save area
+	ldr	r1, [r3]			@ get current Concan owner
+	teq	r1, #0				@ any current owner?
+	beq	1f				@ no: quit
+	teq	r0, #0				@ any owner?
+	teqne	r1, r2				@ or specified one?
+	bne	1f				@ no: quit
+
+	mrc	p15, 0, r4, c15, c1, 0
+	orr	r4, r4, #0x3			@ enable access to CP0 and CP1
+	mcr	p15, 0, r4, c15, c1, 0
+	mov	r0, #0				@ nothing to load
+	str	r0, [r3]			@ no more current owner
+	mrc	p15, 0, r2, c2, c0, 0
+	mov	r2, r2				@ cpwait
+	bl	concan_save
+
+	bic	r4, r4, #0x3			@ disable access to CP0 and CP1
+	mcr	p15, 0, r4, c15, c1, 0
+	mrc	p15, 0, r2, c2, c0, 0
+	mov	r2, r2				@ cpwait
+
+1:	msr	cpsr_c, ip			@ restore interrupt mode
+	ldmfd	sp!, {r4, pc}
+
+/*
+ * Copy Concan state to given memory address
+ *
+ * r0 = struct thread_info pointer of target task
+ * r1 = memory address where to store Concan state
+ *
+ * this is called mainly in the creation of signal stack frames
+ */
+
+ENTRY(iwmmxt_task_copy)
+
+	mrs	ip, cpsr
+	orr	r2, ip, #PSR_I_BIT		@ disable interrupts
+	msr	cpsr_c, r2
+
+	ldr	r3, =concan_owner
+	add	r2, r0, #TI_IWMMXT_STATE	@ get task Concan save area
+	ldr	r3, [r3]			@ get current Concan owner
+	teq	r2, r3				@ does this task own it...
+	beq	1f
+
+	@ current Concan values are in the task save area
+	msr	cpsr_c, ip			@ restore interrupt mode
+	mov	r0, r1
+	mov	r1, r2
+	mov	r2, #MMX_SIZE
+	b	memcpy
+
+1:	@ this task owns Concan regs -- grab a copy from there
+	mov	r0, #0				@ nothing to load
+	mov	r2, #3				@ save all regs
+	mov	r3, lr				@ preserve return address
+	bl	concan_dump
+	msr	cpsr_c, ip			@ restore interrupt mode
+	mov	pc, r3
+
+/*
+ * Restore Concan state from given memory address
+ *
+ * r0 = struct thread_info pointer of target task
+ * r1 = memory address where to get Concan state from
+ *
+ * this is used to restore Concan state when unwinding a signal stack frame
+ */
+
+ENTRY(iwmmxt_task_restore)
+
+	mrs	ip, cpsr
+	orr	r2, ip, #PSR_I_BIT		@ disable interrupts
+	msr	cpsr_c, r2
+
+	ldr	r3, =concan_owner
+	add	r2, r0, #TI_IWMMXT_STATE	@ get task Concan save area
+	ldr	r3, [r3]			@ get current Concan owner
+	bic	r2, r2, #0x7			@ 64-bit alignment
+	teq	r2, r3				@ does this task own it...
+	beq	1f
+
+	@ this task doesn't own Concan regs -- use its save area
+	msr	cpsr_c, ip			@ restore interrupt mode
+	mov	r0, r2
+	mov	r2, #MMX_SIZE
+	b	memcpy
+
+1:	@ this task owns Concan regs -- load them directly
+	mov	r0, r1
+	mov	r1, #0				@ don't clear CUP/MUP
+	mov	r3, lr				@ preserve return address
+	bl	concan_load
+	msr	cpsr_c, ip			@ restore interrupt mode
+	mov	pc, r3
+
+/*
+ * Concan handling on task switch
+ *
+ * r0 = previous task_struct pointer (must be preserved)
+ * r1 = previous thread_info pointer
+ * r2 = next thread_info.cpu_domain pointer (must be preserved)
+ *
+ * Called only from __switch_to with task preemption disabled.
+ * No need to care about preserving r4 and above.
+ */
+ENTRY(iwmmxt_task_switch)
+
+	mrc	p15, 0, r4, c15, c1, 0
+	tst	r4, #0x3			@ CP0 and CP1 accessible?
+	bne	1f				@ yes: block them for next task
+
+	ldr	r5, =concan_owner
+	add	r6, r2, #(TI_IWMMXT_STATE - TI_CPU_DOMAIN) @ get next task Concan save area
+	ldr	r5, [r5]			@ get current Concan owner
+	teq	r5, r6				@ next task owns it?
+	movne	pc, lr				@ no: leave Concan disabled
+
+1:	eor	r4, r4, #3			@ flip Concan access
+	mcr	p15, 0, r4, c15, c1, 0
+
+	mrc	p15, 0, r4, c2, c0, 0
+	sub	pc, lr, r4, lsr #32		@ cpwait and return
+
+/*
+ * Remove Concan ownership of given task
+ *
+ * r0 = struct thread_info pointer
+ */
+ENTRY(iwmmxt_task_release)
+
+	mrs	r2, cpsr
+	orr	ip, r2, #PSR_I_BIT		@ disable interrupts
+	msr	cpsr_c, ip
+	ldr	r3, =concan_owner
+	add	r0, r0, #TI_IWMMXT_STATE	@ get task Concan save area
+	ldr	r1, [r3]			@ get current Concan owner
+	eors	r0, r0, r1			@ if equal...
+	streq	r0, [r3]			@ then clear ownership
+	msr	cpsr_c, r2			@ restore interrupts
+	mov	pc, lr
+
+	.data
+concan_owner:
+	.word	0
+
diff -Nru a/arch/arm/kernel/process.c b/arch/arm/kernel/process.c
--- a/arch/arm/kernel/process.c	2004-10-18 14:57:03 -07:00
+++ b/arch/arm/kernel/process.c	2004-10-18 14:57:03 -07:00
@@ -313,6 +313,9 @@
 
 	memset(thread->used_cp, 0, sizeof(thread->used_cp));
 	memset(&tsk->thread.debug, 0, sizeof(struct debug_info));
+#if defined(CONFIG_IWMMXT)
+	iwmmxt_task_release(thread);
+#endif
 	fp_init(&thread->fpstate);
 #if defined(CONFIG_VFP)
 	vfp_flush_thread(&thread->vfpstate);
@@ -323,6 +326,9 @@
 {
 #if defined(CONFIG_VFP)
 	vfp_release_thread(&dead_task->thread_info->vfpstate);
+#endif
+#if defined(CONFIG_IWMMXT)
+	iwmmxt_task_release(dead_task->thread_info);
 #endif
 }
 
diff -Nru a/arch/arm/kernel/ptrace.c b/arch/arm/kernel/ptrace.c
--- a/arch/arm/kernel/ptrace.c	2004-10-18 14:55:55 -07:00
+++ b/arch/arm/kernel/ptrace.c	2004-10-18 14:55:55 -07:00
@@ -792,11 +792,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
 	 * for normal use.  strace only continues with a signal if the
diff -Nru a/arch/arm/kernel/semaphore.c b/arch/arm/kernel/semaphore.c
--- a/arch/arm/kernel/semaphore.c	2004-10-18 14:56:29 -07:00
+++ b/arch/arm/kernel/semaphore.c	2004-10-18 14:56:29 -07:00
@@ -214,7 +214,7 @@
 	ldmfd	sp!, {r0 - r3, pc}		\n\
 	");
 
-EXPORT_SYMBOL_NOVERS(__down_failed);
-EXPORT_SYMBOL_NOVERS(__down_interruptible_failed);
-EXPORT_SYMBOL_NOVERS(__down_trylock_failed);
-EXPORT_SYMBOL_NOVERS(__up_wakeup);
+EXPORT_SYMBOL(__down_failed);
+EXPORT_SYMBOL(__down_interruptible_failed);
+EXPORT_SYMBOL(__down_trylock_failed);
+EXPORT_SYMBOL(__up_wakeup);
diff -Nru a/arch/arm/kernel/setup.c b/arch/arm/kernel/setup.c
--- a/arch/arm/kernel/setup.c	2004-10-18 14:56:32 -07:00
+++ b/arch/arm/kernel/setup.c	2004-10-18 14:56:32 -07:00
@@ -57,7 +57,6 @@
 extern void paging_init(struct meminfo *, struct machine_desc *desc);
 extern void convert_to_tag_list(struct tag *tags);
 extern void squash_mem_tags(struct tag *tag);
-extern void bootmem_init(struct meminfo *);
 extern void reboot_setup(char *str);
 extern int root_mountflags;
 extern int _stext, _text, _etext, _edata, _end;
@@ -720,7 +719,6 @@
 	memcpy(saved_command_line, from, COMMAND_LINE_SIZE);
 	saved_command_line[COMMAND_LINE_SIZE-1] = '\0';
 	parse_cmdline(cmdline_p, from);
-	bootmem_init(&meminfo);
 	paging_init(&meminfo, mdesc);
 	request_standard_resources(&meminfo, mdesc);
 
@@ -758,6 +756,7 @@
 	"fpa",
 	"vfp",
 	"edsp",
+	"java",
 	NULL
 };
 
diff -Nru a/arch/arm/kernel/signal.c b/arch/arm/kernel/signal.c
--- a/arch/arm/kernel/signal.c	2004-10-18 14:55:54 -07:00
+++ b/arch/arm/kernel/signal.c	2004-10-18 14:55:54 -07:00
@@ -145,6 +145,100 @@
 	unsigned long retcode;
 };
 
+#ifdef CONFIG_IWMMXT
+
+/* iwmmxt_area is 0x98 bytes long, preceeded by 8 bytes of signature */
+#define IWMMXT_STORAGE_SIZE	(0x98 + 8)
+#define IWMMXT_MAGIC0		0x12ef842a
+#define IWMMXT_MAGIC1		0x1c07ca71
+
+static int page_present(struct mm_struct *mm, unsigned long addr, int wr)
+{
+	pgd_t *pgd = pgd_offset(mm, addr);
+	if (pgd_present(*pgd)) {
+		pmd_t *pmd = pmd_offset(pgd, addr);
+		if (pmd_present(*pmd)) {
+			pte_t *pte = pte_offset_map(pmd, addr);
+			return (pte_present(*pte) && (!wr || pte_write(*pte)));
+		}
+	}
+	return 0;
+}
+
+static int
+preserve_iwmmxt_context(void *iwmmxt_save_area)
+{
+	int err = 0;
+
+	/* the iWMMXt context must be 64 bit aligned */
+	long *iwmmxt_storage = (long *)(((long)iwmmxt_save_area + 4) & ~7);
+
+again:
+	__put_user_error(IWMMXT_MAGIC0, iwmmxt_storage+0, err);
+	__put_user_error(IWMMXT_MAGIC1, iwmmxt_storage+1, err);
+	/*
+	 * iwmmxt_task_copy() doesn't check user permissions.
+	 * Let's do a dummy write on the upper boundary to ensure
+	 * access to user mem is OK all way up.
+	 */
+	__put_user_error(0, iwmmxt_storage+IWMMXT_STORAGE_SIZE/4-1, err);
+	if (!err) {
+		/* Let's make sure the user mapping won't disappear under us */
+		struct mm_struct *mm = current->mm;
+		unsigned long addr = (unsigned long)iwmmxt_storage;
+		spin_lock(&mm->page_table_lock);
+		if ( !page_present(mm, addr, 1) ||
+		     !page_present(mm, addr+IWMMXT_STORAGE_SIZE-1, 1) ) {
+			/* our user area has gone before grabbing the lock */
+			spin_unlock(&mm->page_table_lock);
+			goto again;
+		}
+		iwmmxt_task_copy(current_thread_info(), iwmmxt_storage+2);
+		spin_unlock(&mm->page_table_lock);
+		return 0;
+	}
+	return err;
+}
+
+static int
+restore_iwmmxt_context(void *iwmmxt_save_area)
+{
+	int err = 0;
+	long *iwmmxt_storage, magic0, magic1, dummy;
+
+	/* the iWMMXt context is 64 bit aligned */
+	iwmmxt_storage = (long *)(((long)iwmmxt_save_area + 4) & ~7);
+
+	/*
+	 * Validate iWMMXt context signature.
+	 * Also, iwmmxt_task_restore() doesn't check user permissions.
+	 * Let's do a dummy write on the upper boundary to ensure
+	 * access to user mem is OK all way up.
+	 */
+again:
+	__get_user_error(magic0, iwmmxt_storage+0, err);
+	__get_user_error(magic1, iwmmxt_storage+1, err);
+	if (!err && magic0 == IWMMXT_MAGIC0 && magic1 == IWMMXT_MAGIC1 &&
+	    !__get_user(dummy, iwmmxt_storage+IWMMXT_STORAGE_SIZE/4-1)) {
+		/* Let's make sure the user mapping won't disappear under us */
+		struct mm_struct *mm = current->mm;
+		unsigned long addr = (unsigned long)iwmmxt_storage;
+		spin_lock(&mm->page_table_lock);
+		if ( !page_present(mm, addr, 0) ||
+		     !page_present(mm, addr+IWMMXT_STORAGE_SIZE-1, 0) ) {
+			/* our user area has gone before grabbing the lock */
+			spin_unlock(&mm->page_table_lock);
+			goto again;
+		}
+		iwmmxt_task_restore(current_thread_info(), iwmmxt_storage+2);
+		spin_unlock(&mm->page_table_lock);
+		return 0;
+	}
+	return -1;
+}
+
+#endif
+
 static int
 restore_sigcontext(struct pt_regs *regs, struct sigcontext __user *sc)
 {
@@ -208,6 +302,11 @@
 	if (restore_sigcontext(regs, &frame->sc))
 		goto badframe;
 
+#ifdef CONFIG_IWMMXT
+	if (test_thread_flag(TIF_USING_IWMMXT) && restore_iwmmxt_context(frame+1))
+		goto badframe;
+#endif
+
 	/* Send SIGTRAP if we're single-stepping */
 	if (current->ptrace & PT_SINGLESTEP) {
 		ptrace_cancel_bpt(current);
@@ -256,6 +355,11 @@
 	if (do_sigaltstack(&frame->uc.uc_stack, NULL, regs->ARM_sp) == -EFAULT)
 		goto badframe;
 
+#ifdef CONFIG_IWMMXT
+	if (test_thread_flag(TIF_USING_IWMMXT) && restore_iwmmxt_context(frame+1))
+		goto badframe;
+#endif
+
 	/* Send SIGTRAP if we're single-stepping */
 	if (current->ptrace & PT_SINGLESTEP) {
 		ptrace_cancel_bpt(current);
@@ -305,6 +409,12 @@
 get_sigframe(struct k_sigaction *ka, struct pt_regs *regs, int framesize)
 {
 	unsigned long sp = regs->ARM_sp;
+	void __user *frame;
+
+#ifdef CONFIG_IWMMXT
+	if (test_thread_flag(TIF_USING_IWMMXT))
+		framesize = (framesize + 4 + IWMMXT_STORAGE_SIZE) & ~7;
+#endif
 
 	/*
 	 * This is the X/Open sanctioned signal stack switching.
@@ -315,7 +425,15 @@
 	/*
 	 * ATPCS B01 mandates 8-byte alignment
 	 */
-	return (void __user *)((sp - framesize) & ~7);
+	frame = (void __user *)((sp - framesize) & ~7);
+
+	/*
+	 * Check that we can actually write to the signal frame.
+	 */
+	if (!access_ok(VERIFY_WRITE, frame, framesize))
+		frame = NULL;
+
+	return frame;
 }
 
 static int
@@ -384,7 +502,7 @@
 	struct sigframe __user *frame = get_sigframe(ka, regs, sizeof(*frame));
 	int err = 0;
 
-	if (!access_ok(VERIFY_WRITE, frame, sizeof (*frame)))
+	if (!frame)
 		return 1;
 
 	err |= setup_sigcontext(&frame->sc, /*&frame->fpstate,*/ regs, set->sig[0]);
@@ -394,6 +512,11 @@
 				      sizeof(frame->extramask));
 	}
 
+#ifdef CONFIG_IWMMXT
+	if (test_thread_flag(TIF_USING_IWMMXT))
+		err |= preserve_iwmmxt_context(frame+1);
+#endif
+
 	if (err == 0)
 		err = setup_return(regs, ka, &frame->retcode, frame, usig);
 
@@ -408,7 +531,7 @@
 	stack_t stack;
 	int err = 0;
 
-	if (!access_ok(VERIFY_WRITE, frame, sizeof (*frame)))
+	if (!frame)
 		return 1;
 
 	__put_user_error(&frame->info, &frame->pinfo, err);
@@ -428,6 +551,11 @@
 				regs, set->sig[0]);
 	err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set));
 
+#ifdef CONFIG_IWMMXT
+	if (test_thread_flag(TIF_USING_IWMMXT))
+		err |= preserve_iwmmxt_context(frame+1);
+#endif
+
 	if (err == 0)
 		err = setup_return(regs, ka, &frame->retcode, frame, usig);
 
@@ -454,12 +582,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;
 
@@ -514,15 +642,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);
 }
 
 /*
@@ -536,6 +659,7 @@
  */
 static int do_signal(sigset_t *oldset, struct pt_regs *regs, int syscall)
 {
+	struct k_sigaction ka;
 	siginfo_t info;
 	int signr;
 
@@ -556,9 +680,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-10-18 14:56:17 -07:00
+++ b/arch/arm/kernel/sys_arm.c	2004-10-18 14:56:17 -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-10-18 14:56:48 -07:00
+++ b/arch/arm/kernel/time.c	2004-10-18 14:56:48 -07:00
@@ -33,7 +33,7 @@
 #include <asm/io.h>
 #include <asm/irq.h>
 #include <asm/leds.h>
-
+#include <asm/thread_info.h>
 #include <asm/mach/time.h>
 
 u64 jiffies_64 = INITIAL_JIFFIES;
@@ -52,6 +52,20 @@
 /* change this if you have some constant time drift */
 #define USECS_PER_JIFFY	(1000000/HZ)
 
+#ifdef CONFIG_SMP
+unsigned long profile_pc(struct pt_regs *regs)
+{
+	unsigned long fp, pc = instruction_pointer(regs);
+
+	if (in_lock_functions(pc)) {
+		fp = thread_saved_fp(current);
+		pc = pc_pointer(((unsigned long *)fp)[-1]);
+	}
+
+	return pc;
+}
+EXPORT_SYMBOL(profile_pc);
+#endif
 
 /*
  * hook for setting the RTC's idea of the current time.
@@ -79,31 +93,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;
 
 /*
@@ -315,9 +304,42 @@
 
 EXPORT_SYMBOL(do_settimeofday);
 
+/**
+ * save_time_delta - Save the offset between system time and RTC time
+ * @delta: pointer to timespec to store delta
+ * @rtc: pointer to timespec for current RTC time
+ *
+ * Return a delta between the system time and the RTC time, such
+ * that system time can be restored later with restore_time_delta()
+ */
+void save_time_delta(struct timespec *delta, struct timespec *rtc)
+{
+	set_normalized_timespec(delta,
+				xtime.tv_sec - rtc->tv_sec,
+				xtime.tv_nsec - rtc->tv_nsec);
+}
+EXPORT_SYMBOL(save_time_delta);
+
+/**
+ * restore_time_delta - Restore the current system time
+ * @delta: delta returned by save_time_delta()
+ * @rtc: pointer to timespec for current RTC time
+ */
+void restore_time_delta(struct timespec *delta, struct timespec *rtc)
+{
+	struct timespec ts;
+
+	set_normalized_timespec(&ts,
+				delta->tv_sec + rtc->tv_sec,
+				delta->tv_nsec + rtc->tv_nsec);
+
+	do_settimeofday(&ts);
+}
+EXPORT_SYMBOL(restore_time_delta);
+
 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/traps.c b/arch/arm/kernel/traps.c
--- a/arch/arm/kernel/traps.c	2004-10-18 14:56:29 -07:00
+++ b/arch/arm/kernel/traps.c	2004-10-18 14:56:29 -07:00
@@ -381,7 +381,7 @@
 {
 	struct vm_area_struct *vma;
 
-	if (end < start)
+	if (end < start || flags)
 		return;
 
 	vma = find_vma(current->active_mm, start);
@@ -391,7 +391,7 @@
 		if (end > vma->vm_end)
 			end = vma->vm_end;
 
-		flush_cache_range(vma, start, end);
+		flush_cache_user_range(vma, start, end);
 	}
 }
 
@@ -562,7 +562,7 @@
 	printk("Division by zero in kernel.\n");
 	dump_stack();
 }
-EXPORT_SYMBOL_NOVERS(__div0);
+EXPORT_SYMBOL(__div0);
 
 void abort(void)
 {
diff -Nru a/arch/arm/kernel/vmlinux.lds.S b/arch/arm/kernel/vmlinux.lds.S
--- a/arch/arm/kernel/vmlinux.lds.S	2004-10-18 14:56:28 -07:00
+++ b/arch/arm/kernel/vmlinux.lds.S	2004-10-18 14:56:28 -07:00
@@ -38,9 +38,6 @@
 		__early_begin = .;
 			*(__early_param)
 		__early_end = .;
-		__start___param = .;
-			*(__param)
-		__stop___param = .;
 		__initcall_start = .;
 			*(.initcall1.init)
 			*(.initcall2.init)
@@ -74,6 +71,7 @@
 		_text = .;		/* Text and read-only data	*/
 			*(.text)
 			SCHED_TEXT
+			LOCK_TEXT
 			*(.fixup)
 			*(.gnu.warning)
 			*(.rodata)
diff -Nru a/arch/arm/lib/getuser.S b/arch/arm/lib/getuser.S
--- a/arch/arm/lib/getuser.S	2004-10-18 14:57:05 -07:00
+++ b/arch/arm/lib/getuser.S	2004-10-18 14:57:05 -07:00
@@ -32,59 +32,34 @@
 
 	.global	__get_user_1
 __get_user_1:
-	bic	r1, sp, #0x1f00
-	bic	r1, r1, #0x00ff
-	ldr	r1, [r1, #TI_ADDR_LIMIT]
-	sub	r1, r1, #1
-	cmp	r0, r1
-1:	ldrlsbt	r1, [r0]
-	movls	r0, #0
-	movls	pc, lr
-	b	__get_user_bad
+1:	ldrbt	r1, [r0]
+	mov	r0, #0
+	mov	pc, lr
 
 	.global	__get_user_2
 __get_user_2:
-	bic	r2, sp, #0x1f00
-	bic	r2, r2, #0x00ff
-	ldr	r2, [r2, #TI_ADDR_LIMIT]
-	sub	r2, r2, #2
-	cmp	r0, r2
-2:	ldrlsbt	r1, [r0], #1
-3:	ldrlsbt	r2, [r0]
+2:	ldrbt	r1, [r0], #1
+3:	ldrbt	r2, [r0]
 #ifndef __ARMEB__
-	orrls	r1, r1, r2, lsl #8
+	orr	r1, r1, r2, lsl #8
 #else
-	orrls	r1, r2, r1, lsl #8
+	orr	r1, r2, r1, lsl #8
 #endif
-	movls	r0, #0
-	movls	pc, lr
-	b	__get_user_bad
+	mov	r0, #0
+	mov	pc, lr
 
 	.global	__get_user_4
 __get_user_4:
-	bic	r1, sp, #0x1f00
-	bic	r1, r1, #0x00ff
-	ldr	r1, [r1, #TI_ADDR_LIMIT]
-	sub	r1, r1, #4
-	cmp	r0, r1
-4:	ldrlst	r1, [r0]
-	movls	r0, #0
-	movls	pc, lr
-	b	__get_user_bad
+4:	ldrt	r1, [r0]
+	mov	r0, #0
+	mov	pc, lr
 
 	.global	__get_user_8
 __get_user_8:
-	bic	r2, sp, #0x1f00
-	bic	r2, r2, #0x00ff
-	ldr	r2, [r2, #TI_ADDR_LIMIT]
-	sub	r2, r2, #8
-	cmp	r0, r2
-5:	ldrlst	r1, [r0], #4
-6:	ldrlst	r2, [r0]
-	movls	r0, #0
-	movls	pc, lr
-
-	/* fall through */
+5:	ldrt	r1, [r0], #4
+6:	ldrt	r2, [r0]
+	mov	r0, #0
+	mov	pc, lr
 
 __get_user_bad_8:
 	mov	r2, #0
diff -Nru a/arch/arm/lib/putuser.S b/arch/arm/lib/putuser.S
--- a/arch/arm/lib/putuser.S	2004-10-18 14:57:03 -07:00
+++ b/arch/arm/lib/putuser.S	2004-10-18 14:57:03 -07:00
@@ -32,60 +32,35 @@
 
 	.global	__put_user_1
 __put_user_1:
-	bic	ip, sp, #0x1f00
-	bic	ip, ip, #0x00ff
-	ldr	ip, [ip, #TI_ADDR_LIMIT]
-	sub	ip, ip, #1
-	cmp	r0, ip
-1:	strlsbt	r1, [r0]
-	movls	r0, #0
-	movls	pc, lr
-	b	__put_user_bad
+1:	strbt	r1, [r0]
+	mov	r0, #0
+	mov	pc, lr
 
 	.global	__put_user_2
 __put_user_2:
-	bic	ip, sp, #0x1f00
-	bic	ip, ip, #0x00ff
-	ldr	ip, [ip, #TI_ADDR_LIMIT]
-	sub	ip, ip, #2
-	cmp	r0, ip
-	movls	ip, r1, lsr #8
+	mov	ip, r1, lsr #8
 #ifndef __ARMEB__
-2:	strlsbt	r1, [r0], #1
-3:	strlsbt	ip, [r0]
+2:	strbt	r1, [r0], #1
+3:	strbt	ip, [r0]
 #else
-2:	strlsbt	ip, [r0], #1
-3:	strlsbt	r1, [r0]
+2:	strbt	ip, [r0], #1
+3:	strbt	r1, [r0]
 #endif
-	movls	r0, #0
-	movls	pc, lr
-	b	__put_user_bad
+	mov	r0, #0
+	mov	pc, lr
 
 	.global	__put_user_4
 __put_user_4:
-	bic	ip, sp, #0x1f00
-	bic	ip, ip, #0x00ff
-	ldr	ip, [ip, #TI_ADDR_LIMIT]
-	sub	ip, ip, #4
-	cmp	r0, ip
-4:	strlst	r1, [r0]
-	movls	r0, #0
-	movls	pc, lr
-	b	__put_user_bad
+4:	strt	r1, [r0]
+	mov	r0, #0
+	mov	pc, lr
 
 	.global	__put_user_8
 __put_user_8:
-	bic	ip, sp, #0x1f00
-	bic	ip, ip, #0x00ff
-	ldr	ip, [ip, #TI_ADDR_LIMIT]
-	sub	ip, ip, #8
-	cmp	r0, ip
-5:	strlst	r1, [r0], #4
-6:	strlst	r2, [r0]
-	movls	r0, #0
-	movls	pc, lr
-
-	/* fall through */
+5:	strt	r1, [r0], #4
+6:	strt	r2, [r0]
+	mov	r0, #0
+	mov	pc, lr
 
 __put_user_bad:
 	mov	r0, #-EFAULT
diff -Nru a/arch/arm/mach-h720x/Kconfig b/arch/arm/mach-h720x/Kconfig
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/arch/arm/mach-h720x/Kconfig	2004-10-18 14:57:21 -07:00
@@ -0,0 +1,27 @@
+menu "h720x Implementations"
+
+config ARCH_H7201
+	bool "gms30c7201"
+	depends on ARCH_H720X
+	select CPU_H7201
+	help
+	  Say Y here if you are using the Hynix GMS30C7201 Reference Board
+
+config ARCH_H7202
+	bool "hms30c7202"
+	select CPU_H7202
+	depends on ARCH_H720X
+	help
+	  Say Y here if you are using the Hynix HMS30C7202 Reference Board
+
+endmenu
+
+config CPU_H7201
+	bool
+	help
+	  Select code specific to h7201 variants
+
+config CPU_H7202
+	bool
+	help
+	  Select code specific to h7202 variants
diff -Nru a/arch/arm/mach-h720x/Makefile b/arch/arm/mach-h720x/Makefile
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/arch/arm/mach-h720x/Makefile	2004-10-18 14:57:24 -07:00
@@ -0,0 +1,16 @@
+#
+# Makefile for the linux kernel.
+#
+
+# Common support
+obj-y := common.o
+obj-m :=
+obj-n :=
+obj-  :=
+
+# Specific board support
+
+obj-$(CONFIG_ARCH_H7201)		+= h7201-eval.o
+obj-$(CONFIG_ARCH_H7202)		+= h7202-eval.o
+obj-$(CONFIG_CPU_H7201) 		+= cpu-h7201.o
+obj-$(CONFIG_CPU_H7202) 		+= cpu-h7202.o
diff -Nru a/arch/arm/mach-h720x/common.c b/arch/arm/mach-h720x/common.c
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/arch/arm/mach-h720x/common.c	2004-10-18 14:57:21 -07:00
@@ -0,0 +1,247 @@
+/*
+ * linux/arch/arm/mach-h720x/common.c
+ *
+ * Copyright (C) 2003 Thomas Gleixner <tglx@linutronix.de>
+ *               2003 Robert Schwebel <r.schwebel@pengutronix.de>
+ *               2004 Sascha Hauer    <s.hauer@pengutronix.de>
+ *
+ * common stuff for Hynix h720x processors
+ *
+ * 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/sched.h>
+#include <linux/slab.h>
+#include <linux/mman.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+
+#include <asm/page.h>
+#include <asm/pgtable.h>
+#include <asm/dma.h>
+#include <asm/io.h>
+#include <asm/hardware.h>
+#include <asm/irq.h>
+#include <asm/mach/irq.h>
+#include <asm/mach/map.h>
+#include <asm/arch/irqs.h>
+
+#include <asm/mach/dma.h>
+
+#if 0
+#define IRQDBG(args...) printk(args)
+#else
+#define IRQDBG(args...) do {} while(0)
+#endif
+
+void __init arch_dma_init(dma_t *dma)
+{
+}
+
+/*
+ * Return usecs since last timer reload
+ * (timercount * (usecs perjiffie)) / (ticks per jiffie)
+ */
+unsigned long h720x_gettimeoffset(void)
+{
+	return (CPU_REG (TIMER_VIRT, TM0_COUNT) * tick_usec) / LATCH;
+}
+
+/*
+ * mask Global irq's
+ */
+static void mask_global_irq (unsigned int irq )
+{
+	CPU_REG (IRQC_VIRT, IRQC_IER) &= ~(1 << irq);
+}
+
+/*
+ * unmask Global irq's
+ */
+static void unmask_global_irq (unsigned int irq )
+{
+	CPU_REG (IRQC_VIRT, IRQC_IER) |= (1 << irq);
+}
+
+
+/*
+ * ack GPIO irq's
+ * Ack only for edge triggered int's valid
+ */
+static void inline ack_gpio_irq(u32 irq)
+{
+	u32 reg_base = GPIO_VIRT(IRQ_TO_REGNO(irq));
+	u32 bit = IRQ_TO_BIT(irq);
+	if ( (CPU_REG (reg_base, GPIO_EDGE) & bit))
+		CPU_REG (reg_base, GPIO_CLR) = bit;
+}
+
+/*
+ * mask GPIO irq's
+ */
+static void inline mask_gpio_irq(u32 irq)
+{
+	u32 reg_base = GPIO_VIRT(IRQ_TO_REGNO(irq));
+	u32 bit = IRQ_TO_BIT(irq);
+	CPU_REG (reg_base, GPIO_MASK) &= ~bit;
+}
+
+/*
+ * unmask GPIO irq's
+ */
+static void inline unmask_gpio_irq(u32 irq)
+{
+	u32 reg_base = GPIO_VIRT(IRQ_TO_REGNO(irq));
+	u32 bit = IRQ_TO_BIT(irq);
+	CPU_REG (reg_base, GPIO_MASK) |= bit;
+}
+
+static void
+h720x_gpio_handler(unsigned int mask, unsigned int irq,
+                 struct irqdesc *desc, struct pt_regs *regs)
+{
+	IRQDBG("%s irq: %d\n",__FUNCTION__,irq);
+	desc = irq_desc + irq;
+	while (mask) {
+		if (mask & 1) {
+			IRQDBG("handling irq %d\n", irq);
+			desc->handle(irq, desc, regs);
+		}
+		irq++;
+		desc++;
+		mask >>= 1;
+	}
+}
+
+static void
+h720x_gpioa_demux_handler(unsigned int irq_unused, struct irqdesc *desc,
+			struct pt_regs *regs)
+{
+	unsigned int mask, irq;
+
+	mask = CPU_REG(GPIO_A_VIRT,GPIO_STAT);
+	irq = IRQ_CHAINED_GPIOA(0);
+	IRQDBG("%s mask: 0x%08x irq: %d\n",__FUNCTION__,mask,irq);
+	h720x_gpio_handler(mask, irq, desc, regs);
+}
+
+static void
+h720x_gpiob_demux_handler(unsigned int irq_unused, struct irqdesc *desc,
+			struct pt_regs *regs)
+{
+	unsigned int mask, irq;
+	mask = CPU_REG(GPIO_B_VIRT,GPIO_STAT);
+	irq = IRQ_CHAINED_GPIOB(0);
+	IRQDBG("%s mask: 0x%08x irq: %d\n",__FUNCTION__,mask,irq);
+	h720x_gpio_handler(mask, irq, desc, regs);
+}
+
+static void
+h720x_gpioc_demux_handler(unsigned int irq_unused, struct irqdesc *desc,
+			struct pt_regs *regs)
+{
+	unsigned int mask, irq;
+
+	mask = CPU_REG(GPIO_C_VIRT,GPIO_STAT);
+	irq = IRQ_CHAINED_GPIOC(0);
+	IRQDBG("%s mask: 0x%08x irq: %d\n",__FUNCTION__,mask,irq);
+	h720x_gpio_handler(mask, irq, desc, regs);
+}
+
+static void
+h720x_gpiod_demux_handler(unsigned int irq_unused, struct irqdesc *desc,
+			struct pt_regs *regs)
+{
+	unsigned int mask, irq;
+
+	mask = CPU_REG(GPIO_D_VIRT,GPIO_STAT);
+	irq = IRQ_CHAINED_GPIOD(0);
+	IRQDBG("%s mask: 0x%08x irq: %d\n",__FUNCTION__,mask,irq);
+	h720x_gpio_handler(mask, irq, desc, regs);
+}
+
+#ifdef CONFIG_CPU_H7202
+static void
+h720x_gpioe_demux_handler(unsigned int irq_unused, struct irqdesc *desc,
+			struct pt_regs *regs)
+{
+	unsigned int mask, irq;
+
+	mask = CPU_REG(GPIO_E_VIRT,GPIO_STAT);
+	irq = IRQ_CHAINED_GPIOE(0);
+	IRQDBG("%s mask: 0x%08x irq: %d\n",__FUNCTION__,mask,irq);
+	h720x_gpio_handler(mask, irq, desc, regs);
+}
+#endif
+
+static struct irqchip h720x_global_chip = {
+	.ack = mask_global_irq,
+	.mask = mask_global_irq,
+	.unmask = unmask_global_irq,
+};
+
+static struct irqchip h720x_gpio_chip = {
+	.ack = ack_gpio_irq,
+	.mask = mask_gpio_irq,
+	.unmask = unmask_gpio_irq,
+};
+
+/*
+ * Initialize IRQ's, mask all, enable multiplexed irq's
+ */
+void __init h720x_init_irq (void)
+{
+	int 	irq;
+
+	/* Mask global irq's */
+	CPU_REG (IRQC_VIRT, IRQC_IER) = 0x0;
+
+	/* Mask all multiplexed irq's */
+	CPU_REG (GPIO_A_VIRT, GPIO_MASK) = 0x0;
+	CPU_REG (GPIO_B_VIRT, GPIO_MASK) = 0x0;
+	CPU_REG (GPIO_C_VIRT, GPIO_MASK) = 0x0;
+	CPU_REG (GPIO_D_VIRT, GPIO_MASK) = 0x0;
+
+	/* Initialize global IRQ's, fast path */
+	for (irq = 0; irq < NR_GLBL_IRQS; irq++) {
+		set_irq_chip(irq, &h720x_global_chip);
+		set_irq_handler(irq, do_level_IRQ);
+		set_irq_flags(irq, IRQF_VALID | IRQF_PROBE);
+	}
+
+	/* Initialize multiplexed IRQ's, slow path */
+	for (irq = IRQ_CHAINED_GPIOA(0) ; irq <= IRQ_CHAINED_GPIOD(31); irq++) {
+		set_irq_chip(irq, &h720x_gpio_chip);
+		set_irq_handler(irq, do_edge_IRQ);
+		set_irq_flags(irq, IRQF_VALID );
+	}
+	set_irq_chained_handler(IRQ_GPIOA, h720x_gpioa_demux_handler);
+	set_irq_chained_handler(IRQ_GPIOB, h720x_gpiob_demux_handler);
+	set_irq_chained_handler(IRQ_GPIOC, h720x_gpioc_demux_handler);
+	set_irq_chained_handler(IRQ_GPIOD, h720x_gpiod_demux_handler);
+
+#ifdef CONFIG_CPU_H7202
+	for (irq = IRQ_CHAINED_GPIOE(0) ; irq <= IRQ_CHAINED_GPIOE(31); irq++) {
+		set_irq_chip(irq, &h720x_gpio_chip);
+		set_irq_handler(irq, do_edge_IRQ);
+		set_irq_flags(irq, IRQF_VALID );
+	}
+	set_irq_chained_handler(IRQ_GPIOE, h720x_gpioe_demux_handler);
+#endif
+
+	/* Enable multiplexed irq's */
+	CPU_REG (IRQC_VIRT, IRQC_IER) = IRQ_ENA_MUX;
+}
+
+static struct map_desc h720x_io_desc[] __initdata = {
+	{ IO_VIRT, IO_PHYS, IO_SIZE, MT_DEVICE },
+};
+
+/* Initialize io tables */
+void __init h720x_map_io(void)
+{
+	iotable_init(h720x_io_desc,ARRAY_SIZE(h720x_io_desc));
+}
diff -Nru a/arch/arm/mach-h720x/cpu-h7201.c b/arch/arm/mach-h720x/cpu-h7201.c
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/arch/arm/mach-h720x/cpu-h7201.c	2004-10-18 14:57:21 -07:00
@@ -0,0 +1,59 @@
+/*
+ * linux/arch/arm/mach-h720x/cpu-h7201.c
+ *
+ * Copyright (C) 2003 Thomas Gleixner <tglx@linutronix.de>
+ *               2003 Robert Schwebel <r.schwebel@pengutronix.de>
+ *               2004 Sascha Hauer    <s.hauer@pengutronix.de>
+ *
+ * processor specific stuff for the Hynix h7201
+ *
+ * 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/init.h>
+#include <linux/interrupt.h>
+#include <linux/module.h>
+#include <asm/types.h>
+#include <asm/hardware.h>
+#include <asm/irq.h>
+#include <asm/arch/irqs.h>
+#include <asm/mach/irq.h>
+#include <asm/mach/time.h>
+
+extern unsigned long h720x_gettimeoffset(void);
+extern void __init h720x_init_irq (void);
+
+/*
+ * Timer interrupt handler
+ */
+static irqreturn_t
+h7201_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+{
+	CPU_REG (TIMER_VIRT, TIMER_TOPSTAT);
+	timer_tick(regs);
+	return IRQ_HANDLED;
+}
+
+static struct irqaction h7201_timer_irq = {
+	.name		= "h7201 Timer Tick",
+	.flags		= SA_INTERRUPT,
+	.handler	= h7201_timer_interrupt
+};
+
+/*
+ * Setup TIMER0 as system timer
+ */
+void __init h7201_init_time(void)
+{
+	gettimeoffset = h720x_gettimeoffset;
+
+	CPU_REG (TIMER_VIRT, TM0_PERIOD) = LATCH;
+	CPU_REG (TIMER_VIRT, TM0_CTRL) = TM_RESET;
+	CPU_REG (TIMER_VIRT, TM0_CTRL) = TM_REPEAT | TM_START;
+	CPU_REG (TIMER_VIRT, TIMER_TOPCTRL) = ENABLE_TM0_INTR | TIMER_ENABLE_BIT;
+
+	setup_irq(IRQ_TIMER0, &h7201_timer_irq);
+}
diff -Nru a/arch/arm/mach-h720x/cpu-h7202.c b/arch/arm/mach-h720x/cpu-h7202.c
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/arch/arm/mach-h720x/cpu-h7202.c	2004-10-18 14:57:23 -07:00
@@ -0,0 +1,165 @@
+/*
+ * linux/arch/arm/mach-h720x/cpu-h7202.c
+ *
+ * Copyright (C) 2003 Thomas Gleixner <tglx@linutronix.de>
+ *               2003 Robert Schwebel <r.schwebel@pengutronix.de>
+ *               2004 Sascha Hauer    <s.hauer@pengutronix.de>
+ *
+ * processor specific stuff for the Hynix h7201
+ *
+ * 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/init.h>
+#include <linux/interrupt.h>
+#include <linux/module.h>
+#include <asm/types.h>
+#include <asm/hardware.h>
+#include <asm/irq.h>
+#include <asm/arch/irqs.h>
+#include <asm/mach/irq.h>
+#include <asm/mach/time.h>
+#include <linux/device.h>
+
+static struct resource h7202ps2_resources[] = {
+	[0] = {
+		.start	= 0x8002c000,
+		.end	= 0x8002c040,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start	= IRQ_PS2,
+		.end	= IRQ_PS2,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static struct platform_device h7202ps2_device = {
+	.name		= "h7202ps2",
+	.id		= -1,
+	.num_resources	= ARRAY_SIZE(h7202ps2_resources),
+	.resource	= h7202ps2_resources,
+};
+
+static struct platform_device *devices[] __initdata = {
+	&h7202ps2_device,
+};
+
+extern unsigned long h720x_gettimeoffset(void);
+extern void __init h720x_init_irq (void);
+
+/* Although we have two interrupt lines for the timers, we only have one
+ * status register which clears all pending timer interrupts on reading. So
+ * we have to handle all timer interrupts in one place.
+ */
+static void
+h7202_timerx_demux_handler(unsigned int irq_unused, struct irqdesc *desc,
+			struct pt_regs *regs)
+{
+	unsigned int mask, irq;
+
+	mask = CPU_REG (TIMER_VIRT, TIMER_TOPSTAT);
+
+	if ( mask & TSTAT_T0INT ) {
+		timer_tick(regs);
+		if( mask == TSTAT_T0INT )
+			return;
+	}
+
+	mask >>= 1;
+	irq = IRQ_TIMER1;
+	desc = irq_desc + irq;
+	while (mask) {
+		if (mask & 1)
+			desc->handle(irq, desc, regs);
+		irq++;
+		desc++;
+		mask >>= 1;
+	}
+}
+
+/*
+ * Timer interrupt handler
+ */
+static irqreturn_t
+h7202_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+{
+	h7202_timerx_demux_handler(0, NULL, regs);
+	return IRQ_HANDLED;
+}
+
+/*
+ * mask multiplexed timer irq's
+ */
+static void inline mask_timerx_irq (u32 irq)
+{
+	unsigned int bit;
+	bit = 2 << ((irq == IRQ_TIMER64B) ? 4 : (irq - IRQ_TIMER1));
+	CPU_REG (TIMER_VIRT, TIMER_TOPCTRL) &= ~bit;
+}
+
+/*
+ * unmask multiplexed timer irq's
+ */
+static void inline unmask_timerx_irq (u32 irq)
+{
+	unsigned int bit;
+	bit = 2 << ((irq == IRQ_TIMER64B) ? 4 : (irq - IRQ_TIMER1));
+	CPU_REG (TIMER_VIRT, TIMER_TOPCTRL) |= bit;
+}
+
+static struct irqchip h7202_timerx_chip = {
+	.ack = mask_timerx_irq,
+	.mask = mask_timerx_irq,
+	.unmask = unmask_timerx_irq,
+};
+
+static struct irqaction h7202_timer_irq = {
+	.name		= "h7202 Timer Tick",
+	.flags		= SA_INTERRUPT,
+	.handler	= h7202_timer_interrupt
+};
+
+/*
+ * Setup TIMER0 as system timer
+ */
+void __init h7202_init_time(void)
+{
+	gettimeoffset = h720x_gettimeoffset;
+
+	CPU_REG (TIMER_VIRT, TM0_PERIOD) = LATCH;
+	CPU_REG (TIMER_VIRT, TM0_CTRL) = TM_RESET;
+	CPU_REG (TIMER_VIRT, TM0_CTRL) = TM_REPEAT | TM_START;
+	CPU_REG (TIMER_VIRT, TIMER_TOPCTRL) = ENABLE_TM0_INTR | TIMER_ENABLE_BIT;
+
+	setup_irq(IRQ_TIMER0, &h7202_timer_irq);
+}
+
+void __init h7202_init_irq (void)
+{
+	int 	irq;
+
+	CPU_REG (GPIO_E_VIRT, GPIO_MASK) = 0x0;
+
+	for (irq = IRQ_TIMER1;
+	                  irq < IRQ_CHAINED_TIMERX(NR_TIMERX_IRQS); irq++) {
+		mask_timerx_irq(irq);
+		set_irq_chip(irq, &h7202_timerx_chip);
+		set_irq_handler(irq, do_edge_IRQ);
+		set_irq_flags(irq, IRQF_VALID );
+	}
+	set_irq_chained_handler(IRQ_TIMERX, h7202_timerx_demux_handler);
+
+	h720x_init_irq();
+}
+
+void __init init_hw_h7202(void)
+{
+	/* Enable clocks */
+	CPU_REG (PMU_BASE, PMU_PLL_CTRL) |= PLL_2_EN | PLL_1_EN | PLL_3_MUTE;
+
+	(void) platform_add_devices(devices, ARRAY_SIZE(devices));
+}
diff -Nru a/arch/arm/mach-h720x/h7201-eval.c b/arch/arm/mach-h720x/h7201-eval.c
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/arch/arm/mach-h720x/h7201-eval.c	2004-10-18 14:57:23 -07:00
@@ -0,0 +1,42 @@
+/*
+ * linux/arch/arm/mach-h720x/h7201-eval.c
+ *
+ * Copyright (C) 2003 Thomas Gleixner <tglx@linutronix.de>
+ *               2003 Robert Schwebel <r.schwebel@pengutronix.de>
+ *               2004 Sascha Hauer    <s.hauer@pengutronix.de>
+ *
+ * Architecture specific stuff for Hynix GMS30C7201 development board
+ *
+ * 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/init.h>
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/string.h>
+#include <linux/device.h>
+
+#include <asm/setup.h>
+#include <asm/types.h>
+#include <asm/mach-types.h>
+#include <asm/page.h>
+#include <asm/pgtable.h>
+#include <asm/mach/arch.h>
+#include <asm/hardware.h>
+
+extern void h720x_init_irq (void);
+extern void h7201_init_time(void);
+extern void __init h720x_map_io(void);
+
+MACHINE_START(H7201, "Hynix GMS30C7201")
+	MAINTAINER("Robert Schwebel, Pengutronix")
+	BOOT_MEM(0x40000000, 0x80000000, 0xf0000000)
+	BOOT_PARAMS(0xc0001000)
+	MAPIO(h720x_map_io)
+	INITIRQ(h720x_init_irq)
+	INITTIME(h7201_init_time)
+MACHINE_END
diff -Nru a/arch/arm/mach-h720x/h7202-eval.c b/arch/arm/mach-h720x/h7202-eval.c
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/arch/arm/mach-h720x/h7202-eval.c	2004-10-18 14:57:21 -07:00
@@ -0,0 +1,85 @@
+/*
+ * linux/arch/arm/mach-h720x/h7202-eval.c
+ *
+ * Copyright (C) 2003 Thomas Gleixner <tglx@linutronix.de>
+ *               2003 Robert Schwebel <r.schwebel@pengutronix.de>
+ *		 2004 Sascha Hauer <s.hauer@pengutronix.de>
+ *
+ * Architecture specific stuff for Hynix HMS30C7202 development board
+ *
+ * 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/init.h>
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/string.h>
+#include <linux/device.h>
+
+#include <asm/setup.h>
+#include <asm/types.h>
+#include <asm/mach-types.h>
+#include <asm/page.h>
+#include <asm/pgtable.h>
+#include <asm/mach/arch.h>
+#include <asm/hardware.h>
+
+extern void __init init_hw_h7202(void);
+extern void __init h7202_init_irq (void);
+extern void __init h7202_init_time(void);
+extern void __init h720x_map_io(void);
+
+static struct resource cirrus_resources[] = {
+	[0] = {
+		.start	= ETH0_PHYS + 0x300,
+		.end	= ETH0_PHYS + 0x300 + 0x10,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start	= IRQ_CHAINED_GPIOB(8),
+		.end	= IRQ_CHAINED_GPIOB(8),
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static struct platform_device cirrus_device = {
+	.name		= "cirrus-cs89x0",
+	.id		= -1,
+	.num_resources	= ARRAY_SIZE(cirrus_resources),
+	.resource	= cirrus_resources,
+};
+
+static struct platform_device *devices[] __initdata = {
+	&cirrus_device,
+};
+
+/*
+ * Hardware init. This is called early in initcalls
+ * Place pin inits here. So you avoid adding ugly
+ * #ifdef stuff to common drivers.
+ * Use this only, if your bootloader is not able
+ * to initialize the pins proper.
+ */
+static void __init init_eval_h7202(void)
+{
+	init_hw_h7202();
+	(void) platform_add_devices(devices, ARRAY_SIZE(devices));
+
+	/* Enable interrupt on portb bit 8 (ethernet) */
+	CPU_REG (GPIO_B_VIRT, GPIO_POL) &= ~(1 << 8);
+	CPU_REG (GPIO_B_VIRT, GPIO_EN) |= (1 << 8);
+}
+
+MACHINE_START(H7202, "Hynix HMS30C7202")
+	MAINTAINER("Robert Schwebel, Pengutronix")
+	BOOT_MEM(0x40000000, 0x80000000, 0xf0000000)
+	BOOT_PARAMS(0x40000100)
+	MAPIO(h720x_map_io)
+	INITIRQ(h7202_init_irq)
+	INITTIME(h7202_init_time)
+	INIT_MACHINE(init_eval_h7202)
+MACHINE_END
diff -Nru a/arch/arm/mach-imx/Kconfig b/arch/arm/mach-imx/Kconfig
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/arch/arm/mach-imx/Kconfig	2004-10-18 14:57:23 -07:00
@@ -0,0 +1,10 @@
+menu "IMX Implementations"
+	depends on ARCH_IMX
+
+config ARCH_MX1ADS
+	bool "mx1ads"
+	depends on ARCH_IMX
+	help
+	  Say Y here if you are using the Motorola MX1ADS board
+
+endmenu
diff -Nru a/arch/arm/mach-imx/Makefile b/arch/arm/mach-imx/Makefile
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/arch/arm/mach-imx/Makefile	2004-10-18 14:57:24 -07:00
@@ -0,0 +1,19 @@
+#
+# Makefile for the linux kernel.
+#
+# Note! Dependencies are done automagically by 'make dep', which also
+# removes any old dependencies. DON'T put your own dependencies here
+# unless it's something special (ie not a .c file).
+
+# Object file lists.
+
+obj-y			+= irq.o time.o dma.o generic.o
+
+# Specific board support
+obj-$(CONFIG_ARCH_MX1ADS) += mx1ads.o
+
+# Support for blinky lights
+led-y := leds.o
+
+obj-$(CONFIG_LEDS)	+=  $(led-y)
+led-$(CONFIG_ARCH_MX1ADS) += leds-mx1ads.o
diff -Nru a/arch/arm/mach-imx/dma.c b/arch/arm/mach-imx/dma.c
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/arch/arm/mach-imx/dma.c	2004-10-18 14:57:24 -07:00
@@ -0,0 +1,203 @@
+/*
+ *  linux/arch/arm/mach-imx/dma.c
+ *
+ *  imx DMA registration and IRQ dispatching
+ *
+ *  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.
+ *
+ *  03/03/2004 Sascha Hauer <sascha@saschahauer.de>
+ *             initial version heavily inspired by
+ *             linux/arch/arm/mach-pxa/dma.c
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/interrupt.h>
+#include <linux/errno.h>
+
+#include <asm/system.h>
+#include <asm/irq.h>
+#include <asm/hardware.h>
+#include <asm/dma.h>
+
+static struct dma_channel {
+	char *name;
+	void (*irq_handler) (int, void *, struct pt_regs *);
+	void (*err_handler) (int, void *, struct pt_regs *);
+	void *data;
+} dma_channels[11];
+
+/* set err_handler to NULL to have the standard info-only error handler */
+int
+imx_request_dma(char *name, imx_dma_prio prio,
+		void (*irq_handler) (int, void *, struct pt_regs *),
+		void (*err_handler) (int, void *, struct pt_regs *), void *data)
+{
+	unsigned long flags;
+	int i, found = 0;
+
+	/* basic sanity checks */
+	if (!name || !irq_handler)
+		return -EINVAL;
+
+	local_irq_save(flags);
+
+	/* try grabbing a DMA channel with the requested priority */
+	for (i = prio; i < prio + (prio == DMA_PRIO_LOW) ? 8 : 4; i++) {
+		if (!dma_channels[i].name) {
+			found = 1;
+			break;
+		}
+	}
+
+	if (!found) {
+		/* requested prio group is full, try hier priorities */
+		for (i = prio - 1; i >= 0; i--) {
+			if (!dma_channels[i].name) {
+				found = 1;
+				break;
+			}
+		}
+	}
+
+	if (found) {
+		DIMR &= ~(1 << i);
+		dma_channels[i].name = name;
+		dma_channels[i].irq_handler = irq_handler;
+		dma_channels[i].err_handler = err_handler;
+		dma_channels[i].data = data;
+	} else {
+		printk(KERN_WARNING "No more available DMA channels for %s\n",
+		       name);
+		i = -ENODEV;
+	}
+
+	local_irq_restore(flags);
+	return i;
+}
+
+void
+imx_free_dma(int dma_ch)
+{
+	unsigned long flags;
+
+	if (!dma_channels[dma_ch].name) {
+		printk(KERN_CRIT
+		       "%s: trying to free channel %d which is already freed\n",
+		       __FUNCTION__, dma_ch);
+		return;
+	}
+
+	local_irq_save(flags);
+	DIMR &= ~(1 << dma_ch);
+	dma_channels[dma_ch].name = NULL;
+	local_irq_restore(flags);
+}
+
+static irqreturn_t
+dma_err_handler(int irq, void *dev_id, struct pt_regs *regs)
+{
+	int i;
+	struct dma_channel *channel;
+	unsigned int err_mask = DBTOSR | DRTOSR | DSESR | DBOSR;
+
+	for (i = 0; i < 11; i++) {
+		channel = &dma_channels[i];
+
+		if ( (err_mask & 1<<i) && channel->name && channel->err_handler) {
+			channel->err_handler(i, channel->data, regs);
+			continue;
+		}
+
+		if (DBTOSR & (1 << i)) {
+			printk(KERN_WARNING
+			       "Burst timeout on channel %d (%s)\n",
+			       i, channel->name);
+			DBTOSR |= (1 << i);
+		}
+		if (DRTOSR & (1 << i)) {
+			printk(KERN_WARNING
+			       "Request timeout on channel %d (%s)\n",
+			       i, channel->name);
+			DRTOSR |= (1 << i);
+		}
+		if (DSESR & (1 << i)) {
+			printk(KERN_WARNING
+			       "Transfer timeout on channel %d (%s)\n",
+			       i, channel->name);
+			DSESR |= (1 << i);
+		}
+		if (DBOSR & (1 << i)) {
+			printk(KERN_WARNING
+			       "Buffer overflow timeout on channel %d (%s)\n",
+			       i, channel->name);
+			DBOSR |= (1 << i);
+		}
+		DISR |= (1 << i);
+	}
+	return IRQ_HANDLED;
+}
+
+static irqreturn_t
+dma_irq_handler(int irq, void *dev_id, struct pt_regs *regs)
+{
+	int i, disr = DISR;
+
+	for (i = 0; i < 11; i++) {
+		if (disr & (1 << i)) {
+			struct dma_channel *channel = &dma_channels[i];
+			if (channel->name && channel->irq_handler) {
+				channel->irq_handler(i, channel->data, regs);
+			} else {
+				/*
+				 * IRQ for an unregistered DMA channel:
+				 * let's clear the interrupts and disable it.
+				 */
+				printk(KERN_WARNING
+				       "spurious IRQ for DMA channel %d\n", i);
+				DISR |= (1 << i);
+			}
+		}
+	}
+	return IRQ_HANDLED;
+}
+
+static int __init
+imx_dma_init(void)
+{
+	int ret;
+
+	/* reset DMA module */
+	DCR = DCR_DRST;
+
+	ret = request_irq(DMA_INT, dma_irq_handler, 0, "DMA", NULL);
+	if (ret) {
+		printk(KERN_CRIT "Wow!  Can't register IRQ for DMA\n");
+		return ret;
+	}
+
+	ret = request_irq(DMA_ERR, dma_err_handler, 0, "DMA", NULL);
+	if (ret) {
+		printk(KERN_CRIT "Wow!  Can't register ERRIRQ for DMA\n");
+		free_irq(DMA_INT, NULL);
+	}
+
+	/* enable DMA module */
+	DCR = DCR_DEN;
+
+	/* clear all interrupts */
+	DISR = 0x3ff;
+
+	/* enable interrupts */
+	DIMR = 0;
+
+	return ret;
+}
+
+arch_initcall(imx_dma_init);
+
+EXPORT_SYMBOL(imx_request_dma);
+EXPORT_SYMBOL(imx_free_dma);
diff -Nru a/arch/arm/mach-imx/generic.c b/arch/arm/mach-imx/generic.c
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/arch/arm/mach-imx/generic.c	2004-10-18 14:57:24 -07:00
@@ -0,0 +1,274 @@
+/*
+ *  arch/arm/mach-imx/generic.c
+ *
+ *  author: Sascha Hauer
+ *  Created: april 20th, 2004
+ *  Copyright: Synertronixx GmbH
+ *
+ *  Common code for i.MX machines
+ *
+ * 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
+ *
+ */
+#include <linux/device.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <asm/hardware.h>
+
+#include <asm/mach/map.h>
+
+void imx_gpio_mode(int gpio_mode)
+{
+	unsigned int pin = gpio_mode & GPIO_PIN_MASK;
+	unsigned int port = (gpio_mode & GPIO_PORT_MASK) >> 5;
+	unsigned int ocr = (gpio_mode & GPIO_OCR_MASK) >> 10;
+	unsigned int tmp;
+
+	/* Pullup enable */
+	if(gpio_mode & GPIO_PUEN)
+		PUEN(port) |= (1<<pin);
+	else
+		PUEN(port) &= ~(1<<pin);
+
+	/* Data direction */
+	if(gpio_mode & GPIO_OUT)
+		DDIR(port) |= 1<<pin;
+	else
+		DDIR(port) &= ~(1<<pin);
+
+	/* Primary / alternate function */
+	if(gpio_mode & GPIO_AF)
+		GPR(port) |= (1<<pin);
+	else
+		GPR(port) &= ~(1<<pin);
+
+	/* use as gpio? */
+	if( ocr == 3 )
+		GIUS(port) |= (1<<pin);
+	else
+		GIUS(port) &= ~(1<<pin);
+
+	/* Output / input configuration */
+	/* FIXME: I'm not very sure about OCR and ICONF, someone
+	 * should have a look over it
+	 */
+	if(pin<16) {
+		tmp = OCR1(port);
+		tmp &= ~( 3<<(pin*2));
+		tmp |= (ocr << (pin*2));
+		OCR1(port) = tmp;
+
+		if( gpio_mode &	GPIO_AOUT )
+			ICONFA1(port) &= ~( 3<<(pin*2));
+		if( gpio_mode &	GPIO_BOUT )
+			ICONFB1(port) &= ~( 3<<(pin*2));
+	} else {
+		tmp = OCR2(port);
+		tmp &= ~( 3<<((pin-16)*2));
+		tmp |= (ocr << ((pin-16)*2));
+		OCR2(port) = tmp;
+
+		if( gpio_mode &	GPIO_AOUT )
+			ICONFA2(port) &= ~( 3<<((pin-16)*2));
+		if( gpio_mode &	GPIO_BOUT )
+			ICONFB2(port) &= ~( 3<<((pin-16)*2));
+	}
+}
+
+EXPORT_SYMBOL(imx_gpio_mode);
+
+/*
+ *  get the system pll clock in Hz
+ *
+ *                  mfi + mfn / (mfd +1)
+ *  f = 2 * f_ref * --------------------
+ *                        pd + 1
+ */
+static unsigned int imx_decode_pll(unsigned int pll)
+{
+	u32 mfi = (pll >> 10) & 0xf;
+	u32 mfn = pll & 0x3f;
+	u32 mfd = (pll >> 16) & 0x3f;
+	u32 pd =  (pll >> 26) & 0xf;
+	u32 f_ref = (CSCR & CSCR_SYSTEM_SEL) ? 16000000 : (CLK32 * 512);
+
+	mfi = mfi <= 5 ? 5 : mfi;
+
+	return (2 * (f_ref>>10) * ( (mfi<<10) + (mfn<<10) / (mfd+1) )) / (pd+1);
+}
+
+unsigned int imx_get_system_clk(void)
+{
+	return imx_decode_pll(SPCTL0);
+}
+EXPORT_SYMBOL(imx_get_system_clk);
+
+unsigned int imx_get_mcu_clk(void)
+{
+	return imx_decode_pll(MPCTL0);
+}
+EXPORT_SYMBOL(imx_get_mcu_clk);
+
+/*
+ *  get peripheral clock 1 ( UART[12], Timer[12], PWM )
+ */
+unsigned int imx_get_perclk1(void)
+{
+	return imx_get_system_clk() / (((PCDR) & 0xf)+1);
+}
+EXPORT_SYMBOL(imx_get_perclk1);
+
+/*
+ *  get peripheral clock 2 ( LCD, SD, SPI[12] )
+ */
+unsigned int imx_get_perclk2(void)
+{
+	return imx_get_system_clk() / (((PCDR>>4) & 0xf)+1);
+}
+EXPORT_SYMBOL(imx_get_perclk2);
+
+/*
+ *  get peripheral clock 3 ( SSI )
+ */
+unsigned int imx_get_perclk3(void)
+{
+	return imx_get_system_clk() / (((PCDR>>16) & 0x7f)+1);
+}
+EXPORT_SYMBOL(imx_get_perclk3);
+
+/*
+ *  get hclk ( SDRAM, CSI, Memory Stick, I2C, DMA )
+ */
+unsigned int imx_get_hclk(void)
+{
+	return imx_get_system_clk() / (((CSCR>>10) & 0xf)+1);
+}
+EXPORT_SYMBOL(imx_get_hclk);
+
+static struct resource imx_mmc_resources[] = {
+	[0] = {
+		.start	= 0x00214000,
+		.end	= 0x002140FF,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start	= (SDHC_INT),
+		.end	= (SDHC_INT),
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static struct platform_device imx_mmc_device = {
+	.name		= "imx-mmc",
+	.id		= 0,
+	.num_resources	= ARRAY_SIZE(imx_mmc_resources),
+	.resource	= imx_mmc_resources,
+};
+
+static struct resource imx_uart1_resources[] = {
+	[0] = {
+		.start	= 0x00206000,
+		.end	= 0x002060FF,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start	= (UART1_MINT_RX),
+		.end	= (UART1_MINT_RX),
+		.flags	= IORESOURCE_IRQ,
+	},
+	[2] = {
+		.start	= (UART1_MINT_TX),
+		.end	= (UART1_MINT_TX),
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static struct platform_device imx_uart1_device = {
+	.name		= "imx-uart",
+	.id		= 0,
+	.num_resources	= ARRAY_SIZE(imx_uart1_resources),
+	.resource	= imx_uart1_resources,
+};
+
+static struct resource imx_uart2_resources[] = {
+	[0] = {
+		.start	= 0x00207000,
+		.end	= 0x002070FF,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start	= (UART2_MINT_RX),
+		.end	= (UART2_MINT_RX),
+		.flags	= IORESOURCE_IRQ,
+	},
+	[2] = {
+		.start	= (UART2_MINT_TX),
+		.end	= (UART2_MINT_TX),
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static struct platform_device imx_uart2_device = {
+	.name		= "imx-uart",
+	.id		= 1,
+	.num_resources	= ARRAY_SIZE(imx_uart2_resources),
+	.resource	= imx_uart2_resources,
+};
+
+static struct resource imxfb_resources[] = {
+	[0] = {
+		.start	= 0x00205000,
+		.end	= 0x002050FF,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start	= LCDC_INT,
+		.end	= LCDC_INT,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static struct platform_device imxfb_device = {
+	.name		= "imx-fb",
+	.id		= 0,
+	.num_resources	= ARRAY_SIZE(imxfb_resources),
+	.resource	= imxfb_resources,
+};
+
+static struct platform_device *devices[] __initdata = {
+	&imx_mmc_device,
+	&imxfb_device,
+	&imx_uart1_device,
+	&imx_uart2_device,
+};
+
+static struct map_desc imx_io_desc[] __initdata = {
+	/* virtual     physical    length      type */
+	{IMX_IO_BASE, IMX_IO_PHYS, IMX_IO_SIZE, MT_DEVICE},
+};
+
+void __init
+imx_map_io(void)
+{
+	iotable_init(imx_io_desc, ARRAY_SIZE(imx_io_desc));
+}
+
+static int __init imx_init(void)
+{
+	return platform_add_devices(devices, ARRAY_SIZE(devices));
+}
+
+subsys_initcall(imx_init);
diff -Nru a/arch/arm/mach-imx/generic.h b/arch/arm/mach-imx/generic.h
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/arch/arm/mach-imx/generic.h	2004-10-18 14:57:23 -07:00
@@ -0,0 +1,14 @@
+/*
+ *  linux/arch/arm/mach-imx/generic.h
+ *
+ * Author:	Sascha Hauer <sascha@saschahauer.de>
+ * Copyright:	Synertronixx GmbH
+ *
+ * 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.
+ */
+
+extern void __init imx_map_io(void);
+extern void __init imx_init_irq(void);
+extern void __init imx_init_time(void);
diff -Nru a/arch/arm/mach-imx/irq.c b/arch/arm/mach-imx/irq.c
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/arch/arm/mach-imx/irq.c	2004-10-18 14:57:24 -07:00
@@ -0,0 +1,252 @@
+/*
+ *  linux/arch/arm/mach-imx/irq.c
+ *
+ *  Copyright (C) 1999 ARM Limited
+ *  Copyright (C) 2002 Shane Nay (shane@minirl.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
+ *
+ *  03/03/2004   Sascha Hauer <sascha@saschahauer.de>
+ *               Copied from the motorola bsp package and added gpio demux
+ *               interrupt handler
+ */
+
+#include <linux/init.h>
+#include <linux/list.h>
+#include <linux/timer.h>
+
+#include <asm/hardware.h>
+#include <asm/irq.h>
+#include <asm/io.h>
+
+#include <asm/mach/irq.h>
+
+/*
+ *
+ * We simply use the ENABLE DISABLE registers inside of the IMX
+ * to turn on/off specific interrupts.  FIXME- We should
+ * also add support for the accelerated interrupt controller
+ * by putting offets to irq jump code in the appropriate
+ * places.
+ *
+ */
+
+#define INTENNUM_OFF              0x8
+#define INTDISNUM_OFF             0xC
+
+#define VA_AITC_BASE              IO_ADDRESS(IMX_AITC_BASE)
+#define IMX_AITC_INTDISNUM       (VA_AITC_BASE + INTDISNUM_OFF)
+#define IMX_AITC_INTENNUM        (VA_AITC_BASE + INTENNUM_OFF)
+
+#if 0
+#define DEBUG_IRQ(fmt...)	printk(fmt)
+#else
+#define DEBUG_IRQ(fmt...)	do { } while (0)
+#endif
+
+static void
+imx_mask_irq(unsigned int irq)
+{
+	__raw_writel(irq, IMX_AITC_INTDISNUM);
+}
+
+static void
+imx_unmask_irq(unsigned int irq)
+{
+	__raw_writel(irq, IMX_AITC_INTENNUM);
+}
+
+static int
+imx_gpio_irq_type(unsigned int _irq, unsigned int type)
+{
+	unsigned int irq_type = 0, irq, reg, bit;
+
+	irq = _irq - IRQ_GPIOA(0);
+	reg = irq >> 5;
+	bit = 1 << (irq % 32);
+
+	if (type == IRQT_PROBE) {
+		/* Don't mess with enabled GPIOs using preconfigured edges or
+		   GPIOs set to alternate function during probe */
+		/* TODO: support probe */
+//              if ((GPIO_IRQ_rising_edge[idx] | GPIO_IRQ_falling_edge[idx]) &
+//                  GPIO_bit(gpio))
+//                      return 0;
+//              if (GAFR(gpio) & (0x3 << (((gpio) & 0xf)*2)))
+//                      return 0;
+//              type = __IRQT_RISEDGE | __IRQT_FALEDGE;
+	}
+
+	GIUS(reg) |= bit;
+	DDIR(reg) &= ~(bit);
+
+	DEBUG_IRQ("setting type of irq %d to ", _irq);
+
+	if (type & __IRQT_RISEDGE) {
+		DEBUG_IRQ("rising edges\n");
+		irq_type = 0x0;
+	}
+	if (type & __IRQT_FALEDGE) {
+		DEBUG_IRQ("falling edges\n");
+		irq_type = 0x1;
+	}
+	if (type & __IRQT_LOWLVL) {
+		DEBUG_IRQ("low level\n");
+		irq_type = 0x3;
+	}
+	if (type & __IRQT_HIGHLVL) {
+		DEBUG_IRQ("high level\n");
+		irq_type = 0x2;
+	}
+
+	if (irq % 32 < 16) {
+		ICR1(reg) = (ICR1(reg) & ~(0x3 << ((irq % 16) * 2))) |
+		    (irq_type << ((irq % 16) * 2));
+	} else {
+		ICR2(reg) = (ICR2(reg) & ~(0x3 << ((irq % 16) * 2))) |
+		    (irq_type << ((irq % 16) * 2));
+	}
+
+	return 0;
+
+}
+
+static void
+imx_gpio_ack_irq(unsigned int irq)
+{
+	DEBUG_IRQ("%s: irq %d\n", __FUNCTION__, irq);
+	ISR(IRQ_TO_REG(irq)) |= 1 << ((irq - IRQ_GPIOA(0)) % 32);
+}
+
+static void
+imx_gpio_mask_irq(unsigned int irq)
+{
+	DEBUG_IRQ("%s: irq %d\n", __FUNCTION__, irq);
+	IMR(IRQ_TO_REG(irq)) &= ~( 1 << ((irq - IRQ_GPIOA(0)) % 32));
+}
+
+static void
+imx_gpio_unmask_irq(unsigned int irq)
+{
+	DEBUG_IRQ("%s: irq %d\n", __FUNCTION__, irq);
+	IMR(IRQ_TO_REG(irq)) |= 1 << ((irq - IRQ_GPIOA(0)) % 32);
+}
+
+static void
+imx_gpio_handler(unsigned int mask, unsigned int irq,
+                 struct irqdesc *desc, struct pt_regs *regs)
+{
+	desc = irq_desc + irq;
+	while (mask) {
+		if (mask & 1) {
+			DEBUG_IRQ("handling irq %d\n", irq);
+			desc->handle(irq, desc, regs);
+		}
+		irq++;
+		desc++;
+		mask >>= 1;
+	}
+}
+
+static void
+imx_gpioa_demux_handler(unsigned int irq_unused, struct irqdesc *desc,
+			struct pt_regs *regs)
+{
+	unsigned int mask, irq;
+
+	mask = ISR(0);
+	irq = IRQ_GPIOA(0);
+	imx_gpio_handler(mask, irq, desc, regs);
+}
+
+static void
+imx_gpiob_demux_handler(unsigned int irq_unused, struct irqdesc *desc,
+			struct pt_regs *regs)
+{
+	unsigned int mask, irq;
+
+	mask = ISR(1);
+	irq = IRQ_GPIOB(0);
+	imx_gpio_handler(mask, irq, desc, regs);
+}
+
+static void
+imx_gpioc_demux_handler(unsigned int irq_unused, struct irqdesc *desc,
+			struct pt_regs *regs)
+{
+	unsigned int mask, irq;
+
+	mask = ISR(2);
+	irq = IRQ_GPIOC(0);
+	imx_gpio_handler(mask, irq, desc, regs);
+}
+
+static void
+imx_gpiod_demux_handler(unsigned int irq_unused, struct irqdesc *desc,
+			struct pt_regs *regs)
+{
+	unsigned int mask, irq;
+
+	mask = ISR(3);
+	irq = IRQ_GPIOD(0);
+	imx_gpio_handler(mask, irq, desc, regs);
+}
+
+static struct irqchip imx_internal_chip = {
+	.ack = imx_mask_irq,
+	.mask = imx_mask_irq,
+	.unmask = imx_unmask_irq,
+};
+
+static struct irqchip imx_gpio_chip = {
+	.ack = imx_gpio_ack_irq,
+	.mask = imx_gpio_mask_irq,
+	.unmask = imx_gpio_unmask_irq,
+	.type = imx_gpio_irq_type,
+};
+
+void __init
+imx_init_irq(void)
+{
+	unsigned int irq;
+
+	DEBUG_IRQ("Initializing imx interrupts\n");
+
+	/* Mask all interrupts initially */
+	IMR(0) = 0;
+	IMR(1) = 0;
+	IMR(2) = 0;
+	IMR(3) = 0;
+
+	for (irq = 0; irq < IMX_IRQS; irq++) {
+		set_irq_chip(irq, &imx_internal_chip);
+		set_irq_handler(irq, do_level_IRQ);
+		set_irq_flags(irq, IRQF_VALID);
+	}
+
+	for (irq = IRQ_GPIOA(0); irq < IRQ_GPIOD(32); irq++) {
+		set_irq_chip(irq, &imx_gpio_chip);
+		set_irq_handler(irq, do_edge_IRQ);
+		set_irq_flags(irq, IRQF_VALID);
+	}
+
+	set_irq_chained_handler(GPIO_INT_PORTA, imx_gpioa_demux_handler);
+	set_irq_chained_handler(GPIO_INT_PORTB, imx_gpiob_demux_handler);
+	set_irq_chained_handler(GPIO_INT_PORTC, imx_gpioc_demux_handler);
+	set_irq_chained_handler(GPIO_INT_PORTD, imx_gpiod_demux_handler);
+
+	/* Disable all interrupts initially. */
+	/* In IMX this is done in the bootloader. */
+}
diff -Nru a/arch/arm/mach-imx/leds-mx1ads.c b/arch/arm/mach-imx/leds-mx1ads.c
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/arch/arm/mach-imx/leds-mx1ads.c	2004-10-18 14:57:23 -07:00
@@ -0,0 +1,54 @@
+/*
+ * linux/arch/arm/mach-imx/leds-mx1ads.c
+ *
+ * Copyright (c) 2004 Sascha Hauer <sascha@saschahauer.de>
+ *
+ * Original (leds-footbridge.c) by Russell King
+ *
+ * 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/kernel.h>
+#include <linux/init.h>
+#include <asm/hardware.h>
+#include <asm/system.h>
+#include <asm/io.h>
+#include <asm/leds.h>
+#include <asm/mach-types.h>
+#include "leds.h"
+
+/*
+ * The MX1ADS Board has only one usable LED,
+ * so select only the timer led or the
+ * cpu usage led
+ */
+void
+mx1ads_leds_event(led_event_t ledevt)
+{
+	unsigned long flags;
+
+	local_irq_save(flags);
+
+	switch (ledevt) {
+#ifdef CONFIG_LEDS_CPU
+	case led_idle_start:
+		DR(0) &= ~(1<<2);
+		break;
+
+	case led_idle_end:
+		DR(0) |= 1<<2;
+		break;
+#endif
+
+#ifdef CONFIG_LEDS_TIMER
+	case led_timer:
+		DR(0) ^= 1<<2;
+#endif
+	default:
+		break;
+	}
+	local_irq_restore(flags);
+}
diff -Nru a/arch/arm/mach-imx/leds.c b/arch/arm/mach-imx/leds.c
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/arch/arm/mach-imx/leds.c	2004-10-18 14:57:21 -07:00
@@ -0,0 +1,31 @@
+/*
+ * linux/arch/arm/mach-imx/leds.h
+ *
+ * Copyright (C) 2004 Sascha Hauer <sascha@saschahauer.de>
+ *
+ *
+ * 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/kernel.h>
+#include <linux/init.h>
+
+#include <asm/leds.h>
+#include <asm/mach-types.h>
+
+#include "leds.h"
+
+static int __init
+leds_init(void)
+{
+	if (machine_is_mx1ads()) {
+		leds_event = mx1ads_leds_event;
+	}
+
+	return 0;
+}
+
+__initcall(leds_init);
diff -Nru a/arch/arm/mach-imx/leds.h b/arch/arm/mach-imx/leds.h
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/arch/arm/mach-imx/leds.h	2004-10-18 14:57:24 -07:00
@@ -0,0 +1,9 @@
+/*
+ * include/asm-arm/arch-imx/leds.h
+ *
+ * Copyright (c) 2004 Sascha Hauer <sascha@saschahauer.de>
+ *
+ * blinky lights for IMX-based systems
+ *
+ */
+extern void mx1ads_leds_event(led_event_t evt);
diff -Nru a/arch/arm/mach-imx/mx1ads.c b/arch/arm/mach-imx/mx1ads.c
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/arch/arm/mach-imx/mx1ads.c	2004-10-18 14:57:24 -07:00
@@ -0,0 +1,88 @@
+/*
+ * arch/arm/mach-imx/mx1ads.c
+ *
+ * Initially based on:
+ *	linux-2.6.7-imx/arch/arm/mach-imx/scb9328.c
+ *	Copyright (c) 2004 Sascha Hauer <sascha@saschahauer.de>
+ *
+ * 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/device.h>
+#include <linux/init.h>
+#include <asm/system.h>
+#include <asm/hardware.h>
+#include <asm/irq.h>
+#include <asm/pgtable.h>
+#include <asm/page.h>
+
+#include <asm/mach/map.h>
+#include <asm/mach-types.h>
+
+#include <asm/mach/arch.h>
+#include <linux/interrupt.h>
+#include "generic.h"
+#include <asm/serial.h>
+
+static struct resource mx1ads_resources[] = {
+	[0] = {
+		.start	= IMX_CS4_VIRT,
+		.end	= IMX_CS4_VIRT + 16,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start	= 13,
+		.end	= 13,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static struct platform_device mx1ads_device = {
+	.name		= "mx1ads",
+	.num_resources	= ARRAY_SIZE(mx1ads_resources),
+	.resource	= mx1ads_resources,
+};
+
+static struct platform_device *devices[] __initdata = {
+	&mx1ads_device,
+};
+
+static void __init
+mx1ads_init(void)
+{
+#ifdef CONFIG_LEDS
+	imx_gpio_mode(GPIO_PORTA | GPIO_OUT | GPIO_GPIO | 2);
+#endif
+	platform_add_devices(devices, ARRAY_SIZE(devices));
+}
+
+static struct map_desc mx1ads_io_desc[] __initdata = {
+	/* virtual     physical    length      type */
+	{IMX_CS0_VIRT, IMX_CS0_PHYS, IMX_CS0_SIZE, MT_DEVICE},
+	{IMX_CS1_VIRT, IMX_CS1_PHYS, IMX_CS1_SIZE, MT_DEVICE},
+	{IMX_CS2_VIRT, IMX_CS2_PHYS, IMX_CS2_SIZE, MT_DEVICE},
+	{IMX_CS3_VIRT, IMX_CS3_PHYS, IMX_CS3_SIZE, MT_DEVICE},
+	{IMX_CS4_VIRT, IMX_CS4_PHYS, IMX_CS4_SIZE, MT_DEVICE},
+	{IMX_CS5_VIRT, IMX_CS5_PHYS, IMX_CS5_SIZE, MT_DEVICE},
+};
+
+static void __init
+mx1ads_map_io(void)
+{
+	imx_map_io();
+	iotable_init(mx1ads_io_desc, ARRAY_SIZE(mx1ads_io_desc));
+}
+
+MACHINE_START(MX1ADS, "Motorola MX1ADS")
+	MAINTAINER("Sascha Hauer, Pengutronix")
+	BOOT_MEM(0x08000000, 0x00200000, 0xe0200000)
+	BOOT_PARAMS(0x08000100)
+	MAPIO(mx1ads_map_io)
+	INITIRQ(imx_init_irq)
+	INITTIME(imx_init_time)
+	INIT_MACHINE(mx1ads_init)
+MACHINE_END
diff -Nru a/arch/arm/mach-imx/time.c b/arch/arm/mach-imx/time.c
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/arch/arm/mach-imx/time.c	2004-10-18 14:57:23 -07:00
@@ -0,0 +1,95 @@
+/*
+ *  linux/arch/arm/mach-imx/time.c
+ *
+ *  Copyright (C) 2000-2001 Deep Blue Solutions
+ *  Copyright (C) 2002 Shane Nay (shane@minirl.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/sched.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/time.h>
+
+#include <asm/hardware.h>
+#include <asm/io.h>
+#include <asm/leds.h>
+#include <asm/irq.h>
+#include <asm/mach/time.h>
+
+/* Use timer 1 as system timer */
+#define TIMER_BASE IMX_TIM1_BASE
+
+/*
+ * Returns number of us since last clock interrupt.  Note that interrupts
+ * will have been disabled by do_gettimeoffset()
+ */
+static unsigned long
+imx_gettimeoffset(void)
+{
+	unsigned long ticks;
+
+	/*
+	 * Get the current number of ticks.  Note that there is a race
+	 * condition between us reading the timer and checking for
+	 * an interrupt.  We get around this by ensuring that the
+	 * counter has not reloaded between our two reads.
+	 */
+	ticks = IMX_TCN(TIMER_BASE);
+
+	/*
+	 * Interrupt pending?  If so, we've reloaded once already.
+	 */
+	if (IMX_TSTAT(TIMER_BASE) & TSTAT_COMP)
+		ticks += LATCH;
+
+	/*
+	 * Convert the ticks to usecs
+	 */
+	return (1000000 / CLK32) * ticks;
+}
+
+/*
+ * IRQ handler for the timer
+ */
+static irqreturn_t
+imx_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+{
+	/* clear the interrupt */
+	if (IMX_TSTAT(TIMER_BASE))
+		IMX_TSTAT(TIMER_BASE) = 0;
+
+	timer_tick(regs);
+	return IRQ_HANDLED;
+}
+
+static struct irqaction imx_timer_irq = {
+	.name		= "i.MX Timer Tick",
+	.flags		= SA_INTERRUPT,
+	.handler	= imx_timer_interrupt
+};
+
+/*
+ * Set up timer interrupt, and return the current time in seconds.
+ */
+void __init
+imx_init_time(void)
+{
+	/*
+	 * Initialise to a known state (all timers off, and timing reset)
+	 */
+	IMX_TCTL(TIMER_BASE) = 0;
+	IMX_TPRER(TIMER_BASE) = 0;
+	IMX_TCMP(TIMER_BASE) = LATCH - 1;
+	IMX_TCTL(TIMER_BASE) = TCTL_CLK_32 | TCTL_IRQEN | TCTL_TEN;
+
+	/*
+	 * Make irqs happen for the system timer
+	 */
+	setup_irq(TIM1_INT, &imx_timer_irq);
+	gettimeoffset = imx_gettimeoffset;
+}
diff -Nru a/arch/arm/mach-integrator/clock.c b/arch/arm/mach-integrator/clock.c
--- a/arch/arm/mach-integrator/clock.c	2004-10-18 14:57:04 -07:00
+++ b/arch/arm/mach-integrator/clock.c	2004-10-18 14:57:04 -07:00
@@ -76,7 +76,10 @@
 
 long clk_round_rate(struct clk *clk, unsigned long rate)
 {
-	return rate;
+	struct icst525_vco vco;
+
+	vco = icst525_khz_to_vco(clk->params, rate / 1000);
+	return icst525_khz(clk->params, vco) * 1000;
 }
 EXPORT_SYMBOL(clk_round_rate);
 
@@ -86,8 +89,8 @@
 	if (clk->setvco) {
 		struct icst525_vco vco;
 
-		vco = icst525_khz_to_vco(clk->params, rate);
-		clk->rate = icst525_khz(clk->params, vco);
+		vco = icst525_khz_to_vco(clk->params, rate / 1000);
+		clk->rate = icst525_khz(clk->params, vco) * 1000;
 
 		printk("Clock %s: setting VCO reg params: S=%d R=%d V=%d\n",
 			clk->name, vco.s, vco.r, vco.v);
diff -Nru a/arch/arm/mach-integrator/cpu.c b/arch/arm/mach-integrator/cpu.c
--- a/arch/arm/mach-integrator/cpu.c	2004-10-18 14:56:31 -07:00
+++ b/arch/arm/mach-integrator/cpu.c	2004-10-18 14:56:31 -07:00
@@ -79,7 +79,7 @@
 				 unsigned int target_freq,
 				 unsigned int relation)
 {
-	unsigned long cpus_allowed;
+	cpumask_t cpus_allowed;
 	int cpu = policy->cpu;
 	struct icst525_vco vco;
 	struct cpufreq_freqs freqs;
@@ -94,7 +94,7 @@
 	 * Bind to the specified CPU.  When this call returns,
 	 * we should be running on the right CPU.
 	 */
-	set_cpus_allowed(current, 1 << cpu);
+	set_cpus_allowed(current, cpumask_of_cpu(cpu));
 	BUG_ON(cpu != smp_processor_id());
 
 	/* get current setting */
@@ -154,14 +154,14 @@
 
 static unsigned int integrator_get(unsigned int cpu)
 {
-	unsigned long cpus_allowed;
+	cpumask_t cpus_allowed;
 	unsigned int current_freq;
 	u_int cm_osc;
 	struct icst525_vco vco;
 
 	cpus_allowed = current->cpus_allowed;
 
-	set_cpus_allowed(current, 1 << cpu);
+	set_cpus_allowed(current, cpumask_of_cpu(cpu));
 	BUG_ON(cpu != smp_processor_id());
 
 	/* detect memory etc. */
diff -Nru a/arch/arm/mach-integrator/impd1.c b/arch/arm/mach-integrator/impd1.c
--- a/arch/arm/mach-integrator/impd1.c	2004-10-18 14:56:28 -07:00
+++ b/arch/arm/mach-integrator/impd1.c	2004-10-18 14:56:28 -07:00
@@ -21,6 +21,7 @@
 #include <asm/io.h>
 #include <asm/hardware/icst525.h>
 #include <asm/hardware/amba.h>
+#include <asm/hardware/amba_clcd.h>
 #include <asm/arch/lm.h>
 #include <asm/arch/impd1.h>
 #include <asm/sizes.h>
@@ -87,10 +88,198 @@
 
 EXPORT_SYMBOL(impd1_tweak_control);
 
+/*
+ * CLCD support
+ */
+#define PANEL		PROSPECTOR
+
+#define LTM10C209		1
+#define PROSPECTOR		2
+#define SVGA			3
+#define VGA			4
+
+#if PANEL == VGA
+#define PANELTYPE	vga
+static struct clcd_panel vga = {
+	.mode		= {
+		.name		= "VGA",
+		.refresh	= 60,
+		.xres		= 640,
+		.yres		= 480,
+		.pixclock	= 39721,
+		.left_margin	= 40,
+		.right_margin	= 24,
+		.upper_margin	= 32,
+		.lower_margin	= 11,
+		.hsync_len	= 96,
+		.vsync_len	= 2,
+		.sync		= 0,
+		.vmode		= FB_VMODE_NONINTERLACED,
+	},
+	.width		= -1,
+	.height		= -1,
+	.tim2		= TIM2_BCD | TIM2_IPC,
+	.cntl		= CNTL_LCDTFT | CNTL_LCDVCOMP(1),
+	.connector	= IMPD1_CTRL_DISP_VGA,
+	.bpp		= 16,
+	.grayscale	= 0,
+};
+
+#elif PANEL == SVGA
+#define PANELTYPE	svga
+static struct clcd_panel svga = {
+	.mode		= {
+		.name		= "SVGA",
+		.refresh	= 0,
+		.xres		= 800,
+		.yres		= 600,
+		.pixclock	= 27778,
+		.left_margin	= 20,
+		.right_margin	= 20,
+		.upper_margin	= 5,
+		.lower_margin	= 5,
+		.hsync_len	= 164,
+		.vsync_len	= 62,
+		.sync		= 0,
+		.vmode		= FB_VMODE_NONINTERLACED,
+	},
+	.width		= -1,
+	.height		= -1,
+	.tim2		= TIM2_BCD,
+	.cntl		= CNTL_LCDTFT | CNTL_LCDVCOMP(1),
+	.connector	= IMPD1_CTRL_DISP_VGA,
+	.bpp		= 16,
+	.grayscale	= 0,
+};
+
+#elif PANEL == PROSPECTOR
+#define PANELTYPE	prospector
+static struct clcd_panel prospector = {
+	.mode		= {
+		.name		= "PROSPECTOR",
+		.refresh	= 0,
+		.xres		= 640,
+		.yres		= 480,
+		.pixclock	= 40000,
+		.left_margin	= 33,
+		.right_margin	= 64,
+		.upper_margin	= 36,
+		.lower_margin	= 7,
+		.hsync_len	= 64,
+		.vsync_len	= 25,
+		.sync		= FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
+		.vmode		= FB_VMODE_NONINTERLACED,
+	},
+	.width		= -1,
+	.height		= -1,
+	.tim2		= TIM2_BCD,
+	.cntl		= CNTL_LCDTFT | CNTL_LCDVCOMP(1),
+	.fixedtimings	= 1,
+	.connector	= IMPD1_CTRL_DISP_LCD,
+	.bpp		= 16,
+	.grayscale	= 0,
+};
+
+#elif PANEL == LTM10C209
+#define PANELTYPE	ltm10c209
+/*
+ * Untested.
+ */
+static struct clcd_panel ltm10c209 = {
+	.mode		= {
+		.name		= "LTM10C209",
+		.refresh	= 0,
+		.xres		= 640,
+		.yres		= 480,
+		.pixclock	= 40000,
+		.left_margin	= 20,
+		.right_margin	= 20,
+		.upper_margin	= 19,
+		.lower_margin	= 19,
+		.hsync_len	= 20,
+		.vsync_len	= 10,
+		.sync		= FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
+		.vmode		= FB_VMODE_NONINTERLACED,
+	},
+	.width		= -1,
+	.height		= -1,
+	.tim2		= TIM2_BCD,
+	.cntl		= CNTL_LCDTFT | CNTL_LCDVCOMP(1),
+	.fixedtimings	= 1,
+	.connector	= IMPD1_CTRL_DISP_LCD,
+	.bpp		= 16,
+	.grayscale	= 0,
+};
+#endif
+
+/*
+ * Disable all display connectors on the interface module.
+ */
+static void impd1fb_clcd_disable(struct clcd_fb *fb)
+{
+	impd1_tweak_control(fb->dev->dev.parent, IMPD1_CTRL_DISP_MASK, 0);
+}
+
+/*
+ * Enable the relevant connector on the interface module.
+ */
+static void impd1fb_clcd_enable(struct clcd_fb *fb)
+{
+	impd1_tweak_control(fb->dev->dev.parent, IMPD1_CTRL_DISP_MASK,
+			fb->panel->connector | IMPD1_CTRL_DISP_ENABLE);
+}
+
+static int impd1fb_clcd_setup(struct clcd_fb *fb)
+{
+	unsigned long framebase = fb->dev->res.start + 0x01000000;
+	unsigned long framesize = SZ_1M;
+	int ret = 0;
+
+	fb->panel = &PANELTYPE;
+
+	if (!request_mem_region(framebase, framesize, "clcd framebuffer")) {
+		printk(KERN_ERR "IM-PD1: unable to reserve framebuffer\n");
+		return -EBUSY;
+	}
+
+	fb->fb.screen_base = ioremap(framebase, framesize);
+	if (!fb->fb.screen_base) {
+		printk(KERN_ERR "IM-PD1: unable to map framebuffer\n");
+		ret = -ENOMEM;
+		goto free_buffer;
+	}
+
+	fb->fb.fix.smem_start	= framebase;
+	fb->fb.fix.smem_len	= framesize;
+
+	return 0;
+
+ free_buffer:
+	release_mem_region(framebase, framesize);
+	return ret;
+}
+
+static void impd1fb_clcd_remove(struct clcd_fb *fb)
+{
+	iounmap(fb->fb.screen_base);
+	release_mem_region(fb->fb.fix.smem_start, fb->fb.fix.smem_len);
+}
+
+static struct clcd_board impd1_clcd_data = {
+	.name		= "IM-PD/1",
+	.check		= clcdfb_check,
+	.decode		= clcdfb_decode,
+	.disable	= impd1fb_clcd_disable,
+	.enable		= impd1fb_clcd_enable,
+	.setup		= impd1fb_clcd_setup,
+	.remove		= impd1fb_clcd_remove,
+};
+
 struct impd1_device {
 	unsigned long	offset;
 	unsigned int	irq[2];
 	unsigned int	id;
+	void		*platform_data;
 };
 
 static struct impd1_device impd1_devs[] = {
@@ -133,6 +322,7 @@
 		.offset	= 0x01000000,
 		.irq	= { 11 },
 		.id	= 0x00041110,
+		.platform_data = &impd1_clcd_data,
 	}
 };
 
@@ -202,6 +392,7 @@
 		d->irq[0]	= dev->irq;
 		d->irq[1]	= dev->irq;
 		d->periphid	= idev->id;
+		d->dev.platform_data = idev->platform_data;
 
 		ret = amba_device_register(d, &dev->resource);
 		if (ret) {
diff -Nru a/arch/arm/mach-integrator/integrator_cp.c b/arch/arm/mach-integrator/integrator_cp.c
--- a/arch/arm/mach-integrator/integrator_cp.c	2004-10-18 14:57:03 -07:00
+++ b/arch/arm/mach-integrator/integrator_cp.c	2004-10-18 14:57:03 -07:00
@@ -12,6 +12,7 @@
 #include <linux/init.h>
 #include <linux/list.h>
 #include <linux/device.h>
+#include <linux/dma-mapping.h>
 #include <linux/slab.h>
 #include <linux/string.h>
 #include <linux/sysdev.h>
@@ -23,8 +24,10 @@
 #include <asm/mach-types.h>
 #include <asm/hardware/amba.h>
 #include <asm/hardware/amba_kmi.h>
+#include <asm/hardware/amba_clcd.h>
 #include <asm/hardware/icst525.h>
 
+#include <asm/arch/cm.h>
 #include <asm/arch/lm.h>
 
 #include <asm/mach/arch.h>
@@ -382,10 +385,83 @@
 	.periphid	= 0,
 };
 
+
+/*
+ * CLCD support
+ */
+static struct clcd_panel vga = {
+	.mode		= {
+		.name		= "VGA",
+		.refresh	= 60,
+		.xres		= 640,
+		.yres		= 480,
+		.pixclock	= 39721,
+		.left_margin	= 40,
+		.right_margin	= 24,
+		.upper_margin	= 32,
+		.lower_margin	= 11,
+		.hsync_len	= 96,
+		.vsync_len	= 2,
+		.sync		= 0,
+		.vmode		= FB_VMODE_NONINTERLACED,
+	},
+	.width		= -1,
+	.height		= -1,
+	.tim2		= TIM2_BCD | TIM2_IPC,
+	.cntl		= CNTL_LCDTFT | CNTL_LCDVCOMP(1),
+	.bpp		= 16,
+	.grayscale	= 0,
+};
+
+/*
+ * Ensure VGA is selected.
+ */
+static void cp_clcd_enable(struct clcd_fb *fb)
+{
+	cm_control(CM_CTRL_LCDMUXSEL_MASK, CM_CTRL_LCDMUXSEL_VGA);
+}
+
+static unsigned long framesize = SZ_1M;
+
+static int cp_clcd_setup(struct clcd_fb *fb)
+{
+	dma_addr_t dma;
+
+	fb->panel = &vga;
+
+	fb->fb.screen_base = dma_alloc_writecombine(&fb->dev->dev, framesize,
+						    &dma, GFP_KERNEL);
+	if (!fb->fb.screen_base) {
+		printk(KERN_ERR "CLCD: unable to map framebuffer\n");
+		return -ENOMEM;
+	}
+
+	fb->fb.fix.smem_start	= dma;
+	fb->fb.fix.smem_len	= framesize;
+
+	return 0;
+}
+
+static void cp_clcd_remove(struct clcd_fb *fb)
+{
+	dma_free_writecombine(&fb->dev->dev, fb->fb.fix.smem_len,
+			      fb->fb.screen_base, fb->fb.fix.smem_start);
+}
+
+static struct clcd_board clcd_data = {
+	.name		= "Integrator/CP",
+	.check		= clcdfb_check,
+	.decode		= clcdfb_decode,
+	.enable		= cp_clcd_enable,
+	.setup		= cp_clcd_setup,
+	.remove		= cp_clcd_remove,
+};
+
 static struct amba_device clcd_device = {
 	.dev		= {
 		.bus_id	= "mb:c0",
 		.coherent_dma_mask = ~0,
+		.platform_data = &clcd_data,
 	},
 	.res		= {
 		.start	= INTCP_PA_CLCD_BASE,
diff -Nru a/arch/arm/mach-iop3xx/Kconfig b/arch/arm/mach-iop3xx/Kconfig
--- a/arch/arm/mach-iop3xx/Kconfig	2004-10-18 14:57:04 -07:00
+++ b/arch/arm/mach-iop3xx/Kconfig	2004-10-18 14:57:04 -07:00
@@ -2,53 +2,48 @@
 
 menu "IOP3xx Implementation Options"
 
-choice
-	prompt "IOP3xx System Type"
-	default ARCH_IQ80310
-
-config ARCH_IQ80310
-	bool "IQ80310"
-	help
-	  Say Y here if you want to run your kernel on the Intel IQ80310
-	  evaluation kit for the IOP310 chipset.
+comment "IOP3xx Platform Types"
 
 config ARCH_IQ80321
-	bool "IQ80321"
+	bool "Enable support for IQ80321"
+	select ARCH_IOP321
 	help
 	  Say Y here if you want to run your kernel on the Intel IQ80321
 	  evaluation kit for the IOP321 chipset.
-endchoice
 
-# Which IOP variant are we running?
-config ARCH_IOP310
-	bool
-	default ARCH_IQ80310
+config ARCH_IQ31244
+	bool "Enable support for IQ31244"
+	select ARCH_IOP321
+	help
+	  Say Y here if you want to run your kernel on the Intel IQ31244
+	  evaluation kit for the IOP321 chipset.
+
+config ARCH_IQ80331
+	bool "Enable support for IQ80331"
+	select ARCH_IOP331
 	help
-	  The IQ80310 uses the IOP310 variant.
+	  Say Y here if you want to run your kernel on the Intel IQ80331
+	  evaluation kit for the IOP331 chipset.
 
+config ARCH_EP80219
+    bool "Enable support for EP80219"
+    select ARCH_IOP321
+    select ARCH_IQ31244
+
+# Which IOP variant are we running?
 config ARCH_IOP321
 	bool
-	default ARCH_IQ80321
 	help
 	  The IQ80321 uses the IOP321 variant.
+	  The IQ31244 and EP80219 uses the IOP321 variant.
 
-comment "IOP3xx Chipset Features"
+config ARCH_IOP331
+	bool
+	default ARCH_IQ80331
+	help
+	  The IQ80331 uses the IOP331 variant.
 
-config IOP3XX_AAU
-	bool "Support Intel IOP3xx Application Accelerator Unit (EXPERIMENTAL)"
-	depends on EXPERIMENTAL
-
-config IOP3XX_DMA
-	bool "Support Intel IOP3xx DMA (EXPERIMENTAL)"
-	depends on EXPERIMENTAL
-
-config IOP3XX_MU
-	bool "Support Intel IOP3xx Messaging Unit (EXPERIMENTAL)"
-	depends on EXPERIMENTAL
-
-config IOP3XX_PMON
-	bool "Support Intel IOP3xx Performance Monitor (EXPERIMENTAL)"
-	depends on EXPERIMENTAL
+comment "IOP3xx Chipset Features"
 
 endmenu
 
diff -Nru a/arch/arm/mach-iop3xx/Makefile b/arch/arm/mach-iop3xx/Makefile
--- a/arch/arm/mach-iop3xx/Makefile	2004-10-18 14:57:03 -07:00
+++ b/arch/arm/mach-iop3xx/Makefile	2004-10-18 14:57:03 -07:00
@@ -4,27 +4,18 @@
 
 # Object file lists.
 
-obj-y			:= arch.o
+obj-y			:= common.o
 
 obj-m			:=
 obj-n			:=
 obj-			:=
 
-obj-$(CONFIG_ARCH_IOP310)  += xs80200-irq.o iop310-irq.o iop310-pci.o mm.o
+obj-$(CONFIG_ARCH_IOP321)  += iop321-setup.o iop321-irq.o iop321-pci.o iop321-mm.o iop321-time.o
 
-obj-$(CONFIG_ARCH_IQ80310) += iq80310-pci.o iq80310-irq.o
+obj-$(CONFIG_ARCH_IOP331)  += iop331-setup.o iop331-irq.o iop331-pci.o iop331-time.o
 
-obj-$(CONFIG_ARCH_IOP321)  += iop321-irq.o iop321-pci.o mm-321.o iop321-time.o
+obj-$(CONFIG_ARCH_IQ80321) += iq80321-mm.o iq80321-pci.o
 
-obj-$(CONFIG_ARCH_IQ80321) += iq80321-pci.o
+obj-$(CONFIG_ARCH_IQ31244) += iq31244-mm.o iq31244-pci.o
 
-ifeq ($(CONFIG_ARCH_IQ80310),y)
-   ifneq ($(CONFIG_XSCALE_PMU_TIMER),y)
-      obj-y			+= iq80310-time.o
-   endif
-endif
-
-obj-$(CONFIG_IOP3XX_AAU) += aau.o
-obj-$(CONFIG_IOP3XX_DMA) += dma.o
-obj-$(CONFIG_IOP3XX_MU) += message.o
-obj-$(CONFIG_IOP3XX_PMON) += pmon.o
+obj-$(CONFIG_ARCH_IQ80331) += iq80331-mm.o iq80331-pci.o
diff -Nru a/arch/arm/mach-iop3xx/arch.c b/arch/arm/mach-iop3xx/arch.c
--- a/arch/arm/mach-iop3xx/arch.c	2004-10-18 14:56:33 -07:00
+++ b/arch/arm/mach-iop3xx/arch.c	2004-10-18 14:56:33 -07:00
@@ -21,56 +21,30 @@
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
 
-#ifdef CONFIG_ARCH_IQ80310
-extern void iq80310_map_io(void);
-extern void iq80310_init_irq(void);
+#ifdef CONFIG_ARCH_IQ80331
+extern void iq80331_map_io(void);
+extern void iop331_init_irq(void);
+extern void iop331_init_time(void);
 #endif
 
-#ifdef CONFIG_ARCH_IQ80321
-extern void iq80321_map_io(void);
-extern void iop321_init_irq(void);
-extern void iop321_init_time(void);
-#endif
-
-#ifdef CONFIG_ARCH_IQ80310
-static void __init
-fixup_iq80310(struct machine_desc *desc, struct tag *tags,
-	      char **cmdline, struct meminfo *mi)
-{
-	system_rev = (*(volatile unsigned int*)0xfe830000) & 0x0f;
-
-	if (system_rev)
-		system_rev = 0xF;
-}
-#endif
-
-#ifdef CONFIG_ARCH_IQ80321
+#ifdef CONFIG_ARCH_IQ80331
 static void __init
-fixup_iop321(struct machine_desc *desc, struct param_struct *params,
+fixup_iop331(struct machine_desc *desc, struct tag *tags,
 	      char **cmdline, struct meminfo *mi)
 {
 }
 #endif
 
-#ifdef CONFIG_ARCH_IQ80310
-MACHINE_START(IQ80310, "Cyclone IQ80310")
-	MAINTAINER("MontaVista Software Inc.")
-	BOOT_MEM(0xa0000000, 0xfe000000, 0xfe000000)
-	FIXUP(fixup_iq80310)
-	MAPIO(iq80310_map_io)
-	INITIRQ(iq80310_init_irq)
+#if defined(CONFIG_ARCH_IQ80331)
+MACHINE_START(IQ80331, "Intel IQ80331")
+	MAINTAINER("Intel Corp.")
+	BOOT_MEM(PHYS_OFFSET, 0xfff01000, 0xfffff000) // virtual, physical
+//	BOOT_MEM(PHYS_OFFSET, IQ80331_UART0_VIRT, IQ80331_UART0_PHYS)
+	MAPIO(iq80331_map_io)
+	INITIRQ(iop331_init_irq)
+	INITTIME(iop331_init_time)
+	BOOT_PARAMS(0x0100)
 MACHINE_END
-
-#elif defined(CONFIG_ARCH_IQ80321)
-MACHINE_START(IQ80321, "Intel IQ80321")
-	MAINTAINER("MontaVista Software, Inc.")
-	BOOT_MEM(PHYS_OFFSET, IQ80321_UART1, 0xfe800000)
-	FIXUP(fixup_iop321)
-	MAPIO(iq80321_map_io)
-	INITIRQ(iop321_init_irq)
-	INITTIME(iop321_init_time)
-MACHINE_END
-
 #else
-#error No machine descriptor defined for this IOP310 implementation
+#error No machine descriptor defined for this IOP3xx implementation
 #endif
diff -Nru a/arch/arm/mach-iop3xx/common.c b/arch/arm/mach-iop3xx/common.c
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/arch/arm/mach-iop3xx/common.c	2004-10-18 14:57:22 -07:00
@@ -0,0 +1,75 @@
+/*
+ * arch/arm/mach-iop3xx/common.c
+ *
+ * Common routines shared across all IOP3xx implementations
+ *
+ * Author: Deepak Saxena <dsaxena@mvista.com>
+ *
+ * Copyright 2003 (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/delay.h>
+#include <asm/hardware.h>
+
+/*
+ * Shared variables
+ */
+unsigned long iop3xx_pcibios_min_io = 0;
+unsigned long iop3xx_pcibios_min_mem = 0;
+
+#ifdef CONFIG_ARCH_EP80219
+#include <linux/kernel.h>
+/*
+ * Default power-off for EP80219
+ */
+#include <asm/mach-types.h>
+#include <asm/hardware.h>
+
+static inline void ep80219_send_to_pic(__u8 c) {
+}
+
+void ep80219_power_off(void)
+{
+	/*
+     * This function will send a SHUTDOWN_COMPLETE message to the PIC controller
+     * over I2C.  We are not using the i2c subsystem since we are going to power
+     * off and it may be removed
+     */
+
+	/* Send the Address byte w/ the start condition */
+	*IOP321_IDBR1 = 0x60;
+	*IOP321_ICR1 = 0xE9;
+    mdelay(1);
+
+	/* Send the START_MSG byte w/ no start or stop condition */
+	*IOP321_IDBR1 = 0x0F;
+	*IOP321_ICR1 = 0xE8;
+    mdelay(1);
+
+	/* Send the SHUTDOWN_COMPLETE Message ID byte w/ no start or stop condition */
+	*IOP321_IDBR1 = 0x03;
+	*IOP321_ICR1 = 0xE8;
+    mdelay(1);
+
+	/* Send an ignored byte w/ stop condition */
+	*IOP321_IDBR1 = 0x00;
+	*IOP321_ICR1 = 0xEA;
+
+	while (1) ;
+}
+
+#include <linux/init.h>
+#include <linux/pm.h>
+
+static int __init ep80219_init(void)
+{
+	pm_power_off = ep80219_power_off;
+	return 0;
+}
+arch_initcall(ep80219_init);
+#endif
diff -Nru a/arch/arm/mach-iop3xx/iop310-irq.c b/arch/arm/mach-iop3xx/iop310-irq.c
--- a/arch/arm/mach-iop3xx/iop310-irq.c	2004-10-18 14:57:03 -07:00
+++ /dev/null	Wed Dec 31 16:00:00 196900
@@ -1,111 +0,0 @@
-/*
- * linux/arch/arm/mach-iop3xx/iop310-irq.c
- *
- * Generic IOP310 IRQ handling functionality
- *
- * Author:  Nicolas Pitre
- * Copyright:   (C) 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 version 2 as
- * published by the Free Software Foundation.
- *
- * Added IOP310 chipset and IQ80310 board demuxing, masking code. - DS
- *
- */
-#include <linux/init.h>
-#include <linux/interrupt.h>
-#include <linux/list.h>
-
-#include <asm/mach/irq.h>
-#include <asm/irq.h>
-#include <asm/hardware.h>
-
-extern void xs80200_irq_mask(unsigned int);
-extern void xs80200_irq_unmask(unsigned int);
-extern void xs80200_init_irq(void);
-
-extern void do_IRQ(int, struct pt_regs *);
-
-static u32 iop310_mask /* = 0 */;
-
-static void iop310_irq_mask (unsigned int irq)
-{
-	iop310_mask ++;
-
-	/*
-	 * No mask bits on the 80312, so we have to
-	 * mask everything from the outside!
-	 */
-	if (iop310_mask == 1) {
-		disable_irq(IRQ_XS80200_EXTIRQ);
-		irq_desc[IRQ_XS80200_EXTIRQ].chip->mask(IRQ_XS80200_EXTIRQ);
-	}
-}
-
-static void iop310_irq_unmask (unsigned int irq)
-{
-	if (iop310_mask)
-		iop310_mask --;
-
-	/*
-	 * Check if all 80312 sources are unmasked now
-	 */
-	if (iop310_mask == 0)
-		enable_irq(IRQ_XS80200_EXTIRQ);
-}
-
-struct irqchip ext_chip = {
-	.ack	= iop310_irq_mask,
-	.mask	= iop310_irq_mask,
-	.unmask = iop310_irq_unmask,
-};
-
-void
-iop310_irq_demux(unsigned int irq, struct irqdesc *desc, struct pt_regs *regs)
-{
-	u32 fiq1isr = *((volatile u32*)IOP310_FIQ1ISR);
-	u32 fiq2isr = *((volatile u32*)IOP310_FIQ2ISR);
-	struct irqdesc *d;
-	unsigned int irqno = 0;
-
-	if(fiq1isr)
-	{
-		if(fiq1isr & 0x1)
-			irqno = IRQ_IOP310_DMA0;
-		if(fiq1isr & 0x2)
-			irqno = IRQ_IOP310_DMA1;
-		if(fiq1isr & 0x4)
-			irqno = IRQ_IOP310_DMA2;
-		if(fiq1isr & 0x10)
-			irqno = IRQ_IOP310_PMON;
-		if(fiq1isr & 0x20)
-			irqno = IRQ_IOP310_AAU;
-	}
-	else
-	{
-		if(fiq2isr & 0x2)
-			irqno = IRQ_IOP310_I2C;
-		if(fiq2isr & 0x4)
-			irqno = IRQ_IOP310_MU;
-	}
-
-	if (irqno) {
-		d = irq_desc + irqno;
-		d->handle(irqno, d, regs);
-	}
-}
-
-void __init iop310_init_irq(void)
-{
-	unsigned int i;
-
-	for(i = IOP310_IRQ_OFS; i < NR_IOP310_IRQS; i++)
-	{
-		set_irq_chip(i, &ext_chip);
-		set_irq_handler(i, do_level_IRQ);
-		set_irq_flags(i, IRQF_VALID | IRQF_PROBE);
-	}
-
-	xs80200_init_irq();
-}
diff -Nru a/arch/arm/mach-iop3xx/iop310-pci.c b/arch/arm/mach-iop3xx/iop310-pci.c
--- a/arch/arm/mach-iop3xx/iop310-pci.c	2004-10-18 14:56:28 -07:00
+++ /dev/null	Wed Dec 31 16:00:00 196900
@@ -1,434 +0,0 @@
-/*
- * arch/arm/mach-iop3xx/iop310-pci.c
- *
- * PCI support for the Intel IOP310 chipset
- *
- * Matt Porter <mporter@mvista.com>
- *
- * Copyright (C) 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 version 2 as
- * published by the Free Software Foundation.
- */
-#include <linux/kernel.h>
-#include <linux/pci.h>
-#include <linux/slab.h>
-#include <linux/mm.h>
-#include <linux/init.h>
-#include <linux/ioport.h>
-
-#include <asm/io.h>
-#include <asm/irq.h>
-#include <asm/system.h>
-#include <asm/hardware.h>
-#include <asm/mach/pci.h>
-
-#include <asm/arch/iop310.h>
-
-/*
- *    *** Special note - why the IOP310 should NOT be used ***
- *
- * The PCI ATU is a brain dead implementation, only allowing 32-bit
- * accesses to PCI configuration space.  This is especially brain
- * dead for writes to this space.  A simple for-instance:
- *
- *  You want to modify the command register *without* corrupting the
- *  status register.
- *
- *  To perform this, you need to read *32* bits of data from offset 4,
- *  mask off the low 16, replace them with the new data, and write *32*
- *  bits back.
- *
- *  Writing the status register at offset 6 with status bits set *clears*
- *  the status.
- *
- * Hello?  Could we have a *SANE* implementation of a PCI ATU some day
- * *PLEASE*?
- */
-#undef DEBUG
-#ifdef DEBUG
-#define  DBG(x...) printk(x)
-#else
-#define  DBG(x...) do { } while (0)
-#endif
-
-/*
- * Calculate the address, etc from the bus, devfn and register
- * offset.  Note that we have two root buses, so we need some
- * method to determine whether we need config type 0 or 1 cycles.
- * We use a root bus number in our bus->sysdata structure for this.
- */
-static u32 iop310_cfg_address(struct pci_bus *bus, int devfn, int where)
-{
-	struct pci_sys_data *sys = bus->sysdata;
-	u32 addr;
-
-	if (sys->busnr == bus->number)
-		addr = 1 << (PCI_SLOT(devfn) + 16);
-	else
-		addr = bus->number << 16 | PCI_SLOT(devfn) << 11 | 1;
-
-	addr |=	PCI_FUNC(devfn) << 8 | (where & ~3);
-
-	return addr;
-}
-
-/*
- * Primary PCI interface support.
- */
-static int iop310_pri_pci_status(void)
-{
-	unsigned int status;
-	int ret = 0;
-
-	status = *IOP310_PATUSR;
-	if (status & 0xf900) {
-		*IOP310_PATUSR = status & 0xf900;
-		ret = 1;
-	}
-	status = *IOP310_PATUISR;
-	if (status & 0x0000018f) {
-		*IOP310_PATUISR = status & 0x0000018f;
-		ret = 1;
-	}
-	status = *IOP310_PSR;
-	if (status & 0xf900) {
-		*IOP310_PSR = status & 0xf900;
-		ret = 1;
-	}
-	status = *IOP310_PBISR;
-	if (status & 0x003f) {
-		*IOP310_PBISR = status & 0x003f;
-		ret = 1;
-	}
-	return ret;
-}
-
-/*
- * Simply write the address register and read the configuration
- * data.  Note that the 4 nop's ensure that we are able to handle
- * a delayed abort (in theory.)
- */
-static inline u32 iop310_pri_read(unsigned long addr)
-{
-	u32 val;
-
-	__asm__ __volatile__(
-		"str	%1, [%2]\n\t"
-		"ldr	%0, [%3]\n\t"
-		"nop\n\t"
-		"nop\n\t"
-		"nop\n\t"
-		"nop\n\t"
-		: "=r" (val)
-		: "r" (addr), "r" (IOP310_POCCAR), "r" (IOP310_POCCDR));
-
-	return val;
-}
-
-static int
-iop310_pri_read_config(struct pci_bus *bus, unsigned int devfn, int where,
-		       int size, u32 *value)
-{
-	unsigned long addr = iop310_cfg_address(bus, devfn, where);
-	u32 val = iop310_pri_read(addr) >> ((where & 3) * 8);
-
-	if (iop310_pri_pci_status())
-		val = 0xffffffff;
-
-	*value = val;
-
-	return PCIBIOS_SUCCESSFUL;
-}
-
-static int
-iop310_pri_write_config(struct pci_bus *bus, unsigned int devfn, int where,
-			int size, u32 value)
-{
-	unsigned long addr = iop310_cfg_address(bus, devfn, where);
-	u32 val;
-
-	if (size != 4) {
-		val = iop310_pri_read(addr);
-		if (!iop310_pri_pci_status() == 0)
-			return PCIBIOS_SUCCESSFUL;
-
-		where = (where & 3) * 8;
-
-		if (size == 1)
-			val &= ~(0xff << where);
-		else
-			val &= ~(0xffff << where);
-
-		*IOP310_POCCDR = val | value << where;
-	} else {
-		asm volatile(
-			"str	%1, [%2]\n\t"
-			"str	%0, [%3]\n\t"
-			"nop\n\t"
-			"nop\n\t"
-			"nop\n\t"
-			"nop\n\t"
-			:
-			: "r" (value), "r" (addr),
-			  "r" (IOP310_POCCAR), "r" (IOP310_POCCDR));
-	}
-
-	return PCIBIOS_SUCCESSFUL;
-}
-
-static struct pci_ops iop310_primary_ops = {
-	.read	= iop310_pri_read_config,
-	.write	= iop310_pri_write_config,
-};
-
-/*
- * Secondary PCI interface support.
- */
-static int iop310_sec_pci_status(void)
-{
-	unsigned int usr, uisr;
-	int ret = 0;
-
-	usr = *IOP310_SATUSR;
-	uisr = *IOP310_SATUISR;
-	if (usr & 0xf900) {
-		*IOP310_SATUSR = usr & 0xf900;
-		ret = 1;
-	}
-	if (uisr & 0x0000069f) {
-		*IOP310_SATUISR = uisr & 0x0000069f;
-		ret = 1;
-	}
-	if (ret)
-		DBG("ERROR (%08x %08x)", usr, uisr);
-	return ret;
-}
-
-/*
- * Simply write the address register and read the configuration
- * data.  Note that the 4 nop's ensure that we are able to handle
- * a delayed abort (in theory.)
- */
-static inline u32 iop310_sec_read(unsigned long addr)
-{
-	u32 val;
-
-	__asm__ __volatile__(
-		"str	%1, [%2]\n\t"
-		"ldr	%0, [%3]\n\t"
-		"nop\n\t"
-		"nop\n\t"
-		"nop\n\t"
-		"nop\n\t"
-		: "=r" (val)
-		: "r" (addr), "r" (IOP310_SOCCAR), "r" (IOP310_SOCCDR));
-
-	return val;
-}
-
-static int
-iop310_sec_read_config(struct pci_bus *bus, unsigned int devfn, int where,
-		       int size, u32 *value)
-{
-	unsigned long addr = iop310_cfg_address(bus, devfn, where);
-	u32 val = iop310_sec_read(addr) >> ((where & 3) * 8);
-
-	if (iop310_sec_pci_status())
-		val = 0xffffffff;
-
-	*value = val;
-
-	return PCIBIOS_SUCCESSFUL;
-}
-
-static int
-iop310_sec_write_config(struct pci_bus *bus, unsigned int devfn, int where,
-			int size, u32 value)
-{
-	unsigned long addr = iop310_cfg_address(bus, devfn, where);
-	u32 val;
-
-	if (size != 4) {
-		val = iop310_sec_read(addr);
-
-		if (!iop310_sec_pci_status() == 0)
-			return PCIBIOS_SUCCESSFUL;
-
-		where = (where & 3) * 8;
-
-		if (size == 1)
-			val &= ~(0xff << where);
-		else
-			val &= ~(0xffff << where);
-
-		*IOP310_SOCCDR = val | value << where;
-	} else {
-		asm volatile(
-			"str	%1, [%2]\n\t"
-			"str	%0, [%3]\n\t"
-			"nop\n\t"
-			"nop\n\t"
-			"nop\n\t"
-			"nop\n\t"
-			:
-			: "r" (value), "r" (addr),
-			  "r" (IOP310_SOCCAR), "r" (IOP310_SOCCDR));
-	}
-
-	return PCIBIOS_SUCCESSFUL;
-}
-
-static struct pci_ops iop310_secondary_ops = {
-	.read	= iop310_sec_read_config,
-	.write	= iop310_sec_write_config,
-};
-
-/*
- * When a PCI device does not exist during config cycles, the 80200 gets
- * an external abort instead of returning 0xffffffff.  If it was an
- * imprecise abort, we need to correct the return address to point after
- * the instruction.  Also note that the Xscale manual says:
- *
- *  "if a stall-until-complete LD or ST instruction triggers an
- *  imprecise fault, then that fault will be seen by the program
- *  within 3 instructions."
- *
- * This does not appear to be the case.  With 8 NOPs after the load, we
- * see the imprecise abort occurring on the STM of iop310_sec_pci_status()
- * which is about 10 instructions away.
- *
- * Always trust reality!
- */
-static int
-iop310_pci_abort(unsigned long addr, unsigned int fsr, struct pt_regs *regs)
-{
-	DBG("PCI abort: address = 0x%08lx fsr = 0x%03x PC = 0x%08lx LR = 0x%08lx\n",
-		addr, fsr, regs->ARM_pc, regs->ARM_lr);
-
-	/*
-	 * If it was an imprecise abort, then we need to correct the
-	 * return address to be _after_ the instruction.
-	 */
-	if (fsr & (1 << 10))
-		regs->ARM_pc += 4;
-
-	return 0;
-}
-
-/*
- * Scan an IOP310 PCI bus.  sys->bus defines which bus we scan.
- */
-struct pci_bus *iop310_scan_bus(int nr, struct pci_sys_data *sys)
-{
-	struct pci_ops *ops;
-
-	if (nr)
-		ops = &iop310_secondary_ops;
-	else
-		ops = &iop310_primary_ops;
-
-	return pci_scan_bus(sys->busnr, ops, sys);
-}
-
-/*
- * Setup the system data for controller 'nr'.   Return 0 if none found,
- * 1 if found, or negative error.
- *
- * We can alter:
- *  io_offset   - offset between IO resources and PCI bus BARs
- *  mem_offset  - offset between mem resources and PCI bus BARs
- *  resource[0] - parent IO resource
- *  resource[1] - parent non-prefetchable memory resource
- *  resource[2] - parent prefetchable memory resource
- *  swizzle     - bridge swizzling function
- *  map_irq     - irq mapping function
- *
- * Note that 'io_offset' and 'mem_offset' are left as zero since
- * the IOP310 doesn't attempt to perform any address translation
- * on accesses from the host to the bus.
- */
-int iop310_setup(int nr, struct pci_sys_data *sys)
-{
-	struct resource *res;
-
-	if (nr >= 2)
-		return 0;
-
-	res = kmalloc(sizeof(struct resource) * 2, GFP_KERNEL);
-	if (!res)
-		panic("PCI: unable to alloc resources");
-
-	memset(res, 0, sizeof(struct resource) * 2);
-
-	switch (nr) {
-	case 0:
-		res[0].start = IOP310_PCIPRI_LOWER_IO + 0x6e000000;
-		res[0].end   = IOP310_PCIPRI_LOWER_IO + 0x6e00ffff;
-		res[0].name  = "PCI IO Primary";
-		res[0].flags = IORESOURCE_IO;
-
-		res[1].start = IOP310_PCIPRI_LOWER_MEM;
-		res[1].end   = IOP310_PCIPRI_LOWER_MEM + IOP310_PCI_WINDOW_SIZE;
-		res[1].name  = "PCI Memory Primary";
-		res[1].flags = IORESOURCE_MEM;
-		break;
-
-	case 1:
-		res[0].start = IOP310_PCISEC_LOWER_IO + 0x6e000000;
-		res[0].end   = IOP310_PCISEC_LOWER_IO + 0x6e00ffff;
-		res[0].name  = "PCI IO Secondary";
-		res[0].flags = IORESOURCE_IO;
-
-		res[1].start = IOP310_PCISEC_LOWER_MEM;
-		res[1].end   = IOP310_PCISEC_LOWER_MEM + IOP310_PCI_WINDOW_SIZE;
-		res[1].name  = "PCI Memory Secondary";
-		res[1].flags = IORESOURCE_MEM;
-		break;
-	}
-
-	request_resource(&ioport_resource, &res[0]);
-	request_resource(&iomem_resource, &res[1]);
-
-	sys->resource[0] = &res[0];
-	sys->resource[1] = &res[1];
-	sys->resource[2] = NULL;
-	sys->io_offset   = 0x6e000000;
-
-	return 1;
-}
-
-void iop310_init(void)
-{
-	DBG("PCI:  Intel 80312 PCI-to-PCI init code.\n");
-	DBG("  ATU secondary: ATUCR =0x%08x\n", *IOP310_ATUCR);
-	DBG("  ATU secondary: SOMWVR=0x%08x  SOIOWVR=0x%08x\n",
-		*IOP310_SOMWVR,	*IOP310_SOIOWVR);
-	DBG("  ATU secondary: SIABAR=0x%08x  SIALR  =0x%08x SIATVR=%08x\n",
-		*IOP310_SIABAR, *IOP310_SIALR, *IOP310_SIATVR);
-	DBG("  ATU primary:   POMWVR=0x%08x  POIOWVR=0x%08x\n",
-		*IOP310_POMWVR,	*IOP310_POIOWVR);
-	DBG("  ATU primary:   PIABAR=0x%08x  PIALR  =0x%08x PIATVR=%08x\n",
-		*IOP310_PIABAR, *IOP310_PIALR, *IOP310_PIATVR);
-	DBG("  P2P: PCR=0x%04x BCR=0x%04x EBCR=0x%04x\n",
-		*IOP310_PCR, *IOP310_BCR, *IOP310_EBCR);
-
-	/*
-	 * Windows have to be carefully opened via a nice set of calls
-	 * here or just some direct register fiddling in the board
-	 * specific init when we want transactions to occur between the
-	 * two PCI hoses.
-	 *
-	 * To do this, we will have manage RETRY assertion between the
-	 * firmware and the kernel.  This will ensure that the host
-	 * system's enumeration code is held off until we have tweaked
-	 * the interrupt routing and public/private IDSELs.
-	 *
-	 * For now we will simply default to disabling the integrated type
-	 * 81 P2P bridge.
-	 */
-	*IOP310_PCR &= 0xfff8;
-
-	hook_fault_code(16+6, iop310_pci_abort, SIGBUS, "imprecise external abort");
-}
diff -Nru a/arch/arm/mach-iop3xx/iop321-irq.c b/arch/arm/mach-iop3xx/iop321-irq.c
--- a/arch/arm/mach-iop3xx/iop321-irq.c	2004-10-18 14:57:04 -07:00
+++ b/arch/arm/mach-iop3xx/iop321-irq.c	2004-10-18 14:57:04 -07:00
@@ -81,7 +81,8 @@
 
 	intctl_write(0);		// disable all interrupts
 	intstr_write(0);		// treat all as IRQ
-	if(machine_is_iq80321()) 	// all interrupts are inputs to chip
+	if(machine_is_iq80321() ||
+	   machine_is_iq31244()) 	// all interrupts are inputs to chip
 		*IOP321_PCIIRSR = 0x0f;
 
 	for(i = IOP321_IRQ_OFS; i < NR_IOP321_IRQS; i++)
diff -Nru a/arch/arm/mach-iop3xx/iop321-mm.c b/arch/arm/mach-iop3xx/iop321-mm.c
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/arch/arm/mach-iop3xx/iop321-mm.c	2004-10-18 14:57:23 -07:00
@@ -0,0 +1,43 @@
+/*
+ * linux/arch/arm/mach-iop3xx/mm.c
+ *
+ * Low level memory initialization for IOP321 based systems
+ *
+ * Author: Rory Bolt <rorybolt@pacbell.net>
+ * Copyright (C) 2002 Rory Bolt
+ *
+ * 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/mm.h>
+#include <linux/init.h>
+
+#include <asm/io.h>
+#include <asm/pgtable.h>
+#include <asm/page.h>
+
+#include <asm/mach/map.h>
+#include <asm/mach-types.h>
+
+
+/*
+ * Standard IO mapping for all IOP321 based systems
+ */
+static struct map_desc iop321_std_desc[] __initdata = {
+ /* virtual     physical      length      type */
+
+ /* mem mapped registers */
+ { IOP321_VIRT_MEM_BASE,  IOP321_PHY_MEM_BASE,   0x00002000,  MT_DEVICE },
+
+ /* PCI IO space */
+ { 0xfe000000,  0x90000000,   0x00020000,  MT_DEVICE }
+};
+
+void __init iop321_map_io(void)
+{
+	iotable_init(iop321_std_desc, ARRAY_SIZE(iop321_std_desc));
+}
diff -Nru a/arch/arm/mach-iop3xx/iop321-pci.c b/arch/arm/mach-iop3xx/iop321-pci.c
--- a/arch/arm/mach-iop3xx/iop321-pci.c	2004-10-18 14:56:49 -07:00
+++ b/arch/arm/mach-iop3xx/iop321-pci.c	2004-10-18 14:56:49 -07:00
@@ -44,7 +44,7 @@
 	u32 addr;
 
 	if (sys->busnr == bus->number)
-		addr = 1 << (PCI_SLOT(devfn) + 16);
+		addr = 1 << (PCI_SLOT(devfn) + 16) | (PCI_SLOT(devfn) << 11);
 	else
 		addr = bus->number << 16 | PCI_SLOT(devfn) << 11 | 1;
 
@@ -158,6 +158,8 @@
 			: "r" (value), "r" (addr),
 			  "r" (IOP321_OCCAR), "r" (IOP321_OCCDR));
 	}
+
+	return PCIBIOS_SUCCESSFUL;
 }
 
 static struct pci_ops iop321_ops = {
@@ -193,53 +195,16 @@
 	return pci_scan_bus(sys->busnr, &iop321_ops, sys);
 }
 
-/*
- * Setup the system data for controller 'nr'.   Return 0 if none found,
- * 1 if found, or negative error.
- */
-int iop321_setup(int nr, struct pci_sys_data *sys)
-{
-	struct resource *res;
-
-	if (nr >= 1)
-		return 0;
-
-	res = kmalloc(sizeof(struct resource) * 2, GFP_KERNEL);
-	if (!res)
-		panic("PCI: unable to alloc resources");
-
-	memset(res, 0, sizeof(struct resource) * 2);
-
-	switch (nr) {
-	case 0:
-		res[0].start = IOP321_PCI_IO_BASE + 0x6e000000;
-		res[0].end   = IOP321_PCI_IO_BASE + IOP321_PCI_IO_SIZE-1 + 0x6e000000;
-		res[0].name  = "PCI IO Primary";
-		res[0].flags = IORESOURCE_IO;
-
-		res[1].start = IOP321_PCI_MEM_BASE;
-		res[1].end   = IOP321_PCI_MEM_BASE + IOP321_PCI_MEM_SIZE;
-		res[1].name  = "PCI Memory Primary";
-		res[1].flags = IORESOURCE_MEM;
-		break;
-	}
-
-	request_resource(&ioport_resource, &res[0]);
-	request_resource(&iomem_resource, &res[1]);
-
-	sys->resource[0] = &res[0];
-	sys->resource[1] = &res[1];
-	sys->resource[2] = NULL;
-	sys->io_offset   = 0x6e000000;
-
-	return 1;
-}
-
-
-
-
 void iop321_init(void)
 {
+#if CONFIG_ARCH_EP80219
+    *IOP321_ATUCR = 0x2;
+    *IOP321_OIOWTVR = 0x90000000;
+    *IOP321_IABAR0  = 0x00000004;
+    *IOP321_IABAR2  = 0xa000000c;
+    *IOP321_IALR2   = 0xe0000000;
+#endif
+
 	DBG("PCI:  Intel 80321 PCI init code.\n");
 	DBG("\tATU: IOP321_ATUCMD=0x%04x\n", *IOP321_ATUCMD);
 	DBG("\tATU: IOP321_OMWTVR0=0x%04x, IOP321_OIOWTVR=0x%04x\n",
@@ -251,7 +216,12 @@
 	DBG("\tATU: IOP321_IABAR2=0x%08x IOP321_IALR2=0x%08x IOP321_IATVR2=%08x\n", *IOP321_IABAR2, *IOP321_IALR2, *IOP321_IATVR2);
 	DBG("\tATU: IOP321_IABAR3=0x%08x IOP321_IALR3=0x%08x IOP321_IATVR3=%08x\n", *IOP321_IABAR3, *IOP321_IALR3, *IOP321_IATVR3);
 
+#if 0
+	hook_fault_code(4, iop321_pci_abort, SIGBUS, "external abort on linefetch");
+	hook_fault_code(6, iop321_pci_abort, SIGBUS, "external abort on linefetch");
+	hook_fault_code(8, iop321_pci_abort, SIGBUS, "external abort on non-linefetch");
+	hook_fault_code(10, iop321_pci_abort, SIGBUS, "external abort on non-linefetch");
+#endif
 	hook_fault_code(16+6, iop321_pci_abort, SIGBUS, "imprecise external abort");
-
 }
 
diff -Nru a/arch/arm/mach-iop3xx/iop321-setup.c b/arch/arm/mach-iop3xx/iop321-setup.c
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/arch/arm/mach-iop3xx/iop321-setup.c	2004-10-18 14:57:23 -07:00
@@ -0,0 +1,63 @@
+/*
+ * linux/arch/arm/mach-iop3xx/iop321-setup.c
+ *
+ * Author: Nicolas Pitre <nico@cam.org>
+ * Copyright (C) 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 version 2 as
+ * published by the Free Software Foundation.
+ *
+ */
+#include <linux/config.h>
+#include <linux/init.h>
+#include <linux/major.h>
+#include <linux/fs.h>
+
+#include <asm/setup.h>
+#include <asm/system.h>
+#include <asm/memory.h>
+#include <asm/hardware.h>
+#include <asm/mach-types.h>
+#include <asm/mach/arch.h>
+
+#ifdef CONFIG_ARCH_IQ80321
+extern void iq80321_map_io(void);
+extern void iop321_init_irq(void);
+extern void iop321_init_time(void);
+#endif
+
+#ifdef CONFIG_ARCH_IQ31244
+extern void iq31244_map_io(void);
+extern void iop321_init_irq(void);
+extern void iop321_init_time(void);
+#endif
+
+static void __init
+fixup_iop321(struct machine_desc *desc, struct tag *tags,
+	      char **cmdline, struct meminfo *mi)
+{
+}
+
+#if defined(CONFIG_ARCH_IQ80321)
+MACHINE_START(IQ80321, "Intel IQ80321")
+	MAINTAINER("Intel Corporation")
+	BOOT_MEM(PHYS_OFFSET, IQ80321_UART, 0xfe800000)
+	FIXUP(fixup_iop321)
+	MAPIO(iq80321_map_io)
+	INITIRQ(iop321_init_irq)
+	INITTIME(iop321_init_time)
+    BOOT_PARAMS(0xa0000100)
+MACHINE_END
+#elif defined(CONFIG_ARCH_IQ31244)
+    MACHINE_START(IQ31244, "Intel IQ31244")
+    MAINTAINER("Intel Corp.")
+    BOOT_MEM(PHYS_OFFSET, IQ31244_UART, IQ31244_UART)
+    MAPIO(iq31244_map_io)
+    INITIRQ(iop321_init_irq)
+	INITTIME(iop321_init_time)
+    BOOT_PARAMS(0xa0000100)
+MACHINE_END
+#else
+#error No machine descriptor defined for this IOP3XX implementation
+#endif
diff -Nru a/arch/arm/mach-iop3xx/iop321-time.c b/arch/arm/mach-iop3xx/iop321-time.c
--- a/arch/arm/mach-iop3xx/iop321-time.c	2004-10-18 14:56:50 -07:00
+++ b/arch/arm/mach-iop3xx/iop321-time.c	2004-10-18 14:56:50 -07:00
@@ -5,7 +5,7 @@
  *
  * Author: Deepak Saxena <dsaxena@mvista.com>
  *
- * Copyright 2002 MontaVista Software Inc.
+ * Copyright 2002-2003 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
@@ -23,17 +23,25 @@
 #include <asm/io.h>
 #include <asm/irq.h>
 #include <asm/uaccess.h>
-
+#include <asm/mach-types.h>
 #include <asm/mach/irq.h>
 #include <asm/mach/time.h>
 
+#define IOP321_TIME_SYNC 0
+
+static unsigned long iop321_latch;
+
+static inline unsigned long get_elapsed(void)
+{
+	return iop321_latch - *IOP321_TU_TCR0;
+}
+
 static unsigned long iop321_gettimeoffset(void)
 {
 	unsigned long elapsed, usec;
+	u32 tisr1, tisr2;
 
 	/*
-	 * FIXME: Implement what is described in this comment.
-	 *
 	 * If an interrupt was pending before we read the timer,
 	 * we've already wrapped.  Factor this into the time.
 	 * If an interrupt was pending after we read the timer,
@@ -42,12 +50,19 @@
 	 * be sure its value is after the wrap.
 	 */
 
-	elapsed = *IOP321_TU_TCR0;
+	asm volatile("mrc p6, 0, %0, c6, c1, 0" : "=r" (tisr1));
+	elapsed = get_elapsed();
+	asm volatile("mrc p6, 0, %0, c6, c1, 0" : "=r" (tisr2));
+
+	if(tisr1 & 1)
+		elapsed += iop321_latch;
+	else if (tisr2 & 1)
+		elapsed = iop321_latch + get_elapsed();
 
 	/*
 	 * Now convert them to usec.
 	 */
-	usec = (unsigned long)((LATCH - elapsed) * (tick_nsec / 1000)) / LATCH;
+	usec = (unsigned long)(elapsed * (tick_nsec / 1000)) / iop321_latch;
 
 	return usec;
 }
@@ -56,6 +71,10 @@
 iop321_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
 {
 	u32 tisr;
+#ifdef IOP321_TIME_SYNC
+	u32 passed;
+#define TM_THRESH (iop321_latch*2)
+#endif
 
 	asm volatile("mrc p6, 0, %0, c6, c1, 0" : "=r" (tisr));
 
@@ -63,7 +82,24 @@
 
 	asm volatile("mcr p6, 0, %0, c6, c1, 0" : : "r" (tisr));
 
-	timer_tick(regs);
+#ifdef IOP321_TIME_SYNC
+	passed = 0xffffffff - *IOP321_TU_TCR1;
+
+	do
+	{
+		do_timer(regs);
+		if(passed < TM_THRESH)
+			break;
+		if(passed > iop321_latch)
+			passed -= iop321_latch;
+		else
+			passed = 0;
+	} while(1);
+
+	asm volatile("mcr p6, 0, %0, c3, c1, 0" : : "r" (0xffffffff));
+#else
+	do_timer(regs);
+#endif
 
 	return IRQ_HANDLED;
 }
@@ -79,17 +115,27 @@
 void __init iop321_init_time(void)
 {
 	u32 timer_ctl;
-	u32 latch = LATCH;
 
+	iop321_latch = (CLOCK_TICK_RATE + HZ / 2) / HZ;
 	gettimeoffset = iop321_gettimeoffset;
 	setup_irq(IRQ_IOP321_TIMER0, &iop321_timer_irq);
 
 	timer_ctl = IOP321_TMR_EN | IOP321_TMR_PRIVILEGED | IOP321_TMR_RELOAD |
 			IOP321_TMR_RATIO_1_1;
 
-	asm volatile("mcr p6, 0, %0, c4, c1, 0" : : "r" (LATCH));
+	asm volatile("mcr p6, 0, %0, c4, c1, 0" : : "r" (iop321_latch));
 
 	asm volatile("mcr p6, 0, %0, c0, c1, 0"	: : "r" (timer_ctl));
+
+#ifdef IOP321_TIME_SYNC
+        /* Setup second timer */
+        /* setup counter */
+        timer_ctl = IOP321_TMR_EN | IOP321_TMR_PRIVILEGED |
+                        IOP321_TMR_RATIO_1_1;
+        asm volatile("mcr p6, 0, %0, c3, c1, 0" : : "r" (0xffffffff));
+        /* setup control */
+        asm volatile("mcr p6, 0, %0, c1, c1, 0" : : "r" (timer_ctl));
+#endif
 }
 
 
diff -Nru a/arch/arm/mach-iop3xx/iop331-irq.c b/arch/arm/mach-iop3xx/iop331-irq.c
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/arch/arm/mach-iop3xx/iop331-irq.c	2004-10-18 14:57:23 -07:00
@@ -0,0 +1,127 @@
+/*
+ * linux/arch/arm/mach-iop3xx/iop331-irq.c
+ *
+ * Generic IOP331 IRQ handling functionality
+ *
+ * Author: Dave Jiang <dave.jiang@intel.com>
+ * Copyright (C) 2003 Intel Corp.
+ *
+ * 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/init.h>
+#include <linux/interrupt.h>
+#include <linux/list.h>
+
+#include <asm/mach/irq.h>
+#include <asm/irq.h>
+#include <asm/hardware.h>
+
+#include <asm/mach-types.h>
+
+static u32 iop331_mask0 = 0;
+static u32 iop331_mask1 = 0;
+
+static inline void intctl_write0(u32 val)
+{
+    // INTCTL0
+	asm volatile("mcr p6,0,%0,c0,c0,0"::"r" (val));
+}
+
+static inline void intctl_write1(u32 val)
+{
+    // INTCTL1
+    asm volatile("mcr p6,0,%0,c1,c0,0"::"r" (val));
+}
+
+static inline void intstr_write0(u32 val)
+{
+    // INTSTR0
+	asm volatile("mcr p6,0,%0,c2,c0,0"::"r" (val));
+}
+
+static inline void intstr_write1(u32 val)
+{
+    // INTSTR1
+	asm volatile("mcr p6,0,%0,c3,c0,0"::"r" (val));
+}
+
+static void
+iop331_irq_mask1 (unsigned int irq)
+{
+        iop331_mask0 &= ~(1 << (irq - IOP331_IRQ_OFS));
+        intctl_write0(iop331_mask0);
+}
+
+static void
+iop331_irq_mask2 (unsigned int irq)
+{
+        iop331_mask1 &= ~(1 << (irq - IOP331_IRQ_OFS - 32));
+        intctl_write1(iop331_mask1);
+}
+
+static void
+iop331_irq_unmask1(unsigned int irq)
+{
+        iop331_mask0 |= (1 << (irq - IOP331_IRQ_OFS));
+        intctl_write0(iop331_mask0);
+}
+
+static void
+iop331_irq_unmask2(unsigned int irq)
+{
+        iop331_mask1 |= (1 << (irq - IOP331_IRQ_OFS - 32));
+        intctl_write1(iop331_mask1);
+}
+
+struct irqchip iop331_irqchip1 = {
+	.ack    = iop331_irq_mask1,
+	.mask   = iop331_irq_mask1,
+	.unmask = iop331_irq_unmask1,
+};
+
+struct irqchip iop331_irqchip2 = {
+	.ack    = iop331_irq_mask2,
+	.mask   = iop331_irq_mask2,
+	.unmask = iop331_irq_unmask2,
+};
+
+void __init iop331_init_irq(void)
+{
+	unsigned int i, tmp;
+
+	/* Enable access to coprocessor 6 for dealing with IRQs.
+	 * From RMK:
+	 * Basically, the Intel documentation here is poor.  It appears that
+	 * you need to set the bit to be able to access the coprocessor from
+	 * SVC mode.  Whether that allows access from user space or not is
+	 * unclear.
+	 */
+	asm volatile (
+		"mrc p15, 0, %0, c15, c1, 0\n\t"
+		"orr %0, %0, %1\n\t"
+		"mcr p15, 0, %0, c15, c1, 0\n\t"
+		/* The action is delayed, so we have to do this: */
+		"mrc p15, 0, %0, c15, c1, 0\n\t"
+		"mov %0, %0\n\t"
+		"sub pc, pc, #4"
+		: "=r" (tmp) : "i" (1 << 6) );
+
+	intctl_write0(0);		// disable all interrupts
+    	intctl_write1(0);
+	intstr_write0(0);		// treat all as IRQ
+    	intstr_write1(0);
+	if(machine_is_iq80331()) 	// all interrupts are inputs to chip
+		*IOP331_PCIIRSR = 0x0f;
+
+	for(i = IOP331_IRQ_OFS; i < NR_IOP331_IRQS; i++)
+	{
+		set_irq_chip(i, (i < 32) ? &iop331_irqchip1 : &iop331_irqchip2);
+		set_irq_handler(i, do_level_IRQ);
+		set_irq_flags(i, IRQF_VALID | IRQF_PROBE);
+	}
+}
+
diff -Nru a/arch/arm/mach-iop3xx/iop331-mm.c b/arch/arm/mach-iop3xx/iop331-mm.c
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/arch/arm/mach-iop3xx/iop331-mm.c	2004-10-18 14:57:24 -07:00
@@ -0,0 +1,43 @@
+/*
+ * linux/arch/arm/mach-iop3xx/mm.c
+ *
+ * Low level memory initialization for IOP331 based systems
+ *
+ * Author: Dave Jiang <dave.jiang@intel.com>
+ * Copyright (C) 2003 Intel Corp.
+ *
+ * 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/mm.h>
+#include <linux/init.h>
+
+#include <asm/io.h>
+#include <asm/pgtable.h>
+#include <asm/page.h>
+
+#include <asm/mach/map.h>
+#include <asm/mach-types.h>
+
+
+/*
+ * Standard IO mapping for all IOP331 based systems
+ */
+static struct map_desc iop331_std_desc[] __initdata = {
+ /* virtual     physical      length      type */
+
+ /* mem mapped registers */
+ { IOP331_VIRT_MEM_BASE,  IOP331_PHYS_MEM_BASE,   0x00002000,  MT_DEVICE },
+
+ /* PCI IO space */
+ { 0xfe000000,  0x90000000,   0x00020000,  MT_DEVICE }
+};
+
+void __init iop331_map_io(void)
+{
+	iotable_init(iop331_std_desc, ARRAY_SIZE(iop331_std_desc));
+}
diff -Nru a/arch/arm/mach-iop3xx/iop331-pci.c b/arch/arm/mach-iop3xx/iop331-pci.c
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/arch/arm/mach-iop3xx/iop331-pci.c	2004-10-18 14:57:24 -07:00
@@ -0,0 +1,217 @@
+/*
+ * arch/arm/mach-iop3xx/iop331-pci.c
+ *
+ * PCI support for the Intel IOP331 chipset
+ *
+ * Author: Dave Jiang (dave.jiang@intel.com)
+ * Copyright (C) 2003 Intel Corp.
+ *
+ * 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/kernel.h>
+#include <linux/pci.h>
+#include <linux/slab.h>
+#include <linux/mm.h>
+#include <linux/init.h>
+#include <linux/ioport.h>
+
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/system.h>
+#include <asm/hardware.h>
+#include <asm/mach/pci.h>
+
+#include <asm/arch/iop331.h>
+
+//#define DEBUG
+
+#ifdef DEBUG
+#define  DBG(x...) printk(x)
+#else
+#define  DBG(x...) do { } while (0)
+#endif
+
+/*
+ * This routine builds either a type0 or type1 configuration command.  If the
+ * bus is on the 80331 then a type0 made, else a type1 is created.
+ */
+static u32 iop331_cfg_address(struct pci_bus *bus, int devfn, int where)
+{
+	struct pci_sys_data *sys = bus->sysdata;
+	u32 addr;
+
+	if (sys->busnr == bus->number)
+		addr = 1 << (PCI_SLOT(devfn) + 16) | (PCI_SLOT(devfn) << 11);
+	else
+		addr = bus->number << 16 | PCI_SLOT(devfn) << 11 | 1;
+
+	addr |=	PCI_FUNC(devfn) << 8 | (where & ~3);
+
+	return addr;
+}
+
+/*
+ * This routine checks the status of the last configuration cycle.  If an error
+ * was detected it returns a 1, else it returns a 0.  The errors being checked
+ * are parity, master abort, target abort (master and target).  These types of
+ * errors occure during a config cycle where there is no device, like during
+ * the discovery stage.
+ */
+static int iop331_pci_status(void)
+{
+	unsigned int status;
+	int ret = 0;
+
+	/*
+	 * Check the status registers.
+	 */
+	status = *IOP331_ATUSR;
+	if (status & 0xf900)
+	{
+		DBG("\t\t\tPCI: P0 - status = 0x%08x\n", status);
+		*IOP331_ATUSR = status & 0xf900;
+		ret = 1;
+	}
+	status = *IOP331_ATUISR;
+	if (status & 0x679f)
+	{
+		DBG("\t\t\tPCI: P1 - status = 0x%08x\n", status);
+		*IOP331_ATUISR = status & 0x679f;
+		ret = 1;
+	}
+	return ret;
+}
+
+/*
+ * Simply write the address register and read the configuration
+ * data.  Note that the 4 nop's ensure that we are able to handle
+ * a delayed abort (in theory.)
+ */
+static inline u32 iop331_read(unsigned long addr)
+{
+	u32 val;
+
+	__asm__ __volatile__(
+		"str	%1, [%2]\n\t"
+		"ldr	%0, [%3]\n\t"
+		"nop\n\t"
+		"nop\n\t"
+		"nop\n\t"
+		"nop\n\t"
+		: "=r" (val)
+		: "r" (addr), "r" (IOP331_OCCAR), "r" (IOP331_OCCDR));
+
+	return val;
+}
+
+/*
+ * The read routines must check the error status of the last configuration
+ * cycle.  If there was an error, the routine returns all hex f's.
+ */
+static int
+iop331_read_config(struct pci_bus *bus, unsigned int devfn, int where,
+		int size, u32 *value)
+{
+	unsigned long addr = iop331_cfg_address(bus, devfn, where);
+	u32 val = iop331_read(addr) >> ((where & 3) * 8);
+
+	if( iop331_pci_status() )
+		val = 0xffffffff;
+
+	*value = val;
+
+	return PCIBIOS_SUCCESSFUL;
+}
+
+static int
+iop331_write_config(struct pci_bus *bus, unsigned int devfn, int where,
+		int size, u32 value)
+{
+	unsigned long addr = iop331_cfg_address(bus, devfn, where);
+	u32 val;
+
+	if (size != 4) {
+		val = iop331_read(addr);
+		if (!iop331_pci_status() == 0)
+			return PCIBIOS_SUCCESSFUL;
+
+		where = (where & 3) * 8;
+
+		if (size == 1)
+			val &= ~(0xff << where);
+		else
+			val &= ~(0xffff << where);
+
+		*IOP331_OCCDR = val | value << where;
+	} else {
+		asm volatile(
+			"str	%1, [%2]\n\t"
+			"str	%0, [%3]\n\t"
+			"nop\n\t"
+			"nop\n\t"
+			"nop\n\t"
+			"nop\n\t"
+			:
+			: "r" (value), "r" (addr),
+			  "r" (IOP331_OCCAR), "r" (IOP331_OCCDR));
+	}
+
+	return PCIBIOS_SUCCESSFUL;
+}
+
+static struct pci_ops iop331_ops = {
+	.read	= iop331_read_config,
+	.write	= iop331_write_config,
+};
+
+/*
+ * When a PCI device does not exist during config cycles, the XScale gets a
+ * bus error instead of returning 0xffffffff. This handler simply returns.
+ */
+int
+iop331_pci_abort(unsigned long addr, unsigned int fsr, struct pt_regs *regs)
+{
+	DBG("PCI abort: address = 0x%08lx fsr = 0x%03x PC = 0x%08lx LR = 0x%08lx\n",
+		addr, fsr, regs->ARM_pc, regs->ARM_lr);
+
+	/*
+	 * If it was an imprecise abort, then we need to correct the
+	 * return address to be _after_ the instruction.
+	 */
+	if (fsr & (1 << 10))
+		regs->ARM_pc += 4;
+
+	return 0;
+}
+
+/*
+ * Scan an IOP331 PCI bus.  sys->bus defines which bus we scan.
+ */
+struct pci_bus *iop331_scan_bus(int nr, struct pci_sys_data *sys)
+{
+	return pci_scan_bus(sys->busnr, &iop331_ops, sys);
+}
+
+void iop331_init(void)
+{
+	DBG("PCI:  Intel 80331 PCI init code.\n");
+	DBG("\tATU: IOP331_ATUCMD=0x%04x\n", *IOP331_ATUCMD);
+	DBG("\tATU: IOP331_OMWTVR0=0x%04x, IOP331_OIOWTVR=0x%04x\n",
+			*IOP331_OMWTVR0,
+			*IOP331_OIOWTVR);
+	DBG("\tATU: IOP331_ATUCR=0x%08x\n", *IOP331_ATUCR);
+	DBG("\tATU: IOP331_IABAR0=0x%08x IOP331_IALR0=0x%08x IOP331_IATVR0=%08x\n", *IOP331_IABAR0, *IOP331_IALR0, *IOP331_IATVR0);
+	DBG("\tATU: IOP331_ERBAR=0x%08x IOP331_ERLR=0x%08x IOP331_ERTVR=%08x\n", *IOP331_ERBAR, *IOP331_ERLR, *IOP331_ERTVR);
+	DBG("\tATU: IOP331_IABAR2=0x%08x IOP331_IALR2=0x%08x IOP331_IATVR2=%08x\n", *IOP331_IABAR2, *IOP331_IALR2, *IOP331_IATVR2);
+	DBG("\tATU: IOP331_IABAR3=0x%08x IOP331_IALR3=0x%08x IOP331_IATVR3=%08x\n", *IOP331_IABAR3, *IOP331_IALR3, *IOP331_IATVR3);
+
+	/* redboot changed, reset IABAR0 to something sane */
+	/* fixes master aborts in plugged in cards */
+	/* will clean up later and work nicely with redboot */
+	*IOP331_IABAR0 = 0x00000004;
+	hook_fault_code(16+6, iop331_pci_abort, SIGBUS, "imprecise external abort");
+}
+
diff -Nru a/arch/arm/mach-iop3xx/iop331-setup.c b/arch/arm/mach-iop3xx/iop331-setup.c
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/arch/arm/mach-iop3xx/iop331-setup.c	2004-10-18 14:57:24 -07:00
@@ -0,0 +1,102 @@
+/*
+ * linux/arch/arm/mach-iop3xx/iop331-setup.c
+ *
+ * Author: Dave Jiang (dave.jiang@intel.com)
+ * Copyright (C) 2004 Intel Corporation.
+ *
+ * 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/mm.h>
+#include <linux/init.h>
+#include <linux/config.h>
+#include <linux/init.h>
+#include <linux/major.h>
+#include <linux/fs.h>
+#include <linux/device.h>
+#include <linux/serial.h>
+#include <linux/tty.h>
+#include <linux/serial_core.h>
+
+#include <asm/io.h>
+#include <asm/pgtable.h>
+#include <asm/page.h>
+#include <asm/mach/map.h>
+#include <asm/setup.h>
+#include <asm/system.h>
+#include <asm/memory.h>
+#include <asm/hardware.h>
+#include <asm/mach-types.h>
+#include <asm/mach/arch.h>
+
+#define IOP331_UART_XTAL 33334000
+
+/*
+ * Standard IO mapping for all IOP331 based systems
+ */
+static struct map_desc iop331_std_desc[] __initdata = {
+ /* virtual     physical      length      type */
+
+ /* mem mapped registers */
+ { IOP331_VIRT_MEM_BASE,  IOP331_PHYS_MEM_BASE,   0x00002000,  MT_DEVICE },
+
+ /* PCI IO space */
+ { 0xfe000000,  0x90000000,   0x00020000,  MT_DEVICE }
+};
+
+static struct uart_port iop331_serial_ports[] = {
+	{
+		.membase	= (char*)(IQ80331_UART0_VIRT),
+		.mapbase	= (IQ80331_UART0_PHYS),
+		.irq		= IRQ_IOP331_UART0,
+		.flags		= UPF_SKIP_TEST,
+		.iotype		= UPIO_MEM,
+		.regshift	= 2,
+		.uartclk	= IOP331_UART_XTAL,
+		.line		= 0,
+		.type		= PORT_XSCALE,
+		.fifosize	= 32
+	} , {
+		.membase	= (char*)(IQ80331_UART1_VIRT),
+		.mapbase	= (IQ80331_UART1_PHYS),
+		.irq		= IRQ_IOP331_UART1,
+		.flags		= UPF_SKIP_TEST,
+		.iotype		= UPIO_MEM,
+		.regshift	= 2,
+		.uartclk	= IOP331_UART_XTAL,
+		.line		= 1,
+		.type		= PORT_XSCALE,
+		.fifosize	= 32
+	}
+};
+
+void __init iop331_map_io(void)
+{
+	iotable_init(iop331_std_desc, ARRAY_SIZE(iop331_std_desc));
+	early_serial_setup(&iop331_serial_ports[0]);
+	early_serial_setup(&iop331_serial_ports[1]);
+}
+
+#ifdef CONFIG_ARCH_IQ80331
+extern void iop331_init_irq(void);
+extern void iop331_init_time(void);
+extern void iq80331_map_io(void);
+#endif
+
+#if defined(CONFIG_ARCH_IQ80331)
+MACHINE_START(IQ80331, "Intel IQ80331")
+    MAINTAINER("Intel Corp.")
+    BOOT_MEM(PHYS_OFFSET, 0xfefff000, 0xfffff000) // virtual, physical
+    //BOOT_MEM(PHYS_OFFSET, IQ80331_UART0_VIRT, IQ80331_UART0_PHYS)
+    MAPIO(iq80331_map_io)
+    INITIRQ(iop331_init_irq)
+    INITTIME(iop331_init_time)
+    BOOT_PARAMS(0x0100)
+MACHINE_END
+#else
+#error No machine descriptor defined for this IOP3XX implementation
+#endif
+
+
diff -Nru a/arch/arm/mach-iop3xx/iop331-time.c b/arch/arm/mach-iop3xx/iop331-time.c
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/arch/arm/mach-iop3xx/iop331-time.c	2004-10-18 14:57:24 -07:00
@@ -0,0 +1,141 @@
+/*
+ * arch/arm/mach-iop3xx/iop331-time.c
+ *
+ * Timer code for IOP331 based systems
+ *
+ * Author: Dave Jiang <dave.jiang@intel.com>
+ *
+ * Copyright 2003 Intel Corp.
+ *
+ *  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/kernel.h>
+#include <linux/interrupt.h>
+#include <linux/time.h>
+#include <linux/init.h>
+#include <linux/timex.h>
+
+#include <asm/hardware.h>
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/uaccess.h>
+#include <asm/mach-types.h>
+#include <asm/mach/irq.h>
+#include <asm/mach/time.h>
+
+#undef IOP331_TIME_SYNC
+
+static unsigned long iop331_latch;
+
+static inline unsigned long get_elapsed(void)
+{
+	return iop331_latch - *IOP331_TU_TCR0;
+}
+
+static unsigned long iop331_gettimeoffset(void)
+{
+	unsigned long elapsed, usec;
+	u32 tisr1, tisr2;
+
+	/*
+	 * If an interrupt was pending before we read the timer,
+	 * we've already wrapped.  Factor this into the time.
+	 * If an interrupt was pending after we read the timer,
+	 * it may have wrapped between checking the interrupt
+	 * status and reading the timer.  Re-read the timer to
+	 * be sure its value is after the wrap.
+	 */
+
+	asm volatile("mrc p6, 0, %0, c6, c1, 0" : "=r" (tisr1));
+	elapsed = get_elapsed();
+	asm volatile("mrc p6, 0, %0, c6, c1, 0" : "=r" (tisr2));
+
+	if(tisr1 & 1)
+		elapsed += iop331_latch;
+	else if (tisr2 & 1)
+		elapsed = iop331_latch + get_elapsed();
+
+	/*
+	 * Now convert them to usec.
+	 */
+	usec = (unsigned long)(elapsed * (tick_nsec / 1000)) / iop331_latch;
+
+	return usec;
+}
+
+static irqreturn_t
+iop331_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+{
+	u32 tisr;
+#ifdef IOP331_TIME_SYNC
+	u32 passed;
+#define TM_THRESH (iop331_latch*2)
+#endif
+
+	asm volatile("mrc p6, 0, %0, c6, c1, 0" : "=r" (tisr));
+
+	tisr |= 1;
+
+	asm volatile("mcr p6, 0, %0, c6, c1, 0" : : "r" (tisr));
+
+#ifdef IOP331_TIME_SYNC
+	passed = 0xffffffff - *IOP331_TU_TCR1;
+
+	do
+	{
+		do_timer(regs);
+		if(passed < TM_THRESH)
+			break;
+		if(passed > iop331_latch)
+			passed -= iop331_latch;
+		else
+			passed = 0;
+	} while(1);
+
+	asm volatile("mcr p6, 0, %0, c3, c1, 0" : : "r" (0xffffffff));
+#else
+	do_timer(regs);
+#endif
+
+	return IRQ_HANDLED;
+}
+
+static struct irqaction iop331_timer_irq = {
+	.name		= "IOP331 Timer Tick",
+	.handler	= iop331_timer_interrupt,
+	.flags		= SA_INTERRUPT
+};
+
+extern int setup_arm_irq(int, struct irqaction*);
+
+void __init iop331_init_time(void)
+{
+	u32 timer_ctl;
+
+	iop331_latch = (CLOCK_TICK_RATE + HZ / 2) / HZ;
+	gettimeoffset = iop331_gettimeoffset;
+	setup_irq(IRQ_IOP331_TIMER0, &iop331_timer_irq);
+
+	timer_ctl = IOP331_TMR_EN | IOP331_TMR_PRIVILEGED | IOP331_TMR_RELOAD |
+			IOP331_TMR_RATIO_1_1;
+
+	asm volatile("mcr p6, 0, %0, c4, c1, 0" : : "r" (iop331_latch));
+
+	asm volatile("mcr p6, 0, %0, c0, c1, 0"	: : "r" (timer_ctl));
+
+#ifdef IOP331_TIME_SYNC
+        /* Setup second timer */
+        /* setup counter */
+        timer_ctl = IOP331_TMR_EN | IOP331_TMR_PRIVILEGED |
+                        IOP331_TMR_RATIO_1_1;
+        asm volatile("mcr p6, 0, %0, c3, c1, 0" : : "r" (0xffffffff));
+        /* setup control */
+        asm volatile("mcr p6, 0, %0, c1, c1, 0" : : "r" (timer_ctl));
+#endif
+}
+
+
diff -Nru a/arch/arm/mach-iop3xx/iq31244-mm.c b/arch/arm/mach-iop3xx/iq31244-mm.c
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/arch/arm/mach-iop3xx/iq31244-mm.c	2004-10-18 14:57:24 -07:00
@@ -0,0 +1,44 @@
+/*
+ * linux/arch/arm/mach-iop3xx/mm.c
+ *
+ * Low level memory initialization for iq80321 platform
+ *
+ * Author: Rory Bolt <rorybolt@pacbell.net>
+ * Copyright (C) 2002 Rory Bolt
+ *
+ * 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/mm.h>
+#include <linux/init.h>
+
+#include <asm/io.h>
+#include <asm/pgtable.h>
+#include <asm/page.h>
+
+#include <asm/mach/map.h>
+#include <asm/mach-types.h>
+
+
+/*
+ * IQ80321 specific IO mappings
+ *
+ * We use RedBoot's setup for the onboard devices.
+ */
+static struct map_desc iq31244_io_desc[] __initdata = {
+ /* virtual     physical      length        type */
+
+ /* on-board devices */
+ { IQ31244_UART, IQ31244_UART,   0x00100000,   MT_DEVICE }
+};
+
+void __init iq31244_map_io(void)
+{
+	iop321_map_io();
+
+	iotable_init(iq31244_io_desc, ARRAY_SIZE(iq31244_io_desc));
+}
diff -Nru a/arch/arm/mach-iop3xx/iq31244-pci.c b/arch/arm/mach-iop3xx/iq31244-pci.c
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/arch/arm/mach-iop3xx/iq31244-pci.c	2004-10-18 14:57:24 -07:00
@@ -0,0 +1,134 @@
+/*
+ * arch/arm/mach-iop3xx/iq80321-pci.c
+ *
+ * PCI support for the Intel IQ80321 reference board
+ *
+ * Author: Rory Bolt <rorybolt@pacbell.net>
+ * Copyright (C) 2002 Rory Bolt
+ *
+ * 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/kernel.h>
+#include <linux/pci.h>
+#include <linux/init.h>
+
+#include <asm/hardware.h>
+#include <asm/irq.h>
+#include <asm/mach/pci.h>
+#include <asm/mach-types.h>
+
+/*
+ * The following macro is used to lookup irqs in a standard table
+ * format for those systems that do not already have PCI
+ * interrupts properly routed.  We assume 1 <= pin <= 4
+ */
+#define PCI_IRQ_TABLE_LOOKUP(minid,maxid)	\
+({ int _ctl_ = -1;				\
+   unsigned int _idsel = idsel - minid;		\
+   if (_idsel <= maxid)				\
+      _ctl_ = pci_irq_table[_idsel][pin-1];	\
+   _ctl_; })
+
+#define INTA	IRQ_IQ31244_INTA
+#define INTB	IRQ_IQ31244_INTB
+#define INTC	IRQ_IQ31244_INTC
+#define INTD	IRQ_IQ31244_INTD
+
+#define INTE	IRQ_IQ31244_I82546
+
+static inline int __init
+iq31244_map_irq(struct pci_dev *dev, u8 idsel, u8 pin)
+{
+	static int pci_irq_table[][4] = {
+		/*
+		 * PCI IDSEL/INTPIN->INTLINE
+		 * A       B       C       D
+		 */
+#ifdef CONFIG_ARCH_EP80219
+		{INTB, INTB, INTB, INTB}, /* CFlash */
+		{INTE, INTE, INTE, INTE}, /* 82551 Pro 100 */
+		{INTD, INTD, INTD, INTD}, /* PCI-X Slot */
+		{INTC, INTC, INTC, INTC}, /* SATA   */
+#else
+		{INTB, INTB, INTB, INTB}, /* CFlash */
+		{INTC, INTC, INTC, INTC}, /* SATA   */
+		{INTD, INTD, INTD, INTD}, /* PCI-X Slot */
+		{INTE, INTE, INTE, INTE}, /* 82546 GigE */
+#endif // CONFIG_ARCH_EP80219
+	};
+
+	BUG_ON(pin < 1 || pin > 4);
+
+	return PCI_IRQ_TABLE_LOOKUP(0, 7);
+}
+
+static int iq31244_setup(int nr, struct pci_sys_data *sys)
+{
+	struct resource *res;
+
+	if(nr != 0)
+		return 0;
+
+	res = kmalloc(sizeof(struct resource) * 2, GFP_KERNEL);
+	if (!res)
+		panic("PCI: unable to alloc resources");
+
+	memset(res, 0, sizeof(struct resource) * 2);
+
+	res[0].start = IQ31244_PCI_IO_BASE + 0x6e000000;
+	res[0].end   = IQ31244_PCI_IO_BASE + IQ31244_PCI_IO_SIZE - 1 + IQ31244_PCI_IO_OFFSET;
+	res[0].name  = "IQ31244 PCI I/O Space";
+	res[0].flags = IORESOURCE_IO;
+
+	res[1].start = IQ31244_PCI_MEM_BASE;
+	res[1].end   = IQ31244_PCI_MEM_BASE + IQ31244_PCI_MEM_SIZE;
+	res[1].name  = "IQ31244 PCI Memory Space";
+	res[1].flags = IORESOURCE_MEM;
+
+	request_resource(&ioport_resource, &res[0]);
+	request_resource(&iomem_resource, &res[1]);
+
+	sys->resource[0] = &res[0];
+	sys->resource[1] = &res[1];
+	sys->resource[2] = NULL;
+	sys->io_offset   = IQ31244_PCI_IO_OFFSET;
+	sys->mem_offset = IQ80321_PCI_MEM_BASE -
+		(*IOP321_IABAR1 & PCI_BASE_ADDRESS_MEM_MASK);
+
+	iop3xx_pcibios_min_io = IQ31244_PCI_IO_BASE;
+	iop3xx_pcibios_min_mem = IQ31244_PCI_MEM_BASE;
+
+	return 1;
+}
+
+static void iq31244_preinit(void)
+{
+	iop321_init();
+	/* setting up the second translation window */
+	*IOP321_OMWTVR1 = IQ31244_PCI_MEM_BASE + 0x04000000;
+	*IOP321_OUMWTVR1 = 0x0;
+}
+
+static struct hw_pci iq31244_pci __initdata = {
+	.swizzle	= pci_std_swizzle,
+	.nr_controllers = 1,
+	.setup		= iq31244_setup,
+	.scan		= iop321_scan_bus,
+	.preinit	= iq31244_preinit,
+	.map_irq	= iq31244_map_irq
+};
+
+static int __init iq31244_pci_init(void)
+{
+	if (machine_is_iq31244())
+		pci_common_init(&iq31244_pci);
+	return 0;
+}
+
+subsys_initcall(iq31244_pci_init);
+
+
+
+
diff -Nru a/arch/arm/mach-iop3xx/iq80310-irq.c b/arch/arm/mach-iop3xx/iq80310-irq.c
--- a/arch/arm/mach-iop3xx/iq80310-irq.c	2004-10-18 14:56:15 -07:00
+++ /dev/null	Wed Dec 31 16:00:00 196900
@@ -1,139 +0,0 @@
-/*
- * linux/arch/arm/mach-iop3xx/iq80310-irq.c
- *
- * IRQ hadling/demuxing for IQ80310 board
- *
- * Author:  Nicolas Pitre
- * Copyright:   (C) 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 version 2 as
- * published by the Free Software Foundation.
- *
- * 2.4.7-rmk1-iop310.1
- *     Moved demux from asm to C - DS
- *     Fixes for various revision boards - DS
- */
-#include <linux/init.h>
-#include <linux/list.h>
-
-#include <asm/irq.h>
-#include <asm/mach/irq.h>
-#include <asm/hardware.h>
-#include <asm/system.h>
-
-extern void iop310_init_irq(void);
-extern void iop310_irq_demux(unsigned int, struct irqdesc *, struct pt_regs *);
-
-static void iq80310_irq_mask(unsigned int irq)
-{
-	*(volatile char *)IQ80310_INT_MASK |= (1 << (irq - IQ80310_IRQ_OFS));
-}
-
-static void iq80310_irq_unmask(unsigned int irq)
-{
-	*(volatile char *)IQ80310_INT_MASK &= ~(1 << (irq - IQ80310_IRQ_OFS));
-}
-
-static struct irqchip iq80310_irq_chip = {
-	.ack	= iq80310_irq_mask,
-	.mask	= iq80310_irq_mask,
-	.unmask = iq80310_irq_unmask,
-};
-
-extern struct irqchip ext_chip;
-
-static void
-iq80310_cpld_irq_handler(unsigned int irq, struct irqdesc *desc,
-			 struct pt_regs *regs)
-{
-	unsigned int irq_stat = *(volatile u8*)IQ80310_INT_STAT;
-	unsigned int irq_mask = *(volatile u8*)IQ80310_INT_MASK;
-	unsigned int i, handled = 0;
-	struct irqdesc *d;
-
-	desc->chip->ack(irq);
-
-	/*
-	 * Mask out the interrupts which aren't enabled.
-	 */
-	irq_stat &= 0x1f & ~irq_mask;
-
-	/*
-	 * Test each IQ80310 CPLD interrupt
-	 */
-	for (i = IRQ_IQ80310_TIMER, d = irq_desc + IRQ_IQ80310_TIMER;
-	     irq_stat; i++, d++, irq_stat >>= 1)
-		if (irq_stat & 1) {
-			d->handle(i, d, regs);
-			handled++;
-		}
-
-	/*
-	 * If running on a board later than REV D.1, we can
-	 * decode the PCI interrupt status.
-	 */
-	if (system_rev) {
-		irq_stat = *((volatile u8*)IQ80310_PCI_INT_STAT) & 7;
-
-		for (i = IRQ_IQ80310_INTA, d = irq_desc + IRQ_IQ80310_INTA;
-		     irq_stat; i++, d++, irq_stat >>= 1)
-			if (irq_stat & 0x1) {
-				d->handle(i, d, regs);
-				handled++;
-			}
-	}
-
-	/*
-	 * If on a REV D.1 or lower board, we just assumed INTA
-	 * since PCI is not routed, and it may actually be an
-	 * on-chip interrupt.
-	 *
-	 * Note that we're giving on-chip interrupts slightly
-	 * higher priority than PCI by handling them first.
-	 *
-	 * On boards later than REV D.1, if we didn't read a
-	 * CPLD interrupt, we assume it's from a device on the
-	 * chipset itself.
-	 */
-	if (system_rev == 0 || handled == 0)
-		iop310_irq_demux(irq, desc, regs);
-
-	desc->chip->unmask(irq);
-}
-
-void __init iq80310_init_irq(void)
-{
-	volatile char *mask = (volatile char *)IQ80310_INT_MASK;
-	unsigned int i;
-
-	iop310_init_irq();
-
-	/*
-	 * Setup PIRSR to route PCI interrupts into xs80200
-	 */
-	*IOP310_PIRSR = 0xff;
-
-	/*
-	 * Setup the IRQs in the FE820000/FE860000 registers
-	 */
-	for (i = IQ80310_IRQ_OFS; i <= IRQ_IQ80310_INTD; i++) {
-		set_irq_chip(i, &iq80310_irq_chip);
-		set_irq_handler(i, do_level_IRQ);
-		set_irq_flags(i, IRQF_VALID | IRQF_PROBE);
-	}
-
-	/*
-	 * Setup the PCI IRQs
-	 */
-	for (i = IRQ_IQ80310_INTA; i < IRQ_IQ80310_INTC; i++) {
-		set_irq_chip(i, &ext_chip);
-		set_irq_handler(i, do_level_IRQ);
-		set_irq_flags(i, IRQF_VALID);
-	}
-
-	*mask = 0xff;  /* mask all sources */
-
-	set_irq_chained_handler(IRQ_XS80200_EXTIRQ,
-				&iq80310_cpld_irq_handler);
-}
diff -Nru a/arch/arm/mach-iop3xx/iq80310-pci.c b/arch/arm/mach-iop3xx/iq80310-pci.c
--- a/arch/arm/mach-iop3xx/iq80310-pci.c	2004-10-18 14:56:28 -07:00
+++ /dev/null	Wed Dec 31 16:00:00 196900
@@ -1,164 +0,0 @@
-/*
- * arch/arm/mach-iop3xx/iq80310-pci.c
- *
- * PCI support for the Intel IQ80310 reference board
- *
- * Matt Porter <mporter@mvista.com>
- *
- * Copyright (C) 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 version 2 as
- * published by the Free Software Foundation.
- */
-#include <linux/kernel.h>
-#include <linux/pci.h>
-#include <linux/init.h>
-
-#include <asm/hardware.h>
-#include <asm/irq.h>
-#include <asm/mach/pci.h>
-#include <asm/mach-types.h>
-
-/*
- * The following macro is used to lookup irqs in a standard table
- * format for those systems that do not already have PCI
- * interrupts properly routed.  We assume 1 <= pin <= 4
- */
-#define PCI_IRQ_TABLE_LOOKUP(minid,maxid)	\
-({ int _ctl_ = -1;				\
-   unsigned int _idsel = idsel - minid;		\
-   if (_idsel <= maxid)				\
-      _ctl_ = pci_irq_table[_idsel][pin-1];	\
-   _ctl_; })
-
-#define INTA	IRQ_IQ80310_INTA
-#define INTB	IRQ_IQ80310_INTB
-#define INTC	IRQ_IQ80310_INTC
-#define INTD	IRQ_IQ80310_INTD
-
-#define INTE	IRQ_IQ80310_I82559
-
-typedef u8 irq_table[4];
-
-/*
- * IRQ tables for primary bus.
- *
- * On a Rev D.1 and older board, INT A-C are not routed, so we
- * just fake it as INTA and than we take care of handling it
- * correctly in the IRQ demux routine.
- */
-static irq_table pci_pri_d_irq_table[] = {
-/* Pin:    A     B     C     D */
-	{ INTA, INTD, INTA, INTA }, /*  PCI Slot J3 */
-	{ INTD, INTA, INTA, INTA }, /*  PCI Slot J4 */
-};
-
-static irq_table pci_pri_f_irq_table[] = {
-/* Pin:    A     B     C     D */
-	{ INTC, INTD, INTA, INTB }, /*  PCI Slot J3 */
-	{ INTD, INTA, INTB, INTC }, /*  PCI Slot J4 */
-};
-
-static int __init
-iq80310_pri_map_irq(struct pci_dev *dev, u8 idsel, u8 pin)
-{
-	irq_table *pci_irq_table;
-
-	BUG_ON(pin < 1 || pin > 4);
-
-	if (!system_rev) {
-		pci_irq_table = pci_pri_d_irq_table;
-	} else {
-		pci_irq_table = pci_pri_f_irq_table;
-	}
-
-	return PCI_IRQ_TABLE_LOOKUP(2, 3);
-}
-
-/*
- * IRQ tables for secondary bus.
- *
- * On a Rev D.1 and older board, INT A-C are not routed, so we
- * just fake it as INTA and than we take care of handling it
- * correctly in the IRQ demux routine.
- */
-static irq_table pci_sec_d_irq_table[] = {
-/* Pin:    A     B     C     D */
-	{ INTA, INTA, INTA, INTD }, /*  PCI Slot J1 */
-	{ INTA, INTA, INTD, INTA }, /*  PCI Slot J5 */
-	{ INTE, INTE, INTE, INTE }, /*  P2P Bridge */
-};
-
-static irq_table pci_sec_f_irq_table[] = {
-/* Pin:	   A     B     C     D */
-	{ INTA, INTB, INTC, INTD }, /* PCI Slot J1 */
-	{ INTB, INTC, INTD, INTA }, /* PCI Slot J5 */
-	{ INTE, INTE, INTE, INTE }, /* P2P Bridge */
-};
-
-static int __init
-iq80310_sec_map_irq(struct pci_dev *dev, u8 idsel, u8 pin)
-{
-	irq_table *pci_irq_table;
-
-	BUG_ON(pin < 1 || pin > 4);
-
-	if (!system_rev) {
-		pci_irq_table = pci_sec_d_irq_table;
-	} else {
-		pci_irq_table = pci_sec_f_irq_table;
-	}
-
-	return PCI_IRQ_TABLE_LOOKUP(0, 2);
-}
-
-static int iq80310_pri_host;
-
-static int iq80310_setup(int nr, struct pci_sys_data *sys)
-{
-	switch (nr) {
-	case 0:
-		if (!iq80310_pri_host)
-			return 0;
-
-		sys->map_irq = iq80310_pri_map_irq;
-		break;
-
-	case 1:
-		sys->map_irq = iq80310_sec_map_irq;
-		break;
-
-	default:
-		return 0;
-	}
-
-	return iop310_setup(nr, sys);
-}
-
-static void iq80310_preinit(void)
-{
-	iq80310_pri_host = *(volatile u32 *)IQ80310_BACKPLANE & 1;
-
-	printk(KERN_INFO "PCI: IQ80310 is a%s\n",
-		iq80310_pri_host ? " system controller" : "n agent");
-
-	iop310_init();
-}
-
-static struct hw_pci iq80310_pci __initdata = {
-	.swizzle	= pci_std_swizzle,
-	.nr_controllers = 2,
-	.setup		= iq80310_setup,
-	.scan		= iop310_scan_bus,
-	.preinit	= iq80310_preinit,
-};
-
-static int __init iq80310_pci_init(void)
-{
-	if (machine_is_iq80310())
-		pci_common_init(&iq80310_pci);
-	return 0;
-}
-
-subsys_initcall(iq80310_pci_init);
diff -Nru a/arch/arm/mach-iop3xx/iq80310-time.c b/arch/arm/mach-iop3xx/iq80310-time.c
--- a/arch/arm/mach-iop3xx/iq80310-time.c	2004-10-18 14:56:49 -07:00
+++ /dev/null	Wed Dec 31 16:00:00 196900
@@ -1,124 +0,0 @@
-/*
- * linux/arch/arm/mach-iop3xx/time-iq80310.c
- *
- * Timer functions for IQ80310 onboard timer
- *
- * Author:  Nicolas Pitre
- * Copyright:   (C) 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 version 2 as
- * published by the Free Software Foundation.
- *
- */
-#include <linux/kernel.h>
-#include <linux/interrupt.h>
-#include <linux/time.h>
-#include <linux/init.h>
-#include <linux/timex.h>
-
-#include <asm/hardware.h>
-#include <asm/io.h>
-#include <asm/irq.h>
-#include <asm/uaccess.h>
-#include <asm/mach/irq.h>
-
-static void iq80310_write_timer (u_long val)
-{
-	volatile u_char *la0 = (volatile u_char *)IQ80310_TIMER_LA0;
-	volatile u_char *la1 = (volatile u_char *)IQ80310_TIMER_LA1;
-	volatile u_char *la2 = (volatile u_char *)IQ80310_TIMER_LA2;
-
-	*la0 = val;
-	*la1 = val >> 8;
-	*la2 = (val >> 16) & 0x3f;
-}
-
-static u_long iq80310_read_timer (void)
-{
-	volatile u_char *la0 = (volatile u_char *)IQ80310_TIMER_LA0;
-	volatile u_char *la1 = (volatile u_char *)IQ80310_TIMER_LA1;
-	volatile u_char *la2 = (volatile u_char *)IQ80310_TIMER_LA2;
-	volatile u_char *la3 = (volatile u_char *)IQ80310_TIMER_LA3;
-	u_long b0, b1, b2, b3, val;
-
-	b0 = *la0; b1 = *la1; b2 = *la2; b3 = *la3;
-	b0 = (((b0 & 0x40) >> 1) | (b0 & 0x1f));
-	b1 = (((b1 & 0x40) >> 1) | (b1 & 0x1f));
-	b2 = (((b2 & 0x40) >> 1) | (b2 & 0x1f));
-	b3 = (b3 & 0x0f);
-	val = ((b0 << 0) | (b1 << 6) | (b2 << 12) | (b3 << 18));
-	return val;
-}
-
-/*
- * IRQs are disabled before entering here from do_gettimeofday().
- * Note that the counter may wrap.  When it does, 'elapsed' will
- * be small, but we will have a pending interrupt.
- */
-static unsigned long iq80310_gettimeoffset (void)
-{
-	unsigned long elapsed, usec;
-	unsigned int stat1, stat2;
-
-	stat1 = *(volatile u8 *)IQ80310_INT_STAT;
-	elapsed = iq80310_read_timer();
-	stat2 = *(volatile u8 *)IQ80310_INT_STAT;
-
-	/*
-	 * If an interrupt was pending before we read the timer,
-	 * we've already wrapped.  Factor this into the time.
-	 * If an interrupt was pending after we read the timer,
-	 * it may have wrapped between checking the interrupt
-	 * status and reading the timer.  Re-read the timer to
-	 * be sure its value is after the wrap.
-	 */
-	if (stat1 & 1)
-		elapsed += LATCH;
-	else if (stat2 & 1)
-		elapsed = LATCH + iq80310_read_timer();
-
-	/*
-	 * Now convert them to usec.
-	 */
-	usec = (unsigned long)(elapsed * (tick_nsec / 1000))/LATCH;
-
-	return usec;
-}
-
-
-static irqreturn_t
-iq80310_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
-{
-	volatile u_char *timer_en = (volatile u_char *)IQ80310_TIMER_EN;
-
-	/* clear timer interrupt */
-	*timer_en &= ~2;
-	*timer_en |= 2;
-
-	do_timer(regs);
-
-	return IRQ_HANDLED;
-}
-
-extern unsigned long (*gettimeoffset)(void);
-
-static struct irqaction timer_irq = {
-	.name		= "timer",
-	.handler	= iq80310_timer_interrupt,
-};
-
-
-void __init time_init(void)
-{
-	volatile u_char *timer_en = (volatile u_char *)IQ80310_TIMER_EN;
-
-	gettimeoffset = iq80310_gettimeoffset;
-
-	setup_irq(IRQ_IQ80310_TIMER, &timer_irq);
-
-	*timer_en = 0;
-	iq80310_write_timer(LATCH);
-	*timer_en |= 2;
-	*timer_en |= 1;
-}
diff -Nru a/arch/arm/mach-iop3xx/iq80321-mm.c b/arch/arm/mach-iop3xx/iq80321-mm.c
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/arch/arm/mach-iop3xx/iq80321-mm.c	2004-10-18 14:57:24 -07:00
@@ -0,0 +1,44 @@
+/*
+ * linux/arch/arm/mach-iop3xx/mm.c
+ *
+ * Low level memory initialization for iq80321 platform
+ *
+ * Author: Rory Bolt <rorybolt@pacbell.net>
+ * Copyright (C) 2002 Rory Bolt
+ *
+ * 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/mm.h>
+#include <linux/init.h>
+
+#include <asm/io.h>
+#include <asm/pgtable.h>
+#include <asm/page.h>
+
+#include <asm/mach/map.h>
+#include <asm/mach-types.h>
+
+
+/*
+ * IQ80321 specific IO mappings
+ *
+ * We use RedBoot's setup for the onboard devices.
+ */
+static struct map_desc iq80321_io_desc[] __initdata = {
+ /* virtual     physical      length        type */
+
+ /* on-board devices */
+ { IQ80321_UART, IQ80321_UART,   0x00100000,   MT_DEVICE }
+};
+
+void __init iq80321_map_io(void)
+{
+	iop321_map_io();
+
+	iotable_init(iq80321_io_desc, ARRAY_SIZE(iq80321_io_desc));
+}
diff -Nru a/arch/arm/mach-iop3xx/iq80321-pci.c b/arch/arm/mach-iop3xx/iq80321-pci.c
--- a/arch/arm/mach-iop3xx/iq80321-pci.c	2004-10-18 14:57:04 -07:00
+++ b/arch/arm/mach-iop3xx/iq80321-pci.c	2004-10-18 14:57:04 -07:00
@@ -38,37 +38,79 @@
 
 #define INTE	IRQ_IQ80321_I82544
 
-typedef u8 irq_table[4];
-
-static irq_table pci_irq_table[] = {
-	/*
-	 * PCI IDSEL/INTPIN->INTLINE
-	 * A       B       C       D
-	 */
-	{INTE, INTE, INTE, INTE}, /* Gig-E */
-	{INTD, INTC, INTD, INTA}, /* Unused */
-	{INTC, INTD, INTA, INTB}, /* PCI-X Slot */
-};
-
 static inline int __init
 iq80321_map_irq(struct pci_dev *dev, u8 idsel, u8 pin)
 {
+	static int pci_irq_table[][4] = {
+		/*
+		 * PCI IDSEL/INTPIN->INTLINE
+		 * A       B       C       D
+		 */
+		{INTE, INTE, INTE, INTE}, /* Gig-E */
+		{-1, -1, -1, -1}, 	  /* Unused */
+		{INTC, INTD, INTA, INTB}, /* PCI-X Slot */
+		{-1, -1, -1, -1},
+	};
+
 	BUG_ON(pin < 1 || pin > 4);
 
-	return PCI_IRQ_TABLE_LOOKUP(2, 3);
+//	return PCI_IRQ_TABLE_LOOKUP(4, 7);
+	return pci_irq_table[idsel%4][pin-1];
 }
 
 static int iq80321_setup(int nr, struct pci_sys_data *sys)
 {
-	switch (nr) {
-	case 0:
-		sys->map_irq = iq80321_map_irq;
-		break;
-	default:
+	struct resource *res;
+
+	if(nr != 0)
 		return 0;
-	}
 
-	return iop321_setup(nr, sys);
+	res = kmalloc(sizeof(struct resource) * 2, GFP_KERNEL);
+	if (!res)
+		panic("PCI: unable to alloc resources");
+
+	memset(res, 0, sizeof(struct resource) * 2);
+
+	res[0].start = IQ80321_PCI_IO_BASE + IQ80321_PCI_IO_OFFSET;
+	res[0].end   = IQ80321_PCI_IO_BASE + IQ80321_PCI_IO_SIZE - 1 + IQ80321_PCI_IO_OFFSET;
+	res[0].name  = "IQ80321 PCI I/O Space";
+	res[0].flags = IORESOURCE_IO;
+
+	res[1].start = IQ80321_PCI_MEM_BASE;
+	res[1].end   = IQ80321_PCI_MEM_BASE + IQ80321_PCI_MEM_SIZE;
+	res[1].name  = "IQ80321 PCI Memory Space";
+	res[1].flags = IORESOURCE_MEM;
+
+	request_resource(&ioport_resource, &res[0]);
+	request_resource(&iomem_resource, &res[1]);
+
+	/*
+	 * Since the IQ80321 is a slave card on a PCI backplane,
+	 * it uses BAR1 to reserve a portion of PCI memory space for
+	 * use with the private devices on the secondary bus
+	 * (GigE and PCI-X slot). We read BAR1 and configure
+	 * our outbound translation windows to target that
+	 * address range and assign all devices in that
+	 * address range. W/O this, certain BIOSes will fail
+	 * to boot as the IQ80321 claims addresses that are
+	 * in use by other devices.
+	 *
+	 * Note that the same cannot be done  with I/O space,
+	 * so hopefully the host will stick to the lower 64K for
+	 * PCI I/O and leave us alone.
+	 */
+	sys->mem_offset = IQ80321_PCI_MEM_BASE -
+		(*IOP321_IABAR1 & PCI_BASE_ADDRESS_MEM_MASK);
+
+	sys->resource[0] = &res[0];
+	sys->resource[1] = &res[1];
+	sys->resource[2] = NULL;
+	sys->io_offset   = IQ80321_PCI_IO_OFFSET;
+
+	iop3xx_pcibios_min_io = IQ80321_PCI_IO_BASE;
+	iop3xx_pcibios_min_mem = IQ80321_PCI_MEM_BASE;
+
+	return 1;
 }
 
 static void iq80321_preinit(void)
@@ -82,6 +124,7 @@
 	.setup		= iq80321_setup,
 	.scan		= iop321_scan_bus,
 	.preinit	= iq80321_preinit,
+	.map_irq	= iq80321_map_irq
 };
 
 static int __init iq80321_pci_init(void)
diff -Nru a/arch/arm/mach-iop3xx/iq80331-mm.c b/arch/arm/mach-iop3xx/iq80331-mm.c
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/arch/arm/mach-iop3xx/iq80331-mm.c	2004-10-18 14:57:23 -07:00
@@ -0,0 +1,36 @@
+/*
+ * linux/arch/arm/mach-iop3xx/mm.c
+ *
+ * Low level memory initialization for iq80331 platform
+ *
+ * Author: Dave Jiang <dave.jiang@intel.com>
+ * Copyright (C) 2003 Intel Corp.
+ *
+ * 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/mm.h>
+#include <linux/init.h>
+
+#include <asm/io.h>
+#include <asm/pgtable.h>
+#include <asm/page.h>
+
+#include <asm/mach/map.h>
+#include <asm/mach-types.h>
+
+
+/*
+ * IQ80331 specific IO mappings
+ *
+ * We use RedBoot's setup for the onboard devices.
+ */
+
+void __init iq80331_map_io(void)
+{
+	iop331_map_io();
+}
diff -Nru a/arch/arm/mach-iop3xx/iq80331-pci.c b/arch/arm/mach-iop3xx/iq80331-pci.c
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/arch/arm/mach-iop3xx/iq80331-pci.c	2004-10-18 14:57:24 -07:00
@@ -0,0 +1,138 @@
+/*
+ * arch/arm/mach-iop3xx/iq80331-pci.c
+ *
+ * PCI support for the Intel IQ80331 reference board
+ *
+ * Author: Dave Jiang <dave.jiang@intel.com>
+ * Copyright (C) 2003 Intel Corp.
+ *
+ * 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/kernel.h>
+#include <linux/pci.h>
+#include <linux/init.h>
+
+#include <asm/hardware.h>
+#include <asm/irq.h>
+#include <asm/mach/pci.h>
+#include <asm/mach-types.h>
+
+/*
+ * The following macro is used to lookup irqs in a standard table
+ * format for those systems that do not already have PCI
+ * interrupts properly routed.  We assume 1 <= pin <= 4
+ */
+#define PCI_IRQ_TABLE_LOOKUP(minid,maxid)	\
+({ int _ctl_ = -1;				\
+   unsigned int _idsel = idsel - minid;		\
+   if (_idsel <= maxid)				\
+      _ctl_ = pci_irq_table[_idsel][pin-1];	\
+   _ctl_; })
+
+#define INTA	IRQ_IQ80331_INTA
+#define INTB	IRQ_IQ80331_INTB
+#define INTC	IRQ_IQ80331_INTC
+#define INTD	IRQ_IQ80331_INTD
+
+//#define INTE	IRQ_IQ80331_I82544
+
+static inline int __init
+iq80331_map_irq(struct pci_dev *dev, u8 idsel, u8 pin)
+{
+	static int pci_irq_table[][4] = {
+		/*
+		 * PCI IDSEL/INTPIN->INTLINE
+		 * A       B       C       D
+		 */
+		{INTB, INTC, INTD, INTA}, /* PCI-X Slot */
+		{INTC, INTC, INTC, INTC}, /* GigE  */
+	};
+
+	BUG_ON(pin < 1 || pin > 4);
+
+	return PCI_IRQ_TABLE_LOOKUP(1, 7);
+}
+
+static int iq80331_setup(int nr, struct pci_sys_data *sys)
+{
+	struct resource *res;
+
+	if(nr != 0)
+		return 0;
+
+	res = kmalloc(sizeof(struct resource) * 2, GFP_KERNEL);
+	if (!res)
+		panic("PCI: unable to alloc resources");
+
+	memset(res, 0, sizeof(struct resource) * 2);
+
+	res[0].start = IQ80331_PCI_IO_BASE + 0x6e000000;
+	res[0].end   = IQ80331_PCI_IO_BASE + IQ80331_PCI_IO_SIZE - 1 + IQ80331_PCI_IO_OFFSET;
+	res[0].name  = "IQ80331 PCI I/O Space";
+	res[0].flags = IORESOURCE_IO;
+
+	res[1].start = IQ80331_PCI_MEM_BASE;
+	res[1].end   = IQ80331_PCI_MEM_BASE + IQ80331_PCI_MEM_SIZE;
+	res[1].name  = "IQ80331 PCI Memory Space";
+	res[1].flags = IORESOURCE_MEM;
+
+	request_resource(&ioport_resource, &res[0]);
+	request_resource(&iomem_resource, &res[1]);
+
+	/*
+	 * Since the IQ80331 is a slave card on a PCI backplane,
+	 * it uses BAR1 to reserve a portion of PCI memory space for
+	 * use with the private devices on the secondary bus
+	 * (GigE and PCI-X slot). We read BAR1 and configure
+	 * our outbound translation windows to target that
+	 * address range and assign all devices in that
+	 * address range. W/O this, certain BIOSes will fail
+	 * to boot as the IQ80331 claims addresses that are
+	 * in use by other devices.
+	 *
+	 * Note that the same cannot be done  with I/O space,
+	 * so hopefully the host will stick to the lower 64K for
+	 * PCI I/O and leave us alone.
+	 */
+	sys->mem_offset = IQ80331_PCI_MEM_BASE -
+		(*IOP331_IABAR1 & PCI_BASE_ADDRESS_MEM_MASK);
+
+	sys->resource[0] = &res[0];
+	sys->resource[1] = &res[1];
+	sys->resource[2] = NULL;
+	sys->io_offset   = IQ80331_PCI_IO_OFFSET;
+
+	iop3xx_pcibios_min_io = IQ80331_PCI_IO_BASE;
+	iop3xx_pcibios_min_mem = IQ80331_PCI_MEM_BASE;
+
+	return 1;
+}
+
+static void iq80331_preinit(void)
+{
+	iop331_init();
+}
+
+static struct hw_pci iq80331_pci __initdata = {
+	.swizzle	= pci_std_swizzle,
+	.nr_controllers = 1,
+	.setup		= iq80331_setup,
+	.scan		= iop331_scan_bus,
+	.preinit	= iq80331_preinit,
+	.map_irq	= iq80331_map_irq
+};
+
+static int __init iq80331_pci_init(void)
+{
+	if (machine_is_iq80331())
+		pci_common_init(&iq80331_pci);
+	return 0;
+}
+
+subsys_initcall(iq80331_pci_init);
+
+
+
+
diff -Nru a/arch/arm/mach-iop3xx/mm.c b/arch/arm/mach-iop3xx/mm.c
--- a/arch/arm/mach-iop3xx/mm.c	2004-10-18 14:56:15 -07:00
+++ /dev/null	Wed Dec 31 16:00:00 196900
@@ -1,69 +0,0 @@
-/*
- * linux/arch/arm/mach-iop3xx/mm.c
- *
- * Low level memory initialization for IOP310 based systems
- *
- * Author: Nicolas Pitre <npitre@mvista.com>
- *
- * Copyright 2000-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.
- *
- */
-#include <linux/config.h>
-#include <linux/kernel.h>
-#include <linux/mm.h>
-#include <linux/init.h>
-
-#include <asm/io.h>
-#include <asm/pgtable.h>
-#include <asm/page.h>
-
-#include <asm/mach/map.h>
-
-#ifdef CONFIG_IOP310_MU
-#include "message.h"
-#endif
-
-/*
- * Standard IO mapping for all IOP310 based systems
- */
-static struct map_desc iop80310_std_desc[] __initdata = {
- /* virtual     physical      length       type */
- // IOP310 Memory Mapped Registers
- { 0xe8001000,  0x00001000,   0x00001000,  MT_DEVICE },
- // PCI I/O Space
- { 0xfe000000,  0x90000000,   0x00020000,  MT_DEVICE }
-};
-
-void __init iop310_map_io(void)
-{
-	iotable_init(iop80310_std_desc, ARRAY_SIZE(iop80310_std_desc));
-}
-
-/*
- * IQ80310 specific IO mappings
- */
-#ifdef CONFIG_ARCH_IQ80310
-static struct map_desc iq80310_io_desc[] __initdata = {
- /* virtual     physical      length        type */
- // IQ80310 On-Board Devices
- { 0xfe800000,  0xfe800000,   0x00100000,   MT_DEVICE }
-};
-
-void __init iq80310_map_io(void)
-{
-#ifdef CONFIG_IOP310_MU
-	/* acquiring 1MB of memory aligned on 1MB boundary for MU */
-	mu_mem = __alloc_bootmem(0x100000, 0x100000, 0);
-#endif
-
-	iop310_map_io();
-
-	iotable_init(iq80310_io_desc, ARRAY_SIZE(iq80310_io_desc));
-}
-#endif // CONFIG_ARCH_IQ80310
-
diff -Nru a/arch/arm/mach-iop3xx/xs80200-irq.c b/arch/arm/mach-iop3xx/xs80200-irq.c
--- a/arch/arm/mach-iop3xx/xs80200-irq.c	2004-10-18 14:56:33 -07:00
+++ /dev/null	Wed Dec 31 16:00:00 196900
@@ -1,63 +0,0 @@
-/*
- * linux/arch/arm/mach-iop3xx/xs80200-irq.c
- *
- * Generic IRQ handling for the XS80200 XScale core.
- *
- * Author:  Nicolas Pitre
- * Copyright:   (C) 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 version 2 as
- * published by the Free Software Foundation.
- */
-#include <linux/init.h>
-#include <linux/list.h>
-
-#include <asm/mach/irq.h>
-#include <asm/irq.h>
-#include <asm/hardware.h>
-
-static void xs80200_irq_mask (unsigned int irq)
-{
-	unsigned long intctl;
-	asm ("mrc p13, 0, %0, c0, c0, 0" : "=r" (intctl));
-	switch (irq) {
-	    case IRQ_XS80200_BCU:     intctl &= ~(1<<3); break;
-	    case IRQ_XS80200_PMU:     intctl &= ~(1<<2); break;
-	    case IRQ_XS80200_EXTIRQ:  intctl &= ~(1<<1); break;
-	    case IRQ_XS80200_EXTFIQ:  intctl &= ~(1<<0); break;
-	}
-	asm ("mcr p13, 0, %0, c0, c0, 0" : : "r" (intctl));
-}
-
-static void xs80200_irq_unmask (unsigned int irq)
-{
-	unsigned long intctl;
-	asm ("mrc p13, 0, %0, c0, c0, 0" : "=r" (intctl));
-	switch (irq) {
-	    case IRQ_XS80200_BCU:	intctl |= (1<<3); break;
-	    case IRQ_XS80200_PMU:	intctl |= (1<<2); break;
-	    case IRQ_XS80200_EXTIRQ:	intctl |= (1<<1); break;
-	    case IRQ_XS80200_EXTFIQ:	intctl |= (1<<0); break;
-	}
-	asm ("mcr p13, 0, %0, c0, c0, 0" : : "r" (intctl));
-}
-
-static struct irqchip xs80200_chip = {
-	.ack	= xs80200_irq_mask,
-	.mask	= xs80200_irq_mask,
-	.unmask = xs80200_irq_unmask,
-};
-
-void __init xs80200_init_irq(void)
-{
-	unsigned int i;
-
-	asm("mcr p13, 0, %0, c0, c0, 0" : : "r" (0));
-
-	for (i = 0; i < NR_XS80200_IRQS; i++) {
-		set_irq_chip(i, &xs80200_chip);
-		set_irq_handler(i, do_level_IRQ);
-		set_irq_flags(i, IRQF_VALID);
-	}
-}
diff -Nru a/arch/arm/mach-ixp2000/Kconfig b/arch/arm/mach-ixp2000/Kconfig
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/arch/arm/mach-ixp2000/Kconfig	2004-10-18 14:57:23 -07:00
@@ -0,0 +1,59 @@
+
+if ARCH_IXP2000
+
+config ARCH_SUPPORTS_BIG_ENDIAN
+	bool
+	default y
+
+menu "Intel IXP2400/2800 Implementation Options"
+
+comment "IXP2400/2800 Platforms"
+
+config ARCH_ENP2611
+	bool "Support Radisys ENP-2611"
+	help
+	  Say 'Y' here if you want your kernel to support the Radisys
+	  ENP2611 PCI network processing card. For more information on
+	  this card, see Documentation/arm/ENP2611.
+
+config ARCH_IXDP2400
+	bool "Support Intel IXDP2400"
+	help
+	  Say 'Y' here if you want your kernel to support the Intel
+	  IXDP2400 reference platform. For more information on
+	  this platform, see Documentation/arm/IXP2000.
+
+config ARCH_IXDP2800
+	bool "Support Intel IXDP2800"
+	help
+	  Say 'Y' here if you want your kernel to support the Intel
+	  IXDP2800 reference platform. For more information on
+	  this platform, see Documentation/arm/IXP2000.
+
+config ARCH_IXDP2X00
+	bool
+	depends on ARCH_IXDP2400 || ARCH_IXDP2800
+	default y	
+
+config ARCH_IXDP2401
+	bool "Support Intel IXDP2401"
+	help
+	  Say 'Y' here if you want your kernel to support the Intel
+	  IXDP2401 reference platform. For more information on
+	  this platform, see Documentation/arm/IXP2000.
+
+config ARCH_IXDP2801
+	bool "Support Intel IXDP2801"
+	help
+	  Say 'Y' here if you want your kernel to support the Intel
+	  IXDP2801 reference platform. For more information on
+	  this platform, see Documentation/arm/IXP2000.
+
+config ARCH_IXDP2X01
+	bool
+	depends on ARCH_IXDP2401 || ARCH_IXDP2801
+	default y	
+
+endmenu
+
+endif
diff -Nru a/arch/arm/mach-ixp2000/Makefile b/arch/arm/mach-ixp2000/Makefile
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/arch/arm/mach-ixp2000/Makefile	2004-10-18 14:57:23 -07:00
@@ -0,0 +1,14 @@
+#
+# Makefile for the linux kernel.
+#
+obj-y			:= core.o pci.o
+obj-m			:=
+obj-n			:=
+obj-			:=
+
+obj-$(CONFIG_ARCH_ENP2611)	+= enp2611.o
+obj-$(CONFIG_ARCH_IXDP2400)	+= ixdp2400.o
+obj-$(CONFIG_ARCH_IXDP2800)	+= ixdp2800.o
+obj-$(CONFIG_ARCH_IXDP2X00)	+= ixdp2x00.o
+obj-$(CONFIG_ARCH_IXDP2X01)	+= ixdp2x01.o
+
diff -Nru a/arch/arm/mach-ixp2000/core.c b/arch/arm/mach-ixp2000/core.c
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/arch/arm/mach-ixp2000/core.c	2004-10-18 14:57:24 -07:00
@@ -0,0 +1,426 @@
+/*
+ * arch/arm/mach-ixp2000/common.c
+ *
+ * Common routines used by all IXP2400/2800 based platforms.
+ *
+ * Author: Deepak Saxena <dsaxena@plexity.net>
+ *
+ * Copyright 2004 (C) MontaVista Software, Inc. 
+ *
+ * Based on work Copyright (C) 2002-2003 Intel Corporation
+ * 
+ * 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/kernel.h>
+#include <linux/init.h>
+#include <linux/spinlock.h>
+#include <linux/sched.h>
+#include <linux/interrupt.h>
+#include <linux/serial.h>
+#include <linux/tty.h>
+#include <linux/bitops.h>
+#include <linux/serial_core.h>
+#include <linux/mm.h>
+
+#include <asm/types.h>
+#include <asm/setup.h>
+#include <asm/memory.h>
+#include <asm/hardware.h>
+#include <asm/mach-types.h>
+#include <asm/irq.h>
+#include <asm/system.h>
+#include <asm/hardware.h>
+#include <asm/tlbflush.h>
+#include <asm/pgtable.h>
+#include <asm/mach-types.h>
+
+#include <asm/mach/map.h>
+#include <asm/mach/time.h>
+#include <asm/mach/irq.h>
+
+static spinlock_t ixp2000_slowport_lock = SPIN_LOCK_UNLOCKED;
+static unsigned long ixp2000_slowport_irq_flags;
+
+/*************************************************************************
+ * Slowport access routines
+ *************************************************************************/
+void ixp2000_acquire_slowport(struct slowport_cfg *new_cfg, struct slowport_cfg *old_cfg)
+{
+
+	spin_lock_irqsave(&ixp2000_slowport_lock, ixp2000_slowport_irq_flags);
+
+	old_cfg->CCR = *IXP2000_SLOWPORT_CCR;
+	old_cfg->WTC = *IXP2000_SLOWPORT_WTC2;
+	old_cfg->RTC = *IXP2000_SLOWPORT_RTC2;
+	old_cfg->PCR = *IXP2000_SLOWPORT_PCR;
+	old_cfg->ADC = *IXP2000_SLOWPORT_ADC;
+
+	ixp2000_reg_write(IXP2000_SLOWPORT_CCR, new_cfg->CCR);
+	ixp2000_reg_write(IXP2000_SLOWPORT_WTC2, new_cfg->WTC);
+	ixp2000_reg_write(IXP2000_SLOWPORT_RTC2, new_cfg->RTC);
+	ixp2000_reg_write(IXP2000_SLOWPORT_PCR, new_cfg->PCR);
+	ixp2000_reg_write(IXP2000_SLOWPORT_ADC, new_cfg->ADC);
+}
+
+void ixp2000_release_slowport(struct slowport_cfg *old_cfg)
+{
+	ixp2000_reg_write(IXP2000_SLOWPORT_CCR, old_cfg->CCR);
+	ixp2000_reg_write(IXP2000_SLOWPORT_WTC2, old_cfg->WTC);
+	ixp2000_reg_write(IXP2000_SLOWPORT_RTC2, old_cfg->RTC);
+	ixp2000_reg_write(IXP2000_SLOWPORT_PCR, old_cfg->PCR);
+	ixp2000_reg_write(IXP2000_SLOWPORT_ADC, old_cfg->ADC);
+
+	spin_unlock_irqrestore(&ixp2000_slowport_lock, 
+					ixp2000_slowport_irq_flags);
+}
+
+/*************************************************************************
+ * Chip specific mappings shared by all IXP2000 systems
+ *************************************************************************/
+static struct map_desc ixp2000_small_io_desc[] __initdata = {
+	{
+		.virtual	= IXP2000_GLOBAL_REG_VIRT_BASE,
+		.physical	= IXP2000_GLOBAL_REG_PHYS_BASE,
+		.length		= IXP2000_GLOBAL_REG_SIZE,
+		.type		= MT_DEVICE
+	}, {
+		.virtual	= IXP2000_GPIO_VIRT_BASE,
+		.physical	= IXP2000_GPIO_PHYS_BASE,
+		.length		= IXP2000_GPIO_SIZE,
+		.type		= MT_DEVICE
+	}, {
+		.virtual	= IXP2000_TIMER_VIRT_BASE,
+		.physical	= IXP2000_TIMER_PHYS_BASE,
+		.length		= IXP2000_TIMER_SIZE,
+		.type		= MT_DEVICE
+	}, {
+		.virtual	= IXP2000_UART_VIRT_BASE,
+		.physical	= IXP2000_UART_PHYS_BASE,
+		.length		= IXP2000_UART_SIZE,
+		.type		= MT_DEVICE
+	}, {
+		.virtual	= IXP2000_SLOWPORT_CSR_VIRT_BASE,
+		.physical	= IXP2000_SLOWPORT_CSR_PHYS_BASE,
+		.length		= IXP2000_SLOWPORT_CSR_SIZE,
+		.type		= MT_DEVICE
+	}, {
+		.virtual	= IXP2000_INTCTL_VIRT_BASE,
+		.physical	= IXP2000_INTCTL_PHYS_BASE,
+		.length		= IXP2000_INTCTL_SIZE,
+		.type		= MT_DEVICE
+	}, {
+		.virtual	= IXP2000_PCI_CREG_VIRT_BASE,
+		.physical	= IXP2000_PCI_CREG_PHYS_BASE,
+		.length		= IXP2000_PCI_CREG_SIZE,
+		.type		= MT_DEVICE
+	}
+};
+
+static struct map_desc ixp2000_large_io_desc[] __initdata = {
+	{
+		.virtual	= IXP2000_PCI_CSR_VIRT_BASE,
+		.physical	= IXP2000_PCI_CSR_PHYS_BASE,
+		.length		= IXP2000_PCI_CSR_SIZE,
+		.type		= MT_DEVICE
+	}, {
+		.virtual	= IXP2000_PCI_IO_VIRT_BASE,
+		.physical	= IXP2000_PCI_IO_PHYS_BASE,
+		.length		= IXP2000_PCI_IO_SIZE,
+		.type		= MT_DEVICE
+	}, {
+		.virtual	= IXP2000_PCI_CFG0_VIRT_BASE,
+		.physical	= IXP2000_PCI_CFG0_PHYS_BASE,
+		.length		= IXP2000_PCI_CFG0_SIZE,
+		.type		= MT_DEVICE
+	}, {
+		.virtual	= IXP2000_PCI_CFG1_VIRT_BASE,
+		.physical	= IXP2000_PCI_CFG1_PHYS_BASE,
+		.length		= IXP2000_PCI_CFG1_SIZE,
+		.type		= MT_DEVICE
+	}
+};
+
+static struct uart_port ixp2000_serial_port = {
+	.membase	= (char *)(IXP2000_UART_VIRT_BASE + 3),
+	.mapbase	= IXP2000_UART_PHYS_BASE + 3,
+	.irq		= IRQ_IXP2000_UART,
+	.flags		= UPF_SKIP_TEST,
+	.iotype		= UPIO_MEM,
+	.regshift	= 2,
+	.uartclk	= 50000000,
+	.line		= 0,
+	.type		= PORT_XSCALE,
+	.fifosize	= 16
+};
+
+void __init ixp2000_map_io(void)
+{
+	iotable_init(ixp2000_small_io_desc, ARRAY_SIZE(ixp2000_small_io_desc));
+	iotable_init(ixp2000_large_io_desc, ARRAY_SIZE(ixp2000_large_io_desc));
+	early_serial_setup(&ixp2000_serial_port);
+}
+
+/*************************************************************************
+ * Timer-tick functions for IXP2000
+ *************************************************************************/
+static unsigned ticks_per_jiffy;
+static unsigned ticks_per_usec;
+
+static unsigned long ixp2000_gettimeoffset (void)
+{
+	unsigned long elapsed;
+
+	/* Get ticks since last perfect jiffy */
+	elapsed = ticks_per_jiffy - *IXP2000_T1_CSR;
+
+	return elapsed / ticks_per_usec;
+}
+
+static int ixp2000_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+{
+	/* clear timer 1 */
+	ixp2000_reg_write(IXP2000_T1_CLR, 1);
+	
+	timer_tick(regs);
+
+	return IRQ_HANDLED;
+}
+
+static struct irqaction ixp2000_timer_irq = {
+	.name		= "IXP2000 Timer Tick",
+	.flags		= SA_INTERRUPT,
+	.handler	= ixp2000_timer_interrupt
+};
+
+void __init ixp2000_init_time(unsigned long tick_rate)
+{
+	gettimeoffset = ixp2000_gettimeoffset;
+
+	ixp2000_reg_write(IXP2000_T1_CLR, 0);
+	ixp2000_reg_write(IXP2000_T2_CLR, 0);
+
+	ticks_per_jiffy = (tick_rate + HZ/2) / HZ;
+	ticks_per_usec = tick_rate / 1000000;
+
+	ixp2000_reg_write(IXP2000_T1_CLD, ticks_per_jiffy);
+	ixp2000_reg_write(IXP2000_T1_CTL, (1 << 7));
+
+	/* register for interrupt */
+	setup_irq(IRQ_IXP2000_TIMER1, &ixp2000_timer_irq);
+}
+
+/*************************************************************************
+ * GPIO helpers
+ *************************************************************************/
+static unsigned long GPIO_IRQ_rising_edge;
+static unsigned long GPIO_IRQ_falling_edge;
+static unsigned long GPIO_IRQ_level_low;
+static unsigned long GPIO_IRQ_level_high;
+
+void gpio_line_config(int line, int style)
+{
+	unsigned long flags;
+
+	local_irq_save(flags);
+
+	if(style == GPIO_OUT) {
+		/* if it's an output, it ain't an interrupt anymore */
+		ixp2000_reg_write(IXP2000_GPIO_PDSR, (1 << line));
+		GPIO_IRQ_falling_edge &= ~(1 << line);
+		GPIO_IRQ_rising_edge &= ~(1 << line);
+		GPIO_IRQ_level_low &= ~(1 << line);
+		GPIO_IRQ_level_high &= ~(1 << line);
+		ixp2000_reg_write(IXP2000_GPIO_FEDR, GPIO_IRQ_falling_edge);
+		ixp2000_reg_write(IXP2000_GPIO_REDR, GPIO_IRQ_rising_edge);
+		ixp2000_reg_write(IXP2000_GPIO_LSHR, GPIO_IRQ_level_high);
+		ixp2000_reg_write(IXP2000_GPIO_LSLR, GPIO_IRQ_level_low);
+		irq_desc[line+IRQ_IXP2000_GPIO0].valid = 0;
+	} else if(style == GPIO_IN) {
+		ixp2000_reg_write(IXP2000_GPIO_PDCR, (1 << line));
+	}
+		
+	local_irq_restore(flags);
+}	
+
+
+/*************************************************************************
+ * IRQ handling IXP2000
+ *************************************************************************/
+static void ixp2000_GPIO_irq_handler(unsigned int irq, struct irqdesc *desc, struct pt_regs *regs)
+{                               
+	int i;
+	unsigned long status = *IXP2000_GPIO_INST;
+		   
+	for (i = 0; i <= 7; i++) {
+		if (status & (1<<i)) {
+			desc = irq_desc + i + IRQ_IXP2000_GPIO0;
+			desc->handle(i + IRQ_IXP2000_GPIO0, desc, regs);
+		}
+	}
+}
+
+static void ixp2000_GPIO_irq_mask_ack(unsigned int irq)
+{
+	ixp2000_reg_write(IXP2000_GPIO_INCR, (1 << (irq - IRQ_IXP2000_GPIO0)));
+	ixp2000_reg_write(IXP2000_GPIO_INST, (1 << (irq - IRQ_IXP2000_GPIO0)));
+}
+
+static void ixp2000_GPIO_irq_mask(unsigned int irq)
+{
+	ixp2000_reg_write(IXP2000_GPIO_INCR, (1 << (irq - IRQ_IXP2000_GPIO0)));
+}
+
+static void ixp2000_GPIO_irq_unmask(unsigned int irq)
+{
+	ixp2000_reg_write(IXP2000_GPIO_INSR, (1 << (irq - IRQ_IXP2000_GPIO0)));
+}
+
+static struct irqchip ixp2000_GPIO_irq_chip = {
+	.ack	= ixp2000_GPIO_irq_mask_ack,
+	.mask	= ixp2000_GPIO_irq_mask,
+	.unmask	= ixp2000_GPIO_irq_unmask
+};
+
+static void ixp2000_pci_irq_mask(unsigned int irq)
+{
+	unsigned long temp = *IXP2000_PCI_XSCALE_INT_ENABLE;
+	if (irq == IRQ_IXP2000_PCIA)
+		ixp2000_reg_write(IXP2000_PCI_XSCALE_INT_ENABLE, (temp & ~(1 << 26)));
+	else if (irq == IRQ_IXP2000_PCIB)
+		ixp2000_reg_write(IXP2000_PCI_XSCALE_INT_ENABLE, (temp & ~(1 << 27)));
+}
+
+static void ixp2000_pci_irq_unmask(unsigned int irq)
+{
+	unsigned long temp = *IXP2000_PCI_XSCALE_INT_ENABLE;
+	if (irq == IRQ_IXP2000_PCIA)
+		ixp2000_reg_write(IXP2000_PCI_XSCALE_INT_ENABLE, (temp | (1 << 26)));
+	else if (irq == IRQ_IXP2000_PCIB)
+		ixp2000_reg_write(IXP2000_PCI_XSCALE_INT_ENABLE, (temp | (1 << 27)));
+}
+
+static struct irqchip ixp2000_pci_irq_chip = {
+	.ack	= ixp2000_pci_irq_mask,
+	.mask	= ixp2000_pci_irq_mask,
+	.unmask	= ixp2000_pci_irq_unmask
+};
+
+/*
+ * Error interrupts. These are used extensively by the microengine drivers
+ */
+static void ixp2000_err_irq_handler(unsigned int irq, struct irqdesc *desc,  struct pt_regs *regs)
+{
+	int i;
+	unsigned long status = *IXP2000_IRQ_ERR_STATUS;
+
+
+	for (i = 0; i <= 12; i++) {
+		if (status & (1 << i)) {
+			desc = irq_desc + IRQ_IXP2000_DRAM0_MIN_ERR + i;
+			desc->handle(IRQ_IXP2000_DRAM0_MIN_ERR + i, desc, regs);
+		}
+	}
+}
+
+static void ixp2000_err_irq_mask(unsigned int irq)
+{
+	ixp2000_reg_write(IXP2000_IRQ_ERR_ENABLE_CLR,
+			(1 << (irq - IRQ_IXP2000_DRAM0_MIN_ERR)));
+}
+
+static void ixp2000_err_irq_unmask(unsigned int irq)
+{
+	ixp2000_reg_write(IXP2000_IRQ_ERR_ENABLE_SET,
+			(1 << (irq - IRQ_IXP2000_DRAM0_MIN_ERR)));
+}
+
+static struct irqchip ixp2000_err_irq_chip = {
+	.ack	= ixp2000_err_irq_mask,
+	.mask	= ixp2000_err_irq_mask,
+	.unmask	= ixp2000_err_irq_unmask
+};
+
+static void ixp2000_irq_mask(unsigned int irq)
+{
+	ixp2000_reg_write(IXP2000_IRQ_ENABLE_CLR, (1 << irq));
+}
+
+static void ixp2000_irq_unmask(unsigned int irq)
+{
+	ixp2000_reg_write(IXP2000_IRQ_ENABLE_SET,  (1 << irq));
+}
+
+static struct irqchip ixp2000_irq_chip = {
+	.ack	= ixp2000_irq_mask,
+	.mask	= ixp2000_irq_mask,
+	.unmask	= ixp2000_irq_unmask
+};
+
+void __init ixp2000_init_irq(void)
+{
+	int irq;
+
+	/*
+	 * Mask all sources
+	 */
+	ixp2000_reg_write(IXP2000_IRQ_ENABLE_CLR, 0xffffffff);
+	ixp2000_reg_write(IXP2000_FIQ_ENABLE_CLR, 0xffffffff);
+
+	/* clear all GPIO edge/level detects */
+	ixp2000_reg_write(IXP2000_GPIO_REDR, 0);
+	ixp2000_reg_write(IXP2000_GPIO_FEDR, 0);
+	ixp2000_reg_write(IXP2000_GPIO_LSHR, 0);
+	ixp2000_reg_write(IXP2000_GPIO_LSLR, 0);
+	ixp2000_reg_write(IXP2000_GPIO_INCR, -1);
+
+	/* clear PCI interrupt sources */
+	ixp2000_reg_write(IXP2000_PCI_XSCALE_INT_ENABLE, 0);
+
+	/*
+	 * Certain bits in the IRQ status register of the 
+	 * IXP2000 are reserved. Instead of trying to map
+	 * things non 1:1 from bit position to IRQ number,
+	 * we mark the reserved IRQs as invalid. This makes
+	 * our mask/unmask code much simpler.
+	 */
+	for (irq = IRQ_IXP2000_SWI; irq <= IRQ_IXP2000_THDB3; irq++) {
+		if((1 << irq) & IXP2000_VALID_IRQ_MASK) {
+			set_irq_chip(irq, &ixp2000_irq_chip);
+			set_irq_handler(irq, do_level_IRQ);
+			set_irq_flags(irq, IRQF_VALID);
+		} else set_irq_flags(irq, 0);
+	}
+	
+	/*
+	 * GPIO IRQs are invalid until someone sets the interrupt mode
+	 * by calling gpio_line_set();
+	 */
+	for (irq = IRQ_IXP2000_GPIO0; irq <= IRQ_IXP2000_GPIO7; irq++) {
+		set_irq_chip(irq, &ixp2000_GPIO_irq_chip);
+		set_irq_handler(irq, do_level_IRQ);
+		set_irq_flags(irq, 0);
+	}
+	set_irq_chained_handler(IRQ_IXP2000_GPIO, ixp2000_GPIO_irq_handler);
+
+	/*
+	 * Enable PCI irq
+	 */
+	*(IXP2000_IRQ_ENABLE_SET) = (1 << IRQ_IXP2000_PCI);
+	for (irq = IRQ_IXP2000_PCIA; irq <= IRQ_IXP2000_PCIB; irq++) {
+		set_irq_chip(irq, &ixp2000_pci_irq_chip);
+		set_irq_handler(irq, do_level_IRQ);
+		set_irq_flags(irq, IRQF_VALID);
+	}
+
+	for (irq = IRQ_IXP2000_DRAM0_MIN_ERR; irq <= IRQ_IXP2000_SP_INT; irq++) {
+		set_irq_chip(irq, &ixp2000_err_irq_chip);
+		set_irq_handler(irq, do_level_IRQ);
+		set_irq_flags(irq, IRQF_VALID);
+	}       
+	set_irq_chained_handler(IRQ_IXP2000_ERRSUM, ixp2000_err_irq_handler);
+}
+
diff -Nru a/arch/arm/mach-ixp2000/enp2611.c b/arch/arm/mach-ixp2000/enp2611.c
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/arch/arm/mach-ixp2000/enp2611.c	2004-10-18 14:57:23 -07:00
@@ -0,0 +1,210 @@
+/*
+ * arch/arm/mach-ixp2000/enp2611.c
+ *
+ * Radisys ENP-2611 support.
+ *
+ * Created 2004 by Lennert Buytenhek from the ixdp2x01 code.  The
+ * original version carries the following notices:
+ *
+ * Original Author: Andrzej Mialwoski <andrzej.mialwoski@intel.com>
+ * Maintainer: Deepak Saxena <dsaxena@plexity.net>
+ *
+ * Copyright (C) 2002-2003 Intel Corp.
+ * Copyright (C) 2003-2004 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.
+ */
+
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/mm.h>
+#include <linux/sched.h>
+#include <linux/interrupt.h>
+#include <linux/bitops.h>
+#include <linux/pci.h>
+#include <linux/interrupt.h>
+#include <linux/mm.h>
+#include <linux/init.h>
+#include <linux/ioport.h>
+#include <linux/slab.h>
+#include <linux/delay.h>
+#include <linux/serial.h>
+#include <linux/tty.h>
+#include <linux/serial_core.h>
+#include <linux/device.h>
+
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/pgtable.h>
+#include <asm/page.h>
+#include <asm/system.h>
+#include <asm/hardware.h>
+#include <asm/mach-types.h>
+
+#include <asm/mach/pci.h>
+#include <asm/mach/map.h>
+#include <asm/mach/irq.h>
+#include <asm/mach/time.h>
+#include <asm/mach/arch.h>
+#include <asm/mach/flash.h>
+
+/*************************************************************************
+ * ENP-2611 timer tick configuration
+ *************************************************************************/
+static void __init enp2611_init_time(void)
+{
+	ixp2000_init_time(50 * 1000 * 1000);
+}
+
+
+/*************************************************************************
+ * ENP-2611 PCI
+ *************************************************************************/
+static int enp2611_pci_setup(int nr, struct pci_sys_data *sys)
+{
+	sys->mem_offset = 0xe0000000;
+	ixp2000_pci_setup(nr, sys);
+	return 1;
+}
+
+static void __init enp2611_pci_preinit(void)
+{
+	ixp2000_reg_write(IXP2000_PCI_ADDR_EXT, 0x00100000);
+	ixp2000_pci_preinit();
+}
+
+static inline int enp2611_pci_valid_device(struct pci_bus *bus,
+						unsigned int devfn)
+{
+	/* The 82559 ethernet controller appears at both PCI:1:0:0 and
+	 * PCI:1:2:0, so let's pretend the second one isn't there.
+	 */
+	if (bus->number == 0x01 && devfn == 0x10)
+		return 0;
+
+	return 1;
+}
+
+static int enp2611_pci_read_config(struct pci_bus *bus, unsigned int devfn,
+					int where, int size, u32 *value)
+{
+	if (enp2611_pci_valid_device(bus, devfn))
+		return ixp2000_pci_read_config(bus, devfn, where, size, value);
+
+	return PCIBIOS_DEVICE_NOT_FOUND;
+}
+
+static int enp2611_pci_write_config(struct pci_bus *bus, unsigned int devfn,
+					int where, int size, u32 value)
+{
+	if (enp2611_pci_valid_device(bus, devfn))
+		return ixp2000_pci_write_config(bus, devfn, where, size, value);
+
+	return PCIBIOS_DEVICE_NOT_FOUND;
+}
+
+static struct pci_ops enp2611_pci_ops = {
+	.read   = enp2611_pci_read_config,
+	.write  = enp2611_pci_write_config
+};
+
+static struct pci_bus * __init enp2611_pci_scan_bus(int nr,
+						struct pci_sys_data *sys)
+{
+	return pci_scan_bus(sys->busnr, &enp2611_pci_ops, sys);
+}
+
+static int __init enp2611_pci_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
+{
+	int irq;
+
+	if (dev->bus->number == 0x00 && PCI_SLOT(dev->devfn) == 0x01) {
+		/* 21555 non-transparent bridge.  */
+		irq = IRQ_IXP2000_PCIB;
+	} else if (dev->bus->number == 0x01 && PCI_SLOT(dev->devfn) == 0x00) {
+		/* 82559 ethernet.  */
+		irq = IRQ_IXP2000_PCIA;
+	} else {
+		printk(KERN_INFO "enp2611_pci_map_irq for unknown device\n");
+		irq = IRQ_IXP2000_PCI;
+	}
+
+	printk(KERN_INFO "Assigned IRQ %d to PCI:%d:%d:%d\n", irq,
+		dev->bus->number, PCI_SLOT(dev->devfn), PCI_FUNC(dev->devfn));
+
+	return irq;
+}
+
+struct hw_pci enp2611_pci __initdata = {
+	.nr_controllers	= 1,
+	.setup		= enp2611_pci_setup,
+	.preinit	= enp2611_pci_preinit,
+	.scan		= enp2611_pci_scan_bus,
+	.map_irq	= enp2611_pci_map_irq,
+};
+
+int __init enp2611_pci_init(void)
+{
+	pci_common_init(&enp2611_pci);
+	return 0;
+}
+
+subsys_initcall(enp2611_pci_init);
+
+
+/*************************************************************************
+ * ENP-2611 Machine Intialization
+ *************************************************************************/
+static struct flash_platform_data enp2611_flash_platform_data = {
+	.map_name	= "cfi_probe",
+	.width		= 1,
+};
+
+static struct ixp2000_flash_data enp2611_flash_data = {
+	.platform_data	= &enp2611_flash_platform_data,
+	.nr_banks	= 1
+};
+
+static struct resource enp2611_flash_resource = {
+	.start		= 0xc4000000,
+	.end		= 0xc4000000 + 0x00ffffff,
+	.flags		= IORESOURCE_MEM,
+};
+
+static struct platform_device enp2611_flash = {
+	.name		= "IXP2000-Flash",
+	.id		= 0,
+	.dev		= {
+		.platform_data = &enp2611_flash_data,
+	},
+	.num_resources	= 1,
+	.resource	= &enp2611_flash_resource,
+};
+
+static struct platform_device *enp2611_devices[] __initdata = {
+	&enp2611_flash
+};
+
+static void __init enp2611_init_machine(void)
+{
+	platform_add_devices(enp2611_devices, ARRAY_SIZE(enp2611_devices));
+}
+
+
+#ifdef CONFIG_ARCH_ENP2611
+MACHINE_START(ENP2611, "Radisys ENP-2611 PCI network processor board")
+	MAINTAINER("Lennert Buytenhek <buytenh@wantstofly.org>")
+	BOOT_MEM(0x00000000, IXP2000_UART_PHYS_BASE, IXP2000_UART_VIRT_BASE)
+	BOOT_PARAMS(0x00000100)
+	MAPIO(ixp2000_map_io)
+	INITIRQ(ixp2000_init_irq)
+	INITTIME(enp2611_init_time)
+	INIT_MACHINE(enp2611_init_machine)
+MACHINE_END
+#endif
+
+
diff -Nru a/arch/arm/mach-ixp2000/ixdp2400.c b/arch/arm/mach-ixp2000/ixdp2400.c
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/arch/arm/mach-ixp2000/ixdp2400.c	2004-10-18 14:57:23 -07:00
@@ -0,0 +1,177 @@
+/*
+ * arch/arm/mach-ixp2000/ixdp2400.c
+ *
+ * IXDP2400 platform support
+ *
+ * Original Author: Naeem Afzal <naeem.m.afzal@intel.com>
+ * Maintainer: Deepak Saxena <dsaxena@plexity.net>
+ *
+ * Copyright (C) 2002 Intel Corp.
+ * Copyright (C) 2003-2004 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.
+ */
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/mm.h>
+#include <linux/sched.h>
+#include <linux/interrupt.h>
+#include <linux/device.h>
+#include <linux/bitops.h>
+#include <linux/pci.h>
+#include <linux/interrupt.h>
+#include <linux/mm.h>
+#include <linux/init.h>
+#include <linux/ioport.h>
+#include <linux/slab.h>
+#include <linux/delay.h>
+
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/pgtable.h>
+#include <asm/page.h>
+#include <asm/system.h>
+#include <asm/hardware.h>
+#include <asm/mach-types.h>
+
+#include <asm/mach/pci.h>
+#include <asm/mach/map.h>
+#include <asm/mach/irq.h>
+#include <asm/mach/time.h>
+#include <asm/mach/flash.h>
+#include <asm/mach/arch.h>
+
+/*************************************************************************
+ * IXDP2400 timer tick
+ *************************************************************************/
+static void __init ixdp2400_init_time(void)
+{
+	int numerator, denominator;
+	int denom_array[] = {2, 4, 8, 16, 1, 2, 4, 8};
+
+	numerator = (*(IXDP2400_CPLD_SYS_CLK_M) & 0xFF) *2;
+	denominator = denom_array[(*(IXDP2400_CPLD_SYS_CLK_N) & 0x7)];
+
+	ixp2000_init_time(((3125000 * numerator) / (denominator)) / 2);
+}
+
+/*************************************************************************
+ * IXDP2400 PCI
+ *************************************************************************/
+void __init ixdp2400_pci_preinit(void)
+{
+	ixp2000_reg_write(IXP2000_PCI_ADDR_EXT, 0x00100000);
+	ixp2000_pci_preinit();
+}
+
+int ixdp2400_pci_setup(int nr, struct pci_sys_data *sys)
+{
+	sys->mem_offset = 0xe0000000;
+
+	ixp2000_pci_setup(nr, sys);
+
+	return 1;
+}
+
+static int __init ixdp2400_pci_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
+{
+	if (ixdp2x00_master_npu()) {
+
+		/*
+		 * Root bus devices.  Slave NPU is only one with interrupt.
+		 * Everything else, we just return -1 b/c nothing else
+		 * on the root bus has interrupts.
+		 */
+		if(!dev->bus->self) {
+			if(dev->devfn == IXDP2X00_SLAVE_NPU_DEVFN )
+				return IRQ_IXDP2400_INGRESS_NPU;
+
+			return -1;
+		}
+
+		/*
+		 * Bridge behind the PMC slot.
+		 * NOTE: Only INTA from the PMC slot is routed. VERY BAD.
+		 */
+		if(dev->bus->self->devfn == IXDP2X00_PMC_DEVFN &&
+			dev->bus->parent->self->devfn == IXDP2X00_P2P_DEVFN &&
+			!dev->bus->parent->self->bus->parent)
+				  return IRQ_IXDP2400_PMC;
+
+		/*
+		 * Device behind the first bridge
+		 */
+		if(dev->bus->self->devfn == IXDP2X00_P2P_DEVFN) {
+			switch(dev->devfn) {
+				case IXDP2400_MASTER_ENET_DEVFN:	
+					return IRQ_IXDP2400_ENET;	
+			
+				case IXDP2400_MEDIA_DEVFN:
+					return IRQ_IXDP2400_MEDIA_PCI;
+
+				case IXDP2400_SWITCH_FABRIC_DEVFN:
+					return IRQ_IXDP2400_SF_PCI;
+
+				case IXDP2X00_PMC_DEVFN:
+					return IRQ_IXDP2400_PMC;
+			}
+		}
+
+		return -1;
+	} else return IRQ_IXP2000_PCIB; /* Slave NIC interrupt */
+}
+
+
+static void ixdp2400_pci_postinit(void)
+{
+	struct pci_dev *dev;
+
+	if (ixdp2x00_master_npu()) {
+		dev = pci_find_slot(1, IXDP2400_SLAVE_ENET_DEVFN);
+		pci_remove_bus_device(dev);
+	} else {
+		dev = pci_find_slot(1, IXDP2400_MASTER_ENET_DEVFN);
+		pci_remove_bus_device(dev);
+
+		ixdp2x00_slave_pci_postinit();
+	}
+}
+
+static struct hw_pci ixdp2400_pci __initdata = {
+	.nr_controllers	= 1,
+	.setup		= ixdp2400_pci_setup,
+	.preinit	= ixdp2400_pci_preinit,
+	.postinit	= ixdp2400_pci_postinit,
+	.scan		= ixp2000_pci_scan_bus,
+	.map_irq	= ixdp2400_pci_map_irq,
+};
+
+int __init ixdp2400_pci_init(void)
+{
+	if (machine_is_ixdp2400())
+		pci_common_init(&ixdp2400_pci);
+
+	return 0;
+}
+
+subsys_initcall(ixdp2400_pci_init);
+
+void ixdp2400_init_irq(void)
+{
+	ixdp2x00_init_irq(IXDP2400_CPLD_INT_STAT, IXDP2400_CPLD_INT_MASK, IXDP2400_NR_IRQS);
+}
+
+MACHINE_START(IXDP2400, "Intel IXDP2400 Development Platform")
+	MAINTAINER("MontaVista Software, Inc.")
+	BOOT_MEM(0x00000000, IXP2000_UART_PHYS_BASE, IXP2000_UART_VIRT_BASE)
+	BOOT_PARAMS(0x00000100)
+	MAPIO(ixdp2x00_map_io)
+	INITIRQ(ixdp2400_init_irq)
+	INITTIME(ixdp2400_init_time)
+	INIT_MACHINE(ixdp2x00_init_machine)
+MACHINE_END
+
diff -Nru a/arch/arm/mach-ixp2000/ixdp2800.c b/arch/arm/mach-ixp2000/ixdp2800.c
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/arch/arm/mach-ixp2000/ixdp2800.c	2004-10-18 14:57:23 -07:00
@@ -0,0 +1,178 @@
+/*
+ * arch/arm/mach-ixp2000/ixdp2800.c
+ *
+ * IXDP2800 platform support
+ *
+ * Original Author: Jeffrey Daly <jeffrey.daly@intel.com>
+ * Maintainer: Deepak Saxena <dsaxena@plexity.net>
+ *
+ * Copyright (C) 2002 Intel Corp.
+ * Copyright (C) 2003-2004 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.
+ */
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/mm.h>
+#include <linux/sched.h>
+#include <linux/interrupt.h>
+#include <linux/device.h>
+#include <linux/bitops.h>
+#include <linux/pci.h>
+#include <linux/interrupt.h>
+#include <linux/mm.h>
+#include <linux/init.h>
+#include <linux/ioport.h>
+#include <linux/slab.h>
+#include <linux/delay.h>
+
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/pgtable.h>
+#include <asm/page.h>
+#include <asm/system.h>
+#include <asm/hardware.h>
+#include <asm/mach-types.h>
+
+#include <asm/mach/pci.h>
+#include <asm/mach/map.h>
+#include <asm/mach/irq.h>
+#include <asm/mach/time.h>
+#include <asm/mach/flash.h>
+#include <asm/mach/arch.h>
+
+
+void ixdp2400_init_irq(void)
+{
+	ixdp2x00_init_irq(IXDP2800_CPLD_INT_STAT, IXDP2800_CPLD_INT_MASK, IXDP2400_NR_IRQS);
+}
+
+/*************************************************************************
+ * IXDP2800 timer tick
+ *************************************************************************/
+
+static void __init ixdp2800_init_time(void)
+{
+	ixp2000_init_time(50000000);
+}
+
+/*************************************************************************
+ * IXDP2800 PCI
+ *************************************************************************/
+void __init ixdp2800_pci_preinit(void)
+{
+	printk("ixdp2x00_pci_preinit called\n");
+
+	*IXP2000_PCI_ADDR_EXT =  0x0000e000;
+
+	*IXP2000_PCI_DRAM_BASE_ADDR_MASK = (0x40000000 - 1) & ~0xfffff;
+	*IXP2000_PCI_SRAM_BASE_ADDR_MASK = (0x2000000 - 1) & ~0x3ffff;
+
+	ixp2000_pci_preinit();
+}
+
+int ixdp2800_pci_setup(int nr, struct pci_sys_data *sys)
+{
+	sys->mem_offset = 0x00000000;
+
+	ixp2000_pci_setup(nr, sys);
+
+	return 1;
+}
+
+static int __init ixdp2800_pci_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
+{
+	if (ixdp2x00_master_npu()) {
+
+		/*
+		 * Root bus devices.  Slave NPU is only one with interrupt.
+		 * Everything else, we just return -1 which is invalid.
+		 */
+		if(!dev->bus->self) {
+			if(dev->devfn == IXDP2X00_SLAVE_NPU_DEVFN )
+				return IRQ_IXDP2800_INGRESS_NPU;
+
+			return -1;
+		}
+
+		/*
+		 * Bridge behind the PMC slot.
+		 */
+		if(dev->bus->self->devfn == IXDP2X00_PMC_DEVFN &&
+			dev->bus->parent->self->devfn == IXDP2X00_P2P_DEVFN &&
+			!dev->bus->parent->self->bus->parent)
+				  return IRQ_IXDP2800_PMC;
+
+		/*
+		 * Device behind the first bridge
+		 */
+		if(dev->bus->self->devfn == IXDP2X00_P2P_DEVFN) {
+			switch(PCI_SLOT(dev->devfn)) {
+				case IXDP2X00_PMC_DEVFN:
+					return IRQ_IXDP2800_PMC;	
+			
+				case IXDP2800_MASTER_ENET_DEVFN:
+					return IRQ_IXDP2800_EGRESS_ENET;
+
+				case IXDP2800_SWITCH_FABRIC_DEVFN:
+					return IRQ_IXDP2800_FABRIC;
+			}
+		}
+
+		return -1;
+	} else return IRQ_IXP2000_PCIB; /* Slave NIC interrupt */
+}
+
+static void ixdp2800_pci_postinit(void)
+{
+	struct pci_dev *dev;
+
+	if (ixdp2x00_master_npu()) {
+		dev = pci_find_slot(1, IXDP2800_SLAVE_ENET_DEVFN);
+		pci_remove_bus_device(dev);
+	} else {
+		dev = pci_find_slot(1, IXDP2800_MASTER_ENET_DEVFN);
+		pci_remove_bus_device(dev);
+
+		ixdp2x00_slave_pci_postinit();
+	}
+}
+
+struct hw_pci ixdp2800_pci __initdata = {
+	.nr_controllers	= 1,
+	.setup		= ixdp2800_pci_setup,
+	.preinit	= ixdp2800_pci_preinit,
+	.postinit	= ixdp2800_pci_postinit,
+	.scan		= ixp2000_pci_scan_bus,
+	.map_irq	= ixdp2800_pci_map_irq,
+};
+
+int __init ixdp2800_pci_init(void)
+{
+	if (machine_is_ixdp2800())
+		pci_common_init(&ixdp2800_pci);
+
+	return 0;
+}
+
+subsys_initcall(ixdp2800_pci_init);
+
+void ixdp2800_init_irq(void)
+{
+	ixdp2x00_init_irq(IXDP2800_CPLD_INT_STAT, IXDP2800_CPLD_INT_MASK, IXDP2800_NR_IRQS);
+}
+
+MACHINE_START(IXDP2800, "Intel IXDP2800 Development Platform")
+	MAINTAINER("MontaVista Software, Inc.")
+	BOOT_MEM(0x00000000, IXP2000_UART_PHYS_BASE, IXP2000_UART_VIRT_BASE)
+	BOOT_PARAMS(0x00000100)
+	MAPIO(ixdp2x00_map_io)
+	INITIRQ(ixdp2800_init_irq)
+	INITTIME(ixdp2800_init_time)
+	INIT_MACHINE(ixdp2x00_init_machine)
+MACHINE_END
+
diff -Nru a/arch/arm/mach-ixp2000/ixdp2x00.c b/arch/arm/mach-ixp2000/ixdp2x00.c
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/arch/arm/mach-ixp2000/ixdp2x00.c	2004-10-18 14:57:21 -07:00
@@ -0,0 +1,307 @@
+/*
+ * arch/arm/mach-ixp2000/ixdp2x00.c
+ *
+ * Code common to IXDP2400 and IXDP2800 platforms.
+ *
+ * Original Author: Naeem Afzal <naeem.m.afzal@intel.com>
+ * Maintainer: Deepak Saxena <dsaxena@plexity.net>
+ *
+ * Copyright (C) 2002 Intel Corp.
+ * Copyright (C) 2003-2004 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.
+ */
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/mm.h>
+#include <linux/sched.h>
+#include <linux/interrupt.h>
+#include <linux/device.h>
+#include <linux/bitops.h>
+#include <linux/pci.h>
+#include <linux/interrupt.h>
+#include <linux/mm.h>
+#include <linux/init.h>
+#include <linux/ioport.h>
+#include <linux/slab.h>
+#include <linux/delay.h>
+
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/pgtable.h>
+#include <asm/page.h>
+#include <asm/system.h>
+#include <asm/hardware.h>
+#include <asm/mach-types.h>
+
+#include <asm/mach/pci.h>
+#include <asm/mach/map.h>
+#include <asm/mach/irq.h>
+#include <asm/mach/time.h>
+#include <asm/mach/flash.h>
+#include <asm/mach/arch.h>
+
+/*************************************************************************
+ * IXDP2x00 IRQ Initialization
+ *************************************************************************/
+static volatile unsigned long *board_irq_mask;
+static volatile unsigned long *board_irq_stat;
+static unsigned long board_irq_count;
+
+#ifdef CONFIG_ARCH_IXDP2400
+/*
+ * Slowport configuration for accessing CPLD registers on IXDP2x00
+ */
+static struct slowport_cfg slowport_cpld_cfg = {
+	.CCR =	SLOWPORT_CCR_DIV_2,
+	.WTC = 0x00000070,
+	.RTC = 0x00000070,
+	.PCR = SLOWPORT_MODE_FLASH,
+	.ADC = SLOWPORT_ADDR_WIDTH_24 | SLOWPORT_DATA_WIDTH_8
+};
+#endif
+
+static void ixdp2x00_irq_mask(unsigned int irq)
+{
+	unsigned long dummy;
+	static struct slowport_cfg old_cfg;
+
+	/*
+	 * This is ugly in common code but really don't know
+	 * of a better way to handle it. :(
+	 */
+#ifdef CONFIG_ARCH_IXDP2400
+	if (machine_is_ixdp2400())
+		ixp2000_acquire_slowport(&slowport_cpld_cfg, &old_cfg);
+#endif
+
+	dummy = *board_irq_mask;
+	dummy |=  IXP2000_BOARD_IRQ_MASK(irq);
+	ixp2000_reg_write(board_irq_mask, dummy);
+
+#ifdef CONFIG_ARCH_IXDP2400
+	if (machine_is_ixdp2400())
+		ixp2000_release_slowport(&old_cfg);
+#endif
+}
+
+static void ixdp2x00_irq_unmask(unsigned int irq)
+{
+	unsigned long dummy;
+	static struct slowport_cfg old_cfg;
+
+#ifdef CONFGI_ARCH_IXDP2400
+	if (machine_is_ixdp2400())
+		ixp2000_acquire_slowport(&slowport_cpld_cfg, &old_cfg);
+#endif
+
+	dummy = *board_irq_mask;
+	dummy &=  ~IXP2000_BOARD_IRQ_MASK(irq);
+	ixp2000_reg_write(board_irq_mask, dummy);
+
+	if (machine_is_ixdp2400()) 
+		ixp2000_release_slowport(&old_cfg);
+}
+
+static void ixdp2x00_irq_handler(unsigned int irq, struct irqdesc *desc, struct pt_regs *regs)
+{
+        volatile u32 ex_interrupt = 0;
+	static struct slowport_cfg old_cfg;
+	int i;
+
+	desc->chip->mask(irq);
+
+#ifdef CONFIG_ARCH_IXDP2400
+	if (machine_is_ixdp2400())
+		ixp2000_acquire_slowport(&slowport_cpld_cfg, &old_cfg);
+#endif
+        ex_interrupt = *board_irq_stat & 0xff;
+	if (machine_is_ixdp2400())
+		ixp2000_release_slowport(&old_cfg);
+
+	if(!ex_interrupt) {
+		printk(KERN_ERR "Spurious IXDP2x00 CPLD interrupt!\n");
+		return;
+	}
+
+	for(i = 0; i < board_irq_count; i++) {
+		if(ex_interrupt & (1 << i))  {
+			struct irqdesc *cpld_desc;
+			int cpld_irq = IXP2000_BOARD_IRQ(0) + i;
+			cpld_desc = irq_desc + cpld_irq;
+			cpld_desc->handle(cpld_irq, cpld_desc, regs);
+		}
+	}
+
+	desc->chip->unmask(irq);
+}
+
+static struct irqchip ixdp2x00_cpld_irq_chip = {
+	.ack	= ixdp2x00_irq_mask,
+	.mask	= ixdp2x00_irq_mask,
+	.unmask	= ixdp2x00_irq_unmask
+};
+
+void ixdp2x00_init_irq(volatile unsigned long *stat_reg, volatile unsigned long *mask_reg, unsigned long nr_irqs)
+{
+	unsigned int irq;
+
+	ixp2000_init_irq();
+	
+	if (!ixdp2x00_master_npu())
+		return;
+
+	board_irq_stat = stat_reg;
+	board_irq_mask = mask_reg;
+	board_irq_count = nr_irqs;
+
+	*board_irq_mask = 0xffffffff;
+
+	for(irq = IXP2000_BOARD_IRQ(0); irq < IXP2000_BOARD_IRQ(board_irq_count); irq++) {
+		set_irq_chip(irq, &ixdp2x00_cpld_irq_chip);
+		set_irq_handler(irq, do_level_IRQ);
+		set_irq_flags(irq, IRQF_VALID);
+	}
+
+	/* Hook into PCI interrupt */
+	set_irq_chained_handler(IRQ_IXP2000_PCIB, &ixdp2x00_irq_handler);
+}
+
+/*************************************************************************
+ * IXDP2x00 memory map
+ *************************************************************************/
+static struct map_desc ixdp2x00_io_desc __initdata = {
+	.virtual	= IXDP2X00_VIRT_CPLD_BASE, 
+	.physical	= IXDP2X00_PHYS_CPLD_BASE,
+	.length		= IXDP2X00_CPLD_SIZE,
+	.type		= MT_DEVICE
+};
+
+void __init ixdp2x00_map_io(void)
+{
+	ixp2000_map_io();	
+
+	iotable_init(&ixdp2x00_io_desc, 1);
+}
+
+/*************************************************************************
+ * IXDP2x00-common PCI init
+ *
+ * The IXDP2[48]00 has a horrid PCI bus layout. Basically the board 
+ * contains two NPUs (ingress and egress) connected over PCI,  both running 
+ * instances  of the kernel. So far so good. Peers on the PCI bus running 
+ * Linux is a common design in telecom systems. The problem is that instead 
+ * of all the devices being controlled by a single host, different
+ * devices are controlles by different NPUs on the same bus, leading to
+ * multiple hosts on the bus.i The exact bus layout looks like:
+ *
+ *                   Bus 0
+ *    Master NPU <-------------------+-------------------> Slave NPU
+ *                                   |
+ *                                   |
+ *                                  P2P 
+ *                                   |
+ *
+ *                  Bus 1            |
+ *               <--+------+---------+---------+------+-->
+ *                  |      |         |         |      |
+ *                  |      |         |         |      |
+ *             ... Dev    PMC       Media     Eth0   Eth1 ...
+ *
+ * The master controlls all but Eth1, which is controlled by the
+ * slave. What this measn is that the both the master and the slave
+ * have to scan the bus, but only one of them can enumerate the bus.
+ * In addition, after the bus is scaned, each kernel must remove
+ * the device(s) it does not control from the PCI dev list otherwise
+ * a driver on each NPU will try to manage it and we will have horrible
+ * conflicts. Oh..and the slave NPU needs to see the master NPU
+ * for Intel's drivers to work properly. Closed source drivers...
+ *
+ * The way we deal with this is fairly simple but ugly:
+ *
+ * 1) Let master scan and enumerate the bus completely.
+ * 2) Master deletes Eth1 from device list.
+ * 3) Slave scans bus and then deletes all but Eth1 (Eth0 on slave)
+ *    from device list.
+ * 4) Find HW designers and LART them.
+ *
+ * The boards also do not do normal PCI IRQ routing, or any sort of 
+ * sensical  swizzling, so we just need to check where on the  bus a
+ * device sits and figure out to which CPLD pin the interrupt is routed.
+ * See ixdp2[48]00.c files.
+ *
+ *************************************************************************/
+void ixdp2x00_slave_pci_postinit(void)
+{
+	struct pci_dev *dev;
+
+	/*
+	 * Remove PMC device is there is one
+	 */
+	if((dev = pci_find_slot(1, IXDP2X00_PMC_DEVFN)))
+		pci_remove_bus_device(dev);
+
+	dev = pci_find_slot(0, IXDP2X00_21555_DEVFN);
+	pci_remove_bus_device(dev);
+}
+
+/**************************************************************************
+ * IXDP2x00 Machine Setup
+ *************************************************************************/
+static struct flash_platform_data ixdp2x00_platform_data = {
+	.map_name	= "cfi_probe",
+	.width		= 1,
+};
+
+static struct ixp2000_flash_data ixdp2x00_flash_data = {
+	.platform_data	= &ixdp2x00_platform_data,
+	.nr_banks	= 1
+};
+
+static struct resource ixdp2x00_flash_resource = {
+	.start		= 0xc4000000,
+	.end		= 0xc4000000 + 0x00ffffff,
+	.flags		= IORESOURCE_MEM,
+};
+
+static struct platform_device ixdp2x00_flash = {
+	.name		= "IXP2000-Flash",
+	.id		= 0,
+	.dev		= {
+		.platform_data = &ixdp2x00_flash_data,
+	},
+	.num_resources	= 1,
+	.resource	= &ixdp2x00_flash_resource,
+};
+
+static struct ixp2000_i2c_pins ixdp2x00_i2c_gpio_pins = {
+	.sda_pin	= IXDP2X00_GPIO_SDA,
+	.scl_pin	= IXDP2X00_GPIO_SCL,
+};
+
+static struct platform_device ixdp2x00_i2c_controller = {
+	.name		= "IXP2000-I2C",
+	.id		= 0,
+	.dev		= {
+		.platform_data = &ixdp2x00_i2c_gpio_pins,
+	},
+	.num_resources	= 0
+};
+
+static struct platform_device *ixdp2x00_devices[] __initdata = {
+	&ixdp2x00_flash,
+	&ixdp2x00_i2c_controller
+};
+
+void __init ixdp2x00_init_machine(void)
+{
+	gpio_line_set(IXDP2X00_GPIO_I2C_ENABLE, 1);
+	gpio_line_config(IXDP2X00_GPIO_I2C_ENABLE, GPIO_OUT);
+
+	platform_add_devices(ixdp2x00_devices, ARRAY_SIZE(ixdp2x00_devices));
+}
+
diff -Nru a/arch/arm/mach-ixp2000/ixdp2x01.c b/arch/arm/mach-ixp2000/ixdp2x01.c
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/arch/arm/mach-ixp2000/ixdp2x01.c	2004-10-18 14:57:21 -07:00
@@ -0,0 +1,381 @@
+/*
+ * arch/arm/mach-ixp2000/ixdp2x01.c
+ *
+ * Code common to Intel IXDP2401 and IXDP2801 platforms
+ *
+ * Original Author: Andrzej Mialwoski <andrzej.mialwoski@intel.com>
+ * Maintainer: Deepak Saxena <dsaxena@plexity.net>
+ *
+ * Copyright (C) 2002-2003 Intel Corp.
+ * Copyright (C) 2003-2004 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.
+ */
+
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/mm.h>
+#include <linux/sched.h>
+#include <linux/interrupt.h>
+#include <linux/bitops.h>
+#include <linux/pci.h>
+#include <linux/interrupt.h>
+#include <linux/mm.h>
+#include <linux/init.h>
+#include <linux/ioport.h>
+#include <linux/slab.h>
+#include <linux/delay.h>
+#include <linux/serial.h>
+#include <linux/tty.h>
+#include <linux/serial_core.h>
+#include <linux/device.h>
+
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/pgtable.h>
+#include <asm/page.h>
+#include <asm/system.h>
+#include <asm/hardware.h>
+#include <asm/mach-types.h>
+
+#include <asm/mach/pci.h>
+#include <asm/mach/map.h>
+#include <asm/mach/irq.h>
+#include <asm/mach/time.h>
+#include <asm/mach/arch.h>
+#include <asm/mach/flash.h>
+
+/*************************************************************************
+ * IXDP2x01 IRQ Handling
+ *************************************************************************/
+static void ixdp2x01_irq_mask(unsigned int irq)
+{
+	*IXDP2X01_INT_MASK_SET_REG = IXP2000_BOARD_IRQ_MASK(irq);
+}
+
+static void ixdp2x01_irq_unmask(unsigned int irq)
+{
+	*IXDP2X01_INT_MASK_CLR_REG = IXP2000_BOARD_IRQ_MASK(irq);
+}
+
+static u32 valid_irq_mask;
+
+static void ixdp2x01_irq_handler(unsigned int irq, struct irqdesc *desc, struct pt_regs *regs)
+{
+	u32 ex_interrupt;
+	int i;
+
+	desc->chip->mask(irq);
+
+	ex_interrupt = *IXDP2X01_INT_STAT_REG & valid_irq_mask;
+
+	if (!ex_interrupt) {
+		printk(KERN_ERR "Spurious IXDP2X01 CPLD interrupt!\n");
+		return;
+	}
+
+	for (i = 0; i < IXP2000_BOARD_IRQS; i++) {
+		if (ex_interrupt & (1 << i)) {
+			struct irqdesc *cpld_desc;
+			int cpld_irq = IXP2000_BOARD_IRQ(0) + i;
+			cpld_desc = irq_desc + cpld_irq;
+			cpld_desc->handle(cpld_irq, cpld_desc, regs);
+		}
+	}
+
+	desc->chip->unmask(irq);
+}
+
+static struct irqchip ixdp2x01_irq_chip = {
+	.mask	= ixdp2x01_irq_mask,
+	.ack	= ixdp2x01_irq_mask,
+	.unmask	= ixdp2x01_irq_unmask
+};
+
+/*
+ * We only do anything if we are the master NPU on the board.
+ * The slave NPU only has the ethernet chip going directly to
+ * the PCIB interrupt input.
+ */
+void __init ixdp2x01_init_irq(void)
+{
+	int irq = 0;
+
+	/* initialize chip specific interrupts */
+	ixp2000_init_irq();
+
+	if (machine_is_ixdp2401())
+		valid_irq_mask = IXDP2401_VALID_IRQ_MASK;
+	else
+		valid_irq_mask = IXDP2801_VALID_IRQ_MASK;
+
+	/* Mask all interrupts from CPLD, disable simulation */
+	*IXDP2X01_INT_MASK_SET_REG = 0xffffffff;
+	*IXDP2X01_INT_SIM_REG = 0;
+
+	for (irq = NR_IXP2000_IRQS; irq < NR_IXDP2X01_IRQS; irq++) {
+		if (irq & valid_irq_mask) {
+			set_irq_chip(irq, &ixdp2x01_irq_chip);
+			set_irq_handler(irq, do_level_IRQ);
+			set_irq_flags(irq, IRQF_VALID);
+		} else {
+			set_irq_flags(irq, 0);
+		}
+	}
+
+	/* Hook into PCI interrupts */
+	set_irq_chained_handler(IRQ_IXP2000_PCIB, &ixdp2x01_irq_handler);
+}
+
+
+/*************************************************************************
+ * IXDP2x01 memory map and serial ports
+ *************************************************************************/
+static struct map_desc ixdp2x01_io_desc __initdata = {
+	.virtual	= IXDP2X01_VIRT_CPLD_BASE, 
+	.physical	= IXDP2X01_PHYS_CPLD_BASE,
+	.length		= IXDP2X01_CPLD_REGION_SIZE,
+	.type		= MT_DEVICE
+};
+
+static struct uart_port ixdp2x01_serial_ports[2] = {
+	{
+		.membase	= (char *)(IXDP2X01_UART1_VIRT_BASE),
+		.mapbase	= (unsigned long)IXDP2X01_UART1_PHYS_BASE,
+		.irq		= IRQ_IXDP2X01_UART1,
+		.flags		= UPF_SKIP_TEST,
+		.iotype		= UPIO_MEM32,
+		.regshift	= 2,
+		.uartclk	= IXDP2X01_UART_CLK,
+		.line		= 1,
+		.type		= PORT_16550A,
+		.fifosize	= 16
+	}, {
+		.membase	= (char *)(IXDP2X01_UART2_VIRT_BASE),
+		.mapbase	= (unsigned long)IXDP2X01_UART2_PHYS_BASE,
+		.irq		= IRQ_IXDP2X01_UART2,
+		.flags		= UPF_SKIP_TEST,
+		.iotype		= UPIO_MEM32,
+		.regshift	= 2,
+		.uartclk	= IXDP2X01_UART_CLK,
+		.line		= 2,
+		.type		= PORT_16550A,
+		.fifosize	= 16
+	}, 
+};
+
+static void __init ixdp2x01_map_io(void)
+{
+	ixp2000_map_io();	
+
+	iotable_init(&ixdp2x01_io_desc, 1);
+
+	early_serial_setup(&ixdp2x01_serial_ports[0]);
+	early_serial_setup(&ixdp2x01_serial_ports[1]);
+}
+
+
+/*************************************************************************
+ * IXDP2x01 timer tick configuration
+ *************************************************************************/
+static unsigned int ixdp2x01_clock;
+
+static int __init ixdp2x01_clock_setup(char *str)
+{
+	ixdp2x01_clock = simple_strtoul(str, NULL, 10);
+
+	return 1;
+}
+
+__setup("ixdp2x01_clock=", ixdp2x01_clock_setup);
+
+static void __init ixdp2x01_init_time(void)
+{
+	if (!ixdp2x01_clock)
+		ixdp2x01_clock = 50000000;
+
+	ixp2000_init_time(ixdp2x01_clock);
+}
+
+/*************************************************************************
+ * IXDP2x01 PCI
+ *************************************************************************/
+void __init ixdp2x01_pci_preinit(void)
+{
+	ixp2000_reg_write(IXP2000_PCI_ADDR_EXT, 0x00000000);
+	ixp2000_pci_preinit();
+}
+
+#define DEVPIN(dev, pin) ((pin) | ((dev) << 3))
+
+static int __init ixdp2x01_pci_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
+{
+	u8 bus = dev->bus->number;
+	u32 devpin = DEVPIN(PCI_SLOT(dev->devfn), pin);
+	struct pci_bus *tmp_bus = dev->bus;
+
+	/* Primary bus, no interrupts here */
+	if (bus == 0) {
+		return -1;
+	}
+
+	/* Lookup first leaf in bus tree */
+	while ((tmp_bus->parent != NULL) && (tmp_bus->parent->parent != NULL)) {
+		tmp_bus = tmp_bus->parent;
+	}
+
+	/* Select between known bridges */
+	switch (tmp_bus->self->devfn | (tmp_bus->self->bus->number << 8)) {
+	/* Device is located after first MB bridge */
+	case 0x0008:
+		if (tmp_bus == dev->bus) {
+			/* Device is located directy after first MB bridge */
+			switch (devpin) {
+			case DEVPIN(1, 1):	/* Onboard 82546 ch 0 */
+				if (machine_is_ixdp2401())
+					return IRQ_IXDP2401_INTA_82546;
+				return -1;
+			case DEVPIN(1, 2):	/* Onboard 82546 ch 1 */
+				if (machine_is_ixdp2401())
+					return IRQ_IXDP2401_INTB_82546;
+				return -1;
+			case DEVPIN(0, 1):	/* PMC INTA# */
+				return IRQ_IXDP2X01_SPCI_PMC_INTA;
+			case DEVPIN(0, 2):	/* PMC INTB# */
+				return IRQ_IXDP2X01_SPCI_PMC_INTB;
+			case DEVPIN(0, 3):	/* PMC INTC# */
+				return IRQ_IXDP2X01_SPCI_PMC_INTC;
+			case DEVPIN(0, 4):	/* PMC INTD# */
+				return IRQ_IXDP2X01_SPCI_PMC_INTD;
+			}
+		}
+		break;
+	case 0x0010:
+		if (tmp_bus == dev->bus) {
+			/* Device is located directy after second MB bridge */
+			/* Secondary bus of second bridge */
+			switch (devpin) {
+			case DEVPIN(0, 1):	/* DB#0 */
+				return IRQ_IXDP2X01_SPCI_DB_0;
+			case DEVPIN(1, 1):	/* DB#1 */
+				return IRQ_IXDP2X01_SPCI_DB_1;
+			}
+		} else {
+			/* Device is located indirectly after second MB bridge */
+			/* Not supported now */
+		}
+		break;
+	}
+
+	return -1;
+}
+
+
+static int ixdp2x01_pci_setup(int nr, struct pci_sys_data *sys)
+{
+	sys->mem_offset = 0xe0000000;
+
+	if (machine_is_ixdp2801())
+		sys->mem_offset -= ((*IXP2000_PCI_ADDR_EXT & 0xE000) << 16);
+
+	return ixp2000_pci_setup(nr, sys);
+}
+
+struct hw_pci ixdp2x01_pci __initdata = {
+	.nr_controllers	= 1,
+	.setup		= ixdp2x01_pci_setup,
+	.preinit	= ixdp2x01_pci_preinit,
+	.scan		= ixp2000_pci_scan_bus,
+	.map_irq	= ixdp2x01_pci_map_irq,
+};
+
+int __init ixdp2x01_pci_init(void)
+{
+
+	pci_common_init(&ixdp2x01_pci);
+	return 0;
+}
+
+subsys_initcall(ixdp2x01_pci_init);
+
+/*************************************************************************
+ * IXDP2x01 Machine Intialization
+ *************************************************************************/
+static struct flash_platform_data ixdp2x01_flash_platform_data = {
+	.map_name	= "cfi_probe",
+	.width		= 1,
+};
+
+static unsigned long ixdp2x01_flash_bank_setup(unsigned long ofs)
+{
+	*IXDP2X01_CPLD_FLASH_REG = 
+		((ofs >> IXDP2X01_FLASH_WINDOW_BITS) | IXDP2X01_CPLD_FLASH_INTERN);
+	return (ofs & IXDP2X01_FLASH_WINDOW_MASK);
+}
+
+static struct ixp2000_flash_data ixdp2x01_flash_data = {
+	.platform_data	= &ixdp2x01_flash_platform_data,
+	.bank_setup	= ixdp2x01_flash_bank_setup
+};
+
+static struct resource ixdp2x01_flash_resource = {
+	.start		= 0xc4000000,
+	.end		= 0xc4000000 + 0x01ffffff,
+	.flags		= IORESOURCE_MEM,
+};
+
+static struct platform_device ixdp2x01_flash = {
+	.name		= "IXP2000-Flash",
+	.id		= 0,
+	.dev		= {
+		.platform_data = &ixdp2x01_flash_data,
+	},
+	.num_resources	= 1,
+	.resource	= &ixdp2x01_flash_resource,
+};
+
+static struct platform_device *ixdp2x01_devices[] __initdata = {
+	&ixdp2x01_flash
+};
+
+static void __init ixdp2x01_init_machine(void)
+{
+	*IXDP2X01_CPLD_FLASH_REG = 
+		(IXDP2X01_CPLD_FLASH_BANK_MASK | IXDP2X01_CPLD_FLASH_INTERN);
+	
+	ixdp2x01_flash_data.nr_banks =
+		((*IXDP2X01_CPLD_FLASH_REG & IXDP2X01_CPLD_FLASH_BANK_MASK) + 1);
+
+	platform_add_devices(ixdp2x01_devices, ARRAY_SIZE(ixdp2x01_devices));
+}
+
+
+#ifdef CONFIG_ARCH_IXDP2401
+MACHINE_START(IXDP2401, "Intel IXDP2401 Development Platform")
+	MAINTAINER("MontaVista Software, Inc.")
+	BOOT_MEM(0x00000000, IXP2000_UART_PHYS_BASE, IXP2000_UART_VIRT_BASE)
+	BOOT_PARAMS(0x00000100)
+	MAPIO(ixdp2x01_map_io)
+	INITIRQ(ixdp2x01_init_irq)
+	INITTIME(ixdp2x01_init_time)
+	INIT_MACHINE(ixdp2x01_init_machine)
+MACHINE_END
+#endif
+
+#ifdef CONFIG_ARCH_IXDP2801
+MACHINE_START(IXDP2801, "Intel IXDP2801 Development Platform")
+	MAINTAINER("MontaVista Software, Inc.")
+	BOOT_MEM(0x00000000, IXP2000_UART_PHYS_BASE, IXP2000_UART_VIRT_BASE)
+	BOOT_PARAMS(0x00000100)
+	MAPIO(ixdp2x01_map_io)
+	INITIRQ(ixdp2x01_init_irq)
+	INITTIME(ixdp2x01_init_time)
+	INIT_MACHINE(ixdp2x01_init_machine)
+MACHINE_END
+#endif
+
+
diff -Nru a/arch/arm/mach-ixp2000/pci.c b/arch/arm/mach-ixp2000/pci.c
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/arch/arm/mach-ixp2000/pci.c	2004-10-18 14:57:23 -07:00
@@ -0,0 +1,233 @@
+/*
+ * arch/arm/mach-ixp2000/pci.c
+ *
+ * PCI routines for IXDP2400/IXDP2800 boards
+ *
+ * Original Author: Naeem Afzal <naeem.m.afzal@intel.com>
+ * Maintained by: Deepak Saxena <dsaxena@plexity.net>
+ *
+ * Copyright 2002 Intel Corp.
+ * Copyright (C) 2003-2004 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.
+ */
+
+#include <linux/sched.h>
+#include <linux/kernel.h>
+#include <linux/pci.h>
+#include <linux/interrupt.h>
+#include <linux/mm.h>
+#include <linux/init.h>
+#include <linux/ioport.h>
+#include <linux/slab.h>
+#include <linux/delay.h>
+
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/system.h>
+#include <asm/mach-types.h>
+#include <asm/hardware.h>
+
+#include <asm/mach/pci.h>
+
+static int pci_master_aborts = 0;
+
+static int clear_master_aborts(void);
+
+static u32 *
+ixp2000_pci_config_addr(unsigned int bus_nr, unsigned int devfn, int where)
+{
+	u32 *paddress;
+
+	if (PCI_SLOT(devfn) > 7)
+		return 0;
+
+	/* Must be dword aligned */
+	where &= ~3;
+
+	/*
+	 * For top bus, generate type 0, else type 1
+	 */
+	if (!bus_nr) {
+		/* only bits[23:16] are used for IDSEL */
+		paddress = (u32 *) (IXP2000_PCI_CFG0_VIRT_BASE
+				    | (1 << (PCI_SLOT(devfn) + 16))
+				    | (PCI_FUNC(devfn) << 8) | where);
+	} else {
+		paddress = (u32 *) (IXP2000_PCI_CFG1_VIRT_BASE 
+				    | (bus_nr << 16)
+				    | (PCI_SLOT(devfn) << 11)
+				    | (PCI_FUNC(devfn) << 8) | where);
+	}
+
+	return paddress;
+}
+
+/*
+ * Mask table, bits to mask for quantity of size 1, 2 or 4 bytes.
+ * 0 and 3 are not valid indexes...
+ */
+static u32 bytemask[] = {
+	/*0*/	0,
+	/*1*/	0xff,
+	/*2*/	0xffff,
+	/*3*/	0,
+	/*4*/	0xffffffff,
+};
+
+
+int ixp2000_pci_read_config(struct pci_bus *bus, unsigned int devfn, int where,
+				int size, u32 *value)
+{
+	u32 n;
+	u32 *addr;
+
+	n = where % 4;
+
+	addr = ixp2000_pci_config_addr(bus->number, devfn, where);
+	if (!addr)
+		return PCIBIOS_DEVICE_NOT_FOUND;
+
+	pci_master_aborts = 0;
+	*value = (*addr >> (8*n)) & bytemask[size];
+	if (pci_master_aborts) {
+		pci_master_aborts = 0;
+		*value = 0xffffffff;
+		return PCIBIOS_DEVICE_NOT_FOUND;
+	}
+
+	return PCIBIOS_SUCCESSFUL;
+}
+
+/*
+ * We don't do error checks by callling clear_master_aborts() b/c the
+ * assumption is that the caller did a read first to make sure a device
+ * exists.
+ */
+int ixp2000_pci_write_config(struct pci_bus *bus, unsigned int devfn, int where,
+				int size, u32 value)
+{
+	u32 mask;
+	u32 *addr;
+	u32 temp;
+
+	mask = ~(bytemask[size] << ((where % 0x4) * 8));
+	addr = ixp2000_pci_config_addr(bus->number, devfn, where);
+	if (!addr)
+		return PCIBIOS_DEVICE_NOT_FOUND;
+	temp = (u32) (value) << ((where % 0x4) * 8);
+	*addr = (*addr & mask) | temp;
+
+	clear_master_aborts();
+
+	return PCIBIOS_SUCCESSFUL;
+}
+
+
+static struct pci_ops ixp2000_pci_ops = {
+	.read	= ixp2000_pci_read_config,
+	.write	= ixp2000_pci_write_config
+};
+
+struct pci_bus *ixp2000_pci_scan_bus(int nr, struct pci_sys_data *sysdata)
+{
+	return pci_scan_bus(sysdata->busnr, &ixp2000_pci_ops, sysdata);
+}
+
+
+int ixp2000_pci_abort_handler(unsigned long addr, unsigned int fsr, struct pt_regs *regs)
+{
+
+	volatile u32 temp;
+
+	pci_master_aborts = 1;
+
+	cli();
+	temp = *(IXP2000_PCI_CONTROL);
+	if (temp & ((1 << 8) | (1 << 5))) {
+		*(IXP2000_PCI_CONTROL) = temp;
+	}
+
+	temp = *(IXP2000_PCI_CMDSTAT);
+	if (temp & (1 << 29)) {
+		while (temp & (1 << 29)) {	
+			*(IXP2000_PCI_CMDSTAT) = temp;
+			temp = *(IXP2000_PCI_CMDSTAT);
+		}
+	}
+	sti();
+
+	/*
+	 * If it was an imprecise abort, then we need to correct the
+	 * return address to be _after_ the instruction.
+	 */
+	if (fsr & (1 << 10))
+		regs->ARM_pc += 4;
+
+	return 0;
+}
+
+int
+clear_master_aborts(void)
+{
+	volatile u32 temp;
+
+	cli();
+	temp = *(IXP2000_PCI_CONTROL);
+	if (temp & ((1 << 8) | (1 << 5))) {	
+		*(IXP2000_PCI_CONTROL) = temp;
+	}
+
+	temp = *(IXP2000_PCI_CMDSTAT);
+	if (temp & (1 << 29)) {
+		while (temp & (1 << 29)) {
+			*(IXP2000_PCI_CMDSTAT) = temp;
+			temp = *(IXP2000_PCI_CMDSTAT);
+		}
+	}
+	sti();
+
+	return 0;
+}
+
+void __init
+ixp2000_pci_preinit(void)
+{
+	hook_fault_code(16+6, ixp2000_pci_abort_handler, SIGBUS,
+				"PCI config cycle to non-existent device");
+}
+
+
+/*
+ * IXP2000 systems often have large resource requirements, so we just
+ * use our own resource space.
+ */
+static struct resource ixp2000_pci_mem_space = {
+	.start	= 0x00000000,
+	.end	= 0xffffffff,
+	.flags	= IORESOURCE_MEM,
+	.name	= "PCI Mem Space"
+};
+
+static struct resource ixp2000_pci_io_space = {
+	.start	= 0x00000000,
+	.end	= 0xffffffff,
+	.flags	= IORESOURCE_IO,
+	.name	= "PCI I/O Space"
+};
+
+int ixp2000_pci_setup(int nr, struct pci_sys_data *sys)
+{
+	if (nr >= 1)
+		return 0;
+
+	sys->resource[0] = &ixp2000_pci_io_space;
+	sys->resource[1] = &ixp2000_pci_mem_space;
+	sys->resource[2] = NULL;
+
+	return 1;
+}
+
diff -Nru a/arch/arm/mach-ixp4xx/common.c b/arch/arm/mach-ixp4xx/common.c
--- a/arch/arm/mach-ixp4xx/common.c	2004-10-18 14:56:32 -07:00
+++ b/arch/arm/mach-ixp4xx/common.c	2004-10-18 14:56:32 -07:00
@@ -207,7 +207,7 @@
 
 static unsigned volatile last_jiffy_time;
 
-#define CLOCK_TICKS_PER_USEC	(CLOCK_TICK_RATE / USEC_PER_SEC)
+#define CLOCK_TICKS_PER_USEC	((CLOCK_TICK_RATE + USEC_PER_SEC/2) / USEC_PER_SEC)
 
 /* IRQs are disabled before entering here from do_gettimeofday() */
 static unsigned long ixp4xx_gettimeoffset(void)
diff -Nru a/arch/arm/mach-lh7a40x/arch-lpd7a40x.c b/arch/arm/mach-lh7a40x/arch-lpd7a40x.c
--- a/arch/arm/mach-lh7a40x/arch-lpd7a40x.c	2004-10-18 14:55:54 -07:00
+++ b/arch/arm/mach-lh7a40x/arch-lpd7a40x.c	2004-10-18 14:55:54 -07:00
@@ -45,7 +45,6 @@
 	.resource	= smc91x_resources,
 };
 
-#if 0
 static struct resource lh7a40x_usbclient_resources[] = {
 	[0] = {
 		.start	= USB_PHYS,
@@ -53,8 +52,8 @@
 		.flags	= IORESOURCE_MEM,
 	},
 	[1] = {
-		.start	= IRQ_USB,
-		.end	= IRQ_USB,
+		.start	= IRQ_USBINTR,
+		.end	= IRQ_USBINTR,
 		.flags	= IORESOURCE_IRQ,
 	},
 };
@@ -62,7 +61,7 @@
 static u64 lh7a40x_usbclient_dma_mask = 0xffffffffUL;
 
 static struct platform_device lh7a40x_usbclient_device = {
-	.name		= "lh7a40x-udc",
+	.name		= "lh7a40x_udc",
 	.id		= 0,
 	.dev		= {
 		.dma_mask = &lh7a40x_usbclient_dma_mask,
@@ -71,7 +70,6 @@
 	.num_resources	= ARRAY_SIZE (lh7a40x_usbclient_resources),
 	.resource	= lh7a40x_usbclient_resources,
 };
-#endif
 
 #if defined (CONFIG_ARCH_LH7A404)
 
@@ -105,8 +103,7 @@
 
 static struct platform_device *lpd7a40x_devs[] __initdata = {
 	&smc91x_device,
-/*	&lh7a40x_usbclient_device, */
-
+	&lh7a40x_usbclient_device,
 #if defined (CONFIG_ARCH_LH7A404)
 	&lh7a404_usbhost_device,
 #endif
diff -Nru a/arch/arm/mach-lh7a40x/time.c b/arch/arm/mach-lh7a40x/time.c
--- a/arch/arm/mach-lh7a40x/time.c	2004-10-18 14:56:32 -07:00
+++ b/arch/arm/mach-lh7a40x/time.c	2004-10-18 14:56:32 -07:00
@@ -22,12 +22,12 @@
 #include <asm/mach/time.h>
 
 #if HZ < 100
-# define TIMER_CONTROL	TIMER_CONTROL1
-# define TIMER_LOAD	TIMER_LOAD1
+# define TIMER_CONTROL	TIMER_CONTROL2
+# define TIMER_LOAD	TIMER_LOAD2
 # define TIMER_CONSTANT	(508469/HZ)
 # define TIMER_MODE	(TIMER_C_ENABLE | TIMER_C_PERIODIC | TIMER_C_508KHZ)
-# define TIMER_EOI	TIMER_EOI1
-# define TIMER_IRQ	IRQ_T1UI
+# define TIMER_EOI	TIMER_EOI2
+# define TIMER_IRQ	IRQ_T2UI
 #else
 # define TIMER_CONTROL	TIMER_CONTROL3
 # define TIMER_LOAD	TIMER_LOAD3
diff -Nru a/arch/arm/mach-omap/Makefile b/arch/arm/mach-omap/Makefile
--- a/arch/arm/mach-omap/Makefile	2004-10-18 14:56:13 -07:00
+++ b/arch/arm/mach-omap/Makefile	2004-10-18 14:56:13 -07:00
@@ -3,25 +3,29 @@
 #
 
 # Common support
-obj-y := common.o irq.o dma.o clocks.o mux.o bus.o gpio.o time.o
+obj-y := common.o time.o irq.o dma.o clocks.o mux.o gpio.o mcbsp.o
 obj-m :=
 obj-n :=
 obj-  :=
 led-y := leds.o
 
 # Specific board support
+obj-$(CONFIG_MACH_OMAP_H2) += board-h2.o
 obj-$(CONFIG_MACH_OMAP_INNOVATOR) += board-innovator.o
 obj-$(CONFIG_MACH_OMAP_GENERIC) += board-generic.o
 obj-$(CONFIG_MACH_OMAP_PERSEUS2) += board-perseus2.o
 obj-$(CONFIG_MACH_OMAP_OSK) += board-osk.o
+obj-$(CONFIG_MACH_OMAP_H3) += board-h3.o
 
-# OCPI interconnect support for 1610 and 5912
+# OCPI interconnect support for 1710, 1610 and 5912
+obj-$(CONFIG_ARCH_OMAP1710) += ocpi.o
 obj-$(CONFIG_ARCH_OMAP1610) += ocpi.o
 obj-$(CONFIG_ARCH_OMAP5912) += ocpi.o
 
 # LEDs support
+led-$(CONFIG_MACH_OMAP_H2) += leds-h2p2-debug.o
 led-$(CONFIG_MACH_OMAP_INNOVATOR) += leds-innovator.o
-led-$(CONFIG_MACH_OMAP_PERSEUS2) += leds-perseus2.o
+led-$(CONFIG_MACH_OMAP_PERSEUS2) += leds-h2p2-debug.o
 obj-$(CONFIG_LEDS) += $(led-y)
 
 # Power Management
diff -Nru a/arch/arm/mach-omap/board-generic.c b/arch/arm/mach-omap/board-generic.c
--- a/arch/arm/mach-omap/board-generic.c	2004-10-18 14:56:33 -07:00
+++ b/arch/arm/mach-omap/board-generic.c	2004-10-18 14:56:33 -07:00
@@ -25,9 +25,13 @@
 #include <asm/arch/clocks.h>
 #include <asm/arch/gpio.h>
 #include <asm/arch/mux.h>
+#include <asm/arch/usb.h>
+#include <asm/arch/board.h>
 
 #include "common.h"
 
+extern void __init omap_init_time(void);
+
 static void __init omap_generic_init_irq(void)
 {
 	omap_init_irq();
@@ -36,17 +40,49 @@
 /*
  * Muxes the serial ports on
  */
+#ifdef CONFIG_ARCH_OMAP1510
 static void __init omap_early_serial_init(void)
 {
+#ifdef CONFIG_OMAP_LL_DEBUG_UART1
 	omap_cfg_reg(UART1_TX);
 	omap_cfg_reg(UART1_RTS);
+#endif
 
+#ifdef CONFIG_OMAP_LL_DEBUG_UART2
 	omap_cfg_reg(UART2_TX);
 	omap_cfg_reg(UART2_RTS);
+#endif
 
+#ifdef CONFIG_OMAP_LL_DEBUG_UART1
 	omap_cfg_reg(UART3_TX);
 	omap_cfg_reg(UART3_RX);
+#endif
 }
+#endif
+
+/* assume no Mini-AB port */
+
+#ifdef CONFIG_ARCH_OMAP1510
+static struct omap_usb_config generic1510_usb_config __initdata = {
+	.register_host	= 1,
+	.register_dev	= 1,
+	.hmc_mode	= 16,
+	.pins[0]	= 3,
+};
+#endif
+
+#ifdef CONFIG_ARCH_OMAP1610
+static struct omap_usb_config generic1610_usb_config __initdata = {
+	.register_host	= 1,
+	.register_dev	= 1,
+	.hmc_mode	= 16,
+	.pins[0]	= 6,
+};
+#endif
+
+static struct omap_board_config_kernel generic_config[] = {
+	{ OMAP_TAG_USB,           NULL },
+};
 
 static void __init omap_generic_init(void)
 {
@@ -55,9 +91,19 @@
 	 * You have to mux them off in device drivers later on
 	 * if not needed.
 	 */
+#ifdef CONFIG_ARCH_OMAP1510
 	if (cpu_is_omap1510()) {
 		omap_early_serial_init();
+		generic_config[0].data = &generic1510_usb_config;
+	}
+#endif
+#ifdef CONFIG_ARCH_OMAP1610
+	if (!cpu_is_omap1510()) {
+		generic_config[0].data = &generic1610_usb_config;
 	}
+#endif
+	omap_board_config = generic_config;
+	omap_board_config_size = ARRAY_SIZE(generic_config);
 }
 
 static void __init omap_generic_map_io(void)
@@ -65,18 +111,12 @@
 	omap_map_io();
 }
 
-static void __init omap_generic_init_time(void)
-{
-	omap_init_time();
-}
-
-MACHINE_START(OMAP_GENERIC, "Generic OMAP-1510/1610/1710")
+MACHINE_START(OMAP_GENERIC, "Generic OMAP1510/1610/1710")
 	MAINTAINER("Tony Lindgren <tony@atomide.com>")
 	BOOT_MEM(0x10000000, 0xfff00000, 0xfef00000)
 	BOOT_PARAMS(0x10000100)
 	MAPIO(omap_generic_map_io)
 	INITIRQ(omap_generic_init_irq)
 	INIT_MACHINE(omap_generic_init)
-	INITTIME(omap_generic_init_time)
+	INITTIME(omap_init_time)
 MACHINE_END
-
diff -Nru a/arch/arm/mach-omap/board-h2.c b/arch/arm/mach-omap/board-h2.c
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/arch/arm/mach-omap/board-h2.c	2004-10-18 14:57:24 -07:00
@@ -0,0 +1,115 @@
+/*
+ * linux/arch/arm/mach-omap/board-h2.c
+ *
+ * Board specific inits for OMAP-1610 H2
+ *
+ * Copyright (C) 2001 RidgeRun, Inc.
+ * Author: Greg Lonnon <glonnon@ridgerun.com>
+ *
+ * Copyright (C) 2002 MontaVista Software, Inc.
+ *
+ * Separated FPGA interrupts from innovator1510.c and cleaned up for 2.6
+ * Copyright (C) 2004 Nokia Corporation by Tony Lindrgen <tony@atomide.com>
+ *
+ * H2 specific changes and cleanup
+ * Copyright (C) 2004 Nokia Corporation by Imre Deak <imre.deak@nokia.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/kernel.h>
+#include <linux/init.h>
+#include <linux/device.h>
+#include <linux/delay.h>
+
+#include <asm/hardware.h>
+#include <asm/mach-types.h>
+#include <asm/mach/arch.h>
+#include <asm/mach/map.h>
+
+#include <asm/arch/clocks.h>
+#include <asm/arch/gpio.h>
+#include <asm/arch/usb.h>
+
+#include "common.h"
+
+extern void __init omap_init_time(void);
+
+static struct map_desc h2_io_desc[] __initdata = {
+{ OMAP1610_ETHR_BASE, OMAP1610_ETHR_START, OMAP1610_ETHR_SIZE,MT_DEVICE },
+{ OMAP1610_NOR_FLASH_BASE, OMAP1610_NOR_FLASH_START, OMAP1610_NOR_FLASH_SIZE,
+	MT_DEVICE },
+};
+
+static struct resource h2_smc91x_resources[] = {
+	[0] = {
+		.start	= OMAP1610_ETHR_START,		/* Physical */
+		.end	= OMAP1610_ETHR_START + SZ_4K,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start	= 0,				/* Really GPIO 0 */
+		.end	= 0,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static struct platform_device h2_smc91x_device = {
+	.name		= "smc91x",
+	.id		= 0,
+	.num_resources	= ARRAY_SIZE(h2_smc91x_resources),
+	.resource	= h2_smc91x_resources,
+};
+
+static struct platform_device *h2_devices[] __initdata = {
+	&h2_smc91x_device,
+};
+
+void h2_init_irq(void)
+{
+	omap_init_irq();
+}
+
+static struct omap_usb_config h2_usb_config __initdata = {
+	/* usb1 has a Mini-AB port and external isp1301 transceiver */
+	.otg		= 2,
+
+#ifdef	CONFIG_USB_GADGET_OMAP
+	.hmc_mode	= 19,	// 0:host(off) 1:dev|otg 2:disabled
+	// .hmc_mode	= 21,	// 0:host(off) 1:dev(loopback) 2:host(loopback)
+#elif	defined(CONFIG_USB_OHCI_HCD) || defined(CONFIG_USB_OHCI_HCD_MODULE)
+	/* NONSTANDARD CABLE NEEDED (B-to-Mini-B) */
+	.hmc_mode	= 20,	// 1:dev|otg(off) 1:host 2:disabled
+#endif
+
+	.pins[1]	= 3,
+};
+
+static struct omap_board_config_kernel h2_config[] = {
+	{ OMAP_TAG_USB,           &h2_usb_config },
+};
+
+static void __init h2_init(void)
+{
+	platform_add_devices(h2_devices, ARRAY_SIZE(h2_devices));
+	omap_board_config = h2_config;
+	omap_board_config_size = ARRAY_SIZE(h2_config);
+}
+
+static void __init h2_map_io(void)
+{
+	omap_map_io();
+	iotable_init(h2_io_desc, ARRAY_SIZE(h2_io_desc));
+}
+
+MACHINE_START(OMAP_H2, "TI-H2")
+	MAINTAINER("Imre Deak <imre.deak@nokia.com>")
+	BOOT_MEM(0x10000000, 0xfff00000, 0xfef00000)
+	BOOT_PARAMS(0x10000100)
+	MAPIO(h2_map_io)
+	INITIRQ(h2_init_irq)
+	INIT_MACHINE(h2_init)
+	INITTIME(omap_init_time)
+MACHINE_END
diff -Nru a/arch/arm/mach-omap/board-h3.c b/arch/arm/mach-omap/board-h3.c
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/arch/arm/mach-omap/board-h3.c	2004-10-18 14:57:21 -07:00
@@ -0,0 +1,90 @@
+/*
+ * linux/arch/arm/mach-omap/board-h3.c
+ *
+ * This file contains OMAP1710 H3 specific code.
+ *
+ * Copyright (C) 2004 Texas Instruments, Inc.
+ * Copyright (C) 2002 MontaVista Software, Inc.
+ * Copyright (C) 2001 RidgeRun, Inc.
+ * Author: RidgeRun, Inc.
+ *         Greg Lonnon (glonnon@ridgerun.com) or info@ridgerun.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/types.h>
+#include <linux/init.h>
+#include <linux/major.h>
+#include <linux/kernel.h>
+#include <linux/device.h>
+#include <linux/errno.h>
+
+#include <asm/setup.h>
+#include <asm/page.h>
+#include <asm/hardware.h>
+#include <asm/mach/arch.h>
+#include <asm/mach/map.h>
+#include <asm/arch/irqs.h>
+#include <asm/arch/gpio.h>
+#include <asm/mach-types.h>
+#include "common.h"
+
+extern void __init omap_init_time(void);
+
+void h3_init_irq(void)
+{
+	omap_init_irq();
+}
+
+static struct resource smc91x_resources[] = {
+	[0] = {
+		.start	= OMAP1710_ETHR_START,		/* Physical */
+		.end	= OMAP1710_ETHR_START + OMAP1710_ETHR_SIZE,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start	= 0,
+		.end	= 0,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static struct platform_device smc91x_device = {
+	.name		= "smc91x",
+	.id		= 0,
+	.num_resources	= ARRAY_SIZE(smc91x_resources),
+	.resource	= smc91x_resources,
+};
+
+static struct platform_device *devices[] __initdata = {
+        &smc91x_device,
+};
+
+static void __init h3_init(void)
+{
+	(void) platform_add_devices(devices, ARRAY_SIZE(devices));
+}
+
+static struct map_desc h3_io_desc[] __initdata = {
+{ OMAP1710_ETHR_BASE,  OMAP1710_ETHR_START,  OMAP1710_ETHR_SIZE,  MT_DEVICE },
+{ OMAP_NOR_FLASH_BASE, OMAP_NOR_FLASH_START, OMAP_NOR_FLASH_SIZE, MT_DEVICE },
+};
+
+static void __init h3_map_io(void)
+{
+	omap_map_io();
+	iotable_init(h3_io_desc, ARRAY_SIZE(h3_io_desc));
+}
+
+MACHINE_START(OMAP_H3, "TI OMAP1710 H3 board")
+	MAINTAINER("Texas Instruments, Inc.")
+	BOOT_MEM(0x10000000, 0xfff00000, 0xfef00000)
+	BOOT_PARAMS(0x10000100)
+	MAPIO(h3_map_io)
+	INITIRQ(h3_init_irq)
+	INIT_MACHINE(h3_init)
+	INITTIME(omap_init_time)
+MACHINE_END
diff -Nru a/arch/arm/mach-omap/board-innovator.c b/arch/arm/mach-omap/board-innovator.c
--- a/arch/arm/mach-omap/board-innovator.c	2004-10-18 14:55:54 -07:00
+++ b/arch/arm/mach-omap/board-innovator.c	2004-10-18 14:55:54 -07:00
@@ -29,9 +29,12 @@
 #include <asm/arch/clocks.h>
 #include <asm/arch/gpio.h>
 #include <asm/arch/fpga.h>
+#include <asm/arch/usb.h>
 
 #include "common.h"
 
+extern void __init omap_init_time(void);
+
 #ifdef CONFIG_ARCH_OMAP1510
 
 extern int omap_gpio_init(void);
@@ -49,8 +52,8 @@
 		.flags	= IORESOURCE_MEM,
 	},
 	[1] = {
-		.start	= INT_ETHER,
-		.end	= INT_ETHER,
+		.start	= OMAP1510_INT_ETHER,
+		.end	= OMAP1510_INT_ETHER,
 		.flags	= IORESOURCE_IRQ,
 	},
 };
@@ -108,11 +111,43 @@
 #ifdef CONFIG_ARCH_OMAP1510
 	if (cpu_is_omap1510()) {
 		omap_gpio_init();
-		fpga_init_irq();
+		omap1510_fpga_init_irq();
 	}
 #endif
 }
 
+#ifdef CONFIG_ARCH_OMAP1510
+static struct omap_usb_config innovator1510_usb_config __initdata = {
+	/* has usb host and device, but no Mini-AB port */
+	.register_host	= 1,
+	.register_dev	= 1,
+	/* Assume bad Innovator wiring; Use internal host only with custom cable */
+	.hmc_mode	= 16,
+	.pins[0]	= 2,
+};
+#endif
+
+#ifdef CONFIG_ARCH_OMAP1610
+static struct omap_usb_config h2_usb_config __initdata = {
+	/* usb1 has a Mini-AB port and external isp1301 transceiver */
+	.otg		= 2,
+
+#ifdef	CONFIG_USB_GADGET_OMAP
+	.hmc_mode	= 19,	// 0:host(off) 1:dev|otg 2:disabled
+	// .hmc_mode	= 21,	// 0:host(off) 1:dev(loopback) 2:host(loopback)
+#elif	defined(CONFIG_USB_OHCI_HCD) || defined(CONFIG_USB_OHCI_HCD_MODULE)
+	/* NONSTANDARD CABLE NEEDED (B-to-Mini-B) */
+	.hmc_mode	= 20,	// 1:dev|otg(off) 1:host 2:disabled
+#endif
+
+	.pins[1]	= 3,
+};
+#endif
+
+static struct omap_board_config_kernel innovator_config[] = {
+	{ OMAP_TAG_USB,         NULL },
+};
+
 static void __init innovator_init(void)
 {
 #ifdef CONFIG_ARCH_OMAP1510
@@ -121,10 +156,21 @@
 	}
 #endif
 #ifdef CONFIG_ARCH_OMAP1610
-	if (cpu_is_omap1610()) {
+	if (!cpu_is_omap1510()) {
 		platform_add_devices(innovator1610_devices, ARRAY_SIZE(innovator1610_devices));
 	}
 #endif
+
+#ifdef CONFIG_ARCH_OMAP1510
+	if (cpu_is_omap1510())
+		innovator_config[0].data = &innovator1510_usb_config;
+#endif
+#ifdef CONFIG_ARCH_OMAP1610
+	if (cpu_is_omap1610())
+		innovator_config[0].data = &h2_usb_config;
+#endif
+	omap_board_config = innovator_config;
+	omap_board_config_size = ARRAY_SIZE(innovator_config);
 }
 
 static void __init innovator_map_io(void)
@@ -144,7 +190,7 @@
 	}
 #endif
 #ifdef CONFIG_ARCH_OMAP1610
-	if (cpu_is_omap1610()) {
+	if (!cpu_is_omap1510()) {
 		iotable_init(innovator1610_io_desc, ARRAY_SIZE(innovator1610_io_desc));
 	}
 #endif
@@ -156,6 +202,6 @@
 	BOOT_PARAMS(0x10000100)
 	MAPIO(innovator_map_io)
 	INITIRQ(innovator_init_irq)
-	INITTIME(omap_init_time)
 	INIT_MACHINE(innovator_init)
+	INITTIME(omap_init_time)
 MACHINE_END
diff -Nru a/arch/arm/mach-omap/board-osk.c b/arch/arm/mach-omap/board-osk.c
--- a/arch/arm/mach-omap/board-osk.c	2004-10-18 14:56:50 -07:00
+++ b/arch/arm/mach-omap/board-osk.c	2004-10-18 14:56:50 -07:00
@@ -41,6 +41,8 @@
 
 #include "common.h"
 
+extern void __init omap_init_time(void);
+
 static struct map_desc osk5912_io_desc[] __initdata = {
 { OMAP_OSK_ETHR_BASE, OMAP_OSK_ETHR_START, OMAP_OSK_ETHR_SIZE,MT_DEVICE },
 { OMAP_OSK_NOR_FLASH_BASE, OMAP_OSK_NOR_FLASH_START, OMAP_OSK_NOR_FLASH_SIZE,
@@ -94,6 +96,6 @@
 	BOOT_PARAMS(0x10000100)
 	MAPIO(osk_map_io)
 	INITIRQ(osk_init_irq)
-	INITTIME(omap_init_time)
 	INIT_MACHINE(osk_init)
+	INITTIME(omap_init_time)
 MACHINE_END
diff -Nru a/arch/arm/mach-omap/board-perseus2.c b/arch/arm/mach-omap/board-perseus2.c
--- a/arch/arm/mach-omap/board-perseus2.c	2004-10-18 14:56:49 -07:00
+++ b/arch/arm/mach-omap/board-perseus2.c	2004-10-18 14:56:49 -07:00
@@ -23,9 +23,12 @@
 #include <asm/arch/clocks.h>
 #include <asm/arch/gpio.h>
 #include <asm/arch/mux.h>
+#include <asm/arch/fpga.h>
 
 #include "common.h"
 
+extern void __init omap_init_time(void);
+
 void omap_perseus2_init_irq(void)
 {
 	omap_init_irq();
@@ -33,14 +36,14 @@
 
 static struct resource smc91x_resources[] = {
 	[0] = {
-		.start	= OMAP730_FPGA_ETHR_START,	/* Physical */
-		.end	= OMAP730_FPGA_ETHR_START + SZ_4K,
+		.start	= H2P2_DBG_FPGA_ETHR_START,	/* Physical */
+		.end	= H2P2_DBG_FPGA_ETHR_START + SZ_4K,
 		.flags	= IORESOURCE_MEM,
 	},
 	[1] = {
-		.start	= 0,
+		.start	= INT_730_MPU_EXT_NIRQ,
 		.end	= 0,
-		.flags	= INT_ETHER,
+		.flags	= IORESOURCE_IRQ,
 	},
 };
 
@@ -62,7 +65,7 @@
 
 /* Only FPGA needs to be mapped here. All others are done with ioremap */
 static struct map_desc omap_perseus2_io_desc[] __initdata = {
-	{OMAP730_FPGA_BASE, OMAP730_FPGA_START, OMAP730_FPGA_SIZE,
+	{H2P2_DBG_FPGA_BASE, H2P2_DBG_FPGA_START, H2P2_DBG_FPGA_SIZE,
 	 MT_DEVICE},
 };
 
@@ -111,6 +114,6 @@
 	BOOT_PARAMS(0x10000100)
 	MAPIO(omap_perseus2_map_io)
 	INITIRQ(omap_perseus2_init_irq)
-	INITTIME(omap_init_time)
 	INIT_MACHINE(omap_perseus2_init)
+	INITTIME(omap_init_time)
 MACHINE_END
diff -Nru a/arch/arm/mach-omap/bus.c b/arch/arm/mach-omap/bus.c
--- a/arch/arm/mach-omap/bus.c	2004-10-18 14:57:18 -07:00
+++ /dev/null	Wed Dec 31 16:00:00 196900
@@ -1,246 +0,0 @@
-/*
- * linux/arch/arm/mach-omap/bus.c
- *
- * Virtual bus for OMAP. Allows better power management, such as managing
- * shared clocks, and mapping of bus addresses to Local Bus addresses.
- *
- * See drivers/usb/host/ohci-omap.c or drivers/video/omap/omapfb.c for
- * examples on how to register drivers to this bus.
- *
- * Copyright (C) 2003 - 2004 Nokia Corporation
- * Written by Tony Lindgren <tony@atomide.com>
- * Portions of code based on sa1111.c.
- *
- * 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
- */
-
-#include <linux/config.h>
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/kernel.h>
-#include <linux/delay.h>
-#include <linux/ptrace.h>
-#include <linux/errno.h>
-#include <linux/ioport.h>
-#include <linux/device.h>
-#include <linux/slab.h>
-#include <linux/spinlock.h>
-
-#include <asm/hardware.h>
-#include <asm/mach-types.h>
-#include <asm/io.h>
-#include <asm/irq.h>
-#include <asm/mach/irq.h>
-
-#include <asm/arch/bus.h>
-
-static int omap_bus_match(struct device *_dev, struct device_driver *_drv);
-static int omap_bus_suspend(struct device *dev, u32 state);
-static int omap_bus_resume(struct device *dev);
-
-/*
- * OMAP bus definitions
- *
- * NOTE: Most devices should use TIPB. LBUS does automatic address mapping
- *	 to Local Bus addresses, and should only be used for Local Bus devices.
- *	 We may add new buses later on for power management reasons. Basically
- *	 we want to be able to turn off any bus if it's not used by device
- *	 drivers.
- */
-static struct device omap_bus_devices[OMAP_NR_BUSES] = {
-	{
-		.bus_id		= OMAP_BUS_NAME_TIPB
-	}, {
-		.bus_id		= OMAP_BUS_NAME_LBUS
-	},
-};
-
-static struct bus_type omap_bus_types[OMAP_NR_BUSES] = {
-	{
-		.name		= OMAP_BUS_NAME_TIPB,
-		.match		= omap_bus_match,
-		.suspend	= omap_bus_suspend,
-		.resume		= omap_bus_resume,
-	}, {
-		.name		= OMAP_BUS_NAME_LBUS,	/* Local bus on 1510 */
-		.match		= omap_bus_match,
-		.suspend	= omap_bus_suspend,
-		.resume		= omap_bus_resume,
-	},
-};
-
-static int omap_bus_match(struct device *dev, struct device_driver *drv)
-{
-	struct omap_dev *omapdev = OMAP_DEV(dev);
-	struct omap_driver *omapdrv = OMAP_DRV(drv);
-
-	return omapdev->devid == omapdrv->devid;
-}
-
-static int omap_bus_suspend(struct device *dev, u32 state)
-{
-	struct omap_dev *omapdev = OMAP_DEV(dev);
-	struct omap_driver *omapdrv = OMAP_DRV(dev->driver);
-	int ret = 0;
-
-	if (omapdrv && omapdrv->suspend)
-		ret = omapdrv->suspend(omapdev, state);
-	return ret;
-}
-
-static int omap_bus_resume(struct device *dev)
-{
-	struct omap_dev *omapdev = OMAP_DEV(dev);
-	struct omap_driver *omapdrv = OMAP_DRV(dev->driver);
-	int ret = 0;
-
-	if (omapdrv && omapdrv->resume)
-		ret = omapdrv->resume(omapdev);
-	return ret;
-}
-
-static int omap_device_probe(struct device *dev)
-{
-	struct omap_dev *omapdev = OMAP_DEV(dev);
-	struct omap_driver *omapdrv = OMAP_DRV(dev->driver);
-	int ret = -ENODEV;
-
-	if (omapdrv && omapdrv->probe)
-		ret = omapdrv->probe(omapdev);
-
-	return ret;
-}
-
-static int omap_device_remove(struct device *dev)
-{
-	struct omap_dev *omapdev = OMAP_DEV(dev);
-	struct omap_driver *omapdrv = OMAP_DRV(dev->driver);
-	int ret = 0;
-
-	if (omapdrv && omapdrv->remove)
-		ret = omapdrv->remove(omapdev);
-	return ret;
-}
-
-int omap_device_register(struct omap_dev *odev)
-{
-	if (!odev)
-		return -EINVAL;
-
-	if (odev->busid < 0 || odev->busid >= OMAP_NR_BUSES) {
-		printk(KERN_ERR "%s: busid invalid: %s: bus: %i\n",
-		       __FUNCTION__, odev->name, odev->busid);
-		return -EINVAL;
-	}
-
-	odev->dev.parent = &omap_bus_devices[odev->busid];
-	odev->dev.bus = &omap_bus_types[odev->busid];
-
-	/* This is needed for USB OHCI to work */
-	if (odev->dma_mask)
-		odev->dev.dma_mask = odev->dma_mask;
-
-	if (odev->coherent_dma_mask)
-		odev->dev.coherent_dma_mask = odev->coherent_dma_mask;
-
-	snprintf(odev->dev.bus_id, BUS_ID_SIZE, "%s%u",
-		 odev->name, odev->devid);
-
-	printk("Registering OMAP device '%s'. Parent at %s\n",
-		 odev->dev.bus_id, odev->dev.parent->bus_id);
-
-	return device_register(&odev->dev);
-}
-
-void omap_device_unregister(struct omap_dev *odev)
-{
-	if (odev)
-		device_unregister(&odev->dev);
-}
-
-int omap_driver_register(struct omap_driver *driver)
-{
-	int ret;
-
-	if (driver->busid < 0 || driver->busid >= OMAP_NR_BUSES) {
-		printk(KERN_ERR "%s: busid invalid: bus: %i device: %i\n",
-		       __FUNCTION__, driver->busid, driver->devid);
-		return -EINVAL;
-	}
-
-	driver->drv.probe = omap_device_probe;
-	driver->drv.remove = omap_device_remove;
-	driver->drv.bus = &omap_bus_types[driver->busid];
-
-	/*
-	 * driver_register calls bus_add_driver
-	 */
-	ret = driver_register(&driver->drv);
-
-	return ret;
-}
-
-void omap_driver_unregister(struct omap_driver *driver)
-{
-	driver_unregister(&driver->drv);
-}
-
-static int __init omap_bus_init(void)
-{
-	int i, ret;
-
-	/* Initialize all OMAP virtual buses */
-	for (i = 0; i < OMAP_NR_BUSES; i++) {
-		ret = device_register(&omap_bus_devices[i]);
-		if (ret != 0) {
-			printk(KERN_ERR "Unable to register bus device %s\n",
-			       omap_bus_devices[i].bus_id);
-			continue;
-		}
-		ret = bus_register(&omap_bus_types[i]);
-		if (ret != 0) {
-			printk(KERN_ERR "Unable to register bus %s\n",
-			       omap_bus_types[i].name);
-			device_unregister(&omap_bus_devices[i]);
-		}
-	}
-	printk("OMAP virtual buses initialized\n");
-
-	return ret;
-}
-
-static void __exit omap_bus_exit(void)
-{
-	int i;
-
-	/* Unregister all OMAP virtual buses */
-	for (i = 0; i < OMAP_NR_BUSES; i++) {
-		bus_unregister(&omap_bus_types[i]);
-		device_unregister(&omap_bus_devices[i]);
-	}
-}
-
-postcore_initcall(omap_bus_init);
-module_exit(omap_bus_exit);
-
-MODULE_DESCRIPTION("Virtual bus for OMAP");
-MODULE_LICENSE("GPL");
-
-EXPORT_SYMBOL(omap_bus_types);
-EXPORT_SYMBOL(omap_driver_register);
-EXPORT_SYMBOL(omap_driver_unregister);
-EXPORT_SYMBOL(omap_device_register);
-EXPORT_SYMBOL(omap_device_unregister);
-
diff -Nru a/arch/arm/mach-omap/clocks.c b/arch/arm/mach-omap/clocks.c
--- a/arch/arm/mach-omap/clocks.c	2004-10-18 14:56:32 -07:00
+++ b/arch/arm/mach-omap/clocks.c	2004-10-18 14:56:32 -07:00
@@ -36,6 +36,8 @@
 #include <asm/arch/clocks.h>
 #include <asm/arch/board.h>
 
+extern void start_mputimer1(unsigned long load_val);
+
 /* Input clock in MHz */
 static unsigned int source_clock = 12;
 
@@ -239,7 +241,7 @@
 int ck_debug = 0;
 
 #define CK_MAX_PLL_FREQ		OMAP_CK_MAX_RATE
-static __u8 ck_valid_table[CK_MAX_PLL_FREQ / 8 + 1];
+static __u32 ck_valid_table[CK_MAX_PLL_FREQ / 32 + 1];
 static __u8 ck_lookup_table[CK_MAX_PLL_FREQ];
 
 int
@@ -615,11 +617,11 @@
 int __init
 init_ck(void)
 {
-	const struct omap_clock_info *info;
+	const struct omap_clock_config *info;
 	int crystal_type = 0; /* Default 12 MHz */
 
 	__ck_make_lookup_table();
-	info = omap_get_per_info(OMAP_TAG_CLOCK, struct omap_clock_info);
+	info = omap_get_config(OMAP_TAG_CLOCK, struct omap_clock_config);
 	if (info != NULL) {
 		if (!cpu_is_omap1510())
 			crystal_type = info->system_clock_type;
@@ -645,7 +647,8 @@
 #elif defined(CONFIG_OMAP_ARM_182MHZ) && defined(CONFIG_ARCH_OMAP730)
 	omap_writew(0x250E, ARM_CKCTL);
 	omap_writew(0x2710, DPLL_CTL);
-#elif defined(CONFIG_OMAP_ARM_192MHZ) && (defined(CONFIG_ARCH_OMAP1610) || defined(CONFIG_ARCH_OMAP5912))
+#elif defined(CONFIG_OMAP_ARM_192MHZ) && (defined(CONFIG_ARCH_OMAP1610) || defined(CONFIG_ARCH_OMAP5912) \
+					  || defined(CONFIG_ARCH_OMAP1710))
 	omap_writew(0x150f, ARM_CKCTL);
 	if (crystal_type == 2) {
 		source_clock = 13;	/* MHz */
diff -Nru a/arch/arm/mach-omap/common.c b/arch/arm/mach-omap/common.c
--- a/arch/arm/mach-omap/common.c	2004-10-18 14:57:04 -07:00
+++ b/arch/arm/mach-omap/common.c	2004-10-18 14:57:04 -07:00
@@ -104,7 +104,7 @@
 };
 #endif
 
-#ifdef CONFIG_ARCH_OMAP1610
+#if defined(CONFIG_ARCH_OMAP1610) || defined(CONFIG_ARCH_OMAP1710)
 static struct map_desc omap1610_io_desc[] __initdata = {
  { OMAP1610_DSP_BASE,    OMAP1610_DSP_START,    OMAP1610_DSP_SIZE,    MT_DEVICE },
  { OMAP1610_DSPREG_BASE, OMAP1610_DSPREG_START, OMAP1610_DSPREG_SIZE, MT_DEVICE },
@@ -147,8 +147,8 @@
 		iotable_init(omap1510_io_desc, ARRAY_SIZE(omap1510_io_desc));
 	}
 #endif
-#ifdef CONFIG_ARCH_OMAP1610
-	if (cpu_is_omap1610()) {
+#if defined(CONFIG_ARCH_OMAP1610) || defined(CONFIG_ARCH_OMAP1710)
+	if (cpu_is_omap1610() || cpu_is_omap1710()) {
 		iotable_init(omap1610_io_desc, ARRAY_SIZE(omap1610_io_desc));
 	}
 #endif
@@ -181,13 +181,18 @@
 extern int omap_bootloader_tag_len;
 extern u8 omap_bootloader_tag[];
 
-const void *__omap_get_per_info(u16 tag, size_t len)
+struct omap_board_config_kernel *omap_board_config;
+int omap_board_config_size = 0;
+
+const void *__omap_get_config(u16 tag, size_t len)
 {
-	struct omap_board_info_entry *info = NULL;
+	struct omap_board_config_entry *info = NULL;
+	struct omap_board_config_kernel *kinfo = NULL;
+	int i;
 
 #ifdef CONFIG_OMAP_BOOT_TAG
 	if (omap_bootloader_tag_len > 4)
-		info = (struct omap_board_info_entry *) omap_bootloader_tag;
+		info = (struct omap_board_config_entry *) omap_bootloader_tag;
 	while (info != NULL) {
 		u8 *next;
 
@@ -198,26 +203,38 @@
 		if (next >= omap_bootloader_tag + omap_bootloader_tag_len)
 			info = NULL;
 		else
-			info = (struct omap_board_info_entry *) next;
+			info = (struct omap_board_config_entry *) next;
 	}
-#endif
-	if (info == NULL)
-		return NULL;
-	if (info->len != len) {
-		printk(KERN_ERR "OMAP per_info: Length mismatch with tag %x (want %d, got %d)\n",
-		       tag, len, info->len);
-		return NULL;
+	if (info != NULL) {
+		/* Check the length as a lame attempt to check for
+		 * binary inconsistancy. */
+		if (info->len != len) {
+			printk(KERN_ERR "OMAP peripheral config: Length mismatch with tag %x (want %d, got %d)\n",
+			       tag, len, info->len);
+			return NULL;
+		}
+		return info->data;
+	}
+#endif
+	/* Try to find the config from the board-specific structures
+	 * in the kernel. */
+	for (i = 0; i < omap_board_config_size; i++) {
+		if (omap_board_config[i].tag == tag) {
+			kinfo = &omap_board_config[i];
+			break;
+		}
 	}
-
-	return info->data;
+	if (kinfo == NULL)
+		return NULL;
+	return kinfo->data;
 }
-EXPORT_SYMBOL(__omap_get_per_info);
+EXPORT_SYMBOL(__omap_get_config);
 
 static int __init omap_add_serial_console(void)
 {
-	const struct omap_uart_info *info;
+	const struct omap_uart_config *info;
 
-	info = omap_get_per_info(OMAP_TAG_UART, struct omap_uart_info);
+	info = omap_get_config(OMAP_TAG_UART, struct omap_uart_config);
 	if (info != NULL && info->console_uart) {
 		static char speed[11], *opt = NULL;
 
diff -Nru a/arch/arm/mach-omap/common.h b/arch/arm/mach-omap/common.h
--- a/arch/arm/mach-omap/common.h	2004-10-18 14:56:32 -07:00
+++ b/arch/arm/mach-omap/common.h	2004-10-18 14:56:32 -07:00
@@ -28,7 +28,6 @@
 #define __ARCH_ARM_MACH_OMAP_COMMON_H
 
 extern void omap_map_io(void);
-extern void omap_init_time(void);
 
 #endif /* __ARCH_ARM_MACH_OMAP_COMMON_H */
 
diff -Nru a/arch/arm/mach-omap/dma.c b/arch/arm/mach-omap/dma.c
--- a/arch/arm/mach-omap/dma.c	2004-10-18 14:57:04 -07:00
+++ b/arch/arm/mach-omap/dma.c	2004-10-18 14:57:04 -07:00
@@ -118,7 +118,7 @@
 	u16 w;
 
 #ifdef CONFIG_DEBUG_KERNEL
-	if (omap_dma_in_1510_mode) {
+	if (omap_dma_in_1510_mode()) {
 		printk(KERN_ERR "OMAP DMA constant fill not available in 1510 mode.");
 		BUG();
 		return;
@@ -141,7 +141,7 @@
 	u16 w;
 
 #ifdef CONFIG_DEBUG_KERNEL
-	if (omap_dma_in_1510_mode) {
+	if (omap_dma_in_1510_mode()) {
 		printk(KERN_ERR "OMAP DMA transparent copy not available in 1510 mode.");
 		BUG();
 	}
@@ -266,46 +266,78 @@
 	omap_writew(w, OMAP_DMA_CSDP(lch));
 }
 
+static inline void init_intr(int lch)
+{
+	u16 w;
+
+	/* Read CSR to make sure it's cleared. */
+	w = omap_readw(OMAP_DMA_CSR(lch));
+	/* Enable some nice interrupts. */
+	omap_writew(dma_chan[lch].enabled_irqs, OMAP_DMA_CICR(lch));
+	dma_chan[lch].flags |= OMAP_DMA_ACTIVE;
+}
+
+static inline void enable_lnk(int lch)
+{
+	u16 w;
+
+	/* Clear the STOP_LNK bits */
+	w = omap_readw(OMAP_DMA_CLNK_CTRL(lch));
+	w &= ~(1 << 14);
+	omap_writew(w, OMAP_DMA_CLNK_CTRL(lch));
+
+	/* And set the ENABLE_LNK bits */
+	if (dma_chan[lch].next_lch != -1)
+		omap_writew(dma_chan[lch].next_lch | (1 << 15),
+			    OMAP_DMA_CLNK_CTRL(lch));
+}
+
+static inline void disable_lnk(int lch)
+{
+	u16 w;
+
+	/* Disable interrupts */
+	omap_writew(0, OMAP_DMA_CICR(lch));
+
+	/* Set the STOP_LNK bit */
+	w = omap_readw(OMAP_DMA_CLNK_CTRL(lch));
+	w |= (1 << 14);
+	w = omap_writew(w, OMAP_DMA_CLNK_CTRL(lch));
+
+	dma_chan[lch].flags &= ~OMAP_DMA_ACTIVE;
+}
+
 void omap_start_dma(int lch)
 {
 	u16 w;
 
-	if (!omap_dma_in_1510_mode()) {
-		int next_lch;
+	if (!omap_dma_in_1510_mode() && dma_chan[lch].next_lch != -1) {
+		int next_lch, cur_lch;
+		char dma_chan_link_map[OMAP_LOGICAL_DMA_CH_COUNT];
+
+		dma_chan_link_map[lch] = 1;
+		/* Set the link register of the first channel */
+		enable_lnk(lch);
+
+		memset(dma_chan_link_map, 0, sizeof(dma_chan_link_map));
+		cur_lch = dma_chan[lch].next_lch;
+		do {
+			next_lch = dma_chan[cur_lch].next_lch;
 
-		next_lch = dma_chan[lch].next_lch;
+                        /* The loop case: we've been here already */
+			if (dma_chan_link_map[cur_lch])
+				break;
+			/* Mark the current channel */
+			dma_chan_link_map[cur_lch] = 1;
 
-		/* Enable the queue, if needed so. */
-		if (next_lch != -1) {
-			/* Clear the STOP_LNK bits */
-			w = omap_readw(OMAP_DMA_CLNK_CTRL(lch));
-			w &= ~(1 << 14);
-			omap_writew(w, OMAP_DMA_CLNK_CTRL(lch));
-			w = omap_readw(OMAP_DMA_CLNK_CTRL(next_lch));
-			w &= ~(1 << 14);
-			omap_writew(w, OMAP_DMA_CLNK_CTRL(next_lch));
-
-			/* And set the ENABLE_LNK bits */
-			omap_writew(next_lch | (1 << 15),
-				    OMAP_DMA_CLNK_CTRL(lch));
-			/* The loop case */
-			if (dma_chan[next_lch].next_lch == lch)
-				omap_writew(lch | (1 << 15),
-					    OMAP_DMA_CLNK_CTRL(next_lch));
-
-			/* Read CSR to make sure it's cleared. */
-			w = omap_readw(OMAP_DMA_CSR(next_lch));
-			/* Enable some nice interrupts. */
-			omap_writew(dma_chan[next_lch].enabled_irqs,
-				    OMAP_DMA_CICR(next_lch));
-			dma_chan[next_lch].flags |= OMAP_DMA_ACTIVE;
-		}
+			enable_lnk(cur_lch);
+			init_intr(cur_lch);
+
+			cur_lch = next_lch;
+		} while (next_lch != -1);
 	}
 
-	/* Read CSR to make sure it's cleared. */
-	w = omap_readw(OMAP_DMA_CSR(lch));
-	/* Enable some nice interrupts. */
-	omap_writew(dma_chan[lch].enabled_irqs, OMAP_DMA_CICR(lch));
+	init_intr(lch);
 
 	w = omap_readw(OMAP_DMA_CCR(lch));
 	w |= OMAP_DMA_CCR_EN;
@@ -316,37 +348,34 @@
 void omap_stop_dma(int lch)
 {
 	u16 w;
-	int next_lch;
 
-	/* Disable all interrupts on the channel */
-	omap_writew(0, OMAP_DMA_CICR(lch));
+	if (!omap_dma_in_1510_mode() && dma_chan[lch].next_lch != -1) {
+		int next_lch, cur_lch = lch;
+		char dma_chan_link_map[OMAP_LOGICAL_DMA_CH_COUNT];
+
+		memset(dma_chan_link_map, 0, sizeof(dma_chan_link_map));
+		do {
+			/* The loop case: we've been here already */
+			if (dma_chan_link_map[cur_lch])
+				break;
+			/* Mark the current channel */
+			dma_chan_link_map[cur_lch] = 1;
+
+			disable_lnk(cur_lch);
+
+			next_lch = dma_chan[cur_lch].next_lch;
+			cur_lch = next_lch;
+		} while (next_lch != -1);
 
-	if (omap_dma_in_1510_mode()) {
-		w = omap_readw(OMAP_DMA_CCR(lch));
-		w &= ~OMAP_DMA_CCR_EN;
-		omap_writew(w, OMAP_DMA_CCR(lch));
-		dma_chan[lch].flags &= ~OMAP_DMA_ACTIVE;
 		return;
 	}
+	/* Disable all interrupts on the channel */
+	omap_writew(0, OMAP_DMA_CICR(lch));
 
-	next_lch = dma_chan[lch].next_lch;
-
-	/*
-	 * According to thw HW spec, enabling the STOP_LNK bit
-	 * resets the CCR_EN bit at the same time.
-	 */
-	w = omap_readw(OMAP_DMA_CLNK_CTRL(lch));
-	w |= (1 << 14);
-	w = omap_writew(w, OMAP_DMA_CLNK_CTRL(lch));
+	w = omap_readw(OMAP_DMA_CCR(lch));
+	w &= ~OMAP_DMA_CCR_EN;
+	omap_writew(w, OMAP_DMA_CCR(lch));
 	dma_chan[lch].flags &= ~OMAP_DMA_ACTIVE;
-
-	if (next_lch != -1) {
-		omap_writew(0, OMAP_DMA_CICR(next_lch));
-		w = omap_readw(OMAP_DMA_CLNK_CTRL(next_lch));
-		w |= (1 << 14);
-		w = omap_writew(w, OMAP_DMA_CLNK_CTRL(next_lch));
-		dma_chan[next_lch].flags &= ~OMAP_DMA_ACTIVE;
-	}
 }
 
 void omap_enable_dma_irq(int lch, u16 bits)
@@ -445,7 +474,7 @@
 	chan->data = data;
 	chan->enabled_irqs = OMAP_DMA_TOUT_IRQ | OMAP_DMA_DROP_IRQ | OMAP_DMA_BLOCK_IRQ;
 
-	if (cpu_is_omap1610() || cpu_is_omap5912()) {
+	if (cpu_is_omap1610() || cpu_is_omap5912() || cpu_is_omap730() || cpu_is_omap1710()) {
 		/* If the sync device is set, configure it dynamically. */
 		if (dev_id != 0) {
 			set_gdma_dev(free_ch + 1, dev_id);
@@ -533,7 +562,6 @@
 	}
 
 	dma_chan[lch_head].next_lch = -1;
-	dma_chan[lch_queue].next_lch = -1;
 }
 
 
@@ -713,7 +741,7 @@
 		printk(KERN_INFO "DMA support for OMAP1510 initialized\n");
 		dma_chan_count = 9;
 		enable_1510_mode = 1;
-	} else if (cpu_is_omap1610() || cpu_is_omap5912()) {
+	} else if (cpu_is_omap1610() || cpu_is_omap5912() || cpu_is_omap730() || cpu_is_omap1710()) {
 		printk(KERN_INFO "OMAP DMA hardware version %d\n",
 		       omap_readw(OMAP_DMA_HW_ID));
 		printk(KERN_INFO "DMA capabilities: %08x:%08x:%04x:%04x:%04x\n",
@@ -771,6 +799,8 @@
 EXPORT_SYMBOL(omap_free_dma);
 EXPORT_SYMBOL(omap_start_dma);
 EXPORT_SYMBOL(omap_stop_dma);
+EXPORT_SYMBOL(omap_enable_dma_irq);
+EXPORT_SYMBOL(omap_disable_dma_irq);
 
 EXPORT_SYMBOL(omap_set_dma_transfer_params);
 EXPORT_SYMBOL(omap_set_dma_constant_fill);
diff -Nru a/arch/arm/mach-omap/fpga.c b/arch/arm/mach-omap/fpga.c
--- a/arch/arm/mach-omap/fpga.c	2004-10-18 14:56:20 -07:00
+++ b/arch/arm/mach-omap/fpga.c	2004-10-18 14:56:20 -07:00
@@ -31,19 +31,9 @@
 #include <asm/arch/fpga.h>
 #include <asm/arch/gpio.h>
 
-unsigned char fpga_read(int reg)
-{
-	return __raw_readb(reg);
-}
-
-void fpga_write(unsigned char val, int reg)
-{
-	__raw_writeb(val, reg);
-}
-
 static void fpga_mask_irq(unsigned int irq)
 {
-	irq -= IH_FPGA_BASE;
+	irq -= OMAP1510_IH_FPGA_BASE;
 
 	if (irq < 8)
 		__raw_writeb((__raw_readb(OMAP1510_FPGA_IMR_LO)
@@ -76,7 +66,7 @@
 
 static void fpga_unmask_irq(unsigned int irq)
 {
-	irq -= IH_FPGA_BASE;
+	irq -= OMAP1510_IH_FPGA_BASE;
 
 	if (irq < 8)
 		__raw_writeb((__raw_readb(OMAP1510_FPGA_IMR_LO) | (1 << irq)),
@@ -114,8 +104,8 @@
 			break;
 		}
 
-		for (fpga_irq = IH_FPGA_BASE;
-			(fpga_irq < (IH_FPGA_BASE + NR_FPGA_IRQS)) && stat;
+		for (fpga_irq = OMAP1510_IH_FPGA_BASE;
+			(fpga_irq < (OMAP1510_IH_FPGA_BASE + NR_FPGA_IRQS)) && stat;
 			fpga_irq++, stat >>= 1) {
 			if (stat & 1) {
 				d = irq_desc + fpga_irq;
@@ -162,7 +152,7 @@
  * interrupts at the interrupt controller via disable_irq/enable_irq
  * could pose a problem.
  */
-void fpga_init_irq(void)
+void omap1510_fpga_init_irq(void)
 {
 	int i;
 
@@ -170,9 +160,9 @@
 	__raw_writeb(0, OMAP1510_FPGA_IMR_HI);
 	__raw_writeb(0, INNOVATOR_FPGA_IMR2);
 
-	for (i = IH_FPGA_BASE; i < (IH_FPGA_BASE + NR_FPGA_IRQS); i++) {
+	for (i = OMAP1510_IH_FPGA_BASE; i < (OMAP1510_IH_FPGA_BASE + NR_FPGA_IRQS); i++) {
 
-		if (i == INT_FPGA_TS) {
+		if (i == OMAP1510_INT_FPGA_TS) {
 			/*
 			 * The touchscreen interrupt is level-sensitive, so
 			 * we'll use the regular mask_ack routine for it.
@@ -201,9 +191,7 @@
 	omap_request_gpio(13);
 	omap_set_gpio_direction(13, 1);
 	omap_set_gpio_edge_ctrl(13, OMAP_GPIO_RISING_EDGE);
-	set_irq_chained_handler(INT_FPGA, innovator_fpga_IRQ_demux);
+	set_irq_chained_handler(OMAP1510_INT_FPGA, innovator_fpga_IRQ_demux);
 }
 
-EXPORT_SYMBOL(fpga_init_irq);
-EXPORT_SYMBOL(fpga_read);
-EXPORT_SYMBOL(fpga_write);
+EXPORT_SYMBOL(omap1510_fpga_init_irq);
diff -Nru a/arch/arm/mach-omap/gpio.c b/arch/arm/mach-omap/gpio.c
--- a/arch/arm/mach-omap/gpio.c	2004-10-18 14:56:29 -07:00
+++ b/arch/arm/mach-omap/gpio.c	2004-10-18 14:56:29 -07:00
@@ -94,7 +94,7 @@
 #define METHOD_GPIO_1610	2
 #define METHOD_GPIO_730		3
 
-#if defined(CONFIG_ARCH_OMAP1610) || defined(CONFIG_ARCH_OMAP5912)
+#if defined(CONFIG_ARCH_OMAP1610) || defined(CONFIG_ARCH_OMAP1710) || defined(CONFIG_ARCH_OMAP5912)
 static struct gpio_bank gpio_bank_1610[5] = {
 	{ OMAP_MPUIO_BASE,     INT_MPUIO,	    IH_MPUIO_BASE,     METHOD_MPUIO},
 	{ OMAP1610_GPIO1_BASE, INT_GPIO_BANK1,	    IH_GPIO_BASE,      METHOD_GPIO_1610 },
@@ -113,7 +113,7 @@
 
 #ifdef CONFIG_ARCH_OMAP730
 static struct gpio_bank gpio_bank_730[7] = {
-	{ OMAP_MPUIO_BASE,     INT_MPUIO,	    IH_MPUIO_BASE,	METHOD_MPUIO },
+	{ OMAP_MPUIO_BASE,     INT_730_MPUIO,	    IH_MPUIO_BASE,	METHOD_MPUIO },
 	{ OMAP730_GPIO1_BASE,  INT_GPIO_BANK1,	    IH_GPIO_BASE,	METHOD_GPIO_730 },
 	{ OMAP730_GPIO2_BASE,  INT_730_GPIO_BANK2,  IH_GPIO_BASE + 32,	METHOD_GPIO_730 },
 	{ OMAP730_GPIO3_BASE,  INT_730_GPIO_BANK3,  IH_GPIO_BASE + 64,	METHOD_GPIO_730 },
@@ -135,8 +135,8 @@
 		return &gpio_bank[1];
 	}
 #endif
-#if defined(CONFIG_ARCH_OMAP1610) || defined(CONFIG_ARCH_OMAP5912)
-	if (cpu_is_omap1610() || cpu_is_omap5912()) {
+#if defined(CONFIG_ARCH_OMAP1610) || defined(CONFIG_ARCH_OMAP1710) || defined(CONFIG_ARCH_OMAP5912)
+	if (cpu_is_omap1610() || cpu_is_omap1710() || cpu_is_omap5912()) {
 		if (OMAP_GPIO_IS_MPUIO(gpio))
 			return &gpio_bank[0];
 		return &gpio_bank[1 + (gpio >> 4)];
@@ -172,8 +172,8 @@
 	if (cpu_is_omap1510() && gpio < 16)
 		return 0;
 #endif
-#if defined(CONFIG_ARCH_OMAP1610) || defined(CONFIG_ARCH_OMAP5912)
-	if ((cpu_is_omap1610() || cpu_is_omap5912()) && gpio < 64)
+#if defined(CONFIG_ARCH_OMAP1610) || defined(CONFIG_ARCH_OMAP1710) || defined(CONFIG_ARCH_OMAP5912)
+	if ((cpu_is_omap1610() || cpu_is_omap1710() || cpu_is_omap5912()) && gpio < 64)
 		return 0;
 #endif
 #ifdef CONFIG_ARCH_OMAP730
@@ -554,7 +554,7 @@
 	if (bank->method == METHOD_GPIO_1510)
 		isr_reg = bank->base + OMAP1510_GPIO_INT_STATUS;
 #endif
-#if defined(CONFIG_ARCH_OMAP1610) || defined(CONFIG_ARCH_OMAP5912)
+#if defined(CONFIG_ARCH_OMAP1610) || defined(CONFIG_ARCH_OMAP1710) || defined(CONFIG_ARCH_OMAP5912)
 	if (bank->method == METHOD_GPIO_1610)
 		isr_reg = bank->base + OMAP1610_GPIO_IRQSTATUS1;
 #endif
@@ -588,7 +588,7 @@
 	if (bank->method == METHOD_GPIO_1510)
 		__raw_writew(1 << (gpio & 0x0f), bank->base + OMAP1510_GPIO_INT_STATUS);
 #endif
-#if defined(CONFIG_ARCH_OMAP1610) || defined(CONFIG_ARCH_OMAP5912)
+#if defined(CONFIG_ARCH_OMAP1610) || defined(CONFIG_ARCH_OMAP1710) || defined(CONFIG_ARCH_OMAP5912)
 	if (bank->method == METHOD_GPIO_1610)
 		__raw_writew(1 << (gpio & 0x0f), bank->base + OMAP1610_GPIO_IRQSTATUS1);
 #endif
@@ -629,7 +629,7 @@
 	unsigned int gpio = OMAP_MPUIO(irq - IH_MPUIO_BASE);
 	struct gpio_bank *bank = get_gpio_bank(gpio);
 
-	_set_gpio_irqenable(bank, gpio, 0);
+	_set_gpio_irqenable(bank, get_gpio_index(gpio), 0);
 }
 
 static void mpuio_unmask_irq(unsigned int irq)
@@ -637,7 +637,7 @@
 	unsigned int gpio = OMAP_MPUIO(irq - IH_MPUIO_BASE);
 	struct gpio_bank *bank = get_gpio_bank(gpio);
 
-	_set_gpio_irqenable(bank, gpio, 1);
+	_set_gpio_irqenable(bank, get_gpio_index(gpio), 1);
 }
 
 static struct irqchip gpio_irq_chip = {
@@ -668,8 +668,8 @@
 		gpio_bank = gpio_bank_1510;
 	}
 #endif
-#if defined(CONFIG_ARCH_OMAP1610) || defined(CONFIG_ARCH_OMAP5912)
-	if (cpu_is_omap1610() || cpu_is_omap5912()) {
+#if defined(CONFIG_ARCH_OMAP1610) || defined(CONFIG_ARCH_OMAP1710) || defined(CONFIG_ARCH_OMAP5912)
+	if (cpu_is_omap1610() || cpu_is_omap1710() || cpu_is_omap5912()) {
 		int rev;
 
 		gpio_bank_count = 5;
@@ -702,7 +702,7 @@
 			__raw_writew(0x0000, bank->base + OMAP1510_GPIO_INT_STATUS);
 		}
 #endif
-#if defined(CONFIG_ARCH_OMAP1610) || defined(CONFIG_ARCH_OMAP5912)
+#if defined(CONFIG_ARCH_OMAP1610) || defined(CONFIG_ARCH_OMAP1710) || defined(CONFIG_ARCH_OMAP5912)
 		if (bank->method == METHOD_GPIO_1610) {
 			__raw_writew(0x0000, bank->base + OMAP1610_GPIO_IRQENABLE1);
 			__raw_writew(0xffff, bank->base + OMAP1610_GPIO_IRQSTATUS1);
@@ -731,7 +731,7 @@
 
 	/* Enable system clock for GPIO module.
 	 * The CAM_CLK_CTRL *is* really the right place. */
-	if (cpu_is_omap1610())
+	if (cpu_is_omap1610() || cpu_is_omap1710())
 		omap_writel(omap_readl(ULPD_CAM_CLK_CTRL) | 0x04, ULPD_CAM_CLK_CTRL);
 
 	return 0;
diff -Nru a/arch/arm/mach-omap/irq.c b/arch/arm/mach-omap/irq.c
--- a/arch/arm/mach-omap/irq.c	2004-10-18 14:56:13 -07:00
+++ b/arch/arm/mach-omap/irq.c	2004-10-18 14:56:13 -07:00
@@ -140,7 +140,9 @@
 };
 #endif
 
-#if defined(CONFIG_ARCH_OMAP1610) || defined(CONFIG_ARCH_OMAP5912)
+#if defined(CONFIG_ARCH_OMAP1610) || defined(CONFIG_ARCH_OMAP5912) \
+				  || defined(CONFIG_ARCH_OMAP1710)
+
 static struct omap_irq_bank omap1610_irq_banks[] = {
 	{ .base_reg = OMAP_IH1_BASE, 		.trigger_map = 0xb3fefe8f },
 	{ .base_reg = OMAP_IH2_BASE, 		.trigger_map = 0xfffff7ff },
@@ -171,8 +173,9 @@
 		irq_bank_count = ARRAY_SIZE(omap1510_irq_banks);
 	}
 #endif
-#if defined(CONFIG_ARCH_OMAP1610) || defined(CONFIG_ARCH_OMAP5912)
-	if (cpu_is_omap1610() || cpu_is_omap5912()) {
+#if defined(CONFIG_ARCH_OMAP1610) || defined(CONFIG_ARCH_OMAP5912) \
+				  || defined(CONFIG_ARCH_OMAP1710)
+	if (cpu_is_omap1610() || cpu_is_omap5912() || cpu_is_omap1710()) {
 		irq_banks = omap1610_irq_banks;
 		irq_bank_count = ARRAY_SIZE(omap1610_irq_banks);
 	}
@@ -190,6 +193,11 @@
 	irq_bank_writel(0x03, 0, IRQ_CONTROL_REG_OFFSET);
 	irq_bank_writel(0x03, 1, IRQ_CONTROL_REG_OFFSET);
 
+	/* Enable interrupts in global mask */
+	if (cpu_is_omap730()) {
+		irq_bank_writel(0x0, 0, IRQ_GMR_REG_OFFSET);
+	}
+
 	/* Install the interrupt handlers for each bank */
 	for (i = 0; i < irq_bank_count; i++) {
 		for (j = i * 32; j < (i + 1) * 32; j++) {
@@ -205,5 +213,9 @@
 	}
 
 	/* Unmask level 2 handler */
-	omap_unmask_irq(INT_IH2_IRQ);
+	if (cpu_is_omap730()) {
+		omap_unmask_irq(INT_730_IH2_IRQ);
+	} else {
+		omap_unmask_irq(INT_IH2_IRQ);
+	}
 }
diff -Nru a/arch/arm/mach-omap/leds-h2p2-debug.c b/arch/arm/mach-omap/leds-h2p2-debug.c
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/arch/arm/mach-omap/leds-h2p2-debug.c	2004-10-18 14:56:49 -07:00
@@ -0,0 +1,104 @@
+/*
+ * linux/arch/arm/mach-omap/leds-h2p2-debug.c
+ *
+ * Copyright 2003 by Texas Instruments Incorporated
+ *
+ */
+#include <linux/config.h>
+#include <linux/init.h>
+#include <linux/kernel_stat.h>
+#include <linux/sched.h>
+#include <linux/version.h>
+
+#include <asm/io.h>
+#include <asm/hardware.h>
+#include <asm/leds.h>
+#include <asm/system.h>
+
+#include <asm/arch/fpga.h>
+
+#include "leds.h"
+
+void h2p2_dbg_leds_event(led_event_t evt)
+{
+	unsigned long flags;
+	static unsigned long hw_led_state = 0;
+
+	local_irq_save(flags);
+
+	switch (evt) {
+	case led_start:
+		hw_led_state |= H2P2_DBG_FPGA_LED_STARTSTOP;
+		break;
+
+	case led_stop:
+		hw_led_state &= ~H2P2_DBG_FPGA_LED_STARTSTOP;
+		break;
+
+	case led_claim:
+		hw_led_state |= H2P2_DBG_FPGA_LED_CLAIMRELEASE;
+		break;
+
+	case led_release:
+		hw_led_state &= ~H2P2_DBG_FPGA_LED_CLAIMRELEASE;
+		break;
+
+#ifdef CONFIG_LEDS_TIMER
+	case led_timer:
+		/*
+		 * Toggle Timer LED
+		 */
+		if (hw_led_state & H2P2_DBG_FPGA_LED_TIMER)
+			hw_led_state &= ~H2P2_DBG_FPGA_LED_TIMER;
+		else
+			hw_led_state |= H2P2_DBG_FPGA_LED_TIMER;
+		break;
+#endif
+
+#ifdef CONFIG_LEDS_CPU
+	case led_idle_start:
+		hw_led_state |= H2P2_DBG_FPGA_LED_IDLE;
+		break;
+
+	case led_idle_end:
+		hw_led_state &= ~H2P2_DBG_FPGA_LED_IDLE;
+		break;
+#endif
+
+	case led_halted:
+		if (hw_led_state & H2P2_DBG_FPGA_LED_HALTED)
+			hw_led_state &= ~H2P2_DBG_FPGA_LED_HALTED;
+		else
+			hw_led_state |= H2P2_DBG_FPGA_LED_HALTED;
+		break;
+
+	case led_green_on:
+		break;
+
+	case led_green_off:
+		break;
+
+	case led_amber_on:
+		break;
+
+	case led_amber_off:
+		break;
+
+	case led_red_on:
+		break;
+
+	case led_red_off:
+		break;
+
+	default:
+		break;
+	}
+
+
+	/*
+	 *  Actually burn the LEDs
+	 */
+	__raw_writew(~hw_led_state & 0xffff, H2P2_DBG_FPGA_LEDS);
+
+	local_irq_restore(flags);
+}
diff -Nru a/arch/arm/mach-omap/leds-perseus2.c b/arch/arm/mach-omap/leds-perseus2.c
--- a/arch/arm/mach-omap/leds-perseus2.c	2004-10-18 14:56:49 -07:00
+++ /dev/null	Wed Dec 31 16:00:00 196900
@@ -1,102 +0,0 @@
-/*
- * linux/arch/arm/mach-omap/leds-perseus2.c
- *
- * Copyright 2003 by Texas Instruments Incorporated
- *
- */
-#include <linux/config.h>
-#include <linux/init.h>
-#include <linux/kernel_stat.h>
-#include <linux/sched.h>
-#include <linux/version.h>
-
-#include <asm/io.h>
-#include <asm/hardware.h>
-#include <asm/leds.h>
-#include <asm/system.h>
-
-#include "leds.h"
-
-void perseus2_leds_event(led_event_t evt)
-{
-	unsigned long flags;
-	static unsigned long hw_led_state = 0;
-
-	local_irq_save(flags);
-
-	switch (evt) {
-	case led_start:
-		hw_led_state |= OMAP730_FPGA_LED_STARTSTOP;
-		break;
-
-	case led_stop:
-		hw_led_state &= ~OMAP730_FPGA_LED_STARTSTOP;
-		break;
-
-	case led_claim:
-		hw_led_state |= OMAP730_FPGA_LED_CLAIMRELEASE;
-		break;
-
-	case led_release:
-		hw_led_state &= ~OMAP730_FPGA_LED_CLAIMRELEASE;
-		break;
-
-#ifdef CONFIG_LEDS_TIMER
-	case led_timer:
-		/*
-		 * Toggle Timer LED
-		 */
-		if (hw_led_state & OMAP730_FPGA_LED_TIMER)
-			hw_led_state &= ~OMAP730_FPGA_LED_TIMER;
-		else
-			hw_led_state |= OMAP730_FPGA_LED_TIMER;
-		break;
-#endif
-
-#ifdef CONFIG_LEDS_CPU
-	case led_idle_start:
-		hw_led_state |= OMAP730_FPGA_LED_IDLE;
-		break;
-
-	case led_idle_end:
-		hw_led_state &= ~OMAP730_FPGA_LED_IDLE;
-		break;
-#endif
-
-	case led_halted:
-		if (hw_led_state & OMAP730_FPGA_LED_HALTED)
-			hw_led_state &= ~OMAP730_FPGA_LED_HALTED;
-		else
-			hw_led_state |= OMAP730_FPGA_LED_HALTED;
-		break;
-
-	case led_green_on:
-		break;
-
-	case led_green_off:
-		break;
-
-	case led_amber_on:
-		break;
-
-	case led_amber_off:
-		break;
-
-	case led_red_on:
-		break;
-
-	case led_red_off:
-		break;
-
-	default:
-		break;
-	}
-
-
-	/*
-	 *  Actually burn the LEDs
-	 */
-	__raw_writew(~hw_led_state & 0xffff, OMAP730_FPGA_LEDS);
-
-	local_irq_restore(flags);
-}
diff -Nru a/arch/arm/mach-omap/leds.c b/arch/arm/mach-omap/leds.c
--- a/arch/arm/mach-omap/leds.c	2004-10-18 14:56:50 -07:00
+++ b/arch/arm/mach-omap/leds.c	2004-10-18 14:56:50 -07:00
@@ -3,6 +3,7 @@
  *
  * OMAP LEDs dispatcher
  */
+#include <linux/kernel.h>
 #include <linux/init.h>
 
 #include <asm/leds.h>
@@ -11,17 +12,17 @@
 #include "leds.h"
 
 static int __init
-omap1510_leds_init(void)
+omap_leds_init(void)
 {
 	if (machine_is_omap_innovator())
 		leds_event = innovator_leds_event;
 
-	else if (machine_is_omap_perseus2()) {
-		leds_event = perseus2_leds_event;
+	else if (machine_is_omap_h2() || machine_is_omap_perseus2()) {
+		leds_event = h2p2_dbg_leds_event;
 	}
 
 	leds_event(led_start);
 	return 0;
 }
 
-__initcall(omap1510_leds_init);
+__initcall(omap_leds_init);
diff -Nru a/arch/arm/mach-omap/leds.h b/arch/arm/mach-omap/leds.h
--- a/arch/arm/mach-omap/leds.h	2004-10-18 14:57:05 -07:00
+++ b/arch/arm/mach-omap/leds.h	2004-10-18 14:57:05 -07:00
@@ -1,2 +1,2 @@
 extern void innovator_leds_event(led_event_t evt);
-extern void perseus2_leds_event(led_event_t evt);
+extern void h2p2_dbg_leds_event(led_event_t evt);
diff -Nru a/arch/arm/mach-omap/mcbsp.c b/arch/arm/mach-omap/mcbsp.c
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/arch/arm/mach-omap/mcbsp.c	2004-10-18 14:57:23 -07:00
@@ -0,0 +1,669 @@
+/*
+ * linux/arch/arm/omap/mcbsp.c
+ *
+ * Copyright (C) 2004 Nokia Corporation
+ * Author: Samuel Ortiz <samuel.ortiz@nokia.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.
+ *
+ * Multichannel mode not supported.
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/device.h>
+#include <linux/wait.h>
+#include <linux/completion.h>
+#include <linux/interrupt.h>
+
+#include <asm/delay.h>
+#include <asm/io.h>
+#include <asm/irq.h>
+
+#include <asm/arch/dma.h>
+#include <asm/arch/mux.h>
+#include <asm/arch/irqs.h>
+#include <asm/arch/mcbsp.h>
+
+#ifdef CONFIG_MCBSP_DEBUG
+#define DBG(x...)	printk(x)
+#else
+#define DBG(x...)	do { } while (0)
+#endif
+
+struct omap_mcbsp {
+	u32                          io_base;
+	u8                           id;
+	u8                           free;
+	omap_mcbsp_word_length       rx_word_length;
+	omap_mcbsp_word_length       tx_word_length;
+
+	/* IRQ based TX/RX */
+	int                          rx_irq;
+	int                          tx_irq;
+
+	/* DMA stuff */
+	u8                           dma_rx_sync;
+	short                        dma_rx_lch;
+	u8                           dma_tx_sync;
+	short                        dma_tx_lch;
+
+	/* Completion queues */
+	struct completion            tx_irq_completion;
+	struct completion            rx_irq_completion;
+	struct completion            tx_dma_completion;
+	struct completion            rx_dma_completion;
+
+	spinlock_t                   lock;
+};
+
+static struct omap_mcbsp mcbsp[OMAP_MAX_MCBSP_COUNT];
+
+
+static void omap_mcbsp_dump_reg(u8 id)
+{
+	DBG("**** MCBSP%d regs ****\n", mcbsp[id].id);
+	DBG("DRR2:  0x%04x\n", OMAP_MCBSP_READ(mcbsp[id].io_base, DRR2));
+	DBG("DRR1:  0x%04x\n", OMAP_MCBSP_READ(mcbsp[id].io_base, DRR1));
+	DBG("DXR2:  0x%04x\n", OMAP_MCBSP_READ(mcbsp[id].io_base, DXR2));
+	DBG("DXR1:  0x%04x\n", OMAP_MCBSP_READ(mcbsp[id].io_base, DXR1));
+	DBG("SPCR2: 0x%04x\n", OMAP_MCBSP_READ(mcbsp[id].io_base, SPCR2));
+	DBG("SPCR1: 0x%04x\n", OMAP_MCBSP_READ(mcbsp[id].io_base, SPCR1));
+	DBG("RCR2:  0x%04x\n", OMAP_MCBSP_READ(mcbsp[id].io_base, RCR2));
+	DBG("RCR1:  0x%04x\n", OMAP_MCBSP_READ(mcbsp[id].io_base, RCR1));
+	DBG("XCR2:  0x%04x\n", OMAP_MCBSP_READ(mcbsp[id].io_base, XCR2));
+	DBG("XCR1:  0x%04x\n", OMAP_MCBSP_READ(mcbsp[id].io_base, XCR1));
+	DBG("SRGR2: 0x%04x\n", OMAP_MCBSP_READ(mcbsp[id].io_base, SRGR2));
+	DBG("SRGR1: 0x%04x\n", OMAP_MCBSP_READ(mcbsp[id].io_base, SRGR1));
+	DBG("PCR0:  0x%04x\n", OMAP_MCBSP_READ(mcbsp[id].io_base, PCR0));
+	DBG("***********************\n");
+}
+
+
+static irqreturn_t omap_mcbsp_tx_irq_handler(int irq, void *dev_id, struct pt_regs *regs)
+{
+	struct omap_mcbsp * mcbsp_tx = (struct omap_mcbsp *)(dev_id);
+
+	DBG("TX IRQ callback : 0x%x\n", OMAP_MCBSP_READ(mcbsp_tx->io_base, SPCR2));
+
+	complete(&mcbsp_tx->tx_irq_completion);
+	return IRQ_HANDLED;
+}
+
+static irqreturn_t omap_mcbsp_rx_irq_handler(int irq, void *dev_id, struct pt_regs *regs)
+{
+	struct omap_mcbsp * mcbsp_rx = (struct omap_mcbsp *)(dev_id);
+
+	DBG("RX IRQ callback : 0x%x\n", OMAP_MCBSP_READ(mcbsp_rx->io_base, SPCR2));
+
+	complete(&mcbsp_rx->rx_irq_completion);
+	return IRQ_HANDLED;
+}
+
+
+static void omap_mcbsp_tx_dma_callback(int lch, u16 ch_status, void *data)
+{
+	struct omap_mcbsp * mcbsp_dma_tx = (struct omap_mcbsp *)(data);
+
+	DBG("TX DMA callback : 0x%x\n", OMAP_MCBSP_READ(mcbsp_dma_tx->io_base, SPCR2));
+
+	/* We can free the channels */
+	omap_free_dma(mcbsp_dma_tx->dma_tx_lch);
+	mcbsp_dma_tx->dma_tx_lch = -1;
+
+	complete(&mcbsp_dma_tx->tx_dma_completion);
+}
+
+static void omap_mcbsp_rx_dma_callback(int lch, u16 ch_status, void *data)
+{
+	struct omap_mcbsp * mcbsp_dma_rx = (struct omap_mcbsp *)(data);
+
+	DBG("RX DMA callback : 0x%x\n", OMAP_MCBSP_READ(mcbsp_dma_rx->io_base, SPCR2));
+
+	/* We can free the channels */
+	omap_free_dma(mcbsp_dma_rx->dma_rx_lch);
+	mcbsp_dma_rx->dma_rx_lch = -1;
+
+	complete(&mcbsp_dma_rx->rx_dma_completion);
+}
+
+
+/*
+ * omap_mcbsp_config simply write a config to the
+ * appropriate McBSP.
+ * You either call this function or set the McBSP registers
+ * by yourself before calling omap_mcbsp_start().
+ */
+
+void omap_mcbsp_config(unsigned int id, const struct omap_mcbsp_reg_cfg * config)
+{
+	u32 io_base = mcbsp[id].io_base;
+
+	DBG("OMAP-McBSP: McBSP%d  io_base: 0x%8x\n", id+1, io_base);
+
+	/* We write the given config */
+	OMAP_MCBSP_WRITE(io_base, SPCR2, config->spcr2);
+	OMAP_MCBSP_WRITE(io_base, SPCR1, config->spcr1);
+	OMAP_MCBSP_WRITE(io_base, RCR2, config->rcr2);
+	OMAP_MCBSP_WRITE(io_base, RCR1, config->rcr1);
+	OMAP_MCBSP_WRITE(io_base, XCR2, config->xcr2);
+	OMAP_MCBSP_WRITE(io_base, XCR1, config->xcr1);
+	OMAP_MCBSP_WRITE(io_base, SRGR2, config->srgr2);
+	OMAP_MCBSP_WRITE(io_base, SRGR1, config->srgr1);
+	OMAP_MCBSP_WRITE(io_base, SRGR2, config->mcr2);
+	OMAP_MCBSP_WRITE(io_base, SRGR1, config->mcr1);
+	OMAP_MCBSP_WRITE(io_base, PCR0, config->pcr0);
+}
+
+
+
+static int omap_mcbsp_check(unsigned int id)
+{
+	if (cpu_is_omap730()) {
+		if (id > OMAP_MAX_MCBSP_COUNT - 1) {
+		       printk(KERN_ERR "OMAP-McBSP: McBSP%d doesn't exist\n", id + 1);
+		       return -1;
+		}
+		return 0;
+	}
+
+	if (cpu_is_omap1510() || cpu_is_omap1610() || cpu_is_omap1710()) {
+		if (id > OMAP_MAX_MCBSP_COUNT) {
+			printk(KERN_ERR "OMAP-McBSP: McBSP%d doesn't exist\n", id + 1);
+			return -1;
+		}
+		return 0;
+	}
+
+	return -1;
+}
+
+#define DSP_RSTCT2              0xe1008014
+
+static void omap_mcbsp_dsp_request(void)
+{
+	if (cpu_is_omap1510() || cpu_is_omap1610() || cpu_is_omap1710()) {
+		omap_writew((omap_readw(ARM_RSTCT1) | (1 << 1) | (1 << 2)),
+			    ARM_RSTCT1);
+		omap_writew((omap_readw(ARM_CKCTL) | 1 << EN_DSPCK),
+			    ARM_CKCTL);
+		omap_writew((omap_readw(ARM_IDLECT2) | (1 << EN_APICK)),
+			    ARM_IDLECT2);
+
+		/* enable 12MHz clock to mcbsp 1 & 3 */
+		__raw_writew(__raw_readw(DSP_IDLECT2) | (1 << EN_XORPCK),
+			     DSP_IDLECT2);
+		__raw_writew(__raw_readw(DSP_RSTCT2) | 1 | 1 << 1,
+			     DSP_RSTCT2);
+	}
+}
+
+static void omap_mcbsp_dsp_free(void)
+{
+	/* Useless for now */
+}
+
+
+int omap_mcbsp_request(unsigned int id)
+{
+	int err;
+
+	if (omap_mcbsp_check(id) < 0)
+		return -EINVAL;
+
+	/*
+	 * On 1510, 1610 and 1710, McBSP1 and McBSP3
+	 * are DSP public peripherals.
+	 */
+	if (id == OMAP_MCBSP1 || id == OMAP_MCBSP3)
+		omap_mcbsp_dsp_request();
+
+	spin_lock(&mcbsp[id].lock);
+	if (!mcbsp[id].free) {
+		printk (KERN_ERR "OMAP-McBSP: McBSP%d is currently in use\n", id + 1);
+		spin_unlock(&mcbsp[id].lock);
+		return -1;
+	}
+
+	mcbsp[id].free = 0;
+	spin_unlock(&mcbsp[id].lock);
+
+	/* We need to get IRQs here */
+	err = request_irq(mcbsp[id].tx_irq, omap_mcbsp_tx_irq_handler, 0,
+			  "McBSP",
+			  (void *) (&mcbsp[id]));
+	if (err != 0) {
+		printk(KERN_ERR "OMAP-McBSP: Unable to request TX IRQ %d for McBSP%d\n",
+		       mcbsp[id].tx_irq, mcbsp[id].id);
+		return err;
+	}
+
+	init_completion(&(mcbsp[id].tx_irq_completion));
+
+
+	err = request_irq(mcbsp[id].rx_irq, omap_mcbsp_rx_irq_handler, 0,
+			  "McBSP",
+			  (void *) (&mcbsp[id]));
+	if (err != 0) {
+		printk(KERN_ERR "OMAP-McBSP: Unable to request RX IRQ %d for McBSP%d\n",
+		       mcbsp[id].rx_irq, mcbsp[id].id);
+		free_irq(mcbsp[id].tx_irq, (void *) (&mcbsp[id]));
+		return err;
+	}
+
+	init_completion(&(mcbsp[id].rx_irq_completion));
+	return 0;
+
+}
+
+void omap_mcbsp_free(unsigned int id)
+{
+	if (omap_mcbsp_check(id) < 0)
+		return;
+
+	if (id == OMAP_MCBSP1 || id == OMAP_MCBSP3)
+		omap_mcbsp_dsp_free();
+
+	spin_lock(&mcbsp[id].lock);
+	if (mcbsp[id].free) {
+		printk (KERN_ERR "OMAP-McBSP: McBSP%d was not reserved\n", id + 1);
+		spin_unlock(&mcbsp[id].lock);
+		return;
+	}
+
+	mcbsp[id].free = 1;
+	spin_unlock(&mcbsp[id].lock);
+
+	/* Free IRQs */
+	free_irq(mcbsp[id].rx_irq, (void *) (&mcbsp[id]));
+	free_irq(mcbsp[id].tx_irq, (void *) (&mcbsp[id]));
+}
+
+/*
+ * Here we start the McBSP, by enabling the sample
+ * generator, both transmitter and receivers,
+ * and the frame sync.
+ */
+void omap_mcbsp_start(unsigned int id)
+{
+	u32 io_base;
+	u16 w;
+
+	if (omap_mcbsp_check(id) < 0)
+		return;
+
+	io_base = mcbsp[id].io_base;
+
+	mcbsp[id].rx_word_length = ((OMAP_MCBSP_READ(io_base, RCR1) >> 5) & 0x7);
+	mcbsp[id].tx_word_length = ((OMAP_MCBSP_READ(io_base, XCR1) >> 5) & 0x7);
+
+	/* Start the sample generator */
+	w = OMAP_MCBSP_READ(io_base, SPCR2);
+	OMAP_MCBSP_WRITE(io_base, SPCR2, w | (1 << 6));
+
+	/* Enable transmitter and receiver */
+	w = OMAP_MCBSP_READ(io_base, SPCR2);
+	OMAP_MCBSP_WRITE(io_base, SPCR2, w | 1);
+
+	w = OMAP_MCBSP_READ(io_base, SPCR1);
+	OMAP_MCBSP_WRITE(io_base, SPCR1, w | 1);
+
+	udelay(100);
+
+	/* Start frame sync */
+	w = OMAP_MCBSP_READ(io_base, SPCR2);
+	OMAP_MCBSP_WRITE(io_base, SPCR2, w | (1 << 7));
+
+	/* Dump McBSP Regs */
+	omap_mcbsp_dump_reg(id);
+
+}
+
+void omap_mcbsp_stop(unsigned int id)
+{
+	u32 io_base;
+	u16 w;
+
+	if (omap_mcbsp_check(id) < 0)
+		return;
+
+	io_base = mcbsp[id].io_base;
+
+        /* Reset transmitter */
+	w = OMAP_MCBSP_READ(io_base, SPCR2);
+	OMAP_MCBSP_WRITE(io_base, SPCR2, w & ~(1));
+
+	/* Reset receiver */
+	w = OMAP_MCBSP_READ(io_base, SPCR1);
+	OMAP_MCBSP_WRITE(io_base, SPCR1, w & ~(1));
+
+	/* Reset the sample rate generator */
+	w = OMAP_MCBSP_READ(io_base, SPCR2);
+	OMAP_MCBSP_WRITE(io_base, SPCR2, w & ~(1 << 6));
+}
+
+
+/*
+ * IRQ based word transmission.
+ */
+void omap_mcbsp_xmit_word(unsigned int id, u32 word)
+{
+	u32 io_base;
+	omap_mcbsp_word_length word_length = mcbsp[id].tx_word_length;
+
+	if (omap_mcbsp_check(id) < 0)
+		return;
+
+	io_base = mcbsp[id].io_base;
+
+	wait_for_completion(&(mcbsp[id].tx_irq_completion));
+
+	if (word_length > OMAP_MCBSP_WORD_16)
+		OMAP_MCBSP_WRITE(io_base, DXR2, word >> 16);
+	OMAP_MCBSP_WRITE(io_base, DXR1, word & 0xffff);
+}
+
+u32 omap_mcbsp_recv_word(unsigned int id)
+{
+	u32 io_base;
+	u16 word_lsb, word_msb = 0;
+	omap_mcbsp_word_length word_length = mcbsp[id].rx_word_length;
+
+	if (omap_mcbsp_check(id) < 0)
+		return -EINVAL;
+
+	io_base = mcbsp[id].io_base;
+
+	wait_for_completion(&(mcbsp[id].rx_irq_completion));
+
+	if (word_length > OMAP_MCBSP_WORD_16)
+		word_msb = OMAP_MCBSP_READ(io_base, DRR2);
+	word_lsb = OMAP_MCBSP_READ(io_base, DRR1);
+
+	return (word_lsb | (word_msb << 16));
+}
+
+
+/*
+ * Simple DMA based buffer rx/tx routines.
+ * Nothing fancy, just a single buffer tx/rx through DMA.
+ * The DMA resources are released once the transfer is done.
+ * For anything fancier, you should use your own customized DMA
+ * routines and callbacks.
+ */
+int omap_mcbsp_xmit_buffer(unsigned int id, dma_addr_t buffer, unsigned int length)
+{
+	int dma_tx_ch;
+
+	if (omap_mcbsp_check(id) < 0)
+		return -EINVAL;
+
+	if (omap_request_dma(mcbsp[id].dma_tx_sync, "McBSP TX", omap_mcbsp_tx_dma_callback,
+			     &mcbsp[id],
+			     &dma_tx_ch)) {
+		printk("OMAP-McBSP: Unable to request DMA channel for McBSP%d TX. Trying IRQ based TX\n", id+1);
+		return -EAGAIN;
+	}
+	mcbsp[id].dma_tx_lch = dma_tx_ch;
+
+	DBG("TX DMA on channel %d\n", dma_tx_ch);
+
+	init_completion(&(mcbsp[id].tx_dma_completion));
+
+	omap_set_dma_transfer_params(mcbsp[id].dma_tx_lch,
+				     OMAP_DMA_DATA_TYPE_S16,
+				     length >> 1, 1,
+				     OMAP_DMA_SYNC_ELEMENT);
+
+	omap_set_dma_dest_params(mcbsp[id].dma_tx_lch,
+				 OMAP_DMA_PORT_TIPB,
+				 OMAP_DMA_AMODE_CONSTANT,
+				 mcbsp[id].io_base + OMAP_MCBSP_REG_DXR1);
+
+	omap_set_dma_src_params(mcbsp[id].dma_tx_lch,
+				OMAP_DMA_PORT_EMIFF,
+				OMAP_DMA_AMODE_POST_INC,
+				buffer);
+
+	omap_start_dma(mcbsp[id].dma_tx_lch);
+	wait_for_completion(&(mcbsp[id].tx_dma_completion));
+	return 0;
+}
+
+
+int omap_mcbsp_recv_buffer(unsigned int id, dma_addr_t buffer, unsigned int length)
+{
+	int dma_rx_ch;
+
+	if (omap_mcbsp_check(id) < 0)
+		return -EINVAL;
+
+	if (omap_request_dma(mcbsp[id].dma_rx_sync, "McBSP RX", omap_mcbsp_rx_dma_callback,
+			     &mcbsp[id],
+			     &dma_rx_ch)) {
+		printk("Unable to request DMA channel for McBSP%d RX. Trying IRQ based RX\n", id+1);
+		return -EAGAIN;
+	}
+	mcbsp[id].dma_rx_lch = dma_rx_ch;
+
+	DBG("RX DMA on channel %d\n", dma_rx_ch);
+
+	init_completion(&(mcbsp[id].rx_dma_completion));
+
+	omap_set_dma_transfer_params(mcbsp[id].dma_rx_lch,
+				     OMAP_DMA_DATA_TYPE_S16,
+				     length >> 1, 1,
+				     OMAP_DMA_SYNC_ELEMENT);
+
+	omap_set_dma_src_params(mcbsp[id].dma_rx_lch,
+				OMAP_DMA_PORT_TIPB,
+				OMAP_DMA_AMODE_CONSTANT,
+				mcbsp[id].io_base + OMAP_MCBSP_REG_DRR1);
+
+	omap_set_dma_dest_params(mcbsp[id].dma_rx_lch,
+				 OMAP_DMA_PORT_EMIFF,
+				 OMAP_DMA_AMODE_POST_INC,
+				 buffer);
+
+	omap_start_dma(mcbsp[id].dma_rx_lch);
+	wait_for_completion(&(mcbsp[id].rx_dma_completion));
+	return 0;
+}
+
+
+/*
+ * SPI wrapper.
+ * Since SPI setup is much simpler than the generic McBSP one,
+ * this wrapper just need an omap_mcbsp_spi_cfg structure as an input.
+ * Once this is done, you can call omap_mcbsp_start().
+ */
+void omap_mcbsp_set_spi_mode(unsigned int id, const struct omap_mcbsp_spi_cfg * spi_cfg)
+{
+	struct omap_mcbsp_reg_cfg mcbsp_cfg;
+
+	if (omap_mcbsp_check(id) < 0)
+		return;
+
+	memset(&mcbsp_cfg, 0, sizeof(struct omap_mcbsp_reg_cfg));
+
+	/* SPI has only one frame */
+	mcbsp_cfg.rcr1 |= (RWDLEN1(spi_cfg->word_length) | RFRLEN1(0));
+	mcbsp_cfg.xcr1 |= (XWDLEN1(spi_cfg->word_length) | XFRLEN1(0));
+
+        /* Clock stop mode */
+	if (spi_cfg->clk_stp_mode == OMAP_MCBSP_CLK_STP_MODE_NO_DELAY)
+		mcbsp_cfg.spcr1 |= (1 << 12);
+	else
+		mcbsp_cfg.spcr1 |= (3 << 11);
+
+	/* Set clock parities */
+	if (spi_cfg->rx_clock_polarity == OMAP_MCBSP_CLK_RISING)
+		mcbsp_cfg.pcr0 |= CLKRP;
+	else
+		mcbsp_cfg.pcr0 &= ~CLKRP;
+
+	if (spi_cfg->tx_clock_polarity == OMAP_MCBSP_CLK_RISING)
+		mcbsp_cfg.pcr0 &= ~CLKXP;
+	else
+		mcbsp_cfg.pcr0 |= CLKXP;
+
+	/* Set SCLKME to 0 and CLKSM to 1 */
+	mcbsp_cfg.pcr0 &= ~SCLKME;
+	mcbsp_cfg.srgr2 |= CLKSM;
+
+	/* Set FSXP */
+	if (spi_cfg->fsx_polarity == OMAP_MCBSP_FS_ACTIVE_HIGH)
+		mcbsp_cfg.pcr0 &= ~FSXP;
+	else
+		mcbsp_cfg.pcr0 |= FSXP;
+
+	if (spi_cfg->spi_mode == OMAP_MCBSP_SPI_MASTER) {
+		mcbsp_cfg.pcr0 |= CLKXM;
+		mcbsp_cfg.srgr1 |= CLKGDV(spi_cfg->clk_div -1);
+		mcbsp_cfg.pcr0 |= FSXM;
+		mcbsp_cfg.srgr2 &= ~FSGM;
+		mcbsp_cfg.xcr2 |= XDATDLY(1);
+		mcbsp_cfg.rcr2 |= RDATDLY(1);
+	}
+	else {
+		mcbsp_cfg.pcr0 &= ~CLKXM;
+		mcbsp_cfg.srgr1 |= CLKGDV(1);
+		mcbsp_cfg.pcr0 &= ~FSXM;
+		mcbsp_cfg.xcr2 &= ~XDATDLY(3);
+		mcbsp_cfg.rcr2 &= ~RDATDLY(3);
+	}
+
+	mcbsp_cfg.xcr2 &= ~XPHASE;
+	mcbsp_cfg.rcr2 &= ~RPHASE;
+
+	omap_mcbsp_config(id, &mcbsp_cfg);
+}
+
+
+/*
+ * McBSP1 and McBSP3 are directly mapped on 1610 and 1510.
+ * 730 has only 2 McBSP, and both of them are MPU peripherals.
+ */
+struct omap_mcbsp_info {
+	u32 virt_base;
+	u8 dma_rx_sync, dma_tx_sync;
+	u16 rx_irq, tx_irq;
+};
+
+#ifdef CONFIG_ARCH_OMAP730
+static const struct omap_mcbsp_info mcbsp_730[] = {
+	[0] = { .virt_base = io_p2v(OMAP730_MCBSP1_BASE),
+		.dma_rx_sync = OMAP_DMA_MCBSP1_RX,
+		.dma_tx_sync = OMAP_DMA_MCBSP1_TX,
+		.rx_irq = INT_730_McBSP1RX,
+		.tx_irq = INT_730_McBSP1TX },
+	[1] = { .virt_base = io_p2v(OMAP730_MCBSP2_BASE),
+		.dma_rx_sync = OMAP_DMA_MCBSP3_RX,
+		.dma_tx_sync = OMAP_DMA_MCBSP3_TX,
+		.rx_irq = INT_730_McBSP2RX,
+		.tx_irq = INT_730_McBSP2TX },
+};
+#endif
+
+#ifdef CONFIG_ARCH_OMAP1510
+static const struct omap_mcbsp_info mcbsp_1510[] = {
+	[0] = { .virt_base = OMAP1510_MCBSP1_BASE,
+		.dma_rx_sync = OMAP_DMA_MCBSP1_RX,
+		.dma_tx_sync = OMAP_DMA_MCBSP1_TX,
+		.rx_irq = INT_McBSP1RX,
+		.tx_irq = INT_McBSP1TX },
+	[1] = { .virt_base = io_p2v(OMAP1510_MCBSP2_BASE),
+		.dma_rx_sync = OMAP_DMA_MCBSP2_RX,
+		.dma_tx_sync = OMAP_DMA_MCBSP2_TX,
+		.rx_irq = INT_1510_SPI_RX,
+		.tx_irq = INT_1510_SPI_TX },
+	[2] = { .virt_base = OMAP1510_MCBSP3_BASE,
+		.dma_rx_sync = OMAP_DMA_MCBSP3_RX,
+		.dma_tx_sync = OMAP_DMA_MCBSP3_TX,
+		.rx_irq = INT_McBSP3RX,
+		.tx_irq = INT_McBSP3TX },
+};
+#endif
+
+#if defined(CONFIG_ARCH_OMAP1610) || defined(CONFIG_ARCH_OMAP1710)
+static const struct omap_mcbsp_info mcbsp_1610[] = {
+	[0] = { .virt_base = OMAP1610_MCBSP1_BASE,
+		.dma_rx_sync = OMAP_DMA_MCBSP1_RX,
+		.dma_tx_sync = OMAP_DMA_MCBSP1_TX,
+		.rx_irq = INT_McBSP1RX,
+		.tx_irq = INT_McBSP1TX },
+	[1] = { .virt_base = io_p2v(OMAP1610_MCBSP2_BASE),
+		.dma_rx_sync = OMAP_DMA_MCBSP2_RX,
+		.dma_tx_sync = OMAP_DMA_MCBSP2_TX,
+		.rx_irq = INT_1610_McBSP2_RX,
+		.tx_irq = INT_1610_McBSP2_TX },
+	[2] = { .virt_base = OMAP1610_MCBSP3_BASE,
+		.dma_rx_sync = OMAP_DMA_MCBSP3_RX,
+		.dma_tx_sync = OMAP_DMA_MCBSP3_TX,
+		.rx_irq = INT_McBSP3RX,
+		.tx_irq = INT_McBSP3TX },
+};
+#endif
+
+static int __init omap_mcbsp_init(void)
+{
+	int mcbsp_count = 0, i;
+	static const struct omap_mcbsp_info *mcbsp_info;
+
+	printk("Initializing OMAP McBSP system\n");
+#ifdef CONFIG_ARCH_OMAP730
+	if (cpu_is_omap730()) {
+		mcbsp_info = mcbsp_730;
+		mcbsp_count = ARRAY_SIZE(mcbsp_730);
+	}
+#endif
+#ifdef CONFIG_ARCH_OMAP1510
+	if (cpu_is_omap1510()) {
+		mcbsp_info = mcbsp_1510;
+		mcbsp_count = ARRAY_SIZE(mcbsp_1510);
+	}
+#endif
+#if defined(CONFIG_ARCH_OMAP1610) || defined(CONFIG_ARCH_OMAP1710)
+	if (cpu_is_omap1610() || cpu_is_omap1710()) {
+		mcbsp_info = mcbsp_1610;
+		mcbsp_count = ARRAY_SIZE(mcbsp_1610);
+	}
+#endif
+	for (i = 0; i < OMAP_MAX_MCBSP_COUNT ; i++) {
+		if (i >= mcbsp_count) {
+			mcbsp[i].io_base = 0;
+			mcbsp[i].free = 0;
+                        continue;
+		}
+		mcbsp[i].id = i + 1;
+		mcbsp[i].free = 1;
+		mcbsp[i].dma_tx_lch = -1;
+		mcbsp[i].dma_rx_lch = -1;
+
+		mcbsp[i].io_base = mcbsp_info[i].virt_base;
+		mcbsp[i].tx_irq = mcbsp_info[i].tx_irq;
+		mcbsp[i].rx_irq = mcbsp_info[i].rx_irq;
+		mcbsp[i].dma_rx_sync = mcbsp_info[i].dma_rx_sync;
+		mcbsp[i].dma_tx_sync = mcbsp_info[i].dma_tx_sync;
+		spin_lock_init(&mcbsp[i].lock);
+	}
+
+	return 0;
+}
+
+
+arch_initcall(omap_mcbsp_init);
+
+EXPORT_SYMBOL(omap_mcbsp_config);
+EXPORT_SYMBOL(omap_mcbsp_request);
+EXPORT_SYMBOL(omap_mcbsp_free);
+EXPORT_SYMBOL(omap_mcbsp_start);
+EXPORT_SYMBOL(omap_mcbsp_stop);
+EXPORT_SYMBOL(omap_mcbsp_xmit_word);
+EXPORT_SYMBOL(omap_mcbsp_recv_word);
+EXPORT_SYMBOL(omap_mcbsp_xmit_buffer);
+EXPORT_SYMBOL(omap_mcbsp_recv_buffer);
+EXPORT_SYMBOL(omap_mcbsp_set_spi_mode);
diff -Nru a/arch/arm/mach-omap/ocpi.c b/arch/arm/mach-omap/ocpi.c
--- a/arch/arm/mach-omap/ocpi.c	2004-10-18 14:57:04 -07:00
+++ b/arch/arm/mach-omap/ocpi.c	2004-10-18 14:57:04 -07:00
@@ -59,8 +59,8 @@
 
 	/* Make sure there's clock for OCPI */
 
-#ifdef CONFIG_ARCH_OMAP1610
-        if (cpu_is_omap1610()) {
+#if defined(CONFIG_ARCH_OMAP1610) || defined(CONFIG_ARCH_OMAP1710)
+        if (cpu_is_omap1610() || cpu_is_omap1710()) {
 		val = omap_readl(OMAP1610_ARM_IDLECT3);
 		val |= EN_OCPI_CK;
 		val &= ~IDLOCPI_ARM;
diff -Nru a/arch/arm/mach-omap/usb.c b/arch/arm/mach-omap/usb.c
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/arch/arm/mach-omap/usb.c	2004-10-18 14:57:24 -07:00
@@ -0,0 +1,541 @@
+/*
+ * arch/arm/mach-omap/usb.c -- platform level USB initialization
+ *
+ * Copyright (C) 2004 Texas Instruments, 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.
+ *
+ * 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
+ */
+
+#undef	DEBUG
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/device.h>
+#include <linux/usb_otg.h>
+
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/system.h>
+#include <asm/hardware.h>
+#include <asm/mach-types.h>
+
+#include <asm/arch/mux.h>
+#include <asm/arch/usb.h>
+#include <asm/arch/board.h>
+
+/* These routines should handle the standard chip-specific modes
+ * for usb0/1/2 ports, covering basic mux and transceiver setup.
+ * Call omap_usb_init() once, from INIT_MACHINE().
+ *
+ * Some board-*.c files will need to set up additional mux options,
+ * like for suspend handling, vbus sensing, GPIOs, and the D+ pullup.
+ */
+
+/* TESTED ON:
+ *  - 1611B H2 (with usb1 mini-AB)
+ *  - 1510 Innovator with built-in transceiver (custom cable feeding 5V VBUS)
+ *  - 1710 custom development board using alternate pin group
+ */
+
+/*-------------------------------------------------------------------------*/
+
+#ifdef	CONFIG_ARCH_OMAP_OTG
+
+static struct otg_transceiver *xceiv;
+
+/**
+ * otg_get_transceiver - find the (single) OTG transceiver driver
+ *
+ * Returns the transceiver driver, after getting a refcount to it; or
+ * null if there is no such transceiver.  The caller is responsible for
+ * releasing that count.
+ */
+struct otg_transceiver *otg_get_transceiver(void)
+{
+	if (xceiv)
+		get_device(xceiv->dev);
+	return xceiv;
+}
+EXPORT_SYMBOL(otg_get_transceiver);
+
+int otg_set_transceiver(struct otg_transceiver *x)
+{
+	if (xceiv && x)
+		return -EBUSY;
+	xceiv = x;
+	return 0;
+}
+EXPORT_SYMBOL(otg_set_transceiver);
+
+#endif
+
+/*-------------------------------------------------------------------------*/
+
+static u32 __init omap_usb0_init(unsigned nwires, unsigned is_device)
+{
+	u32	syscon1 = 0;
+
+	if (nwires == 0) {
+		USB_TRANSCEIVER_CTRL_REG &= ~(1 << 3);
+		return 0;
+	}
+
+	/*
+	 * VP and VM are needed for all active usb0 configurations.
+	 * USB0_VP and USB0_VM are always set on 1510, there's no muxing
+	 * available for them.
+	 */
+	if (nwires >= 2 && !cpu_is_omap1510()) {
+		omap_cfg_reg(AA9_USB0_VP);
+		omap_cfg_reg(R9_USB0_VM);
+	}
+
+	/* internal transceiver */
+	if (nwires == 2) {
+		if (cpu_is_omap1510()) {
+			/* This works for OHCI on 1510-Innovator, nothing to mux */
+			return 0;
+		}
+
+#if 0
+		/* NOTE:  host OR device mode for now, no OTG */
+		USB_TRANSCEIVER_CTRL_REG &= ~(3 << 4);
+		if (is_device) {
+			omap_cfg_reg(W4_USB_PUEN);
+			omap_cfg_reg(R18_1510_USB_GPIO0);
+			// omap_cfg_reg(USB0_VBUS);
+			// omap_cfg_reg(USB0_PUEN);
+			// USB_TRANSCEIVER_CTRL_REG.CONF_USB0_PORT_R = 7
+			// when USB0_PUEN is needed
+		} else /* host mode needs D+ and D- pulldowns */
+			USB_TRANSCEIVER_CTRL_REG &= ~(3 << 1);
+		return 3 << 16;
+#else
+		/* FIXME: 1610 needs to return the right value here */
+		printk(KERN_ERR "usb0 internal transceiver, nyet\n");
+		return 0;
+#endif
+	}
+
+	/* alternate pin config, external transceiver */
+	omap_cfg_reg(V6_USB0_TXD);
+	omap_cfg_reg(W9_USB0_TXEN);
+	omap_cfg_reg(W5_USB0_SE0);
+
+#ifdef CONFIG_ARCH_OMAP_USB_SPEED
+	/* FIXME: there's good chance that pin V9 is used for MMC2 port cmddir */
+	omap_cfg_reg(V9_USB0_SPEED);
+	// omap_cfg_reg(V9_USB0_SUSP);
+#endif
+
+	if (nwires != 3)
+		omap_cfg_reg(Y5_USB0_RCV);
+
+	switch (nwires) {
+	case 3:
+		syscon1 = 2;
+		break;
+	case 4:
+		syscon1 = 1;
+		break;
+	case 6:
+		syscon1 = 3;
+		/* REVISIT: Is CONF_USB2_UNI_R only needed when nwires = 6? */
+		USB_TRANSCEIVER_CTRL_REG |= CONF_USB2_UNI_R;
+		break;
+	default:
+		printk(KERN_ERR "illegal usb%d %d-wire transceiver\n",
+			0, nwires);
+	}
+	return syscon1 << 16;
+}
+
+static u32 __init omap_usb1_init(unsigned nwires)
+{
+	u32	syscon1 = 0;
+
+	if (nwires != 6)
+		USB_TRANSCEIVER_CTRL_REG &= ~CONF_USB1_UNI_R;
+	if (nwires == 0)
+		return 0;
+
+	/* external transceiver */
+	omap_cfg_reg(USB1_TXD);
+	omap_cfg_reg(USB1_TXEN);
+	if (cpu_is_omap1510()) {
+		omap_cfg_reg(USB1_SEO);
+		omap_cfg_reg(USB1_SPEED);
+		// SUSP
+	} else if (cpu_is_omap1610() || cpu_is_omap5912() || cpu_is_omap1710()) {
+		omap_cfg_reg(W13_1610_USB1_SE0);
+		omap_cfg_reg(R13_1610_USB1_SPEED);
+		// SUSP
+	} else {
+		pr_debug("usb unrecognized\n");
+	}
+	if (nwires != 3)
+		omap_cfg_reg(USB1_RCV);
+
+	switch (nwires) {
+	case 3:
+		syscon1 = 2;
+		break;
+	case 4:
+		syscon1 = 1;
+		break;
+	case 6:
+		syscon1 = 3;
+		omap_cfg_reg(USB1_VP);
+		omap_cfg_reg(USB1_VM);
+		USB_TRANSCEIVER_CTRL_REG |= CONF_USB1_UNI_R;
+		break;
+	default:
+		printk(KERN_ERR "illegal usb%d %d-wire transceiver\n",
+			1, nwires);
+	}
+	return syscon1 << 20;
+}
+
+static u32 __init omap_usb2_init(unsigned nwires, unsigned alt_pingroup)
+{
+	u32	syscon1 = 0;
+
+	if (alt_pingroup)
+		return 0;
+	if (nwires != 6)
+		USB_TRANSCEIVER_CTRL_REG &= ~CONF_USB2_UNI_R;
+	if (nwires == 0)
+		return 0;
+
+	/* external transceiver */
+	if (cpu_is_omap1510()) {
+		omap_cfg_reg(USB2_TXD);
+		omap_cfg_reg(USB2_TXEN);
+		omap_cfg_reg(USB2_SEO);
+		if (nwires != 3)
+			omap_cfg_reg(USB2_RCV);
+	} else if (cpu_is_omap1610() || cpu_is_omap5912() || cpu_is_omap1710()) {
+		omap_cfg_reg(V6_USB2_TXD);
+		omap_cfg_reg(W9_USB2_TXEN);
+		omap_cfg_reg(W5_USB2_SE0);
+		if (nwires != 3)
+			omap_cfg_reg(Y5_USB2_RCV);
+	} else {
+		pr_debug("usb unrecognized\n");
+	}
+	// omap_cfg_reg(USB2_SUSP);
+	// FIXME omap_cfg_reg(USB2_SPEED);
+
+	switch (nwires) {
+	case 3:
+		syscon1 = 2;
+		break;
+	case 4:
+		syscon1 = 1;
+		break;
+	case 6:
+		syscon1 = 3;
+		if (cpu_is_omap1510()) {
+			omap_cfg_reg(USB2_VP);
+			omap_cfg_reg(USB2_VM);
+		} else {
+			omap_cfg_reg(AA9_USB2_VP);
+			omap_cfg_reg(R9_USB2_VM);
+		}
+		USB_TRANSCEIVER_CTRL_REG |= CONF_USB2_UNI_R;
+		break;
+	default:
+		printk(KERN_ERR "illegal usb%d %d-wire transceiver\n",
+			2, nwires);
+	}
+	return syscon1 << 24;
+}
+
+/*-------------------------------------------------------------------------*/
+
+#if	defined(CONFIG_USB_GADGET_OMAP) || \
+	defined(CONFIG_USB_OHCI_HCD) || defined(CONFIG_USB_OHCI_HCD_MODULE) || \
+	(defined(CONFIG_USB_OTG) && defined(CONFIG_ARCH_OMAP_OTG))
+static void usb_release(struct device *dev)
+{
+	/* normally not freed */
+}
+#endif
+
+#ifdef	CONFIG_USB_GADGET_OMAP
+
+static struct resource udc_resources[] = {
+	/* order is significant! */
+	{		/* registers */
+		.start		= IO_ADDRESS(UDC_BASE),
+		.end		= IO_ADDRESS(UDC_BASE + 0xff),
+		.flags		= IORESOURCE_MEM,
+	}, {		/* general IRQ */
+		.start		= IH2_BASE + 20,
+		.flags		= IORESOURCE_IRQ,
+	}, {		/* PIO IRQ */
+		.start		= IH2_BASE + 30,
+		.flags		= IORESOURCE_IRQ,
+	}, {		/* SOF IRQ */
+		.start		= IH2_BASE + 29,
+		.flags		= IORESOURCE_IRQ,
+	},
+};
+
+static u64 udc_dmamask = ~(u32)0;
+
+static struct platform_device udc_device = {
+	.name		= "omap_udc",
+	.id		= -1,
+	.dev = {
+		.release		= usb_release,
+		.dma_mask		= &udc_dmamask,
+		.coherent_dma_mask	= 0xffffffff,
+	},
+	.num_resources	= ARRAY_SIZE(udc_resources),
+	.resource	= udc_resources,
+};
+
+#endif
+
+#if	defined(CONFIG_USB_OHCI_HCD) || defined(CONFIG_USB_OHCI_HCD_MODULE)
+
+/* The dmamask must be set for OHCI to work */
+static u64 ohci_dmamask = ~(u32)0;
+
+static struct resource ohci_resources[] = {
+	{
+		.start	= IO_ADDRESS(OMAP_OHCI_BASE),
+		.end	= IO_ADDRESS(OMAP_OHCI_BASE + 4096),
+		.flags	= IORESOURCE_MEM,
+	},
+	{
+		.start	= INT_USB_HHC_1,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static struct platform_device ohci_device = {
+	.name			= "ohci",
+	.id			= -1,
+	.dev = {
+		.release		= usb_release,
+		.dma_mask		= &ohci_dmamask,
+		.coherent_dma_mask	= 0x0fffffff,
+	},
+	.num_resources	= ARRAY_SIZE(ohci_resources),
+	.resource		= ohci_resources,
+};
+
+#endif
+
+#if	defined(CONFIG_USB_OTG) && defined(CONFIG_ARCH_OMAP_OTG)
+
+static struct resource otg_resources[] = {
+	/* order is significant! */
+	{
+		.start		= IO_ADDRESS(OTG_BASE),
+		.end		= IO_ADDRESS(OTG_BASE + 0xff),
+		.flags		= IORESOURCE_MEM,
+	}, {
+		.start		= IH2_BASE + 8,
+		.flags		= IORESOURCE_IRQ,
+	},
+};
+
+static struct platform_device otg_device = {
+	.name		= "omap_otg",
+	.id		= -1,
+	.dev = {
+		.release		= usb_release,
+	},
+	.num_resources	= ARRAY_SIZE(otg_resources),
+	.resource	= otg_resources,
+};
+
+#endif
+
+/*-------------------------------------------------------------------------*/
+
+// FIXME correct answer depends on hmc_mode,
+// as does any nonzero value for config->otg port number
+#define	is_usb0_device(config)	0
+
+/*-------------------------------------------------------------------------*/
+
+#ifdef	CONFIG_ARCH_OMAP_OTG
+
+void __init
+omap_otg_init(struct omap_usb_config *config)
+{
+	u32		syscon = OTG_SYSCON_1_REG & 0xffff;
+	int		status;
+	int		alt_pingroup = 0;
+
+	/* NOTE:  no bus or clock setup (yet?) */
+
+	syscon = OTG_SYSCON_1_REG & 0xffff;
+	if (!(syscon & OTG_RESET_DONE))
+		pr_debug("USB resets not complete?\n");
+
+	// OTG_IRQ_EN_REG = 0;
+
+	/* pin muxing and transceiver pinouts */
+	if (config->pins[0] > 2)	/* alt pingroup 2 */
+		alt_pingroup = 1;
+	syscon |= omap_usb0_init(config->pins[0], is_usb0_device(config));
+	syscon |= omap_usb1_init(config->pins[1]);
+	syscon |= omap_usb2_init(config->pins[2], alt_pingroup);
+	pr_debug("OTG_SYSCON_1_REG = %08x\n", syscon);
+	OTG_SYSCON_1_REG = syscon;
+
+	syscon = config->hmc_mode;
+	syscon |= USBX_SYNCHRO | (4 << 16) /* B_ASE0_BRST */;
+	if (config->otg || config->register_host)
+		syscon |= UHOST_EN;
+#ifdef	CONFIG_USB_OTG
+	if (config->otg)
+		syscon |= OTG_EN;
+#endif
+	pr_debug("OTG_SYSCON_2_REG = %08x\n", syscon);
+	OTG_SYSCON_2_REG = syscon;
+
+	printk("USB: hmc %d", config->hmc_mode);
+	if (alt_pingroup)
+		printk(", usb2 alt %d wires", config->pins[2]);
+	else if (config->pins[0])
+		printk(", usb0 %d wires%s", config->pins[2],
+			is_usb0_device(config) ? " (dev)" : "");
+	if (config->pins[1])
+		printk(", usb1 %d wires", config->pins[1]);
+	if (!alt_pingroup && config->pins[2])
+		printk(", usb2 %d wires", config->pins[2]);
+	if (config->otg)
+		printk(", Mini-AB on usb%d", config->otg - 1);
+	printk("\n");
+
+	/* don't clock unused USB controllers  */
+	syscon = OTG_SYSCON_1_REG;
+	syscon |= HST_IDLE_EN|DEV_IDLE_EN|OTG_IDLE_EN;
+
+#ifdef	CONFIG_USB_GADGET_OMAP
+	if (config->otg || config->register_dev) {
+		syscon &= ~DEV_IDLE_EN;
+		udc_device.dev.platform_data = config;
+		status = platform_device_register(&udc_device);
+		if (status)
+			pr_debug("can't register UDC device, %d\n", status);
+	}
+#endif
+
+#if	defined(CONFIG_USB_OHCI_HCD) || defined(CONFIG_USB_OHCI_HCD_MODULE)
+	if (config->otg || config->register_host) {
+		syscon &= ~HST_IDLE_EN;
+		ohci_device.dev.platform_data = config;
+		status = platform_device_register(&ohci_device);
+		if (status)
+			pr_debug("can't register OHCI device, %d\n", status);
+	}
+#endif
+
+#ifdef	CONFIG_USB_OTG
+	if (config->otg) {
+		syscon &= ~OTG_IDLE_EN;
+		if (cpu_is_omap730())
+			otg_resources[1].start = INT_730_USB_OTG;
+		status = platform_device_register(&otg_device);
+		// ...
+	}
+#endif
+	pr_debug("OTG_SYSCON_1_REG = %08x\n", syscon);
+	OTG_SYSCON_1_REG = syscon;
+
+	status = 0;
+}
+
+#else
+static inline void omap_otg_init(struct omap_usb_config *config) {}
+#endif
+
+/*-------------------------------------------------------------------------*/
+
+#ifdef	CONFIG_ARCH_OMAP1510
+
+static void __init omap_1510_usb_init(struct omap_usb_config *config)
+{
+	int status;
+	unsigned int val;
+
+	omap_usb0_init(config->pins[0], is_usb0_device(config));
+	omap_usb1_init(config->pins[1]);
+	omap_usb2_init(config->pins[2], 0);
+
+	val = omap_readl(MOD_CONF_CTRL_0) & ~(0x3f << 1);
+	val |= (config->hmc_mode << 1);
+	omap_writel(val, MOD_CONF_CTRL_0);
+
+	// FIXME this has a UDC controller too
+
+#if	defined(CONFIG_USB_OHCI_HCD) || defined(CONFIG_USB_OHCI_HCD_MODULE)
+	if (config->otg || config->register_host) {
+		ohci_device.dev.platform_data = config;
+		status = platform_device_register(&ohci_device);
+		if (status)
+			pr_debug("can't register OHCI device, %d\n", status);
+	}
+	// FIXME completely untested ...
+#endif
+
+}
+
+#else
+static inline void omap_1510_usb_init(struct omap_usb_config *config) {}
+#endif
+
+/*-------------------------------------------------------------------------*/
+
+static struct omap_usb_config platform_data;
+
+static int __init
+omap_usb_init(void)
+{
+	const struct omap_usb_config *config;
+
+	config = omap_get_config(OMAP_TAG_USB, struct omap_usb_config);
+	if (config == NULL) {
+		printk(KERN_ERR "USB: No board-specific platform config found\n");
+		return -ENODEV;
+	}
+	platform_data = *config;
+
+	if (cpu_is_omap730()
+			|| cpu_is_omap1610()
+			|| cpu_is_omap1710()
+			|| cpu_is_omap5912())
+		omap_otg_init(&platform_data);
+	else if (cpu_is_omap1510())
+		omap_1510_usb_init(&platform_data);
+	else {
+		printk(KERN_ERR "USB: No init for your chip yet\n");
+		return -ENODEV;
+	}
+	return 0;
+}
+
+subsys_initcall(omap_usb_init);
diff -Nru a/arch/arm/mach-pxa/Kconfig b/arch/arm/mach-pxa/Kconfig
--- a/arch/arm/mach-pxa/Kconfig	2004-10-18 14:56:20 -07:00
+++ b/arch/arm/mach-pxa/Kconfig	2004-10-18 14:56:20 -07:00
@@ -12,7 +12,7 @@
 config MACH_MAINSTONE
 	bool "Intel HCDDBBVA0 Development Platform"
 	select PXA27x
-	#select IWMMXT
+	select IWMMXT
 
 config ARCH_PXA_IDP
 	bool "Accelent Xscale IDP"
@@ -31,5 +31,10 @@
 	bool
 	help
 	  Select code specific to PXA27x variants
+
+config IWMMXT
+	bool
+	help
+	  Enable support for iWMMXt
 
 endif
diff -Nru a/arch/arm/mach-pxa/dma.c b/arch/arm/mach-pxa/dma.c
--- a/arch/arm/mach-pxa/dma.c	2004-10-18 14:57:05 -07:00
+++ b/arch/arm/mach-pxa/dma.c	2004-10-18 14:57:05 -07:00
@@ -23,6 +23,7 @@
 #include <asm/hardware.h>
 #include <asm/dma.h>
 
+#include <asm/arch/pxa-regs.h>
 
 static struct dma_channel {
 	char *name;
diff -Nru a/arch/arm/mach-pxa/generic.c b/arch/arm/mach-pxa/generic.c
--- a/arch/arm/mach-pxa/generic.c	2004-10-18 14:56:27 -07:00
+++ b/arch/arm/mach-pxa/generic.c	2004-10-18 14:56:27 -07:00
@@ -30,8 +30,10 @@
 #include <asm/pgtable.h>
 #include <asm/mach/map.h>
 
+#include <asm/arch/pxa-regs.h>
 #include <asm/arch/udc.h>
 #include <asm/arch/pxafb.h>
+#include <asm/arch/mmc.h>
 
 #include "generic.h"
 
@@ -127,6 +129,12 @@
 	.num_resources	= ARRAY_SIZE(pxamci_resources),
 	.resource	= pxamci_resources,
 };
+
+void __init pxa_set_mci_info(struct pxamci_platform_data *info)
+{
+	pxamci_device.dev.platform_data = info;
+}
+EXPORT_SYMBOL(pxa_set_mci_info);
 
 
 static struct pxa2xx_udc_mach_info pxa_udc_info;
diff -Nru a/arch/arm/mach-pxa/idp.c b/arch/arm/mach-pxa/idp.c
--- a/arch/arm/mach-pxa/idp.c	2004-10-18 14:55:46 -07:00
+++ b/arch/arm/mach-pxa/idp.c	2004-10-18 14:55:46 -07:00
@@ -27,6 +27,7 @@
 #include <asm/mach/arch.h>
 #include <asm/mach/map.h>
 
+#include <asm/arch/pxa-regs.h>
 #include <asm/arch/idp.h>
 
 #include "generic.h"
@@ -100,7 +101,7 @@
 	pxa_map_io();
 	iotable_init(idp_io_desc, ARRAY_SIZE(idp_io_desc));
 
-	set_irq_type(IRQ_TO_GPIO_2_80(TOUCH_PANEL_IRQ), TOUCH_PANEL_IRQ_EDGE);
+	set_irq_type(TOUCH_PANEL_IRQ, TOUCH_PANEL_IRQ_EDGE);
 
 	// serial ports 2 & 3
 	pxa_gpio_mode(GPIO42_BTRXD_MD);
diff -Nru a/arch/arm/mach-pxa/irq.c b/arch/arm/mach-pxa/irq.c
--- a/arch/arm/mach-pxa/irq.c	2004-10-18 14:57:03 -07:00
+++ b/arch/arm/mach-pxa/irq.c	2004-10-18 14:57:03 -07:00
@@ -20,39 +20,64 @@
 #include <asm/hardware.h>
 #include <asm/irq.h>
 #include <asm/mach/irq.h>
+#include <asm/arch/pxa-regs.h>
 
 #include "generic.h"
 
 
 /*
- * This is for IRQs known as PXA_IRQ([8...31]).
+ * This is for peripheral IRQs internal to the PXA chip.
  */
 
-static void pxa_mask_irq(unsigned int irq)
+static void pxa_mask_low_irq(unsigned int irq)
 {
 	ICMR &= ~(1 << (irq + PXA_IRQ_SKIP));
 }
 
-static void pxa_unmask_irq(unsigned int irq)
+static void pxa_unmask_low_irq(unsigned int irq)
 {
 	ICMR |= (1 << (irq + PXA_IRQ_SKIP));
 }
 
-static struct irqchip pxa_internal_chip = {
-	.ack		= pxa_mask_irq,
-	.mask		= pxa_mask_irq,
-	.unmask		= pxa_unmask_irq,
+static struct irqchip pxa_internal_chip_low = {
+	.ack		= pxa_mask_low_irq,
+	.mask		= pxa_mask_low_irq,
+	.unmask		= pxa_unmask_low_irq,
 };
 
+#if PXA_INTERNAL_IRQS > 32
+
+/*
+ * This is for the second set of internal IRQs as found on the PXA27x.
+ */
+
+static void pxa_mask_high_irq(unsigned int irq)
+{
+	ICMR2 &= ~(1 << (irq - 32 + PXA_IRQ_SKIP));
+}
+
+static void pxa_unmask_high_irq(unsigned int irq)
+{
+	ICMR2 |= (1 << (irq - 32 + PXA_IRQ_SKIP));
+}
+
+static struct irqchip pxa_internal_chip_high = {
+	.ack		= pxa_mask_high_irq,
+	.mask		= pxa_mask_high_irq,
+	.unmask		= pxa_unmask_high_irq,
+};
+
+#endif
+
 /*
  * PXA GPIO edge detection for IRQs:
  * IRQs are generated on Falling-Edge, Rising-Edge, or both.
  * Use this instead of directly setting GRER/GFER.
  */
 
-static long GPIO_IRQ_rising_edge[3];
-static long GPIO_IRQ_falling_edge[3];
-static long GPIO_IRQ_mask[3];
+static long GPIO_IRQ_rising_edge[4];
+static long GPIO_IRQ_falling_edge[4];
+static long GPIO_IRQ_mask[4];
 
 static int pxa_gpio_irq_type(unsigned int irq, unsigned int type)
 {
@@ -106,13 +131,13 @@
 
 static struct irqchip pxa_low_gpio_chip = {
 	.ack		= pxa_ack_low_gpio,
-	.mask		= pxa_mask_irq,
-	.unmask		= pxa_unmask_irq,
+	.mask		= pxa_mask_low_irq,
+	.unmask		= pxa_unmask_low_irq,
 	.type		= pxa_gpio_irq_type,
 };
 
 /*
- * Demux handler for GPIO 2-80 edge detect interrupts
+ * Demux handler for GPIO>=2 edge detect interrupts
  */
 
 static void pxa_gpio_demux_handler(unsigned int irq, struct irqdesc *desc,
@@ -169,6 +194,23 @@
 			} while (mask);
 			loop = 1;
 		}
+
+#if PXA_LAST_GPIO >= 96
+		mask = GEDR3;
+		if (mask) {
+			GEDR3 = mask;
+			irq = IRQ_GPIO(96);
+			desc = irq_desc + irq;
+			do {
+				if (mask & 1)
+					desc->handle(irq, desc, regs);
+				irq++;
+				desc++;
+				mask >>= 1;
+			} while (mask);
+			loop = 1;
+		}
+#endif
 	} while (loop);
 }
 
@@ -214,12 +256,25 @@
 	ICLR = 0;
 
 	/* clear all GPIO edge detects */
-	GFER0 = GFER1 = GFER2 = 0;
-	GRER0 = GRER1 = GRER2 = 0;
+	GFER0 = 0;
+	GFER1 = 0;
+	GFER2 = 0;
+	GRER0 = 0;
+	GRER1 = 0;
+	GRER2 = 0;
 	GEDR0 = GEDR0;
 	GEDR1 = GEDR1;
 	GEDR2 = GEDR2;
 
+#ifdef CONFIG_PXA27x
+	/* And similarly for the extra regs on the PXA27x */
+	ICMR2 = 0;
+	ICLR2 = 0;
+	GFER3 = 0;
+	GRER3 = 0;
+	GEDR3 = GEDR3;
+#endif
+
 	/* only unmasked interrupts kick us out of idle */
 	ICCR = 1;
 
@@ -227,10 +282,18 @@
 	GPIO_IRQ_mask[0] = 3;
 
 	for (irq = PXA_IRQ(PXA_IRQ_SKIP); irq <= PXA_IRQ(31); irq++) {
-		set_irq_chip(irq, &pxa_internal_chip);
+		set_irq_chip(irq, &pxa_internal_chip_low);
+		set_irq_handler(irq, do_level_IRQ);
+		set_irq_flags(irq, IRQF_VALID);
+	}
+
+#if PXA_INTERNAL_IRQS > 32
+	for (irq = PXA_IRQ(32); irq < PXA_IRQ(PXA_INTERNAL_IRQS); irq++) {
+		set_irq_chip(irq, &pxa_internal_chip_high);
 		set_irq_handler(irq, do_level_IRQ);
 		set_irq_flags(irq, IRQF_VALID);
 	}
+#endif
 
 	for (irq = IRQ_GPIO0; irq <= IRQ_GPIO1; irq++) {
 		set_irq_chip(irq, &pxa_low_gpio_chip);
@@ -238,13 +301,13 @@
 		set_irq_flags(irq, IRQF_VALID | IRQF_PROBE);
 	}
 
-	for (irq = IRQ_GPIO(2); irq <= IRQ_GPIO(80); irq++) {
+	for (irq = IRQ_GPIO(2); irq <= IRQ_GPIO(PXA_LAST_GPIO); irq++) {
 		set_irq_chip(irq, &pxa_muxed_gpio_chip);
 		set_irq_handler(irq, do_edge_IRQ);
 		set_irq_flags(irq, IRQF_VALID | IRQF_PROBE);
 	}
 
-	/* Install handler for GPIO 2-80 edge detect interrupts */
-	set_irq_chip(IRQ_GPIO_2_80, &pxa_internal_chip);
-	set_irq_chained_handler(IRQ_GPIO_2_80, pxa_gpio_demux_handler);
+	/* Install handler for GPIO>=2 edge detect interrupts */
+	set_irq_chip(IRQ_GPIO_2_x, &pxa_internal_chip_low);
+	set_irq_chained_handler(IRQ_GPIO_2_x, pxa_gpio_demux_handler);
 }
diff -Nru a/arch/arm/mach-pxa/leds-lubbock.c b/arch/arm/mach-pxa/leds-lubbock.c
--- a/arch/arm/mach-pxa/leds-lubbock.c	2004-10-18 14:55:54 -07:00
+++ b/arch/arm/mach-pxa/leds-lubbock.c	2004-10-18 14:55:54 -07:00
@@ -17,6 +17,7 @@
 #include <asm/hardware.h>
 #include <asm/leds.h>
 #include <asm/system.h>
+#include <asm/arch/pxa-regs.h>
 #include <asm/arch/lubbock.h>
 
 #include "leds.h"
diff -Nru a/arch/arm/mach-pxa/leds-mainstone.c b/arch/arm/mach-pxa/leds-mainstone.c
--- a/arch/arm/mach-pxa/leds-mainstone.c	2004-10-18 14:55:53 -07:00
+++ b/arch/arm/mach-pxa/leds-mainstone.c	2004-10-18 14:55:53 -07:00
@@ -17,6 +17,7 @@
 #include <asm/leds.h>
 #include <asm/system.h>
 
+#include <asm/arch/pxa-regs.h>
 #include <asm/arch/mainstone.h>
 
 #include "leds.h"
diff -Nru a/arch/arm/mach-pxa/lubbock.c b/arch/arm/mach-pxa/lubbock.c
--- a/arch/arm/mach-pxa/lubbock.c	2004-10-18 14:56:28 -07:00
+++ b/arch/arm/mach-pxa/lubbock.c	2004-10-18 14:56:28 -07:00
@@ -29,6 +29,7 @@
 #include <asm/mach/map.h>
 #include <asm/mach/irq.h>
 
+#include <asm/arch/pxa-regs.h>
 #include <asm/arch/lubbock.h>
 #include <asm/arch/udc.h>
 #include <asm/arch/pxafb.h>
diff -Nru a/arch/arm/mach-pxa/mainstone.c b/arch/arm/mach-pxa/mainstone.c
--- a/arch/arm/mach-pxa/mainstone.c	2004-10-18 14:57:04 -07:00
+++ b/arch/arm/mach-pxa/mainstone.c	2004-10-18 14:57:04 -07:00
@@ -31,6 +31,7 @@
 #include <asm/mach/map.h>
 #include <asm/mach/irq.h>
 
+#include <asm/arch/pxa-regs.h>
 #include <asm/arch/mainstone.h>
 #include <asm/arch/pxafb.h>
 
diff -Nru a/arch/arm/mach-pxa/pm.c b/arch/arm/mach-pxa/pm.c
--- a/arch/arm/mach-pxa/pm.c	2004-10-18 14:56:33 -07:00
+++ b/arch/arm/mach-pxa/pm.c	2004-10-18 14:56:33 -07:00
@@ -19,7 +19,9 @@
 #include <asm/hardware.h>
 #include <asm/memory.h>
 #include <asm/system.h>
+#include <asm/arch/pxa-regs.h>
 #include <asm/arch/lubbock.h>
+#include <asm/mach/time.h>
 
 
 /*
@@ -45,7 +47,7 @@
  */
 enum {	SLEEP_SAVE_START = 0,
 
-	SLEEP_SAVE_OSCR, SLEEP_SAVE_OIER,
+	SLEEP_SAVE_OIER,
 	SLEEP_SAVE_OSMR0, SLEEP_SAVE_OSMR1, SLEEP_SAVE_OSMR2, SLEEP_SAVE_OSMR3,
 
 	SLEEP_SAVE_GPLR0, SLEEP_SAVE_GPLR1, SLEEP_SAVE_GPLR2,
@@ -68,17 +70,18 @@
 {
 	unsigned long sleep_save[SLEEP_SAVE_SIZE];
 	unsigned long checksum = 0;
-	unsigned long delta;
+	struct timespec delta, rtc;
 	int i;
 
 	if (state != PM_SUSPEND_MEM)
 		return -EINVAL;
 
 	/* preserve current time */
-	delta = xtime.tv_sec - RCNR;
+	rtc.tv_sec = RCNR;
+	rtc.tv_nsec = 0;
+	save_time_delta(&delta, &rtc);
 
 	/* save vital registers */
-	SAVE(OSCR);
 	SAVE(OSMR0);
 	SAVE(OSMR1);
 	SAVE(OSMR2);
@@ -149,9 +152,11 @@
 	RESTORE(OSMR1);
 	RESTORE(OSMR2);
 	RESTORE(OSMR3);
-	RESTORE(OSCR);
 	RESTORE(OIER);
 
+	/* OSMR0 is the system timer: make sure OSCR is sufficiently behind */
+	OSCR = OSMR0 - LATCH;
+
 	RESTORE(CKEN);
 
 	ICLR = 0;
@@ -159,7 +164,8 @@
 	RESTORE(ICMR);
 
 	/* restore current time */
-	xtime.tv_sec = RCNR + delta;
+	rtc.tv_sec = RCNR;
+	restore_time_delta(&delta, &rtc);
 
 #ifdef DEBUG
 	printk(KERN_DEBUG "*** made it back from resume\n");
diff -Nru a/arch/arm/mach-pxa/pxa25x.c b/arch/arm/mach-pxa/pxa25x.c
--- a/arch/arm/mach-pxa/pxa25x.c	2004-10-18 14:57:19 -07:00
+++ b/arch/arm/mach-pxa/pxa25x.c	2004-10-18 14:57:19 -07:00
@@ -22,6 +22,7 @@
 #include <linux/pm.h>
 
 #include <asm/hardware.h>
+#include <asm/arch/pxa-regs.h>
 
 #include "generic.h"
 
diff -Nru a/arch/arm/mach-pxa/pxa27x.c b/arch/arm/mach-pxa/pxa27x.c
--- a/arch/arm/mach-pxa/pxa27x.c	2004-10-18 14:56:32 -07:00
+++ b/arch/arm/mach-pxa/pxa27x.c	2004-10-18 14:56:32 -07:00
@@ -14,6 +14,7 @@
 #include <linux/config.h>
 #include <linux/module.h>
 #include <linux/kernel.h>
+#include <asm/arch/pxa-regs.h>
 #include <linux/init.h>
 #include <linux/pm.h>
 
diff -Nru a/arch/arm/mach-pxa/sleep.S b/arch/arm/mach-pxa/sleep.S
--- a/arch/arm/mach-pxa/sleep.S	2004-10-18 14:57:03 -07:00
+++ b/arch/arm/mach-pxa/sleep.S	2004-10-18 14:57:03 -07:00
@@ -16,6 +16,8 @@
 #include <asm/assembler.h>
 #include <asm/hardware.h>
 
+#include <asm/arch/pxa-regs.h>
+
 		.text
 
 /*
@@ -64,6 +66,37 @@
 	@ prepare pointer to physical address 0 (virtual mapping in generic.c)
 	mov	r2, #UNCACHED_PHYS_0
 
+	@ Intel PXA255 Specification Update notes problems
+	@ about suspending with PXBus operating above 133MHz
+	@ (see Errata 31, GPIO output signals, ... unpredictable in sleep
+	@
+	@ We keep the change-down close to the actual suspend on SDRAM
+	@ as possible to eliminate messing about with the refresh clock
+	@ as the system will restore with the original speed settings
+	@
+	@ Ben Dooks, 13-Sep-2004
+
+	ldr	r6, =CCCR
+	ldr	r8, [r6]		@ keep original value for resume
+
+	@ ensure x1 for run and turbo mode with memory clock
+	bic	r7, r8, #CCCR_M_MASK | CCCR_N_MASK
+	orr	r7, r7, #(1<<5) | (2<<7)
+
+	@ check that the memory frequency is within limits
+	and	r14, r7, #CCCR_L_MASK
+	teq	r14, #1
+	bicne	r7, r7, #CCCR_L_MASK
+	orrne	r7, r7, #1			@@ 99.53MHz
+
+	@ get ready for the change
+	@ note, since we are making turbo=run, do not remove the turbo
+	@ as this may cause non-turbo mode on resume
+	mrc	p14, 0, r0, c6, c0, 0
+	bic	r0, r0, #2			@ clear change bit
+	mcr	p14, 0, r0, c6, c0, 0
+	orr	r0, r0, #2			@ initiate change bit
+
 	@ align execution to a cache line
 	b	1f
 
@@ -74,6 +107,13 @@
 	@ All needed values are now in registers.
 	@ These last instructions should be in cache
 
+	@ initiate the frequency change...
+	str	r7, [r6]
+	mcr	p14, 0, r0, c6, c0, 0
+
+	@ restore the original cpu speed value for resume
+	str	r8, [r6]
+
 	@ put SDRAM into self-refresh
 	str	r5, [r4]
 
@@ -83,8 +123,7 @@
 	@ enter sleep mode
 	mcr	p14, 0, r1, c7, c0, 0
 
-20:	nop
-	b	20b				@ loop waiting for sleep
+20:	b	20b				@ loop waiting for sleep
 
 /*
  * cpu_pxa_resume()
diff -Nru a/arch/arm/mach-pxa/time.c b/arch/arm/mach-pxa/time.c
--- a/arch/arm/mach-pxa/time.c	2004-10-18 14:56:29 -07:00
+++ b/arch/arm/mach-pxa/time.c	2004-10-18 14:56:29 -07:00
@@ -27,6 +27,7 @@
 #include <asm/irq.h>
 #include <asm/mach/irq.h>
 #include <asm/mach/time.h>
+#include <asm/arch/pxa-regs.h>
 
 
 static inline unsigned long pxa_get_rtc_time(void)
diff -Nru a/arch/arm/mach-s3c2410/Kconfig b/arch/arm/mach-s3c2410/Kconfig
--- a/arch/arm/mach-s3c2410/Kconfig	2004-10-18 14:56:29 -07:00
+++ b/arch/arm/mach-s3c2410/Kconfig	2004-10-18 14:56:29 -07:00
@@ -1,9 +1,10 @@
 if ARCH_S3C2410
 
-menu "S3C2410 Implementations"
+menu "S3C24XX Implementations"
 
 config ARCH_BAST
 	bool "Simtec Electronics BAST (EB2410ITX)"
+	select CPU_S3C2410
 	help
 	  Say Y here if you are using the Simtec Electronics EB2410ITX
 	  development board (also known as BAST)
@@ -12,18 +13,22 @@
 
 config ARCH_H1940
 	bool "IPAQ H1940"
+	select CPU_S3C2410
 	help
 	  Say Y here if you are using the HP IPAQ H1940
+
 	  <http://www.handhelds.org/projects/h1940.html>.
 
 config ARCH_SMDK2410
 	bool "SMDK2410/A9M2410"
+	select CPU_S3C2410
 	help
 	   Say Y here if you are using the SMDK2410 or the derived module A9M2410
            <http://www.fsforth.de>
 
 config MACH_VR1000
 	bool "Thorcom VR1000"
+	select CPU_S3C2410
 	help
 	  Say Y here if you are using the Thorcom VR1000 board.
 
@@ -31,5 +36,40 @@
 	  of Thorcom. Any queries, please contact Thorcom first.
 
 endmenu
+
+config CPU_S3C2410
+	bool
+	depends on ARCH_S3C2410
+	help
+	  Support for S3C2410 and S3C2410A family from the S3C24XX line
+	  of Samsung Mobile CPUs.
+
+config CPU_S3C2440
+	bool
+	depends on ARCH_S3C2410
+	help
+	  Support for S3C2440 Samsung Mobile CPU based systems.
+
+comment "S3C2410 Setup"
+
+config S3C2410_DMA
+	bool "S3C2410 DMA support"
+	depends on ARCH_S3C2410
+	help
+	  S3C2410 DMA support. This is needed for drivers like sound which
+	  use the S3C2410's DMA system to move data to and from the
+	  peripheral blocks.
+
+config S3C2410_DMA_DEBUG
+	bool "S3C2410 DMA support debug"
+	depends on ARCH_S3C2410 && S3C2410_DMA
+	help
+	  Enable debugging output for the DMA code. This option sends info
+	  to the kernel log, at priority KERN_DEBUG.
+
+	  Note, it is easy to create and fill the log buffer in a small
+	  amount of time, as well as using an significant percantage of
+	  the CPU time doing so.
+
 
 endif
diff -Nru a/arch/arm/mach-s3c2410/Makefile b/arch/arm/mach-s3c2410/Makefile
--- a/arch/arm/mach-s3c2410/Makefile	2004-10-18 14:56:17 -07:00
+++ b/arch/arm/mach-s3c2410/Makefile	2004-10-18 14:56:17 -07:00
@@ -1,19 +1,28 @@
+
 #
 # Makefile for the linux kernel.
 #
 
 # Object file lists.
 
-obj-y			:= s3c2410.o irq.o time.o gpio.o
+obj-y			:= cpu.o irq.o time.o gpio.o clock.o devs.o
 obj-m			:=
 obj-n			:=
 obj-			:=
 
-obj-$(CONFIG_ARCH_BAST)    += mach-bast.o
-obj-$(CONFIG_MACH_H1940)   += mach-h1940.o
-obj-$(CONFIG_ARCH_H1940)   += mach-h1940.o
-obj-$(CONFIG_ARCH_SMDK2410) += mach-smdk2410.o
-obj-$(CONFIG_MACH_VR1000)  += mach-vr1000.o
+# S3C2410 support files
+
+obj-$(CONFIG_CPU_S3C2410)  += s3c2410.o
+obj-$(CONFIG_S3C2410_DMA)  += dma.o
+
+# S3C2440 support
+
+obj-$(CONFIG_CPU_S3C2440)  += s3c2440.o s3c2440-dsc.o
+
+# machine specific support
+
+obj-$(CONFIG_ARCH_BAST)		+= mach-bast.o usb-simtec.o
+obj-$(CONFIG_ARCH_H1940)	+= mach-h1940.o
+obj-$(CONFIG_ARCH_SMDK2410)	+= mach-smdk2410.o
+obj-$(CONFIG_MACH_VR1000)	+= mach-vr1000.o usb-simtec.o
 
-#obj-$(CONFIG_PCI)	+=$(pci-y)
-#obj-$(CONFIG_LEDS)	+=$(leds-y)
diff -Nru a/arch/arm/mach-s3c2410/clock.c b/arch/arm/mach-s3c2410/clock.c
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/arch/arm/mach-s3c2410/clock.c	2004-10-18 14:57:21 -07:00
@@ -0,0 +1,310 @@
+/* linux/arch/arm/mach-s3c2410/clock.c
+ *
+ * Copyright (c) 2004 Simtec Electronics
+ * Ben Dooks <ben@simtec.co.uk>
+ *
+ * S3C2410 Clock control support
+ *
+ * Based on, and code from linux/arch/arm/mach-versatile/clock.c
+ **
+ **  Copyright (C) 2004 ARM Limited.
+ **  Written by Deep Blue Solutions Limited.
+ *
+ *
+ * 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
+*/
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/list.h>
+#include <linux/errno.h>
+#include <linux/err.h>
+
+#include <linux/interrupt.h>
+#include <linux/ioport.h>
+
+#include <asm/hardware.h>
+#include <asm/atomic.h>
+#include <asm/irq.h>
+#include <asm/io.h>
+
+#include <asm/hardware/clock.h>
+#include <asm/arch/regs-clock.h>
+
+#include "clock.h"
+
+
+static LIST_HEAD(clocks);
+static DECLARE_MUTEX(clocks_sem);
+
+
+/* old functions */
+
+void s3c2410_clk_enable(unsigned int clocks, unsigned int enable)
+{
+	unsigned long clkcon;
+	unsigned long flags;
+
+	local_irq_save(flags);
+
+	clkcon = __raw_readl(S3C2410_CLKCON);
+	clkcon &= ~clocks;
+
+	if (enable)
+		clkcon |= clocks;
+
+	__raw_writel(clkcon, S3C2410_CLKCON);
+
+	local_irq_restore(flags);
+}
+
+
+/* Clock API calls */
+
+struct clk *clk_get(struct device *dev, const char *id)
+{
+	struct clk *p;
+	struct clk *clk = ERR_PTR(-ENOENT);
+
+	down(&clocks_sem);
+	list_for_each_entry(p, &clocks, list) {
+		if (strcmp(id, p->name) == 0 &&
+		    try_module_get(p->owner)) {
+			clk = p;
+			break;
+		}
+	}
+	up(&clocks_sem);
+
+	return clk;
+}
+
+void clk_put(struct clk *clk)
+{
+	module_put(clk->owner);
+}
+
+int clk_enable(struct clk *clk)
+{
+	if (clk->ctrlbit != 0)
+		s3c2410_clk_enable(clk->ctrlbit, 1);
+
+	return 0;
+}
+
+void clk_disable(struct clk *clk)
+{
+	s3c2410_clk_enable(clk->ctrlbit, 0);
+}
+
+
+int clk_use(struct clk *clk)
+{
+	atomic_inc(&clk->used);
+	return 0;
+}
+
+
+void clk_unuse(struct clk *clk)
+{
+	atomic_dec(&clk->used);
+}
+
+unsigned long clk_get_rate(struct clk *clk)
+{
+	if (clk->parent != NULL)
+		return clk->parent->rate;
+
+	return clk->rate;
+}
+
+long clk_round_rate(struct clk *clk, unsigned long rate)
+{
+	return rate;
+}
+
+int clk_set_rate(struct clk *clk, unsigned long rate)
+{
+	return -EINVAL;
+}
+
+struct clk *clk_get_parent(struct clk *clk)
+{
+	return clk->parent;
+}
+
+EXPORT_SYMBOL(clk_get);
+EXPORT_SYMBOL(clk_put);
+EXPORT_SYMBOL(clk_enable);
+EXPORT_SYMBOL(clk_disable);
+EXPORT_SYMBOL(clk_use);
+EXPORT_SYMBOL(clk_unuse);
+EXPORT_SYMBOL(clk_get_rate);
+EXPORT_SYMBOL(clk_round_rate);
+EXPORT_SYMBOL(clk_set_rate);
+EXPORT_SYMBOL(clk_get_parent);
+
+/* base clocks */
+
+static struct clk clk_f = {
+	.name          = "fclk",
+	.rate          = 0,
+	.parent        = NULL,
+	.ctrlbit       = 0
+};
+
+static struct clk clk_h = {
+	.name          = "hclk",
+	.rate          = 0,
+	.parent        = NULL,
+	.ctrlbit       = 0
+};
+
+static struct clk clk_p = {
+	.name          = "pclk",
+	.rate          = 0,
+	.parent        = NULL,
+	.ctrlbit       = 0
+};
+
+/* clock definitions */
+
+static struct clk init_clocks[] = {
+	{ .name    = "nand",
+	  .parent  = &clk_h,
+	  .ctrlbit = S3C2410_CLKCON_NAND
+	},
+	{ .name    = "lcd",
+	  .parent  = &clk_h,
+	  .ctrlbit = S3C2410_CLKCON_LCDC
+	},
+	{ .name    = "usb-host",
+	  .parent  = &clk_h,
+	  .ctrlbit =   S3C2410_CLKCON_USBH
+	},
+	{ .name    = "usb-device",
+	  .parent  = &clk_h,
+	  .ctrlbit = S3C2410_CLKCON_USBD
+	},
+	{ .name    = "timers",
+	  .parent  = &clk_p,
+	  .ctrlbit = S3C2410_CLKCON_PWMT
+	},
+	{ .name    = "sdi",
+	  .parent  = &clk_p,
+	  .ctrlbit = S3C2410_CLKCON_SDI
+	},
+	{ .name    = "uart0",
+	  .parent  = &clk_p,
+	  .ctrlbit = S3C2410_CLKCON_UART0
+	},
+	{ .name    = "uart1",
+	  .parent  = &clk_p,
+	  .ctrlbit = S3C2410_CLKCON_UART1
+	},
+	{ .name    = "uart2",
+	  .parent  = &clk_p,
+	  .ctrlbit = S3C2410_CLKCON_UART2
+	},
+	{ .name    = "gpio",
+	  .parent  = &clk_p,
+	  .ctrlbit = S3C2410_CLKCON_GPIO
+	},
+	{ .name    = "rtc",
+	  .parent  = &clk_p,
+	  .ctrlbit = S3C2410_CLKCON_RTC
+	},
+	{ .name    = "adc",
+	  .parent  = &clk_p,
+	  .ctrlbit = S3C2410_CLKCON_ADC
+	},
+	{ .name    = "i2c",
+	  .parent  = &clk_p,
+	  .ctrlbit = S3C2410_CLKCON_IIC
+	},
+	{ .name    = "iis",
+	  .parent  = &clk_p,
+	  .ctrlbit = S3C2410_CLKCON_IIS
+	},
+	{ .name    = "spi",
+	  .parent  = &clk_p,
+	  .ctrlbit = S3C2410_CLKCON_SPI
+	},
+	{ .name    = "watchdog",
+	  .parent  = &clk_p,
+	  .ctrlbit = 0
+	}
+};
+
+/* initialise the clock system */
+
+int s3c2410_register_clock(struct clk *clk)
+{
+	clk->owner = THIS_MODULE;
+	atomic_set(&clk->used, 0);
+
+	/* add to the list of available clocks */
+
+	down(&clocks_sem);
+	list_add(&clk->list, &clocks);
+	up(&clocks_sem);
+
+	return 0;
+}
+
+/* initalise all the clocks */
+
+static int __init s3c2410_init_clocks(void)
+{
+	struct clk *clkp = init_clocks;
+	int ptr;
+	int ret;
+
+	printk(KERN_INFO "S3C2410 Clock control, (c) 2004 Simtec Electronics\n");
+
+	/* initialise the main system clocks */
+
+	clk_h.rate = s3c2410_hclk;
+	clk_p.rate = s3c2410_pclk;
+	clk_f.rate = s3c2410_fclk;
+
+	/* set the enabled clocks to a minimal (known) state */
+	__raw_writel(S3C2410_CLKCON_PWMT | S3C2410_CLKCON_UART0 | S3C2410_CLKCON_UART1 | S3C2410_CLKCON_UART2 | S3C2410_CLKCON_GPIO | S3C2410_CLKCON_RTC, S3C2410_CLKCON);
+
+	/* register our clocks */
+
+	if (s3c2410_register_clock(&clk_f) < 0)
+		printk(KERN_ERR "failed to register cpu fclk\n");
+
+	if (s3c2410_register_clock(&clk_h) < 0)
+		printk(KERN_ERR "failed to register cpu hclk\n");
+
+	if (s3c2410_register_clock(&clk_p) < 0)
+		printk(KERN_ERR "failed to register cpu pclk\n");
+
+	for (ptr = 0; ptr < ARRAY_SIZE(init_clocks); ptr++, clkp++) {
+		ret = s3c2410_register_clock(clkp);
+		if (ret < 0) {
+			printk(KERN_ERR "Failed to register clock %s (%d)\n",
+			       clkp->name, ret);
+		}
+	}
+
+	return 0;
+}
+
+arch_initcall(s3c2410_init_clocks);
+
diff -Nru a/arch/arm/mach-s3c2410/clock.h b/arch/arm/mach-s3c2410/clock.h
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/arch/arm/mach-s3c2410/clock.h	2004-10-18 14:57:23 -07:00
@@ -0,0 +1,20 @@
+/*
+ * linux/arch/arm/mach-s3c2410/clock.h
+ *
+ * Copyright (c) 2004 Simtec Electronics
+ * Written by Ben Dooks, <ben@simtec.co.uk>
+ *
+ * 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.
+*/
+
+struct clk {
+	struct list_head      list;
+	struct module        *owner;
+	struct clk           *parent;
+	const char           *name;
+	atomic_t              used;
+	unsigned long         rate;
+	unsigned long         ctrlbit;
+};
diff -Nru a/arch/arm/mach-s3c2410/cpu.c b/arch/arm/mach-s3c2410/cpu.c
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/arch/arm/mach-s3c2410/cpu.c	2004-10-18 14:57:23 -07:00
@@ -0,0 +1,152 @@
+/* linux/arch/arm/mach-s3c2410/cpu.c
+ *
+ * Copyright (c) 2004 Simtec Electronics
+ * Ben Dooks <ben@simtec.co.uk>
+ *
+ * S3C24XX CPU Support
+ *
+ * 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
+*/
+
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/interrupt.h>
+#include <linux/ioport.h>
+#include <linux/device.h>
+
+#include <asm/hardware.h>
+#include <asm/irq.h>
+#include <asm/io.h>
+#include <asm/delay.h>
+
+#include <asm/mach/arch.h>
+#include <asm/mach/map.h>
+
+#include <asm/arch/regs-gpio.h>
+
+#include "cpu.h"
+#include "s3c2410.h"
+#include "s3c2440.h"
+
+struct cpu_table {
+	unsigned long	idcode;
+	unsigned long	idmask;
+	void		(*map_io)(struct map_desc *mach_desc, int size);
+	int		(*init)(void);
+	const char	*name;
+};
+
+/* table of supported CPUs */
+
+static const char name_s3c2410[]  = "S3C2410";
+static const char name_s3c2440[]  = "S3C2440";
+static const char name_s3c2410a[] = "S3C2410A";
+static const char name_s3c2440a[] = "S3C2440A";
+
+static struct cpu_table cpu_ids[] __initdata = {
+	{
+		.idcode	= 0x32410000,
+		.idmask = 0xffffffff,
+		.map_io = s3c2410_map_io,
+		.init   = s3c2410_init,
+		.name   = name_s3c2410
+	},
+	{
+		.idcode	= 0x3241002,
+		.idmask = 0xffffffff,
+		.map_io = s3c2410_map_io,
+		.init   = s3c2410_init,
+		.name   = name_s3c2410a
+	},
+	{
+		.idcode	= 0x32440000,
+		.idmask = 0xffffffff,
+		.map_io = s3c2440_map_io,
+		.init   = s3c2440_init,
+		.name   = name_s3c2440
+	},
+	{
+		.idcode	= 0x32440001,
+		.idmask = 0xffffffff,
+		.map_io = s3c2440_map_io,
+		.init   = s3c2440_init,
+		.name   = name_s3c2440a
+	}
+};
+
+/* minimal IO mapping */
+
+static struct map_desc s3c_iodesc[] __initdata = {
+	IODESC_ENT(GPIO),
+	IODESC_ENT(IRQ),
+	IODESC_ENT(MEMCTRL),
+	IODESC_ENT(UART)
+};
+
+
+static struct cpu_table *
+s3c_lookup_cpu(unsigned long idcode)
+{
+	struct cpu_table *tab;
+	int count;
+
+	tab = cpu_ids;
+	for (count = 0; count < ARRAY_SIZE(cpu_ids); count++) {
+		if ((idcode & tab->idmask) == tab->idcode)
+			return tab;
+	}
+
+	return NULL;
+}
+
+static struct cpu_table *cpu;
+
+void __init s3c24xx_init_io(struct map_desc *mach_desc, int size)
+{
+	unsigned long idcode;
+
+	/* initialise the io descriptors we need for initialisation */
+	iotable_init(s3c_iodesc, ARRAY_SIZE(s3c_iodesc));
+
+	idcode = __raw_readl(S3C2410_GSTATUS1);
+	cpu = s3c_lookup_cpu(idcode);
+
+	if (cpu == NULL) {
+		printk(KERN_ERR "Unknown CPU type 0x%08lx\n", idcode);
+		panic("Unknown S3C24XX CPU");
+	}
+
+	if (cpu->map_io == NULL || cpu->init == NULL) {
+		printk(KERN_ERR "CPU %s support not enabled\n", cpu->name);
+		panic("Unsupported S3C24XX CPU");
+	}
+
+	printk("CPU %s (id 0x%08lx)\n", cpu->name, idcode);
+
+	(cpu->map_io)(mach_desc, size);
+}
+
+static int __init s3c_arch_init(void)
+{
+	// do the correct init for cpu
+
+	if (cpu == NULL)
+		panic("s3c_arch_init: NULL cpu\n");
+
+	return (cpu->init)();
+}
+
+arch_initcall(s3c_arch_init);
diff -Nru a/arch/arm/mach-s3c2410/cpu.h b/arch/arm/mach-s3c2410/cpu.h
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/arch/arm/mach-s3c2410/cpu.h	2004-10-18 14:57:21 -07:00
@@ -0,0 +1,41 @@
+/* arch/arm/mach-s3c2410/cpu.h
+ *
+ * Copyright (c) 2004 Simtec Electronics
+ * Ben Dooks <ben@simtec.co.uk>
+ *
+ * Header file for S3C24XX CPU support
+ *
+ * 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.
+ *
+ * Modifications:
+ *     24-Aug-2004 BJD  Start of generic S3C24XX support
+*/
+
+#define IODESC_ENT(x) { S3C2410_VA_##x, S3C2410_PA_##x, S3C2410_SZ_##x, MT_DEVICE }
+
+#ifndef MHZ
+#define MHZ (1000*1000)
+#endif
+
+#define print_mhz(m) ((m) / MHZ), ((m / 1000) % 1000)
+
+#ifdef CONFIG_CPU_S3C2410
+extern  int s3c2410_init(void);
+extern void s3c2410_map_io(struct map_desc *mach_desc, int size);
+#else
+#define s3c2410_map_io NULL
+#define s3c2410_init NULL
+#endif
+
+#ifdef CONFIG_CPU_S3C2440
+extern  int s3c2440_init(void);
+extern void s3c2440_map_io(struct map_desc *mach_desc, int size);
+#else
+#define s3c2440_map_io NULL
+#define s3c2440_init NULL
+#endif
+
+extern void s3c24xx_init_io(struct map_desc *mach_desc, int size);
+
diff -Nru a/arch/arm/mach-s3c2410/devs.c b/arch/arm/mach-s3c2410/devs.c
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/arch/arm/mach-s3c2410/devs.c	2004-10-18 14:57:22 -07:00
@@ -0,0 +1,442 @@
+/* linux/arch/arm/mach-s3c2410/devs.c
+ *
+ * Copyright (c) 2004 Simtec Electronics
+ * Ben Dooks <ben@simtec.co.uk>
+ *
+ * Base S3C2410 platform device definitions
+ *
+ * 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.
+ *
+ * Modifications:
+ *     29-Aug-2004 BJD  Added timers 0 through 3
+ *     29-Aug-2004 BJD  Changed index of devices we only have one of to -1
+ *     21-Aug-2004 BJD  Added IRQ_TICK to RTC resources
+ *     18-Aug-2004 BJD  Created initial version
+*/
+
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/interrupt.h>
+#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>
+#include <asm/mach/irq.h>
+
+#include <asm/hardware.h>
+#include <asm/io.h>
+#include <asm/irq.h>
+
+#include "devs.h"
+
+/* USB Host Controller */
+
+static struct resource s3c_usb_resource[] = {
+	[0] = {
+		.start = S3C2410_PA_USBHOST,
+		.end   = S3C2410_PA_USBHOST + S3C2410_SZ_USBHOST,
+		.flags = IORESOURCE_MEM,
+	},
+	[1] = {
+		.start = IRQ_USBH,
+		.end   = IRQ_USBH,
+		.flags = IORESOURCE_IRQ,
+	}
+};
+
+static u64 s3c_device_usb_dmamask = 0xffffffffUL;
+
+struct platform_device s3c_device_usb = {
+	.name		  = "s3c2410-ohci",
+	.id		  = -1,
+	.num_resources	  = ARRAY_SIZE(s3c_usb_resource),
+	.resource	  = s3c_usb_resource,
+	.dev              = {
+		.dma_mask = &s3c_device_usb_dmamask,
+		.coherent_dma_mask = 0xffffffffUL
+	}
+};
+
+EXPORT_SYMBOL(s3c_device_usb);
+
+/* LCD Controller */
+
+static struct resource s3c_lcd_resource[] = {
+	[0] = {
+		.start = S3C2410_PA_LCD,
+		.end   = S3C2410_PA_LCD + S3C2410_SZ_LCD,
+		.flags = IORESOURCE_MEM,
+	},
+	[1] = {
+		.start = IRQ_LCD,
+		.end   = IRQ_LCD,
+		.flags = IORESOURCE_IRQ,
+	}
+
+};
+
+static u64 s3c_device_lcd_dmamask = 0xffffffffUL;
+
+struct platform_device s3c_device_lcd = {
+	.name		  = "s3c2410-lcd",
+	.id		  = -1,
+	.num_resources	  = ARRAY_SIZE(s3c_lcd_resource),
+	.resource	  = s3c_lcd_resource,
+	.dev              = {
+		.dma_mask = &s3c_device_lcd_dmamask,
+		.coherent_dma_mask = 0xffffffffUL
+	}
+};
+
+EXPORT_SYMBOL(s3c_device_lcd);
+
+/* NAND Controller */
+
+static struct resource s3c_nand_resource[] = {
+	[0] = {
+		.start = S3C2410_PA_NAND,
+		.end   = S3C2410_PA_NAND + S3C2410_SZ_NAND,
+		.flags = IORESOURCE_MEM,
+	}
+};
+
+struct platform_device s3c_device_nand = {
+	.name		  = "s3c2410-nand",
+	.id		  = -1,
+	.num_resources	  = ARRAY_SIZE(s3c_nand_resource),
+	.resource	  = s3c_nand_resource,
+};
+
+EXPORT_SYMBOL(s3c_device_nand);
+
+/* USB Device (Gadget)*/
+
+static struct resource s3c_usbgadget_resource[] = {
+	[0] = {
+		.start = S3C2410_PA_USBDEV,
+		.end   = S3C2410_PA_USBDEV + S3C2410_SZ_USBDEV,
+		.flags = IORESOURCE_MEM,
+	},
+	[1] = {
+		.start = IRQ_USBD,
+		.end   = IRQ_USBD,
+		.flags = IORESOURCE_IRQ,
+	}
+
+};
+
+struct platform_device s3c_device_usbgadget = {
+	.name		  = "s3c2410-usbgadget",
+	.id		  = -1,
+	.num_resources	  = ARRAY_SIZE(s3c_usbgadget_resource),
+	.resource	  = s3c_usbgadget_resource,
+};
+
+EXPORT_SYMBOL(s3c_device_usbgadget);
+
+/* Watchdog */
+
+static struct resource s3c_wdt_resource[] = {
+	[0] = {
+		.start = S3C2410_PA_WATCHDOG,
+		.end   = S3C2410_PA_WATCHDOG + S3C2410_SZ_WATCHDOG,
+		.flags = IORESOURCE_MEM,
+	},
+	[1] = {
+		.start = IRQ_WDT,
+		.end   = IRQ_WDT,
+		.flags = IORESOURCE_IRQ,
+	}
+
+};
+
+struct platform_device s3c_device_wdt = {
+	.name		  = "s3c2410-wdt",
+	.id		  = -1,
+	.num_resources	  = ARRAY_SIZE(s3c_wdt_resource),
+	.resource	  = s3c_wdt_resource,
+};
+
+EXPORT_SYMBOL(s3c_device_wdt);
+
+/* I2C */
+
+static struct resource s3c_i2c_resource[] = {
+	[0] = {
+		.start = S3C2410_PA_IIC,
+		.end   = S3C2410_PA_IIC + S3C2410_SZ_IIC,
+		.flags = IORESOURCE_MEM,
+	},
+	[1] = {
+		.start = IRQ_IIC,
+		.end   = IRQ_IIC,
+		.flags = IORESOURCE_IRQ,
+	}
+
+};
+
+struct platform_device s3c_device_i2c = {
+	.name		  = "s3c2410-i2c",
+	.id		  = -1,
+	.num_resources	  = ARRAY_SIZE(s3c_i2c_resource),
+	.resource	  = s3c_i2c_resource,
+};
+
+EXPORT_SYMBOL(s3c_device_i2c);
+
+/* IIS */
+
+static struct resource s3c_iis_resource[] = {
+	[0] = {
+		.start = S3C2410_PA_IIS,
+		.end   = S3C2410_PA_IIS + S3C2410_SZ_IIS,
+		.flags = IORESOURCE_MEM,
+	}
+};
+
+static u64 s3c_device_iis_dmamask = 0xffffffffUL;
+
+struct platform_device s3c_device_iis = {
+	.name		  = "s3c2410-iis",
+	.id		  = -1,
+	.num_resources	  = ARRAY_SIZE(s3c_iis_resource),
+	.resource	  = s3c_iis_resource,
+	.dev              = {
+		.dma_mask = &s3c_device_iis_dmamask,
+		.coherent_dma_mask = 0xffffffffUL
+	}
+};
+
+EXPORT_SYMBOL(s3c_device_iis);
+
+/* RTC */
+
+static struct resource s3c_rtc_resource[] = {
+	[0] = {
+		.start = S3C2410_PA_RTC,
+		.end   = S3C2410_PA_RTC + 0xff,
+		.flags = IORESOURCE_MEM,
+	},
+	[1] = {
+		.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 = {
+	.name		  = "s3c2410-rtc",
+	.id		  = -1,
+	.num_resources	  = ARRAY_SIZE(s3c_rtc_resource),
+	.resource	  = s3c_rtc_resource,
+};
+
+EXPORT_SYMBOL(s3c_device_rtc);
+
+/* ADC */
+
+static struct resource s3c_adc_resource[] = {
+	[0] = {
+		.start = S3C2410_PA_ADC,
+		.end   = S3C2410_PA_ADC + S3C2410_SZ_ADC,
+		.flags = IORESOURCE_MEM,
+	},
+	[1] = {
+		.start = IRQ_TC,
+		.end   = IRQ_ADC,
+		.flags = IORESOURCE_IRQ,
+	}
+
+};
+
+struct platform_device s3c_device_adc = {
+	.name		  = "s3c2410-adc",
+	.id		  = -1,
+	.num_resources	  = ARRAY_SIZE(s3c_adc_resource),
+	.resource	  = s3c_adc_resource,
+};
+
+/* SDI */
+
+static struct resource s3c_sdi_resource[] = {
+	[0] = {
+		.start = S3C2410_PA_SDI,
+		.end   = S3C2410_PA_SDI + S3C2410_SZ_SDI,
+		.flags = IORESOURCE_MEM,
+	},
+	[1] = {
+		.start = IRQ_SDI,
+		.end   = IRQ_SDI,
+		.flags = IORESOURCE_IRQ,
+	}
+
+};
+
+struct platform_device s3c_device_sdi = {
+	.name		  = "s3c2410-sdi",
+	.id		  = -1,
+	.num_resources	  = ARRAY_SIZE(s3c_sdi_resource),
+	.resource	  = s3c_sdi_resource,
+};
+
+EXPORT_SYMBOL(s3c_device_sdi);
+
+/* SPI (0) */
+
+static struct resource s3c_spi0_resource[] = {
+	[0] = {
+		.start = S3C2410_PA_SPI,
+		.end   = S3C2410_PA_SPI + 0x1f,
+		.flags = IORESOURCE_MEM,
+	},
+	[1] = {
+		.start = IRQ_SPI0,
+		.end   = IRQ_SPI0,
+		.flags = IORESOURCE_IRQ,
+	}
+
+};
+
+struct platform_device s3c_device_spi0 = {
+	.name		  = "s3c2410-spi",
+	.id		  = 0,
+	.num_resources	  = ARRAY_SIZE(s3c_spi0_resource),
+	.resource	  = s3c_spi0_resource,
+};
+
+EXPORT_SYMBOL(s3c_device_spi0);
+
+/* SPI (1) */
+
+static struct resource s3c_spi1_resource[] = {
+	[0] = {
+		.start = S3C2410_PA_SPI + 0x20,
+		.end   = S3C2410_PA_SPI + 0x20 + 0x1f,
+		.flags = IORESOURCE_MEM,
+	},
+	[1] = {
+		.start = IRQ_SPI1,
+		.end   = IRQ_SPI1,
+		.flags = IORESOURCE_IRQ,
+	}
+
+};
+
+struct platform_device s3c_device_spi1 = {
+	.name		  = "s3c2410-spi",
+	.id		  = 1,
+	.num_resources	  = ARRAY_SIZE(s3c_spi1_resource),
+	.resource	  = s3c_spi1_resource,
+};
+
+EXPORT_SYMBOL(s3c_device_spi1);
+
+/* pwm timer blocks */
+
+static struct resource s3c_timer0_resource[] = {
+	[0] = {
+		.start = S3C2410_PA_TIMER + 0x0C,
+		.end   = S3C2410_PA_TIMER + 0x0C + 0xB,
+		.flags = IORESOURCE_MEM,
+	},
+	[1] = {
+		.start = IRQ_TIMER0,
+		.end   = IRQ_TIMER0,
+		.flags = IORESOURCE_IRQ,
+	}
+
+};
+
+struct platform_device s3c_device_timer0 = {
+	.name		  = "s3c2410-timer",
+	.id		  = 0,
+	.num_resources	  = ARRAY_SIZE(s3c_timer0_resource),
+	.resource	  = s3c_timer0_resource,
+};
+
+EXPORT_SYMBOL(s3c_device_timer0);
+
+/* timer 1 */
+
+static struct resource s3c_timer1_resource[] = {
+	[0] = {
+		.start = S3C2410_PA_TIMER + 0x18,
+		.end   = S3C2410_PA_TIMER + 0x23,
+		.flags = IORESOURCE_MEM,
+	},
+	[1] = {
+		.start = IRQ_TIMER1,
+		.end   = IRQ_TIMER1,
+		.flags = IORESOURCE_IRQ,
+	}
+
+};
+
+struct platform_device s3c_device_timer1 = {
+	.name		  = "s3c2410-timer",
+	.id		  = 1,
+	.num_resources	  = ARRAY_SIZE(s3c_timer1_resource),
+	.resource	  = s3c_timer1_resource,
+};
+
+EXPORT_SYMBOL(s3c_device_timer1);
+
+/* timer 2 */
+
+static struct resource s3c_timer2_resource[] = {
+	[0] = {
+		.start = S3C2410_PA_TIMER + 0x24,
+		.end   = S3C2410_PA_TIMER + 0x2F,
+		.flags = IORESOURCE_MEM,
+	},
+	[1] = {
+		.start = IRQ_TIMER2,
+		.end   = IRQ_TIMER2,
+		.flags = IORESOURCE_IRQ,
+	}
+
+};
+
+struct platform_device s3c_device_timer2 = {
+	.name		  = "s3c2410-timer",
+	.id		  = 2,
+	.num_resources	  = ARRAY_SIZE(s3c_timer2_resource),
+	.resource	  = s3c_timer2_resource,
+};
+
+EXPORT_SYMBOL(s3c_device_timer2);
+
+/* timer 3 */
+
+static struct resource s3c_timer3_resource[] = {
+	[0] = {
+		.start = S3C2410_PA_TIMER + 0x30,
+		.end   = S3C2410_PA_TIMER + 0x3B,
+		.flags = IORESOURCE_MEM,
+	},
+	[1] = {
+		.start = IRQ_TIMER3,
+		.end   = IRQ_TIMER3,
+		.flags = IORESOURCE_IRQ,
+	}
+
+};
+
+struct platform_device s3c_device_timer3 = {
+	.name		  = "s3c2410-timer",
+	.id		  = 3,
+	.num_resources	  = ARRAY_SIZE(s3c_timer3_resource),
+	.resource	  = s3c_timer3_resource,
+};
+
+EXPORT_SYMBOL(s3c_device_timer3);
diff -Nru a/arch/arm/mach-s3c2410/devs.h b/arch/arm/mach-s3c2410/devs.h
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/arch/arm/mach-s3c2410/devs.h	2004-10-18 14:57:21 -07:00
@@ -0,0 +1,36 @@
+/* arch/arm/mach-s3c2410/devs.h
+ *
+ * Copyright (c) 2004 Simtec Electronics
+ * Ben Dooks <ben@simtec.co.uk>
+ *
+ * Header file for s3c2410 standard platform devices
+ *
+ * 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.
+ *
+ * Modifications:
+ *      18-Aug-2004 BJD  Created initial version
+ *	27-Aug-2004 BJD  Added timers 0 through 3
+*/
+
+extern struct platform_device s3c_device_usb;
+extern struct platform_device s3c_device_lcd;
+extern struct platform_device s3c_device_wdt;
+extern struct platform_device s3c_device_i2c;
+extern struct platform_device s3c_device_iis;
+extern struct platform_device s3c_device_rtc;
+extern struct platform_device s3c_device_adc;
+extern struct platform_device s3c_device_sdi;
+
+extern struct platform_device s3c_device_spi0;
+extern struct platform_device s3c_device_spi1;
+
+extern struct platform_device s3c_device_nand;
+
+extern struct platform_device s3c_device_timer0;
+extern struct platform_device s3c_device_timer1;
+extern struct platform_device s3c_device_timer2;
+extern struct platform_device s3c_device_timer3;
+
+extern struct platform_device s3c_device_usbgadget;
diff -Nru a/arch/arm/mach-s3c2410/dma.c b/arch/arm/mach-s3c2410/dma.c
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/arch/arm/mach-s3c2410/dma.c	2004-10-18 14:57:22 -07:00
@@ -0,0 +1,1085 @@
+/* linux/arch/arm/mach-bast/dma.c
+ *
+ * (c) 2003,2004 Simtec Electronics
+ * Ben Dooks <ben@simtec.co.uk>
+ *
+ * S3C2410 DMA core
+ *
+ * http://www.simtec.co.uk/products/EB2410ITX/
+ *
+ * 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.
+ *
+ * Changelog:
+ *  08-Aug-2004 BJD  Apply rmk's suggestions
+ *  21-Jul-2004 BJD  Ported to linux 2.6
+ *  12-Jul-2004 BJD  Finished re-write and change of API
+ *  06-Jul-2004 BJD  Rewrote dma code to try and cope with various problems
+ *  23-May-2003 BJD  Created file
+ *  19-Aug-2003 BJD  Cleanup, header fix, added URL
+ *
+ * This file is based on the Sangwook Lee/Samsung patches, re-written due
+ * to various ommisions from the code (such as flexible dma configuration)
+ * for use with the BAST system board.
+ *
+ * The re-write is pretty much complete, and should be good enough for any
+ * possible DMA function
+ */
+
+#include <linux/config.h>
+
+#ifdef CONFIG_S3C2410_DMA_DEBUG
+#define DEBUG
+#endif
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/sched.h>
+#include <linux/spinlock.h>
+#include <linux/interrupt.h>
+#include <linux/slab.h>
+#include <linux/errno.h>
+#include <linux/delay.h>
+
+#include <asm/system.h>
+#include <asm/irq.h>
+#include <asm/hardware.h>
+#include <asm/io.h>
+#include <asm/dma.h>
+
+#include <asm/mach/dma.h>
+#include <asm/arch/map.h>
+
+/* io map for dma */
+static void *dma_base;
+
+/* dma channel state information */
+s3c2410_dma_chan_t s3c2410_chans[S3C2410_DMA_CHANNELS];
+
+/* debugging functions */
+
+#define BUF_MAGIC (0xcafebabe)
+
+#define dmawarn(fmt...) printk(KERN_DEBUG fmt)
+
+#define dma_regaddr(chan, reg) ((chan)->regs + (reg))
+
+#if 1
+#define dma_wrreg(chan, reg, val) writel((val), (chan)->regs + (reg))
+#else
+static inline void
+dma_wrreg(s3c2410_dma_chan_t *chan, int reg, unsigned long val)
+{
+	pr_debug("writing %08x to register %08x\n",(unsigned int)val,reg);
+	writel(val, dma_regaddr(chan, reg));
+}
+
+#endif
+
+#define dma_rdreg(chan, reg) readl((chan)->regs + (reg))
+
+/* captured register state for debug */
+
+struct s3c2410_dma_regstate {
+	unsigned long         dcsrc;
+	unsigned long         disrc;
+	unsigned long         dstat;
+	unsigned long         dcon;
+	unsigned long         dmsktrig;
+};
+
+#ifdef CONFIG_S3C2410_DMA_DEBUG
+
+/* dmadbg_showregs
+ *
+ * simple debug routine to print the current state of the dma registers
+*/
+
+static void
+dmadbg_capture(s3c2410_dma_chan_t *chan, struct s3c2410_dma_regstate *regs)
+{
+	regs->dcsrc    = dma_rdreg(chan, S3C2410_DMA_DCSRC);
+	regs->disrc    = dma_rdreg(chan, S3C2410_DMA_DISRC);
+	regs->dstat    = dma_rdreg(chan, S3C2410_DMA_DSTAT);
+	regs->dcon     = dma_rdreg(chan, S3C2410_DMA_DCON);
+	regs->dmsktrig = dma_rdreg(chan, S3C2410_DMA_DMASKTRIG);
+}
+
+static void
+dmadbg_showregs(const char *fname, int line, s3c2410_dma_chan_t *chan,
+		 struct s3c2410_dma_regstate *regs)
+{
+	printk(KERN_DEBUG "dma%d: %s:%d: DCSRC=%08lx, DISRC=%08lx, DSTAT=%08lx DMT=%02lx, DCON=%08lx\n",
+	       chan->number, fname, line,
+	       regs->dcsrc, regs->disrc, regs->dstat, regs->dmsktrig,
+	       regs->dcon);
+}
+
+static void
+dmadbg_showchan(const char *fname, int line, s3c2410_dma_chan_t *chan)
+{
+	struct s3c2410_dma_regstate state;
+
+	dmadbg_capture(chan, &state);
+
+	printk(KERN_DEBUG "dma%d: %s:%d: ls=%d, cur=%p, %p %p\n",
+	       chan->number, fname, line, chan->load_state,
+	       chan->curr, chan->next, chan->end);
+
+	dmadbg_showregs(fname, line, chan, &state);
+}
+
+#define dbg_showregs(chan) dmadbg_showregs(__FUNCTION__, __LINE__, (chan))
+#define dbg_showchan(chan) dmadbg_showchan(__FUNCTION__, __LINE__, (chan))
+#else
+#define dbg_showregs(chan) do { } while(0)
+#define dbg_showchan(chan) do { } while(0)
+#endif /* CONFIG_S3C2410_DMA_DEBUG */
+
+#define check_channel(chan) \
+  do { if ((chan) >= S3C2410_DMA_CHANNELS) { \
+    printk(KERN_ERR "%s: invalid channel %d\n", __FUNCTION__, (chan)); \
+    return -EINVAL; \
+  } } while(0)
+
+
+/* s3c2410_dma_stats_timeout
+ *
+ * Update DMA stats from timeout info
+*/
+
+static void
+s3c2410_dma_stats_timeout(s3c2410_dma_stats_t *stats, int val)
+{
+	if (stats == NULL)
+		return;
+
+	if (val > stats->timeout_longest)
+		stats->timeout_longest = val;
+	if (val < stats->timeout_shortest)
+		stats->timeout_shortest = val;
+
+	stats->timeout_avg += val;
+}
+
+/* s3c2410_dma_waitforload
+ *
+ * wait for the DMA engine to load a buffer, and update the state accordingly
+*/
+
+static int
+s3c2410_dma_waitforload(s3c2410_dma_chan_t *chan, int line)
+{
+	int timeout = chan->load_timeout;
+	int took;
+
+	if (chan->load_state != S3C2410_DMALOAD_1LOADED) {
+		printk(KERN_ERR "dma%d: s3c2410_dma_waitforload() called in loadstate %d from line %d\n", chan->number, chan->load_state, line);
+		return 0;
+	}
+
+	if (chan->stats != NULL)
+		chan->stats->loads++;
+
+	while (--timeout > 0) {
+		if ((dma_rdreg(chan, S3C2410_DMA_DSTAT) << (32-20)) != 0) {
+			took = chan->load_timeout - timeout;
+
+			s3c2410_dma_stats_timeout(chan->stats, took);
+
+			switch (chan->load_state) {
+			case S3C2410_DMALOAD_1LOADED:
+				chan->load_state = S3C2410_DMALOAD_1RUNNING;
+				break;
+
+			default:
+				printk(KERN_ERR "dma%d: unknown load_state in s3c2410_dma_waitforload() %d\n", chan->number, chan->load_state);
+			}
+
+			return 1;
+		}
+	}
+
+	if (chan->stats != NULL) {
+		chan->stats->timeout_failed++;
+	}
+
+	return 0;
+}
+
+
+
+/* s3c2410_dma_loadbuffer
+ *
+ * load a buffer, and update the channel state
+*/
+
+static inline int
+s3c2410_dma_loadbuffer(s3c2410_dma_chan_t *chan,
+		       s3c2410_dma_buf_t *buf)
+{
+	unsigned long reload;
+
+	pr_debug("s3c2410_chan_loadbuffer: loading buff %p (0x%08lx,0x%06x)\n",
+		 buf, (unsigned long)buf->data, buf->size);
+
+	if (buf == NULL) {
+		dmawarn("buffer is NULL\n");
+		return -EINVAL;
+	}
+
+	/* check the state of the channel before we do anything */
+
+	if (chan->load_state == S3C2410_DMALOAD_1LOADED) {
+		dmawarn("load_state is S3C2410_DMALOAD_1LOADED\n");
+	}
+
+	if (chan->load_state == S3C2410_DMALOAD_1LOADED_1RUNNING) {
+		dmawarn("state is S3C2410_DMALOAD_1LOADED_1RUNNING\n");
+	}
+
+	/* it would seem sensible if we are the last buffer to not bother
+	 * with the auto-reload bit, so that the DMA engine will not try
+	 * and load another transfer after this one has finished...
+	 */
+	if (chan->load_state == S3C2410_DMALOAD_NONE) {
+		pr_debug("load_state is none, checking for noreload (next=%p)\n",
+			 buf->next);
+		reload = (buf->next == NULL) ? S3C2410_DCON_NORELOAD : 0;
+	} else {
+		pr_debug("load_state is %d => autoreload\n", chan->load_state);
+		reload = S3C2410_DCON_AUTORELOAD;
+	}
+
+	writel(buf->data, chan->addr_reg);
+
+	dma_wrreg(chan, S3C2410_DMA_DCON,
+		  chan->dcon | reload | (buf->size/chan->xfer_unit));
+
+	chan->next = buf->next;
+
+	/* update the state of the channel */
+
+	switch (chan->load_state) {
+	case S3C2410_DMALOAD_NONE:
+		chan->load_state = S3C2410_DMALOAD_1LOADED;
+		break;
+
+	case S3C2410_DMALOAD_1RUNNING:
+		chan->load_state = S3C2410_DMALOAD_1LOADED_1RUNNING;
+		break;
+
+	default:
+		dmawarn("dmaload: unknown state %d in loadbuffer\n",
+			chan->load_state);
+		break;
+	}
+
+	return 0;
+}
+
+/* s3c2410_dma_call_op
+ *
+ * small routine to call the op routine with the given op if it has been
+ * registered
+*/
+
+static void
+s3c2410_dma_call_op(s3c2410_dma_chan_t *chan, s3c2410_chan_op_t op)
+{
+	if (chan->op_fn != NULL) {
+		(chan->op_fn)(chan, op);
+	}
+}
+
+/* s3c2410_dma_buffdone
+ *
+ * small wrapper to check if callback routine needs to be called, and
+ * if so, call it
+*/
+
+static inline void
+s3c2410_dma_buffdone(s3c2410_dma_chan_t *chan, s3c2410_dma_buf_t *buf,
+		     s3c2410_dma_buffresult_t result)
+{
+	pr_debug("callback_fn=%p, buf=%p, id=%p, size=%d, result=%d\n",
+		 chan->callback_fn, buf, buf->id, buf->size, result);
+
+	if (chan->callback_fn != NULL) {
+		(chan->callback_fn)(chan, buf->id, buf->size, result);
+	}
+}
+
+/* s3c2410_dma_start
+ *
+ * start a dma channel going
+*/
+
+static int s3c2410_dma_start(s3c2410_dma_chan_t *chan)
+{
+	unsigned long tmp;
+	unsigned long flags;
+
+	pr_debug("s3c2410_start_dma: channel=%d\n", chan->number);
+
+	local_irq_save(flags);
+
+	if (chan->state == S3C2410_DMA_RUNNING) {
+		pr_debug("s3c2410_start_dma: already running (%d)\n", chan->state);
+		local_irq_restore(flags);
+		return 0;
+	}
+
+	chan->state = S3C2410_DMA_RUNNING;
+
+	/* check wether there is anything to load, and if not, see
+	 * if we can find anything to load
+	 */
+
+	if (chan->load_state == S3C2410_DMALOAD_NONE) {
+		if (chan->next == NULL) {
+			printk(KERN_ERR "dma%d: channel has nothing loaded\n",
+			       chan->number);
+			chan->state = S3C2410_DMA_IDLE;
+			local_irq_restore(flags);
+			return -EINVAL;
+		}
+
+		s3c2410_dma_loadbuffer(chan, chan->next);
+	}
+
+	dbg_showchan(chan);
+
+	/* enable the channel */
+
+	if (!chan->irq_enabled) {
+		enable_irq(chan->irq);
+		chan->irq_enabled = 1;
+	}
+
+	/* start the channel going */
+
+	tmp = dma_rdreg(chan, S3C2410_DMA_DMASKTRIG);
+	tmp &= ~S3C2410_DMASKTRIG_STOP;
+	tmp |= S3C2410_DMASKTRIG_ON;
+	dma_wrreg(chan, S3C2410_DMA_DMASKTRIG, tmp);
+
+	pr_debug("wrote %08lx to DMASKTRIG\n", tmp);
+
+#if 0
+	/* the dma buffer loads should take care of clearing the AUTO
+	 * reloading feature */
+	tmp = dma_rdreg(chan, S3C2410_DMA_DCON);
+	tmp &= ~S3C2410_DCON_NORELOAD;
+	dma_wrreg(chan, S3C2410_DMA_DCON, tmp);
+#endif
+
+	s3c2410_dma_call_op(chan, S3C2410_DMAOP_START);
+
+	dbg_showchan(chan);
+
+	local_irq_restore(flags);
+	return 0;
+}
+
+/* s3c2410_dma_canload
+ *
+ * work out if we can queue another buffer into the DMA engine
+*/
+
+static int
+s3c2410_dma_canload(s3c2410_dma_chan_t *chan)
+{
+	if (chan->load_state == S3C2410_DMALOAD_NONE ||
+	    chan->load_state == S3C2410_DMALOAD_1RUNNING)
+		return 1;
+
+	return 0;
+}
+
+
+/* s3c2410_dma_enqueue
+ *
+ * queue an given buffer for dma transfer.
+ *
+ * id         the device driver's id information for this buffer
+ * data       the physical address of the buffer data
+ * size       the size of the buffer in bytes
+ *
+ * If the channel is not running, then the flag S3C2410_DMAF_AUTOSTART
+ * is checked, and if set, the channel is started. If this flag isn't set,
+ * then an error will be returned.
+ *
+ * It is possible to queue more than one DMA buffer onto a channel at
+ * once, and the code will deal with the re-loading of the next buffer
+ * when necessary.
+*/
+
+int s3c2410_dma_enqueue(unsigned int channel, void *id,
+			dma_addr_t data, int size)
+{
+	s3c2410_dma_chan_t *chan = &s3c2410_chans[channel];
+	s3c2410_dma_buf_t *buf;
+	unsigned long flags;
+
+	check_channel(channel);
+
+	pr_debug("%s: id=%p, data=%08x, size=%d\n",
+		 __FUNCTION__, id, (unsigned int)data, size);
+
+	buf = (s3c2410_dma_buf_t *)kmalloc(sizeof(*buf), GFP_ATOMIC);
+	if (buf == NULL) {
+		pr_debug("%s: out of memory (%d alloc)\n",
+			 __FUNCTION__, sizeof(*buf));
+		return -ENOMEM;
+	}
+
+	pr_debug("%s: new buffer %p\n", __FUNCTION__, buf);
+
+	//dbg_showchan(chan);
+
+	buf->next  = NULL;
+	buf->data  = buf->ptr = data;
+	buf->size  = size;
+	buf->id    = id;
+	buf->magic = BUF_MAGIC;
+
+	local_irq_save(flags);
+
+	if (chan->curr == NULL) {
+		/* we've got nothing loaded... */
+		pr_debug("%s: buffer %p queued onto empty channel\n",
+			 __FUNCTION__, buf);
+
+		chan->curr = buf;
+		chan->end  = buf;
+		chan->next = NULL;
+	} else {
+		pr_debug("dma%d: %s: buffer %p queued onto non-empty channel\n",
+			 chan->number, __FUNCTION__, buf);
+
+		if (chan->end == NULL)
+			pr_debug("dma%d: %s: %p not empty, and chan->end==NULL?\n",
+				 chan->number, __FUNCTION__, chan);
+
+		chan->end->next = buf;
+		chan->end = buf;
+	}
+
+	/* if necessary, update the next buffer field */
+	if (chan->next == NULL)
+		chan->next = buf;
+
+	/* check to see if we can load a buffer */
+	if (chan->state == S3C2410_DMA_RUNNING) {
+		if (chan->load_state == S3C2410_DMALOAD_1LOADED && 1) {
+			if (s3c2410_dma_waitforload(chan, __LINE__) == 0) {
+				printk(KERN_ERR "dma%d: loadbuffer:"
+				       "timeout loading buffer\n",
+				       chan->number);
+				dbg_showchan(chan);
+				local_irq_restore(flags);
+				return -EINVAL;
+			}
+		}
+
+		while (s3c2410_dma_canload(chan) && chan->next != NULL) {
+			s3c2410_dma_loadbuffer(chan, chan->next);
+		}
+	} else if (chan->state == S3C2410_DMA_IDLE) {
+		if (chan->flags & S3C2410_DMAF_AUTOSTART) {
+			s3c2410_dma_ctrl(chan->number, S3C2410_DMAOP_START);
+		} else {
+			printk(KERN_DEBUG "dma%d: cannot load onto stopped channel'n", chan->number);
+			local_irq_restore(flags);
+			return -EINVAL;
+		}
+	}
+
+	local_irq_restore(flags);
+	return 0;
+}
+
+static inline void
+s3c2410_dma_freebuf(s3c2410_dma_buf_t *buf)
+{
+	int magicok = (buf->magic == BUF_MAGIC);
+
+	buf->magic = -1;
+
+	if (magicok) {
+		kfree(buf);
+	} else {
+		printk("s3c2410_dma_freebuf: buff %p with bad magic\n", buf);
+	}
+}
+
+/* s3c2410_dma_lastxfer
+ *
+ * called when the system is out of buffers, to ensure that the channel
+ * is prepared for shutdown.
+*/
+
+static inline void
+s3c2410_dma_lastxfer(s3c2410_dma_chan_t *chan)
+{
+	pr_debug("dma%d: s3c2410_dma_lastxfer: load_state %d\n",
+		 chan->number, chan->load_state);
+
+	switch (chan->load_state) {
+	case S3C2410_DMALOAD_NONE:
+		break;
+
+	case S3C2410_DMALOAD_1LOADED:
+		if (s3c2410_dma_waitforload(chan, __LINE__) == 0) {
+				/* flag error? */
+			printk(KERN_ERR "dma%d: timeout waiting for load\n",
+			       chan->number);
+			return;
+		}
+		break;
+
+	default:
+		pr_debug("dma%d: lastxfer: unhandled load_state %d with no next",
+			 chan->number, chan->load_state);
+		return;
+
+	}
+
+	/* hopefully this'll shut the damned thing up after the transfer... */
+	dma_wrreg(chan, S3C2410_DMA_DCON, chan->dcon | S3C2410_DCON_NORELOAD);
+}
+
+
+#define dmadbg2(x...)
+
+static irqreturn_t
+s3c2410_dma_irq(int irq, void *devpw, struct pt_regs *regs)
+{
+	s3c2410_dma_chan_t *chan = (s3c2410_dma_chan_t *)devpw;
+	s3c2410_dma_buf_t  *buf;
+
+	buf = chan->curr;
+
+	dbg_showchan(chan);
+
+	/* modify the channel state */
+
+	switch (chan->load_state) {
+	case S3C2410_DMALOAD_1RUNNING:
+		/* TODO - if we are running only one buffer, we probably
+		 * want to reload here, and then worry about the buffer
+		 * callback */
+
+		chan->load_state = S3C2410_DMALOAD_NONE;
+		break;
+
+	case S3C2410_DMALOAD_1LOADED:
+		/* iirc, we should go back to NONE loaded here, we
+		 * had a buffer, and it was never verified as being
+		 * loaded.
+		 */
+
+		chan->load_state = S3C2410_DMALOAD_NONE;
+		break;
+
+	case S3C2410_DMALOAD_1LOADED_1RUNNING:
+		/* we'll worry about checking to see if another buffer is
+		 * ready after we've called back the owner. This should
+		 * ensure we do not wait around too long for the DMA
+		 * engine to start the next transfer
+		 */
+
+		chan->load_state = S3C2410_DMALOAD_1LOADED;
+		break;
+
+	case S3C2410_DMALOAD_NONE:
+		printk(KERN_ERR "dma%d: IRQ with no loaded buffer?\n",
+		       chan->number);
+		break;
+
+	default:
+		printk(KERN_ERR "dma%d: IRQ in invalid load_state %d\n",
+		       chan->number, chan->load_state);
+		break;
+	}
+
+	if (buf != NULL) {
+		/* update the chain to make sure that if we load any more
+		 * buffers when we call the callback function, things should
+		 * work properly */
+
+		chan->curr = buf->next;
+		buf->next  = NULL;
+
+		if (buf->magic != BUF_MAGIC) {
+			printk(KERN_ERR "dma%d: %s: buf %p incorrect magic\n",
+			       chan->number, __FUNCTION__, buf);
+			return IRQ_HANDLED;
+		}
+
+		s3c2410_dma_buffdone(chan, buf, S3C2410_RES_OK);
+
+		/* free resouces */
+		s3c2410_dma_freebuf(buf);
+	} else {
+	}
+
+	if (chan->next != NULL) {
+		unsigned long flags;
+
+		switch (chan->load_state) {
+		case S3C2410_DMALOAD_1RUNNING:
+			/* don't need to do anything for this state */
+			break;
+
+		case S3C2410_DMALOAD_NONE:
+			/* can load buffer immediately */
+			break;
+
+		case S3C2410_DMALOAD_1LOADED:
+			if (s3c2410_dma_waitforload(chan, __LINE__) == 0) {
+				/* flag error? */
+				printk(KERN_ERR "dma%d: timeout waiting for load\n",
+				       chan->number);
+				return IRQ_HANDLED;
+			}
+
+			break;
+
+		default:
+			printk(KERN_ERR "dma%d: unknown load_state in irq, %d\n",
+			       chan->number, chan->load_state);
+			return IRQ_HANDLED;
+		}
+
+		local_irq_save(flags);
+		s3c2410_dma_loadbuffer(chan, chan->next);
+		local_irq_restore(flags);
+	} else {
+		s3c2410_dma_lastxfer(chan);
+
+		/* see if we can stop this channel.. */
+		if (chan->load_state == S3C2410_DMALOAD_NONE) {
+			pr_debug("dma%d: end of transfer, stopping channel (%ld)\n",
+				 chan->number, jiffies);
+			s3c2410_dma_ctrl(chan->number, S3C2410_DMAOP_STOP);
+		}
+	}
+
+	return IRQ_HANDLED;
+}
+
+
+
+/* s3c2410_request_dma
+ *
+ * get control of an dma channel
+*/
+
+int s3c2410_dma_request(unsigned int channel, s3c2410_dma_client_t *client,
+			void *dev)
+{
+	s3c2410_dma_chan_t *chan = &s3c2410_chans[channel];
+	unsigned long flags;
+	int err;
+
+	pr_debug("dma%d: s3c2410_request_dma: client=%s, dev=%p\n",
+		 channel, client->name, dev);
+
+	check_channel(channel);
+
+	local_irq_save(flags);
+
+	dbg_showchan(chan);
+
+	if (chan->in_use) {
+		if (client != chan->client) {
+			printk(KERN_ERR "dma%d: already in use\n", channel);
+			local_irq_restore(flags);
+			return -EBUSY;
+		} else {
+			printk(KERN_ERR "dma%d: client already has channel\n", channel);
+		}
+	}
+
+	chan->client = client;
+	chan->in_use = 1;
+
+	if (!chan->irq_claimed) {
+		pr_debug("dma%d: %s : requesting irq %d\n",
+			 channel, __FUNCTION__, chan->irq);
+
+		err = request_irq(chan->irq, s3c2410_dma_irq, SA_INTERRUPT,
+				  client->name, (void *)chan);
+
+		if (err) {
+			chan->in_use = 0;
+			local_irq_restore(flags);
+
+			printk(KERN_ERR "%s: cannot get IRQ %d for DMA %d\n",
+			       client->name, chan->irq, chan->number);
+			return err;
+		}
+
+		chan->irq_claimed = 1;
+		chan->irq_enabled = 1;
+	}
+
+	local_irq_restore(flags);
+
+	/* need to setup */
+
+	pr_debug("%s: channel initialised, %p\n", __FUNCTION__, chan);
+
+	return 0;
+}
+
+/* s3c2410_dma_free
+ *
+ * release the given channel back to the system, will stop and flush
+ * any outstanding transfers, and ensure the channel is ready for the
+ * next claimant.
+ *
+ * Note, although a warning is currently printed if the freeing client
+ * info is not the same as the registrant's client info, the free is still
+ * allowed to go through.
+*/
+
+int s3c2410_dma_free(dmach_t channel, s3c2410_dma_client_t *client)
+{
+	s3c2410_dma_chan_t *chan = &s3c2410_chans[channel];
+	unsigned long flags;
+
+	check_channel(channel);
+
+	local_irq_save(flags);
+
+
+	if (chan->client != client) {
+		printk(KERN_WARNING "dma%d: possible free from different client (channel %p, passed %p)\n",
+		       channel, chan->client, client);
+	}
+
+	/* sort out stopping and freeing the channel */
+
+	if (chan->state != S3C2410_DMA_IDLE) {
+		pr_debug("%s: need to stop dma channel %p\n",
+		       __FUNCTION__, chan);
+
+		/* possibly flush the channel */
+		s3c2410_dma_ctrl(channel, S3C2410_DMAOP_STOP);
+	}
+
+	chan->client = NULL;
+	chan->in_use = 0;
+
+	local_irq_restore(flags);
+
+	return 0;
+}
+
+static int s3c2410_dma_dostop(s3c2410_dma_chan_t *chan)
+{
+	unsigned long tmp;
+	unsigned long flags;
+
+	pr_debug("%s:\n", __FUNCTION__);
+
+	dbg_showchan(chan);
+
+	local_irq_save(flags);
+
+	s3c2410_dma_call_op(chan,  S3C2410_DMAOP_STOP);
+
+	tmp = dma_rdreg(chan, S3C2410_DMA_DMASKTRIG);
+	tmp |= S3C2410_DMASKTRIG_STOP;
+	dma_wrreg(chan, S3C2410_DMA_DMASKTRIG, tmp);
+
+#if 0
+	/* should also clear interrupts, according to WinCE BSP */
+	tmp = dma_rdreg(chan, S3C2410_DMA_DCON);
+	tmp |= S3C2410_DCON_NORELOAD;
+	dma_wrreg(chan, S3C2410_DMA_DCON, tmp);
+#endif
+
+	chan->state      = S3C2410_DMA_IDLE;
+	chan->load_state = S3C2410_DMALOAD_NONE;
+
+	local_irq_restore(flags);
+
+	return 0;
+}
+
+/* s3c2410_dma_flush
+ *
+ * stop the channel, and remove all current and pending transfers
+*/
+
+static int s3c2410_dma_flush(s3c2410_dma_chan_t *chan)
+{
+	s3c2410_dma_buf_t *buf, *next;
+	unsigned long flags;
+
+	pr_debug("%s:\n", __FUNCTION__);
+
+	local_irq_save(flags);
+
+	if (chan->state != S3C2410_DMA_IDLE) {
+		pr_debug("%s: stopping channel...\n", __FUNCTION__ );
+		s3c2410_dma_ctrl(chan->number, S3C2410_DMAOP_STOP);
+	}
+
+	buf = chan->curr;
+	if (buf == NULL)
+		buf = chan->next;
+
+	chan->curr = chan->next = chan->end = NULL;
+
+	if (buf != NULL) {
+		for ( ; buf != NULL; buf = next) {
+			next = buf->next;
+
+			pr_debug("%s: free buffer %p, next %p\n",
+			       __FUNCTION__, buf, buf->next);
+
+			s3c2410_dma_buffdone(chan, buf, S3C2410_RES_ABORT);
+			s3c2410_dma_freebuf(buf);
+		}
+	}
+
+	local_irq_restore(flags);
+
+	return 0;
+}
+
+
+int
+s3c2410_dma_ctrl(dmach_t channel, s3c2410_chan_op_t op)
+{
+	s3c2410_dma_chan_t *chan = &s3c2410_chans[channel];
+
+	check_channel(channel);
+
+	switch (op) {
+	case S3C2410_DMAOP_START:
+		return s3c2410_dma_start(chan);
+
+	case S3C2410_DMAOP_STOP:
+		return s3c2410_dma_dostop(chan);
+
+	case S3C2410_DMAOP_PAUSE:
+		return -ENOENT;
+
+	case S3C2410_DMAOP_RESUME:
+		return -ENOENT;
+
+	case S3C2410_DMAOP_FLUSH:
+		return s3c2410_dma_flush(chan);
+
+	case S3C2410_DMAOP_TIMEOUT:
+		return 0;
+
+	}
+
+	return -ENOENT;      /* unknown, don't bother */
+}
+
+
+/* DMA configuration for each channel
+ *
+ * DISRCC -> source of the DMA (AHB,APB)
+ * DISRC  -> source address of the DMA
+ * DIDSTC -> destination of the DMA (AHB,APD)
+ * DIDST  -> destination address of the DMA
+*/
+
+/* s3c2410_dma_config
+ *
+ * xfersize:     size of unit in bytes (1,2,4)
+ * dcon:         base value of the DCONx register
+*/
+
+int s3c2410_dma_config(dmach_t channel,
+		       int xferunit,
+		       int dcon)
+{
+	s3c2410_dma_chan_t *chan = &s3c2410_chans[channel];
+
+	pr_debug("%s: chan=%d, xfer_unit=%d, dcon=%08x\n",
+		 __FUNCTION__, channel, xferunit, dcon);
+
+	check_channel(channel);
+
+	switch (xferunit) {
+	case 1:
+		dcon |= S3C2410_DCON_BYTE;
+		break;
+
+	case 2:
+		dcon |= S3C2410_DCON_HALFWORD;
+		break;
+
+	case 4:
+		dcon |= S3C2410_DCON_WORD;
+		break;
+
+	default:
+		pr_debug("%s: bad transfer size %d\n", __FUNCTION__, xferunit);
+		return -EINVAL;
+	}
+
+	dcon |= S3C2410_DCON_HWTRIG;
+	dcon |= S3C2410_DCON_INTREQ;
+
+	pr_debug("%s: dcon now %08x\n", __FUNCTION__, dcon);
+
+	chan->dcon = dcon;
+	chan->xfer_unit = xferunit;
+
+	return 0;
+}
+
+
+int s3c2410_dma_setflags(dmach_t channel, unsigned int flags)
+{
+	s3c2410_dma_chan_t *chan = &s3c2410_chans[channel];
+
+	check_channel(channel);
+
+	pr_debug("%s: chan=%p, flags=%08x\n", __FUNCTION__, chan, flags);
+
+	chan->flags = flags;
+
+	return 0;
+}
+
+/* do we need to protect the settings of the fields from
+ * irq?
+*/
+
+int s3c2410_dma_set_opfn(dmach_t channel, s3c2410_dma_opfn_t rtn)
+{
+	s3c2410_dma_chan_t *chan = &s3c2410_chans[channel];
+
+	check_channel(channel);
+
+	pr_debug("%s: chan=%p, op rtn=%p\n", __FUNCTION__, chan, rtn);
+
+	chan->op_fn = rtn;
+
+	return 0;
+}
+
+int s3c2410_dma_set_buffdone_fn(dmach_t channel, s3c2410_dma_cbfn_t rtn)
+{
+	s3c2410_dma_chan_t *chan = &s3c2410_chans[channel];
+
+	check_channel(channel);
+
+	pr_debug("%s: chan=%p, callback rtn=%p\n", __FUNCTION__, chan, rtn);
+
+	chan->callback_fn = rtn;
+
+	return 0;
+}
+
+/* s3c2410_dma_devconfig
+ *
+ * configure the dma source/destination hardware type and address
+ *
+ * source:    S3C2410_DMASRC_HW: source is hardware
+ *            S3C2410_DMASRC_MEM: source is memory
+ *
+ * hwcfg:     the value for xxxSTCn register,
+ *            bit 0: 0=increment pointer, 1=leave pointer
+ *            bit 1: 0=soucre is AHB, 1=soucre is APB
+ *
+ * devaddr:   physical address of the source
+*/
+
+int s3c2410_dma_devconfig(int channel,
+			  s3c2410_dmasrc_t source,
+			  int hwcfg,
+			  unsigned long devaddr)
+{
+	s3c2410_dma_chan_t *chan = &s3c2410_chans[channel];
+
+	check_channel(channel);
+
+	pr_debug("%s: source=%d, hwcfg=%08x, devaddr=%08lx\n",
+		 __FUNCTION__, (int)source, hwcfg, devaddr);
+
+	chan->source = source;
+	chan->dev_addr = devaddr;
+
+	switch (source) {
+	case S3C2410_DMASRC_HW:
+		/* source is hardware */
+		pr_debug("%s: hw source, devaddr=%08lx, hwcfg=%d\n",
+			 __FUNCTION__, devaddr, hwcfg);
+		dma_wrreg(chan, S3C2410_DMA_DISRCC, hwcfg & 3);
+		dma_wrreg(chan, S3C2410_DMA_DISRC,  devaddr);
+		dma_wrreg(chan, S3C2410_DMA_DIDSTC, (0<<1) | (0<<0));
+
+		chan->addr_reg = dma_regaddr(chan, S3C2410_DMA_DIDST);
+		return 0;
+
+	case S3C2410_DMASRC_MEM:
+		/* source is memory */
+		pr_debug( "%s: mem source, devaddr=%08lx, hwcfg=%d\n",
+			  __FUNCTION__, devaddr, hwcfg);
+		dma_wrreg(chan, S3C2410_DMA_DISRCC, (0<<1) | (0<<0));
+		dma_wrreg(chan, S3C2410_DMA_DIDST,  devaddr);
+		dma_wrreg(chan, S3C2410_DMA_DIDSTC, hwcfg & 3);
+
+		chan->addr_reg = dma_regaddr(chan, S3C2410_DMA_DISRC);
+		return 0;
+	}
+
+	printk(KERN_ERR "dma%d: invalid source type (%d)\n", channel, source);
+	return -EINVAL;
+}
+
+/* initialisation code */
+
+static int __init s3c2410_init_dma(void)
+{
+	int channel;
+	s3c2410_dma_chan_t *cp;
+
+	printk("S3C2410 DMA Driver, (c) 2003-2004 Simtec Electronics\n");
+
+	dma_base = ioremap(S3C2410_PA_DMA, 0x200);
+	if (dma_base == NULL) {
+		printk(KERN_ERR "dma failed to remap register block\n");
+		return -ENOMEM;
+	}
+
+	for (channel = 0; channel < S3C2410_DMA_CHANNELS; channel++) {
+		cp = &s3c2410_chans[channel];
+
+		memset(cp, 0, sizeof(s3c2410_dma_chan_t));
+
+		/* dma channel irqs are in order.. */
+		cp->number = channel;
+		cp->irq    = channel + IRQ_DMA0;
+		cp->regs   = (unsigned long)dma_base + (channel*0x40);
+
+		/* point current stats somewhere */
+		cp->stats  = &cp->stats_store;
+		cp->stats_store.timeout_shortest = LONG_MAX;
+
+		/* basic channel configuration */
+
+		cp->load_timeout = 1<<18;
+
+		printk("DMA channel %d at %08lx, irq %d\n",
+		       cp->number, cp->regs, cp->irq);
+	}
+
+	return 0;
+}
+
+__initcall(s3c2410_init_dma);
diff -Nru a/arch/arm/mach-s3c2410/gpio.c b/arch/arm/mach-s3c2410/gpio.c
--- a/arch/arm/mach-s3c2410/gpio.c	2004-10-18 14:56:49 -07:00
+++ b/arch/arm/mach-s3c2410/gpio.c	2004-10-18 14:56:49 -07:00
@@ -19,6 +19,15 @@
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  *
+ * Changelog
+ *	13-Sep-2004  BJD  Implemented change of MISCCR
+ *	14-Sep-2004  BJD  Added getpin call
+ *	14-Sep-2004  BJD  Fixed bug in setpin() call
+ *	30-Sep-2004  BJD  Fixed cfgpin() mask bug
+ *	01-Oct-2004  BJD  Added getcfg() to get pin configuration
+ *	01-Oct-2004  BJD  Fixed mask bug in pullup() call
+ *	01-Oct-2004  BJD  Added getirq() to turn pin into irqno
+ *	04-Oct-2004  BJD  Added irq filter controls for GPIO
  */
 
 
@@ -36,23 +45,20 @@
 void s3c2410_gpio_cfgpin(unsigned int pin, unsigned int function)
 {
 	unsigned long base = S3C2410_GPIO_BASE(pin);
-	unsigned long shift = 1;
-	unsigned long mask = 3;
+	unsigned long mask;
 	unsigned long con;
 	unsigned long flags;
 
 	if (pin < S3C2410_GPIO_BANKB) {
-		shift = 0;
-		mask  = 1;
+		mask = 1 << S3C2410_GPIO_OFFSET(pin);
+	} else {
+		mask = 3 << S3C2410_GPIO_OFFSET(pin)*2;
 	}
 
-	mask <<= S3C2410_GPIO_OFFSET(pin);
-
 	local_irq_save(flags);
 
-	con = __raw_readl(base + 0x00);
-
-	con &= mask << shift;
+	con  = __raw_readl(base + 0x00);
+	con &= ~mask;
 	con |= function;
 
 	__raw_writel(con, base + 0x00);
@@ -60,6 +66,20 @@
 	local_irq_restore(flags);
 }
 
+unsigned int s3c2410_gpio_getcfg(unsigned int pin)
+{
+	unsigned long base = S3C2410_GPIO_BASE(pin);
+	unsigned long mask;
+
+	if (pin < S3C2410_GPIO_BANKB) {
+		mask = 1 << S3C2410_GPIO_OFFSET(pin);
+	} else {
+		mask = 3 << S3C2410_GPIO_OFFSET(pin)*2;
+	}
+
+	return __raw_readl(base) & mask;
+}
+
 void s3c2410_gpio_pullup(unsigned int pin, unsigned int to)
 {
 	unsigned long base = S3C2410_GPIO_BASE(pin);
@@ -73,7 +93,7 @@
 	local_irq_save(flags);
 
 	up = __raw_readl(base + 0x08);
-	up &= 1 << offs;
+	up &= ~(1L << offs);
 	up |= to << offs;
 	__raw_writel(up, base + 0x08);
 
@@ -90,9 +110,85 @@
 	local_irq_save(flags);
 
 	dat = __raw_readl(base + 0x04);
-	dat &= 1 << offs;
+	dat &= ~(1 << offs);
 	dat |= to << offs;
 	__raw_writel(dat, base + 0x04);
 
 	local_irq_restore(flags);
+}
+
+unsigned int s3c2410_gpio_getpin(unsigned int pin)
+{
+	unsigned long base = S3C2410_GPIO_BASE(pin);
+	unsigned long offs = S3C2410_GPIO_OFFSET(pin);
+
+	return __raw_readl(base + 0x04) & (1<< offs);
+}
+
+unsigned int s3c2410_modify_misccr(unsigned int clear, unsigned int change)
+{
+	unsigned long flags;
+	unsigned long misccr;
+
+	local_irq_save(flags);
+	misccr = __raw_readl(S3C2410_MISCCR);
+	misccr &= ~clear;
+	misccr ^= change;
+	__raw_writel(misccr, S3C2410_MISCCR);
+	local_irq_restore(flags);
+
+	return misccr;
+}
+
+int s3c2410_gpio_getirq(unsigned int pin)
+{
+	if (pin < S3C2410_GPF0 || pin > S3C2410_GPG15_EINT23)
+		return -1;	/* not valid interrupts */
+
+	if (pin < S3C2410_GPG0 && pin > S3C2410_GPF7)
+		return -1;	/* not valid pin */
+
+	if (pin < S3C2410_GPF4)
+		return (pin - S3C2410_GPF0) + IRQ_EINT0;
+
+	if (pin < S3C2410_GPG0)
+		return (pin - S3C2410_GPF4) + IRQ_EINT4;
+
+	return (pin - S3C2410_GPG0) + IRQ_EINT8;
+}
+
+int s3c2410_gpio_irqfilter(unsigned int pin, unsigned int on,
+			   unsigned int config)
+{
+	unsigned long reg = S3C2410_EINFLT0;
+	unsigned long flags;
+	unsigned long val;
+
+	if (pin < S3C2410_GPG8 || pin > S3C2410_GPG15)
+		return -1;
+
+	config &= 0xff;
+
+	pin -= S3C2410_GPG8_EINT16;
+	reg += pin & ~3;
+
+	local_irq_save(flags);
+
+	/* update filter width and clock source */
+
+	val = __raw_readl(reg);
+	val &= ~(0xff << ((pin & 3) * 8));
+	val |= config << ((pin & 3) * 8);
+	__raw_writel(val, reg);
+
+	/* update filter enable */
+
+	val = __raw_readl(S3C2410_EXTINT2);
+	val &= ~(1 << ((pin * 4) + 3));
+	val |= on << ((pin * 4) + 3);
+	__raw_writel(val, S3C2410_EXTINT2);
+
+	local_irq_restore(flags);
+
+	return 0;
 }
diff -Nru a/arch/arm/mach-s3c2410/irq.c b/arch/arm/mach-s3c2410/irq.c
--- a/arch/arm/mach-s3c2410/irq.c	2004-10-18 14:56:28 -07:00
+++ b/arch/arm/mach-s3c2410/irq.c	2004-10-18 14:56:28 -07:00
@@ -1,7 +1,7 @@
 /* linux/arch/arm/mach-s3c2410/irq.c
  *
- * Copyright (c) 2003 Simtec Electronics
- * Ben Dooks <ben@simtec.co.uk>
+ * Copyright (c) 2003,2004 Simtec Electronics
+ *	Ben Dooks <ben@simtec.co.uk>
  *
  * 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
@@ -17,7 +17,23 @@
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  *
- */
+ * Changelog:
+ *
+ *   22-Jul-2004  Ben Dooks <ben@simtec.co.uk>
+ *                Fixed compile warnings
+ *
+ *   22-Jul-2004  Roc Wu <cooloney@yahoo.com.cn>
+ *                Fixed s3c_extirq_type
+ *
+ *   21-Jul-2004  Arnaud Patard (Rtp) <arnaud.patard@rtp-net.org>
+ *                Addition of ADC/TC demux
+ *
+ *   04-Oct-2004  Klaus Fetscher <k.fetscher@fetron.de>
+ *		  Fix for set_irq_type() on low EINT numbers
+ *
+ *   05-Oct-2004  Ben Dooks <ben@simtec.co.uk>
+ *		  Tidy up KF's patch and sort out new release
+*/
 
 
 #include <linux/init.h>
@@ -34,11 +50,8 @@
 #include <asm/mach/irq.h>
 
 #include <asm/arch/regs-irq.h>
-#include <asm/arch/regs-lcd.h>
+#include <asm/arch/regs-gpio.h>
 
-#if 0
-#include <asm/debug-ll.h>
-#endif
 
 #define irqdbf(x...)
 #define irqdbf2(x...)
@@ -177,12 +190,84 @@
 	s3c_irq_unmask((irqno <= (IRQ_EINT7 - EXTINT_OFF)) ? IRQ_EINT4t7 : IRQ_EINT8t23);
 }
 
-/* todo - put type handler in here */
-
 static int
 s3c_irqext_type(unsigned int irq, unsigned int type)
 {
-	irqdbf("s3c_irqext_type: called for irq %d, type %d\n", irq, type);
+	unsigned long extint_reg;
+	unsigned long gpcon_reg;
+	unsigned long gpcon_offset, extint_offset;
+	unsigned long newvalue = 0, value;
+
+	if ((irq >= IRQ_EINT0) && (irq <= IRQ_EINT3))
+	{
+		gpcon_reg = S3C2410_GPFCON;
+		extint_reg = S3C2410_EXTINT0;
+		gpcon_offset = (irq - IRQ_EINT0) * 2;
+		extint_offset = (irq - IRQ_EINT0) * 4;
+	}
+	else if ((irq >= IRQ_EINT4) && (irq <= IRQ_EINT7))
+	{
+		gpcon_reg = S3C2410_GPFCON;
+		extint_reg = S3C2410_EXTINT0;
+		gpcon_offset = (irq - (EXTINT_OFF)) * 2;
+		extint_offset = (irq - (EXTINT_OFF)) * 4;
+	}
+	else if ((irq >= IRQ_EINT8) && (irq <= IRQ_EINT15))
+	{
+		gpcon_reg = S3C2410_GPGCON;
+		extint_reg = S3C2410_EXTINT1;
+		gpcon_offset = (irq - IRQ_EINT8) * 2;
+		extint_offset = (irq - IRQ_EINT8) * 4;
+	}
+	else if ((irq >= IRQ_EINT16) && (irq <= IRQ_EINT23))
+	{
+		gpcon_reg = S3C2410_GPGCON;
+		extint_reg = S3C2410_EXTINT2;
+		gpcon_offset = (irq - IRQ_EINT8) * 2;
+		extint_offset = (irq - IRQ_EINT16) * 4;
+	} else
+		return -1;
+
+	/* Set the GPIO to external interrupt mode */
+	value = __raw_readl(gpcon_reg);
+	value = (value & ~(3 << gpcon_offset)) | (0x02 << gpcon_offset);
+	__raw_writel(value, gpcon_reg);
+
+	/* Set the external interrupt to pointed trigger type */
+	switch (type)
+	{
+		case IRQT_NOEDGE:
+			printk(KERN_WARNING "No edge setting!\n");
+			break;
+
+		case IRQT_RISING:
+			newvalue = S3C2410_EXTINT_RISEEDGE;
+			break;
+
+		case IRQT_FALLING:
+			newvalue = S3C2410_EXTINT_FALLEDGE;
+			break;
+
+		case IRQT_BOTHEDGE:
+			newvalue = S3C2410_EXTINT_BOTHEDGE;
+			break;
+
+		case IRQT_LOW:
+			newvalue = S3C2410_EXTINT_LOWLEV;
+			break;
+
+		case IRQT_HIGH:
+			newvalue = S3C2410_EXTINT_HILEV;
+			break;
+
+		default:
+			printk(KERN_ERR "No such irq type %d", type);
+			return -1;
+	}
+
+	value = __raw_readl(extint_reg);
+	value = (value & ~(7 << extint_offset)) | (newvalue << extint_offset);
+	__raw_writel(value, extint_reg);
 
 	return 0;
 }
@@ -194,6 +279,13 @@
 	.type	    = s3c_irqext_type
 };
 
+static struct irqchip s3c_irq_eint0t4 = {
+	.ack	   = s3c_irq_ack,
+	.mask	   = s3c_irq_mask,
+	.unmask	   = s3c_irq_unmask,
+	.type	   = s3c_irqext_type
+};
+
 /* mask values for the parent registers for each of the interrupt types */
 
 #define INTMSK_UART0	 (1UL << (IRQ_UART0 - IRQ_EINT0))
@@ -368,37 +460,37 @@
 	.ack	    = s3c_irq_adc_ack,
 };
 
-#if 0
-/* LCD (todo) */
-
-static void
-s3c_irq_lcd_mask(unsigned int irqno)
+/* irq demux for adc */
+static void s3c_irq_demux_adc(unsigned int irq,
+			      struct irqdesc *desc,
+			      struct pt_regs *regs)
 {
+	unsigned int subsrc, submsk;
+	unsigned int offset = 9;
+	struct irqdesc *mydesc;
 
-}
-
-static void
-s3c_irq_lcd_unmask(unsigned int irqno)
-{
+	/* read the current pending interrupts, and the mask
+	 * for what it is available */
 
-}
+	subsrc = __raw_readl(S3C2410_SUBSRCPND);
+	submsk = __raw_readl(S3C2410_INTSUBMSK);
 
-static void
-s3c_irq_lcd_ack(unsigned int irqno)
-{
+	subsrc &= ~submsk;
+	subsrc >>= offset;
+	subsrc &= 3;
 
+	if (subsrc != 0) {
+		if (subsrc & 1) {
+			mydesc = irq_desc + IRQ_TC;
+			mydesc->handle( IRQ_TC, mydesc, regs);
+		}
+		if (subsrc & 2) {
+			mydesc = irq_desc + IRQ_ADC;
+			mydesc->handle(IRQ_ADC, mydesc, regs);
+		}
+	}
 }
 
-static struct irqchip s3c_irq_lcd = {
-	.mask	    = s3c_irq_lcd_mask,
-	.unmask	    = s3c_irq_lcd_unmask,
-	.ack	    = s3c_irq_lcd_ack,
-};
-#endif
-
-/* irq demux */
-
-
 static void s3c_irq_demux_uart(unsigned int start,
 			       struct pt_regs *regs)
 {
@@ -466,11 +558,15 @@
 	s3c_irq_demux_uart(IRQ_S3CUART_RX2, regs);
 }
 
-
+/* s3c2410_init_irq
+ *
+ * Initialise S3C2410 IRQ system
+*/
 
 void __init s3c2410_init_irq(void)
 {
 	unsigned long pend;
+	unsigned long last;
 	int irqno;
 	int i;
 
@@ -478,48 +574,51 @@
 
 	/* first, clear all interrupts pending... */
 
+	last = 0;
 	for (i = 0; i < 4; i++) {
 		pend = __raw_readl(S3C2410_EINTPEND);
-		if (pend == 0)
+
+		if (pend == 0 || pend == last)
 			break;
+
 		__raw_writel(pend, S3C2410_EINTPEND);
 		printk("irq: clearing pending ext status %08x\n", (int)pend);
+		last = pend;
 	}
 
+	last = 0;
 	for (i = 0; i < 4; i++) {
 		pend = __raw_readl(S3C2410_INTPND);
-		if (pend == 0)
+
+		if (pend == 0 || pend == last)
 			break;
+
 		__raw_writel(pend, S3C2410_SRCPND);
 		__raw_writel(pend, S3C2410_INTPND);
 		printk("irq: clearing pending status %08x\n", (int)pend);
+		last = pend;
 	}
 
+	last = 0;
 	for (i = 0; i < 4; i++) {
 		pend = __raw_readl(S3C2410_SUBSRCPND);
 
-		if (pend == 0)
+		if (pend == 0 || pend == last)
 			break;
 
 		printk("irq: clearing subpending status %08x\n", (int)pend);
 		__raw_writel(pend, S3C2410_SUBSRCPND);
+		last = pend;
 	}
 
 	/* register the main interrupts */
 
 	irqdbf("s3c2410_init_irq: registering s3c2410 interrupt handlers\n");
 
-	for (irqno = IRQ_EINT0; irqno < IRQ_ADCPARENT; irqno++) {
+	for (irqno = IRQ_BATT_FLT; irqno <= IRQ_ADCPARENT; irqno++) {
 		/* set all the s3c2410 internal irqs */
 
 		switch (irqno) {
-
-		case IRQ_EINT4t7:
-		case IRQ_EINT8t23:
-			/* these are already dealt with, so should never
-			 * appear */
-			break;
-
 			/* deal with the special IRQs (cascaded) */
 
 		case IRQ_UART0:
@@ -549,11 +648,17 @@
 	set_irq_chained_handler(IRQ_UART0, s3c_irq_demux_uart0);
 	set_irq_chained_handler(IRQ_UART1, s3c_irq_demux_uart1);
 	set_irq_chained_handler(IRQ_UART2, s3c_irq_demux_uart2);
-	//set_irq_chained_handler(IRQ_LCD, s3c_irq_demux_);
-	//set_irq_chained_handler(IRQ_ADCPARENT, s3c_irq_demux_);
+	set_irq_chained_handler(IRQ_ADCPARENT, s3c_irq_demux_adc);
 
 
 	/* external interrupts */
+
+	for (irqno = IRQ_EINT0; irqno <= IRQ_EINT3; irqno++) {
+		irqdbf("registering irq %d (ext int)\n", irqno);
+		set_irq_chip(irqno, &s3c_irq_eint0t4);
+		set_irq_handler(irqno, do_edge_IRQ);
+		set_irq_flags(irqno, IRQF_VALID);
+	}
 
 	for (irqno = IRQ_EINT4; irqno <= IRQ_EINT23; irqno++) {
 		irqdbf("registering irq %d (extended s3c irq)\n", irqno);
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-10-18 14:56:32 -07:00
+++ b/arch/arm/mach-s3c2410/mach-bast.c	2004-10-18 14:56:32 -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,9 @@
  * published by the Free Software Foundation.
  *
  * Modifications:
+ *     14-Sep-2004 BJD  USB power control
+ *     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 +26,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 +43,9 @@
 #include <asm/arch/regs-serial.h>
 
 #include "s3c2410.h"
+#include "devs.h"
+#include "cpu.h"
+#include "usb-simtec.h"
 
 /* macros for virtual address mods for the io space entries */
 #define VA_C5(item) ((item) + BAST_VAM_CS5)
@@ -154,6 +161,7 @@
 	[1] = {
 		.hwport	     = 1,
 		.flags	     = 0,
+
 		.clock	     = &bast_serial_clock,
 		.ucon	     = UCON,
 		.ulcon	     = ULCON,
@@ -170,19 +178,51 @@
 	}
 };
 
+/* NOR Flash on BAST board */
+
+static struct resource bast_nor_resource[] = {
+	[0] = {
+		.start = S3C2410_CS1 + 0x4000000,
+		.end   = S3C2410_CS1 + 0x4000000 + (32*1024*1024) - 1,
+		.flags = IORESOURCE_MEM,
+	}
+};
+
+static struct platform_device bast_device_nor = {
+	.name		= "bast-nor",
+	.id		= -1,
+	.num_resources	= ARRAY_SIZE(bast_nor_resource),
+	.resource	= bast_nor_resource,
+};
+
+/* Standard BAST devices */
+
+static struct platform_device *bast_devices[] __initdata = {
+	&s3c_device_usb,
+	&s3c_device_lcd,
+	&s3c_device_wdt,
+	&s3c_device_i2c,
+	&s3c_device_iis,
+ 	&s3c_device_rtc,
+	&bast_device_nor
+};
+
+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;
+	s3c24xx_init_io(bast_iodesc, ARRAY_SIZE(bast_iodesc));
+	s3c2410_init_uarts(bast_uartcfgs, ARRAY_SIZE(bast_uartcfgs));
+	s3c2410_set_board(&bast_board);
+	usb_simtec_init();
 }
 
 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-10-18 14:56:49 -07:00
+++ b/arch/arm/mach-s3c2410/mach-h1940.c	2004-10-18 14:56:49 -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,8 @@
  *     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
+ *     04-Sep-2004 BJD  Changed uart init, renamed ipaq_ -> h1940_
 */
 
 #include <linux/kernel.h>
@@ -39,8 +41,10 @@
 #include <asm/arch/regs-serial.h>
 
 #include "s3c2410.h"
+#include "devs.h"
+#include "cpu.h"
 
-static struct map_desc ipaq_iodesc[] __initdata = {
+static struct map_desc h1940_iodesc[] __initdata = {
 	/* nothing here yet */
 };
 
@@ -48,7 +52,7 @@
 #define ULCON S3C2410_LCON_CS8 | S3C2410_LCON_PNONE | S3C2410_LCON_STOPB
 #define UFCON S3C2410_UFCON_RXTRIG8 | S3C2410_UFCON_FIFOMODE
 
-static struct s3c2410_uartcfg ipaq_uartcfgs[] = {
+static struct s3c2410_uartcfg h1940_uartcfgs[] = {
 	[0] = {
 		.hwport	     = 0,
 		.flags	     = 0,
@@ -77,21 +81,35 @@
 };
 
 
-void __init ipaq_map_io(void)
+
+
+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 h1940_map_io(void)
 {
-	s3c2410_map_io(ipaq_iodesc, ARRAY_SIZE(ipaq_iodesc));
-	s3c2410_uartcfgs = ipaq_uartcfgs;
+	s3c24xx_init_io(h1940_iodesc, ARRAY_SIZE(h1940_iodesc));
+	s3c2410_init_uarts(h1940_uartcfgs, ARRAY_SIZE(h1940_uartcfgs));
+	s3c2410_set_board(&h1940_board);
 }
 
-void __init ipaq_init_irq(void)
+void __init h1940_init_irq(void)
 {
-	//llprintk("ipaq_init_irq:\n");
-
 	s3c2410_init_irq();
 
 }
 
-void __init ipaq_init_time(void)
+void __init h1940_init_time(void)
 {
 	s3c2410_init_time();
 }
@@ -100,7 +118,7 @@
      MAINTAINER("Ben Dooks <ben@fluff.org>")
      BOOT_MEM(S3C2410_SDRAM_PA, S3C2410_PA_UART, S3C2410_VA_UART)
      BOOT_PARAMS(S3C2410_SDRAM_PA + 0x100)
-     MAPIO(ipaq_map_io)
-     INITIRQ(ipaq_init_irq)
-     INITTIME(ipaq_init_time)
+     MAPIO(h1940_map_io)
+     INITIRQ(h1940_init_irq)
+     INITTIME(h1940_init_time)
 MACHINE_END
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-10-18 14:56:31 -07:00
+++ b/arch/arm/mach-s3c2410/mach-smdk2410.c	2004-10-18 14:56:31 -07:00
@@ -47,7 +47,8 @@
 #include <asm/arch/regs-serial.h>
 
 #include "s3c2410.h"
-
+#include "devs.h"
+#include "cpu.h"
 
 static struct map_desc smdk2410_iodesc[] __initdata = {
   /* nothing here yet */
@@ -87,11 +88,24 @@
 	}
 };
 
+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;
+	s3c24xx_init_io(smdk2410_iodesc, ARRAY_SIZE(smdk2410_iodesc));
+	s3c2410_init_uarts(smdk2410_uartcfgs, ARRAY_SIZE(smdk2410_uartcfgs));
+	s3c2410_set_board(&smdk2410_board);
 }
 
 void __init smdk2410_init_irq(void)
@@ -113,3 +127,5 @@
      INITIRQ(smdk2410_init_irq)
      INITTIME(smdk2410_init_time)
 MACHINE_END
+
+
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-10-18 14:56:49 -07:00
+++ b/arch/arm/mach-s3c2410/mach-vr1000.c	2004-10-18 14:56:49 -07:00
@@ -11,13 +11,10 @@
  * published by the Free Software Foundation.
  *
  * Modifications:
+ *     14-Sep-2004 BJD  USB Power control
+ *     04-Sep-2004 BJD  Added new uart init, and io init
+ *     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 +41,9 @@
 #include <asm/arch/regs-serial.h>
 
 #include "s3c2410.h"
+#include "devs.h"
+#include "cpu.h"
+#include "usb-simtec.h"
 
 /* macros for virtual address mods for the io space entries */
 #define VA_C5(item) ((item) + BAST_VAM_CS5)
@@ -143,19 +143,31 @@
 	}
 };
 
+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;
+	s3c24xx_init_io(vr1000_iodesc, ARRAY_SIZE(vr1000_iodesc));
+	s3c2410_init_uarts(vr1000_uartcfgs, ARRAY_SIZE(vr1000_uartcfgs));
+	s3c2410_set_board(&vr1000_board);
+	usb_simtec_init();
 }
 
 void __init vr1000_init_irq(void)
 {
-	//llprintk("vr1000init_irq:\n");
-
 	s3c2410_init_irq();
-
 }
 
 void __init vr1000_init_time(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-10-18 14:56:32 -07:00
+++ b/arch/arm/mach-s3c2410/s3c2410.c	2004-10-18 14:56:32 -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,9 @@
 #include <asm/arch/regs-clock.h>
 #include <asm/arch/regs-serial.h>
 
+#include "s3c2410.h"
+#include "cpu.h"
+
 int s3c2410_clock_tick_rate = 12*1000*1000;  /* current timers at 12MHz */
 
 /* serial port setup */
@@ -47,33 +51,14 @@
 unsigned long s3c2410_hclk;
 unsigned long s3c2410_pclk;
 
-#ifndef MHZ
-#define MHZ (1000*1000)
-#endif
-
-#define print_mhz(m) ((m) / MHZ), ((m / 1000) % 1000)
-
-#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(USBHOST),
+	IODESC_ENT(CLKPWR),
+	IODESC_ENT(LCD),
+	IODESC_ENT(UART),
+	IODESC_ENT(TIMER),
+	IODESC_ENT(ADC),
+	IODESC_ENT(WATCHDOG)
 };
 
 static struct resource s3c_uart0_resource[] = {
@@ -146,14 +131,16 @@
 	&s3c_uart2
 };
 
-void __init s3c2410_map_io(struct map_desc *mach_desc, int size)
+void __init s3c2410_map_io(struct map_desc *mach_desc, int mach_size)
 {
 	unsigned long tmp;
 
 	/* register our io-tables */
 
 	iotable_init(s3c2410_iodesc, ARRAY_SIZE(s3c2410_iodesc));
-	iotable_init(mach_desc, size);
+	iotable_init(mach_desc, mach_size);
+
+	printk("machine_initted %p,%d\n", mach_desc, mach_size);
 
 	/* now we've got our machine bits initialised, work out what
 	 * clocks we've got */
@@ -175,16 +162,41 @@
 	       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)
+void s3c2410_init_uarts(struct s3c2410_uartcfg *cfg, int no)
+{
+	s3c2410_uartcfgs = cfg;
+}
+
+int __init s3c2410_init(void)
 {
 	int ret;
 
 	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;
 }
-
-arch_initcall(s3c2410_init);
diff -Nru a/arch/arm/mach-s3c2410/s3c2410.h b/arch/arm/mach-s3c2410/s3c2410.h
--- a/arch/arm/mach-s3c2410/s3c2410.h	2004-10-18 14:56:29 -07:00
+++ b/arch/arm/mach-s3c2410/s3c2410.h	2004-10-18 14:56:29 -07:00
@@ -1,4 +1,19 @@
-
+/* arch/arm/mach-s3c2410/s3c2410.h
+ *
+ * Copyright (c) 2004 Simtec Electronics
+ * Ben Dooks <ben@simtec.co.uk>
+ *
+ * Header file for s3c2410 machine directory
+ *
+ * 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.
+ *
+ * Modifications:
+ *     18-Aug-2004 BJD  Created initial version
+ *     20-Aug-2004 BJD  Added s3c2410_board struct
+ *     04-Sep-2004 BJD  Added s3c2410_init_uarts() call
+*/
 
 extern void s3c2410_map_io(struct map_desc *, int count);
 
@@ -6,3 +21,18 @@
 
 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);
+
+extern void s3c2410_init_uarts(struct s3c2410_uartcfg *cfg, int no);
diff -Nru a/arch/arm/mach-s3c2410/s3c2440-dsc.c b/arch/arm/mach-s3c2410/s3c2440-dsc.c
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/arch/arm/mach-s3c2410/s3c2440-dsc.c	2004-10-18 14:57:24 -07:00
@@ -0,0 +1,57 @@
+/* linux/arch/arm/mach-s3c2410/s3c2440-dsc.c
+ *
+ * Copyright (c) 2004 Simtec Electronics
+ *   Ben Dooks <ben@simtec.co.uk>
+ *
+ * Samsung S3C2440 Drive Strength Control support
+ *
+ * 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.
+ *
+ * Modifications:
+ *     29-Aug-2004 BJD  Start of drive-strength control
+*/
+
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/interrupt.h>
+#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>
+#include <asm/mach/irq.h>
+
+#include <asm/hardware.h>
+#include <asm/io.h>
+#include <asm/irq.h>
+
+#include <asm/arch/regs-gpio.h>
+#include <asm/arch/regs-dsc.h>
+
+#include "s3c2440.h"
+#include "cpu.h"
+
+int s3c2440_set_dsc(unsigned int pin, unsigned int value)
+{
+	unsigned long base;
+	unsigned long val;
+	unsigned long flags;
+	unsigned long mask;
+
+	base = (pin & S3C2440_SELECT_DSC1) ? S3C2440_DSC1 : S3C2440_DSC0;
+	mask = 3 << S3C2440_DSC_GETSHIFT(pin);
+
+	local_irq_save(flags);
+
+	val = __raw_readl(base);
+	val &= ~mask;
+	val |= value & mask;
+	__raw_writel(val, base);
+
+	local_irq_restore(flags);
+	return 0;
+}
diff -Nru a/arch/arm/mach-s3c2410/s3c2440.c b/arch/arm/mach-s3c2410/s3c2440.c
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/arch/arm/mach-s3c2410/s3c2440.c	2004-10-18 14:57:21 -07:00
@@ -0,0 +1,192 @@
+/* linux/arch/arm/mach-s3c2410/s3c2440.c
+ *
+ * Copyright (c) 2004 Simtec Electronics
+ *   Ben Dooks <ben@simtec.co.uk>
+ *
+ * Samsung S3C2440 Mobile CPU support
+ *
+ * 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.
+ *
+ * Modifications:
+ *     24-Aug-2004 BJD  Start of s3c2440 support
+*/
+
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/interrupt.h>
+#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>
+#include <asm/mach/irq.h>
+
+#include <asm/hardware.h>
+#include <asm/io.h>
+#include <asm/irq.h>
+
+#include <asm/arch/regs-clock.h>
+#include <asm/arch/regs-serial.h>
+
+#include "s3c2440.h"
+#include "cpu.h"
+
+int s3c2440_clock_tick_rate = 12*1000*1000;  /* current timers at 12MHz */
+
+/* clock info */
+
+unsigned long s3c2440_baseclk = 12*1000*1000;  /* assume base is 12MHz */
+unsigned long s3c2440_hdiv;
+
+unsigned long s3c2440_fclk;
+unsigned long s3c2440_hclk;
+unsigned long s3c2440_pclk;
+
+static struct map_desc s3c2440_iodesc[] __initdata = {
+	IODESC_ENT(USBHOST),
+	IODESC_ENT(CLKPWR),
+	IODESC_ENT(LCD),
+	IODESC_ENT(TIMER),
+	IODESC_ENT(ADC),
+};
+
+static struct resource s3c_uart0_resource[] = {
+	[0] = {
+		.start = S3C2410_PA_UART0,
+		.end   = S3C2410_PA_UART0 + 0x3fff,
+		.flags = IORESOURCE_MEM,
+	},
+	[1] = {
+		.start = IRQ_S3CUART_RX0,
+		.end   = IRQ_S3CUART_ERR0,
+		.flags = IORESOURCE_IRQ,
+	}
+
+};
+
+static struct resource s3c_uart1_resource[] = {
+	[0] = {
+		.start = S3C2410_PA_UART1,
+		.end   = S3C2410_PA_UART1 + 0x3fff,
+		.flags = IORESOURCE_MEM,
+	},
+	[1] = {
+		.start = IRQ_S3CUART_RX1,
+		.end   = IRQ_S3CUART_ERR1,
+		.flags = IORESOURCE_IRQ,
+	}
+};
+
+static struct resource s3c_uart2_resource[] = {
+	[0] = {
+		.start = S3C2410_PA_UART2,
+		.end   = S3C2410_PA_UART2 + 0x3fff,
+		.flags = IORESOURCE_MEM,
+	},
+	[1] = {
+		.start = IRQ_S3CUART_RX2,
+		.end   = IRQ_S3CUART_ERR2,
+		.flags = IORESOURCE_IRQ,
+	}
+};
+
+/* our uart devices */
+
+static struct platform_device s3c_uart0 = {
+	.name		  = "s3c2440-uart",
+	.id		  = 0,
+	.num_resources	  = ARRAY_SIZE(s3c_uart0_resource),
+	.resource	  = s3c_uart0_resource,
+};
+
+
+static struct platform_device s3c_uart1 = {
+	.name		  = "s3c2440-uart",
+	.id		  = 1,
+	.num_resources	  = ARRAY_SIZE(s3c_uart1_resource),
+	.resource	  = s3c_uart1_resource,
+};
+
+static struct platform_device s3c_uart2 = {
+	.name		  = "s3c2440-uart",
+	.id		  = 2,
+	.num_resources	  = ARRAY_SIZE(s3c_uart2_resource),
+	.resource	  = s3c_uart2_resource,
+};
+
+static struct platform_device *uart_devices[] __initdata = {
+	&s3c_uart0,
+	&s3c_uart1,
+	&s3c_uart2
+};
+
+void __init s3c2440_map_io(struct map_desc *mach_desc, int size)
+{
+	unsigned long tmp;
+	unsigned long camdiv;
+
+	/* register our io-tables */
+
+	iotable_init(s3c2440_iodesc, ARRAY_SIZE(s3c2440_iodesc));
+	iotable_init(mach_desc, size);
+
+	/* now we've got our machine bits initialised, work out what
+	 * clocks we've got */
+
+	s3c2440_fclk = s3c2410_get_pll(__raw_readl(S3C2410_MPLLCON),
+				       s3c2440_baseclk);
+
+	tmp = __raw_readl(S3C2410_CLKDIVN);
+	camdiv = __raw_readl(S3C2440_CAMDIVN);
+
+	/* work out clock scalings */
+
+	switch (tmp & S3C2440_CLKDIVN_HDIVN_MASK) {
+	case S3C2440_CLKDIVN_HDIVN_1:
+		s3c2440_hdiv = 1;
+		break;
+
+	case S3C2440_CLKDIVN_HDIVN_2:
+		s3c2440_hdiv = 1;
+		break;
+
+	case S3C2440_CLKDIVN_HDIVN_4_8:
+		s3c2440_hdiv = (camdiv & S3C2440_CAMDIVN_HCLK4_HALF) ? 8 : 4;
+		break;
+
+	case S3C2440_CLKDIVN_HDIVN_3_6:
+		s3c2440_hdiv = (camdiv & S3C2440_CAMDIVN_HCLK4_HALF) ? 6 : 3;
+		break;
+	}
+
+	s3c2440_hclk = s3c2440_fclk / s3c2440_hdiv;
+	s3c2440_pclk = s3c2440_hclk / ((tmp & S3C2440_CLKDIVN_PDIVN) ? 2 : 1);
+
+	/* print brieft summary of clocks, etc */
+
+	printk("S3C2440: core %ld.%03ld MHz, memory %ld.%03ld MHz, peripheral %ld.%03ld MHz\n",
+	       print_mhz(s3c2440_fclk), print_mhz(s3c2440_hclk),
+	       print_mhz(s3c2440_pclk));
+}
+
+
+
+int __init s3c2440_init(void)
+{
+	int ret;
+
+	printk("S3C2440: Initialising architecture\n");
+
+	ret = platform_add_devices(uart_devices, ARRAY_SIZE(uart_devices));
+	if (ret)
+		return ret;
+
+	// todo: board specific inits?
+
+	return ret;
+}
+
diff -Nru a/arch/arm/mach-s3c2410/s3c2440.h b/arch/arm/mach-s3c2410/s3c2440.h
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/arch/arm/mach-s3c2410/s3c2440.h	2004-10-18 14:57:23 -07:00
@@ -0,0 +1,18 @@
+/* arch/arm/mach-s3c2410/s3c2440.h
+ *
+ * Copyright (c) 2004 Simtec Electronics
+ * Ben Dooks <ben@simtec.co.uk>
+ *
+ * Header file for s3c2440 cpu support
+ *
+ * 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.
+ *
+ * Modifications:
+ *     24-Aug-2004 BJD  Start of S3C2440 CPU support
+*/
+
+extern void s3c2440_init_irq(void);
+
+extern void s3c2440_init_time(void);
diff -Nru a/arch/arm/mach-s3c2410/time.c b/arch/arm/mach-s3c2410/time.c
--- a/arch/arm/mach-s3c2410/time.c	2004-10-18 14:56:28 -07:00
+++ b/arch/arm/mach-s3c2410/time.c	2004-10-18 14:56:28 -07:00
@@ -31,14 +31,12 @@
 #include <asm/irq.h>
 #include <asm/arch/map.h>
 #include <asm/arch/regs-timer.h>
+#include <asm/arch/regs-irq.h>
 #include <asm/mach/time.h>
 
 static unsigned long timer_startval;
 static unsigned long timer_ticks_usec;
 
-#ifdef CONFIG_S3C2410_RTC
-extern void s3c2410_rtc_check();
-#endif
 
 /* with an 12MHz clock, we get 12 ticks per-usec
  */
@@ -49,14 +47,29 @@
  * will have been disabled by do_gettimeoffset()
  * IRQs are disabled before entering here from do_gettimeofday()
  */
+
+#define SRCPND_TIMER4 (1<<(IRQ_TIMER4 - IRQ_EINT0))
+
 static unsigned long s3c2410_gettimeoffset (void)
 {
 	unsigned long tdone;
 	unsigned long usec;
+	unsigned long irqpend;
 
 	/* work out how many ticks have gone since last timer interrupt */
 
 	tdone = timer_startval - __raw_readl(S3C2410_TCNTO(4));
+
+	/* check to see if there is an interrupt pending */
+
+	irqpend = __raw_readl(S3C2410_SRCPND);
+	if (irqpend & SRCPND_TIMER4) {
+		/* re-read the timer, and try and fix up for the missed
+		 * interrupt */
+
+		tdone = timer_startval - __raw_readl(S3C2410_TCNTO(4));
+		tdone += 1<<16;
+	}
 
 	/* currently, tcnt is in 12MHz units, but this may change
 	 * for non-bast machines...
diff -Nru a/arch/arm/mach-s3c2410/usb-simtec.c b/arch/arm/mach-s3c2410/usb-simtec.c
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/arch/arm/mach-s3c2410/usb-simtec.c	2004-10-18 14:57:23 -07:00
@@ -0,0 +1,123 @@
+/* linux/arch/arm/mach-s3c2410/usb-simtec.c
+ *
+ * Copyright (c) 2004 Simtec Electronics
+ *   Ben Dooks <ben@simtec.co.uk>
+ *
+ * http://www.simtec.co.uk/products/EB2410ITX/
+ *
+ * Simtec BAST and Thorcom VR1000 USB port support functions
+ *
+ * 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.
+ *
+ * Modifications:
+ *	14-Sep-2004 BJD  Created
+*/
+
+#define DEBUG
+
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/interrupt.h>
+#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>
+#include <asm/mach/irq.h>
+
+#include <asm/arch/bast-map.h>
+#include <asm/arch/bast-irq.h>
+#include <asm/arch/usb-control.h>
+#include <asm/arch/regs-gpio.h>
+
+#include <asm/hardware.h>
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/mach-types.h>
+
+#include "devs.h"
+#include "usb-simtec.h"
+
+/* control power and monitor over-current events on various Simtec
+ * designed boards.
+*/
+
+static void
+usb_simtec_powercontrol(int port, int to)
+{
+	pr_debug("usb_simtec_powercontrol(%d,%d)\n", port, to);
+
+	if (port == 1) {
+		s3c2410_gpio_setpin(S3C2410_GPB4, to ? 0:1);
+		pr_debug("GPBDAT now %08x\n", __raw_readl(S3C2410_GPBDAT));
+	}
+}
+
+static irqreturn_t
+usb_simtec_ocirq(int irq, void *pw, struct pt_regs *regs)
+{
+	struct s3c2410_hcd_info *info = (struct s3c2410_hcd_info *)pw;
+
+	if (s3c2410_gpio_getpin(S3C2410_GPG10) == 0) {
+		pr_debug("usb_simtec: over-current irq (oc detected)\n");
+		s3c2410_report_oc(info, 3);
+	} else {
+		pr_debug("usb_simtec: over-current irq (oc cleared)\n");
+	}
+
+	return IRQ_HANDLED;
+}
+
+static void usb_simtec_enableoc(struct s3c2410_hcd_info *info, int on)
+{
+	int ret;
+
+	if (on) {
+		pr_debug("claiming usb overccurent\n");
+		ret = request_irq(IRQ_USBOC, usb_simtec_ocirq, SA_INTERRUPT,
+				  "usb-oc", info);
+		if (ret != 0) {
+			printk(KERN_ERR "failed to request usb oc irq\n");
+		}
+
+		set_irq_type(IRQ_USBOC, IRQT_BOTHEDGE);
+	} else {
+		free_irq(IRQ_USBOC, NULL);
+	}
+}
+
+static struct s3c2410_hcd_info usb_simtec_info = {
+	.port[0]	= {
+		.flags	= S3C_HCDFLG_USED
+	},
+	.port[1]	= {
+		.flags	= S3C_HCDFLG_USED
+	},
+
+	.power_control	= usb_simtec_powercontrol,
+	.enable_oc	= usb_simtec_enableoc,
+};
+
+
+int usb_simtec_init(void)
+{
+	printk("USB Power Control, (c) 2004 Simtec Electronics\n");
+	s3c_device_usb.dev.platform_data = &usb_simtec_info;
+
+	s3c2410_gpio_cfgpin(S3C2410_GPB4, S3C2410_GPB4_OUTP);
+	s3c2410_gpio_setpin(S3C2410_GPB4, 1);
+
+	pr_debug("GPB: CON=%08x, DAT=%08x\n",
+		 __raw_readl(S3C2410_GPBCON), __raw_readl(S3C2410_GPBDAT));
+
+	if (0) {
+		s3c2410_modify_misccr(S3C2410_MISCCR_USBHOST,
+				      S3C2410_MISCCR_USBDEV);
+	}
+
+	return 0;
+}
diff -Nru a/arch/arm/mach-s3c2410/usb-simtec.h b/arch/arm/mach-s3c2410/usb-simtec.h
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/arch/arm/mach-s3c2410/usb-simtec.h	2004-10-18 14:57:23 -07:00
@@ -0,0 +1,19 @@
+/* linux/arch/arm/mach-s3c2410/usb-simtec.c
+ *
+ * Copyright (c) 2004 Simtec Electronics
+ *   Ben Dooks <ben@simtec.co.uk>
+ *
+ * http://www.simtec.co.uk/products/EB2410ITX/
+ *
+ * Simtec BAST and Thorcom VR1000 USB port support functions
+ *
+ * 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.
+ *
+ * Modifications:
+ *	20-Aug-2004 BJD  Created
+*/
+
+extern int usb_simtec_init(void);
+
diff -Nru a/arch/arm/mach-sa1100/cpu-sa1100.c b/arch/arm/mach-sa1100/cpu-sa1100.c
--- a/arch/arm/mach-sa1100/cpu-sa1100.c	2004-10-18 14:55:54 -07:00
+++ b/arch/arm/mach-sa1100/cpu-sa1100.c	2004-10-18 14:55:54 -07:00
@@ -230,9 +230,7 @@
 }
 
 static struct cpufreq_driver sa1100_driver = {
-	.flags		= CPUFREQ_STICKY |
-			  CPUFREQ_PANIC_OUTOFSYNC | 
-			  CPUFREQ_PANIC_RESUME_OUTOFSYNC,
+	.flags		= CPUFREQ_STICKY,
 	.verify		= sa11x0_verify_speed,
 	.target		= sa1100_target,
 	.get		= sa11x0_getspeed,
diff -Nru a/arch/arm/mach-sa1100/cpu-sa1110.c b/arch/arm/mach-sa1100/cpu-sa1110.c
--- a/arch/arm/mach-sa1100/cpu-sa1110.c	2004-10-18 14:55:54 -07:00
+++ b/arch/arm/mach-sa1100/cpu-sa1110.c	2004-10-18 14:55:54 -07:00
@@ -329,9 +329,7 @@
 }
 
 static struct cpufreq_driver sa1110_driver = {
-	.flags		= CPUFREQ_STICKY |
-			  CPUFREQ_PANIC_OUTOFSYNC | 
-			  CPUFREQ_PANIC_RESUME_OUTOFSYNC,
+	.flags		= CPUFREQ_STICKY,
 	.verify		= sa11x0_verify_speed,
 	.target		= sa1110_target,
 	.get		= sa11x0_getspeed,
diff -Nru a/arch/arm/mach-sa1100/pm.c b/arch/arm/mach-sa1100/pm.c
--- a/arch/arm/mach-sa1100/pm.c	2004-10-18 14:56:19 -07:00
+++ b/arch/arm/mach-sa1100/pm.c	2004-10-18 14:56:19 -07:00
@@ -30,6 +30,7 @@
 #include <asm/hardware.h>
 #include <asm/memory.h>
 #include <asm/system.h>
+#include <asm/mach/time.h>
 
 extern void sa1100_cpu_suspend(void);
 extern void sa1100_cpu_resume(void);
@@ -44,7 +45,7 @@
  */
 enum {	SLEEP_SAVE_SP = 0,
 
-	SLEEP_SAVE_OSCR, SLEEP_SAVE_OIER,
+	SLEEP_SAVE_OIER,
 	SLEEP_SAVE_OSMR0, SLEEP_SAVE_OSMR1, SLEEP_SAVE_OSMR2, SLEEP_SAVE_OSMR3,
 
 	SLEEP_SAVE_GPDR, SLEEP_SAVE_GAFR,
@@ -58,18 +59,19 @@
 
 static int sa11x0_pm_enter(u32 state)
 {
-	unsigned long sleep_save[SLEEP_SAVE_SIZE];
-	unsigned long delta, gpio;
+	unsigned long gpio, sleep_save[SLEEP_SAVE_SIZE];
+	struct timespec delta, rtc;
 
 	if (state != PM_SUSPEND_MEM)
 		return -EINVAL;
 
 	/* preserve current time */
-	delta = xtime.tv_sec - RCNR;
+	rtc.tv_sec = RCNR;
+	rtc.tv_nsec = 0;
+	save_time_delta(&delta, &rtc);
 	gpio = GPLR;
 
 	/* save vital registers */
-	SAVE(OSCR);
 	SAVE(OSMR0);
 	SAVE(OSMR1);
 	SAVE(OSMR2);
@@ -131,11 +133,14 @@
 	RESTORE(OSMR1);
 	RESTORE(OSMR2);
 	RESTORE(OSMR3);
-	RESTORE(OSCR);
 	RESTORE(OIER);
 
+	/* OSMR0 is the system timer: make sure OSCR is sufficiently behind */
+	OSCR = OSMR0 - LATCH;
+
 	/* restore current time */
-	xtime.tv_sec = RCNR + delta;
+	rtc.tv_sec = RCNR;
+	restore_time_delta(&delta, &rtc);
 
 	return 0;
 }
diff -Nru a/arch/arm/mach-versatile/clock.c b/arch/arm/mach-versatile/clock.c
--- a/arch/arm/mach-versatile/clock.c	2004-10-18 14:55:54 -07:00
+++ b/arch/arm/mach-versatile/clock.c	2004-10-18 14:55:54 -07:00
@@ -87,8 +87,8 @@
 	if (clk->setvco) {
 		struct icst525_vco vco;
 
-		vco = icst525_khz_to_vco(clk->params, rate);
-		clk->rate = icst525_khz(clk->params, vco);
+		vco = icst525_khz_to_vco(clk->params, rate / 1000);
+		clk->rate = icst525_khz(clk->params, vco) * 1000;
 
 		printk("Clock %s: setting VCO reg params: S=%d R=%d V=%d\n",
 			clk->name, vco.s, vco.r, vco.v);
diff -Nru a/arch/arm/mach-versatile/core.c b/arch/arm/mach-versatile/core.c
--- a/arch/arm/mach-versatile/core.c	2004-10-18 14:56:29 -07:00
+++ b/arch/arm/mach-versatile/core.c	2004-10-18 14:56:29 -07:00
@@ -21,6 +21,7 @@
 #include <linux/config.h>
 #include <linux/init.h>
 #include <linux/device.h>
+#include <linux/dma-mapping.h>
 #include <linux/sysdev.h>
 #include <linux/interrupt.h>
 
@@ -31,6 +32,7 @@
 #include <asm/leds.h>
 #include <asm/mach-types.h>
 #include <asm/hardware/amba.h>
+#include <asm/hardware/amba_clcd.h>
 
 #include <asm/mach/arch.h>
 #include <asm/mach/flash.h>
@@ -325,6 +327,213 @@
 };
 #endif
 
+/*
+ * CLCD support.
+ */
+#define SYS_CLCD_MODE_MASK	(3 << 0)
+#define SYS_CLCD_MODE_5551	(0 << 0)
+#define SYS_CLCD_MODE_565	(1 << 0)
+#define SYS_CLCD_MODE_888	(2 << 0)
+#define SYS_CLCD_MODE_LT	(3 << 0)
+#define SYS_CLCD_NLCDIOON	(1 << 2)
+#define SYS_CLCD_VDDPOSSWITCH	(1 << 3)
+#define SYS_CLCD_PWR3V5SWITCH	(1 << 4)
+#define SYS_CLCD_ID_MASK	(0x1f << 8)
+#define SYS_CLCD_ID_SANYO_3_8	(0x00 << 8)
+#define SYS_CLCD_ID_UNKNOWN_8_4	(0x01 << 8)
+#define SYS_CLCD_ID_EPSON_2_2	(0x02 << 8)
+#define SYS_CLCD_ID_VGA		(0x1f << 8)
+
+static struct clcd_panel vga = {
+	.mode		= {
+		.name		= "VGA",
+		.refresh	= 60,
+		.xres		= 640,
+		.yres		= 480,
+		.pixclock	= 39721,
+		.left_margin	= 40,
+		.right_margin	= 24,
+		.upper_margin	= 32,
+		.lower_margin	= 11,
+		.hsync_len	= 96,
+		.vsync_len	= 2,
+		.sync		= 0,
+		.vmode		= FB_VMODE_NONINTERLACED,
+	},
+	.width		= -1,
+	.height		= -1,
+	.tim2		= TIM2_BCD | TIM2_IPC,
+	.cntl		= CNTL_LCDTFT | CNTL_LCDVCOMP(1),
+	.bpp		= 16,
+};
+
+static struct clcd_panel sanyo_3_8_in = {
+	.mode		= {
+		.name		= "Sanyo QVGA",
+		.refresh	= 116,
+		.xres		= 320,
+		.yres		= 240,
+		.pixclock	= 100000,
+		.left_margin	= 6,
+		.right_margin	= 6,
+		.upper_margin	= 5,
+		.lower_margin	= 5,
+		.hsync_len	= 6,
+		.vsync_len	= 6,
+		.sync		= 0,
+		.vmode		= FB_VMODE_NONINTERLACED,
+	},
+	.width		= -1,
+	.height		= -1,
+	.tim2		= TIM2_BCD,
+	.cntl		= CNTL_LCDTFT | CNTL_LCDVCOMP(1),
+	.bpp		= 16,
+};
+
+static struct clcd_panel epson_2_2_in = {
+	.mode		= {
+		.name		= "Epson QCIF",
+		.refresh	= 390,
+		.xres		= 176,
+		.yres		= 220,
+		.pixclock	= 62500,
+		.left_margin	= 3,
+		.right_margin	= 2,
+		.upper_margin	= 1,
+		.lower_margin	= 0,
+		.hsync_len	= 3,
+		.vsync_len	= 2,
+		.sync		= 0,
+		.vmode		= FB_VMODE_NONINTERLACED,
+	},
+	.width		= -1,
+	.height		= -1,
+	.tim2		= TIM2_BCD | TIM2_IPC,
+	.cntl		= CNTL_LCDTFT | CNTL_LCDVCOMP(1),
+	.bpp		= 16,
+};
+
+/*
+ * Detect which LCD panel is connected, and return the appropriate
+ * clcd_panel structure.  Note: we do not have any information on
+ * the required timings for the 8.4in panel, so we presently assume
+ * VGA timings.
+ */
+static struct clcd_panel *versatile_clcd_panel(void)
+{
+	unsigned long sys_clcd = IO_ADDRESS(VERSATILE_SYS_BASE) + VERSATILE_SYS_CLCD_OFFSET;
+	struct clcd_panel *panel = &vga;
+	u32 val;
+
+	val = readl(sys_clcd) & SYS_CLCD_ID_MASK;
+	if (val == SYS_CLCD_ID_SANYO_3_8)
+		panel = &sanyo_3_8_in;
+	else if (val == SYS_CLCD_ID_EPSON_2_2)
+		panel = &epson_2_2_in;
+	else if (val == SYS_CLCD_ID_VGA)
+		panel = &vga;
+	else {
+		printk(KERN_ERR "CLCD: unknown LCD panel ID 0x%08x, using VGA\n",
+			val);
+	}
+
+	return &vga;
+}
+
+/*
+ * Disable all display connectors on the interface module.
+ */
+static void versatile_clcd_disable(struct clcd_fb *fb)
+{
+	unsigned long sys_clcd = IO_ADDRESS(VERSATILE_SYS_BASE) + VERSATILE_SYS_CLCD_OFFSET;
+	u32 val;
+
+	val = readl(sys_clcd);
+	val &= ~SYS_CLCD_NLCDIOON | SYS_CLCD_PWR3V5SWITCH;
+	writel(val, sys_clcd);
+}
+
+/*
+ * Enable the relevant connector on the interface module.
+ */
+static void versatile_clcd_enable(struct clcd_fb *fb)
+{
+	unsigned long sys_clcd = IO_ADDRESS(VERSATILE_SYS_BASE) + VERSATILE_SYS_CLCD_OFFSET;
+	u32 val;
+
+	val = readl(sys_clcd);
+	val &= ~SYS_CLCD_MODE_MASK;
+
+	switch (fb->fb.var.green.length) {
+	case 5:
+#if 0
+		/*
+		 * For some undocumented reason, we need to select 565 mode
+		 * even when using 555 with VGA.  Maybe this is only true
+		 * for the VGA output and needs to be done for LCD panels?
+		 * I can't get an explaination from the people who should
+		 * know.
+		 */
+		val |= SYS_CLCD_MODE_5551;
+		break;
+#endif
+	case 6:
+		val |= SYS_CLCD_MODE_565;
+		break;
+	case 8:
+		val |= SYS_CLCD_MODE_888;
+		break;
+	}
+
+	/*
+	 * Set the MUX
+	 */
+	writel(val, sys_clcd);
+
+	/*
+	 * And now enable the PSUs
+	 */
+	val |= SYS_CLCD_NLCDIOON | SYS_CLCD_PWR3V5SWITCH;
+	writel(val, sys_clcd);
+}
+
+static unsigned long framesize = SZ_1M;
+
+static int versatile_clcd_setup(struct clcd_fb *fb)
+{
+	dma_addr_t dma;
+
+	fb->panel		= versatile_clcd_panel();
+
+	fb->fb.screen_base = dma_alloc_writecombine(&fb->dev->dev, framesize,
+						    &dma, GFP_KERNEL);
+	if (!fb->fb.screen_base) {
+		printk(KERN_ERR "CLCD: unable to map framebuffer\n");
+		return -ENOMEM;
+	}
+
+	fb->fb.fix.smem_start	= dma;
+	fb->fb.fix.smem_len	= framesize;
+
+	return 0;
+}
+
+static void versatile_clcd_remove(struct clcd_fb *fb)
+{
+	dma_free_writecombine(&fb->dev->dev, fb->fb.fix.smem_len,
+			      fb->fb.screen_base, fb->fb.fix.smem_start);
+}
+
+static struct clcd_board clcd_plat_data = {
+	.name		= "Versatile PB",
+	.check		= clcdfb_check,
+	.decode		= clcdfb_decode,
+	.disable	= versatile_clcd_disable,
+	.enable		= versatile_clcd_enable,
+	.setup		= versatile_clcd_setup,
+	.remove		= versatile_clcd_remove,
+};
+
 #define AMBA_DEVICE(name,busid,base,plat)			\
 static struct amba_device name##_device = {			\
 	.dev		= {					\
@@ -417,7 +626,7 @@
 /* DevChip Primecells */
 AMBA_DEVICE(smc,   "dev:00",  SMC,      NULL);
 AMBA_DEVICE(mpmc,  "dev:10",  MPMC,     NULL);
-AMBA_DEVICE(clcd,  "dev:20",  CLCD,     NULL);
+AMBA_DEVICE(clcd,  "dev:20",  CLCD,     &clcd_plat_data);
 AMBA_DEVICE(dmac,  "dev:30",  DMAC,     NULL);
 AMBA_DEVICE(sctl,  "dev:e0",  SCTL,     NULL);
 AMBA_DEVICE(wdog,  "dev:e1",  WATCHDOG, NULL);
diff -Nru a/arch/arm/mm/Kconfig b/arch/arm/mm/Kconfig
--- a/arch/arm/mm/Kconfig	2004-10-18 14:56:28 -07:00
+++ b/arch/arm/mm/Kconfig	2004-10-18 14:56:28 -07:00
@@ -43,7 +43,7 @@
 # ARM720T
 config CPU_ARM720T
 	bool "Support ARM720T processor" if !ARCH_CLPS711X && !ARCH_L7200 && !ARCH_CDB89712 && ARCH_INTEGRATOR
-	default y if ARCH_CLPS711X || ARCH_L7200 || ARCH_CDB89712
+	default y if ARCH_CLPS711X || ARCH_L7200 || ARCH_CDB89712 || ARCH_H720X
 	select CPU_32v4
 	select CPU_ABRT_LV4T
 	select CPU_CACHE_V4
@@ -59,7 +59,7 @@
 # ARM920T
 config CPU_ARM920T
 	bool "Support ARM920T processor" if !ARCH_S3C2410
-	depends on ARCH_INTEGRATOR || ARCH_S3C2410
+	depends on ARCH_INTEGRATOR || ARCH_S3C2410 || ARCH_IMX
 	default y if ARCH_S3C2410
 	select CPU_32v4
 	select CPU_ABRT_EV4T
@@ -220,7 +220,7 @@
 # XScale
 config CPU_XSCALE
 	bool
-	depends on ARCH_IOP3XX || ARCH_PXA || ARCH_IXP4XX
+	depends on ARCH_IOP3XX || ARCH_PXA || ARCH_IXP4XX || ARCH_IXP2000
 	default y
 	select CPU_32v5
 	select CPU_ABRT_EV5T
diff -Nru a/arch/arm/mm/Makefile b/arch/arm/mm/Makefile
--- a/arch/arm/mm/Makefile	2004-10-18 14:57:18 -07:00
+++ b/arch/arm/mm/Makefile	2004-10-18 14:57:18 -07:00
@@ -3,7 +3,8 @@
 #
 
 obj-y				:= consistent.o extable.o fault-armv.o \
-				   fault.o init.o ioremap.o mmap.o mm-armv.o
+				   fault.o flush.o init.o ioremap.o mmap.o \
+				   mm-armv.o
 
 obj-$(CONFIG_MODULES)		+= proc-syms.o
 
diff -Nru a/arch/arm/mm/abort-ev5tj.S b/arch/arm/mm/abort-ev5tj.S
--- a/arch/arm/mm/abort-ev5tj.S	2004-10-18 14:56:32 -07:00
+++ b/arch/arm/mm/abort-ev5tj.S	2004-10-18 14:56:32 -07:00
@@ -23,7 +23,6 @@
 	mrc	p15, 0, r0, c6, c0, 0		@ get FAR
 	bic	r1, r1, #1 << 11 | 1 << 10	@ clear bits 11 and 10 of FSR
 	tst	r3, #PSR_J_BIT			@ Java?
-	orrne	r1, r1, #1 << 11		@ always assume write
 	movne	pc, lr
 	tst	r3, #PSR_T_BIT			@ Thumb?
 	ldrneh	r3, [r2]			@ read aborted thumb instruction
diff -Nru a/arch/arm/mm/cache-v3.S b/arch/arm/mm/cache-v3.S
--- a/arch/arm/mm/cache-v3.S	2004-10-18 14:56:49 -07:00
+++ b/arch/arm/mm/cache-v3.S	2004-10-18 14:56:49 -07:00
@@ -57,6 +57,19 @@
  *	- end	 - virtual end address
  */
 ENTRY(v3_coherent_kern_range)
+	/* FALLTHROUGH */
+
+/*
+ *	coherent_user_range(start, end)
+ *
+ *	Ensure coherency between the Icache and the Dcache in the
+ *	region described by start.  If you have non-snooping
+ *	Harvard caches, you need to implement this function.
+ *
+ *	- start  - virtual start address
+ *	- end	 - virtual end address
+ */
+ENTRY(v3_coherent_user_range)
 	mov	pc, lr
 
 /*
@@ -116,6 +129,7 @@
 	.long	v3_flush_user_cache_all
 	.long	v3_flush_user_cache_range
 	.long	v3_coherent_kern_range
+	.long	v3_coherent_user_range
 	.long	v3_flush_kern_dcache_page
 	.long	v3_dma_inv_range
 	.long	v3_dma_clean_range
diff -Nru a/arch/arm/mm/cache-v4.S b/arch/arm/mm/cache-v4.S
--- a/arch/arm/mm/cache-v4.S	2004-10-18 14:56:28 -07:00
+++ b/arch/arm/mm/cache-v4.S	2004-10-18 14:56:28 -07:00
@@ -59,6 +59,19 @@
  *	- end	 - virtual end address
  */
 ENTRY(v4_coherent_kern_range)
+	/* FALLTHROUGH */
+
+/*
+ *	coherent_user_range(start, end)
+ *
+ *	Ensure coherency between the Icache and the Dcache in the
+ *	region described by start.  If you have non-snooping
+ *	Harvard caches, you need to implement this function.
+ *
+ *	- start  - virtual start address
+ *	- end	 - virtual end address
+ */
+ENTRY(v4_coherent_user_range)
 	mov	pc, lr
 
 /*
@@ -118,6 +131,7 @@
 	.long	v4_flush_user_cache_all
 	.long	v4_flush_user_cache_range
 	.long	v4_coherent_kern_range
+	.long	v4_coherent_user_range
 	.long	v4_flush_kern_dcache_page
 	.long	v4_dma_inv_range
 	.long	v4_dma_clean_range
diff -Nru a/arch/arm/mm/cache-v4wb.S b/arch/arm/mm/cache-v4wb.S
--- a/arch/arm/mm/cache-v4wb.S	2004-10-18 14:56:32 -07:00
+++ b/arch/arm/mm/cache-v4wb.S	2004-10-18 14:56:32 -07:00
@@ -121,6 +121,19 @@
  *	- end	 - virtual end address
  */
 ENTRY(v4wb_coherent_kern_range)
+	/* fall through */
+
+/*
+ *	coherent_user_range(start, end)
+ *
+ *	Ensure coherency between the Icache and the Dcache in the
+ *	region described by start.  If you have non-snooping
+ *	Harvard caches, you need to implement this function.
+ *
+ *	- start  - virtual start address
+ *	- end	 - virtual end address
+ */
+ENTRY(v4wb_coherent_user_range)
 	bic	r0, r0, #CACHE_DLINESIZE - 1
 1:	mcr	p15, 0, r0, c7, c10, 1		@ clean D entry
 	mcr	p15, 0, r0, c7, c6, 1		@ invalidate D entry
@@ -195,6 +208,7 @@
 	.long	v4wb_flush_user_cache_all
 	.long	v4wb_flush_user_cache_range
 	.long	v4wb_coherent_kern_range
+	.long	v4wb_coherent_user_range
 	.long	v4wb_flush_kern_dcache_page
 	.long	v4wb_dma_inv_range
 	.long	v4wb_dma_clean_range
diff -Nru a/arch/arm/mm/cache-v4wt.S b/arch/arm/mm/cache-v4wt.S
--- a/arch/arm/mm/cache-v4wt.S	2004-10-18 14:56:17 -07:00
+++ b/arch/arm/mm/cache-v4wt.S	2004-10-18 14:56:17 -07:00
@@ -97,6 +97,19 @@
  *	- end	 - virtual end address
  */
 ENTRY(v4wt_coherent_kern_range)
+	/* FALLTRHOUGH */
+
+/*
+ *	coherent_user_range(start, end)
+ *
+ *	Ensure coherency between the Icache and the Dcache in the
+ *	region described by start.  If you have non-snooping
+ *	Harvard caches, you need to implement this function.
+ *
+ *	- start  - virtual start address
+ *	- end	 - virtual end address
+ */
+ENTRY(v4wt_coherent_user_range)
 	bic	r0, r0, #CACHE_DLINESIZE - 1
 1:	mcr	p15, 0, r0, c7, c5, 1		@ invalidate I entry
 	add	r0, r0, #CACHE_DLINESIZE
@@ -167,6 +180,7 @@
 	.long	v4wt_flush_user_cache_all
 	.long	v4wt_flush_user_cache_range
 	.long	v4wt_coherent_kern_range
+	.long	v4wt_coherent_user_range
 	.long	v4wt_flush_kern_dcache_page
 	.long	v4wt_dma_inv_range
 	.long	v4wt_dma_clean_range
diff -Nru a/arch/arm/mm/cache-v6.S b/arch/arm/mm/cache-v6.S
--- a/arch/arm/mm/cache-v6.S	2004-10-18 14:55:54 -07:00
+++ b/arch/arm/mm/cache-v6.S	2004-10-18 14:55:54 -07:00
@@ -75,6 +75,22 @@
  *	- the Icache does not read data from the write buffer
  */
 ENTRY(v6_coherent_kern_range)
+	/* FALLTHROUGH */
+
+/*
+ *	v6_coherent_user_range(start,end)
+ *
+ *	Ensure that the I and D caches are coherent within specified
+ *	region.  This is typically used when code has been written to
+ *	a memory region, and will be executed.
+ *
+ *	- start   - virtual start address of region
+ *	- end     - virtual end address of region
+ *
+ *	It is assumed that:
+ *	- the Icache does not read data from the write buffer
+ */
+ENTRY(v6_coherent_user_range)
 	bic	r0, r0, #CACHE_LINE_SIZE - 1
 1:
 #ifdef HARVARD_CACHE
@@ -203,6 +219,7 @@
 	.long	v6_flush_user_cache_all
 	.long	v6_flush_user_cache_range
 	.long	v6_coherent_kern_range
+	.long	v6_coherent_user_range
 	.long	v6_flush_kern_dcache_page
 	.long	v6_dma_inv_range
 	.long	v6_dma_clean_range
diff -Nru a/arch/arm/mm/consistent.c b/arch/arm/mm/consistent.c
--- a/arch/arm/mm/consistent.c	2004-10-18 14:56:49 -07:00
+++ b/arch/arm/mm/consistent.c	2004-10-18 14:56:49 -07:00
@@ -138,7 +138,7 @@
 	struct page *page;
 	struct vm_region *c;
 	unsigned long order;
-	u64 mask = 0x00ffffff, limit; /* ISA default */
+	u64 mask = ISA_DMA_THRESHOLD, limit;
 
 	if (!consistent_pte) {
 		printk(KERN_ERR "%s: not initialised\n", __func__);
@@ -148,19 +148,34 @@
 
 	if (dev) {
 		mask = dev->coherent_dma_mask;
+
+		/*
+		 * Sanity check the DMA mask - it must be non-zero, and
+		 * must be able to be satisfied by a DMA allocation.
+		 */
 		if (mask == 0) {
 			dev_warn(dev, "coherent DMA mask is unset\n");
-			return NULL;
+			goto no_page;
+		}
+
+		if ((~mask) & ISA_DMA_THRESHOLD) {
+			dev_warn(dev, "coherent DMA mask %#llx is smaller "
+				 "than system GFP_DMA mask %#llx\n",
+				 mask, (unsigned long long)ISA_DMA_THRESHOLD);
+			goto no_page;
 		}
 	}
 
+	/*
+	 * Sanity check the allocation size.
+	 */
 	size = PAGE_ALIGN(size);
 	limit = (mask + 1) & ~mask;
-	if ((limit && size >= limit) || size >= (CONSISTENT_END - CONSISTENT_BASE)) {
-		printk(KERN_WARNING "coherent allocation too big (requested %#x mask %#Lx)\n",
-		       size, mask);
-		*handle = ~0;
-		return NULL;
+	if ((limit && size >= limit) ||
+	    size >= (CONSISTENT_END - CONSISTENT_BASE)) {
+		printk(KERN_WARNING "coherent allocation too big "
+		       "(requested %#x mask %#llx)\n", size, mask);
+		goto no_page;
 	}
 
 	order = get_order(size);
@@ -221,6 +236,7 @@
 	if (page)
 		__free_pages(page, order);
  no_page:
+	*handle = ~0;
 	return NULL;
 }
 
diff -Nru a/arch/arm/mm/copypage-v6.c b/arch/arm/mm/copypage-v6.c
--- a/arch/arm/mm/copypage-v6.c	2004-10-18 14:56:28 -07:00
+++ b/arch/arm/mm/copypage-v6.c	2004-10-18 14:56:28 -07:00
@@ -32,13 +32,45 @@
 #define DCACHE_COLOUR(vaddr) ((vaddr & (SHMLBA - 1)) >> PAGE_SHIFT)
 
 /*
+ * Copy the user page.  No aliasing to deal with so we can just
+ * attack the kernel's existing mapping of these pages.
+ */
+void v6_copy_user_page_nonaliasing(void *kto, const void *kfrom, unsigned long vaddr)
+{
+	copy_page(kto, kfrom);
+}
+
+/*
+ * Clear the user page.  No aliasing to deal with so we can just
+ * attack the kernel's existing mapping of this page.
+ */
+void v6_clear_user_page_nonaliasing(void *kaddr, unsigned long vaddr)
+{
+	clear_page(kaddr);
+}
+
+/*
  * Copy the page, taking account of the cache colour.
  */
-void v6_copy_user_page(void *kto, const void *kfrom, unsigned long vaddr)
+void v6_copy_user_page_aliasing(void *kto, const void *kfrom, unsigned long vaddr)
 {
 	unsigned int offset = DCACHE_COLOUR(vaddr);
 	unsigned long from, to;
 
+	/*
+	 * Discard data in the kernel mapping for the new page.
+	 * FIXME: needs this MCRR to be supported.
+	 */
+	__asm__("mcrr	p15, 0, %1, %0, c6	@ 0xec401f06"
+	   :
+	   : "r" (kto),
+	     "r" ((unsigned long)kto + PAGE_SIZE - L1_CACHE_BYTES)
+	   : "cc");
+
+	/*
+	 * Now copy the page using the same cache colour as the
+	 * pages ultimate destination.
+	 */
 	spin_lock(&v6_lock);
 
 	set_pte(from_pte + offset, pfn_pte(__pa(kfrom) >> PAGE_SHIFT, from_pgprot));
@@ -55,11 +87,30 @@
 	spin_unlock(&v6_lock);
 }
 
-void v6_clear_user_page(void *kaddr, unsigned long vaddr)
+/*
+ * Clear the user page.  We need to deal with the aliasing issues,
+ * so remap the kernel page into the same cache colour as the user
+ * page.
+ */
+void v6_clear_user_page_aliasing(void *kaddr, unsigned long vaddr)
 {
 	unsigned int offset = DCACHE_COLOUR(vaddr);
 	unsigned long to = to_address + (offset << PAGE_SHIFT);
 
+	/*
+	 * Discard data in the kernel mapping for the new page
+	 * FIXME: needs this MCRR to be supported.
+	 */
+	__asm__("mcrr	p15, 0, %1, %0, c6	@ 0xec401f06"
+	   :
+	   : "r" (kaddr),
+	     "r" ((unsigned long)kaddr + PAGE_SIZE - L1_CACHE_BYTES)
+	   : "cc");
+
+	/*
+	 * Now clear the page using the same cache colour as
+	 * the pages ultimate destination.
+	 */
 	spin_lock(&v6_lock);
 
 	set_pte(to_pte + offset, pfn_pte(__pa(kaddr) >> PAGE_SHIFT, to_pgprot));
@@ -70,26 +121,31 @@
 }
 
 struct cpu_user_fns v6_user_fns __initdata = {
-	.cpu_clear_user_page	= v6_clear_user_page,
-	.cpu_copy_user_page	= v6_copy_user_page,
+	.cpu_clear_user_page	= v6_clear_user_page_nonaliasing,
+	.cpu_copy_user_page	= v6_copy_user_page_nonaliasing,
 };
 
 static int __init v6_userpage_init(void)
 {
-	pgd_t *pgd;
-	pmd_t *pmd;
-
-	pgd = pgd_offset_k(from_address);
-	pmd = pmd_alloc(&init_mm, pgd, from_address);
-	if (!pmd)
-		BUG();
-	from_pte = pte_alloc_kernel(&init_mm, pmd, from_address);
-	if (!from_pte)
-		BUG();
-
-	to_pte = pte_alloc_kernel(&init_mm, pmd, to_address);
-	if (!to_pte)
-		BUG();
+	if (cache_is_vipt_aliasing()) {
+		pgd_t *pgd;
+		pmd_t *pmd;
+
+		pgd = pgd_offset_k(from_address);
+		pmd = pmd_alloc(&init_mm, pgd, from_address);
+		if (!pmd)
+			BUG();
+		from_pte = pte_alloc_kernel(&init_mm, pmd, from_address);
+		if (!from_pte)
+			BUG();
+
+		to_pte = pte_alloc_kernel(&init_mm, pmd, to_address);
+		if (!to_pte)
+			BUG();
+
+		cpu_user.cpu_clear_user_page = v6_clear_user_page_aliasing;
+		cpu_user.cpu_copy_user_page = v6_copy_user_page_aliasing;
+	}
 
 	return 0;
 }
diff -Nru a/arch/arm/mm/fault-armv.c b/arch/arm/mm/fault-armv.c
--- a/arch/arm/mm/fault-armv.c	2004-10-18 14:56:19 -07:00
+++ b/arch/arm/mm/fault-armv.c	2004-10-18 14:56:19 -07:00
@@ -76,59 +76,12 @@
 	return 0;
 }
 
-static void __flush_dcache_page(struct page *page)
-{
-	struct address_space *mapping = page_mapping(page);
-	struct mm_struct *mm = current->active_mm;
-	struct vm_area_struct *mpnt = NULL;
-	struct prio_tree_iter iter;
-	unsigned long offset;
-	pgoff_t pgoff;
-
-	__cpuc_flush_dcache_page(page_address(page));
-
-	if (!mapping)
-		return;
-
-	/*
-	 * With a VIVT cache, we need to also write back
-	 * and invalidate any user data.
-	 */
-	pgoff = page->index << (PAGE_CACHE_SHIFT - PAGE_SHIFT);
-
-	flush_dcache_mmap_lock(mapping);
-	while ((mpnt = vma_prio_tree_next(mpnt, &mapping->i_mmap,
-					&iter, pgoff, pgoff)) != NULL) {
-		/*
-		 * If this VMA is not in our MM, we can ignore it.
-		 */
-		if (mpnt->vm_mm != mm)
-			continue;
-		if (!(mpnt->vm_flags & VM_MAYSHARE))
-			continue;
-		offset = (pgoff - mpnt->vm_pgoff) << PAGE_SHIFT;
-		flush_cache_page(mpnt, mpnt->vm_start + offset);
-	}
-	flush_dcache_mmap_unlock(mapping);
-}
-
-void flush_dcache_page(struct page *page)
-{
-	struct address_space *mapping = page_mapping(page);
-
-	if (mapping && !mapping_mapped(mapping))
-		set_bit(PG_dcache_dirty, &page->flags);
-	else
-		__flush_dcache_page(page);
-}
-EXPORT_SYMBOL(flush_dcache_page);
-
 static void
 make_coherent(struct vm_area_struct *vma, unsigned long addr, struct page *page, int dirty)
 {
 	struct address_space *mapping = page_mapping(page);
 	struct mm_struct *mm = vma->vm_mm;
-	struct vm_area_struct *mpnt = NULL;
+	struct vm_area_struct *mpnt;
 	struct prio_tree_iter iter;
 	unsigned long offset;
 	pgoff_t pgoff;
@@ -145,8 +98,7 @@
 	 * cache coherency.
 	 */
 	flush_dcache_mmap_lock(mapping);
-	while ((mpnt = vma_prio_tree_next(mpnt, &mapping->i_mmap,
-					&iter, pgoff, pgoff)) != NULL) {
+	vma_prio_tree_foreach(mpnt, &iter, &mapping->i_mmap, pgoff, pgoff) {
 		/*
 		 * If this VMA is not in our MM, we can ignore it.
 		 * Note that we intentionally mask out the VMA
@@ -190,10 +142,21 @@
 	if (page_mapping(page)) {
 		int dirty = test_and_clear_bit(PG_dcache_dirty, &page->flags);
 
-		if (dirty)
+		if (dirty) {
+			/*
+			 * This is our first userspace mapping of this page.
+			 * Ensure that the physical page is coherent with
+			 * the kernel mapping.
+			 *
+			 * FIXME: only need to do this on VIVT and aliasing
+			 *        VIPT cache architectures.  We can do that
+			 *	  by choosing whether to set this bit...
+			 */
 			__cpuc_flush_dcache_page(page_address(page));
+		}
 
-		make_coherent(vma, addr, page, dirty);
+		if (cache_is_vivt())
+			make_coherent(vma, addr, page, dirty);
 	}
 }
 
diff -Nru a/arch/arm/mm/flush.c b/arch/arm/mm/flush.c
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/arch/arm/mm/flush.c	2004-10-18 14:57:23 -07:00
@@ -0,0 +1,94 @@
+/*
+ *  linux/arch/arm/mm/flush.c
+ *
+ *  Copyright (C) 1995-2002 Russell King
+ *
+ * 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/module.h>
+#include <linux/mm.h>
+#include <linux/pagemap.h>
+
+#include <asm/cacheflush.h>
+#include <asm/system.h>
+
+static void __flush_dcache_page(struct address_space *mapping, struct page *page)
+{
+	struct mm_struct *mm = current->active_mm;
+	struct vm_area_struct *mpnt;
+	struct prio_tree_iter iter;
+	pgoff_t pgoff;
+
+	/*
+	 * Writeback any data associated with the kernel mapping of this
+	 * page.  This ensures that data in the physical page is mutually
+	 * coherent with the kernels mapping.
+	 */
+	__cpuc_flush_dcache_page(page_address(page));
+
+	/*
+	 * If there's no mapping pointer here, then this page isn't
+	 * visible to userspace yet, so there are no cache lines
+	 * associated with any other aliases.
+	 */
+	if (!mapping)
+		return;
+
+	/*
+	 * There are possible user space mappings of this page:
+	 * - VIVT cache: we need to also write back and invalidate all user
+	 *   data in the current VM view associated with this page.
+	 * - aliasing VIPT: we only need to find one mapping of this page.
+	 */
+	pgoff = page->index << (PAGE_CACHE_SHIFT - PAGE_SHIFT);
+
+	flush_dcache_mmap_lock(mapping);
+	vma_prio_tree_foreach(mpnt, &iter, &mapping->i_mmap, pgoff, pgoff) {
+		unsigned long offset;
+
+		/*
+		 * If this VMA is not in our MM, we can ignore it.
+		 */
+		if (mpnt->vm_mm != mm)
+			continue;
+		if (!(mpnt->vm_flags & VM_MAYSHARE))
+			continue;
+		offset = (pgoff - mpnt->vm_pgoff) << PAGE_SHIFT;
+		flush_cache_page(mpnt, mpnt->vm_start + offset);
+		if (cache_is_vipt())
+			break;
+	}
+	flush_dcache_mmap_unlock(mapping);
+}
+
+/*
+ * Ensure cache coherency between kernel mapping and userspace mapping
+ * of this page.
+ *
+ * We have three cases to consider:
+ *  - VIPT non-aliasing cache: fully coherent so nothing required.
+ *  - VIVT: fully aliasing, so we need to handle every alias in our
+ *          current VM view.
+ *  - VIPT aliasing: need to handle one alias in our current VM view.
+ *
+ * If we need to handle aliasing:
+ *  If the page only exists in the page cache and there are no user
+ *  space mappings, we can be lazy and remember that we may have dirty
+ *  kernel cache lines for later.  Otherwise, we assume we have
+ *  aliasing mappings.
+ */
+void flush_dcache_page(struct page *page)
+{
+	struct address_space *mapping = page_mapping(page);
+
+	if (cache_is_vipt_nonaliasing())
+		return;
+
+	if (mapping && !mapping_mapped(mapping))
+		set_bit(PG_dcache_dirty, &page->flags);
+	else
+		__flush_dcache_page(mapping, page);
+}
+EXPORT_SYMBOL(flush_dcache_page);
diff -Nru a/arch/arm/mm/init.c b/arch/arm/mm/init.c
--- a/arch/arm/mm/init.c	2004-10-18 14:55:54 -07:00
+++ b/arch/arm/mm/init.c	2004-10-18 14:55:54 -07:00
@@ -14,6 +14,7 @@
 #include <linux/swap.h>
 #include <linux/init.h>
 #include <linux/bootmem.h>
+#include <linux/mman.h>
 #include <linux/initrd.h>
 
 #include <asm/mach-types.h>
@@ -344,7 +345,7 @@
  * Initialise the bootmem allocator for all nodes.  This is called
  * early during the architecture specific initialisation.
  */
-void __init bootmem_init(struct meminfo *mi)
+static void __init bootmem_init(struct meminfo *mi)
 {
 	struct node_info node_info[MAX_NUMNODES], *np = node_info;
 	unsigned int bootmap_pages, bootmap_pfn, map_pg;
@@ -412,9 +413,7 @@
 	}
 #endif
 
-	if (map_pg != bootmap_pfn + bootmap_pages)
-		BUG();
-
+	BUG_ON(map_pg != bootmap_pfn + bootmap_pages);
 }
 
 /*
@@ -426,6 +425,8 @@
 	void *zero_page;
 	int node;
 
+	bootmem_init(mi);
+
 	memcpy(&meminfo, mi, sizeof(meminfo));
 
 	/*
@@ -495,7 +496,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);
 	}
 
@@ -590,7 +591,7 @@
 		 * anywhere without overcommit, so turn
 		 * it on by default.
 		 */
-		sysctl_overcommit_memory = 1;
+		sysctl_overcommit_memory = OVERCOMMIT_ALWAYS;
 	}
 }
 
diff -Nru a/arch/arm/mm/proc-arm1020.S b/arch/arm/mm/proc-arm1020.S
--- a/arch/arm/mm/proc-arm1020.S	2004-10-18 14:55:54 -07:00
+++ b/arch/arm/mm/proc-arm1020.S	2004-10-18 14:55:54 -07:00
@@ -196,6 +196,19 @@
  *	- end	- virtual end address
  */
 ENTRY(arm1020_coherent_kern_range)
+	/* FALLTRHOUGH */
+
+/*
+ *	coherent_user_range(start, end)
+ *
+ *	Ensure coherency between the Icache and the Dcache in the
+ *	region described by start.  If you have non-snooping
+ *	Harvard caches, you need to implement this function.
+ *
+ *	- start	- virtual start address
+ *	- end	- virtual end address
+ */
+ENTRY(arm1020_coherent_user_range)
 	mov	ip, #0
 	bic	r0, r0, #CACHE_DLINESIZE - 1
 	mcr	p15, 0, ip, c7, c10, 4
@@ -317,6 +330,7 @@
 	.long	arm1020_flush_user_cache_all
 	.long	arm1020_flush_user_cache_range
 	.long	arm1020_coherent_kern_range
+	.long	arm1020_coherent_user_range
 	.long	arm1020_flush_kern_dcache_page
 	.long	arm1020_dma_inv_range
 	.long	arm1020_dma_clean_range
diff -Nru a/arch/arm/mm/proc-arm1020e.S b/arch/arm/mm/proc-arm1020e.S
--- a/arch/arm/mm/proc-arm1020e.S	2004-10-18 14:56:33 -07:00
+++ b/arch/arm/mm/proc-arm1020e.S	2004-10-18 14:56:33 -07:00
@@ -193,6 +193,18 @@
  *	- end	- virtual end address
  */
 ENTRY(arm1020e_coherent_kern_range)
+	/* FALLTHROUGH */
+/*
+ *	coherent_user_range(start, end)
+ *
+ *	Ensure coherency between the Icache and the Dcache in the
+ *	region described by start.  If you have non-snooping
+ *	Harvard caches, you need to implement this function.
+ *
+ *	- start	- virtual start address
+ *	- end	- virtual end address
+ */
+ENTRY(arm1020e_coherent_user_range)
 	mov	ip, #0
 	bic	r0, r0, #CACHE_DLINESIZE - 1
 1:
@@ -304,6 +316,7 @@
 	.long	arm1020e_flush_user_cache_all
 	.long	arm1020e_flush_user_cache_range
 	.long	arm1020e_coherent_kern_range
+	.long	arm1020e_coherent_user_range
 	.long	arm1020e_flush_kern_dcache_page
 	.long	arm1020e_dma_inv_range
 	.long	arm1020e_dma_clean_range
@@ -495,7 +508,7 @@
 	b	__arm1020e_setup
 	.long	cpu_arch_name
 	.long	cpu_elf_name
-	.long	HWCAP_SWP | HWCAP_HALF | HWCAP_THUMB
+	.long	HWCAP_SWP | HWCAP_HALF | HWCAP_THUMB | HWCAP_EDSP
 	.long	cpu_arm1020e_name
 	.long	arm1020e_processor_functions
 	.long	v4wbi_tlb_fns
diff -Nru a/arch/arm/mm/proc-arm1022.S b/arch/arm/mm/proc-arm1022.S
--- a/arch/arm/mm/proc-arm1022.S	2004-10-18 14:57:04 -07:00
+++ b/arch/arm/mm/proc-arm1022.S	2004-10-18 14:57:04 -07:00
@@ -180,6 +180,19 @@
  *	- end	- virtual end address
  */
 ENTRY(arm1022_coherent_kern_range)
+	/* FALLTHROUGH */
+
+/*
+ *	coherent_user_range(start, end)
+ *
+ *	Ensure coherency between the Icache and the Dcache in the
+ *	region described by start.  If you have non-snooping
+ *	Harvard caches, you need to implement this function.
+ *
+ *	- start	- virtual start address
+ *	- end	- virtual end address
+ */
+ENTRY(arm1022_coherent_user_range)
 	mov	ip, #0
 	bic	r0, r0, #CACHE_DLINESIZE - 1
 1:
@@ -291,6 +304,7 @@
 	.long	arm1022_flush_user_cache_all
 	.long	arm1022_flush_user_cache_range
 	.long	arm1022_coherent_kern_range
+	.long	arm1022_coherent_user_range
 	.long	arm1022_flush_kern_dcache_page
 	.long	arm1022_dma_inv_range
 	.long	arm1022_dma_clean_range
@@ -475,7 +489,7 @@
 	b	__arm1022_setup
 	.long	cpu_arch_name
 	.long	cpu_elf_name
-	.long	HWCAP_SWP | HWCAP_HALF | HWCAP_THUMB
+	.long	HWCAP_SWP | HWCAP_HALF | HWCAP_THUMB | HWCAP_EDSP
 	.long	cpu_arm1022_name
 	.long	arm1022_processor_functions
 	.long	v4wbi_tlb_fns
diff -Nru a/arch/arm/mm/proc-arm1026.S b/arch/arm/mm/proc-arm1026.S
--- a/arch/arm/mm/proc-arm1026.S	2004-10-18 14:56:29 -07:00
+++ b/arch/arm/mm/proc-arm1026.S	2004-10-18 14:56:29 -07:00
@@ -175,6 +175,18 @@
  *	- end	- virtual end address
  */
 ENTRY(arm1026_coherent_kern_range)
+	/* FALLTHROUGH */
+/*
+ *	coherent_user_range(start, end)
+ *
+ *	Ensure coherency between the Icache and the Dcache in the
+ *	region described by start.  If you have non-snooping
+ *	Harvard caches, you need to implement this function.
+ *
+ *	- start	- virtual start address
+ *	- end	- virtual end address
+ */
+ENTRY(arm1026_coherent_user_range)
 	mov	ip, #0
 	bic	r0, r0, #CACHE_DLINESIZE - 1
 1:
@@ -286,6 +298,7 @@
 	.long	arm1026_flush_user_cache_all
 	.long	arm1026_flush_user_cache_range
 	.long	arm1026_coherent_kern_range
+	.long	arm1026_coherent_user_range
 	.long	arm1026_flush_kern_dcache_page
 	.long	arm1026_dma_inv_range
 	.long	arm1026_dma_clean_range
@@ -471,7 +484,7 @@
 	b	__arm1026_setup
 	.long	cpu_arch_name
 	.long	cpu_elf_name
-	.long	HWCAP_SWP | HWCAP_HALF | HWCAP_THUMB | HWCAP_FAST_MULT
+	.long	HWCAP_SWP|HWCAP_HALF|HWCAP_THUMB|HWCAP_FAST_MULT|HWCAP_EDSP|HWCAP_JAVA
 	.long	cpu_arm1026_name
 	.long	arm1026_processor_functions
 	.long	v4wbi_tlb_fns
diff -Nru a/arch/arm/mm/proc-arm920.S b/arch/arm/mm/proc-arm920.S
--- a/arch/arm/mm/proc-arm920.S	2004-10-18 14:55:54 -07:00
+++ b/arch/arm/mm/proc-arm920.S	2004-10-18 14:55:54 -07:00
@@ -182,6 +182,19 @@
  *	- end	- virtual end address
  */
 ENTRY(arm920_coherent_kern_range)
+	/* FALLTHROUGH */
+
+/*
+ *	coherent_user_range(start, end)
+ *
+ *	Ensure coherency between the Icache and the Dcache in the
+ *	region described by start, end.  If you have non-snooping
+ *	Harvard caches, you need to implement this function.
+ *
+ *	- start	- virtual start address
+ *	- end	- virtual end address
+ */
+ENTRY(arm920_coherent_user_range)
 	bic	r0, r0, #CACHE_DLINESIZE - 1
 1:	mcr	p15, 0, r0, c7, c10, 1		@ clean D entry
 	mcr	p15, 0, r0, c7, c5, 1		@ invalidate I entry
@@ -277,6 +290,7 @@
 	.long	arm920_flush_user_cache_all
 	.long	arm920_flush_user_cache_range
 	.long	arm920_coherent_kern_range
+	.long	arm920_coherent_user_range
 	.long	arm920_flush_kern_dcache_page
 	.long	arm920_dma_inv_range
 	.long	arm920_dma_clean_range
diff -Nru a/arch/arm/mm/proc-arm922.S b/arch/arm/mm/proc-arm922.S
--- a/arch/arm/mm/proc-arm922.S	2004-10-18 14:57:03 -07:00
+++ b/arch/arm/mm/proc-arm922.S	2004-10-18 14:57:03 -07:00
@@ -184,6 +184,19 @@
  *	- end	- virtual end address
  */
 ENTRY(arm922_coherent_kern_range)
+	/* FALLTHROUGH */
+
+/*
+ *	coherent_user_range(start, end)
+ *
+ *	Ensure coherency between the Icache and the Dcache in the
+ *	region described by start, end.  If you have non-snooping
+ *	Harvard caches, you need to implement this function.
+ *
+ *	- start	- virtual start address
+ *	- end	- virtual end address
+ */
+ENTRY(arm922_coherent_user_range)
 	bic	r0, r0, #CACHE_DLINESIZE - 1
 1:	mcr	p15, 0, r0, c7, c10, 1		@ clean D entry
 	mcr	p15, 0, r0, c7, c5, 1		@ invalidate I entry
@@ -279,6 +292,7 @@
 	.long	arm922_flush_user_cache_all
 	.long	arm922_flush_user_cache_range
 	.long	arm922_coherent_kern_range
+	.long	arm922_coherent_user_range
 	.long	arm922_flush_kern_dcache_page
 	.long	arm922_dma_inv_range
 	.long	arm922_dma_clean_range
diff -Nru a/arch/arm/mm/proc-arm925.S b/arch/arm/mm/proc-arm925.S
--- a/arch/arm/mm/proc-arm925.S	2004-10-18 14:56:29 -07:00
+++ b/arch/arm/mm/proc-arm925.S	2004-10-18 14:56:29 -07:00
@@ -225,6 +225,19 @@
  *	- end	- virtual end address
  */
 ENTRY(arm925_coherent_kern_range)
+	/* FALLTHROUGH */
+
+/*
+ *	coherent_user_range(start, end)
+ *
+ *	Ensure coherency between the Icache and the Dcache in the
+ *	region described by start, end.  If you have non-snooping
+ *	Harvard caches, you need to implement this function.
+ *
+ *	- start	- virtual start address
+ *	- end	- virtual end address
+ */
+ENTRY(arm925_coherent_user_range)
 	bic	r0, r0, #CACHE_DLINESIZE - 1
 1:	mcr	p15, 0, r0, c7, c10, 1		@ clean D entry
 	mcr	p15, 0, r0, c7, c5, 1		@ invalidate I entry
@@ -329,6 +342,7 @@
 	.long	arm925_flush_user_cache_all
 	.long	arm925_flush_user_cache_range
 	.long	arm925_coherent_kern_range
+	.long	arm925_coherent_user_range
 	.long	arm925_flush_kern_dcache_page
 	.long	arm925_dma_inv_range
 	.long	arm925_dma_clean_range
diff -Nru a/arch/arm/mm/proc-arm926.S b/arch/arm/mm/proc-arm926.S
--- a/arch/arm/mm/proc-arm926.S	2004-10-18 14:56:32 -07:00
+++ b/arch/arm/mm/proc-arm926.S	2004-10-18 14:56:32 -07:00
@@ -185,6 +185,19 @@
  *	- end	- virtual end address
  */
 ENTRY(arm926_coherent_kern_range)
+	/* FALLTHROUGH */
+
+/*
+ *	coherent_user_range(start, end)
+ *
+ *	Ensure coherency between the Icache and the Dcache in the
+ *	region described by start, end.  If you have non-snooping
+ *	Harvard caches, you need to implement this function.
+ *
+ *	- start	- virtual start address
+ *	- end	- virtual end address
+ */
+ENTRY(arm926_coherent_user_range)
 	bic	r0, r0, #CACHE_DLINESIZE - 1
 1:	mcr	p15, 0, r0, c7, c10, 1		@ clean D entry
 	mcr	p15, 0, r0, c7, c5, 1		@ invalidate I entry
@@ -289,6 +302,7 @@
 	.long	arm926_flush_user_cache_all
 	.long	arm926_flush_user_cache_range
 	.long	arm926_coherent_kern_range
+	.long	arm926_coherent_user_range
 	.long	arm926_flush_kern_dcache_page
 	.long	arm926_dma_inv_range
 	.long	arm926_dma_clean_range
@@ -473,7 +487,7 @@
 	b	__arm926_setup
 	.long	cpu_arch_name
 	.long	cpu_elf_name
-	.long	HWCAP_SWP | HWCAP_HALF | HWCAP_THUMB | HWCAP_FAST_MULT | HWCAP_JAVA
+	.long	HWCAP_SWP|HWCAP_HALF|HWCAP_THUMB|HWCAP_FAST_MULT|HWCAP_EDSP|HWCAP_JAVA
 	.long	cpu_arm926_name
 	.long	arm926_processor_functions
 	.long	v4wbi_tlb_fns
diff -Nru a/arch/arm/mm/proc-syms.c b/arch/arm/mm/proc-syms.c
--- a/arch/arm/mm/proc-syms.c	2004-10-18 14:56:29 -07:00
+++ b/arch/arm/mm/proc-syms.c	2004-10-18 14:56:29 -07:00
@@ -22,10 +22,10 @@
 #endif
 
 #ifndef MULTI_CACHE
-EXPORT_SYMBOL_NOVERS(__cpuc_flush_kern_all);
-EXPORT_SYMBOL_NOVERS(__cpuc_flush_user_all);
-EXPORT_SYMBOL_NOVERS(__cpuc_flush_user_range);
-EXPORT_SYMBOL_NOVERS(__cpuc_coherent_kern_range);
+EXPORT_SYMBOL(__cpuc_flush_kern_all);
+EXPORT_SYMBOL(__cpuc_flush_user_all);
+EXPORT_SYMBOL(__cpuc_flush_user_range);
+EXPORT_SYMBOL(__cpuc_coherent_kern_range);
 #else
 EXPORT_SYMBOL(cpu_cache);
 #endif
diff -Nru a/arch/arm/mm/proc-v6.S b/arch/arm/mm/proc-v6.S
--- a/arch/arm/mm/proc-v6.S	2004-10-18 14:55:53 -07:00
+++ b/arch/arm/mm/proc-v6.S	2004-10-18 14:55:53 -07:00
@@ -189,12 +189,10 @@
  *	- cache type register is implemented
  */
 __v6_setup:
-	mrc	p15, 0, r10, c0, c0, 1		@ read cache type register
-	tst	r10, #1 << 24			@ Harvard cache?
 	mov	r10, #0
-	mcrne	p15, 0, r10, c7, c14, 0		@ clean+invalidate D cache
-	mcrne	p15, 0, r10, c7, c5, 0		@ invalidate I cache
-	mcreq	p15, 0, r10, c7, c15, 0		@ clean+invalidate cache
+	mcr	p15, 0, r10, c7, c14, 0		@ clean+invalidate D cache
+	mcr	p15, 0, r10, c7, c5, 0		@ invalidate I cache
+	mcr	p15, 0, r10, c7, c15, 0		@ clean+invalidate cache
 	mcr	p15, 0, r10, c7, c10, 4		@ drain write buffer
 	mcr	p15, 0, r10, c8, c7, 0		@ invalidate I + D TLBs
 	mcr	p15, 0, r10, c2, c0, 2		@ TTB control register
@@ -258,7 +256,7 @@
 	b	__v6_setup
 	.long	cpu_arch_name
 	.long	cpu_elf_name
-	.long	HWCAP_SWP | HWCAP_HALF | HWCAP_FAST_MULT | HWCAP_VFP
+	.long	HWCAP_SWP|HWCAP_HALF|HWCAP_THUMB|HWCAP_FAST_MULT|HWCAP_VFP|HWCAP_EDSP|HWCAP_JAVA
 	.long	cpu_v6_name
 	.long	v6_processor_functions
 	.long	v6wbi_tlb_fns
diff -Nru a/arch/arm/mm/proc-xscale.S b/arch/arm/mm/proc-xscale.S
--- a/arch/arm/mm/proc-xscale.S	2004-10-18 14:56:50 -07:00
+++ b/arch/arm/mm/proc-xscale.S	2004-10-18 14:56:50 -07:00
@@ -241,6 +241,22 @@
  *	it also trashes the mini I-cache used by JTAG debuggers.
  */
 ENTRY(xscale_coherent_kern_range)
+	/* FALLTHROUGH */
+
+/*
+ *	coherent_user_range(start, end)
+ *
+ *	Ensure coherency between the Icache and the Dcache in the
+ *	region described by start.  If you have non-snooping
+ *	Harvard caches, you need to implement this function.
+ *
+ *	- start  - virtual start address
+ *	- end	 - virtual end address
+ *
+ *	Note: single I-cache line invalidation isn't used here since
+ *	it also trashes the mini I-cache used by JTAG debuggers.
+ */
+ENTRY(xscale_coherent_user_range)
 	bic	r0, r0, #CACHELINESIZE - 1
 1:	mcr	p15, 0, r0, c7, c10, 1		@ clean D entry
 	add	r0, r0, #CACHELINESIZE
@@ -341,6 +357,7 @@
 	.long	xscale_flush_user_cache_all
 	.long	xscale_flush_user_cache_range
 	.long	xscale_coherent_kern_range
+	.long	xscale_coherent_user_range
 	.long	xscale_flush_kern_dcache_page
 	.long	xscale_dma_inv_range
 	.long	xscale_dma_clean_range
@@ -585,7 +602,12 @@
 	mcr	p15, 0, r4, c2, c0, 0		@ load page table pointer
 	mov	r0, #0x1f			@ Domains 0, 1 = client
 	mcr	p15, 0, r0, c3, c0, 0		@ load domain access register
-	mov	r0, #1				@ Allow access to CP0 and CP13
+#ifdef CONFIG_IWMMXT
+	mov	r0, #0				@ initially disallow access to CP0/CP1
+#else
+	mov	r0, #1				@ Allow access to CP0
+#endif
+	orr     r0, r0, #1 << 6			@ cp6 for IOP3xx and Bulverde
 	orr	r0, r0, #1 << 13		@ Its undefined whether this
 	mcr	p15, 0, r0, c15, c1, 0		@ affects USR or SVC modes
 	mrc	p15, 0, r0, c1, c0, 0		@ get control register
@@ -632,10 +654,15 @@
 	.asciz	"XScale-80200"
 	.size	cpu_80200_name, . - cpu_80200_name
 
-	.type	cpu_80321_name, #object
-cpu_80321_name:
-	.asciz	"XScale-IOP80321"
-	.size	cpu_80321_name, . - cpu_80321_name
+	.type	cpu_8032x_name, #object
+cpu_8032x_name:
+	.asciz	"XScale-IOP8032x Family"
+	.size	cpu_8032x_name, . - cpu_8032x_name
+
+	.type	cpu_8033x_name, #object
+cpu_8033x_name:
+	.asciz	"XScale-IOP8033x Family"
+	.size	cpu_8033x_name, . - cpu_8033x_name
 
 	.type	cpu_pxa250_name, #object
 cpu_pxa250_name:
@@ -652,6 +679,16 @@
 	.asciz	"XScale-IXP42x Family"
 	.size	cpu_ixp42x_name, . - cpu_ixp42x_name
 
+	.type	cpu_ixp2400_name, #object
+cpu_ixp2400_name:
+	.asciz	"XScale-IXP2400"
+	.size	cpu_ixp2400_name, . - cpu_ixp2400_name
+
+	.type	cpu_ixp2800_name, #object
+cpu_ixp2800_name:
+	.asciz	"XScale-IXP2800"
+	.size	cpu_ixp2800_name, . - cpu_ixp2800_name
+
 	.type	cpu_pxa255_name, #object
 cpu_pxa255_name:
 	.asciz	"XScale-PXA255"
@@ -682,21 +719,37 @@
 	.long	xscale_cache_fns
 	.size	__80200_proc_info, . - __80200_proc_info
 
-	.type	__80321_proc_info,#object
-__80321_proc_info:
+	.type	__8032x_proc_info,#object
+__8032x_proc_info:
 	.long	0x69052420
-	.long	0xfffff7e0
+	.long	0xfffff5e0      @ mask should accomodate IOP80219 also
+	.long	0x00000c0e
+	b	__xscale_setup
+	.long	cpu_arch_name
+	.long	cpu_elf_name
+	.long	HWCAP_SWP|HWCAP_HALF|HWCAP_THUMB|HWCAP_FAST_MULT|HWCAP_EDSP
+	.long	cpu_8032x_name
+	.long	xscale_processor_functions
+	.long	v4wbi_tlb_fns
+	.long	xscale_mc_user_fns
+	.long	xscale_cache_fns
+	.size	__8032x_proc_info, . - __8032x_proc_info
+
+	.type	__8033x_proc_info,#object
+__8033x_proc_info:
+	.long	0x69054090
+	.long	0xffffffb0
 	.long	0x00000c0e
 	b	__xscale_setup
 	.long	cpu_arch_name
 	.long	cpu_elf_name
 	.long	HWCAP_SWP|HWCAP_HALF|HWCAP_THUMB|HWCAP_FAST_MULT|HWCAP_EDSP
-	.long	cpu_80321_name
+	.long	cpu_8033x_name
 	.long	xscale_processor_functions
 	.long	v4wbi_tlb_fns
 	.long	xscale_mc_user_fns
 	.long	xscale_cache_fns
-	.size	__80321_proc_info, . - __80321_proc_info
+	.size	__8033x_proc_info, . - __8033x_proc_info
 
 	.type	__pxa250_proc_info,#object
 __pxa250_proc_info:
@@ -729,6 +782,38 @@
 	.long	xscale_mc_user_fns
 	.long	xscale_cache_fns
 	.size	__pxa210_proc_info, . - __pxa210_proc_info
+
+	.type	__ixp2400_proc_info, #object
+__ixp2400_proc_info:
+	.long   0x69054190
+	.long   0xfffffff0
+	.long   0x00000c0e
+	b       __xscale_setup
+	.long   cpu_arch_name
+	.long   cpu_elf_name
+	.long   HWCAP_SWP|HWCAP_HALF|HWCAP_THUMB|HWCAP_FAST_MULT|HWCAP_EDSP
+	.long   cpu_ixp2400_name
+	.long   xscale_processor_functions
+	.long	v4wbi_tlb_fns
+	.long	xscale_mc_user_fns
+	.long	xscale_cache_fns
+	.size   __ixp2400_proc_info, . - __ixp2400_proc_info                
+
+	.type	__ixp2800_proc_info, #object
+__ixp2800_proc_info:
+	.long   0x690541a0
+	.long   0xfffffff0
+	.long   0x00000c0e
+	b       __xscale_setup
+	.long   cpu_arch_name
+	.long   cpu_elf_name
+	.long   HWCAP_SWP|HWCAP_HALF|HWCAP_THUMB|HWCAP_FAST_MULT|HWCAP_EDSP
+	.long   cpu_ixp2800_name
+	.long   xscale_processor_functions
+	.long	v4wbi_tlb_fns
+	.long	xscale_mc_user_fns
+	.long	xscale_cache_fns
+	.size   __ixp2800_proc_info, . - __ixp2800_proc_info                
 
 	.type	__ixp42x_proc_info, #object
 __ixp42x_proc_info:
diff -Nru a/arch/arm/nwfpe/fpa11_cpdt.c b/arch/arm/nwfpe/fpa11_cpdt.c
--- a/arch/arm/nwfpe/fpa11_cpdt.c	2004-10-18 14:57:04 -07:00
+++ b/arch/arm/nwfpe/fpa11_cpdt.c	2004-10-18 14:57:04 -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-10-18 14:56:32 -07:00
+++ b/arch/arm/oprofile/op_model_xscale.c	2004-10-18 14:56:32 -07:00
@@ -7,7 +7,7 @@
  * @remark Copyright 2004 Dave Jiang <dave.jiang@intel.com>
  * @remark Copyright 2004 Intel Corporation
  * @remark Copyright 2004 Zwane Mwaikambo <zwane@arm.linux.org.uk>
- * @remark Copyright 2004 Oprofile Authors
+ * @remark Copyright 2004 OProfile Authors
  *
  * @remark Read the file COPYING
  *
@@ -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;
 }
@@ -249,7 +256,7 @@
 	int i;
 
 	for (i = CCNT; i < MAX_COUNTERS; i++) {
-		if (counter_config[i].event)
+		if (counter_config[i].enabled)
 			continue;
 
 		counter_config[i].event = EVT_UNUSED;
@@ -336,7 +343,7 @@
 
 static irqreturn_t xscale_pmu_interrupt(int irq, void *arg, struct pt_regs *regs)
 {
-	unsigned long eip = instruction_pointer(regs);
+	unsigned long pc = profile_pc(regs);
 	int i, is_kernel = !user_mode(regs);
 	u32 pmnc;
 
@@ -350,7 +357,7 @@
 			continue;
 
 		write_counter(i, -(u32)results[i].reset_counter);
-		oprofile_add_sample(eip, is_kernel, i, smp_processor_id());
+		oprofile_add_sample(pc, is_kernel, i, smp_processor_id());
 		results[i].ovf--;
 	}
 
@@ -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/arm/tools/mach-types b/arch/arm/tools/mach-types
--- a/arch/arm/tools/mach-types	2004-10-18 14:56:29 -07:00
+++ b/arch/arm/tools/mach-types	2004-10-18 14:56:29 -07:00
@@ -6,7 +6,7 @@
 # To add an entry into this database, please see Documentation/arm/README,
 # or contact rmk@arm.linux.org.uk
 #
-# Last update: Fri Jul 2 11:58:36 2004
+# Last update: Thu Sep 30 15:23:21 2004
 #
 # machine_is_xxx	CONFIG_xxxx		MACH_TYPE_xxx		number
 #
@@ -519,7 +519,7 @@
 omap_h3			MACH_OMAP_H3		OMAP_H3			509
 omap_h4			MACH_OMAP_H4		OMAP_H4			510
 n10			MACH_N10		N10			511
-montajade		MACH_MONTAJADE		MONTAJADE		512
+montejade		MACH_MONTAJADE		MONTAJADE		512
 sg560			MACH_SG560		SG560			513
 dp1000			MACH_DP1000		DP1000			514
 omap_osk		MACH_OMAP_OSK		OMAP_OSK		515
@@ -559,3 +559,59 @@
 switchgrass		MACH_SWITCHGRASS	SWITCHGRASS		549
 ens_cmu			MACH_ENS_CMU		ENS_CMU			550
 mm6_sdb			MACH_MM6_SDB		MM6_SDB			551
+saturn			MACH_SATURN		SATURN			552
+argonplusevb		MACH_ARGONPLUSEVB	ARGONPLUSEVB		553
+scma11evb		MACH_SCMA11EVB		SCMA11EVB		554
+smdk2800		MACH_SMDK2800		SMDK2800		555
+mtwilson		MACH_MTWILSON		MTWILSON		556
+ziti			MACH_ZITI		ZITI			557
+grandfather		MACH_GRANDFATHER	GRANDFATHER		558
+tengine			MACH_TENGINE		TENGINE			559
+s3c2460			MACH_S3C2460		S3C2460			560
+pdm			MACH_PDM		PDM			561
+h4700			MACH_H4700		H4700			562
+h6300			MACH_H6300		H6300			563
+rz1700			MACH_RZ1700		RZ1700			564
+a716			MACH_A716		A716			565
+estk2440a		MACH_ESTK2440A		ESTK2440A		566
+atwixp425		MACH_ATWIXP425		ATWIXP425		567
+csb336			MACH_CSB336		CSB336			568
+rirm2			MACH_RIRM2		RIRM2			569
+cx23518			MACH_CX23518		CX23518			570
+cx2351x			MACH_CX2351X		CX2351X			571
+computime		MACH_COMPUTIME		COMPUTIME		572
+izarus			MACH_IZARUS		IZARUS			573
+pxa_rts			MACH_RTS		RTS			574
+se5100			MACH_SE5100		SE5100			575
+s3c2510			MACH_S3C2510		S3C2510			576
+csb437tl		MACH_CSB437TL		CSB437TL		577
+slauson			MACH_SLAUSON		SLAUSON			578
+pearlriver		MACH_PEARLRIVER		PEARLRIVER		579
+tdc_p210		MACH_TDC_P210		TDC_P210		580
+sg580			MACH_SG580		SG580			581
+wrsbcarm7		MACH_WRSBCARM7		WRSBCARM7		582
+ipd			MACH_IPD		IPD			583
+pxa_dnp2110		MACH_PXA_DNP2110	PXA_DNP2110		584
+xaeniax			MACH_XAENIAX		XAENIAX			585
+somn4250		MACH_SOMN4250		SOMN4250		586
+pleb2			MACH_PLEB2		PLEB2			587
+cwl			MACH_CWL		CWL			588
+gd			MACH_GD			GD			589
+chaffee			MACH_CHAFFEE		CHAFFEE			590
+rms101			MACH_RMS101		RMS101			591
+rx3715			MACH_RX3715		RX3715			592
+swift			MACH_SWIFT		SWIFT			593
+roverp7			MACH_ROVERP7		ROVERP7			594
+pr818s			MACH_PR818S		PR818S			595
+trxpro			MACH_TRXPRO		TRXPRO			596
+nslu2			MACH_NSLU2		NSLU2			597
+e400			MACH_E400		E400			598
+trab			MACH_TRAB		TRAB			599
+cmc_pu2			MACH_CMC_PU2		CMC_PU2			600
+fulcrum			MACH_FULCRUM		FULCRUM			601
+netgate42x		MACH_NETGATE42X		NETGATE42X		602
+str710			MACH_STR710		STR710			603
+ixdpg425		MACH_IXDPG425		IXDPG425		604
+tomtomgo		MACH_TOMTOMGO		TOMTOMGO		605
+versatile_ab		MACH_VERSATILE_AB	VERSATILE_AB		606
+edb9307			MACH_EDB9307		EDB9307			607
diff -Nru a/arch/arm26/Kconfig b/arch/arm26/Kconfig
--- a/arch/arm26/Kconfig	2004-10-18 14:56:33 -07:00
+++ b/arch/arm26/Kconfig	2004-10-18 14:56:33 -07:00
@@ -62,7 +62,7 @@
         bool "Archimedes"
         help
           Say Y to support the Acorn Archimedes.
-	  
+
 	  The Acorn Archimedes was an personal computer based on an 8MHz ARM2
           processor, released in 1987.  It supported up to 16MB of RAM in
 	  later models and floppy, harddisc, ethernet etc.
@@ -71,7 +71,7 @@
         bool "A5000"
         help
           Say Y here to to support the Acorn A5000.
-	  
+
 	  Linux can support the
           internal IDE disk and CD-ROM interface, serial and parallel port,
           and the floppy drive.  Note that on some A5000s the floppy is
@@ -214,118 +214,7 @@
 
 source "drivers/usb/Kconfig"
 
-menu "Kernel hacking"
-
-# RMK wants arm kernels compiled with frame pointers so hardwire this to y.
-# If you know what you are doing and are willing to live without stack
-# traces, you can get a slightly smaller kernel by setting this option to
-# n, but then RMK will have to kill you ;).
-config FRAME_POINTER
-	bool
-	default y
-	help
-	  If you say N here, the resulting kernel will be slightly smaller and
-	  faster. However, when a problem occurs with the kernel, the
-	  information that is reported is severely limited. Most people
-	  should say Y here.
-
-config DEBUG_USER
-	bool "Verbose user fault messages"
-	help
-	  When a user program crashes due to an exception, the kernel can
-	  print a brief message explaining what the problem was. This is
-	  sometimes helpful for debugging but serves no purpose on a
-	  production system. Most people should say N here.
-
-config DEBUG_INFO
-	bool "Include GDB debugging information in kernel binary"
-	help
-	  Say Y here to include source-level debugging information in the
-	  `vmlinux' binary image. This is handy if you want to use gdb or
-	  addr2line to debug the kernel. It has no impact on the in-memory
-	  footprint of the running kernel but it can increase the amount of
-	  time and disk space needed for compilation of the kernel. If in
-	  doubt say N.
-
-config DEBUG_KERNEL
-	bool "Kernel debugging"
-	help
-	  Say Y here if you are developing drivers or trying to debug and
-	  identify kernel problems.
-
-config DEBUG_SLAB
-	bool "Debug memory allocations"
-	depends on DEBUG_KERNEL
-	help
-	  Say Y here to have the kernel do limited verification on memory
-	  allocation as well as poisoning memory on free to catch use of freed
-	  memory.
-
-config MAGIC_SYSRQ
-	bool "Magic SysRq key"
-	depends on DEBUG_KERNEL
-	help
-	  If you say Y here, you will have some control over the system even
-	  if the system crashes for example during kernel debugging (e.g., you
-	  will be able to flush the buffer cache to disk, reboot the system
-	  immediately or dump some status information). This is accomplished
-	  by pressing various keys while holding SysRq (Alt+PrintScreen). It
-	  also works on a serial console (on PC hardware at least), if you
-	  send a BREAK and then within 5 seconds a command keypress. The
-	  keys are documented in <file:Documentation/sysrq.txt>. Don't say Y
-	  unless you really know what this hack does.
-
-config DEBUG_SPINLOCK
-	bool "Spinlock debugging"
-	depends on DEBUG_KERNEL
-	help
-	  Say Y here and build SMP to catch missing spinlock initialization
-	  and certain other kinds of spinlock errors commonly made.  This is
-	  best used in conjunction with the NMI watchdog so that spinlock
-	  deadlocks are also debuggable.
-
-config DEBUG_WAITQ
-	bool "Wait queue debugging"
-	depends on DEBUG_KERNEL
-
-config DEBUG_BUGVERBOSE
-	bool "Verbose BUG() reporting (adds 70K)"
-	depends on DEBUG_KERNEL
-	help
-	  Say Y here to make BUG() panics output the file name and line number
-	  of the BUG call as well as the EIP and oops trace.  This aids
-	  debugging but costs about 70-100K of memory.
-
-config DEBUG_ERRORS
-	bool "Verbose kernel error messages"
-	depends on DEBUG_KERNEL
-	help
-	  This option controls verbose debugging information which can be
-	  printed when the kernel detects an internal error. This debugging
-	  information is useful to kernel hackers when tracking down problems,
-	  but mostly meaningless to other people. It's safe to say Y unless
-	  you are concerned with the code size or don't want to see these
-	  messages.
-
-config DEBUG_INFO
-	bool "Compile the kernel with debug info"
-	depends on DEBUG_KERNEL
-	help
-          If you say Y here the resulting kernel image will include
-	  debugging info resulting in a larger kernel image.
-	  Say Y here only if you plan to use gdb to debug the kernel.
-	  If you don't debug the kernel, you can say N.
-
-# These options are only for real kernel hackers who want to get their hands dirty. 
-config DEBUG_LL
-	bool "Kernel low-level debugging functions"
-	depends on DEBUG_KERNEL
-	help
-	  Say Y here to include definitions of printascii, printchar, printhex
-	  in the kernel.  This is helpful if you are debugging code that
-	  executes before the console is initialized.
-
-endmenu
+source "arch/arm26/Kconfig.debug"
 
 source "security/Kconfig"
 
diff -Nru a/arch/arm26/Kconfig.debug b/arch/arm26/Kconfig.debug
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/arch/arm26/Kconfig.debug	2004-10-18 14:57:23 -07:00
@@ -0,0 +1,60 @@
+menu "Kernel hacking"
+
+source "lib/Kconfig.debug"
+
+# RMK wants arm kernels compiled with frame pointers so hardwire this to y.
+# If you know what you are doing and are willing to live without stack
+# traces, you can get a slightly smaller kernel by setting this option to
+# n, but then RMK will have to kill you ;).
+config FRAME_POINTER
+	bool
+	default y
+	help
+	  If you say N here, the resulting kernel will be slightly smaller and
+	  faster. However, when a problem occurs with the kernel, the
+	  information that is reported is severely limited. Most people
+	  should say Y here.
+
+config DEBUG_USER
+	bool "Verbose user fault messages"
+	help
+	  When a user program crashes due to an exception, the kernel can
+	  print a brief message explaining what the problem was. This is
+	  sometimes helpful for debugging but serves no purpose on a
+	  production system. Most people should say N here.
+
+config DEBUG_WAITQ
+	bool "Wait queue debugging"
+	depends on DEBUG_KERNEL
+
+config DEBUG_ERRORS
+	bool "Verbose kernel error messages"
+	depends on DEBUG_KERNEL
+	help
+	  This option controls verbose debugging information which can be
+	  printed when the kernel detects an internal error. This debugging
+	  information is useful to kernel hackers when tracking down problems,
+	  but mostly meaningless to other people. It's safe to say Y unless
+	  you are concerned with the code size or don't want to see these
+	  messages.
+
+config DEBUG_INFO
+	bool "Include GDB debugging information in kernel binary"
+	help
+	  Say Y here to include source-level debugging information in the
+	  `vmlinux' binary image. This is handy if you want to use gdb or
+	  addr2line to debug the kernel. It has no impact on the in-memory
+	  footprint of the running kernel but it can increase the amount of
+	  time and disk space needed for compilation of the kernel. If in
+	  doubt say N.
+
+# These options are only for real kernel hackers who want to get their hands dirty.
+config DEBUG_LL
+	bool "Kernel low-level debugging functions"
+	depends on DEBUG_KERNEL
+	help
+	  Say Y here to include definitions of printascii, printchar, printhex
+	  in the kernel.  This is helpful if you are debugging code that
+	  executes before the console is initialized.
+
+endmenu
diff -Nru a/arch/arm26/Makefile b/arch/arm26/Makefile
--- a/arch/arm26/Makefile	2004-10-18 14:56:29 -07:00
+++ b/arch/arm26/Makefile	2004-10-18 14:56:29 -07:00
@@ -8,8 +8,7 @@
 # Copyright (C) 1995-2001 by Russell King
 
 LDFLAGS_vmlinux	:=-p -X
-LDFLAGS_BLOB	:=--format binary
-AFLAGS_vmlinux.lds.o = -DTEXTADDR=$(TEXTADDR) -DDATAADDR=$(DATAADDR)
+CPPFLAGS_vmlinux.lds = -DTEXTADDR=$(TEXTADDR) -DDATAADDR=$(DATAADDR)
 OBJCOPYFLAGS	:=-O binary -R .note -R .comment -S
 GZFLAGS		:=-9
 
@@ -28,7 +27,6 @@
 AFLAGS		+=-mapcs-26 -mcpu=arm3 -mno-fpu -msoft-float -Wa,-mno-fpu
 
 head-y		:= arch/arm26/machine/head.o arch/arm26/kernel/init_task.o
-LDFLAGS_BLOB	+= --oformat elf32-littlearm
 
 ifeq ($(CONFIG_XIP_KERNEL),y)
   TEXTADDR	 := 0x03880000
diff -Nru a/arch/arm26/boot/Makefile b/arch/arm26/boot/Makefile
--- a/arch/arm26/boot/Makefile	2004-10-18 14:57:05 -07:00
+++ b/arch/arm26/boot/Makefile	2004-10-18 14:57:05 -07:00
@@ -67,12 +67,12 @@
 
 install: $(obj)/Image
 	$(CONFIG_SHELL) $(obj)/install.sh \
-	$(VERSION).$(PATCHLEVEL).$(SUBLEVEL)$(EXTRAVERSION) \
+	$(KERNELRELEASE) \
 	$(obj)/Image System.map "$(INSTALL_PATH)"
 
 zinstall: $(obj)/zImage
 	$(CONFIG_SHELL) $(obj)/install.sh \
-	$(VERSION).$(PATCHLEVEL).$(SUBLEVEL)$(EXTRAVERSION) \
+	$(KERNELRELEASE) \
 	$(obj)/zImage System.map "$(INSTALL_PATH)"
 
 subdir-	    := compressed
diff -Nru a/arch/arm26/kernel/Makefile b/arch/arm26/kernel/Makefile
--- a/arch/arm26/kernel/Makefile	2004-10-18 14:56:29 -07:00
+++ b/arch/arm26/kernel/Makefile	2004-10-18 14:56:29 -07:00
@@ -14,5 +14,5 @@
 obj-$(CONFIG_FIQ)		+= fiq.o
 obj-$(CONFIG_MODULES)		+= armksyms.o
 
-extra-y := init_task.o vmlinux.lds.s
+extra-y := init_task.o vmlinux.lds
 
diff -Nru a/arch/arm26/kernel/armksyms.c b/arch/arm26/kernel/armksyms.c
--- a/arch/arm26/kernel/armksyms.c	2004-10-18 14:56:28 -07:00
+++ b/arch/arm26/kernel/armksyms.c	2004-10-18 14:56:28 -07:00
@@ -95,7 +95,7 @@
 EXPORT_SYMBOL(kd_mksound);
 #endif
 
-EXPORT_SYMBOL_NOVERS(__do_softirq);
+EXPORT_SYMBOL(__do_softirq);
 
 	/* platform dependent support */
 EXPORT_SYMBOL(dump_thread);
@@ -125,71 +125,71 @@
 
 	/* io */
 #ifndef __raw_readsb
-EXPORT_SYMBOL_NOVERS(__raw_readsb);
+EXPORT_SYMBOL(__raw_readsb);
 #endif
 #ifndef __raw_readsw
-EXPORT_SYMBOL_NOVERS(__raw_readsw);
+EXPORT_SYMBOL(__raw_readsw);
 #endif
 #ifndef __raw_readsl
-EXPORT_SYMBOL_NOVERS(__raw_readsl);
+EXPORT_SYMBOL(__raw_readsl);
 #endif
 #ifndef __raw_writesb
-EXPORT_SYMBOL_NOVERS(__raw_writesb);
+EXPORT_SYMBOL(__raw_writesb);
 #endif
 #ifndef __raw_writesw
-EXPORT_SYMBOL_NOVERS(__raw_writesw);
+EXPORT_SYMBOL(__raw_writesw);
 #endif
 #ifndef __raw_writesl
-EXPORT_SYMBOL_NOVERS(__raw_writesl);
+EXPORT_SYMBOL(__raw_writesl);
 #endif
 
 	/* string / mem functions */
-EXPORT_SYMBOL_NOVERS(strcpy);
-EXPORT_SYMBOL_NOVERS(strncpy);
-EXPORT_SYMBOL_NOVERS(strcat);
-EXPORT_SYMBOL_NOVERS(strncat);
-EXPORT_SYMBOL_NOVERS(strcmp);
-EXPORT_SYMBOL_NOVERS(strncmp);
-EXPORT_SYMBOL_NOVERS(strchr);
-EXPORT_SYMBOL_NOVERS(strlen);
-EXPORT_SYMBOL_NOVERS(strnlen);
-EXPORT_SYMBOL_NOVERS(strpbrk);
-EXPORT_SYMBOL_NOVERS(strrchr);
-EXPORT_SYMBOL_NOVERS(strstr);
-EXPORT_SYMBOL_NOVERS(memset);
-EXPORT_SYMBOL_NOVERS(memcpy);
-EXPORT_SYMBOL_NOVERS(memmove);
-EXPORT_SYMBOL_NOVERS(memcmp);
-EXPORT_SYMBOL_NOVERS(memscan);
-EXPORT_SYMBOL_NOVERS(__memzero);
+EXPORT_SYMBOL(strcpy);
+EXPORT_SYMBOL(strncpy);
+EXPORT_SYMBOL(strcat);
+EXPORT_SYMBOL(strncat);
+EXPORT_SYMBOL(strcmp);
+EXPORT_SYMBOL(strncmp);
+EXPORT_SYMBOL(strchr);
+EXPORT_SYMBOL(strlen);
+EXPORT_SYMBOL(strnlen);
+EXPORT_SYMBOL(strpbrk);
+EXPORT_SYMBOL(strrchr);
+EXPORT_SYMBOL(strstr);
+EXPORT_SYMBOL(memset);
+EXPORT_SYMBOL(memcpy);
+EXPORT_SYMBOL(memmove);
+EXPORT_SYMBOL(memcmp);
+EXPORT_SYMBOL(memscan);
+EXPORT_SYMBOL(__memzero);
 
 	/* user mem (segment) */
 EXPORT_SYMBOL(uaccess_kernel);
 EXPORT_SYMBOL(uaccess_user);
 
-EXPORT_SYMBOL_NOVERS(__get_user_1);
-EXPORT_SYMBOL_NOVERS(__get_user_2);
-EXPORT_SYMBOL_NOVERS(__get_user_4);
-EXPORT_SYMBOL_NOVERS(__get_user_8);
-
-EXPORT_SYMBOL_NOVERS(__put_user_1);
-EXPORT_SYMBOL_NOVERS(__put_user_2);
-EXPORT_SYMBOL_NOVERS(__put_user_4);
-EXPORT_SYMBOL_NOVERS(__put_user_8);
+EXPORT_SYMBOL(__get_user_1);
+EXPORT_SYMBOL(__get_user_2);
+EXPORT_SYMBOL(__get_user_4);
+EXPORT_SYMBOL(__get_user_8);
+
+EXPORT_SYMBOL(__put_user_1);
+EXPORT_SYMBOL(__put_user_2);
+EXPORT_SYMBOL(__put_user_4);
+EXPORT_SYMBOL(__put_user_8);
 
 	/* gcc lib functions */
-EXPORT_SYMBOL_NOVERS(__ashldi3);
-EXPORT_SYMBOL_NOVERS(__ashrdi3);
-EXPORT_SYMBOL_NOVERS(__divsi3);
-EXPORT_SYMBOL_NOVERS(__lshrdi3);
-EXPORT_SYMBOL_NOVERS(__modsi3);
-EXPORT_SYMBOL_NOVERS(__muldi3);
-EXPORT_SYMBOL_NOVERS(__ucmpdi2);
-EXPORT_SYMBOL_NOVERS(__udivdi3);
-EXPORT_SYMBOL_NOVERS(__umoddi3);
-EXPORT_SYMBOL_NOVERS(__udivmoddi4);
-EXPORT_SYMBOL_NOVERS(__udivsi3);
-EXPORT_SYMBOL_NOVERS(__umodsi3);
+EXPORT_SYMBOL(__ashldi3);
+EXPORT_SYMBOL(__ashrdi3);
+EXPORT_SYMBOL(__divsi3);
+EXPORT_SYMBOL(__lshrdi3);
+EXPORT_SYMBOL(__modsi3);
+EXPORT_SYMBOL(__muldi3);
+EXPORT_SYMBOL(__ucmpdi2);
+EXPORT_SYMBOL(__udivdi3);
+EXPORT_SYMBOL(__umoddi3);
+EXPORT_SYMBOL(__udivmoddi4);
+EXPORT_SYMBOL(__udivsi3);
+EXPORT_SYMBOL(__umodsi3);
 
 	/* bitops */
 EXPORT_SYMBOL(_set_bit_le);
@@ -214,10 +214,10 @@
 EXPORT_SYMBOL(sys_wait4);
 
 	/* semaphores */
-EXPORT_SYMBOL_NOVERS(__down_failed);
-EXPORT_SYMBOL_NOVERS(__down_interruptible_failed);
-EXPORT_SYMBOL_NOVERS(__down_trylock_failed);
-EXPORT_SYMBOL_NOVERS(__up_wakeup);
+EXPORT_SYMBOL(__down_failed);
+EXPORT_SYMBOL(__down_interruptible_failed);
+EXPORT_SYMBOL(__down_trylock_failed);
+EXPORT_SYMBOL(__up_wakeup);
 
 EXPORT_SYMBOL(get_wchan);
 
diff -Nru a/arch/arm26/kernel/irq.c b/arch/arm26/kernel/irq.c
--- a/arch/arm26/kernel/irq.c	2004-10-18 14:57:03 -07:00
+++ b/arch/arm26/kernel/irq.c	2004-10-18 14:57:03 -07:00
@@ -187,6 +187,7 @@
 __do_irq(unsigned int irq, struct irqaction *action, struct pt_regs *regs)
 {
 	unsigned int status;
+	int ret;
 
 	spin_unlock(&irq_controller_lock);
 	if (!(action->flags & SA_INTERRUPT))
@@ -194,8 +195,9 @@
 
 	status = 0;
 	do {
-		status |= action->flags;
-		action->handler(irq, action->dev_id, regs);
+		ret = action->handler(irq, action->dev_id, regs);
+		if (ret == IRQ_HANDLED)
+			status |= action->flags;
 		action = action->next;
 	} while (action);
 
diff -Nru a/arch/arm26/kernel/ptrace.c b/arch/arm26/kernel/ptrace.c
--- a/arch/arm26/kernel/ptrace.c	2004-10-18 14:56:32 -07:00
+++ b/arch/arm26/kernel/ptrace.c	2004-10-18 14:56:32 -07:00
@@ -729,11 +729,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
 	 * for normal use.  strace only continues with a signal if the
diff -Nru a/arch/arm26/kernel/signal.c b/arch/arm26/kernel/signal.c
--- a/arch/arm26/kernel/signal.c	2004-10-18 14:56:27 -07:00
+++ b/arch/arm26/kernel/signal.c	2004-10-18 14:56:27 -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-10-18 14:56:33 -07:00
+++ b/arch/arm26/kernel/sys_arm.c	2004-10-18 14:56:33 -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-10-18 14:56:48 -07:00
+++ b/arch/arm26/kernel/time.c	2004-10-18 14:56:48 -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-10-18 14:56:50 -07:00
+++ b/arch/arm26/kernel/vmlinux-arm26-xip.lds.in	2004-10-18 14:56:50 -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-10-18 14:55:55 -07:00
+++ b/arch/arm26/kernel/vmlinux-arm26.lds.in	2004-10-18 14:55: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-10-18 14:57:04 -07:00
+++ b/arch/arm26/mm/init.c	2004-10-18 14:57:04 -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;
@@ -376,7 +376,7 @@
 	 * Turn on overcommit on tiny machines
 	 */
 	if (PAGE_SIZE >= 16384 && num_physpages <= 128) {
-		sysctl_overcommit_memory = 1;
+		sysctl_overcommit_memory = OVERCOMMIT_ALWAYS;
 		printk("Turning on overcommit\n");
 	}
 }
diff -Nru a/arch/cris/Kconfig b/arch/cris/Kconfig
--- a/arch/cris/Kconfig	2004-10-18 14:57:03 -07:00
+++ b/arch/cris/Kconfig	2004-10-18 14:57:03 -07:00
@@ -20,8 +20,11 @@
 config RWSEM_XCHGADD_ALGORITHM
 	bool
 
-source "init/Kconfig"
+config CRIS
+	bool
+	default y
 
+source "init/Kconfig"
 
 menu "General setup"
 
@@ -51,7 +54,7 @@
        bool "Enable ETRAX fast timer API"
        help
          This options enables the API to a fast timer implementation using
-	 timer1 to get sub jiffie resolution timers (primarily one-shot 
+	 timer1 to get sub jiffie resolution timers (primarily one-shot
 	 timers).
 	 This is needed if CONFIG_ETRAX_SERIAL_FAST_TIMER is enabled.
 
@@ -69,7 +72,6 @@
 
 endmenu
 
-
 menu "Hardware setup"
 
 choice
@@ -96,7 +98,7 @@
 config ETRAX_ARCH_V10
        bool
        default y if ETRAX100LX || ETRAX100LX_V2
-       default n if !(ETRAX100LX || ETRAX100LX_V2) 
+       default n if !(ETRAX100LX || ETRAX100LX_V2)
 
 config ETRAX_DRAM_SIZE
 	int "DRAM size (dec, in MB)"
@@ -165,54 +167,10 @@
 
 source "drivers/usb/Kconfig"
 
-
-menu "Kernel hacking"
-
-#bool 'Debug kmalloc/kfree' CONFIG_DEBUG_MALLOC
-config PROFILE
-	bool "Kernel profiling support"
-
-config PROFILE_SHIFT
-	int "Profile shift count"
-	depends on PROFILE
-	default "2"
-
-config ETRAX_KGDB
-	bool "Use kernel GDB debugger"
-	---help---
-	  The CRIS version of gdb can be used to remotely debug a running
-	  Linux kernel via the serial debug port.  Provided you have gdb-cris
-	  installed, run gdb-cris vmlinux, then type
-
-	  (gdb) set remotebaud 115200           <- kgdb uses 115200 as default
-	  (gdb) target remote /dev/ttyS0        <- maybe you use another port
-
-	  This should connect you to your booted kernel (or boot it now if you
-	  didn't before).  The kernel halts when it boots, waiting for gdb if
-	  this option is turned on!
-
-
-config DEBUG_INFO
-        bool "Compile the kernel with debug info"
-        help
-          If you say Y here the resulting kernel image will include
-          debugging info resulting in a larger kernel image.
-          Say Y here only if you plan to use gdb to debug the kernel.
-          If you don't debug the kernel, you can say N.
-
-config FRAME_POINTER
-        bool "Compile the kernel with frame pointers"
-        help
-          If you say Y here the resulting kernel image will be slightly larger
-          and slower, but it will give very useful debugging information.
-          If you don't debug the kernel, you can say N, but we may not be able
-          to solve problems without frame pointers.
-
-endmenu
+source "arch/cris/Kconfig.debug"
 
 source "security/Kconfig"
 
 source "crypto/Kconfig"
 
 source "lib/Kconfig"
-
diff -Nru a/arch/cris/Kconfig.debug b/arch/cris/Kconfig.debug
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/arch/cris/Kconfig.debug	2004-10-18 14:57:24 -07:00
@@ -0,0 +1,28 @@
+menu "Kernel hacking"
+
+source "lib/Kconfig.debug"
+
+#bool 'Debug kmalloc/kfree' CONFIG_DEBUG_MALLOC
+config PROFILE
+	bool "Kernel profiling support"
+
+config PROFILE_SHIFT
+	int "Profile shift count"
+	depends on PROFILE
+	default "2"
+
+config ETRAX_KGDB
+	bool "Use kernel GDB debugger"
+	---help---
+	  The CRIS version of gdb can be used to remotely debug a running
+	  Linux kernel via the serial debug port.  Provided you have gdb-cris
+	  installed, run gdb-cris vmlinux, then type
+
+	  (gdb) set remotebaud 115200           <- kgdb uses 115200 as default
+	  (gdb) target remote /dev/ttyS0        <- maybe you use another port
+
+	  This should connect you to your booted kernel (or boot it now if you
+	  didn't before).  The kernel halts when it boots, waiting for gdb if
+	  this option is turned on!
+
+endmenu
diff -Nru a/arch/cris/Makefile b/arch/cris/Makefile
--- a/arch/cris/Makefile	2004-10-18 14:56:29 -07:00
+++ b/arch/cris/Makefile	2004-10-18 14:56:29 -07:00
@@ -24,12 +24,10 @@
 endif
 
 LD = $(CROSS_COMPILE)ld -mcrislinux
-LDFLAGS_BLOB	:= --format binary --oformat elf32-cris \
-		   -T arch/cris/$(SARCH)/output_arch.ld
 
 OBJCOPYFLAGS := -O binary -R .note -R .comment -S
 
-AFLAGS_vmlinux.lds.o = -DDRAM_VIRTUAL_BASE=0x$(CONFIG_ETRAX_DRAM_VIRTUAL_BASE)
+CPPFLAGS_vmlinux.lds = -DDRAM_VIRTUAL_BASE=0x$(CONFIG_ETRAX_DRAM_VIRTUAL_BASE)
 AFLAGS += -mlinux
 
 CFLAGS := $(CFLAGS) -mlinux -march=$(arch-y) -pipe
@@ -39,7 +37,7 @@
 CFLAGS += -fno-omit-frame-pointer
 endif
 
-HEAD := arch/$(ARCH)/$(SARCH)/kernel/head.o
+head-y := arch/$(ARCH)/$(SARCH)/kernel/head.o
 
 LIBGCC = $(shell $(CC) $(CFLAGS) -print-file-name=libgcc.a)
 
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-10-18 14:55:54 -07:00
+++ b/arch/cris/arch-v10/kernel/debugport.c	2004-10-18 14:55:54 -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-10-18 14:56:33 -07:00
+++ b/arch/cris/arch-v10/kernel/process.c	2004-10-18 14:56:33 -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/ptrace.c b/arch/cris/arch-v10/kernel/ptrace.c
--- a/arch/cris/arch-v10/kernel/ptrace.c	2004-10-18 14:57:04 -07:00
+++ b/arch/cris/arch-v10/kernel/ptrace.c	2004-10-18 14:57:04 -07:00
@@ -85,17 +85,8 @@
 		goto out_tsk;
 	}
 	
-	ret = -ESRCH;
-	
-	if (!(child->ptrace & PT_PTRACED))
-		goto out_tsk;
-	
-	if (child->state != TASK_STOPPED) {
-		if (request != PTRACE_KILL)
-			goto out_tsk;
-	}
-	
-	if (child->parent != current)
+	ret = ptrace_check_attach(child, request == PTRACE_KILL);
+	if (ret < 0)
 		goto out_tsk;
 
 	switch (request) {
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-10-18 14:55:54 -07:00
+++ b/arch/cris/arch-v10/kernel/signal.c	2004-10-18 14:55:54 -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	2004-10-18 14:56:17 -07:00
+++ b/arch/cris/arch-v10/mm/init.c	2004-10-18 14:56:17 -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-10-18 14:56:29 -07:00
+++ b/arch/cris/arch-v10/vmlinux.lds.S	2004-10-18 14:56:29 -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/cris/kernel/Makefile b/arch/cris/kernel/Makefile
--- a/arch/cris/kernel/Makefile	2004-10-18 14:56:33 -07:00
+++ b/arch/cris/kernel/Makefile	2004-10-18 14:56:33 -07:00
@@ -3,7 +3,7 @@
 # Makefile for the linux kernel.
 #
 
-extra-y	:= vmlinux.lds.s
+extra-y	:= vmlinux.lds
 
 obj-y   := process.o traps.o irq.o ptrace.o setup.o \
 	   time.o sys_cris.o semaphore.o
diff -Nru a/arch/cris/kernel/crisksyms.c b/arch/cris/kernel/crisksyms.c
--- a/arch/cris/kernel/crisksyms.c	2004-10-18 14:56:49 -07:00
+++ b/arch/cris/kernel/crisksyms.c	2004-10-18 14:56:49 -07:00
@@ -16,7 +16,6 @@
 #include <asm/uaccess.h>
 #include <asm/checksum.h>
 #include <asm/io.h>
-#include <asm/hardirq.h>
 #include <asm/delay.h>
 #include <asm/irq.h>
 #include <asm/pgtable.h>
@@ -91,8 +90,8 @@
 #undef memset
 extern void * memset(void *, int, __kernel_size_t);
 extern void * memcpy(void *, const void *, __kernel_size_t);
-EXPORT_SYMBOL_NOVERS(memcpy);
-EXPORT_SYMBOL_NOVERS(memset);
+EXPORT_SYMBOL(memcpy);
+EXPORT_SYMBOL(memset);
 
 #ifdef CONFIG_ETRAX_FAST_TIMER
 /* Fast timer functions */
diff -Nru a/arch/cris/kernel/irq.c b/arch/cris/kernel/irq.c
--- a/arch/cris/kernel/irq.c	2004-10-18 14:57:04 -07:00
+++ b/arch/cris/kernel/irq.c	2004-10-18 14:57:04 -07:00
@@ -125,7 +125,7 @@
 {
 	struct irqaction *action;
 	int do_random, cpu;
-        int retval = 0;
+        int ret, retval = 0;
 
         cpu = smp_processor_id();
         irq_enter();
@@ -137,8 +137,10 @@
                         local_irq_enable();
                 do_random = 0;
                 do {
-                        do_random |= action->flags;
-                        retval |= action->handler(irq, action->dev_id, regs);
+			ret = action->handler(irq, action->dev_id, regs);
+			if (ret == IRQ_HANDLED)
+				do_random |= action->flags;
+                        retval |= ret;
                         action = action->next;
                 } while (action);
 
diff -Nru a/arch/h8300/Kconfig b/arch/h8300/Kconfig
--- a/arch/h8300/Kconfig	2004-10-18 14:56:49 -07:00
+++ b/arch/h8300/Kconfig	2004-10-18 14:56:49 -07:00
@@ -176,86 +176,15 @@
 source "drivers/i2c/Kconfig"
 
 source "drivers/usb/Kconfig"
- 
+
 endmenu
 
 source "fs/Kconfig"
 
-menu "Kernel hacking"
-
-config FULLDEBUG
-	bool "Full Symbolic/Source Debugging support"
-	help
-	  Enable debugging symbols on kernel build.
-
-config MAGIC_SYSRQ
-	bool "Magic SysRq key"
-	help
-	  Enables console device to interprent special characters as
-	  commands to dump state information.
-
-config HIGHPROFILE
-	bool "Use fast second timer for profiling"
-	help
-	  Use a fast secondary clock to produce profiling information.
-
-config NO_KERNEL_MSG
-	bool "Suppress Kernel BUG Messages"
-	help
-	  Do not output any debug BUG messages within the kernel.
-
-config GDB_MAGICPRINT
-	bool "Message Output for GDB MagicPrint service"
-	depends on (H8300H_SIM || H8S_SIM)
-	help
-	  kernel messages output useing MagicPrint service from GDB
-
-config SYSCALL_PRINT
-	bool "SystemCall trace print"
-	help
-	  outout history of systemcall
-
-config GDB_DEBUG
-   	bool "Use gdb stub"
-	depends on (!H8300H_SIM && !H8S_SIM)
-	help
-	  gdb stub exception support
-
-config CONFIG_SH_STANDARD_BIOS
-	bool "Use gdb protocol serial console"
-	depends on (!H8300H_SIM && !H8S_SIM)
-	help
-	  serial console output using GDB protocol.
-	  Require eCos/RedBoot
-
-config DEFAULT_CMDLINE
-	bool "Use buildin commandline"
-	default n
-	help
-	  buildin kernel commandline enabled.
-
-config KERNEL_COMMAND
-	string "Buildin commmand string"
-	depends on DEFAULT_CMDLINE
-	help
-	  buildin kernel commandline strings.
-
-config BLKDEV_RESERVE
-	bool "BLKDEV Reserved Memory"
-	default n
-	help
-	  Reserved BLKDEV area.
-
-config CONFIG_BLKDEV_RESERVE_ADDRESS
-	hex 'start address'
-	depends on BLKDEV_RESERVE
-	help
-	  BLKDEV start address.
-endmenu
+source "arch/h8300/Kconfig.debug"
 
 source "security/Kconfig"
 
 source "crypto/Kconfig"
 
 source "lib/Kconfig"
-
diff -Nru a/arch/h8300/Kconfig.debug b/arch/h8300/Kconfig.debug
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/arch/h8300/Kconfig.debug	2004-10-18 14:57:22 -07:00
@@ -0,0 +1,68 @@
+menu "Kernel hacking"
+
+source "lib/Kconfig.debug"
+
+config FULLDEBUG
+	bool "Full Symbolic/Source Debugging support"
+	help
+	  Enable debugging symbols on kernel build.
+
+config HIGHPROFILE
+	bool "Use fast second timer for profiling"
+	help
+	  Use a fast secondary clock to produce profiling information.
+
+config NO_KERNEL_MSG
+	bool "Suppress Kernel BUG Messages"
+	help
+	  Do not output any debug BUG messages within the kernel.
+
+config GDB_MAGICPRINT
+	bool "Message Output for GDB MagicPrint service"
+	depends on (H8300H_SIM || H8S_SIM)
+	help
+	  kernel messages output useing MagicPrint service from GDB
+
+config SYSCALL_PRINT
+	bool "SystemCall trace print"
+	help
+	  outout history of systemcall
+
+config GDB_DEBUG
+   	bool "Use gdb stub"
+	depends on (!H8300H_SIM && !H8S_SIM)
+	help
+	  gdb stub exception support
+
+config CONFIG_SH_STANDARD_BIOS
+	bool "Use gdb protocol serial console"
+	depends on (!H8300H_SIM && !H8S_SIM)
+	help
+	  serial console output using GDB protocol.
+	  Require eCos/RedBoot
+
+config DEFAULT_CMDLINE
+	bool "Use buildin commandline"
+	default n
+	help
+	  buildin kernel commandline enabled.
+
+config KERNEL_COMMAND
+	string "Buildin commmand string"
+	depends on DEFAULT_CMDLINE
+	help
+	  buildin kernel commandline strings.
+
+config BLKDEV_RESERVE
+	bool "BLKDEV Reserved Memory"
+	default n
+	help
+	  Reserved BLKDEV area.
+
+config CONFIG_BLKDEV_RESERVE_ADDRESS
+	hex 'start address'
+	depends on BLKDEV_RESERVE
+	help
+	  BLKDEV start address.
+
+endmenu
diff -Nru a/arch/h8300/kernel/Makefile b/arch/h8300/kernel/Makefile
--- a/arch/h8300/kernel/Makefile	2004-10-18 14:56:33 -07:00
+++ b/arch/h8300/kernel/Makefile	2004-10-18 14:56:33 -07:00
@@ -2,7 +2,7 @@
 # Makefile for the linux kernel.
 #
 
-extra-y := vmlinux.lds.s
+extra-y := vmlinux.lds
 
 obj-y := process.o traps.o ptrace.o ints.o \
 	 sys_h8300.o time.o semaphore.o signal.o \
diff -Nru a/arch/h8300/kernel/asm-offsets.c b/arch/h8300/kernel/asm-offsets.c
--- a/arch/h8300/kernel/asm-offsets.c	2004-10-18 14:55:54 -07:00
+++ b/arch/h8300/kernel/asm-offsets.c	2004-10-18 14:55:54 -07:00
@@ -12,9 +12,9 @@
 #include <linux/sched.h>
 #include <linux/kernel_stat.h>
 #include <linux/ptrace.h>
+#include <linux/hardirq.h>
 #include <asm/bootinfo.h>
 #include <asm/irq.h>
-#include <asm/hardirq.h>
 #include <asm/ptrace.h>
 
 #define DEFINE(sym, val) \
diff -Nru a/arch/h8300/kernel/h8300_ksyms.c b/arch/h8300/kernel/h8300_ksyms.c
--- a/arch/h8300/kernel/h8300_ksyms.c	2004-10-18 14:57:03 -07:00
+++ b/arch/h8300/kernel/h8300_ksyms.c	2004-10-18 14:57:03 -07:00
@@ -15,7 +15,6 @@
 #include <asm/io.h>
 #include <asm/semaphore.h>
 #include <asm/checksum.h>
-#include <asm/hardirq.h>
 #include <asm/current.h>
 #include <asm/gpio.h>
 
@@ -50,13 +49,13 @@
    explicitly (the C compiler generates them).  Fortunately,
    their interface isn't gonna change any time soon now, so
    it's OK to leave it out of version control.  */
-//EXPORT_SYMBOL_NOVERS(__ashrdi3);
-//EXPORT_SYMBOL_NOVERS(__lshrdi3);
-EXPORT_SYMBOL_NOVERS(memcpy);
-EXPORT_SYMBOL_NOVERS(memset);
-EXPORT_SYMBOL_NOVERS(memcmp);
-EXPORT_SYMBOL_NOVERS(memscan);
-EXPORT_SYMBOL_NOVERS(memmove);
+//EXPORT_SYMBOL(__ashrdi3);
+//EXPORT_SYMBOL(__lshrdi3);
+EXPORT_SYMBOL(memcpy);
+EXPORT_SYMBOL(memset);
+EXPORT_SYMBOL(memcmp);
+EXPORT_SYMBOL(memscan);
+EXPORT_SYMBOL(memmove);
 
 EXPORT_SYMBOL(get_wchan);
 
@@ -85,29 +84,29 @@
 extern void __umodsi3(void);
 
         /* gcc lib functions */
-EXPORT_SYMBOL_NOVERS(__gcc_bcmp);
-EXPORT_SYMBOL_NOVERS(__ashldi3);
-EXPORT_SYMBOL_NOVERS(__ashrdi3);
-EXPORT_SYMBOL_NOVERS(__cmpdi2);
-EXPORT_SYMBOL_NOVERS(__divdi3);
-EXPORT_SYMBOL_NOVERS(__divsi3);
-EXPORT_SYMBOL_NOVERS(__lshrdi3);
-EXPORT_SYMBOL_NOVERS(__moddi3);
-EXPORT_SYMBOL_NOVERS(__modsi3);
-EXPORT_SYMBOL_NOVERS(__muldi3);
-EXPORT_SYMBOL_NOVERS(__mulsi3);
-EXPORT_SYMBOL_NOVERS(__negdi2);
-EXPORT_SYMBOL_NOVERS(__ucmpdi2);
-EXPORT_SYMBOL_NOVERS(__udivdi3);
-EXPORT_SYMBOL_NOVERS(__udivmoddi4);
-EXPORT_SYMBOL_NOVERS(__udivsi3);
-EXPORT_SYMBOL_NOVERS(__umoddi3);
-EXPORT_SYMBOL_NOVERS(__umodsi3);
+EXPORT_SYMBOL(__gcc_bcmp);
+EXPORT_SYMBOL(__ashldi3);
+EXPORT_SYMBOL(__ashrdi3);
+EXPORT_SYMBOL(__cmpdi2);
+EXPORT_SYMBOL(__divdi3);
+EXPORT_SYMBOL(__divsi3);
+EXPORT_SYMBOL(__lshrdi3);
+EXPORT_SYMBOL(__moddi3);
+EXPORT_SYMBOL(__modsi3);
+EXPORT_SYMBOL(__muldi3);
+EXPORT_SYMBOL(__mulsi3);
+EXPORT_SYMBOL(__negdi2);
+EXPORT_SYMBOL(__ucmpdi2);
+EXPORT_SYMBOL(__udivdi3);
+EXPORT_SYMBOL(__udivmoddi4);
+EXPORT_SYMBOL(__udivsi3);
+EXPORT_SYMBOL(__umoddi3);
+EXPORT_SYMBOL(__umodsi3);
 
 #ifdef MAGIC_ROM_PTR
-EXPORT_SYMBOL_NOVERS(is_in_rom);
+EXPORT_SYMBOL(is_in_rom);
 #endif
 
-EXPORT_SYMBOL_NOVERS(h8300_reserved_gpio);
-EXPORT_SYMBOL_NOVERS(h8300_free_gpio);
-EXPORT_SYMBOL_NOVERS(h8300_set_gpio_dir);
+EXPORT_SYMBOL(h8300_reserved_gpio);
+EXPORT_SYMBOL(h8300_free_gpio);
+EXPORT_SYMBOL(h8300_set_gpio_dir);
diff -Nru a/arch/h8300/kernel/ints.c b/arch/h8300/kernel/ints.c
--- a/arch/h8300/kernel/ints.c	2004-10-18 14:56:27 -07:00
+++ b/arch/h8300/kernel/ints.c	2004-10-18 14:56:27 -07:00
@@ -22,13 +22,13 @@
 #include <linux/init.h>
 #include <linux/random.h>
 #include <linux/bootmem.h>
+#include <linux/hardirq.h>
 
 #include <asm/system.h>
 #include <asm/irq.h>
 #include <asm/traps.h>
 #include <asm/io.h>
 #include <asm/setup.h>
-#include <asm/hardirq.h>
 #include <asm/errno.h>
 
 /*
diff -Nru a/arch/h8300/kernel/process.c b/arch/h8300/kernel/process.c
--- a/arch/h8300/kernel/process.c	2004-10-18 14:55:53 -07:00
+++ b/arch/h8300/kernel/process.c	2004-10-18 14:55:53 -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/ptrace.c b/arch/h8300/kernel/ptrace.c
--- a/arch/h8300/kernel/ptrace.c	2004-10-18 14:56:28 -07:00
+++ b/arch/h8300/kernel/ptrace.c	2004-10-18 14:56:28 -07:00
@@ -89,13 +89,6 @@
 		ret = ptrace_attach(child);
 		goto out_tsk;
 	}
-	ret = -ESRCH;
-	if (!(child->ptrace & PT_PTRACED))
-		goto out_tsk;
-	if (child->state != TASK_STOPPED) {
-		if (request != PTRACE_KILL)
-			goto out_tsk;
-	}
 	ret = ptrace_check_attach(child, request == PTRACE_KILL);
 	if (ret < 0)
 		goto out_tsk;
@@ -114,7 +107,7 @@
 
 	/* read the word at location addr in the USER area. */
 		case PTRACE_PEEKUSR: {
-			unsigned long tmp;
+			unsigned long tmp = 0;
 			
 			if ((addr & 3) || addr < 0 || addr >= sizeof(struct user)) {
 				ret = -EIO;
@@ -270,10 +263,8 @@
 		return;
 	if (!(current->ptrace & PT_PTRACED))
 		return;
-	current->exit_code = SIGTRAP;
-	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
 	 * for normal use.  strace only continues with a signal if the
diff -Nru a/arch/h8300/kernel/signal.c b/arch/h8300/kernel/signal.c
--- a/arch/h8300/kernel/signal.c	2004-10-18 14:56:32 -07:00
+++ b/arch/h8300/kernel/signal.c	2004-10-18 14:56:32 -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-10-18 14:56:28 -07:00
+++ b/arch/h8300/kernel/time.c	2004-10-18 14:56:28 -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-10-18 14:56:33 -07:00
+++ b/arch/h8300/kernel/vmlinux.lds.S	2004-10-18 14:56:33 -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/h8300/lib/checksum.c b/arch/h8300/lib/checksum.c
--- a/arch/h8300/lib/checksum.c	2004-10-18 14:55:54 -07:00
+++ b/arch/h8300/lib/checksum.c	2004-10-18 14:55:54 -07:00
@@ -32,6 +32,7 @@
    of the assembly has to go. */
 
 #include <net/checksum.h>
+#include <linux/module.h>
 
 static inline unsigned short from32to16(unsigned long x)
 {
diff -Nru a/arch/h8300/platform/h8300h/generic/timer.c b/arch/h8300/platform/h8300h/generic/timer.c
--- a/arch/h8300/platform/h8300h/generic/timer.c	2004-10-18 14:56:28 -07:00
+++ b/arch/h8300/platform/h8300h/generic/timer.c	2004-10-18 14:56:28 -07:00
@@ -32,7 +32,7 @@
 
 #define H8300_TIMER_FREQ CONFIG_CPU_CLOCK*1000/8192 /* Timer input freq. */
 
-int platform_timer_setup(irqreturn_t (*timer_int)(int, void *, struct pt_regs *))
+void __init platform_timer_setup(irqreturn_t (*timer_int)(int, void *, struct pt_regs *))
 {
 	/* setup 8bit timer ch2 */
 	ctrl_outb(H8300_TIMER_FREQ / HZ, TCORA2);      /* set interval */
@@ -69,7 +69,7 @@
 
 #define H8300_TIMER_FREQ CONFIG_CPU_CLOCK*1000/8 /* Timer input freq. */
 
-int platform_timer_setup(irqreturn_t (*timer_int)(int, void *, struct pt_regs *))
+void __init platform_timer_setup(irqreturn_t (*timer_int)(int, void *, struct pt_regs *))
 {
 	*(unsigned short *)GRA= H8300_TIMER_FREQ / HZ;  /* set interval */
 	*(unsigned short *)TCNT=0;                      /* clear counter */
diff -Nru a/arch/h8300/platform/h8s/ints.c b/arch/h8300/platform/h8s/ints.c
--- a/arch/h8300/platform/h8s/ints.c	2004-10-18 14:56:28 -07:00
+++ b/arch/h8300/platform/h8s/ints.c	2004-10-18 14:56:28 -07:00
@@ -22,6 +22,7 @@
 #include <linux/init.h>
 #include <linux/bootmem.h>
 #include <linux/random.h>
+#include <linux/hardirq.h>
 
 #include <asm/system.h>
 #include <asm/irq.h>
@@ -29,7 +30,6 @@
 #include <asm/io.h>
 #include <asm/setup.h>
 #include <asm/gpio.h>
-#include <asm/hardirq.h>
 #include <asm/regs267x.h>
 #include <asm/errno.h>
 
diff -Nru a/arch/i386/Kconfig b/arch/i386/Kconfig
--- a/arch/i386/Kconfig	2004-10-18 14:56:12 -07:00
+++ b/arch/i386/Kconfig	2004-10-18 14:56:12 -07:00
@@ -29,8 +29,11 @@
 	bool
 	default y
 
-source "init/Kconfig"
+config GENERIC_IOMAP
+	bool
+	default y
 
+source "init/Kconfig"
 
 menu "Processor type and features"
 
@@ -55,20 +58,20 @@
 config X86_VOYAGER
 	bool "Voyager (NCR)"
 	help
-	  Voyager is a MCA based 32 way capable SMP architecture proprietary
-	  to NCR Corp.  Machine classes 345x/35xx/4100/51xx are voyager based.
-	  
+	  Voyager is an MCA-based 32-way capable SMP architecture proprietary
+	  to NCR Corp.  Machine classes 345x/35xx/4100/51xx are Voyager-based.
+
 	  *** WARNING ***
-	
+
 	  If you do not specifically know you have a Voyager based machine,
-	  say N here otherwise the kernel you build will not be bootable.
+	  say N here, otherwise the kernel you build will not be bootable.
 
 config X86_NUMAQ
 	bool "NUMAQ (IBM/Sequent)"
 	select DISCONTIGMEM
 	select NUMA
 	help
-	  This option is used for getting Linux to run on a (IBM/Sequent) NUMA 
+	  This option is used for getting Linux to run on a (IBM/Sequent) NUMA
 	  multiquad box. This changes the way that processors are bootstrapped,
 	  and uses Clustered Logical APIC addressing mode instead of Flat Logical.
 	  You will need a new lynxer.elf file to flash your firmware with - send
@@ -115,8 +118,8 @@
 	depends on SMP
 	help
 	  Support for Unisys ES7000 systems.  Say 'Y' here if this kernel is
-	  supposed to run on an IA32-based Unisys ES7000 system. 
-	  Only choose this option if you have such a system, otherwise you 
+	  supposed to run on an IA32-based Unisys ES7000 system.
+	  Only choose this option if you have such a system, otherwise you
 	  should say N here.
 
 endchoice
@@ -322,7 +325,7 @@
 endchoice
 
 config X86_GENERIC
-       bool "Generic x86 support" 
+       bool "Generic x86 support"
        help
 	  Instead of just including optimizations for the selected
 	  x86 variant (e.g. PII, Crusoe or Athlon), include some more
@@ -1027,7 +1030,6 @@
 
 endmenu
 
-
 menu "Bus options (PCI, PCMCIA, EISA, MCA, ISA)"
 
 config X86_VISWS_APIC
@@ -1105,7 +1107,7 @@
 
 config PCI_MMCONFIG
 	bool
-	depends on PCI && (PCI_GOMMCONFIG || PCI_GOANY)
+	depends on PCI && (PCI_GOMMCONFIG || (PCI_GOANY && ACPI))
 	select ACPI_BOOT
 	default y
 
@@ -1158,7 +1160,7 @@
 	tristate "NatSemi SCx200 support"
 	depends on !X86_VOYAGER
 	help
-	  This provides basic support for the National Semiconductor SCx200 
+	  This provides basic support for the National Semiconductor SCx200
 	  processor.  Right now this is just a driver for the GPIO pins.
 
 	  If you don't know what to do here, say N.
@@ -1172,7 +1174,6 @@
 
 endmenu
 
-
 menu "Executable file formats"
 
 source "fs/Kconfig.binfmt"
@@ -1185,130 +1186,7 @@
 
 source "arch/i386/oprofile/Kconfig"
 
-
-menu "Kernel hacking"
-
-config DEBUG_KERNEL
-	bool "Kernel debugging"
-	help
-	  Say Y here if you are developing drivers or trying to debug and
-	  identify kernel problems.
-
-config EARLY_PRINTK
-	bool "Early printk" if EMBEDDED
-	default y
-	help
-	  Write kernel log output directly into the VGA buffer or to a serial
-	  port.
-
-	  This is useful for kernel debugging when your machine crashes very
-	  early before the console code is initialized. For normal operation
-	  it is not recommended because it looks ugly and doesn't cooperate
-	  with klogd/syslogd or the X server. You should normally N here,
-	  unless you want to debug such a crash.
-
-config DEBUG_STACKOVERFLOW
-	bool "Check for stack overflows"
-	depends on DEBUG_KERNEL
-
-config DEBUG_STACK_USAGE
-	bool "Stack utilization instrumentation"
-	depends on DEBUG_KERNEL
-	help
-	  Enables the display of the minimum amount of free stack which each
-	  task has ever had available in the sysrq-T and sysrq-P debug output.
-
-	  This option will slow down process creation somewhat.
-
-config DEBUG_SLAB
-	bool "Debug memory allocations"
-	depends on DEBUG_KERNEL
-	help
-	  Say Y here to have the kernel do limited verification on memory
-	  allocation as well as poisoning memory on free to catch use of freed
-	  memory.
-
-config MAGIC_SYSRQ
-	bool "Magic SysRq key"
-	depends on DEBUG_KERNEL
-	help
-	  If you say Y here, you will have some control over the system even
-	  if the system crashes for example during kernel debugging (e.g., you
-	  will be able to flush the buffer cache to disk, reboot the system
-	  immediately or dump some status information). This is accomplished
-	  by pressing various keys while holding SysRq (Alt+PrintScreen). It
-	  also works on a serial console (on PC hardware at least), if you
-	  send a BREAK and then within 5 seconds a command keypress. The
-	  keys are documented in <file:Documentation/sysrq.txt>. Don't say Y
-	  unless you really know what this hack does.
-
-config DEBUG_SPINLOCK
-	bool "Spinlock debugging"
-	depends on DEBUG_KERNEL
-	help
-	  Say Y here and build SMP to catch missing spinlock initialization
-	  and certain other kinds of spinlock errors commonly made.  This is
-	  best used in conjunction with the NMI watchdog so that spinlock
-	  deadlocks are also debuggable.
-
-config DEBUG_PAGEALLOC
-	bool "Page alloc debugging"
-	depends on DEBUG_KERNEL
-	help
-	  Unmap pages from the kernel linear mapping after free_pages().
-	  This results in a large slowdown, but helps to find certain types
-	  of memory corruptions.
-
-config DEBUG_HIGHMEM
-	bool "Highmem debugging"
-	depends on DEBUG_KERNEL && HIGHMEM
-	help
-	  This options enables addition error checking for high memory systems.
-	  Disable for production systems.
-
-config DEBUG_INFO
-	bool "Compile the kernel with debug info"
-	depends on DEBUG_KERNEL
-	help
-          If you say Y here the resulting kernel image will include
-	  debugging info resulting in a larger kernel image.
-	  Say Y here only if you plan to use gdb to debug the kernel.
-	  If you don't debug the kernel, you can say N.
-	  
-config DEBUG_SPINLOCK_SLEEP
-	bool "Sleep-inside-spinlock checking"
-	help
-	  If you say Y here, various routines which may sleep will become very
-	  noisy if they are called with a spinlock held.	
-
-config FRAME_POINTER
-	bool "Compile the kernel with frame pointers"
-	help
-	  If you say Y here the resulting kernel image will be slightly larger
-	  and slower, but it will give very useful debugging information.
-	  If you don't debug the kernel, you can say N, but we may not be able
-	  to solve problems without frame pointers.
-
-config 4KSTACKS
-	bool "Use 4Kb for kernel stacks instead of 8Kb"
-	help
-	  If you say Y here the kernel will use a 4Kb stacksize for the
-	  kernel stack attached to each process/thread. This facilitates
-	  running more threads on a system and also reduces the pressure
-	  on the VM subsystem for higher order allocations. This option
-	  will also use IRQ stacks to compensate for the reduced stackspace.
-
-config X86_FIND_SMP_CONFIG
-	bool
-	depends on X86_LOCAL_APIC || X86_VOYAGER
-	default y
-
-config X86_MPPARSE
-	bool
-	depends on X86_LOCAL_APIC && !X86_VISWS
-	default y
-
-endmenu
+source "arch/i386/Kconfig.debug"
 
 source "security/Kconfig"
 
diff -Nru a/arch/i386/Kconfig.debug b/arch/i386/Kconfig.debug
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/arch/i386/Kconfig.debug	2004-10-18 14:57:23 -07:00
@@ -0,0 +1,80 @@
+menu "Kernel hacking"
+
+source "lib/Kconfig.debug"
+
+config EARLY_PRINTK
+	bool "Early printk" if EMBEDDED
+	default y
+	help
+	  Write kernel log output directly into the VGA buffer or to a serial
+	  port.
+
+	  This is useful for kernel debugging when your machine crashes very
+	  early before the console code is initialized. For normal operation
+	  it is not recommended because it looks ugly and doesn't cooperate
+	  with klogd/syslogd or the X server. You should normally N here,
+	  unless you want to debug such a crash.
+
+config DEBUG_STACKOVERFLOW
+	bool "Check for stack overflows"
+	depends on DEBUG_KERNEL
+
+config KPROBES
+	bool "Kprobes"
+	depends on DEBUG_KERNEL
+	help
+	  Kprobes allows you to trap at almost any kernel address and
+	  execute a callback function.  register_kprobe() establishes
+	  a probepoint and specifies the callback.  Kprobes is useful
+	  for kernel debugging, non-intrusive instrumentation and testing.
+	  If in doubt, say "N".
+
+config DEBUG_STACK_USAGE
+	bool "Stack utilization instrumentation"
+	depends on DEBUG_KERNEL
+	help
+	  Enables the display of the minimum amount of free stack which each
+	  task has ever had available in the sysrq-T and sysrq-P debug output.
+
+	  This option will slow down process creation somewhat.
+
+config DEBUG_PAGEALLOC
+	bool "Page alloc debugging"
+	depends on DEBUG_KERNEL
+	help
+	  Unmap pages from the kernel linear mapping after free_pages().
+	  This results in a large slowdown, but helps to find certain types
+	  of memory corruptions.
+
+config 4KSTACKS
+	bool "Use 4Kb for kernel stacks instead of 8Kb"
+	help
+	  If you say Y here the kernel will use a 4Kb stacksize for the
+	  kernel stack attached to each process/thread. This facilitates
+	  running more threads on a system and also reduces the pressure
+	  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
+	default y
+
+config X86_MPPARSE
+	bool
+	depends on X86_LOCAL_APIC && !X86_VISWS
+	default y
+
+endmenu
diff -Nru a/arch/i386/Makefile b/arch/i386/Makefile
--- a/arch/i386/Makefile	2004-10-18 14:56:28 -07:00
+++ b/arch/i386/Makefile	2004-10-18 14:56:28 -07:00
@@ -18,48 +18,47 @@
 LDFLAGS		:= -m elf_i386
 OBJCOPYFLAGS	:= -O binary -R .note -R .comment -S
 LDFLAGS_vmlinux :=
-CHECK		:= $(CHECK) -D__i386__=1
+CHECKFLAGS	+= -D__i386__
 
 CFLAGS += -pipe -msoft-float
 
 # prevent gcc from keeping the stack 16 byte aligned
-CFLAGS += $(call check_gcc,-mpreferred-stack-boundary=2,)
-
-align := $(subst -functions=0,,$(call check_gcc,-falign-functions=0,-malign-functions=0))
+CFLAGS += $(call cc-option,-mpreferred-stack-boundary=2)
 
+align := $(subst -functions=0,,$(call cc-option,-falign-functions=0,-malign-functions=0))
 cflags-$(CONFIG_M386)		+= -march=i386
 cflags-$(CONFIG_M486)		+= -march=i486
 cflags-$(CONFIG_M586)		+= -march=i586
 cflags-$(CONFIG_M586TSC)	+= -march=i586
-cflags-$(CONFIG_M586MMX)	+= $(call check_gcc,-march=pentium-mmx,-march=i586)
+cflags-$(CONFIG_M586MMX)	+= $(call cc-option,-march=pentium-mmx,-march=i586)
 cflags-$(CONFIG_M686)		+= -march=i686
-cflags-$(CONFIG_MPENTIUMII)	+= $(call check_gcc,-march=pentium2,-march=i686)
-cflags-$(CONFIG_MPENTIUMIII)	+= $(call check_gcc,-march=pentium3,-march=i686)
-cflags-$(CONFIG_MPENTIUMM)	+= $(call check_gcc,-march=pentium3,-march=i686)
-cflags-$(CONFIG_MPENTIUM4)	+= $(call check_gcc,-march=pentium4,-march=i686)
+cflags-$(CONFIG_MPENTIUMII)	+= $(call cc-option,-march=pentium2,-march=i686)
+cflags-$(CONFIG_MPENTIUMIII)	+= $(call cc-option,-march=pentium3,-march=i686)
+cflags-$(CONFIG_MPENTIUMM)	+= $(call cc-option,-march=pentium3,-march=i686)
+cflags-$(CONFIG_MPENTIUM4)	+= $(call cc-option,-march=pentium4,-march=i686)
 cflags-$(CONFIG_MK6)		+= -march=k6
 # Please note, that patches that add -march=athlon-xp and friends are pointless.
 # They make zero difference whatsosever to performance at this time.
-cflags-$(CONFIG_MK7)		+= $(call check_gcc,-march=athlon,-march=i686 $(align)-functions=4)
-cflags-$(CONFIG_MK8)		+= $(call check_gcc,-march=k8,$(call check_gcc,-march=athlon,-march=i686 $(align)-functions=4))
+cflags-$(CONFIG_MK7)		+= $(call cc-option,-march=athlon,-march=i686 $(align)-functions=4)
+cflags-$(CONFIG_MK8)		+= $(call cc-option,-march=k8,$(call cc-option,-march=athlon,-march=i686 $(align)-functions=4))
 cflags-$(CONFIG_MCRUSOE)	+= -march=i686 $(align)-functions=0 $(align)-jumps=0 $(align)-loops=0
-cflags-$(CONFIG_MWINCHIPC6)	+= $(call check_gcc,-march=winchip-c6,-march=i586)
-cflags-$(CONFIG_MWINCHIP2)	+= $(call check_gcc,-march=winchip2,-march=i586)
-cflags-$(CONFIG_MWINCHIP3D)	+= $(call check_gcc,-march=winchip2,-march=i586)
-cflags-$(CONFIG_MCYRIXIII)	+= $(call check_gcc,-march=c3,-march=i486) $(align)-functions=0 $(align)-jumps=0 $(align)-loops=0
-cflags-$(CONFIG_MVIAC3_2)	+= $(call check_gcc,-march=c3-2,-march=i686)
+cflags-$(CONFIG_MWINCHIPC6)	+= $(call cc-option,-march=winchip-c6,-march=i586)
+cflags-$(CONFIG_MWINCHIP2)	+= $(call cc-option,-march=winchip2,-march=i586)
+cflags-$(CONFIG_MWINCHIP3D)	+= $(call cc-option,-march=winchip2,-march=i586)
+cflags-$(CONFIG_MCYRIXIII)	+= $(call cc-option,-march=c3,-march=i486) $(align)-functions=0 $(align)-jumps=0 $(align)-loops=0
+cflags-$(CONFIG_MVIAC3_2)	+= $(call cc-option,-march=c3-2,-march=i686)
 
 # AMD Elan support
 cflags-$(CONFIG_X86_ELAN)	+= -march=i486
 
 # -mregparm=3 works ok on gcc-3.0 and later
 #
-GCC_VERSION			:= $(shell $(CONFIG_SHELL) $(srctree)/scripts/gcc-version.sh $(CC))
+GCC_VERSION			:= $(call cc-version)
 cflags-$(CONFIG_REGPARM) 	+= $(shell if [ $(GCC_VERSION) -ge 0300 ] ; then echo "-mregparm=3"; fi ;)
 
 # Disable unit-at-a-time mode, it makes gcc use a lot more stack
 # due to the lack of sharing of stacklots.
-CFLAGS += $(call check_gcc,-fno-unit-at-a-time,)
+CFLAGS += $(call cc-option,-fno-unit-at-a-time)
 
 CFLAGS += $(cflags-y)
 
diff -Nru a/arch/i386/boot/Makefile b/arch/i386/boot/Makefile
--- a/arch/i386/boot/Makefile	2004-10-18 14:56:28 -07:00
+++ b/arch/i386/boot/Makefile	2004-10-18 14:56:28 -07:00
@@ -29,9 +29,9 @@
 		   zImage bzImage
 subdir- 	:= compressed
 
-host-progs	:= tools/build
+hostprogs-y	:= tools/build
 
-HOSTCFLAGS_build.o := -Iinclude
+HOSTCFLAGS_build.o := $(LINUXINCLUDE)
 
 # ---------------------------------------------------------------------------
 
diff -Nru a/arch/i386/boot/setup.S b/arch/i386/boot/setup.S
--- a/arch/i386/boot/setup.S	2004-10-18 14:56:32 -07:00
+++ b/arch/i386/boot/setup.S	2004-10-18 14:56:32 -07:00
@@ -156,7 +156,7 @@
 					# can be located anywhere in
 					# low memory 0x10000 or higher.
 
-ramdisk_max:	.long (MAXMEM-1) & 0x7fffffff
+ramdisk_max:	.long (-__PAGE_OFFSET-(512 << 20)-1) & 0x7fffffff
 					# (Header version 0x0203 or later)
 					# The highest safe address for
 					# the contents of an initrd
diff -Nru a/arch/i386/boot/video.S b/arch/i386/boot/video.S
--- a/arch/i386/boot/video.S	2004-10-18 14:57:19 -07:00
+++ b/arch/i386/boot/video.S	2004-10-18 14:57:19 -07:00
@@ -232,6 +232,41 @@
 	xorl	%eax, %eax
 	movw	18(%di), %ax
 	movl	%eax, %fs:(PARAM_LFB_SIZE)
+
+# switching the DAC to 8-bit is for <= 8 bpp only
+	movw	%fs:(PARAM_LFB_DEPTH), %ax
+	cmpw	$8, %ax
+	jg	dac_done
+
+# get DAC switching capability
+	xorl	%eax, %eax
+	movb	10(%di), %al
+	testb	$1, %al
+	jz	dac_set
+
+# attempt to switch DAC to 8-bit
+	movw	$0x4f08, %ax
+	movw	$0x0800, %bx
+	int	$0x10
+	cmpw	$0x004f, %ax
+	jne     dac_set
+	movb    %bh, dac_size		# store actual DAC size
+
+dac_set:
+# set color size to DAC size
+	movb	dac_size, %al
+	movb	%al, %fs:(PARAM_LFB_COLORS+0)
+	movb	%al, %fs:(PARAM_LFB_COLORS+2)
+	movb	%al, %fs:(PARAM_LFB_COLORS+4)
+	movb	%al, %fs:(PARAM_LFB_COLORS+6)
+
+# set color offsets to 0
+	movb	$0, %fs:(PARAM_LFB_COLORS+1)
+	movb	$0, %fs:(PARAM_LFB_COLORS+3)
+	movb	$0, %fs:(PARAM_LFB_COLORS+5)
+	movb	$0, %fs:(PARAM_LFB_COLORS+7)
+
+dac_done:
 # get protected mode interface informations
 	movw	$0x4f0a, %ax
 	xorw	%bx, %bx
@@ -1929,6 +1964,7 @@
 do_restore:	.byte	0	# Screen contents altered during mode change
 svga_prefix:	.byte	VIDEO_FIRST_BIOS>>8	# Default prefix for BIOS modes
 graphic_mode:	.byte	0	# Graphic mode with a linear frame buffer
+dac_size:	.byte	6	# DAC bit depth
 
 # Status messages
 keymsg:		.ascii	"Press <RETURN> to see video modes available, "
diff -Nru a/arch/i386/kernel/Makefile b/arch/i386/kernel/Makefile
--- a/arch/i386/kernel/Makefile	2004-10-18 14:56:17 -07:00
+++ b/arch/i386/kernel/Makefile	2004-10-18 14:56:17 -07:00
@@ -2,7 +2,7 @@
 # Makefile for the linux kernel.
 #
 
-extra-y := head.o init_task.o vmlinux.lds.s
+extra-y := head.o init_task.o vmlinux.lds
 
 obj-y	:= process.o semaphore.o signal.o entry.o traps.o irq.o vm86.o \
 		ptrace.o i8259.o ioport.o ldt.o setup.o time.o sys_i386.o \
@@ -25,6 +25,7 @@
 obj-$(CONFIG_X86_IO_APIC)	+= io_apic.o
 obj-$(CONFIG_X86_NUMAQ)		+= numaq.o
 obj-$(CONFIG_X86_SUMMIT_NUMA)	+= summit.o
+obj-$(CONFIG_KPROBES)		+= kprobes.o
 obj-$(CONFIG_MODULES)		+= module.o
 obj-y				+= sysenter.o vsyscall.o
 obj-$(CONFIG_ACPI_SRAT) 	+= srat.o
@@ -41,11 +42,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/acpi/boot.c b/arch/i386/kernel/acpi/boot.c
--- a/arch/i386/kernel/acpi/boot.c	2004-10-18 14:56:50 -07:00
+++ b/arch/i386/kernel/acpi/boot.c	2004-10-18 14:56:50 -07:00
@@ -71,6 +71,7 @@
 int acpi_lapic;
 int acpi_ioapic;
 int acpi_strict;
+EXPORT_SYMBOL(acpi_strict);
 
 acpi_interrupt_flags acpi_sci_flags __initdata;
 int acpi_sci_override_gsi __initdata;
@@ -84,6 +85,11 @@
 #warning ACPI uses CMPXCHG, i486 and later hardware
 #endif
 
+#define MAX_MADT_ENTRIES	256
+u8 x86_acpiid_to_apicid[MAX_MADT_ENTRIES] =
+			{ [0 ... MAX_MADT_ENTRIES-1] = 0xff };
+EXPORT_SYMBOL(x86_acpiid_to_apicid);
+
 /* --------------------------------------------------------------------------
                               Boot-time Configuration
    -------------------------------------------------------------------------- */
@@ -225,6 +231,8 @@
 	if (processor->flags.enabled == 0)
 		return 0;
 
+	x86_acpiid_to_apicid[processor->acpi_id] = processor->id;
+
 	mp_register_lapic (
 		processor->id,					   /* APIC ID */
 		processor->flags.enabled);			  /* Enabled? */
@@ -822,9 +830,15 @@
 	 */
 	error = acpi_blacklisted();
 	if (error) {
-		printk(KERN_WARNING PREFIX "BIOS listed in blacklist, disabling ACPI support\n");
-		disable_acpi();
-		return error;
+		extern int acpi_force;
+
+		if (acpi_force) {
+			printk(KERN_WARNING PREFIX "acpi=force override\n");
+		} else {
+			printk(KERN_WARNING PREFIX "Disabling ACPI support\n");
+			disable_acpi();
+			return error;
+		}
 	}
 
 	/*
diff -Nru a/arch/i386/kernel/acpi/sleep.c b/arch/i386/kernel/acpi/sleep.c
--- a/arch/i386/kernel/acpi/sleep.c	2004-10-18 14:56:29 -07:00
+++ b/arch/i386/kernel/acpi/sleep.c	2004-10-18 14:56:29 -07:00
@@ -77,10 +77,7 @@
 		printk(KERN_ERR "ACPI: Wakeup code way too big, S3 disabled.\n");
 		return;
 	}
-#ifdef CONFIG_X86_PAE
-	printk(KERN_ERR "ACPI: S3 and PAE do not like each other for now, S3 disabled.\n");
-	return;
-#endif
+
 	acpi_wakeup_address = (unsigned long)alloc_bootmem_low(PAGE_SIZE);
 	if (!acpi_wakeup_address)
 		printk(KERN_ERR "ACPI: Cannot allocate lowmem, S3 disabled.\n");
diff -Nru a/arch/i386/kernel/apic.c b/arch/i386/kernel/apic.c
--- a/arch/i386/kernel/apic.c	2004-10-18 14:57:05 -07:00
+++ b/arch/i386/kernel/apic.c	2004-10-18 14:57:05 -07:00
@@ -39,6 +39,12 @@
 
 #include "io_ports.h"
 
+/*
+ * Debug level
+ */
+int apic_verbosity;
+
+
 static void apic_pm_activate(void);
 
 void __init apic_intr_init(void)
@@ -85,7 +91,7 @@
 	unsigned int lvr, version;
 	lvr = apic_read(APIC_LVR);
 	version = GET_APIC_VERSION(lvr);
-	if (version >= 0x14)
+	if (!APIC_INTEGRATED(version) || version >= 0x14)
 		return 0xff;
 	else
 		return 0xf;
@@ -173,7 +179,8 @@
 		 * PIC mode, enable APIC mode in the IMCR, i.e.
 		 * connect BSP's local APIC to INT and NMI lines.
 		 */
-		printk("leaving PIC mode, enabling APIC mode.\n");
+		apic_printk(APIC_VERBOSE, "leaving PIC mode, "
+				"enabling APIC mode.\n");
 		outb(0x70, 0x22);
 		outb(0x01, 0x23);
 	}
@@ -189,7 +196,8 @@
 		 * interrupts, including IPIs, won't work beyond
 		 * this point!  The only exception are INIT IPIs.
 		 */
-		printk("disabling APIC mode, entering PIC mode.\n");
+		apic_printk(APIC_VERBOSE, "disabling APIC mode, "
+				"entering PIC mode.\n");
 		outb(0x70, 0x22);
 		outb(0x00, 0x23);
 	}
@@ -230,10 +238,10 @@
 	 * The version register is read-only in a real APIC.
 	 */
 	reg0 = apic_read(APIC_LVR);
-	Dprintk("Getting VERSION: %x\n", reg0);
+	apic_printk(APIC_DEBUG, "Getting VERSION: %x\n", reg0);
 	apic_write(APIC_LVR, reg0 ^ APIC_LVR_MASK);
 	reg1 = apic_read(APIC_LVR);
-	Dprintk("Getting VERSION: %x\n", reg1);
+	apic_printk(APIC_DEBUG, "Getting VERSION: %x\n", reg1);
 
 	/*
 	 * The two version reads above should print the same
@@ -257,7 +265,7 @@
 	 * The ID register is read/write in a real APIC.
 	 */
 	reg0 = apic_read(APIC_ID);
-	Dprintk("Getting ID: %x\n", reg0);
+	apic_printk(APIC_DEBUG, "Getting ID: %x\n", reg0);
 
 	/*
 	 * The next two are just to see if we have sane values.
@@ -265,9 +273,9 @@
 	 * compatibility mode, but most boxes are anymore.
 	 */
 	reg0 = apic_read(APIC_LVT0);
-	Dprintk("Getting LVT0: %x\n", reg0);
+	apic_printk(APIC_DEBUG, "Getting LVT0: %x\n", reg0);
 	reg1 = apic_read(APIC_LVT1);
-	Dprintk("Getting LVT1: %x\n", reg1);
+	apic_printk(APIC_DEBUG, "Getting LVT1: %x\n", reg1);
 
 	return 1;
 }
@@ -279,7 +287,7 @@
 	 */
 	apic_wait_icr_idle();
 
-	Dprintk("Synchronizing Arb IDs.\n");
+	apic_printk(APIC_DEBUG, "Synchronizing Arb IDs.\n");
 	apic_write_around(APIC_ICR, APIC_DEST_ALLINC | APIC_INT_LEVELTRIG
 				| APIC_DM_INIT);
 }
@@ -335,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) {
@@ -427,10 +435,12 @@
 	value = apic_read(APIC_LVT0) & APIC_LVT_MASKED;
 	if (!smp_processor_id() && (pic_mode || !value)) {
 		value = APIC_DM_EXTINT;
-		printk("enabled ExtINT on CPU#%d\n", smp_processor_id());
+		apic_printk(APIC_VERBOSE, "enabled ExtINT on CPU#%d\n",
+				smp_processor_id());
 	} else {
 		value = APIC_DM_EXTINT | APIC_LVT_MASKED;
-		printk("masked ExtINT on CPU#%d\n", smp_processor_id());
+		apic_printk(APIC_VERBOSE, "masked ExtINT on CPU#%d\n",
+				smp_processor_id());
 	}
 	apic_write_around(APIC_LVT0, value);
 
@@ -449,8 +459,7 @@
 		maxlvt = get_maxlvt();
 		if (maxlvt > 3)		/* Due to the Pentium erratum 3AP. */
 			apic_write(APIC_ESR, 0);
-		value = apic_read(APIC_ESR);
-		printk("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);
@@ -460,7 +469,10 @@
 		if (maxlvt > 3)
 			apic_write(APIC_ESR, 0);
 		value = apic_read(APIC_ESR);
-		printk("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)	
 			/* 
@@ -635,6 +647,21 @@
 }
 __setup("lapic", lapic_enable);
 
+static int __init apic_set_verbosity(char *str)
+{
+	if (strcmp("debug", str) == 0)
+		apic_verbosity = APIC_DEBUG;
+	else if (strcmp("verbose", str) == 0)
+		apic_verbosity = APIC_VERBOSE;
+	else
+		printk(KERN_WARNING "APIC Verbosity level %s not recognised"
+				" use apic=verbose or apic=debug", str);
+
+	return 0;
+}
+
+__setup("apic=", apic_set_verbosity);
+
 static int __init detect_init_APIC (void)
 {
 	u32 h, l, features;
@@ -665,13 +692,20 @@
 
 	if (!cpu_has_apic) {
 		/*
+		 * Over-ride BIOS and try to enable LAPIC
+		 * only if "lapic" specified
+		 */
+		if (enable_local_apic != 1)
+			goto no_apic;
+		/*
 		 * Some BIOSes disable the local APIC in the
 		 * APIC_BASE MSR. This can only be done in
 		 * software for Intel P6 and AMD K7 (Model > 1).
 		 */
 		rdmsr(MSR_IA32_APICBASE, l, h);
 		if (!(l & MSR_IA32_APICBASE_ENABLE)) {
-			printk("Local APIC disabled by BIOS -- reenabling.\n");
+			apic_printk(APIC_VERBOSE, "Local APIC disabled "
+					"by BIOS -- reenabling.\n");
 			l &= ~MSR_IA32_APICBASE_BASE;
 			l |= MSR_IA32_APICBASE_ENABLE | APIC_DEFAULT_PHYS_BASE;
 			wrmsr(MSR_IA32_APICBASE, l, h);
@@ -698,7 +732,7 @@
 	if (nmi_watchdog != NMI_NONE)
 		nmi_watchdog = NMI_LOCAL_APIC;
 
-	printk("Found and enabled local APIC!\n");
+	apic_printk(APIC_VERBOSE, "Found and enabled local APIC!\n");
 
 	apic_pm_activate();
 
@@ -725,7 +759,8 @@
 		apic_phys = mp_lapic_addr;
 
 	set_fixmap_nocache(FIX_APIC_BASE, apic_phys);
-	Dprintk("mapped APIC to %08lx (%08lx)\n", APIC_BASE, apic_phys);
+	apic_printk(APIC_DEBUG, "mapped APIC to %08lx (%08lx)\n", APIC_BASE,
+			apic_phys);
 
 	/*
 	 * Fetch the APIC ID of the BSP in case we have a
@@ -755,7 +790,8 @@
 				ioapic_phys = __pa(ioapic_phys);
 			}
 			set_fixmap_nocache(idx, ioapic_phys);
-			Dprintk("mapped IOAPIC to %08lx (%08lx)\n",
+			apic_printk(APIC_DEBUG, "mapped IOAPIC to "
+					"%08lx (%08lx)\n",
 					__fix_to_virt(idx), ioapic_phys);
 			idx++;
 		}
@@ -894,7 +930,7 @@
 	int i;
 	const int LOOPS = HZ/10;
 
-	printk("calibrating APIC timer ...\n");
+	apic_printk(APIC_VERBOSE, "calibrating APIC timer ...\n");
 
 	/*
 	 * Put whatever arbitrary (but long enough) timeout
@@ -939,11 +975,13 @@
 	result = (tt1-tt2)*APIC_DIVISOR/LOOPS;
 
 	if (cpu_has_tsc)
-		printk("..... CPU clock speed is %ld.%04ld MHz.\n",
+		apic_printk(APIC_VERBOSE, "..... CPU clock speed is "
+			"%ld.%04ld MHz.\n",
 			((long)(t2-t1)/LOOPS)/(1000000/HZ),
 			((long)(t2-t1)/LOOPS)%(1000000/HZ));
 
-	printk("..... host bus clock speed is %ld.%04ld MHz.\n",
+	apic_printk(APIC_VERBOSE, "..... host bus clock speed is "
+		"%ld.%04ld MHz.\n",
 		result/(1000000/HZ),
 		result%(1000000/HZ));
 
@@ -954,7 +992,7 @@
 
 void __init setup_boot_APIC_clock(void)
 {
-	printk("Using local APIC timer interrupts.\n");
+	apic_printk(APIC_VERBOSE, "Using local APIC timer interrupts.\n");
 	using_apic_timer = 1;
 
 	local_irq_disable();
@@ -1039,8 +1077,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
@@ -1159,7 +1196,7 @@
 	   6: Received illegal vector
 	   7: Illegal register address
 	*/
-	printk (KERN_INFO "APIC error on CPU%d: %02lx(%02lx)\n",
+	printk (KERN_DEBUG "APIC error on CPU%d: %02lx(%02lx)\n",
 	        smp_processor_id(), v , v1);
 	irq_exit();
 }
diff -Nru a/arch/i386/kernel/apm.c b/arch/i386/kernel/apm.c
--- a/arch/i386/kernel/apm.c	2004-10-18 14:55:54 -07:00
+++ b/arch/i386/kernel/apm.c	2004-10-18 14:55:54 -07:00
@@ -601,8 +601,8 @@
 	cpus = apm_save_cpus();
 	
 	cpu = get_cpu();
-	save_desc_40 = cpu_gdt_table[cpu][0x40 / 8];
-	cpu_gdt_table[cpu][0x40 / 8] = bad_bios_desc;
+	save_desc_40 = per_cpu(cpu_gdt_table, cpu)[0x40 / 8];
+	per_cpu(cpu_gdt_table, cpu)[0x40 / 8] = bad_bios_desc;
 
 	local_save_flags(flags);
 	APM_DO_CLI;
@@ -610,7 +610,7 @@
 	apm_bios_call_asm(func, ebx_in, ecx_in, eax, ebx, ecx, edx, esi);
 	APM_DO_RESTORE_SEGS;
 	local_irq_restore(flags);
-	cpu_gdt_table[cpu][0x40 / 8] = save_desc_40;
+	per_cpu(cpu_gdt_table, cpu)[0x40 / 8] = save_desc_40;
 	put_cpu();
 	apm_restore_cpus(cpus);
 	
@@ -644,8 +644,8 @@
 	cpus = apm_save_cpus();
 	
 	cpu = get_cpu();
-	save_desc_40 = cpu_gdt_table[cpu][0x40 / 8];
-	cpu_gdt_table[cpu][0x40 / 8] = bad_bios_desc;
+	save_desc_40 = per_cpu(cpu_gdt_table, cpu)[0x40 / 8];
+	per_cpu(cpu_gdt_table, cpu)[0x40 / 8] = bad_bios_desc;
 
 	local_save_flags(flags);
 	APM_DO_CLI;
@@ -653,7 +653,7 @@
 	error = apm_bios_call_simple_asm(func, ebx_in, ecx_in, eax);
 	APM_DO_RESTORE_SEGS;
 	local_irq_restore(flags);
-	cpu_gdt_table[smp_processor_id()][0x40 / 8] = save_desc_40;
+	__get_cpu_var(cpu_gdt_table)[0x40 / 8] = save_desc_40;
 	put_cpu();
 	apm_restore_cpus(cpus);
 	return error;
@@ -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;
@@ -2292,35 +2294,35 @@
 	apm_bios_entry.segment = APM_CS;
 
 	for (i = 0; i < NR_CPUS; i++) {
-		set_base(cpu_gdt_table[i][APM_CS >> 3],
+		set_base(per_cpu(cpu_gdt_table, i)[APM_CS >> 3],
 			 __va((unsigned long)apm_info.bios.cseg << 4));
-		set_base(cpu_gdt_table[i][APM_CS_16 >> 3],
+		set_base(per_cpu(cpu_gdt_table, i)[APM_CS_16 >> 3],
 			 __va((unsigned long)apm_info.bios.cseg_16 << 4));
-		set_base(cpu_gdt_table[i][APM_DS >> 3],
+		set_base(per_cpu(cpu_gdt_table, i)[APM_DS >> 3],
 			 __va((unsigned long)apm_info.bios.dseg << 4));
 #ifndef APM_RELAX_SEGMENTS
 		if (apm_info.bios.version == 0x100) {
 #endif
 			/* For ASUS motherboard, Award BIOS rev 110 (and others?) */
-			_set_limit((char *)&cpu_gdt_table[i][APM_CS >> 3], 64 * 1024 - 1);
+			_set_limit((char *)&per_cpu(cpu_gdt_table, i)[APM_CS >> 3], 64 * 1024 - 1);
 			/* For some unknown machine. */
-			_set_limit((char *)&cpu_gdt_table[i][APM_CS_16 >> 3], 64 * 1024 - 1);
+			_set_limit((char *)&per_cpu(cpu_gdt_table, i)[APM_CS_16 >> 3], 64 * 1024 - 1);
 			/* For the DEC Hinote Ultra CT475 (and others?) */
-			_set_limit((char *)&cpu_gdt_table[i][APM_DS >> 3], 64 * 1024 - 1);
+			_set_limit((char *)&per_cpu(cpu_gdt_table, i)[APM_DS >> 3], 64 * 1024 - 1);
 #ifndef APM_RELAX_SEGMENTS
 		} else {
-			_set_limit((char *)&cpu_gdt_table[i][APM_CS >> 3],
+			_set_limit((char *)&per_cpu(cpu_gdt_table, i)[APM_CS >> 3],
 				(apm_info.bios.cseg_len - 1) & 0xffff);
-			_set_limit((char *)&cpu_gdt_table[i][APM_CS_16 >> 3],
+			_set_limit((char *)&per_cpu(cpu_gdt_table, i)[APM_CS_16 >> 3],
 				(apm_info.bios.cseg_16_len - 1) & 0xffff);
-			_set_limit((char *)&cpu_gdt_table[i][APM_DS >> 3],
+			_set_limit((char *)&per_cpu(cpu_gdt_table, i)[APM_DS >> 3],
 				(apm_info.bios.dseg_len - 1) & 0xffff);
 		      /* workaround for broken BIOSes */
 	                if (apm_info.bios.cseg_len <= apm_info.bios.offset)
-        	                _set_limit((char *)&cpu_gdt_table[i][APM_CS >> 3], 64 * 1024 -1);
+        	                _set_limit((char *)&per_cpu(cpu_gdt_table, i)[APM_CS >> 3], 64 * 1024 -1);
                        if (apm_info.bios.dseg_len <= 0x40) { /* 0x40 * 4kB == 64kB */
                         	/* for the BIOS that assumes granularity = 1 */
-                        	cpu_gdt_table[i][APM_DS >> 3].b |= 0x800000;
+                        	per_cpu(cpu_gdt_table, i)[APM_DS >> 3].b |= 0x800000;
                         	printk(KERN_NOTICE "apm: we set the granularity of dseg.\n");
         	        }
 		}
@@ -2360,8 +2362,15 @@
 {
 	int	error;
 
-	if (set_pm_idle)
+	if (set_pm_idle) {
 		pm_idle = original_pm_idle;
+		/*
+		 * We are about to unload the current idle thread pm callback
+		 * (pm_idle), Wait for all processors to update cached/local
+		 * copies of pm_idle before proceeding.
+		 */
+		synchronize_kernel();
+	}
 	if (((apm_info.bios.flags & APM_BIOS_DISENGAGED) == 0)
 	    && (apm_info.connection_version > 0x0100)) {
 		error = apm_engage_power_management(APM_DEVICE_ALL, 0);
diff -Nru a/arch/i386/kernel/asm-offsets.c b/arch/i386/kernel/asm-offsets.c
--- a/arch/i386/kernel/asm-offsets.c	2004-10-18 14:56:28 -07:00
+++ b/arch/i386/kernel/asm-offsets.c	2004-10-18 14:56:28 -07:00
@@ -62,4 +62,5 @@
 		 sizeof(struct tss_struct));
 
 	DEFINE(PAGE_SIZE_asm, PAGE_SIZE);
+	DEFINE(VSYSCALL_BASE, __fix_to_virt(FIX_VSYSCALL));
 }
diff -Nru a/arch/i386/kernel/cpu/centaur.c b/arch/i386/kernel/cpu/centaur.c
--- a/arch/i386/kernel/cpu/centaur.c	2004-10-18 14:56:33 -07:00
+++ b/arch/i386/kernel/cpu/centaur.c	2004-10-18 14:56:33 -07:00
@@ -286,23 +286,20 @@
 		c->x86_capability[5] = cpuid_edx(0xC0000001);
 	}
 
-	switch (c->x86_model) {
-		case 6 ... 8:		/* Cyrix III family */
-			rdmsr (MSR_VIA_FCR, lo, hi);
-			lo |= (1<<1 | 1<<7);	/* Report CX8 & enable PGE */
-			wrmsr (MSR_VIA_FCR, lo, hi);
-
-			set_bit(X86_FEATURE_CX8, c->x86_capability);
-			set_bit(X86_FEATURE_3DNOW, c->x86_capability);
+	/* Cyrix III family needs CX8 & PGE explicity enabled. */
+	if (c->x86_model >=6 && c->x86_model <= 9) {
+		rdmsr (MSR_VIA_FCR, lo, hi);
+		lo |= (1<<1 | 1<<7);
+		wrmsr (MSR_VIA_FCR, lo, hi);
+		set_bit(X86_FEATURE_CX8, c->x86_capability);
+	}
 
-			/* fall through */
+	/* Before Nehemiah, the C3's had 3dNOW! */
+	if (c->x86_model >=6 && c->x86_model <9)
+		set_bit(X86_FEATURE_3DNOW, c->x86_capability);
 
-		case 9:	/* Nehemiah */
-		default:
-			get_model_name(c);
-			display_cacheinfo(c);
-			break;
-	}
+	get_model_name(c);
+	display_cacheinfo(c);
 }
 
 static void __init init_centaur(struct cpuinfo_x86 *c)
diff -Nru a/arch/i386/kernel/cpu/common.c b/arch/i386/kernel/cpu/common.c
--- a/arch/i386/kernel/cpu/common.c	2004-10-18 14:55:54 -07:00
+++ b/arch/i386/kernel/cpu/common.c	2004-10-18 14:55:54 -07:00
@@ -2,6 +2,8 @@
 #include <linux/string.h>
 #include <linux/delay.h>
 #include <linux/smp.h>
+#include <linux/module.h>
+#include <linux/percpu.h>
 #include <asm/semaphore.h>
 #include <asm/processor.h>
 #include <asm/i387.h>
@@ -11,6 +13,9 @@
 
 #include "cpu.h"
 
+DEFINE_PER_CPU(struct desc_struct, cpu_gdt_table[GDT_ENTRIES]);
+EXPORT_PER_CPU_SYMBOL(cpu_gdt_table);
+
 static int cachesize_override __initdata = -1;
 static int disable_x86_fxsr __initdata = 0;
 static int disable_x86_serial_nr __initdata = 1;
@@ -501,7 +506,7 @@
 void __init cpu_init (void)
 {
 	int cpu = smp_processor_id();
-	struct tss_struct * t = init_tss + cpu;
+	struct tss_struct * t = &per_cpu(init_tss, cpu);
 	struct thread_struct *thread = &current->thread;
 
 	if (test_and_set_bit(cpu, &cpu_initialized)) {
@@ -523,15 +528,17 @@
 	 * Initialize the per-CPU GDT with the boot GDT,
 	 * and set up the GDT descriptor:
 	 */
-	if (cpu) {
-		memcpy(cpu_gdt_table[cpu], cpu_gdt_table[0], GDT_SIZE);
-		cpu_gdt_descr[cpu].size = GDT_SIZE - 1;
-		cpu_gdt_descr[cpu].address = (unsigned long)cpu_gdt_table[cpu];
-	}
+	memcpy(&per_cpu(cpu_gdt_table, cpu), cpu_gdt_table,
+	       GDT_SIZE);
+	cpu_gdt_descr[cpu].size = GDT_SIZE - 1;
+	cpu_gdt_descr[cpu].address =
+	    (unsigned long)&per_cpu(cpu_gdt_table, cpu);
+
 	/*
 	 * Set up the per-thread TLS descriptor cache:
 	 */
-	memcpy(thread->tls_array, cpu_gdt_table[cpu], GDT_ENTRY_TLS_ENTRIES * 8);
+	memcpy(thread->tls_array, &per_cpu(cpu_gdt_table, cpu),
+		GDT_ENTRY_TLS_ENTRIES * 8);
 
 	__asm__ __volatile__("lgdt %0" : : "m" (cpu_gdt_descr[cpu]));
 	__asm__ __volatile__("lidt %0" : : "m" (idt_descr));
@@ -552,13 +559,11 @@
 
 	load_esp0(t, thread);
 	set_tss_desc(cpu,t);
-	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);
-	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/Kconfig b/arch/i386/kernel/cpu/cpufreq/Kconfig
--- a/arch/i386/kernel/cpu/cpufreq/Kconfig	2004-10-18 14:56:17 -07:00
+++ b/arch/i386/kernel/cpu/cpufreq/Kconfig	2004-10-18 14:56:17 -07:00
@@ -88,6 +88,11 @@
 
 	  If in doubt, say N.
 
+config X86_POWERNOW_K7_ACPI
+	bool
+	depends on ((X86_POWERNOW_K7 = "m" && ACPI_PROCESSOR) || (X86_POWERNOW_K7 = "y" && ACPI_PROCESSOR = "y"))
+	default y
+
 config X86_POWERNOW_K8
 	tristate "AMD Opteron/Athlon64 PowerNow!"
 	depends on CPU_FREQ && EXPERIMENTAL
@@ -97,6 +102,11 @@
 	  For details, take a look at <file:Documentation/cpu-freq/>.
 
 	  If in doubt, say N.
+
+config X86_POWERNOW_K8_ACPI
+	bool
+	depends on ((X86_POWERNOW_K8 = "m" && ACPI_PROCESSOR) || (X86_POWERNOW_K8 = "y" && ACPI_PROCESSOR = "y"))
+	default y
 
 config X86_GX_SUSPMOD
 	tristate "Cyrix MediaGX/NatSemi Geode Suspend Modulation"
diff -Nru a/arch/i386/kernel/cpu/cpufreq/acpi.c b/arch/i386/kernel/cpu/cpufreq/acpi.c
--- a/arch/i386/kernel/cpu/cpufreq/acpi.c	2004-10-18 14:55:54 -07:00
+++ b/arch/i386/kernel/cpu/cpufreq/acpi.c	2004-10-18 14:55:54 -07:00
@@ -108,13 +108,27 @@
 	u32			value = 0;
 	int			i = 0;
 	struct cpufreq_freqs    cpufreq_freqs;
+	cpumask_t		saved_mask;
+	int			retval;
 
 	ACPI_FUNCTION_TRACE("acpi_processor_set_performance");
 
+	/*
+	 * TBD: Use something other than set_cpus_allowed.
+	 * As set_cpus_allowed is a bit racy, 
+	 * with any other set_cpus_allowed for this process.
+	 */
+	saved_mask = current->cpus_allowed;
+	set_cpus_allowed(current, cpumask_of_cpu(cpu));
+	if (smp_processor_id() != cpu) {
+		return_VALUE(-EAGAIN);
+	}
+	
 	if (state == data->acpi_data.state) {
 		ACPI_DEBUG_PRINT((ACPI_DB_INFO, 
 			"Already at target state (P%d)\n", state));
-		return_VALUE(0);
+		retval = 0;
+		goto migrate_end;
 	}
 
 	ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Transitioning from P%d to P%d\n",
@@ -144,7 +158,8 @@
 	if (ret) {
 		ACPI_DEBUG_PRINT((ACPI_DB_WARN,
 			"Invalid port width 0x%04x\n", bit_width));
-		return_VALUE(ret);
+		retval = ret;
+		goto migrate_end;
 	}
 
 	/*
@@ -166,7 +181,8 @@
 		if (ret) {	
 			ACPI_DEBUG_PRINT((ACPI_DB_WARN,
 				"Invalid port width 0x%04x\n", bit_width));
-			return_VALUE(ret);
+			retval = ret;
+			goto migrate_end;
 		}
 		if (value == (u32) data->acpi_data.states[state].status)
 			break;
@@ -183,7 +199,8 @@
 		cpufreq_notify_transition(&cpufreq_freqs, CPUFREQ_PRECHANGE);
 		cpufreq_notify_transition(&cpufreq_freqs, CPUFREQ_POSTCHANGE);
 		ACPI_DEBUG_PRINT((ACPI_DB_WARN, "Transition failed\n"));
-		return_VALUE(-ENODEV);
+		retval = -ENODEV;
+		goto migrate_end;
 	}
 
 	ACPI_DEBUG_PRINT((ACPI_DB_INFO, 
@@ -192,7 +209,10 @@
 
 	data->acpi_data.state = state;
 
-	return_VALUE(0);
+	retval = 0;
+migrate_end:
+	set_cpus_allowed(current, saved_mask);
+	return_VALUE(retval);
 }
 
 
@@ -266,6 +286,69 @@
 	
 }
 
+
+/* 
+ * acpi_processor_cpu_init_pdc_est - let BIOS know about the SMP capabilities
+ * of this driver
+ * @perf: processor-specific acpi_io_data struct
+ * @cpu: CPU being initialized
+ *
+ * To avoid issues with legacy OSes, some BIOSes require to be informed of
+ * the SMP capabilities of OS P-state driver. Here we set the bits in _PDC 
+ * accordingly, for Enhanced Speedstep. Actual call to _PDC is done in
+ * driver/acpi/processor.c
+ */
+static void 
+acpi_processor_cpu_init_pdc_est(
+		struct acpi_processor_performance *perf, 
+		unsigned int cpu,
+		struct acpi_object_list *obj_list
+		)
+{
+	union acpi_object *obj;
+	u32 *buf;
+	struct cpuinfo_x86 *c = cpu_data + cpu;
+	ACPI_FUNCTION_TRACE("acpi_processor_cpu_init_pdc_est");
+
+	if (!cpu_has(c, X86_FEATURE_EST))
+		return_VOID;
+
+	/* Initialize pdc. It will be used later. */
+	if (!obj_list)
+		return_VOID;
+		
+	if (!(obj_list->count && obj_list->pointer))
+		return_VOID;
+
+	obj = obj_list->pointer;
+	if ((obj->buffer.length == 12) && obj->buffer.pointer) {
+		buf = (u32 *)obj->buffer.pointer;
+       		buf[0] = ACPI_PDC_REVISION_ID;
+       		buf[1] = 1;
+       		buf[2] = ACPI_PDC_EST_CAPABILITY_SMP;
+		perf->pdc = obj_list;
+	}
+	return_VOID;
+}
+ 
+
+/* CPU specific PDC initialization */
+static void 
+acpi_processor_cpu_init_pdc(
+		struct acpi_processor_performance *perf, 
+		unsigned int cpu,
+		struct acpi_object_list *obj_list
+		)
+{
+	struct cpuinfo_x86 *c = cpu_data + cpu;
+	ACPI_FUNCTION_TRACE("acpi_processor_cpu_init_pdc");
+	perf->pdc = NULL;
+	if (cpu_has(c, X86_FEATURE_EST))
+		acpi_processor_cpu_init_pdc_est(perf, cpu, obj_list);
+	return_VOID;
+}
+
+
 static int
 acpi_cpufreq_cpu_init (
 	struct cpufreq_policy   *policy)
@@ -275,7 +358,14 @@
 	struct cpufreq_acpi_io	*data;
 	unsigned int		result = 0;
 
+	union acpi_object		arg0 = {ACPI_TYPE_BUFFER};
+	u32				arg0_buf[3];
+	struct acpi_object_list 	arg_list = {1, &arg0};
+
 	ACPI_FUNCTION_TRACE("acpi_cpufreq_cpu_init");
+	/* setup arg_list for _PDC settings */
+        arg0.buffer.length = 12;
+        arg0.buffer.pointer = (u8 *) arg0_buf;
 
 	data = kmalloc(sizeof(struct cpufreq_acpi_io), GFP_KERNEL);
 	if (!data)
@@ -284,7 +374,10 @@
 
 	acpi_io_data[cpu] = data;
 
+	acpi_processor_cpu_init_pdc(&data->acpi_data, cpu, &arg_list);
 	result = acpi_processor_register_performance(&data->acpi_data, cpu);
+	data->acpi_data.pdc = NULL;
+
 	if (result)
 		goto err_free;
 
diff -Nru a/arch/i386/kernel/cpu/cpufreq/gx-suspmod.c b/arch/i386/kernel/cpu/cpufreq/gx-suspmod.c
--- a/arch/i386/kernel/cpu/cpufreq/gx-suspmod.c	2004-10-18 14:56:31 -07:00
+++ b/arch/i386/kernel/cpu/cpufreq/gx-suspmod.c	2004-10-18 14:56:31 -07:00
@@ -297,6 +297,7 @@
 		case PCI_DEVICE_ID_CYRIX_5520:
 		case PCI_DEVICE_ID_CYRIX_5510:
 			suscfg = gx_params->pci_suscfg | SUSMOD;
+			break;
 		default:
 			local_irq_restore(flags);
 			dprintk("fatal: try to set unknown chipset.\n");
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-10-18 14:55:54 -07:00
+++ b/arch/i386/kernel/cpu/cpufreq/longhaul.c	2004-10-18 14:55:54 -07:00
@@ -5,14 +5,19 @@
  *  Licensed under the terms of the GNU GPL License version 2.
  *  Based upon datasheets & sample CPUs kindly provided by VIA.
  *
- *  VIA have currently 2 different versions of Longhaul.
+ *  VIA have currently 3 different versions of Longhaul.
  *  Version 1 (Longhaul) uses the BCR2 MSR at 0x1147.
- *   It is present only in Samuel 1, Samuel 2 and Ezra.
- *  Version 2 (Powersaver) uses the POWERSAVER MSR at 0x110a.
- *   It is present in Ezra-T, Nehemiah and above.
- *   In addition to scaling multiplier, it can also scale voltage.
- *   There is provision for scaling FSB too, but this doesn't work
- *   too well in practice.
+ *   It is present only in Samuel 1 (C5A), Samuel 2 (C5B) stepping 0.
+ *  Version 2 of longhaul is the same as v1, but adds voltage scaling.
+ *   Present in Samuel 2 (steppings 1-7 only) (C5B), and Ezra (C5C)
+ *   voltage scaling support has currently been disabled in this driver
+ *   until we have code that gets it right.
+ *  Version 3 of longhaul got renamed to Powersaver and redesigned
+ *   to use the POWERSAVER MSR at 0x110a.
+ *   It is present in Ezra-T (C5M), Nehemiah (C5X) and above.
+ *   It's pretty much the same feature wise to longhaul v2, though
+ *   there is provision for scaling FSB too, but this doesn't work
+ *   too well in practice so we don't even try to use this.
  *
  *  BIG FAT DISCLAIMER: Work in progress code. Possibly *dangerous*
  */
@@ -33,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;
@@ -68,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);
 
-static unsigned int calc_speed(int mult, int fsb)
+	return speedbuffer;
+}
+
+
+static unsigned int calc_speed(int mult)
 {
 	int khz;
 	khz = (mult/10)*fsb;
@@ -87,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;
 	}
@@ -95,11 +125,45 @@
 }
 
 
+static void do_powersaver(union msr_longhaul *longhaul,
+			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;
+	longhaul->bits.EnableSoftBusRatio = 1;
+	longhaul->bits.RevisionKey = 0;
+	local_irq_disable();
+	wrmsrl(MSR_VIA_LONGHAUL, longhaul->val);
+	local_irq_enable();
+	__hlt();
+
+	rdmsrl(MSR_VIA_LONGHAUL, longhaul->val);
+	longhaul->bits.EnableSoftBusRatio = 0;
+	longhaul->bits.RevisionKey = version;
+	local_irq_disable();
+	wrmsrl(MSR_VIA_LONGHAUL, longhaul->val);
+	local_irq_enable();
+}
+
 /**
  * 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)
@@ -108,79 +172,71 @@
 	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) {
-	case 1:
+
+	/*
+	 * Longhaul v1. (Samuel[C5A] and Samuel2 stepping 0[C5B])
+	 * Software controlled multipliers only.
+	 *
+	 * *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 TYPE_LONGHAUL_V1:
+	case TYPE_LONGHAUL_V2:
 		rdmsrl (MSR_VIA_BCR2, bcr2.val);
 		/* Enable software clock multiplier */
 		bcr2.bits.ESOFTBF = 1;
 		bcr2.bits.CLOCKMUL = clock_ratio_index;
+		local_irq_disable();
 		wrmsrl (MSR_VIA_BCR2, bcr2.val);
+		local_irq_enable();
 
 		__hlt();
 
 		/* Disable software clock multiplier */
 		rdmsrl (MSR_VIA_BCR2, bcr2.val);
 		bcr2.bits.ESOFTBF = 0;
+		local_irq_disable();
 		wrmsrl (MSR_VIA_BCR2, bcr2.val);
+		local_irq_enable();
 		break;
 
 	/*
-	 * Powersaver. (Ezra-T [C5M], Nehemiah [C5N])
+	 * 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.
-	 * We also need to do the voltage/freq setting in order depending
-	 * on the direction of scaling (like we do in powernow-k7.c)
-	 * Ezra-T was alleged to do FSB scaling too, but it never worked in practice.
+	 * 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)
+	 * Nehemiah can do FSB scaling too, but this has never been proven
+	 * to work in practice.
 	 */
-	case 2:
-		rdmsrl (MSR_VIA_LONGHAUL, longhaul.val);
-		longhaul.bits.SoftBusRatio = clock_ratio_index & 0xf;
-		longhaul.bits.SoftBusRatio4 = (clock_ratio_index & 0x10) >> 4;
-		longhaul.bits.EnableSoftBusRatio = 1;
-		/* We must program the revision key only with values we
-		 * know about, not blindly copy it from 0:3 */
-		longhaul.bits.RevisionKey = 3;	/* SoftVID & SoftBSEL */
-		wrmsrl(MSR_VIA_LONGHAUL, longhaul.val);
-		__hlt();
-
-		rdmsrl (MSR_VIA_LONGHAUL, longhaul.val);
-		longhaul.bits.EnableSoftBusRatio = 0;
-		longhaul.bits.RevisionKey = 3;
-		wrmsrl (MSR_VIA_LONGHAUL, longhaul.val);
-		break;
-	case 3:
-		rdmsrl (MSR_VIA_LONGHAUL, longhaul.val);
-		longhaul.bits.SoftBusRatio = clock_ratio_index & 0xf;
-		longhaul.bits.SoftBusRatio4 = (clock_ratio_index & 0x10) >> 4;
-		longhaul.bits.EnableSoftBusRatio = 1;
-
-		longhaul.bits.RevisionKey = 0x0;
-
-		wrmsrl(MSR_VIA_LONGHAUL, longhaul.val);
-		__hlt();
-
-		rdmsrl (MSR_VIA_LONGHAUL, longhaul.val);
-		longhaul.bits.EnableSoftBusRatio = 0;
-		longhaul.bits.RevisionKey = 0xf;
-		wrmsrl (MSR_VIA_LONGHAUL, longhaul.val);
+	case TYPE_POWERSAVER:
+		do_powersaver(&longhaul, clock_ratio_index);
 		break;
 	}
 
@@ -230,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,
@@ -242,58 +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();
+	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;
+		}
 
-		fsb = eblcr_fsb_table_v2[longhaul.bits.MaxMHzFSB];
-		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) {
@@ -301,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");
@@ -327,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++;
 	}
@@ -403,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;
@@ -419,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;
@@ -434,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;
@@ -461,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:
@@ -495,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)
@@ -540,6 +621,7 @@
 	.attr	= longhaul_attr,
 };
 
+
 static int __init longhaul_init(void)
 {
 	struct cpuinfo_x86 *c = cpu_data;
@@ -557,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/cpufreq/longrun.c b/arch/i386/kernel/cpu/cpufreq/longrun.c
--- a/arch/i386/kernel/cpu/cpufreq/longrun.c	2004-10-18 14:56:48 -07:00
+++ b/arch/i386/kernel/cpu/cpufreq/longrun.c	2004-10-18 14:56:48 -07:00
@@ -7,7 +7,7 @@
  */
 
 #include <linux/kernel.h>
-#include <linux/module.h> 
+#include <linux/module.h>
 #include <linux/init.h>
 #include <linux/slab.h>
 #include <linux/cpufreq.h>
@@ -19,7 +19,7 @@
 static struct cpufreq_driver	longrun_driver;
 
 /**
- * longrun_{low,high}_freq is needed for the conversion of cpufreq kHz 
+ * longrun_{low,high}_freq is needed for the conversion of cpufreq kHz
  * values into per cent values. In TMTA microcode, the following is valid:
  * performance_pctg = (current_freq - low_freq)/(high_freq - low_freq)
  */
@@ -42,18 +42,18 @@
 		policy->policy = CPUFREQ_POLICY_PERFORMANCE;
 	else
 		policy->policy = CPUFREQ_POLICY_POWERSAVE;
-	
+
 	rdmsr(MSR_TMTA_LONGRUN_CTRL, msr_lo, msr_hi);
 	msr_lo &= 0x0000007F;
 	msr_hi &= 0x0000007F;
-	
+
 	if ( longrun_high_freq <= longrun_low_freq ) {
 		/* Assume degenerate Longrun table */
 		policy->min = policy->max = longrun_high_freq;
 	} else {
-		policy->min = longrun_low_freq + msr_lo * 
+		policy->min = longrun_low_freq + msr_lo *
 			((longrun_high_freq - longrun_low_freq) / 100);
-		policy->max = longrun_low_freq + msr_hi * 
+		policy->max = longrun_low_freq + msr_hi *
 			((longrun_high_freq - longrun_low_freq) / 100);
 	}
 	policy->cpu = 0;
@@ -79,9 +79,9 @@
 		/* Assume degenerate Longrun table */
 		pctg_lo = pctg_hi = 100;
 	} else {
-		pctg_lo = (policy->min - longrun_low_freq) / 
+		pctg_lo = (policy->min - longrun_low_freq) /
 			((longrun_high_freq - longrun_low_freq) / 100);
-		pctg_hi = (policy->max - longrun_low_freq) / 
+		pctg_hi = (policy->max - longrun_low_freq) /
 			((longrun_high_freq - longrun_low_freq) / 100);
 	}
 
@@ -118,7 +118,7 @@
  * longrun_verify_poliy - verifies a new CPUFreq policy
  * @policy: the policy to verify
  *
- * Validates a new CPUFreq policy. This function has to be called with 
+ * Validates a new CPUFreq policy. This function has to be called with
  * cpufreq_driver locked.
  */
 static int longrun_verify_policy(struct cpufreq_policy *policy)
@@ -127,8 +127,8 @@
 		return -EINVAL;
 
 	policy->cpu = 0;
-	cpufreq_verify_within_limits(policy, 
-		policy->cpuinfo.min_freq, 
+	cpufreq_verify_within_limits(policy,
+		policy->cpuinfo.min_freq,
 		policy->cpuinfo.max_freq);
 
 	if ((policy->policy != CPUFREQ_POLICY_POWERSAVE) &&
@@ -160,7 +160,7 @@
  * TMTA rules:
  * performance_pctg = (target_freq - low_freq)/(high_freq - low_freq)
  */
-static unsigned int __init longrun_determine_freqs(unsigned int *low_freq, 
+static unsigned int __init longrun_determine_freqs(unsigned int *low_freq,
 						   unsigned int *high_freq)
 {
 	u32 msr_lo, msr_hi;
@@ -174,9 +174,9 @@
 
 	if (cpu_has(c, X86_FEATURE_LRTI)) {
 		/* if the LongRun Table Interface is present, the
-		 * detection is a bit easier: 
+		 * detection is a bit easier:
 		 * For minimum frequency, read out the maximum
-		 * level (msr_hi), write that into "currently 
+		 * level (msr_hi), write that into "currently
 		 * selected level", and read out the frequency.
 		 * For maximum frequency, read out level zero.
 		 */
@@ -223,7 +223,7 @@
 		cpuid(0x80860007, &eax, &ebx, &ecx, &edx);
 
 		/* restore values */
-		wrmsr(MSR_TMTA_LONGRUN_CTRL, save_lo, save_hi);	
+		wrmsr(MSR_TMTA_LONGRUN_CTRL, save_lo, save_hi);
 	}
 
 	/* performance_pctg = (current_freq - low_freq)/(high_freq - low_freq)
@@ -237,7 +237,7 @@
 	if ((ecx > 95) || (ecx == 0) || (eax < ebx))
 		return -EIO;
 
-	edx = (eax - ebx) / (100 - ecx); 
+	edx = (eax - ebx) / (100 - ecx);
 	*low_freq = edx * 1000; /* back to kHz */
 
 	if (*low_freq > *high_freq)
@@ -249,7 +249,7 @@
 
 static int __init longrun_cpu_init(struct cpufreq_policy *policy)
 {
-	int                     result = 0;
+	int result = 0;
 
 	/* capability check */
 	if (policy->cpu != 0)
@@ -265,15 +265,15 @@
 	policy->cpuinfo.max_freq = longrun_high_freq;
 	policy->cpuinfo.transition_latency = CPUFREQ_ETERNAL;
 	longrun_get_policy(policy);
-	
+
 	return 0;
 }
 
 
 static struct cpufreq_driver longrun_driver = {
 	.flags		= CPUFREQ_CONST_LOOPS,
-	.verify 	= longrun_verify_policy,
-	.setpolicy 	= longrun_set_policy,
+	.verify		= longrun_verify_policy,
+	.setpolicy	= longrun_set_policy,
 	.get		= longrun_get,
 	.init		= longrun_cpu_init,
 	.name		= "longrun",
@@ -290,7 +290,7 @@
 {
 	struct cpuinfo_x86 *c = cpu_data;
 
-	if (c->x86_vendor != X86_VENDOR_TRANSMETA || 
+	if (c->x86_vendor != X86_VENDOR_TRANSMETA ||
 	    !cpu_has(c, X86_FEATURE_LONGRUN))
 		return -ENODEV;
 
diff -Nru a/arch/i386/kernel/cpu/cpufreq/p4-clockmod.c b/arch/i386/kernel/cpu/cpufreq/p4-clockmod.c
--- a/arch/i386/kernel/cpu/cpufreq/p4-clockmod.c	2004-10-18 14:57:03 -07:00
+++ b/arch/i386/kernel/cpu/cpufreq/p4-clockmod.c	2004-10-18 14:57:03 -07:00
@@ -184,7 +184,7 @@
 		       "The speedstep_centrino module offers voltage scaling"
 		       " in addition of frequency scaling. You should use "
 		       "that instead of p4-clockmod, if possible.\n");
-		/* on P-4s, the TSC runs with constant frequency independent wether
+		/* on P-4s, the TSC runs with constant frequency independent whether
 		 * throttling is active or not. */
 		p4clockmod_driver.flags |= CPUFREQ_CONST_LOOPS;
 		return speedstep_get_processor_frequency(SPEEDSTEP_PROCESSOR_PM);
@@ -195,7 +195,7 @@
 		return 0;
 	}
 
-	/* on P-4s, the TSC runs with constant frequency independent wether
+	/* on P-4s, the TSC runs with constant frequency independent whether
 	 * throttling is active or not. */
 	p4clockmod_driver.flags |= CPUFREQ_CONST_LOOPS;
 
diff -Nru a/arch/i386/kernel/cpu/cpufreq/powernow-k7.c b/arch/i386/kernel/cpu/cpufreq/powernow-k7.c
--- a/arch/i386/kernel/cpu/cpufreq/powernow-k7.c	2004-10-18 14:55:54 -07:00
+++ b/arch/i386/kernel/cpu/cpufreq/powernow-k7.c	2004-10-18 14:55:54 -07:00
@@ -6,8 +6,6 @@
  *  Licensed under the terms of the GNU GPL License version 2.
  *  Based upon datasheets & sample CPUs kindly provided by AMD.
  *
- *  BIG FAT DISCLAIMER: Work in progress code. Possibly *dangerous*
- *
  * Errata 5: Processor may fail to execute a FID/VID change in presence of interrupt.
  * - We cli/sti on stepping A0 CPUs around the FID/VID transition.
  * Errata 15: Processors with half frequency multipliers may hang upon wakeup from disconnect.
@@ -29,21 +27,13 @@
 #include <asm/io.h>
 #include <asm/system.h>
 
-#if defined(CONFIG_ACPI_PROCESSOR) || defined(CONFIG_ACPI_PROCESSOR_MODULE)
+#ifdef CONFIG_X86_POWERNOW_K7_ACPI
 #include <linux/acpi.h>
 #include <acpi/processor.h>
 #endif
 
 #include "powernow-k7.h"
 
-#define DEBUG
-
-#ifdef DEBUG
-#define dprintk(msg...) printk(msg)
-#else
-#define dprintk(msg...) do { } while(0)
-#endif
-
 #define PFX "powernow: "
 
 
@@ -64,7 +54,7 @@
 	u8 numpstates;
 };
 
-#if defined(CONFIG_ACPI_PROCESSOR) || defined(CONFIG_ACPI_PROCESSOR_MODULE)
+#ifdef CONFIG_X86_POWERNOW_K7_ACPI
 union powernow_acpi_control_t {
 	struct {
 		unsigned long fid:5,
@@ -97,6 +87,7 @@
  */
 
 static int acpi_force;
+static int debug;
 
 static struct cpufreq_frequency_table *powernow_table;
 
@@ -109,6 +100,21 @@
 static unsigned int latency;
 static char have_a0;
 
+static void dprintk(const char *fmt, ...)
+{
+	char s[256];
+	va_list args;
+
+	if (debug==0)
+		return;
+
+	va_start(args,fmt);
+	vsprintf(s, fmt, args);
+	printk(s);
+	va_end(args);
+}
+
+
 static int check_fsb(unsigned int fsbspeed)
 {
 	int delta;
@@ -190,13 +196,13 @@
 		speed = powernow_table[j].frequency;
 
 		if ((fid_codes[fid] % 10)==5) {
-#if defined(CONFIG_ACPI_PROCESSOR) || defined(CONFIG_ACPI_PROCESSOR_MODULE)
+#ifdef CONFIG_X86_POWERNOW_K7_ACPI
 			if (have_a0 == 1)
 				powernow_table[j].frequency = CPUFREQ_ENTRY_INVALID;
 #endif
 		}
 
-		dprintk (KERN_INFO PFX "   FID: 0x%x (%d.%dx [%dMHz])\t", fid,
+		dprintk (KERN_INFO PFX "   FID: 0x%x (%d.%dx [%dMHz])  ", fid,
 			fid_codes[fid] / 10, fid_codes[fid] % 10, speed/1000);
 
 		if (speed < minimum_speed)
@@ -285,7 +291,7 @@
 		change_VID(vid);
 		change_FID(fid);
 	}
-	
+
 
 	if (have_a0 == 1)
 		local_irq_enable();
@@ -294,7 +300,7 @@
 }
 
 
-#if defined(CONFIG_ACPI_PROCESSOR) || defined(CONFIG_ACPI_PROCESSOR_MODULE)
+#ifdef CONFIG_X86_POWERNOW_K7_ACPI
 
 struct acpi_processor_performance *acpi_processor_perf;
 
@@ -377,7 +383,7 @@
 				powernow_table[i].frequency = CPUFREQ_ENTRY_INVALID;
 		}
 
-		dprintk (KERN_INFO PFX "   FID: 0x%x (%d.%dx [%dMHz])\t", fid,
+		dprintk (KERN_INFO PFX "   FID: 0x%x (%d.%dx [%dMHz])  ", fid,
 			fid_codes[fid] / 10, fid_codes[fid] % 10, speed/1000);
 		dprintk ("VID: 0x%x (%d.%03dV)\n", vid,	mobile_vid_table[vid]/1000,
 			mobile_vid_table[vid]%1000);
@@ -467,9 +473,9 @@
 				    (maxfid==pst->maxfid) && (startvid==pst->startvid))
 				{
 					dprintk (KERN_INFO PFX "PST:%d (@%p)\n", i, pst);
-					dprintk (KERN_INFO PFX " cpuid: 0x%x\t", pst->cpuid);
-					dprintk ("fsb: %d\t", pst->fsbspeed);
-					dprintk ("maxFID: 0x%x\t", pst->maxfid);
+					dprintk (KERN_INFO PFX " cpuid: 0x%x  ", pst->cpuid);
+					dprintk ("fsb: %d  ", pst->fsbspeed);
+					dprintk ("maxFID: 0x%x  ", pst->maxfid);
 					dprintk ("startvid: 0x%x\n", pst->startvid);
 
 					ret = get_ranges ((char *) pst + sizeof (struct pst_s));
@@ -591,14 +597,14 @@
 	rdmsrl (MSR_K7_FID_VID_STATUS, fidvidstatus.val);
 
 	/* A K7 with powernow technology is set to max frequency by BIOS */
-	fsb = (10 * cpu_khz) / fid_codes[fidvidstatus.bits.CFID];
+	fsb = (10 * cpu_khz) / fid_codes[fidvidstatus.bits.MFID];
 	if (!fsb) {
 		printk(KERN_WARNING PFX "can not determine bus frequency\n");
 		return -EINVAL;
 	}
 	dprintk(KERN_INFO PFX "FSB: %3d.%03d MHz\n", fsb/1000, fsb%1000);
 
- 	if (dmi_check_system(powernow_dmi_table) || acpi_force) {
+	if (dmi_check_system(powernow_dmi_table) || acpi_force) {
 		printk (KERN_INFO PFX "PSB/PST known to be broken.  Trying ACPI instead\n");
 		result = powernow_acpi_init();
 	} else {
@@ -628,7 +634,7 @@
 
 	policy->governor = CPUFREQ_DEFAULT_GOVERNOR;
 
-	policy->cpuinfo.transition_latency = 20 * latency / fsb;
+	policy->cpuinfo.transition_latency = cpufreq_scale(2000000UL, fsb, latency);
 
 	policy->cur = powernow_get(0);
 
@@ -648,14 +654,14 @@
 };
 
 static struct cpufreq_driver powernow_driver = {
-	.verify 	= powernow_verify,
-	.target 	= powernow_target,
-	.get		= powernow_get,	
-	.init		= powernow_cpu_init,
-	.exit		= powernow_cpu_exit,
-	.name		= "powernow-k7",
-	.owner		= THIS_MODULE,
-	.attr		= powernow_table_attr,
+	.verify	= powernow_verify,
+	.target	= powernow_target,
+	.get	= powernow_get,
+	.init	= powernow_cpu_init,
+	.exit	= powernow_cpu_exit,
+	.name	= "powernow-k7",
+	.owner	= THIS_MODULE,
+	.attr	= powernow_table_attr,
 };
 
 static int __init powernow_init (void)
@@ -668,7 +674,7 @@
 
 static void __exit powernow_exit (void)
 {
-#if defined(CONFIG_ACPI_PROCESSOR) || defined(CONFIG_ACPI_PROCESSOR_MODULE)
+#ifdef CONFIG_X86_POWERNOW_K7_ACPI
 	if (acpi_processor_perf) {
 		acpi_processor_unregister_performance(acpi_processor_perf, 0);
 		kfree(acpi_processor_perf);
@@ -679,8 +685,10 @@
 		kfree(powernow_table);
 }
 
+module_param(debug, int, 0444);
+MODULE_PARM_DESC(debug, "enable debug output.");
 module_param(acpi_force,  int, 0444);
-MODULE_PARM_DESC(acpi_force, "Force ACPI to be used");
+MODULE_PARM_DESC(acpi_force, "Force ACPI to be used.");
 
 MODULE_AUTHOR ("Dave Jones <davej@codemonkey.org.uk>");
 MODULE_DESCRIPTION ("Powernow driver for AMD K7 processors.");
diff -Nru a/arch/i386/kernel/cpu/cpufreq/powernow-k8.c b/arch/i386/kernel/cpu/cpufreq/powernow-k8.c
--- a/arch/i386/kernel/cpu/cpufreq/powernow-k8.c	2004-10-18 14:56:33 -07:00
+++ b/arch/i386/kernel/cpu/cpufreq/powernow-k8.c	2004-10-18 14:56:33 -07:00
@@ -32,7 +32,7 @@
 #include <asm/io.h>
 #include <asm/delay.h>
 
-#if defined(CONFIG_ACPI_PROCESSOR) || defined(CONFIG_ACPI_PROCESSOR_MODULE)
+#ifdef CONFIG_X86_POWERNOW_K8_ACPI
 #include <linux/acpi.h>
 #include <acpi/processor.h>
 #endif
@@ -664,7 +664,7 @@
 	return -ENODEV;
 }
 
-#if defined(CONFIG_ACPI_PROCESSOR) || defined(CONFIG_ACPI_PROCESSOR_MODULE)
+#ifdef CONFIG_X86_POWERNOW_K8_ACPI
 static void powernow_k8_acpi_pst_values(struct powernow_k8_data *data, unsigned int index)
 {
 	if (!data->acpi_data.state_count)
@@ -948,13 +948,13 @@
 		 * an UP version, and is deprecated by AMD.
 		 */
 
-		if (pol->cpu != 0) {
-			printk(KERN_ERR PFX "init not cpu 0\n");
+		if ((num_online_cpus() != 1) || (num_possible_cpus() != 1)) {
+			printk(KERN_INFO PFX "MP systems not supported by PSB BIOS structure\n");
 			kfree(data);
 			return -ENODEV;
 		}
-		if ((num_online_cpus() != 1) || (num_possible_cpus() != 1)) {
-			printk(KERN_INFO PFX "MP systems not supported by PSB BIOS structure\n");
+		if (pol->cpu != 0) {
+			printk(KERN_ERR PFX "init not cpu 0\n");
 			kfree(data);
 			return -ENODEV;
 		}
@@ -1024,7 +1024,7 @@
 	return -ENODEV;
 }
 
-static int __exit powernowk8_cpu_exit (struct cpufreq_policy *pol)
+static int __devexit powernowk8_cpu_exit (struct cpufreq_policy *pol)
 {
 	struct powernow_k8_data *data = powernow_data[pol->cpu];
 
@@ -1076,7 +1076,7 @@
 	.verify = powernowk8_verify,
 	.target = powernowk8_target,
 	.init = powernowk8_cpu_init,
-	.exit = powernowk8_cpu_exit,
+	.exit = __devexit_p(powernowk8_cpu_exit),
 	.get = powernowk8_get,
 	.name = "powernow-k8",
 	.owner = THIS_MODULE,
diff -Nru a/arch/i386/kernel/cpu/cpufreq/powernow-k8.h b/arch/i386/kernel/cpu/cpufreq/powernow-k8.h
--- a/arch/i386/kernel/cpu/cpufreq/powernow-k8.h	2004-10-18 14:56:33 -07:00
+++ b/arch/i386/kernel/cpu/cpufreq/powernow-k8.h	2004-10-18 14:56:33 -07:00
@@ -29,7 +29,7 @@
 	 * frequency is in kHz */
 	struct cpufreq_frequency_table  *powernow_table;
 
-#if defined(CONFIG_ACPI_PROCESSOR) || defined(CONFIG_ACPI_PROCESSOR_MODULE)
+#ifdef CONFIG_X86_POWERNOW_K8_ACPI
 	/* the acpi table needs to be kept. it's only available if ACPI was
 	 * used to determine valid frequency/vid/fid states */
 	struct acpi_processor_performance acpi_data;
diff -Nru a/arch/i386/kernel/cpu/cpufreq/speedstep-centrino.c b/arch/i386/kernel/cpu/cpufreq/speedstep-centrino.c
--- a/arch/i386/kernel/cpu/cpufreq/speedstep-centrino.c	2004-10-18 14:56:28 -07:00
+++ b/arch/i386/kernel/cpu/cpufreq/speedstep-centrino.c	2004-10-18 14:56:28 -07:00
@@ -10,7 +10,7 @@
  * Copyright (C) 2003 Jeremy Fitzhardinge <jeremy@goop.org>
  *
  * WARNING WARNING WARNING
- * 
+ *
  * This driver manipulates the PERF_CTL MSR, which is only somewhat
  * documented.  While it seems to work on my laptop, it has not been
  * tested anywhere else, and it may not work for you, do strange
@@ -23,6 +23,11 @@
 #include <linux/cpufreq.h>
 #include <linux/config.h>
 
+#ifdef CONFIG_X86_SPEEDSTEP_CENTRINO_ACPI
+#include <linux/acpi.h>
+#include <acpi/processor.h>
+#endif
+
 #include <asm/msr.h>
 #include <asm/processor.h>
 #include <asm/cpufeature.h>
@@ -41,24 +46,24 @@
 struct cpu_id
 {
 	__u8	x86;            /* CPU family */
-	__u8	x86_vendor;     /* CPU vendor */
 	__u8	x86_model;	/* model */
 	__u8	x86_mask;	/* stepping */
 };
 
-static const struct cpu_id cpu_id_banias = {
-	.x86_vendor = X86_VENDOR_INTEL,
-	.x86 = 6,
-	.x86_model = 9,
-	.x86_mask = 5,
+enum {
+	CPU_BANIAS,
+	CPU_DOTHAN_A1,
+	CPU_DOTHAN_A2,
+	CPU_DOTHAN_B0,
 };
 
-static const struct cpu_id cpu_id_dothan_a1 = {
-	.x86_vendor = X86_VENDOR_INTEL,
-	.x86 = 6,
-	.x86_model = 13,
-	.x86_mask = 1,
+static const struct cpu_id cpu_ids[] = {
+	[CPU_BANIAS]	= { 6,  9, 5 },
+	[CPU_DOTHAN_A1]	= { 6, 13, 1 },
+	[CPU_DOTHAN_A2]	= { 6, 13, 2 },
+	[CPU_DOTHAN_B0]	= { 6, 13, 6 },
 };
+#define N_IDS	(sizeof(cpu_ids)/sizeof(cpu_ids[0]))
 
 struct cpu_model
 {
@@ -68,10 +73,11 @@
 
 	struct cpufreq_frequency_table *op_points; /* clock/voltage pairs */
 };
-static int centrino_verify_cpu_id(struct cpuinfo_x86 *c, const struct cpu_id *x);
+static int centrino_verify_cpu_id(const struct cpuinfo_x86 *c, const struct cpu_id *x);
 
 /* Operating points for current CPU */
 static struct cpu_model *centrino_model;
+static int centrino_cpu;
 
 #ifdef CONFIG_X86_SPEEDSTEP_CENTRINO_TABLE
 
@@ -84,7 +90,7 @@
 		.index = (((mhz)/100) << 8) | ((mv - 700) / 16)		\
 	}
 
-/* 
+/*
  * These voltage tables were derived from the Intel Pentium M
  * datasheet, document 25261202.pdf, Table 5.  I have verified they
  * are consistent with my IBM ThinkPad X31, which has a 1.3GHz Pentium
@@ -103,9 +109,9 @@
 /* Ultra Low Voltage Intel Pentium M processor 1000MHz (Banias) */
 static struct cpufreq_frequency_table banias_1000[] =
 {
-	OP(600,  844),
-	OP(800,  972),
-	OP(900,  988),
+	OP(600,   844),
+	OP(800,   972),
+	OP(900,   988),
 	OP(1000, 1004),
 	{ .frequency = CPUFREQ_TABLE_END }
 };
@@ -135,7 +141,7 @@
 };
 
 /* Intel Pentium M processor 1.30GHz (Banias) */
-static struct cpufreq_frequency_table banias_1300[] = 
+static struct cpufreq_frequency_table banias_1300[] =
 {
 	OP( 600,  956),
 	OP( 800, 1260),
@@ -146,7 +152,7 @@
 };
 
 /* Intel Pentium M processor 1.40GHz (Banias) */
-static struct cpufreq_frequency_table banias_1400[] = 
+static struct cpufreq_frequency_table banias_1400[] =
 {
 	OP( 600,  956),
 	OP( 800, 1180),
@@ -157,7 +163,7 @@
 };
 
 /* Intel Pentium M processor 1.50GHz (Banias) */
-static struct cpufreq_frequency_table banias_1500[] = 
+static struct cpufreq_frequency_table banias_1500[] =
 {
 	OP( 600,  956),
 	OP( 800, 1116),
@@ -169,7 +175,7 @@
 };
 
 /* Intel Pentium M processor 1.60GHz (Banias) */
-static struct cpufreq_frequency_table banias_1600[] = 
+static struct cpufreq_frequency_table banias_1600[] =
 {
 	OP( 600,  956),
 	OP( 800, 1036),
@@ -199,13 +205,13 @@
 	.max_freq	= (max)*1000,	\
 	.op_points	= banias_##max,	\
 }
-#define BANIAS(max)	_BANIAS(&cpu_id_banias, max, #max)
+#define BANIAS(max)	_BANIAS(&cpu_ids[CPU_BANIAS], max, #max)
 
 /* CPU models, their operating frequency range, and freq/voltage
    operating points */
-static struct cpu_model models[] = 
+static struct cpu_model models[] =
 {
-	_BANIAS(&cpu_id_banias, 900, " 900"),
+	_BANIAS(&cpu_ids[CPU_BANIAS], 900, " 900"),
 	BANIAS(1000),
 	BANIAS(1100),
 	BANIAS(1200),
@@ -214,6 +220,12 @@
 	BANIAS(1500),
 	BANIAS(1600),
 	BANIAS(1700),
+
+	/* NULL model_name is a wildcard */
+	{ &cpu_ids[CPU_DOTHAN_A1], NULL, 0, NULL },
+	{ &cpu_ids[CPU_DOTHAN_A2], NULL, 0, NULL },
+	{ &cpu_ids[CPU_DOTHAN_B0], NULL, 0, NULL },
+
 	{ NULL, }
 };
 #undef _BANIAS
@@ -224,19 +236,30 @@
 	struct cpuinfo_x86 *cpu = &cpu_data[policy->cpu];
 	struct cpu_model *model;
 
-	for(model = models; model->model_name != NULL; model++)
-		if ((strcmp(cpu->x86_model_id, model->model_name) == 0) &&
-		    (!centrino_verify_cpu_id(cpu, model->cpu_id)))
+	for(model = models; model->cpu_id != NULL; model++)
+		if (centrino_verify_cpu_id(cpu, model->cpu_id) &&
+		    (model->model_name == NULL ||
+		     strcmp(cpu->x86_model_id, model->model_name) == 0))
 			break;
-	if (model->model_name == NULL) {
+
+	if (model->cpu_id == NULL) {
+		/* No match at all */
 		printk(KERN_INFO PFX "no support for CPU model \"%s\": "
 		       "send /proc/cpuinfo to " MAINTAINER "\n",
 		       cpu->x86_model_id);
 		return -ENOENT;
 	}
 
+	if (model->op_points == NULL) {
+		/* Matched a non-match */
+		printk(KERN_INFO PFX "no table support for CPU model \"%s\": \n",
+		       cpu->x86_model_id);
+		printk(KERN_INFO PFX "try compiling with CONFIG_X86_SPEEDSTEP_CENTRINO_ACPI enabled\n");
+		return -ENOENT;
+	}
+
 	centrino_model = model;
-		
+
 	printk(KERN_INFO PFX "found \"%s\": max frequency: %dkHz\n",
 	       model->model_name, model->max_freq);
 
@@ -247,31 +270,54 @@
 static inline int centrino_cpu_init_table(struct cpufreq_policy *policy) { return -ENODEV; }
 #endif /* CONFIG_X86_SPEEDSTEP_CENTRINO_TABLE */
 
-static int centrino_verify_cpu_id(struct cpuinfo_x86 *c, const struct cpu_id *x)
+static int centrino_verify_cpu_id(const struct cpuinfo_x86 *c, const struct cpu_id *x)
 {
 	if ((c->x86 == x->x86) &&
-	    (c->x86_vendor == x->x86_vendor) &&
 	    (c->x86_model == x->x86_model) &&
 	    (c->x86_mask == x->x86_mask))
-		return 0;
-	return -ENODEV;
+		return 1;
+	return 0;
 }
 
-/* Extract clock in kHz from PERF_CTL value */
+/* To be called only after centrino_model is initialized */
 static unsigned extract_clock(unsigned msr)
 {
-	msr = (msr >> 8) & 0xff;
-	return msr * 100000;
+	int i;
+
+	/*
+	 * Extract clock in kHz from PERF_CTL value
+	 * for centrino, as some DSDTs are buggy.
+	 * Ideally, this can be done using the acpi_data structure.
+	 */
+	if (centrino_cpu) {
+		msr = (msr >> 8) & 0xff;
+		return msr * 100000;
+	}
+
+	if ((!centrino_model) || (!centrino_model->op_points))
+		return 0;
+
+	msr &= 0xffff;
+	for (i=0;centrino_model->op_points[i].frequency != CPUFREQ_TABLE_END; i++) {
+		if (msr == centrino_model->op_points[i].index)
+		return centrino_model->op_points[i].frequency;
+	}
+	return 0;
 }
 
 /* Return the current CPU frequency in kHz */
 static unsigned int get_cur_freq(unsigned int cpu)
 {
 	unsigned l, h;
-	if (cpu)
+	cpumask_t saved_mask;
+
+	saved_mask = current->cpus_allowed;
+	set_cpus_allowed(current, cpumask_of_cpu(cpu));
+	if (smp_processor_id() != cpu)
 		return 0;
 
 	rdmsr(MSR_IA32_PERF_STATUS, l, h);
+	set_cpus_allowed(current, saved_mask);
 	return extract_clock(l);
 }
 
@@ -280,13 +326,8 @@
 
 static struct acpi_processor_performance p;
 
-#include <linux/acpi.h>
-#include <acpi/processor.h>
-
-#define ACPI_PDC_CAPABILITY_ENHANCED_SPEEDSTEP 0x1
-
 /*
- * centrino_cpu_init_acpi - register with ACPI P-States library 
+ * centrino_cpu_init_acpi - register with ACPI P-States library
  *
  * Register with the ACPI P-States library (part of drivers/acpi/processor.c)
  * in order to determine correct frequency and voltage pairings by reading
@@ -296,7 +337,7 @@
 {
 	union acpi_object		arg0 = {ACPI_TYPE_BUFFER};
 	u32				arg0_buf[3];
-	struct acpi_object_list 	arg_list = {1, &arg0};
+	struct acpi_object_list		arg_list = {1, &arg0};
 	unsigned long			cur_freq;
 	int				result = 0, i;
 
@@ -305,12 +346,12 @@
         arg0.buffer.pointer = (u8 *) arg0_buf;
         arg0_buf[0] = ACPI_PDC_REVISION_ID;
         arg0_buf[1] = 1;
-        arg0_buf[2] = ACPI_PDC_CAPABILITY_ENHANCED_SPEEDSTEP;
+        arg0_buf[2] = ACPI_PDC_EST_CAPABILITY_SMP | ACPI_PDC_EST_CAPABILITY_MSR;
 
 	p.pdc = &arg_list;
 
 	/* register with ACPI core */
-        if (acpi_processor_register_performance(&p, 0))
+        if (acpi_processor_register_performance(&p, policy->cpu))
                 return -EIO;
 
 	/* verify the acpi_data */
@@ -318,7 +359,7 @@
                 printk(KERN_DEBUG "No P-States\n");
                 result = -ENODEV;
                 goto err_unreg;
- 	}
+	}
 
 	if ((p.control_register.space_id != ACPI_ADR_SPACE_FIXED_HARDWARE) ||
 	    (p.status_register.space_id != ACPI_ADR_SPACE_FIXED_HARDWARE)) {
@@ -340,11 +381,10 @@
 			goto err_unreg;
 		}
 
-		if (extract_clock(p.states[i].control) != 
-		    (p.states[i].core_frequency * 1000)) {
-			printk(KERN_DEBUG "Invalid encoded frequency\n");
-			result = -EINVAL;
-			goto err_unreg;
+		if (p.states[i].core_frequency > p.states[0].core_frequency) {
+			printk(KERN_DEBUG "P%u has larger frequency than P0, skipping\n", i);
+			p.states[i].core_frequency = 0;
+			continue;
 		}
 	}
 
@@ -357,29 +397,43 @@
 
 	centrino_model->model_name=NULL;
 	centrino_model->max_freq = p.states[0].core_frequency * 1000;
-	centrino_model->op_points =  kmalloc(sizeof(struct cpufreq_frequency_table) * 
+	centrino_model->op_points =  kmalloc(sizeof(struct cpufreq_frequency_table) *
 					     (p.state_count + 1), GFP_KERNEL);
         if (!centrino_model->op_points) {
                 result = -ENOMEM;
                 goto err_kfree;
         }
 
-	cur_freq = get_cur_freq(0);
-
         for (i=0; i<p.state_count; i++) {
 		centrino_model->op_points[i].index = p.states[i].control;
 		centrino_model->op_points[i].frequency = p.states[i].core_frequency * 1000;
+	}
+	centrino_model->op_points[p.state_count].frequency = CPUFREQ_TABLE_END;
+
+	cur_freq = get_cur_freq(policy->cpu);
+
+	for (i=0; i<p.state_count; i++) {
+		if (extract_clock(centrino_model->op_points[i].index) !=
+		    (centrino_model->op_points[i].frequency)) {
+			printk(KERN_DEBUG "Invalid encoded frequency\n");
+			result = -EINVAL;
+			goto err_kfree_all;
+		}
+
 		if (cur_freq == centrino_model->op_points[i].frequency)
 			p.state = i;
+		if (!p.states[i].core_frequency)
+			centrino_model->op_points[i].frequency = CPUFREQ_ENTRY_INVALID;
 	}
-	centrino_model->op_points[p.state_count].frequency = CPUFREQ_TABLE_END;
 
 	return 0;
 
+ err_kfree_all:
+	kfree(centrino_model->op_points);
  err_kfree:
 	kfree(centrino_model);
  err_unreg:
-	acpi_processor_unregister_performance(&p, 0);
+	acpi_processor_unregister_performance(&p, policy->cpu);
 	return (result);
 }
 #else
@@ -392,21 +446,30 @@
 	unsigned freq;
 	unsigned l, h;
 	int ret;
+	int i;
 
-	if (policy->cpu != 0)
+	/* Only Intel makes Enhanced Speedstep-capable CPUs */
+	if (cpu->x86_vendor != X86_VENDOR_INTEL || !cpu_has(cpu, X86_FEATURE_EST))
 		return -ENODEV;
 
-	if (!cpu_has(cpu, X86_FEATURE_EST))
-		return -ENODEV;
+	for (i = 0; i < N_IDS; i++)
+		if (centrino_verify_cpu_id(cpu, &cpu_ids[i]))
+			break;
 
-	if ((centrino_verify_cpu_id(cpu, &cpu_id_banias)) &&
-	    (centrino_verify_cpu_id(cpu, &cpu_id_dothan_a1))) {
-		printk(KERN_INFO PFX "found unsupported CPU with Enhanced SpeedStep: "
-		       "send /proc/cpuinfo to " MAINTAINER "\n");
-		return -ENODEV;
-	}
+	if (i != N_IDS)
+		centrino_cpu = 1;
 
 	if (centrino_cpu_init_acpi(policy)) {
+		if (policy->cpu != 0)
+			return -ENODEV;
+
+		if (!centrino_cpu) {
+			printk(KERN_INFO PFX "found unsupported CPU with "
+			"Enhanced SpeedStep: send /proc/cpuinfo to "
+			MAINTAINER "\n");
+			return -ENODEV;
+		}
+
 		if (centrino_cpu_init_table(policy)) {
 			return -ENODEV;
 		}
@@ -415,11 +478,11 @@
 	/* Check to see if Enhanced SpeedStep is enabled, and try to
 	   enable it if not. */
 	rdmsr(MSR_IA32_MISC_ENABLE, l, h);
-		
+
 	if (!(l & (1<<16))) {
 		l |= (1<<16);
 		wrmsr(MSR_IA32_MISC_ENABLE, l, h);
-		
+
 		/* check to see if it stuck */
 		rdmsr(MSR_IA32_MISC_ENABLE, l, h);
 		if (!(l & (1<<16))) {
@@ -428,7 +491,7 @@
 		}
 	}
 
-	freq = get_cur_freq(0);
+	freq = get_cur_freq(policy->cpu);
 
 	policy->governor = CPUFREQ_DEFAULT_GOVERNOR;
 	policy->cpuinfo.transition_latency = 10000; /* 10uS transition latency */
@@ -436,7 +499,7 @@
 
 	dprintk(KERN_INFO PFX "centrino_cpu_init: policy=%d cur=%dkHz\n",
 		policy->policy, policy->cur);
-	
+
 	ret = cpufreq_frequency_table_cpuinfo(policy, centrino_model->op_points);
 	if (ret)
 		return (ret);
@@ -455,7 +518,7 @@
 
 #ifdef CONFIG_X86_SPEEDSTEP_CENTRINO_ACPI
 	if (!centrino_model->model_name) {
-		acpi_processor_unregister_performance(&p, 0);
+		acpi_processor_unregister_performance(&p, policy->cpu);
 		kfree(centrino_model->op_points);
 		kfree(centrino_model);
 	}
@@ -493,19 +556,35 @@
 	unsigned int    newstate = 0;
 	unsigned int	msr, oldmsr, h;
 	struct cpufreq_freqs	freqs;
+	cpumask_t		saved_mask;
+	int			retval;
 
 	if (centrino_model == NULL)
 		return -ENODEV;
 
+	/*
+	 * Support for SMP systems.
+	 * Make sure we are running on the CPU that wants to change frequency
+	 */
+	saved_mask = current->cpus_allowed;
+	set_cpus_allowed(current, cpumask_of_cpu(policy->cpu));
+	if (smp_processor_id() != policy->cpu) {
+		return(-EAGAIN);
+	}
+
 	if (cpufreq_frequency_table_target(policy, centrino_model->op_points, target_freq,
-					   relation, &newstate))
-		return -EINVAL;
+					   relation, &newstate)) {
+		retval = -EINVAL;
+		goto migrate_end;
+	}
 
 	msr = centrino_model->op_points[newstate].index;
 	rdmsr(MSR_IA32_PERF_CTL, oldmsr, h);
 
-	if (msr == (oldmsr & 0xffff))
-		return 0;
+	if (msr == (oldmsr & 0xffff)) {
+		retval = 0;
+		goto migrate_end;
+	}
 
 	/* Hm, old frequency can either be the last value we put in
 	   PERF_CTL, or whatever it is now. The trouble is that TM2
@@ -514,31 +593,34 @@
 	   tell us something happened, but it may leave the things on
 	   the notifier chain confused; we therefore stick to using
 	   the last programmed speed rather than the current speed for
-	   "old". 
+	   "old".
 
 	   TODO: work out how the TCC interrupts work, and try to
 	   catch the CPU changing things under us.
 	*/
-	freqs.cpu = 0;
+	freqs.cpu = policy->cpu;
 	freqs.old = extract_clock(oldmsr);
 	freqs.new = extract_clock(msr);
-	
+
 	dprintk(KERN_INFO PFX "target=%dkHz old=%d new=%d msr=%04x\n",
 		target_freq, freqs.old, freqs.new, msr);
 
-	cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);	
+	cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);
 
 	/* all but 16 LSB are "reserved", so treat them with
 	   care */
 	oldmsr &= ~0xffff;
 	msr &= 0xffff;
 	oldmsr |= msr;
-	
+
 	wrmsr(MSR_IA32_PERF_CTL, oldmsr, h);
 
 	cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
 
-	return 0;
+	retval = 0;
+migrate_end:
+	set_cpus_allowed(current, saved_mask);
+	return (retval);
 }
 
 static struct freq_attr* centrino_attr[] = {
@@ -547,12 +629,12 @@
 };
 
 static struct cpufreq_driver centrino_driver = {
-	.name		= "centrino", /* should be speedstep-centrino, 
+	.name		= "centrino", /* should be speedstep-centrino,
 					 but there's a 16 char limit */
 	.init		= centrino_cpu_init,
 	.exit		= centrino_cpu_exit,
-	.verify 	= centrino_verify,
-	.target 	= centrino_target,
+	.verify		= centrino_verify,
+	.target		= centrino_target,
 	.get		= get_cur_freq,
 	.attr           = centrino_attr,
 	.owner		= THIS_MODULE,
diff -Nru a/arch/i386/kernel/cpu/cpufreq/speedstep-ich.c b/arch/i386/kernel/cpu/cpufreq/speedstep-ich.c
--- a/arch/i386/kernel/cpu/cpufreq/speedstep-ich.c	2004-10-18 14:55:53 -07:00
+++ b/arch/i386/kernel/cpu/cpufreq/speedstep-ich.c	2004-10-18 14:55:53 -07:00
@@ -7,7 +7,7 @@
  *  for chipsets ICH2-M and ICH3-M.
  *
  *  Many thanks to Ducrot Bruno for finding and fixing the last
- *  "missing link" for ICH2-M/ICH3-M support, and to Thomas Winkler 
+ *  "missing link" for ICH2-M/ICH3-M support, and to Thomas Winkler
  *  for extensive testing.
  *
  *  BIG FAT DISCLAIMER: Work in progress code. Possibly *dangerous*
@@ -19,7 +19,7 @@
  *********************************************************************/
 
 #include <linux/kernel.h>
-#include <linux/module.h> 
+#include <linux/module.h>
 #include <linux/init.h>
 #include <linux/cpufreq.h>
 #include <linux/pci.h>
@@ -29,24 +29,24 @@
 
 
 /* speedstep_chipset:
- *   It is necessary to know which chipset is used. As accesses to 
- * this device occur at various places in this module, we need a 
+ *   It is necessary to know which chipset is used. As accesses to
+ * this device occur at various places in this module, we need a
  * static struct pci_dev * pointing to that device.
  */
-static struct pci_dev			*speedstep_chipset_dev;
+static struct pci_dev *speedstep_chipset_dev;
 
 
 /* speedstep_processor
  */
-static unsigned int			speedstep_processor = 0;
+static unsigned int speedstep_processor = 0;
 
 
-/* 
+/*
  *   There are only two frequency states for each processor. Values
  * are in kHz for the time being.
  */
 static struct cpufreq_frequency_table speedstep_freqs[] = {
-	{SPEEDSTEP_HIGH, 	0},
+	{SPEEDSTEP_HIGH,	0},
 	{SPEEDSTEP_LOW,		0},
 	{0,			CPUFREQ_TABLE_END},
 };
@@ -68,22 +68,21 @@
  * speedstep_set_state - set the SpeedStep state
  * @state: new processor frequency state (SPEEDSTEP_LOW or SPEEDSTEP_HIGH)
  *
- *   Tries to change the SpeedStep state. 
+ *   Tries to change the SpeedStep state.
  */
 static void speedstep_set_state (unsigned int state)
 {
-	u32			pmbase;
-	u8			pm2_blk;
-	u8			value;
-	unsigned long		flags;
+	u32 pmbase;
+	u8 pm2_blk;
+	u8 value;
+	unsigned long flags;
 
 	if (!speedstep_chipset_dev || (state > 0x1))
 		return;
 
 	/* get PMBASE */
 	pci_read_config_dword(speedstep_chipset_dev, 0x40, &pmbase);
-	if (!(pmbase & 0x01))
-	{
+	if (!(pmbase & 0x01)) {
 		printk(KERN_ERR "cpufreq: could not find speedstep register\n");
 		return;
 	}
@@ -146,18 +145,16 @@
  */
 static int speedstep_activate (void)
 {
-	u16		value = 0;
+	u16 value = 0;
 
 	if (!speedstep_chipset_dev)
 		return -EINVAL;
 
-	pci_read_config_word(speedstep_chipset_dev, 
-			     0x00A0, &value);
+	pci_read_config_word(speedstep_chipset_dev, 0x00A0, &value);
 	if (!(value & 0x08)) {
 		value |= 0x08;
 		dprintk(KERN_DEBUG "cpufreq: activating SpeedStep (TM) registers\n");
-		pci_write_config_word(speedstep_chipset_dev, 
-				      0x00A0, value);
+		pci_write_config_word(speedstep_chipset_dev, 0x00A0, value);
 	}
 
 	return 0;
@@ -167,15 +164,15 @@
 /**
  * speedstep_detect_chipset - detect the Southbridge which contains SpeedStep logic
  *
- *   Detects ICH2-M, ICH3-M and ICH4-M so far. The pci_dev points to 
- * the LPC bridge / PM module which contains all power-management 
+ *   Detects ICH2-M, ICH3-M and ICH4-M so far. The pci_dev points to
+ * the LPC bridge / PM module which contains all power-management
  * functions. Returns the SPEEDSTEP_CHIPSET_-number for the detected
  * chipset, or zero on failure.
  */
 static unsigned int speedstep_detect_chipset (void)
 {
 	speedstep_chipset_dev = pci_find_subsys(PCI_VENDOR_ID_INTEL,
-			      PCI_DEVICE_ID_INTEL_82801DB_12, 
+			      PCI_DEVICE_ID_INTEL_82801DB_12,
 			      PCI_ANY_ID,
 			      PCI_ANY_ID,
 			      NULL);
@@ -183,7 +180,7 @@
 		return 4; /* 4-M */
 
 	speedstep_chipset_dev = pci_find_subsys(PCI_VENDOR_ID_INTEL,
-			      PCI_DEVICE_ID_INTEL_82801CA_12, 
+			      PCI_DEVICE_ID_INTEL_82801CA_12,
 			      PCI_ANY_ID,
 			      PCI_ANY_ID,
 			      NULL);
@@ -198,11 +195,11 @@
 			      NULL);
 	if (speedstep_chipset_dev) {
 		/* speedstep.c causes lockups on Dell Inspirons 8000 and
-		 * 8100 which use a pretty old revision of the 82815 
+		 * 8100 which use a pretty old revision of the 82815
 		 * host brige. Abort on these systems.
 		 */
-		static struct pci_dev	*hostbridge;
-		u8			rev = 0;
+		static struct pci_dev *hostbridge;
+		u8 rev = 0;
 
 		hostbridge  = pci_find_subsys(PCI_VENDOR_ID_INTEL,
 			      PCI_DEVICE_ID_INTEL_82815_MC,
@@ -212,7 +209,7 @@
 
 		if (!hostbridge)
 			return 2; /* 2-M */
-			
+
 		pci_read_config_byte(hostbridge, PCI_REVISION_ID, &rev);
 		if (rev < 5) {
 			dprintk(KERN_INFO "cpufreq: hostbridge does not support speedstep\n");
@@ -226,6 +223,23 @@
 	return 0;
 }
 
+static unsigned int speedstep_get(unsigned int cpu)
+{
+	unsigned int speed;
+	cpumask_t cpus_allowed,affected_cpu_map;
+
+	/* only run on CPU to be set, or on its sibling */
+	cpus_allowed = current->cpus_allowed;
+#ifdef CONFIG_SMP
+	affected_cpu_map = cpu_sibling_map[cpu];
+#else
+	affected_cpu_map = cpumask_of_cpu(cpu);
+#endif
+	set_cpus_allowed(current, affected_cpu_map);
+	speed=speedstep_get_processor_frequency(speedstep_processor);
+	set_cpus_allowed(current, cpus_allowed);
+	return speed;
+}
 
 /**
  * speedstep_target - set a new CPUFreq policy
@@ -239,7 +253,7 @@
 			     unsigned int target_freq,
 			     unsigned int relation)
 {
-	unsigned int	newstate = 0;
+	unsigned int newstate = 0;
 	struct cpufreq_freqs freqs;
 	cpumask_t cpus_allowed, affected_cpu_map;
 	int i;
@@ -247,14 +261,14 @@
 	if (cpufreq_frequency_table_target(policy, &speedstep_freqs[0], target_freq, relation, &newstate))
 		return -EINVAL;
 
+	freqs.old = speedstep_get(policy->cpu);
+	freqs.new = speedstep_freqs[newstate].frequency;
+	freqs.cpu = policy->cpu;
+
 	/* no transition necessary */
 	if (freqs.old == freqs.new)
 		return 0;
 
-	freqs.old = speedstep_get_processor_frequency(speedstep_processor);
-	freqs.new = speedstep_freqs[newstate].frequency;
-	freqs.cpu = policy->cpu;
-
 	cpus_allowed = current->cpus_allowed;
 
 	/* only run on CPU to be set, or on its sibling */
@@ -301,9 +315,9 @@
 
 static int speedstep_cpu_init(struct cpufreq_policy *policy)
 {
-	int		result = 0;
-	unsigned int	speed;
-	cpumask_t       cpus_allowed,affected_cpu_map;
+	int result = 0;
+	unsigned int speed;
+	cpumask_t cpus_allowed,affected_cpu_map;
 
 
 	/* capability check */
@@ -324,18 +338,16 @@
 				     &speedstep_freqs[SPEEDSTEP_LOW].frequency,
 				     &speedstep_freqs[SPEEDSTEP_HIGH].frequency,
 				     &speedstep_set_state);
-	if (result) {
-		set_cpus_allowed(current, cpus_allowed);
+	set_cpus_allowed(current, cpus_allowed);
+	if (result)
 		return result;
-	}
 
 	/* get current speed setting */
-	speed = speedstep_get_processor_frequency(speedstep_processor);
-	set_cpus_allowed(current, cpus_allowed);
+	speed = speedstep_get(policy->cpu);
 	if (!speed)
 		return -EIO;
 
-	dprintk(KERN_INFO "cpufreq: currently at %s speed setting - %i MHz\n", 
+	dprintk(KERN_INFO "cpufreq: currently at %s speed setting - %i MHz\n",
 		(speed == speedstep_freqs[SPEEDSTEP_LOW].frequency) ? "low" : "high",
 		(speed / 1000));
 
@@ -360,11 +372,6 @@
 	return 0;
 }
 
-static unsigned int speedstep_get(unsigned int cpu)
-{
-	return speedstep_get_processor_frequency(speedstep_processor);
-}
-
 static struct freq_attr* speedstep_attr[] = {
 	&cpufreq_freq_attr_scaling_available_freqs,
 	NULL,
@@ -372,14 +379,14 @@
 
 
 static struct cpufreq_driver speedstep_driver = {
-	.name		= "speedstep-ich",
-	.verify 	= speedstep_verify,
-	.target 	= speedstep_target,
-	.init		= speedstep_cpu_init,
-	.exit		= speedstep_cpu_exit,
-	.get		= speedstep_get,
-	.owner		= THIS_MODULE,
-	.attr		= speedstep_attr,
+	.name	= "speedstep-ich",
+	.verify	= speedstep_verify,
+	.target	= speedstep_target,
+	.init	= speedstep_cpu_init,
+	.exit	= speedstep_cpu_exit,
+	.get	= speedstep_get,
+	.owner	= THIS_MODULE,
+	.attr	= speedstep_attr,
 };
 
 
diff -Nru a/arch/i386/kernel/cpu/cpufreq/speedstep-smi.c b/arch/i386/kernel/cpu/cpufreq/speedstep-smi.c
--- a/arch/i386/kernel/cpu/cpufreq/speedstep-smi.c	2004-10-18 14:56:29 -07:00
+++ b/arch/i386/kernel/cpu/cpufreq/speedstep-smi.c	2004-10-18 14:56:29 -07:00
@@ -115,6 +115,11 @@
 		: "=a" (result), "=b" (high_mhz), "=c" (low_mhz), "=d" (state), "=D" (edi)
 		: "a" (command), "b" (function), "c" (state), "d" (smi_port), "S" (0)
 	);
+
+	/* abort if results are obviously incorrect... */
+	if ((high_mhz + low_mhz) < 600)
+		return -EINVAL;
+
 	*high = high_mhz * 1000;
 	*low  = low_mhz  * 1000;
 
@@ -180,7 +185,7 @@
 	local_irq_restore(flags);
 
 	if (new_state == state) {
-		dprintk(KERN_INFO "cpufreq: change to %u MHz succeeded after %u tries with result %u\n", (freqs.new / 1000), retry, result);
+		dprintk(KERN_INFO "cpufreq: change to %u MHz succeeded after %u tries with result %u\n", (speedstep_freqs[new_state].frequency / 1000), retry, result);
 	} else {
 		printk(KERN_ERR "cpufreq: change failed with new_state %u and result %u\n", new_state, result);
 	}
diff -Nru a/arch/i386/kernel/cpu/intel.c b/arch/i386/kernel/cpu/intel.c
--- a/arch/i386/kernel/cpu/intel.c	2004-10-18 14:56:27 -07:00
+++ b/arch/i386/kernel/cpu/intel.c	2004-10-18 14:56:27 -07:00
@@ -72,41 +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 },
-	{ 0x79, LVL_2,      128 },
-	{ 0x7a, LVL_2,      256 },
-	{ 0x7b, LVL_2,      512 },
-	{ 0x7c, LVL_2,      1024 },
-	{ 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/mtrr/mtrr.h b/arch/i386/kernel/cpu/mtrr/mtrr.h
--- a/arch/i386/kernel/cpu/mtrr/mtrr.h	2004-10-18 14:56:20 -07:00
+++ b/arch/i386/kernel/cpu/mtrr/mtrr.h	2004-10-18 14:56:20 -07:00
@@ -52,7 +52,6 @@
 };
 
 extern int generic_get_free_region(unsigned long base, unsigned long size);
-extern void generic_init_secondary(void);
 extern int generic_validate_add_page(unsigned long base, unsigned long size,
 				     unsigned int type);
 
diff -Nru a/arch/i386/kernel/cpu/proc.c b/arch/i386/kernel/cpu/proc.c
--- a/arch/i386/kernel/cpu/proc.c	2004-10-18 14:57:03 -07:00
+++ b/arch/i386/kernel/cpu/proc.c	2004-10-18 14:57:03 -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/dmi_scan.c b/arch/i386/kernel/dmi_scan.c
--- a/arch/i386/kernel/dmi_scan.c	2004-10-18 14:56:28 -07:00
+++ b/arch/i386/kernel/dmi_scan.c	2004-10-18 14:56:28 -07:00
@@ -4,7 +4,7 @@
 #include <linux/init.h>
 #include <linux/module.h>
 #include <linux/slab.h>
-#include <asm/acpi.h>
+#include <linux/acpi.h>
 #include <asm/io.h>
 #include <linux/pm.h>
 #include <asm/system.h>
@@ -163,27 +163,6 @@
 #define MATCH		DMI_MATCH
 
 /*
- * Some machines, usually laptops, can't handle an enabled local APIC.
- * The symptoms include hangs or reboots when suspending or resuming,
- * attaching or detaching the power cord, or entering BIOS setup screens
- * through magic key sequences.
- */
-static int __init local_apic_kills_bios(struct dmi_blacklist *d)
-{
-#ifdef CONFIG_X86_LOCAL_APIC
-	extern int enable_local_apic;
-	if (enable_local_apic == 0) {
-		enable_local_apic = -1;
-		printk(KERN_WARNING "%s with broken BIOS detected. "
-		       "Refusing to enable the local APIC.\n",
-		       d->ident);
-	}
-#endif
-	return 0;
-}
-
-
-/*
  * Toshiba keyboard likes to repeat keys when they are not repeated.
  */
 
@@ -284,32 +263,6 @@
  
 static __initdata struct dmi_blacklist dmi_blacklist[]={
 
-	/* Machines which have problems handling enabled local APICs */
-
-	{ local_apic_kills_bios, "Dell Inspiron", {
-			MATCH(DMI_SYS_VENDOR, "Dell Computer Corporation"),
-			MATCH(DMI_PRODUCT_NAME, "Inspiron"),
-			NO_MATCH, NO_MATCH
-			} },
-
-	{ local_apic_kills_bios, "Dell Latitude", {
-			MATCH(DMI_SYS_VENDOR, "Dell Computer Corporation"),
-			MATCH(DMI_PRODUCT_NAME, "Latitude"),
-			NO_MATCH, NO_MATCH
-			} },
-
-	{ local_apic_kills_bios, "IBM Thinkpad T20", {
-			MATCH(DMI_BOARD_VENDOR, "IBM"),
-			MATCH(DMI_BOARD_NAME, "264741U"),
-			NO_MATCH, NO_MATCH
-			} },
-
-	{ local_apic_kills_bios, "ASUS L3C", {
-			MATCH(DMI_BOARD_VENDOR, "ASUSTeK Computer INC."),
-			MATCH(DMI_BOARD_NAME, "P4_L3C"),
-			NO_MATCH, NO_MATCH
-			} },
-
 	{ broken_toshiba_keyboard, "Toshiba Satellite 4030cdt", { /* Keyboard generates spurious repeats */
 			MATCH(DMI_PRODUCT_NAME, "S4030CDT/4.3"),
 			NO_MATCH, NO_MATCH, NO_MATCH
@@ -490,41 +443,6 @@
 
 	{ NULL, }
 };
-	
-	
-/*
- *	Walk the blacklist table running matching functions until someone 
- *	returns 1 or we hit the end.
- */
- 
-
-static __init void dmi_check_blacklist(void)
-{
-#ifdef	CONFIG_ACPI_BOOT
-#define	ACPI_BLACKLIST_CUTOFF_YEAR	2001
-
-	if (dmi_ident[DMI_BIOS_DATE]) { 
-		char *s = strrchr(dmi_ident[DMI_BIOS_DATE], '/'); 
-		if (s) { 
-			int year, disable = 0;
-			s++; 
-			year = simple_strtoul(s,NULL,0); 
-			if (year >= 1000) 
-				disable = year < ACPI_BLACKLIST_CUTOFF_YEAR; 
-			else if (year < 1 || (year > 90 && year <= 99))
-				disable = 1; 
-			if (disable && !acpi_force) { 
-				printk(KERN_NOTICE "ACPI disabled because your bios is from %s and too old\n", s);
-				printk(KERN_NOTICE "You can enable it with acpi=force\n");
-				disable_acpi();
-			} 
-		}
-	}
-#endif
- 	dmi_check_system(dmi_blacklist);
-}
-
-	
 
 /*
  *	Process a DMI table entry. Right now all we care about are the BIOS
@@ -582,7 +500,7 @@
 {
 	int err = dmi_iterate(dmi_decode);
 	if(err == 0)
-		dmi_check_blacklist();
+ 		dmi_check_system(dmi_blacklist);
 	else
 		printk(KERN_INFO "DMI not present.\n");
 }
diff -Nru a/arch/i386/kernel/doublefault.c b/arch/i386/kernel/doublefault.c
--- a/arch/i386/kernel/doublefault.c	2004-10-18 14:55:55 -07:00
+++ b/arch/i386/kernel/doublefault.c	2004-10-18 14:55:55 -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/entry.S b/arch/i386/kernel/entry.S
--- a/arch/i386/kernel/entry.S	2004-10-18 14:56:27 -07:00
+++ b/arch/i386/kernel/entry.S	2004-10-18 14:56:27 -07:00
@@ -255,11 +255,11 @@
 	pushl %eax
 	SAVE_ALL
 	GET_THREAD_INFO(%ebp)
-	cmpl $(nr_syscalls), %eax
-	jae syscall_badsys
 
 	testb $(_TIF_SYSCALL_TRACE|_TIF_SYSCALL_AUDIT),TI_flags(%ebp)
 	jnz syscall_trace_entry
+	cmpl $(nr_syscalls), %eax
+	jae syscall_badsys
 	call *sys_call_table(,%eax,4)
 	movl %eax,EAX(%esp)
 	cli
@@ -278,11 +278,11 @@
 	pushl %eax			# save orig_eax
 	SAVE_ALL
 	GET_THREAD_INFO(%ebp)
-	cmpl $(nr_syscalls), %eax
-	jae syscall_badsys
 					# system call tracing in operation
 	testb $(_TIF_SYSCALL_TRACE|_TIF_SYSCALL_AUDIT),TI_flags(%ebp)
 	jnz syscall_trace_entry
+	cmpl $(nr_syscalls), %eax
+	jae syscall_badsys
 syscall_call:
 	call *sys_call_table(,%eax,4)
 	movl %eax,EAX(%esp)		# store the return value
@@ -348,7 +348,7 @@
 	# perform syscall exit tracing
 	ALIGN
 syscall_exit_work:
-	testb $(_TIF_SYSCALL_TRACE|_TIF_SYSCALL_AUDIT), %cl
+	testb $(_TIF_SYSCALL_TRACE|_TIF_SYSCALL_AUDIT|_TIF_SINGLESTEP), %cl
 	jz work_pending
 	sti				# could let do_syscall_trace() call
 					# schedule() instead
@@ -489,9 +489,16 @@
 	jne debug_stack_correct
 	FIX_STACK(12, debug_stack_correct, debug_esp_fix_insn)
 debug_stack_correct:
-	pushl $0
-	pushl $do_debug
-	jmp error_code
+	pushl $-1			# mark this as an int
+	SAVE_ALL
+	movl %esp,%edx
+  	pushl $0
+	pushl %edx
+	call do_debug
+	addl $8,%esp
+	testl %eax,%eax
+	jnz restore_all
+	jmp ret_from_exception
 
 /*
  * NMI is doubly nasty. It can happen _while_ we're handling
@@ -540,9 +547,16 @@
 	jmp nmi_stack_correct
 
 ENTRY(int3)
+	pushl $-1			# mark this as an int
+	SAVE_ALL
+	movl %esp,%edx
 	pushl $0
-	pushl $do_int3
-	jmp error_code
+	pushl %edx
+	call do_int3
+	addl $8,%esp
+	testl %eax,%eax
+	jnz restore_all
+	jmp ret_from_exception
 
 ENTRY(overflow)
 	pushl $0
@@ -886,5 +900,6 @@
 	.long sys_mq_notify
 	.long sys_mq_getsetattr
 	.long sys_ni_syscall		/* reserved for kexec */
+	.long sys_waitid
 
 syscall_table_size=(.-sys_call_table)
diff -Nru a/arch/i386/kernel/head.S b/arch/i386/kernel/head.S
--- a/arch/i386/kernel/head.S	2004-10-18 14:55:54 -07:00
+++ b/arch/i386/kernel/head.S	2004-10-18 14:55:54 -07:00
@@ -521,6 +521,3 @@
 	.quad 0x0000000000000000	/* 0xf0 - unused */
 	.quad 0x0000000000000000	/* 0xf8 - GDT entry 31: double-fault TSS */
 
-#ifdef CONFIG_SMP
-	.fill (NR_CPUS-1)*GDT_ENTRIES,8,0 /* other CPU's GDT */
-#endif
diff -Nru a/arch/i386/kernel/i386_ksyms.c b/arch/i386/kernel/i386_ksyms.c
--- a/arch/i386/kernel/i386_ksyms.c	2004-10-18 14:57:04 -07:00
+++ b/arch/i386/kernel/i386_ksyms.c	2004-10-18 14:57:04 -07:00
@@ -23,7 +23,6 @@
 #include <asm/uaccess.h>
 #include <asm/checksum.h>
 #include <asm/io.h>
-#include <asm/hardirq.h>
 #include <asm/delay.h>
 #include <asm/irq.h>
 #include <asm/mmx.h>
@@ -32,6 +31,7 @@
 #include <asm/tlbflush.h>
 #include <asm/nmi.h>
 #include <asm/ist.h>
+#include <asm/kdebug.h>
 
 extern void dump_thread(struct pt_regs *, struct user *);
 extern spinlock_t rtc_lock;
@@ -87,10 +87,10 @@
 EXPORT_SYMBOL(cpu_khz);
 EXPORT_SYMBOL(apm_info);
 
-EXPORT_SYMBOL_NOVERS(__down_failed);
-EXPORT_SYMBOL_NOVERS(__down_failed_interruptible);
-EXPORT_SYMBOL_NOVERS(__down_failed_trylock);
-EXPORT_SYMBOL_NOVERS(__up_wakeup);
+EXPORT_SYMBOL(__down_failed);
+EXPORT_SYMBOL(__down_failed_interruptible);
+EXPORT_SYMBOL(__down_failed_trylock);
+EXPORT_SYMBOL(__up_wakeup);
 /* Networking helper routines. */
 EXPORT_SYMBOL(csum_partial_copy_generic);
 /* Delay loops */
@@ -99,9 +99,9 @@
 EXPORT_SYMBOL(__delay);
 EXPORT_SYMBOL(__const_udelay);
 
-EXPORT_SYMBOL_NOVERS(__get_user_1);
-EXPORT_SYMBOL_NOVERS(__get_user_2);
-EXPORT_SYMBOL_NOVERS(__get_user_4);
+EXPORT_SYMBOL(__get_user_1);
+EXPORT_SYMBOL(__get_user_2);
+EXPORT_SYMBOL(__get_user_4);
 
 EXPORT_SYMBOL(strpbrk);
 EXPORT_SYMBOL(strstr);
@@ -142,8 +142,8 @@
 EXPORT_SYMBOL(cpu_data);
 EXPORT_SYMBOL(cpu_online_map);
 EXPORT_SYMBOL(cpu_callout_map);
-EXPORT_SYMBOL_NOVERS(__write_lock_failed);
-EXPORT_SYMBOL_NOVERS(__read_lock_failed);
+EXPORT_SYMBOL(__write_lock_failed);
+EXPORT_SYMBOL(__read_lock_failed);
 
 /* Global SMP stuff */
 EXPORT_SYMBOL(synchronize_irq);
@@ -175,8 +175,9 @@
 
 #undef memcmp
 extern int memcmp(const void *,const void *,__kernel_size_t);
-EXPORT_SYMBOL_NOVERS(memcmp);
+EXPORT_SYMBOL(memcmp);
 
+EXPORT_SYMBOL(register_die_notifier);
 #ifdef CONFIG_HAVE_DEC_LOCK
 EXPORT_SYMBOL(atomic_dec_and_lock);
 #endif
diff -Nru a/arch/i386/kernel/i8259.c b/arch/i386/kernel/i8259.c
--- a/arch/i386/kernel/i8259.c	2004-10-18 14:57:03 -07:00
+++ b/arch/i386/kernel/i8259.c	2004-10-18 14:57:03 -07:00
@@ -4,7 +4,6 @@
 #include <linux/sched.h>
 #include <linux/ioport.h>
 #include <linux/interrupt.h>
-#include <linux/timex.h>
 #include <linux/slab.h>
 #include <linux/random.h>
 #include <linux/smp_lock.h>
@@ -12,10 +11,12 @@
 #include <linux/kernel_stat.h>
 #include <linux/sysdev.h>
 
+#include <asm/8253pit.h>
 #include <asm/atomic.h>
 #include <asm/system.h>
 #include <asm/io.h>
 #include <asm/irq.h>
+#include <asm/timer.h>
 #include <asm/bitops.h>
 #include <asm/pgtable.h>
 #include <asm/delay.h>
@@ -225,7 +226,7 @@
 		 * lets ACK and report it. [once per IRQ]
 		 */
 		if (!(spurious_irq_mask & irqmask)) {
-			printk("spurious 8259A interrupt: IRQ%d.\n", irq);
+			printk(KERN_DEBUG "spurious 8259A interrupt: IRQ%d.\n", irq);
 			spurious_irq_mask |= irqmask;
 		}
 		atomic_inc(&irq_err_count);
@@ -238,14 +239,39 @@
 	}
 }
 
+static char irq_trigger[2];
+/**
+ * ELCR registers (0x4d0, 0x4d1) control edge/level of IRQ
+ */
+static void restore_ELCR(char *trigger)
+{
+	outb(trigger[0], 0x4d0);
+	outb(trigger[1], 0x4d1);
+}
+
+static void save_ELCR(char *trigger)
+{
+	/* IRQ 0,1,2,8,13 are marked as reserved */
+	trigger[0] = inb(0x4d0) & 0xF8;
+	trigger[1] = inb(0x4d1) & 0xDE;
+}
+
 static int i8259A_resume(struct sys_device *dev)
 {
 	init_8259A(0);
+	restore_ELCR(irq_trigger);
+	return 0;
+}
+
+static int i8259A_suspend(struct sys_device *dev, u32 state)
+{
+	save_ELCR(irq_trigger);
 	return 0;
 }
 
 static struct sysdev_class i8259_sysdev_class = {
 	set_kset_name("i8259"),
+	.suspend = i8259A_suspend,
 	.resume = i8259A_resume,
 };
 
@@ -362,46 +388,6 @@
 	}
 }
 
-static void setup_timer(void)
-{
-	extern spinlock_t i8253_lock;
-	unsigned long flags;
-
-	spin_lock_irqsave(&i8253_lock, flags);
-	outb_p(0x34,PIT_MODE);		/* binary, mode 2, LSB/MSB, ch 0 */
-	udelay(10);
-	outb_p(LATCH & 0xff , PIT_CH0);	/* LSB */
-	udelay(10);
-	outb(LATCH >> 8 , PIT_CH0);	/* MSB */
-	spin_unlock_irqrestore(&i8253_lock, flags);
-}
-
-static int timer_resume(struct sys_device *dev)
-{
-	setup_timer();
-	return 0;
-}
-
-static struct sysdev_class timer_sysclass = {
-	set_kset_name("timer"),
-	.resume	= timer_resume,
-};
-
-static struct sys_device device_timer = {
-	.id	= 0,
-	.cls	= &timer_sysclass,
-};
-
-static int __init init_timer_sysfs(void)
-{
-	int error = sysdev_class_register(&timer_sysclass);
-	if (!error)
-		error = sysdev_register(&device_timer);
-	return error;
-}
-
-device_initcall(init_timer_sysfs);
-
 void __init init_IRQ(void)
 {
 	int i;
@@ -431,7 +417,7 @@
 	 * Set the clock to HZ Hz, we already have a valid
 	 * vector now:
 	 */
-	setup_timer();
+	setup_pit_timer();
 
 	/*
 	 * External FPU? Set up irq13 if so, for
diff -Nru a/arch/i386/kernel/init_task.c b/arch/i386/kernel/init_task.c
--- a/arch/i386/kernel/init_task.c	2004-10-18 14:57:04 -07:00
+++ b/arch/i386/kernel/init_task.c	2004-10-18 14:57:04 -07:00
@@ -40,10 +40,7 @@
 
 /*
  * per-CPU TSS segments. Threads are completely 'soft' on Linux,
- * no more per-task TSS's. The TSS size is kept cacheline-aligned
- * so they are allowed to end up in the .data.cacheline_aligned
- * section. Since TSS's are completely CPU-local, we want them
- * on exact cacheline boundaries, to eliminate cacheline ping-pong.
+ * no more per-task TSS's.
  */ 
-struct tss_struct init_tss[NR_CPUS] __cacheline_aligned = { [0 ... NR_CPUS-1] = INIT_TSS };
+DEFINE_PER_CPU(struct tss_struct, init_tss) ____cacheline_maxaligned_in_smp = INIT_TSS;
 
diff -Nru a/arch/i386/kernel/io_apic.c b/arch/i386/kernel/io_apic.c
--- a/arch/i386/kernel/io_apic.c	2004-10-18 14:56:28 -07:00
+++ b/arch/i386/kernel/io_apic.c	2004-10-18 14:56:28 -07:00
@@ -32,6 +32,7 @@
 #include <linux/compiler.h>
 #include <linux/acpi.h>
 
+#include <linux/sysdev.h>
 #include <asm/io.h>
 #include <asm/smp.h>
 #include <asm/desc.h>
@@ -85,7 +86,7 @@
  * shared ISA-space IRQs, so we have to support them. We are super
  * fast in the common case, and fast for shared ISA-space IRQs.
  */
-static void __init add_pin_to_irq(unsigned int irq, int apic, int pin)
+static void add_pin_to_irq(unsigned int irq, int apic, int pin)
 {
 	static int first_free_entry = NR_IRQS;
 	struct irq_pin_list *entry = irq_2_pin + irq;
@@ -705,13 +706,15 @@
 		pirq_entries[i] = -1;
 
 	pirqs_enabled = 1;
-	printk(KERN_INFO "PIRQ redirection, working around broken MP-BIOS.\n");
+	apic_printk(APIC_VERBOSE, KERN_INFO
+			"PIRQ redirection, working around broken MP-BIOS.\n");
 	max = MAX_PIRQS;
 	if (ints[0] < MAX_PIRQS)
 		max = ints[0];
 
 	for (i = 0; i < max; i++) {
-		printk(KERN_DEBUG "... PIRQ%d -> IRQ %d\n", i, ints[i+1]);
+		apic_printk(APIC_VERBOSE, KERN_DEBUG
+				"... PIRQ%d -> IRQ %d\n", i, ints[i+1]);
 		/*
 		 * PIRQs are mapped upside down, usually.
 		 */
@@ -742,7 +745,7 @@
 /*
  * Find the pin to which IRQ[irq] (ISA) is connected
  */
-static int __init find_isa_irq_pin(int irq, int type)
+static int find_isa_irq_pin(int irq, int type)
 {
 	int i;
 
@@ -772,8 +775,8 @@
 {
 	int apic, i, best_guess = -1;
 
-	Dprintk("querying PCI -> IRQ mapping bus:%d, slot:%d, pin:%d.\n",
-		bus, slot, pin);
+	apic_printk(APIC_DEBUG, "querying PCI -> IRQ mapping bus:%d, "
+		"slot:%d, pin:%d.\n", bus, slot, pin);
 	if (mp_bus_id_to_pci_bus[bus] == -1) {
 		printk(KERN_WARNING "PCI BIOS passed nonexistent PCI bus %d!\n", bus);
 		return -1;
@@ -841,7 +844,8 @@
 		unsigned int port = 0x4d0 + (irq >> 3);
 		return (inb(port) >> (irq & 7)) & 1;
 	}
-	printk(KERN_INFO "Broken MPtable reports ISA irq %d\n", irq);
+	apic_printk(APIC_VERBOSE, KERN_INFO
+			"Broken MPtable reports ISA irq %d\n", irq);
 	return 0;
 }
 
@@ -1083,10 +1087,12 @@
 	if ((pin >= 16) && (pin <= 23)) {
 		if (pirq_entries[pin-16] != -1) {
 			if (!pirq_entries[pin-16]) {
-				printk(KERN_DEBUG "disabling PIRQ%d\n", pin-16);
+				apic_printk(APIC_VERBOSE, KERN_DEBUG
+						"disabling PIRQ%d\n", pin-16);
 			} else {
 				irq = pirq_entries[pin-16];
-				printk(KERN_DEBUG "using PIRQ%d -> IRQ %d\n",
+				apic_printk(APIC_VERBOSE, KERN_DEBUG
+						"using PIRQ%d -> IRQ %d\n",
 						pin-16, irq);
 			}
 		}
@@ -1114,11 +1120,7 @@
 /* irq_vectors is indexed by the sum of all RTEs in all I/O APICs. */
 u8 irq_vector[NR_IRQ_VECTORS] = { FIRST_DEVICE_VECTOR , 0 };
 
-#ifdef CONFIG_PCI_MSI
 int assign_irq_vector(int irq)
-#else
-int __init assign_irq_vector(int irq)
-#endif
 {
 	static int current_vector = FIRST_DEVICE_VECTOR, offset = 0;
 
@@ -1176,7 +1178,7 @@
 	int apic, pin, idx, irq, first_notcon = 1, vector;
 	unsigned long flags;
 
-	printk(KERN_DEBUG "init IO_APIC IRQs\n");
+	apic_printk(APIC_VERBOSE, KERN_DEBUG "init IO_APIC IRQs\n");
 
 	for (apic = 0; apic < nr_ioapics; apic++) {
 	for (pin = 0; pin < nr_ioapic_registers[apic]; pin++) {
@@ -1195,10 +1197,14 @@
 		idx = find_irq_entry(apic,pin,mp_INT);
 		if (idx == -1) {
 			if (first_notcon) {
-				printk(KERN_DEBUG " IO-APIC (apicid-pin) %d-%d", mp_ioapics[apic].mpc_apicid, pin);
+				apic_printk(APIC_VERBOSE, KERN_DEBUG
+						" IO-APIC (apicid-pin) %d-%d",
+						mp_ioapics[apic].mpc_apicid,
+						pin);
 				first_notcon = 0;
 			} else
-				printk(", %d-%d", mp_ioapics[apic].mpc_apicid, pin);
+				apic_printk(APIC_VERBOSE, ", %d-%d",
+					mp_ioapics[apic].mpc_apicid, pin);
 			continue;
 		}
 
@@ -1239,7 +1245,7 @@
 	}
 
 	if (!first_notcon)
-		printk(" not connected.\n");
+		apic_printk(APIC_VERBOSE, " not connected.\n");
 }
 
 /*
@@ -1299,6 +1305,9 @@
 	union IO_APIC_reg_03 reg_03;
 	unsigned long flags;
 
+	if (apic_verbosity == APIC_QUIET)
+		return;
+
  	printk(KERN_DEBUG "number of MP IRQ sources: %d.\n", mp_irq_entries);
 	for (i = 0; i < nr_ioapics; i++)
 		printk(KERN_DEBUG "number of IO-APIC #%d registers: %d.\n",
@@ -1441,6 +1450,9 @@
 	unsigned int v;
 	int i, j;
 
+	if (apic_verbosity == APIC_QUIET)
+		return;
+
 	printk(KERN_DEBUG "0123456789abcdef0123456789abcdef\n" KERN_DEBUG);
 	for (i = 0; i < 8; i++) {
 		v = apic_read(base + i*0x10);
@@ -1458,6 +1470,9 @@
 {
 	unsigned int v, ver, maxlvt;
 
+	if (apic_verbosity == APIC_QUIET)
+		return;
+
 	printk("\n" KERN_DEBUG "printing local APIC contents on CPU#%d/%d:\n",
 		smp_processor_id(), hard_smp_processor_id());
 	v = apic_read(APIC_ID);
@@ -1545,6 +1560,9 @@
 	unsigned int v;
 	unsigned long flags;
 
+	if (apic_verbosity == APIC_QUIET)
+		return;
+
 	printk(KERN_DEBUG "\nprinting PIC contents\n");
 
 	spin_lock_irqsave(&i8259A_lock, flags);
@@ -1680,7 +1698,9 @@
 		} else {
 			physid_mask_t tmp;
 			tmp = apicid_to_cpu_present(mp_ioapics[apic].mpc_apicid);
-			printk("Setting %d in the phys_id_present_map\n", mp_ioapics[apic].mpc_apicid);
+			apic_printk(APIC_VERBOSE, "Setting %d in the "
+					"phys_id_present_map\n",
+					mp_ioapics[apic].mpc_apicid);
 			physids_or(phys_id_present_map, phys_id_present_map, tmp);
 		}
 
@@ -1699,8 +1719,9 @@
 		 * Read the right value from the MPC table and
 		 * write it into the ID register.
 	 	 */
-		printk(KERN_INFO "...changing IO-APIC physical APIC ID to %d ...",
-					mp_ioapics[apic].mpc_apicid);
+		apic_printk(APIC_VERBOSE, KERN_INFO
+			"...changing IO-APIC physical APIC ID to %d ...",
+			mp_ioapics[apic].mpc_apicid);
 
 		reg_00.bits.ID = mp_ioapics[apic].mpc_apicid;
 		spin_lock_irqsave(&ioapic_lock, flags);
@@ -1714,9 +1735,9 @@
 		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
-			printk(" ok.\n");
+			apic_printk(APIC_VERBOSE, " ok.\n");
 	}
 }
 #else
@@ -2031,11 +2052,11 @@
 	 * is from Maciej W. Rozycki - so we do not have to EOI from
 	 * the NMI handler or the timer interrupt.
 	 */ 
-	printk(KERN_INFO "activating NMI Watchdog ...");
+	apic_printk(APIC_VERBOSE, KERN_INFO "activating NMI Watchdog ...");
 
 	on_each_cpu(enable_NMI_through_LVT0, NULL, 1, 1);
 
-	printk(" done.\n");
+	apic_printk(APIC_VERBOSE, " done.\n");
 }
 
 /*
@@ -2212,7 +2233,8 @@
 		return;
 	}
 	printk(" failed :(.\n");
-	panic("IO-APIC + timer doesn't work! Try using the 'noapic' kernel parameter\n");
+	panic("IO-APIC + timer doesn't work!  Boot with apic=debug and send a "
+		"report.  Then try booting with the 'noapic' option");
 }
 
 /*
@@ -2262,6 +2284,98 @@
 
 late_initcall(io_apic_bug_finalize);
 
+struct sysfs_ioapic_data {
+	struct sys_device dev;
+	struct IO_APIC_route_entry entry[0];
+};
+static struct sysfs_ioapic_data * mp_ioapic_data[MAX_IO_APICS];
+
+static int ioapic_suspend(struct sys_device *dev, u32 state)
+{
+	struct IO_APIC_route_entry *entry;
+	struct sysfs_ioapic_data *data;
+	unsigned long flags;
+	int i;
+	
+	data = container_of(dev, struct sysfs_ioapic_data, dev);
+	entry = data->entry;
+	spin_lock_irqsave(&ioapic_lock, flags);
+	for (i = 0; i < nr_ioapic_registers[dev->id]; i ++, entry ++ ) {
+		*(((int *)entry) + 1) = io_apic_read(dev->id, 0x11 + 2 * i);
+		*(((int *)entry) + 0) = io_apic_read(dev->id, 0x10 + 2 * i);
+	}
+	spin_unlock_irqrestore(&ioapic_lock, flags);
+
+	return 0;
+}
+
+static int ioapic_resume(struct sys_device *dev)
+{
+	struct IO_APIC_route_entry *entry;
+	struct sysfs_ioapic_data *data;
+	unsigned long flags;
+	union IO_APIC_reg_00 reg_00;
+	int i;
+	
+	data = container_of(dev, struct sysfs_ioapic_data, dev);
+	entry = data->entry;
+
+	spin_lock_irqsave(&ioapic_lock, flags);
+	reg_00.raw = io_apic_read(dev->id, 0);
+	if (reg_00.bits.ID != mp_ioapics[dev->id].mpc_apicid) {
+		reg_00.bits.ID = mp_ioapics[dev->id].mpc_apicid;
+		io_apic_write(dev->id, 0, reg_00.raw);
+	}
+	for (i = 0; i < nr_ioapic_registers[dev->id]; i ++, entry ++ ) {
+		io_apic_write(dev->id, 0x11+2*i, *(((int *)entry)+1));
+		io_apic_write(dev->id, 0x10+2*i, *(((int *)entry)+0));
+	}
+	spin_unlock_irqrestore(&ioapic_lock, flags);
+
+	return 0;
+}
+
+static struct sysdev_class ioapic_sysdev_class = {
+	set_kset_name("ioapic"),
+	.suspend = ioapic_suspend,
+	.resume = ioapic_resume,
+};
+
+static int __init ioapic_init_sysfs(void)
+{
+	struct sys_device * dev;
+	int i, size, error = 0;
+
+	error = sysdev_class_register(&ioapic_sysdev_class);
+	if (error)
+		return error;
+
+	for (i = 0; i < nr_ioapics; i++ ) {
+		size = sizeof(struct sys_device) + nr_ioapic_registers[i] 
+			* sizeof(struct IO_APIC_route_entry);
+		mp_ioapic_data[i] = kmalloc(size, GFP_KERNEL);
+		if (!mp_ioapic_data[i]) {
+			printk(KERN_ERR "Can't suspend/resume IOAPIC %d\n", i);
+			continue;
+		}
+		memset(mp_ioapic_data[i], 0, size);
+		dev = &mp_ioapic_data[i]->dev;
+		dev->id = i; 
+		dev->cls = &ioapic_sysdev_class;
+		error = sysdev_register(dev);
+		if (error) {
+			kfree(mp_ioapic_data[i]);
+			mp_ioapic_data[i] = NULL;
+			printk(KERN_ERR "Can't suspend/resume IOAPIC %d\n", i);
+			continue;
+		}
+	}
+
+	return 0;
+}
+
+device_initcall(ioapic_init_sysfs);
+
 /* --------------------------------------------------------------------------
                           ACPI-based IOAPIC Configuration
    -------------------------------------------------------------------------- */
@@ -2334,7 +2448,8 @@
 			panic("IOAPIC[%d]: Unable change apic_id!\n", ioapic);
 	}
 
-	printk(KERN_INFO "IOAPIC[%d]: Assigned apic_id %d\n", ioapic, apic_id);
+	apic_printk(APIC_VERBOSE, KERN_INFO
+			"IOAPIC[%d]: Assigned apic_id %d\n", ioapic, apic_id);
 
 	return apic_id;
 }
@@ -2400,19 +2515,12 @@
 
 	entry.vector = assign_irq_vector(irq);
 
-	Dprintk(KERN_DEBUG "IOAPIC[%d]: Set PCI routing entry (%d-%d -> 0x%x -> "
-		"IRQ %d Mode:%i Active:%i)\n", ioapic, 
-		mp_ioapics[ioapic].mpc_apicid, pin, entry.vector, irq, edge_level, active_high_low);
-
- 	if (use_pci_vector() && !platform_legacy_irq(irq))
-		irq = IO_APIC_VECTOR(irq);
-	if (edge_level) {
-		irq_desc[irq].handler = &ioapic_level_type;
-	} else {
-		irq_desc[irq].handler = &ioapic_edge_type;
-	}
+	apic_printk(APIC_DEBUG, KERN_DEBUG "IOAPIC[%d]: Set PCI routing entry "
+		"(%d-%d -> 0x%x -> IRQ %d Mode:%i Active:%i)\n", ioapic,
+		mp_ioapics[ioapic].mpc_apicid, pin, entry.vector, irq,
+		edge_level, active_high_low);
 
-	set_intr_gate(entry.vector, interrupt[irq]);
+	ioapic_register_intr(irq, entry.vector, edge_level);
 
 	if (!ioapic && (irq < 16))
 		disable_8259A_irq(irq);
diff -Nru a/arch/i386/kernel/ioport.c b/arch/i386/kernel/ioport.c
--- a/arch/i386/kernel/ioport.c	2004-10-18 14:56:29 -07:00
+++ b/arch/i386/kernel/ioport.c	2004-10-18 14:56:29 -07:00
@@ -56,6 +56,7 @@
  */
 asmlinkage long sys_ioperm(unsigned long from, unsigned long num, int turn_on)
 {
+	unsigned long i, max_long, bytes, bytes_updated;
 	struct thread_struct * t = &current->thread;
 	struct tss_struct * tss;
 	unsigned long *bitmap;
@@ -81,16 +82,37 @@
 
 	/*
 	 * do it in the per-thread copy and in the TSS ...
+	 *
+	 * Disable preemption via get_cpu() - we must not switch away
+	 * because the ->io_bitmap_max value must match the bitmap
+	 * contents:
 	 */
+	tss = &per_cpu(init_tss, get_cpu());
+
 	set_bitmap(t->io_bitmap_ptr, from, num, !turn_on);
-	tss = init_tss + get_cpu();
-	if (tss->io_bitmap_base == IO_BITMAP_OFFSET) { /* already active? */
-		set_bitmap(tss->io_bitmap, from, num, !turn_on);
-	} else {
-		memcpy(tss->io_bitmap, t->io_bitmap_ptr, IO_BITMAP_BYTES);
-		tss->io_bitmap_base = IO_BITMAP_OFFSET; /* Activate it in the TSS */
-	}
+
+	/*
+	 * Search for a (possibly new) maximum. This is simple and stupid,
+	 * to keep it obviously correct:
+	 */
+	max_long = 0;
+	for (i = 0; i < IO_BITMAP_LONGS; i++)
+		if (t->io_bitmap_ptr[i] != ~0UL)
+			max_long = i;
+
+	bytes = (max_long + 1) * sizeof(long);
+	bytes_updated = max(bytes, t->io_bitmap_max);
+
+	t->io_bitmap_max = bytes;
+
+	/*
+	 * Sets the lazy trigger so that the next I/O operation will
+	 * reload the correct bitmap.
+	 */
+	tss->io_bitmap_base = INVALID_IO_BITMAP_OFFSET_LAZY;
+
 	put_cpu();
+
 	return 0;
 }
 
diff -Nru a/arch/i386/kernel/irq.c b/arch/i386/kernel/irq.c
--- a/arch/i386/kernel/irq.c	2004-10-18 14:55:54 -07:00
+++ b/arch/i386/kernel/irq.c	2004-10-18 14:55:54 -07:00
@@ -220,14 +220,16 @@
 		struct pt_regs *regs, struct irqaction *action)
 {
 	int status = 1;	/* Force the "do bottom halves" bit */
-	int retval = 0;
+	int ret, retval = 0;
 
 	if (!(action->flags & SA_INTERRUPT))
 		local_irq_enable();
 
 	do {
-		status |= action->flags;
-		retval |= action->handler(irq, action->dev_id, regs);
+		ret = action->handler(irq, action->dev_id, regs);
+		if (ret == IRQ_HANDLED)
+			status |= action->flags;
+		retval |= ret;
 		action = action->next;
 	} while (action);
 	if (status & SA_SAMPLE_RANDOM)
@@ -1025,32 +1027,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 +1062,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/kprobes.c b/arch/i386/kernel/kprobes.c
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/arch/i386/kernel/kprobes.c	2004-10-18 14:57:23 -07:00
@@ -0,0 +1,349 @@
+/*
+ *  Kernel Probes (KProbes)
+ *  arch/i386/kernel/kprobes.c
+ *
+ * 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.
+ *
+ * Copyright (C) IBM Corporation, 2002, 2004
+ *
+ * 2002-Oct	Created by Vamsi Krishna S <vamsi_krishna@in.ibm.com> Kernel
+ *		Probes initial implementation ( includes contributions from
+ *		Rusty Russell).
+ * 2004-July	Suparna Bhattacharya <suparna@in.ibm.com> added jumper probes
+ *		interface to access function arguments.
+ */
+
+#include <linux/config.h>
+#include <linux/kprobes.h>
+#include <linux/ptrace.h>
+#include <linux/spinlock.h>
+#include <linux/preempt.h>
+#include <asm/kdebug.h>
+
+/* kprobe_status settings */
+#define KPROBE_HIT_ACTIVE	0x00000001
+#define KPROBE_HIT_SS		0x00000002
+
+static struct kprobe *current_kprobe;
+static unsigned long kprobe_status, kprobe_old_eflags, kprobe_saved_eflags;
+static struct pt_regs jprobe_saved_regs;
+static long *jprobe_saved_esp;
+/* copy of the kernel stack at the probe fire time */
+static kprobe_opcode_t jprobes_stack[MAX_STACK_SIZE];
+
+/*
+ * returns non-zero if opcode modifies the interrupt flag.
+ */
+static inline int is_IF_modifier(kprobe_opcode_t opcode)
+{
+	switch (opcode) {
+	case 0xfa:		/* cli */
+	case 0xfb:		/* sti */
+	case 0xcf:		/* iret/iretd */
+	case 0x9d:		/* popf/popfd */
+		return 1;
+	}
+	return 0;
+}
+
+void arch_prepare_kprobe(struct kprobe *p)
+{
+	memcpy(p->insn, p->addr, MAX_INSN_SIZE * sizeof(kprobe_opcode_t));
+}
+
+static inline void disarm_kprobe(struct kprobe *p, struct pt_regs *regs)
+{
+	*p->addr = p->opcode;
+	regs->eip = (unsigned long)p->addr;
+}
+
+static inline void prepare_singlestep(struct kprobe *p, struct pt_regs *regs)
+{
+	regs->eflags |= TF_MASK;
+	regs->eflags &= ~IF_MASK;
+	regs->eip = (unsigned long)&p->insn;
+}
+
+/*
+ * Interrupts are disabled on entry as trap3 is an interrupt gate and they
+ * remain disabled thorough out this function.
+ */
+static inline int kprobe_handler(struct pt_regs *regs)
+{
+	struct kprobe *p;
+	int ret = 0;
+	u8 *addr = (u8 *) (regs->eip - 1);
+
+	/* We're in an interrupt, but this is clear and BUG()-safe. */
+	preempt_disable();
+
+	/* Check we're not actually recursing */
+	if (kprobe_running()) {
+		/* We *are* holding lock here, so this is safe.
+		   Disarm the probe we just hit, and ignore it. */
+		p = get_kprobe(addr);
+		if (p) {
+			disarm_kprobe(p, regs);
+			ret = 1;
+		} else {
+			p = current_kprobe;
+			if (p->break_handler && p->break_handler(p, regs)) {
+				goto ss_probe;
+			}
+		}
+		/* If it's not ours, can't be delete race, (we hold lock). */
+		goto no_kprobe;
+	}
+
+	lock_kprobes();
+	p = get_kprobe(addr);
+	if (!p) {
+		unlock_kprobes();
+		if (*addr != BREAKPOINT_INSTRUCTION) {
+			/*
+			 * The breakpoint instruction was removed right
+			 * after we hit it.  Another cpu has removed
+			 * either a probepoint or a debugger breakpoint
+			 * at this address.  In either case, no further
+			 * handling of this interrupt is appropriate.
+			 */
+			ret = 1;
+		}
+		/* Not one of ours: let kernel handle it */
+		goto no_kprobe;
+	}
+
+	kprobe_status = KPROBE_HIT_ACTIVE;
+	current_kprobe = p;
+	kprobe_saved_eflags = kprobe_old_eflags
+	    = (regs->eflags & (TF_MASK | IF_MASK));
+	if (is_IF_modifier(p->opcode))
+		kprobe_saved_eflags &= ~IF_MASK;
+
+	if (p->pre_handler(p, regs)) {
+		/* handler has already set things up, so skip ss setup */
+		return 1;
+	}
+
+      ss_probe:
+	prepare_singlestep(p, regs);
+	kprobe_status = KPROBE_HIT_SS;
+	return 1;
+
+      no_kprobe:
+	preempt_enable_no_resched();
+	return ret;
+}
+
+/*
+ * Called after single-stepping.  p->addr is the address of the
+ * instruction whose first byte has been replaced by the "int 3"
+ * instruction.  To avoid the SMP problems that can occur when we
+ * temporarily put back the original opcode to single-step, we
+ * single-stepped a copy of the instruction.  The address of this
+ * copy is p->insn.
+ *
+ * This function prepares to return from the post-single-step
+ * interrupt.  We have to fix up the stack as follows:
+ *
+ * 0) Except in the case of absolute or indirect jump or call instructions,
+ * the new eip is relative to the copied instruction.  We need to make
+ * it relative to the original instruction.
+ *
+ * 1) If the single-stepped instruction was pushfl, then the TF and IF
+ * flags are set in the just-pushed eflags, and may need to be cleared.
+ *
+ * 2) If the single-stepped instruction was a call, the return address
+ * that is atop the stack is the address following the copied instruction.
+ * We need to make it the address following the original instruction.
+ */
+static void resume_execution(struct kprobe *p, struct pt_regs *regs)
+{
+	unsigned long *tos = (unsigned long *)&regs->esp;
+	unsigned long next_eip = 0;
+	unsigned long copy_eip = (unsigned long)&p->insn;
+	unsigned long orig_eip = (unsigned long)p->addr;
+
+	switch (p->insn[0]) {
+	case 0x9c:		/* pushfl */
+		*tos &= ~(TF_MASK | IF_MASK);
+		*tos |= kprobe_old_eflags;
+		break;
+	case 0xe8:		/* call relative - Fix return addr */
+		*tos = orig_eip + (*tos - copy_eip);
+		break;
+	case 0xff:
+		if ((p->insn[1] & 0x30) == 0x10) {
+			/* call absolute, indirect */
+			/* Fix return addr; eip is correct. */
+			next_eip = regs->eip;
+			*tos = orig_eip + (*tos - copy_eip);
+		} else if (((p->insn[1] & 0x31) == 0x20) ||	/* jmp near, absolute indirect */
+			   ((p->insn[1] & 0x31) == 0x21)) {	/* jmp far, absolute indirect */
+			/* eip is correct. */
+			next_eip = regs->eip;
+		}
+		break;
+	case 0xea:		/* jmp absolute -- eip is correct */
+		next_eip = regs->eip;
+		break;
+	default:
+		break;
+	}
+
+	regs->eflags &= ~TF_MASK;
+	if (next_eip) {
+		regs->eip = next_eip;
+	} else {
+		regs->eip = orig_eip + (regs->eip - copy_eip);
+	}
+}
+
+/*
+ * Interrupts are disabled on entry as trap1 is an interrupt gate and they
+ * remain disabled thoroughout this function.  And we hold kprobe lock.
+ */
+static inline int post_kprobe_handler(struct pt_regs *regs)
+{
+	if (!kprobe_running())
+		return 0;
+
+	if (current_kprobe->post_handler)
+		current_kprobe->post_handler(current_kprobe, regs, 0);
+
+	resume_execution(current_kprobe, regs);
+	regs->eflags |= kprobe_saved_eflags;
+
+	unlock_kprobes();
+	preempt_enable_no_resched();
+
+	/*
+	 * if somebody else is singlestepping across a probe point, eflags
+	 * will have TF set, in which case, continue the remaining processing
+	 * of do_debug, as if this is not a probe hit.
+	 */
+	if (regs->eflags & TF_MASK)
+		return 0;
+
+	return 1;
+}
+
+/* Interrupts disabled, kprobe_lock held. */
+static inline int kprobe_fault_handler(struct pt_regs *regs, int trapnr)
+{
+	if (current_kprobe->fault_handler
+	    && current_kprobe->fault_handler(current_kprobe, regs, trapnr))
+		return 1;
+
+	if (kprobe_status & KPROBE_HIT_SS) {
+		resume_execution(current_kprobe, regs);
+		regs->eflags |= kprobe_old_eflags;
+
+		unlock_kprobes();
+		preempt_enable_no_resched();
+	}
+	return 0;
+}
+
+/*
+ * Wrapper routine to for handling exceptions.
+ */
+int kprobe_exceptions_notify(struct notifier_block *self, unsigned long val,
+			     void *data)
+{
+	struct die_args *args = (struct die_args *)data;
+	switch (val) {
+	case DIE_INT3:
+		if (kprobe_handler(args->regs))
+			return NOTIFY_STOP;
+		break;
+	case DIE_DEBUG:
+		if (post_kprobe_handler(args->regs))
+			return NOTIFY_STOP;
+		break;
+	case DIE_GPF:
+		if (kprobe_running() &&
+		    kprobe_fault_handler(args->regs, args->trapnr))
+			return NOTIFY_STOP;
+		break;
+	case DIE_PAGE_FAULT:
+		if (kprobe_running() &&
+		    kprobe_fault_handler(args->regs, args->trapnr))
+			return NOTIFY_STOP;
+		break;
+	default:
+		break;
+	}
+	return NOTIFY_DONE;
+}
+
+int setjmp_pre_handler(struct kprobe *p, struct pt_regs *regs)
+{
+	struct jprobe *jp = container_of(p, struct jprobe, kp);
+	unsigned long addr;
+
+	jprobe_saved_regs = *regs;
+	jprobe_saved_esp = &regs->esp;
+	addr = (unsigned long)jprobe_saved_esp;
+
+	/*
+	 * TBD: As Linus pointed out, gcc assumes that the callee
+	 * owns the argument space and could overwrite it, e.g.
+	 * tailcall optimization. So, to be absolutely safe
+	 * we also save and restore enough stack bytes to cover
+	 * the argument area.
+	 */
+	memcpy(jprobes_stack, (kprobe_opcode_t *) addr, MIN_STACK_SIZE(addr));
+	regs->eflags &= ~IF_MASK;
+	regs->eip = (unsigned long)(jp->entry);
+	return 1;
+}
+
+void jprobe_return(void)
+{
+	preempt_enable_no_resched();
+	asm volatile ("       xchgl   %%ebx,%%esp     \n"
+		      "       int3			\n"::"b"
+		      (jprobe_saved_esp):"memory");
+}
+void jprobe_return_end(void)
+{
+};
+
+int longjmp_break_handler(struct kprobe *p, struct pt_regs *regs)
+{
+	u8 *addr = (u8 *) (regs->eip - 1);
+	unsigned long stack_addr = (unsigned long)jprobe_saved_esp;
+	struct jprobe *jp = container_of(p, struct jprobe, kp);
+
+	if ((addr > (u8 *) jprobe_return) && (addr < (u8 *) jprobe_return_end)) {
+		if (&regs->esp != jprobe_saved_esp) {
+			struct pt_regs *saved_regs =
+			    container_of(jprobe_saved_esp, struct pt_regs, esp);
+			printk("current esp %p does not match saved esp %p\n",
+			       &regs->esp, jprobe_saved_esp);
+			printk("Saved registers for jprobe %p\n", jp);
+			show_registers(saved_regs);
+			printk("Current registers\n");
+			show_registers(regs);
+			BUG();
+		}
+		*regs = jprobe_saved_regs;
+		memcpy((kprobe_opcode_t *) stack_addr, jprobes_stack,
+		       MIN_STACK_SIZE(stack_addr));
+		return 1;
+	}
+	return 0;
+}
diff -Nru a/arch/i386/kernel/ldt.c b/arch/i386/kernel/ldt.c
--- a/arch/i386/kernel/ldt.c	2004-10-18 14:56:48 -07:00
+++ b/arch/i386/kernel/ldt.c	2004-10-18 14:56:48 -07:00
@@ -142,12 +142,17 @@
 		err = -EFAULT;
 	up(&mm->context.sem);
 	if (err < 0)
-		return err;
+		goto error_return;
 	if (size != bytecount) {
 		/* zero-fill the rest */
-		clear_user(ptr+size, bytecount-size);
+		if (clear_user(ptr+size, bytecount-size) != 0) {
+			err = -EFAULT;
+			goto error_return;
+		}
 	}
 	return bytecount;
+error_return:
+	return err;
 }
 
 static int read_default_ldt(void __user * ptr, unsigned long bytecount)
diff -Nru a/arch/i386/kernel/microcode.c b/arch/i386/kernel/microcode.c
--- a/arch/i386/kernel/microcode.c	2004-10-18 14:56:19 -07:00
+++ b/arch/i386/kernel/microcode.c	2004-10-18 14:56:19 -07:00
@@ -485,6 +485,7 @@
 static struct miscdevice microcode_dev = {
 	.minor		= MICROCODE_MINOR,
 	.name		= "microcode",
+	.devfs_name	= "cpu/microcode",
 	.fops		= &microcode_fops,
 };
 
diff -Nru a/arch/i386/kernel/nmi.c b/arch/i386/kernel/nmi.c
--- a/arch/i386/kernel/nmi.c	2004-10-18 14:56:32 -07:00
+++ b/arch/i386/kernel/nmi.c	2004-10-18 14:56:32 -07:00
@@ -25,13 +25,17 @@
 #include <linux/module.h>
 #include <linux/nmi.h>
 #include <linux/sysdev.h>
+#include <linux/sysctl.h>
 
 #include <asm/smp.h>
 #include <asm/mtrr.h>
 #include <asm/mpspec.h>
 #include <asm/nmi.h>
 
+#include "mach_traps.h"
+
 unsigned int nmi_watchdog = NMI_NONE;
+extern int unknown_nmi_panic;
 static unsigned int nmi_hz = HZ;
 static unsigned int nmi_perfctr_msr;	/* the MSR to reset in NMI handler */
 static unsigned int nmi_p4_cccr_val;
@@ -376,7 +380,13 @@
 		clear_msr_range(0x3F1, 2);
 	/* MSR 0x3F0 seems to have a default value of 0xFC00, but current
 	   docs doesn't fully define it, so leave it alone for now. */
-	clear_msr_range(0x3A0, 31);
+	if (boot_cpu_data.x86_model >= 0x3) {
+		/* MSR_P4_IQ_ESCR0/1 (0x3ba/0x3bb) removed */
+		clear_msr_range(0x3A0, 26);
+		clear_msr_range(0x3BC, 3);
+	} else {
+		clear_msr_range(0x3A0, 31);
+	}
 	clear_msr_range(0x3C0, 6);
 	clear_msr_range(0x3C8, 6);
 	clear_msr_range(0x3E0, 2);
@@ -426,8 +436,6 @@
 	nmi_active = 1;
 }
 
-static spinlock_t nmi_print_lock = SPIN_LOCK_UNLOCKED;
-
 /*
  * the best way to detect whether a CPU has a 'hard lockup' problem
  * is to check it's local APIC timer IRQ counts. If they are not
@@ -459,6 +467,8 @@
 		alert_counter[i] = 0;
 }
 
+extern void die_nmi(struct pt_regs *, const char *msg);
+
 void nmi_watchdog_tick (struct pt_regs * regs)
 {
 
@@ -477,21 +487,8 @@
 		 * wait a few IRQs (5 seconds) before doing the oops ...
 		 */
 		alert_counter[cpu]++;
-		if (alert_counter[cpu] == 5*nmi_hz) {
-			spin_lock(&nmi_print_lock);
-			/*
-			 * We are in trouble anyway, lets at least try
-			 * to get a message out.
-			 */
-			bust_spinlocks(1);
-			printk("NMI Watchdog detected LOCKUP on CPU%d, eip %08lx, registers:\n", cpu, regs->eip);
-			show_registers(regs);
-			printk("console shuts up ...\n");
-			console_silent();
-			spin_unlock(&nmi_print_lock);
-			bust_spinlocks(0);
-			do_exit(SIGSEGV);
-		}
+		if (alert_counter[cpu] == 5*nmi_hz)
+			die_nmi(regs, "NMI Watchdog detected LOCKUP");
 	} else {
 		last_irq_sums[cpu] = sum;
 		alert_counter[cpu] = 0;
@@ -517,6 +514,49 @@
 		wrmsr(nmi_perfctr_msr, -(cpu_khz/nmi_hz*1000), -1);
 	}
 }
+
+#ifdef CONFIG_SYSCTL
+
+static int unknown_nmi_panic_callback(struct pt_regs *regs, int cpu)
+{
+	unsigned char reason = get_nmi_reason();
+	char buf[64];
+
+	if (!(reason & 0xc0)) {
+		sprintf(buf, "NMI received for unknown reason %02x\n", reason);
+		die_nmi(regs, buf);
+	}
+	return 0;
+}
+
+/*
+ * proc handler for /proc/sys/kernel/unknown_nmi_panic
+ */
+int proc_unknown_nmi_panic(ctl_table *table, int write, struct file *file,
+			void __user *buffer, size_t *length, loff_t *ppos)
+{
+	int old_state;
+
+	old_state = unknown_nmi_panic;
+	proc_dointvec(table, write, file, buffer, length, ppos);
+	if (!!old_state == !!unknown_nmi_panic)
+		return 0;
+
+	if (unknown_nmi_panic) {
+		if (reserve_lapic_nmi() < 0) {
+			unknown_nmi_panic = 0;
+			return -EBUSY;
+		} else {
+			set_nmi_callback(unknown_nmi_panic_callback);
+		}
+	} else {
+		release_lapic_nmi();
+		unset_nmi_callback();
+	}
+	return 0;
+}
+
+#endif
 
 EXPORT_SYMBOL(nmi_active);
 EXPORT_SYMBOL(nmi_watchdog);
diff -Nru a/arch/i386/kernel/pci-dma.c b/arch/i386/kernel/pci-dma.c
--- a/arch/i386/kernel/pci-dma.c	2004-10-18 14:56:18 -07:00
+++ b/arch/i386/kernel/pci-dma.c	2004-10-18 14:56:18 -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 __iomem *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-10-18 14:55:46 -07:00
+++ b/arch/i386/kernel/process.c	2004-10-18 14:55:46 -07:00
@@ -142,13 +142,21 @@
 	/* endless idle loop with no priority at all */
 	while (1) {
 		while (!need_resched()) {
-			void (*idle)(void) = pm_idle;
+			void (*idle)(void);
+			/*
+			 * Mark this as an RCU critical section so that
+			 * synchronize_kernel() in the unload path waits
+			 * for our completion.
+			 */
+			rcu_read_lock();
+			idle = pm_idle;
 
 			if (!idle)
 				idle = default_idle;
 
 			irq_stat[smp_processor_id()].idle_timestamp = jiffies;
 			idle();
+			rcu_read_unlock();
 		}
 		schedule();
 	}
@@ -183,18 +191,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)
@@ -294,13 +297,22 @@
 void exit_thread(void)
 {
 	struct task_struct *tsk = current;
+	struct thread_struct *t = &tsk->thread;
 
 	/* The process may have allocated an io port bitmap... nuke it. */
-	if (unlikely(NULL != tsk->thread.io_bitmap_ptr)) {
+	if (unlikely(NULL != t->io_bitmap_ptr)) {
 		int cpu = get_cpu();
-		struct tss_struct *tss = init_tss + cpu;
-		kfree(tsk->thread.io_bitmap_ptr);
-		tsk->thread.io_bitmap_ptr = NULL;
+		struct tss_struct *tss = &per_cpu(init_tss, cpu);
+
+		kfree(t->io_bitmap_ptr);
+		t->io_bitmap_ptr = NULL;
+		/*
+		 * Careful, clear this in the TSS too:
+		 */
+		memset(tss->io_bitmap, 0xff, tss->io_bitmap_max);
+		t->io_bitmap_max = 0;
+		tss->io_bitmap_owner = NULL;
+		tss->io_bitmap_max = 0;
 		tss->io_bitmap_base = INVALID_IO_BITMAP_OFFSET;
 		put_cpu();
 	}
@@ -369,8 +381,10 @@
 	tsk = current;
 	if (unlikely(NULL != tsk->thread.io_bitmap_ptr)) {
 		p->thread.io_bitmap_ptr = kmalloc(IO_BITMAP_BYTES, GFP_KERNEL);
-		if (!p->thread.io_bitmap_ptr)
+		if (!p->thread.io_bitmap_ptr) {
+			p->thread.io_bitmap_max = 0;
 			return -ENOMEM;
+		}
 		memcpy(p->thread.io_bitmap_ptr, tsk->thread.io_bitmap_ptr,
 			IO_BITMAP_BYTES);
 	}
@@ -401,8 +415,10 @@
 
 	err = 0;
  out:
-	if (err && p->thread.io_bitmap_ptr)
+	if (err && p->thread.io_bitmap_ptr) {
 		kfree(p->thread.io_bitmap_ptr);
+		p->thread.io_bitmap_max = 0;
+	}
 	return err;
 }
 
@@ -467,6 +483,37 @@
 	return 1;
 }
 
+static inline void
+handle_io_bitmap(struct thread_struct *next, struct tss_struct *tss)
+{
+	if (!next->io_bitmap_ptr) {
+		/*
+		 * Disable the bitmap via an invalid offset. We still cache
+		 * the previous bitmap owner and the IO bitmap contents:
+		 */
+		tss->io_bitmap_base = INVALID_IO_BITMAP_OFFSET;
+		return;
+	}
+	if (likely(next == tss->io_bitmap_owner)) {
+		/*
+		 * Previous owner of the bitmap (hence the bitmap content)
+		 * matches the next task, we dont have to do anything but
+		 * to set a valid offset in the TSS:
+		 */
+		tss->io_bitmap_base = IO_BITMAP_OFFSET;
+		return;
+	}
+	/*
+	 * Lazy TSS's I/O bitmap copy. We set an invalid offset here
+	 * and we let the task to get a GPF in case an I/O instruction
+	 * is performed.  The handler of the GPF will verify that the
+	 * faulting task has a valid I/O bitmap and, it true, does the
+	 * real copy and restart the instruction.  This will save us
+	 * redundant copies when the currently switched task does not
+	 * perform any I/O during its timeslice.
+	 */
+	tss->io_bitmap_base = INVALID_IO_BITMAP_OFFSET_LAZY;
+}
 /*
  * This special macro can be used to load a debugging register
  */
@@ -507,7 +554,7 @@
 	struct thread_struct *prev = &prev_p->thread,
 				 *next = &next_p->thread;
 	int cpu = smp_processor_id();
-	struct tss_struct *tss = init_tss + cpu;
+	struct tss_struct *tss = &per_cpu(init_tss, cpu);
 
 	/* never put a printk in __switch_to... printk() calls wake_up*() indirectly */
 
@@ -551,28 +598,9 @@
 		loaddebug(next, 7);
 	}
 
-	if (unlikely(prev->io_bitmap_ptr || next->io_bitmap_ptr)) {
-		if (next->io_bitmap_ptr) {
-			/*
-			 * 4 cachelines copy ... not good, but not that
-			 * bad either. Anyone got something better?
-			 * This only affects processes which use ioperm().
-			 * [Putting the TSSs into 4k-tlb mapped regions
-			 * and playing VM tricks to switch the IO bitmap
-			 * is not really acceptable.]
-			 */
-			memcpy(tss->io_bitmap, next->io_bitmap_ptr,
-				IO_BITMAP_BYTES);
-			tss->io_bitmap_base = IO_BITMAP_OFFSET;
-		} else
-			/*
-			 * a bitmap offset pointing outside of the TSS limit
-			 * causes a nicely controllable SIGSEGV if a process
-			 * tries to use a port IO instruction. The first
-			 * sys_ioperm() call sets up the bitmap properly.
-			 */
-			tss->io_bitmap_base = INVALID_IO_BITMAP_OFFSET;
-	}
+	if (unlikely(prev->io_bitmap_ptr || next->io_bitmap_ptr))
+		handle_io_bitmap(next, tss);
+
 	return prev_p;
 }
 
@@ -593,7 +621,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/ptrace.c b/arch/i386/kernel/ptrace.c
--- a/arch/i386/kernel/ptrace.c	2004-10-18 14:56:27 -07:00
+++ b/arch/i386/kernel/ptrace.c	2004-10-18 14:56:27 -07:00
@@ -147,6 +147,7 @@
 { 
 	long tmp;
 
+	clear_tsk_thread_flag(child, TIF_SINGLESTEP);
 	tmp = get_stack_long(child, EFL_OFFSET) & ~TRAP_FLAG;
 	put_stack_long(child, EFL_OFFSET, tmp);
 }
@@ -370,6 +371,7 @@
 		else {
 			clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
 		}
+		clear_tsk_thread_flag(child, TIF_SINGLESTEP);
 		child->exit_code = data;
 	/* make sure the single step bit is not set. */
 		tmp = get_stack_long(child, EFL_OFFSET) & ~TRAP_FLAG;
@@ -391,6 +393,7 @@
 		if (child->state == TASK_ZOMBIE)	/* already dead */
 			break;
 		child->exit_code = SIGKILL;
+		clear_tsk_thread_flag(child, TIF_SINGLESTEP);
 		/* make sure the single step bit is not set. */
 		tmp = get_stack_long(child, EFL_OFFSET) & ~TRAP_FLAG;
 		put_stack_long(child, EFL_OFFSET, tmp);
@@ -411,6 +414,7 @@
 		}
 		tmp = get_stack_long(child, EFL_OFFSET) | TRAP_FLAG;
 		put_stack_long(child, EFL_OFFSET, tmp);
+		set_tsk_thread_flag(child, TIF_SINGLESTEP);
 		child->exit_code = data;
 		/* give it a chance to run. */
 		wake_up_process(child);
@@ -535,14 +539,15 @@
 			audit_syscall_exit(current, regs->eax);
 	}
 
-	if (!test_thread_flag(TIF_SYSCALL_TRACE))
+	if (!test_thread_flag(TIF_SYSCALL_TRACE) &&
+	    !test_thread_flag(TIF_SINGLESTEP))
 		return;
 	if (!(current->ptrace & PT_PTRACED))
 		return;
 	/* the 0x80 provides a way for the tracing parent to distinguish
 	   between a syscall stop and SIGTRAP delivery */
-	ptrace_notify(SIGTRAP | ((current->ptrace & PT_TRACESYSGOOD)
-				 ? 0x80 : 0));
+	ptrace_notify(SIGTRAP | ((current->ptrace & PT_TRACESYSGOOD) &&
+				 !test_thread_flag(TIF_SINGLESTEP) ? 0x80 : 0));
 
 	/*
 	 * this isn't the same as continuing with a signal, but it will do
diff -Nru a/arch/i386/kernel/setup.c b/arch/i386/kernel/setup.c
--- a/arch/i386/kernel/setup.c	2004-10-18 14:56:29 -07:00
+++ b/arch/i386/kernel/setup.c	2004-10-18 14:56:29 -07:00
@@ -49,6 +49,7 @@
 #include <asm/ist.h>
 #include <asm/io.h>
 #include "setup_arch_pre.h"
+#include <bios_ebda.h>
 
 /* This value is set up by the early boot code to point to the value
    immediately after the boot time page tables.  It contains a *physical*
@@ -218,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",
@@ -809,6 +815,14 @@
 		if (c == ' ' && !memcmp(from, "highmem=", 8))
 			highmem_pages = memparse(from+8, &from) >> PAGE_SHIFT;
 	
+		/*
+		 * vmalloc=size forces the vmalloc area to be exactly 'size'
+		 * bytes. This can be used to increase (or decrease) the
+		 * vmalloc area - the default is 128m.
+		 */
+		if (c == ' ' && !memcmp(from, "vmalloc=", 8))
+			__VMALLOC_RESERVE = memparse(from+8, &from);
+
 		c = *(from++);
 		if (!c)
 			break;
@@ -991,6 +1005,17 @@
 	}
 }
 
+/*
+ * workaround for Dell systems that neglect to reserve EBDA
+ */
+static void __init reserve_ebda_region(void)
+{
+	unsigned int addr;
+	addr = get_bios_ebda();
+	if (addr)
+		reserve_bootmem(addr, PAGE_SIZE);	
+}
+
 static unsigned long __init setup_memory(void)
 {
 	unsigned long bootmap_size, start_pfn, max_low_pfn;
@@ -1037,6 +1062,9 @@
 	 */
 	reserve_bootmem(0, PAGE_SIZE);
 
+	/* reserve EBDA region, it's a 4K region */
+	reserve_ebda_region();
+
     /* could be an AMD 768MPX chipset. Reserve a page  before VGA to prevent
        PCI prefetch into it (errata #56). Usually the page is reserved anyways,
        unless you have no PS/2 mouse plugged in. */
@@ -1335,13 +1363,22 @@
 
 	/*
 	 * NOTE: before this point _nobody_ is allowed to allocate
-	 * any memory using the bootmem allocator.
+	 * any memory using the bootmem allocator.  Although the
+	 * alloctor is now initialised only the first 8Mb of the kernel
+	 * virtual address space has been mapped.  All allocations before
+	 * paging_init() has completed must use the alloc_bootmem_low_pages()
+	 * variant (which allocates DMA'able memory) and care must be taken
+	 * not to exceed the 8Mb limit.
 	 */
 
 #ifdef CONFIG_SMP
 	smp_alloc_memory(); /* AP processor realmode stacks in low memory*/
 #endif
 	paging_init();
+
+	/*
+	 * NOTE: at this point the bootmem allocator is fully available.
+	 */
 
 #ifdef CONFIG_EARLY_PRINTK
 	{
diff -Nru a/arch/i386/kernel/signal.c b/arch/i386/kernel/signal.c
--- a/arch/i386/kernel/signal.c	2004-10-18 14:56:29 -07:00
+++ b/arch/i386/kernel/signal.c	2004-10-18 14:56:29 -07:00
@@ -19,6 +19,7 @@
 #include <linux/stddef.h>
 #include <linux/personality.h>
 #include <linux/suspend.h>
+#include <linux/ptrace.h>
 #include <linux/elf.h>
 #include <asm/processor.h>
 #include <asm/ucontext.h>
@@ -269,6 +270,7 @@
 		 struct pt_regs *regs, unsigned long mask)
 {
 	int tmp, err = 0;
+	unsigned long eflags;
 
 	tmp = 0;
 	__asm__("movl %%gs,%0" : "=r"(tmp): "0"(tmp));
@@ -290,7 +292,11 @@
 	err |= __put_user(current->thread.error_code, &sc->err);
 	err |= __put_user(regs->eip, &sc->eip);
 	err |= __put_user(regs->xcs, (unsigned int __user *)&sc->cs);
-	err |= __put_user(regs->eflags, &sc->eflags);
+	eflags = regs->eflags;
+	if (current->ptrace & PT_PTRACED) {
+		eflags &= ~TF_MASK;
+	}
+	err |= __put_user(eflags, &sc->eflags);
 	err |= __put_user(regs->esp, &sc->esp_at_signal);
 	err |= __put_user(regs->xss, (unsigned int __user *)&sc->ss);
 
@@ -345,18 +351,20 @@
 	void __user *restorer;
 	struct sigframe __user *frame;
 	int err = 0;
+	int usig;
 
 	frame = get_sigframe(ka, regs, sizeof(*frame));
 
 	if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame)))
 		goto give_sigsegv;
 
-	err |= __put_user((current_thread_info()->exec_domain
-		           && current_thread_info()->exec_domain->signal_invmap
-		           && sig < 32
-		           ? current_thread_info()->exec_domain->signal_invmap[sig]
-		           : sig),
-		          &frame->sig);
+	usig = current_thread_info()->exec_domain
+		&& current_thread_info()->exec_domain->signal_invmap
+		&& sig < 32
+		? current_thread_info()->exec_domain->signal_invmap[sig]
+		: sig;
+
+	err |= __put_user(usig, &frame->sig);
 	if (err)
 		goto give_sigsegv;
 
@@ -395,13 +403,22 @@
 	/* Set up registers for signal handler */
 	regs->esp = (unsigned long) frame;
 	regs->eip = (unsigned long) ka->sa.sa_handler;
+	regs->eax = (unsigned long) sig;
+	regs->edx = (unsigned long) 0;
+	regs->ecx = (unsigned long) 0;
 
 	set_fs(USER_DS);
 	regs->xds = __USER_DS;
 	regs->xes = __USER_DS;
 	regs->xss = __USER_DS;
 	regs->xcs = __USER_CS;
-	regs->eflags &= ~TF_MASK;
+	if (regs->eflags & TF_MASK) {
+		if (current->ptrace & PT_PTRACED) {
+			ptrace_notify(SIGTRAP);
+		} else {
+			regs->eflags &= ~TF_MASK;
+		}
+	}
 
 #if DEBUG_SIG
 	printk("SIG deliver (%s:%d): sp=%p pc=%p ra=%p\n",
@@ -411,9 +428,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,
@@ -422,18 +437,20 @@
 	void __user *restorer;
 	struct rt_sigframe __user *frame;
 	int err = 0;
+	int usig;
 
 	frame = get_sigframe(ka, regs, sizeof(*frame));
 
 	if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame)))
 		goto give_sigsegv;
 
-	err |= __put_user((current_thread_info()->exec_domain
-		    	   && current_thread_info()->exec_domain->signal_invmap
-		    	   && sig < 32
-		    	   ? current_thread_info()->exec_domain->signal_invmap[sig]
-			   : sig),
-			  &frame->sig);
+	usig = current_thread_info()->exec_domain
+		&& current_thread_info()->exec_domain->signal_invmap
+		&& sig < 32
+		? current_thread_info()->exec_domain->signal_invmap[sig]
+		: sig;
+
+	err |= __put_user(usig, &frame->sig);
 	err |= __put_user(&frame->info, &frame->pinfo);
 	err |= __put_user(&frame->uc, &frame->puc);
 	err |= copy_siginfo_to_user(&frame->info, info);
@@ -476,13 +493,22 @@
 	/* Set up registers for signal handler */
 	regs->esp = (unsigned long) frame;
 	regs->eip = (unsigned long) ka->sa.sa_handler;
+	regs->eax = (unsigned long) usig;
+	regs->edx = (unsigned long) &frame->info;
+	regs->ecx = (unsigned long) &frame->uc;
 
 	set_fs(USER_DS);
 	regs->xds = __USER_DS;
 	regs->xes = __USER_DS;
 	regs->xss = __USER_DS;
 	regs->xcs = __USER_CS;
-	regs->eflags &= ~TF_MASK;
+	if (regs->eflags & TF_MASK) {
+		if (current->ptrace & PT_PTRACED) {
+			ptrace_notify(SIGTRAP);
+		} else {
+			regs->eflags &= ~TF_MASK;
+		}
+	}
 
 #if DEBUG_SIG
 	printk("SIG deliver (%s:%d): sp=%p pc=%p ra=%p\n",
@@ -492,9 +518,7 @@
 	return;
 
 give_sigsegv:
-	if (sig == SIGSEGV)
-		ka->sa.sa_handler = SIG_DFL;
-	force_sig(SIGSEGV, current);
+	force_sigsegv(sig, current);
 }
 
 /*
@@ -502,11 +526,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 +556,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 +574,7 @@
 {
 	siginfo_t info;
 	int signr;
+	struct k_sigaction ka;
 
 	/*
 	 * We want the common case to go fast, which
@@ -573,7 +593,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 +603,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/smp.c b/arch/i386/kernel/smp.c
--- a/arch/i386/kernel/smp.c	2004-10-18 14:55:54 -07:00
+++ b/arch/i386/kernel/smp.c	2004-10-18 14:55:54 -07:00
@@ -22,7 +22,6 @@
 
 #include <asm/mtrr.h>
 #include <asm/tlbflush.h>
-#include <mach_ipi.h>
 #include <mach_apic.h>
 
 /*
@@ -104,7 +103,7 @@
  *	about nothing of note with C stepping upwards.
  */
 
-struct tlb_state cpu_tlbstate[NR_CPUS] __cacheline_aligned = {[0 ... NR_CPUS-1] = { &init_mm, 0, }};
+DEFINE_PER_CPU(struct tlb_state, cpu_tlbstate) ____cacheline_aligned = { &init_mm, 0, };
 
 /*
  * the following functions deal with sending IPIs between CPUs.
@@ -122,7 +121,7 @@
 	return SET_APIC_DEST_FIELD(mask);
 }
 
-inline void __send_IPI_shortcut(unsigned int shortcut, int vector)
+void __send_IPI_shortcut(unsigned int shortcut, int vector)
 {
 	/*
 	 * Subtle. In the case of the 'never do double writes' workaround
@@ -157,7 +156,7 @@
 /*
  * This is only used on smaller machines.
  */
-inline void send_IPI_mask_bitmask(cpumask_t cpumask, int vector)
+void send_IPI_mask_bitmask(cpumask_t cpumask, int vector)
 {
 	unsigned long mask = cpus_addr(cpumask)[0];
 	unsigned long cfg;
@@ -230,6 +229,8 @@
 	local_irq_restore(flags);
 }
 
+#include <mach_ipi.h> /* must come after the send_IPI functions above for inlining */
+
 /*
  *	Smarter SMP flushing macros. 
  *		c/o Linus Torvalds.
@@ -255,9 +256,9 @@
  */
 static inline void leave_mm (unsigned long cpu)
 {
-	if (cpu_tlbstate[cpu].state == TLBSTATE_OK)
+	if (per_cpu(cpu_tlbstate, cpu).state == TLBSTATE_OK)
 		BUG();
-	cpu_clear(cpu, cpu_tlbstate[cpu].active_mm->cpu_vm_mask);
+	cpu_clear(cpu, per_cpu(cpu_tlbstate, cpu).active_mm->cpu_vm_mask);
 	load_cr3(swapper_pg_dir);
 }
 
@@ -324,8 +325,8 @@
 		 * BUG();
 		 */
 		 
-	if (flush_mm == cpu_tlbstate[cpu].active_mm) {
-		if (cpu_tlbstate[cpu].state == TLBSTATE_OK) {
+	if (flush_mm == per_cpu(cpu_tlbstate, cpu).active_mm) {
+		if (per_cpu(cpu_tlbstate, cpu).state == TLBSTATE_OK) {
 			if (flush_va == FLUSH_ALL)
 				local_flush_tlb();
 			else
@@ -457,7 +458,7 @@
 	unsigned long cpu = smp_processor_id();
 
 	__flush_tlb_all();
-	if (cpu_tlbstate[cpu].state == TLBSTATE_LAZY)
+	if (per_cpu(cpu_tlbstate, cpu).state == TLBSTATE_LAZY)
 		leave_mm(cpu);
 }
 
diff -Nru a/arch/i386/kernel/smpboot.c b/arch/i386/kernel/smpboot.c
--- a/arch/i386/kernel/smpboot.c	2004-10-18 14:56:29 -07:00
+++ b/arch/i386/kernel/smpboot.c	2004-10-18 14:56:29 -07:00
@@ -17,7 +17,7 @@
  *	Fixes
  *		Felix Koop	:	NR_CPUS used properly
  *		Jose Renau	:	Handle single CPU case.
- *		Alan Cox	:	By repeated request 8) - Total BogoMIP report.
+ *		Alan Cox	:	By repeated request 8) - Total BogoMIPS report.
  *		Greg Wright	:	Fix for kernel stacks panic.
  *		Erich Boleyn	:	MP v1.4 and additional changes.
  *	Matthias Sattler	:	Changes for 2.1 kernel map.
@@ -72,6 +72,10 @@
 /* Per CPU bogomips and other parameters */
 struct cpuinfo_x86 cpu_data[NR_CPUS] __cacheline_aligned;
 
+u8 x86_cpu_to_apicid[NR_CPUS] =
+			{ [0 ... NR_CPUS-1] = 0xff };
+EXPORT_SYMBOL(x86_cpu_to_apicid);
+
 /* Set when the idlers are all forked */
 int smp_threads_ready;
 
@@ -187,34 +191,6 @@
 
 #define NR_LOOPS 5
 
-/*
- * accurate 64-bit/32-bit division, expanded to 32-bit divisions and 64-bit
- * multiplication. Not terribly optimized but we need it at boot time only
- * anyway.
- *
- * result == a / b
- *	== (a1 + a2*(2^32)) / b
- *	== a1/b + a2*(2^32/b)
- *	== a1/b + a2*((2^32-1)/b) + a2/b + (a2*((2^32-1) % b))/b
- *		    ^---- (this multiplication can overflow)
- */
-
-static unsigned long long __init div64 (unsigned long long a, unsigned long b0)
-{
-	unsigned int a1, a2;
-	unsigned long long res;
-
-	a1 = ((unsigned int*)&a)[0];
-	a2 = ((unsigned int*)&a)[1];
-
-	res = a1/b0 +
-		(unsigned long long)a2 * (unsigned long long)(0xffffffff/b0) +
-		a2 / b0 +
-		(a2 * (0xffffffff % b0)) / b0;
-
-	return res;
-}
-
 static void __init synchronize_tsc_bp (void)
 {
 	int i;
@@ -224,7 +200,7 @@
 	unsigned long one_usec;
 	int buggy = 0;
 
-	printk("checking TSC synchronization across %u CPUs: ", num_booting_cpus());
+	printk(KERN_INFO "checking TSC synchronization across %u CPUs: ", num_booting_cpus());
 
 	/* convert from kcyc/sec to cyc/usec */
 	one_usec = cpu_khz / 1000;
@@ -279,7 +255,8 @@
 			sum += t0;
 		}
 	}
-	avg = div64(sum, num_booting_cpus());
+	avg = sum;
+	do_div(avg, num_booting_cpus());
 
 	sum = 0;
 	for (i = 0; i < NR_CPUS; i++) {
@@ -297,18 +274,18 @@
 				buggy = 1;
 				printk("\n");
 			}
-			realdelta = div64(delta, one_usec);
+			realdelta = delta;
+			do_div(realdelta, one_usec);
 			if (tsc_values[i] < avg)
 				realdelta = -realdelta;
 
-			printk("BIOS BUG: CPU#%d improperly initialized, has %ld usecs TSC skew! FIXED.\n", i, realdelta);
+			printk(KERN_INFO "CPU#%d had %ld usecs TSC skew, fixed it up.\n", i, realdelta);
 		}
 
 		sum += delta;
 	}
 	if (!buggy)
 		printk("passed.\n");
-		;
 }
 
 static void __init synchronize_tsc_ap (void)
@@ -492,16 +469,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 */
@@ -797,21 +764,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();
 
@@ -875,6 +831,7 @@
 			inquire_remote_apic(apicid);
 		}
 	}
+	x86_cpu_to_apicid[cpu] = apicid;
 	if (boot_error) {
 		/* Try to put things back the way they were before ... */
 		unmap_cpu_to_logical_apicid(cpu);
@@ -957,6 +914,7 @@
 
 	boot_cpu_physical_apicid = GET_APIC_ID(apic_read(APIC_ID));
 	boot_cpu_logical_apicid = logical_smp_processor_id();
+	x86_cpu_to_apicid[0] = boot_cpu_physical_apicid;
 
 	current_thread_info()->cpu = 0;
 	smp_tune_scheduling();
@@ -1131,213 +1089,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-10-18 14:57:04 -07:00
+++ b/arch/i386/kernel/sysenter.c	2004-10-18 14:57:04 -07:00
@@ -24,7 +24,7 @@
 void enable_sep_cpu(void *info)
 {
 	int cpu = get_cpu();
-	struct tss_struct *tss = init_tss + cpu;
+	struct tss_struct *tss = &per_cpu(init_tss, cpu);
 
 	tss->ss1 = __KERNEL_CS;
 	tss->esp1 = sizeof(struct tss_struct) + (unsigned long) tss;
@@ -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/time.c b/arch/i386/kernel/time.c
--- a/arch/i386/kernel/time.c	2004-10-18 14:56:31 -07:00
+++ b/arch/i386/kernel/time.c	2004-10-18 14:56:31 -07:00
@@ -200,6 +200,18 @@
 }
 EXPORT_SYMBOL(monotonic_clock);
 
+#if defined(CONFIG_SMP) && defined(CONFIG_FRAME_POINTER)
+unsigned long profile_pc(struct pt_regs *regs)
+{
+	unsigned long pc = instruction_pointer(regs);
+
+	if (in_lock_functions(pc))
+		return *(unsigned long *)(regs->ebp + 4);
+
+	return pc;
+}
+EXPORT_SYMBOL(profile_pc);
+#endif
 
 /*
  * timer_interrupt() needs to keep up the real-time clock,
@@ -321,11 +333,12 @@
 
 static int time_resume(struct sys_device *dev)
 {
+	unsigned long flags;
 	unsigned long sec = get_cmos_time() + clock_cmos_diff;
-	write_seqlock_irq(&xtime_lock);
+	write_seqlock_irqsave(&xtime_lock, flags);
 	xtime.tv_sec = sec;
 	xtime.tv_nsec = 0;
-	write_sequnlock_irq(&xtime_lock);
+	write_sequnlock_irqrestore(&xtime_lock, flags);
 	return 0;
 }
 
diff -Nru a/arch/i386/kernel/time_hpet.c b/arch/i386/kernel/time_hpet.c
--- a/arch/i386/kernel/time_hpet.c	2004-10-18 14:56:17 -07:00
+++ b/arch/i386/kernel/time_hpet.c	2004-10-18 14:56:17 -07:00
@@ -29,7 +29,7 @@
 
 static int use_hpet; 		/* can be used for runtime check of hpet */
 static int boot_hpet_disable; 	/* boottime override for HPET timer */
-static unsigned long hpet_virt_address;	/* hpet kernel virtual address */
+static void __iomem * hpet_virt_address;	/* hpet kernel virtual address */
 
 #define FSEC_TO_USEC (1000000000UL)
 
@@ -76,8 +76,7 @@
 	if (!hpet_address) {
 		return -1;
 	}
-	hpet_virt_address = (unsigned long) ioremap_nocache(hpet_address,
-	                                                    HPET_MMAP_SIZE);
+	hpet_virt_address = ioremap_nocache(hpet_address, HPET_MMAP_SIZE);
 	/*
 	 * Read the period, compute tick and quotient.
 	 */
@@ -162,11 +161,11 @@
 		hd.hd_irq[0] = HPET_LEGACY_8254;
 		hd.hd_irq[1] = HPET_LEGACY_RTC;
 		if (ntimer > 2) {
-			struct hpet		*hpet;
-			struct hpet_timer	*timer;
+			struct hpet __iomem	*hpet;
+			struct hpet_timer __iomem *timer;
 			int			i;
 
-			hpet = (struct hpet *) hpet_virt_address;
+			hpet = hpet_virt_address;
 
 			for (i = 2, timer = &hpet->hpet_timers[2]; i < ntimer;
 				timer++, i++)
diff -Nru a/arch/i386/kernel/timers/timer_pit.c b/arch/i386/kernel/timers/timer_pit.c
--- a/arch/i386/kernel/timers/timer_pit.c	2004-10-18 14:56:50 -07:00
+++ b/arch/i386/kernel/timers/timer_pit.c	2004-10-18 14:56:50 -07:00
@@ -7,6 +7,9 @@
 #include <linux/module.h>
 #include <linux/device.h>
 #include <linux/irq.h>
+#include <linux/sysdev.h>
+#include <linux/timex.h>
+#include <asm/delay.h>
 #include <asm/mpspec.h>
 #include <asm/timer.h>
 #include <asm/smp.h>
@@ -156,3 +159,44 @@
 	.monotonic_clock = monotonic_clock_pit,
 	.delay = delay_pit,
 };
+
+void setup_pit_timer(void)
+{
+	extern spinlock_t i8253_lock;
+	unsigned long flags;
+
+	spin_lock_irqsave(&i8253_lock, flags);
+	outb_p(0x34,PIT_MODE);		/* binary, mode 2, LSB/MSB, ch 0 */
+	udelay(10);
+	outb_p(LATCH & 0xff , PIT_CH0);	/* LSB */
+	udelay(10);
+	outb(LATCH >> 8 , PIT_CH0);	/* MSB */
+	spin_unlock_irqrestore(&i8253_lock, flags);
+}
+
+static int timer_resume(struct sys_device *dev)
+{
+	setup_pit_timer();
+	return 0;
+}
+
+static struct sysdev_class timer_sysclass = {
+	set_kset_name("timer"),
+	.resume	= timer_resume,
+};
+
+static struct sys_device device_timer = {
+	.id	= 0,
+	.cls	= &timer_sysclass,
+};
+
+static int __init init_timer_sysfs(void)
+{
+	int error = sysdev_class_register(&timer_sysclass);
+	if (!error)
+		error = sysdev_register(&device_timer);
+	return error;
+}
+
+device_initcall(init_timer_sysfs);
+
diff -Nru a/arch/i386/kernel/timers/timer_tsc.c b/arch/i386/kernel/timers/timer_tsc.c
--- a/arch/i386/kernel/timers/timer_tsc.c	2004-10-18 14:56:48 -07:00
+++ b/arch/i386/kernel/timers/timer_tsc.c	2004-10-18 14:56:48 -07:00
@@ -265,7 +265,8 @@
 {
 	struct cpufreq_freqs *freq = data;
 
-	write_seqlock_irq(&xtime_lock);
+	if (val != CPUFREQ_RESUMECHANGE)
+		write_seqlock_irq(&xtime_lock);
 	if (!ref_freq) {
 		ref_freq = freq->old;
 		loops_per_jiffy_ref = cpu_data[freq->cpu].loops_per_jiffy;
@@ -291,7 +292,9 @@
 		}
 #endif
 	}
-	write_sequnlock_irq(&xtime_lock);
+
+	if (val != CPUFREQ_RESUMECHANGE)
+		write_sequnlock_irq(&xtime_lock);
 
 	return 0;
 }
diff -Nru a/arch/i386/kernel/traps.c b/arch/i386/kernel/traps.c
--- a/arch/i386/kernel/traps.c	2004-10-18 14:56:16 -07:00
+++ b/arch/i386/kernel/traps.c	2004-10-18 14:56:16 -07:00
@@ -26,6 +26,7 @@
 #include <linux/kallsyms.h>
 #include <linux/ptrace.h>
 #include <linux/version.h>
+#include <linux/kprobes.h>
 
 #ifdef CONFIG_EISA
 #include <linux/ioport.h>
@@ -48,6 +49,7 @@
 
 #include <asm/smp.h>
 #include <asm/arch_hooks.h>
+#include <asm/kdebug.h>
 
 #include <linux/irq.h>
 #include <linux/module.h>
@@ -92,6 +94,18 @@
 asmlinkage void machine_check(void);
 
 static int kstack_depth_to_print = 24;
+struct notifier_block *i386die_chain;
+static spinlock_t die_notifier_lock = SPIN_LOCK_UNLOCKED;
+
+int register_die_notifier(struct notifier_block *nb)
+{
+	int err = 0;
+	unsigned long flags;
+	spin_lock_irqsave(&die_notifier_lock, flags);
+	err = notifier_chain_register(&i386die_chain, nb);
+	spin_unlock_irqrestore(&die_notifier_lock, flags);
+	return err;
+}
 
 static int valid_stack_ptr(struct task_struct *task, void *p)
 {
@@ -216,7 +230,7 @@
 		ss = regs->xss & 0xffff;
 	}
 	print_modules();
-	printk("CPU:    %d\nEIP:    %04x:[<%08lx>]    %s\nEFLAGS: %08lx"
+	printk("CPU:    %d\nEIP:    %04x:[<%08lx>]    %s VLI\nEFLAGS: %08lx"
 			"   (%s) \n",
 		smp_processor_id(), 0xffff & regs->xcs, regs->eip,
 		print_tainted(), regs->eflags, UTS_RELEASE);
@@ -234,23 +248,25 @@
 	 * time of the fault..
 	 */
 	if (in_kernel) {
+		u8 *eip;
 
 		printk("\nStack: ");
 		show_stack(NULL, (unsigned long*)esp);
 
 		printk("Code: ");
-		if(regs->eip < PAGE_OFFSET)
-			goto bad;
 
-		for(i=0;i<20;i++)
-		{
+		eip = (u8 *)regs->eip - 43;
+		for (i = 0; i < 64; i++, eip++) {
 			unsigned char c;
-			if(__get_user(c, &((unsigned char*)regs->eip)[i])) {
-bad:
+
+			if (eip < (u8 *)PAGE_OFFSET || __get_user(c, eip)) {
 				printk(" Bad EIP value.");
 				break;
 			}
-			printk("%02x ", c);
+			if (eip == (u8 *)regs->eip)
+				printk("<%02x> ", c);
+			else
+				printk("%02x ", c);
 		}
 	}
 	printk("\n");
@@ -292,35 +308,53 @@
 	printk("Kernel BUG\n");
 }
 
-spinlock_t die_lock = SPIN_LOCK_UNLOCKED;
-
 void die(const char * str, struct pt_regs * regs, long err)
 {
+	static struct {
+		spinlock_t lock;
+		u32 lock_owner;
+		int lock_owner_depth;
+	} die = {
+		.lock =			SPIN_LOCK_UNLOCKED,
+		.lock_owner =		-1,
+		.lock_owner_depth =	0
+	};
 	static int die_counter;
-	int nl = 0;
 
-	console_verbose();
-	spin_lock_irq(&die_lock);
-	bust_spinlocks(1);
-	handle_BUG(regs);
-	printk(KERN_ALERT "%s: %04lx [#%d]\n", str, err & 0xffff, ++die_counter);
+	if (die.lock_owner != smp_processor_id()) {
+		console_verbose();
+		spin_lock_irq(&die.lock);
+		die.lock_owner = smp_processor_id();
+		die.lock_owner_depth = 0;
+		bust_spinlocks(1);
+	}
+
+	if (++die.lock_owner_depth < 3) {
+		int nl = 0;
+		handle_BUG(regs);
+		printk(KERN_ALERT "%s: %04lx [#%d]\n", str, err & 0xffff, ++die_counter);
 #ifdef CONFIG_PREEMPT
-	printk("PREEMPT ");
-	nl = 1;
+		printk("PREEMPT ");
+		nl = 1;
 #endif
 #ifdef CONFIG_SMP
-	printk("SMP ");
-	nl = 1;
+		printk("SMP ");
+		nl = 1;
 #endif
 #ifdef CONFIG_DEBUG_PAGEALLOC
-	printk("DEBUG_PAGEALLOC");
-	nl = 1;
+		printk("DEBUG_PAGEALLOC");
+		nl = 1;
 #endif
-	if (nl)
-		printk("\n");
-	show_registers(regs);
+		if (nl)
+			printk("\n");
+	notify_die(DIE_OOPS, (char *)str, regs, err, 255, SIGSEGV);
+		show_registers(regs);
+  	} else
+		printk(KERN_ERR "Recursive die() failure, output suppressed\n");
+
 	bust_spinlocks(0);
-	spin_unlock_irq(&die_lock);
+	die.lock_owner = -1;
+	spin_unlock_irq(&die.lock);
 	if (in_interrupt())
 		panic("Fatal exception in interrupt");
 
@@ -387,6 +421,9 @@
 #define DO_ERROR(trapnr, signr, str, name) \
 asmlinkage void do_##name(struct pt_regs * regs, long error_code) \
 { \
+	if (notify_die(DIE_TRAP, str, regs, error_code, trapnr, signr) \
+						== NOTIFY_STOP) \
+		return; \
 	do_trap(trapnr, signr, str, 0, regs, error_code, NULL); \
 }
 
@@ -398,12 +435,18 @@
 	info.si_errno = 0; \
 	info.si_code = sicode; \
 	info.si_addr = (void __user *)siaddr; \
+	if (notify_die(DIE_TRAP, str, regs, error_code, trapnr, signr) \
+						== NOTIFY_STOP) \
+		return; \
 	do_trap(trapnr, signr, str, 0, regs, error_code, &info); \
 }
 
 #define DO_VM86_ERROR(trapnr, signr, str, name) \
 asmlinkage void do_##name(struct pt_regs * regs, long error_code) \
 { \
+	if (notify_die(DIE_TRAP, str, regs, error_code, trapnr, signr) \
+						== NOTIFY_STOP) \
+		return; \
 	do_trap(trapnr, signr, str, 1, regs, error_code, NULL); \
 }
 
@@ -415,11 +458,16 @@
 	info.si_errno = 0; \
 	info.si_code = sicode; \
 	info.si_addr = (void __user *)siaddr; \
+	if (notify_die(DIE_TRAP, str, regs, error_code, trapnr, signr) \
+						== NOTIFY_STOP) \
+		return; \
 	do_trap(trapnr, signr, str, 1, regs, error_code, &info); \
 }
 
 DO_VM86_ERROR_INFO( 0, SIGFPE,  "divide error", divide_error, FPE_INTDIV, regs->eip)
+#ifndef CONFIG_KPROBES
 DO_VM86_ERROR( 3, SIGTRAP, "int3", int3)
+#endif
 DO_VM86_ERROR( 4, SIGSEGV, "overflow", overflow)
 DO_VM86_ERROR( 5, SIGSEGV, "bounds", bounds)
 DO_ERROR_INFO( 6, SIGILL,  "invalid operand", invalid_op, ILL_ILLOPN, regs->eip)
@@ -427,13 +475,40 @@
 DO_ERROR(10, SIGSEGV, "invalid TSS", invalid_TSS)
 DO_ERROR(11, SIGBUS,  "segment not present", segment_not_present)
 DO_ERROR(12, SIGBUS,  "stack segment", stack_segment)
-DO_ERROR_INFO(17, SIGBUS, "alignment check", alignment_check, BUS_ADRALN, get_cr2())
+DO_ERROR_INFO(17, SIGBUS, "alignment check", alignment_check, BUS_ADRALN, 0)
 
 asmlinkage void do_general_protection(struct pt_regs * regs, long error_code)
 {
-	if (regs->eflags & X86_EFLAGS_IF)
-		local_irq_enable();
- 
+	int cpu = get_cpu();
+	struct tss_struct *tss = &per_cpu(init_tss, cpu);
+	struct thread_struct *thread = &current->thread;
+
+	/*
+	 * Perform the lazy TSS's I/O bitmap copy. If the TSS has an
+	 * invalid offset set (the LAZY one) and the faulting thread has
+	 * a valid I/O bitmap pointer, we copy the I/O bitmap in the TSS
+	 * and we set the offset field correctly. Then we let the CPU to
+	 * restart the faulting instruction.
+	 */
+	if (tss->io_bitmap_base == INVALID_IO_BITMAP_OFFSET_LAZY &&
+	    thread->io_bitmap_ptr) {
+		memcpy(tss->io_bitmap, thread->io_bitmap_ptr,
+		       thread->io_bitmap_max);
+		/*
+		 * If the previously set map was extending to higher ports
+		 * than the current one, pad extra space with 0xff (no access).
+		 */
+		if (thread->io_bitmap_max < tss->io_bitmap_max)
+			memset((char *) tss->io_bitmap +
+				thread->io_bitmap_max, 0xff,
+				tss->io_bitmap_max - thread->io_bitmap_max);
+		tss->io_bitmap_max = thread->io_bitmap_max;
+		tss->io_bitmap_base = IO_BITMAP_OFFSET;
+		put_cpu();
+		return;
+	}
+	put_cpu();
+
 	if (regs->eflags & VM_MASK)
 		goto gp_in_vm86;
 
@@ -451,8 +526,12 @@
 	return;
 
 gp_in_kernel:
-	if (!fixup_exception(regs))
+	if (!fixup_exception(regs)) {
+		if (notify_die(DIE_GPF, "general protection fault", regs,
+				error_code, 13, SIGSEGV) == NOTIFY_STOP);
+			return;
 		die("general protection fault", regs, error_code);
+	}
 }
 
 static void mem_parity_error(unsigned char reason, struct pt_regs * regs)
@@ -496,11 +575,35 @@
 	printk("Do you have a strange power saving mode enabled?\n");
 }
 
+static spinlock_t nmi_print_lock = SPIN_LOCK_UNLOCKED;
+
+void die_nmi (struct pt_regs *regs, const char *msg)
+{
+	spin_lock(&nmi_print_lock);
+	/*
+	* We are in trouble anyway, lets at least try
+	* to get a message out.
+	*/
+	bust_spinlocks(1);
+	printk(msg);
+	printk(" on CPU%d, eip %08lx, registers:\n",
+		smp_processor_id(), regs->eip);
+	show_registers(regs);
+	printk("console shuts up ...\n");
+	console_silent();
+	spin_unlock(&nmi_print_lock);
+	bust_spinlocks(0);
+	do_exit(SIGSEGV);
+}
+
 static void default_do_nmi(struct pt_regs * regs)
 {
 	unsigned char reason = get_nmi_reason();
  
 	if (!(reason & 0xc0)) {
+		if (notify_die(DIE_NMI_IPI, "nmi_ipi", regs, reason, 0, SIGINT)
+							== NOTIFY_STOP)
+			return;
 #ifdef CONFIG_X86_LOCAL_APIC
 		/*
 		 * Ok, so this is none of the documented NMI sources,
@@ -514,6 +617,8 @@
 		unknown_nmi_error(reason, regs);
 		return;
 	}
+	if (notify_die(DIE_NMI, "nmi", regs, reason, 0, SIGINT) == NOTIFY_STOP)
+		return;
 	if (reason & 0x80)
 		mem_parity_error(reason, regs);
 	if (reason & 0x40)
@@ -557,6 +662,20 @@
 	nmi_callback = dummy_nmi_callback;
 }
 
+#ifdef CONFIG_KPROBES
+asmlinkage int do_int3(struct pt_regs *regs, long error_code)
+{
+	if (notify_die(DIE_INT3, "int3", regs, error_code, 3, SIGTRAP)
+			== NOTIFY_STOP)
+		return 1;
+	/* This is an interrupt gate, because kprobes wants interrupts
+	disabled.  Normal trap handlers don't. */
+	restore_interrupts(regs);
+	do_trap(3, SIGTRAP, "int3", 1, regs, error_code, NULL);
+	return 0;
+}
+#endif
+
 /*
  * Our handling of the processor debug registers is non-trivial.
  * We do not clear them on entry and exit from the kernel. Therefore
@@ -587,6 +706,9 @@
 
 	__asm__ __volatile__("movl %%db6,%0" : "=r" (condition));
 
+	if (notify_die(DIE_DEBUG, "debug", regs, condition, error_code,
+					SIGTRAP) == NOTIFY_STOP)
+		return;
 	/* It's safe to allow irq's after DR6 has been saved */
 	if (regs->eflags & X86_EFLAGS_IF)
 		local_irq_enable();
@@ -875,6 +997,14 @@
 	_set_gate(idt_table+n,14,0,addr,__KERNEL_CS);
 }
 
+/*
+ * This routine sets up an interrupt gate at directory privilege level 3.
+ */
+static inline void set_system_intr_gate(unsigned int n, void *addr)
+{
+	_set_gate(idt_table+n, 14, 3, addr, __KERNEL_CS);
+}
+
 static void __init set_trap_gate(unsigned int n, void *addr)
 {
 	_set_gate(idt_table+n,15,0,addr,__KERNEL_CS);
@@ -911,7 +1041,7 @@
 	set_trap_gate(0,&divide_error);
 	set_intr_gate(1,&debug);
 	set_intr_gate(2,&nmi);
-	set_system_gate(3,&int3);	/* int3-5 can be called from all */
+	set_system_intr_gate(3, &int3); /* int3-5 can be called from all */
 	set_system_gate(4,&overflow);
 	set_system_gate(5,&bounds);
 	set_trap_gate(6,&invalid_op);
diff -Nru a/arch/i386/kernel/vm86.c b/arch/i386/kernel/vm86.c
--- a/arch/i386/kernel/vm86.c	2004-10-18 14:55:55 -07:00
+++ b/arch/i386/kernel/vm86.c	2004-10-18 14:55:55 -07:00
@@ -121,7 +121,7 @@
 		do_exit(SIGSEGV);
 	}
 
-	tss = init_tss + get_cpu();
+	tss = &per_cpu(init_tss, get_cpu());
 	current->thread.esp0 = current->thread.saved_esp0;
 	current->thread.sysenter_cs = __KERNEL_CS;
 	load_esp0(tss, &current->thread);
@@ -303,7 +303,7 @@
 	asm volatile("movl %%fs,%0":"=m" (tsk->thread.saved_fs));
 	asm volatile("movl %%gs,%0":"=m" (tsk->thread.saved_gs));
 
-	tss = init_tss + get_cpu();
+	tss = &per_cpu(init_tss, get_cpu());
 	tsk->thread.esp0 = (unsigned long) &info->VM86_TSS_ESP0;
 	if (cpu_has_sep)
 		tsk->thread.sysenter_cs = 0;
diff -Nru a/arch/i386/kernel/vmlinux.lds.S b/arch/i386/kernel/vmlinux.lds.S
--- a/arch/i386/kernel/vmlinux.lds.S	2004-10-18 14:56:17 -07:00
+++ b/arch/i386/kernel/vmlinux.lds.S	2004-10-18 14:56:17 -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,12 +12,13 @@
 jiffies = jiffies_64;
 SECTIONS
 {
-  . = 0xC0000000 + 0x100000;
+  . = __PAGE_OFFSET + 0x100000;
   /* read-only */
   _text = .;			/* Text and read-only data */
   .text : {
 	*(.text)
 	SCHED_TEXT
+	LOCK_TEXT
 	*(.fixup)
 	*(.gnu.warning)
 	} = 0x9090
@@ -66,9 +68,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	2004-10-18 14:56:28 -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-10-18 14:56:28 -07:00
@@ -0,0 +1,65 @@
+/*
+ * 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/asm_offsets.h>
+
+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/memcpy.c b/arch/i386/lib/memcpy.c
--- a/arch/i386/lib/memcpy.c	2004-10-18 14:57:04 -07:00
+++ b/arch/i386/lib/memcpy.c	2004-10-18 14:57:04 -07:00
@@ -13,13 +13,13 @@
 	return __memcpy(to, from, n);
 #endif
 }
-EXPORT_SYMBOL_NOVERS(memcpy);
+EXPORT_SYMBOL(memcpy);
 
 void *memset(void *s, int c, size_t count)
 {
 	return __memset(s, c, count);
 }
-EXPORT_SYMBOL_NOVERS(memset);
+EXPORT_SYMBOL(memset);
 
 void *memmove(void *dest, const void *src, size_t n)
 {
@@ -41,4 +41,4 @@
 	}
 	return dest;
 }
-EXPORT_SYMBOL_NOVERS(memmove);
+EXPORT_SYMBOL(memmove);
diff -Nru a/arch/i386/lib/mmx.c b/arch/i386/lib/mmx.c
--- a/arch/i386/lib/mmx.c	2004-10-18 14:56:32 -07:00
+++ b/arch/i386/lib/mmx.c	2004-10-18 14:56:32 -07:00
@@ -2,9 +2,9 @@
 #include <linux/types.h>
 #include <linux/string.h>
 #include <linux/sched.h>
+#include <linux/hardirq.h>
 
 #include <asm/i387.h>
-#include <asm/hardirq.h> 
 
 
 /*
diff -Nru a/arch/i386/lib/usercopy.c b/arch/i386/lib/usercopy.c
--- a/arch/i386/lib/usercopy.c	2004-10-18 14:55:53 -07:00
+++ b/arch/i386/lib/usercopy.c	2004-10-18 14:55:53 -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-10-18 14:55:55 -07:00
+++ b/arch/i386/mach-es7000/es7000.h	2004-10-18 14:55:55 -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)   
@@ -103,6 +103,13 @@
 
 #define	MIP_SW_APIC		0x1020b
 #define	MIP_FUNC(VALUE) 	(VALUE & 0xff)
+
+#if defined(CONFIG_X86_IO_APIC) && (defined(CONFIG_ACPI_INTERPRETER) || defined(CONFIG_ACPI_BOOT))
+#define IOAPIC_GSI_BOUND(ioapic) ((ioapic+1) * (nr_ioapic_registers[ioapic]-1))
+#define MAX_GSI_MAPSIZE 32
+#endif
+
+extern unsigned long io_apic_irqs;
 
 extern int parse_unisys_oem (char *oemptr, int oem_entries);
 extern int find_unisys_acpi_oem_table(unsigned long *oem_addr, int *length);
diff -Nru a/arch/i386/mach-es7000/es7000plat.c b/arch/i386/mach-es7000/es7000plat.c
--- a/arch/i386/mach-es7000/es7000plat.c	2004-10-18 14:57:03 -07:00
+++ b/arch/i386/mach-es7000/es7000plat.c	2004-10-18 14:57:03 -07:00
@@ -51,27 +51,74 @@
 int 			mip_port;
 unsigned long		mip_addr, host_addr;
 
+#if defined(CONFIG_X86_IO_APIC) && (defined(CONFIG_ACPI_INTERPRETER) || defined(CONFIG_ACPI_BOOT))
+static unsigned long cycle_irqs = 0;
+static unsigned long free_irqs = 0;
+static int gsi_map[MAX_GSI_MAPSIZE] = { [0 ... MAX_GSI_MAPSIZE-1] = -1 };
+
+/*
+ * GSI override for ES7000 platforms.
+ */
+
+static int __init
+es7000_gsi_override(int ioapic, int gsi)
+{
+	static int newgsi = 0;
+
+	if (gsi_map[gsi] != -1)
+		gsi = gsi_map[gsi];
+	else if (cycle_irqs ^ free_irqs) {
+		newgsi = find_next_bit(&cycle_irqs, IOAPIC_GSI_BOUND(0), newgsi);
+		__set_bit(newgsi, &free_irqs);
+		gsi_map[gsi] = newgsi;
+		gsi = newgsi;
+		newgsi++;
+		Dprintk("es7000_gsi_override: free_irqs = 0x%lx\n", free_irqs);
+	}
+
+	return gsi;
+}
+
 static int __init
 es7000_rename_gsi(int ioapic, int gsi)
 {
+	static int initialized = 0;
+	int i;
+
+	/*
+	 * These should NEVER be true at this point but we'd rather be
+	 * safe than sorry.
+	 */
+	if (acpi_disabled || acpi_pci_disabled || acpi_noirq)
+ 		return gsi;
+
 	if (ioapic)
-		return gsi;
-	else {
-		if (gsi == 0)
-			return 13;
-		if (gsi == 1)
-			return 16;
-		if (gsi == 4)
-			return 17;
-		if (gsi == 6)
-			return 18;
-		if (gsi == 7)
-			return 19;
-		if (gsi == 8)
-			return 20;
-		return gsi;
-        }
+ 		return gsi;
+
+	if (!initialized) {
+		unsigned long tmp_irqs = 0;
+
+		for (i = 0; i < nr_ioapic_registers[0]; i++)
+			__set_bit(mp_irqs[i].mpc_srcbusirq, &tmp_irqs);
+
+		cycle_irqs = (~tmp_irqs & io_apic_irqs & ((1 << IOAPIC_GSI_BOUND(0)) - 1));
+
+		initialized = 1;
+		Dprintk("es7000_rename_gsi: cycle_irqs = 0x%lx\n", cycle_irqs);
+	}
+
+	for (i = 0; i < nr_ioapic_registers[0]; i++) {
+		if (mp_irqs[i].mpc_srcbusirq == gsi) {
+			if (mp_irqs[i].mpc_dstirq == gsi)
+				return gsi;
+			else
+				return es7000_gsi_override(0, gsi);
+		}
+	}
+
+	return gsi;
 }
+#endif // (CONFIG_X86_IO_APIC) && (CONFIG_ACPI_INTERPRETER || CONFIG_ACPI_BOOT)
 
 /*
  * Parse the OEM Table
@@ -193,7 +240,7 @@
 			}
 		}
 	}
-	printk("ES7000: did not find Unisys ACPI OEM table!\n");
+	Dprintk("ES7000: did not find Unisys ACPI OEM table!\n");
 	return -1;
 }
 
@@ -237,7 +284,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	2004-10-18 14:56:27 -07:00
+++ b/arch/i386/mach-generic/bigsmp.c	2004-10-18 14:56:27 -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-10-18 14:56:28 -07:00
+++ b/arch/i386/mach-voyager/voyager_smp.c	2004-10-18 14:56:28 -07:00
@@ -35,7 +35,7 @@
 int reboot_smp = 0;
 
 /* TLB state -- visible externally, indexed physically */
-struct tlb_state cpu_tlbstate[NR_CPUS] __cacheline_aligned = {[0 ... NR_CPUS-1] = { &init_mm, 0 }};
+DEFINE_PER_CPU(struct tlb_state, cpu_tlbstate) ____cacheline_aligned = { &init_mm, 0 };
 
 /* CPU IRQ affinity -- set to all ones initially */
 static unsigned long cpu_irq_affinity[NR_CPUS] __cacheline_aligned = { [0 ... NR_CPUS-1]  = ~0UL };
@@ -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;
 
@@ -860,9 +845,9 @@
 static inline void
 leave_mm (unsigned long cpu)
 {
-	if (cpu_tlbstate[cpu].state == TLBSTATE_OK)
+	if (per_cpu(cpu_tlbstate, cpu).state == TLBSTATE_OK)
 		BUG();
-	cpu_clear(cpu,  cpu_tlbstate[cpu].active_mm->cpu_vm_mask);
+	cpu_clear(cpu, per_cpu(cpu_tlbstate, cpu).active_mm->cpu_vm_mask);
 	load_cr3(swapper_pg_dir);
 }
 
@@ -883,8 +868,8 @@
 		smp_processor_id()));
 	*/
 
-	if (flush_mm == cpu_tlbstate[cpu].active_mm) {
-		if (cpu_tlbstate[cpu].state == TLBSTATE_OK) {
+	if (flush_mm == per_cpu(cpu_tlbstate, cpu).active_mm) {
+		if (per_cpu(cpu_tlbstate, cpu).state == TLBSTATE_OK) {
 			if (flush_va == FLUSH_ALL)
 				local_flush_tlb();
 			else
@@ -1218,7 +1203,7 @@
 	unsigned long cpu = smp_processor_id();
 
 	__flush_tlb_all();
-	if (cpu_tlbstate[cpu].state == TLBSTATE_LAZY)
+	if (per_cpu(cpu_tlbstate, cpu).state == TLBSTATE_LAZY)
 		leave_mm(cpu);
 }
 
@@ -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/math-emu/fpu_proto.h b/arch/i386/math-emu/fpu_proto.h
--- a/arch/i386/math-emu/fpu_proto.h	2004-10-18 14:57:03 -07:00
+++ b/arch/i386/math-emu/fpu_proto.h	2004-10-18 14:57:03 -07:00
@@ -69,7 +69,6 @@
 extern void FPU_pop(void);
 extern int FPU_empty_i(int stnr);
 extern int FPU_stackoverflow(FPU_REG **st_new_ptr);
-extern void FPU_sync_tags(void);
 extern void FPU_copy_to_regi(FPU_REG const *r, u_char tag, int stnr);
 extern void FPU_copy_to_reg1(FPU_REG const *r, u_char tag);
 extern void FPU_copy_to_reg0(FPU_REG const *r, u_char tag);
diff -Nru a/arch/i386/mm/Makefile b/arch/i386/mm/Makefile
--- a/arch/i386/mm/Makefile	2004-10-18 14:56:27 -07:00
+++ b/arch/i386/mm/Makefile	2004-10-18 14:56:27 -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-10-18 14:56:32 -07:00
+++ b/arch/i386/mm/discontig.c	2004-10-18 14:56:32 -07:00
@@ -31,6 +31,7 @@
 #include <asm/e820.h>
 #include <asm/setup.h>
 #include <asm/mmzone.h>
+#include <bios_ebda.h>
 
 struct pglist_data *node_data[MAX_NUMNODES];
 bootmem_data_t node0_bdata;
@@ -219,6 +220,17 @@
 	return reserve_pages;
 }
 
+/*
+ * workaround for Dell systems that neglect to reserve EBDA
+ */
+static void __init reserve_ebda_region_node(void)
+{
+	unsigned int addr;
+	addr = get_bios_ebda();
+	if (addr)
+		reserve_bootmem_node(NODE_DATA(0), addr, PAGE_SIZE);
+}
+
 unsigned long __init setup_memory(void)
 {
 	int nid;
@@ -318,6 +330,9 @@
 	 */
 	reserve_bootmem_node(NODE_DATA(0), PAGE_SIZE, PAGE_SIZE);
 
+	/* reserve EBDA region, it's a 4K region */
+	reserve_ebda_region_node();
+
 #ifdef CONFIG_ACPI_SLEEP
 	/*
 	 * Reserve low memory region for sleep support.
@@ -402,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-10-18 14:55:53 -07:00
+++ b/arch/i386/mm/fault.c	2004-10-18 14:55:53 -07:00
@@ -24,8 +24,8 @@
 
 #include <asm/system.h>
 #include <asm/uaccess.h>
-#include <asm/hardirq.h>
 #include <asm/desc.h>
+#include <asm/kdebug.h>
 
 extern void die(const char *,struct pt_regs *,long);
 
@@ -107,7 +107,7 @@
 		desc = (void *)desc + (seg & ~7);
 	} else {
 		/* Must disable preemption while reading the GDT. */
-		desc = (u32 *)&cpu_gdt_table[get_cpu()];
+		desc = (u32 *)&per_cpu(cpu_gdt_table, get_cpu());
 		desc = (void *)desc + (seg & ~7);
 	}
 
@@ -226,6 +226,9 @@
 	/* get the address */
 	__asm__("movl %%cr2,%0":"=r" (address));
 
+	if (notify_die(DIE_PAGE_FAULT, "page fault", regs, error_code, 14,
+					SIGSEGV) == NOTIFY_STOP)
+		return;
 	/* It's safe to allow irq's after cr2 has been saved */
 	if (regs->eflags & (X86_EFLAGS_IF|VM_MASK))
 		local_irq_enable();
@@ -513,12 +516,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/init.c b/arch/i386/mm/init.c
--- a/arch/i386/mm/init.c	2004-10-18 14:56:49 -07:00
+++ b/arch/i386/mm/init.c	2004-10-18 14:56:49 -07:00
@@ -40,10 +40,12 @@
 #include <asm/tlbflush.h>
 #include <asm/sections.h>
 
+unsigned int __VMALLOC_RESERVE = 128 << 20;
+
 DEFINE_PER_CPU(struct mmu_gather, mmu_gathers);
 unsigned long highstart_pfn, highend_pfn;
 
-static int do_test_wp_bit(void);
+static int noinline do_test_wp_bit(void);
 
 /*
  * Creates a middle page table and puts a pointer to it in the
@@ -671,7 +673,7 @@
  * This function cannot be __init, since exceptions don't work in that
  * section.  Put this after the callers, so that it cannot be inlined.
  */
-static int do_test_wp_bit(void)
+static int noinline do_test_wp_bit(void)
 {
 	char tmp_reg;
 	int flag;
diff -Nru a/arch/i386/mm/ioremap.c b/arch/i386/mm/ioremap.c
--- a/arch/i386/mm/ioremap.c	2004-10-18 14:56:27 -07:00
+++ b/arch/i386/mm/ioremap.c	2004-10-18 14:56:27 -07:00
@@ -110,9 +110,9 @@
  * have to convert them into an offset in a page-aligned mapping, but the
  * caller shouldn't need to know that small detail.
  */
-void * __ioremap(unsigned long phys_addr, unsigned long size, unsigned long flags)
+void __iomem * __ioremap(unsigned long phys_addr, unsigned long size, unsigned long flags)
 {
-	void * addr;
+	void __iomem * addr;
 	struct vm_struct * area;
 	unsigned long offset, last_addr;
 
@@ -125,7 +125,7 @@
 	 * Don't remap the low PCI/ISA area, it's always mapped..
 	 */
 	if (phys_addr >= 0xA0000 && last_addr < 0x100000)
-		return phys_to_virt(phys_addr);
+		return (void __iomem *) phys_to_virt(phys_addr);
 
 	/*
 	 * Don't allow anybody to remap normal RAM that we're using..
@@ -156,12 +156,12 @@
 	if (!area)
 		return NULL;
 	area->phys_addr = phys_addr;
-	addr = area->addr;
+	addr = (void __iomem *) area->addr;
 	if (remap_area_pages((unsigned long) addr, phys_addr, size, flags)) {
-		vunmap(addr);
+		vunmap((void __force *) addr);
 		return NULL;
 	}
-	return (void *) (offset + (char *)addr);
+	return (void __iomem *) (offset + (char __iomem *)addr);
 }
 
 
@@ -187,10 +187,10 @@
  * Must be freed with iounmap.
  */
 
-void *ioremap_nocache (unsigned long phys_addr, unsigned long size)
+void __iomem *ioremap_nocache (unsigned long phys_addr, unsigned long size)
 {
 	unsigned long last_addr;
-	void *p = __ioremap(phys_addr, size, _PAGE_PCD);
+	void __iomem *p = __ioremap(phys_addr, size, _PAGE_PCD);
 	if (!p) 
 		return p; 
 
@@ -221,12 +221,12 @@
 	return p;					
 }
 
-void iounmap(void *addr)
+void iounmap(volatile void __iomem *addr)
 {
 	struct vm_struct *p;
-	if (addr <= high_memory) 
+	if ((void __force *) addr <= high_memory) 
 		return; 
-	p = remove_vm_area((void *) (PAGE_MASK & (unsigned long) addr));
+	p = remove_vm_area((void *) (PAGE_MASK & (unsigned long __force) addr));
 	if (!p) { 
 		printk("__iounmap: bad address %p\n", addr);
 		return;
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-10-18 14:57:23 -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-10-18 14:56:29 -07:00
+++ b/arch/i386/mm/pageattr.c	2004-10-18 14:56:29 -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/oprofile/op_model_athlon.c b/arch/i386/oprofile/op_model_athlon.c
--- a/arch/i386/oprofile/op_model_athlon.c	2004-10-18 14:57:20 -07:00
+++ b/arch/i386/oprofile/op_model_athlon.c	2004-10-18 14:57:20 -07:00
@@ -70,7 +70,7 @@
 
 	/* enable active counters */
 	for (i = 0; i < NUM_COUNTERS; ++i) {
-		if (counter_config[i].event) {
+		if (counter_config[i].enabled) {
 			reset_value[i] = counter_config[i].count;
 
 			CTR_WRITE(counter_config[i].count, msrs, i);
@@ -96,7 +96,7 @@
 {
 	unsigned int low, high;
 	int i;
-	unsigned long eip = instruction_pointer(regs);
+	unsigned long eip = profile_pc(regs);
 	int is_kernel = !user_mode(regs);
 
 	for (i = 0 ; i < NUM_COUNTERS; ++i) {
diff -Nru a/arch/i386/oprofile/op_model_p4.c b/arch/i386/oprofile/op_model_p4.c
--- a/arch/i386/oprofile/op_model_p4.c	2004-10-18 14:55:54 -07:00
+++ b/arch/i386/oprofile/op_model_p4.c	2004-10-18 14:55:54 -07:00
@@ -419,9 +419,28 @@
 		msrs->controls[i].addr = addr;
 	}
 	
-	/* 43 ESCR registers in three discontiguous group */
+	/* 43 ESCR registers in three or four discontiguous group */
 	for (addr = MSR_P4_BSU_ESCR0 + stag;
-	     addr <= MSR_P4_SSU_ESCR0; ++i, addr += addr_increment()) { 
+	     addr < MSR_P4_IQ_ESCR0; ++i, addr += addr_increment()) {
+		msrs->controls[i].addr = addr;
+	}
+
+	/* no IQ_ESCR0/1 on some models, we save a seconde time BSU_ESCR0/1
+	 * to avoid special case in nmi_{save|restore}_registers() */
+	if (boot_cpu_data.x86_model >= 0x3) {
+		for (addr = MSR_P4_BSU_ESCR0 + stag;
+		     addr <= MSR_P4_BSU_ESCR1; ++i, addr += addr_increment()) {
+			msrs->controls[i].addr = addr;
+		}
+	} else {
+		for (addr = MSR_P4_IQ_ESCR0 + stag;
+		     addr <= MSR_P4_IQ_ESCR1; ++i, addr += addr_increment()) {
+			msrs->controls[i].addr = addr;
+		}
+	}
+
+	for (addr = MSR_P4_RAT_ESCR0 + stag;
+	     addr <= MSR_P4_SSU_ESCR0; ++i, addr += addr_increment()) {
 		msrs->controls[i].addr = addr;
 	}
 	
@@ -553,7 +572,18 @@
 
 	/* clear all escrs (including those outside our concern) */
 	for (addr = MSR_P4_BSU_ESCR0 + stag;
-	     addr <= MSR_P4_SSU_ESCR0; addr += addr_increment()) { 
+	     addr <  MSR_P4_IQ_ESCR0; addr += addr_increment()) {
+		wrmsr(addr, 0, 0);
+	}
+
+	/* On older models clear also MSR_P4_IQ_ESCR0/1 */
+	if (boot_cpu_data.x86_model < 0x3) {
+		wrmsr(MSR_P4_IQ_ESCR0, 0, 0);
+		wrmsr(MSR_P4_IQ_ESCR1, 0, 0);
+	}
+
+	for (addr = MSR_P4_RAT_ESCR0 + stag;
+	     addr <= MSR_P4_SSU_ESCR0; ++i, addr += addr_increment()) {
 		wrmsr(addr, 0, 0);
 	}
 	
@@ -578,7 +608,7 @@
 	
 	/* setup all counters */
 	for (i = 0 ; i < num_counters ; ++i) {
-		if (counter_config[i].event) {
+		if (counter_config[i].enabled) {
 			reset_value[i] = counter_config[i].count;
 			pmc_setup_one_p4_counter(i);
 			CTR_WRITE(counter_config[i].count, VIRT_CTR(stag, i));
@@ -595,7 +625,7 @@
 {
 	unsigned long ctr, low, high, stag, real;
 	int i;
-	unsigned long eip = instruction_pointer(regs);
+	unsigned long eip = profile_pc(regs);
 	int is_kernel = !user_mode(regs);
 
 	stag = get_stagger();
diff -Nru a/arch/i386/oprofile/op_model_ppro.c b/arch/i386/oprofile/op_model_ppro.c
--- a/arch/i386/oprofile/op_model_ppro.c	2004-10-18 14:56:48 -07:00
+++ b/arch/i386/oprofile/op_model_ppro.c	2004-10-18 14:56:48 -07:00
@@ -67,7 +67,7 @@
 
 	/* enable active counters */
 	for (i = 0; i < NUM_COUNTERS; ++i) {
-		if (counter_config[i].event) {
+		if (counter_config[i].enabled) {
 			reset_value[i] = counter_config[i].count;
 
 			CTR_WRITE(counter_config[i].count, msrs, i);
@@ -91,7 +91,7 @@
 {
 	unsigned int low, high;
 	int i;
-	unsigned long eip = instruction_pointer(regs);
+	unsigned long eip = profile_pc(regs);
 	int is_kernel = !user_mode(regs);
  
 	for (i = 0 ; i < NUM_COUNTERS; ++i) {
diff -Nru a/arch/i386/pci/common.c b/arch/i386/pci/common.c
--- a/arch/i386/pci/common.c	2004-10-18 14:56:29 -07:00
+++ b/arch/i386/pci/common.c	2004-10-18 14:56:29 -07:00
@@ -70,7 +70,7 @@
 	int i;
 
 	DBG("PCI: Scanning for ghost devices on bus %d\n", b->number);
-	for (ln=b->devices.next; ln != &b->devices; ln=ln->next) {
+	list_for_each(ln, &b->devices) {
 		d = pci_dev_b(ln);
 		if ((d->class >> 8) == PCI_CLASS_BRIDGE_HOST)
 			seen_host_bridge++;
diff -Nru a/arch/i386/pci/fixup.c b/arch/i386/pci/fixup.c
--- a/arch/i386/pci/fixup.c	2004-10-18 14:56:48 -07:00
+++ b/arch/i386/pci/fixup.c	2004-10-18 14:56:48 -07:00
@@ -29,6 +29,7 @@
 	}
 	pcibios_last_bus = -1;
 }
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82451NX, pci_fixup_i450nx);
 
 static void __devinit pci_fixup_i450gx(struct pci_dev *d)
 {
@@ -42,6 +43,7 @@
 	pci_scan_bus(busno, &pci_root_ops, NULL);
 	pcibios_last_bus = -1;
 }
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82454GX, pci_fixup_i450gx);
 
 static void __devinit  pci_fixup_umc_ide(struct pci_dev *d)
 {
@@ -55,6 +57,7 @@
 	for(i=0; i<4; i++)
 		d->resource[i].flags |= PCI_BASE_ADDRESS_SPACE_IO;
 }
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_UMC, PCI_DEVICE_ID_UMC_UM8886BF, pci_fixup_umc_ide);
 
 static void __devinit  pci_fixup_ncr53c810(struct pci_dev *d)
 {
@@ -67,6 +70,7 @@
 		d->class = PCI_CLASS_STORAGE_SCSI << 8;
 	}
 }
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_NCR, PCI_DEVICE_ID_NCR_53C810, pci_fixup_ncr53c810);
 
 static void __devinit pci_fixup_ide_bases(struct pci_dev *d)
 {
@@ -86,6 +90,7 @@
 		}
 	}
 }
+DECLARE_PCI_FIXUP_HEADER(PCI_ANY_ID, PCI_ANY_ID, pci_fixup_ide_bases);
 
 static void __devinit  pci_fixup_ide_trash(struct pci_dev *d)
 {
@@ -108,6 +113,10 @@
 	for(i=0; i<4; i++)
 		d->resource[i].start = d->resource[i].end = d->resource[i].flags = 0;
 }
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_5513, pci_fixup_ide_trash);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801CA_10, pci_fixup_ide_trash);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801CA_11, pci_fixup_ide_trash);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801DB_9, pci_fixup_ide_trash);
 
 static void __devinit  pci_fixup_latency(struct pci_dev *d)
 {
@@ -118,6 +127,8 @@
 	DBG("PCI: Setting max latency to 32\n");
 	pcibios_max_latency = 32;
 }
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_5597, pci_fixup_latency);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_5598, pci_fixup_latency);
 
 static void __devinit pci_fixup_piix4_acpi(struct pci_dev *d)
 {
@@ -126,6 +137,7 @@
 	 */
 	d->irq = 9;
 }
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371AB_3, pci_fixup_piix4_acpi);
 
 /*
  * Addresses issues with problems in the memory write queue timer in
@@ -179,6 +191,10 @@
 		pci_write_config_byte(d, where, v);
 	}
 }
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8363_0, pci_fixup_via_northbridge_bug);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8622, pci_fixup_via_northbridge_bug);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8361, pci_fixup_via_northbridge_bug);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8367_0, pci_fixup_via_northbridge_bug);
 
 /*
  * For some reasons Intel decided that certain parts of their
@@ -195,6 +211,7 @@
 	    (dev->device & 0xff00) == 0x2400)
 		dev->transparent = 1;
 }
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_ANY_ID, pci_fixup_transparent_bridge);
 
 /*
  * Fixup for C1 Halt Disconnect problem on nForce2 systems.
@@ -236,115 +253,5 @@
 		pci_write_config_dword(dev, 0x6c, fixed_val);
 	}
 }
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE2, pci_fixup_nforce2);
 
-struct pci_fixup pcibios_fixups[] = {
-	{
-		.pass		= PCI_FIXUP_HEADER,
-		.vendor		= PCI_VENDOR_ID_INTEL,
-		.device		= PCI_DEVICE_ID_INTEL_82451NX,
-		.hook		= pci_fixup_i450nx
-	},
-	{
-		.pass		= PCI_FIXUP_HEADER,
-		.vendor		= PCI_VENDOR_ID_INTEL,
-		.device		= PCI_DEVICE_ID_INTEL_82454GX,
-		.hook		= pci_fixup_i450gx
-	},
-	{
-		.pass		= PCI_FIXUP_HEADER,
-		.vendor		= PCI_VENDOR_ID_UMC,
-		.device		= PCI_DEVICE_ID_UMC_UM8886BF,
-		.hook		= pci_fixup_umc_ide
-	},
-	{
-		.pass		= PCI_FIXUP_HEADER,
-		.vendor		= PCI_VENDOR_ID_SI,
-		.device		= PCI_DEVICE_ID_SI_5513,
-		.hook		= pci_fixup_ide_trash
-	},
-	{
-		.pass		= PCI_FIXUP_HEADER,
-		.vendor		= PCI_ANY_ID,
-		.device		= PCI_ANY_ID,
-		.hook		= pci_fixup_ide_bases
-	},
-	{
-		.pass		= PCI_FIXUP_HEADER,
-		.vendor		= PCI_VENDOR_ID_SI,
-		.device		= PCI_DEVICE_ID_SI_5597,
-		.hook		= pci_fixup_latency
-	},
-	{
-		.pass		= PCI_FIXUP_HEADER,
-		.vendor		= PCI_VENDOR_ID_SI,
-		.device		= PCI_DEVICE_ID_SI_5598,
-		.hook		= pci_fixup_latency
-	},
- 	{
-		.pass		= PCI_FIXUP_HEADER,
-		.vendor		= PCI_VENDOR_ID_INTEL,
-		.device		= PCI_DEVICE_ID_INTEL_82371AB_3,
-		.hook		= pci_fixup_piix4_acpi
-	},
- 	{
-		.pass		= PCI_FIXUP_HEADER,
-		.vendor		= PCI_VENDOR_ID_INTEL,
-		.device		= PCI_DEVICE_ID_INTEL_82801CA_10,
-		.hook		= pci_fixup_ide_trash
-	},
- 	{
-		.pass		= PCI_FIXUP_HEADER,
-		.vendor		= PCI_VENDOR_ID_INTEL,
-		.device		= PCI_DEVICE_ID_INTEL_82801CA_11,
-		.hook		= pci_fixup_ide_trash
-	},
- 	{
-		.pass		= PCI_FIXUP_HEADER,
-		.vendor		= PCI_VENDOR_ID_INTEL,
-		.device		= PCI_DEVICE_ID_INTEL_82801DB_9,
-		.hook		= pci_fixup_ide_trash
-	},
-	{
-		.pass		= PCI_FIXUP_HEADER,
-		.vendor		= PCI_VENDOR_ID_VIA,
-		.device		= PCI_DEVICE_ID_VIA_8363_0,
-		.hook		= pci_fixup_via_northbridge_bug
-	},
-	{
-		.pass		= PCI_FIXUP_HEADER,
-		.vendor		= PCI_VENDOR_ID_VIA,
-		.device		= PCI_DEVICE_ID_VIA_8622,
-		.hook		= pci_fixup_via_northbridge_bug
-	},
-	{
-		.pass		= PCI_FIXUP_HEADER,
-		.vendor		= PCI_VENDOR_ID_VIA,
-		.device		= PCI_DEVICE_ID_VIA_8361,
-		.hook		= pci_fixup_via_northbridge_bug
-	},
-	{
-		.pass		= PCI_FIXUP_HEADER,
-		.vendor		= PCI_VENDOR_ID_VIA,
-		.device		= PCI_DEVICE_ID_VIA_8367_0,
-		.hook		= pci_fixup_via_northbridge_bug
-	},
-	{
-		.pass		= PCI_FIXUP_HEADER,
-		.vendor		= PCI_VENDOR_ID_NCR,
-		.device		= PCI_DEVICE_ID_NCR_53C810,
-		.hook		= pci_fixup_ncr53c810
-	},
-	{
-		.pass		= PCI_FIXUP_HEADER,
-		.vendor		= PCI_VENDOR_ID_INTEL,
-		.device		= PCI_ANY_ID,
-		.hook		= pci_fixup_transparent_bridge
-	},
-	{
-		.pass		= PCI_FIXUP_HEADER,
-		.vendor		= PCI_VENDOR_ID_NVIDIA,
-		.device		= PCI_DEVICE_ID_NVIDIA_NFORCE2,
-		.hook		= pci_fixup_nforce2
-	},
-	{ .pass = 0 }
-};
diff -Nru a/arch/i386/pci/i386.c b/arch/i386/pci/i386.c
--- a/arch/i386/pci/i386.c	2004-10-18 14:56:21 -07:00
+++ b/arch/i386/pci/i386.c	2004-10-18 14:56:21 -07:00
@@ -164,7 +164,7 @@
 	}
 }
 
-static void __init pcibios_assign_resources(void)
+static int __init pcibios_assign_resources(void)
 {
 	struct pci_dev *dev = NULL;
 	int idx;
@@ -204,6 +204,7 @@
 				pci_assign_resource(dev, PCI_ROM_RESOURCE);
 		}
 	}
+	return 0;
 }
 
 void __init pcibios_resource_survey(void)
@@ -212,8 +213,13 @@
 	pcibios_allocate_bus_resources(&pci_root_buses);
 	pcibios_allocate_resources(0);
 	pcibios_allocate_resources(1);
-	pcibios_assign_resources();
 }
+
+/**
+ * called in fs_initcall (one below subsys_initcall),
+ * give a chance for motherboard reserve resources
+ */
+fs_initcall(pcibios_assign_resources);
 
 int pcibios_enable_resources(struct pci_dev *dev, int mask)
 {
diff -Nru a/arch/i386/pci/mmconfig.c b/arch/i386/pci/mmconfig.c
--- a/arch/i386/pci/mmconfig.c	2004-10-18 14:56:48 -07:00
+++ b/arch/i386/pci/mmconfig.c	2004-10-18 14:56:48 -07:00
@@ -1,4 +1,11 @@
 /*
+ * Copyright (C) 2004 Matthew Wilcox <matthew@wil.cx>
+ * Copyright (C) 2004 Intel Corp.
+ *
+ * This code is released under the GNU General Public License version 2.
+ */
+
+/*
  * mmconfig.c - Low-level direct PCI config space access via MMCONFIG
  */
 
@@ -9,7 +16,7 @@
 /* The physical address of the MMCONFIG aperture.  Set from ACPI tables. */
 u32 pci_mmcfg_base_addr;
 
-#define mmcfg_virt_addr (fix_to_virt(FIX_PCIE_MCFG))
+#define mmcfg_virt_addr ((void __iomem *) fix_to_virt(FIX_PCIE_MCFG))
 
 /* The base address of the last MMCONFIG device accessed */
 static u32 mmcfg_last_accessed_device;
diff -Nru a/arch/i386/pci/numa.c b/arch/i386/pci/numa.c
--- a/arch/i386/pci/numa.c	2004-10-18 14:56:17 -07:00
+++ b/arch/i386/pci/numa.c	2004-10-18 14:56:17 -07:00
@@ -100,10 +100,7 @@
 	}
 	pcibios_last_bus = -1;
 }
-
-struct pci_fixup pcibios_fixups[] = {
-	{ PCI_FIXUP_HEADER,	PCI_VENDOR_ID_INTEL,	PCI_DEVICE_ID_INTEL_82451NX,	pci_fixup_i450nx },
-};
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82451NX, pci_fixup_i450nx);
 
 static int __init pci_numa_init(void)
 {
diff -Nru a/arch/i386/pci/pcbios.c b/arch/i386/pci/pcbios.c
--- a/arch/i386/pci/pcbios.c	2004-10-18 14:55:54 -07:00
+++ b/arch/i386/pci/pcbios.c	2004-10-18 14:55:54 -07:00
@@ -365,7 +365,7 @@
 		idx = found = 0;
 		while (pci_bios_find_device(dev->vendor, dev->device, idx, &bus, &devfn) == PCIBIOS_SUCCESSFUL) {
 			idx++;
-			for (ln=pci_devices.next; ln != &pci_devices; ln=ln->next) {
+			list_for_each(ln, &pci_devices) {
 				d = pci_dev_g(ln);
 				if (d->bus->number == bus && d->devfn == devfn) {
 					list_del(&d->global_list);
diff -Nru a/arch/i386/power/Makefile b/arch/i386/power/Makefile
--- a/arch/i386/power/Makefile	2004-10-18 14:56:27 -07:00
+++ b/arch/i386/power/Makefile	2004-10-18 14:56:27 -07:00
@@ -1,3 +1,2 @@
 obj-$(CONFIG_PM)		+= cpu.o
-obj-$(CONFIG_PM_DISK)		+= pmdisk.o
 obj-$(CONFIG_SOFTWARE_SUSPEND)	+= swsusp.o
diff -Nru a/arch/i386/power/cpu.c b/arch/i386/power/cpu.c
--- a/arch/i386/power/cpu.c	2004-10-18 14:56:49 -07:00
+++ b/arch/i386/power/cpu.c	2004-10-18 14:56:49 -07:00
@@ -83,10 +83,10 @@
 static void fix_processor_context(void)
 {
 	int cpu = smp_processor_id();
-	struct tss_struct * t = init_tss + cpu;
+	struct tss_struct * t = &per_cpu(init_tss, cpu);
 
 	set_tss_desc(cpu,t);	/* This just modifies memory; should not be necessary. But... This is necessary, because 386 hardware has concept of busy TSS or some similar stupidity. */
-        cpu_gdt_table[cpu][GDT_ENTRY_TSS].b &= 0xfffffdff;
+        per_cpu(cpu_gdt_table, cpu)[GDT_ENTRY_TSS].b &= 0xfffffdff;
 
 	load_TR_desc();				/* This does ltr */
 	load_LDT(&current->active_mm->context);	/* This does lldt */
diff -Nru a/arch/i386/power/pmdisk.S b/arch/i386/power/pmdisk.S
--- a/arch/i386/power/pmdisk.S	2004-10-18 14:56:32 -07:00
+++ /dev/null	Wed Dec 31 16:00:00 196900
@@ -1,56 +0,0 @@
-/* Originally gcc generated, modified by hand */
-
-#include <linux/linkage.h>
-#include <asm/segment.h>
-#include <asm/page.h>
-
-	.text
-
-ENTRY(pmdisk_arch_suspend)
-	cmpl $0,4(%esp)
-	jne .L1450
-
-	movl %esp, saved_context_esp
-	movl %ebx, saved_context_ebx
-	movl %ebp, saved_context_ebp
-	movl %esi, saved_context_esi
-	movl %edi, saved_context_edi
-	pushfl ; popl saved_context_eflags
-
-	call pmdisk_suspend
-	jmp .L1449
-	.p2align 4,,7
-.L1450:
-	movl $swsusp_pg_dir-__PAGE_OFFSET,%ecx
-	movl %ecx,%cr3
-
-	movl	pm_pagedir_nosave,%ebx
-	xorl	%eax, %eax
-	xorl	%edx, %edx
-	.p2align 4,,7
-.L1455:
-	movl	4(%ebx,%edx),%edi
-	movl	(%ebx,%edx),%esi
-
-	movl	$1024, %ecx
-	rep
-	movsl
-
-	movl	%cr3, %ecx;
-	movl	%ecx, %cr3;  # flush TLB 
-
-	incl	%eax
-	addl	$16, %edx
-	cmpl	pmdisk_pages,%eax
-	jb .L1455
-	.p2align 4,,7
-.L1453:
-	movl saved_context_esp, %esp
-	movl saved_context_ebp, %ebp
-	movl saved_context_ebx, %ebx
-	movl saved_context_esi, %esi
-	movl saved_context_edi, %edi
-	pushl saved_context_eflags ; popfl
-	call pmdisk_resume
-.L1449:
-	ret
diff -Nru a/arch/i386/power/swsusp.S b/arch/i386/power/swsusp.S
--- a/arch/i386/power/swsusp.S	2004-10-18 14:56:28 -07:00
+++ b/arch/i386/power/swsusp.S	2004-10-18 14:56:28 -07:00
@@ -15,83 +15,47 @@
 
 	.text
 
-ENTRY(do_magic)
-	pushl %ebx
-	cmpl $0,8(%esp)
-	jne resume
-	call do_magic_suspend_1
-	call save_processor_state
+ENTRY(swsusp_arch_suspend)
 
 	movl %esp, saved_context_esp
-	movl %eax, saved_context_eax
 	movl %ebx, saved_context_ebx
-	movl %ecx, saved_context_ecx
-	movl %edx, saved_context_edx
 	movl %ebp, saved_context_ebp
 	movl %esi, saved_context_esi
 	movl %edi, saved_context_edi
 	pushfl ; popl saved_context_eflags
 
-	call do_magic_suspend_2
-	popl %ebx
+	call swsusp_save
 	ret
 
-resume:
+ENTRY(swsusp_arch_resume)
 	movl $swsusp_pg_dir-__PAGE_OFFSET,%ecx
 	movl %ecx,%cr3
 
-	call do_magic_resume_1
-	movl $0,loop
-	cmpl $0,nr_copy_pages
-	je copy_done
-copy_loop:
-	movl $0,loop2
+	movl	pagedir_nosave, %ebx
+	xorl	%eax, %eax
+	xorl	%edx, %edx
 	.p2align 4,,7
-copy_one_page:
-	movl pagedir_nosave,%ecx
-	movl loop,%eax
-	movl loop2,%edx
-	sall $4,%eax
-	movl 4(%ecx,%eax),%ebx
-	movl (%ecx,%eax),%eax
-	movb (%edx,%eax),%al
-	movb %al,(%edx,%ebx)
-
-	movl loop2,%eax
-	leal 1(%eax),%edx
-	movl %edx,loop2
-	movl %edx,%eax
-	cmpl $4095,%eax
-	jbe copy_one_page
-	movl loop,%eax
-	leal 1(%eax),%edx
-	movl %edx,loop
-	movl %edx,%eax
-	cmpl nr_copy_pages,%eax
-	jb copy_loop
 
-copy_done:
-	movl $__USER_DS,%eax
+copy_loop:
+	movl	4(%ebx,%edx),%edi
+	movl	(%ebx,%edx),%esi
+
+	movl	$1024, %ecx
+	rep
+	movsl
+
+	incl	%eax
+	addl	$16, %edx
+	cmpl	nr_copy_pages,%eax
+	jb copy_loop
+	.p2align 4,,7
 
-	movw %ax, %ds
-	movw %ax, %es
 	movl saved_context_esp, %esp
 	movl saved_context_ebp, %ebp
-	movl saved_context_eax, %eax
 	movl saved_context_ebx, %ebx
-	movl saved_context_ecx, %ecx
-	movl saved_context_edx, %edx
 	movl saved_context_esi, %esi
 	movl saved_context_edi, %edi
-	call restore_processor_state
+
 	pushl saved_context_eflags ; popfl
-	call do_magic_resume_2
-	popl %ebx
+	call swsusp_restore
 	ret
-
-       .section .data.nosave
-loop:
-       .quad 0
-loop2:
-       .quad 0
-       .previous
diff -Nru a/arch/ia64/Kconfig b/arch/ia64/Kconfig
--- a/arch/ia64/Kconfig	2004-10-18 14:57:04 -07:00
+++ b/arch/ia64/Kconfig	2004-10-18 14:57:04 -07:00
@@ -38,6 +38,10 @@
 	bool
 	default y
 
+config GENERIC_IOMAP
+	bool
+	default y
+
 choice
 	prompt "System type"
 	default IA64_GENERIC
@@ -72,6 +76,12 @@
 
 config IA64_SGI_SN2
 	bool "SGI-SN2"
+	help
+	  Selecting this option will optimize the kernel for use on sn2 based
+	  systems, but the resulting kernel binary will not run on other
+	  types of ia64 systems.  If you have an SGI Altix system, it's safe
+	  to select this option.  If in doubt, select ia64 generic support
+	  instead.
 
 config IA64_HP_SIM
 	bool "Ski-simulator"
@@ -270,6 +280,9 @@
 	depends on IA32_SUPPORT
 	default y
 
+config IA64_MCA_RECOVERY
+	tristate "MCA recovery from errors other than TLB."
+
 config PERFMON
 	bool "Performance monitor support"
 	help
@@ -372,119 +385,7 @@
 
 source "arch/ia64/oprofile/Kconfig"
 
-menu "Kernel hacking"
-
-choice
-	prompt "Physical memory granularity"
-	default IA64_GRANULE_64MB
-
-config IA64_GRANULE_16MB
-	bool "16MB"
-	help
-	  IA-64 identity-mapped regions use a large page size called "granules".
-
-	  Select "16MB" for a small granule size.
-	  Select "64MB" for a large granule size.  This is the current default.
-
-config IA64_GRANULE_64MB
-	bool "64MB"
-	depends on !(IA64_GENERIC || IA64_HP_ZX1 || IA64_SGI_SN2)
-
-endchoice
-
-config DEBUG_KERNEL
-	bool "Kernel debugging"
-	help
-	  Say Y here if you are developing drivers or trying to debug and
-	  identify kernel problems.
-
-config IA64_PRINT_HAZARDS
-	bool "Print possible IA-64 dependency violations to console"
-	depends on DEBUG_KERNEL
-	help
-	  Selecting this option prints more information for Illegal Dependency
-	  Faults, that is, for Read-after-Write (RAW), Write-after-Write (WAW),
-	  or Write-after-Read (WAR) violations.  This option is ignored if you
-	  are compiling for an Itanium A step processor
-	  (CONFIG_ITANIUM_ASTEP_SPECIFIC).  If you're unsure, select Y.
-
-config DISABLE_VHPT
-	bool "Disable VHPT"
-	depends on DEBUG_KERNEL
-	help
-	  The Virtual Hash Page Table (VHPT) enhances virtual address
-	  translation performance.  Normally you want the VHPT active but you
-	  can select this option to disable the VHPT for debugging.  If you're
-	  unsure, answer N.
-
-config MAGIC_SYSRQ
-	bool "Magic SysRq key"
-	depends on DEBUG_KERNEL
-	help
-	  If you say Y here, you will have some control over the system even
-	  if the system crashes for example during kernel debugging (e.g., you
-	  will be able to flush the buffer cache to disk, reboot the system
-	  immediately or dump some status information). This is accomplished
-	  by pressing various keys while holding SysRq (Alt+PrintScreen). It
-	  also works on a serial console (on PC hardware at least), if you
-	  send a BREAK and then within 5 seconds a command keypress. The
-	  keys are documented in <file:Documentation/sysrq.txt>. Don't say Y
-	  unless you really know what this hack does.
-
-config DEBUG_SLAB
-	bool "Debug memory allocations"
-	depends on DEBUG_KERNEL
-	help
-	  Say Y here to have the kernel do limited verification on memory
-	  allocation as well as poisoning memory on free to catch use of freed
-	  memory.
-
-config DEBUG_SPINLOCK
-	bool "Spinlock debugging"
-	depends on DEBUG_KERNEL
-	help
-	  Say Y here and build SMP to catch missing spinlock initialization
-	  and certain other kinds of spinlock errors commonly made.  This is
-	  best used in conjunction with the NMI watchdog so that spinlock
-	  deadlocks are also debuggable.
-
-config DEBUG_SPINLOCK_SLEEP
-	  bool "Sleep-inside-spinlock checking"
-	  help
-	    If you say Y here, various routines which may sleep will become very
-	    noisy if they are called with a spinlock held.
-
-config IA64_DEBUG_CMPXCHG
-	bool "Turn on compare-and-exchange bug checking (slow!)"
-	depends on DEBUG_KERNEL
-	help
-	  Selecting this option turns on bug checking for the IA-64
-	  compare-and-exchange instructions.  This is slow!  Itaniums
-	  from step B3 or later don't have this problem. If you're unsure,
-	  select N.
-
-config IA64_DEBUG_IRQ
-	bool "Turn on irq debug checks (slow!)"
-	depends on DEBUG_KERNEL
-	help
-	  Selecting this option turns on bug checking for the IA-64 irq_save
-	  and restore instructions.  It's useful for tracking down spinlock
-	  problems, but slow!  If you're unsure, select N.
-
-config DEBUG_INFO
-	bool "Compile the kernel with debug info"
-	depends on DEBUG_KERNEL
-	help
-          If you say Y here the resulting kernel image will include
-	  debugging info resulting in a larger kernel image.
-	  Say Y here only if you plan to use gdb to debug the kernel.
-	  If you don't debug the kernel, you can say N.
-
-config SYSVIPC_COMPAT
-	bool
-	depends on COMPAT && SYSVIPC
-	default y
-endmenu
+source "arch/ia64/Kconfig.debug"
 
 source "security/Kconfig"
 
diff -Nru a/arch/ia64/Kconfig.debug b/arch/ia64/Kconfig.debug
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/arch/ia64/Kconfig.debug	2004-10-18 14:57:23 -07:00
@@ -0,0 +1,64 @@
+menu "Kernel hacking"
+
+source "lib/Kconfig.debug"
+
+choice
+	prompt "Physical memory granularity"
+	default IA64_GRANULE_64MB
+
+config IA64_GRANULE_16MB
+	bool "16MB"
+	help
+	  IA-64 identity-mapped regions use a large page size called "granules".
+
+	  Select "16MB" for a small granule size.
+	  Select "64MB" for a large granule size.  This is the current default.
+
+config IA64_GRANULE_64MB
+	bool "64MB"
+	depends on !(IA64_GENERIC || IA64_HP_ZX1 || IA64_SGI_SN2)
+
+endchoice
+
+config IA64_PRINT_HAZARDS
+	bool "Print possible IA-64 dependency violations to console"
+	depends on DEBUG_KERNEL
+	help
+	  Selecting this option prints more information for Illegal Dependency
+	  Faults, that is, for Read-after-Write (RAW), Write-after-Write (WAW),
+	  or Write-after-Read (WAR) violations.  This option is ignored if you
+	  are compiling for an Itanium A step processor
+	  (CONFIG_ITANIUM_ASTEP_SPECIFIC).  If you're unsure, select Y.
+
+config DISABLE_VHPT
+	bool "Disable VHPT"
+	depends on DEBUG_KERNEL
+	help
+	  The Virtual Hash Page Table (VHPT) enhances virtual address
+	  translation performance.  Normally you want the VHPT active but you
+	  can select this option to disable the VHPT for debugging.  If you're
+	  unsure, answer N.
+
+config IA64_DEBUG_CMPXCHG
+	bool "Turn on compare-and-exchange bug checking (slow!)"
+	depends on DEBUG_KERNEL
+	help
+	  Selecting this option turns on bug checking for the IA-64
+	  compare-and-exchange instructions.  This is slow!  Itaniums
+	  from step B3 or later don't have this problem. If you're unsure,
+	  select N.
+
+config IA64_DEBUG_IRQ
+	bool "Turn on irq debug checks (slow!)"
+	depends on DEBUG_KERNEL
+	help
+	  Selecting this option turns on bug checking for the IA-64 irq_save
+	  and restore instructions.  It's useful for tracking down spinlock
+	  problems, but slow!  If you're unsure, select N.
+
+config SYSVIPC_COMPAT
+	bool
+	depends on COMPAT && SYSVIPC
+	default y
+
+endmenu
diff -Nru a/arch/ia64/Makefile b/arch/ia64/Makefile
--- a/arch/ia64/Makefile	2004-10-18 14:55:54 -07:00
+++ b/arch/ia64/Makefile	2004-10-18 14:55:54 -07:00
@@ -13,6 +13,8 @@
 
 export AWK
 
+CHECKFLAGS	+= -m64 -D__ia64=1 -D__ia64__=1 -D_LP64 -D__LP64__
+
 OBJCOPYFLAGS	:= --strip-all
 LDFLAGS_vmlinux	:= -static
 LDFLAGS_MODULE	+= -T $(srctree)/arch/ia64/module.lds
@@ -20,14 +22,12 @@
 EXTRA		:=
 
 cflags-y	:= -pipe $(EXTRA) -ffixed-r13 -mfixed-range=f12-f15,f32-f127 \
-		   -falign-functions=32 -frename-registers
+		   -falign-functions=32 -frename-registers -fno-optimize-sibling-calls
 CFLAGS_KERNEL	:= -mconstant-gp
 
-GCC_VERSION=$(shell $(CC) -v 2>&1 | fgrep 'gcc version' | cut -f3 -d' ' | cut -f1 -d'.')
-GCC_MINOR_VERSION=$(shell $(CC) -v 2>&1 | fgrep 'gcc version' | cut -f3 -d' ' | cut -f2 -d'.')
-
-GAS_STATUS	= $(shell $(srctree)/arch/ia64/scripts/check-gas $(CC) $(OBJDUMP))
-CPPFLAGS += $(shell $(srctree)/arch/ia64/scripts/toolchain-flags $(CC) $(OBJDUMP) $(READELF))
+GCC_VERSION     := $(call cc-version)
+GAS_STATUS	= $(shell $(srctree)/arch/ia64/scripts/check-gas "$(CC)" "$(OBJDUMP)")
+CPPFLAGS += $(shell $(srctree)/arch/ia64/scripts/toolchain-flags "$(CC)" "$(OBJDUMP)" "$(READELF)")
 
 ifeq ($(GAS_STATUS),buggy)
 $(error Sorry, you need a newer version of the assember, one that is built from	\
@@ -37,16 +37,14 @@
 		ftp://ftp.hpl.hp.com/pub/linux-ia64/gas-030124.tar.gz)
 endif
 
-ifeq ($(GCC_VERSION),2)
+ifneq ($(shell if [ $(GCC_VERSION) -lt 0300 ] ; then echo "bad"; fi ;),)
 $(error Sorry, your compiler is too old.  GCC v2.96 is known to generate bad code.)
 endif
 
-ifeq ($(GCC_VERSION),3)
- ifeq ($(GCC_MINOR_VERSION),4)
+ifeq ($(GCC_VERSION),0304)
 # Workaround Itanium 1 bugs in gcc 3.4.
 #	cflags-$(CONFIG_ITANIUM)	+= -mtune=merced
 	cflags-$(CONFIG_MCKINLEY)	+= -mtune=mckinley
- endif
 endif
 
 cflags-$(CONFIG_ITANIUM_BSTEP_SPECIFIC)	+= -mb-step
diff -Nru a/arch/ia64/configs/bigsur_defconfig b/arch/ia64/configs/bigsur_defconfig
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/arch/ia64/configs/bigsur_defconfig	2004-10-18 14:57:21 -07:00
@@ -0,0 +1,1132 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.9-rc2
+# Tue Sep 28 13:26:53 2004
+#
+
+#
+# Code maturity level options
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_CLEAN_COMPILE=y
+
+#
+# General setup
+#
+CONFIG_LOCALVERSION=""
+CONFIG_SWAP=y
+CONFIG_SYSVIPC=y
+CONFIG_POSIX_MQUEUE=y
+# CONFIG_BSD_PROCESS_ACCT is not set
+CONFIG_SYSCTL=y
+# CONFIG_AUDIT is not set
+CONFIG_LOG_BUF_SHIFT=16
+CONFIG_HOTPLUG=y
+# 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_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+CONFIG_SHMEM=y
+# CONFIG_TINY_SHMEM is not set
+
+#
+# Loadable module support
+#
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+# CONFIG_MODULE_FORCE_UNLOAD is not set
+CONFIG_OBSOLETE_MODPARM=y
+# CONFIG_MODVERSIONS is not set
+CONFIG_KMOD=y
+CONFIG_STOP_MACHINE=y
+
+#
+# Processor type and features
+#
+CONFIG_IA64=y
+CONFIG_64BIT=y
+CONFIG_MMU=y
+CONFIG_RWSEM_XCHGADD_ALGORITHM=y
+CONFIG_TIME_INTERPOLATION=y
+CONFIG_EFI=y
+CONFIG_GENERIC_IOMAP=y
+# CONFIG_IA64_GENERIC is not set
+CONFIG_IA64_DIG=y
+# CONFIG_IA64_HP_ZX1 is not set
+# CONFIG_IA64_SGI_SN2 is not set
+# CONFIG_IA64_HP_SIM is not set
+CONFIG_ITANIUM=y
+# CONFIG_MCKINLEY is not set
+# CONFIG_IA64_PAGE_SIZE_4KB is not set
+# CONFIG_IA64_PAGE_SIZE_8KB is not set
+CONFIG_IA64_PAGE_SIZE_16KB=y
+# CONFIG_IA64_PAGE_SIZE_64KB is not set
+CONFIG_IA64_BRL_EMU=y
+# CONFIG_ITANIUM_BSTEP_SPECIFIC is not set
+CONFIG_IA64_L1_CACHE_SHIFT=6
+# CONFIG_NUMA is not set
+# CONFIG_VIRTUAL_MEM_MAP is not set
+# CONFIG_IA64_CYCLONE is not set
+CONFIG_IOSAPIC=y
+CONFIG_FORCE_MAX_ZONEORDER=18
+CONFIG_SMP=y
+CONFIG_NR_CPUS=2
+# CONFIG_HOTPLUG_CPU is not set
+CONFIG_PREEMPT=y
+CONFIG_HAVE_DEC_LOCK=y
+CONFIG_IA32_SUPPORT=y
+CONFIG_COMPAT=y
+CONFIG_PERFMON=y
+CONFIG_IA64_PALINFO=y
+
+#
+# Firmware Drivers
+#
+CONFIG_EFI_VARS=y
+CONFIG_EFI_PCDP=y
+CONFIG_BINFMT_ELF=y
+CONFIG_BINFMT_MISC=m
+
+#
+# Power management and ACPI
+#
+CONFIG_PM=y
+CONFIG_ACPI=y
+
+#
+# ACPI (Advanced Configuration and Power Interface) Support
+#
+CONFIG_ACPI_BOOT=y
+CONFIG_ACPI_INTERPRETER=y
+CONFIG_ACPI_BUTTON=m
+CONFIG_ACPI_FAN=m
+CONFIG_ACPI_PROCESSOR=m
+CONFIG_ACPI_THERMAL=m
+# CONFIG_ACPI_DEBUG is not set
+CONFIG_ACPI_BUS=y
+CONFIG_ACPI_POWER=y
+CONFIG_ACPI_PCI=y
+CONFIG_ACPI_SYSTEM=y
+
+#
+# Bus options (PCI, PCMCIA)
+#
+CONFIG_PCI=y
+CONFIG_PCI_DOMAINS=y
+# CONFIG_PCI_MSI is not set
+CONFIG_PCI_LEGACY_PROC=y
+CONFIG_PCI_NAMES=y
+
+#
+# PCI Hotplug Support
+#
+# CONFIG_HOTPLUG_PCI is not set
+
+#
+# PCMCIA/CardBus support
+#
+# CONFIG_PCMCIA is not set
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+# CONFIG_FW_LOADER is not set
+# CONFIG_DEBUG_DRIVER is not set
+
+#
+# Memory Technology Devices (MTD)
+#
+# CONFIG_MTD is not set
+
+#
+# Parallel port support
+#
+# CONFIG_PARPORT is not set
+
+#
+# Plug and Play support
+#
+
+#
+# Block devices
+#
+# CONFIG_BLK_CPQ_DA is not set
+# CONFIG_BLK_CPQ_CISS_DA is not set
+# CONFIG_BLK_DEV_DAC960 is not set
+# CONFIG_BLK_DEV_UMEM is not set
+CONFIG_BLK_DEV_LOOP=m
+CONFIG_BLK_DEV_CRYPTOLOOP=m
+CONFIG_BLK_DEV_NBD=m
+# CONFIG_BLK_DEV_SX8 is not set
+# CONFIG_BLK_DEV_UB is not set
+CONFIG_BLK_DEV_RAM=m
+CONFIG_BLK_DEV_RAM_SIZE=4096
+
+#
+# ATA/ATAPI/MFM/RLL support
+#
+CONFIG_IDE=m
+CONFIG_BLK_DEV_IDE=m
+
+#
+# Please see Documentation/ide.txt for help/info on IDE drives
+#
+# CONFIG_BLK_DEV_IDE_SATA is not set
+CONFIG_BLK_DEV_IDEDISK=m
+# CONFIG_IDEDISK_MULTI_MODE is not set
+CONFIG_BLK_DEV_IDECD=m
+# CONFIG_BLK_DEV_IDETAPE is not set
+CONFIG_BLK_DEV_IDEFLOPPY=m
+# 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=m
+CONFIG_BLK_DEV_IDEPCI=y
+CONFIG_IDEPCI_SHARE_IRQ=y
+# CONFIG_BLK_DEV_OFFBOARD is not set
+CONFIG_BLK_DEV_GENERIC=m
+# CONFIG_BLK_DEV_OPTI621 is not set
+CONFIG_BLK_DEV_IDEDMA_PCI=y
+# CONFIG_BLK_DEV_IDEDMA_FORCED is not set
+CONFIG_IDEDMA_PCI_AUTO=y
+# CONFIG_IDEDMA_ONLYDISK is not set
+# CONFIG_BLK_DEV_AEC62XX is not set
+# CONFIG_BLK_DEV_ALI15X3 is not set
+# CONFIG_BLK_DEV_AMD74XX is not set
+# CONFIG_BLK_DEV_CMD64X is not set
+# CONFIG_BLK_DEV_TRIFLEX is not set
+# CONFIG_BLK_DEV_CY82C693 is not set
+# CONFIG_BLK_DEV_CS5520 is not set
+# CONFIG_BLK_DEV_CS5530 is not set
+# CONFIG_BLK_DEV_HPT34X is not set
+# CONFIG_BLK_DEV_HPT366 is not set
+# CONFIG_BLK_DEV_SC1200 is not set
+CONFIG_BLK_DEV_PIIX=m
+# CONFIG_BLK_DEV_NS87415 is not set
+# CONFIG_BLK_DEV_PDC202XX_OLD is not set
+# CONFIG_BLK_DEV_PDC202XX_NEW is not set
+# CONFIG_BLK_DEV_SVWKS is not set
+# CONFIG_BLK_DEV_SIIMAGE 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_IDE_ARM is not set
+CONFIG_BLK_DEV_IDEDMA=y
+# CONFIG_IDEDMA_IVB is not set
+CONFIG_IDEDMA_AUTO=y
+# CONFIG_BLK_DEV_HD is not set
+
+#
+# SCSI device support
+#
+CONFIG_SCSI=y
+CONFIG_SCSI_PROC_FS=y
+
+#
+# SCSI support type (disk, tape, CD-ROM)
+#
+CONFIG_BLK_DEV_SD=y
+# CONFIG_CHR_DEV_ST is not set
+# CONFIG_CHR_DEV_OSST is not set
+# CONFIG_BLK_DEV_SR is not set
+# CONFIG_CHR_DEV_SG is not set
+
+#
+# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
+#
+# CONFIG_SCSI_MULTI_LUN is not set
+CONFIG_SCSI_CONSTANTS=y
+CONFIG_SCSI_LOGGING=y
+
+#
+# SCSI Transport Attributes
+#
+CONFIG_SCSI_SPI_ATTRS=m
+# 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_MEGARAID_NEWGEN is not set
+# CONFIG_MEGARAID_LEGACY is not set
+# CONFIG_SCSI_SATA is not set
+# CONFIG_SCSI_BUSLOGIC 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_IPS is not set
+# CONFIG_SCSI_INIA100 is not set
+# CONFIG_SCSI_SYM53C8XX_2 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=y
+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_DEBUG is not set
+
+#
+# Multi-device support (RAID and LVM)
+#
+CONFIG_MD=y
+CONFIG_BLK_DEV_MD=m
+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
+CONFIG_BLK_DEV_DM=m
+CONFIG_DM_CRYPT=m
+CONFIG_DM_SNAPSHOT=m
+CONFIG_DM_MIRROR=m
+CONFIG_DM_ZERO=m
+
+#
+# Fusion MPT device support
+#
+# CONFIG_FUSION is not set
+
+#
+# IEEE 1394 (FireWire) support
+#
+# CONFIG_IEEE1394 is not set
+
+#
+# I2O device support
+#
+# CONFIG_I2O is not set
+
+#
+# Networking support
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+CONFIG_PACKET=y
+CONFIG_PACKET_MMAP=y
+# CONFIG_NETLINK_DEV is not set
+CONFIG_UNIX=y
+# CONFIG_NET_KEY is not set
+CONFIG_INET=y
+# CONFIG_IP_MULTICAST is not set
+# CONFIG_IP_ADVANCED_ROUTER is not set
+# CONFIG_IP_PNP is not set
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+# CONFIG_ARPD 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
+# CONFIG_INET_TUNNEL is not set
+# CONFIG_IPV6 is not set
+# CONFIG_NETFILTER is not set
+
+#
+# SCTP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_SCTP is not set
+# CONFIG_ATM is not set
+# CONFIG_BRIDGE is not set
+# CONFIG_VLAN_8021Q is not set
+# CONFIG_DECNET 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
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+# CONFIG_NET_HW_FLOWCONTROL is not set
+
+#
+# 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=y
+# CONFIG_BONDING is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
+
+#
+# ARCnet devices
+#
+# CONFIG_ARCNET is not set
+
+#
+# Ethernet (10 or 100Mbit)
+#
+CONFIG_NET_ETHERNET=y
+CONFIG_MII=y
+# CONFIG_HAPPYMEAL is not set
+# CONFIG_SUNGEM is not set
+# CONFIG_NET_VENDOR_3COM is not set
+
+#
+# Tulip family network device support
+#
+# CONFIG_NET_TULIP is not set
+# CONFIG_HP100 is not set
+CONFIG_NET_PCI=y
+# CONFIG_PCNET32 is not set
+# 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_FEALNX is not set
+# CONFIG_NATSEMI is not set
+# CONFIG_NE2K_PCI 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)
+#
+# CONFIG_ACENIC is not set
+# CONFIG_DL2K is not set
+# CONFIG_E1000 is not set
+# CONFIG_NS83820 is not set
+# CONFIG_HAMACHI is not set
+# CONFIG_YELLOWFIN is not set
+# CONFIG_R8169 is not set
+# CONFIG_SK98LIN is not set
+# CONFIG_TIGON3 is not set
+
+#
+# Ethernet (10000 Mbit)
+#
+# CONFIG_IXGB is not set
+# CONFIG_S2IO is not set
+
+#
+# Token Ring devices
+#
+# CONFIG_TR is not set
+
+#
+# Wireless LAN (non-hamradio)
+#
+# CONFIG_NET_RADIO is not set
+
+#
+# Wan interfaces
+#
+# CONFIG_WAN 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 is not set
+
+#
+# Telephony Support
+#
+# CONFIG_PHONE is not set
+
+#
+# Input device support
+#
+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=y
+# CONFIG_INPUT_EVBUG is not set
+
+#
+# Input I/O drivers
+#
+# CONFIG_GAMEPORT is not set
+CONFIG_SOUND_GAMEPORT=y
+CONFIG_SERIO=y
+CONFIG_SERIO_I8042=y
+CONFIG_SERIO_SERPORT=y
+# CONFIG_SERIO_CT82C710 is not set
+# CONFIG_SERIO_PCIPS2 is not set
+# CONFIG_SERIO_RAW is not set
+
+#
+# Input 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
+
+#
+# Serial drivers
+#
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
+# CONFIG_SERIAL_8250_ACPI is not set
+CONFIG_SERIAL_8250_NR_UARTS=4
+CONFIG_SERIAL_8250_EXTENDED=y
+CONFIG_SERIAL_8250_SHARE_IRQ=y
+# CONFIG_SERIAL_8250_DETECT_IRQ is not set
+# CONFIG_SERIAL_8250_MULTIPORT is not set
+# CONFIG_SERIAL_8250_RSA is not set
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+CONFIG_UNIX98_PTYS=y
+CONFIG_LEGACY_PTYS=y
+CONFIG_LEGACY_PTY_COUNT=256
+
+#
+# IPMI
+#
+# CONFIG_IPMI_HANDLER is not set
+
+#
+# Watchdog Cards
+#
+# CONFIG_WATCHDOG is not set
+# CONFIG_HW_RANDOM is not set
+CONFIG_EFI_RTC=y
+# CONFIG_DTLK is not set
+# CONFIG_R3964 is not set
+# CONFIG_APPLICOM is not set
+
+#
+# Ftape, the floppy tape device driver
+#
+CONFIG_AGP=m
+CONFIG_AGP_I460=m
+CONFIG_DRM=y
+# CONFIG_DRM_TDFX is not set
+CONFIG_DRM_R128=m
+# CONFIG_DRM_RADEON is not set
+# CONFIG_DRM_MGA is not set
+# CONFIG_DRM_SIS is not set
+# CONFIG_RAW_DRIVER is not set
+# CONFIG_HPET is not set
+
+#
+# I2C support
+#
+CONFIG_I2C=y
+CONFIG_I2C_CHARDEV=y
+
+#
+# I2C Algorithms
+#
+CONFIG_I2C_ALGOBIT=y
+# CONFIG_I2C_ALGOPCF is not set
+# CONFIG_I2C_ALGOPCA is not set
+
+#
+# I2C Hardware Bus support
+#
+# CONFIG_I2C_ALI1535 is not set
+# CONFIG_I2C_ALI1563 is not set
+# CONFIG_I2C_ALI15X3 is not set
+# CONFIG_I2C_AMD756 is not set
+# CONFIG_I2C_AMD8111 is not set
+# CONFIG_I2C_I801 is not set
+# CONFIG_I2C_I810 is not set
+# CONFIG_I2C_ISA is not set
+# CONFIG_I2C_NFORCE2 is not set
+# CONFIG_I2C_PARPORT_LIGHT is not set
+# CONFIG_I2C_PROSAVAGE is not set
+# CONFIG_I2C_SAVAGE4 is not set
+# CONFIG_SCx200_ACB is not set
+# CONFIG_I2C_SIS5595 is not set
+# CONFIG_I2C_SIS630 is not set
+# CONFIG_I2C_SIS96X is not set
+# CONFIG_I2C_VIA is not set
+# CONFIG_I2C_VIAPRO is not set
+# CONFIG_I2C_VOODOO3 is not set
+# CONFIG_I2C_PCA_ISA is not set
+
+#
+# Hardware Sensors Chip support
+#
+# CONFIG_I2C_SENSOR is not set
+# CONFIG_SENSORS_ADM1021 is not set
+# CONFIG_SENSORS_ADM1025 is not set
+# CONFIG_SENSORS_ADM1031 is not set
+# CONFIG_SENSORS_ASB100 is not set
+# CONFIG_SENSORS_DS1621 is not set
+# CONFIG_SENSORS_FSCHER is not set
+# CONFIG_SENSORS_GL518SM is not set
+# CONFIG_SENSORS_IT87 is not set
+# CONFIG_SENSORS_LM75 is not set
+# CONFIG_SENSORS_LM77 is not set
+# CONFIG_SENSORS_LM78 is not set
+# CONFIG_SENSORS_LM80 is not set
+# CONFIG_SENSORS_LM83 is not set
+# CONFIG_SENSORS_LM85 is not set
+# CONFIG_SENSORS_LM90 is not set
+# CONFIG_SENSORS_MAX1619 is not set
+# CONFIG_SENSORS_SMSC47M1 is not set
+# CONFIG_SENSORS_VIA686A is not set
+# CONFIG_SENSORS_W83781D is not set
+# CONFIG_SENSORS_W83L785TS is not set
+# CONFIG_SENSORS_W83627HF is not set
+
+#
+# Other I2C Chip support
+#
+# CONFIG_SENSORS_EEPROM is not set
+# CONFIG_SENSORS_PCF8574 is not set
+# CONFIG_SENSORS_PCF8591 is not set
+# CONFIG_SENSORS_RTC8564 is not set
+# CONFIG_I2C_DEBUG_CORE is not set
+# CONFIG_I2C_DEBUG_ALGO is not set
+# CONFIG_I2C_DEBUG_BUS is not set
+# CONFIG_I2C_DEBUG_CHIP is not set
+
+#
+# Dallas's 1-wire bus
+#
+# CONFIG_W1 is not set
+
+#
+# Misc devices
+#
+
+#
+# Multimedia devices
+#
+# CONFIG_VIDEO_DEV is not set
+
+#
+# Digital Video Broadcasting Devices
+#
+# CONFIG_DVB is not set
+
+#
+# Graphics support
+#
+# CONFIG_FB is not set
+
+#
+# Console display driver support
+#
+CONFIG_VGA_CONSOLE=y
+CONFIG_DUMMY_CONSOLE=y
+
+#
+# Sound
+#
+CONFIG_SOUND=m
+
+#
+# Advanced Linux Sound Architecture
+#
+CONFIG_SND=m
+CONFIG_SND_TIMER=m
+CONFIG_SND_PCM=m
+CONFIG_SND_HWDEP=m
+CONFIG_SND_RAWMIDI=m
+CONFIG_SND_SEQUENCER=m
+# CONFIG_SND_SEQ_DUMMY is not set
+CONFIG_SND_OSSEMUL=y
+CONFIG_SND_MIXER_OSS=m
+CONFIG_SND_PCM_OSS=m
+# CONFIG_SND_SEQUENCER_OSS is not set
+# CONFIG_SND_VERBOSE_PRINTK is not set
+# CONFIG_SND_DEBUG is not set
+
+#
+# Generic devices
+#
+CONFIG_SND_OPL3_LIB=m
+# CONFIG_SND_DUMMY is not set
+# CONFIG_SND_VIRMIDI is not set
+# CONFIG_SND_MTPAV is not set
+# CONFIG_SND_SERIAL_U16550 is not set
+# CONFIG_SND_MPU401 is not set
+
+#
+# PCI devices
+#
+CONFIG_SND_AC97_CODEC=m
+# CONFIG_SND_ALI5451 is not set
+# CONFIG_SND_ATIIXP is not set
+# CONFIG_SND_ATIIXP_MODEM is not set
+# CONFIG_SND_AU8810 is not set
+# CONFIG_SND_AU8820 is not set
+# CONFIG_SND_AU8830 is not set
+# CONFIG_SND_AZT3328 is not set
+# CONFIG_SND_BT87X is not set
+# CONFIG_SND_CS46XX is not set
+CONFIG_SND_CS4281=m
+# CONFIG_SND_EMU10K1 is not set
+# CONFIG_SND_KORG1212 is not set
+# CONFIG_SND_MIXART is not set
+# CONFIG_SND_NM256 is not set
+# CONFIG_SND_RME32 is not set
+# CONFIG_SND_RME96 is not set
+# CONFIG_SND_RME9652 is not set
+# CONFIG_SND_HDSP is not set
+# CONFIG_SND_TRIDENT is not set
+# CONFIG_SND_YMFPCI is not set
+# CONFIG_SND_ALS4000 is not set
+# CONFIG_SND_CMIPCI is not set
+# CONFIG_SND_ENS1370 is not set
+# CONFIG_SND_ENS1371 is not set
+# CONFIG_SND_ES1938 is not set
+# CONFIG_SND_ES1968 is not set
+# CONFIG_SND_MAESTRO3 is not set
+# CONFIG_SND_FM801 is not set
+# CONFIG_SND_ICE1712 is not set
+# CONFIG_SND_ICE1724 is not set
+# CONFIG_SND_INTEL8X0 is not set
+# CONFIG_SND_INTEL8X0M is not set
+# CONFIG_SND_SONICVIBES is not set
+# CONFIG_SND_VIA82XX is not set
+# CONFIG_SND_VX222 is not set
+
+#
+# ALSA USB devices
+#
+# CONFIG_SND_USB_AUDIO is not set
+# CONFIG_SND_USB_USX2Y is not set
+
+#
+# Open Sound System
+#
+# CONFIG_SOUND_PRIME is not set
+
+#
+# USB support
+#
+CONFIG_USB=m
+# CONFIG_USB_DEBUG is not set
+
+#
+# Miscellaneous USB options
+#
+CONFIG_USB_DEVICEFS=y
+# CONFIG_USB_BANDWIDTH is not set
+# CONFIG_USB_DYNAMIC_MINORS is not set
+# CONFIG_USB_SUSPEND is not set
+# CONFIG_USB_OTG is not set
+
+#
+# USB Host Controller Drivers
+#
+# CONFIG_USB_EHCI_HCD is not set
+# CONFIG_USB_OHCI_HCD is not set
+CONFIG_USB_UHCI_HCD=m
+
+#
+# USB Device Class drivers
+#
+CONFIG_USB_AUDIO=m
+CONFIG_USB_BLUETOOTH_TTY=m
+CONFIG_USB_MIDI=m
+CONFIG_USB_ACM=m
+CONFIG_USB_PRINTER=m
+CONFIG_USB_STORAGE=m
+# CONFIG_USB_STORAGE_DEBUG is not set
+# CONFIG_USB_STORAGE_RW_DETECT 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
+
+#
+# USB Human Interface Devices (HID)
+#
+CONFIG_USB_HID=m
+CONFIG_USB_HIDINPUT=y
+# CONFIG_HID_FF is not set
+CONFIG_USB_HIDDEV=y
+
+#
+# USB HID Boot Protocol drivers
+#
+# CONFIG_USB_KBD is not set
+# CONFIG_USB_MOUSE is not set
+# CONFIG_USB_AIPTEK is not set
+# CONFIG_USB_WACOM is not set
+# CONFIG_USB_KBTAB is not set
+# CONFIG_USB_POWERMATE is not set
+# CONFIG_USB_MTOUCH is not set
+# CONFIG_USB_EGALAX is not set
+# CONFIG_USB_XPAD is not set
+# CONFIG_USB_ATI_REMOTE is not set
+
+#
+# USB Imaging devices
+#
+# CONFIG_USB_MDC800 is not set
+# CONFIG_USB_MICROTEK is not set
+# CONFIG_USB_HPUSBSCSI is not set
+
+#
+# USB Multimedia devices
+#
+# CONFIG_USB_DABUSB is not set
+
+#
+# Video4Linux support is needed for USB Multimedia device support
+#
+
+#
+# USB Network adaptors
+#
+# CONFIG_USB_CATC is not set
+# CONFIG_USB_KAWETH is not set
+# CONFIG_USB_PEGASUS is not set
+# CONFIG_USB_RTL8150 is not set
+# CONFIG_USB_USBNET is not set
+
+#
+# USB port drivers
+#
+
+#
+# USB Serial Converter support
+#
+# CONFIG_USB_SERIAL is not set
+
+#
+# USB Miscellaneous drivers
+#
+# CONFIG_USB_EMI62 is not set
+# CONFIG_USB_EMI26 is not set
+# CONFIG_USB_TIGL is not set
+# CONFIG_USB_AUERSWALD is not set
+# CONFIG_USB_RIO500 is not set
+# CONFIG_USB_LEGOTOWER is not set
+# CONFIG_USB_LCD is not set
+# CONFIG_USB_LED is not set
+# CONFIG_USB_CYTHERM is not set
+# CONFIG_USB_PHIDGETSERVO is not set
+# CONFIG_USB_TEST is not set
+
+#
+# USB Gadget Support
+#
+# CONFIG_USB_GADGET is not set
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+# CONFIG_EXT2_FS_XATTR is not set
+CONFIG_EXT3_FS=y
+CONFIG_EXT3_FS_XATTR=y
+# CONFIG_EXT3_FS_POSIX_ACL is not set
+# CONFIG_EXT3_FS_SECURITY is not set
+CONFIG_JBD=y
+# CONFIG_JBD_DEBUG is not set
+CONFIG_FS_MBCACHE=y
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+CONFIG_FS_POSIX_ACL=y
+CONFIG_XFS_FS=y
+# CONFIG_XFS_RT is not set
+CONFIG_XFS_QUOTA=y
+CONFIG_XFS_SECURITY=y
+CONFIG_XFS_POSIX_ACL=y
+# CONFIG_MINIX_FS is not set
+# CONFIG_ROMFS_FS is not set
+# CONFIG_QUOTA is not set
+CONFIG_QUOTACTL=y
+CONFIG_AUTOFS_FS=m
+CONFIG_AUTOFS4_FS=m
+
+#
+# CD-ROM/DVD Filesystems
+#
+CONFIG_ISO9660_FS=m
+CONFIG_JOLIET=y
+# CONFIG_ZISOFS is not set
+CONFIG_UDF_FS=m
+CONFIG_UDF_NLS=y
+
+#
+# DOS/FAT/NT Filesystems
+#
+CONFIG_FAT_FS=y
+# CONFIG_MSDOS_FS is not set
+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 is not set
+CONFIG_DEVPTS_FS_XATTR=y
+CONFIG_DEVPTS_FS_SECURITY=y
+CONFIG_TMPFS=y
+CONFIG_HUGETLBFS=y
+CONFIG_HUGETLB_PAGE=y
+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_EFS_FS is not set
+# CONFIG_CRAMFS is not set
+# CONFIG_VXFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+
+#
+# Network File Systems
+#
+CONFIG_NFS_FS=m
+CONFIG_NFS_V3=y
+CONFIG_NFS_V4=y
+# CONFIG_NFS_DIRECTIO is not set
+CONFIG_NFSD=m
+CONFIG_NFSD_V3=y
+CONFIG_NFSD_V4=y
+CONFIG_NFSD_TCP=y
+CONFIG_LOCKD=m
+CONFIG_LOCKD_V4=y
+CONFIG_EXPORTFS=m
+CONFIG_SUNRPC=m
+CONFIG_SUNRPC_GSS=m
+CONFIG_RPCSEC_GSS_KRB5=m
+# CONFIG_RPCSEC_GSS_SPKM3 is not set
+# CONFIG_SMB_FS is not set
+CONFIG_CIFS=m
+CONFIG_CIFS_STATS=y
+CONFIG_CIFS_XATTR=y
+CONFIG_CIFS_POSIX=y
+# CONFIG_NCP_FS is not set
+# CONFIG_CODA_FS is not set
+# CONFIG_AFS_FS is not set
+
+#
+# Partition Types
+#
+CONFIG_PARTITION_ADVANCED=y
+# CONFIG_ACORN_PARTITION is not set
+# CONFIG_OSF_PARTITION is not set
+# CONFIG_AMIGA_PARTITION is not set
+# CONFIG_ATARI_PARTITION is not set
+# CONFIG_MAC_PARTITION is not set
+CONFIG_MSDOS_PARTITION=y
+# CONFIG_BSD_DISKLABEL is not set
+# CONFIG_MINIX_SUBPARTITION is not set
+# CONFIG_SOLARIS_X86_PARTITION is not set
+# CONFIG_UNIXWARE_DISKLABEL is not set
+# CONFIG_LDM_PARTITION is not set
+CONFIG_SGI_PARTITION=y
+# CONFIG_ULTRIX_PARTITION is not set
+# CONFIG_SUN_PARTITION is not set
+CONFIG_EFI_PARTITION=y
+
+#
+# Native Language Support
+#
+CONFIG_NLS=y
+CONFIG_NLS_DEFAULT="iso8859-1"
+CONFIG_NLS_CODEPAGE_437=y
+# CONFIG_NLS_CODEPAGE_737 is not set
+# CONFIG_NLS_CODEPAGE_775 is not set
+# CONFIG_NLS_CODEPAGE_850 is not set
+# CONFIG_NLS_CODEPAGE_852 is not set
+# CONFIG_NLS_CODEPAGE_855 is not set
+# CONFIG_NLS_CODEPAGE_857 is not set
+# CONFIG_NLS_CODEPAGE_860 is not set
+# CONFIG_NLS_CODEPAGE_861 is not set
+# CONFIG_NLS_CODEPAGE_862 is not set
+# CONFIG_NLS_CODEPAGE_863 is not set
+# CONFIG_NLS_CODEPAGE_864 is not set
+# CONFIG_NLS_CODEPAGE_865 is not set
+# CONFIG_NLS_CODEPAGE_866 is not set
+# CONFIG_NLS_CODEPAGE_869 is not set
+# CONFIG_NLS_CODEPAGE_936 is not set
+# CONFIG_NLS_CODEPAGE_950 is not set
+# CONFIG_NLS_CODEPAGE_932 is not set
+# CONFIG_NLS_CODEPAGE_949 is not set
+# CONFIG_NLS_CODEPAGE_874 is not set
+# 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=y
+# CONFIG_NLS_ISO8859_2 is not set
+# CONFIG_NLS_ISO8859_3 is not set
+# CONFIG_NLS_ISO8859_4 is not set
+# CONFIG_NLS_ISO8859_5 is not set
+# CONFIG_NLS_ISO8859_6 is not set
+# CONFIG_NLS_ISO8859_7 is not set
+# CONFIG_NLS_ISO8859_9 is not set
+# CONFIG_NLS_ISO8859_13 is not set
+# CONFIG_NLS_ISO8859_14 is not set
+# CONFIG_NLS_ISO8859_15 is not set
+# CONFIG_NLS_KOI8_R is not set
+# CONFIG_NLS_KOI8_U is not set
+CONFIG_NLS_UTF8=m
+
+#
+# Library routines
+#
+# CONFIG_CRC_CCITT is not set
+CONFIG_CRC32=y
+# CONFIG_LIBCRC32C is not set
+
+#
+# Profiling support
+#
+CONFIG_PROFILING=y
+CONFIG_OPROFILE=y
+
+#
+# Kernel hacking
+#
+CONFIG_DEBUG_KERNEL=y
+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_INFO is not set
+# CONFIG_IA64_GRANULE_16MB is not set
+CONFIG_IA64_GRANULE_64MB=y
+# CONFIG_IA64_PRINT_HAZARDS is not set
+# CONFIG_DISABLE_VHPT is not set
+# CONFIG_IA64_DEBUG_CMPXCHG is not set
+# CONFIG_IA64_DEBUG_IRQ is not set
+CONFIG_SYSVIPC_COMPAT=y
+
+#
+# Security options
+#
+# CONFIG_SECURITY is not set
+
+#
+# Cryptographic options
+#
+CONFIG_CRYPTO=y
+# CONFIG_CRYPTO_HMAC is not set
+# CONFIG_CRYPTO_NULL is not set
+# CONFIG_CRYPTO_MD4 is not set
+CONFIG_CRYPTO_MD5=y
+# CONFIG_CRYPTO_SHA1 is not set
+# CONFIG_CRYPTO_SHA256 is not set
+# CONFIG_CRYPTO_SHA512 is not set
+# CONFIG_CRYPTO_WHIRLPOOL is not set
+CONFIG_CRYPTO_DES=y
+# CONFIG_CRYPTO_BLOWFISH is not set
+# CONFIG_CRYPTO_TWOFISH is not set
+# CONFIG_CRYPTO_SERPENT 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
+# CONFIG_CRYPTO_TEST is not set
diff -Nru a/arch/ia64/configs/generic_defconfig b/arch/ia64/configs/generic_defconfig
--- a/arch/ia64/configs/generic_defconfig	2004-10-18 14:56:29 -07:00
+++ b/arch/ia64/configs/generic_defconfig	2004-10-18 14:56:29 -07:00
@@ -1,5 +1,7 @@
 #
 # Automatically generated make config: don't edit
+# Linux kernel version: 2.6.9-rc1
+# Tue Aug 24 15:08:24 2004
 #
 
 #
@@ -126,6 +128,7 @@
 CONFIG_HOTPLUG_PCI=m
 # CONFIG_HOTPLUG_PCI_FAKE is not set
 CONFIG_HOTPLUG_PCI_ACPI=m
+# CONFIG_HOTPLUG_PCI_ACPI_IBM is not set
 # CONFIG_HOTPLUG_PCI_CPCI is not set
 # CONFIG_HOTPLUG_PCI_PCIE is not set
 # CONFIG_HOTPLUG_PCI_SHPC is not set
@@ -172,6 +175,7 @@
 CONFIG_BLK_DEV_CRYPTOLOOP=m
 CONFIG_BLK_DEV_NBD=m
 # CONFIG_BLK_DEV_SX8 is not set
+# CONFIG_BLK_DEV_UB is not set
 CONFIG_BLK_DEV_RAM=m
 CONFIG_BLK_DEV_RAM_SIZE=4096
 
@@ -313,6 +317,7 @@
 CONFIG_MD_LINEAR=m
 CONFIG_MD_RAID0=m
 CONFIG_MD_RAID1=m
+# CONFIG_MD_RAID10 is not set
 CONFIG_MD_RAID5=m
 CONFIG_MD_RAID6=m
 CONFIG_MD_MULTIPATH=m
@@ -365,6 +370,7 @@
 # CONFIG_INET_AH is not set
 # CONFIG_INET_ESP is not set
 # CONFIG_INET_IPCOMP is not set
+# CONFIG_INET_TUNNEL is not set
 # CONFIG_IPV6 is not set
 # CONFIG_NETFILTER is not set
 
@@ -575,6 +581,7 @@
 # CONFIG_SYNCLINKMP is not set
 # CONFIG_N_HDLC is not set
 # CONFIG_STALDRV is not set
+CONFIG_SGI_SNSC=y
 
 #
 # Serial drivers
@@ -766,6 +773,7 @@
 CONFIG_USB_DEVICEFS=y
 # CONFIG_USB_BANDWIDTH is not set
 # CONFIG_USB_DYNAMIC_MINORS is not set
+# CONFIG_USB_SUSPEND is not set
 
 #
 # USB Host Controller Drivers
@@ -918,6 +926,8 @@
 CONFIG_FAT_FS=y
 # CONFIG_MSDOS_FS is not set
 CONFIG_VFAT_FS=y
+CONFIG_FAT_DEFAULT_CODEPAGE=437
+CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
 CONFIG_NTFS_FS=m
 # CONFIG_NTFS_DEBUG is not set
 # CONFIG_NTFS_RW is not set
@@ -945,7 +955,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
@@ -970,6 +979,7 @@
 CONFIG_SUNRPC=m
 CONFIG_SUNRPC_GSS=m
 CONFIG_RPCSEC_GSS_KRB5=m
+# CONFIG_RPCSEC_GSS_SPKM3 is not set
 CONFIG_SMB_FS=m
 CONFIG_SMB_NLS_DEFAULT=y
 CONFIG_SMB_NLS_REMOTE="cp437"
@@ -1006,7 +1016,7 @@
 #
 CONFIG_NLS=y
 CONFIG_NLS_DEFAULT="iso8859-1"
-CONFIG_NLS_CODEPAGE_437=m
+CONFIG_NLS_CODEPAGE_437=y
 CONFIG_NLS_CODEPAGE_737=m
 CONFIG_NLS_CODEPAGE_775=m
 CONFIG_NLS_CODEPAGE_850=m
@@ -1030,7 +1040,7 @@
 CONFIG_NLS_CODEPAGE_1250=m
 CONFIG_NLS_CODEPAGE_1251=m
 # CONFIG_NLS_ASCII is not set
-CONFIG_NLS_ISO8859_1=m
+CONFIG_NLS_ISO8859_1=y
 CONFIG_NLS_ISO8859_2=m
 CONFIG_NLS_ISO8859_3=m
 CONFIG_NLS_ISO8859_4=m
@@ -1067,18 +1077,18 @@
 #
 # Kernel hacking
 #
-CONFIG_IA64_GRANULE_16MB=y
-# CONFIG_IA64_GRANULE_64MB is not set
 CONFIG_DEBUG_KERNEL=y
-# CONFIG_IA64_PRINT_HAZARDS is not set
-# CONFIG_DISABLE_VHPT 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_INFO is not set
+CONFIG_IA64_GRANULE_16MB=y
+# CONFIG_IA64_GRANULE_64MB is not set
+# CONFIG_IA64_PRINT_HAZARDS is not set
+# CONFIG_DISABLE_VHPT is not set
 # CONFIG_IA64_DEBUG_CMPXCHG is not set
 # CONFIG_IA64_DEBUG_IRQ is not set
-# CONFIG_DEBUG_INFO is not set
 CONFIG_SYSVIPC_COMPAT=y
 
 #
@@ -1101,11 +1111,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/ia64/configs/sn2_defconfig b/arch/ia64/configs/sn2_defconfig
--- a/arch/ia64/configs/sn2_defconfig	2004-10-18 14:55:54 -07:00
+++ b/arch/ia64/configs/sn2_defconfig	2004-10-18 14:55:54 -07:00
@@ -1,5 +1,7 @@
 #
 # Automatically generated make config: don't edit
+# Linux kernel version: 2.6.9-rc2
+# Fri Sep 24 08:59:00 2004
 #
 
 #
@@ -7,11 +9,11 @@
 #
 CONFIG_EXPERIMENTAL=y
 CONFIG_CLEAN_COMPILE=y
-CONFIG_STANDALONE=y
 
 #
 # General setup
 #
+CONFIG_LOCALVERSION=""
 CONFIG_SWAP=y
 CONFIG_SYSVIPC=y
 CONFIG_POSIX_MQUEUE=y
@@ -32,6 +34,8 @@
 CONFIG_IOSCHED_DEADLINE=y
 CONFIG_IOSCHED_CFQ=y
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+CONFIG_SHMEM=y
+# CONFIG_TINY_SHMEM is not set
 
 #
 # Loadable module support
@@ -53,6 +57,7 @@
 CONFIG_RWSEM_XCHGADD_ALGORITHM=y
 CONFIG_TIME_INTERPOLATION=y
 CONFIG_EFI=y
+CONFIG_GENERIC_IOMAP=y
 # CONFIG_IA64_GENERIC is not set
 # CONFIG_IA64_DIG is not set
 # CONFIG_IA64_HP_ZX1 is not set
@@ -75,7 +80,7 @@
 CONFIG_SMP=y
 CONFIG_NR_CPUS=512
 # CONFIG_HOTPLUG_CPU is not set
-# CONFIG_PREEMPT is not set
+CONFIG_PREEMPT=y
 CONFIG_HAVE_DEC_LOCK=y
 CONFIG_IA32_SUPPORT=y
 CONFIG_COMPAT=y
@@ -115,7 +120,7 @@
 #
 CONFIG_PCI=y
 CONFIG_PCI_DOMAINS=y
-# CONFIG_PCI_USE_VECTOR is not set
+# CONFIG_PCI_MSI is not set
 CONFIG_PCI_LEGACY_PROC=y
 CONFIG_PCI_NAMES=y
 
@@ -142,6 +147,7 @@
 #
 # Generic Driver Options
 #
+CONFIG_STANDALONE=y
 CONFIG_PREVENT_FIRMWARE_BUILD=y
 CONFIG_FW_LOADER=m
 # CONFIG_DEBUG_DRIVER is not set
@@ -171,6 +177,7 @@
 CONFIG_BLK_DEV_CRYPTOLOOP=m
 CONFIG_BLK_DEV_NBD=m
 # CONFIG_BLK_DEV_SX8 is not set
+# CONFIG_BLK_DEV_UB is not set
 CONFIG_BLK_DEV_RAM=y
 CONFIG_BLK_DEV_RAM_SIZE=4096
 CONFIG_BLK_DEV_INITRD=y
@@ -185,7 +192,8 @@
 # Please see Documentation/ide.txt for help/info on IDE drives
 #
 # CONFIG_BLK_DEV_IDE_SATA is not set
-# CONFIG_BLK_DEV_IDEDISK is not set
+CONFIG_BLK_DEV_IDEDISK=y
+# CONFIG_IDEDISK_MULTI_MODE is not set
 CONFIG_BLK_DEV_IDECD=y
 # CONFIG_BLK_DEV_IDETAPE is not set
 # CONFIG_BLK_DEV_IDEFLOPPY is not set
@@ -206,7 +214,6 @@
 # CONFIG_BLK_DEV_IDEDMA_FORCED is not set
 CONFIG_IDEDMA_PCI_AUTO=y
 # CONFIG_IDEDMA_ONLYDISK is not set
-CONFIG_BLK_DEV_ADMA=y
 # CONFIG_BLK_DEV_AEC62XX is not set
 # CONFIG_BLK_DEV_ALI15X3 is not set
 # CONFIG_BLK_DEV_AMD74XX is not set
@@ -273,7 +280,8 @@
 # CONFIG_SCSI_AIC7XXX is not set
 # CONFIG_SCSI_AIC7XXX_OLD is not set
 # CONFIG_SCSI_AIC79XX is not set
-# CONFIG_SCSI_MEGARAID is not set
+# CONFIG_MEGARAID_NEWGEN is not set
+# CONFIG_MEGARAID_LEGACY is not set
 CONFIG_SCSI_SATA=y
 # CONFIG_SCSI_SATA_SVW is not set
 # CONFIG_SCSI_ATA_PIIX is not set
@@ -316,6 +324,7 @@
 CONFIG_MD_LINEAR=y
 CONFIG_MD_RAID0=y
 CONFIG_MD_RAID1=y
+# CONFIG_MD_RAID10 is not set
 CONFIG_MD_RAID5=y
 # CONFIG_MD_RAID6 is not set
 CONFIG_MD_MULTIPATH=y
@@ -329,8 +338,7 @@
 # Fusion MPT device support
 #
 CONFIG_FUSION=y
-CONFIG_FUSION_MAX_SGE=40
-CONFIG_FUSION_ISENSE=m
+CONFIG_FUSION_MAX_SGE=128
 CONFIG_FUSION_CTL=m
 
 #
@@ -368,11 +376,13 @@
 # CONFIG_INET_AH is not set
 # CONFIG_INET_ESP is not set
 # CONFIG_INET_IPCOMP is not set
+# CONFIG_INET_TUNNEL is not set
 CONFIG_IPV6=m
 # CONFIG_IPV6_PRIVACY is not set
 # CONFIG_INET6_AH is not set
 # CONFIG_INET6_ESP is not set
 # CONFIG_INET6_IPCOMP is not set
+# CONFIG_INET6_TUNNEL is not set
 # CONFIG_IPV6_TUNNEL is not set
 # CONFIG_NETFILTER is not set
 
@@ -527,6 +537,7 @@
 # CONFIG_SYNCLINKMP is not set
 # CONFIG_N_HDLC is not set
 # CONFIG_STALDRV is not set
+CONFIG_SGI_SNSC=y
 
 #
 # Serial drivers
@@ -537,11 +548,11 @@
 # Non-8250 serial port support
 #
 CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
 CONFIG_SERIAL_SGI_L1_CONSOLE=y
 CONFIG_UNIX98_PTYS=y
 CONFIG_LEGACY_PTYS=y
 CONFIG_LEGACY_PTY_COUNT=256
-# CONFIG_QIC02_TAPE is not set
 
 #
 # IPMI
@@ -566,6 +577,7 @@
 CONFIG_RAW_DRIVER=m
 # CONFIG_HPET is not set
 CONFIG_MAX_RAW_DEVS=256
+CONFIG_MMTIMER=y
 
 #
 # I2C support
@@ -600,7 +612,6 @@
 # Console display driver support
 #
 # CONFIG_VGA_CONSOLE is not set
-# CONFIG_MDA_CONSOLE is not set
 CONFIG_DUMMY_CONSOLE=y
 
 #
@@ -620,6 +631,7 @@
 # CONFIG_USB_DEVICEFS is not set
 # CONFIG_USB_BANDWIDTH is not set
 # CONFIG_USB_DYNAMIC_MINORS is not set
+# CONFIG_USB_OTG is not set
 
 #
 # USB Host Controller Drivers
@@ -716,7 +728,7 @@
 #
 # File systems
 #
-CONFIG_EXT2_FS=m
+CONFIG_EXT2_FS=y
 CONFIG_EXT2_FS_XATTR=y
 CONFIG_EXT2_FS_POSIX_ACL=y
 CONFIG_EXT2_FS_SECURITY=y
@@ -791,7 +803,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
@@ -816,10 +827,12 @@
 CONFIG_SUNRPC=m
 CONFIG_SUNRPC_GSS=m
 CONFIG_RPCSEC_GSS_KRB5=m
+# CONFIG_RPCSEC_GSS_SPKM3 is not set
 CONFIG_SMB_FS=m
 # CONFIG_SMB_NLS_DEFAULT is not set
 CONFIG_CIFS=m
 # CONFIG_CIFS_STATS is not set
+# CONFIG_CIFS_XATTR is not set
 # CONFIG_CIFS_POSIX is not set
 # CONFIG_NCP_FS is not set
 # CONFIG_CODA_FS is not set
@@ -906,18 +919,18 @@
 #
 # Kernel hacking
 #
-CONFIG_IA64_GRANULE_16MB=y
-# CONFIG_IA64_GRANULE_64MB is not set
 CONFIG_DEBUG_KERNEL=y
-# CONFIG_IA64_PRINT_HAZARDS is not set
-# CONFIG_DISABLE_VHPT 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_INFO=y
+CONFIG_IA64_GRANULE_16MB=y
+# CONFIG_IA64_GRANULE_64MB is not set
+# CONFIG_IA64_PRINT_HAZARDS is not set
+# CONFIG_DISABLE_VHPT is not set
 # CONFIG_IA64_DEBUG_CMPXCHG is not set
 # CONFIG_IA64_DEBUG_IRQ is not set
-CONFIG_DEBUG_INFO=y
 CONFIG_SYSVIPC_COMPAT=y
 
 #
@@ -936,6 +949,7 @@
 CONFIG_CRYPTO_SHA1=m
 # CONFIG_CRYPTO_SHA256 is not set
 # CONFIG_CRYPTO_SHA512 is not set
+# CONFIG_CRYPTO_WHIRLPOOL is not set
 CONFIG_CRYPTO_DES=m
 # CONFIG_CRYPTO_BLOWFISH is not set
 # CONFIG_CRYPTO_TWOFISH is not set
@@ -945,6 +959,7 @@
 # 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=m
 # CONFIG_CRYPTO_MICHAEL_MIC is not set
 # CONFIG_CRYPTO_CRC32C is not set
diff -Nru a/arch/ia64/configs/tiger_defconfig b/arch/ia64/configs/tiger_defconfig
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/arch/ia64/configs/tiger_defconfig	2004-10-18 14:57:21 -07:00
@@ -0,0 +1,1028 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.9-rc2
+# Tue Sep 28 09:03:25 2004
+#
+
+#
+# Code maturity level options
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_CLEAN_COMPILE=y
+
+#
+# General setup
+#
+CONFIG_LOCALVERSION=""
+CONFIG_SWAP=y
+CONFIG_SYSVIPC=y
+CONFIG_POSIX_MQUEUE=y
+# CONFIG_BSD_PROCESS_ACCT is not set
+CONFIG_SYSCTL=y
+# CONFIG_AUDIT is not set
+CONFIG_LOG_BUF_SHIFT=20
+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 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
+CONFIG_SHMEM=y
+# CONFIG_TINY_SHMEM is not set
+
+#
+# Loadable module support
+#
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+# CONFIG_MODULE_FORCE_UNLOAD is not set
+CONFIG_OBSOLETE_MODPARM=y
+CONFIG_MODVERSIONS=y
+CONFIG_KMOD=y
+CONFIG_STOP_MACHINE=y
+
+#
+# Processor type and features
+#
+CONFIG_IA64=y
+CONFIG_64BIT=y
+CONFIG_MMU=y
+CONFIG_RWSEM_XCHGADD_ALGORITHM=y
+CONFIG_TIME_INTERPOLATION=y
+CONFIG_EFI=y
+CONFIG_GENERIC_IOMAP=y
+# CONFIG_IA64_GENERIC is not set
+CONFIG_IA64_DIG=y
+# CONFIG_IA64_HP_ZX1 is not set
+# CONFIG_IA64_SGI_SN2 is not set
+# CONFIG_IA64_HP_SIM is not set
+# CONFIG_ITANIUM is not set
+CONFIG_MCKINLEY=y
+# CONFIG_IA64_PAGE_SIZE_4KB is not set
+# CONFIG_IA64_PAGE_SIZE_8KB is not set
+CONFIG_IA64_PAGE_SIZE_16KB=y
+# CONFIG_IA64_PAGE_SIZE_64KB is not set
+CONFIG_IA64_L1_CACHE_SHIFT=7
+# CONFIG_NUMA is not set
+CONFIG_VIRTUAL_MEM_MAP=y
+CONFIG_IA64_CYCLONE=y
+CONFIG_IOSAPIC=y
+CONFIG_FORCE_MAX_ZONEORDER=18
+CONFIG_SMP=y
+CONFIG_NR_CPUS=4
+CONFIG_HOTPLUG_CPU=y
+# CONFIG_PREEMPT is not set
+CONFIG_HAVE_DEC_LOCK=y
+CONFIG_IA32_SUPPORT=y
+CONFIG_COMPAT=y
+CONFIG_PERFMON=y
+CONFIG_IA64_PALINFO=y
+
+#
+# Firmware Drivers
+#
+CONFIG_EFI_VARS=y
+CONFIG_EFI_PCDP=y
+CONFIG_BINFMT_ELF=y
+CONFIG_BINFMT_MISC=m
+
+#
+# Power management and ACPI
+#
+CONFIG_PM=y
+CONFIG_ACPI=y
+
+#
+# ACPI (Advanced Configuration and Power Interface) Support
+#
+CONFIG_ACPI_BOOT=y
+CONFIG_ACPI_INTERPRETER=y
+CONFIG_ACPI_BUTTON=m
+CONFIG_ACPI_FAN=m
+CONFIG_ACPI_PROCESSOR=m
+CONFIG_ACPI_THERMAL=m
+# CONFIG_ACPI_DEBUG is not set
+CONFIG_ACPI_BUS=y
+CONFIG_ACPI_POWER=y
+CONFIG_ACPI_PCI=y
+CONFIG_ACPI_SYSTEM=y
+
+#
+# Bus options (PCI, PCMCIA)
+#
+CONFIG_PCI=y
+CONFIG_PCI_DOMAINS=y
+# CONFIG_PCI_MSI is not set
+CONFIG_PCI_LEGACY_PROC=y
+CONFIG_PCI_NAMES=y
+
+#
+# PCI Hotplug Support
+#
+CONFIG_HOTPLUG_PCI=m
+# CONFIG_HOTPLUG_PCI_FAKE is not set
+CONFIG_HOTPLUG_PCI_ACPI=m
+# CONFIG_HOTPLUG_PCI_ACPI_IBM is not set
+# CONFIG_HOTPLUG_PCI_CPCI is not set
+# CONFIG_HOTPLUG_PCI_PCIE is not set
+# CONFIG_HOTPLUG_PCI_SHPC is not set
+
+#
+# PCMCIA/CardBus support
+#
+# CONFIG_PCMCIA is not set
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+# CONFIG_FW_LOADER is not set
+# CONFIG_DEBUG_DRIVER is not set
+
+#
+# Memory Technology Devices (MTD)
+#
+# CONFIG_MTD is not set
+
+#
+# Parallel port support
+#
+# CONFIG_PARPORT is not set
+
+#
+# Plug and Play support
+#
+
+#
+# Block devices
+#
+# CONFIG_BLK_CPQ_DA is not set
+# CONFIG_BLK_CPQ_CISS_DA is not set
+# CONFIG_BLK_DEV_DAC960 is not set
+# CONFIG_BLK_DEV_UMEM is not set
+CONFIG_BLK_DEV_LOOP=m
+CONFIG_BLK_DEV_CRYPTOLOOP=m
+CONFIG_BLK_DEV_NBD=m
+# CONFIG_BLK_DEV_SX8 is not set
+# CONFIG_BLK_DEV_UB is not set
+CONFIG_BLK_DEV_RAM=m
+CONFIG_BLK_DEV_RAM_SIZE=4096
+
+#
+# ATA/ATAPI/MFM/RLL support
+#
+CONFIG_IDE=y
+CONFIG_BLK_DEV_IDE=y
+
+#
+# Please see Documentation/ide.txt for help/info on IDE drives
+#
+# CONFIG_BLK_DEV_IDE_SATA is not set
+CONFIG_BLK_DEV_IDEDISK=y
+# CONFIG_IDEDISK_MULTI_MODE is not set
+CONFIG_BLK_DEV_IDECD=y
+# CONFIG_BLK_DEV_IDETAPE is not set
+CONFIG_BLK_DEV_IDEFLOPPY=y
+CONFIG_BLK_DEV_IDESCSI=m
+# 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=y
+# CONFIG_IDEPCI_SHARE_IRQ is not set
+# CONFIG_BLK_DEV_OFFBOARD is not set
+CONFIG_BLK_DEV_GENERIC=y
+# CONFIG_BLK_DEV_OPTI621 is not set
+CONFIG_BLK_DEV_IDEDMA_PCI=y
+# CONFIG_BLK_DEV_IDEDMA_FORCED is not set
+CONFIG_IDEDMA_PCI_AUTO=y
+# CONFIG_IDEDMA_ONLYDISK is not set
+# CONFIG_BLK_DEV_AEC62XX is not set
+# CONFIG_BLK_DEV_ALI15X3 is not set
+# CONFIG_BLK_DEV_AMD74XX is not set
+CONFIG_BLK_DEV_CMD64X=y
+# CONFIG_BLK_DEV_TRIFLEX is not set
+# CONFIG_BLK_DEV_CY82C693 is not set
+# CONFIG_BLK_DEV_CS5520 is not set
+# CONFIG_BLK_DEV_CS5530 is not set
+# CONFIG_BLK_DEV_HPT34X is not set
+# CONFIG_BLK_DEV_HPT366 is not set
+# CONFIG_BLK_DEV_SC1200 is not set
+CONFIG_BLK_DEV_PIIX=y
+# CONFIG_BLK_DEV_NS87415 is not set
+# CONFIG_BLK_DEV_PDC202XX_OLD is not set
+# CONFIG_BLK_DEV_PDC202XX_NEW is not set
+# CONFIG_BLK_DEV_SVWKS is not set
+# CONFIG_BLK_DEV_SIIMAGE 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_IDE_ARM is not set
+CONFIG_BLK_DEV_IDEDMA=y
+# CONFIG_IDEDMA_IVB is not set
+CONFIG_IDEDMA_AUTO=y
+# CONFIG_BLK_DEV_HD is not set
+
+#
+# SCSI device support
+#
+CONFIG_SCSI=y
+CONFIG_SCSI_PROC_FS=y
+
+#
+# SCSI support type (disk, tape, CD-ROM)
+#
+CONFIG_BLK_DEV_SD=y
+CONFIG_CHR_DEV_ST=m
+# CONFIG_CHR_DEV_OSST is not set
+CONFIG_BLK_DEV_SR=m
+# CONFIG_BLK_DEV_SR_VENDOR is not set
+CONFIG_CHR_DEV_SG=m
+
+#
+# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
+#
+# CONFIG_SCSI_MULTI_LUN 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=y
+
+#
+# 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_MEGARAID_NEWGEN is not set
+# CONFIG_MEGARAID_LEGACY is not set
+# CONFIG_SCSI_SATA is not set
+# CONFIG_SCSI_BUSLOGIC 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_IPS is not set
+# CONFIG_SCSI_INIA100 is not set
+CONFIG_SCSI_SYM53C8XX_2=y
+CONFIG_SCSI_SYM53C8XX_DMA_ADDRESSING_MODE=1
+CONFIG_SCSI_SYM53C8XX_DEFAULT_TAGS=16
+CONFIG_SCSI_SYM53C8XX_MAX_TAGS=64
+# CONFIG_SCSI_SYM53C8XX_IOMAPPED is not set
+# CONFIG_SCSI_IPR is not set
+# CONFIG_SCSI_QLOGIC_ISP is not set
+CONFIG_SCSI_QLOGIC_FC=y
+# CONFIG_SCSI_QLOGIC_FC_FIRMWARE is not set
+CONFIG_SCSI_QLOGIC_1280=y
+CONFIG_SCSI_QLA2XXX=y
+CONFIG_SCSI_QLA21XX=m
+CONFIG_SCSI_QLA22XX=m
+CONFIG_SCSI_QLA2300=m
+CONFIG_SCSI_QLA2322=m
+# 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_DEBUG is not set
+
+#
+# Multi-device support (RAID and LVM)
+#
+CONFIG_MD=y
+CONFIG_BLK_DEV_MD=m
+CONFIG_MD_LINEAR=m
+CONFIG_MD_RAID0=m
+CONFIG_MD_RAID1=m
+# CONFIG_MD_RAID10 is not set
+CONFIG_MD_RAID5=m
+CONFIG_MD_RAID6=m
+CONFIG_MD_MULTIPATH=m
+CONFIG_BLK_DEV_DM=m
+CONFIG_DM_CRYPT=m
+CONFIG_DM_SNAPSHOT=m
+CONFIG_DM_MIRROR=m
+CONFIG_DM_ZERO=m
+
+#
+# Fusion MPT device support
+#
+CONFIG_FUSION=y
+CONFIG_FUSION_MAX_SGE=40
+# CONFIG_FUSION_CTL is not set
+
+#
+# IEEE 1394 (FireWire) support
+#
+# CONFIG_IEEE1394 is not set
+
+#
+# I2O device support
+#
+# CONFIG_I2O is not set
+
+#
+# Networking support
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+CONFIG_PACKET=y
+# CONFIG_PACKET_MMAP is not set
+CONFIG_NETLINK_DEV=y
+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 is not set
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+# CONFIG_IP_MROUTE is not set
+CONFIG_ARPD=y
+CONFIG_SYN_COOKIES=y
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+# CONFIG_INET_TUNNEL is not set
+# CONFIG_IPV6 is not set
+# CONFIG_NETFILTER is not set
+
+#
+# SCTP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_SCTP is not set
+# CONFIG_ATM is not set
+# CONFIG_BRIDGE is not set
+# CONFIG_VLAN_8021Q is not set
+# CONFIG_DECNET 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
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+# CONFIG_NET_HW_FLOWCONTROL is not set
+
+#
+# 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=y
+# CONFIG_NETPOLL_RX is not set
+# CONFIG_NETPOLL_TRAP is not set
+CONFIG_NET_POLL_CONTROLLER=y
+# CONFIG_HAMRADIO is not set
+# CONFIG_IRDA is not set
+# CONFIG_BT is not set
+CONFIG_NETDEVICES=y
+CONFIG_DUMMY=m
+# CONFIG_BONDING is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
+# CONFIG_ETHERTAP is not set
+
+#
+# ARCnet devices
+#
+# CONFIG_ARCNET is not set
+
+#
+# Ethernet (10 or 100Mbit)
+#
+CONFIG_NET_ETHERNET=y
+CONFIG_MII=m
+# CONFIG_HAPPYMEAL is not set
+# CONFIG_SUNGEM is not set
+# CONFIG_NET_VENDOR_3COM is not set
+
+#
+# Tulip family network device support
+#
+CONFIG_NET_TULIP=y
+# CONFIG_DE2104X is not set
+CONFIG_TULIP=m
+# CONFIG_TULIP_MWI is not set
+# CONFIG_TULIP_MMIO is not set
+# CONFIG_TULIP_NAPI is not set
+# CONFIG_DE4X5 is not set
+# CONFIG_WINBOND_840 is not set
+# CONFIG_DM9102 is not set
+# CONFIG_HP100 is not set
+CONFIG_NET_PCI=y
+# CONFIG_PCNET32 is not set
+# 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=m
+# CONFIG_EEPRO100_PIO is not set
+CONFIG_E100=m
+# CONFIG_E100_NAPI is not set
+# CONFIG_FEALNX is not set
+# CONFIG_NATSEMI is not set
+# CONFIG_NE2K_PCI 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)
+#
+# CONFIG_ACENIC is not set
+# CONFIG_DL2K is not set
+CONFIG_E1000=y
+# CONFIG_E1000_NAPI is not set
+# CONFIG_NS83820 is not set
+# CONFIG_HAMACHI is not set
+# CONFIG_YELLOWFIN is not set
+# CONFIG_R8169 is not set
+# CONFIG_SK98LIN is not set
+CONFIG_TIGON3=y
+
+#
+# Ethernet (10000 Mbit)
+#
+# CONFIG_IXGB is not set
+# CONFIG_S2IO is not set
+
+#
+# Token Ring devices
+#
+# CONFIG_TR is not set
+
+#
+# Wireless LAN (non-hamradio)
+#
+# CONFIG_NET_RADIO is not set
+
+#
+# Wan interfaces
+#
+# CONFIG_WAN 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=y
+
+#
+# ISDN subsystem
+#
+# CONFIG_ISDN is not set
+
+#
+# Telephony Support
+#
+# CONFIG_PHONE is not set
+
+#
+# Input device support
+#
+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=m
+CONFIG_SOUND_GAMEPORT=m
+# CONFIG_GAMEPORT_NS558 is not set
+# CONFIG_GAMEPORT_L4 is not set
+# CONFIG_GAMEPORT_EMU10K1 is not set
+# CONFIG_GAMEPORT_VORTEX is not set
+# CONFIG_GAMEPORT_FM801 is not set
+# CONFIG_GAMEPORT_CS461x is not set
+CONFIG_SERIO=y
+CONFIG_SERIO_I8042=y
+# CONFIG_SERIO_SERPORT is not set
+# CONFIG_SERIO_CT82C710 is not set
+# CONFIG_SERIO_PCIPS2 is not set
+# CONFIG_SERIO_RAW is not set
+
+#
+# Input 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=y
+# CONFIG_ROCKETPORT is not set
+# CONFIG_CYCLADES is not set
+# CONFIG_SYNCLINK is not set
+# CONFIG_SYNCLINKMP is not set
+# CONFIG_N_HDLC is not set
+# CONFIG_STALDRV is not set
+
+#
+# Serial drivers
+#
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_ACPI=y
+CONFIG_SERIAL_8250_NR_UARTS=6
+CONFIG_SERIAL_8250_EXTENDED=y
+CONFIG_SERIAL_8250_SHARE_IRQ=y
+# CONFIG_SERIAL_8250_DETECT_IRQ is not set
+# CONFIG_SERIAL_8250_MULTIPORT is not set
+# CONFIG_SERIAL_8250_RSA is not set
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+CONFIG_UNIX98_PTYS=y
+CONFIG_LEGACY_PTYS=y
+CONFIG_LEGACY_PTY_COUNT=256
+
+#
+# IPMI
+#
+# CONFIG_IPMI_HANDLER is not set
+
+#
+# Watchdog Cards
+#
+# CONFIG_WATCHDOG is not set
+# CONFIG_HW_RANDOM is not set
+CONFIG_EFI_RTC=y
+# CONFIG_DTLK is not set
+# CONFIG_R3964 is not set
+# CONFIG_APPLICOM is not set
+
+#
+# Ftape, the floppy tape device driver
+#
+CONFIG_AGP=m
+CONFIG_AGP_I460=m
+CONFIG_DRM=y
+CONFIG_DRM_TDFX=m
+CONFIG_DRM_R128=m
+CONFIG_DRM_RADEON=m
+CONFIG_DRM_MGA=m
+CONFIG_DRM_SIS=m
+CONFIG_RAW_DRIVER=m
+CONFIG_HPET=y
+# CONFIG_HPET_RTC_IRQ is not set
+CONFIG_HPET_MMAP=y
+CONFIG_MAX_RAW_DEVS=256
+
+#
+# I2C support
+#
+# CONFIG_I2C is not set
+
+#
+# Dallas's 1-wire bus
+#
+# CONFIG_W1 is not set
+
+#
+# Misc devices
+#
+
+#
+# Multimedia devices
+#
+# CONFIG_VIDEO_DEV is not set
+
+#
+# Digital Video Broadcasting Devices
+#
+# CONFIG_DVB is not set
+
+#
+# Graphics support
+#
+# CONFIG_FB is not set
+
+#
+# Console display driver support
+#
+CONFIG_VGA_CONSOLE=y
+CONFIG_DUMMY_CONSOLE=y
+
+#
+# Sound
+#
+# CONFIG_SOUND is not set
+
+#
+# USB support
+#
+CONFIG_USB=y
+# CONFIG_USB_DEBUG is not set
+
+#
+# Miscellaneous USB options
+#
+CONFIG_USB_DEVICEFS=y
+# CONFIG_USB_BANDWIDTH is not set
+# CONFIG_USB_DYNAMIC_MINORS is not set
+# CONFIG_USB_SUSPEND is not set
+# CONFIG_USB_OTG is not set
+
+#
+# USB Host Controller Drivers
+#
+CONFIG_USB_EHCI_HCD=m
+# CONFIG_USB_EHCI_SPLIT_ISO is not set
+# CONFIG_USB_EHCI_ROOT_HUB_TT is not set
+CONFIG_USB_OHCI_HCD=m
+CONFIG_USB_UHCI_HCD=y
+
+#
+# USB Device Class drivers
+#
+# CONFIG_USB_BLUETOOTH_TTY is not set
+# CONFIG_USB_ACM is not set
+# CONFIG_USB_PRINTER is not set
+CONFIG_USB_STORAGE=m
+# CONFIG_USB_STORAGE_DEBUG is not set
+# CONFIG_USB_STORAGE_RW_DETECT 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
+
+#
+# USB Human Interface Devices (HID)
+#
+CONFIG_USB_HID=y
+CONFIG_USB_HIDINPUT=y
+# CONFIG_HID_FF is not set
+# CONFIG_USB_HIDDEV is not set
+# CONFIG_USB_AIPTEK is not set
+# CONFIG_USB_WACOM is not set
+# CONFIG_USB_KBTAB is not set
+# CONFIG_USB_POWERMATE is not set
+# CONFIG_USB_MTOUCH is not set
+# CONFIG_USB_EGALAX is not set
+# CONFIG_USB_XPAD is not set
+# CONFIG_USB_ATI_REMOTE is not set
+
+#
+# USB Imaging devices
+#
+# CONFIG_USB_MDC800 is not set
+# CONFIG_USB_MICROTEK is not set
+# CONFIG_USB_HPUSBSCSI is not set
+
+#
+# USB Multimedia devices
+#
+# CONFIG_USB_DABUSB is not set
+
+#
+# Video4Linux support is needed for USB Multimedia device support
+#
+
+#
+# USB Network adaptors
+#
+# CONFIG_USB_CATC is not set
+# CONFIG_USB_KAWETH is not set
+# CONFIG_USB_PEGASUS is not set
+# CONFIG_USB_RTL8150 is not set
+# CONFIG_USB_USBNET is not set
+
+#
+# USB port drivers
+#
+
+#
+# USB Serial Converter support
+#
+# CONFIG_USB_SERIAL is not set
+
+#
+# USB Miscellaneous drivers
+#
+# CONFIG_USB_EMI62 is not set
+# CONFIG_USB_EMI26 is not set
+# CONFIG_USB_TIGL is not set
+# CONFIG_USB_AUERSWALD is not set
+# CONFIG_USB_RIO500 is not set
+# CONFIG_USB_LEGOTOWER is not set
+# CONFIG_USB_LCD is not set
+# CONFIG_USB_LED is not set
+# CONFIG_USB_CYTHERM is not set
+# CONFIG_USB_PHIDGETSERVO is not set
+# CONFIG_USB_TEST is not set
+
+#
+# USB Gadget Support
+#
+# CONFIG_USB_GADGET is not set
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+CONFIG_EXT2_FS_XATTR=y
+CONFIG_EXT2_FS_POSIX_ACL=y
+CONFIG_EXT2_FS_SECURITY=y
+CONFIG_EXT3_FS=y
+CONFIG_EXT3_FS_XATTR=y
+CONFIG_EXT3_FS_POSIX_ACL=y
+CONFIG_EXT3_FS_SECURITY=y
+CONFIG_JBD=y
+# CONFIG_JBD_DEBUG is not set
+CONFIG_FS_MBCACHE=y
+CONFIG_REISERFS_FS=y
+# CONFIG_REISERFS_CHECK is not set
+# CONFIG_REISERFS_PROC_INFO is not set
+CONFIG_REISERFS_FS_XATTR=y
+CONFIG_REISERFS_FS_POSIX_ACL=y
+CONFIG_REISERFS_FS_SECURITY=y
+# CONFIG_JFS_FS is not set
+CONFIG_FS_POSIX_ACL=y
+CONFIG_XFS_FS=y
+# CONFIG_XFS_RT is not set
+# CONFIG_XFS_QUOTA is not set
+# CONFIG_XFS_SECURITY is not set
+# CONFIG_XFS_POSIX_ACL is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_ROMFS_FS is not set
+# CONFIG_QUOTA is not set
+CONFIG_AUTOFS_FS=y
+CONFIG_AUTOFS4_FS=y
+
+#
+# CD-ROM/DVD Filesystems
+#
+CONFIG_ISO9660_FS=m
+CONFIG_JOLIET=y
+# CONFIG_ZISOFS is not set
+CONFIG_UDF_FS=m
+CONFIG_UDF_NLS=y
+
+#
+# DOS/FAT/NT Filesystems
+#
+CONFIG_FAT_FS=y
+# CONFIG_MSDOS_FS is not set
+CONFIG_VFAT_FS=y
+CONFIG_FAT_DEFAULT_CODEPAGE=437
+CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
+CONFIG_NTFS_FS=m
+# CONFIG_NTFS_DEBUG is not set
+# CONFIG_NTFS_RW 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_XATTR is not set
+CONFIG_TMPFS=y
+CONFIG_HUGETLBFS=y
+CONFIG_HUGETLB_PAGE=y
+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_EFS_FS is not set
+# CONFIG_CRAMFS is not set
+# CONFIG_VXFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+
+#
+# Network File Systems
+#
+CONFIG_NFS_FS=m
+CONFIG_NFS_V3=y
+CONFIG_NFS_V4=y
+CONFIG_NFS_DIRECTIO=y
+CONFIG_NFSD=m
+CONFIG_NFSD_V3=y
+CONFIG_NFSD_V4=y
+CONFIG_NFSD_TCP=y
+CONFIG_LOCKD=m
+CONFIG_LOCKD_V4=y
+CONFIG_EXPORTFS=m
+CONFIG_SUNRPC=m
+CONFIG_SUNRPC_GSS=m
+CONFIG_RPCSEC_GSS_KRB5=m
+# CONFIG_RPCSEC_GSS_SPKM3 is not set
+CONFIG_SMB_FS=m
+CONFIG_SMB_NLS_DEFAULT=y
+CONFIG_SMB_NLS_REMOTE="cp437"
+CONFIG_CIFS=m
+# CONFIG_CIFS_STATS is not set
+# CONFIG_CIFS_XATTR is not set
+# CONFIG_CIFS_POSIX is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_CODA_FS is not set
+# CONFIG_AFS_FS is not set
+
+#
+# Partition Types
+#
+CONFIG_PARTITION_ADVANCED=y
+# CONFIG_ACORN_PARTITION is not set
+# CONFIG_OSF_PARTITION is not set
+# CONFIG_AMIGA_PARTITION is not set
+# CONFIG_ATARI_PARTITION is not set
+# CONFIG_MAC_PARTITION is not set
+CONFIG_MSDOS_PARTITION=y
+# CONFIG_BSD_DISKLABEL is not set
+# CONFIG_MINIX_SUBPARTITION is not set
+# CONFIG_SOLARIS_X86_PARTITION is not set
+# CONFIG_UNIXWARE_DISKLABEL is not set
+# CONFIG_LDM_PARTITION is not set
+CONFIG_SGI_PARTITION=y
+# CONFIG_ULTRIX_PARTITION is not set
+# CONFIG_SUN_PARTITION is not set
+CONFIG_EFI_PARTITION=y
+
+#
+# Native Language Support
+#
+CONFIG_NLS=y
+CONFIG_NLS_DEFAULT="iso8859-1"
+CONFIG_NLS_CODEPAGE_437=y
+CONFIG_NLS_CODEPAGE_737=m
+CONFIG_NLS_CODEPAGE_775=m
+CONFIG_NLS_CODEPAGE_850=m
+CONFIG_NLS_CODEPAGE_852=m
+CONFIG_NLS_CODEPAGE_855=m
+CONFIG_NLS_CODEPAGE_857=m
+CONFIG_NLS_CODEPAGE_860=m
+CONFIG_NLS_CODEPAGE_861=m
+CONFIG_NLS_CODEPAGE_862=m
+CONFIG_NLS_CODEPAGE_863=m
+CONFIG_NLS_CODEPAGE_864=m
+CONFIG_NLS_CODEPAGE_865=m
+CONFIG_NLS_CODEPAGE_866=m
+CONFIG_NLS_CODEPAGE_869=m
+CONFIG_NLS_CODEPAGE_936=m
+CONFIG_NLS_CODEPAGE_950=m
+CONFIG_NLS_CODEPAGE_932=m
+CONFIG_NLS_CODEPAGE_949=m
+CONFIG_NLS_CODEPAGE_874=m
+CONFIG_NLS_ISO8859_8=m
+CONFIG_NLS_CODEPAGE_1250=m
+CONFIG_NLS_CODEPAGE_1251=m
+# CONFIG_NLS_ASCII is not set
+CONFIG_NLS_ISO8859_1=y
+CONFIG_NLS_ISO8859_2=m
+CONFIG_NLS_ISO8859_3=m
+CONFIG_NLS_ISO8859_4=m
+CONFIG_NLS_ISO8859_5=m
+CONFIG_NLS_ISO8859_6=m
+CONFIG_NLS_ISO8859_7=m
+CONFIG_NLS_ISO8859_9=m
+CONFIG_NLS_ISO8859_13=m
+CONFIG_NLS_ISO8859_14=m
+CONFIG_NLS_ISO8859_15=m
+CONFIG_NLS_KOI8_R=m
+CONFIG_NLS_KOI8_U=m
+CONFIG_NLS_UTF8=m
+
+#
+# Library routines
+#
+# CONFIG_CRC_CCITT is not set
+CONFIG_CRC32=y
+# CONFIG_LIBCRC32C is not set
+
+#
+# Profiling support
+#
+# CONFIG_PROFILING is not set
+
+#
+# Kernel hacking
+#
+CONFIG_DEBUG_KERNEL=y
+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_INFO is not set
+CONFIG_IA64_GRANULE_16MB=y
+# CONFIG_IA64_GRANULE_64MB is not set
+# CONFIG_IA64_PRINT_HAZARDS is not set
+# CONFIG_DISABLE_VHPT is not set
+# CONFIG_IA64_DEBUG_CMPXCHG is not set
+# CONFIG_IA64_DEBUG_IRQ is not set
+CONFIG_SYSVIPC_COMPAT=y
+
+#
+# Security options
+#
+# CONFIG_SECURITY is not set
+
+#
+# Cryptographic options
+#
+CONFIG_CRYPTO=y
+# CONFIG_CRYPTO_HMAC is not set
+# CONFIG_CRYPTO_NULL is not set
+# CONFIG_CRYPTO_MD4 is not set
+CONFIG_CRYPTO_MD5=m
+# CONFIG_CRYPTO_SHA1 is not set
+# CONFIG_CRYPTO_SHA256 is not set
+# CONFIG_CRYPTO_SHA512 is not set
+# CONFIG_CRYPTO_WHIRLPOOL is not set
+CONFIG_CRYPTO_DES=m
+# CONFIG_CRYPTO_BLOWFISH is not set
+# CONFIG_CRYPTO_TWOFISH is not set
+# CONFIG_CRYPTO_SERPENT 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
+# CONFIG_CRYPTO_TEST is not set
diff -Nru a/arch/ia64/configs/zx1_defconfig b/arch/ia64/configs/zx1_defconfig
--- a/arch/ia64/configs/zx1_defconfig	2004-10-18 14:56:33 -07:00
+++ b/arch/ia64/configs/zx1_defconfig	2004-10-18 14:56:33 -07:00
@@ -1,5 +1,7 @@
 #
 # Automatically generated make config: don't edit
+# Linux kernel version: 2.6.9-rc2-aegl
+# Mon Sep 27 19:03:13 2004
 #
 
 #
@@ -7,33 +9,45 @@
 #
 CONFIG_EXPERIMENTAL=y
 # CONFIG_CLEAN_COMPILE is not set
-CONFIG_STANDALONE=y
 CONFIG_BROKEN=y
 CONFIG_BROKEN_ON_SMP=y
 
 #
 # General setup
 #
+CONFIG_LOCALVERSION=""
 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=17
 CONFIG_HOTPLUG=y
 # 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_IOSCHED_NOOP=y
 CONFIG_IOSCHED_AS=y
 CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+CONFIG_SHMEM=y
+# CONFIG_TINY_SHMEM is not set
 
 #
 # Loadable module support
 #
-# CONFIG_MODULES is not set
+CONFIG_MODULES=y
+# CONFIG_MODULE_UNLOAD is not set
+CONFIG_OBSOLETE_MODPARM=y
+# CONFIG_MODVERSIONS is not set
+# CONFIG_KMOD is not set
 
 #
 # Processor type and features
@@ -44,54 +58,53 @@
 CONFIG_RWSEM_XCHGADD_ALGORITHM=y
 CONFIG_TIME_INTERPOLATION=y
 CONFIG_EFI=y
-# CONFIG_ITANIUM is not set
-CONFIG_MCKINLEY=y
+CONFIG_GENERIC_IOMAP=y
 # CONFIG_IA64_GENERIC is not set
 # CONFIG_IA64_DIG is not set
 CONFIG_IA64_HP_ZX1=y
 # CONFIG_IA64_SGI_SN2 is not set
 # CONFIG_IA64_HP_SIM is not set
+# CONFIG_ITANIUM is not set
+CONFIG_MCKINLEY=y
 # CONFIG_IA64_PAGE_SIZE_4KB is not set
 # CONFIG_IA64_PAGE_SIZE_8KB is not set
 CONFIG_IA64_PAGE_SIZE_16KB=y
 # CONFIG_IA64_PAGE_SIZE_64KB is not set
-CONFIG_ACPI=y
-CONFIG_ACPI_INTERPRETER=y
-CONFIG_ACPI_KERNEL_CONFIG=y
 CONFIG_IA64_L1_CACHE_SHIFT=7
-# CONFIG_MCKINLEY_ASTEP_SPECIFIC is not set
 # CONFIG_NUMA is not set
 CONFIG_VIRTUAL_MEM_MAP=y
-CONFIG_IA64_MCA=y
 # CONFIG_IA64_CYCLONE is not set
-CONFIG_PM=y
 CONFIG_IOSAPIC=y
 CONFIG_FORCE_MAX_ZONEORDER=18
-# CONFIG_HUGETLB_PAGE_SIZE_4GB is not set
-# CONFIG_HUGETLB_PAGE_SIZE_1GB is not set
-# CONFIG_HUGETLB_PAGE_SIZE_256MB is not set
-CONFIG_HUGETLB_PAGE_SIZE_64MB=y
-# CONFIG_HUGETLB_PAGE_SIZE_16MB is not set
-# CONFIG_HUGETLB_PAGE_SIZE_4MB is not set
-# CONFIG_HUGETLB_PAGE_SIZE_1MB is not set
-# CONFIG_HUGETLB_PAGE_SIZE_256KB is not set
-CONFIG_IA64_PAL_IDLE=y
 CONFIG_SMP=y
 CONFIG_NR_CPUS=16
+# CONFIG_HOTPLUG_CPU is not set
 # CONFIG_PREEMPT is not set
 CONFIG_HAVE_DEC_LOCK=y
 CONFIG_IA32_SUPPORT=y
 CONFIG_COMPAT=y
 CONFIG_PERFMON=y
 CONFIG_IA64_PALINFO=y
+
+#
+# Firmware Drivers
+#
 CONFIG_EFI_VARS=y
+CONFIG_EFI_PCDP=y
 CONFIG_BINFMT_ELF=y
 CONFIG_BINFMT_MISC=y
 
 #
+# Power management and ACPI
+#
+CONFIG_PM=y
+CONFIG_ACPI=y
+
+#
 # ACPI (Advanced Configuration and Power Interface) Support
 #
 CONFIG_ACPI_BOOT=y
+CONFIG_ACPI_INTERPRETER=y
 CONFIG_ACPI_BUTTON=y
 CONFIG_ACPI_FAN=y
 CONFIG_ACPI_PROCESSOR=y
@@ -101,8 +114,13 @@
 CONFIG_ACPI_POWER=y
 CONFIG_ACPI_PCI=y
 CONFIG_ACPI_SYSTEM=y
+
+#
+# Bus options (PCI, PCMCIA)
+#
 CONFIG_PCI=y
 CONFIG_PCI_DOMAINS=y
+# CONFIG_PCI_MSI is not set
 CONFIG_PCI_LEGACY_PROC=y
 CONFIG_PCI_NAMES=y
 
@@ -112,6 +130,7 @@
 CONFIG_HOTPLUG_PCI=y
 # CONFIG_HOTPLUG_PCI_FAKE is not set
 CONFIG_HOTPLUG_PCI_ACPI=y
+# CONFIG_HOTPLUG_PCI_ACPI_IBM is not set
 # CONFIG_HOTPLUG_PCI_CPCI is not set
 # CONFIG_HOTPLUG_PCI_PCIE is not set
 # CONFIG_HOTPLUG_PCI_SHPC is not set
@@ -122,14 +141,16 @@
 # CONFIG_PCMCIA is not set
 
 #
-# Parallel port support
+# Device Drivers
 #
-# CONFIG_PARPORT is not set
 
 #
 # Generic Driver Options
 #
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
 # CONFIG_FW_LOADER is not set
+# CONFIG_DEBUG_DRIVER is not set
 
 #
 # Memory Technology Devices (MTD)
@@ -137,13 +158,17 @@
 # CONFIG_MTD is not set
 
 #
+# Parallel port support
+#
+# CONFIG_PARPORT is not set
+
+#
 # Plug and Play support
 #
 
 #
 # Block devices
 #
-# CONFIG_BLK_DEV_FD is not set
 # CONFIG_BLK_CPQ_DA is not set
 # CONFIG_BLK_CPQ_CISS_DA is not set
 # CONFIG_BLK_DEV_DAC960 is not set
@@ -151,10 +176,11 @@
 CONFIG_BLK_DEV_LOOP=y
 # CONFIG_BLK_DEV_CRYPTOLOOP is not set
 # CONFIG_BLK_DEV_NBD is not set
+# CONFIG_BLK_DEV_SX8 is not set
+# CONFIG_BLK_DEV_UB is not set
 CONFIG_BLK_DEV_RAM=y
 CONFIG_BLK_DEV_RAM_SIZE=4096
 CONFIG_BLK_DEV_INITRD=y
-# CONFIG_DCSSBLK is not set
 
 #
 # ATA/ATAPI/MFM/RLL support
@@ -165,9 +191,9 @@
 #
 # Please see Documentation/ide.txt for help/info on IDE drives
 #
+# 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=y
 # CONFIG_BLK_DEV_IDETAPE is not set
 # CONFIG_BLK_DEV_IDEFLOPPY is not set
@@ -187,7 +213,6 @@
 CONFIG_BLK_DEV_IDEDMA_PCI=y
 # CONFIG_BLK_DEV_IDEDMA_FORCED is not set
 # CONFIG_IDEDMA_PCI_AUTO is not set
-CONFIG_BLK_DEV_ADMA=y
 # CONFIG_BLK_DEV_AEC62XX is not set
 # CONFIG_BLK_DEV_ALI15X3 is not set
 # CONFIG_BLK_DEV_AMD74XX is not set
@@ -208,33 +233,13 @@
 # CONFIG_BLK_DEV_SLC90E66 is not set
 # CONFIG_BLK_DEV_TRM290 is not set
 # CONFIG_BLK_DEV_VIA82CXXX is not set
+# CONFIG_IDE_ARM is not set
 CONFIG_BLK_DEV_IDEDMA=y
 # CONFIG_IDEDMA_IVB is not set
 # CONFIG_IDEDMA_AUTO is not set
 # CONFIG_BLK_DEV_HD is not set
 
 #
-# IEEE 1394 (FireWire) support
-#
-# CONFIG_IEEE1394 is not set
-
-#
-# I2O device support
-#
-
-#
-# Multi-device support (RAID and LVM)
-#
-# CONFIG_MD is not set
-
-#
-# Fusion MPT device support
-#
-CONFIG_FUSION=y
-CONFIG_FUSION_BOOT=y
-CONFIG_FUSION_MAX_SGE=40
-
-#
 # SCSI device support
 #
 CONFIG_SCSI=y
@@ -254,21 +259,28 @@
 # Some SCSI devices (e.g. CD jukebox) support multiple LUNs
 #
 CONFIG_SCSI_MULTI_LUN=y
-CONFIG_SCSI_REPORT_LUNS=y
 CONFIG_SCSI_CONSTANTS=y
 CONFIG_SCSI_LOGGING=y
 
 #
+# 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_ADVANSYS is not set
-CONFIG_SCSI_MEGARAID=y
+# CONFIG_MEGARAID_NEWGEN is not set
+# CONFIG_MEGARAID_LEGACY is not set
 # CONFIG_SCSI_SATA is not set
 # CONFIG_SCSI_BUSLOGIC is not set
 # CONFIG_SCSI_CPQFCTS is not set
@@ -285,6 +297,7 @@
 CONFIG_SCSI_SYM53C8XX_DEFAULT_TAGS=16
 CONFIG_SCSI_SYM53C8XX_MAX_TAGS=64
 # CONFIG_SCSI_SYM53C8XX_IOMAPPED is not set
+# CONFIG_SCSI_IPR is not set
 # CONFIG_SCSI_PCI2000 is not set
 # CONFIG_SCSI_PCI2220I is not set
 # CONFIG_SCSI_QLOGIC_ISP is not set
@@ -302,6 +315,28 @@
 # CONFIG_SCSI_DEBUG is not set
 
 #
+# Multi-device support (RAID and LVM)
+#
+# CONFIG_MD is not set
+
+#
+# Fusion MPT device support
+#
+CONFIG_FUSION=y
+CONFIG_FUSION_MAX_SGE=40
+# CONFIG_FUSION_CTL is not set
+
+#
+# IEEE 1394 (FireWire) support
+#
+# CONFIG_IEEE1394 is not set
+
+#
+# I2O device support
+#
+# CONFIG_I2O is not set
+
+#
 # Networking support
 #
 CONFIG_NET=y
@@ -322,19 +357,17 @@
 # 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
+# CONFIG_INET_TUNNEL is not set
 
 #
 # IP: Virtual Server Configuration
 #
 # CONFIG_IP_VS is not set
 # CONFIG_IPV6 is not set
-# CONFIG_DECNET is not set
-# CONFIG_BRIDGE is not set
 CONFIG_NETFILTER=y
 # CONFIG_NETFILTER_DEBUG is not set
 
@@ -353,10 +386,11 @@
 #
 # 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_DECNET is not set
 # CONFIG_LLC2 is not set
 # CONFIG_IPX is not set
 # CONFIG_ATALK is not set
@@ -371,21 +405,27 @@
 # 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=y
+# CONFIG_BONDING is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
 
 #
 # ARCnet devices
 #
 # CONFIG_ARCNET is not set
-CONFIG_DUMMY=y
-# CONFIG_BONDING is not set
-# CONFIG_EQUALIZER is not set
-# CONFIG_TUN is not set
 
 #
 # Ethernet (10 or 100Mbit)
@@ -429,6 +469,7 @@
 # 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)
@@ -441,7 +482,6 @@
 # CONFIG_HAMACHI is not set
 # CONFIG_YELLOWFIN is not set
 # CONFIG_R8169 is not set
-# CONFIG_SIS190 is not set
 # CONFIG_SK98LIN is not set
 CONFIG_TIGON3=y
 
@@ -449,47 +489,39 @@
 # 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
-
-#
-# Wireless LAN (non-hamradio)
-#
-# CONFIG_NET_RADIO is not set
+# CONFIG_S2IO is not set
 
 #
 # Token Ring devices
 #
 # CONFIG_TR is not set
-# CONFIG_NET_FC is not set
-# CONFIG_SHAPER is not set
-
-#
-# Wan interfaces
-#
-# CONFIG_WAN is not set
 
 #
-# Amateur Radio support
+# Wireless LAN (non-hamradio)
 #
-# CONFIG_HAMRADIO is not set
+# CONFIG_NET_RADIO is not set
 
 #
-# IrDA (infrared) support
+# Wan interfaces
 #
-# CONFIG_IRDA is not set
+# CONFIG_WAN 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
 
 #
-# Bluetooth support
+# ISDN subsystem
 #
-# CONFIG_BT is not set
+# CONFIG_ISDN is not set
 
 #
-# ISDN subsystem
+# Telephony Support
 #
-# CONFIG_ISDN is not set
+# CONFIG_PHONE is not set
 
 #
 # Input device support
@@ -518,6 +550,7 @@
 # CONFIG_SERIO_SERPORT is not set
 # CONFIG_SERIO_CT82C710 is not set
 # CONFIG_SERIO_PCIPS2 is not set
+# CONFIG_SERIO_RAW is not set
 
 #
 # Input Device Drivers
@@ -541,7 +574,6 @@
 #
 CONFIG_SERIAL_8250=y
 CONFIG_SERIAL_8250_CONSOLE=y
-CONFIG_SERIAL_8250_HCDP=y
 CONFIG_SERIAL_8250_ACPI=y
 CONFIG_SERIAL_8250_NR_UARTS=8
 CONFIG_SERIAL_8250_EXTENDED=y
@@ -560,12 +592,6 @@
 CONFIG_LEGACY_PTY_COUNT=256
 
 #
-# Mice
-#
-# CONFIG_BUSMOUSE is not set
-# CONFIG_QIC02_TAPE is not set
-
-#
 # IPMI
 #
 # CONFIG_IPMI_HANDLER is not set
@@ -575,8 +601,6 @@
 #
 # CONFIG_WATCHDOG is not set
 # CONFIG_HW_RANDOM is not set
-# CONFIG_NVRAM is not set
-# CONFIG_GEN_RTC is not set
 CONFIG_EFI_RTC=y
 # CONFIG_DTLK is not set
 # CONFIG_R3964 is not set
@@ -585,7 +609,6 @@
 #
 # Ftape, the floppy tape device driver
 #
-# CONFIG_FTAPE is not set
 CONFIG_AGP=y
 CONFIG_AGP_HP_ZX1=y
 CONFIG_DRM=y
@@ -596,6 +619,7 @@
 # CONFIG_DRM_MGA is not set
 # CONFIG_DRM_SIS is not set
 # CONFIG_RAW_DRIVER is not set
+# CONFIG_HPET is not set
 
 #
 # I2C support
@@ -608,11 +632,13 @@
 #
 CONFIG_I2C_ALGOBIT=y
 CONFIG_I2C_ALGOPCF=y
+# CONFIG_I2C_ALGOPCA is not set
 
 #
 # I2C Hardware Bus support
 #
 # CONFIG_I2C_ALI1535 is not set
+# CONFIG_I2C_ALI1563 is not set
 # CONFIG_I2C_ALI15X3 is not set
 # CONFIG_I2C_AMD756 is not set
 # CONFIG_I2C_AMD8111 is not set
@@ -630,30 +656,56 @@
 # CONFIG_I2C_VIA is not set
 # CONFIG_I2C_VIAPRO is not set
 # CONFIG_I2C_VOODOO3 is not set
+# CONFIG_I2C_PCA_ISA is not set
 
 #
-# I2C Hardware Sensors Chip support
+# Hardware Sensors Chip support
 #
 # CONFIG_I2C_SENSOR is not set
 # CONFIG_SENSORS_ADM1021 is not set
+# CONFIG_SENSORS_ADM1025 is not set
+# CONFIG_SENSORS_ADM1031 is not set
 # CONFIG_SENSORS_ASB100 is not set
-# CONFIG_SENSORS_EEPROM is not set
+# CONFIG_SENSORS_DS1621 is not set
 # CONFIG_SENSORS_FSCHER is not set
 # CONFIG_SENSORS_GL518SM is not set
 # CONFIG_SENSORS_IT87 is not set
 # CONFIG_SENSORS_LM75 is not set
+# CONFIG_SENSORS_LM77 is not set
 # CONFIG_SENSORS_LM78 is not set
+# CONFIG_SENSORS_LM80 is not set
 # CONFIG_SENSORS_LM83 is not set
 # CONFIG_SENSORS_LM85 is not set
 # CONFIG_SENSORS_LM90 is not set
+# CONFIG_SENSORS_MAX1619 is not set
+# CONFIG_SENSORS_SMSC47M1 is not set
 # CONFIG_SENSORS_VIA686A is not set
 # CONFIG_SENSORS_W83781D is not set
 # CONFIG_SENSORS_W83L785TS is not set
+# CONFIG_SENSORS_W83627HF is not set
+
+#
+# Other I2C Chip support
+#
+# CONFIG_SENSORS_EEPROM is not set
+# CONFIG_SENSORS_PCF8574 is not set
+# CONFIG_SENSORS_PCF8591 is not set
+# CONFIG_SENSORS_RTC8564 is not set
 # CONFIG_I2C_DEBUG_CORE is not set
+# CONFIG_I2C_DEBUG_ALGO is not set
 # CONFIG_I2C_DEBUG_BUS is not set
 # CONFIG_I2C_DEBUG_CHIP is not set
 
 #
+# Dallas's 1-wire bus
+#
+# CONFIG_W1 is not set
+
+#
+# Misc devices
+#
+
+#
 # Multimedia devices
 #
 # CONFIG_VIDEO_DEV is not set
@@ -664,6 +716,167 @@
 # CONFIG_DVB is not set
 
 #
+# Graphics support
+#
+CONFIG_FB=y
+CONFIG_FB_MODE_HELPERS=y
+# CONFIG_FB_CIRRUS is not set
+# CONFIG_FB_PM2 is not set
+# CONFIG_FB_CYBER2000 is not set
+# CONFIG_FB_ASILIANT is not set
+# CONFIG_FB_IMSTT is not set
+# CONFIG_FB_RIVA is not set
+# CONFIG_FB_MATROX is not set
+# CONFIG_FB_RADEON_OLD is not set
+CONFIG_FB_RADEON=y
+CONFIG_FB_RADEON_I2C=y
+CONFIG_FB_RADEON_DEBUG=y
+# CONFIG_FB_ATY128 is not set
+# CONFIG_FB_ATY is not set
+# CONFIG_FB_SIS is not set
+# CONFIG_FB_NEOMAGIC is not set
+# CONFIG_FB_KYRO is not set
+# CONFIG_FB_3DFX is not set
+# CONFIG_FB_VOODOO1 is not set
+# CONFIG_FB_TRIDENT is not set
+# CONFIG_FB_PM3 is not set
+# CONFIG_FB_VIRTUAL is not set
+
+#
+# Console display driver support
+#
+CONFIG_VGA_CONSOLE=y
+CONFIG_DUMMY_CONSOLE=y
+CONFIG_FRAMEBUFFER_CONSOLE=y
+# CONFIG_FONTS is not set
+CONFIG_FONT_8x8=y
+CONFIG_FONT_8x16=y
+
+#
+# Logo configuration
+#
+CONFIG_LOGO=y
+# CONFIG_LOGO_LINUX_MONO is not set
+# CONFIG_LOGO_LINUX_VGA16 is not set
+CONFIG_LOGO_LINUX_CLUT224=y
+
+#
+# Sound
+#
+# CONFIG_SOUND is not set
+
+#
+# USB support
+#
+CONFIG_USB=y
+# CONFIG_USB_DEBUG is not set
+
+#
+# Miscellaneous USB options
+#
+# CONFIG_USB_DEVICEFS is not set
+CONFIG_USB_BANDWIDTH=y
+# CONFIG_USB_DYNAMIC_MINORS is not set
+# CONFIG_USB_SUSPEND is not set
+# CONFIG_USB_OTG is not set
+
+#
+# USB Host Controller Drivers
+#
+CONFIG_USB_EHCI_HCD=y
+# CONFIG_USB_EHCI_SPLIT_ISO is not set
+# CONFIG_USB_EHCI_ROOT_HUB_TT is not set
+CONFIG_USB_OHCI_HCD=y
+CONFIG_USB_UHCI_HCD=y
+
+#
+# USB Device Class drivers
+#
+# CONFIG_USB_BLUETOOTH_TTY is not set
+# CONFIG_USB_ACM is not set
+# CONFIG_USB_PRINTER is not set
+CONFIG_USB_STORAGE=y
+# CONFIG_USB_STORAGE_DEBUG is not set
+# CONFIG_USB_STORAGE_RW_DETECT 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
+
+#
+# USB Human Interface Devices (HID)
+#
+CONFIG_USB_HID=y
+CONFIG_USB_HIDINPUT=y
+# CONFIG_HID_FF is not set
+CONFIG_USB_HIDDEV=y
+# CONFIG_USB_AIPTEK is not set
+# CONFIG_USB_WACOM is not set
+# CONFIG_USB_KBTAB is not set
+# CONFIG_USB_POWERMATE is not set
+# CONFIG_USB_MTOUCH is not set
+# CONFIG_USB_EGALAX is not set
+# CONFIG_USB_XPAD is not set
+# CONFIG_USB_ATI_REMOTE is not set
+
+#
+# USB Imaging devices
+#
+# CONFIG_USB_MDC800 is not set
+# CONFIG_USB_MICROTEK is not set
+# CONFIG_USB_HPUSBSCSI is not set
+
+#
+# USB Multimedia devices
+#
+# CONFIG_USB_DABUSB is not set
+
+#
+# Video4Linux support is needed for USB Multimedia device support
+#
+
+#
+# USB Network adaptors
+#
+# CONFIG_USB_CATC is not set
+# CONFIG_USB_KAWETH is not set
+# CONFIG_USB_PEGASUS is not set
+# CONFIG_USB_RTL8150 is not set
+# CONFIG_USB_USBNET is not set
+
+#
+# USB port drivers
+#
+
+#
+# USB Serial Converter support
+#
+# CONFIG_USB_SERIAL is not set
+
+#
+# USB Miscellaneous drivers
+#
+# CONFIG_USB_EMI62 is not set
+# CONFIG_USB_EMI26 is not set
+# CONFIG_USB_TIGL is not set
+# CONFIG_USB_AUERSWALD is not set
+# CONFIG_USB_RIO500 is not set
+# CONFIG_USB_LEGOTOWER is not set
+# CONFIG_USB_LCD is not set
+# CONFIG_USB_LED is not set
+# CONFIG_USB_CYTHERM is not set
+# CONFIG_USB_PHIDGETSERVO is not set
+
+#
+# USB Gadget Support
+#
+# CONFIG_USB_GADGET is not set
+
+#
 # File systems
 #
 CONFIG_EXT2_FS=y
@@ -693,6 +906,7 @@
 CONFIG_JOLIET=y
 # CONFIG_ZISOFS is not set
 CONFIG_UDF_FS=y
+CONFIG_UDF_NLS=y
 
 #
 # DOS/FAT/NT Filesystems
@@ -700,6 +914,8 @@
 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
 
 #
@@ -707,6 +923,7 @@
 #
 CONFIG_PROC_FS=y
 CONFIG_PROC_KCORE=y
+CONFIG_SYSFS=y
 # CONFIG_DEVFS_FS is not set
 # CONFIG_DEVPTS_FS_XATTR is not set
 CONFIG_TMPFS=y
@@ -747,11 +964,12 @@
 CONFIG_EXPORTFS=y
 CONFIG_SUNRPC=y
 CONFIG_SUNRPC_GSS=y
+CONFIG_RPCSEC_GSS_KRB5=y
+# CONFIG_RPCSEC_GSS_SPKM3 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
 
 #
@@ -769,7 +987,6 @@
 # CONFIG_SOLARIS_X86_PARTITION is not set
 # CONFIG_UNIXWARE_DISKLABEL is not set
 # CONFIG_LDM_PARTITION is not set
-# CONFIG_NEC98_PARTITION is not set
 # CONFIG_SGI_PARTITION is not set
 # CONFIG_ULTRIX_PARTITION is not set
 # CONFIG_SUN_PARTITION is not set
@@ -803,6 +1020,7 @@
 CONFIG_NLS_ISO8859_8=y
 # CONFIG_NLS_CODEPAGE_1250 is not set
 CONFIG_NLS_CODEPAGE_1251=y
+# CONFIG_NLS_ASCII is not set
 CONFIG_NLS_ISO8859_1=y
 CONFIG_NLS_ISO8859_2=y
 CONFIG_NLS_ISO8859_3=y
@@ -819,226 +1037,11 @@
 CONFIG_NLS_UTF8=y
 
 #
-# Graphics support
-#
-CONFIG_FB=y
-# CONFIG_FB_CIRRUS is not set
-# CONFIG_FB_PM2 is not set
-# CONFIG_FB_CYBER2000 is not set
-# CONFIG_FB_IMSTT is not set
-# CONFIG_FB_RIVA is not set
-# CONFIG_FB_MATROX is not set
-# CONFIG_FB_RADEON_OLD is not set
-CONFIG_FB_RADEON=y
-CONFIG_FB_RADEON_I2C=y
-CONFIG_FB_RADEON_DEBUG=y
-# CONFIG_FB_ATY128 is not set
-# CONFIG_FB_ATY is not set
-# CONFIG_FB_SIS is not set
-# CONFIG_FB_NEOMAGIC is not set
-# CONFIG_FB_KYRO is not set
-# CONFIG_FB_3DFX is not set
-# CONFIG_FB_VOODOO1 is not set
-# CONFIG_FB_TRIDENT is not set
-# CONFIG_FB_PM3 is not set
-# CONFIG_FB_VIRTUAL is not set
-
-#
-# Console display driver support
-#
-CONFIG_VGA_CONSOLE=y
-# CONFIG_MDA_CONSOLE is not set
-CONFIG_DUMMY_CONSOLE=y
-CONFIG_FRAMEBUFFER_CONSOLE=y
-CONFIG_PCI_CONSOLE=y
-# CONFIG_FONTS is not set
-CONFIG_FONT_8x8=y
-CONFIG_FONT_8x16=y
-
-#
-# Logo configuration
-#
-CONFIG_LOGO=y
-# CONFIG_LOGO_LINUX_MONO is not set
-# CONFIG_LOGO_LINUX_VGA16 is not set
-CONFIG_LOGO_LINUX_CLUT224=y
-
-#
-# Sound
-#
-CONFIG_SOUND=y
-
-#
-# Advanced Linux Sound Architecture
-#
-CONFIG_SND=y
-CONFIG_SND_SEQUENCER=y
-# CONFIG_SND_SEQ_DUMMY is not set
-CONFIG_SND_OSSEMUL=y
-CONFIG_SND_MIXER_OSS=y
-CONFIG_SND_PCM_OSS=y
-CONFIG_SND_SEQUENCER_OSS=y
-# CONFIG_SND_VERBOSE_PRINTK is not set
-# CONFIG_SND_DEBUG is not set
-
-#
-# Generic devices
-#
-# CONFIG_SND_DUMMY is not set
-# CONFIG_SND_VIRMIDI is not set
-# CONFIG_SND_MTPAV is not set
-# CONFIG_SND_SERIAL_U16550 is not set
-# CONFIG_SND_MPU401 is not set
-
-#
-# PCI devices
-#
-# CONFIG_SND_ALI5451 is not set
-# CONFIG_SND_AZT3328 is not set
-# CONFIG_SND_BT87X is not set
-# CONFIG_SND_CS46XX is not set
-# CONFIG_SND_CS4281 is not set
-# CONFIG_SND_EMU10K1 is not set
-# CONFIG_SND_KORG1212 is not set
-# CONFIG_SND_NM256 is not set
-# CONFIG_SND_RME32 is not set
-# CONFIG_SND_RME96 is not set
-# CONFIG_SND_RME9652 is not set
-# CONFIG_SND_HDSP is not set
-# CONFIG_SND_TRIDENT is not set
-# CONFIG_SND_YMFPCI is not set
-# CONFIG_SND_ALS4000 is not set
-# CONFIG_SND_CMIPCI is not set
-# CONFIG_SND_ENS1370 is not set
-# CONFIG_SND_ENS1371 is not set
-# CONFIG_SND_ES1938 is not set
-# CONFIG_SND_ES1968 is not set
-# CONFIG_SND_MAESTRO3 is not set
-CONFIG_SND_FM801=y
-# CONFIG_SND_ICE1712 is not set
-# CONFIG_SND_ICE1724 is not set
-# CONFIG_SND_INTEL8X0 is not set
-# CONFIG_SND_SONICVIBES is not set
-# CONFIG_SND_VIA82XX is not set
-# CONFIG_SND_VX222 is not set
-
-#
-# ALSA USB devices
-#
-# CONFIG_SND_USB_AUDIO is not set
-
-#
-# Open Sound System
-#
-# CONFIG_SOUND_PRIME is not set
-
-#
-# USB support
-#
-CONFIG_USB=y
-# CONFIG_USB_DEBUG is not set
-
-#
-# Miscellaneous USB options
-#
-# CONFIG_USB_DEVICEFS is not set
-CONFIG_USB_BANDWIDTH=y
-# CONFIG_USB_DYNAMIC_MINORS is not set
-
-#
-# USB Host Controller Drivers
-#
-CONFIG_USB_EHCI_HCD=y
-CONFIG_USB_OHCI_HCD=y
-CONFIG_USB_UHCI_HCD=y
-
-#
-# USB Device Class drivers
-#
-# CONFIG_USB_AUDIO is not set
-# CONFIG_USB_BLUETOOTH_TTY is not set
-# CONFIG_USB_MIDI is not set
-# CONFIG_USB_ACM is not set
-# CONFIG_USB_PRINTER is not set
-CONFIG_USB_STORAGE=y
-# CONFIG_USB_STORAGE_DEBUG is not set
-# CONFIG_USB_STORAGE_DATAFAB is not set
-# CONFIG_USB_STORAGE_FREECOM is not set
-# CONFIG_USB_STORAGE_ISD200 is not set
-# CONFIG_USB_STORAGE_DPCM is not set
-# CONFIG_USB_STORAGE_HP8200e is not set
-# CONFIG_USB_STORAGE_SDDR09 is not set
-# CONFIG_USB_STORAGE_SDDR55 is not set
-# CONFIG_USB_STORAGE_JUMPSHOT is not set
-
-#
-# USB Human Interface Devices (HID)
-#
-CONFIG_USB_HID=y
-CONFIG_USB_HIDINPUT=y
-# CONFIG_HID_FF is not set
-CONFIG_USB_HIDDEV=y
-# CONFIG_USB_AIPTEK is not set
-# CONFIG_USB_WACOM is not set
-# CONFIG_USB_KBTAB is not set
-# CONFIG_USB_POWERMATE is not set
-# CONFIG_USB_XPAD is not set
-
-#
-# USB Imaging devices
-#
-# CONFIG_USB_MDC800 is not set
-# CONFIG_USB_MICROTEK is not set
-# CONFIG_USB_HPUSBSCSI is not set
-
-#
-# USB Multimedia devices
-#
-# CONFIG_USB_DABUSB is not set
-
-#
-# Video4Linux support is needed for USB Multimedia device support
-#
-
-#
-# USB Network adaptors
-#
-# CONFIG_USB_CATC is not set
-# CONFIG_USB_KAWETH is not set
-# CONFIG_USB_PEGASUS is not set
-# CONFIG_USB_RTL8150 is not set
-# CONFIG_USB_USBNET is not set
-
-#
-# USB port drivers
-#
-
-#
-# USB Serial Converter support
-#
-# CONFIG_USB_SERIAL is not set
-
-#
-# USB Miscellaneous drivers
-#
-# CONFIG_USB_EMI62 is not set
-# CONFIG_USB_EMI26 is not set
-# CONFIG_USB_TIGL is not set
-# CONFIG_USB_AUERSWALD is not set
-# CONFIG_USB_RIO500 is not set
-# CONFIG_USB_LEGOTOWER is not set
-# CONFIG_USB_LCD is not set
-# CONFIG_USB_LED is not set
-
-#
-# USB Gadget Support
-#
-# CONFIG_USB_GADGET is not set
-
-#
 # Library routines
 #
+# CONFIG_CRC_CCITT is not set
 CONFIG_CRC32=y
+# CONFIG_LIBCRC32C is not set
 
 #
 # Profiling support
@@ -1048,18 +1051,19 @@
 #
 # Kernel hacking
 #
-CONFIG_IA64_GRANULE_16MB=y
-# CONFIG_IA64_GRANULE_64MB is not set
 CONFIG_DEBUG_KERNEL=y
-CONFIG_IA64_PRINT_HAZARDS=y
-# CONFIG_DISABLE_VHPT 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_INFO is not set
+CONFIG_IA64_GRANULE_16MB=y
+# CONFIG_IA64_GRANULE_64MB is not set
+CONFIG_IA64_PRINT_HAZARDS=y
+# CONFIG_DISABLE_VHPT is not set
 # CONFIG_IA64_DEBUG_CMPXCHG is not set
 # CONFIG_IA64_DEBUG_IRQ is not set
-# CONFIG_DEBUG_INFO is not set
+CONFIG_SYSVIPC_COMPAT=y
 
 #
 # Security options
@@ -1069,4 +1073,26 @@
 #
 # Cryptographic options
 #
-# CONFIG_CRYPTO is not set
+CONFIG_CRYPTO=y
+# CONFIG_CRYPTO_HMAC is not set
+# CONFIG_CRYPTO_NULL is not set
+# CONFIG_CRYPTO_MD4 is not set
+CONFIG_CRYPTO_MD5=y
+# CONFIG_CRYPTO_SHA1 is not set
+# CONFIG_CRYPTO_SHA256 is not set
+# CONFIG_CRYPTO_SHA512 is not set
+# CONFIG_CRYPTO_WHIRLPOOL is not set
+CONFIG_CRYPTO_DES=y
+# CONFIG_CRYPTO_BLOWFISH is not set
+# CONFIG_CRYPTO_TWOFISH is not set
+# CONFIG_CRYPTO_SERPENT 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
+# CONFIG_CRYPTO_TEST is not set
diff -Nru a/arch/ia64/hp/common/sba_iommu.c b/arch/ia64/hp/common/sba_iommu.c
--- a/arch/ia64/hp/common/sba_iommu.c	2004-10-18 14:55:55 -07:00
+++ b/arch/ia64/hp/common/sba_iommu.c	2004-10-18 14:55:55 -07:00
@@ -191,7 +191,7 @@
 static unsigned long iovp_mask;
 
 struct ioc {
-	void		*ioc_hpa;	/* I/O MMU base address */
+	void __iomem	*ioc_hpa;	/* I/O MMU base address */
 	char		*res_map;	/* resource map, bit == pdir entry */
 	u64		*pdir_base;	/* physical base address */
 	unsigned long	ibase;		/* pdir IOV Space base */
@@ -203,6 +203,9 @@
 					/* clearing pdir to prevent races with allocations. */
 	unsigned int	res_bitshift;	/* from the RIGHT! */
 	unsigned int	res_size;	/* size of resource map in bytes */
+#ifdef CONFIG_NUMA
+	unsigned int	node;		/* node where this IOC lives */
+#endif
 #if DELAYED_RESOURCE_CNT > 0
 	spinlock_t	saved_lock;	/* may want to try to get this on a separate cacheline */
 					/* than res_lock for bigger systems. */
@@ -1057,7 +1060,24 @@
 	struct ioc *ioc;
 	void *addr;
 
+	ioc = GET_IOC(dev);
+	ASSERT(ioc);
+
+#ifdef CONFIG_NUMA
+	{
+		struct page *page;
+		page = alloc_pages_node(ioc->node == MAX_NUMNODES ?
+		                        numa_node_id() : ioc->node, flags,
+		                        get_order(size));
+
+		if (unlikely(!page))
+			return NULL;
+
+		addr = page_address(page);
+	}
+#else
 	addr = (void *) __get_free_pages(flags, get_order(size));
+#endif
 	if (unlikely(!addr))
 		return NULL;
 
@@ -1081,8 +1101,6 @@
 	 * If device can't bypass or bypass is disabled, pass the 32bit fake
 	 * device to map single to get an iova mapping.
 	 */
-	ioc = GET_IOC(dev);
-	ASSERT(ioc);
 	*dma_handle = sba_map_single(&ioc->sac_only_dev->dev, addr, size, 0);
 
 	return addr;
@@ -1135,7 +1153,7 @@
 {
 	struct scatterlist *dma_sg = startsg;	/* pointer to current DMA */
 	int n_mappings = 0;
-	u64 *pdirp = 0;
+	u64 *pdirp = NULL;
 	unsigned long dma_offset = 0;
 
 	dma_sg--;
@@ -1799,6 +1817,10 @@
 
 	seq_printf(s, "Hewlett Packard %s IOC rev %d.%d\n",
 		ioc->name, ((ioc->rev >> 4) & 0xF), (ioc->rev & 0xF));
+#ifdef CONFIG_NUMA
+	if (ioc->node != MAX_NUMNODES)
+		seq_printf(s, "NUMA node       : %d\n", ioc->node);
+#endif
 	seq_printf(s, "IOVA size       : %ld MB\n", ((ioc->pdir_size >> 3) * iovp_size)/(1024*1024));
 	seq_printf(s, "IOVA page size  : %ld kb\n", iovp_size/1024);
 
@@ -1853,7 +1875,7 @@
 {
 	struct proc_dir_entry *dir, *entry;
 
-	dir = proc_mkdir("bus/mckinley", 0);
+	dir = proc_mkdir("bus/mckinley", NULL);
 	if (!dir)
 		return;
 
@@ -1899,6 +1921,58 @@
 	printk(KERN_WARNING "No IOC for PCI Bus %04x:%02x in ACPI\n", pci_domain_nr(bus), bus->number);
 }
 
+#ifdef CONFIG_NUMA
+static void __init
+sba_map_ioc_to_node(struct ioc *ioc, acpi_handle handle)
+{
+	struct acpi_buffer buffer = {ACPI_ALLOCATE_BUFFER, NULL};
+	union acpi_object *obj;
+	acpi_handle phandle;
+	unsigned int node;
+
+	ioc->node = MAX_NUMNODES;
+
+	/*
+	 * Check for a _PXM on this node first.  We don't typically see
+	 * one here, so we'll end up getting it from the parent.
+	 */
+	if (ACPI_FAILURE(acpi_evaluate_object(handle, "_PXM", NULL, &buffer))) {
+		if (ACPI_FAILURE(acpi_get_parent(handle, &phandle)))
+			return;
+
+		/* Reset the acpi buffer */
+		buffer.length = ACPI_ALLOCATE_BUFFER;
+		buffer.pointer = NULL;
+
+		if (ACPI_FAILURE(acpi_evaluate_object(phandle, "_PXM", NULL,
+		                                      &buffer)))
+			return;
+	}
+
+	if (!buffer.length || !buffer.pointer)
+		return;
+
+	obj = buffer.pointer;
+
+	if (obj->type != ACPI_TYPE_INTEGER ||
+	    obj->integer.value >= MAX_PXM_DOMAINS) {
+		acpi_os_free(buffer.pointer);
+		return;
+	}
+
+	node = pxm_to_nid_map[obj->integer.value];
+	acpi_os_free(buffer.pointer);
+
+	if (node >= MAX_NUMNODES || !node_online(node))
+		return;
+
+	ioc->node = node;
+	return;
+}
+#else
+#define sba_map_ioc_to_node(ioc, handle)
+#endif
+
 static int __init
 acpi_sba_ioc_add(struct acpi_device *device)
 {
@@ -1941,6 +2015,8 @@
 	if (!ioc)
 		return 1;
 
+	/* setup NUMA node association */
+	sba_map_ioc_to_node(ioc, device->handle);
 	return 0;
 }
 
diff -Nru a/arch/ia64/hp/sim/simserial.c b/arch/ia64/hp/sim/simserial.c
--- a/arch/ia64/hp/sim/simserial.c	2004-10-18 14:56:31 -07:00
+++ b/arch/ia64/hp/sim/simserial.c	2004-10-18 14:56:31 -07:00
@@ -50,10 +50,6 @@
 #define _INLINE_ inline
 #endif
 
-#ifndef MIN
-#define MIN(a,b)	((a) < (b) ? (a) : (b))
-#endif
-
 #define IRQ_T(info) ((info->flags & ASYNC_SHARE_IRQ) ? SA_SHIRQ : SA_INTERRUPT)
 
 #define SSC_GETCHAR	21
@@ -275,7 +271,7 @@
 	 * Then from the beginning of the buffer until necessary
 	 */
 
-	count = MIN(CIRC_CNT(info->xmit.head, info->xmit.tail, SERIAL_XMIT_SIZE),
+	count = min(CIRC_CNT(info->xmit.head, info->xmit.tail, SERIAL_XMIT_SIZE),
 		    SERIAL_XMIT_SIZE - info->xmit.tail);
 	console->write(console, info->xmit.buf+info->xmit.tail, count);
 
@@ -1055,7 +1051,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-10-18 14:57:03 -07:00
+++ b/arch/ia64/ia32/binfmt_elf32.c	2004-10-18 14:57:03 -07:00
@@ -48,6 +48,7 @@
 
 extern struct page *ia32_shared_page[];
 extern unsigned long *ia32_gdt;
+extern struct page *ia32_gate_page;
 
 struct page *
 ia32_install_shared_page (struct vm_area_struct *vma, unsigned long address, int *type)
@@ -59,10 +60,25 @@
 	return pg;
 }
 
+struct page *
+ia32_install_gate_page (struct vm_area_struct *vma, unsigned long address, int *type)
+{
+	struct page *pg = ia32_gate_page;
+	get_page(pg);
+	if (type)
+		*type = VM_FAULT_MINOR;
+	return pg;
+}
+
+
 static struct vm_operations_struct ia32_shared_page_vm_ops = {
 	.nopage = ia32_install_shared_page
 };
 
+static struct vm_operations_struct ia32_gate_page_vm_ops = {
+	.nopage = ia32_install_gate_page
+};
+
 void
 ia64_elf32_init (struct pt_regs *regs)
 {
@@ -90,6 +106,29 @@
 	}
 
 	/*
+	 * When user stack is not executable, push sigreturn code to stack makes
+	 * segmentation fault raised when returning to kernel. So now sigreturn
+	 * code is locked in specific gate page, which is pointed by pretcode
+	 * when setup_frame_ia32
+	 */
+	vma = kmem_cache_alloc(vm_area_cachep, SLAB_KERNEL);
+	if (vma) {
+		memset(vma, 0, sizeof(*vma));
+		vma->vm_mm = current->mm;
+		vma->vm_start = IA32_GATE_OFFSET;
+		vma->vm_end = vma->vm_start + PAGE_SIZE;
+		vma->vm_page_prot = PAGE_COPY_EXEC;
+		vma->vm_flags = VM_READ | VM_MAYREAD | VM_EXEC
+				| VM_MAYEXEC | VM_RESERVED;
+		vma->vm_ops = &ia32_gate_page_vm_ops;
+		down_write(&current->mm->mmap_sem);
+		{
+			insert_vm_struct(current->mm, vma);
+		}
+		up_write(&current->mm->mmap_sem);
+	}
+
+	/*
 	 * Install LDT as anonymous memory.  This gives us all-zero segment descriptors
 	 * until a task modifies them via modify_ldt().
 	 */
@@ -187,7 +226,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/elfcore32.h b/arch/ia64/ia32/elfcore32.h
--- a/arch/ia64/ia32/elfcore32.h	2004-10-18 14:56:32 -07:00
+++ b/arch/ia64/ia32/elfcore32.h	2004-10-18 14:56:32 -07:00
@@ -103,11 +103,15 @@
 elf_core_copy_task_fpregs(struct task_struct *tsk, struct pt_regs *regs, elf_fpregset_t *fpu)
 {
 	struct ia32_user_i387_struct *fpstate = (void*)fpu;
+	mm_segment_t old_fs;
 
 	if (!tsk->used_math)
 		return 0;
-
-	save_ia32_fpstate(tsk, fpstate);
+	
+	old_fs = get_fs();
+	set_fs(KERNEL_DS);
+	save_ia32_fpstate(tsk, (struct ia32_user_i387_struct __user *) fpstate);
+	set_fs(old_fs);
 
 	return 1;
 }
@@ -117,11 +121,15 @@
 elf_core_copy_task_xfpregs(struct task_struct *tsk, elf_fpxregset_t *xfpu)
 {
 	struct ia32_user_fxsr_struct *fpxstate = (void*) xfpu;
+	mm_segment_t old_fs;
 
 	if (!tsk->used_math)
 		return 0;
 
-	save_ia32_fpxstate(tsk, fpxstate);
+	old_fs = get_fs();
+	set_fs(KERNEL_DS);
+	save_ia32_fpxstate(tsk, (struct ia32_user_fxsr_struct __user *) fpxstate);
+	set_fs(old_fs);
 
 	return 1;
 }
diff -Nru a/arch/ia64/ia32/ia32_entry.S b/arch/ia64/ia32/ia32_entry.S
--- a/arch/ia64/ia32/ia32_entry.S	2004-10-18 14:56:32 -07:00
+++ b/arch/ia64/ia32/ia32_entry.S	2004-10-18 14:56:32 -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
@@ -311,7 +311,7 @@
 	data8 sys_ni_syscall	  /* old profil syscall holder */
 	data8 compat_sys_statfs
 	data8 compat_sys_fstatfs	  /* 100 */
-	data8 sys32_ioperm
+	data8 sys_ni_syscall	/* ioperm */
 	data8 compat_sys_socketcall
 	data8 sys_syslog
 	data8 compat_sys_setitimer
@@ -320,7 +320,7 @@
 	data8 compat_sys_newlstat
 	data8 compat_sys_newfstat
 	data8 sys_ni_syscall
-	data8 sys32_iopl		  /* 110 */
+	data8 sys_ni_syscall	/* iopl */	/* 110 */
 	data8 sys_vhangup
 	data8 sys_ni_syscall		/* used to be sys_idle */
 	data8 sys_ni_syscall
@@ -493,6 +493,8 @@
   	data8 compat_sys_mq_timedreceive	/* 280 */
   	data8 compat_sys_mq_notify
   	data8 compat_sys_mq_getsetattr
+	data8 sys_ni_syscall		/* reserved for kexec */
+	data8 sys32_waitid
 
 	// guard against failures to increase IA32_NR_syscalls
 	.org ia32_syscall_table + 8*IA32_NR_syscalls
diff -Nru a/arch/ia64/ia32/ia32_ldt.c b/arch/ia64/ia32/ia32_ldt.c
--- a/arch/ia64/ia32/ia32_ldt.c	2004-10-18 14:57:04 -07:00
+++ b/arch/ia64/ia32/ia32_ldt.c	2004-10-18 14:57:04 -07:00
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2001 Hewlett-Packard Co
+ * Copyright (C) 2001, 2004 Hewlett-Packard Co
  *	David Mosberger-Tang <davidm@hpl.hp.com>
  *
  * Adapted from arch/i386/kernel/ldt.c
@@ -17,25 +17,24 @@
 
 #include "ia32priv.h"
 
-#define P(p)	((void *) (unsigned long) (p))
-
 /*
  * read_ldt() is not really atomic - this is not a problem since synchronization of reads
  * and writes done to the LDT has to be assured by user-space anyway. Writes are atomic,
  * to protect the security checks done on new descriptors.
  */
 static int
-read_ldt (void *ptr, unsigned long bytecount)
+read_ldt (void __user *ptr, unsigned long bytecount)
 {
-	char *src, *dst, buf[256];	/* temporary buffer (don't overflow kernel stack!) */
 	unsigned long bytes_left, n;
+	char __user *src, *dst;
+	char buf[256];	/* temporary buffer (don't overflow kernel stack!) */
 
 	if (bytecount > IA32_LDT_ENTRIES*IA32_LDT_ENTRY_SIZE)
 		bytecount = IA32_LDT_ENTRIES*IA32_LDT_ENTRY_SIZE;
 
 	bytes_left = bytecount;
 
-	src = (void *) IA32_LDT_OFFSET;
+	src = (void __user *) IA32_LDT_OFFSET;
 	dst = ptr;
 
 	while (bytes_left) {
@@ -61,7 +60,7 @@
 }
 
 static int
-read_default_ldt (void * ptr, unsigned long bytecount)
+read_default_ldt (void __user * ptr, unsigned long bytecount)
 {
 	unsigned long size;
 	int err;
@@ -80,7 +79,7 @@
 }
 
 static int
-write_ldt (void * ptr, unsigned long bytecount, int oldmode)
+write_ldt (void __user * ptr, unsigned long bytecount, int oldmode)
 {
 	struct ia32_user_desc ldt_info;
 	__u64 entry;
@@ -120,7 +119,7 @@
 	 * memory, but we still need to guard against out-of-memory, hence we must use
 	 * put_user().
 	 */
-	ret = __put_user(entry, (__u64 *) IA32_LDT_OFFSET + ldt_info.entry_number);
+	ret = __put_user(entry, (__u64 __user *) IA32_LDT_OFFSET + ldt_info.entry_number);
 	ia32_load_segment_descriptors(current);
 	return ret;
 }
@@ -132,16 +131,16 @@
 
 	switch (func) {
 	      case 0:
-		ret = read_ldt(P(ptr), bytecount);
+		ret = read_ldt(compat_ptr(ptr), bytecount);
 		break;
 	      case 1:
-		ret = write_ldt(P(ptr), bytecount, 1);
+		ret = write_ldt(compat_ptr(ptr), bytecount, 1);
 		break;
 	      case 2:
-		ret = read_default_ldt(P(ptr), bytecount);
+		ret = read_default_ldt(compat_ptr(ptr), bytecount);
 		break;
 	      case 0x11:
-		ret = write_ldt(P(ptr), bytecount, 0);
+		ret = write_ldt(compat_ptr(ptr), bytecount, 0);
 		break;
 	}
 	return ret;
diff -Nru a/arch/ia64/ia32/ia32_signal.c b/arch/ia64/ia32/ia32_signal.c
--- a/arch/ia64/ia32/ia32_signal.c	2004-10-18 14:55:54 -07:00
+++ b/arch/ia64/ia32/ia32_signal.c	2004-10-18 14:55:54 -07:00
@@ -66,7 +66,7 @@
 };
 
 int
-copy_siginfo_from_user32 (siginfo_t *to, siginfo_t32 *from)
+copy_siginfo_from_user32 (siginfo_t *to, siginfo_t32 __user *from)
 {
 	unsigned long tmp;
 	int err;
@@ -78,10 +78,10 @@
 	err |= __get_user(to->si_errno, &from->si_errno);
 	err |= __get_user(to->si_code, &from->si_code);
 
-	if (from->si_code < 0)
+	if (to->si_code < 0)
 		err |= __copy_from_user(&to->_sifields._pad, &from->_sifields._pad, SI_PAD_SIZE);
 	else {
-		switch (from->si_code >> 16) {
+		switch (to->si_code >> 16) {
 		      case __SI_CHLD >> 16:
 			err |= __get_user(to->si_utime, &from->si_utime);
 			err |= __get_user(to->si_stime, &from->si_stime);
@@ -92,7 +92,7 @@
 			break;
 		      case __SI_FAULT >> 16:
 			err |= __get_user(tmp, &from->si_addr);
-			to->si_addr = (void *) tmp;
+			to->si_addr = (void __user *) tmp;
 			break;
 		      case __SI_POLL >> 16:
 			err |= __get_user(to->si_band, &from->si_band);
@@ -110,7 +110,7 @@
 }
 
 int
-copy_siginfo_to_user32 (siginfo_t32 *to, siginfo_t *from)
+copy_siginfo_to_user32 (siginfo_t32 __user *to, siginfo_t *from)
 {
 	unsigned int addr;
 	int err;
@@ -141,7 +141,8 @@
 			err |= __put_user(from->si_uid, &to->si_uid);
 			break;
 		case __SI_FAULT >> 16:
-			err |= __put_user((long)from->si_addr, &to->si_addr);
+			/* avoid type-checking warnings by copying _pad[0] in lieu of si_addr... */
+			err |= __put_user(from->_sifields._pad[0], &to->si_addr);
 			break;
 		case __SI_POLL >> 16:
 			err |= __put_user(from->si_band, &to->si_band);
@@ -202,7 +203,7 @@
  */
 
 static int
-save_ia32_fpstate_live (struct _fpstate_ia32 *save)
+save_ia32_fpstate_live (struct _fpstate_ia32 __user *save)
 {
 	struct task_struct *tsk = current;
 	struct pt_regs *ptp;
@@ -310,7 +311,7 @@
 }
 
 static int
-restore_ia32_fpstate_live (struct _fpstate_ia32 *save)
+restore_ia32_fpstate_live (struct _fpstate_ia32 __user *save)
 {
 	struct task_struct *tsk = current;
 	struct pt_regs *ptp;
@@ -339,37 +340,37 @@
 	fir = ia64_getreg(_IA64_REG_AR_FIR);
 	fdr = ia64_getreg(_IA64_REG_AR_FDR);
 
-	__get_user(mxcsr, (unsigned int *)&save->mxcsr);
+	__get_user(mxcsr, (unsigned int __user *)&save->mxcsr);
 	/* setting bits 0..5 8..12 with cw and 39..47 from mxcsr */
-	__get_user(lo, (unsigned int *)&save->cw);
+	__get_user(lo, (unsigned int __user *)&save->cw);
 	num64 = mxcsr & 0xff10;
 	num64 = (num64 << 32) | (lo & 0x1f3f);
-	fcr = (fcr & (~0xff1000001f3f)) | num64;
+	fcr = (fcr & (~0xff1000001f3fUL)) | num64;
 
 	/* setting bits 0..31 with sw and tag and 32..37 from mxcsr */
-	__get_user(lo, (unsigned int *)&save->sw);
+	__get_user(lo, (unsigned int __user *)&save->sw);
 	/* set bits 15,7 (fsw.b, fsw.es) to reflect the current error status */
 	if ( !(lo & 0x7f) )
 		lo &= (~0x8080);
-	__get_user(hi, (unsigned int *)&save->tag);
+	__get_user(hi, (unsigned int __user *)&save->tag);
 	num64 = mxcsr & 0x3f;
 	num64 = (num64 << 16) | (hi & 0xffff);
 	num64 = (num64 << 16) | (lo & 0xffff);
-	fsr = (fsr & (~0x3fffffffff)) | num64;
+	fsr = (fsr & (~0x3fffffffffUL)) | num64;
 
 	/* setting bits 0..47 with cssel and ipoff */
-	__get_user(lo, (unsigned int *)&save->ipoff);
-	__get_user(hi, (unsigned int *)&save->cssel);
+	__get_user(lo, (unsigned int __user *)&save->ipoff);
+	__get_user(hi, (unsigned int __user *)&save->cssel);
 	num64 = hi & 0xffff;
 	num64 = (num64 << 32) | lo;
-	fir = (fir & (~0xffffffffffff)) | num64;
+	fir = (fir & (~0xffffffffffffUL)) | num64;
 
 	/* setting bits 0..47 with datasel and dataoff */
-	__get_user(lo, (unsigned int *)&save->dataoff);
-	__get_user(hi, (unsigned int *)&save->datasel);
+	__get_user(lo, (unsigned int __user *)&save->dataoff);
+	__get_user(hi, (unsigned int __user *)&save->datasel);
 	num64 = hi & 0xffff;
 	num64 = (num64 << 32) | lo;
-	fdr = (fdr & (~0xffffffffffff)) | num64;
+	fdr = (fdr & (~0xffffffffffffUL)) | num64;
 
 	ia64_setreg(_IA64_REG_AR_FSR, fsr);
 	ia64_setreg(_IA64_REG_AR_FCR, fcr);
@@ -452,8 +453,8 @@
 		sa->sa.sa_handler = (__sighandler_t) (((unsigned long) restorer << 32) | handler);
 }
 
-asmlinkage long
-ia32_rt_sigsuspend (compat_sigset_t *uset, unsigned int sigsetsize, struct sigscratch *scr)
+long
+__ia32_rt_sigsuspend (compat_sigset_t *sset, unsigned int sigsetsize, struct sigscratch *scr)
 {
 	extern long ia64_do_signal (sigset_t *oldset, struct sigscratch *scr, long in_syscall);
 	sigset_t oldset, set;
@@ -461,10 +462,7 @@
 	scr->scratch_unat = 0;	/* avoid leaking kernel bits to user level */
 	memset(&set, 0, sizeof(&set));
 
-	if (sigsetsize > sizeof(sigset_t))
-		return -EINVAL;
-
-	if (copy_from_user(&set.sig, &uset->sig, sigsetsize))
+	if (memcpy(&set.sig, &sset->sig, sigsetsize))
 		return -EFAULT;
 
 	sigdelsetmask(&set, ~_BLOCKABLE);
@@ -492,9 +490,23 @@
 }
 
 asmlinkage long
+ia32_rt_sigsuspend (compat_sigset_t __user *uset, unsigned int sigsetsize, struct sigscratch *scr)
+{
+	compat_sigset_t set;
+
+	if (sigsetsize > sizeof(compat_sigset_t))
+		return -EINVAL;
+
+	if (copy_from_user(&set.sig, &uset->sig, sigsetsize))
+		return -EFAULT;
+
+	return __ia32_rt_sigsuspend(&set, sigsetsize, scr);
+}
+
+asmlinkage long
 ia32_sigsuspend (unsigned int mask, struct sigscratch *scr)
 {
-	return ia32_rt_sigsuspend((compat_sigset_t *)&mask, sizeof(mask), scr);
+	return __ia32_rt_sigsuspend((compat_sigset_t *) &mask, sizeof(mask), scr);
 }
 
 asmlinkage long
@@ -512,8 +524,8 @@
 }
 
 asmlinkage long
-sys32_rt_sigaction (int sig, struct sigaction32 *act,
-		    struct sigaction32 *oact, unsigned int sigsetsize)
+sys32_rt_sigaction (int sig, struct sigaction32 __user *act,
+		    struct sigaction32 __user *oact, unsigned int sigsetsize)
 {
 	struct k_sigaction new_ka, old_ka;
 	unsigned int handler, restorer;
@@ -547,7 +559,8 @@
 
 
 asmlinkage long
-sys32_rt_sigprocmask (int how, compat_sigset_t *set, compat_sigset_t *oset, unsigned int sigsetsize)
+sys32_rt_sigprocmask (int how, compat_sigset_t __user *set, compat_sigset_t __user *oset,
+		      unsigned int sigsetsize)
 {
 	mm_segment_t old_fs = get_fs();
 	sigset_t s;
@@ -562,7 +575,9 @@
 			return -EFAULT;
 	}
 	set_fs(KERNEL_DS);
-	ret = sys_rt_sigprocmask(how, set ? &s : NULL, oset ? &s : NULL, sizeof(s));
+	ret = sys_rt_sigprocmask(how,
+				 set ? (sigset_t __user *) &s : NULL,
+				 oset ? (sigset_t __user *) &s : NULL, sizeof(s));
 	set_fs(old_fs);
 	if (ret)
 		return ret;
@@ -574,10 +589,9 @@
 }
 
 asmlinkage long
-sys32_rt_sigtimedwait (compat_sigset_t *uthese, siginfo_t32 *uinfo,
-		struct compat_timespec *uts, unsigned int sigsetsize)
+sys32_rt_sigtimedwait (compat_sigset_t __user *uthese, siginfo_t32 __user *uinfo,
+		       struct compat_timespec __user *uts, unsigned int sigsetsize)
 {
-	extern int copy_siginfo_to_user32 (siginfo_t32 *, siginfo_t *);
 	mm_segment_t old_fs = get_fs();
 	struct timespec t;
 	siginfo_t info;
@@ -589,8 +603,10 @@
 	if (uts && get_compat_timespec(&t, uts))
 		return -EFAULT;
 	set_fs(KERNEL_DS);
-	ret = sys_rt_sigtimedwait(&s, uinfo ? &info : NULL, uts ? &t : NULL,
-			sigsetsize);
+	ret = sys_rt_sigtimedwait((sigset_t __user *) &s,
+				  uinfo ? (siginfo_t __user *) &info : NULL,
+				  uts ? (struct timespec __user *) &t : NULL,
+				  sigsetsize);
 	set_fs(old_fs);
 	if (ret >= 0 && uinfo) {
 		if (copy_siginfo_to_user32(uinfo, &info))
@@ -600,7 +616,7 @@
 }
 
 asmlinkage long
-sys32_rt_sigqueueinfo (int pid, int sig, siginfo_t32 *uinfo)
+sys32_rt_sigqueueinfo (int pid, int sig, siginfo_t32 __user *uinfo)
 {
 	mm_segment_t old_fs = get_fs();
 	siginfo_t info;
@@ -609,13 +625,13 @@
 	if (copy_siginfo_from_user32(&info, uinfo))
 		return -EFAULT;
 	set_fs(KERNEL_DS);
-	ret = sys_rt_sigqueueinfo(pid, sig, &info);
+	ret = sys_rt_sigqueueinfo(pid, sig, (siginfo_t __user *) &info);
 	set_fs(old_fs);
 	return ret;
 }
 
 asmlinkage long
-sys32_sigaction (int sig, struct old_sigaction32 *act, struct old_sigaction32 *oact)
+sys32_sigaction (int sig, struct old_sigaction32 __user *act, struct old_sigaction32 __user *oact)
 {
 	struct k_sigaction new_ka, old_ka;
 	unsigned int handler, restorer;
@@ -648,7 +664,7 @@
 }
 
 static int
-setup_sigcontext_ia32 (struct sigcontext_ia32 *sc, struct _fpstate_ia32 *fpstate,
+setup_sigcontext_ia32 (struct sigcontext_ia32 __user *sc, struct _fpstate_ia32 __user *fpstate,
 		       struct pt_regs *regs, unsigned long mask)
 {
 	int  err = 0;
@@ -657,10 +673,10 @@
 	if (!access_ok(VERIFY_WRITE, sc, sizeof(*sc)))
 		return -EFAULT;
 
-	err |= __put_user((regs->r16 >> 32) & 0xffff, (unsigned int *)&sc->fs);
-	err |= __put_user((regs->r16 >> 48) & 0xffff, (unsigned int *)&sc->gs);
-	err |= __put_user((regs->r16 >> 16) & 0xffff, (unsigned int *)&sc->es);
-	err |= __put_user(regs->r16 & 0xffff, (unsigned int *)&sc->ds);
+	err |= __put_user((regs->r16 >> 32) & 0xffff, (unsigned int __user *)&sc->fs);
+	err |= __put_user((regs->r16 >> 48) & 0xffff, (unsigned int __user *)&sc->gs);
+	err |= __put_user((regs->r16 >> 16) & 0xffff, (unsigned int __user *)&sc->es);
+	err |= __put_user(regs->r16 & 0xffff, (unsigned int __user *)&sc->ds);
 	err |= __put_user(regs->r15, &sc->edi);
 	err |= __put_user(regs->r14, &sc->esi);
 	err |= __put_user(regs->r13, &sc->ebp);
@@ -674,14 +690,14 @@
 	err |= __put_user(current->tss.error_code, &sc->err);
 #endif
 	err |= __put_user(regs->cr_iip, &sc->eip);
-	err |= __put_user(regs->r17 & 0xffff, (unsigned int *)&sc->cs);
+	err |= __put_user(regs->r17 & 0xffff, (unsigned int __user *)&sc->cs);
 	/*
 	 *  `eflags' is in an ar register for this context
 	 */
 	flag = ia64_getreg(_IA64_REG_AR_EFLAG);
 	err |= __put_user((unsigned int)flag, &sc->eflags);
 	err |= __put_user(regs->r12, &sc->esp_at_signal);
-	err |= __put_user((regs->r17 >> 16) & 0xffff, (unsigned int *)&sc->ss);
+	err |= __put_user((regs->r17 >> 16) & 0xffff, (unsigned int __user *)&sc->ss);
 
 	if ( save_ia32_fpstate_live(fpstate) < 0 )
 		err = -EFAULT;
@@ -705,7 +721,7 @@
 }
 
 static int
-restore_sigcontext_ia32 (struct pt_regs *regs, struct sigcontext_ia32 *sc, int *peax)
+restore_sigcontext_ia32 (struct pt_regs *regs, struct sigcontext_ia32 __user *sc, int *peax)
 {
 	unsigned int err = 0;
 
@@ -775,10 +791,10 @@
 	}
 
 	{
-		struct _fpstate_ia32 *buf = NULL;
+		struct _fpstate_ia32 __user *buf = NULL;
 		u32    fpstate_ptr;
 		err |= get_user(fpstate_ptr, &(sc->fpstate));
-		buf = (struct _fpstate_ia32 *)(u64)fpstate_ptr;
+		buf = compat_ptr(fpstate_ptr);
 		if (buf) {
 			err |= restore_ia32_fpstate_live(buf);
 		}
@@ -808,7 +824,7 @@
 /*
  * Determine which stack to use..
  */
-static inline void *
+static inline void __user *
 get_sigframe (struct k_sigaction *ka, struct pt_regs * regs, size_t frame_size)
 {
 	unsigned long esp;
@@ -823,14 +839,14 @@
 	}
 	/* Legacy stack switching not supported */
 
-	return (void *)((esp - frame_size) & -8ul);
+	return (void __user *)((esp - frame_size) & -8ul);
 }
 
 static int
 setup_frame_ia32 (int sig, struct k_sigaction *ka, sigset_t *set, struct pt_regs * regs)
 {
 	struct exec_domain *ed = current_thread_info()->exec_domain;
-	struct sigframe_ia32 *frame;
+	struct sigframe_ia32 __user *frame;
 	int err = 0;
 
 	frame = get_sigframe(ka, regs, sizeof(*frame));
@@ -853,14 +869,19 @@
 		unsigned int restorer = IA32_SA_RESTORER(ka);
 		err |= __put_user(restorer, &frame->pretcode);
 	} else {
-		err |= __put_user((long)frame->retcode, &frame->pretcode);
-		/* This is popl %eax ; movl $,%eax ; int $0x80 */
-		err |= __put_user(0xb858, (short *)(frame->retcode+0));
-		err |= __put_user(__IA32_NR_sigreturn & 0xffff, (short *)(frame->retcode+2));
-		err |= __put_user(__IA32_NR_sigreturn >> 16, (short *)(frame->retcode+4));
-		err |= __put_user(0x80cd, (short *)(frame->retcode+6));
+		/* Pointing to restorer in ia32 gate page */
+		err |= __put_user(IA32_GATE_OFFSET, &frame->pretcode);
 	}
 
+	/* This is popl %eax ; movl $,%eax ; int $0x80
+	 * and there for historical reasons only.
+	 * See arch/i386/kernel/signal.c
+	 */
+
+	err |= __put_user(0xb858, (short __user *)(frame->retcode+0));
+	err |= __put_user(__IA32_NR_sigreturn, (int __user *)(frame->retcode+2));
+	err |= __put_user(0x80cd, (short __user *)(frame->retcode+6));
+
 	if (err)
 		goto give_sigsegv;
 
@@ -882,9 +903,7 @@
 	return 1;
 
   give_sigsegv:
-	if (sig == SIGSEGV)
-		ka->sa.sa_handler = SIG_DFL;
-	force_sig(SIGSEGV, current);
+	force_sigsegv(sig, current);
 	return 0;
 }
 
@@ -893,7 +912,8 @@
 		     sigset_t *set, struct pt_regs * regs)
 {
 	struct exec_domain *ed = current_thread_info()->exec_domain;
-	struct rt_sigframe_ia32 *frame;
+	compat_uptr_t pinfo, puc;
+	struct rt_sigframe_ia32 __user *frame;
 	int err = 0;
 
 	frame = get_sigframe(ka, regs, sizeof(*frame));
@@ -903,8 +923,11 @@
 
 	err |= __put_user((ed && ed->signal_invmap
 			   && sig < 32 ? ed->signal_invmap[sig] : sig), &frame->sig);
-	err |= __put_user((long)&frame->info, &frame->pinfo);
-	err |= __put_user((long)&frame->uc, &frame->puc);
+
+	pinfo = (long __user) &frame->info;
+	puc = (long __user) &frame->uc;
+	err |= __put_user(pinfo, &frame->pinfo);
+	err |= __put_user(puc, &frame->puc);
 	err |= copy_siginfo_to_user32(&frame->info, info);
 
 	/* Create the ucontext.  */
@@ -924,13 +947,19 @@
 		unsigned int restorer = IA32_SA_RESTORER(ka);
 		err |= __put_user(restorer, &frame->pretcode);
 	} else {
-		err |= __put_user((long)frame->retcode, &frame->pretcode);
-		/* This is movl $,%eax ; int $0x80 */
-		err |= __put_user(0xb8, (char *)(frame->retcode+0));
-		err |= __put_user(__IA32_NR_rt_sigreturn, (int *)(frame->retcode+1));
-		err |= __put_user(0x80cd, (short *)(frame->retcode+5));
+		/* Pointing to rt_restorer in ia32 gate page */
+		err |= __put_user(IA32_GATE_OFFSET + 8, &frame->pretcode);
 	}
 
+	/* This is movl $,%eax ; int $0x80
+	 * and there for historical reasons only.
+	 * See arch/i386/kernel/signal.c
+	 */
+
+	err |= __put_user(0xb8, (char __user *)(frame->retcode+0));
+	err |= __put_user(__IA32_NR_rt_sigreturn, (int __user *)(frame->retcode+1));
+	err |= __put_user(0x80cd, (short __user *)(frame->retcode+5));
+
 	if (err)
 		goto give_sigsegv;
 
@@ -952,9 +981,7 @@
 	return 1;
 
 give_sigsegv:
-	if (sig == SIGSEGV)
-		ka->sa.sa_handler = SIG_DFL;
-	force_sig(SIGSEGV, current);
+	force_sigsegv(sig, current);
 	return 0;
 }
 
@@ -975,7 +1002,7 @@
 {
 	struct pt_regs *regs = (struct pt_regs *) &stack;
 	unsigned long esp = (unsigned int) regs->r12;
-	struct sigframe_ia32 *frame = (struct sigframe_ia32 *)(esp - 8);
+	struct sigframe_ia32 __user *frame = (struct sigframe_ia32 __user *)(esp - 8);
 	sigset_t set;
 	int eax;
 
@@ -989,7 +1016,7 @@
 
 	sigdelsetmask(&set, ~_BLOCKABLE);
 	spin_lock_irq(&current->sighand->siglock);
-	current->blocked = (sigset_t) set;
+	current->blocked = set;
 	recalc_sigpending();
 	spin_unlock_irq(&current->sighand->siglock);
 
@@ -1008,9 +1035,8 @@
 {
 	struct pt_regs *regs = (struct pt_regs *) &stack;
 	unsigned long esp = (unsigned int) regs->r12;
-	struct rt_sigframe_ia32 *frame = (struct rt_sigframe_ia32 *)(esp - 4);
+	struct rt_sigframe_ia32 __user *frame = (struct rt_sigframe_ia32 __user *)(esp - 4);
 	sigset_t set;
-	stack_t st;
 	int eax;
 
 	if (verify_area(VERIFY_READ, frame, sizeof(*frame)))
@@ -1027,11 +1053,9 @@
 	if (restore_sigcontext_ia32(regs, &frame->uc.uc_mcontext, &eax))
 		goto badframe;
 
-	if (__copy_from_user(&st, &frame->uc.uc_stack, sizeof(st)))
-		goto badframe;
 	/* It is more difficult to avoid calling this function than to
 	   call it and ignore errors.  */
-	do_sigaltstack(&st, NULL, esp);
+	do_sigaltstack((stack_t __user *) &frame->uc.uc_stack, NULL, esp);
 
 	return eax;
 
diff -Nru a/arch/ia64/ia32/ia32_support.c b/arch/ia64/ia32/ia32_support.c
--- a/arch/ia64/ia32/ia32_support.c	2004-10-18 14:55:54 -07:00
+++ b/arch/ia64/ia32/ia32_support.c	2004-10-18 14:55:54 -07:00
@@ -33,6 +33,7 @@
 struct page *ia32_shared_page[NR_CPUS];
 unsigned long *ia32_boot_gdt;
 unsigned long *cpu_gdt_table[NR_CPUS];
+struct page *ia32_gate_page;
 
 static unsigned long
 load_desc (u16 selector)
@@ -75,7 +76,7 @@
 	struct ia32_user_desc info;
 	int idx;
 
-	if (copy_from_user(&info, (void *)(childregs->r14 & 0xffffffff), sizeof(info)))
+	if (copy_from_user(&info, (void __user *)(childregs->r14 & 0xffffffff), sizeof(info)))
 		return -EFAULT;
 	if (LDT_empty(&info))
 		return -EINVAL;
@@ -145,6 +146,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 */
@@ -155,23 +159,26 @@
 /*
  * Setup IA32 GDT and TSS
  */
-void
+static void
 ia32_boot_gdt_init (void)
 {
 	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;
 
 	/* CS descriptor in IA-32 (scrambled) format */
 	ia32_boot_gdt[__USER_CS >> 3]
-		= IA32_SEG_DESCRIPTOR(0, (IA32_PAGE_OFFSET-1) >> IA32_PAGE_SHIFT,
+		= IA32_SEG_DESCRIPTOR(0, (IA32_GATE_END-1) >> IA32_PAGE_SHIFT,
 				      0xb, 1, 3, 1, 1, 1, 1);
 
 	/* DS descriptor in IA-32 (scrambled) format */
 	ia32_boot_gdt[__USER_DS >> 3]
-		= IA32_SEG_DESCRIPTOR(0, (IA32_PAGE_OFFSET-1) >> IA32_PAGE_SHIFT,
+		= IA32_SEG_DESCRIPTOR(0, (IA32_GATE_END-1) >> IA32_PAGE_SHIFT,
 				      0x3, 1, 3, 1, 1, 1, 1);
 
 	ldt_size = PAGE_ALIGN(IA32_LDT_ENTRIES*IA32_LDT_ENTRY_SIZE);
@@ -181,6 +188,27 @@
 						       0x2, 0, 3, 1, 1, 1, 0);
 }
 
+static void
+ia32_gate_page_init(void)
+{
+	unsigned long *sr;
+
+	ia32_gate_page = alloc_page(GFP_KERNEL);
+	sr = page_address(ia32_gate_page);
+	/* This is popl %eax ; movl $,%eax ; int $0x80 */
+	*sr++ = 0xb858 | (__IA32_NR_sigreturn << 16) | (0x80cdUL << 48);
+
+	/* This is movl $,%eax ; int $0x80 */
+	*sr = 0xb8 | (__IA32_NR_rt_sigreturn << 8) | (0x80cdUL << 40);
+}
+
+void
+ia32_mem_init(void)
+{
+	ia32_boot_gdt_init();
+	ia32_gate_page_init();
+}
+
 /*
  * Handle bad IA32 interrupt via syscall
  */
@@ -195,7 +223,7 @@
 	siginfo.si_errno = int_num;	/* XXX is it OK to abuse si_errno like this? */
 	siginfo.si_flags = 0;
 	siginfo.si_isr = 0;
-	siginfo.si_addr = 0;
+	siginfo.si_addr = NULL;
 	siginfo.si_imm = 0;
 	siginfo.si_code = TRAP_BRKPT;
 	force_sig_info(SIGTRAP, &siginfo, current);
diff -Nru a/arch/ia64/ia32/ia32priv.h b/arch/ia64/ia32/ia32priv.h
--- a/arch/ia64/ia32/ia32priv.h	2004-10-18 14:57:04 -07:00
+++ b/arch/ia64/ia32/ia32priv.h	2004-10-18 14:57:04 -07:00
@@ -168,6 +168,9 @@
 #define IA32_SA_HANDLER(ka)	((unsigned long) (ka)->sa.sa_handler & 0xffffffff)
 #define IA32_SA_RESTORER(ka)	((unsigned long) (ka)->sa.sa_handler >> 32)
 
+#define __IA32_NR_sigreturn 119
+#define __IA32_NR_rt_sigreturn 173
+
 struct sigaction32 {
        unsigned int sa_handler;		/* Really a pointer, but need to deal with 32 bits */
        unsigned int sa_flags;
@@ -324,14 +327,16 @@
 
 #define IA32_PAGE_OFFSET	0xc0000000
 #define IA32_STACK_TOP		IA32_PAGE_OFFSET
+#define IA32_GATE_OFFSET	IA32_PAGE_OFFSET
+#define IA32_GATE_END		IA32_PAGE_OFFSET + PAGE_SIZE
 
 /*
  * The system segments (GDT, TSS, LDT) have to be mapped below 4GB so the IA-32 engine can
  * access them.
  */
-#define IA32_GDT_OFFSET		(IA32_PAGE_OFFSET)
-#define IA32_TSS_OFFSET		(IA32_PAGE_OFFSET + PAGE_SIZE)
-#define IA32_LDT_OFFSET		(IA32_PAGE_OFFSET + 2*PAGE_SIZE)
+#define IA32_GDT_OFFSET		(IA32_PAGE_OFFSET + PAGE_SIZE)
+#define IA32_TSS_OFFSET		(IA32_PAGE_OFFSET + 2*PAGE_SIZE)
+#define IA32_LDT_OFFSET		(IA32_PAGE_OFFSET + 3*PAGE_SIZE)
 
 #define ELF_EXEC_PAGESIZE	IA32_PAGE_SIZE
 
@@ -356,7 +361,7 @@
 /* This macro yields a string that ld.so will use to load
    implementation specific libraries for optimization.  Not terribly
    relevant until we have real hardware to play with... */
-#define ELF_PLATFORM	0
+#define ELF_PLATFORM	NULL
 
 #ifdef __KERNEL__
 # define SET_PERSONALITY(EX,IBCS2)				\
@@ -434,7 +439,7 @@
 	 | ((((sd) >> IA32_SEG_DB) & 0x1) << SEG_DB)						 \
 	 | ((((sd) >> IA32_SEG_G) & 0x1) << SEG_G))
 
-#define IA32_IOBASE	0x2000000000000000 /* Virtual address for I/O space */
+#define IA32_IOBASE	0x2000000000000000UL /* Virtual address for I/O space */
 
 #define IA32_CR0	0x80000001	/* Enable PG and PE bits */
 #define IA32_CR4	0x600		/* MMXEX and FXSR on */
@@ -551,8 +556,8 @@
 };
 
 /* Prototypes for use in elfcore32.h */
-extern int save_ia32_fpstate (struct task_struct *tsk, struct ia32_user_i387_struct *save);
-extern int save_ia32_fpxstate (struct task_struct *tsk, struct ia32_user_fxsr_struct *save);
+extern int save_ia32_fpstate (struct task_struct *, struct ia32_user_i387_struct __user *);
+extern int save_ia32_fpxstate (struct task_struct *, struct ia32_user_fxsr_struct __user *);
 
 #endif /* !CONFIG_IA32_SUPPORT */
 
diff -Nru a/arch/ia64/ia32/sys_ia32.c b/arch/ia64/ia32/sys_ia32.c
--- a/arch/ia64/ia32/sys_ia32.c	2004-10-18 14:56:33 -07:00
+++ b/arch/ia64/ia32/sys_ia32.c	2004-10-18 14:56:33 -07:00
@@ -70,10 +70,7 @@
 # define DBG(fmt...)
 #endif
 
-#define A(__x)		((unsigned long)(__x))
-#define AA(__x)		((unsigned long)(__x))
 #define ROUND_UP(x,a)	((__typeof__(x))(((unsigned long)(x) + ((a) - 1)) & ~((a) - 1)))
-#define NAME_OFFSET(de) ((int) ((de)->d_name - (char *) (de)))
 
 #define OFFSET4K(a)		((a) & 0xfff)
 #define PAGE_START(addr)	((addr) & PAGE_MASK)
@@ -82,9 +79,6 @@
 #define high2lowuid(uid) ((uid) > 65535 ? 65534 : (uid))
 #define high2lowgid(gid) ((gid) > 65535 ? 65534 : (gid))
 
-extern unsigned long arch_get_unmapped_area (struct file *, unsigned long, unsigned long,
-					     unsigned long, unsigned long);
-
 /*
  * Anything that modifies or inspects ia32 user virtual memory must hold this semaphore
  * while doing so.
@@ -93,7 +87,8 @@
 static DECLARE_MUTEX(ia32_mmap_sem);
 
 asmlinkage long
-sys32_execve (char *name, compat_uptr_t __user *argv, compat_uptr_t __user *envp, struct pt_regs *regs)
+sys32_execve (char __user *name, compat_uptr_t __user *argv, compat_uptr_t __user *envp,
+	      struct pt_regs *regs)
 {
 	long error;
 	char *filename;
@@ -128,7 +123,7 @@
 	return error;
 }
 
-int cp_compat_stat(struct kstat *stat, struct compat_stat *ubuf)
+int cp_compat_stat(struct kstat *stat, struct compat_stat __user *ubuf)
 {
 	int err;
 
@@ -199,7 +194,7 @@
 
 	/* Optimize the case where the old mmap and the new mmap are both anonymous */
 	if ((old_prot & PROT_WRITE) && (flags & MAP_ANONYMOUS) && !vma->vm_file) {
-		if (clear_user((void *) start, end - start)) {
+		if (clear_user((void __user *) start, end - start)) {
 			ret = -EFAULT;
 			goto out;
 		}
@@ -211,11 +206,11 @@
 		return -ENOMEM;
 
 	if (old_prot)
-		copy_from_user(page, (void *) PAGE_START(start), PAGE_SIZE);
+		copy_from_user(page, (void __user *) PAGE_START(start), PAGE_SIZE);
 
 	down_write(&current->mm->mmap_sem);
 	{
-		ret = do_mmap(0, PAGE_START(start), PAGE_SIZE, prot | PROT_WRITE,
+		ret = do_mmap(NULL, PAGE_START(start), PAGE_SIZE, prot | PROT_WRITE,
 			      flags | MAP_FIXED | MAP_ANONYMOUS, 0);
 	}
 	up_write(&current->mm->mmap_sem);
@@ -226,9 +221,10 @@
 	if (old_prot) {
 		/* copy back the old page contents.  */
 		if (offset_in_page(start))
-			copy_to_user((void *) PAGE_START(start), page, offset_in_page(start));
+			copy_to_user((void __user *) PAGE_START(start), page,
+				     offset_in_page(start));
 		if (offset_in_page(end))
-			copy_to_user((void *) end, page + offset_in_page(end),
+			copy_to_user((void __user *) end, page + offset_in_page(end),
 				     PAGE_SIZE - offset_in_page(end));
 	}
 
@@ -236,7 +232,7 @@
 		/* read the file contents */
 		inode = file->f_dentry->d_inode;
 		if (!inode->i_fop || !file->f_op->read
-		    || ((*file->f_op->read)(file, (char *) start, end - start, &off) < 0))
+		    || ((*file->f_op->read)(file, (char __user *) start, end - start, &off) < 0))
 		{
 			ret = -EINVAL;
 			goto out;
@@ -266,9 +262,9 @@
 
 	if ((p = kmalloc(sizeof(*p), GFP_KERNEL)) == NULL)
 		return p;
-	p->pp_head = 0;
+	p->pp_head = NULL;
 	p->ppl_rb = RB_ROOT;
-	p->pp_hint = 0;
+	p->pp_hint = NULL;
 	atomic_set(&p->pp_count, 1);
 	return p;
 }
@@ -825,7 +821,7 @@
 		if (!(flags & MAP_ANONYMOUS) && is_congruent)
 			ret = do_mmap(file, pstart, pend - pstart, prot, flags | MAP_FIXED, poff);
 		else
-			ret = do_mmap(0, pstart, pend - pstart,
+			ret = do_mmap(NULL, pstart, pend - pstart,
 				      prot | ((flags & MAP_ANONYMOUS) ? 0 : PROT_WRITE),
 				      flags | MAP_FIXED | MAP_ANONYMOUS, 0);
 	}
@@ -838,7 +834,8 @@
 		/* read the file contents */
 		inode = file->f_dentry->d_inode;
 		if (!inode->i_fop || !file->f_op->read
-		    || ((*file->f_op->read)(file, (char *) pstart, pend - pstart, &poff) < 0))
+		    || ((*file->f_op->read)(file, (char __user *) pstart, pend - pstart, &poff)
+			< 0))
 		{
 			sys_munmap(pstart, pend - pstart);
 			return -EINVAL;
@@ -927,7 +924,7 @@
 };
 
 asmlinkage long
-sys32_mmap (struct mmap_arg_struct *arg)
+sys32_mmap (struct mmap_arg_struct __user *arg)
 {
 	struct mmap_arg_struct a;
 	struct file *file = NULL;
@@ -1140,7 +1137,7 @@
 }
 
 asmlinkage long
-sys32_pipe (int *fd)
+sys32_pipe (int __user *fd)
 {
 	int retval;
 	int fds[2];
@@ -1155,14 +1152,14 @@
 }
 
 static inline long
-get_tv32 (struct timeval *o, struct compat_timeval *i)
+get_tv32 (struct timeval *o, struct compat_timeval __user *i)
 {
 	return (!access_ok(VERIFY_READ, i, sizeof(*i)) ||
 		(__get_user(o->tv_sec, &i->tv_sec) | __get_user(o->tv_usec, &i->tv_usec)));
 }
 
 static inline long
-put_tv32 (struct compat_timeval *o, struct timeval *i)
+put_tv32 (struct compat_timeval __user *o, struct timeval *i)
 {
 	return (!access_ok(VERIFY_WRITE, o, sizeof(*o)) ||
 		(__put_user(i->tv_sec, &o->tv_sec) | __put_user(i->tv_usec, &o->tv_usec)));
@@ -1192,7 +1189,7 @@
 extern struct timezone sys_tz;
 
 asmlinkage long
-sys32_gettimeofday (struct compat_timeval *tv, struct timezone *tz)
+sys32_gettimeofday (struct compat_timeval __user *tv, struct timezone __user *tz)
 {
 	if (tv) {
 		struct timeval ktv;
@@ -1208,7 +1205,7 @@
 }
 
 asmlinkage long
-sys32_settimeofday (struct compat_timeval *tv, struct timezone *tz)
+sys32_settimeofday (struct compat_timeval __user *tv, struct timezone __user *tz)
 {
 	struct timeval ktv;
 	struct timespec kts;
@@ -1229,14 +1226,14 @@
 }
 
 struct getdents32_callback {
-	struct compat_dirent * current_dir;
-	struct compat_dirent * previous;
+	struct compat_dirent __user *current_dir;
+	struct compat_dirent __user *previous;
 	int count;
 	int error;
 };
 
 struct readdir32_callback {
-	struct old_linux32_dirent * dirent;
+	struct old_linux32_dirent __user * dirent;
 	int count;
 };
 
@@ -1244,9 +1241,9 @@
 filldir32 (void *__buf, const char *name, int namlen, loff_t offset, ino_t ino,
 	   unsigned int d_type)
 {
-	struct compat_dirent * dirent;
+	struct compat_dirent __user * dirent;
 	struct getdents32_callback * buf = (struct getdents32_callback *) __buf;
-	int reclen = ROUND_UP(NAME_OFFSET(dirent) + namlen + 1, 4);
+	int reclen = ROUND_UP(offsetof(struct compat_dirent, d_name) + namlen + 1, 4);
 
 	buf->error = -EINVAL;	/* only used if we fail.. */
 	if (reclen > buf->count)
@@ -1263,17 +1260,17 @@
 	    || copy_to_user(dirent->d_name, name, namlen)
 	    || put_user(0, dirent->d_name + namlen))
 		return -EFAULT;
-	dirent = (struct compat_dirent *) ((char *) dirent + reclen);
+	dirent = (struct compat_dirent __user *) ((char __user *) dirent + reclen);
 	buf->current_dir = dirent;
 	buf->count -= reclen;
 	return 0;
 }
 
 asmlinkage long
-sys32_getdents (unsigned int fd, struct compat_dirent *dirent, unsigned int count)
+sys32_getdents (unsigned int fd, struct compat_dirent __user *dirent, unsigned int count)
 {
 	struct file * file;
-	struct compat_dirent * lastdirent;
+	struct compat_dirent __user * lastdirent;
 	struct getdents32_callback buf;
 	int error;
 
@@ -1310,7 +1307,7 @@
 	      unsigned int d_type)
 {
 	struct readdir32_callback * buf = (struct readdir32_callback *) __buf;
-	struct old_linux32_dirent * dirent;
+	struct old_linux32_dirent __user * dirent;
 
 	if (buf->count)
 		return -EINVAL;
@@ -1326,7 +1323,7 @@
 }
 
 asmlinkage long
-sys32_readdir (unsigned int fd, void *dirent, unsigned int count)
+sys32_readdir (unsigned int fd, void __user *dirent, unsigned int count)
 {
 	int error;
 	struct file * file;
@@ -1357,7 +1354,7 @@
 };
 
 asmlinkage long
-sys32_old_select (struct sel_arg_struct *arg)
+sys32_old_select (struct sel_arg_struct __user *arg)
 {
 	struct sel_arg_struct a;
 
@@ -1434,7 +1431,7 @@
  * so we have to implement this system call here.
  */
 asmlinkage long
-sys32_time (int *tloc)
+sys32_time (int __user *tloc)
 {
 	int i;
 	struct timeval tv;
@@ -1564,8 +1561,8 @@
 }
 
 static void
-put_fpreg (int regno, struct _fpreg_ia32 *reg, struct pt_regs *ptp, struct switch_stack *swp,
-	   int tos)
+put_fpreg (int regno, struct _fpreg_ia32 __user *reg, struct pt_regs *ptp,
+	   struct switch_stack *swp, int tos)
 {
 	struct _fpreg_ia32 *f;
 	char buf[32];
@@ -1597,8 +1594,8 @@
 }
 
 static void
-get_fpreg (int regno, struct _fpreg_ia32 *reg, struct pt_regs *ptp, struct switch_stack *swp,
-	   int tos)
+get_fpreg (int regno, struct _fpreg_ia32 __user *reg, struct pt_regs *ptp,
+	   struct switch_stack *swp, int tos)
 {
 
 	if ((regno += tos) >= 8)
@@ -1627,7 +1624,7 @@
 }
 
 int
-save_ia32_fpstate (struct task_struct *tsk, struct ia32_user_i387_struct *save)
+save_ia32_fpstate (struct task_struct *tsk, struct ia32_user_i387_struct __user *save)
 {
 	struct switch_stack *swp;
 	struct pt_regs *ptp;
@@ -1656,7 +1653,7 @@
 }
 
 static int
-restore_ia32_fpstate (struct task_struct *tsk, struct ia32_user_i387_struct *save)
+restore_ia32_fpstate (struct task_struct *tsk, struct ia32_user_i387_struct __user *save)
 {
 	struct switch_stack *swp;
 	struct pt_regs *ptp;
@@ -1666,15 +1663,15 @@
 	if (!access_ok(VERIFY_READ, save, sizeof(*save)))
 		return(-EFAULT);
 
-	__get_user(num32, (unsigned int *)&save->cwd);
+	__get_user(num32, (unsigned int __user *)&save->cwd);
 	tsk->thread.fcr = (tsk->thread.fcr & (~0x1f3f)) | (num32 & 0x1f3f);
-	__get_user(fsrlo, (unsigned int *)&save->swd);
-	__get_user(fsrhi, (unsigned int *)&save->twd);
+	__get_user(fsrlo, (unsigned int __user *)&save->swd);
+	__get_user(fsrhi, (unsigned int __user *)&save->twd);
 	num32 = (fsrhi << 16) | fsrlo;
 	tsk->thread.fsr = (tsk->thread.fsr & (~0xffffffff)) | num32;
-	__get_user(num32, (unsigned int *)&save->fip);
+	__get_user(num32, (unsigned int __user *)&save->fip);
 	tsk->thread.fir = (tsk->thread.fir & (~0xffffffff)) | num32;
-	__get_user(num32, (unsigned int *)&save->foo);
+	__get_user(num32, (unsigned int __user *)&save->foo);
 	tsk->thread.fdr = (tsk->thread.fdr & (~0xffffffff)) | num32;
 
 	/*
@@ -1689,7 +1686,7 @@
 }
 
 int
-save_ia32_fpxstate (struct task_struct *tsk, struct ia32_user_fxsr_struct *save)
+save_ia32_fpxstate (struct task_struct *tsk, struct ia32_user_fxsr_struct __user *save)
 {
 	struct switch_stack *swp;
 	struct pt_regs *ptp;
@@ -1715,7 +1712,7 @@
         ptp = ia64_task_regs(tsk);
 	tos = (tsk->thread.fsr >> 11) & 7;
         for (i = 0; i < 8; i++)
-		put_fpreg(i, (struct _fpreg_ia32 *)&save->st_space[4*i], ptp, swp, tos);
+		put_fpreg(i, (struct _fpreg_ia32 __user *)&save->st_space[4*i], ptp, swp, tos);
 
 	mxcsr = ((tsk->thread.fcr>>32) & 0xff80) | ((tsk->thread.fsr>>32) & 0x3f);
 	__put_user(mxcsr & 0xffff, &save->mxcsr);
@@ -1728,7 +1725,7 @@
 }
 
 static int
-restore_ia32_fpxstate (struct task_struct *tsk, struct ia32_user_fxsr_struct *save)
+restore_ia32_fpxstate (struct task_struct *tsk, struct ia32_user_fxsr_struct __user *save)
 {
 	struct switch_stack *swp;
 	struct pt_regs *ptp;
@@ -1741,15 +1738,15 @@
 	if (!access_ok(VERIFY_READ, save, sizeof(*save)))
 		return(-EFAULT);
 
-	__get_user(num32, (unsigned int *)&save->cwd);
+	__get_user(num32, (unsigned int __user *)&save->cwd);
 	tsk->thread.fcr = (tsk->thread.fcr & (~0x1f3f)) | (num32 & 0x1f3f);
-	__get_user(fsrlo, (unsigned int *)&save->swd);
-	__get_user(fsrhi, (unsigned int *)&save->twd);
+	__get_user(fsrlo, (unsigned int __user *)&save->swd);
+	__get_user(fsrhi, (unsigned int __user *)&save->twd);
 	num32 = (fsrhi << 16) | fsrlo;
 	tsk->thread.fsr = (tsk->thread.fsr & (~0xffffffff)) | num32;
-	__get_user(num32, (unsigned int *)&save->fip);
+	__get_user(num32, (unsigned int __user *)&save->fip);
 	tsk->thread.fir = (tsk->thread.fir & (~0xffffffff)) | num32;
-	__get_user(num32, (unsigned int *)&save->foo);
+	__get_user(num32, (unsigned int __user *)&save->foo);
 	tsk->thread.fdr = (tsk->thread.fdr & (~0xffffffff)) | num32;
 
 	/*
@@ -1759,13 +1756,13 @@
 	ptp = ia64_task_regs(tsk);
 	tos = (tsk->thread.fsr >> 11) & 7;
 	for (i = 0; i < 8; i++)
-	get_fpreg(i, (struct _fpreg_ia32 *)&save->st_space[4*i], ptp, swp, tos);
+	get_fpreg(i, (struct _fpreg_ia32 __user *)&save->st_space[4*i], ptp, swp, tos);
 
-	__get_user(mxcsr, (unsigned int *)&save->mxcsr);
+	__get_user(mxcsr, (unsigned int __user *)&save->mxcsr);
 	num64 = mxcsr & 0xff10;
-	tsk->thread.fcr = (tsk->thread.fcr & (~0xff1000000000)) | (num64<<32);
+	tsk->thread.fcr = (tsk->thread.fcr & (~0xff1000000000UL)) | (num64<<32);
 	num64 = mxcsr & 0x3f;
-	tsk->thread.fsr = (tsk->thread.fsr & (~0x3f00000000)) | (num64<<32);
+	tsk->thread.fsr = (tsk->thread.fsr & (~0x3f00000000UL)) | (num64<<32);
 
 	for (i = 0; i < 8; i++) {
 		copy_from_user(num128, &save->xmm_space[0] + 4*i, sizeof(struct _xmmreg_ia32));
@@ -1823,7 +1820,7 @@
 	      case PTRACE_PEEKDATA:	/* read word at location addr */
 		ret = ia32_peek(regs, child, addr, &value);
 		if (ret == 0)
-			ret = put_user(value, (unsigned int *) A(data));
+			ret = put_user(value, (unsigned int __user *) compat_ptr(data));
 		else
 			ret = -EIO;
 		goto out_tsk;
@@ -1839,7 +1836,7 @@
 			break;
 
 		tmp = getreg(child, addr);
-		if (!put_user(tmp, (unsigned int *) A(data)))
+		if (!put_user(tmp, (unsigned int __user *) compat_ptr(data)))
 			ret = 0;
 		break;
 
@@ -1853,24 +1850,24 @@
 		break;
 
 	      case IA32_PTRACE_GETREGS:
-		if (!access_ok(VERIFY_WRITE, (int *) A(data), 17*sizeof(int))) {
+		if (!access_ok(VERIFY_WRITE, compat_ptr(data), 17*sizeof(int))) {
 			ret = -EIO;
 			break;
 		}
 		for (i = 0; i < (int) (17*sizeof(int)); i += sizeof(int) ) {
-			put_user(getreg(child, i), (unsigned int *) A(data));
+			put_user(getreg(child, i), (unsigned int __user *) compat_ptr(data));
 			data += sizeof(int);
 		}
 		ret = 0;
 		break;
 
 	      case IA32_PTRACE_SETREGS:
-		if (!access_ok(VERIFY_READ, (int *) A(data), 17*sizeof(int))) {
+		if (!access_ok(VERIFY_READ, compat_ptr(data), 17*sizeof(int))) {
 			ret = -EIO;
 			break;
 		}
 		for (i = 0; i < (int) (17*sizeof(int)); i += sizeof(int) ) {
-			get_user(tmp, (unsigned int *) A(data));
+			get_user(tmp, (unsigned int __user *) compat_ptr(data));
 			putreg(child, i, tmp);
 			data += sizeof(int);
 		}
@@ -1878,19 +1875,23 @@
 		break;
 
 	      case IA32_PTRACE_GETFPREGS:
-		ret = save_ia32_fpstate(child, (struct ia32_user_i387_struct *) A(data));
+		ret = save_ia32_fpstate(child, (struct ia32_user_i387_struct __user *)
+					compat_ptr(data));
 		break;
 
 	      case IA32_PTRACE_GETFPXREGS:
-		ret = save_ia32_fpxstate(child, (struct ia32_user_fxsr_struct *) A(data));
+		ret = save_ia32_fpxstate(child, (struct ia32_user_fxsr_struct __user *)
+					 compat_ptr(data));
 		break;
 
 	      case IA32_PTRACE_SETFPREGS:
-		ret = restore_ia32_fpstate(child, (struct ia32_user_i387_struct *) A(data));
+		ret = restore_ia32_fpstate(child, (struct ia32_user_i387_struct __user *)
+					   compat_ptr(data));
 		break;
 
 	      case IA32_PTRACE_SETFPXREGS:
-		ret = restore_ia32_fpxstate(child, (struct ia32_user_fxsr_struct *) A(data));
+		ret = restore_ia32_fpxstate(child, (struct ia32_user_fxsr_struct __user *)
+					    compat_ptr(data));
 		break;
 
 	      case PTRACE_SYSCALL:	/* continue, stop after next syscall */
@@ -1913,73 +1914,6 @@
 	return ret;
 }
 
-/*
- *  The IA64 maps 4 I/O ports for each 4K page
- */
-#define IOLEN	((65536 / 4) * 4096)
-
-asmlinkage long
-sys32_iopl (int level)
-{
-	extern unsigned long ia64_iobase;
-	int fd;
-	struct file * file;
-	unsigned int old;
-	unsigned long addr;
-	mm_segment_t old_fs = get_fs ();
-
-	if (level != 3)
-		return(-EINVAL);
-	/* Trying to gain more privileges? */
-	old = ia64_getreg(_IA64_REG_AR_EFLAG);
-	if ((unsigned int) level > ((old >> 12) & 3)) {
-		if (!capable(CAP_SYS_RAWIO))
-			return -EPERM;
-	}
-	set_fs(KERNEL_DS);
-	fd = sys_open("/dev/mem", O_SYNC | O_RDWR, 0);
-	set_fs(old_fs);
-	if (fd < 0)
-		return fd;
-	file = fget(fd);
-	if (file == NULL) {
-		sys_close(fd);
-		return(-EFAULT);
-	}
-
-	down_write(&current->mm->mmap_sem);
-	addr = do_mmap_pgoff(file, IA32_IOBASE,
-			     IOLEN, PROT_READ|PROT_WRITE, MAP_SHARED,
-			     (ia64_iobase & ~PAGE_OFFSET) >> PAGE_SHIFT);
-	up_write(&current->mm->mmap_sem);
-
-	if (addr >= 0) {
-		old = (old & ~0x3000) | (level << 12);
-		ia64_setreg(_IA64_REG_AR_EFLAG, old);
-	}
-
-	fput(file);
-	sys_close(fd);
-	return 0;
-}
-
-asmlinkage long
-sys32_ioperm (unsigned int from, unsigned int num, int on)
-{
-
-	/*
-	 *  Since IA64 doesn't have permission bits we'd have to go to
-	 *    a lot of trouble to simulate them in software.  There's
-	 *    no point, only trusted programs can make this call so we'll
-	 *    just turn it into an iopl call and let the process have
-	 *    access to all I/O ports.
-	 *
-	 * XXX proper ioperm() support should be emulated by
-	 *	manipulating the page protections...
-	 */
-	return sys32_iopl(3);
-}
-
 typedef struct {
 	unsigned int	ss_sp;
 	unsigned int	ss_flags;
@@ -1987,7 +1921,7 @@
 } ia32_stack_t;
 
 asmlinkage long
-sys32_sigaltstack (ia32_stack_t *uss32, ia32_stack_t *uoss32,
+sys32_sigaltstack (ia32_stack_t __user *uss32, ia32_stack_t __user *uoss32,
 		   long arg2, long arg3, long arg4, long arg5, long arg6, long arg7, long stack)
 {
 	struct pt_regs *pt = (struct pt_regs *) &stack;
@@ -1999,9 +1933,9 @@
 	if (uss32) {
 		if (copy_from_user(&buf32, uss32, sizeof(ia32_stack_t)))
 			return -EFAULT;
-		uss.ss_sp = (void *) (long) buf32.ss_sp;
+		uss.ss_sp = (void __user *) (long) buf32.ss_sp;
 		uss.ss_flags = buf32.ss_flags;
-		/* MINSIGSTKSZ is different for ia32 vs ia64. We lie here to pass the 
+		/* MINSIGSTKSZ is different for ia32 vs ia64. We lie here to pass the
 	           check and set it to the user requested value later */
 		if ((buf32.ss_flags != SS_DISABLE) && (buf32.ss_size < MINSIGSTKSZ_IA32)) {
 			ret = -ENOMEM;
@@ -2010,14 +1944,15 @@
 		uss.ss_size = MINSIGSTKSZ;
 	}
 	set_fs(KERNEL_DS);
-	ret = do_sigaltstack(uss32 ? &uss : NULL, &uoss, pt->r12);
- 	current->sas_ss_size = buf32.ss_size;	
+	ret = do_sigaltstack(uss32 ? (stack_t __user *) &uss : NULL,
+			     (stack_t __user *) &uoss, pt->r12);
+ 	current->sas_ss_size = buf32.ss_size;
 	set_fs(old_fs);
 out:
 	if (ret < 0)
 		return(ret);
 	if (uoss32) {
-		buf32.ss_sp = (long) uoss.ss_sp;
+		buf32.ss_sp = (long __user) uoss.ss_sp;
 		buf32.ss_flags = uoss.ss_flags;
 		buf32.ss_size = uoss.ss_size;
 		if (copy_to_user(uoss32, &buf32, sizeof(ia32_stack_t)))
@@ -2056,14 +1991,14 @@
 };
 
 asmlinkage long
-sys32_sysctl (struct sysctl32 *args)
+sys32_sysctl (struct sysctl32 __user *args)
 {
 #ifdef CONFIG_SYSCTL
 	struct sysctl32 a32;
 	mm_segment_t old_fs = get_fs ();
-	void *oldvalp, *newvalp;
+	void __user *oldvalp, *newvalp;
 	size_t oldlen;
-	int *namep;
+	int __user *namep;
 	long ret;
 
 	if (copy_from_user(&a32, args, sizeof(a32)))
@@ -2076,11 +2011,11 @@
 	 * addresses, we KNOW that access_ok() will always succeed, so this is an
 	 * expensive NOP, but so what...
 	 */
-	namep = (int *) A(a32.name);
-	oldvalp = (void *) A(a32.oldval);
-	newvalp = (void *) A(a32.newval);
+	namep = (int __user *) compat_ptr(a32.name);
+	oldvalp = compat_ptr(a32.oldval);
+	newvalp = compat_ptr(a32.newval);
 
-	if ((oldvalp && get_user(oldlen, (int *) A(a32.oldlenp)))
+	if ((oldvalp && get_user(oldlen, (int __user *) compat_ptr(a32.oldlenp)))
 	    || !access_ok(VERIFY_WRITE, namep, 0)
 	    || !access_ok(VERIFY_WRITE, oldvalp, 0)
 	    || !access_ok(VERIFY_WRITE, newvalp, 0))
@@ -2088,11 +2023,12 @@
 
 	set_fs(KERNEL_DS);
 	lock_kernel();
-	ret = do_sysctl(namep, a32.nlen, oldvalp, &oldlen, newvalp, (size_t) a32.newlen);
+	ret = do_sysctl(namep, a32.nlen, oldvalp, (size_t __user *) &oldlen,
+			newvalp, (size_t) a32.newlen);
 	unlock_kernel();
 	set_fs(old_fs);
 
-	if (oldvalp && put_user (oldlen, (int *) A(a32.oldlenp)))
+	if (oldvalp && put_user (oldlen, (int __user *) compat_ptr(a32.oldlenp)))
 		return -EFAULT;
 
 	return ret;
@@ -2102,7 +2038,7 @@
 }
 
 asmlinkage long
-sys32_newuname (struct new_utsname *name)
+sys32_newuname (struct new_utsname __user *name)
 {
 	int ret = sys_newuname(name);
 
@@ -2113,14 +2049,14 @@
 }
 
 asmlinkage long
-sys32_getresuid16 (u16 *ruid, u16 *euid, u16 *suid)
+sys32_getresuid16 (u16 __user *ruid, u16 __user *euid, u16 __user *suid)
 {
 	uid_t a, b, c;
 	int ret;
 	mm_segment_t old_fs = get_fs();
 
 	set_fs(KERNEL_DS);
-	ret = sys_getresuid(&a, &b, &c);
+	ret = sys_getresuid((uid_t __user *) &a, (uid_t __user *) &b, (uid_t __user *) &c);
 	set_fs(old_fs);
 
 	if (put_user(a, ruid) || put_user(b, euid) || put_user(c, suid))
@@ -2129,14 +2065,14 @@
 }
 
 asmlinkage long
-sys32_getresgid16 (u16 *rgid, u16 *egid, u16 *sgid)
+sys32_getresgid16 (u16 __user *rgid, u16 __user *egid, u16 __user *sgid)
 {
 	gid_t a, b, c;
 	int ret;
 	mm_segment_t old_fs = get_fs();
 
 	set_fs(KERNEL_DS);
-	ret = sys_getresgid(&a, &b, &c);
+	ret = sys_getresgid((gid_t __user *) &a, (gid_t __user *) &b, (gid_t __user *) &c);
 	set_fs(old_fs);
 
 	if (ret)
@@ -2153,7 +2089,7 @@
 }
 
 static int
-groups16_to_user(short *grouplist, struct group_info *group_info)
+groups16_to_user(short __user *grouplist, struct group_info *group_info)
 {
 	int i;
 	short group;
@@ -2168,7 +2104,7 @@
 }
 
 static int
-groups16_from_user(struct group_info *group_info, short *grouplist)
+groups16_from_user(struct group_info *group_info, short __user *grouplist)
 {
 	int i;
 	short group;
@@ -2183,7 +2119,7 @@
 }
 
 asmlinkage long
-sys32_getgroups16 (int gidsetsize, short *grouplist)
+sys32_getgroups16 (int gidsetsize, short __user *grouplist)
 {
 	int i;
 
@@ -2208,7 +2144,7 @@
 }
 
 asmlinkage long
-sys32_setgroups16 (int gidsetsize, short *grouplist)
+sys32_setgroups16 (int gidsetsize, short __user *grouplist)
 {
 	struct group_info *group_info;
 	int retval;
@@ -2236,7 +2172,7 @@
 asmlinkage long
 sys32_truncate64 (unsigned int path, unsigned int len_lo, unsigned int len_hi)
 {
-	return sys_truncate((const char *) A(path), ((unsigned long) len_hi << 32) | len_lo);
+	return sys_truncate(compat_ptr(path), ((unsigned long) len_hi << 32) | len_lo);
 }
 
 asmlinkage long
@@ -2246,7 +2182,7 @@
 }
 
 static int
-putstat64 (struct stat64 *ubuf, struct kstat *kbuf)
+putstat64 (struct stat64 __user *ubuf, struct kstat *kbuf)
 {
 	int err;
 	u64 hdev;
@@ -2255,8 +2191,8 @@
 		return -EFAULT;
 
 	hdev = huge_encode_dev(kbuf->dev);
-	err  = __put_user(hdev, (u32*)&ubuf->st_dev);
-	err |= __put_user(hdev >> 32, ((u32*)&ubuf->st_dev) + 1);
+	err  = __put_user(hdev, (u32 __user*)&ubuf->st_dev);
+	err |= __put_user(hdev >> 32, ((u32 __user*)&ubuf->st_dev) + 1);
 	err |= __put_user(kbuf->ino, &ubuf->__st_ino);
 	err |= __put_user(kbuf->ino, &ubuf->st_ino_lo);
 	err |= __put_user(kbuf->ino >> 32, &ubuf->st_ino_hi);
@@ -2265,8 +2201,8 @@
 	err |= __put_user(kbuf->uid, &ubuf->st_uid);
 	err |= __put_user(kbuf->gid, &ubuf->st_gid);
 	hdev = huge_encode_dev(kbuf->rdev);
-	err  = __put_user(hdev, (u32*)&ubuf->st_rdev);
-	err |= __put_user(hdev >> 32, ((u32*)&ubuf->st_rdev) + 1);
+	err  = __put_user(hdev, (u32 __user*)&ubuf->st_rdev);
+	err |= __put_user(hdev >> 32, ((u32 __user*)&ubuf->st_rdev) + 1);
 	err |= __put_user(kbuf->size, &ubuf->st_size_lo);
 	err |= __put_user((kbuf->size >> 32), &ubuf->st_size_hi);
 	err |= __put_user(kbuf->atime.tv_sec, &ubuf->st_atime);
@@ -2281,7 +2217,7 @@
 }
 
 asmlinkage long
-sys32_stat64 (char *filename, struct stat64 *statbuf)
+sys32_stat64 (char __user *filename, struct stat64 __user *statbuf)
 {
 	struct kstat s;
 	long ret = vfs_stat(filename, &s);
@@ -2291,7 +2227,7 @@
 }
 
 asmlinkage long
-sys32_lstat64 (char *filename, struct stat64 *statbuf)
+sys32_lstat64 (char __user *filename, struct stat64 __user *statbuf)
 {
 	struct kstat s;
 	long ret = vfs_lstat(filename, &s);
@@ -2301,7 +2237,7 @@
 }
 
 asmlinkage long
-sys32_fstat64 (unsigned int fd, struct stat64 *statbuf)
+sys32_fstat64 (unsigned int fd, struct stat64 __user *statbuf)
 {
 	struct kstat s;
 	long ret = vfs_fstat(fd, &s);
@@ -2328,7 +2264,7 @@
 };
 
 asmlinkage long
-sys32_sysinfo (struct sysinfo32 *info)
+sys32_sysinfo (struct sysinfo32 __user *info)
 {
 	struct sysinfo s;
 	long ret, err;
@@ -2336,7 +2272,7 @@
 	mm_segment_t old_fs = get_fs();
 
 	set_fs(KERNEL_DS);
-	ret = sys_sysinfo(&s);
+	ret = sys_sysinfo((struct sysinfo __user *) &s);
 	set_fs(old_fs);
 	/* Check to see if any memory value is too large for 32-bit and
 	 * scale down if needed.
@@ -2379,14 +2315,14 @@
 }
 
 asmlinkage long
-sys32_sched_rr_get_interval (pid_t pid, struct compat_timespec *interval)
+sys32_sched_rr_get_interval (pid_t pid, struct compat_timespec __user *interval)
 {
 	mm_segment_t old_fs = get_fs();
 	struct timespec t;
 	long ret;
 
 	set_fs(KERNEL_DS);
-	ret = sys_sched_rr_get_interval(pid, &t);
+	ret = sys_sched_rr_get_interval(pid, (struct timespec __user *) &t);
 	set_fs(old_fs);
 	if (put_compat_timespec(&t, interval))
 		return -EFAULT;
@@ -2394,19 +2330,19 @@
 }
 
 asmlinkage long
-sys32_pread (unsigned int fd, void *buf, unsigned int count, u32 pos_lo, u32 pos_hi)
+sys32_pread (unsigned int fd, void __user *buf, unsigned int count, u32 pos_lo, u32 pos_hi)
 {
 	return sys_pread64(fd, buf, count, ((unsigned long) pos_hi << 32) | pos_lo);
 }
 
 asmlinkage long
-sys32_pwrite (unsigned int fd, void *buf, unsigned int count, u32 pos_lo, u32 pos_hi)
+sys32_pwrite (unsigned int fd, void __user *buf, unsigned int count, u32 pos_lo, u32 pos_hi)
 {
 	return sys_pwrite64(fd, buf, count, ((unsigned long) pos_hi << 32) | pos_lo);
 }
 
 asmlinkage long
-sys32_sendfile (int out_fd, int in_fd, int *offset, unsigned int count)
+sys32_sendfile (int out_fd, int in_fd, int __user *offset, unsigned int count)
 {
 	mm_segment_t old_fs = get_fs();
 	long ret;
@@ -2416,7 +2352,7 @@
 		return -EFAULT;
 
 	set_fs(KERNEL_DS);
-	ret = sys_sendfile(out_fd, in_fd, offset ? &of : NULL, count);
+	ret = sys_sendfile(out_fd, in_fd, offset ? (off_t __user *) &of : NULL, count);
 	set_fs(old_fs);
 
 	if (!ret && offset && put_user(of, offset))
@@ -2447,7 +2383,7 @@
 	obrk = mm->brk;
 	ret = sys_brk(brk);
 	if (ret < obrk)
-		clear_user((void *) ret, PAGE_ALIGN(ret) - ret);
+		clear_user(compat_ptr(ret), PAGE_ALIGN(ret) - ret);
 	return ret;
 }
 
@@ -2455,7 +2391,7 @@
  * Exactly like fs/open.c:sys_open(), except that it doesn't set the O_LARGEFILE flag.
  */
 asmlinkage long
-sys32_open (const char * filename, int flags, int mode)
+sys32_open (const char __user * filename, int flags, int mode)
 {
 	char * tmp;
 	int fd, error;
@@ -2487,10 +2423,10 @@
 {
 	u32 events;
 	u32 data[2];
-}; 
+};
 
 asmlinkage long
-sys32_epoll_ctl(int epfd, int op, int fd, struct epoll_event32 *event)
+sys32_epoll_ctl(int epfd, int op, int fd, struct epoll_event32 __user *event)
 {
 	mm_segment_t old_fs = get_fs();
 	struct epoll_event event64;
@@ -2508,14 +2444,14 @@
  	event64.data |= (u64)data_halfword << 32;
 
 	set_fs(KERNEL_DS);
-	error = sys_epoll_ctl(epfd, op, fd, &event64);
+	error = sys_epoll_ctl(epfd, op, fd, (struct epoll_event __user *) &event64);
 	set_fs(old_fs);
 
 	return error;
 }
 
 asmlinkage long
-sys32_epoll_wait(int epfd, struct epoll_event32 *events, int maxevents,
+sys32_epoll_wait(int epfd, struct epoll_event32 __user * events, int maxevents,
 		 int timeout)
 {
 	struct epoll_event *events64 = NULL;
@@ -2533,8 +2469,8 @@
 				 maxevents * sizeof(struct epoll_event32))))
 		return error;
 
-	/* 
- 	 * Allocate space for the intermediate copy.  If the space needed 
+	/*
+ 	 * Allocate space for the intermediate copy.  If the space needed
 	 * is large enough to cause kmalloc to fail, then try again with
 	 * __get_free_pages.
 	 */
@@ -2543,14 +2479,15 @@
 	if (events64 == NULL) {
 		events64 = (struct epoll_event *)
 				__get_free_pages(GFP_KERNEL, get_order(size));
-		if (events64 == NULL) 
+		if (events64 == NULL)
 			return -ENOMEM;
 		do_free_pages = 1;
 	}
 
 	/* Do the system call */
 	set_fs(KERNEL_DS); /* copy_to/from_user should work on kernel mem*/
-	numevents = sys_epoll_wait(epfd, events64, maxevents, timeout);
+	numevents = sys_epoll_wait(epfd, (struct epoll_event __user *) events64,
+				   maxevents, timeout);
 	set_fs(old_fs);
 
 	/* Don't modify userspace memory if we're returning an error */
@@ -2593,7 +2530,7 @@
  * Set a given TLS descriptor:
  */
 asmlinkage int
-sys32_set_thread_area (struct ia32_user_desc *u_info)
+sys32_set_thread_area (struct ia32_user_desc __user *u_info)
 {
 	struct thread_struct *t = &current->thread;
 	struct ia32_user_desc info;
@@ -2654,7 +2591,7 @@
 #define GET_USEABLE(desc)	(((desc)->b >> 20) & 1)
 
 asmlinkage int
-sys32_get_thread_area (struct ia32_user_desc *u_info)
+sys32_get_thread_area (struct ia32_user_desc __user *u_info)
 {
 	struct ia32_user_desc info;
 	struct desc_struct *desc;
@@ -2682,12 +2619,8 @@
 	return 0;
 }
 
-extern asmlinkage long
-sys_timer_create(clockid_t which_clock, struct sigevent *timer_event_spec,
-		 timer_t * created_timer_id);
-
 asmlinkage long
-sys32_timer_create(u32 clock, struct sigevent32 *se32, timer_t *timer_id)
+sys32_timer_create(u32 clock, struct sigevent32 __user *se32, timer_t __user *timer_id)
 {
 	struct sigevent se;
 	mm_segment_t oldfs;
@@ -2710,7 +2643,7 @@
 
 	oldfs = get_fs();
 	set_fs(KERNEL_DS);
-	err = sys_timer_create(clock, &se, &t);
+	err = sys_timer_create(clock, (struct sigevent __user *) &se, (timer_t __user *) &t);
 	set_fs(oldfs);
 
 	if (!err)
@@ -2727,6 +2660,32 @@
 			       (((u64)len_high)<<32) | len_low,
 			       advice); 
 } 
+
+asmlinkage long sys32_waitid(int which, compat_pid_t pid,
+			     siginfo_t32 __user *uinfo, int options,
+			     struct compat_rusage __user *uru)
+{
+	siginfo_t info;
+	struct rusage ru;
+	long ret;
+	mm_segment_t old_fs = get_fs();
+
+	info.si_signo = 0;
+	set_fs (KERNEL_DS);
+	ret = sys_waitid(which, pid, (siginfo_t __user *) &info, options,
+			 uru ? &ru : NULL);
+	set_fs (old_fs);
+
+	if (ret < 0 || info.si_signo == 0)
+		return ret;
+
+	if (uru && (ret = put_compat_rusage(&ru, uru)))
+		return ret;
+
+	BUG_ON(info.si_code & __SI_MASK);
+	info.si_code |= __SI_CHLD;
+	return copy_siginfo_to_user32(uinfo, &info);
+}
 
 #ifdef	NOTYET  /* UNTESTED FOR IA64 FROM HERE DOWN */
 
diff -Nru a/arch/ia64/kernel/Makefile b/arch/ia64/kernel/Makefile
--- a/arch/ia64/kernel/Makefile	2004-10-18 14:57:04 -07:00
+++ b/arch/ia64/kernel/Makefile	2004-10-18 14:57:04 -07:00
@@ -2,7 +2,7 @@
 # Makefile for the linux kernel.
 #
 
-extra-y	:= head.o init_task.o vmlinux.lds.s
+extra-y	:= head.o init_task.o vmlinux.lds
 
 obj-y := acpi.o entry.o efi.o efi_stub.o gate-data.o fsys.o ia64_ksyms.o irq.o irq_ia64.o	\
 	 irq_lsapic.o ivt.o machvec.o pal.o patch.o process.o perfmon.o ptrace.o sal.o		\
@@ -17,29 +17,31 @@
 obj-$(CONFIG_SMP)		+= smp.o smpboot.o
 obj-$(CONFIG_PERFMON)		+= perfmon_default_smpl.o
 obj-$(CONFIG_IA64_CYCLONE)	+= cyclone.o
+obj-$(CONFIG_IA64_MCA_RECOVERY)	+= mca_recovery.o
+mca_recovery-y			+= mca_drv.o mca_drv_asm.o
 
 # The gate DSO image is built using a special linker script.
 targets += gate.so gate-syms.o
 
-extra-y += gate.so gate-syms.o gate.lds.s gate.o
+extra-y += gate.so gate-syms.o gate.lds gate.o
 
 # fp_emulate() expects f2-f5,f16-f31 to contain the user-level state.
 CFLAGS_traps.o  += -mfixed-range=f2-f5,f16-f31
 
-AFLAGS_gate.lds.o += -P -C -U$(ARCH)
+CPPFLAGS_gate.lds := -P -C -U$(ARCH)
 
 quiet_cmd_gate = GATE $@
       cmd_gate = $(CC) -nostdlib $(GATECFLAGS_$(@F)) -Wl,-T,$(filter-out FORCE,$^) -o $@
 
 GATECFLAGS_gate.so = -shared -s -Wl,-soname=linux-gate.so.1
-$(obj)/gate.so: $(obj)/gate.lds.s $(obj)/gate.o FORCE
+$(obj)/gate.so: $(obj)/gate.lds $(obj)/gate.o FORCE
 	$(call if_changed,gate)
 
 $(obj)/built-in.o: $(obj)/gate-syms.o
 $(obj)/built-in.o: ld_flags += -R $(obj)/gate-syms.o
 
 GATECFLAGS_gate-syms.o = -r
-$(obj)/gate-syms.o: $(src)/gate.lds.s $(obj)/gate.o FORCE
+$(obj)/gate-syms.o: $(obj)/gate.lds $(obj)/gate.o FORCE
 	$(call if_changed,gate)
 
 # gate-data.o contains the gate DSO image as data in section .data.gate.
diff -Nru a/arch/ia64/kernel/acpi-ext.c b/arch/ia64/kernel/acpi-ext.c
--- a/arch/ia64/kernel/acpi-ext.c	2004-10-18 14:57:05 -07:00
+++ b/arch/ia64/kernel/acpi-ext.c	2004-10-18 14:57:05 -07:00
@@ -62,7 +62,7 @@
 	struct acpi_vendor_info info;
 
 	info.descriptor = id;
-	info.data = 0;
+	info.data = NULL;
 
 	acpi_walk_resources(obj, METHOD_NAME__CRS, acpi_vendor_resource_match, &info);
 	if (!info.data)
diff -Nru a/arch/ia64/kernel/acpi.c b/arch/ia64/kernel/acpi.c
--- a/arch/ia64/kernel/acpi.c	2004-10-18 14:56:31 -07:00
+++ b/arch/ia64/kernel/acpi.c	2004-10-18 14:56:31 -07:00
@@ -61,10 +61,16 @@
 void (*pm_idle) (void);
 EXPORT_SYMBOL(pm_idle);
 void (*pm_power_off) (void);
+EXPORT_SYMBOL(pm_power_off);
 
 unsigned char acpi_kbd_controller_present = 1;
 unsigned char acpi_legacy_devices;
 
+#define MAX_SAPICS 256
+u16 ia64_acpiid_to_sapicid[MAX_SAPICS] =
+	{ [0 ... MAX_SAPICS - 1] = -1 };
+EXPORT_SYMBOL(ia64_acpiid_to_sapicid);
+
 const char *
 acpi_get_sysname (void)
 {
@@ -172,8 +178,8 @@
 		return -EINVAL;
 
 	if (lapic->address) {
-		iounmap((void *) ipi_base_addr);
-		ipi_base_addr = (unsigned long) ioremap(lapic->address, 0);
+		iounmap(ipi_base_addr);
+		ipi_base_addr = ioremap(lapic->address, 0);
 	}
 	return 0;
 }
@@ -193,6 +199,7 @@
 #ifdef CONFIG_SMP
 		smp_boot_data.cpu_phys_id[available_cpus] = (lsapic->id << 8) | lsapic->eid;
 #endif
+		ia64_acpiid_to_sapicid[lsapic->acpi_id] = (lsapic->id << 8) | lsapic->eid;
 		++available_cpus;
 	}
 
@@ -329,9 +336,9 @@
 	/* Get base address of IPI Message Block */
 
 	if (acpi_madt->lapic_address)
-		ipi_base_addr = (unsigned long) ioremap(acpi_madt->lapic_address, 0);
+		ipi_base_addr = ioremap(acpi_madt->lapic_address, 0);
 
-	printk(KERN_INFO PREFIX "Local APIC address 0x%lx\n", ipi_base_addr);
+	printk(KERN_INFO PREFIX "Local APIC address %p\n", ipi_base_addr);
 
 	acpi_madt_oem_check(acpi_madt->header.oem_id,
 		acpi_madt->header.oem_table_id);
@@ -430,8 +437,9 @@
 {
 	int i, j, node_from, node_to;
 
-	/* If there's no SRAT, fix the phys_id */
+	/* If there's no SRAT, fix the phys_id and mark node 0 online */
 	if (srat_num_cpus == 0) {
+		node_set_online(0);
 		node_cpuid[0].phys_id = hard_smp_processor_id();
 		return;
 	}
@@ -643,4 +651,71 @@
 	return 0;
 }
 
+#ifdef CONFIG_NUMA
+acpi_status __init
+acpi_map_iosapic (acpi_handle handle, u32 depth, void *context, void **ret)
+{
+	struct acpi_buffer buffer = {ACPI_ALLOCATE_BUFFER, NULL};
+	union acpi_object *obj;
+	struct acpi_table_iosapic *iosapic;
+	unsigned int gsi_base;
+	int node;
+
+	/* Only care about objects w/ a method that returns the MADT */
+	if (ACPI_FAILURE(acpi_evaluate_object(handle, "_MAT", NULL, &buffer)))
+		return AE_OK;
+
+	if (!buffer.length || !buffer.pointer)
+		return AE_OK;
+
+	obj = buffer.pointer;
+	if (obj->type != ACPI_TYPE_BUFFER ||
+	    obj->buffer.length < sizeof(*iosapic)) {
+		acpi_os_free(buffer.pointer);
+		return AE_OK;
+	}
+
+	iosapic = (struct acpi_table_iosapic *)obj->buffer.pointer;
+
+	if (iosapic->header.type != ACPI_MADT_IOSAPIC) {
+		acpi_os_free(buffer.pointer);
+		return AE_OK;
+	}
+
+	gsi_base = iosapic->global_irq_base;
+
+	acpi_os_free(buffer.pointer);
+	buffer.length = ACPI_ALLOCATE_BUFFER;
+	buffer.pointer = NULL;
+
+	/*
+	 * OK, it's an IOSAPIC MADT entry, look for a _PXM method to tell
+	 * us which node to associate this with.
+	 */
+	if (ACPI_FAILURE(acpi_evaluate_object(handle, "_PXM", NULL, &buffer)))
+		return AE_OK;
+
+	if (!buffer.length || !buffer.pointer)
+		return AE_OK;
+
+	obj = buffer.pointer;
+
+	if (obj->type != ACPI_TYPE_INTEGER ||
+	    obj->integer.value >= MAX_PXM_DOMAINS) {
+		acpi_os_free(buffer.pointer);
+		return AE_OK;
+	}
+
+	node = pxm_to_nid_map[obj->integer.value];
+	acpi_os_free(buffer.pointer);
+
+	if (node >= MAX_NUMNODES || !node_online(node) ||
+	    cpus_empty(node_to_cpumask(node)))
+		return AE_OK;
+
+	/* We know a gsi to node mapping! */
+	map_iosapic_to_node(gsi_base, node);
+	return AE_OK;
+}
+#endif /* CONFIG_NUMA */
 #endif /* CONFIG_ACPI_BOOT */
diff -Nru a/arch/ia64/kernel/asm-offsets.c b/arch/ia64/kernel/asm-offsets.c
--- a/arch/ia64/kernel/asm-offsets.c	2004-10-18 14:57:03 -07:00
+++ b/arch/ia64/kernel/asm-offsets.c	2004-10-18 14:57:03 -07:00
@@ -34,6 +34,11 @@
 
 	BLANK();
 
+	DEFINE(TI_FLAGS, offsetof(struct thread_info, flags));
+	DEFINE(TI_PRE_COUNT, offsetof(struct thread_info, preempt_count));
+
+	BLANK();
+
 	DEFINE(IA64_TASK_BLOCKED_OFFSET,offsetof (struct task_struct, blocked));
 	DEFINE(IA64_TASK_CLEAR_CHILD_TID_OFFSET,offsetof (struct task_struct, clear_child_tid));
 	DEFINE(IA64_TASK_GROUP_LEADER_OFFSET, offsetof (struct task_struct, group_leader));
@@ -188,18 +193,10 @@
 	DEFINE(IA64_CLONE_VM, CLONE_VM);
 
 	BLANK();
-    /* used by fsys_gettimeofday in arch/ia64/kernel/fsys.S */
-	DEFINE(IA64_CPUINFO_ITM_DELTA_OFFSET, offsetof (struct cpuinfo_ia64, itm_delta));
-	DEFINE(IA64_CPUINFO_ITM_NEXT_OFFSET, offsetof (struct cpuinfo_ia64, itm_next));
 	DEFINE(IA64_CPUINFO_NSEC_PER_CYC_OFFSET, offsetof (struct cpuinfo_ia64, nsec_per_cyc));
 	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"
@@ -207,5 +204,21 @@
 
 	BLANK();
 	DEFINE(IA64_MCA_TLB_INFO_SIZE, sizeof (struct ia64_mca_tlb_info));
+	/* used by head.S */
+	DEFINE(IA64_CPUINFO_NSEC_PER_CYC_OFFSET, offsetof (struct cpuinfo_ia64, nsec_per_cyc));
 
+	BLANK();
+	/* used by fsys_gettimeofday in arch/ia64/kernel/fsys.S */
+	DEFINE(IA64_TIME_INTERPOLATOR_ADDRESS_OFFSET, offsetof (struct time_interpolator, addr));
+	DEFINE(IA64_TIME_INTERPOLATOR_SOURCE_OFFSET, offsetof (struct time_interpolator, source));
+	DEFINE(IA64_TIME_INTERPOLATOR_SHIFT_OFFSET, offsetof (struct time_interpolator, shift));
+	DEFINE(IA64_TIME_INTERPOLATOR_NSEC_OFFSET, offsetof (struct time_interpolator, nsec_per_cyc));
+	DEFINE(IA64_TIME_INTERPOLATOR_OFFSET_OFFSET, offsetof (struct time_interpolator, offset));
+	DEFINE(IA64_TIME_INTERPOLATOR_LAST_CYCLE_OFFSET, offsetof (struct time_interpolator, last_cycle));
+	DEFINE(IA64_TIME_INTERPOLATOR_LAST_COUNTER_OFFSET, offsetof (struct time_interpolator, last_counter));
+	DEFINE(IA64_TIME_INTERPOLATOR_JITTER_OFFSET, offsetof (struct time_interpolator, jitter));
+	DEFINE(IA64_TIME_SOURCE_CPU, TIME_SOURCE_CPU);
+	DEFINE(IA64_TIME_SOURCE_MMIO64, TIME_SOURCE_MMIO64);
+	DEFINE(IA64_TIME_SOURCE_MMIO32, TIME_SOURCE_MMIO32);
+	DEFINE(IA64_TIMESPEC_TV_NSEC_OFFSET, offsetof (struct timespec, tv_nsec));
 }
diff -Nru a/arch/ia64/kernel/cyclone.c b/arch/ia64/kernel/cyclone.c
--- a/arch/ia64/kernel/cyclone.c	2004-10-18 14:56:29 -07:00
+++ b/arch/ia64/kernel/cyclone.c	2004-10-18 14:56:29 -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
@@ -15,62 +17,10 @@
 	use_cyclone = 1;
 }
 
-static u32* volatile cyclone_timer;	/* Cyclone MPMC0 register */
-static u32 last_update_cyclone;
-
-static unsigned long offset_base;
-
-static unsigned long get_offset_cyclone(void)
-{
-	u32 now;
-	unsigned long offset;
-
-	/* Read the cyclone timer */
-	now = readl(cyclone_timer);
-	/* .. relative to previous update*/
-	offset = now - last_update_cyclone;
-
-	/* convert cyclone ticks to nanoseconds */
-	offset = (offset*NSEC_PER_SEC)/CYCLONE_TIMER_FREQ;
-
-	/* our adjusted time in nanoseconds */
-	return offset_base + offset;
-}
-
-static void update_cyclone(long delta_nsec)
-{
-	u32 now;
-	unsigned long offset;
-
-	/* Read the cyclone timer */
-	now = readl(cyclone_timer);
-	/* .. relative to previous update*/
-	offset = now - last_update_cyclone;
-
-	/* convert cyclone ticks to nanoseconds */
-	offset = (offset*NSEC_PER_SEC)/CYCLONE_TIMER_FREQ;
-
-	offset += offset_base;
-
-	/* Be careful about signed/unsigned comparisons here: */
-	if (delta_nsec < 0 || (unsigned long) delta_nsec < offset)
-		offset_base = offset - delta_nsec;
-	else
-		offset_base = 0;
-
-	last_update_cyclone = now;
-}
-
-static void reset_cyclone(void)
-{
-	offset_base = 0;
-	last_update_cyclone = readl(cyclone_timer);
-}
 
 struct time_interpolator cyclone_interpolator = {
-	.get_offset =	get_offset_cyclone,
-	.update =	update_cyclone,
-	.reset =	reset_cyclone,
+	.source =	TIME_SOURCE_MMIO32,
+	.shift =	32,
 	.frequency =	CYCLONE_TIMER_FREQ,
 	.drift =	-100,
 };
@@ -81,6 +31,7 @@
 	u64 base;	/* saved cyclone base address */
 	u64 offset;	/* offset from pageaddr to cyclone_timer register */
 	int i;
+	u32* volatile cyclone_timer;	/* Cyclone MPMC0 register */
 
 	if (!use_cyclone)
 		return -ENODEV;
@@ -148,7 +99,7 @@
 		}
 	}
 	/* initialize last tick */
-	last_update_cyclone = readl(cyclone_timer);
+	cyclone_interpolator.addr = cyclone_timer;
 	register_time_interpolator(&cyclone_interpolator);
 
 	return 0;
diff -Nru a/arch/ia64/kernel/efi.c b/arch/ia64/kernel/efi.c
--- a/arch/ia64/kernel/efi.c	2004-10-18 14:55:54 -07:00
+++ b/arch/ia64/kernel/efi.c	2004-10-18 14:55:54 -07:00
@@ -48,7 +48,7 @@
 prefix##_get_time (efi_time_t *tm, efi_time_cap_t *tc)						  \
 {												  \
 	struct ia64_fpreg fr[6];								  \
-	efi_time_cap_t *atc = 0;								  \
+	efi_time_cap_t *atc = NULL;								  \
 	efi_status_t ret;									  \
 												  \
 	if (tc)											  \
@@ -91,7 +91,7 @@
 prefix##_set_wakeup_time (efi_bool_t enabled, efi_time_t *tm)					\
 {												\
 	struct ia64_fpreg fr[6];								\
-	efi_time_t *atm = 0;									\
+	efi_time_t *atm = NULL;									\
 	efi_status_t ret;									\
 												\
 	if (tm)											\
@@ -109,7 +109,7 @@
 		       unsigned long *data_size, void *data)				\
 {											\
 	struct ia64_fpreg fr[6];							\
-	u32 *aattr = 0;									\
+	u32 *aattr = NULL;									\
 	efi_status_t ret;								\
 											\
 	if (attr)									\
@@ -172,7 +172,7 @@
 		       unsigned long data_size, efi_char16_t *data)		\
 {										\
 	struct ia64_fpreg fr[6];						\
-	efi_char16_t *adata = 0;						\
+	efi_char16_t *adata = NULL;						\
 										\
 	if (data)								\
 		adata = adjust_arg(data);					\
@@ -214,7 +214,7 @@
 	efi_time_t tm;
 
 	memset(ts, 0, sizeof(ts));
-	if ((*efi.get_time)(&tm, 0) != EFI_SUCCESS)
+	if ((*efi.get_time)(&tm, NULL) != EFI_SUCCESS)
 		return;
 
 	ts->tv_sec = mktime(tm.year, tm.month, tm.day, tm.hour, tm.minute, tm.second);
@@ -357,8 +357,10 @@
 			if (total_mem >= mem_limit)
 				continue;
 			total_mem += (md->num_pages << EFI_PAGE_SHIFT);
-			if (total_mem > mem_limit)
+			if (total_mem > mem_limit) {
 				md->num_pages -= ((total_mem - mem_limit) >> EFI_PAGE_SHIFT);
+				max_addr = md->phys_addr + (md->num_pages << EFI_PAGE_SHIFT);
+			}
 
 			if (md->num_pages == 0)
 				continue;
diff -Nru a/arch/ia64/kernel/entry.S b/arch/ia64/kernel/entry.S
--- a/arch/ia64/kernel/entry.S	2004-10-18 14:56:27 -07:00
+++ b/arch/ia64/kernel/entry.S	2004-10-18 14:56:27 -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/fsys.S b/arch/ia64/kernel/fsys.S
--- a/arch/ia64/kernel/fsys.S	2004-10-18 14:57:19 -07:00
+++ b/arch/ia64/kernel/fsys.S	2004-10-18 14:57:19 -07:00
@@ -8,6 +8,8 @@
  * 18-Feb-03 louisk	Implement fsys_gettimeofday().
  * 28-Feb-03 davidm	Fixed several bugs in fsys_gettimeofday().  Tuned it some more,
  *			probably broke it along the way... ;-)
+ * 13-Jul-04 clameter   Implement fsys_clock_gettime and revise fsys_gettimeofday to make
+ *                      it capable of using memory based clocks without falling back to C code.
  */
 
 #include <asm/asmmacro.h>
@@ -144,195 +146,206 @@
 END(fsys_set_tid_address)
 
 /*
- * Note 1: This routine uses floating-point registers, but only with registers that
- *	   operate on integers.  Because of that, we don't need to set ar.fpsr to the
- *	   kernel default value.
- *
- * Note 2: For now, we will assume that all CPUs run at the same clock-frequency.
- *	   If that wasn't the case, we would have to disable preemption (e.g.,
- *	   by disabling interrupts) between reading the ITC and reading
- *	   local_cpu_data->nsec_per_cyc.
- *
- * Note 3: On platforms where the ITC-drift bit is set in the SAL feature vector,
- *	   we ought to either skip the ITC-based interpolation or run an ntp-like
- *	   daemon to keep the ITCs from drifting too far apart.
+ * Ensure that the time interpolator structure is compatible with the asm code
  */
+#if IA64_TIME_INTERPOLATOR_SOURCE_OFFSET !=0 || IA64_TIME_INTERPOLATOR_SHIFT_OFFSET != 2 \
+	|| IA64_TIME_INTERPOLATOR_JITTER_OFFSET != 3 || IA64_TIME_INTERPOLATOR_NSEC_OFFSET != 4
+#error fsys_gettimeofday incompatible with changes to struct time_interpolator
+#endif
+#define CLOCK_REALTIME 0
+#define CLOCK_MONOTONIC 1
+#define CLOCK_DIVIDE_BY_1000 0x4000
+#define CLOCK_ADD_MONOTONIC 0x8000
 
 ENTRY(fsys_gettimeofday)
 	.prologue
 	.altrp b6
 	.body
-	add r9=TI_FLAGS+IA64_TASK_SIZE,r16
-	addl r3=THIS_CPU(cpu_info),r0
-
-#ifdef CONFIG_SMP
-	movl r10=__per_cpu_offset
-	movl r2=sal_platform_features
-	;;
-
-	ld8 r2=[r2]
-	movl r19=xtime			// xtime is a timespec struct
-
-	ld8 r10=[r10]			// r10 <- __per_cpu_offset[0]
-	addl r21=THIS_CPU(cpu_info),r0
-	;;
-	add r10=r21, r10		// r10 <- &cpu_data(time_keeper_id)
-	tbit.nz p8,p0 = r2, IA64_SAL_PLATFORM_FEATURE_ITC_DRIFT_BIT
-(p8)	br.spnt.many fsys_fallback_syscall
-#else
-	;;
-	mov r10=r3
-	movl r19=xtime			// xtime is a timespec struct
-#endif
-	ld4 r9=[r9]
-	movl r17=xtime_lock
-	;;
-
-	// r32, r33 should contain the 2 args of gettimeofday
-	adds r21=IA64_CPUINFO_ITM_NEXT_OFFSET, r10
-	mov r2=-1
-	tnat.nz p6,p7=r32		// guard against NaT args
-	;;
-
-	adds r10=IA64_CPUINFO_ITM_DELTA_OFFSET, r10
-(p7)	tnat.nz p6,p0=r33
-(p6)	br.cond.spnt.few .fail_einval
-
-	adds r8=IA64_CPUINFO_NSEC_PER_CYC_OFFSET, r3
-	movl r24=2361183241434822607	// for division hack (only for / 1000)
-	;;
-
-	ldf8 f7=[r10]			// f7 now contains itm_delta
-	setf.sig f11=r2
-	adds r10=8, r32
-
-	adds r20=IA64_TIMESPEC_TV_NSEC_OFFSET, r19	// r20 = &xtime->tv_nsec
-	movl r26=jiffies
-
-	setf.sig f9=r24			// f9 is used for division hack
-	movl r27=wall_jiffies
-
-	and r9=TIF_ALLWORK_MASK,r9
-	movl r25=last_nsec_offset
-	;;
-
-	/*
-	 * Verify that we have permission to write to struct timeval.  Note:
-	 * Another thread might unmap the mapping before we actually get
-	 * to store the result.  That's OK as long as the stores are also
-	 * protect by EX().
-	 */
-EX(.fail_efault, probe.w.fault r32, 3)		// this must come _after_ NaT-check
-EX(.fail_efault, probe.w.fault r10, 3)		// this must come _after_ NaT-check
-	nop 0
-
-	ldf8 f10=[r8]			// f10 <- local_cpu_data->nsec_per_cyc value
-	cmp.ne p8, p0=0, r9
-(p8)	br.spnt.many fsys_fallback_syscall
-	;;
-.retry:	// *** seq = read_seqbegin(&xtime_lock); ***
-	ld4.acq r23=[r17]		// since &xtime_lock == &xtime_lock->sequence
-	ld8 r14=[r25]			// r14 (old) = last_nsec_offset
-
-	ld8 r28=[r26]			// r28 = jiffies
-	ld8 r29=[r27]			// r29 = wall_jiffies
-	;;
-
-	ldf8 f8=[r21]			// f8 now contains itm_next
-	mov.m r31=ar.itc		// put time stamp into r31 (ITC) == now
-	sub r28=r29, r28, 1		// r28 now contains "-(lost + 1)"
-	;;
-
-	ld8 r2=[r19]			// r2 = sec = xtime.tv_sec
-	ld8 r29=[r20]			// r29 = nsec = xtime.tv_nsec
-	tbit.nz p9, p10=r23, 0		// p9 <- is_odd(r23), p10 <- is_even(r23)
-
-	setf.sig f6=r28			// f6 <- -(lost + 1)				(6 cyc)
-	;;
-
+	mov r31 = r32
+	tnat.nz p6,p0 = r33		// guard against NaT argument
+(p6)    br.cond.spnt.few .fail_einval
+	mov r30 = CLOCK_DIVIDE_BY_1000
+	;;
+.gettime:
+	// Register map
+	// Incoming r31 = pointer to address where to place result
+	//          r30 = flags determining how time is processed
+	// r2,r3 = temp r4-r7 preserved
+	// r8 = result nanoseconds
+	// r9 = result seconds
+	// r10 = temporary storage for clock difference
+	// r11 = preserved: saved ar.pfs
+	// r12 = preserved: memory stack
+	// r13 = preserved: thread pointer
+	// r14 = debug pointer / usable
+	// r15 = preserved: system call number
+	// r16 = preserved: current task pointer
+	// r17 = wall to monotonic use
+	// r18 = time_interpolator->offset
+	// r19 = address of wall_to_monotonic
+	// r20 = pointer to struct time_interpolator / pointer to time_interpolator->address
+	// r21 = shift factor
+	// r22 = address of time interpolator->last_counter
+	// r23 = address of time_interpolator->last_cycle
+	// r24 = adress of time_interpolator->offset
+	// r25 = last_cycle value
+	// r26 = last_counter value
+	// r27 = pointer to xtime
+	// r28 = sequence number at the beginning of critcal section
+	// r29 = address of seqlock
+	// r30 = time processing flags / memory address
+	// r31 = pointer to result
+	// Predicates
+	// p6,p7 short term use
+	// p8 = timesource ar.itc
+	// p9 = timesource mmio64
+	// p10 = timesource mmio32
+	// p11 = timesource not to be handled by asm code
+	// p12 = memory time source ( = p9 | p10)
+	// p13 = do cmpxchg with time_interpolator_last_cycle
+	// p14 = Divide by 1000
+	// p15 = Add monotonic
+	//
+	// Note that instructions are optimized for McKinley. McKinley can process two
+	// bundles simultaneously and therefore we continuously try to feed the CPU
+	// two bundles and then a stop.
+	tnat.nz p6,p0 = r31	// branch deferred since it does not fit into bundle structure
+	mov pr = r30,0xc000	// Set predicates according to function
+	add r2 = TI_FLAGS+IA64_TASK_SIZE,r16
+	movl r20 = time_interpolator
+	;;
+	ld8 r20 = [r20]		// get pointer to time_interpolator structure
+	movl r29 = xtime_lock
+	ld4 r2 = [r2]		// process work pending flags
+	movl r27 = xtime
+	;;	// only one bundle here
+	ld8 r21 = [r20]		// first quad with control information
+	and r2 = TIF_ALLWORK_MASK,r2
+(p6)    br.cond.spnt.few .fail_einval	// deferred branch
+	;;
+	add r10 = IA64_TIME_INTERPOLATOR_ADDRESS_OFFSET,r20
+	extr r3 = r21,32,32	// time_interpolator->nsec_per_cyc
+	extr r8 = r21,0,16	// time_interpolator->source
+	nop.i 123
+	cmp.ne p6, p0 = 0, r2	// Fallback if work is scheduled
+(p6)    br.cond.spnt.many fsys_fallback_syscall
+	;;
+	cmp.eq p8,p12 = 0,r8	// Check for cpu timer
+	cmp.eq p9,p0 = 1,r8	// MMIO64 ?
+	extr r2 = r21,24,8	// time_interpolator->jitter
+	cmp.eq p10,p0 = 2,r8	// MMIO32 ?
+	cmp.ltu p11,p0 = 2,r8	// function or other clock
+(p11)	br.cond.spnt.many fsys_fallback_syscall
+	;;
+	setf.sig f7 = r3	// Setup for scaling of counter
+(p15)	movl r19 = wall_to_monotonic
+(p12)	ld8 r30 = [r10]
+	cmp.ne p13,p0 = r2,r0	// need jitter compensation?
+	extr r21 = r21,16,8	// shift factor
+	;;
+.time_redo:
+	.pred.rel.mutex p8,p9,p10
+	ld4.acq r28 = [r29]	// xtime_lock.sequence. Must come first for locking purposes
+(p8)	mov r2 = ar.itc		// CPU_TIMER. 36 clocks latency!!!
+	add r22 = IA64_TIME_INTERPOLATOR_LAST_COUNTER_OFFSET,r20
+(p9)	ld8 r2 = [r30]		// readq(ti->address). Could also have latency issues..
+(p10)	ld4 r2 = [r30]		// readw(ti->address)
+(p13)	add r23 = IA64_TIME_INTERPOLATOR_LAST_CYCLE_OFFSET,r20
+	;;			// could be removed by moving the last add upward
+	ld8 r26 = [r22]		// time_interpolator->last_counter
+(p13)	ld8 r25 = [r23]		// time interpolator->last_cycle
+	add r24 = IA64_TIME_INTERPOLATOR_OFFSET_OFFSET,r20
+(p15)	ld8 r17 = [r19],IA64_TIMESPEC_TV_NSEC_OFFSET
+ 	ld8 r9 = [r27],IA64_TIMESPEC_TV_NSEC_OFFSET
+	nop.i 123
+	;;
+	ld8 r18 = [r24]		// time_interpolator->offset
+	ld8 r8 = [r27],-IA64_TIMESPEC_TV_NSEC_OFFSET	// xtime.tv_nsec
+(p13)	sub r3 = r25,r2	// Diff needed before comparison (thanks davidm)
+	;;
+(p13)	cmp.gt.unc p6,p7 = r3,r0	// check if it is less than last. p6,p7 cleared
+	sub r10 = r2,r26	// current_counter - last_counter
+	;;
+(p6)	sub r10 = r25,r26	// time we got was less than last_cycle
+(p7)	mov ar.ccv = r25	// more than last_cycle. Prep for cmpxchg
+	;;
+	setf.sig f8 = r10
+	nop.i 123
+	;;
+(p7)	cmpxchg8.rel r3 = [r23],r2,ar.ccv
+EX(.fail_efault, probe.w.fault r31, 3)	// This takes 5 cycles and we have spare time
+	xmpy.l f8 = f8,f7	// nsec_per_cyc*(counter-last_counter)
+(p15)	add r9 = r9,r17		// Add wall to monotonic.secs to result secs
+	;;
+(p15)	ld8 r17 = [r19],-IA64_TIMESPEC_TV_NSEC_OFFSET
+(p7)	cmp.ne p7,p0 = r25,r3	// if cmpxchg not successful redo
+	// simulate tbit.nz.or p7,p0 = r28,0
+	and r28 = ~1,r28	// Make sequence even to force retry if odd
+	getf.sig r2 = f8
 	mf
-	xma.l f8=f6, f7, f8	// f8 (last_tick) <- -(lost + 1)*itm_delta + itm_next	(5 cyc)
-	nop 0
-
-	setf.sig f12=r31		// f12 <- ITC					(6 cyc)
-	// *** if (unlikely(read_seqretry(&xtime_lock, seq))) continue; ***
-	ld4 r24=[r17]			// r24 = xtime_lock->sequence (re-read)
-	nop 0
-	;;
-
-	xma.l f8=f11, f8, f12	// f8 (elapsed_cycles) <- (-1*last_tick + now) = (now - last_tick)
-	nop 0
-	;;
-
-	getf.sig r18=f8			// r18 <- (now - last_tick)
-	xmpy.l f8=f8, f10		// f8 <- elapsed_cycles*nsec_per_cyc (5 cyc)
-	add r3=r29, r14			// r3 = (nsec + old)
-	;;
-
-	cmp.lt p7, p8=r18, r0		// if now < last_tick, set p7 = 1, p8 = 0
-	getf.sig r18=f8			// r18 = elapsed_cycles*nsec_per_cyc		(6 cyc)
-	nop 0
-	;;
-
-(p10)	cmp.ne p9, p0=r23, r24		// if xtime_lock->sequence != seq, set p9
-	shr.u r18=r18, IA64_NSEC_PER_CYC_SHIFT	// r18 <- offset
-(p9)	br.spnt.many .retry
-	;;
-
-	mov ar.ccv=r14			// ar.ccv = old					(1 cyc)
-	cmp.leu p7, p8=r18, r14		// if (offset <= old), set p7 = 1, p8 = 0
+	add r8 = r8,r18		// Add time interpolator offset
 	;;
-
-(p8)	cmpxchg8.rel r24=[r25], r18, ar.ccv	// compare-and-exchange (atomic!)
-(p8)	add r3=r29, r18			// r3 = (nsec + offset)
-	;;
-	shr.u r3=r3, 3			// initiate dividing r3 by 1000
-	;;
-	setf.sig f8=r3			//						(6 cyc)
-	mov r10=1000000			// r10 = 1000000
+	ld4 r10 = [r29]		// xtime_lock.sequence
+(p15)	add r8 = r8, r17	// Add monotonic.nsecs to nsecs
+	shr.u r2 = r2,r21
+	;;		// overloaded 3 bundles!
+	// End critical section.
+	add r8 = r8,r2		// Add xtime.nsecs
+	cmp4.ne.or p7,p0 = r28,r10
+(p7)	br.cond.dpnt.few .time_redo	// sequence number changed ?
+	// Now r8=tv->tv_nsec and r9=tv->tv_sec
+	mov r10 = r0
+	movl r2 = 1000000000
+	add r23 = IA64_TIMESPEC_TV_NSEC_OFFSET, r31
+(p14)	movl r3 = 2361183241434822607	// Prep for / 1000 hack
+	;;
+.time_normalize:
+	mov r21 = r8
+	cmp.ge p6,p0 = r8,r2
+(p14)	shr.u r20 = r8, 3		// We can repeat this if necessary just wasting some time
+	;;
+(p14)	setf.sig f8 = r20
+(p6)	sub r8 = r8,r2
+(p6)	add r9 = 1,r9			// two nops before the branch.
+(p14)	setf.sig f7 = r3		// Chances for repeats are 1 in 10000 for gettod
+(p6)	br.cond.dpnt.few .time_normalize
+	;;
+	// Divided by 8 though shift. Now divide by 125
+	// The compiler was able to do that with a multiply
+	// and a shift and we do the same
+EX(.fail_efault, probe.w.fault r23, 3)		// This also costs 5 cycles
+(p14)	xmpy.hu f8 = f8, f7			// xmpy has 5 cycles latency so use it...
 	;;
-(p8)	cmp.ne.unc p9, p0=r24, r14
-	xmpy.hu f6=f8, f9		//						(5 cyc)
-(p9)	br.spnt.many .retry
-	;;
-
-	getf.sig r3=f6			//						(6 cyc)
+	mov r8 = r0
+(p14)	getf.sig r2 = f8
 	;;
-	shr.u r3=r3, 4			// end of division, r3 is divided by 1000 (=usec)
-	;;
-
-1:	cmp.geu p7, p0=r3, r10		// while (usec >= 1000000)
-	;;
-(p7)	sub r3=r3, r10			// usec -= 1000000
-(p7)	adds r2=1, r2			// ++sec
-(p7)	br.spnt.many 1b
-
-	// finally: r2 = sec, r3 = usec
-EX(.fail_efault, st8 [r32]=r2)
-	adds r9=8, r32
-	mov r8=r0			// success
+(p14)	shr.u r21 = r2, 4
 	;;
-EX(.fail_efault, st8 [r9]=r3)		// store them in the timeval struct
-	mov r10=0
+EX(.fail_efault, st8 [r31] = r9)
+EX(.fail_efault, st8 [r23] = r21)
 	FSYS_RETURN
-	/*
-	 * Note: We are NOT clearing the scratch registers here.  Since the only things
-	 *	 in those registers are time-related variables and some addresses (which
-	 *	 can be obtained from System.map), none of this should be security-sensitive
-	 *	 and we should be fine.
-	 */
-
 .fail_einval:
-	mov r8=EINVAL			// r8 = EINVAL
-	mov r10=-1			// r10 = -1
+	mov r8 = EINVAL
+	mov r10 = -1
 	FSYS_RETURN
-
 .fail_efault:
-	mov r8=EFAULT			// r8 = EFAULT
-	mov r10=-1			// r10 = -1
+	mov r8 = EFAULT
+	mov r10 = -1
 	FSYS_RETURN
 END(fsys_gettimeofday)
 
+ENTRY(fsys_clock_gettime)
+	.prologue
+	.altrp b6
+	.body
+	cmp4.ltu p6, p0 = CLOCK_MONOTONIC, r32
+	// Fallback if this is not CLOCK_REALTIME or CLOCK_MONOTONIC
+(p6)	br.spnt.few fsys_fallback_syscall
+	mov r31 = r33
+	shl r30 = r32,15
+	br.many .gettime
+END(fsys_clock_gettime)
+
 /*
  * long fsys_rt_sigprocmask (int how, sigset_t *set, sigset_t *oset, size_t sigsetsize).
  */
@@ -838,7 +851,7 @@
 	data8 0				// timer_getoverrun
 	data8 0				// timer_delete
 	data8 0				// clock_settime
-	data8 0				// clock_gettime
+	data8 fsys_clock_gettime	// clock_gettime
 	data8 0				// clock_getres		// 1255
 	data8 0				// clock_nanosleep
 	data8 0				// fstatfs64
diff -Nru a/arch/ia64/kernel/head.S b/arch/ia64/kernel/head.S
--- a/arch/ia64/kernel/head.S	2004-10-18 14:56:48 -07:00
+++ b/arch/ia64/kernel/head.S	2004-10-18 14:56:48 -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/iosapic.c b/arch/ia64/kernel/iosapic.c
--- a/arch/ia64/kernel/iosapic.c	2004-10-18 14:56:29 -07:00
+++ b/arch/ia64/kernel/iosapic.c	2004-10-18 14:56:29 -07:00
@@ -104,7 +104,7 @@
 /* These tables map IA-64 vectors to the IOSAPIC pin that generates this vector. */
 
 static struct iosapic_intr_info {
-	char		*addr;		/* base address of IOSAPIC */
+	char __iomem	*addr;		/* base address of IOSAPIC */
 	u32		low32;		/* current value of low word of Redirection table entry */
 	unsigned int	gsi_base;	/* first GSI assigned to this IOSAPIC */
 	char		rte_index;	/* IOSAPIC RTE index (-1 => not an IOSAPIC interrupt) */
@@ -114,9 +114,12 @@
 } iosapic_intr_info[IA64_NUM_VECTORS];
 
 static struct iosapic {
-	char		*addr;		/* base address of IOSAPIC */
+	char __iomem	*addr;		/* base address of IOSAPIC */
 	unsigned int 	gsi_base;	/* first GSI assigned to this IOSAPIC */
 	unsigned short 	num_rte;	/* number of RTE in this IOSAPIC */
+#ifdef CONFIG_NUMA
+	unsigned short	node;		/* numa node association via pxm */
+#endif
 } iosapic_lists[NR_IOSAPICS];
 
 static int num_iosapic;
@@ -176,7 +179,7 @@
 {
 	unsigned long pol, trigger, dmode, flags;
 	u32 low32, high32;
-	char *addr;
+	char __iomem *addr;
 	int rte_index;
 	char redir;
 
@@ -234,7 +237,7 @@
 mask_irq (unsigned int irq)
 {
 	unsigned long flags;
-	char *addr;
+	char __iomem *addr;
 	u32 low32;
 	int rte_index;
 	ia64_vector vec = irq_to_vector(irq);
@@ -258,7 +261,7 @@
 unmask_irq (unsigned int irq)
 {
 	unsigned long flags;
-	char *addr;
+	char __iomem *addr;
 	u32 low32;
 	int rte_index;
 	ia64_vector vec = irq_to_vector(irq);
@@ -284,7 +287,7 @@
 	unsigned long flags;
 	u32 high32, low32;
 	int dest, rte_index;
-	char *addr;
+	char __iomem *addr;
 	int redir = (irq & IA64_IRQ_REDIRECTED) ? 1 : 0;
 	ia64_vector vec;
 
@@ -409,7 +412,7 @@
 };
 
 unsigned int
-iosapic_version (char *addr)
+iosapic_version (char __iomem *addr)
 {
 	/*
 	 * IOSAPIC Version Register return 32 bit structure like:
@@ -454,7 +457,7 @@
 	int rte_index;
 	int index;
 	unsigned long gsi_base;
-	char *iosapic_address;
+	void __iomem *iosapic_address;
 
 	index = find_iosapic(gsi);
 	if (index < 0) {
@@ -488,7 +491,7 @@
 }
 
 static unsigned int
-get_target_cpu (void)
+get_target_cpu (unsigned int gsi, int vector)
 {
 #ifdef CONFIG_SMP
 	static int cpu = -1;
@@ -507,6 +510,34 @@
 	if (!cpu_online(smp_processor_id()))
 		return hard_smp_processor_id();
 
+#ifdef CONFIG_NUMA
+	{
+		int num_cpus, cpu_index, iosapic_index, numa_cpu, i = 0;
+		cpumask_t cpu_mask;
+
+		iosapic_index = find_iosapic(gsi);
+		if (iosapic_index < 0 ||
+		    iosapic_lists[iosapic_index].node == MAX_NUMNODES)
+			goto skip_numa_setup;
+
+		cpu_mask = node_to_cpumask(iosapic_lists[iosapic_index].node);
+		
+		num_cpus = cpus_weight(cpu_mask);
+
+		if (!num_cpus)
+			goto skip_numa_setup;
+
+		/* Use vector assigment to distribute across cpus in node */
+		cpu_index = vector % num_cpus;
+
+		for (numa_cpu = first_cpu(cpu_mask) ; i < cpu_index ; i++)
+			numa_cpu = next_cpu(numa_cpu, cpu_mask);
+
+		if (numa_cpu != NR_CPUS)
+			return cpu_physical_id(numa_cpu);
+	}
+skip_numa_setup:
+#endif
 	/*
 	 * Otherwise, round-robin interrupt vectors across all the
 	 * processors.  (It'd be nice if we could be smarter in the
@@ -550,7 +581,7 @@
 		}
 
 		vector = assign_irq_vector(AUTO_ASSIGN);
-		dest = get_target_cpu();
+		dest = get_target_cpu(gsi, vector);
 		register_intr(gsi, vector, IOSAPIC_LOWEST_PRIORITY,
 			polarity, trigger);
 	}
@@ -665,7 +696,7 @@
 {
 	int num_rte;
 	unsigned int isa_irq, ver;
-	char *addr;
+	char __iomem *addr;
 
 	addr = ioremap(phys_addr, 0);
 	ver = iosapic_version(addr);
@@ -680,6 +711,9 @@
 	iosapic_lists[num_iosapic].addr = addr;
 	iosapic_lists[num_iosapic].gsi_base = gsi_base;
 	iosapic_lists[num_iosapic].num_rte = num_rte;
+#ifdef CONFIG_NUMA
+	iosapic_lists[num_iosapic].node = MAX_NUMNODES;
+#endif
 	num_iosapic++;
 
 	if ((gsi_base == 0) && pcat_compat) {
@@ -692,3 +726,20 @@
 			iosapic_override_isa_irq(isa_irq, isa_irq, IOSAPIC_POL_HIGH, IOSAPIC_EDGE);
 	}
 }
+
+#ifdef CONFIG_NUMA
+void __init
+map_iosapic_to_node(unsigned int gsi_base, int node)
+{
+	int index;
+
+	index = find_iosapic(gsi_base);
+	if (index < 0) {
+		printk(KERN_WARNING "%s: No IOSAPIC for GSI %u\n",
+		       __FUNCTION__, gsi_base);
+		return;
+	}
+	iosapic_lists[index].node = node;
+	return;
+}
+#endif
diff -Nru a/arch/ia64/kernel/irq.c b/arch/ia64/kernel/irq.c
--- a/arch/ia64/kernel/irq.c	2004-10-18 14:56:50 -07:00
+++ b/arch/ia64/kernel/irq.c	2004-10-18 14:56:50 -07:00
@@ -84,11 +84,13 @@
 	}
 };
 
+#ifdef CONFIG_SMP
 /*
  * This is updated when the user sets irq affinity via /proc
  */
 cpumask_t __cacheline_aligned pending_irq_cpumask[NR_IRQS];
 static unsigned long pending_irq_redir[BITS_TO_LONGS(NR_IRQS)];
+#endif
 
 #ifdef CONFIG_IA64_GENERIC
 irq_desc_t * __ia64_irq_desc (unsigned int irq)
@@ -255,14 +257,16 @@
 		struct pt_regs *regs, struct irqaction *action)
 {
 	int status = 1;	/* Force the "do bottom halves" bit */
-	int retval = 0;
+	int ret, retval = 0;
 
 	if (!(action->flags & SA_INTERRUPT))
 		local_irq_enable();
 
 	do {
-		status |= action->flags;
-		retval |= action->handler(irq, action->dev_id, regs);
+		ret = action->handler(irq, action->dev_id, regs);
+		if (ret == IRQ_HANDLED)
+			status |= action->flags;
+		retval |= ret;
 		action = action->next;
 	} while (action);
 	if (status & SA_SAMPLE_RANDOM)
@@ -962,7 +966,7 @@
 	return len;
 }
 
-static int irq_affinity_write_proc (struct file *file, const char *buffer,
+static int irq_affinity_write_proc (struct file *file, const char __user *buffer,
 				    unsigned long count, void *data)
 {
 	unsigned int irq = (unsigned long) data;
@@ -1137,31 +1141,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 +1175,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);
+	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/ia64/kernel/irq_ia64.c b/arch/ia64/kernel/irq_ia64.c
--- a/arch/ia64/kernel/irq_ia64.c	2004-10-18 14:56:28 -07:00
+++ b/arch/ia64/kernel/irq_ia64.c	2004-10-18 14:56:28 -07:00
@@ -47,7 +47,8 @@
 #define IRQ_DEBUG	0
 
 /* default base addr of IPI table */
-unsigned long ipi_base_addr = (__IA64_UNCACHED_OFFSET | IA64_IPI_DEFAULT_BASE_ADDR);
+void __iomem *ipi_base_addr = ((void __iomem *)
+			       (__IA64_UNCACHED_OFFSET | IA64_IPI_DEFAULT_BASE_ADDR));
 
 /*
  * Legacy IRQ to IA-64 vector translation table.
@@ -254,7 +255,7 @@
 void
 ia64_send_ipi (int cpu, int vector, int delivery_mode, int redirect)
 {
-	unsigned long ipi_addr;
+	void __iomem *ipi_addr;
 	unsigned long ipi_data;
 	unsigned long phys_cpu_id;
 
@@ -269,7 +270,7 @@
 	 */
 
 	ipi_data = (delivery_mode << 8) | (vector & 0xff);
-	ipi_addr = ipi_base_addr | (phys_cpu_id << 4) | ((redirect & 1)  << 3);
+	ipi_addr = ipi_base_addr + ((phys_cpu_id << 4) | ((redirect & 1) << 3));
 
 	writeq(ipi_data, ipi_addr);
 }
diff -Nru a/arch/ia64/kernel/mca.c b/arch/ia64/kernel/mca.c
--- a/arch/ia64/kernel/mca.c	2004-10-18 14:56:29 -07:00
+++ b/arch/ia64/kernel/mca.c	2004-10-18 14:56:29 -07:00
@@ -82,11 +82,6 @@
 # define IA64_MCA_DEBUG(fmt...)
 #endif
 
-typedef struct ia64_fptr {
-	unsigned long fp;
-	unsigned long gp;
-} ia64_fptr_t;
-
 /* Used by mca_asm.S */
 ia64_mca_sal_to_os_state_t	ia64_sal_to_os_handoff_state;
 ia64_mca_os_to_sal_state_t	ia64_os_to_sal_handoff_state;
@@ -831,6 +826,31 @@
 
 }
 
+/* Function pointer for extra MCA recovery */
+int (*ia64_mca_ucmc_extension)
+	(void*,ia64_mca_sal_to_os_state_t*,ia64_mca_os_to_sal_state_t*)
+	= NULL;
+
+int
+ia64_reg_MCA_extension(void *fn)
+{
+	if (ia64_mca_ucmc_extension)
+		return 1;
+
+	ia64_mca_ucmc_extension = fn;
+	return 0;
+}
+
+void
+ia64_unreg_MCA_extension(void)
+{
+	if (ia64_mca_ucmc_extension)
+		ia64_mca_ucmc_extension = NULL;
+}
+
+EXPORT_SYMBOL(ia64_reg_MCA_extension);
+EXPORT_SYMBOL(ia64_unreg_MCA_extension);
+
 /*
  * ia64_mca_ucmc_handler
  *
@@ -852,10 +872,19 @@
 {
 	pal_processor_state_info_t *psp = (pal_processor_state_info_t *)
 		&ia64_sal_to_os_handoff_state.proc_state_param;
-	int recover = psp->tc && !(psp->cc || psp->bc || psp->rc || psp->uc);
+	int recover; 
 
 	/* Get the MCA error record and log it */
 	ia64_mca_log_sal_error_record(SAL_INFO_TYPE_MCA);
+
+	/* TLB error is only exist in this SAL error record */
+	recover = (psp->tc && !(psp->cc || psp->bc || psp->rc || psp->uc))
+	/* other error recovery */
+	   || (ia64_mca_ucmc_extension 
+		&& ia64_mca_ucmc_extension(
+			IA64_LOG_CURR_BUFFER(SAL_INFO_TYPE_MCA),
+			&ia64_sal_to_os_handoff_state,
+			&ia64_os_to_sal_handoff_state)); 
 
 	/*
 	 *  Wakeup all the processors which are spinning in the rendezvous
diff -Nru a/arch/ia64/kernel/mca_drv.c b/arch/ia64/kernel/mca_drv.c
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/arch/ia64/kernel/mca_drv.c	2004-10-18 14:57:24 -07:00
@@ -0,0 +1,639 @@
+/*
+ * File:	mca_drv.c
+ * Purpose:	Generic MCA handling layer
+ *
+ * Copyright (C) 2004 FUJITSU LIMITED
+ * Copyright (C) Hidetoshi Seto (seto.hidetoshi@jp.fujitsu.com)
+ */
+#include <linux/config.h>
+#include <linux/types.h>
+#include <linux/init.h>
+#include <linux/sched.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/kallsyms.h>
+#include <linux/smp_lock.h>
+#include <linux/bootmem.h>
+#include <linux/acpi.h>
+#include <linux/timer.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/smp.h>
+#include <linux/workqueue.h>
+#include <linux/mm.h>
+
+#include <asm/delay.h>
+#include <asm/machvec.h>
+#include <asm/page.h>
+#include <asm/ptrace.h>
+#include <asm/system.h>
+#include <asm/sal.h>
+#include <asm/mca.h>
+
+#include <asm/irq.h>
+#include <asm/hw_irq.h>
+
+#include "mca_drv.h"
+
+/* max size of SAL error record (default) */
+static int sal_rec_max = 10000;
+
+/* from mca.c */
+static ia64_mca_sal_to_os_state_t *sal_to_os_handoff_state;
+static ia64_mca_os_to_sal_state_t *os_to_sal_handoff_state;
+
+/* from mca_drv_asm.S */
+extern void *mca_handler_bhhook(void);
+
+static spinlock_t mca_bh_lock = SPIN_LOCK_UNLOCKED;
+
+typedef enum {
+	MCA_IS_LOCAL  = 0,
+	MCA_IS_GLOBAL = 1
+} mca_type_t;
+
+#define MAX_PAGE_ISOLATE 32
+
+static struct page *page_isolate[MAX_PAGE_ISOLATE];
+static int num_page_isolate = 0;
+
+typedef enum {
+	ISOLATE_NG = 0,
+	ISOLATE_OK = 1
+} isolate_status_t;
+
+/*
+ *  This pool keeps pointers to the section part of SAL error record
+ */
+static struct {
+	slidx_list_t *buffer; /* section pointer list pool */
+	int	     cur_idx; /* Current index of section pointer list pool */
+	int	     max_idx; /* Maximum index of section pointer list pool */
+} slidx_pool;
+
+/**
+ * mca_page_isolate - isolate a poisoned page in order not to use it later
+ * @paddr:	poisoned memory location
+ *
+ * Return value:
+ *	ISOLATE_OK / ISOLATE_NG
+ */
+
+static isolate_status_t
+mca_page_isolate(unsigned long paddr)
+{
+	int i;
+	struct page *p;
+
+	/* whether physical address is valid or not */
+	if ( !ia64_phys_addr_valid(paddr) ) 
+		return ISOLATE_NG;
+
+	/* convert physical address to physical page number */
+	p = pfn_to_page(paddr>>PAGE_SHIFT);
+
+	/* check whether a page number have been already registered or not */
+	for( i = 0; i < num_page_isolate; i++ )
+		if( page_isolate[i] == p )
+			return ISOLATE_OK; /* already listed */
+
+	/* limitation check */
+	if( num_page_isolate == MAX_PAGE_ISOLATE ) 
+		return ISOLATE_NG;
+
+	/* kick pages having attribute 'SLAB' or 'Reserved' */
+	if( PageSlab(p) || PageReserved(p) ) 
+		return ISOLATE_NG;
+
+	/* add attribute 'Reserved' and register the page */
+	SetPageReserved(p);
+	page_isolate[num_page_isolate++] = p;
+
+	return ISOLATE_OK;
+}
+
+/**
+ * mca_hanlder_bh - Kill the process which occurred memory read error
+ * @paddr:	poisoned address received from MCA Handler
+ */
+
+void
+mca_handler_bh(unsigned long paddr)
+{
+	printk(KERN_DEBUG "OS_MCA: process [pid: %d](%s) encounters MCA.\n",
+		current->pid, current->comm);
+
+	spin_lock(&mca_bh_lock);
+	if (mca_page_isolate(paddr) == ISOLATE_OK) {
+		printk(KERN_DEBUG "Page isolation: ( %lx ) success.\n", paddr);
+	} else {
+		printk(KERN_DEBUG "Page isolation: ( %lx ) failure.\n", paddr);
+	}
+	spin_unlock(&mca_bh_lock);
+
+	/* This process is about to be killed itself */
+	force_sig(SIGKILL, current);
+	schedule();
+}
+
+/**
+ * mca_make_peidx - Make index of processor error section
+ * @slpi:	pointer to record of processor error section
+ * @peidx:	pointer to index of processor error section
+ */
+
+static void 
+mca_make_peidx(sal_log_processor_info_t *slpi, peidx_table_t *peidx)
+{
+	/* 
+	 * calculate the start address of
+	 *   "struct cpuid_info" and "sal_processor_static_info_t".
+	 */
+	u64 total_check_num = slpi->valid.num_cache_check
+				+ slpi->valid.num_tlb_check
+				+ slpi->valid.num_bus_check
+				+ slpi->valid.num_reg_file_check
+				+ slpi->valid.num_ms_check;
+	u64 head_size =	sizeof(sal_log_mod_error_info_t) * total_check_num
+			+ sizeof(sal_log_processor_info_t);
+	u64 mid_size  = slpi->valid.cpuid_info * sizeof(struct sal_cpuid_info);
+
+	peidx_head(peidx)   = slpi;
+	peidx_mid(peidx)    = (struct sal_cpuid_info *)
+		(slpi->valid.cpuid_info ? ((char*)slpi + head_size) : NULL);
+	peidx_bottom(peidx) = (sal_processor_static_info_t *)
+		(slpi->valid.psi_static_struct ?
+			((char*)slpi + head_size + mid_size) : NULL);
+}
+
+/**
+ * mca_make_slidx -  Make index of SAL error record 
+ * @buffer:	pointer to SAL error record
+ * @slidx:	pointer to index of SAL error record
+ *
+ * Return value:
+ *	1 if record has platform error / 0 if not
+ */
+#define LOG_INDEX_ADD_SECT_PTR(sect, ptr) \
+        { slidx_list_t *hl = &slidx_pool.buffer[slidx_pool.cur_idx]; \
+          hl->hdr = ptr; \
+          list_add(&hl->list, &(sect)); \
+          slidx_pool.cur_idx = (slidx_pool.cur_idx + 1)%slidx_pool.max_idx; }
+
+static int 
+mca_make_slidx(void *buffer, slidx_table_t *slidx)
+{
+	int platform_err = 0;
+	int record_len = ((sal_log_record_header_t*)buffer)->len;
+	u32 ercd_pos;
+	int sects;
+	sal_log_section_hdr_t *sp;
+
+	/*
+	 * Initialize index referring current record
+	 */
+	INIT_LIST_HEAD(&(slidx->proc_err));
+	INIT_LIST_HEAD(&(slidx->mem_dev_err));
+	INIT_LIST_HEAD(&(slidx->sel_dev_err));
+	INIT_LIST_HEAD(&(slidx->pci_bus_err));
+	INIT_LIST_HEAD(&(slidx->smbios_dev_err));
+	INIT_LIST_HEAD(&(slidx->pci_comp_err));
+	INIT_LIST_HEAD(&(slidx->plat_specific_err));
+	INIT_LIST_HEAD(&(slidx->host_ctlr_err));
+	INIT_LIST_HEAD(&(slidx->plat_bus_err));
+	INIT_LIST_HEAD(&(slidx->unsupported));
+
+	/*
+	 * Extract a Record Header
+	 */
+	slidx->header = buffer;
+
+	/*
+	 * Extract each section records
+	 * (arranged from "int ia64_log_platform_info_print()")
+	 */
+	for (ercd_pos = sizeof(sal_log_record_header_t), sects = 0;
+		ercd_pos < record_len; ercd_pos += sp->len, sects++) {
+		sp = (sal_log_section_hdr_t *)((char*)buffer + ercd_pos);
+		if (!efi_guidcmp(sp->guid, SAL_PROC_DEV_ERR_SECT_GUID)) {
+			LOG_INDEX_ADD_SECT_PTR(slidx->proc_err, sp);
+		} else if (!efi_guidcmp(sp->guid, SAL_PLAT_MEM_DEV_ERR_SECT_GUID)) {
+			platform_err = 1;
+			LOG_INDEX_ADD_SECT_PTR(slidx->mem_dev_err, sp);
+		} else if (!efi_guidcmp(sp->guid, SAL_PLAT_SEL_DEV_ERR_SECT_GUID)) {
+			platform_err = 1;
+			LOG_INDEX_ADD_SECT_PTR(slidx->sel_dev_err, sp);
+		} else if (!efi_guidcmp(sp->guid, SAL_PLAT_PCI_BUS_ERR_SECT_GUID)) {
+			platform_err = 1;
+			LOG_INDEX_ADD_SECT_PTR(slidx->pci_bus_err, sp);
+		} else if (!efi_guidcmp(sp->guid, SAL_PLAT_SMBIOS_DEV_ERR_SECT_GUID)) {
+			platform_err = 1;
+			LOG_INDEX_ADD_SECT_PTR(slidx->smbios_dev_err, sp);
+		} else if (!efi_guidcmp(sp->guid, SAL_PLAT_PCI_COMP_ERR_SECT_GUID)) {
+			platform_err = 1;
+			LOG_INDEX_ADD_SECT_PTR(slidx->pci_comp_err, sp);
+		} else if (!efi_guidcmp(sp->guid, SAL_PLAT_SPECIFIC_ERR_SECT_GUID)) {
+			platform_err = 1;
+			LOG_INDEX_ADD_SECT_PTR(slidx->plat_specific_err, sp);
+		} else if (!efi_guidcmp(sp->guid, SAL_PLAT_HOST_CTLR_ERR_SECT_GUID)) {
+			platform_err = 1;
+			LOG_INDEX_ADD_SECT_PTR(slidx->host_ctlr_err, sp);
+		} else if (!efi_guidcmp(sp->guid, SAL_PLAT_BUS_ERR_SECT_GUID)) {
+			platform_err = 1;
+			LOG_INDEX_ADD_SECT_PTR(slidx->plat_bus_err, sp);
+		} else {
+			LOG_INDEX_ADD_SECT_PTR(slidx->unsupported, sp);
+		}
+	}
+	slidx->n_sections = sects;
+
+	return platform_err;
+}
+
+/**
+ * init_record_index_pools - Initialize pool of lists for SAL record index
+ *
+ * Return value:
+ *	0 on Success / -ENOMEM on Failure
+ */
+static int 
+init_record_index_pools(void)
+{
+	int i;
+	int rec_max_size;  /* Maximum size of SAL error records */
+	int sect_min_size; /* Minimum size of SAL error sections */
+	/* minimum size table of each section */
+	static int sal_log_sect_min_sizes[] = { 
+		sizeof(sal_log_processor_info_t) + sizeof(sal_processor_static_info_t),
+		sizeof(sal_log_mem_dev_err_info_t),
+		sizeof(sal_log_sel_dev_err_info_t),
+		sizeof(sal_log_pci_bus_err_info_t),
+		sizeof(sal_log_smbios_dev_err_info_t),
+		sizeof(sal_log_pci_comp_err_info_t),
+		sizeof(sal_log_plat_specific_err_info_t),
+		sizeof(sal_log_host_ctlr_err_info_t),
+		sizeof(sal_log_plat_bus_err_info_t),
+	};
+
+	/*
+	 * MCA handler cannot allocate new memory on flight,
+	 * so we preallocate enough memory to handle a SAL record.
+	 *
+	 * Initialize a handling set of slidx_pool:
+	 *   1. Pick up the max size of SAL error records
+	 *   2. Pick up the min size of SAL error sections
+	 *   3. Allocate the pool as enough to 2 SAL records
+	 *     (now we can estimate the maxinum of section in a record.)
+	 */
+
+	/* - 1 - */
+	rec_max_size = sal_rec_max;
+
+	/* - 2 - */
+	sect_min_size = sal_log_sect_min_sizes[0];
+	for (i = 1; i < sizeof sal_log_sect_min_sizes/sizeof(size_t); i++)
+		if (sect_min_size > sal_log_sect_min_sizes[i])
+			sect_min_size = sal_log_sect_min_sizes[i];
+
+	/* - 3 - */
+	slidx_pool.max_idx = (rec_max_size/sect_min_size) * 2 + 1;
+	slidx_pool.buffer = (slidx_list_t *) kmalloc(slidx_pool.max_idx * sizeof(slidx_list_t), GFP_KERNEL);
+
+	return slidx_pool.buffer ? 0 : -ENOMEM;
+}
+
+
+/*****************************************************************************
+ * Recovery functions                                                        *
+ *****************************************************************************/
+
+/**
+ * is_mca_global - Check whether this MCA is global or not
+ * @peidx:	pointer of index of processor error section
+ * @pbci:	pointer to pal_bus_check_info_t
+ *
+ * Return value:
+ *	MCA_IS_LOCAL / MCA_IS_GLOBAL
+ */
+
+static mca_type_t
+is_mca_global(peidx_table_t *peidx, pal_bus_check_info_t *pbci)
+{
+	pal_processor_state_info_t *psp = (pal_processor_state_info_t*)peidx_psp(peidx);
+
+	/* 
+	 * PAL can request a rendezvous, if the MCA has a global scope.
+	 * If "rz_always" flag is set, SAL requests MCA rendezvous 
+	 * in spite of global MCA.
+	 * Therefore it is local MCA when rendezvous has not been requested.
+	 * Failed to rendezvous, the system must be down.
+	 */
+	switch (sal_to_os_handoff_state->imsto_rendez_state) {
+		case -1: /* SAL rendezvous unsuccessful */
+			return MCA_IS_GLOBAL;
+		case  0: /* SAL rendezvous not required */
+			return MCA_IS_LOCAL;
+		case  1: /* SAL rendezvous successful int */
+		case  2: /* SAL rendezvous successful int with init */
+		default:
+			break;
+	}
+
+	/*
+	 * If One or more Cache/TLB/Reg_File/Uarch_Check is here,
+	 * it would be a local MCA. (i.e. processor internal error)
+	 */
+	if (psp->tc || psp->cc || psp->rc || psp->uc)
+		return MCA_IS_LOCAL;
+	
+	/*
+	 * Bus_Check structure with Bus_Check.ib (internal bus error) flag set
+	 * would be a global MCA. (e.g. a system bus address parity error)
+	 */
+	if (!pbci || pbci->ib)
+		return MCA_IS_GLOBAL;
+
+	/*
+	 * Bus_Check structure with Bus_Check.eb (external bus error) flag set
+	 * could be either a local MCA or a global MCA.
+	 *
+	 * Referring Bus_Check.bsi:
+	 *   0: Unknown/unclassified
+	 *   1: BERR#
+	 *   2: BINIT#
+	 *   3: Hard Fail
+	 * (FIXME: Are these SGI specific or generic bsi values?)
+	 */
+	if (pbci->eb)
+		switch (pbci->bsi) {
+			case 0:
+				/* e.g. a load from poisoned memory */
+				return MCA_IS_LOCAL;
+			case 1:
+			case 2:
+			case 3:
+				return MCA_IS_GLOBAL;
+		}
+
+	return MCA_IS_GLOBAL;
+}
+
+/**
+ * recover_from_read_error - Try to recover the errors which type are "read"s.
+ * @slidx:	pointer of index of SAL error record
+ * @peidx:	pointer of index of processor error section
+ * @pbci:	pointer of pal_bus_check_info
+ *
+ * Return value:
+ *	1 on Success / 0 on Failure
+ */
+
+static int
+recover_from_read_error(slidx_table_t *slidx, peidx_table_t *peidx, pal_bus_check_info_t *pbci)
+{
+	sal_log_mod_error_info_t *smei;
+	pal_min_state_area_t *pmsa;
+	struct ia64_psr *psr1, *psr2;
+	ia64_fptr_t *mca_hdlr_bh = (ia64_fptr_t*)mca_handler_bhhook;
+
+	/* Is target address valid? */
+	if (!pbci->tv)
+		return 0;
+
+	/*
+	 * cpu read or memory-mapped io read
+	 *
+	 *    offending process  affected process  OS MCA do
+	 *     kernel mode        kernel mode       down system
+	 *     kernel mode        user   mode       kill the process
+	 *     user   mode        kernel mode       down system (*)
+	 *     user   mode        user   mode       kill the process
+	 *
+	 * (*) You could terminate offending user-mode process
+	 *    if (pbci->pv && pbci->pl != 0) *and* if you sure
+	 *    the process not have any locks of kernel.
+	 */
+
+	psr1 =(struct ia64_psr *)&(peidx_minstate_area(peidx)->pmsa_ipsr);
+
+	/*
+	 *  Check the privilege level of interrupted context.
+	 *   If it is user-mode, then terminate affected process.
+	 */
+	if (psr1->cpl != 0) {
+		smei = peidx_bus_check(peidx, 0);
+		if (smei->valid.target_identifier) {
+			/*
+			 *  setup for resume to bottom half of MCA,
+			 * "mca_handler_bhhook"
+			 */
+			pmsa = (pal_min_state_area_t *)(sal_to_os_handoff_state->pal_min_state | (6ul<<61));
+			/* pass to bhhook as 1st argument (gr8) */
+			pmsa->pmsa_gr[8-1] = smei->target_identifier;
+			/* set interrupted return address (but no use) */
+			pmsa->pmsa_br0 = pmsa->pmsa_iip;
+			/* change resume address to bottom half */
+			pmsa->pmsa_iip = mca_hdlr_bh->fp;
+			pmsa->pmsa_gr[1-1] = mca_hdlr_bh->gp;
+			/* set cpl with kernel mode */
+			psr2 = (struct ia64_psr *)&pmsa->pmsa_ipsr;
+			psr2->cpl = 0;
+			psr2->ri  = 0;
+
+			return 1;
+		}
+
+	}
+
+	return 0;
+}
+
+/**
+ * recover_from_platform_error - Recover from platform error.
+ * @slidx:	pointer of index of SAL error record
+ * @peidx:	pointer of index of processor error section
+ * @pbci:	pointer of pal_bus_check_info
+ *
+ * Return value:
+ *	1 on Success / 0 on Failure
+ */
+
+static int
+recover_from_platform_error(slidx_table_t *slidx, peidx_table_t *peidx, pal_bus_check_info_t *pbci)
+{
+	int status = 0;
+	pal_processor_state_info_t *psp = (pal_processor_state_info_t*)peidx_psp(peidx);
+
+	if (psp->bc && pbci->eb && pbci->bsi == 0) {
+		switch(pbci->type) {
+		case 1: /* partial read */
+		case 3: /* full line(cpu) read */
+		case 9: /* I/O space read */
+			status = recover_from_read_error(slidx, peidx, pbci);
+			break;
+		case 0: /* unknown */
+		case 2: /* partial write */
+		case 4: /* full line write */
+		case 5: /* implicit or explicit write-back operation */
+		case 6: /* snoop probe */
+		case 7: /* incoming or outgoing ptc.g */
+		case 8: /* write coalescing transactions */
+		case 10: /* I/O space write */
+		case 11: /* inter-processor interrupt message(IPI) */
+		case 12: /* interrupt acknowledge or external task priority cycle */
+		default:
+			break;
+		}
+	}
+
+	return status;
+}
+
+/**
+ * recover_from_processor_error
+ * @platform:	whether there are some platform error section or not
+ * @slidx:	pointer of index of SAL error record
+ * @peidx:	pointer of index of processor error section
+ * @pbci:	pointer of pal_bus_check_info
+ *
+ * Return value:
+ *	1 on Success / 0 on Failure
+ */
+/*
+ *  Later we try to recover when below all conditions are satisfied.
+ *   1. Only one processor error section is exist.
+ *   2. BUS_CHECK is exist and the others are not exist.(Except TLB_CHECK)
+ *   3. The entry of BUS_CHECK_INFO is 1.
+ *   4. "External bus error" flag is set and the others are not set.
+ */
+
+static int
+recover_from_processor_error(int platform, slidx_table_t *slidx, peidx_table_t *peidx, pal_bus_check_info_t *pbci)
+{
+	pal_processor_state_info_t *psp = (pal_processor_state_info_t*)peidx_psp(peidx);
+
+	/* 
+	 * We cannot recover errors with other than bus_check.
+	 */
+	if (psp->cc || psp->rc || psp->uc) 
+		return 0;
+
+	/*
+	 * If there is no bus error, record is weird but we need not to recover.
+	 */
+	if (psp->bc == 0 || pbci == NULL)
+		return 1;
+
+	/*
+	 * Sorry, we cannot handle so many.
+	 */
+	if (peidx_bus_check_num(peidx) > 1)
+		return 0;
+	/*
+	 * Well, here is only one bus error.
+	 */
+	if (pbci->ib || pbci->cc)
+		return 0;
+	if (pbci->eb && pbci->bsi > 0)
+		return 0;
+	if (psp->ci == 0)
+		return 0;
+
+	/*
+	 * This is a local MCA and estimated as recoverble external bus error.
+	 * (e.g. a load from poisoned memory)
+	 * This means "there are some platform errors".
+	 */
+	if (platform) 
+		return recover_from_platform_error(slidx, peidx, pbci);
+	/* 
+	 * On account of strange SAL error record, we cannot recover. 
+	 */
+	return 0;
+}
+
+/**
+ * mca_try_to_recover - Try to recover from MCA
+ * @rec:	pointer to a SAL error record
+ *
+ * Return value:
+ *	1 on Success / 0 on Failure
+ */
+
+static int
+mca_try_to_recover(void *rec, 
+	ia64_mca_sal_to_os_state_t *sal_to_os_state,
+	ia64_mca_os_to_sal_state_t *os_to_sal_state)
+{
+	int platform_err;
+	int n_proc_err;
+	slidx_table_t slidx;
+	peidx_table_t peidx;
+	pal_bus_check_info_t pbci;
+
+	/* handoff state from/to mca.c */
+	sal_to_os_handoff_state = sal_to_os_state;
+	os_to_sal_handoff_state = os_to_sal_state;
+
+	/* Make index of SAL error record */
+	platform_err = mca_make_slidx(rec, &slidx);
+
+	/* Count processor error sections */
+	n_proc_err = slidx_count(&slidx, proc_err);
+
+	 /* Now, OS can recover when there is one processor error section */
+	if (n_proc_err > 1)
+		return 0;
+	else if (n_proc_err == 0) {
+		/* Weird SAL record ... We need not to recover */
+
+		return 1;
+	}
+
+	/* Make index of processor error section */
+	mca_make_peidx((sal_log_processor_info_t*)slidx_first_entry(&slidx.proc_err)->hdr, &peidx);
+
+	/* Extract Processor BUS_CHECK[0] */
+	*((u64*)&pbci) = peidx_check_info(&peidx, bus_check, 0);
+
+	/* Check whether MCA is global or not */
+	if (is_mca_global(&peidx, &pbci))
+		return 0;
+	
+	/* Try to recover a processor error */
+	return recover_from_processor_error(platform_err, &slidx, &peidx, &pbci);
+}
+
+/*
+ * =============================================================================
+ */
+
+int __init mca_external_handler_init(void)
+{
+	if (init_record_index_pools())
+		return -ENOMEM;
+
+	/* register external mca handlers */
+	if (ia64_reg_MCA_extension(mca_try_to_recover)){	
+		printk(KERN_ERR "ia64_reg_MCA_extension failed.\n");
+		kfree(slidx_pool.buffer);
+		return -EFAULT;
+	}
+	return 0;
+}
+
+void __exit mca_external_handler_exit(void)
+{
+	/* unregister external mca handlers */
+	ia64_unreg_MCA_extension();
+	kfree(slidx_pool.buffer);
+}
+
+module_init(mca_external_handler_init);
+module_exit(mca_external_handler_exit);
+
+module_param(sal_rec_max, int, 0644);
+MODULE_PARM_DESC(sal_rec_max, "Max size of SAL error record");
+
+MODULE_DESCRIPTION("ia64 platform dependent mca handler driver");
+MODULE_LICENSE("GPL");
diff -Nru a/arch/ia64/kernel/mca_drv.h b/arch/ia64/kernel/mca_drv.h
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/arch/ia64/kernel/mca_drv.h	2004-10-18 14:57:23 -07:00
@@ -0,0 +1,113 @@
+/*
+ * File:	mca_drv.h
+ * Purpose:	Define helpers for Generic MCA handling
+ *
+ * Copyright (C) 2004 FUJITSU LIMITED
+ * Copyright (C) Hidetoshi Seto (seto.hidetoshi@jp.fujitsu.com)
+ */
+/*
+ * Processor error section: 
+ *
+ *  +-sal_log_processor_info_t *info-------------+
+ *  | sal_log_section_hdr_t header;              |
+ *  | ...                                        |
+ *  | sal_log_mod_error_info_t info[0];          |
+ *  +-+----------------+-------------------------+
+ *    | CACHE_CHECK    |  ^ num_cache_check v
+ *    +----------------+
+ *    | TLB_CHECK      |  ^ num_tlb_check v
+ *    +----------------+
+ *    | BUS_CHECK      |  ^ num_bus_check v
+ *    +----------------+
+ *    | REG_FILE_CHECK |  ^ num_reg_file_check v
+ *    +----------------+
+ *    | MS_CHECK       |  ^ num_ms_check v
+ *  +-struct cpuid_info *id----------------------+
+ *  | regs[5];                                   |
+ *  | reserved;                                  |
+ *  +-sal_processor_static_info_t *regs----------+
+ *  | valid;                                     |
+ *  | ...                                        |
+ *  | fr[128];                                   |
+ *  +--------------------------------------------+
+ */
+
+/* peidx: index of processor error section */
+typedef struct peidx_table {
+	sal_log_processor_info_t        *info;
+	struct sal_cpuid_info           *id;
+	sal_processor_static_info_t     *regs;
+} peidx_table_t;
+
+#define peidx_head(p)   (((p)->info))
+#define peidx_mid(p)    (((p)->id))
+#define peidx_bottom(p) (((p)->regs))
+
+#define peidx_psp(p)           (&(peidx_head(p)->proc_state_parameter))
+#define peidx_field_valid(p)   (&(peidx_head(p)->valid))
+#define peidx_minstate_area(p) (&(peidx_bottom(p)->min_state_area))
+
+#define peidx_cache_check_num(p)    (peidx_head(p)->valid.num_cache_check)
+#define peidx_tlb_check_num(p)      (peidx_head(p)->valid.num_tlb_check)
+#define peidx_bus_check_num(p)      (peidx_head(p)->valid.num_bus_check)
+#define peidx_reg_file_check_num(p) (peidx_head(p)->valid.num_reg_file_check)
+#define peidx_ms_check_num(p)       (peidx_head(p)->valid.num_ms_check)
+
+#define peidx_cache_check_idx(p, n)    (n)
+#define peidx_tlb_check_idx(p, n)      (peidx_cache_check_idx(p, peidx_cache_check_num(p)) + n)
+#define peidx_bus_check_idx(p, n)      (peidx_tlb_check_idx(p, peidx_tlb_check_num(p)) + n)
+#define peidx_reg_file_check_idx(p, n) (peidx_bus_check_idx(p, peidx_bus_check_num(p)) + n)
+#define peidx_ms_check_idx(p, n)       (peidx_reg_file_check_idx(p, peidx_reg_file_check_num(p)) + n)
+
+#define peidx_mod_error_info(p, name, n) \
+({	int __idx = peidx_##name##_idx(p, n); \
+	sal_log_mod_error_info_t *__ret = NULL; \
+	if (peidx_##name##_num(p) > n) /*BUG*/ \
+		__ret = &(peidx_head(p)->info[__idx]); \
+	__ret; })
+
+#define peidx_cache_check(p, n)    peidx_mod_error_info(p, cache_check, n)
+#define peidx_tlb_check(p, n)      peidx_mod_error_info(p, tlb_check, n)
+#define peidx_bus_check(p, n)      peidx_mod_error_info(p, bus_check, n)
+#define peidx_reg_file_check(p, n) peidx_mod_error_info(p, reg_file_check, n)
+#define peidx_ms_check(p, n)       peidx_mod_error_info(p, ms_check, n)
+
+#define peidx_check_info(proc, name, n) \
+({ \
+	sal_log_mod_error_info_t *__info = peidx_mod_error_info(proc, name, n);\
+	u64 __temp = __info && __info->valid.check_info \
+		? __info->check_info : 0; \
+	__temp; })
+
+/* slidx: index of SAL log error record */
+
+typedef struct slidx_list {
+	struct list_head list;
+	sal_log_section_hdr_t *hdr;
+} slidx_list_t;
+
+typedef struct slidx_table {
+	sal_log_record_header_t *header;
+	int n_sections;			/* # of section headers */
+	struct list_head proc_err;
+	struct list_head mem_dev_err;
+	struct list_head sel_dev_err;
+	struct list_head pci_bus_err;
+	struct list_head smbios_dev_err;
+	struct list_head pci_comp_err;
+	struct list_head plat_specific_err;
+	struct list_head host_ctlr_err;
+	struct list_head plat_bus_err;
+	struct list_head unsupported;	/* list of unsupported sections */
+} slidx_table_t;
+
+#define slidx_foreach_entry(pos, head) \
+	list_for_each_entry(pos, head, list)
+#define slidx_first_entry(head) \
+	(((head)->next != (head)) ? list_entry((head)->next, typeof(slidx_list_t), list) : NULL)
+#define slidx_count(slidx, sec) \
+({	int __count = 0; \
+	slidx_list_t *__pos; \
+	slidx_foreach_entry(__pos, &((slidx)->sec)) { __count++; }\
+	__count; })
+
diff -Nru a/arch/ia64/kernel/mca_drv_asm.S b/arch/ia64/kernel/mca_drv_asm.S
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/arch/ia64/kernel/mca_drv_asm.S	2004-10-18 14:57:23 -07:00
@@ -0,0 +1,45 @@
+/*
+ * File:        mca_drv_asm.S
+ * Purpose:     Assembly portion of Generic MCA handling
+ *
+ * Copyright (C) 2004 FUJITSU LIMITED
+ * Copyright (C) Hidetoshi Seto (seto.hidetoshi@jp.fujitsu.com)
+ */
+#include <linux/config.h>
+#include <linux/threads.h>
+
+#include <asm/asmmacro.h>
+#include <asm/processor.h>
+
+GLOBAL_ENTRY(mca_handler_bhhook)
+	invala						// clear RSE ?
+	;;						//
+	cover						// 
+	;;						//
+	clrrrb						//
+	;;						
+	alloc		r16=ar.pfs,0,2,1,0		// make a new frame
+	;;
+	mov		r13=IA64_KR(CURRENT)		// current task pointer
+	;;
+	adds		r12=IA64_TASK_THREAD_KSP_OFFSET,r13
+	;;
+	ld8		r12=[r12]			// stack pointer
+	;;
+	mov		loc0=r16
+	movl		loc1=mca_handler_bh		// recovery C function
+	;;
+	mov		out0=r8				// poisoned address
+	mov		b6=loc1
+	;;
+	mov		loc1=rp
+	;;
+	br.call.sptk.many    rp=b6			// not return ...
+	;;
+	mov		ar.pfs=loc0
+	mov 		rp=loc1
+	;;
+	mov		r8=r0
+	br.ret.sptk.many rp
+	;;
+END(mca_handler_bhhook)
diff -Nru a/arch/ia64/kernel/minstate.h b/arch/ia64/kernel/minstate.h
--- a/arch/ia64/kernel/minstate.h	2004-10-18 14:56:50 -07:00
+++ b/arch/ia64/kernel/minstate.h	2004-10-18 14:56:50 -07:00
@@ -54,8 +54,7 @@
 (pUStk)	mov ar.rsc=0x3;		/* set eager mode, pl 0, little-endian, loadrs=0 */		\
 
 #define MINSTATE_END_SAVE_MIN_PHYS								\
-	or r12=r12,r14;		/* make sp a kernel virtual address */				\
-	or r13=r13,r14;		/* make `current' a kernel virtual address */			\
+	dep r12=-1,r12,61,3;		/* make sp a kernel virtual address */			\
 	;;
 
 #ifdef MINSTATE_VIRT
@@ -65,7 +64,7 @@
 #endif
 
 #ifdef MINSTATE_PHYS
-# define MINSTATE_GET_CURRENT(reg)	mov reg=IA64_KR(CURRENT);; dep reg=0,reg,61,3
+# define MINSTATE_GET_CURRENT(reg)	mov reg=IA64_KR(CURRENT);; tpa reg=reg
 # define MINSTATE_START_SAVE_MIN	MINSTATE_START_SAVE_MIN_PHYS
 # define MINSTATE_END_SAVE_MIN		MINSTATE_END_SAVE_MIN_PHYS
 #endif
@@ -172,7 +171,6 @@
 	;;											\
 .mem.offset 0,0; st8.spill [r16]=r15,16;							\
 .mem.offset 8,0; st8.spill [r17]=r14,16;							\
-	dep r14=-1,r0,61,3;									\
 	;;											\
 .mem.offset 0,0; st8.spill [r16]=r2,16;								\
 .mem.offset 8,0; st8.spill [r17]=r3,16;								\
diff -Nru a/arch/ia64/kernel/module.c b/arch/ia64/kernel/module.c
--- a/arch/ia64/kernel/module.c	2004-10-18 14:56:29 -07:00
+++ b/arch/ia64/kernel/module.c	2004-10-18 14:56:29 -07:00
@@ -195,10 +195,10 @@
 		printk(KERN_ERR "%s: value %li out of IMM22 range\n", mod->name, (int64_t)val);
 		return 0;
 	}
-	ia64_patch((u64) insn, 0x01fffcfe000, (  ((val & 0x200000) << 15) /* bit 21 -> 36 */
-					       | ((val & 0x1f0000) <<  6) /* bit 16 -> 22 */
-					       | ((val & 0x00ff80) << 20) /* bit  7 -> 27 */
-					       | ((val & 0x00007f) << 13) /* bit  0 -> 13 */));
+	ia64_patch((u64) insn, 0x01fffcfe000UL, (  ((val & 0x200000UL) << 15) /* bit 21 -> 36 */
+					         | ((val & 0x1f0000UL) <<  6) /* bit 16 -> 22 */
+					         | ((val & 0x00ff80UL) << 20) /* bit  7 -> 27 */
+					         | ((val & 0x00007fUL) << 13) /* bit  0 -> 13 */));
 	return 1;
 }
 
@@ -209,8 +209,8 @@
 		printk(KERN_ERR "%s: value %li out of IMM21b range\n", mod->name, (int64_t)val);
 		return 0;
 	}
-	ia64_patch((u64) insn, 0x11ffffe000, (  ((val & 0x100000) << 16) /* bit 20 -> 36 */
-					      | ((val & 0x0fffff) << 13) /* bit  0 -> 13 */));
+	ia64_patch((u64) insn, 0x11ffffe000UL, (  ((val & 0x100000UL) << 16) /* bit 20 -> 36 */
+					        | ((val & 0x0fffffUL) << 13) /* bit  0 -> 13 */));
 	return 1;
 }
 
@@ -253,9 +253,9 @@
 	long off;
 
 	b0 = b[0]; b1 = b[1];
-	off = (  ((b1 & 0x00fffff000000000) >> 36)		/* imm20b -> bit 0 */
-	       | ((b0 >> 48) << 20) | ((b1 & 0x7fffff) << 36)	/* imm39 -> bit 20 */
-	       | ((b1 & 0x0800000000000000) << 0));		/* i -> bit 59 */
+	off = (  ((b1 & 0x00fffff000000000UL) >> 36)		/* imm20b -> bit 0 */
+	       | ((b0 >> 48) << 20) | ((b1 & 0x7fffffUL) << 36)	/* imm39 -> bit 20 */
+	       | ((b1 & 0x0800000000000000UL) << 0));		/* i -> bit 59 */
 	return (long) plt->bundle[1] + 16*off;
 }
 
@@ -739,7 +739,7 @@
 			if (gp_addressable(mod, val)) {
 				/* turn "ld8" into "mov": */
 				DEBUGP("%s: patching ld8 at %p to mov\n", __FUNCTION__, location);
-				ia64_patch((u64) location, 0x1fff80fe000, 0x10000000000);
+				ia64_patch((u64) location, 0x1fff80fe000UL, 0x10000000000UL);
 			}
 			return 0;
 
diff -Nru a/arch/ia64/kernel/palinfo.c b/arch/ia64/kernel/palinfo.c
--- a/arch/ia64/kernel/palinfo.c	2004-10-18 14:55:54 -07:00
+++ b/arch/ia64/kernel/palinfo.c	2004-10-18 14:55:54 -07:00
@@ -446,7 +446,7 @@
 		     "RSE stacked physical registers   : %ld\n"
 		     "RSE load/store hints             : %ld (%s)\n",
 		     phys_stacked, hints.ph_data,
-		     hints.ph_data < RSE_HINTS_COUNT ? rse_hints[hints.ph_data]: "(\?\?)");
+		     hints.ph_data < RSE_HINTS_COUNT ? rse_hints[hints.ph_data]: "(??)");
 
 	if (ia64_pal_debug_info(&iregs, &dregs))
 		return 0;
@@ -479,7 +479,7 @@
 	"Enable CMCI promotion",
 	"Enable MCA to BINIT promotion",
 	"Enable MCA promotion",
-	"Enable BEER promotion"
+	"Enable BERR promotion"
 };
 
 
diff -Nru a/arch/ia64/kernel/patch.c b/arch/ia64/kernel/patch.c
--- a/arch/ia64/kernel/patch.c	2004-10-18 14:56:48 -07:00
+++ b/arch/ia64/kernel/patch.c	2004-10-18 14:56:48 -07:00
@@ -65,21 +65,21 @@
 ia64_patch_imm64 (u64 insn_addr, u64 val)
 {
 	ia64_patch(insn_addr,
-		   0x01fffefe000, (  ((val & 0x8000000000000000) >> 27) /* bit 63 -> 36 */
-				   | ((val & 0x0000000000200000) <<  0) /* bit 21 -> 21 */
-				   | ((val & 0x00000000001f0000) <<  6) /* bit 16 -> 22 */
-				   | ((val & 0x000000000000ff80) << 20) /* bit  7 -> 27 */
-				   | ((val & 0x000000000000007f) << 13) /* bit  0 -> 13 */));
-	ia64_patch(insn_addr - 1, 0x1ffffffffff, val >> 22);
+		   0x01fffefe000UL, (  ((val & 0x8000000000000000UL) >> 27) /* bit 63 -> 36 */
+				     | ((val & 0x0000000000200000UL) <<  0) /* bit 21 -> 21 */
+				     | ((val & 0x00000000001f0000UL) <<  6) /* bit 16 -> 22 */
+				     | ((val & 0x000000000000ff80UL) << 20) /* bit  7 -> 27 */
+				     | ((val & 0x000000000000007fUL) << 13) /* bit  0 -> 13 */));
+	ia64_patch(insn_addr - 1, 0x1ffffffffffUL, val >> 22);
 }
 
 void
 ia64_patch_imm60 (u64 insn_addr, u64 val)
 {
 	ia64_patch(insn_addr,
-		   0x011ffffe000, (  ((val & 0x0800000000000000) >> 23) /* bit 59 -> 36 */
-				   | ((val & 0x00000000000fffff) << 13) /* bit  0 -> 13 */));
-	ia64_patch(insn_addr - 1, 0x1fffffffffc, val >> 18);
+		   0x011ffffe000UL, (  ((val & 0x0800000000000000UL) >> 23) /* bit 59 -> 36 */
+				     | ((val & 0x00000000000fffffUL) << 13) /* bit  0 -> 13 */));
+	ia64_patch(insn_addr - 1, 0x1fffffffffcUL, val >> 18);
 }
 
 /*
@@ -130,10 +130,10 @@
 
 	while (offp < (s32 *) end) {
 		wp = (u64 *) ia64_imva((char *) offp + *offp);
-		wp[0] = 0x0000000100000000; /* nop.m 0; nop.i 0; nop.i 0 */
-		wp[1] = 0x0004000000000200;
-		wp[2] = 0x0000000100000011; /* nop.m 0; nop.i 0; br.ret.sptk.many b6 */
-		wp[3] = 0x0084006880000200;
+		wp[0] = 0x0000000100000000UL; /* nop.m 0; nop.i 0; nop.i 0 */
+		wp[1] = 0x0004000000000200UL;
+		wp[2] = 0x0000000100000011UL; /* nop.m 0; nop.i 0; br.ret.sptk.many b6 */
+		wp[3] = 0x0084006880000200UL;
 		ia64_fc(wp); ia64_fc(wp + 2);
 		++offp;
 	}
diff -Nru a/arch/ia64/kernel/perfmon.c b/arch/ia64/kernel/perfmon.c
--- a/arch/ia64/kernel/perfmon.c	2004-10-18 14:57:04 -07:00
+++ b/arch/ia64/kernel/perfmon.c	2004-10-18 14:57:04 -07:00
@@ -1513,7 +1513,7 @@
 }
 
 static ssize_t
-pfm_read(struct file *filp, char *buf, size_t size, loff_t *ppos)
+pfm_read(struct file *filp, char __user *buf, size_t size, loff_t *ppos)
 {
 	pfm_context_t *ctx;
 	pfm_msg_t *msg;
@@ -1606,7 +1606,7 @@
 }
 
 static ssize_t
-pfm_write(struct file *file, const char *ubuf,
+pfm_write(struct file *file, const char __user *ubuf,
 			  size_t size, loff_t *ppos)
 {
 	DPRINT(("pfm_write called\n"));
@@ -1678,7 +1678,6 @@
 pfm_fasync(int fd, struct file *filp, int on)
 {
 	pfm_context_t *ctx;
-	unsigned long flags;
 	int ret;
 
 	if (PFM_IS_FILE(filp) == 0) {
@@ -1691,19 +1690,21 @@
 		printk(KERN_ERR "perfmon: pfm_fasync NULL ctx [%d]\n", current->pid);
 		return -EBADF;
 	}
-
-
-	PROTECT_CTX(ctx, flags);
-
+	/*
+	 * we cannot mask interrupts during this call because this may
+	 * may go to sleep if memory is not readily avalaible.
+	 *
+	 * We are protected from the conetxt disappearing by the get_fd()/put_fd()
+	 * done in caller. Serialization of this function is ensured by caller.
+	 */
 	ret = pfm_do_fasync(fd, filp, ctx, on);
 
+
 	DPRINT(("pfm_fasync called on ctx_fd=%d on=%d async_queue=%p ret=%d\n",
 		fd,
 		on,
 		ctx->ctx_async_queue, ret));
 
-	UNPROTECT_CTX(ctx, flags);
-
 	return ret;
 }
 
@@ -2227,6 +2228,15 @@
 static void
 pfm_free_fd(int fd, struct file *file)
 {
+	struct files_struct *files = current->files;
+
+	/* 
+	 * there ie no fd_uninstall(), so we do it here
+	 */
+	spin_lock(&files->file_lock);
+        files->fd[fd] = NULL;
+	spin_unlock(&files->file_lock);
+
 	if (file) put_filp(file);
 	put_unused_fd(fd);
 }
@@ -2277,7 +2287,7 @@
 	 * if ((mm->total_vm << PAGE_SHIFT) + len> task->rlim[RLIMIT_AS].rlim_cur)
 	 * 	return -ENOMEM;
 	 */
-	if (size > task->rlim[RLIMIT_MEMLOCK].rlim_cur) return -EAGAIN;
+	if (size > task->rlim[RLIMIT_MEMLOCK].rlim_cur) return -ENOMEM;
 
 	/*
 	 * We do the easy to undo allocations first.
@@ -2352,7 +2362,7 @@
 	insert_vm_struct(mm, vma);
 
 	mm->total_vm  += size >> PAGE_SHIFT;
-
+	vm_stat_account(vma);
 	up_write(&task->mm->mmap_sem);
 
 	/*
@@ -2592,7 +2602,7 @@
 	 */
 	if (task == current) return 0;
 
-	if (task->state != TASK_STOPPED) {
+	if ((task->state != TASK_STOPPED) && (task->state != TASK_TRACED)) {
 		DPRINT(("cannot attach to non-stopped task [%d] state=%ld\n", task->pid, task->state));
 		return -EBUSY;
 	}
@@ -2659,8 +2669,10 @@
 	ctx = pfm_context_alloc();
 	if (!ctx) goto error;
 
-	req->ctx_fd = ctx->ctx_fd = pfm_alloc_fd(&filp);
-	if (req->ctx_fd < 0) goto error_file;
+	ret = pfm_alloc_fd(&filp);
+	if (ret < 0) goto error_file;
+
+	req->ctx_fd = ctx->ctx_fd = ret;
 
 	/*
 	 * attach context to file
@@ -3985,7 +3997,10 @@
 	state     = ctx->ctx_state;
 	is_system = ctx->ctx_fl_system;
 
-	if (state != PFM_CTX_LOADED && state != PFM_CTX_MASKED) return -EINVAL;
+	/*
+	 * context must be attached to issue the stop command (includes LOADED,MASKED,ZOMBIE)
+	 */
+	if (state == PFM_CTX_UNLOADED) return -EINVAL;
 
 	/*
  	 * In system wide and when the context is loaded, access can only happen
@@ -4741,7 +4756,7 @@
 	 * the task must be stopped.
 	 */
 	if (PFM_CMD_STOPPED(cmd)) {
-		if (task->state != TASK_STOPPED) {
+		if ((task->state != TASK_STOPPED) && (task->state != TASK_TRACED)) {
 			DPRINT(("[%d] task not in stopped state\n", task->pid));
 			return -EBUSY;
 		}
@@ -4782,7 +4797,7 @@
  * system-call entry point (must return long)
  */
 asmlinkage long
-sys_perfmonctl (int fd, int cmd, void *arg, int count, long arg5, long arg6, long arg7,
+sys_perfmonctl (int fd, int cmd, void __user *arg, int count, long arg5, long arg6, long arg7,
 		long arg8, long stack)
 {
 	struct pt_regs *regs = (struct pt_regs *)&stack;
@@ -6312,15 +6327,15 @@
 	 */
 	is_self = ctx->ctx_task == task ? 1 : 0;
 
-#ifdef CONFIG_SMP
-	if (task == current) {
-#else
 	/*
-	 * in UP, the state can still be in the registers
+	 * can access PMU is task is the owner of the PMU state on the current CPU
+	 * or if we are running on the CPU bound to the context in system-wide mode
+	 * (that is not necessarily the task the context is attached to in this mode).
+	 * In system-wide we always have can_access_pmu true because a task running on an
+	 * invalid processor is flagged earlier in the call stack (see pfm_stop).
 	 */
-	if (task == current || GET_PMU_OWNER() == task) {
-#endif
-		can_access_pmu = 1;
+	can_access_pmu = (GET_PMU_OWNER() == task) || (ctx->ctx_fl_system && ctx->ctx_cpu == smp_processor_id());
+	if (can_access_pmu) {
 		/*
 		 * Mark the PMU as not owned
 		 * This will cause the interrupt handler to do nothing in case an overflow
@@ -6330,6 +6345,7 @@
 		 * on.
 		 */
 		SET_PMU_OWNER(NULL, NULL);
+		DPRINT(("releasing ownership\n"));
 
 		/*
 		 * read current overflow status:
diff -Nru a/arch/ia64/kernel/process.c b/arch/ia64/kernel/process.c
--- a/arch/ia64/kernel/process.c	2004-10-18 14:56:29 -07:00
+++ b/arch/ia64/kernel/process.c	2004-10-18 14:56:29 -07:00
@@ -74,12 +74,12 @@
 show_stack (struct task_struct *task, unsigned long *sp)
 {
 	if (!task)
-		unw_init_running(ia64_do_show_stack, 0);
+		unw_init_running(ia64_do_show_stack, NULL);
 	else {
 		struct unw_frame_info info;
 
 		unw_init_from_blocked_task(&info, task);
-		ia64_do_show_stack(&info, 0);
+		ia64_do_show_stack(&info, NULL);
 	}
 }
 
@@ -138,7 +138,7 @@
 		ndirty = (regs->loadrs >> 19);
 		bsp = ia64_rse_skip_regs((unsigned long *) regs->ar_bspstore, ndirty);
 		for (i = 0; i < sof; ++i) {
-			get_user(val, ia64_rse_skip_regs(bsp, i));
+			get_user(val, (unsigned long __user *) ia64_rse_skip_regs(bsp, i));
 			printk("r%-3u:%c%016lx%s", 32 + i, is_nat ? '*' : ' ', val,
 			       ((i == sof - 1) || (i % 3) == 2) ? "\n" : " ");
 		}
@@ -228,18 +228,26 @@
 
 	/* endless idle loop with no priority at all */
 	while (1) {
-		void (*idle)(void) = pm_idle;
-		if (!idle)
-			idle = default_idle;
-
 #ifdef CONFIG_SMP
 		if (!need_resched())
 			min_xtp();
 #endif
 		while (!need_resched()) {
+			void (*idle)(void);
+
 			if (mark_idle)
 				(*mark_idle)(1);
+			/*
+			 * Mark this as an RCU critical section so that
+			 * synchronize_kernel() in the unload path waits
+			 * for our completion.
+			 */
+			rcu_read_lock();
+			idle = pm_idle;
+			if (!idle)
+				idle = default_idle;
 			(*idle)();
+			rcu_read_unlock();
 		}
 
 		if (mark_idle)
@@ -602,16 +610,18 @@
 }
 
 asmlinkage long
-sys_execve (char *filename, char **argv, char **envp, struct pt_regs *regs)
+sys_execve (char __user *filename, char __user * __user *argv, char __user * __user *envp,
+	    struct pt_regs *regs)
 {
+	char *fname;
 	int error;
 
-	filename = getname(filename);
-	error = PTR_ERR(filename);
-	if (IS_ERR(filename))
+	fname = getname(filename);
+	error = PTR_ERR(fname);
+	if (IS_ERR(fname))
 		goto out;
-	error = do_execve(filename, argv, envp, regs);
-	putname(filename);
+	error = do_execve(fname, argv, envp, regs);
+	putname(fname);
 out:
 	return error;
 }
@@ -743,7 +753,7 @@
 void
 machine_restart (char *restart_cmd)
 {
-	(*efi.reset_system)(EFI_RESET_WARM, 0, 0, 0);
+	(*efi.reset_system)(EFI_RESET_WARM, 0, 0, NULL);
 }
 
 EXPORT_SYMBOL(machine_restart);
diff -Nru a/arch/ia64/kernel/ptrace.c b/arch/ia64/kernel/ptrace.c
--- a/arch/ia64/kernel/ptrace.c	2004-10-18 14:57:04 -07:00
+++ b/arch/ia64/kernel/ptrace.c	2004-10-18 14:57:04 -07:00
@@ -152,7 +152,7 @@
 		ri = 0;
 		regs->cr_iip += 16;
 	} else if (ri == 2) {
-		get_user(w0, (char *) regs->cr_iip + 0);
+		get_user(w0, (char __user *) regs->cr_iip + 0);
 		if (((w0 >> 1) & 0xf) == IA64_MLX_TEMPLATE) {
 			/*
 			 * rfi'ing to slot 2 of an MLX bundle causes
@@ -174,7 +174,7 @@
 	if (ia64_psr(regs)->ri == 0) {
 		regs->cr_iip -= 16;
 		ri = 2;
-		get_user(w0, (char *) regs->cr_iip + 0);
+		get_user(w0, (char __user *) regs->cr_iip + 0);
 		if (((w0 >> 1) & 0xf) == IA64_MLX_TEMPLATE) {
 			/*
 			 * rfi'ing to slot 2 of an MLX bundle causes
@@ -833,7 +833,7 @@
 		      case PT_CFM:
 			urbs_end = ia64_get_user_rbs_end(child, pt, &cfm);
 			if (write_access) {
-				if (((cfm ^ *data) & 0x3fffffffffU) != 0) {
+				if (((cfm ^ *data) & 0x3fffffffffUL) != 0) {
 					if (ia64_sync_user_rbs(child, sw,
 							       pt->ar_bspstore, urbs_end) < 0)
 						return -1;
@@ -997,12 +997,14 @@
 }
 
 static long
-ptrace_getregs (struct task_struct *child, struct pt_all_user_regs *ppr)
+ptrace_getregs (struct task_struct *child, struct pt_all_user_regs __user *ppr)
 {
+	unsigned long psr, ec, lc, rnat, bsp, cfm, nat_bits, val;
+	struct unw_frame_info info;
+	struct ia64_fpreg fpval;
 	struct switch_stack *sw;
 	struct pt_regs *pt;
 	long ret, retval;
-	struct unw_frame_info info;
 	char nat = 0;
 	int i;
 
@@ -1023,12 +1025,21 @@
 		return -EIO;
 	}
 
+	if (access_uarea(child, PT_CR_IPSR, &psr, 0) < 0
+	    || access_uarea(child, PT_AR_EC, &ec, 0) < 0
+	    || access_uarea(child, PT_AR_LC, &lc, 0) < 0
+	    || access_uarea(child, PT_AR_RNAT, &rnat, 0) < 0
+	    || access_uarea(child, PT_AR_BSP, &bsp, 0) < 0
+	    || access_uarea(child, PT_CFM, &cfm, 0)
+	    || access_uarea(child, PT_NAT_BITS, &nat_bits, 0))
+		return -EIO;
+
 	retval = 0;
 
 	/* control regs */
 
 	retval |= __put_user(pt->cr_iip, &ppr->cr_iip);
-	retval |= access_uarea(child, PT_CR_IPSR, &ppr->cr_ipsr, 0);
+	retval |= __put_user(psr, &ppr->cr_ipsr);
 
 	/* app regs */
 
@@ -1039,11 +1050,11 @@
 	retval |= __put_user(pt->ar_ccv, &ppr->ar[PT_AUR_CCV]);
 	retval |= __put_user(pt->ar_fpsr, &ppr->ar[PT_AUR_FPSR]);
 
-	retval |= access_uarea(child, PT_AR_EC, &ppr->ar[PT_AUR_EC], 0);
-	retval |= access_uarea(child, PT_AR_LC, &ppr->ar[PT_AUR_LC], 0);
-	retval |= access_uarea(child, PT_AR_RNAT, &ppr->ar[PT_AUR_RNAT], 0);
-	retval |= access_uarea(child, PT_AR_BSP, &ppr->ar[PT_AUR_BSP], 0);
-	retval |= access_uarea(child, PT_CFM, &ppr->cfm, 0);
+	retval |= __put_user(ec, &ppr->ar[PT_AUR_EC]);
+	retval |= __put_user(lc, &ppr->ar[PT_AUR_LC]);
+	retval |= __put_user(rnat, &ppr->ar[PT_AUR_RNAT]);
+	retval |= __put_user(bsp, &ppr->ar[PT_AUR_BSP]);
+	retval |= __put_user(cfm, &ppr->cfm);
 
 	/* gr1-gr3 */
 
@@ -1053,7 +1064,9 @@
 	/* gr4-gr7 */
 
 	for (i = 4; i < 8; i++) {
-		retval |= unw_access_gr(&info, i, &ppr->gr[i], &nat, 0);
+		if (unw_access_gr(&info, i, &val, &nat, 0) < 0)
+			return -EIO;
+		retval |= __put_user(val, &ppr->gr[i]);
 	}
 
 	/* gr8-gr11 */
@@ -1077,7 +1090,9 @@
 	/* b1-b5 */
 
 	for (i = 1; i < 6; i++) {
-		retval |= unw_access_br(&info, i, &ppr->br[i], 0);
+		if (unw_access_br(&info, i, &val, 0) < 0)
+			return -EIO;
+		__put_user(val, &ppr->br[i]);
 	}
 
 	/* b6-b7 */
@@ -1088,8 +1103,9 @@
 	/* fr2-fr5 */
 
 	for (i = 2; i < 6; i++) {
-		retval |= access_fr(&info, i, 0, (unsigned long *) &ppr->fr[i], 0);
-		retval |= access_fr(&info, i, 1, (unsigned long *) &ppr->fr[i] + 1, 0);
+		if (unw_get_fr(&info, i, &fpval) < 0)
+			return -EIO;
+		retval |= __copy_to_user(&ppr->fr[i], &fpval, sizeof (fpval));
 	}
 
 	/* fr6-fr11 */
@@ -1103,8 +1119,9 @@
 	/* fr16-fr31 */
 
 	for (i = 16; i < 32; i++) {
-		retval |= access_fr(&info, i, 0, (unsigned long *) &ppr->fr[i], 0);
-		retval |= access_fr(&info, i, 1, (unsigned long *) &ppr->fr[i] + 1, 0);
+		if (unw_get_fr(&info, i, &fpval) < 0)
+			return -EIO;
+		retval |= __copy_to_user(&ppr->fr[i], &fpval, sizeof (fpval));
 	}
 
 	/* fph */
@@ -1118,22 +1135,25 @@
 
 	/* nat bits */
 
-	retval |= access_uarea(child, PT_NAT_BITS, &ppr->nat, 0);
+	retval |= __put_user(nat_bits, &ppr->nat);
 
 	ret = retval ? -EIO : 0;
 	return ret;
 }
 
 static long
-ptrace_setregs (struct task_struct *child, struct pt_all_user_regs *ppr)
+ptrace_setregs (struct task_struct *child, struct pt_all_user_regs __user *ppr)
 {
+	unsigned long psr, ec, lc, rnat, bsp, cfm, nat_bits, val = 0;
+	struct unw_frame_info info;
 	struct switch_stack *sw;
+	struct ia64_fpreg fpval;
 	struct pt_regs *pt;
 	long ret, retval;
-	struct unw_frame_info info;
-	char nat = 0;
 	int i;
 
+	memset(&fpval, 0, sizeof(fpval));
+
 	retval = verify_area(VERIFY_READ, ppr, sizeof(struct pt_all_user_regs));
 	if (retval != 0) {
 		return -EIO;
@@ -1156,7 +1176,7 @@
 	/* control regs */
 
 	retval |= __get_user(pt->cr_iip, &ppr->cr_iip);
-	retval |= access_uarea(child, PT_CR_IPSR, &ppr->cr_ipsr, 1);
+	retval |= __get_user(psr, &ppr->cr_ipsr);
 
 	/* app regs */
 
@@ -1167,11 +1187,11 @@
 	retval |= __get_user(pt->ar_ccv, &ppr->ar[PT_AUR_CCV]);
 	retval |= __get_user(pt->ar_fpsr, &ppr->ar[PT_AUR_FPSR]);
 
-	retval |= access_uarea(child, PT_AR_EC, &ppr->ar[PT_AUR_EC], 1);
-	retval |= access_uarea(child, PT_AR_LC, &ppr->ar[PT_AUR_LC], 1);
-	retval |= access_uarea(child, PT_AR_RNAT, &ppr->ar[PT_AUR_RNAT], 1);
-	retval |= access_uarea(child, PT_AR_BSP, &ppr->ar[PT_AUR_BSP], 1);
-	retval |= access_uarea(child, PT_CFM, &ppr->cfm, 1);
+	retval |= __get_user(ec, &ppr->ar[PT_AUR_EC]);
+	retval |= __get_user(lc, &ppr->ar[PT_AUR_LC]);
+	retval |= __get_user(rnat, &ppr->ar[PT_AUR_RNAT]);
+	retval |= __get_user(bsp, &ppr->ar[PT_AUR_BSP]);
+	retval |= __get_user(cfm, &ppr->cfm);
 
 	/* gr1-gr3 */
 
@@ -1181,11 +1201,9 @@
 	/* gr4-gr7 */
 
 	for (i = 4; i < 8; i++) {
-		long ret = unw_get_gr(&info, i, &ppr->gr[i], &nat);
-		if (ret < 0) {
-			return ret;
-		}
-		retval |= unw_access_gr(&info, i, &ppr->gr[i], &nat, 1);
+		retval |= __get_user(val, &ppr->gr[i]);
+		if (unw_set_gr(&info, i, val, 0) < 0)	 /* NaT bit will be set via PT_NAT_BITS */
+			return -EIO;
 	}
 
 	/* gr8-gr11 */
@@ -1209,7 +1227,8 @@
 	/* b1-b5 */
 
 	for (i = 1; i < 6; i++) {
-		retval |= unw_access_br(&info, i, &ppr->br[i], 1);
+		retval |= __get_user(val, &ppr->br[i]);
+		unw_set_br(&info, i, val);
 	}
 
 	/* b6-b7 */
@@ -1220,8 +1239,9 @@
 	/* fr2-fr5 */
 
 	for (i = 2; i < 6; i++) {
-		retval |= access_fr(&info, i, 0, (unsigned long *) &ppr->fr[i], 1);
-		retval |= access_fr(&info, i, 1, (unsigned long *) &ppr->fr[i] + 1, 1);
+		retval |= __copy_from_user(&fpval, &ppr->fr[i], sizeof(fpval));
+		if (unw_set_fr(&info, i, fpval) < 0)
+			return -EIO;
 	}
 
 	/* fr6-fr11 */
@@ -1235,8 +1255,9 @@
 	/* fr16-fr31 */
 
 	for (i = 16; i < 32; i++) {
-		retval |= access_fr(&info, i, 0, (unsigned long *) &ppr->fr[i], 1);
-		retval |= access_fr(&info, i, 1, (unsigned long *) &ppr->fr[i] + 1, 1);
+		retval |= __copy_from_user(&fpval, &ppr->fr[i], sizeof(fpval));
+		if (unw_set_fr(&info, i, fpval) < 0)
+			return -EIO;
 	}
 
 	/* fph */
@@ -1250,7 +1271,15 @@
 
 	/* nat bits */
 
-	retval |= access_uarea(child, PT_NAT_BITS, &ppr->nat, 1);
+	retval |= __get_user(nat_bits, &ppr->nat);
+
+	retval |= access_uarea(child, PT_CR_IPSR, &psr, 1);
+	retval |= access_uarea(child, PT_AR_EC, &ec, 1);
+	retval |= access_uarea(child, PT_AR_LC, &lc, 1);
+	retval |= access_uarea(child, PT_AR_RNAT, &rnat, 1);
+	retval |= access_uarea(child, PT_AR_BSP, &bsp, 1);
+	retval |= access_uarea(child, PT_CFM, &cfm, 1);
+	retval |= access_uarea(child, PT_NAT_BITS, &nat_bits, 1);
 
 	ret = retval ? -EIO : 0;
 	return ret;
@@ -1429,11 +1458,11 @@
 		goto out_tsk;
 
 	      case PTRACE_GETREGS:
-		ret = ptrace_getregs(child, (struct pt_all_user_regs*) data);
+		ret = ptrace_getregs(child, (struct pt_all_user_regs __user *) data);
 		goto out_tsk;
 
 	      case PTRACE_SETREGS:
-		ret = ptrace_setregs(child, (struct pt_all_user_regs*) data);
+		ret = ptrace_setregs(child, (struct pt_all_user_regs __user *) data);
 		goto out_tsk;
 
 	      default:
diff -Nru a/arch/ia64/kernel/sal.c b/arch/ia64/kernel/sal.c
--- a/arch/ia64/kernel/sal.c	2004-10-18 14:57:04 -07:00
+++ b/arch/ia64/kernel/sal.c	2004-10-18 14:57:04 -07:00
@@ -10,6 +10,7 @@
 
 #include <linux/kernel.h>
 #include <linux/init.h>
+#include <linux/module.h>
 #include <linux/spinlock.h>
 #include <linux/string.h>
 
@@ -262,3 +263,40 @@
 		p += SAL_DESC_SIZE(*p);
 	}
 }
+
+int
+ia64_sal_oemcall(struct ia64_sal_retval *isrvp, u64 oemfunc, u64 arg1,
+		 u64 arg2, u64 arg3, u64 arg4, u64 arg5, u64 arg6, u64 arg7)
+{
+	if (oemfunc < IA64_SAL_OEMFUNC_MIN || oemfunc > IA64_SAL_OEMFUNC_MAX)
+		return -1;
+	SAL_CALL(*isrvp, oemfunc, arg1, arg2, arg3, arg4, arg5, arg6, arg7);
+	return 0;
+}
+EXPORT_SYMBOL(ia64_sal_oemcall);
+
+int
+ia64_sal_oemcall_nolock(struct ia64_sal_retval *isrvp, u64 oemfunc, u64 arg1,
+			u64 arg2, u64 arg3, u64 arg4, u64 arg5, u64 arg6,
+			u64 arg7)
+{
+	if (oemfunc < IA64_SAL_OEMFUNC_MIN || oemfunc > IA64_SAL_OEMFUNC_MAX)
+		return -1;
+	SAL_CALL_NOLOCK(*isrvp, oemfunc, arg1, arg2, arg3, arg4, arg5, arg6,
+			arg7);
+	return 0;
+}
+EXPORT_SYMBOL(ia64_sal_oemcall_nolock);
+
+int
+ia64_sal_oemcall_reentrant(struct ia64_sal_retval *isrvp, u64 oemfunc,
+			   u64 arg1, u64 arg2, u64 arg3, u64 arg4, u64 arg5,
+			   u64 arg6, u64 arg7)
+{
+	if (oemfunc < IA64_SAL_OEMFUNC_MIN || oemfunc > IA64_SAL_OEMFUNC_MAX)
+		return -1;
+	SAL_CALL_REENTRANT(*isrvp, oemfunc, arg1, arg2, arg3, arg4, arg5, arg6,
+			   arg7);
+	return 0;
+}
+EXPORT_SYMBOL(ia64_sal_oemcall_reentrant);
diff -Nru a/arch/ia64/kernel/salinfo.c b/arch/ia64/kernel/salinfo.c
--- a/arch/ia64/kernel/salinfo.c	2004-10-18 14:56:48 -07:00
+++ b/arch/ia64/kernel/salinfo.c	2004-10-18 14:56:48 -07:00
@@ -268,7 +268,7 @@
 }
 
 static ssize_t
-salinfo_event_read(struct file *file, char *buffer, size_t count, loff_t *ppos)
+salinfo_event_read(struct file *file, char __user *buffer, size_t count, loff_t *ppos)
 {
 	struct inode *inode = file->f_dentry->d_inode;
 	struct proc_dir_entry *entry = PDE(inode);
@@ -417,11 +417,16 @@
 
 	if (!data->saved_num)
 		call_on_cpu(cpu, salinfo_log_read_cpu, data);
-	data->state = data->log_size ? STATE_LOG_RECORD : STATE_NO_DATA;
+	if (!data->log_size) {
+	        data->state = STATE_NO_DATA;
+	        clear_bit(cpu, &data->cpu_event);
+	} else {
+	        data->state = STATE_LOG_RECORD;
+	}
 }
 
 static ssize_t
-salinfo_log_read(struct file *file, char *buffer, size_t count, loff_t *ppos)
+salinfo_log_read(struct file *file, char __user *buffer, size_t count, loff_t *ppos)
 {
 	struct inode *inode = file->f_dentry->d_inode;
 	struct proc_dir_entry *entry = PDE(inode);
@@ -478,7 +483,7 @@
 }
 
 static ssize_t
-salinfo_log_write(struct file *file, const char *buffer, size_t count, loff_t *ppos)
+salinfo_log_write(struct file *file, const char __user *buffer, size_t count, loff_t *ppos)
 {
 	struct inode *inode = file->f_dentry->d_inode;
 	struct proc_dir_entry *entry = PDE(inode);
diff -Nru a/arch/ia64/kernel/setup.c b/arch/ia64/kernel/setup.c
--- a/arch/ia64/kernel/setup.c	2004-10-18 14:55:55 -07:00
+++ b/arch/ia64/kernel/setup.c	2004-10-18 14:55:55 -07:00
@@ -680,7 +680,7 @@
 			break;
 	}
 
-	if (ia64_pal_rse_info(&num_phys_stacked, 0) != 0) {
+	if (ia64_pal_rse_info(&num_phys_stacked, NULL) != 0) {
 		printk(KERN_WARNING "cpu_init: PAL RSE info failed; assuming 96 physical "
 		       "stacked regs\n");
 		num_phys_stacked = 96;
diff -Nru a/arch/ia64/kernel/sigframe.h b/arch/ia64/kernel/sigframe.h
--- a/arch/ia64/kernel/sigframe.h	2004-10-18 14:56:49 -07:00
+++ b/arch/ia64/kernel/sigframe.h	2004-10-18 14:56:49 -07:00
@@ -17,7 +17,7 @@
 	 * End of architected state.
 	 */
 
-	void *handler;			/* pointer to the plabel of the signal handler */
+	void __user *handler;		/* pointer to the plabel of the signal handler */
 	struct siginfo info;
 	struct sigcontext sc;
 };
diff -Nru a/arch/ia64/kernel/signal.c b/arch/ia64/kernel/signal.c
--- a/arch/ia64/kernel/signal.c	2004-10-18 14:56:33 -07:00
+++ b/arch/ia64/kernel/signal.c	2004-10-18 14:56:33 -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.
@@ -43,7 +43,7 @@
 #endif
 
 long
-ia64_rt_sigsuspend (sigset_t *uset, size_t sigsetsize, struct sigscratch *scr)
+ia64_rt_sigsuspend (sigset_t __user *uset, size_t sigsetsize, struct sigscratch *scr)
 {
 	sigset_t oldset, set;
 
@@ -84,7 +84,7 @@
 }
 
 asmlinkage long
-sys_sigaltstack (const stack_t *uss, stack_t *uoss, long arg2, long arg3, long arg4,
+sys_sigaltstack (const stack_t __user *uss, stack_t __user *uoss, long arg2, long arg3, long arg4,
 		 long arg5, long arg6, long arg7, long stack)
 {
 	struct pt_regs *pt = (struct pt_regs *) &stack;
@@ -93,7 +93,7 @@
 }
 
 static long
-restore_sigcontext (struct sigcontext *sc, struct sigscratch *scr)
+restore_sigcontext (struct sigcontext __user *sc, struct sigscratch *scr)
 {
 	unsigned long ip, flags, nat, um, cfm;
 	long err;
@@ -155,7 +155,7 @@
 }
 
 int
-copy_siginfo_to_user (siginfo_t *to, siginfo_t *from)
+copy_siginfo_to_user (siginfo_t __user *to, siginfo_t *from)
 {
 	if (!access_ok(VERIFY_WRITE, to, sizeof(siginfo_t)))
 		return -EFAULT;
@@ -211,12 +211,12 @@
 ia64_rt_sigreturn (struct sigscratch *scr)
 {
 	extern char ia64_strace_leave_kernel, ia64_leave_kernel;
-	struct sigcontext *sc;
+	struct sigcontext __user *sc;
 	struct siginfo si;
 	sigset_t set;
 	long retval;
 
-	sc = &((struct sigframe *) (scr->pt.r12 + 16))->sc;
+	sc = &((struct sigframe __user *) (scr->pt.r12 + 16))->sc;
 
 	/*
 	 * When we return to the previously executing context, r8 and r10 have already
@@ -260,7 +260,7 @@
 	 * It is more difficult to avoid calling this function than to
 	 * call it and ignore errors.
 	 */
-	do_sigaltstack(&sc->sc_stack, 0, scr->pt.r12);
+	do_sigaltstack(&sc->sc_stack, NULL, scr->pt.r12);
 	return retval;
 
   give_sigsegv:
@@ -281,7 +281,7 @@
  * trampoline starts.  Everything else is done at the user-level.
  */
 static long
-setup_sigcontext (struct sigcontext *sc, sigset_t *mask, struct sigscratch *scr)
+setup_sigcontext (struct sigcontext __user *sc, sigset_t *mask, struct sigscratch *scr)
 {
 	unsigned long flags = 0, ifs, cfm, nat;
 	long err;
@@ -335,7 +335,7 @@
 		err |= __put_user(scr->pt.ar_ccv, &sc->sc_ar_ccv);		/* ar.ccv */
 		err |= __put_user(scr->pt.b7, &sc->sc_br[7]);			/* b7 */
 		err |= __put_user(scr->pt.r14, &sc->sc_gr[14]);			/* r14 */
-		err |= __copy_to_user(&scr->pt.ar_csd, &sc->sc_ar25, 2*8); /* ar.csd & ar.ssd */
+		err |= __copy_to_user(&sc->sc_ar25, &scr->pt.ar_csd, 2*8); /* ar.csd & ar.ssd */
 		err |= __copy_to_user(&sc->sc_gr[2], &scr->pt.r2, 2*8);		/* r2-r3 */
 		err |= __copy_to_user(&sc->sc_gr[16], &scr->pt.r16, 16*8);	/* r16-r31 */
 	}
@@ -352,20 +352,49 @@
 }
 
 static long
+force_sigsegv_info (int sig, void __user *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;
+	struct sigframe __user *frame;
 	long err;
 
-	frame = (void *) scr->pt.r12;
+	frame = (void __user *) scr->pt.r12;
 	tramp_addr = (unsigned long) __kernel_sigtramp;
 	if ((ka->sa.sa_flags & SA_ONSTACK) && sas_ss_flags((unsigned long) frame) == 0) {
-		frame = (void *) ((current->sas_ss_sp + current->sas_ss_size)
-				  & ~(STACK_ALIGN - 1));
+		frame = (void __user *) ((current->sas_ss_sp + current->sas_ss_size)
+					 & ~(STACK_ALIGN - 1));
 		/*
 		 * We need to check for the register stack being on the signal stack
 		 * separately, because it's switched separately (memory stack is switched
@@ -374,10 +403,10 @@
 		if (!rbs_on_sig_stack(scr->pt.ar_bspstore))
 			new_rbs = (current->sas_ss_sp + sizeof(long) - 1) & ~(sizeof(long) - 1);
 	}
-	frame = (void *) frame - ((sizeof(*frame) + STACK_ALIGN - 1) & ~(STACK_ALIGN - 1));
+	frame = (void __user *) 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/smp.c b/arch/ia64/kernel/smp.c
--- a/arch/ia64/kernel/smp.c	2004-10-18 14:57:04 -07:00
+++ b/arch/ia64/kernel/smp.c	2004-10-18 14:57:04 -07:00
@@ -225,7 +225,7 @@
 void
 smp_flush_tlb_all (void)
 {
-	on_each_cpu((void (*)(void *))local_flush_tlb_all, 0, 1, 1);
+	on_each_cpu((void (*)(void *))local_flush_tlb_all, NULL, 1, 1);
 }
 EXPORT_SYMBOL(smp_flush_tlb_all);
 
diff -Nru a/arch/ia64/kernel/smpboot.c b/arch/ia64/kernel/smpboot.c
--- a/arch/ia64/kernel/smpboot.c	2004-10-18 14:56:20 -07:00
+++ b/arch/ia64/kernel/smpboot.c	2004-10-18 14:56:20 -07:00
@@ -356,19 +356,15 @@
 	return cpu_idle();
 }
 
-static struct task_struct * __devinit
-fork_by_hand (void)
+struct pt_regs * __devinit 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/sys_ia64.c b/arch/ia64/kernel/sys_ia64.c
--- a/arch/ia64/kernel/sys_ia64.c	2004-10-18 14:56:33 -07:00
+++ b/arch/ia64/kernel/sys_ia64.c	2004-10-18 14:56:33 -07:00
@@ -93,7 +93,7 @@
 }
 
 asmlinkage unsigned long
-ia64_shmat (int shmid, void *shmaddr, int shmflg)
+ia64_shmat (int shmid, void __user *shmaddr, int shmflg)
 {
 	unsigned long raddr;
 	int retval;
@@ -183,7 +183,7 @@
 do_mmap2 (unsigned long addr, unsigned long len, int prot, int flags, int fd, unsigned long pgoff)
 {
 	unsigned long roff;
-	struct file *file = 0;
+	struct file *file = NULL;
 
 	flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE);
 	if (!(flags & MAP_ANONYMOUS)) {
diff -Nru a/arch/ia64/kernel/time.c b/arch/ia64/kernel/time.c
--- a/arch/ia64/kernel/time.c	2004-10-18 14:56:17 -07:00
+++ b/arch/ia64/kernel/time.c	2004-10-18 14:56:17 -07:00
@@ -45,192 +45,7 @@
 
 #endif
 
-static void
-itc_reset (void)
-{
-}
-
-/*
- * Adjust for the fact that xtime has been advanced by delta_nsec (may be negative and/or
- * larger than NSEC_PER_SEC.
- */
-static void
-itc_update (long delta_nsec)
-{
-}
-
-/*
- * Return the number of nano-seconds that elapsed since the last
- * update to jiffy.  It is quite possible that the timer interrupt
- * will interrupt this and result in a race for any of jiffies,
- * wall_jiffies or itm_next.  Thus, the xtime_lock must be at least
- * read synchronised when calling this routine (see do_gettimeofday()
- * below for an example).
- */
-unsigned long
-itc_get_offset (void)
-{
-	unsigned long elapsed_cycles, lost = jiffies - wall_jiffies;
-	unsigned long now = ia64_get_itc(), last_tick;
-
-	last_tick = (cpu_data(TIME_KEEPER_ID)->itm_next
-		     - (lost + 1)*cpu_data(TIME_KEEPER_ID)->itm_delta);
-
-	elapsed_cycles = now - last_tick;
-	return (elapsed_cycles*local_cpu_data->nsec_per_cyc) >> IA64_NSEC_PER_CYC_SHIFT;
-}
-
-static struct time_interpolator itc_interpolator = {
-	.get_offset =	itc_get_offset,
-	.update =	itc_update,
-	.reset =	itc_reset
-};
-
-int
-do_settimeofday (struct timespec *tv)
-{
-	time_t wtm_sec, sec = tv->tv_sec;
-	long wtm_nsec, nsec = tv->tv_nsec;
-
-	if ((unsigned long)tv->tv_nsec >= NSEC_PER_SEC)
-		return -EINVAL;
-
-	write_seqlock_irq(&xtime_lock);
-	{
-		/*
-		 * This is revolting. We need to set "xtime" correctly. However, the value
-		 * in this location is the value at the most recent update of wall time.
-		 * Discover what correction gettimeofday would have done, and then undo
-		 * it!
-		 */
-		nsec -= time_interpolator_get_offset();
-
-		wtm_sec  = wall_to_monotonic.tv_sec + (xtime.tv_sec - sec);
-		wtm_nsec = wall_to_monotonic.tv_nsec + (xtime.tv_nsec - nsec);
-
-		set_normalized_timespec(&xtime, sec, nsec);
-		set_normalized_timespec(&wall_to_monotonic, wtm_sec, wtm_nsec);
-
-		time_adjust = 0;		/* stop active adjtime() */
-		time_status |= STA_UNSYNC;
-		time_maxerror = NTP_PHASE_LIMIT;
-		time_esterror = NTP_PHASE_LIMIT;
-		time_interpolator_reset();
-	}
-	write_sequnlock_irq(&xtime_lock);
-	clock_was_set();
-	return 0;
-}
-
-EXPORT_SYMBOL(do_settimeofday);
-
-void
-do_gettimeofday (struct timeval *tv)
-{
-	unsigned long seq, nsec, usec, sec, old, offset;
-
-	while (1) {
-		seq = read_seqbegin(&xtime_lock);
-		{
-			old = last_nsec_offset;
-			offset = time_interpolator_get_offset();
-			sec = xtime.tv_sec;
-			nsec = xtime.tv_nsec;
-		}
-		if (unlikely(read_seqretry(&xtime_lock, seq)))
-			continue;
-		/*
-		 * Ensure that for any pair of causally ordered gettimeofday() calls, time
-		 * never goes backwards (even when ITC on different CPUs are not perfectly
-		 * synchronized).  (A pair of concurrent calls to gettimeofday() is by
-		 * definition non-causal and hence it makes no sense to talk about
-		 * time-continuity for such calls.)
-		 *
-		 * Doing this in a lock-free and race-free manner is tricky.  Here is why
-		 * it works (most of the time): read_seqretry() just succeeded, which
-		 * implies we calculated a consistent (valid) value for "offset".  If the
-		 * cmpxchg() below succeeds, we further know that last_nsec_offset still
-		 * has the same value as at the beginning of the loop, so there was
-		 * presumably no timer-tick or other updates to last_nsec_offset in the
-		 * meantime.  This isn't 100% true though: there _is_ a possibility of a
-		 * timer-tick occurring right right after read_seqretry() and then getting
-		 * zero or more other readers which will set last_nsec_offset to the same
-		 * value as the one we read at the beginning of the loop.  If this
-		 * happens, we'll end up returning a slightly newer time than we ought to
-		 * (the jump forward is at most "offset" nano-seconds).  There is no
-		 * danger of causing time to go backwards, though, so we are safe in that
-		 * sense.  We could make the probability of this unlucky case occurring
-		 * arbitrarily small by encoding a version number in last_nsec_offset, but
-		 * even without versioning, the probability of this unlucky case should be
-		 * so small that we won't worry about it.
-		 */
-		if (offset <= old) {
-			offset = old;
-			break;
-		} else if (likely(cmpxchg(&last_nsec_offset, old, offset) == old))
-			break;
-
-		/* someone else beat us to updating last_nsec_offset; try again */
-	}
-
-	usec = (nsec + offset) / 1000;
-
-	while (unlikely(usec >= USEC_PER_SEC)) {
-		usec -= USEC_PER_SEC;
-		++sec;
-	}
-
-	tv->tv_sec = sec;
-	tv->tv_usec = usec;
-}
-
-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 struct time_interpolator itc_interpolator;
 
 static irqreturn_t
 timer_interrupt (int irq, void *dev_id, struct pt_regs *regs)
@@ -249,7 +64,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
@@ -323,6 +138,18 @@
 	ia64_set_itm(local_cpu_data->itm_next);
 }
 
+static int nojitter;
+
+static int __init nojitter_setup(char *str)
+{
+	nojitter = 1;
+	printk("Jitter checking for ITC timers disabled\n");
+	return 1;
+}
+
+__setup("nojitter", nojitter_setup);
+
+
 void __devinit
 ia64_init_itm (void)
 {
@@ -340,7 +167,7 @@
 	if (status != 0) {
 		printk(KERN_ERR "SAL_FREQ_BASE_PLATFORM failed: %s\n", ia64_sal_strerror(status));
 	} else {
-		status = ia64_pal_freq_ratios(&proc_ratio, 0, &itc_ratio);
+		status = ia64_pal_freq_ratios(&proc_ratio, NULL, &itc_ratio);
 		if (status != 0)
 			printk(KERN_ERR "PAL_FREQ_RATIOS failed with status=%ld\n", status);
 	}
@@ -371,7 +198,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,
@@ -385,7 +212,23 @@
 
 	if (!(sal_platform_features & IA64_SAL_PLATFORM_FEATURE_ITC_DRIFT)) {
 		itc_interpolator.frequency = local_cpu_data->itc_freq;
+		itc_interpolator.shift = 16;
 		itc_interpolator.drift = itc_drift;
+		itc_interpolator.source = TIME_SOURCE_CPU;
+#ifdef CONFIG_SMP
+		/* On IA64 in an SMP configuration ITCs are never accurately synchronized.
+		 * Jitter compensation requires a cmpxchg which may limit
+		 * the scalability of the syscalls for retrieving time.
+		 * The ITC synchronization is usually successful to within a few
+		 * ITC ticks but this is not a sure thing. If you need to improve
+		 * timer performance in SMP situations then boot the kernel with the
+		 * "nojitter" option. However, doing so may result in time fluctuating (maybe
+		 * even going backward) if the ITC offsets between the individual CPUs
+		 * are too large.
+		 */
+		if (!nojitter) itc_interpolator.jitter = 1;
+#endif
+		itc_interpolator.addr = NULL;
 		register_time_interpolator(&itc_interpolator);
 	}
 
diff -Nru a/arch/ia64/kernel/traps.c b/arch/ia64/kernel/traps.c
--- a/arch/ia64/kernel/traps.c	2004-10-18 14:57:04 -07:00
+++ b/arch/ia64/kernel/traps.c	2004-10-18 14:57:04 -07:00
@@ -14,9 +14,9 @@
 #include <linux/tty.h>
 #include <linux/vt_kern.h>		/* For unblank_screen() */
 #include <linux/module.h>       /* for EXPORT_SYMBOL */
+#include <linux/hardirq.h>
 
 #include <asm/fpswa.h>
-#include <asm/hardirq.h>
 #include <asm/ia32.h>
 #include <asm/intrinsics.h>
 #include <asm/processor.h>
@@ -112,7 +112,7 @@
 	int sig, code;
 
 	/* SIGILL, SIGFPE, SIGSEGV, and SIGBUS want these field initialized: */
-	siginfo.si_addr = (void *) (regs->cr_iip + ia64_psr(regs)->ri);
+	siginfo.si_addr = (void __user *) (regs->cr_iip + ia64_psr(regs)->ri);
 	siginfo.si_imm = break_num;
 	siginfo.si_flags = 0;		/* clear __ISR_VALID */
 	siginfo.si_isr = 0;
@@ -282,7 +282,7 @@
 	fault_ip = regs->cr_iip;
 	if (!fp_fault && (ia64_psr(regs)->ri == 0))
 		fault_ip -= 16;
-	if (copy_from_user(bundle, (void *) fault_ip, sizeof(bundle)))
+	if (copy_from_user(bundle, (void __user *) fault_ip, sizeof(bundle)))
 		return -1;
 
 	if (jiffies - last_time > 5*HZ)
@@ -312,7 +312,7 @@
 			siginfo.si_signo = SIGFPE;
 			siginfo.si_errno = 0;
 			siginfo.si_code = __SI_FAULT;	/* default code */
-			siginfo.si_addr = (void *) (regs->cr_iip + ia64_psr(regs)->ri);
+			siginfo.si_addr = (void __user *) (regs->cr_iip + ia64_psr(regs)->ri);
 			if (isr & 0x11) {
 				siginfo.si_code = FPE_FLTINV;
 			} else if (isr & 0x22) {
@@ -336,7 +336,7 @@
 			siginfo.si_signo = SIGFPE;
 			siginfo.si_errno = 0;
 			siginfo.si_code = __SI_FAULT;	/* default code */
-			siginfo.si_addr = (void *) (regs->cr_iip + ia64_psr(regs)->ri);
+			siginfo.si_addr = (void __user *) (regs->cr_iip + ia64_psr(regs)->ri);
 			if (isr & 0x880) {
 				siginfo.si_code = FPE_FLTOVF;
 			} else if (isr & 0x1100) {
@@ -383,7 +383,7 @@
 	memset(&si, 0, sizeof(si));
 	si.si_signo = SIGILL;
 	si.si_code = ILL_ILLOPC;
-	si.si_addr = (void *) (regs->cr_iip + ia64_psr(regs)->ri);
+	si.si_addr = (void __user *) (regs->cr_iip + ia64_psr(regs)->ri);
 	force_sig_info(SIGILL, &si, current);
 	rv.fkt = 0;
 	return rv;
@@ -445,18 +445,18 @@
 
 	      case 26: /* NaT Consumption */
 		if (user_mode(regs)) {
-			void *addr;
+			void __user *addr;
 
 			if (((isr >> 4) & 0xf) == 2) {
 				/* NaT page consumption */
 				sig = SIGSEGV;
 				code = SEGV_ACCERR;
-				addr = (void *) ifa;
+				addr = (void __user *) ifa;
 			} else {
 				/* register NaT consumption */
 				sig = SIGILL;
 				code = ILL_ILLOPN;
-				addr = (void *) (regs->cr_iip + ia64_psr(regs)->ri);
+				addr = (void __user *) (regs->cr_iip + ia64_psr(regs)->ri);
 			}
 			siginfo.si_signo = sig;
 			siginfo.si_code = code;
@@ -477,7 +477,7 @@
 			siginfo.si_signo = SIGILL;
 			siginfo.si_code = ILL_ILLOPN;
 			siginfo.si_errno = 0;
-			siginfo.si_addr = (void *) (regs->cr_iip + ia64_psr(regs)->ri);
+			siginfo.si_addr = (void __user *) (regs->cr_iip + ia64_psr(regs)->ri);
 			siginfo.si_imm = vector;
 			siginfo.si_flags = __ISR_VALID;
 			siginfo.si_isr = isr;
@@ -524,7 +524,7 @@
 		}
 		siginfo.si_signo = SIGTRAP;
 		siginfo.si_errno = 0;
-		siginfo.si_addr  = (void *) ifa;
+		siginfo.si_addr  = (void __user *) ifa;
 		siginfo.si_imm   = 0;
 		siginfo.si_flags = __ISR_VALID;
 		siginfo.si_isr   = isr;
@@ -538,7 +538,7 @@
 			siginfo.si_signo = SIGFPE;
 			siginfo.si_errno = 0;
 			siginfo.si_code = FPE_FLTINV;
-			siginfo.si_addr = (void *) (regs->cr_iip + ia64_psr(regs)->ri);
+			siginfo.si_addr = (void __user *) (regs->cr_iip + ia64_psr(regs)->ri);
 			siginfo.si_flags = __ISR_VALID;
 			siginfo.si_isr = isr;
 			siginfo.si_imm = 0;
@@ -565,7 +565,8 @@
 				siginfo.si_flags = 0;
 				siginfo.si_isr = 0;
 				siginfo.si_imm = 0;
-				siginfo.si_addr = (void *) (regs->cr_iip + ia64_psr(regs)->ri);
+				siginfo.si_addr = (void __user *)
+					(regs->cr_iip + ia64_psr(regs)->ri);
 				force_sig_info(SIGILL, &siginfo, current);
 				return;
 			}
diff -Nru a/arch/ia64/kernel/unaligned.c b/arch/ia64/kernel/unaligned.c
--- a/arch/ia64/kernel/unaligned.c	2004-10-18 14:57:03 -07:00
+++ b/arch/ia64/kernel/unaligned.c	2004-10-18 14:57:03 -07:00
@@ -760,7 +760,7 @@
 		return -1;
 	}
 	/* this assumes little-endian byte-order: */
-	if (copy_from_user(&val, (void *) ifa, len))
+	if (copy_from_user(&val, (void __user *) ifa, len))
 		return -1;
 	setreg(ld.r1, val, 0, regs);
 
@@ -869,7 +869,7 @@
 	 *
 	 * extract the value to be stored
 	 */
-	getreg(ld.imm, &r2, 0, regs);
+	getreg(ld.imm, &r2, NULL, regs);
 
 	/*
 	 * we rely on the macros in unaligned.h for now i.e.,
@@ -887,7 +887,7 @@
 	}
 
 	/* this assumes little-endian byte-order: */
-	if (copy_to_user((void *) ifa, &r2, len))
+	if (copy_to_user((void __user *) ifa, &r2, len))
 		return -1;
 
 	/*
@@ -1036,8 +1036,8 @@
 		 * This assumes little-endian byte-order.  Note that there is no "ldfpe"
 		 * instruction:
 		 */
-		if (copy_from_user(&fpr_init[0], (void *) ifa, len)
-		    || copy_from_user(&fpr_init[1], (void *) (ifa + len), len))
+		if (copy_from_user(&fpr_init[0], (void __user *) ifa, len)
+		    || copy_from_user(&fpr_init[1], (void __user *) (ifa + len), len))
 			return -1;
 
 		DPRINT("ld.r1=%d ld.imm=%d x6_sz=%d\n", ld.r1, ld.imm, ld.x6_sz);
@@ -1138,7 +1138,7 @@
 	 * See comments in ldX for descriptions on how the various loads are handled.
 	 */
 	if (ld.x6_op != 0x2) {
-		if (copy_from_user(&fpr_init, (void *) ifa, len))
+		if (copy_from_user(&fpr_init, (void __user *) ifa, len))
 			return -1;
 
 		DPRINT("ld.r1=%d x6_sz=%d\n", ld.r1, ld.x6_sz);
@@ -1230,7 +1230,7 @@
 	DDUMP("fpr_init =", &fpr_init, len);
 	DDUMP("fpr_final =", &fpr_final, len);
 
-	if (copy_to_user((void *) ifa, &fpr_final, len))
+	if (copy_to_user((void __user *) ifa, &fpr_final, len))
 		return -1;
 
 	/*
@@ -1351,7 +1351,7 @@
 	DPRINT("iip=%lx ifa=%lx isr=%lx (ei=%d, sp=%d)\n",
 	       regs->cr_iip, ifa, regs->cr_ipsr, ipsr->ri, ipsr->it);
 
-	if (__copy_from_user(bundle, (void *) regs->cr_iip, 16))
+	if (__copy_from_user(bundle, (void __user *) regs->cr_iip, 16))
 		goto failure;
 
 	/*
@@ -1496,7 +1496,7 @@
 	si.si_signo = SIGBUS;
 	si.si_errno = 0;
 	si.si_code = BUS_ADRALN;
-	si.si_addr = (void *) ifa;
+	si.si_addr = (void __user *) ifa;
 	si.si_flags = 0;
 	si.si_isr = 0;
 	si.si_imm = 0;
diff -Nru a/arch/ia64/kernel/unwind.c b/arch/ia64/kernel/unwind.c
--- a/arch/ia64/kernel/unwind.c	2004-10-18 14:57:18 -07:00
+++ b/arch/ia64/kernel/unwind.c	2004-10-18 14:57:18 -07:00
@@ -47,7 +47,6 @@
 #include "entry.h"
 #include "unwind_i.h"
 
-#define MIN(a,b)	((a) < (b) ? (a) : (b))
 #define p5		5
 
 #define UNW_LOG_CACHE_SIZE	7	/* each unw_script is ~256 bytes in size */
@@ -447,7 +446,7 @@
 int
 unw_access_fr (struct unw_frame_info *info, int regnum, struct ia64_fpreg *val, int write)
 {
-	struct ia64_fpreg *addr = 0;
+	struct ia64_fpreg *addr = NULL;
 	struct pt_regs *pt;
 
 	if ((unsigned) (regnum - 2) >= 126) {
@@ -843,7 +842,7 @@
 		}
 		sr->gr_save_loc = grsave;
 		sr->any_spills = 0;
-		sr->imask = 0;
+		sr->imask = NULL;
 		sr->spill_offset = 0x10;	/* default to psp+16 */
 	}
 }
@@ -963,13 +962,13 @@
 desc_mem_stack_f (unw_word t, unw_word size, struct unw_state_record *sr)
 {
 	set_reg(sr->curr.reg + UNW_REG_PSP, UNW_WHERE_NONE,
-		sr->region_start + MIN((int)t, sr->region_len - 1), 16*size);
+		sr->region_start + min_t(int, t, sr->region_len - 1), 16*size);
 }
 
 static inline void
 desc_mem_stack_v (unw_word t, struct unw_state_record *sr)
 {
-	sr->curr.reg[UNW_REG_PSP].when = sr->region_start + MIN((int)t, sr->region_len - 1);
+	sr->curr.reg[UNW_REG_PSP].when = sr->region_start + min_t(int, t, sr->region_len - 1);
 }
 
 static inline void
@@ -1005,7 +1004,7 @@
 
 	if (reg->where == UNW_WHERE_NONE)
 		reg->where = UNW_WHERE_GR_SAVE;
-	reg->when = sr->region_start + MIN((int)t, sr->region_len - 1);
+	reg->when = sr->region_start + min_t(int, t, sr->region_len - 1);
 }
 
 static inline void
@@ -1073,7 +1072,7 @@
 static inline int
 desc_is_active (unsigned char qp, unw_word t, struct unw_state_record *sr)
 {
-	if (sr->when_target <= sr->region_start + MIN((int)t, sr->region_len - 1))
+	if (sr->when_target <= sr->region_start + min_t(int, t, sr->region_len - 1))
 		return 0;
 	if (qp > 0) {
 		if ((sr->pr_val & (1UL << qp)) == 0)
@@ -1114,7 +1113,7 @@
 
 	r = sr->curr.reg + decode_abreg(abreg, 0);
 	r->where = where;
-	r->when = sr->region_start + MIN((int)t, sr->region_len - 1);
+	r->when = sr->region_start + min_t(int, t, sr->region_len - 1);
 	r->val = (ytreg & 0x7f);
 }
 
@@ -1129,7 +1128,7 @@
 
 	r = sr->curr.reg + decode_abreg(abreg, 1);
 	r->where = UNW_WHERE_PSPREL;
-	r->when = sr->region_start + MIN((int)t, sr->region_len - 1);
+	r->when = sr->region_start + min_t(int, t, sr->region_len - 1);
 	r->val = 0x10 - 4*pspoff;
 }
 
@@ -1144,7 +1143,7 @@
 
 	r = sr->curr.reg + decode_abreg(abreg, 1);
 	r->where = UNW_WHERE_SPREL;
-	r->when = sr->region_start + MIN((int)t, sr->region_len - 1);
+	r->when = sr->region_start + min_t(int, t, sr->region_len - 1);
 	r->val = 4*spoff;
 }
 
@@ -1206,7 +1205,7 @@
 static inline unw_hash_index_t
 hash (unsigned long ip)
 {
-#	define hashmagic	0x9e3779b97f4a7c16	/* based on (sqrt(5)/2-1)*2^64 */
+#	define hashmagic	0x9e3779b97f4a7c16UL	/* based on (sqrt(5)/2-1)*2^64 */
 
 	return (ip >> 4)*hashmagic >> (64 - UNW_LOG_HASH_SIZE);
 #undef hashmagic
@@ -1231,7 +1230,7 @@
 	unsigned long ip, pr;
 
 	if (UNW_DEBUG_ON(0))
-		return 0;	/* Always regenerate scripts in debug mode */
+		return NULL;	/* Always regenerate scripts in debug mode */
 
 	STAT(++unw.stat.cache.lookups);
 
@@ -1245,7 +1244,7 @@
 
 	index = unw.hash[hash(ip)];
 	if (index >= UNW_CACHE_SIZE)
-		return 0;
+		return NULL;
 
 	script = unw.cache + index;
 	while (1) {
@@ -1256,7 +1255,7 @@
 			return script;
 		}
 		if (script->coll_chain >= UNW_HASH_SIZE)
-			return 0;
+			return NULL;
 		script = unw.cache + script->coll_chain;
 		STAT(++unw.stat.cache.collision_chain_traversals);
 	}
@@ -1306,7 +1305,7 @@
 		if (script->ip) {
 			index = hash(script->ip);
 			tmp = unw.cache + unw.hash[index];
-			prev = 0;
+			prev = NULL;
 			while (1) {
 				if (tmp == script) {
 					if (prev)
@@ -1511,7 +1510,7 @@
 static inline const struct unw_table_entry *
 lookup (struct unw_table *table, unsigned long rel_ip)
 {
-	const struct unw_table_entry *e = 0;
+	const struct unw_table_entry *e = NULL;
 	unsigned long lo, hi, mid;
 
 	/* do a binary search for right entry: */
@@ -1537,8 +1536,8 @@
 static inline struct unw_script *
 build_script (struct unw_frame_info *info)
 {
-	const struct unw_table_entry *e = 0;
-	struct unw_script *script = 0;
+	const struct unw_table_entry *e = NULL;
+	struct unw_script *script = NULL;
 	struct unw_labeled_state *ls, *next;
 	unsigned long ip = info->ip;
 	struct unw_state_record sr;
@@ -1563,7 +1562,7 @@
 	if (!script) {
 		UNW_DPRINT(0, "unwind.%s: failed to create unwind script\n",  __FUNCTION__);
 		STAT(unw.stat.script.build_time += ia64_get_itc() - start);
-		return 0;
+		return NULL;
 	}
 	unw.cache[info->prev_script].hint = script - unw.cache;
 
@@ -1836,7 +1835,7 @@
 		/* don't let obviously bad addresses pollute the cache */
 		/* FIXME: should really be level 0 but it occurs too often. KAO */
 		UNW_DPRINT(1, "unwind.%s: rejecting bad ip=0x%lx\n", __FUNCTION__, info->ip);
-		info->rp_loc = 0;
+		info->rp_loc = NULL;
 		return -1;
 	}
 
@@ -2093,12 +2092,12 @@
 	if (end - start <= 0) {
 		UNW_DPRINT(0, "unwind.%s: ignoring attempt to insert empty unwind table\n",
 			   __FUNCTION__);
-		return 0;
+		return NULL;
 	}
 
 	table = kmalloc(sizeof(*table), GFP_USER);
 	if (!table)
-		return 0;
+		return NULL;
 
 	init_unwind_table(table, name, segment_base, gp, table_start, table_end);
 
@@ -2300,7 +2299,7 @@
  *	EFAULT	BUF points outside your accessible address space.
  */
 asmlinkage long
-sys_getunwind (void *buf, size_t buf_size)
+sys_getunwind (void __user *buf, size_t buf_size)
 {
 	if (buf && buf_size >= unw.gate_table_size)
 		if (copy_to_user(buf, unw.gate_table, unw.gate_table_size) != 0)
diff -Nru a/arch/ia64/kernel/vmlinux.lds.S b/arch/ia64/kernel/vmlinux.lds.S
--- a/arch/ia64/kernel/vmlinux.lds.S	2004-10-18 14:56:50 -07:00
+++ b/arch/ia64/kernel/vmlinux.lds.S	2004-10-18 14:56:50 -07:00
@@ -42,6 +42,7 @@
 	*(.text.ivt)
 	*(.text)
 	SCHED_TEXT
+	LOCK_TEXT
 	*(.gnu.linkonce.t*)
     }
   .text2 : AT(ADDR(.text2) - LOAD_OFFSET)
@@ -134,12 +135,6 @@
 	  __setup_start = .;
 	  *(.init.setup)
 	  __setup_end = .;
-	}
-  __param : AT(ADDR(__param) - LOAD_OFFSET)
-        {
-	  __start___param = .;
-	  *(__param)
-	  __stop___param = .;
 	}
   .initcall.init : AT(ADDR(.initcall.init) - LOAD_OFFSET)
 	{
diff -Nru a/arch/ia64/lib/csum_partial_copy.c b/arch/ia64/lib/csum_partial_copy.c
--- a/arch/ia64/lib/csum_partial_copy.c	2004-10-18 14:56:33 -07:00
+++ b/arch/ia64/lib/csum_partial_copy.c	2004-10-18 14:56:33 -07:00
@@ -1,7 +1,7 @@
 /*
  * Network Checksum & Copy routine
  *
- * Copyright (C) 1999, 2003 Hewlett-Packard Co
+ * Copyright (C) 1999, 2003-2004 Hewlett-Packard Co
  *	Stephane Eranian <eranian@hpl.hp.com>
  *
  * Most of the code has been imported from Linux/Alpha
@@ -105,7 +105,7 @@
 extern unsigned long do_csum(const unsigned char *, long);
 
 static unsigned int
-do_csum_partial_copy_from_user (const char *src, char *dst, int len,
+do_csum_partial_copy_from_user (const char __user *src, char *dst, int len,
 				unsigned int psum, int *errp)
 {
 	unsigned long result;
@@ -129,10 +129,10 @@
 }
 
 unsigned int
-csum_partial_copy_from_user(const char *src, char *dst, int len,
-			    unsigned int sum, int *errp)
+csum_partial_copy_from_user (const char __user *src, char *dst, int len,
+			     unsigned int sum, int *errp)
 {
-	if (!access_ok(src, len, VERIFY_READ)) {
+	if (!access_ok(VERIFY_READ, src, len)) {
 		*errp = -EFAULT;
 		memset(dst, 0, len);
 		return sum;
@@ -142,7 +142,7 @@
 }
 
 unsigned int
-csum_partial_copy_nocheck(const char *src, char *dst, int len, unsigned int sum)
+csum_partial_copy_nocheck(const char __user *src, char *dst, int len, unsigned int sum)
 {
 	return do_csum_partial_copy_from_user(src, dst, len, sum, NULL);
 }
diff -Nru a/arch/ia64/lib/io.c b/arch/ia64/lib/io.c
--- a/arch/ia64/lib/io.c	2004-10-18 14:55:46 -07:00
+++ b/arch/ia64/lib/io.c	2004-10-18 14:55:46 -07:00
@@ -9,7 +9,7 @@
  * This needs to be optimized.
  */
 void
-__ia64_memcpy_fromio (void *to, unsigned long from, long count)
+__ia64_memcpy_fromio (void *to, volatile void __iomem *from, long count)
 {
 	char *dst = to;
 
@@ -25,7 +25,7 @@
  * This needs to be optimized.
  */
 void
-__ia64_memcpy_toio (unsigned long to, void *from, long count)
+__ia64_memcpy_toio (volatile void __iomem *to, void *from, long count)
 {
 	char *src = from;
 
@@ -41,7 +41,7 @@
  * This needs to be optimized.
  */
 void
-__ia64_memset_c_io (unsigned long dst, unsigned long c, long count)
+__ia64_memset_c_io (volatile void __iomem *dst, unsigned long c, long count)
 {
 	unsigned char ch = (char)(c & 0xff);
 
@@ -111,49 +111,49 @@
 }
 
 unsigned char
-__ia64_readb (void *addr)
+__ia64_readb (void __iomem *addr)
 {
 	return ___ia64_readb (addr);
 }
 
 unsigned short
-__ia64_readw (void *addr)
+__ia64_readw (void __iomem *addr)
 {
 	return ___ia64_readw (addr);
 }
 
 unsigned int
-__ia64_readl (void *addr)
+__ia64_readl (void __iomem *addr)
 {
 	return ___ia64_readl (addr);
 }
 
 unsigned long
-__ia64_readq (void *addr)
+__ia64_readq (void __iomem *addr)
 {
 	return ___ia64_readq (addr);
 }
 
 unsigned char
-__ia64_readb_relaxed (void *addr)
+__ia64_readb_relaxed (void __iomem *addr)
 {
 	return ___ia64_readb (addr);
 }
 
 unsigned short
-__ia64_readw_relaxed (void *addr)
+__ia64_readw_relaxed (void __iomem *addr)
 {
 	return ___ia64_readw (addr);
 }
 
 unsigned int
-__ia64_readl_relaxed (void *addr)
+__ia64_readl_relaxed (void __iomem *addr)
 {
 	return ___ia64_readl (addr);
 }
 
 unsigned long
-__ia64_readq_relaxed (void *addr)
+__ia64_readq_relaxed (void __iomem *addr)
 {
 	return ___ia64_readq (addr);
 }
diff -Nru a/arch/ia64/lib/swiotlb.c b/arch/ia64/lib/swiotlb.c
--- a/arch/ia64/lib/swiotlb.c	2004-10-18 14:56:49 -07:00
+++ b/arch/ia64/lib/swiotlb.c	2004-10-18 14:56:49 -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-10-18 14:56:28 -07:00
+++ b/arch/ia64/mm/contig.c	2004-10-18 14:56:28 -07:00
@@ -116,19 +116,19 @@
 		range_start = max(start, free_start);
 		range_end   = min(end, rsvd_region[i].start & PAGE_MASK);
 
+		free_start = PAGE_ALIGN(rsvd_region[i].end);
+
 		if (range_end <= range_start)
 			continue; /* skip over empty range */
 
-	       	if (range_end - range_start >= needed) {
+		if (range_end - range_start >= needed) {
 			bootmap_start = __pa(range_start);
-			return 1;	/* done */
+			return -1;	/* done */
 		}
 
 		/* nothing more available in this segment */
 		if (range_end == end)
 			return 0;
-
-		free_start = PAGE_ALIGN(rsvd_region[i].end);
 	}
 	return 0;
 }
@@ -267,9 +267,8 @@
 	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 {
 		unsigned long map_size;
 
@@ -278,12 +277,12 @@
 		map_size = PAGE_ALIGN(max_low_pfn * sizeof(struct page));
 		vmalloc_end -= map_size;
 		vmem_map = (struct page *) vmalloc_end;
-		efi_memmap_walk(create_mem_map_page_table, 0);
+		efi_memmap_walk(create_mem_map_page_table, NULL);
 
-		free_area_init_node(0, &contig_page_data, vmem_map, zones_size,
+		mem_map = 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;
 		printk("Virtual mem_map starts at 0x%p\n", mem_map);
 	}
 #else /* !CONFIG_VIRTUAL_MEM_MAP */
diff -Nru a/arch/ia64/mm/discontig.c b/arch/ia64/mm/discontig.c
--- a/arch/ia64/mm/discontig.c	2004-10-18 14:56:50 -07:00
+++ b/arch/ia64/mm/discontig.c	2004-10-18 14:56:50 -07:00
@@ -53,11 +53,12 @@
 static void __init reassign_cpu_only_nodes(void)
 {
 	struct node_memblk_s *p;
-	int i, j, k, nnode, nid, cpu, cpunid;
+	int i, j, k, nnode, nid, cpu, cpunid, pxm;
 	u8 cslit, slit;
 	static DECLARE_BITMAP(nodes_with_mem, NR_NODES) __initdata;
 	static u8 numa_slit_fix[MAX_NUMNODES * MAX_NUMNODES] __initdata;
 	static int node_flip[NR_NODES] __initdata;
+	static int old_nid_map[NR_CPUS] __initdata;
 
 	for (nnode = 0, p = &node_memblk[0]; p < &node_memblk[num_node_memblks]; p++)
 		if (!test_bit(p->nid, (void *) nodes_with_mem)) {
@@ -104,9 +105,14 @@
 
 		for (cpu = 0; cpu < NR_CPUS; cpu++)
 			if (node_cpuid[cpu].nid == i) {
-				/* For nodes not being reassigned just fix the cpu's nid. */
+				/*
+				 * For nodes not being reassigned just
+				 * fix the cpu's nid and reverse pxm map
+				 */
 				if (cpunid < numnodes) {
-					node_cpuid[cpu].nid = cpunid;
+					pxm = nid_to_pxm_map[i];
+					pxm_to_nid_map[pxm] =
+					          node_cpuid[cpu].nid = cpunid;
 					continue;
 				}
 
@@ -126,6 +132,8 @@
 						}
 					}
 
+				/* save old nid map so we can update the pxm */
+				old_nid_map[cpu] = node_cpuid[cpu].nid;
 				node_cpuid[cpu].nid = k;
 			}
 	}
@@ -134,14 +142,19 @@
 	 * Fixup temporary nid values for CPU-only nodes.
 	 */
 	for (cpu = 0; cpu < NR_CPUS; cpu++)
-		if (node_cpuid[cpu].nid == (numnodes + numnodes))
-			node_cpuid[cpu].nid = nnode - 1;
-		else
-			for (i = 0; i < nnode; i++)
-				if (node_flip[i] == (node_cpuid[cpu].nid - numnodes)) {
-					node_cpuid[cpu].nid = i;
-					break;
-				}
+		if (node_cpuid[cpu].nid == (numnodes + numnodes)) {
+			pxm = nid_to_pxm_map[old_nid_map[cpu]];
+			pxm_to_nid_map[pxm] = node_cpuid[cpu].nid = nnode - 1;
+		} else {
+			for (i = 0; i < nnode; i++) {
+				if (node_flip[i] != (node_cpuid[cpu].nid - numnodes))
+					continue;
+
+				pxm = nid_to_pxm_map[old_nid_map[cpu]];
+				pxm_to_nid_map[pxm] = node_cpuid[cpu].nid = i;
+				break;
+			}
+		}
 
 	/*
 	 * Fix numa_slit by compressing from larger
@@ -492,14 +505,17 @@
  */
 void show_mem(void)
 {
-	int i, reserved = 0;
-	int shared = 0, cached = 0;
+	int i, total_reserved = 0;
+	int total_shared = 0, total_cached = 0;
+	unsigned long total_present = 0;
 	pg_data_t *pgdat;
 
 	printk("Mem-info:\n");
 	show_free_areas();
 	printk("Free swap:       %6ldkB\n", nr_swap_pages<<(PAGE_SHIFT-10));
 	for_each_pgdat(pgdat) {
+		unsigned long present = pgdat->node_present_pages;
+		int shared = 0, cached = 0, reserved = 0;
 		printk("Node ID: %d\n", pgdat->node_id);
 		for(i = 0; i < pgdat->node_spanned_pages; i++) {
 			if (!ia64_pfn_valid(pgdat->node_start_pfn+i))
@@ -511,11 +527,19 @@
 			else if (page_count(pgdat->node_mem_map+i))
 				shared += page_count(pgdat->node_mem_map+i)-1;
 		}
-		printk("\t%ld pages of RAM\n", pgdat->node_present_pages);
+		total_present += present;
+		total_reserved += reserved;
+		total_cached += cached;
+		total_shared += shared;
+		printk("\t%ld pages of RAM\n", present);
 		printk("\t%d reserved pages\n", reserved);
 		printk("\t%d pages shared\n", shared);
 		printk("\t%d pages swap cached\n", cached);
 	}
+	printk("%ld pages of RAM\n", total_present);
+	printk("%d reserved pages\n", total_reserved);
+	printk("%d pages shared\n", total_shared);
+	printk("%d pages swap cached\n", total_cached);
 	printk("Total of %ld pages in page table cache\n", pgtable_cache_size);
 	printk("%d free buffer pages\n", nr_free_buffer_pages());
 }
@@ -607,12 +631,10 @@
 	unsigned long max_dma;
 	unsigned long zones_size[MAX_NR_ZONES];
 	unsigned long zholes_size[MAX_NR_ZONES];
-	unsigned long max_gap, pfn_offset = 0;
+	unsigned long pfn_offset = 0;
 	int node;
 
 	max_dma = virt_to_phys((void *) MAX_DMA_ADDRESS) >> PAGE_SHIFT;
-	max_gap = 0;
-	efi_memmap_walk(find_largest_hole, &max_gap);
 
 	/* so min() will work in count_node_pages */
 	for (node = 0; node < numnodes; node++)
@@ -664,8 +686,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/extable.c b/arch/ia64/mm/extable.c
--- a/arch/ia64/mm/extable.c	2004-10-18 14:56:27 -07:00
+++ b/arch/ia64/mm/extable.c	2004-10-18 14:56:27 -07:00
@@ -77,7 +77,7 @@
                 else
                         last = mid - 1;
         }
-        return 0;
+        return NULL;
 }
 
 void
diff -Nru a/arch/ia64/mm/fault.c b/arch/ia64/mm/fault.c
--- a/arch/ia64/mm/fault.c	2004-10-18 14:57:04 -07:00
+++ b/arch/ia64/mm/fault.c	2004-10-18 14:57:04 -07:00
@@ -14,7 +14,6 @@
 #include <asm/processor.h>
 #include <asm/system.h>
 #include <asm/uaccess.h>
-#include <asm/hardirq.h>
 
 extern void die (char *, struct pt_regs *, long);
 
@@ -40,6 +39,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;
 }
 
@@ -196,7 +196,7 @@
 		si.si_signo = signal;
 		si.si_errno = 0;
 		si.si_code = code;
-		si.si_addr = (void *) address;
+		si.si_addr = (void __user *) address;
 		si.si_isr = isr;
 		si.si_flags = __ISR_VALID;
 		force_sig_info(signal, &si, current);
diff -Nru a/arch/ia64/mm/init.c b/arch/ia64/mm/init.c
--- a/arch/ia64/mm/init.c	2004-10-18 14:56:29 -07:00
+++ b/arch/ia64/mm/init.c	2004-10-18 14:56:29 -07:00
@@ -67,9 +67,9 @@
 	if (pgtable_cache_size > (u64) high) {
 		do {
 			if (pgd_quicklist)
-				free_page((unsigned long)pgd_alloc_one_fast(0));
+				free_page((unsigned long)pgd_alloc_one_fast(NULL));
 			if (pmd_quicklist)
-				free_page((unsigned long)pmd_alloc_one_fast(0, 0));
+				free_page((unsigned long)pmd_alloc_one_fast(NULL, 0));
 		} while (pgtable_cache_size > (u64) low);
 	}
 	preempt_enable();
@@ -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;
@@ -458,9 +460,9 @@
 	char byte;
 	struct page *pg = pfn_to_page(pfn);
 
-	return     (__get_user(byte, (char *) pg) == 0)
+	return     (__get_user(byte, (char __user *) pg) == 0)
 		&& ((((u64)pg & PAGE_MASK) == (((u64)(pg + 1) - 1) & PAGE_MASK))
-			|| (__get_user(byte, (char *) (pg + 1) - 1) == 0));
+			|| (__get_user(byte, (char __user *) (pg + 1) - 1) == 0));
 }
 EXPORT_SYMBOL(ia64_pfn_valid);
 
@@ -585,6 +587,6 @@
 	setup_gate();
 
 #ifdef CONFIG_IA32_SUPPORT
-	ia32_boot_gdt_init();
+	ia32_mem_init();
 #endif
 }
diff -Nru a/arch/ia64/mm/tlb.c b/arch/ia64/mm/tlb.c
--- a/arch/ia64/mm/tlb.c	2004-10-18 14:56:48 -07:00
+++ b/arch/ia64/mm/tlb.c	2004-10-18 14:56:48 -07:00
@@ -176,7 +176,7 @@
 	if ((status = ia64_pal_vm_page_size(&tr_pgbits, &purge.mask)) != 0) {
 		printk(KERN_ERR "PAL_VM_PAGE_SIZE failed with status=%ld;"
 		       "defaulting to architected purge page-sizes.\n", status);
-		purge.mask = 0x115557000;
+		purge.mask = 0x115557000UL;
 	}
 	purge.max_bits = ia64_fls(purge.mask);
 
diff -Nru a/arch/ia64/oprofile/Kconfig b/arch/ia64/oprofile/Kconfig
--- a/arch/ia64/oprofile/Kconfig	2004-10-18 14:56:33 -07:00
+++ b/arch/ia64/oprofile/Kconfig	2004-10-18 14:56:33 -07:00
@@ -16,6 +16,10 @@
 	  whole system, include the kernel, kernel modules, libraries,
 	  and applications.
 
+	  Due to firmware bugs, you may need to use the "nohalt" boot
+	  option if you're using OProfile with the hardware performance
+	  counters.
+
 	  If unsure, say N.
 
 endmenu
diff -Nru a/arch/ia64/oprofile/Makefile b/arch/ia64/oprofile/Makefile
--- a/arch/ia64/oprofile/Makefile	2004-10-18 14:56:19 -07:00
+++ b/arch/ia64/oprofile/Makefile	2004-10-18 14:56:19 -07:00
@@ -7,3 +7,4 @@
 		timer_int.o )
 
 oprofile-y := $(DRIVER_OBJS) init.o
+oprofile-$(CONFIG_PERFMON) += perfmon.o
diff -Nru a/arch/ia64/oprofile/init.c b/arch/ia64/oprofile/init.c
--- a/arch/ia64/oprofile/init.c	2004-10-18 14:55:55 -07:00
+++ b/arch/ia64/oprofile/init.c	2004-10-18 14:55:55 -07:00
@@ -12,14 +12,21 @@
 #include <linux/init.h>
 #include <linux/errno.h>
  
-extern void timer_init(struct oprofile_operations ** ops);
+extern int perfmon_init(struct oprofile_operations ** ops);
+extern void perfmon_exit(void);
 
 int __init oprofile_arch_init(struct oprofile_operations ** ops)
 {
+#ifdef CONFIG_PERFMON
+	return perfmon_init(ops);
+#endif
 	return -ENODEV;
 }
 
 
 void oprofile_arch_exit(void)
 {
+#ifdef CONFIG_PERFMON
+	perfmon_exit();
+#endif
 }
diff -Nru a/arch/ia64/oprofile/perfmon.c b/arch/ia64/oprofile/perfmon.c
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/arch/ia64/oprofile/perfmon.c	2004-10-18 14:57:23 -07:00
@@ -0,0 +1,105 @@
+/**
+ * @file perfmon.c
+ *
+ * @remark Copyright 2003 OProfile authors
+ * @remark Read the file COPYING
+ *
+ * @author John Levon <levon@movementarian.org>
+ */
+
+#include <linux/kernel.h>
+#include <linux/config.h>
+#include <linux/oprofile.h>
+#include <linux/sched.h>
+#include <asm/perfmon.h>
+#include <asm/ptrace.h>
+#include <asm/errno.h>
+
+static int allow_ints;
+
+static int
+perfmon_handler(struct task_struct *task, void *buf, pfm_ovfl_arg_t *arg,
+                struct pt_regs *regs, unsigned long stamp)
+{
+	int cpu = smp_processor_id();
+	unsigned long eip = instruction_pointer(regs);
+	int event = arg->pmd_eventid;
+ 
+	arg->ovfl_ctrl.bits.reset_ovfl_pmds = 1;
+
+	/* the owner of the oprofile event buffer may have exited
+	 * without perfmon being shutdown (e.g. SIGSEGV)
+	 */
+	if (allow_ints)
+		oprofile_add_sample(eip, !user_mode(regs), event, cpu);
+	return 0;
+}
+
+
+static int perfmon_start(void)
+{
+	allow_ints = 1;
+	return 0;
+}
+
+
+static void perfmon_stop(void)
+{
+	allow_ints = 0;
+}
+
+
+#define OPROFILE_FMT_UUID { \
+	0x77, 0x7a, 0x6e, 0x61, 0x20, 0x65, 0x73, 0x69, 0x74, 0x6e, 0x72, 0x20, 0x61, 0x65, 0x0a, 0x6c }
+
+static pfm_buffer_fmt_t oprofile_fmt = {
+ 	.fmt_name 	    = "oprofile_format",
+ 	.fmt_uuid	    = OPROFILE_FMT_UUID,
+ 	.fmt_handler	    = perfmon_handler,
+};
+
+
+static char * get_cpu_type(void)
+{
+	__u8 family = local_cpu_data->family;
+
+	switch (family) {
+		case 0x07:
+			return "ia64/itanium";
+		case 0x1f:
+			return "ia64/itanium2";
+		default:
+			return "ia64/ia64";
+	}
+}
+
+
+/* all the ops are handled via userspace for IA64 perfmon */
+static struct oprofile_operations perfmon_ops = {
+	.start = perfmon_start,
+	.stop = perfmon_stop,
+};
+
+static int using_perfmon;
+
+int perfmon_init(struct oprofile_operations ** ops)
+{
+	int ret = pfm_register_buffer_fmt(&oprofile_fmt);
+	if (ret)
+		return -ENODEV;
+
+	perfmon_ops.cpu_type = get_cpu_type();
+	*ops = &perfmon_ops;
+	using_perfmon = 1;
+	printk(KERN_INFO "oprofile: using perfmon.\n");
+	return 0;
+}
+
+
+void perfmon_exit(void)
+{
+	if (!using_perfmon)
+		return;
+
+	pfm_unregister_buffer_fmt(oprofile_fmt.fmt_uuid);
+}
diff -Nru a/arch/ia64/pci/pci.c b/arch/ia64/pci/pci.c
--- a/arch/ia64/pci/pci.c	2004-10-18 14:56:29 -07:00
+++ b/arch/ia64/pci/pci.c	2004-10-18 14:56:29 -07:00
@@ -46,8 +46,6 @@
 #define DBG(x...)
 #endif
 
-struct pci_fixup pcibios_fixups[1];
-
 /*
  * Low-level SAL-based PCI configuration access functions. Note that SAL
  * calls are already serialized (via sal_lock), so we don't need another
@@ -138,6 +136,11 @@
 
 	printk(KERN_INFO "PCI: Using ACPI for IRQ routing\n");
 
+#ifdef CONFIG_NUMA
+extern acpi_status acpi_map_iosapic (acpi_handle, u32, void*, void**);
+
+	acpi_get_devices(NULL, acpi_map_iosapic, NULL, NULL);
+#endif
 	/*
 	 * PCI IRQ routing is set up by pci_enable_device(), but we
 	 * also do it here in case there are still broken drivers that
@@ -332,7 +335,7 @@
 	struct pci_window *window;
 	int i, j;
 	int limit = (dev->hdr_type == PCI_HEADER_TYPE_NORMAL) ? \
-		PCI_ROM_RESOURCE : PCI_NUM_RESOURCES;
+		PCI_BRIDGE_RESOURCES : PCI_NUM_RESOURCES;
 
 	for (i = 0; i < limit; i++) {
 		if (!dev->resource[i].start)
diff -Nru a/arch/ia64/sn/fakeprom/Makefile b/arch/ia64/sn/fakeprom/Makefile
--- a/arch/ia64/sn/fakeprom/Makefile	2004-10-18 14:57:03 -07: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-10-18 14:57:05 -07: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	2004-10-18 14:56:28 -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	2004-10-18 14:56:32 -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-10-18 14:56:49 -07: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	2004-10-18 14:56:27 -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-10-18 14:56:49 -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	2004-10-18 14:55:53 -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	2004-10-18 14:56:32 -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	2004-10-18 14:55:53 -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	2004-10-18 14:56:27 -07: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/hwgfs/interface.c b/arch/ia64/sn/io/hwgfs/interface.c
--- a/arch/ia64/sn/io/hwgfs/interface.c	2004-10-18 14:57:04 -07:00
+++ b/arch/ia64/sn/io/hwgfs/interface.c	2004-10-18 14:57:04 -07:00
@@ -42,7 +42,7 @@
 
 		nd->dentry = lookup_create(nd, is_dir);
 		nd->flags |= LOOKUP_PARENT;
-		if (unlikely(IS_ERR(nd->dentry)))
+		if (IS_ERR(nd->dentry))
 			return PTR_ERR(nd->dentry);
 
 		if (!nd->dentry->d_inode)
@@ -89,7 +89,7 @@
 
 	*dentry = lookup_create(&nd, is_dir);
 
-	if (unlikely(IS_ERR(*dentry)))
+	if (IS_ERR(*dentry))
 		return PTR_ERR(*dentry);
 	*parent_inode = (*dentry)->d_parent->d_inode;
 	return 0;
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-10-18 14:56:49 -07:00
+++ b/arch/ia64/sn/io/machvec/pci_bus_cvlink.c	2004-10-18 14:56:49 -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,10 +353,24 @@
                         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;
                 }
-        }
+        } else {
+		/*
+		 * Remove other ROM resources since they don't have valid
+		 * CPU addresses.
+		 */
+                size = dev->resource[PCI_ROM_RESOURCE].end -
+                        dev->resource[PCI_ROM_RESOURCE].start;
+
+		if (size) {
+			dev->resource[PCI_ROM_RESOURCE].start = 0;
+			dev->resource[PCI_ROM_RESOURCE].end = 0;
+			dev->resource[PCI_ROM_RESOURCE].flags = 0;
+		}
+	}
 
 	/*
 	 * Update the Command Word on the Card.
diff -Nru a/arch/ia64/sn/kernel/bte.c b/arch/ia64/sn/kernel/bte.c
--- a/arch/ia64/sn/kernel/bte.c	2004-10-18 14:56:32 -07:00
+++ b/arch/ia64/sn/kernel/bte.c	2004-10-18 14:56:32 -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/setup.c b/arch/ia64/sn/kernel/setup.c
--- a/arch/ia64/sn/kernel/setup.c	2004-10-18 14:56:27 -07:00
+++ b/arch/ia64/sn/kernel/setup.c	2004-10-18 14:56:27 -07:00
@@ -64,6 +64,8 @@
 
 unsigned long sn_rtc_cycles_per_second;   
 
+EXPORT_SYMBOL(sn_rtc_cycles_per_second);
+
 partid_t sn_partid = -1;
 char sn_system_serial_number_string[128];
 u64 sn_partition_serial_number;
diff -Nru a/arch/ia64/sn/kernel/sn2/Makefile b/arch/ia64/sn/kernel/sn2/Makefile
--- a/arch/ia64/sn/kernel/sn2/Makefile	2004-10-18 14:57:04 -07:00
+++ b/arch/ia64/sn/kernel/sn2/Makefile	2004-10-18 14:57:04 -07:00
@@ -10,4 +10,4 @@
 #
 
 obj-y += cache.o io.o ptc_deadlock.o sn2_smp.o sn_proc_fs.o \
-	 prominfo_proc.o timer.o timer_interrupt.o
+	 prominfo_proc.o timer.o timer_interrupt.o sn_hwperf.o
diff -Nru a/arch/ia64/sn/kernel/sn2/prominfo_proc.c b/arch/ia64/sn/kernel/sn2/prominfo_proc.c
--- a/arch/ia64/sn/kernel/sn2/prominfo_proc.c	2004-10-18 14:56:18 -07:00
+++ b/arch/ia64/sn/kernel/sn2/prominfo_proc.c	2004-10-18 14:56:18 -07:00
@@ -3,10 +3,10 @@
  * License.  See the file "COPYING" in the main directory of this archive
  * for more details.
  *
- * Copyright (C) 1999,2001-2003 Silicon Graphics, Inc.  All Rights Reserved.
+ * Copyright (C) 1999,2001-2004 Silicon Graphics, Inc.  All Rights Reserved.
  *
  * Module to export the system's Firmware Interface Tables, including
- * PROM revision numbers, in /proc
+ * PROM revision numbers and banners, in /proc
  */
 #include <linux/config.h>
 #include <linux/module.h>
@@ -14,41 +14,14 @@
 #include <linux/proc_fs.h>
 #include <asm/system.h>
 #include <asm/io.h>
-#include <asm/sn/sn2/addrs.h>
-#include <asm/sn/simulator.h>
-
-/* to lookup nasids */
+#include <asm/sn/sn_sal.h>
 #include <asm/sn/sn_cpuid.h>
+#include <asm/sn/sn2/addrs.h>
 
 MODULE_DESCRIPTION("PROM version reporting for /proc");
 MODULE_AUTHOR("Chad Talbott");
 MODULE_LICENSE("GPL");
 
-#undef DEBUG_PROMINFO
-
-#define TRACE_PROMINFO
-
-#if defined(DEBUG_PROMINFO)
-#  define DPRINTK(x...) printk(KERN_DEBUG x)
-#else
-#  define DPRINTK(x...)
-#endif
-
-#if defined(TRACE_PROMINFO) && defined(DEBUG_PROMINFO)
-#  if defined(__GNUC__)
-#    define TRACE()	printk(KERN_DEBUG "%s:%d:%s\n", \
-			       __FILE__, __LINE__, __FUNCTION__)
-#  else
-#    define TRACE()	printk(KERN_DEBUG "%s:%d\n", __LINE__, __FILE__)
-#  endif
-#else
-#  define TRACE()
-#endif
-
-/* Sub-regions determined by bits in Node Offset */
-#define	LB_PROM_SPACE		0x0000000700000000ul /* Local LB PROM */
-
-#define FIT_SIGNATURE		0x2020205f5449465ful
 /* Standard Intel FIT entry types */
 #define FIT_ENTRY_FIT_HEADER	0x00	/* FIT header entry */
 #define FIT_ENTRY_PAL_B		0x01	/* PAL_B entry */
@@ -81,12 +54,6 @@
 #define FIT_TYPE(q)	\
 	((unsigned) ((q) >> FIT_TYPE_SHIFT) & FIT_TYPE_MASK)
 
-#define FIT_ENTRY(type, maj, min, size)					\
-	((((unsigned long)(maj) & FIT_MAJOR_MASK) << FIT_MAJOR_SHIFT) |	\
-	 (((unsigned long)(min) & FIT_MINOR_MASK) << FIT_MINOR_SHIFT) |	\
-	 (((unsigned long)(type) & FIT_TYPE_MASK) << FIT_TYPE_SHIFT) |	\
-	 (size))
-
 struct fit_type_map_t {
 	unsigned char	type;
 	const char	*name;
@@ -125,32 +92,148 @@
 	return "Unknown type";
 }
 
-/* These two routines read the FIT table directly from the FLASH PROM
- * on a specific node.  The PROM can only be accessed using aligned 64
- * bit reads, so we do that and then shift and mask the result to get
- * at each field.
+
+/* ============ BEGIN temp til old PROMs are no longer supported =============
+ *
+ * The OS should not make direct access to the PROM flash memory. Access to
+ * this region must be serialized with a PROM lock. If SAL on one cpu is
+ * updating the FLASH error log at the same time another cpu is accessing the
+ * PROM, data corruption will occur.
+ *
+ * To solve the problem, all flash PROM access has been moved to SAL. Because
+ * not all systems will have instant PROM updates, we need to support a new OS
+ * running on a system with old PROMs.
+ *
+ * This code should be deleted after 1 OS/PROM release has occurred & the OS
+ * no longer supports downrev PROMs. (PROM support should be in the 3.50
+ * PROMs).
+ */
+#define SUPPORT_OLD_PROMS
+#ifdef SUPPORT_OLD_PROMS
+
+
+#define FIT_SIGNATURE		0x2020205f5449465ful
+
+/* Sub-regions determined by bits in Node Offset */
+#define	LB_PROM_SPACE		0x0000000700000000ul /* Local LB PROM */
+
+/* Offset of PROM banner pointers in SAL A and SAL B */
+#define SAL_A_BANNER_OFFSET	(1 * 16)
+#define SAL_B_BANNER_OFFSET	(3 * 16)
+
+/* Architected IA64 firmware space */
+#define FW_BASE                 0x00000000FF000000
+#define FW_TOP                  0x0000000100000000
+
+static unsigned long
+convert_fw_addr(nasid_t nasid, unsigned long addr)
+{
+	/* snag just the node-relative offset */
+	addr &= ~0ul >> (63-35);
+	/* the pointer to SAL A is relative to IA-64 compatibility
+	 * space.  However, the PROM is mapped at a different offset
+	 * in MMR space (both local and global)
+	 */
+	addr += 0x700000000;
+	return GLOBAL_MMR_ADDR(nasid, addr);
+}
+
+static int
+valid_fw_addr(unsigned long addr)
+{
+	addr &= ~(1ul << 63); /* Clear cached/uncached bit */
+	return (addr >= FW_BASE && addr < FW_TOP);
+}
+
+static unsigned long *
+lookup_fit(int nasid)
+{
+	unsigned long *fitp;
+	unsigned long fit_paddr;
+	unsigned long *fit_vaddr;
+
+	fitp = (void *)GLOBAL_MMR_ADDR(nasid, LB_PROM_SPACE - 32);
+	fit_paddr = readq(fitp);
+	fit_vaddr = (unsigned long *) convert_fw_addr(nasid, fit_paddr);
+	return fit_vaddr;
+}
+#endif /* SUPPORT_OLD_PROMS */
+/* ============ END temp til old PROMs are no longer supported ============= */
+
+static int
+get_fit_entry(unsigned long nasid, int index, unsigned long *fentry,
+	      char *banner, int banlen)
+{
+	int ret;
+
+	ret = ia64_sn_get_fit_compt(nasid, index, fentry, banner, banlen);
+
+#ifdef SUPPORT_OLD_PROMS
+	/* The following is hack is temporary until PROMs are updated */
+	if (ret == SALRET_NOT_IMPLEMENTED) {
+		unsigned long *fitadr = lookup_fit(nasid);
+		int nentries;
+
+		if (readq(fitadr) != FIT_SIGNATURE) {
+			printk(KERN_WARNING "Unrecognized FIT signature");
+			return -2;
+		}
+
+		nentries = (unsigned int) (readq(fitadr + 1) & 0xffffff);
+		if (index >= nentries)
+			return -2;
+
+		fentry[0] = readq(fitadr + 2 * index);
+		fentry[1] = readq(fitadr + 2 * index + 1);
+		ret = 0;
+
+		if (banner && FIT_TYPE(fentry[1]) == FIT_ENTRY_SAL_A) {
+			unsigned long i, qw, *bwp, *qwp;
+
+			banner[0] = '\0';
+			qw = fentry[0];	/* Address of SAL A */
+			if (!valid_fw_addr(qw))
+				return 0;
+
+			qw += SAL_A_BANNER_OFFSET;
+			qw = convert_fw_addr(nasid, qw);
+
+			qw = readq(qw);			/* Address of banner */
+			if (!valid_fw_addr(qw))
+				return 0;
+			qw = convert_fw_addr(nasid, qw);
+			qwp = (unsigned long *) qw;
+			bwp = (unsigned long *) banner;
+			for (i=0; i<banlen/8; i++)
+				bwp[i] = qwp[i];
+		}
+	}
+#endif /* SUPPORT_OLD_PROMS */
+	return ret;
+}
+
+
+/*
+ * These two routines display the FIT table for each node.
  */
 static int
 dump_fit_entry(char *page, unsigned long *fentry)
 {
-	unsigned long q1, q2;
 	unsigned type;
 
-	TRACE();
-
-	q1 = readq(fentry);
-	q2 = readq(fentry + 1);
-	type = FIT_TYPE(q2);
+	type = FIT_TYPE(fentry[1]);
 	return sprintf(page, "%02x %-25s %x.%02x %016lx %u\n",
 		       type,
 		       fit_type_name(type),
-		       FIT_MAJOR(q2), FIT_MINOR(q2),
-		       q1,
+		       FIT_MAJOR(fentry[1]), FIT_MINOR(fentry[1]),
+		       fentry[0],
 		       /* mult by sixteen to get size in bytes */
-		       (unsigned)q2 * 16);
+		       (unsigned)(fentry[1] & 0xffffff) * 16);
 }
 
-/* We assume that the fit table will be small enough that we can print
+
+/*
+ * We assume that the fit table will be small enough that we can print
  * the whole thing into one page.  (This is true for our default 16kB
  * pages -- each entry is about 60 chars wide when printed.)  I read
  * somewhere that the maximum size of the FIT is 128 entries, so we're
@@ -158,55 +241,47 @@
  * anyway).
  */
 static int
-dump_fit(char *page, unsigned long *fit)
+dump_fit(char *page, unsigned long nasid)
 {
-	unsigned long qw;
-	int nentries;
-	int fentry;
+	unsigned long fentry[2];
+	int index;
 	char *p;
 
-	TRACE();
-
-	DPRINTK("dumping fit from %p\n", (void *)fit);
-
-	qw = readq(fit);
-	DPRINTK("FIT signature: %016lx (%.8s)\n", qw, (char *)&qw);
-	if (qw != FIT_SIGNATURE)
-		printk(KERN_WARNING "Unrecognized FIT signature");
-
-	qw = readq(fit + 1);
-	nentries = (unsigned)qw;
-	DPRINTK("number of fit entries: %u\n", nentries);
-	/* check that we won't overflow the page -- see comment above */
-	BUG_ON(nentries * 60 > PAGE_SIZE);
-
 	p = page;
-	for (fentry = 0; fentry < nentries; fentry++)
-		/* each FIT entry is two 64 bit words */
-		p += dump_fit_entry(p, fit + 2 * fentry);
+	for (index=0;;index++) {
+		BUG_ON(index * 60 > PAGE_SIZE);
+		if (get_fit_entry(nasid, index, fentry, NULL, 0))
+			break;
+		p += dump_fit_entry(p, fentry);
+	}
 
 	return p - page;
 }
 
 static int
-dump_version(char *page, unsigned long *fit)
+dump_version(char *page, unsigned long nasid)
 {
-	int nentries;
-	int fentry;
-	unsigned long qw;
-
-	TRACE();
-
-	nentries = (unsigned)readq(fit + 1);
-	BUG_ON(nentries * 60 > PAGE_SIZE);
-
-	for (fentry = 0; fentry < nentries; fentry++) {
-		qw = readq(fit + 2 * fentry + 1);
-		if (FIT_TYPE(qw) == FIT_ENTRY_SAL_A)
-			return sprintf(page, "%x.%02x\n",
-				       FIT_MAJOR(qw), FIT_MINOR(qw));
+	unsigned long fentry[2];
+	char banner[128];
+	int index;
+	int len;
+
+	for (index = 0; ; index++) {
+		if (get_fit_entry(nasid, index, fentry, banner,
+				  sizeof(banner)))
+			return 0;
+		if (FIT_TYPE(fentry[1]) == FIT_ENTRY_SAL_A)
+			break;
 	}
-	return 0;
+
+	len = sprintf(page, "%x.%02x\n", FIT_MAJOR(fentry[1]),
+		      FIT_MINOR(fentry[1]));
+	page += len;
+
+	if (banner[0])
+		len += snprintf(page, PAGE_SIZE-len, "%s\n", banner);
+
+	return len;
 }
 
 /* same as in proc_misc.c */
@@ -228,8 +303,8 @@
 {
 	int len = 0;
 
-	/* data holds the pointer to this node's FIT */
-	len = dump_version(page, (unsigned long *)data);
+	/* data holds the NASID of the node */
+	len = dump_version(page, (unsigned long)data);
 	len = proc_calc_metrics(page, start, off, count, eof, len);
 	return len;
 }
@@ -240,56 +315,13 @@
 {
 	int len = 0;
 
-	/* data holds the pointer to this node's FIT */
-	len = dump_fit(page, (unsigned long *)data);
+	/* data holds the NASID of the node */
+	len = dump_fit(page, (unsigned long)data);
 	len = proc_calc_metrics(page, start, off, count, eof, len);
 
 	return len;
 }
 
-/* this is a fake FIT that's used on the medusa simulator which
- * doesn't usually run a complete PROM. 
- */
-#ifdef CONFIG_IA64_SGI_SN_SIM
-static unsigned long fakefit[] = {
-	/* this is all we need to satisfy the code below */
-	FIT_SIGNATURE,
-	FIT_ENTRY(FIT_ENTRY_FIT_HEADER, 0x02, 0x60, 2),
-	/* dump something arbitrary for
-	 * /proc/sgi_prominfo/nodeX/version */
-	0xbadbeef00fa3ef17ul,
-	FIT_ENTRY(FIT_ENTRY_SAL_A, 0, 0x99, 0x100)
-};	
-#endif
-
-static unsigned long *
-lookup_fit(int nasid)
-{
-	unsigned long *fitp;
-	unsigned long fit_paddr;
-	unsigned long *fit_vaddr;
-
-#ifdef CONFIG_IA64_SGI_SN_SIM
-	if (IS_RUNNING_ON_SIMULATOR())
-		return fakefit;
-#endif
-
-	fitp = (void *)GLOBAL_MMR_ADDR(nasid, LB_PROM_SPACE - 32);
-	DPRINTK("pointer to fit at %p\n", (void *)fitp);
-	fit_paddr = readq(fitp);
-	DPRINTK("fit pointer contains %lx\n", fit_paddr);
-	/* snag just the node-relative offset */
-	fit_paddr &= ~0ul >> (63-35);
-	/* the pointer to the FIT is relative to IA-64 compatibility
-	 * space.  However, the PROM is mapped at a different offset
-	 * in MMR space (both local and global)
-	 */
-	fit_paddr += 0x700000000;
-	fit_vaddr = (void *)GLOBAL_MMR_ADDR(nasid, fit_paddr);
-	DPRINTK("fit at %p\n", (void *)fit_vaddr);
-	return fit_vaddr;
-}
-
 /* module entry points */
 int __init prominfo_init(void);
 void __exit prominfo_exit(void);
@@ -308,17 +340,12 @@
 	struct proc_dir_entry **entp;
 	struct proc_dir_entry *p;
 	cnodeid_t cnodeid;
-	nasid_t nasid;
+	unsigned long nasid;
 	char name[NODE_NAME_LEN];
 
 	if (!ia64_platform_is("sn2"))
 		return 0;
 
-	TRACE();
-
-	DPRINTK("running on cpu %d\n", smp_processor_id());
-	DPRINTK("numnodes %d\n", numnodes);
-
 	proc_entries = kmalloc(numnodes * sizeof(struct proc_dir_entry *),
 			       GFP_KERNEL);
 
@@ -332,12 +359,12 @@
 		nasid = cnodeid_to_nasid(cnodeid);
 		p = create_proc_read_entry(
 			"fit", 0, *entp, read_fit_entry,
-			lookup_fit(nasid));
+			(void *)nasid);
 		if (p)
 			p->owner = THIS_MODULE;
 		p = create_proc_read_entry(
 			"version", 0, *entp, read_version_entry,
-			lookup_fit(nasid));
+			(void *)nasid);
 		if (p)
 			p->owner = THIS_MODULE;
 	}
@@ -351,8 +378,6 @@
 	struct proc_dir_entry **entp;
 	unsigned cnodeid;
 	char name[NODE_NAME_LEN];
-
-	TRACE();
 
 	for (cnodeid = 0, entp = proc_entries;
 	     cnodeid < numnodes;
diff -Nru a/arch/ia64/sn/kernel/sn2/sn_hwperf.c b/arch/ia64/sn/kernel/sn2/sn_hwperf.c
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/arch/ia64/sn/kernel/sn2/sn_hwperf.c	2004-10-18 14:57:24 -07:00
@@ -0,0 +1,652 @@
+/* 
+ * 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) 2004 Silicon Graphics, Inc. All rights reserved.
+ *
+ * SGI Altix topology and hardware performance monitoring API.
+ * Mark Goodwin <markgw@sgi.com>. 
+ *
+ * Creates /proc/sgi_sn/sn_topology (read-only) to export
+ * info about Altix nodes, routers, CPUs and NumaLink
+ * interconnection/topology.
+ *
+ * Also creates a dynamic misc device named "sn_hwperf"
+ * that supports an ioctl interface to call down into SAL
+ * to discover hw objects, topology and to read/write
+ * memory mapped registers, e.g. for performance monitoring.
+ * The "sn_hwperf" device is registered only after the procfs
+ * file is first opened, i.e. only if/when it's needed. 
+ *
+ * This API is used by SGI Performance Co-Pilot and other
+ * tools, see http://oss.sgi.com/projects/pcp
+ */
+
+#include <linux/fs.h>
+#include <linux/slab.h>
+#include <linux/vmalloc.h>
+#include <linux/seq_file.h>
+#include <linux/miscdevice.h>
+#include <linux/cpumask.h>
+#include <linux/smp_lock.h>
+#include <asm/processor.h>
+#include <asm/topology.h>
+#include <asm/smp.h>
+#include <asm/semaphore.h>
+#include <asm/segment.h>
+#include <asm/uaccess.h>
+#include <asm-ia64/sal.h>
+#include <asm-ia64/sn/sn_sal.h>
+#include <asm-ia64/sn/sn2/sn_hwperf.h>
+
+static void *sn_hwperf_salheap = NULL;
+static int sn_hwperf_obj_cnt = 0;
+static nasid_t sn_hwperf_master_nasid = INVALID_NASID;
+static int sn_hwperf_init(void);
+static DECLARE_MUTEX(sn_hwperf_init_mutex);
+
+static int sn_hwperf_enum_objects(int *nobj, struct sn_hwperf_object_info **ret)
+{
+	int e;
+	u64 sz;
+	struct sn_hwperf_object_info *objbuf = NULL;
+
+	if ((e = sn_hwperf_init()) < 0) {
+		printk("sn_hwperf_init failed: err %d\n", e);
+		goto out;
+	}
+
+	sz = sn_hwperf_obj_cnt * sizeof(struct sn_hwperf_object_info);
+	if ((objbuf = (struct sn_hwperf_object_info *) vmalloc(sz)) == NULL) {
+		printk("sn_hwperf_enum_objects: vmalloc(%d) failed\n", (int)sz);
+		e = -ENOMEM;
+		goto out;
+	}
+
+	e = ia64_sn_hwperf_op(sn_hwperf_master_nasid, SN_HWPERF_ENUM_OBJECTS,
+		0, sz, (u64) objbuf, 0, 0, NULL);
+	if (e != SN_HWPERF_OP_OK) {
+		e = -EINVAL;
+		vfree(objbuf);
+	}
+
+out:
+	*nobj = sn_hwperf_obj_cnt;
+	*ret = objbuf;
+	return e;
+}
+
+static int sn_hwperf_geoid_to_cnode(char *location)
+{
+	int cnode;
+	int mod, slot, slab;
+	int cmod, cslot, cslab;
+
+	if (sscanf(location, "%03dc%02d#%d", &mod, &slot, &slab) != 3)
+		return -1;
+	for (cnode = 0; cnode < numnodes; cnode++) {
+		/* XXX: need a better way than this ... */
+		if (sscanf(NODEPDA(cnode)->hwg_node_name,
+		   "hw/module/%03dc%02d/slab/%d", &cmod, &cslot, &cslab) == 3) {
+			if (mod == cmod && slot == cslot && slab == cslab)
+				break;
+		}
+	}
+
+	return cnode < numnodes ? cnode : -1;
+}
+
+static int sn_hwperf_obj_to_cnode(struct sn_hwperf_object_info * obj)
+{
+	if (!obj->sn_hwp_this_part)
+		return -1;
+	return sn_hwperf_geoid_to_cnode(obj->location);
+}
+
+static int sn_hwperf_generic_ordinal(struct sn_hwperf_object_info *obj,
+				struct sn_hwperf_object_info *objs)
+{
+	int ordinal;
+	struct sn_hwperf_object_info *p;
+
+	for (ordinal=0, p=objs; p != obj; p++) {
+		if (SN_HWPERF_FOREIGN(p))
+			continue;
+		if (p->location[3] == obj->location[3])
+			ordinal++;
+	}
+
+	return ordinal;
+}
+
+#ifndef MODULE_IOBRICK 
+/* this will be available when ioif TIO support is added */
+#define MODULE_IOBRICK (MODULE_OPUSBRICK+1)
+#endif
+
+static const char *sn_hwperf_get_brickname(struct sn_hwperf_object_info *obj,
+				struct sn_hwperf_object_info *objs, int *ordinal)
+{
+	int i;
+	const char *objtype = NULL;
+
+	for (i=0; i < MAX_BRICK_TYPES; i++) {
+		if (brick_types[i] != obj->location[3])
+			continue;
+		switch (i) {
+		case MODULE_CBRICK:
+		    objtype = "node";
+		    *ordinal = sn_hwperf_obj_to_cnode(obj); /* cnodeid */
+		    break;
+
+		case MODULE_RBRICK:
+		    objtype = "router";
+		    *ordinal = sn_hwperf_generic_ordinal(obj, objs);
+		    break;
+
+		case MODULE_IOBRICK:
+		    objtype = "ionode";
+		    *ordinal = sn_hwperf_generic_ordinal(obj, objs);
+		    break;
+		}
+		break;
+	}
+
+	if (i == MAX_BRICK_TYPES) {
+		objtype = "other";
+		*ordinal = sn_hwperf_generic_ordinal(obj, objs);
+	}
+
+	return objtype;
+}
+
+static int sn_topology_show(struct seq_file *s, void *d)
+{
+	int sz;
+	int pt;
+	int e;
+	int i;
+	int j;
+	const char *brickname;
+	int ordinal;
+	cpumask_t cpumask;
+	char slice;
+	struct cpuinfo_ia64 *c;
+	struct sn_hwperf_port_info *ptdata;
+	struct sn_hwperf_object_info *p;
+	struct sn_hwperf_object_info *obj = d;	/* this object */
+	struct sn_hwperf_object_info *objs = s->private; /* all objects */
+
+	if (obj == objs) {
+		seq_printf(s, "# sn_topology version 1\n");
+		seq_printf(s, "# objtype ordinal location partition"
+			" [attribute value [, ...]]\n");
+	}
+
+	if (SN_HWPERF_FOREIGN(obj)) {
+		/* private in another partition: not interesting */
+		return 0;
+	}
+
+	for (i = 0; obj->name[i]; i++) {
+		if (obj->name[i] == ' ')
+			obj->name[i] = '_';
+	}
+
+	brickname = sn_hwperf_get_brickname(obj, objs, &ordinal);
+	seq_printf(s, "%s %d %s %s asic %s", brickname, ordinal, obj->location,
+		obj->sn_hwp_this_part ? "local" : "shared", obj->name);
+
+	if (obj->location[3] != 'c')
+		seq_putc(s, '\n');
+	else {
+		seq_printf(s, ", nasid 0x%x", cnodeid_to_nasid(ordinal));
+		for (i=0; i < numnodes; i++) {
+			seq_printf(s, i ? ":%d" : ", dist %d",
+				node_distance(ordinal, i));
+		}
+		seq_putc(s, '\n');
+
+		/*
+		 * CPUs on this node
+		 */
+		cpumask = node_to_cpumask(ordinal);
+		for_each_online_cpu(i) {
+			if (cpu_isset(i, cpumask)) {
+				slice = 'a' + cpuid_to_slice(i);
+				c = cpu_data(i);
+				seq_printf(s, "cpu %d %s%c local"
+					" freq %luMHz, arch ia64",
+					i, obj->location, slice,
+					c->proc_freq / 1000000);
+				for_each_online_cpu(j) {
+					seq_printf(s, j ? ":%d" : ", dist %d",
+						node_distance(
+						    cpuid_to_cnodeid(i),
+						    cpuid_to_cnodeid(j)));
+				}
+				seq_putc(s, '\n');
+			}
+		}
+	}
+
+	if (obj->ports) {
+		/*
+		 * numalink ports
+		 */
+		sz = obj->ports * sizeof(struct sn_hwperf_port_info);
+		if ((ptdata = vmalloc(sz)) == NULL)
+			return -ENOMEM;
+		e = ia64_sn_hwperf_op(sn_hwperf_master_nasid,
+				      SN_HWPERF_ENUM_PORTS, obj->id, sz,
+				      (u64) ptdata, 0, 0, NULL);
+		if (e != SN_HWPERF_OP_OK)
+			return -EINVAL;
+		for (ordinal=0, p=objs; p != obj; p++) {
+			if (!SN_HWPERF_FOREIGN(p))
+				ordinal += p->ports;
+		}
+		for (pt = 0; pt < obj->ports; pt++) {
+			for (p = objs, i = 0; i < sn_hwperf_obj_cnt; i++, p++) {
+				if (ptdata[pt].conn_id == p->id) {
+					break;
+				}
+			}
+			if (i >= sn_hwperf_obj_cnt)
+				continue;
+			seq_printf(s, "numalink %d %s-%d",
+			    ordinal+pt, obj->location, ptdata[pt].port);
+
+			if (obj->sn_hwp_this_part && p->sn_hwp_this_part)
+				/* both ends local to this partition */
+				seq_puts(s, " local");
+			else if (!obj->sn_hwp_this_part && !p->sn_hwp_this_part)
+				/* both ends of the link in foreign partiton */
+				seq_puts(s, " foreign");
+			else
+				/* link straddles a partition */
+				seq_puts(s, " shared");
+
+			/*
+			 * Unlikely, but strictly should query the LLP config
+			 * registers because an NL4R can be configured to run
+			 * NL3 protocol, even when not talking to an NL3 router.
+			 * Ditto for node-node.
+			 */
+			seq_printf(s, " endpoint %s-%d, protocol %s\n",
+				p->location, ptdata[pt].conn_port,
+				strcmp(obj->name, "NL3Router") == 0 ||
+				strcmp(p->name, "NL3Router") == 0 ?
+				"LLP3" : "LLP4");
+		}
+		vfree(ptdata);
+	}
+
+	return 0;
+}
+
+static void *sn_topology_start(struct seq_file *s, loff_t * pos)
+{
+	struct sn_hwperf_object_info *objs = s->private;
+
+	if (*pos < sn_hwperf_obj_cnt)
+		return (void *)(objs + *pos);
+
+	return NULL;
+}
+
+static void *sn_topology_next(struct seq_file *s, void *v, loff_t * pos)
+{
+	++*pos;
+	return sn_topology_start(s, pos);
+}
+
+static void sn_topology_stop(struct seq_file *m, void *v)
+{
+	return;
+}
+
+/*
+ * /proc/sgi_sn/sn_topology, read-only using seq_file
+ */
+static struct seq_operations sn_topology_seq_ops = {
+	.start = sn_topology_start,
+	.next = sn_topology_next,
+	.stop = sn_topology_stop,
+	.show = sn_topology_show
+};
+
+struct sn_hwperf_op_info {
+	u64 op;
+	struct sn_hwperf_ioctl_args *a;
+	void *p;
+	int *v0;
+	int ret;
+};
+
+static void sn_hwperf_call_sal(void *info)
+{
+	struct sn_hwperf_op_info *op_info = info;
+	int r;
+
+	r = ia64_sn_hwperf_op(sn_hwperf_master_nasid, op_info->op,
+		      op_info->a->arg, op_info->a->sz,
+		      (u64) op_info->p, 0, 0, op_info->v0);
+	op_info->ret = r;
+}
+
+static int sn_hwperf_op_cpu(struct sn_hwperf_op_info *op_info)
+{
+	u32 cpu;
+	u32 use_ipi;
+	int r = 0;
+	cpumask_t save_allowed;
+	
+	cpu = (op_info->a->arg & SN_HWPERF_ARG_CPU_MASK) >> 32;
+	use_ipi = op_info->a->arg & SN_HWPERF_ARG_USE_IPI_MASK;
+	op_info->a->arg &= SN_HWPERF_ARG_OBJID_MASK;
+
+	if (cpu != SN_HWPERF_ARG_ANY_CPU) {
+		if (cpu >= num_online_cpus() || !cpu_online(cpu)) {
+			r = -EINVAL;
+			goto out;
+		}
+	}
+
+	if (cpu == SN_HWPERF_ARG_ANY_CPU || cpu == get_cpu()) {
+		/* don't care, or already on correct cpu */
+		sn_hwperf_call_sal(op_info);
+	}
+	else {
+		if (use_ipi) {
+			/* use an interprocessor interrupt to call SAL */
+			smp_call_function_single(cpu, sn_hwperf_call_sal,
+				op_info, 1, 1);
+		}
+		else {
+			/* migrate the task before calling SAL */ 
+			save_allowed = current->cpus_allowed;
+			set_cpus_allowed(current, cpumask_of_cpu(cpu));
+			sn_hwperf_call_sal(op_info);
+			set_cpus_allowed(current, save_allowed);
+		}
+	}
+	r = op_info->ret;
+
+out:
+	return r;
+}
+
+/*
+ * ioctl for "sn_hwperf" misc device
+ */
+static int
+sn_hwperf_ioctl(struct inode *in, struct file *fp, u32 op, u64 arg)
+{
+	struct sn_hwperf_ioctl_args a;
+	struct cpuinfo_ia64 *cdata;
+	struct sn_hwperf_object_info *objs;
+	struct sn_hwperf_object_info *cpuobj;
+	struct sn_hwperf_op_info op_info;
+	void *p = NULL;
+	int nobj;
+	char slice;
+	int node;
+	int r;
+	int v0;
+	int i;
+	int j;
+
+	unlock_kernel();
+
+	/* only user requests are allowed here */
+	if ((op & SN_HWPERF_OP_MASK) < 10) {
+		r = -EINVAL;
+		goto error;
+	}
+	r = copy_from_user(&a, (const void *)arg,
+		sizeof(struct sn_hwperf_ioctl_args));
+	if (r != 0) {
+		r = -EFAULT;
+		goto error;
+	}
+
+	/*
+	 * Allocate memory to hold a kernel copy of the user buffer. The
+	 * buffer contents are either copied in or out (or both) of user
+	 * space depending on the flags encoded in the requested operation.
+	 */
+	if (a.ptr) {
+		p = vmalloc(a.sz);
+		if (!p) {
+			r = -ENOMEM;
+			goto error;
+		}
+	}
+
+	if (op & SN_HWPERF_OP_MEM_COPYIN) {
+		r = copy_from_user(p, (const void *)a.ptr, a.sz);
+		if (r != 0) {
+			r = -EFAULT;
+			goto error;
+		}
+	}
+
+	switch (op) {
+	case SN_HWPERF_GET_CPU_INFO:
+		if (a.sz == sizeof(u64)) {
+			/* special case to get size needed */
+			*(u64 *) p = (u64) num_online_cpus() *
+				sizeof(struct sn_hwperf_object_info);
+		} else
+		if (a.sz < num_online_cpus() * sizeof(struct sn_hwperf_object_info)) {
+			r = -ENOMEM;
+			goto error;
+		} else
+		if ((r = sn_hwperf_enum_objects(&nobj, &objs)) == 0) {
+			memset(p, 0, a.sz);
+			for (i = 0; i < nobj; i++) {
+				node = sn_hwperf_obj_to_cnode(objs + i);
+				for_each_online_cpu(j) {
+					if (node != cpu_to_node(j))
+						continue;
+					cpuobj = (struct sn_hwperf_object_info *) p + j;
+					slice = 'a' + cpuid_to_slice(j);
+					cdata = cpu_data(j);
+					cpuobj->id = j;
+					snprintf(cpuobj->name,
+						 sizeof(cpuobj->name),
+						 "CPU %luMHz %s",
+						 cdata->proc_freq / 1000000,
+						 cdata->vendor);
+					snprintf(cpuobj->location,
+						 sizeof(cpuobj->location),
+						 "%s%c", objs[i].location,
+						 slice);
+				}
+			}
+
+			vfree(objs);
+		}
+		break;
+
+	case SN_HWPERF_GET_NODE_NASID:
+		if (a.sz != sizeof(u64) ||
+		   (node = a.arg) < 0 || node >= numnodes) {
+			r = -EINVAL;
+			goto error;
+		}
+		*(u64 *)p = (u64)cnodeid_to_nasid(node);
+		break;
+
+	case SN_HWPERF_GET_OBJ_NODE:
+		if (a.sz != sizeof(u64) || a.arg < 0) {
+			r = -EINVAL;
+			goto error;
+		}
+		if ((r = sn_hwperf_enum_objects(&nobj, &objs)) == 0) {
+			if (a.arg >= nobj) {
+				r = -EINVAL;
+				vfree(objs);
+				goto error;
+			}
+			if (objs[(i = a.arg)].id != a.arg) {
+				for (i = 0; i < nobj; i++) {
+					if (objs[i].id == a.arg)
+						break;
+				}
+			}
+			if (i == nobj) {
+				r = -EINVAL;
+				vfree(objs);
+				goto error;
+			}
+			*(u64 *)p = (u64)sn_hwperf_obj_to_cnode(objs + i);
+			vfree(objs);
+		}
+		break;
+
+	case SN_HWPERF_GET_MMRS:
+	case SN_HWPERF_SET_MMRS:
+	case SN_HWPERF_OBJECT_DISTANCE:
+		op_info.p = p;
+		op_info.a = &a;
+		op_info.v0 = &v0;
+		op_info.op = op;
+		r = sn_hwperf_op_cpu(&op_info);
+		break;
+
+	default:
+		/* all other ops are a direct SAL call */
+		r = ia64_sn_hwperf_op(sn_hwperf_master_nasid, op,
+			      a.arg, a.sz, (u64) p, 0, 0, &v0);
+		a.v0 = v0;
+		break;
+	}
+
+	if (op & SN_HWPERF_OP_MEM_COPYOUT) {
+		r = copy_to_user((void *)a.ptr, p, a.sz);
+		if (r != 0) {
+			r = -EFAULT;
+			goto error;
+		}
+	}
+
+error:
+	if (p)
+		vfree(p);
+
+	lock_kernel();
+	return r;
+}
+
+static struct file_operations sn_hwperf_fops = {
+	.ioctl = sn_hwperf_ioctl,
+};
+
+static struct miscdevice sn_hwperf_dev = {
+	MISC_DYNAMIC_MINOR,
+	"sn_hwperf",
+	&sn_hwperf_fops
+};
+
+static int sn_hwperf_init(void)
+{
+	u64 v;
+	int salr;
+	int e = 0;
+
+	/* single threaded, once-only initialization */
+	down(&sn_hwperf_init_mutex);
+	if (sn_hwperf_salheap) {
+		up(&sn_hwperf_init_mutex);
+		return e;
+	}
+
+	/*
+	 * The PROM code needs a fixed reference node. For convenience the
+	 * same node as the console I/O is used.
+	 */
+	sn_hwperf_master_nasid = (nasid_t) ia64_sn_get_console_nasid();
+
+	/*
+	 * Request the needed size and install the PROM scratch area.
+	 * The PROM keeps various tracking bits in this memory area.
+	 */
+	salr = ia64_sn_hwperf_op(sn_hwperf_master_nasid,
+				 (u64) SN_HWPERF_GET_HEAPSIZE, 0,
+				 (u64) sizeof(u64), (u64) &v, 0, 0, NULL);
+	if (salr != SN_HWPERF_OP_OK) {
+		e = -EINVAL;
+		goto out;
+	}
+
+	if ((sn_hwperf_salheap = vmalloc(v)) == NULL) {
+		e = -ENOMEM;
+		goto out;
+	}
+	salr = ia64_sn_hwperf_op(sn_hwperf_master_nasid,
+				 SN_HWPERF_INSTALL_HEAP, 0, v,
+				 (u64) sn_hwperf_salheap, 0, 0, NULL);
+	if (salr != SN_HWPERF_OP_OK) {
+		e = -EINVAL;
+		goto out;
+	}
+
+	salr = ia64_sn_hwperf_op(sn_hwperf_master_nasid,
+				 SN_HWPERF_OBJECT_COUNT, 0,
+				 sizeof(u64), (u64) &v, 0, 0, NULL);
+	if (salr != SN_HWPERF_OP_OK) {
+		e = -EINVAL;
+		goto out;
+	}
+	sn_hwperf_obj_cnt = (int)v;
+
+out:
+	if (e < 0 && sn_hwperf_salheap) {
+		vfree(sn_hwperf_salheap);
+		sn_hwperf_salheap = NULL;
+		sn_hwperf_obj_cnt = 0;
+	}
+
+	if (!e) {
+		/*
+		 * Register a dynamic misc device for ioctl. Platforms
+		 * supporting hotplug will create /dev/sn_hwperf, else
+		 * user can to look up the minor number in /proc/misc.
+		 */
+		if ((e = misc_register(&sn_hwperf_dev)) != 0) {
+			printk(KERN_ERR "sn_hwperf_init: misc register "
+			       "for \"sn_hwperf\" failed, err %d\n", e);
+		}
+	}
+
+	up(&sn_hwperf_init_mutex);
+	return e;
+}
+
+int sn_topology_open(struct inode *inode, struct file *file)
+{
+	int e;
+	struct seq_file *seq;
+	struct sn_hwperf_object_info *objbuf;
+	int nobj;
+
+	if ((e = sn_hwperf_enum_objects(&nobj, &objbuf)) == 0) {
+		e = seq_open(file, &sn_topology_seq_ops);
+		seq = file->private_data;
+		seq->private = objbuf;
+	}
+
+	return e;
+}
+
+int sn_topology_release(struct inode *inode, struct file *file)
+{
+	struct seq_file *seq = file->private_data;
+
+	if (seq->private)
+		vfree(seq->private);
+	return seq_release(inode, file);
+}
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-10-18 14:57:04 -07:00
+++ b/arch/ia64/sn/kernel/sn2/sn_proc_fs.c	2004-10-18 14:57:04 -07:00
@@ -3,74 +3,48 @@
  * 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>
 
 #ifdef CONFIG_PROC_FS
 #include <linux/proc_fs.h>
+#include <linux/seq_file.h>
 #include <asm/sn/sgi.h>
 #include <asm/sn/sn_sal.h>
 
-
-static int partition_id_read_proc(char *page, char **start, off_t off,
-		int count, int *eof, void *data) {
-
-	return sprintf(page, "%d\n", sn_local_partid());
+static int partition_id_show(struct seq_file *s, void *p)
+{
+	seq_printf(s, "%d\n", sn_local_partid());
+	return 0;
 }
 
-static struct proc_dir_entry * sgi_proc_dir;
-
-void
-register_sn_partition_id(void) {
-	struct proc_dir_entry *entry;
-
-	if (!sgi_proc_dir) {
-		sgi_proc_dir = proc_mkdir("sgi_sn", 0);
-	}
-	entry = create_proc_entry("partition_id", 0444, sgi_proc_dir);
-	if (entry) {
-		entry->nlink = 1;
-		entry->data = 0;
-		entry->read_proc = partition_id_read_proc;
-		entry->write_proc = NULL;
-	}
+static int partition_id_open(struct inode *inode, struct file *file)
+{
+	return single_open(file, partition_id_show, NULL);
 }
 
-static int
-system_serial_number_read_proc(char *page, char **start, off_t off,
-		int count, int *eof, void *data) {
-	return sprintf(page, "%s\n", sn_system_serial_number());
+static int system_serial_number_show(struct seq_file *s, void *p)
+{
+	seq_printf(s, "%s\n", sn_system_serial_number());
+	return 0;
 }
 
-static int
-licenseID_read_proc(char *page, char **start, off_t off,
-		int count, int *eof, void *data) {
-	return sprintf(page, "0x%lx\n",sn_partition_serial_number_val());
+static int system_serial_number_open(struct inode *inode, struct file *file)
+{
+	return single_open(file, system_serial_number_show, NULL);
 }
 
-void
-register_sn_serial_numbers(void) {
-	struct proc_dir_entry *entry;
+static int licenseID_show(struct seq_file *s, void *p)
+{
+	seq_printf(s, "0x%lx\n", sn_partition_serial_number_val());
+	return 0;
+}
 
-	if (!sgi_proc_dir) {
-		sgi_proc_dir = proc_mkdir("sgi_sn", 0);
-	}
-	entry = create_proc_entry("system_serial_number", 0444, sgi_proc_dir);
-	if (entry) {
-		entry->nlink = 1;
-		entry->data = 0;
-		entry->read_proc = system_serial_number_read_proc;
-		entry->write_proc = NULL;
-	}
-	entry = create_proc_entry("licenseID", 0444, sgi_proc_dir);
-	if (entry) {
-		entry->nlink = 1;
-		entry->data = 0;
-		entry->read_proc = licenseID_read_proc;
-		entry->write_proc = NULL;
-	}
+static int licenseID_open(struct inode *inode, struct file *file)
+{
+	return single_open(file, licenseID_show, NULL);
 }
 
 /*
@@ -81,48 +55,90 @@
  */
 int sn_force_interrupt_flag = 1;
 
-static int
-sn_force_interrupt_read_proc(char *page, char **start, off_t off,
-		int count, int *eof, void *data) {
-	if (sn_force_interrupt_flag) {
-		return sprintf(page, "Force interrupt is enabled\n");
-	}
-	return sprintf(page, "Force interrupt is disabled\n");
+static int sn_force_interrupt_show(struct seq_file *s, void *p)
+{
+	seq_printf(s, "Force interrupt is %s\n",
+		sn_force_interrupt_flag ? "enabled" : "disabled");
+	return 0;
 }
 
-static int 
-sn_force_interrupt_write_proc(struct file *file, const char *buffer,
-                                        unsigned long count, void *data)
+static ssize_t sn_force_interrupt_write_proc(struct file *file,
+		const __user char *buffer, size_t count, loff_t *data)
 {
-	if (*buffer == '0') {
-		sn_force_interrupt_flag = 0;
-	} else {
-		sn_force_interrupt_flag = 1;
-	}
-	return 1;
+	sn_force_interrupt_flag = (*buffer == '0') ? 0 : 1;
+	return count;
 }
 
-void
-register_sn_force_interrupt(void) {
-	struct proc_dir_entry *entry;
+static int sn_force_interrupt_open(struct inode *inode, struct file *file)
+{
+	return single_open(file, sn_force_interrupt_show, NULL);
+}
 
-	if (!sgi_proc_dir) {
-		sgi_proc_dir = proc_mkdir("sgi_sn", 0);
-	}
-	entry = create_proc_entry("sn_force_interrupt",0444, sgi_proc_dir);
-	if (entry) {
-		entry->nlink = 1;
-		entry->data = 0;
-		entry->read_proc = sn_force_interrupt_read_proc;
-		entry->write_proc = sn_force_interrupt_write_proc;
+static int coherence_id_show(struct seq_file *s, void *p)
+{
+	seq_printf(s, "%d\n", cpuid_to_coherence_id(smp_processor_id()));
+	return 0;
+}
+
+static int coherence_id_open(struct inode *inode, struct file *file)
+{
+	return single_open(file, coherence_id_show, NULL);
+}
+
+static struct proc_dir_entry *sn_procfs_create_entry(
+	const char *name, struct proc_dir_entry *parent,
+	int (*openfunc)(struct inode *, struct file *),
+	int (*releasefunc)(struct inode *, struct file *))
+{
+	struct proc_dir_entry *e = create_proc_entry(name, 0444, parent);
+
+	if (e) {
+		e->proc_fops = (struct file_operations *)kmalloc(
+			sizeof(struct file_operations), GFP_KERNEL);
+		if (e->proc_fops) {
+			memset(e->proc_fops, 0, sizeof(struct file_operations));
+			e->proc_fops->open = openfunc;
+			e->proc_fops->read = seq_read;
+			e->proc_fops->llseek = seq_lseek;
+			e->proc_fops->release = releasefunc;
+		}
 	}
+
+	return e;
 }
 
-void
-register_sn_procfs(void) {
-	register_sn_partition_id();
-	register_sn_serial_numbers();
-	register_sn_force_interrupt();
+/* /proc/sgi_sn/sn_topology uses seq_file, see sn_hwperf.c */
+extern int sn_topology_open(struct inode *, struct file *);
+extern int sn_topology_release(struct inode *, struct file *);
+
+void register_sn_procfs(void)
+{
+	static struct proc_dir_entry *sgi_proc_dir = NULL;
+	struct proc_dir_entry *e;
+
+	BUG_ON(sgi_proc_dir != NULL);
+	if (!(sgi_proc_dir = proc_mkdir("sgi_sn", 0)))
+		return;
+
+	sn_procfs_create_entry("partition_id", sgi_proc_dir,
+		partition_id_open, single_release);
+
+	sn_procfs_create_entry("system_serial_number", sgi_proc_dir,
+		system_serial_number_open, single_release);
+
+	sn_procfs_create_entry("licenseID", sgi_proc_dir, 
+		licenseID_open, single_release);
+
+	e = sn_procfs_create_entry("sn_force_interrupt", sgi_proc_dir, 
+		sn_force_interrupt_open, single_release);
+	if (e) 
+		e->proc_fops->write = sn_force_interrupt_write_proc;
+
+	sn_procfs_create_entry("coherence_id", sgi_proc_dir, 
+		coherence_id_open, single_release);
+	
+	sn_procfs_create_entry("sn_topology", sgi_proc_dir,
+		sn_topology_open, sn_topology_release);
 }
 
 #endif /* CONFIG_PROC_FS */
diff -Nru a/arch/ia64/sn/kernel/sn2/timer.c b/arch/ia64/sn/kernel/sn2/timer.c
--- a/arch/ia64/sn/kernel/sn2/timer.c	2004-10-18 14:56:32 -07:00
+++ b/arch/ia64/sn/kernel/sn2/timer.c	2004-10-18 14:56:32 -07:00
@@ -20,57 +20,16 @@
 
 
 extern unsigned long sn_rtc_cycles_per_second;
-static volatile unsigned long last_wall_rtc;
 
-static unsigned long rtc_offset;	/* updated only when xtime write-lock is held! */
-static long rtc_nsecs_per_cycle;
-static long rtc_per_timer_tick;
-
-static unsigned long
-getoffset(void)
-{
-	return rtc_offset + (GET_RTC_COUNTER() - last_wall_rtc)*rtc_nsecs_per_cycle;
-}
-
-
-static void
-update(long delta_nsec)
-{
-	unsigned long rtc_counter = GET_RTC_COUNTER();
-	unsigned long offset = rtc_offset + (rtc_counter - last_wall_rtc)*rtc_nsecs_per_cycle;
-
-	/* Be careful about signed/unsigned comparisons here: */
-	if (delta_nsec < 0 || (unsigned long) delta_nsec < offset)
-		rtc_offset = offset - delta_nsec;
-	else
-		rtc_offset = 0;
-	last_wall_rtc = rtc_counter;
-}
-
-
-static void
-reset(void)
-{
-	rtc_offset = 0;
-	last_wall_rtc = GET_RTC_COUNTER();
-}
-
-
-static struct time_interpolator sn2_interpolator = {
-	.get_offset =	getoffset,
-	.update =	update,
-	.reset =	reset
-};
+static struct time_interpolator sn2_interpolator;
 
 void __init
 sn_timer_init(void)
 {
 	sn2_interpolator.frequency = sn_rtc_cycles_per_second;
 	sn2_interpolator.drift = -1;	/* unknown */
+	sn2_interpolator.shift = 10;	/* RTC is 54 bits maximum shift is 10 */
+	sn2_interpolator.addr = RTC_COUNTER_ADDR;
+	sn2_interpolator.source = TIME_SOURCE_MMIO64;
 	register_time_interpolator(&sn2_interpolator);
-
-	rtc_per_timer_tick = sn_rtc_cycles_per_second / HZ;
-	rtc_nsecs_per_cycle = 1000000000 / sn_rtc_cycles_per_second;
-
-	last_wall_rtc = GET_RTC_COUNTER();
 }
diff -Nru a/arch/m32r/Kconfig b/arch/m32r/Kconfig
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/arch/m32r/Kconfig	2004-10-18 14:57:21 -07:00
@@ -0,0 +1,441 @@
+#
+# For a description of the syntax of this configuration file,
+# see Documentation/kbuild/kconfig-language.txt.
+#
+
+mainmenu "Linux Kernel Configuration"
+
+config M32R
+	bool
+	default y
+
+config SBUS
+	bool
+
+config UID16
+	bool
+	default y
+
+config GENERIC_ISA_DMA
+	bool
+	default y
+
+source "init/Kconfig"
+
+
+menu "Processor type and features"
+
+choice
+	prompt "Platform Type"
+	default PLAT_MAPPI
+
+config PLAT_MAPPI
+	bool "Mappi-I"
+	help
+	  The Mappi-I is an FPGA board for SOC (System-On-a-Chip) prototyping.
+	  You can operate a Linux system on this board by using an M32R
+	  softmacro core, which is a fully-synthesizable functional model
+	  described in Verilog-HDL.
+
+	  The Mappi-I board was the first platform, which had been used
+	  to port and develop a Linux system for the M32R processor.
+	  Currently, the Mappi-II, an heir to the Mappi-I, is available.
+
+config PLAT_USRV
+	bool "uServer"
+
+config PLAT_M32700UT
+	bool "M32700UT"
+	help
+	  The M3T-M32700UT is an evaluation board based on uT-Engine
+	  specification.  This board has an M32700 (Chaos) evaluation chip.
+	  You can say Y for SMP, because the M32700 is a single chip
+	  multiprocessor.
+
+config PLAT_OPSPUT
+	bool "OPSPUT"
+	help
+	  The OPSPUT is an evaluation board based on uT-Engine
+	  specification.  This board has a OPSP-REP chip.
+
+config PLAT_OAKS32R
+	bool "OAKS32R"
+	help
+	  The OAKS32R is a tiny, inexpensive evaluation board.
+	  Please note that if you say Y here and choose chip "M32102",
+	  say N for MMU and select a no-MMU version kernel, otherwise
+	  a kernel with MMU support will not work, because the M32102
+	  is a microcontroller for embedded systems and it has no MMU.
+
+config PLAT_MAPPI2
+       bool "Mappi-II(M3A-ZA36/M3A-ZA52)"
+
+endchoice
+
+choice
+	prompt "Processor family"
+	default CHIP_M32700
+
+config CHIP_M32700
+	bool "M32700 (Chaos)"
+
+config CHIP_M32102
+	bool "M32102"
+
+config CHIP_VDEC2
+       bool "VDEC2"
+
+config CHIP_OPSP
+       bool "OPSP"
+
+endchoice
+
+config MMU
+	bool "Support for memory management hardware"
+	depends on CHIP_M32700 || CHIP_VDEC2 || CHIP_OPSP
+	default y
+
+config TLB_ENTRIES
+       int "TLB Entries"
+       depends on CHIP_M32700 || CHIP_VDEC2 || CHIP_OPSP
+       default 32 if CHIP_M32700 || CHIP_OPSP
+       default 16 if CHIP_VDEC2
+
+
+config ISA_M32R
+        bool
+	depends on CHIP_M32102
+	default y
+
+config ISA_M32R2
+	bool
+	depends on CHIP_M32700 || CHIP_VDEC2 || CHIP_OPSP
+	default y
+
+config ISA_DSP_LEVEL2
+	bool
+	depends on CHIP_M32700 || CHIP_OPSP
+	default y
+
+config ISA_DUAL_ISSUE
+	bool
+	depends on CHIP_M32700 || CHIP_OPSP
+	default y
+
+config BUS_CLOCK
+	int "Bus Clock [Hz] (integer)"
+	default "70000000" if PLAT_MAPPI
+	default "25000000" if PLAT_USRV
+	default "50000000" if PLAT_M32700UT
+	default "50000000" if PLAT_OPSPUT
+	default "33333333" if PLAT_OAKS32R
+	default "20000000" if PLAT_MAPPI2
+
+config TIMER_DIVIDE
+	int "Timer divider (integer)"
+	default "128"
+
+config CPU_LITTLE_ENDIAN
+        bool "Generate little endian code"
+	default n
+
+config MEMORY_START
+	hex "Physical memory start address (hex)"
+	default "08000000" if PLAT_MAPPI || PLAT_MAPPI2
+	default "08000000" if PLAT_USRV
+	default "08000000" if PLAT_M32700UT
+	default "08000000" if PLAT_OPSPUT
+	default "01000000" if PLAT_OAKS32R
+
+config MEMORY_SIZE
+	hex "Physical memory size (hex)"
+	default "04000000" if PLAT_MAPPI || PLAT_MAPPI2
+	default "02000000" if PLAT_USRV
+	default "01000000" if PLAT_M32700UT
+	default "01000000" if PLAT_OPSPUT
+	default "00800000" if PLAT_OAKS32R
+
+config NOHIGHMEM
+	bool
+	default y
+
+config DISCONTIGMEM
+	bool "Internal RAM Support"
+	depends on CHIP_M32700 || CHIP_M32102 || CHIP_VDEC2 || CHIP_OPSP
+	default y
+
+config IRAM_START
+	hex "Internal memory start address (hex)"
+	default "00f00000"
+	depends on (CHIP_M32700 || CHIP_M32102 || CHIP_VDEC2 || CHIP_OPSP) && DISCONTIGMEM
+
+config IRAM_SIZE
+	hex "Internal memory size (hex)"
+	depends on (CHIP_M32700 || CHIP_M32102 || CHIP_VDEC2 || CHIP_OPSP) && DISCONTIGMEM
+	default "00080000" if CHIP_M32700
+	default "00010000" if CHIP_M32102 || CHIP_OPSP
+	default "00008000" if CHIP_VDEC2
+
+#
+# Define implied options from the CPU selection here
+#
+
+config RWSEM_GENERIC_SPINLOCK
+	bool
+	depends on M32R
+	default y
+
+config RWSEM_XCHGADD_ALGORITHM
+	bool
+	default n
+
+config PREEMPT
+	bool "Preemptible Kernel"
+	help
+	  This option reduces the latency of the kernel when reacting to
+	  real-time or interactive events by allowing a low priority process to
+	  be preempted even if it is in kernel mode executing a system call.
+	  This allows applications to run more reliably even when the system is
+	  under load.
+
+	  Say Y here if you are building a kernel for a desktop, embedded
+	  or real-time system.  Say N if you are unsure.
+
+config HAVE_DEC_LOCK
+	bool
+	depends on (SMP || PREEMPT)
+	default n
+
+config SMP
+	bool "Symmetric multi-processing support"
+	---help---
+	  This enables support for systems with more than one CPU. If you have
+	  a system with only one CPU, like most personal computers, say N. If
+	  you have a system with more than one CPU, say Y.
+
+	  If you say N here, the kernel will run on single and multiprocessor
+	  machines, but will use only one CPU of a multiprocessor machine. If
+	  you say Y here, the kernel will run on many, but not all,
+	  singleprocessor machines. On a singleprocessor machine, the kernel
+	  will run faster if you say N here.
+
+	  People using multiprocessor machines who say Y here should also say
+	  Y to "Enhanced Real Time Clock Support", below. The "Advanced Power
+	  Management" code will be disabled if you say Y here.
+
+	  See also the <file:Documentation/smp.tex>,
+	  <file:Documentation/smp.txt> and the SMP-HOWTO available at
+	  <http://www.linuxdoc.org/docs.html#howto>.
+
+	  If you don't know what to do here, say N.
+
+config CHIP_M32700_TS1
+	bool "Workaround code for the M32700 TS1 chip's bug"
+	depends on (CHIP_M32700 && SMP)
+	default n
+
+config NR_CPUS
+	int "Maximum number of CPUs (2-32)"
+	range 2 32
+	depends on SMP
+	default "2"
+	help
+	  This allows you to specify the maximum number of CPUs which this
+	  kernel will support.  The maximum supported value is 32 and the
+	  minimum value which makes sense is 2.
+
+	  This is purely to save memory - each supported CPU adds
+	  approximately eight kilobytes to the kernel image.
+
+# Common NUMA Features
+config NUMA
+	bool "Numa Memory Allocation Support"
+	depends on SMP
+	default n
+
+# turning this on wastes a bunch of space.
+# Summit needs it only when NUMA is on
+config BOOT_IOREMAP
+	bool
+	depends on NUMA
+	default n
+
+endmenu
+
+
+menu "Bus options (PCI, PCMCIA, EISA, MCA, ISA)"
+
+config PCI
+	bool "PCI support"
+	default n
+	help
+	  Find out whether you have a PCI motherboard. PCI is the name of a
+	  bus system, i.e. the way the CPU talks to the other stuff inside
+	  your box. Other bus systems are ISA, EISA, MicroChannel (MCA) or
+	  VESA. If you have PCI, say Y, otherwise N.
+
+	  The PCI-HOWTO, available from
+	  <http://www.linuxdoc.org/docs.html#howto>, contains valuable
+	  information about which PCI hardware does work under Linux and which
+	  doesn't.
+
+choice
+	prompt "PCI access mode"
+	depends on PCI
+	default PCI_GOANY
+
+config PCI_GOBIOS
+	bool "BIOS"
+	---help---
+	  On PCI systems, the BIOS can be used to detect the PCI devices and
+	  determine their configuration. However, some old PCI motherboards
+	  have BIOS bugs and may crash if this is done. Also, some embedded
+	  PCI-based systems don't have any BIOS at all. Linux can also try to
+	  detect the PCI hardware directly without using the BIOS.
+
+	  With this option, you can specify how Linux should detect the PCI
+	  devices. If you choose "BIOS", the BIOS will be used, if you choose
+	  "Direct", the BIOS won't be used, and if you choose "Any", the
+	  kernel will try the direct access method and falls back to the BIOS
+	  if that doesn't work. If unsure, go with the default, which is
+	  "Any".
+
+config PCI_GODIRECT
+	bool "Direct"
+
+config PCI_GOANY
+	bool "Any"
+
+endchoice
+
+config PCI_BIOS
+	bool
+	depends on PCI && (PCI_GOBIOS || PCI_GOANY)
+	default y
+
+config PCI_DIRECT
+	bool
+ 	depends on PCI && (PCI_GODIRECT || PCI_GOANY)
+	default y
+
+source "drivers/pci/Kconfig"
+
+config ISA
+	bool "ISA support"
+	help
+	  Find out whether you have ISA slots on your motherboard.  ISA is the
+	  name of a bus system, i.e. the way the CPU talks to the other stuff
+	  inside your box.  If you have ISA, say Y, otherwise N.
+
+source "drivers/pcmcia/Kconfig"
+
+source "drivers/pci/hotplug/Kconfig"
+
+endmenu
+
+
+menu "Executable file formats"
+
+source "fs/Kconfig.binfmt"
+
+endmenu
+
+source "drivers/Kconfig"
+
+source "fs/Kconfig"
+
+source "arch/m32r/oprofile/Kconfig"
+
+menu "Kernel hacking"
+
+config DEBUG_KERNEL
+	bool "Kernel debugging"
+	help
+	  Say Y here if you are developing drivers or trying to debug and
+	  identify kernel problems.
+
+config DEBUG_STACKOVERFLOW
+	bool "Check for stack overflows"
+	depends on DEBUG_KERNEL
+
+config DEBUG_SLAB
+	bool "Debug memory allocations"
+	depends on DEBUG_KERNEL
+	help
+	  Say Y here to have the kernel do limited verification on memory
+	  allocation as well as poisoning memory on free to catch use of freed
+	  memory.
+
+config DEBUG_IOVIRT
+	bool "Memory mapped I/O debugging"
+	depends on DEBUG_KERNEL
+	help
+	  Say Y here to get warned whenever an attempt is made to do I/O on
+	  obviously invalid addresses such as those generated when ioremap()
+	  calls are forgotten.  Memory mapped I/O will go through an extra
+	  check to catch access to unmapped ISA addresses, an access method
+	  that can still be used by old drivers that are being ported from
+	  2.0/2.2.
+
+config MAGIC_SYSRQ
+	bool "Magic SysRq key"
+	depends on DEBUG_KERNEL
+	help
+	  If you say Y here, you will have some control over the system even
+	  if the system crashes for example during kernel debugging (e.g., you
+	  will be able to flush the buffer cache to disk, reboot the system
+	  immediately or dump some status information). This is accomplished
+	  by pressing various keys while holding SysRq (Alt+PrintScreen). It
+	  also works on a serial console (on PC hardware at least), if you
+	  send a BREAK and then within 5 seconds a command keypress. The
+	  keys are documented in <file:Documentation/sysrq.txt>. Don't say Y
+	  unless you really know what this hack does.
+
+config DEBUG_SPINLOCK
+	bool "Spinlock debugging"
+	depends on DEBUG_KERNEL
+	help
+	  Say Y here and build SMP to catch missing spinlock initialization
+	  and certain other kinds of spinlock errors commonly made.  This is
+	  best used in conjunction with the NMI watchdog so that spinlock
+	  deadlocks are also debuggable.
+
+config DEBUG_PAGEALLOC
+	bool "Page alloc debugging"
+	depends on DEBUG_KERNEL
+	help
+	  Unmap pages from the kernel linear mapping after free_pages().
+	  This results in a large slowdown, but helps to find certain types
+	  of memory corruptions.
+
+config DEBUG_INFO
+	bool "Compile the kernel with debug info"
+	depends on DEBUG_KERNEL
+	help
+          If you say Y here the resulting kernel image will include
+	  debugging info resulting in a larger kernel image.
+	  Say Y here only if you plan to use gdb to debug the kernel.
+	  If you don't debug the kernel, you can say N.
+
+config DEBUG_SPINLOCK_SLEEP
+	bool "Sleep-inside-spinlock checking"
+	help
+	  If you say Y here, various routines which may sleep will become very
+	  noisy if they are called with a spinlock held.
+
+config FRAME_POINTER
+	bool "Compile the kernel with frame pointers"
+	help
+	  If you say Y here the resulting kernel image will be slightly larger
+	  and slower, but it will give very useful debugging information.
+	  If you don't debug the kernel, you can say N, but we may not be able
+	  to solve problems without frame pointers.
+
+endmenu
+
+source "security/Kconfig"
+
+source "crypto/Kconfig"
+
+source "lib/Kconfig"
+
diff -Nru a/arch/m32r/Makefile b/arch/m32r/Makefile
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/arch/m32r/Makefile	2004-10-18 14:57:24 -07:00
@@ -0,0 +1,55 @@
+#
+# m32r/Makefile
+#
+
+LDFLAGS		:=
+OBJCOPYFLAGS	:= -O binary -R .note -R .comment -S
+LDFLAGS_vmlinux	:= -e startup_32
+LDFLAGS_BLOB	:= --format binary --oformat elf32-m32r
+
+CFLAGS += -pipe -fno-schedule-insns
+CFLAGS_KERNEL += -mmodel=medium
+CFLAGS_MODULE += -mmodel=large
+
+ifdef CONFIG_CHIP_VDEC2
+cflags-$(CONFIG_ISA_M32R2)	+= -DNO_FPU -Wa,-bitinst
+aflags-$(CONFIG_ISA_M32R2)	+= -DNO_FPU -Wa,-bitinst
+else
+cflags-$(CONFIG_ISA_M32R2)	+= -DNO_FPU -m32r2
+aflags-$(CONFIG_ISA_M32R2)	+= -DNO_FPU -m32r2
+endif
+
+cflags-$(CONFIG_ISA_M32R)	+= -DNO_FPU
+aflags-$(CONFIG_ISA_M32R)	+= -DNO_FPU -Wa,-no-bitinst
+
+CFLAGS += $(cflags-y)
+AFLAGS += $(aflags-y)
+
+CHECKFLAGS	:= $(CHECK) -D__m32r__
+
+head-y	:= arch/m32r/kernel/head.o arch/m32r/kernel/init_task.o
+
+LIBGCC	:= $(shell $(CC) $(CFLAGS) -print-libgcc-file-name)
+
+libs-y	+= arch/m32r/lib/ $(LIBGCC)
+core-y	+= arch/m32r/kernel/	\
+	   arch/m32r/mm/	\
+	   arch/m32r/boot/
+
+drivers-$(CONFIG_OPROFILE)	+= arch/m32r/oprofile/
+
+boot := arch/m32r/boot
+
+.PHONY: zImage
+
+zImage: vmlinux
+	$(Q)$(MAKE) $(build)=$(boot) $(boot)/$@
+
+compressed: zImage
+
+archclean:
+	$(Q)$(MAKE) $(clean)=$(boot)
+
+define archhelp
+	@echo '  zImage			- Compressed kernel image (arch/m32r/boot/zImage)'
+endef
diff -Nru a/arch/m32r/boot/Makefile b/arch/m32r/boot/Makefile
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/arch/m32r/boot/Makefile	2004-10-18 14:57:23 -07:00
@@ -0,0 +1,19 @@
+#
+# arch/m32r/boot/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.
+
+targets := zImage
+subdir- := compressed
+
+obj-y	:= setup.o
+
+$(obj)/zImage: $(obj)/compressed/vmlinux FORCE
+	$(call if_changed,objcopy)
+	@echo 'Kernel: $@ is ready'
+
+$(obj)/compressed/vmlinux: FORCE
+	$(Q)$(MAKE) $(build)=$(obj)/compressed $@
+
diff -Nru a/arch/m32r/boot/compressed/Makefile b/arch/m32r/boot/compressed/Makefile
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/arch/m32r/boot/compressed/Makefile	2004-10-18 14:57:21 -07:00
@@ -0,0 +1,38 @@
+#
+# linux/arch/sh/boot/compressed/Makefile
+#
+# create a compressed vmlinux image from the original vmlinux
+#
+
+targets		:= vmlinux vmlinux.bin vmlinux.bin.gz head.o misc.o \
+		   m32r-sio.o piggy.o vmlinux.lds
+EXTRA_AFLAGS	:= -traditional
+
+OBJECTS = $(obj)/head.o $(obj)/misc.o $(obj)/m32r_sio.o
+
+#
+# IMAGE_OFFSET is the load offset of the compression loader
+#
+#IMAGE_OFFSET := $(shell printf "0x%08x" $$[$(CONFIG_MEMORY_START)+0x2000])
+#IMAGE_OFFSET := $(shell printf "0x%08x" $$[$(CONFIG_MEMORY_START)+0x00400000])
+
+LDFLAGS_vmlinux := -T
+
+$(obj)/vmlinux: $(obj)/vmlinux.lds $(OBJECTS) $(obj)/piggy.o FORCE
+	$(call if_changed,ld)
+	@:
+
+$(obj)/vmlinux.bin: vmlinux FORCE
+	$(call if_changed,objcopy)
+
+$(obj)/vmlinux.bin.gz: $(obj)/vmlinux.bin FORCE
+	$(call if_changed,gzip)
+
+$(obj)/vmlinux.lds: $(obj)/vmlinux.lds.S FORCE
+	$(CPP) $(EXTRA_AFLAGS) -C -P -I include $< >$@
+
+LDFLAGS_piggy.o := -r --format binary --oformat elf32-m32r-linux -T
+OBJCOPYFLAGS += -R .empty_zero_page
+
+$(obj)/piggy.o: $(obj)/vmlinux.scr $(obj)/vmlinux.bin.gz FORCE
+	$(call if_changed,ld)
diff -Nru a/arch/m32r/boot/compressed/boot.h b/arch/m32r/boot/compressed/boot.h
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/arch/m32r/boot/compressed/boot.h	2004-10-18 14:57:24 -07:00
@@ -0,0 +1,59 @@
+/*
+ * 1. load vmlinuz
+ *
+ * CONFIG_MEMORY_START  	+-----------------------+
+ *				|        vmlinuz	|
+ *				+-----------------------+
+ * 2. decompressed
+ *
+ * CONFIG_MEMORY_START  	+-----------------------+
+ *				|        vmlinuz	|
+ *				+-----------------------+
+ *				|			|
+ * BOOT_RELOC_ADDR		+-----------------------+
+ *				|		 	|
+ * KERNEL_DECOMPRESS_ADDR 	+-----------------------+
+ *				|  	vmlinux		|
+ *				+-----------------------+
+ *
+ * 3. relocate copy & jump code
+ *
+ * CONFIG_MEMORY_START  	+-----------------------+
+ *				|        vmlinuz	|
+ *				+-----------------------+
+ *				|			|
+ * BOOT_RELOC_ADDR		+-----------------------+
+ *				|    boot(copy&jump)	|
+ * KERNEL_DECOMPRESS_ADDR 	+-----------------------+
+ *				|  	vmlinux		|
+ *				+-----------------------+
+ *
+ * 4. relocate decompressed kernel
+ *
+ * CONFIG_MEMORY_START  	+-----------------------+
+ *				|        vmlinux	|
+ *				+-----------------------+
+ *				|			|
+ * BOOT_RELOC_ADDR		+-----------------------+
+ *				|     boot(copy&jump) 	|
+ * KERNEL_DECOMPRESS_ADDR 	+-----------------------+
+ *				|  			|
+ *				+-----------------------+
+ *
+ */
+#ifdef __ASSEMBLY__
+#define __val(x)	x
+#else
+#define __val(x)	(x)
+#endif
+
+#define DECOMPRESS_OFFSET_BASE	__val(0x00900000)
+#define BOOT_RELOC_SIZE		__val(0x00001000)
+
+#define KERNEL_EXEC_ADDR	__val(CONFIG_MEMORY_START)
+#define KERNEL_DECOMPRESS_ADDR	__val(CONFIG_MEMORY_START + \
+				      DECOMPRESS_OFFSET_BASE + BOOT_RELOC_SIZE)
+#define KERNEL_ENTRY		__val(CONFIG_MEMORY_START + 0x1000)
+
+#define BOOT_EXEC_ADDR		__val(CONFIG_MEMORY_START)
+#define BOOT_RELOC_ADDR		__val(CONFIG_MEMORY_START + DECOMPRESS_OFFSET_BASE)
diff -Nru a/arch/m32r/boot/compressed/head.S b/arch/m32r/boot/compressed/head.S
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/arch/m32r/boot/compressed/head.S	2004-10-18 14:57:22 -07:00
@@ -0,0 +1,115 @@
+/*
+ *  linux/arch/m32r/boot/compressed/head.S
+ *
+ *  Copyright (c) 2001-2003	Hiroyuki Kondo, Hirokazu Takata,
+ *				Hitoshi Yamamoto, Takeo Takahashi
+ *  Copyright (c) 2004		Hirokazu Takata
+ */
+
+	.text
+#include <linux/config.h>
+#include <linux/linkage.h>
+#include <asm/addrspace.h>
+#include <asm/page.h>
+#include <asm/assembler.h>
+
+	.global	startup
+	__ALIGN
+startup:
+	ldi	r0, #0x0000			/* SPI, disable EI */
+	mvtc	r0, psw
+
+/*
+ * Clear BSS first so that there are no surprises...
+ */
+#ifdef CONFIG_ISA_DUAL_ISSUE
+
+	LDIMM	(r2, __bss_start)
+	LDIMM	(r3, _end)
+	sub	r3, r2		; BSS size in bytes
+	; R4 = BSS size in longwords (rounded down)
+	mv	r4, r3		    ||	ldi	r1, #0
+	srli	r4, #4		    ||	addi	r2, #-4
+	beqz	r4, .Lendloop1
+.Lloop1:
+#ifndef CONFIG_CHIP_M32310
+	; Touch memory for the no-write-allocating cache.
+	ld	r0, @(4,r2)
+#endif
+	st	r1, @+r2	    ||	addi	r4, #-1
+	st	r1, @+r2
+	st	r1, @+r2
+	st	r1, @+r2	    ||	cmpeq	r1, r4	; R4 = 0?
+	bnc	.Lloop1
+.Lendloop1:
+	and3	r4, r3, #15
+	addi	r2, #4
+	beqz	r4, .Lendloop2
+.Lloop2:
+	stb	r1, @r2		    ||	addi	r4, #-1
+	addi	r2, #1
+	bnez	r4, .Lloop2
+.Lendloop2:
+
+#else /* not CONFIG_ISA_DUAL_ISSUE */
+
+	LDIMM	(r2, __bss_start)
+	LDIMM	(r3, _end)
+	sub	r3, r2		; BSS size in bytes
+	mv	r4, r3
+	srli	r4, #2		; R4 = BSS size in longwords (rounded down)
+	ldi	r1, #0		; clear R1 for longwords store
+	addi	r2, #-4		; account for pre-inc store
+	beqz	r4, .Lendloop1	; any more to go?
+.Lloop1:
+	st	r1, @+r2	; yep, zero out another longword
+	addi	r4, #-1		; decrement count
+	bnez	r4, .Lloop1	; go do some more
+.Lendloop1:
+	and3	r4, r3, #3	; get no. of remaining BSS bytes to clear
+	addi	r2, #4		; account for pre-inc store
+	beqz	r4, .Lendloop2	; any more to go?
+.Lloop2:
+	stb	r1, @r2		; yep, zero out another byte
+	addi	r2, #1		; bump address
+	addi	r4, #-1		; decrement count
+	bnez	r4, .Lloop2	; go do some more
+.Lendloop2:
+
+#endif /* not CONFIG_ISA_DUAL_ISSUE */
+
+	seth	r0, #shigh(stack_start)
+	ld	sp, @(r0, low(stack_start))	/* set stack point */
+
+/*
+ * decompress the kernel
+ */
+	bl	decompress_kernel
+
+#if defined(CONFIG_CHIP_M32700)
+	/* Cache flush */
+	ldi	r0, -1
+	ldi	r1, 0xd0	; invalidate i-cache, copy back d-cache
+	stb	r1, @r0
+#else
+#error "put your cache flush function, please"
+#endif
+        seth	r0, #high(CONFIG_MEMORY_START)
+        or3	r0, r0, #0x2000
+        jmp	r0
+
+	.balign 512
+fake_headers_as_bzImage:
+	.short	0
+	.ascii	"HdrS"
+	.short	0x0202
+	.short	0
+	.short	0
+	.byte	0x00, 0x10
+	.short	0
+	.byte	0
+	.byte	1
+	.byte	0x00, 0x80
+	.long	0
+	.long	0
+
diff -Nru a/arch/m32r/boot/compressed/install.sh b/arch/m32r/boot/compressed/install.sh
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/arch/m32r/boot/compressed/install.sh	2004-10-18 14:57:24 -07:00
@@ -0,0 +1,57 @@
+#!/bin/sh
+#
+# arch/sh/boot/install.sh
+#
+# 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) 1995 by Linus Torvalds
+#
+# Adapted from code in arch/i386/boot/Makefile by H. Peter Anvin
+# Adapted from code in arch/i386/boot/install.sh by Russell King
+# Adapted from code in arch/arm/boot/install.sh by Stuart Menefy
+# Adapted from code in arch/sh/boot/install.sh by Takeo Takahashi
+#
+# "make install" script for sh architecture
+#
+# Arguments:
+#   $1 - kernel version
+#   $2 - kernel image file
+#   $3 - kernel map file
+#   $4 - default install path (blank if root directory)
+#
+
+# User may have a custom install script
+
+if [ -x /sbin/installkernel ]; then
+  exec /sbin/installkernel "$@"
+fi
+
+if [ "$2" = "zImage" ]; then
+# Compressed install
+  echo "Installing compressed kernel"
+  if [ -f $4/vmlinuz-$1 ]; then
+    mv $4/vmlinuz-$1 $4/vmlinuz.old
+  fi
+
+  if [ -f $4/System.map-$1 ]; then
+    mv $4/System.map-$1 $4/System.old
+  fi
+
+  cat $2 > $4/vmlinuz-$1
+  cp $3 $4/System.map-$1
+else
+# Normal install
+  echo "Installing normal kernel"
+  if [ -f $4/vmlinux-$1 ]; then
+    mv $4/vmlinux-$1 $4/vmlinux.old
+  fi
+
+  if [ -f $4/System.map ]; then
+    mv $4/System.map $4/System.old
+  fi
+
+  cat $2 > $4/vmlinux-$1
+  cp $3 $4/System.map
+fi
diff -Nru a/arch/m32r/boot/compressed/m32r_sio.c b/arch/m32r/boot/compressed/m32r_sio.c
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/arch/m32r/boot/compressed/m32r_sio.c	2004-10-18 14:57:23 -07:00
@@ -0,0 +1,53 @@
+/*
+ * arch/m32r/boot/compressed/m32r_sio.c
+ *
+ * 2003-02-12:	Takeo Takahashi
+ *
+ */
+
+#include <linux/config.h>
+#include <asm/m32r.h>
+#include <asm/io.h>
+
+void putc(char c);
+
+int puts(const char *s)
+{
+	char c;
+	while ((c = *s++)) putc(c);
+	return 0;
+}
+
+#if defined(CONFIG_PLAT_M32700UT_Alpha) || defined(CONFIG_PLAT_M32700UT)
+#define USE_FPGA_MAP	0
+
+#if USE_FPGA_MAP
+/*
+ * fpga configuration program uses MMU, and define map as same as
+ * M32104 uT-Engine board.
+ */
+#define BOOT_SIO0STS	(volatile unsigned short *)(0x02c00000 + 0x20006)
+#define BOOT_SIO0TXB	(volatile unsigned short *)(0x02c00000 + 0x2000c)
+#else
+#undef PLD_BASE
+#define PLD_BASE	0xa4c00000
+#define BOOT_SIO0STS	PLD_ESIO0STS
+#define BOOT_SIO0TXB	PLD_ESIO0TXB
+#endif
+
+void putc(char c)
+{
+
+	while ((*BOOT_SIO0STS & 0x3) != 0x3) ;
+	if (c == '\n') {
+		*BOOT_SIO0TXB = '\r';
+		while ((*BOOT_SIO0STS & 0x3) != 0x3) ;
+	}
+	*BOOT_SIO0TXB = c;
+}
+#else
+void putc(char c)
+{
+	/* do nothing */
+}
+#endif
diff -Nru a/arch/m32r/boot/compressed/misc.c b/arch/m32r/boot/compressed/misc.c
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/arch/m32r/boot/compressed/misc.c	2004-10-18 14:57:21 -07:00
@@ -0,0 +1,223 @@
+/*
+ * arch/m32r/boot/compressed/misc.c
+ *
+ * This is a collection of several routines from gzip-1.0.3
+ * adapted for Linux.
+ *
+ * malloc by Hannu Savolainen 1993 and Matthias Urlichs 1994
+ *
+ * Adapted for SH by Stuart Menefy, Aug 1999
+ *
+ * Modified to use standard LinuxSH BIOS by Greg Banks 7Jul2000
+ *
+ * 2003-02-12:	Support M32R by Takeo Takahashi
+ * 		This is based on arch/sh/boot/compressed/misc.c.
+ */
+
+#include <linux/config.h>
+#include <linux/string.h>
+
+/*
+ * gzip declarations
+ */
+
+#define OF(args)  args
+#define STATIC static
+
+#undef memset
+#undef memcpy
+#define memzero(s, n)     memset ((s), 0, (n))
+
+typedef unsigned char  uch;
+typedef unsigned short ush;
+typedef unsigned long  ulg;
+
+#define WSIZE 0x8000		/* Window size must be at least 32k, */
+				/* and a power of two */
+
+static uch *inbuf;	     /* input buffer */
+static uch window[WSIZE];    /* Sliding window buffer */
+
+static unsigned insize;  /* valid bytes in inbuf */
+static unsigned inptr;   /* index of next byte to be processed in inbuf */
+static unsigned outcnt;  /* bytes in output buffer */
+
+/* gzip flag byte */
+#define ASCII_FLAG   0x01 /* bit 0 set: file probably ASCII text */
+#define CONTINUATION 0x02 /* bit 1 set: continuation of multi-part gzip file */
+#define EXTRA_FIELD  0x04 /* bit 2 set: extra field present */
+#define ORIG_NAME    0x08 /* bit 3 set: original file name present */
+#define COMMENT      0x10 /* bit 4 set: file comment present */
+#define ENCRYPTED    0x20 /* bit 5 set: file is encrypted */
+#define RESERVED     0xC0 /* bit 6,7:   reserved */
+
+#define get_byte()  (inptr < insize ? inbuf[inptr++] : fill_inbuf())
+
+/* Diagnostic functions */
+#ifdef DEBUG
+#  define Assert(cond,msg) {if(!(cond)) error(msg);}
+#  define Trace(x) fprintf x
+#  define Tracev(x) {if (verbose) fprintf x ;}
+#  define Tracevv(x) {if (verbose>1) fprintf x ;}
+#  define Tracec(c,x) {if (verbose && (c)) fprintf x ;}
+#  define Tracecv(c,x) {if (verbose>1 && (c)) fprintf x ;}
+#else
+#  define Assert(cond,msg)
+#  define Trace(x)
+#  define Tracev(x)
+#  define Tracevv(x)
+#  define Tracec(c,x)
+#  define Tracecv(c,x)
+#endif
+
+static int  fill_inbuf(void);
+static void flush_window(void);
+static void error(char *m);
+static void gzip_mark(void **);
+static void gzip_release(void **);
+
+extern char input_data[];
+extern int input_len;
+
+static long bytes_out;
+static uch *output_data;
+static unsigned long output_ptr;
+
+
+static void *malloc(int size);
+static void free(void *where);
+static void error(char *m);
+static void gzip_mark(void **);
+static void gzip_release(void **);
+
+extern int puts(const char *);
+
+extern int _text;		/* Defined in vmlinux.lds.S */
+extern int _end;
+static unsigned long free_mem_ptr;
+static unsigned long free_mem_end_ptr;
+
+#define HEAP_SIZE             0x10000
+
+#include "../../../../lib/inflate.c"
+
+static void *malloc(int size)
+{
+	void *p;
+
+	if (size <0) error("Malloc error\n");
+	if (free_mem_ptr == 0) error("Memory error\n");
+
+	free_mem_ptr = (free_mem_ptr + 3) & ~3;	/* Align */
+
+	p = (void *)free_mem_ptr;
+	free_mem_ptr += size;
+
+	if (free_mem_ptr >= free_mem_end_ptr)
+		error("\nOut of memory\n");
+
+	return p;
+}
+
+static void free(void *where)
+{	/* Don't care */
+}
+
+static void gzip_mark(void **ptr)
+{
+	*ptr = (void *) free_mem_ptr;
+}
+
+static void gzip_release(void **ptr)
+{
+	free_mem_ptr = (long) *ptr;
+}
+
+void* memset(void* s, int c, size_t n)
+{
+	int i;
+	char *ss = (char*)s;
+
+	for (i=0;i<n;i++) ss[i] = c;
+	return s;
+}
+
+void* memcpy(void* __dest, __const void* __src,
+			    size_t __n)
+{
+	int i;
+	char *d = (char *)__dest, *s = (char *)__src;
+
+	for (i=0;i<__n;i++) d[i] = s[i];
+	return __dest;
+}
+
+/* ===========================================================================
+ * Fill the input buffer. This is called only when the buffer is empty
+ * and at least one byte is really needed.
+ */
+static int fill_inbuf(void)
+{
+	if (insize != 0) {
+		error("ran out of input data\n");
+	}
+
+	inbuf = input_data;
+	insize = input_len;
+	inptr = 1;
+	return inbuf[0];
+}
+
+/* ===========================================================================
+ * Write the output window window[0..outcnt-1] and update crc and bytes_out.
+ * (Used for the decompressed data only.)
+ */
+static void flush_window(void)
+{
+    ulg c = crc;         /* temporary variable */
+    unsigned n;
+    uch *in, *out, ch;
+
+    in = window;
+    out = &output_data[output_ptr];
+    for (n = 0; n < outcnt; n++) {
+	    ch = *out++ = *in++;
+	    c = crc_32_tab[((int)c ^ ch) & 0xff] ^ (c >> 8);
+    }
+    crc = c;
+    bytes_out += (ulg)outcnt;
+    output_ptr += (ulg)outcnt;
+    outcnt = 0;
+}
+
+static void error(char *x)
+{
+	puts("\n\n");
+	puts(x);
+	puts("\n\n -- System halted");
+
+	while(1);	/* Halt */
+}
+
+#define STACK_SIZE (4096)
+long user_stack [STACK_SIZE];
+long* stack_start = &user_stack[STACK_SIZE];
+
+/* return decompressed size */
+long decompress_kernel(void)
+{
+	insize = 0;
+	inptr = 0;
+	bytes_out = 0;
+	outcnt = 0;
+	output_data = 0;
+	output_ptr = CONFIG_MEMORY_START + 0x2000;
+	free_mem_ptr = (unsigned long)&_end;
+	free_mem_end_ptr = free_mem_ptr + HEAP_SIZE;
+
+	makecrc();
+	puts("Uncompressing Linux... ");
+	gunzip();
+	puts("Ok, booting the kernel.\n");
+	return bytes_out;
+}
diff -Nru a/arch/m32r/boot/compressed/vmlinux.lds.S b/arch/m32r/boot/compressed/vmlinux.lds.S
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/arch/m32r/boot/compressed/vmlinux.lds.S	2004-10-18 14:57:23 -07:00
@@ -0,0 +1,23 @@
+#include <linux/config.h>
+
+OUTPUT_ARCH(m32r)
+ENTRY(startup)
+SECTIONS
+{
+  . = CONFIG_MEMORY_START + 0x00400000;
+
+  _text = .;
+  .text : { *(.text) } = 0
+  .rodata : { *(.rodata) }
+  _etext = .;
+
+  . = ALIGN(32) + (. & (32 - 1));
+  .data : { *(.data) }
+  _edata  =  .;
+
+  . = ALIGN(32 / 8);
+  __bss_start = .;
+  .bss : { *(.bss) }
+  . = ALIGN(32 / 8);
+  _end = . ;
+}
diff -Nru a/arch/m32r/boot/compressed/vmlinux.scr b/arch/m32r/boot/compressed/vmlinux.scr
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/arch/m32r/boot/compressed/vmlinux.scr	2004-10-18 14:57:22 -07:00
@@ -0,0 +1,9 @@
+SECTIONS
+{
+  .data : {
+	input_len = .;
+	LONG(input_data_end - input_data) input_data = .;
+	*(.data)
+	input_data_end = .;
+	}
+}
diff -Nru a/arch/m32r/boot/setup.S b/arch/m32r/boot/setup.S
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/arch/m32r/boot/setup.S	2004-10-18 14:57:23 -07:00
@@ -0,0 +1,162 @@
+/*
+ *  linux/arch/m32r/boot/setup.S -- A setup code.
+ *
+ *  Copyright (C) 2001, 2002  Hiroyuki Kondo, Hirokazu Takata,
+ *  and Hitoshi Yamamoto
+ *
+ */
+/* $Id$ */
+
+#include <linux/linkage.h>
+#include <asm/segment.h>
+#include <asm/page.h>
+#include <asm/pgtable.h>
+
+#include <linux/config.h>
+#include <asm/assembler.h>
+#include <asm/mmu_context.h>
+#include <asm/m32r.h>
+
+/*
+ * References to members of the boot_cpu_data structure.
+ */
+
+#define CPU_PARAMS	boot_cpu_data
+#define M32R_MCICAR	 0xfffffff0
+#define M32R_MCDCAR	 0xfffffff4
+#define	M32R_MCCR 	 0xfffffffc
+#define M32R_BSCR0	 0xffffffd2
+
+;BSEL
+#define BSEL0CR0	 0x00ef5000
+#define	BSEL0CR1	 0x00ef5004
+#define BSEL1CR0	 0x00ef5100
+#define BSEL1CR1	 0x00ef5104
+#define BSEL0CR0_VAL	 0x00000000
+#define BSEL0CR1_VAL	 0x01200100
+#define BSEL1CR0_VAL	 0x01018000
+#define BSEL1CR1_VAL	 0x00200001
+
+;SDRAMC
+#define SDRAMC_SDRF0	 0x00ef6000
+#define SDRAMC_SDRF1	 0x00ef6004
+#define SDRAMC_SDIR0	 0x00ef6008
+#define SDRAMC_SDIR1	 0x00ef600c
+#define SDRAMC_SD0ADR	 0x00ef6020
+#define SDRAMC_SD0ER	 0x00ef6024
+#define SDRAMC_SD0TR	 0x00ef6028
+#define SDRAMC_SD0MOD	 0x00ef602c
+#define SDRAMC_SD1ADR	 0x00ef6040
+#define SDRAMC_SD1ER	 0x00ef6044
+#define SDRAMC_SD1TR	 0x00ef6048
+#define SDRAMC_SD1MOD	 0x00ef604c
+#define SDRAM0		 0x18000000
+#define SDRAM1		 0x1c000000
+
+/*------------------------------------------------------------------------
+ * start up
+ */
+
+/*------------------------------------------------------------------------
+ * Kernel entry
+ */
+	.section .boot, "ax"
+ENTRY(boot)
+
+/* Set cache mode */
+#if defined(CONFIG_CHIP_XNUX2)
+	ldi	r0, #-2              ;LDIMM	(r0, M32R_MCCR)
+	ldi	r1, #0x0101		; cache on (with invalidation)
+;	ldi	r1, #0x00		; cache off
+	sth	r1, @r0
+#elif defined(CONFIG_CHIP_M32700) || defined(CONFIG_CHIP_VDEC2) \
+    || defined(CONFIG_CHIP_OPSP)
+	ldi	r0, #-4              ;LDIMM	(r0, M32R_MCCR)
+	ldi	r1, #0x73		; cache on (with invalidation)
+;	ldi	r1, #0x00		; cache off
+	st	r1, @r0
+#else
+#error unknown chip configuration
+#endif
+
+#ifdef CONFIG_SMP
+	;; if not BSP (CPU#0) goto AP_loop
+	seth	r5, #shigh(M32R_CPUID_PORTL)
+	ld      r5, @(low(M32R_CPUID_PORTL), r5)
+	bnez	r5, AP_loop
+#if !defined(CONFIG_PLAT_USRV)
+	;; boot AP
+	ld24	r5, #0xeff2f8		; IPICR7
+	ldi	r6, #0x2		; IPI to CPU1
+	st	r6, @r5
+#endif
+#endif
+
+/*
+ *  Now, Jump to stext
+ *        if with MMU,    TLB on.
+ *        if with no MMU, only jump.
+ */
+ 	.global	eit_vector
+mmu_on:
+	LDIMM	(r13, stext)
+#ifdef CONFIG_MMU
+	bl	init_tlb
+	LDIMM	(r2, eit_vector)		; set EVB(cr5)
+	mvtc    r2, cr5
+	seth	r0, #high(MMU_REG_BASE)		; Set MMU_REG_BASE higher
+	or3     r0, r0, #low(MMU_REG_BASE)	; Set MMU_REG_BASE lower
+	ldi     r1, #0x01
+	st      r1, @(MATM_offset,r0)		; Set MATM (T bit ON)
+	ld      r0, @(MATM_offset,r0)		; Check
+#else
+	seth	r0,#high(M32R_MCDCAR)
+	or3	r0,r0,#low(M32R_MCDCAR)
+	ld24	r1,#0x8080
+	st	r1,@r0
+#endif	/* CONFIG_MMU */
+	jmp	r13
+	nop
+	nop
+
+#ifdef CONFIG_SMP
+/*
+ * AP wait loop
+ */
+ENTRY(AP_loop)
+	;; disable interrupt
+	clrpsw	#0x40
+	;; reset EVB
+	LDIMM	(r4, _AP_RE)
+	seth	r5, #high(__PAGE_OFFSET)
+	or3	r5, r5, #low(__PAGE_OFFSET)
+	not	r5, r5
+	and	r4, r5
+	mvtc	r4, cr5
+	;; disable maskable interrupt
+	seth	r4, #high(M32R_ICU_IMASK_PORTL)
+	or3	r4, r4, #low(M32R_ICU_IMASK_PORTL)
+	ldi	r5, #0
+	st	r5, @r4
+	ld	r5, @r4
+	;; enable only IPI
+	setpsw	#0x40
+    	;; LOOOOOOOOOOOOOOP!!!
+	.fillinsn
+2:
+	nop
+	nop
+	bra	2b
+	nop
+	nop
+
+#ifdef CONFIG_CHIP_M32700_TS1
+	.global	dcache_dummy
+	.balign	16, 0
+dcache_dummy:
+	.byte	16
+#endif	/* CONFIG_CHIP_M32700_TS1 */
+#endif	/* CONFIG_SMP */
+
+	.end
+
diff -Nru a/arch/m32r/defconfig b/arch/m32r/defconfig
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/arch/m32r/defconfig	2004-10-18 14:57:23 -07:00
@@ -0,0 +1,635 @@
+#
+# Automatically generated make config: don't edit
+#
+CONFIG_M32R=y
+CONFIG_UID16=y
+CONFIG_GENERIC_ISA_DMA=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=y
+CONFIG_IKCONFIG=y
+# CONFIG_IKCONFIG_PROC is not set
+CONFIG_EMBEDDED=y
+# CONFIG_KALLSYMS is not set
+# CONFIG_FUTEX is not set
+# CONFIG_EPOLL is not set
+CONFIG_IOSCHED_NOOP=y
+# CONFIG_IOSCHED_AS is not set
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+
+#
+# Loadable module support
+#
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+# CONFIG_MODULE_FORCE_UNLOAD is not set
+CONFIG_OBSOLETE_MODPARM=y
+# CONFIG_MODVERSIONS is not set
+CONFIG_KMOD=y
+
+#
+# Processor type and features
+#
+# CONFIG_PLAT_MAPPI is not set
+# CONFIG_PLAT_USRV is not set
+CONFIG_PLAT_M32700UT=y
+# CONFIG_PLAT_OPSPUT is not set
+# CONFIG_PLAT_OAKS32R is not set
+# CONFIG_PLAT_MAPPI2 is not set
+CONFIG_CHIP_M32700=y
+# CONFIG_CHIP_M32102 is not set
+# CONFIG_CHIP_VDEC2 is not set
+# CONFIG_CHIP_OPSP is not set
+CONFIG_MMU=y
+CONFIG_TLB_ENTRIES=32
+CONFIG_ISA_M32R2=y
+CONFIG_ISA_DSP_LEVEL2=y
+CONFIG_ISA_DUAL_ISSUE=y
+CONFIG_BUS_CLOCK=50000000
+CONFIG_TIMER_DIVIDE=128
+# CONFIG_CPU_LITTLE_ENDIAN is not set
+CONFIG_MEMORY_START=0x08000000
+CONFIG_MEMORY_SIZE=0x01000000
+CONFIG_NOHIGHMEM=y
+# CONFIG_DISCONTIGMEM is not set
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+# CONFIG_RWSEM_XCHGADD_ALGORITHM is not set
+CONFIG_PREEMPT=y
+# CONFIG_HAVE_DEC_LOCK is not set
+# CONFIG_SMP is not set
+
+#
+# M32R drivers
+#
+# CONFIG_M32RPCC is not set
+CONFIG_M32R_CFC=y
+CONFIG_M32700UT_CFC=y
+CONFIG_CFC_NUM=1
+# CONFIG_MTD_M32R is not set
+CONFIG_M32R_SMC91111=y
+CONFIG_M32700UT_DS1302=y
+
+#
+# Power management options (ACPI, APM)
+#
+# CONFIG_PM is not set
+
+#
+# Bus options (PCI, PCMCIA, EISA, MCA, ISA)
+#
+# CONFIG_PCI is not set
+# CONFIG_ISA is not set
+
+#
+# PCMCIA/CardBus support
+#
+CONFIG_PCMCIA=y
+# CONFIG_PCMCIA_DEBUG is not set
+# CONFIG_TCIC is not set
+
+#
+# PCI Hotplug Support
+#
+
+#
+# Executable file formats
+#
+CONFIG_BINFMT_ELF=y
+# CONFIG_BINFMT_MISC is not set
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+# CONFIG_FW_LOADER is not set
+
+#
+# Memory Technology Devices (MTD)
+#
+# CONFIG_MTD is not set
+
+#
+# Parallel port support
+#
+# CONFIG_PARPORT is not set
+
+#
+# Plug and Play support
+#
+
+#
+# Block devices
+#
+# CONFIG_BLK_DEV_FD is not set
+CONFIG_BLK_DEV_LOOP=y
+# CONFIG_BLK_DEV_CRYPTOLOOP is not set
+CONFIG_BLK_DEV_NBD=y
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_SIZE=4096
+# CONFIG_BLK_DEV_INITRD is not set
+
+#
+# ATA/ATAPI/MFM/RLL support
+#
+CONFIG_IDE=y
+CONFIG_BLK_DEV_IDE=y
+
+#
+# Please see Documentation/ide.txt for help/info on IDE drives
+#
+# CONFIG_BLK_DEV_IDE_SATA is not set
+CONFIG_BLK_DEV_IDEDISK=y
+# CONFIG_IDEDISK_MULTI_MODE is not set
+CONFIG_BLK_DEV_IDECS=y
+CONFIG_BLK_DEV_IDECD=m
+# 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_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 device support
+#
+CONFIG_SCSI=m
+CONFIG_SCSI_PROC_FS=y
+
+#
+# SCSI support type (disk, tape, CD-ROM)
+#
+CONFIG_BLK_DEV_SD=m
+# CONFIG_CHR_DEV_ST is not set
+# CONFIG_CHR_DEV_OSST is not set
+CONFIG_BLK_DEV_SR=m
+# CONFIG_BLK_DEV_SR_VENDOR is not set
+CONFIG_CHR_DEV_SG=m
+
+#
+# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
+#
+CONFIG_SCSI_MULTI_LUN=y
+# CONFIG_SCSI_CONSTANTS is not set
+# CONFIG_SCSI_LOGGING is not set
+
+#
+# SCSI Transport Attributes
+#
+# CONFIG_SCSI_SPI_ATTRS is not set
+# CONFIG_SCSI_FC_ATTRS is not set
+
+#
+# SCSI low-level drivers
+#
+# CONFIG_SCSI_AIC7XXX_OLD is not set
+# CONFIG_SCSI_SATA is not set
+# CONFIG_SCSI_EATA_PIO is not set
+# CONFIG_SCSI_DEBUG is not set
+
+#
+# PCMCIA SCSI adapter support
+#
+# CONFIG_PCMCIA_AHA152X is not set
+# CONFIG_PCMCIA_FDOMAIN is not set
+# CONFIG_PCMCIA_NINJA_SCSI is not set
+# CONFIG_PCMCIA_QLOGIC is not set
+# CONFIG_PCMCIA_SYM53C500 is not set
+
+#
+# Multi-device support (RAID and LVM)
+#
+# CONFIG_MD is not set
+
+#
+# Fusion MPT device support
+#
+
+#
+# IEEE 1394 (FireWire) support
+#
+
+#
+# I2O device support
+#
+
+#
+# Networking support
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+CONFIG_PACKET=y
+# CONFIG_PACKET_MMAP is not set
+# CONFIG_NETLINK_DEV is not set
+CONFIG_UNIX=y
+# CONFIG_NET_KEY is not set
+CONFIG_INET=y
+# CONFIG_IP_MULTICAST is not set
+# 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_RARP is not set
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+# CONFIG_ARPD 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
+# CONFIG_IPV6 is not set
+# CONFIG_NETFILTER is not set
+
+#
+# SCTP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_SCTP is not set
+# CONFIG_ATM is not set
+# CONFIG_BRIDGE is not set
+# CONFIG_VLAN_8021Q is not set
+# CONFIG_DECNET 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
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+# CONFIG_NET_HW_FLOWCONTROL is not set
+
+#
+# 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 is not set
+
+#
+# ISDN subsystem
+#
+# CONFIG_ISDN is not set
+
+#
+# Telephony Support
+#
+# CONFIG_PHONE is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+
+#
+# Userland interfaces
+#
+# CONFIG_INPUT_MOUSEDEV is not set
+# 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=y
+# CONFIG_SERIO_I8042 is not set
+CONFIG_SERIO_SERPORT=y
+# CONFIG_SERIO_CT82C710 is not set
+
+#
+# Input Device Drivers
+#
+# CONFIG_INPUT_KEYBOARD is not set
+# CONFIG_INPUT_MOUSE 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 is not set
+# CONFIG_SERIAL_NONSTANDARD is not set
+
+#
+# Serial drivers
+#
+# CONFIG_SERIAL_8250 is not set
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+# CONFIG_SERIAL_M32R_SIO is not set
+CONFIG_SERIAL_M32R_PLDSIO=y
+CONFIG_SERIAL_M32R_PLDSIO_CONSOLE=y
+CONFIG_UNIX98_PTYS=y
+CONFIG_LEGACY_PTYS=y
+CONFIG_LEGACY_PTY_COUNT=256
+# CONFIG_QIC02_TAPE is not set
+
+#
+# IPMI
+#
+# CONFIG_IPMI_HANDLER is not set
+
+#
+# Watchdog Cards
+#
+# CONFIG_WATCHDOG is not set
+# CONFIG_RTC is not set
+# CONFIG_GEN_RTC is not set
+# CONFIG_DTLK is not set
+# CONFIG_R3964 is not set
+
+#
+# Ftape, the floppy tape device driver
+#
+# CONFIG_AGP is not set
+# CONFIG_DRM is not set
+
+#
+# PCMCIA character devices
+#
+# CONFIG_SYNCLINK_CS is not set
+# CONFIG_RAW_DRIVER is not set
+
+#
+# I2C support
+#
+# CONFIG_I2C is not set
+
+#
+# Dallas's 1-wire bus
+#
+# CONFIG_W1 is not set
+
+#
+# Misc devices
+#
+
+#
+# Multimedia devices
+#
+CONFIG_VIDEO_DEV=y
+
+#
+# Video For Linux
+#
+
+#
+# Video Adapters
+#
+# CONFIG_VIDEO_CPIA is not set
+CONFIG_M32R_AR=y
+CONFIG_M32R_AR_VGA=y
+
+#
+# Radio Adapters
+#
+# CONFIG_RADIO_MAESTRO is not set
+
+#
+# Digital Video Broadcasting Devices
+#
+# CONFIG_DVB is not set
+
+#
+# Graphics support
+#
+# CONFIG_FB is not set
+
+#
+# Sound
+#
+# CONFIG_SOUND is not set
+
+#
+# USB support
+#
+
+#
+# USB Gadget Support
+#
+# CONFIG_USB_GADGET is not set
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+# CONFIG_EXT2_FS_XATTR is not set
+CONFIG_EXT3_FS=m
+CONFIG_EXT3_FS_XATTR=y
+# CONFIG_EXT3_FS_POSIX_ACL is not set
+# CONFIG_EXT3_FS_SECURITY is not set
+CONFIG_JBD=m
+CONFIG_JBD_DEBUG=y
+CONFIG_FS_MBCACHE=y
+CONFIG_REISERFS_FS=m
+# 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 is not set
+# CONFIG_ROMFS_FS is not set
+# CONFIG_QUOTA is not set
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_AUTOFS4_FS is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+CONFIG_ISO9660_FS=m
+CONFIG_JOLIET=y
+# CONFIG_ZISOFS is not set
+CONFIG_UDF_FS=m
+CONFIG_UDF_NLS=y
+
+#
+# DOS/FAT/NT Filesystems
+#
+CONFIG_FAT_FS=m
+CONFIG_MSDOS_FS=m
+CONFIG_VFAT_FS=m
+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_EFS_FS is not set
+# CONFIG_CRAMFS is not set
+# CONFIG_VXFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+
+#
+# Network File Systems
+#
+CONFIG_NFS_FS=y
+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_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_AFS_FS is not set
+
+#
+# Partition Types
+#
+# CONFIG_PARTITION_ADVANCED is not set
+CONFIG_MSDOS_PARTITION=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
+# CONFIG_NLS_CODEPAGE_775 is not set
+# CONFIG_NLS_CODEPAGE_850 is not set
+# CONFIG_NLS_CODEPAGE_852 is not set
+# CONFIG_NLS_CODEPAGE_855 is not set
+# CONFIG_NLS_CODEPAGE_857 is not set
+# CONFIG_NLS_CODEPAGE_860 is not set
+# CONFIG_NLS_CODEPAGE_861 is not set
+# CONFIG_NLS_CODEPAGE_862 is not set
+# CONFIG_NLS_CODEPAGE_863 is not set
+# CONFIG_NLS_CODEPAGE_864 is not set
+# CONFIG_NLS_CODEPAGE_865 is not set
+# CONFIG_NLS_CODEPAGE_866 is not set
+# CONFIG_NLS_CODEPAGE_869 is not set
+# CONFIG_NLS_CODEPAGE_936 is not set
+# CONFIG_NLS_CODEPAGE_950 is not set
+# CONFIG_NLS_CODEPAGE_932 is not set
+# CONFIG_NLS_CODEPAGE_949 is not set
+# CONFIG_NLS_CODEPAGE_874 is not set
+# 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
+# CONFIG_NLS_ISO8859_4 is not set
+# CONFIG_NLS_ISO8859_5 is not set
+# CONFIG_NLS_ISO8859_6 is not set
+# CONFIG_NLS_ISO8859_7 is not set
+# CONFIG_NLS_ISO8859_9 is not set
+# CONFIG_NLS_ISO8859_13 is not set
+# CONFIG_NLS_ISO8859_14 is not set
+# CONFIG_NLS_ISO8859_15 is not set
+# CONFIG_NLS_KOI8_R is not set
+# CONFIG_NLS_KOI8_U is not set
+# CONFIG_NLS_UTF8 is not set
+
+#
+# Profiling support
+#
+# CONFIG_PROFILING is not set
+
+#
+# Kernel hacking
+#
+# CONFIG_DEBUG_KERNEL is not set
+# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
+# CONFIG_FRAME_POINTER is not set
+
+#
+# Security options
+#
+# CONFIG_SECURITY is not set
+
+#
+# Cryptographic options
+#
+# CONFIG_CRYPTO is not set
+
+#
+# Library routines
+#
+# CONFIG_CRC_CCITT is not set
+CONFIG_CRC32=y
+# CONFIG_LIBCRC32C is not set
diff -Nru a/arch/m32r/kernel/Makefile b/arch/m32r/kernel/Makefile
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/arch/m32r/kernel/Makefile	2004-10-18 14:57:23 -07:00
@@ -0,0 +1,20 @@
+#
+# Makefile for the Linux/M32R kernel.
+#
+
+extra-y	:= head.o init_task.o vmlinux.lds
+
+obj-y	:= process.o entry.o traps.o align.o irq.o setup.o time.o \
+	m32r_ksyms.o sys_m32r.o semaphore.o signal.o ptrace.o
+
+obj-$(CONFIG_SMP)		+= smp.o smpboot.o
+obj-$(CONFIG_PLAT_MAPPI)	+= setup_mappi.o io_mappi.o
+obj-$(CONFIG_PLAT_MAPPI2)	+= setup_mappi2.o io_mappi2.o
+obj-$(CONFIG_PLAT_USRV)		+= setup_usrv.o io_usrv.o
+obj-$(CONFIG_PLAT_M32700UT)	+= setup_m32700ut.o io_m32700ut.o
+obj-$(CONFIG_PLAT_OPSPUT)	+= setup_opsput.o io_opsput.o
+obj-$(CONFIG_MODULES)		+= module.o
+obj-$(CONFIG_PLAT_OAKS32R)	+= setup_oaks32r.o io_oaks32r.o
+
+EXTRA_AFLAGS	:= -traditional
+
diff -Nru a/arch/m32r/kernel/align.c b/arch/m32r/kernel/align.c
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/arch/m32r/kernel/align.c	2004-10-18 14:57:21 -07:00
@@ -0,0 +1,585 @@
+/*
+ * align.c - address exception handler for M32R
+ *
+ * Copyright (c) 2003 Hitoshi Yamamoto
+ */
+
+#include <linux/config.h>
+#include <asm/ptrace.h>
+#include <asm/uaccess.h>
+
+static int get_reg(struct pt_regs *regs, int nr)
+{
+	int val;
+
+	if (nr < 4)
+		val = *(unsigned long *)(&regs->r0 + nr);
+	else if (nr < 7)
+		val = *(unsigned long *)(&regs->r4 + (nr - 4));
+	else if (nr < 13)
+		val = *(unsigned long *)(&regs->r7 + (nr - 7));
+	else
+		val = *(unsigned long *)(&regs->fp + (nr - 13));
+
+	return val;
+}
+
+static void set_reg(struct pt_regs *regs, int nr, int val)
+{
+	if (nr < 4)
+		*(unsigned long *)(&regs->r0 + nr) = val;
+	else if (nr < 7)
+		*(unsigned long *)(&regs->r4 + (nr - 4)) = val;
+	else if (nr < 13)
+		*(unsigned long *)(&regs->r7 + (nr - 7)) = val;
+	else
+		*(unsigned long *)(&regs->fp + (nr - 13)) = val;
+}
+
+#define REG1(insn)	(((insn) & 0x0f00) >> 8)
+#define REG2(insn)	((insn) & 0x000f)
+#define PSW_BC		0x100
+
+/* O- instruction */
+#define ISA_LD1		0x20c0	/* ld Rdest, @Rsrc */
+#define ISA_LD2		0x20e0	/* ld Rdest, @Rsrc+ */
+#define ISA_LDH		0x20a0	/* ldh Rdest, @Rsrc */
+#define ISA_LDUH	0x20b0	/* lduh Rdest, @Rsrc */
+#define ISA_ST1		0x2040	/* st Rsrc1, @Rsrc2 */
+#define ISA_ST2		0x2060	/* st Rsrc1, @+Rsrc2 */
+#define ISA_ST3		0x2070	/* st Rsrc1, @-Rsrc2 */
+#define ISA_STH1	0x2020	/* sth Rsrc1, @Rsrc2 */
+#define ISA_STH2	0x2030	/* sth Rsrc1, @Rsrc2+ */
+
+#ifdef CONFIG_ISA_DUAL_ISSUE
+
+/* OS instruction */
+#define ISA_ADD		0x00a0	/* add Rdest, Rsrc */
+#define ISA_ADDI	0x4000	/* addi Rdest, #imm8 */
+#define ISA_ADDX	0x0090	/* addx Rdest, Rsrc */
+#define ISA_AND		0x00c0	/* and Rdest, Rsrc */
+#define ISA_CMP		0x0040	/* cmp Rsrc1, Rsrc2 */
+#define ISA_CMPEQ	0x0060	/* cmpeq Rsrc1, Rsrc2 */
+#define ISA_CMPU	0x0050	/* cmpu Rsrc1, Rsrc2 */
+#define ISA_CMPZ	0x0070	/* cmpz Rsrc */
+#define ISA_LDI		0x6000	/* ldi Rdest, #imm8 */
+#define ISA_MV		0x1080	/* mv Rdest, Rsrc */
+#define ISA_NEG		0x0030	/* neg Rdest, Rsrc */
+#define ISA_NOP		0x7000	/* nop */
+#define ISA_NOT		0x00b0	/* not Rdest, Rsrc */
+#define ISA_OR		0x00e0	/* or Rdest, Rsrc */
+#define ISA_SUB		0x0020	/* sub Rdest, Rsrc */
+#define ISA_SUBX	0x0010	/* subx Rdest, Rsrc */
+#define ISA_XOR		0x00d0	/* xor Rdest, Rsrc */
+
+/* -S instruction */
+#define ISA_MUL		0x1060	/* mul Rdest, Rsrc */
+#define ISA_MULLO_A0	0x3010	/* mullo Rsrc1, Rsrc2, A0 */
+#define ISA_MULLO_A1	0x3090	/* mullo Rsrc1, Rsrc2, A1 */
+#define ISA_MVFACMI_A0	0x50f2	/* mvfacmi Rdest, A0 */
+#define ISA_MVFACMI_A1	0x50f6	/* mvfacmi Rdest, A1 */
+
+static int emu_addi(unsigned short insn, struct pt_regs *regs)
+{
+	char imm = (char)(insn & 0xff);
+	int dest = REG1(insn);
+	int val;
+
+	val = get_reg(regs, dest);
+	val += imm;
+	set_reg(regs, dest, val);
+
+	return 0;
+}
+
+static int emu_ldi(unsigned short insn, struct pt_regs *regs)
+{
+	char imm = (char)(insn & 0xff);
+
+	set_reg(regs, REG1(insn), (int)imm);
+
+	return 0;
+}
+
+static int emu_add(unsigned short insn, struct pt_regs *regs)
+{
+	int dest = REG1(insn);
+	int src = REG2(insn);
+	int val;
+
+	val = get_reg(regs, dest);
+	val += get_reg(regs, src);
+	set_reg(regs, dest, val);
+
+	return 0;
+}
+
+static int emu_addx(unsigned short insn, struct pt_regs *regs)
+{
+	int dest = REG1(insn);
+	unsigned int val, tmp;
+
+	val = regs->psw & PSW_BC ? 1 : 0;
+	tmp = get_reg(regs, dest);
+	val += tmp;
+	val += (unsigned int)get_reg(regs, REG2(insn));
+	set_reg(regs, dest, val);
+
+	/* C bit set */
+	if (val < tmp)
+		regs->psw |= PSW_BC;
+	else
+		regs->psw &= ~(PSW_BC);
+
+	return 0;
+}
+
+static int emu_and(unsigned short insn, struct pt_regs *regs)
+{
+	int dest = REG1(insn);
+	int val;
+
+	val = get_reg(regs, dest);
+	val &= get_reg(regs, REG2(insn));
+	set_reg(regs, dest, val);
+
+	return 0;
+}
+
+static int emu_cmp(unsigned short insn, struct pt_regs *regs)
+{
+	if (get_reg(regs, REG1(insn)) < get_reg(regs, REG2(insn)))
+		regs->psw |= PSW_BC;
+	else
+		regs->psw &= ~(PSW_BC);
+
+	return 0;
+}
+
+static int emu_cmpeq(unsigned short insn, struct pt_regs *regs)
+{
+	if (get_reg(regs, REG1(insn)) == get_reg(regs, REG2(insn)))
+		regs->psw |= PSW_BC;
+	else
+		regs->psw &= ~(PSW_BC);
+
+	return 0;
+}
+
+static int emu_cmpu(unsigned short insn, struct pt_regs *regs)
+{
+	if ((unsigned int)get_reg(regs, REG1(insn))
+		< (unsigned int)get_reg(regs, REG2(insn)))
+		regs->psw |= PSW_BC;
+	else
+		regs->psw &= ~(PSW_BC);
+
+	return 0;
+}
+
+static int emu_cmpz(unsigned short insn, struct pt_regs *regs)
+{
+	if (!get_reg(regs, REG2(insn)))
+		regs->psw |= PSW_BC;
+	else
+		regs->psw &= ~(PSW_BC);
+
+	return 0;
+}
+
+static int emu_mv(unsigned short insn, struct pt_regs *regs)
+{
+	int val;
+
+	val = get_reg(regs, REG2(insn));
+	set_reg(regs, REG1(insn), val);
+
+	return 0;
+}
+
+static int emu_neg(unsigned short insn, struct pt_regs *regs)
+{
+	int val;
+
+	val = get_reg(regs, REG2(insn));
+	set_reg(regs, REG1(insn), 0 - val);
+
+	return 0;
+}
+
+static int emu_not(unsigned short insn, struct pt_regs *regs)
+{
+	int val;
+
+	val = get_reg(regs, REG2(insn));
+	set_reg(regs, REG1(insn), ~val);
+
+	return 0;
+}
+
+static int emu_or(unsigned short insn, struct pt_regs *regs)
+{
+	int dest = REG1(insn);
+	int val;
+
+	val = get_reg(regs, dest);
+	val |= get_reg(regs, REG2(insn));
+	set_reg(regs, dest, val);
+
+	return 0;
+}
+
+static int emu_sub(unsigned short insn, struct pt_regs *regs)
+{
+	int dest = REG1(insn);
+	int val;
+
+	val = get_reg(regs, dest);
+	val -= get_reg(regs, REG2(insn));
+	set_reg(regs, dest, val);
+
+	return 0;
+}
+
+static int emu_subx(unsigned short insn, struct pt_regs *regs)
+{
+	int dest = REG1(insn);
+	unsigned int val, tmp;
+
+	val = tmp = get_reg(regs, dest);
+	val -= (unsigned int)get_reg(regs, REG2(insn));
+	val -= regs->psw & PSW_BC ? 1 : 0;
+	set_reg(regs, dest, val);
+
+	/* C bit set */
+	if (val > tmp)
+		regs->psw |= PSW_BC;
+	else
+		regs->psw &= ~(PSW_BC);
+
+	return 0;
+}
+
+static int emu_xor(unsigned short insn, struct pt_regs *regs)
+{
+	int dest = REG1(insn);
+	unsigned int val;
+
+	val = (unsigned int)get_reg(regs, dest);
+	val ^= (unsigned int)get_reg(regs, REG2(insn));
+	set_reg(regs, dest, val);
+
+	return 0;
+}
+
+static int emu_mul(unsigned short insn, struct pt_regs *regs)
+{
+	int dest = REG1(insn);
+	int reg1, reg2;
+
+	reg1 = get_reg(regs, dest);
+	reg2 = get_reg(regs, REG2(insn));
+
+	__asm__ __volatile__ (
+		"mul	%0, %1;		\n\t"
+		: "+r" (reg1) : "r" (reg2)
+	);
+
+	set_reg(regs, dest, reg1);
+
+	return 0;
+}
+
+static int emu_mullo_a0(unsigned short insn, struct pt_regs *regs)
+{
+	int reg1, reg2;
+
+	reg1 = get_reg(regs, REG1(insn));
+	reg2 = get_reg(regs, REG2(insn));
+
+	__asm__ __volatile__ (
+		"mullo		%0, %1, a0;	\n\t"
+		"mvfachi	%0, a0;		\n\t"
+		"mvfaclo	%1, a0;		\n\t"
+		: "+r" (reg1), "+r" (reg2)
+	);
+
+	regs->acc0h = reg1;
+	regs->acc0l = reg2;
+
+	return 0;
+}
+
+static int emu_mullo_a1(unsigned short insn, struct pt_regs *regs)
+{
+	int reg1, reg2;
+
+	reg1 = get_reg(regs, REG1(insn));
+	reg2 = get_reg(regs, REG2(insn));
+
+	__asm__ __volatile__ (
+		"mullo		%0, %1, a0;	\n\t"
+		"mvfachi	%0, a0;		\n\t"
+		"mvfaclo	%1, a0;		\n\t"
+		: "+r" (reg1), "+r" (reg2)
+	);
+
+	regs->acc1h = reg1;
+	regs->acc1l = reg2;
+
+	return 0;
+}
+
+static int emu_mvfacmi_a0(unsigned short insn, struct pt_regs *regs)
+{
+	unsigned long val;
+
+	val = (regs->acc0h << 16) | (regs->acc0l >> 16);
+	set_reg(regs, REG1(insn), (int)val);
+
+	return 0;
+}
+
+static int emu_mvfacmi_a1(unsigned short insn, struct pt_regs *regs)
+{
+	unsigned long val;
+
+	val = (regs->acc1h << 16) | (regs->acc1l >> 16);
+	set_reg(regs, REG1(insn), (int)val);
+
+	return 0;
+}
+
+static int emu_m32r2(unsigned short insn, struct pt_regs *regs)
+{
+	int res = -1;
+
+	if ((insn & 0x7fff) == ISA_NOP)	/* nop */
+		return 0;
+
+	switch(insn & 0x7000) {
+	case ISA_ADDI:		/* addi Rdest, #imm8 */
+		res = emu_addi(insn, regs);
+		break;
+	case ISA_LDI:		/* ldi Rdest, #imm8 */
+		res = emu_ldi(insn, regs);
+		break;
+	default:
+		break;
+	}
+
+	if (!res)
+		return 0;
+
+	switch(insn & 0x70f0) {
+	case ISA_ADD:		/* add Rdest, Rsrc */
+		res = emu_add(insn, regs);
+		break;
+	case ISA_ADDX:		/* addx Rdest, Rsrc */
+		res = emu_addx(insn, regs);
+		break;
+	case ISA_AND:		/* and Rdest, Rsrc */
+		res = emu_and(insn, regs);
+		break;
+	case ISA_CMP:		/* cmp Rsrc1, Rsrc2 */
+		res = emu_cmp(insn, regs);
+		break;
+	case ISA_CMPEQ:		/* cmpeq Rsrc1, Rsrc2 */
+		res = emu_cmpeq(insn, regs);
+		break;
+	case ISA_CMPU:		/* cmpu Rsrc1, Rsrc2 */
+		res = emu_cmpu(insn, regs);
+		break;
+	case ISA_CMPZ:		/* cmpz Rsrc */
+		res = emu_cmpz(insn, regs);
+		break;
+	case ISA_MV:		/* mv Rdest, Rsrc */
+		res = emu_mv(insn, regs);
+		break;
+	case ISA_NEG:		/* neg Rdest, Rsrc */
+		res = emu_neg(insn, regs);
+		break;
+	case ISA_NOT:		/* not Rdest, Rsrc */
+		res = emu_not(insn, regs);
+		break;
+	case ISA_OR:		/* or Rdest, Rsrc */
+		res = emu_or(insn, regs);
+		break;
+	case ISA_SUB:		/* sub Rdest, Rsrc */
+		res = emu_sub(insn, regs);
+		break;
+	case ISA_SUBX:		/* subx Rdest, Rsrc */
+		res = emu_subx(insn, regs);
+		break;
+	case ISA_XOR:		/* xor Rdest, Rsrc */
+		res = emu_xor(insn, regs);
+		break;
+	case ISA_MUL:		/* mul Rdest, Rsrc */
+		res = emu_mul(insn, regs);
+		break;
+	case ISA_MULLO_A0:	/* mullo Rsrc1, Rsrc2 */
+		res = emu_mullo_a0(insn, regs);
+		break;
+	case ISA_MULLO_A1:	/* mullo Rsrc1, Rsrc2 */
+		res = emu_mullo_a1(insn, regs);
+		break;
+	default:
+		break;
+	}
+
+	if (!res)
+		return 0;
+
+	switch(insn & 0x70ff) {
+	case ISA_MVFACMI_A0:	/* mvfacmi Rdest */
+		res = emu_mvfacmi_a0(insn, regs);
+		break;
+	case ISA_MVFACMI_A1:	/* mvfacmi Rdest */
+		res = emu_mvfacmi_a1(insn, regs);
+		break;
+	default:
+		break;
+	}
+
+	return res;
+}
+
+#endif	/* CONFIG_ISA_DUAL_ISSUE */
+
+/*
+ * ld   : ?010 dest 1100 src
+ *        0010 dest 1110 src : ld Rdest, @Rsrc+
+ * ldh  : ?010 dest 1010 src
+ * lduh : ?010 dest 1011 src
+ * st   : ?010 src1 0100 src2
+ *        0010 src1 0110 src2 : st Rsrc1, @+Rsrc2
+ *        0010 src1 0111 src2 : st Rsrc1, @-Rsrc2
+ * sth  : ?010 src1 0010 src2
+ */
+
+static int insn_check(unsigned long insn, struct pt_regs *regs,
+	unsigned char **ucp)
+{
+	int res = 0;
+
+	/*
+	 * 32bit insn
+	 *  ld Rdest, @(disp16, Rsrc)
+	 *  st Rdest, @(disp16, Rsrc)
+	 */
+	if (insn & 0x80000000) {	/* 32bit insn */
+		*ucp += (short)(insn & 0x0000ffff);
+		regs->bpc += 4;
+	} else {			/* 16bit insn */
+#ifdef CONFIG_ISA_DUAL_ISSUE
+		/* parallel exec check */
+		if (!(regs->bpc & 0x2) && insn & 0x8000) {
+			res = emu_m32r2((unsigned short)insn, regs);
+			regs->bpc += 4;
+		} else
+#endif	/* CONFIG_ISA_DUAL_ISSUE */
+			regs->bpc += 2;
+	}
+
+	return res;
+}
+
+static int emu_ld(unsigned long insn32, struct pt_regs *regs)
+{
+	unsigned char *ucp;
+	unsigned long val;
+	unsigned short insn16;
+	int size, src;
+
+	insn16 = insn32 >> 16;
+	src = REG2(insn16);
+	ucp = (unsigned char *)get_reg(regs, src);
+
+	if (insn_check(insn32, regs, &ucp))
+		return -1;
+
+	size = insn16 & 0x0040 ? 4 : 2;
+	if (copy_from_user(&val, ucp, size))
+		return -1;
+
+	if (size == 2)
+		val >>= 16;
+
+	/* ldh sign check */
+	if ((insn16 & 0x00f0) == 0x00a0 && (val & 0x8000))
+		val |= 0xffff0000;
+
+	set_reg(regs, REG1(insn16), val);
+
+	/* ld increment check */
+	if ((insn16 & 0xf0f0) == ISA_LD2)	/* ld Rdest, @Rsrc+ */
+		set_reg(regs, src, (unsigned long)(ucp + 4));
+
+	return 0;
+}
+
+static int emu_st(unsigned long insn32, struct pt_regs *regs)
+{
+	unsigned char *ucp;
+	unsigned long val;
+	unsigned short insn16;
+	int size, src2;
+
+	insn16 = insn32 >> 16;
+	src2 = REG2(insn16);
+
+	ucp = (unsigned char *)get_reg(regs, src2);
+
+	if (insn_check(insn32, regs, &ucp))
+		return -1;
+
+	size = insn16 & 0x0040 ? 4 : 2;
+	val = get_reg(regs, REG1(insn16));
+	if (size == 2)
+		val <<= 16;
+
+	/* st inc/dec check */
+	if ((insn16 & 0xf0e0) == 0x2060) {
+		if (insn16 & 0x0010)
+			ucp -= 4;
+		else
+			ucp += 4;
+
+		set_reg(regs, src2, (unsigned long)ucp);
+	}
+
+	if (copy_to_user(ucp, &val, size))
+		return -1;
+
+	/* sth inc check */
+	if ((insn16 & 0xf0f0) == ISA_STH2) {
+		ucp += 2;
+		set_reg(regs, src2, (unsigned long)ucp);
+	}
+
+	return 0;
+}
+
+int handle_unaligned_access(unsigned long insn32, struct pt_regs *regs)
+{
+	unsigned short insn16;
+	int res;
+
+	insn16 = insn32 >> 16;
+
+	/* ld or st check */
+	if ((insn16 & 0x7000) != 0x2000)
+		return -1;
+
+	/* insn alignment check */
+	if ((insn16 & 0x8000) && (regs->bpc & 3))
+		return -1;
+
+	if (insn16 & 0x0080)	/* ld */
+		res = emu_ld(insn32, regs);
+	else			/* st */
+		res = emu_st(insn32, regs);
+
+	return res;
+}
+
diff -Nru a/arch/m32r/kernel/entry.S b/arch/m32r/kernel/entry.S
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/arch/m32r/kernel/entry.S	2004-10-18 14:57:24 -07:00
@@ -0,0 +1,999 @@
+/*
+ *  linux/arch/m32r/kernel/entry.S
+ *
+ *  Copyright (c) 2001, 2002  Hirokazu Takata, Hitoshi Yamamoto, H. Kondo
+ *  Copyright (c) 2003  Hitoshi Yamamoto
+ *  Copyright (c) 2004  Hirokazu Takata <takata at linux-m32r.org>
+ *
+ *  Taken from i386 version.
+ *    Copyright (C) 1991, 1992  Linus Torvalds
+ */
+
+/*
+ * entry.S contains the system-call and fault low-level handling routines.
+ * This also contains the timer-interrupt handler, as well as all interrupts
+ * and faults that can result in a task-switch.
+ *
+ * NOTE: This code handles signal-recognition, which happens every time
+ * after a timer-interrupt and after each system call.
+ *
+ * Stack layout in 'ret_from_system_call':
+ * 	ptrace needs to have all regs on the stack.
+ *	if the order here is changed, it needs to be
+ *	updated in fork.c:copy_process, signal.c:do_signal,
+ *	ptrace.c and ptrace.h
+ *
+ * M32Rx/M32R2				M32R
+ *       @(sp)      - r4		ditto
+ *       @(0x04,sp) - r5		ditto
+ *       @(0x08,sp) - r6		ditto
+ *       @(0x0c,sp) - *pt_regs		ditto
+ *       @(0x10,sp) - r0		ditto
+ *       @(0x14,sp) - r1		ditto
+ *       @(0x18,sp) - r2		ditto
+ *       @(0x1c,sp) - r3		ditto
+ *       @(0x20,sp) - r7		ditto
+ *       @(0x24,sp) - r8		ditto
+ *       @(0x28,sp) - r9		ditto
+ *       @(0x2c,sp) - r10		ditto
+ *       @(0x30,sp) - r11		ditto
+ *       @(0x34,sp) - r12		ditto
+ *       @(0x38,sp) - syscall_nr	ditto
+ *       @(0x3c,sp) - acc0h		@(0x3c,sp) - acch
+ *       @(0x40,sp) - acc0l		@(0x40,sp) - accl
+ *       @(0x44,sp) - acc1h		@(0x44,sp) - psw
+ *       @(0x48,sp) - acc1l		@(0x48,sp) - bpc
+ *       @(0x4c,sp) - psw		@(0x4c,sp) - bbpsw
+ *       @(0x50,sp) - bpc		@(0x50,sp) - bbpc
+ *       @(0x54,sp) - bbpsw		@(0x54,sp) - spu (cr3)
+ *       @(0x58,sp) - bbpc		@(0x58,sp) - fp (r13)
+ *       @(0x5c,sp) - spu (cr3)		@(0x5c,sp) - lr (r14)
+ *       @(0x60,sp) - fp (r13)		@(0x60,sp) - spi (cr12)
+ *       @(0x64,sp) - lr (r14)		@(0x64,sp) - orig_r0
+ *       @(0x68,sp) - spi (cr2)
+ *       @(0x6c,sp) - orig_r0
+ *
+ */
+
+#include <linux/config.h>
+#include <linux/linkage.h>
+#include <asm/irq.h>
+#include <asm/unistd.h>
+#include <asm/assembler.h>
+#include <asm/thread_info.h>
+#include <asm/errno.h>
+#include <asm/segment.h>
+#include <asm/smp.h>
+#include <asm/page.h>
+#include <asm/m32r.h>
+#include <asm/mmu_context.h>
+
+#if !defined(CONFIG_MMU)
+#define sys_madvise             sys_ni_syscall
+#define sys_readahead           sys_ni_syscall
+#define sys_mprotect            sys_ni_syscall
+#define sys_msync               sys_ni_syscall
+#define sys_mlock               sys_ni_syscall
+#define sys_munlock             sys_ni_syscall
+#define sys_mlockall            sys_ni_syscall
+#define sys_munlockall          sys_ni_syscall
+#define sys_mremap              sys_ni_syscall
+#define sys_mincore             sys_ni_syscall
+#endif /* CONFIG_MMU */
+
+#define R4(reg)			@reg
+#define R5(reg)			@(0x04,reg)
+#define R6(reg)			@(0x08,reg)
+#define PTREGS(reg)		@(0x0C,reg)
+#define R0(reg)			@(0x10,reg)
+#define R1(reg)			@(0x14,reg)
+#define R2(reg)			@(0x18,reg)
+#define R3(reg)			@(0x1C,reg)
+#define R7(reg)			@(0x20,reg)
+#define R8(reg)			@(0x24,reg)
+#define R9(reg)			@(0x28,reg)
+#define R10(reg)		@(0x2C,reg)
+#define R11(reg)		@(0x30,reg)
+#define R12(reg)		@(0x34,reg)
+#define SYSCALL_NR(reg)		@(0x38,reg)
+#if defined(CONFIG_ISA_M32R2) && defined(CONFIG_ISA_DSP_LEVEL2)
+#define ACC0H(reg)		@(0x3C,reg)
+#define ACC0L(reg)		@(0x40,reg)
+#define ACC1H(reg)		@(0x44,reg)
+#define ACC1L(reg)		@(0x48,reg)
+#define PSW(reg)		@(0x4C,reg)
+#define BPC(reg)		@(0x50,reg)
+#define BBPSW(reg)		@(0x54,reg)
+#define BBPC(reg)		@(0x58,reg)
+#define SPU(reg)		@(0x5C,reg)
+#define FP(reg)			@(0x60,reg)  /* FP = R13 */
+#define LR(reg)			@(0x64,reg)
+#define SP(reg)			@(0x68,reg)
+#define ORIG_R0(reg)		@(0x6C,reg)
+#elif defined(CONFIG_ISA_M32R2) || defined(CONFIG_ISA_M32R)
+#define ACCH(reg)		@(0x3C,reg)
+#define ACCL(reg)		@(0x40,reg)
+#define PSW(reg)		@(0x44,reg)
+#define BPC(reg)		@(0x48,reg)
+#define BBPSW(reg)		@(0x4C,reg)
+#define BBPC(reg)		@(0x50,reg)
+#define SPU(reg)		@(0x54,reg)
+#define FP(reg)			@(0x58,reg)  /* FP = R13 */
+#define LR(reg)			@(0x5C,reg)
+#define SP(reg)			@(0x60,reg)
+#define ORIG_R0(reg)		@(0x64,reg)
+#else
+#error unknown isa configuration
+#endif
+
+CF_MASK		= 0x00000001
+TF_MASK		= 0x00000100
+IF_MASK		= 0x00000200
+DF_MASK		= 0x00000400
+NT_MASK		= 0x00004000
+VM_MASK		= 0x00020000
+
+#ifdef CONFIG_PREEMPT
+#define preempt_stop(x)		CLI(x)
+#else
+#define preempt_stop(x)
+#define resume_kernel		restore_all
+#endif
+
+ENTRY(ret_from_fork)
+	ld	r0, @sp+
+	bl	schedule_tail
+	GET_THREAD_INFO(r8)
+	bra	syscall_exit
+
+/*
+ * Return to user mode is not as complex as all this looks,
+ * but we want the default path for a system call return to
+ * go as quickly as possible which is why some of this is
+ * less clear than it otherwise should be.
+ */
+
+	; userspace resumption stub bypassing syscall exit tracing
+	ALIGN
+ret_from_exception:
+	preempt_stop(r4)
+ret_from_intr:
+	ld	r4, PSW(sp)
+#ifdef CONFIG_ISA_M32R2
+	and3	r4, r4, #0x8800		; check BSM and BPM bits
+#else
+	and3	r4, r4, #0x8000		; check BSM bit
+#endif
+	beqz	r4, resume_kernel
+ENTRY(resume_userspace)
+	CLI(r4)				; make sure we don't miss an interrupt
+					; setting need_resched or sigpending
+					; between sampling and the iret
+	GET_THREAD_INFO(r8)
+	ld	r9, @(TI_FLAGS, r8)
+	and3	r4, r9, #_TIF_WORK_MASK	; is there any work to be done on
+					; int/exception return?
+	bnez	r4, work_pending
+	bra	restore_all
+
+#ifdef CONFIG_PREEMPT
+ENTRY(resume_kernel)
+	GET_THREAD_INFO(r8)
+	ld	r9, @(TI_PRE_COUNT, r8)	; non-zero preempt_count ?
+	bnez	r9, restore_all
+need_resched:
+	ld	r9, @(TI_FLAGS, r8)	; need_resched set ?
+	and3	r4, r9, #_TIF_NEED_RESCHED
+	beqz	r4, restore_all
+	ld	r4, PSW(sp)		; interrupts off (exception path) ?
+	and3	r4, r4, #0x4000
+	beqz	r4, restore_all
+	LDIMM	(r4, PREEMPT_ACTIVE)
+	st	r4, @(TI_PRE_COUNT, r8)
+	STI(r4)
+	bl	schedule
+	ldi	r4, #0
+	st	r4, @(TI_PRE_COUNT, r8)
+	CLI(r4)
+	bra	need_resched
+#endif
+
+	; system call handler stub
+ENTRY(system_call)
+	SWITCH_TO_KERNEL_STACK
+	SAVE_ALL
+	STI(r4)				; Enable interrupt
+	st	sp, PTREGS(sp)		; implicit pt_regs parameter
+	cmpui	r7, #NR_syscalls
+	bnc	syscall_badsys
+	st	r7, SYSCALL_NR(sp)	; syscall_nr
+					; system call tracing in operation
+	GET_THREAD_INFO(r8)
+	ld	r9, @(TI_FLAGS, r8)
+	and3	r4, r9, #_TIF_SYSCALL_TRACE
+	bnez	r4, syscall_trace_entry
+syscall_call:
+	slli	r7, #2			; table jump for the system call
+	LDIMM	(r4, sys_call_table)
+	add	r7, r4
+	ld	r7, @r7
+	jl	r7			; execute system call
+	st	r0, R0(sp)		; save the return value
+syscall_exit:
+	CLI(r4)				; make sure we don't miss an interrupt
+					; setting need_resched or sigpending
+					; between sampling and the iret
+	ld	r9, @(TI_FLAGS, r8)
+	and3	r4, r9, #_TIF_ALLWORK_MASK	; current->work
+	bnez	r4, syscall_exit_work
+restore_all:
+	RESTORE_ALL
+
+	# perform work that needs to be done immediately before resumption
+	# r9 : frags
+	ALIGN
+work_pending:
+	and3	r4, r9, #_TIF_NEED_RESCHED
+	beqz	r4, work_notifysig
+work_resched:
+	bl	schedule
+	CLI(r4)				; make sure we don't miss an interrupt
+					; setting need_resched or sigpending
+					; between sampling and the iret
+	ld	r9, @(TI_FLAGS, r8)
+	and3	r4, r9, #_TIF_WORK_MASK	; is there any work to be done other
+					; than syscall tracing?
+	beqz	r4, restore_all
+	and3	r4, r4, #_TIF_NEED_RESCHED
+	bnez	r4, work_resched
+
+work_notifysig:				; deal with pending signals and
+					; notify-resume requests
+	mv	r0, sp			; arg1 : struct pt_regs *regs
+	ldi	r1, #0			; arg2 : sigset_t *oldset
+	mv	r2, r9			; arg3 : __u32 thread_info_flags
+	bl	do_notify_resume
+	bra	restore_all
+
+	; perform syscall exit tracing
+	ALIGN
+syscall_trace_entry:
+	ldi	r4, #-ENOSYS
+	st	r4, R0(sp)
+	bl	do_syscall_trace
+	ld	r0, ORIG_R0(sp)
+	ld	r1, R1(sp)
+	ld	r2, R2(sp)
+	ld	r3, R3(sp)
+	ld	r4, R4(sp)
+	ld	r5, R5(sp)
+	ld	r6, R6(sp)
+	ld	r7, SYSCALL_NR(sp)
+	cmpui	r7, #NR_syscalls
+	bc	syscall_call
+	bra	syscall_exit
+
+	; perform syscall exit tracing
+	ALIGN
+syscall_exit_work:
+	ld	r9, @(TI_FLAGS, r8)
+	and3	r4, r9, #_TIF_SYSCALL_TRACE
+	beqz	r4, work_pending
+	STI(r4)				; could let do_syscall_trace() call
+					; schedule() instead
+	bl	do_syscall_trace
+	bra	resume_userspace
+
+	ALIGN
+syscall_fault:
+	SAVE_ALL
+	GET_THREAD_INFO(r8)
+	ldi	r4, #-EFAULT
+	st	r4, R0(sp)
+	bra	resume_userspace
+
+	ALIGN
+syscall_badsys:
+	ldi	r4, #-ENOSYS
+	st	r4, R0(sp)
+	bra	resume_userspace
+
+	.global	eit_vector
+
+	.equ ei_vec_table, eit_vector + 0x0200
+
+/*
+ * EI handler routine
+ */
+ENTRY(ei_handler)
+#if defined(CONFIG_CHIP_M32700)
+	SWITCH_TO_KERNEL_STACK
+	; WORKAROUND: force to clear SM bit and use the kernel stack (SPI).
+#endif
+	SAVE_ALL
+	mv	r1, sp			; arg1(regs)
+#if defined(CONFIG_CHIP_VDEC2) || defined(CONFIG_CHIP_XNUX2) \
+	|| defined(CONFIG_CHIP_M32700) || defined(CONFIG_CHIP_M32102) \
+	|| defined(CONFIG_CHIP_OPSP)
+
+;    GET_ICU_STATUS;
+	seth	r0, #shigh(M32R_ICU_ISTS_ADDR)
+	ld	r0, @(low(M32R_ICU_ISTS_ADDR),r0)
+	st	r0, @-sp
+#if defined(CONFIG_SMP)
+	/*
+	 * If IRQ == 0      --> Nothing to do,  Not write IMASK
+	 * If IRQ == IPI    --> Do IPI handler, Not write IMASK
+	 * If IRQ != 0, IPI --> Do do_IRQ(),    Write IMASK
+	 */
+	slli	r0, #4
+	srli	r0, #24			; r0(irq_num<<2)
+	;; IRQ exist check
+#if defined(CONFIG_CHIP_M32700)
+	/* WORKAROUND: IMASK bug M32700-TS1, TS2 chip. */
+	beqz	r0, 3f			; if (!irq_num) goto exit
+#else
+	beqz	r0, 1f			; if (!irq_num) goto exit
+#endif	/* WORKAROUND */
+	;; IPI check
+	cmpi	r0, #(M32R_IRQ_IPI0<<2)	; ISN < IPI0 check
+	bc	2f
+	cmpi	r0, #((M32R_IRQ_IPI7+1)<<2)	; ISN > IPI7 check
+	bnc	2f
+	LDIMM	(r2, ei_vec_table)
+	add	r2, r0
+	ld	r2, @r2
+	beqz	r2, 1f			; if (no IPI handler) goto exit
+	mv	r0, r1			; arg0(regs)
+	jl	r2
+	.fillinsn
+1:
+	addi	sp, #4
+	bra	ret_to_intr
+#if defined(CONFIG_CHIP_M32700)
+	/* WORKAROUND: IMASK bug M32700-TS1, TS2 chip. */
+	.fillinsn
+3:
+	ld24	r14, #0x00070000
+	seth	r0, #shigh(M32R_ICU_IMASK_ADDR)
+	st	r14, @(low(M32R_ICU_IMASK_ADDR), r0)
+	addi	sp, #4
+	bra	ret_to_intr
+#endif	/* WORKAROUND */
+	;; do_IRQ
+	.fillinsn
+2:
+	srli	r0, #2
+#if defined(CONFIG_PLAT_USRV)
+	add3	r2, r0, #-(M32R_IRQ_INT1)	; INT1# interrupt
+	bnez	r2, 9f
+	; read ICU status register of PLD
+	seth	r0, #high(PLD_ICUISTS)
+	or3	r0, r0, #low(PLD_ICUISTS)
+	lduh	r0, @r0
+	slli	r0, #21
+	srli	r0, #27				; ISN
+	addi	r0, #(M32700UT_PLD_IRQ_BASE)
+	.fillinsn
+9:
+#elif defined(CONFIG_PLAT_M32700UT)
+	add3	r2, r0, #-(M32R_IRQ_INT1)       ; INT1# interrupt
+	bnez	r2, check_int0
+	; read ICU status register of PLD
+	seth	r0, #high(PLD_ICUISTS)
+	or3	r0, r0, #low(PLD_ICUISTS)
+	lduh	r0, @r0
+	slli	r0, #21
+	srli	r0, #27                         ; ISN
+	addi	r0, #(M32700UT_PLD_IRQ_BASE)
+	bra	check_end
+	.fillinsn
+check_int0:
+	add3	r2, r0, #-(M32R_IRQ_INT0)       ; INT0# interrupt
+	bnez	r2, check_int2
+	; read ICU status of LAN-board
+	seth	r0, #high(M32700UT_LAN_ICUISTS)
+	or3	r0, r0, #low(M32700UT_LAN_ICUISTS)
+	lduh	r0, @r0
+	slli	r0, #21
+	srli	r0, #27                         ; ISN
+	add3	r0, r0, #(M32700UT_LAN_PLD_IRQ_BASE)
+	bra	check_end
+	.fillinsn
+check_int2:
+	add3	r2, r0, #-(M32R_IRQ_INT2)       ; INT2# interrupt
+	bnez	r2, check_end
+	; read ICU status of LCD-board
+	seth	r0, #high(M32700UT_LCD_ICUISTS)
+	or3	r0, r0, #low(M32700UT_LCD_ICUISTS)
+	lduh	r0, @r0
+	slli	r0, #21
+	srli	r0, #27                         ; ISN
+	add3	r0, r0, #(M32700UT_LCD_PLD_IRQ_BASE)
+	bra	check_end
+	.fillinsn
+check_end:
+#elif defined(CONFIG_PLAT_OPSPUT)
+	add3	r2, r0, #-(M32R_IRQ_INT1)       ; INT1# interrupt
+	bnez	r2, check_int0
+	; read ICU status register of PLD
+	seth	r0, #high(PLD_ICUISTS)
+	or3	r0, r0, #low(PLD_ICUISTS)
+	lduh	r0, @r0
+	slli	r0, #21
+	srli	r0, #27                         ; ISN
+	addi	r0, #(OPSPUT_PLD_IRQ_BASE)
+	bra	check_end
+	.fillinsn
+check_int0:
+	add3	r2, r0, #-(M32R_IRQ_INT0)       ; INT0# interrupt
+	bnez	r2, check_int2
+	; read ICU status of LAN-board
+	seth	r0, #high(OPSPUT_LAN_ICUISTS)
+	or3	r0, r0, #low(OPSPUT_LAN_ICUISTS)
+	lduh	r0, @r0
+	slli	r0, #21
+	srli	r0, #27                         ; ISN
+	add3	r0, r0, #(OPSPUT_LAN_PLD_IRQ_BASE)
+	bra	check_end
+	.fillinsn
+check_int2:
+	add3	r2, r0, #-(M32R_IRQ_INT2)       ; INT2# interrupt
+	bnez	r2, check_end
+	; read ICU status of LCD-board
+	seth	r0, #high(OPSPUT_LCD_ICUISTS)
+	or3	r0, r0, #low(OPSPUT_LCD_ICUISTS)
+	lduh	r0, @r0
+	slli	r0, #21
+	srli	r0, #27                         ; ISN
+	add3	r0, r0, #(OPSPUT_LCD_PLD_IRQ_BASE)
+	bra	check_end
+	.fillinsn
+check_end:
+#endif  /* CONFIG_PLAT_OPSPUT */
+	bl	do_IRQ			; r0(irq), r1(regs)
+#else  /* not CONFIG_SMP */
+	srli	r0, #22			; r0(irq)
+#if defined(CONFIG_PLAT_USRV)
+	add3	r2, r0, #-(M32R_IRQ_INT1)	; INT1# interrupt
+	bnez	r2, 1f
+	; read ICU status register of PLD
+	seth	r0, #high(PLD_ICUISTS)
+	or3	r0, r0, #low(PLD_ICUISTS)
+	lduh	r0, @r0
+	slli	r0, #21
+	srli	r0, #27				; ISN
+	addi	r0, #(M32700UT_PLD_IRQ_BASE)
+	.fillinsn
+1:
+#elif defined(CONFIG_PLAT_M32700UT)
+	add3	r2, r0, #-(M32R_IRQ_INT1)       ; INT1# interrupt
+	bnez	r2, check_int0
+	; read ICU status register of PLD
+	seth	r0, #high(PLD_ICUISTS)
+	or3	r0, r0, #low(PLD_ICUISTS)
+	lduh	r0, @r0
+	slli	r0, #21
+	srli	r0, #27                         ; ISN
+	addi	r0, #(M32700UT_PLD_IRQ_BASE)
+	bra	check_end
+	.fillinsn
+check_int0:
+	add3	r2, r0, #-(M32R_IRQ_INT0)       ; INT0# interrupt
+	bnez	r2, check_int2
+	; read ICU status of LAN-board
+	seth	r0, #high(M32700UT_LAN_ICUISTS)
+	or3	r0, r0, #low(M32700UT_LAN_ICUISTS)
+	lduh	r0, @r0
+	slli	r0, #21
+	srli	r0, #27                         ; ISN
+	add3	r0, r0, #(M32700UT_LAN_PLD_IRQ_BASE)
+	bra	check_end
+	.fillinsn
+check_int2:
+	add3	r2, r0, #-(M32R_IRQ_INT2)       ; INT2# interrupt
+	bnez	r2, check_end
+	; read ICU status of LCD-board
+	seth	r0, #high(M32700UT_LCD_ICUISTS)
+	or3	r0, r0, #low(M32700UT_LCD_ICUISTS)
+	lduh	r0, @r0
+	slli	r0, #21
+	srli	r0, #27                         ; ISN
+	add3	r0, r0, #(M32700UT_LCD_PLD_IRQ_BASE)
+	bra	check_end
+	.fillinsn
+check_end:
+#elif defined(CONFIG_PLAT_OPSPUT)
+	add3	r2, r0, #-(M32R_IRQ_INT1)       ; INT1# interrupt
+	bnez	r2, check_int0
+	; read ICU status register of PLD
+	seth	r0, #high(PLD_ICUISTS)
+	or3	r0, r0, #low(PLD_ICUISTS)
+	lduh	r0, @r0
+	slli	r0, #21
+	srli	r0, #27                         ; ISN
+	addi	r0, #(OPSPUT_PLD_IRQ_BASE)
+	bra	check_end
+	.fillinsn
+check_int0:
+	add3	r2, r0, #-(M32R_IRQ_INT0)       ; INT0# interrupt
+	bnez	r2, check_int2
+	; read ICU status of LAN-board
+	seth	r0, #high(OPSPUT_LAN_ICUISTS)
+	or3	r0, r0, #low(OPSPUT_LAN_ICUISTS)
+	lduh	r0, @r0
+	slli	r0, #21
+	srli	r0, #27                         ; ISN
+	add3	r0, r0, #(OPSPUT_LAN_PLD_IRQ_BASE)
+	bra	check_end
+	.fillinsn
+check_int2:
+	add3	r2, r0, #-(M32R_IRQ_INT2)       ; INT2# interrupt
+	bnez	r2, check_end
+	; read ICU status of LCD-board
+	seth	r0, #high(OPSPUT_LCD_ICUISTS)
+	or3	r0, r0, #low(OPSPUT_LCD_ICUISTS)
+	lduh	r0, @r0
+	slli	r0, #21
+	srli	r0, #27                         ; ISN
+	add3	r0, r0, #(OPSPUT_LCD_PLD_IRQ_BASE)
+	bra	check_end
+	.fillinsn
+check_end:
+#endif  /* CONFIG_PLAT_OPSPUT */
+	bl	do_IRQ
+#endif  /* CONFIG_SMP */
+	ld	r14, @sp+
+	seth	r0, #shigh(M32R_ICU_IMASK_ADDR)
+	st	r14, @(low(M32R_ICU_IMASK_ADDR),r0)
+#else
+#error no chip configuration
+#endif
+ret_to_intr:
+	bra  ret_from_intr
+
+/*
+ * Default EIT handler
+ */
+	ALIGN
+int_msg:
+	.asciz  "Unknown interrupt\n"
+	.byte	0
+
+ENTRY(default_eit_handler)
+	push	r0
+	mvfc	r0, psw
+	push	r1
+	push	r2
+	push	r3
+	push	r0
+	LDIMM	(r0, __KERNEL_DS)
+	mv	r0, r1
+	mv	r0, r2
+	LDIMM	(r0, int_msg)
+	bl	printk
+	pop	r0
+	pop	r3
+	pop	r2
+	pop	r1
+	mvtc	r0, psw
+	pop	r0
+infinit:
+	bra	infinit
+
+#ifdef CONFIG_MMU
+/*
+ * Access Exception handler
+ */
+ENTRY(ace_handler)
+	SWITCH_TO_KERNEL_STACK
+	SAVE_ALL
+
+	seth	r2, #shigh(MMU_REG_BASE)	/* Check status register */
+	ld	r4, @(low(MESTS_offset),r2)
+	st	r4, @(low(MESTS_offset),r2)
+	srl3	r1, r4, #4
+#ifdef CONFIG_CHIP_M32700
+	and3	r1, r1, #0x0000ffff
+	; WORKAROUND: ignore TME bit for the M32700(TS1).
+#endif /* CONFIG_CHIP_M32700 */
+	beqz	r1, inst
+oprand:
+	ld	r2, @(low(MDEVA_offset),r2)	; set address
+	srli	r2, #12
+	slli	r2, #12
+	srli	r1, #1
+	bra	1f
+inst:
+	and3	r1, r4, #2
+	srli	r1, #1
+	or3	r1, r1, #8
+	mvfc	r2, bpc				; set address
+	.fillinsn
+1:
+	mvfc	r3, psw
+	mv	r0, sp
+	and3	r3, r3, 0x800
+	srli	r3, #9
+	or	r1, r3
+	/*
+	 * do_page_fault():
+	 *    r0 : struct pt_regs *regs
+	 *    r1 : unsigned long error-code
+	 *    r2 : unsigned long address
+	 * error-code:
+	 *    +------+------+------+------+
+	 *    | bit3 | bit2 | bit1 | bit0 |
+	 *    +------+------+------+------+
+	 *    bit 3 == 0:means data,          1:means instruction
+	 *    bit 2 == 0:means kernel,        1:means user-mode
+	 *    bit 1 == 0:means read,          1:means write
+	 *    bit 0 == 0:means no page found  1:means protection fault
+	 *
+	 */
+	bl	do_page_fault
+	bra	ret_from_intr
+#endif  /* CONFIG_MMU */
+
+
+ENTRY(alignment_check)
+/* void alignment_check(int error_code) */
+	SWITCH_TO_KERNEL_STACK
+	SAVE_ALL
+	ldi	r1, #0x30			; error_code
+	mv	r0, sp				; pt_regs
+	bl	do_alignment_check
+error_code:
+	bra	ret_from_exception
+
+ENTRY(rie_handler)
+/* void rie_handler(int error_code) */
+	SWITCH_TO_KERNEL_STACK
+	SAVE_ALL
+	mvfc	r0, bpc
+	ld	r1, @r0
+	seth	r0, #0xa0f0
+	st	r1, @r0
+	ldi	r1, #0x20			; error_code
+	mv	r0, sp				; pt_regs
+	bl	do_rie_handler
+	bra	error_code
+
+ENTRY(pie_handler)
+/* void pie_handler(int error_code) */
+	SWITCH_TO_KERNEL_STACK
+	SAVE_ALL
+	ldi	r1, #0				; error_code ; FIXME
+	mv	r0, sp				; pt_regs
+	bl	do_pie_handler
+	bra	error_code
+
+ENTRY(debug_trap)
+	.global	withdraw_debug_trap
+	/* void debug_trap(void) */
+	SWITCH_TO_KERNEL_STACK
+	SAVE_ALL
+	mv	r0, sp				; pt_regs
+	bl	withdraw_debug_trap
+	ldi	r1, #0				; error_code
+	mv	r0, sp				; pt_regs
+	bl	do_debug_trap
+	bra	error_code
+
+
+/* Cache flushing handler */
+ENTRY(cache_flushing_handler)
+	.global	_flush_cache_all
+	/* void _flush_cache_all(void); */
+	SWITCH_TO_KERNEL_STACK
+	push	r0
+	push	r1
+	push	r2
+	push	r3
+	push	r4
+	push	r5
+	push	r6
+	push	r7
+	push	lr
+	bl	_flush_cache_all
+	pop	lr
+	pop	r7
+	pop	r6
+	pop	r5
+	pop	r4
+	pop	r3
+	pop	r2
+	pop	r1
+	pop	r0
+	rte
+
+.data
+ENTRY(sys_call_table)
+	.long sys_restart_syscall	/* 0  -  old "setup()" system call*/
+	.long sys_exit
+	.long sys_fork
+	.long sys_read
+	.long sys_write
+	.long sys_open			/* 5 */
+	.long sys_close
+	.long sys_waitpid
+	.long sys_creat
+	.long sys_link
+	.long sys_unlink		/* 10 */
+	.long sys_execve
+	.long sys_chdir
+	.long sys_time
+	.long sys_mknod
+	.long sys_chmod			/* 15 */
+	.long sys_lchown
+	.long sys_ni_syscall		/* old break syscall holder */
+	.long sys_stat
+	.long sys_lseek
+	.long sys_getpid		/* 20 */
+	.long sys_mount
+	.long sys_oldumount
+	.long sys_setuid
+	.long sys_getuid
+	.long sys_stime			/* 25 */
+	.long sys_ptrace
+	.long sys_alarm
+	.long sys_fstat
+	.long sys_pause
+	.long sys_utime			/* 30 */
+	.long sys_cacheflush		/* for M32R */ /* old stty syscall holder */
+	.long sys_cachectl		/* for M32R */ /* old gtty syscall holder */
+	.long sys_access
+	.long sys_nice
+	.long sys_ni_syscall		/* 35  -  old ftime syscall holder */
+	.long sys_sync
+	.long sys_kill
+	.long sys_rename
+	.long sys_mkdir
+	.long sys_rmdir			/* 40 */
+	.long sys_dup
+	.long sys_pipe
+	.long sys_times
+	.long sys_ni_syscall		/* old prof syscall holder */
+	.long sys_brk			/* 45 */
+	.long sys_setgid
+	.long sys_getgid
+	.long sys_signal
+	.long sys_geteuid
+	.long sys_getegid		/* 50 */
+	.long sys_acct
+	.long sys_umount		/* recycled never used phys() */
+	.long sys_ni_syscall		/* old lock syscall holder */
+	.long sys_ioctl
+	.long sys_fcntl			/* 55 */
+	.long sys_ni_syscall		/* old mpx syscall holder */
+	.long sys_setpgid
+	.long sys_ni_syscall		/* old ulimit syscall holder */
+	.long sys_ni_syscall		/* sys_olduname */
+	.long sys_umask			/* 60 */
+	.long sys_chroot
+	.long sys_ustat
+	.long sys_dup2
+	.long sys_getppid
+	.long sys_getpgrp		/* 65 */
+	.long sys_setsid
+	.long sys_sigaction
+	.long sys_sgetmask
+	.long sys_ssetmask
+	.long sys_setreuid		/* 70 */
+	.long sys_setregid
+	.long sys_sigsuspend
+	.long sys_sigpending
+	.long sys_sethostname
+	.long sys_setrlimit		/* 75 */
+	.long sys_getrlimit
+	.long sys_getrusage
+	.long sys_gettimeofday
+	.long sys_settimeofday
+	.long sys_getgroups		/* 80 */
+	.long sys_setgroups
+	.long sys_ni_syscall		/* sys_oldselect */
+	.long sys_symlink
+	.long sys_lstat
+	.long sys_readlink		/* 85 */
+	.long sys_uselib
+	.long sys_swapon
+	.long sys_reboot
+	.long old_readdir
+	.long sys_ni_syscall		/* 90 - old_mmap syscall holder */
+	.long sys_munmap
+	.long sys_truncate
+	.long sys_ftruncate
+	.long sys_fchmod
+	.long sys_fchown		/* 95 */
+	.long sys_getpriority
+	.long sys_setpriority
+	.long sys_ni_syscall		/* old profil syscall holder */
+	.long sys_statfs
+	.long sys_fstatfs		/* 100 */
+	.long sys_ni_syscall		/* ioperm */
+	.long sys_socketcall
+	.long sys_syslog
+	.long sys_setitimer
+	.long sys_getitimer		/* 105 */
+	.long sys_newstat
+	.long sys_newlstat
+	.long sys_newfstat
+	.long sys_uname
+	.long sys_ni_syscall		/* 110  -  iopl */
+	.long sys_vhangup
+	.long sys_ni_syscall		/* for idle */
+	.long sys_ni_syscall		/* for vm86old */
+	.long sys_wait4
+	.long sys_swapoff		/* 115 */
+	.long sys_sysinfo
+	.long sys_ipc
+	.long sys_fsync
+	.long sys_sigreturn
+	.long sys_clone			/* 120 */
+	.long sys_setdomainname
+	.long sys_newuname
+	.long sys_ni_syscall		/* sys_modify_ldt */
+	.long sys_adjtimex
+	.long sys_mprotect		/* 125 */
+	.long sys_sigprocmask
+	.long sys_ni_syscall		/* sys_create_module */
+	.long sys_init_module
+	.long sys_delete_module
+	.long sys_ni_syscall		/* 130 sys_get_kernel_syms */
+	.long sys_quotactl
+	.long sys_getpgid
+	.long sys_fchdir
+	.long sys_bdflush
+	.long sys_sysfs			/* 135 */
+	.long sys_personality
+	.long sys_ni_syscall		/* for afs_syscall */
+	.long sys_setfsuid
+	.long sys_setfsgid
+	.long sys_llseek		/* 140 */
+	.long sys_getdents
+	.long sys_select
+	.long sys_flock
+	.long sys_msync
+	.long sys_readv			/* 145 */
+	.long sys_writev
+	.long sys_getsid
+	.long sys_fdatasync
+	.long sys_sysctl
+	.long sys_mlock			/* 150 */
+	.long sys_munlock
+	.long sys_mlockall
+	.long sys_munlockall
+	.long sys_sched_setparam
+	.long sys_sched_getparam	/* 155 */
+	.long sys_sched_setscheduler
+	.long sys_sched_getscheduler
+	.long sys_sched_yield
+	.long sys_sched_get_priority_max
+	.long sys_sched_get_priority_min	/* 160 */
+	.long sys_sched_rr_get_interval
+	.long sys_nanosleep
+	.long sys_mremap
+	.long sys_setresuid
+	.long sys_getresuid		/* 165 */
+	.long sys_tas			/* vm86 */
+	.long sys_ni_syscall		/* sys_query_module */
+	.long sys_poll
+	.long sys_nfsservctl
+	.long sys_setresgid		/* 170 */
+	.long sys_getresgid
+	.long sys_prctl
+	.long sys_rt_sigreturn
+	.long sys_rt_sigaction
+	.long sys_rt_sigprocmask	/* 175 */
+	.long sys_rt_sigpending
+	.long sys_rt_sigtimedwait
+	.long sys_rt_sigqueueinfo
+	.long sys_rt_sigsuspend
+	.long sys_pread64		/* 180 */
+	.long sys_pwrite64
+	.long sys_chown
+	.long sys_getcwd
+	.long sys_capget
+	.long sys_capset		/* 185 */
+	.long sys_sigaltstack
+	.long sys_sendfile
+	.long sys_ni_syscall		/* streams1 */
+	.long sys_ni_syscall		/* streams2 */
+	.long sys_vfork			/* 190 */
+	.long sys_getrlimit
+	.long sys_mmap2
+	.long sys_truncate64
+	.long sys_ftruncate64
+	.long sys_stat64		/* 195 */
+	.long sys_lstat64
+	.long sys_fstat64
+	.long sys_lchown
+	.long sys_getuid
+	.long sys_getgid		/* 200 */
+	.long sys_geteuid
+	.long sys_getegid
+	.long sys_setreuid
+	.long sys_setregid
+	.long sys_getgroups		/* 205 */
+	.long sys_setgroups
+	.long sys_fchown
+	.long sys_setresuid
+	.long sys_getresuid
+	.long sys_setresgid		/* 210 */
+	.long sys_getresgid
+	.long sys_chown
+	.long sys_setuid
+	.long sys_setgid
+	.long sys_setfsuid		/* 215 */
+	.long sys_setfsgid
+	.long sys_pivot_root
+	.long sys_mincore
+	.long sys_madvise
+	.long sys_getdents64		/* 220 */
+	.long sys_fcntl64
+	.long sys_ni_syscall		/* reserved for TUX */
+	.long sys_ni_syscall		/* Reserved for Security */
+	.long sys_gettid
+	.long sys_readahead		/* 225 */
+	.long sys_setxattr
+	.long sys_lsetxattr
+	.long sys_fsetxattr
+	.long sys_getxattr
+	.long sys_lgetxattr		/* 230 */
+	.long sys_fgetxattr
+	.long sys_listxattr
+	.long sys_llistxattr
+	.long sys_flistxattr
+	.long sys_removexattr		/* 235 */
+	.long sys_lremovexattr
+	.long sys_fremovexattr
+	.long sys_tkill
+	.long sys_sendfile64
+	.long sys_futex			/* 240 */
+	.long sys_sched_setaffinity
+	.long sys_sched_getaffinity
+	.long sys_ni_syscall		/* reserved for "set_thread_area" system call */
+	.long sys_ni_syscall		/* reserved for "get_thread_area" system call */
+	.long sys_io_setup		/* 245 */
+	.long sys_io_destroy
+	.long sys_io_getevents
+	.long sys_io_submit
+	.long sys_io_cancel
+	.long sys_fadvise64		/* 250 */
+	.long sys_ni_syscall
+	.long sys_exit_group
+	.long sys_lookup_dcookie
+	.long sys_epoll_create
+	.long sys_epoll_ctl		/* 255 */
+	.long sys_epoll_wait
+ 	.long sys_remap_file_pages
+ 	.long sys_set_tid_address
+ 	.long sys_timer_create
+ 	.long sys_timer_settime		/* 260 */
+ 	.long sys_timer_gettime
+ 	.long sys_timer_getoverrun
+ 	.long sys_timer_delete
+ 	.long sys_clock_settime
+ 	.long sys_clock_gettime		/* 265 */
+ 	.long sys_clock_getres
+ 	.long sys_clock_nanosleep
+	.long sys_statfs64
+	.long sys_fstatfs64
+	.long sys_tgkill		/* 270 */
+	.long sys_utimes
+ 	.long sys_fadvise64_64
+	.long sys_ni_syscall		/* Reserved for sys_vserver */
+        .long sys_ni_syscall		/* Reserved for sys_mbind */
+        .long sys_ni_syscall		/* Reserved for sys_get_mempolicy */
+        .long sys_ni_syscall		/* Reserved for sys_set_mempolicy */
+        .long sys_mq_open
+        .long sys_mq_unlink
+        .long sys_mq_timedsend
+        .long sys_mq_timedreceive       /* 280 */
+        .long sys_mq_notify
+        .long sys_mq_getsetattr
+        .long sys_ni_syscall            /* reserved for kexec */
+	.long sys_waitid
+
+syscall_table_size=(.-sys_call_table)
+
diff -Nru a/arch/m32r/kernel/head.S b/arch/m32r/kernel/head.S
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/arch/m32r/kernel/head.S	2004-10-18 14:57:23 -07:00
@@ -0,0 +1,287 @@
+/*
+ *  linux/arch/m32r/kernel/head.S
+ *
+ *  M32R startup code.
+ *
+ *  Copyright (c) 2001, 2002  Hiroyuki Kondo, Hirokazu Takata,
+ *                            Hitoshi Yamamoto
+ */
+
+/* $Id$ */
+
+#include <linux/init.h>
+__INIT
+__INITDATA
+
+	.text
+#include <linux/config.h>
+#include <linux/linkage.h>
+#include <asm/segment.h>
+#include <asm/page.h>
+#include <asm/pgtable.h>
+#include <asm/assembler.h>
+#include <asm/m32r.h>
+#include <asm/mmu_context.h>
+
+/*
+ * References to members of the boot_cpu_data structure.
+ */
+	.text
+	.global	start_kernel
+	.global __bss_start
+	.global _end
+ENTRY(stext)
+ENTRY(_stext)
+ENTRY(startup_32)
+	/* Setup up the stack pointer */
+	LDIMM	(r0, spi_stack_top)
+	LDIMM	(r1, spu_stack_top)
+	mvtc	r0, spi
+	mvtc	r1, spu
+
+	/* Initilalize PSW */
+	ldi	r0, #0x0000		/* use SPI, disable EI */
+	mvtc	r0, psw
+
+	/* Set up the stack pointer */
+	LDIMM	(r0, stack_start)
+	ld	r0, @r0
+	mvtc	r0, spi
+
+/*
+ * Clear BSS first so that there are no surprises...
+ */
+#ifdef CONFIG_ISA_DUAL_ISSUE
+
+	LDIMM	(r2, __bss_start)
+	LDIMM	(r3, _end)
+	sub	r3, r2		; BSS size in bytes
+	; R4 = BSS size in longwords (rounded down)
+	mv	r4, r3		    ||	ldi	r1, #0
+	srli	r4, #4		    ||	addi	r2, #-4
+	beqz	r4, .Lendloop1
+.Lloop1:
+#ifndef CONFIG_CHIP_M32310
+	; Touch memory for the no-write-allocating cache.
+	ld	r0, @(4,r2)
+#endif
+	st	r1, @+r2	    ||	addi	r4, #-1
+	st	r1, @+r2
+	st	r1, @+r2
+	st	r1, @+r2	    ||	cmpeq	r1, r4	; R4 = 0?
+	bnc	.Lloop1
+.Lendloop1:
+	and3	r4, r3, #15
+	addi	r2, #4
+	beqz	r4, .Lendloop2
+.Lloop2:
+	stb	r1, @r2		    ||	addi	r4, #-1
+	addi	r2, #1
+	bnez	r4, .Lloop2
+.Lendloop2:
+
+#else /* not CONFIG_ISA_DUAL_ISSUE */
+
+	LDIMM	(r2, __bss_start)
+	LDIMM	(r3, _end)
+	sub	r3, r2		; BSS size in bytes
+	mv	r4, r3
+	srli	r4, #2		; R4 = BSS size in longwords (rounded down)
+	ldi	r1, #0		; clear R1 for longwords store
+	addi	r2, #-4		; account for pre-inc store
+	beqz	r4, .Lendloop1	; any more to go?
+.Lloop1:
+	st	r1, @+r2	; yep, zero out another longword
+	addi	r4, #-1		; decrement count
+	bnez	r4, .Lloop1	; go do some more
+.Lendloop1:
+	and3	r4, r3, #3	; get no. of remaining BSS bytes to clear
+	addi	r2, #4		; account for pre-inc store
+	beqz	r4, .Lendloop2	; any more to go?
+.Lloop2:
+	stb	r1, @r2		; yep, zero out another byte
+	addi	r2, #1		; bump address
+	addi	r4, #-1		; decrement count
+	bnez	r4, .Lloop2	; go do some more
+.Lendloop2:
+
+#endif /* not CONFIG_ISA_DUAL_ISSUE */
+
+#if 0  /* M32R_FIXME */
+/*
+ * Copy data segment from ROM to RAM.
+ */
+	.global ROM_D, TOP_DATA, END_DATA
+
+	LDIMM	(r1, ROM_D)
+	LDIMM	(r2, TOP_DATA)
+	LDIMM	(r3, END_DATA)
+	addi	r2, #-4
+	addi	r3, #-4
+loop1:
+	ld	r0, @r1+
+	st	r0, @+r2
+	cmp	r2, r3
+	bc	loop1
+#endif /* 0 */
+
+/* Jump to kernel */
+	LDIMM	(r2, start_kernel)
+	jl	r2
+	.fillinsn
+1:
+	bra	1b		; main should never return here, but
+				; just in case, we know what happens.
+
+#ifdef CONFIG_SMP
+/*
+ * AP startup routine
+ */
+	.text
+	.global	eit_vector
+ENTRY(startup_AP)
+;; setup EVB
+	LDIMM  (r4, eit_vector)
+	mvtc   r4, cr5
+
+;; enable MMU
+	LDIMM	(r2, init_tlb)
+	jl	r2
+	seth  r4, #high(MATM)
+	or3   r4, r4, #low(MATM)
+	ldi   r5, #0x01
+	st    r5, @r4            ; Set MATM Reg(T bit ON)
+	ld    r6, @r4            ; MATM Check
+	LDIMM (r5, 1f)
+	jmp   r5                 ; enable MMU
+	nop
+	.fillinsn
+1:
+;; ISN check
+	ld    r6, @r4            ; MATM Check
+	seth  r4, #high(M32R_ICU_ISTS_ADDR)
+	or3   r4, r4, #low(M32R_ICU_ISTS_ADDR)
+	ld    r5, @r4		; Read ISTSi reg.
+	mv    r6, r5
+	slli  r5, #13  ; PIML check
+	srli  r5, #13  ;
+	seth  r4, #high(M32R_ICU_IMASK_ADDR)
+	or3   r4, r4, #low(M32R_ICU_IMASK_ADDR)
+	st    r5, @r4		; Write IMASKi reg.
+	slli  r6, #4   ; ISN check
+	srli  r6, #26  ;
+	seth  r4, #high(M32R_IRQ_IPI5)
+	or3   r4, r4, #low(M32R_IRQ_IPI5)
+	bne   r4, r6, 2f  ; if (ISN != CPU_BOOT_IPI) goto sleep;
+
+;; check cpu_bootout_map and set cpu_bootin_map
+	LDIMM (r4, cpu_bootout_map)
+	ld    r4, @r4
+	seth  r5, #high(M32R_CPUID_PORTL)
+	or3   r5, r5, #low(M32R_CPUID_PORTL)
+	ld    r5, @r5
+	ldi   r6, #1
+	sll   r6, r5
+	and   r4, r6
+	beqz  r4, 2f
+	LDIMM (r4, cpu_bootin_map)
+	ld    r5, @r4
+	or    r5, r6
+	st    r6, @r4
+
+;; clear PSW
+	ldi   r4, #0
+	mvtc  r4, psw
+
+;; setup SPI
+	LDIMM (r4, stack_start)
+	ld    r4, @r4
+	mvtc  r4, spi
+
+;; setup BPC (start_secondary)
+	LDIMM (r4, start_secondary)
+	mvtc  r4, bpc
+
+	rte  ; goto startup_secondary
+	nop
+	nop
+
+	.fillinsn
+2:
+	;; disable MMU
+	seth  r4, #high(MATM)
+	or3   r4, r4, #low(MATM)
+	ldi   r5, #0
+    	st    r5, @r4            ; Set MATM Reg(T bit OFF)
+    	ld    r6, @r4            ; MATM Check
+	LDIMM (r4, 3f)
+	seth  r5, #high(__PAGE_OFFSET)
+	or3   r5, r5, #low(__PAGE_OFFSET)
+	not   r5, r5
+	and   r4, r5
+	jmp   r4                 ; disable MMU
+	nop
+	.fillinsn
+3:
+	;; SLEEP and wait IPI
+	LDIMM (r4, AP_loop)
+	seth  r5, #high(__PAGE_OFFSET)
+	or3   r5, r5, #low(__PAGE_OFFSET)
+	not   r5, r5
+	and   r4, r5
+	jmp   r4
+	nop
+	nop
+#endif  /* CONFIG_SMP */
+
+ENTRY(stack_start)
+	.long	init_thread_union+8192
+	.long	__KERNEL_DS
+
+/*
+ * This is initialized to create a identity-mapping at 0-4M (for bootup
+ * purposes) and another mapping of the 0-4M area at virtual address
+ * PAGE_OFFSET.
+ */
+	.text
+
+#define  MOUNT_ROOT_RDONLY    1
+#define  RAMDISK_FLAGS        0		; 1024KB
+#define  ORIG_ROOT_DEV        0x0100	; /dev/ram0 (major:01, minor:00)
+#define  LOADER_TYPE          1		; (??? - non-zero value seems
+					; to be needed to boot from initrd)
+
+#define  COMMAND_LINE ""
+
+	.section	.empty_zero_page, "aw"
+ENTRY(empty_zero_page)
+	.long	MOUNT_ROOT_RDONLY		/* offset: +0x00 */
+	.long	RAMDISK_FLAGS
+	.long	ORIG_ROOT_DEV
+	.long	LOADER_TYPE
+	.long	0	/* INITRD_START */	/* +0x10 */
+	.long	0	/* INITRD_SIZE */
+	.long	0	/* CPU_CLOCK */
+	.long	0	/* BUS_CLOCK */
+	.long	0	/* TIMER_DIVIDE */	/* +0x20 */
+	.balign	256,0
+	.asciz	COMMAND_LINE
+  	.byte	0
+	.balign	4096,0,4096
+
+/*------------------------------------------------------------------------
+ * Stack area
+ */
+	.section .spi
+	ALIGN
+	.global spi_stack_top
+	.zero	1024
+spi_stack_top:
+
+	.section .spu
+	ALIGN
+	.global spu_stack_top
+	.zero	1024
+spu_stack_top:
+
+	.end
diff -Nru a/arch/m32r/kernel/init_task.c b/arch/m32r/kernel/init_task.c
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/arch/m32r/kernel/init_task.c	2004-10-18 14:57:23 -07:00
@@ -0,0 +1,41 @@
+/* orig : i386 init_task.c */
+
+#include <linux/mm.h>
+#include <linux/module.h>
+#include <linux/sched.h>
+#include <linux/init.h>
+#include <linux/init_task.h>
+#include <linux/fs.h>
+#include <linux/mqueue.h>
+
+#include <asm/uaccess.h>
+#include <asm/pgtable.h>
+
+static struct fs_struct init_fs = INIT_FS;
+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);
+struct mm_struct init_mm = INIT_MM(init_mm);
+
+EXPORT_SYMBOL(init_mm);
+
+/*
+ * Initial thread structure.
+ *
+ * We need to make sure that this is 8192-byte aligned due to the
+ * way process stacks are handled. This is done by having a special
+ * "init_task" linker map entry..
+ */
+union thread_union init_thread_union
+	__attribute__((__section__(".data.init_task"))) =
+		{ INIT_THREAD_INFO(init_task) };
+
+/*
+ * Initial task structure.
+ *
+ * All other task structs will be allocated on slabs in fork.c
+ */
+struct task_struct init_task = INIT_TASK(init_task);
+
+EXPORT_SYMBOL(init_task);
+
diff -Nru a/arch/m32r/kernel/io_m32700ut.c b/arch/m32r/kernel/io_m32700ut.c
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/arch/m32r/kernel/io_m32700ut.c	2004-10-18 14:57:23 -07:00
@@ -0,0 +1,455 @@
+/*
+ *  linux/arch/m32r/kernel/io_mappi.c
+ *
+ *  Typical I/O routines for M32700UT board.
+ *
+ *  Copyright (c) 2001, 2002  Hiroyuki Kondo, Hirokazu Takata,
+ *                            Hitoshi Yamamoto, Takeo Takahashi
+ *
+ *  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.
+ *
+ */
+
+#include <linux/config.h>
+#include <asm/m32r.h>
+#include <asm/page.h>
+#include <asm/io.h>
+#include <asm/byteorder.h>
+
+#if defined(CONFIG_PCMCIA) && defined(CONFIG_M32R_CFC)
+#include <linux/types.h>
+
+#define M32R_PCC_IOMAP_SIZE 0x1000
+
+#define M32R_PCC_IOSTART0 0x1000
+#define M32R_PCC_IOEND0   (M32R_PCC_IOSTART0 + M32R_PCC_IOMAP_SIZE - 1)
+
+extern void pcc_ioread_byte(int, unsigned long, void *, size_t, size_t, int);
+extern void pcc_ioread_word(int, unsigned long, void *, size_t, size_t, int);
+extern void pcc_iowrite_byte(int, unsigned long, void *, size_t, size_t, int);
+extern void pcc_iowrite_word(int, unsigned long, void *, size_t, size_t, int);
+#endif /* CONFIG_PCMCIA && CONFIG_M32R_CFC */
+
+#define PORT2ADDR(port)  _port2addr(port)
+#define PORT2ADDR_USB(port) _port2addr_usb(port)
+
+static __inline__ void *_port2addr(unsigned long port)
+{
+	return (void *)(port + NONCACHE_OFFSET);
+}
+
+#if defined(CONFIG_IDE) && !defined(CONFIG_M32R_CFC)
+static __inline__ void *__port2addr_ata(unsigned long port)
+{
+	static int	dummy_reg;
+
+	switch (port) {
+	case 0x1f0:	return (void *)0xac002000;
+	case 0x1f1:	return (void *)0xac012800;
+	case 0x1f2:	return (void *)0xac012002;
+	case 0x1f3:	return (void *)0xac012802;
+	case 0x1f4:	return (void *)0xac012004;
+	case 0x1f5:	return (void *)0xac012804;
+	case 0x1f6:	return (void *)0xac012006;
+	case 0x1f7:	return (void *)0xac012806;
+	case 0x3f6:	return (void *)0xac01200e;
+	default: 	return (void *)&dummy_reg;
+	}
+}
+#endif
+
+/*
+ * M32700UT-LAN is located in the extended bus space
+ * from 0x10000000 to 0x13ffffff on physical address.
+ * The base address of LAN controller(LAN91C111) is 0x300.
+ */
+#define LAN_IOSTART	0x300
+#define LAN_IOEND	0x320
+static __inline__ void *_port2addr_ne(unsigned long port)
+{
+	return (void *)(port + NONCACHE_OFFSET + 0x10000000);
+}
+static __inline__ void *_port2addr_usb(unsigned long port)
+{
+  return (void *)((port & 0x0f) + NONCACHE_OFFSET + 0x10303000);
+}
+
+static __inline__ void delay(void)
+{
+	__asm__ __volatile__ ("push r0; \n\t pop r0;" : : :"memory");
+}
+
+/*
+ * NIC I/O function
+ */
+
+#define PORT2ADDR_NE(port)  _port2addr_ne(port)
+
+static __inline__ unsigned char _ne_inb(void *portp)
+{
+	return *(volatile unsigned char *)portp;
+}
+
+static __inline__ unsigned short _ne_inw(void *portp)
+{
+	return (unsigned short)le16_to_cpu(*(volatile unsigned short *)portp);
+}
+
+static __inline__ void _ne_insb(void *portp, void * addr, unsigned long count)
+{
+	unsigned char *buf = (unsigned char *)addr;
+
+	while (count--) *buf++ = _ne_inb(portp);
+}
+
+static __inline__ void _ne_outb(unsigned char b, void *portp)
+{
+	*(volatile unsigned char *)portp = b;
+}
+
+static __inline__ void _ne_outw(unsigned short w, void *portp)
+{
+	*(volatile unsigned short *)portp = cpu_to_le16(w);
+}
+
+unsigned char _inb(unsigned long port)
+{
+	if (port >= LAN_IOSTART && port < LAN_IOEND)
+		return _ne_inb(PORT2ADDR_NE(port));
+
+#if defined(CONFIG_IDE) && !defined(CONFIG_M32R_CFC)
+	else if ((port >= 0x1f0 && port <=0x1f7) || port == 0x3f6) {
+		return *(volatile unsigned char *)__port2addr_ata(port);
+	}
+#endif
+#if defined(CONFIG_PCMCIA) && defined(CONFIG_M32R_CFC)
+	else if (port >= M32R_PCC_IOSTART0 && port <= M32R_PCC_IOEND0) {
+	   unsigned char b;
+	   pcc_ioread_byte(0, port, &b, sizeof(b), 1, 0);
+	   return b;
+	} else
+#endif
+
+	return *(volatile unsigned char *)PORT2ADDR(port);
+}
+
+unsigned short _inw(unsigned long port)
+{
+	if (port >= LAN_IOSTART && port < LAN_IOEND)
+		return _ne_inw(PORT2ADDR_NE(port));
+#if defined(CONFIG_IDE) && !defined(CONFIG_M32R_CFC)
+	else if ((port >= 0x1f0 && port <=0x1f7) || port == 0x3f6) {
+		return *(volatile unsigned short *)__port2addr_ata(port);
+	}
+#endif
+#if defined(CONFIG_USB)
+	else if(port >= 0x340 && port < 0x3a0)
+	  return *(volatile unsigned short *)PORT2ADDR_USB(port);
+#endif
+#if defined(CONFIG_PCMCIA) && defined(CONFIG_M32R_CFC)
+	else if (port >= M32R_PCC_IOSTART0 && port <= M32R_PCC_IOEND0) {
+	   unsigned short w;
+	   pcc_ioread_word(0, port, &w, sizeof(w), 1, 0);
+	   return w;
+	} else
+#endif
+	return *(volatile unsigned short *)PORT2ADDR(port);
+}
+
+unsigned long _inl(unsigned long port)
+{
+#if defined(CONFIG_PCMCIA) && defined(CONFIG_M32R_CFC)
+	if (port >= M32R_PCC_IOSTART0 && port <= M32R_PCC_IOEND0) {
+	   unsigned long l;
+	   pcc_ioread_word(0, port, &l, sizeof(l), 1, 0);
+	   return l;
+	} else
+#endif
+	return *(volatile unsigned long *)PORT2ADDR(port);
+}
+
+unsigned char _inb_p(unsigned long port)
+{
+	unsigned char  v;
+
+	if (port >= LAN_IOSTART && port < LAN_IOEND)
+		v = _ne_inb(PORT2ADDR_NE(port));
+	else
+#if defined(CONFIG_IDE) && !defined(CONFIG_M32R_CFC)
+	if ((port >= 0x1f0 && port <=0x1f7) || port == 0x3f6) {
+		return *(volatile unsigned char *)__port2addr_ata(port);
+	} else
+#endif
+#if defined(CONFIG_PCMCIA) && defined(CONFIG_M32R_CFC)
+	if (port >= M32R_PCC_IOSTART0 && port <= M32R_PCC_IOEND0) {
+	   unsigned char b;
+	   pcc_ioread_byte(0, port, &b, sizeof(b), 1, 0);
+	   return b;
+	} else
+#endif
+		v = *(volatile unsigned char *)PORT2ADDR(port);
+
+	delay();
+	return (v);
+}
+
+unsigned short _inw_p(unsigned long port)
+{
+	unsigned short  v;
+
+	if (port >= LAN_IOSTART && port < LAN_IOEND)
+		v = _ne_inw(PORT2ADDR_NE(port));
+	else
+#if defined(CONFIG_IDE) && !defined(CONFIG_M32R_CFC)
+	if ((port >= 0x1f0 && port <=0x1f7) || port == 0x3f6) {
+		return *(volatile unsigned short *)__port2addr_ata(port);
+	} else
+#endif
+#if defined(CONFIG_USB)
+	  if(port >= 0x340 && port < 0x3a0)
+	    return *(volatile unsigned short *)PORT2ADDR_USB(port);
+	else
+#endif
+#if defined(CONFIG_PCMCIA) && defined(CONFIG_M32R_CFC)
+	if (port >= M32R_PCC_IOSTART0 && port <= M32R_PCC_IOEND0) {
+	   unsigned short w;
+	   pcc_ioread_word(0, port, &w, sizeof(w), 1, 0);
+	   return w;
+	} else
+#endif
+		v = *(volatile unsigned short *)PORT2ADDR(port);
+
+	delay();
+	return (v);
+}
+
+unsigned long _inl_p(unsigned long port)
+{
+	unsigned long  v;
+
+	v = *(volatile unsigned long *)PORT2ADDR(port);
+	delay();
+	return (v);
+}
+
+void _outb(unsigned char b, unsigned long port)
+{
+	if (port >= LAN_IOSTART && port < LAN_IOEND)
+		_ne_outb(b, PORT2ADDR_NE(port));
+	else
+#if defined(CONFIG_IDE) && !defined(CONFIG_M32R_CFC)
+	if ((port >= 0x1f0 && port <=0x1f7) || port == 0x3f6) {
+		*(volatile unsigned char *)__port2addr_ata(port) = b;
+	} else
+#endif
+#if defined(CONFIG_PCMCIA) && defined(CONFIG_M32R_CFC)
+	if (port >= M32R_PCC_IOSTART0 && port <= M32R_PCC_IOEND0) {
+	   pcc_iowrite_byte(0, port, &b, sizeof(b), 1, 0);
+	} else
+#endif
+		*(volatile unsigned char *)PORT2ADDR(port) = b;
+}
+
+void _outw(unsigned short w, unsigned long port)
+{
+	if (port >= LAN_IOSTART && port < LAN_IOEND)
+		_ne_outw(w, PORT2ADDR_NE(port));
+	else
+#if defined(CONFIG_IDE) && !defined(CONFIG_M32R_CFC)
+	if ((port >= 0x1f0 && port <=0x1f7) || port == 0x3f6) {
+		*(volatile unsigned short *)__port2addr_ata(port) = w;
+	} else
+#endif
+#if defined(CONFIG_USB)
+	if(port >= 0x340 && port < 0x3a0)
+	  *(volatile unsigned short *)PORT2ADDR_USB(port) = w;
+	else
+#endif
+#if defined(CONFIG_PCMCIA) && defined(CONFIG_M32R_CFC)
+	if (port >= M32R_PCC_IOSTART0 && port <= M32R_PCC_IOEND0) {
+	   pcc_iowrite_word(0, port, &w, sizeof(w), 1, 0);
+	} else
+#endif
+		*(volatile unsigned short *)PORT2ADDR(port) = w;
+}
+
+void _outl(unsigned long l, unsigned long port)
+{
+#if defined(CONFIG_PCMCIA) && defined(CONFIG_M32R_CFC)
+	if (port >= M32R_PCC_IOSTART0 && port <= M32R_PCC_IOEND0) {
+	   pcc_iowrite_word(0, port, &l, sizeof(l), 1, 0);
+	} else
+#endif
+	*(volatile unsigned long *)PORT2ADDR(port) = l;
+}
+
+void _outb_p(unsigned char b, unsigned long port)
+{
+	if (port >= LAN_IOSTART && port < LAN_IOEND)
+		_ne_outb(b, PORT2ADDR_NE(port));
+	else
+#if defined(CONFIG_IDE) && !defined(CONFIG_M32R_CFC)
+	if ((port >= 0x1f0 && port <=0x1f7) || port == 0x3f6) {
+		*(volatile unsigned char *)__port2addr_ata(port) = b;
+	} else
+#endif
+#if defined(CONFIG_PCMCIA) && defined(CONFIG_M32R_CFC)
+	if (port >= M32R_PCC_IOSTART0 && port <= M32R_PCC_IOEND0) {
+	   pcc_iowrite_byte(0, port, &b, sizeof(b), 1, 0);
+	} else
+#endif
+		*(volatile unsigned char *)PORT2ADDR(port) = b;
+
+	delay();
+}
+
+void _outw_p(unsigned short w, unsigned long port)
+{
+	if (port >= LAN_IOSTART && port < LAN_IOEND)
+		_ne_outw(w, PORT2ADDR_NE(port));
+	else
+#if defined(CONFIG_IDE) && !defined(CONFIG_M32R_CFC)
+	if ((port >= 0x1f0 && port <=0x1f7) || port == 0x3f6) {
+		*(volatile unsigned short *)__port2addr_ata(port) = w;
+	} else
+#endif
+#if defined(CONFIG_USB)
+	  if(port >= 0x340 && port < 0x3a0)
+	    *(volatile unsigned short *)PORT2ADDR_USB(port) = w;
+	else
+#endif
+#if defined(CONFIG_PCMCIA) && defined(CONFIG_M32R_CFC)
+	if (port >= M32R_PCC_IOSTART0 && port <= M32R_PCC_IOEND0) {
+	   pcc_iowrite_word(0, port, &w, sizeof(w), 1, 0);
+	} else
+#endif
+		*(volatile unsigned short *)PORT2ADDR(port) = w;
+
+	delay();
+}
+
+void _outl_p(unsigned long l, unsigned long port)
+{
+	*(volatile unsigned long *)PORT2ADDR(port) = l;
+	delay();
+}
+
+void _insb(unsigned int port, void * addr, unsigned long count)
+{
+	if (port >= LAN_IOSTART && port < LAN_IOEND)
+		_ne_insb(PORT2ADDR_NE(port), addr, count);
+#if defined(CONFIG_IDE) && !defined(CONFIG_M32R_CFC)
+	else if ((port >= 0x1f0 && port <=0x1f7) || port == 0x3f6) {
+		unsigned char *buf = addr;
+		unsigned char *portp = __port2addr_ata(port);
+		while(count--) *buf++ = *(volatile unsigned char *)portp;
+	}
+#endif
+#if defined(CONFIG_PCMCIA) && defined(CONFIG_M32R_CFC)
+	  else if (port >= M32R_PCC_IOSTART0 && port <= M32R_PCC_IOEND0) {
+	   pcc_ioread_byte(0, port, (void *)addr, sizeof(unsigned char), count, 1);
+	}
+#endif
+	else {
+		unsigned char *buf = addr;
+		unsigned char *portp = PORT2ADDR(port);
+		while(count--) *buf++ = *(volatile unsigned char *)portp;
+	}
+}
+
+void _insw(unsigned int port, void * addr, unsigned long count)
+{
+	unsigned short *buf = addr;
+	unsigned short *portp;
+
+	if (port >= LAN_IOSTART && port < LAN_IOEND) {
+		/*
+		 * This portion is only used by smc91111.c to read data
+		 * from the DATA_REG. Do not swap the data.
+		 */
+		portp = PORT2ADDR_NE(port);
+		while (count--) *buf++ = *(volatile unsigned short *)portp;
+#if defined(CONFIG_PCMCIA) && defined(CONFIG_M32R_CFC)
+	} else if (port >= M32R_PCC_IOSTART0 && port <= M32R_PCC_IOEND0) {
+	   pcc_ioread_word(9, port, (void *)addr, sizeof(unsigned short), count, 1);
+#endif
+#if defined(CONFIG_IDE) && !defined(CONFIG_M32R_CFC)
+	} else if ((port >= 0x1f0 && port <=0x1f7) || port == 0x3f6) {
+		portp = __port2addr_ata(port);
+		while (count--) *buf++ = *(volatile unsigned short *)portp;
+#endif
+	} else {
+		portp = PORT2ADDR(port);
+		while (count--) *buf++ = *(volatile unsigned short *)portp;
+	}
+}
+
+void _insl(unsigned int port, void * addr, unsigned long count)
+{
+	unsigned long *buf = addr;
+	unsigned long *portp;
+
+	portp = PORT2ADDR(port);
+	while (count--) *buf++ = *(volatile unsigned long *)portp;
+}
+
+void _outsb(unsigned int port, const void * addr, unsigned long count)
+{
+	const unsigned char *buf = addr;
+	unsigned char *portp;
+
+	if (port >= LAN_IOSTART && port < LAN_IOEND) {
+		portp = PORT2ADDR_NE(port);
+		while (count--) _ne_outb(*buf++, portp);
+#if defined(CONFIG_IDE) && !defined(CONFIG_M32R_CFC)
+	} else if ((port >= 0x1f0 && port <=0x1f7) || port == 0x3f6) {
+		portp = __port2addr_ata(port);
+		while(count--) *(volatile unsigned char *)portp = *buf++;
+#endif
+#if defined(CONFIG_PCMCIA) && defined(CONFIG_M32R_CFC)
+	} else if (port >= M32R_PCC_IOSTART0 && port <= M32R_PCC_IOEND0) {
+	   pcc_iowrite_byte(0, port, (void *)addr, sizeof(unsigned char), count, 1);
+#endif
+	} else {
+		portp = PORT2ADDR(port);
+		while(count--) *(volatile unsigned char *)portp = *buf++;
+	}
+}
+
+void _outsw(unsigned int port, const void * addr, unsigned long count)
+{
+	const unsigned short *buf = addr;
+	unsigned short *portp;
+
+	if (port >= LAN_IOSTART && port < LAN_IOEND) {
+		/*
+		 * This portion is only used by smc91111.c to write data
+		 * into the DATA_REG. Do not swap the data.
+		 */
+		portp = PORT2ADDR_NE(port);
+		while(count--) *(volatile unsigned short *)portp = *buf++;
+#if defined(CONFIG_IDE) && !defined(CONFIG_M32R_CFC)
+	} else if ((port >= 0x1f0 && port <=0x1f7) || port == 0x3f6) {
+		portp = __port2addr_ata(port);
+		while(count--) *(volatile unsigned short *)portp = *buf++;
+#endif
+#if defined(CONFIG_PCMCIA) && defined(CONFIG_M32R_CFC)
+	} else if (port >= M32R_PCC_IOSTART0 && port <= M32R_PCC_IOEND0) {
+	   pcc_iowrite_word(9, port, (void *)addr, sizeof(unsigned short), count, 1);
+#endif
+	} else {
+		portp = PORT2ADDR(port);
+		while(count--) *(volatile unsigned short *)portp = *buf++;
+	}
+}
+
+void _outsl(unsigned int port, const void * addr, unsigned long count)
+{
+	const unsigned long *buf = addr;
+	unsigned char *portp;
+
+	portp = PORT2ADDR(port);
+	while(count--) *(volatile unsigned long *)portp = *buf++;
+}
diff -Nru a/arch/m32r/kernel/io_mappi.c b/arch/m32r/kernel/io_mappi.c
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/arch/m32r/kernel/io_mappi.c	2004-10-18 14:57:22 -07:00
@@ -0,0 +1,368 @@
+/*
+ *  linux/arch/m32r/kernel/io_mappi.c
+ *
+ *  Typical I/O routines for Mappi board.
+ *
+ *  Copyright (c) 2001, 2002  Hiroyuki Kondo, Hirokazu Takata,
+ *                            Hitoshi Yamamoto
+ */
+
+/* $Id: io_mappi.c,v 1.9 2003/12/02 07:18:08 fujiwara Exp $ */
+
+#include <linux/config.h>
+#include <asm/m32r.h>
+#include <asm/page.h>
+#include <asm/io.h>
+#include <asm/byteorder.h>
+
+#if defined(CONFIG_PCMCIA) && defined(CONFIG_M32RPCC)
+#include <linux/types.h>
+
+#define M32R_PCC_IOMAP_SIZE 0x1000
+
+#define M32R_PCC_IOSTART0 0x1000
+#define M32R_PCC_IOEND0   (M32R_PCC_IOSTART0 + M32R_PCC_IOMAP_SIZE - 1)
+#define M32R_PCC_IOSTART1 0x2000
+#define M32R_PCC_IOEND1   (M32R_PCC_IOSTART1 + M32R_PCC_IOMAP_SIZE - 1)
+
+extern void pcc_ioread(int, unsigned long, void *, size_t, size_t, int);
+extern void pcc_iowrite(int, unsigned long, void *, size_t, size_t, int);
+#endif /* CONFIG_PCMCIA && CONFIG_M32RPCC */
+
+#define PORT2ADDR(port)  _port2addr(port)
+
+static __inline__ void *_port2addr(unsigned long port)
+{
+	return (void *)(port + NONCACHE_OFFSET);
+}
+
+static __inline__ void *_port2addr_ne(unsigned long port)
+{
+	return (void *)((port<<1) + NONCACHE_OFFSET + 0x0C000000);
+}
+
+static __inline__ void delay(void)
+{
+	__asm__ __volatile__ ("push r0; \n\t pop r0;" : : :"memory");
+}
+
+/*
+ * NIC I/O function
+ */
+
+#define PORT2ADDR_NE(port)  _port2addr_ne(port)
+
+static __inline__ unsigned char _ne_inb(void *portp)
+{
+	return (unsigned char) *(volatile unsigned short *)portp;
+}
+
+static __inline__ unsigned short _ne_inw(void *portp)
+{
+	unsigned short tmp;
+
+	tmp = *(volatile unsigned short *)portp;
+	return le16_to_cpu(tmp);
+}
+
+static __inline__ void _ne_outb(unsigned char b, void *portp)
+{
+	*(volatile unsigned short *)portp = (unsigned short)b;
+}
+
+static __inline__ void _ne_outw(unsigned short w, void *portp)
+{
+	*(volatile unsigned short *)portp = cpu_to_le16(w);
+}
+
+unsigned char _inb(unsigned long port)
+{
+	if (port >= 0x300 && port < 0x320)
+		return _ne_inb(PORT2ADDR_NE(port));
+	else
+#if defined(CONFIG_PCMCIA) && defined(CONFIG_M32RPCC)
+        if (port >= M32R_PCC_IOSTART0 && port <= M32R_PCC_IOEND0) {
+	   unsigned char b;
+	   pcc_ioread(0, port, &b, sizeof(b), 1, 0);
+	   return b;
+	} else 	if (port >= M32R_PCC_IOSTART1 && port <= M32R_PCC_IOEND1) {
+	  unsigned char b;
+	   pcc_ioread(1, port, &b, sizeof(b), 1, 0);
+	   return b;
+	} else
+#endif
+
+	return *(volatile unsigned char *)PORT2ADDR(port);
+}
+
+unsigned short _inw(unsigned long port)
+{
+	if (port >= 0x300 && port < 0x320)
+		return _ne_inw(PORT2ADDR_NE(port));
+	else
+#if defined(CONFIG_PCMCIA) && defined(CONFIG_M32RPCC)
+	if (port >= M32R_PCC_IOSTART0 && port <= M32R_PCC_IOEND0) {
+	   unsigned short w;
+	   pcc_ioread(0, port, &w, sizeof(w), 1, 0);
+	   return w;
+	} else 	if (port >= M32R_PCC_IOSTART1 && port <= M32R_PCC_IOEND1) {
+	   unsigned short w;
+	   pcc_ioread(1, port, &w, sizeof(w), 1, 0);
+	   return w;
+	} else
+#endif
+	return *(volatile unsigned short *)PORT2ADDR(port);
+}
+
+unsigned long _inl(unsigned long port)
+{
+#if defined(CONFIG_PCMCIA) && defined(CONFIG_M32RPCC)
+	if (port >= M32R_PCC_IOSTART0 && port <= M32R_PCC_IOEND0) {
+	   unsigned long l;
+	   pcc_ioread(0, port, &l, sizeof(l), 1, 0);
+	   return l;
+	} else 	if (port >= M32R_PCC_IOSTART1 && port <= M32R_PCC_IOEND1) {
+	   unsigned short l;
+	   pcc_ioread(1, port, &l, sizeof(l), 1, 0);
+	   return l;
+	} else
+#endif
+	return *(volatile unsigned long *)PORT2ADDR(port);
+}
+
+unsigned char _inb_p(unsigned long port)
+{
+	unsigned char  v;
+
+	if (port >= 0x300 && port < 0x320)
+		v = _ne_inb(PORT2ADDR_NE(port));
+	else
+#if defined(CONFIG_PCMCIA) && defined(CONFIG_M32RPCC)
+	if (port >= M32R_PCC_IOSTART0 && port <= M32R_PCC_IOEND0) {
+	   unsigned char b;
+	   pcc_ioread(0, port, &b, sizeof(b), 1, 0);
+	   return b;
+	} else 	if (port >= M32R_PCC_IOSTART1 && port <= M32R_PCC_IOEND1) {
+	  unsigned char b;
+	   pcc_ioread(1, port, &b, sizeof(b), 1, 0);
+	   return b;
+	} else
+#endif
+		v = *(volatile unsigned char *)PORT2ADDR(port);
+
+	delay();
+	return (v);
+}
+
+unsigned short _inw_p(unsigned long port)
+{
+	unsigned short  v;
+
+	if (port >= 0x300 && port < 0x320)
+		v = _ne_inw(PORT2ADDR_NE(port));
+	else
+#if defined(CONFIG_PCMCIA) && defined(CONFIG_M32RPCC)
+	if (port >= M32R_PCC_IOSTART0 && port <= M32R_PCC_IOEND0) {
+	   unsigned short w;
+	   pcc_ioread(0, port, &w, sizeof(w), 1, 0);
+	   return w;
+	} else 	if (port >= M32R_PCC_IOSTART1 && port <= M32R_PCC_IOEND1) {
+	   unsigned short w;
+	   pcc_ioread(1, port, &w, sizeof(w), 1, 0);
+	   return w;
+	} else
+#endif
+		v = *(volatile unsigned short *)PORT2ADDR(port);
+
+	delay();
+	return (v);
+}
+
+unsigned long _inl_p(unsigned long port)
+{
+	unsigned long  v;
+
+	v = *(volatile unsigned long *)PORT2ADDR(port);
+	delay();
+	return (v);
+}
+
+void _outb(unsigned char b, unsigned long port)
+{
+	if (port >= 0x300 && port < 0x320)
+		_ne_outb(b, PORT2ADDR_NE(port));
+	else
+#if defined(CONFIG_PCMCIA) && defined(CONFIG_M32RPCC)
+	if (port >= M32R_PCC_IOSTART0 && port <= M32R_PCC_IOEND0) {
+	   pcc_iowrite(0, port, &b, sizeof(b), 1, 0);
+	} else 	if (port >= M32R_PCC_IOSTART1 && port <= M32R_PCC_IOEND1) {
+	   pcc_iowrite(1, port, &b, sizeof(b), 1, 0);
+	} else
+#endif
+		*(volatile unsigned char *)PORT2ADDR(port) = b;
+}
+
+void _outw(unsigned short w, unsigned long port)
+{
+	if (port >= 0x300 && port < 0x320)
+		_ne_outw(w, PORT2ADDR_NE(port));
+	else
+#if defined(CONFIG_PCMCIA) && defined(CONFIG_M32RPCC)
+	if (port >= M32R_PCC_IOSTART0 && port <= M32R_PCC_IOEND0) {
+	   pcc_iowrite(0, port, &w, sizeof(w), 1, 0);
+	} else 	if (port >= M32R_PCC_IOSTART1 && port <= M32R_PCC_IOEND1) {
+	   pcc_iowrite(1, port, &w, sizeof(w), 1, 0);
+	} else
+#endif
+		*(volatile unsigned short *)PORT2ADDR(port) = w;
+}
+
+void _outl(unsigned long l, unsigned long port)
+{
+#if defined(CONFIG_PCMCIA) && defined(CONFIG_M32RPCC)
+	if (port >= M32R_PCC_IOSTART0 && port <= M32R_PCC_IOEND0) {
+	   pcc_iowrite(0, port, &l, sizeof(l), 1, 0);
+	} else 	if (port >= M32R_PCC_IOSTART1 && port <= M32R_PCC_IOEND1) {
+	   pcc_iowrite(1, port, &l, sizeof(l), 1, 0);
+	} else
+#endif
+	*(volatile unsigned long *)PORT2ADDR(port) = l;
+}
+
+void _outb_p(unsigned char b, unsigned long port)
+{
+	if (port >= 0x300 && port < 0x320)
+		_ne_outb(b, PORT2ADDR_NE(port));
+	else
+#if defined(CONFIG_PCMCIA) && defined(CONFIG_M32RPCC)
+	if (port >= M32R_PCC_IOSTART0 && port <= M32R_PCC_IOEND0) {
+	   pcc_iowrite(0, port, &b, sizeof(b), 1, 0);
+	} else 	if (port >= M32R_PCC_IOSTART1 && port <= M32R_PCC_IOEND1) {
+	   pcc_iowrite(1, port, &b, sizeof(b), 1, 0);
+	} else
+#endif
+		*(volatile unsigned char *)PORT2ADDR(port) = b;
+
+	delay();
+}
+
+void _outw_p(unsigned short w, unsigned long port)
+{
+	if (port >= 0x300 && port < 0x320)
+		_ne_outw(w, PORT2ADDR_NE(port));
+	else
+#if defined(CONFIG_PCMCIA) && defined(CONFIG_M32RPCC)
+	if (port >= M32R_PCC_IOSTART0 && port <= M32R_PCC_IOEND0) {
+	   pcc_iowrite(0, port, &w, sizeof(w), 1, 0);
+	} else 	if (port >= M32R_PCC_IOSTART1 && port <= M32R_PCC_IOEND1) {
+	   pcc_iowrite(1, port, &w, sizeof(w), 1, 0);
+	} else
+#endif
+		*(volatile unsigned short *)PORT2ADDR(port) = w;
+
+	delay();
+}
+
+void _outl_p(unsigned long l, unsigned long port)
+{
+	*(volatile unsigned long *)PORT2ADDR(port) = l;
+	delay();
+}
+
+void _insb(unsigned int port, void * addr, unsigned long count)
+{
+	unsigned short *buf = addr;
+	unsigned short *portp;
+
+	if (port >= 0x300 && port < 0x320){
+		portp = PORT2ADDR_NE(port);
+		while(count--) *buf++ = *(volatile unsigned char *)portp;
+#if defined(CONFIG_PCMCIA) && defined(CONFIG_M32RPCC)
+	} else if (port >= M32R_PCC_IOSTART0 && port <= M32R_PCC_IOEND0) {
+	   pcc_ioread(0, port, (void *)addr, sizeof(unsigned char), count, 1);
+	} else 	if (port >= M32R_PCC_IOSTART1 && port <= M32R_PCC_IOEND1) {
+	   pcc_ioread(1, port, (void *)addr, sizeof(unsigned char), count, 1);
+#endif
+	} else {
+		portp = PORT2ADDR(port);
+		while(count--) *buf++ = *(volatile unsigned char *)portp;
+	}
+}
+
+void _insw(unsigned int port, void * addr, unsigned long count)
+{
+	unsigned short *buf = addr;
+	unsigned short *portp;
+
+	if (port >= 0x300 && port < 0x320) {
+		portp = PORT2ADDR_NE(port);
+		while (count--) *buf++ = _ne_inw(portp);
+#if defined(CONFIG_PCMCIA) && defined(CONFIG_M32RPCC)
+	} else if (port >= M32R_PCC_IOSTART0 && port <= M32R_PCC_IOEND0) {
+	   pcc_ioread(0, port, (void *)addr, sizeof(unsigned short), count, 1);
+	} else 	if (port >= M32R_PCC_IOSTART1 && port <= M32R_PCC_IOEND1) {
+	   pcc_ioread(1, port, (void *)addr, sizeof(unsigned short), count, 1);
+#endif
+	} else {
+		portp = PORT2ADDR(port);
+		while (count--) *buf++ = *(volatile unsigned short *)portp;
+	}
+}
+
+void _insl(unsigned int port, void * addr, unsigned long count)
+{
+	unsigned long *buf = addr;
+	unsigned long *portp;
+
+	portp = PORT2ADDR(port);
+	while (count--) *buf++ = *(volatile unsigned long *)portp;
+}
+
+void _outsb(unsigned int port, const void * addr, unsigned long count)
+{
+	const unsigned char *buf = addr;
+	unsigned char *portp;
+
+	if (port >= 0x300 && port < 0x320) {
+		portp = PORT2ADDR_NE(port);
+		while (count--) _ne_outb(*buf++, portp);
+#if defined(CONFIG_PCMCIA) && defined(CONFIG_M32RPCC)
+	} else if (port >= M32R_PCC_IOSTART0 && port <= M32R_PCC_IOEND0) {
+	   pcc_iowrite(0, port, (void *)addr, sizeof(unsigned char), count, 1);
+	} else if (port >= M32R_PCC_IOSTART1 && port <= M32R_PCC_IOEND1) {
+	   pcc_iowrite(1, port, (void *)addr, sizeof(unsigned char), count, 1);
+#endif
+	} else {
+		portp = PORT2ADDR(port);
+		while(count--) *(volatile unsigned char *)portp = *buf++;
+	}
+}
+
+void _outsw(unsigned int port, const void * addr, unsigned long count)
+{
+	const unsigned short *buf = addr;
+	unsigned short *portp;
+
+	if (port >= 0x300 && port < 0x320) {
+		portp = PORT2ADDR_NE(port);
+		while (count--) _ne_outw(*buf++, portp);
+#if defined(CONFIG_PCMCIA) && defined(CONFIG_M32RPCC)
+	} else if (port >= M32R_PCC_IOSTART0 && port <= M32R_PCC_IOEND0) {
+	   pcc_iowrite(0, port, (void *)addr, sizeof(unsigned short), count, 1);
+	} else 	if (port >= M32R_PCC_IOSTART1 && port <= M32R_PCC_IOEND1) {
+	   pcc_iowrite(1, port, (void *)addr, sizeof(unsigned short), count, 1);
+#endif
+	} else {
+		portp = PORT2ADDR(port);
+		while(count--) *(volatile unsigned short *)portp = *buf++;
+	}
+}
+
+void _outsl(unsigned int port, const void * addr, unsigned long count)
+{
+	const unsigned long *buf = addr;
+	unsigned char *portp;
+
+	portp = PORT2ADDR(port);
+	while(count--) *(volatile unsigned long *)portp = *buf++;
+}
diff -Nru a/arch/m32r/kernel/io_mappi2.c b/arch/m32r/kernel/io_mappi2.c
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/arch/m32r/kernel/io_mappi2.c	2004-10-18 14:57:24 -07:00
@@ -0,0 +1,370 @@
+/*
+ *  linux/arch/m32r/kernel/io_mappi2.c
+ *
+ *  Typical I/O routines for Mappi2 board.
+ *
+ *  Copyright (c) 2001-2003  Hiroyuki Kondo, Hirokazu Takata,
+ *                            Hitoshi Yamamoto, Mamoru Sakugawa
+ */
+
+/* $Id:$ */
+
+#include <linux/config.h>
+#include <asm/m32r.h>
+#include <asm/page.h>
+#include <asm/io.h>
+
+#if defined(CONFIG_PCMCIA) && defined(CONFIG_M32R_CFC)
+#include <linux/types.h>
+
+#define M32R_PCC_IOMAP_SIZE 0x1000
+
+#define M32R_PCC_IOSTART0 0x1000
+#define M32R_PCC_IOEND0   (M32R_PCC_IOSTART0 + M32R_PCC_IOMAP_SIZE - 1)
+
+extern void pcc_ioread_byte(int, unsigned long, void *, size_t, size_t, int);
+extern void pcc_ioread_word(int, unsigned long, void *, size_t, size_t, int);
+extern void pcc_iowrite_byte(int, unsigned long, void *, size_t, size_t, int);
+extern void pcc_iowrite_word(int, unsigned long, void *, size_t, size_t, int);
+#endif /* CONFIG_PCMCIA && CONFIG_MAPPI2_CFC */
+
+#define PORT2ADDR(port)      _port2addr(port)
+#define PORT2ADDR_NE(port)   _port2addr_ne(port)
+#define PORT2ADDR_USB(port)  _port2addr_usb(port)
+
+static __inline__ void *_port2addr(unsigned long port)
+{
+	return (void *)(port + NONCACHE_OFFSET);
+}
+
+#define LAN_IOSTART	0x300
+#define LAN_IOEND	0x320
+#ifdef CONFIG_CHIP_OPSP
+static __inline__ void *_port2addr_ne(unsigned long port)
+{
+	return (void *)(port + NONCACHE_OFFSET + 0x10000000);
+}
+#else
+static __inline__ void *_port2addr_ne(unsigned long port)
+{
+	return (void *)(port + NONCACHE_OFFSET + 0x04000000);
+}
+#endif
+static __inline__ void *_port2addr_usb(unsigned long port)
+{
+	return (void *)(port + NONCACHE_OFFSET + 0x14000000);
+}
+static __inline__ void delay(void)
+{
+	__asm__ __volatile__ ("push r0; \n\t pop r0;" : : :"memory");
+}
+
+/*
+ * NIC I/O function
+ */
+
+static __inline__ unsigned char _ne_inb(void *portp)
+{
+	return (unsigned char) *(volatile unsigned char *)portp;
+}
+
+static __inline__ unsigned short _ne_inw(void *portp)
+{
+#if 1  /* byte swap */
+	unsigned short tmp,tmp2;
+	tmp = *(volatile unsigned short *)portp;
+	tmp2 = (tmp>>8|tmp<<8);
+	return tmp2;
+#else
+	return *(volatile unsigned short *)portp;
+#endif
+}
+
+static __inline__ void _ne_insb(void *portp, void * addr, unsigned long count)
+{
+	unsigned short tmp;
+	unsigned char *buf = addr;
+
+	tmp = *(volatile unsigned char *)portp;
+	while (count--) *buf++ = *(volatile unsigned char *)portp;
+}
+
+static __inline__ void _ne_outb(unsigned char b, void *portp)
+{
+	*(volatile unsigned char *)portp = (unsigned char)b;
+}
+
+static __inline__ void _ne_outw(unsigned short w, void *portp)
+{
+	*(volatile unsigned short *)portp = (w>>8|w<<8);
+}
+
+unsigned char _inb(unsigned long port)
+{
+	if (port >= LAN_IOSTART && port < LAN_IOEND)
+		return _ne_inb(PORT2ADDR_NE(port));
+#if defined(CONFIG_PCMCIA) && defined(CONFIG_M32R_CFC)
+	else if (port >= M32R_PCC_IOSTART0 && port <= M32R_PCC_IOEND0) {
+	   unsigned char b;
+	   pcc_ioread_byte(0, port, &b, sizeof(b), 1, 0);
+	   return b;
+	} else
+#endif
+
+	return *(volatile unsigned char *)PORT2ADDR(port);
+}
+
+unsigned short _inw(unsigned long port)
+{
+	if (port >= LAN_IOSTART && port < LAN_IOEND)
+		return _ne_inw(PORT2ADDR_NE(port));
+#if defined(CONFIG_USB)
+        else if (port >= 0x340 && port < 0x3a0)
+	  return *(volatile unsigned short *)PORT2ADDR_USB(port);
+#endif
+
+#if defined(CONFIG_PCMCIA) && defined(CONFIG_M32R_CFC)
+	  else if (port >= M32R_PCC_IOSTART0 && port <= M32R_PCC_IOEND0) {
+	   unsigned short w;
+	   pcc_ioread_word(0, port, &w, sizeof(w), 1, 0);
+	   return w;
+	} else
+#endif
+	return *(volatile unsigned short *)PORT2ADDR(port);
+}
+
+unsigned long _inl(unsigned long port)
+{
+#if defined(CONFIG_PCMCIA) && defined(CONFIG_M32R_CFC)
+	if (port >= M32R_PCC_IOSTART0 && port <= M32R_PCC_IOEND0) {
+	   unsigned long l;
+	   pcc_ioread_word(0, port, &l, sizeof(l), 1, 0);
+	   return l;
+	} else
+#endif
+	return *(volatile unsigned long *)PORT2ADDR(port);
+}
+
+unsigned char _inb_p(unsigned long port)
+{
+	unsigned char  v;
+
+	if (port >= 0x300 && port < 0x320)
+		v = _ne_inb(PORT2ADDR_NE(port));
+	else
+#if defined(CONFIG_PCMCIA) && defined(CONFIG_M32R_CFC)
+	if (port >= M32R_PCC_IOSTART0 && port <= M32R_PCC_IOEND0) {
+	   unsigned char b;
+	   pcc_ioread_byte(0, port, &b, sizeof(b), 1, 0);
+	   return b;
+	} else
+#endif
+		v = *(volatile unsigned char *)PORT2ADDR(port);
+
+	delay();
+	return (v);
+}
+
+unsigned short _inw_p(unsigned long port)
+{
+	unsigned short  v;
+
+	if (port >= 0x300 && port < 0x320)
+		v = _ne_inw(PORT2ADDR_NE(port));
+	else
+#if defined(CONFIG_USB)
+	  if (port >= 0x340 && port < 0x3a0)
+		v = *(volatile unsigned short *)PORT2ADDR_USB(port);
+	  else
+#endif
+#if defined(CONFIG_PCMCIA) && defined(CONFIG_M32R_CFC)
+	if (port >= M32R_PCC_IOSTART0 && port <= M32R_PCC_IOEND0) {
+	   unsigned short w;
+	   pcc_ioread_word(0, port, &w, sizeof(w), 1, 0);
+	   return w;
+	} else
+#endif
+		v = *(volatile unsigned short *)PORT2ADDR(port);
+
+	delay();
+	return (v);
+}
+
+unsigned long _inl_p(unsigned long port)
+{
+	unsigned long  v;
+
+	v = *(volatile unsigned long *)PORT2ADDR(port);
+	delay();
+	return (v);
+}
+
+void _outb(unsigned char b, unsigned long port)
+{
+	if (port >= LAN_IOSTART && port < LAN_IOEND)
+		_ne_outb(b, PORT2ADDR_NE(port));
+	else
+#if defined(CONFIG_PCMCIA) && defined(CONFIG_M32R_CFC)
+	if (port >= M32R_PCC_IOSTART0 && port <= M32R_PCC_IOEND0) {
+	   pcc_iowrite_byte(0, port, &b, sizeof(b), 1, 0);
+	} else
+#endif
+		*(volatile unsigned char *)PORT2ADDR(port) = b;
+}
+
+void _outw(unsigned short w, unsigned long port)
+{
+	if (port >= LAN_IOSTART && port < LAN_IOEND)
+		_ne_outw(w, PORT2ADDR_NE(port));
+	else
+#if defined(CONFIG_USB)
+	  if (port >= 0x340 && port < 0x3a0)
+	    *(volatile unsigned short *)PORT2ADDR_USB(port) = w;
+	else
+#endif
+#if defined(CONFIG_PCMCIA) && defined(CONFIG_M32R_CFC)
+	if (port >= M32R_PCC_IOSTART0 && port <= M32R_PCC_IOEND0) {
+	   pcc_iowrite_word(0, port, &w, sizeof(w), 1, 0);
+	} else
+#endif
+		*(volatile unsigned short *)PORT2ADDR(port) = w;
+}
+
+void _outl(unsigned long l, unsigned long port)
+{
+#if defined(CONFIG_PCMCIA) && defined(CONFIG_M32R_CFC)
+	if (port >= M32R_PCC_IOSTART0 && port <= M32R_PCC_IOEND0) {
+	   pcc_iowrite_word(0, port, &l, sizeof(l), 1, 0);
+	} else
+#endif
+	*(volatile unsigned long *)PORT2ADDR(port) = l;
+}
+
+void _outb_p(unsigned char b, unsigned long port)
+{
+	if (port >= LAN_IOSTART && port < LAN_IOEND)
+		_ne_outb(b, PORT2ADDR_NE(port));
+	else
+#if defined(CONFIG_PCMCIA) && defined(CONFIG_M32R_CFC)
+	if (port >= M32R_PCC_IOSTART0 && port <= M32R_PCC_IOEND0) {
+	   pcc_iowrite_byte(0, port, &b, sizeof(b), 1, 0);
+	} else
+#endif
+		*(volatile unsigned char *)PORT2ADDR(port) = b;
+
+	delay();
+}
+
+void _outw_p(unsigned short w, unsigned long port)
+{
+	if (port >= LAN_IOSTART && port < LAN_IOEND)
+		_ne_outw(w, PORT2ADDR_NE(port));
+	else
+#if defined(CONFIG_USB)
+	  if (port >= 0x340 && port < 0x3a0)
+		*(volatile unsigned short *)PORT2ADDR_USB(port) = w;
+	else
+#endif
+#if defined(CONFIG_PCMCIA) && defined(CONFIG_M32R_CFC)
+	if (port >= M32R_PCC_IOSTART0 && port <= M32R_PCC_IOEND0) {
+	   pcc_iowrite_word(0, port, &w, sizeof(w), 1, 0);
+	} else
+#endif
+		*(volatile unsigned short *)PORT2ADDR(port) = w;
+
+	delay();
+}
+
+void _outl_p(unsigned long l, unsigned long port)
+{
+	*(volatile unsigned long *)PORT2ADDR(port) = l;
+	delay();
+}
+
+void _insb(unsigned int port, void * addr, unsigned long count)
+{
+	if (port >= LAN_IOSTART && port < LAN_IOEND)
+		_ne_insb(PORT2ADDR_NE(port), addr, count);
+#if defined(CONFIG_PCMCIA) && defined(CONFIG_M32R_CFC)
+	  else if (port >= M32R_PCC_IOSTART0 && port <= M32R_PCC_IOEND0) {
+	   pcc_ioread_byte(0, port, (void *)addr, sizeof(unsigned char), count, 1);
+	}
+#endif
+	else {
+		unsigned char *buf = addr;
+		unsigned char *portp = PORT2ADDR(port);
+		while(count--) *buf++ = *(volatile unsigned char *)portp;
+	}
+}
+
+void _insw(unsigned int port, void * addr, unsigned long count)
+{
+	unsigned short *buf = addr;
+	unsigned short *portp;
+
+	if (port >= LAN_IOSTART && port < LAN_IOEND)
+		portp = PORT2ADDR_NE(port);
+		while (count--) *buf++ = *(volatile unsigned short *)portp;
+#if defined(CONFIG_PCMCIA) && defined(CONFIG_M32R_CFC)
+	} else if (port >= M32R_PCC_IOSTART0 && port <= M32R_PCC_IOEND0) {
+	   pcc_ioread_word(9, port, (void *)addr, sizeof(unsigned short), count, 1);
+#endif
+	} else {
+		portp = PORT2ADDR(port);
+		while (count--) *buf++ = *(volatile unsigned short *)portp;
+	}
+}
+
+void _insl(unsigned int port, void * addr, unsigned long count)
+{
+	unsigned long *buf = addr;
+	unsigned long *portp;
+
+	portp = PORT2ADDR(port);
+	while (count--) *buf++ = *(volatile unsigned long *)portp;
+}
+
+void _outsb(unsigned int port, const void * addr, unsigned long count)
+{
+	const unsigned char *buf = addr;
+	unsigned char *portp;
+
+	if (port >= LAN_IOSTART && port < LAN_IOEND)
+		portp = PORT2ADDR_NE(port);
+		while (count--) _ne_outb(*buf++, portp);
+#if defined(CONFIG_PCMCIA) && defined(CONFIG_M32R_CFC)
+	} else if (port >= M32R_PCC_IOSTART0 && port <= M32R_PCC_IOEND0) {
+	   pcc_iowrite_byte(0, port, (void *)addr, sizeof(unsigned char), count, 1);
+#endif
+	} else {
+		portp = PORT2ADDR(port);
+		while(count--) *(volatile unsigned char *)portp = *buf++;
+	}
+}
+
+void _outsw(unsigned int port, const void * addr, unsigned long count)
+{
+	const unsigned short *buf = addr;
+	unsigned short *portp;
+
+	if (port >= LAN_IOSTART && port < LAN_IOEND)
+		portp = PORT2ADDR_NE(port);
+		while (count--) *(volatile unsigned short *)portp = *buf++;
+#if defined(CONFIG_PCMCIA) && defined(CONFIG_M32R_CFC)
+	} else if (port >= M32R_PCC_IOSTART0 && port <= M32R_PCC_IOEND0) {
+	   pcc_iowrite_word(9, port, (void *)addr, sizeof(unsigned short), count, 1);
+#endif
+	} else {
+		portp = PORT2ADDR(port);
+		while(count--) *(volatile unsigned short *)portp = *buf++;
+	}
+}
+
+void _outsl(unsigned int port, const void * addr, unsigned long count)
+{
+	const unsigned long *buf = addr;
+	unsigned char *portp;
+
+	portp = PORT2ADDR(port);
+	while(count--) *(volatile unsigned long *)portp = *buf++;
+}
diff -Nru a/arch/m32r/kernel/io_oaks32r.c b/arch/m32r/kernel/io_oaks32r.c
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/arch/m32r/kernel/io_oaks32r.c	2004-10-18 14:57:24 -07:00
@@ -0,0 +1,243 @@
+/*
+ *  linux/arch/m32r/kernel/io_oaks32r.c
+ *
+ *  Typical I/O routines for OAKS32R board.
+ *
+ *  Copyright (c) 2001-2004  Hiroyuki Kondo, Hirokazu Takata,
+ *                            Hitoshi Yamamoto, Mamoru Sakugawa
+ */
+
+/* $Id$ */
+
+#include <linux/config.h>
+#include <asm/m32r.h>
+#include <asm/page.h>
+#include <asm/io.h>
+
+#define PORT2ADDR(port)  _port2addr(port)
+
+static __inline__ void *_port2addr(unsigned long port)
+{
+	return (void *)(port + NONCACHE_OFFSET);
+}
+
+static __inline__  void *_port2addr_ne(unsigned long port)
+{
+	return (void *)((port<<1) + NONCACHE_OFFSET + 0x02000000);
+}
+
+static __inline__ void delay(void)
+{
+	__asm__ __volatile__ ("push r0; \n\t pop r0;" : : :"memory");
+}
+
+/*
+ * NIC I/O function
+ */
+
+#define PORT2ADDR_NE(port)  _port2addr_ne(port)
+
+static __inline__ unsigned char _ne_inb(void *portp)
+{
+	return *(volatile unsigned char *)(portp+1);
+}
+
+static __inline__ unsigned short _ne_inw(void *portp)
+{
+	unsigned short tmp;
+
+	tmp = *(unsigned short *)(portp) & 0xff;
+	tmp |= *(unsigned short *)(portp+2) << 8;
+	return tmp;
+}
+
+static __inline__  void _ne_insb(void *portp, void * addr, unsigned long count)
+{
+	unsigned char *buf = addr;
+	while (count--) *buf++ = *(volatile unsigned char *)(portp+1);
+}
+
+static __inline__ void _ne_outb(unsigned char b, void *portp)
+{
+	*(volatile unsigned char *)(portp+1) = b;
+}
+
+static __inline__ void _ne_outw(unsigned short w, void *portp)
+{
+  *(volatile unsigned short *)portp =  (w >> 8);
+  *(volatile unsigned short *)(portp+2) =  (w & 0xff);
+}
+
+unsigned char _inb(unsigned long port)
+{
+	if (port >= 0x300 && port < 0x320)
+		return _ne_inb(PORT2ADDR_NE(port));
+
+	return *(volatile unsigned char *)PORT2ADDR(port);
+}
+
+unsigned short _inw(unsigned long port)
+{
+	if (port >= 0x300 && port < 0x320)
+		return _ne_inw(PORT2ADDR_NE(port));
+
+	return *(volatile unsigned short *)PORT2ADDR(port);
+}
+
+unsigned long _inl(unsigned long port)
+{
+	return *(volatile unsigned long *)PORT2ADDR(port);
+}
+
+unsigned char _inb_p(unsigned long port)
+{
+	unsigned char  v;
+
+	if (port >= 0x300 && port < 0x320)
+		v = _ne_inb(PORT2ADDR_NE(port));
+	else
+		v = *(volatile unsigned char *)PORT2ADDR(port);
+
+	delay();
+	return (v);
+}
+
+unsigned short _inw_p(unsigned long port)
+{
+	unsigned short  v;
+
+	if (port >= 0x300 && port < 0x320)
+		v = _ne_inw(PORT2ADDR_NE(port));
+	else
+		v = *(volatile unsigned short *)PORT2ADDR(port);
+
+	delay();
+	return (v);
+}
+
+unsigned long _inl_p(unsigned long port)
+{
+	unsigned long  v;
+
+	v = *(volatile unsigned long *)PORT2ADDR(port);
+	delay();
+	return (v);
+}
+
+void _outb(unsigned char b, unsigned long port)
+{
+	if (port >= 0x300 && port < 0x320)
+		_ne_outb(b, PORT2ADDR_NE(port));
+	else
+		*(volatile unsigned char *)PORT2ADDR(port) = b;
+}
+
+void _outw(unsigned short w, unsigned long port)
+{
+	if (port >= 0x300 && port < 0x320)
+		_ne_outw(w, PORT2ADDR_NE(port));
+	else
+		*(volatile unsigned short *)PORT2ADDR(port) = w;
+}
+
+void _outl(unsigned long l, unsigned long port)
+{
+	*(volatile unsigned long *)PORT2ADDR(port) = l;
+}
+
+void _outb_p(unsigned char b, unsigned long port)
+{
+	if (port >= 0x300 && port < 0x320)
+		_ne_outb(b, PORT2ADDR_NE(port));
+	else
+		*(volatile unsigned char *)PORT2ADDR(port) = b;
+
+	delay();
+}
+
+void _outw_p(unsigned short w, unsigned long port)
+{
+	if (port >= 0x300 && port < 0x320)
+		_ne_outw(w, PORT2ADDR_NE(port));
+	else
+		*(volatile unsigned short *)PORT2ADDR(port) = w;
+
+	delay();
+}
+
+void _outl_p(unsigned long l, unsigned long port)
+{
+	*(volatile unsigned long *)PORT2ADDR(port) = l;
+	delay();
+}
+
+void _insb(unsigned int port, void * addr, unsigned long count)
+{
+	if (port >= 0x300 && port < 0x320)
+		_ne_insb(PORT2ADDR_NE(port), addr, count);
+	else {
+		unsigned char *buf = addr;
+		unsigned char *portp = PORT2ADDR(port);
+		while(count--) *buf++ = *(volatile unsigned char *)portp;
+	}
+}
+
+void _insw(unsigned int port, void * addr, unsigned long count)
+{
+	unsigned short *buf = addr;
+	unsigned short *portp;
+
+	if (port >= 0x300 && port < 0x320) {
+		portp = PORT2ADDR_NE(port);
+		while (count--) *buf++ = _ne_inw(portp);
+	} else {
+		portp = PORT2ADDR(port);
+		while (count--) *buf++ = *(volatile unsigned short *)portp;
+	}
+}
+
+void _insl(unsigned int port, void * addr, unsigned long count)
+{
+	unsigned long *buf = addr;
+	unsigned long *portp;
+
+	portp = PORT2ADDR(port);
+	while (count--) *buf++ = *(volatile unsigned long *)portp;
+}
+
+void _outsb(unsigned int port, const void * addr, unsigned long count)
+{
+	const unsigned char *buf = addr;
+	unsigned char *portp;
+
+	if (port >= 0x300 && port < 0x320) {
+		portp = PORT2ADDR_NE(port);
+		while (count--) _ne_outb(*buf++, portp);
+	} else {
+		portp = PORT2ADDR(port);
+		while(count--) *(volatile unsigned char *)portp = *buf++;
+	}
+}
+
+void _outsw(unsigned int port, const void * addr, unsigned long count)
+{
+	const unsigned short *buf = addr;
+	unsigned short *portp;
+
+	if (port >= 0x300 && port < 0x320) {
+		portp = PORT2ADDR_NE(port);
+		while (count--) _ne_outw(*buf++, portp);
+	} else {
+		portp = PORT2ADDR(port);
+		while(count--) *(volatile unsigned short *)portp = *buf++;
+	}
+}
+
+void _outsl(unsigned int port, const void * addr, unsigned long count)
+{
+	const unsigned long *buf = addr;
+	unsigned char *portp;
+
+	portp = PORT2ADDR(port);
+	while(count--) *(volatile unsigned long *)portp = *buf++;
+}
diff -Nru a/arch/m32r/kernel/io_opsput.c b/arch/m32r/kernel/io_opsput.c
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/arch/m32r/kernel/io_opsput.c	2004-10-18 14:57:23 -07:00
@@ -0,0 +1,377 @@
+/*
+ *  linux/arch/m32r/kernel/io_mappi.c
+ *
+ *  Typical I/O routines for OPSPUT board.
+ *
+ *  Copyright (c) 2001, 2002  Hiroyuki Kondo, Hirokazu Takata,
+ *                            Hitoshi Yamamoto, Takeo Takahashi
+ *
+ *  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.
+ *
+ */
+
+#include <linux/config.h>
+#include <asm/m32r.h>
+#include <asm/page.h>
+#include <asm/io.h>
+#include <asm/byteorder.h>
+
+#if defined(CONFIG_PCMCIA) && defined(CONFIG_M32R_CFC)
+#include <linux/types.h>
+
+#define M32R_PCC_IOMAP_SIZE 0x1000
+
+#define M32R_PCC_IOSTART0 0x1000
+#define M32R_PCC_IOEND0   (M32R_PCC_IOSTART0 + M32R_PCC_IOMAP_SIZE - 1)
+
+extern void pcc_ioread_byte(int, unsigned long, void *, size_t, size_t, int);
+extern void pcc_ioread_word(int, unsigned long, void *, size_t, size_t, int);
+extern void pcc_iowrite_byte(int, unsigned long, void *, size_t, size_t, int);
+extern void pcc_iowrite_word(int, unsigned long, void *, size_t, size_t, int);
+#endif /* CONFIG_PCMCIA && CONFIG_M32R_CFC */
+
+#define PORT2ADDR(port)  _port2addr(port)
+#define PORT2ADDR_USB(port) _port2addr_usb(port)
+
+static __inline__ void *_port2addr(unsigned long port)
+{
+	return (void *)(port + NONCACHE_OFFSET);
+}
+
+/*
+ * OPSPUT-LAN is located in the extended bus space
+ * from 0x10000000 to 0x13ffffff on physical address.
+ * The base address of LAN controller(LAN91C111) is 0x300.
+ */
+#define LAN_IOSTART	0x300
+#define LAN_IOEND	0x320
+static __inline__ void *_port2addr_ne(unsigned long port)
+{
+	return (void *)(port + NONCACHE_OFFSET + 0x10000000);
+}
+static __inline__ void *_port2addr_usb(unsigned long port)
+{
+  return (void *)((port & 0x0f) + NONCACHE_OFFSET + 0x10303000);
+}
+
+static __inline__ void delay(void)
+{
+	__asm__ __volatile__ ("push r0; \n\t pop r0;" : : :"memory");
+}
+
+/*
+ * NIC I/O function
+ */
+
+#define PORT2ADDR_NE(port)  _port2addr_ne(port)
+
+static __inline__ unsigned char _ne_inb(void *portp)
+{
+	return *(volatile unsigned char *)portp;
+}
+
+static __inline__ unsigned short _ne_inw(void *portp)
+{
+	return (unsigned short)le16_to_cpu(*(volatile unsigned short *)portp);
+}
+
+static __inline__ void _ne_insb(void *portp, void * addr, unsigned long count)
+{
+	unsigned char *buf = (unsigned char *)addr;
+
+	while (count--) *buf++ = _ne_inb(portp);
+}
+
+static __inline__ void _ne_outb(unsigned char b, void *portp)
+{
+	*(volatile unsigned char *)portp = b;
+}
+
+static __inline__ void _ne_outw(unsigned short w, void *portp)
+{
+	*(volatile unsigned short *)portp = cpu_to_le16(w);
+}
+
+unsigned char _inb(unsigned long port)
+{
+	if (port >= LAN_IOSTART && port < LAN_IOEND)
+		return _ne_inb(PORT2ADDR_NE(port));
+
+#if defined(CONFIG_PCMCIA) && defined(CONFIG_M32R_CFC)
+	else if (port >= M32R_PCC_IOSTART0 && port <= M32R_PCC_IOEND0) {
+	   unsigned char b;
+	   pcc_ioread_byte(0, port, &b, sizeof(b), 1, 0);
+	   return b;
+	} else
+#endif
+
+	return *(volatile unsigned char *)PORT2ADDR(port);
+}
+
+unsigned short _inw(unsigned long port)
+{
+	if (port >= LAN_IOSTART && port < LAN_IOEND)
+		return _ne_inw(PORT2ADDR_NE(port));
+#if defined(CONFIG_USB)
+	else if(port >= 0x340 && port < 0x3a0)
+	  return *(volatile unsigned short *)PORT2ADDR_USB(port);
+#endif
+
+#if defined(CONFIG_PCMCIA) && defined(CONFIG_M32R_CFC)
+	  else if (port >= M32R_PCC_IOSTART0 && port <= M32R_PCC_IOEND0) {
+	   unsigned short w;
+	   pcc_ioread_word(0, port, &w, sizeof(w), 1, 0);
+	   return w;
+	} else
+#endif
+	return *(volatile unsigned short *)PORT2ADDR(port);
+}
+
+unsigned long _inl(unsigned long port)
+{
+#if defined(CONFIG_PCMCIA) && defined(CONFIG_M32R_CFC)
+	if (port >= M32R_PCC_IOSTART0 && port <= M32R_PCC_IOEND0) {
+	   unsigned long l;
+	   pcc_ioread_word(0, port, &l, sizeof(l), 1, 0);
+	   return l;
+	} else
+#endif
+	return *(volatile unsigned long *)PORT2ADDR(port);
+}
+
+unsigned char _inb_p(unsigned long port)
+{
+	unsigned char  v;
+
+	if (port >= LAN_IOSTART && port < LAN_IOEND)
+		v = _ne_inb(PORT2ADDR_NE(port));
+	else
+#if defined(CONFIG_PCMCIA) && defined(CONFIG_M32R_CFC)
+	if (port >= M32R_PCC_IOSTART0 && port <= M32R_PCC_IOEND0) {
+	   unsigned char b;
+	   pcc_ioread_byte(0, port, &b, sizeof(b), 1, 0);
+	   return b;
+	} else
+#endif
+		v = *(volatile unsigned char *)PORT2ADDR(port);
+
+	delay();
+	return (v);
+}
+
+unsigned short _inw_p(unsigned long port)
+{
+	unsigned short  v;
+
+	if (port >= LAN_IOSTART && port < LAN_IOEND)
+		v = _ne_inw(PORT2ADDR_NE(port));
+	else
+#if defined(CONFIG_USB)
+	  if(port >= 0x340 && port < 0x3a0)
+	    return *(volatile unsigned short *)PORT2ADDR_USB(port);
+	else
+#endif
+
+#if defined(CONFIG_PCMCIA) && defined(CONFIG_M32R_CFC)
+	if (port >= M32R_PCC_IOSTART0 && port <= M32R_PCC_IOEND0) {
+	   unsigned short w;
+	   pcc_ioread_word(0, port, &w, sizeof(w), 1, 0);
+	   return w;
+	} else
+#endif
+		v = *(volatile unsigned short *)PORT2ADDR(port);
+
+	delay();
+	return (v);
+}
+
+unsigned long _inl_p(unsigned long port)
+{
+	unsigned long  v;
+
+	v = *(volatile unsigned long *)PORT2ADDR(port);
+	delay();
+	return (v);
+}
+
+void _outb(unsigned char b, unsigned long port)
+{
+	if (port >= LAN_IOSTART && port < LAN_IOEND)
+		_ne_outb(b, PORT2ADDR_NE(port));
+	else
+#if defined(CONFIG_PCMCIA) && defined(CONFIG_M32R_CFC)
+	if (port >= M32R_PCC_IOSTART0 && port <= M32R_PCC_IOEND0) {
+	   pcc_iowrite_byte(0, port, &b, sizeof(b), 1, 0);
+	} else
+#endif
+		*(volatile unsigned char *)PORT2ADDR(port) = b;
+}
+
+void _outw(unsigned short w, unsigned long port)
+{
+	if (port >= LAN_IOSTART && port < LAN_IOEND)
+		_ne_outw(w, PORT2ADDR_NE(port));
+	else
+#if defined(CONFIG_USB)
+	if(port >= 0x340 && port < 0x3a0)
+	  *(volatile unsigned short *)PORT2ADDR_USB(port) = w;
+	else
+#endif
+
+#if defined(CONFIG_PCMCIA) && defined(CONFIG_M32R_CFC)
+	if (port >= M32R_PCC_IOSTART0 && port <= M32R_PCC_IOEND0) {
+	   pcc_iowrite_word(0, port, &w, sizeof(w), 1, 0);
+	} else
+#endif
+		*(volatile unsigned short *)PORT2ADDR(port) = w;
+}
+
+void _outl(unsigned long l, unsigned long port)
+{
+#if defined(CONFIG_PCMCIA) && defined(CONFIG_M32R_CFC)
+	if (port >= M32R_PCC_IOSTART0 && port <= M32R_PCC_IOEND0) {
+	   pcc_iowrite_word(0, port, &l, sizeof(l), 1, 0);
+	} else
+#endif
+	*(volatile unsigned long *)PORT2ADDR(port) = l;
+}
+
+void _outb_p(unsigned char b, unsigned long port)
+{
+	if (port >= LAN_IOSTART && port < LAN_IOEND)
+		_ne_outb(b, PORT2ADDR_NE(port));
+	else
+#if defined(CONFIG_PCMCIA) && defined(CONFIG_M32R_CFC)
+	if (port >= M32R_PCC_IOSTART0 && port <= M32R_PCC_IOEND0) {
+	   pcc_iowrite_byte(0, port, &b, sizeof(b), 1, 0);
+	} else
+#endif
+		*(volatile unsigned char *)PORT2ADDR(port) = b;
+
+	delay();
+}
+
+void _outw_p(unsigned short w, unsigned long port)
+{
+	if (port >= LAN_IOSTART && port < LAN_IOEND)
+		_ne_outw(w, PORT2ADDR_NE(port));
+	else
+#if defined(CONFIG_USB)
+	  if(port >= 0x340 && port < 0x3a0)
+	    *(volatile unsigned short *)PORT2ADDR_USB(port) = w;
+	else
+#endif
+
+#if defined(CONFIG_PCMCIA) && defined(CONFIG_M32R_CFC)
+	if (port >= M32R_PCC_IOSTART0 && port <= M32R_PCC_IOEND0) {
+	   pcc_iowrite_word(0, port, &w, sizeof(w), 1, 0);
+	} else
+#endif
+		*(volatile unsigned short *)PORT2ADDR(port) = w;
+
+	delay();
+}
+
+void _outl_p(unsigned long l, unsigned long port)
+{
+	*(volatile unsigned long *)PORT2ADDR(port) = l;
+	delay();
+}
+
+void _insb(unsigned int port, void * addr, unsigned long count)
+{
+	if (port >= LAN_IOSTART && port < LAN_IOEND)
+		_ne_insb(PORT2ADDR_NE(port), addr, count);
+#if defined(CONFIG_PCMCIA) && defined(CONFIG_M32R_CFC)
+	  else if (port >= M32R_PCC_IOSTART0 && port <= M32R_PCC_IOEND0) {
+	   pcc_ioread_byte(0, port, (void *)addr, sizeof(unsigned char), count, 1);
+	}
+#endif
+	else {
+		unsigned char *buf = addr;
+		unsigned char *portp = PORT2ADDR(port);
+		while(count--) *buf++ = *(volatile unsigned char *)portp;
+	}
+}
+
+void _insw(unsigned int port, void * addr, unsigned long count)
+{
+	unsigned short *buf = addr;
+	unsigned short *portp;
+
+	if (port >= LAN_IOSTART && port < LAN_IOEND) {
+		/*
+		 * This portion is only used by smc91111.c to read data
+		 * from the DATA_REG. Do not swap the data.
+		 */
+		portp = PORT2ADDR_NE(port);
+		while (count--) *buf++ = *(volatile unsigned short *)portp;
+#if defined(CONFIG_PCMCIA) && defined(CONFIG_M32R_CFC)
+	} else if (port >= M32R_PCC_IOSTART0 && port <= M32R_PCC_IOEND0) {
+	   pcc_ioread_word(9, port, (void *)addr, sizeof(unsigned short), count, 1);
+#endif
+	} else {
+		portp = PORT2ADDR(port);
+		while (count--) *buf++ = *(volatile unsigned short *)portp;
+	}
+}
+
+void _insl(unsigned int port, void * addr, unsigned long count)
+{
+	unsigned long *buf = addr;
+	unsigned long *portp;
+
+	portp = PORT2ADDR(port);
+	while (count--) *buf++ = *(volatile unsigned long *)portp;
+}
+
+void _outsb(unsigned int port, const void * addr, unsigned long count)
+{
+	const unsigned char *buf = addr;
+	unsigned char *portp;
+
+	if (port >= LAN_IOSTART && port < LAN_IOEND) {
+		portp = PORT2ADDR_NE(port);
+		while (count--) _ne_outb(*buf++, portp);
+#if defined(CONFIG_PCMCIA) && defined(CONFIG_M32R_CFC)
+	} else if (port >= M32R_PCC_IOSTART0 && port <= M32R_PCC_IOEND0) {
+	   pcc_iowrite_byte(0, port, (void *)addr, sizeof(unsigned char), count, 1);
+#endif
+	} else {
+		portp = PORT2ADDR(port);
+		while(count--) *(volatile unsigned char *)portp = *buf++;
+	}
+}
+
+void _outsw(unsigned int port, const void * addr, unsigned long count)
+{
+	const unsigned short *buf = addr;
+	unsigned short *portp;
+
+	if (port >= LAN_IOSTART && port < LAN_IOEND) {
+		/*
+		 * This portion is only used by smc91111.c to write data
+		 * into the DATA_REG. Do not swap the data.
+		 */
+		portp = PORT2ADDR_NE(port);
+		while(count--) *(volatile unsigned short *)portp = *buf++;
+#if defined(CONFIG_PCMCIA) && defined(CONFIG_M32R_CFC)
+	} else if (port >= M32R_PCC_IOSTART0 && port <= M32R_PCC_IOEND0) {
+	   pcc_iowrite_word(9, port, (void *)addr, sizeof(unsigned short), count, 1);
+#endif
+	} else {
+		portp = PORT2ADDR(port);
+		while(count--) *(volatile unsigned short *)portp = *buf++;
+	}
+}
+
+void _outsl(unsigned int port, const void * addr, unsigned long count)
+{
+	const unsigned long *buf = addr;
+	unsigned char *portp;
+
+	portp = PORT2ADDR(port);
+	while(count--) *(volatile unsigned long *)portp = *buf++;
+}
diff -Nru a/arch/m32r/kernel/io_usrv.c b/arch/m32r/kernel/io_usrv.c
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/arch/m32r/kernel/io_usrv.c	2004-10-18 14:57:24 -07:00
@@ -0,0 +1,247 @@
+/*
+ *  linux/arch/m32r/kernel/io_usrv.c
+ *
+ *  Typical I/O routines for uServer board.
+ *
+ *  Copyright (c) 2001 - 2003  Hiroyuki Kondo, Hirokazu Takata,
+ *                             Hitoshi Yamamoto, Takeo Takahashi
+ *
+ *  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.
+ *
+ */
+
+#include <linux/config.h>
+#include <asm/m32r.h>
+#include <asm/page.h>
+#include <asm/io.h>
+
+#include <linux/types.h>
+#include "../drivers/m32r_cfc.h"
+
+extern void pcc_ioread_byte(int, unsigned long, void *, size_t, size_t, int);
+extern void pcc_ioread_word(int, unsigned long, void *, size_t, size_t, int);
+extern void pcc_iowrite_byte(int, unsigned long, void *, size_t, size_t, int);
+extern void pcc_iowrite_word(int, unsigned long, void *, size_t, size_t, int);
+#define CFC_IOSTART	CFC_IOPORT_BASE
+#define CFC_IOEND	(CFC_IOSTART + (M32R_PCC_MAPSIZE * M32R_MAX_PCC) - 1)
+
+#if defined(CONFIG_SERIAL_8250) || defined(CONFIG_SERIAL_8250_MODULE)
+#define UART0_REGSTART		0x04c20000
+#define UART1_REGSTART		0x04c20100
+#define UART_IOMAP_SIZE		8
+#define UART0_IOSTART		0x3f8
+#define UART0_IOEND		(UART0_IOSTART + UART_IOMAP_SIZE - 1)
+#define UART1_IOSTART		0x2f8
+#define UART1_IOEND		(UART1_IOSTART + UART_IOMAP_SIZE - 1)
+#endif	/* CONFIG_SERIAL_8250 || CONFIG_SERIAL_8250_MODULE */
+
+#define PORT2ADDR(port)	_port2addr(port)
+
+static __inline__ void *_port2addr(unsigned long port)
+{
+#if defined(CONFIG_SERIAL_8250) || defined(CONFIG_SERIAL_8250_MODULE)
+	if (port >= UART0_IOSTART && port <= UART0_IOEND)
+		port = ((port - UART0_IOSTART) << 1) + UART0_REGSTART;
+	else if (port >= UART1_IOSTART && port <= UART1_IOEND)
+		port = ((port - UART1_IOSTART) << 1) + UART1_REGSTART;
+#endif	/* CONFIG_SERIAL_8250 || CONFIG_SERIAL_8250_MODULE */
+	return (void *)(port + NONCACHE_OFFSET);
+}
+
+static __inline__ void delay(void)
+{
+	__asm__ __volatile__ ("push r0; \n\t pop r0;" : : :"memory");
+}
+
+unsigned char _inb(unsigned long port)
+{
+	if (port >= CFC_IOSTART && port <= CFC_IOEND) {
+		unsigned char b;
+		pcc_ioread_byte(0, port, &b, sizeof(b), 1, 0);
+		return b;
+	} else
+		return *(volatile unsigned char *)PORT2ADDR(port);
+}
+
+unsigned short _inw(unsigned long port)
+{
+	if (port >= CFC_IOSTART && port <= CFC_IOEND) {
+		unsigned short w;
+		pcc_ioread_word(0, port, &w, sizeof(w), 1, 0);
+		return w;
+	} else
+		return *(volatile unsigned short *)PORT2ADDR(port);
+}
+
+unsigned long _inl(unsigned long port)
+{
+	if (port >= CFC_IOSTART && port <= CFC_IOEND) {
+		unsigned long l;
+		pcc_ioread_word(0, port, &l, sizeof(l), 1, 0);
+		return l;
+	} else
+		return *(volatile unsigned long *)PORT2ADDR(port);
+}
+
+unsigned char _inb_p(unsigned long port)
+{
+	unsigned char b;
+
+	if (port >= CFC_IOSTART && port <= CFC_IOEND) {
+		pcc_ioread_byte(0, port, &b, sizeof(b), 1, 0);
+		return b;
+	} else {
+		b = *(volatile unsigned char *)PORT2ADDR(port);
+		delay();
+		return b;
+	}
+}
+
+unsigned short _inw_p(unsigned long port)
+{
+	unsigned short w;
+
+	if (port >= CFC_IOSTART && port <= CFC_IOEND) {
+		pcc_ioread_word(0, port, &w, sizeof(w), 1, 0);
+		return w;
+	} else {
+		w = *(volatile unsigned short *)PORT2ADDR(port);
+		delay();
+		return w;
+	}
+}
+
+unsigned long _inl_p(unsigned long port)
+{
+	unsigned long v;
+
+	v = *(volatile unsigned long *)PORT2ADDR(port);
+	delay();
+
+	return v;
+}
+
+void _outb(unsigned char b, unsigned long port)
+{
+	if (port >= CFC_IOSTART && port <= CFC_IOEND)
+		pcc_iowrite_byte(0, port, &b, sizeof(b), 1, 0);
+	else
+		*(volatile unsigned char *)PORT2ADDR(port) = b;
+}
+
+void _outw(unsigned short w, unsigned long port)
+{
+	if (port >= CFC_IOSTART && port <= CFC_IOEND)
+		pcc_iowrite_word(0, port, &w, sizeof(w), 1, 0);
+	else
+		*(volatile unsigned short *)PORT2ADDR(port) = w;
+}
+
+void _outl(unsigned long l, unsigned long port)
+{
+	if (port >= CFC_IOSTART && port <= CFC_IOEND)
+		pcc_iowrite_word(0, port, &l, sizeof(l), 1, 0);
+	else
+		*(volatile unsigned long *)PORT2ADDR(port) = l;
+}
+
+void _outb_p(unsigned char b, unsigned long port)
+{
+	if (port >= CFC_IOSTART && port <= CFC_IOEND)
+		pcc_iowrite_byte(0, port, &b, sizeof(b), 1, 0);
+	else
+		*(volatile unsigned char *)PORT2ADDR(port) = b;
+	delay();
+}
+
+void _outw_p(unsigned short w, unsigned long port)
+{
+	if (port >= CFC_IOSTART && port <= CFC_IOEND)
+		pcc_iowrite_word(0, port, &w, sizeof(w), 1, 0);
+	else
+		*(volatile unsigned short *)PORT2ADDR(port) = w;
+	delay();
+}
+
+void _outl_p(unsigned long l, unsigned long port)
+{
+	*(volatile unsigned long *)PORT2ADDR(port) = l;
+	delay();
+}
+
+void _insb(unsigned int port, void * addr, unsigned long count)
+{
+	if (port >= CFC_IOSTART && port <= CFC_IOEND)
+		pcc_ioread_byte(0, port, addr, sizeof(unsigned char), count, 1);
+	else {
+		unsigned char *buf = addr;
+		unsigned char *portp = PORT2ADDR(port);
+		while(count--) *buf++ = *(volatile unsigned char *)portp;
+	}
+}
+
+void _insw(unsigned int port, void * addr, unsigned long count)
+{
+	unsigned short *buf = addr;
+	unsigned short *portp;
+
+	if (port >= CFC_IOSTART && port <= CFC_IOEND)
+		pcc_ioread_word(0, port, addr, sizeof(unsigned short), count,
+			1);
+	else {
+		portp = PORT2ADDR(port);
+		while (count--) *buf++ = *(volatile unsigned short *)portp;
+	}
+}
+
+void _insl(unsigned int port, void * addr, unsigned long count)
+{
+	unsigned long *buf = addr;
+	unsigned long *portp;
+
+	portp = PORT2ADDR(port);
+	while (count--)
+		*buf++ = *(volatile unsigned long *)portp;
+}
+
+void _outsb(unsigned int port, const void * addr, unsigned long count)
+{
+	const unsigned char *buf = addr;
+	unsigned char *portp;
+
+	if (port >= CFC_IOSTART && port <= CFC_IOEND)
+		pcc_iowrite_byte(0, port, (void *)addr, sizeof(unsigned char),
+			count, 1);
+	else {
+		portp = PORT2ADDR(port);
+		while (count--)
+			*(volatile unsigned char *)portp = *buf++;
+	}
+}
+
+void _outsw(unsigned int port, const void * addr, unsigned long count)
+{
+	const unsigned short *buf = addr;
+	unsigned short *portp;
+
+	if (port >= CFC_IOSTART && port <= CFC_IOEND)
+		pcc_iowrite_word(0, port, (void *)addr, sizeof(unsigned short),
+			count, 1);
+	else {
+		portp = PORT2ADDR(port);
+		while (count--)
+			*(volatile unsigned short *)portp = *buf++;
+	}
+}
+
+void _outsl(unsigned int port, const void * addr, unsigned long count)
+{
+	const unsigned long *buf = addr;
+	unsigned char *portp;
+
+	portp = PORT2ADDR(port);
+	while (count--)
+		*(volatile unsigned long *)portp = *buf++;
+}
diff -Nru a/arch/m32r/kernel/irq.c b/arch/m32r/kernel/irq.c
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/arch/m32r/kernel/irq.c	2004-10-18 14:57:23 -07:00
@@ -0,0 +1,1020 @@
+/*
+ * linux/arch/m32r/kernel/irq.c
+ *
+ *  Copyright (c) 2003, 2004 Hitoshi Yamamoto
+ *
+ *  Taken from i386 2.6.4 version.
+ */
+
+/*
+ *	linux/arch/i386/kernel/irq.c
+ *
+ *	Copyright (C) 1992, 1998 Linus Torvalds, Ingo Molnar
+ *
+ * This file contains the code used by various IRQ handling routines:
+ * asking for different IRQ's should be done through these routines
+ * instead of just grabbing them. Thus setups with different IRQ numbers
+ * shouldn't result in any weird surprises, and installing new handlers
+ * should be easier.
+ */
+
+/*
+ * (mostly architecture independent, will move to kernel/irq.c in 2.5.)
+ *
+ * IRQs are in fact implemented a bit like signal handlers for the kernel.
+ * Naturally it's not a 1:1 relation, but there are similarities.
+ */
+
+#include <linux/config.h>
+#include <linux/errno.h>
+#include <linux/module.h>
+#include <linux/signal.h>
+#include <linux/sched.h>
+#include <linux/ioport.h>
+#include <linux/interrupt.h>
+#include <linux/timex.h>
+#include <linux/slab.h>
+#include <linux/random.h>
+#include <linux/smp_lock.h>
+#include <linux/init.h>
+#include <linux/kernel_stat.h>
+#include <linux/irq.h>
+#include <linux/proc_fs.h>
+#include <linux/seq_file.h>
+#include <linux/kallsyms.h>
+
+#include <asm/atomic.h>
+#include <asm/io.h>
+#include <asm/smp.h>
+#include <asm/system.h>
+#include <asm/bitops.h>
+#include <asm/uaccess.h>
+#include <asm/delay.h>
+#include <asm/irq.h>
+
+/*
+ * Linux has a controller-independent x86 interrupt architecture.
+ * every controller has a 'controller-template', that is used
+ * by the main code to do the right thing. Each driver-visible
+ * interrupt source is transparently wired to the apropriate
+ * controller. Thus drivers need not be aware of the
+ * interrupt-controller.
+ *
+ * Various interrupt controllers we handle: 8259 PIC, SMP IO-APIC,
+ * PIIX4's internal 8259 PIC and SGI's Visual Workstation Cobalt (IO-)APIC.
+ * (IO-APICs assumed to be messaging to Pentium local-APICs)
+ *
+ * the code is designed to be easily extended with new/different
+ * interrupt controllers, without having to do assembly magic.
+ */
+
+/*
+ * Controller mappings for all interrupt sources:
+ */
+irq_desc_t irq_desc[NR_IRQS] __cacheline_aligned = {
+	[0 ... NR_IRQS-1] = {
+		.handler = &no_irq_type,
+		.lock = SPIN_LOCK_UNLOCKED
+	}
+};
+
+static void register_irq_proc (unsigned int irq);
+
+/*
+ * Special irq handlers.
+ */
+
+irqreturn_t no_action(int cpl, void *dev_id, struct pt_regs *regs)
+{ return IRQ_NONE; }
+
+/*
+ * Generic no controller code
+ */
+
+static void enable_none(unsigned int irq) { }
+static unsigned int startup_none(unsigned int irq) { return 0; }
+static void disable_none(unsigned int irq) { }
+static void ack_none(unsigned int irq)
+{
+/*
+ * 'what should we do if we get a hw irq event on an illegal vector'.
+ * each architecture has to answer this themselves, it doesn't deserve
+ * a generic callback i think.
+ */
+	printk("unexpected IRQ trap at vector %02x\n", irq);
+}
+
+/* startup is the same as "enable", shutdown is same as "disable" */
+#define shutdown_none	disable_none
+#define end_none	enable_none
+
+struct hw_interrupt_type no_irq_type = {
+	"none",
+	startup_none,
+	shutdown_none,
+	enable_none,
+	disable_none,
+	ack_none,
+	end_none
+};
+
+atomic_t irq_err_count;
+atomic_t irq_mis_count;
+
+/*
+ * Generic, controller-independent functions:
+ */
+
+int show_interrupts(struct seq_file *p, void *v)
+{
+	int i = *(loff_t *) v, j;
+	struct irqaction * action;
+	unsigned long flags;
+
+	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');
+	}
+
+	if (i < NR_IRQS) {
+		spin_lock_irqsave(&irq_desc[i].lock, flags);
+		action = irq_desc[i].action;
+		if (!action)
+			goto skip;
+		seq_printf(p, "%3d: ",i);
+#ifndef CONFIG_SMP
+		seq_printf(p, "%10u ", kstat_irqs(i));
+#else
+		for (j = 0; j < NR_CPUS; j++)
+			if (cpu_online(j))
+				seq_printf(p, "%10u ", kstat_cpu(j).irqs[i]);
+#endif
+		seq_printf(p, " %14s", irq_desc[i].handler->typename);
+		seq_printf(p, "  %s", action->name);
+
+		for (action=action->next; action; action = action->next)
+			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, "ERR: %10u\n", atomic_read(&irq_err_count));
+		seq_printf(p, "MIS: %10u\n", atomic_read(&irq_mis_count));
+	}
+	return 0;
+}
+
+#ifdef CONFIG_SMP
+inline void synchronize_irq(unsigned int irq)
+{
+	while (irq_desc[irq].status & IRQ_INPROGRESS)
+		cpu_relax();
+}
+#endif
+
+/*
+ * This should really return information about whether
+ * we should do bottom half handling etc. Right now we
+ * end up _always_ checking the bottom half, which is a
+ * waste of time and is not what some drivers would
+ * prefer.
+ */
+int handle_IRQ_event(unsigned int irq,
+		struct pt_regs *regs, struct irqaction *action)
+{
+	int status = 1;	/* Force the "do bottom halves" bit */
+	int ret, retval = 0;
+
+	if (!(action->flags & SA_INTERRUPT))
+		local_irq_enable();
+
+	do {
+		ret = action->handler(irq, action->dev_id, regs);
+		if (ret == IRQ_HANDLED)
+			status |= action->flags;
+		action = action->next;
+		retval |= ret;
+	} while (action);
+	if (status & SA_SAMPLE_RANDOM)
+		add_interrupt_randomness(irq);
+	local_irq_disable();
+	return retval;
+}
+
+static void __report_bad_irq(int irq, irq_desc_t *desc, irqreturn_t action_ret)
+{
+	struct irqaction *action;
+
+	if (action_ret != IRQ_HANDLED && action_ret != IRQ_NONE) {
+		printk(KERN_ERR "irq event %d: bogus return value %x\n",
+				irq, action_ret);
+	} else {
+		printk(KERN_ERR "irq %d: nobody cared!\n", irq);
+	}
+	dump_stack();
+	printk(KERN_ERR "handlers:\n");
+	action = desc->action;
+	do {
+		printk(KERN_ERR "[<%p>]", action->handler);
+		print_symbol(" (%s)",
+			(unsigned long)action->handler);
+		printk("\n");
+		action = action->next;
+	} while (action);
+}
+
+static void report_bad_irq(int irq, irq_desc_t *desc, irqreturn_t action_ret)
+{
+	static int count = 100;
+
+	if (count) {
+		count--;
+		__report_bad_irq(irq, desc, action_ret);
+	}
+}
+
+static int noirqdebug;
+
+static int __init noirqdebug_setup(char *str)
+{
+	noirqdebug = 1;
+	printk("IRQ lockup detection disabled\n");
+	return 1;
+}
+
+__setup("noirqdebug", noirqdebug_setup);
+
+/*
+ * If 99,900 of the previous 100,000 interrupts have not been handled then
+ * assume that the IRQ is stuck in some manner.  Drop a diagnostic and try to
+ * turn the IRQ off.
+ *
+ * (The other 100-of-100,000 interrupts may have been a correctly-functioning
+ *  device sharing an IRQ with the failing one)
+ *
+ * Called under desc->lock
+ */
+static void note_interrupt(int irq, irq_desc_t *desc, irqreturn_t action_ret)
+{
+	if (action_ret != IRQ_HANDLED) {
+		desc->irqs_unhandled++;
+		if (action_ret != IRQ_NONE)
+			report_bad_irq(irq, desc, action_ret);
+	}
+
+	desc->irq_count++;
+	if (desc->irq_count < 100000)
+		return;
+
+	desc->irq_count = 0;
+	if (desc->irqs_unhandled > 99900) {
+		/*
+		 * The interrupt is stuck
+		 */
+		__report_bad_irq(irq, desc, action_ret);
+		/*
+		 * Now kill the IRQ
+		 */
+		printk(KERN_EMERG "Disabling IRQ #%d\n", irq);
+		desc->status |= IRQ_DISABLED;
+		desc->handler->disable(irq);
+	}
+	desc->irqs_unhandled = 0;
+}
+
+/*
+ * Generic enable/disable code: this just calls
+ * down into the PIC-specific version for the actual
+ * hardware disable after having gotten the irq
+ * controller lock.
+ */
+
+/**
+ *	disable_irq_nosync - disable an irq without waiting
+ *	@irq: Interrupt to disable
+ *
+ *	Disable the selected interrupt line.  Disables and Enables are
+ *	nested.
+ *	Unlike disable_irq(), this function does not ensure existing
+ *	instances of the IRQ handler have completed before returning.
+ *
+ *	This function may be called from IRQ context.
+ */
+
+inline void disable_irq_nosync(unsigned int irq)
+{
+	irq_desc_t *desc = irq_desc + irq;
+	unsigned long flags;
+
+	spin_lock_irqsave(&desc->lock, flags);
+	if (!desc->depth++) {
+		desc->status |= IRQ_DISABLED;
+		desc->handler->disable(irq);
+	}
+	spin_unlock_irqrestore(&desc->lock, flags);
+}
+
+/**
+ *	disable_irq - disable an irq and wait for completion
+ *	@irq: Interrupt to disable
+ *
+ *	Disable the selected interrupt line.  Enables and Disables are
+ *	nested.
+ *	This function waits for any pending IRQ handlers for this interrupt
+ *	to complete before returning. If you use this function while
+ *	holding a resource the IRQ handler may need you will deadlock.
+ *
+ *	This function may be called - with care - from IRQ context.
+ */
+
+void disable_irq(unsigned int irq)
+{
+	irq_desc_t *desc = irq_desc + irq;
+	disable_irq_nosync(irq);
+	if (desc->action)
+		synchronize_irq(irq);
+}
+
+/**
+ *	enable_irq - enable handling of an irq
+ *	@irq: Interrupt to enable
+ *
+ *	Undoes the effect of one call to disable_irq().  If this
+ *	matches the last disable, processing of interrupts on this
+ *	IRQ line is re-enabled.
+ *
+ *	This function may be called from IRQ context.
+ */
+
+void enable_irq(unsigned int irq)
+{
+	irq_desc_t *desc = irq_desc + irq;
+	unsigned long flags;
+
+	spin_lock_irqsave(&desc->lock, flags);
+	switch (desc->depth) {
+	case 1: {
+		unsigned int status = desc->status & ~IRQ_DISABLED;
+		desc->status = status;
+		if ((status & (IRQ_PENDING | IRQ_REPLAY)) == IRQ_PENDING) {
+			desc->status = status | IRQ_REPLAY;
+			hw_resend_irq(desc->handler,irq);
+		}
+		desc->handler->enable(irq);
+		/* fall-through */
+	}
+	default:
+		desc->depth--;
+		break;
+	case 0:
+		printk("enable_irq(%u) unbalanced from %p\n", irq,
+		       __builtin_return_address(0));
+	}
+	spin_unlock_irqrestore(&desc->lock, flags);
+}
+
+/*
+ * do_IRQ handles all normal device IRQ's (the special
+ * SMP cross-CPU interrupts have their own specific
+ * handlers).
+ */
+asmlinkage unsigned int do_IRQ(int irq, struct pt_regs *regs)
+{
+	/*
+	 * We ack quickly, we don't want the irq controller
+	 * thinking we're snobs just because some other CPU has
+	 * disabled global interrupts (we have already done the
+	 * INT_ACK cycles, it's too late to try to pretend to the
+	 * controller that we aren't taking the interrupt).
+	 *
+	 * 0 return value means that this irq is already being
+	 * handled by some other CPU. (or is disabled)
+	 */
+	irq_desc_t *desc = irq_desc + irq;
+	struct irqaction * action;
+	unsigned int status;
+
+	irq_enter();
+
+#ifdef CONFIG_DEBUG_STACKOVERFLOW
+	/* FIXME M32R */
+#endif
+	kstat_this_cpu.irqs[irq]++;
+	spin_lock(&desc->lock);
+	desc->handler->ack(irq);
+	/*
+	   REPLAY is when Linux resends an IRQ that was dropped earlier
+	   WAITING is used by probe to mark irqs that are being tested
+	   */
+	status = desc->status & ~(IRQ_REPLAY | IRQ_WAITING);
+	status |= IRQ_PENDING; /* we _want_ to handle it */
+
+	/*
+	 * If the IRQ is disabled for whatever reason, we cannot
+	 * use the action we have.
+	 */
+	action = NULL;
+	if (likely(!(status & (IRQ_DISABLED | IRQ_INPROGRESS)))) {
+		action = desc->action;
+		status &= ~IRQ_PENDING; /* we commit to handling */
+		status |= IRQ_INPROGRESS; /* we are handling it */
+	}
+	desc->status = status;
+
+	/*
+	 * If there is no IRQ handler or it was disabled, exit early.
+	   Since we set PENDING, if another processor is handling
+	   a different instance of this same irq, the other processor
+	   will take care of it.
+	 */
+	if (unlikely(!action))
+		goto out;
+
+	/*
+	 * Edge triggered interrupts need to remember
+	 * pending events.
+	 * This applies to any hw interrupts that allow a second
+	 * instance of the same irq to arrive while we are in do_IRQ
+	 * or in the handler. But the code here only handles the _second_
+	 * instance of the irq, not the third or fourth. So it is mostly
+	 * useful for irq hardware that does not mask cleanly in an
+	 * SMP environment.
+	 */
+	for (;;) {
+		irqreturn_t action_ret;
+
+		spin_unlock(&desc->lock);
+		action_ret = handle_IRQ_event(irq, regs, action);
+		spin_lock(&desc->lock);
+		if (!noirqdebug)
+			note_interrupt(irq, desc, action_ret);
+		if (likely(!(desc->status & IRQ_PENDING)))
+			break;
+		desc->status &= ~IRQ_PENDING;
+	}
+	desc->status &= ~IRQ_INPROGRESS;
+
+out:
+	/*
+	 * The ->end() handler has to deal with interrupts which got
+	 * disabled while the handler was running.
+	 */
+	desc->handler->end(irq);
+	spin_unlock(&desc->lock);
+
+	irq_exit();
+
+#if defined(CONFIG_SMP)
+	if (irq == M32R_IRQ_MFT2)
+		smp_send_timer();
+#endif	/* CONFIG_SMP */
+
+	return 1;
+}
+
+int can_request_irq(unsigned int irq, unsigned long irqflags)
+{
+	struct irqaction *action;
+
+	if (irq >= NR_IRQS)
+		return 0;
+	action = irq_desc[irq].action;
+	if (action) {
+		if (irqflags & action->flags & SA_SHIRQ)
+			action = NULL;
+	}
+	return !action;
+}
+
+/**
+ *	request_irq - allocate an interrupt line
+ *	@irq: Interrupt line to allocate
+ *	@handler: Function to be called when the IRQ occurs
+ *	@irqflags: Interrupt type flags
+ *	@devname: An ascii name for the claiming device
+ *	@dev_id: A cookie passed back to the handler function
+ *
+ *	This call allocates interrupt resources and enables the
+ *	interrupt line and IRQ handling. From the point this
+ *	call is made your handler function may be invoked. Since
+ *	your handler function must clear any interrupt the board
+ *	raises, you must take care both to initialise your hardware
+ *	and to set up the interrupt handler in the right order.
+ *
+ *	Dev_id must be globally unique. Normally the address of the
+ *	device data structure is used as the cookie. Since the handler
+ *	receives this value it makes sense to use it.
+ *
+ *	If your interrupt is shared you must pass a non NULL dev_id
+ *	as this is required when freeing the interrupt.
+ *
+ *	Flags:
+ *
+ *	SA_SHIRQ		Interrupt is shared
+ *
+ *	SA_INTERRUPT		Disable local interrupts while processing
+ *
+ *	SA_SAMPLE_RANDOM	The interrupt can be used for entropy
+ *
+ */
+
+int request_irq(unsigned int irq,
+		irqreturn_t (*handler)(int, void *, struct pt_regs *),
+		unsigned long irqflags,
+		const char * devname,
+		void *dev_id)
+{
+	int retval;
+	struct irqaction * action;
+
+#if 1
+	/*
+	 * Sanity-check: shared interrupts should REALLY pass in
+	 * a real dev-ID, otherwise we'll have trouble later trying
+	 * to figure out which interrupt is which (messes up the
+	 * interrupt freeing logic etc).
+	 */
+	if (irqflags & SA_SHIRQ) {
+		if (!dev_id)
+			printk("Bad boy: %s (at 0x%x) called us without a dev_id!\n", devname, (&irq)[-1]);
+	}
+#endif
+
+	if (irq >= NR_IRQS)
+		return -EINVAL;
+	if (!handler)
+		return -EINVAL;
+
+	action = (struct irqaction *)
+			kmalloc(sizeof(struct irqaction), GFP_ATOMIC);
+	if (!action)
+		return -ENOMEM;
+
+	action->handler = handler;
+	action->flags = irqflags;
+	cpus_clear(action->mask);
+	action->name = devname;
+	action->next = NULL;
+	action->dev_id = dev_id;
+
+	retval = setup_irq(irq, action);
+	if (retval)
+		kfree(action);
+	return retval;
+}
+
+EXPORT_SYMBOL(request_irq);
+
+/**
+ *	free_irq - free an interrupt
+ *	@irq: Interrupt line to free
+ *	@dev_id: Device identity to free
+ *
+ *	Remove an interrupt handler. The handler is removed and if the
+ *	interrupt line is no longer in use by any driver it is disabled.
+ *	On a shared IRQ the caller must ensure the interrupt is disabled
+ *	on the card it drives before calling this function. The function
+ *	does not return until any executing interrupts for this IRQ
+ *	have completed.
+ *
+ *	This function must not be called from interrupt context.
+ */
+
+void free_irq(unsigned int irq, void *dev_id)
+{
+	irq_desc_t *desc;
+	struct irqaction **p;
+	unsigned long flags;
+
+	if (irq >= NR_IRQS)
+		return;
+
+	desc = irq_desc + irq;
+	spin_lock_irqsave(&desc->lock,flags);
+	p = &desc->action;
+	for (;;) {
+		struct irqaction * action = *p;
+		if (action) {
+			struct irqaction **pp = p;
+			p = &action->next;
+			if (action->dev_id != dev_id)
+				continue;
+
+			/* Found it - now remove it from the list of entries */
+			*pp = action->next;
+			if (!desc->action) {
+				desc->status |= IRQ_DISABLED;
+				desc->handler->shutdown(irq);
+			}
+			spin_unlock_irqrestore(&desc->lock,flags);
+
+			/* Wait to make sure it's not being used on another CPU */
+			synchronize_irq(irq);
+			kfree(action);
+			return;
+		}
+		printk("Trying to free free IRQ%d\n",irq);
+		spin_unlock_irqrestore(&desc->lock,flags);
+		return;
+	}
+}
+
+EXPORT_SYMBOL(free_irq);
+
+/*
+ * IRQ autodetection code..
+ *
+ * This depends on the fact that any interrupt that
+ * comes in on to an unassigned handler will get stuck
+ * with "IRQ_WAITING" cleared and the interrupt
+ * disabled.
+ */
+
+static DECLARE_MUTEX(probe_sem);
+
+/**
+ *	probe_irq_on	- begin an interrupt autodetect
+ *
+ *	Commence probing for an interrupt. The interrupts are scanned
+ *	and a mask of potential interrupt lines is returned.
+ *
+ */
+
+unsigned long probe_irq_on(void)
+{
+	unsigned int i;
+	irq_desc_t *desc;
+	unsigned long val;
+	unsigned long delay;
+
+	down(&probe_sem);
+	/*
+	 * something may have generated an irq long ago and we want to
+	 * flush such a longstanding irq before considering it as spurious.
+	 */
+	for (i = NR_IRQS-1; i > 0; i--)  {
+		desc = irq_desc + i;
+
+		spin_lock_irq(&desc->lock);
+		if (!irq_desc[i].action)
+			irq_desc[i].handler->startup(i);
+		spin_unlock_irq(&desc->lock);
+	}
+
+	/* Wait for longstanding interrupts to trigger. */
+	for (delay = jiffies + HZ/50; time_after(delay, jiffies); )
+		/* about 20ms delay */ barrier();
+
+	/*
+	 * enable any unassigned irqs
+	 * (we must startup again here because if a longstanding irq
+	 * happened in the previous stage, it may have masked itself)
+	 */
+	for (i = NR_IRQS-1; i > 0; i--) {
+		desc = irq_desc + i;
+
+		spin_lock_irq(&desc->lock);
+		if (!desc->action) {
+			desc->status |= IRQ_AUTODETECT | IRQ_WAITING;
+			if (desc->handler->startup(i))
+				desc->status |= IRQ_PENDING;
+		}
+		spin_unlock_irq(&desc->lock);
+	}
+
+	/*
+	 * Wait for spurious interrupts to trigger
+	 */
+	for (delay = jiffies + HZ/10; time_after(delay, jiffies); )
+		/* about 100ms delay */ barrier();
+
+	/*
+	 * Now filter out any obviously spurious interrupts
+	 */
+	val = 0;
+	for (i = 0; i < NR_IRQS; i++) {
+		irq_desc_t *desc = irq_desc + i;
+		unsigned int status;
+
+		spin_lock_irq(&desc->lock);
+		status = desc->status;
+
+		if (status & IRQ_AUTODETECT) {
+			/* It triggered already - consider it spurious. */
+			if (!(status & IRQ_WAITING)) {
+				desc->status = status & ~IRQ_AUTODETECT;
+				desc->handler->shutdown(i);
+			} else
+				if (i < 32)
+					val |= 1 << i;
+		}
+		spin_unlock_irq(&desc->lock);
+	}
+
+	return val;
+}
+
+EXPORT_SYMBOL(probe_irq_on);
+
+/*
+ * Return a mask of triggered interrupts (this
+ * can handle only legacy ISA interrupts).
+ */
+
+/**
+ *	probe_irq_mask - scan a bitmap of interrupt lines
+ *	@val:	mask of interrupts to consider
+ *
+ *	Scan the ISA bus interrupt lines and return a bitmap of
+ *	active interrupts. The interrupt probe logic state is then
+ *	returned to its previous value.
+ *
+ *	Note: we need to scan all the irq's even though we will
+ *	only return ISA irq numbers - just so that we reset them
+ *	all to a known state.
+ */
+unsigned int probe_irq_mask(unsigned long val)
+{
+	int i;
+	unsigned int mask;
+
+	mask = 0;
+	for (i = 0; i < NR_IRQS; i++) {
+		irq_desc_t *desc = irq_desc + i;
+		unsigned int status;
+
+		spin_lock_irq(&desc->lock);
+		status = desc->status;
+
+		if (status & IRQ_AUTODETECT) {
+			if (i < 16 && !(status & IRQ_WAITING))
+				mask |= 1 << i;
+
+			desc->status = status & ~IRQ_AUTODETECT;
+			desc->handler->shutdown(i);
+		}
+		spin_unlock_irq(&desc->lock);
+	}
+	up(&probe_sem);
+
+	return mask & val;
+}
+
+/*
+ * Return the one interrupt that triggered (this can
+ * handle any interrupt source).
+ */
+
+/**
+ *	probe_irq_off	- end an interrupt autodetect
+ *	@val: mask of potential interrupts (unused)
+ *
+ *	Scans the unused interrupt lines and returns the line which
+ *	appears to have triggered the interrupt. If no interrupt was
+ *	found then zero is returned. If more than one interrupt is
+ *	found then minus the first candidate is returned to indicate
+ *	their is doubt.
+ *
+ *	The interrupt probe logic state is returned to its previous
+ *	value.
+ *
+ *	BUGS: When used in a module (which arguably shouldnt happen)
+ *	nothing prevents two IRQ probe callers from overlapping. The
+ *	results of this are non-optimal.
+ */
+
+int probe_irq_off(unsigned long val)
+{
+	int i, irq_found, nr_irqs;
+
+	nr_irqs = 0;
+	irq_found = 0;
+	for (i = 0; i < NR_IRQS; i++) {
+		irq_desc_t *desc = irq_desc + i;
+		unsigned int status;
+
+		spin_lock_irq(&desc->lock);
+		status = desc->status;
+
+		if (status & IRQ_AUTODETECT) {
+			if (!(status & IRQ_WAITING)) {
+				if (!nr_irqs)
+					irq_found = i;
+				nr_irqs++;
+			}
+			desc->status = status & ~IRQ_AUTODETECT;
+			desc->handler->shutdown(i);
+		}
+		spin_unlock_irq(&desc->lock);
+	}
+	up(&probe_sem);
+
+	if (nr_irqs > 1)
+		irq_found = -irq_found;
+	return irq_found;
+}
+
+EXPORT_SYMBOL(probe_irq_off);
+
+/* this was setup_x86_irq but it seems pretty generic */
+int setup_irq(unsigned int irq, struct irqaction * new)
+{
+	int shared = 0;
+	unsigned long flags;
+	struct irqaction *old, **p;
+	irq_desc_t *desc = irq_desc + irq;
+
+	if (desc->handler == &no_irq_type)
+		return -ENOSYS;
+	/*
+	 * Some drivers like serial.c use request_irq() heavily,
+	 * so we have to be careful not to interfere with a
+	 * running system.
+	 */
+	if (new->flags & SA_SAMPLE_RANDOM) {
+		/*
+		 * This function might sleep, we want to call it first,
+		 * outside of the atomic block.
+		 * Yes, this might clear the entropy pool if the wrong
+		 * driver is attempted to be loaded, without actually
+		 * installing a new handler, but is this really a problem,
+		 * only the sysadmin is able to do this.
+		 */
+		rand_initialize_irq(irq);
+	}
+
+	/*
+	 * The following block of code has to be executed atomically
+	 */
+	spin_lock_irqsave(&desc->lock,flags);
+	p = &desc->action;
+	if ((old = *p) != NULL) {
+		/* Can't share interrupts unless both agree to */
+		if (!(old->flags & new->flags & SA_SHIRQ)) {
+			spin_unlock_irqrestore(&desc->lock,flags);
+			return -EBUSY;
+		}
+
+		/* add new interrupt at end of irq queue */
+		do {
+			p = &old->next;
+			old = *p;
+		} while (old);
+		shared = 1;
+	}
+
+	*p = new;
+
+	if (!shared) {
+		desc->depth = 0;
+		desc->status &= ~(IRQ_DISABLED | IRQ_AUTODETECT | IRQ_WAITING | IRQ_INPROGRESS);
+		desc->handler->startup(irq);
+	}
+	spin_unlock_irqrestore(&desc->lock,flags);
+
+	register_irq_proc(irq);
+	return 0;
+}
+
+static struct proc_dir_entry * root_irq_dir;
+static struct proc_dir_entry * irq_dir [NR_IRQS];
+
+#ifdef CONFIG_SMP
+
+static struct proc_dir_entry *smp_affinity_entry[NR_IRQS];
+
+cpumask_t irq_affinity[NR_IRQS] = { [0 ... NR_IRQS-1] = CPU_MASK_ALL };
+
+static int irq_affinity_read_proc(char *page, char **start, off_t off,
+			int count, int *eof, void *data)
+{
+	int len = cpumask_scnprintf(page, count, irq_affinity[(long)data]);
+	if (count - len < 2)
+		return -EINVAL;
+	len += sprintf(page + len, "\n");
+	return len;
+}
+
+static int irq_affinity_write_proc(struct file *file, const char __user *buffer,
+					unsigned long count, void *data)
+{
+	int irq = (long)data, full_count = count, err;
+	cpumask_t new_value, tmp;
+
+	if (!irq_desc[irq].handler->set_affinity)
+		return -EIO;
+
+	err = cpumask_parse(buffer, count, new_value);
+	if (err)
+		return err;
+
+	/*
+	 * Do not allow disabling IRQs completely - it's a too easy
+	 * 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;
+
+	irq_affinity[irq] = new_value;
+	irq_desc[irq].handler->set_affinity(irq,
+					cpumask_of_cpu(first_cpu(new_value)));
+
+	return full_count;
+}
+
+#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)
+{
+	char name [MAX_NAMELEN];
+
+	if (!root_irq_dir || (irq_desc[irq].handler == &no_irq_type) ||
+			irq_dir[irq])
+		return;
+
+	memset(name, 0, MAX_NAMELEN);
+	sprintf(name, "%d", irq);
+
+	/* create /proc/irq/1234 */
+	irq_dir[irq] = proc_mkdir(name, root_irq_dir);
+
+#ifdef CONFIG_SMP
+	{
+		struct proc_dir_entry *entry;
+
+		/* create /proc/irq/1234/smp_affinity */
+		entry = create_proc_entry("smp_affinity", 0600, irq_dir[irq]);
+
+		if (entry) {
+			entry->nlink = 1;
+			entry->data = (void *)(long)irq;
+			entry->read_proc = irq_affinity_read_proc;
+			entry->write_proc = irq_affinity_write_proc;
+		}
+
+		smp_affinity_entry[irq] = entry;
+	}
+#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 entries for all existing IRQs.
+	 */
+	for (i = 0; i < NR_IRQS; i++)
+		register_irq_proc(i);
+}
+
diff -Nru a/arch/m32r/kernel/m32r_ksyms.c b/arch/m32r/kernel/m32r_ksyms.c
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/arch/m32r/kernel/m32r_ksyms.c	2004-10-18 14:57:22 -07:00
@@ -0,0 +1,141 @@
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/smp.h>
+#include <linux/user.h>
+#include <linux/elfcore.h>
+#include <linux/sched.h>
+#include <linux/in6.h>
+#include <linux/interrupt.h>
+#include <linux/smp_lock.h>
+#include <linux/string.h>
+
+#include <asm/semaphore.h>
+#include <asm/processor.h>
+#include <asm/uaccess.h>
+#include <asm/checksum.h>
+#include <asm/io.h>
+#include <asm/delay.h>
+#include <asm/irq.h>
+#include <asm/tlbflush.h>
+
+extern void dump_thread(struct pt_regs *, struct user *);
+
+#if defined(CONFIG_BLK_DEV_IDE) || defined(CONFIG_BLK_DEV_HD) || defined(CONFIG_BLK_DEV_IDE_MODULE) || defined(CONFIG_BLK_DEV_HD_MODULE)
+extern struct drive_info_struct drive_info;
+EXPORT_SYMBOL(drive_info);
+#endif
+
+/* platform dependent support */
+EXPORT_SYMBOL(boot_cpu_data);
+EXPORT_SYMBOL(dump_thread);
+EXPORT_SYMBOL(dump_fpu);
+EXPORT_SYMBOL(__ioremap);
+EXPORT_SYMBOL(iounmap);
+EXPORT_SYMBOL(enable_irq);
+EXPORT_SYMBOL(disable_irq);
+EXPORT_SYMBOL(disable_irq_nosync);
+EXPORT_SYMBOL(kernel_thread);
+EXPORT_SYMBOL(__down);
+EXPORT_SYMBOL(__down_interruptible);
+EXPORT_SYMBOL(__up);
+EXPORT_SYMBOL(__down_trylock);
+
+/* Networking helper routines. */
+/* Delay loops */
+EXPORT_SYMBOL(__udelay);
+EXPORT_SYMBOL(__delay);
+EXPORT_SYMBOL(__const_udelay);
+
+EXPORT_SYMBOL(__get_user_1);
+EXPORT_SYMBOL(__get_user_2);
+EXPORT_SYMBOL(__get_user_4);
+
+EXPORT_SYMBOL(strpbrk);
+EXPORT_SYMBOL(strstr);
+
+EXPORT_SYMBOL(strncpy_from_user);
+EXPORT_SYMBOL(__strncpy_from_user);
+EXPORT_SYMBOL(clear_user);
+EXPORT_SYMBOL(__clear_user);
+EXPORT_SYMBOL(__generic_copy_from_user);
+EXPORT_SYMBOL(__generic_copy_to_user);
+EXPORT_SYMBOL(strnlen_user);
+
+#ifdef CONFIG_SMP
+#ifdef CONFIG_CHIP_M32700_TS1
+extern void *dcache_dummy;
+EXPORT_SYMBOL(dcache_dummy);
+#endif
+EXPORT_SYMBOL(cpu_data);
+EXPORT_SYMBOL(cpu_online_map);
+EXPORT_SYMBOL(cpu_callout_map);
+
+/* Global SMP stuff */
+EXPORT_SYMBOL(synchronize_irq);
+EXPORT_SYMBOL(smp_call_function);
+
+/* TLB flushing */
+EXPORT_SYMBOL(smp_flush_tlb_page);
+EXPORT_SYMBOL_GPL(smp_flush_tlb_all);
+#endif
+
+/* compiler generated symbol */
+extern void __ashldi3(void);
+extern void __ashrdi3(void);
+extern void __lshldi3(void);
+extern void __lshrdi3(void);
+extern void __muldi3(void);
+EXPORT_SYMBOL(__ashldi3);
+EXPORT_SYMBOL(__ashrdi3);
+EXPORT_SYMBOL(__lshldi3);
+EXPORT_SYMBOL(__lshrdi3);
+EXPORT_SYMBOL(__muldi3);
+
+/* memory and string operations */
+EXPORT_SYMBOL(memchr);
+EXPORT_SYMBOL(memcpy);
+/* EXPORT_SYMBOL(memcpy_fromio); // not implement yet */
+/* EXPORT_SYMBOL(memcpy_toio); // not implement yet */
+EXPORT_SYMBOL(memset);
+/* EXPORT_SYMBOL(memset_io); // not implement yet */
+EXPORT_SYMBOL(memmove);
+EXPORT_SYMBOL(memcmp);
+EXPORT_SYMBOL(memscan);
+EXPORT_SYMBOL(copy_page);
+EXPORT_SYMBOL(clear_page);
+
+EXPORT_SYMBOL(strcat);
+EXPORT_SYMBOL(strchr);
+EXPORT_SYMBOL(strcmp);
+EXPORT_SYMBOL(strcpy);
+EXPORT_SYMBOL(strlen);
+EXPORT_SYMBOL(strncat);
+EXPORT_SYMBOL(strncmp);
+EXPORT_SYMBOL(strnlen);
+EXPORT_SYMBOL(strncpy);
+
+EXPORT_SYMBOL(_inb);
+EXPORT_SYMBOL(_inw);
+EXPORT_SYMBOL(_inl);
+EXPORT_SYMBOL(_outb);
+EXPORT_SYMBOL(_outw);
+EXPORT_SYMBOL(_outl);
+EXPORT_SYMBOL(_inb_p);
+EXPORT_SYMBOL(_inw_p);
+EXPORT_SYMBOL(_inl_p);
+EXPORT_SYMBOL(_outb_p);
+EXPORT_SYMBOL(_outw_p);
+EXPORT_SYMBOL(_outl_p);
+EXPORT_SYMBOL(_insb);
+EXPORT_SYMBOL(_insw);
+EXPORT_SYMBOL(_insl);
+EXPORT_SYMBOL(_outsb);
+EXPORT_SYMBOL(_outsw);
+EXPORT_SYMBOL(_outsl);
+EXPORT_SYMBOL(_readb);
+EXPORT_SYMBOL(_readw);
+EXPORT_SYMBOL(_readl);
+EXPORT_SYMBOL(_writeb);
+EXPORT_SYMBOL(_writew);
+EXPORT_SYMBOL(_writel);
+
diff -Nru a/arch/m32r/kernel/module.c b/arch/m32r/kernel/module.c
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/arch/m32r/kernel/module.c	2004-10-18 14:57:24 -07:00
@@ -0,0 +1,253 @@
+/*  Kernel module help for M32R.
+
+    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
+*/
+#include <linux/moduleloader.h>
+#include <linux/elf.h>
+#include <linux/vmalloc.h>
+#include <linux/fs.h>
+#include <linux/string.h>
+#include <linux/kernel.h>
+
+#if 0
+#define DEBUGP printk
+#else
+#define DEBUGP(fmt...)
+#endif
+
+void *module_alloc(unsigned long size)
+{
+	if (size == 0)
+		return NULL;
+	return vmalloc_exec(size);
+}
+
+
+/* Free memory returned from module_alloc */
+void module_free(struct module *mod, void *module_region)
+{
+	vfree(module_region);
+	/* FIXME: If module_region == mod->init_region, trim exception
+           table entries. */
+}
+
+/* We don't need anything special. */
+int module_frob_arch_sections(Elf_Ehdr *hdr,
+			      Elf_Shdr *sechdrs,
+			      char *secstrings,
+			      struct module *mod)
+{
+	return 0;
+}
+
+#define COPY_UNALIGNED_WORD(sw, tw, align) \
+{ \
+	void *__s = &(sw), *__t = &(tw); \
+	unsigned short *__s2 = __s, *__t2 =__t; \
+	unsigned char *__s1 = __s, *__t1 =__t; \
+	switch ((align)) \
+	{ \
+	case 0: \
+		*(unsigned long *) __t = *(unsigned long *) __s; \
+		break; \
+	case 2: \
+		*__t2++ = *__s2++; \
+		*__t2 = *__s2; \
+		break; \
+	default: \
+		*__t1++ = *__s1++; \
+		*__t1++ = *__s1++; \
+		*__t1++ = *__s1++; \
+		*__t1 = *__s1; \
+		break; \
+	} \
+}
+
+#define COPY_UNALIGNED_HWORD(sw, tw, align) \
+  { \
+    void *__s = &(sw), *__t = &(tw); \
+    unsigned short *__s2 = __s, *__t2 =__t; \
+    unsigned char *__s1 = __s, *__t1 =__t; \
+    switch ((align)) \
+    { \
+    case 0: \
+      *__t2 = *__s2; \
+      break; \
+    default: \
+      *__t1++ = *__s1++; \
+      *__t1 = *__s1; \
+      break; \
+    } \
+  }
+
+int apply_relocate_add(Elf32_Shdr *sechdrs,
+		   const char *strtab,
+		   unsigned int symindex,
+		   unsigned int relsec,
+		   struct module *me)
+{
+	unsigned int i;
+	Elf32_Rela *rel = (void *)sechdrs[relsec].sh_addr;
+	Elf32_Sym *sym;
+	Elf32_Addr relocation;
+	uint32_t *location;
+	uint32_t value;
+	unsigned short *hlocation;
+	unsigned short hvalue;
+	int svalue;
+	int align;
+
+	DEBUGP("Applying relocate section %u to %u\n", relsec,
+	       sechdrs[relsec].sh_info);
+	for (i = 0; i < sechdrs[relsec].sh_size / sizeof(*rel); i++) {
+		/* This is where to make the change */
+		location = (void *)sechdrs[sechdrs[relsec].sh_info].sh_addr
+			+ rel[i].r_offset;
+		/* This is the symbol it is referring to.  Note that all
+		   undefined symbols have been resolved.  */
+		sym = (Elf32_Sym *)sechdrs[symindex].sh_addr
+			+ ELF32_R_SYM(rel[i].r_info);
+		relocation = sym->st_value + rel[i].r_addend;
+		align = (int)location & 3;
+
+		switch (ELF32_R_TYPE(rel[i].r_info)) {
+		case R_M32R_32_RELA:
+	    		COPY_UNALIGNED_WORD (*location, value, align);
+			value += relocation;
+	    		COPY_UNALIGNED_WORD (value, *location, align);
+			break;
+		case R_M32R_HI16_ULO_RELA:
+	    		COPY_UNALIGNED_WORD (*location, value, align);
+                        relocation = (relocation >>16) & 0xffff;
+			/* RELA must has 0 at relocation field. */
+			value += relocation;
+	    		COPY_UNALIGNED_WORD (value, *location, align);
+			break;
+		case R_M32R_HI16_SLO_RELA:
+	    		COPY_UNALIGNED_WORD (*location, value, align);
+			if (relocation & 0x8000) relocation += 0x10000;
+                        relocation = (relocation >>16) & 0xffff;
+			/* RELA must has 0 at relocation field. */
+			value += relocation;
+	    		COPY_UNALIGNED_WORD (value, *location, align);
+			break;
+		case R_M32R_16_RELA:
+			hlocation = (unsigned short *)location;
+                        relocation = relocation & 0xffff;
+			/* RELA must has 0 at relocation field. */
+			hvalue = relocation;
+	    		COPY_UNALIGNED_WORD (hvalue, *hlocation, align);
+			break;
+		case R_M32R_SDA16_RELA:
+		case R_M32R_LO16_RELA:
+	    		COPY_UNALIGNED_WORD (*location, value, align);
+                        relocation = relocation & 0xffff;
+			/* RELA must has 0 at relocation field. */
+			value += relocation;
+	    		COPY_UNALIGNED_WORD (value, *location, align);
+			break;
+		case R_M32R_24_RELA:
+	    		COPY_UNALIGNED_WORD (*location, value, align);
+                        relocation = relocation & 0xffffff;
+			/* RELA must has 0 at relocation field. */
+			value += relocation;
+	    		COPY_UNALIGNED_WORD (value, *location, align);
+			break;
+		case R_M32R_18_PCREL_RELA:
+	  		relocation = (relocation - (Elf32_Addr) location);
+			if (relocation < -0x20000 || 0x1fffc < relocation)
+				{
+					printk(KERN_ERR "module %s: relocation overflow: %u\n",
+					me->name, relocation);
+					return -ENOEXEC;
+				}
+	    		COPY_UNALIGNED_WORD (*location, value, align);
+			if (value & 0xffff)
+				{
+					/* RELA must has 0 at relocation field. */
+					printk(KERN_ERR "module %s: illegal relocation field: %u\n",
+					me->name, value);
+					return -ENOEXEC;
+				}
+                        relocation = (relocation >> 2) & 0xffff;
+			value += relocation;
+	    		COPY_UNALIGNED_WORD (value, *location, align);
+			break;
+		case R_M32R_10_PCREL_RELA:
+			hlocation = (unsigned short *)location;
+	  		relocation = (relocation - (Elf32_Addr) location);
+	    		COPY_UNALIGNED_HWORD (*hlocation, hvalue, align);
+			svalue = (int)hvalue;
+			svalue = (signed char)svalue << 2;
+			relocation += svalue;
+                        relocation = (relocation >> 2) & 0xff;
+			hvalue = hvalue & 0xff00;
+			hvalue += relocation;
+	    		COPY_UNALIGNED_HWORD (hvalue, *hlocation, align);
+			break;
+		case R_M32R_26_PCREL_RELA:
+	  		relocation = (relocation - (Elf32_Addr) location);
+			if (relocation < -0x2000000 || 0x1fffffc < relocation)
+				{
+					printk(KERN_ERR "module %s: relocation overflow: %u\n",
+					me->name, relocation);
+					return -ENOEXEC;
+				}
+	    		COPY_UNALIGNED_WORD (*location, value, align);
+			if (value & 0xffffff)
+				{
+					/* RELA must has 0 at relocation field. */
+					printk(KERN_ERR "module %s: illegal relocation field: %u\n",
+					me->name, value);
+					return -ENOEXEC;
+				}
+                        relocation = (relocation >> 2) & 0xffffff;
+			value += relocation;
+	    		COPY_UNALIGNED_WORD (value, *location, align);
+			break;
+		default:
+			printk(KERN_ERR "module %s: Unknown relocation: %u\n",
+			       me->name, ELF32_R_TYPE(rel[i].r_info));
+			return -ENOEXEC;
+		}
+	}
+	return 0;
+}
+
+int apply_relocate(Elf32_Shdr *sechdrs,
+		       const char *strtab,
+		       unsigned int symindex,
+		       unsigned int relsec,
+		       struct module *me)
+{
+#if 0
+	printk(KERN_ERR "module %s: REL RELOCATION unsupported\n",
+	       me->name);
+	return -ENOEXEC;
+#endif
+	return 0;
+
+}
+
+int module_finalize(const Elf_Ehdr *hdr,
+		    const Elf_Shdr *sechdrs,
+		    struct module *me)
+{
+	return 0;
+}
+
+void module_arch_cleanup(struct module *mod)
+{
+}
diff -Nru a/arch/m32r/kernel/process.c b/arch/m32r/kernel/process.c
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/arch/m32r/kernel/process.c	2004-10-18 14:57:24 -07:00
@@ -0,0 +1,356 @@
+/*
+ *  linux/arch/m32r/kernel/process.c
+ *    orig : sh
+ *
+ *  Copyright (c) 2001, 2002  Hiroyuki Kondo, Hirokazu Takata,
+ *                            Hitoshi Yamamoto
+ *  Taken from sh version.
+ *    Copyright (C) 1995  Linus Torvalds
+ *    SuperH version:  Copyright (C) 1999, 2000  Niibe Yutaka & Kaz Kojima
+ */
+
+#undef DEBUG_PROCESS
+#ifdef DEBUG_PROCESS
+#define DPRINTK(fmt, args...)  printk("%s:%d:%s: " fmt, __FILE__, __LINE__, \
+  __FUNCTION__, ##args)
+#else
+#define DPRINTK(fmt, args...)
+#endif
+
+/*
+ * This file handles the architecture-dependent parts of process handling..
+ */
+
+#include <linux/fs.h>
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/ptrace.h>
+#include <linux/unistd.h>
+#include <linux/slab.h>
+#include <linux/hardirq.h>
+
+#include <asm/io.h>
+#include <asm/uaccess.h>
+#include <asm/mmu_context.h>
+#include <asm/elf.h>
+#include <asm/m32r.h>
+
+#include <linux/err.h>
+
+static int hlt_counter=0;
+
+/*
+ * Return saved PC of a blocked thread.
+ */
+unsigned long thread_saved_pc(struct task_struct *tsk)
+{
+	return tsk->thread.lr;
+}
+
+/*
+ * Powermanagement idle function, if any..
+ */
+void (*pm_idle)(void) = NULL;
+
+void disable_hlt(void)
+{
+	hlt_counter++;
+}
+
+EXPORT_SYMBOL(disable_hlt);
+
+void enable_hlt(void)
+{
+	hlt_counter--;
+}
+
+EXPORT_SYMBOL(enable_hlt);
+
+/*
+ * We use this is we don't have any better
+ * idle routine..
+ */
+void default_idle(void)
+{
+	/* M32R_FIXME: Please use "cpu_sleep" mode.  */
+	cpu_relax();
+}
+
+/*
+ * On SMP it's slightly faster (but much more power-consuming!)
+ * to poll the ->work.need_resched flag instead of waiting for the
+ * cross-CPU IPI to arrive. Use this option with caution.
+ */
+static void poll_idle (void)
+{
+	/* M32R_FIXME */
+	cpu_relax();
+}
+
+/*
+ * The idle thread. There's no useful work to be
+ * done, so just try to conserve power and have a
+ * low exit latency (ie sit in a loop waiting for
+ * somebody to say that they'd like to reschedule)
+ */
+void cpu_idle (void)
+{
+	/* endless idle loop with no priority at all */
+	while (1) {
+		while (!need_resched()) {
+			void (*idle)(void) = pm_idle;
+
+			if (!idle)
+				idle = default_idle;
+
+			idle();
+		}
+		schedule();
+	}
+}
+
+void machine_restart(char *__unused)
+{
+	printk("Please push reset button!\n");
+	while (1)
+		cpu_relax();
+}
+
+EXPORT_SYMBOL(machine_restart);
+
+void machine_halt(void)
+{
+	printk("Please push reset button!\n");
+	while (1)
+		cpu_relax();
+}
+
+EXPORT_SYMBOL(machine_halt);
+
+void machine_power_off(void)
+{
+	/* M32R_FIXME */
+}
+
+EXPORT_SYMBOL(machine_power_off);
+
+static int __init idle_setup (char *str)
+{
+	if (!strncmp(str, "poll", 4)) {
+		printk("using poll in idle threads.\n");
+		pm_idle = poll_idle;
+	} else if (!strncmp(str, "sleep", 4)) {
+		printk("using sleep in idle threads.\n");
+		pm_idle = default_idle;
+	}
+
+	return 1;
+}
+
+__setup("idle=", idle_setup);
+
+void show_regs(struct pt_regs * regs)
+{
+	printk("\n");
+	printk("BPC[%08lx]:PSW[%08lx]:LR [%08lx]:FP [%08lx]\n", \
+	  regs->bpc, regs->psw, regs->lr, regs->fp);
+	printk("BBPC[%08lx]:BBPSW[%08lx]:SPU[%08lx]:SPI[%08lx]\n", \
+	  regs->bbpc, regs->bbpsw, regs->spu, regs->spi);
+	printk("R0 [%08lx]:R1 [%08lx]:R2 [%08lx]:R3 [%08lx]\n", \
+	  regs->r0, regs->r1, regs->r2, regs->r3);
+	printk("R4 [%08lx]:R5 [%08lx]:R6 [%08lx]:R7 [%08lx]\n", \
+	  regs->r4, regs->r5, regs->r6, regs->r7);
+	printk("R8 [%08lx]:R9 [%08lx]:R10[%08lx]:R11[%08lx]\n", \
+	  regs->r8, regs->r9, regs->r10, regs->r11);
+	printk("R12[%08lx]\n", \
+	  regs->r12);
+
+#if defined(CONFIG_ISA_M32R2) && defined(CONFIG_ISA_DSP_LEVEL2)
+	printk("ACC0H[%08lx]:ACC0L[%08lx]\n", \
+	  regs->acc0h, regs->acc0l);
+	printk("ACC1H[%08lx]:ACC1L[%08lx]\n", \
+	  regs->acc1h, regs->acc1l);
+#elif defined(CONFIG_ISA_M32R2) || defined(CONFIG_ISA_M32R)
+	printk("ACCH[%08lx]:ACCL[%08lx]\n", \
+	  regs->acch, regs->accl);
+#else
+#error unknown isa configuration
+#endif
+}
+
+/*
+ * Create a kernel thread
+ */
+
+/*
+ * This is the mechanism for creating a new kernel thread.
+ *
+ * NOTE! Only a kernel-only process(ie the swapper or direct descendants
+ * who haven't done an "execve()") should use this: it will work within
+ * a system call from a "real" process, but the process memory space will
+ * not be free'd until both the parent and the child have exited.
+ */
+static void kernel_thread_helper(void *nouse, int (*fn)(void *), void *arg)
+{
+	fn(arg);
+	do_exit(-1);
+}
+
+int kernel_thread(int (*fn)(void *), void *arg, unsigned long flags)
+{
+	struct pt_regs regs;
+
+	memset(&regs, 0, sizeof (regs));
+	regs.r1 = (unsigned long)fn;
+	regs.r2 = (unsigned long)arg;
+
+	regs.bpc = (unsigned long)kernel_thread_helper;
+
+	regs.psw = M32R_PSW_BIE;
+
+	/* Ok, create the new process. */
+	return do_fork(flags | CLONE_VM | CLONE_UNTRACED, 0, &regs, 0, NULL,
+		NULL);
+}
+
+/*
+ * Free current thread data structures etc..
+ */
+void exit_thread(void)
+{
+	/* Nothing to do. */
+	DPRINTK("pid = %d\n", current->pid);
+}
+
+void flush_thread(void)
+{
+	DPRINTK("pid = %d\n", current->pid);
+	memset(&current->thread.debug_trap, 0, sizeof(struct debug_trap));
+}
+
+void release_thread(struct task_struct *dead_task)
+{
+	/* do nothing */
+	DPRINTK("pid = %d\n", dead_task->pid);
+}
+
+/* Fill in the fpu structure for a core dump.. */
+int dump_fpu(struct pt_regs *regs, elf_fpregset_t *fpu)
+{
+	return 0; /* Task didn't use the fpu at all. */
+}
+
+int copy_thread(int nr, unsigned long clone_flags, unsigned long spu,
+	unsigned long unused, struct task_struct *tsk, struct pt_regs *regs)
+{
+	struct pt_regs *childregs;
+	unsigned long sp = (unsigned long)tsk->thread_info + THREAD_SIZE;
+	extern void ret_from_fork(void);
+
+	tsk->set_child_tid = tsk->clear_child_tid = NULL;
+
+	/* Copy registers */
+	sp -= sizeof (struct pt_regs);
+	childregs = (struct pt_regs *)sp;
+	*childregs = *regs;
+
+	childregs->spu = spu;
+	childregs->r0 = 0;	/* Child gets zero as return value */
+	regs->r0 = tsk->pid;
+	tsk->thread.sp = (unsigned long)childregs;
+	tsk->thread.lr = (unsigned long)ret_from_fork;
+
+	return 0;
+}
+
+/*
+ * fill in the user structure for a core dump..
+ */
+void dump_thread(struct pt_regs * regs, struct user * dump)
+{
+	/* M32R_FIXME */
+}
+
+/*
+ * Capture the user space registers if the task is not running (in user space)
+ */
+int dump_task_regs(struct task_struct *tsk, elf_gregset_t *regs)
+{
+	/* M32R_FIXME */
+	return 1;
+}
+
+asmlinkage int sys_fork(unsigned long r0, unsigned long r1, unsigned long r2,
+	unsigned long r3, unsigned long r4, unsigned long r5, unsigned long r6,
+	struct pt_regs regs)
+{
+#ifdef CONFIG_MMU
+	return do_fork(SIGCHLD, regs.spu, &regs, 0, NULL, NULL);
+#else
+	return -EINVAL;
+#endif /* CONFIG_MMU */
+}
+
+asmlinkage int sys_clone(unsigned long clone_flags, unsigned long newsp,
+	unsigned long r2, unsigned long r3, unsigned long r4, unsigned long r5,
+	unsigned long r6, struct pt_regs regs)
+{
+	if (!newsp)
+		newsp = regs.spu;
+
+	return do_fork(clone_flags, newsp, &regs, 0, NULL, NULL);
+}
+
+/*
+ * This is trivial, and on the face of it looks like it
+ * could equally well be done in user mode.
+ *
+ * Not so, for quite unobvious reasons - register pressure.
+ * In user mode vfork() cannot have a stack frame, and if
+ * done by calling the "clone()" system call directly, you
+ * do not have enough call-clobbered registers to hold all
+ * the information you need.
+ */
+asmlinkage int sys_vfork(unsigned long r0, unsigned long r1, unsigned long r2,
+	unsigned long r3, unsigned long r4, unsigned long r5, unsigned long r6,
+	struct pt_regs regs)
+{
+	return do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, regs.spu, &regs, 0,
+			NULL, NULL);
+}
+
+/*
+ * sys_execve() executes a new program.
+ */
+asmlinkage int sys_execve(char __user *ufilename, char __user * __user *uargv, char __user * __user *uenvp,
+  unsigned long r3, unsigned long r4, unsigned long r5, unsigned long r6,
+  struct pt_regs regs)
+{
+	int error;
+	char *filename;
+
+	filename = getname(ufilename);
+	error = PTR_ERR(filename);
+	if (IS_ERR(filename))
+		goto out;
+
+	error = do_execve(filename, uargv, uenvp, &regs);
+	if (error == 0)
+		current->ptrace &= ~PT_DTRACE;
+	putname(filename);
+out:
+	return error;
+}
+
+/*
+ * These bracket the sleeping functions..
+ */
+#define first_sched	((unsigned long) scheduling_functions_start_here)
+#define last_sched	((unsigned long) scheduling_functions_end_here)
+
+unsigned long get_wchan(struct task_struct *p)
+{
+	/* M32R_FIXME */
+	return (0);
+}
+
diff -Nru a/arch/m32r/kernel/ptrace.c b/arch/m32r/kernel/ptrace.c
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/arch/m32r/kernel/ptrace.c	2004-10-18 14:57:24 -07:00
@@ -0,0 +1,858 @@
+/*
+ * linux/arch/m32r/kernel/ptrace.c
+ *
+ * Copyright (C) 2002  Hirokazu Takata, Takeo Takahashi
+ * Copyright (C) 2004  Hirokazu Takata <takata at linux-m32r.org>
+ *
+ * Original x86 implementation:
+ *	By Ross Biro 1/23/92
+ *	edited by Linus Torvalds
+ *
+ * Some code taken from sh version:
+ *   Copyright (C) 1999, 2000  Kaz Kojima & Niibe Yutaka
+ * Some code taken from arm version:
+ *   Copyright (C) 2000 Russell King
+ */
+
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/mm.h>
+#include <linux/smp.h>
+#include <linux/smp_lock.h>
+#include <linux/errno.h>
+#include <linux/ptrace.h>
+#include <linux/user.h>
+#include <linux/string.h>
+
+#include <asm/cacheflush.h>
+#include <asm/io.h>
+#include <asm/uaccess.h>
+#include <asm/pgtable.h>
+#include <asm/system.h>
+#include <asm/processor.h>
+#include <asm/mmu_context.h>
+
+/*
+ * Get the address of the live pt_regs for the specified task.
+ * These are saved onto the top kernel stack when the process
+ * is not running.
+ *
+ * Note: if a user thread is execve'd from kernel space, the
+ * kernel stack will not be empty on entry to the kernel, so
+ * ptracing these tasks will fail.
+ */
+static inline struct pt_regs *
+get_user_regs(struct task_struct *task)
+{
+        return (struct pt_regs *)
+                ((unsigned long)task->thread_info + THREAD_SIZE
+                 - sizeof(struct pt_regs));
+}
+
+/*
+ * This routine will get a word off of the process kernel stack.
+ */
+static inline unsigned long int
+get_stack_long(struct task_struct *task, int offset)
+{
+	unsigned long *stack;
+
+	stack = (unsigned long *)get_user_regs(task);
+
+	return stack[offset];
+}
+
+/*
+ * This routine will put a word on the process kernel stack.
+ */
+static inline int
+put_stack_long(struct task_struct *task, int offset, unsigned long data)
+{
+	unsigned long *stack;
+
+	stack = (unsigned long *)get_user_regs(task);
+	stack[offset] = data;
+
+	return 0;
+}
+
+static int reg_offset[] = {
+	PT_R0, PT_R1, PT_R2, PT_R3, PT_R4, PT_R5, PT_R6, PT_R7,
+	PT_R8, PT_R9, PT_R10, PT_R11, PT_R12, PT_FP, PT_LR, PT_SPU,
+};
+
+/*
+ * Read the word at offset "off" into the "struct user".  We
+ * actually access the pt_regs stored on the kernel stack.
+ */
+static int ptrace_read_user(struct task_struct *tsk, unsigned long off,
+			    unsigned long __user *data)
+{
+	unsigned long tmp;
+#ifndef NO_FPU
+	struct user * dummy = NULL;
+#endif
+
+	if ((off & 3) || (off < 0) || (off > sizeof(struct user) - 3))
+		return -EIO;
+
+	off >>= 2;
+	switch (off) {
+	case PT_EVB:
+		__asm__ __volatile__ (
+			"mvfc	%0, cr5 \n\t"
+	 		: "=r" (tmp)
+		);
+		break;
+	case PT_CBR: {
+			unsigned long psw;
+			psw = get_stack_long(tsk, PT_PSW);
+			tmp = ((psw >> 8) & 1);
+		}
+		break;
+	case PT_PSW: {
+			unsigned long psw, bbpsw;
+			psw = get_stack_long(tsk, PT_PSW);
+			bbpsw = get_stack_long(tsk, PT_BBPSW);
+			tmp = ((psw >> 8) & 0xff) | ((bbpsw & 0xff) << 8);
+		}
+		break;
+	case PT_PC:
+		tmp = get_stack_long(tsk, PT_BPC);
+		break;
+	case PT_BPC:
+		off = PT_BBPC;
+		/* fall through */
+	default:
+		if (off < (sizeof(struct pt_regs) >> 2))
+			tmp = get_stack_long(tsk, off);
+#ifndef NO_FPU
+		else if (off >= (long)(&dummy->fpu >> 2) &&
+			 off < (long)(&dummy->u_fpvalid >> 2)) {
+			if (!tsk->used_math) {
+				if (off == (long)(&dummy->fpu.fpscr >> 2))
+					tmp = FPSCR_INIT;
+				else
+					tmp = 0;
+			} else
+				tmp = ((long *)(&tsk->thread.fpu >> 2))
+					[off - (long)&dummy->fpu];
+		} else if (off == (long)(&dummy->u_fpvalid >> 2))
+			tmp = tsk->used_math;
+#endif /* not NO_FPU */
+		else
+			tmp = 0;
+	}
+
+	return put_user(tmp, data);
+}
+
+static int ptrace_write_user(struct task_struct *tsk, unsigned long off,
+			     unsigned long data)
+{
+	int ret = -EIO;
+#ifndef NO_FPU
+	struct user * dummy = NULL;
+#endif
+
+	if ((off & 3) || off < 0 ||
+	    off > sizeof(struct user) - 3)
+		return -EIO;
+
+	off >>= 2;
+	switch (off) {
+	case PT_EVB:
+	case PT_BPC:
+	case PT_SPI:
+		/* We don't allow to modify evb. */
+		ret = 0;
+		break;
+	case PT_PSW:
+	case PT_CBR: {
+			/* We allow to modify only cbr in psw */
+			unsigned long psw;
+			psw = get_stack_long(tsk, PT_PSW);
+			psw = (psw & ~0x100) | ((data & 1) << 8);
+			ret = put_stack_long(tsk, PT_PSW, psw);
+		}
+		break;
+	case PT_PC:
+		off = PT_BPC;
+		data &= ~1;
+		/* fall through */
+	default:
+		if (off < (sizeof(struct pt_regs) >> 2))
+			ret = put_stack_long(tsk, off, data);
+#ifndef NO_FPU
+		else if (off >= (long)(&dummy->fpu >> 2) &&
+			 off < (long)(&dummy->u_fpvalid >> 2)) {
+			tsk->used_math = 1;
+			((long *)&tsk->thread.fpu)
+				[off - (long)&dummy->fpu] = data;
+			ret = 0;
+		} else if (off == (long)(&dummy->u_fpvalid >> 2)) {
+			tsk->used_math = data ? 1 : 0;
+			ret = 0;
+		}
+#endif /* not NO_FPU */
+		break;
+	}
+
+	return ret;
+}
+
+/*
+ * Get all user integer registers.
+ */
+static int ptrace_getregs(struct task_struct *tsk, void __user *uregs)
+{
+	struct pt_regs *regs = get_user_regs(tsk);
+
+	return copy_to_user(uregs, regs, sizeof(struct pt_regs)) ? -EFAULT : 0;
+}
+
+/*
+ * Set all user integer registers.
+ */
+static int ptrace_setregs(struct task_struct *tsk, void __user *uregs)
+{
+	struct pt_regs newregs;
+	int ret;
+
+	ret = -EFAULT;
+	if (copy_from_user(&newregs, uregs, sizeof(struct pt_regs)) == 0) {
+		struct pt_regs *regs = get_user_regs(tsk);
+		*regs = newregs;
+		ret = 0;
+	}
+
+	return ret;
+}
+
+
+static inline int
+check_condition_bit(struct task_struct *child)
+{
+	return (int)((get_stack_long(child, PT_PSW) >> 8) & 1);
+}
+
+static int
+check_condition_src(unsigned long op, unsigned long regno1,
+		    unsigned long regno2, struct task_struct *child)
+{
+	unsigned long reg1, reg2;
+
+	reg2 = get_stack_long(child, reg_offset[regno2]);
+
+	switch (op) {
+	case 0x0: /* BEQ */
+		reg1 = get_stack_long(child, reg_offset[regno1]);
+		return reg1 == reg2;
+	case 0x1: /* BNE */
+		reg1 = get_stack_long(child, reg_offset[regno1]);
+		return reg1 != reg2;
+	case 0x8: /* BEQZ */
+		return reg2 == 0;
+	case 0x9: /* BNEZ */
+		return reg2 != 0;
+	case 0xa: /* BLTZ */
+		return (int)reg2 < 0;
+	case 0xb: /* BGEZ */
+		return (int)reg2 >= 0;
+	case 0xc: /* BLEZ */
+		return (int)reg2 <= 0;
+	case 0xd: /* BGTZ */
+		return (int)reg2 > 0;
+	default:
+		/* never reached */
+		return 0;
+	}
+}
+
+static void
+compute_next_pc_for_16bit_insn(unsigned long insn, unsigned long pc,
+			       unsigned long *next_pc,
+			       struct task_struct *child)
+{
+	unsigned long op, op2, op3;
+	unsigned long disp;
+	unsigned long regno;
+	int parallel = 0;
+
+	if (insn & 0x00008000)
+		parallel = 1;
+	if (pc & 3)
+		insn &= 0x7fff;	/* right slot */
+	else
+		insn >>= 16;	/* left slot */
+
+	op = (insn >> 12) & 0xf;
+	op2 = (insn >> 8) & 0xf;
+	op3 = (insn >> 4) & 0xf;
+
+	if (op == 0x7) {
+		switch (op2) {
+		case 0xd: /* BNC */
+		case 0x9: /* BNCL */
+			if (!check_condition_bit(child)) {
+				disp = (long)(insn << 24) >> 22;
+				*next_pc = (pc & ~0x3) + disp;
+				return;
+			}
+			break;
+		case 0x8: /* BCL */
+		case 0xc: /* BC */
+			if (check_condition_bit(child)) {
+				disp = (long)(insn << 24) >> 22;
+				*next_pc = (pc & ~0x3) + disp;
+				return;
+			}
+			break;
+		case 0xe: /* BL */
+		case 0xf: /* BRA */
+			disp = (long)(insn << 24) >> 22;
+			*next_pc = (pc & ~0x3) + disp;
+			return;
+			break;
+		}
+	} else if (op == 0x1) {
+		switch (op2) {
+		case 0x0:
+			if (op3 == 0xf) { /* TRAP */
+#if 1
+				/* pass through */
+#else
+ 				/* kernel space is not allowed as next_pc */
+				unsigned long evb;
+				unsigned long trapno;
+				trapno = insn & 0xf;
+				__asm__ __volatile__ (
+					"mvfc %0, cr5\n"
+		 			:"=r"(evb)
+		 			:
+				);
+				*next_pc = evb + (trapno << 2);
+				return;
+#endif
+			} else if (op3 == 0xd) { /* RTE */
+				*next_pc = get_stack_long(child, PT_BPC);
+				return;
+			}
+			break;
+		case 0xc: /* JC */
+			if (op3 == 0xc && check_condition_bit(child)) {
+				regno = insn & 0xf;
+				*next_pc = get_stack_long(child,
+							  reg_offset[regno]);
+				return;
+			}
+			break;
+		case 0xd: /* JNC */
+			if (op3 == 0xc && !check_condition_bit(child)) {
+				regno = insn & 0xf;
+				*next_pc = get_stack_long(child,
+							  reg_offset[regno]);
+				return;
+			}
+			break;
+		case 0xe: /* JL */
+		case 0xf: /* JMP */
+			if (op3 == 0xc) { /* JMP */
+				regno = insn & 0xf;
+				*next_pc = get_stack_long(child,
+							  reg_offset[regno]);
+				return;
+			}
+			break;
+		}
+	}
+	if (parallel)
+		*next_pc = pc + 4;
+	else
+		*next_pc = pc + 2;
+}
+
+static void
+compute_next_pc_for_32bit_insn(unsigned long insn, unsigned long pc,
+			       unsigned long *next_pc,
+			       struct task_struct *child)
+{
+	unsigned long op;
+	unsigned long op2;
+	unsigned long disp;
+	unsigned long regno1, regno2;
+
+	op = (insn >> 28) & 0xf;
+	if (op == 0xf) { 	/* branch 24-bit relative */
+		op2 = (insn >> 24) & 0xf;
+		switch (op2) {
+		case 0xd:	/* BNC */
+		case 0x9:	/* BNCL */
+			if (!check_condition_bit(child)) {
+				disp = (long)(insn << 8) >> 6;
+				*next_pc = (pc & ~0x3) + disp;
+				return;
+			}
+			break;
+		case 0x8:	/* BCL */
+		case 0xc:	/* BC */
+			if (check_condition_bit(child)) {
+				disp = (long)(insn << 8) >> 6;
+				*next_pc = (pc & ~0x3) + disp;
+				return;
+			}
+			break;
+		case 0xe:	/* BL */
+		case 0xf:	/* BRA */
+			disp = (long)(insn << 8) >> 6;
+			*next_pc = (pc & ~0x3) + disp;
+			return;
+		}
+	} else if (op == 0xb) { /* branch 16-bit relative */
+		op2 = (insn >> 20) & 0xf;
+		switch (op2) {
+		case 0x0: /* BEQ */
+		case 0x1: /* BNE */
+		case 0x8: /* BEQZ */
+		case 0x9: /* BNEZ */
+		case 0xa: /* BLTZ */
+		case 0xb: /* BGEZ */
+		case 0xc: /* BLEZ */
+		case 0xd: /* BGTZ */
+			regno1 = ((insn >> 24) & 0xf);
+			regno2 = ((insn >> 16) & 0xf);
+			if (check_condition_src(op2, regno1, regno2, child)) {
+				disp = (long)(insn << 16) >> 14;
+				*next_pc = (pc & ~0x3) + disp;
+				return;
+			}
+			break;
+		}
+	}
+	*next_pc = pc + 4;
+}
+
+static inline void
+compute_next_pc(unsigned long insn, unsigned long pc,
+		unsigned long *next_pc, struct task_struct *child)
+{
+	if (insn & 0x80000000)
+		compute_next_pc_for_32bit_insn(insn, pc, next_pc, child);
+	else
+		compute_next_pc_for_16bit_insn(insn, pc, next_pc, child);
+}
+
+static int
+register_debug_trap(struct task_struct *child, unsigned long next_pc,
+	unsigned long next_insn, unsigned long *code)
+{
+	struct debug_trap *p = &child->thread.debug_trap;
+	unsigned long addr = next_pc & ~3;
+
+	if (p->nr_trap != 0) {
+		printk("kernel BUG at %s %d: p->nr_trap = %d\n",
+					__FILE__, __LINE__, p->nr_trap);
+		return -1;
+	}
+	p->addr = addr;
+	p->insn = next_insn;
+	p->nr_trap++;
+	if (next_pc & 3) {
+		*code = (next_insn & 0xffff0000) | 0x10f1;
+		/* xxx --> TRAP1 */
+	} else {
+		if ((next_insn & 0x80000000) || (next_insn & 0x8000)) {
+			*code = 0x10f17000;
+			/* TRAP1 --> NOP */
+		} else {
+			*code = (next_insn & 0xffff) | 0x10f10000;
+			/* TRAP1 --> xxx */
+		}
+	}
+	return 0;
+}
+
+int withdraw_debug_trap_for_signal(struct task_struct *child)
+{
+	struct debug_trap *p = &child->thread.debug_trap;
+	int nr_trap = p->nr_trap;
+
+	if (nr_trap) {
+		access_process_vm(child, p->addr, &p->insn, sizeof(p->insn), 1);
+		p->nr_trap = 0;
+		p->addr = 0;
+		p->insn = 0;
+	}
+	return nr_trap;
+}
+
+static int
+unregister_debug_trap(struct task_struct *child, unsigned long addr,
+		      unsigned long *code)
+{
+	struct debug_trap *p = &child->thread.debug_trap;
+
+	if (p->nr_trap != 1 || p->addr != addr) {
+		/* The trap may be requested from debugger.
+		 * ptrace should do nothing in this case.
+		 */
+		return 0;
+	}
+	*code = p->insn;
+	p->insn = 0;
+	p->addr = 0;
+	p->nr_trap--;
+	return 1;
+}
+
+static void
+unregister_all_debug_traps(struct task_struct *child)
+{
+	struct debug_trap *p = &child->thread.debug_trap;
+
+	if (p->nr_trap) {
+		access_process_vm(child, p->addr, &p->insn, sizeof(p->insn), 1);
+		p->addr = 0;
+		p->insn = 0;
+		p->nr_trap = 0;
+	}
+}
+
+static inline void
+invalidate_cache(void)
+{
+#if defined(CONFIG_CHIP_M32700) || defined(CONFIG_CHIP_OPSP)
+
+	_flush_cache_copyback_all();
+
+#else	/* ! CONFIG_CHIP_M32700 */
+
+	/* Invalidate cache */
+	__asm__ __volatile__ (
+                "ldi    r0, #-1					\n\t"
+                "ldi    r1, #0					\n\t"
+                "stb    r1, @r0		; cache off		\n\t"
+                ";						\n\t"
+                "ldi    r0, #-2					\n\t"
+                "ldi    r1, #1					\n\t"
+                "stb    r1, @r0		; cache invalidate	\n\t"
+                ".fillinsn					\n"
+                "0:						\n\t"
+                "ldb    r1, @r0		; invalidate check	\n\t"
+                "bnez   r1, 0b					\n\t"
+                ";						\n\t"
+                "ldi    r0, #-1					\n\t"
+                "ldi    r1, #1					\n\t"
+                "stb    r1, @r0		; cache on		\n\t"
+		: : : "r0", "r1", "memory"
+	);
+	/* FIXME: copying-back d-cache and invalidating i-cache are needed.
+	 */
+#endif	/* CONFIG_CHIP_M32700 */
+}
+
+/* Embed a debug trap (TRAP1) code */
+static int
+embed_debug_trap(struct task_struct *child, unsigned long next_pc)
+{
+	unsigned long next_insn, code;
+	unsigned long addr = next_pc & ~3;
+
+	if (access_process_vm(child, addr, &next_insn, sizeof(next_insn), 0)
+	    != sizeof(next_insn)) {
+		return -1; /* error */
+	}
+
+	/* Set a trap code. */
+	if (register_debug_trap(child, next_pc, next_insn, &code)) {
+		return -1; /* error */
+	}
+	if (access_process_vm(child, addr, &code, sizeof(code), 1)
+	    != sizeof(code)) {
+		return -1; /* error */
+	}
+	return 0; /* success */
+}
+
+void
+embed_debug_trap_for_signal(struct task_struct *child)
+{
+	unsigned long next_pc;
+	unsigned long pc, insn;
+	int ret;
+
+	pc = get_stack_long(child, PT_BPC);
+	ret = access_process_vm(child, pc&~3, &insn, sizeof(insn), 0);
+	if (ret != sizeof(insn)) {
+		printk("kernel BUG at %s %d: access_process_vm returns %d\n",
+		       __FILE__, __LINE__, ret);
+		return;
+	}
+	compute_next_pc(insn, pc, &next_pc, child);
+	if (next_pc & 0x80000000) {
+		printk("kernel BUG at %s %d: next_pc = 0x%08x\n",
+		       __FILE__, __LINE__, (int)next_pc);
+		return;
+	}
+	if (embed_debug_trap(child, next_pc)) {
+		printk("kernel BUG at %s %d: embed_debug_trap error\n",
+		       __FILE__, __LINE__);
+		return;
+	}
+	invalidate_cache();
+}
+
+void
+withdraw_debug_trap(struct pt_regs *regs)
+{
+	unsigned long addr;
+	unsigned long code;
+
+ 	addr = (regs->bpc - 2) & ~3;
+	regs->bpc -= 2;
+	if (unregister_debug_trap(current, addr, &code)) {
+	    access_process_vm(current, addr, &code, sizeof(code), 1);
+	    invalidate_cache();
+	}
+}
+
+static void
+init_debug_traps(struct task_struct *child)
+{
+	struct debug_trap *p = &child->thread.debug_trap;
+	p->nr_trap = 0;
+	p->addr = 0;
+	p->insn = 0;
+}
+
+
+/*
+ * Called by kernel/ptrace.c when detaching..
+ *
+ * Make sure single step bits etc are not set.
+ */
+void ptrace_disable(struct task_struct *child)
+{
+	/* nothing to do.. */
+}
+
+static int
+do_ptrace(long request, struct task_struct *child, long addr, long data)
+{
+	unsigned long tmp;
+	int ret;
+
+	switch (request) {
+	/*
+	 * read word at location "addr" in the child process.
+	 */
+	case PTRACE_PEEKTEXT:
+	case PTRACE_PEEKDATA:
+		ret = access_process_vm(child, addr, &tmp, sizeof(tmp), 0);
+		if (ret == sizeof(tmp))
+			ret = put_user(tmp,(unsigned long __user *) data);
+		else
+			ret = -EIO;
+		break;
+
+	/*
+	 * read the word at location addr in the USER area.
+	 */
+	case PTRACE_PEEKUSR:
+		ret = ptrace_read_user(child, addr,
+				       (unsigned long __user *)data);
+		break;
+
+	/*
+	 * write the word at location addr.
+	 */
+	case PTRACE_POKETEXT:
+	case PTRACE_POKEDATA:
+		ret = access_process_vm(child, addr, &data, sizeof(data), 1);
+		if (ret == sizeof(data)) {
+			ret = 0;
+			if (request == PTRACE_POKETEXT) {
+				invalidate_cache();
+			}
+		} else {
+			ret = -EIO;
+		}
+		break;
+
+	/*
+	 * write the word at location addr in the USER area.
+	 */
+	case PTRACE_POKEUSR:
+		ret = ptrace_write_user(child, addr, data);
+		break;
+
+	/*
+	 * continue/restart and stop at next (return from) syscall
+	 */
+	case PTRACE_SYSCALL:
+	case PTRACE_CONT:
+		ret = -EIO;
+		if ((unsigned long) data > _NSIG)
+			break;
+		if (request == PTRACE_SYSCALL)
+			set_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
+		else
+			clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
+		child->exit_code = data;
+		wake_up_process(child);
+		ret = 0;
+		break;
+
+	/*
+	 * make the child exit.  Best I can do is send it a sigkill.
+	 * perhaps it should be put in the status that it wants to
+	 * exit.
+	 */
+	case PTRACE_KILL: {
+		ret = 0;
+		unregister_all_debug_traps(child);
+		invalidate_cache();
+		if (child->state == TASK_ZOMBIE)	/* already dead */
+			break;
+		child->exit_code = SIGKILL;
+		wake_up_process(child);
+		break;
+	}
+
+	/*
+	 * execute single instruction.
+	 */
+	case PTRACE_SINGLESTEP: {
+		unsigned long next_pc;
+		unsigned long pc, insn;
+
+		ret = -EIO;
+		if ((unsigned long) data > _NSIG)
+			break;
+		clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
+		if ((child->ptrace & PT_DTRACE) == 0) {
+			/* Spurious delayed TF traps may occur */
+			child->ptrace |= PT_DTRACE;
+		}
+
+		/* Compute next pc.  */
+		pc = get_stack_long(child, PT_BPC);
+
+		if (access_process_vm(child, pc&~3, &insn, sizeof(insn), 0)
+		    != sizeof(insn))
+			break;
+
+		compute_next_pc(insn, pc, &next_pc, child);
+		if (next_pc & 0x80000000)
+			break;
+
+		if (embed_debug_trap(child, next_pc))
+			break;
+
+		invalidate_cache();
+		child->exit_code = data;
+
+		/* give it a chance to run. */
+		wake_up_process(child);
+		ret = 0;
+		break;
+	}
+
+	/*
+	 * detach a process that was attached.
+	 */
+	case PTRACE_DETACH:
+		ret = 0;
+		ret = ptrace_detach(child, data);
+		break;
+
+	case PTRACE_GETREGS:
+		ret = ptrace_getregs(child, (void __user *)data);
+		break;
+
+	case PTRACE_SETREGS:
+		ret = ptrace_setregs(child, (void __user *)data);
+		break;
+
+	default:
+		ret = ptrace_request(child, request, addr, data);
+		break;
+	}
+
+	return ret;
+}
+
+asmlinkage int sys_ptrace(long request, long pid, long addr, long data)
+{
+	struct task_struct *child;
+	int ret;
+
+	lock_kernel();
+	ret = -EPERM;
+	if (request == PTRACE_TRACEME) {
+		/* are we already being traced? */
+		if (current->ptrace & PT_PTRACED)
+			goto out;
+		/* set the ptrace bit in the process flags. */
+		current->ptrace |= PT_PTRACED;
+		ret = 0;
+		goto out;
+	}
+	ret = -ESRCH;
+	read_lock(&tasklist_lock);
+	child = find_task_by_pid(pid);
+	if (child)
+		get_task_struct(child);
+	read_unlock(&tasklist_lock);
+	if (!child)
+		goto out;
+
+	ret = -EPERM;
+	if (pid == 1)		/* you may not mess with init */
+		goto out;
+
+	if (request == PTRACE_ATTACH) {
+		ret = ptrace_attach(child);
+		if (ret == 0)
+			init_debug_traps(child);
+		goto out_tsk;
+	}
+
+	ret = ptrace_check_attach(child, request == PTRACE_KILL);
+	if (ret == 0)
+		ret = do_ptrace(request, child, addr, data);
+
+out_tsk:
+	put_task_struct(child);
+out:
+	unlock_kernel();
+
+	return ret;
+}
+
+/* notification of system call entry/exit
+ * - triggered by current->work.syscall_trace
+ */
+void do_syscall_trace(void)
+{
+	if (!test_thread_flag(TIF_SYSCALL_TRACE))
+		return;
+	if (!(current->ptrace & PT_PTRACED))
+		return;
+	/* the 0x80 provides a way for the tracing parent to distinguish
+	   between a syscall stop and SIGTRAP delivery */
+	ptrace_notify(SIGTRAP | ((current->ptrace & PT_TRACESYSGOOD)
+				 ? 0x80 : 0));
+
+	/*
+	 * this isn't the same as continuing with a signal, but it will do
+	 * for normal use.  strace only continues with a signal if the
+	 * stopping signal is not SIGTRAP.  -brl
+	 */
+	if (current->exit_code) {
+		send_sig(current->exit_code, current, 1);
+		current->exit_code = 0;
+	}
+}
+
diff -Nru a/arch/m32r/kernel/semaphore.c b/arch/m32r/kernel/semaphore.c
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/arch/m32r/kernel/semaphore.c	2004-10-18 14:57:23 -07:00
@@ -0,0 +1,186 @@
+/*
+ *  linux/arch/m32r/semaphore.c
+ *    orig : i386 2.6.4
+ *
+ *  M32R semaphore implementation.
+ *
+ *	Copyright (c) 2002 - 2004 Hitoshi Yamamoto
+ */
+
+/*
+ * i386 semaphore implementation.
+ *
+ * (C) Copyright 1999 Linus Torvalds
+ *
+ * Portions Copyright 1999 Red Hat, 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.
+ *
+ * rw semaphores implemented November 1999 by Benjamin LaHaise <bcrl@redhat.com>
+ */
+#include <linux/config.h>
+#include <linux/sched.h>
+#include <linux/err.h>
+#include <linux/init.h>
+#include <asm/semaphore.h>
+
+/*
+ * Semaphores are implemented using a two-way counter:
+ * The "count" variable is decremented for each process
+ * that tries to acquire the semaphore, while the "sleeping"
+ * variable is a count of such acquires.
+ *
+ * Notably, the inline "up()" and "down()" functions can
+ * efficiently test if they need to do any extra work (up
+ * needs to do something only if count was negative before
+ * the increment operation.
+ *
+ * "sleeping" and the contention routine ordering is protected
+ * by the spinlock in the semaphore's waitqueue head.
+ *
+ * Note that these functions are only called when there is
+ * contention on the lock, and as such all this is the
+ * "non-critical" part of the whole semaphore business. The
+ * critical part is the inline stuff in <asm/semaphore.h>
+ * where we want to avoid any extra jumps and calls.
+ */
+
+/*
+ * Logic:
+ *  - only on a boundary condition do we need to care. When we go
+ *    from a negative count to a non-negative, we wake people up.
+ *  - when we go from a non-negative count to a negative do we
+ *    (a) synchronize with the "sleeper" count and (b) make sure
+ *    that we're on the wakeup list before we synchronize so that
+ *    we cannot lose wakeup events.
+ */
+
+asmlinkage void __up(struct semaphore *sem)
+{
+	wake_up(&sem->wait);
+}
+
+asmlinkage void __sched __down(struct semaphore * sem)
+{
+	struct task_struct *tsk = current;
+	DECLARE_WAITQUEUE(wait, tsk);
+	unsigned long flags;
+
+	tsk->state = TASK_UNINTERRUPTIBLE;
+	spin_lock_irqsave(&sem->wait.lock, flags);
+	add_wait_queue_exclusive_locked(&sem->wait, &wait);
+
+	sem->sleepers++;
+	for (;;) {
+		int sleepers = sem->sleepers;
+
+		/*
+		 * Add "everybody else" into it. They aren't
+		 * playing, because we own the spinlock in
+		 * the wait_queue_head.
+		 */
+		if (!atomic_add_negative(sleepers - 1, &sem->count)) {
+			sem->sleepers = 0;
+			break;
+		}
+		sem->sleepers = 1;	/* us - see -1 above */
+		spin_unlock_irqrestore(&sem->wait.lock, flags);
+
+		schedule();
+
+		spin_lock_irqsave(&sem->wait.lock, flags);
+		tsk->state = TASK_UNINTERRUPTIBLE;
+	}
+	remove_wait_queue_locked(&sem->wait, &wait);
+	wake_up_locked(&sem->wait);
+	spin_unlock_irqrestore(&sem->wait.lock, flags);
+	tsk->state = TASK_RUNNING;
+}
+
+asmlinkage int __sched __down_interruptible(struct semaphore * sem)
+{
+	int retval = 0;
+	struct task_struct *tsk = current;
+	DECLARE_WAITQUEUE(wait, tsk);
+	unsigned long flags;
+
+	tsk->state = TASK_INTERRUPTIBLE;
+	spin_lock_irqsave(&sem->wait.lock, flags);
+	add_wait_queue_exclusive_locked(&sem->wait, &wait);
+
+	sem->sleepers++;
+	for (;;) {
+		int sleepers = sem->sleepers;
+
+		/*
+		 * With signals pending, this turns into
+		 * the trylock failure case - we won't be
+		 * sleeping, and we* can't get the lock as
+		 * it has contention. Just correct the count
+		 * and exit.
+		 */
+		if (signal_pending(current)) {
+			retval = -EINTR;
+			sem->sleepers = 0;
+			atomic_add(sleepers, &sem->count);
+			break;
+		}
+
+		/*
+		 * Add "everybody else" into it. They aren't
+		 * playing, because we own the spinlock in
+		 * wait_queue_head. The "-1" is because we're
+		 * still hoping to get the semaphore.
+		 */
+		if (!atomic_add_negative(sleepers - 1, &sem->count)) {
+			sem->sleepers = 0;
+			break;
+		}
+		sem->sleepers = 1;	/* us - see -1 above */
+		spin_unlock_irqrestore(&sem->wait.lock, flags);
+
+		schedule();
+
+		spin_lock_irqsave(&sem->wait.lock, flags);
+		tsk->state = TASK_INTERRUPTIBLE;
+	}
+	remove_wait_queue_locked(&sem->wait, &wait);
+	wake_up_locked(&sem->wait);
+	spin_unlock_irqrestore(&sem->wait.lock, flags);
+
+	tsk->state = TASK_RUNNING;
+	return retval;
+}
+
+/*
+ * Trylock failed - make sure we correct for
+ * having decremented the count.
+ *
+ * We could have done the trylock with a
+ * single "cmpxchg" without failure cases,
+ * but then it wouldn't work on a 386.
+ */
+asmlinkage int __down_trylock(struct semaphore * sem)
+{
+	int sleepers;
+	unsigned long flags;
+
+	spin_lock_irqsave(&sem->wait.lock, flags);
+	sleepers = sem->sleepers + 1;
+	sem->sleepers = 0;
+
+	/*
+	 * Add "everybody else" and us into it. They aren't
+	 * playing, because we own the spinlock in the
+	 * wait_queue_head.
+	 */
+	if (!atomic_add_negative(sleepers, &sem->count)) {
+		wake_up_locked(&sem->wait);
+	}
+
+	spin_unlock_irqrestore(&sem->wait.lock, flags);
+	return 1;
+}
diff -Nru a/arch/m32r/kernel/setup.c b/arch/m32r/kernel/setup.c
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/arch/m32r/kernel/setup.c	2004-10-18 14:57:23 -07:00
@@ -0,0 +1,403 @@
+/*
+ *  linux/arch/m32r/kernel/setup.c
+ *
+ *  Setup routines for Renesas M32R
+ *
+ *  Copyright (c) 2001, 2002  Hiroyuki Kondo, Hirokazu Takata,
+ *                            Hitoshi Yamamoto
+ */
+
+/* $Id$ */
+
+#include <linux/config.h>
+#include <linux/init.h>
+#include <linux/stddef.h>
+#include <linux/fs.h>
+#include <linux/sched.h>
+#include <linux/ioport.h>
+#include <linux/mm.h>
+#include <linux/bootmem.h>
+#include <linux/console.h>
+#include <linux/initrd.h>
+#include <linux/major.h>
+#include <linux/root_dev.h>
+#include <linux/seq_file.h>
+#include <linux/timex.h>
+#include <linux/tty.h>
+#include <asm/processor.h>
+#include <asm/pgtable.h>
+#include <asm/io.h>
+#include <asm/mmu_context.h>
+#include <asm/m32r.h>
+#include <asm/setup.h>
+#include <asm/sections.h>
+
+#ifdef CONFIG_MMU
+extern void init_mmu(void);
+#endif
+
+#if defined(CONFIG_BLK_DEV_IDE) || defined(CONFIG_BLK_DEV_HD)	\
+	|| defined(CONFIG_BLK_DEV_IDE_MODULE)			\
+	|| defined(CONFIG_BLK_DEV_HD_MODULE)
+struct drive_info_struct { char dummy[32]; } drive_info;
+#endif
+
+extern char _end[];
+
+/*
+ * Machine setup..
+ */
+struct cpuinfo_m32r boot_cpu_data;
+
+#ifdef CONFIG_BLK_DEV_RAM
+extern int rd_doload;	/* 1 = load ramdisk, 0 = don't load */
+extern int rd_prompt;	/* 1 = prompt for ramdisk, 0 = don't prompt */
+extern int rd_image_start;  /* starting block # of image */
+#endif
+
+#if defined(CONFIG_VGA_CONSOLE)
+struct screen_info screen_info = {
+	.orig_video_lines      = 25,
+	.orig_video_cols       = 80,
+	.orig_video_mode       = 0,
+	.orig_video_ega_bx     = 0,
+	.orig_video_isVGA      = 1,
+	.orig_video_points     = 8
+};
+#endif
+
+extern int root_mountflags;
+
+static char command_line[COMMAND_LINE_SIZE];
+
+static struct resource data_resource = {
+	.name   = "Kernel data",
+	.start  = 0,
+	.end    = 0,
+	.flags  = IORESOURCE_BUSY | IORESOURCE_MEM
+};
+
+static struct resource code_resource = {
+	.name   = "Kernel code",
+	.start  = 0,
+	.end    = 0,
+	.flags  = IORESOURCE_BUSY | IORESOURCE_MEM
+};
+
+unsigned long memory_start;
+unsigned long memory_end;
+
+void __init setup_arch(char **);
+int get_cpuinfo(char *);
+
+static __inline__ void parse_mem_cmdline(char ** cmdline_p)
+{
+	char c = ' ';
+	char *to = command_line;
+	char *from = COMMAND_LINE;
+	int len = 0;
+	int usermem = 0;
+
+	/* Save unparsed command line copy for /proc/cmdline */
+	memcpy(saved_command_line, COMMAND_LINE, COMMAND_LINE_SIZE);
+	saved_command_line[COMMAND_LINE_SIZE-1] = '\0';
+
+	memory_start = (unsigned long)CONFIG_MEMORY_START+PAGE_OFFSET;
+	memory_end = memory_start+(unsigned long)CONFIG_MEMORY_SIZE;
+
+	for ( ; ; ) {
+		if (c == ' ' && !memcmp(from, "mem=", 4)) {
+			if (to != command_line)
+				to--;
+
+			{
+				unsigned long mem_size;
+
+				usermem = 1;
+				mem_size = memparse(from+4, &from);
+				memory_end = memory_start + mem_size;
+			}
+		}
+		c = *(from++);
+		if (!c)
+			break;
+
+		if (COMMAND_LINE_SIZE <= ++len)
+			break;
+
+		*(to++) = c;
+	}
+	*to = '\0';
+	*cmdline_p = command_line;
+	if (usermem)
+		printk(KERN_INFO "user-defined physical RAM map:\n");
+}
+
+#ifndef CONFIG_DISCONTIGMEM
+static unsigned long __init setup_memory(void)
+{
+	unsigned long start_pfn, max_low_pfn, bootmap_size;
+
+	start_pfn = PFN_UP( __pa(_end) );
+	max_low_pfn = PFN_DOWN( __pa(memory_end) );
+
+	/*
+	 * Initialize the boot-time allocator (with low memory only):
+	 */
+	bootmap_size = init_bootmem_node(NODE_DATA(0), start_pfn,
+		CONFIG_MEMORY_START>>PAGE_SHIFT, max_low_pfn);
+
+	/*
+	 * Register fully available low RAM pages with the bootmem allocator.
+	 */
+	{
+		unsigned long curr_pfn;
+		unsigned long last_pfn;
+		unsigned long pages;
+
+		/*
+		 * We are rounding up the start address of usable memory:
+		 */
+		curr_pfn = PFN_UP(__pa(memory_start));
+
+		/*
+		 * ... and at the end of the usable range downwards:
+		 */
+		last_pfn = PFN_DOWN(__pa(memory_end));
+
+		if (last_pfn > max_low_pfn)
+			last_pfn = max_low_pfn;
+
+		pages = last_pfn - curr_pfn;
+		free_bootmem(PFN_PHYS(curr_pfn), PFN_PHYS(pages));
+	}
+
+	/*
+	 * Reserve the kernel text and
+	 * Reserve the bootmem bitmap. We do this in two steps (first step
+	 * was init_bootmem()), because this catches the (definitely buggy)
+	 * case of us accidentally initializing the bootmem allocator with
+	 * an invalid RAM area.
+	 */
+	reserve_bootmem(CONFIG_MEMORY_START + PAGE_SIZE,
+		(PFN_PHYS(start_pfn) + bootmap_size + PAGE_SIZE - 1)
+		- CONFIG_MEMORY_START);
+
+	/*
+	 * reserve physical page 0 - it's a special BIOS page on many boxes,
+	 * enabling clean reboots, SMP operation, laptop functions.
+	 */
+	reserve_bootmem(CONFIG_MEMORY_START, PAGE_SIZE);
+
+	/*
+	 * reserve memory hole
+	 */
+#ifdef CONFIG_MEMHOLE
+	reserve_bootmem(CONFIG_MEMHOLE_START, CONFIG_MEMHOLE_SIZE);
+#endif
+
+#ifdef CONFIG_BLK_DEV_INITRD
+	if (LOADER_TYPE && INITRD_START) {
+		if (INITRD_START + INITRD_SIZE <= (max_low_pfn << PAGE_SHIFT)) {
+			reserve_bootmem(INITRD_START, INITRD_SIZE);
+			initrd_start = INITRD_START ?
+				INITRD_START + PAGE_OFFSET : 0;
+
+			initrd_end = initrd_start + INITRD_SIZE;
+			printk("initrd:start[%08lx],size[%08lx]\n",
+				initrd_start, INITRD_SIZE);
+		} else {
+			printk("initrd extends beyond end of memory "
+				"(0x%08lx > 0x%08lx)\ndisabling initrd\n",
+				INITRD_START + INITRD_SIZE,
+				max_low_pfn << PAGE_SHIFT);
+
+			initrd_start = 0;
+		}
+	}
+#endif
+
+	return max_low_pfn;
+}
+#else	/* CONFIG_DISCONTIGMEM */
+extern unsigned long setup_memory(void);
+#endif	/* CONFIG_DISCONTIGMEM */
+
+#define M32R_PCC_PCATCR	0x00ef7014	/* will move to m32r.h */
+
+void __init setup_arch(char **cmdline_p)
+{
+	ROOT_DEV = old_decode_dev(ORIG_ROOT_DEV);
+
+	boot_cpu_data.cpu_clock = M32R_CPUCLK;
+	boot_cpu_data.bus_clock = M32R_BUSCLK;
+	boot_cpu_data.timer_divide = M32R_TIMER_DIVIDE;
+
+#ifdef CONFIG_BLK_DEV_RAM
+	rd_image_start = RAMDISK_FLAGS & RAMDISK_IMAGE_START_MASK;
+	rd_prompt = ((RAMDISK_FLAGS & RAMDISK_PROMPT_FLAG) != 0);
+	rd_doload = ((RAMDISK_FLAGS & RAMDISK_LOAD_FLAG) != 0);
+#endif
+
+	if (!MOUNT_ROOT_RDONLY)
+		root_mountflags &= ~MS_RDONLY;
+
+#ifdef CONFIG_VT
+#if defined(CONFIG_VGA_CONSOLE)
+	conswitchp = &vga_con;
+#elif defined(CONFIG_DUMMY_CONSOLE)
+	conswitchp = &dummy_con;
+#endif
+#endif
+
+#ifdef CONFIG_DISCONTIGMEM
+	numnodes = 2;
+#endif	/* CONFIG_DISCONTIGMEM */
+
+	init_mm.start_code = (unsigned long) _text;
+	init_mm.end_code = (unsigned long) _etext;
+	init_mm.end_data = (unsigned long) _edata;
+	init_mm.brk = (unsigned long) _end;
+
+	code_resource.start = virt_to_phys(_text);
+	code_resource.end = virt_to_phys(_etext)-1;
+	data_resource.start = virt_to_phys(_etext);
+	data_resource.end = virt_to_phys(_edata)-1;
+
+	parse_mem_cmdline(cmdline_p);
+
+	setup_memory();
+
+	paging_init();
+}
+
+#ifdef CONFIG_PROC_FS
+/*
+ *	Get CPU information for use by the procfs.
+ */
+static int show_cpuinfo(struct seq_file *m, void *v)
+{
+	struct cpuinfo_m32r *c = v;
+	unsigned long cpu = c - cpu_data;
+
+#ifdef CONFIG_SMP
+	if (!cpu_online(cpu))
+		return 0;
+#endif  /* CONFIG_SMP */
+
+	seq_printf(m, "processor\t: %ld\n", cpu);
+
+#ifdef CONFIG_CHIP_VDEC2
+	seq_printf(m, "cpu family\t: VDEC2\n"
+		"cache size\t: Unknown\n");
+#elif  CONFIG_CHIP_M32700
+	seq_printf(m,"cpu family\t: M32700\n"
+		"cache size\t: I-8KB/D-8KB\n");
+#elif  CONFIG_CHIP_M32102
+	seq_printf(m,"cpu family\t: M32102\n"
+		"cache size\t: I-8KB\n");
+#elif  CONFIG_CHIP_OPSP
+	seq_printf(m,"cpu family\t: OPSP\n"
+		"cache size\t: I-8KB/D-8KB\n");
+#elif  CONFIG_CHIP_MP
+	seq_printf(m, "cpu family\t: M32R-MP\n"
+		"cache size\t: I-xxKB/D-xxKB\n");
+#else
+	seq_printf(m, "cpu family\t: Unknown\n");
+#endif
+	seq_printf(m, "bogomips\t: %lu.%02lu\n",
+		c->loops_per_jiffy/(500000/HZ),
+		(c->loops_per_jiffy/(5000/HZ)) % 100);
+#ifdef CONFIG_PLAT_MAPPI
+	seq_printf(m, "Machine\t\t: Mappi Evaluation board\n");
+#elif CONFIG_PLAT_MAPPI2
+	seq_printf(m, "Machine\t\t: Mappi-II Evaluation board\n");
+#elif  CONFIG_PLAT_M32700UT
+	seq_printf(m, "Machine\t\t: M32700UT Evaluation board\n");
+#elif  CONFIG_PLAT_OPSPUT
+	seq_printf(m, "Machine\t\t: OPSPUT Evaluation board\n");
+#elif  CONFIG_PLAT_USRV
+	seq_printf(m, "Machine\t\t: uServer\n");
+#elif  CONFIG_PLAT_OAKS32R
+	seq_printf(m, "Machine\t\t: OAKS32R\n");
+#else
+	seq_printf(m, "Machine\t\t: Unknown\n");
+#endif
+
+#define PRINT_CLOCK(name, value)				\
+	seq_printf(m, name " clock\t: %d.%02dMHz\n",		\
+		((value) / 1000000), ((value) % 1000000)/10000)
+
+	PRINT_CLOCK("CPU", (int)c->cpu_clock);
+	PRINT_CLOCK("Bus", (int)c->bus_clock);
+
+	seq_printf(m, "\n");
+
+	return 0;
+}
+
+static void *c_start(struct seq_file *m, loff_t *pos)
+{
+	return *pos < NR_CPUS ? cpu_data + *pos : NULL;
+}
+
+static void *c_next(struct seq_file *m, void *v, loff_t *pos)
+{
+	++*pos;
+	return c_start(m, pos);
+}
+
+static void c_stop(struct seq_file *m, void *v)
+{
+}
+
+struct seq_operations cpuinfo_op = {
+	start:	c_start,
+	next:	c_next,
+	stop:	c_stop,
+	show:	show_cpuinfo,
+};
+#endif  /* CONFIG_PROC_FS */
+
+unsigned long cpu_initialized __initdata = 0;
+
+/*
+ * cpu_init() initializes state that is per-CPU. Some data is already
+ * initialized (naturally) in the bootstrap process.
+ * We reload them nevertheless, this function acts as a
+ * 'CPU state barrier', nothing should get across.
+ */
+#if defined(CONFIG_CHIP_VDEC2) || defined(CONFIG_CHIP_XNUX2)	\
+	|| defined(CONFIG_CHIP_M32700) || defined(CONFIG_CHIP_M32102) \
+	|| defined(CONFIG_CHIP_OPSP)
+void __init cpu_init (void)
+{
+	int cpu_id = smp_processor_id();
+
+	if (test_and_set_bit(cpu_id, &cpu_initialized)) {
+		printk(KERN_WARNING "CPU#%d already initialized!\n", cpu_id);
+		for ( ; ; )
+			local_irq_enable();
+	}
+	printk(KERN_INFO "Initializing CPU#%d\n", cpu_id);
+
+	/* Set up and load the per-CPU TSS and LDT */
+	atomic_inc(&init_mm.mm_count);
+	current->active_mm = &init_mm;
+	if (current->mm)
+		BUG();
+
+	/* Force FPU initialization */
+	current_thread_info()->status = 0;
+	current->used_math = 0;
+
+#ifdef CONFIG_MMU
+	/* Set up MMU */
+	init_mmu();
+#endif
+
+	/* Set up ICUIMASK */
+	outl(0x00070000, M32R_ICU_IMASK_PORTL);   /* imask=111 */
+}
+#endif  /* defined(CONFIG_CHIP_VDEC2) ... */
+
diff -Nru a/arch/m32r/kernel/setup_m32700ut.c b/arch/m32r/kernel/setup_m32700ut.c
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/arch/m32r/kernel/setup_m32700ut.c	2004-10-18 14:57:24 -07:00
@@ -0,0 +1,478 @@
+/*
+ *  linux/arch/m32r/kernel/setup_m32700ut.c
+ *
+ *  Setup routines for Renesas M32700UT Board
+ *
+ *  Copyright (c) 2002 	Hiroyuki Kondo, Hirokazu Takata,
+ *                      Hitoshi Yamamoto, Takeo Takahashi
+ *
+ *  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.
+ */
+
+#include <linux/config.h>
+#include <linux/irq.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/device.h>
+
+#include <asm/system.h>
+#include <asm/m32r.h>
+#include <asm/io.h>
+
+/*
+ * M32700 Interrupt Control Unit (Level 1)
+ */
+#define irq2port(x) (M32R_ICU_CR1_PORTL + ((x - 1) * sizeof(unsigned long)))
+
+#ifndef CONFIG_SMP
+typedef struct {
+	unsigned long icucr;  /* ICU Control Register */
+} icu_data_t;
+#endif /* CONFIG_SMP */
+
+static icu_data_t icu_data[M32700UT_NUM_CPU_IRQ];
+
+static void disable_m32700ut_irq(unsigned int irq)
+{
+	unsigned long port, data;
+
+	port = irq2port(irq);
+	data = icu_data[irq].icucr|M32R_ICUCR_ILEVEL7;
+	outl(data, port);
+}
+
+static void enable_m32700ut_irq(unsigned int irq)
+{
+	unsigned long port, data;
+
+	port = irq2port(irq);
+	data = icu_data[irq].icucr|M32R_ICUCR_IEN|M32R_ICUCR_ILEVEL6;
+	outl(data, port);
+}
+
+static void mask_and_ack_m32700ut(unsigned int irq)
+{
+	disable_m32700ut_irq(irq);
+}
+
+static void end_m32700ut_irq(unsigned int irq)
+{
+	enable_m32700ut_irq(irq);
+}
+
+static unsigned int startup_m32700ut_irq(unsigned int irq)
+{
+	enable_m32700ut_irq(irq);
+	return (0);
+}
+
+static void shutdown_m32700ut_irq(unsigned int irq)
+{
+	unsigned long port;
+
+	port = irq2port(irq);
+	outl(M32R_ICUCR_ILEVEL7, port);
+}
+
+static struct hw_interrupt_type m32700ut_irq_type =
+{
+	"M32700UT-IRQ",
+	startup_m32700ut_irq,
+	shutdown_m32700ut_irq,
+	enable_m32700ut_irq,
+	disable_m32700ut_irq,
+	mask_and_ack_m32700ut,
+	end_m32700ut_irq
+};
+
+/*
+ * Interrupt Control Unit of PLD on M32700UT (Level 2)
+ */
+#define irq2pldirq(x)		((x) - M32700UT_PLD_IRQ_BASE)
+#define pldirq2port(x)		(unsigned long)((int)PLD_ICUCR1 + \
+				 (((x) - 1) * sizeof(unsigned short)))
+
+typedef struct {
+	unsigned short icucr;  /* ICU Control Register */
+} pld_icu_data_t;
+
+static pld_icu_data_t pld_icu_data[M32700UT_NUM_PLD_IRQ];
+
+static void disable_m32700ut_pld_irq(unsigned int irq)
+{
+	unsigned long port, data;
+	unsigned int pldirq;
+
+	pldirq = irq2pldirq(irq);
+//	disable_m32700ut_irq(M32R_IRQ_INT1);
+	port = pldirq2port(pldirq);
+	data = pld_icu_data[pldirq].icucr|PLD_ICUCR_ILEVEL7;
+	outw(data, port);
+}
+
+static void enable_m32700ut_pld_irq(unsigned int irq)
+{
+	unsigned long port, data;
+	unsigned int pldirq;
+
+	pldirq = irq2pldirq(irq);
+//	enable_m32700ut_irq(M32R_IRQ_INT1);
+	port = pldirq2port(pldirq);
+	data = pld_icu_data[pldirq].icucr|PLD_ICUCR_IEN|PLD_ICUCR_ILEVEL6;
+	outw(data, port);
+}
+
+static void mask_and_ack_m32700ut_pld(unsigned int irq)
+{
+	disable_m32700ut_pld_irq(irq);
+//	mask_and_ack_m32700ut(M32R_IRQ_INT1);
+}
+
+static void end_m32700ut_pld_irq(unsigned int irq)
+{
+	enable_m32700ut_pld_irq(irq);
+	end_m32700ut_irq(M32R_IRQ_INT1);
+}
+
+static unsigned int startup_m32700ut_pld_irq(unsigned int irq)
+{
+	enable_m32700ut_pld_irq(irq);
+	return (0);
+}
+
+static void shutdown_m32700ut_pld_irq(unsigned int irq)
+{
+	unsigned long port;
+	unsigned int pldirq;
+
+	pldirq = irq2pldirq(irq);
+//	shutdown_m32700ut_irq(M32R_IRQ_INT1);
+	port = pldirq2port(pldirq);
+	outw(PLD_ICUCR_ILEVEL7, port);
+}
+
+static struct hw_interrupt_type m32700ut_pld_irq_type =
+{
+	"M32700UT-PLD-IRQ",
+	startup_m32700ut_pld_irq,
+	shutdown_m32700ut_pld_irq,
+	enable_m32700ut_pld_irq,
+	disable_m32700ut_pld_irq,
+	mask_and_ack_m32700ut_pld,
+	end_m32700ut_pld_irq
+};
+
+/*
+ * Interrupt Control Unit of PLD on M32700UT-LAN (Level 2)
+ */
+#define irq2lanpldirq(x)	((x) - M32700UT_LAN_PLD_IRQ_BASE)
+#define lanpldirq2port(x)	(unsigned long)((int)M32700UT_LAN_ICUCR1 + \
+				 (((x) - 1) * sizeof(unsigned short)))
+
+static pld_icu_data_t lanpld_icu_data[M32700UT_NUM_LAN_PLD_IRQ];
+
+static void disable_m32700ut_lanpld_irq(unsigned int irq)
+{
+	unsigned long port, data;
+	unsigned int pldirq;
+
+	pldirq = irq2lanpldirq(irq);
+	port = lanpldirq2port(pldirq);
+	data = lanpld_icu_data[pldirq].icucr|PLD_ICUCR_ILEVEL7;
+	outw(data, port);
+}
+
+static void enable_m32700ut_lanpld_irq(unsigned int irq)
+{
+	unsigned long port, data;
+	unsigned int pldirq;
+
+	pldirq = irq2lanpldirq(irq);
+	port = lanpldirq2port(pldirq);
+	data = lanpld_icu_data[pldirq].icucr|PLD_ICUCR_IEN|PLD_ICUCR_ILEVEL6;
+	outw(data, port);
+}
+
+static void mask_and_ack_m32700ut_lanpld(unsigned int irq)
+{
+	disable_m32700ut_lanpld_irq(irq);
+}
+
+static void end_m32700ut_lanpld_irq(unsigned int irq)
+{
+	enable_m32700ut_lanpld_irq(irq);
+	end_m32700ut_irq(M32R_IRQ_INT0);
+}
+
+static unsigned int startup_m32700ut_lanpld_irq(unsigned int irq)
+{
+	enable_m32700ut_lanpld_irq(irq);
+	return (0);
+}
+
+static void shutdown_m32700ut_lanpld_irq(unsigned int irq)
+{
+	unsigned long port;
+	unsigned int pldirq;
+
+	pldirq = irq2lanpldirq(irq);
+	port = lanpldirq2port(pldirq);
+	outw(PLD_ICUCR_ILEVEL7, port);
+}
+
+static struct hw_interrupt_type m32700ut_lanpld_irq_type =
+{
+	"M32700UT-PLD-LAN-IRQ",
+	startup_m32700ut_lanpld_irq,
+	shutdown_m32700ut_lanpld_irq,
+	enable_m32700ut_lanpld_irq,
+	disable_m32700ut_lanpld_irq,
+	mask_and_ack_m32700ut_lanpld,
+	end_m32700ut_lanpld_irq
+};
+
+/*
+ * Interrupt Control Unit of PLD on M32700UT-LCD (Level 2)
+ */
+#define irq2lcdpldirq(x)	((x) - M32700UT_LCD_PLD_IRQ_BASE)
+#define lcdpldirq2port(x)	(unsigned long)((int)M32700UT_LCD_ICUCR1 + \
+				 (((x) - 1) * sizeof(unsigned short)))
+
+static pld_icu_data_t lcdpld_icu_data[M32700UT_NUM_LCD_PLD_IRQ];
+
+static void disable_m32700ut_lcdpld_irq(unsigned int irq)
+{
+	unsigned long port, data;
+	unsigned int pldirq;
+
+	pldirq = irq2lcdpldirq(irq);
+	port = lcdpldirq2port(pldirq);
+	data = lcdpld_icu_data[pldirq].icucr|PLD_ICUCR_ILEVEL7;
+	outw(data, port);
+}
+
+static void enable_m32700ut_lcdpld_irq(unsigned int irq)
+{
+	unsigned long port, data;
+	unsigned int pldirq;
+
+	pldirq = irq2lcdpldirq(irq);
+	port = lcdpldirq2port(pldirq);
+	data = lcdpld_icu_data[pldirq].icucr|PLD_ICUCR_IEN|PLD_ICUCR_ILEVEL6;
+	outw(data, port);
+}
+
+static void mask_and_ack_m32700ut_lcdpld(unsigned int irq)
+{
+	disable_m32700ut_lcdpld_irq(irq);
+}
+
+static void end_m32700ut_lcdpld_irq(unsigned int irq)
+{
+	enable_m32700ut_lcdpld_irq(irq);
+	end_m32700ut_irq(M32R_IRQ_INT2);
+}
+
+static unsigned int startup_m32700ut_lcdpld_irq(unsigned int irq)
+{
+	enable_m32700ut_lcdpld_irq(irq);
+	return (0);
+}
+
+static void shutdown_m32700ut_lcdpld_irq(unsigned int irq)
+{
+	unsigned long port;
+	unsigned int pldirq;
+
+	pldirq = irq2lcdpldirq(irq);
+	port = lcdpldirq2port(pldirq);
+	outw(PLD_ICUCR_ILEVEL7, port);
+}
+
+static struct hw_interrupt_type m32700ut_lcdpld_irq_type =
+{
+	"M32700UT-PLD-LCD-IRQ",
+	startup_m32700ut_lcdpld_irq,
+	shutdown_m32700ut_lcdpld_irq,
+	enable_m32700ut_lcdpld_irq,
+	disable_m32700ut_lcdpld_irq,
+	mask_and_ack_m32700ut_lcdpld,
+	end_m32700ut_lcdpld_irq
+};
+
+void __init init_IRQ(void)
+{
+#if defined(CONFIG_SMC91X)
+	/* INT#0: LAN controller on M32700UT-LAN (SMC91C111)*/
+	irq_desc[M32700UT_LAN_IRQ_LAN].status = IRQ_DISABLED;
+	irq_desc[M32700UT_LAN_IRQ_LAN].handler = &m32700ut_lanpld_irq_type;
+	irq_desc[M32700UT_LAN_IRQ_LAN].action = 0;
+	irq_desc[M32700UT_LAN_IRQ_LAN].depth = 1;	/* disable nested irq */
+	lanpld_icu_data[irq2lanpldirq(M32700UT_LAN_IRQ_LAN)].icucr = PLD_ICUCR_IEN|PLD_ICUCR_ISMOD02;	/* "H" edge sense */
+	disable_m32700ut_lanpld_irq(M32700UT_LAN_IRQ_LAN);
+#endif  /* CONFIG_SMC91X */
+
+	/* MFT2 : system timer */
+	irq_desc[M32R_IRQ_MFT2].status = IRQ_DISABLED;
+	irq_desc[M32R_IRQ_MFT2].handler = &m32700ut_irq_type;
+	irq_desc[M32R_IRQ_MFT2].action = 0;
+	irq_desc[M32R_IRQ_MFT2].depth = 1;
+	icu_data[M32R_IRQ_MFT2].icucr = M32R_ICUCR_IEN;
+	disable_m32700ut_irq(M32R_IRQ_MFT2);
+
+	/* SIO0 : receive */
+	irq_desc[M32R_IRQ_SIO0_R].status = IRQ_DISABLED;
+	irq_desc[M32R_IRQ_SIO0_R].handler = &m32700ut_irq_type;
+	irq_desc[M32R_IRQ_SIO0_R].action = 0;
+	irq_desc[M32R_IRQ_SIO0_R].depth = 1;
+	icu_data[M32R_IRQ_SIO0_R].icucr = 0;
+	disable_m32700ut_irq(M32R_IRQ_SIO0_R);
+
+	/* SIO0 : send */
+	irq_desc[M32R_IRQ_SIO0_S].status = IRQ_DISABLED;
+	irq_desc[M32R_IRQ_SIO0_S].handler = &m32700ut_irq_type;
+	irq_desc[M32R_IRQ_SIO0_S].action = 0;
+	irq_desc[M32R_IRQ_SIO0_S].depth = 1;
+	icu_data[M32R_IRQ_SIO0_S].icucr = 0;
+	disable_m32700ut_irq(M32R_IRQ_SIO0_S);
+
+	/* SIO1 : receive */
+	irq_desc[M32R_IRQ_SIO1_R].status = IRQ_DISABLED;
+	irq_desc[M32R_IRQ_SIO1_R].handler = &m32700ut_irq_type;
+	irq_desc[M32R_IRQ_SIO1_R].action = 0;
+	irq_desc[M32R_IRQ_SIO1_R].depth = 1;
+	icu_data[M32R_IRQ_SIO1_R].icucr = 0;
+	disable_m32700ut_irq(M32R_IRQ_SIO1_R);
+
+	/* SIO1 : send */
+	irq_desc[M32R_IRQ_SIO1_S].status = IRQ_DISABLED;
+	irq_desc[M32R_IRQ_SIO1_S].handler = &m32700ut_irq_type;
+	irq_desc[M32R_IRQ_SIO1_S].action = 0;
+	irq_desc[M32R_IRQ_SIO1_S].depth = 1;
+	icu_data[M32R_IRQ_SIO1_S].icucr = 0;
+	disable_m32700ut_irq(M32R_IRQ_SIO1_S);
+
+	/* DMA1 : */
+	irq_desc[M32R_IRQ_DMA1].status = IRQ_DISABLED;
+	irq_desc[M32R_IRQ_DMA1].handler = &m32700ut_irq_type;
+	irq_desc[M32R_IRQ_DMA1].action = 0;
+	irq_desc[M32R_IRQ_DMA1].depth = 1;
+	icu_data[M32R_IRQ_DMA1].icucr = 0;
+	disable_m32700ut_irq(M32R_IRQ_DMA1);
+
+#ifdef CONFIG_SERIAL_M32R_PLDSIO
+	/* INT#1: SIO0 Receive on PLD */
+	irq_desc[PLD_IRQ_SIO0_RCV].status = IRQ_DISABLED;
+	irq_desc[PLD_IRQ_SIO0_RCV].handler = &m32700ut_pld_irq_type;
+	irq_desc[PLD_IRQ_SIO0_RCV].action = 0;
+	irq_desc[PLD_IRQ_SIO0_RCV].depth = 1;	/* disable nested irq */
+	pld_icu_data[irq2pldirq(PLD_IRQ_SIO0_RCV)].icucr = PLD_ICUCR_IEN|PLD_ICUCR_ISMOD03;
+	disable_m32700ut_pld_irq(PLD_IRQ_SIO0_RCV);
+
+	/* INT#1: SIO0 Send on PLD */
+	irq_desc[PLD_IRQ_SIO0_SND].status = IRQ_DISABLED;
+	irq_desc[PLD_IRQ_SIO0_SND].handler = &m32700ut_pld_irq_type;
+	irq_desc[PLD_IRQ_SIO0_SND].action = 0;
+	irq_desc[PLD_IRQ_SIO0_SND].depth = 1;	/* disable nested irq */
+	pld_icu_data[irq2pldirq(PLD_IRQ_SIO0_SND)].icucr = PLD_ICUCR_IEN|PLD_ICUCR_ISMOD03;
+	disable_m32700ut_pld_irq(PLD_IRQ_SIO0_SND);
+#endif  /* CONFIG_SERIAL_M32R_PLDSIO */
+
+	/* INT#1: CFC IREQ on PLD */
+	irq_desc[PLD_IRQ_CFIREQ].status = IRQ_DISABLED;
+	irq_desc[PLD_IRQ_CFIREQ].handler = &m32700ut_pld_irq_type;
+	irq_desc[PLD_IRQ_CFIREQ].action = 0;
+	irq_desc[PLD_IRQ_CFIREQ].depth = 1;	/* disable nested irq */
+	pld_icu_data[irq2pldirq(PLD_IRQ_CFIREQ)].icucr = PLD_ICUCR_IEN|PLD_ICUCR_ISMOD01;	/* 'L' level sense */
+	disable_m32700ut_pld_irq(PLD_IRQ_CFIREQ);
+
+	/* INT#1: CFC Insert on PLD */
+	irq_desc[PLD_IRQ_CFC_INSERT].status = IRQ_DISABLED;
+	irq_desc[PLD_IRQ_CFC_INSERT].handler = &m32700ut_pld_irq_type;
+	irq_desc[PLD_IRQ_CFC_INSERT].action = 0;
+	irq_desc[PLD_IRQ_CFC_INSERT].depth = 1;	/* disable nested irq */
+	pld_icu_data[irq2pldirq(PLD_IRQ_CFC_INSERT)].icucr = PLD_ICUCR_IEN|PLD_ICUCR_ISMOD00;	/* 'L' edge sense */
+	disable_m32700ut_pld_irq(PLD_IRQ_CFC_INSERT);
+
+	/* INT#1: CFC Eject on PLD */
+	irq_desc[PLD_IRQ_CFC_EJECT].status = IRQ_DISABLED;
+	irq_desc[PLD_IRQ_CFC_EJECT].handler = &m32700ut_pld_irq_type;
+	irq_desc[PLD_IRQ_CFC_EJECT].action = 0;
+	irq_desc[PLD_IRQ_CFC_EJECT].depth = 1;	/* disable nested irq */
+	pld_icu_data[irq2pldirq(PLD_IRQ_CFC_EJECT)].icucr = PLD_ICUCR_IEN|PLD_ICUCR_ISMOD02;	/* 'H' edge sense */
+	disable_m32700ut_pld_irq(PLD_IRQ_CFC_EJECT);
+
+	/*
+	 * INT0# is used for LAN, DIO
+	 * We enable it here.
+	 */
+	icu_data[M32R_IRQ_INT0].icucr = M32R_ICUCR_IEN|M32R_ICUCR_ISMOD11;
+	enable_m32700ut_irq(M32R_IRQ_INT0);
+
+	/*
+	 * INT1# is used for UART, MMC, CF Controller in FPGA.
+	 * We enable it here.
+	 */
+	icu_data[M32R_IRQ_INT1].icucr = M32R_ICUCR_IEN|M32R_ICUCR_ISMOD11;
+	enable_m32700ut_irq(M32R_IRQ_INT1);
+
+#if defined(CONFIG_USB)
+	outw(USBCR_OTGS, USBCR); 	/* USBCR: non-OTG */
+
+    irq_desc[M32700UT_LCD_IRQ_USB_INT1].status = IRQ_DISABLED;
+    irq_desc[M32700UT_LCD_IRQ_USB_INT1].handler = &m32700ut_lcdpld_irq_type;
+    irq_desc[M32700UT_LCD_IRQ_USB_INT1].action = 0;
+    irq_desc[M32700UT_LCD_IRQ_USB_INT1].depth = 1;
+    lcdpld_icu_data[irq2lcdpldirq(M32700UT_LCD_IRQ_USB_INT1)].icucr = PLD_ICUCR_IEN|PLD_ICUCR_ISMOD01;	/* "L" level sense */
+    disable_m32700ut_lcdpld_irq(M32700UT_LCD_IRQ_USB_INT1);
+#endif
+	/*
+	 * INT2# is used for BAT, USB, AUDIO
+	 * We enable it here.
+	 */
+	icu_data[M32R_IRQ_INT2].icucr = M32R_ICUCR_IEN|M32R_ICUCR_ISMOD01;
+	enable_m32700ut_irq(M32R_IRQ_INT2);
+
+//#if defined(CONFIG_M32R_AR_VGA)
+	/*
+	 * INT3# is used for AR
+	 */
+	irq_desc[M32R_IRQ_INT3].status = IRQ_DISABLED;
+	irq_desc[M32R_IRQ_INT3].handler = &m32700ut_irq_type;
+	irq_desc[M32R_IRQ_INT3].action = 0;
+	irq_desc[M32R_IRQ_INT3].depth = 1;
+	icu_data[M32R_IRQ_INT3].icucr = M32R_ICUCR_IEN|M32R_ICUCR_ISMOD10;
+	disable_m32700ut_irq(M32R_IRQ_INT3);
+//#endif	/* CONFIG_M32R_ARV */
+}
+
+#define LAN_IOSTART     0x300
+#define LAN_IOEND       0x320
+static struct resource smc91x_resources[] = {
+	[0] = {
+		.start  = (LAN_IOSTART),
+		.end    = (LAN_IOEND),
+		.flags  = IORESOURCE_MEM,
+	},
+	[1] = {
+		.start  = M32700UT_LAN_IRQ_LAN,
+		.end    = M32700UT_LAN_IRQ_LAN,
+		.flags  = IORESOURCE_IRQ,
+	}
+};
+
+static struct platform_device smc91x_device = {
+	.name		= "smc91x",
+	.id		= 0,
+	.num_resources  = ARRAY_SIZE(smc91x_resources),
+	.resource       = smc91x_resources,
+};
+
+static int __init platform_init(void)
+{
+	platform_device_register(&smc91x_device);
+	return 0;
+}
+arch_initcall(platform_init);
diff -Nru a/arch/m32r/kernel/setup_mappi.c b/arch/m32r/kernel/setup_mappi.c
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/arch/m32r/kernel/setup_mappi.c	2004-10-18 14:57:23 -07:00
@@ -0,0 +1,160 @@
+/*
+ *  linux/arch/m32r/kernel/setup_mappi.c
+ *
+ *  Setup routines for Renesas MAPPI Board
+ *
+ *  Copyright (c) 2001, 2002  Hiroyuki Kondo, Hirokazu Takata,
+ *                            Hitoshi Yamamoto
+ */
+
+#include <linux/config.h>
+#include <linux/irq.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+
+#include <asm/system.h>
+#include <asm/m32r.h>
+#include <asm/io.h>
+
+#define irq2port(x) (M32R_ICU_CR1_PORTL + ((x - 1) * sizeof(unsigned long)))
+
+#ifndef CONFIG_SMP
+typedef struct {
+	unsigned long icucr;  /* ICU Control Register */
+} icu_data_t;
+#endif /* CONFIG_SMP */
+
+icu_data_t icu_data[NR_IRQS];
+
+static void disable_mappi_irq(unsigned int irq)
+{
+	unsigned long port, data;
+
+	port = irq2port(irq);
+	data = icu_data[irq].icucr|M32R_ICUCR_ILEVEL7;
+	outl(data, port);
+}
+
+static void enable_mappi_irq(unsigned int irq)
+{
+	unsigned long port, data;
+
+	port = irq2port(irq);
+	data = icu_data[irq].icucr|M32R_ICUCR_IEN|M32R_ICUCR_ILEVEL6;
+	outl(data, port);
+}
+
+static void mask_and_ack_mappi(unsigned int irq)
+{
+	disable_mappi_irq(irq);
+}
+
+static void end_mappi_irq(unsigned int irq)
+{
+	enable_mappi_irq(irq);
+}
+
+static unsigned int startup_mappi_irq(unsigned int irq)
+{
+	enable_mappi_irq(irq);
+	return (0);
+}
+
+static void shutdown_mappi_irq(unsigned int irq)
+{
+	unsigned long port;
+
+	port = irq2port(irq);
+	outl(M32R_ICUCR_ILEVEL7, port);
+}
+
+static struct hw_interrupt_type mappi_irq_type =
+{
+	"MAPPI-IRQ",
+	startup_mappi_irq,
+	shutdown_mappi_irq,
+	enable_mappi_irq,
+	disable_mappi_irq,
+	mask_and_ack_mappi,
+	end_mappi_irq
+};
+
+void __init init_IRQ(void)
+{
+	static int once = 0;
+
+	if (once)
+		return;
+	else
+		once++;
+
+#ifdef CONFIG_NE2000
+	/* INT0 : LAN controller (RTL8019AS) */
+	irq_desc[M32R_IRQ_INT0].status = IRQ_DISABLED;
+	irq_desc[M32R_IRQ_INT0].handler = &mappi_irq_type;
+	irq_desc[M32R_IRQ_INT0].action = 0;
+	irq_desc[M32R_IRQ_INT0].depth = 1;
+	icu_data[M32R_IRQ_INT0].icucr = M32R_ICUCR_IEN|M32R_ICUCR_ISMOD10;
+	disable_mappi_irq(M32R_IRQ_INT0);
+#endif /* CONFIG_M32R_NE2000 */
+
+	/* MFT2 : system timer */
+	irq_desc[M32R_IRQ_MFT2].status = IRQ_DISABLED;
+	irq_desc[M32R_IRQ_MFT2].handler = &mappi_irq_type;
+	irq_desc[M32R_IRQ_MFT2].action = 0;
+	irq_desc[M32R_IRQ_MFT2].depth = 1;
+	icu_data[M32R_IRQ_MFT2].icucr = M32R_ICUCR_IEN;
+	disable_mappi_irq(M32R_IRQ_MFT2);
+
+#ifdef CONFIG_SERIAL_M32R_SIO
+	/* SIO0_R : uart receive data */
+	irq_desc[M32R_IRQ_SIO0_R].status = IRQ_DISABLED;
+	irq_desc[M32R_IRQ_SIO0_R].handler = &mappi_irq_type;
+	irq_desc[M32R_IRQ_SIO0_R].action = 0;
+	irq_desc[M32R_IRQ_SIO0_R].depth = 1;
+	icu_data[M32R_IRQ_SIO0_R].icucr = 0;
+	disable_mappi_irq(M32R_IRQ_SIO0_R);
+
+	/* SIO0_S : uart send data */
+	irq_desc[M32R_IRQ_SIO0_S].status = IRQ_DISABLED;
+	irq_desc[M32R_IRQ_SIO0_S].handler = &mappi_irq_type;
+	irq_desc[M32R_IRQ_SIO0_S].action = 0;
+	irq_desc[M32R_IRQ_SIO0_S].depth = 1;
+	icu_data[M32R_IRQ_SIO0_S].icucr = 0;
+	disable_mappi_irq(M32R_IRQ_SIO0_S);
+
+	/* SIO1_R : uart receive data */
+	irq_desc[M32R_IRQ_SIO1_R].status = IRQ_DISABLED;
+	irq_desc[M32R_IRQ_SIO1_R].handler = &mappi_irq_type;
+	irq_desc[M32R_IRQ_SIO1_R].action = 0;
+	irq_desc[M32R_IRQ_SIO1_R].depth = 1;
+	icu_data[M32R_IRQ_SIO1_R].icucr = 0;
+	disable_mappi_irq(M32R_IRQ_SIO1_R);
+
+	/* SIO1_S : uart send data */
+	irq_desc[M32R_IRQ_SIO1_S].status = IRQ_DISABLED;
+	irq_desc[M32R_IRQ_SIO1_S].handler = &mappi_irq_type;
+	irq_desc[M32R_IRQ_SIO1_S].action = 0;
+	irq_desc[M32R_IRQ_SIO1_S].depth = 1;
+	icu_data[M32R_IRQ_SIO1_S].icucr = 0;
+	disable_mappi_irq(M32R_IRQ_SIO1_S);
+#endif /* CONFIG_SERIAL_M32R_SIO */
+
+#if defined(CONFIG_M32RPCC)
+	/* INT1 : pccard0 interrupt */
+	irq_desc[M32R_IRQ_INT1].status = IRQ_DISABLED;
+	irq_desc[M32R_IRQ_INT1].handler = &mappi_irq_type;
+	irq_desc[M32R_IRQ_INT1].action = 0;
+	irq_desc[M32R_IRQ_INT1].depth = 1;
+	icu_data[M32R_IRQ_INT1].icucr = M32R_ICUCR_IEN | M32R_ICUCR_ISMOD00;
+	disable_mappi_irq(M32R_IRQ_INT1);
+
+	/* INT2 : pccard1 interrupt */
+	irq_desc[M32R_IRQ_INT2].status = IRQ_DISABLED;
+	irq_desc[M32R_IRQ_INT2].handler = &mappi_irq_type;
+	irq_desc[M32R_IRQ_INT2].action = 0;
+	irq_desc[M32R_IRQ_INT2].depth = 1;
+	icu_data[M32R_IRQ_INT2].icucr = M32R_ICUCR_IEN | M32R_ICUCR_ISMOD00;
+	disable_mappi_irq(M32R_IRQ_INT2);
+#endif /* CONFIG_M32RPCC */
+}
diff -Nru a/arch/m32r/kernel/setup_mappi2.c b/arch/m32r/kernel/setup_mappi2.c
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/arch/m32r/kernel/setup_mappi2.c	2004-10-18 14:57:23 -07:00
@@ -0,0 +1,212 @@
+/*
+ *  linux/arch/m32r/kernel/setup_mappi.c
+ *
+ *  Setup routines for Renesas MAPPI-II(M3A-ZA36) Board
+ *
+ *  Copyright (c) 2001, 2002  Hiroyuki Kondo, Hirokazu Takata,
+ *                            Hitoshi Yamamoto, Mamoru Sakugawa
+ */
+
+#include <linux/config.h>
+#include <linux/irq.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/device.h>
+
+#include <asm/system.h>
+#include <asm/m32r.h>
+#include <asm/io.h>
+
+#define irq2port(x) (M32R_ICU_CR1_PORTL + ((x - 1) * sizeof(unsigned long)))
+
+#ifndef CONFIG_SMP
+typedef struct {
+	unsigned long icucr;  /* ICU Control Register */
+} icu_data_t;
+#endif /* CONFIG_SMP */
+
+icu_data_t icu_data[NR_IRQS];
+
+static void disable_mappi2_irq(unsigned int irq)
+{
+	unsigned long port, data;
+
+	if ((irq == 0) ||(irq >= NR_IRQS))  {
+		printk("bad irq 0x%08x\n", irq);
+		return;
+	}
+	port = irq2port(irq);
+	data = icu_data[irq].icucr|M32R_ICUCR_ILEVEL7;
+	outl(data, port);
+}
+
+static void enable_mappi2_irq(unsigned int irq)
+{
+	unsigned long port, data;
+
+	if ((irq == 0) ||(irq >= NR_IRQS))  {
+		printk("bad irq 0x%08x\n", irq);
+		return;
+	}
+	port = irq2port(irq);
+	data = icu_data[irq].icucr|M32R_ICUCR_IEN|M32R_ICUCR_ILEVEL6;
+	outl(data, port);
+}
+
+static void mask_and_ack_mappi2(unsigned int irq)
+{
+	disable_mappi2_irq(irq);
+}
+
+static void end_mappi2_irq(unsigned int irq)
+{
+	enable_mappi2_irq(irq);
+}
+
+static unsigned int startup_mappi2_irq(unsigned int irq)
+{
+	enable_mappi2_irq(irq);
+	return (0);
+}
+
+static void shutdown_mappi2_irq(unsigned int irq)
+{
+	unsigned long port;
+
+	port = irq2port(irq);
+	outl(M32R_ICUCR_ILEVEL7, port);
+}
+
+static struct hw_interrupt_type mappi2_irq_type =
+{
+	"MAPPI2-IRQ",
+	startup_mappi2_irq,
+	shutdown_mappi2_irq,
+	enable_mappi2_irq,
+	disable_mappi2_irq,
+	mask_and_ack_mappi2,
+	end_mappi2_irq
+};
+
+void __init init_IRQ(void)
+{
+#if defined(CONFIG_SMC91X)
+	/* INT0 : LAN controller (SMC91111) */
+	irq_desc[M32R_IRQ_INT0].status = IRQ_DISABLED;
+	irq_desc[M32R_IRQ_INT0].handler = &mappi2_irq_type;
+	irq_desc[M32R_IRQ_INT0].action = 0;
+	irq_desc[M32R_IRQ_INT0].depth = 1;
+	icu_data[M32R_IRQ_INT0].icucr = M32R_ICUCR_IEN|M32R_ICUCR_ISMOD10;
+	disable_mappi2_irq(M32R_IRQ_INT0);
+#endif  /* CONFIG_SMC91X */
+
+	/* MFT2 : system timer */
+	irq_desc[M32R_IRQ_MFT2].status = IRQ_DISABLED;
+	irq_desc[M32R_IRQ_MFT2].handler = &mappi2_irq_type;
+	irq_desc[M32R_IRQ_MFT2].action = 0;
+	irq_desc[M32R_IRQ_MFT2].depth = 1;
+	icu_data[M32R_IRQ_MFT2].icucr = M32R_ICUCR_IEN;
+	disable_mappi2_irq(M32R_IRQ_MFT2);
+
+#ifdef CONFIG_SERIAL_M32R_SIO
+	/* SIO0_R : uart receive data */
+	irq_desc[M32R_IRQ_SIO0_R].status = IRQ_DISABLED;
+	irq_desc[M32R_IRQ_SIO0_R].handler = &mappi2_irq_type;
+	irq_desc[M32R_IRQ_SIO0_R].action = 0;
+	irq_desc[M32R_IRQ_SIO0_R].depth = 1;
+	icu_data[M32R_IRQ_SIO0_R].icucr = 0;
+	disable_mappi2_irq(M32R_IRQ_SIO0_R);
+
+	/* SIO0_S : uart send data */
+	irq_desc[M32R_IRQ_SIO0_S].status = IRQ_DISABLED;
+	irq_desc[M32R_IRQ_SIO0_S].handler = &mappi2_irq_type;
+	irq_desc[M32R_IRQ_SIO0_S].action = 0;
+	irq_desc[M32R_IRQ_SIO0_S].depth = 1;
+	icu_data[M32R_IRQ_SIO0_S].icucr = 0;
+	disable_mappi2_irq(M32R_IRQ_SIO0_S);
+	/* SIO1_R : uart receive data */
+	irq_desc[M32R_IRQ_SIO1_R].status = IRQ_DISABLED;
+	irq_desc[M32R_IRQ_SIO1_R].handler = &mappi2_irq_type;
+	irq_desc[M32R_IRQ_SIO1_R].action = 0;
+	irq_desc[M32R_IRQ_SIO1_R].depth = 1;
+	icu_data[M32R_IRQ_SIO1_R].icucr = 0;
+	disable_mappi2_irq(M32R_IRQ_SIO1_R);
+
+	/* SIO1_S : uart send data */
+	irq_desc[M32R_IRQ_SIO1_S].status = IRQ_DISABLED;
+	irq_desc[M32R_IRQ_SIO1_S].handler = &mappi2_irq_type;
+	irq_desc[M32R_IRQ_SIO1_S].action = 0;
+	irq_desc[M32R_IRQ_SIO1_S].depth = 1;
+	icu_data[M32R_IRQ_SIO1_S].icucr = 0;
+	disable_mappi2_irq(M32R_IRQ_SIO1_S);
+#endif  /* CONFIG_M32R_USE_DBG_CONSOLE */
+
+#if defined(CONFIG_USB)
+	/* INT1 : USB Host controller interrupt */
+	irq_desc[M32R_IRQ_INT1].status = IRQ_DISABLED;
+	irq_desc[M32R_IRQ_INT1].handler = &mappi2_irq_type;
+	irq_desc[M32R_IRQ_INT1].action = 0;
+	irq_desc[M32R_IRQ_INT1].depth = 1;
+	icu_data[M32R_IRQ_INT1].icucr = M32R_ICUCR_ISMOD01;
+	disable_mappi2_irq(M32R_IRQ_INT1);
+#endif /* CONFIG_USB */
+
+#if defined(CONFIG_M32R_CFC)
+	/* ICUCR40: CFC IREQ */
+	irq_desc[PLD_IRQ_CFIREQ].status = IRQ_DISABLED;
+	irq_desc[PLD_IRQ_CFIREQ].handler = &mappi2_irq_type;
+	irq_desc[PLD_IRQ_CFIREQ].action = 0;
+	irq_desc[PLD_IRQ_CFIREQ].depth = 1;	/* disable nested irq */
+//	icu_data[PLD_IRQ_CFIREQ].icucr = M32R_ICUCR_IEN|M32R_ICUCR_ISMOD00;
+	icu_data[PLD_IRQ_CFIREQ].icucr = M32R_ICUCR_IEN|M32R_ICUCR_ISMOD01;
+	disable_mappi2_irq(PLD_IRQ_CFIREQ);
+
+	/* ICUCR41: CFC Insert */
+	irq_desc[PLD_IRQ_CFC_INSERT].status = IRQ_DISABLED;
+	irq_desc[PLD_IRQ_CFC_INSERT].handler = &mappi2_irq_type;
+	irq_desc[PLD_IRQ_CFC_INSERT].action = 0;
+	irq_desc[PLD_IRQ_CFC_INSERT].depth = 1;	/* disable nested irq */
+	icu_data[PLD_IRQ_CFC_INSERT].icucr = M32R_ICUCR_IEN|M32R_ICUCR_ISMOD00;
+//	icu_data[PLD_IRQ_CFC_INSERT].icucr = 0;
+	disable_mappi2_irq(PLD_IRQ_CFC_INSERT);
+
+	/* ICUCR42: CFC Eject */
+	irq_desc[PLD_IRQ_CFC_EJECT].status = IRQ_DISABLED;
+	irq_desc[PLD_IRQ_CFC_EJECT].handler = &mappi2_irq_type;
+	irq_desc[PLD_IRQ_CFC_EJECT].action = 0;
+	irq_desc[PLD_IRQ_CFC_EJECT].depth = 1;	/* disable nested irq */
+	icu_data[PLD_IRQ_CFC_EJECT].icucr = M32R_ICUCR_IEN|M32R_ICUCR_ISMOD10;
+//	icu_data[PLD_IRQ_CFC_EJECT].icucr = 0;
+	disable_mappi2_irq(PLD_IRQ_CFC_EJECT);
+
+#endif /* CONFIG_MAPPI2_CFC */
+}
+
+#define LAN_IOSTART     0x300
+#define LAN_IOEND       0x320
+static struct resource smc91x_resources[] = {
+	[0] = {
+		.start  = (LAN_IOSTART),
+		.end    = (LAN_IOEND),
+		.flags  = IORESOURCE_MEM,
+	},
+	[1] = {
+		.start  = M32R_IRQ_INT0,
+		.end    = M32R_IRQ_INT0,
+		.flags  = IORESOURCE_IRQ,
+	}
+};
+
+static struct platform_device smc91x_device = {
+	.name		= "smc91x",
+	.id		= 0,
+	.num_resources  = ARRAY_SIZE(smc91x_resources),
+	.resource       = smc91x_resources,
+};
+
+static int __init platform_init(void)
+{
+	platform_device_register(&smc91x_device);
+	return 0;
+}
+arch_initcall(platform_init);
diff -Nru a/arch/m32r/kernel/setup_oaks32r.c b/arch/m32r/kernel/setup_oaks32r.c
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/arch/m32r/kernel/setup_oaks32r.c	2004-10-18 14:57:24 -07:00
@@ -0,0 +1,143 @@
+/*
+ *  linux/arch/m32r/kernel/setup_oaks32r.c
+ *
+ *  Setup routines for OAKS32R Board
+ *
+ *  Copyright (c) 2002-2004   Hiroyuki Kondo, Hirokazu Takata,
+ *                            Hitoshi Yamamoto, Mamoru Sakugawa
+ */
+
+#include <linux/config.h>
+#include <linux/irq.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+
+#include <asm/system.h>
+#include <asm/m32r.h>
+#include <asm/io.h>
+
+#define irq2port(x) (M32R_ICU_CR1_PORTL + ((x - 1) * sizeof(unsigned long)))
+
+#ifndef CONFIG_SMP
+typedef struct {
+	unsigned long icucr;  /* ICU Control Register */
+} icu_data_t;
+#endif /* CONFIG_SMP */
+
+icu_data_t icu_data[NR_IRQS];
+
+static void disable_oaks32r_irq(unsigned int irq)
+{
+	unsigned long port, data;
+
+	port = irq2port(irq);
+	data = icu_data[irq].icucr|M32R_ICUCR_ILEVEL7;
+	outl(data, port);
+}
+
+static void enable_oaks32r_irq(unsigned int irq)
+{
+	unsigned long port, data;
+
+	port = irq2port(irq);
+	data = icu_data[irq].icucr|M32R_ICUCR_IEN|M32R_ICUCR_ILEVEL6;
+	outl(data, port);
+}
+
+static void mask_and_ack_mappi(unsigned int irq)
+{
+	disable_oaks32r_irq(irq);
+}
+
+static void end_oaks32r_irq(unsigned int irq)
+{
+	enable_oaks32r_irq(irq);
+}
+
+static unsigned int startup_oaks32r_irq(unsigned int irq)
+{
+	enable_oaks32r_irq(irq);
+	return (0);
+}
+
+static void shutdown_oaks32r_irq(unsigned int irq)
+{
+	unsigned long port;
+
+	port = irq2port(irq);
+	outl(M32R_ICUCR_ILEVEL7, port);
+}
+
+static struct hw_interrupt_type oaks32r_irq_type =
+{
+	"OAKS32R-IRQ",
+	startup_oaks32r_irq,
+	shutdown_oaks32r_irq,
+	enable_oaks32r_irq,
+	disable_oaks32r_irq,
+	mask_and_ack_mappi,
+	end_oaks32r_irq
+};
+
+void __init init_IRQ(void)
+{
+	static int once = 0;
+
+	if (once)
+		return;
+	else
+		once++;
+
+#ifdef CONFIG_NE2000
+	/* INT3 : LAN controller (RTL8019AS) */
+	irq_desc[M32R_IRQ_INT3].status = IRQ_DISABLED;
+	irq_desc[M32R_IRQ_INT3].handler = &oaks32r_irq_type;
+	irq_desc[M32R_IRQ_INT3].action = 0;
+	irq_desc[M32R_IRQ_INT3].depth = 1;
+	icu_data[M32R_IRQ_INT3].icucr = M32R_ICUCR_IEN|M32R_ICUCR_ISMOD10;
+	disable_oaks32r_irq(M32R_IRQ_INT3);
+#endif /* CONFIG_M32R_NE2000 */
+
+	/* MFT2 : system timer */
+	irq_desc[M32R_IRQ_MFT2].status = IRQ_DISABLED;
+	irq_desc[M32R_IRQ_MFT2].handler = &oaks32r_irq_type;
+	irq_desc[M32R_IRQ_MFT2].action = 0;
+	irq_desc[M32R_IRQ_MFT2].depth = 1;
+	icu_data[M32R_IRQ_MFT2].icucr = M32R_ICUCR_IEN;
+	disable_oaks32r_irq(M32R_IRQ_MFT2);
+
+#ifdef CONFIG_SERIAL_M32R_SIO
+	/* SIO0_R : uart receive data */
+	irq_desc[M32R_IRQ_SIO0_R].status = IRQ_DISABLED;
+	irq_desc[M32R_IRQ_SIO0_R].handler = &oaks32r_irq_type;
+	irq_desc[M32R_IRQ_SIO0_R].action = 0;
+	irq_desc[M32R_IRQ_SIO0_R].depth = 1;
+	icu_data[M32R_IRQ_SIO0_R].icucr = 0;
+	disable_oaks32r_irq(M32R_IRQ_SIO0_R);
+
+	/* SIO0_S : uart send data */
+	irq_desc[M32R_IRQ_SIO0_S].status = IRQ_DISABLED;
+	irq_desc[M32R_IRQ_SIO0_S].handler = &oaks32r_irq_type;
+	irq_desc[M32R_IRQ_SIO0_S].action = 0;
+	irq_desc[M32R_IRQ_SIO0_S].depth = 1;
+	icu_data[M32R_IRQ_SIO0_S].icucr = 0;
+	disable_oaks32r_irq(M32R_IRQ_SIO0_S);
+
+	/* SIO1_R : uart receive data */
+	irq_desc[M32R_IRQ_SIO1_R].status = IRQ_DISABLED;
+	irq_desc[M32R_IRQ_SIO1_R].handler = &oaks32r_irq_type;
+	irq_desc[M32R_IRQ_SIO1_R].action = 0;
+	irq_desc[M32R_IRQ_SIO1_R].depth = 1;
+	icu_data[M32R_IRQ_SIO1_R].icucr = 0;
+	disable_oaks32r_irq(M32R_IRQ_SIO1_R);
+
+	/* SIO1_S : uart send data */
+	irq_desc[M32R_IRQ_SIO1_S].status = IRQ_DISABLED;
+	irq_desc[M32R_IRQ_SIO1_S].handler = &oaks32r_irq_type;
+	irq_desc[M32R_IRQ_SIO1_S].action = 0;
+	irq_desc[M32R_IRQ_SIO1_S].depth = 1;
+	icu_data[M32R_IRQ_SIO1_S].icucr = 0;
+	disable_oaks32r_irq(M32R_IRQ_SIO1_S);
+#endif /* CONFIG_SERIAL_M32R_SIO */
+
+}
diff -Nru a/arch/m32r/kernel/setup_opsput.c b/arch/m32r/kernel/setup_opsput.c
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/arch/m32r/kernel/setup_opsput.c	2004-10-18 14:57:21 -07:00
@@ -0,0 +1,482 @@
+/*
+ *  linux/arch/m32r/kernel/setup_opsput.c
+ *
+ *  Setup routines for Renesas OPSPUT Board
+ *
+ *  Copyright (c) 2002-2004
+ * 	Hiroyuki Kondo, Hirokazu Takata,
+ *      Hitoshi Yamamoto, Takeo Takahashi, Mamoru Sakugawa
+ *
+ *  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.
+ */
+
+#include <linux/config.h>
+#include <linux/irq.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/device.h>
+
+#include <asm/system.h>
+#include <asm/m32r.h>
+#include <asm/io.h>
+
+/*
+ * OPSP Interrupt Control Unit (Level 1)
+ */
+#define irq2port(x) (M32R_ICU_CR1_PORTL + ((x - 1) * sizeof(unsigned long)))
+
+#ifndef CONFIG_SMP
+typedef struct {
+	unsigned long icucr;  /* ICU Control Register */
+} icu_data_t;
+#endif /* CONFIG_SMP */
+
+static icu_data_t icu_data[OPSPUT_NUM_CPU_IRQ];
+
+static void disable_opsput_irq(unsigned int irq)
+{
+	unsigned long port, data;
+
+	port = irq2port(irq);
+	data = icu_data[irq].icucr|M32R_ICUCR_ILEVEL7;
+	outl(data, port);
+}
+
+static void enable_opsput_irq(unsigned int irq)
+{
+	unsigned long port, data;
+
+	port = irq2port(irq);
+	data = icu_data[irq].icucr|M32R_ICUCR_IEN|M32R_ICUCR_ILEVEL6;
+	outl(data, port);
+}
+
+static void mask_and_ack_opsput(unsigned int irq)
+{
+	disable_opsput_irq(irq);
+}
+
+static void end_opsput_irq(unsigned int irq)
+{
+	enable_opsput_irq(irq);
+}
+
+static unsigned int startup_opsput_irq(unsigned int irq)
+{
+	enable_opsput_irq(irq);
+	return (0);
+}
+
+static void shutdown_opsput_irq(unsigned int irq)
+{
+	unsigned long port;
+
+	port = irq2port(irq);
+	outl(M32R_ICUCR_ILEVEL7, port);
+}
+
+static struct hw_interrupt_type opsput_irq_type =
+{
+	"OPSPUT-IRQ",
+	startup_opsput_irq,
+	shutdown_opsput_irq,
+	enable_opsput_irq,
+	disable_opsput_irq,
+	mask_and_ack_opsput,
+	end_opsput_irq
+};
+
+/*
+ * Interrupt Control Unit of PLD on OPSPUT (Level 2)
+ */
+#define irq2pldirq(x)		((x) - OPSPUT_PLD_IRQ_BASE)
+#define pldirq2port(x)		(unsigned long)((int)PLD_ICUCR1 + \
+				 (((x) - 1) * sizeof(unsigned short)))
+
+typedef struct {
+	unsigned short icucr;  /* ICU Control Register */
+} pld_icu_data_t;
+
+static pld_icu_data_t pld_icu_data[OPSPUT_NUM_PLD_IRQ];
+
+static void disable_opsput_pld_irq(unsigned int irq)
+{
+	unsigned long port, data;
+	unsigned int pldirq;
+
+	pldirq = irq2pldirq(irq);
+//	disable_opsput_irq(M32R_IRQ_INT1);
+	port = pldirq2port(pldirq);
+	data = pld_icu_data[pldirq].icucr|PLD_ICUCR_ILEVEL7;
+	outw(data, port);
+}
+
+static void enable_opsput_pld_irq(unsigned int irq)
+{
+	unsigned long port, data;
+	unsigned int pldirq;
+
+	pldirq = irq2pldirq(irq);
+//	enable_opsput_irq(M32R_IRQ_INT1);
+	port = pldirq2port(pldirq);
+	data = pld_icu_data[pldirq].icucr|PLD_ICUCR_IEN|PLD_ICUCR_ILEVEL6;
+	outw(data, port);
+}
+
+static void mask_and_ack_opsput_pld(unsigned int irq)
+{
+	disable_opsput_pld_irq(irq);
+//	mask_and_ack_opsput(M32R_IRQ_INT1);
+}
+
+static void end_opsput_pld_irq(unsigned int irq)
+{
+	enable_opsput_pld_irq(irq);
+	end_opsput_irq(M32R_IRQ_INT1);
+}
+
+static unsigned int startup_opsput_pld_irq(unsigned int irq)
+{
+	enable_opsput_pld_irq(irq);
+	return (0);
+}
+
+static void shutdown_opsput_pld_irq(unsigned int irq)
+{
+	unsigned long port;
+	unsigned int pldirq;
+
+	pldirq = irq2pldirq(irq);
+//	shutdown_opsput_irq(M32R_IRQ_INT1);
+	port = pldirq2port(pldirq);
+	outw(PLD_ICUCR_ILEVEL7, port);
+}
+
+static struct hw_interrupt_type opsput_pld_irq_type =
+{
+	"OPSPUT-PLD-IRQ",
+	startup_opsput_pld_irq,
+	shutdown_opsput_pld_irq,
+	enable_opsput_pld_irq,
+	disable_opsput_pld_irq,
+	mask_and_ack_opsput_pld,
+	end_opsput_pld_irq
+};
+
+/*
+ * Interrupt Control Unit of PLD on OPSPUT-LAN (Level 2)
+ */
+#define irq2lanpldirq(x)	((x) - OPSPUT_LAN_PLD_IRQ_BASE)
+#define lanpldirq2port(x)	(unsigned long)((int)OPSPUT_LAN_ICUCR1 + \
+				 (((x) - 1) * sizeof(unsigned short)))
+
+static pld_icu_data_t lanpld_icu_data[OPSPUT_NUM_LAN_PLD_IRQ];
+
+static void disable_opsput_lanpld_irq(unsigned int irq)
+{
+	unsigned long port, data;
+	unsigned int pldirq;
+
+	pldirq = irq2lanpldirq(irq);
+	port = lanpldirq2port(pldirq);
+	data = lanpld_icu_data[pldirq].icucr|PLD_ICUCR_ILEVEL7;
+	outw(data, port);
+}
+
+static void enable_opsput_lanpld_irq(unsigned int irq)
+{
+	unsigned long port, data;
+	unsigned int pldirq;
+
+	pldirq = irq2lanpldirq(irq);
+	port = lanpldirq2port(pldirq);
+	data = lanpld_icu_data[pldirq].icucr|PLD_ICUCR_IEN|PLD_ICUCR_ILEVEL6;
+	outw(data, port);
+}
+
+static void mask_and_ack_opsput_lanpld(unsigned int irq)
+{
+	disable_opsput_lanpld_irq(irq);
+}
+
+static void end_opsput_lanpld_irq(unsigned int irq)
+{
+	enable_opsput_lanpld_irq(irq);
+	end_opsput_irq(M32R_IRQ_INT0);
+}
+
+static unsigned int startup_opsput_lanpld_irq(unsigned int irq)
+{
+	enable_opsput_lanpld_irq(irq);
+	return (0);
+}
+
+static void shutdown_opsput_lanpld_irq(unsigned int irq)
+{
+	unsigned long port;
+	unsigned int pldirq;
+
+	pldirq = irq2lanpldirq(irq);
+	port = lanpldirq2port(pldirq);
+	outw(PLD_ICUCR_ILEVEL7, port);
+}
+
+static struct hw_interrupt_type opsput_lanpld_irq_type =
+{
+	"OPSPUT-PLD-LAN-IRQ",
+	startup_opsput_lanpld_irq,
+	shutdown_opsput_lanpld_irq,
+	enable_opsput_lanpld_irq,
+	disable_opsput_lanpld_irq,
+	mask_and_ack_opsput_lanpld,
+	end_opsput_lanpld_irq
+};
+
+/*
+ * Interrupt Control Unit of PLD on OPSPUT-LCD (Level 2)
+ */
+#define irq2lcdpldirq(x)	((x) - OPSPUT_LCD_PLD_IRQ_BASE)
+#define lcdpldirq2port(x)	(unsigned long)((int)OPSPUT_LCD_ICUCR1 + \
+				 (((x) - 1) * sizeof(unsigned short)))
+
+static pld_icu_data_t lcdpld_icu_data[OPSPUT_NUM_LCD_PLD_IRQ];
+
+static void disable_opsput_lcdpld_irq(unsigned int irq)
+{
+	unsigned long port, data;
+	unsigned int pldirq;
+
+	pldirq = irq2lcdpldirq(irq);
+	port = lcdpldirq2port(pldirq);
+	data = lcdpld_icu_data[pldirq].icucr|PLD_ICUCR_ILEVEL7;
+	outw(data, port);
+}
+
+static void enable_opsput_lcdpld_irq(unsigned int irq)
+{
+	unsigned long port, data;
+	unsigned int pldirq;
+
+	pldirq = irq2lcdpldirq(irq);
+	port = lcdpldirq2port(pldirq);
+	data = lcdpld_icu_data[pldirq].icucr|PLD_ICUCR_IEN|PLD_ICUCR_ILEVEL6;
+	outw(data, port);
+}
+
+static void mask_and_ack_opsput_lcdpld(unsigned int irq)
+{
+	disable_opsput_lcdpld_irq(irq);
+}
+
+static void end_opsput_lcdpld_irq(unsigned int irq)
+{
+	enable_opsput_lcdpld_irq(irq);
+	end_opsput_irq(M32R_IRQ_INT2);
+}
+
+static unsigned int startup_opsput_lcdpld_irq(unsigned int irq)
+{
+	enable_opsput_lcdpld_irq(irq);
+	return (0);
+}
+
+static void shutdown_opsput_lcdpld_irq(unsigned int irq)
+{
+	unsigned long port;
+	unsigned int pldirq;
+
+	pldirq = irq2lcdpldirq(irq);
+	port = lcdpldirq2port(pldirq);
+	outw(PLD_ICUCR_ILEVEL7, port);
+}
+
+static struct hw_interrupt_type opsput_lcdpld_irq_type =
+{
+	"OPSPUT-PLD-LCD-IRQ",
+	startup_opsput_lcdpld_irq,
+	shutdown_opsput_lcdpld_irq,
+	enable_opsput_lcdpld_irq,
+	disable_opsput_lcdpld_irq,
+	mask_and_ack_opsput_lcdpld,
+	end_opsput_lcdpld_irq
+};
+
+void __init init_IRQ(void)
+{
+#if defined(CONFIG_SMC91X)
+	/* INT#0: LAN controller on OPSPUT-LAN (SMC91C111)*/
+	irq_desc[OPSPUT_LAN_IRQ_LAN].status = IRQ_DISABLED;
+	irq_desc[OPSPUT_LAN_IRQ_LAN].handler = &opsput_lanpld_irq_type;
+	irq_desc[OPSPUT_LAN_IRQ_LAN].action = 0;
+	irq_desc[OPSPUT_LAN_IRQ_LAN].depth = 1;	/* disable nested irq */
+	lanpld_icu_data[irq2lanpldirq(OPSPUT_LAN_IRQ_LAN)].icucr = PLD_ICUCR_IEN|PLD_ICUCR_ISMOD02;	/* "H" edge sense */
+	disable_opsput_lanpld_irq(OPSPUT_LAN_IRQ_LAN);
+#endif  /* CONFIG_SMC91X */
+
+	/* MFT2 : system timer */
+	irq_desc[M32R_IRQ_MFT2].status = IRQ_DISABLED;
+	irq_desc[M32R_IRQ_MFT2].handler = &opsput_irq_type;
+	irq_desc[M32R_IRQ_MFT2].action = 0;
+	irq_desc[M32R_IRQ_MFT2].depth = 1;
+	icu_data[M32R_IRQ_MFT2].icucr = M32R_ICUCR_IEN;
+	disable_opsput_irq(M32R_IRQ_MFT2);
+
+	/* SIO0 : receive */
+	irq_desc[M32R_IRQ_SIO0_R].status = IRQ_DISABLED;
+	irq_desc[M32R_IRQ_SIO0_R].handler = &opsput_irq_type;
+	irq_desc[M32R_IRQ_SIO0_R].action = 0;
+	irq_desc[M32R_IRQ_SIO0_R].depth = 1;
+	icu_data[M32R_IRQ_SIO0_R].icucr = 0;
+	disable_opsput_irq(M32R_IRQ_SIO0_R);
+
+	/* SIO0 : send */
+	irq_desc[M32R_IRQ_SIO0_S].status = IRQ_DISABLED;
+	irq_desc[M32R_IRQ_SIO0_S].handler = &opsput_irq_type;
+	irq_desc[M32R_IRQ_SIO0_S].action = 0;
+	irq_desc[M32R_IRQ_SIO0_S].depth = 1;
+	icu_data[M32R_IRQ_SIO0_S].icucr = 0;
+	disable_opsput_irq(M32R_IRQ_SIO0_S);
+
+	/* SIO1 : receive */
+	irq_desc[M32R_IRQ_SIO1_R].status = IRQ_DISABLED;
+	irq_desc[M32R_IRQ_SIO1_R].handler = &opsput_irq_type;
+	irq_desc[M32R_IRQ_SIO1_R].action = 0;
+	irq_desc[M32R_IRQ_SIO1_R].depth = 1;
+	icu_data[M32R_IRQ_SIO1_R].icucr = 0;
+	disable_opsput_irq(M32R_IRQ_SIO1_R);
+
+	/* SIO1 : send */
+	irq_desc[M32R_IRQ_SIO1_S].status = IRQ_DISABLED;
+	irq_desc[M32R_IRQ_SIO1_S].handler = &opsput_irq_type;
+	irq_desc[M32R_IRQ_SIO1_S].action = 0;
+	irq_desc[M32R_IRQ_SIO1_S].depth = 1;
+	icu_data[M32R_IRQ_SIO1_S].icucr = 0;
+	disable_opsput_irq(M32R_IRQ_SIO1_S);
+
+	/* DMA1 : */
+	irq_desc[M32R_IRQ_DMA1].status = IRQ_DISABLED;
+	irq_desc[M32R_IRQ_DMA1].handler = &opsput_irq_type;
+	irq_desc[M32R_IRQ_DMA1].action = 0;
+	irq_desc[M32R_IRQ_DMA1].depth = 1;
+	icu_data[M32R_IRQ_DMA1].icucr = 0;
+	disable_opsput_irq(M32R_IRQ_DMA1);
+
+#ifdef CONFIG_SERIAL_M32R_PLDSIO
+	/* INT#1: SIO0 Receive on PLD */
+	irq_desc[PLD_IRQ_SIO0_RCV].status = IRQ_DISABLED;
+	irq_desc[PLD_IRQ_SIO0_RCV].handler = &opsput_pld_irq_type;
+	irq_desc[PLD_IRQ_SIO0_RCV].action = 0;
+	irq_desc[PLD_IRQ_SIO0_RCV].depth = 1;	/* disable nested irq */
+	pld_icu_data[irq2pldirq(PLD_IRQ_SIO0_RCV)].icucr = PLD_ICUCR_IEN|PLD_ICUCR_ISMOD03;
+	disable_opsput_pld_irq(PLD_IRQ_SIO0_RCV);
+
+	/* INT#1: SIO0 Send on PLD */
+	irq_desc[PLD_IRQ_SIO0_SND].status = IRQ_DISABLED;
+	irq_desc[PLD_IRQ_SIO0_SND].handler = &opsput_pld_irq_type;
+	irq_desc[PLD_IRQ_SIO0_SND].action = 0;
+	irq_desc[PLD_IRQ_SIO0_SND].depth = 1;	/* disable nested irq */
+	pld_icu_data[irq2pldirq(PLD_IRQ_SIO0_SND)].icucr = PLD_ICUCR_IEN|PLD_ICUCR_ISMOD03;
+	disable_opsput_pld_irq(PLD_IRQ_SIO0_SND);
+#endif  /* CONFIG_SERIAL_M32R_PLDSIO */
+
+#if defined(CONFIG_M32R_CFC)
+	/* INT#1: CFC IREQ on PLD */
+	irq_desc[PLD_IRQ_CFIREQ].status = IRQ_DISABLED;
+	irq_desc[PLD_IRQ_CFIREQ].handler = &opsput_pld_irq_type;
+	irq_desc[PLD_IRQ_CFIREQ].action = 0;
+	irq_desc[PLD_IRQ_CFIREQ].depth = 1;	/* disable nested irq */
+	pld_icu_data[irq2pldirq(PLD_IRQ_CFIREQ)].icucr = PLD_ICUCR_IEN|PLD_ICUCR_ISMOD01;	/* 'L' level sense */
+	disable_opsput_pld_irq(PLD_IRQ_CFIREQ);
+
+	/* INT#1: CFC Insert on PLD */
+	irq_desc[PLD_IRQ_CFC_INSERT].status = IRQ_DISABLED;
+	irq_desc[PLD_IRQ_CFC_INSERT].handler = &opsput_pld_irq_type;
+	irq_desc[PLD_IRQ_CFC_INSERT].action = 0;
+	irq_desc[PLD_IRQ_CFC_INSERT].depth = 1;	/* disable nested irq */
+	pld_icu_data[irq2pldirq(PLD_IRQ_CFC_INSERT)].icucr = PLD_ICUCR_IEN|PLD_ICUCR_ISMOD00;	/* 'L' edge sense */
+	disable_opsput_pld_irq(PLD_IRQ_CFC_INSERT);
+
+	/* INT#1: CFC Eject on PLD */
+	irq_desc[PLD_IRQ_CFC_EJECT].status = IRQ_DISABLED;
+	irq_desc[PLD_IRQ_CFC_EJECT].handler = &opsput_pld_irq_type;
+	irq_desc[PLD_IRQ_CFC_EJECT].action = 0;
+	irq_desc[PLD_IRQ_CFC_EJECT].depth = 1;	/* disable nested irq */
+	pld_icu_data[irq2pldirq(PLD_IRQ_CFC_EJECT)].icucr = PLD_ICUCR_IEN|PLD_ICUCR_ISMOD02;	/* 'H' edge sense */
+	disable_opsput_pld_irq(PLD_IRQ_CFC_EJECT);
+#endif /* CONFIG_M32R_CFC */
+
+
+	/*
+	 * INT0# is used for LAN, DIO
+	 * We enable it here.
+	 */
+	icu_data[M32R_IRQ_INT0].icucr = M32R_ICUCR_IEN|M32R_ICUCR_ISMOD11;
+	enable_opsput_irq(M32R_IRQ_INT0);
+
+	/*
+	 * INT1# is used for UART, MMC, CF Controller in FPGA.
+	 * We enable it here.
+	 */
+	icu_data[M32R_IRQ_INT1].icucr = M32R_ICUCR_IEN|M32R_ICUCR_ISMOD11;
+	enable_opsput_irq(M32R_IRQ_INT1);
+
+#if defined(CONFIG_USB)
+	outw(USBCR_OTGS, USBCR); 	/* USBCR: non-OTG */
+
+    irq_desc[OPSPUT_LCD_IRQ_USB_INT1].status = IRQ_DISABLED;
+    irq_desc[OPSPUT_LCD_IRQ_USB_INT1].handler = &opsput_lcdpld_irq_type;
+    irq_desc[OPSPUT_LCD_IRQ_USB_INT1].action = 0;
+    irq_desc[OPSPUT_LCD_IRQ_USB_INT1].depth = 1;
+    lcdpld_icu_data[irq2lcdpldirq(OPSPUT_LCD_IRQ_USB_INT1)].icucr = PLD_ICUCR_IEN|PLD_ICUCR_ISMOD01;	/* "L" level sense */
+    disable_opsput_lcdpld_irq(OPSPUT_LCD_IRQ_USB_INT1);
+#endif
+	/*
+	 * INT2# is used for BAT, USB, AUDIO
+	 * We enable it here.
+	 */
+	icu_data[M32R_IRQ_INT2].icucr = M32R_ICUCR_IEN|M32R_ICUCR_ISMOD01;
+	enable_opsput_irq(M32R_IRQ_INT2);
+
+//#if defined(CONFIG_M32R_AR_VGA)
+	/*
+	 * INT3# is used for AR
+	 */
+	irq_desc[M32R_IRQ_INT3].status = IRQ_DISABLED;
+	irq_desc[M32R_IRQ_INT3].handler = &opsput_irq_type;
+	irq_desc[M32R_IRQ_INT3].action = 0;
+	irq_desc[M32R_IRQ_INT3].depth = 1;
+	icu_data[M32R_IRQ_INT3].icucr = M32R_ICUCR_IEN|M32R_ICUCR_ISMOD10;
+	disable_opsput_irq(M32R_IRQ_INT3);
+//#endif	/* CONFIG_M32R_ARV */
+}
+
+#define LAN_IOSTART     0x300
+#define LAN_IOEND       0x320
+static struct resource smc91x_resources[] = {
+	[0] = {
+		.start  = (LAN_IOSTART),
+		.end    = (LAN_IOEND),
+		.flags  = IORESOURCE_MEM,
+	},
+	[1] = {
+		.start  = OPSPUT_LAN_IRQ_LAN,
+		.end    = OPSPUT_LAN_IRQ_LAN,
+		.flags  = IORESOURCE_IRQ,
+	}
+};
+
+static struct platform_device smc91x_device = {
+	.name		= "smc91x",
+	.id		= 0,
+	.num_resources  = ARRAY_SIZE(smc91x_resources),
+	.resource       = smc91x_resources,
+};
+
+static int __init platform_init(void)
+{
+	platform_device_register(&smc91x_device);
+	return 0;
+}
+arch_initcall(platform_init);
diff -Nru a/arch/m32r/kernel/setup_usrv.c b/arch/m32r/kernel/setup_usrv.c
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/arch/m32r/kernel/setup_usrv.c	2004-10-18 14:57:23 -07:00
@@ -0,0 +1,256 @@
+/*
+ *  linux/arch/m32r/kernel/setup_usrv.c
+ *
+ *  Setup routines for MITSUBISHI uServer
+ *
+ *  Copyright (c) 2001, 2002, 2003  Hiroyuki Kondo, Hirokazu Takata,
+ *                                  Hitoshi Yamamoto
+ */
+
+#include <linux/config.h>
+#include <linux/irq.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+
+#include <asm/system.h>
+#include <asm/m32r.h>
+#include <asm/io.h>
+
+#define irq2port(x) (M32R_ICU_CR1_PORTL + ((x - 1) * sizeof(unsigned long)))
+
+#if !defined(CONFIG_SMP)
+typedef struct {
+	unsigned long icucr;	/* ICU Control Register */
+} icu_data_t;
+#endif /* CONFIG_SMP */
+
+icu_data_t icu_data[M32700UT_NUM_CPU_IRQ];
+
+static void disable_mappi_irq(unsigned int irq)
+{
+	unsigned long port, data;
+
+	port = irq2port(irq);
+	data = icu_data[irq].icucr|M32R_ICUCR_ILEVEL7;
+	outl(data, port);
+}
+
+static void enable_mappi_irq(unsigned int irq)
+{
+	unsigned long port, data;
+
+	port = irq2port(irq);
+	data = icu_data[irq].icucr|M32R_ICUCR_IEN|M32R_ICUCR_ILEVEL6;
+	outl(data, port);
+}
+
+static void mask_and_ack_mappi(unsigned int irq)
+{
+	disable_mappi_irq(irq);
+}
+
+static void end_mappi_irq(unsigned int irq)
+{
+	enable_mappi_irq(irq);
+}
+
+static unsigned int startup_mappi_irq(unsigned int irq)
+{
+	enable_mappi_irq(irq);
+	return 0;
+}
+
+static void shutdown_mappi_irq(unsigned int irq)
+{
+	unsigned long port;
+
+	port = irq2port(irq);
+	outl(M32R_ICUCR_ILEVEL7, port);
+}
+
+static struct hw_interrupt_type mappi_irq_type =
+{
+	"M32700-IRQ",
+	startup_mappi_irq,
+	shutdown_mappi_irq,
+	enable_mappi_irq,
+	disable_mappi_irq,
+	mask_and_ack_mappi,
+	end_mappi_irq
+};
+
+/*
+ * Interrupt Control Unit of PLD on M32700UT (Level 2)
+ */
+#define irq2pldirq(x)		((x) - M32700UT_PLD_IRQ_BASE)
+#define pldirq2port(x)		(unsigned long)((int)PLD_ICUCR1 + \
+				 (((x) - 1) * sizeof(unsigned short)))
+
+typedef struct {
+	unsigned short icucr;  /* ICU Control Register */
+} pld_icu_data_t;
+
+static pld_icu_data_t pld_icu_data[M32700UT_NUM_PLD_IRQ];
+
+static void disable_m32700ut_pld_irq(unsigned int irq)
+{
+	unsigned long port, data;
+	unsigned int pldirq;
+
+	pldirq = irq2pldirq(irq);
+	port = pldirq2port(pldirq);
+	data = pld_icu_data[pldirq].icucr|PLD_ICUCR_ILEVEL7;
+	outw(data, port);
+}
+
+static void enable_m32700ut_pld_irq(unsigned int irq)
+{
+	unsigned long port, data;
+	unsigned int pldirq;
+
+	pldirq = irq2pldirq(irq);
+	port = pldirq2port(pldirq);
+	data = pld_icu_data[pldirq].icucr|PLD_ICUCR_IEN|PLD_ICUCR_ILEVEL6;
+	outw(data, port);
+}
+
+static void mask_and_ack_m32700ut_pld(unsigned int irq)
+{
+	disable_m32700ut_pld_irq(irq);
+}
+
+static void end_m32700ut_pld_irq(unsigned int irq)
+{
+	enable_m32700ut_pld_irq(irq);
+	end_mappi_irq(M32R_IRQ_INT1);
+}
+
+static unsigned int startup_m32700ut_pld_irq(unsigned int irq)
+{
+	enable_m32700ut_pld_irq(irq);
+	return 0;
+}
+
+static void shutdown_m32700ut_pld_irq(unsigned int irq)
+{
+	unsigned long port;
+	unsigned int pldirq;
+
+	pldirq = irq2pldirq(irq);
+	port = pldirq2port(pldirq);
+	outw(PLD_ICUCR_ILEVEL7, port);
+}
+
+static struct hw_interrupt_type m32700ut_pld_irq_type =
+{
+	"USRV-PLD-IRQ",
+	startup_m32700ut_pld_irq,
+	shutdown_m32700ut_pld_irq,
+	enable_m32700ut_pld_irq,
+	disable_m32700ut_pld_irq,
+	mask_and_ack_m32700ut_pld,
+	end_m32700ut_pld_irq
+};
+
+void __init init_IRQ(void)
+{
+	static int once = 0;
+	int i;
+
+	if (once)
+		return;
+	else
+		once++;
+
+	/* MFT2 : system timer */
+	irq_desc[M32R_IRQ_MFT2].status = IRQ_DISABLED;
+	irq_desc[M32R_IRQ_MFT2].handler = &mappi_irq_type;
+	irq_desc[M32R_IRQ_MFT2].action = 0;
+	irq_desc[M32R_IRQ_MFT2].depth = 1;
+	icu_data[M32R_IRQ_MFT2].icucr = M32R_ICUCR_IEN;
+	disable_mappi_irq(M32R_IRQ_MFT2);
+
+#if defined(CONFIG_SERIAL_M32R_SIO)
+	/* SIO0_R : uart receive data */
+	irq_desc[M32R_IRQ_SIO0_R].status = IRQ_DISABLED;
+	irq_desc[M32R_IRQ_SIO0_R].handler = &mappi_irq_type;
+	irq_desc[M32R_IRQ_SIO0_R].action = 0;
+	irq_desc[M32R_IRQ_SIO0_R].depth = 1;
+	icu_data[M32R_IRQ_SIO0_R].icucr = 0;
+	disable_mappi_irq(M32R_IRQ_SIO0_R);
+
+	/* SIO0_S : uart send data */
+	irq_desc[M32R_IRQ_SIO0_S].status = IRQ_DISABLED;
+	irq_desc[M32R_IRQ_SIO0_S].handler = &mappi_irq_type;
+	irq_desc[M32R_IRQ_SIO0_S].action = 0;
+	irq_desc[M32R_IRQ_SIO0_S].depth = 1;
+	icu_data[M32R_IRQ_SIO0_S].icucr = 0;
+	disable_mappi_irq(M32R_IRQ_SIO0_S);
+
+	/* SIO1_R : uart receive data */
+	irq_desc[M32R_IRQ_SIO1_R].status = IRQ_DISABLED;
+	irq_desc[M32R_IRQ_SIO1_R].handler = &mappi_irq_type;
+	irq_desc[M32R_IRQ_SIO1_R].action = 0;
+	irq_desc[M32R_IRQ_SIO1_R].depth = 1;
+	icu_data[M32R_IRQ_SIO1_R].icucr = 0;
+	disable_mappi_irq(M32R_IRQ_SIO1_R);
+
+	/* SIO1_S : uart send data */
+	irq_desc[M32R_IRQ_SIO1_S].status = IRQ_DISABLED;
+	irq_desc[M32R_IRQ_SIO1_S].handler = &mappi_irq_type;
+	irq_desc[M32R_IRQ_SIO1_S].action = 0;
+	irq_desc[M32R_IRQ_SIO1_S].depth = 1;
+	icu_data[M32R_IRQ_SIO1_S].icucr = 0;
+	disable_mappi_irq(M32R_IRQ_SIO1_S);
+#endif  /* CONFIG_SERIAL_M32R_SIO */
+
+	/* INT#67-#71: CFC#0 IREQ on PLD */
+	for (i = 0 ; i < CONFIG_CFC_NUM ; i++ ) {
+		irq_desc[PLD_IRQ_CF0 + i].status = IRQ_DISABLED;
+		irq_desc[PLD_IRQ_CF0 + i].handler = &m32700ut_pld_irq_type;
+		irq_desc[PLD_IRQ_CF0 + i].action = 0;
+		irq_desc[PLD_IRQ_CF0 + i].depth = 1;	/* disable nested irq */
+		pld_icu_data[irq2pldirq(PLD_IRQ_CF0 + i)].icucr
+			= PLD_ICUCR_ISMOD01;	/* 'L' level sense */
+		disable_m32700ut_pld_irq(PLD_IRQ_CF0 + i);
+	}
+
+#if defined(CONFIG_SERIAL_8250) || defined(CONFIG_SERIAL_8250_MODULE)
+	/* INT#76: 16552D#0 IREQ on PLD */
+	irq_desc[PLD_IRQ_UART0].status = IRQ_DISABLED;
+	irq_desc[PLD_IRQ_UART0].handler = &m32700ut_pld_irq_type;
+	irq_desc[PLD_IRQ_UART0].action = 0;
+	irq_desc[PLD_IRQ_UART0].depth = 1;	/* disable nested irq */
+	pld_icu_data[irq2pldirq(PLD_IRQ_UART0)].icucr
+		= PLD_ICUCR_ISMOD03;	/* 'H' level sense */
+	disable_m32700ut_pld_irq(PLD_IRQ_UART0);
+
+	/* INT#77: 16552D#1 IREQ on PLD */
+	irq_desc[PLD_IRQ_UART1].status = IRQ_DISABLED;
+	irq_desc[PLD_IRQ_UART1].handler = &m32700ut_pld_irq_type;
+	irq_desc[PLD_IRQ_UART1].action = 0;
+	irq_desc[PLD_IRQ_UART1].depth = 1;	/* disable nested irq */
+	pld_icu_data[irq2pldirq(PLD_IRQ_UART1)].icucr
+		= PLD_ICUCR_ISMOD03;	/* 'H' level sense */
+	disable_m32700ut_pld_irq(PLD_IRQ_UART1);
+#endif	/* CONFIG_SERIAL_8250 || CONFIG_SERIAL_8250_MODULE */
+
+#if defined(CONFIG_IDC_AK4524) || defined(CONFIG_IDC_AK4524_MODULE)
+	/* INT#80: AK4524 IREQ on PLD */
+	irq_desc[PLD_IRQ_SNDINT].status = IRQ_DISABLED;
+	irq_desc[PLD_IRQ_SNDINT].handler = &m32700ut_pld_irq_type;
+	irq_desc[PLD_IRQ_SNDINT].action = 0;
+	irq_desc[PLD_IRQ_SNDINT].depth = 1;	/* disable nested irq */
+	pld_icu_data[irq2pldirq(PLD_IRQ_SNDINT)].icucr
+		= PLD_ICUCR_ISMOD01;	/* 'L' level sense */
+	disable_m32700ut_pld_irq(PLD_IRQ_SNDINT);
+#endif	/* CONFIG_IDC_AK4524 || CONFIG_IDC_AK4524_MODULE */
+
+	/*
+	 * INT1# is used for UART, MMC, CF Controller in FPGA.
+	 * We enable it here.
+	 */
+	icu_data[M32R_IRQ_INT1].icucr = M32R_ICUCR_ISMOD11;
+	enable_mappi_irq(M32R_IRQ_INT1);
+}
+
diff -Nru a/arch/m32r/kernel/signal.c b/arch/m32r/kernel/signal.c
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/arch/m32r/kernel/signal.c	2004-10-18 14:57:23 -07:00
@@ -0,0 +1,621 @@
+/*
+ *  linux/arch/m32r/kernel/signal.c
+ *
+ *  Copyright (c) 2003  Hitoshi Yamamoto
+ *
+ *  Taken from i386 version.
+ *  Copyright (C) 1991, 1992  Linus Torvalds
+ *
+ *  1997-11-28  Modified for POSIX.1b signals by Richard Henderson
+ *  2000-06-20  Pentium III FXSR, SSE support by Gareth Hughes
+ */
+
+#include <linux/config.h>
+#include <linux/sched.h>
+#include <linux/mm.h>
+#include <linux/smp.h>
+#include <linux/smp_lock.h>
+#include <linux/kernel.h>
+#include <linux/signal.h>
+#include <linux/errno.h>
+#include <linux/wait.h>
+#include <linux/unistd.h>
+#include <linux/stddef.h>
+#include <linux/personality.h>
+#include <linux/suspend.h>
+#include <asm/cacheflush.h>
+#include <asm/ucontext.h>
+#include <asm/uaccess.h>
+
+#define DEBUG_SIG 0
+
+#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
+
+int do_signal(struct pt_regs *, sigset_t *);
+
+/*
+ * Atomically swap in the new signal mask, and wait for a signal.
+ */
+asmlinkage int
+sys_sigsuspend(old_sigset_t mask, unsigned long r1,
+	       unsigned long r2, unsigned long r3, unsigned long r4,
+	       unsigned long r5, unsigned long r6, struct pt_regs regs)
+{
+	sigset_t saveset;
+
+	mask &= _BLOCKABLE;
+	spin_lock_irq(&current->sighand->siglock);
+	saveset = current->blocked;
+	siginitset(&current->blocked, mask);
+	recalc_sigpending();
+	spin_unlock_irq(&current->sighand->siglock);
+
+	regs.r0 = -EINTR;
+	while (1) {
+		current->state = TASK_INTERRUPTIBLE;
+		schedule();
+		if (do_signal(&regs, &saveset))
+			return regs.r0;
+	}
+}
+
+asmlinkage int
+sys_rt_sigsuspend(sigset_t *unewset, size_t sigsetsize,
+		  unsigned long r2, unsigned long r3, unsigned long r4,
+		  unsigned long r5, unsigned long r6, struct pt_regs regs)
+{
+	sigset_t saveset, newset;
+
+	/* XXX: Don't preclude handling different sized sigset_t's.  */
+	if (sigsetsize != sizeof(sigset_t))
+		return -EINVAL;
+
+	if (copy_from_user(&newset, unewset, sizeof(newset)))
+		return -EFAULT;
+	sigdelsetmask(&newset, ~_BLOCKABLE);
+
+	spin_lock_irq(&current->sighand->siglock);
+	saveset = current->blocked;
+	current->blocked = newset;
+	recalc_sigpending();
+	spin_unlock_irq(&current->sighand->siglock);
+
+	regs.r0 = -EINTR;
+	while (1) {
+		current->state = TASK_INTERRUPTIBLE;
+		schedule();
+		if (do_signal(&regs, &saveset))
+			return regs.r0;
+	}
+}
+
+asmlinkage 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;
+}
+
+asmlinkage int
+sys_sigaltstack(const stack_t __user *uss, stack_t __user *uoss,
+		unsigned long r2, unsigned long r3, unsigned long r4,
+		unsigned long r5, unsigned long r6, struct pt_regs regs)
+{
+	return do_sigaltstack(uss, uoss, regs.spu);
+}
+
+
+/*
+ * Do a signal return; undo the signal stack.
+ */
+
+struct sigframe
+{
+//	char *pretcode;
+	int sig;
+	struct sigcontext sc;
+//	struct _fpstate fpstate;
+	unsigned long extramask[_NSIG_WORDS-1];
+	char retcode[4];
+};
+
+struct rt_sigframe
+{
+//	char *pretcode;
+	int sig;
+	struct siginfo *pinfo;
+	void *puc;
+	struct siginfo info;
+	struct ucontext uc;
+//	struct _fpstate fpstate;
+	char retcode[8];
+};
+
+static int
+restore_sigcontext(struct pt_regs *regs, struct sigcontext __user *sc,
+		   int *r0_p)
+{
+	unsigned int err = 0;
+
+	/* Always make any pending restarted system calls return -EINTR */
+	current_thread_info()->restart_block.fn = do_no_restart_syscall;
+
+#define COPY(x)		err |= __get_user(regs->x, &sc->sc_##x)
+	COPY(r4);
+	COPY(r5);
+	COPY(r6);
+	COPY(pt_regs);
+	/* COPY(r0); Skip r0 */
+	COPY(r1);
+	COPY(r2);
+	COPY(r3);
+	COPY(r7);
+	COPY(r8);
+	COPY(r9);
+	COPY(r10);
+	COPY(r11);
+	COPY(r12);
+#if defined(CONFIG_ISA_M32R2) && defined(CONFIG_ISA_DSP_LEVEL2)
+	COPY(acc0h);
+	COPY(acc0l);
+	COPY(acc1h);
+	COPY(acc1l);
+#elif defined(CONFIG_ISA_M32R2) || defined(CONFIG_ISA_M32R)
+	COPY(acch);
+	COPY(accl);
+#else
+#error unknown isa configuration
+#endif
+	COPY(psw);
+	COPY(bpc);
+	COPY(bbpsw);
+	COPY(bbpc);
+	COPY(spu);
+	COPY(fp);
+	COPY(lr);
+	COPY(spi);
+#undef COPY
+
+	regs->syscall_nr = -1;	/* disable syscall checks */
+	err |= __get_user(*r0_p, &sc->sc_r0);
+
+	return err;
+}
+
+asmlinkage int
+sys_sigreturn(unsigned long r0, unsigned long r1,
+	      unsigned long r2, unsigned long r3, unsigned long r4,
+	      unsigned long r5, unsigned long r6, struct pt_regs regs)
+{
+	struct sigframe __user *frame = (struct sigframe __user *)regs.spu;
+	sigset_t set;
+	int result;
+
+	if (verify_area(VERIFY_READ, frame, sizeof(*frame)))
+		goto badframe;
+	if (__get_user(set.sig[0], &frame->sc.oldmask)
+	    || (_NSIG_WORDS > 1
+		&& __copy_from_user(&set.sig[1], &frame->extramask,
+				    sizeof(frame->extramask))))
+		goto badframe;
+
+	sigdelsetmask(&set, ~_BLOCKABLE);
+	spin_lock_irq(&current->sighand->siglock);
+	current->blocked = set;
+	recalc_sigpending();
+	spin_unlock_irq(&current->sighand->siglock);
+
+	if (restore_sigcontext(&regs, &frame->sc, &result))
+		goto badframe;
+	return result;
+
+badframe:
+	force_sig(SIGSEGV, current);
+	return 0;
+}
+
+asmlinkage int
+sys_rt_sigreturn(unsigned long r0, unsigned long r1,
+		 unsigned long r2, unsigned long r3, unsigned long r4,
+		 unsigned long r5, unsigned long r6, struct pt_regs regs)
+{
+	struct rt_sigframe __user *frame = (struct rt_sigframe __user *)regs.spu;
+	sigset_t set;
+	stack_t st;
+	int result;
+
+	if (verify_area(VERIFY_READ, frame, sizeof(*frame)))
+		goto badframe;
+	if (__copy_from_user(&set, &frame->uc.uc_sigmask, sizeof(set)))
+		goto badframe;
+
+	sigdelsetmask(&set, ~_BLOCKABLE);
+	spin_lock_irq(&current->sighand->siglock);
+	current->blocked = set;
+	recalc_sigpending();
+	spin_unlock_irq(&current->sighand->siglock);
+
+	if (restore_sigcontext(&regs, &frame->uc.uc_mcontext, &result))
+		goto badframe;
+
+	if (__copy_from_user(&st, &frame->uc.uc_stack, sizeof(st)))
+		goto badframe;
+	/* It is more difficult to avoid calling this function than to
+	   call it and ignore errors.  */
+	do_sigaltstack(&st, NULL, regs.spu);
+
+	return result;
+
+badframe:
+	force_sig(SIGSEGV, current);
+	return 0;
+}
+
+/*
+ * Set up a signal frame.
+ */
+
+static int
+setup_sigcontext(struct sigcontext __user *sc, struct pt_regs *regs,
+	         unsigned long mask)
+{
+	int err = 0;
+
+#define COPY(x)	err |= __put_user(regs->x, &sc->sc_##x)
+	COPY(r4);
+	COPY(r5);
+	COPY(r6);
+	COPY(pt_regs);
+	COPY(r0);
+	COPY(r1);
+	COPY(r2);
+	COPY(r3);
+	COPY(r7);
+	COPY(r8);
+	COPY(r9);
+	COPY(r10);
+	COPY(r11);
+	COPY(r12);
+#if defined(CONFIG_ISA_M32R2) && defined(CONFIG_ISA_DSP_LEVEL2)
+	COPY(acc0h);
+	COPY(acc0l);
+	COPY(acc1h);
+	COPY(acc1l);
+#elif defined(CONFIG_ISA_M32R2) || defined(CONFIG_ISA_M32R)
+	COPY(acch);
+	COPY(accl);
+#else
+#error unknown isa configuration
+#endif
+	COPY(psw);
+	COPY(bpc);
+	COPY(bbpsw);
+	COPY(bbpc);
+	COPY(spu);
+	COPY(fp);
+	COPY(lr);
+	COPY(spi);
+#undef COPY
+
+	err |= __put_user(mask, &sc->oldmask);
+
+	return err;
+}
+
+/*
+ * Determine which stack to use..
+ */
+static inline void __user *
+get_sigframe(struct k_sigaction *ka, unsigned long sp, size_t frame_size)
+{
+	/* This is the X/Open sanctioned signal stack switching.  */
+	if (ka->sa.sa_flags & SA_ONSTACK) {
+		if (sas_ss_flags(sp) == 0)
+			sp = current->sas_ss_sp + current->sas_ss_size;
+	}
+
+	return (void __user *)((sp - frame_size) & -8ul);
+}
+
+static void setup_frame(int sig, struct k_sigaction *ka,
+			sigset_t *set, struct pt_regs *regs)
+{
+	struct sigframe __user *frame;
+	int err = 0;
+	int signal;
+
+	frame = get_sigframe(ka, regs->spu, sizeof(*frame));
+
+	if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame)))
+		goto give_sigsegv;
+
+	signal = current_thread_info()->exec_domain
+		&& current_thread_info()->exec_domain->signal_invmap
+		&& sig < 32
+		? current_thread_info()->exec_domain->signal_invmap[sig]
+		: sig;
+
+	err |= __put_user(signal, &frame->sig);
+	if (err)
+		goto give_sigsegv;
+
+	err |= setup_sigcontext(&frame->sc, regs, set->sig[0]);
+	if (err)
+		goto give_sigsegv;
+
+	if (_NSIG_WORDS > 1) {
+		err |= __copy_to_user(frame->extramask, &set->sig[1],
+				      sizeof(frame->extramask));
+		if (err)
+			goto give_sigsegv;
+	}
+
+	if (ka->sa.sa_flags & SA_RESTORER)
+		regs->lr = (unsigned long)ka->sa.sa_restorer;
+	else {
+		/* This is : ldi r7, #__NR_sigreturn ; trap #2 */
+		unsigned long code = 0x670010f2 | (__NR_sigreturn << 16);
+
+		regs->lr = (unsigned long)frame->retcode;
+		err |= __put_user(code, (long __user *)(frame->retcode+0));
+		if (err)
+			goto give_sigsegv;
+		flush_cache_sigtramp((unsigned long)frame->retcode);
+	}
+
+	/* Set up registers for signal handler */
+	regs->spu = (unsigned long)frame;
+	regs->r0 = signal;	/* Arg for signal handler */
+	regs->r1 = (unsigned long)&frame->sc;
+	regs->bpc = (unsigned long)ka->sa.sa_handler;
+
+	set_fs(USER_DS);
+
+#if DEBUG_SIG
+	printk("SIG deliver (%s:%d): sp=%p pc=%p\n",
+		current->comm, current->pid, frame, regs->pc);
+#endif
+
+	return;
+
+give_sigsegv:
+	force_sigsegv(sig, current);
+}
+
+static void setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
+			   sigset_t *set, struct pt_regs *regs)
+{
+	struct rt_sigframe __user *frame;
+	int err = 0;
+	int signal;
+
+	frame = get_sigframe(ka, regs->spu, sizeof(*frame));
+
+	if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame)))
+		goto give_sigsegv;
+
+	signal = current_thread_info()->exec_domain
+		&& current_thread_info()->exec_domain->signal_invmap
+		&& sig < 32
+		? current_thread_info()->exec_domain->signal_invmap[sig]
+		: sig;
+
+	err |= __put_user(signal, &frame->sig);
+	if (err)
+		goto give_sigsegv;
+
+	err |= __put_user(&frame->info, &frame->pinfo);
+	err |= __put_user(&frame->uc, &frame->puc);
+	err |= copy_siginfo_to_user(&frame->info, info);
+	if (err)
+		goto give_sigsegv;
+
+	/* Create the ucontext.  */
+	err |= __put_user(0, &frame->uc.uc_flags);
+	err |= __put_user(0, &frame->uc.uc_link);
+	err |= __put_user(current->sas_ss_sp, &frame->uc.uc_stack.ss_sp);
+	err |= __put_user(sas_ss_flags(regs->spu),
+			  &frame->uc.uc_stack.ss_flags);
+	err |= __put_user(current->sas_ss_size, &frame->uc.uc_stack.ss_size);
+	err |= setup_sigcontext(&frame->uc.uc_mcontext, regs, set->sig[0]);
+	err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set));
+	if (err)
+		goto give_sigsegv;
+
+	/* Set up to return from userspace.  */
+	if (ka->sa.sa_flags & SA_RESTORER)
+		regs->lr = (unsigned long)ka->sa.sa_restorer;
+	else {
+		/* This is : ldi r7, #__NR_rt_sigreturn ; trap #2 */
+		unsigned long code1 = 0x97f00000 | (__NR_rt_sigreturn);
+		unsigned long code2 = 0x10f2f000;
+
+		regs->lr = (unsigned long)frame->retcode;
+		err |= __put_user(code1, (long __user *)(frame->retcode+0));
+		err |= __put_user(code2, (long __user *)(frame->retcode+4));
+		if (err)
+			goto give_sigsegv;
+		flush_cache_sigtramp((unsigned long)frame->retcode);
+	}
+
+	/* Set up registers for signal handler */
+	regs->spu = (unsigned long)frame;
+	regs->r0 = signal;	/* Arg for signal handler */
+	regs->r1 = (unsigned long)&frame->info;
+	regs->r2 = (unsigned long)&frame->uc;
+	regs->bpc = (unsigned long)ka->sa.sa_handler;
+
+	set_fs(USER_DS);
+
+#if DEBUG_SIG
+	printk("SIG deliver (%s:%d): sp=%p pc=%p\n",
+		current->comm, current->pid, frame, regs->pc);
+#endif
+
+	return;
+
+give_sigsegv:
+	force_sigsegv(sig, current);
+}
+
+/*
+ * OK, we're invoking a handler
+ */
+
+static void
+handle_signal(unsigned long sig, struct k_sigaction *ka, siginfo_t *info,
+	      sigset_t *oldset, struct pt_regs *regs)
+{
+	unsigned short inst;
+
+	/* Are we from a system call? */
+	if (regs->syscall_nr >= 0) {
+		/* If so, check system call restarting.. */
+		switch (regs->r0) {
+		        case -ERESTART_RESTARTBLOCK:
+			case -ERESTARTNOHAND:
+				regs->r0 = -EINTR;
+				break;
+
+			case -ERESTARTSYS:
+				if (!(ka->sa.sa_flags & SA_RESTART)) {
+					regs->r0 = -EINTR;
+					break;
+				}
+			/* fallthrough */
+			case -ERESTARTNOINTR:
+				regs->r0 = regs->orig_r0;
+				inst = *(unsigned short *)(regs->bpc - 2);
+				if ((inst & 0xfff0) == 0x10f0)	/* trap ? */
+					regs->bpc -= 2;
+				else
+					regs->bpc -= 4;
+		}
+	}
+
+	/* 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_NODEFER)) {
+		spin_lock_irq(&current->sighand->siglock);
+		sigorsets(&current->blocked,&current->blocked,&ka->sa.sa_mask);
+		sigaddset(&current->blocked,sig);
+		recalc_sigpending();
+		spin_unlock_irq(&current->sighand->siglock);
+	}
+}
+
+/*
+ * Note that 'init' is a special process: it doesn't get signals it doesn't
+ * want to handle. Thus you cannot kill init even with a SIGKILL even by
+ * mistake.
+ */
+int do_signal(struct pt_regs *regs, sigset_t *oldset)
+{
+	siginfo_t info;
+	int signr;
+	struct k_sigaction ka;
+	unsigned short inst;
+
+	/*
+	 * We want the common case to go fast, which
+	 * is why we may in certain cases get here from
+	 * kernel mode. Just return without doing anything
+	 * if so.
+	 */
+	if (!user_mode(regs))
+		return 1;
+
+	if (current->flags & PF_FREEZE) {
+		refrigerator(0);
+		goto no_signal;
+	}
+
+	if (!oldset)
+		oldset = &current->blocked;
+
+	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
+		 * have been cleared if the watchpoint triggered
+		 * inside the kernel.
+		 */
+
+		/* Whee!  Actually deliver the signal.  */
+		handle_signal(signr, &ka, &info, oldset, regs);
+		return 1;
+	}
+
+ no_signal:
+	/* Did we come from a system call? */
+	if (regs->syscall_nr >= 0) {
+		/* Restart the system call - no handlers present */
+		if (regs->r0 == -ERESTARTNOHAND ||
+		    regs->r0 == -ERESTARTSYS ||
+		    regs->r0 == -ERESTARTNOINTR) {
+			regs->r0 = regs->orig_r0;
+			inst = *(unsigned short *)(regs->bpc - 2);
+			if ((inst & 0xfff0) == 0x10f0)	/* trap ? */
+				regs->bpc -= 2;
+			else
+				regs->bpc -= 4;
+		}
+		if (regs->r0 == -ERESTART_RESTARTBLOCK){
+			regs->r0 = regs->orig_r0;
+			regs->r7 = __NR_restart_syscall;
+			inst = *(unsigned short *)(regs->bpc - 2);
+			if ((inst & 0xfff0) == 0x10f0)	/* trap ? */
+				regs->bpc -= 2;
+			else
+				regs->bpc -= 4;
+		}
+	}
+	return 0;
+}
+
+/*
+ * notification of userspace execution resumption
+ * - triggered by current->work.notify_resume
+ */
+void do_notify_resume(struct pt_regs *regs, sigset_t *oldset,
+		      __u32 thread_info_flags)
+{
+	/* Pending single-step? */
+	if (thread_info_flags & _TIF_SINGLESTEP)
+		clear_thread_flag(TIF_SINGLESTEP);
+
+	/* deal with pending signal delivery */
+	if (thread_info_flags & _TIF_SIGPENDING)
+		do_signal(regs,oldset);
+
+	clear_thread_flag(TIF_IRET);
+}
diff -Nru a/arch/m32r/kernel/smp.c b/arch/m32r/kernel/smp.c
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/arch/m32r/kernel/smp.c	2004-10-18 14:57:23 -07:00
@@ -0,0 +1,965 @@
+/*
+ *  linux/arch/m32r/kernel/smp.c
+ *
+ *  M32R SMP support routines.
+ *
+ *  Copyright (c) 2001, 2002  Hitoshi Yamamoto
+ *
+ *  Taken from i386 version.
+ *    (c) 1995 Alan Cox, Building #3 <alan@redhat.com>
+ *    (c) 1998-99, 2000 Ingo Molnar <mingo@redhat.com>
+ *
+ *  This code is released under the GNU General Public License version 2 or
+ *  later.
+ */
+
+#undef DEBUG_SMP
+
+#include <linux/irq.h>
+#include <linux/interrupt.h>
+#include <linux/spinlock.h>
+#include <linux/mm.h>
+#include <linux/smp.h>
+#include <linux/profile.h>
+#include <linux/cpu.h>
+
+#include <asm/cacheflush.h>
+#include <asm/pgalloc.h>
+#include <asm/atomic.h>
+#include <asm/io.h>
+#include <asm/mmu_context.h>
+#include <asm/m32r.h>
+
+/*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*/
+/* Data structures and variables                                             */
+/*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*/
+
+/*
+ * Structure and data for smp_call_function(). This is designed to minimise
+ * static memory requirements. It also looks cleaner.
+ */
+static spinlock_t call_lock = SPIN_LOCK_UNLOCKED;
+
+struct call_data_struct {
+	void (*func) (void *info);
+	void *info;
+	atomic_t started;
+	atomic_t finished;
+	int wait;
+} __attribute__ ((__aligned__(SMP_CACHE_BYTES)));
+
+static struct call_data_struct *call_data;
+
+/*
+ * For flush_cache_all()
+ */
+static spinlock_t flushcache_lock = SPIN_LOCK_UNLOCKED;
+static volatile unsigned long flushcache_cpumask = 0;
+
+/*
+ * For flush_tlb_others()
+ */
+static volatile cpumask_t flush_cpumask;
+static struct mm_struct *flush_mm;
+static struct vm_area_struct *flush_vma;
+static volatile unsigned long flush_va;
+static spinlock_t tlbstate_lock = SPIN_LOCK_UNLOCKED;
+#define FLUSH_ALL 0xffffffff
+
+DECLARE_PER_CPU(int, prof_multiplier);
+DECLARE_PER_CPU(int, prof_old_multiplier);
+DECLARE_PER_CPU(int, prof_counter);
+
+extern spinlock_t ipi_lock[];
+
+/*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*/
+/* Function Prototypes                                                       */
+/*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*/
+
+void smp_send_reschedule(int);
+void smp_reschedule_interrupt(void);
+
+void smp_flush_cache_all(void);
+void smp_flush_cache_all_interrupt(void);
+
+void smp_flush_tlb_all(void);
+static void flush_tlb_all_ipi(void *);
+
+void smp_flush_tlb_mm(struct mm_struct *);
+void smp_flush_tlb_range(struct vm_area_struct *, unsigned long, \
+	unsigned long);
+void smp_flush_tlb_page(struct vm_area_struct *, unsigned long);
+static void flush_tlb_others(cpumask_t, struct mm_struct *,
+	struct vm_area_struct *, unsigned long);
+void smp_invalidate_interrupt(void);
+
+void smp_send_stop(void);
+static void stop_this_cpu(void *);
+
+int smp_call_function(void (*) (void *), void *, int, int);
+void smp_call_function_interrupt(void);
+
+void smp_send_timer(void);
+void smp_ipi_timer_interrupt(struct pt_regs *);
+void smp_local_timer_interrupt(struct pt_regs *);
+
+void send_IPI_allbutself(int, int);
+static void send_IPI_mask(cpumask_t, int, int);
+unsigned long send_IPI_mask_phys(cpumask_t, int, int);
+
+/*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*/
+/* Rescheduling request Routines                                             */
+/*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*/
+
+/*==========================================================================*
+ * Name:         smp_send_reschedule
+ *
+ * Description:  This routine requests other CPU to execute rescheduling.
+ *               1.Send 'RESCHEDULE_IPI' to other CPU.
+ *                 Request other CPU to execute 'smp_reschedule_interrupt()'.
+ *
+ * Born on Date: 2002.02.05
+ *
+ * Arguments:    cpu_id - Target CPU ID
+ *
+ * Returns:      void (cannot fail)
+ *
+ * Modification log:
+ * Date       Who Description
+ * ---------- --- --------------------------------------------------------
+ *
+ *==========================================================================*/
+void smp_send_reschedule(int cpu_id)
+{
+	WARN_ON(cpu_is_offline(cpu_id));
+	send_IPI_mask(cpumask_of_cpu(cpu_id), RESCHEDULE_IPI, 1);
+}
+
+/*==========================================================================*
+ * Name:         smp_reschedule_interrupt
+ *
+ * Description:  This routine executes on CPU which received
+ *               'RESCHEDULE_IPI'.
+ *               Rescheduling is processed at the exit of interrupt
+ *               operation.
+ *
+ * Born on Date: 2002.02.05
+ *
+ * Arguments:    NONE
+ *
+ * Returns:      void (cannot fail)
+ *
+ * Modification log:
+ * Date       Who Description
+ * ---------- --- --------------------------------------------------------
+ *
+ *==========================================================================*/
+void smp_reschedule_interrupt(void)
+{
+	/* nothing to do */
+}
+
+/*==========================================================================*
+ * Name:         smp_flush_cache_all
+ *
+ * Description:  This routine sends a 'INVALIDATE_CACHE_IPI' to all other
+ *               CPUs in the system.
+ *
+ * Born on Date: 2003-05-28
+ *
+ * Arguments:    NONE
+ *
+ * Returns:      void (cannot fail)
+ *
+ * Modification log:
+ * Date       Who Description
+ * ---------- --- --------------------------------------------------------
+ *
+ *==========================================================================*/
+void smp_flush_cache_all(void)
+{
+	cpumask_t cpumask;
+	unsigned long *mask;
+
+	preempt_disable();
+	cpumask = cpu_online_map;
+	cpu_clear(smp_processor_id(), cpumask);
+	spin_lock(&flushcache_lock);
+	mask=cpus_addr(cpumask);
+	atomic_set_mask(*mask, (atomic_t *)&flushcache_cpumask);
+	send_IPI_mask(cpumask, INVALIDATE_CACHE_IPI, 0);
+	_flush_cache_copyback_all();
+	while (flushcache_cpumask)
+		mb();
+	spin_unlock(&flushcache_lock);
+	preempt_enable();
+}
+
+void smp_flush_cache_all_interrupt(void)
+{
+	_flush_cache_copyback_all();
+	clear_bit(smp_processor_id(), &flushcache_cpumask);
+}
+
+/*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*/
+/* TLB flush request Routins                                                 */
+/*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*/
+
+/*==========================================================================*
+ * Name:         smp_flush_tlb_all
+ *
+ * Description:  This routine flushes all processes TLBs.
+ *               1.Request other CPU to execute 'flush_tlb_all_ipi()'.
+ *               2.Execute 'do_flush_tlb_all_local()'.
+ *
+ * Born on Date: 2002.02.05
+ *
+ * Arguments:    NONE
+ *
+ * Returns:      void (cannot fail)
+ *
+ * Modification log:
+ * Date       Who Description
+ * ---------- --- --------------------------------------------------------
+ *
+ *==========================================================================*/
+void smp_flush_tlb_all(void)
+{
+	unsigned long flags;
+
+	preempt_disable();
+	local_irq_save(flags);
+	__flush_tlb_all();
+	local_irq_restore(flags);
+	smp_call_function(flush_tlb_all_ipi, 0, 1, 1);
+	preempt_enable();
+}
+
+/*==========================================================================*
+ * Name:         flush_tlb_all_ipi
+ *
+ * Description:  This routine flushes all local TLBs.
+ *               1.Execute 'do_flush_tlb_all_local()'.
+ *
+ * Born on Date: 2002.02.05
+ *
+ * Arguments:    *info - not used
+ *
+ * Returns:      void (cannot fail)
+ *
+ * Modification log:
+ * Date       Who Description
+ * ---------- --- --------------------------------------------------------
+ *
+ *==========================================================================*/
+static void flush_tlb_all_ipi(void *info)
+{
+	__flush_tlb_all();
+}
+
+/*==========================================================================*
+ * Name:         smp_flush_tlb_mm
+ *
+ * Description:  This routine flushes the specified mm context TLB's.
+ *
+ * Born on Date: 2002.02.05
+ *
+ * Arguments:    *mm - a pointer to the mm struct for flush TLB
+ *
+ * Returns:      void (cannot fail)
+ *
+ * Modification log:
+ * Date       Who Description
+ * ---------- --- --------------------------------------------------------
+ *
+ *==========================================================================*/
+void smp_flush_tlb_mm(struct mm_struct *mm)
+{
+	int cpu_id = smp_processor_id();
+	cpumask_t cpu_mask;
+	unsigned long *mmc = &mm->context[cpu_id];
+	unsigned long flags;
+
+	preempt_disable();
+	cpu_mask = mm->cpu_vm_mask;
+	cpu_clear(cpu_id, cpu_mask);
+
+	if (*mmc != NO_CONTEXT) {
+		local_irq_save(flags);
+		*mmc = NO_CONTEXT;
+		if (mm == current->mm)
+			activate_context(mm);
+		else
+			cpu_clear(cpu_id, mm->cpu_vm_mask);
+		local_irq_restore(flags);
+	}
+	if (!cpus_empty(cpu_mask))
+		flush_tlb_others(cpu_mask, mm, NULL, FLUSH_ALL);
+
+	preempt_enable();
+}
+
+/*==========================================================================*
+ * Name:         smp_flush_tlb_range
+ *
+ * Description:  This routine flushes a range of pages.
+ *
+ * Born on Date: 2002.02.05
+ *
+ * Arguments:    *mm - a pointer to the mm struct for flush TLB
+ *               start - not used
+ *               end - not used
+ *
+ * Returns:      void (cannot fail)
+ *
+ * Modification log:
+ * Date       Who Description
+ * ---------- --- --------------------------------------------------------
+ *
+ *==========================================================================*/
+void smp_flush_tlb_range(struct vm_area_struct *vma, unsigned long start,
+	unsigned long end)
+{
+	smp_flush_tlb_mm(vma->vm_mm);
+}
+
+/*==========================================================================*
+ * Name:         smp_flush_tlb_page
+ *
+ * Description:  This routine flushes one page.
+ *
+ * Born on Date: 2002.02.05
+ *
+ * Arguments:    *vma - a pointer to the vma struct include va
+ *               va - virtual address for flush TLB
+ *
+ * Returns:      void (cannot fail)
+ *
+ * Modification log:
+ * Date       Who Description
+ * ---------- --- --------------------------------------------------------
+ *
+ *==========================================================================*/
+void smp_flush_tlb_page(struct vm_area_struct *vma, unsigned long va)
+{
+	struct mm_struct *mm = vma->vm_mm;
+	int cpu_id = smp_processor_id();
+	cpumask_t cpu_mask;
+	unsigned long *mmc = &mm->context[cpu_id];
+	unsigned long flags;
+
+	preempt_disable();
+	cpu_mask = mm->cpu_vm_mask;
+	cpu_clear(cpu_id, cpu_mask);
+
+#ifdef DEBUG_SMP
+	if (!mm)
+		BUG();
+#endif
+
+	if (*mmc != NO_CONTEXT) {
+		local_irq_save(flags);
+		va &= PAGE_MASK;
+		va |= (*mmc & MMU_CONTEXT_ASID_MASK);
+		__flush_tlb_page(va);
+		local_irq_restore(flags);
+	}
+	if (!cpus_empty(cpu_mask))
+		flush_tlb_others(cpu_mask, mm, vma, va);
+
+	preempt_enable();
+}
+
+/*==========================================================================*
+ * Name:         flush_tlb_others
+ *
+ * Description:  This routine requests other CPU to execute flush TLB.
+ *               1.Setup parmeters.
+ *               2.Send 'INVALIDATE_TLB_IPI' to other CPU.
+ *                 Request other CPU to execute 'smp_invalidate_interrupt()'.
+ *               3.Wait for other CPUs operation finished.
+ *
+ * Born on Date: 2002.02.05
+ *
+ * Arguments:    cpumask - bitmap of target CPUs
+ *               *mm -  a pointer to the mm struct for flush TLB
+ *               *vma -  a pointer to the vma struct include va
+ *               va - virtual address for flush TLB
+ *
+ * Returns:      void (cannot fail)
+ *
+ * Modification log:
+ * Date       Who Description
+ * ---------- --- --------------------------------------------------------
+ *
+ *==========================================================================*/
+static void flush_tlb_others(cpumask_t cpumask, struct mm_struct *mm,
+	struct vm_area_struct *vma, unsigned long va)
+{
+	unsigned long *mask;
+#ifdef DEBUG_SMP
+	unsigned long flags;
+	__save_flags(flags);
+	if (!(flags & 0x0040))	/* Interrupt Disable NONONO */
+		BUG();
+#endif /* DEBUG_SMP */
+
+	/*
+	 * A couple of (to be removed) sanity checks:
+	 *
+	 * - we do not send IPIs to not-yet booted CPUs.
+	 * - current CPU must not be in mask
+	 * - mask must exist :)
+	 */
+	BUG_ON(cpus_empty(cpumask));
+
+	BUG_ON(cpu_isset(smp_processor_id(), cpumask));
+	BUG_ON(!mm);
+
+	/* If a CPU which we ran on has gone down, OK. */
+	cpus_and(cpumask, cpumask, cpu_online_map);
+	if (cpus_empty(cpumask))
+		return;
+
+	/*
+	 * i'm not happy about this global shared spinlock in the
+	 * MM hot path, but we'll see how contended it is.
+	 * Temporarily this turns IRQs off, so that lockups are
+	 * detected by the NMI watchdog.
+	 */
+	spin_lock(&tlbstate_lock);
+
+	flush_mm = mm;
+	flush_vma = vma;
+	flush_va = va;
+	mask=cpus_addr(cpumask);
+	atomic_set_mask(*mask, (atomic_t *)&flush_cpumask);
+
+	/*
+	 * We have to send the IPI only to
+	 * CPUs affected.
+	 */
+	send_IPI_mask(cpumask, INVALIDATE_TLB_IPI, 0);
+
+	while (!cpus_empty(flush_cpumask)) {
+		/* nothing. lockup detection does not belong here */
+		mb();
+	}
+
+	flush_mm = NULL;
+	flush_vma = NULL;
+	flush_va = 0;
+	spin_unlock(&tlbstate_lock);
+}
+
+/*==========================================================================*
+ * Name:         smp_invalidate_interrupt
+ *
+ * Description:  This routine executes on CPU which received
+ *               'INVALIDATE_TLB_IPI'.
+ *               1.Flush local TLB.
+ *               2.Report flush TLB process was finished.
+ *
+ * Born on Date: 2002.02.05
+ *
+ * Arguments:    NONE
+ *
+ * Returns:      void (cannot fail)
+ *
+ * Modification log:
+ * Date       Who Description
+ * ---------- --- --------------------------------------------------------
+ *
+ *==========================================================================*/
+void smp_invalidate_interrupt(void)
+{
+	int cpu_id = smp_processor_id();
+	unsigned long *mmc = &flush_mm->context[cpu_id];
+
+	if (!cpu_isset(cpu_id, flush_cpumask))
+		return;
+
+	if (flush_va == FLUSH_ALL) {
+		*mmc = NO_CONTEXT;
+		if (flush_mm == current->active_mm)
+			activate_context(flush_mm);
+		else
+			cpu_clear(cpu_id, flush_mm->cpu_vm_mask);
+	} else {
+		unsigned long va = flush_va;
+
+		if (*mmc != NO_CONTEXT) {
+			va &= PAGE_MASK;
+			va |= (*mmc & MMU_CONTEXT_ASID_MASK);
+			__flush_tlb_page(va);
+		}
+	}
+	cpu_clear(cpu_id, flush_cpumask);
+}
+
+/*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*/
+/* Stop CPU request Routins                                                 */
+/*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*/
+
+/*==========================================================================*
+ * Name:         smp_send_stop
+ *
+ * Description:  This routine requests stop all CPUs.
+ *               1.Request other CPU to execute 'stop_this_cpu()'.
+ *
+ * Born on Date: 2002.02.05
+ *
+ * Arguments:    NONE
+ *
+ * Returns:      void (cannot fail)
+ *
+ * Modification log:
+ * Date       Who Description
+ * ---------- --- --------------------------------------------------------
+ *
+ *==========================================================================*/
+void smp_send_stop(void)
+{
+	smp_call_function(stop_this_cpu, NULL, 1, 0);
+}
+
+/*==========================================================================*
+ * Name:         stop_this_cpu
+ *
+ * Description:  This routine halt CPU.
+ *
+ * Born on Date: 2002.02.05
+ *
+ * Arguments:    NONE
+ *
+ * Returns:      void (cannot fail)
+ *
+ * Modification log:
+ * Date       Who Description
+ * ---------- --- --------------------------------------------------------
+ *
+ *==========================================================================*/
+static void stop_this_cpu(void *dummy)
+{
+	int cpu_id = smp_processor_id();
+
+	/*
+	 * Remove this CPU:
+	 */
+	cpu_clear(cpu_id, cpu_online_map);
+
+	/*
+	 * PSW IE = 1;
+	 * IMASK = 0;
+	 * goto SLEEP
+	 */
+	local_irq_disable();
+	outl(0, M32R_ICU_IMASK_PORTL);
+	inl(M32R_ICU_IMASK_PORTL);	/* dummy read */
+	local_irq_enable();
+
+	for ( ; ; );
+}
+
+/*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*/
+/* Call function Routins                                                     */
+/*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*/
+
+/*==========================================================================*
+ * Name:         smp_call_function
+ *
+ * Description:  This routine sends a 'CALL_FUNCTION_IPI' to all other CPUs
+ *               in the system.
+ *
+ * Born on Date: 2002.02.05
+ *
+ * Arguments:    *func - The function to run. This must be fast and
+ *                       non-blocking.
+ *               *info - An arbitrary pointer to pass to the function.
+ *               nonatomic - currently unused.
+ *               wait - If true, wait (atomically) until function has
+ *                      completed on other CPUs.
+ *
+ * Returns:      0 on success, else a negative status code. Does not return
+ *               until remote CPUs are nearly ready to execute <<func>> or
+ *               are or have executed.
+ *
+ * Cautions:     You must not call this function with disabled interrupts or
+ *               from a hardware interrupt handler, you may call it from a
+ *               bottom half handler.
+ *
+ * Modification log:
+ * Date       Who Description
+ * ---------- --- --------------------------------------------------------
+ *
+ *==========================================================================*/
+int smp_call_function(void (*func) (void *info), void *info, int nonatomic,
+	int wait)
+{
+	struct call_data_struct data;
+	int cpus;
+
+#ifdef DEBUG_SMP
+	unsigned long flags;
+	__save_flags(flags);
+	if (!(flags & 0x0040))	/* Interrupt Disable NONONO */
+		BUG();
+#endif /* DEBUG_SMP */
+
+	/* Holding any lock stops cpus from going down. */
+	spin_lock(&call_lock);
+	cpus = num_online_cpus() - 1;
+
+	if (!cpus) {
+		spin_unlock(&call_lock);
+		return 0;
+	}
+
+	/* Can deadlock when called with interrupts disabled */
+	WARN_ON(irqs_disabled());
+
+	data.func = func;
+	data.info = info;
+	atomic_set(&data.started, 0);
+	data.wait = wait;
+	if (wait)
+		atomic_set(&data.finished, 0);
+
+	call_data = &data;
+	mb();
+
+	/* Send a message to all other CPUs and wait for them to respond */
+	send_IPI_allbutself(CALL_FUNCTION_IPI, 0);
+
+	/* Wait for response */
+	while (atomic_read(&data.started) != cpus)
+		barrier();
+
+	if (wait)
+		while (atomic_read(&data.finished) != cpus)
+			barrier();
+	spin_unlock(&call_lock);
+
+	return 0;
+}
+
+/*==========================================================================*
+ * Name:         smp_call_function_interrupt
+ *
+ * Description:  This routine executes on CPU which received
+ *               'CALL_FUNCTION_IPI'.
+ *
+ * Born on Date: 2002.02.05
+ *
+ * Arguments:    NONE
+ *
+ * Returns:      void (cannot fail)
+ *
+ * Modification log:
+ * Date       Who Description
+ * ---------- --- --------------------------------------------------------
+ *
+ *==========================================================================*/
+void smp_call_function_interrupt(void)
+{
+	void (*func) (void *info) = call_data->func;
+	void *info = call_data->info;
+	int wait = call_data->wait;
+
+	/*
+	 * Notify initiating CPU that I've grabbed the data and am
+	 * about to execute the function
+	 */
+	mb();
+	atomic_inc(&call_data->started);
+	/*
+	 * At this point the info structure may be out of scope unless wait==1
+	 */
+	irq_enter();
+	(*func)(info);
+	irq_exit();
+
+	if (wait) {
+		mb();
+		atomic_inc(&call_data->finished);
+	}
+}
+
+/*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*/
+/* Timer Routins                                                             */
+/*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*/
+
+/*==========================================================================*
+ * Name:         smp_send_timer
+ *
+ * Description:  This routine sends a 'LOCAL_TIMER_IPI' to all other CPUs
+ *               in the system.
+ *
+ * Born on Date: 2002.02.05
+ *
+ * Arguments:    NONE
+ *
+ * Returns:      void (cannot fail)
+ *
+ * Modification log:
+ * Date       Who Description
+ * ---------- --- --------------------------------------------------------
+ *
+ *==========================================================================*/
+void smp_send_timer(void)
+{
+	send_IPI_allbutself(LOCAL_TIMER_IPI, 1);
+}
+
+/*==========================================================================*
+ * Name:         smp_send_timer
+ *
+ * Description:  This routine executes on CPU which received
+ *               'LOCAL_TIMER_IPI'.
+ *
+ * Born on Date: 2002.02.05
+ *
+ * Arguments:    *regs - a pointer to the saved regster info
+ *
+ * Returns:      void (cannot fail)
+ *
+ * Modification log:
+ * Date       Who Description
+ * ---------- --- --------------------------------------------------------
+ *
+ *==========================================================================*/
+void smp_ipi_timer_interrupt(struct pt_regs *regs)
+{
+	irq_enter();
+	smp_local_timer_interrupt(regs);
+	irq_exit();
+}
+
+/*==========================================================================*
+ * Name:         smp_local_timer_interrupt
+ *
+ * Description:  Local timer interrupt handler. It does both profiling and
+ *               process statistics/rescheduling.
+ *               We do profiling in every local tick, statistics/rescheduling
+ *               happen only every 'profiling multiplier' ticks. The default
+ *               multiplier is 1 and it can be changed by writing the new
+ *               multiplier value into /proc/profile.
+ *
+ * Born on Date: 2002.02.05
+ *
+ * Arguments:    *regs - a pointer to the saved regster info
+ *
+ * Returns:      void (cannot fail)
+ *
+ * Original:     arch/i386/kernel/apic.c
+ *
+ * Modification log:
+ * Date       Who Description
+ * ---------- --- --------------------------------------------------------
+ * 2003-06-24 hy  use per_cpu structure.
+ *==========================================================================*/
+void smp_local_timer_interrupt(struct pt_regs *regs)
+{
+	int user = user_mode(regs);
+	int cpu_id = smp_processor_id();
+
+	/*
+	 * 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
+	 */
+
+	profile_tick(CPU_PROFILING, regs);
+
+	if (--per_cpu(prof_counter, cpu_id) <= 0) {
+		/*
+		 * The multiplier may have changed since the last time we got
+		 * to this point as a result of the user writing to
+		 * /proc/profile. In this case we need to adjust the APIC
+		 * timer accordingly.
+		 *
+		 * Interrupts are already masked off at this point.
+		 */
+		per_cpu(prof_counter, cpu_id)
+			= per_cpu(prof_multiplier, cpu_id);
+		if (per_cpu(prof_counter, cpu_id)
+			!= per_cpu(prof_old_multiplier, cpu_id))
+		{
+			per_cpu(prof_old_multiplier, cpu_id)
+				= per_cpu(prof_counter, cpu_id);
+		}
+
+		update_process_times(user);
+	}
+}
+
+/*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*/
+/* Send IPI Routins                                                          */
+/*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*/
+
+/*==========================================================================*
+ * Name:         send_IPI_allbutself
+ *
+ * Description:  This routine sends a IPI to all other CPUs in the system.
+ *
+ * Born on Date: 2002.02.05
+ *
+ * Arguments:    ipi_num - Number of IPI
+ *               try -  0 : Send IPI certainly.
+ *                     !0 : The following IPI is not sended when Target CPU
+ *                          has not received the before IPI.
+ *
+ * Returns:      void (cannot fail)
+ *
+ * Modification log:
+ * Date       Who Description
+ * ---------- --- --------------------------------------------------------
+ *
+ *==========================================================================*/
+void send_IPI_allbutself(int ipi_num, int try)
+{
+	cpumask_t cpumask;
+
+	cpumask = cpu_online_map;
+	cpu_clear(smp_processor_id(), cpumask);
+
+	send_IPI_mask(cpumask, ipi_num, try);
+}
+
+/*==========================================================================*
+ * Name:         send_IPI_mask
+ *
+ * Description:  This routine sends a IPI to CPUs in the system.
+ *
+ * Born on Date: 2002.02.05
+ *
+ * Arguments:    cpu_mask - Bitmap of target CPUs logical ID
+ *               ipi_num - Number of IPI
+ *               try -  0 : Send IPI certainly.
+ *                     !0 : The following IPI is not sended when Target CPU
+ *                          has not received the before IPI.
+ *
+ * Returns:      void (cannot fail)
+ *
+ * Modification log:
+ * Date       Who Description
+ * ---------- --- --------------------------------------------------------
+ *
+ *==========================================================================*/
+static void send_IPI_mask(cpumask_t cpumask, int ipi_num, int try)
+{
+	cpumask_t physid_mask, tmp;
+	int cpu_id, phys_id;
+	int num_cpus = num_online_cpus();
+
+	if (num_cpus <= 1)	/* NO MP */
+		return;
+
+	cpus_and(tmp, cpumask, cpu_online_map);
+	BUG_ON(!cpus_equal(cpumask, tmp));
+
+	physid_mask = CPU_MASK_NONE;
+	for_each_cpu_mask(cpu_id, cpumask){
+		if ((phys_id = cpu_to_physid(cpu_id)) != -1)
+			cpu_set(phys_id, physid_mask);
+	}
+
+	send_IPI_mask_phys(physid_mask, ipi_num, try);
+}
+
+/*==========================================================================*
+ * Name:         send_IPI_mask_phys
+ *
+ * Description:  This routine sends a IPI to other CPUs in the system.
+ *
+ * Born on Date: 2002.02.05
+ *
+ * Arguments:    cpu_mask - Bitmap of target CPUs physical ID
+ *               ipi_num - Number of IPI
+ *               try -  0 : Send IPI certainly.
+ *                     !0 : The following IPI is not sended when Target CPU
+ *                          has not received the before IPI.
+ *
+ * Returns:      IPICRi regster value.
+ *
+ * Modification log:
+ * Date       Who Description
+ * ---------- --- --------------------------------------------------------
+ *
+ *==========================================================================*/
+unsigned long send_IPI_mask_phys(cpumask_t physid_mask, int ipi_num,
+	int try)
+{
+	spinlock_t *ipilock;
+	unsigned long flags = 0;
+	volatile unsigned long *ipicr_addr;
+	unsigned long ipicr_val;
+	unsigned long my_physid_mask;
+	unsigned long mask = cpus_addr(physid_mask)[0];
+
+
+	if (mask & ~physids_coerce(phys_cpu_present_map))
+		BUG();
+	if (ipi_num >= NR_IPIS)
+		BUG();
+
+	mask <<= IPI_SHIFT;
+	ipilock = &ipi_lock[ipi_num];
+	ipicr_addr = (volatile unsigned long *)(M32R_ICU_IPICR_ADDR
+		+ (ipi_num << 2));
+	my_physid_mask = ~(1 << smp_processor_id());
+
+	/*
+	 * lock ipi_lock[i]
+	 * check IPICRi == 0
+	 * write IPICRi (send IPIi)
+	 * unlock ipi_lock[i]
+	 */
+	__asm__ __volatile__ (
+		";; LOCK ipi_lock[i]		\n\t"
+		".fillinsn			\n"
+		"1:				\n\t"
+		"mvfc	%1, psw 		\n\t"
+		"clrpsw	#0x40 -> nop		\n\t"
+		DCACHE_CLEAR("r4", "r5", "%2")
+		"lock	r4, @%2			\n\t"
+		"addi	r4, #-1			\n\t"
+		"unlock	r4, @%2			\n\t"
+		"mvtc	%1, psw			\n\t"
+		"bnez	r4, 2f			\n\t"
+		LOCK_SECTION_START(".balign 4 \n\t")
+		".fillinsn			\n"
+		"2:				\n\t"
+		"ld	r4, @%2			\n\t"
+		"blez	r4, 2b			\n\t"
+		"bra	1b			\n\t"
+		LOCK_SECTION_END
+		";; CHECK IPICRi == 0		\n\t"
+		".fillinsn			\n"
+		"3:				\n\t"
+		"ld	%0, @%3			\n\t"
+		"and	%0, %6			\n\t"
+		"beqz	%0, 4f			\n\t"
+		"bnez	%5, 5f			\n\t"
+		"bra	3b			\n\t"
+		";; WRITE IPICRi (send IPIi)	\n\t"
+		".fillinsn			\n"
+		"4:				\n\t"
+		"st	%4, @%3			\n\t"
+		";; UNLOCK ipi_lock[i]		\n\t"
+		".fillinsn			\n"
+		"5:				\n\t"
+		"ldi	r4, #1			\n\t"
+		"st	r4, @%2			\n\t"
+		: "=&r"(ipicr_val)
+		: "r"(flags), "r"(&ipilock->lock), "r"(ipicr_addr),
+		  "r"(mask), "r"(try), "r"(my_physid_mask)
+		: "memory", "r4"
+#ifdef CONFIG_CHIP_M32700_TS1
+		, "r5"
+#endif	/* CONFIG_CHIP_M32700_TS1 */
+	);
+
+	return ipicr_val;
+}
diff -Nru a/arch/m32r/kernel/smpboot.c b/arch/m32r/kernel/smpboot.c
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/arch/m32r/kernel/smpboot.c	2004-10-18 14:57:24 -07:00
@@ -0,0 +1,635 @@
+/*
+ *  linux/arch/m32r/kernel/smpboot.c
+ *    orig : i386 2.4.10
+ *
+ *  M32R SMP booting functions
+ *
+ *  Copyright (c) 2001, 2002, 2003  Hitoshi Yamamoto
+ *
+ *  Taken from i386 version.
+ *	  (c) 1995 Alan Cox, Building #3 <alan@redhat.com>
+ *	  (c) 1998, 1999, 2000 Ingo Molnar <mingo@redhat.com>
+ *
+ *	Much of the core SMP work is based on previous work by Thomas Radke, to
+ *	whom a great many thanks are extended.
+ *
+ *	Thanks to Intel for making available several different Pentium,
+ *	Pentium Pro and Pentium-II/Xeon MP machines.
+ *	Original development of Linux SMP code supported by Caldera.
+ *
+ *	This code is released under the GNU General Public License version 2 or
+ *	later.
+ *
+ *	Fixes
+ *		Felix Koop	:	NR_CPUS used properly
+ *		Jose Renau	:	Handle single CPU case.
+ *		Alan Cox	:	By repeated request
+ *					8) - Total BogoMIP report.
+ *		Greg Wright	:	Fix for kernel stacks panic.
+ *		Erich Boleyn	:	MP v1.4 and additional changes.
+ *	Matthias Sattler	:	Changes for 2.1 kernel map.
+ *	Michel Lespinasse	:	Changes for 2.1 kernel map.
+ *	Michael Chastain	:	Change trampoline.S to gnu as.
+ *		Alan Cox	:	Dumb bug: 'B' step PPro's are fine
+ *		Ingo Molnar	:	Added APIC timers, based on code
+ *					from Jose Renau
+ *		Ingo Molnar	:	various cleanups and rewrites
+ *		Tigran Aivazian	:	fixed "0.00 in /proc/uptime on SMP" bug.
+ *	Maciej W. Rozycki	:	Bits for genuine 82489DX APICs
+ *		Martin J. Bligh	: 	Added support for multi-quad systems
+ */
+
+#include <linux/config.h>
+#include <linux/init.h>
+#include <linux/mm.h>
+#include <linux/smp_lock.h>
+#include <linux/irq.h>
+#include <linux/bootmem.h>
+#include <linux/delay.h>
+
+#include <asm/io.h>
+#include <asm/pgalloc.h>
+#include <asm/tlbflush.h>
+
+#define DEBUG_SMP
+#ifdef DEBUG_SMP
+#define Dprintk(x...) printk(x)
+#else
+#define Dprintk(x...)
+#endif
+
+extern int cpu_idle(void);
+extern cpumask_t cpu_initialized;
+
+/*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*/
+/* Data structures and variables                                             */
+/*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*/
+
+/* Processor that is doing the boot up */
+static unsigned int bsp_phys_id = -1;
+
+/* Bitmask of physically existing CPUs */
+physid_mask_t phys_cpu_present_map;
+
+/* Bitmask of currently online CPUs */
+cpumask_t cpu_online_map;
+
+cpumask_t cpu_bootout_map;
+cpumask_t cpu_bootin_map;
+cpumask_t cpu_callout_map;
+static cpumask_t cpu_callin_map;
+
+/* Per CPU bogomips and other parameters */
+struct cpuinfo_m32r cpu_data[NR_CPUS] __cacheline_aligned;
+
+/* Set when the idlers are all forked */
+int smp_threads_ready;
+
+static int cpucount;
+static cpumask_t smp_commenced_mask;
+
+extern struct {
+	void * spi;
+	unsigned short ss;
+} stack_start;
+
+/* which physical physical ID maps to which logical CPU number */
+static volatile int physid_2_cpu[NR_CPUS];
+
+/* which logical CPU number maps to which physical ID */
+volatile int cpu_2_physid[NR_CPUS];
+
+DEFINE_PER_CPU(int, prof_multiplier) = 1;
+DEFINE_PER_CPU(int, prof_old_multiplier) = 1;
+DEFINE_PER_CPU(int, prof_counter) = 1;
+
+spinlock_t ipi_lock[NR_IPIS];
+
+static unsigned int calibration_result;
+
+unsigned long cache_decay_ticks = HZ / 100;
+
+/*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*/
+/* Function Prototypes                                                       */
+/*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*/
+
+void smp_prepare_boot_cpu(void);
+void smp_prepare_cpus(unsigned int);
+static void smp_tune_scheduling(void);
+static void init_ipi_lock(void);
+static void do_boot_cpu(int);
+int __cpu_up(unsigned int);
+void smp_cpus_done(unsigned int);
+
+int start_secondary(void *);
+static void smp_callin(void);
+static void smp_online(void);
+
+static void show_mp_info(int);
+static void smp_store_cpu_info(int);
+static void show_cpu_info(int);
+int setup_profiling_timer(unsigned int);
+static void init_cpu_to_physid(void);
+static void map_cpu_to_physid(int, int);
+static void unmap_cpu_to_physid(int, int);
+
+/*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*/
+/* Boot up APs Routins : BSP                                                 */
+/*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*/
+void __devinit smp_prepare_boot_cpu(void)
+{
+	bsp_phys_id = hard_smp_processor_id();
+	physid_set(bsp_phys_id, phys_cpu_present_map);
+	cpu_set(0, cpu_online_map);	/* BSP's cpu_id == 0 */
+	cpu_set(0, cpu_callout_map);
+	cpu_set(0, cpu_callin_map);
+
+	/*
+	 * Initialize the logical to physical CPU number mapping
+	 */
+	init_cpu_to_physid();
+	map_cpu_to_physid(0, bsp_phys_id);
+	current_thread_info()->cpu = 0;
+}
+
+/*==========================================================================*
+ * Name:         smp_prepare_cpus (old smp_boot_cpus)
+ *
+ * Description:  This routine boot up APs.
+ *
+ * Born on Date: 2002.02.05
+ *
+ * Arguments:    NONE
+ *
+ * Returns:      void (cannot fail)
+ *
+ * Modification log:
+ * Date       Who Description
+ * ---------- --- --------------------------------------------------------
+ * 2003-06-24 hy  modify for linux-2.5.69
+ *
+ *==========================================================================*/
+void __init smp_prepare_cpus(unsigned int max_cpus)
+{
+	int phys_id;
+	unsigned long nr_cpu;
+
+	nr_cpu = inl(M32R_FPGA_NUM_OF_CPUS_PORTL);
+	if (nr_cpu > NR_CPUS) {
+		printk(KERN_INFO "NUM_OF_CPUS reg. value [%ld] > NR_CPU [%d]",
+			nr_cpu, NR_CPUS);
+		goto smp_done;
+	}
+	for (phys_id = 0 ; phys_id < nr_cpu ; phys_id++)
+		physid_set(phys_id, phys_cpu_present_map);
+
+	show_mp_info(nr_cpu);
+
+	init_ipi_lock();
+
+	/*
+	 * Setup boot CPU information
+	 */
+	smp_store_cpu_info(0); /* Final full version of the data */
+	smp_tune_scheduling();
+
+	/*
+	 * If SMP should be disabled, then really disable it!
+	 */
+	if (!max_cpus) {
+		printk(KERN_INFO "SMP mode deactivated by commandline.\n");
+		goto smp_done;
+	}
+
+	/*
+	 * Now scan the CPU present map and fire up the other CPUs.
+	 */
+	Dprintk("CPU present map : %lx\n", physids_coerce(phys_cpu_present_map));
+
+	for (phys_id = 0 ; phys_id < NR_CPUS ; phys_id++) {
+		/*
+		 * Don't even attempt to start the boot CPU!
+		 */
+		if (phys_id == bsp_phys_id)
+			continue;
+
+		if (!physid_isset(phys_id, phys_cpu_present_map))
+			continue;
+
+		if ((max_cpus >= 0) && (max_cpus <= cpucount + 1))
+			continue;
+
+		do_boot_cpu(phys_id);
+
+		/*
+		 * Make sure we unmap all failed CPUs
+		 */
+		if (physid_to_cpu(phys_id) == -1) {
+			physid_clear(phys_id, phys_cpu_present_map);
+			printk("phys CPU#%d not responding - " \
+				"cannot use it.\n", phys_id);
+		}
+	}
+
+smp_done:
+	Dprintk("Boot done.\n");
+}
+
+static void __init smp_tune_scheduling(void)
+{
+	/* Nothing to do. */
+}
+
+/*
+ * init_ipi_lock : Initialize IPI locks.
+ */
+static void __init init_ipi_lock(void)
+{
+	int ipi;
+
+	for (ipi = 0 ; ipi < NR_IPIS ; ipi++)
+		ipi_lock[ipi] = SPIN_LOCK_UNLOCKED;
+}
+
+/*==========================================================================*
+ * Name:         do_boot_cpu
+ *
+ * Description:  This routine boot up one AP.
+ *
+ * Born on Date: 2002.02.05
+ *
+ * Arguments:    phys_id - Target CPU physical ID
+ *
+ * Returns:      void (cannot fail)
+ *
+ * Modification log:
+ * Date       Who Description
+ * ---------- --- --------------------------------------------------------
+ * 2003-06-24 hy  modify for linux-2.5.69
+ *
+ *==========================================================================*/
+static void __init do_boot_cpu(int phys_id)
+{
+	struct task_struct *idle;
+	unsigned long send_status, boot_status;
+	int timeout, cpu_id;
+
+	cpu_id = ++cpucount;
+
+	/*
+	 * We can't use kernel_thread since we must avoid to
+	 * reschedule the child.
+	 */
+	idle = fork_idle(cpu_id);
+	if (IS_ERR(idle))
+		panic("failed fork for CPU#%d.", cpu_id);
+
+	idle->thread.lr = (unsigned long)start_secondary;
+
+	map_cpu_to_physid(cpu_id, phys_id);
+
+	/* So we see what's up   */
+	printk("Booting processor %d/%d\n", phys_id, cpu_id);
+	stack_start.spi = (void *)idle->thread.sp;
+	idle->thread_info->cpu = cpu_id;
+
+	/*
+	 * Send Startup IPI
+	 *   1.IPI received by CPU#(phys_id).
+	 *   2.CPU#(phys_id) enter startup_AP (arch/m32r/kernel/head.S)
+	 *   3.CPU#(phys_id) enter start_secondary()
+	 */
+	send_status = 0;
+	boot_status = 0;
+
+	cpu_set(phys_id, cpu_bootout_map);
+
+	/* Send Startup IPI */
+	send_IPI_mask_phys(cpumask_of_cpu(phys_id), CPU_BOOT_IPI, 0);
+
+	Dprintk("Waiting for send to finish...\n");
+	timeout = 0;
+
+	/* Wait 100[ms] */
+	do {
+		Dprintk("+");
+		udelay(1000);
+		send_status = !cpu_isset(phys_id, cpu_bootin_map);
+	} while (send_status && (timeout++ < 100));
+
+	Dprintk("After Startup.\n");
+
+	if (!send_status) {
+		/*
+		 * allow APs to start initializing.
+		 */
+		Dprintk("Before Callout %d.\n", cpu_id);
+		cpu_set(cpu_id, cpu_callout_map);
+		Dprintk("After Callout %d.\n", cpu_id);
+
+		/*
+		 * Wait 5s total for a response
+		 */
+		for (timeout = 0; timeout < 5000; timeout++) {
+			if (cpu_isset(cpu_id, cpu_callin_map))
+				break;	/* It has booted */
+			udelay(1000);
+		}
+
+		if (cpu_isset(cpu_id, cpu_callin_map)) {
+			/* number CPUs logically, starting from 1 (BSP is 0) */
+			Dprintk("OK.\n");
+		} else {
+			boot_status = 1;
+			printk("Not responding.\n");
+		}
+	} else
+		printk("IPI never delivered???\n");
+
+	if (send_status || boot_status) {
+		unmap_cpu_to_physid(cpu_id, phys_id);
+		cpu_clear(cpu_id, cpu_callout_map);
+		cpu_clear(cpu_id, cpu_callin_map);
+		cpu_clear(cpu_id, cpu_initialized);
+		cpucount--;
+	}
+}
+
+int __devinit __cpu_up(unsigned int cpu_id)
+{
+	int timeout;
+
+	cpu_set(cpu_id, smp_commenced_mask);
+
+	/*
+	 * Wait 5s total for a response
+	 */
+	for (timeout = 0; timeout < 5000; timeout++) {
+		if (cpu_isset(cpu_id, cpu_online_map))
+			break;
+		udelay(1000);
+	}
+	if (!cpu_isset(cpu_id, cpu_online_map))
+		BUG();
+
+	return 0;
+}
+
+void __init smp_cpus_done(unsigned int max_cpus)
+{
+	int cpu_id, timeout;
+	unsigned long bogosum = 0;
+
+	for (timeout = 0; timeout < 5000; timeout++) {
+		if (cpus_equal(cpu_callin_map, cpu_online_map))
+			break;
+		udelay(1000);
+	}
+	if (!cpus_equal(cpu_callin_map, cpu_online_map))
+		BUG();
+
+	for (cpu_id = 0 ; cpu_id < num_online_cpus() ; cpu_id++)
+		show_cpu_info(cpu_id);
+
+	/*
+	 * Allow the user to impress friends.
+	 */
+	Dprintk("Before bogomips.\n");
+	if (cpucount) {
+		for_each_cpu_mask(cpu_id, cpu_online_map)
+			bogosum += cpu_data[cpu_id].loops_per_jiffy;
+
+		printk(KERN_INFO "Total of %d processors activated " \
+			"(%lu.%02lu BogoMIPS).\n", cpucount + 1,
+			bogosum / (500000 / HZ),
+			(bogosum / (5000 / HZ)) % 100);
+		Dprintk("Before bogocount - setting activated=1.\n");
+	}
+}
+
+/*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*/
+/* Activate a secondary processor Routins                                    */
+/*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*/
+
+/*==========================================================================*
+ * Name:         start_secondary
+ *
+ * Description:  This routine activate a secondary processor.
+ *
+ * Born on Date: 2002.02.05
+ *
+ * Arguments:    *unused - currently unused.
+ *
+ * Returns:      void (cannot fail)
+ *
+ * Modification log:
+ * Date       Who Description
+ * ---------- --- --------------------------------------------------------
+ * 2003-06-24 hy  modify for linux-2.5.69
+ *
+ *==========================================================================*/
+int __init start_secondary(void *unused)
+{
+	cpu_init();
+	smp_callin();
+	while (!cpu_isset(smp_processor_id(), smp_commenced_mask))
+		rep_nop();
+
+	smp_online();
+
+	/*
+	 * low-memory mappings have been cleared, flush them from
+	 * the local TLBs too.
+	 */
+	local_flush_tlb_all();
+
+	return cpu_idle();
+}
+
+/*==========================================================================*
+ * Name:         smp_callin
+ *
+ * Description:  This routine activate a secondary processor.
+ *
+ * Born on Date: 2002.02.05
+ *
+ * Arguments:    NONE
+ *
+ * Returns:      void (cannot fail)
+ *
+ * Modification log:
+ * Date       Who Description
+ * ---------- --- --------------------------------------------------------
+ * 2003-06-24 hy  modify for linux-2.5.69
+ *
+ *==========================================================================*/
+static void __init smp_callin(void)
+{
+	int phys_id = hard_smp_processor_id();
+	int cpu_id = smp_processor_id();
+	unsigned long timeout;
+
+	if (cpu_isset(cpu_id, cpu_callin_map)) {
+		printk("huh, phys CPU#%d, CPU#%d already present??\n",
+			phys_id, cpu_id);
+		BUG();
+	}
+	Dprintk("CPU#%d (phys ID: %d) waiting for CALLOUT\n", cpu_id, phys_id);
+
+	/* Waiting 2s total for startup (udelay is not yet working) */
+	timeout = jiffies + (2 * HZ);
+	while (time_before(jiffies, timeout)) {
+		/* Has the boot CPU finished it's STARTUP sequence ? */
+		if (cpu_isset(cpu_id, cpu_callout_map))
+			break;
+		rep_nop();
+	}
+
+	if (!time_before(jiffies, timeout)) {
+		printk("BUG: CPU#%d started up but did not get a callout!\n",
+			cpu_id);
+		BUG();
+	}
+
+	/* Allow the master to continue. */
+	cpu_set(cpu_id, cpu_callin_map);
+}
+
+static void __init smp_online(void)
+{
+	int cpu_id = smp_processor_id();
+
+	local_irq_enable();
+
+	/* Get our bogomips. */
+	calibrate_delay();
+
+	/* Save our processor parameters */
+ 	smp_store_cpu_info(cpu_id);
+
+	cpu_set(cpu_id, cpu_online_map);
+}
+
+/*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*/
+/* Boot up CPUs common Routins                                               */
+/*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*/
+static void __init show_mp_info(int nr_cpu)
+{
+	int i;
+	char cpu_model0[17], cpu_model1[17], cpu_ver[9];
+
+	strncpy(cpu_model0, (char *)M32R_FPGA_CPU_NAME_ADDR, 16);
+	strncpy(cpu_model1, (char *)M32R_FPGA_MODEL_ID_ADDR, 16);
+	strncpy(cpu_ver, (char *)M32R_FPGA_VERSION_ADDR, 8);
+
+	cpu_model0[16] = '\0';
+	for (i = 15 ; i >= 0 ; i--) {
+		if (cpu_model0[i] != ' ')
+			break;
+		cpu_model0[i] = '\0';
+	}
+	cpu_model1[16] = '\0';
+	for (i = 15 ; i >= 0 ; i--) {
+		if (cpu_model1[i] != ' ')
+			break;
+		cpu_model1[i] = '\0';
+	}
+	cpu_ver[8] = '\0';
+	for (i = 7 ; i >= 0 ; i--) {
+		if (cpu_ver[i] != ' ')
+			break;
+		cpu_ver[i] = '\0';
+	}
+
+	printk(KERN_INFO "M32R-mp information\n");
+	printk(KERN_INFO "  On-chip CPUs : %d\n", nr_cpu);
+	printk(KERN_INFO "  CPU model : %s/%s(%s)\n", cpu_model0,
+		cpu_model1, cpu_ver);
+}
+
+/*
+ * The bootstrap kernel entry code has set these up. Save them for
+ * a given CPU
+ */
+static void __init smp_store_cpu_info(int cpu_id)
+{
+	struct cpuinfo_m32r *ci = cpu_data + cpu_id;
+
+	*ci = boot_cpu_data;
+	ci->loops_per_jiffy = loops_per_jiffy;
+}
+
+static void __init show_cpu_info(int cpu_id)
+{
+	struct cpuinfo_m32r *ci = &cpu_data[cpu_id];
+
+	printk("CPU#%d : ", cpu_id);
+
+#define PRINT_CLOCK(name, value) \
+	printk(name " clock %d.%02dMHz", \
+		((value) / 1000000), ((value) % 1000000) / 10000)
+
+	PRINT_CLOCK("CPU", (int)ci->cpu_clock);
+	PRINT_CLOCK(", Bus", (int)ci->bus_clock);
+	printk(", loops_per_jiffy[%ld]\n", ci->loops_per_jiffy);
+}
+
+/*
+ * the frequency of the profiling timer can be changed
+ * by writing a multiplier value into /proc/profile.
+ */
+int setup_profiling_timer(unsigned int multiplier)
+{
+	int i;
+
+	/*
+	 * Sanity check. [at least 500 APIC cycles should be
+	 * between APIC interrupts as a rule of thumb, to avoid
+	 * irqs flooding us]
+	 */
+	if ( (!multiplier) || (calibration_result / multiplier < 500))
+		return -EINVAL;
+
+	/*
+	 * Set the new multiplier for each CPU. CPUs don't start using the
+	 * new values until the next timer interrupt in which they do process
+	 * accounting. At that time they also adjust their APIC timers
+	 * accordingly.
+	 */
+	for (i = 0; i < NR_CPUS; ++i)
+		per_cpu(prof_multiplier, i) = multiplier;
+
+	return 0;
+}
+
+/* Initialize all maps between cpu number and apicids */
+static void __init init_cpu_to_physid(void)
+{
+	int  i;
+
+	for (i = 0 ; i < NR_CPUS ; i++) {
+		cpu_2_physid[i] = -1;
+		physid_2_cpu[i] = -1;
+	}
+}
+
+/*
+ * set up a mapping between cpu and apicid. Uses logical apicids for multiquad,
+ * else physical apic ids
+ */
+static void __init map_cpu_to_physid(int cpu_id, int phys_id)
+{
+	physid_2_cpu[phys_id] = cpu_id;
+	cpu_2_physid[cpu_id] = phys_id;
+}
+
+/*
+ * undo a mapping between cpu and apicid. Uses logical apicids for multiquad,
+ * else physical apic ids
+ */
+static void __init unmap_cpu_to_physid(int cpu_id, int phys_id)
+{
+	physid_2_cpu[phys_id] = -1;
+	cpu_2_physid[cpu_id] = -1;
+}
+
diff -Nru a/arch/m32r/kernel/sys_m32r.c b/arch/m32r/kernel/sys_m32r.c
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/arch/m32r/kernel/sys_m32r.c	2004-10-18 14:57:24 -07:00
@@ -0,0 +1,217 @@
+/*
+ * linux/arch/m32r/kernel/sys_m32r.c
+ *
+ * This file contains various random system calls that
+ * have a non-standard calling sequence on the Linux/M32R platform.
+ *
+ * Taken from i386 version.
+ */
+
+#include <linux/config.h>
+#include <linux/errno.h>
+#include <linux/sched.h>
+#include <linux/mm.h>
+#include <linux/smp.h>
+#include <linux/smp_lock.h>
+#include <linux/sem.h>
+#include <linux/msg.h>
+#include <linux/shm.h>
+#include <linux/stat.h>
+#include <linux/syscalls.h>
+#include <linux/mman.h>
+#include <linux/file.h>
+#include <linux/utsname.h>
+
+#include <asm/uaccess.h>
+#include <asm/cachectl.h>
+#include <asm/cacheflush.h>
+#include <asm/ipc.h>
+
+/*
+ * sys_tas() - test-and-set
+ * linuxthreads testing version
+ */
+#ifndef CONFIG_SMP
+asmlinkage int sys_tas(int *addr)
+{
+	int oldval;
+	unsigned long flags;
+
+	if (!access_ok(VERIFY_WRITE, addr, sizeof (int)))
+		return -EFAULT;
+	local_irq_save(flags);
+	oldval = *addr;
+	*addr = 1;
+	local_irq_restore(flags);
+	return oldval;
+}
+#else /* CONFIG_SMP */
+#include <linux/spinlock.h>
+
+static spinlock_t tas_lock = SPIN_LOCK_UNLOCKED;
+
+asmlinkage int sys_tas(int *addr)
+{
+	int oldval;
+
+	if (!access_ok(VERIFY_WRITE, addr, sizeof (int)))
+		return -EFAULT;
+
+	spin_lock(&tas_lock);
+	oldval = *addr;
+	*addr = 1;
+	spin_unlock(&tas_lock);
+
+	return oldval;
+}
+#endif /* CONFIG_SMP */
+
+/*
+ * sys_pipe() is the normal C calling standard for creating
+ * a pipe. It's not the way Unix traditionally does this, though.
+ */
+asmlinkage int
+sys_pipe(unsigned long r0, unsigned long r1, unsigned long r2,
+	unsigned long r3, unsigned long r4, unsigned long r5,
+	unsigned long r6, struct pt_regs regs)
+{
+	int fd[2];
+	int error;
+
+	error = do_pipe(fd);
+	if (!error) {
+		if (copy_to_user((void *)r0, (void *)fd, 2*sizeof(int)))
+			error = -EFAULT;
+	}
+	return error;
+}
+
+asmlinkage long sys_mmap2(unsigned long addr, unsigned long len,
+	unsigned long prot, unsigned long flags,
+	unsigned long fd, unsigned long pgoff)
+{
+	int error = -EBADF;
+	struct file *file = NULL;
+
+	flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE);
+	if (!(flags & MAP_ANONYMOUS)) {
+		file = fget(fd);
+		if (!file)
+			goto out;
+	}
+
+	down_write(&current->mm->mmap_sem);
+	error = do_mmap_pgoff(file, addr, len, prot, flags, pgoff);
+	up_write(&current->mm->mmap_sem);
+
+	if (file)
+		fput(file);
+out:
+	return error;
+}
+
+/*
+ * sys_ipc() is the de-multiplexer for the SysV IPC calls..
+ *
+ * This is really horribly ugly.
+ */
+asmlinkage int sys_ipc(uint call, int first, int second,
+		       int third, void __user *ptr, long fifth)
+{
+	int version, ret;
+
+	version = call >> 16; /* hack for backward compatibility */
+	call &= 0xffff;
+
+	switch (call) {
+	case SEMOP:
+		return sys_semtimedop(first, (struct sembuf __user *)ptr,
+				      second, NULL);
+	case SEMTIMEDOP:
+		return sys_semtimedop(first, (struct sembuf __user *)ptr,
+				      second, (const struct timespec __user *)fifth);
+	case SEMGET:
+		return sys_semget (first, second, third);
+	case SEMCTL: {
+		union semun fourth;
+		if (!ptr)
+			return -EINVAL;
+		if (get_user(fourth.__pad, (void __user * __user *) ptr))
+			return -EFAULT;
+		return sys_semctl (first, second, third, fourth);
+		}
+
+	case MSGSND:
+		return sys_msgsnd (first, (struct msgbuf __user *) ptr,
+				   second, third);
+	case MSGRCV:
+		switch (version) {
+		case 0: {
+			struct ipc_kludge tmp;
+			if (!ptr)
+				return -EINVAL;
+
+			if (copy_from_user(&tmp,
+					   (struct ipc_kludge __user *) ptr,
+					   sizeof (tmp)))
+				return -EFAULT;
+			return sys_msgrcv (first, tmp.msgp, second,
+					   tmp.msgtyp, third);
+			}
+		default:
+			return sys_msgrcv (first,
+					   (struct msgbuf __user *) ptr,
+					   second, fifth, third);
+		}
+	case MSGGET:
+		return sys_msgget ((key_t) first, second);
+	case MSGCTL:
+		return sys_msgctl (first, second,
+				   (struct msqid_ds __user *) ptr);
+	case SHMAT: {
+		ulong raddr;
+
+		if ((ret = verify_area(VERIFY_WRITE, (ulong __user *) third,
+				      sizeof(ulong))))
+			return ret;
+		ret = do_shmat (first, (char __user *) ptr, second, &raddr);
+		if (ret)
+			return ret;
+		return put_user (raddr, (ulong __user *) third);
+		}
+	case SHMDT:
+		return sys_shmdt ((char __user *)ptr);
+	case SHMGET:
+		return sys_shmget (first, second, third);
+	case SHMCTL:
+		return sys_shmctl (first, second,
+				   (struct shmid_ds __user *) ptr);
+	default:
+		return -ENOSYS;
+	}
+}
+
+asmlinkage int sys_uname(struct old_utsname * name)
+{
+	int err;
+	if (!name)
+		return -EFAULT;
+	down_read(&uts_sem);
+	err=copy_to_user(name, &system_utsname, sizeof (*name));
+	up_read(&uts_sem);
+	return err?-EFAULT:0;
+}
+
+asmlinkage int sys_cacheflush(void *addr, int bytes, int cache)
+{
+	/* This should flush more selectivly ...  */
+	_flush_cache_all();
+	return 0;
+}
+
+asmlinkage int sys_cachectl(char *addr, int nbytes, int op)
+{
+	/* Not implemented yet. */
+	return -ENOSYS;
+}
+
diff -Nru a/arch/m32r/kernel/time.c b/arch/m32r/kernel/time.c
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/arch/m32r/kernel/time.c	2004-10-18 14:57:24 -07:00
@@ -0,0 +1,317 @@
+/*
+ *  linux/arch/m32r/kernel/time.c
+ *
+ *  Copyright (c) 2001, 2002  Hiroyuki Kondo, Hirokazu Takata,
+ *                            Hitoshi Yamamoto
+ *  Taken from i386 version.
+ *    Copyright (C) 1991, 1992, 1995  Linus Torvalds
+ *    Copyright (C) 1996, 1997, 1998  Ralf Baechle
+ *
+ *  This file contains the time handling details for PC-style clocks as
+ *  found in some MIPS systems.
+ *
+ *  Some code taken from sh version.
+ *    Copyright (C) 1999  Tetsuya Okada & Niibe Yutaka
+ *    Copyright (C) 2000  Philipp Rumpf <prumpf@tux.org>
+ */
+
+#undef  DEBUG_TIMER
+
+#include <linux/config.h>
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/sched.h>
+#include <linux/kernel.h>
+#include <linux/param.h>
+#include <linux/string.h>
+#include <linux/mm.h>
+#include <linux/interrupt.h>
+#include <linux/profile.h>
+
+#include <asm/io.h>
+#include <asm/m32r.h>
+
+#include <asm/hw_irq.h>
+
+#ifdef CONFIG_SMP
+extern void send_IPI_allbutself(int, int);
+extern void smp_local_timer_interrupt(struct pt_regs *);
+#endif
+
+u64 jiffies_64 = INITIAL_JIFFIES;
+
+EXPORT_SYMBOL(jiffies_64);
+
+extern unsigned long wall_jiffies;
+#define TICK_SIZE	(tick_nsec / 1000)
+
+/*
+ * Change this if you have some constant time drift
+ */
+
+/* This is for machines which generate the exact clock. */
+#define USECS_PER_JIFFY (1000000/HZ)
+
+static unsigned long latch;
+
+static unsigned long do_gettimeoffset(void)
+{
+	unsigned long  elapsed_time = 0;  /* [us] */
+
+#if defined(CONFIG_CHIP_M32102) || defined(CONFIG_CHIP_XNUX2) \
+	|| defined(CONFIG_CHIP_VDEC2) || defined(CONFIG_CHIP_M32700) \
+	|| defined(CONFIG_CHIP_OPSP)
+#ifndef CONFIG_SMP
+
+	unsigned long count;
+
+	/* timer count may underflow right here */
+	count = inl(M32R_MFT2CUT_PORTL);
+
+	if (inl(M32R_ICU_CR18_PORTL) & 0x00000100)	/* underflow check */
+		count = 0;
+
+	count = (latch - count) * TICK_SIZE;
+	elapsed_time = (count + latch / 2) / latch;
+	/* NOTE: LATCH is equal to the "interval" value (= reload count). */
+
+#else /* CONFIG_SMP */
+	unsigned long count;
+	static unsigned long p_jiffies = -1;
+	static unsigned long p_count = 0;
+
+	/* timer count may underflow right here */
+	count = inl(M32R_MFT2CUT_PORTL);
+
+	if (jiffies == p_jiffies && count > p_count)
+		count = 0;
+
+	p_jiffies = jiffies;
+	p_count = count;
+
+	count = (latch - count) * TICK_SIZE;
+	elapsed_time = (count + latch / 2) / latch;
+	/* NOTE: LATCH is equal to the "interval" value (= reload count). */
+#endif /* CONFIG_SMP */
+#elif defined(CONFIG_CHIP_M32310)
+#warning do_gettimeoffse not implemented
+#else
+#error no chip configuration
+#endif
+
+	return elapsed_time;
+}
+
+/*
+ * This version of gettimeofday has near microsecond resolution.
+ */
+void do_gettimeofday(struct timeval *tv)
+{
+	unsigned long seq;
+	unsigned long usec, sec;
+	unsigned long max_ntp_tick = tick_usec - tickadj;
+
+	do {
+		unsigned long lost;
+
+		seq = read_seqbegin(&xtime_lock);
+
+		usec = do_gettimeoffset();
+		lost = jiffies - wall_jiffies;
+
+		/*
+		 * If time_adjust is negative then NTP is slowing the clock
+		 * so make sure not to go into next possible interval.
+		 * Better to lose some accuracy than have time go backwards..
+		 */
+		if (unlikely(time_adjust < 0)) {
+			usec = min(usec, max_ntp_tick);
+			if (lost)
+				usec += lost * max_ntp_tick;
+		} else if (unlikely(lost))
+			usec += lost * tick_usec;
+
+		sec = xtime.tv_sec;
+		usec += (xtime.tv_nsec / 1000);
+	} while (read_seqretry(&xtime_lock, seq));
+
+	while (usec >= 1000000) {
+		usec -= 1000000;
+		sec++;
+	}
+
+	tv->tv_sec = sec;
+	tv->tv_usec = usec;
+}
+
+EXPORT_SYMBOL(do_gettimeofday);
+
+int do_settimeofday(struct timespec *tv)
+{
+	time_t wtm_sec, sec = tv->tv_sec;
+ 	long wtm_nsec, nsec = tv->tv_nsec;
+
+	if ((unsigned long)tv->tv_nsec >= NSEC_PER_SEC)
+		return -EINVAL;
+
+	write_seqlock_irq(&xtime_lock);
+	/*
+	 * This is revolting. We need to set "xtime" correctly. However, the
+	 * value in this location is the value at the most recent update of
+	 * wall time.  Discover what correction gettimeofday() would have
+	 * made, and then undo it!
+	 */
+	nsec -= do_gettimeoffset() * NSEC_PER_USEC;
+	nsec -= (jiffies - wall_jiffies) * TICK_NSEC;
+
+	wtm_sec = wall_to_monotonic.tv_sec + (xtime.tv_sec - sec);
+	wtm_nsec = wall_to_monotonic.tv_nsec + (xtime.tv_nsec - nsec);
+
+	set_normalized_timespec(&xtime, sec, nsec);
+	set_normalized_timespec(&wall_to_monotonic, wtm_sec, wtm_nsec);
+
+	time_adjust = 0;		/* stop active adjtime() */
+	time_status |= STA_UNSYNC;
+	time_maxerror = NTP_PHASE_LIMIT;
+	time_esterror = NTP_PHASE_LIMIT;
+	write_sequnlock_irq(&xtime_lock);
+	clock_was_set();
+
+	return 0;
+}
+
+EXPORT_SYMBOL(do_settimeofday);
+
+/*
+ * In order to set the CMOS clock precisely, set_rtc_mmss has to be
+ * called 500 ms after the second nowtime has started, because when
+ * nowtime is written into the registers of the CMOS clock, it will
+ * jump to the next second precisely 500 ms later. Check the Motorola
+ * MC146818A or Dallas DS12887 data sheet for details.
+ *
+ * BUG: This routine does not handle hour overflow properly; it just
+ *      sets the minutes. Usually you won't notice until after reboot!
+ */
+static __inline__ int set_rtc_mmss(unsigned long nowtime)
+{
+	return 0;
+}
+
+/* last time the cmos clock got updated */
+static long last_rtc_update = 0;
+
+/*
+ * timer_interrupt() needs to keep up the real-time clock,
+ * as well as call the "do_timer()" routine every clocktick
+ */
+static __inline__ void do_timer_interrupt(int irq, void *dev_id,
+	struct pt_regs * regs)
+{
+	do_timer(regs);
+
+	/*
+	 * If we have an externally synchronized Linux clock, then update
+	 * CMOS clock accordingly every ~11 minutes. Set_rtc_mmss() has to be
+	 * called as close as possible to 500 ms before the new second starts.
+	 */
+	if ((time_status & STA_UNSYNC) == 0
+		&& xtime.tv_sec > last_rtc_update + 660
+		&& (xtime.tv_nsec / 1000) >= 500000 - ((unsigned)TICK_SIZE) / 2
+		&& (xtime.tv_nsec / 1000) <= 500000 + ((unsigned)TICK_SIZE) / 2)
+	{
+		if (set_rtc_mmss(xtime.tv_sec) == 0)
+			last_rtc_update = xtime.tv_sec;
+		else	/* do it again in 60 s */
+			last_rtc_update = xtime.tv_sec - 600;
+	}
+	/* As we return to user mode fire off the other CPU schedulers..
+	   this is basically because we don't yet share IRQ's around.
+	   This message is rigged to be safe on the 386 - basically it's
+	   a hack, so don't look closely for now.. */
+
+#ifdef CONFIG_SMP
+	smp_local_timer_interrupt(regs);
+#endif
+}
+
+irqreturn_t timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+{
+	write_seqlock(&xtime_lock);
+	do_timer_interrupt(irq, NULL, regs);
+	write_sequnlock(&xtime_lock);
+
+#ifndef CONFIG_SMP
+	profile_tick(CPU_PROFILING, regs);
+#endif
+
+	return IRQ_HANDLED;
+}
+
+struct irqaction irq0 = { timer_interrupt, SA_INTERRUPT, CPU_MASK_NONE,
+			  "MFT2", NULL, NULL };
+
+void __init time_init(void)
+{
+	unsigned int epoch, year, mon, day, hour, min, sec;
+
+	sec = min = hour = day = mon = year = 0;
+	epoch = 0;
+
+	year = 23;
+	mon = 4;
+	day = 17;
+
+	/* Attempt to guess the epoch.  This is the same heuristic as in rtc.c
+	   so no stupid things will happen to timekeeping.  Who knows, maybe
+	   Ultrix also uses 1952 as epoch ...  */
+	if (year > 10 && year < 44)
+		epoch = 1980;
+	else if (year < 96)
+		epoch = 1952;
+	year += epoch;
+
+	xtime.tv_sec = mktime(year, mon, day, hour, min, sec);
+	xtime.tv_nsec = (INITIAL_JIFFIES % HZ) * (NSEC_PER_SEC / HZ);
+	wall_to_monotonic.tv_sec = -xtime.tv_sec;
+	wall_to_monotonic.tv_nsec = -xtime.tv_nsec;
+
+#if defined(CONFIG_CHIP_M32102) || defined(CONFIG_CHIP_XNUX2) \
+	|| defined(CONFIG_CHIP_VDEC2) || defined(CONFIG_CHIP_M32700) \
+	|| defined(CONFIG_CHIP_OPSP)
+
+	/* M32102 MFT setup */
+	setup_irq(M32R_IRQ_MFT2, &irq0);
+	{
+		unsigned long bus_clock;
+		unsigned short divide;
+
+		bus_clock = boot_cpu_data.bus_clock;
+		divide = boot_cpu_data.timer_divide;
+		latch = (bus_clock/divide + HZ / 2) / HZ;
+
+		printk("Timer start : latch = %ld\n", latch);
+
+		outl((M32R_MFTMOD_CC_MASK | M32R_MFTMOD_TCCR \
+			|M32R_MFTMOD_CSSEL011), M32R_MFT2MOD_PORTL);
+		outl(latch, M32R_MFT2RLD_PORTL);
+		outl(latch, M32R_MFT2CUT_PORTL);
+		outl(0, M32R_MFT2CMPRLD_PORTL);
+		outl((M32R_MFTCR_MFT2MSK|M32R_MFTCR_MFT2EN), M32R_MFTCR_PORTL);
+	}
+
+#elif defined(CONFIG_CHIP_M32310)
+#warning time_init not implemented
+#else
+#error no chip configuration
+#endif
+}
+
+/*
+ *  Scheduler clock - returns current time in nanosec units.
+ */
+unsigned long long sched_clock(void)
+{
+	return (unsigned long long)jiffies * (1000000000 / HZ);
+}
+
diff -Nru a/arch/m32r/kernel/traps.c b/arch/m32r/kernel/traps.c
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/arch/m32r/kernel/traps.c	2004-10-18 14:57:23 -07:00
@@ -0,0 +1,330 @@
+/*
+ *  linux/arch/m32r/kernel/traps.c
+ *
+ *  Copyright (C) 2001, 2002  Hirokazu Takata, Hiroyuki Kondo,
+ *                            Hitoshi Yamamoto
+ */
+
+/* $Id$ */
+
+/*
+ * 'traps.c' handles hardware traps and faults after we have saved some
+ * state in 'entry.S'.
+ */
+#include <linux/config.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/kallsyms.h>
+#include <linux/stddef.h>
+#include <linux/ptrace.h>
+#include <linux/mm.h>
+#include <asm/page.h>
+#include <asm/processor.h>
+
+#include <asm/system.h>
+#include <asm/uaccess.h>
+#include <asm/io.h>
+#include <asm/atomic.h>
+
+#include <asm/smp.h>
+
+#include <linux/module.h>
+
+asmlinkage void alignment_check(void);
+asmlinkage void ei_handler(void);
+asmlinkage void rie_handler(void);
+asmlinkage void debug_trap(void);
+asmlinkage void cache_flushing_handler(void);
+
+#ifdef CONFIG_SMP
+extern void smp_reschedule_interrupt(void);
+extern void smp_invalidate_interrupt(void);
+extern void smp_call_function_interrupt(void);
+extern void smp_ipi_timer_interrupt(void);
+extern void smp_flush_cache_all_interrupt(void);
+
+/*
+ * for Boot AP function
+ */
+asm (
+	"	.section .eit_vector4,\"ax\"	\n"
+	"	.global _AP_RE			\n"
+	"	.global startup_AP		\n"
+	"_AP_RE:				\n"
+	"	.fill 32, 4, 0			\n"
+	"_AP_EI: bra	startup_AP		\n"
+	"	.previous			\n"
+);
+#endif  /* CONFIG_SMP */
+
+extern unsigned long	eit_vector[];
+#define BRA_INSN(func, entry)	\
+	((unsigned long)func - (unsigned long)eit_vector - entry*4)/4 \
+	+ 0xff000000UL
+
+void	set_eit_vector_entries(void)
+{
+	extern void default_eit_handler(void);
+	extern void system_call(void);
+	extern void pie_handler(void);
+	extern void ace_handler(void);
+	extern void tme_handler(void);
+	extern void _flush_cache_copyback_all(void);
+
+	eit_vector[0] = 0xd0c00001; /* seth r0, 0x01 */
+	eit_vector[1] = BRA_INSN(default_eit_handler, 1);
+	eit_vector[4] = 0xd0c00010; /* seth r0, 0x10 */
+	eit_vector[5] = BRA_INSN(default_eit_handler, 5);
+	eit_vector[8] = BRA_INSN(rie_handler, 8);
+	eit_vector[12] = BRA_INSN(alignment_check, 12);
+	eit_vector[16] = 0xff000000UL;
+	eit_vector[17] = BRA_INSN(debug_trap, 17);
+	eit_vector[18] = BRA_INSN(system_call, 18);
+	eit_vector[19] = 0xff000000UL;
+	eit_vector[20] = 0xff000000UL;
+	eit_vector[21] = 0xff000000UL;
+	eit_vector[22] = 0xff000000UL;
+	eit_vector[23] = 0xff000000UL;
+	eit_vector[24] = 0xff000000UL;
+	eit_vector[25] = 0xff000000UL;
+	eit_vector[26] = 0xff000000UL;
+	eit_vector[27] = 0xff000000UL;
+	eit_vector[28] = BRA_INSN(cache_flushing_handler, 28);
+	eit_vector[29] = 0xff000000UL;
+	eit_vector[30] = 0xff000000UL;
+	eit_vector[31] = 0xff000000UL;
+	eit_vector[32] = BRA_INSN(ei_handler, 32);
+	eit_vector[64] = BRA_INSN(pie_handler, 64);
+	eit_vector[68] = BRA_INSN(ace_handler, 68);
+	eit_vector[72] = BRA_INSN(tme_handler, 72);
+#ifdef CONFIG_SMP
+	eit_vector[184] = (unsigned long)smp_reschedule_interrupt;
+	eit_vector[185] = (unsigned long)smp_invalidate_interrupt;
+	eit_vector[186] = (unsigned long)smp_call_function_interrupt;
+	eit_vector[187] = (unsigned long)smp_ipi_timer_interrupt;
+	eit_vector[188] = (unsigned long)smp_flush_cache_all_interrupt;
+	eit_vector[189] = 0;
+	eit_vector[190] = 0;
+	eit_vector[191] = 0;
+#endif
+	_flush_cache_copyback_all();
+}
+
+void __init trap_init(void)
+{
+	set_eit_vector_entries();
+
+	/*
+	 * Should be a barrier for any external CPU state.
+	 */
+	cpu_init();
+}
+
+int kstack_depth_to_print = 24;
+
+void show_trace(struct task_struct *task, unsigned long *stack)
+{
+	unsigned long addr;
+
+	if (!stack)
+		stack = (unsigned long*)&stack;
+
+	printk("Call Trace: ");
+	while (!kstack_end(stack)) {
+		addr = *stack++;
+		if (__kernel_text_address(addr)) {
+			printk("[<%08lx>] ", addr);
+			print_symbol("%s\n", addr);
+		}
+	}
+	printk("\n");
+}
+
+void show_stack(struct task_struct *task, unsigned long *sp)
+{
+	unsigned long  *stack;
+	int  i;
+
+	/*
+	 * debugging aid: "show_stack(NULL);" prints the
+	 * back trace for this cpu.
+	 */
+
+	if(sp==NULL) {
+		if (task)
+			sp = (unsigned long *)task->thread.sp;
+		else
+			sp=(unsigned long*)&sp;
+	}
+
+	stack = sp;
+	for(i=0; i < kstack_depth_to_print; i++) {
+		if (kstack_end(stack))
+			break;
+		if (i && ((i % 4) == 0))
+			printk("\n       ");
+		printk("%08lx ", *stack++);
+	}
+	printk("\n");
+	show_trace(task, sp);
+}
+
+void dump_stack(void)
+{
+	unsigned long stack;
+
+	show_trace(current, &stack);
+}
+
+EXPORT_SYMBOL(dump_stack);
+
+static void show_registers(struct pt_regs *regs)
+{
+	int i = 0;
+	int in_kernel = 1;
+	unsigned long sp;
+
+	printk("CPU:    %d\n", smp_processor_id());
+	show_regs(regs);
+
+	sp = (unsigned long) (1+regs);
+	if (user_mode(regs)) {
+		in_kernel = 0;
+		sp = regs->spu;
+		printk("SPU: %08lx\n", sp);
+	} else {
+		printk("SPI: %08lx\n", sp);
+	}
+	printk("Process %s (pid: %d, process nr: %d, stackpage=%08lx)",
+		current->comm, current->pid, 0xffff & i, 4096+(unsigned long)current);
+
+	/*
+	 * When in-kernel, we also print out the stack and code at the
+	 * time of the fault..
+	 */
+	if (in_kernel) {
+		printk("\nStack: ");
+		show_stack(current, (unsigned long*) sp);
+
+		printk("\nCode: ");
+		if (regs->bpc < PAGE_OFFSET)
+			goto bad;
+
+		for(i=0;i<20;i++) {
+			unsigned char c;
+			if (__get_user(c, &((unsigned char*)regs->bpc)[i])) {
+bad:
+				printk(" Bad PC value.");
+				break;
+			}
+			printk("%02x ", c);
+		}
+	}
+	printk("\n");
+}
+
+spinlock_t die_lock = SPIN_LOCK_UNLOCKED;
+
+void die(const char * str, struct pt_regs * regs, long err)
+{
+	console_verbose();
+	spin_lock_irq(&die_lock);
+	bust_spinlocks(1);
+	printk("%s: %04lx\n", str, err & 0xffff);
+	show_registers(regs);
+	bust_spinlocks(0);
+	spin_unlock_irq(&die_lock);
+	do_exit(SIGSEGV);
+}
+
+static __inline__ void die_if_kernel(const char * str,
+	struct pt_regs * regs, long err)
+{
+	if (!user_mode(regs))
+		die(str, regs, err);
+}
+
+static __inline__ void do_trap(int trapnr, int signr, const char * str,
+	struct pt_regs * regs, long error_code, siginfo_t *info)
+{
+	if (user_mode(regs)) {
+		/* trap_signal */
+		struct task_struct *tsk = current;
+		tsk->thread.error_code = error_code;
+		tsk->thread.trap_no = trapnr;
+		if (info)
+			force_sig_info(signr, info, tsk);
+		else
+			force_sig(signr, tsk);
+		return;
+	} else {
+		/* kernel_trap */
+		if (!fixup_exception(regs))
+			die(str, regs, error_code);
+		return;
+	}
+}
+
+#define DO_ERROR(trapnr, signr, str, name) \
+asmlinkage void do_##name(struct pt_regs * regs, long error_code) \
+{ \
+	do_trap(trapnr, signr, 0, regs, error_code, NULL); \
+}
+
+#define DO_ERROR_INFO(trapnr, signr, str, name, sicode, siaddr) \
+asmlinkage void do_##name(struct pt_regs * regs, long error_code) \
+{ \
+	siginfo_t info; \
+	info.si_signo = signr; \
+	info.si_errno = 0; \
+	info.si_code = sicode; \
+	info.si_addr = (void __user *)siaddr; \
+	do_trap(trapnr, signr, str, regs, error_code, &info); \
+}
+
+DO_ERROR( 1, SIGTRAP, "debug trap", debug_trap)
+DO_ERROR_INFO(0x20, SIGILL,  "reserved instruction ", rie_handler, ILL_ILLOPC, regs->bpc)
+DO_ERROR_INFO(0x100, SIGILL,  "privilege instruction", pie_handler, ILL_PRVOPC, regs->bpc)
+
+extern int handle_unaligned_access(unsigned long, struct pt_regs *);
+
+/* This code taken from arch/sh/kernel/traps.c */
+asmlinkage void do_alignment_check(struct pt_regs *regs, long error_code)
+{
+	mm_segment_t oldfs;
+	unsigned long insn;
+	int tmp;
+
+	oldfs = get_fs();
+
+	if (user_mode(regs)) {
+		local_irq_enable();
+		current->thread.error_code = error_code;
+		current->thread.trap_no = 0x17;
+
+		set_fs(USER_DS);
+		if (copy_from_user(&insn, (void *)regs->bpc, 4)) {
+			set_fs(oldfs);
+			goto uspace_segv;
+		}
+		tmp = handle_unaligned_access(insn, regs);
+		set_fs(oldfs);
+
+		if (!tmp)
+			return;
+
+	uspace_segv:
+		printk(KERN_NOTICE "Killing process \"%s\" due to unaligned "
+			"access\n", current->comm);
+		force_sig(SIGSEGV, current);
+	} else {
+		set_fs(KERNEL_DS);
+		if (copy_from_user(&insn, (void *)regs->bpc, 4)) {
+			set_fs(oldfs);
+			die("insn faulting in do_address_error", regs, 0);
+		}
+		handle_unaligned_access(insn, regs);
+		set_fs(oldfs);
+	}
+}
+
diff -Nru a/arch/m32r/kernel/vmlinux.lds.S b/arch/m32r/kernel/vmlinux.lds.S
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/arch/m32r/kernel/vmlinux.lds.S	2004-10-18 14:57:22 -07:00
@@ -0,0 +1,143 @@
+/* ld script to make M32R Linux kernel
+ */
+
+#include <linux/config.h>
+#include <asm-generic/vmlinux.lds.h>
+#include <asm/addrspace.h>
+#include <asm/page.h>
+
+OUTPUT_ARCH(m32r)
+ENTRY(startup_32)
+#if defined(__LITTLE_ENDIAN__)
+       jiffies = jiffies_64;
+#else
+       jiffies = jiffies_64 + 4;
+#endif
+SECTIONS
+{
+  . = CONFIG_MEMORY_START + __PAGE_OFFSET;
+  eit_vector = .;
+
+  . = . + 0x1000;
+  .empty_zero_page : { *(.empty_zero_page) } = 0
+
+  /* read-only */
+  _text = .;			/* Text and read-only data */
+  .boot : { *(.boot) } = 0
+  .text : {
+	*(.text)
+	SCHED_TEXT
+	LOCK_TEXT
+	*(.fixup)
+	*(.gnu.warning)
+	} = 0x9090
+#ifdef CONFIG_SMP
+  . = ALIGN(65536);
+  .eit_vector4 : { *(.eit_vector4) }
+#endif
+  _etext = .;			/* End of text section */
+
+  . = ALIGN(16);		/* Exception table */
+  __start___ex_table = .;
+  __ex_table : { *(__ex_table) }
+  __stop___ex_table = .;
+
+  RODATA
+
+  /* writeable */
+  .data : {			/* Data */
+	*(.spu)
+	*(.spi)
+	*(.data)
+	CONSTRUCTORS
+	}
+
+  . = ALIGN(4096);
+  __nosave_begin = .;
+  .data_nosave : { *(.data.nosave) }
+  . = ALIGN(4096);
+  __nosave_end = .;
+
+  . = ALIGN(4096);
+  .data.page_aligned : { *(.data.idt) }
+
+  . = ALIGN(32);
+  .data.cacheline_aligned : { *(.data.cacheline_aligned) }
+
+  _edata = .;			/* End of data section */
+
+  . = ALIGN(8192);		/* init_task */
+  .data.init_task : { *(.data.init_task) }
+
+  /* will be freed after init */
+  . = ALIGN(4096);		/* Init code and data */
+  __init_begin = .;
+  .init.text : {
+	_sinittext = .;
+	*(.init.text)
+	_einittext = .;
+  }
+  .init.data : { *(.init.data) }
+  . = ALIGN(16);
+  __setup_start = .;
+  .init.setup : { *(.init.setup) }
+  __setup_end = .;
+  __initcall_start = .;
+  .initcall.init : {
+	*(.initcall1.init)
+	*(.initcall2.init)
+	*(.initcall3.init)
+	*(.initcall4.init)
+	*(.initcall5.init)
+	*(.initcall6.init)
+	*(.initcall7.init)
+  }
+  __initcall_end = .;
+  __con_initcall_start = .;
+  .con_initcall.init : { *(.con_initcall.init) }
+  __con_initcall_end = .;
+  SECURITY_INIT
+  . = ALIGN(4);
+  __alt_instructions = .;
+  .altinstructions : { *(.altinstructions) }
+  __alt_instructions_end = .;
+  .altinstr_replacement : { *(.altinstr_replacement) }
+  /* .exit.text is discard at runtime, not link time, to deal with references
+     from .altinstructions and .eh_frame */
+  .exit.text : { *(.exit.text) }
+  .exit.data : { *(.exit.data) }
+  . = ALIGN(4096);
+  __initramfs_start = .;
+  .init.ramfs : { *(.init.ramfs) }
+  __initramfs_end = .;
+  . = ALIGN(32);
+  __per_cpu_start = .;
+  .data.percpu  : { *(.data.percpu) }
+  __per_cpu_end = .;
+  . = ALIGN(4096);
+  __init_end = .;
+  /* freed after init ends here */
+
+  __bss_start = .;		/* BSS */
+  .bss : { *(.bss) }
+  . = ALIGN(4);
+  __bss_stop = .;
+
+  _end = . ;
+
+  /* Sections to be discarded */
+  /DISCARD/ : {
+	*(.exit.text)
+	*(.exit.data)
+	*(.exitcall.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) }
+  .comment 0 : { *(.comment) }
+}
diff -Nru a/arch/m32r/lib/Makefile b/arch/m32r/lib/Makefile
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/arch/m32r/lib/Makefile	2004-10-18 14:57:23 -07:00
@@ -0,0 +1,7 @@
+#
+# Makefile for M32R-specific library files..
+#
+
+lib-y  := checksum.o ashxdi3.o memset.o memcpy.o getuser.o \
+	  putuser.o delay.o strlen.o usercopy.o csum_partial_copy.o
+
diff -Nru a/arch/m32r/lib/ashxdi3.S b/arch/m32r/lib/ashxdi3.S
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/arch/m32r/lib/ashxdi3.S	2004-10-18 14:57:23 -07:00
@@ -0,0 +1,297 @@
+/*
+ * linux/arch/m32r/lib/ashxdi3.S
+ *
+ * Copyright (C) 2001,2002  Hiroyuki Kondo, and Hirokazu Takata
+ *
+ */
+/* $Id$ */
+
+#include <linux/config.h>
+
+;
+;      input   (r0,r1)  src
+;      input    r2      shift val
+;               r3      scratch
+;      output  (r0,r1)
+;
+
+#ifdef CONFIG_ISA_DUAL_ISSUE
+
+#ifndef __LITTLE_ENDIAN__
+
+	.text
+	.align	4
+	.globl __ashrdi3
+__ashrdi3:
+	cmpz	r2		    ||	ldi	r3, #32
+	jc	r14		    ||	cmpu	r2, r3
+	bc      1f
+    ;   case 32 =< shift
+	mv      r1, r0		    ||	srai    r0, #31
+	addi    r2, #-32
+	sra     r1, r2
+	jmp     r14
+	.fillinsn
+1:  ;   case shift <32
+	mv      r3, r0		    ||	srl     r1, r2
+	sra     r0, r2		    ||	neg     r2, r2
+	sll     r3, r2
+	or      r1, r3		    ||	jmp	r14
+
+        .align  4
+        .globl __ashldi3
+        .globl __lshldi3
+__ashldi3:
+__lshldi3:
+	cmpz	r2		    ||	ldi	r3, #32
+	jc	r14		    ||	cmpu	r2, r3
+	bc      1f
+    ;   case 32 =< shift
+	mv      r0, r1		    ||	addi    r2, #-32
+	sll     r0, r2		    ||	ldi     r1, #0
+	jmp     r14
+	.fillinsn
+1:  ;   case shift <32
+	mv      r3, r1		    ||	sll     r0, r2
+	sll     r1, r2		    ||	neg     r2, r2
+	srl     r3, r2
+	or      r0, r3		    ||	jmp	r14
+
+	.align	4
+	.globl __lshrdi3
+__lshrdi3:
+	cmpz	r2		    ||	ldi	r3, #32
+	jc	r14		    ||	cmpu	r2, r3
+	bc      1f
+    ;   case 32 =< shift
+	mv      r1, r0		    ||	addi    r2, #-32
+	ldi	r0, #0		    ||	srl     r1, r2
+	jmp     r14
+	.fillinsn
+1:  ;   case shift <32
+	mv      r3, r0		    ||	srl     r1, r2
+	srl     r0, r2		    ||	neg     r2, r2
+	sll     r3, r2
+	or      r1, r3		    ||	jmp	r14
+
+#else /* LITTLE_ENDIAN */
+
+	.text
+	.align	4
+	.globl __ashrdi3
+__ashrdi3:
+	cmpz	r2		    ||	ldi	r3, #32
+	jc	r14		    ||	cmpu	r2, r3
+	bc      1f
+    ;   case 32 =< shift
+	mv      r0, r1		    ||	srai    r1, #31
+	addi    r2, #-32
+	sra     r0, r2
+	jmp     r14
+	.fillinsn
+1:  ;   case shift <32
+	mv      r3, r1		    ||	srl     r0, r2
+	sra     r1, r2		    ||	neg     r2, r2
+	sll     r3, r2
+	or      r0, r3		    ||	jmp	r14
+
+        .align  4
+        .globl __ashldi3
+        .globl __lshldi3
+__ashldi3:
+__lshldi3:
+	cmpz	r2		    ||	ldi	r3, #32
+	jc	r14		    ||	cmpu	r2, r3
+	bc      1f
+    ;   case 32 =< shift
+	mv      r1, r0		    ||	addi    r2, #-32
+	sll     r1, r2		    ||	ldi     r0, #0
+	jmp     r14
+	.fillinsn
+1:  ;   case shift <32
+	mv      r3, r0		    ||	sll     r1, r2
+	sll     r0, r2		    ||	neg     r2, r2
+	srl     r3, r2
+	or      r1, r3		    ||	jmp	r14
+
+	.align	4
+	.globl __lshrdi3
+__lshrdi3:
+	cmpz	r2		    ||	ldi	r3, #32
+	jc	r14		    ||	cmpu	r2, r3
+	bc      1f
+    ;   case 32 =< shift
+	mv      r0, r1		    ||	addi    r2, #-32
+	ldi	r1, #0		    ||	srl     r0, r2
+	jmp     r14
+	.fillinsn
+1:  ;   case shift <32
+	mv      r3, r1		    ||	srl     r0, r2
+	srl     r1, r2		    ||	neg     r2, r2
+	sll     r3, r2
+	or      r0, r3		    ||	jmp	r14
+
+#endif
+
+#else /* not CONFIG_ISA_DUAL_ISSUE */
+
+#ifndef __LITTLE_ENDIAN__
+
+	.text
+	.align	4
+	.globl __ashrdi3
+__ashrdi3:
+	beqz	r2, 2f
+	cmpui   r2, #32
+	bc      1f
+    ;   case 32 =< shift
+	mv      r1, r0
+	srai    r0, #31
+	addi    r2, #-32
+	sra     r1, r2
+	jmp     r14
+	.fillinsn
+1:  ;   case shift <32
+	mv      r3, r0
+	srl     r1, r2
+	sra     r0, r2
+	neg     r2, r2
+	sll     r3, r2
+	or      r1, r3
+	.fillinsn
+2:
+	jmp	r14
+
+        .align  4
+        .globl __ashldi3
+        .globl __lshldi3
+__ashldi3:
+__lshldi3:
+	beqz	r2, 2f
+	cmpui   r2, #32
+	bc      1f
+    ;   case 32 =< shift
+	mv      r0, r1
+	addi    r2, #-32
+	sll     r0, r2
+	ldi     r1, #0
+	jmp     r14
+	.fillinsn
+1:  ;   case shift <32
+	mv      r3, r1
+	sll     r0, r2
+	sll     r1, r2
+	neg     r2, r2
+	srl     r3, r2
+	or      r0, r3
+	.fillinsn
+2:
+	jmp	r14
+
+	.align	4
+	.globl __lshrdi3
+__lshrdi3:
+	beqz	r2, 2f
+	cmpui   r2, #32
+	bc      1f
+    ;   case 32 =< shift
+	mv      r1, r0
+	ldi	r0, #0
+	addi    r2, #-32
+	srl     r1, r2
+	jmp     r14
+	.fillinsn
+1:  ;   case shift <32
+	mv      r3, r0
+	srl     r1, r2
+	srl     r0, r2
+	neg     r2, r2
+	sll     r3, r2
+	or      r1, r3
+	.fillinsn
+2:
+	jmp	r14
+
+#else
+
+	.text
+	.align	4
+	.globl __ashrdi3
+__ashrdi3:
+	beqz	r2, 2f
+	cmpui   r2, #32
+	bc      1f
+    ;   case 32 =< shift
+	mv      r0, r1
+	srai    r1, #31
+	addi    r2, #-32
+	sra     r0, r2
+	jmp     r14
+	.fillinsn
+1:  ;   case shift <32
+	mv      r3, r1
+	srl     r0, r2
+	sra     r1, r2
+	neg     r2, r2
+	sll     r3, r2
+	or      r0, r3
+	.fillinsn
+2:
+	jmp	r14
+
+        .align  4
+        .globl __ashldi3
+        .globl __lshldi3
+__ashldi3:
+__lshldi3:
+	beqz	r2, 2f
+	cmpui   r2, #32
+	bc      1f
+    ;   case 32 =< shift
+	mv      r1, r0
+	addi    r2, #-32
+	sll     r1, r2
+	ldi     r0, #0
+	jmp     r14
+	.fillinsn
+1:  ;   case shift <32
+	mv      r3, r0
+	sll     r1, r2
+	sll     r0, r2
+	neg     r2, r2
+	srl     r3, r2
+	or      r1, r3
+	.fillinsn
+2:
+	jmp	r14
+
+	.align	4
+	.globl __lshrdi3
+__lshrdi3:
+	beqz	r2, 2f
+	cmpui   r2, #32
+	bc      1f
+    ;   case 32 =< shift
+	mv      r0, r1
+	ldi	r1, #0
+	addi    r2, #-32
+	srl     r0, r2
+	jmp     r14
+	.fillinsn
+1:  ;   case shift <32
+	mv      r3, r1
+	srl     r0, r2
+	srl     r1, r2
+	neg     r2, r2
+	sll     r3, r2
+	or      r0, r3
+	.fillinsn
+2:
+	jmp	r14
+
+#endif
+
+#endif /* not CONFIG_ISA_DUAL_ISSUE */
+
+	.end
+
diff -Nru a/arch/m32r/lib/checksum.S b/arch/m32r/lib/checksum.S
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/arch/m32r/lib/checksum.S	2004-10-18 14:57:24 -07:00
@@ -0,0 +1,322 @@
+/*
+ * INET		An implementation of the TCP/IP protocol suite for the LINUX
+ *		operating system.  INET is implemented using the  BSD Socket
+ *		interface as the means of communication with the user level.
+ *
+ *		IP/TCP/UDP checksumming routines
+ *
+ * Authors:	Jorge Cwik, <jorge@laser.satlink.net>
+ *		Arnt Gulbrandsen, <agulbra@nvg.unit.no>
+ *		Tom May, <ftom@netcom.com>
+ *              Pentium Pro/II routines:
+ *              Alexander Kjeldaas <astor@guardian.no>
+ *              Finn Arne Gangstad <finnag@guardian.no>
+ *		Lots of code moved from tcp.c and ip.c; see those files
+ *		for more names.
+ *
+ * Changes:     Ingo Molnar, converted csum_partial_copy() to 2.1 exception
+ *			     handling.
+ *		Andi Kleen,  add zeroing on error
+ *                   converted to pure assembler
+ *		Hirokazu Takata,Hiroyuki Kondo rewrite for the m32r architecture.
+ *
+ *		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.
+ */
+/* $Id$ */
+
+
+#include <linux/config.h>
+#include <linux/linkage.h>
+#include <asm/assembler.h>
+#include <asm/errno.h>
+
+/*
+ * computes a partial checksum, e.g. for TCP/UDP fragments
+ */
+
+/*
+unsigned int csum_partial(const unsigned char * buff, int len, unsigned int sum)
+ */
+
+
+#ifdef CONFIG_ISA_DUAL_ISSUE
+
+	/*
+	 * Experiments with Ethernet and SLIP connections show that buff
+	 * is aligned on either a 2-byte or 4-byte boundary.  We get at
+	 * least a twofold speedup on 486 and Pentium if it is 4-byte aligned.
+	 * Fortunately, it is easy to convert 2-byte alignment to 4-byte
+	 * alignment for the unrolled loop.
+	 */
+
+	.text
+ENTRY(csum_partial)
+	; Function args
+	;  r0: unsigned char *buff
+	;  r1: int len
+	;  r2: unsigned int sum
+
+	push	r2		    ||	ldi	r2, #0
+	and3	r7, r0, #1		; Check alignment.
+	beqz	r7, 1f	 		; Jump if alignment is ok.
+	; 1-byte mis aligned
+	ldub	r4, @r0		    ||	addi	r0, #1
+	; clear c-bit || Alignment uses up bytes.
+	cmp	r0, r0		    ||	addi	r1, #-1
+	ldi	r3, #0		    ||	addx	r2, r4
+	addx	r2, r3
+	.fillinsn
+1:
+	and3	r4, r0, #2		; Check alignment.
+	beqz	r4, 2f	 		; Jump if alignment is ok.
+	; clear c-bit || Alignment uses up two bytes.
+	cmp	r0, r0		    ||	addi	r1, #-2
+	bgtz	r1, 1f			; Jump if we had at least two bytes.
+	bra	4f		    ||	addi	r1, #2
+	.fillinsn			; len(r1) was < 2.  Deal with it.
+1:
+	; 2-byte aligned
+	lduh	r4, @r0		    ||	ldi	r3, #0
+	addx	r2, r4		    ||	addi	r0, #2
+	addx	r2, r3
+	.fillinsn
+2:
+	; 4-byte aligned
+	cmp	r0, r0			; clear c-bit
+	srl3	r6, r1, #5
+	beqz	r6, 2f
+	.fillinsn
+
+1:	ld	r3, @r0+
+	ld	r4, @r0+					; +4
+	ld	r5, @r0+					; +8
+	ld	r3, @r0+	    ||	addx    r2, r3		; +12
+	ld	r4, @r0+	    ||	addx    r2, r4		; +16
+	ld	r5, @r0+	    ||	addx    r2, r5		; +20
+	ld	r3, @r0+	    ||	addx    r2, r3		; +24
+	ld	r4, @r0+	    ||	addx    r2, r4		; +28
+	addx	r2, r5		    ||	addi	r6, #-1
+	addx	r2, r3
+	addx	r2, r4
+	bnez	r6, 1b
+
+	addx	r2, r6			; r6=0
+	cmp	r0, r0			; This clears c-bit
+	.fillinsn
+2:	and3	r6, r1, #0x1c		; withdraw len
+	beqz	r6, 4f
+	srli	r6, #2
+	.fillinsn
+
+3:	ld	r4, @r0+	    ||	addi	r6, #-1
+	addx	r2, r4
+	bnez	r6, 3b
+
+	addx	r2, r6			; r6=0
+	cmp	r0, r0			; This clears c-bit
+	.fillinsn
+4:	and3	r1, r1, #3
+	beqz	r1, 7f			; if len == 0 goto end
+	and3	r6, r1, #2
+	beqz	r6, 5f			; if len < 2  goto 5f(1byte)
+	lduh	r4, @r0		    ||	addi	r0, #2
+	addi	r1, #-2		    ||	slli    r4, #16
+	addx	r2, r4
+	beqz	r1, 6f
+	.fillinsn
+5:	ldub	r4, @r0		    ||	ldi	r1, #0
+#ifndef __LITTLE_ENDIAN__
+	slli    r4, #8
+#endif
+	addx	r2, r4
+	.fillinsn
+6:	addx	r2, r1
+	.fillinsn
+7:
+	and3	r0, r2, #0xffff
+	srli	r2, #16
+	add	r0, r2
+	srl3	r2, r0, #16
+	beqz	r2, 1f
+	addi	r0, #1
+	and3	r0, r0, #0xffff
+	.fillinsn
+1:
+	beqz	r7, 1f			; swap the upper byte for the lower
+	and3	r2, r0, #0xff
+	srl3	r0, r0, #8
+	slli	r2, #8
+	or	r0, r2
+	.fillinsn
+1:
+	pop	r2		    ||	cmp	r0, r0
+	addx	r0, r2		    ||	ldi	r2, #0
+	addx	r0, r2
+	jmp	r14
+
+#else /* not CONFIG_ISA_DUAL_ISSUE */
+
+	/*
+	 * Experiments with Ethernet and SLIP connections show that buff
+	 * is aligned on either a 2-byte or 4-byte boundary.  We get at
+	 * least a twofold speedup on 486 and Pentium if it is 4-byte aligned.
+	 * Fortunately, it is easy to convert 2-byte alignment to 4-byte
+	 * alignment for the unrolled loop.
+	 */
+
+	.text
+ENTRY(csum_partial)
+	; Function args
+	;  r0: unsigned char *buff
+	;  r1: int len
+	;  r2: unsigned int sum
+
+	push	r2
+	ldi	r2, #0
+	and3	r7, r0, #1		; Check alignment.
+	beqz	r7, 1f	 		; Jump if alignment is ok.
+	; 1-byte mis aligned
+	ldub	r4, @r0
+	addi	r0, #1
+	addi	r1, #-1			; Alignment uses up bytes.
+	cmp	r0, r0			; clear c-bit
+	ldi	r3, #0
+	addx	r2, r4
+	addx	r2, r3
+	.fillinsn
+1:
+	and3	r4, r0, #2		; Check alignment.
+	beqz	r4, 2f	 		; Jump if alignment is ok.
+	addi	r1, #-2			; Alignment uses up two bytes.
+	cmp		r0, r0			; clear c-bit
+	bgtz	r1, 1f			; Jump if we had at least two bytes.
+	addi	r1, #2			; len(r1) was < 2.  Deal with it.
+	bra	4f
+	.fillinsn
+1:
+	; 2-byte aligned
+	lduh	r4, @r0
+	addi	r0, #2
+	ldi		r3, #0
+	addx	r2, r4
+	addx	r2, r3
+	.fillinsn
+2:
+	; 4-byte aligned
+	cmp	r0, r0			; clear c-bit
+	srl3	r6, r1, #5
+	beqz	r6, 2f
+	.fillinsn
+
+1:	ld	r3, @r0+
+	ld	r4, @r0+		; +4
+	ld	r5, @r0+		; +8
+	addx	r2, r3
+	addx	r2, r4
+	addx	r2, r5
+	ld	r3, @r0+		; +12
+	ld	r4, @r0+		; +16
+	ld	r5, @r0+		; +20
+	addx	r2, r3
+	addx	r2, r4
+	addx	r2, r5
+	ld	r3, @r0+		; +24
+	ld	r4, @r0+		; +28
+	addi	r6, #-1
+	addx	r2, r3
+	addx	r2, r4
+	bnez	r6, 1b
+	addx	r2, r6			; r6=0
+	cmp	r0, r0			; This clears c-bit
+	.fillinsn
+
+2:	and3	r6, r1, #0x1c		; withdraw len
+	beqz	r6, 4f
+	srli	r6, #2
+	.fillinsn
+
+3:	ld	r4, @r0+
+	addi	r6, #-1
+	addx	r2, r4
+	bnez	r6, 3b
+	addx	r2, r6			; r6=0
+	cmp	r0, r0			; This clears c-bit
+	.fillinsn
+
+4:	and3	r1, r1, #3
+	beqz	r1, 7f			; if len == 0 goto end
+	and3	r6, r1, #2
+	beqz	r6, 5f			; if len < 2  goto 5f(1byte)
+
+	lduh	r4, @r0
+	addi	r0, #2
+	addi	r1, #-2
+	slli    r4, #16
+	addx	r2, r4
+	beqz	r1, 6f
+	.fillinsn
+5:	ldub	r4, @r0
+#ifndef __LITTLE_ENDIAN__
+	slli    r4, #8
+#endif
+	addx	r2, r4
+	.fillinsn
+6:	ldi	r5, #0
+	addx	r2, r5
+	.fillinsn
+7:
+	and3	r0, r2, #0xffff
+	srli	r2, #16
+	add	r0, r2
+	srl3	r2, r0, #16
+	beqz	r2, 1f
+	addi	r0, #1
+	and3	r0, r0, #0xffff
+	.fillinsn
+1:
+	beqz	r7, 1f
+	mv	r2, r0
+	srl3	r0, r2, #8
+	and3	r2, r2, #0xff
+	slli	r2, #8
+	or	r0, r2
+	.fillinsn
+1:
+	pop	r2
+	cmp	r0, r0
+	addx	r0, r2
+	ldi	r2, #0
+	addx	r0, r2
+	jmp	r14
+
+#endif /* not CONFIG_ISA_DUAL_ISSUE */
+
+/*
+unsigned int csum_partial_copy_generic (const char *src, char *dst,
+				  int len, int sum, int *src_err_ptr, int *dst_err_ptr)
+ */
+
+/*
+ * Copy from ds while checksumming, otherwise like csum_partial
+ *
+ * The macros SRC and DST specify the type of access for the instruction.
+ * thus we can call a custom exception handler for all access types.
+ *
+ * FIXME: could someone double-check whether I haven't mixed up some SRC and
+ *	  DST definitions? It's damn hard to trigger all cases.  I hope I got
+ *	  them all but there's no guarantee.
+ */
+
+ENTRY(csum_partial_copy_generic)
+	nop
+	nop
+	nop
+	nop
+	jmp r14
+	nop
+	nop
+	nop
+
diff -Nru a/arch/m32r/lib/csum_partial_copy.c b/arch/m32r/lib/csum_partial_copy.c
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/arch/m32r/lib/csum_partial_copy.c	2004-10-18 14:57:21 -07:00
@@ -0,0 +1,58 @@
+/*
+ * INET		An implementation of the TCP/IP protocol suite for the LINUX
+ *		operating system.  INET is implemented using the  BSD Socket
+ *		interface as the means of communication with the user level.
+ *
+ *		MIPS specific IP/TCP/UDP checksumming routines
+ *
+ * Authors:	Ralf Baechle, <ralf@waldorf-gmbh.de>
+ *		Lots of code moved from tcp.c and ip.c; see those files
+ *		for more names.
+ *
+ *		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/module.h>
+#include <linux/types.h>
+
+#include <net/checksum.h>
+#include <asm/byteorder.h>
+#include <asm/string.h>
+#include <asm/uaccess.h>
+
+/*
+ * Copy while checksumming, otherwise like csum_partial
+ */
+unsigned int csum_partial_copy_nocheck (const char *src, char *dst,
+                                        int len, unsigned int sum)
+{
+	sum = csum_partial(src, len, sum);
+	memcpy(dst, src, len);
+
+	return sum;
+}
+EXPORT_SYMBOL(csum_partial_copy_nocheck);
+
+/*
+ * Copy from userspace and compute checksum.  If we catch an exception
+ * then zero the rest of the buffer.
+ */
+unsigned int csum_partial_copy_from_user (const char __user *src, char *dst,
+                                          int len, unsigned int sum,
+                                          int *err_ptr)
+{
+	int missing;
+
+	missing = copy_from_user(dst, src, len);
+	if (missing) {
+		memset(dst + len - missing, 0, missing);
+		*err_ptr = -EFAULT;
+	}
+
+	return csum_partial(dst, len-missing, sum);
+}
+EXPORT_SYMBOL(csum_partial_copy_from_user);
diff -Nru a/arch/m32r/lib/delay.c b/arch/m32r/lib/delay.c
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/arch/m32r/lib/delay.c	2004-10-18 14:57:24 -07:00
@@ -0,0 +1,126 @@
+/*
+ * linux/arch/m32r/lib/delay.c
+ *
+ * Copyright (c) 2002  Hitoshi Yamamoto, Hirokazu Takata
+ * Copyright (c) 2004  Hirokazu Takata
+ */
+
+/* $Id$ */
+
+#include <linux/config.h>
+#include <linux/param.h>
+#ifdef CONFIG_SMP
+#include <linux/sched.h>
+#include <asm/current.h>
+#include <asm/smp.h>
+#endif  /* CONFIG_SMP */
+#include <asm/processor.h>
+
+void __delay(unsigned long loops)
+{
+#ifdef CONFIG_ISA_DUAL_ISSUE
+	__asm__ __volatile__ (
+		"beqz	%0, 2f			\n\t"
+		"addi	%0, #-1			\n\t"
+
+		" .fillinsn			\n\t"
+		"1:				\n\t"
+		"cmpz	%0  ||  addi  %0, #-1	\n\t"
+		"bc	2f  ||  cmpz  %0	\n\t"
+		"bc	2f  ||  addi  %0, #-1	\n\t"
+		"cmpz	%0  ||  addi  %0, #-1	\n\t"
+		"bc	2f  ||  cmpz  %0	\n\t"
+		"bnc	1b  ||  addi  %0, #-1	\n\t"
+		" .fillinsn			\n\t"
+		"2:				\n\t"
+		: "+r" (loops)
+		: "r" (0)
+		: "cbit"
+	);
+#else
+	__asm__ __volatile__ (
+		"beqz	%0, 2f			\n\t"
+		" .fillinsn			\n\t"
+		"1:				\n\t"
+		"addi	%0, #-1			\n\t"
+		"blez	%0, 2f			\n\t"
+		"addi	%0, #-1			\n\t"
+		"blez	%0, 2f			\n\t"
+		"addi	%0, #-1			\n\t"
+		"blez	%0, 2f			\n\t"
+		"addi	%0, #-1			\n\t"
+		"bgtz	%0, 1b			\n\t"
+		" .fillinsn			\n\t"
+		"2:i				\n\t"
+		: "+r" (loops)
+		: "r" (0)
+	);
+#endif
+}
+
+void __const_udelay(unsigned long xloops)
+{
+#if defined(CONFIG_ISA_M32R2) && defined(CONFIG_ISA_DSP_LEVEL2)
+	/*
+	 * loops [1] = (xloops >> 32) [sec] * loops_per_jiffy [1/jiffy]
+	 *            * HZ [jiffy/sec]
+	 *          = (xloops >> 32) [sec] * (loops_per_jiffy * HZ) [1/sec]
+	 *          = (((xloops * loops_per_jiffy) >> 32) * HZ) [1]
+	 *
+	 * NOTE:
+	 *   - '[]' depicts variable's dimension in the above equation.
+	 *   - "rac" instruction rounds the accumulator in word size.
+	 */
+	__asm__ __volatile__ (
+		"srli	%0, #1				\n\t"
+		"mulwhi	%0, %1	; a0			\n\t"
+		"mulwu1	%0, %1	; a1			\n\t"
+		"sadd		; a0 += (a1 >> 16)	\n\t"
+		"rac	a0, a0, #1			\n\t"
+		"mvfacmi %0, a0				\n\t"
+		: "+r" (xloops)
+		: "r" (current_cpu_data.loops_per_jiffy)
+		: "a0", "a1"
+	);
+#elif defined(CONFIG_ISA_M32R2) || defined(CONFIG_ISA_M32R)
+	/*
+	 * u64 ull;
+	 * ull = (u64)xloops * (u64)current_cpu_data.loops_per_jiffy;
+	 * xloops = (ull >> 32);
+	 */
+	__asm__ __volatile__ (
+		"and3	r4, %0, #0xffff		\n\t"
+		"and3	r5, %1, #0xffff		\n\t"
+		"mul	r4, r5			\n\t"
+		"srl3	r6, %0, #16		\n\t"
+		"srli	r4, #16			\n\t"
+		"mul	r5, r6			\n\t"
+		"add	r4, r5			\n\t"
+		"and3	r5, %0, #0xffff		\n\t"
+		"srl3	r6, %1, #16		\n\t"
+		"mul	r5, r6			\n\t"
+		"add	r4, r5			\n\t"
+		"srl3	r5, %0, #16		\n\t"
+		"srli	r4, #16			\n\t"
+		"mul	r5, r6			\n\t"
+		"add	r4, r5			\n\t"
+		"mv	%0, r4			\n\t"
+		: "+r" (xloops)
+		: "r" (current_cpu_data.loops_per_jiffy)
+		: "r4", "r5", "r6"
+	);
+#else
+#error unknown isa configuration
+#endif
+	__delay(xloops * HZ);
+}
+
+void __udelay(unsigned long usecs)
+{
+	__const_udelay(usecs * 0x000010c7);  /* 2**32 / 1000000 (rounded up) */
+}
+
+void __ndelay(unsigned long nsecs)
+{
+	__const_udelay(nsecs * 0x00005);  /* 2**32 / 1000000000 (rounded up) */
+}
diff -Nru a/arch/m32r/lib/getuser.S b/arch/m32r/lib/getuser.S
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/arch/m32r/lib/getuser.S	2004-10-18 14:57:23 -07:00
@@ -0,0 +1,88 @@
+/*
+ * __get_user functions.
+ *
+ * (C) Copyright 2001 Hirokazu Takata
+ *
+ * These functions have a non-standard call interface
+ * to make them more efficient, especially as they
+ * return an error value in addition to the "real"
+ * return value.
+ */
+
+#include <linux/config.h>
+
+/*
+ * __get_user_X
+ *
+ * Inputs:	r0 contains the address
+ *
+ * Outputs:	r0 is error code (0 or -EFAULT)
+ *		r1 contains zero-extended value
+ *
+ * These functions should not modify any other registers,
+ * as they get called from within inline assembly.
+ */
+
+#ifdef CONFIG_ISA_DUAL_ISSUE
+
+	.text
+	.balign 4
+	.globl __get_user_1
+__get_user_1:
+1:	ldub	r1, @r0		    ||	ldi	r0, #0
+	jmp	r14
+
+	.balign 4
+	.globl __get_user_2
+__get_user_2:
+2:	lduh	r1, @r0		    ||	ldi	r0, #0
+	jmp	r14
+
+	.balign 4
+	.globl __get_user_4
+__get_user_4:
+3:	ld	r1, @r0		    ||	ldi	r0, #0
+	jmp	r14
+
+bad_get_user:
+	ldi	r1, #0		    ||	ldi	r0, #-14
+	jmp	r14
+
+#else /* not CONFIG_ISA_DUAL_ISSUE */
+
+	.text
+	.balign 4
+	.globl __get_user_1
+__get_user_1:
+1:	ldub	r1, @r0
+	ldi	r0, #0
+	jmp	r14
+
+	.balign 4
+	.globl __get_user_2
+__get_user_2:
+2:	lduh	r1, @r0
+	ldi	r0, #0
+	jmp	r14
+
+	.balign 4
+	.globl __get_user_4
+__get_user_4:
+3:	ld	r1, @r0
+	ldi	r0, #0
+	jmp	r14
+
+bad_get_user:
+	ldi	r1, #0
+	ldi	r0, #-14
+	jmp	r14
+
+#endif /* not CONFIG_ISA_DUAL_ISSUE */
+
+.section __ex_table,"a"
+	.long 1b,bad_get_user
+	.long 2b,bad_get_user
+	.long 3b,bad_get_user
+.previous
+
+	.end
diff -Nru a/arch/m32r/lib/memcpy.S b/arch/m32r/lib/memcpy.S
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/arch/m32r/lib/memcpy.S	2004-10-18 14:57:21 -07:00
@@ -0,0 +1,95 @@
+/*
+ *  linux/arch/m32r/lib/memcpy.S
+ *
+ *  Copyright (C) 2001  Hiroyuki Kondo, and Hirokazu Takata
+ *  Copyright (C) 2004  Hirokazu Takata
+ *
+ *  void *memcopy(void *dst, const void *src, int n);
+ *
+ *        dst: r0
+ *        src: r1
+ *        n  : r2
+ */
+/* $Id$ */
+
+
+	.text
+#include <linux/config.h>
+#include <linux/linkage.h>
+#include <asm/assembler.h>
+
+#ifdef CONFIG_ISA_DUAL_ISSUE
+
+	.text
+ENTRY(memcpy)
+memcopy:
+	mv	r4, r0		    ||	mv	r7, r0
+	or	r7, r1		    ||	cmpz	r2
+	jc	r14		    ||	cmpeq	r0, r1	; return if r2=0
+	jc	r14					; return if r0=r1
+
+	and3	r7, r7, #3
+	bnez	r7, byte_copy
+	srl3	r3, r2, #2
+	and3	r2, r2, #3
+	beqz	r3, byte_copy
+	addi	r4, #-4
+word_copy:
+	ld	r7, @r1+	    ||	addi	r3, #-1
+	st	r7, @+r4	    ||	cmpz	r2
+	bnez	r3, word_copy
+	addi	r4, #4		    ||	jc	r14	; return if r2=0
+#if defined(CONFIG_ISA_M32R2)
+byte_copy:
+	ldb	r7, @r1		    ||	addi	r1, #1
+	addi	r2, #-1		    ||	stb	r7, @r4+
+	bnez	r2, byte_copy
+#elif defined(CONFIG_ISA_M32R)
+byte_copy:
+	ldb	r7, @r1		    ||	addi	r1, #1
+	addi	r2, #-1		    ||	stb	r7, @r4
+	addi	r4, #1
+	bnez	r2, byte_copy
+#else
+#error unknown isa configuration
+#endif
+end_memcopy:
+	jmp	r14
+
+#else /* not CONFIG_ISA_DUAL_ISSUE */
+
+	.text
+ENTRY(memcpy)
+memcopy:
+	mv	r4, r0
+	mv	r7, r0
+	or	r7, r1
+	beq	r0, r1, end_memcopy
+	beqz	r2, end_memcopy
+
+	and3	r7, r7, #3
+	bnez	r7, byte_copy
+	srl3	r3, r2, #2
+	and3	r2, r2, #3
+	beqz	r3, byte_copy
+	addi	r4, #-4
+word_copy:
+	ld	r7, @r1+
+	addi	r3, #-1
+	st	r7, @+r4
+	bnez	r3, word_copy
+	beqz	r2, end_memcopy
+	addi	r4, #4
+byte_copy:
+	ldb	r7, @r1
+	addi	r1, #1
+	addi	r2, #-1
+	stb	r7, @r4
+	addi	r4, #1
+	bnez	r2, byte_copy
+end_memcopy:
+	jmp	r14
+
+#endif /* not CONFIG_ISA_DUAL_ISSUE */
+
+	.end
diff -Nru a/arch/m32r/lib/memset.S b/arch/m32r/lib/memset.S
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/arch/m32r/lib/memset.S	2004-10-18 14:57:24 -07:00
@@ -0,0 +1,178 @@
+/*
+ *  linux/arch/m32r/lib/memset.S
+ *
+ *  Copyright (C) 2001,2002  Hiroyuki Kondo, and Hirokazu Takata
+ *  Copyright (C) 2004  Hirokazu Takata
+ *
+ *  void *memset(void *dst, int val, int len);
+ *
+ *        dst: r0
+ *        val: r1
+ *        len: r2
+ *        ret: r0
+ *
+ */
+/* $Id$ */
+
+#include <linux/config.h>
+
+	.text
+	.global	memset
+
+#ifdef CONFIG_ISA_DUAL_ISSUE
+
+	.align 4
+memset:
+	mv      r4, r0		    ||	cmpz	r2
+	jc	r14
+	cmpui	r2, #16
+	bnc	qword_align_check
+	cmpui	r2, #4
+	bc	byte_set
+word_align_check:			/* len >= 4 */
+	and3	r3, r4, #3
+	beqz	r3, word_set
+	addi	r3, #-4
+	neg	r3, r3			/* r3 = -(r3 - 4) */
+align_word:
+	stb	r1, @r4		    ||	addi	r4, #1
+	addi	r2, #-1		    ||	addi	r3, #-1
+	bnez	r3, align_word
+	cmpui	r2, #4
+	bc	byte_set
+word_set:
+	and3	r1, r1, #0x00ff		/* r1: abababab <-- ??????ab */
+	sll3	r3, r1, #8
+	or	r1, r3		    ||	addi	r4, #-4
+	sll3	r3, r1, #16
+	or	r1, r3		    ||	addi	r2, #-4
+word_set_loop:
+	st	r1, @+r4	    ||	addi	r2, #-4
+	bgtz	r2, word_set_loop
+	bnez	r2, byte_set_wrap
+	st	r1, @+r4
+	jmp	r14
+
+qword_align_check:			/* len >= 16 */
+	and3	r3, r4, #15
+	bnez	r3, word_align_check
+qword_set:
+	and3	r1, r1, #0x00ff		/* r1: abababab <-- ??????ab */
+	sll3	r3, r1, #8
+	or	r1, r3		    ||	addi	r4, #-4
+	sll3	r3, r1, #16
+	or	r1, r3		    ||	ldi	r5, #16
+qword_set_loop:
+	ld	r3, @(4,r4)		/* cache line allocate */
+	st	r1, @+r4	    ||	addi	r2, #-16
+	st	r1, @+r4	    ||	cmpu	r2, r5
+	st	r1, @+r4
+	st	r1, @+r4
+	bnc	qword_set_loop	    ||  cmpz	r2
+	jc	r14
+word_set_wrap:
+	cmpui	r2, #4
+	bc	byte_set
+	addi	r2, #-4
+	bra	word_set_loop
+
+byte_set_wrap:
+	addi	r2, #4
+	addi	r4, #4		    ||  cmpz	r2
+	jc	r14
+#if defined(CONFIG_ISA_M32R2)
+byte_set:
+	addi	r2, #-1		    ||	stb	r1, @r4+
+	bnez	r2, byte_set
+#elif defined(CONFIG_ISA_M32R)
+byte_set:
+	addi	r2, #-1		    ||	stb	r1, @r4
+	addi	r4, #1
+	bnez	r2, byte_set
+#else
+#error unknown isa configuration
+#endif
+end_memset:
+	jmp	r14
+
+#else /* not CONFIG_ISA_DUAL_ISSUE */
+
+	.align 4
+memset:
+	mv      r4, r0
+	beqz	r2, end_memset
+	cmpui	r2, #16
+	bnc	qword_align_check
+	cmpui	r2, #4
+	bc	byte_set
+word_align_check:			/* len >= 4 */
+	and3	r3, r4, #3
+	beqz	r3, word_set
+	addi	r3, #-4
+	neg	r3, r3			/* r3 = -(r3 - 4) */
+align_word:
+	stb	r1, @r4
+	addi	r4, #1
+	addi	r2, #-1
+	addi	r3, #-1
+	bnez	r3, align_word
+	cmpui	r2, #4
+	bc	byte_set
+word_set:
+	and3	r1, r1, #0x00ff		/* r1: abababab <-- ??????ab */
+	sll3	r3, r1, #8
+	or	r1, r3
+	sll3	r3, r1, #16
+	or	r1, r3
+	addi	r2, #-4
+	addi	r4, #-4
+word_set_loop:
+	st	r1, @+r4
+	addi	r2, #-4
+	bgtz    r2, word_set_loop
+	bnez	r2, byte_set_wrap
+	st	r1, @+r4
+	jmp	r14
+
+qword_align_check:			/* len >= 16 */
+	and3	r3, r4, #15
+	bnez	r3, word_align_check
+qword_set:
+	and3	r1, r1, #0x00ff		/* r1: abababab <-- ??????ab */
+	sll3	r3, r1, #8
+	or	r1, r3
+	sll3	r3, r1, #16
+	or	r1, r3
+	addi	r4, #-4
+qword_set_loop:
+	ld	r3, @(4,r4)		/* cache line allocate */
+	addi	r2, #-16
+	st	r1, @+r4
+	st	r1, @+r4
+	cmpui	r2, #16
+	st	r1, @+r4
+	st	r1, @+r4
+	bnc	qword_set_loop
+	bnez	r2, word_set_wrap
+	jmp	r14
+word_set_wrap:
+	cmpui	r2, #4
+	bc	byte_set
+	addi	r2, #-4
+	bra	word_set_loop
+
+byte_set_wrap:
+	addi	r2, #4
+	addi	r4, #4
+	beqz	r2, end_memset
+byte_set:
+	addi	r2, #-1
+	stb	r1, @r4
+	addi	r4, #1
+	bnez	r2, byte_set
+end_memset:
+	jmp	r14
+
+#endif /* not CONFIG_ISA_DUAL_ISSUE */
+
+	.end
diff -Nru a/arch/m32r/lib/putuser.S b/arch/m32r/lib/putuser.S
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/arch/m32r/lib/putuser.S	2004-10-18 14:57:21 -07:00
@@ -0,0 +1,84 @@
+/*
+ * __put_user functions.
+ *
+ * (C) Copyright 1998 Linus Torvalds
+ * (C) Copyright 2001 Hirokazu Takata
+ *
+ * These functions have a non-standard call interface
+ * to make them more efficient.
+ */
+
+#include <linux/config.h>
+
+/*
+ * __put_user_X
+ *
+ * Inputs:	r0 contains the address
+ *		r1 contains the value
+ *
+ * Outputs:	r0 is error code (0 or -EFAULT)
+ *		r1 is corrupted (will contain "current_task").
+ *
+ * These functions should not modify any other registers,
+ * as they get called from within inline assembly.
+ */
+
+#ifdef CONFIG_ISA_DUAL_ISSUE
+
+	.text
+	.balign 4
+	.globl __put_user_1
+__put_user_1:
+1:	stb	r1, @r0		    ||	ldi	r0, #0
+	jmp	r14
+
+	.balign 4
+	.globl __put_user_2
+__put_user_2:
+2:	sth	r1, @r0		    ||	ldi	r0, #0
+	jmp	r14
+
+	.balign 4
+	.globl __put_user_4
+__put_user_4:
+3:	st	r1, @r0		    ||	ldi	r0, #0
+	jmp	r14
+
+bad_put_user:
+	ldi	r0, #-14	    ||	jmp	r14
+
+#else /* not CONFIG_ISA_DUAL_ISSUE */
+
+	.text
+	.balign 4
+	.globl __put_user_1
+__put_user_1:
+1:	stb	r1, @r0
+	ldi	r0, #0
+	jmp	r14
+
+	.balign 4
+	.globl __put_user_2
+__put_user_2:
+2:	sth	r1, @r0
+	ldi	r0, #0
+	jmp	r14
+
+	.balign 4
+	.globl __put_user_4
+__put_user_4:
+3:	st	r1, @r0
+	ldi	r0, #0
+	jmp	r14
+
+bad_put_user:
+	ldi	r0, #-14
+	jmp	r14
+
+#endif /* not CONFIG_ISA_DUAL_ISSUE */
+
+.section __ex_table,"a"
+	.long 1b,bad_put_user
+	.long 2b,bad_put_user
+	.long 3b,bad_put_user
+.previous
diff -Nru a/arch/m32r/lib/strlen.S b/arch/m32r/lib/strlen.S
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/arch/m32r/lib/strlen.S	2004-10-18 14:57:24 -07:00
@@ -0,0 +1,120 @@
+/*
+ *  linux/arch/m32r/strlen.S --  strlen code.
+ *
+ *  Copyright (C) 2001  Hirokazu Takata
+ *
+ *  size_t strlen(const char *s);
+ *
+ */
+/* $Id$ */
+
+
+#include <linux/config.h>
+#include <linux/linkage.h>
+#include <asm/assembler.h>
+
+#ifdef CONFIG_ISA_DUAL_ISSUE
+
+	.text
+ENTRY(strlen)
+	mv	r6, r0		    ||	ldi	r2, #0
+	and3	r0, r0, #3
+	bnez	r0, strlen_byte
+;
+strlen_word:
+	ld	r0, @r6+
+;
+	seth	r5, #high(0x01010101)
+	or3	r5, r5, #low(0x01010101)
+	sll3	r7, r5, #7
+strlen_word_loop:
+	ld	r1, @r6+	    ||	not	r4, r0
+	sub	r0, r5		    ||	and	r4, r7
+	and	r4, r0
+	bnez	r4, strlen_last_bytes
+	ld	r0, @r6+	    ||	not	r4, r1
+	sub	r1, r5		    ||	and	r4, r7
+	and	r4, r1		    ||	addi	r2, #4
+	bnez	r4, strlen_last_bytes
+	addi	r2, #4		    ||	bra.s	strlen_word_loop
+
+	; NOTE: If a null char. exists, return 0.
+	; if ((x - 0x01010101) & ~x & 0x80808080)
+	;     return 0;
+;
+strlen_byte:
+	ldb	r1, @r6		    ||	addi	r6, #1
+	beqz	r1, strlen_exit
+	addi	r2, #1		    ||	bra.s	strlen_byte
+;
+strlen_last_bytes:
+	ldi	r0, #4		    ||	addi	r6, #-8
+;
+strlen_byte_loop:
+	ldb	r1, @r6		    ||	addi	r6, #1
+	addi	r0, #-1		    ||  cmpz	r1
+	bc.s	strlen_exit	    ||  cmpz	r0
+	addi	r2, #1		    ||	bnc.s	strlen_byte_loop
+;
+strlen_exit:
+	mv	r0, r2		    ||	jmp	r14
+
+#else /* not CONFIG_ISA_DUAL_ISSUE */
+
+	.text
+ENTRY(strlen)
+	mv	r6, r0
+	ldi	r2, #0
+	and3	r0, r0, #3
+	bnez	r0, strlen_byte
+;
+strlen_word:
+	ld	r0, @r6+
+;
+	seth	r5, #high(0x01010101)
+	or3	r5, r5, #low(0x01010101)
+	sll3	r7, r5, #7
+strlen_word_loop:
+	ld	r1, @r6+
+	not	r4, r0		; NOTE: If a null char. exists, return 0.
+	sub	r0, r5		; if ((x - 0x01010101) & ~x & 0x80808080)
+	and	r4, r7		;     return 0;
+	and	r4, r0
+	bnez	r4, strlen_last_bytes
+	addi	r2, #4
+;
+	ld	r0, @r6+
+	not	r4, r1		; NOTE: If a null char. exists, return 0.
+	sub	r1, r5		; if ((x - 0x01010101) & ~x & 0x80808080)
+	and	r4, r7		;     return 0;
+	and	r4, r1
+	bnez	r4, strlen_last_bytes
+	addi	r2, #4
+	bra	strlen_word_loop
+;
+strlen_byte:
+	ldb	r1, @r6
+	addi	r6, #1
+	beqz	r1, strlen_exit
+	addi	r2, #1
+	bra	strlen_byte
+;
+strlen_last_bytes:
+	ldi	r0, #4
+	addi	r6, #-8
+;
+strlen_byte_loop:
+	ldb	r1, @r6
+	addi	r6, #1
+	addi	r0, #-1
+	beqz	r1, strlen_exit
+	addi	r2, #1
+	bnez	r0, strlen_byte_loop
+;
+strlen_exit:
+	mv	r0, r2
+	jmp	r14
+
+#endif /* not CONFIG_ISA_DUAL_ISSUE */
+
+	.end
diff -Nru a/arch/m32r/lib/usercopy.c b/arch/m32r/lib/usercopy.c
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/arch/m32r/lib/usercopy.c	2004-10-18 14:57:23 -07:00
@@ -0,0 +1,391 @@
+/*
+ * User address space access functions.
+ * The non inlined parts of asm-m32r/uaccess.h are here.
+ *
+ * Copyright 1997 Andi Kleen <ak@muc.de>
+ * Copyright 1997 Linus Torvalds
+ * Copyright 2001, 2002, 2004 Hirokazu Takata
+ */
+#include <linux/config.h>
+#include <linux/prefetch.h>
+#include <linux/string.h>
+#include <linux/thread_info.h>
+#include <asm/uaccess.h>
+
+unsigned long
+__generic_copy_to_user(void *to, const void *from, unsigned long n)
+{
+	prefetch(from);
+	if (access_ok(VERIFY_WRITE, to, n))
+		__copy_user(to,from,n);
+	return n;
+}
+
+unsigned long
+__generic_copy_from_user(void *to, const void *from, unsigned long n)
+{
+	prefetchw(to);
+	if (access_ok(VERIFY_READ, from, n))
+		__copy_user_zeroing(to,from,n);
+	else
+		memset(to, 0, n);
+	return n;
+}
+
+
+/*
+ * Copy a null terminated string from userspace.
+ */
+
+#ifdef CONFIG_ISA_DUAL_ISSUE
+
+#define __do_strncpy_from_user(dst,src,count,res)			\
+do {									\
+	int __d0, __d1, __d2;						\
+	__asm__ __volatile__(						\
+		"	beqz	%1, 2f\n"				\
+		"	.fillinsn\n"					\
+		"0:	ldb	r14, @%3    ||	addi	%3, #1\n"	\
+		"	stb	r14, @%4    ||	addi	%4, #1\n"	\
+		"	beqz	r14, 1f\n"				\
+		"	addi	%1, #-1\n"				\
+		"	bnez	%1, 0b\n"				\
+		"	.fillinsn\n"					\
+		"1:	sub	%0, %1\n"				\
+		"	.fillinsn\n"					\
+		"2:\n"							\
+		".section .fixup,\"ax\"\n"				\
+		"	.balign 4\n"					\
+		"3:	seth	r14, #high(2b)\n"			\
+		"	or3	r14, r14, #low(2b)\n"			\
+		"	jmp	r14	    ||	ldi	%0, #%5\n"	\
+		".previous\n"						\
+		".section __ex_table,\"a\"\n"				\
+		"	.balign 4\n"					\
+		"	.long 0b,3b\n"					\
+		".previous"						\
+		: "=r"(res), "=r"(count), "=&r" (__d0), "=&r" (__d1),	\
+		  "=&r" (__d2)						\
+		: "i"(-EFAULT), "0"(count), "1"(count), "3"(src), 	\
+		  "4"(dst)						\
+		: "r14", "cbit", "memory");				\
+} while (0)
+
+#else /* not CONFIG_ISA_DUAL_ISSUE */
+
+#define __do_strncpy_from_user(dst,src,count,res)			\
+do {									\
+	int __d0, __d1, __d2;						\
+	__asm__ __volatile__(						\
+		"	beqz	%1, 2f\n"				\
+		"	.fillinsn\n"					\
+		"0:	ldb	r14, @%3\n"				\
+		"	stb	r14, @%4\n"				\
+		"	addi	%3, #1\n"				\
+		"	addi	%4, #1\n"				\
+		"	beqz	r14, 1f\n"				\
+		"	addi	%1, #-1\n"				\
+		"	bnez	%1, 0b\n"				\
+		"	.fillinsn\n"					\
+		"1:	sub	%0, %1\n"				\
+		"	.fillinsn\n"					\
+		"2:\n"							\
+		".section .fixup,\"ax\"\n"				\
+		"	.balign 4\n"					\
+		"3:	ldi	%0, #%5\n"				\
+		"	seth	r14, #high(2b)\n"			\
+		"	or3	r14, r14, #low(2b)\n"			\
+		"	jmp	r14\n"					\
+		".previous\n"						\
+		".section __ex_table,\"a\"\n"				\
+		"	.balign 4\n"					\
+		"	.long 0b,3b\n"					\
+		".previous"						\
+		: "=r"(res), "=r"(count), "=&r" (__d0), "=&r" (__d1),	\
+		  "=&r" (__d2)						\
+		: "i"(-EFAULT), "0"(count), "1"(count), "3"(src),	\
+		  "4"(dst)						\
+		: "r14", "cbit", "memory");				\
+} while (0)
+
+#endif /* CONFIG_ISA_DUAL_ISSUE */
+
+long
+__strncpy_from_user(char *dst, const char *src, long count)
+{
+	long res;
+	__do_strncpy_from_user(dst, src, count, res);
+	return res;
+}
+
+long
+strncpy_from_user(char *dst, const char *src, long count)
+{
+	long res = -EFAULT;
+	if (access_ok(VERIFY_READ, src, 1))
+		__do_strncpy_from_user(dst, src, count, res);
+	return res;
+}
+
+
+/*
+ * Zero Userspace
+ */
+
+#ifdef CONFIG_ISA_DUAL_ISSUE
+
+#define __do_clear_user(addr,size)					\
+do {									\
+	int __dst, __c;							\
+  	__asm__ __volatile__(						\
+		"	beqz	%1, 9f\n"				\
+		"	and3	r14, %0, #3\n"				\
+		"	bnez	r14, 2f\n"				\
+		"	and3	r14, %1, #3\n"				\
+		"	bnez	r14, 2f\n"				\
+		"	and3	%1, %1, #3\n"				\
+		"	beqz	%2, 2f\n"				\
+		"	addi	%0, #-4\n"				\
+		"	.fillinsn\n"					\
+		"0:	; word clear \n"				\
+		"	st	%6, @+%0    ||	addi	%2, #-1\n"	\
+		"	bnez	%2, 0b\n"				\
+		"	beqz	%1, 9f\n"				\
+		"	.fillinsn\n"					\
+		"2:	; byte clear \n"				\
+		"	stb	%6, @%0	    ||	addi	%1, #-1\n"	\
+		"	addi	%0, #1\n"				\
+		"	bnez	%1, 2b\n"				\
+		"	.fillinsn\n"					\
+		"9:\n"							\
+		".section .fixup,\"ax\"\n"				\
+		"	.balign 4\n"					\
+		"4:	slli	%2, #2\n"				\
+		"	seth	r14, #high(9b)\n"			\
+		"	or3	r14, r14, #low(9b)\n"			\
+		"	jmp	r14	    ||	add	%1, %2\n"	\
+		".previous\n"						\
+		".section __ex_table,\"a\"\n"				\
+		"	.balign 4\n"					\
+		"	.long 0b,4b\n"					\
+		"	.long 2b,9b\n"					\
+		".previous\n"						\
+		: "=&r"(__dst), "=&r"(size), "=&r"(__c)			\
+		: "0"(addr), "1"(size), "2"(size / 4), "r"(0)		\
+		: "r14", "cbit", "memory");				\
+} while (0)
+
+#else /* not CONFIG_ISA_DUAL_ISSUE */
+
+#define __do_clear_user(addr,size)					\
+do {									\
+	int __dst, __c;							\
+  	__asm__ __volatile__(						\
+		"	beqz	%1, 9f\n"				\
+		"	and3	r14, %0, #3\n"				\
+		"	bnez	r14, 2f\n"				\
+		"	and3	r14, %1, #3\n"				\
+		"	bnez	r14, 2f\n"				\
+		"	and3	%1, %1, #3\n"				\
+		"	beqz	%2, 2f\n"				\
+		"	addi	%0, #-4\n"				\
+		"	.fillinsn\n"					\
+		"0:	st	%6, @+%0	; word clear \n"	\
+		"	addi	%2, #-1\n"				\
+		"	bnez	%2, 0b\n"				\
+		"	beqz	%1, 9f\n"				\
+		"	.fillinsn\n"					\
+		"2:	stb	%6, @%0		; byte clear \n"	\
+		"	addi	%1, #-1\n"				\
+		"	addi	%0, #1\n"				\
+		"	bnez	%1, 2b\n"				\
+		"	.fillinsn\n"					\
+		"9:\n"							\
+		".section .fixup,\"ax\"\n"				\
+		"	.balign 4\n"					\
+		"4:	slli	%2, #2\n"				\
+		"	add	%1, %2\n"				\
+		"	seth	r14, #high(9b)\n"			\
+		"	or3	r14, r14, #low(9b)\n"			\
+		"	jmp	r14\n"					\
+		".previous\n"						\
+		".section __ex_table,\"a\"\n"				\
+		"	.balign 4\n"					\
+		"	.long 0b,4b\n"					\
+		"	.long 2b,9b\n"					\
+		".previous\n"						\
+		: "=&r"(__dst), "=&r"(size), "=&r"(__c)			\
+		: "0"(addr), "1"(size), "2"(size / 4), "r"(0)		\
+		: "r14", "cbit", "memory");				\
+} while (0)
+
+#endif /* not CONFIG_ISA_DUAL_ISSUE */
+
+unsigned long
+clear_user(void *to, unsigned long n)
+{
+	if (access_ok(VERIFY_WRITE, to, n))
+		__do_clear_user(to, n);
+	return n;
+}
+
+unsigned long
+__clear_user(void *to, unsigned long n)
+{
+	__do_clear_user(to, n);
+	return n;
+}
+
+/*
+ * Return the size of a string (including the ending 0)
+ *
+ * Return 0 on exception, a value greater than N if too long
+ */
+
+#ifdef CONFIG_ISA_DUAL_ISSUE
+
+long strnlen_user(const char *s, long n)
+{
+	unsigned long mask = -__addr_ok(s);
+	unsigned long res;
+
+	__asm__ __volatile__(
+		"	and	%0, %5	    ||	mv	r1, %1\n"
+		"	beqz	%0, strnlen_exit\n"
+		"	and3	r0, %1, #3\n"
+		"	bnez	r0, strnlen_byte_loop\n"
+		"	cmpui	%0, #4\n"
+		"	bc	strnlen_byte_loop\n"
+		"strnlen_word_loop:\n"
+		"0:	ld	r0, @%1+\n"
+		"	pcmpbz	r0\n"
+		"	bc	strnlen_last_bytes_fixup\n"
+		"	addi	%0, #-4\n"
+		"	beqz	%0, strnlen_exit\n"
+		"	bgtz	%0, strnlen_word_loop\n"
+		"strnlen_last_bytes:\n"
+		"	mv	%0, %4\n"
+		"strnlen_last_bytes_fixup:\n"
+		"	addi	%1, #-4\n"
+		"strnlen_byte_loop:\n"
+		"1:	ldb	r0, @%1	    ||	addi	%0, #-1\n"
+		"	beqz	r0, strnlen_exit\n"
+		"	addi	%1, #1\n"
+		"	bnez	%0, strnlen_byte_loop\n"
+		"strnlen_exit:\n"
+		"	sub	%1, r1\n"
+		"	add3	%0, %1, #1\n"
+		"	.fillinsn\n"
+		"9:\n"
+		".section .fixup,\"ax\"\n"
+		"	.balign 4\n"
+		"4:	addi	%1, #-4\n"
+		"	.fillinsn\n"
+		"5:	seth	r1, #high(9b)\n"
+		"	or3	r1, r1, #low(9b)\n"
+		"	jmp	r1	    ||	ldi	%0, #0\n"
+		".previous\n"
+		".section __ex_table,\"a\"\n"
+		"	.balign 4\n"
+		"	.long 0b,4b\n"
+		"	.long 1b,5b\n"
+		".previous"
+		: "=&r" (res), "=r" (s)
+		: "0" (n), "1" (s), "r" (n & 3), "r" (mask), "r"(0x01010101)
+		: "r0", "r1", "cbit");
+
+	/* NOTE: strnlen_user() algorism:
+	 * {
+	 *   char *p;
+	 *   for (p = s; n-- && *p != '\0'; ++p)
+	 *     ;
+	 *   return p - s + 1;
+	 * }
+	 */
+
+	/* NOTE: If a null char. exists, return 0.
+	 * if ((x - 0x01010101) & ~x & 0x80808080)\n"
+	 *   return 0;\n"
+	 */
+
+	return res & mask;
+}
+
+#else /* not CONFIG_ISA_DUAL_ISSUE */
+
+long strnlen_user(const char *s, long n)
+{
+	unsigned long mask = -__addr_ok(s);
+	unsigned long res;
+
+	__asm__ __volatile__(
+		"	and	%0, %5\n"
+		"	mv	r1, %1\n"
+		"	beqz	%0, strnlen_exit\n"
+		"	and3	r0, %1, #3\n"
+		"	bnez	r0, strnlen_byte_loop\n"
+		"	cmpui	%0, #4\n"
+		"	bc	strnlen_byte_loop\n"
+		"	sll3	r3, %6, #7\n"
+		"strnlen_word_loop:\n"
+		"0:	ld	r0, @%1+\n"
+		"	not	r2, r0\n"
+		"	sub	r0, %6\n"
+		"	and	r2, r3\n"
+		"	and	r2, r0\n"
+		"	bnez	r2, strnlen_last_bytes_fixup\n"
+		"	addi	%0, #-4\n"
+		"	beqz	%0, strnlen_exit\n"
+		"	bgtz	%0, strnlen_word_loop\n"
+		"strnlen_last_bytes:\n"
+		"	mv	%0, %4\n"
+		"strnlen_last_bytes_fixup:\n"
+		"	addi	%1, #-4\n"
+		"strnlen_byte_loop:\n"
+		"1:	ldb	r0, @%1\n"
+		"	addi	%0, #-1\n"
+		"	beqz	r0, strnlen_exit\n"
+		"	addi	%1, #1\n"
+		"	bnez	%0, strnlen_byte_loop\n"
+		"strnlen_exit:\n"
+		"	sub	%1, r1\n"
+		"	add3	%0, %1, #1\n"
+		"	.fillinsn\n"
+		"9:\n"
+		".section .fixup,\"ax\"\n"
+		"	.balign 4\n"
+		"4:	addi	%1, #-4\n"
+		"	.fillinsn\n"
+		"5:	ldi	%0, #0\n"
+		"	seth	r1, #high(9b)\n"
+		"	or3	r1, r1, #low(9b)\n"
+		"	jmp	r1\n"
+		".previous\n"
+		".section __ex_table,\"a\"\n"
+		"	.balign 4\n"
+		"	.long 0b,4b\n"
+		"	.long 1b,5b\n"
+		".previous"
+		: "=&r" (res), "=r" (s)
+		: "0" (n), "1" (s), "r" (n & 3), "r" (mask), "r"(0x01010101)
+		: "r0", "r1", "r2", "r3", "cbit");
+
+	/* NOTE: strnlen_user() algorism:
+	 * {
+	 *   char *p;
+	 *   for (p = s; n-- && *p != '\0'; ++p)
+	 *     ;
+	 *   return p - s + 1;
+	 * }
+	 */
+
+	/* NOTE: If a null char. exists, return 0.
+	 * if ((x - 0x01010101) & ~x & 0x80808080)\n"
+	 *   return 0;\n"
+	 */
+
+	return res & mask;
+}
+
+#endif /* CONFIG_ISA_DUAL_ISSUE */
+
diff -Nru a/arch/m32r/m32700ut/defconfig.m32700ut.smp b/arch/m32r/m32700ut/defconfig.m32700ut.smp
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/arch/m32r/m32700ut/defconfig.m32700ut.smp	2004-10-18 14:57:23 -07:00
@@ -0,0 +1,662 @@
+#
+# Automatically generated make config: don't edit
+#
+CONFIG_M32R=y
+CONFIG_UID16=y
+CONFIG_GENERIC_ISA_DMA=y
+
+#
+# Code maturity level options
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_CLEAN_COMPILE=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=15
+CONFIG_HOTPLUG=y
+CONFIG_IKCONFIG=y
+# CONFIG_IKCONFIG_PROC is not set
+CONFIG_EMBEDDED=y
+# CONFIG_KALLSYMS is not set
+# CONFIG_FUTEX is not set
+# CONFIG_EPOLL is not set
+CONFIG_IOSCHED_NOOP=y
+# CONFIG_IOSCHED_AS is not set
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+
+#
+# Loadable module support
+#
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+# CONFIG_MODULE_FORCE_UNLOAD is not set
+CONFIG_OBSOLETE_MODPARM=y
+# CONFIG_MODVERSIONS is not set
+CONFIG_KMOD=y
+CONFIG_STOP_MACHINE=y
+
+#
+# Processor type and features
+#
+# CONFIG_PLAT_MAPPI is not set
+# CONFIG_PLAT_USRV is not set
+CONFIG_PLAT_M32700UT=y
+# CONFIG_PLAT_OPSPUT is not set
+# CONFIG_PLAT_OAKS32R is not set
+# CONFIG_PLAT_MAPPI2 is not set
+CONFIG_CHIP_M32700=y
+# CONFIG_CHIP_M32102 is not set
+# CONFIG_CHIP_VDEC2 is not set
+# CONFIG_CHIP_OPSP is not set
+CONFIG_MMU=y
+CONFIG_TLB_ENTRIES=32
+CONFIG_ISA_M32R2=y
+CONFIG_ISA_DSP_LEVEL2=y
+CONFIG_ISA_DUAL_ISSUE=y
+CONFIG_BUS_CLOCK=50000000
+CONFIG_TIMER_DIVIDE=128
+# CONFIG_CPU_LITTLE_ENDIAN is not set
+CONFIG_MEMORY_START=0x08000000
+CONFIG_MEMORY_SIZE=0x01000000
+CONFIG_NOHIGHMEM=y
+# CONFIG_DISCONTIGMEM is not set
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+# CONFIG_RWSEM_XCHGADD_ALGORITHM is not set
+CONFIG_PREEMPT=y
+# CONFIG_HAVE_DEC_LOCK is not set
+CONFIG_SMP=y
+CONFIG_CHIP_M32700_TS1=y
+CONFIG_NR_CPUS=2
+# CONFIG_NUMA is not set
+
+#
+# M32R drivers
+#
+# CONFIG_M32RPCC is not set
+CONFIG_M32R_CFC=y
+CONFIG_M32700UT_CFC=y
+CONFIG_CFC_NUM=1
+# CONFIG_MTD_M32R is not set
+CONFIG_M32R_SMC91111=y
+CONFIG_M32700UT_DS1302=y
+
+#
+# Power management options (ACPI, APM)
+#
+# CONFIG_PM is not set
+
+#
+# Bus options (PCI, PCMCIA, EISA, MCA, ISA)
+#
+# CONFIG_PCI is not set
+# CONFIG_ISA is not set
+
+#
+# PCMCIA/CardBus support
+#
+CONFIG_PCMCIA=y
+# CONFIG_PCMCIA_DEBUG is not set
+# CONFIG_TCIC is not set
+
+#
+# PCI Hotplug Support
+#
+
+#
+# Executable file formats
+#
+CONFIG_BINFMT_ELF=y
+# CONFIG_BINFMT_MISC is not set
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+# CONFIG_FW_LOADER is not set
+
+#
+# Memory Technology Devices (MTD)
+#
+# CONFIG_MTD is not set
+
+#
+# Parallel port support
+#
+# CONFIG_PARPORT is not set
+
+#
+# Plug and Play support
+#
+
+#
+# Block devices
+#
+# CONFIG_BLK_DEV_FD is not set
+CONFIG_BLK_DEV_LOOP=y
+# CONFIG_BLK_DEV_CRYPTOLOOP is not set
+CONFIG_BLK_DEV_NBD=y
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_SIZE=4096
+# CONFIG_BLK_DEV_INITRD is not set
+
+#
+# ATA/ATAPI/MFM/RLL support
+#
+CONFIG_IDE=y
+CONFIG_BLK_DEV_IDE=y
+
+#
+# Please see Documentation/ide.txt for help/info on IDE drives
+#
+# CONFIG_BLK_DEV_IDE_SATA is not set
+CONFIG_BLK_DEV_IDEDISK=y
+# CONFIG_IDEDISK_MULTI_MODE is not set
+CONFIG_BLK_DEV_IDECS=y
+CONFIG_BLK_DEV_IDECD=m
+# 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_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 device support
+#
+CONFIG_SCSI=m
+CONFIG_SCSI_PROC_FS=y
+
+#
+# SCSI support type (disk, tape, CD-ROM)
+#
+CONFIG_BLK_DEV_SD=m
+# CONFIG_CHR_DEV_ST is not set
+# CONFIG_CHR_DEV_OSST is not set
+CONFIG_BLK_DEV_SR=m
+# CONFIG_BLK_DEV_SR_VENDOR is not set
+CONFIG_CHR_DEV_SG=m
+
+#
+# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
+#
+CONFIG_SCSI_MULTI_LUN=y
+# CONFIG_SCSI_CONSTANTS is not set
+# CONFIG_SCSI_LOGGING is not set
+
+#
+# SCSI Transport Attributes
+#
+# CONFIG_SCSI_SPI_ATTRS is not set
+# CONFIG_SCSI_FC_ATTRS is not set
+
+#
+# SCSI low-level drivers
+#
+# CONFIG_SCSI_AIC7XXX_OLD is not set
+# CONFIG_SCSI_SATA is not set
+# CONFIG_SCSI_EATA_PIO is not set
+# CONFIG_SCSI_DEBUG is not set
+
+#
+# PCMCIA SCSI adapter support
+#
+# CONFIG_PCMCIA_AHA152X is not set
+# CONFIG_PCMCIA_FDOMAIN is not set
+# CONFIG_PCMCIA_NINJA_SCSI is not set
+# CONFIG_PCMCIA_QLOGIC is not set
+# CONFIG_PCMCIA_SYM53C500 is not set
+
+#
+# Multi-device support (RAID and LVM)
+#
+# CONFIG_MD is not set
+
+#
+# Fusion MPT device support
+#
+
+#
+# IEEE 1394 (FireWire) support
+#
+
+#
+# I2O device support
+#
+
+#
+# Networking support
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+CONFIG_PACKET=y
+# CONFIG_PACKET_MMAP is not set
+# CONFIG_NETLINK_DEV is not set
+CONFIG_UNIX=y
+# CONFIG_NET_KEY is not set
+CONFIG_INET=y
+# CONFIG_IP_MULTICAST is not set
+# 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_RARP is not set
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+# CONFIG_ARPD 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
+# CONFIG_IPV6 is not set
+# CONFIG_NETFILTER is not set
+
+#
+# SCTP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_SCTP is not set
+# CONFIG_ATM is not set
+# CONFIG_BRIDGE is not set
+# CONFIG_VLAN_8021Q is not set
+# CONFIG_DECNET 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
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+# CONFIG_NET_HW_FLOWCONTROL is not set
+
+#
+# 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 is not set
+
+#
+# ISDN subsystem
+#
+# CONFIG_ISDN is not set
+
+#
+# Telephony Support
+#
+# CONFIG_PHONE is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+
+#
+# Userland interfaces
+#
+# CONFIG_INPUT_MOUSEDEV is not set
+# 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=y
+# CONFIG_SERIO_I8042 is not set
+CONFIG_SERIO_SERPORT=y
+# CONFIG_SERIO_CT82C710 is not set
+
+#
+# Input Device Drivers
+#
+# CONFIG_INPUT_KEYBOARD is not set
+# CONFIG_INPUT_MOUSE 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
+
+#
+# Serial drivers
+#
+# CONFIG_SERIAL_8250 is not set
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+# CONFIG_SERIAL_M32R_SIO is not set
+CONFIG_SERIAL_M32R_PLDSIO=y
+CONFIG_SERIAL_M32R_PLDSIO_CONSOLE=y
+CONFIG_UNIX98_PTYS=y
+CONFIG_LEGACY_PTYS=y
+CONFIG_LEGACY_PTY_COUNT=256
+# CONFIG_QIC02_TAPE is not set
+
+#
+# IPMI
+#
+# CONFIG_IPMI_HANDLER is not set
+
+#
+# Watchdog Cards
+#
+# CONFIG_WATCHDOG is not set
+# CONFIG_RTC is not set
+# CONFIG_GEN_RTC is not set
+# CONFIG_DTLK is not set
+# CONFIG_R3964 is not set
+
+#
+# Ftape, the floppy tape device driver
+#
+# CONFIG_AGP is not set
+# CONFIG_DRM is not set
+
+#
+# PCMCIA character devices
+#
+# CONFIG_SYNCLINK_CS is not set
+# CONFIG_RAW_DRIVER is not set
+
+#
+# I2C support
+#
+# CONFIG_I2C is not set
+
+#
+# Dallas's 1-wire bus
+#
+# CONFIG_W1 is not set
+
+#
+# Misc devices
+#
+
+#
+# Multimedia devices
+#
+CONFIG_VIDEO_DEV=y
+
+#
+# Video For Linux
+#
+
+#
+# Video Adapters
+#
+# CONFIG_VIDEO_CPIA is not set
+CONFIG_M32R_AR=y
+CONFIG_M32R_AR_VGA=y
+
+#
+# Radio Adapters
+#
+# CONFIG_RADIO_MAESTRO is not set
+
+#
+# Digital Video Broadcasting Devices
+#
+# CONFIG_DVB is not set
+
+#
+# Graphics support
+#
+CONFIG_FB=y
+CONFIG_FB_EPSON_S1D13806=y
+# CONFIG_FB_VIRTUAL is not set
+
+#
+# Console display driver support
+#
+# CONFIG_VGA_CONSOLE is not set
+# CONFIG_MDA_CONSOLE is not set
+CONFIG_DUMMY_CONSOLE=y
+CONFIG_FRAMEBUFFER_CONSOLE=y
+# CONFIG_FONTS is not set
+CONFIG_FONT_8x8=y
+CONFIG_FONT_8x16=y
+
+#
+# Logo configuration
+#
+CONFIG_LOGO=y
+CONFIG_LOGO_LINUX_MONO=y
+CONFIG_LOGO_LINUX_VGA16=y
+CONFIG_LOGO_LINUX_CLUT224=y
+CONFIG_LOGO_M32R_CLUT224=y
+
+#
+# Sound
+#
+# CONFIG_SOUND is not set
+
+#
+# USB support
+#
+
+#
+# USB Gadget Support
+#
+# CONFIG_USB_GADGET is not set
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+# CONFIG_EXT2_FS_XATTR is not set
+CONFIG_EXT3_FS=m
+CONFIG_EXT3_FS_XATTR=y
+# CONFIG_EXT3_FS_POSIX_ACL is not set
+# CONFIG_EXT3_FS_SECURITY is not set
+CONFIG_JBD=m
+CONFIG_JBD_DEBUG=y
+CONFIG_FS_MBCACHE=y
+CONFIG_REISERFS_FS=m
+# 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 is not set
+# CONFIG_ROMFS_FS is not set
+# CONFIG_QUOTA is not set
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_AUTOFS4_FS is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+CONFIG_ISO9660_FS=m
+CONFIG_JOLIET=y
+# CONFIG_ZISOFS is not set
+CONFIG_UDF_FS=m
+CONFIG_UDF_NLS=y
+
+#
+# DOS/FAT/NT Filesystems
+#
+CONFIG_FAT_FS=m
+CONFIG_MSDOS_FS=m
+CONFIG_VFAT_FS=m
+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_EFS_FS is not set
+# CONFIG_CRAMFS is not set
+# CONFIG_VXFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+
+#
+# Network File Systems
+#
+CONFIG_NFS_FS=y
+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_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_AFS_FS is not set
+
+#
+# Partition Types
+#
+# CONFIG_PARTITION_ADVANCED is not set
+CONFIG_MSDOS_PARTITION=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
+# CONFIG_NLS_CODEPAGE_775 is not set
+# CONFIG_NLS_CODEPAGE_850 is not set
+# CONFIG_NLS_CODEPAGE_852 is not set
+# CONFIG_NLS_CODEPAGE_855 is not set
+# CONFIG_NLS_CODEPAGE_857 is not set
+# CONFIG_NLS_CODEPAGE_860 is not set
+# CONFIG_NLS_CODEPAGE_861 is not set
+# CONFIG_NLS_CODEPAGE_862 is not set
+# CONFIG_NLS_CODEPAGE_863 is not set
+# CONFIG_NLS_CODEPAGE_864 is not set
+# CONFIG_NLS_CODEPAGE_865 is not set
+# CONFIG_NLS_CODEPAGE_866 is not set
+# CONFIG_NLS_CODEPAGE_869 is not set
+# CONFIG_NLS_CODEPAGE_936 is not set
+# CONFIG_NLS_CODEPAGE_950 is not set
+# CONFIG_NLS_CODEPAGE_932 is not set
+# CONFIG_NLS_CODEPAGE_949 is not set
+# CONFIG_NLS_CODEPAGE_874 is not set
+# 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
+# CONFIG_NLS_ISO8859_4 is not set
+# CONFIG_NLS_ISO8859_5 is not set
+# CONFIG_NLS_ISO8859_6 is not set
+# CONFIG_NLS_ISO8859_7 is not set
+# CONFIG_NLS_ISO8859_9 is not set
+# CONFIG_NLS_ISO8859_13 is not set
+# CONFIG_NLS_ISO8859_14 is not set
+# CONFIG_NLS_ISO8859_15 is not set
+# CONFIG_NLS_KOI8_R is not set
+# CONFIG_NLS_KOI8_U is not set
+# CONFIG_NLS_UTF8 is not set
+
+#
+# Profiling support
+#
+# CONFIG_PROFILING is not set
+
+#
+# Kernel hacking
+#
+# CONFIG_DEBUG_KERNEL is not set
+# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
+# CONFIG_FRAME_POINTER is not set
+
+#
+# Security options
+#
+# CONFIG_SECURITY is not set
+
+#
+# Cryptographic options
+#
+# CONFIG_CRYPTO is not set
+
+#
+# Library routines
+#
+# CONFIG_CRC_CCITT is not set
+CONFIG_CRC32=y
+# CONFIG_LIBCRC32C is not set
diff -Nru a/arch/m32r/m32700ut/defconfig.m32700ut.up b/arch/m32r/m32700ut/defconfig.m32700ut.up
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/arch/m32r/m32700ut/defconfig.m32700ut.up	2004-10-18 14:57:23 -07:00
@@ -0,0 +1,659 @@
+#
+# Automatically generated make config: don't edit
+#
+CONFIG_M32R=y
+CONFIG_UID16=y
+CONFIG_GENERIC_ISA_DMA=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=y
+CONFIG_IKCONFIG=y
+# CONFIG_IKCONFIG_PROC is not set
+CONFIG_EMBEDDED=y
+# CONFIG_KALLSYMS is not set
+# CONFIG_FUTEX is not set
+# CONFIG_EPOLL is not set
+CONFIG_IOSCHED_NOOP=y
+# CONFIG_IOSCHED_AS is not set
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+
+#
+# Loadable module support
+#
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+# CONFIG_MODULE_FORCE_UNLOAD is not set
+CONFIG_OBSOLETE_MODPARM=y
+# CONFIG_MODVERSIONS is not set
+CONFIG_KMOD=y
+
+#
+# Processor type and features
+#
+# CONFIG_PLAT_MAPPI is not set
+# CONFIG_PLAT_USRV is not set
+CONFIG_PLAT_M32700UT=y
+# CONFIG_PLAT_OPSPUT is not set
+# CONFIG_PLAT_OAKS32R is not set
+# CONFIG_PLAT_MAPPI2 is not set
+CONFIG_CHIP_M32700=y
+# CONFIG_CHIP_M32102 is not set
+# CONFIG_CHIP_VDEC2 is not set
+# CONFIG_CHIP_OPSP is not set
+CONFIG_MMU=y
+CONFIG_TLB_ENTRIES=32
+CONFIG_ISA_M32R2=y
+CONFIG_ISA_DSP_LEVEL2=y
+CONFIG_ISA_DUAL_ISSUE=y
+CONFIG_BUS_CLOCK=50000000
+CONFIG_TIMER_DIVIDE=128
+# CONFIG_CPU_LITTLE_ENDIAN is not set
+CONFIG_MEMORY_START=0x08000000
+CONFIG_MEMORY_SIZE=0x01000000
+CONFIG_NOHIGHMEM=y
+# CONFIG_DISCONTIGMEM is not set
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+# CONFIG_RWSEM_XCHGADD_ALGORITHM is not set
+CONFIG_PREEMPT=y
+# CONFIG_HAVE_DEC_LOCK is not set
+# CONFIG_SMP is not set
+
+#
+# M32R drivers
+#
+# CONFIG_M32RPCC is not set
+CONFIG_M32R_CFC=y
+CONFIG_M32700UT_CFC=y
+CONFIG_CFC_NUM=1
+# CONFIG_MTD_M32R is not set
+CONFIG_M32R_SMC91111=y
+CONFIG_M32700UT_DS1302=y
+
+#
+# Power management options (ACPI, APM)
+#
+# CONFIG_PM is not set
+
+#
+# Bus options (PCI, PCMCIA, EISA, MCA, ISA)
+#
+# CONFIG_PCI is not set
+# CONFIG_ISA is not set
+
+#
+# PCMCIA/CardBus support
+#
+CONFIG_PCMCIA=y
+# CONFIG_PCMCIA_DEBUG is not set
+# CONFIG_TCIC is not set
+
+#
+# PCI Hotplug Support
+#
+
+#
+# Executable file formats
+#
+CONFIG_BINFMT_ELF=y
+# CONFIG_BINFMT_MISC is not set
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+# CONFIG_FW_LOADER is not set
+
+#
+# Memory Technology Devices (MTD)
+#
+# CONFIG_MTD is not set
+
+#
+# Parallel port support
+#
+# CONFIG_PARPORT is not set
+
+#
+# Plug and Play support
+#
+
+#
+# Block devices
+#
+# CONFIG_BLK_DEV_FD is not set
+CONFIG_BLK_DEV_LOOP=y
+# CONFIG_BLK_DEV_CRYPTOLOOP is not set
+CONFIG_BLK_DEV_NBD=y
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_SIZE=4096
+# CONFIG_BLK_DEV_INITRD is not set
+
+#
+# ATA/ATAPI/MFM/RLL support
+#
+CONFIG_IDE=y
+CONFIG_BLK_DEV_IDE=y
+
+#
+# Please see Documentation/ide.txt for help/info on IDE drives
+#
+# CONFIG_BLK_DEV_IDE_SATA is not set
+CONFIG_BLK_DEV_IDEDISK=y
+# CONFIG_IDEDISK_MULTI_MODE is not set
+CONFIG_BLK_DEV_IDECS=y
+CONFIG_BLK_DEV_IDECD=m
+# 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_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 device support
+#
+CONFIG_SCSI=m
+CONFIG_SCSI_PROC_FS=y
+
+#
+# SCSI support type (disk, tape, CD-ROM)
+#
+CONFIG_BLK_DEV_SD=m
+# CONFIG_CHR_DEV_ST is not set
+# CONFIG_CHR_DEV_OSST is not set
+CONFIG_BLK_DEV_SR=m
+# CONFIG_BLK_DEV_SR_VENDOR is not set
+CONFIG_CHR_DEV_SG=m
+
+#
+# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
+#
+CONFIG_SCSI_MULTI_LUN=y
+# CONFIG_SCSI_CONSTANTS is not set
+# CONFIG_SCSI_LOGGING is not set
+
+#
+# SCSI Transport Attributes
+#
+# CONFIG_SCSI_SPI_ATTRS is not set
+# CONFIG_SCSI_FC_ATTRS is not set
+
+#
+# SCSI low-level drivers
+#
+# CONFIG_SCSI_AIC7XXX_OLD is not set
+# CONFIG_SCSI_SATA is not set
+# CONFIG_SCSI_EATA_PIO is not set
+# CONFIG_SCSI_DEBUG is not set
+
+#
+# PCMCIA SCSI adapter support
+#
+# CONFIG_PCMCIA_AHA152X is not set
+# CONFIG_PCMCIA_FDOMAIN is not set
+# CONFIG_PCMCIA_NINJA_SCSI is not set
+# CONFIG_PCMCIA_QLOGIC is not set
+# CONFIG_PCMCIA_SYM53C500 is not set
+
+#
+# Multi-device support (RAID and LVM)
+#
+# CONFIG_MD is not set
+
+#
+# Fusion MPT device support
+#
+
+#
+# IEEE 1394 (FireWire) support
+#
+
+#
+# I2O device support
+#
+
+#
+# Networking support
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+CONFIG_PACKET=y
+# CONFIG_PACKET_MMAP is not set
+# CONFIG_NETLINK_DEV is not set
+CONFIG_UNIX=y
+# CONFIG_NET_KEY is not set
+CONFIG_INET=y
+# CONFIG_IP_MULTICAST is not set
+# 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_RARP is not set
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+# CONFIG_ARPD 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
+# CONFIG_IPV6 is not set
+# CONFIG_NETFILTER is not set
+
+#
+# SCTP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_SCTP is not set
+# CONFIG_ATM is not set
+# CONFIG_BRIDGE is not set
+# CONFIG_VLAN_8021Q is not set
+# CONFIG_DECNET 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
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+# CONFIG_NET_HW_FLOWCONTROL is not set
+
+#
+# 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 is not set
+
+#
+# ISDN subsystem
+#
+# CONFIG_ISDN is not set
+
+#
+# Telephony Support
+#
+# CONFIG_PHONE is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+
+#
+# Userland interfaces
+#
+# CONFIG_INPUT_MOUSEDEV is not set
+# 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=y
+# CONFIG_SERIO_I8042 is not set
+CONFIG_SERIO_SERPORT=y
+# CONFIG_SERIO_CT82C710 is not set
+
+#
+# Input Device Drivers
+#
+# CONFIG_INPUT_KEYBOARD is not set
+# CONFIG_INPUT_MOUSE 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
+
+#
+# Serial drivers
+#
+# CONFIG_SERIAL_8250 is not set
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+# CONFIG_SERIAL_M32R_SIO is not set
+CONFIG_SERIAL_M32R_PLDSIO=y
+CONFIG_SERIAL_M32R_PLDSIO_CONSOLE=y
+CONFIG_UNIX98_PTYS=y
+CONFIG_LEGACY_PTYS=y
+CONFIG_LEGACY_PTY_COUNT=256
+# CONFIG_QIC02_TAPE is not set
+
+#
+# IPMI
+#
+# CONFIG_IPMI_HANDLER is not set
+
+#
+# Watchdog Cards
+#
+# CONFIG_WATCHDOG is not set
+# CONFIG_RTC is not set
+# CONFIG_GEN_RTC is not set
+# CONFIG_DTLK is not set
+# CONFIG_R3964 is not set
+
+#
+# Ftape, the floppy tape device driver
+#
+# CONFIG_AGP is not set
+# CONFIG_DRM is not set
+
+#
+# PCMCIA character devices
+#
+# CONFIG_SYNCLINK_CS is not set
+# CONFIG_RAW_DRIVER is not set
+
+#
+# I2C support
+#
+# CONFIG_I2C is not set
+
+#
+# Dallas's 1-wire bus
+#
+# CONFIG_W1 is not set
+
+#
+# Misc devices
+#
+
+#
+# Multimedia devices
+#
+CONFIG_VIDEO_DEV=y
+
+#
+# Video For Linux
+#
+
+#
+# Video Adapters
+#
+# CONFIG_VIDEO_CPIA is not set
+CONFIG_M32R_AR=y
+CONFIG_M32R_AR_VGA=y
+
+#
+# Radio Adapters
+#
+# CONFIG_RADIO_MAESTRO is not set
+
+#
+# Digital Video Broadcasting Devices
+#
+# CONFIG_DVB is not set
+
+#
+# Graphics support
+#
+CONFIG_FB=y
+CONFIG_FB_EPSON_S1D13806=y
+# CONFIG_FB_VIRTUAL is not set
+
+#
+# Console display driver support
+#
+# CONFIG_VGA_CONSOLE is not set
+# CONFIG_MDA_CONSOLE is not set
+CONFIG_DUMMY_CONSOLE=y
+CONFIG_FRAMEBUFFER_CONSOLE=y
+# CONFIG_FONTS is not set
+CONFIG_FONT_8x8=y
+CONFIG_FONT_8x16=y
+
+#
+# Logo configuration
+#
+CONFIG_LOGO=y
+CONFIG_LOGO_LINUX_MONO=y
+CONFIG_LOGO_LINUX_VGA16=y
+CONFIG_LOGO_LINUX_CLUT224=y
+CONFIG_LOGO_M32R_CLUT224=y
+
+#
+# Sound
+#
+# CONFIG_SOUND is not set
+
+#
+# USB support
+#
+
+#
+# USB Gadget Support
+#
+# CONFIG_USB_GADGET is not set
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+# CONFIG_EXT2_FS_XATTR is not set
+CONFIG_EXT3_FS=m
+CONFIG_EXT3_FS_XATTR=y
+# CONFIG_EXT3_FS_POSIX_ACL is not set
+# CONFIG_EXT3_FS_SECURITY is not set
+CONFIG_JBD=m
+CONFIG_JBD_DEBUG=y
+CONFIG_FS_MBCACHE=y
+CONFIG_REISERFS_FS=m
+# 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 is not set
+# CONFIG_ROMFS_FS is not set
+# CONFIG_QUOTA is not set
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_AUTOFS4_FS is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+CONFIG_ISO9660_FS=m
+CONFIG_JOLIET=y
+# CONFIG_ZISOFS is not set
+CONFIG_UDF_FS=m
+CONFIG_UDF_NLS=y
+
+#
+# DOS/FAT/NT Filesystems
+#
+CONFIG_FAT_FS=m
+CONFIG_MSDOS_FS=m
+CONFIG_VFAT_FS=m
+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_EFS_FS is not set
+# CONFIG_CRAMFS is not set
+# CONFIG_VXFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+
+#
+# Network File Systems
+#
+CONFIG_NFS_FS=y
+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_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_AFS_FS is not set
+
+#
+# Partition Types
+#
+# CONFIG_PARTITION_ADVANCED is not set
+CONFIG_MSDOS_PARTITION=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
+# CONFIG_NLS_CODEPAGE_775 is not set
+# CONFIG_NLS_CODEPAGE_850 is not set
+# CONFIG_NLS_CODEPAGE_852 is not set
+# CONFIG_NLS_CODEPAGE_855 is not set
+# CONFIG_NLS_CODEPAGE_857 is not set
+# CONFIG_NLS_CODEPAGE_860 is not set
+# CONFIG_NLS_CODEPAGE_861 is not set
+# CONFIG_NLS_CODEPAGE_862 is not set
+# CONFIG_NLS_CODEPAGE_863 is not set
+# CONFIG_NLS_CODEPAGE_864 is not set
+# CONFIG_NLS_CODEPAGE_865 is not set
+# CONFIG_NLS_CODEPAGE_866 is not set
+# CONFIG_NLS_CODEPAGE_869 is not set
+# CONFIG_NLS_CODEPAGE_936 is not set
+# CONFIG_NLS_CODEPAGE_950 is not set
+# CONFIG_NLS_CODEPAGE_932 is not set
+# CONFIG_NLS_CODEPAGE_949 is not set
+# CONFIG_NLS_CODEPAGE_874 is not set
+# 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
+# CONFIG_NLS_ISO8859_4 is not set
+# CONFIG_NLS_ISO8859_5 is not set
+# CONFIG_NLS_ISO8859_6 is not set
+# CONFIG_NLS_ISO8859_7 is not set
+# CONFIG_NLS_ISO8859_9 is not set
+# CONFIG_NLS_ISO8859_13 is not set
+# CONFIG_NLS_ISO8859_14 is not set
+# CONFIG_NLS_ISO8859_15 is not set
+# CONFIG_NLS_KOI8_R is not set
+# CONFIG_NLS_KOI8_U is not set
+# CONFIG_NLS_UTF8 is not set
+
+#
+# Profiling support
+#
+# CONFIG_PROFILING is not set
+
+#
+# Kernel hacking
+#
+# CONFIG_DEBUG_KERNEL is not set
+# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
+# CONFIG_FRAME_POINTER is not set
+
+#
+# Security options
+#
+# CONFIG_SECURITY is not set
+
+#
+# Cryptographic options
+#
+# CONFIG_CRYPTO is not set
+
+#
+# Library routines
+#
+# CONFIG_CRC_CCITT is not set
+CONFIG_CRC32=y
+# CONFIG_LIBCRC32C is not set
diff -Nru a/arch/m32r/m32700ut/dot.gdbinit_200MHz_16MB b/arch/m32r/m32700ut/dot.gdbinit_200MHz_16MB
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/arch/m32r/m32700ut/dot.gdbinit_200MHz_16MB	2004-10-18 14:57:23 -07:00
@@ -0,0 +1,249 @@
+# .gdbinit file
+# $Id: dot.gdbinit_200MHz_16MB,v 1.1 2004/08/17 02:58:11 takata Exp $
+#-----
+# NOTE: this file is generated by a script, "gen_gdbinit.pl".
+# (Please type "gen_gdbinit.pl --help" and check the help message).
+# $ Id: gen_gdbinit.pl,v 1.12 2004/07/26 09:56:10 takata Exp $
+#-----
+# target platform: m32700ut
+
+# setting
+set width 0d70
+set radix 0d16
+
+debug_chaos
+
+# clk xin:cpu:bif:bus=25:200:50:50
+define clock_init
+  set *(unsigned long *)0x00ef4008 = 0x00000000
+  set *(unsigned long *)0x00ef4004 = 0
+  shell sleep 0.1
+  # NOTE: Please change the master clock source from PLL-clock to Xin-clock
+  # and switch off PLL, before resetting the clock gear ratio.
+
+  set *(unsigned long *)0x00ef4024 = 2
+  set *(unsigned long *)0x00ef4020 = 2
+  set *(unsigned long *)0x00ef4010 = 0
+  set *(unsigned long *)0x00ef4014 = 0
+  set *(unsigned long *)0x00ef4004 = 3
+  shell sleep 0.1
+  set *(unsigned long *)0x00ef4008 = 0x00000200
+end
+
+# Initialize SDRAM controller
+define sdram_init
+  # SDIR0
+  set *(unsigned long *)0x00ef6008 = 0x00000182
+  # SDIR1
+  set *(unsigned long *)0x00ef600c = 0x00000001
+  # Initialize wait
+  shell sleep 0.1
+  # Ch0-MOD
+  set *(unsigned long *)0x00ef602c = 0x00000020
+  # Ch0-TR
+  set *(unsigned long *)0x00ef6028 = 0x00041302
+  # Ch0-ADR (size:16MB)
+  set *(unsigned long *)0x00ef6020 = 0x08000002
+  # AutoRef On
+  set *(unsigned long *)0x00ef6004 = 0x00010517
+  # Access enable
+  set *(unsigned long *)0x00ef6024 = 0x00000001
+end
+document sdram_init
+  SDRAM controller initialization
+  0x08000000 - 0x08ffffff (16MB)
+end
+
+# Initialize BSEL3 for UT-CFC
+define cfc_init
+  set $sfrbase = 0xa0ef0000
+# too fast
+#  set *(unsigned long *)($sfrbase + 0x5300) = 0x0b0b8000
+#  set *(unsigned long *)($sfrbase + 0x5304) = 0x00102204
+#  set *(unsigned long *)($sfrbase + 0x5300) = 0x1f1f8000
+#  set *(unsigned long *)($sfrbase + 0x5300) = 0x1f1f1fdf
+#  set *(unsigned long *)($sfrbase + 0x5304) = 0x0013220f
+#  set *(unsigned long *)($sfrbase + 0x5304) = 0x0013330f
+end
+document cfc_init
+  CF controller initialization
+end
+
+# MMU enable
+define mmu_enable
+  set $evb=0x88000000
+  set *(unsigned long *)0xffff0024=1
+end
+
+# MMU disable
+define mmu_disable
+  set $evb=0
+  set *(unsigned long *)0xffff0024=0
+end
+
+# Show TLB entries
+define show_tlb_entries
+  set $i = 0
+  set $addr = $arg0
+  set $nr_entries = $arg1
+  use_mon_code
+  while ($i < $nr_entries)
+    set $tlb_tag = *(unsigned long*)$addr
+    set $tlb_data = *(unsigned long*)($addr + 4)
+    printf " [%2d] 0x%08lx : 0x%08lx - 0x%08lx\n", $i, $addr, $tlb_tag, $tlb_data
+    set $i = $i + 1
+    set $addr = $addr + 8
+  end
+  use_debug_dma
+end
+define itlb
+  set $itlb=0xfe000000
+  show_tlb_entries $itlb 0d32
+end
+define dtlb
+  set $dtlb=0xfe000800
+  show_tlb_entries $dtlb 0d32
+end
+
+# Initialize TLB entries
+define init_tlb_entries
+  set $i = 0
+  set $addr = $arg0
+  set $nr_entries = $arg1
+  use_mon_code
+  while ($i < $nr_entries)
+    set *(unsigned long *)($addr + 0x4) = 0
+    set $i = $i + 1
+    set $addr = $addr + 8
+  end
+  use_debug_dma
+end
+define tlb_init
+  set $itlb=0xfe000000
+  init_tlb_entries $itlb 0d32
+  set $dtlb=0xfe000800
+  init_tlb_entries $dtlb 0d32
+end
+
+# Show current task structure
+define show_current
+  set $current = $spi & 0xffffe000
+  printf "$current=0x%08lX\n",$current
+  print *(struct task_struct *)$current
+end
+
+# Show user assigned task structure
+define show_task
+  set  = $arg0 & 0xffffe000
+  printf "$task=0x%08lX\n",$task
+  print *(struct task_struct *)$task
+end
+document show_task
+  Show user assigned task structure
+  arg0 : task structure address
+end
+
+# Show M32R registers
+define show_regs
+  printf " R0[0x%08lX]   R1[0x%08lX]   R2[0x%08lX]   R3[0x%08lX]\n",$r0,$r1,$r2,$r3
+  printf " R4[0x%08lX]   R5[0x%08lX]   R6[0x%08lX]   R7[0x%08lX]\n",$r4,$r5,$r6,$r7
+  printf " R8[0x%08lX]   R9[0x%08lX]  R10[0x%08lX]  R11[0x%08lX]\n",$r8,$r9,$r10,$r11
+  printf "R12[0x%08lX]   FP[0x%08lX]   LR[0x%08lX]   SP[0x%08lX]\n",$r12,$fp,$lr,$sp
+  printf "PSW[0x%08lX]  CBR[0x%08lX]  SPI[0x%08lX]  SPU[0x%08lX]\n",$psw,$cbr,$spi,$spu
+  printf "BPC[0x%08lX]   PC[0x%08lX] ACCL[0x%08lX] ACCH[0x%08lX]\n",$bpc,$pc,$accl,$acch
+  printf "EVB[0x%08lX]\n",$evb
+end
+
+# Setup all
+define setup
+  use_mon_code
+  set *(unsigned int)0xfffffffc=0x60
+  shell sleep 0.1
+  clock_init
+  shell sleep 0.1
+  # SDRAM: 16MB
+  set *(unsigned long *)0x00ef6020 = 0x08000002
+  cfc_init
+  # USB
+  set *(unsigned short *)0xb0301000 = 0x100
+
+  set $evb=0x08000000
+end
+
+# Load modules
+define load_modules
+  use_debug_dma
+  load
+end
+
+# Set kernel parameters
+define set_kernel_parameters
+  set $param = (void*)0x08002000
+  # INITRD_START
+  set *(unsigned long *)($param + 0x0010) = 0x082a0000
+  # INITRD_SIZE
+  set *(unsigned long *)($param + 0x0014) = 0x00000000
+  # M32R_CPUCLK
+  set *(unsigned long *)($param + 0x0018) = 0d200000000
+  # M32R_BUSCLK
+  set *(unsigned long *)($param + 0x001c) = 0d50000000
+
+  # M32R_TIMER_DIVIDE
+  set *(unsigned long *)($param + 0x0020) = 0d128
+
+  set {char[0x200]}($param + 0x100) = "console=ttyD0,115200n8x console=tty1 video=s1d13xxxfb:mode:240x320-16 root=/dev/nfsroot nfsroot=192.168.0.1:/project/m32r-linux/export/rootfs,rsize=1024,wsize=1024 nfsaddrs=192.168.0.101:192.168.0.1:192.168.0.1:255.255.255.0:mappi001 mem=16M \0"
+end
+
+# Boot
+define boot
+  set_kernel_parameters
+  set $fp = 0
+  set $pc = 0x08001000
+  set *(unsigned char *)0xffffffff = 0x03
+  si
+  c
+end
+
+# Set breakpoints
+define set_breakpoints
+  b *0x08000030
+end
+
+# Restart
+define restart
+  sdireset
+  sdireset
+  set $pc = 0
+  b *0x04001000
+  b *0x08001000
+  b *0x08002000
+  si
+  c
+  tlb_init
+  del
+  setup
+  load_modules
+  boot
+end
+
+define si
+  stepi
+  x/i $pc
+  show_reg
+end
+
+sdireset
+sdireset
+file vmlinux
+target m32rsdi
+set $pc = 0
+b *0x04001000
+b *0x08001000
+b *0x08002000
+c
+tlb_init
+del
+setup
+load_modules
+boot
+
diff -Nru a/arch/m32r/m32700ut/dot.gdbinit_300MHz_32MB b/arch/m32r/m32700ut/dot.gdbinit_300MHz_32MB
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/arch/m32r/m32700ut/dot.gdbinit_300MHz_32MB	2004-10-18 14:57:24 -07:00
@@ -0,0 +1,249 @@
+# .gdbinit file
+# $Id: dot.gdbinit_300MHz_32MB,v 1.1 2004/08/17 02:58:11 takata Exp $
+#-----
+# NOTE: this file is generated by a script, "gen_gdbinit.pl".
+# (Please type "gen_gdbinit.pl --help" and check the help message).
+# $ Id: gen_gdbinit.pl,v 1.12 2004/07/26 09:56:10 takata Exp $
+#-----
+# target platform: m32700ut
+
+# setting
+set width 0d70
+set radix 0d16
+
+debug_chaos
+
+# clk xin:cpu:bif:bus=25:300:75:75
+define clock_init
+  set *(unsigned long *)0x00ef4008 = 0x00000000
+  set *(unsigned long *)0x00ef4004 = 0
+  shell sleep 0.1
+  # NOTE: Please change the master clock source from PLL-clock to Xin-clock
+  # and switch off PLL, before resetting the clock gear ratio.
+
+  set *(unsigned long *)0x00ef4024 = 2
+  set *(unsigned long *)0x00ef4020 = 2
+  set *(unsigned long *)0x00ef4010 = 0
+  set *(unsigned long *)0x00ef4014 = 0
+  set *(unsigned long *)0x00ef4004 = 5
+  shell sleep 0.1
+  set *(unsigned long *)0x00ef4008 = 0x00000200
+end
+
+# Initialize SDRAM controller
+define sdram_init
+  # SDIR0
+  set *(unsigned long *)0x00ef6008 = 0x00000182
+  # SDIR1
+  set *(unsigned long *)0x00ef600c = 0x00000001
+  # Initialize wait
+  shell sleep 0.1
+  # Ch0-MOD
+  set *(unsigned long *)0x00ef602c = 0x00000020
+  # Ch0-TR
+  set *(unsigned long *)0x00ef6028 = 0x00051502
+  # Ch0-ADR (size:16MB)
+  set *(unsigned long *)0x00ef6020 = 0x08000002
+  # AutoRef On
+  set *(unsigned long *)0x00ef6004 = 0x00010e24
+  # Access enable
+  set *(unsigned long *)0x00ef6024 = 0x00000001
+end
+document sdram_init
+  SDRAM controller initialization
+  0x08000000 - 0x08ffffff (16MB)
+end
+
+# Initialize BSEL3 for UT-CFC
+define cfc_init
+  set $sfrbase = 0xa0ef0000
+# too fast
+#  set *(unsigned long *)($sfrbase + 0x5300) = 0x0b0b8000
+#  set *(unsigned long *)($sfrbase + 0x5304) = 0x00102204
+#  set *(unsigned long *)($sfrbase + 0x5300) = 0x1f1f8000
+#  set *(unsigned long *)($sfrbase + 0x5300) = 0x1f1f1fdf
+#  set *(unsigned long *)($sfrbase + 0x5304) = 0x0013220f
+#  set *(unsigned long *)($sfrbase + 0x5304) = 0x0013330f
+end
+document cfc_init
+  CF controller initialization
+end
+
+# MMU enable
+define mmu_enable
+  set $evb=0x88000000
+  set *(unsigned long *)0xffff0024=1
+end
+
+# MMU disable
+define mmu_disable
+  set $evb=0
+  set *(unsigned long *)0xffff0024=0
+end
+
+# Show TLB entries
+define show_tlb_entries
+  set $i = 0
+  set $addr = $arg0
+  set $nr_entries = $arg1
+  use_mon_code
+  while ($i < $nr_entries)
+    set $tlb_tag = *(unsigned long*)$addr
+    set $tlb_data = *(unsigned long*)($addr + 4)
+    printf " [%2d] 0x%08lx : 0x%08lx - 0x%08lx\n", $i, $addr, $tlb_tag, $tlb_data
+    set $i = $i + 1
+    set $addr = $addr + 8
+  end
+  use_debug_dma
+end
+define itlb
+  set $itlb=0xfe000000
+  show_tlb_entries $itlb 0d32
+end
+define dtlb
+  set $dtlb=0xfe000800
+  show_tlb_entries $dtlb 0d32
+end
+
+# Initialize TLB entries
+define init_tlb_entries
+  set $i = 0
+  set $addr = $arg0
+  set $nr_entries = $arg1
+  use_mon_code
+  while ($i < $nr_entries)
+    set *(unsigned long *)($addr + 0x4) = 0
+    set $i = $i + 1
+    set $addr = $addr + 8
+  end
+  use_debug_dma
+end
+define tlb_init
+  set $itlb=0xfe000000
+  init_tlb_entries $itlb 0d32
+  set $dtlb=0xfe000800
+  init_tlb_entries $dtlb 0d32
+end
+
+# Show current task structure
+define show_current
+  set $current = $spi & 0xffffe000
+  printf "$current=0x%08lX\n",$current
+  print *(struct task_struct *)$current
+end
+
+# Show user assigned task structure
+define show_task
+  set  = $arg0 & 0xffffe000
+  printf "$task=0x%08lX\n",$task
+  print *(struct task_struct *)$task
+end
+document show_task
+  Show user assigned task structure
+  arg0 : task structure address
+end
+
+# Show M32R registers
+define show_regs
+  printf " R0[0x%08lX]   R1[0x%08lX]   R2[0x%08lX]   R3[0x%08lX]\n",$r0,$r1,$r2,$r3
+  printf " R4[0x%08lX]   R5[0x%08lX]   R6[0x%08lX]   R7[0x%08lX]\n",$r4,$r5,$r6,$r7
+  printf " R8[0x%08lX]   R9[0x%08lX]  R10[0x%08lX]  R11[0x%08lX]\n",$r8,$r9,$r10,$r11
+  printf "R12[0x%08lX]   FP[0x%08lX]   LR[0x%08lX]   SP[0x%08lX]\n",$r12,$fp,$lr,$sp
+  printf "PSW[0x%08lX]  CBR[0x%08lX]  SPI[0x%08lX]  SPU[0x%08lX]\n",$psw,$cbr,$spi,$spu
+  printf "BPC[0x%08lX]   PC[0x%08lX] ACCL[0x%08lX] ACCH[0x%08lX]\n",$bpc,$pc,$accl,$acch
+  printf "EVB[0x%08lX]\n",$evb
+end
+
+# Setup all
+define setup
+  use_mon_code
+  set *(unsigned int)0xfffffffc=0x60
+  shell sleep 0.1
+  clock_init
+  shell sleep 0.1
+  # SDRAM: 16MB
+  set *(unsigned long *)0x00ef6020 = 0x08000002
+  cfc_init
+  # USB
+  set *(unsigned short *)0xb0301000 = 0x100
+
+  set $evb=0x08000000
+end
+
+# Load modules
+define load_modules
+  use_debug_dma
+  load
+end
+
+# Set kernel parameters
+define set_kernel_parameters
+  set $param = (void*)0x08002000
+  # INITRD_START
+  set *(unsigned long *)($param + 0x0010) = 0x082a0000
+  # INITRD_SIZE
+  set *(unsigned long *)($param + 0x0014) = 0x00000000
+  # M32R_CPUCLK
+  set *(unsigned long *)($param + 0x0018) = 0d300000000
+  # M32R_BUSCLK
+  set *(unsigned long *)($param + 0x001c) = 0d75000000
+
+  # M32R_TIMER_DIVIDE
+  set *(unsigned long *)($param + 0x0020) = 0d128
+
+  set {char[0x200]}($param + 0x100) = "console=ttyD0,115200n8x console=tty1 video=s1d13xxxfb:mode:240x320-16 root=/dev/nfsroot nfsroot=192.168.0.1:/project/m32r-linux/export/rootfs,rsize=1024,wsize=1024 nfsaddrs=192.168.0.101:192.168.0.1:192.168.0.1:255.255.255.0:mappi001 mem=16M \0"
+end
+
+# Boot
+define boot
+  set_kernel_parameters
+  set $fp = 0
+  set $pc = 0x08001000
+  set *(unsigned char *)0xffffffff = 0x03
+  si
+  c
+end
+
+# Set breakpoints
+define set_breakpoints
+  b *0x08000030
+end
+
+# Restart
+define restart
+  sdireset
+  sdireset
+  set $pc = 0
+  b *0x04001000
+  b *0x08001000
+  b *0x08002000
+  si
+  c
+  tlb_init
+  del
+  setup
+  load_modules
+  boot
+end
+
+define si
+  stepi
+  x/i $pc
+  show_reg
+end
+
+sdireset
+sdireset
+file vmlinux
+target m32rsdi
+set $pc = 0
+b *0x04001000
+b *0x08001000
+b *0x08002000
+c
+tlb_init
+del
+setup
+load_modules
+boot
+
diff -Nru a/arch/m32r/mappi/defconfig.nommu b/arch/m32r/mappi/defconfig.nommu
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/arch/m32r/mappi/defconfig.nommu	2004-10-18 14:57:24 -07:00
@@ -0,0 +1,529 @@
+#
+# Automatically generated make config: don't edit
+#
+CONFIG_M32R=y
+CONFIG_UID16=y
+CONFIG_GENERIC_ISA_DMA=y
+
+#
+# Code maturity level options
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_CLEAN_COMPILE=y
+CONFIG_BROKEN_ON_SMP=y
+
+#
+# General setup
+#
+# 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=y
+CONFIG_IKCONFIG=y
+# CONFIG_IKCONFIG_PROC is not set
+CONFIG_EMBEDDED=y
+# CONFIG_KALLSYMS is not set
+# CONFIG_FUTEX is not set
+# CONFIG_EPOLL is not set
+CONFIG_IOSCHED_NOOP=y
+# CONFIG_IOSCHED_AS is not set
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+
+#
+# Loadable module support
+#
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+# CONFIG_MODULE_FORCE_UNLOAD is not set
+CONFIG_OBSOLETE_MODPARM=y
+# CONFIG_MODVERSIONS is not set
+CONFIG_KMOD=y
+
+#
+# Processor type and features
+#
+CONFIG_PLAT_MAPPI=y
+# CONFIG_PLAT_USRV is not set
+# CONFIG_PLAT_M32700UT is not set
+# CONFIG_PLAT_OPSPUT is not set
+# CONFIG_PLAT_OAKS32R is not set
+# CONFIG_PLAT_MAPPI2 is not set
+CONFIG_CHIP_M32700=y
+# CONFIG_CHIP_M32102 is not set
+# CONFIG_CHIP_VDEC2 is not set
+# CONFIG_CHIP_OPSP is not set
+# CONFIG_MMU is not set
+CONFIG_TLB_ENTRIES=32
+CONFIG_ISA_M32R2=y
+CONFIG_ISA_DSP_LEVEL2=y
+CONFIG_ISA_DUAL_ISSUE=y
+CONFIG_BUS_CLOCK=50000000
+CONFIG_TIMER_DIVIDE=128
+# CONFIG_CPU_LITTLE_ENDIAN is not set
+CONFIG_MEMORY_START=0x00000000
+CONFIG_MEMORY_SIZE=0x00E00000
+CONFIG_NOHIGHMEM=y
+# CONFIG_DISCONTIGMEM is not set
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+# CONFIG_RWSEM_XCHGADD_ALGORITHM is not set
+CONFIG_PREEMPT=y
+# CONFIG_HAVE_DEC_LOCK is not set
+# CONFIG_SMP is not set
+
+#
+# M32R drivers
+#
+# CONFIG_M32RPCC is not set
+CONFIG_M32R_NE2000=y
+
+#
+# Power management options (ACPI, APM)
+#
+# CONFIG_PM is not set
+
+#
+# Bus options (PCI, PCMCIA, EISA, MCA, ISA)
+#
+# CONFIG_PCI is not set
+# CONFIG_ISA is not set
+
+#
+# PCMCIA/CardBus support
+#
+# CONFIG_PCMCIA is not set
+
+#
+# PCI Hotplug Support
+#
+
+#
+# Executable file formats
+#
+CONFIG_BINFMT_FLAT=y
+# CONFIG_BINFMT_ZFLAT is not set
+# CONFIG_BINFMT_SHARED_FLAT is not set
+# CONFIG_BINFMT_MISC is not set
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+# CONFIG_FW_LOADER is not set
+
+#
+# Memory Technology Devices (MTD)
+#
+# CONFIG_MTD is not set
+
+#
+# Parallel port support
+#
+# CONFIG_PARPORT is not set
+
+#
+# Plug and Play support
+#
+
+#
+# Block devices
+#
+# CONFIG_BLK_DEV_FD is not set
+CONFIG_BLK_DEV_LOOP=y
+# CONFIG_BLK_DEV_CRYPTOLOOP is not set
+CONFIG_BLK_DEV_NBD=y
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_SIZE=4096
+# CONFIG_BLK_DEV_INITRD is not set
+
+#
+# ATA/ATAPI/MFM/RLL support
+#
+# CONFIG_IDE is not set
+
+#
+# SCSI device support
+#
+# CONFIG_SCSI is not set
+
+#
+# Multi-device support (RAID and LVM)
+#
+# CONFIG_MD is not set
+
+#
+# Fusion MPT device support
+#
+
+#
+# IEEE 1394 (FireWire) support
+#
+
+#
+# I2O device support
+#
+
+#
+# Networking support
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+CONFIG_PACKET=y
+# CONFIG_PACKET_MMAP is not set
+# CONFIG_NETLINK_DEV is not set
+CONFIG_UNIX=y
+# CONFIG_NET_KEY is not set
+CONFIG_INET=y
+# CONFIG_IP_MULTICAST is not set
+# 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_RARP is not set
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+# CONFIG_ARPD 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
+# CONFIG_IPV6 is not set
+# CONFIG_NETFILTER is not set
+
+#
+# SCTP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_SCTP is not set
+# CONFIG_ATM is not set
+# CONFIG_BRIDGE is not set
+# CONFIG_VLAN_8021Q is not set
+# CONFIG_DECNET 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
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+# CONFIG_NET_HW_FLOWCONTROL is not set
+
+#
+# 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 is not set
+
+#
+# ISDN subsystem
+#
+# CONFIG_ISDN is not set
+
+#
+# Telephony Support
+#
+# CONFIG_PHONE is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+
+#
+# Userland interfaces
+#
+# CONFIG_INPUT_MOUSEDEV is not set
+# 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=y
+# CONFIG_SERIO_I8042 is not set
+CONFIG_SERIO_SERPORT=y
+# CONFIG_SERIO_CT82C710 is not set
+
+#
+# Input Device Drivers
+#
+# CONFIG_INPUT_KEYBOARD is not set
+# CONFIG_INPUT_MOUSE 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 is not set
+# CONFIG_SERIAL_NONSTANDARD is not set
+
+#
+# Serial drivers
+#
+# CONFIG_SERIAL_8250 is not set
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+CONFIG_SERIAL_M32R_SIO=y
+CONFIG_SERIAL_M32R_SIO_CONSOLE=y
+# CONFIG_SERIAL_M32R_PLDSIO is not set
+CONFIG_UNIX98_PTYS=y
+CONFIG_LEGACY_PTYS=y
+CONFIG_LEGACY_PTY_COUNT=256
+# CONFIG_QIC02_TAPE is not set
+
+#
+# IPMI
+#
+# CONFIG_IPMI_HANDLER is not set
+
+#
+# Watchdog Cards
+#
+# CONFIG_WATCHDOG is not set
+# CONFIG_RTC is not set
+# CONFIG_GEN_RTC is not set
+# CONFIG_DTLK is not set
+# CONFIG_R3964 is not set
+
+#
+# Ftape, the floppy tape device driver
+#
+# CONFIG_AGP is not set
+# CONFIG_DRM is not set
+# CONFIG_RAW_DRIVER is not set
+
+#
+# I2C support
+#
+# CONFIG_I2C is not set
+
+#
+# Dallas's 1-wire bus
+#
+# CONFIG_W1 is not set
+
+#
+# Misc devices
+#
+
+#
+# Multimedia devices
+#
+# CONFIG_VIDEO_DEV is not set
+
+#
+# Digital Video Broadcasting Devices
+#
+# CONFIG_DVB is not set
+
+#
+# Graphics support
+#
+# CONFIG_FB is not set
+
+#
+# Sound
+#
+# CONFIG_SOUND is not set
+
+#
+# USB support
+#
+
+#
+# USB Gadget Support
+#
+# CONFIG_USB_GADGET 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_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+# CONFIG_XFS_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_ROMFS_FS is not set
+# CONFIG_QUOTA is not set
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_AUTOFS4_FS is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+# CONFIG_ISO9660_FS is not set
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+# 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=y
+CONFIG_DEVFS_MOUNT=y
+# CONFIG_DEVFS_DEBUG is not set
+CONFIG_DEVPTS_FS_XATTR=y
+CONFIG_DEVPTS_FS_SECURITY=y
+# CONFIG_TMPFS is not set
+# 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_EFS_FS is not set
+# CONFIG_CRAMFS is not set
+# CONFIG_VXFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+
+#
+# Network File Systems
+#
+CONFIG_NFS_FS=y
+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_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_AFS_FS is not set
+
+#
+# Partition Types
+#
+# CONFIG_PARTITION_ADVANCED is not set
+CONFIG_MSDOS_PARTITION=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
+# CONFIG_NLS_CODEPAGE_775 is not set
+# CONFIG_NLS_CODEPAGE_850 is not set
+# CONFIG_NLS_CODEPAGE_852 is not set
+# CONFIG_NLS_CODEPAGE_855 is not set
+# CONFIG_NLS_CODEPAGE_857 is not set
+# CONFIG_NLS_CODEPAGE_860 is not set
+# CONFIG_NLS_CODEPAGE_861 is not set
+# CONFIG_NLS_CODEPAGE_862 is not set
+# CONFIG_NLS_CODEPAGE_863 is not set
+# CONFIG_NLS_CODEPAGE_864 is not set
+# CONFIG_NLS_CODEPAGE_865 is not set
+# CONFIG_NLS_CODEPAGE_866 is not set
+# CONFIG_NLS_CODEPAGE_869 is not set
+# CONFIG_NLS_CODEPAGE_936 is not set
+# CONFIG_NLS_CODEPAGE_950 is not set
+# CONFIG_NLS_CODEPAGE_932 is not set
+# CONFIG_NLS_CODEPAGE_949 is not set
+# CONFIG_NLS_CODEPAGE_874 is not set
+# 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
+# CONFIG_NLS_ISO8859_4 is not set
+# CONFIG_NLS_ISO8859_5 is not set
+# CONFIG_NLS_ISO8859_6 is not set
+# CONFIG_NLS_ISO8859_7 is not set
+# CONFIG_NLS_ISO8859_9 is not set
+# CONFIG_NLS_ISO8859_13 is not set
+# CONFIG_NLS_ISO8859_14 is not set
+# CONFIG_NLS_ISO8859_15 is not set
+# CONFIG_NLS_KOI8_R is not set
+# CONFIG_NLS_KOI8_U is not set
+# CONFIG_NLS_UTF8 is not set
+
+#
+# Profiling support
+#
+# CONFIG_PROFILING is not set
+
+#
+# Kernel hacking
+#
+# CONFIG_DEBUG_KERNEL is not set
+# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
+# CONFIG_FRAME_POINTER is not set
+
+#
+# Security options
+#
+# CONFIG_SECURITY is not set
+
+#
+# Cryptographic options
+#
+# CONFIG_CRYPTO is not set
+
+#
+# Library routines
+#
+# CONFIG_CRC_CCITT is not set
+CONFIG_CRC32=y
+# CONFIG_LIBCRC32C is not set
diff -Nru a/arch/m32r/mappi/defconfig.smp b/arch/m32r/mappi/defconfig.smp
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/arch/m32r/mappi/defconfig.smp	2004-10-18 14:57:23 -07:00
@@ -0,0 +1,646 @@
+#
+# Automatically generated make config: don't edit
+#
+CONFIG_M32R=y
+CONFIG_UID16=y
+CONFIG_GENERIC_ISA_DMA=y
+
+#
+# Code maturity level options
+#
+CONFIG_EXPERIMENTAL=y
+# CONFIG_CLEAN_COMPILE is not set
+CONFIG_BROKEN=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=15
+CONFIG_HOTPLUG=y
+CONFIG_IKCONFIG=y
+CONFIG_IKCONFIG_PROC=y
+CONFIG_EMBEDDED=y
+# CONFIG_KALLSYMS is not set
+# CONFIG_FUTEX is not set
+# CONFIG_EPOLL is not set
+CONFIG_IOSCHED_NOOP=y
+# CONFIG_IOSCHED_AS is not set
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+
+#
+# Loadable module support
+#
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+# CONFIG_MODULE_FORCE_UNLOAD is not set
+CONFIG_OBSOLETE_MODPARM=y
+# CONFIG_MODVERSIONS is not set
+CONFIG_KMOD=y
+CONFIG_STOP_MACHINE=y
+
+#
+# Processor type and features
+#
+CONFIG_PLAT_MAPPI=y
+# CONFIG_PLAT_USRV is not set
+# CONFIG_PLAT_M32700UT is not set
+# CONFIG_PLAT_OPSPUT is not set
+# CONFIG_PLAT_OAKS32R is not set
+# CONFIG_PLAT_MAPPI2 is not set
+CONFIG_CHIP_M32700=y
+# CONFIG_CHIP_M32102 is not set
+# CONFIG_CHIP_VDEC2 is not set
+# CONFIG_CHIP_OPSP is not set
+CONFIG_MMU=y
+CONFIG_TLB_ENTRIES=32
+CONFIG_ISA_M32R2=y
+CONFIG_ISA_DSP_LEVEL2=y
+CONFIG_ISA_DUAL_ISSUE=y
+CONFIG_BUS_CLOCK=10000000
+CONFIG_TIMER_DIVIDE=128
+# CONFIG_CPU_LITTLE_ENDIAN is not set
+CONFIG_MEMORY_START=0x08000000
+CONFIG_MEMORY_SIZE=0x04000000
+CONFIG_NOHIGHMEM=y
+CONFIG_DISCONTIGMEM=y
+CONFIG_IRAM_START=0x00f00000
+CONFIG_IRAM_SIZE=0x00080000
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+# CONFIG_RWSEM_XCHGADD_ALGORITHM is not set
+CONFIG_PREEMPT=y
+# CONFIG_HAVE_DEC_LOCK is not set
+CONFIG_SMP=y
+CONFIG_CHIP_M32700_TS1=y
+CONFIG_NR_CPUS=2
+# CONFIG_NUMA is not set
+
+#
+# M32R drivers
+#
+CONFIG_M32RPCC=y
+CONFIG_M32R_NE2000=y
+
+#
+# Power management options (ACPI, APM)
+#
+# CONFIG_PM is not set
+
+#
+# Bus options (PCI, PCMCIA, EISA, MCA, ISA)
+#
+# CONFIG_PCI is not set
+# CONFIG_ISA is not set
+
+#
+# PCMCIA/CardBus support
+#
+CONFIG_PCMCIA=y
+# CONFIG_PCMCIA_DEBUG is not set
+# CONFIG_TCIC is not set
+
+#
+# PCI Hotplug Support
+#
+
+#
+# Executable file formats
+#
+CONFIG_BINFMT_ELF=y
+# CONFIG_BINFMT_MISC is not set
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+# CONFIG_STANDALONE is not set
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+# CONFIG_FW_LOADER is not set
+
+#
+# Memory Technology Devices (MTD)
+#
+CONFIG_MTD=y
+# CONFIG_MTD_DEBUG is not set
+CONFIG_MTD_PARTITIONS=y
+# CONFIG_MTD_CONCAT is not set
+CONFIG_MTD_REDBOOT_PARTS=y
+# CONFIG_MTD_REDBOOT_PARTS_UNALLOCATED is not set
+# CONFIG_MTD_REDBOOT_PARTS_READONLY is not set
+# CONFIG_MTD_CMDLINE_PARTS is not set
+
+#
+# User Modules And Translation Layers
+#
+CONFIG_MTD_CHAR=y
+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 is not set
+
+#
+# Disk-On-Chip Device Drivers
+#
+# CONFIG_MTD_DOC2000 is not set
+# CONFIG_MTD_DOC2001 is not set
+# CONFIG_MTD_DOC2001PLUS is not set
+
+#
+# NAND Flash Device Drivers
+#
+# CONFIG_MTD_NAND is not set
+
+#
+# Parallel port support
+#
+# CONFIG_PARPORT is not set
+
+#
+# Plug and Play support
+#
+
+#
+# Block devices
+#
+# CONFIG_BLK_DEV_FD is not set
+CONFIG_BLK_DEV_LOOP=y
+# CONFIG_BLK_DEV_CRYPTOLOOP is not set
+CONFIG_BLK_DEV_NBD=m
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_SIZE=4096
+CONFIG_BLK_DEV_INITRD=y
+
+#
+# ATA/ATAPI/MFM/RLL support
+#
+CONFIG_IDE=m
+CONFIG_BLK_DEV_IDE=m
+
+#
+# Please see Documentation/ide.txt for help/info on IDE drives
+#
+# CONFIG_BLK_DEV_IDE_SATA is not set
+CONFIG_BLK_DEV_IDEDISK=m
+# CONFIG_IDEDISK_MULTI_MODE is not set
+CONFIG_BLK_DEV_IDECS=m
+CONFIG_BLK_DEV_IDECD=m
+# CONFIG_BLK_DEV_IDETAPE is not set
+# CONFIG_BLK_DEV_IDEFLOPPY is not set
+# CONFIG_IDE_TASK_IOCTL is not set
+# CONFIG_IDE_TASKFILE_IO is not set
+
+#
+# IDE chipset support/bugfixes
+#
+CONFIG_IDE_GENERIC=m
+# 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 device support
+#
+# CONFIG_SCSI is not set
+
+#
+# Multi-device support (RAID and LVM)
+#
+# CONFIG_MD is not set
+
+#
+# Fusion MPT device support
+#
+
+#
+# IEEE 1394 (FireWire) support
+#
+# CONFIG_IEEE1394 is not set
+
+#
+# I2O device support
+#
+
+#
+# Networking support
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+# CONFIG_PACKET is not set
+# CONFIG_NETLINK_DEV is not set
+CONFIG_UNIX=y
+# CONFIG_NET_KEY is not set
+CONFIG_INET=y
+# CONFIG_IP_MULTICAST is not set
+# 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_RARP is not set
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+# CONFIG_ARPD 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
+# CONFIG_IPV6 is not set
+# CONFIG_NETFILTER is not set
+
+#
+# SCTP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_SCTP is not set
+# CONFIG_ATM is not set
+# CONFIG_BRIDGE is not set
+# CONFIG_VLAN_8021Q is not set
+# CONFIG_DECNET 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
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+# CONFIG_NET_HW_FLOWCONTROL is not set
+
+#
+# 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 is not set
+
+#
+# ISDN subsystem
+#
+# CONFIG_ISDN is not set
+
+#
+# Telephony Support
+#
+# CONFIG_PHONE is not set
+
+#
+# Input device support
+#
+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=y
+# CONFIG_SERIO_I8042 is not set
+# CONFIG_SERIO_SERPORT is not set
+# CONFIG_SERIO_CT82C710 is not set
+
+#
+# Input Device Drivers
+#
+# CONFIG_INPUT_KEYBOARD is not set
+# CONFIG_INPUT_MOUSE 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 is not set
+# CONFIG_SERIAL_NONSTANDARD is not set
+
+#
+# Serial drivers
+#
+# CONFIG_SERIAL_8250 is not set
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+CONFIG_SERIAL_M32R_SIO=y
+CONFIG_SERIAL_M32R_SIO_CONSOLE=y
+# CONFIG_SERIAL_M32R_PLDSIO is not set
+CONFIG_UNIX98_PTYS=y
+CONFIG_LEGACY_PTYS=y
+CONFIG_LEGACY_PTY_COUNT=256
+# CONFIG_QIC02_TAPE is not set
+
+#
+# IPMI
+#
+# CONFIG_IPMI_HANDLER is not set
+
+#
+# Watchdog Cards
+#
+# CONFIG_WATCHDOG is not set
+# CONFIG_RTC is not set
+# CONFIG_GEN_RTC is not set
+# CONFIG_DTLK is not set
+# CONFIG_R3964 is not set
+
+#
+# Ftape, the floppy tape device driver
+#
+# CONFIG_AGP is not set
+# CONFIG_DRM is not set
+
+#
+# PCMCIA character devices
+#
+# CONFIG_SYNCLINK_CS is not set
+# CONFIG_RAW_DRIVER is not set
+
+#
+# I2C support
+#
+# CONFIG_I2C is not set
+
+#
+# Dallas's 1-wire bus
+#
+# CONFIG_W1 is not set
+
+#
+# Misc devices
+#
+
+#
+# Multimedia devices
+#
+# CONFIG_VIDEO_DEV is not set
+
+#
+# Digital Video Broadcasting Devices
+#
+# CONFIG_DVB is not set
+
+#
+# Graphics support
+#
+# CONFIG_FB is not set
+
+#
+# Sound
+#
+# CONFIG_SOUND is not set
+
+#
+# USB support
+#
+
+#
+# USB Gadget Support
+#
+# CONFIG_USB_GADGET 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_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+# CONFIG_XFS_FS is not set
+# CONFIG_MINIX_FS is not set
+CONFIG_ROMFS_FS=y
+# CONFIG_QUOTA is not set
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_AUTOFS4_FS is not set
+
+#
+# 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=m
+CONFIG_MSDOS_FS=m
+CONFIG_VFAT_FS=m
+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_HUGETLBFS is not set
+# 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_EFS_FS is not set
+CONFIG_JFFS_FS=y
+CONFIG_JFFS_FS_VERBOSE=0
+CONFIG_JFFS_PROC_FS=y
+CONFIG_JFFS2_FS=y
+CONFIG_JFFS2_FS_DEBUG=0
+# CONFIG_JFFS2_FS_NAND is not set
+# CONFIG_JFFS2_COMPRESSION_OPTIONS is not set
+CONFIG_JFFS2_ZLIB=y
+CONFIG_JFFS2_RTIME=y
+# CONFIG_JFFS2_RUBIN is not set
+# CONFIG_CRAMFS is not set
+# CONFIG_VXFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+
+#
+# Network File Systems
+#
+CONFIG_NFS_FS=y
+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_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_AFS_FS is not set
+
+#
+# Partition Types
+#
+# CONFIG_PARTITION_ADVANCED is not set
+CONFIG_MSDOS_PARTITION=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
+# CONFIG_NLS_CODEPAGE_775 is not set
+# CONFIG_NLS_CODEPAGE_850 is not set
+# CONFIG_NLS_CODEPAGE_852 is not set
+# CONFIG_NLS_CODEPAGE_855 is not set
+# CONFIG_NLS_CODEPAGE_857 is not set
+# CONFIG_NLS_CODEPAGE_860 is not set
+# CONFIG_NLS_CODEPAGE_861 is not set
+# CONFIG_NLS_CODEPAGE_862 is not set
+# CONFIG_NLS_CODEPAGE_863 is not set
+# CONFIG_NLS_CODEPAGE_864 is not set
+# CONFIG_NLS_CODEPAGE_865 is not set
+# CONFIG_NLS_CODEPAGE_866 is not set
+# CONFIG_NLS_CODEPAGE_869 is not set
+# CONFIG_NLS_CODEPAGE_936 is not set
+# CONFIG_NLS_CODEPAGE_950 is not set
+# CONFIG_NLS_CODEPAGE_932 is not set
+# CONFIG_NLS_CODEPAGE_949 is not set
+# CONFIG_NLS_CODEPAGE_874 is not set
+# 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
+# CONFIG_NLS_ISO8859_4 is not set
+# CONFIG_NLS_ISO8859_5 is not set
+# CONFIG_NLS_ISO8859_6 is not set
+# CONFIG_NLS_ISO8859_7 is not set
+# CONFIG_NLS_ISO8859_9 is not set
+# CONFIG_NLS_ISO8859_13 is not set
+# CONFIG_NLS_ISO8859_14 is not set
+# CONFIG_NLS_ISO8859_15 is not set
+# CONFIG_NLS_KOI8_R is not set
+# CONFIG_NLS_KOI8_U is not set
+# CONFIG_NLS_UTF8 is not set
+
+#
+# Profiling support
+#
+# CONFIG_PROFILING is not set
+
+#
+# Kernel hacking
+#
+# CONFIG_DEBUG_KERNEL is not set
+# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
+# CONFIG_FRAME_POINTER is not set
+
+#
+# Security options
+#
+# CONFIG_SECURITY is not set
+
+#
+# Cryptographic options
+#
+# CONFIG_CRYPTO is not set
+
+#
+# Library routines
+#
+# CONFIG_CRC_CCITT is not set
+CONFIG_CRC32=y
+# CONFIG_LIBCRC32C is not set
+CONFIG_ZLIB_INFLATE=y
+CONFIG_ZLIB_DEFLATE=y
diff -Nru a/arch/m32r/mappi/defconfig.up b/arch/m32r/mappi/defconfig.up
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/arch/m32r/mappi/defconfig.up	2004-10-18 14:57:23 -07:00
@@ -0,0 +1,642 @@
+#
+# Automatically generated make config: don't edit
+#
+CONFIG_M32R=y
+CONFIG_UID16=y
+CONFIG_GENERIC_ISA_DMA=y
+
+#
+# Code maturity level options
+#
+CONFIG_EXPERIMENTAL=y
+# CONFIG_CLEAN_COMPILE is not set
+CONFIG_BROKEN=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=y
+CONFIG_IKCONFIG=y
+CONFIG_IKCONFIG_PROC=y
+CONFIG_EMBEDDED=y
+# CONFIG_KALLSYMS is not set
+# CONFIG_FUTEX is not set
+# CONFIG_EPOLL is not set
+CONFIG_IOSCHED_NOOP=y
+# CONFIG_IOSCHED_AS is not set
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+
+#
+# Loadable module support
+#
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+# CONFIG_MODULE_FORCE_UNLOAD is not set
+CONFIG_OBSOLETE_MODPARM=y
+# CONFIG_MODVERSIONS is not set
+CONFIG_KMOD=y
+
+#
+# Processor type and features
+#
+CONFIG_PLAT_MAPPI=y
+# CONFIG_PLAT_USRV is not set
+# CONFIG_PLAT_M32700UT is not set
+# CONFIG_PLAT_OPSPUT is not set
+# CONFIG_PLAT_OAKS32R is not set
+# CONFIG_PLAT_MAPPI2 is not set
+CONFIG_CHIP_M32700=y
+# CONFIG_CHIP_M32102 is not set
+# CONFIG_CHIP_VDEC2 is not set
+# CONFIG_CHIP_OPSP is not set
+CONFIG_MMU=y
+CONFIG_TLB_ENTRIES=32
+CONFIG_ISA_M32R2=y
+CONFIG_ISA_DSP_LEVEL2=y
+CONFIG_ISA_DUAL_ISSUE=y
+CONFIG_BUS_CLOCK=10000000
+CONFIG_TIMER_DIVIDE=128
+# CONFIG_CPU_LITTLE_ENDIAN is not set
+CONFIG_MEMORY_START=0x08000000
+CONFIG_MEMORY_SIZE=0x04000000
+CONFIG_NOHIGHMEM=y
+CONFIG_DISCONTIGMEM=y
+CONFIG_IRAM_START=0x00f00000
+CONFIG_IRAM_SIZE=0x00080000
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+# CONFIG_RWSEM_XCHGADD_ALGORITHM is not set
+CONFIG_PREEMPT=y
+# CONFIG_HAVE_DEC_LOCK is not set
+# CONFIG_SMP is not set
+
+#
+# M32R drivers
+#
+CONFIG_M32RPCC=y
+CONFIG_M32R_NE2000=y
+
+#
+# Power management options (ACPI, APM)
+#
+# CONFIG_PM is not set
+
+#
+# Bus options (PCI, PCMCIA, EISA, MCA, ISA)
+#
+# CONFIG_PCI is not set
+# CONFIG_ISA is not set
+
+#
+# PCMCIA/CardBus support
+#
+CONFIG_PCMCIA=y
+# CONFIG_PCMCIA_DEBUG is not set
+# CONFIG_TCIC is not set
+
+#
+# PCI Hotplug Support
+#
+
+#
+# Executable file formats
+#
+CONFIG_BINFMT_ELF=y
+# CONFIG_BINFMT_MISC is not set
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+# CONFIG_STANDALONE is not set
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+# CONFIG_FW_LOADER is not set
+
+#
+# Memory Technology Devices (MTD)
+#
+CONFIG_MTD=y
+# CONFIG_MTD_DEBUG is not set
+CONFIG_MTD_PARTITIONS=y
+# CONFIG_MTD_CONCAT is not set
+CONFIG_MTD_REDBOOT_PARTS=y
+# CONFIG_MTD_REDBOOT_PARTS_UNALLOCATED is not set
+# CONFIG_MTD_REDBOOT_PARTS_READONLY is not set
+# CONFIG_MTD_CMDLINE_PARTS is not set
+
+#
+# User Modules And Translation Layers
+#
+CONFIG_MTD_CHAR=y
+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 is not set
+
+#
+# Disk-On-Chip Device Drivers
+#
+# CONFIG_MTD_DOC2000 is not set
+# CONFIG_MTD_DOC2001 is not set
+# CONFIG_MTD_DOC2001PLUS is not set
+
+#
+# NAND Flash Device Drivers
+#
+# CONFIG_MTD_NAND is not set
+
+#
+# Parallel port support
+#
+# CONFIG_PARPORT is not set
+
+#
+# Plug and Play support
+#
+
+#
+# Block devices
+#
+# CONFIG_BLK_DEV_FD is not set
+CONFIG_BLK_DEV_LOOP=y
+# CONFIG_BLK_DEV_CRYPTOLOOP is not set
+CONFIG_BLK_DEV_NBD=m
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_SIZE=4096
+CONFIG_BLK_DEV_INITRD=y
+
+#
+# ATA/ATAPI/MFM/RLL support
+#
+CONFIG_IDE=m
+CONFIG_BLK_DEV_IDE=m
+
+#
+# Please see Documentation/ide.txt for help/info on IDE drives
+#
+# CONFIG_BLK_DEV_IDE_SATA is not set
+CONFIG_BLK_DEV_IDEDISK=m
+# CONFIG_IDEDISK_MULTI_MODE is not set
+CONFIG_BLK_DEV_IDECS=m
+CONFIG_BLK_DEV_IDECD=m
+# CONFIG_BLK_DEV_IDETAPE is not set
+# CONFIG_BLK_DEV_IDEFLOPPY is not set
+# CONFIG_IDE_TASK_IOCTL is not set
+# CONFIG_IDE_TASKFILE_IO is not set
+
+#
+# IDE chipset support/bugfixes
+#
+CONFIG_IDE_GENERIC=m
+# 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 device support
+#
+# CONFIG_SCSI is not set
+
+#
+# Multi-device support (RAID and LVM)
+#
+# CONFIG_MD is not set
+
+#
+# Fusion MPT device support
+#
+
+#
+# IEEE 1394 (FireWire) support
+#
+# CONFIG_IEEE1394 is not set
+
+#
+# I2O device support
+#
+
+#
+# Networking support
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+# CONFIG_PACKET is not set
+# CONFIG_NETLINK_DEV is not set
+CONFIG_UNIX=y
+# CONFIG_NET_KEY is not set
+CONFIG_INET=y
+# CONFIG_IP_MULTICAST is not set
+# 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_RARP is not set
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+# CONFIG_ARPD 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
+# CONFIG_IPV6 is not set
+# CONFIG_NETFILTER is not set
+
+#
+# SCTP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_SCTP is not set
+# CONFIG_ATM is not set
+# CONFIG_BRIDGE is not set
+# CONFIG_VLAN_8021Q is not set
+# CONFIG_DECNET 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
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+# CONFIG_NET_HW_FLOWCONTROL is not set
+
+#
+# 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 is not set
+
+#
+# ISDN subsystem
+#
+# CONFIG_ISDN is not set
+
+#
+# Telephony Support
+#
+# CONFIG_PHONE is not set
+
+#
+# Input device support
+#
+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=y
+# CONFIG_SERIO_I8042 is not set
+# CONFIG_SERIO_SERPORT is not set
+# CONFIG_SERIO_CT82C710 is not set
+
+#
+# Input Device Drivers
+#
+# CONFIG_INPUT_KEYBOARD is not set
+# CONFIG_INPUT_MOUSE 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 is not set
+# CONFIG_SERIAL_NONSTANDARD is not set
+
+#
+# Serial drivers
+#
+# CONFIG_SERIAL_8250 is not set
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+CONFIG_SERIAL_M32R_SIO=y
+CONFIG_SERIAL_M32R_SIO_CONSOLE=y
+# CONFIG_SERIAL_M32R_PLDSIO is not set
+CONFIG_UNIX98_PTYS=y
+CONFIG_LEGACY_PTYS=y
+CONFIG_LEGACY_PTY_COUNT=256
+# CONFIG_QIC02_TAPE is not set
+
+#
+# IPMI
+#
+# CONFIG_IPMI_HANDLER is not set
+
+#
+# Watchdog Cards
+#
+# CONFIG_WATCHDOG is not set
+# CONFIG_RTC is not set
+# CONFIG_GEN_RTC is not set
+# CONFIG_DTLK is not set
+# CONFIG_R3964 is not set
+
+#
+# Ftape, the floppy tape device driver
+#
+# CONFIG_AGP is not set
+# CONFIG_DRM is not set
+
+#
+# PCMCIA character devices
+#
+# CONFIG_SYNCLINK_CS is not set
+# CONFIG_RAW_DRIVER is not set
+
+#
+# I2C support
+#
+# CONFIG_I2C is not set
+
+#
+# Dallas's 1-wire bus
+#
+# CONFIG_W1 is not set
+
+#
+# Misc devices
+#
+
+#
+# Multimedia devices
+#
+# CONFIG_VIDEO_DEV is not set
+
+#
+# Digital Video Broadcasting Devices
+#
+# CONFIG_DVB is not set
+
+#
+# Graphics support
+#
+# CONFIG_FB is not set
+
+#
+# Sound
+#
+# CONFIG_SOUND is not set
+
+#
+# USB support
+#
+
+#
+# USB Gadget Support
+#
+# CONFIG_USB_GADGET 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_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+# CONFIG_XFS_FS is not set
+# CONFIG_MINIX_FS is not set
+CONFIG_ROMFS_FS=y
+# CONFIG_QUOTA is not set
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_AUTOFS4_FS is not set
+
+#
+# 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=m
+CONFIG_MSDOS_FS=m
+CONFIG_VFAT_FS=m
+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_HUGETLBFS is not set
+# 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_EFS_FS is not set
+CONFIG_JFFS_FS=y
+CONFIG_JFFS_FS_VERBOSE=0
+CONFIG_JFFS_PROC_FS=y
+CONFIG_JFFS2_FS=y
+CONFIG_JFFS2_FS_DEBUG=0
+# CONFIG_JFFS2_FS_NAND is not set
+# CONFIG_JFFS2_COMPRESSION_OPTIONS is not set
+CONFIG_JFFS2_ZLIB=y
+CONFIG_JFFS2_RTIME=y
+# CONFIG_JFFS2_RUBIN is not set
+# CONFIG_CRAMFS is not set
+# CONFIG_VXFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+
+#
+# Network File Systems
+#
+CONFIG_NFS_FS=y
+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_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_AFS_FS is not set
+
+#
+# Partition Types
+#
+# CONFIG_PARTITION_ADVANCED is not set
+CONFIG_MSDOS_PARTITION=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
+# CONFIG_NLS_CODEPAGE_775 is not set
+# CONFIG_NLS_CODEPAGE_850 is not set
+# CONFIG_NLS_CODEPAGE_852 is not set
+# CONFIG_NLS_CODEPAGE_855 is not set
+# CONFIG_NLS_CODEPAGE_857 is not set
+# CONFIG_NLS_CODEPAGE_860 is not set
+# CONFIG_NLS_CODEPAGE_861 is not set
+# CONFIG_NLS_CODEPAGE_862 is not set
+# CONFIG_NLS_CODEPAGE_863 is not set
+# CONFIG_NLS_CODEPAGE_864 is not set
+# CONFIG_NLS_CODEPAGE_865 is not set
+# CONFIG_NLS_CODEPAGE_866 is not set
+# CONFIG_NLS_CODEPAGE_869 is not set
+# CONFIG_NLS_CODEPAGE_936 is not set
+# CONFIG_NLS_CODEPAGE_950 is not set
+# CONFIG_NLS_CODEPAGE_932 is not set
+# CONFIG_NLS_CODEPAGE_949 is not set
+# CONFIG_NLS_CODEPAGE_874 is not set
+# 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
+# CONFIG_NLS_ISO8859_4 is not set
+# CONFIG_NLS_ISO8859_5 is not set
+# CONFIG_NLS_ISO8859_6 is not set
+# CONFIG_NLS_ISO8859_7 is not set
+# CONFIG_NLS_ISO8859_9 is not set
+# CONFIG_NLS_ISO8859_13 is not set
+# CONFIG_NLS_ISO8859_14 is not set
+# CONFIG_NLS_ISO8859_15 is not set
+# CONFIG_NLS_KOI8_R is not set
+# CONFIG_NLS_KOI8_U is not set
+# CONFIG_NLS_UTF8 is not set
+
+#
+# Profiling support
+#
+# CONFIG_PROFILING is not set
+
+#
+# Kernel hacking
+#
+# CONFIG_DEBUG_KERNEL is not set
+# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
+# CONFIG_FRAME_POINTER is not set
+
+#
+# Security options
+#
+# CONFIG_SECURITY is not set
+
+#
+# Cryptographic options
+#
+# CONFIG_CRYPTO is not set
+
+#
+# Library routines
+#
+# CONFIG_CRC_CCITT is not set
+CONFIG_CRC32=y
+# CONFIG_LIBCRC32C is not set
+CONFIG_ZLIB_INFLATE=y
+CONFIG_ZLIB_DEFLATE=y
diff -Nru a/arch/m32r/mappi/dot.gdbinit b/arch/m32r/mappi/dot.gdbinit
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/arch/m32r/mappi/dot.gdbinit	2004-10-18 14:57:21 -07:00
@@ -0,0 +1,242 @@
+# .gdbinit file
+# $Id$
+#-----
+# NOTE: this file is generated by a script, "gen_gdbinit.pl".
+# (Please type "gen_gdbinit.pl --help" and check the help message).
+# $ Id: gen_gdbinit.pl,v 1.8 2004/02/27 07:08:32 takata Exp $
+#-----
+# target platform: mappi
+
+# setting
+set width 0d70
+set radix 0d16
+debug_chaos
+
+# clk xin:cpu:bif:bus=30:360:180:90
+define clock_init
+  set *(unsigned long *)0x00ef4024 = 2
+  set *(unsigned long *)0x00ef4020 = 1
+  set *(unsigned long *)0x00ef4010 = 0
+  set *(unsigned long *)0x00ef4014 = 0
+  set *(unsigned long *)0x00ef4004 = 5
+  shell sleep 0.1
+  set *(unsigned long *)0x00ef4008 = 0x00000200
+end
+
+# Initialize programmable ports
+define port_init
+  set $sfrbase = 0x00ef0000
+  set *(unsigned short *)0x00ef1060 = 0x5555
+  set *(unsigned short *)0x00ef1062 = 0x5555
+  set *(unsigned short *)0x00ef1064 = 0x5555
+  set *(unsigned short *)0x00ef1066 = 0x5555
+  set *(unsigned short *)0x00ef1068 = 0x5555
+  set *(unsigned short *)0x00ef106a = 0x0000
+  set *(unsigned short *)0x00ef106e = 0x5555
+  set *(unsigned short *)0x00ef1070 = 0x5555
+  # LED ON
+  set *(unsigned char *)($sfrbase + 0x1015) = 0xff
+  set *(unsigned char *)($sfrbase + 0x1085) = 0xff
+  shell sleep 0.1
+  # LED OFF
+  set *(unsigned char *)($sfrbase + 0x1085) = 0x00
+end
+document port_init
+  P5=LED(output), P6.b4=LAN_RESET(output)
+end
+
+# Initialize SDRAM controller
+define sdram_init
+  # SDIR0
+  set *(unsigned long *)0x00ef6008 = 0x00000182
+  # SDIR1
+  set *(unsigned long *)0x00ef600c = 0x00000001
+  # Initialize wait
+  shell sleep 0.1
+  # Ch0-MOD
+  set *(unsigned long *)0x00ef602c = 0x00000020
+  # Ch0-TR
+  set *(unsigned long *)0x00ef6028 = 0x00051502
+  # Ch0-ADR (size:64MB)
+  set *(unsigned long *)0x00ef6020 = 0x08000004
+  # AutoRef On
+  set *(unsigned long *)0x00ef6004 = 0x00010e2b
+  # Access enable
+  set *(unsigned long *)0x00ef6024 = 0x00000001
+end
+document sdram_init
+  SDRAM controller initialization
+  0x08000000 - 0x0bffffff (64MB)
+end
+
+# Initialize LAN controller
+define lanc_init
+  set $sfrbase = 0x00ef0000
+  # Set BSEL3 (BSEL3 for the Chaos's bselc)
+  set *(unsigned long *)($sfrbase + 0x5300) = 0x0a0a8040
+  set *(unsigned long *)($sfrbase + 0x5304) = 0x01120203
+  set *(unsigned long *)($sfrbase + 0x5308) = 0x00000001
+  # Reset (P5=LED,P6.b4=LAN_RESET)
+  set *(unsigned short *)($sfrbase + 0x106c) = 0x0000
+  set *(unsigned char *)($sfrbase + 0x1016) = 0xff
+  set *(unsigned char *)($sfrbase + 0x1086) = 0xff
+  shell sleep 0.1
+  # swivel: 0=normal, 4=reverse
+#  set *(unsigned char *)($sfrbase + 0x1086) = 0x00
+  set *(unsigned char *)($sfrbase + 0x1086) = 0x04
+  set *(unsigned long *)(0x0c000330) = 0xffffffff
+  # Set mac address
+  set $lanc = (void*)0x0c000300
+  set *(unsigned long *)($lanc + 0x0000) = 0x00610010
+  set *(unsigned long *)($lanc + 0x0004) = 0x00200030
+  set *(unsigned long *)($lanc + 0x0008) = 0x00400050
+  set *(unsigned long *)($lanc + 0x000c) = 0x00600007
+end
+document lanc_init
+  LAN controller initialization
+  ex.) MAC address:  10 20 30 40 50 60
+end
+
+# LCD & CRT dual-head setting (8bpp)
+define dispc_init
+  set $sfrbase = 0x00ef0000
+  # BSEL4 Dispc
+  set *(unsigned long *)($sfrbase + 0x5400) = 0x0e0e8000
+  set *(unsigned long *)($sfrbase + 0x5404) = 0x0012220a
+end
+
+# MMU enable
+define mmu_enable
+  set $evb=0x88000000
+  set *(unsigned long *)0xffff0024=1
+end
+
+# MMU disable
+define mmu_disable
+  set $evb=0
+  set *(unsigned long *)0xffff0024=0
+end
+
+# Show TLB entries
+define show_tlb_entries
+  set $i = 0
+  set $addr = $arg0
+  set $nr_entries = $arg1
+  use_mon_code
+  while ($i < $nr_entries)
+    set $tlb_tag = *(unsigned long*)$addr
+    set $tlb_data = *(unsigned long*)($addr + 4)
+    printf " [%2d] 0x%08lx : 0x%08lx - 0x%08lx\n", $i, $addr, $tlb_tag, $tlb_data
+    set $i = $i + 1
+    set $addr = $addr + 8
+  end
+  use_debug_dma
+end
+define itlb
+  set $itlb=0xfe000000
+  show_tlb_entries $itlb 0d32
+end
+define dtlb
+  set $dtlb=0xfe000800
+  show_tlb_entries $dtlb 0d32
+end
+
+# Show current task structure
+define show_current
+  set $current = $spi & 0xffffe000
+  printf "$current=0x%08lX\n",$current
+  print *(struct task_struct *)$current
+end
+
+# Show user assigned task structure
+define show_task
+  set  = $arg0 & 0xffffe000
+  printf "$task=0x%08lX\n",$task
+  print *(struct task_struct *)$task
+end
+document show_task
+  Show user assigned task structure
+  arg0 : task structure address
+end
+
+# Show M32R registers
+define show_regs
+  printf " R0[0x%08lX]   R1[0x%08lX]   R2[0x%08lX]   R3[0x%08lX]\n",$r0,$r1,$r2,$r3
+  printf " R4[0x%08lX]   R5[0x%08lX]   R6[0x%08lX]   R7[0x%08lX]\n",$r4,$r5,$r6,$r7
+  printf " R8[0x%08lX]   R9[0x%08lX]  R10[0x%08lX]  R11[0x%08lX]\n",$r8,$r9,$r10,$r11
+  printf "R12[0x%08lX]   FP[0x%08lX]   LR[0x%08lX]   SP[0x%08lX]\n",$r12,$fp,$lr,$sp
+  printf "PSW[0x%08lX]  CBR[0x%08lX]  SPI[0x%08lX]  SPU[0x%08lX]\n",$psw,$cbr,$spi,$spu
+  printf "BPC[0x%08lX]   PC[0x%08lX] ACCL[0x%08lX] ACCH[0x%08lX]\n",$bpc,$pc,$accl,$acch
+  printf "EVB[0x%08lX]\n",$evb
+end
+
+# Setup all
+define setup
+  use_mon_code
+  set *(unsigned int)0xfffffffc=0x60
+  shell sleep 0.1
+  clock_init
+  shell sleep 0.1
+  port_init
+  sdram_init
+  lanc_init
+  dispc_init
+  set $evb=0x08000000
+end
+
+# Load modules
+define load_modules
+  use_debug_dma
+  load
+end
+
+# Set kernel parameters
+define set_kernel_parameters
+  set $param = (void*)0x08002000
+  # INITRD_START
+  set *(unsigned long *)($param + 0x0010) = 0x082a0000
+  # INITRD_SIZE
+  set *(unsigned long *)($param + 0x0014) = 0x00000000
+  # M32R_CPUCLK
+  set *(unsigned long *)($param + 0x0018) = 0d360000000
+  # M32R_BUSCLK
+  set *(unsigned long *)($param + 0x001c) = 0d90000000
+
+  # M32R_TIMER_DIVIDE
+  set *(unsigned long *)($param + 0x0020) = 0d128
+
+  set {char[0x200]}($param + 0x100) = "console=ttyD0,115200n8x root=/dev/nfsroot nfsroot=192.168.0.1:/project/m32r-linux/export/root.x nfsaddrs=192.168.0.101:192.168.0.1:192.168.0.1:255.255.255.0:mappi001 \0"
+end
+
+# Boot
+define boot
+  set_kernel_parameters
+  set $fp = 0
+  set $pc=0x08001000
+  si
+  c
+end
+
+# Set breakpoints
+define set_breakpoints
+  b *0x08000030
+end
+
+# Restart
+define restart
+  sdireset
+  sdireset
+  setup
+  load_modules
+  boot
+end
+
+sdireset
+sdireset
+file vmlinux
+target m32rsdi
+setup
+#load_module
+#set_breakpoints
+#boot
+
diff -Nru a/arch/m32r/mappi/dot.gdbinit.nommu b/arch/m32r/mappi/dot.gdbinit.nommu
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/arch/m32r/mappi/dot.gdbinit.nommu	2004-10-18 14:57:23 -07:00
@@ -0,0 +1,245 @@
+# .gdbinit file
+# $Id$
+#-----
+# NOTE: this file is generated by a script, "gen_gdbinit.pl".
+# (Please type "gen_gdbinit.pl --help" and check the help message).
+# $ Id: gen_gdbinit.pl,v 1.5 2004/01/23 08:23:25 takata Exp $
+#-----
+# target platform: mappi
+
+# setting
+set width 0d70
+set radix 0d16
+debug_chaos
+
+# clk xin:cpu:bif:bus=25:200:50:50
+define clock_init
+  set *(unsigned long *)0x00ef4024 = 2
+  set *(unsigned long *)0x00ef4020 = 2
+  set *(unsigned long *)0x00ef4010 = 0
+  set *(unsigned long *)0x00ef4014 = 0
+  set *(unsigned long *)0x00ef4004 = 3
+  shell sleep 0.1
+  set *(unsigned long *)0x00ef4008 = 0x00000200
+end
+
+# Initialize programmable ports
+define port_init
+  set $sfrbase = 0x00ef0000
+  set *(unsigned short *)0x00ef1060 = 0x5555
+  set *(unsigned short *)0x00ef1062 = 0x5555
+  set *(unsigned short *)0x00ef1064 = 0x5555
+  set *(unsigned short *)0x00ef1066 = 0x5555
+  set *(unsigned short *)0x00ef1068 = 0x5555
+  set *(unsigned short *)0x00ef106a = 0x0000
+  set *(unsigned short *)0x00ef106e = 0x5555
+  set *(unsigned short *)0x00ef1070 = 0x5555
+  # LED ON
+  set *(unsigned char *)($sfrbase + 0x1015) = 0xff
+  set *(unsigned char *)($sfrbase + 0x1085) = 0xff
+  shell sleep 0.1
+  # LED OFF
+  set *(unsigned char *)($sfrbase + 0x1085) = 0x00
+end
+document port_init
+  P5=LED(output), P6.b4=LAN_RESET(output)
+end
+
+# Initialize SDRAM controller
+define sdram_init
+  # SDIR0
+  set *(unsigned long *)0x00ef6008 = 0x00000182
+  # SDIR1
+  set *(unsigned long *)0x00ef600c = 0x00000001
+  # Initialize wait
+  shell sleep 0.1
+  # Ch0-MOD
+  set *(unsigned long *)0x00ef602c = 0x00000020
+  # Ch0-TR
+  set *(unsigned long *)0x00ef6028 = 0x00051502
+  # Ch0-ADR (size:64MB)
+  set *(unsigned long *)0x00ef6020 = 0x00000004
+  # AutoRef On
+  set *(unsigned long *)0x00ef6004 = 0x00010f05
+  # Access enable
+  set *(unsigned long *)0x00ef6024 = 0x00000001
+end
+document sdram_init
+  SDRAM controller initialization
+  0x08000000 - 0x0bffffff (64MB)
+end
+
+# Initialize LAN controller
+define lanc_init
+  set $sfrbase = 0x00ef0000
+  # Set BSEL3 (BSEL3 for the Chaos's bselc)
+  set *(unsigned long *)($sfrbase + 0x5300) = 0x07078040
+  set *(unsigned long *)($sfrbase + 0x5304) = 0x01110102
+  set *(unsigned long *)($sfrbase + 0x5308) = 0x00000001
+  # Reset (P5=LED,P6.b4=LAN_RESET)
+  set *(unsigned short *)($sfrbase + 0x106c) = 0x0000
+  set *(unsigned char *)($sfrbase + 0x1016) = 0xff
+  set *(unsigned char *)($sfrbase + 0x1086) = 0xff
+  shell sleep 0.1
+  # swivel: 0=normal, 4=reverse
+#  set *(unsigned char *)($sfrbase + 0x1086) = 0x00
+  set *(unsigned char *)($sfrbase + 0x1086) = 0x04
+  set *(unsigned long *)(0x0c000330) = 0xffffffff
+  # Set mac address
+  set $lanc = (void*)0x0c000300
+  set *(unsigned long *)($lanc + 0x0000) = 0x00610010
+  set *(unsigned long *)($lanc + 0x0004) = 0x00200030
+  set *(unsigned long *)($lanc + 0x0008) = 0x00400050
+  set *(unsigned long *)($lanc + 0x000c) = 0x00600007
+end
+document lanc_init
+  LAN controller initialization
+  ex.) MAC address:  10 20 30 40 50 60
+end
+
+# LCD & CRT dual-head setting (8bpp)
+define dispc_init
+  set $sfrbase = 0x00ef0000
+  # BSEL4 Dispc
+  set *(unsigned long *)($sfrbase + 0x5400) = 0x06078000
+  set *(unsigned long *)($sfrbase + 0x5404) = 0x00101101
+end
+
+# MMU enable
+define mmu_enable
+  set $evb=0x88000000
+  set *(unsigned long *)0xffff0024=1
+end
+
+# MMU disable
+define mmu_disable
+  set $evb=0
+  set *(unsigned long *)0xffff0024=0
+end
+
+# Show TLB entries
+define show_tlb_entries
+  set $i = 0
+  set $addr = $arg0
+  set $nr_entries = $arg1
+  use_mon_code
+  while ($i < $nr_entries)
+    set $tlb_tag = *(unsigned long*)$addr
+    set $tlb_data = *(unsigned long*)($addr + 4)
+    printf " [%2d] 0x%08lx : 0x%08lx - 0x%08lx\n", $i, $addr, $tlb_tag, $tlb_data
+    set $i = $i + 1
+    set $addr = $addr + 8
+  end
+  use_debug_dma
+end
+define itlb
+  set $itlb=0xfe000000
+  show_tlb_entries $itlb 0d32
+end
+define dtlb
+  set $dtlb=0xfe000800
+  show_tlb_entries $dtlb 0d32
+end
+
+# Show current task structure
+define show_current
+  set $current = $spi & 0xffffe000
+  printf "$current=0x%08lX\n",$current
+  print *(struct task_struct *)$current
+end
+
+# Show user assigned task structure
+define show_task
+  set  = $arg0 & 0xffffe000
+  printf "$task=0x%08lX\n",$task
+  print *(struct task_struct *)$task
+end
+document show_task
+  Show user assigned task structure
+  arg0 : task structure address
+end
+
+# Show M32R registers
+define show_regs
+  printf " R0[0x%08lX]   R1[0x%08lX]   R2[0x%08lX]   R3[0x%08lX]\n",$r0,$r1,$r2,$r3
+  printf " R4[0x%08lX]   R5[0x%08lX]   R6[0x%08lX]   R7[0x%08lX]\n",$r4,$r5,$r6,$r7
+  printf " R8[0x%08lX]   R9[0x%08lX]  R10[0x%08lX]  R11[0x%08lX]\n",$r8,$r9,$r10,$r11
+  printf "R12[0x%08lX]   FP[0x%08lX]   LR[0x%08lX]   SP[0x%08lX]\n",$r12,$fp,$lr,$sp
+  printf "PSW[0x%08lX]  CBR[0x%08lX]  SPI[0x%08lX]  SPU[0x%08lX]\n",$psw,$cbr,$spi,$spu
+  printf "BPC[0x%08lX]   PC[0x%08lX] ACCL[0x%08lX] ACCH[0x%08lX]\n",$bpc,$pc,$accl,$acch
+  printf "EVB[0x%08lX]\n",$evb
+end
+
+# Setup all
+define setup
+  use_mon_code
+  set *(unsigned int)0xfffffffc=0x60
+  shell sleep 0.1
+  clock_init
+  shell sleep 0.1
+  port_init
+  sdram_init
+  lanc_init
+  dispc_init
+  set $evb=0x00000000
+end
+
+# Load modules
+define load_modules
+  use_debug_dma
+  load
+end
+
+# Set kernel parameters
+define set_kernel_parameters
+  set $param = (void*)0x00002000
+  # INITRD_START
+  #set *(unsigned long *)($param + 0x0010) = 0x082a0000
+  # INITRD_SIZE
+  #set *(unsigned long *)($param + 0x0014) = 0x00000000
+  # M32R_CPUCLK
+  set *(unsigned long *)($param + 0x0018) = 0d200000000
+  # M32R_BUSCLK
+  set *(unsigned long *)($param + 0x001c) = 0d50000000
+
+  # M32R_TIMER_DIVIDE
+  set *(unsigned long *)($param + 0x0020) = 0d128
+
+  set {char[0x200]}($param + 0x100) = "console=ttyD0,115200n8x root=/dev/nfsroot nfsroot=192.168.0.1:/project/m32r-linux/export/root.bbox-httpd nfsaddrs=192.168.0.101:192.168.0.1:192.168.0.1:255.255.255.0:mappi001 \0"
+end
+
+# Boot
+define boot
+  set_kernel_parameters
+  set $fp = 0
+  set $pc=0x00001000
+  set *(long *)0xfffffff4=0x8080
+#  b load_flat_binary
+#  set *(unsigned char *)0x08001003=0x63
+#  set *(unsigned char *)0x08001003=0x02
+  si
+#  c
+end
+
+# Set breakpoints
+define set_breakpoints
+  b *0x08000030
+end
+
+# Restart
+define restart
+  sdireset
+  sdireset
+  setup
+  load_modules
+  boot
+end
+
+sdireset
+sdireset
+file vmlinux
+target m32rsdi
+setup
+load_modules
+boot
+
diff -Nru a/arch/m32r/mappi/dot.gdbinit.smp b/arch/m32r/mappi/dot.gdbinit.smp
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/arch/m32r/mappi/dot.gdbinit.smp	2004-10-18 14:57:21 -07:00
@@ -0,0 +1,344 @@
+# .gdbinit file
+# $Id$
+
+# setting
+set width 0d70
+set radix 0d16
+debug_chaos
+
+# clk xin:cpu:bif:bus=1:4:2:1
+define clock_init_on
+  set *(unsigned long *)0x00ef4024 = 2
+  set *(unsigned long *)0x00ef4020 = 1
+  set *(unsigned long *)0x00ef4010 = 0
+  set *(unsigned long *)0x00ef4014 = 0
+  set *(unsigned long *)0x00ef4004 = 0x1
+  shell sleep 0.1
+  set *(unsigned long *)0x00ef4008 = 0x0200
+#  set *(unsigned long *)0x00ef4008 = 0x0201
+end
+
+# clk xin:cpu:bif:bus=1:4:1:1
+define clock_init_on_1411
+  set *(unsigned long *)0x00ef4024 = 2
+  set *(unsigned long *)0x00ef4020 = 2
+  set *(unsigned long *)0x00ef4010 = 0
+  set *(unsigned long *)0x00ef4014 = 0
+  set *(unsigned long *)0x00ef4004 = 0x1
+  shell sleep 0.1
+  set *(unsigned long *)0x00ef4008 = 0x0200
+end
+
+# clk xin:cpu:bif:bus=1:4:2:1
+define clock_init_on_1421
+  set *(unsigned long *)0x00ef4024 = 2
+  set *(unsigned long *)0x00ef4020 = 1
+  set *(unsigned long *)0x00ef4010 = 0
+  set *(unsigned long *)0x00ef4014 = 0
+  set *(unsigned long *)0x00ef4004 = 0x1
+  shell sleep 0.1
+  set *(unsigned long *)0x00ef4008 = 0x0200
+end
+
+# clk xin:cpu:bif:bus=1:8:2:1
+define clock_init_on_1821
+  set *(unsigned long *)0x00ef4024 = 3
+  set *(unsigned long *)0x00ef4020 = 2
+  set *(unsigned long *)0x00ef4010 = 0
+  set *(unsigned long *)0x00ef4014 = 0
+  set *(unsigned long *)0x00ef4004 = 0x3
+  shell sleep 0.1
+  set *(unsigned long *)0x00ef4008 = 0x0200
+end
+
+# clk xin:cpu:bif:bus=1:8:4:1
+define clock_init_on_1841
+  set *(unsigned long *)0x00ef4024 = 3
+  set *(unsigned long *)0x00ef4020 = 1
+  set *(unsigned long *)0x00ef4010 = 0
+  set *(unsigned long *)0x00ef4014 = 0
+  set *(unsigned long *)0x00ef4004 = 0x3
+  shell sleep 0.1
+  set *(unsigned long *)0x00ef4008 = 0x0200
+end
+
+# clk xin:cpu:bif:bus=1:16:8:1
+define clock_init_on_11681
+  set *(unsigned long *)0x00ef4024 = 4
+  set *(unsigned long *)0x00ef4020 = 2
+  set *(unsigned long *)0x00ef4010 = 0
+  set *(unsigned long *)0x00ef4014 = 0
+  set *(unsigned long *)0x00ef4004 = 0x7
+  shell sleep 0.1
+  set *(unsigned long *)0x00ef4008 = 0x0200
+end
+
+# clk xin:cpu:bif:bus=1:1:1:1
+define clock_init_off
+  # CPU
+  set *(unsigned long *)0x00ef4010 = 0
+  set *(unsigned long *)0x00ef4014 = 0
+  # BIF
+  set *(unsigned long *)0x00ef4020 = 0
+  # BUS
+  set *(unsigned long *)0x00ef4024 = 0
+  # PLL
+  set *(unsigned long *)0x00ef4008 = 0x0000
+end
+
+# Initialize programmable ports
+define port_init
+  set $sfrbase = 0x00ef0000
+  set *(unsigned short *)0x00ef1060 = 0x5555
+  set *(unsigned short *)0x00ef1062 = 0x5555
+  set *(unsigned short *)0x00ef1064 = 0x5555
+  set *(unsigned short *)0x00ef1066 = 0x5555
+  set *(unsigned short *)0x00ef1068 = 0x5555
+  set *(unsigned short *)0x00ef106a = 0x0000
+  set *(unsigned short *)0x00ef106e = 0x5555
+  set *(unsigned short *)0x00ef1070 = 0x5555
+  # LED ON
+  set *(unsigned char *)($sfrbase + 0x1015) = 0xff
+  set *(unsigned char *)($sfrbase + 0x1085) = 0xff
+  shell sleep 0.1
+  # LED OFF
+  set *(unsigned char *)($sfrbase + 0x1085) = 0x00
+end
+document port_init
+  P5=LED(output), P6.b4=LAN_RESET(output)
+end
+
+# Initialize SDRAM controller for Mappi
+define sdram_init
+  # SDIR0
+  set *(unsigned long *)0x00ef6008 = 0x00000182
+  # SDIR1
+  set *(unsigned long *)0x00ef600c = 0x00000001
+  # Initialize wait
+  shell sleep 0.1
+  # Ch0-MOD
+  set *(unsigned long *)0x00ef602c = 0x00000020
+  # Ch0-TR
+  set *(unsigned long *)0x00ef6028 = 0x00010002
+  # Ch0-ADR
+  set *(unsigned long *)0x00ef6020 = 0x08000004
+  # AutoRef On
+  set *(unsigned long *)0x00ef6004 = 0x00010107
+  # Access enable
+  set *(unsigned long *)0x00ef6024 = 0x00000001
+end
+document sdram_init
+  Mappi SDRAM controller initialization
+  0x08000000 - 0x0bffffff (64MB)
+end
+
+# Initialize LAN controller for Mappi
+define lanc_init
+  set $sfrbase = 0x00ef0000
+  # Set BSEL3 (BSEL3 for the Chaos's bselc)
+#  set *(unsigned long *)($sfrbase + 0x5300) = 0x01018040
+#  set *(unsigned long *)($sfrbase + 0x5304) = 0x01011101
+  set *(unsigned long *)($sfrbase + 0x5300) = 0x04048000
+  set *(unsigned long *)($sfrbase + 0x5304) = 0x01011103
+  set *(unsigned long *)($sfrbase + 0x5308) = 0x00000001
+  # Reset (P5=LED,P6.b4=LAN_RESET)
+  set *(unsigned short *)($sfrbase + 0x106c) = 0x0000
+  set *(unsigned char *)($sfrbase + 0x1016) = 0xff
+  set *(unsigned char *)($sfrbase + 0x1086) = 0xff
+  shell sleep 0.1
+#  set *(unsigned char *)($sfrbase + 0x1086) = 0x00
+  set *(unsigned char *)($sfrbase + 0x1086) = 0x04
+  set *(unsigned long *)(0x0c000330) = 0xffffffff
+  # Set mac address
+  set $lanc = (void*)0x0c000300
+  set *(unsigned long *)($lanc + 0x0000) = 0x00610010
+  set *(unsigned long *)($lanc + 0x0004) = 0x00200030
+  set *(unsigned long *)($lanc + 0x0008) = 0x00400050
+  set *(unsigned long *)($lanc + 0x000c) = 0x00600007
+end
+document lanc_init
+  Mappi LAN controller initialization
+  ex.) MAC address:  10 20 30 40 50 60
+end
+
+# LCD & CRT dual-head setting (8bpp)
+define dispc_init
+  set $sfrbase = 0x00ef0000
+  # BSEL4 Dispc
+  # 20MHz
+#  set *(unsigned long *)($sfrbase + 0x5400) = 0x02028282
+#  set *(unsigned long *)($sfrbase + 0x5404) = 0x00122202
+  # 40MHz
+  set *(unsigned long *)($sfrbase + 0x5400) = 0x04048000
+  set *(unsigned long *)($sfrbase + 0x5404) = 0x00101103
+end
+
+# MMU enable
+define mmu_enable
+  set $evb=0x88000000
+  set *(unsigned long *)0xffff0024=1
+end
+
+# MMU disable
+define mmu_disable
+  set $evb=0
+  set *(unsigned long *)0xffff0024=0
+end
+
+# Show TLB entries
+define show_tlb_entries
+  set $i = 0
+  set $addr = $arg0
+  use_mon_code
+  while ($i < 0d32 )
+    set $tlb_tag = *(unsigned long*)$addr
+    set $tlb_data = *(unsigned long*)($addr + 4)
+    printf " [%2d] 0x%08lx : 0x%08lx - 0x%08lx\n", $i, $addr, $tlb_tag, $tlb_data
+    set $i = $i + 1
+    set $addr = $addr + 8
+  end
+  use_debug_dma
+end
+define itlb
+  set $itlb=0xfe000000
+  show_tlb_entries $itlb
+end
+define dtlb
+  set $dtlb=0xfe000800
+  show_tlb_entries $dtlb
+end
+
+
+# Show current task structure
+define show_current
+  set $current = $spi & 0xffffe000
+  printf "$current=0x%08lX\n",$current
+  print *(struct task_struct *)$current
+end
+
+# Show user assigned task structure
+define show_task
+  set $task = $arg0 & 0xffffe000
+  printf "$task=0x%08lX\n",$task
+  print *(struct task_struct *)$task
+end
+document show_task
+  Show user assigned task structure
+  arg0 : task structure address
+end
+
+# Show M32R registers
+define show_regs
+  printf " R0[0x%08lX]   R1[0x%08lX]   R2[0x%08lX]   R3[0x%08lX]\n",$r0,$r1,$r2,$r3
+  printf " R4[0x%08lX]   R5[0x%08lX]   R6[0x%08lX]   R7[0x%08lX]\n",$r4,$r5,$r6,$r7
+  printf " R8[0x%08lX]   R9[0x%08lX]  R10[0x%08lX]  R11[0x%08lX]\n",$r8,$r9,$r10,$r11
+  printf "R12[0x%08lX]   FP[0x%08lX]   LR[0x%08lX]   SP[0x%08lX]\n",$r12,$fp,$lr,$fp
+  printf "PSW[0x%08lX]  CBR[0x%08lX]  SPI[0x%08lX]  SPU[0x%08lX]\n",$psw,$cbr,$spi,$spu
+  printf "BPC[0x%08lX]   PC[0x%08lX] ACCL[0x%08lX] ACCH[0x%08lX]\n",$bpc,$pc,$accl,$acch
+  printf "EVB[0x%08lX]\n",$evb
+end
+
+
+# Setup all
+define setup
+  use_mon_code
+  set *(unsigned int)0xfffffffc=0x60
+  shell sleep 0.1
+#  clock_init_on_1411
+  clock_init_on_1421
+#  clock_init_on_1821
+#  clock_init_on_1841
+#  clock_init_on_11681
+#  clock_init_off
+  shell sleep 0.1
+  port_init
+  sdram_init
+  lanc_init
+  dispc_init
+  set $evb=0x08000000
+end
+
+# Load modules
+define load_modules
+  use_debug_dma
+  load
+#  load ramdisk_082a0000.mot
+#  load romfs_082a0000.mot
+#  use_mon_code
+end
+
+# Set kernel parameters
+define set_kernel_parameters
+  set $param = (void*)0x08002000
+  # INITRD_START
+# set *(unsigned long *)($param + 0x0010) = 0x082a0000
+  # INITRD_SIZE
+  set *(unsigned long *)($param + 0x0014) = 0x00000000
+  # M32R_CPUCLK
+  set *(unsigned long *)($param + 0x0018) = 0d160000000
+#  set *(unsigned long *)($param + 0x0018) = 0d80000000
+#  set *(unsigned long *)($param + 0x0018) = 0d40000000
+  # M32R_BUSCLK
+  set *(unsigned long *)($param + 0x001c) = 0d40000000
+
+  # M32R_TIMER_DIVIDE
+  set *(unsigned long *)($param + 0x0020) = 0d128
+
+  set {char[0x200]}($param + 0x100) = "console=tty1 console=ttyD0,115200n8x root=/dev/nfsroot nfsroot=192.168.0.1:/project/m32r-linux/export/root.x nfsaddrs=192.168.0.101:192.168.0.1:192.168.0.1:255.255.255.0:mappi001 \0"
+#  set {char[0x200]}($param + 0x100) = "console=tty1 root=/dev/nfsroot nfsroot=192.168.0.1:/project/m32r-linux/export/root.x nfsaddrs=192.168.0.101:192.168.0.1:192.168.0.1:255.255.255.0:mappi001 \0"
+end
+
+# Boot
+define boot
+  set_kernel_parameters
+  set $pc=0x08001000
+  set *(unsigned char *)0x08001003=0x03
+  si
+  c
+end
+
+# Set breakpoints
+define set_breakpoints
+  b *0x08000030
+end
+
+## Boot MP
+define boot_mp
+  set_kernel_parameters
+  set *(unsigned long *)0x00f00000 = boot - 0x80000000
+  set *(unsigned long *)0x00eff2f8 = 0x2
+  x 0x00eff2f8
+
+  set $pc=0x08001000
+  si
+  c
+end
+document boot_mp
+  Boot BSP
+end
+
+## Boot UP
+define boot_up
+  set_kernel_parameters
+  set $pc=0x08001000
+  si
+  c
+end
+document boot_up
+  Boot BSP
+end
+
+# Restart
+define restart
+  sdireset
+  sdireset
+  setup
+  load_modules
+  boot_mp
+end
+
+sdireset
+sdireset
+file vmlinux
+target m32rsdi
+setup
diff -Nru a/arch/m32r/mm/Makefile b/arch/m32r/mm/Makefile
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/arch/m32r/mm/Makefile	2004-10-18 14:57:23 -07:00
@@ -0,0 +1,12 @@
+#
+# Makefile for the Linux M32R-specific parts of the memory manager.
+#
+
+ifdef CONFIG_MMU
+obj-y	:= init.o fault.o mmu.o extable.o ioremap.o cache.o page.o
+else
+obj-y 	:= init.o fault-nommu.o mmu.o extable.o ioremap-nommu.o cache.o page.o
+endif
+
+obj-$(CONFIG_DISCONTIGMEM)	+= discontig.o
+
diff -Nru a/arch/m32r/mm/cache.c b/arch/m32r/mm/cache.c
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/arch/m32r/mm/cache.c	2004-10-18 14:57:23 -07:00
@@ -0,0 +1,68 @@
+/*
+ *  linux/arch/m32r/mm/cache.c
+ *
+ *  Copyright (C) 2002  Hirokazu Takata
+ */
+
+/* $Id$ */
+
+#include <linux/config.h>
+#include <asm/pgtable.h>
+
+#undef MCCR
+
+#if defined(CONFIG_CHIP_XNUX2) || defined(CONFIG_CHIP_M32700) || defined(CONFIG_CHIP_VDEC2) || defined(CONFIG_CHIP_OPSP)
+/* Cache Control Register */
+#define MCCR		((volatile unsigned long*)0xfffffffc)
+#define MCCR_CC		(1UL << 7)	/* Cache mode modify bit */
+#define MCCR_IIV	(1UL << 6)	/* I-cache invalidate */
+#define MCCR_DIV	(1UL << 5)	/* D-cache invalidate */
+#define MCCR_DCB	(1UL << 4)	/* D-cache copy back */
+#define MCCR_ICM	(1UL << 1)	/* I-cache mode [0:off,1:on] */
+#define MCCR_DCM	(1UL << 0)	/* D-cache mode [0:off,1:on] */
+#define MCCR_ICACHE_INV		(MCCR_CC|MCCR_IIV)
+#define MCCR_DCACHE_CB		(MCCR_CC|MCCR_DCB)
+#define MCCR_DCACHE_CBINV	(MCCR_CC|MCCR_DIV|MCCR_DCB)
+#define CHECK_MCCR(mccr)	(mccr = *MCCR)
+#elif defined(CONFIG_CHIP_M32102)
+#define MCCR		((volatile unsigned long*)0xfffffffc)
+#define MCCR_IIV	(1UL << 8)	/* I-cache invalidate */
+#define MCCR_ICACHE_INV		MCCR_IIV
+#endif /* CONFIG_CHIP_XNUX2 || CONFIG_CHIP_M32700 */
+
+#ifndef MCCR
+#error Unknown cache type.
+#endif
+
+
+/* Copy back and invalidate D-cache and invalidate I-cache all */
+void _flush_cache_all(void)
+{
+#if defined(CONFIG_CHIP_M32102)
+	*MCCR = MCCR_ICACHE_INV;
+#else
+	unsigned long mccr;
+
+	/* Copyback and invalidate D-cache */
+	/* Invalidate I-cache */
+	*MCCR = MCCR_ICACHE_INV | MCCR_DCACHE_CBINV;
+	while ((mccr = *MCCR) & MCCR_IIV); /* loop while invalidating... */
+#endif
+}
+
+/* Copy back D-cache and invalidate I-cache all */
+void _flush_cache_copyback_all(void)
+{
+#if defined(CONFIG_CHIP_M32102)
+	*MCCR = MCCR_ICACHE_INV;
+#else
+	unsigned long mccr;
+
+	/* Copyback D-cache */
+	/* Invalidate I-cache */
+	*MCCR = MCCR_ICACHE_INV | MCCR_DCACHE_CB;
+	while ((mccr = *MCCR) & MCCR_IIV); /* loop while invalidating... */
+
+#endif
+}
+
diff -Nru a/arch/m32r/mm/discontig.c b/arch/m32r/mm/discontig.c
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/arch/m32r/mm/discontig.c	2004-10-18 14:57:21 -07:00
@@ -0,0 +1,170 @@
+/*
+ *  linux/arch/m32r/mm/discontig.c
+ *
+ *  Discontig memory support
+ *
+ *  Copyright (c) 2003  Hitoshi Yamamoto
+ */
+
+#include <linux/config.h>
+#include <linux/mm.h>
+#include <linux/bootmem.h>
+#include <linux/mmzone.h>
+#include <linux/initrd.h>
+
+#include <asm/setup.h>
+
+extern char _end[];
+
+struct pglist_data *node_data[MAX_NUMNODES];
+static bootmem_data_t node_bdata[MAX_NUMNODES] __initdata;
+
+pg_data_t m32r_node_data[MAX_NUMNODES];
+
+/* Memory profile */
+typedef struct {
+	unsigned long start_pfn;
+	unsigned long pages;
+	unsigned long holes;
+	unsigned long free_pfn;
+} mem_prof_t;
+static mem_prof_t mem_prof[MAX_NUMNODES];
+
+static void __init mem_prof_init(void)
+{
+	unsigned long start_pfn, holes, free_pfn;
+	const unsigned long zone_alignment = 1UL << (MAX_ORDER - 1);
+	unsigned long ul;
+	mem_prof_t *mp;
+
+	/* Node#0 SDRAM */
+	mp = &mem_prof[0];
+	mp->start_pfn = PFN_UP(CONFIG_MEMORY_START);
+	mp->pages = PFN_DOWN(CONFIG_MEMORY_SIZE);
+	mp->holes = 0;
+	mp->free_pfn = PFN_UP(__pa(_end));
+
+	/* Node#1 internal SRAM */
+	mp = &mem_prof[1];
+	start_pfn = free_pfn = PFN_UP(CONFIG_IRAM_START);
+	holes = 0;
+	if (start_pfn & (zone_alignment - 1)) {
+		ul = zone_alignment;
+		while (start_pfn >= ul)
+			ul += zone_alignment;
+
+		start_pfn = ul - zone_alignment;
+		holes = free_pfn - start_pfn;
+	}
+
+	mp->start_pfn = start_pfn;
+	mp->pages = PFN_DOWN(CONFIG_IRAM_SIZE) + holes;
+	mp->holes = holes;
+	mp->free_pfn = PFN_UP(CONFIG_IRAM_START);
+}
+
+unsigned long __init setup_memory(void)
+{
+	unsigned long bootmap_size;
+	unsigned long min_pfn;
+	int nid;
+	mem_prof_t *mp;
+
+	max_low_pfn = 0;
+	min_low_pfn = -1;
+
+	mem_prof_init();
+
+	for (nid = 0 ; nid < numnodes ; nid++) {
+		mp = &mem_prof[nid];
+		NODE_DATA(nid)=(pg_data_t *)&m32r_node_data[nid];
+		NODE_DATA(nid)->bdata = &node_bdata[nid];
+		min_pfn = mp->start_pfn;
+		max_pfn = mp->start_pfn + mp->pages;
+		bootmap_size = init_bootmem_node(NODE_DATA(nid), mp->free_pfn,
+			mp->start_pfn, max_pfn);
+
+		free_bootmem_node(NODE_DATA(nid), PFN_PHYS(mp->start_pfn),
+			PFN_PHYS(mp->pages));
+
+		reserve_bootmem_node(NODE_DATA(nid), PFN_PHYS(mp->start_pfn),
+			PFN_PHYS(mp->free_pfn - mp->start_pfn) + bootmap_size);
+
+		if (max_low_pfn < max_pfn)
+			max_low_pfn = max_pfn;
+
+		if (min_low_pfn > min_pfn)
+			min_low_pfn = min_pfn;
+	}
+
+#ifdef CONFIG_BLK_DEV_INITRD
+	if (LOADER_TYPE && INITRD_START) {
+		if (INITRD_START + INITRD_SIZE <= PFN_PHYS(max_low_pfn)) {
+			reserve_bootmem_node(NODE_DATA(0), INITRD_START,
+				INITRD_SIZE);
+			initrd_start = INITRD_START ?
+				INITRD_START + PAGE_OFFSET : 0;
+
+			initrd_end = initrd_start + INITRD_SIZE;
+			printk("initrd:start[%08lx],size[%08lx]\n",
+				initrd_start, INITRD_SIZE);
+		} else {
+			printk("initrd extends beyond end of memory "
+				"(0x%08lx > 0x%08lx)\ndisabling initrd\n",
+				INITRD_START + INITRD_SIZE,
+				PFN_PHYS(max_low_pfn));
+
+			initrd_start = 0;
+		}
+	}
+#endif	/* CONFIG_BLK_DEV_INITRD */
+
+	return max_low_pfn;
+}
+
+#define START_PFN(nid)	\
+	(NODE_DATA(nid)->bdata->node_boot_start >> PAGE_SHIFT)
+#define MAX_LOW_PFN(nid)	(NODE_DATA(nid)->bdata->node_low_pfn)
+
+unsigned long __init zone_sizes_init(void)
+{
+	unsigned long zones_size[MAX_NR_ZONES], zholes_size[MAX_NR_ZONES];
+	unsigned long low, start_pfn;
+	unsigned long holes = 0;
+	int nid, i;
+	mem_prof_t *mp;
+
+	pgdat_list = NULL;
+	for (nid = numnodes - 1 ; nid >= 0 ; nid--) {
+		NODE_DATA(nid)->pgdat_next = pgdat_list;
+		pgdat_list = NODE_DATA(nid);
+	}
+
+	for (nid = 0 ; nid < numnodes ; nid++) {
+		mp = &mem_prof[nid];
+		for (i = 0 ; i < MAX_NR_ZONES ; i++) {
+			zones_size[i] = 0;
+			zholes_size[i] = 0;
+		}
+		start_pfn = START_PFN(nid);
+		low = MAX_LOW_PFN(nid);
+		zones_size[ZONE_DMA] = low - start_pfn;
+		zholes_size[ZONE_DMA] = mp->holes;
+		holes += zholes_size[ZONE_DMA];
+
+		free_area_init_node(nid, NODE_DATA(nid), zones_size,
+			start_pfn, zholes_size);
+	}
+
+	/*
+	 * For test
+	 *  Use all area of internal RAM.
+	 *  see __alloc_pages()
+	 */
+	NODE_DATA(1)->node_zones->pages_min = 0;
+	NODE_DATA(1)->node_zones->pages_low = 0;
+	NODE_DATA(1)->node_zones->pages_high = 0;
+
+	return holes;
+}
+
diff -Nru a/arch/m32r/mm/extable.c b/arch/m32r/mm/extable.c
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/arch/m32r/mm/extable.c	2004-10-18 14:57:24 -07:00
@@ -0,0 +1,22 @@
+/*
+ * linux/arch/i386/mm/extable.c
+ */
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/spinlock.h>
+#include <asm/uaccess.h>
+
+int fixup_exception(struct pt_regs *regs)
+{
+	const struct exception_table_entry *fixup;
+
+	fixup = search_exception_tables(regs->bpc);
+	if (fixup) {
+		regs->bpc = fixup->fixup;
+		return 1;
+	}
+
+	return 0;
+}
+
diff -Nru a/arch/m32r/mm/fault-nommu.c b/arch/m32r/mm/fault-nommu.c
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/arch/m32r/mm/fault-nommu.c	2004-10-18 14:57:23 -07:00
@@ -0,0 +1,164 @@
+/*
+ *  linux/arch/m32r/mm/fault.c
+ *
+ *  Copyright (c) 2001, 2002  Hitoshi Yamamoto, and H. Kondo
+ *
+ *  Some code taken from i386 version.
+ *    Copyright (C) 1995  Linus Torvalds
+ */
+
+/* $Id: fault-nommu.c,v 1.1 2004/03/30 06:40:59 sakugawa Exp $ */
+
+#include <linux/config.h>
+#include <linux/signal.h>
+#include <linux/sched.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/string.h>
+#include <linux/types.h>
+#include <linux/ptrace.h>
+#include <linux/mman.h>
+#include <linux/mm.h>
+#include <linux/smp.h>
+#include <linux/smp_lock.h>
+#include <linux/interrupt.h>
+#include <linux/init.h>
+
+#include <asm/m32r.h>
+#include <asm/system.h>
+#include <asm/uaccess.h>
+#include <asm/pgalloc.h>
+#include <asm/pgtable.h>
+#include <asm/hardirq.h>
+#include <asm/mmu_context.h>
+
+extern void die(const char *, struct pt_regs *, long);
+
+#ifndef CONFIG_SMP
+asmlinkage unsigned int tlb_entry_i_dat;
+asmlinkage unsigned int tlb_entry_d_dat;
+#define tlb_entry_i tlb_entry_i_dat
+#define tlb_entry_d tlb_entry_d_dat
+#else
+unsigned int tlb_entry_i_dat[NR_CPUS];
+unsigned int tlb_entry_d_dat[NR_CPUS];
+#define tlb_entry_i tlb_entry_i_dat[smp_processor_id()]
+#define tlb_entry_d tlb_entry_d_dat[smp_processor_id()]
+#endif
+
+/*
+ * Unlock any spinlocks which will prevent us from getting the
+ * message out
+ */
+void bust_spinlocks(int yes)
+{
+	int loglevel_save = console_loglevel;
+
+	if (yes) {
+		oops_in_progress = 1;
+		return;
+	}
+#ifdef CONFIG_VT
+	unblank_screen();
+#endif
+	oops_in_progress = 0;
+	/*
+	 * OK, the message is on the console.  Now we call printk()
+	 * without oops_in_progress set so that printk will give klogd
+	 * a poke.  Hold onto your hats...
+	 */
+	console_loglevel = 15;		/* NMI oopser may have shut the console up */
+	printk(" ");
+	console_loglevel = loglevel_save;
+}
+
+void do_BUG(const char *file, int line)
+{
+	bust_spinlocks(1);
+	printk("kernel BUG at %s:%d!\n", file, line);
+}
+
+/*======================================================================*
+ * do_page_fault()
+ *======================================================================*
+ * This routine handles page faults.  It determines the address,
+ * and the problem, and then passes it off to one of the appropriate
+ * routines.
+ *
+ * ARGUMENT:
+ *  regs       : M32R SP reg.
+ *  error_code : See below
+ *  address    : M32R MMU MDEVA reg. (Operand ACE)
+ *             : M32R BPC reg. (Instruction ACE)
+ *
+ * error_code :
+ *  bit 0 == 0 means no page found, 1 means protection fault
+ *  bit 1 == 0 means read, 1 means write
+ *  bit 2 == 0 means kernel, 1 means user-mode
+ *======================================================================*/
+asmlinkage void do_page_fault(struct pt_regs *regs, unsigned long error_code,
+  unsigned long address)
+{
+
+/*
+ * Oops. The kernel tried to access some bad page. We'll have to
+ * terminate things with extreme prejudice.
+ */
+
+	bust_spinlocks(1);
+
+	if (address < PAGE_SIZE)
+		printk(KERN_ALERT "Unable to handle kernel NULL pointer dereference");
+	else
+		printk(KERN_ALERT "Unable to handle kernel paging request");
+	printk(" at virtual address %08lx\n",address);
+	printk(" printing bpc:\n");
+	printk(KERN_ALERT "bpc = %08lx\n", regs->bpc);
+
+	die("Oops", regs, error_code);
+	bust_spinlocks(0);
+	do_exit(SIGKILL);
+}
+
+/*======================================================================*
+ * update_mmu_cache()
+ *======================================================================*/
+void update_mmu_cache(struct vm_area_struct *vma, unsigned long addr,
+	pte_t pte)
+{
+	BUG();
+}
+
+/*======================================================================*
+ * flush_tlb_page() : flushes one page
+ *======================================================================*/
+void local_flush_tlb_page(struct vm_area_struct *vma, unsigned long page)
+{
+	BUG();
+}
+
+/*======================================================================*
+ * flush_tlb_range() : flushes a range of pages
+ *======================================================================*/
+void local_flush_tlb_range(struct vm_area_struct *vma, unsigned long start,
+	unsigned long end)
+{
+	BUG();
+}
+
+/*======================================================================*
+ * flush_tlb_mm() : flushes the specified mm context TLB's
+ *======================================================================*/
+void local_flush_tlb_mm(struct mm_struct *mm)
+{
+	BUG();
+}
+
+/*======================================================================*
+ * flush_tlb_all() : flushes all processes TLBs
+ *======================================================================*/
+void local_flush_tlb_all(void)
+{
+	BUG();
+}
+
diff -Nru a/arch/m32r/mm/fault.c b/arch/m32r/mm/fault.c
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/arch/m32r/mm/fault.c	2004-10-18 14:57:23 -07:00
@@ -0,0 +1,572 @@
+/*
+ *  linux/arch/m32r/mm/fault.c
+ *
+ *  Copyright (c) 2001, 2002  Hitoshi Yamamoto, and H. Kondo
+ *
+ *  Some code taken from i386 version.
+ *    Copyright (C) 1995  Linus Torvalds
+ */
+
+/* $Id$ */
+
+#include <linux/config.h>
+#include <linux/signal.h>
+#include <linux/sched.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/string.h>
+#include <linux/types.h>
+#include <linux/ptrace.h>
+#include <linux/mman.h>
+#include <linux/mm.h>
+#include <linux/smp.h>
+#include <linux/smp_lock.h>
+#include <linux/interrupt.h>
+#include <linux/init.h>
+#include <linux/tty.h>
+#include <linux/vt_kern.h>		/* For unblank_screen() */
+#include <linux/highmem.h>
+#include <linux/module.h>
+
+#include <asm/m32r.h>
+#include <asm/system.h>
+#include <asm/uaccess.h>
+#include <asm/hardirq.h>
+#include <asm/mmu_context.h>
+#include <asm/tlbflush.h>
+
+extern void die(const char *, struct pt_regs *, long);
+
+#ifndef CONFIG_SMP
+asmlinkage unsigned int tlb_entry_i_dat;
+asmlinkage unsigned int tlb_entry_d_dat;
+#define tlb_entry_i tlb_entry_i_dat
+#define tlb_entry_d tlb_entry_d_dat
+#else
+unsigned int tlb_entry_i_dat[NR_CPUS];
+unsigned int tlb_entry_d_dat[NR_CPUS];
+#define tlb_entry_i tlb_entry_i_dat[smp_processor_id()]
+#define tlb_entry_d tlb_entry_d_dat[smp_processor_id()]
+#endif
+
+extern void init_tlb(void);
+
+/*
+ * Unlock any spinlocks which will prevent us from getting the
+ * message out
+ */
+void bust_spinlocks(int yes)
+{
+	int loglevel_save = console_loglevel;
+
+	if (yes) {
+		oops_in_progress = 1;
+		return;
+	}
+#ifdef CONFIG_VT
+	unblank_screen();
+#endif
+	oops_in_progress = 0;
+	/*
+	 * OK, the message is on the console.  Now we call printk()
+	 * without oops_in_progress set so that printk will give klogd
+	 * a poke.  Hold onto your hats...
+	 */
+	console_loglevel = 15;		/* NMI oopser may have shut the console up */
+	printk(" ");
+	console_loglevel = loglevel_save;
+}
+
+/*======================================================================*
+ * do_page_fault()
+ *======================================================================*
+ * This routine handles page faults.  It determines the address,
+ * and the problem, and then passes it off to one of the appropriate
+ * routines.
+ *
+ * ARGUMENT:
+ *  regs       : M32R SP reg.
+ *  error_code : See below
+ *  address    : M32R MMU MDEVA reg. (Operand ACE)
+ *             : M32R BPC reg. (Instruction ACE)
+ *
+ * error_code :
+ *  bit 0 == 0 means no page found, 1 means protection fault
+ *  bit 1 == 0 means read, 1 means write
+ *  bit 2 == 0 means kernel, 1 means user-mode
+ *  bit 3 == 0 means data, 1 means instruction
+ *======================================================================*/
+asmlinkage void do_page_fault(struct pt_regs *regs, unsigned long error_code,
+  unsigned long address)
+{
+	struct task_struct *tsk;
+	struct mm_struct *mm;
+	struct vm_area_struct * vma;
+	unsigned long page, addr;
+	int write;
+	siginfo_t info;
+
+	/*
+	 * If BPSW IE bit enable --> set PSW IE bit
+	 */
+	if (regs->psw & M32R_PSW_BIE)
+		local_irq_enable();
+
+	tsk = current;
+
+	info.si_code = SEGV_MAPERR;
+
+	/*
+	 * 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 (address >= TASK_SIZE && !(error_code & 4))
+		goto vmalloc_fault;
+
+	mm = tsk->mm;
+
+	/*
+	 * If we're in an interrupt or have no user context or are running in an
+	 * atomic region then we must not take the fault..
+	 */
+	if (in_atomic() || !mm)
+		goto bad_area_nosemaphore;
+
+	/* When running in the kernel we expect faults to occur only to
+	 * addresses in user space.  All other faults represent errors in the
+	 * kernel and should generate an OOPS.  Unfortunatly, in the case of an
+	 * erroneous fault occuring in a code path which already holds mmap_sem
+	 * we will deadlock attempting to validate the fault against the
+	 * address space.  Luckily the kernel only validly references user
+	 * space from well defined areas of code, which are listed in the
+	 * exceptions table.
+	 *
+	 * As the vast majority of faults will be valid we will only perform
+	 * the source reference check when there is a possibilty of a deadlock.
+	 * Attempt to lock the address space, if we cannot we then validate the
+	 * source.  If this is invalid we can skip the address space check,
+	 * thus avoiding the deadlock.
+	 */
+	if (!down_read_trylock(&mm->mmap_sem)) {
+		if ((error_code & 4) == 0 &&
+		    !search_exception_tables(regs->psw))
+			goto bad_area_nosemaphore;
+		down_read(&mm->mmap_sem);
+	}
+
+	vma = find_vma(mm, address);
+	if (!vma)
+		goto bad_area;
+	if (vma->vm_start <= address)
+		goto good_area;
+	if (!(vma->vm_flags & VM_GROWSDOWN))
+		goto bad_area;
+#if 0
+	if (error_code & 4) {
+		/*
+		 * accessing the stack below "spu" is always a bug.
+		 * The "+ 4" is there due to the push instruction
+		 * doing pre-decrement on the stack and that
+		 * doesn't show up until later..
+		 */
+		if (address + 4 < regs->spu)
+			goto bad_area;
+	}
+#endif
+	if (expand_stack(vma, address))
+		goto bad_area;
+/*
+ * Ok, we have a good vm_area for this memory access, so
+ * we can handle it..
+ */
+good_area:
+	info.si_code = SEGV_ACCERR;
+	write = 0;
+	switch (error_code & 3) {
+		default:	/* 3: write, present */
+			/* fall through */
+		case 2:		/* write, not present */
+			if (!(vma->vm_flags & VM_WRITE))
+				goto bad_area;
+			write++;
+			break;
+		case 1:		/* read, present */
+		case 0:		/* read, not present */
+			if (!(vma->vm_flags & (VM_READ | VM_EXEC)))
+				goto bad_area;
+	}
+
+survive:
+	/*
+	 * If for any reason at all we couldn't handle the fault,
+	 * make sure we exit gracefully rather than endlessly redo
+	 * the fault.
+	 */
+	addr = (address & PAGE_MASK) | (error_code & 8);
+	switch (handle_mm_fault(mm, vma, addr, write)) {
+		case VM_FAULT_MINOR:
+			tsk->min_flt++;
+			break;
+		case VM_FAULT_MAJOR:
+			tsk->maj_flt++;
+			break;
+		case VM_FAULT_SIGBUS:
+			goto do_sigbus;
+		case VM_FAULT_OOM:
+			goto out_of_memory;
+		default:
+			BUG();
+	}
+
+	up_read(&mm->mmap_sem);
+	return;
+
+/*
+ * Something tried to access memory that isn't in our memory map..
+ * Fix it, but check if it's kernel or user first..
+ */
+bad_area:
+	up_read(&mm->mmap_sem);
+
+bad_area_nosemaphore:
+	/* User mode accesses just cause a SIGSEGV */
+	if (error_code & 4) {
+		tsk->thread.address = address;
+		tsk->thread.error_code = error_code | (address >= TASK_SIZE);
+		tsk->thread.trap_no = 14;
+		info.si_signo = SIGSEGV;
+		info.si_errno = 0;
+		/* info.si_code has been set above */
+		info.si_addr = (void __user *)address;
+		force_sig_info(SIGSEGV, &info, tsk);
+		return;
+	}
+
+no_context:
+	/* Are we prepared to handle this kernel fault?  */
+	if (fixup_exception(regs))
+		return;
+
+/*
+ * Oops. The kernel tried to access some bad page. We'll have to
+ * terminate things with extreme prejudice.
+ */
+
+	bust_spinlocks(1);
+
+	if (address < PAGE_SIZE)
+		printk(KERN_ALERT "Unable to handle kernel NULL pointer dereference");
+	else
+		printk(KERN_ALERT "Unable to handle kernel paging request");
+	printk(" at virtual address %08lx\n",address);
+	printk(KERN_ALERT " printing bpc:\n");
+	printk("%08lx\n", regs->bpc);
+	page = *(unsigned long *)MPTB;
+	page = ((unsigned long *) page)[address >> PGDIR_SHIFT];
+	printk(KERN_ALERT "*pde = %08lx\n", page);
+	if (page & _PAGE_PRESENT) {
+		page &= PAGE_MASK;
+		address &= 0x003ff000;
+		page = ((unsigned long *) __va(page))[address >> PAGE_SHIFT];
+		printk(KERN_ALERT "*pte = %08lx\n", page);
+	}
+	die("Oops", regs, error_code);
+	bust_spinlocks(0);
+	do_exit(SIGKILL);
+
+/*
+ * We ran out of memory, or some other thing happened to us that made
+ * us unable to handle the page fault gracefully.
+ */
+out_of_memory:
+	up_read(&mm->mmap_sem);
+	if (tsk->pid == 1) {
+		yield();
+		down_read(&mm->mmap_sem);
+		goto survive;
+	}
+	printk("VM: killing process %s\n", tsk->comm);
+	if (error_code & 4)
+		do_exit(SIGKILL);
+	goto no_context;
+
+do_sigbus:
+	up_read(&mm->mmap_sem);
+
+	/* Kernel mode? Handle exception or die */
+	if (!(error_code & 4))
+		goto no_context;
+
+	tsk->thread.address = address;
+	tsk->thread.error_code = error_code;
+	tsk->thread.trap_no = 14;
+	info.si_signo = SIGBUS;
+	info.si_errno = 0;
+	info.si_code = BUS_ADRERR;
+	info.si_addr = (void __user *)address;
+	force_sig_info(SIGBUS, &info, tsk);
+	return;
+
+vmalloc_fault:
+	{
+		/*
+		 * Synchronize this task's top level page-table
+		 * with the 'reference' page table.
+		 *
+		 * Do _not_ use "tsk" here. We might be inside
+		 * an interrupt in the middle of a task switch..
+		 */
+		int offset = pgd_index(address);
+		pgd_t *pgd, *pgd_k;
+		pmd_t *pmd, *pmd_k;
+		pte_t *pte_k;
+
+		pgd = (pgd_t *)*(unsigned long *)MPTB;
+		pgd = offset + (pgd_t *)pgd;
+		pgd_k = init_mm.pgd + offset;
+
+		if (!pgd_present(*pgd_k))
+			goto no_context;
+
+		/*
+		 * set_pgd(pgd, *pgd_k); here would be useless on PAE
+		 * and redundant with the set_pmd() on non-PAE.
+		 */
+
+		pmd = pmd_offset(pgd, address);
+		pmd_k = pmd_offset(pgd_k, address);
+		if (!pmd_present(*pmd_k))
+			goto no_context;
+		set_pmd(pmd, *pmd_k);
+
+		pte_k = pte_offset_kernel(pmd_k, address);
+		if (!pte_present(*pte_k))
+			goto no_context;
+
+		addr = (address & PAGE_MASK) | (error_code & 8);
+		update_mmu_cache(NULL, addr, *pte_k);
+		return;
+	}
+}
+
+/*======================================================================*
+ * update_mmu_cache()
+ *======================================================================*/
+#define TLB_MASK	(NR_TLB_ENTRIES - 1)
+#define ITLB_END	(unsigned long *)(ITLB_BASE + (NR_TLB_ENTRIES * 8))
+#define DTLB_END	(unsigned long *)(DTLB_BASE + (NR_TLB_ENTRIES * 8))
+void update_mmu_cache(struct vm_area_struct *vma, unsigned long vaddr,
+	pte_t pte)
+{
+	unsigned long *entry1, *entry2;
+	unsigned long pte_data, flags;
+	unsigned int *entry_dat;
+	int inst = vaddr & 8;
+	int i;
+
+	/* Ptrace may call this routine. */
+	if (vma && current->active_mm != vma->vm_mm)
+		return;
+
+	local_irq_save(flags);
+
+	vaddr = (vaddr & PAGE_MASK) | get_asid();
+
+#ifdef CONFIG_CHIP_OPSP
+	entry1 = (unsigned long *)ITLB_BASE;
+	for(i = 0 ; i < NR_TLB_ENTRIES; i++) {
+	        if(*entry1++ == vaddr) {
+	                pte_data = pte_val(pte);
+	                set_tlb_data(entry1, pte_data);
+	                break;
+	        }
+	        entry1++;
+	}
+	entry2 = (unsigned long *)DTLB_BASE;
+	for(i = 0 ; i < NR_TLB_ENTRIES ; i++) {
+	        if(*entry2++ == vaddr) {
+	                pte_data = pte_val(pte);
+	                set_tlb_data(entry2, pte_data);
+	                break;
+	        }
+	        entry2++;
+	}
+	local_irq_restore(flags);
+	return;
+#else
+	pte_data = pte_val(pte);
+
+	/*
+	 * Update TLB entries
+	 *  entry1: ITLB entry address
+	 *  entry2: DTLB entry address
+	 */
+	__asm__ __volatile__ (
+		"seth	%0, #high(%4)	\n\t"
+		"st	%2, @(%5, %0)	\n\t"
+		"ldi	%1, #1		\n\t"
+		"st	%1, @(%6, %0)	\n\t"
+		"add3	r4, %0, %7	\n\t"
+		".fillinsn		\n"
+		"1:			\n\t"
+		"ld	%1, @(%6, %0)	\n\t"
+		"bnez	%1, 1b		\n\t"
+		"ld	%0, @r4+	\n\t"
+		"ld	%1, @r4		\n\t"
+		"st	%3, @+%0	\n\t"
+		"st	%3, @+%1	\n\t"
+		: "=&r" (entry1), "=&r" (entry2)
+		: "r" (vaddr), "r" (pte_data), "i" (MMU_REG_BASE),
+		"i" (MSVA_offset), "i" (MTOP_offset), "i" (MIDXI_offset)
+		: "r4", "memory"
+	);
+
+	if ((!inst && entry2 >= DTLB_END) || (inst && entry1 >= ITLB_END))
+		goto notfound;
+
+found:
+	local_irq_restore(flags);
+
+	return;
+
+	/* Valid entry not found */
+notfound:
+	/*
+	 * Update ITLB or DTLB entry
+	 *  entry1: TLB entry address
+	 *  entry2: TLB base address
+	 */
+	if (!inst) {
+		entry2 = (unsigned long *)DTLB_BASE;
+		entry_dat = &tlb_entry_d;
+	} else {
+		entry2 = (unsigned long *)ITLB_BASE;
+		entry_dat = &tlb_entry_i;
+	}
+	entry1 = entry2 + (((*entry_dat - 1) & TLB_MASK) << 1);
+
+	for (i = 0 ; i < NR_TLB_ENTRIES ; i++) {
+		if (!(entry1[1] & 2))	/* Valid bit check */
+			break;
+
+		if (entry1 != entry2)
+			entry1 -= 2;
+		else
+			entry1 += TLB_MASK << 1;
+	}
+
+	if (i >= NR_TLB_ENTRIES) {	/* Empty entry not found */
+		entry1 = entry2 + (*entry_dat << 1);
+		*entry_dat = (*entry_dat + 1) & TLB_MASK;
+	}
+	*entry1++ = vaddr;	/* Set TLB tag */
+	set_tlb_data(entry1, pte_data);
+
+	goto found;
+#endif
+}
+
+/*======================================================================*
+ * flush_tlb_page() : flushes one page
+ *======================================================================*/
+void local_flush_tlb_page(struct vm_area_struct *vma, unsigned long page)
+{
+	if (vma->vm_mm && mm_context(vma->vm_mm) != NO_CONTEXT) {
+		unsigned long flags;
+
+		local_irq_save(flags);
+		page &= PAGE_MASK;
+		page |= (mm_context(vma->vm_mm) & MMU_CONTEXT_ASID_MASK);
+		__flush_tlb_page(page);
+		local_irq_restore(flags);
+	}
+}
+
+/*======================================================================*
+ * flush_tlb_range() : flushes a range of pages
+ *======================================================================*/
+void local_flush_tlb_range(struct vm_area_struct *vma, unsigned long start,
+	unsigned long end)
+{
+	struct mm_struct *mm;
+
+	mm = vma->vm_mm;
+	if (mm_context(mm) != NO_CONTEXT) {
+		unsigned long flags;
+		int size;
+
+		local_irq_save(flags);
+		size = (end - start + (PAGE_SIZE - 1)) >> PAGE_SHIFT;
+		if (size > (NR_TLB_ENTRIES / 4)) { /* Too many TLB to flush */
+			mm_context(mm) = NO_CONTEXT;
+			if (mm == current->mm)
+				activate_context(mm);
+		} else {
+			unsigned long asid;
+
+			asid = mm_context(mm) & MMU_CONTEXT_ASID_MASK;
+			start &= PAGE_MASK;
+			end += (PAGE_SIZE - 1);
+			end &= PAGE_MASK;
+
+			start |= asid;
+			end   |= asid;
+			while (start < end) {
+				__flush_tlb_page(start);
+				start += PAGE_SIZE;
+			}
+		}
+		local_irq_restore(flags);
+	}
+}
+
+/*======================================================================*
+ * flush_tlb_mm() : flushes the specified mm context TLB's
+ *======================================================================*/
+void local_flush_tlb_mm(struct mm_struct *mm)
+{
+	/* Invalidate all TLB of this process. */
+	/* Instead of invalidating each TLB, we get new MMU context. */
+	if (mm_context(mm) != NO_CONTEXT) {
+		unsigned long flags;
+
+		local_irq_save(flags);
+		mm_context(mm) = NO_CONTEXT;
+		if (mm == current->mm)
+			activate_context(mm);
+		local_irq_restore(flags);
+	}
+}
+
+/*======================================================================*
+ * flush_tlb_all() : flushes all processes TLBs
+ *======================================================================*/
+void local_flush_tlb_all(void)
+{
+	unsigned long flags;
+
+	local_irq_save(flags);
+	__flush_tlb_all();
+	local_irq_restore(flags);
+}
+
+/*======================================================================*
+ * init_mmu()
+ *======================================================================*/
+void __init init_mmu(void)
+{
+	tlb_entry_i = 0;
+	tlb_entry_d = 0;
+	mmu_context_cache = MMU_CONTEXT_FIRST_VERSION;
+	set_asid(mmu_context_cache & MMU_CONTEXT_ASID_MASK);
+	*(volatile unsigned long *)MPTB = (unsigned long)swapper_pg_dir;
+}
diff -Nru a/arch/m32r/mm/init.c b/arch/m32r/mm/init.c
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/arch/m32r/mm/init.c	2004-10-18 14:57:24 -07:00
@@ -0,0 +1,250 @@
+/*
+ *  linux/arch/m32r/mm/init.c
+ *
+ *  Copyright (c) 2001, 2002  Hitoshi Yamamoto
+ *
+ *  Some code taken from sh version.
+ *    Copyright (C) 1999  Niibe Yutaka
+ *    Based on linux/arch/i386/mm/init.c:
+ *      Copyright (C) 1995  Linus Torvalds
+ */
+
+/* $Id$ */
+
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/mm.h>
+#include <linux/pagemap.h>
+#include <linux/bootmem.h>
+#include <linux/swap.h>
+#include <linux/highmem.h>
+#include <asm/types.h>
+#include <asm/processor.h>
+#include <asm/bitops.h>
+#include <asm/page.h>
+#include <asm/pgtable.h>
+#include <asm/pgalloc.h>
+#include <asm/mmu_context.h>
+#include <asm/setup.h>
+#include <asm/tlb.h>
+
+/* References to section boundaries */
+extern char _text, _etext, _edata;
+extern char __init_begin, __init_end;
+
+pgd_t swapper_pg_dir[1024];
+
+DEFINE_PER_CPU(struct mmu_gather, mmu_gathers);
+
+void show_mem(void)
+{
+	int total = 0, reserved = 0;
+	int shared = 0, cached = 0;
+	int highmem = 0;
+	struct page *page;
+	pg_data_t *pgdat;
+	unsigned long i;
+
+	printk("Mem-info:\n");
+	show_free_areas();
+	printk("Free swap:       %6ldkB\n",nr_swap_pages<<(PAGE_SHIFT-10));
+	for_each_pgdat(pgdat) {
+		for (i = 0; i < pgdat->node_spanned_pages; ++i) {
+			page = pgdat->node_mem_map + i;
+			total++;
+			if (PageHighMem(page))
+				highmem++;
+			if (PageReserved(page))
+				reserved++;
+			else if (PageSwapCache(page))
+				cached++;
+			else if (page_count(page))
+				shared += page_count(page) - 1;
+		}
+	}
+	printk("%d pages of RAM\n", total);
+	printk("%d pages of HIGHMEM\n",highmem);
+	printk("%d reserved pages\n",reserved);
+	printk("%d pages shared\n",shared);
+	printk("%d pages swap cached\n",cached);
+}
+
+/*
+ * Cache of MMU context last used.
+ */
+#ifndef CONFIG_SMP
+unsigned long mmu_context_cache_dat;
+#else
+unsigned long mmu_context_cache_dat[NR_CPUS];
+#endif
+static unsigned long hole_pages;
+
+/*
+ * function prototype
+ */
+void __init paging_init(void);
+void __init mem_init(void);
+void free_initmem(void);
+#ifdef CONFIG_BLK_DEV_INITRD
+void free_initrd_mem(unsigned long, unsigned long);
+#endif
+
+/* It'd be good if these lines were in the standard header file. */
+#define START_PFN(nid)	\
+	(NODE_DATA(nid)->bdata->node_boot_start >> PAGE_SHIFT)
+#define MAX_LOW_PFN(nid)	(NODE_DATA(nid)->bdata->node_low_pfn)
+
+#ifndef CONFIG_DISCONTIGMEM
+unsigned long __init zone_sizes_init(void)
+{
+	unsigned long  zones_size[MAX_NR_ZONES] = {0, 0, 0};
+	unsigned long  max_dma;
+	unsigned long  low;
+	unsigned long  start_pfn;
+
+#ifdef CONFIG_MMU
+	start_pfn = START_PFN(0);
+	max_dma = virt_to_phys((char *)MAX_DMA_ADDRESS) >> PAGE_SHIFT;
+	low = MAX_LOW_PFN(0);
+
+	if (low < max_dma){
+		zones_size[ZONE_DMA] = low - start_pfn;
+		zones_size[ZONE_NORMAL] = 0;
+	} else {
+		zones_size[ZONE_DMA] = low - start_pfn;
+		zones_size[ZONE_NORMAL] = low - max_dma;
+	}
+#else
+	zones_size[ZONE_DMA] = 0 >> PAGE_SHIFT;
+	zones_size[ZONE_NORMAL] = __MEMORY_SIZE >> PAGE_SHIFT;
+	start_pfn = __MEMORY_START >> PAGE_SHIFT;
+#endif /* CONFIG_MMU */
+
+	free_area_init_node(0, NODE_DATA(0), zones_size, start_pfn, 0);
+
+	mem_map = contig_page_data.node_mem_map;
+
+	return 0;
+}
+#else	/* CONFIG_DISCONTIGMEM */
+extern unsigned long zone_sizes_init(void);
+#endif	/* CONFIG_DISCONTIGMEM */
+
+/*======================================================================*
+ * paging_init() : sets up the page tables
+ *======================================================================*/
+void __init paging_init(void)
+{
+#ifdef CONFIG_MMU
+	int  i;
+	pgd_t *pg_dir;
+
+	/* We don't need kernel mapping as hardware support that. */
+	pg_dir = swapper_pg_dir;
+
+	for (i = 0 ; i < USER_PTRS_PER_PGD * 2 ; i++)
+		pgd_val(pg_dir[i]) = 0;
+#endif /* CONFIG_MMU */
+	hole_pages = zone_sizes_init();
+}
+
+int __init reservedpages_count(void)
+{
+	int reservedpages, nid, i;
+
+	reservedpages = 0;
+	for (nid = 0 ; nid < numnodes ; nid++)
+		for (i = 0 ; i < MAX_LOW_PFN(nid) - START_PFN(nid) ; i++)
+			if (PageReserved(NODE_DATA(nid)->node_mem_map + i))
+				reservedpages++;
+
+	return reservedpages;
+}
+
+/*======================================================================*
+ * mem_init() :
+ * orig : arch/sh/mm/init.c
+ *======================================================================*/
+void __init mem_init(void)
+{
+	int codesize, reservedpages, datasize, initsize;
+	int nid;
+#ifndef CONFIG_MMU
+	extern unsigned long memory_end;
+#endif
+
+	num_physpages = 0;
+	for (nid = 0 ; nid < numnodes ; nid++)
+		num_physpages += MAX_LOW_PFN(nid) - START_PFN(nid) + 1;
+
+	num_physpages -= hole_pages;
+
+#ifndef CONFIG_DISCONTIGMEM
+	max_mapnr = num_physpages;
+#endif	/* CONFIG_DISCONTIGMEM */
+
+#ifdef CONFIG_MMU
+	high_memory = (void *)__va(PFN_PHYS(MAX_LOW_PFN(0)));
+#else
+	high_memory = (void *)(memory_end & PAGE_MASK);
+#endif /* CONFIG_MMU */
+
+	/* clear the zero-page */
+	memset(empty_zero_page, 0, PAGE_SIZE);
+
+	/* this will put all low memory onto the freelists */
+	for (nid = 0 ; nid < numnodes ; nid++)
+		totalram_pages += free_all_bootmem_node(NODE_DATA(nid));
+
+	reservedpages = reservedpages_count() - hole_pages;
+	codesize = (unsigned long) &_etext - (unsigned long)&_text;
+	datasize = (unsigned long) &_edata - (unsigned long)&_etext;
+	initsize = (unsigned long) &__init_end - (unsigned long)&__init_begin;
+
+	printk(KERN_INFO "Memory: %luk/%luk available (%dk kernel code, "
+		"%dk reserved, %dk data, %dk init)\n",
+		(unsigned long) nr_free_pages() << (PAGE_SHIFT-10),
+		num_physpages << (PAGE_SHIFT-10),
+		codesize >> 10,
+		reservedpages << (PAGE_SHIFT-10),
+		datasize >> 10,
+		initsize >> 10);
+}
+
+/*======================================================================*
+ * free_initmem() :
+ * orig : arch/sh/mm/init.c
+ *======================================================================*/
+void free_initmem(void)
+{
+	unsigned long addr;
+
+	addr = (unsigned long)(&__init_begin);
+	for (; addr < (unsigned long)(&__init_end); addr += PAGE_SIZE) {
+		ClearPageReserved(virt_to_page(addr));
+		set_page_count(virt_to_page(addr), 1);
+		free_page(addr);
+		totalram_pages++;
+	}
+	printk (KERN_INFO "Freeing unused kernel memory: %dk freed\n", \
+	  (int)(&__init_end - &__init_begin) >> 10);
+}
+
+#ifdef CONFIG_BLK_DEV_INITRD
+/*======================================================================*
+ * free_initrd_mem() :
+ * orig : arch/sh/mm/init.c
+ *======================================================================*/
+void free_initrd_mem(unsigned long start, unsigned long end)
+{
+	unsigned long p;
+	for (p = start; p < end; p += PAGE_SIZE) {
+		ClearPageReserved(virt_to_page(p));
+		set_page_count(virt_to_page(p), 1);
+		free_page(p);
+		totalram_pages++;
+	}
+	printk (KERN_INFO "Freeing initrd memory: %ldk freed\n", (end - start) >> 10);
+}
+#endif
+
diff -Nru a/arch/m32r/mm/ioremap-nommu.c b/arch/m32r/mm/ioremap-nommu.c
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/arch/m32r/mm/ioremap-nommu.c	2004-10-18 14:57:24 -07:00
@@ -0,0 +1,52 @@
+/*
+ *  linux/arch/m32r/mm/ioremap-nommu.c
+ *
+ *  Copyright (c) 2001, 2002  Hiroyuki Kondo
+ *
+ *  Taken from mips version.
+ *    (C) Copyright 1995 1996 Linus Torvalds
+ *    (C) Copyright 2001 Ralf Baechle
+ */
+
+/*
+ * 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.
+ *
+ */
+
+#include <linux/module.h>
+#include <asm/addrspace.h>
+#include <asm/byteorder.h>
+
+#include <linux/vmalloc.h>
+#include <asm/io.h>
+#include <asm/pgalloc.h>
+#include <asm/cacheflush.h>
+#include <asm/tlbflush.h>
+
+
+/*
+ * Remap an arbitrary physical address space into the kernel virtual
+ * address space. Needed when the kernel wants to access high addresses
+ * directly.
+ *
+ * NOTE! We need to allow non-page-aligned mappings too: we will obviously
+ * have to convert them into an offset in a page-aligned mapping, but the
+ * caller shouldn't need to know that small detail.
+ */
+
+#define IS_LOW512(addr) (!((unsigned long)(addr) & ~0x1fffffffUL))
+
+void __iomem *
+__ioremap(unsigned long phys_addr, unsigned long size, unsigned long flags)
+{
+	return (void *)phys_addr;
+}
+
+#define IS_KSEG1(addr) (((unsigned long)(addr) & ~0x1fffffffUL) == KSEG1)
+
+void iounmap(volatile void __iomem *addr)
+{
+}
+
diff -Nru a/arch/m32r/mm/ioremap.c b/arch/m32r/mm/ioremap.c
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/arch/m32r/mm/ioremap.c	2004-10-18 14:57:23 -07:00
@@ -0,0 +1,192 @@
+/*
+ *  linux/arch/m32r/mm/ioremap.c
+ *
+ *  Copyright (c) 2001, 2002  Hiroyuki Kondo
+ *
+ *  Taken from mips version.
+ *    (C) Copyright 1995 1996 Linus Torvalds
+ *    (C) Copyright 2001 Ralf Baechle
+ */
+
+/*
+ * 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.
+ *
+ */
+
+#include <linux/module.h>
+#include <asm/addrspace.h>
+#include <asm/byteorder.h>
+
+#include <linux/vmalloc.h>
+#include <asm/io.h>
+#include <asm/pgalloc.h>
+#include <asm/cacheflush.h>
+#include <asm/tlbflush.h>
+
+static inline void
+remap_area_pte(pte_t * pte, unsigned long address, unsigned long size,
+	       unsigned long phys_addr, unsigned long flags)
+{
+	unsigned long end;
+	unsigned long pfn;
+	pgprot_t pgprot = __pgprot(_PAGE_GLOBAL | _PAGE_PRESENT | _PAGE_READ
+	                           | _PAGE_WRITE | flags);
+
+	address &= ~PMD_MASK;
+	end = address + size;
+	if (end > PMD_SIZE)
+		end = PMD_SIZE;
+	if (address >= end)
+		BUG();
+	pfn = phys_addr >> PAGE_SHIFT;
+	do {
+		if (!pte_none(*pte)) {
+			printk("remap_area_pte: page already exists\n");
+			BUG();
+		}
+		set_pte(pte, pfn_pte(pfn, pgprot));
+		address += PAGE_SIZE;
+		pfn++;
+		pte++;
+	} while (address && (address < end));
+}
+
+static inline int
+remap_area_pmd(pmd_t * pmd, unsigned long address, unsigned long size,
+	       unsigned long phys_addr, unsigned long flags)
+{
+	unsigned long end;
+
+	address &= ~PGDIR_MASK;
+	end = address + size;
+	if (end > PGDIR_SIZE)
+		end = PGDIR_SIZE;
+	phys_addr -= address;
+	if (address >= end)
+		BUG();
+	do {
+		pte_t * pte = pte_alloc_kernel(&init_mm, pmd, address);
+		if (!pte)
+			return -ENOMEM;
+		remap_area_pte(pte, address, end - address, address + phys_addr, flags);
+		address = (address + PMD_SIZE) & PMD_MASK;
+		pmd++;
+	} while (address && (address < end));
+	return 0;
+}
+
+static int
+remap_area_pages(unsigned long address, unsigned long phys_addr,
+		 unsigned long size, unsigned long flags)
+{
+	int error;
+	pgd_t * dir;
+	unsigned long end = address + size;
+
+	phys_addr -= address;
+	dir = pgd_offset(&init_mm, address);
+	flush_cache_all();
+	if (address >= end)
+		BUG();
+	spin_lock(&init_mm.page_table_lock);
+	do {
+		pmd_t *pmd;
+		pmd = pmd_alloc(&init_mm, dir, address);
+		error = -ENOMEM;
+		if (!pmd)
+			break;
+		if (remap_area_pmd(pmd, address, end - address,
+					 phys_addr + address, flags))
+			break;
+		error = 0;
+		address = (address + PGDIR_SIZE) & PGDIR_MASK;
+		dir++;
+	} while (address && (address < end));
+	spin_unlock(&init_mm.page_table_lock);
+	flush_tlb_all();
+	return error;
+}
+
+/*
+ * Generic mapping function (not visible outside):
+ */
+
+/*
+ * Remap an arbitrary physical address space into the kernel virtual
+ * address space. Needed when the kernel wants to access high addresses
+ * directly.
+ *
+ * NOTE! We need to allow non-page-aligned mappings too: we will obviously
+ * have to convert them into an offset in a page-aligned mapping, but the
+ * caller shouldn't need to know that small detail.
+ */
+
+#define IS_LOW512(addr) (!((unsigned long)(addr) & ~0x1fffffffUL))
+
+void __iomem *
+__ioremap(unsigned long phys_addr, unsigned long size, unsigned long flags)
+{
+	void __iomem * addr;
+	struct vm_struct * area;
+	unsigned long offset, last_addr;
+
+	/* Don't allow wraparound or zero size */
+	last_addr = phys_addr + size - 1;
+	if (!size || last_addr < phys_addr)
+		return NULL;
+
+	/*
+	 * Map objects in the low 512mb of address space using KSEG1, otherwise
+	 * map using page tables.
+	 */
+	if (IS_LOW512(phys_addr) && IS_LOW512(phys_addr + size - 1))
+		return (void *) KSEG1ADDR(phys_addr);
+
+	/*
+	 * Don't allow anybody to remap normal RAM that we're using..
+	 */
+	if (phys_addr < virt_to_phys(high_memory)) {
+		char *t_addr, *t_end;
+		struct page *page;
+
+		t_addr = __va(phys_addr);
+		t_end = t_addr + (size - 1);
+
+		for(page = virt_to_page(t_addr); page <= virt_to_page(t_end); page++)
+			if(!PageReserved(page))
+				return NULL;
+	}
+
+	/*
+	 * Mappings have to be page-aligned
+	 */
+	offset = phys_addr & ~PAGE_MASK;
+	phys_addr &= PAGE_MASK;
+	size = PAGE_ALIGN(last_addr + 1) - phys_addr;
+
+	/*
+	 * Ok, go for it..
+	 */
+	area = get_vm_area(size, VM_IOREMAP);
+	if (!area)
+		return NULL;
+	area->phys_addr = phys_addr;
+	addr = (void __iomem *) area->addr;
+	if (remap_area_pages((unsigned long)addr, phys_addr, size, flags)) {
+		vunmap((void __force *) addr);
+		return NULL;
+	}
+
+	return (void __iomem *) (offset + (char __iomem *)addr);
+}
+
+#define IS_KSEG1(addr) (((unsigned long)(addr) & ~0x1fffffffUL) == KSEG1)
+
+void iounmap(volatile void __iomem *addr)
+{
+	if (!IS_KSEG1(addr))
+		vfree((void *) (PAGE_MASK & (unsigned long) addr));
+}
+
diff -Nru a/arch/m32r/mm/mmu.S b/arch/m32r/mm/mmu.S
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/arch/m32r/mm/mmu.S	2004-10-18 14:57:23 -07:00
@@ -0,0 +1,350 @@
+/*
+ *  linux/arch/m32r/mm/mmu.S
+ *
+ *  Copyright (C) 2001 by Hiroyuki Kondo
+ */
+
+/* $Id: mmu.S,v 1.15 2004/03/16 02:56:27 takata Exp $ */
+
+#include <linux/config.h>	/* CONFIG_MMU */
+#include <linux/linkage.h>
+#include <asm/assembler.h>
+#include <asm/smp.h>
+
+	.text
+#ifdef CONFIG_MMU
+
+#include <asm/mmu_context.h>
+#include <asm/page.h>
+#include <asm/pgtable.h>
+#include <asm/m32r.h>
+
+/*
+ * TLB Miss Exception handler
+ */
+	.balign	16
+ENTRY(tme_handler)
+	.global	tlb_entry_i_dat
+	.global	tlb_entry_d_dat
+
+	SWITCH_TO_KERNEL_STACK
+
+#if defined(CONFIG_ISA_M32R2)
+	st	r0, @-sp
+	st	r1, @-sp
+	st	r2, @-sp
+	st	r3, @-sp
+
+	seth	r3, #high(MMU_REG_BASE)
+	ld	r1, @(MESTS_offset, r3)	; r1: status     (MESTS reg.)
+	ld	r0, @(MDEVP_offset, r3)	; r0: PFN + ASID (MDEVP reg.)
+	st	r1, @(MESTS_offset, r3)	; clear status   (MESTS reg.)
+	and3	r1, r1, #(MESTS_IT)
+	bnez	r1, 1f			; instruction TLB miss?
+
+;; data TLB miss
+;;  input
+;;   r0: PFN + ASID (MDEVP reg.)
+;;   r1 - r3: free
+;;  output
+;;   r0: PFN + ASID
+;;   r1: TLB entry base address
+;;   r2: &tlb_entry_{i|d}_dat
+;;   r3: free
+
+#ifndef CONFIG_SMP
+	seth	r2, #high(tlb_entry_d_dat)
+	or3	r2, r2, #low(tlb_entry_d_dat)
+#else	/* CONFIG_SMP */
+	ldi	r1, #-8192
+	seth	r2, #high(tlb_entry_d_dat)
+	or3	r2, r2, #low(tlb_entry_d_dat)
+	and	r1, sp
+	ld	r1, @(16, r1)		; current_thread_info->cpu
+	slli	r1, #2
+	add	r2, r1
+#endif	/* !CONFIG_SMP */
+	seth	r1, #high(DTLB_BASE)
+	or3	r1, r1, #low(DTLB_BASE)
+	bra	2f
+
+	.balign	16
+	.fillinsn
+1:
+;; instrucntion TLB miss
+;;  input
+;;   r0: MDEVP reg. (included ASID)
+;;   r1 - r3: free
+;;  output
+;;   r0: PFN + ASID
+;;   r1: TLB entry base address
+;;   r2: &tlb_entry_{i|d}_dat
+;;   r3: free
+	ldi	r3, #-4096
+	and3	r0, r0, #(MMU_CONTEXT_ASID_MASK)
+	mvfc	r1, bpc
+	and	r1, r3
+	or	r0, r1			; r0: PFN + ASID
+#ifndef CONFIG_SMP
+	seth	r2, #high(tlb_entry_i_dat)
+	or3	r2, r2, #low(tlb_entry_i_dat)
+#else	/* CONFIG_SMP */
+	ldi	r1, #-8192
+	seth	r2, #high(tlb_entry_i_dat)
+	or3	r2, r2, #low(tlb_entry_i_dat)
+	and	r1, sp
+	ld	r1, @(16, r1)		; current_thread_info->cpu
+	slli	r1, #2
+	add	r2, r1
+#endif	/* !CONFIG_SMP */
+	seth	r1, #high(ITLB_BASE)
+	or3	r1, r1, #low(ITLB_BASE)
+
+	.fillinsn
+2:
+;; select TLB entry
+;;  input
+;;   r0: PFN + ASID
+;;   r1: TLB entry base address
+;;   r2: &tlb_entry_{i|d}_dat
+;;   r3: free
+;;  output
+;;   r0: PFN + ASID
+;;   r1: TLB entry address
+;;   r2, r3: free
+#ifdef CONFIG_ISA_DUAL_ISSUE
+	ld	r3, @r2		||	srli	r1, #3
+#else
+	ld	r3, @r2
+	srli	r1, #3
+#endif
+	add	r1, r3
+	; tlb_entry_{d|i}_dat++;
+	addi	r3, #1
+	and3	r3, r3, #(NR_TLB_ENTRIES - 1)
+#ifdef CONFIG_ISA_DUAL_ISSUE
+	st	r3, @r2		||	slli	r1, #3
+#else
+	st	r3, @r2
+	slli	r1, #3
+#endif
+
+;; load pte
+;;  input
+;;   r0: PFN + ASID
+;;   r1: TLB entry address
+;;   r2, r3: free
+;;  output
+;;   r0: PFN + ASID
+;;   r1: TLB entry address
+;;   r2: pte_data
+;;   r3: free
+	; pgd = *(unsigned long *)MPTB;
+	ld24	r2, #(-MPTB - 1)
+	srl3	r3, r0, #22
+#ifdef CONFIG_ISA_DUAL_ISSUE
+	not	r2, r2		    ||	slli	r3, #2	; r3: pgd offset
+#else
+	not	r2, r2
+	slli	r3, #2
+#endif
+	ld	r2, @r2			; r2: pgd base addr (MPTB reg.)
+	or	r3, r2			; r3: pmd addr
+
+	; pmd = pmd_offset(pgd, address);
+	ld	r3, @r3			; r3: pmd data
+	ldi	r2, #-4096
+	beqz	r3, 3f			; pmd_none(*pmd) ?
+
+	; pte = pte_offset(pmd, address);
+	and	r2, r3			; r2: pte base addr
+	srl3	r3, r0, #10
+	and3	r3, r3, #0xffc		; r3: pte offset
+	or	r3, r2
+	seth	r2, #0x8000
+	or	r3, r2			; r3: pte addr
+
+	; pte_data = (unsigned long)pte_val(*pte);
+	ld	r2, @r3			; r2: pte data
+	or3	r2, r2, #2		; _PAGE_PRESENT(=2)
+
+	.fillinsn
+5:
+;; set tlb
+;;  input
+;;   r0: PFN + ASID
+;;   r1: TLB entry address
+;;   r2: pte_data
+;;   r3: free
+	st	r0, @r1			; set_tlb_tag(entry++, address);
+	st	r2, @+r1		; set_tlb_data(entry, pte_data);
+
+	.fillinsn
+6:
+	ld	r3, @sp+
+	ld	r2, @sp+
+	ld	r1, @sp+
+	ld	r0, @sp+
+	rte
+
+	.fillinsn
+3:
+;; error
+;;  input
+;;   r0: PFN + ASID
+;;   r1: TLB entry address
+;;   r2, r3: free
+;;  output
+;;   r0: PFN + ASID
+;;   r1: TLB entry address
+;;   r2: pte_data
+;;   r3: free
+#ifdef CONFIG_ISA_DUAL_ISSUE
+	bra	5b		    ||	ldi	r2, #2
+#else
+	ldi	r2, #2		; r2: pte_data = 0 | _PAGE_PRESENT(=2)
+	bra	5b
+#endif
+
+#elif defined (CONFIG_ISA_M32R)
+
+	st	sp, @-sp
+	st	r0, @-sp
+	st	r1, @-sp
+	st	r2, @-sp
+	st	r3, @-sp
+	st	r4, @-sp
+
+	seth	r3, #high(MMU_REG_BASE)
+	ld	r0, @(MDEVA_offset,r3)	; r0: address  (MDEVA reg.)
+	mvfc	r2, bpc			; r2: bpc
+	ld	r1, @(MESTS_offset,r3)	; r1: status   (MESTS reg.)
+	st	r1, @(MESTS_offset,r3)	; clear status (MESTS reg.)
+	and3	r1, r1, #(MESTS_IT)
+	beqz	r1, 1f			; data TLB miss?
+
+;; instrucntion TLB miss
+	mv	r0, r2			; address = bpc;
+	; entry = (unsigned long *)ITLB_BASE+tlb_entry_i*2;
+	seth	r3, #shigh(tlb_entry_i_dat)
+	ld	r4, @(low(tlb_entry_i_dat),r3)
+	sll3	r2, r4, #3
+	seth	r1, #high(ITLB_BASE)
+	or3	r1, r1, #low(ITLB_BASE)
+	add	r2, r1			; r2: entry
+	addi	r4, #1			; tlb_entry_i++;
+	and3	r4, r4, #(NR_TLB_ENTRIES-1)
+	st	r4, @(low(tlb_entry_i_dat),r3)
+	bra	2f
+	.fillinsn
+1:
+;; data TLB miss
+	; entry = (unsigned long *)DTLB_BASE+tlb_entry_d*2;
+	seth	r3, #shigh(tlb_entry_d_dat)
+	ld	r4, @(low(tlb_entry_d_dat),r3)
+	sll3	r2, r4, #3
+	seth	r1, #high(DTLB_BASE)
+	or3	r1, r1, #low(DTLB_BASE)
+	add	r2, r1			; r2: entry
+	addi	r4, #1			; tlb_entry_d++;
+	and3	r4, r4, #(NR_TLB_ENTRIES-1)
+	st	r4, @(low(tlb_entry_d_dat),r3)
+	.fillinsn
+2:
+;; load pte
+; r0: address, r2: entry
+; r1,r3,r4: (free)
+	; pgd = *(unsigned long *)MPTB;
+	ld24	r1, #(-MPTB-1)
+	not	r1, r1
+	ld	r1, @r1
+	srl3	r4, r0, #22
+	sll3	r3, r4, #2
+	add	r3, r1			; r3: pgd
+	; pmd = pmd_offset(pgd, address);
+	ld	r1, @r3			; r1: pmd
+	beqz	r1, 3f			; pmd_none(*pmd) ?
+;
+	and3	r1, r1, #0xeff
+	ldi	r4, #611		; _KERNPG_TABLE(=611)
+	beq	r1, r4, 4f		; !pmd_bad(*pmd) ?
+	.fillinsn
+3:
+	ldi	r1, #0			; r1: pte_data = 0
+	bra	5f
+	.fillinsn
+4:
+	; pte = pte_offset(pmd, address);
+	ld	r4, @r3			; r4: pte
+	ldi	r3, #-4096
+	and	r4, r3
+	srl3	r3, r0, #10
+	and3	r3, r3, #0xffc
+	add	r4, r3
+	seth	r3, #0x8000
+	add	r4, r3			; r4: pte
+	; pte_data = (unsigned long)pte_val(*pte);
+	ld	r1, @r4			; r1: pte_data
+	.fillinsn
+
+;; set tlb
+; r0: address, r1: pte_data, r2: entry
+; r3,r4: (free)
+5:
+	ldi	r3, #-4096		; set_tlb_tag(entry++, address);
+	and	r3, r0
+	seth	r4, #shigh(MASID)
+	ld	r4, @(low(MASID),r4)	; r4: MASID
+	and3	r4, r4, #(MMU_CONTEXT_ASID_MASK)
+	or	r3, r4
+	st	r3, @r2
+	or3	r4, r1, #2		; _PAGE_PRESENT(=2)
+	st	r4, @(4,r2)		; set_tlb_data(entry, pte_data);
+
+	ld	r4, @sp+
+	ld	r3, @sp+
+	ld	r2, @sp+
+	ld	r1, @sp+
+	ld	r0, @sp+
+	ld	sp, @sp+
+	rte
+
+#else
+#error unknown isa configuration
+#endif
+
+ENTRY(init_tlb)
+;; Set MMU Register
+	seth	r0, #high(MMU_REG_BASE)	 ; Set MMU_REG_BASE higher
+	or3	r0, r0, #low(MMU_REG_BASE)  ; Set MMU_REG_BASE lower
+	ldi	r1, #0
+	st	r1, @(MPSZ_offset,r0)	; Set MPSZ Reg(Page size 4KB:0 16KB:1 64KB:2)
+	ldi	r1, #0
+	st	r1, @(MASID_offset,r0)	; Set ASID Zero
+
+;; Set TLB
+	seth	r0, #high(ITLB_BASE)	; Set ITLB_BASE higher
+	or3	r0, r0, #low(ITLB_BASE)	; Set ITLB_BASE lower
+	seth	r1, #high(DTLB_BASE)	; Set DTLB_BASE higher
+	or3	r1, r1, #low(DTLB_BASE)	; Set DTLB_BASE lower
+	ldi	r2, #0
+	ldi	r3, #NR_TLB_ENTRIES
+	addi	r0, #-4
+	addi	r1, #-4
+clear_tlb:
+	st	r2, @+r0		; VPA <- 0
+	st	r2, @+r0		; PPA <- 0
+	st	r2, @+r1		; VPA <- 0
+	st	r2, @+r1		; PPA <- 0
+	addi	r3, #-1
+	bnez	r3, clear_tlb
+;;
+	jmp	r14
+
+ENTRY(m32r_itlb_entrys)
+ENTRY(m32r_otlb_entrys)
+
+#endif  /* CONFIG_MMU */
+
+.end
+
diff -Nru a/arch/m32r/mm/page.S b/arch/m32r/mm/page.S
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/arch/m32r/mm/page.S	2004-10-18 14:57:23 -07:00
@@ -0,0 +1,82 @@
+/*
+ *  linux/arch/m32r/mm/page.S
+ *
+ *  Clear/Copy page with CPU
+ *
+ *  Copyright (C) 2004  The Free Software Initiative of Japan
+ *
+ *  Written by Niibe Yutaka
+ *
+ * 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.
+ *
+ */
+	.text
+	.global	copy_page
+	/*
+	 * copy_page (to, from)
+	 *
+	 * PAGE_SIZE = 4096-byte
+	 * Cache line = 16-byte
+	 * 16 * 256
+	 */
+	.align	4
+copy_page:
+	ldi	r2, #255
+	ld	r3, @r0		/* cache line allocate */
+	ld	r4, @r1+
+	ld	r5, @r1+
+	ld	r6, @r1+
+	ld	r7, @r1+
+	.fillinsn
+0:
+	st	r4, @r0
+	st	r5, @+r0
+	st	r6, @+r0
+	st	r7, @+r0
+	ld	r4, @r1+
+	addi	r0, #4
+	ld	r5, @r1+
+	ld	r6, @r1+
+	ld	r7, @r1+
+	ld	r3, @r0		/* cache line allocate */
+	addi	r2, #-1
+	bnez	r2, 0b
+
+	st	r4, @r0
+	st	r5, @+r0
+	st	r6, @+r0
+	st	r7, @+r0
+	jmp	r14
+
+	.text
+	.global	clear_page
+	/*
+	 * clear_page (to)
+	 *
+	 * PAGE_SIZE = 4096-byte
+	 * Cache line = 16-byte
+	 * 16 * 256
+	 */
+	.align	4
+clear_page:
+	ldi	r2, #255
+	ldi	r4, #0
+	ld	r3, @r0		/* cache line allocate */
+	.fillinsn
+0:
+	st	r4, @r0
+	st	r4, @+r0
+	st	r4, @+r0
+	st	r4, @+r0
+	addi	r0, #4
+	ld	r3, @r0		/* cache line allocate */
+	addi	r2, #-1
+	bnez	r2, 0b
+
+	st	r4, @r0
+	st	r4, @+r0
+	st	r4, @+r0
+	st	r4, @+r0
+	jmp	r14
diff -Nru a/arch/m32r/oaks32r/defconfig.nommu b/arch/m32r/oaks32r/defconfig.nommu
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/arch/m32r/oaks32r/defconfig.nommu	2004-10-18 14:57:21 -07:00
@@ -0,0 +1,521 @@
+#
+# Automatically generated make config: don't edit
+#
+CONFIG_M32R=y
+CONFIG_UID16=y
+CONFIG_GENERIC_ISA_DMA=y
+
+#
+# Code maturity level options
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_CLEAN_COMPILE=y
+CONFIG_BROKEN_ON_SMP=y
+
+#
+# General setup
+#
+# 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=y
+# CONFIG_IKCONFIG is not set
+CONFIG_EMBEDDED=y
+# CONFIG_KALLSYMS is not set
+# CONFIG_FUTEX is not set
+# CONFIG_EPOLL is not set
+CONFIG_IOSCHED_NOOP=y
+# CONFIG_IOSCHED_AS is not set
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+
+#
+# Loadable module support
+#
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+# CONFIG_MODULE_FORCE_UNLOAD is not set
+CONFIG_OBSOLETE_MODPARM=y
+# CONFIG_MODVERSIONS is not set
+CONFIG_KMOD=y
+
+#
+# Processor type and features
+#
+# CONFIG_PLAT_MAPPI is not set
+# CONFIG_PLAT_USRV is not set
+# CONFIG_PLAT_M32700UT is not set
+# CONFIG_PLAT_OPSPUT is not set
+CONFIG_PLAT_OAKS32R=y
+# CONFIG_PLAT_MAPPI2 is not set
+# CONFIG_CHIP_M32700 is not set
+CONFIG_CHIP_M32102=y
+# CONFIG_CHIP_VDEC2 is not set
+# CONFIG_CHIP_OPSP is not set
+CONFIG_ISA_M32R=y
+CONFIG_BUS_CLOCK=33333333
+CONFIG_TIMER_DIVIDE=128
+# CONFIG_CPU_LITTLE_ENDIAN is not set
+CONFIG_MEMORY_START=0x01000000
+CONFIG_MEMORY_SIZE=0x00800000
+CONFIG_NOHIGHMEM=y
+# CONFIG_DISCONTIGMEM is not set
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+# CONFIG_RWSEM_XCHGADD_ALGORITHM is not set
+CONFIG_PREEMPT=y
+# CONFIG_HAVE_DEC_LOCK is not set
+# CONFIG_SMP is not set
+
+#
+# M32R drivers
+#
+CONFIG_M32R_NE2000=y
+
+#
+# Power management options (ACPI, APM)
+#
+# CONFIG_PM is not set
+
+#
+# Bus options (PCI, PCMCIA, EISA, MCA, ISA)
+#
+# CONFIG_PCI is not set
+# CONFIG_ISA is not set
+
+#
+# PCMCIA/CardBus support
+#
+# CONFIG_PCMCIA is not set
+
+#
+# PCI Hotplug Support
+#
+
+#
+# Executable file formats
+#
+CONFIG_BINFMT_FLAT=y
+# CONFIG_BINFMT_ZFLAT is not set
+# CONFIG_BINFMT_SHARED_FLAT is not set
+# CONFIG_BINFMT_MISC is not set
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+# CONFIG_FW_LOADER is not set
+
+#
+# Memory Technology Devices (MTD)
+#
+# CONFIG_MTD is not set
+
+#
+# Parallel port support
+#
+# CONFIG_PARPORT is not set
+
+#
+# Plug and Play support
+#
+
+#
+# Block devices
+#
+# CONFIG_BLK_DEV_FD is not set
+CONFIG_BLK_DEV_LOOP=y
+# CONFIG_BLK_DEV_CRYPTOLOOP is not set
+CONFIG_BLK_DEV_NBD=y
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_SIZE=4096
+# CONFIG_BLK_DEV_INITRD is not set
+
+#
+# ATA/ATAPI/MFM/RLL support
+#
+# CONFIG_IDE is not set
+
+#
+# SCSI device support
+#
+# CONFIG_SCSI is not set
+
+#
+# Multi-device support (RAID and LVM)
+#
+# CONFIG_MD is not set
+
+#
+# Fusion MPT device support
+#
+
+#
+# IEEE 1394 (FireWire) support
+#
+
+#
+# I2O device support
+#
+
+#
+# Networking support
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+CONFIG_PACKET=y
+# CONFIG_PACKET_MMAP is not set
+# CONFIG_NETLINK_DEV is not set
+CONFIG_UNIX=y
+# CONFIG_NET_KEY is not set
+CONFIG_INET=y
+# CONFIG_IP_MULTICAST is not set
+# 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_RARP is not set
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+# CONFIG_ARPD 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
+# CONFIG_IPV6 is not set
+# CONFIG_NETFILTER is not set
+
+#
+# SCTP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_SCTP is not set
+# CONFIG_ATM is not set
+# CONFIG_BRIDGE is not set
+# CONFIG_VLAN_8021Q is not set
+# CONFIG_DECNET 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
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+# CONFIG_NET_HW_FLOWCONTROL is not set
+
+#
+# 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 is not set
+
+#
+# ISDN subsystem
+#
+# CONFIG_ISDN is not set
+
+#
+# Telephony Support
+#
+# CONFIG_PHONE is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+
+#
+# Userland interfaces
+#
+# CONFIG_INPUT_MOUSEDEV is not set
+# 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=y
+# CONFIG_SERIO_I8042 is not set
+CONFIG_SERIO_SERPORT=y
+# CONFIG_SERIO_CT82C710 is not set
+
+#
+# Input Device Drivers
+#
+# CONFIG_INPUT_KEYBOARD is not set
+# CONFIG_INPUT_MOUSE 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 is not set
+# CONFIG_SERIAL_NONSTANDARD is not set
+
+#
+# Serial drivers
+#
+# CONFIG_SERIAL_8250 is not set
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+CONFIG_SERIAL_M32R_SIO=y
+CONFIG_SERIAL_M32R_SIO_CONSOLE=y
+# CONFIG_SERIAL_M32R_PLDSIO is not set
+CONFIG_UNIX98_PTYS=y
+CONFIG_LEGACY_PTYS=y
+CONFIG_LEGACY_PTY_COUNT=256
+# CONFIG_QIC02_TAPE is not set
+
+#
+# IPMI
+#
+# CONFIG_IPMI_HANDLER is not set
+
+#
+# Watchdog Cards
+#
+# CONFIG_WATCHDOG is not set
+# CONFIG_RTC is not set
+# CONFIG_GEN_RTC is not set
+# CONFIG_DTLK is not set
+# CONFIG_R3964 is not set
+
+#
+# Ftape, the floppy tape device driver
+#
+# CONFIG_AGP is not set
+# CONFIG_DRM is not set
+# CONFIG_RAW_DRIVER is not set
+
+#
+# I2C support
+#
+# CONFIG_I2C is not set
+
+#
+# Dallas's 1-wire bus
+#
+# CONFIG_W1 is not set
+
+#
+# Misc devices
+#
+
+#
+# Multimedia devices
+#
+# CONFIG_VIDEO_DEV is not set
+
+#
+# Digital Video Broadcasting Devices
+#
+# CONFIG_DVB is not set
+
+#
+# Graphics support
+#
+# CONFIG_FB is not set
+
+#
+# Sound
+#
+# CONFIG_SOUND is not set
+
+#
+# USB support
+#
+
+#
+# USB Gadget Support
+#
+# CONFIG_USB_GADGET 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_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+# CONFIG_XFS_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_ROMFS_FS is not set
+# CONFIG_QUOTA is not set
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_AUTOFS4_FS is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+# CONFIG_ISO9660_FS is not set
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+# 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_XATTR=y
+CONFIG_DEVPTS_FS_SECURITY=y
+# CONFIG_TMPFS is not set
+# 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_EFS_FS is not set
+# CONFIG_CRAMFS is not set
+# CONFIG_VXFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+
+#
+# Network File Systems
+#
+CONFIG_NFS_FS=y
+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_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_AFS_FS is not set
+
+#
+# Partition Types
+#
+# CONFIG_PARTITION_ADVANCED is not set
+CONFIG_MSDOS_PARTITION=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
+# CONFIG_NLS_CODEPAGE_775 is not set
+# CONFIG_NLS_CODEPAGE_850 is not set
+# CONFIG_NLS_CODEPAGE_852 is not set
+# CONFIG_NLS_CODEPAGE_855 is not set
+# CONFIG_NLS_CODEPAGE_857 is not set
+# CONFIG_NLS_CODEPAGE_860 is not set
+# CONFIG_NLS_CODEPAGE_861 is not set
+# CONFIG_NLS_CODEPAGE_862 is not set
+# CONFIG_NLS_CODEPAGE_863 is not set
+# CONFIG_NLS_CODEPAGE_864 is not set
+# CONFIG_NLS_CODEPAGE_865 is not set
+# CONFIG_NLS_CODEPAGE_866 is not set
+# CONFIG_NLS_CODEPAGE_869 is not set
+# CONFIG_NLS_CODEPAGE_936 is not set
+# CONFIG_NLS_CODEPAGE_950 is not set
+# CONFIG_NLS_CODEPAGE_932 is not set
+# CONFIG_NLS_CODEPAGE_949 is not set
+# CONFIG_NLS_CODEPAGE_874 is not set
+# 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
+# CONFIG_NLS_ISO8859_4 is not set
+# CONFIG_NLS_ISO8859_5 is not set
+# CONFIG_NLS_ISO8859_6 is not set
+# CONFIG_NLS_ISO8859_7 is not set
+# CONFIG_NLS_ISO8859_9 is not set
+# CONFIG_NLS_ISO8859_13 is not set
+# CONFIG_NLS_ISO8859_14 is not set
+# CONFIG_NLS_ISO8859_15 is not set
+# CONFIG_NLS_KOI8_R is not set
+# CONFIG_NLS_KOI8_U is not set
+# CONFIG_NLS_UTF8 is not set
+
+#
+# Profiling support
+#
+# CONFIG_PROFILING is not set
+
+#
+# Kernel hacking
+#
+# CONFIG_DEBUG_KERNEL is not set
+# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
+# CONFIG_FRAME_POINTER is not set
+
+#
+# Security options
+#
+# CONFIG_SECURITY is not set
+
+#
+# Cryptographic options
+#
+# CONFIG_CRYPTO is not set
+
+#
+# Library routines
+#
+# CONFIG_CRC_CCITT is not set
+CONFIG_CRC32=y
+# CONFIG_LIBCRC32C is not set
diff -Nru a/arch/m32r/oaks32r/dot.gdbinit.nommu b/arch/m32r/oaks32r/dot.gdbinit.nommu
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/arch/m32r/oaks32r/dot.gdbinit.nommu	2004-10-18 14:57:21 -07:00
@@ -0,0 +1,155 @@
+# .gdbinit file
+# $Id: dot.gdbinit.oaks32r,v 1.2 2004/04/15 02:33:14 takata Exp $
+#-----
+# NOTE: this file is generated by a script, "gen_gdbinit.pl".
+# (Please type "gen_gdbinit.pl --help" and check the help message).
+# $ Id: gen_gdbinit.pl,v 1.10 2004/04/15 02:10:45 takata Exp $
+#-----
+# target platform: oaks32r
+
+# setting
+set width 0d70
+set radix 0d16
+
+# clk xin:cpu:bus=16:66:33
+define clock_init
+  set *(unsigned long *)0x00ef4008 = 1
+  shell sleep 0.1
+  set *(unsigned long *)0x00ef4000 = 0x00020100
+end
+
+# Initialize programmable ports
+define port_init
+  set *(unsigned long *)0x00ef1000 = 0x1
+  set *(unsigned long *)0x00ef1060 = 0x01400001
+  set *(unsigned long *)0x00ef1064 = 0x00015555
+  set *(unsigned long *)0x00ef1068 = 0x55555050
+  set *(unsigned long *)0x00ef106c = 0x05150040
+end
+
+# Initialize SDRAM controller
+define sdram_init
+  set *(unsigned long *)0x00ef6008 = 0x00000182
+  set *(unsigned long *)0x00ef600c = 0x00000001
+  shell sleep 0.1
+  set *(unsigned long *)0x00ef602c = 0x00000010
+  set *(unsigned long *)0x00ef6028 = 0x00000300
+  set *(unsigned long *)0x00ef6048 = 0x00000001
+  set *(unsigned long *)0x00ef6020 = 0x01000041
+  set *(unsigned long *)0x00ef6004 = 0x00010117
+  set *(unsigned long *)0x00ef6010 = 0x00000001
+  set *(unsigned long *)0x00ef6024 = 0x00000001
+end
+document sdram_init
+  SDRAM controller initialization
+  0x01000000 - 0x017fffff (8MB)
+end
+
+# Initialize LAN controller
+define lanc_init
+  set *(unsigned long *)0x00ef5008 = 0x03031303
+  #RST DRV (P64)
+  set *(unsigned char *)0x00ef1046 = 0x08
+  set *(unsigned char *)0x00ef1026 = 0xff
+  set *(unsigned char *)0x00ef1026 = 0x00
+  set *(unsigned short *)0x02000630 = 0xffff
+end
+
+# Show current task structure
+define show_current
+  set $current = $spi & 0xffffe000
+  printf "$current=0x%08lX\n",$current
+  print *(struct task_struct *)$current
+end
+
+# Show user assigned task structure
+define show_task
+  set  = $arg0 & 0xffffe000
+  printf "$task=0x%08lX\n",$task
+  print *(struct task_struct *)$task
+end
+document show_task
+  Show user assigned task structure
+  arg0 : task structure address
+end
+
+# Show M32R registers
+define show_regs
+  printf " R0[0x%08lX]   R1[0x%08lX]   R2[0x%08lX]   R3[0x%08lX]\n",$r0,$r1,$r2,$r3
+  printf " R4[0x%08lX]   R5[0x%08lX]   R6[0x%08lX]   R7[0x%08lX]\n",$r4,$r5,$r6,$r7
+  printf " R8[0x%08lX]   R9[0x%08lX]  R10[0x%08lX]  R11[0x%08lX]\n",$r8,$r9,$r10,$r11
+  printf "R12[0x%08lX]   FP[0x%08lX]   LR[0x%08lX]   SP[0x%08lX]\n",$r12,$fp,$lr,$sp
+  printf "PSW[0x%08lX]  CBR[0x%08lX]  SPI[0x%08lX]  SPU[0x%08lX]\n",$psw,$cbr,$spi,$spu
+  printf "BPC[0x%08lX]   PC[0x%08lX] ACCL[0x%08lX] ACCH[0x%08lX]\n",$bpc,$pc,$accl,$acch
+end
+
+# Setup all
+define setup
+  use_mon_code
+  set *(unsigned int)0xfffffffc=0x60
+  shell sleep 0.1
+  clock_init
+  shell sleep 0.1
+  port_init
+  sdram_init
+  lanc_init
+end
+
+# Load modules
+define load_modules
+  use_debug_dma
+  load
+end
+
+# Set kernel parameters
+define set_kernel_parameters
+  set $param = (void*)0x01002000
+  # INITRD_START
+  set *(unsigned long *)($param + 0x0010) = 0x00000000
+  # INITRD_SIZE
+  set *(unsigned long *)($param + 0x0014) = 0x00000000
+  # M32R_CPUCLK
+  set *(unsigned long *)($param + 0x0018) = 0d66666667
+  # M32R_BUSCLK
+  set *(unsigned long *)($param + 0x001c) = 0d33333333
+
+  # M32R_TIMER_DIVIDE
+  set *(unsigned long *)($param + 0x0020) = 0d128
+
+#  set {char[0x200]}($param + 0x100) = "console=ttyD0,115200n8x root=/dev/nfsroot nfsroot=192.168.0.1:/project/m32r-linux/export/rootfs nfsaddrs=192.168.0.101:192.168.0.1:192.168.0.1:255.255.255.0:mappi001 \0"
+  set {char[0x200]}($param + 0x100) = "console=ttyD0,115200n8x root=/dev/nfsroot nfsroot=192.168.0.1:/project/m32r-linux/export/root.busybox.flat nfsaddrs=192.168.0.101:192.168.0.1:192.168.0.1:255.255.255.0:mappi001 \0"
+end
+
+# Boot
+define boot
+  set_kernel_parameters
+  set $fp = 0
+  set $pc = 0x01001000
+  si
+  c
+end
+
+# Set breakpoints
+define set_breakpoints
+  b *0x00000020
+  b *0x00000030
+end
+
+# Restart
+define restart
+  sdireset
+  sdireset
+  setup
+  load_modules
+  boot
+end
+
+sdireset
+sdireset
+file vmlinux
+target m32rsdi
+setup
+#load_modules
+#set_breakpoints
+#boot
+
diff -Nru a/arch/m32r/oprofile/Kconfig b/arch/m32r/oprofile/Kconfig
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/arch/m32r/oprofile/Kconfig	2004-10-18 14:57:24 -07:00
@@ -0,0 +1,23 @@
+
+menu "Profiling support"
+	depends on EXPERIMENTAL
+
+config PROFILING
+	bool "Profiling support (EXPERIMENTAL)"
+	help
+	  Say Y here to enable the extended profiling support mechanisms used
+	  by profilers such as OProfile.
+
+
+config OPROFILE
+	tristate "OProfile system profiling (EXPERIMENTAL)"
+	depends on PROFILING
+	help
+	  OProfile is a profiling system capable of profiling the
+	  whole system, include the kernel, kernel modules, libraries,
+	  and applications.
+
+	  If unsure, say N.
+
+endmenu
+
diff -Nru a/arch/m32r/oprofile/Makefile b/arch/m32r/oprofile/Makefile
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/arch/m32r/oprofile/Makefile	2004-10-18 14:57:23 -07:00
@@ -0,0 +1,9 @@
+obj-$(CONFIG_OPROFILE) += oprofile.o
+
+DRIVER_OBJS := $(addprefix ../../../drivers/oprofile/, \
+		oprof.o cpu_buffer.o buffer_sync.o \
+		event_buffer.o oprofile_files.o \
+		oprofilefs.o oprofile_stats.o \
+		timer_int.o )
+
+oprofile-y := $(DRIVER_OBJS) init.o
diff -Nru a/arch/m32r/oprofile/init.c b/arch/m32r/oprofile/init.c
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/arch/m32r/oprofile/init.c	2004-10-18 14:57:21 -07:00
@@ -0,0 +1,25 @@
+/**
+ * @file init.c
+ *
+ * @remark Copyright 2002 OProfile authors
+ * @remark Read the file COPYING
+ *
+ * @author John Levon <levon@movementarian.org>
+ */
+
+#include <linux/kernel.h>
+#include <linux/oprofile.h>
+#include <linux/errno.h>
+#include <linux/init.h>
+
+extern void timer_init(struct oprofile_operations ** ops);
+
+int __init oprofile_arch_init(struct oprofile_operations ** ops)
+{
+	return -ENODEV;
+}
+
+
+void oprofile_arch_exit(void)
+{
+}
diff -Nru a/arch/m32r/opsput/defconfig.opsput b/arch/m32r/opsput/defconfig.opsput
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/arch/m32r/opsput/defconfig.opsput	2004-10-18 14:57:22 -07:00
@@ -0,0 +1,598 @@
+#
+# Automatically generated make config: don't edit
+#
+CONFIG_M32R=y
+CONFIG_UID16=y
+CONFIG_GENERIC_ISA_DMA=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=y
+CONFIG_IKCONFIG=y
+# CONFIG_IKCONFIG_PROC is not set
+CONFIG_EMBEDDED=y
+# CONFIG_KALLSYMS is not set
+# CONFIG_FUTEX is not set
+# CONFIG_EPOLL is not set
+CONFIG_IOSCHED_NOOP=y
+# CONFIG_IOSCHED_AS is not set
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+
+#
+# Loadable module support
+#
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+# CONFIG_MODULE_FORCE_UNLOAD is not set
+CONFIG_OBSOLETE_MODPARM=y
+# CONFIG_MODVERSIONS is not set
+CONFIG_KMOD=y
+
+#
+# Processor type and features
+#
+# CONFIG_PLAT_MAPPI is not set
+# CONFIG_PLAT_USRV is not set
+# CONFIG_PLAT_M32700UT is not set
+CONFIG_PLAT_OPSPUT=y
+# CONFIG_PLAT_OAKS32R is not set
+# CONFIG_PLAT_MAPPI2 is not set
+# CONFIG_CHIP_M32700 is not set
+# CONFIG_CHIP_M32102 is not set
+# CONFIG_CHIP_VDEC2 is not set
+CONFIG_CHIP_OPSP=y
+CONFIG_MMU=y
+CONFIG_TLB_ENTRIES=32
+CONFIG_ISA_M32R2=y
+CONFIG_ISA_DSP_LEVEL2=y
+CONFIG_ISA_DUAL_ISSUE=y
+CONFIG_BUS_CLOCK=50000000
+CONFIG_TIMER_DIVIDE=128
+# CONFIG_CPU_LITTLE_ENDIAN is not set
+CONFIG_MEMORY_START=0x08000000
+CONFIG_MEMORY_SIZE=0x01000000
+CONFIG_NOHIGHMEM=y
+# CONFIG_DISCONTIGMEM is not set
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+# CONFIG_RWSEM_XCHGADD_ALGORITHM is not set
+# CONFIG_PREEMPT is not set
+# CONFIG_SMP is not set
+
+#
+# M32R drivers
+#
+# CONFIG_M32R_CFC is not set
+CONFIG_M32R_SMC91111=y
+CONFIG_M32700UT_DS1302=y
+
+#
+# Power management options (ACPI, APM)
+#
+# CONFIG_PM is not set
+
+#
+# Bus options (PCI, PCMCIA, EISA, MCA, ISA)
+#
+# CONFIG_PCI is not set
+# CONFIG_ISA is not set
+
+#
+# PCMCIA/CardBus support
+#
+CONFIG_PCMCIA=y
+# CONFIG_PCMCIA_DEBUG is not set
+# CONFIG_TCIC is not set
+
+#
+# PCI Hotplug Support
+#
+
+#
+# Executable file formats
+#
+CONFIG_BINFMT_ELF=y
+# CONFIG_BINFMT_MISC is not set
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+# CONFIG_FW_LOADER is not set
+# CONFIG_DEBUG_DRIVER is not set
+
+#
+# Memory Technology Devices (MTD)
+#
+# CONFIG_MTD is not set
+
+#
+# Parallel port support
+#
+# CONFIG_PARPORT is not set
+
+#
+# Plug and Play support
+#
+
+#
+# Block devices
+#
+# CONFIG_BLK_DEV_FD is not set
+CONFIG_BLK_DEV_LOOP=y
+# CONFIG_BLK_DEV_CRYPTOLOOP is not set
+# CONFIG_BLK_DEV_NBD is not set
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_SIZE=4096
+# CONFIG_BLK_DEV_INITRD is not set
+
+#
+# ATA/ATAPI/MFM/RLL support
+#
+# CONFIG_IDE is not set
+
+#
+# SCSI device support
+#
+CONFIG_SCSI=m
+CONFIG_SCSI_PROC_FS=y
+
+#
+# SCSI support type (disk, tape, CD-ROM)
+#
+CONFIG_BLK_DEV_SD=m
+# CONFIG_CHR_DEV_ST is not set
+# CONFIG_CHR_DEV_OSST is not set
+CONFIG_BLK_DEV_SR=m
+# CONFIG_BLK_DEV_SR_VENDOR is not set
+CONFIG_CHR_DEV_SG=m
+
+#
+# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
+#
+CONFIG_SCSI_MULTI_LUN=y
+# CONFIG_SCSI_CONSTANTS is not set
+# CONFIG_SCSI_LOGGING is not set
+
+#
+# SCSI Transport Attributes
+#
+# CONFIG_SCSI_SPI_ATTRS is not set
+# CONFIG_SCSI_FC_ATTRS is not set
+
+#
+# SCSI low-level drivers
+#
+# CONFIG_SCSI_AIC7XXX_OLD is not set
+# CONFIG_SCSI_SATA is not set
+# CONFIG_SCSI_EATA_PIO is not set
+# CONFIG_SCSI_DEBUG is not set
+
+#
+# PCMCIA SCSI adapter support
+#
+# CONFIG_PCMCIA_AHA152X is not set
+# CONFIG_PCMCIA_FDOMAIN is not set
+# CONFIG_PCMCIA_NINJA_SCSI is not set
+# CONFIG_PCMCIA_QLOGIC is not set
+# CONFIG_PCMCIA_SYM53C500 is not set
+
+#
+# Multi-device support (RAID and LVM)
+#
+# CONFIG_MD is not set
+
+#
+# Fusion MPT device support
+#
+
+#
+# IEEE 1394 (FireWire) support
+#
+
+#
+# I2O device support
+#
+
+#
+# Networking support
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+CONFIG_PACKET=y
+# CONFIG_PACKET_MMAP is not set
+# CONFIG_NETLINK_DEV is not set
+CONFIG_UNIX=y
+# CONFIG_NET_KEY is not set
+CONFIG_INET=y
+# CONFIG_IP_MULTICAST is not set
+# 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_RARP is not set
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+# CONFIG_ARPD 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
+# CONFIG_IPV6 is not set
+# CONFIG_NETFILTER is not set
+
+#
+# SCTP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_SCTP is not set
+# CONFIG_ATM is not set
+# CONFIG_BRIDGE is not set
+# CONFIG_VLAN_8021Q is not set
+# CONFIG_DECNET 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
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+# CONFIG_NET_HW_FLOWCONTROL is not set
+
+#
+# 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 is not set
+
+#
+# ISDN subsystem
+#
+# CONFIG_ISDN is not set
+
+#
+# Telephony Support
+#
+# CONFIG_PHONE is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+
+#
+# Userland interfaces
+#
+# CONFIG_INPUT_MOUSEDEV is not set
+# 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=y
+# CONFIG_SERIO_I8042 is not set
+CONFIG_SERIO_SERPORT=y
+# CONFIG_SERIO_CT82C710 is not set
+
+#
+# Input Device Drivers
+#
+# CONFIG_INPUT_KEYBOARD is not set
+# CONFIG_INPUT_MOUSE 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 is not set
+# CONFIG_SERIAL_NONSTANDARD is not set
+
+#
+# Serial drivers
+#
+# CONFIG_SERIAL_8250 is not set
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+# CONFIG_SERIAL_M32R_SIO is not set
+CONFIG_SERIAL_M32R_PLDSIO=y
+CONFIG_SERIAL_M32R_PLDSIO_CONSOLE=y
+CONFIG_UNIX98_PTYS=y
+CONFIG_LEGACY_PTYS=y
+CONFIG_LEGACY_PTY_COUNT=256
+# CONFIG_QIC02_TAPE is not set
+
+#
+# IPMI
+#
+# CONFIG_IPMI_HANDLER is not set
+
+#
+# Watchdog Cards
+#
+# CONFIG_WATCHDOG is not set
+# CONFIG_RTC is not set
+# CONFIG_GEN_RTC is not set
+# CONFIG_DTLK is not set
+# CONFIG_R3964 is not set
+
+#
+# Ftape, the floppy tape device driver
+#
+# CONFIG_AGP is not set
+# CONFIG_DRM is not set
+
+#
+# PCMCIA character devices
+#
+# CONFIG_SYNCLINK_CS is not set
+# CONFIG_RAW_DRIVER is not set
+
+#
+# I2C support
+#
+# CONFIG_I2C is not set
+
+#
+# Dallas's 1-wire bus
+#
+# CONFIG_W1 is not set
+
+#
+# Misc devices
+#
+
+#
+# Multimedia devices
+#
+# CONFIG_VIDEO_DEV is not set
+
+#
+# Digital Video Broadcasting Devices
+#
+# CONFIG_DVB is not set
+
+#
+# Graphics support
+#
+# CONFIG_FB is not set
+
+#
+# Sound
+#
+# CONFIG_SOUND is not set
+
+#
+# USB support
+#
+
+#
+# USB Gadget Support
+#
+# CONFIG_USB_GADGET is not set
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+# CONFIG_EXT2_FS_XATTR is not set
+CONFIG_EXT3_FS=m
+CONFIG_EXT3_FS_XATTR=y
+# CONFIG_EXT3_FS_POSIX_ACL is not set
+# CONFIG_EXT3_FS_SECURITY is not set
+CONFIG_JBD=m
+CONFIG_JBD_DEBUG=y
+CONFIG_FS_MBCACHE=y
+CONFIG_REISERFS_FS=m
+# 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 is not set
+# CONFIG_ROMFS_FS is not set
+# CONFIG_QUOTA is not set
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_AUTOFS4_FS is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+CONFIG_ISO9660_FS=m
+CONFIG_JOLIET=y
+# CONFIG_ZISOFS is not set
+CONFIG_UDF_FS=m
+CONFIG_UDF_NLS=y
+
+#
+# DOS/FAT/NT Filesystems
+#
+CONFIG_FAT_FS=m
+CONFIG_MSDOS_FS=m
+CONFIG_VFAT_FS=m
+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_EFS_FS is not set
+# CONFIG_CRAMFS is not set
+# CONFIG_VXFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+
+#
+# Network File Systems
+#
+CONFIG_NFS_FS=y
+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_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_AFS_FS is not set
+
+#
+# Partition Types
+#
+# CONFIG_PARTITION_ADVANCED is not set
+CONFIG_MSDOS_PARTITION=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
+# CONFIG_NLS_CODEPAGE_775 is not set
+# CONFIG_NLS_CODEPAGE_850 is not set
+# CONFIG_NLS_CODEPAGE_852 is not set
+# CONFIG_NLS_CODEPAGE_855 is not set
+# CONFIG_NLS_CODEPAGE_857 is not set
+# CONFIG_NLS_CODEPAGE_860 is not set
+# CONFIG_NLS_CODEPAGE_861 is not set
+# CONFIG_NLS_CODEPAGE_862 is not set
+# CONFIG_NLS_CODEPAGE_863 is not set
+# CONFIG_NLS_CODEPAGE_864 is not set
+# CONFIG_NLS_CODEPAGE_865 is not set
+# CONFIG_NLS_CODEPAGE_866 is not set
+# CONFIG_NLS_CODEPAGE_869 is not set
+# CONFIG_NLS_CODEPAGE_936 is not set
+# CONFIG_NLS_CODEPAGE_950 is not set
+# CONFIG_NLS_CODEPAGE_932 is not set
+# CONFIG_NLS_CODEPAGE_949 is not set
+# CONFIG_NLS_CODEPAGE_874 is not set
+# 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
+# CONFIG_NLS_ISO8859_4 is not set
+# CONFIG_NLS_ISO8859_5 is not set
+# CONFIG_NLS_ISO8859_6 is not set
+# CONFIG_NLS_ISO8859_7 is not set
+# CONFIG_NLS_ISO8859_9 is not set
+# CONFIG_NLS_ISO8859_13 is not set
+# CONFIG_NLS_ISO8859_14 is not set
+# CONFIG_NLS_ISO8859_15 is not set
+# CONFIG_NLS_KOI8_R is not set
+# CONFIG_NLS_KOI8_U is not set
+# CONFIG_NLS_UTF8 is not set
+
+#
+# Profiling support
+#
+# CONFIG_PROFILING is not set
+
+#
+# Kernel hacking
+#
+CONFIG_DEBUG_KERNEL=y
+# CONFIG_DEBUG_STACKOVERFLOW is not set
+# CONFIG_DEBUG_SLAB is not set
+# CONFIG_DEBUG_IOVIRT is not set
+# CONFIG_MAGIC_SYSRQ is not set
+# CONFIG_DEBUG_SPINLOCK is not set
+# CONFIG_DEBUG_PAGEALLOC is not set
+CONFIG_DEBUG_INFO=y
+# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
+# CONFIG_FRAME_POINTER is not set
+
+#
+# Security options
+#
+# CONFIG_SECURITY is not set
+
+#
+# Cryptographic options
+#
+# CONFIG_CRYPTO is not set
+
+#
+# Library routines
+#
+# CONFIG_CRC_CCITT is not set
+CONFIG_CRC32=y
+# CONFIG_LIBCRC32C is not set
diff -Nru a/arch/m32r/opsput/dot.gdbinit b/arch/m32r/opsput/dot.gdbinit
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/arch/m32r/opsput/dot.gdbinit	2004-10-18 14:57:23 -07:00
@@ -0,0 +1,180 @@
+# .gdbinit file
+# $Id: dot.gdbinit,v 1.1 2004/07/27 06:54:20 sakugawa Exp $
+
+# setting
+set width 0d70
+set radix 0d16
+set height 0
+debug_chaos
+
+define tlb_init
+  set $tlbbase = 0xfe000000
+  set *(unsigned long *)($tlbbase + 0x04) = 0x0
+  set *(unsigned long *)($tlbbase + 0x0c) = 0x0
+  set *(unsigned long *)($tlbbase + 0x14) = 0x0
+  set *(unsigned long *)($tlbbase + 0x1c) = 0x0
+  set *(unsigned long *)($tlbbase + 0x24) = 0x0
+  set *(unsigned long *)($tlbbase + 0x2c) = 0x0
+  set *(unsigned long *)($tlbbase + 0x34) = 0x0
+  set *(unsigned long *)($tlbbase + 0x3c) = 0x0
+  set *(unsigned long *)($tlbbase + 0x44) = 0x0
+  set *(unsigned long *)($tlbbase + 0x4c) = 0x0
+  set *(unsigned long *)($tlbbase + 0x54) = 0x0
+  set *(unsigned long *)($tlbbase + 0x5c) = 0x0
+  set *(unsigned long *)($tlbbase + 0x64) = 0x0
+  set *(unsigned long *)($tlbbase + 0x6c) = 0x0
+  set *(unsigned long *)($tlbbase + 0x74) = 0x0
+  set *(unsigned long *)($tlbbase + 0x7c) = 0x0
+  set *(unsigned long *)($tlbbase + 0x84) = 0x0
+  set *(unsigned long *)($tlbbase + 0x8c) = 0x0
+  set *(unsigned long *)($tlbbase + 0x94) = 0x0
+  set *(unsigned long *)($tlbbase + 0x9c) = 0x0
+  set *(unsigned long *)($tlbbase + 0xa4) = 0x0
+  set *(unsigned long *)($tlbbase + 0xac) = 0x0
+  set *(unsigned long *)($tlbbase + 0xb4) = 0x0
+  set *(unsigned long *)($tlbbase + 0xbc) = 0x0
+  set *(unsigned long *)($tlbbase + 0xc4) = 0x0
+  set *(unsigned long *)($tlbbase + 0xcc) = 0x0
+  set *(unsigned long *)($tlbbase + 0xd4) = 0x0
+  set *(unsigned long *)($tlbbase + 0xdc) = 0x0
+  set *(unsigned long *)($tlbbase + 0xe4) = 0x0
+  set *(unsigned long *)($tlbbase + 0xec) = 0x0
+  set *(unsigned long *)($tlbbase + 0xf4) = 0x0
+  set *(unsigned long *)($tlbbase + 0xfc) = 0x0
+  set $tlbbase = 0xfe000800
+  set *(unsigned long *)($tlbbase + 0x04) = 0x0
+  set *(unsigned long *)($tlbbase + 0x0c) = 0x0
+  set *(unsigned long *)($tlbbase + 0x14) = 0x0
+  set *(unsigned long *)($tlbbase + 0x1c) = 0x0
+  set *(unsigned long *)($tlbbase + 0x24) = 0x0
+  set *(unsigned long *)($tlbbase + 0x2c) = 0x0
+  set *(unsigned long *)($tlbbase + 0x34) = 0x0
+  set *(unsigned long *)($tlbbase + 0x3c) = 0x0
+  set *(unsigned long *)($tlbbase + 0x44) = 0x0
+  set *(unsigned long *)($tlbbase + 0x4c) = 0x0
+  set *(unsigned long *)($tlbbase + 0x54) = 0x0
+  set *(unsigned long *)($tlbbase + 0x5c) = 0x0
+  set *(unsigned long *)($tlbbase + 0x64) = 0x0
+  set *(unsigned long *)($tlbbase + 0x6c) = 0x0
+  set *(unsigned long *)($tlbbase + 0x74) = 0x0
+  set *(unsigned long *)($tlbbase + 0x7c) = 0x0
+  set *(unsigned long *)($tlbbase + 0x84) = 0x0
+  set *(unsigned long *)($tlbbase + 0x8c) = 0x0
+  set *(unsigned long *)($tlbbase + 0x94) = 0x0
+  set *(unsigned long *)($tlbbase + 0x9c) = 0x0
+  set *(unsigned long *)($tlbbase + 0xa4) = 0x0
+  set *(unsigned long *)($tlbbase + 0xac) = 0x0
+  set *(unsigned long *)($tlbbase + 0xb4) = 0x0
+  set *(unsigned long *)($tlbbase + 0xbc) = 0x0
+  set *(unsigned long *)($tlbbase + 0xc4) = 0x0
+  set *(unsigned long *)($tlbbase + 0xcc) = 0x0
+  set *(unsigned long *)($tlbbase + 0xd4) = 0x0
+  set *(unsigned long *)($tlbbase + 0xdc) = 0x0
+  set *(unsigned long *)($tlbbase + 0xe4) = 0x0
+  set *(unsigned long *)($tlbbase + 0xec) = 0x0
+  set *(unsigned long *)($tlbbase + 0xf4) = 0x0
+  set *(unsigned long *)($tlbbase + 0xfc) = 0x0
+end
+
+define load_modules
+  use_debug_dma
+  load
+end
+
+# Set kernel parameters
+define set_kernel_parameters
+  set $param = (void*)0x88002000
+  # INITRD_START
+#  set *(unsigned long *)($param + 0x0010) = 0x08300000
+  # INITRD_SIZE
+#  set *(unsigned long *)($param + 0x0014) = 0x00400000
+  # M32R_CPUCLK
+  set *(unsigned long *)($param + 0x0018) = 0d200000000
+  # M32R_BUSCLK
+  set *(unsigned long *)($param + 0x001c) = 0d50000000
+#  set *(unsigned long *)($param + 0x001c) = 0d25000000
+
+  # M32R_TIMER_DIVIDE
+  set *(unsigned long *)($param + 0x0020) = 0d128
+
+  set {char[0x200]}($param + 0x100) = "console=ttyD0,115200n8x\
+  root=/dev/nfsroot \
+  nfsroot=192.168.0.1:/project/m32r-linux/export/root.2.6 \
+  nfsaddrs=192.168.0.101:192.168.0.1:192.168.0.1:255.255.255.0:mappi001 \
+  mem=16m \0"
+end
+
+define boot
+  set_kernel_parameters
+  set $pc=0x88001000
+  set $fp=0
+  set $evb=0x88000000
+  # I/D-Cache ON
+
+# IPI
+#  set *(long *)0x00eff2f8 = 0x2
+  set $fp=0
+#  set *(unsigned long *)0xa0ef4000 = 0x100
+  si
+end
+
+# Show TLB entries
+define show_tlb_entries
+  set $i = 0
+  set $addr = $arg0
+  use_mon_code
+  while ($i < 0d32 )
+    set $tlb_tag = *(unsigned long*)$addr
+    set $tlb_data = *(unsigned long*)($addr + 4)
+    printf " [%2d] 0x%08lx : 0x%08lx - 0x%08lx\n", $i, $addr, $tlb_tag, $tlb_data
+    set $i = $i + 1
+    set $addr = $addr + 8
+  end
+#  use_debug_dma
+end
+define itlb
+  set $itlb=0xfe000000
+  show_tlb_entries $itlb
+end
+define dtlb
+  set $dtlb=0xfe000800
+  show_tlb_entries $dtlb
+end
+
+define show_regs
+  printf " R0[%08lx]   R1[%08lx]   R2[%08lx]   R3[%08lx]\n",$r0,$r1,$r2,$r3
+  printf " R4[%08lx]   R5[%08lx]   R6[%08lx]   R7[%08lx]\n",$r4,$r5,$r6,$r7
+  printf " R8[%08lx]   R9[%08lx]  R10[%08lx]  R11[%08lx]\n",$r8,$r9,$r10,$r11
+  printf "R12[%08lx]   FP[%08lx]   LR[%08lx]   SP[%08lx]\n",$r12,$fp,$lr,$sp
+  printf "PSW[%08lx]  CBR[%08lx]  SPI[%08lx]  SPU[%08lx]\n",$psw,$cbr,$spi,$spu
+  printf "BPC[%08lx]   PC[%08lx] ACCL[%08lx] ACCH[%08lx]\n",$bpc,$pc,$accl,$acch
+  printf "EVB[%08lx]\n",$evb
+end
+
+define setup
+  debug_chaos
+  set *(unsigned long *)0xa0ef6004 = 0x0001053f
+  set *(unsigned long *)0xa0ef6028 = 0x00031102
+#  set *(unsigned long *)0xa0ef400c = 0x2
+end
+
+sdireset
+sdireset
+file vmlinux
+target m32rsdi
+set $pc=0x0
+b *0x30000
+c
+setup
+tlb_init
+load_modules
+#set *(long *)0xa0ef4000=0x101
+#set *(long *)0xa0ef400c=0x002
+
+boot
+#b tme_handler
+b *0x88000020
+
+
+
+
diff -Nru a/arch/m68k/Kconfig b/arch/m68k/Kconfig
--- a/arch/m68k/Kconfig	2004-10-18 14:56:33 -07:00
+++ b/arch/m68k/Kconfig	2004-10-18 14:56:33 -07:00
@@ -21,12 +21,10 @@
 config RWSEM_XCHGADD_ALGORITHM
 	bool
 
-
 mainmenu "Linux/68k Kernel Configuration"
 
 source "init/Kconfig"
 
-
 menu "Platform dependent setup"
 
 config EISA
@@ -355,7 +353,6 @@
 
 endmenu
 
-
 menu "General setup"
 
 source "fs/Kconfig.binfmt"
@@ -447,7 +444,6 @@
 
 source "drivers/Kconfig"
 
-
 menu "Character devices"
 
 config ATARI_MFPSER
@@ -652,47 +648,10 @@
 
 source "fs/Kconfig"
 
-menu "Kernel hacking"
-
-config DEBUG_KERNEL
-	bool "Kernel debugging"
-
-config MAGIC_SYSRQ
-	bool "Magic SysRq key"
-	depends on DEBUG_KERNEL
-	help
-	  If you say Y here, you will have some control over the system even
-	  if the system crashes for example during kernel debugging (e.g., you
-	  will be able to flush the buffer cache to disk, reboot the system
-	  immediately or dump some status information). This is accomplished
-	  by pressing various keys while holding SysRq (Alt+PrintScreen). It
-	  also works on a serial console (on PC hardware at least), if you
-	  send a BREAK and then within 5 seconds a command keypress. The
-	  keys are documented in <file:Documentation/sysrq.txt>. Don't say Y
-	  unless you really know what this hack does.
-
-config DEBUG_SLAB
-	bool "Debug memory allocations"
-	depends on DEBUG_KERNEL
-
-config DEBUG_BUGVERBOSE
-	bool "Verbose BUG() reporting"
-	depends on DEBUG_KERNEL
-
-config DEBUG_INFO
-	bool "Compile the kernel with debug info"
-	depends on DEBUG_KERNEL
-	help
-          If you say Y here the resulting kernel image will include
-	  debugging info resulting in a larger kernel image.
-	  Say Y here only if you plan to use gdb to debug the kernel.
-	  If you don't debug the kernel, you can say N.
-
-endmenu
+source "arch/m68k/Kconfig.debug"
 
 source "security/Kconfig"
 
 source "crypto/Kconfig"
 
 source "lib/Kconfig"
-
diff -Nru a/arch/m68k/Kconfig.debug b/arch/m68k/Kconfig.debug
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/arch/m68k/Kconfig.debug	2004-10-18 14:57:24 -07:00
@@ -0,0 +1,5 @@
+menu "Kernel hacking"
+
+source "lib/Kconfig.debug"
+
+endmenu
diff -Nru a/arch/m68k/Makefile b/arch/m68k/Makefile
--- a/arch/m68k/Makefile	2004-10-18 14:57:03 -07:00
+++ b/arch/m68k/Makefile	2004-10-18 14:57:03 -07:00
@@ -28,7 +28,7 @@
 LDFLAGS_vmlinux = -N
 endif
 
-CHECK := $(CHECK) -D__mc68000__=1 -I$(shell $(CC) -print-file-name=include)
+CHECKFLAGS += -D__mc68000__ -I$(shell $(CC) -print-file-name=include)
 
 # without -fno-strength-reduce the 53c7xx.c driver fails ;-(
 CFLAGS += -pipe -fno-strength-reduce -ffixed-a2
diff -Nru a/arch/m68k/kernel/Makefile b/arch/m68k/kernel/Makefile
--- a/arch/m68k/kernel/Makefile	2004-10-18 14:56:49 -07:00
+++ b/arch/m68k/kernel/Makefile	2004-10-18 14:56:49 -07:00
@@ -7,7 +7,7 @@
 else
   extra-y := sun3-head.o
 endif
-extra-y	+= vmlinux.lds.s
+extra-y	+= vmlinux.lds
 
 obj-y		:= entry.o process.o traps.o ints.o signal.o ptrace.o \
 			sys_m68k.o time.o semaphore.o setup.o m68k_ksyms.o
diff -Nru a/arch/m68k/kernel/bios32.c b/arch/m68k/kernel/bios32.c
--- a/arch/m68k/kernel/bios32.c	2004-10-18 14:56:32 -07:00
+++ b/arch/m68k/kernel/bios32.c	2004-10-18 14:56:32 -07:00
@@ -77,11 +77,6 @@
 static unsigned int io_base;
 static unsigned int mem_base;
 
-struct pci_fixup pcibios_fixups[] =
-{
-	{ 0 }
-};
-
 /*
  * static void disable_dev(struct pci_dev *dev)
  *
diff -Nru a/arch/m68k/kernel/m68k_ksyms.c b/arch/m68k/kernel/m68k_ksyms.c
--- a/arch/m68k/kernel/m68k_ksyms.c	2004-10-18 14:56:50 -07:00
+++ b/arch/m68k/kernel/m68k_ksyms.c	2004-10-18 14:56:50 -07:00
@@ -16,7 +16,6 @@
 #include <asm/io.h>
 #include <asm/semaphore.h>
 #include <asm/checksum.h>
-#include <asm/hardirq.h>
 
 asmlinkage long long __ashldi3 (long long, int);
 asmlinkage long long __ashrdi3 (long long, int);
@@ -72,18 +71,18 @@
    explicitly (the C compiler generates them).  Fortunately,
    their interface isn't gonna change any time soon now, so
    it's OK to leave it out of version control.  */
-EXPORT_SYMBOL_NOVERS(__ashldi3);
-EXPORT_SYMBOL_NOVERS(__ashrdi3);
-EXPORT_SYMBOL_NOVERS(__lshrdi3);
-EXPORT_SYMBOL_NOVERS(memcpy);
-EXPORT_SYMBOL_NOVERS(memset);
-EXPORT_SYMBOL_NOVERS(memcmp);
-EXPORT_SYMBOL_NOVERS(memscan);
-EXPORT_SYMBOL_NOVERS(__muldi3);
-
-EXPORT_SYMBOL_NOVERS(__down_failed);
-EXPORT_SYMBOL_NOVERS(__down_failed_interruptible);
-EXPORT_SYMBOL_NOVERS(__down_failed_trylock);
-EXPORT_SYMBOL_NOVERS(__up_wakeup);
+EXPORT_SYMBOL(__ashldi3);
+EXPORT_SYMBOL(__ashrdi3);
+EXPORT_SYMBOL(__lshrdi3);
+EXPORT_SYMBOL(memcpy);
+EXPORT_SYMBOL(memset);
+EXPORT_SYMBOL(memcmp);
+EXPORT_SYMBOL(memscan);
+EXPORT_SYMBOL(__muldi3);
+
+EXPORT_SYMBOL(__down_failed);
+EXPORT_SYMBOL(__down_failed_interruptible);
+EXPORT_SYMBOL(__down_failed_trylock);
+EXPORT_SYMBOL(__up_wakeup);
 
 EXPORT_SYMBOL(get_wchan);
diff -Nru a/arch/m68k/kernel/process.c b/arch/m68k/kernel/process.c
--- a/arch/m68k/kernel/process.c	2004-10-18 14:57:05 -07:00
+++ b/arch/m68k/kernel/process.c	2004-10-18 14:57:05 -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/ptrace.c b/arch/m68k/kernel/ptrace.c
--- a/arch/m68k/kernel/ptrace.c	2004-10-18 14:56:27 -07:00
+++ b/arch/m68k/kernel/ptrace.c	2004-10-18 14:56:27 -07:00
@@ -379,11 +379,8 @@
 	if (!current->thread.work.delayed_trace &&
 	    !current->thread.work.syscall_trace)
 		return;
-	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
 	 * for normal use.  strace only continues with a signal if the
diff -Nru a/arch/m68k/kernel/signal.c b/arch/m68k/kernel/signal.c
--- a/arch/m68k/kernel/signal.c	2004-10-18 14:56:48 -07:00
+++ b/arch/m68k/kernel/signal.c	2004-10-18 14:56:48 -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-10-18 14:56:20 -07:00
+++ b/arch/m68k/kernel/time.c	2004-10-18 14:56:20 -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-10-18 14:57:03 -07:00
+++ b/arch/m68k/kernel/vmlinux-std.lds	2004-10-18 14:57:03 -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-10-18 14:55:46 -07:00
+++ b/arch/m68k/kernel/vmlinux-sun3.lds	2004-10-18 14:55:46 -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/m68k/q40/q40ints.c b/arch/m68k/q40/q40ints.c
--- a/arch/m68k/q40/q40ints.c	2004-10-18 14:57:03 -07:00
+++ b/arch/m68k/q40/q40ints.c	2004-10-18 14:57:03 -07:00
@@ -19,12 +19,12 @@
 #include <linux/sched.h>
 #include <linux/seq_file.h>
 #include <linux/interrupt.h>
+#include <linux/hardirq.h>
 
 #include <asm/rtc.h>
 #include <asm/ptrace.h>
 #include <asm/system.h>
 #include <asm/irq.h>
-#include <asm/hardirq.h>
 #include <asm/traps.h>
 
 #include <asm/q40_master.h>
diff -Nru a/arch/m68knommu/Kconfig b/arch/m68knommu/Kconfig
--- a/arch/m68knommu/Kconfig	2004-10-18 14:56:48 -07:00
+++ b/arch/m68knommu/Kconfig	2004-10-18 14:56:48 -07:00
@@ -5,6 +5,10 @@
 
 mainmenu "uClinux/68k (w/o MMU) Kernel Configuration"
 
+config M68KNOMMU
+	bool
+	default y
+
 config MMU
 	bool
 	default n
@@ -25,7 +29,6 @@
 	bool
 	default n
 
-
 source "init/Kconfig"
 
 menu "Processor type and features"
@@ -388,7 +391,7 @@
 	  a lot of RAM, and you need to able to allocate very large
 	  contiguous chunks. If unsure, say N.
 
-choice 
+choice
 	prompt "RAM size"
 	default AUTO
 
@@ -421,7 +424,7 @@
 
 endchoice
 
-choice 
+choice
 	prompt "RAM bus width"
 	default RAMAUTOBIT
 
@@ -472,7 +475,6 @@
 
 endmenu
 
-
 menu "Bus options (PCI, PCMCIA, EISA, MCA, ISA)"
 
 config PCI
@@ -511,64 +513,10 @@
 
 source "fs/Kconfig"
 
-menu "Kernel hacking"
-
-config FULLDEBUG
-	bool "Full Symbolic/Source Debugging support"
-	help
-	  Enable debuging symbols on kernel build.
-
-config FRAME_POINTER
-	bool "Compile the kernel with frame pointers"
-	help
-	  If you say Y here the resulting kernel image will be slightly larger
-	  and slower, but it will give very useful debugging information.
-	  If you don't debug the kernel, you can say N, but we may not be able
-	  to solve problems without frame pointers.
-
-config MAGIC_SYSRQ
-	bool "Magic SysRq key"
-	help
-	  Enables console device to interpret special characters as
-	  commands to dump state information.
-
-config HIGHPROFILE
-	bool "Use fast second timer for profiling"
-	depends on COLDFIRE
-	help
-	  Use a fast secondary clock to produce profiling information.
-
-config BOOTPARAM
-	bool 'Compiled-in Kernel Boot Parameter'
-
-config BOOTPARAM_STRING 
-	string 'Kernel Boot Parameter'
-	default 'console=ttyS0,19200'
-	depends on BOOTPARAM
-
-config DUMPTOFLASH
-	bool "Panic/Dump to FLASH"
-	depends on COLDFIRE
-	help
-	  Dump any panic of trap output into a flash memory segment
-	  for later analysis.
-
-config NO_KERNEL_MSG
-	bool "Suppress Kernel BUG Messages"
-	help
-	  Do not output any debug BUG messages within the kernel.
-
-config BDM_DISABLE
-	bool "Disable BDM signals"
-	depends on (EXPERIMENTAL && COLDFIRE)
-	help
-	  Disable the ColdFire CPU's BDM signals.
-
-endmenu
+source "arch/m68knommu/Kconfig.debug"
 
 source "security/Kconfig"
 
 source "crypto/Kconfig"
 
 source "lib/Kconfig"
-
diff -Nru a/arch/m68knommu/Kconfig.debug b/arch/m68knommu/Kconfig.debug
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/arch/m68knommu/Kconfig.debug	2004-10-18 14:57:22 -07:00
@@ -0,0 +1,42 @@
+menu "Kernel hacking"
+
+source "lib/Kconfig.debug"
+
+config FULLDEBUG
+	bool "Full Symbolic/Source Debugging support"
+	help
+	  Enable debuging symbols on kernel build.
+
+config HIGHPROFILE
+	bool "Use fast second timer for profiling"
+	depends on COLDFIRE
+	help
+	  Use a fast secondary clock to produce profiling information.
+
+config BOOTPARAM
+	bool 'Compiled-in Kernel Boot Parameter'
+
+config BOOTPARAM_STRING
+	string 'Kernel Boot Parameter'
+	default 'console=ttyS0,19200'
+	depends on BOOTPARAM
+
+config DUMPTOFLASH
+	bool "Panic/Dump to FLASH"
+	depends on COLDFIRE
+	help
+	  Dump any panic of trap output into a flash memory segment
+	  for later analysis.
+
+config NO_KERNEL_MSG
+	bool "Suppress Kernel BUG Messages"
+	help
+	  Do not output any debug BUG messages within the kernel.
+
+config BDM_DISABLE
+	bool "Disable BDM signals"
+	depends on (EXPERIMENTAL && COLDFIRE)
+	help
+	  Disable the ColdFire CPU's BDM signals.
+
+endmenu
diff -Nru a/arch/m68knommu/kernel/Makefile b/arch/m68knommu/kernel/Makefile
--- a/arch/m68knommu/kernel/Makefile	2004-10-18 14:56:27 -07:00
+++ b/arch/m68knommu/kernel/Makefile	2004-10-18 14:56:27 -07:00
@@ -2,7 +2,7 @@
 # Makefile for arch/m68knommu/kernel.
 #
 
-extra-y := vmlinux.lds.s
+extra-y := vmlinux.lds
 
 obj-y += dma.o entry.o init_task.o m68k_ksyms.o process.o ptrace.o semaphore.o \
 	 setup.o signal.o syscalltable.o sys_m68k.o time.o traps.o
diff -Nru a/arch/m68knommu/kernel/asm-offsets.c b/arch/m68knommu/kernel/asm-offsets.c
--- a/arch/m68knommu/kernel/asm-offsets.c	2004-10-18 14:57:04 -07:00
+++ b/arch/m68knommu/kernel/asm-offsets.c	2004-10-18 14:57:04 -07:00
@@ -12,9 +12,9 @@
 #include <linux/sched.h>
 #include <linux/kernel_stat.h>
 #include <linux/ptrace.h>
+#include <linux/hardirq.h>
 #include <asm/bootinfo.h>
 #include <asm/irq.h>
-#include <asm/hardirq.h>
 
 #define DEFINE(sym, val) \
         asm volatile("\n->" #sym " %0 " #val : : "i" (val))
diff -Nru a/arch/m68knommu/kernel/comempci.c b/arch/m68knommu/kernel/comempci.c
--- a/arch/m68knommu/kernel/comempci.c	2004-10-18 14:56:32 -07:00
+++ b/arch/m68knommu/kernel/comempci.c	2004-10-18 14:56:32 -07:00
@@ -351,8 +351,6 @@
 }
 /*****************************************************************************/
 
-struct pci_fixup pcibios_fixups[] = { { 0 } };
-
 void pcibios_fixup_bus(struct pci_bus *b)
 {
 }
diff -Nru a/arch/m68knommu/kernel/m68k_ksyms.c b/arch/m68knommu/kernel/m68k_ksyms.c
--- a/arch/m68knommu/kernel/m68k_ksyms.c	2004-10-18 14:57:03 -07:00
+++ b/arch/m68knommu/kernel/m68k_ksyms.c	2004-10-18 14:57:03 -07:00
@@ -16,7 +16,6 @@
 #include <asm/io.h>
 #include <asm/semaphore.h>
 #include <asm/checksum.h>
-#include <asm/hardirq.h>
 #include <asm/current.h>
 
 extern void dump_thread(struct pt_regs *, struct user *);
@@ -50,16 +49,16 @@
    explicitly (the C compiler generates them).  Fortunately,
    their interface isn't gonna change any time soon now, so
    it's OK to leave it out of version control.  */
-EXPORT_SYMBOL_NOVERS(memcpy);
-EXPORT_SYMBOL_NOVERS(memset);
-EXPORT_SYMBOL_NOVERS(memcmp);
-EXPORT_SYMBOL_NOVERS(memscan);
-EXPORT_SYMBOL_NOVERS(memmove);
-
-EXPORT_SYMBOL_NOVERS(__down_failed);
-EXPORT_SYMBOL_NOVERS(__down_failed_interruptible);
-EXPORT_SYMBOL_NOVERS(__down_failed_trylock);
-EXPORT_SYMBOL_NOVERS(__up_wakeup);
+EXPORT_SYMBOL(memcpy);
+EXPORT_SYMBOL(memset);
+EXPORT_SYMBOL(memcmp);
+EXPORT_SYMBOL(memscan);
+EXPORT_SYMBOL(memmove);
+
+EXPORT_SYMBOL(__down_failed);
+EXPORT_SYMBOL(__down_failed_interruptible);
+EXPORT_SYMBOL(__down_failed_trylock);
+EXPORT_SYMBOL(__up_wakeup);
 
 EXPORT_SYMBOL(get_wchan);
 
@@ -79,27 +78,27 @@
 extern void __umodsi3(void);
 
         /* gcc lib functions */
-EXPORT_SYMBOL_NOVERS(__ashldi3);
-EXPORT_SYMBOL_NOVERS(__ashrdi3);
-EXPORT_SYMBOL_NOVERS(__divsi3);
-EXPORT_SYMBOL_NOVERS(__lshrdi3);
-EXPORT_SYMBOL_NOVERS(__modsi3);
-EXPORT_SYMBOL_NOVERS(__muldi3);
-EXPORT_SYMBOL_NOVERS(__mulsi3);
-EXPORT_SYMBOL_NOVERS(__udivsi3);
-EXPORT_SYMBOL_NOVERS(__umodsi3);
+EXPORT_SYMBOL(__ashldi3);
+EXPORT_SYMBOL(__ashrdi3);
+EXPORT_SYMBOL(__divsi3);
+EXPORT_SYMBOL(__lshrdi3);
+EXPORT_SYMBOL(__modsi3);
+EXPORT_SYMBOL(__muldi3);
+EXPORT_SYMBOL(__mulsi3);
+EXPORT_SYMBOL(__udivsi3);
+EXPORT_SYMBOL(__umodsi3);
 
-EXPORT_SYMBOL_NOVERS(is_in_rom);
+EXPORT_SYMBOL(is_in_rom);
 
 #ifdef CONFIG_COLDFIRE
 extern unsigned int *dma_device_address;
 extern unsigned long dma_base_addr, _ramend;
-EXPORT_SYMBOL_NOVERS(dma_base_addr);
-EXPORT_SYMBOL_NOVERS(dma_device_address);
-EXPORT_SYMBOL_NOVERS(_ramend);
+EXPORT_SYMBOL(dma_base_addr);
+EXPORT_SYMBOL(dma_device_address);
+EXPORT_SYMBOL(_ramend);
 
 extern asmlinkage void trap(void);
 extern void	*_ramvec;
-EXPORT_SYMBOL_NOVERS(trap);
-EXPORT_SYMBOL_NOVERS(_ramvec);
+EXPORT_SYMBOL(trap);
+EXPORT_SYMBOL(_ramvec);
 #endif /* CONFIG_COLDFIRE */
diff -Nru a/arch/m68knommu/kernel/process.c b/arch/m68knommu/kernel/process.c
--- a/arch/m68knommu/kernel/process.c	2004-10-18 14:56:18 -07:00
+++ b/arch/m68knommu/kernel/process.c	2004-10-18 14:56:18 -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/ptrace.c b/arch/m68knommu/kernel/ptrace.c
--- a/arch/m68knommu/kernel/ptrace.c	2004-10-18 14:56:32 -07:00
+++ b/arch/m68knommu/kernel/ptrace.c	2004-10-18 14:56:32 -07:00
@@ -133,13 +133,6 @@
 		ret = ptrace_attach(child);
 		goto out_tsk;
 	}
-	ret = -ESRCH;
-	if (!(child->ptrace & PT_PTRACED))
-		goto out_tsk;
-	if (child->state != TASK_STOPPED) {
-		if (request != PTRACE_KILL)
-			goto out_tsk;
-	}
 	ret = ptrace_check_attach(child, request == PTRACE_KILL);
 	if (ret < 0)
 		goto out_tsk;
@@ -376,10 +369,8 @@
 		return;
 	if (!(current->ptrace & PT_PTRACED))
 		return;
-	current->exit_code = SIGTRAP;
-	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
 	 * for normal use.  strace only continues with a signal if the
diff -Nru a/arch/m68knommu/kernel/signal.c b/arch/m68knommu/kernel/signal.c
--- a/arch/m68knommu/kernel/signal.c	2004-10-18 14:56:33 -07:00
+++ b/arch/m68knommu/kernel/signal.c	2004-10-18 14:56:33 -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-10-18 14:56:33 -07:00
+++ b/arch/m68knommu/kernel/time.c	2004-10-18 14:56:33 -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-10-18 14:56:29 -07:00
+++ b/arch/m68knommu/kernel/vmlinux.lds.S	2004-10-18 14:56:29 -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-10-18 14:57:05 -07:00
+++ b/arch/m68knommu/platform/5307/timers.c	2004-10-18 14:57:05 -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/Kconfig b/arch/mips/Kconfig
--- a/arch/mips/Kconfig	2004-10-18 14:56:29 -07:00
+++ b/arch/mips/Kconfig	2004-10-18 14:56:29 -07:00
@@ -381,7 +381,7 @@
 	  evaluation board.
 
 	  Features : kernel debugging, serial terminal, NFS root fs, on-board
-	  ether port USB, AC97, PCI, PCI VGA card & framebuffer console, 
+	  ether port USB, AC97, PCI, PCI VGA card & framebuffer console,
 	  IDE controller, PS2 keyboard, PS2 mouse, etc.
 
 config DDB5477
@@ -400,7 +400,7 @@
 	int "bus frequency (in kHZ, 0 for auto-detect)"
 	depends on DDB5477
 	default 0
-	
+
 config NEC_OSPREY
 	bool "Support for NEC Osprey board"
 	select DMA_NONCOHERENT
@@ -513,15 +513,15 @@
 
 endchoice
 
-choice  
+choice
         prompt "AMD/Alchemy Au1x00 board support"
         depends on SOC_AU1X00
 	help
 	  These are evaluation boards built by AMD/Alchemy to
 	  showcase their Au1X00 Internet Edge Processors. The SOC design
-	  is based on the MIPS32 architecture running at 266/400/500MHz 
-          with many integrated peripherals. Further information can be 
-          found at their website, <http://www.amd.com/>. Say Y here if you 
+	  is based on the MIPS32 architecture running at 266/400/500MHz
+          with many integrated peripherals. Further information can be
+          found at their website, <http://www.amd.com/>. Say Y here if you
           wish to build a kernel for this platform.
 
 config MIPS_PB1000
@@ -1091,7 +1091,6 @@
 
 endmenu
 
-
 menu "CPU selection"
 
 choice
@@ -1194,7 +1193,7 @@
 	 This option select the standard 4kB Linux page size.  On some
 	 R3000-family processors this is the only available page size.  Using
 	 4kB page size will minimize memory consumption and is therefore
-	 recommended for low memory systems. 
+	 recommended for low memory systems.
 
 config PAGE_SIZE_8KB
 	bool "8kB"
@@ -1382,21 +1381,6 @@
 	  This allows applications to run more reliably even when the system is
 	  under load.
 
-config DEBUG_SPINLOCK
-	bool "Spinlock debugging"
-	depends on DEBUG_KERNEL
-	help
-	  Say Y here and build SMP to catch missing spinlock initialization
-	  and certain other kinds of spinlock errors commonly made.  This is
-	  best used in conjunction with the NMI watchdog so that spinlock
-	  deadlocks are also debuggable.
-
-config DEBUG_SPINLOCK_SLEEP
-	bool "Sleep-inside-spinlock checking"
-	help
-	  If you say Y here, various routines which may sleep will become very
-	  noisy if they are called with a spinlock held.
-
 config RTC_DS1742
 	bool "DS1742 BRAM/RTC support"
 	depends on TOSHIBA_JMR3927 || TOSHIBA_RBTX4927
@@ -1562,7 +1546,7 @@
 	default "ramdisk.gz"
 	help
 	  This is the filename of the ramdisk image to be built into the
-	  kernel.  Relative pathnames are relative to arch/mips/ramdisk/.  
+	  kernel.  Relative pathnames are relative to arch/mips/ramdisk/.
 	  The ramdisk image is not part of the kernel distribution; you must
 	  provide one yourself.
 
@@ -1572,119 +1556,7 @@
 
 source "fs/Kconfig"
 
-menu "Kernel hacking"
-
-config CROSSCOMPILE
-	bool "Are you using a crosscompiler"
-	help
-	  Say Y here if you are compiling the kernel on a different
-	  architecture than the one it is intended to run on.
-
-config CMDLINE
-	string "Default kernel command string"
-	default ""
-	help
-          On some platforms, there is currently no way for the boot loader to
-          pass arguments to the kernel. For these platforms, you can supply
-          some command-line options at build time by entering them here.  In
-          other cases you can specify kernel args so that you don't have
-	  to set them up in board prom initialization routines.
-
-config DEBUG_KERNEL
-	bool "Kernel debugging"
-
-config DEBUG_STACK_USAGE
-	bool "Enable stack utilization instrumentation"
-	depends on DEBUG_KERNEL
-	help
-	  Enables the display of the minimum amount of free stack which each
-	  task has ever had available in the sysrq-T and sysrq-P debug output.
-
-	  This option will slow down process creation somewhat.
-
-config DEBUG_SLAB
-	bool "Debug memory allocations"
-	depends on DEBUG_KERNEL
-	help
-	  Say Y here to have the kernel do limited verification on memory
-	  allocation as well as poisoning memory on free to catch use of freed
-	  memory.
-
-config KGDB
-	bool "Remote GDB kernel debugging"
-	depends on DEBUG_KERNEL
-	select DEBUG_INFO
-	help
-	  If you say Y here, it will be possible to remotely debug the MIPS
-	  kernel using gdb. This enlarges your kernel image disk size by
-	  several megabytes and requires a machine with more than 16 MB,
-	  better 32 MB RAM to avoid excessive linking time. This is only
-	  useful for kernel hackers. If unsure, say N.
-
-config GDB_CONSOLE
-	bool "Console output to GDB"
-	depends on KGDB
-	help
-	  If you are using GDB for remote debugging over a serial port and
-	  would like kernel messages to be formatted into GDB $O packets so
-	  that GDB prints them as program output, say 'Y'.
-
-config DEBUG_INFO
-	bool "Compile the kernel with debug info"
-	depends on DEBUG_KERNEL
-	help
-	  If you say Y here the resulting kernel image will include
-	  debugging info resulting in a larger kernel image.
-	  Say Y here only if you plan to use gdb to debug the kernel.
-	  If you don't debug the kernel, you can say N.
-
-config SB1XXX_CORELIS
-	bool "Corelis Debugger"
-	depends on SIBYTE_SB1xxx_SOC
-	select DEBUG_INFO
-	help
-	  Select compile flags that produce code that can be processed by the
-	  Corelis mksym utility and UDB Emulator.
-
-config RUNTIME_DEBUG
-	bool "Enable run-time debugging"
-	depends on DEBUG_KERNEL
-	help
-	  If you say Y here, some debugging macros will do run-time checking.
-	  If you say N here, those macros will mostly turn to no-ops.  See 
-	  include/asm-mips/debug.h for debuging macros.
-	  If unsure, say N.
-
-
-config MAGIC_SYSRQ
-	bool "Magic SysRq key"
-	depends on DEBUG_KERNEL
-	help
-	  If you say Y here, you will have some control over the system even
-	  if the system crashes for example during kernel debugging (e.g., you
-	  will be able to flush the buffer cache to disk, reboot the system
-	  immediately or dump some status information). This is accomplished
-	  by pressing various keys while holding SysRq (Alt+PrintScreen). It
-	  also works on a serial console (on PC hardware at least), if you
-	  send a BREAK and then within 5 seconds a command keypress. The
-	  keys are documented in <file:Documentation/sysrq.txt>. Don't say Y
-	  unless you really know what this hack does.
-
-config MIPS_UNCACHED
-	bool "Run uncached"
-	depends on DEBUG_KERNEL && !SMP && !SGI_IP27
-	help
-	  If you say Y here there kernel will disable all CPU caches.  This will
-	  reduce the system's performance dramatically but can help finding
-	  otherwise hard to track bugs.  It can also useful if you're doing
-	  hardware debugging with a logic analyzer and need to see all traffic
-	  on the bus.
-
-config DEBUG_HIGHMEM
-	bool "Highmem debugging"
-	depends on DEBUG_KERNEL && HIGHMEM
-
-endmenu
+source "arch/mips/Kconfig.debug"
 
 source "security/Kconfig"
 
diff -Nru a/arch/mips/Kconfig.debug b/arch/mips/Kconfig.debug
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/arch/mips/Kconfig.debug	2004-10-18 14:57:23 -07:00
@@ -0,0 +1,76 @@
+menu "Kernel hacking"
+
+source "lib/Kconfig.debug"
+
+config CROSSCOMPILE
+	bool "Are you using a crosscompiler"
+	help
+	  Say Y here if you are compiling the kernel on a different
+	  architecture than the one it is intended to run on.
+
+config CMDLINE
+	string "Default kernel command string"
+	default ""
+	help
+          On some platforms, there is currently no way for the boot loader to
+          pass arguments to the kernel. For these platforms, you can supply
+          some command-line options at build time by entering them here.  In
+          other cases you can specify kernel args so that you don't have
+	  to set them up in board prom initialization routines.
+
+config DEBUG_STACK_USAGE
+	bool "Enable stack utilization instrumentation"
+	depends on DEBUG_KERNEL
+	help
+	  Enables the display of the minimum amount of free stack which each
+	  task has ever had available in the sysrq-T and sysrq-P debug output.
+
+	  This option will slow down process creation somewhat.
+
+config KGDB
+	bool "Remote GDB kernel debugging"
+	depends on DEBUG_KERNEL
+	select DEBUG_INFO
+	help
+	  If you say Y here, it will be possible to remotely debug the MIPS
+	  kernel using gdb. This enlarges your kernel image disk size by
+	  several megabytes and requires a machine with more than 16 MB,
+	  better 32 MB RAM to avoid excessive linking time. This is only
+	  useful for kernel hackers. If unsure, say N.
+
+config GDB_CONSOLE
+	bool "Console output to GDB"
+	depends on KGDB
+	help
+	  If you are using GDB for remote debugging over a serial port and
+	  would like kernel messages to be formatted into GDB $O packets so
+	  that GDB prints them as program output, say 'Y'.
+
+config SB1XXX_CORELIS
+	bool "Corelis Debugger"
+	depends on SIBYTE_SB1xxx_SOC
+	select DEBUG_INFO
+	help
+	  Select compile flags that produce code that can be processed by the
+	  Corelis mksym utility and UDB Emulator.
+
+config RUNTIME_DEBUG
+	bool "Enable run-time debugging"
+	depends on DEBUG_KERNEL
+	help
+	  If you say Y here, some debugging macros will do run-time checking.
+	  If you say N here, those macros will mostly turn to no-ops.  See
+	  include/asm-mips/debug.h for debuging macros.
+	  If unsure, say N.
+
+config MIPS_UNCACHED
+	bool "Run uncached"
+	depends on DEBUG_KERNEL && !SMP && !SGI_IP27
+	help
+	  If you say Y here there kernel will disable all CPU caches.  This will
+	  reduce the system's performance dramatically but can help finding
+	  otherwise hard to track bugs.  It can also useful if you're doing
+	  hardware debugging with a logic analyzer and need to see all traffic
+	  on the bus.
+
+endmenu
diff -Nru a/arch/mips/Makefile b/arch/mips/Makefile
--- a/arch/mips/Makefile	2004-10-18 14:55:54 -07:00
+++ b/arch/mips/Makefile	2004-10-18 14:55:54 -07:00
@@ -56,14 +56,12 @@
 #
 cflags-y			:= -I $(TOPDIR)/include/asm/gcc
 cflags-y			+= -G 0 -mno-abicalls -fno-pic -pipe
-cflags-y			+= $(call check_gcc, -finline-limit=100000,)
+cflags-y			+= $(call cc-option, -finline-limit=100000)
 LDFLAGS_vmlinux			+= -G 0 -static -n
 MODFLAGS			+= -mlong-calls
 
 cflags-$(CONFIG_SB1XXX_CORELIS)	+= -mno-sched-prolog -fno-omit-frame-pointer
 
-check_warning = $(shell if $(CC) $(1) -c -o /dev/null -xc /dev/null > /dev/null 2>&1; then echo "$(1)"; else echo "$(2)"; fi)
-
 #
 # Use: $(call set_gccflags,<cpu0>,<isa0>,<cpu1>,<isa1>,<isa2>)
 #
@@ -162,7 +160,7 @@
 cflags-$(CONFIG_CPU_NEVADA)	+= \
 			$(call set_gccflags,rm5200,mips4,r5000,mips4,mips2) \
 			-Wa,--trap
-#			$(call check_gcc,-mmad,)
+#			$(call cc-option,-mmad)
 
 cflags-$(CONFIG_CPU_RM7000)	+= \
 			$(call set_gccflags,rm7000,mips4,r5000,mips4,mips2) \
@@ -643,7 +641,7 @@
 # none has been choosen above.
 #
 
-AFLAGS_vmlinux.lds.o := \
+CPPFLAGS_vmlinux.lds := \
 	-D"LOADADDR=$(load-y)" \
 	-D"JIFFIES=$(JIFFIES)" \
 	-imacros $(srctree)/include/asm-$(ARCH)/sn/mapped_kernel.h
diff -Nru a/arch/mips/au1000/common/time.c b/arch/mips/au1000/common/time.c
--- a/arch/mips/au1000/common/time.c	2004-10-18 14:56:28 -07:00
+++ b/arch/mips/au1000/common/time.c	2004-10-18 14:56:28 -07:00
@@ -38,11 +38,11 @@
 #include <linux/kernel_stat.h>
 #include <linux/sched.h>
 #include <linux/spinlock.h>
+#include <linux/hardirq.h>
 
 #include <asm/mipsregs.h>
 #include <asm/ptrace.h>
 #include <asm/time.h>
-#include <asm/hardirq.h>
 #include <asm/div64.h>
 #include <asm/mach-au1x00/au1000.h>
 
diff -Nru a/arch/mips/baget/irq.c b/arch/mips/baget/irq.c
--- a/arch/mips/baget/irq.c	2004-10-18 14:56:48 -07:00
+++ b/arch/mips/baget/irq.c	2004-10-18 14:56:48 -07:00
@@ -180,7 +180,7 @@
 static void do_IRQ(int irq, struct pt_regs * regs)
 {
 	struct irqaction *action;
-	int do_random, cpu;
+	int ret, do_random, cpu;
 
 	cpu = smp_processor_id();
 	irq_enter();
@@ -194,8 +194,9 @@
 		action = *(irq + irq_action);
 		do_random = 0;
         	do {
-			do_random |= action->flags;
-			action->handler(irq, action->dev_id, regs);
+			ret = action->handler(irq, action->dev_id, regs);
+			if (ret == IRQ_HANDLED)
+				do_random |= action->flags;
 			action = action->next;
         	} while (action);
 		if (do_random & SA_SAMPLE_RANDOM)
diff -Nru a/arch/mips/configs/jaguar-atx_defconfig b/arch/mips/configs/jaguar-atx_defconfig
--- a/arch/mips/configs/jaguar-atx_defconfig	2004-10-18 14:57:03 -07:00
+++ b/arch/mips/configs/jaguar-atx_defconfig	2004-10-18 14:57:03 -07:00
@@ -306,10 +306,10 @@
 # CONFIG_R8169 is not set
 # CONFIG_SK98LIN is not set
 # CONFIG_TIGON3 is not set
-CONFIG_MV64340_ETH=y
-CONFIG_MV64340_ETH_0=y
-CONFIG_MV64340_ETH_1=y
-CONFIG_MV64340_ETH_2=y
+CONFIG_MV643XX_ETH=y
+CONFIG_MV643XX_ETH_0=y
+CONFIG_MV643XX_ETH_1=y
+CONFIG_MV643XX_ETH_2=y
 
 #
 # Ethernet (10000 Mbit)
diff -Nru a/arch/mips/configs/ocelot_c_defconfig b/arch/mips/configs/ocelot_c_defconfig
--- a/arch/mips/configs/ocelot_c_defconfig	2004-10-18 14:56:17 -07:00
+++ b/arch/mips/configs/ocelot_c_defconfig	2004-10-18 14:56:17 -07:00
@@ -303,7 +303,7 @@
 # CONFIG_R8169 is not set
 # CONFIG_SK98LIN is not set
 # CONFIG_TIGON3 is not set
-# CONFIG_MV64340_ETH is not set
+# CONFIG_MV643XX_ETH is not set
 
 #
 # Ethernet (10000 Mbit)
diff -Nru a/arch/mips/configs/tb0226_defconfig b/arch/mips/configs/tb0226_defconfig
--- a/arch/mips/configs/tb0226_defconfig	2004-10-18 14:56:33 -07:00
+++ b/arch/mips/configs/tb0226_defconfig	2004-10-18 14:56:33 -07:00
@@ -272,7 +272,6 @@
 CONFIG_IP_MULTIPLE_TABLES=y
 CONFIG_IP_ROUTE_NAT=y
 CONFIG_IP_ROUTE_MULTIPATH=y
-CONFIG_IP_ROUTE_TOS=y
 CONFIG_IP_ROUTE_VERBOSE=y
 CONFIG_IP_PNP=y
 # CONFIG_IP_PNP_DHCP is not set
diff -Nru a/arch/mips/configs/tb0229_defconfig b/arch/mips/configs/tb0229_defconfig
--- a/arch/mips/configs/tb0229_defconfig	2004-10-18 14:57:04 -07:00
+++ b/arch/mips/configs/tb0229_defconfig	2004-10-18 14:57:04 -07:00
@@ -229,7 +229,6 @@
 CONFIG_IP_MULTIPLE_TABLES=y
 CONFIG_IP_ROUTE_NAT=y
 CONFIG_IP_ROUTE_MULTIPATH=y
-CONFIG_IP_ROUTE_TOS=y
 CONFIG_IP_ROUTE_VERBOSE=y
 CONFIG_IP_PNP=y
 # CONFIG_IP_PNP_DHCP is not set
diff -Nru a/arch/mips/kernel/Makefile b/arch/mips/kernel/Makefile
--- a/arch/mips/kernel/Makefile	2004-10-18 14:56:29 -07:00
+++ b/arch/mips/kernel/Makefile	2004-10-18 14:56:29 -07:00
@@ -2,7 +2,7 @@
 # Makefile for the Linux/MIPS kernel.
 #
 
-extra-y		:= head.o init_task.o vmlinux.lds.s
+extra-y		:= head.o init_task.o vmlinux.lds
 
 obj-y		+= cpu-probe.o branch.o entry.o genex.o irq.o process.o \
 		   ptrace.o reset.o semaphore.o setup.o signal.o syscall.o \
diff -Nru a/arch/mips/kernel/irixsig.c b/arch/mips/kernel/irixsig.c
--- a/arch/mips/kernel/irixsig.c	2004-10-18 14:56:50 -07:00
+++ b/arch/mips/kernel/irixsig.c	2004-10-18 14:56:50 -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-10-18 14:55:55 -07:00
+++ b/arch/mips/kernel/irq.c	2004-10-18 14:55:55 -07:00
@@ -144,14 +144,16 @@
 int handle_IRQ_event(unsigned int irq, struct pt_regs * regs, struct irqaction * action)
 {
 	int status = 1;	/* Force the "do bottom halves" bit */
-	int retval = 0;
+	int ret, retval = 0;
 
 	if (!(action->flags & SA_INTERRUPT))
 		local_irq_enable();
 
 	do {
-		status |= action->flags;
-		retval |= action->handler(irq, action->dev_id, regs);
+		ret = action->handler(irq, action->dev_id, regs);
+		if (ret == IRQ_HANDLED)
+			status |= action->flags;
+		retval |= ret;
 		action = action->next;
 	} while (action);
 	if (status & SA_SAMPLE_RANDOM)
@@ -872,30 +874,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 +909,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/mips_ksyms.c b/arch/mips/kernel/mips_ksyms.c
--- a/arch/mips/kernel/mips_ksyms.c	2004-10-18 14:56:17 -07:00
+++ b/arch/mips/kernel/mips_ksyms.c	2004-10-18 14:56:17 -07:00
@@ -26,36 +26,36 @@
 /*
  * String functions
  */
-EXPORT_SYMBOL_NOVERS(memchr);
-EXPORT_SYMBOL_NOVERS(memcmp);
-EXPORT_SYMBOL_NOVERS(memset);
-EXPORT_SYMBOL_NOVERS(memcpy);
-EXPORT_SYMBOL_NOVERS(memmove);
-EXPORT_SYMBOL_NOVERS(strcat);
-EXPORT_SYMBOL_NOVERS(strchr);
+EXPORT_SYMBOL(memchr);
+EXPORT_SYMBOL(memcmp);
+EXPORT_SYMBOL(memset);
+EXPORT_SYMBOL(memcpy);
+EXPORT_SYMBOL(memmove);
+EXPORT_SYMBOL(strcat);
+EXPORT_SYMBOL(strchr);
 #ifdef CONFIG_MIPS64
-EXPORT_SYMBOL_NOVERS(strncmp);
+EXPORT_SYMBOL(strncmp);
 #endif
-EXPORT_SYMBOL_NOVERS(strlen);
-EXPORT_SYMBOL_NOVERS(strpbrk);
-EXPORT_SYMBOL_NOVERS(strncat);
-EXPORT_SYMBOL_NOVERS(strnlen);
-EXPORT_SYMBOL_NOVERS(strrchr);
-EXPORT_SYMBOL_NOVERS(strstr);
+EXPORT_SYMBOL(strlen);
+EXPORT_SYMBOL(strpbrk);
+EXPORT_SYMBOL(strncat);
+EXPORT_SYMBOL(strnlen);
+EXPORT_SYMBOL(strrchr);
+EXPORT_SYMBOL(strstr);
 
 EXPORT_SYMBOL(kernel_thread);
 
 /*
  * Userspace access stuff.
  */
-EXPORT_SYMBOL_NOVERS(__copy_user);
-EXPORT_SYMBOL_NOVERS(__bzero);
-EXPORT_SYMBOL_NOVERS(__strncpy_from_user_nocheck_asm);
-EXPORT_SYMBOL_NOVERS(__strncpy_from_user_asm);
-EXPORT_SYMBOL_NOVERS(__strlen_user_nocheck_asm);
-EXPORT_SYMBOL_NOVERS(__strlen_user_asm);
-EXPORT_SYMBOL_NOVERS(__strnlen_user_nocheck_asm);
-EXPORT_SYMBOL_NOVERS(__strnlen_user_asm);
+EXPORT_SYMBOL(__copy_user);
+EXPORT_SYMBOL(__bzero);
+EXPORT_SYMBOL(__strncpy_from_user_nocheck_asm);
+EXPORT_SYMBOL(__strncpy_from_user_asm);
+EXPORT_SYMBOL(__strlen_user_nocheck_asm);
+EXPORT_SYMBOL(__strlen_user_asm);
+EXPORT_SYMBOL(__strnlen_user_nocheck_asm);
+EXPORT_SYMBOL(__strnlen_user_asm);
 
 EXPORT_SYMBOL(csum_partial);
 
diff -Nru a/arch/mips/kernel/signal.c b/arch/mips/kernel/signal.c
--- a/arch/mips/kernel/signal.c	2004-10-18 14:56:49 -07:00
+++ b/arch/mips/kernel/signal.c	2004-10-18 14:56:49 -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,19 +473,15 @@
 	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,
 	struct pt_regs *regs, int signr, sigset_t *set, siginfo_t *info);
 
 static inline void handle_signal(unsigned long sig, siginfo_t *info,
-	sigset_t *oldset, struct pt_regs *regs)
+	struct k_sigaction *ka, sigset_t *oldset, struct pt_regs *regs)
 {
-	struct k_sigaction *ka = &current->sighand->action[sig-1];
-
 	switch(regs->regs[0]) {
 	case ERESTART_RESTARTBLOCK:
 	case ERESTARTNOHAND:
@@ -539,6 +533,7 @@
 
 asmlinkage int do_signal(sigset_t *oldset, struct pt_regs *regs)
 {
+	struct k_sigaction ka;
 	siginfo_t info;
 	int signr;
 
@@ -564,9 +559,9 @@
 	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) {
-		handle_signal(signr, &info, oldset, regs);
+		handle_signal(signr, &info, &ka, oldset, regs);
 		return 1;
 	}
 
diff -Nru a/arch/mips/kernel/signal32.c b/arch/mips/kernel/signal32.c
--- a/arch/mips/kernel/signal32.c	2004-10-18 14:56:32 -07:00
+++ b/arch/mips/kernel/signal32.c	2004-10-18 14:56:32 -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-10-18 14:56:33 -07:00
+++ b/arch/mips/kernel/signal_n32.c	2004-10-18 14:56:33 -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-10-18 14:56:16 -07:00
+++ b/arch/mips/kernel/smp.c	2004-10-18 14:56:16 -07:00
@@ -35,7 +35,6 @@
 #include <asm/cpu.h>
 #include <asm/processor.h>
 #include <asm/system.h>
-#include <asm/hardirq.h>
 #include <asm/mmu_context.h>
 #include <asm/smp.h>
 
@@ -254,16 +253,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 +264,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-10-18 14:56:49 -07:00
+++ b/arch/mips/kernel/syscall.c	2004-10-18 14:56:49 -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/sysirix.c b/arch/mips/kernel/sysirix.c
--- a/arch/mips/kernel/sysirix.c	2004-10-18 14:57:03 -07:00
+++ b/arch/mips/kernel/sysirix.c	2004-10-18 14:57:03 -07:00
@@ -810,8 +810,8 @@
 			return err;
 		err |= __put_user(current->utime, &tbuf->tms_utime);
 		err |= __put_user(current->stime, &tbuf->tms_stime);
-		err |= __put_user(current->cutime, &tbuf->tms_cutime);
-		err |= __put_user(current->cstime, &tbuf->tms_cstime);
+		err |= __put_user(current->signal->cutime, &tbuf->tms_cutime);
+		err |= __put_user(current->signal->cstime, &tbuf->tms_cstime);
 	}
 
 	return err;
diff -Nru a/arch/mips/kernel/time.c b/arch/mips/kernel/time.c
--- a/arch/mips/kernel/time.c	2004-10-18 14:56:29 -07:00
+++ b/arch/mips/kernel/time.c	2004-10-18 14:56:29 -07:00
@@ -29,7 +29,6 @@
 #include <asm/cpu.h>
 #include <asm/cpu-features.h>
 #include <asm/div64.h>
-#include <asm/hardirq.h>
 #include <asm/sections.h>
 #include <asm/time.h>
 
@@ -417,23 +416,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-10-18 14:56:28 -07:00
+++ b/arch/mips/kernel/vmlinux.lds.S	2004-10-18 14:56:28 -07:00
@@ -29,6 +29,7 @@
   .text : {
     *(.text)
     SCHED_TEXT
+    LOCK_TEXT
     *(.fixup)
     *(.gnu.warning)
   } =0
@@ -96,9 +97,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/mips-boards/generic/time.c b/arch/mips/mips-boards/generic/time.c
--- a/arch/mips/mips-boards/generic/time.c	2004-10-18 14:56:33 -07:00
+++ b/arch/mips/mips-boards/generic/time.c	2004-10-18 14:56:33 -07:00
@@ -31,7 +31,6 @@
 
 #include <asm/mipsregs.h>
 #include <asm/ptrace.h>
-#include <asm/hardirq.h>
 #include <asm/div64.h>
 #include <asm/cpu.h>
 #include <asm/time.h>
diff -Nru a/arch/mips/mm/fault.c b/arch/mips/mm/fault.c
--- a/arch/mips/mm/fault.c	2004-10-18 14:56:27 -07:00
+++ b/arch/mips/mm/fault.c	2004-10-18 14:56:27 -07:00
@@ -21,7 +21,6 @@
 #include <linux/module.h>
 
 #include <asm/branch.h>
-#include <asm/hardirq.h>
 #include <asm/mmu_context.h>
 #include <asm/system.h>
 #include <asm/uaccess.h>
diff -Nru a/arch/mips/momentum/jaguar_atx/prom.c b/arch/mips/momentum/jaguar_atx/prom.c
--- a/arch/mips/momentum/jaguar_atx/prom.c	2004-10-18 14:57:19 -07:00
+++ b/arch/mips/momentum/jaguar_atx/prom.c	2004-10-18 14:57:19 -07:00
@@ -40,7 +40,7 @@
 	return "Momentum Jaguar-ATX";
 }
 
-#ifdef CONFIG_MV64340_ETH
+#ifdef CONFIG_MV643XX_ETH
 extern unsigned char prom_mac_addr_base[6];
 
 static void burn_clocks(void)
@@ -230,7 +230,7 @@
 	mips_machgroup = MACH_GROUP_MOMENCO;
 	mips_machtype = MACH_MOMENCO_JAGUAR_ATX;
 
-#ifdef CONFIG_MV64340_ETH
+#ifdef CONFIG_MV643XX_ETH
 	/* get the base MAC address for on-board ethernet ports */
 	get_mac(prom_mac_addr_base);
 #endif
diff -Nru a/arch/mips/momentum/ocelot_c/prom.c b/arch/mips/momentum/ocelot_c/prom.c
--- a/arch/mips/momentum/ocelot_c/prom.c	2004-10-18 14:56:32 -07:00
+++ b/arch/mips/momentum/ocelot_c/prom.c	2004-10-18 14:56:32 -07:00
@@ -32,7 +32,7 @@
 extern unsigned long marvell_base;
 extern unsigned long cpu_clock;
 
-#ifdef CONFIG_MV64340_ETH
+#ifdef CONFIG_MV643XX_ETH
 extern unsigned char prom_mac_addr_base[6];
 #endif
 
@@ -45,7 +45,7 @@
 #endif
 }
 
-#ifdef CONFIG_MV64340_ETH
+#ifdef CONFIG_MV643XX_ETH
 static void burn_clocks(void)
 {
 	int i;
@@ -227,7 +227,7 @@
 	mips_machgroup = MACH_GROUP_MOMENCO;
 	mips_machtype = MACH_MOMENCO_OCELOT_C;
 
-#ifdef CONFIG_MV64340_ETH
+#ifdef CONFIG_MV643XX_ETH
 	/* get the base MAC address for on-board ethernet ports */
 	get_mac(prom_mac_addr_base);
 #endif
diff -Nru a/arch/mips/pci/fixup-atlas.c b/arch/mips/pci/fixup-atlas.c
--- a/arch/mips/pci/fixup-atlas.c	2004-10-18 14:55:53 -07:00
+++ b/arch/mips/pci/fixup-atlas.c	2004-10-18 14:55:53 -07:00
@@ -60,13 +60,7 @@
 	printk ("saa9730_base = %x\n", saa9730_base);
 }
 
-#endif
-
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_PHILIPS, PCI_DEVICE_ID_PHILIPS_SAA9730,
+	atlas_saa9730_base_fixup);
 
-struct pci_fixup pcibios_fixups[] __initdata = {
-#ifdef CONFIG_KGDB
-	{PCI_FIXUP_HEADER, PCI_VENDOR_ID_PHILIPS, PCI_DEVICE_ID_PHILIPS_SAA9730,
-	 atlas_saa9730_base_fixup},
 #endif
-	{ 0 }
-};
diff -Nru a/arch/mips/pci/fixup-au1000.c b/arch/mips/pci/fixup-au1000.c
--- a/arch/mips/pci/fixup-au1000.c	2004-10-18 14:55:54 -07:00
+++ b/arch/mips/pci/fixup-au1000.c	2004-10-18 14:55:54 -07:00
@@ -102,7 +102,3 @@
 {
 return irq_tab_alchemy[slot][pin];
 }
-
-struct pci_fixup pcibios_fixups[] __initdata = {
-{ 0 }
-};
diff -Nru a/arch/mips/pci/fixup-capcella.c b/arch/mips/pci/fixup-capcella.c
--- a/arch/mips/pci/fixup-capcella.c	2004-10-18 14:56:28 -07:00
+++ b/arch/mips/pci/fixup-capcella.c	2004-10-18 14:56:28 -07:00
@@ -42,7 +42,3 @@
 {
 	return irq_tab_capcella[slot][pin];
 }
-
-struct pci_fixup pcibios_fixups[] __initdata = {
-	{	.pass = 0,	},
-};
diff -Nru a/arch/mips/pci/fixup-cobalt.c b/arch/mips/pci/fixup-cobalt.c
--- a/arch/mips/pci/fixup-cobalt.c	2004-10-18 14:56:29 -07:00
+++ b/arch/mips/pci/fixup-cobalt.c	2004-10-18 14:56:29 -07:00
@@ -41,6 +41,9 @@
 	pci_write_config_byte(dev, PCI_CACHE_LINE_SIZE, 7);
 }
 
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C586_1,
+	 qube_raq_via_bmIDE_fixup);
+
 static void qube_raq_galileo_fixup(struct pci_dev *dev)
 {
 	unsigned short galileo_id;
@@ -73,13 +76,8 @@
 	}
 }
 
-struct pci_fixup pcibios_fixups[] __initdata = {
-	{PCI_FIXUP_HEADER, PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C586_1,
-	 qube_raq_via_bmIDE_fixup},
-	{PCI_FIXUP_HEADER, PCI_VENDOR_ID_GALILEO, PCI_ANY_ID,
-	 qube_raq_galileo_fixup},
-	0
-};
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_GALILEO, PCI_ANY_ID,
+	qube_raq_galileo_fixup);
 
 static char irq_tab_cobalt[] __initdata = {
   [COBALT_PCICONF_CPU]     = 0,
diff -Nru a/arch/mips/pci/fixup-ddb5074.c b/arch/mips/pci/fixup-ddb5074.c
--- a/arch/mips/pci/fixup-ddb5074.c	2004-10-18 14:56:13 -07:00
+++ b/arch/mips/pci/fixup-ddb5074.c	2004-10-18 14:56:13 -07:00
@@ -17,8 +17,5 @@
 	pci_write_config_byte(dev, 0x7e, t8);
 }
 
-struct pci_fixup pcibios_fixups[] __initdata = {
-	{ PCI_FIXUP_FINAL, PCI_VENDOR_ID_AL, PCI_DEVICE_ID_AL_M7101,
-	  ddb5074_fixup },
-	{0}
-};
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_AL, PCI_DEVICE_ID_AL_M7101,
+	ddb5074_fixup);
diff -Nru a/arch/mips/pci/fixup-ddb5477.c b/arch/mips/pci/fixup-ddb5477.c
--- a/arch/mips/pci/fixup-ddb5477.c	2004-10-18 14:56:32 -07:00
+++ b/arch/mips/pci/fixup-ddb5477.c	2004-10-18 14:56:32 -07:00
@@ -41,6 +41,11 @@
 	pci_write_config_byte(dev, 0x41, old | 0xd0);
 }
 
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_AL, PCI_DEVICE_ID_AL_M1533,
+	  ddb5477_fixup);
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_AL, PCI_DEVICE_ID_AL_M1535,
+	  ddb5477_fixup);
+
 /*
  * Fixup baseboard AMD chip so that tx does not underflow.
  *      bcr_18 |= 0x0800
@@ -69,12 +74,5 @@
 	outw(temp, ioaddr + PCNET32_WIO_BDP);
 }
 
-struct pci_fixup pcibios_fixups[] __initdata = {
-	{ PCI_FIXUP_FINAL, PCI_VENDOR_ID_AL, PCI_DEVICE_ID_AL_M1533,
-	  ddb5477_fixup },
-	{ PCI_FIXUP_FINAL, PCI_VENDOR_ID_AL, PCI_DEVICE_ID_AL_M1535,
-	  ddb5477_fixup },
-	{ PCI_FIXUP_FINAL, PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_LANCE,
-	  ddb5477_amd_lance_fixup },
-	{0}
-};
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_LANCE,
+          ddb5477_amd_lance_fixup);
diff -Nru a/arch/mips/pci/fixup-ip32.c b/arch/mips/pci/fixup-ip32.c
--- a/arch/mips/pci/fixup-ip32.c	2004-10-18 14:57:03 -07:00
+++ b/arch/mips/pci/fixup-ip32.c	2004-10-18 14:57:03 -07:00
@@ -44,7 +44,3 @@
 {
 	return irq_tab_mace[slot][pin];
 }
-
-struct pci_fixup pcibios_fixups[] = {
-	{0}
-};
diff -Nru a/arch/mips/pci/fixup-jaguar.c b/arch/mips/pci/fixup-jaguar.c
--- a/arch/mips/pci/fixup-jaguar.c	2004-10-18 14:57:18 -07:00
+++ b/arch/mips/pci/fixup-jaguar.c	2004-10-18 14:57:18 -07:00
@@ -36,7 +36,3 @@
 return 0;
 	panic("Whooops in pcibios_map_irq");
 }
-
-struct pci_fixup pcibios_fixups[] = {
-	{0}
-};
diff -Nru a/arch/mips/pci/fixup-lasat.c b/arch/mips/pci/fixup-lasat.c
--- a/arch/mips/pci/fixup-lasat.c	2004-10-18 14:56:32 -07:00
+++ b/arch/mips/pci/fixup-lasat.c	2004-10-18 14:56:32 -07:00
@@ -4,7 +4,3 @@
 void __init pcibios_fixup_irqs(void)
 {
 }
-
-struct pci_fixup pcibios_fixups[] __initdata = {
-    { 0 }
-};
diff -Nru a/arch/mips/pci/fixup-malta.c b/arch/mips/pci/fixup-malta.c
--- a/arch/mips/pci/fixup-malta.c	2004-10-18 14:55:54 -07:00
+++ b/arch/mips/pci/fixup-malta.c	2004-10-18 14:55:54 -07:00
@@ -79,6 +79,8 @@
 	}
 }
 
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371AB_0,
+	 malta_piix_func0_fixup);
 
 static void __init malta_piix_func1_fixup(struct pci_dev *pdev)
 {
@@ -96,10 +98,5 @@
 	}
 }
 
-struct pci_fixup pcibios_fixups[] __initdata = {
-	{PCI_FIXUP_HEADER, PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371AB_0,
-	 malta_piix_func0_fixup},
-	{PCI_FIXUP_HEADER, PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371AB,
-	 malta_piix_func1_fixup},
-	{ 0 }
-};
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371AB,
+	malta_piix_func1_fixup);
diff -Nru a/arch/mips/pci/fixup-mpc30x.c b/arch/mips/pci/fixup-mpc30x.c
--- a/arch/mips/pci/fixup-mpc30x.c	2004-10-18 14:56:32 -07:00
+++ b/arch/mips/pci/fixup-mpc30x.c	2004-10-18 14:56:32 -07:00
@@ -42,7 +42,3 @@
 
 	return irq_tab_mpc30x[slot];
 }
-
-struct pci_fixup pcibios_fixups[] __initdata = {
-	{	.pass = 0,	},
-};
diff -Nru a/arch/mips/pci/fixup-ocelot-c.c b/arch/mips/pci/fixup-ocelot-c.c
--- a/arch/mips/pci/fixup-ocelot-c.c	2004-10-18 14:57:19 -07:00
+++ b/arch/mips/pci/fixup-ocelot-c.c	2004-10-18 14:57:19 -07:00
@@ -33,7 +33,3 @@
 return 0;
 	panic("Whooops in pcibios_map_irq");
 }
-
-struct pci_fixup pcibios_fixups[] = {
-	{0}
-};
diff -Nru a/arch/mips/pci/fixup-ocelot-g.c b/arch/mips/pci/fixup-ocelot-g.c
--- a/arch/mips/pci/fixup-ocelot-g.c	2004-10-18 14:56:29 -07:00
+++ b/arch/mips/pci/fixup-ocelot-g.c	2004-10-18 14:56:29 -07:00
@@ -29,7 +29,3 @@
 
 	return -1;
 }
-
-struct pci_fixup pcibios_fixups[] = {
-	{0}
-};
diff -Nru a/arch/mips/pci/fixup-sni.c b/arch/mips/pci/fixup-sni.c
--- a/arch/mips/pci/fixup-sni.c	2004-10-18 14:56:27 -07:00
+++ b/arch/mips/pci/fixup-sni.c	2004-10-18 14:56:27 -07:00
@@ -82,7 +82,3 @@
 
 	return irq_tab_rm200[slot][pin];
 }
-
-struct pci_fixup pcibios_fixups[] = {
-	{0}
-};
diff -Nru a/arch/mips/pci/fixup-tb0219.c b/arch/mips/pci/fixup-tb0219.c
--- a/arch/mips/pci/fixup-tb0219.c	2004-10-18 14:57:03 -07:00
+++ b/arch/mips/pci/fixup-tb0219.c	2004-10-18 14:57:03 -07:00
@@ -58,7 +58,3 @@
 
 	return irq;
 }
-
-struct pci_fixup pcibios_fixups[] __initdata = {
-	{	.pass = 0,	},
-};
diff -Nru a/arch/mips/pci/fixup-tb0226.c b/arch/mips/pci/fixup-tb0226.c
--- a/arch/mips/pci/fixup-tb0226.c	2004-10-18 14:56:49 -07:00
+++ b/arch/mips/pci/fixup-tb0226.c	2004-10-18 14:56:49 -07:00
@@ -77,7 +77,3 @@
 
 	return irq;
 }
-
-struct pci_fixup pcibios_fixups[] __initdata = {
-	{	.pass = 0,	},
-};
diff -Nru a/arch/mips/pci/fixup-yosemite.c b/arch/mips/pci/fixup-yosemite.c
--- a/arch/mips/pci/fixup-yosemite.c	2004-10-18 14:56:29 -07:00
+++ b/arch/mips/pci/fixup-yosemite.c	2004-10-18 14:56:29 -07:00
@@ -33,7 +33,3 @@
 
 	return 3;			/* Everything goes to one irq bit */
 }
-
-struct pci_fixup pcibios_fixups[] = {
-	{0}
-};
diff -Nru a/arch/mips/pci/pci-ip27.c b/arch/mips/pci/pci-ip27.c
--- a/arch/mips/pci/pci-ip27.c	2004-10-18 14:57:04 -07:00
+++ b/arch/mips/pci/pci-ip27.c	2004-10-18 14:57:04 -07:00
@@ -329,6 +329,9 @@
 	pci_disable_swapping(d);
 }
 
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_SGI, PCI_DEVICE_ID_SGI_IOC3,
+	 pci_fixup_ioc3);
+
 static void __init pci_fixup_isp1020(struct pci_dev *d)
 {
 	struct bridge_controller *bc = BRIDGE_CONTROLLER(d->bus);
@@ -353,6 +356,9 @@
 	pci_enable_swapping(d);
 }
 
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_QLOGIC, PCI_DEVICE_ID_QLOGIC_ISP1020,
+	 pci_fixup_isp1020);
+
 static void __init pci_fixup_isp2x00(struct pci_dev *d)
 {
 	struct bridge_controller *bc = BRIDGE_CONTROLLER(d->bus);
@@ -427,14 +433,7 @@
 	/*d->resource[1].flags |= 1; */
 }
 
-struct pci_fixup pcibios_fixups[] = {
-	{PCI_FIXUP_HEADER, PCI_VENDOR_ID_SGI, PCI_DEVICE_ID_SGI_IOC3,
-	 pci_fixup_ioc3},
-	{PCI_FIXUP_HEADER, PCI_VENDOR_ID_QLOGIC, PCI_DEVICE_ID_QLOGIC_ISP1020,
-	 pci_fixup_isp1020},
-	{PCI_FIXUP_HEADER, PCI_VENDOR_ID_QLOGIC, PCI_DEVICE_ID_QLOGIC_ISP2100,
-	 pci_fixup_isp2x00},
-	{PCI_FIXUP_HEADER, PCI_VENDOR_ID_QLOGIC, PCI_DEVICE_ID_QLOGIC_ISP2200,
-	 pci_fixup_isp2x00},
-	{0}
-};
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_QLOGIC, PCI_DEVICE_ID_QLOGIC_ISP2100,
+	 pci_fixup_isp2x00);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_QLOGIC, PCI_DEVICE_ID_QLOGIC_ISP2200,
+	 pci_fixup_isp2x00);
diff -Nru a/arch/mips/pci/pci-sb1250.c b/arch/mips/pci/pci-sb1250.c
--- a/arch/mips/pci/pci-sb1250.c	2004-10-18 14:56:17 -07:00
+++ b/arch/mips/pci/pci-sb1250.c	2004-10-18 14:56:17 -07:00
@@ -279,7 +279,3 @@
 	return 0;
 }
 arch_initcall(sb1250_pcibios_init);
-
-struct pci_fixup pcibios_fixups[] = {
-	{0}
-};
diff -Nru a/arch/mips/pmc-sierra/yosemite/ht.c b/arch/mips/pmc-sierra/yosemite/ht.c
--- a/arch/mips/pmc-sierra/yosemite/ht.c	2004-10-18 14:56:28 -07:00
+++ b/arch/mips/pmc-sierra/yosemite/ht.c	2004-10-18 14:56:28 -07:00
@@ -414,11 +414,6 @@
         titan_ht_config_write_dword
 };
 
-
-struct pci_fixup pcibios_fixups[] = {
-        {0}
-};
-
 void __init pcibios_fixup_bus(struct pci_bus *c)
 {
         titan_ht_pcibios_fixup_bus(c);
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-10-18 14:56:27 -07:00
+++ b/arch/mips/sgi-ip27/ip27-memory.c	2004-10-18 14:56:27 -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/mips/vr41xx/common/giu.c b/arch/mips/vr41xx/common/giu.c
--- a/arch/mips/vr41xx/common/giu.c	2004-10-18 14:55:54 -07:00
+++ b/arch/mips/vr41xx/common/giu.c	2004-10-18 14:55:54 -07:00
@@ -63,6 +63,12 @@
 
 static uint32_t giu_base;
 
+static struct irqaction giu_cascade = {
+	.handler	= no_action,
+	.mask		= CPU_MASK_NONE,
+	.name		= "cascade",
+};
+
 #define read_giuint(offset)		readw(giu_base + (offset))
 #define write_giuint(val, offset)	writew((val), giu_base + (offset))
 
@@ -303,7 +309,6 @@
 };
 
 static struct vr41xx_giuint_cascade giuint_cascade[GIUINT_NR_IRQS];
-static struct irqaction giu_cascade = {no_action, 0, CPU_MASK_NONE, "cascade", NULL, NULL};
 
 static int no_irq_number(int irq)
 {
diff -Nru a/arch/mips/vr41xx/common/icu.c b/arch/mips/vr41xx/common/icu.c
--- a/arch/mips/vr41xx/common/icu.c	2004-10-18 14:55:54 -07:00
+++ b/arch/mips/vr41xx/common/icu.c	2004-10-18 14:55:54 -07:00
@@ -51,6 +51,12 @@
 static uint32_t icu1_base;
 static uint32_t icu2_base;
 
+static struct irqaction icu_cascade = {
+	.handler	= no_action,
+	.mask		= CPU_MASK_NONE,
+	.name		= "cascade",
+};
+
 static unsigned char sysint1_assign[16] = {
 	0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
 static unsigned char sysint2_assign[16] = {
@@ -159,218 +165,268 @@
 {
 	irq_desc_t *desc = irq_desc + PIU_IRQ;
 	unsigned long flags;
-	uint16_t val;
 
-	spin_lock_irqsave(&desc->lock, flags);
-	val = read_icu1(MPIUINTREG);
-	val |= mask;
-	write_icu1(val, MPIUINTREG);
-	spin_unlock_irqrestore(&desc->lock, flags);
+	if (current_cpu_data.cputype == CPU_VR4111 ||
+	    current_cpu_data.cputype == CPU_VR4121) {
+		spin_lock_irqsave(&desc->lock, flags);
+		set_icu1(MPIUINTREG, mask);
+		spin_unlock_irqrestore(&desc->lock, flags);
+	}
 }
 
+EXPORT_SYMBOL(vr41xx_enable_piuint);
+
 void vr41xx_disable_piuint(uint16_t mask)
 {
 	irq_desc_t *desc = irq_desc + PIU_IRQ;
 	unsigned long flags;
-	uint16_t val;
 
-	spin_lock_irqsave(&desc->lock, flags);
-	val = read_icu1(MPIUINTREG);
-	val &= ~mask;
-	write_icu1(val, MPIUINTREG);
-	spin_unlock_irqrestore(&desc->lock, flags);
+	if (current_cpu_data.cputype == CPU_VR4111 ||
+	    current_cpu_data.cputype == CPU_VR4121) {
+		spin_lock_irqsave(&desc->lock, flags);
+		clear_icu1(MPIUINTREG, mask);
+		spin_unlock_irqrestore(&desc->lock, flags);
+	}
 }
 
+EXPORT_SYMBOL(vr41xx_disable_piuint);
+
 void vr41xx_enable_aiuint(uint16_t mask)
 {
 	irq_desc_t *desc = irq_desc + AIU_IRQ;
 	unsigned long flags;
-	uint16_t val;
 
-	spin_lock_irqsave(&desc->lock, flags);
-	val = read_icu1(MAIUINTREG);
-	val |= mask;
-	write_icu1(val, MAIUINTREG);
-	spin_unlock_irqrestore(&desc->lock, flags);
+	if (current_cpu_data.cputype == CPU_VR4111 ||
+	    current_cpu_data.cputype == CPU_VR4121) {
+		spin_lock_irqsave(&desc->lock, flags);
+		set_icu1(MAIUINTREG, mask);
+		spin_unlock_irqrestore(&desc->lock, flags);
+	}
 }
 
+EXPORT_SYMBOL(vr41xx_enable_aiuint);
+
 void vr41xx_disable_aiuint(uint16_t mask)
 {
 	irq_desc_t *desc = irq_desc + AIU_IRQ;
 	unsigned long flags;
-	uint16_t val;
 
-	spin_lock_irqsave(&desc->lock, flags);
-	val = read_icu1(MAIUINTREG);
-	val &= ~mask;
-	write_icu1(val, MAIUINTREG);
-	spin_unlock_irqrestore(&desc->lock, flags);
+	if (current_cpu_data.cputype == CPU_VR4111 ||
+	    current_cpu_data.cputype == CPU_VR4121) {
+		spin_lock_irqsave(&desc->lock, flags);
+		clear_icu1(MAIUINTREG, mask);
+		spin_unlock_irqrestore(&desc->lock, flags);
+	}
 }
 
+EXPORT_SYMBOL(vr41xx_disable_aiuint);
+
 void vr41xx_enable_kiuint(uint16_t mask)
 {
 	irq_desc_t *desc = irq_desc + KIU_IRQ;
 	unsigned long flags;
-	uint16_t val;
 
-	spin_lock_irqsave(&desc->lock, flags);
-	val = read_icu1(MKIUINTREG);
-	val |= mask;
-	write_icu1(val, MKIUINTREG);
-	spin_unlock_irqrestore(&desc->lock, flags);
+	if (current_cpu_data.cputype == CPU_VR4111 ||
+	    current_cpu_data.cputype == CPU_VR4121) {
+		spin_lock_irqsave(&desc->lock, flags);
+		set_icu1(MKIUINTREG, mask);
+		spin_unlock_irqrestore(&desc->lock, flags);
+	}
 }
 
+EXPORT_SYMBOL(vr41xx_enable_kiuint);
+
 void vr41xx_disable_kiuint(uint16_t mask)
 {
 	irq_desc_t *desc = irq_desc + KIU_IRQ;
 	unsigned long flags;
-	uint16_t val;
 
-	spin_lock_irqsave(&desc->lock, flags);
-	val = read_icu1(MKIUINTREG);
-	val &= ~mask;
-	write_icu1(val, MKIUINTREG);
-	spin_unlock_irqrestore(&desc->lock, flags);
+	if (current_cpu_data.cputype == CPU_VR4111 ||
+	    current_cpu_data.cputype == CPU_VR4121) {
+		spin_lock_irqsave(&desc->lock, flags);
+		clear_icu1(MKIUINTREG, mask);
+		spin_unlock_irqrestore(&desc->lock, flags);
+	}
 }
 
+EXPORT_SYMBOL(vr41xx_disable_kiuint);
+
 void vr41xx_enable_dsiuint(uint16_t mask)
 {
 	irq_desc_t *desc = irq_desc + DSIU_IRQ;
 	unsigned long flags;
-	uint16_t val;
 
 	spin_lock_irqsave(&desc->lock, flags);
-	val = read_icu1(MDSIUINTREG);
-	val |= mask;
-	write_icu1(val, MDSIUINTREG);
+	set_icu1(MDSIUINTREG, mask);
 	spin_unlock_irqrestore(&desc->lock, flags);
 }
 
+EXPORT_SYMBOL(vr41xx_enable_dsiuint);
+
 void vr41xx_disable_dsiuint(uint16_t mask)
 {
 	irq_desc_t *desc = irq_desc + DSIU_IRQ;
 	unsigned long flags;
-	uint16_t val;
 
 	spin_lock_irqsave(&desc->lock, flags);
-	val = read_icu1(MDSIUINTREG);
-	val &= ~mask;
-	write_icu1(val, MDSIUINTREG);
+	clear_icu1(MDSIUINTREG, mask);
 	spin_unlock_irqrestore(&desc->lock, flags);
 }
 
+EXPORT_SYMBOL(vr41xx_disable_dsiuint);
+
 void vr41xx_enable_firint(uint16_t mask)
 {
 	irq_desc_t *desc = irq_desc + FIR_IRQ;
 	unsigned long flags;
-	uint16_t val;
 
 	spin_lock_irqsave(&desc->lock, flags);
-	val = read_icu2(MFIRINTREG);
-	val |= mask;
-	write_icu2(val, MFIRINTREG);
+	set_icu2(MFIRINTREG, mask);
 	spin_unlock_irqrestore(&desc->lock, flags);
 }
 
+EXPORT_SYMBOL(vr41xx_enable_firint);
+
 void vr41xx_disable_firint(uint16_t mask)
 {
 	irq_desc_t *desc = irq_desc + FIR_IRQ;
 	unsigned long flags;
-	uint16_t val;
 
 	spin_lock_irqsave(&desc->lock, flags);
-	val = read_icu2(MFIRINTREG);
-	val &= ~mask;
-	write_icu2(val, MFIRINTREG);
+	clear_icu2(MFIRINTREG, mask);
 	spin_unlock_irqrestore(&desc->lock, flags);
 }
 
+EXPORT_SYMBOL(vr41xx_disable_firint);
+
 void vr41xx_enable_pciint(void)
 {
 	irq_desc_t *desc = irq_desc + PCI_IRQ;
 	unsigned long flags;
 
-	spin_lock_irqsave(&desc->lock, flags);
-	write_icu2(PCIINT0, MPCIINTREG);
-	spin_unlock_irqrestore(&desc->lock, flags);
+	if (current_cpu_data.cputype == CPU_VR4122 ||
+	    current_cpu_data.cputype == CPU_VR4131 ||
+	    current_cpu_data.cputype == CPU_VR4133) {
+		spin_lock_irqsave(&desc->lock, flags);
+		write_icu2(PCIINT0, MPCIINTREG);
+		spin_unlock_irqrestore(&desc->lock, flags);
+	}
 }
 
+EXPORT_SYMBOL(vr41xx_enable_pciint);
+
 void vr41xx_disable_pciint(void)
 {
 	irq_desc_t *desc = irq_desc + PCI_IRQ;
 	unsigned long flags;
 
-	spin_lock_irqsave(&desc->lock, flags);
-	write_icu2(0, MPCIINTREG);
-	spin_unlock_irqrestore(&desc->lock, flags);
+	if (current_cpu_data.cputype == CPU_VR4122 ||
+	    current_cpu_data.cputype == CPU_VR4131 ||
+	    current_cpu_data.cputype == CPU_VR4133) {
+		spin_lock_irqsave(&desc->lock, flags);
+		write_icu2(0, MPCIINTREG);
+		spin_unlock_irqrestore(&desc->lock, flags);
+	}
 }
 
+EXPORT_SYMBOL(vr41xx_disable_pciint);
+
 void vr41xx_enable_scuint(void)
 {
 	irq_desc_t *desc = irq_desc + SCU_IRQ;
 	unsigned long flags;
 
-	spin_lock_irqsave(&desc->lock, flags);
-	write_icu2(SCUINT0, MSCUINTREG);
-	spin_unlock_irqrestore(&desc->lock, flags);
+	if (current_cpu_data.cputype == CPU_VR4122 ||
+	    current_cpu_data.cputype == CPU_VR4131 ||
+	    current_cpu_data.cputype == CPU_VR4133) {
+		spin_lock_irqsave(&desc->lock, flags);
+		write_icu2(SCUINT0, MSCUINTREG);
+		spin_unlock_irqrestore(&desc->lock, flags);
+	}
 }
 
+EXPORT_SYMBOL(vr41xx_enable_scuint);
+
 void vr41xx_disable_scuint(void)
 {
 	irq_desc_t *desc = irq_desc + SCU_IRQ;
 	unsigned long flags;
 
-	spin_lock_irqsave(&desc->lock, flags);
-	write_icu2(0, MSCUINTREG);
-	spin_unlock_irqrestore(&desc->lock, flags);
+	if (current_cpu_data.cputype == CPU_VR4122 ||
+	    current_cpu_data.cputype == CPU_VR4131 ||
+	    current_cpu_data.cputype == CPU_VR4133) {
+		spin_lock_irqsave(&desc->lock, flags);
+		write_icu2(0, MSCUINTREG);
+		spin_unlock_irqrestore(&desc->lock, flags);
+	}
 }
 
+EXPORT_SYMBOL(vr41xx_disable_scuint);
+
 void vr41xx_enable_csiint(uint16_t mask)
 {
 	irq_desc_t *desc = irq_desc + CSI_IRQ;
 	unsigned long flags;
-	uint16_t val;
 
-	spin_lock_irqsave(&desc->lock, flags);
-	val = read_icu2(MCSIINTREG);
-	val |= mask;
-	write_icu2(val, MCSIINTREG);
-	spin_unlock_irqrestore(&desc->lock, flags);
+	if (current_cpu_data.cputype == CPU_VR4122 ||
+	    current_cpu_data.cputype == CPU_VR4131 ||
+	    current_cpu_data.cputype == CPU_VR4133) {
+		spin_lock_irqsave(&desc->lock, flags);
+		set_icu2(MCSIINTREG, mask);
+		spin_unlock_irqrestore(&desc->lock, flags);
+	}
 }
 
+EXPORT_SYMBOL(vr41xx_enable_csiint);
+
 void vr41xx_disable_csiint(uint16_t mask)
 {
 	irq_desc_t *desc = irq_desc + CSI_IRQ;
 	unsigned long flags;
-	uint16_t val;
 
-	spin_lock_irqsave(&desc->lock, flags);
-	val = read_icu2(MCSIINTREG);
-	val &= ~mask;
-	write_icu2(val, MCSIINTREG);
-	spin_unlock_irqrestore(&desc->lock, flags);
+	if (current_cpu_data.cputype == CPU_VR4122 ||
+	    current_cpu_data.cputype == CPU_VR4131 ||
+	    current_cpu_data.cputype == CPU_VR4133) {
+		spin_lock_irqsave(&desc->lock, flags);
+		clear_icu2(MCSIINTREG, mask);
+		spin_unlock_irqrestore(&desc->lock, flags);
+	}
 }
 
+EXPORT_SYMBOL(vr41xx_disable_csiint);
+
 void vr41xx_enable_bcuint(void)
 {
 	irq_desc_t *desc = irq_desc + BCU_IRQ;
 	unsigned long flags;
 
-	spin_lock_irqsave(&desc->lock, flags);
-	write_icu2(BCUINTR, MBCUINTREG);
-	spin_unlock_irqrestore(&desc->lock, flags);
+	if (current_cpu_data.cputype == CPU_VR4122 ||
+	    current_cpu_data.cputype == CPU_VR4131 ||
+	    current_cpu_data.cputype == CPU_VR4133) {
+		spin_lock_irqsave(&desc->lock, flags);
+		write_icu2(BCUINTR, MBCUINTREG);
+		spin_unlock_irqrestore(&desc->lock, flags);
+	}
 }
 
+EXPORT_SYMBOL(vr41xx_enable_bcuint);
+
 void vr41xx_disable_bcuint(void)
 {
 	irq_desc_t *desc = irq_desc + BCU_IRQ;
 	unsigned long flags;
 
-	spin_lock_irqsave(&desc->lock, flags);
-	write_icu2(0, MBCUINTREG);
-	spin_unlock_irqrestore(&desc->lock, flags);
+	if (current_cpu_data.cputype == CPU_VR4122 ||
+	    current_cpu_data.cputype == CPU_VR4131 ||
+	    current_cpu_data.cputype == CPU_VR4133) {
+		spin_lock_irqsave(&desc->lock, flags);
+		write_icu2(0, MBCUINTREG);
+		spin_unlock_irqrestore(&desc->lock, flags);
+	}
 }
 
+EXPORT_SYMBOL(vr41xx_disable_bcuint);
+
 /*=======================================================================*/
 
 static unsigned int startup_sysint1_irq(unsigned int irq)
@@ -673,8 +729,6 @@
 early_initcall(vr41xx_icu_init);
 
 /*=======================================================================*/
-
-static struct irqaction icu_cascade = {no_action, 0, 0, "cascade", NULL, NULL};
 
 static inline void init_vr41xx_icu_irq(void)
 {
diff -Nru a/arch/mips/vr41xx/common/serial.c b/arch/mips/vr41xx/common/serial.c
--- a/arch/mips/vr41xx/common/serial.c	2004-10-18 14:56:28 -07:00
+++ b/arch/mips/vr41xx/common/serial.c	2004-10-18 14:56:28 -07:00
@@ -115,7 +115,7 @@
 	port.line = vr41xx_serial_ports;
 	port.uartclk = SIU_BASE_BAUD * 16;
 	port.irq = SIU_IRQ;
-	port.flags = UPF_RESOURCES | UPF_BOOT_AUTOCONF | UPF_SKIP_TEST;
+	port.flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST;
 	switch (current_cpu_data.cputype) {
 	case CPU_VR4111:
 	case CPU_VR4121:
@@ -160,7 +160,7 @@
 	port.line = vr41xx_serial_ports;
 	port.uartclk = DSIU_BASE_BAUD * 16;
 	port.irq = DSIU_IRQ;
-	port.flags = UPF_RESOURCES | UPF_BOOT_AUTOCONF | UPF_SKIP_TEST;
+	port.flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST;
 	port.mapbase = DSIU_BASE;
 	port.regshift = 0;
 	port.iotype = UPIO_MEM;
diff -Nru a/arch/mips/vr41xx/common/vrc4173.c b/arch/mips/vr41xx/common/vrc4173.c
--- a/arch/mips/vr41xx/common/vrc4173.c	2004-10-18 14:56:48 -07:00
+++ b/arch/mips/vr41xx/common/vrc4173.c	2004-10-18 14:56:48 -07:00
@@ -316,6 +316,96 @@
 	spin_lock_init(&vrc4173_giu_lock);
 }
 
+void vrc4173_enable_piuint(uint16_t mask)
+{
+	irq_desc_t *desc = irq_desc + VRC4173_PIU_IRQ;
+	unsigned long flags;
+	uint16_t val;
+
+	spin_lock_irqsave(&desc->lock, flags);
+	val = vrc4173_inw(VRC4173_MPIUINTREG);
+	val |= mask;
+	vrc4173_outw(val, VRC4173_MPIUINTREG);
+	spin_unlock_irqrestore(&desc->lock, flags);
+}
+
+EXPORT_SYMBOL(vrc4173_eanble_piuint);
+
+void vrc4173_disable_piuint(uint16_t mask)
+{
+	irq_desc_t *desc = irq_desc + VRC4173_PIU_IRQ;
+	unsigned long flags;
+	uint16_t val;
+
+	spin_lock_irqsave(&desc->lock, flags);
+	val = vrc4173_inw(VRC4173_MPIUINTREG);
+	val &= ~mask;
+	vrc4173_outw(val, VRC4173_MPIUINTREG);
+	spin_unlock_irqrestore(&desc->lock, flags);
+}
+
+EXPORT_SYMBOL(vrc4173_disable_piuint);
+
+void vrc4173_enable_aiuint(uint16_t mask)
+{
+	irq_desc_t *desc = irq_desc + VRC4173_AIU_IRQ;
+	unsigned long flags;
+	uint16_t val;
+
+	spin_lock_irqsave(&desc->lock, flags);
+	val = vrc4173_inw(VRC4173_MAIUINTREG);
+	val |= mask;
+	vrc4173_outw(val, VRC4173_MAIUINTREG);
+	spin_unlock_irqrestore(&desc->lock, flags);
+}
+
+EXPORT_SYMBOL(vrc4173_enable_aiuint);
+
+void vrc4173_disable_aiuint(uint16_t mask)
+{
+	irq_desc_t *desc = irq_desc + VRC4173_AIU_IRQ;
+	unsigned long flags;
+	uint16_t val;
+
+	spin_lock_irqsave(&desc->lock, flags);
+	val = vrc4173_inw(VRC4173_MAIUINTREG);
+	val &= ~mask;
+	vrc4173_outw(val, VRC4173_MAIUINTREG);
+	spin_unlock_irqrestore(&desc->lock, flags);
+}
+
+EXPORT_SYMBOL(vrc4173_disable_aiuint);
+
+void vrc4173_enable_kiuint(uint16_t mask)
+{
+	irq_desc_t *desc = irq_desc + VRC4173_KIU_IRQ;
+	unsigned long flags;
+	uint16_t val;
+
+	spin_lock_irqsave(&desc->lock, flags);
+	val = vrc4173_inw(VRC4173_MKIUINTREG);
+	val |= mask;
+	vrc4173_outw(val, VRC4173_MKIUINTREG);
+	spin_unlock_irqrestore(&desc->lock, flags);
+}
+
+EXPORT_SYMBOL(vrc4173_enable_kiuint);
+
+void vrc4173_disable_kiuint(uint16_t mask)
+{
+	irq_desc_t *desc = irq_desc + VRC4173_KIU_IRQ;
+	unsigned long flags;
+	uint16_t val;
+
+	spin_lock_irqsave(&desc->lock, flags);
+	val = vrc4173_inw(VRC4173_MKIUINTREG);
+	val &= ~mask;
+	vrc4173_outw(val, VRC4173_MKIUINTREG);
+	spin_unlock_irqrestore(&desc->lock, flags);
+}
+
+EXPORT_SYMBOL(vrc4173_disable_kiuint);
+
 static void enable_vrc4173_irq(unsigned int irq)
 {
 	uint16_t val;
diff -Nru a/arch/parisc/Kconfig b/arch/parisc/Kconfig
--- a/arch/parisc/Kconfig	2004-10-18 14:56:33 -07:00
+++ b/arch/parisc/Kconfig	2004-10-18 14:56:33 -07:00
@@ -106,7 +106,7 @@
 	depends on PA8X00
 	help
 	  Enable this if you want to support 64bit kernel on PA-RISC platform.
-	  
+
 	  At the moment, only people willing to use more than 2GB of RAM,
 	  or having a 64bit-only capable PA-RISC machine should say Y here.
 
@@ -188,76 +188,10 @@
 
 source "arch/parisc/oprofile/Kconfig"
 
-menu "Kernel hacking"
-
-config DEBUG_KERNEL
-	bool "Kernel debugging"
-	help
-	  Say Y here if you are developing drivers or trying to debug and
-	  identify kernel problems.
-
-config DEBUG_SLAB
-	bool "Debug memory allocations"
-	depends on DEBUG_KERNEL
-	help
-	  Say Y here to have the kernel do limited verification on memory
-	  allocation as well as poisoning memory on free to catch use of freed
-	  memory.
-
-config MAGIC_SYSRQ
-	bool "Magic SysRq key"
-	depends on DEBUG_KERNEL
-	help
-	  If you say Y here, you will have some control over the system even
-	  if the system crashes for example during kernel debugging (e.g., you
-	  will be able to flush the buffer cache to disk, reboot the system
-	  immediately or dump some status information). This is accomplished
-	  by pressing various keys while holding SysRq (Alt+PrintScreen). It
-	  also works on a serial console (on PC hardware at least), if you
-	  send a BREAK and then within 5 seconds a command keypress. The
-	  keys are documented in <file:Documentation/sysrq.txt>. Don't say Y
-	  unless you really know what this hack does.
-
-config DEBUG_SPINLOCK
-        bool "Spinlock debugging"
-        depends on DEBUG_KERNEL
-        help
-          Say Y here and build SMP to catch missing spinlock initialization
-          and certain other kinds of spinlock errors commonly made.  This is
-          best used in conjunction with the NMI watchdog so that spinlock
-          deadlocks are also debuggable.
-
-config DEBUG_RWLOCK
-        bool "Read-write spinlock debugging"
-        depends on DEBUG_KERNEL && SMP
-        help
-          If you say Y here then read-write lock processing will count how many
-          times it has tried to get the lock and issue an error message after
-          too many attempts.  If you suspect a rwlock problem or a kernel
-          hacker asks for this option then say Y.  Otherwise say N.
-
-config FRAME_POINTER
-	bool "Compile the kernel with frame pointers"
-	help
-	  If you say Y here the resulting kernel image will be slightly larger
-	  and slower, but it will give very useful debugging information.
-	  If you don't debug the kernel, you can say N, but we may not be able
-	  to solve problems without frame pointers.
-
-config DEBUG_INFO
-	bool "Compile the kernel with debug info"
-	depends on DEBUG_KERNEL
-	help
-          If you say Y here the resulting kernel image will include
-	  debugging info resulting in a larger kernel image.
-	  Say Y here only if you plan to use gdb to debug the kernel.
-	  If you don't debug the kernel, you can say N.
-	  
-endmenu
+source "arch/parisc/Kconfig.debug"
 
 source "security/Kconfig"
 
 source "crypto/Kconfig"
 
 source "lib/Kconfig"
-
diff -Nru a/arch/parisc/Kconfig.debug b/arch/parisc/Kconfig.debug
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/arch/parisc/Kconfig.debug	2004-10-18 14:57:23 -07:00
@@ -0,0 +1,14 @@
+menu "Kernel hacking"
+
+source "lib/Kconfig.debug"
+
+config DEBUG_RWLOCK
+        bool "Read-write spinlock debugging"
+        depends on DEBUG_KERNEL && SMP
+        help
+          If you say Y here then read-write lock processing will count how many
+          times it has tried to get the lock and issue an error message after
+          too many attempts.  If you suspect a rwlock problem or a kernel
+          hacker asks for this option then say Y.  Otherwise say N.
+
+endmenu
diff -Nru a/arch/parisc/kernel/Makefile b/arch/parisc/kernel/Makefile
--- a/arch/parisc/kernel/Makefile	2004-10-18 14:56:28 -07:00
+++ b/arch/parisc/kernel/Makefile	2004-10-18 14:56:28 -07:00
@@ -4,7 +4,7 @@
 
 head-y			:= head.o
 head-$(CONFIG_PARISC64)	:= head64.o
-extra-y			:= init_task.o $(head-y) vmlinux.lds.s
+extra-y			:= init_task.o $(head-y) vmlinux.lds
 
 AFLAGS_entry.o	:= -traditional
 AFLAGS_pacache.o := -traditional
diff -Nru a/arch/parisc/kernel/asm-offsets.c b/arch/parisc/kernel/asm-offsets.c
--- a/arch/parisc/kernel/asm-offsets.c	2004-10-18 14:55:55 -07:00
+++ b/arch/parisc/kernel/asm-offsets.c	2004-10-18 14:55:55 -07:00
@@ -32,11 +32,11 @@
 #include <linux/thread_info.h>
 #include <linux/version.h>
 #include <linux/ptrace.h>
-#include <asm/pgtable.h>
+#include <linux/hardirq.h>
 
+#include <asm/pgtable.h>
 #include <asm/ptrace.h>
 #include <asm/processor.h>
-#include <asm/hardirq.h>
 #include <asm/pdc.h>
 
 #define DEFINE(sym, val) \
diff -Nru a/arch/parisc/kernel/cache.c b/arch/parisc/kernel/cache.c
--- a/arch/parisc/kernel/cache.c	2004-10-18 14:56:29 -07:00
+++ b/arch/parisc/kernel/cache.c	2004-10-18 14:56:29 -07:00
@@ -245,7 +245,7 @@
 void flush_dcache_page(struct page *page)
 {
 	struct address_space *mapping = page_mapping(page);
-	struct vm_area_struct *mpnt = NULL;
+	struct vm_area_struct *mpnt;
 	struct prio_tree_iter iter;
 	unsigned long offset;
 	unsigned long addr;
@@ -272,8 +272,7 @@
 	 * to flush one address here for them all to become coherent */
 
 	flush_dcache_mmap_lock(mapping);
-	while ((mpnt = vma_prio_tree_next(mpnt, &mapping->i_mmap,
-					&iter, pgoff, pgoff)) != NULL) {
+	vma_prio_tree_foreach(mpnt, &iter, &mapping->i_mmap, pgoff, pgoff) {
 		offset = (pgoff - mpnt->vm_pgoff) << PAGE_SHIFT;
 		addr = mpnt->vm_start + offset;
 
diff -Nru a/arch/parisc/kernel/hardware.c b/arch/parisc/kernel/hardware.c
--- a/arch/parisc/kernel/hardware.c	2004-10-18 14:56:29 -07:00
+++ b/arch/parisc/kernel/hardware.c	2004-10-18 14:56:29 -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/pci.c b/arch/parisc/kernel/pci.c
--- a/arch/parisc/kernel/pci.c	2004-10-18 14:55:53 -07:00
+++ b/arch/parisc/kernel/pci.c	2004-10-18 14:55:53 -07:00
@@ -146,15 +146,6 @@
 	return str;
 }
 
-/* Used in drivers/pci/quirks.c */
-struct pci_fixup pcibios_fixups[] = { 
-#ifdef CONFIG_SUPERIO
-	{ PCI_FIXUP_HEADER,	PCI_VENDOR_ID_NS,	PCI_DEVICE_ID_NS_87415,	superio_fixup_pci },
-#endif
-	{ 0 }
-};
-
-
 /*
  * Called by pci_set_master() - a driver interface.
  *
diff -Nru a/arch/parisc/kernel/process.c b/arch/parisc/kernel/process.c
--- a/arch/parisc/kernel/process.c	2004-10-18 14:57:04 -07:00
+++ b/arch/parisc/kernel/process.c	2004-10-18 14:57:04 -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/ptrace.c b/arch/parisc/kernel/ptrace.c
--- a/arch/parisc/kernel/ptrace.c	2004-10-18 14:55:55 -07:00
+++ b/arch/parisc/kernel/ptrace.c	2004-10-18 14:55:55 -07:00
@@ -404,11 +404,8 @@
 		return;
 	if (!(current->ptrace & PT_PTRACED))
 		return;
-	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
 	 * for normal use.  strace only continues with a signal if the
diff -Nru a/arch/parisc/kernel/smp.c b/arch/parisc/kernel/smp.c
--- a/arch/parisc/kernel/smp.c	2004-10-18 14:57:04 -07:00
+++ b/arch/parisc/kernel/smp.c	2004-10-18 14:57:04 -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-10-18 14:57:19 -07:00
+++ b/arch/parisc/kernel/time.c	2004-10-18 14:57:19 -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-10-18 14:56:17 -07:00
+++ b/arch/parisc/kernel/vmlinux.lds.S	2004-10-18 14:56:17 -07:00
@@ -52,6 +52,7 @@
   .text ALIGN(16) : {
 	*(.text)
 	SCHED_TEXT
+	LOCK_TEXT
 	*(.text.do_softirq)
 	*(.text.sys_exit)
 	*(.text.do_sigaltstack)
@@ -130,9 +131,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/lib/debuglocks.c b/arch/parisc/lib/debuglocks.c
--- a/arch/parisc/lib/debuglocks.c	2004-10-18 14:56:33 -07:00
+++ b/arch/parisc/lib/debuglocks.c	2004-10-18 14:56:33 -07:00
@@ -25,8 +25,8 @@
 #include <linux/kernel.h>
 #include <linux/sched.h>
 #include <linux/spinlock.h>
+#include <linux/hardirq.h>	/* in_interrupt() */
 #include <asm/system.h>
-#include <asm/hardirq.h>	/* in_interrupt() */
 
 #undef INIT_STUCK
 #define INIT_STUCK 1L << 30
diff -Nru a/arch/parisc/mm/init.c b/arch/parisc/mm/init.c
--- a/arch/parisc/mm/init.c	2004-10-18 14:56:31 -07:00
+++ b/arch/parisc/mm/init.c	2004-10-18 14:56:31 -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/8260_io/fcc_enet.c b/arch/ppc/8260_io/fcc_enet.c
--- a/arch/ppc/8260_io/fcc_enet.c	2004-10-18 14:56:29 -07:00
+++ b/arch/ppc/8260_io/fcc_enet.c	2004-10-18 14:56:29 -07:00
@@ -1986,9 +1986,9 @@
 	fccp = fcp->fccp;
 
 	if (duplex)
-		fccp->fcc_fpsmr |= FCC_PSMR_FDE;
+		fccp->fcc_fpsmr |= FCC_PSMR_FDE | FCC_PSMR_LPB;
 	else
-		fccp->fcc_fpsmr &= ~FCC_PSMR_FDE;
+		fccp->fcc_fpsmr &= ~(FCC_PSMR_FDE | FCC_PSMR_LPB);
 
 	/* Enable transmit/receive */
 	fccp->fcc_gfmr |= FCC_GFMR_ENR | FCC_GFMR_ENT;
diff -Nru a/arch/ppc/8xx_io/uart.c b/arch/ppc/8xx_io/uart.c
--- a/arch/ppc/8xx_io/uart.c	2004-10-18 14:56:49 -07:00
+++ b/arch/ppc/8xx_io/uart.c	2004-10-18 14:56:49 -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-10-18 14:57:04 -07:00
+++ b/arch/ppc/Kconfig	2004-10-18 14:57:04 -07:00
@@ -49,7 +49,7 @@
 	  There are four types of PowerPC chips supported.  The more common
 	  types (601, 603, 604, 740, 750, 7400), the Motorola embedded
 	  versions (821, 823, 850, 855, 860, 52xx, 8260), the IBM embedded
-	  versions (403 and 405) and the high end 64 bit Power processors 
+	  versions (403 and 405) and the high end 64 bit Power processors
 	  (POWER 3, POWER4, and IBM 970 also known as G5)
 	  Unless you are building a kernel for one of the embedded processor
 	  systems, 64 bit IBM RS/6000 or an Apple G5, choose 6xx.
@@ -626,7 +626,7 @@
 	bool
 	depends on 8xx || 8260
 	default y
-	
+
 config PPC_MPC52xx
 	bool
 
@@ -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"
@@ -1043,13 +1041,13 @@
 	bool
 	depends on PCI && 8260 && !8272
 	default y
-	
+
 config 8260_PCI9
 	bool "  Enable workaround for MPC826x erratum PCI 9"
 	depends on PCI_8260
 	default y
 
-choice 
+choice
 	prompt "  IDMA channel for PCI 9 workaround"
 	depends on 8260_PCI9
 
@@ -1228,128 +1226,7 @@
 
 source "arch/ppc/oprofile/Kconfig"
 
-menu "Kernel hacking"
-
-config DEBUG_KERNEL
-	bool "Kernel debugging"
-
-config DEBUG_SLAB
-	bool "Debug memory allocations"
-	depends on DEBUG_KERNEL
-
-config MAGIC_SYSRQ
-	bool "Magic SysRq key"
-	depends on DEBUG_KERNEL
-	help
-	  If you say Y here, you will have some control over the system even
-	  if the system crashes for example during kernel debugging (e.g., you
-	  will be able to flush the buffer cache to disk, reboot the system
-	  immediately or dump some status information). This is accomplished
-	  by pressing various keys while holding SysRq (Alt+PrintScreen). It
-	  also works on a serial console (on PC hardware at least), if you
-	  send a BREAK and then within 5 seconds a command keypress. The
-	  keys are documented in <file:Documentation/sysrq.txt>. Don't say Y
-	  unless you really know what this hack does.
-
-config DEBUG_SPINLOCK
-	bool "Spinlock debugging"
-	depends on DEBUG_KERNEL
-	help
-	  Say Y here and to CONFIG_SMP to include code to check for missing
-	  spinlock initialization and some other common spinlock errors.
-
-config DEBUG_HIGHMEM
-	bool "Highmem debugging"
-	depends on DEBUG_KERNEL && HIGHMEM
-	help
-	  This options enables additional error checking for high memory
-	  systems.  Disable for production systems.
-
-config DEBUG_SPINLOCK_SLEEP
-	bool "Sleep-inside-spinlock checking"
-	depends on DEBUG_KERNEL
-	help
-	  If you say Y here, various routines which may sleep will become very
-	  noisy if they are called with a spinlock held.
-
-config KGDB
-	bool "Include kgdb kernel debugger"
-	depends on DEBUG_KERNEL && (BROKEN || PPC_GEN550 || 4xx)
-	select DEBUG_INFO
-	help
-	  Include in-kernel hooks for kgdb, the Linux kernel source level
-	  debugger.  See <http://kgdb.sourceforge.net/> for more information.
-	  Unless you are intending to debug the kernel, say N here.
-
-choice
-	prompt "Serial Port"
-	depends on KGDB
-	default KGDB_TTYS1
-
-config KGDB_TTYS0
-	bool "ttyS0"
-
-config KGDB_TTYS1
-	bool "ttyS1"
-
-config KGDB_TTYS2
-	bool "ttyS2"
-
-config KGDB_TTYS3
-	bool "ttyS3"
-
-endchoice
-
-config KGDB_CONSOLE
-	bool "Enable serial console thru kgdb port"
-	depends on KGDB && 8xx || CPM2
-	help
-	  If you enable this, all serial console messages will be sent
-	  over the gdb stub.
-	  If unsure, say N.
-
-config XMON
-	bool "Include xmon kernel debugger"
-	depends on DEBUG_KERNEL
-	help
-	  Include in-kernel hooks for the xmon kernel monitor/debugger.
-	  Unless you are intending to debug the kernel, say N here.
-
-config BDI_SWITCH
-	bool "Include BDI-2000 user context switcher"
-	depends on DEBUG_KERNEL
-	help
-	  Include in-kernel support for the Abatron BDI2000 debugger.
-	  Unless you are intending to debug the kernel with one of these
-	  machines, say N here.
-
-config DEBUG_INFO
-	bool "Compile the kernel with debug info"
-	depends on DEBUG_KERNEL
-	help
-          If you say Y here the resulting kernel image will include
-	  debugging info resulting in a larger kernel image.
-	  Say Y here only if you plan to use some sort of debugger to
-	  debug the kernel.
-	  If you don't debug the kernel, you can say N.
-
-config BOOTX_TEXT
-	bool "Support for early boot text console (BootX or OpenFirmware only)"
-	depends PPC_OF
-	help
-	  Say Y here to see progress messages from the boot firmware in text
-	  mode. Requires either BootX or Open Firmware.
-
-config SERIAL_TEXT_DEBUG
-	bool "Support for early boot texts over serial port"
-	depends on 4xx || GT64260 || LOPEC || PPLUS || PRPMC800 || PPC_GEN550 || PPC_MPC52xx
-
-config PPC_OCP
-	bool
-	depends on IBM_OCP || FSL_OCP
-	default y
-
-endmenu
+source "arch/ppc/Kconfig.debug"
 
 source "security/Kconfig"
 
diff -Nru a/arch/ppc/Kconfig.debug b/arch/ppc/Kconfig.debug
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/arch/ppc/Kconfig.debug	2004-10-18 14:57:24 -07:00
@@ -0,0 +1,84 @@
+menu "Kernel hacking"
+
+source "lib/Kconfig.debug"
+
+config KGDB
+	bool "Include kgdb kernel debugger"
+	depends on DEBUG_KERNEL && (BROKEN || PPC_GEN550 || 4xx)
+	select DEBUG_INFO
+	help
+	  Include in-kernel hooks for kgdb, the Linux kernel source level
+	  debugger.  See <http://kgdb.sourceforge.net/> for more information.
+	  Unless you are intending to debug the kernel, say N here.
+
+choice
+	prompt "Serial Port"
+	depends on KGDB
+	default KGDB_TTYS1
+
+config KGDB_TTYS0
+	bool "ttyS0"
+
+config KGDB_TTYS1
+	bool "ttyS1"
+
+config KGDB_TTYS2
+	bool "ttyS2"
+
+config KGDB_TTYS3
+	bool "ttyS3"
+
+endchoice
+
+config KGDB_CONSOLE
+	bool "Enable serial console thru kgdb port"
+	depends on KGDB && 8xx || CPM2
+	help
+	  If you enable this, all serial console messages will be sent
+	  over the gdb stub.
+	  If unsure, say N.
+
+config XMON
+	bool "Include xmon kernel debugger"
+	depends on DEBUG_KERNEL
+	help
+	  Include in-kernel hooks for the xmon kernel monitor/debugger.
+	  Unless you are intending to debug the kernel, say N here.
+
+config BDI_SWITCH
+	bool "Include BDI-2000 user context switcher"
+	depends on DEBUG_KERNEL
+	help
+	  Include in-kernel support for the Abatron BDI2000 debugger.
+	  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
+	help
+	  Say Y here to see progress messages from the boot firmware in text
+	  mode. Requires either BootX or Open Firmware.
+
+config SERIAL_TEXT_DEBUG
+	bool "Support for early boot texts over serial port"
+	depends on 4xx || GT64260 || LOPEC || PPLUS || PRPMC800 || PPC_GEN550 || PPC_MPC52xx
+
+config PPC_OCP
+	bool
+	depends on IBM_OCP || FSL_OCP
+	default y
+
+endmenu
diff -Nru a/arch/ppc/Makefile b/arch/ppc/Makefile
--- a/arch/ppc/Makefile	2004-10-18 14:55:54 -07:00
+++ b/arch/ppc/Makefile	2004-10-18 14:55:54 -07:00
@@ -13,7 +13,7 @@
 # This must match PAGE_OFFSET in include/asm-ppc/page.h.
 KERNELLOAD	:= $(CONFIG_KERNEL_START)
 
-HAS_BIARCH	:= $(shell if $(CC) -m32 -S -o /dev/null -xc /dev/null > /dev/null 2>&1; then echo y; else echo n; fi;)
+HAS_BIARCH	:= $(call cc-option-yn, -m32)
 ifeq ($(HAS_BIARCH),y)
 AS		:= $(AS) -a32
 LD		:= $(LD) -m elf32ppc
@@ -24,10 +24,10 @@
 CPPFLAGS	+= -Iarch/$(ARCH)
 AFLAGS		+= -Iarch/$(ARCH)
 CFLAGS		+= -Iarch/$(ARCH) -msoft-float -pipe \
-		-ffixed-r2 -Wno-uninitialized -mmultiple
+		-ffixed-r2 -mmultiple
 CPP		= $(CC) -E $(CFLAGS)
 
-CHECK		:= $(CHECK) -D__powerpc__=1
+CHECKFLAGS	+= -D__powerpc__
 
 ifndef CONFIG_E500
 CFLAGS		+= -mstring
@@ -70,7 +70,7 @@
 
 all: zImage
 
-AFLAGS_vmlinux.lds.o	:= -Upowerpc
+CPPFLAGS_vmlinux.lds	:= -Upowerpc
 
 # All the instructions talk about "make bzImage".
 bzImage: zImage
@@ -104,16 +104,15 @@
 include/asm-$(ARCH)/offsets.h: arch/$(ARCH)/kernel/asm-offsets.s
 	$(call filechk,gen-asm-offsets)
 
-ifdef CONFIG_6xx
-# Ensure this is binutils 2.12.1 (or 2.12.90.0.7) or later
-NEW_AS	:= $(shell echo dssall | $(AS) -many -o /dev/null >/dev/null 2>&1 ; echo $$?)
-GOODVER	:= 2.12.1
-else
-NEW_AS	:= 0
-endif
+# Use the file '.tmp_gas_check' for binutils tests, as gas won't output
+# to stdout and these checks are run even on install targets.
+TOUT	:= .tmp_gas_check
+# Ensure this is binutils 2.12.1 (or 2.12.90.0.7) or later for altivec
+# instructions.
+AS_ALTIVEC	:= $(shell echo dssall | $(AS) -many -o $(TOUT) >/dev/null 2>&1 ; echo $$?)
 # gcc-3.4 and binutils-2.14 are a fatal combination.
-GCC_VERSION	:= $(shell $(CONFIG_SHELL) $(srctree)/scripts/gcc-version.sh $(CC))
-BAD_GCC_AS	:= $(shell echo mftb 5 | $(AS) -mppc -many -o /dev/null >/dev/null 2>&1 && echo 0 || echo 1)
+GCC_VERSION	:= $(call cc-version)
+BAD_GCC_AS	:= $(shell echo mftb 5 | $(AS) -mppc -many -o $(TOUT) >/dev/null 2>&1 && echo 0 || echo 1)
 
 checkbin:
 ifeq ($(GCC_VERSION)$(BAD_GCC_AS),03041)
@@ -122,13 +121,16 @@
 	@echo '*** Please upgrade your binutils or downgrade your gcc'
 	@false
 endif
-ifneq ($(NEW_AS),0)
+ifneq ($(AS_ALTIVEC),0)
+	echo $(AS_ALTIVEC)
 	@echo -n '*** ${VERSION}.${PATCHLEVEL} kernels no longer build '
 	@echo 'correctly with old versions of binutils.'
-	@echo '*** Please upgrade your binutils to ${GOODVER} or newer'
+	@echo '*** Please upgrade your binutils to 2.12.1 or newer'
 	@false
 endif
 	@true
 
 CLEAN_FILES +=	include/asm-$(ARCH)/offsets.h \
-		arch/$(ARCH)/kernel/asm-offsets.s
+		arch/$(ARCH)/kernel/asm-offsets.s \
+		$(TOUT)
+
diff -Nru a/arch/ppc/amiga/config.c b/arch/ppc/amiga/config.c
--- a/arch/ppc/amiga/config.c	2004-10-18 14:56:50 -07:00
+++ b/arch/ppc/amiga/config.c	2004-10-18 14:56:50 -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/Makefile b/arch/ppc/boot/Makefile
--- a/arch/ppc/boot/Makefile	2004-10-18 14:56:33 -07:00
+++ b/arch/ppc/boot/Makefile	2004-10-18 14:56:33 -07:00
@@ -23,12 +23,12 @@
 # for cleaning
 subdir-				+= simple openfirmware
 
-host-progs := $(addprefix utils/, addnote mknote hack-coff mkprep mkbugboot mktree)
+hostprogs-y := $(addprefix utils/, addnote mknote hack-coff mkprep mkbugboot mktree)
 
 .PHONY: $(BOOT_TARGETS) $(bootdir-y)
 
 $(BOOT_TARGETS): $(bootdir-y)
 
 $(bootdir-y): $(addprefix $(obj)/,$(subdir-y)) \
-		$(addprefix $(obj)/,$(host-progs))
+		$(addprefix $(obj)/,$(hostprogs-y))
 	$(Q)$(MAKE) $(build)=$(obj)/$@ $(MAKECMDGOALS)
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-10-18 14:56:31 -07:00
+++ b/arch/ppc/boot/common/misc-common.c	2004-10-18 14:56:31 -07:00
@@ -17,7 +17,7 @@
 #include <stdarg.h>	/* for va_ bits */
 #include <linux/config.h>
 #include <linux/string.h>
-#include "zlib.h"
+#include <linux/zlib.h>
 #include "nonstdio.h"
 
 /* If we're on a PReP, assume we have a keyboard controller
@@ -202,11 +202,10 @@
 	while(1);	/* Halt */
 }
 
-void *zalloc(void *x, unsigned items, unsigned size)
+static void *zalloc(unsigned size)
 {
 	void *p = avail_ram;
 
-	size *= items;
 	size = (size + 7) & -8;
 	avail_ram += size;
 	if (avail_ram > end_avail) {
@@ -216,18 +215,12 @@
 	return p;
 }
 
-void zfree(void *x, void *addr, unsigned nb)
-{
-}
-
 #define HEAD_CRC	2
 #define EXTRA_FIELD	4
 #define ORIG_NAME	8
 #define COMMENT		0x10
 #define RESERVED	0xe0
 
-#define DEFLATED	8
-
 void gunzip(void *dst, int dstlen, unsigned char *src, int *lenp)
 {
 	z_stream s;
@@ -236,7 +229,7 @@
 	/* skip header */
 	i = 10;
 	flags = src[3];
-	if (src[2] != DEFLATED || (flags & RESERVED) != 0) {
+	if (src[2] != Z_DEFLATED || (flags & RESERVED) != 0) {
 		puts("bad gzipped data\n");
 		exit();
 	}
@@ -255,24 +248,24 @@
 		exit();
 	}
 
-	s.zalloc = zalloc;
-	s.zfree = zfree;
-	r = inflateInit2(&s, -MAX_WBITS);
+	/* Initialize ourself. */
+	s.workspace = zalloc(zlib_inflate_workspacesize());
+	r = zlib_inflateInit2(&s, -MAX_WBITS);
 	if (r != Z_OK) {
-		puts("inflateInit2 returned "); puthex(r); puts("\n");
+		puts("zlib_inflateInit2 returned "); puthex(r); puts("\n");
 		exit();
 	}
 	s.next_in = src + i;
 	s.avail_in = *lenp - i;
 	s.next_out = dst;
 	s.avail_out = dstlen;
-	r = inflate(&s, Z_FINISH);
+	r = zlib_inflate(&s, Z_FINISH);
 	if (r != Z_OK && r != Z_STREAM_END) {
 		puts("inflate returned "); puthex(r); puts("\n");
 		exit();
 	}
 	*lenp = s.next_out - (unsigned char *) dst;
-	inflateEnd(&s);
+	zlib_inflateEnd(&s);
 }
 
 void
@@ -525,6 +518,11 @@
  * because on some platforms we give inb/outb an exact location, and
  * 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/ns16550.c b/arch/ppc/boot/common/ns16550.c
--- a/arch/ppc/boot/common/ns16550.c	2004-10-18 14:57:04 -07:00
+++ b/arch/ppc/boot/common/ns16550.c	2004-10-18 14:57:04 -07:00
@@ -5,14 +5,14 @@
 #include <linux/config.h>
 #include <linux/types.h>
 #include <linux/serial.h>
-#include <linux/serialP.h>
 #include <linux/serial_reg.h>
 #include <asm/serial.h>
 
+#include "nonstdio.h"
+#include "serial.h"
+
 #define SERIAL_BAUD	9600
 
-extern void outb(int port, unsigned char val);
-extern unsigned char inb(int port);
 extern unsigned long ISA_io;
 
 static struct serial_state rs_table[RS_TABLE_SIZE] = {
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	2004-10-18 14:57:04 -07:00
+++ b/arch/ppc/boot/common/serial_stub.c	2004-10-18 14:57:04 -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/common/util.S b/arch/ppc/boot/common/util.S
--- a/arch/ppc/boot/common/util.S	2004-10-18 14:57:05 -07:00
+++ b/arch/ppc/boot/common/util.S	2004-10-18 14:57:05 -07:00
@@ -41,7 +41,7 @@
 	/* Test for a 601 */
 	mfpvr	r10
 	srwi	r10,r10,16
-	cmpi	0,r10,1		/* 601 ? */
+	cmpwi	0,r10,1		/* 601 ? */
 	beq	.clearbats_601
 
 	/* Clear BATs */
@@ -117,9 +117,9 @@
 	/* Wait for the invalidation to complete */
 	mfspr   r8,PVR
 	srwi    r8,r8,16
-	cmpli	cr0,r8,0x8000			/* 7450 */
-	cmpli	cr1,r8,0x8001			/* 7455 */
-	cmpli	cr2,r8,0x8002			/* 7457 */
+	cmplwi	cr0,r8,0x8000			/* 7450 */
+	cmplwi	cr1,r8,0x8001			/* 7455 */
+	cmplwi	cr2,r8,0x8002			/* 7457 */
 	cror	4*cr0+eq,4*cr0+eq,4*cr1+eq	/* Now test if any are true. */
 	cror	4*cr0+eq,4*cr0+eq,4*cr2+eq
 	bne     2f
@@ -190,7 +190,7 @@
 udelay:
 	mfspr	r4,PVR
 	srwi	r4,r4,16
-	cmpi	0,r4,1		/* 601 ? */
+	cmpwi	0,r4,1		/* 601 ? */
 	bne	.udelay_not_601
 00:	li	r0,86	/* Instructions / microsecond? */
 	mtctr	r0
@@ -213,16 +213,16 @@
 1:	mftbu	r5
 	mftb	r6
 	mftbu	r7
-	cmp	0,r5,r7
+	cmpw	0,r5,r7
 	bne	1b		/* Get [synced] base time */
 	addc	r9,r6,r4	/* Compute end time */
 	addze	r8,r5
 2:	mftbu	r5
-	cmp	0,r5,r8
+	cmpw	0,r5,r8
 	blt	2b
 	bgt	3f
 	mftb	r6
-	cmp	0,r6,r9
+	cmpw	0,r6,r9
 	blt	2b
 3:	blr
 
diff -Nru a/arch/ppc/boot/include/nonstdio.h b/arch/ppc/boot/include/nonstdio.h
--- a/arch/ppc/boot/include/nonstdio.h	2004-10-18 14:56:28 -07:00
+++ b/arch/ppc/boot/include/nonstdio.h	2004-10-18 14:56:28 -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/include/serial.h b/arch/ppc/boot/include/serial.h
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/arch/ppc/boot/include/serial.h	2004-10-18 14:57:21 -07:00
@@ -0,0 +1,46 @@
+/*
+ * A really private header file for the (dumb) serial driver in arch/ppc/boot
+ *
+ * Shamelessly taken from include/linux/serialP.h:
+ *
+ * Copyright (C) 1997 by Theodore Ts'o.
+ *
+ * Redistribution of this file is permitted under the terms of the GNU
+ * Public License (GPL)
+ */
+
+#ifndef _PPC_BOOT_SERIALP_H
+#define _PPC_BOOT_SERIALP_H
+
+/*
+ * This is our internal structure for each serial port's state.
+ *
+ * Many fields are paralleled by the structure used by the serial_struct
+ * structure.
+ *
+ * Given that this is how SERIAL_PORT_DFNS are done, and that we need
+ * to use a few of their fields, we need to have our own copy of it.
+ */
+struct serial_state {
+	int	magic;
+	int	baud_base;
+	unsigned long	port;
+	int	irq;
+	int	flags;
+	int	hub6;
+	int	type;
+	int	line;
+	int	revision;	/* Chip revision (950) */
+	int	xmit_fifo_size;
+	int	custom_divisor;
+	int	count;
+	u8	*iomem_base;
+	u16	iomem_reg_shift;
+	unsigned short	close_delay;
+	unsigned short	closing_wait; /* time to wait before closing */
+	unsigned long	icount;
+	int	io_type;
+	void    *info;
+	void    *dev;
+};
+#endif /* _PPC_BOOT_SERIAL_H */
diff -Nru a/arch/ppc/boot/include/zlib.h b/arch/ppc/boot/include/zlib.h
--- a/arch/ppc/boot/include/zlib.h	2004-10-18 14:56:17 -07:00
+++ /dev/null	Wed Dec 31 16:00:00 196900
@@ -1,430 +0,0 @@
-/*
- * This file is derived from zlib.h and zconf.h from the zlib-0.95
- * distribution by Jean-loup Gailly and Mark Adler, with some additions
- * by Paul Mackerras to aid in implementing Deflate compression and
- * decompression for PPP packets.
- */
-
-/*
- *  ==FILEVERSION 960122==
- *
- * This marker is used by the Linux installation script to determine
- * whether an up-to-date version of this file is already installed.
- */
-
-/* zlib.h -- interface of the 'zlib' general purpose compression library
-  version 0.95, Aug 16th, 1995.
-
-  Copyright (C) 1995 Jean-loup Gailly and Mark Adler
-
-  This software is provided 'as-is', without any express or implied
-  warranty.  In no event will the authors be held liable for any damages
-  arising from the use of this software.
-
-  Permission is granted to anyone to use this software for any purpose,
-  including commercial applications, and to alter it and redistribute it
-  freely, subject to the following restrictions:
-
-  1. The origin of this software must not be misrepresented; you must not
-     claim that you wrote the original software. If you use this software
-     in a product, an acknowledgment in the product documentation would be
-     appreciated but is not required.
-  2. Altered source versions must be plainly marked as such, and must not be
-     misrepresented as being the original software.
-  3. This notice may not be removed or altered from any source distribution.
-
-  Jean-loup Gailly        Mark Adler
-  gzip@prep.ai.mit.edu    madler@alumni.caltech.edu
- */
-
-#ifndef _ZLIB_H
-#define _ZLIB_H
-
-/* #include "zconf.h" */	/* included directly here */
-
-/* zconf.h -- configuration of the zlib compression library
- * Copyright (C) 1995 Jean-loup Gailly.
- * For conditions of distribution and use, see copyright notice in zlib.h
- */
-
-/* From: zconf.h,v 1.12 1995/05/03 17:27:12 jloup Exp */
-
-/*
-     The library does not install any signal handler. It is recommended to
-  add at least a handler for SIGSEGV when decompressing; the library checks
-  the consistency of the input data whenever possible but may go nuts
-  for some forms of corrupted input.
- */
-
-/*
- * Compile with -DMAXSEG_64K if the alloc function cannot allocate more
- * than 64k bytes at a time (needed on systems with 16-bit int).
- * Compile with -DUNALIGNED_OK if it is OK to access shorts or ints
- * at addresses which are not a multiple of their size.
- * Under DOS, -DFAR=far or -DFAR=__far may be needed.
- */
-
-#ifndef STDC
-#  if defined(MSDOS) || defined(__STDC__) || defined(__cplusplus)
-#    define STDC
-#  endif
-#endif
-
-#ifdef	__MWERKS__ /* Metrowerks CodeWarrior declares fileno() in unix.h */
-#  include <unix.h>
-#endif
-
-/* Maximum value for memLevel in deflateInit2 */
-#ifndef MAX_MEM_LEVEL
-#  ifdef MAXSEG_64K
-#    define MAX_MEM_LEVEL 8
-#  else
-#    define MAX_MEM_LEVEL 9
-#  endif
-#endif
-
-#ifndef FAR
-#  define FAR
-#endif
-
-/* Maximum value for windowBits in deflateInit2 and inflateInit2 */
-#ifndef MAX_WBITS
-#  define MAX_WBITS   15 /* 32K LZ77 window */
-#endif
-
-/* The memory requirements for deflate are (in bytes):
-            1 << (windowBits+2)   +  1 << (memLevel+9)
- that is: 128K for windowBits=15  +  128K for memLevel = 8  (default values)
- plus a few kilobytes for small objects. For example, if you want to reduce
- the default memory requirements from 256K to 128K, compile with
-     make CFLAGS="-O -DMAX_WBITS=14 -DMAX_MEM_LEVEL=7"
- Of course this will generally degrade compression (there's no free lunch).
-
-   The memory requirements for inflate are (in bytes) 1 << windowBits
- that is, 32K for windowBits=15 (default value) plus a few kilobytes
- for small objects.
-*/
-
-                        /* Type declarations */
-
-#ifndef OF /* function prototypes */
-#  ifdef STDC
-#    define OF(args)  args
-#  else
-#    define OF(args)  ()
-#  endif
-#endif
-
-typedef unsigned char  Byte;  /* 8 bits */
-typedef unsigned int   uInt;  /* 16 bits or more */
-typedef unsigned long  uLong; /* 32 bits or more */
-
-typedef Byte FAR Bytef;
-typedef char FAR charf;
-typedef int FAR intf;
-typedef uInt FAR uIntf;
-typedef uLong FAR uLongf;
-
-#ifdef STDC
-   typedef void FAR *voidpf;
-   typedef void     *voidp;
-#else
-   typedef Byte FAR *voidpf;
-   typedef Byte     *voidp;
-#endif
-
-/* end of original zconf.h */
-
-#define ZLIB_VERSION "0.95P"
-
-/*
-     The 'zlib' compression library provides in-memory compression and
-  decompression functions, including integrity checks of the uncompressed
-  data.  This version of the library supports only one compression method
-  (deflation) but other algorithms may be added later and will have the same
-  stream interface.
-
-     For compression the application must provide the output buffer and
-  may optionally provide the input buffer for optimization. For decompression,
-  the application must provide the input buffer and may optionally provide
-  the output buffer for optimization.
-
-     Compression can be done in a single step if the buffers are large
-  enough (for example if an input file is mmap'ed), or can be done by
-  repeated calls of the compression function.  In the latter case, the
-  application must provide more input and/or consume the output
-  (providing more output space) before each call.
-*/
-
-typedef voidpf (*alloc_func) OF((voidpf opaque, uInt items, uInt size));
-typedef void   (*free_func)  OF((voidpf opaque, voidpf address, uInt nbytes));
-
-struct internal_state;
-
-typedef struct z_stream_s {
-    Bytef    *next_in;  /* next input byte */
-    uInt     avail_in;  /* number of bytes available at next_in */
-    uLong    total_in;  /* total nb of input bytes read so far */
-
-    Bytef    *next_out; /* next output byte should be put there */
-    uInt     avail_out; /* remaining free space at next_out */
-    uLong    total_out; /* total nb of bytes output so far */
-
-    char     *msg;      /* last error message, NULL if no error */
-    struct internal_state FAR *state; /* not visible by applications */
-
-    alloc_func zalloc;  /* used to allocate the internal state */
-    free_func  zfree;   /* used to free the internal state */
-    voidp      opaque;  /* private data object passed to zalloc and zfree */
-
-    Byte     data_type; /* best guess about the data type: ascii or binary */
-
-} z_stream;
-
-/*
-   The application must update next_in and avail_in when avail_in has
-   dropped to zero. It must update next_out and avail_out when avail_out
-   has dropped to zero. The application must initialize zalloc, zfree and
-   opaque before calling the init function. All other fields are set by the
-   compression library and must not be updated by the application.
-
-   The opaque value provided by the application will be passed as the first
-   parameter for calls of zalloc and zfree. This can be useful for custom
-   memory management. The compression library attaches no meaning to the
-   opaque value.
-
-   zalloc must return Z_NULL if there is not enough memory for the object.
-   On 16-bit systems, the functions zalloc and zfree must be able to allocate
-   exactly 65536 bytes, but will not be required to allocate more than this
-   if the symbol MAXSEG_64K is defined (see zconf.h). WARNING: On MSDOS,
-   pointers returned by zalloc for objects of exactly 65536 bytes *must*
-   have their offset normalized to zero. The default allocation function
-   provided by this library ensures this (see zutil.c). To reduce memory
-   requirements and avoid any allocation of 64K objects, at the expense of
-   compression ratio, compile the library with -DMAX_WBITS=14 (see zconf.h).
-
-   The fields total_in and total_out can be used for statistics or
-   progress reports. After compression, total_in holds the total size of
-   the uncompressed data and may be saved for use in the decompressor
-   (particularly if the decompressor wants to decompress everything in
-   a single step).
-*/
-
-                        /* constants */
-
-#define Z_NO_FLUSH      0
-#define Z_PARTIAL_FLUSH 1
-#define Z_FULL_FLUSH    2
-#define Z_SYNC_FLUSH    3 /* experimental: partial_flush + byte align */
-#define Z_FINISH        4
-#define Z_PACKET_FLUSH	5
-/* See deflate() below for the usage of these constants */
-
-#define Z_OK            0
-#define Z_STREAM_END    1
-#define Z_ERRNO        (-1)
-#define Z_STREAM_ERROR (-2)
-#define Z_DATA_ERROR   (-3)
-#define Z_MEM_ERROR    (-4)
-#define Z_BUF_ERROR    (-5)
-/* error codes for the compression/decompression functions */
-
-#define Z_BEST_SPEED             1
-#define Z_BEST_COMPRESSION       9
-#define Z_DEFAULT_COMPRESSION  (-1)
-/* compression levels */
-
-#define Z_FILTERED            1
-#define Z_HUFFMAN_ONLY        2
-#define Z_DEFAULT_STRATEGY    0
-
-#define Z_BINARY   0
-#define Z_ASCII    1
-#define Z_UNKNOWN  2
-/* Used to set the data_type field */
-
-#define Z_NULL  0  /* for initializing zalloc, zfree, opaque */
-
-extern char *zlib_version;
-/* The application can compare zlib_version and ZLIB_VERSION for consistency.
-   If the first character differs, the library code actually used is
-   not compatible with the zlib.h header file used by the application.
- */
-
-                        /* basic functions */
-
-extern int inflateInit OF((z_stream *strm));
-/*
-     Initializes the internal stream state for decompression. The fields
-   zalloc and zfree must be initialized before by the caller.  If zalloc and
-   zfree are set to Z_NULL, inflateInit updates them to use default allocation
-   functions.
-
-     inflateInit returns Z_OK if success, Z_MEM_ERROR if there was not
-   enough memory.  msg is set to null if there is no error message.
-   inflateInit does not perform any decompression: this will be done by
-   inflate().
-*/
-
-
-extern int inflate OF((z_stream *strm, int flush));
-/*
-  Performs one or both of the following actions:
-
-  - Decompress more input starting at next_in and update next_in and avail_in
-    accordingly. If not all input can be processed (because there is not
-    enough room in the output buffer), next_in is updated and processing
-    will resume at this point for the next call of inflate().
-
-  - Provide more output starting at next_out and update next_out and avail_out
-    accordingly.  inflate() always provides as much output as possible
-    (until there is no more input data or no more space in the output buffer).
-
-  Before the call of inflate(), the application should ensure that at least
-  one of the actions is possible, by providing more input and/or consuming
-  more output, and updating the next_* and avail_* values accordingly.
-  The application can consume the uncompressed output when it wants, for
-  example when the output buffer is full (avail_out == 0), or after each
-  call of inflate().
-
-    If the parameter flush is set to Z_PARTIAL_FLUSH or Z_PACKET_FLUSH,
-  inflate flushes as much output as possible to the output buffer. The
-  flushing behavior of inflate is not specified for values of the flush
-  parameter other than Z_PARTIAL_FLUSH, Z_PACKET_FLUSH or Z_FINISH, but the
-  current implementation actually flushes as much output as possible
-  anyway.  For Z_PACKET_FLUSH, inflate checks that once all the input data
-  has been consumed, it is expecting to see the length field of a stored
-  block; if not, it returns Z_DATA_ERROR.
-
-    inflate() should normally be called until it returns Z_STREAM_END or an
-  error. However if all decompression is to be performed in a single step
-  (a single call of inflate), the parameter flush should be set to
-  Z_FINISH. In this case all pending input is processed and all pending
-  output is flushed; avail_out must be large enough to hold all the
-  uncompressed data. (The size of the uncompressed data may have been saved
-  by the compressor for this purpose.) The next operation on this stream must
-  be inflateEnd to deallocate the decompression state. The use of Z_FINISH
-  is never required, but can be used to inform inflate that a faster routine
-  may be used for the single inflate() call.
-
-    inflate() returns Z_OK if some progress has been made (more input
-  processed or more output produced), Z_STREAM_END if the end of the
-  compressed data has been reached and all uncompressed output has been
-  produced, Z_DATA_ERROR if the input data was corrupted, Z_STREAM_ERROR if
-  the stream structure was inconsistent (for example if next_in or next_out
-  was NULL), Z_MEM_ERROR if there was not enough memory, Z_BUF_ERROR if no
-  progress is possible or if there was not enough room in the output buffer
-  when Z_FINISH is used. In the Z_DATA_ERROR case, the application may then
-  call inflateSync to look for a good compression block.  */
-
-
-extern int inflateEnd OF((z_stream *strm));
-/*
-     All dynamically allocated data structures for this stream are freed.
-   This function discards any unprocessed input and does not flush any
-   pending output.
-
-     inflateEnd returns Z_OK if success, Z_STREAM_ERROR if the stream state
-   was inconsistent. In the error case, msg may be set but then points to a
-   static string (which must not be deallocated).
-*/
-
-                        /* advanced functions */
-
-extern int inflateInit2 OF((z_stream *strm,
-                            int  windowBits));
-/*
-     This is another version of inflateInit with more compression options. The
-   fields next_out, zalloc and zfree must be initialized before by the caller.
-
-     The windowBits parameter is the base two logarithm of the maximum window
-   size (the size of the history buffer).  It should be in the range 8..15 for
-   this version of the library (the value 16 will be allowed soon). The
-   default value is 15 if inflateInit is used instead. If a compressed stream
-   with a larger window size is given as input, inflate() will return with
-   the error code Z_DATA_ERROR instead of trying to allocate a larger window.
-
-     If next_out is not null, the library will use this buffer for the history
-   buffer; the buffer must either be large enough to hold the entire output
-   data, or have at least 1<<windowBits bytes.  If next_out is null, the
-   library will allocate its own buffer (and leave next_out null). next_in
-   need not be provided here but must be provided by the application for the
-   next call of inflate().
-
-     If the history buffer is provided by the application, next_out must
-   never be changed by the application since the decompressor maintains
-   history information inside this buffer from call to call; the application
-   can only reset next_out to the beginning of the history buffer when
-   avail_out is zero and all output has been consumed.
-
-      inflateInit2 returns Z_OK if success, Z_MEM_ERROR if there was
-   not enough memory, Z_STREAM_ERROR if a parameter is invalid (such as
-   windowBits < 8). msg is set to null if there is no error message.
-   inflateInit2 does not perform any decompression: this will be done by
-   inflate().
-*/
-
-extern int inflateSync OF((z_stream *strm));
-/*
-    Skips invalid compressed data until the special marker (see deflate()
-  above) can be found, or until all available input is skipped. No output
-  is provided.
-
-    inflateSync returns Z_OK if the special marker has been found, Z_BUF_ERROR
-  if no more input was provided, Z_DATA_ERROR if no marker has been found,
-  or Z_STREAM_ERROR if the stream structure was inconsistent. In the success
-  case, the application may save the current current value of total_in which
-  indicates where valid compressed data was found. In the error case, the
-  application may repeatedly call inflateSync, providing more input each time,
-  until success or end of the input data.
-*/
-
-extern int inflateReset OF((z_stream *strm));
-/*
-     This function is equivalent to inflateEnd followed by inflateInit,
-   but does not free and reallocate all the internal decompression state.
-   The stream will keep attributes that may have been set by inflateInit2.
-
-      inflateReset returns Z_OK if success, or Z_STREAM_ERROR if the source
-   stream state was inconsistent (such as zalloc or state being NULL).
-*/
-
-extern int inflateIncomp OF((z_stream *strm));
-/*
-     This function adds the data at next_in (avail_in bytes) to the output
-   history without performing any output.  There must be no pending output,
-   and the decompressor must be expecting to see the start of a block.
-   Calling this function is equivalent to decompressing a stored block
-   containing the data at next_in (except that the data is not output).
-*/
-
-                        /* checksum functions */
-
-/*
-     This function is not related to compression but is exported
-   anyway because it might be useful in applications using the
-   compression library.
-*/
-
-extern uLong adler32 OF((uLong adler, Bytef *buf, uInt len));
-
-/*
-     Update a running Adler-32 checksum with the bytes buf[0..len-1] and
-   return the updated checksum. If buf is NULL, this function returns
-   the required initial value for the checksum.
-   An Adler-32 checksum is almost as reliable as a CRC32 but can be computed
-   much faster. Usage example:
-
-     uLong adler = adler32(0L, Z_NULL, 0);
-
-     while (read_buffer(buffer, length) != EOF) {
-       adler = adler32(adler, buffer, length);
-     }
-     if (adler != original_adler) error();
-*/
-
-#ifndef _Z_UTIL_H
-    struct internal_state {int dummy;}; /* hack for buggy compilers */
-#endif
-
-#endif /* _ZLIB_H */
diff -Nru a/arch/ppc/boot/lib/Makefile b/arch/ppc/boot/lib/Makefile
--- a/arch/ppc/boot/lib/Makefile	2004-10-18 14:56:49 -07:00
+++ b/arch/ppc/boot/lib/Makefile	2004-10-18 14:56:49 -07:00
@@ -4,5 +4,7 @@
 
 CFLAGS_kbd.o	+= -Idrivers/char
 
-lib-y := zlib.o div64.o
+lib-y := $(addprefix ../../../../lib/zlib_inflate/, \
+           infblock.o infcodes.o inffast.o inflate.o inftrees.o infutil.o)
+lib-y += div64.o
 lib-$(CONFIG_VGA_CONSOLE) += vreset.o kbd.o
diff -Nru a/arch/ppc/boot/lib/zlib.c b/arch/ppc/boot/lib/zlib.c
--- a/arch/ppc/boot/lib/zlib.c	2004-10-18 14:56:27 -07:00
+++ /dev/null	Wed Dec 31 16:00:00 196900
@@ -1,2169 +0,0 @@
-/*
- * This file is derived from various .h and .c files from the zlib-0.95
- * distribution by Jean-loup Gailly and Mark Adler, with some additions
- * by Paul Mackerras to aid in implementing Deflate compression and
- * decompression for PPP packets.  See zlib.h for conditions of
- * distribution and use.
- *
- * Changes that have been made include:
- * - changed functions not used outside this file to "local"
- * - added minCompression parameter to deflateInit2
- * - added Z_PACKET_FLUSH (see zlib.h for details)
- * - added inflateIncomp
- *
- */
-
-/*+++++*/
-/* zutil.h -- internal interface and configuration of the compression library
- * Copyright (C) 1995 Jean-loup Gailly.
- * For conditions of distribution and use, see copyright notice in zlib.h
- */
-
-/* WARNING: this file should *not* be used by applications. It is
-   part of the implementation of the compression library and is
-   subject to change. Applications should only use zlib.h.
- */
-
-/* From: zutil.h,v 1.9 1995/05/03 17:27:12 jloup Exp */
-
-#define _Z_UTIL_H
-
-#include "zlib.h"
-
-#ifndef local
-#  define local static
-#endif
-/* compile with -Dlocal if your debugger can't find static symbols */
-
-#define FAR
-
-typedef unsigned char  uch;
-typedef uch FAR uchf;
-typedef unsigned short ush;
-typedef ush FAR ushf;
-typedef unsigned long  ulg;
-
-extern char *z_errmsg[]; /* indexed by 1-zlib_error */
-
-#define ERR_RETURN(strm,err) return (strm->msg=z_errmsg[1-err], err)
-/* To be used only when the state is known to be valid */
-
-#ifndef NULL
-#define NULL	((void *) 0)
-#endif
-
-        /* common constants */
-
-#define DEFLATED   8
-
-#ifndef DEF_WBITS
-#  define DEF_WBITS MAX_WBITS
-#endif
-/* default windowBits for decompression. MAX_WBITS is for compression only */
-
-#if MAX_MEM_LEVEL >= 8
-#  define DEF_MEM_LEVEL 8
-#else
-#  define DEF_MEM_LEVEL  MAX_MEM_LEVEL
-#endif
-/* default memLevel */
-
-#define STORED_BLOCK 0
-#define STATIC_TREES 1
-#define DYN_TREES    2
-/* The three kinds of block type */
-
-#define MIN_MATCH  3
-#define MAX_MATCH  258
-/* The minimum and maximum match lengths */
-
-         /* functions */
-
-#include <linux/string.h>
-#define zmemcpy memcpy
-#define zmemzero(dest, len)	memset(dest, 0, len)
-
-/* Diagnostic functions */
-#ifdef DEBUG_ZLIB
-#  include <stdio.h>
-#  ifndef verbose
-#    define verbose 0
-#  endif
-#  define Assert(cond,msg) {if(!(cond)) z_error(msg);}
-#  define Trace(x) fprintf x
-#  define Tracev(x) {if (verbose) fprintf x ;}
-#  define Tracevv(x) {if (verbose>1) fprintf x ;}
-#  define Tracec(c,x) {if (verbose && (c)) fprintf x ;}
-#  define Tracecv(c,x) {if (verbose>1 && (c)) fprintf x ;}
-#else
-#  define Assert(cond,msg)
-#  define Trace(x)
-#  define Tracev(x)
-#  define Tracevv(x)
-#  define Tracec(c,x)
-#  define Tracecv(c,x)
-#endif
-
-
-typedef uLong (*check_func) OF((uLong check, Bytef *buf, uInt len));
-
-/* voidpf zcalloc OF((voidpf opaque, unsigned items, unsigned size)); */
-/* void   zcfree  OF((voidpf opaque, voidpf ptr)); */
-
-#define ZALLOC(strm, items, size) \
-           (*((strm)->zalloc))((strm)->opaque, (items), (size))
-#define ZFREE(strm, addr, size)	\
-	   (*((strm)->zfree))((strm)->opaque, (voidpf)(addr), (size))
-#define TRY_FREE(s, p, n) {if (p) ZFREE(s, p, n);}
-
-/* deflate.h -- internal compression state
- * Copyright (C) 1995 Jean-loup Gailly
- * For conditions of distribution and use, see copyright notice in zlib.h
- */
-
-/* WARNING: this file should *not* be used by applications. It is
-   part of the implementation of the compression library and is
-   subject to change. Applications should only use zlib.h.
- */
-
-/*+++++*/
-/* infblock.h -- header to use infblock.c
- * Copyright (C) 1995 Mark Adler
- * For conditions of distribution and use, see copyright notice in zlib.h
- */
-
-/* WARNING: this file should *not* be used by applications. It is
-   part of the implementation of the compression library and is
-   subject to change. Applications should only use zlib.h.
- */
-
-struct inflate_blocks_state;
-typedef struct inflate_blocks_state FAR inflate_blocks_statef;
-
-local inflate_blocks_statef * inflate_blocks_new OF((
-    z_stream *z,
-    check_func c,               /* check function */
-    uInt w));                   /* window size */
-
-local int inflate_blocks OF((
-    inflate_blocks_statef *,
-    z_stream *,
-    int));                      /* initial return code */
-
-local void inflate_blocks_reset OF((
-    inflate_blocks_statef *,
-    z_stream *,
-    uLongf *));                  /* check value on output */
-
-local int inflate_blocks_free OF((
-    inflate_blocks_statef *,
-    z_stream *,
-    uLongf *));                  /* check value on output */
-
-local int inflate_addhistory OF((
-    inflate_blocks_statef *,
-    z_stream *));
-
-local int inflate_packet_flush OF((
-    inflate_blocks_statef *));
-
-/*+++++*/
-/* inftrees.h -- header to use inftrees.c
- * Copyright (C) 1995 Mark Adler
- * For conditions of distribution and use, see copyright notice in zlib.h
- */
-
-/* WARNING: this file should *not* be used by applications. It is
-   part of the implementation of the compression library and is
-   subject to change. Applications should only use zlib.h.
- */
-
-/* Huffman code lookup table entry--this entry is four bytes for machines
-   that have 16-bit pointers (e.g. PC's in the small or medium model). */
-
-typedef struct inflate_huft_s FAR inflate_huft;
-
-struct inflate_huft_s {
-  union {
-    struct {
-      Byte Exop;        /* number of extra bits or operation */
-      Byte Bits;        /* number of bits in this code or subcode */
-    } what;
-    uInt Nalloc;	/* number of these allocated here */
-    Bytef *pad;         /* pad structure to a power of 2 (4 bytes for */
-  } word;               /*  16-bit, 8 bytes for 32-bit machines) */
-  union {
-    uInt Base;          /* literal, length base, or distance base */
-    inflate_huft *Next; /* pointer to next level of table */
-  } more;
-};
-
-#ifdef DEBUG_ZLIB
-  local uInt inflate_hufts;
-#endif
-
-local int inflate_trees_bits OF((
-    uIntf *,                    /* 19 code lengths */
-    uIntf *,                    /* bits tree desired/actual depth */
-    inflate_huft * FAR *,       /* bits tree result */
-    z_stream *));               /* for zalloc, zfree functions */
-
-local int inflate_trees_dynamic OF((
-    uInt,                       /* number of literal/length codes */
-    uInt,                       /* number of distance codes */
-    uIntf *,                    /* that many (total) code lengths */
-    uIntf *,                    /* literal desired/actual bit depth */
-    uIntf *,                    /* distance desired/actual bit depth */
-    inflate_huft * FAR *,       /* literal/length tree result */
-    inflate_huft * FAR *,       /* distance tree result */
-    z_stream *));               /* for zalloc, zfree functions */
-
-local int inflate_trees_fixed OF((
-    uIntf *,                    /* literal desired/actual bit depth */
-    uIntf *,                    /* distance desired/actual bit depth */
-    inflate_huft * FAR *,       /* literal/length tree result */
-    inflate_huft * FAR *));     /* distance tree result */
-
-local int inflate_trees_free OF((
-    inflate_huft *,             /* tables to free */
-    z_stream *));               /* for zfree function */
-
-
-/*+++++*/
-/* infcodes.h -- header to use infcodes.c
- * Copyright (C) 1995 Mark Adler
- * For conditions of distribution and use, see copyright notice in zlib.h
- */
-
-/* WARNING: this file should *not* be used by applications. It is
-   part of the implementation of the compression library and is
-   subject to change. Applications should only use zlib.h.
- */
-
-struct inflate_codes_state;
-typedef struct inflate_codes_state FAR inflate_codes_statef;
-
-local inflate_codes_statef *inflate_codes_new OF((
-    uInt, uInt,
-    inflate_huft *, inflate_huft *,
-    z_stream *));
-
-local int inflate_codes OF((
-    inflate_blocks_statef *,
-    z_stream *,
-    int));
-
-local void inflate_codes_free OF((
-    inflate_codes_statef *,
-    z_stream *));
-
-
-/*+++++*/
-/* inflate.c -- zlib interface to inflate modules
- * Copyright (C) 1995 Mark Adler
- * For conditions of distribution and use, see copyright notice in zlib.h
- */
-
-/* inflate private state */
-struct internal_state {
-
-  /* mode */
-  enum {
-      METHOD,   /* waiting for method byte */
-      FLAG,     /* waiting for flag byte */
-      BLOCKS,   /* decompressing blocks */
-      CHECK4,   /* four check bytes to go */
-      CHECK3,   /* three check bytes to go */
-      CHECK2,   /* two check bytes to go */
-      CHECK1,   /* one check byte to go */
-      DONE,     /* finished check, done */
-      BAD}      /* got an error--stay here */
-    mode;               /* current inflate mode */
-
-  /* mode dependent information */
-  union {
-    uInt method;        /* if FLAGS, method byte */
-    struct {
-      uLong was;                /* computed check value */
-      uLong need;               /* stream check value */
-    } check;            /* if CHECK, check values to compare */
-    uInt marker;        /* if BAD, inflateSync's marker bytes count */
-  } sub;        /* submode */
-
-  /* mode independent information */
-  int  nowrap;          /* flag for no wrapper */
-  uInt wbits;           /* log2(window size)  (8..15, defaults to 15) */
-  inflate_blocks_statef
-    *blocks;            /* current inflate_blocks state */
-
-};
-
-
-int inflateReset(
-	z_stream *z
-)
-{
-  uLong c;
-
-  if (z == Z_NULL || z->state == Z_NULL)
-    return Z_STREAM_ERROR;
-  z->total_in = z->total_out = 0;
-  z->msg = Z_NULL;
-  z->state->mode = z->state->nowrap ? BLOCKS : METHOD;
-  inflate_blocks_reset(z->state->blocks, z, &c);
-  Trace((stderr, "inflate: reset\n"));
-  return Z_OK;
-}
-
-
-int inflateEnd(
-	z_stream *z
-)
-{
-  uLong c;
-
-  if (z == Z_NULL || z->state == Z_NULL || z->zfree == Z_NULL)
-    return Z_STREAM_ERROR;
-  if (z->state->blocks != Z_NULL)
-    inflate_blocks_free(z->state->blocks, z, &c);
-  ZFREE(z, z->state, sizeof(struct internal_state));
-  z->state = Z_NULL;
-  Trace((stderr, "inflate: end\n"));
-  return Z_OK;
-}
-
-
-int inflateInit2(
-	z_stream *z,
-	int w
-)
-{
-  /* initialize state */
-  if (z == Z_NULL)
-    return Z_STREAM_ERROR;
-/*  if (z->zalloc == Z_NULL) z->zalloc = zcalloc; */
-/*  if (z->zfree == Z_NULL) z->zfree = zcfree; */
-  if ((z->state = (struct internal_state FAR *)
-       ZALLOC(z,1,sizeof(struct internal_state))) == Z_NULL)
-    return Z_MEM_ERROR;
-  z->state->blocks = Z_NULL;
-
-  /* handle undocumented nowrap option (no zlib header or check) */
-  z->state->nowrap = 0;
-  if (w < 0)
-  {
-    w = - w;
-    z->state->nowrap = 1;
-  }
-
-  /* set window size */
-  if (w < 8 || w > 15)
-  {
-    inflateEnd(z);
-    return Z_STREAM_ERROR;
-  }
-  z->state->wbits = (uInt)w;
-
-  /* create inflate_blocks state */
-  if ((z->state->blocks =
-       inflate_blocks_new(z, z->state->nowrap ? Z_NULL : adler32, 1 << w))
-      == Z_NULL)
-  {
-    inflateEnd(z);
-    return Z_MEM_ERROR;
-  }
-  Trace((stderr, "inflate: allocated\n"));
-
-  /* reset state */
-  inflateReset(z);
-  return Z_OK;
-}
-
-
-int inflateInit(
-	z_stream *z
-)
-{
-  return inflateInit2(z, DEF_WBITS);
-}
-
-
-#define NEEDBYTE {if(z->avail_in==0)goto empty;r=Z_OK;}
-#define NEXTBYTE (z->avail_in--,z->total_in++,*z->next_in++)
-
-int inflate(
-	z_stream *z,
-	int f
-)
-{
-  int r;
-  uInt b;
-
-  if (z == Z_NULL || z->next_in == Z_NULL)
-    return Z_STREAM_ERROR;
-  r = Z_BUF_ERROR;
-  while (1) switch (z->state->mode)
-  {
-    case METHOD:
-      NEEDBYTE
-      if (((z->state->sub.method = NEXTBYTE) & 0xf) != DEFLATED)
-      {
-        z->state->mode = BAD;
-        z->msg = "unknown compression method";
-        z->state->sub.marker = 5;       /* can't try inflateSync */
-        break;
-      }
-      if ((z->state->sub.method >> 4) + 8 > z->state->wbits)
-      {
-        z->state->mode = BAD;
-        z->msg = "invalid window size";
-        z->state->sub.marker = 5;       /* can't try inflateSync */
-        break;
-      }
-      z->state->mode = FLAG;
-    case FLAG:
-      NEEDBYTE
-      if ((b = NEXTBYTE) & 0x20)
-      {
-        z->state->mode = BAD;
-        z->msg = "invalid reserved bit";
-        z->state->sub.marker = 5;       /* can't try inflateSync */
-        break;
-      }
-      if (((z->state->sub.method << 8) + b) % 31)
-      {
-        z->state->mode = BAD;
-        z->msg = "incorrect header check";
-        z->state->sub.marker = 5;       /* can't try inflateSync */
-        break;
-      }
-      Trace((stderr, "inflate: zlib header ok\n"));
-      z->state->mode = BLOCKS;
-    case BLOCKS:
-      r = inflate_blocks(z->state->blocks, z, r);
-      if (f == Z_PACKET_FLUSH && z->avail_in == 0 && z->avail_out != 0)
-	  r = inflate_packet_flush(z->state->blocks);
-      if (r == Z_DATA_ERROR)
-      {
-        z->state->mode = BAD;
-        z->state->sub.marker = 0;       /* can try inflateSync */
-        break;
-      }
-      if (r != Z_STREAM_END)
-        return r;
-      r = Z_OK;
-      inflate_blocks_reset(z->state->blocks, z, &z->state->sub.check.was);
-      if (z->state->nowrap)
-      {
-        z->state->mode = DONE;
-        break;
-      }
-      z->state->mode = CHECK4;
-    case CHECK4:
-      NEEDBYTE
-      z->state->sub.check.need = (uLong)NEXTBYTE << 24;
-      z->state->mode = CHECK3;
-    case CHECK3:
-      NEEDBYTE
-      z->state->sub.check.need += (uLong)NEXTBYTE << 16;
-      z->state->mode = CHECK2;
-    case CHECK2:
-      NEEDBYTE
-      z->state->sub.check.need += (uLong)NEXTBYTE << 8;
-      z->state->mode = CHECK1;
-    case CHECK1:
-      NEEDBYTE
-      z->state->sub.check.need += (uLong)NEXTBYTE;
-
-      if (z->state->sub.check.was != z->state->sub.check.need)
-      {
-        z->state->mode = BAD;
-        z->msg = "incorrect data check";
-        z->state->sub.marker = 5;       /* can't try inflateSync */
-        break;
-      }
-      Trace((stderr, "inflate: zlib check ok\n"));
-      z->state->mode = DONE;
-    case DONE:
-      return Z_STREAM_END;
-    case BAD:
-      return Z_DATA_ERROR;
-    default:
-      return Z_STREAM_ERROR;
-  }
-
- empty:
-  if (f != Z_PACKET_FLUSH)
-    return r;
-  z->state->mode = BAD;
-  z->state->sub.marker = 0;       /* can try inflateSync */
-  return Z_DATA_ERROR;
-}
-
-/*
- * This subroutine adds the data at next_in/avail_in to the output history
- * without performing any output.  The output buffer must be "caught up";
- * i.e. no pending output (hence s->read equals s->write), and the state must
- * be BLOCKS (i.e. we should be willing to see the start of a series of
- * BLOCKS).  On exit, the output will also be caught up, and the checksum
- * will have been updated if need be.
- */
-
-int inflateIncomp(
-	z_stream *z
-)
-{
-    if (z->state->mode != BLOCKS)
-	return Z_DATA_ERROR;
-    return inflate_addhistory(z->state->blocks, z);
-}
-
-
-int inflateSync(
-	z_stream *z
-)
-{
-  uInt n;       /* number of bytes to look at */
-  Bytef *p;     /* pointer to bytes */
-  uInt m;       /* number of marker bytes found in a row */
-  uLong r, w;   /* temporaries to save total_in and total_out */
-
-  /* set up */
-  if (z == Z_NULL || z->state == Z_NULL)
-    return Z_STREAM_ERROR;
-  if (z->state->mode != BAD)
-  {
-    z->state->mode = BAD;
-    z->state->sub.marker = 0;
-  }
-  if ((n = z->avail_in) == 0)
-    return Z_BUF_ERROR;
-  p = z->next_in;
-  m = z->state->sub.marker;
-
-  /* search */
-  while (n && m < 4)
-  {
-    if (*p == (Byte)(m < 2 ? 0 : 0xff))
-      m++;
-    else if (*p)
-      m = 0;
-    else
-      m = 4 - m;
-    p++, n--;
-  }
-
-  /* restore */
-  z->total_in += p - z->next_in;
-  z->next_in = p;
-  z->avail_in = n;
-  z->state->sub.marker = m;
-
-  /* return no joy or set up to restart on a new block */
-  if (m != 4)
-    return Z_DATA_ERROR;
-  r = z->total_in;  w = z->total_out;
-  inflateReset(z);
-  z->total_in = r;  z->total_out = w;
-  z->state->mode = BLOCKS;
-  return Z_OK;
-}
-
-#undef NEEDBYTE
-#undef NEXTBYTE
-
-/*+++++*/
-/* infutil.h -- types and macros common to blocks and codes
- * Copyright (C) 1995 Mark Adler
- * For conditions of distribution and use, see copyright notice in zlib.h
- */
-
-/* WARNING: this file should *not* be used by applications. It is
-   part of the implementation of the compression library and is
-   subject to change. Applications should only use zlib.h.
- */
-
-/* inflate blocks semi-private state */
-struct inflate_blocks_state {
-
-  /* mode */
-  enum {
-      TYPE,     /* get type bits (3, including end bit) */
-      LENS,     /* get lengths for stored */
-      STORED,   /* processing stored block */
-      TABLE,    /* get table lengths */
-      BTREE,    /* get bit lengths tree for a dynamic block */
-      DTREE,    /* get length, distance trees for a dynamic block */
-      CODES,    /* processing fixed or dynamic block */
-      DRY,      /* output remaining window bytes */
-      DONEB,     /* finished last block, done */
-      BADB}      /* got a data error--stuck here */
-    mode;               /* current inflate_block mode */
-
-  /* mode dependent information */
-  union {
-    uInt left;          /* if STORED, bytes left to copy */
-    struct {
-      uInt table;               /* table lengths (14 bits) */
-      uInt index;               /* index into blens (or border) */
-      uIntf *blens;             /* bit lengths of codes */
-      uInt bb;                  /* bit length tree depth */
-      inflate_huft *tb;         /* bit length decoding tree */
-      int nblens;		/* # elements allocated at blens */
-    } trees;            /* if DTREE, decoding info for trees */
-    struct {
-      inflate_huft *tl, *td;    /* trees to free */
-      inflate_codes_statef
-         *codes;
-    } decode;           /* if CODES, current state */
-  } sub;                /* submode */
-  uInt last;            /* true if this block is the last block */
-
-  /* mode independent information */
-  uInt bitk;            /* bits in bit buffer */
-  uLong bitb;           /* bit buffer */
-  Bytef *window;        /* sliding window */
-  Bytef *end;           /* one byte after sliding window */
-  Bytef *read;          /* window read pointer */
-  Bytef *write;         /* window write pointer */
-  check_func checkfn;   /* check function */
-  uLong check;          /* check on output */
-
-};
-
-
-/* defines for inflate input/output */
-/*   update pointers and return */
-#define UPDBITS {s->bitb=b;s->bitk=k;}
-#define UPDIN {z->avail_in=n;z->total_in+=p-z->next_in;z->next_in=p;}
-#define UPDOUT {s->write=q;}
-#define UPDATE {UPDBITS UPDIN UPDOUT}
-#define LEAVE {UPDATE return inflate_flush(s,z,r);}
-/*   get bytes and bits */
-#define LOADIN {p=z->next_in;n=z->avail_in;b=s->bitb;k=s->bitk;}
-#define NEEDBYTE {if(n)r=Z_OK;else LEAVE}
-#define NEXTBYTE (n--,*p++)
-#define NEEDBITS(j) {while(k<(j)){NEEDBYTE;b|=((uLong)NEXTBYTE)<<k;k+=8;}}
-#define DUMPBITS(j) {b>>=(j);k-=(j);}
-/*   output bytes */
-#define WAVAIL (q<s->read?s->read-q-1:s->end-q)
-#define LOADOUT {q=s->write;m=WAVAIL;}
-#define WRAP {if(q==s->end&&s->read!=s->window){q=s->window;m=WAVAIL;}}
-#define FLUSH {UPDOUT r=inflate_flush(s,z,r); LOADOUT}
-#define NEEDOUT {if(m==0){WRAP if(m==0){FLUSH WRAP if(m==0) LEAVE}}r=Z_OK;}
-#define OUTBYTE(a) {*q++=(Byte)(a);m--;}
-/*   load local pointers */
-#define LOAD {LOADIN LOADOUT}
-
-/* And'ing with mask[n] masks the lower n bits */
-local uInt inflate_mask[] = {
-    0x0000,
-    0x0001, 0x0003, 0x0007, 0x000f, 0x001f, 0x003f, 0x007f, 0x00ff,
-    0x01ff, 0x03ff, 0x07ff, 0x0fff, 0x1fff, 0x3fff, 0x7fff, 0xffff
-};
-
-/* copy as much as possible from the sliding window to the output area */
-local int inflate_flush OF((
-    inflate_blocks_statef *,
-    z_stream *,
-    int));
-
-/*+++++*/
-/* inffast.h -- header to use inffast.c
- * Copyright (C) 1995 Mark Adler
- * For conditions of distribution and use, see copyright notice in zlib.h
- */
-
-/* WARNING: this file should *not* be used by applications. It is
-   part of the implementation of the compression library and is
-   subject to change. Applications should only use zlib.h.
- */
-
-local int inflate_fast OF((
-    uInt,
-    uInt,
-    inflate_huft *,
-    inflate_huft *,
-    inflate_blocks_statef *,
-    z_stream *));
-
-
-/*+++++*/
-/* infblock.c -- interpret and process block types to last block
- * Copyright (C) 1995 Mark Adler
- * For conditions of distribution and use, see copyright notice in zlib.h
- */
-
-/* Table for deflate from PKZIP's appnote.txt. */
-local uInt border[] = { /* Order of the bit length code lengths */
-        16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15};
-
-/*
-   Notes beyond the 1.93a appnote.txt:
-
-   1. Distance pointers never point before the beginning of the output
-      stream.
-   2. Distance pointers can point back across blocks, up to 32k away.
-   3. There is an implied maximum of 7 bits for the bit length table and
-      15 bits for the actual data.
-   4. If only one code exists, then it is encoded using one bit.  (Zero
-      would be more efficient, but perhaps a little confusing.)  If two
-      codes exist, they are coded using one bit each (0 and 1).
-   5. There is no way of sending zero distance codes--a dummy must be
-      sent if there are none.  (History: a pre 2.0 version of PKZIP would
-      store blocks with no distance codes, but this was discovered to be
-      too harsh a criterion.)  Valid only for 1.93a.  2.04c does allow
-      zero distance codes, which is sent as one code of zero bits in
-      length.
-   6. There are up to 286 literal/length codes.  Code 256 represents the
-      end-of-block.  Note however that the static length tree defines
-      288 codes just to fill out the Huffman codes.  Codes 286 and 287
-      cannot be used though, since there is no length base or extra bits
-      defined for them.  Similarily, there are up to 30 distance codes.
-      However, static trees define 32 codes (all 5 bits) to fill out the
-      Huffman codes, but the last two had better not show up in the data.
-   7. Unzip can check dynamic Huffman blocks for complete code sets.
-      The exception is that a single code would not be complete (see #4).
-   8. The five bits following the block type is really the number of
-      literal codes sent minus 257.
-   9. Length codes 8,16,16 are interpreted as 13 length codes of 8 bits
-      (1+6+6).  Therefore, to output three times the length, you output
-      three codes (1+1+1), whereas to output four times the same length,
-      you only need two codes (1+3).  Hmm.
-  10. In the tree reconstruction algorithm, Code = Code + Increment
-      only if BitLength(i) is not zero.  (Pretty obvious.)
-  11. Correction: 4 Bits: # of Bit Length codes - 4     (4 - 19)
-  12. Note: length code 284 can represent 227-258, but length code 285
-      really is 258.  The last length deserves its own, short code
-      since it gets used a lot in very redundant files.  The length
-      258 is special since 258 - 3 (the min match length) is 255.
-  13. The literal/length and distance code bit lengths are read as a
-      single stream of lengths.  It is possible (and advantageous) for
-      a repeat code (16, 17, or 18) to go across the boundary between
-      the two sets of lengths.
- */
-
-
-local void inflate_blocks_reset(
-	inflate_blocks_statef *s,
-	z_stream *z,
-	uLongf *c
-)
-{
-  if (s->checkfn != Z_NULL)
-    *c = s->check;
-  if (s->mode == BTREE || s->mode == DTREE)
-    ZFREE(z, s->sub.trees.blens, s->sub.trees.nblens * sizeof(uInt));
-  if (s->mode == CODES)
-  {
-    inflate_codes_free(s->sub.decode.codes, z);
-    inflate_trees_free(s->sub.decode.td, z);
-    inflate_trees_free(s->sub.decode.tl, z);
-  }
-  s->mode = TYPE;
-  s->bitk = 0;
-  s->bitb = 0;
-  s->read = s->write = s->window;
-  if (s->checkfn != Z_NULL)
-    s->check = (*s->checkfn)(0L, Z_NULL, 0);
-  Trace((stderr, "inflate:   blocks reset\n"));
-}
-
-
-local inflate_blocks_statef *inflate_blocks_new(
-	z_stream *z,
-	check_func c,
-	uInt w
-)
-{
-  inflate_blocks_statef *s;
-
-  if ((s = (inflate_blocks_statef *)ZALLOC
-       (z,1,sizeof(struct inflate_blocks_state))) == Z_NULL)
-    return s;
-  if ((s->window = (Bytef *)ZALLOC(z, 1, w)) == Z_NULL)
-  {
-    ZFREE(z, s, sizeof(struct inflate_blocks_state));
-    return Z_NULL;
-  }
-  s->end = s->window + w;
-  s->checkfn = c;
-  s->mode = TYPE;
-  Trace((stderr, "inflate:   blocks allocated\n"));
-  inflate_blocks_reset(s, z, &s->check);
-  return s;
-}
-
-
-local int inflate_blocks(
-	inflate_blocks_statef *s,
-	z_stream *z,
-	int r
-)
-{
-  uInt t;               /* temporary storage */
-  uLong b;              /* bit buffer */
-  uInt k;               /* bits in bit buffer */
-  Bytef *p;             /* input data pointer */
-  uInt n;               /* bytes available there */
-  Bytef *q;             /* output window write pointer */
-  uInt m;               /* bytes to end of window or read pointer */
-
-  /* copy input/output information to locals (UPDATE macro restores) */
-  LOAD
-
-  /* process input based on current state */
-  while (1) switch (s->mode)
-  {
-    case TYPE:
-      NEEDBITS(3)
-      t = (uInt)b & 7;
-      s->last = t & 1;
-      switch (t >> 1)
-      {
-        case 0:                         /* stored */
-          Trace((stderr, "inflate:     stored block%s\n",
-                 s->last ? " (last)" : ""));
-          DUMPBITS(3)
-          t = k & 7;                    /* go to byte boundary */
-          DUMPBITS(t)
-          s->mode = LENS;               /* get length of stored block */
-          break;
-        case 1:                         /* fixed */
-          Trace((stderr, "inflate:     fixed codes block%s\n",
-                 s->last ? " (last)" : ""));
-          {
-            uInt bl, bd;
-            inflate_huft *tl, *td;
-
-            inflate_trees_fixed(&bl, &bd, &tl, &td);
-            s->sub.decode.codes = inflate_codes_new(bl, bd, tl, td, z);
-            if (s->sub.decode.codes == Z_NULL)
-            {
-              r = Z_MEM_ERROR;
-              LEAVE
-            }
-            s->sub.decode.tl = Z_NULL;  /* don't try to free these */
-            s->sub.decode.td = Z_NULL;
-          }
-          DUMPBITS(3)
-          s->mode = CODES;
-          break;
-        case 2:                         /* dynamic */
-          Trace((stderr, "inflate:     dynamic codes block%s\n",
-                 s->last ? " (last)" : ""));
-          DUMPBITS(3)
-          s->mode = TABLE;
-          break;
-        case 3:                         /* illegal */
-          DUMPBITS(3)
-          s->mode = BADB;
-          z->msg = "invalid block type";
-          r = Z_DATA_ERROR;
-          LEAVE
-      }
-      break;
-    case LENS:
-      NEEDBITS(32)
-      if (((~b) >> 16) != (b & 0xffff))
-      {
-        s->mode = BADB;
-        z->msg = "invalid stored block lengths";
-        r = Z_DATA_ERROR;
-        LEAVE
-      }
-      s->sub.left = (uInt)b & 0xffff;
-      b = k = 0;                      /* dump bits */
-      Tracev((stderr, "inflate:       stored length %u\n", s->sub.left));
-      s->mode = s->sub.left ? STORED : TYPE;
-      break;
-    case STORED:
-      if (n == 0)
-        LEAVE
-      NEEDOUT
-      t = s->sub.left;
-      if (t > n) t = n;
-      if (t > m) t = m;
-      zmemcpy(q, p, t);
-      p += t;  n -= t;
-      q += t;  m -= t;
-      if ((s->sub.left -= t) != 0)
-        break;
-      Tracev((stderr, "inflate:       stored end, %lu total out\n",
-              z->total_out + (q >= s->read ? q - s->read :
-              (s->end - s->read) + (q - s->window))));
-      s->mode = s->last ? DRY : TYPE;
-      break;
-    case TABLE:
-      NEEDBITS(14)
-      s->sub.trees.table = t = (uInt)b & 0x3fff;
-#ifndef PKZIP_BUG_WORKAROUND
-      if ((t & 0x1f) > 29 || ((t >> 5) & 0x1f) > 29)
-      {
-        s->mode = BADB;
-        z->msg = "too many length or distance symbols";
-        r = Z_DATA_ERROR;
-        LEAVE
-      }
-#endif
-      t = 258 + (t & 0x1f) + ((t >> 5) & 0x1f);
-      if (t < 19)
-        t = 19;
-      if ((s->sub.trees.blens = (uIntf*)ZALLOC(z, t, sizeof(uInt))) == Z_NULL)
-      {
-        r = Z_MEM_ERROR;
-        LEAVE
-      }
-      s->sub.trees.nblens = t;
-      DUMPBITS(14)
-      s->sub.trees.index = 0;
-      Tracev((stderr, "inflate:       table sizes ok\n"));
-      s->mode = BTREE;
-    case BTREE:
-      while (s->sub.trees.index < 4 + (s->sub.trees.table >> 10))
-      {
-        NEEDBITS(3)
-        s->sub.trees.blens[border[s->sub.trees.index++]] = (uInt)b & 7;
-        DUMPBITS(3)
-      }
-      while (s->sub.trees.index < 19)
-        s->sub.trees.blens[border[s->sub.trees.index++]] = 0;
-      s->sub.trees.bb = 7;
-      t = inflate_trees_bits(s->sub.trees.blens, &s->sub.trees.bb,
-                             &s->sub.trees.tb, z);
-      if (t != Z_OK)
-      {
-        r = t;
-        if (r == Z_DATA_ERROR)
-          s->mode = BADB;
-        LEAVE
-      }
-      s->sub.trees.index = 0;
-      Tracev((stderr, "inflate:       bits tree ok\n"));
-      s->mode = DTREE;
-    case DTREE:
-      while (t = s->sub.trees.table,
-             s->sub.trees.index < 258 + (t & 0x1f) + ((t >> 5) & 0x1f))
-      {
-        inflate_huft *h;
-        uInt i, j, c;
-
-        t = s->sub.trees.bb;
-        NEEDBITS(t)
-        h = s->sub.trees.tb + ((uInt)b & inflate_mask[t]);
-        t = h->word.what.Bits;
-        c = h->more.Base;
-        if (c < 16)
-        {
-          DUMPBITS(t)
-          s->sub.trees.blens[s->sub.trees.index++] = c;
-        }
-        else /* c == 16..18 */
-        {
-          i = c == 18 ? 7 : c - 14;
-          j = c == 18 ? 11 : 3;
-          NEEDBITS(t + i)
-          DUMPBITS(t)
-          j += (uInt)b & inflate_mask[i];
-          DUMPBITS(i)
-          i = s->sub.trees.index;
-          t = s->sub.trees.table;
-          if (i + j > 258 + (t & 0x1f) + ((t >> 5) & 0x1f) ||
-              (c == 16 && i < 1))
-          {
-            s->mode = BADB;
-            z->msg = "invalid bit length repeat";
-            r = Z_DATA_ERROR;
-            LEAVE
-          }
-          c = c == 16 ? s->sub.trees.blens[i - 1] : 0;
-          do {
-            s->sub.trees.blens[i++] = c;
-          } while (--j);
-          s->sub.trees.index = i;
-        }
-      }
-      inflate_trees_free(s->sub.trees.tb, z);
-      s->sub.trees.tb = Z_NULL;
-      {
-        uInt bl, bd;
-        inflate_huft *tl, *td;
-        inflate_codes_statef *c;
-
-        bl = 9;         /* must be <= 9 for lookahead assumptions */
-        bd = 6;         /* must be <= 9 for lookahead assumptions */
-        t = s->sub.trees.table;
-        t = inflate_trees_dynamic(257 + (t & 0x1f), 1 + ((t >> 5) & 0x1f),
-                                  s->sub.trees.blens, &bl, &bd, &tl, &td, z);
-        if (t != Z_OK)
-        {
-          if (t == (uInt)Z_DATA_ERROR)
-            s->mode = BADB;
-          r = t;
-          LEAVE
-        }
-        Tracev((stderr, "inflate:       trees ok\n"));
-        if ((c = inflate_codes_new(bl, bd, tl, td, z)) == Z_NULL)
-        {
-          inflate_trees_free(td, z);
-          inflate_trees_free(tl, z);
-          r = Z_MEM_ERROR;
-          LEAVE
-        }
-        ZFREE(z, s->sub.trees.blens, s->sub.trees.nblens * sizeof(uInt));
-        s->sub.decode.codes = c;
-        s->sub.decode.tl = tl;
-        s->sub.decode.td = td;
-      }
-      s->mode = CODES;
-    case CODES:
-      UPDATE
-      if ((r = inflate_codes(s, z, r)) != Z_STREAM_END)
-        return inflate_flush(s, z, r);
-      r = Z_OK;
-      inflate_codes_free(s->sub.decode.codes, z);
-      inflate_trees_free(s->sub.decode.td, z);
-      inflate_trees_free(s->sub.decode.tl, z);
-      LOAD
-      Tracev((stderr, "inflate:       codes end, %lu total out\n",
-              z->total_out + (q >= s->read ? q - s->read :
-              (s->end - s->read) + (q - s->window))));
-      if (!s->last)
-      {
-        s->mode = TYPE;
-        break;
-      }
-      if (k > 7)              /* return unused byte, if any */
-      {
-        Assert(k < 16, "inflate_codes grabbed too many bytes")
-        k -= 8;
-        n++;
-        p--;                    /* can always return one */
-      }
-      s->mode = DRY;
-    case DRY:
-      FLUSH
-      if (s->read != s->write)
-        LEAVE
-      s->mode = DONEB;
-    case DONEB:
-      r = Z_STREAM_END;
-      LEAVE
-    case BADB:
-      r = Z_DATA_ERROR;
-      LEAVE
-    default:
-      r = Z_STREAM_ERROR;
-      LEAVE
-  }
-}
-
-
-local int inflate_blocks_free(
-	inflate_blocks_statef *s,
-	z_stream *z,
-	uLongf *c
-)
-{
-  inflate_blocks_reset(s, z, c);
-  ZFREE(z, s->window, s->end - s->window);
-  ZFREE(z, s, sizeof(struct inflate_blocks_state));
-  Trace((stderr, "inflate:   blocks freed\n"));
-  return Z_OK;
-}
-
-/*
- * This subroutine adds the data at next_in/avail_in to the output history
- * without performing any output.  The output buffer must be "caught up";
- * i.e. no pending output (hence s->read equals s->write), and the state must
- * be BLOCKS (i.e. we should be willing to see the start of a series of
- * BLOCKS).  On exit, the output will also be caught up, and the checksum
- * will have been updated if need be.
- */
-local int inflate_addhistory(
-	inflate_blocks_statef *s,
-	z_stream *z
-)
-{
-    uLong b;              /* bit buffer */  /* NOT USED HERE */
-    uInt k;               /* bits in bit buffer */ /* NOT USED HERE */
-    uInt t;               /* temporary storage */
-    Bytef *p;             /* input data pointer */
-    uInt n;               /* bytes available there */
-    Bytef *q;             /* output window write pointer */
-    uInt m;               /* bytes to end of window or read pointer */
-
-    if (s->read != s->write)
-	return Z_STREAM_ERROR;
-    if (s->mode != TYPE)
-	return Z_DATA_ERROR;
-
-    /* we're ready to rock */
-    LOAD
-    /* while there is input ready, copy to output buffer, moving
-     * pointers as needed.
-     */
-    while (n) {
-	t = n;  /* how many to do */
-	/* is there room until end of buffer? */
-	if (t > m) t = m;
-	/* update check information */
-	if (s->checkfn != Z_NULL)
-	    s->check = (*s->checkfn)(s->check, q, t);
-	zmemcpy(q, p, t);
-	q += t;
-	p += t;
-	n -= t;
-	z->total_out += t;
-	s->read = q;    /* drag read pointer forward */
-/*      WRAP  */ 	/* expand WRAP macro by hand to handle s->read */
-	if (q == s->end) {
-	    s->read = q = s->window;
-	    m = WAVAIL;
-	}
-    }
-    UPDATE
-    return Z_OK;
-}
-
-
-/*
- * At the end of a Deflate-compressed PPP packet, we expect to have seen
- * a `stored' block type value but not the (zero) length bytes.
- */
-local int inflate_packet_flush(
-	inflate_blocks_statef *s
-)
-{
-    if (s->mode != LENS)
-	return Z_DATA_ERROR;
-    s->mode = TYPE;
-    return Z_OK;
-}
-
-
-/*+++++*/
-/* inftrees.c -- generate Huffman trees for efficient decoding
- * Copyright (C) 1995 Mark Adler
- * For conditions of distribution and use, see copyright notice in zlib.h
- */
-
-/* simplify the use of the inflate_huft type with some defines */
-#define base more.Base
-#define next more.Next
-#define exop word.what.Exop
-#define bits word.what.Bits
-
-
-local int huft_build OF((
-    uIntf *,            /* code lengths in bits */
-    uInt,               /* number of codes */
-    uInt,               /* number of "simple" codes */
-    uIntf *,            /* list of base values for non-simple codes */
-    uIntf *,            /* list of extra bits for non-simple codes */
-    inflate_huft * FAR*,/* result: starting table */
-    uIntf *,            /* maximum lookup bits (returns actual) */
-    z_stream *));       /* for zalloc function */
-
-local voidpf falloc OF((
-    voidpf,             /* opaque pointer (not used) */
-    uInt,               /* number of items */
-    uInt));             /* size of item */
-
-local void ffree OF((
-    voidpf q,           /* opaque pointer (not used) */
-    voidpf p,           /* what to free (not used) */
-    uInt n));		/* number of bytes (not used) */
-
-/* Tables for deflate from PKZIP's appnote.txt. */
-local uInt cplens[] = { /* Copy lengths for literal codes 257..285 */
-        3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31,
-        35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258, 0, 0};
-        /* actually lengths - 2; also see note #13 above about 258 */
-local uInt cplext[] = { /* Extra bits for literal codes 257..285 */
-        0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2,
-        3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 0, 192, 192}; /* 192==invalid */
-local uInt cpdist[] = { /* Copy offsets for distance codes 0..29 */
-        1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193,
-        257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145,
-        8193, 12289, 16385, 24577};
-local uInt cpdext[] = { /* Extra bits for distance codes */
-        0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6,
-        7, 7, 8, 8, 9, 9, 10, 10, 11, 11,
-        12, 12, 13, 13};
-
-/*
-   Huffman code decoding is performed using a multi-level table lookup.
-   The fastest way to decode is to simply build a lookup table whose
-   size is determined by the longest code.  However, the time it takes
-   to build this table can also be a factor if the data being decoded
-   is not very long.  The most common codes are necessarily the
-   shortest codes, so those codes dominate the decoding time, and hence
-   the speed.  The idea is you can have a shorter table that decodes the
-   shorter, more probable codes, and then point to subsidiary tables for
-   the longer codes.  The time it costs to decode the longer codes is
-   then traded against the time it takes to make longer tables.
-
-   This results of this trade are in the variables lbits and dbits
-   below.  lbits is the number of bits the first level table for literal/
-   length codes can decode in one step, and dbits is the same thing for
-   the distance codes.  Subsequent tables are also less than or equal to
-   those sizes.  These values may be adjusted either when all of the
-   codes are shorter than that, in which case the longest code length in
-   bits is used, or when the shortest code is *longer* than the requested
-   table size, in which case the length of the shortest code in bits is
-   used.
-
-   There are two different values for the two tables, since they code a
-   different number of possibilities each.  The literal/length table
-   codes 286 possible values, or in a flat code, a little over eight
-   bits.  The distance table codes 30 possible values, or a little less
-   than five bits, flat.  The optimum values for speed end up being
-   about one bit more than those, so lbits is 8+1 and dbits is 5+1.
-   The optimum values may differ though from machine to machine, and
-   possibly even between compilers.  Your mileage may vary.
- */
-
-
-/* If BMAX needs to be larger than 16, then h and x[] should be uLong. */
-#define BMAX 15         /* maximum bit length of any code */
-#define N_MAX 288       /* maximum number of codes in any set */
-
-#ifdef DEBUG_ZLIB
-  uInt inflate_hufts;
-#endif
-
-local int huft_build(
-	uIntf *b,               /* code lengths in bits (all assumed <= BMAX) */
-	uInt n,                 /* number of codes (assumed <= N_MAX) */
-	uInt s,                 /* number of simple-valued codes (0..s-1) */
-	uIntf *d,               /* list of base values for non-simple codes */
-	uIntf *e,               /* list of extra bits for non-simple codes */
-	inflate_huft * FAR *t,  /* result: starting table */
-	uIntf *m,               /* maximum lookup bits, returns actual */
-	z_stream *zs            /* for zalloc function */
-)
-/* Given a list of code lengths and a maximum table size, make a set of
-   tables to decode that set of codes.  Return Z_OK on success, Z_BUF_ERROR
-   if the given code set is incomplete (the tables are still built in this
-   case), Z_DATA_ERROR if the input is invalid (all zero length codes or an
-   over-subscribed set of lengths), or Z_MEM_ERROR if not enough memory. */
-{
-
-  uInt a;                       /* counter for codes of length k */
-  uInt c[BMAX+1];               /* bit length count table */
-  uInt f;                       /* i repeats in table every f entries */
-  int g;                        /* maximum code length */
-  int h;                        /* table level */
-  register uInt i;              /* counter, current code */
-  register uInt j;              /* counter */
-  register int k;               /* number of bits in current code */
-  int l;                        /* bits per table (returned in m) */
-  register uIntf *p;            /* pointer into c[], b[], or v[] */
-  inflate_huft *q;              /* points to current table */
-  struct inflate_huft_s r;      /* table entry for structure assignment */
-  inflate_huft *u[BMAX];        /* table stack */
-  uInt v[N_MAX];                /* values in order of bit length */
-  register int w;               /* bits before this table == (l * h) */
-  uInt x[BMAX+1];               /* bit offsets, then code stack */
-  uIntf *xp;                    /* pointer into x */
-  int y;                        /* number of dummy codes added */
-  uInt z;                       /* number of entries in current table */
-
-
-  /* Generate counts for each bit length */
-  p = c;
-#define C0 *p++ = 0;
-#define C2 C0 C0 C0 C0
-#define C4 C2 C2 C2 C2
-  C4                            /* clear c[]--assume BMAX+1 is 16 */
-  p = b;  i = n;
-  do {
-    c[*p++]++;                  /* assume all entries <= BMAX */
-  } while (--i);
-  if (c[0] == n)                /* null input--all zero length codes */
-  {
-    *t = (inflate_huft *)Z_NULL;
-    *m = 0;
-    return Z_OK;
-  }
-
-
-  /* Find minimum and maximum length, bound *m by those */
-  l = *m;
-  for (j = 1; j <= BMAX; j++)
-    if (c[j])
-      break;
-  k = j;                        /* minimum code length */
-  if ((uInt)l < j)
-    l = j;
-  for (i = BMAX; i; i--)
-    if (c[i])
-      break;
-  g = i;                        /* maximum code length */
-  if ((uInt)l > i)
-    l = i;
-  *m = l;
-
-
-  /* Adjust last length count to fill out codes, if needed */
-  for (y = 1 << j; j < i; j++, y <<= 1)
-    if ((y -= c[j]) < 0)
-      return Z_DATA_ERROR;
-  if ((y -= c[i]) < 0)
-    return Z_DATA_ERROR;
-  c[i] += y;
-
-
-  /* Generate starting offsets into the value table for each length */
-  x[1] = j = 0;
-  p = c + 1;  xp = x + 2;
-  while (--i) {                 /* note that i == g from above */
-    *xp++ = (j += *p++);
-  }
-
-
-  /* Make a table of values in order of bit lengths */
-  p = b;  i = 0;
-  do {
-    if ((j = *p++) != 0)
-      v[x[j]++] = i;
-  } while (++i < n);
-
-
-  /* Generate the Huffman codes and for each, make the table entries */
-  x[0] = i = 0;                 /* first Huffman code is zero */
-  p = v;                        /* grab values in bit order */
-  h = -1;                       /* no tables yet--level -1 */
-  w = -l;                       /* bits decoded == (l * h) */
-  u[0] = (inflate_huft *)Z_NULL;        /* just to keep compilers happy */
-  q = (inflate_huft *)Z_NULL;   /* ditto */
-  z = 0;                        /* ditto */
-
-  /* go through the bit lengths (k already is bits in shortest code) */
-  for (; k <= g; k++)
-  {
-    a = c[k];
-    while (a--)
-    {
-      /* here i is the Huffman code of length k bits for value *p */
-      /* make tables up to required level */
-      while (k > w + l)
-      {
-        h++;
-        w += l;                 /* previous table always l bits */
-
-        /* compute minimum size table less than or equal to l bits */
-        z = (z = g - w) > (uInt)l ? l : z;      /* table size upper limit */
-        if ((f = 1 << (j = k - w)) > a + 1)     /* try a k-w bit table */
-        {                       /* too few codes for k-w bit table */
-          f -= a + 1;           /* deduct codes from patterns left */
-          xp = c + k;
-          if (j < z)
-            while (++j < z)     /* try smaller tables up to z bits */
-            {
-              if ((f <<= 1) <= *++xp)
-                break;          /* enough codes to use up j bits */
-              f -= *xp;         /* else deduct codes from patterns */
-            }
-        }
-        z = 1 << j;             /* table entries for j-bit table */
-
-        /* allocate and link in new table */
-        if ((q = (inflate_huft *)ZALLOC
-             (zs,z + 1,sizeof(inflate_huft))) == Z_NULL)
-        {
-          if (h)
-            inflate_trees_free(u[0], zs);
-          return Z_MEM_ERROR;   /* not enough memory */
-        }
-	q->word.Nalloc = z + 1;
-#ifdef DEBUG_ZLIB
-        inflate_hufts += z + 1;
-#endif
-        *t = q + 1;             /* link to list for huft_free() */
-        *(t = &(q->next)) = Z_NULL;
-        u[h] = ++q;             /* table starts after link */
-
-        /* connect to last table, if there is one */
-        if (h)
-        {
-          x[h] = i;             /* save pattern for backing up */
-          r.bits = (Byte)l;     /* bits to dump before this table */
-          r.exop = (Byte)j;     /* bits in this table */
-          r.next = q;           /* pointer to this table */
-          j = i >> (w - l);     /* (get around Turbo C bug) */
-          u[h-1][j] = r;        /* connect to last table */
-        }
-      }
-
-      /* set up table entry in r */
-      r.bits = (Byte)(k - w);
-      if (p >= v + n)
-        r.exop = 128 + 64;      /* out of values--invalid code */
-      else if (*p < s)
-      {
-        r.exop = (Byte)(*p < 256 ? 0 : 32 + 64);     /* 256 is end-of-block */
-        r.base = *p++;          /* simple code is just the value */
-      }
-      else
-      {
-        r.exop = (Byte)e[*p - s] + 16 + 64; /* non-simple--look up in lists */
-        r.base = d[*p++ - s];
-      }
-
-      /* fill code-like entries with r */
-      f = 1 << (k - w);
-      for (j = i >> w; j < z; j += f)
-        q[j] = r;
-
-      /* backwards increment the k-bit code i */
-      for (j = 1 << (k - 1); i & j; j >>= 1)
-        i ^= j;
-      i ^= j;
-
-      /* backup over finished tables */
-      while ((i & ((1 << w) - 1)) != x[h])
-      {
-        h--;                    /* don't need to update q */
-        w -= l;
-      }
-    }
-  }
-
-
-  /* Return Z_BUF_ERROR if we were given an incomplete table */
-  return y != 0 && g != 1 ? Z_BUF_ERROR : Z_OK;
-}
-
-
-local int inflate_trees_bits(
-	uIntf *c,               /* 19 code lengths */
-	uIntf *bb,              /* bits tree desired/actual depth */
-	inflate_huft * FAR *tb, /* bits tree result */
-	z_stream *z             /* for zfree function */
-)
-{
-  int r;
-
-  r = huft_build(c, 19, 19, (uIntf*)Z_NULL, (uIntf*)Z_NULL, tb, bb, z);
-  if (r == Z_DATA_ERROR)
-    z->msg = "oversubscribed dynamic bit lengths tree";
-  else if (r == Z_BUF_ERROR)
-  {
-    inflate_trees_free(*tb, z);
-    z->msg = "incomplete dynamic bit lengths tree";
-    r = Z_DATA_ERROR;
-  }
-  return r;
-}
-
-
-local int inflate_trees_dynamic(
-	uInt nl,                /* number of literal/length codes */
-	uInt nd,                /* number of distance codes */
-	uIntf *c,               /* that many (total) code lengths */
-	uIntf *bl,              /* literal desired/actual bit depth */
-	uIntf *bd,              /* distance desired/actual bit depth */
-	inflate_huft * FAR *tl, /* literal/length tree result */
-	inflate_huft * FAR *td, /* distance tree result */
-	z_stream *z             /* for zfree function */
-)
-{
-  int r;
-
-  /* build literal/length tree */
-  if ((r = huft_build(c, nl, 257, cplens, cplext, tl, bl, z)) != Z_OK)
-  {
-    if (r == Z_DATA_ERROR)
-      z->msg = "oversubscribed literal/length tree";
-    else if (r == Z_BUF_ERROR)
-    {
-      inflate_trees_free(*tl, z);
-      z->msg = "incomplete literal/length tree";
-      r = Z_DATA_ERROR;
-    }
-    return r;
-  }
-
-  /* build distance tree */
-  if ((r = huft_build(c + nl, nd, 0, cpdist, cpdext, td, bd, z)) != Z_OK)
-  {
-    if (r == Z_DATA_ERROR)
-      z->msg = "oversubscribed literal/length tree";
-    else if (r == Z_BUF_ERROR) {
-#ifdef PKZIP_BUG_WORKAROUND
-      r = Z_OK;
-    }
-#else
-      inflate_trees_free(*td, z);
-      z->msg = "incomplete literal/length tree";
-      r = Z_DATA_ERROR;
-    }
-    inflate_trees_free(*tl, z);
-    return r;
-#endif
-  }
-
-  /* done */
-  return Z_OK;
-}
-
-
-/* build fixed tables only once--keep them here */
-local int fixed_lock = 0;
-local int fixed_built = 0;
-#define FIXEDH 530      /* number of hufts used by fixed tables */
-local uInt fixed_left = FIXEDH;
-local inflate_huft fixed_mem[FIXEDH];
-local uInt fixed_bl;
-local uInt fixed_bd;
-local inflate_huft *fixed_tl;
-local inflate_huft *fixed_td;
-
-
-local voidpf falloc(q, n, s)
-voidpf q;        /* opaque pointer (not used) */
-uInt n;         /* number of items */
-uInt s;         /* size of item */
-{
-  Assert(s == sizeof(inflate_huft) && n <= fixed_left,
-         "inflate_trees falloc overflow");
-  if (q) s++; /* to make some compilers happy */
-  fixed_left -= n;
-  return (voidpf)(fixed_mem + fixed_left);
-}
-
-
-local void ffree(q, p, n)
-voidpf q;
-voidpf p;
-uInt n;
-{
-  Assert(0, "inflate_trees ffree called!");
-  if (q) q = p; /* to make some compilers happy */
-}
-
-
-local int inflate_trees_fixed(
-	uIntf *bl,               /* literal desired/actual bit depth */
-	uIntf *bd,               /* distance desired/actual bit depth */
-	inflate_huft * FAR *tl,  /* literal/length tree result */
-	inflate_huft * FAR *td   /* distance tree result */
-)
-{
-  /* build fixed tables if not built already--lock out other instances */
-  while (++fixed_lock > 1)
-    fixed_lock--;
-  if (!fixed_built)
-  {
-    int k;              /* temporary variable */
-    unsigned c[288];    /* length list for huft_build */
-    z_stream z;         /* for falloc function */
-
-    /* set up fake z_stream for memory routines */
-    z.zalloc = falloc;
-    z.zfree = ffree;
-    z.opaque = Z_NULL;
-
-    /* literal table */
-    for (k = 0; k < 144; k++)
-      c[k] = 8;
-    for (; k < 256; k++)
-      c[k] = 9;
-    for (; k < 280; k++)
-      c[k] = 7;
-    for (; k < 288; k++)
-      c[k] = 8;
-    fixed_bl = 7;
-    huft_build(c, 288, 257, cplens, cplext, &fixed_tl, &fixed_bl, &z);
-
-    /* distance table */
-    for (k = 0; k < 30; k++)
-      c[k] = 5;
-    fixed_bd = 5;
-    huft_build(c, 30, 0, cpdist, cpdext, &fixed_td, &fixed_bd, &z);
-
-    /* done */
-    fixed_built = 1;
-  }
-  fixed_lock--;
-  *bl = fixed_bl;
-  *bd = fixed_bd;
-  *tl = fixed_tl;
-  *td = fixed_td;
-  return Z_OK;
-}
-
-
-local int inflate_trees_free(
-	inflate_huft *t,        /* table to free */
-	z_stream *z             /* for zfree function */
-)
-/* Free the malloc'ed tables built by huft_build(), which makes a linked
-   list of the tables it made, with the links in a dummy first entry of
-   each table. */
-{
-  register inflate_huft *p, *q;
-
-  /* Go through linked list, freeing from the malloced (t[-1]) address. */
-  p = t;
-  while (p != Z_NULL)
-  {
-    q = (--p)->next;
-    ZFREE(z, p, p->word.Nalloc * sizeof(inflate_huft));
-    p = q;
-  }
-  return Z_OK;
-}
-
-/*+++++*/
-/* infcodes.c -- process literals and length/distance pairs
- * Copyright (C) 1995 Mark Adler
- * For conditions of distribution and use, see copyright notice in zlib.h
- */
-
-/* simplify the use of the inflate_huft type with some defines */
-#define base more.Base
-#define next more.Next
-#define exop word.what.Exop
-#define bits word.what.Bits
-
-/* inflate codes private state */
-struct inflate_codes_state {
-
-  /* mode */
-  enum {        /* waiting for "i:"=input, "o:"=output, "x:"=nothing */
-      START,    /* x: set up for LEN */
-      LEN,      /* i: get length/literal/eob next */
-      LENEXT,   /* i: getting length extra (have base) */
-      DIST,     /* i: get distance next */
-      DISTEXT,  /* i: getting distance extra */
-      COPY,     /* o: copying bytes in window, waiting for space */
-      LIT,      /* o: got literal, waiting for output space */
-      WASH,     /* o: got eob, possibly still output waiting */
-      END,      /* x: got eob and all data flushed */
-      BADCODE}  /* x: got error */
-    mode;               /* current inflate_codes mode */
-
-  /* mode dependent information */
-  uInt len;
-  union {
-    struct {
-      inflate_huft *tree;       /* pointer into tree */
-      uInt need;                /* bits needed */
-    } code;             /* if LEN or DIST, where in tree */
-    uInt lit;           /* if LIT, literal */
-    struct {
-      uInt get;                 /* bits to get for extra */
-      uInt dist;                /* distance back to copy from */
-    } copy;             /* if EXT or COPY, where and how much */
-  } sub;                /* submode */
-
-  /* mode independent information */
-  Byte lbits;           /* ltree bits decoded per branch */
-  Byte dbits;           /* dtree bits decoder per branch */
-  inflate_huft *ltree;          /* literal/length/eob tree */
-  inflate_huft *dtree;          /* distance tree */
-
-};
-
-
-local inflate_codes_statef *inflate_codes_new(
-	uInt bl,
-	uInt bd,
-	inflate_huft *tl,
-	inflate_huft *td,
-	z_stream *z
-)
-{
-  inflate_codes_statef *c;
-
-  if ((c = (inflate_codes_statef *)
-       ZALLOC(z,1,sizeof(struct inflate_codes_state))) != Z_NULL)
-  {
-    c->mode = START;
-    c->lbits = (Byte)bl;
-    c->dbits = (Byte)bd;
-    c->ltree = tl;
-    c->dtree = td;
-    Tracev((stderr, "inflate:       codes new\n"));
-  }
-  return c;
-}
-
-
-local int inflate_codes(
-	inflate_blocks_statef *s,
-	z_stream *z,
-	int r
-)
-{
-  uInt j;               /* temporary storage */
-  inflate_huft *t;      /* temporary pointer */
-  uInt e;               /* extra bits or operation */
-  uLong b;              /* bit buffer */
-  uInt k;               /* bits in bit buffer */
-  Bytef *p;             /* input data pointer */
-  uInt n;               /* bytes available there */
-  Bytef *q;             /* output window write pointer */
-  uInt m;               /* bytes to end of window or read pointer */
-  Bytef *f;             /* pointer to copy strings from */
-  inflate_codes_statef *c = s->sub.decode.codes;  /* codes state */
-
-  /* copy input/output information to locals (UPDATE macro restores) */
-  LOAD
-
-  /* process input and output based on current state */
-  while (1) switch (c->mode)
-  {             /* waiting for "i:"=input, "o:"=output, "x:"=nothing */
-    case START:         /* x: set up for LEN */
-#ifndef SLOW
-      if (m >= 258 && n >= 10)
-      {
-        UPDATE
-        r = inflate_fast(c->lbits, c->dbits, c->ltree, c->dtree, s, z);
-        LOAD
-        if (r != Z_OK)
-        {
-          c->mode = r == Z_STREAM_END ? WASH : BADCODE;
-          break;
-        }
-      }
-#endif /* !SLOW */
-      c->sub.code.need = c->lbits;
-      c->sub.code.tree = c->ltree;
-      c->mode = LEN;
-    case LEN:           /* i: get length/literal/eob next */
-      j = c->sub.code.need;
-      NEEDBITS(j)
-      t = c->sub.code.tree + ((uInt)b & inflate_mask[j]);
-      DUMPBITS(t->bits)
-      e = (uInt)(t->exop);
-      if (e == 0)               /* literal */
-      {
-        c->sub.lit = t->base;
-        Tracevv((stderr, t->base >= 0x20 && t->base < 0x7f ?
-                 "inflate:         literal '%c'\n" :
-                 "inflate:         literal 0x%02x\n", t->base));
-        c->mode = LIT;
-        break;
-      }
-      if (e & 16)               /* length */
-      {
-        c->sub.copy.get = e & 15;
-        c->len = t->base;
-        c->mode = LENEXT;
-        break;
-      }
-      if ((e & 64) == 0)        /* next table */
-      {
-        c->sub.code.need = e;
-        c->sub.code.tree = t->next;
-        break;
-      }
-      if (e & 32)               /* end of block */
-      {
-        Tracevv((stderr, "inflate:         end of block\n"));
-        c->mode = WASH;
-        break;
-      }
-      c->mode = BADCODE;        /* invalid code */
-      z->msg = "invalid literal/length code";
-      r = Z_DATA_ERROR;
-      LEAVE
-    case LENEXT:        /* i: getting length extra (have base) */
-      j = c->sub.copy.get;
-      NEEDBITS(j)
-      c->len += (uInt)b & inflate_mask[j];
-      DUMPBITS(j)
-      c->sub.code.need = c->dbits;
-      c->sub.code.tree = c->dtree;
-      Tracevv((stderr, "inflate:         length %u\n", c->len));
-      c->mode = DIST;
-    case DIST:          /* i: get distance next */
-      j = c->sub.code.need;
-      NEEDBITS(j)
-      t = c->sub.code.tree + ((uInt)b & inflate_mask[j]);
-      DUMPBITS(t->bits)
-      e = (uInt)(t->exop);
-      if (e & 16)               /* distance */
-      {
-        c->sub.copy.get = e & 15;
-        c->sub.copy.dist = t->base;
-        c->mode = DISTEXT;
-        break;
-      }
-      if ((e & 64) == 0)        /* next table */
-      {
-        c->sub.code.need = e;
-        c->sub.code.tree = t->next;
-        break;
-      }
-      c->mode = BADCODE;        /* invalid code */
-      z->msg = "invalid distance code";
-      r = Z_DATA_ERROR;
-      LEAVE
-    case DISTEXT:       /* i: getting distance extra */
-      j = c->sub.copy.get;
-      NEEDBITS(j)
-      c->sub.copy.dist += (uInt)b & inflate_mask[j];
-      DUMPBITS(j)
-      Tracevv((stderr, "inflate:         distance %u\n", c->sub.copy.dist));
-      c->mode = COPY;
-    case COPY:          /* o: copying bytes in window, waiting for space */
-#ifndef __TURBOC__ /* Turbo C bug for following expression */
-      f = (uInt)(q - s->window) < c->sub.copy.dist ?
-          s->end - (c->sub.copy.dist - (q - s->window)) :
-          q - c->sub.copy.dist;
-#else
-      f = q - c->sub.copy.dist;
-      if ((uInt)(q - s->window) < c->sub.copy.dist)
-        f = s->end - (c->sub.copy.dist - (q - s->window));
-#endif
-      while (c->len)
-      {
-        NEEDOUT
-        OUTBYTE(*f++)
-        if (f == s->end)
-          f = s->window;
-        c->len--;
-      }
-      c->mode = START;
-      break;
-    case LIT:           /* o: got literal, waiting for output space */
-      NEEDOUT
-      OUTBYTE(c->sub.lit)
-      c->mode = START;
-      break;
-    case WASH:          /* o: got eob, possibly more output */
-      FLUSH
-      if (s->read != s->write)
-        LEAVE
-      c->mode = END;
-    case END:
-      r = Z_STREAM_END;
-      LEAVE
-    case BADCODE:       /* x: got error */
-      r = Z_DATA_ERROR;
-      LEAVE
-    default:
-      r = Z_STREAM_ERROR;
-      LEAVE
-  }
-}
-
-
-local void inflate_codes_free(
-	inflate_codes_statef *c,
-	z_stream *z
-)
-{
-  ZFREE(z, c, sizeof(struct inflate_codes_state));
-  Tracev((stderr, "inflate:       codes free\n"));
-}
-
-/*+++++*/
-/* inflate_util.c -- data and routines common to blocks and codes
- * Copyright (C) 1995 Mark Adler
- * For conditions of distribution and use, see copyright notice in zlib.h
- */
-
-/* copy as much as possible from the sliding window to the output area */
-local int inflate_flush(
-	inflate_blocks_statef *s,
-	z_stream *z,
-	int r
-)
-{
-  uInt n;
-  Bytef *p, *q;
-
-  /* local copies of source and destination pointers */
-  p = z->next_out;
-  q = s->read;
-
-  /* compute number of bytes to copy as far as end of window */
-  n = (uInt)((q <= s->write ? s->write : s->end) - q);
-  if (n > z->avail_out) n = z->avail_out;
-  if (n && r == Z_BUF_ERROR) r = Z_OK;
-
-  /* update counters */
-  z->avail_out -= n;
-  z->total_out += n;
-
-  /* update check information */
-  if (s->checkfn != Z_NULL)
-    s->check = (*s->checkfn)(s->check, q, n);
-
-  /* copy as far as end of window */
-  zmemcpy(p, q, n);
-  p += n;
-  q += n;
-
-  /* see if more to copy at beginning of window */
-  if (q == s->end)
-  {
-    /* wrap pointers */
-    q = s->window;
-    if (s->write == s->end)
-      s->write = s->window;
-
-    /* compute bytes to copy */
-    n = (uInt)(s->write - q);
-    if (n > z->avail_out) n = z->avail_out;
-    if (n && r == Z_BUF_ERROR) r = Z_OK;
-
-    /* update counters */
-    z->avail_out -= n;
-    z->total_out += n;
-
-    /* update check information */
-    if (s->checkfn != Z_NULL)
-      s->check = (*s->checkfn)(s->check, q, n);
-
-    /* copy */
-    zmemcpy(p, q, n);
-    p += n;
-    q += n;
-  }
-
-  /* update pointers */
-  z->next_out = p;
-  s->read = q;
-
-  /* done */
-  return r;
-}
-
-
-/*+++++*/
-/* inffast.c -- process literals and length/distance pairs fast
- * Copyright (C) 1995 Mark Adler
- * For conditions of distribution and use, see copyright notice in zlib.h
- */
-
-/* simplify the use of the inflate_huft type with some defines */
-#define base more.Base
-#define next more.Next
-#define exop word.what.Exop
-#define bits word.what.Bits
-
-/* macros for bit input with no checking and for returning unused bytes */
-#define GRABBITS(j) {while(k<(j)){b|=((uLong)NEXTBYTE)<<k;k+=8;}}
-#define UNGRAB {n+=(c=k>>3);p-=c;k&=7;}
-
-/* Called with number of bytes left to write in window at least 258
-   (the maximum string length) and number of input bytes available
-   at least ten.  The ten bytes are six bytes for the longest length/
-   distance pair plus four bytes for overloading the bit buffer. */
-
-local int inflate_fast(
-	uInt bl,
-	uInt bd,
-	inflate_huft *tl,
-	inflate_huft *td,
-	inflate_blocks_statef *s,
-	z_stream *z
-)
-{
-  inflate_huft *t;      /* temporary pointer */
-  uInt e;               /* extra bits or operation */
-  uLong b;              /* bit buffer */
-  uInt k;               /* bits in bit buffer */
-  Bytef *p;             /* input data pointer */
-  uInt n;               /* bytes available there */
-  Bytef *q;             /* output window write pointer */
-  uInt m;               /* bytes to end of window or read pointer */
-  uInt ml;              /* mask for literal/length tree */
-  uInt md;              /* mask for distance tree */
-  uInt c;               /* bytes to copy */
-  uInt d;               /* distance back to copy from */
-  Bytef *r;             /* copy source pointer */
-
-  /* load input, output, bit values */
-  LOAD
-
-  /* initialize masks */
-  ml = inflate_mask[bl];
-  md = inflate_mask[bd];
-
-  /* do until not enough input or output space for fast loop */
-  do {                          /* assume called with m >= 258 && n >= 10 */
-    /* get literal/length code */
-    GRABBITS(20)                /* max bits for literal/length code */
-    if ((e = (t = tl + ((uInt)b & ml))->exop) == 0)
-    {
-      DUMPBITS(t->bits)
-      Tracevv((stderr, t->base >= 0x20 && t->base < 0x7f ?
-                "inflate:         * literal '%c'\n" :
-                "inflate:         * literal 0x%02x\n", t->base));
-      *q++ = (Byte)t->base;
-      m--;
-      continue;
-    }
-    do {
-      DUMPBITS(t->bits)
-      if (e & 16)
-      {
-        /* get extra bits for length */
-        e &= 15;
-        c = t->base + ((uInt)b & inflate_mask[e]);
-        DUMPBITS(e)
-        Tracevv((stderr, "inflate:         * length %u\n", c));
-
-        /* decode distance base of block to copy */
-        GRABBITS(15);           /* max bits for distance code */
-        e = (t = td + ((uInt)b & md))->exop;
-        do {
-          DUMPBITS(t->bits)
-          if (e & 16)
-          {
-            /* get extra bits to add to distance base */
-            e &= 15;
-            GRABBITS(e)         /* get extra bits (up to 13) */
-            d = t->base + ((uInt)b & inflate_mask[e]);
-            DUMPBITS(e)
-            Tracevv((stderr, "inflate:         * distance %u\n", d));
-
-            /* do the copy */
-            m -= c;
-            if ((uInt)(q - s->window) >= d)     /* offset before dest */
-            {                                   /*  just copy */
-              r = q - d;
-              *q++ = *r++;  c--;        /* minimum count is three, */
-              *q++ = *r++;  c--;        /*  so unroll loop a little */
-            }
-            else                        /* else offset after destination */
-            {
-              e = d - (q - s->window);  /* bytes from offset to end */
-              r = s->end - e;           /* pointer to offset */
-              if (c > e)                /* if source crosses, */
-              {
-                c -= e;                 /* copy to end of window */
-                do {
-                  *q++ = *r++;
-                } while (--e);
-                r = s->window;          /* copy rest from start of window */
-              }
-            }
-            do {                        /* copy all or what's left */
-              *q++ = *r++;
-            } while (--c);
-            break;
-          }
-          else if ((e & 64) == 0)
-            e = (t = t->next + ((uInt)b & inflate_mask[e]))->exop;
-          else
-          {
-            z->msg = "invalid distance code";
-            UNGRAB
-            UPDATE
-            return Z_DATA_ERROR;
-          }
-        } while (1);
-        break;
-      }
-      if ((e & 64) == 0)
-      {
-        if ((e = (t = t->next + ((uInt)b & inflate_mask[e]))->exop) == 0)
-        {
-          DUMPBITS(t->bits)
-          Tracevv((stderr, t->base >= 0x20 && t->base < 0x7f ?
-                    "inflate:         * literal '%c'\n" :
-                    "inflate:         * literal 0x%02x\n", t->base));
-          *q++ = (Byte)t->base;
-          m--;
-          break;
-        }
-      }
-      else if (e & 32)
-      {
-        Tracevv((stderr, "inflate:         * end of block\n"));
-        UNGRAB
-        UPDATE
-        return Z_STREAM_END;
-      }
-      else
-      {
-        z->msg = "invalid literal/length code";
-        UNGRAB
-        UPDATE
-        return Z_DATA_ERROR;
-      }
-    } while (1);
-  } while (m >= 258 && n >= 10);
-
-  /* not enough input or output--restore pointers and return */
-  UNGRAB
-  UPDATE
-  return Z_OK;
-}
-
-
-/*+++++*/
-/* zutil.c -- target dependent utility functions for the compression library
- * Copyright (C) 1995 Jean-loup Gailly.
- * For conditions of distribution and use, see copyright notice in zlib.h
- */
-
-/* From: zutil.c,v 1.8 1995/05/03 17:27:12 jloup Exp */
-
-char *zlib_version = ZLIB_VERSION;
-
-char *z_errmsg[] = {
-"stream end",          /* Z_STREAM_END    1 */
-"",                    /* Z_OK            0 */
-"file error",          /* Z_ERRNO        (-1) */
-"stream error",        /* Z_STREAM_ERROR (-2) */
-"data error",          /* Z_DATA_ERROR   (-3) */
-"insufficient memory", /* Z_MEM_ERROR    (-4) */
-"buffer error",        /* Z_BUF_ERROR    (-5) */
-""};
-
-
-/*+++++*/
-/* adler32.c -- compute the Adler-32 checksum of a data stream
- * Copyright (C) 1995 Mark Adler
- * For conditions of distribution and use, see copyright notice in zlib.h
- */
-
-/* From: adler32.c,v 1.6 1995/05/03 17:27:08 jloup Exp */
-
-#define BASE 65521L /* largest prime smaller than 65536 */
-#define NMAX 5552
-/* NMAX is the largest n such that 255n(n+1)/2 + (n+1)(BASE-1) <= 2^32-1 */
-
-#define DO1(buf)  {s1 += *buf++; s2 += s1;}
-#define DO2(buf)  DO1(buf); DO1(buf);
-#define DO4(buf)  DO2(buf); DO2(buf);
-#define DO8(buf)  DO4(buf); DO4(buf);
-#define DO16(buf) DO8(buf); DO8(buf);
-
-/* ========================================================================= */
-uLong adler32(adler, buf, len)
-    uLong adler;
-    Bytef *buf;
-    uInt len;
-{
-    unsigned long s1 = adler & 0xffff;
-    unsigned long s2 = (adler >> 16) & 0xffff;
-    int k;
-
-    if (buf == Z_NULL) return 1L;
-
-    while (len > 0) {
-        k = len < NMAX ? len : NMAX;
-        len -= k;
-        while (k >= 16) {
-            DO16(buf);
-            k -= 16;
-        }
-        if (k != 0) do {
-            DO1(buf);
-        } while (--k);
-        s1 %= BASE;
-        s2 %= BASE;
-    }
-    return (s2 << 16) | s1;
-}
diff -Nru a/arch/ppc/boot/openfirmware/coffmain.c b/arch/ppc/boot/openfirmware/coffmain.c
--- a/arch/ppc/boot/openfirmware/coffmain.c	2004-10-18 14:56:32 -07:00
+++ b/arch/ppc/boot/openfirmware/coffmain.c	2004-10-18 14:56:32 -07:00
@@ -12,7 +12,6 @@
 
 #include "nonstdio.h"
 #include "of1275.h"
-#include "zlib.h"
 
 /* Passed from the linker */
 extern char __image_begin, __image_end;
diff -Nru a/arch/ppc/boot/openfirmware/common.c b/arch/ppc/boot/openfirmware/common.c
--- a/arch/ppc/boot/openfirmware/common.c	2004-10-18 14:56:49 -07:00
+++ b/arch/ppc/boot/openfirmware/common.c	2004-10-18 14:56:49 -07:00
@@ -7,10 +7,10 @@
  * 2 of the License, or (at your option) any later version.
  */
 
-#include "zlib.h"
 #include "nonstdio.h"
 #include "of1275.h"
 #include <linux/string.h>
+#include <linux/zlib.h>
 #include <asm/bootinfo.h>
 #include <asm/page.h>
 
@@ -30,12 +30,11 @@
 
 static struct memchunk *freechunks;
 
-static void *zalloc(void *x, unsigned items, unsigned size)
+static void *zalloc(unsigned size)
 {
     void *p;
     struct memchunk **mpp, *mp;
 
-    size *= items;
     size = (size + 7) & -8;
     heap_use += size;
     if (heap_use > heap_max)
@@ -57,74 +56,57 @@
     return p;
 }
 
-static void zfree(void *x, void *addr, unsigned nb)
-{
-    struct memchunk *mp = addr;
-
-    nb = (nb + 7) & -8;
-    heap_use -= nb;
-    if (avail_ram == addr + nb) {
-	avail_ram = addr;
-	return;
-    }
-    mp->size = nb;
-    mp->next = freechunks;
-    freechunks = mp;
-}
-
 #define HEAD_CRC	2
 #define EXTRA_FIELD	4
 #define ORIG_NAME	8
 #define COMMENT		0x10
 #define RESERVED	0xe0
 
-#define DEFLATED	8
-
 void gunzip(void *dst, int dstlen, unsigned char *src, int *lenp)
 {
-    z_stream s;
-    int r, i, flags;
+	z_stream s;
+	int r, i, flags;
 
-    /* skip header */
-    i = 10;
-    flags = src[3];
-    if (src[2] != DEFLATED || (flags & RESERVED) != 0) {
-	printf("bad gzipped data\n\r");
-	exit();
-    }
-    if ((flags & EXTRA_FIELD) != 0)
-	i = 12 + src[10] + (src[11] << 8);
-    if ((flags & ORIG_NAME) != 0)
-	while (src[i++] != 0)
-	    ;
-    if ((flags & COMMENT) != 0)
-	while (src[i++] != 0)
-	    ;
-    if ((flags & HEAD_CRC) != 0)
-	i += 2;
-    if (i >= *lenp) {
-	printf("gunzip: ran out of data in header\n\r");
-	exit();
-    }
+	/* skip header */
+	i = 10;
+	flags = src[3];
+	if (src[2] != Z_DEFLATED || (flags & RESERVED) != 0) {
+		printf("bad gzipped data\n\r");
+		exit();
+	}
+	if ((flags & EXTRA_FIELD) != 0)
+		i = 12 + src[10] + (src[11] << 8);
+	if ((flags & ORIG_NAME) != 0)
+		while (src[i++] != 0)
+			;
+	if ((flags & COMMENT) != 0)
+		while (src[i++] != 0)
+			;
+	if ((flags & HEAD_CRC) != 0)
+		i += 2;
+	if (i >= *lenp) {
+		printf("gunzip: ran out of data in header\n\r");
+		exit();
+	}
 
-    s.zalloc = zalloc;
-    s.zfree = zfree;
-    r = inflateInit2(&s, -MAX_WBITS);
-    if (r != Z_OK) {
-	printf("inflateInit2 returned %d\n\r", r);
-	exit();
-    }
-    s.next_in = src + i;
-    s.avail_in = *lenp - i;
-    s.next_out = dst;
-    s.avail_out = dstlen;
-    r = inflate(&s, Z_FINISH);
-    if (r != Z_OK && r != Z_STREAM_END) {
-	printf("inflate returned %d msg: %s\n\r", r, s.msg);
-	exit();
-    }
-    *lenp = s.next_out - (unsigned char *) dst;
-    inflateEnd(&s);
+	/* Initialize ourself. */
+	s.workspace = zalloc(zlib_inflate_workspacesize());
+	r = zlib_inflateInit2(&s, -MAX_WBITS);
+	if (r != Z_OK) {
+		printf("zlib_inflateInit2 returned %d\n\r", r);
+		exit();
+	}
+	s.next_in = src + i;
+	s.avail_in = *lenp - i;
+	s.next_out = dst;
+	s.avail_out = dstlen;
+	r = zlib_inflate(&s, Z_FINISH);
+	if (r != Z_OK && r != Z_STREAM_END) {
+		printf("inflate returned %d msg: %s\n\r", r, s.msg);
+		exit();
+	}
+	*lenp = s.next_out - (unsigned char *) dst;
+	zlib_inflateEnd(&s);
 }
 
 /* Make a bi_rec in OF.  We need to be passed a name for BI_BOOTLOADER_ID,
diff -Nru a/arch/ppc/boot/openfirmware/misc.S b/arch/ppc/boot/openfirmware/misc.S
--- a/arch/ppc/boot/openfirmware/misc.S	2004-10-18 14:56:33 -07:00
+++ b/arch/ppc/boot/openfirmware/misc.S	2004-10-18 14:56:33 -07:00
@@ -16,7 +16,7 @@
 setup_bats:
 	mfpvr	5
 	rlwinm	5,5,16,16,31		/* r3 = 1 for 601, 4 for 604 */
-	cmpi	0,5,1
+	cmpwi	0,5,1
 	li	0,0
 	bne	4f
 	mtibatl	3,0			/* invalidate BAT first */
diff -Nru a/arch/ppc/boot/simple/Makefile b/arch/ppc/boot/simple/Makefile
--- a/arch/ppc/boot/simple/Makefile	2004-10-18 14:55:53 -07:00
+++ b/arch/ppc/boot/simple/Makefile	2004-10-18 14:55:53 -07:00
@@ -64,6 +64,7 @@
 zimageinitrd-$(CONFIG_OCOTEA)		:= zImage.initrd-TREE
          end-$(CONFIG_OCOTEA)		:= ocotea
   entrypoint-$(CONFIG_OCOTEA)		:= 0x01000000
+     extra.o-$(CONFIG_OCOTEA)		:= pibs.o
 
      extra.o-$(CONFIG_EV64260)		:= direct.o misc-ev64260.o
          end-$(CONFIG_EV64260)		:= ev64260
@@ -73,7 +74,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 +90,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 +101,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	2004-10-18 14:56:49 -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-10-18 14:57:21 -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	2004-10-18 14:56:29 -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-10-18 14:56:16 -07:00
+++ b/arch/ppc/boot/simple/misc-embedded.c	2004-10-18 14:56:16 -07:00
@@ -22,7 +22,6 @@
 #endif
 
 #include "nonstdio.h"
-#include "zlib.h"
 
 /* The linker tells us where the image is. */
 extern char __image_begin, __image_end;
@@ -71,6 +70,14 @@
 extern void flush_instruction_cache(void);
 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-10-18 14:55:54 -07:00
+++ b/arch/ppc/boot/simple/misc-prep.c	2004-10-18 14:55:54 -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-10-18 14:56:32 -07:00
+++ b/arch/ppc/boot/simple/misc-spruce.c	2004-10-18 14:56:32 -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-10-18 14:56:49 -07:00
+++ b/arch/ppc/boot/simple/misc.c	2004-10-18 14:56:49 -07:00
@@ -29,7 +29,6 @@
 #include <asm/reg.h>
 
 #include "nonstdio.h"
-#include "zlib.h"
 
 /* Default cmdline */
 #ifdef CONFIG_CMDLINE
@@ -49,7 +48,9 @@
  * Val Henson has requested that Gemini doesn't wait for the
  * user to edit the cmdline or not.
  */
-#if (defined(CONFIG_SERIAL_8250_CONSOLE) || defined(CONFIG_VGA_CONSOLE)) \
+#if (defined(CONFIG_SERIAL_8250_CONSOLE) \
+	|| defined(CONFIG_VGA_CONSOLE) \
+	|| defined(CONFIG_SERIAL_MPC52xx_CONSOLE)) \
 	&& !defined(CONFIG_GEMINI)
 #define INTERACTIVE_CONSOLE	1
 #endif
@@ -95,9 +96,8 @@
 #endif
 	char *cp;
 	struct bi_record *rec;
-	unsigned long initrd_loc, TotalMemory = 0;
+	unsigned long initrd_loc = 0, TotalMemory = 0;
 
-	serial_fixups();
 #ifdef CONFIG_SERIAL_8250_CONSOLE
 	com_port = serial_init(0, NULL);
 #endif
@@ -221,7 +221,7 @@
 	puts("\n");
 
 	puts("Uncompressing Linux...");
-	gunzip(NULL, 0x400000, zimage_start, &zimage_size);
+	gunzip(0x0, 0x400000, zimage_start, &zimage_size);
 	puts("done.\n");
 
 	/* get the bi_rec address */
@@ -268,10 +268,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/pibs.c b/arch/ppc/boot/simple/pibs.c
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/arch/ppc/boot/simple/pibs.c	2004-10-18 14:57:23 -07:00
@@ -0,0 +1,101 @@
+/*
+ * 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/types.h>
+#include <linux/config.h>
+#include <linux/string.h>
+#include <linux/ctype.h>
+#include <asm/ppcboot.h>
+#include <platforms/4xx/ocotea.h>
+
+extern unsigned long decompress_kernel(unsigned long load_addr, int num_words,
+				       unsigned long cksum);
+
+/* We need to make sure that this is before the images to ensure
+ * that it's in a mapped location. - Tom */
+bd_t hold_resid_buf __attribute__ ((__section__ (".data.boot")));
+bd_t *hold_residual = &hold_resid_buf;
+
+/* String functions lifted from lib/vsprintf.c and lib/ctype.c */
+unsigned char _ctype[] = {
+_C,_C,_C,_C,_C,_C,_C,_C,			/* 0-7 */
+_C,_C|_S,_C|_S,_C|_S,_C|_S,_C|_S,_C,_C,		/* 8-15 */
+_C,_C,_C,_C,_C,_C,_C,_C,			/* 16-23 */
+_C,_C,_C,_C,_C,_C,_C,_C,			/* 24-31 */
+_S|_SP,_P,_P,_P,_P,_P,_P,_P,			/* 32-39 */
+_P,_P,_P,_P,_P,_P,_P,_P,			/* 40-47 */
+_D,_D,_D,_D,_D,_D,_D,_D,			/* 48-55 */
+_D,_D,_P,_P,_P,_P,_P,_P,			/* 56-63 */
+_P,_U|_X,_U|_X,_U|_X,_U|_X,_U|_X,_U|_X,_U,	/* 64-71 */
+_U,_U,_U,_U,_U,_U,_U,_U,			/* 72-79 */
+_U,_U,_U,_U,_U,_U,_U,_U,			/* 80-87 */
+_U,_U,_U,_P,_P,_P,_P,_P,			/* 88-95 */
+_P,_L|_X,_L|_X,_L|_X,_L|_X,_L|_X,_L|_X,_L,	/* 96-103 */
+_L,_L,_L,_L,_L,_L,_L,_L,			/* 104-111 */
+_L,_L,_L,_L,_L,_L,_L,_L,			/* 112-119 */
+_L,_L,_L,_P,_P,_P,_P,_C,			/* 120-127 */
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,		/* 128-143 */
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,		/* 144-159 */
+_S|_SP,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,   /* 160-175 */
+_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,       /* 176-191 */
+_U,_U,_U,_U,_U,_U,_U,_U,_U,_U,_U,_U,_U,_U,_U,_U,       /* 192-207 */
+_U,_U,_U,_U,_U,_U,_U,_P,_U,_U,_U,_U,_U,_U,_U,_L,       /* 208-223 */
+_L,_L,_L,_L,_L,_L,_L,_L,_L,_L,_L,_L,_L,_L,_L,_L,       /* 224-239 */
+_L,_L,_L,_L,_L,_L,_L,_P,_L,_L,_L,_L,_L,_L,_L,_L};      /* 240-255 */
+
+/**
+ * simple_strtoull - convert a string to an unsigned long long
+ * @cp: The start of the string
+ * @endp: A pointer to the end of the parsed string will be placed here
+ * @base: The number base to use
+ */
+unsigned long long simple_strtoull(const char *cp,char **endp,unsigned int base)
+{
+	unsigned long long result = 0,value;
+
+	if (!base) {
+		base = 10;
+		if (*cp == '0') {
+			base = 8;
+			cp++;
+			if ((toupper(*cp) == 'X') && isxdigit(cp[1])) {
+				cp++;
+				base = 16;
+			}
+		}
+	} else if (base == 16) {
+		if (cp[0] == '0' && toupper(cp[1]) == 'X')
+			cp += 2;
+	}
+	while (isxdigit(*cp) && (value = isdigit(*cp) ? *cp-'0' : (islower(*cp)
+	    ? toupper(*cp) : *cp)-'A'+10) < base) {
+		result = result*base + value;
+		cp++;
+	}
+	if (endp)
+		*endp = (char *)cp;
+	return result;
+}
+
+void *
+load_kernel(unsigned long load_addr, int num_words, unsigned long cksum,
+		void *ign1, void *ign2)
+{
+	unsigned long long mac64;
+
+	decompress_kernel(load_addr, num_words, cksum);
+
+	mac64 = simple_strtoull((char *)OCOTEA_PIBS_MAC_BASE, 0, 16);
+	memcpy(hold_residual->bi_enetaddr, (char *)&mac64+2, 6);
+	mac64 = simple_strtoull((char *)(OCOTEA_PIBS_MAC_BASE+OCOTEA_PIBS_MAC_OFFSET), 0, 16);
+	memcpy(hold_residual->bi_enet1addr, (char *)&mac64+2, 6);
+	mac64 = simple_strtoull((char *)(OCOTEA_PIBS_MAC_BASE+OCOTEA_PIBS_MAC_OFFSET*2), 0, 16);
+	memcpy(hold_residual->bi_enet2addr, (char *)&mac64+2, 6);
+	mac64 = simple_strtoull((char *)(OCOTEA_PIBS_MAC_BASE+OCOTEA_PIBS_MAC_OFFSET*3), 0, 16);
+	memcpy(hold_residual->bi_enet3addr, (char *)&mac64+2, 6);
+	return (void *)hold_residual;
+}
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-10-18 14:57:24 -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/boot/simple/relocate.S b/arch/ppc/boot/simple/relocate.S
--- a/arch/ppc/boot/simple/relocate.S	2004-10-18 14:56:29 -07:00
+++ b/arch/ppc/boot/simple/relocate.S	2004-10-18 14:56:29 -07:00
@@ -50,7 +50,7 @@
 	 * Check if we need to relocate ourselves to the link addr or were
 	 * we loaded there to begin with.
 	 */
-	cmp	cr0,r3,r4
+	cmpw	cr0,r3,r4
 	beq	start_ldr	/* If 0, we don't need to relocate */
 
 	/* Move this code somewhere safe.  This is max(load + size, end)
@@ -122,7 +122,7 @@
 	GETSYM(r4, start)
 	mr	r3,r8		/* Get the load addr */
 
-	cmp	cr0,r4,r3	/* If we need to copy from the end, do so */
+	cmpw	cr0,r4,r3	/* If we need to copy from the end, do so */
 	bgt	do_relocate_from_end
 
 do_relocate_from_start:
@@ -165,7 +165,7 @@
 	subi	r4,r4,4
 	li	r0,0
 50:	stwu	r0,4(r3)
-	cmp	cr0,r3,r4
+	cmpw	cr0,r3,r4
 	bne	50b
 90:	mr	r9,r1		/* Save old stack pointer (in case it matters) */
 	lis	r1,.stack@h
diff -Nru a/arch/ppc/boot/utils/mkbugboot.c b/arch/ppc/boot/utils/mkbugboot.c
--- a/arch/ppc/boot/utils/mkbugboot.c	2004-10-18 14:56:32 -07:00
+++ b/arch/ppc/boot/utils/mkbugboot.c	2004-10-18 14:56:32 -07:00
@@ -1,5 +1,5 @@
 /*
- * arch/ppc/pp3boot/mkbugboot.c
+ * arch/ppc/boot/utils/mkbugboot.c
  *
  * Makes a Motorola PPCBUG ROM bootable image which can be flashed
  * into one of the FLASH banks on a Motorola PowerPlus board.
@@ -21,6 +21,11 @@
 #include <stdlib.h>
 #include <errno.h>
 #include <fcntl.h>
+#ifdef __sun__
+#include <inttypes.h>
+#else
+#include <stdint.h>
+#endif
 
 #ifdef __i386__
 #define cpu_to_be32(x) le32_to_cpu(x)
@@ -48,11 +53,6 @@
 
 /* size of read buffer */
 #define SIZE 0x1000
-
-/* typedef long int32_t; */
-typedef unsigned long uint32_t;
-typedef unsigned short uint16_t;
-typedef unsigned char uint8_t;
 
 /* PPCBUG ROM boot header */
 typedef struct bug_boot_header {
diff -Nru a/arch/ppc/boot/utils/mktree.c b/arch/ppc/boot/utils/mktree.c
--- a/arch/ppc/boot/utils/mktree.c	2004-10-18 14:56:49 -07:00
+++ b/arch/ppc/boot/utils/mktree.c	2004-10-18 14:56:49 -07:00
@@ -15,7 +15,11 @@
 #include <sys/stat.h>
 #include <unistd.h>
 #include <netinet/in.h>
+#ifdef __sun__
+#include <inttypes.h>
+#else
 #include <stdint.h>
+#endif
 
 /* This gets tacked on the front of the image.  There are also a few
  * bytes allocated after the _start label used by the boot rom (see
diff -Nru a/arch/ppc/configs/mvme5100_defconfig b/arch/ppc/configs/mvme5100_defconfig
--- a/arch/ppc/configs/mvme5100_defconfig	2004-10-18 14:55:54 -07:00
+++ b/arch/ppc/configs/mvme5100_defconfig	2004-10-18 14:55:54 -07:00
@@ -1,26 +1,48 @@
 #
 # Automatically generated make config: don't edit
+# Linux kernel version: 2.6.9-rc2
+# Wed Sep 22 09:53:26 2004
 #
 CONFIG_MMU=y
 CONFIG_RWSEM_XCHGADD_ALGORITHM=y
 CONFIG_HAVE_DEC_LOCK=y
+CONFIG_PPC=y
+CONFIG_PPC32=y
+CONFIG_GENERIC_NVRAM=y
+CONFIG_GENERIC_IOMAP=y
 
 #
 # Code maturity level options
 #
 CONFIG_EXPERIMENTAL=y
+CONFIG_CLEAN_COMPILE=y
+CONFIG_BROKEN_ON_SMP=y
 
 #
 # General setup
 #
+CONFIG_LOCALVERSION=""
 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_EMBEDDED is not set
+# CONFIG_HOTPLUG is not set
+# CONFIG_IKCONFIG is not set
+CONFIG_EMBEDDED=y
+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
+CONFIG_SHMEM=y
+# CONFIG_TINY_SHMEM is not set
 
 #
 # Loadable module support
@@ -33,24 +55,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 +90,30 @@
 # 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_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 +130,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 +163,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 +218,70 @@
 # 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_MEGARAID_NEWGEN is not set
+# CONFIG_MEGARAID_LEGACY 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 +291,10 @@
 # CONFIG_I2O is not set
 
 #
+# Macintosh device drivers
+#
+
+#
 # Networking support
 #
 CONFIG_NET=y
@@ -261,86 +305,90 @@
 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
+CONFIG_INET_TUNNEL=m
+
+#
+# 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
+# CONFIG_IP_NF_CT_ACCT is not set
+# CONFIG_IP_NF_CT_PROTO_SCTP is not set
 CONFIG_IP_NF_FTP=m
 CONFIG_IP_NF_IRC=m
-# CONFIG_IP_NF_TFTP is not set
-# CONFIG_IP_NF_AMANDA is not set
+CONFIG_IP_NF_TFTP=m
+CONFIG_IP_NF_AMANDA=m
 # CONFIG_IP_NF_QUEUE is not set
 CONFIG_IP_NF_IPTABLES=m
-CONFIG_IP_NF_MATCH_LIMIT=m
-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_ECN=m
-CONFIG_IP_NF_MATCH_DSCP=m
-CONFIG_IP_NF_MATCH_AH_ESP=m
-CONFIG_IP_NF_MATCH_LENGTH=m
-CONFIG_IP_NF_MATCH_TTL=m
-CONFIG_IP_NF_MATCH_TCPMSS=m
+# CONFIG_IP_NF_MATCH_LIMIT is not set
+# CONFIG_IP_NF_MATCH_IPRANGE is not set
+# CONFIG_IP_NF_MATCH_MAC is not set
+# CONFIG_IP_NF_MATCH_PKTTYPE is not set
+# CONFIG_IP_NF_MATCH_MARK is not set
+# CONFIG_IP_NF_MATCH_MULTIPORT is not set
+# CONFIG_IP_NF_MATCH_TOS is not set
+# CONFIG_IP_NF_MATCH_RECENT is not set
+# CONFIG_IP_NF_MATCH_ECN is not set
+# CONFIG_IP_NF_MATCH_DSCP is not set
+# CONFIG_IP_NF_MATCH_AH_ESP is not set
+# CONFIG_IP_NF_MATCH_LENGTH is not set
+# CONFIG_IP_NF_MATCH_TTL is not set
+# CONFIG_IP_NF_MATCH_TCPMSS is not set
 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_NAT_LOCAL is not set
-# CONFIG_IP_NF_NAT_SNMP_BASIC is not set
-CONFIG_IP_NF_NAT_IRC=m
-CONFIG_IP_NF_NAT_FTP=m
-# CONFIG_IP_NF_MANGLE is not set
+# CONFIG_IP_NF_MATCH_STATE is not set
+# CONFIG_IP_NF_MATCH_CONNTRACK is not set
+# CONFIG_IP_NF_MATCH_OWNER is not set
+# CONFIG_IP_NF_MATCH_ADDRTYPE is not set
+# CONFIG_IP_NF_MATCH_REALM is not set
+# CONFIG_IP_NF_MATCH_SCTP is not set
+# CONFIG_IP_NF_FILTER is not set
 # CONFIG_IP_NF_TARGET_LOG is not set
-CONFIG_IP_NF_TARGET_ULOG=m
-CONFIG_IP_NF_TARGET_TCPMSS=m
-CONFIG_IP_NF_ARPTABLES=m
-CONFIG_IP_NF_ARPFILTER=m
-CONFIG_IP_NF_COMPAT_IPCHAINS=m
+# CONFIG_IP_NF_TARGET_ULOG is not set
+# CONFIG_IP_NF_TARGET_TCPMSS is not set
+# CONFIG_IP_NF_NAT is not set
+# CONFIG_IP_NF_MANGLE is not set
+# CONFIG_IP_NF_RAW is not set
+# CONFIG_IP_NF_ARPTABLES is not set
+# CONFIG_IP_NF_COMPAT_IPCHAINS is not set
 # CONFIG_IP_NF_COMPAT_IPFWADM is not set
-# CONFIG_IPV6 is not set
-# CONFIG_XFRM_USER is not set
+CONFIG_XFRM=y
+CONFIG_XFRM_USER=y
 
 #
 # 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
@@ -382,17 +434,26 @@
 #
 # Tulip family network device support
 #
-# CONFIG_NET_TULIP is not set
+CONFIG_NET_TULIP=y
+# CONFIG_DE2104X is not set
+CONFIG_TULIP=y
+# CONFIG_TULIP_MWI is not set
+# CONFIG_TULIP_MMIO is not set
+# CONFIG_TULIP_NAPI is not set
+# CONFIG_DE4X5 is not set
+# CONFIG_WINBOND_840 is not set
+# CONFIG_DM9102 is not set
 # CONFIG_HP100 is not set
 CONFIG_NET_PCI=y
 # CONFIG_PCNET32 is not set
 # 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 +464,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,52 +483,39 @@
 # 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
+# CONFIG_ISDN is not set
 
 #
-# Graphics support
+# Telephony Support
 #
-# CONFIG_FB is not set
-
-#
-# Old CD-ROM drivers (not SCSI, not IDE)
-#
-# CONFIG_CD_NO_IDESCSI is not set
+# CONFIG_PHONE is not set
 
 #
 # Input device support
@@ -483,18 +532,16 @@
 # CONFIG_GAMEPORT is not set
 CONFIG_SOUND_GAMEPORT=y
 # CONFIG_SERIO is not set
+# CONFIG_SERIO_I8042 is not set
 
 #
 # Input Device Drivers
 #
 
 #
-# Macintosh device drivers
-#
-
-#
 # Character devices
 #
+# CONFIG_VT is not set
 # CONFIG_SERIAL_NONSTANDARD is not set
 
 #
@@ -502,6 +549,7 @@
 #
 CONFIG_SERIAL_8250=y
 CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_NR_UARTS=4
 # CONFIG_SERIAL_8250_EXTENDED is not set
 
 #
@@ -510,27 +558,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_QIC02_TAPE is not set
+CONFIG_LEGACY_PTYS=y
+CONFIG_LEGACY_PTY_COUNT=256
 
 #
 # IPMI
@@ -551,11 +580,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 +609,26 @@
 # CONFIG_DVB is not set
 
 #
+# Graphics support
+#
+# CONFIG_FB is not set
+
+#
+# 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 +653,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 +675,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 +690,21 @@
 # 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_RPCSEC_GSS_SPKM3 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 +714,26 @@
 CONFIG_MSDOS_PARTITION=y
 
 #
-# Sound
+# Native Language Support
 #
-# CONFIG_SOUND is not set
+# CONFIG_NLS is not set
 
 #
-# USB support
-#
-# CONFIG_USB is not set
-# CONFIG_USB_GADGET is not set
-
-#
-# Bluetooth support
+# Library routines
 #
-# CONFIG_BT is not set
+# CONFIG_CRC_CCITT is not set
+CONFIG_CRC32=y
+# 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/Makefile b/arch/ppc/kernel/Makefile
--- a/arch/ppc/kernel/Makefile	2004-10-18 14:57:03 -07:00
+++ b/arch/ppc/kernel/Makefile	2004-10-18 14:57:03 -07:00
@@ -9,7 +9,7 @@
 extra-$(CONFIG_8xx)		:= head_8xx.o
 extra-$(CONFIG_6xx)		+= idle_6xx.o
 extra-$(CONFIG_POWER4)		+= idle_power4.o
-extra-y				+= vmlinux.lds.s
+extra-y				+= vmlinux.lds
 
 obj-y				:= entry.o traps.o irq.o idle.o time.o misc.o \
 					process.o signal.o ptrace.o align.o \
diff -Nru a/arch/ppc/kernel/align.c b/arch/ppc/kernel/align.c
--- a/arch/ppc/kernel/align.c	2004-10-18 14:55:53 -07:00
+++ b/arch/ppc/kernel/align.c	2004-10-18 14:55:53 -07:00
@@ -37,6 +37,7 @@
 #define U	0x10	/* update index register */
 #define M	0x20	/* multiple load/store */
 #define S	0x40	/* single-precision fp, or byte-swap value */
+#define SX	0x40	/* byte count in XER */
 #define HARD	0x80	/* string, stwcx. */
 
 #define DCBZ	0x5f	/* 8xx/82xx dcbz faults when cache not enabled */
@@ -88,10 +89,10 @@
 	INVALID,		/* 01 0 0101: lwax */
 	INVALID,		/* 01 0 0110 */
 	INVALID,		/* 01 0 0111 */
-	{ 0, LD+HARD },		/* 01 0 1000: lswx */
-	{ 0, LD+HARD },		/* 01 0 1001: lswi */
-	{ 0, ST+HARD },		/* 01 0 1010: stswx */
-	{ 0, ST+HARD },		/* 01 0 1011: stswi */
+	{ 4, LD+M+HARD+SX },	/* 01 0 1000: lswx */
+	{ 4, LD+M+HARD },	/* 01 0 1001: lswi */
+	{ 4, ST+M+HARD+SX },	/* 01 0 1010: stswx */
+	{ 4, ST+M+HARD },	/* 01 0 1011: stswi */
 	INVALID,		/* 01 0 1100 */
 	INVALID,		/* 01 0 1101 */
 	INVALID,		/* 01 0 1110 */
@@ -189,7 +190,9 @@
 #endif
 	int i, t;
 	int reg, areg;
+	int offset, nb0;
 	unsigned char __user *addr;
+	unsigned char *rptr;
 	union {
 		long l;
 		float f;
@@ -206,7 +209,8 @@
 	 * an alignment fault.  -- paulus
 	 */
 
-	instr = *((unsigned int *)regs->nip);
+	if (__get_user(instr, (unsigned int __user *) regs->nip))
+		return 0;
 	opcode = OPCD(instr);
 	reg = RS(instr);
 	areg = RA(instr);
@@ -230,7 +234,7 @@
 
 	nb = aligninfo[instr].len;
 	if (nb == 0) {
-		long *p;
+		long __user *p;
 		int i;
 
 		if (instr != DCBZ)
@@ -242,13 +246,19 @@
 		 * case when we are running with the cache disabled
 		 * for debugging.
 		 */
-		p = (long *) (regs->dar & -L1_CACHE_BYTES);
+		p = (long __user *) (regs->dar & -L1_CACHE_BYTES);
+		if (user_mode(regs)
+		    && verify_area(VERIFY_WRITE, p, L1_CACHE_BYTES))
+			return -EFAULT;
 		for (i = 0; i < L1_CACHE_BYTES / sizeof(long); ++i)
-			p[i] = 0;
+			if (__put_user(0, p+i))
+				return -EFAULT;
 		return 1;
 	}
 
 	flags = aligninfo[instr].flags;
+	if ((flags & (LD|ST)) == 0)
+		return 0;
 
 	/* For the 4xx-family & Book-E processors, the 'dar' field of the
 	 * pt_regs structure is overloaded and is really from the DEAR.
@@ -256,6 +266,66 @@
 
 	addr = (unsigned char __user *)regs->dar;
 
+	if (flags & M) {
+		/* lmw, stmw, lswi/x, stswi/x */
+		nb0 = 0;
+		if (flags & HARD) {
+			if (flags & SX) {
+				nb = regs->xer & 127;
+				if (nb == 0)
+					return 1;
+			} else {
+				if (__get_user(instr,
+					    (unsigned int __user *)regs->nip))
+					return 0;
+				nb = (instr >> 11) & 0x1f;
+				if (nb == 0)
+					nb = 32;
+			}
+			if (nb + reg * 4 > 128) {
+				nb0 = nb + reg * 4 - 128;
+				nb = 128 - reg * 4;
+			}
+		} else {
+			/* lwm, stmw */
+			nb = (32 - reg) * 4;
+		}
+		rptr = (unsigned char *) &regs->gpr[reg];
+		if (flags & LD) {
+			for (i = 0; i < nb; ++i)
+				if (__get_user(rptr[i], addr+i))
+					return -EFAULT;
+			if (nb0 > 0) {
+				rptr = (unsigned char *) &regs->gpr[0];
+				addr += nb;
+				for (i = 0; i < nb0; ++i)
+					if (__get_user(rptr[i], addr+i))
+						return -EFAULT;
+			}
+			for (; (i & 3) != 0; ++i)
+				rptr[i] = 0;
+		} else {
+			for (i = 0; i < nb; ++i)
+				if (__put_user(rptr[i], addr+i))
+					return -EFAULT;
+			if (nb0 > 0) {
+				rptr = (unsigned char *) &regs->gpr[0];
+				addr += nb;
+				for (i = 0; i < nb0; ++i)
+					if (__put_user(rptr[i], addr+i))
+						return -EFAULT;
+			}
+		}
+		return 1;
+	}
+
+	offset = 0;
+	if (nb < 4) {
+		/* read/write the least significant bits */
+		data.l = 0;
+		offset = 4 - nb;
+	}
+
 	/* Verify the address of the operand */
 	if (user_mode(regs)) {
 		if (verify_area((flags & ST? VERIFY_WRITE: VERIFY_READ), addr, nb))
@@ -268,45 +338,26 @@
 			giveup_fpu(current);
 		preempt_enable();
 	}
-	if (flags & M)
-		return 0;		/* too hard for now */
 
-	/* If we read the operand, copy it in */
+	/* If we read the operand, copy it in, else get register values */
 	if (flags & LD) {
-		if (nb == 2) {
-			data.v[0] = data.v[1] = 0;
-			if (__get_user(data.v[2], addr)
-			    || __get_user(data.v[3], addr+1))
+		for (i = 0; i < nb; ++i)
+			if (__get_user(data.v[offset+i], addr+i))
 				return -EFAULT;
-		} else {
-			for (i = 0; i < nb; ++i)
-				if (__get_user(data.v[i], addr+i))
-					return -EFAULT;
-		}
+	} else if (flags & F) {
+		data.d = current->thread.fpr[reg];
+	} else {
+		data.l = regs->gpr[reg];
 	}
 
 	switch (flags & ~U) {
-	case LD+SE:
+	case LD+SE:	/* sign extend */
 		if (data.v[2] >= 0x80)
 			data.v[0] = data.v[1] = -1;
-		/* fall through */
-	case LD:
-		regs->gpr[reg] = data.l;
-		break;
-	case LD+S:
-		if (nb == 2) {
-			SWAP(data.v[2], data.v[3]);
-		} else {
-			SWAP(data.v[0], data.v[3]);
-			SWAP(data.v[1], data.v[2]);
-		}
-		regs->gpr[reg] = data.l;
-		break;
-	case ST:
-		data.l = regs->gpr[reg];
 		break;
+
+	case LD+S:	/* byte-swap */
 	case ST+S:
-		data.l = regs->gpr[reg];
 		if (nb == 2) {
 			SWAP(data.v[2], data.v[3]);
 		} else {
@@ -314,50 +365,34 @@
 			SWAP(data.v[1], data.v[2]);
 		}
 		break;
-	case LD+F:
-		current->thread.fpr[reg] = data.d;
-		break;
-	case ST+F:
-		data.d = current->thread.fpr[reg];
-		break;
-	/* these require some floating point conversions... */
-	/* we'd like to use the assignment, but we have to compile
-	 * the kernel with -msoft-float so it doesn't use the
-	 * fp regs for copying 8-byte objects. */
+
+	/* Single-precision FP load and store require conversions... */
 	case LD+F+S:
 		preempt_disable();
 		enable_kernel_fp();
-		cvt_fd(&data.f, &current->thread.fpr[reg], &current->thread.fpscr);
-		/* current->thread.fpr[reg] = data.f; */
+		cvt_fd(&data.f, &data.d, &current->thread.fpscr);
 		preempt_enable();
 		break;
 	case ST+F+S:
 		preempt_disable();
 		enable_kernel_fp();
-		cvt_df(&current->thread.fpr[reg], &data.f, &current->thread.fpscr);
-		/* data.f = current->thread.fpr[reg]; */
+		cvt_df(&data.d, &data.f, &current->thread.fpscr);
 		preempt_enable();
 		break;
-	default:
-		printk("align: can't handle flags=%x\n", flags);
-		return 0;
 	}
 
 	if (flags & ST) {
-		if (nb == 2) {
-			if (__put_user(data.v[2], addr)
-			    || __put_user(data.v[3], addr+1))
+		for (i = 0; i < nb; ++i)
+			if (__put_user(data.v[offset+i], addr+i))
 				return -EFAULT;
-		} else {
-			for (i = 0; i < nb; ++i)
-				if (__put_user(data.v[i], addr+i))
-					return -EFAULT;
-		}
+	} else if (flags & F) {
+		current->thread.fpr[reg] = data.d;
+	} else {
+		regs->gpr[reg] = data.l;
 	}
 
-	if (flags & U) {
+	if (flags & U)
 		regs->gpr[areg] = regs->dar;
-	}
 
 	return 1;
 }
diff -Nru a/arch/ppc/kernel/asm-offsets.c b/arch/ppc/kernel/asm-offsets.c
--- a/arch/ppc/kernel/asm-offsets.c	2004-10-18 14:56:32 -07:00
+++ b/arch/ppc/kernel/asm-offsets.c	2004-10-18 14:56:32 -07:00
@@ -129,6 +129,13 @@
 	DEFINE(CPU_SPEC_FEATURES, offsetof(struct cpu_spec, cpu_features));
 	DEFINE(CPU_SPEC_SETUP, offsetof(struct cpu_spec, cpu_setup));
 
+	DEFINE(TI_TASK, offsetof(struct thread_info, task));
+	DEFINE(TI_EXECDOMAIN, offsetof(struct thread_info, exec_domain));
+	DEFINE(TI_FLAGS, offsetof(struct thread_info, flags));
+	DEFINE(TI_LOCAL_FLAGS, offsetof(struct thread_info, local_flags));
+	DEFINE(TI_CPU, offsetof(struct thread_info, cpu));
+	DEFINE(TI_PREEMPT, offsetof(struct thread_info, preempt_count));
+
 	DEFINE(NUM_USER_SEGMENTS, TASK_SIZE>>28);
 	return 0;
 }
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-10-18 14:56:17 -07:00
+++ b/arch/ppc/kernel/cpu_setup_6xx.S	2004-10-18 14:56:17 -07:00
@@ -172,9 +172,9 @@
 setup_750cx:
 	mfspr	r10, SPRN_HID1
 	rlwinm	r10,r10,4,28,31
-	cmpi	cr0,r10,7
-	cmpi	cr1,r10,9
-	cmpi	cr2,r10,11
+	cmpwi	cr0,r10,7
+	cmpwi	cr1,r10,9
+	cmpwi	cr2,r10,11
 	cror	4*cr0+eq,4*cr0+eq,4*cr1+eq
 	cror	4*cr0+eq,4*cr0+eq,4*cr2+eq
 	bnelr
@@ -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)
@@ -287,12 +287,12 @@
 	/* Now deal with CPU type dependent registers */
 	mfspr	r3,PVR
 	srwi	r3,r3,16
-	cmpli	cr0,r3,0x8000	/* 7450 */
-	cmpli	cr1,r3,0x000c	/* 7400 */
-	cmpli	cr2,r3,0x800c	/* 7410 */
-	cmpli	cr3,r3,0x8001	/* 7455 */
-	cmpli	cr4,r3,0x8002	/* 7457 */
-	cmpli	cr5,r3,0x7000	/* 750FX */
+	cmplwi	cr0,r3,0x8000	/* 7450 */
+	cmplwi	cr1,r3,0x000c	/* 7400 */
+	cmplwi	cr2,r3,0x800c	/* 7410 */
+	cmplwi	cr3,r3,0x8001	/* 7455 */
+	cmplwi	cr4,r3,0x8002	/* 7457 */
+	cmplwi	cr5,r3,0x7000	/* 750FX */
 	/* cr1 is 7400 || 7410 */
 	cror	4*cr1+eq,4*cr1+eq,4*cr2+eq
 	/* cr0 is 74xx */
@@ -323,7 +323,7 @@
 	/* If rev 2.x, backup HID2 */
 	mfspr	r3,PVR
 	andi.	r3,r3,0xff00
-	cmpi	cr0,r3,0x0200
+	cmpwi	cr0,r3,0x0200
 	bne	1f
 	mfspr	r4,SPRN_HID2
 	stw	r4,CS_HID2(r5)
@@ -354,12 +354,12 @@
 	/* Now deal with CPU type dependent registers */
 	mfspr	r3,PVR
 	srwi	r3,r3,16
-	cmpli	cr0,r3,0x8000	/* 7450 */
-	cmpli	cr1,r3,0x000c	/* 7400 */
-	cmpli	cr2,r3,0x800c	/* 7410 */
-	cmpli	cr3,r3,0x8001	/* 7455 */
-	cmpli	cr4,r3,0x8002	/* 7457 */
-	cmpli	cr5,r3,0x7000	/* 750FX */
+	cmplwi	cr0,r3,0x8000	/* 7450 */
+	cmplwi	cr1,r3,0x000c	/* 7400 */
+	cmplwi	cr2,r3,0x800c	/* 7410 */
+	cmplwi	cr3,r3,0x8001	/* 7455 */
+	cmplwi	cr4,r3,0x8002	/* 7457 */
+	cmplwi	cr5,r3,0x7000	/* 750FX */
 	/* cr1 is 7400 || 7410 */
 	cror	4*cr1+eq,4*cr1+eq,4*cr2+eq
 	/* cr0 is 74xx */
@@ -412,7 +412,7 @@
 	/* If rev 2.x, restore HID2 with low voltage bit cleared */
 	mfspr	r3,PVR
 	andi.	r3,r3,0xff00
-	cmpi	cr0,r3,0x0200
+	cmpwi	cr0,r3,0x0200
 	bne	4f
 	lwz	r4,CS_HID2(r5)
 	rlwinm	r4,r4,0,19,17
@@ -426,7 +426,7 @@
 	mftbl	r5
 3:	mftbl	r6
 	sub	r6,r6,r5
-	cmpli	cr0,r6,10000
+	cmplwi	cr0,r6,10000
 	ble	3b
 	/* Setup final PLL */
 	mtspr	SPRN_HID1,r4
diff -Nru a/arch/ppc/kernel/cpu_setup_power4.S b/arch/ppc/kernel/cpu_setup_power4.S
--- a/arch/ppc/kernel/cpu_setup_power4.S	2004-10-18 14:56:49 -07:00
+++ b/arch/ppc/kernel/cpu_setup_power4.S	2004-10-18 14:56:49 -07:00
@@ -112,7 +112,9 @@
 	/* We only deal with 970 for now */
 	mfspr	r0,SPRN_PVR
 	srwi	r0,r0,16
-	cmpwi	r0,0x39
+	cmpwi	cr0,r0,0x39
+	cmpwi	cr1,r0,0x3c
+	cror	4*cr0+eq,4*cr0+eq,4*cr1+eq
 	bne	1f
 
 	/* Save HID0,1,4 and 5 */
@@ -144,7 +146,9 @@
 	/* We only deal with 970 for now */
 	mfspr	r0,SPRN_PVR
 	srwi	r0,r0,16
-	cmpwi	r0,0x39
+	cmpwi	cr0,r0,0x39
+	cmpwi	cr1,r0,0x3c
+	cror	4*cr0+eq,4*cr0+eq,4*cr1+eq
 	bne	1f
 
 	/* Clear interrupt prefix */
diff -Nru a/arch/ppc/kernel/cputable.c b/arch/ppc/kernel/cputable.c
--- a/arch/ppc/kernel/cputable.c	2004-10-18 14:56:32 -07:00
+++ b/arch/ppc/kernel/cputable.c	2004-10-18 14:56:32 -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
@@ -63,6 +63,17 @@
 #define CPU_FTR_COMMON                  0
 #endif
 
+/* The powersave features NAP & DOZE seems to confuse BDI when
+   debugging. So if a BDI is used, disable theses
+ */
+#ifndef CONFIG_BDI_SWITCH
+#define CPU_FTR_MAYBE_CAN_DOZE	CPU_FTR_CAN_DOZE
+#define CPU_FTR_MAYBE_CAN_NAP	CPU_FTR_CAN_NAP
+#else
+#define CPU_FTR_MAYBE_CAN_DOZE	0
+#define CPU_FTR_MAYBE_CAN_NAP	0
+#endif
+
 struct cpu_spec	cpu_specs[] = {
 #if CLASSIC_PPC
     { 	/* 601 */
@@ -76,8 +87,8 @@
     {	/* 603 */
     	0xffff0000, 0x00030000, "603",
 	CPU_FTR_COMMON |
-    	CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_CAN_DOZE | CPU_FTR_USE_TB |
-    	CPU_FTR_CAN_NAP,
+    	CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_MAYBE_CAN_DOZE | CPU_FTR_USE_TB |
+    	CPU_FTR_MAYBE_CAN_NAP,
 	COMMON_PPC,
     	32, 32,
 	__setup_cpu_603
@@ -85,8 +96,8 @@
     {	/* 603e */
     	0xffff0000, 0x00060000, "603e",
 	CPU_FTR_COMMON |
-    	CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_CAN_DOZE | CPU_FTR_USE_TB |
-    	CPU_FTR_CAN_NAP,
+    	CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_MAYBE_CAN_DOZE | CPU_FTR_USE_TB |
+    	CPU_FTR_MAYBE_CAN_NAP,
 	COMMON_PPC,
 	32, 32,
 	__setup_cpu_603
@@ -94,8 +105,8 @@
     {	/* 603ev */
     	0xffff0000, 0x00070000, "603ev",
 	CPU_FTR_COMMON |
-    	CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_CAN_DOZE | CPU_FTR_USE_TB |
-    	CPU_FTR_CAN_NAP,
+    	CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_MAYBE_CAN_DOZE | CPU_FTR_USE_TB |
+    	CPU_FTR_MAYBE_CAN_NAP,
 	COMMON_PPC,
 	32, 32,
 	__setup_cpu_603
@@ -139,8 +150,8 @@
     {	/* 740/750 (0x4202, don't support TAU ?) */
     	0xffffffff, 0x00084202, "740/750",
 	CPU_FTR_COMMON |
-    	CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_CAN_DOZE | CPU_FTR_USE_TB |
-	CPU_FTR_L2CR | CPU_FTR_HPTE_TABLE | CPU_FTR_CAN_NAP,
+    	CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_MAYBE_CAN_DOZE | CPU_FTR_USE_TB |
+	CPU_FTR_L2CR | CPU_FTR_HPTE_TABLE | CPU_FTR_MAYBE_CAN_NAP,
 	COMMON_PPC,
 	32, 32,
 	__setup_cpu_750
@@ -148,8 +159,8 @@
     {	/* 745/755 */
     	0xfffff000, 0x00083000, "745/755",
 	CPU_FTR_COMMON |
-    	CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_CAN_DOZE | CPU_FTR_USE_TB |
-	CPU_FTR_L2CR | CPU_FTR_TAU | CPU_FTR_HPTE_TABLE | CPU_FTR_CAN_NAP,
+    	CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_MAYBE_CAN_DOZE | CPU_FTR_USE_TB |
+	CPU_FTR_L2CR | CPU_FTR_TAU | CPU_FTR_HPTE_TABLE | CPU_FTR_MAYBE_CAN_NAP,
 	COMMON_PPC,
 	32, 32,
 	__setup_cpu_750
@@ -157,8 +168,8 @@
     {	/* 750CX (80100 and 8010x?) */
     	0xfffffff0, 0x00080100, "750CX",
 	CPU_FTR_COMMON |
-    	CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_CAN_DOZE | CPU_FTR_USE_TB |
-	CPU_FTR_L2CR | CPU_FTR_TAU | CPU_FTR_HPTE_TABLE | CPU_FTR_CAN_NAP,
+    	CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_MAYBE_CAN_DOZE | CPU_FTR_USE_TB |
+	CPU_FTR_L2CR | CPU_FTR_TAU | CPU_FTR_HPTE_TABLE | CPU_FTR_MAYBE_CAN_NAP,
 	COMMON_PPC,
 	32, 32,
 	__setup_cpu_750cx
@@ -166,8 +177,8 @@
     {	/* 750CX (82201 and 82202) */
     	0xfffffff0, 0x00082200, "750CX",
 	CPU_FTR_COMMON |
-    	CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_CAN_DOZE | CPU_FTR_USE_TB |
-	CPU_FTR_L2CR | CPU_FTR_TAU | CPU_FTR_HPTE_TABLE | CPU_FTR_CAN_NAP,
+    	CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_MAYBE_CAN_DOZE | CPU_FTR_USE_TB |
+	CPU_FTR_L2CR | CPU_FTR_TAU | CPU_FTR_HPTE_TABLE | CPU_FTR_MAYBE_CAN_NAP,
 	COMMON_PPC,
 	32, 32,
 	__setup_cpu_750cx
@@ -175,8 +186,8 @@
     {	/* 750CXe (82214) */
     	0xfffffff0, 0x00082210, "750CXe",
 	CPU_FTR_COMMON |
-    	CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_CAN_DOZE | CPU_FTR_USE_TB |
-	CPU_FTR_L2CR | CPU_FTR_TAU | CPU_FTR_HPTE_TABLE | CPU_FTR_CAN_NAP,
+    	CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_MAYBE_CAN_DOZE | CPU_FTR_USE_TB |
+	CPU_FTR_L2CR | CPU_FTR_TAU | CPU_FTR_HPTE_TABLE | CPU_FTR_MAYBE_CAN_NAP,
 	COMMON_PPC,
 	32, 32,
 	__setup_cpu_750cx
@@ -184,8 +195,8 @@
     {	/* 750FX rev 1.x */
     	0xffffff00, 0x70000100, "750FX",
 	CPU_FTR_COMMON |
-    	CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_CAN_DOZE | CPU_FTR_USE_TB |
-	CPU_FTR_L2CR | CPU_FTR_TAU | CPU_FTR_HPTE_TABLE | CPU_FTR_CAN_NAP |
+    	CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_MAYBE_CAN_DOZE | CPU_FTR_USE_TB |
+	CPU_FTR_L2CR | CPU_FTR_TAU | CPU_FTR_HPTE_TABLE | CPU_FTR_MAYBE_CAN_NAP |
 	CPU_FTR_DUAL_PLL_750FX | CPU_FTR_NO_DPM,
 	COMMON_PPC,
 	32, 32,
@@ -194,8 +205,8 @@
     {	/* 750FX rev 2.0 must disable HID0[DPM] */
     	0xffffffff, 0x70000200, "750FX",
 	CPU_FTR_COMMON |
-    	CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_CAN_DOZE | CPU_FTR_USE_TB |
-	CPU_FTR_L2CR | CPU_FTR_TAU | CPU_FTR_HPTE_TABLE | CPU_FTR_CAN_NAP |
+    	CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_MAYBE_CAN_DOZE | CPU_FTR_USE_TB |
+	CPU_FTR_L2CR | CPU_FTR_TAU | CPU_FTR_HPTE_TABLE | CPU_FTR_MAYBE_CAN_NAP |
 	CPU_FTR_NO_DPM,
 	COMMON_PPC,
 	32, 32,
@@ -204,8 +215,8 @@
     {	/* 750FX (All revs except 2.0) */
     	0xffff0000, 0x70000000, "750FX",
 	CPU_FTR_COMMON |
-    	CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_CAN_DOZE | CPU_FTR_USE_TB |
-	CPU_FTR_L2CR | CPU_FTR_TAU | CPU_FTR_HPTE_TABLE | CPU_FTR_CAN_NAP |
+    	CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_MAYBE_CAN_DOZE | CPU_FTR_USE_TB |
+	CPU_FTR_L2CR | CPU_FTR_TAU | CPU_FTR_HPTE_TABLE | CPU_FTR_MAYBE_CAN_NAP |
 	CPU_FTR_DUAL_PLL_750FX | CPU_FTR_HAS_HIGH_BATS,
 	COMMON_PPC,
 	32, 32,
@@ -213,8 +224,8 @@
     },
     {	/* 750GX */
     	0xffff0000, 0x70020000, "750GX",
-    	CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_CAN_DOZE | CPU_FTR_USE_TB |
-	CPU_FTR_L2CR | CPU_FTR_TAU | CPU_FTR_HPTE_TABLE | CPU_FTR_CAN_NAP |
+    	CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_MAYBE_CAN_DOZE | CPU_FTR_USE_TB |
+	CPU_FTR_L2CR | CPU_FTR_TAU | CPU_FTR_HPTE_TABLE | CPU_FTR_MAYBE_CAN_NAP |
 	CPU_FTR_DUAL_PLL_750FX | CPU_FTR_HAS_HIGH_BATS,
 	COMMON_PPC,
 	32, 32,
@@ -223,8 +234,8 @@
     {	/* 740/750 (L2CR bit need fixup for 740) */
     	0xffff0000, 0x00080000, "740/750",
 	CPU_FTR_COMMON |
-    	CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_CAN_DOZE | CPU_FTR_USE_TB |
-	CPU_FTR_L2CR | CPU_FTR_TAU | CPU_FTR_HPTE_TABLE | CPU_FTR_CAN_NAP,
+    	CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_MAYBE_CAN_DOZE | CPU_FTR_USE_TB |
+	CPU_FTR_L2CR | CPU_FTR_TAU | CPU_FTR_HPTE_TABLE | CPU_FTR_MAYBE_CAN_NAP,
 	COMMON_PPC,
 	32, 32,
 	__setup_cpu_750
@@ -232,9 +243,9 @@
     {	/* 7400 rev 1.1 ? (no TAU) */
     	0xffffffff, 0x000c1101, "7400 (1.1)",
 	CPU_FTR_COMMON |
-    	CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_CAN_DOZE | CPU_FTR_USE_TB |
+    	CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_MAYBE_CAN_DOZE | CPU_FTR_USE_TB |
 	CPU_FTR_L2CR | CPU_FTR_ALTIVEC_COMP | CPU_FTR_HPTE_TABLE |
-	CPU_FTR_CAN_NAP,
+	CPU_FTR_MAYBE_CAN_NAP,
 	COMMON_PPC | PPC_FEATURE_ALTIVEC_COMP,
 	32, 32,
 	__setup_cpu_7400
@@ -242,9 +253,9 @@
     {	/* 7400 */
     	0xffff0000, 0x000c0000, "7400",
 	CPU_FTR_COMMON |
-    	CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_CAN_DOZE | CPU_FTR_USE_TB |
+    	CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_MAYBE_CAN_DOZE | CPU_FTR_USE_TB |
 	CPU_FTR_L2CR | CPU_FTR_TAU | CPU_FTR_ALTIVEC_COMP | CPU_FTR_HPTE_TABLE |
-	CPU_FTR_CAN_NAP,
+	CPU_FTR_MAYBE_CAN_NAP,
 	COMMON_PPC | PPC_FEATURE_ALTIVEC_COMP,
 	32, 32,
 	__setup_cpu_7400
@@ -252,9 +263,9 @@
     {	/* 7410 */
     	0xffff0000, 0x800c0000, "7410",
 	CPU_FTR_COMMON |
-    	CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_CAN_DOZE | CPU_FTR_USE_TB |
+    	CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_MAYBE_CAN_DOZE | CPU_FTR_USE_TB |
 	CPU_FTR_L2CR | CPU_FTR_TAU | CPU_FTR_ALTIVEC_COMP | CPU_FTR_HPTE_TABLE |
-	CPU_FTR_CAN_NAP,
+	CPU_FTR_MAYBE_CAN_NAP,
 	COMMON_PPC | PPC_FEATURE_ALTIVEC_COMP,
 	32, 32,
 	__setup_cpu_7410
@@ -272,7 +283,7 @@
     {	/* 7450 2.1 */
     	0xffffffff, 0x80000201, "7450",
 	CPU_FTR_COMMON |
-    	CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | CPU_FTR_CAN_NAP |
+    	CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | CPU_FTR_MAYBE_CAN_NAP |
 	CPU_FTR_L2CR | CPU_FTR_ALTIVEC_COMP | CPU_FTR_L3CR |
 	CPU_FTR_HPTE_TABLE | CPU_FTR_SPEC7450 | CPU_FTR_NAP_DISABLE_L2_PR |
 	CPU_FTR_L3_DISABLE_NAP | CPU_FTR_NEED_COHERENT,
@@ -283,7 +294,7 @@
     {	/* 7450 2.3 and newer */
     	0xffff0000, 0x80000000, "7450",
 	CPU_FTR_COMMON |
-    	CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | CPU_FTR_CAN_NAP |
+    	CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | CPU_FTR_MAYBE_CAN_NAP |
 	CPU_FTR_L2CR | CPU_FTR_ALTIVEC_COMP | CPU_FTR_L3CR |
 	CPU_FTR_HPTE_TABLE | CPU_FTR_SPEC7450 | CPU_FTR_NAP_DISABLE_L2_PR |
 	CPU_FTR_NEED_COHERENT,
@@ -305,7 +316,7 @@
     {	/* 7455 rev 2.0 */
     	0xffffffff, 0x80010200, "7455",
 	CPU_FTR_COMMON |
-    	CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | CPU_FTR_CAN_NAP |
+    	CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | CPU_FTR_MAYBE_CAN_NAP |
 	CPU_FTR_L2CR | CPU_FTR_ALTIVEC_COMP | CPU_FTR_L3CR |
 	CPU_FTR_HPTE_TABLE | CPU_FTR_SPEC7450 | CPU_FTR_NAP_DISABLE_L2_PR |
 	CPU_FTR_L3_DISABLE_NAP | CPU_FTR_NEED_COHERENT | CPU_FTR_HAS_HIGH_BATS,
@@ -316,7 +327,7 @@
     {	/* 7455 others */
     	0xffff0000, 0x80010000, "7455",
 	CPU_FTR_COMMON |
-    	CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | CPU_FTR_CAN_NAP |
+    	CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | CPU_FTR_MAYBE_CAN_NAP |
 	CPU_FTR_L2CR | CPU_FTR_ALTIVEC_COMP | CPU_FTR_L3CR |
 	CPU_FTR_HPTE_TABLE | CPU_FTR_SPEC7450 | CPU_FTR_NAP_DISABLE_L2_PR |
 	CPU_FTR_HAS_HIGH_BATS | CPU_FTR_NEED_COHERENT,
@@ -327,7 +338,7 @@
     {	/* 7447/7457 Rev 1.0 */
     	0xffffffff, 0x80020100, "7447/7457",
 	CPU_FTR_COMMON |
-    	CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | CPU_FTR_CAN_NAP |
+    	CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | CPU_FTR_MAYBE_CAN_NAP |
 	CPU_FTR_L2CR | CPU_FTR_ALTIVEC_COMP | CPU_FTR_L3CR |
 	CPU_FTR_HPTE_TABLE | CPU_FTR_SPEC7450 | CPU_FTR_NAP_DISABLE_L2_PR |
 	CPU_FTR_HAS_HIGH_BATS | CPU_FTR_NEED_COHERENT | CPU_FTR_NO_BTIC,
@@ -338,7 +349,7 @@
     {	/* 7447/7457 Rev 1.1 */
     	0xffffffff, 0x80020101, "7447/7457",
 	CPU_FTR_COMMON |
-    	CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | CPU_FTR_CAN_NAP |
+    	CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | CPU_FTR_MAYBE_CAN_NAP |
 	CPU_FTR_L2CR | CPU_FTR_ALTIVEC_COMP | CPU_FTR_L3CR |
 	CPU_FTR_HPTE_TABLE | CPU_FTR_SPEC7450 | CPU_FTR_NAP_DISABLE_L2_PR |
 	CPU_FTR_HAS_HIGH_BATS | CPU_FTR_NEED_COHERENT | CPU_FTR_NO_BTIC,
@@ -349,7 +360,7 @@
     {	/* 7447/7457 Rev 1.2 and later */
     	0xffff0000, 0x80020000, "7447/7457",
 	CPU_FTR_COMMON |
-    	CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | CPU_FTR_CAN_NAP |
+    	CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | CPU_FTR_MAYBE_CAN_NAP |
 	CPU_FTR_L2CR | CPU_FTR_ALTIVEC_COMP | CPU_FTR_L3CR |
 	CPU_FTR_HPTE_TABLE | CPU_FTR_SPEC7450 | CPU_FTR_NAP_DISABLE_L2_PR |
 	CPU_FTR_HAS_HIGH_BATS | CPU_FTR_NEED_COHERENT,
@@ -360,7 +371,7 @@
     {	/* 7447A */
     	0xffff0000, 0x80030000, "7447A",
 	CPU_FTR_COMMON |
-    	CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | CPU_FTR_CAN_NAP |
+    	CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | CPU_FTR_MAYBE_CAN_NAP |
 	CPU_FTR_L2CR | CPU_FTR_ALTIVEC_COMP |
 	CPU_FTR_HPTE_TABLE | CPU_FTR_SPEC7450 | CPU_FTR_NAP_DISABLE_L2_PR |
 	CPU_FTR_HAS_HIGH_BATS | CPU_FTR_NEED_COHERENT,
@@ -371,15 +382,15 @@
     {	/* 82xx (8240, 8245, 8260 are all 603e cores) */
 	0x7fff0000, 0x00810000, "82xx",
 	CPU_FTR_COMMON |
-	CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_CAN_DOZE | CPU_FTR_USE_TB,
+	CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_MAYBE_CAN_DOZE | CPU_FTR_USE_TB,
 	COMMON_PPC,
 	32, 32,
 	__setup_cpu_603
     },
     {	/* All G2_LE (603e core, plus some) have the same pvr */
 	0x7fff0000, 0x00820000, "G2_LE",
-	CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_CAN_DOZE | CPU_FTR_USE_TB |
-	CPU_FTR_CAN_NAP | CPU_FTR_HAS_HIGH_BATS,
+	CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_MAYBE_CAN_DOZE | CPU_FTR_USE_TB |
+	CPU_FTR_MAYBE_CAN_NAP | CPU_FTR_HAS_HIGH_BATS,
 	COMMON_PPC,
 	32, 32,
 	__setup_cpu_603
@@ -440,7 +451,16 @@
 	0xffff0000, 0x00390000, "PPC970",
 	CPU_FTR_COMMON |
 	CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | CPU_FTR_HPTE_TABLE |
-	CPU_FTR_ALTIVEC_COMP | CPU_FTR_CAN_NAP,
+	CPU_FTR_ALTIVEC_COMP | CPU_FTR_MAYBE_CAN_NAP,
+	COMMON_PPC | PPC_FEATURE_64 | PPC_FEATURE_ALTIVEC_COMP,
+	128, 128,
+	__setup_cpu_ppc970
+    },
+    {	/* PPC970FX */
+	0xffff0000, 0x003c0000, "PPC970FX",
+	CPU_FTR_COMMON |
+	CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | CPU_FTR_HPTE_TABLE |
+	CPU_FTR_ALTIVEC_COMP | CPU_FTR_MAYBE_CAN_NAP,
 	COMMON_PPC | PPC_FEATURE_64 | PPC_FEATURE_ALTIVEC_COMP,
 	128, 128,
 	__setup_cpu_ppc970
@@ -449,7 +469,8 @@
 #ifdef CONFIG_8xx
     {	/* 8xx */
     	0xffff0000, 0x00500000, "8xx",
-		/* CPU_FTR_CAN_DOZE is possible, if the 8xx code is there.... */
+		/* CPU_FTR_MAYBE_CAN_DOZE is possible,
+		 * if the 8xx code is there.... */
     	CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB,
     	PPC_FEATURE_32 | PPC_FEATURE_HAS_MMU,
  	16, 16,
@@ -590,7 +611,7 @@
 #ifdef CONFIG_E500
     { /* e500 */
         0xffff0000, 0x80200000, "e500",
-	/* xxx - galak: add CPU_FTR_CAN_DOZE */
+	/* xxx - galak: add CPU_FTR_MAYBE_CAN_DOZE */
         CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB,
         PPC_FEATURE_32 | PPC_FEATURE_HAS_MMU,
         32, 32,
diff -Nru a/arch/ppc/kernel/dma-mapping.c b/arch/ppc/kernel/dma-mapping.c
--- a/arch/ppc/kernel/dma-mapping.c	2004-10-18 14:55:46 -07:00
+++ b/arch/ppc/kernel/dma-mapping.c	2004-10-18 14:55:46 -07:00
@@ -41,11 +41,11 @@
 #include <linux/bootmem.h>
 #include <linux/highmem.h>
 #include <linux/dma-mapping.h>
+#include <linux/hardirq.h>
 
 #include <asm/pgalloc.h>
 #include <asm/prom.h>
 #include <asm/io.h>
-#include <asm/hardirq.h>
 #include <asm/mmu_context.h>
 #include <asm/pgtable.h>
 #include <asm/mmu.h>
@@ -381,6 +381,7 @@
 		break;
 	}
 }
+EXPORT_SYMBOL(__dma_sync);
 
 #ifdef CONFIG_HIGHMEM
 /*
@@ -438,3 +439,4 @@
 	__dma_sync((void *)start, size, direction);
 #endif
 }
+EXPORT_SYMBOL(__dma_sync_page);
diff -Nru a/arch/ppc/kernel/entry.S b/arch/ppc/kernel/entry.S
--- a/arch/ppc/kernel/entry.S	2004-10-18 14:57:03 -07:00
+++ b/arch/ppc/kernel/entry.S	2004-10-18 14:57:03 -07:00
@@ -206,7 +206,7 @@
 	andi.	r11,r11,_TIF_SYSCALL_TRACE
 	bne-	syscall_dotrace
 syscall_dotrace_cont:
-	cmpli	0,r0,NR_syscalls
+	cmplwi	0,r0,NR_syscalls
 	lis	r10,sys_call_table@h
 	ori	r10,r10,sys_call_table@l
 	slwi	r0,r0,2
@@ -222,7 +222,7 @@
 #endif
 	mr	r6,r3
 	li	r11,-_LAST_ERRNO
-	cmpl	0,r3,r11
+	cmplw	0,r3,r11
 	rlwinm	r12,r1,0,0,18	/* current_thread_info() */
 	blt+	30f
 	lwz	r11,TI_LOCAL_FLAGS(r12)
diff -Nru a/arch/ppc/kernel/head.S b/arch/ppc/kernel/head.S
--- a/arch/ppc/kernel/head.S	2004-10-18 14:56:32 -07:00
+++ b/arch/ppc/kernel/head.S	2004-10-18 14:56:32 -07:00
@@ -800,7 +800,7 @@
 	tophys(r6,0)			/* get __pa constant */
 	addis	r3,r6,last_task_used_math@ha
 	lwz	r4,last_task_used_math@l(r3)
-	cmpi	0,r4,0
+	cmpwi	0,r4,0
 	beq	1f
 	add	r4,r4,r6
 	addi	r4,r4,THREAD		/* want last_task_used_math->thread */
@@ -927,7 +927,7 @@
 	tophys(r6,0)
 	addis	r3,r6,last_task_used_altivec@ha
 	lwz	r4,last_task_used_altivec@l(r3)
-	cmpi	0,r4,0
+	cmpwi	0,r4,0
 	beq	1f
 	add	r4,r4,r6
 	addi	r4,r4,THREAD	/* want THREAD of last_task_used_altivec */
@@ -992,11 +992,11 @@
 	SYNC
 	MTMSRD(r5)			/* enable use of AltiVec now */
 	isync
-	cmpi	0,r3,0
+	cmpwi	0,r3,0
 	beqlr-				/* if no previous owner, done */
 	addi	r3,r3,THREAD		/* want THREAD of task */
 	lwz	r5,PT_REGS(r3)
-	cmpi	0,r5,0
+	cmpwi	0,r5,0
 	SAVE_32VR(0, r4, r3)
 	mfvscr	vr0
 	li	r4,THREAD_VSCR
@@ -1030,11 +1030,11 @@
 	MTMSRD(r5)			/* enable use of fpu now */
 	SYNC_601
 	isync
-	cmpi	0,r3,0
+	cmpwi	0,r3,0
 	beqlr-				/* if no previous owner, done */
 	addi	r3,r3,THREAD	        /* want THREAD of task */
 	lwz	r5,PT_REGS(r3)
-	cmpi	0,r5,0
+	cmpwi	0,r5,0
 	SAVE_32FPRS(0, r3)
 	mffs	fr0
 	stfd	fr0,THREAD_FPSCR-4(r3)
@@ -1539,7 +1539,7 @@
 #ifndef CONFIG_PPC64BRIDGE
 	mfspr	r9,PVR
 	rlwinm	r9,r9,16,16,31		/* r9 = 1 for 601, 4 for 604 */
-	cmpi	0,r9,1
+	cmpwi	0,r9,1
 	bne	4f
 	ori	r11,r11,4		/* set up BAT registers for 601 */
 	li	r8,0x7f			/* valid, block length = 8MB */
@@ -1591,7 +1591,7 @@
 	lwz	r8,4(r8)
 	mfspr	r9,PVR
 	rlwinm	r9,r9,16,16,31		/* r9 = 1 for 601, 4 for 604 */
-	cmpi	0,r9,1
+	cmpwi	0,r9,1
 	beq	1f
 	mtspr	DBAT3L,r8
 	mtspr	DBAT3U,r11
diff -Nru a/arch/ppc/kernel/head_44x.S b/arch/ppc/kernel/head_44x.S
--- a/arch/ppc/kernel/head_44x.S	2004-10-18 14:56:27 -07:00
+++ b/arch/ppc/kernel/head_44x.S	2004-10-18 14:56:27 -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-10-18 14:57:21 -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-10-18 14:56:49 -07:00
+++ b/arch/ppc/kernel/head_e500.S	2004-10-18 14:56:49 -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	2004-10-18 14:55:54 -07:00
+++ b/arch/ppc/kernel/idle.c	2004-10-18 14:55:54 -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/idle_6xx.S b/arch/ppc/kernel/idle_6xx.S
--- a/arch/ppc/kernel/idle_6xx.S	2004-10-18 14:56:33 -07:00
+++ b/arch/ppc/kernel/idle_6xx.S	2004-10-18 14:56:33 -07:00
@@ -79,12 +79,12 @@
 	/* Now check if user or arch enabled NAP mode */
 	lis	r4,powersave_nap@ha
 	lwz	r4,powersave_nap@l(r4)
-	cmpi	0,r4,0
+	cmpwi	0,r4,0
 	beq	1f
 	lis	r3,HID0_NAP@h
 1:	
 END_FTR_SECTION_IFSET(CPU_FTR_CAN_NAP)
-	cmpi	0,r3,0
+	cmpwi	0,r3,0
 	beqlr
 
 	/* Clear MSR:EE */
@@ -133,7 +133,7 @@
 	/* Go to low speed mode on some 750FX */
 	lis	r4,powersave_lowspeed@ha
 	lwz	r4,powersave_lowspeed@l(r4)
-	cmpi	0,r4,0
+	cmpwi	0,r4,0
 	beq	1f
 	mfspr	r4,SPRN_HID1
 	oris	r4,r4,0x0001
diff -Nru a/arch/ppc/kernel/idle_power4.S b/arch/ppc/kernel/idle_power4.S
--- a/arch/ppc/kernel/idle_power4.S	2004-10-18 14:55:55 -07:00
+++ b/arch/ppc/kernel/idle_power4.S	2004-10-18 14:55:55 -07:00
@@ -56,7 +56,7 @@
 	/* Now check if user or arch enabled NAP mode */
 	lis	r4,powersave_nap@ha
 	lwz	r4,powersave_nap@l(r4)
-	cmpi	0,r4,0
+	cmpwi	0,r4,0
 	beqlr
 
 	/* Clear MSR:EE */
diff -Nru a/arch/ppc/kernel/irq.c b/arch/ppc/kernel/irq.c
--- a/arch/ppc/kernel/irq.c	2004-10-18 14:56:49 -07:00
+++ b/arch/ppc/kernel/irq.c	2004-10-18 14:56:49 -07:00
@@ -46,6 +46,7 @@
 #include <linux/random.h>
 #include <linux/seq_file.h>
 #include <linux/cpumask.h>
+#include <linux/profile.h>
 
 #include <asm/uaccess.h>
 #include <asm/bitops.h>
@@ -414,13 +415,15 @@
 handle_irq_event(int irq, struct pt_regs *regs, struct irqaction *action)
 {
 	int status = 0;
+	int ret;
 
 	if (!(action->flags & SA_INTERRUPT))
 		local_irq_enable();
 
 	do {
-		status |= action->flags;
-		action->handler(irq, action->dev_id, regs);
+		ret = action->handler(irq, action->dev_id, regs);
+		if (ret == IRQ_HANDLED)
+			status |= action->flags;
 		action = action->next;
 	} while (action);
 	if (status & SA_SAMPLE_RANDOM)
@@ -620,32 +623,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 +650,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-10-18 14:57:03 -07:00
+++ b/arch/ppc/kernel/misc.S	2004-10-18 14:57:03 -07:00
@@ -214,7 +214,7 @@
 	mtmsr	r0
 
 	/* If switching to PLL1, disable HID0:BTIC */
-	cmpli	cr0,r3,0
+	cmplwi	cr0,r3,0
 	beq	1f
 	mfspr	r5,HID0
 	rlwinm	r5,r5,0,27,25
@@ -239,7 +239,7 @@
 	stw	r4,nap_save_hid1@l(r6)
 
 	/* If switching to PLL0, enable HID0:BTIC */
-	cmpli	cr0,r3,0
+	cmplwi	cr0,r3,0
 	bne	1f
 	mfspr	r5,HID0
 	ori	r5,r5,HID0_BTIC
@@ -470,7 +470,7 @@
 	ori	r9,r9,mmu_hash_lock@l
 	tophys(r9,r9)
 10:	lwarx	r7,0,r9
-	cmpi	0,r7,0
+	cmpwi	0,r7,0
 	bne-	10b
 	stwcx.	r8,0,r9
 	bne-	10b
@@ -551,7 +551,7 @@
 	ori	r9,r9,mmu_hash_lock@l
 	tophys(r9,r9)
 10:	lwarx	r7,0,r9
-	cmpi	0,r7,0
+	cmpwi	0,r7,0
 	bne-	10b
 	stwcx.	r8,0,r9
 	bne-	10b
@@ -599,7 +599,7 @@
 #else
 	mfspr	r3,PVR
 	rlwinm	r3,r3,16,16,31
-	cmpi	0,r3,1
+	cmpwi	0,r3,1
 	beqlr			/* for 601, do nothing */
 	/* 603/604 processor - use invalidate-all bit in HID0 */
 	mfspr	r3,HID0
@@ -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
@@ -1144,7 +1141,7 @@
 	li	r4,0		/* new sp (unused) */
 	li	r0,__NR_clone
 	sc
-	cmpi	0,r3,0		/* parent or child? */
+	cmpwi	0,r3,0		/* parent or child? */
 	bne	1f		/* return if parent */
 	li	r0,0		/* make top-level stack frame */
 	stwu	r0,-16(r1)
diff -Nru a/arch/ppc/kernel/pci.c b/arch/ppc/kernel/pci.c
--- a/arch/ppc/kernel/pci.c	2004-10-18 14:56:29 -07:00
+++ b/arch/ppc/kernel/pci.c	2004-10-18 14:56:29 -07:00
@@ -33,6 +33,7 @@
 unsigned long isa_io_base     = 0;
 unsigned long isa_mem_base    = 0;
 unsigned long pci_dram_offset = 0;
+int pcibios_assign_bus_offset = 1;
 
 void pcibios_make_OF_bus_map(void);
 
@@ -45,11 +46,6 @@
 static int reparent_resources(struct resource *parent, struct resource *res);
 static void fixup_rev1_53c810(struct pci_dev* dev);
 static void fixup_cpc710_pci64(struct pci_dev* dev);
-#ifdef CONFIG_PPC_PMAC
-extern void pmac_pci_fixup_cardbus(struct pci_dev* dev);
-extern void pmac_pci_fixup_pciata(struct pci_dev* dev);
-extern void pmac_pci_fixup_k2_sata(struct pci_dev* dev);
-#endif
 #ifdef CONFIG_PPC_OF
 static u8* pci_to_OF_bus_map;
 #endif
@@ -64,20 +60,6 @@
 
 static int pci_bus_count;
 
-struct pci_fixup pcibios_fixups[] = {
-	{ PCI_FIXUP_HEADER,	PCI_VENDOR_ID_TRIDENT,	PCI_ANY_ID,			fixup_broken_pcnet32 },
-	{ PCI_FIXUP_HEADER,	PCI_VENDOR_ID_NCR,	PCI_DEVICE_ID_NCR_53C810,	fixup_rev1_53c810 },
-	{ PCI_FIXUP_HEADER,	PCI_VENDOR_ID_IBM,	PCI_DEVICE_ID_IBM_CPC710_PCI64,	fixup_cpc710_pci64},
-	{ PCI_FIXUP_HEADER,	PCI_ANY_ID,		PCI_ANY_ID,			pcibios_fixup_resources },
-#ifdef CONFIG_PPC_PMAC
-	/* We should add per-machine fixup support in xxx_setup.c or xxx_pci.c */
-	{ PCI_FIXUP_FINAL,	PCI_VENDOR_ID_TI,	PCI_ANY_ID,			pmac_pci_fixup_cardbus },
-	{ PCI_FIXUP_FINAL,	PCI_ANY_ID,		PCI_ANY_ID,			pmac_pci_fixup_pciata },
-	{ PCI_FIXUP_HEADER,	PCI_VENDOR_ID_SERVERWORKS, 0x0240,			pmac_pci_fixup_k2_sata },
-#endif /* CONFIG_PPC_PMAC */
- 	{ 0 }
-};
-
 static void
 fixup_rev1_53c810(struct pci_dev* dev)
 {
@@ -90,6 +72,7 @@
 		dev->class = PCI_CLASS_STORAGE_SCSI;
 	}
 }
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_NCR,	PCI_DEVICE_ID_NCR_53C810,	fixup_rev1_53c810);
 
 static void
 fixup_broken_pcnet32(struct pci_dev* dev)
@@ -100,6 +83,7 @@
 		pci_name_device(dev);
 	}
 }
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_TRIDENT,	PCI_ANY_ID,			fixup_broken_pcnet32);
 
 static void
 fixup_cpc710_pci64(struct pci_dev* dev)
@@ -112,6 +96,7 @@
 	dev->resource[1].start = dev->resource[1].end = 0;
 	dev->resource[1].flags = 0;
 }
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_IBM,	PCI_DEVICE_ID_IBM_CPC710_PCI64,	fixup_cpc710_pci64);
 
 static void
 pcibios_fixup_resources(struct pci_dev *dev)
@@ -158,9 +143,9 @@
 	if (ppc_md.pcibios_fixup_resources)
 		ppc_md.pcibios_fixup_resources(dev);
 }
+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;
@@ -173,6 +158,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
@@ -187,8 +173,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;
@@ -208,7 +193,7 @@
 		}
 	}
 }
-
+EXPORT_SYMBOL(pcibios_align_resource);
 
 /*
  *  Handle resources of PCI devices.  If the world were perfect, we could
@@ -427,7 +412,7 @@
 			r = &dev->resource[i];
 			if (!r->flags || (r->flags & IORESOURCE_UNSET))
 				continue;
-			if (pci_find_parent_resource(bus->self, r) != pr)
+			if (pci_find_parent_resource(dev, r) != pr)
 				continue;
 			if (r->end >= res->start && res->end >= r->start) {
 				*conflict = r;
@@ -1279,7 +1264,7 @@
 		bus = pci_scan_bus(hose->first_busno, hose->ops, hose);
 		hose->last_busno = bus->subordinate;
 		if (pci_assign_all_busses || next_busno <= hose->last_busno)
-			next_busno = hose->last_busno+1;
+			next_busno = hose->last_busno + pcibios_assign_bus_offset;
 	}
 	pci_bus_count = next_busno;
 
@@ -1723,6 +1708,32 @@
 	res->sibling = NULL;
 	res->child = NULL;
 }
+
+void __iomem *pci_iomap(struct pci_dev *dev, int bar, unsigned long max)
+{
+	unsigned long start = pci_resource_start(dev, bar);
+	unsigned long len = pci_resource_len(dev, bar);
+	unsigned long flags = pci_resource_flags(dev, bar);
+
+	if (!len)
+		return NULL;
+	if (max && len > max)
+		len = max;
+	if (flags & IORESOURCE_IO)
+		return ioport_map(start, len);
+	if (flags & IORESOURCE_MEM)
+		return (void __iomem *) start;
+	/* What? */
+	return NULL;
+}
+
+void pci_iounmap(struct pci_dev *dev, void __iomem *addr)
+{
+	/* Nothing to do */
+}
+EXPORT_SYMBOL(pci_iomap);
+EXPORT_SYMBOL(pci_iounmap);
+
 
 /*
  * Null PCI config access functions, for the case when we can't
diff -Nru a/arch/ppc/kernel/ppc_htab.c b/arch/ppc/kernel/ppc_htab.c
--- a/arch/ppc/kernel/ppc_htab.c	2004-10-18 14:55:54 -07:00
+++ b/arch/ppc/kernel/ppc_htab.c	2004-10-18 14:55:54 -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/ppc_ksyms.c b/arch/ppc/kernel/ppc_ksyms.c
--- a/arch/ppc/kernel/ppc_ksyms.c	2004-10-18 14:57:03 -07:00
+++ b/arch/ppc/kernel/ppc_ksyms.c	2004-10-18 14:57:03 -07:00
@@ -352,3 +352,7 @@
 extern unsigned long agp_special_page;
 EXPORT_SYMBOL(agp_special_page);
 #endif
+#if defined(CONFIG_40x) || defined(CONFIG_BOOKE)
+EXPORT_SYMBOL(__mtdcr);
+EXPORT_SYMBOL(__mfdcr);
+#endif
diff -Nru a/arch/ppc/kernel/process.c b/arch/ppc/kernel/process.c
--- a/arch/ppc/kernel/process.c	2004-10-18 14:56:29 -07:00
+++ b/arch/ppc/kernel/process.c	2004-10-18 14:56:29 -07:00
@@ -36,6 +36,7 @@
 #include <linux/module.h>
 #include <linux/kallsyms.h>
 #include <linux/mqueue.h>
+#include <linux/hardirq.h>
 
 #include <asm/pgtable.h>
 #include <asm/uaccess.h>
@@ -44,7 +45,6 @@
 #include <asm/processor.h>
 #include <asm/mmu.h>
 #include <asm/prom.h>
-#include <asm/hardirq.h>
 
 extern unsigned long _get_SP(void);
 
@@ -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-10-18 14:57:04 -07:00
+++ b/arch/ppc/kernel/setup.c	2004-10-18 14:57:04 -07:00
@@ -418,7 +418,6 @@
 	 * are used for initrd_start and initrd_size,
 	 * otherwise they contain 0xdeadbeef.
 	 */
-	cmd_line[0] = 0;
 	if (r3 >= 0x4000 && r3 < 0x800000 && r4 == 0) {
 		strlcpy(cmd_line, (char *)r3 + KERNELBASE,
 			sizeof(cmd_line));
@@ -484,6 +483,9 @@
 	char *name;
 	int offset;
 
+	if (of_stdout_device == NULL)
+		return -ENODEV;
+
 	/* The user has requested a console so this is already set up. */
 	if (strstr(saved_command_line, "console="))
 		return -EBUSY;
@@ -742,6 +744,10 @@
 	/* Initialize OCP device list */
 	ocp_early_init();
 	if ( ppc_md.progress ) ppc_md.progress("ocp: exit", 0x3eab);
+#endif
+
+#ifdef CONFIG_DUMMY_CONSOLE
+	conswitchp = &dummy_con;
 #endif
 
 	ppc_md.setup_arch();
diff -Nru a/arch/ppc/kernel/signal.c b/arch/ppc/kernel/signal.c
--- a/arch/ppc/kernel/signal.c	2004-10-18 14:57:04 -07:00
+++ b/arch/ppc/kernel/signal.c	2004-10-18 14:57:04 -07:00
@@ -270,7 +270,7 @@
 static int
 restore_user_regs(struct pt_regs *regs, struct mcontext __user *sr, int sig)
 {
-	unsigned long save_r2;
+	unsigned long save_r2 = 0;
 #if defined(CONFIG_ALTIVEC) || defined(CONFIG_SPE)
 	unsigned long msr;
 #endif
@@ -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-10-18 14:57:04 -07:00
+++ b/arch/ppc/kernel/smp.c	2004-10-18 14:57:04 -07:00
@@ -26,7 +26,6 @@
 #include <asm/irq.h>
 #include <asm/page.h>
 #include <asm/pgtable.h>
-#include <asm/hardirq.h>
 #include <asm/io.h>
 #include <asm/prom.h>
 #include <asm/smp.h>
@@ -364,22 +363,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-10-18 14:56:49 -07:00
+++ b/arch/ppc/kernel/time.c	2004-10-18 14:56:49 -07:00
@@ -108,41 +108,18 @@
 	return delta;
 }
 
-extern char _stext;
-
-static inline void ppc_do_profile (struct pt_regs *regs)
+#ifdef CONFIG_SMP
+unsigned long profile_pc(struct pt_regs *regs)
 {
-	unsigned long nip;
-	extern unsigned long prof_cpu_mask;
-
-	profile_hook(regs);
+	unsigned long pc = instruction_pointer(regs);
 
-	if (user_mode(regs))
-		return;
+	if (in_lock_functions(pc))
+		return regs->link;
 
-	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]);
+	return pc;
 }
+EXPORT_SYMBOL(profile_pc);
+#endif
 
 /*
  * timer_interrupt - gets called when the decrementer overflows,
@@ -161,10 +138,10 @@
 
 	irq_enter();
 
-	while ((next_dec = tb_ticks_per_jiffy - tb_delta(&jiffy_stamp)) < 0) {
+	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/traps.c b/arch/ppc/kernel/traps.c
--- a/arch/ppc/kernel/traps.c	2004-10-18 14:56:17 -07:00
+++ b/arch/ppc/kernel/traps.c	2004-10-18 14:56:17 -07:00
@@ -357,7 +357,7 @@
 
 /* Illegal instruction emulation support.  Originally written to
  * provide the PVR to user applications using the mfspr rd, PVR.
- * Return non-zero if we can't emulate, or EFAULT if the associated
+ * Return non-zero if we can't emulate, or -EFAULT if the associated
  * memory access caused an access fault.  Return zero on success.
  *
  * There are a couple of ways to do this, either "decode" the instruction
@@ -368,16 +368,19 @@
 #define INST_MFSPR_PVR		0x7c1f42a6
 #define INST_MFSPR_PVR_MASK	0xfc1fffff
 
+#define INST_DCBA		0x7c0005ec
+#define INST_DCBA_MASK		0x7c0007fe
+
+#define INST_MCRXR		0x7c000400
+#define INST_MCRXR_MASK		0x7c0007fe
+
 static int emulate_instruction(struct pt_regs *regs)
 {
 	u32 instword;
 	u32 rd;
-	int retval;
-
-	retval = -EINVAL;
 
 	if (!user_mode(regs))
-		return retval;
+		return -EINVAL;
 	CHECK_FULL_REGS(regs);
 
 	if (get_user(instword, (u32 __user *)(regs->nip)))
@@ -388,10 +391,24 @@
 	if ((instword & INST_MFSPR_PVR_MASK) == INST_MFSPR_PVR) {
 		rd = (instword >> 21) & 0x1f;
 		regs->gpr[rd] = mfspr(PVR);
-		retval = 0;
-		regs->nip += 4;
+		return 0;
+	}
+
+	/* Emulating the dcba insn is just a no-op.  */
+	if ((instword & INST_DCBA_MASK) == INST_DCBA)
+		return 0;
+
+	/* Emulate the mcrxr insn.  */
+	if ((instword & INST_MCRXR_MASK) == INST_MCRXR) {
+		int shift = (instword >> 21) & 0x1c;
+		unsigned long msk = 0xf0000000UL >> shift;
+
+		regs->ccr = (regs->ccr & ~msk) | ((regs->xer >> shift) & msk);
+		regs->xer &= ~0xf0000000UL;
+		return 0;
 	}
-	return retval;
+
+	return -EINVAL;
 }
 
 /*
@@ -528,17 +545,23 @@
 		return;
 	}
 
-	if (reason & REASON_PRIVILEGED) {
-		/* Try to emulate it if we should. */
-		if (emulate_instruction(regs) == 0) {
+	/* Try to emulate it if we should. */
+	if (reason & (REASON_ILLEGAL | REASON_PRIVILEGED)) {
+		switch (emulate_instruction(regs)) {
+		case 0:
+			regs->nip += 4;
 			emulate_single_step(regs);
 			return;
+		case -EFAULT:
+			_exception(SIGSEGV, regs, SEGV_MAPERR, regs->nip);
+			return;
 		}
-		_exception(SIGILL, regs, ILL_PRVOPC, regs->nip);
-		return;
 	}
 
-	_exception(SIGILL, regs, ILL_ILLOPC, regs->nip);
+	if (reason & REASON_PRIVILEGED)
+		_exception(SIGILL, regs, ILL_PRVOPC, regs->nip);
+	else
+		_exception(SIGILL, regs, ILL_ILLOPC, regs->nip);
 }
 
 void SingleStepException(struct pt_regs *regs)
diff -Nru a/arch/ppc/kernel/vector.S b/arch/ppc/kernel/vector.S
--- a/arch/ppc/kernel/vector.S	2004-10-18 14:57:04 -07:00
+++ b/arch/ppc/kernel/vector.S	2004-10-18 14:57:04 -07:00
@@ -106,7 +106,7 @@
 1:	lfsx	fr0,r4,r7
 	lfsx	fr1,r5,r7
 	lfsx	fr2,r6,r7
-	fmadds	fr0,fr0,fr1,fr2
+	fmadds	fr0,fr0,fr2,fr1
 	stfsx	fr0,r3,r7
 	addi	r7,r7,4
 	bdnz	1b
@@ -133,7 +133,7 @@
 1:	lfsx	fr0,r4,r7
 	lfsx	fr1,r5,r7
 	lfsx	fr2,r6,r7
-	fnmsubs	fr0,fr0,fr1,fr2
+	fnmsubs	fr0,fr0,fr2,fr1
 	stfsx	fr0,r3,r7
 	addi	r7,r7,4
 	bdnz	1b
diff -Nru a/arch/ppc/kernel/vmlinux.lds.S b/arch/ppc/kernel/vmlinux.lds.S
--- a/arch/ppc/kernel/vmlinux.lds.S	2004-10-18 14:57:19 -07:00
+++ b/arch/ppc/kernel/vmlinux.lds.S	2004-10-18 14:57:19 -07:00
@@ -32,6 +32,7 @@
   {
     *(.text)
     SCHED_TEXT
+    LOCK_TEXT
     *(.fixup)
     *(.got1)
     __got2_start = .;
@@ -102,9 +103,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/lib/checksum.S b/arch/ppc/lib/checksum.S
--- a/arch/ppc/lib/checksum.S	2004-10-18 14:56:27 -07:00
+++ b/arch/ppc/lib/checksum.S	2004-10-18 14:56:27 -07:00
@@ -80,13 +80,13 @@
 	adde	r0,r0,r5	/* be unnecessary to unroll this loop */
 	bdnz	2b
 	andi.	r4,r4,3
-3:	cmpi	0,r4,2
+3:	cmpwi	0,r4,2
 	blt+	4f
 	lhz	r5,4(r3)
 	addi	r3,r3,2
 	subi	r4,r4,2
 	adde	r0,r0,r5
-4:	cmpi	0,r4,1
+4:	cmpwi	0,r4,1
 	bne+	5f
 	lbz	r5,4(r3)
 	slwi	r5,r5,8		/* Upper byte of word */
@@ -143,7 +143,7 @@
 	adde	r0,r0,r9
 	bdnz	82b
 13:	andi.	r5,r5,3
-3:	cmpi	0,r5,2
+3:	cmpwi	0,r5,2
 	blt+	4f
 83:	lhz	r6,4(r3)
 	addi	r3,r3,2
@@ -151,7 +151,7 @@
 93:	sth	r6,4(r4)
 	addi	r4,r4,2
 	adde	r0,r0,r6
-4:	cmpi	0,r5,1
+4:	cmpwi	0,r5,1
 	bne+	5f
 84:	lbz	r6,4(r3)
 94:	stb	r6,4(r4)
@@ -188,7 +188,7 @@
 97:	stbu	r6,1(r4)
 	bdnz	97b
 src_error:
-	cmpi	0,r7,0
+	cmpwi	0,r7,0
 	beq	1f
 	li	r6,-EFAULT
 	stw	r6,0(r7)
@@ -196,7 +196,7 @@
 	blr
 
 dst_error:
-	cmpi	0,r8,0
+	cmpwi	0,r8,0
 	beq	1f
 	li	r6,-EFAULT
 	stw	r6,0(r8)
diff -Nru a/arch/ppc/lib/rheap.c b/arch/ppc/lib/rheap.c
--- a/arch/ppc/lib/rheap.c	2004-10-18 14:56:28 -07:00
+++ b/arch/ppc/lib/rheap.c	2004-10-18 14:56:28 -07:00
@@ -216,7 +216,7 @@
 
 	/* Grow the after block backwards */
 	if (before == NULL && after != NULL) {
-		(int8_t *) after->start -= size;
+		after->start = (int8_t *)after->start - size;
 		after->size += size;
 		return;
 	}
@@ -407,7 +407,7 @@
 	/* blk still in free list, with updated start and/or size */
 	if (bs == s || be == e) {
 		if (bs == s)
-			(int8_t *) blk->start += size;
+			blk->start = (int8_t *)blk->start + size;
 		blk->size -= size;
 
 	} else {
@@ -471,7 +471,7 @@
 	newblk->owner = owner;
 
 	/* blk still in free list, with updated start, size */
-	(int8_t *) blk->start += size;
+	blk->start = (int8_t *)blk->start + size;
 	blk->size -= size;
 
 	start = newblk->start;
@@ -535,7 +535,7 @@
 	/* blk still in free list, with updated start and/or size */
 	if (bs == s || be == e) {
 		if (bs == s)
-			(int8_t *) blk->start += size;
+			blk->start = (int8_t *)blk->start + size;
 		blk->size -= size;
 
 	} else {
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	2004-10-18 14:56:50 -07:00
+++ b/arch/ppc/math-emu/op-common.h	2004-10-18 14:56:50 -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/mm/44x_mmu.c b/arch/ppc/mm/44x_mmu.c
--- a/arch/ppc/mm/44x_mmu.c	2004-10-18 14:56:33 -07:00
+++ b/arch/ppc/mm/44x_mmu.c	2004-10-18 14:56:33 -07:00
@@ -72,7 +72,7 @@
 static void __init
 ppc44x_pin_tlb(int slot, unsigned int virt, unsigned int phys)
 {
-	unsigned long attrib;
+	unsigned long attrib = 0;
 
 	__asm__ __volatile__("\
 	clrrwi	%2,%2,10\n\
diff -Nru a/arch/ppc/mm/4xx_mmu.c b/arch/ppc/mm/4xx_mmu.c
--- a/arch/ppc/mm/4xx_mmu.c	2004-10-18 14:55:53 -07:00
+++ b/arch/ppc/mm/4xx_mmu.c	2004-10-18 14:55:53 -07:00
@@ -52,6 +52,7 @@
 #include <asm/setup.h>
 #include "mmu_decl.h"
 
+extern int __map_without_ltlbs;
 /*
  * MMU_init_hw does the chip-specific initialization of the MMU hardware.
  */
@@ -101,6 +102,10 @@
 	v = KERNELBASE;
 	p = PPC_MEMSTART;
 	s = 0;
+
+	if (__map_without_ltlbs) {
+		return s;
+	}
 
 	while (s <= (total_lowmem - LARGE_PAGE_SIZE_16M)) {
 		pmd_t *pmdp;
diff -Nru a/arch/ppc/mm/init.c b/arch/ppc/mm/init.c
--- a/arch/ppc/mm/init.c	2004-10-18 14:56:19 -07:00
+++ b/arch/ppc/mm/init.c	2004-10-18 14:56:19 -07:00
@@ -104,6 +104,7 @@
  * -- Cort
  */
 int __map_without_bats;
+int __map_without_ltlbs;
 
 /* max amount of RAM to use */
 unsigned long __max_memory;
@@ -202,6 +203,10 @@
 	/* Check for nobats option (used in mapin_ram). */
 	if (strstr(cmd_line, "nobats")) {
 		__map_without_bats = 1;
+	}
+
+	if (strstr(cmd_line, "noltlbs")) {
+		__map_without_ltlbs = 1;
 	}
 
 	/* Look for mem= option on command line */
diff -Nru a/arch/ppc/mm/pgtable.c b/arch/ppc/mm/pgtable.c
--- a/arch/ppc/mm/pgtable.c	2004-10-18 14:56:17 -07:00
+++ b/arch/ppc/mm/pgtable.c	2004-10-18 14:56:17 -07:00
@@ -22,6 +22,7 @@
 
 #include <linux/config.h>
 #include <linux/kernel.h>
+#include <linux/module.h>
 #include <linux/types.h>
 #include <linux/mm.h>
 #include <linux/vmalloc.h>
@@ -270,6 +271,18 @@
 	if (addr > high_memory && (unsigned long) addr < ioremap_bot)
 		vunmap((void *) (PAGE_MASK & (unsigned long)addr));
 }
+
+void __iomem *ioport_map(unsigned long port, unsigned int len)
+{
+	return (void __iomem *) (port + _IO_BASE);
+}
+
+void ioport_unmap(void __iomem *addr)
+{
+	/* Nothing to do */
+}
+EXPORT_SYMBOL(ioport_map);
+EXPORT_SYMBOL(ioport_unmap);
 
 int
 map_page(unsigned long va, phys_addr_t pa, int flags)
diff -Nru a/arch/ppc/platforms/4xx/ebony.c b/arch/ppc/platforms/4xx/ebony.c
--- a/arch/ppc/platforms/4xx/ebony.c	2004-10-18 14:57:05 -07:00
+++ b/arch/ppc/platforms/4xx/ebony.c	2004-10-18 14:57:05 -07:00
@@ -4,9 +4,11 @@
  * Ebony board specific routines
  *
  * Matt Porter <mporter@mvista.com>
- *
  * Copyright 2002 MontaVista Software Inc.
  *
+ * Eugene Surovegin <eugene.surovegin@zultys.com> or <ebs@ebshome.net>
+ * Copyright (c) 2003, 2004 Zultys Technologies
+ *
  * 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
@@ -118,7 +120,7 @@
 	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* 63: EMAC 1 WOL */
 };
 
-extern void abort(void);
+static struct ibm44x_clocks clocks __initdata;
 
 static void __init
 ebony_calibrate_decr(void)
@@ -143,18 +145,7 @@
 			break;
 	}
 
-	tb_ticks_per_jiffy = freq / HZ;
-	tb_to_us = mulhwu_scale_factor(freq, 1000000);
-
-	/* Set the time base to zero */
-	mtspr(SPRN_TBWL, 0);
-	mtspr(SPRN_TBWU, 0);
-
-	/* Clear any pending timer interrupts */
-	mtspr(SPRN_TSR, TSR_ENW | TSR_WIS | TSR_DIS | TSR_FIS);
-
-	/* Enable decrementer interrupt */
-	mtspr(SPRN_TCR, TCR_DIE);
+	ibm44x_calibrate_decr(freq);
 }
 
 static int
@@ -283,7 +274,7 @@
 	memset(&port, 0, sizeof(port));
 	port.membase = ioremap64(PPC440GP_UART0_ADDR, 8);
 	port.irq = 0;
-	port.uartclk = BASE_BAUD * 16;
+	port.uartclk = clocks.uart0;
 	port.regshift = 0;
 	port.iotype = SERIAL_IO_MEM;
 	port.flags = ASYNC_BOOT_AUTOCONF | ASYNC_SKIP_TEST;
@@ -306,7 +297,6 @@
 ebony_setup_arch(void)
 {
 	unsigned char * vpd_base;
-	struct ibm44x_clocks clocks;
 	struct ocp_def *def;
 	struct ocp_func_emac_data *emacdata;
 
@@ -361,10 +351,6 @@
 		ROOT_DEV = Root_HDA1;
 #endif
 
-#ifdef CONFIG_VT
-	conswitchp = &dummy_con;
-#endif
-
 	ebony_early_serial_map();
 
 	ibm4xxPIC_InitSenses = ebony_IRQ_initsenses;
@@ -374,152 +360,17 @@
 	printk("IBM Ebony port (MontaVista Software, Inc. (source@mvista.com))\n");
 }
 
-static void
-ebony_restart(char *cmd)
-{
-	local_irq_disable();
-	abort();
-}
-
-static void
-ebony_power_off(void)
-{
-	local_irq_disable();
-	for(;;);
-}
-
-static void
-ebony_halt(void)
-{
-	local_irq_disable();
-	for(;;);
-}
-
-/*
- * Read the 440GP memory controller to get size of system memory.
- */
-static unsigned long __init
-ebony_find_end_of_memory(void)
-{
-	u32 i, bank_config;
-	u32 mem_size = 0;
-
-	for (i=0; i<4; i++)
-	{
-		switch (i)
-		{
-			case 0:
-				mtdcr(DCRN_SDRAM0_CFGADDR, SDRAM0_B0CR);
-				break;
-			case 1:
-				mtdcr(DCRN_SDRAM0_CFGADDR, SDRAM0_B1CR);
-				break;
-			case 2:
-				mtdcr(DCRN_SDRAM0_CFGADDR, SDRAM0_B2CR);
-				break;
-			case 3:
-				mtdcr(DCRN_SDRAM0_CFGADDR, SDRAM0_B3CR);
-				break;
-		}
-
-		bank_config = mfdcr(DCRN_SDRAM0_CFGDATA);
-
-		if (!(bank_config & SDRAM_CONFIG_BANK_ENABLE))
-			continue;
-		switch (SDRAM_CONFIG_BANK_SIZE(bank_config))
-		{
-			case SDRAM_CONFIG_SIZE_8M:
-				mem_size += PPC44x_MEM_SIZE_8M;
-				break;
-			case SDRAM_CONFIG_SIZE_16M:
-				mem_size += PPC44x_MEM_SIZE_16M;
-				break;
-			case SDRAM_CONFIG_SIZE_32M:
-				mem_size += PPC44x_MEM_SIZE_32M;
-				break;
-			case SDRAM_CONFIG_SIZE_64M:
-				mem_size += PPC44x_MEM_SIZE_64M;
-				break;
-			case SDRAM_CONFIG_SIZE_128M:
-				mem_size += PPC44x_MEM_SIZE_128M;
-				break;
-			case SDRAM_CONFIG_SIZE_256M:
-				mem_size += PPC44x_MEM_SIZE_256M;
-				break;
-			case SDRAM_CONFIG_SIZE_512M:
-				mem_size += PPC44x_MEM_SIZE_512M;
-				break;
-		}
-	}
-	return mem_size;
-}
-
-static void __init
-ebony_init_irq(void)
-{
-	int i;
-
-	ppc4xx_pic_init();
-
-	for (i = 0; i < NR_IRQS; i++)
-		irq_desc[i].handler = ppc4xx_pic;
-}
-
-#ifdef CONFIG_SERIAL_TEXT_DEBUG
-#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> */
-};
-
-static void
-ebony_progress(char *s, unsigned short hex)
-{
-	volatile char c;
-	volatile unsigned long com_port;
-	u16 shift;
-
-	com_port = (unsigned long)rs_table[0].iomem_base;
-	shift = rs_table[0].iomem_reg_shift;
-
-	while ((c = *s++) != 0) {
-		while ((*((volatile unsigned char *)com_port +
-				(UART_LSR << shift)) & UART_LSR_THRE) == 0)
-			;
-		*(volatile unsigned char *)com_port = c;
-
-	}
-
-	/* Send LF/CR to pretty up output */
-	while ((*((volatile unsigned char *)com_port +
-		(UART_LSR << shift)) & UART_LSR_THRE) == 0)
-		;
-	*(volatile unsigned char *)com_port = '\r';
-	while ((*((volatile unsigned char *)com_port +
-		(UART_LSR << shift)) & UART_LSR_THRE) == 0)
-		;
-	*(volatile unsigned char *)com_port = '\n';
-}
-#endif /* CONFIG_SERIAL_TEXT_DEBUG */
-
 void __init platform_init(unsigned long r3, unsigned long r4,
 		unsigned long r5, unsigned long r6, unsigned long r7)
 {
 	parse_bootinfo((struct bi_record *) (r3 + KERNELBASE));
 
+	ibm44x_platform_init();
+
 	ppc_md.setup_arch = ebony_setup_arch;
 	ppc_md.show_cpuinfo = ebony_show_cpuinfo;
-	ppc_md.init_IRQ = ebony_init_irq;
 	ppc_md.get_irq = NULL;		/* Set in ppc4xx_pic_init() */
 
-	ppc_md.find_end_of_memory = ebony_find_end_of_memory;
-
-	ppc_md.restart = ebony_restart;
-	ppc_md.power_off = ebony_power_off;
-	ppc_md.halt = ebony_halt;
-
 	ppc_md.calibrate_decr = ebony_calibrate_decr;
 	ppc_md.time_init = todc_time_init;
 	ppc_md.set_rtc_time = todc_set_rtc_time;
@@ -528,9 +379,6 @@
 	ppc_md.nvram_read_val = todc_direct_read_val;
 	ppc_md.nvram_write_val = todc_direct_write_val;
 
-#ifdef CONFIG_SERIAL_TEXT_DEBUG
-	ppc_md.progress = ebony_progress;
-#endif /* CONFIG_SERIAL_TEXT_DEBUG */
 #ifdef CONFIG_KGDB
 	ppc_md.early_serial_map = ebony_early_serial_map;
 #endif
diff -Nru a/arch/ppc/platforms/4xx/ebony.h b/arch/ppc/platforms/4xx/ebony.h
--- a/arch/ppc/platforms/4xx/ebony.h	2004-10-18 14:56:49 -07:00
+++ b/arch/ppc/platforms/4xx/ebony.h	2004-10-18 14:56:49 -07:00
@@ -40,21 +40,21 @@
 #define EBONY_RTC_SIZE		0x2000
 
 /* Flash */
-#define EBONY_FPGA_ADDR		0x0000000148300000
+#define EBONY_FPGA_ADDR		0x0000000148300000ULL
 #define EBONY_BOOT_SMALL_FLASH(x)	(x & 0x20)
 #define EBONY_ONBRD_FLASH_EN(x)		(x & 0x02)
 #define EBONY_FLASH_SEL(x)		(x & 0x01)
-#define EBONY_SMALL_FLASH_LOW1	0x00000001ff800000
-#define EBONY_SMALL_FLASH_LOW2	0x00000001ff880000
-#define EBONY_SMALL_FLASH_HIGH1	0x00000001fff00000
-#define EBONY_SMALL_FLASH_HIGH2	0x00000001fff80000
+#define EBONY_SMALL_FLASH_LOW1	0x00000001ff800000ULL
+#define EBONY_SMALL_FLASH_LOW2	0x00000001ff880000ULL
+#define EBONY_SMALL_FLASH_HIGH1	0x00000001fff00000ULL
+#define EBONY_SMALL_FLASH_HIGH2	0x00000001fff80000ULL
 #define EBONY_SMALL_FLASH_SIZE	0x80000
-#define EBONY_LARGE_FLASH_LOW	0x00000001ff800000
-#define EBONY_LARGE_FLASH_HIGH	0x00000001ffc00000
+#define EBONY_LARGE_FLASH_LOW	0x00000001ff800000ULL
+#define EBONY_LARGE_FLASH_HIGH	0x00000001ffc00000ULL
 #define EBONY_LARGE_FLASH_SIZE	0x400000
 
-#define EBONY_SMALL_FLASH_BASE	0x00000001fff80000
-#define EBONY_LARGE_FLASH_BASE	0x00000001ff800000
+#define EBONY_SMALL_FLASH_BASE	0x00000001fff80000ULL
+#define EBONY_LARGE_FLASH_BASE	0x00000001ff800000ULL
 
 /*
  * Serial port defines
diff -Nru a/arch/ppc/platforms/4xx/ocotea.c b/arch/ppc/platforms/4xx/ocotea.c
--- a/arch/ppc/platforms/4xx/ocotea.c	2004-10-18 14:56:50 -07:00
+++ b/arch/ppc/platforms/4xx/ocotea.c	2004-10-18 14:56:50 -07:00
@@ -47,6 +47,7 @@
 #include <asm/todc.h>
 #include <asm/bootinfo.h>
 #include <asm/ppc4xx_pic.h>
+#include <asm/ppcboot.h>
 
 #include <syslib/ibm440gx_common.h>
 
@@ -57,27 +58,21 @@
  */
 #include "../../../../drivers/net/ibm_emac/ibm_emac_phy.h"
 
-extern void abort(void);
+bd_t __res;
+
+static struct ibm44x_clocks clocks __initdata;
 
 static void __init
 ocotea_calibrate_decr(void)
 {
 	unsigned int freq;
 
-	freq = OCOTEA_SYSCLK;
-
-	tb_ticks_per_jiffy = freq / HZ;
-	tb_to_us = mulhwu_scale_factor(freq, 1000000);
-
-	/* Set the time base to zero */
-	mtspr(SPRN_TBWL, 0);
-	mtspr(SPRN_TBWU, 0);
-
-	/* Clear any pending timer interrupts */
-	mtspr(SPRN_TSR, TSR_ENW | TSR_WIS | TSR_DIS | TSR_FIS);
+	if (mfspr(SPRN_CCR1) & CCR1_TCS)
+		freq = OCOTEA_TMR_CLK;
+	else
+		freq = clocks.cpu;
 
-	/* Enable decrementer interrupt */
-	mtspr(SPRN_TCR, TCR_DIE);
+	ibm44x_calibrate_decr(freq);
 }
 
 static int
@@ -88,6 +83,7 @@
 
 	return 0;
 }
+
 static inline int
 ocotea_map_irq(struct pci_dev *dev, unsigned char idsel, unsigned char pin)
 {
@@ -107,6 +103,46 @@
 	return PCI_IRQ_TABLE_LOOKUP;
 }
 
+static void __init ocotea_set_emacdata(void)
+{
+	struct ocp_def *def;
+	struct ocp_func_emac_data *emacdata;
+	int i;
+
+	/*
+	 * Note: Current rev. board only operates in Group 4a
+	 * mode, so we always set EMAC0-1 for SMII and EMAC2-3
+	 * for RGMII (though these could run in RTBI just the same).
+	 *
+	 * The FPGA reg 3 information isn't even suitable for
+	 * determining the phy_mode, so if the board becomes
+	 * usable in !4a, it will be necessary to parse an environment
+	 * variable from the firmware or similar to properly configure
+	 * the phy_map/phy_mode.
+	 */
+	/* Set phy_map, phy_mode, and mac_addr for each EMAC */
+	for (i=0; i<4; i++) {
+		def = ocp_get_one_device(OCP_VENDOR_IBM, OCP_FUNC_EMAC, i);
+		emacdata = def->additions;
+		if (i < 2) {
+			emacdata->phy_map = 0x00000001;	/* Skip 0x00 */
+			emacdata->phy_mode = PHY_MODE_SMII;
+		}
+		else {
+			emacdata->phy_map = 0x0000ffff; /* Skip 0x00-0x0f */
+			emacdata->phy_mode = PHY_MODE_RGMII;
+		}
+		if (i == 0)
+			memcpy(emacdata->mac_addr, __res.bi_enetaddr, 6);
+		else if (i == 1)
+			memcpy(emacdata->mac_addr, __res.bi_enet1addr, 6);
+		else if (i == 2)
+			memcpy(emacdata->mac_addr, __res.bi_enet2addr, 6);
+		else if (i == 3)
+			memcpy(emacdata->mac_addr, __res.bi_enet3addr, 6);
+	}
+}
+
 #define PCIX_READW(offset) \
 	(readw((u32)pcix_reg_base+offset))
 
@@ -209,7 +245,7 @@
 TODC_ALLOC();
 
 static void __init
-ocotea_early_serial_map(const struct ibm44x_clocks *clks)
+ocotea_early_serial_map(void)
 {
 	struct uart_port port;
 
@@ -217,7 +253,7 @@
 	memset(&port, 0, sizeof(port));
 	port.membase = ioremap64(PPC440GX_UART0_ADDR, 8);
 	port.irq = UART0_INT;
-	port.uartclk = clks->uart0;
+	port.uartclk = clocks.uart0;
 	port.regshift = 0;
 	port.iotype = SERIAL_IO_MEM;
 	port.flags = ASYNC_BOOT_AUTOCONF | ASYNC_SKIP_TEST;
@@ -229,7 +265,7 @@
 
 	port.membase = ioremap64(PPC440GX_UART1_ADDR, 8);
 	port.irq = UART1_INT;
-	port.uartclk = clks->uart1;
+	port.uartclk = clocks.uart1;
 	port.line = 1;
 
 	if (early_serial_setup(&port) != 0) {
@@ -240,41 +276,7 @@
 static void __init
 ocotea_setup_arch(void)
 {
-	unsigned char *addr;
-	unsigned long long mac64;
-	struct ocp_def *def;
-	struct ocp_func_emac_data *emacdata;
-	int i;
-	struct ibm44x_clocks clocks;
-
-	/*
-	 * Note: Current rev. board only operates in Group 4a
-	 * mode, so we always set EMAC0-1 for SMII and EMAC2-3
-	 * for RGMII (though these could run in RTBI just the same).
-	 *
-	 * The FPGA reg 3 information isn't even suitable for
-	 * determining the phy_mode, so if the board becomes
-	 * usable in !4a, it will be necessary to parse an environment
-	 * variable from the firmware or similar to properly configure
-	 * the phy_map/phy_mode.
-	 */
-	/* Set phy_map, phy_mode, and mac_addr for each EMAC */
-	addr = ioremap64(OCOTEA_MAC_BASE, OCOTEA_MAC_SIZE);
-	for (i=0; i<4; i++) {
-		mac64 = simple_strtoull(addr+OCOTEA_MAC_OFFSET*i, 0, 16);
-		def = ocp_get_one_device(OCP_VENDOR_IBM, OCP_FUNC_EMAC, i);
-		emacdata = def->additions;
-		if (i < 2) {
-			emacdata->phy_map = 0x00000001;	/* Skip 0x00 */
-			emacdata->phy_mode = PHY_MODE_SMII;
-		}
-		else {
-			emacdata->phy_map = 0x0000ffff; /* Skip 0x00-0x0f */
-			emacdata->phy_mode = PHY_MODE_RGMII;
-		}
-		memcpy(emacdata->mac_addr, (char *)&mac64+2, 6);
-	}
-	iounmap(addr);
+	ocotea_set_emacdata();
 
 	ibm440gx_tah_enable();
 
@@ -319,173 +321,33 @@
 		ROOT_DEV = Root_HDA1;
 #endif
 
-#ifdef CONFIG_DUMMY_CONSOLE
-	conswitchp = &dummy_con;
-#endif
-
-	ocotea_early_serial_map(&clocks);
+	ocotea_early_serial_map();
 
 	/* Identify the system */
 	printk("IBM Ocotea port (MontaVista Software, Inc. <source@mvista.com>)\n");
 }
 
-static void
-ocotea_restart(char *cmd)
-{
-	local_irq_disable();
-	abort();
-}
-
-static void
-ocotea_power_off(void)
-{
-	local_irq_disable();
-	for(;;);
-}
-
-static void
-ocotea_halt(void)
-{
-	local_irq_disable();
-	for(;;);
-}
-
-/*
- * Read the 440GX memory controller to get size of system memory.
- */
-static unsigned long __init
-ocotea_find_end_of_memory(void)
-{
-	u32 i, bank_config;
-	u32 mem_size = 0;
-
-	for (i=0; i<4; i++)
-	{
-		switch (i)
-		{
-			case 0:
-				mtdcr(DCRN_SDRAM0_CFGADDR, SDRAM0_B0CR);
-				break;
-			case 1:
-				mtdcr(DCRN_SDRAM0_CFGADDR, SDRAM0_B1CR);
-				break;
-			case 2:
-				mtdcr(DCRN_SDRAM0_CFGADDR, SDRAM0_B2CR);
-				break;
-			case 3:
-				mtdcr(DCRN_SDRAM0_CFGADDR, SDRAM0_B3CR);
-				break;
-		}
-
-		bank_config = mfdcr(DCRN_SDRAM0_CFGDATA);
-
-		if (!(bank_config & SDRAM_CONFIG_BANK_ENABLE))
-			continue;
-		switch (SDRAM_CONFIG_BANK_SIZE(bank_config))
-		{
-			case SDRAM_CONFIG_SIZE_8M:
-				mem_size += PPC44x_MEM_SIZE_8M;
-				break;
-			case SDRAM_CONFIG_SIZE_16M:
-				mem_size += PPC44x_MEM_SIZE_16M;
-				break;
-			case SDRAM_CONFIG_SIZE_32M:
-				mem_size += PPC44x_MEM_SIZE_32M;
-				break;
-			case SDRAM_CONFIG_SIZE_64M:
-				mem_size += PPC44x_MEM_SIZE_64M;
-				break;
-			case SDRAM_CONFIG_SIZE_128M:
-				mem_size += PPC44x_MEM_SIZE_128M;
-				break;
-			case SDRAM_CONFIG_SIZE_256M:
-				mem_size += PPC44x_MEM_SIZE_256M;
-				break;
-			case SDRAM_CONFIG_SIZE_512M:
-				mem_size += PPC44x_MEM_SIZE_512M;
-				break;
-		}
-	}
-	return mem_size;
-}
-
-static void __init
-ocotea_init_irq(void)
-{
-	int i;
-
-	ppc4xx_pic_init();
-
-	for (i = 0; i < NR_IRQS; i++)
-		irq_desc[i].handler = ppc4xx_pic;
-}
-
-#ifdef CONFIG_SERIAL_TEXT_DEBUG
-#include <linux/serialP.h>
-#include <linux/serial_reg.h>
-#include <asm/serial.h>
-struct serial_state rs_table[RS_TABLE_SIZE] = {
-	SERIAL_PORT_DFNS	/* Defined in <asm/serial.h> */
-};
-
-static void
-ocotea_progress(char *s, unsigned short hex)
-{
-	volatile char c;
-	volatile unsigned long com_port;
-	u16 shift;
-
-	com_port = (unsigned long)rs_table[0].iomem_base;
-	shift = rs_table[0].iomem_reg_shift;
-
-	while ((c = *s++) != 0) {
-		while ((*((volatile unsigned char *)com_port +
-				(UART_LSR << shift)) & UART_LSR_THRE) == 0)
-			;
-		*(volatile unsigned char *)com_port = c;
-
-	}
-
-	/* Send LF/CR to pretty up output */
-	while ((*((volatile unsigned char *)com_port +
-		(UART_LSR << shift)) & UART_LSR_THRE) == 0)
-		;
-	*(volatile unsigned char *)com_port = '\r';
-	while ((*((volatile unsigned char *)com_port +
-		(UART_LSR << shift)) & UART_LSR_THRE) == 0)
-		;
-	*(volatile unsigned char *)com_port = '\n';
-}
-#endif /* CONFIG_SERIAL_TEXT_DEBUG */
-
-#if 0
-static void __init
-ocotea_map_io(void)
-{
-	io_block_mapping(0xe0000000, 0x0000000140000000,
-			 0x00001000, _PAGE_IO);
-}
-#endif
-
 void __init platform_init(unsigned long r3, unsigned long r4,
 		unsigned long r5, unsigned long r6, unsigned long r7)
 {
-	parse_bootinfo((struct bi_record *) (r3 + KERNELBASE));
+	parse_bootinfo(find_bootinfo());
+
+	/*
+	 * If we were passed in a board information, copy it into the
+	 * residual data area.
+	 */
+	if (r3)
+		__res = *(bd_t *)(r3 + KERNELBASE);
 
 	/* Disable L2-Cache due to hardware issues */
 	ibm440gx_l2c_disable();
 
+	ibm44x_platform_init();
+
 	ppc_md.setup_arch = ocotea_setup_arch;
 	ppc_md.show_cpuinfo = ocotea_show_cpuinfo;
-	ppc_md.init_IRQ = ocotea_init_irq;
 	ppc_md.get_irq = NULL;		/* Set in ppc4xx_pic_init() */
 
-	ppc_md.find_end_of_memory = ocotea_find_end_of_memory;
-
-	ppc_md.restart = ocotea_restart;
-	ppc_md.power_off = ocotea_power_off;
-	ppc_md.halt = ocotea_halt;
-
 	ppc_md.calibrate_decr = ocotea_calibrate_decr;
 	ppc_md.time_init = todc_time_init;
 	ppc_md.set_rtc_time = todc_set_rtc_time;
@@ -494,9 +356,6 @@
 	ppc_md.nvram_read_val = todc_direct_read_val;
 	ppc_md.nvram_write_val = todc_direct_write_val;
 
-#ifdef CONFIG_SERIAL_TEXT_DEBUG
-	ppc_md.progress = ocotea_progress;
-#endif /* CONFIG_SERIAL_TEXT_DEBUG */
 #ifdef CONFIG_KGDB
 	ppc_md.early_serial_map = ocotea_early_serial_map;
 #endif
diff -Nru a/arch/ppc/platforms/4xx/ocotea.h b/arch/ppc/platforms/4xx/ocotea.h
--- a/arch/ppc/platforms/4xx/ocotea.h	2004-10-18 14:56:29 -07:00
+++ b/arch/ppc/platforms/4xx/ocotea.h	2004-10-18 14:56:29 -07:00
@@ -24,13 +24,14 @@
 /* F/W TLB mapping used in bootloader glue to reset EMAC */
 #define PPC44x_EMAC0_MR0	0xE0000800
 
-/* Location of MAC addresses in firmware */
-#define OCOTEA_MAC_BASE		(OCOTEA_SMALL_FLASH_HIGH+0xb0500)
-#define OCOTEA_MAC_SIZE		0x200
-#define OCOTEA_MAC_OFFSET	0x100
+/* Location of MAC addresses in PIBS image */
+#define OCOTEA_PIBS_FLASH	0xfff00000
+#define OCOTEA_PIBS_MAC_BASE	(OCOTEA_PIBS_FLASH+0xb0500)
+#define OCOTEA_PIBS_MAC_SIZE	0x200
+#define OCOTEA_PIBS_MAC_OFFSET	0x100
 
-/* Default clock rate */
-#define OCOTEA_SYSCLK		25000000
+/* External timer clock frequency */
+#define OCOTEA_TMR_CLK	25000000
 
 /* RTC/NVRAM location */
 #define OCOTEA_RTC_ADDR		0x0000000148000000ULL
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-10-18 14:56:28 -07:00
+++ b/arch/ppc/platforms/85xx/mpc8540_ads.c	2004-10-18 14:56:28 -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-10-18 14:57:03 -07:00
+++ b/arch/ppc/platforms/85xx/mpc85xx_cds_common.c	2004-10-18 14:57:03 -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-10-18 14:56:19 -07:00
+++ b/arch/ppc/platforms/85xx/sbc8560.c	2004-10-18 14:56:19 -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-10-18 14:57:05 -07:00
+++ b/arch/ppc/platforms/Makefile	2004-10-18 14:57:05 -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-10-18 14:56:50 -07:00
+++ b/arch/ppc/platforms/chrp_setup.c	2004-10-18 14:56:50 -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
 	 */
@@ -382,7 +375,7 @@
 {
 	struct device_node *np;
 	int i;
-	unsigned long chrp_int_ack;
+	unsigned long chrp_int_ack = 0;
 	unsigned char init_senses[NR_IRQS - NUM_8259_INTERRUPTS];
 #if defined(CONFIG_VT) && defined(CONFIG_INPUT_ADBHID) && defined(XMON)
 	struct device_node *kbd;
diff -Nru a/arch/ppc/platforms/chrp_smp.c b/arch/ppc/platforms/chrp_smp.c
--- a/arch/ppc/platforms/chrp_smp.c	2004-10-18 14:56:28 -07:00
+++ b/arch/ppc/platforms/chrp_smp.c	2004-10-18 14:56:28 -07:00
@@ -24,7 +24,6 @@
 #include <asm/irq.h>
 #include <asm/page.h>
 #include <asm/pgtable.h>
-#include <asm/hardirq.h>
 #include <asm/sections.h>
 #include <asm/io.h>
 #include <asm/prom.h>
diff -Nru a/arch/ppc/platforms/est8260.h b/arch/ppc/platforms/est8260.h
--- a/arch/ppc/platforms/est8260.h	2004-10-18 14:56:49 -07:00
+++ b/arch/ppc/platforms/est8260.h	2004-10-18 14:56:49 -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	2004-10-18 14:55:54 -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-10-18 14:55:54 -07:00
+++ b/arch/ppc/platforms/k2.c	2004-10-18 14:55:54 -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/lite5200.c b/arch/ppc/platforms/lite5200.c
--- a/arch/ppc/platforms/lite5200.c	2004-10-18 14:55:53 -07:00
+++ b/arch/ppc/platforms/lite5200.c	2004-10-18 14:55:53 -07:00
@@ -36,6 +36,8 @@
 #include <asm/mpc52xx.h>
 
 
+extern int powersave_nap;
+
 /* Board data given by U-Boot */
 bd_t __res;
 EXPORT_SYMBOL(__res);	/* For modules */
@@ -64,25 +66,55 @@
 		.vendor		= OCP_VENDOR_INVALID
 	}
 };
-	
+
 
 /* ======================================================================== */
 /* Platform specific code                                                   */
 /* ======================================================================== */
 
 static int
-icecube_show_cpuinfo(struct seq_file *m)
+lite5200_show_cpuinfo(struct seq_file *m)
 {
 	seq_printf(m, "machine\t\t: Freescale LITE5200\n");
 	return 0;
 }
 
 static void __init
-icecube_setup_arch(void)
+lite5200_setup_cpu(void)
 {
+	struct mpc52xx_intr *intr;
+
+	u32 intr_ctrl;
+
+	/* Map zones */
+	intr = (struct mpc52xx_intr *)
+		ioremap(MPC52xx_INTR,sizeof(struct mpc52xx_intr));
+
+	if (!intr) {
+		printk("lite5200.c: Error while mapping INTR during lite5200_setup_cpu\n");
+		goto unmap_regs;
+	}
+
+	/* IRQ[0-3] setup : IRQ0     - Level Active Low  */
+	/*                  IRQ[1-3] - Level Active High */
+	intr_ctrl = in_be32(&intr->ctrl);
+	intr_ctrl &= ~0x00ff0000;
+	intr_ctrl |=  0x00c00000;
+	out_be32(&intr->ctrl, intr_ctrl);
+
+	/* Unmap reg zone */
+unmap_regs:
+	if (intr) iounmap(intr);
+}
 
+static void __init
+lite5200_setup_arch(void)
+{
 	/* Add board OCP definitions */
 	mpc52xx_add_board_devices(board_ocp);
+
+	/* CPU & Port mux setup */
+	lite5200_setup_cpu();
 }
 
 void __init
@@ -110,7 +142,7 @@
 			initrd_end = r5 + KERNELBASE;
 		}
 #endif
-	
+
 		/* Load the command line */
 		if (r6) {
 			*(char *)(r7+KERNELBASE) = 0;
@@ -120,14 +152,17 @@
 
 	/* BAT setup */
 	mpc52xx_set_bat();
-	
+
 	/* No ISA bus AFAIK */
 	isa_io_base		= 0;
 	isa_mem_base		= 0;
 
+	/* Powersave */
+	powersave_nap = 1;	/* We allow this platform to NAP */
+
 	/* Setup the ppc_md struct */
-	ppc_md.setup_arch	= icecube_setup_arch;
-	ppc_md.show_cpuinfo	= icecube_show_cpuinfo;
+	ppc_md.setup_arch	= lite5200_setup_arch;
+	ppc_md.show_cpuinfo	= lite5200_show_cpuinfo;
 	ppc_md.show_percpuinfo	= NULL;
 	ppc_md.init_IRQ		= mpc52xx_init_irq;
 	ppc_md.get_irq		= mpc52xx_get_irq;
@@ -138,12 +173,12 @@
 	ppc_md.restart		= mpc52xx_restart;
 	ppc_md.power_off	= mpc52xx_power_off;
 	ppc_md.halt		= mpc52xx_halt;
-	
-		/* No time keeper on the IceCube */
+
+		/* No time keeper on the LITE5200 */
 	ppc_md.time_init	= NULL;
 	ppc_md.get_rtc_time	= NULL;
 	ppc_md.set_rtc_time	= NULL;
-	
+
 	ppc_md.calibrate_decr	= mpc52xx_calibrate_decr;
 #ifdef CONFIG_SERIAL_TEXT_DEBUG
 	ppc_md.progress		= mpc52xx_progress;
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-10-18 14:56:32 -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-10-18 14:57:03 -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	2004-10-18 14:56:32 -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	2004-10-18 14:57:03 -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-10-18 14:56:32 -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-10-18 14:56:48 -07:00
+++ b/arch/ppc/platforms/mcpn765.c	2004-10-18 14:56:48 -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	2004-10-18 14:56:21 -07:00
+++ b/arch/ppc/platforms/mcpn765.h	2004-10-18 14:56:21 -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	2004-10-18 14:56:49 -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/mpc5200.c b/arch/ppc/platforms/mpc5200.c
--- a/arch/ppc/platforms/mpc5200.c	2004-10-18 14:56:17 -07:00
+++ b/arch/ppc/platforms/mpc5200.c	2004-10-18 14:56:17 -07:00
@@ -16,6 +16,12 @@
 #include <asm/ocp.h>
 #include <asm/mpc52xx.h>
 
+
+struct ocp_fs_i2c_data mpc5200_i2c_def = {
+        .flags  = FS_I2C_CLOCK_5200,
+};
+
+
 /* Here is the core_ocp struct.
  * With all the devices common to all board. Even if port multiplexing is
  * not setup for them (if the user don't want them, just don't select the
@@ -23,6 +29,24 @@
  * board specific file.
  */
 struct ocp_def core_ocp[] = {
+	{
+		.vendor         = OCP_VENDOR_FREESCALE,
+		.function       = OCP_FUNC_IIC,
+		.index          = 0,
+		.paddr          = MPC52xx_I2C1,
+		.irq            = OCP_IRQ_NA,   /* MPC52xx_IRQ_I2C1 - Buggy */
+		.pm             = OCP_CPM_NA,
+		.additions      = &mpc5200_i2c_def,
+	},
+	{
+		.vendor         = OCP_VENDOR_FREESCALE,
+		.function       = OCP_FUNC_IIC,
+		.index          = 1,
+		.paddr          = MPC52xx_I2C2,
+		.irq            = OCP_IRQ_NA,   /* MPC52xx_IRQ_I2C2 - Buggy */
+		.pm             = OCP_CPM_NA,
+		.additions      = &mpc5200_i2c_def,
+	},
 	{	/* Terminating entry */
 		.vendor		= OCP_VENDOR_INVALID
 	}
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-10-18 14:56:28 -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	2004-10-18 14:56:49 -07:00
+++ b/arch/ppc/platforms/mvme5100.h	2004-10-18 14:56:49 -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	2004-10-18 14:55:54 -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	2004-10-18 14:56:32 -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-10-18 14:56:28 -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-10-18 14:55:54 -07:00
+++ b/arch/ppc/platforms/pcore.c	2004-10-18 14:55:54 -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_cpufreq.c b/arch/ppc/platforms/pmac_cpufreq.c
--- a/arch/ppc/platforms/pmac_cpufreq.c	2004-10-18 14:56:33 -07:00
+++ b/arch/ppc/platforms/pmac_cpufreq.c	2004-10-18 14:56:33 -07:00
@@ -24,10 +24,10 @@
 #include <linux/init.h>
 #include <linux/sysdev.h>
 #include <linux/i2c.h>
+#include <linux/hardirq.h>
 #include <asm/prom.h>
 #include <asm/machdep.h>
 #include <asm/irq.h>
-#include <asm/hardirq.h>
 #include <asm/pmac_feature.h>
 #include <asm/mmu_context.h>
 #include <asm/sections.h>
@@ -301,7 +301,6 @@
 static int __pmac do_set_cpu_speed(int speed_mode)
 {
 	struct cpufreq_freqs freqs;
-	int rc;
 
 	freqs.old = cur_freq;
 	freqs.new = (speed_mode == PMAC_CPU_HIGH_SPEED) ? hi_freq : low_freq;
@@ -315,7 +314,7 @@
 	cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
 	cur_freq = (speed_mode == PMAC_CPU_HIGH_SPEED) ? hi_freq : low_freq;
 
-	return rc;
+	return 0;
 }
 
 static int __pmac pmac_cpufreq_verify(struct cpufreq_policy *policy)
@@ -498,7 +497,7 @@
  *  - Titanium PowerBook 800 (PMU based, 667Mhz & 800Mhz)
  *  - Titanium PowerBook 400 (PMU based, 300Mhz & 400Mhz)
  *  - Titanium PowerBook 500 (PMU based, 300Mhz & 500Mhz)
- *  - iBook2 500 (PMU based, 400Mhz & 500Mhz)
+ *  - iBook2 500/600 (PMU based, 400Mhz & 500/600Mhz)
  *  - iBook2 700 (CPU based, 400Mhz & 700Mhz, support low voltage)
  *  - Recent MacRISC3 laptops
  *  - iBook G4s and PowerBook G4s with 7447A CPUs
@@ -533,11 +532,8 @@
 		   machine_is_compatible("PowerBook3,5") ||
 		   machine_is_compatible("MacRISC3")) {
 		pmac_cpufreq_init_MacRISC3(cpunode);
-	/* Else check for iBook2 500 */
+	/* Else check for iBook2 500/600 */
 	} else if (machine_is_compatible("PowerBook4,1")) {
-		/* We only know about 500Mhz model */
-		if (cur_freq < 450000 || cur_freq > 550000)
-			goto out;
 		hi_freq = cur_freq;
 		low_freq = 400000;
 		set_speed_proc = pmu_set_cpu_speed;
diff -Nru a/arch/ppc/platforms/pmac_feature.c b/arch/ppc/platforms/pmac_feature.c
--- a/arch/ppc/platforms/pmac_feature.c	2004-10-18 14:57:03 -07:00
+++ b/arch/ppc/platforms/pmac_feature.c	2004-10-18 14:57:03 -07:00
@@ -2665,7 +2665,7 @@
 			struct device_node *p = of_get_parent(ui2c);
 			if (p && !strcmp(p->name, "uni-n"))
 				break;
-			ui2c = of_find_node_by_type(np, "i2c");
+			ui2c = of_find_node_by_type(ui2c, "i2c");
 		}
 		if (ui2c == NULL)
 			break;
diff -Nru a/arch/ppc/platforms/pmac_pci.c b/arch/ppc/platforms/pmac_pci.c
--- a/arch/ppc/platforms/pmac_pci.c	2004-10-18 14:56:32 -07:00
+++ b/arch/ppc/platforms/pmac_pci.c	2004-10-18 14:56:32 -07:00
@@ -50,6 +50,7 @@
 #endif /* CONFIG_POWER4 */
 
 extern u8 pci_cache_line_size;
+extern int pcibios_assign_bus_offset;
 
 struct pci_dev *k2_skiplist[2];
 
@@ -315,6 +316,10 @@
 	unsigned int addr;
 	int i;
 
+	struct device_node *np = pci_busdev_to_OF_node(bus, devfn);
+	if (np == NULL)
+		return PCIBIOS_DEVICE_NOT_FOUND;
+
 	/*
 	 * When a device in K2 is powered down, we die on config
 	 * cycle accesses. Fix that here.
@@ -362,6 +367,9 @@
 	unsigned int addr;
 	int i;
 
+	struct device_node *np = pci_busdev_to_OF_node(bus, devfn);
+	if (np == NULL)
+		return PCIBIOS_DEVICE_NOT_FOUND;
 	/*
 	 * When a device in K2 is powered down, we die on config
 	 * cycle accesses. Fix that here.
@@ -565,6 +573,14 @@
 
 	init_p2pbridge();
 	fixup_nec_usb2();
+	
+	/* We are still having some issues with the Xserve G4, enabling
+	 * some offset between bus number and domains for now when we
+	 * assign all busses should help for now
+	 */
+	if (pci_assign_all_busses)
+		pcibios_assign_bus_offset = 0x10;
+
 #ifdef CONFIG_POWER4 
 	/* There is something wrong with DMA on U3/HT. I haven't figured out
 	 * the details yet, but if I set the cache line size to 128 bytes like
@@ -707,7 +723,7 @@
 	 * properties or figuring out the U3 address space decoding logic and
 	 * then read its configuration register (if any).
 	 */
-	hose->io_base_phys = 0xf4000000 + 0x00400000;
+	hose->io_base_phys = 0xf4000000;
 	hose->io_base_virt = ioremap(hose->io_base_phys, 0x00400000);
 	isa_io_base = (unsigned long) hose->io_base_virt;
 	hose->io_resource.name = np->full_name;
@@ -1034,6 +1050,8 @@
 	}
 }
 
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_TI, PCI_ANY_ID, pmac_pci_fixup_cardbus);
+
 void pmac_pci_fixup_pciata(struct pci_dev* dev)
 {
        u8 progif = 0;
@@ -1074,6 +1092,8 @@
 			printk(KERN_ERR "Rewrite of PROGIF failed !\n");
 	}
 }
+DECLARE_PCI_FIXUP_FINAL(PCI_ANY_ID, PCI_ANY_ID, pmac_pci_fixup_pciata);
+
 
 /*
  * Disable second function on K2-SATA, it's broken
@@ -1104,3 +1124,4 @@
 		}
 	}
 }
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_SERVERWORKS, 0x0240, pmac_pci_fixup_k2_sata);
diff -Nru a/arch/ppc/platforms/pmac_setup.c b/arch/ppc/platforms/pmac_setup.c
--- a/arch/ppc/platforms/pmac_setup.c	2004-10-18 14:56:33 -07:00
+++ b/arch/ppc/platforms/pmac_setup.c	2004-10-18 14:56:33 -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/pmac_smp.c b/arch/ppc/platforms/pmac_smp.c
--- a/arch/ppc/platforms/pmac_smp.c	2004-10-18 14:56:32 -07:00
+++ b/arch/ppc/platforms/pmac_smp.c	2004-10-18 14:56:32 -07:00
@@ -32,13 +32,13 @@
 #include <linux/init.h>
 #include <linux/spinlock.h>
 #include <linux/errno.h>
+#include <linux/hardirq.h>
 
 #include <asm/ptrace.h>
 #include <asm/atomic.h>
 #include <asm/irq.h>
 #include <asm/page.h>
 #include <asm/pgtable.h>
-#include <asm/hardirq.h>
 #include <asm/sections.h>
 #include <asm/io.h>
 #include <asm/prom.h>
diff -Nru a/arch/ppc/platforms/pmac_time.c b/arch/ppc/platforms/pmac_time.c
--- a/arch/ppc/platforms/pmac_time.c	2004-10-18 14:56:27 -07:00
+++ b/arch/ppc/platforms/pmac_time.c	2004-10-18 14:56:27 -07:00
@@ -19,6 +19,7 @@
 #include <linux/adb.h>
 #include <linux/cuda.h>
 #include <linux/pmu.h>
+#include <linux/hardirq.h>
 
 #include <asm/sections.h>
 #include <asm/prom.h>
@@ -26,7 +27,6 @@
 #include <asm/io.h>
 #include <asm/pgtable.h>
 #include <asm/machdep.h>
-#include <asm/hardirq.h>
 #include <asm/time.h>
 #include <asm/nvram.h>
 
diff -Nru a/arch/ppc/platforms/powerpmc250.h b/arch/ppc/platforms/powerpmc250.h
--- a/arch/ppc/platforms/powerpmc250.h	2004-10-18 14:56:48 -07:00
+++ b/arch/ppc/platforms/powerpmc250.h	2004-10-18 14:56:48 -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	2004-10-18 14:56:28 -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-10-18 14:57:04 -07:00
+++ b/arch/ppc/platforms/pplus.c	2004-10-18 14:57:04 -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-10-18 14:57:05 -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-10-18 14:56:32 -07:00
+++ b/arch/ppc/platforms/pq2ads.h	2004-10-18 14:56:32 -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-10-18 14:57:05 -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-10-18 14:57:04 -07:00
+++ b/arch/ppc/platforms/prep_pci.c	2004-10-18 14:57:04 -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-10-18 14:56:50 -07:00
+++ b/arch/ppc/platforms/prep_setup.c	2004-10-18 14:56:50 -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-10-18 14:57:03 -07:00
+++ b/arch/ppc/platforms/prpmc750.c	2004-10-18 14:57:03 -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-10-18 14:56:27 -07:00
+++ b/arch/ppc/platforms/prpmc750.h	2004-10-18 14:56:27 -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	2004-10-18 14:56:20 -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-10-18 14:56:48 -07:00
+++ b/arch/ppc/platforms/prpmc800.c	2004-10-18 14:56:48 -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-10-18 14:56:49 -07:00
+++ b/arch/ppc/platforms/prpmc800.h	2004-10-18 14:56:49 -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	2004-10-18 14:56:50 -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-10-18 14:56:17 -07:00
+++ b/arch/ppc/platforms/residual.c	2004-10-18 14:56:17 -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 system address */
+	if (!((p.PPCData[0] == 3) && (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-10-18 14:56:31 -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-10-18 14:56:32 -07:00
+++ b/arch/ppc/platforms/rpx8260.h	2004-10-18 14:56:32 -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-10-18 14:57:05 -07:00
+++ b/arch/ppc/platforms/sandpoint.c	2004-10-18 14:57:05 -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-10-18 14:56:20 -07:00
+++ b/arch/ppc/platforms/sbc82xx.c	2004-10-18 14:56:20 -07:00
@@ -16,10 +16,11 @@
  */
 
 #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>
 #include <asm/machdep.h>
@@ -28,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();
 
@@ -236,26 +210,36 @@
 	return PCI_IRQ_TABLE_LOOKUP;
 }
 
+static void __devinit quirk_sbc8260_cardbus(struct pci_dev *pdev)
+{
+	uint32_t ctrl;
 
+	if (pdev->bus->number != 0 || pdev->devfn != PCI_DEVFN(17, 0))
+		return;
+
+	printk(KERN_INFO "Setting up CardBus controller\n");
+
+	/* Set P2CCLK bit in System Control Register */
+	pci_read_config_dword(pdev, 0x80, &ctrl);
+	ctrl |= (1<<27);
+	pci_write_config_dword(pdev, 0x80, ctrl);
+
+	/* Set MFUNC up for PCI IRQ routing via INTA and INTB, and LEDs. */
+	pci_write_config_dword(pdev, 0x8c, 0x00c01d22);
+
+}
+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-10-18 14:57:04 -07:00
+++ b/arch/ppc/platforms/sbc82xx.h	2004-10-18 14:57:04 -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-10-18 14:55:55 -07:00
+++ b/arch/ppc/platforms/spruce.c	2004-10-18 14:55:55 -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-10-18 14:56:31 -07:00
+++ b/arch/ppc/platforms/tqm8260.h	2004-10-18 14:56:31 -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-10-18 14:56:28 -07:00
+++ b/arch/ppc/platforms/tqm8260_setup.c	2004-10-18 14:56:28 -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-10-18 14:55:54 -07:00
+++ b/arch/ppc/syslib/Makefile	2004-10-18 14:55:54 -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-10-18 14:56:32 -07:00
+++ b/arch/ppc/syslib/cpm2_pic.c	2004-10-18 14:56:32 -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-10-18 14:57:04 -07:00
+++ b/arch/ppc/syslib/cpm2_pic.h	2004-10-18 14:57:04 -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-10-18 14:56:32 -07:00
+++ b/arch/ppc/syslib/hawk_common.c	2004-10-18 14:56:32 -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/ibm44x_common.c b/arch/ppc/syslib/ibm44x_common.c
--- a/arch/ppc/syslib/ibm44x_common.c	2004-10-18 14:56:29 -07:00
+++ b/arch/ppc/syslib/ibm44x_common.c	2004-10-18 14:56:29 -07:00
@@ -6,6 +6,9 @@
  * Matt Porter <mporter@mvista.com>
  * Copyright 2002-2003 MontaVista Software Inc.
  *
+ * Eugene Surovegin <eugene.surovegin@zultys.com> or <ebs@ebshome.net>
+ * Copyright (c) 2003, 2004 Zultys Technologies
+ *
  * 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
@@ -14,8 +17,14 @@
  */
 #include <linux/config.h>
 #include <linux/types.h>
+#include <linux/serial.h>
+
+#include <asm/param.h>
 #include <asm/ibm44x.h>
 #include <asm/mmu.h>
+#include <asm/machdep.h>
+#include <asm/time.h>
+#include <asm/ppc4xx_pic.h>
 
 phys_addr_t fixup_bigphys_addr(phys_addr_t addr, phys_addr_t size)
 {
@@ -35,3 +44,159 @@
 
 	return (page_4gb | addr);
 };
+
+void __init ibm44x_calibrate_decr(unsigned int freq)
+{
+	tb_ticks_per_jiffy = freq / HZ;
+	tb_to_us = mulhwu_scale_factor(freq, 1000000);
+
+	/* Set the time base to zero */
+	mtspr(SPRN_TBWL, 0);
+	mtspr(SPRN_TBWU, 0);
+
+	/* Clear any pending timer interrupts */
+	mtspr(SPRN_TSR, TSR_ENW | TSR_WIS | TSR_DIS | TSR_FIS);
+
+	/* Enable decrementer interrupt */
+	mtspr(SPRN_TCR, TCR_DIE);
+}
+
+extern void abort(void);
+
+static void ibm44x_restart(char *cmd)
+{
+	local_irq_disable();
+	abort();
+}
+
+static void ibm44x_power_off(void)
+{
+	local_irq_disable();
+	for(;;);
+}
+
+static void ibm44x_halt(void)
+{
+	local_irq_disable();
+	for(;;);
+}
+
+/*
+ * Read the 44x memory controller to get size of system memory.
+ */
+static unsigned long __init ibm44x_find_end_of_memory(void)
+{
+	u32 i, bank_config;
+	u32 mem_size = 0;
+
+	for (i=0; i<4; i++)
+	{
+		switch (i)
+		{
+			case 0:
+				mtdcr(DCRN_SDRAM0_CFGADDR, SDRAM0_B0CR);
+				break;
+			case 1:
+				mtdcr(DCRN_SDRAM0_CFGADDR, SDRAM0_B1CR);
+				break;
+			case 2:
+				mtdcr(DCRN_SDRAM0_CFGADDR, SDRAM0_B2CR);
+				break;
+			case 3:
+				mtdcr(DCRN_SDRAM0_CFGADDR, SDRAM0_B3CR);
+				break;
+		}
+
+		bank_config = mfdcr(DCRN_SDRAM0_CFGDATA);
+
+		if (!(bank_config & SDRAM_CONFIG_BANK_ENABLE))
+			continue;
+		switch (SDRAM_CONFIG_BANK_SIZE(bank_config))
+		{
+			case SDRAM_CONFIG_SIZE_8M:
+				mem_size += PPC44x_MEM_SIZE_8M;
+				break;
+			case SDRAM_CONFIG_SIZE_16M:
+				mem_size += PPC44x_MEM_SIZE_16M;
+				break;
+			case SDRAM_CONFIG_SIZE_32M:
+				mem_size += PPC44x_MEM_SIZE_32M;
+				break;
+			case SDRAM_CONFIG_SIZE_64M:
+				mem_size += PPC44x_MEM_SIZE_64M;
+				break;
+			case SDRAM_CONFIG_SIZE_128M:
+				mem_size += PPC44x_MEM_SIZE_128M;
+				break;
+			case SDRAM_CONFIG_SIZE_256M:
+				mem_size += PPC44x_MEM_SIZE_256M;
+				break;
+			case SDRAM_CONFIG_SIZE_512M:
+				mem_size += PPC44x_MEM_SIZE_512M;
+				break;
+		}
+	}
+	return mem_size;
+}
+
+static void __init ibm44x_init_irq(void)
+{
+	int i;
+
+	ppc4xx_pic_init();
+
+	for (i = 0; i < NR_IRQS; i++)
+		irq_desc[i].handler = ppc4xx_pic;
+}
+
+#ifdef CONFIG_SERIAL_TEXT_DEBUG
+#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> */
+};
+
+static void ibm44x_progress(char *s, unsigned short hex)
+{
+	volatile char c;
+	volatile unsigned long com_port;
+	u16 shift;
+
+	com_port = (unsigned long)rs_table[0].iomem_base;
+	shift = rs_table[0].iomem_reg_shift;
+
+	while ((c = *s++) != 0) {
+		while ((*((volatile unsigned char *)com_port +
+				(UART_LSR << shift)) & UART_LSR_THRE) == 0)
+			;
+		*(volatile unsigned char *)com_port = c;
+
+	}
+
+	/* Send LF/CR to pretty up output */
+	while ((*((volatile unsigned char *)com_port +
+		(UART_LSR << shift)) & UART_LSR_THRE) == 0)
+		;
+	*(volatile unsigned char *)com_port = '\r';
+	while ((*((volatile unsigned char *)com_port +
+		(UART_LSR << shift)) & UART_LSR_THRE) == 0)
+		;
+	*(volatile unsigned char *)com_port = '\n';
+}
+#endif /* CONFIG_SERIAL_TEXT_DEBUG */
+
+void __init ibm44x_platform_init(void)
+{
+	ppc_md.init_IRQ = ibm44x_init_irq;
+	ppc_md.find_end_of_memory = ibm44x_find_end_of_memory;
+	ppc_md.restart = ibm44x_restart;
+	ppc_md.power_off = ibm44x_power_off;
+	ppc_md.halt = ibm44x_halt;
+
+#ifdef CONFIG_SERIAL_TEXT_DEBUG
+	ppc_md.progress = ibm44x_progress;
+#endif /* CONFIG_SERIAL_TEXT_DEBUG */
+}
+
diff -Nru a/arch/ppc/syslib/ibm44x_common.h b/arch/ppc/syslib/ibm44x_common.h
--- a/arch/ppc/syslib/ibm44x_common.h	2004-10-18 14:56:18 -07:00
+++ b/arch/ppc/syslib/ibm44x_common.h	2004-10-18 14:56:18 -07:00
@@ -4,7 +4,7 @@
  * PPC44x system library
  *
  * Eugene Surovegin <eugene.surovegin@zultys.com> or <ebs@ebshome.net>
- * Copyright (c) 2003 Zultys Technologies
+ * Copyright (c) 2003, 2004 Zultys Technologies
  *
  * 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
@@ -30,6 +30,12 @@
 	unsigned int uart0;
 	unsigned int uart1;
 };
+
+/* common 44x platform init */
+void ibm44x_platform_init(void) __init;
+
+/* initialize decrementer and tick-related variables */
+void ibm44x_calibrate_decr(unsigned int freq) __init;
 
 #endif /* __ASSEMBLY__ */
 #endif /* __PPC_SYSLIB_IBM44x_COMMON_H */
diff -Nru a/arch/ppc/syslib/m8260_pci.h b/arch/ppc/syslib/m8260_pci.h
--- a/arch/ppc/syslib/m8260_pci.h	2004-10-18 14:57:03 -07:00
+++ b/arch/ppc/syslib/m8260_pci.h	2004-10-18 14:57:03 -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-10-18 14:56:32 -07:00
+++ b/arch/ppc/syslib/m8260_setup.c	2004-10-18 14:56:32 -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-10-18 14:56:29 -07:00
+++ b/arch/ppc/syslib/m8xx_setup.c	2004-10-18 14:56:29 -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-10-18 14:57:23 -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-10-18 14:57:23 -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/mpc52xx_pic.c b/arch/ppc/syslib/mpc52xx_pic.c
--- a/arch/ppc/syslib/mpc52xx_pic.c	2004-10-18 14:57:21 -07:00
+++ b/arch/ppc/syslib/mpc52xx_pic.c	2004-10-18 14:57:21 -07:00
@@ -114,7 +114,7 @@
 	/*
 	 * Only some irqs are reset here, others in interrupting hardware.
 	 */
-			
+
 	switch (irq) {
 	case MPC52xx_IRQ0:
 		val = in_be32(&intr->ctrl);
@@ -180,13 +180,14 @@
 mpc52xx_init_irq(void)
 {
 	int i;
+	u32 intr_ctrl;
 
 	/* Remap the necessary zones */
 	intr = (struct mpc52xx_intr *)
 		ioremap(MPC52xx_INTR, sizeof(struct mpc52xx_intr));
 	sdma = (struct mpc52xx_sdma *)
 		ioremap(MPC52xx_SDMA, sizeof(struct mpc52xx_sdma));
-	
+
 	if ((intr==NULL) || (sdma==NULL))
 		panic("Can't ioremap PIC/SDMA register for init_irq !");
 
@@ -195,12 +196,13 @@
 	out_be32(&sdma->IntMask, 0xffffffff);	/* 1 means disabled */
 	out_be32(&intr->per_mask, 0x7ffffc00);	/* 1 means disabled */
 	out_be32(&intr->main_mask, 0x00010fff);	/* 1 means disabled */
-	out_be32(&intr->ctrl,
-			0x0f000000 |	/* clear IRQ 0-3 */
-			0x00c00000 |	/* IRQ0: level-sensitive, active low */
+	intr_ctrl = in_be32(&intr->ctrl);
+	intr_ctrl &=    0x00ff0000;	/* Keeps IRQ[0-3] config */
+	intr_ctrl |=	0x0f000000 |	/* clear IRQ 0-3 */
 			0x00001000 |	/* MEE master external enable */
 			0x00000000 |	/* 0 means disable IRQ 0-3 */
-			0x00000001);	/* CEb route critical normally */
+			0x00000001;	/* CEb route critical normally */
+	out_be32(&intr->ctrl, intr_ctrl);
 
 	/* Zero a bunch of the priority settings.  */
 	out_be32(&intr->per_pri1, 0);
@@ -213,6 +215,14 @@
 	for (i = 0; i < NR_IRQS; i++) {
 		irq_desc[i].handler = &mpc52xx_ic;
 		irq_desc[i].status = IRQ_LEVEL;
+	}
+
+	#define IRQn_MODE(intr_ctrl,irq) (((intr_ctrl) >> (22-(i<<1))) & 0x03)
+	for (i=0 ; i<4 ; i++) {
+		int mode;
+		mode = IRQn_MODE(intr_ctrl,i);
+		if ((mode == 0x1) || (mode == 0x2))
+			irq_desc[i?MPC52xx_IRQ1+i-1:MPC52xx_IRQ0].status = 0;
 	}
 }
 
diff -Nru a/arch/ppc/syslib/mpc52xx_setup.c b/arch/ppc/syslib/mpc52xx_setup.c
--- a/arch/ppc/syslib/mpc52xx_setup.c	2004-10-18 14:56:49 -07:00
+++ b/arch/ppc/syslib/mpc52xx_setup.c	2004-10-18 14:56:49 -07:00
@@ -1,5 +1,5 @@
 /*
- * arch/ppc/syslib/mpc52xx_common.c
+ * arch/ppc/syslib/mpc52xx_setup.c
  *
  * Common code for the boards based on Freescale MPC52xx embedded CPU.
  *
@@ -23,6 +23,7 @@
 #include <asm/mpc52xx.h>
 #include <asm/mpc52xx_psc.h>
 #include <asm/ocp.h>
+#include <asm/pgtable.h>
 #include <asm/ppcboot.h>
 
 extern bd_t __res;
@@ -38,9 +39,9 @@
 mpc52xx_restart(char *cmd)
 {
 	struct mpc52xx_gpt* gpt0 = (struct mpc52xx_gpt*) MPC52xx_GPTx(0);
-	
+
 	local_irq_disable();
-	
+
 	/* Turn on the watchdog and wait for it to expire. It effectively
 	  does a reset */
 	if (gpt0 != NULL) {
@@ -99,24 +100,28 @@
 #error "mpc52xx PSC for console not selected"
 #endif
 
+static void
+mpc52xx_psc_putc(struct mpc52xx_psc * psc, unsigned char c)
+{
+	while (!(in_be16(&psc->mpc52xx_psc_status) &
+	         MPC52xx_PSC_SR_TXRDY));
+	out_8(&psc->mpc52xx_psc_buffer_8, c);
+}
+
 void
 mpc52xx_progress(char *s, unsigned short hex)
 {
 	struct mpc52xx_psc *psc = (struct mpc52xx_psc *)MPC52xx_CONSOLE;
 	char c;
 
-		/* Don't we need to disable serial interrupts ? */
-	
 	while ((c = *s++) != 0) {
-		if (c == '\n') {
-			while (!(in_be16(&psc->mpc52xx_psc_status) &
-			         MPC52xx_PSC_SR_TXRDY)) ;
-			out_8(&psc->mpc52xx_psc_buffer_8, '\r');
-		}
-		while (!(in_be16(&psc->mpc52xx_psc_status) &
-		         MPC52xx_PSC_SR_TXRDY)) ;
-		out_8(&psc->mpc52xx_psc_buffer_8, c);
+		if (c == '\n')
+			mpc52xx_psc_putc(psc, '\r');
+		mpc52xx_psc_putc(psc, c);
 	}
+
+	mpc52xx_psc_putc(psc, '\r');
+	mpc52xx_psc_putc(psc, '\n');
 }
 
 #endif  /* CONFIG_SERIAL_TEXT_DEBUG */
@@ -137,7 +142,7 @@
 
 		/* Temp BAT2 mapping active when this is called ! */
 		mmap_ctl = (struct mpc52xx_mmap_ctl*) MPC52xx_MMAP_CTL;
-			
+
 		sdram_config_0 = in_be32(&mmap_ctl->sdram0);
 		sdram_config_1 = in_be32(&mmap_ctl->sdram1);
 
@@ -147,10 +152,8 @@
 		if (((sdram_config_1 & 0x1f) >= 0x13) &&
 				((sdram_config_1 & 0xfff00000) == ramsize))
 			ramsize += 1 << ((sdram_config_1 & 0xf) + 17);
-
-		iounmap(mmap_ctl);
 	}
-	
+
 	return ramsize;
 }
 
@@ -167,7 +170,7 @@
 		/* Get RTC & Clock manager modules */
 		struct mpc52xx_rtc *rtc;
 		struct mpc52xx_cdm *cdm;
-		
+
 		rtc = (struct mpc52xx_rtc*)
 			ioremap(MPC52xx_RTC, sizeof(struct mpc52xx_rtc));
 		cdm = (struct mpc52xx_cdm*)
@@ -206,7 +209,7 @@
 		__res.bi_intfreq = cpufreq;
 		__res.bi_ipbfreq = ipbfreq;
 		__res.bi_pcifreq = pcifreq;
-	
+
 		/* Release mapping */
 		iounmap((void*)rtc);
 		iounmap((void*)cdm);
diff -Nru a/arch/ppc/syslib/open_pic.c b/arch/ppc/syslib/open_pic.c
--- a/arch/ppc/syslib/open_pic.c	2004-10-18 14:56:33 -07:00
+++ b/arch/ppc/syslib/open_pic.c	2004-10-18 14:56:33 -07:00
@@ -16,6 +16,7 @@
 #include <linux/irq.h>
 #include <linux/interrupt.h>
 #include <linux/sysdev.h>
+#include <linux/errno.h>
 #include <asm/ptrace.h>
 #include <asm/signal.h>
 #include <asm/io.h>
@@ -24,7 +25,6 @@
 #include <asm/sections.h>
 #include <asm/open_pic.h>
 #include <asm/i8259.h>
-#include <asm/hardirq.h>
 
 #include "open_pic_defs.h"
 
@@ -412,7 +412,7 @@
 
 	/* Initialize the spurious interrupt */
 	if (ppc_md.progress) ppc_md.progress("openpic: spurious",0x3bd);
-	openpic_set_spurious(OPENPIC_VEC_SPURIOUS+offset);
+	openpic_set_spurious(OPENPIC_VEC_SPURIOUS);
 	openpic_disable_8259_pass_through();
 #ifdef CONFIG_EPIC_SERIAL_MODE
 	openpic_eicr_set_clk(7);	/* Slowest value until we know better */
@@ -865,7 +865,7 @@
 			irq = cirq;
 			openpic_eoi();
 		}
-        } else if (irq == OPENPIC_VEC_SPURIOUS + open_pic_irq_offset)
+	} else if (irq == OPENPIC_VEC_SPURIOUS)
 		irq = -1;
 	return irq;
 }
@@ -988,9 +988,9 @@
 
 	/* OpenPIC sometimes seem to need some time to be fully back up... */
 	do {
-		openpic_set_spurious(OPENPIC_VEC_SPURIOUS+open_pic_irq_offset);
+		openpic_set_spurious(OPENPIC_VEC_SPURIOUS);
 	} while(openpic_readfield(&OpenPIC->Global.Spurious_Vector, OPENPIC_VECTOR_MASK)
-			!= (OPENPIC_VEC_SPURIOUS + open_pic_irq_offset));
+			!= OPENPIC_VEC_SPURIOUS);
 	
 	openpic_disable_8259_pass_through();
 
diff -Nru a/arch/ppc/syslib/open_pic2.c b/arch/ppc/syslib/open_pic2.c
--- a/arch/ppc/syslib/open_pic2.c	2004-10-18 14:56:28 -07:00
+++ b/arch/ppc/syslib/open_pic2.c	2004-10-18 14:56:28 -07:00
@@ -20,6 +20,7 @@
 #include <linux/irq.h>
 #include <linux/interrupt.h>
 #include <linux/sysdev.h>
+#include <linux/errno.h>
 #include <asm/ptrace.h>
 #include <asm/signal.h>
 #include <asm/io.h>
@@ -28,7 +29,6 @@
 #include <asm/sections.h>
 #include <asm/open_pic.h>
 #include <asm/i8259.h>
-#include <asm/hardirq.h>
 
 #include "open_pic_defs.h"
 
diff -Nru a/arch/ppc/syslib/ppc4xx_pic.c b/arch/ppc/syslib/ppc4xx_pic.c
--- a/arch/ppc/syslib/ppc4xx_pic.c	2004-10-18 14:55:46 -07:00
+++ b/arch/ppc/syslib/ppc4xx_pic.c	2004-10-18 14:55:46 -07:00
@@ -256,7 +256,7 @@
 ppc4xx_uic_end(unsigned int irq)
 {
 	int bit, word;
-	unsigned int tr_bits;
+	unsigned int tr_bits = 0;
 
 	bit = irq & 0x1f;
 	word = irq >> 5;
diff -Nru a/arch/ppc/syslib/ppc4xx_setup.c b/arch/ppc/syslib/ppc4xx_setup.c
--- a/arch/ppc/syslib/ppc4xx_setup.c	2004-10-18 14:55:53 -07:00
+++ b/arch/ppc/syslib/ppc4xx_setup.c	2004-10-18 14:55:53 -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-10-18 14:57:03 -07:00
+++ b/arch/ppc/syslib/ppc85xx_setup.c	2004-10-18 14:57:03 -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/ppc/syslib/prom_init.c b/arch/ppc/syslib/prom_init.c
--- a/arch/ppc/syslib/prom_init.c	2004-10-18 14:57:04 -07:00
+++ b/arch/ppc/syslib/prom_init.c	2004-10-18 14:57:04 -07:00
@@ -115,11 +115,11 @@
 ihandle prom_chosen __initdata;
 ihandle prom_stdout __initdata;
 
-char *prom_display_paths[FB_MAX] __initdata;
-phandle prom_display_nodes[FB_MAX] __initdata;
-unsigned int prom_num_displays __initdata;
-char *of_stdout_device __initdata;
+static char *prom_display_paths[FB_MAX] __initdata;
+static phandle prom_display_nodes[FB_MAX] __initdata;
+static unsigned int prom_num_displays __initdata;
 static ihandle prom_disp_node __initdata;
+char *of_stdout_device __initdata;
 
 unsigned int rtas_data;   /* physical pointer */
 unsigned int rtas_entry;  /* physical pointer */
@@ -403,6 +403,7 @@
 
 	for (j=0; j<prom_num_displays; j++) {
 		path = prom_display_paths[j];
+		node = prom_display_nodes[j];
 		prom_print("opening display ");
 		prom_print(path);
 		ih = call_prom("open", 1, 1, path);
@@ -420,6 +421,8 @@
 			continue;
 		} else {
 			prom_print("... ok\n");
+			call_prom("setprop", 4, 1, node, "linux,opened", 0, NULL);
+
 			/*
 			 * Setup a usable color table when the appropriate
 			 * method is available.
@@ -439,6 +442,19 @@
 						   clut[1], clut[2]) != 0)
 					break;
 #endif /* CONFIG_LOGO_LINUX_CLUT224 */
+		}
+	}
+	
+	if (prom_stdout) {
+		phandle p;
+		p = call_prom("instance-to-package", 1, 1, prom_stdout);
+		if (p && (int)p != -1) {
+			type[0] = 0;
+			call_prom("getprop", 4, 1, p, "device_type",
+				  type, sizeof(type));
+			if (strcmp(type, "display") == 0)
+				call_prom("setprop", 4, 1, p, "linux,boot-display",
+					  0, NULL);
 		}
 	}
 
diff -Nru a/arch/ppc/syslib/todc_time.c b/arch/ppc/syslib/todc_time.c
--- a/arch/ppc/syslib/todc_time.c	2004-10-18 14:56:49 -07:00
+++ b/arch/ppc/syslib/todc_time.c	2004-10-18 14:56:49 -07:00
@@ -277,9 +277,9 @@
 ulong
 todc_get_rtc_time(void)
 {
-	uint	year, mon, day, hour, min, sec;
+	uint	year = 0, mon = 0, day = 0, hour = 0, min = 0, sec = 0;
 	uint	limit, i;
-	u_char	save_control, uip;
+	u_char	save_control, uip = 0;
 
 	spin_lock(&rtc_lock);
 	save_control = todc_read_val(todc_info->control_a);
@@ -361,7 +361,7 @@
 todc_set_rtc_time(unsigned long nowtime)
 {
 	struct rtc_time	tm;
-	u_char		save_control, save_freq_select;
+	u_char		save_control, save_freq_select = 0;
 
 	spin_lock(&rtc_lock);
 	to_tm(nowtime, &tm);
@@ -416,7 +416,7 @@
  */
 static unsigned char __init todc_read_timereg(int addr)
 {
-	unsigned char save_control, val;
+	unsigned char save_control = 0, val;
 
 	switch (todc_info->rtc_type) {
 		case TODC_TYPE_DS1557:
diff -Nru a/arch/ppc64/Kconfig b/arch/ppc64/Kconfig
--- a/arch/ppc64/Kconfig	2004-10-18 14:56:32 -07:00
+++ b/arch/ppc64/Kconfig	2004-10-18 14:56:32 -07:00
@@ -1,4 +1,4 @@
-# 
+#
 # For a description of the syntax of this configuration file,
 # see Documentation/kbuild/kconfig-language.txt.
 #
@@ -58,16 +58,28 @@
 
 choice
 	prompt "Platform Type"
-	default PPC_PSERIES
+	default PPC_MULTIPLATFORM
 
 config PPC_ISERIES
-	bool "iSeries"
+	bool "IBM Legacy iSeries"
 
-config PPC_PSERIES
-	bool "pSeries / PowerMac G5"
+config PPC_MULTIPLATFORM
+	bool "Generic"
 
 endchoice
 
+config PPC_PSERIES
+	depends on PPC_MULTIPLATFORM
+	bool "  IBM pSeries & new iSeries"
+	default y
+
+config PPC_PMAC
+	depends on PPC_MULTIPLATFORM
+	bool "  Apple G5 based machines"
+	default y
+	select ADB_PMU
+	select U3_DART
+
 config PPC
 	bool
 	default y
@@ -77,7 +89,7 @@
 	default y
 
 config PPC_OF
-	depends on PPC_PSERIES
+	depends on PPC_MULTIPLATFORM
 	bool
 	default y
 
@@ -85,14 +97,9 @@
 # exception vectors for it
 config ALTIVEC
 	bool "Support for VMX (Altivec) vector unit"
-	depends on PPC_PSERIES
+	depends on PPC_MULTIPLATFORM
 	default y
 
-config PPC_PMAC
-	depends on PPC_PSERIES
-	bool "Apple PowerMac G5 support"
-	select ADB_PMU
-
 config PPC_SPLPAR
 	depends on PPC_PSERIES
 	bool "Support for shared-processor logical partitions"
@@ -103,16 +110,10 @@
 	  processors, that is, which share physical processors between
 	  two or more partitions.
 
-config PMAC_DART
-	bool "Enable DART/IOMMU on PowerMac (allow >2G of RAM)"
-	depends on PPC_PMAC
-	depends on EXPERIMENTAL
+config U3_DART
+	bool 
+	depends on PPC_MULTIPLATFORM
 	default n
-	help
-	  Enabling DART makes it possible to boot a PowerMac G5 with more
-	  than 2GB of memory. Note that the code is very new and untested
-	  at this time, so it has to be considered experimental. Enabling
-	  this might result in data loss.
 
 config PPC_PMAC64
 	bool
@@ -163,7 +164,7 @@
 
 config IRQ_ALL_CPUS
 	bool "Distribute interrupts on all CPUs by default"
-	depends on SMP && PPC_PSERIES
+	depends on SMP && PPC_MULTIPLATFORM
 	help
 	  This option gives the kernel permission to distribute IRQs across
 	  multiple CPUs.  Saying N here will route all IRQs to the first
@@ -214,7 +215,7 @@
 
 config PPC_RTAS
 	bool "Proc interface to RTAS"
-	depends on !PPC_ISERIES
+	depends on PPC_PSERIES
 
 config RTAS_FLASH
 	tristate "Firmware flash interface"
@@ -226,8 +227,9 @@
 
 config LPARCFG
 	tristate "LPAR Configuration Data"
+	depends on PPC_PSERIES || PPC_ISERIES
 	help
-	Provide system capacity information via human readable 
+	Provide system capacity information via human readable
 	<key word>=<value> pairs through a /proc/ppc64/lparcfg interface.
 
 endmenu
@@ -272,7 +274,7 @@
 
 config HOTPLUG_CPU
 	bool "Support for hot-pluggable CPUs"
-	depends on SMP && HOTPLUG && EXPERIMENTAL
+	depends on SMP && HOTPLUG && EXPERIMENTAL && PPC_PSERIES
 	---help---
 	  Say Y here to be able to turn CPUs off and on.
 
@@ -343,102 +345,10 @@
 
 source "arch/ppc64/oprofile/Kconfig"
 
-menu "Kernel hacking"
-
-config DEBUG_KERNEL
-	bool "Kernel debugging"
-	help
-	  Say Y here if you are developing drivers or trying to debug and
-	  identify kernel problems.
-
-config DEBUG_STACKOVERFLOW
-	bool "Check for stack overflows"
-	depends on DEBUG_KERNEL
-
-config DEBUG_STACK_USAGE
-	bool "Stack utilization instrumentation"
-	depends on DEBUG_KERNEL
-	help
-	  Enables the display of the minimum amount of free stack which each
-	  task has ever had available in the sysrq-T and sysrq-P debug output.
-
-	  This option will slow down process creation somewhat.
-
-config DEBUG_SLAB
-	bool "Debug memory allocations"
-	depends on DEBUG_KERNEL
-	help
-	  Say Y here to have the kernel do limited verification on memory
-	  allocation as well as poisoning memory on free to catch use of freed
-	  memory.
-
-config MAGIC_SYSRQ
-	bool "Magic SysRq key"
-	depends on DEBUG_KERNEL
-	help
-	  If you say Y here, you will have some control over the system even
-	  if the system crashes for example during kernel debugging (e.g., you
-	  will be able to flush the buffer cache to disk, reboot the system
-	  immediately or dump some status information). This is accomplished
-	  by pressing various keys while holding SysRq (Alt+PrintScreen). It
-	  also works on a serial console (on PC hardware at least), if you
-	  send a BREAK and then within 5 seconds a command keypress. The
-	  keys are documented in <file:Documentation/sysrq.txt>. Don't say Y
-	  unless you really know what this hack does.
-
-config DEBUGGER
-	bool "Enable debugger hooks"
-	depends on DEBUG_KERNEL
-	help
-	  Include in-kernel hooks for kernel debuggers. Unless you are
-	  intending to debug the kernel, say N here.
-
-config XMON
-	bool "Include xmon kernel debugger"
-	depends on DEBUGGER
-	help
-	  Include in-kernel hooks for the xmon kernel monitor/debugger.
-	  Unless you are intending to debug the kernel, say N here.
-
-config XMON_DEFAULT
-	bool "Enable xmon by default"
-	depends on XMON
-
-config PPCDBG
-	bool "Include PPCDBG realtime debugging"
-	depends on DEBUG_KERNEL
-
-config DEBUG_INFO
-	bool "Compile the kernel with debug info"
-	depends on DEBUG_KERNEL
-	help
-          If you say Y here the resulting kernel image will include
-	  debugging info resulting in a larger kernel image.
-	  Say Y here only if you plan to use gdb to debug the kernel.
-	  If you don't debug the kernel, you can say N.
-
-config IRQSTACKS
-	bool "Use separate kernel stacks when processing interrupts"
-	help
-	  If you say Y here the kernel will use separate kernel stacks
-	  for handling hard and soft interrupts.  This can help avoid
-	  overflowing the process kernel stacks.
-	  
-config SPINLINE
-	bool "Inline spinlock code at each call site"
-	depends on SMP && !PPC_SPLPAR && !PPC_ISERIES
-	help
-	  Say Y if you want to have the code for acquiring spinlocks
-	  and rwlocks inlined at each call site.  This makes the kernel
-	  somewhat bigger, but can be useful when profiling the kernel.
-
-	  If in doubt, say N.
-
-endmenu
+source "arch/ppc64/Kconfig.debug"
 
 source "security/Kconfig"
 
 source "crypto/Kconfig"
 
 source "lib/Kconfig"
-
diff -Nru a/arch/ppc64/Kconfig.debug b/arch/ppc64/Kconfig.debug
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/arch/ppc64/Kconfig.debug	2004-10-18 14:57:24 -07:00
@@ -0,0 +1,59 @@
+menu "Kernel hacking"
+
+source "lib/Kconfig.debug"
+
+config DEBUG_STACKOVERFLOW
+	bool "Check for stack overflows"
+	depends on DEBUG_KERNEL
+
+config DEBUG_STACK_USAGE
+	bool "Stack utilization instrumentation"
+	depends on DEBUG_KERNEL
+	help
+	  Enables the display of the minimum amount of free stack which each
+	  task has ever had available in the sysrq-T and sysrq-P debug output.
+
+	  This option will slow down process creation somewhat.
+
+config DEBUGGER
+	bool "Enable debugger hooks"
+	depends on DEBUG_KERNEL
+	help
+	  Include in-kernel hooks for kernel debuggers. Unless you are
+	  intending to debug the kernel, say N here.
+
+config XMON
+	bool "Include xmon kernel debugger"
+	depends on DEBUGGER
+	help
+	  Include in-kernel hooks for the xmon kernel monitor/debugger.
+	  Unless you are intending to debug the kernel, say N here.
+
+config XMON_DEFAULT
+	bool "Enable xmon by default"
+	depends on XMON
+
+config PPCDBG
+	bool "Include PPCDBG realtime debugging"
+	depends on DEBUG_KERNEL
+
+config IRQSTACKS
+	bool "Use separate kernel stacks when processing interrupts"
+	help
+	  If you say Y here the kernel will use separate kernel stacks
+	  for handling hard and soft interrupts.  This can help avoid
+	  overflowing the process kernel stacks.
+
+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/Makefile b/arch/ppc64/Makefile
--- a/arch/ppc64/Makefile	2004-10-18 14:55:55 -07:00
+++ b/arch/ppc64/Makefile	2004-10-18 14:55:55 -07:00
@@ -15,29 +15,34 @@
 
 KERNELLOAD	:= 0xc000000000000000
 
-HAS_BIARCH      := $(shell if $(CC) -m64 -S -o /dev/null -xc /dev/null > /dev/null 2>&1; then echo y; else echo n; fi;)
+HAS_BIARCH      := $(call cc-option-yn, -m64)
 ifeq ($(HAS_BIARCH),y)
 AS              := $(AS) -a64
 LD              := $(LD) -m elf64ppc
 CC		:= $(CC) -m64
 endif
 
-CHECK		:= $(CHECK) -m64 -D__powerpc__=1
+new_nm := $(shell if $(NM) --help 2>&1 | grep -- '--synthetic' > /dev/null; then echo y; else echo n; fi)
+
+ifeq ($(new_nm),y)
+NM		:= $(NM) --synthetic
+endif
+
+CHECKFLAGS	+= -m64 -D__powerpc__
 
 LDFLAGS		:= -m elf64ppc
 LDFLAGS_vmlinux	:= -Bstatic -e $(KERNELLOAD) -Ttext $(KERNELLOAD)
-CFLAGS		+= -msoft-float -pipe -Wno-uninitialized -mminimal-toc \
-		   -mtraceback=none
+CFLAGS		+= -msoft-float -pipe -mminimal-toc -mtraceback=none
 
 ifeq ($(CONFIG_POWER4_ONLY),y)
-	CFLAGS += $(call check_gcc,-mcpu=power4,)
+	CFLAGS += $(call cc-option,-mcpu=power4)
 else
-	CFLAGS += $(call check_gcc,-mtune=power4,)
+	CFLAGS += $(call cc-option,-mtune=power4)
 endif
 
 # Enable unit-at-a-time mode when possible. It shrinks the
 # kernel considerably.
-CFLAGS += $(call check_gcc,-funit-at-a-time,)
+CFLAGS += $(call cc-option,-funit-at-a-time)
 
 head-y := arch/ppc64/kernel/head.o
 
diff -Nru a/arch/ppc64/boot/Makefile b/arch/ppc64/boot/Makefile
--- a/arch/ppc64/boot/Makefile	2004-10-18 14:56:50 -07:00
+++ b/arch/ppc64/boot/Makefile	2004-10-18 14:56:50 -07:00
@@ -25,11 +25,11 @@
 
 BOOTCC		:= $(CROSS32_COMPILE)gcc
 HOSTCC		:= gcc
-BOOTCFLAGS	:= $(HOSTCFLAGS) -Iinclude -fno-builtin 
+BOOTCFLAGS	:= $(HOSTCFLAGS) $(LINUXINCLUDE) -fno-builtin 
 BOOTAS		:= $(CROSS32_COMPILE)as
 BOOTAFLAGS	:= -D__ASSEMBLY__ $(BOOTCFLAGS) -traditional
 BOOTLD		:= $(CROSS32_COMPILE)ld
-BOOTLFLAGS	:= -Ttext 0x00400000 -e _start -T $(obj)/zImage.lds
+BOOTLFLAGS	:= -Ttext 0x00400000 -e _start -T $(srctree)/$(src)/zImage.lds
 BOOTOBJCOPY	:= $(CROSS32_COMPILE)objcopy
 OBJCOPYFLAGS    := contents,alloc,load,readonly,data
 
@@ -51,36 +51,31 @@
 #-----------------------------------------------------------
 # ELF sections within the zImage bootloader/wrapper
 #-----------------------------------------------------------
-required := vmlinux .config System.map
+required := vmlinux.strip
 initrd   := initrd
 
 obj-sec = $(foreach section, $(1), $(patsubst %,$(obj)/kernel-%.o, $(section)))
 src-sec = $(foreach section, $(1), $(patsubst %,$(obj)/kernel-%.c, $(section)))
 gz-sec  = $(foreach section, $(1), $(patsubst %,$(obj)/kernel-%.gz, $(section)))
 
-host-progs		:= piggy addnote addSystemMap addRamDisk
+hostprogs-y		:= piggy addnote addRamDisk
 targets 		+= zImage zImage.initrd imagesize.c \
 			   $(patsubst $(obj)/%,%, $(call obj-sec, $(required) $(initrd))) \
 			   $(patsubst $(obj)/%,%, $(call src-sec, $(required) $(initrd))) \
 			   $(patsubst $(obj)/%,%, $(call gz-sec, $(required) $(initrd))) \
-			   vmlinux.sm vmlinux.initrd vmlinux.sminitrd
-extra-y			:= sysmap.o initrd.o
-
-quiet_cmd_sysmap = SYSMAP   $@
-      cmd_sysmap = $(obj)/addSystemMap System.map $< $@
-$(obj)/vmlinux.sm: vmlinux $(obj)/addSystemMap System.map FORCE
-	$(call if_changed,sysmap)
+			   vmlinux.initrd
+extra-y			:= initrd.o
 
 quiet_cmd_ramdisk = RAMDISK $@
-      cmd_ramdisk = $(obj)/addRamDisk $(obj)/ramdisk.image.gz System.map $< $@
-$(obj)/vmlinux.initrd: vmlinux $(obj)/addRamDisk $(obj)/ramdisk.image.gz System.map FORCE
-	$(call if_changed,ramdisk)
+      cmd_ramdisk = $(obj)/addRamDisk $(obj)/ramdisk.image.gz $< $@
 
-$(obj)/vmlinux.sminitrd: $(obj)/vmlinux.sm $(obj)/addRamDisk $(obj)/ramdisk.image.gz FORCE
-	$(call if_changed,ramdisk)
+quiet_cmd_stripvm = STRIP $@
+      cmd_stripvm = $(STRIP) -s $< -o $@
 
-$(obj)/sysmap.o: System.map $(obj)/piggyback FORCE
-	$(call if_changed,piggy)
+vmlinux.strip: vmlinux FORCE
+	$(call if_changed,stripvm)
+$(obj)/vmlinux.initrd: vmlinux.strip $(obj)/addRamDisk $(obj)/ramdisk.image.gz FORCE
+	$(call if_changed,ramdisk)
 
 addsection = $(BOOTOBJCOPY) $(1) \
 		--add-section=.kernel:$(strip $(patsubst $(obj)/kernel-%.o,%, $(1)))=$(patsubst %.o,%.gz, $(1)) \
@@ -113,9 +108,9 @@
 $(obj)/zImage.initrd: $(call obj-sec, $(required) $(initrd)) $(obj-boot) $(obj)/addnote FORCE
 	$(call if_changed,addnote)
 
-$(obj)/imagesize.c: vmlinux
+$(obj)/imagesize.c: vmlinux.strip
 	@echo Generating $@
-	ls -l vmlinux | \
+	ls -l vmlinux.strip | \
 	awk '{printf "/* generated -- do not edit! */\n" \
 		"unsigned long vmlinux_filesize = %d;\n", $$5}' > $(obj)/imagesize.c
 	$(CROSS_COMPILE)nm -n vmlinux | tail -n 1 | \
@@ -123,6 +118,6 @@
 		>> $(obj)/imagesize.c
 
 install: $(CONFIGURE) $(obj)/$(BOOTIMAGE)
-	sh -x $(src)/install.sh "$(KERNELRELEASE)" "$(obj)/$(BOOTIMAGE)" "$(TOPDIR)/System.map" "$(INSTALL_PATH)"
+	sh -x $(src)/install.sh "$(KERNELRELEASE)" "$(obj)/$(BOOTIMAGE)" "$(INSTALL_PATH)"
 
-clean-files := $(patsubst $(obj)/%,%, $(obj-boot))
+clean-files := $(addprefix $(objtree)/, $(obj-boot) vmlinux.strip)
diff -Nru a/arch/ppc64/boot/addSystemMap.c b/arch/ppc64/boot/addSystemMap.c
--- a/arch/ppc64/boot/addSystemMap.c	2004-10-18 14:56:29 -07:00
+++ /dev/null	Wed Dec 31 16:00:00 196900
@@ -1,248 +0,0 @@
-#include <stdio.h>
-#include <stdlib.h>
-#include <byteswap.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <string.h>
-
-void xlate( char * inb, char * trb, unsigned len )
-{
-	unsigned i;
-	for (  i=0; i<len; ++i )
-	{
-		char c = *inb++;
-		char c1 = c >> 4;
-		char c2 = c & 0xf;
-		if ( c1 > 9 )
-			c1 = c1 + 'A' - 10;
-		else
-			c1 = c1 + '0';
-		if ( c2 > 9 )
-			c2 = c2 + 'A' - 10;
-		else
-			c2 = c2 + '0';
-		*trb++ = c1;
-		*trb++ = c2;
-	}
-	*trb = 0;
-}
-
-#define ElfHeaderSize  (64 * 1024)
-#define ElfPages  (ElfHeaderSize / 4096)
-
-void get4k( /*istream *inf*/FILE *file, char *buf )
-{
-	unsigned j;
-	unsigned num = fread(buf, 1, 4096, file);
-	for ( j=num; j<4096; ++j )
-		buf[j] = 0;
-}
-
-void put4k( /*ostream *outf*/FILE *file, char *buf )
-{
-	fwrite(buf, 1, 4096, file);
-}
-
-int main(int argc, char **argv)
-{
-	char inbuf[4096];
-	FILE *sysmap = NULL;
-	char* ptr_end = NULL; 
-	FILE *inputVmlinux = NULL;
-	FILE *outputVmlinux = NULL;
-	long i = 0;
-	unsigned long sysmapFileLen = 0;
-	unsigned long sysmapLen = 0;
-	unsigned long roundR = 0;
-	unsigned long kernelLen = 0;
-	unsigned long actualKernelLen = 0;
-	unsigned long round = 0;
-	unsigned long roundedKernelLen = 0;
-	unsigned long sysmapStartOffs = 0;
-	unsigned long sysmapPages = 0;
-	unsigned long roundedKernelPages = 0;
-	long padPages = 0;
-	if ( argc < 2 )
-	{
-		fprintf(stderr, "Name of System Map file missing.\n");
-		exit(1);
-	}
-
-	if ( argc < 3 )
-	{
-		fprintf(stderr, "Name of vmlinux file missing.\n");
-		exit(1);
-	}
-
-	if ( argc < 4 )
-	{
-		fprintf(stderr, "Name of vmlinux output file missing.\n");
-		exit(1);
-	}
-
-	sysmap = fopen(argv[1], "r");
-	if ( ! sysmap )
-	{
-		fprintf(stderr, "System Map file \"%s\" failed to open.\n", argv[1]);
-		exit(1);
-	}
-	inputVmlinux = fopen(argv[2], "r");
-	if ( ! inputVmlinux )
-	{
-		fprintf(stderr, "vmlinux file \"%s\" failed to open.\n", argv[2]);
-		exit(1);
-	}
-	outputVmlinux = fopen(argv[3], "w");
-	if ( ! outputVmlinux )
-	{
-		fprintf(stderr, "output vmlinux file \"%s\" failed to open.\n", argv[3]);
-		exit(1);
-	}
-
-
-  
-	fseek(inputVmlinux, 0, SEEK_END);
-	kernelLen = ftell(inputVmlinux);
-	fseek(inputVmlinux, 0, SEEK_SET);
-	printf("kernel file size = %ld\n", kernelLen);
-	if ( kernelLen == 0 )
-	{
-		fprintf(stderr, "You must have a linux kernel specified as argv[2]\n");
-		exit(1);
-	}
-
-
-	actualKernelLen = kernelLen - ElfHeaderSize;
-
-	printf("actual kernel length (minus ELF header) = %ld/%lxx \n", actualKernelLen, actualKernelLen);
-
-	round = actualKernelLen % 4096;
-	roundedKernelLen = actualKernelLen;
-	if ( round )
-		roundedKernelLen += (4096 - round);
-
-	printf("Kernel length rounded up to a 4k multiple = %ld/%lxx \n", roundedKernelLen, roundedKernelLen);
-	roundedKernelPages = roundedKernelLen / 4096;
-	printf("Kernel pages to copy = %ld/%lxx\n", roundedKernelPages, roundedKernelPages);
-
-
-
-	/* Sysmap file */
-	fseek(sysmap, 0, SEEK_END);
-	sysmapFileLen = ftell(sysmap);
-	fseek(sysmap, 0, SEEK_SET);
-	printf("%s file size = %ld\n", argv[1], sysmapFileLen);
-
-	sysmapLen = sysmapFileLen;
-
-	roundR = 4096 - (sysmapLen % 4096);
-	if (roundR)
-	{
-		printf("Rounding System Map file up to a multiple of 4096, adding %ld\n", roundR);
-		sysmapLen += roundR;
-	}
-	printf("Rounded System Map size is %ld\n", sysmapLen);
-  
-  /* Process the Sysmap file to determine the true end of the kernel */
-	sysmapPages = sysmapLen / 4096;
-	printf("System map pages to copy = %ld\n", sysmapPages);
-	/* read the whole file line by line, expect that it doesn't fail */
-	while ( fgets(inbuf, 4096, sysmap) )  ;
-	/* search for _end in the last page of the system map */
-	ptr_end = strstr(inbuf, " _end");
-	if (!ptr_end)
-	{
-		fprintf(stderr, "Unable to find _end in the sysmap file \n");
-		fprintf(stderr, "inbuf: \n");
-		fprintf(stderr, "%s \n", inbuf);
-		exit(1);
-	}
-	printf("Found _end in the last page of the sysmap - backing up 10 characters it looks like %s", ptr_end-10);
-	sysmapStartOffs = (unsigned int)strtol(ptr_end-10, NULL, 16);
-	/* calc how many pages we need to insert between the vmlinux and the start of the sysmap */
-	padPages = sysmapStartOffs/4096 - roundedKernelPages;
-
-	/* Check and see if the vmlinux is larger than _end in System.map */
-	if (padPages < 0)
-	{ /* vmlinux is larger than _end - adjust the offset to start the embedded system map */ 
-		sysmapStartOffs = roundedKernelLen;
-		printf("vmlinux is larger than _end indicates it needs to be - sysmapStartOffs = %lx \n", sysmapStartOffs);
-		padPages = 0;
-		printf("will insert %lx pages between the vmlinux and the start of the sysmap \n", padPages);
-	}
-	else
-	{ /* _end is larger than vmlinux - use the sysmapStartOffs we calculated from the system map */
-		printf("vmlinux is smaller than _end indicates is needed - sysmapStartOffs = %lx \n", sysmapStartOffs);
-		printf("will insert %lx pages between the vmlinux and the start of the sysmap \n", padPages);
-	}
-
-
-
-
-	/* Copy 64K ELF header */
-	for (i=0; i<(ElfPages); ++i)
-	{
-		get4k( inputVmlinux, inbuf );
-		put4k( outputVmlinux, inbuf );
-	}
-
-  
-	/* Copy the vmlinux (as full pages). */
-	fseek(inputVmlinux, ElfHeaderSize, SEEK_SET);
-	for ( i=0; i<roundedKernelPages; ++i )
-	{
-		get4k( inputVmlinux, inbuf );
-    
-		/* Set the offsets (of the start and end) of the embedded sysmap so it is set in the vmlinux.sm */
-		if ( i == 0 )
-		{
-			unsigned long * p;
-			printf("Storing embedded_sysmap_start at 0x3c\n");
-			p = (unsigned long *)(inbuf + 0x3c);
-
-#if (BYTE_ORDER == __BIG_ENDIAN)
-			*p = sysmapStartOffs;
-#else
-			*p = bswap_32(sysmapStartOffs);
-#endif
-
-			printf("Storing embedded_sysmap_end at 0x44\n");
-			p = (unsigned long *)(inbuf + 0x44);
-
-#if (BYTE_ORDER == __BIG_ENDIAN)
-			*p = sysmapStartOffs + sysmapFileLen;
-#else
-			*p = bswap_32(sysmapStartOffs + sysmapFileLen);
-#endif
-		}
-    
-		put4k( outputVmlinux, inbuf );
-	}
-  
-  
-	/* Insert any pad pages between the end of the vmlinux and where the system map needs to be. */
-	for (i=0; i<padPages; ++i)
-	{
-		memset(inbuf, 0, 4096);
-		put4k(outputVmlinux, inbuf);
-	}
-
-
-	/* Copy the system map (as full pages). */
-	fseek(sysmap, 0, SEEK_SET);  /* start reading from begining of the system map */
-	for ( i=0; i<sysmapPages; ++i )
-	{
-		get4k( sysmap, inbuf );
-		put4k( outputVmlinux, inbuf );
-	}
-
-
-	fclose(sysmap);
-	fclose(inputVmlinux);
-	fclose(outputVmlinux);
-	/* Set permission to executable */
-	chmod(argv[3], S_IRUSR|S_IWUSR|S_IXUSR|S_IRGRP|S_IXGRP|S_IROTH|S_IXOTH);
-
-	return 0;
-}
-
diff -Nru a/arch/ppc64/boot/main.c b/arch/ppc64/boot/main.c
--- a/arch/ppc64/boot/main.c	2004-10-18 14:57:18 -07:00
+++ b/arch/ppc64/boot/main.c	2004-10-18 14:57:18 -07:00
@@ -31,13 +31,9 @@
 void *memmove(void *dest, const void *src, unsigned long n);
 void *memcpy(void *dest, const void *src, unsigned long n);
 
-static struct bi_record *make_bi_recs(unsigned long);
-
-#define RAM_START	0x00000000
-#define RAM_END		(64<<20)
-
 /* Value picked to match that used by yaboot */
 #define PROG_START	0x01400000
+#define RAM_END		(256<<20) // Fixme: use OF */
 
 char *avail_ram;
 char *begin_avail, *end_avail;
@@ -48,8 +44,6 @@
 extern char _start[];
 extern char _vmlinux_start[];
 extern char _vmlinux_end[];
-extern char _sysmap_start[];
-extern char _sysmap_end[];
 extern char _initrd_start[];
 extern char _initrd_end[];
 extern unsigned long vmlinux_filesize;
@@ -62,7 +56,6 @@
 };
 struct addr_range vmlinux = {0, 0, 0};
 struct addr_range vmlinuz = {0, 0, 0};
-struct addr_range sysmap  = {0, 0, 0};
 struct addr_range initrd  = {0, 0, 0};
 
 static char scratch[128<<10];	/* 128kB of scratch space for gunzip */
@@ -70,7 +63,7 @@
 typedef void (*kernel_entry_t)( unsigned long,
                                 unsigned long,
                                 void *,
-				struct bi_record *);
+				void *);
 
 
 int (*prom)(void *);
@@ -80,12 +73,31 @@
 void *stdout;
 void *stderr;
 
+#define DEBUG
+
+static unsigned long claim_base = PROG_START;
+
+static unsigned long try_claim(unsigned long size)
+{
+	unsigned long addr = 0;
+
+	for(; claim_base < RAM_END; claim_base += 0x100000) {
+#ifdef DEBUG
+		printf("    trying: 0x%08lx\n\r", claim_base);
+#endif
+		addr = (unsigned long)claim(claim_base, size, 0);
+		if ((void *)addr != (void *)-1)
+			break;
+	}
+	if (addr == 0)
+		return 0;
+	claim_base = PAGE_ALIGN(claim_base + size);
+	return addr;
+}
 
-void
-start(unsigned long a1, unsigned long a2, void *promptr)
+void start(unsigned long a1, unsigned long a2, void *promptr)
 {
-	unsigned long i, claim_addr, claim_size;
-	struct bi_record *bi_recs;
+	unsigned long i;
 	kernel_entry_t kernel_entry;
 	Elf64_Ehdr *elf64;
 	Elf64_Phdr *elf64ph;
@@ -102,61 +114,59 @@
 
 	printf("zImage starting: loaded at 0x%x\n\r", (unsigned)_start);
 
-#if 0
-	sysmap.size = (unsigned long)(_sysmap_end - _sysmap_start);
-	sysmap.memsize = sysmap.size;
-	if ( sysmap.size > 0 ) {
-		sysmap.addr = (RAM_END - sysmap.size) & ~0xFFF;
-		claim(sysmap.addr, RAM_END - sysmap.addr, 0);
-		printf("initial ramdisk moving 0x%lx <- 0x%lx (%lx bytes)\n\r",
-		       sysmap.addr, (unsigned long)_sysmap_start, sysmap.size);
-		memcpy((void *)sysmap.addr, (void *)_sysmap_start, sysmap.size);
+	/*
+	 * Now we try to claim some memory for the kernel itself
+	 * our "vmlinux_memsize" is the memory footprint in RAM, _HOWEVER_, what
+	 * our Makefile stuffs in is an image containing all sort of junk including
+	 * an ELF header. We need to do some calculations here to find the right
+	 * size... In practice we add 1Mb, that is enough, but we should really
+	 * consider fixing the Makefile to put a _raw_ kernel in there !
+	 */
+	vmlinux_memsize += 0x100000;
+	printf("Allocating 0x%lx bytes for kernel ...\n\r", vmlinux_memsize);
+	vmlinux.addr = try_claim(vmlinux_memsize);
+	if (vmlinux.addr == 0) {
+		printf("Can't allocate memory for kernel image !\n\r");
+		exit();
 	}
-#endif
+	vmlinuz.addr = (unsigned long)_vmlinux_start;
+	vmlinuz.size = (unsigned long)(_vmlinux_end - _vmlinux_start);
+	vmlinux.size = PAGE_ALIGN(vmlinux_filesize);
+	vmlinux.memsize = vmlinux_memsize;
 
+	/*
+	 * Now we try to claim memory for the initrd (and copy it there)
+	 */
 	initrd.size = (unsigned long)(_initrd_end - _initrd_start);
 	initrd.memsize = initrd.size;
 	if ( initrd.size > 0 ) {
-		initrd.addr = (RAM_END - initrd.size) & ~0xFFF;
-		a1 = a2 = 0;
-		claim(initrd.addr, RAM_END - initrd.addr, 0);
+		printf("Allocating 0x%lx bytes for initrd ...\n\r", initrd.size);
+		initrd.addr = try_claim(initrd.size);
+		if (initrd.addr == 0) {
+			printf("Can't allocate memory for initial ramdisk !\n\r");
+			exit();
+		}
+		a1 = initrd.addr;
+		a2 = initrd.size;
 		printf("initial ramdisk moving 0x%lx <- 0x%lx (%lx bytes)\n\r",
 		       initrd.addr, (unsigned long)_initrd_start, initrd.size);
-		memcpy((void *)initrd.addr, (void *)_initrd_start, initrd.size);
+		memmove((void *)initrd.addr, (void *)_initrd_start, initrd.size);
+		printf("initrd head: 0x%lx\n", *((u32 *)initrd.addr));
 	}
 
-	vmlinuz.addr = (unsigned long)_vmlinux_start;
-	vmlinuz.size = (unsigned long)(_vmlinux_end - _vmlinux_start);
-	vmlinux.addr = (unsigned long)(void *)-1;
-	vmlinux.size = PAGE_ALIGN(vmlinux_filesize);
-	vmlinux.memsize = vmlinux_memsize;
-
-	claim_size = vmlinux.memsize /* PPPBBB: + fudge for bi_recs */;
-	for(claim_addr = PROG_START; 
-	    claim_addr <= PROG_START * 8; 
-	    claim_addr += 0x100000) {
-#ifdef DEBUG
-		printf("    trying: 0x%08lx\n\r", claim_addr);
-#endif
-		vmlinux.addr = (unsigned long)claim(claim_addr, claim_size, 0);
-		if ((void *)vmlinux.addr != (void *)-1) break;
-	}
-	if ((void *)vmlinux.addr == (void *)-1) {
-		printf("claim error, can't allocate kernel memory\n\r");
-		exit();
-	}
-
-	/* PPPBBB: should kernel always be gziped? */
+	/* Eventually gunzip the kernel */
 	if (*(unsigned short *)vmlinuz.addr == 0x1f8b) {
+		int len;
 		avail_ram = scratch;
 		begin_avail = avail_high = avail_ram;
 		end_avail = scratch + sizeof(scratch);
 		printf("gunzipping (0x%lx <- 0x%lx:0x%0lx)...",
 		       vmlinux.addr, vmlinuz.addr, vmlinuz.addr+vmlinuz.size);
+		len = vmlinuz.size;
 		gunzip((void *)vmlinux.addr, vmlinux.size,
-			(unsigned char *)vmlinuz.addr, (int *)&vmlinuz.size);
-		printf("done %lu bytes\n\r", vmlinuz.size);
-		printf("%u bytes of heap consumed, max in use %u\n\r",
+			(unsigned char *)vmlinuz.addr, &len);
+		printf("done 0x%lx bytes\n\r", len);
+		printf("0x%x bytes of heap consumed, max in use 0x%\n\r",
 		       (unsigned)(avail_high - begin_avail), heap_max);
 	} else {
 		memmove((void *)vmlinux.addr,(void *)vmlinuz.addr,vmlinuz.size);
@@ -192,7 +202,8 @@
 
 	flush_cache((void *)vmlinux.addr, vmlinux.memsize);
 
-	bi_recs = make_bi_recs(vmlinux.addr + vmlinux.memsize);
+	if (a1)
+		printf("initrd head: 0x%lx\n\r", *((u32 *)initrd.addr));
 
 	kernel_entry = (kernel_entry_t)vmlinux.addr;
 #ifdef DEBUG
@@ -203,63 +214,14 @@
 		"        prom       = 0x%lx,\n\r"
 		"        bi_recs    = 0x%lx,\n\r",
 		(unsigned long)kernel_entry, a1, a2,
-		(unsigned long)prom, (unsigned long)bi_recs);
+		(unsigned long)prom, NULL);
 #endif
 
-	kernel_entry( a1, a2, prom, bi_recs );
+	kernel_entry( a1, a2, prom, NULL );
 
 	printf("Error: Linux kernel returned to zImage bootloader!\n\r");
 
 	exit();
-}
-
-static struct bi_record *
-make_bi_recs(unsigned long addr)
-{
-	struct bi_record *bi_recs;
-	struct bi_record *rec;
-
-	bi_recs = rec = bi_rec_init(addr);
-
-	rec = bi_rec_alloc(rec, 2);
-	rec->tag = BI_FIRST;
-	/* rec->data[0] = ...;	# Written below before return */
-	/* rec->data[1] = ...;	# Written below before return */
-
-	rec = bi_rec_alloc_bytes(rec, strlen("chrpboot")+1);
-	rec->tag = BI_BOOTLOADER_ID;
-	sprintf( (char *)rec->data, "chrpboot");
-
-	rec = bi_rec_alloc(rec, 2);
-	rec->tag = BI_MACHTYPE;
-	rec->data[0] = PLATFORM_PSERIES;
-	rec->data[1] = 1;
-
-	if ( initrd.size > 0 ) {
-		rec = bi_rec_alloc(rec, 2);
-		rec->tag = BI_INITRD;
-		rec->data[0] = initrd.addr;
-		rec->data[1] = initrd.size;
-	}
-
-	if ( sysmap.size > 0 ) {
-		rec = bi_rec_alloc(rec, 2);
-		rec->tag = BI_SYSMAP;
-		rec->data[0] = (unsigned long)sysmap.addr;
-		rec->data[1] = (unsigned long)sysmap.size;
-	}
-
-	rec = bi_rec_alloc(rec, 1);
-	rec->tag = BI_LAST;
-	rec->data[0] = (bi_rec_field)bi_recs;
-
-	/* Save the _end_ address of the bi_rec's in the first bi_rec
-	 * data field for easy access by the kernel.
-	 */
-	bi_recs->data[0] = (bi_rec_field)rec;
-	bi_recs->data[1] = (bi_rec_field)rec + rec->size - (bi_rec_field)bi_recs;
-
-	return bi_recs;
 }
 
 struct memchunk {
diff -Nru a/arch/ppc64/boot/zImage.lds b/arch/ppc64/boot/zImage.lds
--- a/arch/ppc64/boot/zImage.lds	2004-10-18 14:55:54 -07:00
+++ b/arch/ppc64/boot/zImage.lds	2004-10-18 14:55:54 -07:00
@@ -61,18 +61,8 @@
 
   . = ALIGN(4096);
   _vmlinux_start =  .;
-  .kernel:vmlinux : { *(.kernel:vmlinux) }
+  .kernel:vmlinux.strip : { *(.kernel:vmlinux.strip) }
   _vmlinux_end =  .;
-
-  . = ALIGN(4096);
-  _dotconfig_start =  .;
-  .kernel:.config : { *(.kernel:.config) }
-  _dotconfig_end =  .;
-
-  . = ALIGN(4096);
-  _sysmap_start =  .;
-  .kernel:System.map : { *(.kernel:System.map) }
-  _sysmap_end =  .;
 
   . = ALIGN(4096);
   _initrd_start =  .;
diff -Nru a/arch/ppc64/configs/g5_defconfig b/arch/ppc64/configs/g5_defconfig
--- a/arch/ppc64/configs/g5_defconfig	2004-10-18 14:55:54 -07:00
+++ b/arch/ppc64/configs/g5_defconfig	2004-10-18 14:55:54 -07:00
@@ -1,5 +1,7 @@
 #
 # Automatically generated make config: don't edit
+# Linux kernel version: 2.6.9-rc3
+# Thu Oct  7 15:18:38 2004
 #
 CONFIG_64BIT=y
 CONFIG_MMU=y
@@ -16,11 +18,11 @@
 #
 CONFIG_EXPERIMENTAL=y
 CONFIG_CLEAN_COMPILE=y
-CONFIG_STANDALONE=y
 
 #
 # General setup
 #
+CONFIG_LOCALVERSION=""
 CONFIG_SWAP=y
 CONFIG_SYSVIPC=y
 # CONFIG_POSIX_MQUEUE is not set
@@ -32,6 +34,8 @@
 # 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_IOSCHED_NOOP=y
@@ -39,6 +43,8 @@
 CONFIG_IOSCHED_DEADLINE=y
 CONFIG_IOSCHED_CFQ=y
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+CONFIG_SHMEM=y
+# CONFIG_TINY_SHMEM is not set
 
 #
 # Loadable module support
@@ -50,18 +56,20 @@
 # CONFIG_MODVERSIONS is not set
 # CONFIG_KMOD is not set
 CONFIG_STOP_MACHINE=y
+CONFIG_SYSVIPC_COMPAT=y
 
 #
 # Platform support
 #
 # CONFIG_PPC_ISERIES is not set
-CONFIG_PPC_PSERIES=y
+CONFIG_PPC_MULTIPLATFORM=y
+# CONFIG_PPC_PSERIES is not set
+CONFIG_PPC_PMAC=y
 CONFIG_PPC=y
 CONFIG_PPC64=y
 CONFIG_PPC_OF=y
 CONFIG_ALTIVEC=y
-CONFIG_PPC_PMAC=y
-CONFIG_PMAC_DART=y
+CONFIG_U3_DART=y
 CONFIG_PPC_PMAC64=y
 CONFIG_BOOTX_TEXT=y
 CONFIG_POWER4_ONLY=y
@@ -69,8 +77,8 @@
 CONFIG_SMP=y
 CONFIG_IRQ_ALL_CPUS=y
 CONFIG_NR_CPUS=2
-# CONFIG_HMT is not set
-# CONFIG_DISCONTIGMEM is not set
+# CONFIG_SCHED_SMT is not set
+# CONFIG_PREEMPT is not set
 # CONFIG_PPC_RTAS is not set
 # CONFIG_LPARCFG is not set
 
@@ -104,6 +112,8 @@
 #
 # Generic Driver Options
 #
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
 CONFIG_FW_LOADER=y
 # CONFIG_DEBUG_DRIVER is not set
 
@@ -132,7 +142,8 @@
 CONFIG_BLK_DEV_LOOP=y
 # CONFIG_BLK_DEV_CRYPTOLOOP is not set
 CONFIG_BLK_DEV_NBD=m
-# CONFIG_BLK_DEV_CARMEL is not set
+# CONFIG_BLK_DEV_SX8 is not set
+# CONFIG_BLK_DEV_UB is not set
 CONFIG_BLK_DEV_RAM=y
 CONFIG_BLK_DEV_RAM_SIZE=8192
 CONFIG_BLK_DEV_INITRD=y
@@ -146,9 +157,9 @@
 #
 # Please see Documentation/ide.txt for help/info on IDE drives
 #
+# 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=y
 CONFIG_BLK_DEV_IDETAPE=y
 CONFIG_BLK_DEV_IDEFLOPPY=y
@@ -170,7 +181,6 @@
 # CONFIG_BLK_DEV_IDEDMA_FORCED is not set
 CONFIG_IDEDMA_PCI_AUTO=y
 # CONFIG_IDEDMA_ONLYDISK is not set
-CONFIG_BLK_DEV_ADMA=y
 # CONFIG_BLK_DEV_AEC62XX is not set
 # CONFIG_BLK_DEV_ALI15X3 is not set
 # CONFIG_BLK_DEV_AMD74XX is not set
@@ -196,6 +206,7 @@
 CONFIG_BLK_DEV_IDEDMA_PMAC=y
 # CONFIG_BLK_DEV_IDE_PMAC_BLINK is not set
 CONFIG_BLK_DEV_IDEDMA_PMAC_AUTO=y
+# CONFIG_IDE_ARM is not set
 CONFIG_BLK_DEV_IDEDMA=y
 # CONFIG_IDEDMA_IVB is not set
 CONFIG_IDEDMA_AUTO=y
@@ -221,7 +232,6 @@
 # Some SCSI devices (e.g. CD jukebox) support multiple LUNs
 #
 CONFIG_SCSI_MULTI_LUN=y
-CONFIG_SCSI_REPORT_LUNS=y
 CONFIG_SCSI_CONSTANTS=y
 # CONFIG_SCSI_LOGGING is not set
 
@@ -235,23 +245,25 @@
 # 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_ADVANSYS is not set
-# CONFIG_SCSI_MEGARAID is not set
+# CONFIG_MEGARAID_NEWGEN is not set
+# CONFIG_MEGARAID_LEGACY is not set
 CONFIG_SCSI_SATA=y
 CONFIG_SCSI_SATA_SVW=y
 # CONFIG_SCSI_ATA_PIIX is not set
+# 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
 # CONFIG_SCSI_SATA_SIS is not set
 # CONFIG_SCSI_SATA_VIA is not set
 # 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
@@ -264,6 +276,7 @@
 CONFIG_SCSI_SYM53C8XX_DEFAULT_TAGS=16
 CONFIG_SCSI_SYM53C8XX_MAX_TAGS=64
 # 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
@@ -277,7 +290,6 @@
 # CONFIG_SCSI_DC395x is not set
 # CONFIG_SCSI_DC390T is not set
 # CONFIG_SCSI_DEBUG is not set
-# CONFIG_SCSI_MESH is not set
 # CONFIG_SCSI_MAC53C94 is not set
 
 #
@@ -288,11 +300,15 @@
 CONFIG_MD_LINEAR=y
 CONFIG_MD_RAID0=y
 CONFIG_MD_RAID1=y
+# CONFIG_MD_RAID10 is not set
 CONFIG_MD_RAID5=y
 # CONFIG_MD_RAID6 is not set
 # CONFIG_MD_MULTIPATH is not set
 CONFIG_BLK_DEV_DM=y
 # CONFIG_DM_CRYPT is not set
+# CONFIG_DM_SNAPSHOT is not set
+# CONFIG_DM_MIRROR is not set
+# CONFIG_DM_ZERO is not set
 
 #
 # Fusion MPT device support
@@ -332,6 +348,7 @@
 #
 # I2O device support
 #
+# CONFIG_I2O is not set
 
 #
 # Macintosh device drivers
@@ -340,7 +357,6 @@
 CONFIG_ADB_PMU=y
 # CONFIG_PMAC_PBOOK is not set
 # CONFIG_PMAC_BACKLIGHT is not set
-# CONFIG_MAC_SERIAL is not set
 # CONFIG_INPUT_ADBHID is not set
 CONFIG_THERM_PM72=y
 
@@ -369,14 +385,13 @@
 CONFIG_INET_AH=m
 CONFIG_INET_ESP=m
 CONFIG_INET_IPCOMP=m
+CONFIG_INET_TUNNEL=y
 
 #
 # IP: Virtual Server Configuration
 #
 # CONFIG_IP_VS is not set
 # CONFIG_IPV6 is not set
-# CONFIG_DECNET is not set
-# CONFIG_BRIDGE is not set
 CONFIG_NETFILTER=y
 # CONFIG_NETFILTER_DEBUG is not set
 
@@ -384,6 +399,8 @@
 # IP: Netfilter Configuration
 #
 CONFIG_IP_NF_CONNTRACK=y
+# CONFIG_IP_NF_CT_ACCT is not set
+# CONFIG_IP_NF_CT_PROTO_SCTP is not set
 # CONFIG_IP_NF_FTP is not set
 # CONFIG_IP_NF_IRC is not set
 # CONFIG_IP_NF_TFTP is not set
@@ -408,8 +425,15 @@
 CONFIG_IP_NF_MATCH_STATE=y
 CONFIG_IP_NF_MATCH_CONNTRACK=y
 CONFIG_IP_NF_MATCH_OWNER=y
+# CONFIG_IP_NF_MATCH_ADDRTYPE is not set
+# CONFIG_IP_NF_MATCH_REALM is not set
+# CONFIG_IP_NF_MATCH_SCTP is not set
+# CONFIG_IP_NF_MATCH_COMMENT is not set
 CONFIG_IP_NF_FILTER=y
 CONFIG_IP_NF_TARGET_REJECT=y
+CONFIG_IP_NF_TARGET_LOG=y
+CONFIG_IP_NF_TARGET_ULOG=y
+CONFIG_IP_NF_TARGET_TCPMSS=y
 CONFIG_IP_NF_NAT=y
 CONFIG_IP_NF_NAT_NEEDED=y
 CONFIG_IP_NF_TARGET_MASQUERADE=y
@@ -424,9 +448,7 @@
 CONFIG_IP_NF_TARGET_DSCP=y
 CONFIG_IP_NF_TARGET_MARK=y
 CONFIG_IP_NF_TARGET_CLASSIFY=y
-CONFIG_IP_NF_TARGET_LOG=y
-CONFIG_IP_NF_TARGET_ULOG=y
-CONFIG_IP_NF_TARGET_TCPMSS=y
+# CONFIG_IP_NF_RAW is not set
 CONFIG_IP_NF_ARPTABLES=y
 CONFIG_IP_NF_ARPFILTER=y
 CONFIG_IP_NF_ARP_MANGLE=y
@@ -438,7 +460,9 @@
 #
 # CONFIG_IP_SCTP is not set
 # CONFIG_ATM is not set
+# CONFIG_BRIDGE is not set
 # CONFIG_VLAN_8021Q is not set
+# CONFIG_DECNET is not set
 CONFIG_LLC=y
 # CONFIG_LLC2 is not set
 # CONFIG_IPX is not set
@@ -454,30 +478,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=m
+CONFIG_BONDING=m
+# CONFIG_EQUALIZER is not set
+CONFIG_TUN=m
 
 #
 # ARCnet devices
 #
 # CONFIG_ARCNET is not set
-CONFIG_DUMMY=m
-CONFIG_BONDING=m
-# CONFIG_EQUALIZER is not set
-CONFIG_TUN=m
 
 #
 # Ethernet (10 or 100Mbit)
 #
 CONFIG_NET_ETHERNET=y
 CONFIG_MII=y
-# CONFIG_MACE is not set
-# CONFIG_BMAC is not set
-# CONFIG_OAKNET is not set
 # CONFIG_HAPPYMEAL is not set
 CONFIG_SUNGEM=y
 # CONFIG_NET_VENDOR_3COM is not set
@@ -509,57 +536,38 @@
 #
 # CONFIG_IXGB is not set
 # CONFIG_S2IO is not set
-# CONFIG_FDDI is not set
-# CONFIG_HIPPI is not set
-# CONFIG_IBMVETH is not set
-CONFIG_PPP=m
-# CONFIG_PPP_MULTILINK is not set
-# CONFIG_PPP_FILTER is not set
-CONFIG_PPP_ASYNC=m
-CONFIG_PPP_SYNC_TTY=m
-CONFIG_PPP_DEFLATE=m
-CONFIG_PPP_BSDCOMP=m
-CONFIG_PPPOE=m
-# CONFIG_SLIP is not set
-
-#
-# Wireless LAN (non-hamradio)
-#
-# CONFIG_NET_RADIO is not set
 
 #
 # Token Ring devices
 #
 CONFIG_TR=y
 CONFIG_IBMOL=y
-# CONFIG_IBMLS is not set
 # CONFIG_3C359 is not set
 # CONFIG_TMS380TR is not set
-# CONFIG_NET_FC is not set
-# CONFIG_SHAPER is not set
-# CONFIG_NETCONSOLE is not set
-
-#
-# Wan interfaces
-#
-# CONFIG_WAN is not set
-
-#
-# Amateur Radio support
-#
-# CONFIG_HAMRADIO is not set
 
 #
-# IrDA (infrared) support
+# Wireless LAN (non-hamradio)
 #
-# CONFIG_IRDA is not set
+# CONFIG_NET_RADIO is not set
 
 #
-# Bluetooth support
+# Wan interfaces
 #
-# CONFIG_BT is not set
-# CONFIG_NETPOLL is not set
-# CONFIG_NET_POLL_CONTROLLER is not set
+# CONFIG_WAN is not set
+# CONFIG_FDDI is not set
+# CONFIG_HIPPI is not set
+CONFIG_PPP=m
+# CONFIG_PPP_MULTILINK is not set
+# CONFIG_PPP_FILTER is not set
+CONFIG_PPP_ASYNC=m
+CONFIG_PPP_SYNC_TTY=m
+CONFIG_PPP_DEFLATE=m
+CONFIG_PPP_BSDCOMP=m
+CONFIG_PPPOE=m
+# CONFIG_SLIP is not set
+# CONFIG_NET_FC is not set
+# CONFIG_SHAPER is not set
+# CONFIG_NETCONSOLE is not set
 
 #
 # ISDN subsystem
@@ -598,6 +606,7 @@
 # CONFIG_SERIO_SERPORT is not set
 # CONFIG_SERIO_CT82C710 is not set
 # CONFIG_SERIO_PCIPS2 is not set
+# CONFIG_SERIO_RAW is not set
 
 #
 # Input Device Drivers
@@ -636,8 +645,6 @@
 CONFIG_UNIX98_PTYS=y
 CONFIG_LEGACY_PTYS=y
 CONFIG_LEGACY_PTY_COUNT=256
-CONFIG_HVC_CONSOLE=y
-# CONFIG_QIC02_TAPE is not set
 
 #
 # IPMI
@@ -673,6 +680,7 @@
 #
 CONFIG_I2C_ALGOBIT=y
 # CONFIG_I2C_ALGOPCF is not set
+# CONFIG_I2C_ALGOPCA is not set
 
 #
 # I2C Hardware Bus support
@@ -697,23 +705,29 @@
 # CONFIG_I2C_VIA is not set
 # CONFIG_I2C_VIAPRO is not set
 # CONFIG_I2C_VOODOO3 is not set
+# CONFIG_I2C_PCA_ISA is not set
 
 #
 # Hardware Sensors Chip support
 #
 # CONFIG_I2C_SENSOR is not set
 # CONFIG_SENSORS_ADM1021 is not set
+# CONFIG_SENSORS_ADM1025 is not set
+# CONFIG_SENSORS_ADM1031 is not set
 # CONFIG_SENSORS_ASB100 is not set
 # CONFIG_SENSORS_DS1621 is not set
 # CONFIG_SENSORS_FSCHER is not set
 # CONFIG_SENSORS_GL518SM is not set
 # CONFIG_SENSORS_IT87 is not set
 # CONFIG_SENSORS_LM75 is not set
+# CONFIG_SENSORS_LM77 is not set
 # CONFIG_SENSORS_LM78 is not set
 # CONFIG_SENSORS_LM80 is not set
 # CONFIG_SENSORS_LM83 is not set
 # CONFIG_SENSORS_LM85 is not set
 # CONFIG_SENSORS_LM90 is not set
+# CONFIG_SENSORS_MAX1619 is not set
+# CONFIG_SENSORS_SMSC47M1 is not set
 # CONFIG_SENSORS_VIA686A is not set
 # CONFIG_SENSORS_W83781D is not set
 # CONFIG_SENSORS_W83L785TS is not set
@@ -725,12 +739,18 @@
 # CONFIG_SENSORS_EEPROM is not set
 # CONFIG_SENSORS_PCF8574 is not set
 # CONFIG_SENSORS_PCF8591 is not set
+# CONFIG_SENSORS_RTC8564 is not set
 # CONFIG_I2C_DEBUG_CORE is not set
 # CONFIG_I2C_DEBUG_ALGO is not set
 # CONFIG_I2C_DEBUG_BUS is not set
 # CONFIG_I2C_DEBUG_CHIP is not set
 
 #
+# Dallas's 1-wire bus
+#
+# CONFIG_W1 is not set
+
+#
 # Misc devices
 #
 
@@ -748,6 +768,8 @@
 # Graphics support
 #
 CONFIG_FB=y
+CONFIG_FB_MODE_HELPERS=y
+# CONFIG_FB_CIRRUS is not set
 # CONFIG_FB_PM2 is not set
 # CONFIG_FB_CYBER2000 is not set
 CONFIG_FB_OF=y
@@ -755,10 +777,12 @@
 # CONFIG_FB_PLATINUM is not set
 # CONFIG_FB_VALKYRIE is not set
 # CONFIG_FB_CT65550 is not set
+# CONFIG_FB_ASILIANT is not set
 # CONFIG_FB_IMSTT is not set
-# CONFIG_FB_S3TRIO is not set
 # CONFIG_FB_VGA16 is not set
 CONFIG_FB_RIVA=y
+# CONFIG_FB_RIVA_I2C is not set
+# CONFIG_FB_RIVA_DEBUG is not set
 # CONFIG_FB_MATROX is not set
 # CONFIG_FB_RADEON_OLD is not set
 CONFIG_FB_RADEON=y
@@ -778,10 +802,8 @@
 # Console display driver support
 #
 # CONFIG_VGA_CONSOLE is not set
-# CONFIG_MDA_CONSOLE is not set
 CONFIG_DUMMY_CONSOLE=y
 CONFIG_FRAMEBUFFER_CONSOLE=y
-CONFIG_PCI_CONSOLE=y
 # CONFIG_FONTS is not set
 CONFIG_FONT_8x8=y
 CONFIG_FONT_8x16=y
@@ -811,6 +833,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
@@ -829,6 +852,7 @@
 CONFIG_USB_PRINTER=y
 CONFIG_USB_STORAGE=y
 # CONFIG_USB_STORAGE_DEBUG is not set
+# CONFIG_USB_STORAGE_RW_DETECT is not set
 CONFIG_USB_STORAGE_DATAFAB=y
 CONFIG_USB_STORAGE_FREECOM=y
 CONFIG_USB_STORAGE_ISD200=y
@@ -853,6 +877,7 @@
 # CONFIG_USB_KBTAB is not set
 # CONFIG_USB_POWERMATE is not set
 # CONFIG_USB_MTOUCH is not set
+# CONFIG_USB_EGALAX is not set
 # CONFIG_USB_XPAD is not set
 # CONFIG_USB_ATI_REMOTE is not set
 
@@ -959,6 +984,7 @@
 # CONFIG_USB_LCD is not set
 # CONFIG_USB_LED is not set
 # CONFIG_USB_CYTHERM is not set
+# CONFIG_USB_PHIDGETSERVO is not set
 # CONFIG_USB_TEST is not set
 
 #
@@ -997,6 +1023,7 @@
 # CONFIG_JOLIET is not set
 # CONFIG_ZISOFS is not set
 CONFIG_UDF_FS=m
+CONFIG_UDF_NLS=y
 
 #
 # DOS/FAT/NT Filesystems
@@ -1004,6 +1031,8 @@
 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
 
 #
@@ -1016,8 +1045,8 @@
 CONFIG_DEVPTS_FS_XATTR=y
 # CONFIG_DEVPTS_FS_SECURITY is not set
 CONFIG_TMPFS=y
-# CONFIG_HUGETLBFS is not set
-# CONFIG_HUGETLB_PAGE is not set
+CONFIG_HUGETLBFS=y
+CONFIG_HUGETLB_PAGE=y
 CONFIG_RAMFS=y
 
 #
@@ -1030,7 +1059,7 @@
 # CONFIG_BEFS_FS is not set
 # CONFIG_BFS_FS is not set
 # CONFIG_EFS_FS is not set
-# CONFIG_CRAMFS is not set
+CONFIG_CRAMFS=y
 # CONFIG_VXFS_FS is not set
 # CONFIG_HPFS_FS is not set
 # CONFIG_QNX4FS_FS is not set
@@ -1054,11 +1083,14 @@
 CONFIG_SUNRPC=y
 CONFIG_SUNRPC_GSS=y
 CONFIG_RPCSEC_GSS_KRB5=y
+# CONFIG_RPCSEC_GSS_SPKM3 is not set
 # CONFIG_SMB_FS is not set
 CONFIG_CIFS=m
+# CONFIG_CIFS_STATS is not set
+# CONFIG_CIFS_XATTR is not set
+# CONFIG_CIFS_POSIX 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
 
 #
@@ -1076,7 +1108,6 @@
 # CONFIG_SOLARIS_X86_PARTITION is not set
 # CONFIG_UNIXWARE_DISKLABEL is not set
 # CONFIG_LDM_PARTITION is not set
-# CONFIG_NEC98_PARTITION is not set
 # CONFIG_SGI_PARTITION is not set
 # CONFIG_ULTRIX_PARTITION is not set
 # CONFIG_SUN_PARTITION is not set
@@ -1110,6 +1141,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
@@ -1135,13 +1167,16 @@
 # Kernel hacking
 #
 CONFIG_DEBUG_KERNEL=y
+CONFIG_MAGIC_SYSRQ=y
+# CONFIG_DEBUG_SLAB is not set
+# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
+# CONFIG_DEBUG_INFO is not set
 # CONFIG_DEBUG_STACKOVERFLOW is not set
 # CONFIG_DEBUG_STACK_USAGE is not set
-# CONFIG_DEBUG_SLAB is not set
-CONFIG_MAGIC_SYSRQ=y
 # CONFIG_DEBUGGER is not set
 # CONFIG_PPCDBG is not set
-# CONFIG_DEBUG_INFO is not set
+CONFIG_IRQSTACKS=y
+# CONFIG_SCHEDSTATS is not set
 
 #
 # Security options
@@ -1159,6 +1194,7 @@
 CONFIG_CRYPTO_SHA1=m
 CONFIG_CRYPTO_SHA256=m
 CONFIG_CRYPTO_SHA512=m
+# CONFIG_CRYPTO_WP512 is not set
 CONFIG_CRYPTO_DES=y
 CONFIG_CRYPTO_BLOWFISH=m
 CONFIG_CRYPTO_TWOFISH=m
@@ -1166,14 +1202,19 @@
 CONFIG_CRYPTO_AES=m
 CONFIG_CRYPTO_CAST5=m
 CONFIG_CRYPTO_CAST6=m
+# CONFIG_CRYPTO_TEA is not set
 CONFIG_CRYPTO_ARC4=m
+# CONFIG_CRYPTO_KHAZAD is not set
 CONFIG_CRYPTO_DEFLATE=m
 CONFIG_CRYPTO_MICHAEL_MIC=m
+# CONFIG_CRYPTO_CRC32C is not set
 CONFIG_CRYPTO_TEST=m
 
 #
 # Library routines
 #
+CONFIG_CRC_CCITT=m
 CONFIG_CRC32=y
-CONFIG_ZLIB_INFLATE=m
+# CONFIG_LIBCRC32C is not set
+CONFIG_ZLIB_INFLATE=y
 CONFIG_ZLIB_DEFLATE=m
diff -Nru a/arch/ppc64/configs/iSeries_defconfig b/arch/ppc64/configs/iSeries_defconfig
--- a/arch/ppc64/configs/iSeries_defconfig	2004-10-18 14:57:05 -07:00
+++ b/arch/ppc64/configs/iSeries_defconfig	2004-10-18 14:57:05 -07:00
@@ -16,17 +16,17 @@
 #
 CONFIG_EXPERIMENTAL=y
 CONFIG_CLEAN_COMPILE=y
-CONFIG_STANDALONE=y
 
 #
 # General setup
 #
 CONFIG_SWAP=y
 CONFIG_SYSVIPC=y
-# CONFIG_POSIX_MQUEUE is not set
+CONFIG_POSIX_MQUEUE=y
 # CONFIG_BSD_PROCESS_ACCT is not set
 CONFIG_SYSCTL=y
-# CONFIG_AUDIT is not set
+CONFIG_AUDIT=y
+CONFIG_AUDITSYSCALL=y
 CONFIG_LOG_BUF_SHIFT=17
 CONFIG_HOTPLUG=y
 CONFIG_IKCONFIG=y
@@ -34,6 +34,7 @@
 # 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_IOSCHED_NOOP=y
@@ -41,6 +42,8 @@
 CONFIG_IOSCHED_DEADLINE=y
 CONFIG_IOSCHED_CFQ=y
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+CONFIG_SHMEM=y
+# CONFIG_TINY_SHMEM is not set
 
 #
 # Loadable module support
@@ -62,10 +65,11 @@
 CONFIG_PPC=y
 CONFIG_PPC64=y
 # CONFIG_POWER4_ONLY is not set
-# CONFIG_IOMMU_VMERGE is not set
+CONFIG_IOMMU_VMERGE=y
 CONFIG_SMP=y
 CONFIG_NR_CPUS=32
 # CONFIG_SCHED_SMT is not set
+# CONFIG_PREEMPT is not set
 CONFIG_MSCHUNKS=y
 CONFIG_LPARCFG=y
 
@@ -97,6 +101,8 @@
 #
 # Generic Driver Options
 #
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
 CONFIG_FW_LOADER=m
 # CONFIG_DEBUG_DRIVER is not set
 
@@ -125,7 +131,7 @@
 CONFIG_BLK_DEV_LOOP=y
 # CONFIG_BLK_DEV_CRYPTOLOOP is not set
 CONFIG_BLK_DEV_NBD=m
-# 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
@@ -168,22 +174,23 @@
 # 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_ADVANSYS is not set
-# CONFIG_SCSI_MEGARAID is not set
+# CONFIG_MEGARAID_NEWGEN is not set
+# CONFIG_MEGARAID_LEGACY 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_IPS is not set
+CONFIG_SCSI_IBMVSCSI=m
 # CONFIG_SCSI_INIA100 is not set
 # CONFIG_SCSI_SYM53C8XX_2 is not set
 # CONFIG_SCSI_IPR is not set
@@ -209,11 +216,15 @@
 CONFIG_MD_LINEAR=y
 CONFIG_MD_RAID0=y
 CONFIG_MD_RAID1=y
+CONFIG_MD_RAID10=m
 CONFIG_MD_RAID5=y
-CONFIG_MD_RAID6=y
-# CONFIG_MD_MULTIPATH is not set
+CONFIG_MD_RAID6=m
+CONFIG_MD_MULTIPATH=m
 CONFIG_BLK_DEV_DM=y
 CONFIG_DM_CRYPT=m
+CONFIG_DM_SNAPSHOT=m
+CONFIG_DM_MIRROR=m
+CONFIG_DM_ZERO=m
 
 #
 # Fusion MPT device support
@@ -259,6 +270,7 @@
 CONFIG_INET_AH=m
 CONFIG_INET_ESP=m
 CONFIG_INET_IPCOMP=m
+CONFIG_INET_TUNNEL=y
 
 #
 # IP: Virtual Server Configuration
@@ -324,7 +336,13 @@
 CONFIG_IP_NF_ARP_MANGLE=m
 CONFIG_IP_NF_COMPAT_IPCHAINS=m
 CONFIG_IP_NF_COMPAT_IPFWADM=m
-# CONFIG_IP_NF_RAW is not set
+CONFIG_IP_NF_TARGET_NOTRACK=m
+CONFIG_IP_NF_RAW=m
+CONFIG_IP_NF_MATCH_ADDRTYPE=m
+CONFIG_IP_NF_MATCH_REALM=m
+# CONFIG_IP_NF_CT_ACCT is not set
+CONFIG_IP_NF_MATCH_SCTP=m
+CONFIG_IP_NF_CT_PROTO_SCTP=m
 CONFIG_XFRM=y
 CONFIG_XFRM_USER=m
 
@@ -351,6 +369,7 @@
 # QoS and/or fair queueing
 #
 # CONFIG_NET_SCHED is not set
+CONFIG_NET_CLS_ROUTE=y
 
 #
 # Network testing
@@ -379,7 +398,6 @@
 #
 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
@@ -408,18 +426,32 @@
 # CONFIG_EPIC100 is not set
 # CONFIG_SUNDANCE is not set
 # CONFIG_VIA_RHINE is not set
+# CONFIG_VIA_VELOCITY is not set
 
 #
-# Gigabit Ethernet (1000/10000 Mbit)
+# Ethernet (1000 Mbit)
 #
-# CONFIG_NET_GIGE is not set
+# CONFIG_ACENIC is not set
+# CONFIG_DL2K is not set
+# CONFIG_E1000 is not set
+# CONFIG_NS83820 is not set
+# CONFIG_HAMACHI is not set
+# CONFIG_YELLOWFIN is not set
+# CONFIG_R8169 is not set
+# CONFIG_SK98LIN is not set
+# CONFIG_TIGON3 is not set
+
+#
+# Ethernet (10000 Mbit)
+#
+# CONFIG_IXGB is not set
+# CONFIG_S2IO is not set
 
 #
 # Token Ring devices
 #
 CONFIG_TR=y
 CONFIG_IBMOL=y
-# CONFIG_IBMLS is not set
 # CONFIG_3C359 is not set
 # CONFIG_TMS380TR is not set
 
@@ -508,10 +540,11 @@
 #
 # Non-8250 serial port support
 #
+CONFIG_SERIAL_CORE=m
+CONFIG_SERIAL_ICOM=m
 CONFIG_UNIX98_PTYS=y
 CONFIG_LEGACY_PTYS=y
 CONFIG_LEGACY_PTY_COUNT=256
-# CONFIG_QIC02_TAPE is not set
 
 #
 # IPMI
@@ -542,6 +575,11 @@
 # CONFIG_I2C is not set
 
 #
+# Dallas's 1-wire bus
+#
+# CONFIG_W1 is not set
+
+#
 # Misc devices
 #
 
@@ -592,8 +630,10 @@
 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=y
+CONFIG_REISERFS_FS_XATTR=y
+CONFIG_REISERFS_FS_POSIX_ACL=y
+# CONFIG_REISERFS_FS_SECURITY is not set
+CONFIG_JFS_FS=m
 CONFIG_JFS_POSIX_ACL=y
 # CONFIG_JFS_DEBUG is not set
 # CONFIG_JFS_STATISTICS is not set
@@ -616,6 +656,7 @@
 # CONFIG_JOLIET is not set
 # CONFIG_ZISOFS is not set
 CONFIG_UDF_FS=m
+CONFIG_UDF_NLS=y
 
 #
 # DOS/FAT/NT Filesystems
@@ -623,6 +664,8 @@
 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
 
 #
@@ -663,19 +706,22 @@
 CONFIG_NFS_V3=y
 CONFIG_NFS_V4=y
 # CONFIG_NFS_DIRECTIO is not set
-CONFIG_NFSD=y
+CONFIG_NFSD=m
 CONFIG_NFSD_V3=y
 CONFIG_NFSD_V4=y
 CONFIG_NFSD_TCP=y
 CONFIG_LOCKD=y
 CONFIG_LOCKD_V4=y
-CONFIG_EXPORTFS=y
+CONFIG_EXPORTFS=m
 CONFIG_SUNRPC=y
 CONFIG_SUNRPC_GSS=y
 CONFIG_RPCSEC_GSS_KRB5=y
+CONFIG_RPCSEC_GSS_SPKM3=m
 # CONFIG_SMB_FS is not set
 CONFIG_CIFS=m
 # CONFIG_CIFS_STATS is not set
+CONFIG_CIFS_XATTR=y
+CONFIG_CIFS_POSIX=y
 # CONFIG_NCP_FS is not set
 # CONFIG_CODA_FS is not set
 # CONFIG_AFS_FS is not set
@@ -691,7 +737,7 @@
 #
 CONFIG_NLS=y
 CONFIG_NLS_DEFAULT="iso8859-1"
-# CONFIG_NLS_CODEPAGE_437 is not set
+CONFIG_NLS_CODEPAGE_437=y
 # CONFIG_NLS_CODEPAGE_737 is not set
 # CONFIG_NLS_CODEPAGE_775 is not set
 # CONFIG_NLS_CODEPAGE_850 is not set
@@ -714,7 +760,8 @@
 # CONFIG_NLS_ISO8859_8 is not set
 # CONFIG_NLS_CODEPAGE_1250 is not set
 # CONFIG_NLS_CODEPAGE_1251 is not set
-# CONFIG_NLS_ISO8859_1 is not set
+CONFIG_NLS_ASCII=y
+CONFIG_NLS_ISO8859_1=y
 # CONFIG_NLS_ISO8859_2 is not set
 # CONFIG_NLS_ISO8859_3 is not set
 # CONFIG_NLS_ISO8859_4 is not set
@@ -748,14 +795,16 @@
 # Kernel hacking
 #
 CONFIG_DEBUG_KERNEL=y
+CONFIG_MAGIC_SYSRQ=y
+# CONFIG_DEBUG_SLAB is not set
+# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
+# CONFIG_DEBUG_INFO is not set
 CONFIG_DEBUG_STACKOVERFLOW=y
 CONFIG_DEBUG_STACK_USAGE=y
-# CONFIG_DEBUG_SLAB is not set
-CONFIG_MAGIC_SYSRQ=y
 # CONFIG_DEBUGGER is not set
 # CONFIG_PPCDBG is not set
-# CONFIG_DEBUG_INFO is not set
 # CONFIG_IRQSTACKS is not set
+# CONFIG_SCHEDSTATS is not set
 
 #
 # Security options
@@ -773,6 +822,7 @@
 CONFIG_CRYPTO_SHA1=m
 CONFIG_CRYPTO_SHA256=m
 CONFIG_CRYPTO_SHA512=m
+CONFIG_CRYPTO_WHIRLPOOL=m
 CONFIG_CRYPTO_DES=y
 CONFIG_CRYPTO_BLOWFISH=m
 CONFIG_CRYPTO_TWOFISH=m
@@ -780,16 +830,19 @@
 CONFIG_CRYPTO_AES=m
 CONFIG_CRYPTO_CAST5=m
 CONFIG_CRYPTO_CAST6=m
+CONFIG_CRYPTO_TEA=m
 CONFIG_CRYPTO_ARC4=m
+CONFIG_CRYPTO_KHAZAD=m
 CONFIG_CRYPTO_DEFLATE=m
-# CONFIG_CRYPTO_MICHAEL_MIC is not set
-# CONFIG_CRYPTO_CRC32C is not set
+CONFIG_CRYPTO_MICHAEL_MIC=m
+CONFIG_CRYPTO_CRC32C=m
 CONFIG_CRYPTO_TEST=m
 
 #
 # Library routines
 #
+CONFIG_CRC_CCITT=m
 CONFIG_CRC32=y
-# CONFIG_LIBCRC32C is not set
+CONFIG_LIBCRC32C=m
 CONFIG_ZLIB_INFLATE=y
 CONFIG_ZLIB_DEFLATE=m
diff -Nru a/arch/ppc64/configs/pSeries_defconfig b/arch/ppc64/configs/pSeries_defconfig
--- a/arch/ppc64/configs/pSeries_defconfig	2004-10-18 14:57:03 -07:00
+++ b/arch/ppc64/configs/pSeries_defconfig	2004-10-18 14:57:03 -07:00
@@ -1,5 +1,7 @@
 #
 # Automatically generated make config: don't edit
+# Linux kernel version: 2.6.9-rc2
+# Thu Sep 23 16:45:05 2004
 #
 CONFIG_64BIT=y
 CONFIG_MMU=y
@@ -16,27 +18,35 @@
 #
 CONFIG_EXPERIMENTAL=y
 CONFIG_CLEAN_COMPILE=y
-CONFIG_STANDALONE=y
 
 #
 # General setup
 #
+CONFIG_LOCALVERSION=""
 CONFIG_SWAP=y
 CONFIG_SYSVIPC=y
+CONFIG_POSIX_MQUEUE=y
 # CONFIG_BSD_PROCESS_ACCT is not set
 CONFIG_SYSCTL=y
+CONFIG_AUDIT=y
+CONFIG_AUDITSYSCALL=y
 CONFIG_LOG_BUF_SHIFT=17
 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 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
+CONFIG_SHMEM=y
+# CONFIG_TINY_SHMEM is not set
 
 #
 # Loadable module support
@@ -48,25 +58,31 @@
 # CONFIG_MODVERSIONS is not set
 # CONFIG_KMOD is not set
 CONFIG_STOP_MACHINE=y
+CONFIG_SYSVIPC_COMPAT=y
 
 #
 # Platform support
 #
 # CONFIG_PPC_ISERIES is not set
+CONFIG_PPC_MULTIPLATFORM=y
 CONFIG_PPC_PSERIES=y
+# CONFIG_PPC_PMAC is not set
 CONFIG_PPC=y
 CONFIG_PPC64=y
 CONFIG_PPC_OF=y
 CONFIG_ALTIVEC=y
-# CONFIG_PPC_PMAC is not set
+CONFIG_PPC_SPLPAR=y
 # CONFIG_BOOTX_TEXT is not set
 # CONFIG_POWER4_ONLY is not set
-# CONFIG_IOMMU_VMERGE is not set
+CONFIG_IOMMU_VMERGE=y
 CONFIG_SMP=y
 CONFIG_IRQ_ALL_CPUS=y
-CONFIG_NR_CPUS=32
+CONFIG_NR_CPUS=128
 # CONFIG_HMT is not set
-# CONFIG_DISCONTIGMEM is not set
+CONFIG_DISCONTIGMEM=y
+CONFIG_NUMA=y
+CONFIG_SCHED_SMT=y
+# CONFIG_PREEMPT is not set
 CONFIG_PPC_RTAS=y
 CONFIG_RTAS_FLASH=m
 CONFIG_SCANLOG=m
@@ -81,6 +97,7 @@
 # CONFIG_BINFMT_MISC is not set
 CONFIG_PCI_LEGACY_PROC=y
 CONFIG_PCI_NAMES=y
+CONFIG_HOTPLUG_CPU=y
 
 #
 # PCMCIA/CardBus support
@@ -107,7 +124,9 @@
 #
 # Generic Driver Options
 #
-CONFIG_FW_LOADER=m
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+CONFIG_FW_LOADER=y
 # CONFIG_DEBUG_DRIVER is not set
 
 #
@@ -127,7 +146,7 @@
 #
 # Block devices
 #
-CONFIG_BLK_DEV_FD=y
+CONFIG_BLK_DEV_FD=m
 # CONFIG_BLK_CPQ_DA is not set
 # CONFIG_BLK_CPQ_CISS_DA is not set
 # CONFIG_BLK_DEV_DAC960 is not set
@@ -135,7 +154,8 @@
 CONFIG_BLK_DEV_LOOP=y
 # CONFIG_BLK_DEV_CRYPTOLOOP is not set
 CONFIG_BLK_DEV_NBD=m
-# CONFIG_BLK_DEV_CARMEL is not set
+# CONFIG_BLK_DEV_SX8 is not set
+# CONFIG_BLK_DEV_UB is not set
 CONFIG_BLK_DEV_RAM=y
 CONFIG_BLK_DEV_RAM_SIZE=4096
 CONFIG_BLK_DEV_INITRD=y
@@ -149,9 +169,9 @@
 #
 # Please see Documentation/ide.txt for help/info on IDE drives
 #
+# 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=y
 # CONFIG_BLK_DEV_IDETAPE is not set
 # CONFIG_BLK_DEV_IDEFLOPPY is not set
@@ -173,7 +193,6 @@
 # CONFIG_BLK_DEV_IDEDMA_FORCED is not set
 CONFIG_IDEDMA_PCI_AUTO=y
 # CONFIG_IDEDMA_ONLYDISK is not set
-CONFIG_BLK_DEV_ADMA=y
 # CONFIG_BLK_DEV_AEC62XX is not set
 # CONFIG_BLK_DEV_ALI15X3 is not set
 CONFIG_BLK_DEV_AMD74XX=y
@@ -194,6 +213,7 @@
 # CONFIG_BLK_DEV_SLC90E66 is not set
 # CONFIG_BLK_DEV_TRM290 is not set
 # CONFIG_BLK_DEV_VIA82CXXX is not set
+# CONFIG_IDE_ARM is not set
 CONFIG_BLK_DEV_IDEDMA=y
 # CONFIG_IDEDMA_IVB is not set
 CONFIG_IDEDMA_AUTO=y
@@ -219,7 +239,6 @@
 # Some SCSI devices (e.g. CD jukebox) support multiple LUNs
 #
 CONFIG_SCSI_MULTI_LUN=y
-CONFIG_SCSI_REPORT_LUNS=y
 CONFIG_SCSI_CONSTANTS=y
 # CONFIG_SCSI_LOGGING is not set
 
@@ -233,28 +252,32 @@
 # 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_ADVANSYS is not set
-# CONFIG_SCSI_MEGARAID is not set
+# CONFIG_MEGARAID_NEWGEN is not set
+# CONFIG_MEGARAID_LEGACY 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_IPS is not set
+CONFIG_SCSI_IBMVSCSI=m
 # CONFIG_SCSI_INIA100 is not set
 CONFIG_SCSI_SYM53C8XX_2=y
 CONFIG_SCSI_SYM53C8XX_DMA_ADDRESSING_MODE=0
 CONFIG_SCSI_SYM53C8XX_DEFAULT_TAGS=16
 CONFIG_SCSI_SYM53C8XX_MAX_TAGS=64
 # CONFIG_SCSI_SYM53C8XX_IOMAPPED is not set
+CONFIG_SCSI_IPR=y
+# CONFIG_SCSI_IPR_TRACE is not set
+# CONFIG_SCSI_IPR_DUMP is not set
 # CONFIG_SCSI_QLOGIC_ISP is not set
 # CONFIG_SCSI_QLOGIC_FC is not set
 # CONFIG_SCSI_QLOGIC_1280 is not set
@@ -277,11 +300,15 @@
 CONFIG_MD_LINEAR=y
 CONFIG_MD_RAID0=y
 CONFIG_MD_RAID1=y
+CONFIG_MD_RAID10=m
 CONFIG_MD_RAID5=y
-CONFIG_MD_RAID6=y
-# CONFIG_MD_MULTIPATH is not set
+CONFIG_MD_RAID6=m
+CONFIG_MD_MULTIPATH=m
 CONFIG_BLK_DEV_DM=y
 CONFIG_DM_CRYPT=m
+CONFIG_DM_SNAPSHOT=m
+CONFIG_DM_MIRROR=m
+CONFIG_DM_ZERO=m
 
 #
 # Fusion MPT device support
@@ -296,6 +323,7 @@
 #
 # I2O device support
 #
+# CONFIG_I2O is not set
 
 #
 # Macintosh device drivers
@@ -322,19 +350,17 @@
 # CONFIG_NET_IPGRE is not set
 # CONFIG_IP_MROUTE is not set
 # CONFIG_ARPD is not set
-CONFIG_INET_ECN=y
 CONFIG_SYN_COOKIES=y
 CONFIG_INET_AH=m
 CONFIG_INET_ESP=m
 CONFIG_INET_IPCOMP=m
+CONFIG_INET_TUNNEL=y
 
 #
 # IP: Virtual Server Configuration
 #
 # CONFIG_IP_VS is not set
 # CONFIG_IPV6 is not set
-# CONFIG_DECNET is not set
-# CONFIG_BRIDGE is not set
 CONFIG_NETFILTER=y
 # CONFIG_NETFILTER_DEBUG is not set
 
@@ -342,6 +368,8 @@
 # IP: Netfilter Configuration
 #
 CONFIG_IP_NF_CONNTRACK=m
+# CONFIG_IP_NF_CT_ACCT is not set
+CONFIG_IP_NF_CT_PROTO_SCTP=m
 CONFIG_IP_NF_FTP=m
 CONFIG_IP_NF_IRC=m
 CONFIG_IP_NF_TFTP=m
@@ -366,8 +394,14 @@
 CONFIG_IP_NF_MATCH_STATE=m
 CONFIG_IP_NF_MATCH_CONNTRACK=m
 CONFIG_IP_NF_MATCH_OWNER=m
+CONFIG_IP_NF_MATCH_ADDRTYPE=m
+CONFIG_IP_NF_MATCH_REALM=m
+CONFIG_IP_NF_MATCH_SCTP=m
 CONFIG_IP_NF_FILTER=m
 CONFIG_IP_NF_TARGET_REJECT=m
+CONFIG_IP_NF_TARGET_LOG=m
+CONFIG_IP_NF_TARGET_ULOG=m
+CONFIG_IP_NF_TARGET_TCPMSS=m
 CONFIG_IP_NF_NAT=m
 CONFIG_IP_NF_NAT_NEEDED=y
 CONFIG_IP_NF_TARGET_MASQUERADE=m
@@ -386,9 +420,8 @@
 CONFIG_IP_NF_TARGET_DSCP=m
 CONFIG_IP_NF_TARGET_MARK=m
 CONFIG_IP_NF_TARGET_CLASSIFY=m
-CONFIG_IP_NF_TARGET_LOG=m
-CONFIG_IP_NF_TARGET_ULOG=m
-CONFIG_IP_NF_TARGET_TCPMSS=m
+CONFIG_IP_NF_RAW=m
+CONFIG_IP_NF_TARGET_NOTRACK=m
 CONFIG_IP_NF_ARPTABLES=m
 CONFIG_IP_NF_ARPFILTER=m
 CONFIG_IP_NF_ARP_MANGLE=m
@@ -400,10 +433,11 @@
 #
 # 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_DECNET is not set
 CONFIG_LLC=y
 # CONFIG_LLC2 is not set
 # CONFIG_IPX is not set
@@ -419,28 +453,35 @@
 # QoS and/or fair queueing
 #
 # CONFIG_NET_SCHED is not set
+CONFIG_NET_CLS_ROUTE=y
 
 #
 # Network testing
 #
 # CONFIG_NET_PKTGEN is not set
+CONFIG_NETPOLL=y
+CONFIG_NETPOLL_RX=y
+CONFIG_NETPOLL_TRAP=y
+CONFIG_NET_POLL_CONTROLLER=y
+# CONFIG_HAMRADIO is not set
+# CONFIG_IRDA is not set
+# CONFIG_BT is not set
 CONFIG_NETDEVICES=y
+CONFIG_DUMMY=m
+CONFIG_BONDING=m
+# CONFIG_EQUALIZER is not set
+CONFIG_TUN=m
 
 #
 # ARCnet devices
 #
 # CONFIG_ARCNET is not set
-CONFIG_DUMMY=m
-CONFIG_BONDING=m
-# CONFIG_EQUALIZER is not set
-CONFIG_TUN=m
 
 #
 # 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=y
@@ -452,6 +493,7 @@
 #
 # CONFIG_NET_TULIP is not set
 # CONFIG_HP100 is not set
+CONFIG_IBMVETH=m
 CONFIG_NET_PCI=y
 CONFIG_PCNET32=y
 # CONFIG_AMD8111_ETH is not set
@@ -471,6 +513,7 @@
 # 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)
@@ -484,7 +527,6 @@
 # CONFIG_HAMACHI is not set
 # CONFIG_YELLOWFIN is not set
 # CONFIG_R8169 is not set
-# CONFIG_SIS190 is not set
 # CONFIG_SK98LIN is not set
 CONFIG_TIGON3=y
 
@@ -493,59 +535,40 @@
 #
 CONFIG_IXGB=m
 # CONFIG_IXGB_NAPI is not set
-# CONFIG_FDDI is not set
-# CONFIG_HIPPI is not set
-CONFIG_IBMVETH=m
-CONFIG_PPP=m
-# CONFIG_PPP_MULTILINK is not set
-# CONFIG_PPP_FILTER is not set
-CONFIG_PPP_ASYNC=m
-CONFIG_PPP_SYNC_TTY=m
-CONFIG_PPP_DEFLATE=m
-CONFIG_PPP_BSDCOMP=m
-CONFIG_PPPOE=m
-# CONFIG_SLIP is not set
-
-#
-# Wireless LAN (non-hamradio)
-#
-# CONFIG_NET_RADIO is not set
+CONFIG_S2IO=m
+# CONFIG_S2IO_NAPI is not set
 
 #
 # Token Ring devices
 #
 CONFIG_TR=y
 CONFIG_IBMOL=y
-# CONFIG_IBMLS is not set
 # CONFIG_3C359 is not set
 # CONFIG_TMS380TR is not set
-# CONFIG_NET_FC is not set
-# CONFIG_SHAPER is not set
-CONFIG_NETCONSOLE=y
 
 #
-# Wan interfaces
-#
-# CONFIG_WAN is not set
-
-#
-# Amateur Radio support
-#
-# CONFIG_HAMRADIO is not set
-
-#
-# IrDA (infrared) support
+# Wireless LAN (non-hamradio)
 #
-# CONFIG_IRDA is not set
+# CONFIG_NET_RADIO is not set
 
 #
-# Bluetooth support
+# Wan interfaces
 #
-# CONFIG_BT is not set
-CONFIG_NETPOLL=y
-CONFIG_NETPOLL_RX=y
-CONFIG_NETPOLL_TRAP=y
-CONFIG_NET_POLL_CONTROLLER=y
+# CONFIG_WAN is not set
+# CONFIG_FDDI is not set
+# CONFIG_HIPPI is not set
+CONFIG_PPP=m
+# CONFIG_PPP_MULTILINK is not set
+# CONFIG_PPP_FILTER is not set
+CONFIG_PPP_ASYNC=m
+CONFIG_PPP_SYNC_TTY=m
+CONFIG_PPP_DEFLATE=m
+CONFIG_PPP_BSDCOMP=m
+CONFIG_PPPOE=m
+# CONFIG_SLIP is not set
+# CONFIG_NET_FC is not set
+# CONFIG_SHAPER is not set
+CONFIG_NETCONSOLE=y
 
 #
 # ISDN subsystem
@@ -584,6 +607,7 @@
 # CONFIG_SERIO_SERPORT is not set
 # CONFIG_SERIO_CT82C710 is not set
 # CONFIG_SERIO_PCIPS2 is not set
+# CONFIG_SERIO_RAW is not set
 
 #
 # Input Device Drivers
@@ -591,15 +615,17 @@
 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=y
-CONFIG_INPUT_PCSPKR=y
+# CONFIG_INPUT_PCSPKR is not set
 # CONFIG_INPUT_UINPUT is not set
 
 #
@@ -624,16 +650,12 @@
 CONFIG_SERIAL_CORE=y
 CONFIG_SERIAL_CORE_CONSOLE=y
 # CONFIG_SERIAL_PMACZILOG is not set
+CONFIG_SERIAL_ICOM=m
 CONFIG_UNIX98_PTYS=y
 CONFIG_LEGACY_PTYS=y
 CONFIG_LEGACY_PTY_COUNT=256
 CONFIG_HVC_CONSOLE=y
-
-#
-# Mice
-#
-# CONFIG_BUSMOUSE is not set
-# CONFIG_QIC02_TAPE is not set
+CONFIG_HVCS=m
 
 #
 # IPMI
@@ -656,7 +678,7 @@
 # CONFIG_AGP is not set
 # CONFIG_DRM is not set
 CONFIG_RAW_DRIVER=y
-CONFIG_MAX_RAW_DEVS=256
+CONFIG_MAX_RAW_DEVS=1024
 
 #
 # I2C support
@@ -669,11 +691,13 @@
 #
 CONFIG_I2C_ALGOBIT=y
 # CONFIG_I2C_ALGOPCF is not set
+# CONFIG_I2C_ALGOPCA is not set
 
 #
 # I2C Hardware Bus support
 #
 # CONFIG_I2C_ALI1535 is not set
+# CONFIG_I2C_ALI1563 is not set
 # CONFIG_I2C_ALI15X3 is not set
 # CONFIG_I2C_AMD756 is not set
 # CONFIG_I2C_AMD8111 is not set
@@ -691,30 +715,52 @@
 # CONFIG_I2C_VIA is not set
 # CONFIG_I2C_VIAPRO is not set
 # CONFIG_I2C_VOODOO3 is not set
+# CONFIG_I2C_PCA_ISA is not set
 
 #
-# I2C Hardware Sensors Chip support
+# Hardware Sensors Chip support
 #
 # CONFIG_I2C_SENSOR is not set
 # CONFIG_SENSORS_ADM1021 is not set
+# CONFIG_SENSORS_ADM1025 is not set
+# CONFIG_SENSORS_ADM1031 is not set
 # CONFIG_SENSORS_ASB100 is not set
-# CONFIG_SENSORS_EEPROM is not set
+# CONFIG_SENSORS_DS1621 is not set
 # CONFIG_SENSORS_FSCHER is not set
 # CONFIG_SENSORS_GL518SM is not set
 # CONFIG_SENSORS_IT87 is not set
 # CONFIG_SENSORS_LM75 is not set
+# CONFIG_SENSORS_LM77 is not set
 # CONFIG_SENSORS_LM78 is not set
+# CONFIG_SENSORS_LM80 is not set
 # CONFIG_SENSORS_LM83 is not set
 # CONFIG_SENSORS_LM85 is not set
 # CONFIG_SENSORS_LM90 is not set
+# CONFIG_SENSORS_MAX1619 is not set
+# CONFIG_SENSORS_SMSC47M1 is not set
 # CONFIG_SENSORS_VIA686A is not set
 # CONFIG_SENSORS_W83781D is not set
 # CONFIG_SENSORS_W83L785TS is not set
+# CONFIG_SENSORS_W83627HF is not set
+
+#
+# Other I2C Chip support
+#
+# CONFIG_SENSORS_EEPROM is not set
+# CONFIG_SENSORS_PCF8574 is not set
+# CONFIG_SENSORS_PCF8591 is not set
+# CONFIG_SENSORS_RTC8564 is not set
 # CONFIG_I2C_DEBUG_CORE is not set
+# CONFIG_I2C_DEBUG_ALGO is not set
 # CONFIG_I2C_DEBUG_BUS is not set
 # CONFIG_I2C_DEBUG_CHIP is not set
 
 #
+# Dallas's 1-wire bus
+#
+# CONFIG_W1 is not set
+
+#
 # Misc devices
 #
 
@@ -732,12 +778,14 @@
 # Graphics support
 #
 CONFIG_FB=y
+CONFIG_FB_MODE_HELPERS=y
+# CONFIG_FB_CIRRUS is not set
 # CONFIG_FB_PM2 is not set
 # CONFIG_FB_CYBER2000 is not set
 CONFIG_FB_OF=y
 # CONFIG_FB_CT65550 is not set
+# CONFIG_FB_ASILIANT is not set
 # CONFIG_FB_IMSTT is not set
-# CONFIG_FB_S3TRIO is not set
 # CONFIG_FB_VGA16 is not set
 # CONFIG_FB_RIVA is not set
 CONFIG_FB_MATROX=y
@@ -765,10 +813,8 @@
 # Console display driver support
 #
 # CONFIG_VGA_CONSOLE is not set
-# CONFIG_MDA_CONSOLE is not set
 CONFIG_DUMMY_CONSOLE=y
 CONFIG_FRAMEBUFFER_CONSOLE=y
-CONFIG_PCI_CONSOLE=y
 # CONFIG_FONTS is not set
 CONFIG_FONT_8x8=y
 CONFIG_FONT_8x16=y
@@ -798,11 +844,14 @@
 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
 #
 CONFIG_USB_EHCI_HCD=y
+# CONFIG_USB_EHCI_SPLIT_ISO is not set
+# CONFIG_USB_EHCI_ROOT_HUB_TT is not set
 CONFIG_USB_OHCI_HCD=y
 # CONFIG_USB_UHCI_HCD is not set
 
@@ -814,6 +863,7 @@
 # CONFIG_USB_PRINTER is not set
 CONFIG_USB_STORAGE=y
 # CONFIG_USB_STORAGE_DEBUG is not set
+# CONFIG_USB_STORAGE_RW_DETECT is not set
 # CONFIG_USB_STORAGE_DATAFAB is not set
 # CONFIG_USB_STORAGE_FREECOM is not set
 # CONFIG_USB_STORAGE_ISD200 is not set
@@ -834,7 +884,10 @@
 # CONFIG_USB_WACOM is not set
 # CONFIG_USB_KBTAB is not set
 # CONFIG_USB_POWERMATE is not set
+# CONFIG_USB_MTOUCH is not set
+# CONFIG_USB_EGALAX is not set
 # CONFIG_USB_XPAD is not set
+# CONFIG_USB_ATI_REMOTE is not set
 
 #
 # USB Imaging devices
@@ -881,6 +934,8 @@
 # CONFIG_USB_LEGOTOWER is not set
 # CONFIG_USB_LCD is not set
 # CONFIG_USB_LED is not set
+# CONFIG_USB_CYTHERM is not set
+# CONFIG_USB_PHIDGETSERVO is not set
 # CONFIG_USB_TEST is not set
 
 #
@@ -905,7 +960,10 @@
 CONFIG_REISERFS_FS=y
 # CONFIG_REISERFS_CHECK is not set
 # CONFIG_REISERFS_PROC_INFO is not set
-CONFIG_JFS_FS=y
+CONFIG_REISERFS_FS_XATTR=y
+CONFIG_REISERFS_FS_POSIX_ACL=y
+# CONFIG_REISERFS_FS_SECURITY is not set
+CONFIG_JFS_FS=m
 CONFIG_JFS_POSIX_ACL=y
 # CONFIG_JFS_DEBUG is not set
 # CONFIG_JFS_STATISTICS is not set
@@ -928,6 +986,7 @@
 # CONFIG_JOLIET is not set
 # CONFIG_ZISOFS is not set
 CONFIG_UDF_FS=m
+CONFIG_UDF_NLS=y
 
 #
 # DOS/FAT/NT Filesystems
@@ -935,6 +994,8 @@
 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
 
 #
@@ -942,6 +1003,7 @@
 #
 CONFIG_PROC_FS=y
 CONFIG_PROC_KCORE=y
+CONFIG_SYSFS=y
 # CONFIG_DEVFS_FS is not set
 CONFIG_DEVPTS_FS_XATTR=y
 # CONFIG_DEVPTS_FS_SECURITY is not set
@@ -974,18 +1036,22 @@
 CONFIG_NFS_V3=y
 CONFIG_NFS_V4=y
 # CONFIG_NFS_DIRECTIO is not set
-CONFIG_NFSD=y
+CONFIG_NFSD=m
 CONFIG_NFSD_V3=y
 CONFIG_NFSD_V4=y
 CONFIG_NFSD_TCP=y
 CONFIG_LOCKD=y
 CONFIG_LOCKD_V4=y
-CONFIG_EXPORTFS=y
+CONFIG_EXPORTFS=m
 CONFIG_SUNRPC=y
-CONFIG_SUNRPC_GSS=m
-CONFIG_RPCSEC_GSS_KRB5=m
+CONFIG_SUNRPC_GSS=y
+CONFIG_RPCSEC_GSS_KRB5=y
+CONFIG_RPCSEC_GSS_SPKM3=m
 # CONFIG_SMB_FS is not set
 CONFIG_CIFS=m
+# CONFIG_CIFS_STATS is not set
+CONFIG_CIFS_XATTR=y
+CONFIG_CIFS_POSIX=y
 # CONFIG_NCP_FS is not set
 # CONFIG_CODA_FS is not set
 # CONFIG_AFS_FS is not set
@@ -1001,7 +1067,7 @@
 #
 CONFIG_NLS=y
 CONFIG_NLS_DEFAULT="iso8859-1"
-# CONFIG_NLS_CODEPAGE_437 is not set
+CONFIG_NLS_CODEPAGE_437=y
 # CONFIG_NLS_CODEPAGE_737 is not set
 # CONFIG_NLS_CODEPAGE_775 is not set
 # CONFIG_NLS_CODEPAGE_850 is not set
@@ -1024,7 +1090,8 @@
 # CONFIG_NLS_ISO8859_8 is not set
 # CONFIG_NLS_CODEPAGE_1250 is not set
 # CONFIG_NLS_CODEPAGE_1251 is not set
-# CONFIG_NLS_ISO8859_1 is not set
+CONFIG_NLS_ASCII=y
+CONFIG_NLS_ISO8859_1=y
 # CONFIG_NLS_ISO8859_2 is not set
 # CONFIG_NLS_ISO8859_3 is not set
 # CONFIG_NLS_ISO8859_4 is not set
@@ -1049,15 +1116,18 @@
 # Kernel hacking
 #
 CONFIG_DEBUG_KERNEL=y
+CONFIG_MAGIC_SYSRQ=y
+# CONFIG_DEBUG_SLAB is not set
+# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
+# CONFIG_DEBUG_INFO is not set
 CONFIG_DEBUG_STACKOVERFLOW=y
 CONFIG_DEBUG_STACK_USAGE=y
-# CONFIG_DEBUG_SLAB is not set
-CONFIG_MAGIC_SYSRQ=y
 CONFIG_DEBUGGER=y
 CONFIG_XMON=y
 CONFIG_XMON_DEFAULT=y
 # CONFIG_PPCDBG is not set
-# CONFIG_DEBUG_INFO is not set
+CONFIG_IRQSTACKS=y
+# CONFIG_SCHEDSTATS is not set
 
 #
 # Security options
@@ -1071,24 +1141,31 @@
 CONFIG_CRYPTO_HMAC=y
 CONFIG_CRYPTO_NULL=m
 CONFIG_CRYPTO_MD4=m
-CONFIG_CRYPTO_MD5=m
+CONFIG_CRYPTO_MD5=y
 CONFIG_CRYPTO_SHA1=m
 CONFIG_CRYPTO_SHA256=m
 CONFIG_CRYPTO_SHA512=m
-CONFIG_CRYPTO_DES=m
+CONFIG_CRYPTO_WHIRLPOOL=m
+CONFIG_CRYPTO_DES=y
 CONFIG_CRYPTO_BLOWFISH=m
 CONFIG_CRYPTO_TWOFISH=m
 CONFIG_CRYPTO_SERPENT=m
 CONFIG_CRYPTO_AES=m
 CONFIG_CRYPTO_CAST5=m
 CONFIG_CRYPTO_CAST6=m
+CONFIG_CRYPTO_TEA=m
 CONFIG_CRYPTO_ARC4=m
+CONFIG_CRYPTO_KHAZAD=m
 CONFIG_CRYPTO_DEFLATE=m
+CONFIG_CRYPTO_MICHAEL_MIC=m
+CONFIG_CRYPTO_CRC32C=m
 CONFIG_CRYPTO_TEST=m
 
 #
 # Library routines
 #
+CONFIG_CRC_CCITT=m
 CONFIG_CRC32=y
+CONFIG_LIBCRC32C=m
 CONFIG_ZLIB_INFLATE=y
 CONFIG_ZLIB_DEFLATE=m
diff -Nru a/arch/ppc64/kernel/ItLpQueue.c b/arch/ppc64/kernel/ItLpQueue.c
--- a/arch/ppc64/kernel/ItLpQueue.c	2004-10-18 14:55:55 -07:00
+++ b/arch/ppc64/kernel/ItLpQueue.c	2004-10-18 14:55:55 -07:00
@@ -25,7 +25,7 @@
 
 	__asm__ __volatile__("\n\
 1:	lwarx	%0,0,%2		\n\
-	cmpi	0,%0,0		\n\
+	cmpwi	0,%0,0		\n\
 	li	%0,0		\n\
 	bne-	2f		\n\
 	addi	%0,%0,1		\n\
diff -Nru a/arch/ppc64/kernel/Makefile b/arch/ppc64/kernel/Makefile
--- a/arch/ppc64/kernel/Makefile	2004-10-18 14:57:04 -07:00
+++ b/arch/ppc64/kernel/Makefile	2004-10-18 14:57:04 -07:00
@@ -3,11 +3,11 @@
 #
 
 EXTRA_CFLAGS	+= -mno-minimal-toc
-extra-y		:= head.o vmlinux.lds.s
+extra-y		:= head.o vmlinux.lds
 
 obj-y               :=	setup.o entry.o traps.o irq.o idle.o dma.o \
 			time.o process.o signal.o syscalls.o misc.o ptrace.o \
-			align.o semaphore.o bitops.o stab.o pacaData.o \
+			align.o semaphore.o bitops.o pacaData.o \
 			udbg.o binfmt_elf32.o sys_ppc32.o ioctl32.o \
 			ptrace32.o signal32.o rtc.o init_task.o \
 			lmb.o cputable.o cpu_setup_power4.o idle_power4.o \
@@ -17,9 +17,9 @@
 
 pci-obj-$(CONFIG_PPC_ISERIES)	+= iSeries_pci.o iSeries_pci_reset.o \
 				     iSeries_IoMmTable.o
-pci-obj-$(CONFIG_PPC_PSERIES)	+= pci_dn.o pci_dma_direct.o
+pci-obj-$(CONFIG_PPC_MULTIPLATFORM)	+= pci_dn.o pci_dma_direct.o
 
-obj-$(CONFIG_PCI)	+= pci.o pci_iommu.o $(pci-obj-y)
+obj-$(CONFIG_PCI)	+= pci.o pci_iommu.o iomap.o $(pci-obj-y)
 
 obj-$(CONFIG_PPC_ISERIES) += iSeries_irq.o \
 			     iSeries_VpdInfo.o XmPciLpEvent.o \
@@ -28,10 +28,11 @@
 			     mf.o HvLpEvent.o iSeries_proc.o iSeries_htab.o \
 			     iSeries_iommu.o
 
+obj-$(CONFIG_PPC_MULTIPLATFORM) += nvram.o open_pic.o i8259.o prom_init.o prom.o
+
 obj-$(CONFIG_PPC_PSERIES) += pSeries_pci.o pSeries_lpar.o pSeries_hvCall.o \
-			     eeh.o nvram.o pSeries_nvram.o rtasd.o ras.o \
-			     open_pic.o xics.o pSeries_htab.o rtas.o \
-			     chrp_setup.o i8259.o prom.o pSeries_iommu.o
+			     eeh.o pSeries_nvram.o rtasd.o ras.o \
+			     xics.o rtas.o pSeries_setup.o pSeries_iommu.o
 
 obj-$(CONFIG_PROC_FS)		+= proc_ppc64.o
 obj-$(CONFIG_RTAS_FLASH)	+= rtas_flash.o
@@ -48,7 +49,7 @@
 obj-$(CONFIG_PPC_PMAC)		+= pmac_setup.o pmac_feature.o pmac_pci.o \
 				   pmac_time.o pmac_nvram.o pmac_low_i2c.o \
 				   open_pic_u3.o
-obj-$(CONFIG_PMAC_DART)		+= pmac_iommu.o
+obj-$(CONFIG_U3_DART)		+= u3_iommu.o
 
 ifdef CONFIG_SMP
 obj-$(CONFIG_PPC_PMAC)		+= pmac_smp.o smp-tbsync.o
diff -Nru a/arch/ppc64/kernel/asm-offsets.c b/arch/ppc64/kernel/asm-offsets.c
--- a/arch/ppc64/kernel/asm-offsets.c	2004-10-18 14:56:33 -07:00
+++ b/arch/ppc64/kernel/asm-offsets.c	2004-10-18 14:56:33 -07:00
@@ -22,18 +22,17 @@
 #include <linux/types.h>
 #include <linux/mman.h>
 #include <linux/mm.h>
+#include <linux/hardirq.h>
 #include <asm/io.h>
 #include <asm/page.h>
 #include <asm/pgtable.h>
 #include <asm/processor.h>
-#include <asm/hardirq.h>
 
 #include <asm/naca.h>
 #include <asm/paca.h>
 #include <asm/iSeries/ItLpPaca.h>
 #include <asm/iSeries/ItLpQueue.h>
 #include <asm/iSeries/HvLpEvent.h>
-#include <asm/prom.h>
 #include <asm/rtas.h>
 #include <asm/cputable.h>
 
@@ -58,6 +57,7 @@
 	DEFINE(THREAD_FPR0, offsetof(struct thread_struct, fpr[0]));
 	DEFINE(THREAD_FPSCR, offsetof(struct thread_struct, fpscr));
 	DEFINE(KSP, offsetof(struct thread_struct, ksp));
+	DEFINE(KSP_VSID, offsetof(struct thread_struct, ksp_vsid));
 
 #ifdef CONFIG_ALTIVEC
 	DEFINE(THREAD_VR0, offsetof(struct thread_struct, vr[0]));
@@ -93,16 +93,10 @@
 	DEFINE(PACASLBCACHE, offsetof(struct paca_struct, slb_cache));
 	DEFINE(PACASLBCACHEPTR, offsetof(struct paca_struct, slb_cache_ptr));
 	DEFINE(PACACONTEXTID, offsetof(struct paca_struct, context.id));
-	DEFINE(PACASLBR3, offsetof(struct paca_struct, slb_r3));
 #ifdef CONFIG_HUGETLB_PAGE
 	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));
@@ -113,15 +107,10 @@
         DEFINE(LPPACASRR1, offsetof(struct ItLpPaca, xSavedSrr1));
 	DEFINE(LPPACAANYINT, offsetof(struct ItLpPaca, xIntDword.xAnyInt));
 	DEFINE(LPPACADECRINT, offsetof(struct ItLpPaca, xIntDword.xFields.xDecrInt));
-        DEFINE(LPQCUREVENTPTR, offsetof(struct ItLpQueue, xSlicCurEventPtr));
-        DEFINE(LPQOVERFLOW, offsetof(struct ItLpQueue, xPlicOverflowIntPending));
-        DEFINE(LPEVENTFLAGS, offsetof(struct HvLpEvent, xFlags));
-	DEFINE(PROMENTRY, offsetof(struct prom_t, entry));
 
 	/* RTAS */
 	DEFINE(RTASBASE, offsetof(struct rtas_t, base));
 	DEFINE(RTASENTRY, offsetof(struct rtas_t, entry));
-	DEFINE(RTASSIZE, offsetof(struct rtas_t, size));
 
 	/* Interrupt register frame */
 	DEFINE(STACK_FRAME_OVERHEAD, STACK_FRAME_OVERHEAD);
@@ -148,10 +137,6 @@
 	DEFINE(GPR11, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, gpr[11]));
 	DEFINE(GPR12, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, gpr[12]));
 	DEFINE(GPR13, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, gpr[13]));
-	DEFINE(GPR20, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, gpr[20]));
-	DEFINE(GPR21, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, gpr[21]));
-	DEFINE(GPR22, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, gpr[22]));
-	DEFINE(GPR23, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, gpr[23]));
 	/*
 	 * Note: these symbols include _ because they overlap with special
 	 * register names
diff -Nru a/arch/ppc64/kernel/btext.c b/arch/ppc64/kernel/btext.c
--- a/arch/ppc64/kernel/btext.c	2004-10-18 14:56:49 -07:00
+++ b/arch/ppc64/kernel/btext.c	2004-10-18 14:56:49 -07:00
@@ -10,7 +10,7 @@
 #include <linux/version.h>
 
 #include <asm/sections.h>
-#include <asm/bootx.h>
+#include <asm/prom.h>
 #include <asm/btext.h>
 #include <asm/prom.h>
 #include <asm/page.h>
@@ -36,6 +36,11 @@
 static int g_max_loc_X;
 static int g_max_loc_Y;
 
+static int dispDeviceRowBytes;
+static int dispDeviceDepth;
+static int dispDeviceRect[4];
+static unsigned char *dispDeviceBase, *logicalDisplayBase;
+
 unsigned long disp_BAT[2] __initdata = {0, 0};
 
 #define cmapsz	(16*256)
@@ -45,30 +50,6 @@
 int boot_text_mapped;
 int force_printk_to_btext = 0;
 
-boot_infos_t disp_bi;
-
-/* This function will enable the early boot text when doing OF booting. This
- * way, xmon output should work too
- */
-void __init btext_setup_display(int width, int height, int depth, int pitch,
-		    unsigned long address)
-{
-	unsigned long offset = reloc_offset();
-	boot_infos_t* bi = PTRRELOC(&disp_bi);
-
-	RELOC(g_loc_X) = 0;
-	RELOC(g_loc_Y) = 0;
-	RELOC(g_max_loc_X) = width / 8;
-	RELOC(g_max_loc_Y) = height / 16;
-	bi->logicalDisplayBase = (unsigned char *)address;
-	bi->dispDeviceBase = (unsigned char *)address;
-	bi->dispDeviceRowBytes = pitch;
-	bi->dispDeviceDepth = depth;
-	bi->dispDeviceRect[0] = bi->dispDeviceRect[1] = 0;
-	bi->dispDeviceRect[2] = width;
-	bi->dispDeviceRect[3] = height;
-	RELOC(boot_text_mapped) = 1;
-}
 
 /* Here's a small text engine to use during early boot
  * or for debugging purposes
@@ -84,34 +65,84 @@
 void map_boot_text(void)
 {
 	unsigned long base, offset, size;
-	boot_infos_t *bi = &disp_bi;
 	unsigned char *vbase;
 
 	/* By default, we are no longer mapped */
 	boot_text_mapped = 0;
-	if (bi->dispDeviceBase == 0)
+	if (dispDeviceBase == 0)
 		return;
-	base = ((unsigned long) bi->dispDeviceBase) & 0xFFFFF000UL;
-	offset = ((unsigned long) bi->dispDeviceBase) - base;
-	size = bi->dispDeviceRowBytes * bi->dispDeviceRect[3] + offset
-		+ bi->dispDeviceRect[0];
+	base = ((unsigned long) dispDeviceBase) & 0xFFFFF000UL;
+	offset = ((unsigned long) dispDeviceBase) - base;
+	size = dispDeviceRowBytes * dispDeviceRect[3] + offset
+		+ dispDeviceRect[0];
 	vbase = __ioremap(base, size, _PAGE_NO_CACHE);
 	if (vbase == 0)
 		return;
-	bi->logicalDisplayBase = vbase + offset;
+	logicalDisplayBase = vbase + offset;
 	boot_text_mapped = 1;
 }
 
+int btext_initialize(struct device_node *np)
+{
+	unsigned int width, height, depth, pitch;
+	unsigned long address = 0;
+	u32 *prop;
+
+	prop = (u32 *)get_property(np, "width", NULL);
+	if (prop == NULL)
+		return -EINVAL;
+	width = *prop;
+	prop = (u32 *)get_property(np, "height", NULL);
+	if (prop == NULL)
+		return -EINVAL;
+	height = *prop;
+	prop = (u32 *)get_property(np, "depth", NULL);
+	if (prop == NULL)
+		return -EINVAL;
+	depth = *prop;
+	pitch = width * ((depth + 7) / 8);
+	prop = (u32 *)get_property(np, "linebytes", NULL);
+	if (prop)
+		pitch = *prop;
+	if (pitch == 1)
+		pitch = 0x1000;
+	prop = (u32 *)get_property(np, "address", NULL);
+	if (prop)
+		address = *prop;
+
+	/* FIXME: Add support for PCI reg properties */
+
+	if (address == 0)
+		return -EINVAL;
+
+	g_loc_X = 0;
+	g_loc_Y = 0;
+	g_max_loc_X = width / 8;
+	g_max_loc_Y = height / 16;
+	logicalDisplayBase = (unsigned char *)address;
+	dispDeviceBase = (unsigned char *)address;
+	dispDeviceRowBytes = pitch;
+	dispDeviceDepth = depth;
+	dispDeviceRect[0] = dispDeviceRect[1] = 0;
+	dispDeviceRect[2] = width;
+	dispDeviceRect[3] = height;
+
+	map_boot_text();
+
+	return 0;
+}
+
+
 /* Calc the base address of a given point (x,y) */
-static unsigned char * calc_base(boot_infos_t *bi, int x, int y)
+static unsigned char * calc_base(int x, int y)
 {
 	unsigned char *base;
 
-	base = bi->logicalDisplayBase;
+	base = logicalDisplayBase;
 	if (base == 0)
-		base = bi->dispDeviceBase;
-	base += (x + bi->dispDeviceRect[0]) * (bi->dispDeviceDepth >> 3);
-	base += (y + bi->dispDeviceRect[1]) * bi->dispDeviceRowBytes;
+		base = dispDeviceBase;
+	base += (x + dispDeviceRect[0]) * (dispDeviceDepth >> 3);
+	base += (y + dispDeviceRect[1]) * dispDeviceRowBytes;
 	return base;
 }
 
@@ -119,24 +150,22 @@
 void btext_update_display(unsigned long phys, int width, int height,
 			  int depth, int pitch)
 {
-	boot_infos_t *bi = &disp_bi;
-
-	if (bi->dispDeviceBase == 0)
+	if (dispDeviceBase == 0)
 		return;
 
 	/* check it's the same frame buffer (within 256MB) */
-	if ((phys ^ (unsigned long)bi->dispDeviceBase) & 0xf0000000)
+	if ((phys ^ (unsigned long)dispDeviceBase) & 0xf0000000)
 		return;
 
-	bi->dispDeviceBase = (__u8 *) phys;
-	bi->dispDeviceRect[0] = 0;
-	bi->dispDeviceRect[1] = 0;
-	bi->dispDeviceRect[2] = width;
-	bi->dispDeviceRect[3] = height;
-	bi->dispDeviceDepth = depth;
-	bi->dispDeviceRowBytes = pitch;
+	dispDeviceBase = (__u8 *) phys;
+	dispDeviceRect[0] = 0;
+	dispDeviceRect[1] = 0;
+	dispDeviceRect[2] = width;
+	dispDeviceRect[3] = height;
+	dispDeviceDepth = depth;
+	dispDeviceRowBytes = pitch;
 	if (boot_text_mapped) {
-		iounmap(bi->logicalDisplayBase);
+		iounmap(logicalDisplayBase);
 		boot_text_mapped = 0;
 	}
 	map_boot_text();
@@ -148,108 +177,101 @@
 
 void btext_clearscreen(void)
 {
-	unsigned long offset = reloc_offset();
-	boot_infos_t* bi	= PTRRELOC(&disp_bi);
-	unsigned long *base	= (unsigned long *)calc_base(bi, 0, 0);
-	unsigned long width 	= ((bi->dispDeviceRect[2] - bi->dispDeviceRect[0]) *
-					(bi->dispDeviceDepth >> 3)) >> 3;
+	unsigned long *base	= (unsigned long *)calc_base(0, 0);
+	unsigned long width 	= ((dispDeviceRect[2] - dispDeviceRect[0]) *
+					(dispDeviceDepth >> 3)) >> 3;
 	int i,j;
 
-	for (i=0; i<(bi->dispDeviceRect[3] - bi->dispDeviceRect[1]); i++)
+	for (i=0; i<(dispDeviceRect[3] - dispDeviceRect[1]); i++)
 	{
 		unsigned long *ptr = base;
 		for(j=width; j; --j)
 			*(ptr++) = 0;
-		base += (bi->dispDeviceRowBytes >> 3);
+		base += (dispDeviceRowBytes >> 3);
 	}
 }
 
 #ifndef NO_SCROLL
 static void scrollscreen(void)
 {
-	unsigned long offset   	= reloc_offset();
-	boot_infos_t* bi       	= PTRRELOC(&disp_bi);
-	unsigned long *src     	= (unsigned long *)calc_base(bi,0,16);
-	unsigned long *dst     	= (unsigned long *)calc_base(bi,0,0);
-	unsigned long width    	= ((bi->dispDeviceRect[2] - bi->dispDeviceRect[0]) *
-				   (bi->dispDeviceDepth >> 3)) >> 3;
+	unsigned long *src     	= (unsigned long *)calc_base(0,16);
+	unsigned long *dst     	= (unsigned long *)calc_base(0,0);
+	unsigned long width    	= ((dispDeviceRect[2] - dispDeviceRect[0]) *
+				   (dispDeviceDepth >> 3)) >> 3;
 	int i,j;
 
-	for (i=0; i<(bi->dispDeviceRect[3] - bi->dispDeviceRect[1] - 16); i++)
+	for (i=0; i<(dispDeviceRect[3] - dispDeviceRect[1] - 16); i++)
 	{
 		unsigned long *src_ptr = src;
 		unsigned long *dst_ptr = dst;
 		for(j=width; j; --j)
 			*(dst_ptr++) = *(src_ptr++);
-		src += (bi->dispDeviceRowBytes >> 3);
-		dst += (bi->dispDeviceRowBytes >> 3);
+		src += (dispDeviceRowBytes >> 3);
+		dst += (dispDeviceRowBytes >> 3);
 	}
 	for (i=0; i<16; i++)
 	{
 		unsigned long *dst_ptr = dst;
 		for(j=width; j; --j)
 			*(dst_ptr++) = 0;
-		dst += (bi->dispDeviceRowBytes >> 3);
+		dst += (dispDeviceRowBytes >> 3);
 	}
 }
 #endif /* ndef NO_SCROLL */
 
 void btext_drawchar(char c)
 {
-	unsigned long offset = reloc_offset();
 	int cline = 0;
 #ifdef NO_SCROLL
 	int x;
 #endif
-	if (!RELOC(boot_text_mapped))
+	if (!boot_text_mapped)
 		return;
 
 	switch (c) {
 	case '\b':
-		if (RELOC(g_loc_X) > 0)
-			--RELOC(g_loc_X);
+		if (g_loc_X > 0)
+			--g_loc_X;
 		break;
 	case '\t':
-		RELOC(g_loc_X) = (RELOC(g_loc_X) & -8) + 8;
+		g_loc_X = (g_loc_X & -8) + 8;
 		break;
 	case '\r':
-		RELOC(g_loc_X) = 0;
+		g_loc_X = 0;
 		break;
 	case '\n':
-		RELOC(g_loc_X) = 0;
-		RELOC(g_loc_Y)++;
+		g_loc_X = 0;
+		g_loc_Y++;
 		cline = 1;
 		break;
 	default:
-		draw_byte(c, RELOC(g_loc_X)++, RELOC(g_loc_Y));
+		draw_byte(c, g_loc_X++, g_loc_Y);
 	}
-	if (RELOC(g_loc_X) >= RELOC(g_max_loc_X)) {
-		RELOC(g_loc_X) = 0;
-		RELOC(g_loc_Y)++;
+	if (g_loc_X >= g_max_loc_X) {
+		g_loc_X = 0;
+		g_loc_Y++;
 		cline = 1;
 	}
 #ifndef NO_SCROLL
-	while (RELOC(g_loc_Y) >= RELOC(g_max_loc_Y)) {
+	while (g_loc_Y >= g_max_loc_Y) {
 		scrollscreen();
-		RELOC(g_loc_Y)--;
+		g_loc_Y--;
 	}
 #else
 	/* wrap around from bottom to top of screen so we don't
 	   waste time scrolling each line.  -- paulus. */
-	if (RELOC(g_loc_Y) >= RELOC(g_max_loc_Y))
-		RELOC(g_loc_Y) = 0;
+	if (g_loc_Y >= g_max_loc_Y)
+		g_loc_Y = 0;
 	if (cline) {
-		for (x = 0; x < RELOC(g_max_loc_X); ++x)
-			draw_byte(' ', x, RELOC(g_loc_Y));
+		for (x = 0; x < g_max_loc_X; ++x)
+			draw_byte(' ', x, g_loc_Y);
 	}
 #endif
 }
 
 void btext_drawstring(const char *c)
 {
-	unsigned long offset = reloc_offset();
-
-	if (!RELOC(boot_text_mapped))
+	if (!boot_text_mapped)
 		return;
 	while (*c)
 		btext_drawchar(*c++);
@@ -257,10 +279,9 @@
 
 void btext_drawhex(unsigned long v)
 {
-	unsigned long offset = reloc_offset();
-	char *hex_table = RELOC("0123456789abcdef");
+	char *hex_table = "0123456789abcdef";
 
-	if (!RELOC(boot_text_mapped))
+	if (!boot_text_mapped)
 		return;
 	btext_drawchar(hex_table[(v >> 60) & 0x0000000FUL]);
 	btext_drawchar(hex_table[(v >> 56) & 0x0000000FUL]);
@@ -283,14 +304,11 @@
 
 static void draw_byte(unsigned char c, long locX, long locY)
 {
-	unsigned long offset	= reloc_offset();
-	boot_infos_t* bi       	= PTRRELOC(&disp_bi);
-	unsigned char *base	= calc_base(bi, locX << 3, locY << 4);
-	unsigned char *font	= PTRRELOC(&vga_font[((unsigned int)c) * 16]);
-	int rb			= bi->dispDeviceRowBytes;
+	unsigned char *base	= calc_base(locX << 3, locY << 4);
+	unsigned char *font	= &vga_font[((unsigned int)c) * 16];
+	int rb			= dispDeviceRowBytes;
 
-#if 0
-	switch(bi->dispDeviceDepth) {
+	switch(dispDeviceDepth) {
 	case 24:
 	case 32:
 		draw_byte_32(font, (unsigned int *)base, rb);
@@ -303,17 +321,6 @@
 		draw_byte_8(font, (unsigned int *)base, rb);
 		break;
 	}
-#else
-	if(bi->dispDeviceDepth == 24 ||
-	   bi->dispDeviceDepth == 32) {
-		draw_byte_32(font, (unsigned int *)base, rb);
-	} else if(bi->dispDeviceDepth == 15 ||
-	   bi->dispDeviceDepth == 16) {
-		draw_byte_16(font, (unsigned int *)base, rb);
-	} else if(bi->dispDeviceDepth == 8) {
-		draw_byte_8(font, (unsigned int *)base, rb);
-	} 
-#endif
 }
 
 static unsigned int expand_bits_8[16] = {
@@ -369,8 +376,7 @@
 	int l, bits;
 	int fg = 0xFFFFFFFFUL;
 	int bg = 0x00000000UL;
-	unsigned long offset = reloc_offset();
-	unsigned int *eb = PTRRELOC((int *)expand_bits_16);
+	unsigned int *eb = (int *)expand_bits_16;
 
 	for (l = 0; l < 16; ++l)
 	{
@@ -388,8 +394,7 @@
 	int l, bits;
 	int fg = 0x0F0F0F0FUL;
 	int bg = 0x00000000UL;
-	unsigned long offset = reloc_offset();
-	unsigned int *eb = PTRRELOC((int *)expand_bits_8);
+	unsigned int *eb = (int *)expand_bits_8;
 
 	for (l = 0; l < 16; ++l)
 	{
diff -Nru a/arch/ppc64/kernel/chrp_setup.c b/arch/ppc64/kernel/chrp_setup.c
--- a/arch/ppc64/kernel/chrp_setup.c	2004-10-18 14:55:55 -07:00
+++ /dev/null	Wed Dec 31 16:00:00 196900
@@ -1,464 +0,0 @@
-/*
- *  linux/arch/ppc/kernel/setup.c
- *
- *  Copyright (C) 1995  Linus Torvalds
- *  Adapted from 'alpha' version by Gary Thomas
- *  Modified by Cort Dougan (cort@cs.nmt.edu)
- *  Modified by PPC64 Team, IBM Corp
- *
- * 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.
- */
-
-/*
- * 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/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/ioport.h>
-#include <linux/console.h>
-#include <linux/pci.h>
-#include <linux/version.h>
-#include <linux/adb.h>
-#include <linux/module.h>
-#include <linux/delay.h>
-
-#include <linux/irq.h>
-#include <linux/seq_file.h>
-#include <linux/root_dev.h>
-
-#include <asm/mmu.h>
-#include <asm/processor.h>
-#include <asm/io.h>
-#include <asm/pgtable.h>
-#include <asm/prom.h>
-#include <asm/rtas.h>
-#include <asm/pci-bridge.h>
-#include <asm/iommu.h>
-#include <asm/dma.h>
-#include <asm/machdep.h>
-#include <asm/irq.h>
-#include <asm/naca.h>
-#include <asm/time.h>
-#include <asm/nvram.h>
-
-#include "i8259.h"
-#include "open_pic.h"
-#include <asm/xics.h>
-#include <asm/ppcdebug.h>
-#include <asm/cputable.h>
-
-void chrp_progress(char *, unsigned short);
-
-extern void pSeries_init_openpic(void);
-
-extern void find_and_init_phbs(void);
-extern void pSeries_final_fixup(void);
-
-extern void pSeries_get_boot_time(struct rtc_time *rtc_time);
-extern void pSeries_get_rtc_time(struct rtc_time *rtc_time);
-extern int  pSeries_set_rtc_time(struct rtc_time *rtc_time);
-void pSeries_calibrate_decr(void);
-void fwnmi_init(void);
-extern void SystemReset_FWNMI(void), MachineCheck_FWNMI(void);	/* from head.S */
-int fwnmi_active;  /* TRUE if an FWNMI handler is present */
-
-dev_t boot_dev;
-unsigned long  virtPython0Facilities = 0;  // python0 facility area (memory mapped io) (64-bit format) VIRTUAL address.
-
-extern unsigned long loops_per_jiffy;
-
-extern unsigned long ppc_proc_freq;
-extern unsigned long ppc_tb_freq;
-
-void chrp_get_cpuinfo(struct seq_file *m)
-{
-	struct device_node *root;
-	const char *model = "";
-
-	root = of_find_node_by_path("/");
-	if (root)
-		model = get_property(root, "model", NULL);
-	seq_printf(m, "machine\t\t: CHRP %s\n", model);
-	of_node_put(root);
-}
-
-#define I8042_DATA_REG 0x60
-
-void __init chrp_request_regions(void)
-{
-	struct device_node *i8042;
-
-	request_region(0x20,0x20,"pic1");
-	request_region(0xa0,0x20,"pic2");
-	request_region(0x00,0x20,"dma1");
-	request_region(0x40,0x20,"timer");
-	request_region(0x80,0x10,"dma page reg");
-	request_region(0xc0,0x20,"dma2");
-
-	/*
-	 * Some machines have an unterminated i8042 so check the device
-	 * tree and reserve the region if it does not appear. Later on
-	 * the i8042 code will try and reserve this region and fail.
-	 */
-	if (!(i8042 = of_find_node_by_type(NULL, "8042")))
-		request_region(I8042_DATA_REG, 16, "reserved (no i8042)");
-	of_node_put(i8042);
-}
-
-void __init
-chrp_setup_arch(void)
-{
-	struct device_node *root;
-	unsigned int *opprop;
-	
-	/* openpic global configuration register (64-bit format). */
-	/* openpic Interrupt Source Unit pointer (64-bit format). */
-	/* python0 facility area (mmio) (64-bit format) REAL address. */
-
-	/* init to some ~sane value until calibrate_delay() runs */
-	loops_per_jiffy = 50000000;
-
-	if (ROOT_DEV == 0) {
-		printk("No ramdisk, default root is /dev/sda2\n");
-		ROOT_DEV = Root_SDA2;
-	}
-
-	printk("Boot arguments: %s\n", cmd_line);
-
-	fwnmi_init();
-
-#ifndef CONFIG_PPC_ISERIES
-	/* Find and initialize PCI host bridges */
-	/* iSeries needs to be done much later. */
-	eeh_init();
-	find_and_init_phbs();
-#endif
-
-	/* Find the Open PIC if present */
-	root = of_find_node_by_path("/");
-	opprop = (unsigned int *) get_property(root,
-				"platform-open-pic", NULL);
-	if (opprop != 0) {
-		int n = prom_n_addr_cells(root);
-		unsigned long openpic;
-
-		for (openpic = 0; n > 0; --n)
-			openpic = (openpic << 32) + *opprop++;
-		printk(KERN_DEBUG "OpenPIC addr: %lx\n", openpic);
-		OpenPIC_Addr = __ioremap(openpic, 0x40000, _PAGE_NO_CACHE);
-	}
-	of_node_put(root);
-
-#ifdef CONFIG_DUMMY_CONSOLE
-	conswitchp = &dummy_con;
-#endif
-
-#ifdef CONFIG_PPC_PSERIES
-	pSeries_nvram_init();
-#endif
-}
-
-void __init
-chrp_init2(void)
-{
-	/* Manually leave the kernel version on the panel. */
-	ppc_md.progress("Linux ppc64\n", 0);
-	ppc_md.progress(UTS_RELEASE, 0);
-}
-
-/* Initialize firmware assisted non-maskable interrupts if
- * the firmware supports this feature.
- *
- */
-void __init fwnmi_init(void)
-{
-	int ret;
-	int ibm_nmi_register = rtas_token("ibm,nmi-register");
-	if (ibm_nmi_register == RTAS_UNKNOWN_SERVICE)
-		return;
-	ret = rtas_call(ibm_nmi_register, 2, 1, NULL,
-			__pa((unsigned long)SystemReset_FWNMI),
-			__pa((unsigned long)MachineCheck_FWNMI));
-	if (ret == 0)
-		fwnmi_active = 1;
-}
-
-/* Early initialization.  Relocation is on but do not reference unbolted pages */
-void __init pSeries_init_early(void)
-{
-	void *comport;
-
-	hpte_init_pSeries();
-
-	if (ppc64_iommu_off)
-		pci_dma_init_direct();
-	else
-		tce_init_pSeries();
-
-#ifdef CONFIG_SMP
-	smp_init_pSeries();
-#endif
-
-	/* Map the uart for udbg. */
-	comport = (void *)__ioremap(naca->serialPortAddr, 16, _PAGE_NO_CACHE);
-	udbg_init_uart(comport);
-
-	ppc_md.udbg_putc = udbg_putc;
-	ppc_md.udbg_getc = udbg_getc;
-	ppc_md.udbg_getc_poll = udbg_getc_poll;
-}
-
-void __init
-chrp_init(unsigned long r3, unsigned long r4, unsigned long r5,
-	  unsigned long r6, unsigned long r7)
-{
-	struct device_node * dn;
-	char * hypertas;
-	unsigned int len;
-
-	ppc_md.setup_arch     = chrp_setup_arch;
-	ppc_md.get_cpuinfo    = chrp_get_cpuinfo;
-	if (naca->interrupt_controller == IC_OPEN_PIC) {
-		ppc_md.init_IRQ       = pSeries_init_openpic; 
-		ppc_md.get_irq        = openpic_get_irq;
-	} else {
-		ppc_md.init_IRQ       = xics_init_IRQ;
-		ppc_md.get_irq        = xics_get_irq;
-	}
-
-	ppc_md.log_error      = pSeries_log_error;
-
-	ppc_md.init           = chrp_init2;
-
-	ppc_md.pcibios_fixup  = pSeries_final_fixup;
-
-	ppc_md.restart        = rtas_restart;
-	ppc_md.power_off      = rtas_power_off;
-	ppc_md.halt           = rtas_halt;
-	ppc_md.panic          = rtas_os_term;
-
-	ppc_md.get_boot_time  = pSeries_get_boot_time;
-	ppc_md.get_rtc_time   = pSeries_get_rtc_time;
-	ppc_md.set_rtc_time   = pSeries_set_rtc_time;
-	ppc_md.calibrate_decr = pSeries_calibrate_decr;
-
-	ppc_md.progress       = chrp_progress;
-
-        /* Build up the firmware_features bitmask field
-         * using contents of device-tree/ibm,hypertas-functions.
-         * Ultimately this functionality may be moved into prom.c prom_init().
-         */
-	cur_cpu_spec->firmware_features = 0;
-	dn = of_find_node_by_path("/rtas");
-	if (dn == NULL) {
-		printk(KERN_ERR "WARNING ! Cannot find RTAS in device-tree !\n");
-		goto no_rtas;
-	}
-
-	hypertas = get_property(dn, "ibm,hypertas-functions", &len);
-	if (hypertas) {
-		while (len > 0){
-			int i, hypertas_len;
-			/* check value against table of strings */
-			for(i=0; i < FIRMWARE_MAX_FEATURES ;i++) {
-				if ((firmware_features_table[i].name) &&
-				    (strcmp(firmware_features_table[i].name,hypertas))==0) {
-					/* we have a match */
-					cur_cpu_spec->firmware_features |= 
-						(firmware_features_table[i].val);
-					break;
-				} 
-			}
-			hypertas_len = strlen(hypertas);
-			len -= hypertas_len +1;
-			hypertas+= hypertas_len +1;
-		}
-	}
-
-	of_node_put(dn);
- no_rtas:
-	printk(KERN_INFO "firmware_features = 0x%lx\n", 
-	       cur_cpu_spec->firmware_features);
-}
-
-void chrp_progress(char *s, unsigned short hex)
-{
-	struct device_node *root;
-	int width, *p;
-	char *os;
-	static int display_character, set_indicator;
-	static int max_width;
-	static spinlock_t progress_lock = SPIN_LOCK_UNLOCKED;
-	static int pending_newline = 0;  /* did last write end with unprinted newline? */
-
-	if (!rtas.base)
-		return;
-
-	if (max_width == 0) {
-		if ((root = find_path_device("/rtas")) &&
-		     (p = (unsigned int *)get_property(root,
-						       "ibm,display-line-length",
-						       NULL)))
-			max_width = *p;
-		else
-			max_width = 0x10;
-		display_character = rtas_token("display-character");
-		set_indicator = rtas_token("set-indicator");
-	}
-
-	if (display_character == RTAS_UNKNOWN_SERVICE) {
-		/* use hex display if available */
-		if (set_indicator != RTAS_UNKNOWN_SERVICE)
-			rtas_call(set_indicator, 3, 1, NULL, 6, 0, hex);
-		return;
-	}
-
-	spin_lock(&progress_lock);
-
-	/*
-	 * Last write ended with newline, but we didn't print it since
-	 * it would just clear the bottom line of output. Print it now
-	 * instead.
-	 *
-	 * If no newline is pending, print a CR to start output at the
-	 * beginning of the line.
-	 */
-	if (pending_newline) {
-		rtas_call(display_character, 1, 1, NULL, '\r');
-		rtas_call(display_character, 1, 1, NULL, '\n');
-		pending_newline = 0;
-	} else {
-		rtas_call(display_character, 1, 1, NULL, '\r');
-	}
- 
-	width = max_width;
-	os = s;
-	while (*os) {
-		if (*os == '\n' || *os == '\r') {
-			/* Blank to end of line. */
-			while (width-- > 0)
-				rtas_call(display_character, 1, 1, NULL, ' ');
- 
-			/* If newline is the last character, save it
-			 * until next call to avoid bumping up the
-			 * display output.
-			 */
-			if (*os == '\n' && !os[1]) {
-				pending_newline = 1;
-				spin_unlock(&progress_lock);
-				return;
-			}
- 
-			/* RTAS wants CR-LF, not just LF */
- 
-			if (*os == '\n') {
-				rtas_call(display_character, 1, 1, NULL, '\r');
-				rtas_call(display_character, 1, 1, NULL, '\n');
-			} else {
-				/* CR might be used to re-draw a line, so we'll
-				 * leave it alone and not add LF.
-				 */
-				rtas_call(display_character, 1, 1, NULL, *os);
-			}
- 
-			width = max_width;
-		} else {
-			width--;
-			rtas_call(display_character, 1, 1, NULL, *os);
-		}
- 
-		os++;
- 
-		/* if we overwrite the screen length */
-		if (width <= 0)
-			while ((*os != 0) && (*os != '\n') && (*os != '\r'))
-				os++;
-	}
- 
-	/* Blank to end of line. */
-	while (width-- > 0)
-		rtas_call(display_character, 1, 1, NULL, ' ');
-
-	spin_unlock(&progress_lock);
-}
-
-extern void setup_default_decr(void);
-
-/* Some sane defaults: 125 MHz timebase, 1GHz processor */
-#define DEFAULT_TB_FREQ		125000000UL
-#define DEFAULT_PROC_FREQ	(DEFAULT_TB_FREQ * 8)
-
-void __init pSeries_calibrate_decr(void)
-{
-	struct device_node *cpu;
-	struct div_result divres;
-	unsigned int *fp;
-	int node_found;
-
-	/*
-	 * The cpu node should have a timebase-frequency property
-	 * to tell us the rate at which the decrementer counts.
-	 */
-	cpu = of_find_node_by_type(NULL, "cpu");
-
-	ppc_tb_freq = DEFAULT_TB_FREQ;		/* hardcoded default */
-	node_found = 0;
-	if (cpu != 0) {
-		fp = (unsigned int *)get_property(cpu, "timebase-frequency",
-						  NULL);
-		if (fp != 0) {
-			node_found = 1;
-			ppc_tb_freq = *fp;
-		}
-	}
-	if (!node_found)
-		printk(KERN_ERR "WARNING: Estimating decrementer frequency "
-				"(not found)\n");
-
-	ppc_proc_freq = DEFAULT_PROC_FREQ;
-	node_found = 0;
-	if (cpu != 0) {
-		fp = (unsigned int *)get_property(cpu, "clock-frequency",
-						  NULL);
-		if (fp != 0) {
-			node_found = 1;
-			ppc_proc_freq = *fp;
-		}
-	}
-	if (!node_found)
-		printk(KERN_ERR "WARNING: Estimating processor frequency "
-				"(not found)\n");
-
-	of_node_put(cpu);
-
-	printk(KERN_INFO "time_init: decrementer frequency = %lu.%.6lu MHz\n",
-	       ppc_tb_freq/1000000, ppc_tb_freq%1000000);
-	printk(KERN_INFO "time_init: processor frequency   = %lu.%.6lu MHz\n",
-	       ppc_proc_freq/1000000, ppc_proc_freq%1000000);
-
-	tb_ticks_per_jiffy = ppc_tb_freq / HZ;
-	tb_ticks_per_sec = tb_ticks_per_jiffy * HZ;
-	tb_ticks_per_usec = ppc_tb_freq / 1000000;
-	tb_to_us = mulhwu_scale_factor(ppc_tb_freq, 1000000);
-	div128_by_32(1024*1024, 0, tb_ticks_per_sec, &divres);
-	tb_to_xs = divres.result_low;
-
-	setup_default_decr();
-}
diff -Nru a/arch/ppc64/kernel/eeh.c b/arch/ppc64/kernel/eeh.c
--- a/arch/ppc64/kernel/eeh.c	2004-10-18 14:56:33 -07:00
+++ b/arch/ppc64/kernel/eeh.c	2004-10-18 14:56:33 -07:00
@@ -48,9 +48,6 @@
 static int ibm_slot_error_detail;
 
 static int eeh_subsystem_enabled;
-#define EEH_MAX_OPTS 4096
-static char *eeh_opts;
-static int eeh_opts_last;
 
 /* Buffer for reporting slot-error-detail rtas calls */
 static unsigned char slot_errbuf[RTAS_ERROR_LOG_MAX];
@@ -62,10 +59,6 @@
 static DEFINE_PER_CPU(unsigned long, false_positives);
 static DEFINE_PER_CPU(unsigned long, ignored_failures);
 
-static int eeh_check_opts_config(struct device_node *dn, int class_code,
-				 int vendor_id, int device_id,
-				 int default_state);
-
 /**
  * The pci address cache subsystem.  This subsystem places
  * PCI device address resources into a red-black tree, sorted
@@ -209,6 +202,7 @@
 {
 	struct device_node *dn;
 	int i;
+	int inserted = 0;
 
 	dn = pci_device_to_OF_node(dev);
 	if (!dn) {
@@ -242,7 +236,12 @@
 		if (start == 0 || ~start == 0 || end == 0 || ~end == 0)
 			 continue;
 		pci_addr_cache_insert(dev, start, end, flags);
+		inserted = 1;
 	}
+
+	/* If there was nothing to add, the cache has no reference... */
+	if (!inserted)
+		pci_dev_put(dev);
 }
 
 /**
@@ -265,6 +264,7 @@
 static inline void __pci_addr_cache_remove_device(struct pci_dev *dev)
 {
 	struct rb_node *n;
+	int removed = 0;
 
 restart:
 	n = rb_first(&pci_io_addr_cache_root.rb_root);
@@ -274,6 +274,7 @@
 
 		if (piar->pcidev == dev) {
 			rb_erase(n, &pci_io_addr_cache_root.rb_root);
+			removed = 1;
 			kfree(piar);
 			goto restart;
 		}
@@ -281,7 +282,8 @@
 	}
 
 	/* The cache no longer holds its reference to this device... */
-	pci_dev_put(dev);
+	if (removed)
+		pci_dev_put(dev);
 }
 
 /**
@@ -333,47 +335,38 @@
 
 /**
  * eeh_token_to_phys - convert EEH address token to phys address
- * @token i/o token, should be address in the form 0xA....
- *
- * Converts EEH address tokens into physical addresses.  Note that
- * ths routine does *not* convert I/O BAR addresses (which start
- * with 0xE...) to phys addresses!
+ * @token i/o token, should be address in the form 0xE....
  */
-static unsigned long eeh_token_to_phys(unsigned long token)
+static inline unsigned long eeh_token_to_phys(unsigned long token)
 {
 	pte_t *ptep;
-	unsigned long pa, vaddr;
+	unsigned long pa;
 
-	if (REGION_ID(token) == EEH_REGION_ID)
-		vaddr = IO_TOKEN_TO_ADDR(token);
-	else
+	ptep = find_linux_pte(ioremap_mm.pgd, token);
+	if (!ptep)
 		return token;
-
-	ptep = find_linux_pte(ioremap_mm.pgd, vaddr);
 	pa = pte_pfn(*ptep) << PAGE_SHIFT;
 
-	return pa | (vaddr & (PAGE_SIZE-1));
+	return pa | (token & (PAGE_SIZE-1));
 }
 
 /**
- * eeh_check_failure - check if all 1's data is due to EEH slot freeze
- * @token i/o token, should be address in the form 0xA....
- * @val value, should be all 1's (XXX why do we need this arg??)
+ * eeh_dn_check_failure - check if all 1's data is due to EEH slot freeze
+ * @dn device node
+ * @dev pci device, if known
  *
- * Check for an eeh failure at the given token address.
- * The given value has been read and it should be 1's (0xff, 0xffff or
- * 0xffffffff).
+ * Check for an EEH failure for the given device node.  Call this
+ * routine if the result of a read was all 0xff's and you want to
+ * find out if this is due to an EEH slot freeze event.  This routine
+ * will query firmware for the EEH status.
  *
- * Probe to determine if an error actually occurred.  If not return val.
- * Otherwise panic.
+ * Returns 0 if there has not been an EEH error; otherwise returns
+ * an error code.
  *
- * Note this routine might be called in an interrupt context ...
+ * It is safe to call this routine in an interrupt context.
  */
-unsigned long eeh_check_failure(void *token, unsigned long val)
+int eeh_dn_check_failure(struct device_node *dn, struct pci_dev *dev)
 {
-	unsigned long addr;
-	struct pci_dev *dev;
-	struct device_node *dn;
 	int ret;
 	int rets[2];
 	unsigned long flags;
@@ -381,30 +374,19 @@
 	__get_cpu_var(total_mmio_ffs)++;
 
 	if (!eeh_subsystem_enabled)
-		return val;
+		return 0;
 
-	/* Finding the phys addr + pci device; this is pretty quick. */
-	addr = eeh_token_to_phys((unsigned long)token);
-	dev = pci_get_device_by_addr(addr);
-	if (!dev)
-		return val;
-
-	dn = pci_device_to_OF_node(dev);
-	if (!dn) {
-		pci_dev_put(dev);
-		return val;
-	}
+	if (!dn)
+		return 0;
 
 	/* Access to IO BARs might get this far and still not want checking. */
 	if (!(dn->eeh_mode & EEH_MODE_SUPPORTED) ||
 	    dn->eeh_mode & EEH_MODE_NOCHECK) {
-		pci_dev_put(dev);
-		return val;
+		return 0;
 	}
 
 	if (!dn->eeh_config_addr) {
-		pci_dev_put(dev);
-		return val;
+		return 0;
 	}
 
 	/*
@@ -418,7 +400,7 @@
 			dn->eeh_config_addr, BUID_HI(dn->phb->buid),
 			BUID_LO(dn->phb->buid));
 
-	if (ret == 0 && rets[1] == 1 && rets[0] >= 2) {
+	if (ret == 0 && rets[1] == 1 && (rets[0] == 2 || rets[0] == 4)) {
 		int log_event;
 
 		spin_lock_irqsave(&slot_errbuf_lock, flags);
@@ -430,7 +412,7 @@
 		                      BUID_LO(dn->phb->buid), NULL, 0,
 		                      virt_to_phys(slot_errbuf),
 		                      eeh_error_buf_size,
-		                      2 /* Permanent Error */);
+		                      1 /* Temporary Error */);
 
 		if (log_event == 0)
 			log_error(slot_errbuf, ERR_TYPE_RTAS_LOG,
@@ -438,6 +420,10 @@
 
 		spin_unlock_irqrestore(&slot_errbuf_lock, flags);
 
+		printk(KERN_INFO "EEH: MMIO failure (%d) on device: %s %s\n",
+		       rets[0], dn->name, dn->full_name);
+		WARN_ON(1);
+
 		/*
 		 * XXX We should create a separate sysctl for this.
 		 *
@@ -446,26 +432,57 @@
 		 * can use it here.
 		 */
 		if (panic_on_oops) {
-			panic("EEH: MMIO failure (%d) on device:%s %s\n",
-			      rets[0], pci_name(dev), pci_pretty_name(dev));
+			panic("EEH: MMIO failure (%d) on device: %s %s\n",
+			      rets[0], dn->name, dn->full_name);
 		} else {
 			__get_cpu_var(ignored_failures)++;
-			printk(KERN_INFO "EEH: MMIO failure (%d) on device:%s %s\n",
-			       rets[0], pci_name(dev), pci_pretty_name(dev));
 		}
 	} else {
 		__get_cpu_var(false_positives)++;
 	}
 
+	return 0;
+}
+
+EXPORT_SYMBOL(eeh_dn_check_failure);
+
+/**
+ * eeh_check_failure - check if all 1's data is due to EEH slot freeze
+ * @token i/o token, should be address in the form 0xA....
+ * @val value, should be all 1's (XXX why do we need this arg??)
+ *
+ * Check for an eeh failure at the given token address.
+ * Check for an EEH failure at the given token address.  Call this
+ * routine if the result of a read was all 0xff's and you want to
+ * find out if this is due to an EEH slot freeze event.  This routine
+ * will query firmware for the EEH status.
+ *
+ * Note this routine is safe to call in an interrupt context.
+ */
+unsigned long eeh_check_failure(const volatile void __iomem *token, unsigned long val)
+{
+	unsigned long addr;
+	struct pci_dev *dev;
+	struct device_node *dn;
+
+	/* Finding the phys addr + pci device; this is pretty quick. */
+	addr = eeh_token_to_phys((unsigned long __force) token);
+	dev = pci_get_device_by_addr(addr);
+	if (!dev)
+		return val;
+
+	dn = pci_device_to_OF_node(dev);
+	eeh_dn_check_failure (dn, dev);
+
 	pci_dev_put(dev);
 	return val;
 }
+
 EXPORT_SYMBOL(eeh_check_failure);
 
 struct eeh_early_enable_info {
 	unsigned int buid_hi;
 	unsigned int buid_lo;
-	int force_off;
 };
 
 /* Enable eeh for the given device node. */
@@ -507,18 +524,8 @@
 	if ((*class_code >> 16) == PCI_BASE_CLASS_DISPLAY)
 		enable = 0;
 
-	if (!eeh_check_opts_config(dn, *class_code, *vendor_id, *device_id,
-				   enable)) {
-		if (enable) {
-			printk(KERN_WARNING "EEH: %s user requested to run "
-			       "without EEH checking.\n", dn->full_name);
-			enable = 0;
-		}
-	}
-
-	if (!enable || info->force_off) {
+	if (!enable)
 		dn->eeh_mode |= EEH_MODE_NOCHECK;
-	}
 
 	/* Ok... see if this device supports EEH.  Some do, some don't,
 	 * and the only way to find out is to check each and every one. */
@@ -572,15 +579,12 @@
 {
 	struct device_node *phb, *np;
 	struct eeh_early_enable_info info;
-	char *eeh_force_off = strstr(saved_command_line, "eeh-force-off");
 
 	init_pci_config_tokens();
 
 	np = of_find_node_by_path("/rtas");
-	if (np == NULL) {
-		printk(KERN_WARNING "EEH: RTAS not found !\n");
+	if (np == NULL)
 		return;
-	}
 
 	ibm_set_eeh_option = rtas_token("ibm,set-eeh-option");
 	ibm_set_slot_reset = rtas_token("ibm,set-slot-reset");
@@ -600,13 +604,6 @@
 		eeh_error_buf_size = RTAS_ERROR_LOG_MAX;
 	}
 
-	info.force_off = 0;
-	if (eeh_force_off) {
-		printk(KERN_WARNING "EEH: WARNING: PCI Enhanced I/O Error "
-		       "Handling is user disabled\n");
-		info.force_off = 1;
-	}
-
 	/* Enable EEH for all adapters.  Note that eeh requires buid's */
 	for (phb = of_find_node_by_name(NULL, "pci"); phb;
 	     phb = of_find_node_by_name(phb, "pci")) {
@@ -621,11 +618,10 @@
 		traverse_pci_devices(phb, early_enable_eeh, &info);
 	}
 
-	if (eeh_subsystem_enabled) {
+	if (eeh_subsystem_enabled)
 		printk(KERN_INFO "EEH: PCI Enhanced I/O Error Handling Enabled\n");
-	} else {
-		printk(KERN_WARNING "EEH: disabled PCI Enhanced I/O Error Handling\n");
-	}
+	else
+		printk(KERN_WARNING "EEH: No capable adapters found\n");
 }
 
 /**
@@ -701,39 +697,6 @@
 }
 EXPORT_SYMBOL(eeh_remove_device);
 
-/*
- * If EEH is implemented, find the PCI device using given phys addr
- * and check to see if eeh failure checking is disabled.
- * Remap the addr (trivially) to the EEH region if EEH checking enabled.
- * For addresses not known to PCI the vaddr is simply returned unchanged.
- */
-void *eeh_ioremap(unsigned long addr, void *vaddr)
-{
-	struct pci_dev *dev;
-	struct device_node *dn;
-
-	if (!eeh_subsystem_enabled)
-		return vaddr;
-
-	dev = pci_get_device_by_addr(addr);
-	if (!dev)
-		return vaddr;
-
-	dn = pci_device_to_OF_node(dev);
-	if (!dn) {
-		pci_dev_put(dev);
-		return vaddr;
-	}
-
-	if (dn->eeh_mode & EEH_MODE_NOCHECK) {
-		pci_dev_put(dev);
-		return vaddr;
-	}
-
-	pci_dev_put(dev);
-	return (void *)IO_ADDR_TO_TOKEN(vaddr);
-}
-
 static int proc_eeh_show(struct seq_file *m, void *v)
 {
 	unsigned int cpu;
@@ -784,129 +747,3 @@
 	return 0;
 }
 __initcall(eeh_init_proc);
-
-/*
- * Test if "dev" should be configured on or off.
- * This processes the options literally from left to right.
- * This lets the user specify stupid combinations of options,
- * but at least the result should be very predictable.
- */
-static int eeh_check_opts_config(struct device_node *dn,
-				 int class_code, int vendor_id, int device_id,
-				 int default_state)
-{
-	char devname[32], classname[32];
-	char *strs[8], *s;
-	int nstrs, i;
-	int ret = default_state;
-
-	/* Build list of strings to match */
-	nstrs = 0;
-	s = (char *)get_property(dn, "ibm,loc-code", NULL);
-	if (s)
-		strs[nstrs++] = s;
-	sprintf(devname, "dev%04x:%04x", vendor_id, device_id);
-	strs[nstrs++] = devname;
-	sprintf(classname, "class%04x", class_code);
-	strs[nstrs++] = classname;
-	strs[nstrs++] = "";	/* yes, this matches the empty string */
-
-	/*
-	 * Now see if any string matches the eeh_opts list.
-	 * The eeh_opts list entries start with + or -.
-	 */
-	for (s = eeh_opts; s && (s < (eeh_opts + eeh_opts_last));
-	     s += strlen(s)+1) {
-		for (i = 0; i < nstrs; i++) {
-			if (strcasecmp(strs[i], s+1) == 0) {
-				ret = (strs[i][0] == '+') ? 1 : 0;
-			}
-		}
-	}
-	return ret;
-}
-
-/*
- * Handle kernel eeh-on & eeh-off cmd line options for eeh.
- *
- * We support:
- *	eeh-off=loc1,loc2,loc3...
- *
- * and this option can be repeated so
- *      eeh-off=loc1,loc2 eeh-off=loc3
- * is the same as eeh-off=loc1,loc2,loc3
- *
- * loc is an IBM location code that can be found in a manual or
- * via openfirmware (or the Hardware Management Console).
- *
- * We also support these additional "loc" values:
- *
- *	dev#:#    vendor:device id in hex (e.g. dev1022:2000)
- *	class#    class id in hex (e.g. class0200)
- *
- * If no location code is specified all devices are assumed
- * so eeh-off means eeh by default is off.
- */
-
-/*
- * This is implemented as a null separated list of strings.
- * Each string looks like this:  "+X" or "-X"
- * where X is a loc code, vendor:device, class (as shown above)
- * or empty which is used to indicate all.
- *
- * We interpret this option string list so that it will literally
- * behave left-to-right even if some combinations don't make sense.
- */
-static int __init eeh_parm(char *str, int state)
-{
-	char *s, *cur, *curend;
-
-	if (!eeh_opts) {
-		eeh_opts = alloc_bootmem(EEH_MAX_OPTS);
-		eeh_opts[eeh_opts_last++] = '+'; /* default */
-		eeh_opts[eeh_opts_last++] = '\0';
-	}
-	if (*str == '\0') {
-		eeh_opts[eeh_opts_last++] = state ? '+' : '-';
-		eeh_opts[eeh_opts_last++] = '\0';
-		return 1;
-	}
-	if (*str == '=')
-		str++;
-	for (s = str; s && *s != '\0'; s = curend) {
-		cur = s;
-		/* ignore empties.  Don't treat as "all-on" or "all-off" */
-		while (*cur == ',')
-			cur++;
-		curend = strchr(cur, ',');
-		if (!curend)
-			curend = cur + strlen(cur);
-		if (*cur) {
-			int curlen = curend-cur;
-			if (eeh_opts_last + curlen > EEH_MAX_OPTS-2) {
-				printk(KERN_WARNING "EEH: sorry...too many "
-				       "eeh cmd line options\n");
-				return 1;
-			}
-			eeh_opts[eeh_opts_last++] = state ? '+' : '-';
-			strncpy(eeh_opts+eeh_opts_last, cur, curlen);
-			eeh_opts_last += curlen;
-			eeh_opts[eeh_opts_last++] = '\0';
-		}
-	}
-
-	return 1;
-}
-
-static int __init eehoff_parm(char *str)
-{
-	return eeh_parm(str, 0);
-}
-
-static int __init eehon_parm(char *str)
-{
-	return eeh_parm(str, 1);
-}
-
-__setup("eeh-off", eehoff_parm);
-__setup("eeh-on", eehon_parm);
diff -Nru a/arch/ppc64/kernel/entry.S b/arch/ppc64/kernel/entry.S
--- a/arch/ppc64/kernel/entry.S	2004-10-18 14:55:54 -07:00
+++ b/arch/ppc64/kernel/entry.S	2004-10-18 14:55:54 -07:00
@@ -122,7 +122,7 @@
 	andi.	r11,r10,_TIF_SYSCALL_T_OR_A
 	bne-	syscall_dotrace
 syscall_dotrace_cont:
-	cmpli	0,r0,NR_syscalls
+	cmpldi	0,r0,NR_syscalls
 	bge-	syscall_enosys
 
 system_call:			/* label this so stack traces look sane */
@@ -204,7 +204,7 @@
 
 syscall_error:
 	lbz	r11,TI_SC_NOERR(r12)
-	cmpi	0,r11,0
+	cmpwi	0,r11,0
 	bne-	syscall_error_cont
 	neg	r3,r3
 	oris	r5,r5,0x1000	/* Set SO bit in CR */
@@ -393,9 +393,17 @@
 	cmpd	cr1,r6,r9	/* or is new ESID the same as current ESID? */
 	cror	eq,4*cr1+eq,eq
 	beq	2f		/* if yes, don't slbie it */
-	oris	r6,r6,0x0800	/* set C (class) bit */
-	slbie	r6
-	slbie	r6		/* Workaround POWER5 < DD2.1 issue */
+	oris	r0,r6,0x0800	/* set C (class) bit */
+
+	/* Bolt in the new stack SLB entry */
+	ld	r7,KSP_VSID(r4)	/* Get new stack's VSID */
+	oris	r6,r6,(SLB_ESID_V)@h
+	ori	r6,r6,(SLB_NUM_BOLTED-1)@l
+	slbie	r0
+	slbie	r0		/* Workaround POWER5 < DD2.1 issue */
+	slbmte	r7,r6
+	isync
+
 2:
 END_FTR_SECTION_IFSET(CPU_FTR_SLB)
 	clrrdi	r7,r8,THREAD_SHIFT	/* base of new stack */
@@ -738,6 +746,10 @@
 	mtlr    r0
         blr				/* return to caller */
 
+#endif /* CONFIG_PPC_PSERIES */
+
+#ifdef CONFIG_PPC_MULTIPLATFORM
+
 _GLOBAL(enter_prom)
 	mflr	r0
 	std	r0,16(r1)
@@ -769,11 +781,8 @@
 	std	r11,_MSR(r1)
 
 	/* Get the PROM entrypoint */
-        bl      .reloc_offset
-	LOADADDR(r12,prom)
-	sub	r12,r12,r3
-	ld	r12,PROMENTRY(r12)
-	mtlr	r12
+	ld	r0,GPR4(r1)
+	mtlr	r0
 
 	/* Switch MSR to 32 bits mode
 	 */
@@ -826,4 +835,4 @@
 	mtlr    r0
         blr
 	
-#endif	/* defined(CONFIG_PPC_PSERIES) */
+#endif	/* CONFIG_PPC_MULTIPLATFORM */
diff -Nru a/arch/ppc64/kernel/head.S b/arch/ppc64/kernel/head.S
--- a/arch/ppc64/kernel/head.S	2004-10-18 14:56:32 -07:00
+++ b/arch/ppc64/kernel/head.S	2004-10-18 14:56:32 -07:00
@@ -83,13 +83,14 @@
 	.text
 	.globl  _stext
 _stext:
-#ifdef CONFIG_PPC_PSERIES
-_STATIC(__start)
+#ifdef CONFIG_PPC_MULTIPLATFORM
+_GLOBAL(__start)
 	/* NOP this out unconditionally */
 BEGIN_FTR_SECTION
-	b .__start_initialization_pSeries
+	b .__start_initialization_multiplatform
 END_FTR_SECTION(0, 1)
-#endif
+#endif /* CONFIG_PPC_MULTIPLATFORM */
+
 	/* Catch branch to 0 in real mode */
 	trap
 #ifdef CONFIG_PPC_ISERIES
@@ -117,7 +118,8 @@
 	.globl	embedded_sysmap_end
 embedded_sysmap_end:
 	.llong	0
-#else
+
+#else /* CONFIG_PPC_ISERIES */
 
 	/* Secondary processors spin on this value until it goes to 1. */
 	.globl  __secondary_hold_spinloop
@@ -199,6 +201,7 @@
 #define EX_R12		24
 #define EX_R13		32
 #define EX_SRR0		40
+#define EX_R3		40	/* SLB miss saves R3, but not SRR0 */
 #define EX_DAR		48
 #define EX_LR		48	/* SLB miss saves LR, but not DAR */
 #define EX_DSISR	56
@@ -322,36 +325,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				\
@@ -446,21 +424,13 @@
 	std	r10,PACA_EXSLB+EX_R10(r13)
 	std	r11,PACA_EXSLB+EX_R11(r13)
 	std	r12,PACA_EXSLB+EX_R12(r13)
-	std	r3,PACASLBR3(r13)
+	std	r3,PACA_EXSLB+EX_R3(r13)
 	mfspr	r9,SPRG1
 	std	r9,PACA_EXSLB+EX_R13(r13)
 	mfcr	r9
-	clrrdi	r12,r13,32		/* get high part of &label */
-	mfmsr	r10
-	mfspr	r11,SRR0		/* save SRR0 */
-	ori	r12,r12,(.do_slb_miss)@l
-	ori	r10,r10,MSR_IR|MSR_DR	/* DON'T set RI for SLB miss */
-	mtspr	SRR0,r12
 	mfspr	r12,SRR1		/* and SRR1 */
-	mtspr	SRR1,r10
 	mfspr	r3,DAR
-	rfid
-	b	.	/* prevent speculative execution */
+	b	.do_slb_miss		/* Rel. branch works in real mode */
 
 	STD_EXCEPTION_PSERIES(0x400, InstructionAccess)
 
@@ -474,21 +444,13 @@
 	std	r10,PACA_EXSLB+EX_R10(r13)
 	std	r11,PACA_EXSLB+EX_R11(r13)
 	std	r12,PACA_EXSLB+EX_R12(r13)
-	std	r3,PACASLBR3(r13)
+	std	r3,PACA_EXSLB+EX_R3(r13)
 	mfspr	r9,SPRG1
 	std	r9,PACA_EXSLB+EX_R13(r13)
 	mfcr	r9
-	clrrdi	r12,r13,32		/* get high part of &label */
-	mfmsr	r10
-	mfspr	r11,SRR0		/* save SRR0 */
-	ori	r12,r12,(.do_slb_miss)@l
-	ori	r10,r10,MSR_IR|MSR_DR	/* DON'T set RI for SLB miss */
-	mtspr	SRR0,r12
 	mfspr	r12,SRR1		/* and SRR1 */
-	mtspr	SRR1,r10
-	mr	r3,r11			/* SRR0 is faulting address */
-	rfid
-	b	.	/* prevent speculative execution */
+	mfspr	r3,SRR0			/* SRR0 is faulting address */
+	b	.do_slb_miss		/* Rel. branch works in real mode */
 
 	STD_EXCEPTION_PSERIES(0x500, HardwareInterrupt)
 	STD_EXCEPTION_PSERIES(0x600, Alignment)
@@ -580,7 +542,7 @@
 	 * VSID generation algorithm.  See include/asm/mmu_context.h.
 	 */
 
-	.llong	1		/* # ESIDs to be mapped by hypervisor	 */
+	.llong	2		/* # ESIDs to be mapped by hypervisor	 */
 	.llong	1		/* # memory ranges to be mapped by hypervisor */
 	.llong	STAB0_PAGE	/* Page # of segment table within load area	*/
 	.llong	0		/* Reserved */
@@ -588,11 +550,15 @@
 	.llong	0		/* Reserved */
 	.llong	0		/* Reserved */
 	.llong	0		/* Reserved */
-	.llong	0x0c00000000	/* ESID to map (Kernel at EA = 0xC000000000000000) */
-	.llong	0x06a99b4b14	/* VSID to map (Kernel at VA = 0x6a99b4b140000000) */
+	.llong	(KERNELBASE>>SID_SHIFT)
+	.llong	0x408f92c94	/* KERNELBASE VSID */
+	/* We have to list the bolted VMALLOC segment here, too, so that it
+	 * will be restored on shared processor switch */
+	.llong	(VMALLOCBASE>>SID_SHIFT)
+	.llong	0xf09b89af5	/* VMALLOCBASE VSID */
 	.llong	8192		/* # pages to map (32 MB) */
 	.llong	0		/* Offset from start of loadarea to start of map */
-	.llong	0x0006a99b4b140000	/* VPN of first page to map */
+	.llong	0x408f92c940000	/* VPN of first page to map */
 
 	. = 0x6100
 
@@ -630,8 +596,7 @@
 DataAccessSLB_Iseries:
 	mtspr	SPRG1,r13		/* save r13 */
 	EXCEPTION_PROLOG_ISERIES_1(PACA_EXSLB)
-	std	r3,PACASLBR3(r13)
-	ld	r11,PACALPPACA+LPPACASRR0(r13)
+	std	r3,PACA_EXSLB+EX_R3(r13)
 	ld	r12,PACALPPACA+LPPACASRR1(r13)
 	mfspr	r3,DAR
 	b	.do_slb_miss
@@ -642,10 +607,9 @@
 InstructionAccessSLB_Iseries:
 	mtspr	SPRG1,r13		/* save r13 */
 	EXCEPTION_PROLOG_ISERIES_1(PACA_EXSLB)
-	std	r3,PACASLBR3(r13)
-	ld	r11,PACALPPACA+LPPACASRR0(r13)
+	std	r3,PACA_EXSLB+EX_R3(r13)
 	ld	r12,PACALPPACA+LPPACASRR1(r13)
-	mr	r3,r11
+	ld	r3,PACALPPACA+LPPACASRR0(r13)
 	b	.do_slb_miss
 
 	MASKABLE_EXCEPTION_ISERIES(0x500, HardwareInterrupt)
@@ -1033,6 +997,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
@@ -1043,6 +1010,8 @@
 	b	11f
 #else
 	beq	fast_exception_return   /* Return from exception on success */
+	ble-	12f			/* Failure return from hash_page */
+
 	/* fall through */
 #endif
 
@@ -1062,6 +1031,15 @@
 	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 */
 _GLOBAL(do_ste_alloc)
 	bl	.ste_allocate		/* try to insert stab entry */
@@ -1088,18 +1066,9 @@
 	rldimi	r10,r11,7,52	/* r10 = first ste of the group */
 
 	/* Calculate VSID */
-	/* (((ea >> 28) & 0x1fff) << 15) | (ea >> 60) */
-	rldic	r11,r11,15,36
-	ori	r11,r11,0xc
-
-	/* VSID_RANDOMIZER */
-	li	r9,9
-	sldi	r9,r9,32
-	oris	r9,r9,58231
-	ori	r9,r9,39831
-
-	mulld	r9,r11,r9
-	rldic	r9,r9,12,16	/* r9 = vsid << 12 */
+	/* This is a kernel address, so protovsid = ESID */
+	ASM_VSID_SCRAMBLE(r11, r9)
+	rldic	r9,r11,12,16	/* r9 = vsid << 12 */
 
 	/* Search the primary group for a free entry */
 1:	ld	r11,0(r10)	/* Test valid bit of the current ste	*/
@@ -1176,7 +1145,6 @@
 	mflr	r10
 
 	stw	r9,PACA_EXSLB+EX_CCR(r13)	/* save CR in exc. frame */
-	std	r11,PACA_EXSLB+EX_SRR0(r13)	/* save SRR0 in exc. frame */
 	std	r10,PACA_EXSLB+EX_LR(r13)	/* save LR */
 
 	bl	.slb_allocate			/* handle it */
@@ -1184,9 +1152,11 @@
 	/* All done -- return from exception. */
 
 	ld	r10,PACA_EXSLB+EX_LR(r13)
-	ld	r3,PACASLBR3(r13)
+	ld	r3,PACA_EXSLB+EX_R3(r13)
 	lwz	r9,PACA_EXSLB+EX_CCR(r13)	/* get saved CR */
-	ld	r11,PACA_EXSLB+EX_SRR0(r13)	/* get saved SRR0 */
+#ifdef CONFIG_PPC_ISERIES
+	ld	r11,PACALPPACA+LPPACASRR0(r13)	/* get SRR0 value */
+#endif /* CONFIG_PPC_ISERIES */
 
 	mtlr	r10
 
@@ -1199,8 +1169,10 @@
 	mtcrf	0x01,r9		/* slb_allocate uses cr0 and cr7 */
 .machine	pop
 
+#ifdef CONFIG_PPC_ISERIES
 	mtspr	SRR0,r11
 	mtspr	SRR1,r12
+#endif /* CONFIG_PPC_ISERIES */
 	ld	r9,PACA_EXSLB+EX_R9(r13)
 	ld	r10,PACA_EXSLB+EX_R10(r13)
 	ld	r11,PACA_EXSLB+EX_R11(r13)
@@ -1253,12 +1225,10 @@
 #endif
 	b 	1b			/* Loop until told to go	 */
 #ifdef CONFIG_PPC_ISERIES
-_GLOBAL(__start_initialization_iSeries)
+_STATIC(__start_initialization_iSeries)
 	/* Clear out the BSS */
 	LOADADDR(r11,__bss_stop)
-
 	LOADADDR(r8,__bss_start)
-
 	sub	r11,r11,r8		/* bss size			*/
 	addi	r11,r11,7		/* round up to an even double word */
 	rldicl. r11,r11,61,3		/* shift right by 3		*/
@@ -1295,32 +1265,73 @@
 	ld	r6,PACA(r4)		/* Get the base paca pointer	*/
 	ld	r4,PACASTABVIRT(r6)
 
-	bl	.iSeries_fixup_klimit
+	bl	.iSeries_early_setup
 
 	/* relocation is on at this point */
 
 	b	.start_here_common
-#endif
+#endif /* CONFIG_PPC_ISERIES */
 
-#ifdef CONFIG_PPC_PSERIES
+#ifdef CONFIG_PPC_MULTIPLATFORM
 
-_STATIC(mmu_off)
+_STATIC(__mmu_off)
 	mfmsr	r3
 	andi.	r0,r3,MSR_IR|MSR_DR
 	beqlr
 	andc	r3,r3,r0
-	mtspr	SRR0,r4
-	mtspr	SRR1,r3
+	mtspr	SPRN_SRR0,r4
+	mtspr	SPRN_SRR1,r3
 	sync
 	rfid
 	b	.	/* prevent speculative execution */
-_GLOBAL(__start_initialization_pSeries)
-	mr	r31,r3			/* save parameters */
+
+
+/*
+ * Here is our main kernel entry point. We support currently 2 kind of entries
+ * depending on the value of r5.
+ *
+ *   r5 != NULL -> OF entry, we go to prom_init, "legacy" parameter content
+ *                 in r3...r7
+ *   
+ *   r5 == NULL -> kexec style entry. r3 is a physical pointer to the
+ *                 DT block, r4 is a physical pointer to the kernel itself
+ *
+ */
+_GLOBAL(__start_initialization_multiplatform)
+	/*
+	 * Are we booted from a PROM Of-type client-interface ?
+	 */
+	cmpldi	cr0,r5,0
+	bne	.__boot_from_prom		/* yes -> prom */
+
+	/* Save parameters */
+	mr	r31,r3
+	mr	r30,r4
+
+	/* Make sure we are running in 64 bits mode */
+	bl	.enable_64b_mode
+
+	/* Setup some critical 970 SPRs before switching MMU off */
+	bl	.__970_cpu_preinit
+
+	/* cpu # */
+	li	r24,0
+
+	/* Switch off MMU if not already */
+	LOADADDR(r4, .__after_prom_start - KERNELBASE)
+	add	r4,r4,r30
+	bl	.__mmu_off
+	b	.__after_prom_start
+
+_STATIC(__boot_from_prom)
+	/* Save parameters */
+	mr	r31,r3
 	mr	r30,r4
 	mr	r29,r5
 	mr	r28,r6
 	mr	r27,r7
 
+	/* Make sure we are running in 64 bits mode */
 	bl	.enable_64b_mode
 
 	/* put a relocation offset into r3 */
@@ -1333,7 +1344,7 @@
 	/* Relocate the TOC from a virt addr to a real addr */
 	sub	r2,r2,r3
 
-	/* Save parameters */
+	/* Restore parameters */
 	mr	r3,r31
 	mr	r4,r30
 	mr	r5,r29
@@ -1342,17 +1353,8 @@
 
 	/* Do all of the interaction with OF client interface */
 	bl	.prom_init
-	mr	r23,r3			/* Save phys address we are running at */
-
-	/* Setup some critical 970 SPRs before switching MMU off */
-	bl	.__970_cpu_preinit
-
-	li	r24,0			/* cpu # */
-
-	/* Switch off MMU if not already */
-	LOADADDR(r4, .__after_prom_start - KERNELBASE)
-	add	r4,r4,r23
-	bl	.mmu_off	
+	/* We never return */
+	trap
 
 /*
  * At this point, r3 contains the physical address we are running at,
@@ -1378,7 +1380,7 @@
 
 	li	r3,0			/* target addr */
 
-	// XXX FIXME: Use phys returned by OF (r23)
+	// XXX FIXME: Use phys returned by OF (r30)
 	sub	r4,r27,r26 		/* source addr			 */
 					/* current address of _start	 */
 					/*   i.e. where we are running	 */
@@ -1403,8 +1405,9 @@
 	ld	r5,0(r5)		/* get the value of klimit */
 	sub	r5,r5,r27
 	bl	.copy_and_flush		/* copy the rest */
-	b	.start_here_pSeries
-#endif
+	b	.start_here_multiplatform
+
+#endif /* CONFIG_PPC_MULTIPLATFORM */
 
 /*
  * Copy routine used to copy the kernel to start at physical address 0
@@ -1609,6 +1612,7 @@
 	li	r10,THREAD_VSCR
 	stw	r4,THREAD_USED_VR(r5)
 	lvx	vr0,r10,r5
+	mtvscr	vr0
 	REST_32VRS(0,r4,r5)
 #ifndef CONFIG_SMP
 	/* Update last_task_used_math to 'current' */
@@ -1823,15 +1827,33 @@
 	isync
 	blr
 
-#ifdef CONFIG_PPC_PSERIES
+#ifdef CONFIG_PPC_MULTIPLATFORM
 /*
  * This is where the main kernel code starts.
  */
-_STATIC(start_here_pSeries)
+_STATIC(start_here_multiplatform)
 	/* get a new offset, now that the kernel has moved. */
 	bl	.reloc_offset
 	mr	r26,r3
 
+	/* Clear out the BSS. It may have been done in prom_init,
+	 * already but that's irrelevant since prom_init will soon
+	 * be detached from the kernel completely. Besides, we need
+	 * to clear it now for kexec-style entry.
+	 */
+	LOADADDR(r11,__bss_stop)
+	LOADADDR(r8,__bss_start)
+	sub	r11,r11,r8		/* bss size			*/
+	addi	r11,r11,7		/* round up to an even double word */
+	rldicl. r11,r11,61,3		/* shift right by 3		*/
+	beq	4f
+	addi	r8,r8,-8
+	li	r0,0
+	mtctr	r11			/* zero this many doublewords	*/
+3:	stdu	r0,8(r8)
+	bdnz	3b
+4:
+
 	mfmsr	r6
 	ori	r6,r6,MSR_RI
 	mtmsrd	r6			/* RI on */
@@ -1904,8 +1926,11 @@
 	mr	r5,r26
 	bl	.identify_cpu
 
-	/* Get the pointer to the segment table which is used by		*/
-	/* stab_initialize						 */
+	/* Setup a valid physical PACA pointer in SPRG3 for early_setup
+	 * note that boot_cpuid can always be 0 nowadays since there is
+	 * nowhere it can be initialized differently before we reach this
+	 * code
+	 */
 	LOADADDR(r27, boot_cpuid)
 	sub	r27,r27,r26
 	lwz	r27,0(r27)
@@ -1914,12 +1939,18 @@
 	mulli	r13,r27,PACA_SIZE	/* Calculate vaddr of right paca */
 	add	r13,r13,r24		/* for this processor.		 */
 	sub	r13,r13,r26		/* convert to physical addr	 */
-
 	mtspr	SPRG3,r13		/* PPPBBB: Temp... -Peter */
-	ld	r3,PACASTABREAL(r13)
-	ori	r4,r3,1			/* turn on valid bit		 */
 	
+	/* Do very early kernel initializations, including initial hash table,
+	 * stab and slb setup before we turn on relocation.	*/
+
+	/* Restore parameters passed from prom_init/kexec */
+	mr	r3,r31
+ 	bl	.early_setup
+
 	/* set the ASR */
+	ld	r3,PACASTABREAL(r13)
+	ori	r4,r3,1			/* turn on valid bit		 */
 	li	r3,SYSTEMCFG_PHYS_ADDR	/* r3 = ptr to systemcfg */
 	lwz	r3,PLATFORM(r3)		/* r3 = platform flags */
 	cmpldi 	r3,PLATFORM_PSERIES_LPAR
@@ -1938,13 +1969,7 @@
 98:					/* !(rpa hypervisor) || !(star) */
 	mtasr	r4			/* set the stab location	*/
 99:
-	mfspr	r6,SPRG3
-	ld	r3,PACASTABREAL(r6)	/* restore r3 for stab_initialize */
-
-	/* Initialize an initial memory mapping and turn on relocation.	*/
-	bl	.stab_initialize
-	bl	.htab_initialize
-
+	/* Set SDR1 (hash table pointer) */
 	li	r3,SYSTEMCFG_PHYS_ADDR	/* r3 = ptr to systemcfg */
 	lwz	r3,PLATFORM(r3)		/* r3 = platform flags */
 	/* Test if bit 0 is set (LPAR bit) */
@@ -1961,7 +1986,7 @@
 	mtspr	SRR1,r4
 	rfid
 	b	.	/* prevent speculative execution */
-#endif /* CONFIG_PPC_PSERIES */
+#endif /* CONFIG_PPC_MULTIPLATFORM */
 	
 	/* This is where all platforms converge execution */
 _STATIC(start_here_common)
@@ -2008,13 +2033,6 @@
 	/* Load the TOC */
 	ld	r2,PACATOC(r13)
 	std	r1,PACAKSAVE(r13)
-
-	/* Restore the parms passed in from the bootloader. */
-	mr	r3,r31
-	mr	r4,r30
-	mr	r5,r29
-	mr	r6,r28
-	mr	r7,r27
 
 	bl	.setup_system
 
diff -Nru a/arch/ppc64/kernel/hvconsole.c b/arch/ppc64/kernel/hvconsole.c
--- a/arch/ppc64/kernel/hvconsole.c	2004-10-18 14:56:32 -07:00
+++ b/arch/ppc64/kernel/hvconsole.c	2004-10-18 14:56:32 -07:00
@@ -1,6 +1,10 @@
 /*
  * hvconsole.c
  * Copyright (C) 2004 Hollis Blanchard, IBM Corporation
+ * Copyright (C) 2004 IBM Corporation
+ *
+ * Additional Author(s):
+ *  Ryan S. Arnold <rsa@us.ibm.com>
  *
  * LPAR console support.
  * 
@@ -22,14 +26,22 @@
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <asm/hvcall.h>
-#include <asm/prom.h>
 #include <asm/hvconsole.h>
+#include <asm/prom.h>
 
-int hvc_get_chars(int index, char *buf, int count)
+/**
+ * hvc_get_chars - retrieve characters from firmware for denoted vterm adatper
+ * @vtermno: The vtermno or unit_address of the adapter from which to fetch the
+ *	data.
+ * @buf: The character buffer into which to put the character data fetched from
+ *	firmware.
+ * @count: not used?
+ */
+int hvc_get_chars(uint32_t vtermno, char *buf, int count)
 {
 	unsigned long got;
 
-	if (plpar_hcall(H_GET_TERM_CHAR, index, 0, 0, 0, &got,
+	if (plpar_hcall(H_GET_TERM_CHAR, vtermno, 0, 0, 0, &got,
 		(unsigned long *)buf, (unsigned long *)buf+1) == H_Success) {
 		/*
 		 * Work around a HV bug where it gives us a null
@@ -53,40 +65,56 @@
 
 EXPORT_SYMBOL(hvc_get_chars);
 
-int hvc_put_chars(int index, const char *buf, int count)
+/**
+ * hvc_put_chars: send characters to firmware for denoted vterm adapter
+ * @vtermno: The vtermno or unit_address of the adapter from which the data
+ *	originated.
+ * @buf: The character buffer that contains the character data to send to
+ *	firmware.
+ * @count: Send this number of characters.
+ */
+int hvc_put_chars(uint32_t vtermno, const char *buf, int count)
 {
 	unsigned long *lbuf = (unsigned long *) buf;
 	long ret;
 
-	ret = plpar_hcall_norets(H_PUT_TERM_CHAR, index, count, lbuf[0],
+	ret = plpar_hcall_norets(H_PUT_TERM_CHAR, vtermno, count, lbuf[0],
 				 lbuf[1]);
 	if (ret == H_Success)
 		return count;
 	if (ret == H_Busy)
 		return 0;
-	return -1;
+	return -EIO;
 }
 
 EXPORT_SYMBOL(hvc_put_chars);
 
-/* return the number of client vterms present */
-/* XXX this requires an interface change to handle multiple discontiguous
- * vterms */
-int hvc_count(int *start_termno)
+/*
+ * We hope/assume that the first vty found corresponds to the first console
+ * device.
+ */
+int hvc_find_vtys(void)
 {
 	struct device_node *vty;
 	int num_found = 0;
 
-	/* consider only the first vty node.
-	 * we should _always_ be able to find one. */
-	vty = of_find_node_by_name(NULL, "vty");
-	if (vty && device_is_compatible(vty, "hvterm1")) {
-		u32 *termno = (u32 *)get_property(vty, "reg", NULL);
-
-		if (termno && start_termno)
-			*start_termno = *termno;
-		num_found = 1;
-		of_node_put(vty);
+	for (vty = of_find_node_by_name(NULL, "vty"); vty != NULL;
+			vty = of_find_node_by_name(vty, "vty")) {
+		uint32_t *vtermno;
+
+		/* We have statically defined space for only a certain number of
+		 * console adapters. */
+		if (num_found >= MAX_NR_HVC_CONSOLES)
+			break;
+
+		vtermno = (uint32_t *)get_property(vty, "reg", NULL);
+		if (!vtermno)
+			continue;
+
+		if (device_is_compatible(vty, "hvterm1")) {
+			hvc_instantiate(*vtermno, num_found);
+			++num_found;
+		}
 	}
 
 	return num_found;
diff -Nru a/arch/ppc64/kernel/hvcserver.c b/arch/ppc64/kernel/hvcserver.c
--- a/arch/ppc64/kernel/hvcserver.c	2004-10-18 14:56:33 -07:00
+++ b/arch/ppc64/kernel/hvcserver.c	2004-10-18 14:56:33 -07:00
@@ -61,14 +61,21 @@
 	}
 }
 
+/**
+ * hvcs_free_partner_info - free pi allocated by hvcs_get_partner_info
+ * @head: list_head pointer for an allocated list of partner info structs to
+ *	free.
+ *
+ * This function is used to free the partner info list that was returned by
+ * calling hvcs_get_partner_info().
+ */
 int hvcs_free_partner_info(struct list_head *head)
 {
 	struct hvcs_partner_info *pi;
 	struct list_head *element;
 
-	if (!head) {
+	if (!head)
 		return -EINVAL;
-	}
 
 	while (!list_empty(head)) {
 		element = head->next;
@@ -82,7 +89,7 @@
 EXPORT_SYMBOL(hvcs_free_partner_info);
 
 /* Helper function for hvcs_get_partner_info */
-int hvcs_next_partner(unsigned int unit_address,
+int hvcs_next_partner(uint32_t unit_address,
 		unsigned long last_p_partition_ID,
 		unsigned long last_p_unit_address, unsigned long *pi_buff)
 
@@ -94,25 +101,37 @@
 	return hvcs_convert(retval);
 }
 
-/*
- * The unit_address parameter is the unit address of the vty-server vdevice
- * in whose partner information the caller is interested.  This function
- * uses a pointer to a list_head instance in which to store the partner info.
+/**
+ * hvcs_get_partner_info - Get all of the partner info for a vty-server adapter
+ * @unit_address: The unit_address of the vty-server adapter for which this
+ *	function is fetching partner info.
+ * @head: An initialized list_head pointer to an empty list to use to return the
+ *	list of partner info fetched from the hypervisor to the caller.
+ * @pi_buff: A page sized buffer pre-allocated prior to calling this function
+ *	that is to be used to be used by firmware as an iterator to keep track
+ *	of the partner info retrieval.
+ *
  * This function returns non-zero on success, or if there is no partner info.
  *
+ * The pi_buff is pre-allocated prior to calling this function because this
+ * function may be called with a spin_lock held and kmalloc of a page is not
+ * recommended as GFP_ATOMIC.
+ *
+ * The first long of this buffer is used to store a partner unit address.  The
+ * second long is used to store a partner partition ID and starting at
+ * pi_buff[2] is the 79 character Converged Location Code (diff size than the
+ * unsigned longs, hence the casting mumbo jumbo you see later).
+ *
  * Invocation of this function should always be followed by an invocation of
  * hvcs_free_partner_info() using a pointer to the SAME list head instance
- * that was used to store the partner_info list.
+ * that was passed as a parameter to this function.
  */
-int hvcs_get_partner_info(unsigned int unit_address, struct list_head *head,
+int hvcs_get_partner_info(uint32_t unit_address, struct list_head *head,
 		unsigned long *pi_buff)
 {
 	/*
-	 * This is a page sized buffer to be passed to hvcall per invocation.
-	 * NOTE: the first long returned is unit_address.  The second long
-	 * returned is the partition ID and starting with pi_buff[2] are
-	 * HVCS_CLC_LENGTH characters, which are diff size than the unsigned
-	 * long, hence the casting mumbojumbo you see later.
+	 * Dealt with as longs because of the hcall interface even though the
+	 * values are uint32_t.
 	 */
 	unsigned long	last_p_partition_ID;
 	unsigned long	last_p_unit_address;
@@ -122,15 +141,12 @@
 
 	memset(pi_buff, 0x00, PAGE_SIZE);
 	/* invalid parameters */
-	if (!head)
+	if (!head || !pi_buff)
 		return -EINVAL;
 
 	last_p_partition_ID = last_p_unit_address = ~0UL;
 	INIT_LIST_HEAD(head);
 
-	if (!pi_buff)
-		return -ENOMEM;
-
 	do {
 		retval = hvcs_next_partner(unit_address, last_p_partition_ID,
 				last_p_unit_address, pi_buff);
@@ -183,21 +199,29 @@
 }
 EXPORT_SYMBOL(hvcs_get_partner_info);
 
-/*
+/**
+ * hvcs_register_connection - establish a connection between this vty-server and
+ *	a vty.
+ * @unit_address: The unit address of the vty-server adapter that is to be
+ *	establish a connection.
+ * @p_partition_ID: The partition ID of the vty adapter that is to be connected.
+ * @p_unit_address: The unit address of the vty adapter to which the vty-server
+ *	is to be connected.
+ *
  * If this function is called once and -EINVAL is returned it may
  * indicate that the partner info needs to be refreshed for the
  * target unit address at which point the caller must invoke
  * hvcs_get_partner_info() and then call this function again.  If,
  * for a second time, -EINVAL is returned then it indicates that
  * there is probably already a partner connection registered to a
- * different vty-server@ vdevice.  It is also possible that a second
+ * different vty-server adapter.  It is also possible that a second
  * -EINVAL may indicate that one of the parms is not valid, for
- * instance if the link was removed between the vty-server@ vdevice
- * and the vty@ vdevice that you are trying to open.  Don't shoot the
+ * instance if the link was removed between the vty-server adapter
+ * and the vty adapter that you are trying to open.  Don't shoot the
  * messenger.  Firmware implemented it this way.
  */
-int hvcs_register_connection( unsigned int unit_address,
-		unsigned int p_partition_ID, unsigned int p_unit_address)
+int hvcs_register_connection( uint32_t unit_address,
+		uint32_t p_partition_ID, uint32_t p_unit_address)
 {
 	long retval;
 	retval = plpar_hcall_norets(H_REGISTER_VTERM, unit_address,
@@ -206,11 +230,17 @@
 }
 EXPORT_SYMBOL(hvcs_register_connection);
 
-/*
- * If -EBUSY is returned continue to call this function
- * until 0 is returned.
+/**
+ * hvcs_free_connection - free the connection between a vty-server and vty
+ * @unit_address: The unit address of the vty-server that is to have its
+ *	connection severed.
+ *
+ * This function is used to free the partner connection between a vty-server
+ * adapter and a vty adapter.
+ *
+ * If -EBUSY is returned continue to call this function until 0 is returned.
  */
-int hvcs_free_connection(unsigned int unit_address)
+int hvcs_free_connection(uint32_t unit_address)
 {
 	long retval;
 	retval = plpar_hcall_norets(H_FREE_VTERM, unit_address);
diff -Nru a/arch/ppc64/kernel/iSeries_htab.c b/arch/ppc64/kernel/iSeries_htab.c
--- a/arch/ppc64/kernel/iSeries_htab.c	2004-10-18 14:56:29 -07:00
+++ b/arch/ppc64/kernel/iSeries_htab.c	2004-10-18 14:56:29 -07:00
@@ -233,4 +233,6 @@
 	ppc_md.hpte_updateboltedpp = iSeries_hpte_updateboltedpp;
 	ppc_md.hpte_insert	= iSeries_hpte_insert;
 	ppc_md.hpte_remove     	= iSeries_hpte_remove;
+
+	htab_finish_init();
 }
diff -Nru a/arch/ppc64/kernel/iSeries_pci.c b/arch/ppc64/kernel/iSeries_pci.c
--- a/arch/ppc64/kernel/iSeries_pci.c	2004-10-18 14:57:04 -07:00
+++ b/arch/ppc64/kernel/iSeries_pci.c	2004-10-18 14:57:04 -07:00
@@ -419,46 +419,39 @@
  * I/0 Memory copy MUST use mmio commands on iSeries
  * To do; For performance, include the hv call directly
  */
-void *iSeries_memset_io(void *dest, char c, size_t Count)
+void iSeries_memset_io(volatile void __iomem *dest, char c, size_t Count)
 {
 	u8 ByteValue = c;
 	long NumberOfBytes = Count;
-	char *IoBuffer = dest;
 
 	while (NumberOfBytes > 0) {
-		iSeries_Write_Byte(ByteValue, (void *)IoBuffer);
-		++IoBuffer;
+		iSeries_Write_Byte(ByteValue, dest++);
 		-- NumberOfBytes;
 	}
-	return dest;
 }
 EXPORT_SYMBOL(iSeries_memset_io);
 
-void *iSeries_memcpy_toio(void *dest, void *source, size_t count)
+void iSeries_memcpy_toio(volatile void __iomem *dest, void *source, size_t count)
 {
-	char *dst = dest;
 	char *src = source;
 	long NumberOfBytes = count;
 
 	while (NumberOfBytes > 0) {
-		iSeries_Write_Byte(*src++, (void *)dst++);
+		iSeries_Write_Byte(*src++, dest++);
 		-- NumberOfBytes;
 	}
-	return dest;
 }
 EXPORT_SYMBOL(iSeries_memcpy_toio);
 
-void *iSeries_memcpy_fromio(void *dest, void *source, size_t count)
+void iSeries_memcpy_fromio(void *dest, const volatile void __iomem *src, size_t count)
 {
 	char *dst = dest;
-	char *src = source;
 	long NumberOfBytes = count;
 
 	while (NumberOfBytes > 0) {
-		*dst++ = iSeries_Read_Byte((void *)src++);
+		*dst++ = iSeries_Read_Byte(src++);
 		-- NumberOfBytes;
 	}
-	return dest;
 }
 EXPORT_SYMBOL(iSeries_memcpy_fromio);
 
@@ -612,17 +605,19 @@
  * Note: Make sure the passed variable end up on the stack to avoid
  * the exposure of being device global.
  */
-static inline struct iSeries_Device_Node *xlateIoMmAddress(void *IoAddress,
+static inline struct iSeries_Device_Node *xlateIoMmAddress(const volatile void __iomem *IoAddress,
 		 u64 *dsaptr, u64 *BarOffsetPtr)
 {
+	unsigned long OrigIoAddr;
 	unsigned long BaseIoAddr;
 	unsigned long TableIndex;
 	struct iSeries_Device_Node *DevNode;
 
-	if (((unsigned long)IoAddress < iSeries_Base_Io_Memory) ||
-			((unsigned long)IoAddress >= iSeries_Max_Io_Memory))
+	OrigIoAddr = (unsigned long __force)IoAddress;
+	if ((OrigIoAddr < iSeries_Base_Io_Memory) ||
+			(OrigIoAddr >= iSeries_Max_Io_Memory))
 		return NULL;
-	BaseIoAddr = (unsigned long)IoAddress - iSeries_Base_Io_Memory;
+	BaseIoAddr = OrigIoAddr - iSeries_Base_Io_Memory;
 	TableIndex = BaseIoAddr / iSeries_IoMmTable_Entry_Size;
 	DevNode = iSeries_IoMmTable[TableIndex];
 
@@ -644,7 +639,7 @@
  * iSeries_Read_Word = Read Word  (16 bit)
  * iSeries_Read_Long = Read Long  (32 bit)
  */
-u8 iSeries_Read_Byte(void *IoAddress)
+u8 iSeries_Read_Byte(const volatile void __iomem *IoAddress)
 {
 	u64 BarOffset;
 	u64 dsa;
@@ -673,7 +668,7 @@
 }
 EXPORT_SYMBOL(iSeries_Read_Byte);
 
-u16 iSeries_Read_Word(void *IoAddress)
+u16 iSeries_Read_Word(const volatile void __iomem *IoAddress)
 {
 	u64 BarOffset;
 	u64 dsa;
@@ -703,7 +698,7 @@
 }
 EXPORT_SYMBOL(iSeries_Read_Word);
 
-u32 iSeries_Read_Long(void *IoAddress)
+u32 iSeries_Read_Long(const volatile void __iomem *IoAddress)
 {
 	u64 BarOffset;
 	u64 dsa;
@@ -740,7 +735,7 @@
  * iSeries_Write_Word = Write Word(16 bit)
  * iSeries_Write_Long = Write Long(32 bit)
  */
-void iSeries_Write_Byte(u8 data, void *IoAddress)
+void iSeries_Write_Byte(u8 data, volatile void __iomem *IoAddress)
 {
 	u64 BarOffset;
 	u64 dsa;
@@ -767,7 +762,7 @@
 }
 EXPORT_SYMBOL(iSeries_Write_Byte);
 
-void iSeries_Write_Word(u16 data, void *IoAddress)
+void iSeries_Write_Word(u16 data, volatile void __iomem *IoAddress)
 {
 	u64 BarOffset;
 	u64 dsa;
@@ -794,7 +789,7 @@
 }
 EXPORT_SYMBOL(iSeries_Write_Word);
 
-void iSeries_Write_Long(u32 data, void *IoAddress)
+void iSeries_Write_Long(u32 data, volatile void __iomem *IoAddress)
 {
 	u64 BarOffset;
 	u64 dsa;
@@ -820,7 +815,3 @@
 	} while (CheckReturnCode("WWL", DevNode, rc) != 0);
 }
 EXPORT_SYMBOL(iSeries_Write_Long);
-
-void pcibios_name_device(struct pci_dev *dev)
-{
-}
diff -Nru a/arch/ppc64/kernel/iSeries_pci_reset.c b/arch/ppc64/kernel/iSeries_pci_reset.c
--- a/arch/ppc64/kernel/iSeries_pci_reset.c	2004-10-18 14:56:49 -07:00
+++ b/arch/ppc64/kernel/iSeries_pci_reset.c	2004-10-18 14:56:49 -07:00
@@ -65,7 +65,8 @@
 		AssertDelay = (5 * HZ) / 10;
 	else
 		AssertDelay = (AssertTime * HZ) / 10;
-	if (WaitDelay == 0)
+
+	if (DelayTime == 0)
 		WaitDelay = (30 * HZ) / 10;
 	else
 		WaitDelay = (DelayTime * HZ) / 10;
diff -Nru a/arch/ppc64/kernel/iSeries_setup.c b/arch/ppc64/kernel/iSeries_setup.c
--- a/arch/ppc64/kernel/iSeries_setup.c	2004-10-18 14:56:49 -07:00
+++ b/arch/ppc64/kernel/iSeries_setup.c	2004-10-18 14:56:49 -07:00
@@ -16,6 +16,8 @@
  *      2 of the License, or (at your option) any later version.
  */
  
+#undef DEBUG
+
 #include <linux/config.h>
 #include <linux/init.h>
 #include <linux/threads.h>
@@ -36,6 +38,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"
@@ -53,18 +56,21 @@
 #include <asm/iSeries/iSeries_proc.h>
 #include <asm/iSeries/mf.h>
 
+extern void hvlog(char *fmt, ...);
+
+#ifdef DEBUG
+#define DBG(fmt...) hvlog(fmt)
+#else
+#define DBG(fmt...)
+#endif
+
 /* 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 +83,8 @@
 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;
@@ -285,8 +283,28 @@
 	return mem_blocks;
 }
 
-void __init iSeries_init_early(void)
+static void __init iSeries_parse_cmdline(void)
+{
+	char *p, *q;
+
+	/* copy the command line parameter from the primary VSP  */
+	HvCallEvent_dmaToSp(cmd_line, 2 * 64* 1024, 256,
+			HvLpDma_Direction_RemoteToLocal);
+
+	p = cmd_line;
+	q = cmd_line + 255;
+	while(p < q) {
+		if (!*p || *p == '\n')
+			break;
+		++p;
+	}
+	*p = 0;
+}
+
+/*static*/ void __init iSeries_init_early(void)
 {
+	DBG(" -> iSeries_init_early()\n");
+
 	ppcdbg_initialize();
 
 #if defined(CONFIG_BLK_DEV_INITRD)
@@ -310,25 +328,20 @@
 	iSeries_recal_tb = get_tb();
 	iSeries_recal_titan = HvCallXm_loadTod();
 
-	ppc_md.setup_arch = iSeries_setup_arch;
-	ppc_md.get_cpuinfo = iSeries_get_cpuinfo;
-	ppc_md.init_IRQ = iSeries_init_IRQ;
-	ppc_md.get_irq = iSeries_get_irq;
-	ppc_md.init = NULL;
-
-	ppc_md.pcibios_fixup  = iSeries_pci_final_fixup;
-
-	ppc_md.restart = iSeries_restart;
-	ppc_md.power_off = iSeries_power_off;
-	ppc_md.halt = iSeries_halt;
-
-	ppc_md.get_boot_time = iSeries_get_boot_time;
-	ppc_md.set_rtc_time = iSeries_set_rtc_time;
-	ppc_md.get_rtc_time = iSeries_get_rtc_time;
-	ppc_md.calibrate_decr = iSeries_calibrate_decr;
-	ppc_md.progress = iSeries_progress;
+	/*
+	 * Cache sizes must be initialized before hpte_init_iSeries is called
+	 * as the later need them for flush_icache_range()
+	 */
+	setup_iSeries_cache_sizes();
 
+	/*
+	 * Initialize the hash table management pointers
+	 */
 	hpte_init_iSeries();
+
+	/*
+	 * Initialize the DMA/TCE management
+	 */
 	tce_init_iSeries();
 
 	/*
@@ -336,63 +349,36 @@
 	 * AS/400 absolute addresses
 	 */
 	build_iSeries_Memory_Map();
-	setup_iSeries_cache_sizes();
+
 	/* Initialize machine-dependency vectors */
 #ifdef CONFIG_SMP
 	smp_init_iSeries();
 #endif
 	if (itLpNaca.xPirEnvironMode == 0) 
 		piranha_simulator = 1;
-}
-
-void __init iSeries_init(unsigned long r3, unsigned long r4, unsigned long r5, 
-	   unsigned long r6, unsigned long r7)
-{
-	char *p, *q;
 
 	/* Associate Lp Event Queue 0 with processor 0 */
 	HvCallEvent_setLpEventQueueInterruptProc(0, 0);
 
-	/* copy the command line parameter from the primary VSP  */
-	HvCallEvent_dmaToSp(cmd_line, 2 * 64* 1024, 256,
-			HvLpDma_Direction_RemoteToLocal);
+	mf_init();
+	mf_initialized = 1;
+	mb();
 
-	p = cmd_line;
-	q = cmd_line + 255;
-	while( p < q ) {
-		if (!*p || *p == '\n')
-			break;
-		++p;
-	}
-	*p = 0;
+	/* If we were passed an initrd, set the ROOT_DEV properly if the values
+	 * look sensible. If not, clear initrd reference.
+	 */
+#ifdef CONFIG_BLK_DEV_INITRD
+	if (initrd_start >= KERNELBASE && initrd_end >= KERNELBASE &&
+	    initrd_end > initrd_start)
+		ROOT_DEV = Root_RAM0;
+	else
+		initrd_start = initrd_end = 0;
+#endif /* CONFIG_BLK_DEV_INITRD */
 
-        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();
+	iSeries_parse_cmdline();
 
-	mf_init();
-	mf_initialized = 1;
-	mb();
+	DBG(" <- iSeries_init_early()\n");
 }
 
 /*
@@ -816,7 +802,7 @@
 	}
 }
 
-void iSeries_fixup_klimit(void)
+static void __init iSeries_fixup_klimit(void)
 {
 	/*
 	 * Change klimit to take into account any ram disk
@@ -837,22 +823,6 @@
 	}
 }
 
-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;
-		}
-	}
-}
-
 int __init iSeries_src_init(void)
 {
         /* clear the progress line */
@@ -861,3 +831,27 @@
 }
 
 late_initcall(iSeries_src_init);
+
+void __init iSeries_early_setup(void)
+{
+	iSeries_fixup_klimit();
+
+	ppc_md.setup_arch = iSeries_setup_arch;
+	ppc_md.get_cpuinfo = iSeries_get_cpuinfo;
+	ppc_md.init_IRQ = iSeries_init_IRQ;
+	ppc_md.get_irq = iSeries_get_irq;
+	ppc_md.init_early = iSeries_init_early,
+
+	ppc_md.pcibios_fixup  = iSeries_pci_final_fixup;
+
+	ppc_md.restart = iSeries_restart;
+	ppc_md.power_off = iSeries_power_off;
+	ppc_md.halt = iSeries_halt;
+
+	ppc_md.get_boot_time = iSeries_get_boot_time;
+	ppc_md.set_rtc_time = iSeries_set_rtc_time;
+	ppc_md.get_rtc_time = iSeries_get_rtc_time;
+	ppc_md.calibrate_decr = iSeries_calibrate_decr;
+	ppc_md.progress = iSeries_progress;
+}
+
diff -Nru a/arch/ppc64/kernel/iSeries_setup.h b/arch/ppc64/kernel/iSeries_setup.h
--- a/arch/ppc64/kernel/iSeries_setup.h	2004-10-18 14:56:49 -07:00
+++ b/arch/ppc64/kernel/iSeries_setup.h	2004-10-18 14:56:49 -07:00
@@ -19,10 +19,6 @@
 #ifndef	__ISERIES_SETUP_H__
 #define	__ISERIES_SETUP_H__
 
-extern void iSeries_init_early(void);
-extern void iSeries_init(unsigned long r3, unsigned long ird_start,
-		unsigned long ird_end, unsigned long cline_start,
-		unsigned long cline_end);
 extern void iSeries_setup_arch(void);
 extern void iSeries_setup_residual(struct seq_file *m, int cpu_id);
 extern void iSeries_get_cpuinfo(struct seq_file *m);
diff -Nru a/arch/ppc64/kernel/idle.c b/arch/ppc64/kernel/idle.c
--- a/arch/ppc64/kernel/idle.c	2004-10-18 14:56:49 -07:00
+++ b/arch/ppc64/kernel/idle.c	2004-10-18 14:56:49 -07:00
@@ -16,40 +16,29 @@
  */
 
 #include <linux/config.h>
-#include <linux/errno.h>
 #include <linux/sched.h>
 #include <linux/kernel.h>
-#include <linux/mm.h>
 #include <linux/smp.h>
-#include <linux/smp_lock.h>
-#include <linux/stddef.h>
-#include <linux/unistd.h>
-#include <linux/slab.h>
-#include <linux/interrupt.h>
 #include <linux/cpu.h>
+#include <linux/module.h>
+#include <linux/sysctl.h>
 
-#include <asm/pgtable.h>
-#include <asm/uaccess.h>
 #include <asm/system.h>
-#include <asm/io.h>
 #include <asm/processor.h>
 #include <asm/mmu.h>
-#include <asm/cache.h>
 #include <asm/cputable.h>
 #include <asm/time.h>
-#include <asm/iSeries/LparData.h>
 #include <asm/iSeries/HvCall.h>
 #include <asm/iSeries/ItLpQueue.h>
+#include <asm/plpar_wrappers.h>
 
-extern long cede_processor(void);
-extern long poll_pending(void);
 extern void power4_idle(void);
 
-int (*idle_loop)(void);
+static int (*idle_loop)(void);
 
 #ifdef CONFIG_PPC_ISERIES
-unsigned long maxYieldTime = 0;
-unsigned long minYieldTime = 0xffffffffffffffffUL;
+static unsigned long maxYieldTime = 0;
+static unsigned long minYieldTime = 0xffffffffffffffffUL;
 
 static void yield_shared_processor(void)
 {
@@ -80,7 +69,7 @@
 	process_iSeries_events();
 }
 
-int iSeries_idle(void)
+static int iSeries_idle(void)
 {
 	struct paca_struct *lpaca;
 	long oldval;
@@ -91,13 +80,10 @@
 	CTRL = mfspr(CTRLF);
 	CTRL &= ~RUNLATCH;
 	mtspr(CTRLT, CTRL);
-#if 0
-	init_idle();	
-#endif
 
 	lpaca = get_paca();
 
-	for (;;) {
+	while (1) {
 		if (lpaca->lppaca.xSharedProc) {
 			if (ItLpQueue_isLpIntPending(lpaca->lpqueue_ptr))
 				process_iSeries_events();
@@ -125,13 +111,16 @@
 
 		schedule();
 	}
+
 	return 0;
 }
-#endif
 
-int default_idle(void)
+#else
+
+static int default_idle(void)
 {
 	long oldval;
+	unsigned int cpu = smp_processor_id();
 
 	while (1) {
 		oldval = test_and_clear_thread_flag(TIF_NEED_RESCHED);
@@ -139,9 +128,14 @@
 		if (!oldval) {
 			set_thread_flag(TIF_POLLING_NRFLAG);
 
-			while (!need_resched()) {
+			while (!need_resched() && !cpu_is_offline(cpu)) {
 				barrier();
+				/*
+				 * Go into low thread priority and possibly
+				 * low power mode.
+				 */
 				HMT_low();
+				HMT_very_low();
 			}
 
 			HMT_medium();
@@ -151,8 +145,7 @@
 		}
 
 		schedule();
-		if (cpu_is_offline(smp_processor_id()) &&
-				system_state == SYSTEM_RUNNING)
+		if (cpu_is_offline(cpu) && system_state == SYSTEM_RUNNING)
 			cpu_die();
 	}
 
@@ -169,12 +162,15 @@
 	struct paca_struct *lpaca = get_paca(), *ppaca;
 	unsigned long start_snooze;
 	unsigned long *smt_snooze_delay = &__get_cpu_var(smt_snooze_delay);
+	unsigned int cpu = smp_processor_id();
 
-	ppaca = &paca[smp_processor_id() ^ 1];
+	ppaca = &paca[cpu ^ 1];
 
 	while (1) {
-		/* Indicate to the HV that we are idle.  Now would be
-		 * a good time to find other work to dispatch. */
+		/*
+		 * Indicate to the HV that we are idle. Now would be
+		 * a good time to find other work to dispatch.
+		 */
 		lpaca->lppaca.xIdle = 1;
 
 		oldval = test_and_clear_thread_flag(TIF_NEED_RESCHED);
@@ -182,42 +178,32 @@
 			set_thread_flag(TIF_POLLING_NRFLAG);
 			start_snooze = __get_tb() +
 				*smt_snooze_delay * tb_ticks_per_usec;
-			while (!need_resched()) {
-				/* need_resched could be 1 or 0 at this 
-				 * point.  If it is 0, set it to 0, so
-				 * an IPI/Prod is sent.  If it is 1, keep
-				 * it that way & schedule work.
+			while (!need_resched() && !cpu_is_offline(cpu)) {
+				/*
+				 * Go into low thread priority and possibly
+				 * low power mode.
 				 */
+				HMT_low();
+				HMT_very_low();
+
 				if (*smt_snooze_delay == 0 ||
-				    __get_tb() < start_snooze) {
-					HMT_low(); /* Low thread priority */
+				    __get_tb() < start_snooze)
 					continue;
-				}
 
-				HMT_very_low(); /* Low power mode */
+				HMT_medium();
 
-				/* If the SMT mode is system controlled & the 
-				 * partner thread is doing work, switch into
-				 * ST mode.
-				 */
-				if((naca->smt_state == SMT_DYNAMIC) &&
-				   (!(ppaca->lppaca.xIdle))) {
-					/* Indicate we are no longer polling for
-					 * work, and then clear need_resched.  If
-					 * need_resched was 1, set it back to 1
-					 * and schedule work
+				if (!(ppaca->lppaca.xIdle)) {
+					local_irq_disable();
+
+					/*
+					 * We are about to sleep the thread
+					 * and so wont be polling any
+					 * more.
 					 */
 					clear_thread_flag(TIF_POLLING_NRFLAG);
-					oldval = test_and_clear_thread_flag(TIF_NEED_RESCHED);
-					if(oldval == 1) {
-						set_need_resched();
-						break;
-					}
 
-					/* DRENG: Go HMT_medium here ? */
-					local_irq_disable(); 
-
-					/* SMT dynamic mode.  Cede will result 
+					/*
+					 * SMT dynamic mode. Cede will result
 					 * in this thread going dormant, if the
 					 * partner thread is still doing work.
 					 * Thread wakes up if partner goes idle,
@@ -225,15 +211,21 @@
 					 * occurs.  Returning from the cede
 					 * enables external interrupts.
 					 */
-					cede_processor();
+					if (!need_resched())
+						cede_processor();
+					else
+						local_irq_enable();
 				} else {
-					/* Give the HV an opportunity at the
+					/*
+					 * Give the HV an opportunity at the
 					 * processor, since we are not doing
 					 * any work.
 					 */
 					poll_pending();
 				}
 			}
+
+			clear_thread_flag(TIF_POLLING_NRFLAG);
 		} else {
 			set_need_resched();
 		}
@@ -241,57 +233,60 @@
 		HMT_medium();
 		lpaca->lppaca.xIdle = 0;
 		schedule();
-		if (cpu_is_offline(smp_processor_id()) &&
-				system_state == SYSTEM_RUNNING)
+		if (cpu_is_offline(cpu) && system_state == SYSTEM_RUNNING)
 			cpu_die();
 	}
 	return 0;
 }
 
-int shared_idle(void)
+static int shared_idle(void)
 {
 	struct paca_struct *lpaca = get_paca();
+	unsigned int cpu = smp_processor_id();
 
 	while (1) {
-		if (cpu_is_offline(smp_processor_id()) &&
-				system_state == SYSTEM_RUNNING)
-			cpu_die();
-
-		/* Indicate to the HV that we are idle.  Now would be
-		 * a good time to find other work to dispatch. */
+		/*
+		 * Indicate to the HV that we are idle. Now would be
+		 * a good time to find other work to dispatch.
+		 */
 		lpaca->lppaca.xIdle = 1;
 
-		if (!need_resched()) {
-			local_irq_disable(); 
-			
-			/* 
+		while (!need_resched() && !cpu_is_offline(cpu)) {
+			local_irq_disable();
+
+			/*
 			 * Yield the processor to the hypervisor.  We return if
 			 * an external interrupt occurs (which are driven prior
 			 * to returning here) or if a prod occurs from another 
-			 * processor.  When returning here, external interrupts 
+			 * processor. When returning here, external interrupts
 			 * are enabled.
+			 *
+			 * Check need_resched() again with interrupts disabled
+			 * to avoid a race.
 			 */
-			cede_processor();
+			if (!need_resched())
+				cede_processor();
+			else
+				local_irq_enable();
 		}
 
 		HMT_medium();
 		lpaca->lppaca.xIdle = 0;
 		schedule();
+		if (cpu_is_offline(smp_processor_id()) &&
+		    system_state == SYSTEM_RUNNING)
+			cpu_die();
 	}
 
 	return 0;
 }
-#endif
 
-int cpu_idle(void)
-{
-	idle_loop();
-	return 0; 
-}
+#endif /* CONFIG_PPC_PSERIES */
 
-int native_idle(void)
+static int native_idle(void)
 {
 	while(1) {
+		/* check CPU type here */
 		if (!need_resched())
 			power4_idle();
 		if (need_resched())
@@ -300,33 +295,80 @@
 	return 0;
 }
 
+#endif /* CONFIG_PPC_ISERIES */
+
+int cpu_idle(void)
+{
+	idle_loop();
+	return 0;
+}
+
+int powersave_nap;
+
+#ifdef CONFIG_SYSCTL
+/*
+ * Register the sysctl to set/clear 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
+
 int idle_setup(void)
 {
+	/*
+	 * Move that junk to each platform specific file, eventually define
+	 * a pSeries_idle for shared processor stuff
+	 */
 #ifdef CONFIG_PPC_ISERIES
 	idle_loop = iSeries_idle;
+	return 1;
 #else
+	idle_loop = default_idle;
+#endif
+#ifdef CONFIG_PPC_PSERIES
 	if (systemcfg->platform & PLATFORM_PSERIES) {
 		if (cur_cpu_spec->firmware_features & FW_FEATURE_SPLPAR) {
 			if (get_paca()->lppaca.xSharedProc) {
-				printk("idle = shared_idle\n");
+				printk(KERN_INFO "Using shared processor idle loop\n");
 				idle_loop = shared_idle;
 			} else {
-				printk("idle = dedicated_idle\n");
+				printk(KERN_INFO "Using dedicated idle loop\n");
 				idle_loop = dedicated_idle;
 			}
 		} else {
-			printk("idle = default_idle\n");
+			printk(KERN_INFO "Using default idle loop\n");
 			idle_loop = default_idle;
 		}
-	} else if (systemcfg->platform == PLATFORM_POWERMAC) {
-		printk("idle = native_idle\n");
+	}
+#endif /* CONFIG_PPC_PSERIES */
+#ifdef CONFIG_PPC_PMAC
+	if (systemcfg->platform == PLATFORM_POWERMAC) {
+		printk(KERN_INFO "Using native/NAP idle loop\n");
 		idle_loop = native_idle;
-	} else {
-		printk("idle_setup: unknown platform, use default_idle\n");
-		idle_loop = default_idle;
 	}
-#endif
+#endif /* CONFIG_PPC_PMAC */
 
 	return 1;
 }
-
diff -Nru a/arch/ppc64/kernel/idle_power4.S b/arch/ppc64/kernel/idle_power4.S
--- a/arch/ppc64/kernel/idle_power4.S	2004-10-18 14:56:32 -07:00
+++ b/arch/ppc64/kernel/idle_power4.S	2004-10-18 14:56:32 -07:00
@@ -46,7 +46,7 @@
 	/* Now check if user or arch enabled NAP mode */
 	LOADBASE(r3,powersave_nap)
 	lwz	r4,powersave_nap@l(r3)
-	cmpi	0,r4,0
+	cmpwi	0,r4,0
 	beqlr
 
 	/* Clear MSR:EE */
diff -Nru a/arch/ppc64/kernel/ioctl32.c b/arch/ppc64/kernel/ioctl32.c
--- a/arch/ppc64/kernel/ioctl32.c	2004-10-18 14:57:05 -07:00
+++ b/arch/ppc64/kernel/ioctl32.c	2004-10-18 14:57:05 -07:00
@@ -22,9 +22,7 @@
 
 #define INCLUDES
 #include "compat_ioctl.c"
-#include <linux/ncp_fs.h>
 #include <linux/syscalls.h>
-#include <asm/ppc32.h>
 
 #define CODE
 #include "compat_ioctl.c"
diff -Nru a/arch/ppc64/kernel/iomap.c b/arch/ppc64/kernel/iomap.c
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/arch/ppc64/kernel/iomap.c	2004-10-18 14:57:23 -07:00
@@ -0,0 +1,119 @@
+#include <linux/init.h>
+#include <linux/pci.h>
+#include <linux/mm.h>
+#include <asm/io.h>
+
+/*
+ * Here comes the ppc64 implementation of the IOMAP 
+ * interfaces.
+ */
+unsigned int fastcall ioread8(void __iomem *addr)
+{
+	return readb(addr);
+}
+unsigned int fastcall ioread16(void __iomem *addr)
+{
+	return readw(addr);
+}
+unsigned int fastcall ioread32(void __iomem *addr)
+{
+	return readl(addr);
+}
+EXPORT_SYMBOL(ioread8);
+EXPORT_SYMBOL(ioread16);
+EXPORT_SYMBOL(ioread32);
+
+void fastcall iowrite8(u8 val, void __iomem *addr)
+{
+	writeb(val, addr);
+}
+void fastcall iowrite16(u16 val, void __iomem *addr)
+{
+	writew(val, addr);
+}
+void fastcall iowrite32(u32 val, void __iomem *addr)
+{
+	writel(val, addr);
+}
+EXPORT_SYMBOL(iowrite8);
+EXPORT_SYMBOL(iowrite16);
+EXPORT_SYMBOL(iowrite32);
+
+/*
+ * These are the "repeat read/write" functions. Note the
+ * non-CPU byte order. We do things in "IO byteorder"
+ * here.
+ *
+ * FIXME! We could make these do EEH handling if we really
+ * wanted. Not clear if we do.
+ */
+void ioread8_rep(void __iomem *addr, void *dst, unsigned long count)
+{
+	_insb((u8 __force *) addr, dst, count);
+}
+void ioread16_rep(void __iomem *addr, void *dst, unsigned long count)
+{
+	_insw_ns((u16 __force *) addr, dst, count);
+}
+void ioread32_rep(void __iomem *addr, void *dst, unsigned long count)
+{
+	_insl_ns((u32 __force *) addr, dst, count);
+}
+EXPORT_SYMBOL(ioread8_rep);
+EXPORT_SYMBOL(ioread16_rep);
+EXPORT_SYMBOL(ioread32_rep);
+
+void iowrite8_rep(void __iomem *addr, const void *src, unsigned long count)
+{
+	_outsb((u8 __force *) addr, src, count);
+}
+void iowrite16_rep(void __iomem *addr, const void *src, unsigned long count)
+{
+	_outsw_ns((u16 __force *) addr, src, count);
+}
+void iowrite32_rep(void __iomem *addr, const void *src, unsigned long count)
+{
+	_outsl_ns((u32 __force *) addr, src, count);
+}
+EXPORT_SYMBOL(iowrite8_rep);
+EXPORT_SYMBOL(iowrite16_rep);
+EXPORT_SYMBOL(iowrite32_rep);
+
+void __iomem *ioport_map(unsigned long port, unsigned int len)
+{
+	if (!_IO_IS_VALID(port))
+		return NULL;
+	return (void __iomem *) (port+pci_io_base);
+}
+
+void ioport_unmap(void __iomem *addr)
+{
+	/* Nothing to do */
+}
+EXPORT_SYMBOL(ioport_map);
+EXPORT_SYMBOL(ioport_unmap);
+
+void __iomem *pci_iomap(struct pci_dev *dev, int bar, unsigned long max)
+{
+	unsigned long start = pci_resource_start(dev, bar);
+	unsigned long len = pci_resource_len(dev, bar);
+	unsigned long flags = pci_resource_flags(dev, bar);
+
+	if (!len)
+		return NULL;
+	if (max && len > max)
+		len = max;
+	if (flags & IORESOURCE_IO)
+		return ioport_map(start, len);
+	if (flags & IORESOURCE_MEM)
+		return (void __iomem *) start;
+	/* What? */
+	return NULL;
+}
+
+void pci_iounmap(struct pci_dev *dev, void __iomem *addr)
+{
+	/* Nothing to do */
+}
+EXPORT_SYMBOL(pci_iomap);
+EXPORT_SYMBOL(pci_iounmap);
diff -Nru a/arch/ppc64/kernel/iommu.c b/arch/ppc64/kernel/iommu.c
--- a/arch/ppc64/kernel/iommu.c	2004-10-18 14:55:53 -07:00
+++ b/arch/ppc64/kernel/iommu.c	2004-10-18 14:55:53 -07:00
@@ -229,7 +229,7 @@
 		struct scatterlist *sglist, int nelems,
 		enum dma_data_direction direction)
 {
-	dma_addr_t dma_next, dma_addr;
+	dma_addr_t dma_next = 0, dma_addr;
 	unsigned long flags;
 	struct scatterlist *s, *outs, *segstart;
 	int outcount;
diff -Nru a/arch/ppc64/kernel/irq.c b/arch/ppc64/kernel/irq.c
--- a/arch/ppc64/kernel/irq.c	2004-10-18 14:56:29 -07:00
+++ b/arch/ppc64/kernel/irq.c	2004-10-18 14:56:29 -07:00
@@ -41,6 +41,7 @@
 #include <linux/proc_fs.h>
 #include <linux/random.h>
 #include <linux/kallsyms.h>
+#include <linux/profile.h>
 
 #include <asm/uaccess.h>
 #include <asm/bitops.h>
@@ -362,14 +363,16 @@
 int handle_irq_event(int irq, struct pt_regs *regs, struct irqaction *action)
 {
 	int status = 0;
-	int retval = 0;
+	int ret, retval = 0;
 
 	if (!(action->flags & SA_INTERRUPT))
 		local_irq_enable();
 
 	do {
-		status |= action->flags;
-		retval |= action->handler(irq, action->dev_id, regs);
+		ret = action->handler(irq, action->dev_id, regs);
+		if (ret == IRQ_HANDLED)
+			status |= action->flags;
+		retval |= ret;
 		action = action->next;
 	} while (action);
 	if (status & SA_SAMPLE_RANDOM)
@@ -586,13 +589,13 @@
 	irq_enter();
 
 #ifdef CONFIG_DEBUG_STACKOVERFLOW
-	/* Debugging check for stack overflow: is there less than 4KB free? */
+	/* Debugging check for stack overflow: is there less than 2KB free? */
 	{
 		long sp;
 
 		sp = __get_SP() & (THREAD_SIZE-1);
 
-		if (unlikely(sp < (sizeof(struct thread_info) + 4096))) {
+		if (unlikely(sp < (sizeof(struct thread_info) + 2048))) {
 			printk("do_IRQ: stack overflow: %ld\n",
 				sp - sizeof(struct thread_info));
 			dump_stack();
@@ -629,13 +632,13 @@
 	irq_enter();
 
 #ifdef CONFIG_DEBUG_STACKOVERFLOW
-	/* Debugging check for stack overflow: is there less than 4KB free? */
+	/* Debugging check for stack overflow: is there less than 2KB free? */
 	{
 		long sp;
 
 		sp = __get_SP() & (THREAD_SIZE-1);
 
-		if (unlikely(sp < (sizeof(struct thread_info) + 4096))) {
+		if (unlikely(sp < (sizeof(struct thread_info) + 2048))) {
 			printk("do_IRQ: stack overflow: %ld\n",
 				sp - sizeof(struct thread_info));
 			dump_stack();
@@ -674,6 +677,8 @@
 	return 0;
 }
 
+EXPORT_SYMBOL(probe_irq_mask);
+
 void __init init_IRQ(void)
 {
 	static int once = 0;
@@ -757,44 +762,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)
@@ -824,26 +791,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.
@@ -977,7 +933,7 @@
 	struct thread_info *tp;
 	int i;
 
-	for (i = 0; i < NR_CPUS; i++) {
+	for_each_cpu(i) {
 		memset((void *)softirq_ctx[i], 0, THREAD_SIZE);
 		tp = softirq_ctx[i];
 		tp->cpu = i;
diff -Nru a/arch/ppc64/kernel/lmb.c b/arch/ppc64/kernel/lmb.c
--- a/arch/ppc64/kernel/lmb.c	2004-10-18 14:56:33 -07:00
+++ b/arch/ppc64/kernel/lmb.c	2004-10-18 14:56:33 -07:00
@@ -20,7 +20,44 @@
 #include <asm/abs_addr.h>
 #include <asm/bitops.h>
 
-struct lmb lmb __initdata;
+struct lmb lmb;
+
+#undef DEBUG
+
+void lmb_dump_all(void)
+{
+#ifdef DEBUG
+	unsigned long i;
+	struct lmb *_lmb  = &lmb;
+
+	udbg_printf("lmb_dump_all:\n");
+	udbg_printf("    memory.cnt		  = 0x%lx\n",
+		    _lmb->memory.cnt);
+	udbg_printf("    memory.size		  = 0x%lx\n",
+		    _lmb->memory.size);
+	for (i=0; i < _lmb->memory.cnt ;i++) {
+		udbg_printf("    memory.region[0x%x].base       = 0x%lx\n",
+			    i, _lmb->memory.region[i].base);
+		udbg_printf("		      .physbase = 0x%lx\n",
+			    _lmb->memory.region[i].physbase);
+		udbg_printf("		      .size     = 0x%lx\n",
+			    _lmb->memory.region[i].size);
+	}
+
+	udbg_printf("\n    reserved.cnt	  = 0x%lx\n",
+		    _lmb->reserved.cnt);
+	udbg_printf("    reserved.size	  = 0x%lx\n",
+		    _lmb->reserved.size);
+	for (i=0; i < _lmb->reserved.cnt ;i++) {
+		udbg_printf("    reserved.region[0x%x].base       = 0x%lx\n",
+			    i, _lmb->reserved.region[i].base);
+		udbg_printf("		      .physbase = 0x%lx\n",
+			    _lmb->reserved.region[i].physbase);
+		udbg_printf("		      .size     = 0x%lx\n",
+			    _lmb->reserved.region[i].size);
+	}
+#endif /* DEBUG */
+}
 
 static unsigned long __init
 lmb_addrs_overlap(unsigned long base1, unsigned long size1,
@@ -71,8 +108,7 @@
 void __init
 lmb_init(void)
 {
-	unsigned long offset = reloc_offset();
-	struct lmb *_lmb = PTRRELOC(&lmb);
+	struct lmb *_lmb = &lmb;
 
 	/* Create a dummy zero size LMB which will get coalesced away later.
 	 * This simplifies the lmb_add() code below...
@@ -94,8 +130,7 @@
 	unsigned long i;
 	unsigned long mem_size = 0;
 	unsigned long size_mask = 0;
-	unsigned long offset = reloc_offset();
-	struct lmb *_lmb = PTRRELOC(&lmb);
+	struct lmb *_lmb = &lmb;
 #ifdef CONFIG_MSCHUNKS
 	unsigned long physbase = 0;
 #endif
@@ -178,8 +213,7 @@
 long __init
 lmb_add(unsigned long base, unsigned long size)
 {
-	unsigned long offset = reloc_offset();
-	struct lmb *_lmb = PTRRELOC(&lmb);
+	struct lmb *_lmb = &lmb;
 	struct lmb_region *_rgn = &(_lmb->memory);
 
 	/* On pSeries LPAR systems, the first LMB is our RMO region. */
@@ -193,8 +227,7 @@
 long __init
 lmb_reserve(unsigned long base, unsigned long size)
 {
-	unsigned long offset = reloc_offset();
-	struct lmb *_lmb = PTRRELOC(&lmb);
+	struct lmb *_lmb = &lmb;
 	struct lmb_region *_rgn = &(_lmb->reserved);
 
 	return lmb_add_region(_rgn, base, size);
@@ -227,8 +260,7 @@
 {
 	long i, j;
 	unsigned long base = 0;
-	unsigned long offset = reloc_offset();
-	struct lmb *_lmb = PTRRELOC(&lmb);
+	struct lmb *_lmb = &lmb;
 	struct lmb_region *_mem = &(_lmb->memory);
 	struct lmb_region *_rsv = &(_lmb->reserved);
 
@@ -263,8 +295,7 @@
 unsigned long __init
 lmb_phys_mem_size(void)
 {
-	unsigned long offset = reloc_offset();
-	struct lmb *_lmb = PTRRELOC(&lmb);
+	struct lmb *_lmb = &lmb;
 #ifdef CONFIG_MSCHUNKS
 	return _lmb->memory.size;
 #else
@@ -282,8 +313,7 @@
 unsigned long __init
 lmb_end_of_DRAM(void)
 {
-	unsigned long offset = reloc_offset();
-	struct lmb *_lmb = PTRRELOC(&lmb);
+	struct lmb *_lmb = &lmb;
 	struct lmb_region *_mem = &(_lmb->memory);
 	int idx = _mem->cnt - 1;
 
@@ -300,8 +330,7 @@
 lmb_abs_to_phys(unsigned long aa)
 {
 	unsigned long i, pa = aa;
-	unsigned long offset = reloc_offset();
-	struct lmb *_lmb = PTRRELOC(&lmb);
+	struct lmb *_lmb = &lmb;
 	struct lmb_region *_mem = &(_lmb->memory);
 
 	for (i=0; i < _mem->cnt; i++) {
diff -Nru a/arch/ppc64/kernel/lparcfg.c b/arch/ppc64/kernel/lparcfg.c
--- a/arch/ppc64/kernel/lparcfg.c	2004-10-18 14:55:55 -07:00
+++ b/arch/ppc64/kernel/lparcfg.c	2004-10-18 14:55:55 -07:00
@@ -34,31 +34,37 @@
 #include <asm/rtas.h>
 #include <asm/system.h>
 
-#define MODULE_VERS "1.3"
+#define MODULE_VERS "1.4"
 #define MODULE_NAME "lparcfg"
 
 /* #define LPARCFG_DEBUG */
 
 /* find a better place for this function... */
-void log_plpar_hcall_return(unsigned long rc,char * tag)
+void log_plpar_hcall_return(unsigned long rc, char *tag)
 {
-	if (rc ==0 ) /* success, return */
+	if (rc == 0)		/* success, return */
 		return;
 /* check for null tag ? */
 	if (rc == H_Hardware)
-		printk(KERN_INFO "plpar-hcall (%s) failed with hardware fault\n",tag);
+		printk(KERN_INFO
+		       "plpar-hcall (%s) failed with hardware fault\n", tag);
 	else if (rc == H_Function)
-		printk(KERN_INFO "plpar-hcall (%s) failed; function not allowed\n",tag);
+		printk(KERN_INFO
+		       "plpar-hcall (%s) failed; function not allowed\n", tag);
 	else if (rc == H_Authority)
-		printk(KERN_INFO "plpar-hcall (%s) failed; not authorized to this function\n",tag);
+		printk(KERN_INFO
+		       "plpar-hcall (%s) failed; not authorized to this function\n",
+		       tag);
 	else if (rc == H_Parameter)
-		printk(KERN_INFO "plpar-hcall (%s) failed; Bad parameter(s)\n",tag);
+		printk(KERN_INFO "plpar-hcall (%s) failed; Bad parameter(s)\n",
+		       tag);
 	else
-		printk(KERN_INFO "plpar-hcall (%s) failed with unexpected rc(0x%lx)\n",tag,rc);
+		printk(KERN_INFO
+		       "plpar-hcall (%s) failed with unexpected rc(0x%lx)\n",
+		       tag, rc);
 
 }
 
-
 static struct proc_dir_entry *proc_ppc64_lparcfg;
 #define LPARCFG_BUFF_SIZE 4096
 
@@ -78,59 +84,60 @@
 
 	shared = (int)(lpaca->lppaca_ptr->xSharedProc);
 	seq_printf(m, "serial_number=%c%c%c%c%c%c%c\n",
-		      e2a(xItExtVpdPanel.mfgID[2]),
-		      e2a(xItExtVpdPanel.mfgID[3]),
-		      e2a(xItExtVpdPanel.systemSerial[1]),
-		      e2a(xItExtVpdPanel.systemSerial[2]),
-		      e2a(xItExtVpdPanel.systemSerial[3]),
-		      e2a(xItExtVpdPanel.systemSerial[4]),
-		      e2a(xItExtVpdPanel.systemSerial[5])); 
+		   e2a(xItExtVpdPanel.mfgID[2]),
+		   e2a(xItExtVpdPanel.mfgID[3]),
+		   e2a(xItExtVpdPanel.systemSerial[1]),
+		   e2a(xItExtVpdPanel.systemSerial[2]),
+		   e2a(xItExtVpdPanel.systemSerial[3]),
+		   e2a(xItExtVpdPanel.systemSerial[4]),
+		   e2a(xItExtVpdPanel.systemSerial[5]));
 
 	seq_printf(m, "system_type=%c%c%c%c\n",
-		      e2a(xItExtVpdPanel.machineType[0]),
-		      e2a(xItExtVpdPanel.machineType[1]),
-		      e2a(xItExtVpdPanel.machineType[2]),
-		      e2a(xItExtVpdPanel.machineType[3])); 
+		   e2a(xItExtVpdPanel.machineType[0]),
+		   e2a(xItExtVpdPanel.machineType[1]),
+		   e2a(xItExtVpdPanel.machineType[2]),
+		   e2a(xItExtVpdPanel.machineType[3]));
 
-	lp_index = HvLpConfig_getLpIndex(); 
+	lp_index = HvLpConfig_getLpIndex();
 	seq_printf(m, "partition_id=%d\n", (int)lp_index);
 
 	seq_printf(m, "system_active_processors=%d\n",
-		      (int)HvLpConfig_getSystemPhysicalProcessors()); 
+		   (int)HvLpConfig_getSystemPhysicalProcessors());
 
 	seq_printf(m, "system_potential_processors=%d\n",
-		      (int)HvLpConfig_getSystemPhysicalProcessors()); 
+		   (int)HvLpConfig_getSystemPhysicalProcessors());
 
-	processors = (int)HvLpConfig_getPhysicalProcessors(); 
+	processors = (int)HvLpConfig_getPhysicalProcessors();
 	seq_printf(m, "partition_active_processors=%d\n", processors);
 
-	max_processors = (int)HvLpConfig_getMaxPhysicalProcessors(); 
+	max_processors = (int)HvLpConfig_getMaxPhysicalProcessors();
 	seq_printf(m, "partition_potential_processors=%d\n", max_processors);
 
-	if(shared) {
-		entitled_capacity = HvLpConfig_getSharedProcUnits(); 
-		max_entitled_capacity = HvLpConfig_getMaxSharedProcUnits(); 
+	if (shared) {
+		entitled_capacity = HvLpConfig_getSharedProcUnits();
+		max_entitled_capacity = HvLpConfig_getMaxSharedProcUnits();
 	} else {
-		entitled_capacity = processors * 100; 
-		max_entitled_capacity = max_processors * 100; 
+		entitled_capacity = processors * 100;
+		max_entitled_capacity = max_processors * 100;
 	}
 	seq_printf(m, "partition_entitled_capacity=%d\n", entitled_capacity);
 
 	seq_printf(m, "partition_max_entitled_capacity=%d\n",
-		      max_entitled_capacity);
+		   max_entitled_capacity);
 
-	if(shared) {
-		pool_id = HvLpConfig_getSharedPoolIndex(); 
+	if (shared) {
+		pool_id = HvLpConfig_getSharedPoolIndex();
 		seq_printf(m, "pool=%d\n", (int)pool_id);
 		seq_printf(m, "pool_capacity=%d\n",
-		    (int)(HvLpConfig_getNumProcsInSharedPool(pool_id)*100));
+			   (int)(HvLpConfig_getNumProcsInSharedPool(pool_id) *
+				 100));
 	}
 
 	seq_printf(m, "shared_processor_mode=%d\n", shared);
 
 	return 0;
 }
-#endif /* CONFIG_PPC_ISERIES */
+#endif				/* CONFIG_PPC_ISERIES */
 
 #ifdef CONFIG_PPC_PSERIES
 /* 
@@ -158,11 +165,13 @@
  *                  XXXX  - Processors active on platform. 
  */
 static unsigned int h_get_ppp(unsigned long *entitled,
-		unsigned long  *unallocated, unsigned long *aggregation,
-		unsigned long *resource)
+			      unsigned long *unallocated,
+			      unsigned long *aggregation,
+			      unsigned long *resource)
 {
 	unsigned long rc;
-	rc = plpar_hcall_4out(H_GET_PPP,0,0,0,0,entitled,unallocated,aggregation,resource);
+	rc = plpar_hcall_4out(H_GET_PPP, 0, 0, 0, 0, entitled, unallocated,
+			      aggregation, resource);
 
 	log_plpar_hcall_return(rc, "H_GET_PPP");
 
@@ -185,7 +194,7 @@
  */
 static unsigned long get_purr()
 {
-	unsigned long sum_purr=0;
+	unsigned long sum_purr = 0;
 	return sum_purr;
 }
 
@@ -202,7 +211,7 @@
 {
 	int call_status;
 
-	char * local_buffer = kmalloc(SPLPAR_MAXLENGTH, GFP_KERNEL);
+	char *local_buffer = kmalloc(SPLPAR_MAXLENGTH, GFP_KERNEL);
 	if (!local_buffer) {
 		printk(KERN_ERR "%s %s kmalloc failure at line %d \n",
 		       __FILE__, __FUNCTION__, __LINE__);
@@ -219,22 +228,23 @@
 	spin_unlock(&rtas_data_buf_lock);
 
 	if (call_status != 0) {
-		printk(KERN_INFO "%s %s Error calling get-system-parameter (0x%x)\n",
+		printk(KERN_INFO
+		       "%s %s Error calling get-system-parameter (0x%x)\n",
 		       __FILE__, __FUNCTION__, call_status);
 	} else {
 		int splpar_strlen;
 		int idx, w_idx;
-		char * workbuffer = kmalloc(SPLPAR_MAXLENGTH, GFP_KERNEL);
+		char *workbuffer = kmalloc(SPLPAR_MAXLENGTH, GFP_KERNEL);
 		if (!workbuffer) {
-			printk(KERN_ERR "%s %s kmalloc failure at line %d \n",__FILE__,__FUNCTION__,__LINE__);
+			printk(KERN_ERR "%s %s kmalloc failure at line %d \n",
+			       __FILE__, __FUNCTION__, __LINE__);
 			return;
 		}
-
 #ifdef LPARCFG_DEBUG
 		printk(KERN_INFO "success calling get-system-parameter \n");
 #endif
 		splpar_strlen = local_buffer[0] * 16 + local_buffer[1];
-		local_buffer += 2; /* step over strlen value */
+		local_buffer += 2;	/* step over strlen value */
 
 		memset(workbuffer, 0, SPLPAR_MAXLENGTH);
 		w_idx = 0;
@@ -253,13 +263,15 @@
 				w_idx = 0;
 			} else if (local_buffer[idx] == '=') {
 				/* code here to replace workbuffer contents
-				 with different keyword strings */
-				if (0 == strcmp(workbuffer,"MaxEntCap")) {
-					strcpy(workbuffer, "partition_max_entitled_capacity");
+				   with different keyword strings */
+				if (0 == strcmp(workbuffer, "MaxEntCap")) {
+					strcpy(workbuffer,
+					       "partition_max_entitled_capacity");
 					w_idx = strlen(workbuffer);
 				}
-				if (0 == strcmp(workbuffer,"MaxPlatProcs")) {
-					strcpy(workbuffer, "system_potential_processors");
+				if (0 == strcmp(workbuffer, "MaxPlatProcs")) {
+					strcpy(workbuffer,
+					       "system_potential_processors");
 					w_idx = strlen(workbuffer);
 				}
 			}
@@ -283,7 +295,7 @@
 
 	while ((cpus_dn = of_find_node_by_type(cpus_dn, "cpu"))) {
 #ifdef LPARCFG_DEBUG
-		printk(KERN_ERR "cpus_dn %p \n",cpus_dn);
+		printk(KERN_ERR "cpus_dn %p \n", cpus_dn);
 #endif
 		count++;
 	}
@@ -292,7 +304,8 @@
 
 static int lparcfg_data(struct seq_file *m, void *v)
 {
-	int system_active_processors;
+	int partition_potential_processors;
+	int partition_active_processors;
 	struct device_node *rootdn;
 	const char *model = "";
 	const char *system_id = "";
@@ -305,12 +318,11 @@
 		model = get_property(rootdn, "model", NULL);
 		system_id = get_property(rootdn, "system-id", NULL);
 		lp_index_ptr = (unsigned int *)
-			get_property(rootdn, "ibm,partition-no", NULL);
+		    get_property(rootdn, "ibm,partition-no", NULL);
 		if (lp_index_ptr)
 			lp_index = *lp_index_ptr;
 	}
 
-
 	seq_printf(m, "%s %s \n", MODULE_NAME, MODULE_VERS);
 
 	seq_printf(m, "serial_number=%s\n", system_id);
@@ -323,11 +335,13 @@
 	lrdrp = (int *)get_property(rtas_node, "ibm,lrdr-capacity", NULL);
 
 	if (lrdrp == NULL) {
-		system_active_processors = systemcfg->processorCount;
+		partition_potential_processors = systemcfg->processorCount;
 	} else {
-		system_active_processors = *(lrdrp + 4);
+		partition_potential_processors = *(lrdrp + 4);
 	}
 
+	partition_active_processors = lparcfg_count_active_processors();
+
 	if (cur_cpu_spec->firmware_features & FW_FEATURE_SPLPAR) {
 		unsigned long h_entitled, h_unallocated;
 		unsigned long h_aggregation, h_resource;
@@ -342,71 +356,69 @@
 		seq_printf(m, "R6=0x%lx\n", h_aggregation);
 		seq_printf(m, "R7=0x%lx\n", h_resource);
 
-		h_pic(&pool_idle_time, &pool_procs);
-
 		purr = get_purr();
 
 		/* this call handles the ibm,get-system-parameter contents */
 		parse_system_parameter_string(m);
 
-		seq_printf(m, "partition_entitled_capacity=%ld\n",
-			      h_entitled);
-
-		seq_printf(m, "pool=%ld\n",
-			      (h_aggregation >> 0*8) & 0xffff);
+		seq_printf(m, "partition_entitled_capacity=%ld\n", h_entitled);
 
-		seq_printf(m, "group=%ld\n",
-			      (h_aggregation >> 2*8) & 0xffff);
+		seq_printf(m, "group=%ld\n", (h_aggregation >> 2 * 8) & 0xffff);
 
 		seq_printf(m, "system_active_processors=%ld\n",
-			      (h_resource >> 0*8) & 0xffff);
+			   (h_resource >> 0 * 8) & 0xffff);
+
+		/* pool related entries are apropriate for shared configs */
+		if (paca[0].lppaca.xSharedProc) {
 
-		seq_printf(m, "pool_capacity=%ld\n",
-			      (h_resource >> 2*8) & 0xffff);
+			h_pic(&pool_idle_time, &pool_procs);
+
+			seq_printf(m, "pool=%ld\n",
+				   (h_aggregation >> 0 * 8) & 0xffff);
+
+			/* report pool_capacity in percentage */
+			seq_printf(m, "pool_capacity=%ld\n",
+				   ((h_resource >> 2 * 8) & 0xffff) * 100);
+
+			seq_printf(m, "pool_idle_time=%ld\n", pool_idle_time);
+
+			seq_printf(m, "pool_num_procs=%ld\n", pool_procs);
+		}
 
 		seq_printf(m, "unallocated_capacity_weight=%ld\n",
-			      (h_resource >> 4*8) & 0xFF);
+			   (h_resource >> 4 * 8) & 0xFF);
 
 		seq_printf(m, "capacity_weight=%ld\n",
-			      (h_resource >> 5*8) & 0xFF);
-
-		seq_printf(m, "capped=%ld\n",
-			      (h_resource >> 6*8) & 0x01);
+			   (h_resource >> 5 * 8) & 0xFF);
 
-		seq_printf(m, "unallocated_capacity=%ld\n",
-			      h_unallocated);
+		seq_printf(m, "capped=%ld\n", (h_resource >> 6 * 8) & 0x01);
 
-		seq_printf(m, "pool_idle_time=%ld\n",
-			      pool_idle_time);
+		seq_printf(m, "unallocated_capacity=%ld\n", h_unallocated);
 
-		seq_printf(m, "pool_num_procs=%ld\n",
-			      pool_procs);
+		seq_printf(m, "purr=%ld\n", purr);
 
-		seq_printf(m, "purr=%ld\n",
-			      purr);
+	} else {		/* non SPLPAR case */
 
-	} else /* non SPLPAR case */ {
 		seq_printf(m, "system_active_processors=%d\n",
-			      system_active_processors);
+			   partition_potential_processors);
 
 		seq_printf(m, "system_potential_processors=%d\n",
-			      system_active_processors);
+			   partition_potential_processors);
 
 		seq_printf(m, "partition_max_entitled_capacity=%d\n",
-			      100*system_active_processors);
+			   partition_potential_processors * 100);
 
 		seq_printf(m, "partition_entitled_capacity=%d\n",
-			      system_active_processors*100);
+			   partition_active_processors * 100);
 	}
 
 	seq_printf(m, "partition_active_processors=%d\n",
-			(int) lparcfg_count_active_processors());
+		   partition_active_processors);
 
 	seq_printf(m, "partition_potential_processors=%d\n",
-			system_active_processors);
+		   partition_potential_processors);
 
-	seq_printf(m, "shared_processor_mode=%d\n",
-			paca[0].lppaca.xSharedProc);
+	seq_printf(m, "shared_processor_mode=%d\n", paca[0].lppaca.xSharedProc);
 
 	return 0;
 }
@@ -421,14 +433,15 @@
  * This function should be invoked only on systems with
  * FW_FEATURE_SPLPAR.
  */
-static ssize_t lparcfg_write(struct file *file, const char __user *buf, size_t count, loff_t *off)
+static ssize_t lparcfg_write(struct file *file, const char __user * buf,
+			     size_t count, loff_t * off)
 {
 	char *kbuf;
 	char *tmp;
 	u64 new_entitled, *new_entitled_ptr = &new_entitled;
 	u8 new_weight, *new_weight_ptr = &new_weight;
 
-	unsigned long current_entitled;    /* parameters for h_get_ppp */
+	unsigned long current_entitled;	/* parameters for h_get_ppp */
 	unsigned long dummy;
 	unsigned long resource;
 	u8 current_weight;
@@ -453,13 +466,13 @@
 
 	if (!strcmp(kbuf, "partition_entitled_capacity")) {
 		char *endp;
-		*new_entitled_ptr = (u64)simple_strtoul(tmp, &endp, 10);
+		*new_entitled_ptr = (u64) simple_strtoul(tmp, &endp, 10);
 		if (endp == tmp)
 			goto out;
 		new_weight_ptr = &current_weight;
 	} else if (!strcmp(kbuf, "capacity_weight")) {
 		char *endp;
-		*new_weight_ptr = (u8)simple_strtoul(tmp, &endp, 10);
+		*new_weight_ptr = (u8) simple_strtoul(tmp, &endp, 10);
 		if (endp == tmp)
 			goto out;
 		new_entitled_ptr = &current_entitled;
@@ -473,7 +486,7 @@
 		goto out;
 	}
 
-	current_weight = (resource>>5*8)&0xFF;
+	current_weight = (resource >> 5 * 8) & 0xFF;
 
 	pr_debug("%s: current_entitled = %lu, current_weight = %lu\n",
 		 __FUNCTION__, current_entitled, current_weight);
@@ -498,23 +511,23 @@
 		retval = -EIO;
 	}
 
-out:
+      out:
 	kfree(kbuf);
 	return retval;
 }
 
-#endif /* CONFIG_PPC_PSERIES */
+#endif				/* CONFIG_PPC_PSERIES */
 
-static int lparcfg_open(struct inode * inode, struct file * file)
+static int lparcfg_open(struct inode *inode, struct file *file)
 {
-	return single_open(file,lparcfg_data,NULL);
+	return single_open(file, lparcfg_data, NULL);
 }
 
 struct file_operations lparcfg_fops = {
-	owner:		THIS_MODULE,
-	read:		seq_read,
-	open:		lparcfg_open,
-	release:	single_release,
+      owner:THIS_MODULE,
+      read:seq_read,
+      open:lparcfg_open,
+      release:single_release,
 };
 
 int __init lparcfg_init(void)
@@ -533,7 +546,8 @@
 		ent->proc_fops = &lparcfg_fops;
 		ent->data = kmalloc(LPARCFG_BUFF_SIZE, GFP_KERNEL);
 		if (!ent->data) {
-			printk(KERN_ERR "Failed to allocate buffer for lparcfg\n");
+			printk(KERN_ERR
+			       "Failed to allocate buffer for lparcfg\n");
 			remove_proc_entry("lparcfg", ent->parent);
 			return -ENOMEM;
 		}
@@ -550,7 +564,7 @@
 {
 	if (proc_ppc64_lparcfg) {
 		if (proc_ppc64_lparcfg->data) {
-		    kfree(proc_ppc64_lparcfg->data);
+			kfree(proc_ppc64_lparcfg->data);
 		}
 		remove_proc_entry("lparcfg", proc_ppc64_lparcfg->parent);
 	}
diff -Nru a/arch/ppc64/kernel/mf_proc.c b/arch/ppc64/kernel/mf_proc.c
--- a/arch/ppc64/kernel/mf_proc.c	2004-10-18 14:56:29 -07:00
+++ b/arch/ppc64/kernel/mf_proc.c	2004-10-18 14:56:29 -07:00
@@ -167,22 +167,29 @@
 	return count;			
 }
 
-static int proc_mf_change_vmlinux(struct file *file, const char *buffer,
-		unsigned long count, void *data)
+static ssize_t proc_mf_change_vmlinux(struct file *file, 
+				      const char __user *buf,
+				      size_t count, loff_t *ppos)
 {
+	struct inode * inode = file->f_dentry->d_inode;
+	struct proc_dir_entry * dp = PDE(inode);
 	int rc;
 	if (!capable(CAP_SYS_ADMIN))
 		return -EACCES;
 
-	rc = mf_setVmlinuxChunk(buffer, count, file->f_pos, (u64)data);
+	rc = mf_setVmlinuxChunk(buf, count, *ppos, (u64)dp->data);
 	if (rc < 0)
 		return rc;
 
-	file->f_pos += count;
+	*ppos += count;
 
 	return count;			
 }
 
+static struct file_operations proc_vmlinux_operations = {
+	.write		= proc_mf_change_vmlinux,
+};
+
 static int __init mf_proc_init(void)
 {
 	struct proc_dir_entry *mf_proc_root;
@@ -218,20 +225,7 @@
 			return 1;
 		ent->nlink = 1;
 		ent->data = (void *)(long)i;
-#if 0
-		if (i == 3) {
-			/*
-			 * if we had a 'D' vmlinux entry, it would only
-			 * be readable.
-			 */
-			ent->read_proc = proc_mf_dump_vmlinux;
-			ent->write_proc = NULL;
-		} else
-#endif
-		{
-			ent->write_proc = proc_mf_change_vmlinux;
-			ent->read_proc = NULL;
-		}
+		ent->proc_fops = &proc_vmlinux_operations;
 	}
 
 	ent = create_proc_entry("side", S_IFREG|S_IRUSR|S_IWUSR, mf_proc_root);
diff -Nru a/arch/ppc64/kernel/misc.S b/arch/ppc64/kernel/misc.S
--- a/arch/ppc64/kernel/misc.S	2004-10-18 14:56:50 -07:00
+++ b/arch/ppc64/kernel/misc.S	2004-10-18 14:56:50 -07:00
@@ -127,6 +127,47 @@
 	blr
 #endif /* CONFIG_IRQSTACKS */
 
+	/*
+ * To be called by C code which needs to do some operations with MMU
+ * disabled. Note that interrupts have to be disabled by the caller
+ * prior to calling us. The code called _MUST_ be in the RMO of course
+ * and part of the linear mapping as we don't attempt to translate the
+ * stack pointer at all. The function is called with the stack switched
+ * to this CPU emergency stack
+ *
+ * prototype is void *call_with_mmu_off(void *func, void *data);
+ *
+ * the called function is expected to be of the form
+ *
+ * void *called(void *data); 
+ */
+_GLOBAL(call_with_mmu_off)
+	mflr	r0			/* get link, save it on stackframe */
+	std	r0,16(r1)
+	mr	r1,r5			/* save old stack ptr */
+	ld	r1,PACAEMERGSP(r13)	/* get emerg. stack */
+	subi	r1,r1,STACK_FRAME_OVERHEAD
+	std	r0,16(r1)		/* save link on emerg. stack */
+	std	r5,0(r1)		/* save old stack ptr in backchain */
+	ld	r3,0(r3)		/* get to real function ptr (assume same TOC) */
+	bl	2f			/* we need LR to return, continue at label 2 */
+
+	ld	r0,16(r1)		/* we return here from the call, get LR and */
+	ld	r1,0(r1)		/* .. old stack ptr */
+	mtspr	SPRN_SRR0,r0		/* and get back to virtual mode with these */
+	mfmsr	r4
+	ori	r4,r4,MSR_IR|MSR_DR
+	mtspr	SPRN_SRR1,r4
+	rfid
+
+2:	mtspr	SPRN_SRR0,r3		/* coming from above, enter real mode */
+	mr	r3,r4			/* get parameter */
+	mfmsr	r0
+	ori	r0,r0,MSR_IR|MSR_DR
+	xori	r0,r0,MSR_IR|MSR_DR
+	mtspr	SPRN_SRR1,r0
+	rfid
+	
 /*
  * Flush instruction cache.
  */
@@ -454,23 +495,6 @@
 	sync
 	blr	
 
-_GLOBAL(abs)
-	cmpi	0,r3,0
-	bge	10f
-	neg	r3,r3
-10:	blr
-
-_GLOBAL(_get_PVR)
-	mfspr	r3,PVR
-	blr
-
-_GLOBAL(_get_PIR)
-	mfspr	r3,PIR
-	blr
-
-_GLOBAL(_get_HID0)
-	mfspr	r3,HID0
-	blr
 
 _GLOBAL(cvt_fd)
 	lfd	0,0(r5)		/* load up fpscr value */
@@ -567,6 +591,69 @@
 	isync
 	b	1b
 
+#ifdef CONFIG_PPC_PMAC
+/*
+ * Do an IO access in real mode
+ */
+_GLOBAL(real_readb)
+	mfmsr	r7
+	ori	r0,r7,MSR_DR
+	xori	r0,r0,MSR_DR
+	sync
+	mtmsrd	r0
+	sync
+	isync
+	mfspr	r6,SPRN_HID4
+	rldicl	r5,r6,32,0
+	ori	r5,r5,0x100
+	rldicl	r5,r5,32,0
+	sync
+	mtspr	SPRN_HID4,r5
+	isync
+	slbia
+	isync
+	lbz	r3,0(r3)
+	sync
+	mtspr	SPRN_HID4,r6
+	isync
+	slbia
+	isync
+	mtmsrd	r7
+	sync
+	isync
+	blr
+
+	/*
+ * Do an IO access in real mode
+ */
+_GLOBAL(real_writeb)
+	mfmsr	r7
+	ori	r0,r7,MSR_DR
+	xori	r0,r0,MSR_DR
+	sync
+	mtmsrd	r0
+	sync
+	isync
+	mfspr	r6,SPRN_HID4
+	rldicl	r5,r6,32,0
+	ori	r5,r5,0x100
+	rldicl	r5,r5,32,0
+	sync
+	mtspr	SPRN_HID4,r5
+	isync
+	slbia
+	isync
+	stb	r3,0(r4)
+	sync
+	mtspr	SPRN_HID4,r6
+	isync
+	slbia
+	isync
+	mtmsrd	r7
+	sync
+	isync
+	blr
+#endif /* CONFIG_PPC_PMAC */
 
 /*
  * Create a kernel thread
@@ -583,7 +670,7 @@
 	li	r4,0		/* new sp (unused) */
 	li	r0,__NR_clone
 	sc
-	cmpi	0,r3,0		/* parent or child? */
+	cmpdi	0,r3,0		/* parent or child? */
 	bne	1f		/* return if parent */
 	li	r0,0
 	stdu	r0,-STACK_FRAME_OVERHEAD(r1)
@@ -600,7 +687,7 @@
 	ld	r30,-16(r1)
 	blr
 
-#ifdef CONFIG_PPC_ISERIES	/* hack hack hack */
+#ifndef CONFIG_PPC_PSERIES	/* hack hack hack */
 #define ppc_rtas	sys_ni_syscall
 #endif
 
@@ -866,9 +953,9 @@
 	.llong .sys_ni_syscall		/* 256 reserved for sys_debug_setcontext */
 	.llong .sys_ni_syscall		/* 257 reserved for vserver */
 	.llong .sys_ni_syscall		/* 258 reserved for new sys_remap_file_pages */
-	.llong .sys_ni_syscall		/* 259 reserved for new sys_mbind */
-	.llong .sys_ni_syscall		/* 260 reserved for new sys_get_mempolicy */
-	.llong .sys_ni_syscall		/* 261 reserved for new sys_set_mempolicy */
+	.llong .compat_mbind
+	.llong .compat_get_mempolicy	/* 260 */
+	.llong .compat_set_mempolicy
 	.llong .compat_sys_mq_open
 	.llong .sys_mq_unlink
 	.llong .compat_sys_mq_timedsend
@@ -1138,9 +1225,9 @@
 	.llong .sys_ni_syscall		/* 256 reserved for sys_debug_setcontext */
 	.llong .sys_ni_syscall		/* 257 reserved for vserver */
 	.llong .sys_ni_syscall		/* 258 reserved for new sys_remap_file_pages */
-	.llong .sys_ni_syscall		/* 259 reserved for new sys_mbind */
-	.llong .sys_ni_syscall		/* 260 reserved for new sys_get_mempolicy */
-	.llong .sys_ni_syscall		/* 261 reserved for new sys_set_mempolicy */
+	.llong .sys_mbind
+	.llong .sys_get_mempolicy	/* 260 */
+	.llong .sys_set_mempolicy
 	.llong .sys_mq_open
 	.llong .sys_mq_unlink
 	.llong .sys_mq_timedsend
diff -Nru a/arch/ppc64/kernel/nvram.c b/arch/ppc64/kernel/nvram.c
--- a/arch/ppc64/kernel/nvram.c	2004-10-18 14:55:54 -07:00
+++ b/arch/ppc64/kernel/nvram.c	2004-10-18 14:55:54 -07:00
@@ -340,7 +340,7 @@
 	struct list_head * p;
 	struct nvram_partition * part;
 	struct nvram_partition * new_part = NULL;
-	struct nvram_partition * free_part;
+	struct nvram_partition * free_part = NULL;
 	int seq_init[2] = { 0, 0 };
 	loff_t tmp_index;
 	long size = 0;
@@ -603,6 +603,7 @@
 }
 
 
+#ifdef CONFIG_PPC_PSERIES
 
 /* nvram_write_error_log
  *
@@ -727,6 +728,7 @@
 	return 0;
 }
 
+#endif /* CONFIG_PPC_PSERIES */
 
 module_init(nvram_init);
 module_exit(nvram_cleanup);
diff -Nru a/arch/ppc64/kernel/open_pic.c b/arch/ppc64/kernel/open_pic.c
--- a/arch/ppc64/kernel/open_pic.c	2004-10-18 14:56:33 -07:00
+++ b/arch/ppc64/kernel/open_pic.c	2004-10-18 14:56:33 -07:00
@@ -362,7 +362,6 @@
 	find_ISUs();
 
 	/* Initialize timer interrupts */
-	ppc64_boot_msg(0x21, "OpenPic Timer");
 	for (i = 0; i < OPENPIC_NUM_TIMERS; i++) {
 		/* Disabled, Priority 0 */
 		openpic_inittimer(i, 0, openpic_vec_timer+i);
@@ -372,7 +371,6 @@
 
 #ifdef CONFIG_SMP
 	/* Initialize IPI interrupts */
-	ppc64_boot_msg(0x22, "OpenPic IPI");
 	openpic_test_broken_IPI();
 	for (i = 0; i < OPENPIC_NUM_IPI; i++) {
 		/* Disabled, Priority 10..13 */
@@ -384,8 +382,6 @@
 #endif
 
 	/* Initialize external interrupts */
-	ppc64_boot_msg(0x23, "OpenPic Ext");
-
 	openpic_set_priority(0xf);
 
 	/* SIOint (8259 cascade) is special */
@@ -420,7 +416,6 @@
 		irq_desc[i].handler = &open_pic;
 
 	/* Initialize the spurious interrupt */
-	ppc64_boot_msg(0x24, "OpenPic Spurious");
 	openpic_set_spurious(openpic_vec_spurious);
 
 	openpic_set_priority(0);
diff -Nru a/arch/ppc64/kernel/open_pic_u3.c b/arch/ppc64/kernel/open_pic_u3.c
--- a/arch/ppc64/kernel/open_pic_u3.c	2004-10-18 14:55:46 -07:00
+++ b/arch/ppc64/kernel/open_pic_u3.c	2004-10-18 14:55:46 -07:00
@@ -344,5 +344,5 @@
 	openpic2_set_priority(0);
 	openpic2_disable_8259_pass_through();
 
-	ppc64_boot_msg(0x25, "OpenPic2 Done");
+	ppc64_boot_msg(0x25, "OpenPic U3 Done");
 }
diff -Nru a/arch/ppc64/kernel/pSeries_htab.c b/arch/ppc64/kernel/pSeries_htab.c
--- a/arch/ppc64/kernel/pSeries_htab.c	2004-10-18 14:56:28 -07:00
+++ /dev/null	Wed Dec 31 16:00:00 196900
@@ -1,408 +0,0 @@
-/*
- * pSeries hashtable management.
- *
- * SMP scalability work:
- *    Copyright (C) 2001 Anton Blanchard <anton@au.ibm.com>, IBM
- * 
- * 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/spinlock.h>
-#include <linux/bitops.h>
-#include <linux/threads.h>
-#include <linux/smp.h>
-
-#include <asm/abs_addr.h>
-#include <asm/machdep.h>
-#include <asm/mmu.h>
-#include <asm/mmu_context.h>
-#include <asm/pgtable.h>
-#include <asm/tlbflush.h>
-#include <asm/tlb.h>
-#include <asm/cputable.h>
-
-#define HPTE_LOCK_BIT 3
-
-static inline void pSeries_lock_hpte(HPTE *hptep)
-{
-	unsigned long *word = &hptep->dw0.dword0;
-
-	while (1) {
-		if (!test_and_set_bit(HPTE_LOCK_BIT, word))
-			break;
-		while(test_bit(HPTE_LOCK_BIT, word))
-			cpu_relax();
-	}
-}
-
-static inline void pSeries_unlock_hpte(HPTE *hptep)
-{
-	unsigned long *word = &hptep->dw0.dword0;
-
-	asm volatile("lwsync":::"memory");
-	clear_bit(HPTE_LOCK_BIT, word);
-}
-
-static spinlock_t pSeries_tlbie_lock = SPIN_LOCK_UNLOCKED;
-
-long pSeries_hpte_insert(unsigned long hpte_group, unsigned long va,
-			 unsigned long prpn, int secondary,
-			 unsigned long hpteflags, int bolted, int large)
-{
-	unsigned long arpn = physRpn_to_absRpn(prpn);
-	HPTE *hptep = htab_data.htab + hpte_group;
-	Hpte_dword0 dw0;
-	HPTE lhpte;
-	int i;
-
-	for (i = 0; i < HPTES_PER_GROUP; i++) {
-		dw0 = hptep->dw0.dw0;
-
-		if (!dw0.v) {
-			/* retry with lock held */
-			pSeries_lock_hpte(hptep);
-			dw0 = hptep->dw0.dw0;
-			if (!dw0.v)
-				break;
-			pSeries_unlock_hpte(hptep);
-		}
-
-		hptep++;
-	}
-
-	if (i == HPTES_PER_GROUP)
-		return -1;
-
-	lhpte.dw1.dword1      = 0;
-	lhpte.dw1.dw1.rpn     = arpn;
-	lhpte.dw1.flags.flags = hpteflags;
-
-	lhpte.dw0.dword0      = 0;
-	lhpte.dw0.dw0.avpn    = va >> 23;
-	lhpte.dw0.dw0.h       = secondary;
-	lhpte.dw0.dw0.bolted  = bolted;
-	lhpte.dw0.dw0.v       = 1;
-
-	if (large) {
-		lhpte.dw0.dw0.l = 1;
-		lhpte.dw0.dw0.avpn &= ~0x1UL;
-	}
-
-	hptep->dw1.dword1 = lhpte.dw1.dword1;
-
-	/* Guarantee the second dword is visible before the valid bit */
-	__asm__ __volatile__ ("eieio" : : : "memory");
-
-	/*
-	 * Now set the first dword including the valid bit
-	 * NOTE: this also unlocks the hpte
-	 */
-	hptep->dw0.dword0 = lhpte.dw0.dword0;
-
-	__asm__ __volatile__ ("ptesync" : : : "memory");
-
-	return i | (secondary << 3);
-}
-
-static long pSeries_hpte_remove(unsigned long hpte_group)
-{
-	HPTE *hptep;
-	Hpte_dword0 dw0;
-	int i;
-	int slot_offset;
-
-	/* pick a random entry to start at */
-	slot_offset = mftb() & 0x7;
-
-	for (i = 0; i < HPTES_PER_GROUP; i++) {
-		hptep = htab_data.htab + hpte_group + slot_offset;
-		dw0 = hptep->dw0.dw0;
-
-		if (dw0.v && !dw0.bolted) {
-			/* retry with lock held */
-			pSeries_lock_hpte(hptep);
-			dw0 = hptep->dw0.dw0;
-			if (dw0.v && !dw0.bolted)
-				break;
-			pSeries_unlock_hpte(hptep);
-		}
-
-		slot_offset++;
-		slot_offset &= 0x7;
-	}
-
-	if (i == HPTES_PER_GROUP)
-		return -1;
-
-	/* Invalidate the hpte. NOTE: this also unlocks it */
-	hptep->dw0.dword0 = 0;
-
-	return i;
-}
-
-static inline void set_pp_bit(unsigned long pp, HPTE *addr)
-{
-	unsigned long old;
-	unsigned long *p = &addr->dw1.dword1;
-
-	__asm__ __volatile__(
-	"1:	ldarx	%0,0,%3\n\
-		rldimi	%0,%2,0,61\n\
-		stdcx.	%0,0,%3\n\
-		bne	1b"
-	: "=&r" (old), "=m" (*p)
-	: "r" (pp), "r" (p), "m" (*p)
-	: "cc");
-}
-
-/*
- * Only works on small pages. Yes its ugly to have to check each slot in
- * the group but we only use this during bootup.
- */
-static long pSeries_hpte_find(unsigned long vpn)
-{
-	HPTE *hptep;
-	unsigned long hash;
-	unsigned long i, j;
-	long slot;
-	Hpte_dword0 dw0;
-
-	hash = hpt_hash(vpn, 0);
-
-	for (j = 0; j < 2; j++) {
-		slot = (hash & htab_data.htab_hash_mask) * HPTES_PER_GROUP;
-		for (i = 0; i < HPTES_PER_GROUP; i++) {
-			hptep = htab_data.htab + slot;
-			dw0 = hptep->dw0.dw0;
-
-			if ((dw0.avpn == (vpn >> 11)) && dw0.v &&
-			    (dw0.h == j)) {
-				/* HPTE matches */
-				if (j)
-					slot = -slot;
-				return slot;
-			}
-			++slot;
-		}
-		hash = ~hash;
-	}
-
-	return -1;
-}
-
-static long pSeries_hpte_updatepp(unsigned long slot, unsigned long newpp,
-				  unsigned long va, int large, int local)
-{
-	HPTE *hptep = htab_data.htab + slot;
-	Hpte_dword0 dw0;
-	unsigned long avpn = va >> 23;
-	int ret = 0;
-
-	if (large)
-		avpn &= ~0x1UL;
-
-	pSeries_lock_hpte(hptep);
-
-	dw0 = hptep->dw0.dw0;
-
-	/* Even if we miss, we need to invalidate the TLB */
-	if ((dw0.avpn != avpn) || !dw0.v) {
-		pSeries_unlock_hpte(hptep);
-		ret = -1;
-	} else {
-		set_pp_bit(newpp, hptep);
-		pSeries_unlock_hpte(hptep);
-	}
-
-	/* Ensure it is out of the tlb too */
-	if ((cur_cpu_spec->cpu_features & CPU_FTR_TLBIEL) && !large && local) {
-		tlbiel(va);
-	} else {
-		if (!(cur_cpu_spec->cpu_features & CPU_FTR_LOCKLESS_TLBIE))
-			spin_lock(&pSeries_tlbie_lock);
-		tlbie(va, large);
-		if (!(cur_cpu_spec->cpu_features & CPU_FTR_LOCKLESS_TLBIE))
-			spin_unlock(&pSeries_tlbie_lock);
-	}
-
-	return ret;
-}
-
-/*
- * Update the page protection bits. Intended to be used to create
- * guard pages for kernel data structures on pages which are bolted
- * in the HPT. Assumes pages being operated on will not be stolen.
- * Does not work on large pages.
- *
- * No need to lock here because we should be the only user.
- */
-static void pSeries_hpte_updateboltedpp(unsigned long newpp, unsigned long ea)
-{
-	unsigned long vsid, va, vpn, flags;
-	long slot;
-	HPTE *hptep;
-
-	vsid = get_kernel_vsid(ea);
-	va = (vsid << 28) | (ea & 0x0fffffff);
-	vpn = va >> PAGE_SHIFT;
-
-	slot = pSeries_hpte_find(vpn);
-	if (slot == -1)
-		panic("could not find page to bolt\n");
-	hptep = htab_data.htab + slot;
-
-	set_pp_bit(newpp, hptep);
-
-	/* Ensure it is out of the tlb too */
-	if (!(cur_cpu_spec->cpu_features & CPU_FTR_LOCKLESS_TLBIE))
-		spin_lock_irqsave(&pSeries_tlbie_lock, flags);
-	tlbie(va, 0);
-	if (!(cur_cpu_spec->cpu_features & CPU_FTR_LOCKLESS_TLBIE))
-		spin_unlock_irqrestore(&pSeries_tlbie_lock, flags);
-}
-
-static void pSeries_hpte_invalidate(unsigned long slot, unsigned long va,
-				    int large, int local)
-{
-	HPTE *hptep = htab_data.htab + slot;
-	Hpte_dword0 dw0;
-	unsigned long avpn = va >> 23;
-	unsigned long flags;
-
-	if (large)
-		avpn &= ~0x1UL;
-
-	local_irq_save(flags);
-	pSeries_lock_hpte(hptep);
-
-	dw0 = hptep->dw0.dw0;
-
-	/* Even if we miss, we need to invalidate the TLB */
-	if ((dw0.avpn != avpn) || !dw0.v) {
-		pSeries_unlock_hpte(hptep);
-	} else {
-		/* Invalidate the hpte. NOTE: this also unlocks it */
-		hptep->dw0.dword0 = 0;
-	}
-
-	/* Invalidate the tlb */
-	if ((cur_cpu_spec->cpu_features & CPU_FTR_TLBIEL) && !large && local) {
-		tlbiel(va);
-	} else {
-		if (!(cur_cpu_spec->cpu_features & CPU_FTR_LOCKLESS_TLBIE))
-			spin_lock(&pSeries_tlbie_lock);
-		tlbie(va, large);
-		if (!(cur_cpu_spec->cpu_features & CPU_FTR_LOCKLESS_TLBIE))
-			spin_unlock(&pSeries_tlbie_lock);
-	}
-	local_irq_restore(flags);
-}
-
-static void pSeries_flush_hash_range(unsigned long context,
-				     unsigned long number, int local)
-{
-	unsigned long vsid, vpn, va, hash, secondary, slot, flags, avpn;
-	int i, j;
-	HPTE *hptep;
-	Hpte_dword0 dw0;
-	struct ppc64_tlb_batch *batch = &__get_cpu_var(ppc64_tlb_batch);
-
-	/* XXX fix for large ptes */
-	unsigned long large = 0;
-
-	local_irq_save(flags);
-
-	j = 0;
-	for (i = 0; i < number; i++) {
-		if ((batch->addr[i] >= USER_START) &&
-		    (batch->addr[i] <= USER_END))
-			vsid = get_vsid(context, batch->addr[i]);
-		else
-			vsid = get_kernel_vsid(batch->addr[i]);
-
-		va = (vsid << 28) | (batch->addr[i] & 0x0fffffff);
-		batch->vaddr[j] = va;
-		if (large)
-			vpn = va >> LARGE_PAGE_SHIFT;
-		else
-			vpn = va >> PAGE_SHIFT;
-		hash = hpt_hash(vpn, large);
-		secondary = (pte_val(batch->pte[i]) & _PAGE_SECONDARY) >> 15;
-		if (secondary)
-			hash = ~hash;
-		slot = (hash & htab_data.htab_hash_mask) * HPTES_PER_GROUP;
-		slot += (pte_val(batch->pte[i]) & _PAGE_GROUP_IX) >> 12;
-
-		hptep = htab_data.htab + slot;
-
-		avpn = va >> 23;
-		if (large)
-			avpn &= ~0x1UL;
-
-		pSeries_lock_hpte(hptep);
-
-		dw0 = hptep->dw0.dw0;
-
-		/* Even if we miss, we need to invalidate the TLB */
-		if ((dw0.avpn != avpn) || !dw0.v) {
-			pSeries_unlock_hpte(hptep);
-		} else {
-			/* Invalidate the hpte. NOTE: this also unlocks it */
-			hptep->dw0.dword0 = 0;
-		}
-
-		j++;
-	}
-
-	if ((cur_cpu_spec->cpu_features & CPU_FTR_TLBIEL) && !large && local) {
-		asm volatile("ptesync":::"memory");
-
-		for (i = 0; i < j; i++)
-			__tlbiel(batch->vaddr[i]);
-
-		asm volatile("ptesync":::"memory");
-	} else {
-		/* XXX double check that it is safe to take this late */
-		if (!(cur_cpu_spec->cpu_features & CPU_FTR_LOCKLESS_TLBIE))
-			spin_lock(&pSeries_tlbie_lock);
-
-		asm volatile("ptesync":::"memory");
-
-		for (i = 0; i < j; i++)
-			__tlbie(batch->vaddr[i], 0);
-
-		asm volatile("eieio; tlbsync; ptesync":::"memory");
-
-		if (!(cur_cpu_spec->cpu_features & CPU_FTR_LOCKLESS_TLBIE))
-			spin_unlock(&pSeries_tlbie_lock);
-	}
-
-	local_irq_restore(flags);
-}
-
-void hpte_init_pSeries(void)
-{
-	struct device_node *root;
-	const char *model;
-
-	ppc_md.hpte_invalidate	= pSeries_hpte_invalidate;
-	ppc_md.hpte_updatepp	= pSeries_hpte_updatepp;
-	ppc_md.hpte_updateboltedpp = pSeries_hpte_updateboltedpp;
-	ppc_md.hpte_insert	= pSeries_hpte_insert;
-	ppc_md.hpte_remove     	= pSeries_hpte_remove;
-
-	/* Disable TLB batching on nighthawk */
-	root = of_find_node_by_path("/");
-	if (root) {
-		model = get_property(root, "model", NULL);
-		if (!strcmp(model, "CHRP IBM,9076-N81")) {
-			of_node_put(root);
-			return;
-		}
-		of_node_put(root);
-	}
-
-	ppc_md.flush_hash_range = pSeries_flush_hash_range;
-}
diff -Nru a/arch/ppc64/kernel/pSeries_iommu.c b/arch/ppc64/kernel/pSeries_iommu.c
--- a/arch/ppc64/kernel/pSeries_iommu.c	2004-10-18 14:56:17 -07:00
+++ b/arch/ppc64/kernel/pSeries_iommu.c	2004-10-18 14:56:17 -07:00
@@ -42,6 +42,7 @@
 #include <asm/pci-bridge.h>
 #include <asm/machdep.h>
 #include <asm/abs_addr.h>
+#include <asm/plpar_wrappers.h>
 #include "pci.h"
 
 
@@ -88,9 +89,153 @@
 }
 
 
+static void tce_build_pSeriesLP(struct iommu_table *tbl, long tcenum,
+				long npages, unsigned long uaddr,
+				enum dma_data_direction direction)
+{
+	u64 rc;
+	union tce_entry tce;
+
+	tce.te_word = 0;
+	tce.te_rpn = (virt_to_abs(uaddr)) >> PAGE_SHIFT;
+	tce.te_rdwr = 1;
+	if (direction != DMA_TO_DEVICE)
+		tce.te_pciwr = 1;
+
+	while (npages--) {
+		rc = plpar_tce_put((u64)tbl->it_index, 
+				   (u64)tcenum << 12, 
+				   tce.te_word );
+		
+		if (rc && printk_ratelimit()) {
+			printk("tce_build_pSeriesLP: plpar_tce_put failed. rc=%ld\n", rc);
+			printk("\tindex   = 0x%lx\n", (u64)tbl->it_index);
+			printk("\ttcenum  = 0x%lx\n", (u64)tcenum);
+			printk("\ttce val = 0x%lx\n", tce.te_word );
+			show_stack(current, (unsigned long *)__get_SP());
+		}
+			
+		tcenum++;
+		tce.te_rpn++;
+	}
+}
+
+DEFINE_PER_CPU(void *, tce_page) = NULL;
+
+static void tce_buildmulti_pSeriesLP(struct iommu_table *tbl, long tcenum,
+				     long npages, unsigned long uaddr,
+				     enum dma_data_direction direction)
+{
+	u64 rc;
+	union tce_entry tce, *tcep;
+	long l, limit;
+
+	if (npages == 1)
+		return tce_build_pSeriesLP(tbl, tcenum, npages, uaddr,
+					   direction);
+
+	tcep = __get_cpu_var(tce_page);
+
+	/* This is safe to do since interrupts are off when we're called
+	 * from iommu_alloc{,_sg}()
+	 */
+	if (!tcep) {
+		tcep = (void *)__get_free_page(GFP_ATOMIC);
+		/* If allocation fails, fall back to the loop implementation */
+		if (!tcep)
+			return tce_build_pSeriesLP(tbl, tcenum, npages,
+						   uaddr, direction);
+		__get_cpu_var(tce_page) = tcep;
+	}
+
+	tce.te_word = 0;
+	tce.te_rpn = (virt_to_abs(uaddr)) >> PAGE_SHIFT;
+	tce.te_rdwr = 1;
+	if (direction != DMA_TO_DEVICE)
+		tce.te_pciwr = 1;
+
+	/* We can map max one pageful of TCEs at a time */
+	do {
+		/*
+		 * Set up the page with TCE data, looping through and setting
+		 * the values.
+		 */
+		limit = min_t(long, npages, PAGE_SIZE/sizeof(union tce_entry));
+
+		for (l = 0; l < limit; l++) {
+			tcep[l] = tce;
+			tce.te_rpn++;
+		}
+
+		rc = plpar_tce_put_indirect((u64)tbl->it_index,
+					    (u64)tcenum << 12,
+					    (u64)virt_to_abs(tcep),
+					    limit);
+
+		npages -= limit;
+		tcenum += limit;
+	} while (npages > 0 && !rc);
+
+	if (rc && printk_ratelimit()) {
+		printk("tce_buildmulti_pSeriesLP: plpar_tce_put failed. rc=%ld\n", rc);
+		printk("\tindex   = 0x%lx\n", (u64)tbl->it_index);
+		printk("\tnpages  = 0x%lx\n", (u64)npages);
+		printk("\ttce[0] val = 0x%lx\n", tcep[0].te_word);
+		show_stack(current, (unsigned long *)__get_SP());
+	}
+}
+
+static void tce_free_pSeriesLP(struct iommu_table *tbl, long tcenum, long npages)
+{
+	u64 rc;
+	union tce_entry tce;
+
+	tce.te_word = 0;
+
+	while (npages--) {
+		rc = plpar_tce_put((u64)tbl->it_index,
+				   (u64)tcenum << 12,
+				   tce.te_word);
+
+		if (rc && printk_ratelimit()) {
+			printk("tce_free_pSeriesLP: plpar_tce_put failed. rc=%ld\n", rc);
+			printk("\tindex   = 0x%lx\n", (u64)tbl->it_index);
+			printk("\ttcenum  = 0x%lx\n", (u64)tcenum);
+			printk("\ttce val = 0x%lx\n", tce.te_word );
+			show_stack(current, (unsigned long *)__get_SP());
+		}
+
+		tcenum++;
+	}
+}
+
+
+static void tce_freemulti_pSeriesLP(struct iommu_table *tbl, long tcenum, long npages)
+{
+	u64 rc;
+	union tce_entry tce;
+
+	tce.te_word = 0;
+
+	rc = plpar_tce_stuff((u64)tbl->it_index,
+			   (u64)tcenum << 12,
+			   tce.te_word,
+			   npages);
+
+	if (rc && printk_ratelimit()) {
+		printk("tce_freemulti_pSeriesLP: plpar_tce_stuff failed\n");
+		printk("\trc      = %ld\n", rc);
+		printk("\tindex   = 0x%lx\n", (u64)tbl->it_index);
+		printk("\tnpages  = 0x%lx\n", (u64)npages);
+		printk("\ttce val = 0x%lx\n", tce.te_word );
+		show_stack(current, (unsigned long *)__get_SP());
+	}
+}
+
+
 static void iommu_buses_init(void)
 {
-	struct pci_controller* phb;
+	struct pci_controller *phb, *tmp;
 	struct device_node *dn, *first_dn;
 	int num_slots, num_slots_ilog2;
 	int first_phb = 1;
@@ -106,10 +251,10 @@
 	else
 		tcetable_ilog2 = 22;
 
-	/* XXX Should we be using pci_root_buses instead?  -ojn 
+	/* XXX Should we be using pci_root_buses instead?  -ojn
 	 */
 
-	for (phb=hose_head; phb; phb=phb->next) {
+	list_for_each_entry_safe(phb, tmp, &hose_list, list_node) {
 		first_dn = ((struct device_node *)phb->arch_data)->child;
 
 		/* Carve 2GB into the largest dma_window_size possible */
@@ -166,24 +311,25 @@
 				 struct device_node *dn,
 				 struct iommu_table *tbl) 
 {
-	phandle node;
-	unsigned long i;
-	struct of_tce_table *oft;
-
-	node = ((struct device_node *)(phb->arch_data))->node;
-
-	oft = NULL;
-
-	for (i=0; of_tce_table[i].node; i++)
-		if(of_tce_table[i].node == node) {
-			oft = &of_tce_table[i];
-			break;
-		}
-
-	if (!oft)
-		panic("PCI_DMA: iommu_table_setparms: Can't find phb named '%s' in of_tce_table\n", dn->full_name);
-
-	memset((void *)oft->base, 0, oft->size);
+	struct device_node *node;
+	unsigned long *basep;
+	unsigned int *sizep;
+
+	node = (struct device_node *)phb->arch_data;
+
+	if (get_property(node, "linux,has-tce-table", NULL) == NULL) {
+		printk(KERN_ERR "PCI_DMA: iommu_table_setparms: %s has no tce table !\n",
+		      dn->full_name);
+		return;
+	}
+	basep = (unsigned long *)get_property(node, "linux,tce-base", NULL);
+	sizep = (unsigned int *)get_property(node, "linux,tce-size", NULL);
+	if (basep == NULL || sizep == NULL) {
+		printk(KERN_ERR "PCI_DMA: iommu_table_setparms: %s has missing tce"
+		       " entries !\n", dn->full_name);
+		return;
+	}
+	memset((void *)(*basep), 0, *sizep);
 
 	tbl->it_busno = phb->bus->number;
 	
@@ -207,10 +353,11 @@
 	if (phb->dma_window_base_cur > (1 << 19))
 		panic("PCI_DMA: Unexpected number of IOAs under this PHB.\n"); 
 	
-	tbl->it_base = oft->base;
+	tbl->it_base = *basep;
 	tbl->it_index = 0;
 	tbl->it_entrysize = sizeof(union tce_entry);
 	tbl->it_blocksize = 16;
+	tbl->it_type = TCE_PCI;
 }
 
 /*
@@ -246,6 +393,7 @@
 	tbl->it_index  = dma_window[0];
 	tbl->it_entrysize = sizeof(union tce_entry);
 	tbl->it_blocksize  = 16;
+	tbl->it_type = TCE_PCI;
 }
 
 
@@ -293,8 +441,16 @@
 /* These are called very early. */
 void tce_init_pSeries(void)
 {
-	ppc_md.tce_build = tce_build_pSeries;
-	ppc_md.tce_free  = tce_free_pSeries;
+	if (!(systemcfg->platform & PLATFORM_LPAR)) {
+		ppc_md.tce_build = tce_build_pSeries;
+		ppc_md.tce_free  = tce_free_pSeries;
+	} else if (cur_cpu_spec->firmware_features & FW_FEATURE_MULTITCE) {
+		ppc_md.tce_build = tce_buildmulti_pSeriesLP;
+		ppc_md.tce_free	 = tce_freemulti_pSeriesLP;
+	} else {
+		ppc_md.tce_build = tce_build_pSeriesLP;
+		ppc_md.tce_free	 = tce_free_pSeriesLP;
+	}
 
 	pci_iommu_init();
 }
diff -Nru a/arch/ppc64/kernel/pSeries_lpar.c b/arch/ppc64/kernel/pSeries_lpar.c
--- a/arch/ppc64/kernel/pSeries_lpar.c	2004-10-18 14:57:05 -07:00
+++ b/arch/ppc64/kernel/pSeries_lpar.c	2004-10-18 14:57:05 -07:00
@@ -19,6 +19,8 @@
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
  */
 
+#define DEBUG
+
 #include <linux/config.h>
 #include <linux/kernel.h>
 #include <linux/dma-mapping.h>
@@ -34,10 +36,16 @@
 #include <asm/naca.h>
 #include <asm/tlbflush.h>
 #include <asm/tlb.h>
-#include <asm/hvcall.h>
 #include <asm/prom.h>
 #include <asm/abs_addr.h>
 #include <asm/cputable.h>
+#include <asm/plpar_wrappers.h>
+
+#ifdef DEBUG
+#define DBG(fmt...) udbg_printf(fmt)
+#else
+#define DBG(fmt...)
+#endif
 
 /* in pSeries_hvCall.S */
 EXPORT_SYMBOL(plpar_hcall);
@@ -45,146 +53,9 @@
 EXPORT_SYMBOL(plpar_hcall_norets);
 EXPORT_SYMBOL(plpar_hcall_8arg_2ret);
 
-long poll_pending(void)
-{
-	unsigned long dummy;
-	return plpar_hcall(H_POLL_PENDING, 0, 0, 0, 0,
-			   &dummy, &dummy, &dummy);
-}
-
-long prod_processor(void)
-{
-	plpar_hcall_norets(H_PROD);
-	return(0); 
-}
-
-long cede_processor(void)
-{
-	plpar_hcall_norets(H_CEDE);
-	return(0); 
-}
-
-long register_vpa(unsigned long flags, unsigned long proc, unsigned long vpa)
-{
-	plpar_hcall_norets(H_REGISTER_VPA, flags, proc, vpa);
-	return(0); 
-}
-
-long plpar_pte_remove(unsigned long flags,
-		      unsigned long ptex,
-		      unsigned long avpn,
-		      unsigned long *old_pteh_ret, unsigned long *old_ptel_ret)
-{
-	unsigned long dummy;
-	return plpar_hcall(H_REMOVE, flags, ptex, avpn, 0,
-			   old_pteh_ret, old_ptel_ret, &dummy);
-}
-
-long plpar_pte_read(unsigned long flags,
-		    unsigned long ptex,
-		    unsigned long *old_pteh_ret, unsigned long *old_ptel_ret)
-{
-	unsigned long dummy;
-	return plpar_hcall(H_READ, flags, ptex, 0, 0,
-			   old_pteh_ret, old_ptel_ret, &dummy);
-}
-
-long plpar_pte_protect(unsigned long flags,
-		       unsigned long ptex,
-		       unsigned long avpn)
-{
-	return plpar_hcall_norets(H_PROTECT, flags, ptex, avpn);
-}
-
-long plpar_tce_get(unsigned long liobn,
-		   unsigned long ioba,
-		   unsigned long *tce_ret)
-{
-	unsigned long dummy;
-	return plpar_hcall(H_GET_TCE, liobn, ioba, 0, 0,
-			   tce_ret, &dummy, &dummy);
-}
+extern void fw_feature_init(void);
+extern void pSeries_find_serial_port(void);
 
-long plpar_tce_put(unsigned long liobn,
-		   unsigned long ioba,
-		   unsigned long tceval)
-{
-	return plpar_hcall_norets(H_PUT_TCE, liobn, ioba, tceval);
-}
-
-long plpar_get_term_char(unsigned long termno,
-			 unsigned long *len_ret,
-			 char *buf_ret)
-{
-	unsigned long *lbuf = (unsigned long *)buf_ret;  /* ToDo: alignment? */
-	return plpar_hcall(H_GET_TERM_CHAR, termno, 0, 0, 0,
-			   len_ret, lbuf+0, lbuf+1);
-}
-
-long plpar_put_term_char(unsigned long termno,
-			 unsigned long len,
-			 const char *buffer)
-{
-	unsigned long *lbuf = (unsigned long *)buffer;  /* ToDo: alignment? */
-	return plpar_hcall_norets(H_PUT_TERM_CHAR, termno, len, lbuf[0],
-				  lbuf[1]);
-}
-
-static void tce_build_pSeriesLP(struct iommu_table *tbl, long tcenum,
-		long npages, unsigned long uaddr,
-		enum dma_data_direction direction)
-{
-	u64 rc;
-	union tce_entry tce;
-
-	tce.te_word = 0;
-	tce.te_rpn = (virt_to_abs(uaddr)) >> PAGE_SHIFT;
-	tce.te_rdwr = 1;
-	if (direction != DMA_TO_DEVICE)
-		tce.te_pciwr = 1;
-
-	while (npages--) {
-		rc = plpar_tce_put((u64)tbl->it_index, 
-				   (u64)tcenum << 12, 
-				   tce.te_word );
-		
-		if (rc && printk_ratelimit()) {
-			printk("tce_build_pSeriesLP: plpar_tce_put failed. rc=%ld\n", rc);
-			printk("\tindex   = 0x%lx\n", (u64)tbl->it_index);
-			printk("\ttcenum  = 0x%lx\n", (u64)tcenum);
-			printk("\ttce val = 0x%lx\n", tce.te_word );
-			show_stack(current, (unsigned long *)__get_SP());
-		}
-			
-		tcenum++;
-		tce.te_rpn++;
-	}
-}
-
-static void tce_free_pSeriesLP(struct iommu_table *tbl, long tcenum, long npages)
-{
-	u64 rc;
-	union tce_entry tce;
-
-	tce.te_word = 0;
-
-	while (npages--) {
-		rc = plpar_tce_put((u64)tbl->it_index, 
-				   (u64)tcenum << 12,
-				   tce.te_word );
-		
-		if (rc && printk_ratelimit()) {
-			printk("tce_free_pSeriesLP: plpar_tce_put failed\n");
-			printk("\trc      = %ld\n", rc);
-			printk("\tindex   = 0x%lx\n", (u64)tbl->it_index);
-			printk("\ttcenum  = 0x%lx\n", (u64)tcenum);
-			printk("\ttce val = 0x%lx\n", tce.te_word );
-			show_stack(current, (unsigned long *)__get_SP());
-		}
-		
-		tcenum++;
-	}
-}
 
 int vtermno;	/* virtual terminal# for udbg  */
 
@@ -249,8 +120,19 @@
 	}
 }
 
+/* call this from early_init() for a working debug console on
+ * vterm capable LPAR machines
+ */
+void udbg_init_debug_lpar(void)
+{
+	vtermno = 0;
+	ppc_md.udbg_putc = udbg_putcLP;
+	ppc_md.udbg_getc = udbg_getcLP;
+	ppc_md.udbg_getc_poll = udbg_getc_pollLP;
+}
+
 /* returns 0 if couldn't find or use /chosen/stdout as console */
-static int find_udbg_vterm(void)
+int find_udbg_vterm(void)
 {
 	struct device_node *stdout_node;
 	u32 *termno;
@@ -258,15 +140,14 @@
 	int found = 0;
 
 	/* find the boot console from /chosen/stdout */
-	if (!of_stdout_device) {
-		printk(KERN_WARNING "couldn't get path from /chosen/stdout!\n");
-		return found;
-	}
-	stdout_node = of_find_node_by_path(of_stdout_device);
-	if (!stdout_node) {
-		printk(KERN_WARNING "couldn't find node from /chosen/stdout\n");
-		return found;
-	}
+	if (!of_chosen)
+		return 0;
+	name = (char *)get_property(of_chosen, "linux,stdout-path", NULL);
+	if (name == NULL)
+		return 0;
+	stdout_node = of_find_node_by_path(name);
+	if (!stdout_node)
+		return 0;
 
 	/* now we have the stdout node; figure out what type of device it is. */
 	name = (char *)get_property(stdout_node, "name", NULL);
@@ -288,15 +169,17 @@
 		} else {
 			/* XXX implement udbg_putcLP_vtty for hvterm-protocol1 case */
 			printk(KERN_WARNING "%s doesn't speak hvterm1; "
-					"can't print udbg messages\n", of_stdout_device);
+					"can't print udbg messages\n",
+			       stdout_node->full_name);
 		}
 	} else if (strncmp(name, "serial", 6)) {
 		/* XXX fix ISA serial console */
 		printk(KERN_WARNING "serial stdout on LPAR ('%s')! "
-				"can't print udbg messages\n", of_stdout_device);
+				"can't print udbg messages\n",
+		       stdout_node->full_name);
 	} else {
 		printk(KERN_WARNING "don't know how to print to stdout '%s'\n",
-				of_stdout_device);
+		       stdout_node->full_name);
 	}
 
 out:
@@ -304,35 +187,6 @@
 	return found;
 }
 
-void pSeries_lpar_mm_init(void);
-
-/* This is called early in setup.c.
- * Use it to setup page table ppc_md stuff as well as udbg.
- */
-void pSeriesLP_init_early(void)
-{
-	pSeries_lpar_mm_init();
-
-	tce_init_pSeries();
-
-	ppc_md.tce_build = tce_build_pSeriesLP;
-	ppc_md.tce_free	 = tce_free_pSeriesLP;
-
-	pci_iommu_init();
-
-#ifdef CONFIG_SMP
-	smp_init_pSeries();
-#endif
-
-	/* The keyboard is not useful in the LPAR environment.
-	 * Leave all the ppc_md keyboard interfaces NULL.
-	 */
-
-	if (0 == find_udbg_vterm()) {
-		printk(KERN_WARNING
-			"can't use stdout; can't print early debug messages.\n");
-	}
-}
 
 long pSeries_lpar_hpte_insert(unsigned long hpte_group,
 			      unsigned long va, unsigned long prpn,
@@ -377,7 +231,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 +239,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 +269,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;
@@ -426,6 +278,18 @@
 	return -1;
 }
 
+static void pSeries_lpar_hptab_clear(void)
+{
+	unsigned long size_bytes = 1UL << naca->pftSize;
+	unsigned long hpte_count = size_bytes >> 4;
+	unsigned long dummy1, dummy2;
+	int i;
+
+	/* TODO: Use bulk call */
+	for (i = 0; i < hpte_count; i++)
+		plpar_pte_remove(0, i, 0, &dummy1, &dummy2);
+}
+
 /*
  * NOTE: for updatepp ops we are fortunate that the linux "newpp" bits and
  * the low 3 bits of flags happen to line up.  So no transform is needed.
@@ -447,8 +311,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;
 }
@@ -464,11 +327,10 @@
 	/* Do not need RPN to logical page translation */
 	/* No cross CEC PFT access                     */
 	flags = 0;
-	
+
 	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 +381,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 +405,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);
 }
 
 /*
@@ -560,18 +418,19 @@
 	int i;
 	unsigned long flags;
 	struct ppc64_tlb_batch *batch = &__get_cpu_var(ppc64_tlb_batch);
+	int lock_tlbie = !(cur_cpu_spec->cpu_features & CPU_FTR_LOCKLESS_TLBIE);
 
-	if (!(cur_cpu_spec->cpu_features & CPU_FTR_LOCKLESS_TLBIE))
+	if (lock_tlbie)
 		spin_lock_irqsave(&pSeries_lpar_tlbie_lock, flags);
 
 	for (i = 0; i < number; i++)
 		flush_hash_page(context, batch->addr[i], batch->pte[i], local);
 
-	if (!(cur_cpu_spec->cpu_features & CPU_FTR_LOCKLESS_TLBIE))
+	if (lock_tlbie)
 		spin_unlock_irqrestore(&pSeries_lpar_tlbie_lock, flags);
 }
 
-void pSeries_lpar_mm_init(void)
+void hpte_init_lpar(void)
 {
 	ppc_md.hpte_invalidate	= pSeries_lpar_hpte_invalidate;
 	ppc_md.hpte_updatepp	= pSeries_lpar_hpte_updatepp;
@@ -579,4 +438,7 @@
 	ppc_md.hpte_insert	= pSeries_lpar_hpte_insert;
 	ppc_md.hpte_remove	= pSeries_lpar_hpte_remove;
 	ppc_md.flush_hash_range	= pSeries_lpar_flush_hash_range;
+	ppc_md.hpte_clear_all   = pSeries_lpar_hptab_clear;
+
+	htab_finish_init();
 }
diff -Nru a/arch/ppc64/kernel/pSeries_pci.c b/arch/ppc64/kernel/pSeries_pci.c
--- a/arch/ppc64/kernel/pSeries_pci.c	2004-10-18 14:57:18 -07:00
+++ b/arch/ppc64/kernel/pSeries_pci.c	2004-10-18 14:57:18 -07:00
@@ -45,12 +45,6 @@
 #include "open_pic.h"
 #include "pci.h"
 
-/* legal IO pages under MAX_ISA_PORT.  This is to ensure we don't touch
-   devices we don't have access to. */
-unsigned long io_page_mask;
-
-EXPORT_SYMBOL(io_page_mask);
-
 /* RTAS tokens */
 static int read_pci_config;
 static int write_pci_config;
@@ -68,7 +62,9 @@
 	int ret;
 
 	if (!dn)
-		return -2;
+		return PCIBIOS_DEVICE_NOT_FOUND;
+	if (where & (size - 1))
+		return PCIBIOS_BAD_REGISTER_NUMBER;
 
 	addr = (dn->busno << 16) | (dn->devfn << 8) | where;
 	buid = dn->phb->buid;
@@ -79,7 +75,15 @@
 		ret = rtas_call(read_pci_config, 2, 2, &returnval, addr, size);
 	}
 	*val = returnval;
-	return ret;
+
+	if (ret)
+		return PCIBIOS_DEVICE_NOT_FOUND;
+
+	if (returnval == EEH_IO_ERROR_VALUE(size)
+	    && eeh_dn_check_failure (dn, NULL))
+		return PCIBIOS_DEVICE_NOT_FOUND;
+
+	return PCIBIOS_SUCCESSFUL;
 }
 
 static int rtas_pci_read_config(struct pci_bus *bus,
@@ -106,7 +110,9 @@
 	int ret;
 
 	if (!dn)
-		return -2;
+		return PCIBIOS_DEVICE_NOT_FOUND;
+	if (where & (size - 1))
+		return PCIBIOS_BAD_REGISTER_NUMBER;
 
 	addr = (dn->busno << 16) | (dn->devfn << 8) | where;
 	buid = dn->phb->buid;
@@ -115,7 +121,11 @@
 	} else {
 		ret = rtas_call(write_pci_config, 3, 1, NULL, addr, size, (ulong)val);
 	}
-	return ret;
+
+	if (ret)
+		return PCIBIOS_DEVICE_NOT_FOUND;
+
+	return PCIBIOS_SUCCESSFUL;
 }
 
 static int rtas_pci_write_config(struct pci_bus *bus,
@@ -141,189 +151,6 @@
 	rtas_pci_write_config
 };
 
-/******************************************************************
- * pci_read_irq_line
- *
- * Reads the Interrupt Pin to determine if interrupt is use by card.
- * If the interrupt is used, then gets the interrupt line from the 
- * openfirmware and sets it in the pci_dev and pci_config line.
- *
- ******************************************************************/
-int pci_read_irq_line(struct pci_dev *pci_dev)
-{
-	u8 intpin;
-	struct device_node *node;
-
-    	pci_read_config_byte(pci_dev, PCI_INTERRUPT_PIN, &intpin);
-
-	if (intpin == 0) {
-		PPCDBG(PPCDBG_BUSWALK,"\tDevice: %s No Interrupt used by device.\n", pci_name(pci_dev));
-		return 0;	
-	}
-
-	node = pci_device_to_OF_node(pci_dev);
-	if (node == NULL) { 
-		PPCDBG(PPCDBG_BUSWALK,"\tDevice: %s Device Node not found.\n",
-		       pci_name(pci_dev));
-		return -1;	
-	}
-	if (node->n_intrs == 0) 	{
-		PPCDBG(PPCDBG_BUSWALK,"\tDevice: %s No Device OF interrupts defined.\n", pci_name(pci_dev));
-		return -1;	
-	}
-	pci_dev->irq = node->intrs[0].line;
-
-	if (s7a_workaround) {
-		if (pci_dev->irq > 16)
-			pci_dev->irq -= 3;
-	}
-
-	pci_write_config_byte(pci_dev, PCI_INTERRUPT_LINE, pci_dev->irq);
-	
-	PPCDBG(PPCDBG_BUSWALK,"\tDevice: %s pci_dev->irq = 0x%02X\n",
-	       pci_name(pci_dev), pci_dev->irq);
-	return 0;
-}
-EXPORT_SYMBOL(pci_read_irq_line);
-
-#define ISA_SPACE_MASK 0x1
-#define ISA_SPACE_IO 0x1
-
-static void pci_process_ISA_OF_ranges(struct device_node *isa_node,
-		                      unsigned long phb_io_base_phys,
-				      void * phb_io_base_virt)
-{
-	struct isa_range *range;
-	unsigned long pci_addr;
-	unsigned int isa_addr;
-	unsigned int size;
-	int rlen = 0;
-
-	range = (struct isa_range *) get_property(isa_node, "ranges", &rlen);
-	if (rlen < sizeof(struct isa_range)) {
-		printk(KERN_ERR "unexpected isa range size: %s\n", 
-				__FUNCTION__);
-		return;	
-	}
-	
-	/* From "ISA Binding to 1275"
-	 * The ranges property is laid out as an array of elements,
-	 * each of which comprises:
-	 *   cells 0 - 1:	an ISA address
-	 *   cells 2 - 4:	a PCI address 
-	 *			(size depending on dev->n_addr_cells)
-	 *   cell 5:		the size of the range
-	 */
-	if ((range->isa_addr.a_hi && ISA_SPACE_MASK) == ISA_SPACE_IO) {
-		isa_addr = range->isa_addr.a_lo;
-		pci_addr = (unsigned long) range->pci_addr.a_mid << 32 | 
-			range->pci_addr.a_lo;
-
-		/* Assume these are both zero */
-		if ((pci_addr != 0) || (isa_addr != 0)) {
-			printk(KERN_ERR "unexpected isa to pci mapping: %s\n",
-					__FUNCTION__);
-			return;
-		}
-		
-		size = PAGE_ALIGN(range->size);
-
-		__ioremap_explicit(phb_io_base_phys, 
-				   (unsigned long) phb_io_base_virt, 
-				   size, _PAGE_NO_CACHE);
-	}
-}
-
-static void __init pci_process_bridge_OF_ranges(struct pci_controller *hose,
-						struct device_node *dev,
-						int primary)
-{
-	unsigned int *ranges;
-	unsigned long size;
-	int rlen = 0;
-	int memno = 0;
-	struct resource *res;
-	int np, na = prom_n_addr_cells(dev);
-	unsigned long pci_addr, cpu_phys_addr;
-	struct device_node *isa_dn;
-
-	np = na + 5;
-
-	/* From "PCI Binding to 1275"
-	 * The ranges property is laid out as an array of elements,
-	 * each of which comprises:
-	 *   cells 0 - 2:	a PCI address
-	 *   cells 3 or 3+4:	a CPU physical address
-	 *			(size depending on dev->n_addr_cells)
-	 *   cells 4+5 or 5+6:	the size of the range
-	 */
-	rlen = 0;
-	hose->io_base_phys = 0;
-	ranges = (unsigned int *) get_property(dev, "ranges", &rlen);
-	while ((rlen -= np * sizeof(unsigned int)) >= 0) {
-		res = NULL;
-		pci_addr = (unsigned long)ranges[1] << 32 | ranges[2];
-
-		cpu_phys_addr = ranges[3];
-		if (na == 2)
-			cpu_phys_addr = cpu_phys_addr << 32 | ranges[4];
-
-		size = (unsigned long)ranges[na+3] << 32 | ranges[na+4];
-
-		switch (ranges[0] >> 24) {
-		case 1:		/* I/O space */
-			hose->io_base_phys = cpu_phys_addr;
-			hose->io_base_virt = reserve_phb_iospace(size);
-			PPCDBG(PPCDBG_PHBINIT, 
-			       "phb%d io_base_phys 0x%lx io_base_virt 0x%lx\n", 
-			       hose->global_number, hose->io_base_phys, 
-			       (unsigned long) hose->io_base_virt);
-
-			if (primary) {
-				pci_io_base = (unsigned long)hose->io_base_virt;
-				isa_dn = of_find_node_by_type(NULL, "isa");
-				if (isa_dn) {
-					isa_io_base = pci_io_base;
-					pci_process_ISA_OF_ranges(isa_dn,
-						hose->io_base_phys,
-						hose->io_base_virt);
-					of_node_put(isa_dn);
-                                        /* Allow all IO */
-                                        io_page_mask = -1;
-				}
-			}
-
-			res = &hose->io_resource;
-			res->flags = IORESOURCE_IO;
-			res->start = pci_addr;
-			res->start += (unsigned long)hose->io_base_virt -
-				pci_io_base;
-			break;
-		case 2:		/* memory space */
-			memno = 0;
-			while (memno < 3 && hose->mem_resources[memno].flags)
-				++memno;
-
-			if (memno == 0)
-				hose->pci_mem_offset = cpu_phys_addr - pci_addr;
-			if (memno < 3) {
-				res = &hose->mem_resources[memno];
-				res->flags = IORESOURCE_MEM;
-				res->start = cpu_phys_addr;
-			}
-			break;
-		}
-		if (res != NULL) {
-			res->name = dev->full_name;
-			res->end = res->start + size - 1;
-			res->parent = NULL;
-			res->sibling = NULL;
-			res->child = NULL;
-		}
-		ranges += np;
-	}
-}
-
 static void python_countermeasures(unsigned long addr)
 {
 	void *chip_regs;
@@ -481,7 +308,7 @@
 	struct pci_controller *phb;
 	unsigned int root_size_cells = 0;
 	unsigned int index;
-	unsigned int *opprop;
+	unsigned int *opprop = NULL;
 	struct device_node *root = of_find_node_by_path("/");
 
 	if (naca->interrupt_controller == IC_OPEN_PIC) {
@@ -519,9 +346,9 @@
 	return 0;
 }
 
+#if 0
 void pcibios_name_device(struct pci_dev *dev)
 {
-#if 0
 	struct device_node *dn;
 
 	/*
@@ -541,98 +368,9 @@
 			}
 		}
 	}
-#endif
 }   
-
-void __devinit pcibios_fixup_device_resources(struct pci_dev *dev,
-					   struct pci_bus *bus)
-{
-	/* Update device resources.  */
-	struct pci_controller *hose = PCI_GET_PHB_PTR(bus);
-	int i;
-
-	for (i = 0; i < PCI_NUM_RESOURCES; i++) {
-		if (dev->resource[i].flags & IORESOURCE_IO) {
-			unsigned long offset = (unsigned long)hose->io_base_virt - pci_io_base;
-                        unsigned long start, end, mask;
-
-                        start = dev->resource[i].start += offset;
-                        end = dev->resource[i].end += offset;
-
-                        /* Need to allow IO access to pages that are in the
-                           ISA range */
-                        if (start < MAX_ISA_PORT) {
-                                if (end > MAX_ISA_PORT)
-                                        end = MAX_ISA_PORT;
-
-                                start >>= PAGE_SHIFT;
-                                end >>= PAGE_SHIFT;
-
-                                /* get the range of pages for the map */
-                                mask = ((1 << (end+1))-1) ^ ((1 << start)-1);
-                                io_page_mask |= mask;
-                        }
-		}
-                else if (dev->resource[i].flags & IORESOURCE_MEM) {
-			dev->resource[i].start += hose->pci_mem_offset;
-			dev->resource[i].end += hose->pci_mem_offset;
-		}
-        }
-}
-EXPORT_SYMBOL(pcibios_fixup_device_resources);
-
-void __devinit pcibios_fixup_bus(struct pci_bus *bus)
-{
-	struct pci_controller *hose = PCI_GET_PHB_PTR(bus);
-	struct list_head *ln;
-
-	/* XXX or bus->parent? */
-	struct pci_dev *dev = bus->self;
-	struct resource *res;
-	int i;
-
-	if (!dev) {
-		/* Root bus. */
-
-		hose->bus = bus;
-		bus->resource[0] = res = &hose->io_resource;
-		if (!res->flags)
-			BUG();	/* No I/O resource for this PHB? */
-
-		if (request_resource(&ioport_resource, res))
-			printk(KERN_ERR "Failed to request IO on "
-					"PCI domain %d\n", pci_domain_nr(bus));
-
-
-		for (i = 0; i < 3; ++i) {
-			res = &hose->mem_resources[i];
-			if (!res->flags && i == 0)
-				BUG();	/* No memory resource for this PHB? */
-			bus->resource[i+1] = res;
-			if (res->flags && request_resource(&iomem_resource, res))
-				printk(KERN_ERR "Failed to request MEM on "
-						"PCI domain %d\n",
-						pci_domain_nr(bus));
-		}
-	} else if (pci_probe_only &&
-		   (dev->class >> 8) == PCI_CLASS_BRIDGE_PCI) {
-		/* This is a subordinate bridge */
-
-		pci_read_bridge_bases(bus);
-		pcibios_fixup_device_resources(dev, bus);
-	}
-
-	/* XXX Need to check why Alpha doesnt do this - Anton */
-	if (!pci_probe_only)
-		return;
-
-	for (ln = bus->devices.next; ln != &bus->devices; ln = ln->next) {
-		struct pci_dev *dev = pci_dev_b(ln);
-		if ((dev->class >> 8) != PCI_CLASS_BRIDGE_PCI)
-			pcibios_fixup_device_resources(dev, bus);
-	}
-}
-EXPORT_SYMBOL(pcibios_fixup_bus);
+DECLARE_PCI_FIXUP_HEADER(PCI_ANY_ID, PCI_ANY_ID, pcibios_name_device);
+#endif
 
 static void check_s7a(void)
 {
@@ -728,13 +466,34 @@
 
 static void phbs_fixup_io(void)
 {
-	struct pci_controller *hose;
+	struct pci_controller *hose, *tmp;
 
-	for (hose=hose_head;hose;hose=hose->next) 
+	list_for_each_entry_safe(hose, tmp, &hose_list, list_node)
 		remap_bus_range(hose->bus);
 }
 
-extern void chrp_request_regions(void);
+static void __init pSeries_request_regions(void)
+{
+	struct device_node *i8042;
+
+	request_region(0x20,0x20,"pic1");
+	request_region(0xa0,0x20,"pic2");
+	request_region(0x00,0x20,"dma1");
+	request_region(0x40,0x20,"timer");
+	request_region(0x80,0x10,"dma page reg");
+	request_region(0xc0,0x20,"dma2");
+
+#define I8042_DATA_REG 0x60
+
+	/*
+	 * Some machines have an unterminated i8042 so check the device
+	 * tree and reserve the region if it does not appear. Later on
+	 * the i8042 code will try and reserve this region and fail.
+	 */
+	if (!(i8042 = of_find_node_by_type(NULL, "8042")))
+		request_region(I8042_DATA_REG, 16, "reserved (no i8042)");
+	of_node_put(i8042);
+}
 
 void __init pSeries_final_fixup(void)
 {
@@ -742,58 +501,23 @@
 
 	check_s7a();
 
-	while ((dev = pci_find_device(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL)
+	while ((dev = pci_find_device(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL) {
 		pci_read_irq_line(dev);
+		if (s7a_workaround) {
+			if (dev->irq > 16) {
+				dev->irq -= 3;
+				pci_write_config_byte(dev, PCI_INTERRUPT_LINE, dev->irq);
+			}
+		}
+	}
 
 	phbs_fixup_io();
-	chrp_request_regions();
+	pSeries_request_regions();
 	pci_fix_bus_sysdata();
-	if (!ppc64_iommu_off)
-		iommu_setup_pSeries();
-}
 
-/*********************************************************************** 
- * pci_find_hose_for_OF_device
- *
- * This function finds the PHB that matching device_node in the 
- * OpenFirmware by scanning all the pci_controllers.
- * 
- ***********************************************************************/
-struct pci_controller*
-pci_find_hose_for_OF_device(struct device_node *node)
-{
-	while (node) {
-		struct pci_controller *hose;
-		for (hose=hose_head;hose;hose=hose->next)
-			if (hose->arch_data == node)
-				return hose;
-		node=node->parent;
-	}
-	return NULL;
-}
-
-/*
- * ppc64 can have multifunction devices that do not respond to function 0.
- * In this case we must scan all functions.
- */
-int
-pcibios_scan_all_fns(struct pci_bus *bus, int devfn)
-{
-       struct device_node *busdn, *dn;
-
-       if (bus->self)
-               busdn = pci_device_to_OF_node(bus->self);
-       else
-               busdn = bus->sysdata;   /* must be a phb */
-
-       /*
-        * Check to see if there is any of the 8 functions are in the
-        * device tree.  If they are then we need to scan all the
-        * functions of this slot.
-        */
-       for (dn = busdn->child; dn; dn = dn->sibling)
-               if ((dn->devfn >> 3) == (devfn >> 3))
-                       return 1;
+	if (!of_chosen || !get_property(of_chosen, "linux,iommu-off", NULL))
+		iommu_setup_pSeries();
 
-       return 0;
+	pci_addr_cache_build();
 }
+
diff -Nru a/arch/ppc64/kernel/pSeries_setup.c b/arch/ppc64/kernel/pSeries_setup.c
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/arch/ppc64/kernel/pSeries_setup.c	2004-10-18 14:55:55 -07:00
@@ -0,0 +1,579 @@
+/*
+ *  linux/arch/ppc/kernel/setup.c
+ *
+ *  Copyright (C) 1995  Linus Torvalds
+ *  Adapted from 'alpha' version by Gary Thomas
+ *  Modified by Cort Dougan (cort@cs.nmt.edu)
+ *  Modified by PPC64 Team, IBM Corp
+ *
+ * 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.
+ */
+
+/*
+ * bootup setup stuff..
+ */
+
+#undef DEBUG
+
+#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/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/ioport.h>
+#include <linux/console.h>
+#include <linux/pci.h>
+#include <linux/version.h>
+#include <linux/adb.h>
+#include <linux/module.h>
+#include <linux/delay.h>
+
+#include <linux/irq.h>
+#include <linux/seq_file.h>
+#include <linux/root_dev.h>
+
+#include <asm/mmu.h>
+#include <asm/processor.h>
+#include <asm/io.h>
+#include <asm/pgtable.h>
+#include <asm/prom.h>
+#include <asm/rtas.h>
+#include <asm/pci-bridge.h>
+#include <asm/iommu.h>
+#include <asm/dma.h>
+#include <asm/machdep.h>
+#include <asm/irq.h>
+#include <asm/naca.h>
+#include <asm/time.h>
+#include <asm/nvram.h>
+
+#include "i8259.h"
+#include "open_pic.h"
+#include <asm/xics.h>
+#include <asm/ppcdebug.h>
+#include <asm/cputable.h>
+
+#ifdef DEBUG
+#define DBG(fmt...) udbg_printf(fmt)
+#else
+#define DBG(fmt...)
+#endif
+
+extern void pSeries_init_openpic(void);
+
+extern void find_and_init_phbs(void);
+extern void pSeries_final_fixup(void);
+
+extern void pSeries_get_boot_time(struct rtc_time *rtc_time);
+extern void pSeries_get_rtc_time(struct rtc_time *rtc_time);
+extern int  pSeries_set_rtc_time(struct rtc_time *rtc_time);
+extern void find_udbg_vterm(void);
+extern void SystemReset_FWNMI(void), MachineCheck_FWNMI(void);	/* from head.S */
+int fwnmi_active;  /* TRUE if an FWNMI handler is present */
+
+unsigned long  virtPython0Facilities = 0;  // python0 facility area (memory mapped io) (64-bit format) VIRTUAL address.
+
+extern unsigned long loops_per_jiffy;
+
+extern unsigned long ppc_proc_freq;
+extern unsigned long ppc_tb_freq;
+
+void pSeries_get_cpuinfo(struct seq_file *m)
+{
+	struct device_node *root;
+	const char *model = "";
+
+	root = of_find_node_by_path("/");
+	if (root)
+		model = get_property(root, "model", NULL);
+	seq_printf(m, "machine\t\t: CHRP %s\n", model);
+	of_node_put(root);
+}
+
+/* Initialize firmware assisted non-maskable interrupts if
+ * the firmware supports this feature.
+ *
+ */
+static void __init fwnmi_init(void)
+{
+	int ret;
+	int ibm_nmi_register = rtas_token("ibm,nmi-register");
+	if (ibm_nmi_register == RTAS_UNKNOWN_SERVICE)
+		return;
+	ret = rtas_call(ibm_nmi_register, 2, 1, NULL,
+			__pa((unsigned long)SystemReset_FWNMI),
+			__pa((unsigned long)MachineCheck_FWNMI));
+	if (ret == 0)
+		fwnmi_active = 1;
+}
+
+static void __init pSeries_setup_arch(void)
+{
+	struct device_node *root;
+	unsigned int *opprop;
+
+	/* Fixup ppc_md depending on the type of interrupt controller */
+	if (naca->interrupt_controller == IC_OPEN_PIC) {
+		ppc_md.init_IRQ       = pSeries_init_openpic; 
+		ppc_md.get_irq        = openpic_get_irq;
+	} else {
+		ppc_md.init_IRQ       = xics_init_IRQ;
+		ppc_md.get_irq        = xics_get_irq;
+	}
+
+#ifdef CONFIG_SMP
+	smp_init_pSeries();
+#endif
+	/* openpic global configuration register (64-bit format). */
+	/* openpic Interrupt Source Unit pointer (64-bit format). */
+	/* python0 facility area (mmio) (64-bit format) REAL address. */
+
+	/* init to some ~sane value until calibrate_delay() runs */
+	loops_per_jiffy = 50000000;
+
+	if (ROOT_DEV == 0) {
+		printk("No ramdisk, default root is /dev/sda2\n");
+		ROOT_DEV = Root_SDA2;
+	}
+
+	fwnmi_init();
+
+	/* Find and initialize PCI host bridges */
+	/* iSeries needs to be done much later. */
+	eeh_init();
+	find_and_init_phbs();
+
+	/* Find the Open PIC if present */
+	root = of_find_node_by_path("/");
+	opprop = (unsigned int *) get_property(root,
+				"platform-open-pic", NULL);
+	if (opprop != 0) {
+		int n = prom_n_addr_cells(root);
+		unsigned long openpic;
+
+		for (openpic = 0; n > 0; --n)
+			openpic = (openpic << 32) + *opprop++;
+		printk(KERN_DEBUG "OpenPIC addr: %lx\n", openpic);
+		OpenPIC_Addr = __ioremap(openpic, 0x40000, _PAGE_NO_CACHE);
+	}
+	of_node_put(root);
+
+#ifdef CONFIG_DUMMY_CONSOLE
+	conswitchp = &dummy_con;
+#endif
+
+	pSeries_nvram_init();
+}
+
+static int __init pSeries_init_panel(void)
+{
+	/* Manually leave the kernel version on the panel. */
+	ppc_md.progress("Linux ppc64\n", 0);
+	ppc_md.progress(UTS_RELEASE, 0);
+
+	return 0;
+}
+arch_initcall(pSeries_init_panel);
+
+
+
+void __init pSeries_find_serial_port(void)
+{
+	struct device_node *np;
+	unsigned long encode_phys_size = 32;
+	u32 *sizeprop;
+
+	struct isa_reg_property {
+		u32 space;
+		u32 address;
+		u32 size;
+	};
+	struct pci_reg_property {
+		struct pci_address addr;
+		u32 size_hi;
+		u32 size_lo;
+	};                                                                        
+
+	DBG(" -> pSeries_find_serial_port()\n");
+
+	naca->serialPortAddr = 0;
+
+	np = of_find_node_by_path("/");
+	if (!np)
+		return;
+	sizeprop = (u32 *)get_property(np, "#size-cells", NULL);
+	if (sizeprop != NULL)
+		encode_phys_size = (*sizeprop) << 5;
+	
+	for (np = NULL; (np = of_find_node_by_type(np, "serial"));) {
+		struct device_node *isa, *pci;
+		struct isa_reg_property *reg;
+		union pci_range *rangesp;
+		char *typep;
+
+	 	typep = (char *)get_property(np, "ibm,aix-loc", NULL);
+		if ((typep == NULL) || (typep && strcmp(typep, "S1")))
+			continue;
+
+		reg = (struct isa_reg_property *)get_property(np, "reg", NULL);	
+
+		isa = of_get_parent(np);
+		if (!isa) {
+			DBG("no isa parent found\n");
+			break;
+		}
+		pci = of_get_parent(isa);
+		if (!pci) {
+			DBG("no pci parent found\n");
+			break;
+		}
+
+		rangesp = (union pci_range *)get_property(pci, "ranges", NULL);
+
+		if ( encode_phys_size == 32 )
+			naca->serialPortAddr = rangesp->pci32.phys+reg->address;
+		else {
+			naca->serialPortAddr =
+				((((unsigned long)rangesp->pci64.phys_hi) << 32)
+				|
+			(rangesp->pci64.phys_lo)) + reg->address;
+		}
+		break;
+	}
+
+	DBG(" <- pSeries_find_serial_port()\n");
+}
+
+
+/* Build up the firmware_features bitmask field
+ * using contents of device-tree/ibm,hypertas-functions.
+ * Ultimately this functionality may be moved into prom.c prom_init().
+ */
+void __init fw_feature_init(void)
+{
+	struct device_node * dn;
+	char * hypertas;
+	unsigned int len;
+
+	DBG(" -> fw_feature_init()\n");
+
+	cur_cpu_spec->firmware_features = 0;
+	dn = of_find_node_by_path("/rtas");
+	if (dn == NULL) {
+		printk(KERN_ERR "WARNING ! Cannot find RTAS in device-tree !\n");
+		goto no_rtas;
+	}
+
+	hypertas = get_property(dn, "ibm,hypertas-functions", &len);
+	if (hypertas) {
+		while (len > 0){
+			int i, hypertas_len;
+			/* check value against table of strings */
+			for(i=0; i < FIRMWARE_MAX_FEATURES ;i++) {
+				if ((firmware_features_table[i].name) &&
+				    (strcmp(firmware_features_table[i].name,hypertas))==0) {
+					/* we have a match */
+					cur_cpu_spec->firmware_features |= 
+						(firmware_features_table[i].val);
+					break;
+				} 
+			}
+			hypertas_len = strlen(hypertas);
+			len -= hypertas_len +1;
+			hypertas+= hypertas_len +1;
+		}
+	}
+
+	of_node_put(dn);
+ no_rtas:
+	printk(KERN_INFO "firmware_features = 0x%lx\n", 
+	       cur_cpu_spec->firmware_features);
+
+	DBG(" <- fw_feature_init()\n");
+}
+
+
+static  void __init pSeries_discover_pic(void)
+{
+	struct device_node *np;
+	char *typep;
+
+	/*
+	 * Setup interrupt mapping options that are needed for finish_device_tree
+	 * to properly parse the OF interrupt tree & do the virtual irq mapping
+	 */
+	__irq_offset_value = NUM_ISA_INTERRUPTS;
+	naca->interrupt_controller = IC_INVALID;
+	for (np = NULL; (np = of_find_node_by_name(np, "interrupt-controller"));) {
+		typep = (char *)get_property(np, "compatible", NULL);
+		if (strstr(typep, "open-pic"))
+			naca->interrupt_controller = IC_OPEN_PIC;
+		else if (strstr(typep, "ppc-xicp"))
+			naca->interrupt_controller = IC_PPC_XIC;
+		else
+			printk("initialize_naca: failed to recognize"
+			       " interrupt-controller\n");
+		break;
+	}
+}
+
+/*
+ * Early initialization.  Relocation is on but do not reference unbolted pages
+ */
+static void __init pSeries_init_early(void)
+{
+	void *comport;
+	int iommu_off = 0;
+
+	DBG(" -> pSeries_init_early()\n");
+
+	fw_feature_init();
+	
+	if (systemcfg->platform & PLATFORM_LPAR)
+		hpte_init_lpar();
+	else {
+		hpte_init_native();
+		iommu_off = (of_chosen &&
+			     get_property(of_chosen, "linux,iommu-off", NULL));
+	}
+
+	pSeries_find_serial_port();
+
+	if (systemcfg->platform & PLATFORM_LPAR)
+		find_udbg_vterm();
+	else if (naca->serialPortAddr) {
+		/* Map the uart for udbg. */
+		comport = (void *)__ioremap(naca->serialPortAddr, 16, _PAGE_NO_CACHE);
+		udbg_init_uart(comport);
+
+		ppc_md.udbg_putc = udbg_putc;
+		ppc_md.udbg_getc = udbg_getc;
+		ppc_md.udbg_getc_poll = udbg_getc_poll;
+		DBG("Hello World !\n");
+	}
+
+
+	if (iommu_off)
+		pci_dma_init_direct();
+	else
+		tce_init_pSeries();
+
+	pSeries_discover_pic();
+
+	DBG(" <- pSeries_init_early()\n");
+}
+
+
+static void pSeries_progress(char *s, unsigned short hex)
+{
+	struct device_node *root;
+	int width, *p;
+	char *os;
+	static int display_character, set_indicator;
+	static int max_width;
+	static spinlock_t progress_lock = SPIN_LOCK_UNLOCKED;
+	static int pending_newline = 0;  /* did last write end with unprinted newline? */
+
+	if (!rtas.base)
+		return;
+
+	if (max_width == 0) {
+		if ((root = find_path_device("/rtas")) &&
+		     (p = (unsigned int *)get_property(root,
+						       "ibm,display-line-length",
+						       NULL)))
+			max_width = *p;
+		else
+			max_width = 0x10;
+		display_character = rtas_token("display-character");
+		set_indicator = rtas_token("set-indicator");
+	}
+
+	if (display_character == RTAS_UNKNOWN_SERVICE) {
+		/* use hex display if available */
+		if (set_indicator != RTAS_UNKNOWN_SERVICE)
+			rtas_call(set_indicator, 3, 1, NULL, 6, 0, hex);
+		return;
+	}
+
+	spin_lock(&progress_lock);
+
+	/*
+	 * Last write ended with newline, but we didn't print it since
+	 * it would just clear the bottom line of output. Print it now
+	 * instead.
+	 *
+	 * If no newline is pending, print a CR to start output at the
+	 * beginning of the line.
+	 */
+	if (pending_newline) {
+		rtas_call(display_character, 1, 1, NULL, '\r');
+		rtas_call(display_character, 1, 1, NULL, '\n');
+		pending_newline = 0;
+	} else {
+		rtas_call(display_character, 1, 1, NULL, '\r');
+	}
+ 
+	width = max_width;
+	os = s;
+	while (*os) {
+		if (*os == '\n' || *os == '\r') {
+			/* Blank to end of line. */
+			while (width-- > 0)
+				rtas_call(display_character, 1, 1, NULL, ' ');
+ 
+			/* If newline is the last character, save it
+			 * until next call to avoid bumping up the
+			 * display output.
+			 */
+			if (*os == '\n' && !os[1]) {
+				pending_newline = 1;
+				spin_unlock(&progress_lock);
+				return;
+			}
+ 
+			/* RTAS wants CR-LF, not just LF */
+ 
+			if (*os == '\n') {
+				rtas_call(display_character, 1, 1, NULL, '\r');
+				rtas_call(display_character, 1, 1, NULL, '\n');
+			} else {
+				/* CR might be used to re-draw a line, so we'll
+				 * leave it alone and not add LF.
+				 */
+				rtas_call(display_character, 1, 1, NULL, *os);
+			}
+ 
+			width = max_width;
+		} else {
+			width--;
+			rtas_call(display_character, 1, 1, NULL, *os);
+		}
+ 
+		os++;
+ 
+		/* if we overwrite the screen length */
+		if (width <= 0)
+			while ((*os != 0) && (*os != '\n') && (*os != '\r'))
+				os++;
+	}
+ 
+	/* Blank to end of line. */
+	while (width-- > 0)
+		rtas_call(display_character, 1, 1, NULL, ' ');
+
+	spin_unlock(&progress_lock);
+}
+
+extern void setup_default_decr(void);
+
+/* Some sane defaults: 125 MHz timebase, 1GHz processor */
+#define DEFAULT_TB_FREQ		125000000UL
+#define DEFAULT_PROC_FREQ	(DEFAULT_TB_FREQ * 8)
+
+static void __init pSeries_calibrate_decr(void)
+{
+	struct device_node *cpu;
+	struct div_result divres;
+	unsigned int *fp;
+	int node_found;
+
+	/*
+	 * The cpu node should have a timebase-frequency property
+	 * to tell us the rate at which the decrementer counts.
+	 */
+	cpu = of_find_node_by_type(NULL, "cpu");
+
+	ppc_tb_freq = DEFAULT_TB_FREQ;		/* hardcoded default */
+	node_found = 0;
+	if (cpu != 0) {
+		fp = (unsigned int *)get_property(cpu, "timebase-frequency",
+						  NULL);
+		if (fp != 0) {
+			node_found = 1;
+			ppc_tb_freq = *fp;
+		}
+	}
+	if (!node_found)
+		printk(KERN_ERR "WARNING: Estimating decrementer frequency "
+				"(not found)\n");
+
+	ppc_proc_freq = DEFAULT_PROC_FREQ;
+	node_found = 0;
+	if (cpu != 0) {
+		fp = (unsigned int *)get_property(cpu, "clock-frequency",
+						  NULL);
+		if (fp != 0) {
+			node_found = 1;
+			ppc_proc_freq = *fp;
+		}
+	}
+	if (!node_found)
+		printk(KERN_ERR "WARNING: Estimating processor frequency "
+				"(not found)\n");
+
+	of_node_put(cpu);
+
+	printk(KERN_INFO "time_init: decrementer frequency = %lu.%.6lu MHz\n",
+	       ppc_tb_freq/1000000, ppc_tb_freq%1000000);
+	printk(KERN_INFO "time_init: processor frequency   = %lu.%.6lu MHz\n",
+	       ppc_proc_freq/1000000, ppc_proc_freq%1000000);
+
+	tb_ticks_per_jiffy = ppc_tb_freq / HZ;
+	tb_ticks_per_sec = tb_ticks_per_jiffy * HZ;
+	tb_ticks_per_usec = ppc_tb_freq / 1000000;
+	tb_to_us = mulhwu_scale_factor(ppc_tb_freq, 1000000);
+	div128_by_32(1024*1024, 0, tb_ticks_per_sec, &divres);
+	tb_to_xs = divres.result_low;
+
+	setup_default_decr();
+}
+
+/*
+ * Called very early, MMU is off, device-tree isn't unflattened
+ */
+extern struct machdep_calls pSeries_md;
+
+static int __init pSeries_probe(int platform)
+{
+	if (platform != PLATFORM_PSERIES &&
+	    platform != PLATFORM_PSERIES_LPAR)
+		return 0;
+
+	/* if we have some ppc_md fixups for LPAR to do, do
+	 * it here ...
+	 */
+
+	return 1;
+}
+
+struct machdep_calls __initdata pSeries_md = {
+	.probe			= pSeries_probe,
+	.setup_arch		= pSeries_setup_arch,
+	.init_early		= pSeries_init_early,
+	.get_cpuinfo		= pSeries_get_cpuinfo,
+	.log_error		= pSeries_log_error,
+	.pcibios_fixup		= pSeries_final_fixup,
+	.restart		= rtas_restart,
+	.power_off		= rtas_power_off,
+	.halt			= rtas_halt,
+	.panic			= rtas_os_term,
+	.get_boot_time		= pSeries_get_boot_time,
+	.get_rtc_time		= pSeries_get_rtc_time,
+	.set_rtc_time		= pSeries_set_rtc_time,
+	.calibrate_decr		= pSeries_calibrate_decr,
+	.progress		= pSeries_progress,
+};
diff -Nru a/arch/ppc64/kernel/pacaData.c b/arch/ppc64/kernel/pacaData.c
--- a/arch/ppc64/kernel/pacaData.c	2004-10-18 14:56:49 -07:00
+++ b/arch/ppc64/kernel/pacaData.c	2004-10-18 14:56:49 -07:00
@@ -27,13 +27,6 @@
  * field correctly */
 extern unsigned long __toc_start;
 
-/* Stack space used when we detect a bad kernel stack pointer, and
- * early in SMP boots before relocation is enabled.
- *
- * ABI requires stack to be 128-byte aligned
- */
-char emergency_stack[PAGE_SIZE * NR_CPUS] __attribute__((aligned(128)));
-
 /* The Paca is an array with one entry per processor.  Each contains an 
  * ItLpPaca, which contains the information shared between the 
  * hypervisor and Linux.  Each also contains an ItLpRegSave area which
@@ -44,18 +37,27 @@
  * processors.  The processor VPD array needs one entry per physical
  * processor (not thread).
  */
-#define PACAINITDATA(number,start,lpq,asrr,asrv)			    \
-{									    \
+#ifdef CONFIG_PPC_ISERIES
+#define EXTRA_INITS(number, lpq)					    \
 	.lppaca_ptr = &paca[number].lppaca,				    \
+	.lpqueue_ptr = (lpq),		/* &xItLpQueue, */		    \
 	.reg_save_ptr = &paca[number].reg_save,				    \
+	.reg_save = {							    \
+		.xDesc = 0xd397d9e2,	/* "LpRS" */			    \
+		.xSize = sizeof(struct ItLpRegSave)			    \
+	},
+#else
+#define EXTRA_INITS(number, lpq)
+#endif
+
+#define PACAINITDATA(number,start,lpq,asrr,asrv)			    \
+{									    \
 	.lock_token = 0x8000,						    \
 	.paca_index = (number),		/* Paca Index */		    \
-	.lpqueue_ptr = (lpq),		/* &xItLpQueue, */		    \
 	.default_decr = 0x00ff0000,	/* Initial Decr */		    \
 	.kernel_toc = (unsigned long)(&__toc_start) + 0x8000UL,		    \
 	.stab_real = (asrr), 		/* Real pointer to segment table */ \
 	.stab_addr = (asrv),		/* Virt pointer to segment table */ \
-	.emergency_sp = &emergency_stack[((number)+1) * PAGE_SIZE],	    \
 	.cpu_start = (start),		/* Processor start */		    \
 	.lppaca = {							    \
 		.xDesc = 0xd397d781,	/* "LpPa" */			    \
@@ -66,13 +68,10 @@
 		.xEndOfQuantum = 0xfffffffffffffffful,			    \
 		.xSLBCount = 64,					    \
 	},								    \
-	.reg_save = {							    \
-		.xDesc = 0xd397d9e2,	/* "LpRS" */			    \
-		.xSize = sizeof(struct ItLpRegSave)			    \
-	},								    \
+	EXTRA_INITS((number), (lpq))					    \
 }
 
-struct paca_struct paca[] __page_aligned = {
+struct paca_struct paca[] = {
 #ifdef CONFIG_PPC_ISERIES
 	PACAINITDATA( 0, 1, &xItLpQueue, 0, STAB0_VIRT_ADDR),
 #else
diff -Nru a/arch/ppc64/kernel/pci.c b/arch/ppc64/kernel/pci.c
--- a/arch/ppc64/kernel/pci.c	2004-10-18 14:56:50 -07:00
+++ b/arch/ppc64/kernel/pci.c	2004-10-18 14:56:50 -07:00
@@ -23,6 +23,7 @@
 #include <linux/bootmem.h>
 #include <linux/module.h>
 #include <linux/mm.h>
+#include <linux/list.h>
 
 #include <asm/processor.h>
 #include <asm/io.h>
@@ -41,6 +42,13 @@
 unsigned long pci_probe_only = 1;
 unsigned long pci_assign_all_buses = 0;
 
+/* legal IO pages under MAX_ISA_PORT.  This is to ensure we don't touch
+   devices we don't have access to. */
+unsigned long io_page_mask;
+
+EXPORT_SYMBOL(io_page_mask);
+
+
 unsigned int pcibios_assign_all_busses(void)
 {
 	return pci_assign_all_buses;
@@ -55,16 +63,9 @@
 unsigned long isa_io_base;	/* NULL if no ISA bus */
 unsigned long pci_io_base;
 
-void pcibios_name_device(struct pci_dev* dev);
-void pcibios_final_fixup(void);
-static void fixup_broken_pcnet32(struct pci_dev* dev);
-static void fixup_windbond_82c105(struct pci_dev* dev);
-extern void fixup_k2_sata(struct pci_dev* dev);
-
 void iSeries_pcibios_init(void);
 
-struct pci_controller *hose_head;
-struct pci_controller **hose_tail = &hose_head;
+LIST_HEAD(hose_list);
 
 struct pci_dma_ops pci_dma_ops;
 EXPORT_SYMBOL(pci_dma_ops);
@@ -74,20 +75,6 @@
 /* Cached ISA bridge dev. */
 struct pci_dev *ppc64_isabridge_dev = NULL;
 
-struct pci_fixup pcibios_fixups[] = {
-	{ PCI_FIXUP_HEADER,	PCI_VENDOR_ID_TRIDENT,		PCI_ANY_ID,
-	  fixup_broken_pcnet32 },
-	{ PCI_FIXUP_HEADER,	PCI_VENDOR_ID_WINBOND,		PCI_DEVICE_ID_WINBOND_82C105,
-	  fixup_windbond_82c105 },
-	{ PCI_FIXUP_HEADER,	PCI_ANY_ID,    			PCI_ANY_ID,
-	  pcibios_name_device },
-#ifdef CONFIG_PPC_PMAC
-	{ PCI_FIXUP_HEADER,	PCI_VENDOR_ID_SERVERWORKS,	0x0240,
-	  fixup_k2_sata },
-#endif
-	{ 0 }
-};
-
 static void fixup_broken_pcnet32(struct pci_dev* dev)
 {
 	if ((dev->class>>8 == PCI_CLASS_NETWORK_ETHERNET)) {
@@ -96,6 +83,7 @@
 		pci_name_device(dev);
 	}
 }
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_TRIDENT, PCI_ANY_ID, fixup_broken_pcnet32);
 
 static void fixup_windbond_82c105(struct pci_dev* dev)
 {
@@ -118,6 +106,7 @@
 			dev->resource[i].flags &= ~IORESOURCE_IO;
 	}
 }
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_WINBOND, PCI_DEVICE_ID_WINBOND_82C105, fixup_windbond_82c105);
 
 void 
 pcibios_resource_to_bus(struct pci_dev *dev, struct pci_bus_region *region,
@@ -239,9 +228,9 @@
 		memcpy(hose->what,model,7);
         hose->type = controller_type;
         hose->global_number = global_phb_number++;
-        
-        *hose_tail = hose;
-        hose_tail = &hose->next;
+
+	list_add_tail(&hose->list_node, &hose_list);
+
         return hose;
 }
 
@@ -281,18 +270,17 @@
 
 static int __init pcibios_init(void)
 {
-	struct pci_controller *hose;
+	struct pci_controller *hose, *tmp;
 	struct pci_bus *bus;
 
 #ifdef CONFIG_PPC_ISERIES
 	iSeries_pcibios_init(); 
 #endif
 
-	//ppc64_boot_msg(0x40, "PCI Probe");
 	printk("PCI: Probing PCI hardware\n");
 
 	/* Scan all of the recorded PCI controllers.  */
-	for (hose = hose_head; hose; hose = hose->next) {
+	list_for_each_entry_safe(hose, tmp, &hose_list, list_node) {
 		hose->last_busno = 0xff;
 		bus = pci_scan_bus(hose->first_busno, hose->ops,
 				   hose->arch_data);
@@ -308,7 +296,7 @@
 		   pci_assign_unassigned_resources() is able to work
 		   correctly with [partially] allocated PCI tree. */
 		pci_assign_unassigned_resources();
-#endif
+#endif /* !CONFIG_PPC_ISERIES */
 
 	/* Call machine dependent final fixup */
 	if (ppc_md.pcibios_fixup)
@@ -320,11 +308,6 @@
 		printk("ISA bridge at %s\n", pci_name(ppc64_isabridge_dev));
 
 	printk("PCI: Probing PCI hardware done\n");
-	//ppc64_boot_msg(0x41, "PCI Done");
-
-#ifdef CONFIG_PPC_PSERIES
-	pci_addr_cache_build();
-#endif
 
 	return 0;
 }
@@ -524,7 +507,7 @@
 	return ret;
 }
 
-#ifdef CONFIG_PPC_PSERIES
+#ifdef CONFIG_PPC_MULTIPLATFORM
 static ssize_t pci_show_devspec(struct device *dev, char *buf)
 {
 	struct pci_dev *pdev;
@@ -537,11 +520,329 @@
 	return sprintf(buf, "%s", np->full_name);
 }
 static DEVICE_ATTR(devspec, S_IRUGO, pci_show_devspec, NULL);
-#endif /* CONFIG_PPC_PSERIES */
+#endif /* CONFIG_PPC_MULTIPLATFORM */
 
 void pcibios_add_platform_entries(struct pci_dev *pdev)
 {
-#ifdef CONFIG_PPC_PSERIES
+#ifdef CONFIG_PPC_MULTIPLATFORM
 	device_create_file(&pdev->dev, &dev_attr_devspec);
-#endif /* CONFIG_PPC_PSERIES */
+#endif /* CONFIG_PPC_MULTIPLATFORM */
+}
+
+#ifdef CONFIG_PPC_MULTIPLATFORM
+
+#define ISA_SPACE_MASK 0x1
+#define ISA_SPACE_IO 0x1
+
+static void pci_process_ISA_OF_ranges(struct device_node *isa_node,
+				      unsigned long phb_io_base_phys,
+				      void * phb_io_base_virt)
+{
+	struct isa_range *range;
+	unsigned long pci_addr;
+	unsigned int isa_addr;
+	unsigned int size;
+	int rlen = 0;
+
+	range = (struct isa_range *) get_property(isa_node, "ranges", &rlen);
+	if (rlen < sizeof(struct isa_range)) {
+		printk(KERN_ERR "unexpected isa range size: %s\n", 
+				__FUNCTION__);
+		return;	
+	}
+	
+	/* From "ISA Binding to 1275"
+	 * The ranges property is laid out as an array of elements,
+	 * each of which comprises:
+	 *   cells 0 - 1:	an ISA address
+	 *   cells 2 - 4:	a PCI address 
+	 *			(size depending on dev->n_addr_cells)
+	 *   cell 5:		the size of the range
+	 */
+	if ((range->isa_addr.a_hi && ISA_SPACE_MASK) == ISA_SPACE_IO) {
+		isa_addr = range->isa_addr.a_lo;
+		pci_addr = (unsigned long) range->pci_addr.a_mid << 32 | 
+			range->pci_addr.a_lo;
+
+		/* Assume these are both zero */
+		if ((pci_addr != 0) || (isa_addr != 0)) {
+			printk(KERN_ERR "unexpected isa to pci mapping: %s\n",
+					__FUNCTION__);
+			return;
+		}
+		
+		size = PAGE_ALIGN(range->size);
+
+		__ioremap_explicit(phb_io_base_phys, 
+				   (unsigned long) phb_io_base_virt, 
+				   size, _PAGE_NO_CACHE);
+	}
+}
+
+void __init pci_process_bridge_OF_ranges(struct pci_controller *hose,
+					 struct device_node *dev, int primary)
+{
+	unsigned int *ranges;
+	unsigned long size;
+	int rlen = 0;
+	int memno = 0;
+	struct resource *res;
+	int np, na = prom_n_addr_cells(dev);
+	unsigned long pci_addr, cpu_phys_addr;
+	struct device_node *isa_dn;
+
+	np = na + 5;
+
+	/* From "PCI Binding to 1275"
+	 * The ranges property is laid out as an array of elements,
+	 * each of which comprises:
+	 *   cells 0 - 2:	a PCI address
+	 *   cells 3 or 3+4:	a CPU physical address
+	 *			(size depending on dev->n_addr_cells)
+	 *   cells 4+5 or 5+6:	the size of the range
+	 */
+	rlen = 0;
+	hose->io_base_phys = 0;
+	ranges = (unsigned int *) get_property(dev, "ranges", &rlen);
+	while ((rlen -= np * sizeof(unsigned int)) >= 0) {
+		res = NULL;
+		pci_addr = (unsigned long)ranges[1] << 32 | ranges[2];
+
+		cpu_phys_addr = ranges[3];
+		if (na == 2)
+			cpu_phys_addr = cpu_phys_addr << 32 | ranges[4];
+
+		size = (unsigned long)ranges[na+3] << 32 | ranges[na+4];
+
+		switch (ranges[0] >> 24) {
+		case 1:		/* I/O space */
+			hose->io_base_phys = cpu_phys_addr;
+			hose->io_base_virt = reserve_phb_iospace(size);
+			PPCDBG(PPCDBG_PHBINIT, 
+			       "phb%d io_base_phys 0x%lx io_base_virt 0x%lx\n", 
+			       hose->global_number, hose->io_base_phys, 
+			       (unsigned long) hose->io_base_virt);
+
+			if (primary) {
+				pci_io_base = (unsigned long)hose->io_base_virt;
+				isa_dn = of_find_node_by_type(NULL, "isa");
+				if (isa_dn) {
+					isa_io_base = pci_io_base;
+					pci_process_ISA_OF_ranges(isa_dn,
+						hose->io_base_phys,
+						hose->io_base_virt);
+					of_node_put(isa_dn);
+                                        /* Allow all IO */
+                                        io_page_mask = -1;
+				}
+			}
+
+			res = &hose->io_resource;
+			res->flags = IORESOURCE_IO;
+			res->start = pci_addr;
+			res->start += (unsigned long)hose->io_base_virt -
+				pci_io_base;
+			break;
+		case 2:		/* memory space */
+			memno = 0;
+			while (memno < 3 && hose->mem_resources[memno].flags)
+				++memno;
+
+			if (memno == 0)
+				hose->pci_mem_offset = cpu_phys_addr - pci_addr;
+			if (memno < 3) {
+				res = &hose->mem_resources[memno];
+				res->flags = IORESOURCE_MEM;
+				res->start = cpu_phys_addr;
+			}
+			break;
+		}
+		if (res != NULL) {
+			res->name = dev->full_name;
+			res->end = res->start + size - 1;
+			res->parent = NULL;
+			res->sibling = NULL;
+			res->child = NULL;
+		}
+		ranges += np;
+	}
+}
+
+/*********************************************************************** 
+ * pci_find_hose_for_OF_device
+ *
+ * This function finds the PHB that matching device_node in the 
+ * OpenFirmware by scanning all the pci_controllers.
+ * 
+ ***********************************************************************/
+struct pci_controller* pci_find_hose_for_OF_device(struct device_node *node)
+{
+	while (node) {
+		struct pci_controller *hose, *tmp;
+		list_for_each_entry_safe(hose, tmp, &hose_list, list_node)
+			if (hose->arch_data == node)
+				return hose;
+		node=node->parent;
+	}
+	return NULL;
+}
+
+/*
+ * ppc64 can have multifunction devices that do not respond to function 0.
+ * In this case we must scan all functions.
+ */
+int pcibios_scan_all_fns(struct pci_bus *bus, int devfn)
+{
+       struct device_node *busdn, *dn;
+
+       if (bus->self)
+               busdn = pci_device_to_OF_node(bus->self);
+       else
+               busdn = bus->sysdata;   /* must be a phb */
+
+       /*
+        * Check to see if there is any of the 8 functions are in the
+        * device tree.  If they are then we need to scan all the
+        * functions of this slot.
+        */
+       for (dn = busdn->child; dn; dn = dn->sibling)
+               if ((dn->devfn >> 3) == (devfn >> 3))
+                       return 1;
+
+       return 0;
+}
+
+
+void __devinit pcibios_fixup_device_resources(struct pci_dev *dev,
+					   struct pci_bus *bus)
+{
+	/* Update device resources.  */
+	struct pci_controller *hose = PCI_GET_PHB_PTR(bus);
+	int i;
+
+	for (i = 0; i < PCI_NUM_RESOURCES; i++) {
+		if (dev->resource[i].flags & IORESOURCE_IO) {
+			unsigned long offset = (unsigned long)hose->io_base_virt - pci_io_base;
+                        unsigned long start, end, mask;
+
+                        start = dev->resource[i].start += offset;
+                        end = dev->resource[i].end += offset;
+
+                        /* Need to allow IO access to pages that are in the
+                           ISA range */
+                        if (start < MAX_ISA_PORT) {
+                                if (end > MAX_ISA_PORT)
+                                        end = MAX_ISA_PORT;
+
+                                start >>= PAGE_SHIFT;
+                                end >>= PAGE_SHIFT;
+
+                                /* get the range of pages for the map */
+                                mask = ((1 << (end+1))-1) ^ ((1 << start)-1);
+                                io_page_mask |= mask;
+                        }
+		}
+                else if (dev->resource[i].flags & IORESOURCE_MEM) {
+			dev->resource[i].start += hose->pci_mem_offset;
+			dev->resource[i].end += hose->pci_mem_offset;
+		}
+        }
 }
+EXPORT_SYMBOL(pcibios_fixup_device_resources);
+
+void __devinit pcibios_fixup_bus(struct pci_bus *bus)
+{
+	struct pci_controller *hose = PCI_GET_PHB_PTR(bus);
+	struct list_head *ln;
+
+	/* XXX or bus->parent? */
+	struct pci_dev *dev = bus->self;
+	struct resource *res;
+	int i;
+
+	if (!dev) {
+		/* Root bus. */
+
+		hose->bus = bus;
+		bus->resource[0] = res = &hose->io_resource;
+		if (!res->flags)
+			BUG();	/* No I/O resource for this PHB? */
+
+		if (request_resource(&ioport_resource, res))
+			printk(KERN_ERR "Failed to request IO on "
+					"PCI domain %d\n", pci_domain_nr(bus));
+
+
+		for (i = 0; i < 3; ++i) {
+			res = &hose->mem_resources[i];
+			if (!res->flags && i == 0)
+				BUG();	/* No memory resource for this PHB? */
+			bus->resource[i+1] = res;
+			if (res->flags && request_resource(&iomem_resource, res))
+				printk(KERN_ERR "Failed to request MEM on "
+						"PCI domain %d\n",
+						pci_domain_nr(bus));
+		}
+	} else if (pci_probe_only &&
+		   (dev->class >> 8) == PCI_CLASS_BRIDGE_PCI) {
+		/* This is a subordinate bridge */
+
+		pci_read_bridge_bases(bus);
+		pcibios_fixup_device_resources(dev, bus);
+	}
+
+	/* XXX Need to check why Alpha doesnt do this - Anton */
+	if (!pci_probe_only)
+		return;
+
+	for (ln = bus->devices.next; ln != &bus->devices; ln = ln->next) {
+		struct pci_dev *dev = pci_dev_b(ln);
+		if ((dev->class >> 8) != PCI_CLASS_BRIDGE_PCI)
+			pcibios_fixup_device_resources(dev, bus);
+	}
+}
+EXPORT_SYMBOL(pcibios_fixup_bus);
+
+/******************************************************************
+ * pci_read_irq_line
+ *
+ * Reads the Interrupt Pin to determine if interrupt is use by card.
+ * If the interrupt is used, then gets the interrupt line from the 
+ * openfirmware and sets it in the pci_dev and pci_config line.
+ *
+ ******************************************************************/
+int pci_read_irq_line(struct pci_dev *pci_dev)
+{
+	u8 intpin;
+	struct device_node *node;
+
+    	pci_read_config_byte(pci_dev, PCI_INTERRUPT_PIN, &intpin);
+
+	if (intpin == 0) {
+		PPCDBG(PPCDBG_BUSWALK,"\tDevice: %s No Interrupt used by device.\n",
+		       pci_name(pci_dev));
+		return 0;	
+	}
+
+	node = pci_device_to_OF_node(pci_dev);
+	if (node == NULL) { 
+		PPCDBG(PPCDBG_BUSWALK,"\tDevice: %s Device Node not found.\n",
+		       pci_name(pci_dev));
+		return -1;	
+	}
+	if (node->n_intrs == 0) 	{
+		PPCDBG(PPCDBG_BUSWALK,"\tDevice: %s No Device OF interrupts defined.\n",
+		       pci_name(pci_dev));
+		return -1;	
+	}
+	pci_dev->irq = node->intrs[0].line;
+
+	pci_write_config_byte(pci_dev, PCI_INTERRUPT_LINE, pci_dev->irq);
+	
+	PPCDBG(PPCDBG_BUSWALK,"\tDevice: %s pci_dev->irq = 0x%02X\n",
+	       pci_name(pci_dev), pci_dev->irq);
+	return 0;
+}
+EXPORT_SYMBOL(pci_read_irq_line);
+
+#endif /* CONFIG_PPC_MULTIPLATFORM */
diff -Nru a/arch/ppc64/kernel/pci.h b/arch/ppc64/kernel/pci.h
--- a/arch/ppc64/kernel/pci.h	2004-10-18 14:55:53 -07:00
+++ b/arch/ppc64/kernel/pci.h	2004-10-18 14:55:53 -07:00
@@ -17,9 +17,7 @@
 extern struct pci_controller* pci_alloc_pci_controller(enum phb_types controller_type);
 extern struct pci_controller* pci_find_hose_for_OF_device(struct device_node* node);
 
-extern struct pci_controller* hose_head;
-extern struct pci_controller** hose_tail;
-
+extern struct list_head hose_list;
 extern int global_phb_number;
 
 /*******************************************************************
diff -Nru a/arch/ppc64/kernel/pci_dn.c b/arch/ppc64/kernel/pci_dn.c
--- a/arch/ppc64/kernel/pci_dn.c	2004-10-18 14:57:05 -07:00
+++ b/arch/ppc64/kernel/pci_dn.c	2004-10-18 14:57:05 -07:00
@@ -129,10 +129,10 @@
  */
 static void *traverse_all_pci_devices(traverse_func pre)
 {
-	struct pci_controller *phb;
+	struct pci_controller *phb, *tmp;
 	void *ret;
 
-	for (phb = hose_head; phb; phb = phb->next)
+	list_for_each_entry_safe(phb, tmp, &hose_list, list_node)
 		if ((ret = traverse_pci_devices(phb->arch_data, pre, phb))
 				!= NULL)
 			return ret;
diff -Nru a/arch/ppc64/kernel/pci_iommu.c b/arch/ppc64/kernel/pci_iommu.c
--- a/arch/ppc64/kernel/pci_iommu.c	2004-10-18 14:56:48 -07:00
+++ b/arch/ppc64/kernel/pci_iommu.c	2004-10-18 14:56:48 -07:00
@@ -54,9 +54,9 @@
 	return ISERIES_DEVNODE(dev)->iommu_table;
 #endif /* CONFIG_PPC_ISERIES */
 
-#ifdef CONFIG_PPC_PSERIES
+#ifdef CONFIG_PPC_MULTIPLATFORM
 	return PCI_GET_DN(dev)->iommu_table;
-#endif /* CONFIG_PPC_PSERIES */
+#endif /* CONFIG_PPC_MULTIPLATFORM */
 }
 
 
diff -Nru a/arch/ppc64/kernel/pmac_feature.c b/arch/ppc64/kernel/pmac_feature.c
--- a/arch/ppc64/kernel/pmac_feature.c	2004-10-18 14:56:49 -07:00
+++ b/arch/ppc64/kernel/pmac_feature.c	2004-10-18 14:56:49 -07:00
@@ -44,9 +44,9 @@
 #undef DEBUG_FEATURE
 
 #ifdef DEBUG_FEATURE
-#define DBG(fmt,...) printk(KERN_DEBUG fmt)
+#define DBG(fmt...) printk(KERN_DEBUG fmt)
 #else
-#define DBG(fmt,...)
+#define DBG(fmt...)
 #endif
 
 /*
@@ -343,6 +343,10 @@
 		PMAC_TYPE_POWERMAC_G5,		g5_features,
 		0,
 	},
+	{	"PowerMac7,3",			"PowerMac G5",
+		PMAC_TYPE_POWERMAC_G5,		g5_features,
+		0,
+	},
 	{       "RackMac3,1",                   "XServe G5",
 		PMAC_TYPE_POWERMAC_G5,          g5_features,
 		0,
@@ -611,7 +615,7 @@
 
 device_initcall(pmac_feature_late_init);
 
-
+#if 0
 static void dump_HT_speeds(char *name, u32 cfg, u32 frq)
 {
 	int	freqs[16] = { 200,300,400,500,600,800,1000,0,0,0,0,0,0,0,0,0 };
@@ -625,6 +629,7 @@
 		       name, freqs[freq],
 		       bits[(cfg >> 28) & 0x7], bits[(cfg >> 24) & 0x7]);
 }
+#endif
 
 void __init pmac_check_ht_link(void)
 {
diff -Nru a/arch/ppc64/kernel/pmac_iommu.c b/arch/ppc64/kernel/pmac_iommu.c
--- a/arch/ppc64/kernel/pmac_iommu.c	2004-10-18 14:57:04 -07:00
+++ /dev/null	Wed Dec 31 16:00:00 196900
@@ -1,305 +0,0 @@
-/*
- * arch/ppc64/kernel/pmac_iommu.c
- *
- * Copyright (C) 2004 Olof Johansson <olof@austin.ibm.com>, IBM Corporation
- *
- * Based on pSeries_iommu.c:
- * Copyright (C) 2001 Mike Corrigan & Dave Engebretsen, IBM Corporation
- * Copyright (C) 2004 Olof Johansson <olof@austin.ibm.com>, IBM Corporation
- *
- * Dynamic DMA mapping support, PowerMac G5 (DART)-specific parts.
- *
- * 
- * 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
- */
-
-#include <linux/config.h>
-#include <linux/init.h>
-#include <linux/types.h>
-#include <linux/slab.h>
-#include <linux/mm.h>
-#include <linux/spinlock.h>
-#include <linux/string.h>
-#include <linux/pci.h>
-#include <linux/dma-mapping.h>
-#include <linux/vmalloc.h>
-#include <asm/io.h>
-#include <asm/prom.h>
-#include <asm/rtas.h>
-#include <asm/ppcdebug.h>
-#include <asm/iommu.h>
-#include <asm/pci-bridge.h>
-#include <asm/machdep.h>
-#include <asm/abs_addr.h>
-#include <asm/cacheflush.h>
-#include "pci.h"
-
-
-/* physical base of DART registers */
-#define DART_BASE        0xf8033000UL
-
-/* Offset from base to control register */
-#define DARTCNTL   0
-/* Offset from base to exception register */
-#define DARTEXCP   0x10
-/* Offset from base to TLB tag registers */
-#define DARTTAG    0x1000
-
-
-/* Control Register fields */
-
-/* base address of table (pfn) */
-#define DARTCNTL_BASE_MASK    0xfffff
-#define DARTCNTL_BASE_SHIFT   12
-
-#define DARTCNTL_FLUSHTLB     0x400
-#define DARTCNTL_ENABLE       0x200
-
-/* size of table in pages */
-#define DARTCNTL_SIZE_MASK    0x1ff
-#define DARTCNTL_SIZE_SHIFT   0
-
-/* DART table fields */
-#define DARTMAP_VALID   0x80000000
-#define DARTMAP_RPNMASK 0x00ffffff
-
-/* Physical base address and size of the DART table */
-unsigned long dart_tablebase;
-unsigned long dart_tablesize;
-
-/* Virtual base address of the DART table */
-static u32 *dart_vbase;
-
-/* Mapped base address for the dart */
-static unsigned int *dart; 
-
-/* Dummy val that entries are set to when unused */
-static unsigned int dart_emptyval;
-
-static struct iommu_table iommu_table_pmac;
-static int dart_dirty;
-
-#define DBG(...)
-
-static inline void dart_tlb_invalidate_all(void)
-{
-	unsigned long l = 0;
-	unsigned int reg;
-	unsigned long limit;
-
-	DBG("dart: flush\n");
-
-	/* To invalidate the DART, set the DARTCNTL_FLUSHTLB bit in the
-	 * control register and wait for it to clear.
-	 *
-	 * Gotcha: Sometimes, the DART won't detect that the bit gets
-	 * set. If so, clear it and set it again.
-	 */ 
-
-	limit = 0;
-
-retry:
-	reg = in_be32((unsigned int *)dart+DARTCNTL);
-	reg |= DARTCNTL_FLUSHTLB;
-	out_be32((unsigned int *)dart+DARTCNTL, reg);
-
-	l = 0;
-	while ((in_be32((unsigned int *)dart+DARTCNTL) & DARTCNTL_FLUSHTLB) &&
-		l < (1L<<limit)) {
-		l++;
-	}
-	if (l == (1L<<limit)) {
-		if (limit < 4) {
-			limit++;
-		        reg = in_be32((unsigned int *)dart+DARTCNTL);
-		        reg &= ~DARTCNTL_FLUSHTLB;
-		        out_be32((unsigned int *)dart+DARTCNTL, reg);
-			goto retry;
-		} else
-			panic("U3-DART: TLB did not flush after waiting a long "
-			      "time. Buggy U3 ?");
-	}
-}
-
-static void dart_flush(struct iommu_table *tbl)
-{
-	if (dart_dirty)
-		dart_tlb_invalidate_all();
-	dart_dirty = 0;
-}
-
-static void dart_build_pmac(struct iommu_table *tbl, long index, 
-			    long npages, unsigned long uaddr,
-			    enum dma_data_direction direction)
-{
-	unsigned int *dp;
-	unsigned int rpn;
-
-	DBG("dart: build at: %lx, %lx, addr: %x\n", index, npages, uaddr);
-
-	dp = ((unsigned int*)tbl->it_base) + index;
-	
-	/* On pmac, all memory is contigous, so we can move this
-	 * out of the loop.
-	 */
-	while (npages--) {
-		rpn = virt_to_abs(uaddr) >> PAGE_SHIFT;
-
-		*(dp++) = DARTMAP_VALID | (rpn & DARTMAP_RPNMASK);
-
-		rpn++;
-		uaddr += PAGE_SIZE;
-	}
-
-	dart_dirty = 1;
-}
-
-
-static void dart_free_pmac(struct iommu_table *tbl, long index, long npages)
-{
-	unsigned int *dp;
-	
-	/* We don't worry about flushing the TLB cache. The only drawback of
-	 * not doing it is that we won't catch buggy device drivers doing
-	 * bad DMAs, but then no 32-bit architecture ever does either.
-	 */
-
-	DBG("dart: free at: %lx, %lx\n", index, npages);
-
-	dp  = ((unsigned int *)tbl->it_base) + index;
-		
-	while (npages--)
-		*(dp++) = dart_emptyval;
-}
-
-
-static int dart_init(struct device_node *dart_node)
-{
-	unsigned int regword;
-	unsigned int i;
-	unsigned long tmp;
-	struct page *p;
-
-	if (dart_tablebase == 0 || dart_tablesize == 0) {
-		printk(KERN_INFO "U3-DART: table not allocated, using direct DMA\n");
-		return -ENODEV;
-	}
-
-	/* Make sure nothing from the DART range remains in the CPU cache
-	 * from a previous mapping that existed before the kernel took
-	 * over
-	 */
-	flush_dcache_phys_range(dart_tablebase, dart_tablebase + dart_tablesize);
-
-	/* Allocate a spare page to map all invalid DART pages. We need to do
-	 * that to work around what looks like a problem with the HT bridge
-	 * prefetching into invalid pages and corrupting data
-	 */
-	tmp = __get_free_pages(GFP_ATOMIC, 1);
-	if (tmp == 0)
-		panic("U3-DART: Cannot allocate spare page !");
-	dart_emptyval = DARTMAP_VALID |
-		((virt_to_abs(tmp) >> PAGE_SHIFT) & DARTMAP_RPNMASK);
-
-	/* Map in DART registers. FIXME: Use device node to get base address */
-	dart = ioremap(DART_BASE, 0x7000);
-	if (dart == NULL)
-		panic("U3-DART: Cannot map registers !");
-
-	/* Set initial control register contents: table base, 
-	 * table size and enable bit
-	 */
-	regword = DARTCNTL_ENABLE | 
-		((dart_tablebase >> PAGE_SHIFT) << DARTCNTL_BASE_SHIFT) |
-		(((dart_tablesize >> PAGE_SHIFT) & DARTCNTL_SIZE_MASK)
-				 << DARTCNTL_SIZE_SHIFT);
-	p = virt_to_page(dart_tablebase);
-	dart_vbase = ioremap(virt_to_abs(dart_tablebase), dart_tablesize);
-
-	/* Fill initial table */
-	for (i = 0; i < dart_tablesize/4; i++)
-		dart_vbase[i] = dart_emptyval;
-
-	/* Initialize DART with table base and enable it. */
-	out_be32((unsigned int *)dart, regword);
-
-	/* Invalidate DART to get rid of possible stale TLBs */
-	dart_tlb_invalidate_all();
-
-	iommu_table_pmac.it_busno = 0;
-	
-	/* Units of tce entries */
-	iommu_table_pmac.it_offset = 0;
-	
-	/* Set the tce table size - measured in pages */
-	iommu_table_pmac.it_size = dart_tablesize >> PAGE_SHIFT;
-
-	/* Initialize the common IOMMU code */
-	iommu_table_pmac.it_base = (unsigned long)dart_vbase;
-	iommu_table_pmac.it_index = 0;
-	iommu_table_pmac.it_blocksize = 1;
-	iommu_table_pmac.it_entrysize = sizeof(u32);
-	iommu_init_table(&iommu_table_pmac);
-
-	/* Reserve the last page of the DART to avoid possible prefetch
-	 * past the DART mapped area
-	 */
-	set_bit(iommu_table_pmac.it_mapsize - 1, iommu_table_pmac.it_map);
-
-	printk(KERN_INFO "U3-DART IOMMU initialized\n");
-
-	return 0;
-}
-
-
-void iommu_setup_pmac(void)
-{
-	struct pci_dev *dev = NULL;
-	struct device_node *dn;
-
-	/* Find the DART in the device-tree */
-	dn = of_find_compatible_node(NULL, "dart", "u3-dart");
-	if (dn == NULL)
-		return;
-
-	/* Setup low level TCE operations for the core IOMMU code */
-	ppc_md.tce_build = dart_build_pmac;
-	ppc_md.tce_free  = dart_free_pmac;
-	ppc_md.tce_flush = dart_flush;
-
-	/* Initialize the DART HW */
-	if (dart_init(dn))
-		return;
-
-	/* Setup pci_dma ops */
-	pci_iommu_init();
-
-	/* We only have one iommu table on the mac for now, which makes
-	 * things simple. Setup all PCI devices to point to this table
-	 */
-	while ((dev = pci_find_device(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL) {
-		/* We must use pci_device_to_OF_node() to make sure that
-		 * we get the real "final" pointer to the device in the
-		 * pci_dev sysdata and not the temporary PHB one
-		 */
-		struct device_node *dn = pci_device_to_OF_node(dev);
-		if (dn)
-			dn->iommu_table = &iommu_table_pmac;
-	}
-}
-
-
-
-
diff -Nru a/arch/ppc64/kernel/pmac_low_i2c.c b/arch/ppc64/kernel/pmac_low_i2c.c
--- a/arch/ppc64/kernel/pmac_low_i2c.c	2004-10-18 14:56:28 -07:00
+++ b/arch/ppc64/kernel/pmac_low_i2c.c	2004-10-18 14:56:28 -07:00
@@ -50,7 +50,7 @@
 	struct device_node	*np;		/* OF device node */
 	struct semaphore	mutex;		/* Access mutex for use by i2c-keywest */
 	low_i2c_func_t		func;		/* Access function */
-	int			is_open : 1;	/* Poor man's access control */
+	unsigned		is_open : 1;	/* Poor man's access control */
 	int			mode;		/* Current mode */
 	int			channel;	/* Current channel */
 	int			num_channels;	/* Number of channels */
diff -Nru a/arch/ppc64/kernel/pmac_pci.c b/arch/ppc64/kernel/pmac_pci.c
--- a/arch/ppc64/kernel/pmac_pci.c	2004-10-18 14:56:48 -07:00
+++ b/arch/ppc64/kernel/pmac_pci.c	2004-10-18 14:56:48 -07:00
@@ -271,7 +271,7 @@
 				    int offset, int len, u32 *val)
 {
 	struct pci_controller *hose;
-	struct device_node *busdn;
+	struct device_node *busdn, *dn;
 	unsigned long addr;
 
 	if (bus->self)
@@ -284,6 +284,16 @@
 	if (hose == NULL)
 		return PCIBIOS_DEVICE_NOT_FOUND;
 
+	/* We only allow config cycles to devices that are in OF device-tree
+	 * as we are apparently having some weird things going on with some
+	 * revs of K2 on recent G5s
+	 */
+	for (dn = busdn->child; dn; dn = dn->sibling)
+		if (dn->devfn == devfn)
+			break;
+	if (dn == NULL)
+		return PCIBIOS_DEVICE_NOT_FOUND;
+
 	addr = u3_ht_cfg_access(hose, bus->number, devfn, offset);
 	if (!addr)
 		return PCIBIOS_DEVICE_NOT_FOUND;
@@ -419,7 +429,7 @@
 	 * properties or figuring out the U3 address space decoding logic and
 	 * then read it's configuration register (if any).
 	 */
-	hose->io_base_phys = 0xf4000000 + 0x00400000;
+	hose->io_base_phys = 0xf4000000;
 	hose->io_base_virt = ioremap(hose->io_base_phys, 0x00400000);
 	isa_io_base = pci_io_base = (unsigned long) hose->io_base_virt;
 	hose->io_resource.name = np->full_name;
@@ -664,17 +674,15 @@
 
 	pci_fix_bus_sysdata();
 
-#ifdef CONFIG_PMAC_DART
-	iommu_setup_pmac();
-#endif /* CONFIG_PMAC_DART */
+	iommu_setup_u3();
 
 }
 
 static void __init pmac_fixup_phb_resources(void)
 {
-	struct pci_controller *hose;
+	struct pci_controller *hose, *tmp;
 	
-	for (hose = hose_head; hose; hose = hose->next) {
+	list_for_each_entry_safe(hose, tmp, &hose_list, list_node) {
 		unsigned long offset = (unsigned long)hose->io_base_virt - pci_io_base;
 		hose->io_resource.start += offset;
 		hose->io_resource.end += offset;
@@ -746,6 +754,9 @@
 	 * the exception of U3/AGP (hook into pci_set_mwi)
 	 */
 	pci_cache_line_size = 16; /* 64 bytes */
+
+	/* Allow all IO */
+	io_page_mask = -1;
 }
 
 /*
@@ -777,3 +788,4 @@
 		}
 	}
 }
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_SERVERWORKS, 0x0240, fixup_k2_sata);
diff -Nru a/arch/ppc64/kernel/pmac_setup.c b/arch/ppc64/kernel/pmac_setup.c
--- a/arch/ppc64/kernel/pmac_setup.c	2004-10-18 14:55:55 -07:00
+++ b/arch/ppc64/kernel/pmac_setup.c	2004-10-18 14:55:55 -07:00
@@ -23,6 +23,8 @@
  * bootup setup stuff..
  */
 
+#undef DEBUG
+
 #include <linux/config.h>
 #include <linux/init.h>
 #include <linux/errno.h>
@@ -63,7 +65,6 @@
 #include <asm/iommu.h>
 #include <asm/machdep.h>
 #include <asm/dma.h>
-#include <asm/bootx.h>
 #include <asm/btext.h>
 #include <asm/cputable.h>
 #include <asm/pmac_feature.h>
@@ -73,6 +74,13 @@
 
 #include "pmac.h"
 
+#ifdef DEBUG
+#define DBG(fmt...) udbg_printf(fmt)
+#else
+#define DBG(fmt...)
+#endif
+
+
 static int current_root_goodness = -1;
 #define DEFAULT_ROOT_DEVICE Root_SDA1	/* sda1 - slightly silly choice */
 
@@ -81,10 +89,6 @@
 
 extern void udbg_init_scc(struct device_node *np);
 
-#ifdef CONFIG_BOOTX_TEXT
-void pmac_progress(char *s, unsigned short hex);
-#endif
-
 void __pmac pmac_show_cpuinfo(struct seq_file *m)
 {
 	struct device_node *np;
@@ -134,28 +138,20 @@
 
 void __init pmac_setup_arch(void)
 {
-	struct device_node *cpu;
-	int *fp;
-	unsigned long pvr;
-
-	pvr = PVR_VER(mfspr(PVR));
-
-	/* Set loops_per_jiffy to a half-way reasonable value,
-	   for use until calibrate_delay gets called. */
-	cpu = find_type_devices("cpu");
-	if (cpu != 0) {
-		fp = (int *) get_property(cpu, "clock-frequency", NULL);
-		if (fp != 0) {
-			if (pvr == 4 || pvr >= 8)
-				/* 604, G3, G4 etc. */
-				loops_per_jiffy = *fp / HZ;
-			else
-				/* 601, 603, etc. */
-				loops_per_jiffy = *fp / (2*HZ);
-		} else
-			loops_per_jiffy = 50000000 / HZ;
+	/* init to some ~sane value until calibrate_delay() runs */
+	loops_per_jiffy = 50000000;
+
+	/* Probe motherboard chipset */
+	pmac_feature_init();
+#if 0
+	/* Lock-enable the SCC channel used for debug */
+	if (sccdbg) {
+		np = of_find_node_by_name(NULL, "escc");
+		if (np)
+			pmac_call_feature(PMAC_FTR_SCC_ENABLE, np,
+					  PMAC_SCC_ASYNC | PMAC_SCC_FLAG_XMON, 1);
 	}
-	
+#endif
 	/* We can NAP */
 	powersave_nap = 1;
 
@@ -183,67 +179,13 @@
 #endif
 }
 
-extern char *bootpath;
-extern char *bootdevice;
-void *boot_host;
-int boot_target;
-int boot_part;
-extern dev_t boot_dev;
-
 #ifdef CONFIG_SCSI
-void __init note_scsi_host(struct device_node *node, void *host)
+void note_scsi_host(struct device_node *node, void *host)
 {
-	int l;
-	char *p;
-
-	l = strlen(node->full_name);
-	if (bootpath != NULL && bootdevice != NULL
-	    && strncmp(node->full_name, bootdevice, l) == 0
-	    && (bootdevice[l] == '/' || bootdevice[l] == 0)) {
-		boot_host = host;
-		/*
-		 * There's a bug in OF 1.0.5.  (Why am I not surprised.)
-		 * If you pass a path like scsi/sd@1:0 to canon, it returns
-		 * something like /bandit@F2000000/gc@10/53c94@10000/sd@0,0
-		 * That is, the scsi target number doesn't get preserved.
-		 * So we pick the target number out of bootpath and use that.
-		 */
-		p = strstr(bootpath, "/sd@");
-		if (p != NULL) {
-			p += 4;
-			boot_target = simple_strtoul(p, NULL, 10);
-			p = strchr(p, ':');
-			if (p != NULL)
-				boot_part = simple_strtoul(p + 1, NULL, 10);
-		}
-	}
+	/* Obsolete */
 }
 #endif
 
-#if defined(CONFIG_BLK_DEV_IDE) && defined(CONFIG_BLK_DEV_IDE_PMAC)
-static dev_t __init find_ide_boot(void)
-{
-	char *p;
-	int n;
-	dev_t __init pmac_find_ide_boot(char *bootdevice, int n);
-
-	if (bootdevice == NULL)
-		return 0;
-	p = strrchr(bootdevice, '/');
-	if (p == NULL)
-		return 0;
-	n = p - bootdevice;
-
-	return pmac_find_ide_boot(bootdevice, n);
-}
-#endif /* CONFIG_BLK_DEV_IDE && CONFIG_BLK_DEV_IDE_PMAC */
-
-void __init find_boot_device(void)
-{
-#if defined(CONFIG_BLK_DEV_IDE) && defined(CONFIG_BLK_DEV_IDE_PMAC)
-	boot_dev = find_ide_boot();
-#endif
-}
 
 static int initializing = 1;
 
@@ -258,7 +200,7 @@
 /* can't be __init - can be called whenever a disk is first accessed */
 void __pmac note_bootable_part(dev_t dev, int part, int goodness)
 {
-	static int found_boot = 0;
+	extern dev_t boot_dev;
 	char *p;
 
 	if (!initializing)
@@ -270,10 +212,6 @@
 	if (p != NULL && (p == saved_command_line || p[-1] == ' '))
 		return;
 
-	if (!found_boot) {
-		find_boot_device();
-		found_boot = 1;
-	}
 	if (!boot_dev || dev == boot_dev) {
 		ROOT_DEV = dev + part;
 		boot_dev = 0;
@@ -313,21 +251,73 @@
 }
 #endif /* CONFIG_BOOTX_TEXT */
 
+static void __init init_boot_display(void)
+{
+	char *name;
+	struct device_node *np = NULL; 
+	int rc = -ENODEV;
+
+	printk("trying to initialize btext ...\n");
+
+	name = (char *)get_property(of_chosen, "linux,stdout-path", NULL);
+	if (name != NULL) {
+		np = of_find_node_by_path(name);
+		if (np != NULL) {
+			if (strcmp(np->type, "display") != 0) {
+				printk("boot stdout isn't a display !\n");
+				of_node_put(np);
+				np = NULL;
+			}
+		}
+	}
+	if (np)
+		rc = btext_initialize(np);
+	if (rc == 0)
+		return;
+
+	for (np = NULL; (np = of_find_node_by_type(np, "display"));) {
+		if (get_property(np, "linux,opened", NULL)) {
+			printk("trying %s ...\n", np->full_name);
+			rc = btext_initialize(np);
+			printk("result: %d\n", rc);
+		}
+		if (rc == 0)
+			return;
+	}
+}
+
 /* 
  * Early initialization.
- * Relocation is on but do not reference unbolted pages
- * Also, device-tree hasn't been "finished", so don't muck with
- * it too much
  */
 void __init pmac_init_early(void)
 {
-	hpte_init_pSeries();
+	DBG(" -> pmac_init_early\n");
+
+	/* Initialize hash table, from now on, we can take hash faults
+	 * and call ioremap
+	 */
+	hpte_init_native();
 
+	/* Init SCC */
+       	if (strstr(cmd_line, "sccdbg")) {
+		sccdbg = 1;
+       		udbg_init_scc(NULL);
+       	}
+
+	else {
 #ifdef CONFIG_BOOTX_TEXT
-	ppc_md.udbg_putc = btext_putc;
-	ppc_md.udbg_getc = dummy_getc;
-	ppc_md.udbg_getc_poll = dummy_getc_poll;
+		init_boot_display();
+
+		ppc_md.udbg_putc = btext_putc;
+		ppc_md.udbg_getc = dummy_getc;
+		ppc_md.udbg_getc_poll = dummy_getc_poll;
 #endif /* CONFIG_BOOTX_TEXT */
+	}
+
+	/* Setup interrupt mapping options */
+	naca->interrupt_controller = IC_OPEN_PIC;
+
+	DBG(" <- pmac_init_early\n");
 }
 
 extern void* OpenPIC_Addr;
@@ -417,60 +407,19 @@
 
 core_initcall(pmac_irq_cascade_init);
 
-void __init pmac_init(unsigned long r3, unsigned long r4, unsigned long r5,
-		      unsigned long r6, unsigned long r7)
-{
-	/* Probe motherboard chipset */
-	pmac_feature_init();
-
-	/* Init SCC */
-	if (strstr(cmd_line, "sccdbg")) {
-		sccdbg = 1;
-		udbg_init_scc(NULL);
-	}
-
-	/* Fill up the machine description */
-	ppc_md.setup_arch     = pmac_setup_arch;
-       	ppc_md.get_cpuinfo    = pmac_show_cpuinfo;
-
-	ppc_md.init_IRQ       = pmac_init_IRQ;
-	ppc_md.get_irq        = openpic_get_irq;
-
-	ppc_md.pcibios_fixup  = pmac_pcibios_fixup;
-
-	ppc_md.restart        = pmac_restart;
-	ppc_md.power_off      = pmac_power_off;
-	ppc_md.halt           = pmac_halt;
-
-       	ppc_md.get_boot_time  = pmac_get_boot_time;
-       	ppc_md.set_rtc_time   = pmac_set_rtc_time;
-       	ppc_md.get_rtc_time   = pmac_get_rtc_time;
-      	ppc_md.calibrate_decr = pmac_calibrate_decr;
-
-	ppc_md.feature_call   = pmac_do_feature_call;
-
-
-#ifdef CONFIG_BOOTX_TEXT
-	ppc_md.progress       = pmac_progress;
-#endif /* CONFIG_BOOTX_TEXT */
-
-	if (ppc_md.progress) ppc_md.progress("pmac_init(): exit", 0);
-
-}
-
-#ifdef CONFIG_BOOTX_TEXT
-void __init pmac_progress(char *s, unsigned short hex)
+static void __init pmac_progress(char *s, unsigned short hex)
 {
 	if (sccdbg) {
 		udbg_puts(s);
-		udbg_putc('\n');
+		udbg_puts("\n");
 	}
+#ifdef CONFIG_BOOTX_TEXT
 	else if (boot_text_mapped) {
 		btext_drawstring(s);
-		btext_drawchar('\n');
+		btext_drawstring("\n");
 	}
-}
 #endif /* CONFIG_BOOTX_TEXT */
+}
 
 static int __init pmac_declare_of_platform_devices(void)
 {
@@ -489,3 +438,41 @@
 }
 
 device_initcall(pmac_declare_of_platform_devices);
+
+/*
+ * Called very early, MMU is off, device-tree isn't unflattened
+ */
+static int __init pmac_probe(int platform)
+{
+	if (platform != PLATFORM_POWERMAC)
+		return 0;
+
+	/*
+	 * On U3, the DART (iommu) must be allocated now since it
+	 * has an impact on htab_initialize (due to the large page it
+	 * occupies having to be broken up so the DART itself is not
+	 * part of the cacheable linar mapping
+	 */
+	alloc_u3_dart_table();
+
+	return 1;
+}
+
+struct machdep_calls __initdata pmac_md = {
+	.probe			= pmac_probe,
+	.setup_arch		= pmac_setup_arch,
+	.init_early		= pmac_init_early,
+       	.get_cpuinfo		= pmac_show_cpuinfo,
+	.init_IRQ		= pmac_init_IRQ,
+	.get_irq		= openpic_get_irq,
+	.pcibios_fixup		= pmac_pcibios_fixup,
+	.restart		= pmac_restart,
+	.power_off		= pmac_power_off,
+	.halt			= pmac_halt,
+       	.get_boot_time		= pmac_get_boot_time,
+       	.set_rtc_time		= pmac_set_rtc_time,
+       	.get_rtc_time		= pmac_get_rtc_time,
+      	.calibrate_decr		= pmac_calibrate_decr,
+	.feature_call		= pmac_do_feature_call,
+	.progress		= pmac_progress,
+};
diff -Nru a/arch/ppc64/kernel/pmac_smp.c b/arch/ppc64/kernel/pmac_smp.c
--- a/arch/ppc64/kernel/pmac_smp.c	2004-10-18 14:55:54 -07:00
+++ b/arch/ppc64/kernel/pmac_smp.c	2004-10-18 14:55:54 -07:00
@@ -38,7 +38,6 @@
 #include <asm/irq.h>
 #include <asm/page.h>
 #include <asm/pgtable.h>
-#include <asm/hardirq.h>
 #include <asm/sections.h>
 #include <asm/io.h>
 #include <asm/prom.h>
diff -Nru a/arch/ppc64/kernel/pmac_time.c b/arch/ppc64/kernel/pmac_time.c
--- a/arch/ppc64/kernel/pmac_time.c	2004-10-18 14:56:48 -07:00
+++ b/arch/ppc64/kernel/pmac_time.c	2004-10-18 14:56:48 -07:00
@@ -18,6 +18,7 @@
 #include <linux/time.h>
 #include <linux/adb.h>
 #include <linux/pmu.h>
+#include <linux/interrupt.h>
 
 #include <asm/sections.h>
 #include <asm/prom.h>
@@ -25,7 +26,6 @@
 #include <asm/io.h>
 #include <asm/pgtable.h>
 #include <asm/machdep.h>
-#include <asm/hardirq.h>
 #include <asm/time.h>
 #include <asm/nvram.h>
 
diff -Nru a/arch/ppc64/kernel/ppc_ksyms.c b/arch/ppc64/kernel/ppc_ksyms.c
--- a/arch/ppc64/kernel/ppc_ksyms.c	2004-10-18 14:56:17 -07:00
+++ b/arch/ppc64/kernel/ppc_ksyms.c	2004-10-18 14:56:17 -07:00
@@ -119,7 +119,6 @@
 EXPORT_SYMBOL(kernel_thread);
 
 EXPORT_SYMBOL(flush_instruction_cache);
-EXPORT_SYMBOL(_get_PVR);
 EXPORT_SYMBOL(giveup_fpu);
 #ifdef CONFIG_ALTIVEC
 EXPORT_SYMBOL(giveup_altivec);
@@ -137,7 +136,7 @@
 
 EXPORT_SYMBOL(ppc_md);
 
-#ifdef CONFIG_PPC_PSERIES
+#ifdef CONFIG_PPC_MULTIPLATFORM
 EXPORT_SYMBOL(find_devices);
 EXPORT_SYMBOL(find_type_devices);
 EXPORT_SYMBOL(find_compatible_devices);
@@ -148,12 +147,12 @@
 EXPORT_SYMBOL(get_property);
 #endif
 
-EXPORT_SYMBOL_NOVERS(memcpy);
-EXPORT_SYMBOL_NOVERS(memset);
-EXPORT_SYMBOL_NOVERS(memmove);
-EXPORT_SYMBOL_NOVERS(memscan);
-EXPORT_SYMBOL_NOVERS(memcmp);
-EXPORT_SYMBOL_NOVERS(memchr);
+EXPORT_SYMBOL(memcpy);
+EXPORT_SYMBOL(memset);
+EXPORT_SYMBOL(memmove);
+EXPORT_SYMBOL(memscan);
+EXPORT_SYMBOL(memcmp);
+EXPORT_SYMBOL(memchr);
 
 EXPORT_SYMBOL(timer_interrupt);
 EXPORT_SYMBOL(irq_desc);
diff -Nru a/arch/ppc64/kernel/process.c b/arch/ppc64/kernel/process.c
--- a/arch/ppc64/kernel/process.c	2004-10-18 14:56:33 -07:00
+++ b/arch/ppc64/kernel/process.c	2004-10-18 14:56:33 -07:00
@@ -34,6 +34,7 @@
 #include <linux/prctl.h>
 #include <linux/ptrace.h>
 #include <linux/kallsyms.h>
+#include <linux/interrupt.h>
 #include <linux/version.h>
 
 #include <asm/pgtable.h>
@@ -47,7 +48,6 @@
 #include <asm/ppcdebug.h>
 #include <asm/machdep.h>
 #include <asm/iSeries/HvCallHpt.h>
-#include <asm/hardirq.h>
 #include <asm/cputable.h>
 #include <asm/sections.h>
 #include <asm/tlbflush.h>
@@ -147,7 +147,6 @@
  */
 void flush_altivec_to_thread(struct task_struct *tsk)
 {
-#ifdef CONFIG_ALTIVEC
 	if (tsk->thread.regs) {
 		preempt_disable();
 		if (tsk->thread.regs->msr & MSR_VEC) {
@@ -158,7 +157,6 @@
 		}
 		preempt_enable();
 	}
-#endif
 }
 
 int dump_task_altivec(struct pt_regs *regs, elf_vrregset_t *vrregs)
@@ -356,6 +354,16 @@
 	kregs = (struct pt_regs *) sp;
 	sp -= STACK_FRAME_OVERHEAD;
 	p->thread.ksp = sp;
+	if (cur_cpu_spec->cpu_features & CPU_FTR_SLB) {
+		unsigned long sp_vsid = get_kernel_vsid(sp);
+
+		sp_vsid <<= SLB_VSID_SHIFT;
+		sp_vsid |= SLB_VSID_KERNEL;
+		if (cur_cpu_spec->cpu_features & CPU_FTR_16M_PAGE)
+			sp_vsid |= SLB_VSID_L;
+
+		p->thread.ksp_vsid = sp_vsid;
+	}
 
 	/*
 	 * The PPC64 ABI makes use of a TOC to contain function 
@@ -387,11 +395,22 @@
 	/* Check whether the e_entry function descriptor entries
 	 * need to be relocated before we can use them.
 	 */
-	if ( load_addr != 0 ) {
+	if (load_addr != 0) {
 		entry += load_addr;
 		toc   += load_addr;
 	}
 
+	/*
+	 * If we exec out of a kernel thread then thread.regs will not be
+	 * set. Do it now.
+	 */
+	if (!current->thread.regs) {
+		unsigned long childregs = (unsigned long)current->thread_info +
+						THREAD_SIZE;
+		childregs -= sizeof(struct pt_regs);
+		current->thread.regs = (struct pt_regs *)childregs;
+	}
+
 	regs->nip = entry;
 	regs->gpr[1] = sp;
 	regs->gpr[2] = toc;
@@ -458,7 +477,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/prom.c b/arch/ppc64/kernel/prom.c
--- a/arch/ppc64/kernel/prom.c	2004-10-18 14:56:48 -07:00
+++ b/arch/ppc64/kernel/prom.c	2004-10-18 14:56:48 -07:00
@@ -15,7 +15,7 @@
  *      2 of the License, or (at your option) any later version.
  */
 
-#undef DEBUG_PROM
+#undef DEBUG
 
 #include <stdarg.h>
 #include <linux/config.h>
@@ -54,1806 +54,58 @@
 #include <asm/machdep.h>
 #include "open_pic.h"
 
-#ifdef CONFIG_LOGO_LINUX_CLUT224
-#include <linux/linux_logo.h>
-extern const struct linux_logo logo_linux_clut224;
-#endif
-
-/*
- * Properties whose value is longer than this get excluded from our
- * copy of the device tree. This value does need to be big enough to
- * ensure that we don't lose things like the interrupt-map property
- * on a PCI-PCI bridge.
- */
-#define MAX_PROPERTY_LENGTH	(1UL * 1024 * 1024)
-
-/*
- * prom_init() is called very early on, before the kernel text
- * and data have been mapped to KERNELBASE.  At this point the code
- * is running at whatever address it has been loaded at, so
- * references to extern and static variables must be relocated
- * explicitly.  The procedure reloc_offset() returns the address
- * we're currently running at minus the address we were linked at.
- * (Note that strings count as static variables.)
- *
- * Because OF may have mapped I/O devices into the area starting at
- * KERNELBASE, particularly on CHRP machines, we can't safely call
- * OF once the kernel has been mapped to KERNELBASE.  Therefore all
- * OF calls should be done within prom_init(), and prom_init()
- * and all routines called within it must be careful to relocate
- * references as necessary.
- *
- * Note that the bss is cleared *after* prom_init runs, so we have
- * to make sure that any static or extern variables it accesses
- * are put in the data segment.
- */
-
-
-#define PROM_BUG() do {						\
-        prom_printf("kernel BUG at %s line 0x%x!\n",		\
-		    RELOC(__FILE__), __LINE__);			\
-        __asm__ __volatile__(".long " BUG_ILLEGAL_INSTR);	\
-} while (0)
-
-#ifdef DEBUG_PROM
-#define prom_debug(x...)	prom_printf(x)
+#ifdef DEBUG
+#define DBG(fmt...) udbg_printf(fmt)
 #else
-#define prom_debug(x...)
+#define DBG(fmt...)
 #endif
 
-
 struct pci_reg_property {
 	struct pci_address addr;
 	u32 size_hi;
 	u32 size_lo;
 };
 
-
 struct isa_reg_property {
 	u32 space;
 	u32 address;
 	u32 size;
 };
 
-struct pci_intr_map {
-	struct pci_address addr;
-	u32 dunno;
-	phandle int_ctrler;
-	u32 intr;
-};
-
 
 typedef unsigned long interpret_func(struct device_node *, unsigned long,
 				     int, int, int);
 
-#ifndef FB_MAX			/* avoid pulling in all of the fb stuff */
-#define FB_MAX	8
-#endif
-
-/* prom structure */
-struct prom_t prom;
-
-char *prom_display_paths[FB_MAX] __initdata = { NULL, };
-phandle prom_display_nodes[FB_MAX] __initdata;
-unsigned int prom_num_displays = 0;
-char *of_stdout_device = NULL;
-
-static int iommu_force_on;
-int ppc64_iommu_off;
-
 extern struct rtas_t rtas;
-extern unsigned long klimit;
 extern struct lmb lmb;
+extern unsigned long klimit;
 
-#define MAX_PHB (32 * 6)  /* 32 drawers * 6 PHBs/drawer */
-struct of_tce_table of_tce_table[MAX_PHB + 1];
+static int __initdata dt_root_addr_cells;
+static int __initdata dt_root_size_cells;
+static int __initdata iommu_is_off;
+int __initdata iommu_force_on;
+typedef u32 cell_t;
 
-char *bootpath = NULL;
-char *bootdevice = NULL;
+#if 0
+static struct boot_param_header *initial_boot_params __initdata;
+#else
+struct boot_param_header *initial_boot_params;
+#endif
 
-int boot_cpuid = 0;
-#define MAX_CPU_THREADS 2
+static struct device_node *allnodes = NULL;
 
-struct device_node *allnodes = NULL;
 /* use when traversing tree through the allnext, child, sibling,
  * or parent members of struct device_node.
  */
 static rwlock_t devtree_lock = RW_LOCK_UNLOCKED;
 
-extern unsigned long reloc_offset(void);
-
-extern void enter_prom(struct prom_args *args);
-extern void copy_and_flush(unsigned long dest, unsigned long src,
-			   unsigned long size, unsigned long offset);
-
-unsigned long dev_tree_size;
-unsigned long _get_PIR(void);
-
-#ifdef CONFIG_HMT
-struct {
-	unsigned int pir;
-	unsigned int threadid;
-} hmt_thread_data[NR_CPUS];
-#endif /* CONFIG_HMT */
-
-char testString[] = "LINUX\n"; 
-
-/*
- * This are used in calls to call_prom.  The 4th and following
- * arguments to call_prom should be 32-bit values.  64 bit values
- * are truncated to 32 bits (and fortunately don't get interpreted
- * as two arguments).
- */
-#define ADDR(x)		(u32) ((unsigned long)(x) - offset)
-
-/* This is the one and *ONLY* place where we actually call open
- * firmware from, since we need to make sure we're running in 32b
- * mode when we do.  We switch back to 64b mode upon return.
- */
-
-#define PROM_ERROR	(-1)
-
-static int __init call_prom(const char *service, int nargs, int nret, ...)
-{
-	int i;
-	unsigned long offset = reloc_offset();
-	struct prom_t *_prom = PTRRELOC(&prom);
-	va_list list;
-
-	_prom->args.service = ADDR(service);
-	_prom->args.nargs = nargs;
-	_prom->args.nret = nret;
-	_prom->args.rets = (prom_arg_t *)&(_prom->args.args[nargs]);
-
-	va_start(list, nret);
-	for (i=0; i < nargs; i++)
-		_prom->args.args[i] = va_arg(list, prom_arg_t);
-	va_end(list);
-
-	for (i=0; i < nret ;i++)
-		_prom->args.rets[i] = 0;
-
-	enter_prom(&_prom->args);
-
-	return (nret > 0)? _prom->args.rets[0]: 0;
-}
-
-
-static void __init prom_print(const char *msg)
-{
-	const char *p, *q;
-	unsigned long offset = reloc_offset();
-	struct prom_t *_prom = PTRRELOC(&prom);
-
-	if (_prom->stdout == 0)
-		return;
-
-	for (p = msg; *p != 0; p = q) {
-		for (q = p; *q != 0 && *q != '\n'; ++q)
-			;
-		if (q > p)
-			call_prom("write", 3, 1, _prom->stdout, p, q - p);
-		if (*q == 0)
-			break;
-		++q;
-		call_prom("write", 3, 1, _prom->stdout, ADDR("\r\n"), 2);
-	}
-}
-
-
-static void __init prom_print_hex(unsigned long val)
-{
-	unsigned long offset = reloc_offset();
-	int i, nibbles = sizeof(val)*2;
-	char buf[sizeof(val)*2+1];
-	struct prom_t *_prom = PTRRELOC(&prom);
-
-	for (i = nibbles-1;  i >= 0;  i--) {
-		buf[i] = (val & 0xf) + '0';
-		if (buf[i] > '9')
-			buf[i] += ('a'-'0'-10);
-		val >>= 4;
-	}
-	buf[nibbles] = '\0';
-	call_prom("write", 3, 1, _prom->stdout, buf, nibbles);
-}
-
-
-static void __init prom_printf(const char *format, ...)
-{
-	unsigned long offset = reloc_offset();
-	const char *p, *q, *s;
-	va_list args;
-	unsigned long v;
-	struct prom_t *_prom = PTRRELOC(&prom);
-
-	va_start(args, format);
-	for (p = PTRRELOC(format); *p != 0; p = q) {
-		for (q = p; *q != 0 && *q != '\n' && *q != '%'; ++q)
-			;
-		if (q > p)
-			call_prom("write", 3, 1, _prom->stdout, p, q - p);
-		if (*q == 0)
-			break;
-		if (*q == '\n') {
-			++q;
-			call_prom("write", 3, 1, _prom->stdout,
-				  ADDR("\r\n"), 2);
-			continue;
-		}
-		++q;
-		if (*q == 0)
-			break;
-		switch (*q) {
-		case 's':
-			++q;
-			s = va_arg(args, const char *);
-			prom_print(s);
-			break;
-		case 'x':
-			++q;
-			v = va_arg(args, unsigned long);
-			prom_print_hex(v);
-			break;
-		}
-	}
-}
-
-
-static void __init __attribute__((noreturn)) prom_panic(const char *reason)
-{
-	unsigned long offset = reloc_offset();
-
-	prom_print(PTRRELOC(reason));
-	/* ToDo: should put up an SRC here */
-	call_prom("exit", 0, 0);
-
-	for (;;)			/* should never get here */
-		;
-}
-
-
-static int __init prom_next_node(phandle *nodep)
-{
-	phandle node;
-
-	if ((node = *nodep) != 0
-	    && (*nodep = call_prom("child", 1, 1, node)) != 0)
-		return 1;
-	if ((*nodep = call_prom("peer", 1, 1, node)) != 0)
-		return 1;
-	for (;;) {
-		if ((node = call_prom("parent", 1, 1, node)) == 0)
-			return 0;
-		if ((*nodep = call_prom("peer", 1, 1, node)) != 0)
-			return 1;
-	}
-}
-
-static int __init prom_getprop(phandle node, const char *pname,
-			       void *value, size_t valuelen)
-{
-	unsigned long offset = reloc_offset();
-
-	return call_prom("getprop", 4, 1, node, ADDR(pname),
-			 (u32)(unsigned long) value, (u32) valuelen);
-}
-
-static void __init prom_initialize_naca(void)
-{
-	phandle node;
-	char type[64];
-	unsigned long num_cpus = 0;
-	unsigned long offset = reloc_offset();
-	struct prom_t *_prom = PTRRELOC(&prom);
-	struct naca_struct *_naca = RELOC(naca);
-	struct systemcfg *_systemcfg = RELOC(systemcfg);
-
-	/* NOTE: _naca->debug_switch is already initialized. */
-	prom_debug("prom_initialize_naca: start...\n");
-
-	_naca->pftSize = 0;	/* ilog2 of htab size.  computed below. */
-
-	for (node = 0; prom_next_node(&node); ) {
-		type[0] = 0;
-		prom_getprop(node, "device_type", type, sizeof(type));
-
-		if (!strcmp(type, RELOC("cpu"))) {
-			num_cpus += 1;
-
-			/* We're assuming *all* of the CPUs have the same
-			 * d-cache and i-cache sizes... -Peter
-			 */
-			if ( num_cpus == 1 ) {
-				u32 size, lsize;
-				const char *dc, *ic;
-
-				if (_systemcfg->platform == PLATFORM_POWERMAC){
-					dc = "d-cache-block-size";
-					ic = "i-cache-block-size";
-				} else {
-					dc = "d-cache-line-size";
-					ic = "i-cache-line-size";
-				}
-
-				prom_getprop(node, "d-cache-size",
-					     &size, sizeof(size));
-
-				prom_getprop(node, dc, &lsize, sizeof(lsize));
-
-				_systemcfg->dCacheL1Size = size;
-				_systemcfg->dCacheL1LineSize = lsize;
-				_naca->dCacheL1LogLineSize = __ilog2(lsize);
-				_naca->dCacheL1LinesPerPage = PAGE_SIZE/lsize;
-
-				prom_getprop(node, "i-cache-size",
-					     &size, sizeof(size));
-
-				prom_getprop(node, ic, &lsize, sizeof(lsize));
-
-				_systemcfg->iCacheL1Size = size;
-				_systemcfg->iCacheL1LineSize = lsize;
-				_naca->iCacheL1LogLineSize = __ilog2(lsize);
-				_naca->iCacheL1LinesPerPage = PAGE_SIZE/lsize;
-
-				if (_systemcfg->platform == PLATFORM_PSERIES_LPAR) {
-					u32 pft_size[2];
-					prom_getprop(node, "ibm,pft-size",
-						&pft_size, sizeof(pft_size));
-				/* pft_size[0] is the NUMA CEC cookie */
-					_naca->pftSize = pft_size[1];
-				}
-			}
-		} else if (!strcmp(type, RELOC("serial"))) {
-			phandle isa, pci;
-			struct isa_reg_property reg;
-			union pci_range ranges;
-
-			if (_systemcfg->platform == PLATFORM_POWERMAC)
-				continue;
-			type[0] = 0;
-			prom_getprop(node, "ibm,aix-loc", type, sizeof(type));
-
-			if (strcmp(type, RELOC("S1")))
-				continue;
-
-			prom_getprop(node, "reg", &reg, sizeof(reg));
-
-			isa = call_prom("parent", 1, 1, node);
-			if (!isa)
-				PROM_BUG();
-			pci = call_prom("parent", 1, 1, isa);
-			if (!pci)
-				PROM_BUG();
-
-			prom_getprop(pci, "ranges", &ranges, sizeof(ranges));
-
-			if ( _prom->encode_phys_size == 32 )
-				_naca->serialPortAddr = ranges.pci32.phys+reg.address;
-			else {
-				_naca->serialPortAddr = 
-					((((unsigned long)ranges.pci64.phys_hi) << 32) |
-					 (ranges.pci64.phys_lo)) + reg.address;
-			}
-		}
-	}
-
-	if (_systemcfg->platform == PLATFORM_POWERMAC)
-		_naca->interrupt_controller = IC_OPEN_PIC;
-	else {
-		_naca->interrupt_controller = IC_INVALID;
-		for (node = 0; prom_next_node(&node); ) {
-			type[0] = 0;
-			prom_getprop(node, "name", type, sizeof(type));
-			if (strcmp(type, RELOC("interrupt-controller")))
-				continue;
-			prom_getprop(node, "compatible", type, sizeof(type));
-			if (strstr(type, RELOC("open-pic")))
-				_naca->interrupt_controller = IC_OPEN_PIC;
-			else if (strstr(type, RELOC("ppc-xicp")))
-				_naca->interrupt_controller = IC_PPC_XIC;
-			else
-				prom_printf("prom: failed to recognize"
-					    " interrupt-controller\n");
-			break;
-		}
-	}
-
-	if (_naca->interrupt_controller == IC_INVALID) {
-		prom_printf("prom: failed to find interrupt-controller\n");
-		PROM_BUG();
-	}
-
-	/* We gotta have at least 1 cpu... */
-	if ( (_systemcfg->processorCount = num_cpus) < 1 )
-		PROM_BUG();
-
-	_systemcfg->physicalMemorySize = lmb_phys_mem_size();
-
-	if (_systemcfg->platform == PLATFORM_PSERIES ||
-	    _systemcfg->platform == PLATFORM_POWERMAC) {
-		unsigned long rnd_mem_size, pteg_count;
-
-		/* round mem_size up to next power of 2 */
-		rnd_mem_size = 1UL << __ilog2(_systemcfg->physicalMemorySize);
-		if (rnd_mem_size < _systemcfg->physicalMemorySize)
-			rnd_mem_size <<= 1;
-
-		/* # pages / 2 */
-		pteg_count = (rnd_mem_size >> (12 + 1));
-
-		_naca->pftSize = __ilog2(pteg_count << 7);
-	}
-
-	if (_naca->pftSize == 0) {
-		prom_printf("prom: failed to compute pftSize!\n");
-		PROM_BUG();
-	}
-
-	/* Add an eye catcher and the systemcfg layout version number */
-	strcpy(_systemcfg->eye_catcher, RELOC("SYSTEMCFG:PPC64"));
-	_systemcfg->version.major = SYSTEMCFG_MAJOR;
-	_systemcfg->version.minor = SYSTEMCFG_MINOR;
-	_systemcfg->processor = _get_PVR();
-
-	prom_debug("systemcfg->processorCount       = 0x%x\n",
-		   _systemcfg->processorCount);
-	prom_debug("systemcfg->physicalMemorySize   = 0x%x\n",
-		   _systemcfg->physicalMemorySize);
-	prom_debug("naca->pftSize                   = 0x%x\n",
-		   _naca->pftSize);
-	prom_debug("systemcfg->dCacheL1LineSize     = 0x%x\n",
-		   _systemcfg->dCacheL1LineSize);
-	prom_debug("systemcfg->iCacheL1LineSize     = 0x%x\n",
-		   _systemcfg->iCacheL1LineSize);
-	prom_debug("naca->serialPortAddr            = 0x%x\n",
-		   _naca->serialPortAddr);
-	prom_debug("naca->interrupt_controller      = 0x%x\n",
-		   _naca->interrupt_controller);
-	prom_debug("systemcfg->platform             = 0x%x\n",
-		   _systemcfg->platform);
-	prom_debug("prom_initialize_naca: end...\n");
-}
-
-
-static void __init early_cmdline_parse(void)
-{
-	unsigned long offset = reloc_offset();
-	char *opt;
-#ifndef CONFIG_PMAC_DART
-	struct systemcfg *_systemcfg = RELOC(systemcfg);
-#endif
-
-	opt = strstr(RELOC(cmd_line), RELOC("iommu="));
-	if (opt) {
-		prom_printf("opt is:%s\n", opt);
-		opt += 6;
-		while (*opt && *opt == ' ')
-			opt++;
-		if (!strncmp(opt, RELOC("off"), 3))
-			RELOC(ppc64_iommu_off) = 1;
-		else if (!strncmp(opt, RELOC("force"), 5))
-			RELOC(iommu_force_on) = 1;
-	}
-
-#ifndef CONFIG_PMAC_DART
-	if (_systemcfg->platform == PLATFORM_POWERMAC) {
-		RELOC(ppc64_iommu_off) = 1;
-		prom_printf("DART disabled on PowerMac !\n");
-	}
-#endif
-}
-
-#ifdef DEBUG_PROM
-void prom_dump_lmb(void)
-{
-	unsigned long i;
-	unsigned long offset = reloc_offset();
-	struct lmb *_lmb  = PTRRELOC(&lmb);
-
-	prom_printf("\nprom_dump_lmb:\n");
-	prom_printf("    memory.cnt		  = 0x%x\n",
-		    _lmb->memory.cnt);
-	prom_printf("    memory.size		 = 0x%x\n",
-		    _lmb->memory.size);
-	for (i=0; i < _lmb->memory.cnt ;i++) {
-		prom_printf("    memory.region[0x%x].base       = 0x%x\n",
-			    i, _lmb->memory.region[i].base);
-		prom_printf("		      .physbase = 0x%x\n",
-			    _lmb->memory.region[i].physbase);
-		prom_printf("		      .size     = 0x%x\n",
-			    _lmb->memory.region[i].size);
-	}
-
-	prom_printf("\n    reserved.cnt		  = 0x%x\n",
-		    _lmb->reserved.cnt);
-	prom_printf("    reserved.size		 = 0x%x\n",
-		    _lmb->reserved.size);
-	for (i=0; i < _lmb->reserved.cnt ;i++) {
-		prom_printf("    reserved.region[0x%x\n].base       = 0x%x\n",
-			    i, _lmb->reserved.region[i].base);
-		prom_printf("		      .physbase = 0x%x\n",
-			    _lmb->reserved.region[i].physbase);
-		prom_printf("		      .size     = 0x%x\n",
-			    _lmb->reserved.region[i].size);
-	}
-}
-#endif /* DEBUG_PROM */
-
-static void __init prom_initialize_lmb(void)
-{
-	phandle node;
-	char type[64];
-	unsigned long i, offset = reloc_offset();
-	struct prom_t *_prom = PTRRELOC(&prom);
-	struct systemcfg *_systemcfg = RELOC(systemcfg);
-	union lmb_reg_property reg;
-	unsigned long lmb_base, lmb_size;
-	unsigned long num_regs, bytes_per_reg = (_prom->encode_phys_size*2)/8;
-
-	lmb_init();
-
-	/* XXX Quick HACK. Proper fix is to drop those structures and properly use
-	 * #address-cells. PowerMac has #size-cell set to 1 and #address-cells to 2
-	 */
-	if (_systemcfg->platform == PLATFORM_POWERMAC)
-		bytes_per_reg = 12;
-
-	for (node = 0; prom_next_node(&node); ) {
-		type[0] = 0;
-		prom_getprop(node, "device_type", type, sizeof(type));
-
-		if (strcmp(type, RELOC("memory")))
-			continue;
-
-		num_regs = prom_getprop(node, "reg", &reg, sizeof(reg))
-			/ bytes_per_reg;
-
-		for (i=0; i < num_regs ;i++) {
-			if (_systemcfg->platform == PLATFORM_POWERMAC) {
-				lmb_base = ((unsigned long)reg.addrPM[i].address_hi) << 32;
-				lmb_base |= (unsigned long)reg.addrPM[i].address_lo;
-				lmb_size = reg.addrPM[i].size;
-			} else if (_prom->encode_phys_size == 32) {
-				lmb_base = reg.addr32[i].address;
-				lmb_size = reg.addr32[i].size;
-			} else {
-				lmb_base = reg.addr64[i].address;
-				lmb_size = reg.addr64[i].size;
-			}
-
-			/* We limit memory to 2GB if the IOMMU is off */
-			if (RELOC(ppc64_iommu_off)) {
-				if (lmb_base >= 0x80000000UL)
-					continue;
-
-				if ((lmb_base + lmb_size) > 0x80000000UL)
-					lmb_size = 0x80000000UL - lmb_base;
-			}
-
-			if (lmb_add(lmb_base, lmb_size) < 0)
-				prom_printf("Too many LMB's, discarding this one...\n");
-		}
-
-	}
-
-	lmb_analyze();
-#ifdef DEBUG_PROM
-	prom_dump_lmb();
-#endif /* DEBUG_PROM */
-}
-
-static void __init
-prom_instantiate_rtas(void)
-{
-	unsigned long offset = reloc_offset();
-	struct prom_t *_prom = PTRRELOC(&prom);
-	struct rtas_t *_rtas = PTRRELOC(&rtas);
-	struct systemcfg *_systemcfg = RELOC(systemcfg);
-	ihandle prom_rtas;
-	u32 getprop_rval;
-	char hypertas_funcs[4];
-
-	prom_debug("prom_instantiate_rtas: start...\n");
-
-	prom_rtas = call_prom("finddevice", 1, 1, ADDR("/rtas"));
-	if (prom_rtas != (ihandle) -1) {
-		unsigned long x;
-		x = prom_getprop(prom_rtas, "ibm,hypertas-functions",
-				 hypertas_funcs, sizeof(hypertas_funcs));
-
-		if (x != PROM_ERROR) {
-			prom_printf("Hypertas detected, assuming LPAR !\n");
-			_systemcfg->platform = PLATFORM_PSERIES_LPAR;
-		}
-
-		prom_getprop(prom_rtas, "rtas-size",
-			     &getprop_rval, sizeof(getprop_rval));
-		_rtas->size = getprop_rval;
-		prom_printf("instantiating rtas");
-		if (_rtas->size != 0) {
-			unsigned long rtas_region = RTAS_INSTANTIATE_MAX;
-
-			/* Grab some space within the first RTAS_INSTANTIATE_MAX bytes
-			 * of physical memory (or within the RMO region) because RTAS
-			 * runs in 32-bit mode and relocate off.
-			 */
-			if ( _systemcfg->platform == PLATFORM_PSERIES_LPAR ) {
-				struct lmb *_lmb  = PTRRELOC(&lmb);
-				rtas_region = min(_lmb->rmo_size, RTAS_INSTANTIATE_MAX);
-			}
-
-			_rtas->base = lmb_alloc_base(_rtas->size, PAGE_SIZE, rtas_region);
-
-			prom_printf(" at 0x%x", _rtas->base);
-
-			prom_rtas = call_prom("open", 1, 1, ADDR("/rtas"));
-			prom_printf("...");
-
-			if (call_prom("call-method", 3, 2,
-				      ADDR("instantiate-rtas"),
-				      prom_rtas,
-				      _rtas->base) != PROM_ERROR) {
-				_rtas->entry = (long)_prom->args.rets[1];
-			}
-			RELOC(rtas_rmo_buf)
-				= lmb_alloc_base(RTAS_RMOBUF_MAX, PAGE_SIZE,
-							rtas_region);
-		}
-
-		if (_rtas->entry <= 0) {
-			prom_printf(" failed\n");
-		} else {
-			prom_printf(" done\n");
-		}
-
-		prom_debug("rtas->base		= 0x%x\n", _rtas->base);
-		prom_debug("rtas->entry	       = 0x%x\n", _rtas->entry);
-		prom_debug("rtas->size		= 0x%x\n", _rtas->size);
-	}
-	prom_debug("prom_instantiate_rtas: end...\n");
-}
-
-
-#ifdef CONFIG_PMAC_DART
-static void __init prom_initialize_dart_table(void)
-{
-	unsigned long offset = reloc_offset();
-	extern unsigned long dart_tablebase;
-	extern unsigned long dart_tablesize;
-
-	/* Only reserve DART space if machine has more than 2GB of RAM
-	 * or if requested with iommu=on on cmdline.
-	 */
-	if (lmb_end_of_DRAM() <= 0x80000000ull && !RELOC(iommu_force_on))
-		return;
-
-	/* 512 pages (2MB) is max DART tablesize. */
-	RELOC(dart_tablesize) = 1UL << 21;
-	/* 16MB (1 << 24) alignment. We allocate a full 16Mb chuck since we
-	 * will blow up an entire large page anyway in the kernel mapping
-	 */
-	RELOC(dart_tablebase) = (unsigned long)
-		abs_to_virt(lmb_alloc_base(1UL<<24, 1UL<<24, 0x80000000L));
-
-	prom_printf("Dart at: %x\n", RELOC(dart_tablebase));
-}
-#endif /* CONFIG_PMAC_DART */
-
-static void __init prom_initialize_tce_table(void)
-{
-	phandle node;
-	ihandle phb_node;
-	unsigned long offset = reloc_offset();
-	char compatible[64], path[64], type[64], model[64];
-	unsigned long i, table = 0;
-	unsigned long base, vbase, align;
-	unsigned int minalign, minsize;
-	struct of_tce_table *prom_tce_table = RELOC(of_tce_table);
-	unsigned long tce_entry, *tce_entryp;
-
-	if (RELOC(ppc64_iommu_off))
-		return;
-
-	prom_debug("starting prom_initialize_tce_table\n");
-
-	/* Search all nodes looking for PHBs. */
-	for (node = 0; prom_next_node(&node); ) {
-		if (table == MAX_PHB) {
-			prom_printf("WARNING: PCI host bridge ignored, "
-				    "need to increase MAX_PHB\n");
-			continue;
-		}
-
-		compatible[0] = 0;
-		type[0] = 0;
-		model[0] = 0;
-		prom_getprop(node, "compatible",
-			     compatible, sizeof(compatible));
-		prom_getprop(node, "device_type", type, sizeof(type));
-		prom_getprop(node, "model", model, sizeof(model));
-
-		/* Keep the old logic in tack to avoid regression. */
-		if (compatible[0] != 0) {
-			if ((strstr(compatible, RELOC("python")) == NULL) &&
-			    (strstr(compatible, RELOC("Speedwagon")) == NULL) &&
-			    (strstr(compatible, RELOC("Winnipeg")) == NULL))
-				continue;
-		} else if (model[0] != 0) {
-			if ((strstr(model, RELOC("ython")) == NULL) &&
-			    (strstr(model, RELOC("peedwagon")) == NULL) &&
-			    (strstr(model, RELOC("innipeg")) == NULL))
-				continue;
-		}
-
-		if ((type[0] == 0) || (strstr(type, RELOC("pci")) == NULL)) {
-			continue;
-		}
-
-		if (prom_getprop(node, "tce-table-minalign", &minalign,
-				 sizeof(minalign)) == PROM_ERROR) {
-			minalign = 0;
-		}
-
-		if (prom_getprop(node, "tce-table-minsize", &minsize,
-				 sizeof(minsize)) == PROM_ERROR) {
-			minsize = 4UL << 20;
-		}
-
-		/*
-		 * Even though we read what OF wants, we just set the table
-		 * size to 4 MB.  This is enough to map 2GB of PCI DMA space.
-		 * By doing this, we avoid the pitfalls of trying to DMA to
-		 * MMIO space and the DMA alias hole.
-		 *
-		 * On POWER4, firmware sets the TCE region by assuming
-		 * each TCE table is 8MB. Using this memory for anything
-		 * else will impact performance, so we always allocate 8MB.
-		 * Anton
-		 */
-		if (__is_processor(PV_POWER4) || __is_processor(PV_POWER4p))
-			minsize = 8UL << 20;
-		else
-			minsize = 4UL << 20;
-
-		/* Align to the greater of the align or size */
-		align = max(minalign, minsize);
-
-		/* Carve out storage for the TCE table. */
-		base = lmb_alloc(minsize, align);
-
-		if ( !base ) {
-			prom_panic("ERROR, cannot find space for TCE table.\n");
-		}
-
-		vbase = (unsigned long)abs_to_virt(base);
-
-		/* Save away the TCE table attributes for later use. */
-		prom_tce_table[table].node = node;
-		prom_tce_table[table].base = vbase;
-		prom_tce_table[table].size = minsize;
-
-		prom_debug("TCE table: 0x%x\n", table);
-		prom_debug("\tnode = 0x%x\n", node);
-		prom_debug("\tbase = 0x%x\n", vbase);
-		prom_debug("\tsize = 0x%x\n", minsize);
-
-		/* Initialize the table to have a one-to-one mapping
-		 * over the allocated size.
-		 */
-		tce_entryp = (unsigned long *)base;
-		for (i = 0; i < (minsize >> 3) ;tce_entryp++, i++) {
-			tce_entry = (i << PAGE_SHIFT);
-			tce_entry |= 0x3;
-			*tce_entryp = tce_entry;
-		}
-
-		/* It seems OF doesn't null-terminate the path :-( */
-		memset(path, 0, sizeof(path));
-		/* Call OF to setup the TCE hardware */
-		if (call_prom("package-to-path", 3, 1, node,
-			      path, sizeof(path)-1) == PROM_ERROR) {
-			prom_printf("package-to-path failed\n");
-		} else {
-			prom_printf("opening PHB %s", path);
-		}
-
-		phb_node = call_prom("open", 1, 1, path);
-		if ( (long)phb_node <= 0) {
-			prom_printf("... failed\n");
-		} else {
-			prom_printf("... done\n");
-		}
-		call_prom("call-method", 6, 0, ADDR("set-64-bit-addressing"),
-			  phb_node, -1, minsize,
-			  (u32) base, (u32) (base >> 32));
-		call_prom("close", 1, 0, phb_node);
-
-		table++;
-	}
-
-	/* Flag the first invalid entry */
-	prom_tce_table[table].node = 0;
-	prom_debug("ending prom_initialize_tce_table\n");
-}
-
-/*
- * With CHRP SMP we need to use the OF to start the other
- * processors so we can't wait until smp_boot_cpus (the OF is
- * trashed by then) so we have to put the processors into
- * a holding pattern controlled by the kernel (not OF) before
- * we destroy the OF.
- *
- * This uses a chunk of low memory, puts some holding pattern
- * code there and sends the other processors off to there until
- * smp_boot_cpus tells them to do something.  The holding pattern
- * checks that address until its cpu # is there, when it is that
- * cpu jumps to __secondary_start().  smp_boot_cpus() takes care
- * of setting those values.
- *
- * We also use physical address 0x4 here to tell when a cpu
- * is in its holding pattern code.
- *
- * Fixup comment... DRENG / PPPBBB - Peter
- *
- * -- Cort
- */
-static void __init prom_hold_cpus(unsigned long mem)
-{
-	unsigned long i;
-	unsigned int reg;
-	phandle node;
-	unsigned long offset = reloc_offset();
-	char type[64], *path;
-	int cpuid = 0;
-	unsigned int interrupt_server[MAX_CPU_THREADS];
-	unsigned int cpu_threads, hw_cpu_num;
-	int propsize;
-	extern void __secondary_hold(void);
-	extern unsigned long __secondary_hold_spinloop;
-	extern unsigned long __secondary_hold_acknowledge;
-	unsigned long *spinloop
-		= (void *)virt_to_abs(&__secondary_hold_spinloop);
-	unsigned long *acknowledge
-		= (void *)virt_to_abs(&__secondary_hold_acknowledge);
-	unsigned long secondary_hold
-		= virt_to_abs(*PTRRELOC((unsigned long *)__secondary_hold));
-	struct systemcfg *_systemcfg = RELOC(systemcfg);
-	struct paca_struct *lpaca = PTRRELOC(&paca[0]);
-	struct prom_t *_prom = PTRRELOC(&prom);
-#ifdef CONFIG_SMP
-	struct naca_struct *_naca = RELOC(naca);
-#endif
-
-	/* On pmac, we just fill out the various global bitmasks and
-	 * arrays indicating our CPUs are here, they are actually started
-	 * later on from pmac_smp
-	 */
-	if (_systemcfg->platform == PLATFORM_POWERMAC) {
-		for (node = 0; prom_next_node(&node); ) {
-			type[0] = 0;
-			prom_getprop(node, "device_type", type, sizeof(type));
-			if (strcmp(type, RELOC("cpu")) != 0)
-				continue;
-			reg = -1;
-			prom_getprop(node, "reg", &reg, sizeof(reg));
-			lpaca[cpuid].hw_cpu_id = reg;
-
-#ifdef CONFIG_SMP
-			cpu_set(cpuid, RELOC(cpu_available_map));
-			cpu_set(cpuid, RELOC(cpu_possible_map));
-			cpu_set(cpuid, RELOC(cpu_present_at_boot));
-			if (reg == 0)
-				cpu_set(cpuid, RELOC(cpu_online_map));
-#endif /* CONFIG_SMP */
-			cpuid++;
-		}
-		return;
-	}
-
-	/* Initially, we must have one active CPU. */
-	_systemcfg->processorCount = 1;
-
-	prom_debug("prom_hold_cpus: start...\n");
-	prom_debug("    1) spinloop       = 0x%x\n", (unsigned long)spinloop);
-	prom_debug("    1) *spinloop      = 0x%x\n", *spinloop);
-	prom_debug("    1) acknowledge    = 0x%x\n",
-		   (unsigned long)acknowledge);
-	prom_debug("    1) *acknowledge   = 0x%x\n", *acknowledge);
-	prom_debug("    1) secondary_hold = 0x%x\n", secondary_hold);
-
-	/* Set the common spinloop variable, so all of the secondary cpus
-	 * will block when they are awakened from their OF spinloop.
-	 * This must occur for both SMP and non SMP kernels, since OF will
-	 * be trashed when we move the kernel.
-	 */
-	*spinloop = 0;
-
-#ifdef CONFIG_HMT
-	for (i=0; i < NR_CPUS; i++) {
-		RELOC(hmt_thread_data)[i].pir = 0xdeadbeef;
-	}
-#endif
-	/* look for cpus */
-	for (node = 0; prom_next_node(&node); ) {
-		type[0] = 0;
-		prom_getprop(node, "device_type", type, sizeof(type));
-		if (strcmp(type, RELOC("cpu")) != 0)
-			continue;
-
-		/* Skip non-configured cpus. */
-		prom_getprop(node, "status", type, sizeof(type));
-		if (strcmp(type, RELOC("okay")) != 0)
-			continue;
-
-		reg = -1;
-		prom_getprop(node, "reg", &reg, sizeof(reg));
-
-		path = (char *) mem;
-		memset(path, 0, 256);
-		if (call_prom("package-to-path", 3, 1,
-			      node, path, 255) == PROM_ERROR)
-			continue;
-
-		prom_debug("\ncpuid        = 0x%x\n", cpuid);
-		prom_debug("cpu hw idx   = 0x%x\n", reg);
-		lpaca[cpuid].hw_cpu_id = reg;
-
-		/* Init the acknowledge var which will be reset by
-		 * the secondary cpu when it awakens from its OF
-		 * spinloop.
-		 */
-		*acknowledge = (unsigned long)-1;
-
-		propsize = prom_getprop(node, "ibm,ppc-interrupt-server#s",
-					&interrupt_server,
-					sizeof(interrupt_server));
-		if (propsize < 0) {
-			/* no property.  old hardware has no SMT */
-			cpu_threads = 1;
-			interrupt_server[0] = reg; /* fake it with phys id */
-		} else {
-			/* We have a threaded processor */
-			cpu_threads = propsize / sizeof(u32);
-			if (cpu_threads > MAX_CPU_THREADS) {
-				prom_printf("SMT: too many threads!\n"
-					    "SMT: found %x, max is %x\n",
-					    cpu_threads, MAX_CPU_THREADS);
-				cpu_threads = 1; /* ToDo: panic? */
-			}
-		}
-
-		hw_cpu_num = interrupt_server[0];
-		if (hw_cpu_num != _prom->cpu) {
-			/* Primary Thread of non-boot cpu */
-			prom_printf("%x : starting cpu %s... ", cpuid, path);
-			call_prom("start-cpu", 3, 0, node,
-				  secondary_hold, cpuid);
-
-			for ( i = 0 ; (i < 100000000) && 
-			      (*acknowledge == ((unsigned long)-1)); i++ ) ;
-
-			if (*acknowledge == cpuid) {
-				prom_printf("... done\n");
-				/* We have to get every CPU out of OF,
-				 * even if we never start it. */
-				if (cpuid >= NR_CPUS)
-					goto next;
-#ifdef CONFIG_SMP
-				/* Set the number of active processors. */
-				_systemcfg->processorCount++;
-				cpu_set(cpuid, RELOC(cpu_available_map));
-				cpu_set(cpuid, RELOC(cpu_possible_map));
-				cpu_set(cpuid, RELOC(cpu_present_at_boot));
-#endif
-			} else {
-				prom_printf("... failed: %x\n", *acknowledge);
-			}
-		}
-#ifdef CONFIG_SMP
-		else {
-			prom_printf("%x : booting  cpu %s\n", cpuid, path);
-			cpu_set(cpuid, RELOC(cpu_available_map));
-			cpu_set(cpuid, RELOC(cpu_possible_map));
-			cpu_set(cpuid, RELOC(cpu_online_map));
-			cpu_set(cpuid, RELOC(cpu_present_at_boot));
-		}
-#endif
-next:
-#ifdef CONFIG_SMP
-		/* Init paca for secondary threads.   They start later. */
-		for (i=1; i < cpu_threads; i++) {
-			cpuid++;
-			if (cpuid >= NR_CPUS)
-				continue;
-			lpaca[cpuid].hw_cpu_id = interrupt_server[i];
-			prom_printf("%x : preparing thread ... ",
-				    interrupt_server[i]);
-			if (_naca->smt_state) {
-				cpu_set(cpuid, RELOC(cpu_available_map));
-				cpu_set(cpuid, RELOC(cpu_present_at_boot));
-				prom_printf("available\n");
-			} else {
-				prom_printf("not available\n");
-			}
-		}
-#endif
-		cpuid++;
-	}
-#ifdef CONFIG_HMT
-	/* Only enable HMT on processors that provide support. */
-	if (__is_processor(PV_PULSAR) || 
-	    __is_processor(PV_ICESTAR) ||
-	    __is_processor(PV_SSTAR)) {
-		prom_printf("    starting secondary threads\n");
-
-		for (i = 0; i < NR_CPUS; i += 2) {
-			if (!cpu_online(i))
-				continue;
-
-			if (i == 0) {
-				unsigned long pir = _get_PIR();
-				if (__is_processor(PV_PULSAR)) {
-					RELOC(hmt_thread_data)[i].pir = 
-						pir & 0x1f;
-				} else {
-					RELOC(hmt_thread_data)[i].pir = 
-						pir & 0x3ff;
-				}
-			}
-/* 			cpu_set(i+1, cpu_online_map); */
-			cpu_set(i+1, RELOC(cpu_possible_map));
-		}
-		_systemcfg->processorCount *= 2;
-	} else {
-		prom_printf("Processor is not HMT capable\n");
-	}
-#endif
-
-	if (cpuid > NR_CPUS)
-		prom_printf("WARNING: maximum CPUs (" __stringify(NR_CPUS)
-			    ") exceeded: ignoring extras\n");
-
-	prom_debug("prom_hold_cpus: end...\n");
-}
-
-static void __init smt_setup(void)
-{
-	char *p, *q;
-	char my_smt_enabled = SMT_DYNAMIC;
-	ihandle prom_options = 0;
-	char option[9];
-	unsigned long offset = reloc_offset();
-	struct naca_struct *_naca = RELOC(naca);
-	char found = 0;
-
-	if (strstr(RELOC(cmd_line), RELOC("smt-enabled="))) {
-		for (q = RELOC(cmd_line); (p = strstr(q, RELOC("smt-enabled="))) != 0; ) {
-			q = p + 12;
-			if (p > RELOC(cmd_line) && p[-1] != ' ')
-				continue;
-			found = 1;
-			if (q[0] == 'o' && q[1] == 'f' && 
-			    q[2] == 'f' && (q[3] == ' ' || q[3] == '\0')) {
-				my_smt_enabled = SMT_OFF;
-			} else if (q[0]=='o' && q[1] == 'n' && 
-				   (q[2] == ' ' || q[2] == '\0')) {
-				my_smt_enabled = SMT_ON;
-			} else {
-				my_smt_enabled = SMT_DYNAMIC;
-			} 
-		}
-	}
-	if (!found) {
-		prom_options = call_prom("finddevice", 1, 1, ADDR("/options"));
-		if (prom_options != (ihandle) -1) {
-			prom_getprop(prom_options, "ibm,smt-enabled",
-				     option, sizeof(option));
-			if (option[0] != 0) {
-				found = 1;
-				if (!strcmp(option, RELOC("off")))
-					my_smt_enabled = SMT_OFF;
-				else if (!strcmp(option, RELOC("on")))
-					my_smt_enabled = SMT_ON;
-				else
-					my_smt_enabled = SMT_DYNAMIC;
-			}
-		}
-	}
-
-	if (!found )
-		my_smt_enabled = SMT_DYNAMIC; /* default to on */
-
-	_naca->smt_state = my_smt_enabled;
-}
-
-
-#ifdef CONFIG_BOOTX_TEXT
-
-/* This function will enable the early boot text when doing OF booting. This
- * way, xmon output should work too
- */
-static void __init setup_disp_fake_bi(ihandle dp)
-{
-	int width = 640, height = 480, depth = 8, pitch;
-	unsigned address;
-	struct pci_reg_property addrs[8];
-	int i, naddrs;
-	char name[64];
-	unsigned long offset = reloc_offset();
-
-	memset(name, 0, sizeof(name));
-	prom_getprop(dp, "name", name, sizeof(name));
-	name[sizeof(name)-1] = 0;
-	prom_printf("Initializing fake screen: %s\n", name);
-
-	prom_getprop(dp, "width", &width, sizeof(width));
-	prom_getprop(dp, "height", &height, sizeof(height));
-	prom_getprop(dp, "depth", &depth, sizeof(depth));
-	pitch = width * ((depth + 7) / 8);
-	prom_getprop(dp, "linebytes", &pitch, sizeof(pitch));
-	if (pitch == 1)
-		pitch = 0x1000;		/* for strange IBM display */
-	address = 0;
-
-	prom_printf("width %x height %x depth %x linebytes %x\n",
-		    width, height, depth, depth);
-
-	prom_getprop(dp, "address", &address, sizeof(address));
-	if (address == 0) {
-		/* look for an assigned address with a size of >= 1MB */
-		naddrs = prom_getprop(dp, "assigned-addresses",
-				      addrs, sizeof(addrs));
-		naddrs /= sizeof(struct pci_reg_property);
-		for (i = 0; i < naddrs; ++i) {
-			if (addrs[i].size_lo >= (1 << 20)) {
-				address = addrs[i].addr.a_lo;
-				/* use the BE aperture if possible */
-				if (addrs[i].size_lo >= (16 << 20))
-					address += (8 << 20);
-				break;
-			}
-		}
-		if (address == 0) {
-			prom_printf("Failed to get address of frame buffer\n");
-			return;
-		}
-	}
-	btext_setup_display(width, height, depth, pitch, address);
-	prom_printf("Addr of fb: %x\n", address);
-	RELOC(boot_text_mapped) = 0;
-}
-#endif /* CONFIG_BOOTX_TEXT */
-
-static void __init prom_init_client_services(unsigned long pp)
-{
-	unsigned long offset = reloc_offset();
-	struct prom_t *_prom = PTRRELOC(&prom);
-
-	/* Get a handle to the prom entry point before anything else */
-	_prom->entry = pp;
-
-	/* Init default value for phys size */
-	_prom->encode_phys_size = 32;
-
-	/* get a handle for the stdout device */
-	_prom->chosen = call_prom("finddevice", 1, 1, ADDR("/chosen"));
-	if ((long)_prom->chosen <= 0)
-		prom_panic("cannot find chosen"); /* msg won't be printed :( */
-
-	/* get device tree root */
-	_prom->root = call_prom("finddevice", 1, 1, ADDR("/"));
-	if ((long)_prom->root <= 0)
-		prom_panic("cannot find device tree root"); /* msg won't be printed :( */
-}
-
-static void __init prom_init_stdout(void)
-{
-	unsigned long offset = reloc_offset();
-	struct prom_t *_prom = PTRRELOC(&prom);
-	u32 val;
-
-	if (prom_getprop(_prom->chosen, "stdout", &val, sizeof(val)) <= 0)
-		prom_panic("cannot find stdout");
-
-	_prom->stdout = val;
-}
-
-static int __init prom_find_machine_type(void)
-{
-	unsigned long offset = reloc_offset();
-	struct prom_t *_prom = PTRRELOC(&prom);
-	char compat[256];
-	int len, i = 0;
-
-	len = prom_getprop(_prom->root, "compatible",
-			   compat, sizeof(compat)-1);
-	if (len > 0) {
-		compat[len] = 0;
-		while (i < len) {
-			char *p = &compat[i];
-			int sl = strlen(p);
-			if (sl == 0)
-				break;
-			if (strstr(p, RELOC("Power Macintosh")) ||
-			    strstr(p, RELOC("MacRISC4")))
-				return PLATFORM_POWERMAC;
-			i += sl + 1;
-		}
-	}
-	/* Default to pSeries */
-	return PLATFORM_PSERIES;
-}
-
-static int __init prom_set_color(ihandle ih, int i, int r, int g, int b)
-{
-	unsigned long offset = reloc_offset();
-
-	return call_prom("call-method", 6, 1, ADDR("color!"), ih, i, b, g, r);
-}
-
-/*
- * If we have a display that we don't know how to drive,
- * we will want to try to execute OF's open method for it
- * later.  However, OF will probably fall over if we do that
- * we've taken over the MMU.
- * So we check whether we will need to open the display,
- * and if so, open it now.
- */
-static unsigned long __init check_display(unsigned long mem)
-{
-	phandle node;
-	ihandle ih;
-	int i, j;
-	unsigned long offset = reloc_offset();
-	struct prom_t *_prom = PTRRELOC(&prom);
-	char type[16], *path;
-	static unsigned char default_colors[] = {
-		0x00, 0x00, 0x00,
-		0x00, 0x00, 0xaa,
-		0x00, 0xaa, 0x00,
-		0x00, 0xaa, 0xaa,
-		0xaa, 0x00, 0x00,
-		0xaa, 0x00, 0xaa,
-		0xaa, 0xaa, 0x00,
-		0xaa, 0xaa, 0xaa,
-		0x55, 0x55, 0x55,
-		0x55, 0x55, 0xff,
-		0x55, 0xff, 0x55,
-		0x55, 0xff, 0xff,
-		0xff, 0x55, 0x55,
-		0xff, 0x55, 0xff,
-		0xff, 0xff, 0x55,
-		0xff, 0xff, 0xff
-	};
-	const unsigned char *clut;
-
-	_prom->disp_node = 0;
-
-	prom_printf("Looking for displays\n");
-	if (RELOC(of_stdout_device) != 0)
-		prom_printf("OF stdout is    : %s\n",
-			    PTRRELOC(RELOC(of_stdout_device)));
-	for (node = 0; prom_next_node(&node); ) {
-		type[0] = 0;
-		prom_getprop(node, "device_type", type, sizeof(type));
-		if (strcmp(type, RELOC("display")) != 0)
-			continue;
-		/* It seems OF doesn't null-terminate the path :-( */
-		path = (char *) mem;
-		memset(path, 0, 256);
-
-		/*
-		 * leave some room at the end of the path for appending extra
-		 * arguments
-		 */
-		if (call_prom("package-to-path", 3, 1, node, path, 250) < 0)
-			continue;
-		prom_printf("found display   : %s\n", path);
-		
-		/*
-		 * If this display is the device that OF is using for stdout,
-		 * move it to the front of the list.
-		 */
-		mem += strlen(path) + 1;
-		i = RELOC(prom_num_displays);
-		RELOC(prom_num_displays) = i + 1;
-		if (RELOC(of_stdout_device) != 0 && i > 0
-		    && strcmp(PTRRELOC(RELOC(of_stdout_device)), path) == 0) {
-			for (; i > 0; --i) {
-				RELOC(prom_display_paths[i])
-					= RELOC(prom_display_paths[i-1]);
-				RELOC(prom_display_nodes[i])
-					= RELOC(prom_display_nodes[i-1]);
-			}
-			_prom->disp_node = node;
-		}
-		RELOC(prom_display_paths[i]) = PTRUNRELOC(path);
-		RELOC(prom_display_nodes[i]) = node;
-		if (_prom->disp_node == 0)
-			_prom->disp_node = node;
-		if (RELOC(prom_num_displays) >= FB_MAX)
-			break;
-	}
-	prom_printf("Opening displays...\n");
-	for (j = RELOC(prom_num_displays) - 1; j >= 0; j--) {
-		path = PTRRELOC(RELOC(prom_display_paths[j]));
-		prom_printf("opening display : %s", path);
-		ih = call_prom("open", 1, 1, path);
-		if (ih == (ihandle)0 || ih == (ihandle)-1) {
-			prom_printf("... failed\n");
-			continue;
-		}
-
-		prom_printf("... done\n");
-
-		/* Setup a useable color table when the appropriate
-		 * method is available. Should update this to set-colors */
-		clut = RELOC(default_colors);
-		for (i = 0; i < 32; i++, clut += 3)
-			if (prom_set_color(ih, i, clut[0], clut[1],
-					   clut[2]) != 0)
-				break;
-
-#ifdef CONFIG_LOGO_LINUX_CLUT224
-		clut = PTRRELOC(RELOC(logo_linux_clut224.clut));
-		for (i = 0; i < RELOC(logo_linux_clut224.clutsize); i++, clut += 3)
-			if (prom_set_color(ih, i + 32, clut[0], clut[1],
-					   clut[2]) != 0)
-				break;
-#endif /* CONFIG_LOGO_LINUX_CLUT224 */
-	}
-
-	return DOUBLEWORD_ALIGN(mem);
-}
-
-/* Return (relocated) pointer to this much memory: moves initrd if reqd. */
-static void __init *__make_room(unsigned long *mem_start, unsigned long *mem_end,
-				unsigned long needed, unsigned long align)
-{
-	void *ret;
-
-	*mem_start = ALIGN(*mem_start, align);
-	if (*mem_start + needed > *mem_end) {
-#ifdef CONFIG_BLK_DEV_INITRD
-		unsigned long offset = reloc_offset();
-		/* FIXME: Apple OF doesn't map unclaimed mem.  If this
-		 * ever happened on G5, we'd need to fix. */
-		unsigned long initrd_len;
-
-		if (*mem_end != RELOC(initrd_start))
-			prom_panic("No memory for copy_device_tree");
-
-		prom_printf("Huge device_tree: moving initrd\n");
-		/* Move by 4M. */
-		initrd_len = RELOC(initrd_end) - RELOC(initrd_start);
-		*mem_end = RELOC(initrd_start) + 4 * 1024 * 1024;
-		memmove((void *)*mem_end, (void *)RELOC(initrd_start),
-			initrd_len);
-		RELOC(initrd_start) = *mem_end;
-		RELOC(initrd_end) = RELOC(initrd_start) + initrd_len;
-#else
-		prom_panic("No memory for copy_device_tree");
-#endif
-	}
-
-	ret = (void *)*mem_start;
-	*mem_start += needed;
-
-	return ret;
-}
-
-#define make_room(startp, endp, type) \
-	__make_room(startp, endp, sizeof(type), __alignof__(type))
-
-static void __init
-inspect_node(phandle node, struct device_node *dad,
-	     unsigned long *mem_start, unsigned long *mem_end,
-	     struct device_node ***allnextpp)
-{
-	int l;
-	phandle child;
-	struct device_node *np;
-	struct property *pp, **prev_propp;
-	char *prev_name, *namep;
-	unsigned char *valp;
-	unsigned long offset = reloc_offset();
-	phandle ibm_phandle;
-
-	np = make_room(mem_start, mem_end, struct device_node);
-	memset(np, 0, sizeof(*np));
-
-	np->node = node;
-	**allnextpp = PTRUNRELOC(np);
-	*allnextpp = &np->allnext;
-	if (dad != 0) {
-		np->parent = PTRUNRELOC(dad);
-		/* we temporarily use the `next' field as `last_child'. */
-		if (dad->next == 0)
-			dad->child = PTRUNRELOC(np);
-		else
-			dad->next->sibling = PTRUNRELOC(np);
-		dad->next = np;
-	}
-
-	/* get and store all properties */
-	prev_propp = &np->properties;
-	prev_name = RELOC("");
-	for (;;) {
-		/* 32 is max len of name including nul. */
-		namep = make_room(mem_start, mem_end, char[32]);
-		if (call_prom("nextprop", 3, 1, node, prev_name, namep) <= 0) {
-			/* No more nodes: unwind alloc */
-			*mem_start = (unsigned long)namep;
-			break;
-		}
-		/* Trim off some if we can */
-		*mem_start = DOUBLEWORD_ALIGN((unsigned long)namep
-					     + strlen(namep) + 1);
-		pp = make_room(mem_start, mem_end, struct property);
-		pp->name = PTRUNRELOC(namep);
-		prev_name = namep;
-
-		pp->length = call_prom("getproplen", 2, 1, node, namep);
-		if (pp->length < 0)
-			continue;
-		if (pp->length > MAX_PROPERTY_LENGTH) {
-			char path[128];
-
-			prom_printf("WARNING: ignoring large property ");
-			/* It seems OF doesn't null-terminate the path :-( */
-			memset(path, 0, sizeof(path));
-			if (call_prom("package-to-path", 3, 1, node,
-				      path, sizeof(path)-1) > 0)
-				prom_printf("[%s] ", path);
-			prom_printf("%s length 0x%x\n", namep, pp->length);
-			continue;
-		}
-		valp = __make_room(mem_start, mem_end, pp->length, 1);
-		pp->value = PTRUNRELOC(valp);
-		call_prom("getprop", 4, 1, node, namep, valp, pp->length);
-		*prev_propp = PTRUNRELOC(pp);
-		prev_propp = &pp->next;
-	}
-
-	/* Add a "linux,phandle" property. */
-	namep = make_room(mem_start, mem_end, char[16]);
-	strcpy(namep, RELOC("linux,phandle"));
-	pp = make_room(mem_start, mem_end, struct property);
-	pp->name = PTRUNRELOC(namep);
-	pp->length = sizeof(phandle);
-	valp = make_room(mem_start, mem_end, phandle);
-	pp->value = PTRUNRELOC(valp);
-	*(phandle *)valp = node;
-	*prev_propp = PTRUNRELOC(pp);
-	pp->next = NULL;
-
-	/* Set np->linux_phandle to the value of the ibm,phandle property
-	   if it exists, otherwise to the phandle for this node. */
-	np->linux_phandle = node;
-	if (prom_getprop(node, "ibm,phandle",
-			 &ibm_phandle, sizeof(ibm_phandle)) > 0)
-		np->linux_phandle = ibm_phandle;
-
-	/* get the node's full name */
-	namep = (char *)*mem_start;
-	l = call_prom("package-to-path", 3, 1, node,
-		      namep, *mem_end - *mem_start);
-	if (l >= 0) {
-		/* Didn't fit?  Get more room. */
-		if (l+1 > *mem_end - *mem_start) {
-			namep = __make_room(mem_start, mem_end, l+1, 1);
-			call_prom("package-to-path", 3, 1, node, namep, l);
-		}
-		np->full_name = PTRUNRELOC(namep);
-		namep[l] = '\0';
-		*mem_start = DOUBLEWORD_ALIGN(*mem_start + l + 1);
-	}
-
-	/* do all our children */
-	child = call_prom("child", 1, 1, node);
-	while (child != (phandle)0) {
-		inspect_node(child, np, mem_start, mem_end,
-					 allnextpp);
-		child = call_prom("peer", 1, 1, child);
-	}
-}
-
-/*
- * Make a copy of the device tree from the PROM.
- */
-static unsigned long __init
-copy_device_tree(unsigned long mem_start)
-{
-	phandle root;
-	struct device_node **allnextp;
-	unsigned long offset = reloc_offset();
-	unsigned long mem_end;
-
-	/* We pass mem_end-mem_start to OF: keep it well under 32-bit */
-	mem_end = mem_start + 1024*1024*1024;
-#ifdef CONFIG_BLK_DEV_INITRD
-	if (RELOC(initrd_start) && RELOC(initrd_start) > mem_start)
-		mem_end = RELOC(initrd_start);
-#endif /* CONFIG_BLK_DEV_INITRD */
-
-	root = call_prom("peer", 1, 1, (phandle)0);
-	if (root == (phandle)0) {
-		prom_panic("couldn't get device tree root\n");
-	}
-	allnextp = &RELOC(allnodes);
-	inspect_node(root, NULL, &mem_start, &mem_end, &allnextp);
-	*allnextp = NULL;
-	return mem_start;
-}
-
-/* Verify bi_recs are good */
-static struct bi_record * __init prom_bi_rec_verify(struct bi_record *bi_recs)
-{
-	struct bi_record *first, *last;
-
-	prom_debug("birec_verify: r6=0x%x\n", (unsigned long)bi_recs);
-	if (bi_recs != NULL)
-		prom_debug("  tag=0x%x\n", bi_recs->tag);
-
-	if ( bi_recs == NULL || bi_recs->tag != BI_FIRST )
-		return NULL;
-
-	last = (struct bi_record *)(long)bi_recs->data[0];
-
-	prom_debug("  last=0x%x\n", (unsigned long)last);
-	if (last != NULL)
-		prom_debug("  last_tag=0x%x\n", last->tag);
-
-	if ( last == NULL || last->tag != BI_LAST )
-		return NULL;
-
-	first = (struct bi_record *)(long)last->data[0];
-	prom_debug("  first=0x%x\n", (unsigned long)first);
-
-	if ( first == NULL || first != bi_recs )
-		return NULL;
-
-	return bi_recs;
-}
-
-static void __init prom_bi_rec_reserve(void)
-{
-	unsigned long offset = reloc_offset();
-	struct prom_t *_prom = PTRRELOC(&prom);
-	struct bi_record *rec;
-
-	if ( _prom->bi_recs != NULL) {
-
-		for ( rec=_prom->bi_recs;
-		      rec->tag != BI_LAST;
-		      rec=bi_rec_next(rec) ) {
-			prom_debug("bi: 0x%x\n", rec->tag);
-			switch (rec->tag) {
-#ifdef CONFIG_BLK_DEV_INITRD
-			case BI_INITRD:
-				RELOC(initrd_start) = (unsigned long)(rec->data[0]);
-				RELOC(initrd_end) = RELOC(initrd_start) + rec->data[1];
-				break;
-#endif /* CONFIG_BLK_DEV_INITRD */
-			}
-		}
-		/* The next use of this field will be after relocation
-	 	 * is enabled, so convert this physical address into a
-	 	 * virtual address.
-	 	 */
-		_prom->bi_recs = PTRUNRELOC(_prom->bi_recs);
-	}
-}
-
-/*
- * We enter here early on, when the Open Firmware prom is still
- * handling exceptions and the MMU hash table for us.
- */
-
-unsigned long __init
-prom_init(unsigned long r3, unsigned long r4, unsigned long pp,
-	  unsigned long r6, unsigned long r7)
-{
-	unsigned long mem;
-	ihandle prom_cpu;
-	phandle cpu_pkg;
-	unsigned long offset = reloc_offset();
-	long l;
-	char *p, *d;
-	unsigned long phys;
-	u32 getprop_rval;
-	struct systemcfg *_systemcfg;
-	struct paca_struct *lpaca = PTRRELOC(&paca[0]);
-	struct prom_t *_prom = PTRRELOC(&prom);
-
-	/* First zero the BSS -- use memset, some arches don't have
-	 * caches on yet */
-	memset(PTRRELOC(&__bss_start), 0, __bss_stop - __bss_start);
-
-	/* Setup systemcfg and NACA pointers now */
-	RELOC(systemcfg) = _systemcfg = (struct systemcfg *)(SYSTEMCFG_VIRT_ADDR - offset);
-	RELOC(naca) = (struct naca_struct *)(NACA_VIRT_ADDR - offset);
-
-	/* Init interface to Open Firmware and pickup bi-recs */
-	prom_init_client_services(pp);
-
-	/* Init prom stdout device */
-	prom_init_stdout();
-
-	prom_debug("klimit=0x%x\n", RELOC(klimit));
-	prom_debug("offset=0x%x\n", offset);
-	prom_debug("->mem=0x%x\n", RELOC(klimit) - offset);
-
-	/* check out if we have bi_recs */
-	_prom->bi_recs = prom_bi_rec_verify((struct bi_record *)r6);
-	if ( _prom->bi_recs != NULL ) {
-		RELOC(klimit) = PTRUNRELOC((unsigned long)_prom->bi_recs +
-					   _prom->bi_recs->data[1]);
-		prom_debug("bi_recs=0x%x\n", (unsigned long)_prom->bi_recs);
-		prom_debug("new mem=0x%x\n", RELOC(klimit) - offset);
-	}
-
-	/* If we don't have birec's or didn't find them, check for an initrd
-	 * using the "yaboot" way
-	 */
-#ifdef CONFIG_BLK_DEV_INITRD
-	if ( _prom->bi_recs == NULL && r3 && r4 && r4 != 0xdeadbeef) {
-		RELOC(initrd_start) = (r3 >= KERNELBASE) ? __pa(r3) : r3;
-		RELOC(initrd_end) = RELOC(initrd_start) + r4;
-		RELOC(initrd_below_start_ok) = 1;
-	}
-#endif /* CONFIG_BLK_DEV_INITRD */
-
-	/* Default machine type. */
-	_systemcfg->platform = prom_find_machine_type();
-
-	/* On pSeries, copy the CPU hold code */
-	if (_systemcfg->platform == PLATFORM_PSERIES)
-		copy_and_flush(0, KERNELBASE - offset, 0x100, 0);
-
-	/* Start storing things at klimit */
-	mem = RELOC(klimit) - offset;
-
-	/* Get the full OF pathname of the stdout device */
-	p = (char *) mem;
-	memset(p, 0, 256);
-	call_prom("instance-to-path", 3, 1, _prom->stdout, p, 255);
-	RELOC(of_stdout_device) = PTRUNRELOC(p);
-	mem += strlen(p) + 1;
-
-	getprop_rval = 1;
-	prom_getprop(_prom->root, "#size-cells",
-		     &getprop_rval, sizeof(getprop_rval));
-	_prom->encode_phys_size = (getprop_rval == 1) ? 32 : 64;
-
-	/* Determine which cpu is actually running right _now_ */
-	if (prom_getprop(_prom->chosen, "cpu",
-			 &prom_cpu, sizeof(prom_cpu)) <= 0)
-		prom_panic("cannot find boot cpu");
-
-	cpu_pkg = call_prom("instance-to-package", 1, 1, prom_cpu);
-	prom_getprop(cpu_pkg, "reg", &getprop_rval, sizeof(getprop_rval));
-	_prom->cpu = getprop_rval;
-	lpaca[0].hw_cpu_id = _prom->cpu;
-
-	RELOC(boot_cpuid) = 0;
-
-	prom_debug("Booting CPU hw index = 0x%x\n", _prom->cpu);
-
-	/* Get the boot device and translate it to a full OF pathname. */
-	p = (char *) mem;
-	l = prom_getprop(_prom->chosen, "bootpath", p, 1<<20);
-	if (l > 0) {
-		p[l] = 0;	/* should already be null-terminated */
-		RELOC(bootpath) = PTRUNRELOC(p);
-		mem += l + 1;
-		d = (char *) mem;
-		*d = 0;
-		call_prom("canon", 3, 1, p, d, 1<<20);
-		RELOC(bootdevice) = PTRUNRELOC(d);
-		mem = DOUBLEWORD_ALIGN(mem + strlen(d) + 1);
-	}
-
-	RELOC(cmd_line[0]) = 0;
-	if ((long)_prom->chosen > 0) {
-		prom_getprop(_prom->chosen, "bootargs", p, sizeof(cmd_line));
-		if (p != NULL && p[0] != 0)
-			strlcpy(RELOC(cmd_line), p, sizeof(cmd_line));
-	}
-
-	early_cmdline_parse();
-
-	prom_initialize_lmb();
-
-	prom_bi_rec_reserve();
-
-	mem = check_display(mem);
-
-	if (_systemcfg->platform != PLATFORM_POWERMAC)
-		prom_instantiate_rtas();
-
-	/* Initialize some system info into the Naca early... */
-	prom_initialize_naca();
-
-	smt_setup();
-
-	/* If we are on an SMP machine, then we *MUST* do the
-	 * following, regardless of whether we have an SMP
-	 * kernel or not.
-	 */
-	prom_hold_cpus(mem);
-
-	prom_debug("after basic inits, mem=0x%x\n", mem);
-#ifdef CONFIG_BLK_DEV_INITRD
-	prom_debug("initrd_start=0x%x\n", RELOC(initrd_start));
-	prom_debug("initrd_end=0x%x\n", RELOC(initrd_end));
-#endif /* CONFIG_BLK_DEV_INITRD */
-	prom_debug("copying OF device tree...\n");
-
-	mem = copy_device_tree(mem);
-
-	RELOC(klimit) = mem + offset;
-
-	prom_debug("new klimit is\n");
-	prom_debug("klimit=0x%x\n", RELOC(klimit));
-	prom_debug(" ->mem=0x%x\n", mem);
-
-	lmb_reserve(0, __pa(RELOC(klimit)));
-
-#ifdef CONFIG_BLK_DEV_INITRD
-	if (RELOC(initrd_start)) {
-		unsigned long initrd_len;
-		initrd_len = RELOC(initrd_end) - RELOC(initrd_start);
-
-		/* Move initrd if it's where we're going to copy kernel. */
-		if (RELOC(initrd_start) < __pa(RELOC(klimit))) {
-			memmove((void *)mem, (void *)RELOC(initrd_start),
-				initrd_len);
-			RELOC(initrd_start) = mem;
-			RELOC(initrd_end) = mem + initrd_len;
-		}
-
-		lmb_reserve(RELOC(initrd_start), initrd_len);
-	}
-#endif /* CONFIG_BLK_DEV_INITRD */
-
-	if (_systemcfg->platform == PLATFORM_PSERIES)
-		prom_initialize_tce_table();
-
-#ifdef CONFIG_PMAC_DART
-	if (_systemcfg->platform == PLATFORM_POWERMAC)
-		prom_initialize_dart_table();
-#endif
-
-#ifdef CONFIG_BOOTX_TEXT
-	if (_prom->disp_node) {
-		prom_printf("Setting up bi display...\n");
-		setup_disp_fake_bi(_prom->disp_node);
-	}
-#endif /* CONFIG_BOOTX_TEXT */
-
-	prom_printf("Calling quiesce ...\n");
-	call_prom("quiesce", 0, 0);
-	phys = KERNELBASE - offset;
-
-#ifdef CONFIG_BLK_DEV_INITRD
-	/* If we had an initrd, we convert its address to virtual */
-	if (RELOC(initrd_start)) {
-		RELOC(initrd_start) = (unsigned long)__va(RELOC(initrd_start));
-		RELOC(initrd_end) = (unsigned long)__va(RELOC(initrd_end));
-	}
-#endif /* CONFIG_BLK_DEV_INITRD */
-
-	prom_printf("returning from prom_init\n");
-	return phys;
-}
+/* export that to outside world */
+struct device_node *of_chosen;
 
 /*
  * Find the device_node with a given phandle.
  */
-static struct device_node * __devinit
-find_phandle(phandle ph)
+static struct device_node * find_phandle(phandle ph)
 {
 	struct device_node *np;
 
@@ -1866,8 +118,7 @@
 /*
  * Find the interrupt parent of a node.
  */
-static struct device_node * __devinit
-intr_parent(struct device_node *p)
+static struct device_node * __devinit intr_parent(struct device_node *p)
 {
 	phandle *parp;
 
@@ -1908,14 +159,14 @@
  * Map an interrupt from a device up to the platform interrupt
  * descriptor.
  */
-static int __devinit
-map_interrupt(unsigned int **irq, struct device_node **ictrler,
-	      struct device_node *np, unsigned int *ints, int nintrc)
+static int __devinit map_interrupt(unsigned int **irq, struct device_node **ictrler,
+				   struct device_node *np, unsigned int *ints,
+				   int nintrc)
 {
 	struct device_node *p, *ipar;
 	unsigned int *imap, *imask, *ip;
 	int i, imaplen, match;
-	int newintrc, newaddrc;
+	int newintrc = 0, newaddrc = 0;
 	unsigned int *reg;
 	int naddrc;
 
@@ -2004,9 +255,9 @@
 	return nintrc;
 }
 
-static unsigned long __init
-finish_node_interrupts(struct device_node *np, unsigned long mem_start,
-		       int measure_only)
+static unsigned long __init finish_node_interrupts(struct device_node *np,
+						   unsigned long mem_start,
+						   int measure_only)
 {
 	unsigned int *ints;
 	int intlen, intrcells, intrcount;
@@ -2067,9 +318,10 @@
 	return mem_start;
 }
 
-static unsigned long __init
-interpret_pci_props(struct device_node *np, unsigned long mem_start,
-		    int naddrc, int nsizec, int measure_only)
+static unsigned long __init interpret_pci_props(struct device_node *np,
+						unsigned long mem_start,
+						int naddrc, int nsizec,
+						int measure_only)
 {
 	struct address_range *adr;
 	struct pci_reg_property *pci_addrs;
@@ -2095,9 +347,10 @@
 	return mem_start;
 }
 
-static unsigned long __init
-interpret_dbdma_props(struct device_node *np, unsigned long mem_start,
-		      int naddrc, int nsizec, int measure_only)
+static unsigned long __init interpret_dbdma_props(struct device_node *np,
+						  unsigned long mem_start,
+						  int naddrc, int nsizec,
+						  int measure_only)
 {
 	struct reg_property32 *rp;
 	struct address_range *adr;
@@ -2135,9 +388,10 @@
 	return mem_start;
 }
 
-static unsigned long __init
-interpret_macio_props(struct device_node *np, unsigned long mem_start,
-		      int naddrc, int nsizec, int measure_only)
+static unsigned long __init interpret_macio_props(struct device_node *np,
+						  unsigned long mem_start,
+						  int naddrc, int nsizec,
+						  int measure_only)
 {
 	struct reg_property32 *rp;
 	struct address_range *adr;
@@ -2175,9 +429,10 @@
 	return mem_start;
 }
 
-static unsigned long __init
-interpret_isa_props(struct device_node *np, unsigned long mem_start,
-		    int naddrc, int nsizec, int measure_only)
+static unsigned long __init interpret_isa_props(struct device_node *np,
+						unsigned long mem_start,
+						int naddrc, int nsizec,
+						int measure_only)
 {
 	struct isa_reg_property *rp;
 	struct address_range *adr;
@@ -2203,9 +458,10 @@
 	return mem_start;
 }
 
-static unsigned long __init
-interpret_root_props(struct device_node *np, unsigned long mem_start,
-		     int naddrc, int nsizec, int measure_only)
+static unsigned long __init interpret_root_props(struct device_node *np,
+						 unsigned long mem_start,
+						 int naddrc, int nsizec,
+						 int measure_only)
 {
 	struct address_range *adr;
 	int i, l;
@@ -2233,21 +489,15 @@
 	return mem_start;
 }
 
-static unsigned long __init
-finish_node(struct device_node *np, unsigned long mem_start,
-	    interpret_func *ifunc, int naddrc, int nsizec, int measure_only)
+static unsigned long __init finish_node(struct device_node *np,
+					unsigned long mem_start,
+					interpret_func *ifunc,
+					int naddrc, int nsizec,
+					int measure_only)
 {
 	struct device_node *child;
 	int *ip;
 
-	np->name = get_property(np, "name", NULL);
-	np->type = get_property(np, "device_type", NULL);
-
-	if (!np->name)
-		np->name = "<NULL>";
-	if (!np->type)
-		np->type = "<NULL>";
-
 	/* get the device addresses and interrupts */
 	if (ifunc != NULL)
 		mem_start = ifunc(np, mem_start, naddrc, nsizec, measure_only);
@@ -2298,24 +548,516 @@
 /**
  * finish_device_tree is called once things are running normally
  * (i.e. with text and data mapped to the address they were linked at).
- * It traverses the device tree and fills in the name, type,
- * {n_}addrs and {n_}intrs fields of each node.
+ * It traverses the device tree and fills in some of the additional,
+ * fields in each node like {n_}addrs and {n_}intrs, the virt interrupt
+ * mapping is also initialized at this point.
  */
-void __init
-finish_device_tree(void)
+void __init finish_device_tree(void)
 {
-	unsigned long mem = klimit;
+	unsigned long mem, size;
 
+	DBG(" -> finish_device_tree\n");
+
+	if (naca->interrupt_controller == IC_INVALID) {
+		DBG("failed to configure interrupt controller type\n");
+		panic("failed to configure interrupt controller type\n");
+	}
+	
+	/* Initialize virtual IRQ map */
 	virt_irq_init();
 
-	dev_tree_size = finish_node(allnodes, 0, NULL, 0, 0, 1);
-	mem = (long)abs_to_virt(lmb_alloc(dev_tree_size,
-					  __alignof__(struct device_node)));
-	if (finish_node(allnodes, mem, NULL, 0, 0, 0) != mem + dev_tree_size)
+	/* Finish device-tree (pre-parsing some properties etc...) */
+	size = finish_node(allnodes, 0, NULL, 0, 0, 1);
+	mem = (unsigned long)abs_to_virt(lmb_alloc(size, 128));
+	if (finish_node(allnodes, mem, NULL, 0, 0, 0) != mem + size)
 		BUG();
-	rtas.dev = of_find_node_by_name(NULL, "rtas");
+
+	DBG(" <- finish_device_tree\n");
+}
+
+#ifdef DEBUG
+#define printk udbg_printf
+#endif
+
+static inline char *find_flat_dt_string(u32 offset)
+{
+	return ((char *)initial_boot_params) + initial_boot_params->off_dt_strings
+		+ offset;
+}
+
+/**
+ * This function is used to scan the flattened device-tree, it is
+ * used to extract the memory informations at boot before we can
+ * unflatten the tree
+ */
+static int __init scan_flat_dt(int (*it)(unsigned long node,
+					 const char *full_path, void *data),
+			       void *data)
+{
+	unsigned long p = ((unsigned long)initial_boot_params) +
+		initial_boot_params->off_dt_struct;
+	int rc = 0;
+
+	do {
+		u32 tag = *((u32 *)p);
+		char *pathp;
+		
+		p += 4;
+		if (tag == OF_DT_END_NODE)
+			continue;
+		if (tag == OF_DT_END)
+			break;
+		if (tag == OF_DT_PROP) {
+			u32 sz = *((u32 *)p);
+			p += 8;
+			p = _ALIGN(p, sz >= 8 ? 8 : 4);
+			p += sz;
+			p = _ALIGN(p, 4);
+			continue;
+		}
+		if (tag != OF_DT_BEGIN_NODE) {
+			printk(KERN_WARNING "Invalid tag %x scanning flattened"
+			       " device tree !\n", tag);
+			return -EINVAL;
+		}
+		pathp = (char *)p;
+		p = _ALIGN(p + strlen(pathp) + 1, 4);
+		rc = it(p, pathp, data);
+		if (rc != 0)
+			break;		
+	} while(1);
+
+	return rc;
 }
 
+/**
+ * This  function can be used within scan_flattened_dt callback to get
+ * access to properties
+ */
+static void* __init get_flat_dt_prop(unsigned long node, const char *name,
+				     unsigned long *size)
+{
+	unsigned long p = node;
+
+	do {
+		u32 tag = *((u32 *)p);
+		u32 sz, noff;
+		const char *nstr;
+
+		p += 4;
+		if (tag != OF_DT_PROP)
+			return NULL;
+
+		sz = *((u32 *)p);
+		noff = *((u32 *)(p + 4));
+		p += 8;
+		p = _ALIGN(p, sz >= 8 ? 8 : 4);
+
+		nstr = find_flat_dt_string(noff);
+		if (nstr == NULL) {
+			printk(KERN_WARNING "Can't find property index name !\n");
+			return NULL;
+		}
+		if (strcmp(name, nstr) == 0) {
+			if (size)
+				*size = sz;
+			return (void *)p;
+		}
+		p += sz;
+		p = _ALIGN(p, 4);
+	} while(1);
+}
+
+static void *__init unflatten_dt_alloc(unsigned long *mem, unsigned long size,
+					       unsigned long align)
+{
+	void *res;
+
+	*mem = _ALIGN(*mem, align);
+	res = (void *)*mem;
+	*mem += size;
+
+	return res;
+}
+
+static unsigned long __init unflatten_dt_node(unsigned long mem,
+					      unsigned long *p,
+					      struct device_node *dad,
+					      struct device_node ***allnextpp)
+{
+	struct device_node *np;
+	struct property *pp, **prev_pp = NULL;
+	char *pathp;
+	u32 tag;
+	unsigned int l;
+
+	tag = *((u32 *)(*p));
+	if (tag != OF_DT_BEGIN_NODE) {
+		printk("Weird tag at start of node: %x\n", tag);
+		return mem;
+	}
+	*p += 4;
+	pathp = (char *)*p;
+	l = strlen(pathp) + 1;
+	*p = _ALIGN(*p + l, 4);
+
+	np = unflatten_dt_alloc(&mem, sizeof(struct device_node) + l,
+				__alignof__(struct device_node));
+	if (allnextpp) {
+		memset(np, 0, sizeof(*np));
+		np->full_name = ((char*)np) + sizeof(struct device_node);
+		memcpy(np->full_name, pathp, l);
+		prev_pp = &np->properties;
+		**allnextpp = np;
+		*allnextpp = &np->allnext;
+		if (dad != NULL) {
+			np->parent = dad;
+			/* we temporarily use the `next' field as `last_child'. */
+			if (dad->next == 0)
+				dad->child = np;
+			else
+				dad->next->sibling = np;
+			dad->next = np;
+		}
+	}
+	while(1) {
+		u32 sz, noff;
+		char *pname;
+
+		tag = *((u32 *)(*p));
+		if (tag != OF_DT_PROP)
+			break;
+		*p += 4;
+		sz = *((u32 *)(*p));
+		noff = *((u32 *)((*p) + 4));
+		*p = _ALIGN((*p) + 8, sz >= 8 ? 8 : 4);
+
+		pname = find_flat_dt_string(noff);
+		if (pname == NULL) {
+			printk("Can't find property name in list !\n");
+			break;
+		}
+		l = strlen(pname) + 1;
+		pp = unflatten_dt_alloc(&mem, sizeof(struct property),
+					__alignof__(struct property));
+		if (allnextpp) {
+			if (strcmp(pname, "linux,phandle") == 0) {
+				np->node = *((u32 *)*p);
+				if (np->linux_phandle == 0)
+					np->linux_phandle = np->node;
+			}
+			if (strcmp(pname, "ibm,phandle") == 0)
+				np->linux_phandle = *((u32 *)*p);
+			pp->name = pname;
+			pp->length = sz;
+			pp->value = (void *)*p;
+			*prev_pp = pp;
+			prev_pp = &pp->next;
+		}
+		*p = _ALIGN((*p) + sz, 4);
+	}
+	if (allnextpp) {
+		*prev_pp = NULL;
+		np->name = get_property(np, "name", NULL);
+		np->type = get_property(np, "device_type", NULL);
+
+		if (!np->name)
+			np->name = "<NULL>";
+		if (!np->type)
+			np->type = "<NULL>";
+	}
+	while (tag == OF_DT_BEGIN_NODE) {
+		mem = unflatten_dt_node(mem, p, np, allnextpp);
+		tag = *((u32 *)(*p));
+	}
+	if (tag != OF_DT_END_NODE) {
+		printk("Weird tag at start of node: %x\n", tag);
+		return mem;
+	}
+	*p += 4;
+	return mem;
+}
+
+
+/**
+ * unflattens the device-tree passed by the firmware, creating the
+ * tree of struct device_node. It also fills the "name" and "type"
+ * pointers of the nodes so the normal device-tree walking functions
+ * can be used (this used to be done by finish_device_tree)
+ */
+void __init unflatten_device_tree(void)
+{
+	unsigned long start, mem, size;
+	struct device_node **allnextp = &allnodes;
+	char *p;
+	int l = 0;
+
+	DBG(" -> unflatten_device_tree()\n");
+
+	/* First pass, scan for size */
+	start = ((unsigned long)initial_boot_params) +
+		initial_boot_params->off_dt_struct;
+	size = unflatten_dt_node(0, &start, NULL, NULL);
+
+	DBG("  size is %lx, allocating...\n", size);
+
+	/* Allocate memory for the expanded device tree */
+	mem = (unsigned long)abs_to_virt(lmb_alloc(size,
+						   __alignof__(struct device_node)));
+	DBG("  unflattening...\n", mem);
+
+	/* Second pass, do actual unflattening */
+	start = ((unsigned long)initial_boot_params) +
+		initial_boot_params->off_dt_struct;
+	unflatten_dt_node(mem, &start, NULL, &allnextp);
+	if (*((u32 *)start) != OF_DT_END)
+		printk(KERN_WARNING "Weird tag at end of tree: %x\n", *((u32 *)start));
+	*allnextp = NULL;
+
+	/* Get pointer to OF "/chosen" node for use everywhere */
+	of_chosen = of_find_node_by_path("/chosen");
+
+	/* Retreive command line */
+	if (of_chosen != NULL) {
+		p = (char *)get_property(of_chosen, "bootargs", &l);
+		if (p != NULL && l > 0)
+			strlcpy(cmd_line, p, min(l, COMMAND_LINE_SIZE));
+	}
+#ifdef CONFIG_CMDLINE
+	if (l == 0) /* dbl check */
+		strlcpy(cmd_line, CONFIG_CMDLINE, COMMAND_LINE_SIZE);
+#endif /* CONFIG_CMDLINE */
+
+	DBG("Command line is: %s\n", cmd_line);
+
+	DBG(" <- unflatten_device_tree()\n");
+}
+
+
+static int __init early_init_dt_scan_cpus(unsigned long node,
+					  const char *full_path, void *data)
+{
+	char *type = get_flat_dt_prop(node, "device_type", NULL);
+
+	/* We are scanning "cpu" nodes only */
+	if (type == NULL || strcmp(type, "cpu") != 0)
+		return 0;
+
+	/* On LPAR, look for the first ibm,pft-size property for the  hash table size
+	 */
+	if (systemcfg->platform == PLATFORM_PSERIES_LPAR && naca->pftSize == 0) {
+		u32 *pft_size;
+		pft_size = (u32 *)get_flat_dt_prop(node, "ibm,pft-size", NULL);
+		if (pft_size != NULL) {
+			/* pft_size[0] is the NUMA CEC cookie */
+			naca->pftSize = pft_size[1];
+		}
+	}
+
+	/* Check if it's the boot-cpu, set it's hw index in paca now */
+	if (get_flat_dt_prop(node, "linux,boot-cpu", NULL) != NULL) {
+		u32 *prop = get_flat_dt_prop(node, "reg", NULL);
+		paca[0].hw_cpu_id = prop == NULL ? 0 : *prop;
+	}
+
+	return 0;
+}
+
+static int __init early_init_dt_scan_chosen(unsigned long node,
+					    const char *full_path, void *data)
+{
+	u32 *prop;
+
+	if (strcmp(full_path, "/chosen") != 0)
+		return 0;
+
+	/* get platform type */
+	prop = (u32 *)get_flat_dt_prop(node, "linux,platform", NULL);
+	if (prop == NULL)
+		return 0;
+	systemcfg->platform = *prop;
+
+	/* check if iommu is forced on or off */
+	if (get_flat_dt_prop(node, "linux,iommu-off", NULL) != NULL)
+		iommu_is_off = 1;
+	if (get_flat_dt_prop(node, "linux,iommu-force-on", NULL) != NULL)
+		iommu_force_on = 1;
+
+#ifdef CONFIG_PPC_PSERIES
+	/* To help early debugging via the front panel, we retreive a minimal
+	 * set of RTAS infos now if available
+	 */
+	{
+		u64 *basep, *entryp;
+
+		basep = (u64*)get_flat_dt_prop(node, "linux,rtas-base", NULL);
+		entryp = (u64*)get_flat_dt_prop(node, "linux,rtas-entry", NULL);
+		prop = (u32*)get_flat_dt_prop(node, "linux,rtas-size", NULL);
+		if (basep && entryp && prop) {
+			rtas.base = *basep;
+			rtas.entry = *entryp;
+			rtas.size = *prop;
+		}
+	}
+#endif /* CONFIG_PPC_PSERIES */
+
+	/* break now */
+	return 1;
+}
+
+static int __init early_init_dt_scan_root(unsigned long node,
+					  const char *full_path, void *data)
+{
+	u32 *prop;
+
+	if (strcmp(full_path, "/") != 0)
+		return 0;
+
+	prop = (u32 *)get_flat_dt_prop(node, "#size-cells", NULL);
+	dt_root_size_cells = (prop == NULL) ? 1 : *prop;
+		
+	prop = (u32 *)get_flat_dt_prop(node, "#address-cells", NULL);
+	dt_root_addr_cells = (prop == NULL) ? 2 : *prop;
+	
+	/* break now */
+	return 1;
+}
+
+static unsigned long __init dt_mem_next_cell(int s, cell_t **cellp)
+{
+	cell_t *p = *cellp;
+	unsigned long r = 0;
+
+	/* Ignore more than 2 cells */
+	while (s > 2) {
+		p++;
+		s--;
+	}
+	while (s) {
+		r <<= 32;
+		r |= *(p++);
+		s--;
+	}
+
+	*cellp = p;
+	return r;
+}
+
+
+static int __init early_init_dt_scan_memory(unsigned long node,
+					    const char *full_path, void *data)
+{
+	char *type = get_flat_dt_prop(node, "device_type", NULL);
+	cell_t *reg, *endp;
+	unsigned long l;
+
+	/* We are scanning "memory" nodes only */
+	if (type == NULL || strcmp(type, "memory") != 0)
+		return 0;
+
+	reg = (cell_t *)get_flat_dt_prop(node, "reg", &l);
+	if (reg == NULL)
+		return 0;
+
+	endp = reg + (l / sizeof(cell_t));
+
+	DBG("memory scan node %s ...\n", full_path);
+	while ((endp - reg) >= (dt_root_addr_cells + dt_root_size_cells)) {
+		unsigned long base, size;
+
+		base = dt_mem_next_cell(dt_root_addr_cells, &reg);
+		size = dt_mem_next_cell(dt_root_size_cells, &reg);
+
+		if (size == 0)
+			continue;
+		DBG(" - %lx ,  %lx\n", base, size);
+		if (iommu_is_off) {
+			if (base >= 0x80000000ul)
+				continue;
+			if ((base + size) > 0x80000000ul)
+				size = 0x80000000ul - base;
+		}
+		lmb_add(base, size);
+	}
+	return 0;
+}
+
+static void __init early_reserve_mem(void)
+{
+	u64 base, size;
+	u64 *reserve_map = (u64 *)(((unsigned long)initial_boot_params) +
+				   initial_boot_params->off_mem_rsvmap);
+	while (1) {
+		base = *(reserve_map++);
+		size = *(reserve_map++);
+		if (size == 0)
+			break;
+		DBG("reserving: %lx -> %lx\n", base, size);
+		lmb_reserve(base, size);
+	}
+
+#if 0
+	DBG("memory reserved, lmbs :\n");
+      	lmb_dump_all();
+#endif
+}
+
+void __init early_init_devtree(void *params)
+{
+	DBG(" -> early_init_devtree()\n");
+
+	/* Setup flat device-tree pointer */
+	initial_boot_params = params;
+
+	/* By default, hash size is not set */
+	naca->pftSize = 0;
+
+	/* Retreive various informations from the /chosen node of the
+	 * device-tree, including the platform type, initrd location and
+	 * size, TCE reserve, and more ...
+	 */
+	scan_flat_dt(early_init_dt_scan_chosen, NULL);
+
+	/* Scan memory nodes and rebuild LMBs */
+	lmb_init();
+	scan_flat_dt(early_init_dt_scan_root, NULL);
+	scan_flat_dt(early_init_dt_scan_memory, NULL);
+	lmb_analyze();
+	systemcfg->physicalMemorySize = lmb_phys_mem_size();
+
+	DBG("Phys. mem: %lx\n", systemcfg->physicalMemorySize);
+
+	/* Reserve LMB regions used by kernel, initrd, dt, etc... */
+	early_reserve_mem();
+
+	DBG("Scanning CPUs ...\n");
+
+	/* Retreive hash table size from flattened tree */
+	scan_flat_dt(early_init_dt_scan_cpus, NULL);
+
+	/* If hash size wasn't obtained above, we calculate it now based on
+	 * the total RAM size
+	 */
+	if (naca->pftSize == 0) {
+		unsigned long rnd_mem_size, pteg_count;
+
+		/* round mem_size up to next power of 2 */
+		rnd_mem_size = 1UL << __ilog2(systemcfg->physicalMemorySize);
+		if (rnd_mem_size < systemcfg->physicalMemorySize)
+			rnd_mem_size <<= 1;
+
+		/* # pages / 2 */
+		pteg_count = (rnd_mem_size >> (12 + 1));
+
+		naca->pftSize = __ilog2(pteg_count << 7);
+	}
+
+	DBG("Hash pftSize: %x\n", (int)naca->pftSize);
+	DBG(" <- early_init_devtree()\n");
+}
+
+#undef printk
+
 int
 prom_n_addr_cells(struct device_node* np)
 {
@@ -2628,6 +1370,28 @@
 EXPORT_SYMBOL(of_find_node_by_path);
 
 /**
+ *	of_find_node_by_phandle - Find a node given a phandle
+ *	@handle:	phandle of the node to find
+ *
+ *	Returns a node pointer with refcount incremented, use
+ *	of_node_put() on it when done.
+ */
+struct device_node *of_find_node_by_phandle(phandle handle)
+{
+	struct device_node *np;
+
+	read_lock(&devtree_lock);
+	for (np = allnodes; np != 0; np = np->allnext)
+		if (np->linux_phandle == handle)
+			break;
+	if (np)
+		of_node_get(np);
+	read_unlock(&devtree_lock);
+	return np;
+}
+EXPORT_SYMBOL(of_find_node_by_phandle);
+
+/**
  *	of_find_all_nodes - Get next node in global list
  *	@prev:	Previous node or NULL to start iteration
  *		of_node_put() will be called on it
@@ -2886,6 +1650,7 @@
 	return 0;
 }
 
+
 /*
  * Fix up the uninitialized fields in a new device node:
  * name, type, n_addrs, addrs, n_intrs, intrs, and pci-specific fields
@@ -2971,12 +1736,14 @@
 
 	/* fixing up iommu_table */
 
+#ifdef CONFIG_PPC_PSERIES
 	if (strcmp(node->name, "pci") == 0 &&
 	    get_property(node, "ibm,dma-window", NULL)) {
 		node->bussubno = node->busno;
 		iommu_devnode_init(node);
 	} else
 		node->iommu_table = parent->iommu_table;
+#endif /* CONFIG_PPC_PSERIES */
 
 out:
 	of_node_put(parent);
@@ -3163,3 +1930,13 @@
 	}
 }
 #endif
+
+
+
+
+
+
+
+
+
+
diff -Nru a/arch/ppc64/kernel/prom_init.c b/arch/ppc64/kernel/prom_init.c
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/arch/ppc64/kernel/prom_init.c	2004-10-18 14:57:24 -07:00
@@ -0,0 +1,1714 @@
+/*
+ * 
+ *
+ * Procedures for interfacing to Open Firmware.
+ *
+ * Paul Mackerras	August 1996.
+ * Copyright (C) 1996 Paul Mackerras.
+ * 
+ *  Adapted for 64bit PowerPC by Dave Engebretsen and Peter Bergner.
+ *    {engebret|bergner}@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.
+ */
+
+#undef DEBUG_PROM
+
+#include <stdarg.h>
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/string.h>
+#include <linux/init.h>
+#include <linux/version.h>
+#include <linux/threads.h>
+#include <linux/spinlock.h>
+#include <linux/types.h>
+#include <linux/pci.h>
+#include <linux/proc_fs.h>
+#include <linux/stringify.h>
+#include <linux/delay.h>
+#include <linux/initrd.h>
+#include <asm/prom.h>
+#include <asm/rtas.h>
+#include <asm/abs_addr.h>
+#include <asm/page.h>
+#include <asm/processor.h>
+#include <asm/irq.h>
+#include <asm/io.h>
+#include <asm/smp.h>
+#include <asm/system.h>
+#include <asm/mmu.h>
+#include <asm/pgtable.h>
+#include <asm/bitops.h>
+#include <asm/naca.h>
+#include <asm/pci.h>
+#include <asm/iommu.h>
+#include <asm/bootinfo.h>
+#include <asm/ppcdebug.h>
+#include <asm/btext.h>
+#include <asm/sections.h>
+#include <asm/machdep.h>
+#include "open_pic.h"
+
+#ifdef CONFIG_LOGO_LINUX_CLUT224
+#include <linux/linux_logo.h>
+extern const struct linux_logo logo_linux_clut224;
+#endif
+
+/*
+ * Properties whose value is longer than this get excluded from our
+ * copy of the device tree. This value does need to be big enough to
+ * ensure that we don't lose things like the interrupt-map property
+ * on a PCI-PCI bridge.
+ */
+#define MAX_PROPERTY_LENGTH	(1UL * 1024 * 1024)
+
+/*
+ * Eventually bump that one up
+ */
+#define DEVTREE_CHUNK_SIZE	0x100000
+
+/*
+ * This is the size of the local memory reserve map that gets copied
+ * into the boot params passed to the kernel. That size is totally
+ * flexible as the kernel just reads the list until it encounters an
+ * entry with size 0, so it can be changed without breaking binary
+ * compatibility
+ */
+#define MEM_RESERVE_MAP_SIZE	8
+
+/*
+ * prom_init() is called very early on, before the kernel text
+ * and data have been mapped to KERNELBASE.  At this point the code
+ * is running at whatever address it has been loaded at, so
+ * references to extern and static variables must be relocated
+ * explicitly.  The procedure reloc_offset() returns the address
+ * we're currently running at minus the address we were linked at.
+ * (Note that strings count as static variables.)
+ *
+ * Because OF may have mapped I/O devices into the area starting at
+ * KERNELBASE, particularly on CHRP machines, we can't safely call
+ * OF once the kernel has been mapped to KERNELBASE.  Therefore all
+ * OF calls should be done within prom_init(), and prom_init()
+ * and all routines called within it must be careful to relocate
+ * references as necessary.
+ *
+ * Note that the bss is cleared *after* prom_init runs, so we have
+ * to make sure that any static or extern variables it accesses
+ * are put in the data segment.
+ */
+
+
+#define PROM_BUG() do {						\
+        prom_printf("kernel BUG at %s line 0x%x!\n",		\
+		    RELOC(__FILE__), __LINE__);			\
+        __asm__ __volatile__(".long " BUG_ILLEGAL_INSTR);	\
+} while (0)
+
+#ifdef DEBUG_PROM
+#define prom_debug(x...)	prom_printf(x)
+#else
+#define prom_debug(x...)
+#endif
+
+
+typedef u32 prom_arg_t;
+
+struct prom_args {
+        u32 service;
+        u32 nargs;
+        u32 nret;
+        prom_arg_t args[10];
+        prom_arg_t *rets;     /* Pointer to return values in args[16]. */
+};
+
+struct prom_t {
+	unsigned long entry;
+	ihandle root;
+	ihandle chosen;
+	int cpu;
+	ihandle stdout;
+	ihandle disp_node;
+	struct prom_args args;
+	unsigned long version;
+	unsigned long root_size_cells;
+	unsigned long root_addr_cells;
+};
+
+struct pci_reg_property {
+	struct pci_address addr;
+	u32 size_hi;
+	u32 size_lo;
+};
+
+struct mem_map_entry {
+	u64	base;
+	u64	size;
+};
+
+typedef u32 cell_t;
+
+extern void __start(unsigned long r3, unsigned long r4, unsigned long r5);
+
+extern unsigned long reloc_offset(void);
+extern void enter_prom(struct prom_args *args, unsigned long entry);
+extern void copy_and_flush(unsigned long dest, unsigned long src,
+			   unsigned long size, unsigned long offset);
+
+extern unsigned long klimit;
+
+//int global_width = 640, global_height = 480, global_depth = 8, global_pitch;
+//unsigned global_address;
+/* prom structure */
+static struct prom_t __initdata prom;
+
+#define PROM_SCRATCH_SIZE 256
+
+static char __initdata of_stdout_device[256];
+static char __initdata prom_scratch[PROM_SCRATCH_SIZE];
+
+static unsigned long __initdata dt_header_start;
+static unsigned long __initdata dt_struct_start, dt_struct_end;
+static unsigned long __initdata dt_string_start, dt_string_end;
+
+static unsigned long __initdata prom_initrd_start, prom_initrd_end;
+
+static int __initdata iommu_force_on;
+static int __initdata ppc64_iommu_off;
+static int __initdata of_platform;
+
+static char __initdata prom_cmd_line[COMMAND_LINE_SIZE];
+
+static unsigned long __initdata alloc_top;
+static unsigned long __initdata alloc_top_high;
+static unsigned long __initdata alloc_bottom;
+static unsigned long __initdata rmo_top;
+static unsigned long __initdata ram_top;
+
+static struct mem_map_entry __initdata mem_reserve_map[MEM_RESERVE_MAP_SIZE];
+static int __initdata mem_reserve_cnt;
+
+static cell_t __initdata regbuf[1024];
+
+
+#define MAX_CPU_THREADS 2
+
+/* TO GO */
+#ifdef CONFIG_HMT
+struct {
+	unsigned int pir;
+	unsigned int threadid;
+} hmt_thread_data[NR_CPUS];
+#endif /* CONFIG_HMT */
+
+/*
+ * This are used in calls to call_prom.  The 4th and following
+ * arguments to call_prom should be 32-bit values.  64 bit values
+ * are truncated to 32 bits (and fortunately don't get interpreted
+ * as two arguments).
+ */
+#define ADDR(x)		(u32) ((unsigned long)(x) - offset)
+
+/* This is the one and *ONLY* place where we actually call open
+ * firmware from, since we need to make sure we're running in 32b
+ * mode when we do.  We switch back to 64b mode upon return.
+ */
+
+#define PROM_ERROR	(-1)
+
+static int __init call_prom(const char *service, int nargs, int nret, ...)
+{
+	int i;
+	unsigned long offset = reloc_offset();
+	struct prom_t *_prom = PTRRELOC(&prom);
+	va_list list;
+
+	_prom->args.service = ADDR(service);
+	_prom->args.nargs = nargs;
+	_prom->args.nret = nret;
+	_prom->args.rets = (prom_arg_t *)&(_prom->args.args[nargs]);
+
+	va_start(list, nret);
+	for (i=0; i < nargs; i++)
+		_prom->args.args[i] = va_arg(list, prom_arg_t);
+	va_end(list);
+
+	for (i=0; i < nret ;i++)
+		_prom->args.rets[i] = 0;
+
+	enter_prom(&_prom->args, _prom->entry);
+
+	return (nret > 0) ? _prom->args.rets[0] : 0;
+}
+
+
+static unsigned int __init prom_claim(unsigned long virt, unsigned long size,
+				unsigned long align)
+{
+	return (unsigned int)call_prom("claim", 3, 1,
+				       (prom_arg_t)virt, (prom_arg_t)size,
+				       (prom_arg_t)align);
+}
+
+static void __init prom_print(const char *msg)
+{
+	const char *p, *q;
+	unsigned long offset = reloc_offset();
+	struct prom_t *_prom = PTRRELOC(&prom);
+
+	if (_prom->stdout == 0)
+		return;
+
+	for (p = msg; *p != 0; p = q) {
+		for (q = p; *q != 0 && *q != '\n'; ++q)
+			;
+		if (q > p)
+			call_prom("write", 3, 1, _prom->stdout, p, q - p);
+		if (*q == 0)
+			break;
+		++q;
+		call_prom("write", 3, 1, _prom->stdout, ADDR("\r\n"), 2);
+	}
+}
+
+
+static void __init prom_print_hex(unsigned long val)
+{
+	unsigned long offset = reloc_offset();
+	int i, nibbles = sizeof(val)*2;
+	char buf[sizeof(val)*2+1];
+	struct prom_t *_prom = PTRRELOC(&prom);
+
+	for (i = nibbles-1;  i >= 0;  i--) {
+		buf[i] = (val & 0xf) + '0';
+		if (buf[i] > '9')
+			buf[i] += ('a'-'0'-10);
+		val >>= 4;
+	}
+	buf[nibbles] = '\0';
+	call_prom("write", 3, 1, _prom->stdout, buf, nibbles);
+}
+
+
+static void __init prom_printf(const char *format, ...)
+{
+	unsigned long offset = reloc_offset();
+	const char *p, *q, *s;
+	va_list args;
+	unsigned long v;
+	struct prom_t *_prom = PTRRELOC(&prom);
+
+	va_start(args, format);
+	for (p = PTRRELOC(format); *p != 0; p = q) {
+		for (q = p; *q != 0 && *q != '\n' && *q != '%'; ++q)
+			;
+		if (q > p)
+			call_prom("write", 3, 1, _prom->stdout, p, q - p);
+		if (*q == 0)
+			break;
+		if (*q == '\n') {
+			++q;
+			call_prom("write", 3, 1, _prom->stdout,
+				  ADDR("\r\n"), 2);
+			continue;
+		}
+		++q;
+		if (*q == 0)
+			break;
+		switch (*q) {
+		case 's':
+			++q;
+			s = va_arg(args, const char *);
+			prom_print(s);
+			break;
+		case 'x':
+			++q;
+			v = va_arg(args, unsigned long);
+			prom_print_hex(v);
+			break;
+		}
+	}
+}
+
+
+static void __init __attribute__((noreturn)) prom_panic(const char *reason)
+{
+	unsigned long offset = reloc_offset();
+
+	prom_print(PTRRELOC(reason));
+	/* ToDo: should put up an SRC here */
+	call_prom("exit", 0, 0);
+
+	for (;;)			/* should never get here */
+		;
+}
+
+
+static int __init prom_next_node(phandle *nodep)
+{
+	phandle node;
+
+	if ((node = *nodep) != 0
+	    && (*nodep = call_prom("child", 1, 1, node)) != 0)
+		return 1;
+	if ((*nodep = call_prom("peer", 1, 1, node)) != 0)
+		return 1;
+	for (;;) {
+		if ((node = call_prom("parent", 1, 1, node)) == 0)
+			return 0;
+		if ((*nodep = call_prom("peer", 1, 1, node)) != 0)
+			return 1;
+	}
+}
+
+static int __init prom_getprop(phandle node, const char *pname,
+			       void *value, size_t valuelen)
+{
+	unsigned long offset = reloc_offset();
+
+	return call_prom("getprop", 4, 1, node, ADDR(pname),
+			 (u32)(unsigned long) value, (u32) valuelen);
+}
+
+static int __init prom_getproplen(phandle node, const char *pname)
+{
+	unsigned long offset = reloc_offset();
+
+	return call_prom("getproplen", 2, 1, node, ADDR(pname));
+}
+
+static int __init prom_setprop(phandle node, const char *pname,
+			       void *value, size_t valuelen)
+{
+	unsigned long offset = reloc_offset();
+
+	return call_prom("setprop", 4, 1, node, ADDR(pname),
+			 (u32)(unsigned long) value, (u32) valuelen);
+}
+
+
+/*
+ * Early parsing of the command line passed to the kernel, used for
+ * the options that affect the iommu
+ */
+static void __init early_cmdline_parse(void)
+{
+	unsigned long offset = reloc_offset();
+	struct prom_t *_prom = PTRRELOC(&prom);
+	char *opt, *p;
+	int l = 0;
+
+	RELOC(prom_cmd_line[0]) = 0;
+	p = RELOC(prom_cmd_line);
+	if ((long)_prom->chosen > 0)
+		l = prom_getprop(_prom->chosen, "bootargs", p, COMMAND_LINE_SIZE-1);
+#ifdef CONFIG_CMDLINE
+	if (l == 0) /* dbl check */
+		strlcpy(RELOC(prom_cmd_line),
+			RELOC(CONFIG_CMDLINE), sizeof(prom_cmd_line));
+#endif /* CONFIG_CMDLINE */
+	prom_printf("command line: %s\n", RELOC(prom_cmd_line));
+
+	opt = strstr(RELOC(prom_cmd_line), RELOC("iommu="));
+	if (opt) {
+		prom_printf("iommu opt is: %s\n", opt);
+		opt += 6;
+		while (*opt && *opt == ' ')
+			opt++;
+		if (!strncmp(opt, RELOC("off"), 3))
+			RELOC(ppc64_iommu_off) = 1;
+		else if (!strncmp(opt, RELOC("force"), 5))
+			RELOC(iommu_force_on) = 1;
+	}
+}
+
+/*
+ * Memory allocation strategy... our layout is normally:
+ *
+ *  at 14Mb or more we vmlinux, then a gap and initrd. In some rare cases, initrd
+ *  might end up beeing before the kernel though. We assume this won't override
+ *  the final kernel at 0, we have no provision to handle that in this version,
+ *  but it should hopefully never happen.
+ *
+ *  alloc_top is set to the top of RMO, eventually shrink down if the TCEs overlap
+ *  alloc_bottom is set to the top of kernel/initrd
+ *
+ *  from there, allocations are done that way : rtas is allocated topmost, and
+ *  the device-tree is allocated from the bottom. We try to grow the device-tree
+ *  allocation as we progress. If we can't, then we fail, we don't currently have
+ *  a facility to restart elsewhere, but that shouldn't be necessary neither
+ *
+ *  Note that calls to reserve_mem have to be done explicitely, memory allocated
+ *  with either alloc_up or alloc_down isn't automatically reserved.
+ */
+
+
+/*
+ * Allocates memory in the RMO upward from the kernel/initrd
+ *
+ * When align is 0, this is a special case, it means to allocate in place
+ * at the current location of alloc_bottom or fail (that is basically
+ * extending the previous allocation). Used for the device-tree flattening
+ */
+static unsigned long __init alloc_up(unsigned long size, unsigned long align)
+{
+	unsigned long offset = reloc_offset();
+	unsigned long base = _ALIGN_UP(RELOC(alloc_bottom), align);
+	unsigned long addr = 0;
+
+	prom_debug("alloc_up(%x, %x)\n", size, align);
+	if (RELOC(ram_top) == 0)
+		prom_panic("alloc_up() called with mem not initialized\n");
+
+	if (align)
+		base = _ALIGN_UP(RELOC(alloc_bottom), align);
+	else
+		base = RELOC(alloc_bottom);
+
+	for(; (base + size) <= RELOC(alloc_top); 
+	    base = _ALIGN_UP(base + 0x100000, align)) {
+		prom_debug("    trying: 0x%x\n\r", base);
+		addr = (unsigned long)prom_claim(base, size, 0);
+		if ((int)addr != PROM_ERROR)
+			break;
+		addr = 0;
+		if (align == 0)
+			break;
+	}
+	if (addr == 0)
+		return 0;
+	RELOC(alloc_bottom) = addr;
+
+	prom_debug(" -> %x\n", addr);
+	prom_debug("  alloc_bottom : %x\n", RELOC(alloc_bottom));
+	prom_debug("  alloc_top    : %x\n", RELOC(alloc_top));
+	prom_debug("  alloc_top_hi : %x\n", RELOC(alloc_top_high));
+	prom_debug("  rmo_top      : %x\n", RELOC(rmo_top));
+	prom_debug("  ram_top      : %x\n", RELOC(ram_top));
+
+	return addr;
+}
+
+/*
+ * Allocates memory downard, either from top of RMO, or if highmem
+ * is set, from the top of RAM. Note that this one doesn't handle
+ * failures. In does claim memory if highmem is not set.
+ */
+static unsigned long __init alloc_down(unsigned long size, unsigned long align,
+				       int highmem)
+{
+	unsigned long offset = reloc_offset();
+	unsigned long base, addr = 0;
+
+	prom_debug("alloc_down(%x, %x, %s)\n", size, align,
+		   highmem ? RELOC("(high)") : RELOC("(low)"));
+	if (RELOC(ram_top) == 0)
+		prom_panic("alloc_down() called with mem not initialized\n");
+
+	if (highmem) {
+		/* Carve out storage for the TCE table. */
+		addr = _ALIGN_DOWN(RELOC(alloc_top_high) - size, align);
+		if (addr <= RELOC(alloc_bottom))
+			return 0;
+		else {
+			/* Will we bump into the RMO ? If yes, check out that we
+			 * didn't overlap existing allocations there, if we did,
+			 * we are dead, we must be the first in town !
+			 */
+			if (addr < RELOC(rmo_top)) {
+				/* Good, we are first */
+				if (RELOC(alloc_top) == RELOC(rmo_top))
+					RELOC(alloc_top) = RELOC(rmo_top) = addr;
+				else
+					return 0;
+			}
+			RELOC(alloc_top_high) = addr;
+		}
+		goto bail;
+	}
+
+	base = _ALIGN_DOWN(RELOC(alloc_top) - size, align);
+	for(; base > RELOC(alloc_bottom); base = _ALIGN_DOWN(base - 0x100000, align))  {
+		prom_debug("    trying: 0x%x\n\r", base);
+		addr = (unsigned long)prom_claim(base, size, 0);
+		if ((int)addr != PROM_ERROR)
+			break;
+		addr = 0;
+	}
+	if (addr == 0)
+		return 0;
+	RELOC(alloc_top) = addr;
+
+ bail:
+	prom_debug(" -> %x\n", addr);
+	prom_debug("  alloc_bottom : %x\n", RELOC(alloc_bottom));
+	prom_debug("  alloc_top    : %x\n", RELOC(alloc_top));
+	prom_debug("  alloc_top_hi : %x\n", RELOC(alloc_top_high));
+	prom_debug("  rmo_top      : %x\n", RELOC(rmo_top));
+	prom_debug("  ram_top      : %x\n", RELOC(ram_top));
+
+	return addr;
+}
+
+/*
+ * Parse a "reg" cell
+ */
+static unsigned long __init prom_next_cell(int s, cell_t **cellp)
+{
+	cell_t *p = *cellp;
+	unsigned long r = 0;
+
+	/* Ignore more than 2 cells */
+	while (s > 2) {
+		p++;
+		s--;
+	}
+	while (s) {
+		r <<= 32;
+		r |= *(p++);
+		s--;
+	}
+
+	*cellp = p;
+	return r;
+}
+
+/*
+ * Very dumb function for adding to the memory reserve list, but
+ * we don't need anything smarter at this point
+ *
+ * XXX Eventually check for collisions. They should NEVER happen
+ * if problems seem to show up, it would be a good start to track
+ * them down.
+ */
+static void reserve_mem(unsigned long base, unsigned long size)
+{
+	unsigned long offset = reloc_offset();
+	unsigned long top = base + size;
+	unsigned long cnt = RELOC(mem_reserve_cnt);
+
+	if (size == 0)
+		return;
+
+	/* We need to always keep one empty entry so that we
+	 * have our terminator with "size" set to 0 since we are
+	 * dumb and just copy this entire array to the boot params
+	 */
+	base = _ALIGN_DOWN(base, PAGE_SIZE);
+	top = _ALIGN_UP(top, PAGE_SIZE);
+	size = top - base;
+
+	if (cnt >= (MEM_RESERVE_MAP_SIZE - 1))
+		prom_panic("Memory reserve map exhausted !\n");
+	RELOC(mem_reserve_map)[cnt].base = base;
+	RELOC(mem_reserve_map)[cnt].size = size;
+	RELOC(mem_reserve_cnt) = cnt + 1;
+}
+
+/*
+ * Initialize memory allocation mecanism, parse "memory" nodes and
+ * obtain that way the top of memory and RMO to setup out local allocator
+ */
+static void __init prom_init_mem(void)
+{
+	phandle node;
+	char *path, type[64];
+	unsigned int plen;
+	cell_t *p, *endp;
+	unsigned long offset = reloc_offset();
+	struct prom_t *_prom = PTRRELOC(&prom);
+
+	/*
+	 * We iterate the memory nodes to find
+	 * 1) top of RMO (first node)
+	 * 2) top of memory
+	 */
+	prom_debug("root_addr_cells: %x\n", (long)_prom->root_addr_cells);
+	prom_debug("root_size_cells: %x\n", (long)_prom->root_size_cells);
+
+	prom_debug("scanning memory:\n");
+	path = RELOC(prom_scratch);
+
+	for (node = 0; prom_next_node(&node); ) {
+		type[0] = 0;
+		prom_getprop(node, "device_type", type, sizeof(type));
+
+		if (strcmp(type, RELOC("memory")))
+			continue;
+	
+		plen = prom_getprop(node, "reg", RELOC(regbuf), sizeof(regbuf));
+		if (plen > sizeof(regbuf)) {
+			prom_printf("memory node too large for buffer !\n");
+			plen = sizeof(regbuf);
+		}
+		p = RELOC(regbuf);
+		endp = p + (plen / sizeof(cell_t));
+
+#ifdef DEBUG_PROM
+		memset(path, 0, PROM_SCRATCH_SIZE);
+		call_prom("package-to-path", 3, 1, node, path, PROM_SCRATCH_SIZE-1);
+		prom_debug("  node %s :\n", path);
+#endif /* DEBUG_PROM */
+
+		while ((endp - p) >= (_prom->root_addr_cells + _prom->root_size_cells)) {
+			unsigned long base, size;
+
+			base = prom_next_cell(_prom->root_addr_cells, &p);
+			size = prom_next_cell(_prom->root_size_cells, &p);
+
+			if (size == 0)
+				continue;
+			prom_debug("    %x %x\n", base, size);
+			if (base == 0)
+				RELOC(rmo_top) = size;
+			if ((base + size) > RELOC(ram_top))
+				RELOC(ram_top) = base + size;
+		}
+	}
+
+	/* Setup our top/bottom alloc points, that is top of RMO or top of
+	 * segment 0 when running non-LPAR
+	 */
+	if ( RELOC(of_platform) == PLATFORM_PSERIES_LPAR )
+		RELOC(alloc_top) = RELOC(rmo_top);
+	else
+		RELOC(alloc_top) = min(0x40000000ul, RELOC(ram_top));
+	RELOC(alloc_bottom) = PAGE_ALIGN(RELOC(klimit) - offset + 0x4000);
+	RELOC(alloc_top_high) = RELOC(ram_top);
+
+	/* Check if we have an initrd after the kernel, if we do move our bottom
+	 * point to after it
+	 */
+	if (RELOC(prom_initrd_start)) {
+		if ((RELOC(prom_initrd_start) + RELOC(prom_initrd_end))
+		    > RELOC(alloc_bottom))
+			RELOC(alloc_bottom) = PAGE_ALIGN(RELOC(prom_initrd_end));
+	}
+
+	prom_printf("memory layout at init:\n");
+	prom_printf("  alloc_bottom : %x\n", RELOC(alloc_bottom));
+	prom_printf("  alloc_top    : %x\n", RELOC(alloc_top));
+	prom_printf("  alloc_top_hi : %x\n", RELOC(alloc_top_high));
+	prom_printf("  rmo_top      : %x\n", RELOC(rmo_top));
+	prom_printf("  ram_top      : %x\n", RELOC(ram_top));
+}
+
+
+/*
+ * Allocate room for and instanciate RTAS
+ */
+static void __init prom_instantiate_rtas(void)
+{
+	unsigned long offset = reloc_offset();
+	struct prom_t *_prom = PTRRELOC(&prom);
+	phandle prom_rtas;
+	u64 base, entry = 0;
+        u32 size;
+
+	prom_debug("prom_instantiate_rtas: start...\n");
+
+	prom_rtas = call_prom("finddevice", 1, 1, ADDR("/rtas"));
+	if (prom_rtas != (phandle) -1) {
+		prom_getprop(prom_rtas, "rtas-size", &size, sizeof(size));
+		if (size != 0) {
+			base = alloc_down(size, PAGE_SIZE, 0);
+			if (base == 0) {
+				prom_printf("RTAS allocation failed !\n");
+				return;
+			}
+			prom_printf("instantiating rtas at 0x%x", base);
+
+			prom_rtas = call_prom("open", 1, 1, ADDR("/rtas"));
+			prom_printf("...");
+
+			if (call_prom("call-method", 3, 2,
+				      ADDR("instantiate-rtas"),
+				      prom_rtas, base) != PROM_ERROR) {
+				entry = (long)_prom->args.rets[1];
+			}
+			if (entry == 0) {
+				prom_printf(" failed\n");
+				return;
+			}
+			prom_printf(" done\n");
+
+	       		reserve_mem(base, size);
+		}
+
+		prom_setprop(_prom->chosen, "linux,rtas-base", &base, sizeof(base));
+		prom_setprop(_prom->chosen, "linux,rtas-entry", &entry, sizeof(entry));
+		prom_setprop(_prom->chosen, "linux,rtas-size", &size, sizeof(size));
+
+		prom_debug("rtas base     = 0x%x\n", base);
+		prom_debug("rtas entry    = 0x%x\n", entry);
+		prom_debug("rtas size     = 0x%x\n", (long)size);
+	}
+	prom_debug("prom_instantiate_rtas: end...\n");
+}
+
+
+/*
+ * Allocate room for and initialize TCE tables
+ */
+static void __init prom_initialize_tce_table(void)
+{
+	phandle node;
+	ihandle phb_node;
+	unsigned long offset = reloc_offset();
+	char compatible[64], type[64], model[64];
+	char *path = RELOC(prom_scratch);
+	u64 base, vbase, align;
+	u32 minalign, minsize;
+	u64 tce_entry, *tce_entryp;
+	u64 local_alloc_top, local_alloc_bottom;
+	u64 i;
+
+	if (RELOC(ppc64_iommu_off))
+		return;
+
+	prom_debug("starting prom_initialize_tce_table\n");
+
+	/* Cache current top of allocs so we reserve a single block */
+	local_alloc_top = RELOC(alloc_top_high);
+	local_alloc_bottom = local_alloc_top;
+
+	/* Search all nodes looking for PHBs. */
+	for (node = 0; prom_next_node(&node); ) {
+		compatible[0] = 0;
+		type[0] = 0;
+		model[0] = 0;
+		prom_getprop(node, "compatible",
+			     compatible, sizeof(compatible));
+		prom_getprop(node, "device_type", type, sizeof(type));
+		prom_getprop(node, "model", model, sizeof(model));
+
+		if ((type[0] == 0) || (strstr(type, RELOC("pci")) == NULL))
+			continue;
+
+		/* Keep the old logic in tack to avoid regression. */
+		if (compatible[0] != 0) {
+			if ((strstr(compatible, RELOC("python")) == NULL) &&
+			    (strstr(compatible, RELOC("Speedwagon")) == NULL) &&
+			    (strstr(compatible, RELOC("Winnipeg")) == NULL))
+				continue;
+		} else if (model[0] != 0) {
+			if ((strstr(model, RELOC("ython")) == NULL) &&
+			    (strstr(model, RELOC("peedwagon")) == NULL) &&
+			    (strstr(model, RELOC("innipeg")) == NULL))
+				continue;
+		}
+
+		if (prom_getprop(node, "tce-table-minalign", &minalign,
+				 sizeof(minalign)) == PROM_ERROR)
+			minalign = 0;
+		if (prom_getprop(node, "tce-table-minsize", &minsize,
+				 sizeof(minsize)) == PROM_ERROR)
+			minsize = 4UL << 20;
+
+		/*
+		 * Even though we read what OF wants, we just set the table
+		 * size to 4 MB.  This is enough to map 2GB of PCI DMA space.
+		 * By doing this, we avoid the pitfalls of trying to DMA to
+		 * MMIO space and the DMA alias hole.
+		 *
+		 * On POWER4, firmware sets the TCE region by assuming
+		 * each TCE table is 8MB. Using this memory for anything
+		 * else will impact performance, so we always allocate 8MB.
+		 * Anton
+		 */
+		if (__is_processor(PV_POWER4) || __is_processor(PV_POWER4p))
+			minsize = 8UL << 20;
+		else
+			minsize = 4UL << 20;
+
+		/* Align to the greater of the align or size */
+		align = max(minalign, minsize);
+		base = alloc_down(minsize, align, 1);
+		if (base == 0)
+			prom_panic("ERROR, cannot find space for TCE table.\n");
+		if (base < local_alloc_bottom)
+			local_alloc_bottom = base;
+
+		vbase = (unsigned long)abs_to_virt(base);
+
+		/* Save away the TCE table attributes for later use. */
+		prom_setprop(node, "linux,tce-base", &vbase, sizeof(vbase));
+		prom_setprop(node, "linux,tce-size", &minsize, sizeof(minsize));
+		prom_setprop(node, "linux,has-tce-table", NULL, 0);
+
+		/* It seems OF doesn't null-terminate the path :-( */
+		memset(path, 0, sizeof(path));
+		/* Call OF to setup the TCE hardware */
+		if (call_prom("package-to-path", 3, 1, node,
+			      path, PROM_SCRATCH_SIZE-1) == PROM_ERROR) {
+			prom_printf("package-to-path failed\n");
+		}
+
+		prom_debug("TCE table: %s\n", path);
+		prom_debug("\tnode = 0x%x\n", node);
+		prom_debug("\tbase = 0x%x\n", vbase);
+		prom_debug("\tsize = 0x%x\n", minsize);
+
+		/* Initialize the table to have a one-to-one mapping
+		 * over the allocated size.
+		 */
+		tce_entryp = (unsigned long *)base;
+		for (i = 0; i < (minsize >> 3) ;tce_entryp++, i++) {
+			tce_entry = (i << PAGE_SHIFT);
+			tce_entry |= 0x3;
+			*tce_entryp = tce_entry;
+		}
+
+		prom_printf("opening PHB %s", path);
+		phb_node = call_prom("open", 1, 1, path);
+		if ( (long)phb_node <= 0)
+			prom_printf("... failed\n");
+		else
+			prom_printf("... done\n");
+
+		call_prom("call-method", 6, 0, ADDR("set-64-bit-addressing"),
+			  phb_node, -1, minsize,
+			  (u32) base, (u32) (base >> 32));
+		call_prom("close", 1, 0, phb_node);
+	}
+
+	reserve_mem(local_alloc_bottom, local_alloc_top - local_alloc_bottom);
+
+	/* Flag the first invalid entry */
+	prom_debug("ending prom_initialize_tce_table\n");
+}
+
+/*
+ * With CHRP SMP we need to use the OF to start the other
+ * processors so we can't wait until smp_boot_cpus (the OF is
+ * trashed by then) so we have to put the processors into
+ * a holding pattern controlled by the kernel (not OF) before
+ * we destroy the OF.
+ *
+ * This uses a chunk of low memory, puts some holding pattern
+ * code there and sends the other processors off to there until
+ * smp_boot_cpus tells them to do something.  The holding pattern
+ * checks that address until its cpu # is there, when it is that
+ * cpu jumps to __secondary_start().  smp_boot_cpus() takes care
+ * of setting those values.
+ *
+ * We also use physical address 0x4 here to tell when a cpu
+ * is in its holding pattern code.
+ *
+ * Fixup comment... DRENG / PPPBBB - Peter
+ *
+ * -- Cort
+ */
+static void __init prom_hold_cpus(void)
+{
+	unsigned long i;
+	unsigned int reg;
+	phandle node;
+	unsigned long offset = reloc_offset();
+	char type[64];
+	int cpuid = 0;
+	unsigned int interrupt_server[MAX_CPU_THREADS];
+	unsigned int cpu_threads, hw_cpu_num;
+	int propsize;
+	extern void __secondary_hold(void);
+	extern unsigned long __secondary_hold_spinloop;
+	extern unsigned long __secondary_hold_acknowledge;
+	unsigned long *spinloop
+		= (void *)virt_to_abs(&__secondary_hold_spinloop);
+	unsigned long *acknowledge
+		= (void *)virt_to_abs(&__secondary_hold_acknowledge);
+	unsigned long secondary_hold
+		= virt_to_abs(*PTRRELOC((unsigned long *)__secondary_hold));
+	struct prom_t *_prom = PTRRELOC(&prom);
+
+	prom_debug("prom_hold_cpus: start...\n");
+	prom_debug("    1) spinloop       = 0x%x\n", (unsigned long)spinloop);
+	prom_debug("    1) *spinloop      = 0x%x\n", *spinloop);
+	prom_debug("    1) acknowledge    = 0x%x\n",
+		   (unsigned long)acknowledge);
+	prom_debug("    1) *acknowledge   = 0x%x\n", *acknowledge);
+	prom_debug("    1) secondary_hold = 0x%x\n", secondary_hold);
+
+	/* Set the common spinloop variable, so all of the secondary cpus
+	 * will block when they are awakened from their OF spinloop.
+	 * This must occur for both SMP and non SMP kernels, since OF will
+	 * be trashed when we move the kernel.
+	 */
+	*spinloop = 0;
+
+#ifdef CONFIG_HMT
+	for (i=0; i < NR_CPUS; i++) {
+		RELOC(hmt_thread_data)[i].pir = 0xdeadbeef;
+	}
+#endif
+	/* look for cpus */
+	for (node = 0; prom_next_node(&node); ) {
+		type[0] = 0;
+		prom_getprop(node, "device_type", type, sizeof(type));
+		if (strcmp(type, RELOC("cpu")) != 0)
+			continue;
+
+		/* Skip non-configured cpus. */
+		prom_getprop(node, "status", type, sizeof(type));
+		if (strcmp(type, RELOC("okay")) != 0)
+			continue;
+
+		reg = -1;
+		prom_getprop(node, "reg", &reg, sizeof(reg));
+
+		prom_debug("\ncpuid        = 0x%x\n", cpuid);
+		prom_debug("cpu hw idx   = 0x%x\n", reg);
+
+		/* Init the acknowledge var which will be reset by
+		 * the secondary cpu when it awakens from its OF
+		 * spinloop.
+		 */
+		*acknowledge = (unsigned long)-1;
+
+		propsize = prom_getprop(node, "ibm,ppc-interrupt-server#s",
+					&interrupt_server,
+					sizeof(interrupt_server));
+		if (propsize < 0) {
+			/* no property.  old hardware has no SMT */
+			cpu_threads = 1;
+			interrupt_server[0] = reg; /* fake it with phys id */
+		} else {
+			/* We have a threaded processor */
+			cpu_threads = propsize / sizeof(u32);
+			if (cpu_threads > MAX_CPU_THREADS) {
+				prom_printf("SMT: too many threads!\n"
+					    "SMT: found %x, max is %x\n",
+					    cpu_threads, MAX_CPU_THREADS);
+				cpu_threads = 1; /* ToDo: panic? */
+			}
+		}
+
+		hw_cpu_num = interrupt_server[0];
+		if (hw_cpu_num != _prom->cpu) {
+			/* Primary Thread of non-boot cpu */
+			prom_printf("%x : starting cpu hw idx %x... ", cpuid, reg);
+			call_prom("start-cpu", 3, 0, node,
+				  secondary_hold, cpuid);
+
+			for ( i = 0 ; (i < 100000000) && 
+			      (*acknowledge == ((unsigned long)-1)); i++ ) ;
+
+			if (*acknowledge == cpuid) {
+				prom_printf("done\n");
+				/* We have to get every CPU out of OF,
+				 * even if we never start it. */
+				if (cpuid >= NR_CPUS)
+					goto next;
+			} else {
+				prom_printf("failed: %x\n", *acknowledge);
+			}
+		}
+#ifdef CONFIG_SMP
+		else
+			prom_printf("%x : boot cpu     %x\n", cpuid, reg);
+#endif
+next:
+#ifdef CONFIG_SMP
+		/* Init paca for secondary threads.   They start later. */
+		for (i=1; i < cpu_threads; i++) {
+			cpuid++;
+			if (cpuid >= NR_CPUS)
+				continue;
+		}
+#endif /* CONFIG_SMP */
+		cpuid++;
+	}
+#ifdef CONFIG_HMT
+	/* Only enable HMT on processors that provide support. */
+	if (__is_processor(PV_PULSAR) || 
+	    __is_processor(PV_ICESTAR) ||
+	    __is_processor(PV_SSTAR)) {
+		prom_printf("    starting secondary threads\n");
+
+		for (i = 0; i < NR_CPUS; i += 2) {
+			if (!cpu_online(i))
+				continue;
+
+			if (i == 0) {
+				unsigned long pir = mfspr(SPRN_PIR);
+				if (__is_processor(PV_PULSAR)) {
+					RELOC(hmt_thread_data)[i].pir = 
+						pir & 0x1f;
+				} else {
+					RELOC(hmt_thread_data)[i].pir = 
+						pir & 0x3ff;
+				}
+			}
+		}
+	} else {
+		prom_printf("Processor is not HMT capable\n");
+	}
+#endif
+
+	if (cpuid > NR_CPUS)
+		prom_printf("WARNING: maximum CPUs (" __stringify(NR_CPUS)
+			    ") exceeded: ignoring extras\n");
+
+	prom_debug("prom_hold_cpus: end...\n");
+}
+
+
+static void __init prom_init_client_services(unsigned long pp)
+{
+	unsigned long offset = reloc_offset();
+	struct prom_t *_prom = PTRRELOC(&prom);
+
+	/* Get a handle to the prom entry point before anything else */
+	_prom->entry = pp;
+
+	/* Init default value for phys size */
+	_prom->root_size_cells = 1;
+	_prom->root_addr_cells = 2;
+
+	/* get a handle for the stdout device */
+	_prom->chosen = call_prom("finddevice", 1, 1, ADDR("/chosen"));
+	if ((long)_prom->chosen <= 0)
+		prom_panic("cannot find chosen"); /* msg won't be printed :( */
+
+	/* get device tree root */
+	_prom->root = call_prom("finddevice", 1, 1, ADDR("/"));
+	if ((long)_prom->root <= 0)
+		prom_panic("cannot find device tree root"); /* msg won't be printed :( */
+}
+
+static void __init prom_init_stdout(void)
+{
+	unsigned long offset = reloc_offset();
+	struct prom_t *_prom = PTRRELOC(&prom);
+	char *path = RELOC(of_stdout_device);
+	char type[16];
+	u32 val;
+
+	if (prom_getprop(_prom->chosen, "stdout", &val, sizeof(val)) <= 0)
+		prom_panic("cannot find stdout");
+
+	_prom->stdout = val;
+
+	/* Get the full OF pathname of the stdout device */
+	memset(path, 0, 256);
+	call_prom("instance-to-path", 3, 1, _prom->stdout, path, 255);
+	val = call_prom("instance-to-package", 1, 1, _prom->stdout);
+	prom_setprop(_prom->chosen, "linux,stdout-package", &val, sizeof(val));
+	prom_printf("OF stdout device is: %s\n", RELOC(of_stdout_device));
+	prom_setprop(_prom->chosen, "linux,stdout-path",
+		     RELOC(of_stdout_device), strlen(RELOC(of_stdout_device))+1);
+
+	/* If it's a display, note it */
+	memset(type, 0, sizeof(type));
+	prom_getprop(val, "device_type", type, sizeof(type));
+	if (strcmp(type, RELOC("display")) == 0) {
+		_prom->disp_node = val;
+		prom_setprop(val, "linux,boot-display", NULL, 0);
+	}
+}
+
+static int __init prom_find_machine_type(void)
+{
+	unsigned long offset = reloc_offset();
+	struct prom_t *_prom = PTRRELOC(&prom);
+	char compat[256];
+	int len, i = 0;
+	phandle rtas;
+
+	len = prom_getprop(_prom->root, "compatible",
+			   compat, sizeof(compat)-1);
+	if (len > 0) {
+		compat[len] = 0;
+		while (i < len) {
+			char *p = &compat[i];
+			int sl = strlen(p);
+			if (sl == 0)
+				break;
+			if (strstr(p, RELOC("Power Macintosh")) ||
+			    strstr(p, RELOC("MacRISC4")))
+				return PLATFORM_POWERMAC;
+			i += sl + 1;
+		}
+	}
+	/* Default to pSeries. We need to know if we are running LPAR */
+	rtas = call_prom("finddevice", 1, 1, ADDR("/rtas"));
+	if (rtas != (phandle) -1) {
+		unsigned long x;
+		x = prom_getproplen(rtas, "ibm,hypertas-functions");
+		if (x != PROM_ERROR) {
+			prom_printf("Hypertas detected, assuming LPAR !\n");
+			return PLATFORM_PSERIES_LPAR;
+		}
+	}
+	return PLATFORM_PSERIES;
+}
+
+static int __init prom_set_color(ihandle ih, int i, int r, int g, int b)
+{
+	unsigned long offset = reloc_offset();
+
+	return call_prom("call-method", 6, 1, ADDR("color!"), ih, i, b, g, r);
+}
+
+/*
+ * If we have a display that we don't know how to drive,
+ * we will want to try to execute OF's open method for it
+ * later.  However, OF will probably fall over if we do that
+ * we've taken over the MMU.
+ * So we check whether we will need to open the display,
+ * and if so, open it now.
+ */
+static unsigned long __init prom_check_displays(void)
+{
+	unsigned long offset = reloc_offset();
+	struct prom_t *_prom = PTRRELOC(&prom);
+	char type[16], *path;
+	phandle node;
+	ihandle ih;
+	int i;
+
+	static unsigned char default_colors[] = {
+		0x00, 0x00, 0x00,
+		0x00, 0x00, 0xaa,
+		0x00, 0xaa, 0x00,
+		0x00, 0xaa, 0xaa,
+		0xaa, 0x00, 0x00,
+		0xaa, 0x00, 0xaa,
+		0xaa, 0xaa, 0x00,
+		0xaa, 0xaa, 0xaa,
+		0x55, 0x55, 0x55,
+		0x55, 0x55, 0xff,
+		0x55, 0xff, 0x55,
+		0x55, 0xff, 0xff,
+		0xff, 0x55, 0x55,
+		0xff, 0x55, 0xff,
+		0xff, 0xff, 0x55,
+		0xff, 0xff, 0xff
+	};
+	const unsigned char *clut;
+
+	prom_printf("Looking for displays\n");
+	for (node = 0; prom_next_node(&node); ) {
+		memset(type, 0, sizeof(type));
+		prom_getprop(node, "device_type", type, sizeof(type));
+		if (strcmp(type, RELOC("display")) != 0)
+			continue;
+
+		/* It seems OF doesn't null-terminate the path :-( */
+		path = RELOC(prom_scratch);
+		memset(path, 0, PROM_SCRATCH_SIZE);
+
+		/*
+		 * leave some room at the end of the path for appending extra
+		 * arguments
+		 */
+		if (call_prom("package-to-path", 3, 1, node, path, PROM_SCRATCH_SIZE-10) < 0)
+			continue;
+		prom_printf("found display   : %s, opening ... ", path);
+		
+		ih = call_prom("open", 1, 1, path);
+		if (ih == (ihandle)0 || ih == (ihandle)-1) {
+			prom_printf("failed\n");
+			continue;
+		}
+
+		/* Success */
+		prom_printf("done\n");
+		prom_setprop(node, "linux,opened", NULL, 0);
+
+		/*
+		 * stdout wasn't a display node, pick the first we can find
+		 * for btext
+		 */
+		if (_prom->disp_node == 0)
+			_prom->disp_node = node;
+
+		/* Setup a useable color table when the appropriate
+		 * method is available. Should update this to set-colors */
+		clut = RELOC(default_colors);
+		for (i = 0; i < 32; i++, clut += 3)
+			if (prom_set_color(ih, i, clut[0], clut[1],
+					   clut[2]) != 0)
+				break;
+
+#ifdef CONFIG_LOGO_LINUX_CLUT224
+		clut = PTRRELOC(RELOC(logo_linux_clut224.clut));
+		for (i = 0; i < RELOC(logo_linux_clut224.clutsize); i++, clut += 3)
+			if (prom_set_color(ih, i + 32, clut[0], clut[1],
+					   clut[2]) != 0)
+				break;
+#endif /* CONFIG_LOGO_LINUX_CLUT224 */
+	}
+}
+
+
+/* Return (relocated) pointer to this much memory: moves initrd if reqd. */
+static void __init *make_room(unsigned long *mem_start, unsigned long *mem_end,
+			      unsigned long needed, unsigned long align)
+{
+	unsigned long offset = reloc_offset();
+	void *ret;
+
+	*mem_start = _ALIGN(*mem_start, align);
+	while ((*mem_start + needed) > *mem_end) {
+		unsigned long room, chunk;
+
+		prom_debug("Chunk exhausted, claiming more at %x...\n",
+			   RELOC(alloc_bottom));
+		room = RELOC(alloc_top) - RELOC(alloc_bottom);
+		if (room > DEVTREE_CHUNK_SIZE)
+			room = DEVTREE_CHUNK_SIZE;
+		if (room < PAGE_SIZE)
+			prom_panic("No memory for flatten_device_tree (no room)");
+		chunk = alloc_up(room, 0);
+		if (chunk == 0)
+			prom_panic("No memory for flatten_device_tree (claim failed)");
+		*mem_end = RELOC(alloc_top);
+	}
+
+	ret = (void *)*mem_start;
+	*mem_start += needed;
+
+	return ret;
+}
+
+#define dt_push_token(token, mem_start, mem_end) \
+	do { *((u32 *)make_room(mem_start, mem_end, 4, 4)) = token; } while(0)
+
+static unsigned long __init dt_find_string(char *str)
+{
+	unsigned long offset = reloc_offset();
+	char *s, *os;
+
+	s = os = (char *)RELOC(dt_string_start);
+	s += 4;
+	while (s <  (char *)RELOC(dt_string_end)) {
+		if (strcmp(s, str) == 0)
+			return s - os;
+		s += strlen(s) + 1;
+	}
+	return 0;
+}
+
+static void __init scan_dt_build_strings(phandle node, unsigned long *mem_start,
+					 unsigned long *mem_end)
+{
+	unsigned long offset = reloc_offset();
+	char *prev_name, *namep, *sstart;
+	unsigned long soff;
+	phandle child;
+
+	sstart =  (char *)RELOC(dt_string_start);
+
+	/* get and store all property names */
+	prev_name = RELOC("");
+	for (;;) {
+		
+		/* 32 is max len of name including nul. */
+		namep = make_room(mem_start, mem_end, 32, 1);
+		if (call_prom("nextprop", 3, 1, node, prev_name, namep) <= 0) {
+			/* No more nodes: unwind alloc */
+			*mem_start = (unsigned long)namep;
+			break;
+		}
+		soff = dt_find_string(namep);
+		if (soff != 0) {
+			*mem_start = (unsigned long)namep;
+			namep = sstart + soff;
+		} else {
+			/* Trim off some if we can */
+			*mem_start = (unsigned long)namep + strlen(namep) + 1;
+			RELOC(dt_string_end) = *mem_start;
+		}
+		prev_name = namep;
+	}
+
+	/* do all our children */
+	child = call_prom("child", 1, 1, node);
+	while (child != (phandle)0) {
+		scan_dt_build_strings(child, mem_start, mem_end);
+		child = call_prom("peer", 1, 1, child);
+	}
+}
+
+static void __init scan_dt_build_struct(phandle node, unsigned long *mem_start,
+					unsigned long *mem_end)
+{
+	int l, align;
+	phandle child;
+	char *namep, *prev_name, *sstart;
+	unsigned long soff;
+	unsigned char *valp;
+	unsigned long offset = reloc_offset();
+	char pname[32];
+	char *path;
+
+	path = RELOC(prom_scratch);
+
+	dt_push_token(OF_DT_BEGIN_NODE, mem_start, mem_end);
+
+	/* get the node's full name */
+	namep = (char *)*mem_start;
+	l = call_prom("package-to-path", 3, 1, node,
+		      namep, *mem_end - *mem_start);
+	if (l >= 0) {
+		/* Didn't fit?  Get more room. */
+		if (l+1 > *mem_end - *mem_start) {
+			namep = make_room(mem_start, mem_end, l+1, 1);
+			call_prom("package-to-path", 3, 1, node, namep, l);
+		}
+		namep[l] = '\0';
+		*mem_start = _ALIGN(((unsigned long) namep) + strlen(namep) + 1, 4);
+	}
+
+	/* get it again for debugging */
+	memset(path, 0, PROM_SCRATCH_SIZE);
+	call_prom("package-to-path", 3, 1, node, path, PROM_SCRATCH_SIZE-1);
+
+	/* get and store all properties */
+	prev_name = RELOC("");
+	sstart = (char *)RELOC(dt_string_start);
+	for (;;) {
+		if (call_prom("nextprop", 3, 1, node, prev_name, pname) <= 0)
+			break;
+
+		/* find string offset */
+		soff = dt_find_string(pname);
+		if (soff == 0) {
+			prom_printf("WARNING: Can't find string index for <%s>, node %s\n",
+				    pname, path);
+			break;
+		}
+		prev_name = sstart + soff;
+
+		/* get length */
+		l = call_prom("getproplen", 2, 1, node, pname);
+
+		/* sanity checks */
+		if (l < 0)
+			continue;
+		if (l > MAX_PROPERTY_LENGTH) {
+			prom_printf("WARNING: ignoring large property ");
+			/* It seems OF doesn't null-terminate the path :-( */
+			prom_printf("[%s] ", path);
+			prom_printf("%s length 0x%x\n", pname, l);
+			continue;
+		}
+
+		/* push property head */
+		dt_push_token(OF_DT_PROP, mem_start, mem_end);
+		dt_push_token(l, mem_start, mem_end);
+		dt_push_token(soff, mem_start, mem_end);
+
+		/* push property content */
+		align = (l >= 8) ? 8 : 4;
+		valp = make_room(mem_start, mem_end, l, align);
+		call_prom("getprop", 4, 1, node, pname, valp, l);
+		*mem_start = _ALIGN(*mem_start, 4);
+	}
+
+	/* Add a "linux,phandle" property. */
+	soff = dt_find_string(RELOC("linux,phandle"));
+	if (soff == 0)
+		prom_printf("WARNING: Can't find string index for <linux-phandle>"
+			    " node %s\n", path);
+	else {
+		dt_push_token(OF_DT_PROP, mem_start, mem_end);
+		dt_push_token(4, mem_start, mem_end);
+		dt_push_token(soff, mem_start, mem_end);
+		valp = make_room(mem_start, mem_end, 4, 4);
+		*(u32 *)valp = node;
+	}
+
+	/* do all our children */
+	child = call_prom("child", 1, 1, node);
+	while (child != (phandle)0) {
+		scan_dt_build_struct(child, mem_start, mem_end);
+		child = call_prom("peer", 1, 1, child);
+	}
+
+	dt_push_token(OF_DT_END_NODE, mem_start, mem_end);
+}
+
+static void __init flatten_device_tree(void)
+{
+	phandle root;
+	unsigned long offset = reloc_offset();
+	unsigned long mem_start, mem_end, room;
+	struct boot_param_header *hdr;
+	char *namep;
+	u64 *rsvmap;
+
+	/*
+	 * Check how much room we have between alloc top & bottom (+/- a
+	 * few pages), crop to 4Mb, as this is our "chuck" size
+	 */
+	room = RELOC(alloc_top) - RELOC(alloc_bottom) - 0x4000;
+	if (room > DEVTREE_CHUNK_SIZE)
+		room = DEVTREE_CHUNK_SIZE;
+	prom_debug("starting device tree allocs at %x\n", RELOC(alloc_bottom));
+
+	/* Now try to claim that */
+	mem_start = (unsigned long)alloc_up(room, PAGE_SIZE);
+	if (mem_start == 0)
+		prom_panic("Can't allocate initial device-tree chunk\n");
+	mem_end = RELOC(alloc_top);
+
+	/* Get root of tree */
+	root = call_prom("peer", 1, 1, (phandle)0);
+	if (root == (phandle)0)
+		prom_panic ("couldn't get device tree root\n");
+
+	/* Build header and make room for mem rsv map */ 
+	mem_start = _ALIGN(mem_start, 4);
+	hdr = make_room(&mem_start, &mem_end, sizeof(struct boot_param_header), 4);
+	RELOC(dt_header_start) = (unsigned long)hdr;
+	rsvmap = make_room(&mem_start, &mem_end, sizeof(mem_reserve_map), 8);
+
+	/* Start of strings */
+	mem_start = PAGE_ALIGN(mem_start);
+	RELOC(dt_string_start) = mem_start;
+	mem_start += 4; /* hole */
+
+	/* Add "linux,phandle" in there, we'll need it */
+	namep = make_room(&mem_start, &mem_end, 16, 1);
+	strcpy(namep, RELOC("linux,phandle"));
+	mem_start = (unsigned long)namep + strlen(namep) + 1;
+	RELOC(dt_string_end) = mem_start;
+
+	/* Build string array */
+	prom_printf("Building dt strings...\n"); 
+	scan_dt_build_strings(root, &mem_start, &mem_end);
+
+	/* Build structure */
+	mem_start = PAGE_ALIGN(mem_start);
+	RELOC(dt_struct_start) = mem_start;
+	prom_printf("Building dt structure...\n"); 
+	scan_dt_build_struct(root, &mem_start, &mem_end);
+	dt_push_token(OF_DT_END, &mem_start, &mem_end);
+	RELOC(dt_struct_end) = PAGE_ALIGN(mem_start);
+
+	/* Finish header */
+	hdr->magic = OF_DT_HEADER;
+	hdr->totalsize = RELOC(dt_struct_end) - RELOC(dt_header_start);
+	hdr->off_dt_struct = RELOC(dt_struct_start) - RELOC(dt_header_start);
+	hdr->off_dt_strings = RELOC(dt_string_start) - RELOC(dt_header_start);
+	hdr->off_mem_rsvmap = ((unsigned long)rsvmap) - RELOC(dt_header_start);
+	hdr->version = OF_DT_VERSION;
+	hdr->last_comp_version = 1;
+
+	/* Reserve the whole thing and copy the reserve map in, we
+	 * also bump mem_reserve_cnt to cause further reservations to
+	 * fail since it's too late.
+	 */
+	reserve_mem(RELOC(dt_header_start), hdr->totalsize);
+	memcpy(rsvmap, RELOC(mem_reserve_map), sizeof(mem_reserve_map));
+
+#ifdef DEBUG_PROM
+	{
+		int i;
+		prom_printf("reserved memory map:\n");
+		for (i = 0; i < RELOC(mem_reserve_cnt); i++)
+			prom_printf("  %x - %x\n", RELOC(mem_reserve_map)[i].base,
+				    RELOC(mem_reserve_map)[i].size);
+	}
+#endif
+	RELOC(mem_reserve_cnt) = MEM_RESERVE_MAP_SIZE;
+
+	prom_printf("Device tree strings 0x%x -> 0x%x\n",
+		    RELOC(dt_string_start), RELOC(dt_string_end)); 
+	prom_printf("Device tree struct  0x%x -> 0x%x\n",
+		    RELOC(dt_struct_start), RELOC(dt_struct_end));
+
+ }
+
+static void __init prom_find_boot_cpu(void)
+{
+	unsigned long offset = reloc_offset();
+       	struct prom_t *_prom = PTRRELOC(&prom);
+	u32 getprop_rval;
+	ihandle prom_cpu;
+	phandle cpu_pkg;
+
+	if (prom_getprop(_prom->chosen, "cpu", &prom_cpu, sizeof(prom_cpu)) <= 0)
+		prom_panic("cannot find boot cpu");
+
+	cpu_pkg = call_prom("instance-to-package", 1, 1, prom_cpu);
+
+	prom_setprop(cpu_pkg, "linux,boot-cpu", NULL, 0);
+	prom_getprop(cpu_pkg, "reg", &getprop_rval, sizeof(getprop_rval));
+	_prom->cpu = getprop_rval;
+
+	prom_debug("Booting CPU hw index = 0x%x\n", _prom->cpu);
+}
+
+static void __init prom_check_initrd(unsigned long r3, unsigned long r4)
+{
+#ifdef CONFIG_BLK_DEV_INITRD
+	unsigned long offset = reloc_offset();
+       	struct prom_t *_prom = PTRRELOC(&prom);
+
+	if ( r3 && r4 && r4 != 0xdeadbeef) {
+		u64 val;
+
+		RELOC(prom_initrd_start) = (r3 >= KERNELBASE) ? __pa(r3) : r3;
+		RELOC(prom_initrd_end) = RELOC(prom_initrd_start) + r4;
+
+		val = (u64)RELOC(prom_initrd_start);
+		prom_setprop(_prom->chosen, "linux,initrd-start", &val, sizeof(val));
+		val = (u64)RELOC(prom_initrd_end);
+		prom_setprop(_prom->chosen, "linux,initrd-end", &val, sizeof(val));
+
+		reserve_mem(RELOC(prom_initrd_start),
+			    RELOC(prom_initrd_end) - RELOC(prom_initrd_start));
+
+		prom_debug("initrd_start=0x%x\n", RELOC(prom_initrd_start));
+		prom_debug("initrd_end=0x%x\n", RELOC(prom_initrd_end));
+	}
+#endif /* CONFIG_BLK_DEV_INITRD */
+}
+
+/*
+ * We enter here early on, when the Open Firmware prom is still
+ * handling exceptions and the MMU hash table for us.
+ */
+
+unsigned long __init prom_init(unsigned long r3, unsigned long r4, unsigned long pp,
+			       unsigned long r6, unsigned long r7)
+{	
+	unsigned long offset = reloc_offset();
+       	struct prom_t *_prom = PTRRELOC(&prom);
+	unsigned long phys = KERNELBASE - offset;
+	u32 getprop_rval;
+	
+	/*
+	 * First zero the BSS
+	 */
+	memset(PTRRELOC(&__bss_start), 0, __bss_stop - __bss_start);
+
+	/*
+	 * Init interface to Open Firmware, get some node references,
+	 * like /chosen
+	 */
+	prom_init_client_services(pp);
+
+	/*
+	 * Init prom stdout device
+	 */
+	prom_init_stdout();
+	prom_debug("klimit=0x%x\n", RELOC(klimit));
+	prom_debug("offset=0x%x\n", offset);
+
+	/*
+	 * Reserve kernel in reserve map
+	 */
+	reserve_mem(0, __pa(RELOC(klimit)));
+
+	/*
+	 * Check for an initrd
+	 */
+	prom_check_initrd(r3, r4);
+
+	/*
+	 * Get default machine type. At this point, we do not differenciate
+	 * between pSeries SMP and pSeries LPAR
+	 */
+	RELOC(of_platform) = prom_find_machine_type();
+	getprop_rval = RELOC(of_platform);
+	prom_setprop(_prom->chosen, "linux,platform",
+		     &getprop_rval, sizeof(getprop_rval));
+
+	/*
+	 * On pSeries, copy the CPU hold code
+	 */
+       	if (RELOC(of_platform) & PLATFORM_PSERIES)
+       		copy_and_flush(0, KERNELBASE - offset, 0x100, 0);
+
+	/*
+	 * Get memory cells format
+	 */
+	getprop_rval = 1;
+	prom_getprop(_prom->root, "#size-cells",
+		     &getprop_rval, sizeof(getprop_rval));
+	_prom->root_size_cells = getprop_rval;
+	getprop_rval = 2;
+	prom_getprop(_prom->root, "#address-cells",
+		     &getprop_rval, sizeof(getprop_rval));
+	_prom->root_addr_cells = getprop_rval;
+
+	/*
+	 * Do early parsing of command line
+	 */
+	early_cmdline_parse();
+
+	/*
+	 * Initialize memory management within prom_init
+	 */
+	prom_init_mem();
+
+	/*
+	 * Determine which cpu is actually running right _now_
+	 */
+	prom_find_boot_cpu();
+
+	/* 
+	 * Initialize display devices
+	 */
+	prom_check_displays();
+
+	/*
+	 * Initialize IOMMU (TCE tables) on pSeries. Do that before anything else
+	 * that uses the allocator, we need to make sure we get the top of memory
+	 * available for us here...
+	 */
+	if (RELOC(of_platform) == PLATFORM_PSERIES)
+		prom_initialize_tce_table();
+
+	/*
+	 * On non-powermacs, try to instantiate RTAS and puts all CPUs
+	 * in spin-loops. PowerMacs don't have a working RTAS and use
+	 * a different way to spin CPUs
+	 */
+	if (RELOC(of_platform) != PLATFORM_POWERMAC) {
+		prom_instantiate_rtas();
+		prom_hold_cpus();
+	}
+
+	/*
+	 * Fill in some infos for use by the kernel later on
+	 */
+	if (RELOC(ppc64_iommu_off))
+		prom_setprop(_prom->chosen, "linux,iommu-off", NULL, 0);
+	if (RELOC(iommu_force_on))
+		prom_setprop(_prom->chosen, "linux,iommu-force-on", NULL, 0);
+
+	/*
+	 * Now finally create the flattened device-tree
+	 */
+       	prom_printf("copying OF device tree ...\n");
+       	flatten_device_tree();
+
+	/*
+	 * Call OF "quiesce" method to shut down pending DMA's from
+	 * devices etc...
+	 */
+	prom_printf("Calling quiesce ...\n");
+	call_prom("quiesce", 0, 0);
+
+	/*
+	 * And finally, call the kernel passing it the flattened device
+	 * tree and NULL as r5, thus triggering the new entry point which
+	 * is common to us and kexec
+	 */
+	prom_printf("returning from prom_init\n");
+	prom_debug("->dt_header_start=0x%x\n", RELOC(dt_header_start));
+	prom_debug("->phys=0x%x\n", phys);
+
+	__start(RELOC(dt_header_start), phys, 0);
+
+	return 0;
+}
+
diff -Nru a/arch/ppc64/kernel/ras.c b/arch/ppc64/kernel/ras.c
--- a/arch/ppc64/kernel/ras.c	2004-10-18 14:56:27 -07:00
+++ b/arch/ppc64/kernel/ras.c	2004-10-18 14:56:28 -07:00
@@ -161,7 +161,8 @@
 			   RAS_VECTOR_OFFSET,
 			   virt_irq_to_real(irq_offset_down(irq)),
 			   RTAS_EPOW_WARNING | RTAS_POWERMGM_EVENTS,
-			   critical, __pa(&ras_log_buf), RTAS_ERROR_LOG_MAX);
+			   critical, __pa(&ras_log_buf),
+				rtas_get_error_log_max());
 
 	udbg_printf("EPOW <0x%lx 0x%x 0x%x>\n",
 		    *((unsigned long *)&ras_log_buf), status, state);
@@ -196,11 +197,12 @@
 			   RAS_VECTOR_OFFSET,
 			   virt_irq_to_real(irq_offset_down(irq)),
 			   RTAS_INTERNAL_ERROR, 1 /*Time Critical */,
-			   __pa(&ras_log_buf), RTAS_ERROR_LOG_MAX);
+			   __pa(&ras_log_buf),
+				rtas_get_error_log_max());
 
 	rtas_elog = (struct rtas_error_log *)ras_log_buf;
 
-	if ((status == 0) && (rtas_elog->severity >= SEVERITY_ERROR_SYNC))
+	if ((status == 0) && (rtas_elog->severity >= RTAS_SEVERITY_ERROR_SYNC))
 		fatal = 1;
 	else
 		fatal = 0;
diff -Nru a/arch/ppc64/kernel/rtas-proc.c b/arch/ppc64/kernel/rtas-proc.c
--- a/arch/ppc64/kernel/rtas-proc.c	2004-10-18 14:56:29 -07:00
+++ b/arch/ppc64/kernel/rtas-proc.c	2004-10-18 14:56:29 -07:00
@@ -580,7 +580,7 @@
 			}
 			break;
 		case THERMAL_SENSOR:
-			seq_printf(m, "Temp. (°C/°F):\t");
+			seq_printf(m, "Temp. (C/F):\t");
 			temperature = 1;
 			break;
 		case LID_STATUS:
diff -Nru a/arch/ppc64/kernel/rtas.c b/arch/ppc64/kernel/rtas.c
--- a/arch/ppc64/kernel/rtas.c	2004-10-18 14:55:55 -07:00
+++ b/arch/ppc64/kernel/rtas.c	2004-10-18 14:55:55 -07:00
@@ -22,7 +22,6 @@
 #include <asm/rtas.h>
 #include <asm/semaphore.h>
 #include <asm/machdep.h>
-#include <asm/paca.h>
 #include <asm/page.h>
 #include <asm/param.h>
 #include <asm/system.h>
@@ -37,17 +36,22 @@
 	.lock = SPIN_LOCK_UNLOCKED
 };
 
+EXPORT_SYMBOL(rtas);
+
 char rtas_err_buf[RTAS_ERROR_LOG_MAX];
 
 spinlock_t rtas_data_buf_lock = SPIN_LOCK_UNLOCKED;
 char rtas_data_buf[RTAS_DATA_BUF_SIZE]__page_aligned;
+unsigned long rtas_rmo_buf;
 
 void
-call_rtas_display_status(char c)
+call_rtas_display_status(unsigned char c)
 {
 	struct rtas_args *args = &rtas.args;
 	unsigned long s;
 
+	if (!rtas.base)
+		return;
 	spin_lock_irqsave(&rtas.lock, s);
 
 	args->token = 10;
@@ -61,6 +65,31 @@
 	spin_unlock_irqrestore(&rtas.lock, s);
 }
 
+void
+call_rtas_display_status_delay(unsigned char c)
+{
+	static int pending_newline = 0;  /* did last write end with unprinted newline? */
+	static int width = 16;
+
+	if (c == '\n') {	
+		while (width-- > 0)
+			call_rtas_display_status(' ');
+		width = 16;
+		udelay(500000);
+		pending_newline = 1;
+	} else {
+		if (pending_newline) {
+			call_rtas_display_status('\r');
+			call_rtas_display_status('\n');
+		} 
+		pending_newline = 0;
+		if (width--) {
+			call_rtas_display_status(c);
+			udelay(10000);
+		}
+	}
+}
+
 int
 rtas_token(const char *service)
 {
@@ -73,7 +102,6 @@
 	return tokp ? *tokp : RTAS_UNKNOWN_SERVICE;
 }
 
-
 /** Return a copy of the detailed error text associated with the
  *  most recent failed call to rtas.  Because the error text
  *  might go stale if there are any other intervening rtas calls,
@@ -84,28 +112,32 @@
 __fetch_rtas_last_error(void)
 {
 	struct rtas_args err_args, save_args;
+	u32 bufsz;
+
+	bufsz = rtas_token ("rtas-error-log-max");
+	if ((bufsz == RTAS_UNKNOWN_SERVICE) ||
+	    (bufsz > RTAS_ERROR_LOG_MAX)) {
+		printk (KERN_WARNING "RTAS: bad log buffer size %d\n", bufsz);
+		bufsz = RTAS_ERROR_LOG_MAX;
+	}
 
 	err_args.token = rtas_token("rtas-last-error");
 	err_args.nargs = 2;
 	err_args.nret = 1;
-	err_args.rets = (rtas_arg_t *)&(err_args.args[2]);
 
 	err_args.args[0] = (rtas_arg_t)__pa(rtas_err_buf);
-	err_args.args[1] = RTAS_ERROR_LOG_MAX;
+	err_args.args[1] = bufsz;
 	err_args.args[2] = 0;
 
 	save_args = rtas.args;
 	rtas.args = err_args;
 
-	PPCDBG(PPCDBG_RTAS, "\tentering rtas with 0x%lx\n",
-	       __pa(&err_args));
 	enter_rtas(__pa(&rtas.args));
-	PPCDBG(PPCDBG_RTAS, "\treturned from rtas ...\n");
 
 	err_args = rtas.args;
 	rtas.args = save_args;
 
-	return err_args.rets[0];
+	return err_args.args[2];
 }
 
 int rtas_call(int token, int nargs, int nret, int *outputs, ...)
@@ -165,9 +197,12 @@
 
 	/* Log the error in the unlikely case that there was one. */
 	if (unlikely(logit)) {
-		buff_copy = kmalloc(RTAS_ERROR_LOG_MAX, GFP_ATOMIC);
-		if (buff_copy) {
-			memcpy(buff_copy, rtas_err_buf, RTAS_ERROR_LOG_MAX);
+		buff_copy = rtas_err_buf;
+		if (mem_init_done) {
+			buff_copy = kmalloc(RTAS_ERROR_LOG_MAX, GFP_ATOMIC);
+			if (buff_copy)
+				memcpy(buff_copy, rtas_err_buf,
+				       RTAS_ERROR_LOG_MAX);
 		}
 	}
 
@@ -176,7 +211,8 @@
 
 	if (buff_copy) {
 		log_error(buff_copy, ERR_TYPE_RTAS_LOG, 0);
-		kfree(buff_copy);
+		if (mem_init_done)
+			kfree(buff_copy);
 	}
 	return ret;
 }
@@ -417,7 +453,6 @@
 	} while (status == RTAS_BUSY);
 }
 
-unsigned long rtas_rmo_buf = 0;
 
 asmlinkage int ppc_rtas(struct rtas_args __user *uargs)
 {
@@ -508,6 +543,73 @@
 }
 #endif /* CONFIG_HOTPLUG_CPU */
 
+/*
+ * Return the firmware-specified size of the error log buffer
+ *  for all rtas calls that require an error buffer argument.
+ *  This includes 'check-exception' and 'rtas-last-error'.
+ */
+int rtas_get_error_log_max(void)
+{
+	static int rtas_error_log_max;
+	if (rtas_error_log_max)
+		return rtas_error_log_max;
+
+	rtas_error_log_max = rtas_token ("rtas-error-log-max");
+	if ((rtas_error_log_max == RTAS_UNKNOWN_SERVICE) ||
+	    (rtas_error_log_max > RTAS_ERROR_LOG_MAX)) {
+		printk (KERN_WARNING "RTAS: bad log buffer size %d\n", rtas_error_log_max);
+		rtas_error_log_max = RTAS_ERROR_LOG_MAX;
+	}
+	return rtas_error_log_max;
+}
+
+/*
+ * Call early during boot, before mem init or bootmem, to retreive the RTAS
+ * informations from the device-tree and allocate the RMO buffer for userland
+ * accesses.
+ */
+void __init rtas_initialize(void)
+{
+	/* Get RTAS dev node and fill up our "rtas" structure with infos
+	 * about it.
+	 */
+	rtas.dev = of_find_node_by_name(NULL, "rtas");
+	if (rtas.dev) {
+		u64 *basep, *entryp;
+		u32 *sizep;
+
+		basep = (u64 *)get_property(of_chosen, "linux,rtas-base", NULL);
+		sizep = (u32 *)get_property(of_chosen, "linux,rtas-size", NULL);
+		if (basep != NULL && sizep != NULL) {
+			rtas.base = *basep;
+			rtas.size = *sizep;
+			entryp = (u64 *)get_property(of_chosen, "linux,rtas-entry", NULL);
+			if (entryp == NULL) /* Ugh */
+				rtas.entry = rtas.base;
+			else
+				rtas.entry = *entryp;
+		} else
+			rtas.dev = NULL;
+	}
+	/* If RTAS was found, allocate the RMO buffer for it and look for
+	 * the stop-self token if any
+	 */
+	if (rtas.dev) {
+		unsigned long rtas_region = RTAS_INSTANTIATE_MAX;
+		if (systemcfg->platform == PLATFORM_PSERIES_LPAR)
+			rtas_region = min(lmb.rmo_size, RTAS_INSTANTIATE_MAX);
+
+		rtas_rmo_buf = lmb_alloc_base(RTAS_RMOBUF_MAX, PAGE_SIZE,
+							rtas_region);
+
+#ifdef CONFIG_HOTPLUG_CPU
+		rtas_stop_self_args.token = rtas_token("stop-self");
+#endif /* CONFIG_HOTPLUG_CPU */
+	}
+
+}
+
+
 EXPORT_SYMBOL(rtas_firmware_flash_list);
 EXPORT_SYMBOL(rtas_token);
 EXPORT_SYMBOL(rtas_call);
@@ -518,3 +620,4 @@
 EXPORT_SYMBOL(rtas_get_power_level);
 EXPORT_SYMBOL(rtas_set_power_level);
 EXPORT_SYMBOL(rtas_set_indicator);
+EXPORT_SYMBOL(rtas_get_error_log_max);
diff -Nru a/arch/ppc64/kernel/rtasd.c b/arch/ppc64/kernel/rtasd.c
--- a/arch/ppc64/kernel/rtasd.c	2004-10-18 14:56:28 -07:00
+++ b/arch/ppc64/kernel/rtasd.c	2004-10-18 14:56:28 -07:00
@@ -46,6 +46,8 @@
 static unsigned int rtas_error_log_max;
 static unsigned int rtas_error_log_buffer_max;
 
+static int full_rtas_msgs = 0;
+
 extern volatile int no_more_logging;
 
 volatile int error_log_cnt = 0;
@@ -57,6 +59,37 @@
  */
 static unsigned char logdata[RTAS_ERROR_LOG_MAX];
 
+static int get_eventscan_parms(void);
+
+static char *rtas_type[] = {
+	"Unknown", "Retry", "TCE Error", "Internal Device Failure",
+	"Timeout", "Data Parity", "Address Parity", "Cache Parity",
+	"Address Invalid", "ECC Uncorrected", "ECC Corrupted",
+};
+
+static char *rtas_event_type(int type)
+{
+	if ((type > 0) && (type < 11))
+		return rtas_type[type];
+
+	switch (type) {
+		case RTAS_TYPE_EPOW:
+			return "EPOW";
+		case RTAS_TYPE_PLATFORM:
+			return "Platform Error";
+		case RTAS_TYPE_IO:
+			return "I/O Event";
+		case RTAS_TYPE_INFO:
+			return "Platform Information Event";
+		case RTAS_TYPE_DEALLOC:
+			return "Resource Deallocation Event";
+		case RTAS_TYPE_DUMP:
+			return "Dump Notification Event";
+	}
+
+	return rtas_type[0];
+}
+
 /* To see this info, grep RTAS /var/log/messages and each entry
  * will be collected together with obvious begin/end.
  * There will be a unique identifier on the begin and end lines.
@@ -73,38 +106,48 @@
 static void printk_log_rtas(char *buf, int len)
 {
 
-	int i,j,n;
+	int i,j,n = 0;
 	int perline = 16;
 	char buffer[64];
 	char * str = "RTAS event";
 
-	printk(RTAS_DEBUG "%d -------- %s begin --------\n", error_log_cnt, str);
+	if (full_rtas_msgs) {
+		printk(RTAS_DEBUG "%d -------- %s begin --------\n",
+		       error_log_cnt, str);
+
+		/*
+		 * Print perline bytes on each line, each line will start
+		 * with RTAS and a changing number, so syslogd will
+		 * print lines that are otherwise the same.  Separate every
+		 * 4 bytes with a space.
+		 */
+		for (i = 0; i < len; i++) {
+			j = i % perline;
+			if (j == 0) {
+				memset(buffer, 0, sizeof(buffer));
+				n = sprintf(buffer, "RTAS %d:", i/perline);
+			}
 
-	/*
-	 * Print perline bytes on each line, each line will start
-	 * with RTAS and a changing number, so syslogd will
-	 * print lines that are otherwise the same.  Separate every
-	 * 4 bytes with a space.
-	 */
-	for (i=0; i < len; i++) {
-		j = i % perline;
-		if (j == 0) {
-			memset(buffer, 0, sizeof(buffer));
-			n = sprintf(buffer, "RTAS %d:", i/perline);
-		}
+			if ((i % 4) == 0)
+				n += sprintf(buffer+n, " ");
 
-		if ((i % 4) == 0)
-			n += sprintf(buffer+n, " ");
+			n += sprintf(buffer+n, "%02x", (unsigned char)buf[i]);
 
-		n += sprintf(buffer+n, "%02x", (unsigned char)buf[i]);
-
-		if (j == (perline-1))
+			if (j == (perline-1))
+				printk(KERN_DEBUG "%s\n", buffer);
+		}
+		if ((i % perline) != 0)
 			printk(KERN_DEBUG "%s\n", buffer);
-	}
-	if ((i % perline) != 0)
-		printk(KERN_DEBUG "%s\n", buffer);
 
-	printk(RTAS_DEBUG "%d -------- %s end ----------\n", error_log_cnt, str);
+		printk(RTAS_DEBUG "%d -------- %s end ----------\n",
+		       error_log_cnt, str);
+	} else {
+		struct rtas_error_log *errlog = (struct rtas_error_log *)buf;
+
+		printk(RTAS_DEBUG "event: %d, Type: %s, Severity: %d\n",
+		       error_log_cnt, rtas_event_type(errlog->type),
+		       errlog->severity);
+	}
 }
 
 static int log_rtas_len(char * buf)
@@ -121,6 +164,9 @@
 		len += err->extended_log_length;
 	}
 
+	if (rtas_error_log_max == 0) {
+		get_eventscan_parms();
+	}
 	if (len > rtas_error_log_max)
 		len = rtas_error_log_max;
 
@@ -148,7 +194,6 @@
 	int len = 0;
 
 	DEBUG("logging event\n");
-
 	if (buf == NULL)
 		return;
 
@@ -171,6 +216,14 @@
 	if (!no_more_logging && !(err_type & ERR_FLAG_BOOT))
 		nvram_write_error_log(buf, len, err_type);
 
+	/*
+	 * rtas errors can occur during boot, and we do want to capture
+	 * those somewhere, even if nvram isn't ready (why not?), and even
+	 * if rtasd isn't ready. Put them into the boot log, at least.
+	 */
+	if ((err_type & ERR_TYPE_MASK) == ERR_TYPE_RTAS_LOG)
+		printk_log_rtas(buf, len);
+
 	/* Check to see if we need to or have stopped logging */
 	if (fatal || no_more_logging) {
 		no_more_logging = 1;
@@ -181,9 +234,6 @@
 	/* call type specific method for error */
 	switch (err_type & ERR_TYPE_MASK) {
 	case ERR_TYPE_RTAS_LOG:
-		/* put into syslog and error_log file */
-		printk_log_rtas(buf, len);
-
 		offset = rtas_error_log_buffer_max *
 			((rtas_log_start+rtas_log_size) & LOG_NUMBER_MASK);
 
@@ -291,15 +341,18 @@
 {
 	int error;
 
-	error = rtas_call(rtas_token("set-indicator"), 3, 1, NULL,
-			  SURVEILLANCE_TOKEN, 0, timeout);
+	error = rtas_set_indicator(SURVEILLANCE_TOKEN, 0, timeout);
 
-	if (error) {
-		printk(KERN_ERR "rtasd: could not enable surveillance\n");
-		return -1;
+	if (error == 0)
+		return 0;
+
+	if (error == RTAS_NO_SUCH_INDICATOR) {
+		printk(KERN_INFO "rtasd: surveillance not supported\n");
+		return 0;
 	}
 
-	return 0;
+	printk(KERN_ERR "rtasd: could not update surveillance\n");
+	return -1;
 }
 
 static int get_eventscan_parms(void)
@@ -318,21 +371,8 @@
 	rtas_event_scan_rate = *ip;
 	DEBUG("rtas-event-scan-rate %d\n", rtas_event_scan_rate);
 
-	ip = (int *)get_property(node, "rtas-error-log-max", NULL);
-	if (ip == NULL) {
-		printk(KERN_ERR "rtasd: no rtas-error-log-max\n");
-		of_node_put(node);
-		return -1;
-	}
-	rtas_error_log_max = *ip;
-	DEBUG("rtas-error-log-max %d\n", rtas_error_log_max);
-
-	if (rtas_error_log_max > RTAS_ERROR_LOG_MAX) {
-		printk(KERN_ERR "rtasd: truncated error log from %d to %d bytes\n", rtas_error_log_max, RTAS_ERROR_LOG_MAX);
-		rtas_error_log_max = RTAS_ERROR_LOG_MAX;
-	}
-
 	/* Make room for the sequence number */
+	rtas_error_log_max = rtas_get_error_log_max();
 	rtas_error_log_buffer_max = rtas_error_log_max + sizeof(int);
 
 	of_node_put(node);
@@ -473,5 +513,15 @@
 	return 1;
 }
 
+static int __init rtasmsgs_setup(char *str)
+{
+	if (strcmp(str, "on") == 0)
+		full_rtas_msgs = 1;
+	else if (strcmp(str, "off") == 0)
+		full_rtas_msgs = 0;
+
+	return 1;
+}
 __initcall(rtas_init);
 __setup("surveillance=", surveillance_setup);
+__setup("rtasmsgs=", rtasmsgs_setup);
diff -Nru a/arch/ppc64/kernel/rtc.c b/arch/ppc64/kernel/rtc.c
--- a/arch/ppc64/kernel/rtc.c	2004-10-18 14:56:32 -07:00
+++ b/arch/ppc64/kernel/rtc.c	2004-10-18 14:56:32 -07:00
@@ -34,8 +34,8 @@
 #include <linux/proc_fs.h>
 #include <linux/spinlock.h>
 #include <linux/bcd.h>
+#include <linux/interrupt.h>
 
-#include <asm/hardirq.h>
 #include <asm/io.h>
 #include <asm/uaccess.h>
 #include <asm/system.h>
diff -Nru a/arch/ppc64/kernel/setup.c b/arch/ppc64/kernel/setup.c
--- a/arch/ppc64/kernel/setup.c	2004-10-18 14:56:29 -07:00
+++ b/arch/ppc64/kernel/setup.c	2004-10-18 14:56:29 -07:00
@@ -10,6 +10,8 @@
  *      2 of the License, or (at your option) any later version.
  */
 
+#undef DEBUG
+
 #include <linux/config.h>
 #include <linux/module.h>
 #include <linux/string.h>
@@ -27,6 +29,7 @@
 #include <linux/root_dev.h>
 #include <linux/notifier.h>
 #include <linux/cpu.h>
+#include <linux/unistd.h>
 #include <asm/io.h>
 #include <asm/prom.h>
 #include <asm/processor.h>
@@ -47,60 +50,79 @@
 #include <asm/setup.h>
 #include <asm/system.h>
 #include <asm/rtas.h>
+#include <asm/iommu.h>
+
+#ifdef DEBUG
+#define DBG(fmt...) udbg_printf(fmt)
+#else
+#define DBG(fmt...)
+#endif
+
+/*
+ * Here are some early debugging facilities. You can enable one
+ * but your kernel will not boot on anything else if you do so
+ */
+
+/* This one is for use on LPAR machines that support an HVC console
+ * on vterm 0
+ */
+extern void udbg_init_debug_lpar(void);
+/* This one is for use on Apple G5 machines
+ */
+extern void udbg_init_pmac_realmode(void);
+/* That's RTAS panel debug */
+extern void call_rtas_display_status_delay(unsigned char c);
+
+#define EARLY_DEBUG_INIT() do {} while(0)
+
+#if 0
+#define EARLY_DEBUG_INIT() udbg_init_debug_lpar()
+#define EARLY_DEBUG_INIT() udbg_init_pmac_realmode()
+#define EARLY_DEBUG_INIT()						\
+	do { ppc_md.udbg_putc = call_rtas_display_status_delay; } while(0)
+#endif
 
-extern unsigned long klimit;
 /* extern void *stab; */
 extern HTAB htab_data;
-extern unsigned long loops_per_jiffy;
-
-int have_of = 1;
+extern unsigned long klimit;
 
-extern void  chrp_init(unsigned long r3,
-		       unsigned long r4,
-		       unsigned long r5,
-		       unsigned long r6,
-		       unsigned long r7);
-
-extern void  pmac_init(unsigned long r3,
-		       unsigned long r4,
-		       unsigned long r5,
-		       unsigned long r6,
-		       unsigned long r7);
-
-extern void iSeries_init( void );
-extern void iSeries_init_early( void );
-extern void pSeries_init_early( void );
-extern void pSeriesLP_init_early(void);
-extern void pmac_init_early(void);
-extern void mm_init_ppc64( void ); 
-extern void pseries_secondary_smp_init(unsigned long); 
+extern void mm_init_ppc64(void);
 extern int  idle_setup(void);
-extern void vpa_init(int cpu);
+extern void stab_initialize(unsigned long stab);
+extern void htab_initialize(void);
+extern void early_init_devtree(void *flat_dt);
+extern void unflatten_device_tree(void);
 
 unsigned long decr_overclock = 1;
 unsigned long decr_overclock_proc0 = 1;
 unsigned long decr_overclock_set = 0;
 unsigned long decr_overclock_proc0_set = 0;
 
-int powersave_nap;
+int have_of = 1;
+int boot_cpuid = 0;
+dev_t boot_dev;
 
-unsigned char aux_device_present;
+/*
+ * These are used in binfmt_elf.c to put aux entries on the stack
+ * for each elf executable being started.
+ */
+int dcache_bsize;
+int icache_bsize;
+int ucache_bsize;
 
-void parse_cmd_line(unsigned long r3, unsigned long r4, unsigned long r5,
-		    unsigned long r6, unsigned long r7);
-int parse_bootinfo(void);
+/* The main machine-dep calls structure
+ */
+struct machdep_calls ppc_md;
 
 #ifdef CONFIG_MAGIC_SYSRQ
 unsigned long SYSRQ_KEY;
 #endif /* CONFIG_MAGIC_SYSRQ */
 
-struct machdep_calls ppc_md;
 
 static int ppc64_panic_event(struct notifier_block *, unsigned long, void *);
-
 static struct notifier_block ppc64_panic_block = {
-	notifier_call: ppc64_panic_event,
-	priority: INT_MIN /* may not return; must be done last */
+	.notifier_call = ppc64_panic_event,
+	.priority = INT_MIN /* may not return; must be done last */
 };
 
 /*
@@ -112,42 +134,32 @@
  * these processors use on existing boards.  -- Dan
  */ 
 struct screen_info screen_info = {
-	0, 25,			/* orig-x, orig-y */
-	0,			/* unused */
-	0,			/* orig-video-page */
-	0,			/* orig-video-mode */
-	80,			/* orig-video-cols */
-	0,0,0,			/* ega_ax, ega_bx, ega_cx */
-	25,			/* orig-video-lines */
-	1,			/* orig-video-isVGA */
-	16			/* orig-video-points */
+	.orig_x = 0,
+	.orig_y = 25,
+	.orig_video_cols = 80,
+	.orig_video_lines = 25,
+	.orig_video_isVGA = 1,
+	.orig_video_points = 16
 };
 
 /*
- * These are used in binfmt_elf.c to put aux entries on the stack
- * for each elf executable being started.
- */
-int dcache_bsize;
-int icache_bsize;
-int ucache_bsize;
-
-/*
  * Initialize the PPCDBG state.  Called before relocation has been enabled.
  */
-void ppcdbg_initialize(void) {
-	unsigned long offset = reloc_offset();
-	struct naca_struct *_naca = RELOC(naca);
-
-	_naca->debug_switch = PPC_DEBUG_DEFAULT; /* | PPCDBG_BUSWALK | PPCDBG_PHBINIT | PPCDBG_MM | PPCDBG_MMINIT | PPCDBG_TCEINIT | PPCDBG_TCE */;
+void __init ppcdbg_initialize(void)
+{
+	naca->debug_switch = PPC_DEBUG_DEFAULT; /* | PPCDBG_BUSWALK | */
+	/* PPCDBG_PHBINIT | PPCDBG_MM | PPCDBG_MMINIT | PPCDBG_TCEINIT | PPCDBG_TCE */;
 }
 
+/*
+ * Early boot console based on udbg
+ */
 static struct console udbg_console = {
 	.name	= "udbg",
 	.write	= udbg_console_write,
 	.flags	= CON_PRINTBUFFER,
 	.index	= -1,
 };
-
 static int early_console_initialized;
 
 void __init disable_early_printk(void)
@@ -158,111 +170,457 @@
 	early_console_initialized = 0;
 }
 
-/*
- * Do some initial setup of the system.  The parameters are those which 
- * were passed in from the bootloader.
+#if defined(CONFIG_PPC_MULTIPLATFORM) && defined(CONFIG_SMP)
+
+static int smt_enabled_cmdline;
+
+/* Look for ibm,smt-enabled OF option */
+static void check_smt_enabled(void)
+{
+	struct device_node *dn;
+	char *smt_option;
+
+	/* Allow the command line to overrule the OF option */
+	if (smt_enabled_cmdline)
+		return;
+
+	dn = of_find_node_by_path("/options");
+
+	if (dn) {
+		smt_option = (char *)get_property(dn, "ibm,smt-enabled", NULL);
+
+                if (smt_option) {
+			if (!strcmp(smt_option, "on"))
+				smt_enabled_at_boot = 1;
+			else if (!strcmp(smt_option, "off"))
+				smt_enabled_at_boot = 0;
+                }
+        }
+}
+
+/* Look for smt-enabled= cmdline option */
+static int __init early_smt_enabled(char *p)
+{
+	smt_enabled_cmdline = 1;
+
+	if (!p)
+		return 0;
+
+	if (!strcmp(p, "on") || !strcmp(p, "1"))
+		smt_enabled_at_boot = 1;
+	else if (!strcmp(p, "off") || !strcmp(p, "0"))
+		smt_enabled_at_boot = 0;
+
+	return 0;
+}
+early_param("smt-enabled", early_smt_enabled);
+
+/**
+ * setup_cpu_maps - initialize the following cpu maps:
+ *                  cpu_possible_map
+ *                  cpu_present_map
+ *                  cpu_sibling_map
+ *
+ * Having the possible map set up early allows us to restrict allocations
+ * of things like irqstacks to num_possible_cpus() rather than NR_CPUS.
+ *
+ * We do not initialize the online map here; cpus set their own bits in
+ * cpu_online_map as they come up.
+ *
+ * This function is valid only for Open Firmware systems.  finish_device_tree
+ * must be called before using this.
+ *
+ * While we're here, we may as well set the "physical" cpu ids in the paca.
  */
-void setup_system(unsigned long r3, unsigned long r4, unsigned long r5,
-		  unsigned long r6, unsigned long r7)
+static void __init setup_cpu_maps(void)
 {
-#if defined(CONFIG_SMP) && defined(CONFIG_PPC_PSERIES)
-	int ret, i;
-#endif
+	struct device_node *dn = NULL;
+	int cpu = 0;
 
-#ifdef CONFIG_XMON_DEFAULT
-	xmon_init();
-#endif
+	check_smt_enabled();
 
-#ifdef CONFIG_PPC_ISERIES
-	/* pSeries systems are identified in prom.c via OF. */
-	if ( itLpNaca.xLparInstalled == 1 )
-		systemcfg->platform = PLATFORM_ISERIES_LPAR;
-#endif
-	
-	switch (systemcfg->platform) {
-#ifdef CONFIG_PPC_ISERIES
-	case PLATFORM_ISERIES_LPAR:
-		iSeries_init_early();
-		break;
-#endif
+	while ((dn = of_find_node_by_type(dn, "cpu")) && cpu < NR_CPUS) {
+		u32 *intserv;
+		int j, len = sizeof(u32), nthreads;
+
+		intserv = (u32 *)get_property(dn, "ibm,ppc-interrupt-server#s",
+					      &len);
+		if (!intserv)
+			intserv = (u32 *)get_property(dn, "reg", NULL);
+
+		nthreads = len / sizeof(u32);
+
+		for (j = 0; j < nthreads && cpu < NR_CPUS; j++) {
+			/*
+			 * Only spin up secondary threads if SMT is enabled.
+			 * We must leave space in the logical map for the
+			 * threads.
+			 */
+			if (j == 0 || smt_enabled_at_boot) {
+				cpu_set(cpu, cpu_present_map);
+				set_hard_smp_processor_id(cpu, intserv[j]);
+			}
+			cpu_set(cpu, cpu_possible_map);
+			cpu++;
+		}
+	}
 
+	/*
+	 * On pSeries LPAR, we need to know how many cpus
+	 * could possibly be added to this partition.
+	 */
+	if (systemcfg->platform == PLATFORM_PSERIES_LPAR &&
+				(dn = of_find_node_by_path("/rtas"))) {
+		int num_addr_cell, num_size_cell, maxcpus;
+		unsigned int *ireg;
+
+		num_addr_cell = prom_n_addr_cells(dn);
+		num_size_cell = prom_n_size_cells(dn);
+
+		ireg = (unsigned int *)
+			get_property(dn, "ibm,lrdr-capacity", NULL);
+
+		if (!ireg)
+			goto out;
+
+		maxcpus = ireg[num_addr_cell + num_size_cell];
+
+		/* Double maxcpus for processors which have SMT capability */
+		if (cur_cpu_spec->cpu_features & CPU_FTR_SMT)
+			maxcpus *= 2;
+
+		if (maxcpus > NR_CPUS) {
+			printk(KERN_WARNING
+			       "Partition configured for %d cpus, "
+			       "operating system maximum is %d.\n",
+			       maxcpus, NR_CPUS);
+			maxcpus = NR_CPUS;
+		} else
+			printk(KERN_INFO "Partition configured for %d cpus.\n",
+			       maxcpus);
+
+		for (cpu = 0; cpu < maxcpus; cpu++)
+			cpu_set(cpu, cpu_possible_map);
+	out:
+		of_node_put(dn);
+	}
+
+	/*
+	 * Do the sibling map; assume only two threads per processor.
+	 */
+	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]);
+	}
+
+	systemcfg->processorCount = num_present_cpus();
+}
+#endif /* defined(CONFIG_PPC_MULTIPLATFORM) && defined(CONFIG_SMP) */
+
+
+#ifdef CONFIG_PPC_MULTIPLATFORM
+
+extern struct machdep_calls pSeries_md;
+extern struct machdep_calls pmac_md;
+
+/* Ultimately, stuff them in an elf section like initcalls... */
+static struct machdep_calls __initdata *machines[] = {
 #ifdef CONFIG_PPC_PSERIES
-	case PLATFORM_PSERIES:
-		pSeries_init_early();
-		parse_bootinfo();
-		break;
-
-	case PLATFORM_PSERIES_LPAR:
-		pSeriesLP_init_early();
-		parse_bootinfo();
-		break;
+	&pSeries_md,
 #endif /* CONFIG_PPC_PSERIES */
 #ifdef CONFIG_PPC_PMAC
-	case PLATFORM_POWERMAC:
-		pmac_init_early();
-		parse_bootinfo();
+	&pmac_md,
 #endif /* CONFIG_PPC_PMAC */
+	NULL
+};
+
+/*
+ * Early initialization entry point. This is called by head.S
+ * with MMU translation disabled. We rely on the "feature" of
+ * the CPU that ignores the top 2 bits of the address in real
+ * mode so we can access kernel globals normally provided we
+ * only toy with things in the RMO region. From here, we do
+ * some early parsing of the device-tree to setup out LMB
+ * data structures, and allocate & initialize the hash table
+ * and segment tables so we can start running with translation
+ * enabled.
+ *
+ * It is this function which will call the probe() callback of
+ * the various platform types and copy the matching one to the
+ * global ppc_md structure. Your platform can eventually do
+ * some very early initializations from the probe() routine, but
+ * this is not recommended, be very careful as, for example, the
+ * device-tree is not accessible via normal means at this point.
+ */
+
+void __init early_setup(unsigned long dt_ptr)
+{
+	struct paca_struct *lpaca = get_paca();
+	static struct machdep_calls **mach;
+
+	/*
+	 * Enable early debugging if any specified (see top of
+	 * this file)
+	 */
+	EARLY_DEBUG_INIT();
+
+	DBG(" -> early_setup()\n");
+
+	/*
+	 * Fill the default DBG level in naca (do we want to keep
+	 * that old mecanism around forever ?)
+	 */
+	ppcdbg_initialize();
+
+	/*
+	 * Do early initializations using the flattened device
+	 * tree, like retreiving the physical memory map or
+	 * calculating/retreiving the hash table size
+	 */
+	early_init_devtree(__va(dt_ptr));
+
+	/*
+	 * Iterate all ppc_md structures until we find the proper
+	 * one for the current machine type
+	 */
+	DBG("Probing machine type for platform %x...\n",
+	    systemcfg->platform);
+
+	for (mach = machines; *mach; mach++) {
+		if ((*mach)->probe(systemcfg->platform))
+			break;
+	}
+	/* What can we do if we didn't find ? */
+	if (*mach == NULL) {
+		DBG("No suitable machine found !\n");
+		for (;;);
+	}
+	ppc_md = **mach;
+
+	/* our udbg callbacks got overriden by the above, let's put them
+	 * back in. Ultimately, I want those things to be split from the
+	 * main ppc_md
+	 */
+	EARLY_DEBUG_INIT();
+
+	DBG("Found, Initializing memory management...\n");
+
+	/*
+	 * Initialize stab / SLB management
+	 */
+	stab_initialize(lpaca->stab_real);
+
+	/*
+	 * Initialize the MMU Hash table and create the linear mapping
+	 * of memory
+	 */
+	htab_initialize();
+
+	DBG(" <- early_setup()\n");
+}
+
+
+/*
+ * Initialize some remaining members of the naca and systemcfg structures
+ * (at least until we get rid of them completely). This is mostly some
+ * cache informations about the CPU that will be used by cache flush
+ * routines and/or provided to userland
+ */
+static void __init initialize_naca(void)
+{
+	struct device_node *np;
+	unsigned long num_cpus = 0;
+
+	DBG(" -> initialize_naca()\n");
+
+	for (np = NULL; (np = of_find_node_by_type(np, "cpu"));) {
+		num_cpus += 1;
+
+		/* We're assuming *all* of the CPUs have the same
+		 * d-cache and i-cache sizes... -Peter
+		 */
+
+		if ( num_cpus == 1 ) {
+			u32 *sizep, *lsizep;
+			u32 size, lsize;
+			const char *dc, *ic;
+
+			/* Then read cache informations */
+			if (systemcfg->platform == PLATFORM_POWERMAC) {
+				dc = "d-cache-block-size";
+				ic = "i-cache-block-size";
+			} else {
+				dc = "d-cache-line-size";
+				ic = "i-cache-line-size";
+			}
+
+			size = 0;
+			lsize = cur_cpu_spec->dcache_bsize;
+			sizep = (u32 *)get_property(np, "d-cache-size", NULL);
+			if (sizep != NULL)
+				size = *sizep;
+			lsizep = (u32 *) get_property(np, dc, NULL);
+			if (lsizep != NULL)
+				lsize = *lsizep;
+
+			if (sizep == 0 || lsizep == 0)
+				DBG("Argh, can't find dcache properties ! "
+				    "sizep: %p, lsizep: %p\n", sizep, lsizep);
+
+			systemcfg->dCacheL1Size = size;
+			systemcfg->dCacheL1LineSize = lsize;
+			naca->dCacheL1LogLineSize = __ilog2(lsize);
+			naca->dCacheL1LinesPerPage = PAGE_SIZE/(lsize);
+
+			size = 0;
+			lsize = cur_cpu_spec->icache_bsize;
+			sizep = (u32 *)get_property(np, "i-cache-size", NULL);
+			if (sizep != NULL)
+				size = *sizep;
+			lsizep = (u32 *)get_property(np, ic, NULL);
+			if (lsizep != NULL)
+				lsize = *lsizep;
+			if (sizep == 0 || lsizep == 0)
+				DBG("Argh, can't find icache properties ! "
+				    "sizep: %p, lsizep: %p\n", sizep, lsizep);
+
+			systemcfg->iCacheL1Size = size;
+			systemcfg->iCacheL1LineSize = lsize;
+			naca->iCacheL1LogLineSize = __ilog2(lsize);
+			naca->iCacheL1LinesPerPage = PAGE_SIZE/(lsize);
+
+		}
+	}
+
+	/* Add an eye catcher and the systemcfg layout version number */
+	strcpy(systemcfg->eye_catcher, "SYSTEMCFG:PPC64");
+	systemcfg->version.major = SYSTEMCFG_MAJOR;
+	systemcfg->version.minor = SYSTEMCFG_MINOR;
+	systemcfg->processor = mfspr(SPRN_PVR);
+
+	DBG(" <- initialize_naca()\n");
+}
+
+static void __init check_for_initrd(void)
+{
+#ifdef CONFIG_BLK_DEV_INITRD
+	u64 *prop;
+
+	DBG(" -> check_for_initrd()\n");
+
+	prop = (u64 *)get_property(of_chosen, "linux,initrd-start", NULL);
+	if (prop != NULL) {
+		initrd_start = (unsigned long)__va(*prop);
+		prop = (u64 *)get_property(of_chosen, "linux,initrd-end", NULL);
+		if (prop != NULL) {
+			initrd_end = (unsigned long)__va(*prop);
+			initrd_below_start_ok = 1;
+		} else
+			initrd_start = 0;
 	}
 
 	/* If we were passed an initrd, set the ROOT_DEV properly if the values
 	 * look sensible. If not, clear initrd reference.
 	 */
-#ifdef CONFIG_BLK_DEV_INITRD
 	if (initrd_start >= KERNELBASE && initrd_end >= KERNELBASE &&
 	    initrd_end > initrd_start)
 		ROOT_DEV = Root_RAM0;
 	else
 		initrd_start = initrd_end = 0;
+
+	if (initrd_start)
+		printk("Found initrd at 0x%lx:0x%lx\n", initrd_start, initrd_end);
+
+	DBG(" <- check_for_initrd()\n");
 #endif /* CONFIG_BLK_DEV_INITRD */
+}
 
-#ifdef CONFIG_BOOTX_TEXT
-	map_boot_text();
-	if (systemcfg->platform == PLATFORM_POWERMAC) {
-		early_console_initialized = 1;
-		register_console(&udbg_console);
-	}
-#endif /* CONFIG_BOOTX_TEXT */
+#endif /* CONFIG_PPC_MULTIPLATFORM */
 
-#ifdef CONFIG_PPC_PSERIES
-	if (systemcfg->platform & PLATFORM_PSERIES) {
-		early_console_initialized = 1;
-		register_console(&udbg_console);
-		__irq_offset_value = NUM_ISA_INTERRUPTS;
-		finish_device_tree();
-		chrp_init(r3, r4, r5, r6, r7);
+/*
+ * Do some initial setup of the system.  The parameters are those which 
+ * were passed in from the bootloader.
+ */
+void __init setup_system(void)
+{
+	DBG(" -> setup_system()\n");
 
-#ifdef CONFIG_SMP
-		/* Start secondary threads on SMT systems */
-		for (i = 0; i < NR_CPUS; i++) {
-			if (cpu_available(i) && !cpu_possible(i)) {
-				printk("%16.16x : starting thread\n", i);
-				rtas_call(rtas_token("start-cpu"), 3, 1, &ret,
-					  get_hard_smp_processor_id(i), 
-					  (u32)*((unsigned long *)pseries_secondary_smp_init),
-					  i);
-				cpu_set(i, cpu_possible_map);
-				systemcfg->processorCount++;
-			}
-		}
-#endif /* CONFIG_SMP */
-	}
+#ifdef CONFIG_PPC_ISERIES
+	/* pSeries systems are identified in prom.c via OF. */
+	if (itLpNaca.xLparInstalled == 1)
+		systemcfg->platform = PLATFORM_ISERIES_LPAR;
+
+	ppc_md.init_early();
+#else /* CONFIG_PPC_ISERIES */
+
+	/*
+	 * Unflatten the device-tree passed by prom_init or kexec
+	 */
+	unflatten_device_tree();
+
+	/*
+	 * Fill the naca & systemcfg structures with informations
+	 * retreived from the device-tree. Need to be called before
+	 * finish_device_tree() since the later requires some of the
+	 * informations filled up here to properly parse the interrupt
+	 * tree.
+	 * It also sets up the cache line sizes which allows to call
+	 * routines like flush_icache_range (used by the hash init
+	 * later on).
+	 */
+	initialize_naca();
+
+#ifdef CONFIG_PPC_PSERIES
+	/*
+	 * Initialize RTAS if available
+	 */
+	rtas_initialize();
 #endif /* CONFIG_PPC_PSERIES */
 
-#ifdef CONFIG_PPC_PMAC
-	if (systemcfg->platform == PLATFORM_POWERMAC) {
-		finish_device_tree();
-		pmac_init(r3, r4, r5, r6, r7);
-	}
-#endif /* CONFIG_PPC_PMAC */
+	/*
+	 * Check if we have an initrd provided via the device-tree
+	 */
+	check_for_initrd();
+
+	/*
+	 * Do some platform specific early initializations, that includes
+	 * setting up the hash table pointers. It also sets up some interrupt-mapping
+	 * related options that will be used by finish_device_tree()
+	 */
+	ppc_md.init_early();
+
+	/*
+	 * "Finish" the device-tree, that is do the actual parsing of
+	 * some of the properties like the interrupt map
+	 */
+	finish_device_tree();
+
+	/*
+	 * Initialize xmon
+	 */
+#ifdef CONFIG_XMON_DEFAULT
+	xmon_init();
+#endif
+	/*
+	 * Register early console
+	 */
+	early_console_initialized = 1;
+	register_console(&udbg_console);
 
-#if defined(CONFIG_HOTPLUG_CPU) &&  !defined(CONFIG_PPC_PMAC)
-	rtas_stop_self_args.token = rtas_token("stop-self");
-#endif /* CONFIG_HOTPLUG_CPU && !CONFIG_PPC_PMAC */
+#endif /* !CONFIG_PPC_ISERIES */
 
-	/* Finish initializing the hash table (do the dynamic
-	 * patching for the fast-path hashtable.S code)
+	/* Save unparsed command line copy for /proc/cmdline */
+	strlcpy(saved_command_line, cmd_line, COMMAND_LINE_SIZE);
+
+	parse_early_param();
+
+#if defined(CONFIG_SMP) && !defined(CONFIG_PPC_ISERIES)
+	/*
+	 * iSeries has already initialized the cpu maps at this point.
 	 */
-	htab_finish_init();
+	setup_cpu_maps();
+#endif /* defined(CONFIG_SMP) && !defined(CONFIG_PPC_ISERIES) */
 
 	printk("Starting Linux PPC64 %s\n", UTS_RELEASE);
 
@@ -282,28 +640,10 @@
 
 	mm_init_ppc64();
 
-#if defined(CONFIG_SMP) && defined(CONFIG_PPC_PSERIES)
-	if (cur_cpu_spec->firmware_features & FW_FEATURE_SPLPAR) {
-		vpa_init(boot_cpuid);
-	}
-#endif
-
-	/* Select the correct idle loop for the platform. */
-	idle_setup();
-
-	switch (systemcfg->platform) {
-#ifdef CONFIG_PPC_ISERIES
-	case PLATFORM_ISERIES_LPAR:
-		iSeries_init();
-		break;
-#endif
-	default:
-		/* The following relies on the device tree being */
-		/* fully configured.                             */
-		parse_cmd_line(r3, r4, r5, r6, r7);
-	}
+	DBG(" <- setup_system()\n");
 }
 
+
 void machine_restart(char *cmd)
 {
 	if (ppc_md.nvram_sync)
@@ -373,7 +713,7 @@
 #ifdef CONFIG_SMP
 	pvr = per_cpu(pvr, cpu_id);
 #else
-	pvr = _get_PVR();
+	pvr = mfspr(SPRN_PVR);
 #endif
 	maj = (pvr >> 8) & 0xFF;
 	min = pvr & 0xFF;
@@ -425,74 +765,75 @@
 	.show =	show_cpuinfo,
 };
 
-/*
- * Fetch the cmd_line from open firmware. 
- */
-void parse_cmd_line(unsigned long r3, unsigned long r4, unsigned long r5,
-		  unsigned long r6, unsigned long r7)
-{
-	cmd_line[0] = 0;
+#if 0 /* XXX not currently used */
+unsigned long memory_limit;
 
-#ifdef CONFIG_CMDLINE
-	strlcpy(cmd_line, CONFIG_CMDLINE, sizeof(cmd_line));
-#endif /* CONFIG_CMDLINE */
-
-#ifdef CONFIG_PPC_PSERIES
-	{
-	struct device_node *chosen;
+static int __init early_parsemem(char *p)
+{
+	if (!p)
+		return 0;
 
-	chosen = of_find_node_by_name(NULL, "chosen");
-	if (chosen != NULL) {
-		char *p;
-		p = get_property(chosen, "bootargs", NULL);
-		if (p != NULL && p[0] != 0)
-			strlcpy(cmd_line, p, sizeof(cmd_line));
-		of_node_put(chosen);
-	}
-	}
-#endif
+	memory_limit = memparse(p, &p);
 
-	/* Look for mem= option on command line */
-	if (strstr(cmd_line, "mem=")) {
-		char *p, *q;
-		unsigned long maxmem = 0;
-		extern unsigned long __max_memory;
-
-		for (q = cmd_line; (p = strstr(q, "mem=")) != 0; ) {
-			q = p + 4;
-			if (p > cmd_line && p[-1] != ' ')
-				continue;
-			maxmem = simple_strtoul(q, &q, 0);
-			if (*q == 'k' || *q == 'K') {
-				maxmem <<= 10;
-				++q;
-			} else if (*q == 'm' || *q == 'M') {
-				maxmem <<= 20;
-				++q;
-			}
-		}
-		__max_memory = maxmem;
-	}
+	return 0;
 }
+early_param("mem", early_parsemem);
+#endif
 
-#ifdef CONFIG_PPC_PSERIES
+#ifdef CONFIG_PPC_MULTIPLATFORM
 static int __init set_preferred_console(void)
 {
 	struct device_node *prom_stdout;
 	char *name;
-	int offset;
+	int offset = 0;
+#if  0
+	phandle *stdout_ph;
+#endif
+	DBG(" -> set_preferred_console()\n");
 
 	/* The user has requested a console so this is already set up. */
-	if (strstr(saved_command_line, "console="))
+	if (strstr(saved_command_line, "console=")) {
+		DBG(" console was specified !\n");
 		return -EBUSY;
+	}
 
-	prom_stdout = find_path_device(of_stdout_device);
-	if (!prom_stdout)
+	if (!of_chosen) {
+		DBG(" of_chosen is NULL !\n");
 		return -ENODEV;
+	}
+	/* We are getting a weird phandle from OF ... */
+#if 0
+	stdout_ph = (phandle *)get_property(of_chosen, "linux,stdout-package", NULL);
+	if (stdout_ph == NULL) {
+		DBG(" no linux,stdout-package !\n");
+		return -ENODEV;
+	}
+	prom_stdout = of_find_node_by_phandle(*stdout_ph);
+	if (!prom_stdout) {
+		DBG(" can't find stdout package for phandle 0x%x !\n", *stdout_ph);
+		return -ENODEV;
+	}
+#endif
+	/* ... So use the full path instead */
+#if 1
+	name = (char *)get_property(of_chosen, "linux,stdout-path", NULL);
+	if (name == NULL) {
+		DBG(" no linux,stdout-path !\n");
+		return -ENODEV;
+	}
+	prom_stdout = of_find_node_by_path(name);
+	if (!prom_stdout) {
+		DBG(" can't find stdout package %s !\n", name);
+		return -ENODEV;
+	}	
+#endif
+	DBG("stdout is %s\n", prom_stdout->full_name);
 
 	name = (char *)get_property(prom_stdout, "name", NULL);
-	if (!name)
-		return -ENODEV;
+	if (!name) {
+		DBG(" stdout package has no name !\n");
+		goto not_found;
+	}
 
 	if (strcmp(name, "serial") == 0) {
 		int i;
@@ -513,76 +854,69 @@
 					break;
 				default:
 					/* We dont recognise the serial port */
-					return -ENODEV;
+					goto not_found;
 			}
 		}
-	} else if (strcmp(name, "vty") == 0)
-		/* pSeries LPAR virtual console */
-		return add_preferred_console("hvc", 0, NULL);
+	}
+#ifdef CONFIG_PPC_PSERIES
+	else if (strcmp(name, "vty") == 0) {
+ 		u32 *reg = (u32 *)get_property(prom_stdout, "reg", NULL);
+ 		char *compat = (char *)get_property(prom_stdout, "compatible", NULL);
+
+ 		if (reg && compat && (strcmp(compat, "hvterm-protocol") == 0)) {
+ 			/* Host Virtual Serial Interface */
+ 			int offset;
+ 			switch (reg[0]) {
+ 				case 0x30000000:
+ 					offset = 0;
+ 					break;
+ 				case 0x30000001:
+ 					offset = 1;
+ 					break;
+ 				default:
+					goto not_found;
+ 			}
+			of_node_put(prom_stdout);
+			DBG("Found hvsi console at offset %d\n", offset);
+ 			return add_preferred_console("hvsi", offset, NULL);
+ 		} else {
+ 			/* pSeries LPAR virtual console */
+			of_node_put(prom_stdout);
+			DBG("Found hvc console\n");
+ 			return add_preferred_console("hvc", 0, NULL);
+ 		}
+	}
+#endif /* CONFIG_PPC_PSERIES */
 	else if (strcmp(name, "ch-a") == 0)
 		offset = 0;
 	else if (strcmp(name, "ch-b") == 0)
 		offset = 1;
 	else
-		return -ENODEV;
+		goto not_found;
+	of_node_put(prom_stdout);
+
+	DBG("Found serial console at ttyS%d\n", offset);
 
 	return add_preferred_console("ttyS", offset, NULL);
 
+ not_found:
+	DBG("No preferred console found !\n");
+	of_node_put(prom_stdout);
+	return -ENODEV;
 }
 console_initcall(set_preferred_console);
-
-int parse_bootinfo(void)
-{
-	struct bi_record *rec;
-
-	rec = prom.bi_recs;
-
-	if ( rec == NULL || rec->tag != BI_FIRST )
-		return -1;
-
-	for ( ; rec->tag != BI_LAST ; rec = bi_rec_next(rec) ) {
-		switch (rec->tag) {
-		case BI_CMD_LINE:
-			strlcpy(cmd_line, (void *)rec->data, sizeof(cmd_line));
-			break;
-		}
-	}
-
-	return 0;
-}
-#endif
-
-int __init ppc_init(void)
-{
-	/* clear the progress line */
-	ppc_md.progress(" ", 0xffff);
-
-	if (ppc_md.init != NULL) {
-		ppc_md.init();
-	}
-	return 0;
-}
-
-arch_initcall(ppc_init);
-
-void __init ppc64_calibrate_delay(void)
-{
-	loops_per_jiffy = tb_ticks_per_jiffy;
-
-	printk("Calibrating delay loop... %lu.%02lu BogoMips\n",
-			       loops_per_jiffy/(500000/HZ),
-			       loops_per_jiffy/(5000/HZ) % 100);
-}	
-
-extern void (*calibrate_delay)(void);
+#endif /* CONFIG_PPC_MULTIPLATFORM */
 
 #ifdef CONFIG_IRQSTACKS
 static void __init irqstack_early_init(void)
 {
-	int i;
+	unsigned int i;
 
-	/* interrupt stacks must be under 256MB, we cannot afford to take SLB misses on them */
-	for (i = 0; i < NR_CPUS; i++) {
+	/*
+	 * interrupt stacks must be under 256MB, we cannot afford to take
+	 * SLB misses on them.
+	 */
+	for_each_cpu(i) {
 		softirq_ctx[i] = (struct thread_info *)__va(lmb_alloc_base(THREAD_SIZE,
 					THREAD_SIZE, 0x10000000));
 		hardirq_ctx[i] = (struct thread_info *)__va(lmb_alloc_base(THREAD_SIZE,
@@ -594,6 +928,31 @@
 #endif
 
 /*
+ * Stack space used when we detect a bad kernel stack pointer, and
+ * early in SMP boots before relocation is enabled.
+ */
+static void __init emergency_stack_init(void)
+{
+	unsigned long limit;
+	unsigned int i;
+
+	/*
+	 * Emergency stacks must be under 256MB, we cannot afford to take
+	 * SLB misses on them. The ABI also requires them to be 128-byte
+	 * aligned.
+	 *
+	 * Since we use these as temporary stacks during secondary CPU
+	 * bringup, we need to get at them in real mode. This means they
+	 * must also be within the RMO region.
+	 */
+	limit = min(0x10000000UL, lmb.rmo_size);
+
+	for_each_cpu(i)
+		paca[i].emergency_sp = __va(lmb_alloc_base(PAGE_SIZE, 128,
+						limit)) + PAGE_SIZE;
+}
+
+/*
  * Called into from start_kernel, after lock_kernel has been called.
  * Initializes bootmem, which is unsed to manage page allocation until
  * mem_init is called.
@@ -603,17 +962,9 @@
 	extern int panic_timeout;
 	extern void do_init_bootmem(void);
 
-	calibrate_delay = ppc64_calibrate_delay;
-
 	ppc64_boot_msg(0x12, "Setup Arch");
 
-#ifdef CONFIG_XMON
-	if (strstr(cmd_line, "xmon")) {
-		/* ensure xmon is enabled */
-		xmon_init();
-		debugger(0);
-	}
-#endif /* CONFIG_XMON */
+	*cmdline_p = cmd_line;
 
 	/*
 	 * Set cache line size based on type of cpu as a default.
@@ -634,21 +985,22 @@
 	init_mm.end_data = (unsigned long) _edata;
 	init_mm.brk = klimit;
 	
-	/* Save unparsed command line copy for /proc/cmdline */
-	strlcpy(saved_command_line, cmd_line, COMMAND_LINE_SIZE);
-	*cmdline_p = cmd_line;
-
 	irqstack_early_init();
+	emergency_stack_init();
 
 	/* set up the bootmem stuff with available memory */
 	do_init_bootmem();
 
+	/* Select the correct idle loop for the platform. */
+	idle_setup();
+
 	ppc_md.setup_arch();
 
 	paging_init();
 	ppc64_boot_msg(0x15, "Setup Done");
 }
 
+
 /* ToDo: do something useful if ppc_md is not yet setup. */
 #define PPC64_LINUX_FUNCTION 0x0f000000
 #define PPC64_IPL_MESSAGE 0xc0000000
@@ -753,3 +1105,16 @@
 __setup("spread_lpevents=", set_spread_lpevents );
 __setup("decr_overclock_proc0=", set_decr_overclock_proc0 );
 __setup("decr_overclock=", set_decr_overclock );
+
+#ifdef CONFIG_XMON
+static int __init early_xmon(char *p)
+{
+	/* ensure xmon is enabled */
+	xmon_init();
+	debugger(0);
+
+	return 0;
+}
+early_param("xmon", early_xmon);
+#endif
+
diff -Nru a/arch/ppc64/kernel/signal.c b/arch/ppc64/kernel/signal.c
--- a/arch/ppc64/kernel/signal.c	2004-10-18 14:55:53 -07:00
+++ b/arch/ppc64/kernel/signal.c	2004-10-18 14:55:53 -07:00
@@ -26,7 +26,6 @@
 #include <linux/unistd.h>
 #include <linux/stddef.h>
 #include <linux/elf.h>
-#include <asm/ppc32.h>
 #include <asm/sigcontext.h>
 #include <asm/ucontext.h>
 #include <asm/uaccess.h>
@@ -127,7 +126,7 @@
 	 * v_regs pointer or not
 	 */
 #ifdef CONFIG_ALTIVEC
-	elf_vrreg_t __user *v_regs = (elf_vrreg_t __user *)(((unsigned long)sc->vmx_reserve) & ~0xful);
+	elf_vrreg_t __user *v_regs = (elf_vrreg_t __user *)(((unsigned long)sc->vmx_reserve + 15) & ~0xful);
 #endif
 	long err = 0;
 
@@ -178,7 +177,7 @@
 	elf_vrreg_t __user *v_regs;
 #endif
 	unsigned long err = 0;
-	unsigned long save_r13;
+	unsigned long save_r13 = 0;
 	elf_greg_t *gregs = (elf_greg_t *)regs;
 	int i;
 
@@ -371,7 +370,8 @@
 	printk("badframe in sys_rt_sigreturn, regs=%p uc=%p &uc->uc_mcontext=%p\n",
 	       regs, uc, &uc->uc_mcontext);
 #endif
-	do_exit(SIGSEGV);
+	force_sig(SIGSEGV, current);
+	return 0;
 }
 
 static void setup_rt_frame(int signr, struct k_sigaction *ka, siginfo_t *info,
@@ -446,7 +446,7 @@
 	printk("badframe in setup_rt_frame, regs=%p frame=%p newsp=%lx\n",
 	       regs, frame, newsp);
 #endif
-	do_exit(SIGSEGV);
+	force_sigsegv(signr, current);
 }
 
 
@@ -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-10-18 14:57:03 -07:00
+++ b/arch/ppc64/kernel/signal32.c	2004-10-18 14:57:03 -07:00
@@ -189,7 +189,7 @@
 	elf_greg_t64 *gregs = (elf_greg_t64 *)regs;
 	int i;
 	long err = 0;
-	unsigned int save_r2;
+	unsigned int save_r2 = 0;
 #ifdef CONFIG_ALTIVEC
 	unsigned long msr;
 #endif
@@ -472,10 +472,14 @@
 				  &d->si_addr);
 		break;
 	case __SI_POLL >> 16:
-	case __SI_TIMER >> 16:
 		err |= __put_user(s->si_band, &d->si_band);
 		err |= __put_user(s->si_fd, &d->si_fd);
 		break;
+	case __SI_TIMER >> 16:
+		err |= __put_user(s->si_tid, &d->si_tid);
+		err |= __put_user(s->si_overrun, &d->si_overrun);
+		err |= __put_user(s->si_int, &d->si_int);
+		break;
 	case __SI_RT >> 16: /* This is not generated by the kernel as of now.  */
 	case __SI_MESGQ >> 16:
 		err |= __put_user(s->si_int, &d->si_int);
@@ -699,9 +703,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 +866,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 +928,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 +948,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 +967,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 +975,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-10-18 14:56:49 -07:00
+++ b/arch/ppc64/kernel/smp.c	2004-10-18 14:56:49 -07:00
@@ -15,6 +15,8 @@
  *      2 of the License, or (at your option) any later version.
  */
 
+#undef DEBUG
+
 #include <linux/config.h>
 #include <linux/kernel.h>
 #include <linux/module.h>
@@ -36,7 +38,6 @@
 #include <asm/irq.h>
 #include <asm/page.h>
 #include <asm/pgtable.h>
-#include <asm/hardirq.h>
 #include <asm/io.h>
 #include <asm/prom.h>
 #include <asm/smp.h>
@@ -53,14 +54,20 @@
 #include <asm/cputable.h>
 #include <asm/system.h>
 #include <asm/rtas.h>
+#include <asm/plpar_wrappers.h>
+
+#ifdef DEBUG
+#define DBG(fmt...) udbg_printf(fmt)
+#else
+#define DBG(fmt...)
+#endif
 
 int smp_threads_ready;
 unsigned long cache_decay_ticks;
 
 cpumask_t cpu_possible_map = CPU_MASK_NONE;
 cpumask_t cpu_online_map = CPU_MASK_NONE;
-cpumask_t cpu_available_map = CPU_MASK_NONE;
-cpumask_t cpu_present_at_boot = 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);
@@ -76,9 +83,13 @@
 extern long register_vpa(unsigned long flags, unsigned long proc,
 			 unsigned long vpa);
 
+int smt_enabled_at_boot = 1;
+
 /* Low level assembly function used to backup CPU 0 state */
 extern void __save_cpu_setup(void);
 
+extern void pseries_secondary_smp_init(unsigned long); 
+
 #ifdef CONFIG_PPC_ISERIES
 static unsigned long iSeries_smp_message[NR_CPUS];
 
@@ -124,9 +135,8 @@
 	np = 0;
         for (i=0; i < NR_CPUS; ++i) {
                 if (paca[i].lppaca.xDynProcStatus < 2) {
-			cpu_set(i, cpu_available_map);
 			cpu_set(i, cpu_possible_map);
-			cpu_set(i, cpu_present_at_boot);
+			cpu_set(i, cpu_present_map);
                         ++np;
                 }
         }
@@ -183,7 +193,7 @@
 }
 #endif
 
-#ifdef CONFIG_PPC_PSERIES
+#ifdef CONFIG_PPC_MULTIPLATFORM
 void smp_openpic_message_pass(int target, int msg)
 {
 	/* make sure we're sending something that translates to an IPI */
@@ -224,7 +234,10 @@
 	do_openpic_setup_cpu();
 }
 
-#ifdef CONFIG_HOTPLUG_CPU
+#endif /* CONFIG_PPC_MULTIPLATFORM */
+
+#ifdef CONFIG_PPC_PSERIES
+
 /* Get state of physical CPU.
  * Return codes:
  *	0	- The processor is in the RTAS stopped state
@@ -233,13 +246,15 @@
  *	-1	- Hardware Error
  *	-2	- Hardware Busy, Try again later.
  */
-static int query_cpu_stopped(unsigned int pcpu)
+int query_cpu_stopped(unsigned int pcpu)
 {
 	int cpu_status;
 	int status, qcss_tok;
 
+	DBG(" -> query_cpu_stopped(%d)\n", pcpu);
 	qcss_tok = rtas_token("query-cpu-stopped-state");
-	BUG_ON(qcss_tok == RTAS_UNKNOWN_SERVICE);
+	if (qcss_tok == RTAS_UNKNOWN_SERVICE)
+		return -1;
 	status = rtas_call(qcss_tok, 1, 2, &cpu_status, pcpu);
 	if (status != 0) {
 		printk(KERN_ERR
@@ -247,9 +262,13 @@
 		return status;
 	}
 
+	DBG(" <- query_cpu_stopped(), status: %d\n", cpu_status);
+
 	return cpu_status;
 }
 
+#ifdef CONFIG_HOTPLUG_CPU
+
 int __cpu_disable(void)
 {
 	/* FIXME: go put this in a header somewhere */
@@ -272,13 +291,12 @@
 	int cpu_status;
 	unsigned int pcpu = get_hard_smp_processor_id(cpu);
 
-	for (tries = 0; tries < 5; tries++) {
+	for (tries = 0; tries < 25; tries++) {
 		cpu_status = query_cpu_stopped(pcpu);
-
-		if (cpu_status == 0)
+		if (cpu_status == 0 || cpu_status == -1)
 			break;
 		set_current_state(TASK_UNINTERRUPTIBLE);
-		schedule_timeout(HZ);
+		schedule_timeout(HZ/5);
 	}
 	if (cpu_status != 0) {
 		printk("Querying DEAD? cpu %i (%i) shows %i\n",
@@ -372,13 +390,13 @@
 static inline int __devinit smp_startup_cpu(unsigned int lcpu)
 {
 	int status;
-	extern void (*pseries_secondary_smp_init)(unsigned int cpu);
-	unsigned long start_here = __pa(pseries_secondary_smp_init);
+	unsigned long start_here = __pa((u32)*((unsigned long *)
+					       pseries_secondary_smp_init));
 	unsigned int pcpu;
 
 	/* At boot time the cpus are already spinning in hold
 	 * loops, so nothing to do. */
- 	if (system_state == SYSTEM_BOOTING)
+ 	if (system_state < SYSTEM_RUNNING)
 		return 1;
 
 	pcpu = find_physical_cpu_to_start(get_hard_smp_processor_id(lcpu));
@@ -401,56 +419,11 @@
 	}
 	return 1;
 }
-
-static inline void look_for_more_cpus(void)
-{
-	int num_addr_cell, num_size_cell, len, i, maxcpus;
-	struct device_node *np;
-	unsigned int *ireg;
-
-	/* Find the property which will tell us about how many CPUs
-	 * we're allowed to have. */
-	if ((np = find_path_device("/rtas")) == NULL) {
-		printk(KERN_ERR "Could not find /rtas in device tree!");
-		return;
-	}
-	num_addr_cell = prom_n_addr_cells(np);
-	num_size_cell = prom_n_size_cells(np);
-
-	ireg = (unsigned int *)get_property(np, "ibm,lrdr-capacity", &len);
-	if (ireg == NULL) {
-		/* FIXME: make sure not marked as lrdr_capable() */
-		return;
-	}
-
-	maxcpus = ireg[num_addr_cell + num_size_cell];
-
-	/* Double maxcpus for processors which have SMT capability */
-	if (cur_cpu_spec->cpu_features & CPU_FTR_SMT)
-		maxcpus *= 2;
-
-
-	if (maxcpus > NR_CPUS) {
-		printk(KERN_WARNING
-		       "Partition configured for %d cpus, "
-		       "operating system maximum is %d.\n", maxcpus, NR_CPUS);
-		maxcpus = NR_CPUS;
-	} else
-		printk(KERN_INFO "Partition configured for %d cpus.\n",
-		       maxcpus);
-
-	/* Make those cpus (which might appear later) possible too. */
-	for (i = 0; i < maxcpus; i++)
-		cpu_set(i, cpu_possible_map);
-}
 #else /* ... CONFIG_HOTPLUG_CPU */
 static inline int __devinit smp_startup_cpu(unsigned int lcpu)
 {
 	return 1;
 }
-static inline void look_for_more_cpus(void)
-{
-}
 #endif /* CONFIG_HOTPLUG_CPU */
 
 static void smp_pSeries_kick_cpu(int nr)
@@ -485,13 +458,13 @@
 }
 
 #ifdef CONFIG_PPC_PSERIES
-void vpa_init(int cpu)
+static void vpa_init(int cpu)
 {
-	unsigned long flags;
+	unsigned long flags, pcpu = get_hard_smp_processor_id(cpu);
 
 	/* Register the Virtual Processor Area (VPA) */
 	flags = 1UL << (63 - 18);
-	register_vpa(flags, cpu, __pa((unsigned long)&(paca[cpu].lppaca)));
+	register_vpa(flags, pcpu, __pa((unsigned long)&(paca[cpu].lppaca)));
 }
 
 static inline void smp_xics_do_message(int cpu, int msg)
@@ -576,26 +549,47 @@
 /* This is called very early */
 void __init smp_init_pSeries(void)
 {
+	int ret, i;
+
+	DBG(" -> smp_init_pSeries()\n");
 
 	if (naca->interrupt_controller == IC_OPEN_PIC)
 		smp_ops = &pSeries_openpic_smp_ops;
 	else
 		smp_ops = &pSeries_xics_smp_ops;
 
+	/* Start secondary threads on SMT systems; primary threads
+	 * are already in the running state.
+	 */
+	for_each_present_cpu(i) {
+		if (query_cpu_stopped(get_hard_smp_processor_id(i)) == 0) {
+			printk("%16.16x : starting thread\n", i);
+			DBG("%16.16x : starting thread\n", i);
+			rtas_call(rtas_token("start-cpu"), 3, 1, &ret,
+				  get_hard_smp_processor_id(i),
+				  __pa((u32)*((unsigned long *)
+					      pseries_secondary_smp_init)),
+				  i);
+		}
+	}
+
+	if (cur_cpu_spec->firmware_features & FW_FEATURE_SPLPAR)
+		vpa_init(boot_cpuid);
+
 	/* Non-lpar has additional take/give timebase */
 	if (systemcfg->platform == PLATFORM_PSERIES) {
 		smp_ops->give_timebase = pSeries_give_timebase;
 		smp_ops->take_timebase = pSeries_take_timebase;
 	}
+
+
+	DBG(" <- smp_init_pSeries()\n");
 }
-#endif
+#endif /* CONFIG_PPC_PSERIES */
 
 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)
@@ -751,6 +745,8 @@
 	return ret;
 }
 
+EXPORT_SYMBOL(smp_call_function);
+
 void smp_call_function_interrupt(void)
 {
 	void (*func) (void *info);
@@ -794,26 +790,17 @@
 
 static void __devinit smp_store_cpu_info(int id)
 {
-	per_cpu(pvr, id) = _get_PVR();
+	per_cpu(pvr, id) = mfspr(SPRN_PVR);
 }
 
 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;
 }
@@ -831,8 +818,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();
@@ -843,8 +828,7 @@
 	 * number of msecs off until someone does a settimeofday()
 	 */
 	do_gtod.tb_orig_stamp = tb_last_stamp;
-
-	look_for_more_cpus();
+	systemcfg->tb_orig_stamp = tb_last_stamp;
 #endif
 
 	max_cpus = smp_ops->probe();
@@ -863,7 +847,6 @@
 {
 	BUG_ON(smp_processor_id() != boot_cpuid);
 
-	/* cpu_possible is set up in prom.c */
 	cpu_set(boot_cpuid, cpu_online_map);
 
 	paca[boot_cpuid].__current = current;
@@ -875,11 +858,9 @@
 	int c;
 
 	/* At boot, don't bother with non-present cpus -JSCHOPP */
-	if (system_state == SYSTEM_BOOTING && !cpu_present_at_boot(cpu))
+	if (system_state < SYSTEM_RUNNING && !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)) {
@@ -909,7 +890,7 @@
 	 * use this value that I found through experimentation.
 	 * -- Cort
 	 */
-	if (system_state == SYSTEM_BOOTING)
+	if (system_state < SYSTEM_RUNNING)
 		for (c = 5000; c && !cpu_callin_map[cpu]; c--)
 			udelay(100);
 #ifdef CONFIG_HOTPLUG_CPU
@@ -1004,219 +985,12 @@
 	smp_threads_ready = 1;
 
 	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);
-	}
+	/*
+	 * We know at boot the maximum number of cpus we can add to
+	 * a partition and set cpu_possible_map accordingly. cpu_present_map
+	 * needs to match for the hotplug code to allow us to hot add
+	 * any offline cpus.
+	 */
+	cpu_present_map = cpu_possible_map;
 }
-#endif /* CONFIG_NUMA */
-#endif /* CONFIG_SCHED_SMT */
diff -Nru a/arch/ppc64/kernel/stab.c b/arch/ppc64/kernel/stab.c
--- a/arch/ppc64/kernel/stab.c	2004-10-18 14:56:49 -07:00
+++ /dev/null	Wed Dec 31 16:00:00 196900
@@ -1,281 +0,0 @@
-/*
- * PowerPC64 Segment Translation Support.
- *
- * Dave Engebretsen and Mike Corrigan {engebret|mikejc}@us.ibm.com
- *    Copyright (c) 2001 Dave Engebretsen
- *
- * Copyright (C) 2002 Anton Blanchard <anton@au.ibm.com>, IBM
- * 
- *      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 <asm/pgtable.h>
-#include <asm/mmu.h>
-#include <asm/mmu_context.h>
-#include <asm/paca.h>
-#include <asm/naca.h>
-#include <asm/cputable.h>
-
-static int make_ste(unsigned long stab, unsigned long esid,
-		    unsigned long vsid);
-
-void slb_initialize(void);
-
-/*
- * Build an entry for the base kernel segment and put it into
- * the segment table or SLB.  All other segment table or SLB
- * entries are faulted in.
- */
-void stab_initialize(unsigned long stab)
-{
-	unsigned long vsid = get_kernel_vsid(KERNELBASE);
-
-	if (cur_cpu_spec->cpu_features & CPU_FTR_SLB) {
-		slb_initialize();
-	} else {
-		asm volatile("isync; slbia; isync":::"memory");
-		make_ste(stab, GET_ESID(KERNELBASE), vsid);
-
-		/* Order update */
-		asm volatile("sync":::"memory"); 
-	}
-}
-
-/* Both the segment table and SLB code uses the following cache */
-#define NR_STAB_CACHE_ENTRIES 8
-DEFINE_PER_CPU(long, stab_cache_ptr);
-DEFINE_PER_CPU(long, stab_cache[NR_STAB_CACHE_ENTRIES]);
-
-/*
- * Segment table stuff
- */
-
-/*
- * Create a segment table entry for the given esid/vsid pair.
- */
-static int make_ste(unsigned long stab, unsigned long esid, unsigned long vsid)
-{
-	unsigned long entry, group, old_esid, castout_entry, i;
-	unsigned int global_entry;
-	STE *ste, *castout_ste;
-	unsigned long kernel_segment = (REGION_ID(esid << SID_SHIFT) != 
-					USER_REGION_ID);
-
-	/* Search the primary group first. */
-	global_entry = (esid & 0x1f) << 3;
-	ste = (STE *)(stab | ((esid & 0x1f) << 7)); 
-
-	/* Find an empty entry, if one exists. */
-	for (group = 0; group < 2; group++) {
-		for (entry = 0; entry < 8; entry++, ste++) {
-			if (!(ste->dw0.dw0.v)) {
-				ste->dw0.dword0 = 0;
-				ste->dw1.dword1 = 0;
-				ste->dw1.dw1.vsid = vsid;
-				ste->dw0.dw0.esid = esid;
-				ste->dw0.dw0.kp = 1;
-				if (!kernel_segment)
-					ste->dw0.dw0.ks = 1;
-				asm volatile("eieio":::"memory");
-				ste->dw0.dw0.v = 1;
-				return (global_entry | entry);
-			}
-		}
-		/* Now search the secondary group. */
-		global_entry = ((~esid) & 0x1f) << 3;
-		ste = (STE *)(stab | (((~esid) & 0x1f) << 7)); 
-	}
-
-	/*
-	 * Could not find empty entry, pick one with a round robin selection.
-	 * Search all entries in the two groups.
-	 */
-	castout_entry = get_paca()->stab_rr;
-	for (i = 0; i < 16; i++) {
-		if (castout_entry < 8) {
-			global_entry = (esid & 0x1f) << 3;
-			ste = (STE *)(stab | ((esid & 0x1f) << 7)); 
-			castout_ste = ste + castout_entry;
-		} else {
-			global_entry = ((~esid) & 0x1f) << 3;
-			ste = (STE *)(stab | (((~esid) & 0x1f) << 7)); 
-			castout_ste = ste + (castout_entry - 8);
-		}
-
-		/* Dont cast out the first kernel segment */
-		if (castout_ste->dw0.dw0.esid != GET_ESID(KERNELBASE))
-			break;
-
-		castout_entry = (castout_entry + 1) & 0xf;
-	}
-
-	get_paca()->stab_rr = (castout_entry + 1) & 0xf;
-
-	/* Modify the old entry to the new value. */
-
-	/* Force previous translations to complete. DRENG */
-	asm volatile("isync" : : : "memory");
-
-	castout_ste->dw0.dw0.v = 0;
-	asm volatile("sync" : : : "memory");    /* Order update */
-
-	castout_ste->dw0.dword0 = 0;
-	castout_ste->dw1.dword1 = 0;
-	castout_ste->dw1.dw1.vsid = vsid;
-	old_esid = castout_ste->dw0.dw0.esid;
-	castout_ste->dw0.dw0.esid = esid;
-	castout_ste->dw0.dw0.kp = 1;
-	if (!kernel_segment)
-		castout_ste->dw0.dw0.ks = 1;
-	asm volatile("eieio" : : : "memory");   /* Order update */
-	castout_ste->dw0.dw0.v  = 1;
-	asm volatile("slbie  %0" : : "r" (old_esid << SID_SHIFT)); 
-	/* Ensure completion of slbie */
-	asm volatile("sync" : : : "memory");
-
-	return (global_entry | (castout_entry & 0x7));
-}
-
-static inline void __ste_allocate(unsigned long esid, unsigned long vsid)
-{
-	unsigned char stab_entry;
-	unsigned long offset;
-	int region_id = REGION_ID(esid << SID_SHIFT);
-
-	stab_entry = make_ste(get_paca()->stab_addr, esid, vsid);
-
-	if (region_id != USER_REGION_ID)
-		return;
-
-	offset = __get_cpu_var(stab_cache_ptr);
-	if (offset < NR_STAB_CACHE_ENTRIES)
-		__get_cpu_var(stab_cache[offset++]) = stab_entry;
-	else
-		offset = NR_STAB_CACHE_ENTRIES+1;
-	__get_cpu_var(stab_cache_ptr) = offset;
-}
-
-/*
- * Allocate a segment table entry for the given ea.
- */
-int ste_allocate(unsigned long ea)
-{
-	unsigned long vsid, esid;
-	mm_context_t context;
-
-	/* Check for invalid effective addresses. */
-	if (!IS_VALID_EA(ea))
-		return 1;
-
-	/* Kernel or user address? */
-	if (REGION_ID(ea) >= KERNEL_REGION_ID) {
-		vsid = get_kernel_vsid(ea);
-		context = KERNEL_CONTEXT(ea);
-	} else {
-		if (!current->mm)
-			return 1;
-
-		context = current->mm->context;
-		vsid = get_vsid(context.id, ea);
-	}
-
-	esid = GET_ESID(ea);
-	__ste_allocate(esid, vsid);
-	/* Order update */
-	asm volatile("sync":::"memory");
-
-	return 0;
-}
-
-/*
- * preload some userspace segments into the segment table.
- */
-static void preload_stab(struct task_struct *tsk, struct mm_struct *mm)
-{
-	unsigned long pc = KSTK_EIP(tsk);
-	unsigned long stack = KSTK_ESP(tsk);
-	unsigned long unmapped_base;
-	unsigned long pc_esid = GET_ESID(pc);
-	unsigned long stack_esid = GET_ESID(stack);
-	unsigned long unmapped_base_esid;
-	unsigned long vsid;
-
-	if (test_tsk_thread_flag(tsk, TIF_32BIT))
-		unmapped_base = TASK_UNMAPPED_BASE_USER32;
-	else
-		unmapped_base = TASK_UNMAPPED_BASE_USER64;
-
-	unmapped_base_esid = GET_ESID(unmapped_base);
-
-	if (!IS_VALID_EA(pc) || (REGION_ID(pc) >= KERNEL_REGION_ID))
-		return;
-	vsid = get_vsid(mm->context.id, pc);
-	__ste_allocate(pc_esid, vsid);
-
-	if (pc_esid == stack_esid)
-		return;
-
-	if (!IS_VALID_EA(stack) || (REGION_ID(stack) >= KERNEL_REGION_ID))
-		return;
-	vsid = get_vsid(mm->context.id, stack);
-	__ste_allocate(stack_esid, vsid);
-
-	if (pc_esid == unmapped_base_esid || stack_esid == unmapped_base_esid)
-		return;
-
-	if (!IS_VALID_EA(unmapped_base) ||
-	    (REGION_ID(unmapped_base) >= KERNEL_REGION_ID))
-		return;
-	vsid = get_vsid(mm->context.id, unmapped_base);
-	__ste_allocate(unmapped_base_esid, vsid);
-
-	/* Order update */
-	asm volatile("sync" : : : "memory");
-}
-
-/* Flush all user entries from the segment table of the current processor. */
-void flush_stab(struct task_struct *tsk, struct mm_struct *mm)
-{
-	STE *stab = (STE *) get_paca()->stab_addr;
-	STE *ste;
-	unsigned long offset = __get_cpu_var(stab_cache_ptr);
-
-	/* Force previous translations to complete. DRENG */
-	asm volatile("isync" : : : "memory");
-
-	if (offset <= NR_STAB_CACHE_ENTRIES) {
-		int i;
-
-		for (i = 0; i < offset; i++) {
-			ste = stab + __get_cpu_var(stab_cache[i]);
-			ste->dw0.dw0.v = 0;
-		}
-	} else {
-		unsigned long entry;
-
-		/* Invalidate all entries. */
-		ste = stab;
-
-		/* Never flush the first entry. */
-		ste += 1;
-		for (entry = 1;
-		     entry < (PAGE_SIZE / sizeof(STE));
-		     entry++, ste++) {
-			unsigned long ea;
-			ea = ste->dw0.dw0.esid << SID_SHIFT;
-			if (ea < KERNELBASE) {
-				ste->dw0.dw0.v = 0;
-			}
-		}
-	}
-
-	asm volatile("sync; slbia; sync":::"memory");
-
-	__get_cpu_var(stab_cache_ptr) = 0;
-
-	preload_stab(tsk, mm);
-}
diff -Nru a/arch/ppc64/kernel/sys_ppc32.c b/arch/ppc64/kernel/sys_ppc32.c
--- a/arch/ppc64/kernel/sys_ppc32.c	2004-10-18 14:56:48 -07:00
+++ b/arch/ppc64/kernel/sys_ppc32.c	2004-10-18 14:56:48 -07:00
@@ -72,7 +72,6 @@
 #include <asm/semaphore.h>
 #include <asm/ppcdebug.h>
 #include <asm/time.h>
-#include <asm/ppc32.h>
 #include <asm/mmu_context.h>
 
 #include "pci.h"
@@ -634,8 +633,24 @@
 void start_thread32(struct pt_regs* regs, unsigned long nip, unsigned long sp)
 {
 	set_fs(USER_DS);
-	memset(regs->gpr, 0, sizeof(regs->gpr));
-	memset(&regs->ctr, 0, 4 * sizeof(regs->ctr));
+
+	/*
+	 * If we exec out of a kernel thread then thread.regs will not be
+	 * set. Do it now.
+	 */
+	if (!current->thread.regs) {
+		unsigned long childregs = (unsigned long)current->thread_info +
+						THREAD_SIZE;
+		childregs -= sizeof(struct pt_regs);
+		current->thread.regs = (struct pt_regs *)childregs;
+	}
+
+	/*
+	 * ELF_PLAT_INIT already clears all registers but it also sets r2.
+	 * So just clear r2 here.
+	 */
+	regs->gpr[2] = 0;
+
 	regs->nip = nip;
 	regs->gpr[1] = sp;
 	regs->msr = MSR_USER32;
@@ -700,7 +715,7 @@
 				  (unsigned long) dfn,
 				  (unsigned long) off,
 				  (unsigned long) len,
-				  (unsigned char __user *)AA(ubuf));
+				  compat_ptr(ubuf));
 }
 
 asmlinkage int sys32_pciconfig_write(u32 bus, u32 dfn, u32 off, u32 len, u32 ubuf)
@@ -709,7 +724,7 @@
 				   (unsigned long) dfn,
 				   (unsigned long) off,
 				   (unsigned long) len,
-				   (unsigned char __user *)AA(ubuf));
+				   compat_ptr(ubuf));
 }
 
 #define IOBASE_BRIDGE_NUMBER	0
@@ -1095,7 +1110,7 @@
 	u32 __unused[4];
 };
 
-extern asmlinkage long sys32_sysctl(struct __sysctl_args32 __user *args)
+asmlinkage long sys32_sysctl(struct __sysctl_args32 __user *args)
 {
 	struct __sysctl_args32 tmp;
 	int error;
@@ -1114,19 +1129,20 @@
 		   glibc's __sysctl uses rw memory for the structure
 		   anyway.  */
 		oldlenp = (size_t __user *)addr;
-		if (get_user(oldlen, (u32 __user *)A(tmp.oldlenp)) ||
+		if (get_user(oldlen, (compat_size_t __user *)compat_ptr(tmp.oldlenp)) ||
 		    put_user(oldlen, oldlenp))
 			return -EFAULT;
 	}
 
 	lock_kernel();
-	error = do_sysctl((int __user *)A(tmp.name), tmp.nlen, (void __user *)A(tmp.oldval),
-			  oldlenp, (void __user *)A(tmp.newval), tmp.newlen);
+	error = do_sysctl(compat_ptr(tmp.name), tmp.nlen,
+			  compat_ptr(tmp.oldval), oldlenp,
+			  compat_ptr(tmp.newval), tmp.newlen);
 	unlock_kernel();
 	if (oldlenp) {
 		if (!error) {
 			if (get_user(oldlen, oldlenp) ||
-			    put_user(oldlen, (u32 __user *)A(tmp.oldlenp)))
+			    put_user(oldlen, (compat_size_t __user *)compat_ptr(tmp.oldlenp)))
 				error = -EFAULT;
 		}
 		copy_to_user(args->__unused, tmp.__unused, sizeof(tmp.__unused));
diff -Nru a/arch/ppc64/kernel/sysfs.c b/arch/ppc64/kernel/sysfs.c
--- a/arch/ppc64/kernel/sysfs.c	2004-10-18 14:55:55 -07:00
+++ b/arch/ppc64/kernel/sysfs.c	2004-10-18 14:55:55 -07:00
@@ -5,6 +5,7 @@
 #include <linux/percpu.h>
 #include <linux/init.h>
 #include <linux/sched.h>
+#include <linux/module.h>
 #include <asm/current.h>
 #include <asm/processor.h>
 #include <asm/cputable.h>
@@ -96,6 +97,14 @@
 
 /* PMC stuff */
 
+#ifdef CONFIG_PPC_ISERIES
+void ppc64_enable_pmcs(void)
+{
+	/* XXX Implement for iseries */
+}
+#endif
+
+#ifdef CONFIG_PPC_MULTIPLATFORM
 /*
  * Enabling PMCs will slow partition context switch times so we only do
  * it the first time we write to the PMCs.
@@ -103,18 +112,14 @@
 
 static DEFINE_PER_CPU(char, pmcs_enabled);
 
-#ifdef CONFIG_PPC_ISERIES
-void ppc64_enable_pmcs(void)
-{
-	/* XXX Implement for iseries */
-}
-#else
 void ppc64_enable_pmcs(void)
 {
 	unsigned long hid0;
+#ifdef CONFIG_PPC_PSERIES
 	unsigned long set, reset;
 	int ret;
 	unsigned int ctrl;
+#endif /* CONFIG_PPC_PSERIES */
 
 	/* Only need to enable them once */
 	if (__get_cpu_var(pmcs_enabled))
@@ -123,37 +128,42 @@
 	__get_cpu_var(pmcs_enabled) = 1;
 
 	switch (systemcfg->platform) {
-		case PLATFORM_PSERIES:
-			hid0 = mfspr(HID0);
-			hid0 |= 1UL << (63 - 20);
-
-			/* POWER4 requires the following sequence */
-			asm volatile(
-				"sync\n"
-				"mtspr	%1, %0\n"
-				"mfspr	%0, %1\n"
-				"mfspr	%0, %1\n"
-				"mfspr	%0, %1\n"
-				"mfspr	%0, %1\n"
-				"mfspr	%0, %1\n"
-				"mfspr	%0, %1\n"
-				"isync" : "=&r" (hid0) : "i" (HID0), "0" (hid0):
-				"memory");
-			break;
-
-		case PLATFORM_PSERIES_LPAR:
-			set = 1UL << 63;
-			reset = 0;
-			ret = plpar_hcall_norets(H_PERFMON, set, reset);
-			if (ret)
-				printk(KERN_ERR "H_PERFMON call returned %d",
-				       ret);
-			break;
+	case PLATFORM_PSERIES:
+	case PLATFORM_POWERMAC:
+		hid0 = mfspr(HID0);
+		hid0 |= 1UL << (63 - 20);
+
+		/* POWER4 requires the following sequence */
+		asm volatile(
+			     "sync\n"
+			     "mtspr	%1, %0\n"
+			     "mfspr	%0, %1\n"
+			     "mfspr	%0, %1\n"
+			     "mfspr	%0, %1\n"
+			     "mfspr	%0, %1\n"
+			     "mfspr	%0, %1\n"
+			     "mfspr	%0, %1\n"
+			     "isync" : "=&r" (hid0) : "i" (HID0), "0" (hid0):
+			     "memory");
+		break;
+
+#ifdef CONFIG_PPC_PSERIES
+	case PLATFORM_PSERIES_LPAR:
+		set = 1UL << 63;
+		reset = 0;
+		ret = plpar_hcall_norets(H_PERFMON, set, reset);
+		if (ret)
+			printk(KERN_ERR "H_PERFMON call on cpu %u "
+			       "returned %d\n",
+			       smp_processor_id(), ret);
+		break;
+#endif /* CONFIG_PPC_PSERIES */
 
-		default:
-			break;
+	default:
+		break;
 	}
 
+#ifdef CONFIG_PPC_PSERIES
 	/* instruct hypervisor to maintain PMCs */
 	if (cur_cpu_spec->firmware_features & FW_FEATURE_SPLPAR) {
 		char *ptr = (char *)&paca[smp_processor_id()].lppaca;
@@ -169,8 +179,11 @@
 		ctrl |= RUNLATCH;
 		mtspr(CTRLT, ctrl);
 	}
+#endif /* CONFIG_PPC_PSERIES */
 }
-#endif
+#endif /* CONFIG_PPC_MULTIPLATFORM */
+
+EXPORT_SYMBOL(ppc64_enable_pmcs);
 
 /* XXX convert to rusty's on_one_cpu */
 static unsigned long run_on_cpu(unsigned long cpu,
diff -Nru a/arch/ppc64/kernel/time.c b/arch/ppc64/kernel/time.c
--- a/arch/ppc64/kernel/time.c	2004-10-18 14:57:03 -07:00
+++ b/arch/ppc64/kernel/time.c	2004-10-18 14:57:03 -07:00
@@ -48,6 +48,7 @@
 #include <linux/time.h>
 #include <linux/init.h>
 #include <linux/profile.h>
+#include <linux/cpu.h>
 
 #include <asm/segment.h>
 #include <asm/io.h>
@@ -83,7 +84,7 @@
 #define XSEC_PER_SEC (1024*1024)
 
 unsigned long tb_ticks_per_jiffy;
-unsigned long tb_ticks_per_usec;
+unsigned long tb_ticks_per_usec = 100; /* sane default */
 unsigned long tb_ticks_per_sec;
 unsigned long next_xtime_sync_tb;
 unsigned long xtime_sync_interval;
@@ -101,50 +102,12 @@
 extern unsigned long lpevent_count;
 extern int smp_tb_synchronized;
 
+extern struct timezone sys_tz;
+
 void ppc_adjtimex(void);
 
 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)
 {
         /*
@@ -195,6 +158,19 @@
 	}
 }
 
+#ifdef CONFIG_SMP
+unsigned long profile_pc(struct pt_regs *regs)
+{
+	unsigned long pc = instruction_pointer(regs);
+
+	if (in_lock_functions(pc))
+		return regs->link;
+
+	return pc;
+}
+EXPORT_SYMBOL(profile_pc);
+#endif
+
 #ifdef CONFIG_PPC_ISERIES
 
 /* 
@@ -233,6 +209,8 @@
 				do_gtod.tb_ticks_per_sec = tb_ticks_per_sec;
 				tb_to_xs = divres.result_low;
 				do_gtod.varp->tb_to_xs = tb_to_xs;
+				systemcfg->tb_ticks_per_sec = tb_ticks_per_sec;
+				systemcfg->tb_to_xs = tb_to_xs;
 			}
 			else {
 				printk( "Titan recalibrate: FAILED (difference > 4 percent)\n"
@@ -273,7 +251,7 @@
 	irq_enter();
 
 #ifndef CONFIG_PPC_ISERIES
-	ppc64_do_profile(regs);
+	profile_tick(CPU_PROFILING, regs);
 #endif
 
 	lpaca->lppaca.xIntDword.xFields.xDecrInt = 0;
@@ -281,8 +259,20 @@
 	while (lpaca->next_jiffy_update_tb <= (cur_tb = get_tb())) {
 
 #ifdef CONFIG_SMP
-		smp_local_timer_interrupt(regs);
+		/*
+		 * We cannot disable the decrementer, so in the period
+		 * between this cpu's being marked offline in cpu_online_map
+		 * and calling stop-self, it is taking timer interrupts.
+		 * Avoid calling into the scheduler rebalancing code if this
+		 * is the case.
+		 */
+		if (!cpu_is_offline(cpu))
+			smp_local_timer_interrupt(regs);
 #endif
+		/*
+		 * No need to check whether cpu is offline here; boot_cpuid
+		 * should have been fixed up by now.
+		 */
 		if (cpu == boot_cpuid) {
 			write_seqlock(&xtime_lock);
 			tb_last_stamp = lpaca->next_jiffy_update_tb;
@@ -408,6 +398,7 @@
 	new_xsec += new_sec * XSEC_PER_SEC;
 	if ( new_xsec > delta_xsec ) {
 		do_gtod.varp->stamp_xsec = new_xsec - delta_xsec;
+		systemcfg->stamp_xsec = new_xsec - delta_xsec;
 	}
 	else {
 		/* This is only for the case where the user is setting the time
@@ -416,8 +407,13 @@
 		 * the time to Jan 5, 1970 */
 		do_gtod.varp->stamp_xsec = new_xsec;
 		do_gtod.tb_orig_stamp = tb_last_stamp;
+		systemcfg->stamp_xsec = new_xsec;
+		systemcfg->tb_orig_stamp = tb_last_stamp;
 	}
 
+	systemcfg->tz_minuteswest = sys_tz.tz_minuteswest;
+	systemcfg->tz_dsttime = sys_tz.tz_dsttime;
+
 	write_sequnlock_irqrestore(&xtime_lock, flags);
 	clock_was_set();
 	return 0;
@@ -520,6 +516,11 @@
 	do_gtod.tb_ticks_per_sec = tb_ticks_per_sec;
 	do_gtod.varp->tb_to_xs = tb_to_xs;
 	do_gtod.tb_to_us = tb_to_us;
+	systemcfg->tb_orig_stamp = tb_last_stamp;
+	systemcfg->tb_update_count = 0;
+	systemcfg->tb_ticks_per_sec = tb_ticks_per_sec;
+	systemcfg->stamp_xsec = xtime.tv_sec * XSEC_PER_SEC;
+	systemcfg->tb_to_xs = tb_to_xs;
 
 	xtime_sync_interval = tb_ticks_per_sec - (tb_ticks_per_sec/8);
 	next_xtime_sync_tb = tb_last_stamp + xtime_sync_interval;
@@ -654,6 +655,22 @@
 	mb();
 	do_gtod.varp = temp_varp;
 	do_gtod.var_idx = temp_idx;
+
+	/*
+	 * tb_update_count is used to allow the problem state gettimeofday code
+	 * to assure itself that it sees a consistent view of the tb_to_xs and
+	 * stamp_xsec variables.  It reads the tb_update_count, then reads
+	 * tb_to_xs and stamp_xsec and then reads tb_update_count again.  If
+	 * the two values of tb_update_count match and are even then the
+	 * tb_to_xs and stamp_xsec values are consistent.  If not, then it
+	 * loops back and reads them again until this criteria is met.
+	 */
+	++(systemcfg->tb_update_count);
+	wmb();
+	systemcfg->tb_to_xs = new_tb_to_xs;
+	systemcfg->stamp_xsec = new_stamp_xsec;
+	wmb();
+	++(systemcfg->tb_update_count);
 
 	write_sequnlock_irqrestore( &xtime_lock, flags );
 
diff -Nru a/arch/ppc64/kernel/traps.c b/arch/ppc64/kernel/traps.c
--- a/arch/ppc64/kernel/traps.c	2004-10-18 14:56:32 -07:00
+++ b/arch/ppc64/kernel/traps.c	2004-10-18 14:56:32 -07:00
@@ -134,14 +134,20 @@
 }
 
 static void
-_exception(int signr, siginfo_t *info, struct pt_regs *regs)
+_exception(int signr, struct pt_regs *regs, int code, unsigned long addr)
 {
+	siginfo_t info;
+
 	if (!user_mode(regs)) {
 		if (die("Exception in kernel mode", regs, signr))
 			return;
 	}
 
-	force_sig_info(signr, info, current);
+	memset(&info, 0, sizeof(info));
+	info.si_signo = signr;
+	info.si_code = code;
+	info.si_addr = (void __user *) addr;
+	force_sig_info(signr, &info, current);
 }
 
 #ifdef CONFIG_PPC_PSERIES
@@ -213,27 +219,21 @@
  */
 static int recover_mce(struct pt_regs *regs, struct rtas_error_log err)
 {
-	siginfo_t info;
-
-	if (err.disposition == DISP_FULLY_RECOVERED) {
+	if (err.disposition == RTAS_DISP_FULLY_RECOVERED) {
 		/* Platform corrected itself */
 		return 1;
 	} else if ((regs->msr & MSR_RI) &&
 		   user_mode(regs) &&
-		   err.severity == SEVERITY_ERROR_SYNC &&
-		   err.disposition == DISP_NOT_RECOVERED &&
-		   err.target == TARGET_MEMORY &&
-		   err.type == TYPE_ECC_UNCORR &&
+		   err.severity == RTAS_SEVERITY_ERROR_SYNC &&
+		   err.disposition == RTAS_DISP_NOT_RECOVERED &&
+		   err.target == RTAS_TARGET_MEMORY &&
+		   err.type == RTAS_TYPE_ECC_UNCORR &&
 		   !(current->pid == 0 || current->pid == 1)) {
 		/* Kill off a user process with an ECC error */
-		info.si_signo = SIGBUS;
-		info.si_errno = 0;
-		/* XXX something better for ECC error? */
-		info.si_code = BUS_ADRERR;
-		info.si_addr = (void __user *)regs->nip;
 		printk(KERN_ERR "MCE: uncorrectable ecc error for pid %d\n",
 		       current->pid);
-		_exception(SIGBUS, &info, regs);
+		/* XXX something better for ECC error? */
+		_exception(SIGBUS, regs, BUS_ADRERR, regs->nip);
 		return 1;
 	}
 	return 0;
@@ -278,35 +278,46 @@
 void
 UnknownException(struct pt_regs *regs)
 {
-	siginfo_t info;
-
 	printk("Bad trap at PC: %lx, SR: %lx, vector=%lx\n",
 	       regs->nip, regs->msr, regs->trap);
 
-	info.si_signo = SIGTRAP;
-	info.si_errno = 0;
-	info.si_code = 0;
-	info.si_addr = NULL;
-	_exception(SIGTRAP, &info, regs);	
+	_exception(SIGTRAP, regs, 0, 0);
 }
 
 void
 InstructionBreakpointException(struct pt_regs *regs)
 {
-	siginfo_t info;
-
 	if (debugger_iabr_match(regs))
 		return;
-	info.si_signo = SIGTRAP;
-	info.si_errno = 0;
-	info.si_code = TRAP_BRKPT;
-	info.si_addr = (void __user *)regs->nip;
-	_exception(SIGTRAP, &info, regs);
+	_exception(SIGTRAP, regs, TRAP_BRKPT, regs->nip);
+}
+
+void
+SingleStepException(struct pt_regs *regs)
+{
+	regs->msr &= ~MSR_SE;  /* Turn off 'trace' bit */
+
+	if (debugger_sstep(regs))
+		return;
+
+	_exception(SIGTRAP, regs, TRAP_TRACE, regs->nip);
+}
+
+/*
+ * After we have successfully emulated an instruction, we have to
+ * check if the instruction was being single-stepped, and if so,
+ * pretend we got a single-step exception.  This was pointed out
+ * by Kumar Gala.  -- paulus
+ */
+static inline void emulate_single_step(struct pt_regs *regs)
+{
+	if (regs->msr & MSR_SE)
+		SingleStepException(regs);
 }
 
 static void parse_fpe(struct pt_regs *regs)
 {
-	siginfo_t info;
+	int code = 0;
 	unsigned long fpscr;
 
 	flush_fp_to_thread(current);
@@ -315,31 +326,84 @@
 
 	/* Invalid operation */
 	if ((fpscr & FPSCR_VE) && (fpscr & FPSCR_VX))
-		info.si_code = FPE_FLTINV;
+		code = FPE_FLTINV;
 
 	/* Overflow */
 	else if ((fpscr & FPSCR_OE) && (fpscr & FPSCR_OX))
-		info.si_code = FPE_FLTOVF;
+		code = FPE_FLTOVF;
 
 	/* Underflow */
 	else if ((fpscr & FPSCR_UE) && (fpscr & FPSCR_UX))
-		info.si_code = FPE_FLTUND;
+		code = FPE_FLTUND;
 
 	/* Divide by zero */
 	else if ((fpscr & FPSCR_ZE) && (fpscr & FPSCR_ZX))
-		info.si_code = FPE_FLTDIV;
+		code = FPE_FLTDIV;
 
 	/* Inexact result */
 	else if ((fpscr & FPSCR_XE) && (fpscr & FPSCR_XX))
-		info.si_code = FPE_FLTRES;
+		code = FPE_FLTRES;
+
+	_exception(SIGFPE, regs, code, regs->nip);
+}
+
+/*
+ * Illegal instruction emulation support.  Return non-zero if we can't
+ * emulate, or -EFAULT if the associated memory access caused an access
+ * fault.  Return zero on success.
+ */
+
+#define INST_DCBA		0x7c0005ec
+#define INST_DCBA_MASK		0x7c0007fe
+
+#define INST_MCRXR		0x7c000400
+#define INST_MCRXR_MASK		0x7c0007fe
+
+static int emulate_instruction(struct pt_regs *regs)
+{
+	unsigned int instword;
+
+	if (!user_mode(regs))
+		return -EINVAL;
+
+	CHECK_FULL_REGS(regs);
 
-	else
-		info.si_code = 0;
+	if (get_user(instword, (unsigned int __user *)(regs->nip)))
+		return -EFAULT;
 
-	info.si_signo = SIGFPE;
-	info.si_errno = 0;
-	info.si_addr = (void __user *)regs->nip;
-	_exception(SIGFPE, &info, regs);
+	/* Emulating the dcba insn is just a no-op.  */
+	if ((instword & INST_DCBA_MASK) == INST_DCBA) {
+		static int warned;
+
+		if (!warned) {
+			printk(KERN_WARNING
+			       "process %d (%s) uses obsolete 'dcba' insn\n",
+			       current->pid, current->comm);
+			warned = 1;
+		}
+		return 0;
+	}
+
+	/* Emulate the mcrxr insn.  */
+	if ((instword & INST_MCRXR_MASK) == INST_MCRXR) {
+		static int warned;
+		unsigned int shift;
+
+		if (!warned) {
+			printk(KERN_WARNING
+			       "process %d (%s) uses obsolete 'mcrxr' insn\n",
+			       current->pid, current->comm);
+			warned = 1;
+		}
+
+		shift = (instword >> 21) & 0x1c;
+		regs->ccr &= ~(0xf0000000 >> shift);
+		regs->ccr |= (regs->xer & 0xf0000000) >> shift;
+		regs->xer &= ~0xf0000000;
+		return 0;
+	}
+
+	return -EINVAL;
 }
 
 /*
@@ -395,20 +459,14 @@
 void
 ProgramCheckException(struct pt_regs *regs)
 {
-	siginfo_t info;
-
 	if (regs->msr & 0x100000) {
 		/* IEEE FP exception */
-
 		parse_fpe(regs);
+
 	} else if (regs->msr & 0x40000) {
 		/* Privileged instruction */
+		_exception(SIGILL, regs, ILL_PRVOPC, regs->nip);
 
-		info.si_signo = SIGILL;
-		info.si_errno = 0;
-		info.si_code = ILL_PRVOPC;
-		info.si_addr = (void __user *)regs->nip;
-		_exception(SIGILL, &info, regs);
 	} else if (regs->msr & 0x20000) {
 		/* trap exception */
 
@@ -419,19 +477,24 @@
 			regs->nip += 4;
 			return;
 		}
-		info.si_signo = SIGTRAP;
-		info.si_errno = 0;
-		info.si_code = TRAP_BRKPT;
-		info.si_addr = (void __user *)regs->nip;
-		_exception(SIGTRAP, &info, regs);
+		_exception(SIGTRAP, regs, TRAP_BRKPT, regs->nip);
+
 	} else {
-		/* Illegal instruction */
+		/* Illegal instruction; try to emulate it.  */
+		switch (emulate_instruction(regs)) {
+		case 0:
+			regs->nip += 4;
+			emulate_single_step(regs);
+			break;
 
-		info.si_signo = SIGILL;
-		info.si_errno = 0;
-		info.si_code = ILL_ILLTRP;
-		info.si_addr = (void __user *)regs->nip;
-		_exception(SIGILL, &info, regs);
+		case -EFAULT:
+			_exception(SIGSEGV, regs, SEGV_MAPERR, regs->nip);
+			break;
+
+		default:
+			_exception(SIGILL, regs, ILL_ILLOPC, regs->nip);
+			break;
+		}
 	}
 }
 
@@ -448,13 +511,7 @@
 	if (user_mode(regs)) {
 		/* A user program has executed an altivec instruction,
 		   but this kernel doesn't support altivec. */
-		siginfo_t info;
-
-		memset(&info, 0, sizeof(info));
-		info.si_signo = SIGILL;
-		info.si_code = ILL_ILLOPC;
-		info.si_addr = (void *) regs->nip;
-		_exception(SIGILL, &info, regs);
+		_exception(SIGILL, regs, ILL_ILLOPC, regs->nip);
 		return;
 	}
 #endif
@@ -463,41 +520,22 @@
 	die("Unrecoverable VMX/Altivec Unavailable Exception", regs, SIGABRT);
 }
 
-void
-SingleStepException(struct pt_regs *regs)
-{
-	siginfo_t info;
-
-	regs->msr &= ~MSR_SE;  /* Turn off 'trace' bit */
-
-	if (debugger_sstep(regs))
-		return;
-
-	info.si_signo = SIGTRAP;
-	info.si_errno = 0;
-	info.si_code = TRAP_TRACE;
-	info.si_addr = (void __user *)regs->nip;
-	_exception(SIGTRAP, &info, regs);	
-}
-
-/*
- * After we have successfully emulated an instruction, we have to
- * check if the instruction was being single-stepped, and if so,
- * pretend we got a single-step exception.  This was pointed out
- * by Kumar Gala.  -- paulus
- */
-static inline void emulate_single_step(struct pt_regs *regs)
-{
-	if (regs->msr & MSR_SE)
-		SingleStepException(regs);
-}
+/* Ensure exceptions are disabled */
+#define MMCR0_PMXE      (1UL << (31 - 5))
+#define MMCR0_PMAO      (1UL << (31 - 24))
 
 static void dummy_perf(struct pt_regs *regs)
 {
+	unsigned int mmcr0 = mfspr(SPRN_MMCR0);
+
+	mmcr0 &= ~(MMCR0_PMXE|MMCR0_PMAO);
+	mtspr(SPRN_MMCR0, mmcr0);
 }
 
 void (*perf_irq)(struct pt_regs *) = dummy_perf;
 
+EXPORT_SYMBOL(perf_irq);
+
 void
 PerformanceMonitorException(struct pt_regs *regs)
 {
@@ -508,7 +546,6 @@
 AlignmentException(struct pt_regs *regs)
 {
 	int fixed;
-	siginfo_t info;
 
 	fixed = fix_alignment(regs);
 
@@ -521,11 +558,7 @@
 	/* Operand address was bad */	
 	if (fixed == -EFAULT) {
 		if (user_mode(regs)) {
-			info.si_signo = SIGSEGV;
-			info.si_errno = 0;
-			info.si_code = SEGV_MAPERR;
-			info.si_addr = (void __user *)regs->dar;
-			force_sig_info(SIGSEGV, &info, current);
+			_exception(SIGSEGV, regs, SEGV_MAPERR, regs->dar);
 		} else {
 			/* Search exception table */
 			bad_page_fault(regs, regs->dar, SIGSEGV);
@@ -534,11 +567,7 @@
 		return;
 	}
 
-	info.si_signo = SIGBUS;
-	info.si_errno = 0;
-	info.si_code = BUS_ADRALN;
-	info.si_addr = (void __user *)regs->nip;
-	_exception(SIGBUS, &info, regs);	
+	_exception(SIGBUS, regs, BUS_ADRALN, regs->nip);
 }
 
 #ifdef CONFIG_ALTIVEC
diff -Nru a/arch/ppc64/kernel/u3_iommu.c b/arch/ppc64/kernel/u3_iommu.c
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/arch/ppc64/kernel/u3_iommu.c	2004-10-18 14:57:04 -07:00
@@ -0,0 +1,321 @@
+/*
+ * arch/ppc64/kernel/u3_iommu.c
+ *
+ * Copyright (C) 2004 Olof Johansson <olof@austin.ibm.com>, IBM Corporation
+ *
+ * Based on pSeries_iommu.c:
+ * Copyright (C) 2001 Mike Corrigan & Dave Engebretsen, IBM Corporation
+ * Copyright (C) 2004 Olof Johansson <olof@austin.ibm.com>, IBM Corporation
+ *
+ * Dynamic DMA mapping support, Apple U3 & IBM CPC925 "DART" iommu.
+ *
+ * 
+ * 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
+ */
+
+#include <linux/config.h>
+#include <linux/init.h>
+#include <linux/types.h>
+#include <linux/slab.h>
+#include <linux/mm.h>
+#include <linux/spinlock.h>
+#include <linux/string.h>
+#include <linux/pci.h>
+#include <linux/dma-mapping.h>
+#include <linux/vmalloc.h>
+#include <asm/io.h>
+#include <asm/prom.h>
+#include <asm/ppcdebug.h>
+#include <asm/iommu.h>
+#include <asm/pci-bridge.h>
+#include <asm/machdep.h>
+#include <asm/abs_addr.h>
+#include <asm/cacheflush.h>
+#include <asm/lmb.h>
+
+#include "pci.h"
+
+extern int iommu_force_on;
+
+/* physical base of DART registers */
+#define DART_BASE        0xf8033000UL
+
+/* Offset from base to control register */
+#define DARTCNTL   0
+/* Offset from base to exception register */
+#define DARTEXCP   0x10
+/* Offset from base to TLB tag registers */
+#define DARTTAG    0x1000
+
+
+/* Control Register fields */
+
+/* base address of table (pfn) */
+#define DARTCNTL_BASE_MASK    0xfffff
+#define DARTCNTL_BASE_SHIFT   12
+
+#define DARTCNTL_FLUSHTLB     0x400
+#define DARTCNTL_ENABLE       0x200
+
+/* size of table in pages */
+#define DARTCNTL_SIZE_MASK    0x1ff
+#define DARTCNTL_SIZE_SHIFT   0
+
+/* DART table fields */
+#define DARTMAP_VALID   0x80000000
+#define DARTMAP_RPNMASK 0x00ffffff
+
+/* Physical base address and size of the DART table */
+unsigned long dart_tablebase; /* exported to htab_initialize */
+static unsigned long dart_tablesize;
+
+/* Virtual base address of the DART table */
+static u32 *dart_vbase;
+
+/* Mapped base address for the dart */
+static unsigned int *dart; 
+
+/* Dummy val that entries are set to when unused */
+static unsigned int dart_emptyval;
+
+static struct iommu_table iommu_table_u3;
+static int dart_dirty;
+
+#define DBG(...)
+
+static inline void dart_tlb_invalidate_all(void)
+{
+	unsigned long l = 0;
+	unsigned int reg;
+	unsigned long limit;
+
+	DBG("dart: flush\n");
+
+	/* To invalidate the DART, set the DARTCNTL_FLUSHTLB bit in the
+	 * control register and wait for it to clear.
+	 *
+	 * Gotcha: Sometimes, the DART won't detect that the bit gets
+	 * set. If so, clear it and set it again.
+	 */ 
+
+	limit = 0;
+
+retry:
+	reg = in_be32((unsigned int *)dart+DARTCNTL);
+	reg |= DARTCNTL_FLUSHTLB;
+	out_be32((unsigned int *)dart+DARTCNTL, reg);
+
+	l = 0;
+	while ((in_be32((unsigned int *)dart+DARTCNTL) & DARTCNTL_FLUSHTLB) &&
+		l < (1L<<limit)) {
+		l++;
+	}
+	if (l == (1L<<limit)) {
+		if (limit < 4) {
+			limit++;
+		        reg = in_be32((unsigned int *)dart+DARTCNTL);
+		        reg &= ~DARTCNTL_FLUSHTLB;
+		        out_be32((unsigned int *)dart+DARTCNTL, reg);
+			goto retry;
+		} else
+			panic("U3-DART: TLB did not flush after waiting a long "
+			      "time. Buggy U3 ?");
+	}
+}
+
+static void dart_flush(struct iommu_table *tbl)
+{
+	if (dart_dirty)
+		dart_tlb_invalidate_all();
+	dart_dirty = 0;
+}
+
+static void dart_build(struct iommu_table *tbl, long index, 
+		       long npages, unsigned long uaddr,
+		       enum dma_data_direction direction)
+{
+	unsigned int *dp;
+	unsigned int rpn;
+
+	DBG("dart: build at: %lx, %lx, addr: %x\n", index, npages, uaddr);
+
+	dp = ((unsigned int*)tbl->it_base) + index;
+	
+	/* On U3, all memory is contigous, so we can move this
+	 * out of the loop.
+	 */
+	while (npages--) {
+		rpn = virt_to_abs(uaddr) >> PAGE_SHIFT;
+
+		*(dp++) = DARTMAP_VALID | (rpn & DARTMAP_RPNMASK);
+
+		rpn++;
+		uaddr += PAGE_SIZE;
+	}
+
+	dart_dirty = 1;
+}
+
+
+static void dart_free(struct iommu_table *tbl, long index, long npages)
+{
+	unsigned int *dp;
+	
+	/* We don't worry about flushing the TLB cache. The only drawback of
+	 * not doing it is that we won't catch buggy device drivers doing
+	 * bad DMAs, but then no 32-bit architecture ever does either.
+	 */
+
+	DBG("dart: free at: %lx, %lx\n", index, npages);
+
+	dp  = ((unsigned int *)tbl->it_base) + index;
+		
+	while (npages--)
+		*(dp++) = dart_emptyval;
+}
+
+
+static int dart_init(struct device_node *dart_node)
+{
+	unsigned int regword;
+	unsigned int i;
+	unsigned long tmp;
+	struct page *p;
+
+	if (dart_tablebase == 0 || dart_tablesize == 0) {
+		printk(KERN_INFO "U3-DART: table not allocated, using direct DMA\n");
+		return -ENODEV;
+	}
+
+	/* Make sure nothing from the DART range remains in the CPU cache
+	 * from a previous mapping that existed before the kernel took
+	 * over
+	 */
+	flush_dcache_phys_range(dart_tablebase, dart_tablebase + dart_tablesize);
+
+	/* Allocate a spare page to map all invalid DART pages. We need to do
+	 * that to work around what looks like a problem with the HT bridge
+	 * prefetching into invalid pages and corrupting data
+	 */
+	tmp = __get_free_pages(GFP_ATOMIC, 1);
+	if (tmp == 0)
+		panic("U3-DART: Cannot allocate spare page !");
+	dart_emptyval = DARTMAP_VALID |
+		((virt_to_abs(tmp) >> PAGE_SHIFT) & DARTMAP_RPNMASK);
+
+	/* Map in DART registers. FIXME: Use device node to get base address */
+	dart = ioremap(DART_BASE, 0x7000);
+	if (dart == NULL)
+		panic("U3-DART: Cannot map registers !");
+
+	/* Set initial control register contents: table base, 
+	 * table size and enable bit
+	 */
+	regword = DARTCNTL_ENABLE | 
+		((dart_tablebase >> PAGE_SHIFT) << DARTCNTL_BASE_SHIFT) |
+		(((dart_tablesize >> PAGE_SHIFT) & DARTCNTL_SIZE_MASK)
+				 << DARTCNTL_SIZE_SHIFT);
+	p = virt_to_page(dart_tablebase);
+	dart_vbase = ioremap(virt_to_abs(dart_tablebase), dart_tablesize);
+
+	/* Fill initial table */
+	for (i = 0; i < dart_tablesize/4; i++)
+		dart_vbase[i] = dart_emptyval;
+
+	/* Initialize DART with table base and enable it. */
+	out_be32((unsigned int *)dart, regword);
+
+	/* Invalidate DART to get rid of possible stale TLBs */
+	dart_tlb_invalidate_all();
+
+	iommu_table_u3.it_busno = 0;
+	
+	/* Units of tce entries */
+	iommu_table_u3.it_offset = 0;
+	
+	/* Set the tce table size - measured in pages */
+	iommu_table_u3.it_size = dart_tablesize >> PAGE_SHIFT;
+
+	/* Initialize the common IOMMU code */
+	iommu_table_u3.it_base = (unsigned long)dart_vbase;
+	iommu_table_u3.it_index = 0;
+	iommu_table_u3.it_blocksize = 1;
+	iommu_table_u3.it_entrysize = sizeof(u32);
+	iommu_init_table(&iommu_table_u3);
+
+	/* Reserve the last page of the DART to avoid possible prefetch
+	 * past the DART mapped area
+	 */
+	set_bit(iommu_table_u3.it_mapsize - 1, iommu_table_u3.it_map);
+
+	printk(KERN_INFO "U3/CPC925 DART IOMMU initialized\n");
+
+	return 0;
+}
+
+void iommu_setup_u3(void)
+{
+	struct pci_dev *dev = NULL;
+	struct device_node *dn;
+
+	/* Find the DART in the device-tree */
+	dn = of_find_compatible_node(NULL, "dart", "u3-dart");
+	if (dn == NULL)
+		return;
+
+	/* Setup low level TCE operations for the core IOMMU code */
+	ppc_md.tce_build = dart_build;
+	ppc_md.tce_free  = dart_free;
+	ppc_md.tce_flush = dart_flush;
+
+	/* Initialize the DART HW */
+	if (dart_init(dn))
+		return;
+
+	/* Setup pci_dma ops */
+	pci_iommu_init();
+
+	/* We only have one iommu table on the mac for now, which makes
+	 * things simple. Setup all PCI devices to point to this table
+	 */
+	while ((dev = pci_find_device(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL) {
+		/* We must use pci_device_to_OF_node() to make sure that
+		 * we get the real "final" pointer to the device in the
+		 * pci_dev sysdata and not the temporary PHB one
+		 */
+		struct device_node *dn = pci_device_to_OF_node(dev);
+		if (dn)
+			dn->iommu_table = &iommu_table_u3;
+	}
+}
+
+void __init alloc_u3_dart_table(void)
+{
+	/* Only reserve DART space if machine has more than 2GB of RAM
+	 * or if requested with iommu=on on cmdline.
+	 */
+	if (lmb_end_of_DRAM() <= 0x80000000ull && !iommu_force_on)
+		return;
+
+	/* 512 pages (2MB) is max DART tablesize. */
+	dart_tablesize = 1UL << 21;
+	/* 16MB (1 << 24) alignment. We allocate a full 16Mb chuck since we
+	 * will blow up an entire large page anyway in the kernel mapping
+	 */
+	dart_tablebase = (unsigned long)
+		abs_to_virt(lmb_alloc_base(1UL<<24, 1UL<<24, 0x80000000L));
+
+	printk(KERN_INFO "U3-DART allocated at: %lx\n", dart_tablebase);
+}
diff -Nru a/arch/ppc64/kernel/udbg.c b/arch/ppc64/kernel/udbg.c
--- a/arch/ppc64/kernel/udbg.c	2004-10-18 14:55:54 -07:00
+++ b/arch/ppc64/kernel/udbg.c	2004-10-18 14:55:54 -07:00
@@ -84,23 +84,38 @@
 
 void udbg_init_scc(struct device_node *np)
 {
+	u32 *reg;
 	unsigned long addr;
 	int i, x;
 
 	if (np == NULL)
 		np = of_find_node_by_name(NULL, "escc");
-	if (np == NULL)
+	if (np == NULL || np->parent == NULL)
+		return;
+
+	udbg_printf("found SCC...\n");
+	/* Get address within mac-io ASIC */ 
+	reg = (u32 *)get_property(np, "reg", NULL);
+	if (reg == NULL)
+		return;
+	addr = reg[0];
+	udbg_printf("local addr: %lx\n", addr);
+	/* Get address of mac-io PCI itself */
+	reg = (u32 *)get_property(np->parent, "assigned-addresses", NULL);
+	if (reg == NULL)
 		return;
-	
-	/* Lock-enable the SCC channel */
-	pmac_call_feature(PMAC_FTR_SCC_ENABLE, np, PMAC_SCC_ASYNC | PMAC_SCC_FLAG_XMON, 1);
+	addr += reg[2];
+	udbg_printf("final addr: %lx\n", addr);
 
 	/* Setup for 57600 8N1 */
-	addr = np->addrs[0].address + 0x20;
+	addr += 0x20;
 	sccc = (volatile u8 *) ioremap(addr & PAGE_MASK, PAGE_SIZE) ;
 	sccc += addr & ~PAGE_MASK;
 	sccd = sccc + 0x10;
 
+	udbg_printf("ioremap result sccc: %p\n", sccc);
+	mb();
+
 	for (i = 20000; i != 0; --i)
 		x = *sccc; eieio();
 	*sccc = 9; eieio();		/* reset A or B side */
@@ -119,6 +134,30 @@
 
 #endif /* CONFIG_PPC_PMAC */
 
+#if CONFIG_PPC_PMAC
+extern u8 real_readb(volatile u8 *addr);
+extern void real_writeb(u8 data, volatile u8 *addr);
+
+static void udbg_real_putc(unsigned char c)
+{
+	while ((real_readb(sccc) & SCC_TXRDY) == 0)
+		;
+	real_writeb(c, sccd);
+	if (c == '\n')
+		udbg_real_putc('\r');
+}
+
+void udbg_init_pmac_realmode(void)
+{
+	sccc = (volatile u8 *)0x80013020ul;
+	sccd = (volatile u8 *)0x80013030ul;
+
+	ppc_md.udbg_putc = udbg_real_putc;
+	ppc_md.udbg_getc = NULL;
+	ppc_md.udbg_getc_poll = NULL;
+}
+#endif /* CONFIG_PPC_PMAC */
+
 void udbg_putc(unsigned char c)
 {
 	if (udbg_comport) {
@@ -191,9 +230,12 @@
 			while ((c = *s++) != '\0')
 				ppc_md.udbg_putc(c);
 		}
-	} else {
+	}
+#if 0
+	else {
 		printk("%s", s);
 	}
+#endif
 }
 
 int udbg_write(const char *s, int n)
@@ -218,7 +260,7 @@
 	char c, *p = buf;
 	int i;
 
-	if (!ppc_md.udbg_putc)
+	if (!ppc_md.udbg_getc)
 		return 0;
 
 	for (i = 0; i < buflen; ++i) {
diff -Nru a/arch/ppc64/kernel/vector.S b/arch/ppc64/kernel/vector.S
--- a/arch/ppc64/kernel/vector.S	2004-10-18 14:56:32 -07:00
+++ b/arch/ppc64/kernel/vector.S	2004-10-18 14:56:32 -07:00
@@ -89,7 +89,7 @@
 1:	lfsx	fr0,r4,r7
 	lfsx	fr1,r5,r7
 	lfsx	fr2,r6,r7
-	fmadds	fr0,fr0,fr1,fr2
+	fmadds	fr0,fr0,fr2,fr1
 	stfsx	fr0,r3,r7
 	addi	r7,r7,4
 	bdnz	1b
@@ -109,7 +109,7 @@
 1:	lfsx	fr0,r4,r7
 	lfsx	fr1,r5,r7
 	lfsx	fr2,r6,r7
-	fnmsubs	fr0,fr0,fr1,fr2
+	fnmsubs	fr0,fr0,fr2,fr1
 	stfsx	fr0,r3,r7
 	addi	r7,r7,4
 	bdnz	1b
diff -Nru a/arch/ppc64/kernel/vio.c b/arch/ppc64/kernel/vio.c
--- a/arch/ppc64/kernel/vio.c	2004-10-18 14:56:27 -07:00
+++ b/arch/ppc64/kernel/vio.c	2004-10-18 14:56:27 -07:00
@@ -225,6 +225,10 @@
 	struct vio_dev *viodev;
 	int i;
 
+	/* there is only one of each of these */
+	vio_register_device_iseries("viocons", 0);
+	vio_register_device_iseries("vscsi", 0);
+
 	vlan_map = HvLpConfig_getVirtualLanIndexMap();
 	for (i = 0; i < HVMAXARCHITECTEDVIRTUALLANS; i++) {
 		if ((vlan_map & (0x8000 >> i)) == 0)
diff -Nru a/arch/ppc64/kernel/viopath.c b/arch/ppc64/kernel/viopath.c
--- a/arch/ppc64/kernel/viopath.c	2004-10-18 14:55:55 -07:00
+++ b/arch/ppc64/kernel/viopath.c	2004-10-18 14:55:55 -07:00
@@ -38,8 +38,8 @@
 #include <linux/wait.h>
 #include <linux/seq_file.h>
 #include <linux/smp_lock.h>
+#include <linux/interrupt.h>
 
-#include <asm/hardirq.h>
 #include <asm/system.h>
 #include <asm/uaccess.h>
 #include <asm/iSeries/LparData.h>
diff -Nru a/arch/ppc64/kernel/vmlinux.lds.S b/arch/ppc64/kernel/vmlinux.lds.S
--- a/arch/ppc64/kernel/vmlinux.lds.S	2004-10-18 14:56:49 -07:00
+++ b/arch/ppc64/kernel/vmlinux.lds.S	2004-10-18 14:56:49 -07:00
@@ -14,6 +14,7 @@
   .text : {
 	*(.text .text.*)
 	SCHED_TEXT
+	LOCK_TEXT
 	*(.fixup)
 	. = ALIGN(4096);
 	_etext = .;
@@ -61,12 +62,6 @@
 	__setup_end = .;
 	}
 
-  __param : {
-	__start___param = .;
-	*(__param)
-	__stop___param = .;
-	}
-
   .initcall.init : {
 	__initcall_start = .;
 	*(.initcall1.init)
@@ -122,8 +117,11 @@
 
   .data : {
 	*(.data .data.rel* .toc1)
-	*(.opd)
 	*(.branch_lt)
+	}
+
+  .opd : {
+	*(.opd)
 	}
 
   .got : {
diff -Nru a/arch/ppc64/kernel/xics.c b/arch/ppc64/kernel/xics.c
--- a/arch/ppc64/kernel/xics.c	2004-10-18 14:56:32 -07:00
+++ b/arch/ppc64/kernel/xics.c	2004-10-18 14:56:32 -07:00
@@ -536,7 +536,7 @@
 #ifdef CONFIG_SMP
 		for_each_cpu(i) {
 			/* FIXME: Do this dynamically! --RR */
-			if (!cpu_present_at_boot(i))
+			if (!cpu_present(i))
 				continue;
 			xics_per_cpu[i] = __ioremap((ulong)inodes[get_hard_smp_processor_id(i)].addr, 
 						    (ulong)inodes[get_hard_smp_processor_id(i)].size,
diff -Nru a/arch/ppc64/lib/checksum.S b/arch/ppc64/lib/checksum.S
--- a/arch/ppc64/lib/checksum.S	2004-10-18 14:56:29 -07:00
+++ b/arch/ppc64/lib/checksum.S	2004-10-18 14:56:29 -07:00
@@ -92,19 +92,19 @@
         adde    r5,r5,r6
         bdnz    2b
         andi.	r4,r4,7         /* compute bytes left to sum after doublewords */
-3:	cmpi	0,r4,4		/* is at least a full word left? */
+3:	cmpwi	0,r4,4		/* is at least a full word left? */
 	blt	4f
 	lwz	r6,8(r3)	/* sum this word */
 	addi	r3,r3,4
 	subi	r4,r4,4
 	adde	r5,r5,r6
-4:      cmpi    0,r4,2		/* is at least a halfword left? */
+4:	cmpwi	0,r4,2		/* is at least a halfword left? */
         blt+	5f
         lhz     r6,8(r3)        /* sum this halfword */
         addi    r3,r3,2
         subi    r4,r4,2
         adde    r5,r5,r6
-5:      cmpi    0,r4,1		/* is at least a byte left? */
+5:	cmpwi	0,r4,1		/* is at least a byte left? */
         bne+    6f
         lbz     r6,8(r3)        /* sum this byte */
         slwi    r6,r6,8         /* this byte is assumed to be the upper byte of a halfword */
@@ -150,7 +150,7 @@
 	adde	r0,r0,r6
 	bdnz	82b
 	andi.	r5,r5,3
-3:	cmpi	0,r5,2
+3:	cmpwi	0,r5,2
 	blt+	4f
 83:	lhz	r6,4(r3)
 	addi	r3,r3,2
@@ -158,7 +158,7 @@
 93:	sth	r6,4(r4)
 	addi	r4,r4,2
 	adde	r0,r0,r6
-4:	cmpi	0,r5,1
+4:	cmpwi	0,r5,1
 	bne+	5f
 84:	lbz	r6,4(r3)
 94:	stb	r6,4(r4)
@@ -198,7 +198,7 @@
 	bdnz	97b
 	.globl src_error
 src_error:
-	cmpi	0,r7,0
+	cmpdi	0,r7,0
 	beq	1f
 	li	r6,-EFAULT
 	stw	r6,0(r7)
@@ -207,7 +207,7 @@
 
 	.globl dst_error
 dst_error:
-	cmpi	0,r8,0
+	cmpdi	0,r8,0
 	beq	1f
 	li	r6,-EFAULT
 	stw	r6,0(r8)
diff -Nru a/arch/ppc64/lib/locks.c b/arch/ppc64/lib/locks.c
--- a/arch/ppc64/lib/locks.c	2004-10-18 14:56:33 -07:00
+++ b/arch/ppc64/lib/locks.c	2004-10-18 14:56:33 -07:00
@@ -20,28 +20,9 @@
 #include <asm/hvcall.h>
 #include <asm/iSeries/HvCall.h>
 
-#ifndef CONFIG_SPINLINE
-
-/*
- * On a system with shared processors (that is, where a physical
- * processor is multiplexed between several virtual processors),
- * there is no point spinning on a lock if the holder of the lock
- * isn't currently scheduled on a physical processor.  Instead
- * we detect this situation and ask the hypervisor to give the
- * rest of our timeslice to the lock holder.
- *
- * So that we can tell which virtual processor is holding a lock,
- * we put 0x80000000 | smp_processor_id() in the lock when it is
- * held.  Conveniently, we have a word in the paca that holds this
- * value.
- */
-
 /* waiting for a spinlock... */
 #if defined(CONFIG_PPC_SPLPAR) || defined(CONFIG_PPC_ISERIES)
 
-/* We only yield to the hypervisor if we are in shared processor mode */
-#define SHARED_PROCESSOR (get_paca()->lppaca.xSharedProc)
-
 void __spin_yield(spinlock_t *lock)
 {
 	unsigned int lock_value, holder_cpu, yield_count;
@@ -63,100 +44,16 @@
 	HvCall2(HvCallBaseYieldProcessor, HvCall_YieldToProc,
 		((u64)holder_cpu << 32) | yield_count);
 #else
-	plpar_hcall_norets(H_CONFER, holder_cpu, yield_count);
+	plpar_hcall_norets(H_CONFER, get_hard_smp_processor_id(holder_cpu),
+			   yield_count);
 #endif
 }
 
-#else /* SPLPAR || ISERIES */
-#define __spin_yield(x)	barrier()
-#define SHARED_PROCESSOR	0
-#endif
-
-/*
- * This returns the old value in the lock, so we succeeded
- * in getting the lock if the return value is 0.
- */
-static __inline__ unsigned long __spin_trylock(spinlock_t *lock)
-{
-	unsigned long tmp, tmp2;
-
-	__asm__ __volatile__(
-"	lwz		%1,%3(13)		# __spin_trylock\n\
-1:	lwarx		%0,0,%2\n\
-	cmpwi		0,%0,0\n\
-	bne-		2f\n\
-	stwcx.		%1,0,%2\n\
-	bne-		1b\n\
-	isync\n\
-2:"	: "=&r" (tmp), "=&r" (tmp2)
-	: "r" (&lock->lock), "i" (offsetof(struct paca_struct, lock_token))
-	: "cr0", "memory");
-
-	return tmp;
-}
-
-int _raw_spin_trylock(spinlock_t *lock)
-{
-	return __spin_trylock(lock) == 0;
-}
-
-EXPORT_SYMBOL(_raw_spin_trylock);
-
-void _raw_spin_lock(spinlock_t *lock)
-{
-	while (1) {
-		if (likely(__spin_trylock(lock) == 0))
-			break;
-		do {
-			HMT_low();
-			if (SHARED_PROCESSOR)
-				__spin_yield(lock);
-		} while (likely(lock->lock != 0));
-		HMT_medium();
-	}
-}
-
-EXPORT_SYMBOL(_raw_spin_lock);
-
-void _raw_spin_lock_flags(spinlock_t *lock, unsigned long flags)
-{
-	unsigned long flags_dis;
-
-	while (1) {
-		if (likely(__spin_trylock(lock) == 0))
-			break;
-		local_save_flags(flags_dis);
-		local_irq_restore(flags);
-		do {
-			HMT_low();
-			if (SHARED_PROCESSOR)
-				__spin_yield(lock);
-		} while (likely(lock->lock != 0));
-		HMT_medium();
-		local_irq_restore(flags_dis);
-	}
-}
-
-EXPORT_SYMBOL(_raw_spin_lock_flags);
-
-void spin_unlock_wait(spinlock_t *lock)
-{
-	while (lock->lock) {
-		HMT_low();
-		if (SHARED_PROCESSOR)
-			__spin_yield(lock);
-	}
-	HMT_medium();
-}
-
-EXPORT_SYMBOL(spin_unlock_wait);
-
 /*
  * Waiting for a read lock or a write lock on a rwlock...
  * This turns out to be the same for read and write locks, since
  * we only know the holder if it is write-locked.
  */
-#if defined(CONFIG_PPC_SPLPAR) || defined(CONFIG_PPC_ISERIES)
 void __rw_yield(rwlock_t *rw)
 {
 	int lock_value;
@@ -179,121 +76,20 @@
 	HvCall2(HvCallBaseYieldProcessor, HvCall_YieldToProc,
 		((u64)holder_cpu << 32) | yield_count);
 #else
-	plpar_hcall_norets(H_CONFER, holder_cpu, yield_count);
+	plpar_hcall_norets(H_CONFER, get_hard_smp_processor_id(holder_cpu),
+			   yield_count);
 #endif
 }
-
-#else /* SPLPAR || ISERIES */
-#define __rw_yield(x)	barrier()
 #endif
 
-/*
- * This returns the old value in the lock + 1,
- * so we got a read lock if the return value is > 0.
- */
-static __inline__ long __read_trylock(rwlock_t *rw)
-{
-	long tmp;
-
-	__asm__ __volatile__(
-"1:	lwarx		%0,0,%1		# read_trylock\n\
-	extsw		%0,%0\n\
-	addic.		%0,%0,1\n\
-	ble-		2f\n\
-	stwcx.		%0,0,%1\n\
-	bne-		1b\n\
-	isync\n\
-2:"	: "=&r" (tmp)
-	: "r" (&rw->lock)
-	: "cr0", "xer", "memory");
-
-	return tmp;
-}
-
-int _raw_read_trylock(rwlock_t *rw)
-{
-	return __read_trylock(rw) > 0;
-}
-
-EXPORT_SYMBOL(_raw_read_trylock);
-
-void _raw_read_lock(rwlock_t *rw)
-{
-	while (1) {
-		if (likely(__read_trylock(rw) > 0))
-			break;
-		do {
-			HMT_low();
-			if (SHARED_PROCESSOR)
-				__rw_yield(rw);
-		} while (likely(rw->lock < 0));
-		HMT_medium();
-	}
-}
-
-EXPORT_SYMBOL(_raw_read_lock);
-
-void _raw_read_unlock(rwlock_t *rw)
-{
-	long tmp;
-
-	__asm__ __volatile__(
-	"eieio				# read_unlock\n\
-1:	lwarx		%0,0,%1\n\
-	addic		%0,%0,-1\n\
-	stwcx.		%0,0,%1\n\
-	bne-		1b"
-	: "=&r"(tmp)
-	: "r"(&rw->lock)
-	: "cr0", "memory");
-}
-
-EXPORT_SYMBOL(_raw_read_unlock);
-
-/*
- * This returns the old value in the lock,
- * so we got the write lock if the return value is 0.
- */
-static __inline__ long __write_trylock(rwlock_t *rw)
-{
-	long tmp, tmp2;
-
-	__asm__ __volatile__(
-"	lwz		%1,%3(13)	# write_trylock\n\
-1:	lwarx		%0,0,%2\n\
-	cmpwi		0,%0,0\n\
-	bne-		2f\n\
-	stwcx.		%1,0,%2\n\
-	bne-		1b\n\
-	isync\n\
-2:"	: "=&r" (tmp), "=&r" (tmp2)
-	: "r" (&rw->lock), "i" (offsetof(struct paca_struct, lock_token))
-	: "cr0", "memory");
-
-	return tmp;
-}
-
-int _raw_write_trylock(rwlock_t *rw)
-{
-	return __write_trylock(rw) == 0;
-}
-
-EXPORT_SYMBOL(_raw_write_trylock);
-
-void _raw_write_lock(rwlock_t *rw)
+void spin_unlock_wait(spinlock_t *lock)
 {
-	while (1) {
-		if (likely(__write_trylock(rw) == 0))
-			break;
-		do {
-			HMT_low();
-			if (SHARED_PROCESSOR)
-				__rw_yield(rw);
-		} while (likely(rw->lock != 0));
-		HMT_medium();
+	while (lock->lock) {
+		HMT_low();
+		if (SHARED_PROCESSOR)
+			__spin_yield(lock);
 	}
+	HMT_medium();
 }
 
-EXPORT_SYMBOL(_raw_write_lock);
-
-#endif /* CONFIG_SPINLINE */
+EXPORT_SYMBOL(spin_unlock_wait);
diff -Nru a/arch/ppc64/mm/Makefile b/arch/ppc64/mm/Makefile
--- a/arch/ppc64/mm/Makefile	2004-10-18 14:55:54 -07:00
+++ b/arch/ppc64/mm/Makefile	2004-10-18 14:55:54 -07:00
@@ -4,6 +4,8 @@
 
 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
+obj-y := fault.o init.o imalloc.o hash_utils.o hash_low.o tlb.o \
+	slb_low.o slb.o stab.o mmap.o
 obj-$(CONFIG_DISCONTIGMEM) += numa.o
 obj-$(CONFIG_HUGETLB_PAGE) += hugetlbpage.o
+obj-$(CONFIG_PPC_MULTIPLATFORM) += hash_native.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-10-18 14:56:50 -07:00
+++ b/arch/ppc64/mm/hash_low.S	2004-10-18 14:56:50 -07:00
@@ -172,9 +172,9 @@
 	li	r9,0
 _GLOBAL(htab_call_hpte_insert1)
 	bl	.			/* Will be patched by htab_finish_init() */
-	cmpi	0,r3,0
+	cmpdi	0,r3,0
 	bge	htab_pte_insert_ok	/* Insertion successful */
-	cmpi	0,r3,-2			/* Critical failure */
+	cmpdi	0,r3,-2			/* Critical failure */
 	beq-	htab_pte_insert_failure
 
 	/* Now try secondary slot */
@@ -194,9 +194,9 @@
 	li	r9,0
 _GLOBAL(htab_call_hpte_insert2)
 	bl	.			/* Will be patched by htab_finish_init() */
-	cmpi	0,r3,0
+	cmpdi	0,r3,0
 	bge+	htab_pte_insert_ok	/* Insertion successful */
-	cmpi	0,r3,-2			/* Critical failure */
+	cmpdi	0,r3,-2			/* Critical failure */
 	beq-	htab_pte_insert_failure
 
 	/* Both are full, we need to evict something */
@@ -263,7 +263,7 @@
 	/* if we failed because typically the HPTE wasn't really here
 	 * we try an insertion. 
 	 */
-	cmpi	0,r3,-1
+	cmpdi	0,r3,-1
 	beq-	htab_insert_pte
 
 	/* Clear the BUSY bit and Write out the PTE */
@@ -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_native.c b/arch/ppc64/mm/hash_native.c
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/arch/ppc64/mm/hash_native.c	2004-10-18 14:56:28 -07:00
@@ -0,0 +1,419 @@
+/*
+ * native hashtable management.
+ *
+ * SMP scalability work:
+ *    Copyright (C) 2001 Anton Blanchard <anton@au.ibm.com>, IBM
+ * 
+ * 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/spinlock.h>
+#include <linux/bitops.h>
+#include <linux/threads.h>
+#include <linux/smp.h>
+
+#include <asm/abs_addr.h>
+#include <asm/machdep.h>
+#include <asm/mmu.h>
+#include <asm/mmu_context.h>
+#include <asm/pgtable.h>
+#include <asm/tlbflush.h>
+#include <asm/tlb.h>
+#include <asm/cputable.h>
+
+#define HPTE_LOCK_BIT 3
+
+static spinlock_t native_tlbie_lock = SPIN_LOCK_UNLOCKED;
+
+static inline void native_lock_hpte(HPTE *hptep)
+{
+	unsigned long *word = &hptep->dw0.dword0;
+
+	while (1) {
+		if (!test_and_set_bit(HPTE_LOCK_BIT, word))
+			break;
+		while(test_bit(HPTE_LOCK_BIT, word))
+			cpu_relax();
+	}
+}
+
+static inline void native_unlock_hpte(HPTE *hptep)
+{
+	unsigned long *word = &hptep->dw0.dword0;
+
+	asm volatile("lwsync":::"memory");
+	clear_bit(HPTE_LOCK_BIT, word);
+}
+
+long native_hpte_insert(unsigned long hpte_group, unsigned long va,
+			unsigned long prpn, int secondary,
+			unsigned long hpteflags, int bolted, int large)
+{
+	unsigned long arpn = physRpn_to_absRpn(prpn);
+	HPTE *hptep = htab_data.htab + hpte_group;
+	Hpte_dword0 dw0;
+	HPTE lhpte;
+	int i;
+
+	for (i = 0; i < HPTES_PER_GROUP; i++) {
+		dw0 = hptep->dw0.dw0;
+
+		if (!dw0.v) {
+			/* retry with lock held */
+			native_lock_hpte(hptep);
+			dw0 = hptep->dw0.dw0;
+			if (!dw0.v)
+				break;
+			native_unlock_hpte(hptep);
+		}
+
+		hptep++;
+	}
+
+	if (i == HPTES_PER_GROUP)
+		return -1;
+
+	lhpte.dw1.dword1      = 0;
+	lhpte.dw1.dw1.rpn     = arpn;
+	lhpte.dw1.flags.flags = hpteflags;
+
+	lhpte.dw0.dword0      = 0;
+	lhpte.dw0.dw0.avpn    = va >> 23;
+	lhpte.dw0.dw0.h       = secondary;
+	lhpte.dw0.dw0.bolted  = bolted;
+	lhpte.dw0.dw0.v       = 1;
+
+	if (large) {
+		lhpte.dw0.dw0.l = 1;
+		lhpte.dw0.dw0.avpn &= ~0x1UL;
+	}
+
+	hptep->dw1.dword1 = lhpte.dw1.dword1;
+
+	/* Guarantee the second dword is visible before the valid bit */
+	__asm__ __volatile__ ("eieio" : : : "memory");
+
+	/*
+	 * Now set the first dword including the valid bit
+	 * NOTE: this also unlocks the hpte
+	 */
+	hptep->dw0.dword0 = lhpte.dw0.dword0;
+
+	__asm__ __volatile__ ("ptesync" : : : "memory");
+
+	return i | (secondary << 3);
+}
+
+static long native_hpte_remove(unsigned long hpte_group)
+{
+	HPTE *hptep;
+	Hpte_dword0 dw0;
+	int i;
+	int slot_offset;
+
+	/* pick a random entry to start at */
+	slot_offset = mftb() & 0x7;
+
+	for (i = 0; i < HPTES_PER_GROUP; i++) {
+		hptep = htab_data.htab + hpte_group + slot_offset;
+		dw0 = hptep->dw0.dw0;
+
+		if (dw0.v && !dw0.bolted) {
+			/* retry with lock held */
+			native_lock_hpte(hptep);
+			dw0 = hptep->dw0.dw0;
+			if (dw0.v && !dw0.bolted)
+				break;
+			native_unlock_hpte(hptep);
+		}
+
+		slot_offset++;
+		slot_offset &= 0x7;
+	}
+
+	if (i == HPTES_PER_GROUP)
+		return -1;
+
+	/* Invalidate the hpte. NOTE: this also unlocks it */
+	hptep->dw0.dword0 = 0;
+
+	return i;
+}
+
+static inline void set_pp_bit(unsigned long pp, HPTE *addr)
+{
+	unsigned long old;
+	unsigned long *p = &addr->dw1.dword1;
+
+	__asm__ __volatile__(
+	"1:	ldarx	%0,0,%3\n\
+		rldimi	%0,%2,0,61\n\
+		stdcx.	%0,0,%3\n\
+		bne	1b"
+	: "=&r" (old), "=m" (*p)
+	: "r" (pp), "r" (p), "m" (*p)
+	: "cc");
+}
+
+/*
+ * Only works on small pages. Yes its ugly to have to check each slot in
+ * the group but we only use this during bootup.
+ */
+static long native_hpte_find(unsigned long vpn)
+{
+	HPTE *hptep;
+	unsigned long hash;
+	unsigned long i, j;
+	long slot;
+	Hpte_dword0 dw0;
+
+	hash = hpt_hash(vpn, 0);
+
+	for (j = 0; j < 2; j++) {
+		slot = (hash & htab_data.htab_hash_mask) * HPTES_PER_GROUP;
+		for (i = 0; i < HPTES_PER_GROUP; i++) {
+			hptep = htab_data.htab + slot;
+			dw0 = hptep->dw0.dw0;
+
+			if ((dw0.avpn == (vpn >> 11)) && dw0.v &&
+			    (dw0.h == j)) {
+				/* HPTE matches */
+				if (j)
+					slot = -slot;
+				return slot;
+			}
+			++slot;
+		}
+		hash = ~hash;
+	}
+
+	return -1;
+}
+
+static long native_hpte_updatepp(unsigned long slot, unsigned long newpp,
+				 unsigned long va, int large, int local)
+{
+	HPTE *hptep = htab_data.htab + slot;
+	Hpte_dword0 dw0;
+	unsigned long avpn = va >> 23;
+	int ret = 0;
+
+	if (large)
+		avpn &= ~0x1UL;
+
+	native_lock_hpte(hptep);
+
+	dw0 = hptep->dw0.dw0;
+
+	/* Even if we miss, we need to invalidate the TLB */
+	if ((dw0.avpn != avpn) || !dw0.v) {
+		native_unlock_hpte(hptep);
+		ret = -1;
+	} else {
+		set_pp_bit(newpp, hptep);
+		native_unlock_hpte(hptep);
+	}
+
+	/* Ensure it is out of the tlb too */
+	if ((cur_cpu_spec->cpu_features & CPU_FTR_TLBIEL) && !large && local) {
+		tlbiel(va);
+	} else {
+		int lock_tlbie = !(cur_cpu_spec->cpu_features & CPU_FTR_LOCKLESS_TLBIE);
+
+		if (lock_tlbie)
+			spin_lock(&native_tlbie_lock);
+		tlbie(va, large);
+		if (lock_tlbie)
+			spin_unlock(&native_tlbie_lock);
+	}
+
+	return ret;
+}
+
+/*
+ * Update the page protection bits. Intended to be used to create
+ * guard pages for kernel data structures on pages which are bolted
+ * in the HPT. Assumes pages being operated on will not be stolen.
+ * Does not work on large pages.
+ *
+ * No need to lock here because we should be the only user.
+ */
+static void native_hpte_updateboltedpp(unsigned long newpp, unsigned long ea)
+{
+	unsigned long vsid, va, vpn, flags;
+	long slot;
+	HPTE *hptep;
+	int lock_tlbie = !(cur_cpu_spec->cpu_features & CPU_FTR_LOCKLESS_TLBIE);
+
+	vsid = get_kernel_vsid(ea);
+	va = (vsid << 28) | (ea & 0x0fffffff);
+	vpn = va >> PAGE_SHIFT;
+
+	slot = native_hpte_find(vpn);
+	if (slot == -1)
+		panic("could not find page to bolt\n");
+	hptep = htab_data.htab + slot;
+
+	set_pp_bit(newpp, hptep);
+
+	/* Ensure it is out of the tlb too */
+	if (lock_tlbie)
+		spin_lock_irqsave(&native_tlbie_lock, flags);
+	tlbie(va, 0);
+	if (lock_tlbie)
+		spin_unlock_irqrestore(&native_tlbie_lock, flags);
+}
+
+static void native_hpte_invalidate(unsigned long slot, unsigned long va,
+				    int large, int local)
+{
+	HPTE *hptep = htab_data.htab + slot;
+	Hpte_dword0 dw0;
+	unsigned long avpn = va >> 23;
+	unsigned long flags;
+	int lock_tlbie = !(cur_cpu_spec->cpu_features & CPU_FTR_LOCKLESS_TLBIE);
+
+	if (large)
+		avpn &= ~0x1UL;
+
+	local_irq_save(flags);
+	native_lock_hpte(hptep);
+
+	dw0 = hptep->dw0.dw0;
+
+	/* Even if we miss, we need to invalidate the TLB */
+	if ((dw0.avpn != avpn) || !dw0.v) {
+		native_unlock_hpte(hptep);
+	} else {
+		/* Invalidate the hpte. NOTE: this also unlocks it */
+		hptep->dw0.dword0 = 0;
+	}
+
+	/* Invalidate the tlb */
+	if ((cur_cpu_spec->cpu_features & CPU_FTR_TLBIEL) && !large && local) {
+		tlbiel(va);
+	} else {
+		if (lock_tlbie)
+			spin_lock(&native_tlbie_lock);
+		tlbie(va, large);
+		if (lock_tlbie)
+			spin_unlock(&native_tlbie_lock);
+	}
+	local_irq_restore(flags);
+}
+
+static void native_flush_hash_range(unsigned long context,
+				    unsigned long number, int local)
+{
+	unsigned long vsid, vpn, va, hash, secondary, slot, flags, avpn;
+	int i, j;
+	HPTE *hptep;
+	Hpte_dword0 dw0;
+	struct ppc64_tlb_batch *batch = &__get_cpu_var(ppc64_tlb_batch);
+
+	/* XXX fix for large ptes */
+	unsigned long large = 0;
+
+	local_irq_save(flags);
+
+	j = 0;
+	for (i = 0; i < number; i++) {
+		if ((batch->addr[i] >= USER_START) &&
+		    (batch->addr[i] <= USER_END))
+			vsid = get_vsid(context, batch->addr[i]);
+		else
+			vsid = get_kernel_vsid(batch->addr[i]);
+
+		va = (vsid << 28) | (batch->addr[i] & 0x0fffffff);
+		batch->vaddr[j] = va;
+		if (large)
+			vpn = va >> HPAGE_SHIFT;
+		else
+			vpn = va >> PAGE_SHIFT;
+		hash = hpt_hash(vpn, large);
+		secondary = (pte_val(batch->pte[i]) & _PAGE_SECONDARY) >> 15;
+		if (secondary)
+			hash = ~hash;
+		slot = (hash & htab_data.htab_hash_mask) * HPTES_PER_GROUP;
+		slot += (pte_val(batch->pte[i]) & _PAGE_GROUP_IX) >> 12;
+
+		hptep = htab_data.htab + slot;
+
+		avpn = va >> 23;
+		if (large)
+			avpn &= ~0x1UL;
+
+		native_lock_hpte(hptep);
+
+		dw0 = hptep->dw0.dw0;
+
+		/* Even if we miss, we need to invalidate the TLB */
+		if ((dw0.avpn != avpn) || !dw0.v) {
+			native_unlock_hpte(hptep);
+		} else {
+			/* Invalidate the hpte. NOTE: this also unlocks it */
+			hptep->dw0.dword0 = 0;
+		}
+
+		j++;
+	}
+
+	if ((cur_cpu_spec->cpu_features & CPU_FTR_TLBIEL) && !large && local) {
+		asm volatile("ptesync":::"memory");
+
+		for (i = 0; i < j; i++)
+			__tlbiel(batch->vaddr[i]);
+
+		asm volatile("ptesync":::"memory");
+	} else {
+		int lock_tlbie = !(cur_cpu_spec->cpu_features & CPU_FTR_LOCKLESS_TLBIE);
+
+		if (lock_tlbie)
+			spin_lock(&native_tlbie_lock);
+
+		asm volatile("ptesync":::"memory");
+
+		for (i = 0; i < j; i++)
+			__tlbie(batch->vaddr[i], 0);
+
+		asm volatile("eieio; tlbsync; ptesync":::"memory");
+
+		if (lock_tlbie)
+			spin_unlock(&native_tlbie_lock);
+	}
+
+	local_irq_restore(flags);
+}
+
+void hpte_init_native(void)
+{
+#ifdef CONFIG_PPC_PSERIES
+	struct device_node *root;
+	const char *model;
+#endif /* CONFIG_PPC_PSERIES */
+
+	ppc_md.hpte_invalidate	= native_hpte_invalidate;
+	ppc_md.hpte_updatepp	= native_hpte_updatepp;
+	ppc_md.hpte_updateboltedpp = native_hpte_updateboltedpp;
+	ppc_md.hpte_insert	= native_hpte_insert;
+	ppc_md.hpte_remove     	= native_hpte_remove;
+
+#ifdef CONFIG_PPC_PSERIES
+	/* Disable TLB batching on nighthawk */
+	root = of_find_node_by_path("/");
+	if (root) {
+		model = get_property(root, "model", NULL);
+		if (!strcmp(model, "CHRP IBM,9076-N81")) {
+			of_node_put(root);
+			goto bail;
+		}
+		of_node_put(root);
+	}
+#endif /* CONFIG_PPC_PSERIES */
+
+	ppc_md.flush_hash_range = native_flush_hash_range;
+ bail:
+	htab_finish_init();
+}
diff -Nru a/arch/ppc64/mm/hash_utils.c b/arch/ppc64/mm/hash_utils.c
--- a/arch/ppc64/mm/hash_utils.c	2004-10-18 14:56:33 -07:00
+++ b/arch/ppc64/mm/hash_utils.c	2004-10-18 14:56:33 -07:00
@@ -18,6 +18,8 @@
  * 2 of the License, or (at your option) any later version.
  */
 
+#undef DEBUG
+
 #include <linux/config.h>
 #include <linux/spinlock.h>
 #include <linux/errno.h>
@@ -28,6 +30,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>
@@ -50,6 +53,12 @@
 #include <asm/cputable.h>
 #include <asm/abs_addr.h>
 
+#ifdef DEBUG
+#define DBG(fmt...) udbg_printf(fmt)
+#else
+#define DBG(fmt...)
+#endif
+
 /*
  * Note:  pte   --> Linux PTE
  *        HPTE  --> PowerPC Hashed Page Table Entry
@@ -62,9 +71,9 @@
  *
  */
 
-#ifdef CONFIG_PMAC_DART
+#ifdef CONFIG_U3_DART
 extern unsigned long dart_tablebase;
-#endif /* CONFIG_PMAC_DART */
+#endif /* CONFIG_U3_DART */
 
 HTAB htab_data = {NULL, 0, 0, 0, 0};
 
@@ -80,7 +89,7 @@
 		;
 }
 
-#ifdef CONFIG_PPC_PSERIES
+#ifdef CONFIG_PPC_MULTIPLATFORM
 static inline void create_pte_mapping(unsigned long start, unsigned long end,
 				      unsigned long mode, int large)
 {
@@ -99,7 +108,7 @@
 		int ret;
 
 		if (large)
-			vpn = va >> LARGE_PAGE_SHIFT;
+			vpn = va >> HPAGE_SHIFT;
 		else
 			vpn = va >> PAGE_SHIFT;
 
@@ -107,12 +116,14 @@
 
 		hpteg = ((hash & htab_data.htab_hash_mask)*HPTES_PER_GROUP);
 
-		if (systemcfg->platform == PLATFORM_PSERIES_LPAR)
+#ifdef CONFIG_PPC_PSERIES
+		if (systemcfg->platform & PLATFORM_LPAR)
 			ret = pSeries_lpar_hpte_insert(hpteg, va,
 				virt_to_abs(addr) >> PAGE_SHIFT,
 				0, mode, 1, large);
 		else
-			ret = pSeries_hpte_insert(hpteg, va,
+#endif /* CONFIG_PPC_PSERIES */
+			ret = native_hpte_insert(hpteg, va,
 				virt_to_abs(addr) >> PAGE_SHIFT,
 				0, mode, 1, large);
 
@@ -130,6 +141,8 @@
 	unsigned long mode_rw;
 	int i, use_largepages = 0;
 
+	DBG(" -> htab_initialize()\n");
+
 	/*
 	 * Calculate the required size of the htab.  We want the number of
 	 * PTEGs to equal one half the number of real pages.
@@ -146,12 +159,19 @@
 	htab_data.htab_num_ptegs = pteg_count;
 	htab_data.htab_hash_mask = pteg_count - 1;
 
-	if (systemcfg->platform == PLATFORM_PSERIES ||
-	    systemcfg->platform == PLATFORM_POWERMAC) {
+	if (systemcfg->platform & PLATFORM_LPAR) {
+		/* Using a hypervisor which owns the htab */
+		htab_data.htab = NULL;
+		_SDR1 = 0; 
+	} else {
 		/* Find storage for the HPT.  Must be contiguous in
 		 * the absolute address space.
 		 */
 		table = lmb_alloc(htab_size_bytes, htab_size_bytes);
+
+		DBG("Hash table allocated at %lx, size: %lx\n", table,
+		    htab_size_bytes);
+
 		if ( !table ) {
 			ppc64_terminate_msg(0x20, "hpt space");
 			loop_forever();
@@ -163,10 +183,6 @@
 
 		/* Initialize the HPT with no entries */
 		memset((void *)table, 0, htab_size_bytes);
-	} else {
-		/* Using a hypervisor which owns the htab */
-		htab_data.htab = NULL;
-		_SDR1 = 0; 
 	}
 
 	mode_rw = _PAGE_ACCESSED | _PAGE_COHERENT | PP_RWXX;
@@ -178,14 +194,16 @@
 	if (cur_cpu_spec->cpu_features & CPU_FTR_16M_PAGE)
 		use_largepages = 1;
 
-	/* add all physical memory to the bootmem map */
+	/* create bolted the linear mapping in the hash table */
 	for (i=0; i < lmb.memory.cnt; i++) {
 		unsigned long base, size;
 
 		base = lmb.memory.region[i].physbase + KERNELBASE;
 		size = lmb.memory.region[i].size;
 
-#ifdef CONFIG_PMAC_DART
+		DBG("creating mapping for region: %lx : %lx\n", base, size);
+
+#ifdef CONFIG_U3_DART
 		/* Do not map the DART space. Fortunately, it will be aligned
 		 * in such a way that it will not cross two lmb regions and will
 		 * fit within a single 16Mb page.
@@ -193,6 +211,8 @@
 		 * only use 2Mb of that space. We will use more of it later for
 		 * AGP GART. We have to use a full 16Mb large page.
 		 */
+		DBG("DART base: %lx\n", dart_tablebase);
+
 		if (dart_tablebase != 0 && dart_tablebase >= base
 		    && dart_tablebase < (base + size)) {
 			if (base != dart_tablebase)
@@ -203,13 +223,14 @@
 						   mode_rw, use_largepages);
 			continue;
 		}
-#endif /* CONFIG_PMAC_DART */
+#endif /* CONFIG_U3_DART */
 		create_pte_mapping(base, base + size, mode_rw, use_largepages);
 	}
+	DBG(" <- htab_initialize()\n");
 }
 #undef KB
 #undef MB
-#endif
+#endif /* CONFIG_PPC_MULTIPLATFORM */
 
 /*
  * Called by asm hashtable.S for doing lazy icache flush
@@ -236,14 +257,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;
@@ -255,24 +273,24 @@
 	int local = 0;
 	cpumask_t tmp;
 
-	/* Check for invalid addresses. */
-	if (!IS_VALID_EA(ea))
-		return 1;
-
  	switch (REGION_ID(ea)) {
 	case USER_REGION_ID:
 		user_region = 1;
 		mm = current->mm;
-		if (mm == NULL)
+		if ((ea > USER_END) || (! mm))
 			return 1;
 
 		vsid = get_vsid(mm->context.id, ea);
 		break;
 	case IO_REGION_ID:
+		if (ea > IMALLOC_END)
+			return 1;
 		mm = &ioremap_mm;
 		vsid = get_kernel_vsid(ea);
 		break;
 	case VMALLOC_REGION_ID:
+		if (ea > VMALLOC_END)
+			return 1;
 		mm = &init_mm;
 		vsid = get_kernel_vsid(ea);
 		break;
@@ -334,7 +352,7 @@
 
 	va = (vsid << 28) | (ea & 0x0fffffff);
 	if (large)
-		vpn = va >> LARGE_PAGE_SHIFT;
+		vpn = va >> HPAGE_SHIFT;
 	else
 		vpn = va >> PAGE_SHIFT;
 	hash = hpt_hash(vpn, large);
@@ -369,6 +387,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/hugetlbpage.c b/arch/ppc64/mm/hugetlbpage.c
--- a/arch/ppc64/mm/hugetlbpage.c	2004-10-18 14:56:32 -07:00
+++ b/arch/ppc64/mm/hugetlbpage.c	2004-10-18 14:56:32 -07:00
@@ -527,6 +527,108 @@
 	return -ENOMEM;
 }
 
+/*
+ * This mmap-allocator allocates new areas top-down from below the
+ * stack's low limit (the base):
+ *
+ * Because we have an exclusive hugepage region which lies within the
+ * normal user address space, we have to take special measures to make
+ * non-huge mmap()s evade the hugepage reserved regions.
+ */
+unsigned long
+arch_get_unmapped_area_topdown(struct file *filp, const unsigned long addr0,
+			  const unsigned long len, const unsigned long pgoff,
+			  const unsigned long flags)
+{
+	struct vm_area_struct *vma, *prev_vma;
+	struct mm_struct *mm = current->mm;
+	unsigned long base = mm->mmap_base, addr = addr0;
+	int first_time = 1;
+
+	/* requested length too big for entire address space */
+	if (len > TASK_SIZE)
+		return -ENOMEM;
+
+	/* dont allow allocations above current base */
+	if (mm->free_area_cache > base)
+		mm->free_area_cache = base;
+
+	/* requesting a specific address */
+	if (addr) {
+		addr = PAGE_ALIGN(addr);
+		vma = find_vma(mm, addr);
+		if (TASK_SIZE - len >= addr &&
+				(!vma || addr + len <= vma->vm_start)
+				&& !is_hugepage_only_range(addr,len))
+			return addr;
+	}
+
+try_again:
+	/* make sure it can fit in the remaining address space */
+	if (mm->free_area_cache < len)
+		goto fail;
+
+	/* either no address requested or cant fit in requested address hole */
+	addr = (mm->free_area_cache - len) & PAGE_MASK;
+	do {
+hugepage_recheck:
+		if (touches_hugepage_low_range(addr, len)) {
+			addr = (addr & ((~0) << SID_SHIFT)) - len;
+			goto hugepage_recheck;
+		} else if (touches_hugepage_high_range(addr, len)) {
+			addr = TASK_HPAGE_BASE - len;
+		}
+
+		/*
+		 * Lookup failure means no vma is above this address,
+		 * i.e. return with success:
+		 */
+ 	 	if (!(vma = find_vma_prev(mm, addr, &prev_vma)))
+			return addr;
+
+		/*
+		 * new region fits between prev_vma->vm_end and
+		 * vma->vm_start, use it:
+		 */
+		if (addr+len <= vma->vm_start &&
+				(!prev_vma || (addr >= prev_vma->vm_end)))
+			/* remember the address as a hint for next time */
+			return (mm->free_area_cache = addr);
+		else
+			/* pull free_area_cache down to the first hole */
+			if (mm->free_area_cache == vma->vm_end)
+				mm->free_area_cache = vma->vm_start;
+
+		/* try just below the current vma->vm_start */
+		addr = vma->vm_start-len;
+	} while (len <= vma->vm_start);
+
+fail:
+	/*
+	 * if hint left us with no space for the requested
+	 * mapping then try again:
+	 */
+	if (first_time) {
+		mm->free_area_cache = base;
+		first_time = 0;
+		goto try_again;
+	}
+	/*
+	 * A failed mmap() very likely causes application failure,
+	 * so fall back to the bottom-up function here. This scenario
+	 * can happen with large stack limits and large mmap()
+	 * allocations.
+	 */
+	mm->free_area_cache = TASK_UNMAPPED_BASE;
+	addr = arch_get_unmapped_area(filp, addr0, len, pgoff, flags);
+	/*
+	 * Restore the topdown base:
+	 */
+	mm->free_area_cache = base;
+
+	return addr;
+}
+
 static unsigned long htlb_get_low_area(unsigned long len, u16 segmask)
 {
 	unsigned long addr = 0;
@@ -751,7 +853,7 @@
 	vsid = get_vsid(context.id, ea);
 
 	va = (vsid << 28) | (ea & 0x0fffffff);
-	vpn = va >> LARGE_PAGE_SHIFT;
+	vpn = va >> HPAGE_SHIFT;
 	hash = hpt_hash(vpn, 1);
 	if (hugepte_val(pte) & _HUGEPAGE_SECONDARY)
 		hash = ~hash;
diff -Nru a/arch/ppc64/mm/imalloc.c b/arch/ppc64/mm/imalloc.c
--- a/arch/ppc64/mm/imalloc.c	2004-10-18 14:56:27 -07:00
+++ b/arch/ppc64/mm/imalloc.c	2004-10-18 14:56:27 -07:00
@@ -37,33 +37,51 @@
 	return 0;
 }
 
+/* Return whether the region described by v_addr and size is a subset
+ * of the region described by parent
+ */
+static inline int im_region_is_subset(unsigned long v_addr, unsigned long size,
+			struct vm_struct *parent)
+{
+	return (int) (v_addr >= (unsigned long) parent->addr &&
+	              v_addr < (unsigned long) parent->addr + parent->size &&
+	    	      size < parent->size);
+}
+
+/* Return whether the region described by v_addr and size is a superset
+ * of the region described by child
+ */
+static int im_region_is_superset(unsigned long v_addr, unsigned long size,
+		struct vm_struct *child)
+{
+	struct vm_struct parent;
+
+	parent.addr = (void *) v_addr;
+	parent.size = size;
+
+	return im_region_is_subset((unsigned long) child->addr, child->size,
+			&parent);
+}
+
 /* Return whether the region described by v_addr and size overlaps
- * the region described by vm.  Overlapping regions meet the 
+ * the region described by vm.  Overlapping regions meet the
  * following conditions:
  * 1) The regions share some part of the address space
  * 2) The regions aren't identical
- * 3) The first region is not a subset of the second
+ * 3) Neither region is a subset of the other
  */
-static inline int im_region_overlaps(unsigned long v_addr, unsigned long size,
+static int im_region_overlaps(unsigned long v_addr, unsigned long size,
 		     struct vm_struct *vm)
 {
+	if (im_region_is_superset(v_addr, size, vm))
+		return 0;
+
 	return (v_addr + size > (unsigned long) vm->addr + vm->size &&
 		v_addr < (unsigned long) vm->addr + vm->size) ||
 	       (v_addr < (unsigned long) vm->addr &&
 		v_addr + size > (unsigned long) vm->addr);
 }
 
-/* Return whether the region described by v_addr and size is a subset
- * of the region described by vm
- */
-static inline int im_region_is_subset(unsigned long v_addr, unsigned long size,
-			struct vm_struct *vm)
-{
-	return (int) (v_addr >= (unsigned long) vm->addr && 
-	              v_addr < (unsigned long) vm->addr + vm->size &&
-	    	      size < vm->size);
-}
-
 /* Determine imalloc status of region described by v_addr and size.
  * Can return one of the following:
  * IM_REGION_UNUSED   -  Entire region is unallocated in imalloc space.
@@ -73,28 +91,37 @@
  * IM_REGION_EXISTS -    Exact region already allocated in imalloc space.
  *                       vm will be assigned to a ptr to the existing imlist
  *                       member.
- * IM_REGION_OVERLAPS -  A portion of the region is already allocated in 
- *                       imalloc space.
+ * IM_REGION_OVERLAPS -  Region overlaps an allocated region in imalloc space.
+ * IM_REGION_SUPERSET -  Region is a superset of a region that is already
+ *                       allocated in imalloc space.
  */
-static int im_region_status(unsigned long v_addr, unsigned long size, 
+static int im_region_status(unsigned long v_addr, unsigned long size,
 		    struct vm_struct **vm)
 {
 	struct vm_struct *tmp;
 
-	for (tmp = imlist; tmp; tmp = tmp->next) 
-		if (v_addr < (unsigned long) tmp->addr + tmp->size) 
+	for (tmp = imlist; tmp; tmp = tmp->next)
+		if (v_addr < (unsigned long) tmp->addr + tmp->size)
 			break;
-					
+
 	if (tmp) {
 		if (im_region_overlaps(v_addr, size, tmp))
 			return IM_REGION_OVERLAP;
 
 		*vm = tmp;
-		if (im_region_is_subset(v_addr, size, tmp))
+		if (im_region_is_subset(v_addr, size, tmp)) {
+			/* Return with tmp pointing to superset */
 			return IM_REGION_SUBSET;
-		else if (v_addr == (unsigned long) tmp->addr && 
-		 	 size == tmp->size) 
+		}
+		if (im_region_is_superset(v_addr, size, tmp)) {
+			/* Return with tmp pointing to first subset */
+			return IM_REGION_SUPERSET;
+		}
+		else if (v_addr == (unsigned long) tmp->addr &&
+		 	 size == tmp->size) {
+			/* Return with tmp pointing to exact region */
 			return IM_REGION_EXISTS;
+		}
 	}
 
 	*vm = NULL;
@@ -208,6 +235,10 @@
 		tmp = split_im_region(req_addr, size, tmp);
 		break;
 	case IM_REGION_EXISTS:
+		/* Return requested region */
+		break;
+	case IM_REGION_SUPERSET:
+		/* Return first existing subset of requested region */
 		break;
 	default:
 		printk(KERN_ERR "%s() unexpected imalloc region status\n",
diff -Nru a/arch/ppc64/mm/init.c b/arch/ppc64/mm/init.c
--- a/arch/ppc64/mm/init.c	2004-10-18 14:56:33 -07:00
+++ b/arch/ppc64/mm/init.c	2004-10-18 14:56:33 -07:00
@@ -36,6 +36,7 @@
 #include <linux/delay.h>
 #include <linux/bootmem.h>
 #include <linux/highmem.h>
+#include <linux/idr.h>
 
 #include <asm/pgalloc.h>
 #include <asm/page.h>
@@ -62,8 +63,6 @@
 #include <asm/iommu.h>
 #include <asm/abs_addr.h>
 
-
-struct mmu_context_queue_t mmu_context_queue;
 int mem_init_done;
 unsigned long ioremap_bot = IMALLOC_BASE;
 static unsigned long phbs_io_bot = PHBS_IO_BASE;
@@ -85,7 +84,6 @@
 /* info on what we think the IO hole is */
 unsigned long 	io_hole_start;
 unsigned long	io_hole_size;
-unsigned long	top_of_ram;
 
 void show_mem(void)
 {
@@ -118,18 +116,18 @@
 
 #ifdef CONFIG_PPC_ISERIES
 
-void *ioremap(unsigned long addr, unsigned long size)
+void __iomem *ioremap(unsigned long addr, unsigned long size)
 {
-	return (void *)addr;
+	return (void __iomem *)addr;
 }
 
-extern void *__ioremap(unsigned long addr, unsigned long size,
+extern void __iomem *__ioremap(unsigned long addr, unsigned long size,
 		       unsigned long flags)
 {
-	return (void *)addr;
+	return (void __iomem *)addr;
 }
 
-void iounmap(void *addr)
+void iounmap(volatile void __iomem *addr)
 {
 	return;
 }
@@ -183,7 +181,7 @@
 }
 
 
-static void * __ioremap_com(unsigned long addr, unsigned long pa,
+static void __iomem * __ioremap_com(unsigned long addr, unsigned long pa,
 			    unsigned long ea, unsigned long size,
 			    unsigned long flags)
 {
@@ -198,20 +196,17 @@
 		map_io_page(ea+i, pa+i, flags);
 	}
 
-	return (void *) (ea + (addr & ~PAGE_MASK));
+	return (void __iomem *) (ea + (addr & ~PAGE_MASK));
 }
 
 
-void *
+void __iomem *
 ioremap(unsigned long addr, unsigned long size)
 {
-	void *ret = __ioremap(addr, size, _PAGE_NO_CACHE);
-	if(mem_init_done)
-		return eeh_ioremap(addr, ret);	/* may remap the addr */
-	return ret;
+	return __ioremap(addr, size, _PAGE_NO_CACHE);
 }
 
-void *
+void __iomem *
 __ioremap(unsigned long addr, unsigned long size, unsigned long flags)
 {
 	unsigned long pa, ea;
@@ -354,19 +349,18 @@
  *
  * XXX	what about calls before mem_init_done (ie python_countermeasures())	
  */
-void iounmap(void *addr)
+void iounmap(volatile void __iomem *token)
 {
 	unsigned long address, start, end, size;
 	struct mm_struct *mm;
 	pgd_t *dir;
+	void *addr;
 
 	if (!mem_init_done) {
 		return;
 	}
 	
-	/* addr could be in EEH or IO region, map it to IO region regardless.
-	 */
-	addr = (void *) (IO_TOKEN_TO_ADDR(addr) & PAGE_MASK);
+	addr = (void *) ((unsigned long __force) token & PAGE_MASK);
 	
 	if ((size = im_free(addr)) == 0) {
 		return;
@@ -392,27 +386,55 @@
 	return;
 }
 
-int iounmap_explicit(void *addr, unsigned long size)
+static int iounmap_subset_regions(unsigned long addr, unsigned long size)
 {
 	struct vm_struct *area;
+
+	/* Check whether subsets of this region exist */
+	area = im_get_area(addr, size, IM_REGION_SUPERSET);
+	if (area == NULL)
+		return 1;
+
+	while (area) {
+		iounmap((void __iomem *) area->addr);
+		area = im_get_area(addr, size,
+				IM_REGION_SUPERSET);
+	}
+
+	return 0;
+}
+
+int iounmap_explicit(volatile void __iomem *start, unsigned long size)
+{
+	struct vm_struct *area;
+	unsigned long addr;
+	int rc;
 	
-	/* addr could be in EEH or IO region, map it to IO region regardless.
-	 */
-	addr = (void *) (IO_TOKEN_TO_ADDR(addr) & PAGE_MASK);
+	addr = (unsigned long __force) start & PAGE_MASK;
 
 	/* Verify that the region either exists or is a subset of an existing
 	 * region.  In the latter case, split the parent region to create 
 	 * the exact region 
 	 */
-	area = im_get_area((unsigned long) addr, size, 
+	area = im_get_area(addr, size, 
 			    IM_REGION_EXISTS | IM_REGION_SUBSET);
 	if (area == NULL) {
-		printk(KERN_ERR "%s() cannot unmap nonexistent range 0x%lx\n",
-				__FUNCTION__, (unsigned long) addr);
-		return 1;
+		/* Determine whether subset regions exist.  If so, unmap */
+		rc = iounmap_subset_regions(addr, size);
+		if (rc) {
+			printk(KERN_ERR
+			       "%s() cannot unmap nonexistent range 0x%lx\n",
+ 				__FUNCTION__, addr);
+			return 1;
+		}
+	} else {
+		iounmap((void __iomem *) area->addr);
 	}
-
+	/*
+	 * FIXME! This can't be right:
 	iounmap(area->addr);
+	 * Maybe it should be "iounmap(area);"
+	 */
 	return 0;
 }
 
@@ -447,41 +469,81 @@
 }
 #endif
 
+static spinlock_t mmu_context_lock = SPIN_LOCK_UNLOCKED;
+static DEFINE_IDR(mmu_context_idr);
+
+int init_new_context(struct task_struct *tsk, struct mm_struct *mm)
+{
+	int index;
+	int err;
+
+again:
+	if (!idr_pre_get(&mmu_context_idr, GFP_KERNEL))
+		return -ENOMEM;
+
+	spin_lock(&mmu_context_lock);
+	err = idr_get_new(&mmu_context_idr, NULL, &index);
+	spin_unlock(&mmu_context_lock);
+
+	if (err == -EAGAIN)
+		goto again;
+	else if (err)
+		return err;
+
+	if (index > MAX_CONTEXT) {
+		idr_remove(&mmu_context_idr, index);
+		return -ENOMEM;
+	}
+
+	mm->context.id = index;
+
+	return 0;
+}
+
+void destroy_context(struct mm_struct *mm)
+{
+	spin_lock(&mmu_context_lock);
+	idr_remove(&mmu_context_idr, mm->context.id);
+	spin_unlock(&mmu_context_lock);
+
+	mm->context.id = NO_CONTEXT;
+}
+
+static int __init mmu_context_init(void)
+{
+	int index;
+
+	/* Reserve the first (invalid) context*/
+	idr_pre_get(&mmu_context_idr, GFP_KERNEL);
+	idr_get_new(&mmu_context_idr, NULL, &index);
+	BUG_ON(0 != index);
+
+	return 0;
+}
+arch_initcall(mmu_context_init);
+
 /*
  * Do very early mm setup.
  */
 void __init mm_init_ppc64(void)
 {
+#ifndef CONFIG_PPC_ISERIES
 	unsigned long i;
+#endif
 
 	ppc64_boot_msg(0x100, "MM Init");
 
-	/* Reserve all contexts < FIRST_USER_CONTEXT for kernel use.
-	 * The range of contexts [FIRST_USER_CONTEXT, NUM_USER_CONTEXT)
-	 * are stored on a stack/queue for easy allocation and deallocation.
-	 */
-	mmu_context_queue.lock = SPIN_LOCK_UNLOCKED;
-	mmu_context_queue.head = 0;
-	mmu_context_queue.tail = NUM_USER_CONTEXT-1;
-	mmu_context_queue.size = NUM_USER_CONTEXT;
-	for (i = 0; i < NUM_USER_CONTEXT; i++)
-		mmu_context_queue.elements[i] = i + FIRST_USER_CONTEXT;
-
 	/* This is the story of the IO hole... please, keep seated,
 	 * unfortunately, we are out of oxygen masks at the moment.
 	 * So we need some rough way to tell where your big IO hole
 	 * is. On pmac, it's between 2G and 4G, on POWER3, it's around
 	 * that area as well, on POWER4 we don't have one, etc...
-	 * We need that to implement something approx. decent for
-	 * page_is_ram() so that /dev/mem doesn't map cacheable IO space
-	 * when XFree resquest some IO regions witout using O_SYNC, we
-	 * also need that as a "hint" when sizing the TCE table on POWER3
+	 * We need that as a "hint" when sizing the TCE table on POWER3
 	 * So far, the simplest way that seem work well enough for us it
 	 * to just assume that the first discontinuity in our physical
 	 * RAM layout is the IO hole. That may not be correct in the future
 	 * (and isn't on iSeries but then we don't care ;)
 	 */
-	top_of_ram = lmb_end_of_DRAM();
 
 #ifndef CONFIG_PPC_ISERIES
 	for (i = 1; i < lmb.memory.cnt; i++) {
@@ -504,22 +566,32 @@
 	ppc64_boot_msg(0x100, "MM Init Done");
 }
 
-
 /*
  * This is called by /dev/mem to know if a given address has to
  * be mapped non-cacheable or not
  */
-int page_is_ram(unsigned long physaddr)
+int page_is_ram(unsigned long pfn)
 {
-#ifdef CONFIG_PPC_ISERIES
-	return 1;
+	int i;
+	unsigned long paddr = (pfn << PAGE_SHIFT);
+
+	for (i=0; i < lmb.memory.cnt; i++) {
+		unsigned long base;
+
+#ifdef CONFIG_MSCHUNKS
+		base = lmb.memory.region[i].physbase;
+#else
+		base = lmb.memory.region[i].base;
 #endif
-	if (physaddr >= top_of_ram)
-		return 0;
-	return io_hole_start == 0 ||  physaddr < io_hole_start ||
-		physaddr >= (io_hole_start + io_hole_size);
-}
+		if ((paddr >= base) &&
+			(paddr < (base + lmb.memory.region[i].size))) {
+			return 1;
+		}
+	}
 
+	return 0;
+}
+EXPORT_SYMBOL(page_is_ram);
 
 /*
  * Initialize the bootmem system and give it all the memory we
@@ -573,6 +645,7 @@
 	unsigned long zones_size[MAX_NR_ZONES];
 	unsigned long zholes_size[MAX_NR_ZONES];
 	unsigned long total_ram = lmb_phys_mem_size();
+	unsigned long top_of_ram = lmb_end_of_DRAM();
 
 	printk(KERN_INFO "Top of RAM: 0x%lx, Total RAM: 0x%lx\n",
 	       top_of_ram, total_ram);
@@ -587,7 +660,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;
 }
@@ -622,59 +695,53 @@
 
 void __init mem_init(void)
 {
-#ifndef CONFIG_DISCONTIGMEM
-	unsigned long addr;
+#ifdef CONFIG_DISCONTIGMEM
+	int nid;
 #endif
-	int codepages = 0;
-	int datapages = 0;
-	int initpages = 0;
+	pg_data_t *pgdat;
+	unsigned long i;
+	struct page *page;
+	unsigned long reservedpages = 0, codesize, initsize, datasize, bsssize;
 
 	num_physpages = max_low_pfn;	/* RAM is assumed contiguous */
 	high_memory = (void *) __va(max_low_pfn * PAGE_SIZE);
 
 #ifdef CONFIG_DISCONTIGMEM
-{
-	int nid;
-
         for (nid = 0; nid < numnodes; nid++) {
-		if (node_data[nid].node_spanned_pages != 0) {
+		if (NODE_DATA(nid)->node_spanned_pages != 0) {
 			printk("freeing bootmem node %x\n", nid);
 			totalram_pages +=
 				free_all_bootmem_node(NODE_DATA(nid));
 		}
 	}
-
-	printk("Memory: %luk available (%dk kernel code, %dk data, %dk init) [%08lx,%08lx]\n",
-	       (unsigned long)nr_free_pages()<< (PAGE_SHIFT-10),
-	       codepages<< (PAGE_SHIFT-10), datapages<< (PAGE_SHIFT-10),
-	       initpages<< (PAGE_SHIFT-10),
-	       PAGE_OFFSET, (unsigned long)__va(lmb_end_of_DRAM()));
-}
 #else
 	max_mapnr = num_physpages;
-
 	totalram_pages += free_all_bootmem();
+#endif
 
-	for (addr = KERNELBASE; addr < (unsigned long)__va(lmb_end_of_DRAM());
-	     addr += PAGE_SIZE) {
-		if (!PageReserved(virt_to_page(addr)))
-			continue;
-		if (addr < (unsigned long)_etext)
-			codepages++;
-
-		else if (addr >= (unsigned long)__init_begin
-			 && addr < (unsigned long)__init_end)
-			initpages++;
-		else if (addr < klimit)
-			datapages++;
+	for_each_pgdat(pgdat) {
+		for (i = 0; i < pgdat->node_spanned_pages; i++) {
+			page = pgdat->node_mem_map + i;
+			if (PageReserved(page))
+				reservedpages++;
+		}
 	}
 
-	printk("Memory: %luk available (%dk kernel code, %dk data, %dk init) [%08lx,%08lx]\n",
-	       (unsigned long)nr_free_pages()<< (PAGE_SHIFT-10),
-	       codepages<< (PAGE_SHIFT-10), datapages<< (PAGE_SHIFT-10),
-	       initpages<< (PAGE_SHIFT-10),
-	       PAGE_OFFSET, (unsigned long)__va(lmb_end_of_DRAM()));
-#endif
+	codesize = (unsigned long)&_etext - (unsigned long)&_stext;
+	initsize = (unsigned long)&__init_end - (unsigned long)&__init_begin;
+	datasize = (unsigned long)&_edata - (unsigned long)&__init_end;
+	bsssize = (unsigned long)&__bss_stop - (unsigned long)&__bss_start;
+
+	printk(KERN_INFO "Memory: %luk/%luk available (%luk kernel code, "
+	       "%luk reserved, %luk data, %luk bss, %luk init)\n",
+		(unsigned long)nr_free_pages() << (PAGE_SHIFT-10),
+		num_physpages << (PAGE_SHIFT-10),
+		codesize >> 10,
+		reservedpages << (PAGE_SHIFT-10),
+		datasize >> 10,
+		bsssize >> 10,
+		initsize >> 10);
+
 	mem_init_done = 1;
 
 #ifdef CONFIG_PPC_ISERIES
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-10-18 14:57:21 -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-10-18 14:56:48 -07:00
+++ b/arch/ppc64/mm/numa.c	2004-10-18 14:56:48 -07:00
@@ -18,11 +18,10 @@
 #include <asm/machdep.h>
 #include <asm/abs_addr.h>
 
-#if 1
-#define dbg(args...) printk(KERN_INFO args)
-#else
-#define dbg(args...)
-#endif
+static int numa_enabled = 1;
+
+static int numa_debug;
+#define dbg(args...) if (numa_debug) { printk(KERN_INFO args); }
 
 #ifdef DEBUG_NUMA
 #define ARRAY_INITIALISER -1
@@ -36,10 +35,19 @@
 cpumask_t numa_cpumask_lookup_table[MAX_NUMNODES];
 int nr_cpus_in_node[MAX_NUMNODES] = { [0 ... (MAX_NUMNODES -1)] = 0};
 
-struct pglist_data node_data[MAX_NUMNODES];
-bootmem_data_t plat_node_bdata[MAX_NUMNODES];
+struct pglist_data *node_data[MAX_NUMNODES];
+bootmem_data_t __initdata plat_node_bdata[MAX_NUMNODES];
 static unsigned long node0_io_hole_size;
 
+/*
+ * We need somewhere to store start/span for each node until we have
+ * allocated the real node_data structures.
+ */
+static struct {
+	unsigned long node_start_pfn;
+	unsigned long node_spanned_pages;
+} init_node_data[MAX_NUMNODES] __initdata;
+
 EXPORT_SYMBOL(node_data);
 EXPORT_SYMBOL(numa_cpu_lookup_table);
 EXPORT_SYMBOL(numa_memory_lookup_table);
@@ -48,7 +56,6 @@
 
 static inline void map_cpu_to_node(int cpu, int node)
 {
-	dbg("cpu %d maps to domain %d\n", cpu, node);
 	numa_cpu_lookup_table[cpu] = node;
 	if (!(cpu_isset(cpu, numa_cpumask_lookup_table[node]))) {
 		cpu_set(cpu, numa_cpumask_lookup_table[node]);
@@ -107,8 +114,8 @@
 	if (tmp && (tmp[0] >= depth)) {
 		numa_domain = tmp[depth];
 	} else {
-		printk(KERN_ERR "WARNING: no NUMA information for "
-		       "%s\n", device->full_name);
+		dbg("WARNING: no NUMA information for %s\n",
+		    device->full_name);
 		numa_domain = 0;
 	}
 	return numa_domain;
@@ -137,11 +144,8 @@
 
 	rtas_root = of_find_node_by_path("/rtas");
 
-	if (!rtas_root) {
-		printk(KERN_ERR "WARNING: %s() could not find rtas root\n",
-				__FUNCTION__);
+	if (!rtas_root)
 		return -1;
-	}
 
 	/*
 	 * this property is 2 32-bit integers, each representing a level of
@@ -155,8 +159,8 @@
 	if ((len >= 1) && ref_points) {
 		depth = ref_points[1];
 	} else {
-		printk(KERN_ERR "WARNING: could not find NUMA "
-				"associativity reference point\n");
+		dbg("WARNING: could not find NUMA "
+		    "associativity reference point\n");
 		depth = -1;
 	}
 	of_node_put(rtas_root);
@@ -187,20 +191,21 @@
 	long entries = lmb_end_of_DRAM() >> MEMORY_INCREMENT_SHIFT;
 	unsigned long i;
 
-	if (strstr(saved_command_line, "numa=off")) {
+	if (numa_enabled == 0) {
 		printk(KERN_WARNING "NUMA disabled by user\n");
 		return -1;
 	}
 
 	numa_memory_lookup_table =
 		(char *)abs_to_virt(lmb_alloc(entries * sizeof(char), 1));
+	memset(numa_memory_lookup_table, 0, entries * sizeof(char));
 
 	for (i = 0; i < entries ; i++)
 		numa_memory_lookup_table[i] = ARRAY_INITIALISER;
 
 	depth = find_min_common_depth();
 
-	printk(KERN_INFO "NUMA associativity depth for CPU/Memory: %d\n", depth);
+	dbg("NUMA associativity depth for CPU/Memory: %d\n", depth);
 	if (depth < 0)
 		return depth;
 
@@ -225,8 +230,7 @@
 				numa_domain = 0;
 			}
 		} else {
-			printk(KERN_ERR "WARNING: no NUMA information for "
-			       "cpu %ld\n", i);
+			dbg("WARNING: no NUMA information for cpu %ld\n", i);
 			numa_domain = 0;
 		}
 
@@ -281,22 +285,22 @@
 		 * this simple case and complain if there is a gap in
 		 * memory
 		 */
-		if (node_data[numa_domain].node_spanned_pages) {
+		if (init_node_data[numa_domain].node_spanned_pages) {
 			unsigned long shouldstart =
-				node_data[numa_domain].node_start_pfn + 
-				node_data[numa_domain].node_spanned_pages;
+				init_node_data[numa_domain].node_start_pfn +
+				init_node_data[numa_domain].node_spanned_pages;
 			if (shouldstart != (start / PAGE_SIZE)) {
-				printk(KERN_ERR "Hole in node, disabling "
-						"region start %lx length %lx\n",
-						start, size);
+				printk(KERN_ERR "WARNING: Hole in node, "
+						"disabling region start %lx "
+						"length %lx\n", start, size);
 				continue;
 			}
-			node_data[numa_domain].node_spanned_pages +=
+			init_node_data[numa_domain].node_spanned_pages +=
 				size / PAGE_SIZE;
 		} else {
-			node_data[numa_domain].node_start_pfn =
+			init_node_data[numa_domain].node_start_pfn =
 				start / PAGE_SIZE;
-			node_data[numa_domain].node_spanned_pages =
+			init_node_data[numa_domain].node_spanned_pages =
 				size / PAGE_SIZE;
 		}
 
@@ -304,9 +308,6 @@
 			numa_memory_lookup_table[i >> MEMORY_INCREMENT_SHIFT] =
 				numa_domain;
 
-		dbg("memory region %lx to %lx maps to domain %d\n",
-		    start, start+size, numa_domain);
-
 		ranges--;
 		if (ranges)
 			goto new_range;
@@ -332,6 +333,7 @@
 		long entries = top_of_ram >> MEMORY_INCREMENT_SHIFT;
 		numa_memory_lookup_table =
 			(char *)abs_to_virt(lmb_alloc(entries * sizeof(char), 1));
+		memset(numa_memory_lookup_table, 0, entries * sizeof(char));
 		for (i = 0; i < entries ; i++)
 			numa_memory_lookup_table[i] = ARRAY_INITIALISER;
 	}
@@ -341,8 +343,8 @@
 
 	node_set_online(0);
 
-	node_data[0].node_start_pfn = 0;
-	node_data[0].node_spanned_pages = lmb_end_of_DRAM() / PAGE_SIZE;
+	init_node_data[0].node_start_pfn = 0;
+	init_node_data[0].node_spanned_pages = lmb_end_of_DRAM() / PAGE_SIZE;
 
 	for (i = 0 ; i < top_of_ram; i += MEMORY_INCREMENT)
 		numa_memory_lookup_table[i >> MEMORY_INCREMENT_SHIFT] = 0;
@@ -350,6 +352,108 @@
 	node0_io_hole_size = top_of_ram - total_ram;
 }
 
+static void __init dump_numa_topology(void)
+{
+	unsigned int node;
+	unsigned int cpu, count;
+
+	for (node = 0; node < MAX_NUMNODES; node++) {
+		if (!node_online(node))
+			continue;
+
+		printk(KERN_INFO "Node %d CPUs:", node);
+
+		count = 0;
+		/*
+		 * If we used a CPU iterator here we would miss printing
+		 * the holes in the cpumap.
+		 */
+		for (cpu = 0; cpu < NR_CPUS; cpu++) {
+			if (cpu_isset(cpu, numa_cpumask_lookup_table[node])) {
+				if (count == 0)
+					printk(" %u", cpu);
+				++count;
+			} else {
+				if (count > 1)
+					printk("-%u", cpu - 1);
+				count = 0;
+			}
+		}
+
+		if (count > 1)
+			printk("-%u", NR_CPUS - 1);
+		printk("\n");
+	}
+
+	for (node = 0; node < MAX_NUMNODES; node++) {
+		unsigned long i;
+
+		if (!node_online(node))
+			continue;
+
+		printk(KERN_INFO "Node %d Memory:", node);
+
+		count = 0;
+
+		for (i = 0; i < lmb_end_of_DRAM(); i += MEMORY_INCREMENT) {
+			if (numa_memory_lookup_table[i >> MEMORY_INCREMENT_SHIFT] == node) {
+				if (count == 0)
+					printk(" 0x%lx", i);
+				++count;
+			} else {
+				if (count > 0)
+					printk("-0x%lx", i);
+				count = 0;
+			}
+		}
+
+		if (count > 0)
+			printk("-0x%lx", i);
+		printk("\n");
+	}
+}
+
+/*
+ * Allocate some memory, satisfying the lmb or bootmem allocator where
+ * required. nid is the preferred node and end is the physical address of
+ * the highest address in the node.
+ *
+ * Returns the physical address of the memory.
+ */
+static unsigned long careful_allocation(int nid, unsigned long size,
+					unsigned long align, unsigned long end)
+{
+	unsigned long ret = lmb_alloc_base(size, align, end);
+
+	/* retry over all memory */
+	if (!ret)
+		ret = lmb_alloc_base(size, align, lmb_end_of_DRAM());
+
+	if (!ret)
+		panic("numa.c: cannot allocate %lu bytes on node %d",
+		      size, nid);
+
+	/*
+	 * If the memory came from a previously allocated node, we must
+	 * retry with the bootmem allocator.
+	 */
+	if (pa_to_nid(ret) < nid) {
+		nid = pa_to_nid(ret);
+		ret = (unsigned long)__alloc_bootmem_node(NODE_DATA(nid),
+				size, align, 0);
+
+		if (!ret)
+			panic("numa.c: cannot allocate %lu bytes on node %d",
+			      size, nid);
+
+		ret = virt_to_abs(ret);
+
+		dbg("alloc_bootmem %lx %lx\n", ret, size);
+	}
+
+	return ret;
+}
+
 void __init do_init_bootmem(void)
 {
 	int nid;
@@ -360,6 +464,8 @@
 
 	if (parse_numa_properties())
 		setup_nonnuma();
+	else
+		dump_numa_topology();
 
 	for (nid = 0; nid < numnodes; nid++) {
 		unsigned long start_paddr, end_paddr;
@@ -367,24 +473,38 @@
 		unsigned long bootmem_paddr;
 		unsigned long bootmap_pages;
 
-		if (node_data[nid].node_spanned_pages == 0)
-			continue;
+		start_paddr = init_node_data[nid].node_start_pfn * PAGE_SIZE;
+		end_paddr = start_paddr + (init_node_data[nid].node_spanned_pages * PAGE_SIZE);
+
+		/* Allocate the node structure node local if possible */
+		NODE_DATA(nid) = (struct pglist_data *)careful_allocation(nid,
+					sizeof(struct pglist_data),
+					SMP_CACHE_BYTES, end_paddr);
+		NODE_DATA(nid) = abs_to_virt(NODE_DATA(nid));
+		memset(NODE_DATA(nid), 0, sizeof(struct pglist_data));
 
-		start_paddr = node_data[nid].node_start_pfn * PAGE_SIZE;
-		end_paddr = start_paddr + 
-				(node_data[nid].node_spanned_pages * PAGE_SIZE);
-
-		dbg("node %d\n", nid);
-		dbg("start_paddr = %lx\n", start_paddr);
-		dbg("end_paddr = %lx\n", end_paddr);
+  		dbg("node %d\n", nid);
+		dbg("NODE_DATA() = %p\n", NODE_DATA(nid));
 
 		NODE_DATA(nid)->bdata = &plat_node_bdata[nid];
+		NODE_DATA(nid)->node_start_pfn =
+			init_node_data[nid].node_start_pfn;
+		NODE_DATA(nid)->node_spanned_pages =
+			init_node_data[nid].node_spanned_pages;
+
+		if (init_node_data[nid].node_spanned_pages == 0)
+  			continue;
+
+  		dbg("start_paddr = %lx\n", start_paddr);
+  		dbg("end_paddr = %lx\n", end_paddr);
 
 		bootmap_pages = bootmem_bootmap_pages((end_paddr - start_paddr) >> PAGE_SHIFT);
-		dbg("bootmap_pages = %lx\n", bootmap_pages);
 
-		bootmem_paddr = lmb_alloc_base(bootmap_pages << PAGE_SHIFT,
+		bootmem_paddr = careful_allocation(nid,
+				bootmap_pages << PAGE_SHIFT,
 				PAGE_SIZE, end_paddr);
+		memset(abs_to_virt(bootmem_paddr), 0,
+		       bootmap_pages << PAGE_SHIFT);
 		dbg("bootmap_paddr = %lx\n", bootmem_paddr);
 
 		init_bootmem_node(NODE_DATA(nid), bootmem_paddr >> PAGE_SHIFT,
@@ -442,7 +562,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));
@@ -463,17 +582,22 @@
 		dbg("free_area_init node %d %lx %lx (hole: %lx)\n", nid,
 		    zones_size[ZONE_DMA], start_pfn, zholes_size[ZONE_DMA]);
 
-		/* 
-		 * Give this empty node a dummy struct page to avoid
-		 * us from trying to allocate a node local mem_map
-		 * in free_area_init_node (which will fail).
-		 */
-		if (!node_data[nid].node_spanned_pages)
-			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);
+		free_area_init_node(nid, NODE_DATA(nid), zones_size,
+							start_pfn, zholes_size);
 	}
 }
+
+static int __init early_numa(char *p)
+{
+	if (!p)
+		return 0;
+
+	if (strstr(p, "off"))
+		numa_enabled = 0;
+
+	if (strstr(p, "debug"))
+		numa_debug = 1;
+
+	return 0;
+}
+early_param("numa", early_numa);
diff -Nru a/arch/ppc64/mm/slb.c b/arch/ppc64/mm/slb.c
--- a/arch/ppc64/mm/slb.c	2004-10-18 14:56:32 -07:00
+++ b/arch/ppc64/mm/slb.c	2004-10-18 14:56:32 -07:00
@@ -24,32 +24,55 @@
 
 extern void slb_allocate(unsigned long ea);
 
+static inline unsigned long mk_esid_data(unsigned long ea, unsigned long slot)
+{
+	return (ea & ESID_MASK) | SLB_ESID_V | slot;
+}
+
+static inline unsigned long mk_vsid_data(unsigned long ea, unsigned long flags)
+{
+	return (get_kernel_vsid(ea) << SLB_VSID_SHIFT) | flags;
+}
+
 static inline void create_slbe(unsigned long ea, unsigned long vsid,
 			       unsigned long flags, unsigned long entry)
 {
-	ea = (ea & ESID_MASK) | SLB_ESID_V | entry;
-	vsid = (vsid << SLB_VSID_SHIFT) | flags;
 	asm volatile("slbmte  %0,%1" :
-		     : "r" (vsid), "r" (ea)
+		     : "r" (mk_vsid_data(ea, flags)),
+		       "r" (mk_esid_data(ea, entry))
 		     : "memory" );
 }
 
-static void slb_add_bolted(void)
+static void slb_flush_and_rebolt(void)
 {
-#ifndef CONFIG_PPC_ISERIES
-	WARN_ON(!irqs_disabled());
-
 	/* If you change this make sure you change SLB_NUM_BOLTED
-	 * appropriately too */
+	 * appropriately too. */
+	unsigned long ksp_flags = SLB_VSID_KERNEL;
+	unsigned long ksp_esid_data;
 
-	/* Slot 1 - first VMALLOC segment
-         * 	Since modules end up there it gets hit very heavily.
-         */
-	create_slbe(VMALLOCBASE, get_kernel_vsid(VMALLOCBASE),
-		    SLB_VSID_KERNEL, 1);
+	WARN_ON(!irqs_disabled());
 
-	asm volatile("isync":::"memory");
-#endif
+	if (cur_cpu_spec->cpu_features & CPU_FTR_16M_PAGE)
+		ksp_flags |= SLB_VSID_L;
+
+	ksp_esid_data = mk_esid_data(get_paca()->kstack, 2);
+	if ((ksp_esid_data & ESID_MASK) == KERNELBASE)
+		ksp_esid_data &= ~SLB_ESID_V;
+
+	/* We need to do this all in asm, so we're sure we don't touch
+	 * the stack between the slbia and rebolting it. */
+	asm volatile("isync\n"
+		     "slbia\n"
+		     /* Slot 1 - first VMALLOC segment */
+		     "slbmte	%0,%1\n"
+		     /* Slot 2 - kernel stack */
+		     "slbmte	%2,%3\n"
+		     "isync"
+		     :: "r"(mk_vsid_data(VMALLOCBASE, SLB_VSID_KERNEL)),
+		        "r"(mk_esid_data(VMALLOCBASE, 1)),
+		        "r"(mk_vsid_data(ksp_esid_data, ksp_flags)),
+		        "r"(ksp_esid_data)
+		     : "memory");
 }
 
 /* Flush all user entries from the segment table of the current processor. */
@@ -71,8 +94,7 @@
 		}
 		asm volatile("isync" : : : "memory");
 	} else {
-		asm volatile("isync; slbia; isync" : : : "memory");
-		slb_add_bolted();
+		slb_flush_and_rebolt();
 	}
 
 	/* Workaround POWER5 < DD2.1 issue */
@@ -115,22 +137,27 @@
 
 void slb_initialize(void)
 {
-#ifdef CONFIG_PPC_ISERIES
-	asm volatile("isync; slbia; isync":::"memory");
-#else
+	/* On iSeries the bolted entries have already been set up by
+	 * the hypervisor from the lparMap data in head.S */
+#ifndef CONFIG_PPC_ISERIES
 	unsigned long flags = SLB_VSID_KERNEL;
 
-	/* Invalidate the entire SLB (even slot 0) & all the ERATS */
-	if (cur_cpu_spec->cpu_features & CPU_FTR_16M_PAGE)
-		flags |= SLB_VSID_L;
+ 	/* Invalidate the entire SLB (even slot 0) & all the ERATS */
+ 	if (cur_cpu_spec->cpu_features & CPU_FTR_16M_PAGE)
+ 		flags |= SLB_VSID_L;
 
-	asm volatile("isync":::"memory");
-	asm volatile("slbmte  %0,%0"::"r" (0) : "memory");
+ 	asm volatile("isync":::"memory");
+ 	asm volatile("slbmte  %0,%0"::"r" (0) : "memory");
 	asm volatile("isync; slbia; isync":::"memory");
-	create_slbe(KERNELBASE, get_kernel_vsid(KERNELBASE),
-		    flags, 0);
-
+	create_slbe(KERNELBASE, get_kernel_vsid(KERNELBASE), flags, 0);
+	create_slbe(VMALLOCBASE, get_kernel_vsid(KERNELBASE),
+		    SLB_VSID_KERNEL, 1);
+	/* We don't bolt the stack for the time being - we're in boot,
+	 * so the stack is in the bolted segment.  By the time it goes
+	 * elsewhere, we'll call _switch() which will bolt in the new
+	 * one. */
+	asm volatile("isync":::"memory");
 #endif
-	slb_add_bolted();
+
 	get_paca()->stab_rr = SLB_NUM_BOLTED;
 }
diff -Nru a/arch/ppc64/mm/slb_low.S b/arch/ppc64/mm/slb_low.S
--- a/arch/ppc64/mm/slb_low.S	2004-10-18 14:56:33 -07:00
+++ b/arch/ppc64/mm/slb_low.S	2004-10-18 14:56:33 -07:00
@@ -37,8 +37,21 @@
 	 * a free slot first but that took too long. Unfortunately we
 	 * dont have any LRU information to help us choose a slot.
 	 */
+#ifdef CONFIG_PPC_ISERIES
+	/*
+	 * On iSeries, the "bolted" stack segment can be cast out on
+	 * shared processor switch so we need to check for a miss on
+	 * it and restore it to the right slot.
+	 */
+	ld	r9,PACAKSAVE(r13)
+	clrrdi	r9,r9,28
+	clrrdi	r11,r3,28
+	li	r10,SLB_NUM_BOLTED-1	/* Stack goes in last bolted slot */
+	cmpld	r9,r11
+	beq	3f
+#endif /* CONFIG_PPC_ISERIES */
+
 	ld	r10,PACASTABRR(r13)
-3:
 	addi	r10,r10,1
 	/* use a cpu feature mask if we ever change our slb size */
 	cmpldi	r10,SLB_NUM_ENTRIES
@@ -46,55 +59,28 @@
 	blt+	4f
 	li	r10,SLB_NUM_BOLTED
 
-	/*
-	 * Never cast out the segment for our kernel stack. Since we
-	 * dont invalidate the ERAT we could have a valid translation
-	 * for the kernel stack during the first part of exception exit
-	 * which gets invalidated due to a tlbie from another cpu at a
-	 * non recoverable point (after setting srr0/1) - Anton
-	 */
-4:	slbmfee	r11,r10
-	srdi	r11,r11,27
-	/*
-	 * Use paca->ksave as the value of the kernel stack pointer,
-	 * because this is valid at all times.
-	 * The >> 27 (rather than >> 28) is so that the LSB is the
-	 * valid bit - this way we check valid and ESID in one compare.
-	 * In order to completely close the tiny race in the context
-	 * switch (between updating r1 and updating paca->ksave),
-	 * we check against both r1 and paca->ksave.
-	 */
-	srdi	r9,r1,27
-	ori	r9,r9,1			/* mangle SP for later compare */
-	cmpd	r11,r9
-	beq-	3b
-	ld	r9,PACAKSAVE(r13)
-	srdi	r9,r9,27
-	ori	r9,r9,1
-	cmpd	r11,r9
-	beq-	3b
-
+4:
 	std	r10,PACASTABRR(r13)
-
+3:
 	/* r3 = faulting address, r10 = entry */
 
 	srdi	r9,r3,60		/* get region */
 	srdi	r3,r3,28		/* get esid */
 	cmpldi	cr7,r9,0xc		/* cmp KERNELBASE for later use */
 
-	/* r9 = region, r3 = esid, cr7 = <>KERNELBASE */
-
-	rldicr.	r11,r3,32,16
-	bne-	8f			/* invalid ea bits set */
-	addi	r11,r9,-1
-	cmpldi	r11,0xb
-	blt-	8f			/* invalid region */
+	rldimi	r10,r3,28,0		/* r10= ESID<<28 | entry */
+	oris	r10,r10,SLB_ESID_V@h	/* r10 |= SLB_ESID_V */
 
-	/* r9 = region, r3 = esid, r10 = entry, cr7 = <>KERNELBASE */
+	/* r3 = esid, r10 = esid_data, cr7 = <>KERNELBASE */
 
 	blt	cr7,0f			/* user or kernel? */
 
-	/* kernel address */
+	/* kernel address: proto-VSID = ESID */
+	/* WARNING - MAGIC: we don't use the VSID 0xfffffffff, but
+	 * this code will generate the protoVSID 0xfffffffff for the
+	 * top segment.  That's ok, the scramble below will translate
+	 * it to VSID 0, which is reserved as a bad VSID - one which
+	 * will never have any pages in it.  */
 	li	r11,SLB_VSID_KERNEL
 BEGIN_FTR_SECTION
 	bne	cr7,9f
@@ -102,8 +88,12 @@
 END_FTR_SECTION_IFSET(CPU_FTR_16M_PAGE)
 	b	9f
 
-0:	/* user address */
+0:	/* user address: proto-VSID = context<<15 | ESID */
 	li	r11,SLB_VSID_USER
+
+	srdi.	r9,r3,13
+	bne-	8f			/* invalid ea bits set */
+
 #ifdef CONFIG_HUGETLB_PAGE
 BEGIN_FTR_SECTION
 	/* check against the hugepage ranges */
@@ -125,33 +115,18 @@
 #endif /* CONFIG_HUGETLB_PAGE */
 
 6:	ld	r9,PACACONTEXTID(r13)
+	rldimi	r3,r9,USER_ESID_BITS,0
 
-9:	/* r9 = "context", r3 = esid, r11 = flags, r10 = entry */
-
-	rldimi	r9,r3,15,0		/* r9= VSID ordinal */
-
-7:	rldimi	r10,r3,28,0		/* r10= ESID<<28 | entry */
-	oris	r10,r10,SLB_ESID_V@h	/* r10 |= SLB_ESID_V */
-
-	/* r9 = ordinal, r3 = esid, r11 = flags, r10 = esid_data */
-
-	li	r3,VSID_RANDOMIZER@higher
-	sldi	r3,r3,32
-	oris	r3,r3,VSID_RANDOMIZER@h
-	ori	r3,r3,VSID_RANDOMIZER@l
-
-	mulld	r9,r3,r9		/* r9 = ordinal * VSID_RANDOMIZER */
-	clrldi	r9,r9,28		/* r9 &= VSID_MASK */
-	sldi	r9,r9,SLB_VSID_SHIFT	/* r9 <<= SLB_VSID_SHIFT */
-	or	r9,r9,r11		/* r9 |= flags */
+9:	/* r3 = protovsid, r11 = flags, r10 = esid_data, cr7 = <>KERNELBASE */
+	ASM_VSID_SCRAMBLE(r3,r9)
 
-	/* r9 = vsid_data, r10 = esid_data, cr7 = <>KERNELBASE */
+	rldimi	r11,r3,SLB_VSID_SHIFT,16	/* combine VSID and flags */
 
 	/*
 	 * No need for an isync before or after this slbmte. The exception
 	 * we enter with and the rfid we exit with are context synchronizing.
 	 */
-	slbmte	r9,r10
+	slbmte	r11,r10
 
 	bgelr	cr7			/* we're done for kernel addresses */
 
@@ -174,6 +149,6 @@
 	blr
 
 8:	/* invalid EA */
-	li	r9,0			/* 0 VSID ordinal -> BAD_VSID */
+	li	r3,0			/* BAD_VSID */
 	li	r11,SLB_VSID_USER	/* flags don't much matter */
-	b	7b
+	b	9b
diff -Nru a/arch/ppc64/mm/stab.c b/arch/ppc64/mm/stab.c
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/arch/ppc64/mm/stab.c	2004-10-18 14:56:49 -07:00
@@ -0,0 +1,240 @@
+/*
+ * PowerPC64 Segment Translation Support.
+ *
+ * Dave Engebretsen and Mike Corrigan {engebret|mikejc}@us.ibm.com
+ *    Copyright (c) 2001 Dave Engebretsen
+ *
+ * Copyright (C) 2002 Anton Blanchard <anton@au.ibm.com>, IBM
+ *
+ *      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 <asm/pgtable.h>
+#include <asm/mmu.h>
+#include <asm/mmu_context.h>
+#include <asm/paca.h>
+#include <asm/naca.h>
+#include <asm/cputable.h>
+
+/* Both the segment table and SLB code uses the following cache */
+#define NR_STAB_CACHE_ENTRIES 8
+DEFINE_PER_CPU(long, stab_cache_ptr);
+DEFINE_PER_CPU(long, stab_cache[NR_STAB_CACHE_ENTRIES]);
+
+/*
+ * Create a segment table entry for the given esid/vsid pair.
+ */
+static int make_ste(unsigned long stab, unsigned long esid, unsigned long vsid)
+{
+	unsigned long esid_data, vsid_data;
+	unsigned long entry, group, old_esid, castout_entry, i;
+	unsigned int global_entry;
+	struct stab_entry *ste, *castout_ste;
+	unsigned long kernel_segment = (esid << SID_SHIFT) >= KERNELBASE;
+
+	vsid_data = vsid << STE_VSID_SHIFT;
+	esid_data = esid << SID_SHIFT | STE_ESID_KP | STE_ESID_V;
+	if (! kernel_segment)
+		esid_data |= STE_ESID_KS;
+
+	/* Search the primary group first. */
+	global_entry = (esid & 0x1f) << 3;
+	ste = (struct stab_entry *)(stab | ((esid & 0x1f) << 7));
+
+	/* Find an empty entry, if one exists. */
+	for (group = 0; group < 2; group++) {
+		for (entry = 0; entry < 8; entry++, ste++) {
+			if (!(ste->esid_data & STE_ESID_V)) {
+				ste->vsid_data = vsid_data;
+				asm volatile("eieio":::"memory");
+				ste->esid_data = esid_data;
+				return (global_entry | entry);
+			}
+		}
+		/* Now search the secondary group. */
+		global_entry = ((~esid) & 0x1f) << 3;
+		ste = (struct stab_entry *)(stab | (((~esid) & 0x1f) << 7));
+	}
+
+	/*
+	 * Could not find empty entry, pick one with a round robin selection.
+	 * Search all entries in the two groups.
+	 */
+	castout_entry = get_paca()->stab_rr;
+	for (i = 0; i < 16; i++) {
+		if (castout_entry < 8) {
+			global_entry = (esid & 0x1f) << 3;
+			ste = (struct stab_entry *)(stab | ((esid & 0x1f) << 7));
+			castout_ste = ste + castout_entry;
+		} else {
+			global_entry = ((~esid) & 0x1f) << 3;
+			ste = (struct stab_entry *)(stab | (((~esid) & 0x1f) << 7));
+			castout_ste = ste + (castout_entry - 8);
+		}
+
+		/* Dont cast out the first kernel segment */
+		if ((castout_ste->esid_data & ESID_MASK) != KERNELBASE)
+			break;
+
+		castout_entry = (castout_entry + 1) & 0xf;
+	}
+
+	get_paca()->stab_rr = (castout_entry + 1) & 0xf;
+
+	/* Modify the old entry to the new value. */
+
+	/* Force previous translations to complete. DRENG */
+	asm volatile("isync" : : : "memory");
+
+	old_esid = castout_ste->esid_data >> SID_SHIFT;
+	castout_ste->esid_data = 0;		/* Invalidate old entry */
+
+	asm volatile("sync" : : : "memory");    /* Order update */
+
+	castout_ste->vsid_data = vsid_data;
+	asm volatile("eieio" : : : "memory");   /* Order update */
+	castout_ste->esid_data = esid_data;
+
+	asm volatile("slbie  %0" : : "r" (old_esid << SID_SHIFT));
+	/* Ensure completion of slbie */
+	asm volatile("sync" : : : "memory");
+
+	return (global_entry | (castout_entry & 0x7));
+}
+
+/*
+ * Allocate a segment table entry for the given ea and mm
+ */
+static int __ste_allocate(unsigned long ea, struct mm_struct *mm)
+{
+	unsigned long vsid;
+	unsigned char stab_entry;
+	unsigned long offset;
+
+	/* Kernel or user address? */
+	if (ea >= KERNELBASE) {
+		vsid = get_kernel_vsid(ea);
+	} else {
+		if ((ea >= TASK_SIZE_USER64) || (! mm))
+			return 1;
+
+		vsid = get_vsid(mm->context.id, ea);
+	}
+
+	stab_entry = make_ste(get_paca()->stab_addr, GET_ESID(ea), vsid);
+
+	if (ea < KERNELBASE) {
+		offset = __get_cpu_var(stab_cache_ptr);
+		if (offset < NR_STAB_CACHE_ENTRIES)
+			__get_cpu_var(stab_cache[offset++]) = stab_entry;
+		else
+			offset = NR_STAB_CACHE_ENTRIES+1;
+		__get_cpu_var(stab_cache_ptr) = offset;
+
+		/* Order update */
+		asm volatile("sync":::"memory");
+	}
+
+	return 0;
+}
+
+int ste_allocate(unsigned long ea)
+{
+	return __ste_allocate(ea, current->mm);
+}
+
+/*
+ * Do the segment table work for a context switch: flush all user
+ * entries from the table, then preload some probably useful entries
+ * for the new task
+ */
+void switch_stab(struct task_struct *tsk, struct mm_struct *mm)
+{
+	struct stab_entry *stab = (struct stab_entry *) get_paca()->stab_addr;
+	struct stab_entry *ste;
+	unsigned long offset = __get_cpu_var(stab_cache_ptr);
+	unsigned long pc = KSTK_EIP(tsk);
+	unsigned long stack = KSTK_ESP(tsk);
+	unsigned long unmapped_base;
+
+	/* Force previous translations to complete. DRENG */
+	asm volatile("isync" : : : "memory");
+
+	if (offset <= NR_STAB_CACHE_ENTRIES) {
+		int i;
+
+		for (i = 0; i < offset; i++) {
+			ste = stab + __get_cpu_var(stab_cache[i]);
+			ste->esid_data = 0; /* invalidate entry */
+		}
+	} else {
+		unsigned long entry;
+
+		/* Invalidate all entries. */
+		ste = stab;
+
+		/* Never flush the first entry. */
+		ste += 1;
+		for (entry = 1;
+		     entry < (PAGE_SIZE / sizeof(struct stab_entry));
+		     entry++, ste++) {
+			unsigned long ea;
+			ea = ste->esid_data & ESID_MASK;
+			if (ea < KERNELBASE) {
+				ste->esid_data = 0;
+			}
+		}
+	}
+
+	asm volatile("sync; slbia; sync":::"memory");
+
+	__get_cpu_var(stab_cache_ptr) = 0;
+
+	/* Now preload some entries for the new task */
+	if (test_tsk_thread_flag(tsk, TIF_32BIT))
+		unmapped_base = TASK_UNMAPPED_BASE_USER32;
+	else
+		unmapped_base = TASK_UNMAPPED_BASE_USER64;
+
+	__ste_allocate(pc, mm);
+
+	if (GET_ESID(pc) == GET_ESID(stack))
+		return;
+
+	__ste_allocate(stack, mm);
+
+	if ((GET_ESID(pc) == GET_ESID(unmapped_base))
+	    || (GET_ESID(stack) == GET_ESID(unmapped_base)))
+		return;
+
+	__ste_allocate(unmapped_base, mm);
+
+	/* Order update */
+	asm volatile("sync" : : : "memory");
+}
+
+extern void slb_initialize(void);
+
+/*
+ * Build an entry for the base kernel segment and put it into
+ * the segment table or SLB.  All other segment table or SLB
+ * entries are faulted in.
+ */
+void stab_initialize(unsigned long stab)
+{
+	unsigned long vsid = get_kernel_vsid(KERNELBASE);
+
+	if (cur_cpu_spec->cpu_features & CPU_FTR_SLB) {
+		slb_initialize();
+	} else {
+		asm volatile("isync; slbia; isync":::"memory");
+		make_ste(stab, GET_ESID(KERNELBASE), vsid);
+
+		/* Order update */
+		asm volatile("sync":::"memory");
+	}
+}
diff -Nru a/arch/ppc64/mm/tlb.c b/arch/ppc64/mm/tlb.c
--- a/arch/ppc64/mm/tlb.c	2004-10-18 14:56:31 -07:00
+++ b/arch/ppc64/mm/tlb.c	2004-10-18 14:56:31 -07:00
@@ -26,10 +26,10 @@
 #include <linux/mm.h>
 #include <linux/init.h>
 #include <linux/percpu.h>
+#include <linux/hardirq.h>
 #include <asm/pgalloc.h>
 #include <asm/tlbflush.h>
 #include <asm/tlb.h>
-#include <asm/hardirq.h>
 #include <linux/highmem.h>
 
 DEFINE_PER_CPU(struct ppc64_tlb_batch, ppc64_tlb_batch);
diff -Nru a/arch/ppc64/oprofile/common.c b/arch/ppc64/oprofile/common.c
--- a/arch/ppc64/oprofile/common.c	2004-10-18 14:57:04 -07:00
+++ b/arch/ppc64/oprofile/common.c	2004-10-18 14:57:04 -07:00
@@ -52,17 +52,10 @@
 
 static void op_ppc64_shutdown(void)
 {
-	/*
-	 * We need to be sure we have cleared all pending exceptions before
-	 * removing the interrupt handler. For the moment we play it safe and
-	 * leave it in
-	 */
-#if 0
 	mb();
 
 	/* Remove our interrupt handler. We may be removing this module. */
 	perf_irq = save_perf_irq;
-#endif
 }
 
 static void op_ppc64_cpu_start(void *dummy)
@@ -90,6 +83,14 @@
 {
 	int i;
 
+	/*
+	 * There is one mmcr0, mmcr1 and mmcra for setting the events for
+	 * all of the counters.
+	 */
+	oprofilefs_create_ulong(sb, root, "mmcr0", &sys.mmcr0);
+	oprofilefs_create_ulong(sb, root, "mmcr1", &sys.mmcr1);
+	oprofilefs_create_ulong(sb, root, "mmcra", &sys.mmcra);
+
 	for (i = 0; i < model->num_counters; ++i) {
 		struct dentry *dir;
 		char buf[3];
@@ -112,6 +113,10 @@
 	oprofilefs_create_ulong(sb, root, "enable_kernel", &sys.enable_kernel);
 	oprofilefs_create_ulong(sb, root, "enable_user", &sys.enable_user);
 
+	/* Default to tracing both kernel and user */
+	sys.enable_kernel = 1;
+	sys.enable_user = 1;
+
 	return 0;
 }
 
@@ -128,7 +133,7 @@
 {
 	unsigned int pvr;
 
-	pvr = _get_PVR();
+	pvr = mfspr(SPRN_PVR);
 
 	switch (PVR_VER(pvr)) {
 		case PV_630:
diff -Nru a/arch/ppc64/oprofile/op_impl.h b/arch/ppc64/oprofile/op_impl.h
--- a/arch/ppc64/oprofile/op_impl.h	2004-10-18 14:56:32 -07:00
+++ b/arch/ppc64/oprofile/op_impl.h	2004-10-18 14:56:32 -07:00
@@ -19,6 +19,12 @@
 /* freeze counters. set to 1 on a perfmon exception */
 #define MMCR0_FC	(1UL << (31 - 0))
 
+/* freeze in supervisor state */
+#define MMCR0_KERNEL_DISABLE (1UL << (31 - 1))
+
+/* freeze in problem state */
+#define MMCR0_PROBLEM_DISABLE (1UL << (31 - 2))
+
 /* freeze counters while MSR mark = 1 */
 #define MMCR0_FCM1	(1UL << (31 - 3))
 
@@ -28,15 +34,15 @@
 /* freeze counters on enabled condition or event */
 #define MMCR0_FCECE	(1UL << (31 - 6))
 
-/* performance monitor alert has occurred, set to 0 after handling exception */
-#define MMCR0_PMAO	(1UL << (31 - 24))
-
 /* PMC1 count enable*/
 #define MMCR0_PMC1INTCONTROL	(1UL << (31 - 16))
 
 /* PMCn count enable*/
 #define MMCR0_PMCNINTCONTROL	(1UL << (31 - 17))
 
+/* performance monitor alert has occurred, set to 0 after handling exception */
+#define MMCR0_PMAO	(1UL << (31 - 24))
+
 /* state of MSR HV when SIAR set */
 #define MMCRA_SIHV	(1UL << (63 - 35))
 
@@ -60,6 +66,9 @@
 
 /* System-wide configuration as set via oprofilefs.  */
 struct op_system_config {
+	unsigned long mmcr0;
+	unsigned long mmcr1;
+	unsigned long mmcra;
 	unsigned long enable_kernel;
 	unsigned long enable_user;
 };
diff -Nru a/arch/ppc64/oprofile/op_model_power4.c b/arch/ppc64/oprofile/op_model_power4.c
--- a/arch/ppc64/oprofile/op_model_power4.c	2004-10-18 14:56:48 -07:00
+++ b/arch/ppc64/oprofile/op_model_power4.c	2004-10-18 14:56:48 -07:00
@@ -17,7 +17,7 @@
 #include <asm/systemcfg.h>
 #include <asm/rtas.h>
 
-#define dbg(args...) printk(args)
+#define dbg(args...)
 
 #include "op_impl.h"
 
@@ -27,6 +27,11 @@
 static int oprofile_running;
 static int mmcra_has_sihv;
 
+/* mmcr values are set in power4_reg_setup, used in power4_cpu_setup */
+static u32 mmcr0_val;
+static u64 mmcr1_val;
+static u32 mmcra_val;
+
 static void power4_reg_setup(struct op_counter_config *ctr,
 			     struct op_system_config *sys,
 			     int num_ctrs)
@@ -45,18 +50,36 @@
 	if (cur_cpu_spec->cpu_features & CPU_FTR_MMCRA_SIHV)
 		mmcra_has_sihv = 1;
 
+	/*
+	 * The performance counter event settings are given in the mmcr0,
+	 * mmcr1 and mmcra values passed from the user in the
+	 * op_system_config structure (sys variable).
+	 */
+	mmcr0_val = sys->mmcr0;
+	mmcr1_val = sys->mmcr1;
+	mmcra_val = sys->mmcra;
+
 	for (i = 0; i < num_counters; ++i)
 		reset_value[i] = 0x80000000UL - ctr[i].count;
 
-	/* XXX setup user and kernel profiling */
+	/* setup user and kernel profiling */
+	if (sys->enable_kernel)
+		mmcr0_val &= ~MMCR0_KERNEL_DISABLE;
+	else
+		mmcr0_val |= MMCR0_KERNEL_DISABLE;
+
+	if (sys->enable_user)
+		mmcr0_val &= ~MMCR0_PROBLEM_DISABLE;
+	else
+		mmcr0_val |= MMCR0_PROBLEM_DISABLE;
 }
 
 extern void ppc64_enable_pmcs(void);
 
 static void power4_cpu_setup(void *unused)
 {
-	unsigned int mmcr0 = mfspr(SPRN_MMCR0);
-	unsigned long mmcra = mfspr(SPRN_MMCRA);
+	unsigned int mmcr0 = mmcr0_val;
+	unsigned long mmcra = mmcra_val;
 
 	ppc64_enable_pmcs();
 
@@ -67,6 +90,8 @@
 	mmcr0 |= MMCR0_FCM1|MMCR0_PMXE|MMCR0_FCECE;
 	mmcr0 |= MMCR0_PMC1INTCONTROL|MMCR0_PMCNINTCONTROL;
 	mtspr(SPRN_MMCR0, mmcr0);
+
+	mtspr(SPRN_MMCR1, mmcr1_val);
 
 	mmcra |= MMCRA_SAMPLE_ENABLE;
 	mtspr(SPRN_MMCRA, mmcra);
diff -Nru a/arch/ppc64/oprofile/op_model_rs64.c b/arch/ppc64/oprofile/op_model_rs64.c
--- a/arch/ppc64/oprofile/op_model_rs64.c	2004-10-18 14:57:03 -07:00
+++ b/arch/ppc64/oprofile/op_model_rs64.c	2004-10-18 14:57:03 -07:00
@@ -15,14 +15,14 @@
 #include <asm/processor.h>
 #include <asm/cputable.h>
 
-#define dbg(args...) printk(args)
+#define dbg(args...)
 
 #include "op_impl.h"
 
 static void ctrl_write(unsigned int i, unsigned int val)
 {
-	unsigned int tmp;
-	unsigned long shift, mask;
+	unsigned int tmp = 0;
+	unsigned long shift = 0, mask = 0;
 
 	dbg("ctrl_write %d %x\n", i, val);
 
diff -Nru a/arch/ppc64/xmon/xmon.c b/arch/ppc64/xmon/xmon.c
--- a/arch/ppc64/xmon/xmon.c	2004-10-18 14:56:50 -07:00
+++ b/arch/ppc64/xmon/xmon.c	2004-10-18 14:56:50 -07:00
@@ -252,30 +252,28 @@
 
 static inline void disable_surveillance(void)
 {
-#ifndef CONFIG_PPC_ISERIES
+#ifdef CONFIG_PPC_PSERIES
 	/* Since this can't be a module, args should end up below 4GB. */
 	static struct rtas_args args;
 
-	if (systemcfg->platform & PLATFORM_PSERIES) {
-		/*
-		 * At this point we have got all the cpus we can into
-		 * xmon, so there is hopefully no other cpu calling RTAS
-		 * at the moment, even though we don't take rtas.lock.
-		 * If we did try to take rtas.lock there would be a
-		 * real possibility of deadlock.
-		 */
-		args.token = rtas_token("set-indicator");
-		if (args.token == RTAS_UNKNOWN_SERVICE)
-			return;
-		args.nargs = 3;
-		args.nret = 1;
-		args.rets = &args.args[3];
-		args.args[0] = SURVEILLANCE_TOKEN;
-		args.args[1] = 0;
-		args.args[2] = 0;
-		enter_rtas(__pa(&args));
-	}
-#endif
+	/*
+	 * At this point we have got all the cpus we can into
+	 * xmon, so there is hopefully no other cpu calling RTAS
+	 * at the moment, even though we don't take rtas.lock.
+	 * If we did try to take rtas.lock there would be a
+	 * real possibility of deadlock.
+	 */
+	args.token = rtas_token("set-indicator");
+	if (args.token == RTAS_UNKNOWN_SERVICE)
+		return;
+	args.nargs = 3;
+	args.nret = 1;
+	args.rets = &args.args[3];
+	args.args[0] = SURVEILLANCE_TOKEN;
+	args.args[1] = 0;
+	args.args[2] = 0;
+	enter_rtas(__pa(&args));
+#endif /* CONFIG_PPC_PSERIES */
 }
 
 #ifdef CONFIG_SMP
@@ -2059,7 +2057,7 @@
 {
 	int nr, dotted;
 	unsigned long first_adr;
-	unsigned long inst, last_inst;
+	unsigned long inst, last_inst = 0;
 	unsigned char val[4];
 
 	dotted = 0;
diff -Nru a/arch/s390/Kconfig b/arch/s390/Kconfig
--- a/arch/s390/Kconfig	2004-10-18 14:56:28 -07:00
+++ b/arch/s390/Kconfig	2004-10-18 14:56:28 -07:00
@@ -48,34 +48,6 @@
 	depends on ARCH_S390X = 'n'
 	default y
 
-choice 
-	prompt "Processor type"
-	default MARCH_G5
-
-config MARCH_G5
-	bool "S/390 model G5 and G6"
-	depends on ARCH_S390_31
-	help
-	  Select this to build a 31 bit kernel that works
-	  on all S/390 and zSeries machines.
-
-config MARCH_Z900
-	bool "IBM eServer zSeries model z800 and z900"
-	help
-	  Select this to optimize for zSeries machines. This
-	  will enable some optimizations that are not available
-	  on older 31 bit only CPUs.
-
-config MARCH_Z990
-	bool "IBM eServer zSeries model z890 and z990"
-	help
-	  Select this enable optimizations for model z890/z990.
-	  This will be slightly faster but does not work on
-	  older machines such as the z900.
-
-endchoice 
-
-
 config SMP
 	bool "Symmetric multi-processing support"
 	---help---
@@ -121,7 +93,7 @@
 	depends on MARCH_G5
 	help
 	  This option is required for IEEE compliant floating point arithmetic
-	  on older S/390 machines. Say Y unless you know your machine doesn't 
+	  on older S/390 machines. Say Y unless you know your machine doesn't
 	  need this.
 
 config S390_SUPPORT
@@ -150,13 +122,112 @@
 	  This allows you to run 32-bit Linux/ELF binaries on your zSeries
 	  in 64 bit mode. Everybody wants this; say Y.
 
+comment "Code generation options"
+
+choice
+	prompt "Processor type"
+	default MARCH_G5
+
+config MARCH_G5
+	bool "S/390 model G5 and G6"
+	depends on ARCH_S390_31
+	help
+	  Select this to build a 31 bit kernel that works
+	  on all S/390 and zSeries machines.
+
+config MARCH_Z900
+	bool "IBM eServer zSeries model z800 and z900"
+	help
+	  Select this to optimize for zSeries machines. This
+	  will enable some optimizations that are not available
+	  on older 31 bit only CPUs.
+
+config MARCH_Z990
+	bool "IBM eServer zSeries model z890 and z990"
+	help
+	  Select this enable optimizations for model z890/z990.
+	  This will be slightly faster but does not work on
+	  older machines such as the z900.
+
+endchoice
+
+config PACK_STACK
+	bool "Pack kernel stack"
+	help
+	  This option enables the compiler option -mkernel-backchain if it
+	  is available. If the option is available the compiler supports
+	  the new stack layout which dramatically reduces the minimum stack
+	  frame size. With an old compiler a non-leaf function needs a
+	  minimum of 96 bytes on 31 bit and 160 bytes on 64 bit. With
+	  -mkernel-backchain the minimum size drops to 16 byte on 31 bit
+	  and 24 byte on 64 bit.
+
+	  Say Y if you are unsure.
+
+config SMALL_STACK
+	bool "Use 4kb/8kb for kernel stack instead of 8kb/16kb"
+	depends on PACK_STACK
+	help
+	  If you say Y here and the compiler supports the -mkernel-backchain
+	  option the kernel will use a smaller kernel stack size. For 31 bit
+	  the reduced size is 4kb instead of 8kb and for 64 bit it is 8kb
+	  instead of 16kb. This allows to run more thread on a system and
+	  reduces the pressure on the memory management for higher order
+	  page allocations.
+
+	  Say N if you are unsure.
+
+
+config CHECK_STACK
+	bool "Detect kernel stack overflow"
+	help
+	  This option enables the compiler option -mstack-guard and
+	  -mstack-size if they are available. If the compiler supports them
+	  it will emit additional code to each function prolog to trigger
+	  an illegal operation if the kernel stack is about to overflow.
+
+	  Say N if you are unsure.
+
+config STACK_GUARD
+	int "Size of the guard area (128-1024)"
+	range 128 1024
+	depends on CHECK_STACK
+	default "256"
+	help
+	  This allows you to specify the size of the guard area at the lower
+	  end of the kernel stack. If the kernel stack points into the guard
+	  area on function entry an illegal operation is triggered. The size
+	  needs to be a power of 2. Please keep in mind that the size of an
+	  interrupt frame is 184 bytes for 31 bit and 328 bytes on 64 bit.
+	  The minimum size for the stack guard should be 256 for 31 bit and
+	  512 for 64 bit.
+
+config WARN_STACK
+	bool "Emit compiler warnings for function with broken stack usage"
+	help
+	  This option enables the compiler options -mwarn-framesize and
+	  -mwarn-dynamicstack. If the compiler supports these options it
+	  will generate warnings for function which either use alloca or
+	  create a stack frame bigger then CONFIG_WARN_STACK_SIZE.
+
+	  Say N if you are unsure.
+
+config WARN_STACK_SIZE
+	int "Maximum frame size considered safe (128-2048)"
+	range 128 2048
+	depends on WARN_STACK
+	default "256"
+	help
+	  This allows you to specify the maximum frame size a function may
+	  have without the compiler complaining about it.
+
 comment "I/O subsystem configuration"
 
 config MACHCHK_WARNING
 	bool "Process warning machine checks"
 	help
 	  Select this option if you want the machine check handler on IBM S/390 or
-	  zSeries to process warning machine checks (e.g. on power failures). 
+	  zSeries to process warning machine checks (e.g. on power failures).
 	  If unsure, say "Y".
 
 config QDIO
@@ -388,64 +459,10 @@
 
 source "arch/s390/oprofile/Kconfig"
 
-menu "Kernel hacking"
-
-config DEBUG_KERNEL
-	bool "Kernel debugging"
-	help
-	  Say Y here if you are developing drivers or trying to debug and
-	  identify kernel problems.
-
-config MAGIC_SYSRQ
-	bool "Magic SysRq key"
-	depends on DEBUG_KERNEL
-	help
-	  If you say Y here, you will have some control over the system even
-	  if the system crashes for example during kernel debugging (e.g., you
-	  will be able to flush the buffer cache to disk, reboot the system
-	  immediately or dump some status information). This is accomplished
-	  by pressing various keys while holding SysRq (Alt+PrintScreen). It
-	  also works on a serial console (on PC hardware at least), if you
-	  send a BREAK and then within 5 seconds a command keypress. The
-	  keys are documented in <file:Documentation/sysrq.txt>. Don't say Y
-	  unless you really know what this hack does.
-
-config DEBUG_SLAB
-	bool "Debug memory allocations"
-	depends on DEBUG_KERNEL
-	help
-	  Say Y here to have the kernel do limited verification on memory
-	  allocation as well as poisoning memory on free to catch use of freed
-	  memory.
-
-config KALLSYMS
-	bool "Load all symbols for debugging/kksymoops"
-	depends on DEBUG_KERNEL
-	help
-	  Say Y here to let the kernel print out symbolic crash information and
-	  symbolic stack backtraces. This increases the size of the kernel
-	  somewhat, as all symbols have to be loaded into the kernel image.
-
-config DEBUG_INFO
-	bool "Compile the kernel with debug info"
-	depends on DEBUG_KERNEL
-	help
-          If you say Y here the resulting kernel image will include
-	  debugging info resulting in a larger kernel image.
-	  Say Y here only if you plan to use gdb to debug the kernel.
-	  If you don't debug the kernel, you can say N.
-	  
-config DEBUG_SPINLOCK_SLEEP
-	bool "Sleep-inside-spinlock checking"
-	help
-	  If you say Y here, various routines which may sleep will become very
-	  noisy if they are called with a spinlock held.	
-
-endmenu
+source "arch/s390/Kconfig.debug"
 
 source "security/Kconfig"
 
 source "crypto/Kconfig"
 
 source "lib/Kconfig"
-
diff -Nru a/arch/s390/Kconfig.debug b/arch/s390/Kconfig.debug
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/arch/s390/Kconfig.debug	2004-10-18 14:57:23 -07:00
@@ -0,0 +1,5 @@
+menu "Kernel hacking"
+
+source "lib/Kconfig.debug"
+
+endmenu
diff -Nru a/arch/s390/Makefile b/arch/s390/Makefile
--- a/arch/s390/Makefile	2004-10-18 14:56:17 -07:00
+++ b/arch/s390/Makefile	2004-10-18 14:56:17 -07:00
@@ -18,6 +18,7 @@
 CFLAGS		+= -m31
 AFLAGS		+= -m31
 UTS_MACHINE	:= s390
+STACK_SIZE	:= 8192
 endif
 
 ifdef CONFIG_ARCH_S390X
@@ -26,16 +27,37 @@
 CFLAGS		+= -m64
 AFLAGS		+= -m64
 UTS_MACHINE	:= s390x
+STACK_SIZE	:= 16384
 endif
 
-cflags-$(CONFIG_MARCH_G5)   += $(call check_gcc,-march=g5,)
-cflags-$(CONFIG_MARCH_Z900) += $(call check_gcc,-march=z900,)
-cflags-$(CONFIG_MARCH_Z990) += $(call check_gcc,-march=z990,)
+cflags-$(CONFIG_MARCH_G5)   += $(call cc-option,-march=g5)
+cflags-$(CONFIG_MARCH_Z900) += $(call cc-option,-march=z900)
+cflags-$(CONFIG_MARCH_Z990) += $(call cc-option,-march=z990)
 
-CFLAGS		+= $(cflags-y)
-CFLAGS		+= $(call check_gcc,-finline-limit=10000,)
+ifeq ($(call cc-option-yn,-mkernel-backchain),y)
+cflags-$(CONFIG_PACK_STACK)  += -mkernel-backchain -D__PACK_STACK
+aflags-$(CONFIG_PACK_STACK)  += -D__PACK_STACK
+cflags-$(CONFIG_SMALL_STACK) += -D__SMALL_STACK
+aflags-$(CONFIG_SMALL_STACK) += -D__SMALL_STACK
+ifdef CONFIG_SMALL_STACK
+STACK_SIZE := $(shell echo $$(($(STACK_SIZE)/2)) )
+endif
+endif
+
+ifeq ($(call cc-option-yn,-mstack-size=8192 -mstack-guard=128),y)
+cflags-$(CONFIG_CHECK_STACK) += -mstack-size=$(STACK_SIZE)
+cflags-$(CONFIG_CHECK_STACK) += -mstack-guard=$(CONFIG_STACK_GUARD)
+endif
+
+ifeq ($(call cc-option-yn,-mwarn-dynamicstack),y)
+cflags-$(CONFIG_WARN_STACK) += -mwarn-dynamicstack
+cflags-$(CONFIG_WARN_STACK) += -mwarn-framesize=$(CONFIG_WARN_STACK_SIZE)
+endif
+
+CFLAGS		+= -mbackchain $(cflags-y)
+CFLAGS		+= $(call cc-option,-finline-limit=10000)
 CFLAGS 		+= -pipe -fno-strength-reduce -Wno-sign-compare 
-CFLAGS		+= -mbackchain
+AFLAGS		+= $(aflags-y)
 
 OBJCOPYFLAGS	:= -O binary
 LDFLAGS_vmlinux := -e start
diff -Nru a/arch/s390/appldata/appldata_mem.c b/arch/s390/appldata/appldata_mem.c
--- a/arch/s390/appldata/appldata_mem.c	2004-10-18 14:55:55 -07:00
+++ b/arch/s390/appldata/appldata_mem.c	2004-10-18 14:55:55 -07:00
@@ -102,8 +102,12 @@
  */
 static void appldata_get_mem_data(void *data)
 {
-	struct sysinfo val;
-	struct page_state ps;
+	/*
+	 * don't put large structures on the stack, we are
+	 * serialized through the appldata_ops_lock and can use static
+	 */
+	static struct sysinfo val;
+	static struct page_state ps;
 	struct appldata_mem_data *mem_data;
 
 	mem_data = data;
diff -Nru a/arch/s390/defconfig b/arch/s390/defconfig
--- a/arch/s390/defconfig	2004-10-18 14:56:50 -07:00
+++ b/arch/s390/defconfig	2004-10-18 14:56:50 -07:00
@@ -1,5 +1,7 @@
 #
 # Automatically generated make config: don't edit
+# Linux kernel version: 2.6.9-rc3
+# Fri Oct  8 19:17:35 2004
 #
 CONFIG_MMU=y
 CONFIG_RWSEM_XCHGADD_ALGORITHM=y
@@ -15,6 +17,7 @@
 #
 # General setup
 #
+CONFIG_LOCALVERSION=""
 CONFIG_SWAP=y
 CONFIG_SYSVIPC=y
 # CONFIG_POSIX_MQUEUE is not set
@@ -36,6 +39,8 @@
 CONFIG_IOSCHED_DEADLINE=y
 CONFIG_IOSCHED_CFQ=y
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+CONFIG_SHMEM=y
+# CONFIG_TINY_SHMEM is not set
 
 #
 # Loadable module support
@@ -56,15 +61,23 @@
 # CONFIG_ARCH_S390X is not set
 # CONFIG_64BIT is not set
 CONFIG_ARCH_S390_31=y
-CONFIG_MARCH_G5=y
-# CONFIG_MARCH_Z900 is not set
-# CONFIG_MARCH_Z990 is not set
 CONFIG_SMP=y
 CONFIG_NR_CPUS=32
 # CONFIG_HOTPLUG_CPU is not set
 CONFIG_MATHEMU=y
 
 #
+# Code generation options
+#
+CONFIG_MARCH_G5=y
+# CONFIG_MARCH_Z900 is not set
+# CONFIG_MARCH_Z990 is not set
+CONFIG_PACK_STACK=y
+# CONFIG_SMALL_STACK is not set
+# CONFIG_CHECK_STACK is not set
+# CONFIG_WARN_STACK is not set
+
+#
 # I/O subsystem configuration
 #
 CONFIG_MACHCHK_WARNING=y
@@ -130,9 +143,7 @@
 #
 # SCSI low-level drivers
 #
-# CONFIG_SCSI_AIC7XXX_OLD is not set
 # CONFIG_SCSI_SATA is not set
-# CONFIG_SCSI_EATA_PIO is not set
 # CONFIG_SCSI_DEBUG is not set
 CONFIG_ZFCP=y
 CONFIG_CCW=y
@@ -154,7 +165,7 @@
 CONFIG_BLK_DEV_XPRAM=m
 # CONFIG_DCSSBLK is not set
 CONFIG_DASD=y
-# CONFIG_DASD_PROFILE is not set
+CONFIG_DASD_PROFILE=y
 CONFIG_DASD_ECKD=y
 CONFIG_DASD_FBA=y
 CONFIG_DASD_DIAG=y
@@ -168,6 +179,7 @@
 CONFIG_MD_LINEAR=m
 CONFIG_MD_RAID0=m
 CONFIG_MD_RAID1=m
+# CONFIG_MD_RAID10 is not set
 CONFIG_MD_RAID5=m
 # CONFIG_MD_RAID6 is not set
 CONFIG_MD_MULTIPATH=m
@@ -236,11 +248,13 @@
 # CONFIG_INET_AH is not set
 # CONFIG_INET_ESP is not set
 # CONFIG_INET_IPCOMP is not set
+# CONFIG_INET_TUNNEL is not set
 CONFIG_IPV6=y
 # CONFIG_IPV6_PRIVACY is not set
 # CONFIG_INET6_AH is not set
 # CONFIG_INET6_ESP is not set
 # CONFIG_INET6_IPCOMP is not set
+# CONFIG_INET6_TUNNEL is not set
 # CONFIG_IPV6_TUNNEL is not set
 # CONFIG_NETFILTER is not set
 CONFIG_XFRM=y
@@ -419,7 +433,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
@@ -443,6 +456,7 @@
 CONFIG_EXPORTFS=y
 CONFIG_SUNRPC=y
 # CONFIG_RPCSEC_GSS_KRB5 is not set
+# CONFIG_RPCSEC_GSS_SPKM3 is not set
 # CONFIG_SMB_FS is not set
 # CONFIG_CIFS is not set
 # CONFIG_NCP_FS is not set
@@ -486,8 +500,8 @@
 CONFIG_DEBUG_KERNEL=y
 CONFIG_MAGIC_SYSRQ=y
 # CONFIG_DEBUG_SLAB is not set
-# CONFIG_DEBUG_INFO is not set
 # CONFIG_DEBUG_SPINLOCK_SLEEP is not set
+# CONFIG_DEBUG_INFO is not set
 
 #
 # Security options
@@ -506,16 +520,18 @@
 # CONFIG_CRYPTO_SHA1_Z990 is not set
 # CONFIG_CRYPTO_SHA256 is not set
 # CONFIG_CRYPTO_SHA512 is not set
+# CONFIG_CRYPTO_WP512 is not set
 # CONFIG_CRYPTO_DES is not set
 # CONFIG_CRYPTO_DES_Z990 is not set
 # 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/Makefile b/arch/s390/kernel/Makefile
--- a/arch/s390/kernel/Makefile	2004-10-18 14:57:04 -07:00
+++ b/arch/s390/kernel/Makefile	2004-10-18 14:57:04 -07:00
@@ -6,11 +6,11 @@
 
 obj-y	:=  bitmap.o traps.o time.o process.o \
             setup.o sys_s390.o ptrace.o signal.o cpcmd.o ebcdic.o \
-            semaphore.o s390_ext.o debug.o profile.o
+            semaphore.o s390_ext.o debug.o profile.o irq.o
 
 extra-$(CONFIG_ARCH_S390_31)	+= head.o 
 extra-$(CONFIG_ARCH_S390X)	+= head64.o 
-extra-y				+= init_task.o vmlinux.lds.s
+extra-y				+= init_task.o vmlinux.lds
 
 obj-$(CONFIG_MODULES)		+= s390_ksyms.o module.o
 obj-$(CONFIG_SMP)		+= smp.o
diff -Nru a/arch/s390/kernel/asm-offsets.c b/arch/s390/kernel/asm-offsets.c
--- a/arch/s390/kernel/asm-offsets.c	2004-10-18 14:56:21 -07:00
+++ b/arch/s390/kernel/asm-offsets.c	2004-10-18 14:56:21 -07:00
@@ -39,5 +39,9 @@
 	DEFINE(__PT_ILC, offsetof(struct pt_regs, ilc),);
 	DEFINE(__PT_TRAP, offsetof(struct pt_regs, trap),);
 	DEFINE(__PT_SIZE, sizeof(struct pt_regs),);
+	BLANK();
+	DEFINE(__SF_BACKCHAIN, offsetof(struct stack_frame, back_chain),);
+	DEFINE(__SF_GPRS, offsetof(struct stack_frame, gprs),);
+	DEFINE(__SF_EMPTY, offsetof(struct stack_frame, empty1),);
 	return 0;
 }
diff -Nru a/arch/s390/kernel/compat_exec.c b/arch/s390/kernel/compat_exec.c
--- a/arch/s390/kernel/compat_exec.c	2004-10-18 14:56:50 -07:00
+++ b/arch/s390/kernel/compat_exec.c	2004-10-18 14:56:50 -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-10-18 14:56:49 -07:00
+++ b/arch/s390/kernel/compat_linux.c	2004-10-18 14:56:49 -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-10-18 14:57:03 -07:00
+++ b/arch/s390/kernel/compat_signal.c	2004-10-18 14:57:03 -07:00
@@ -118,10 +118,10 @@
 	err |= __get_user(to->si_errno, &from->si_errno);
 	err |= __get_user(to->si_code, &from->si_code);
 
-	if (from->si_code < 0)
+	if (to->si_code < 0)
 		err |= __copy_from_user(&to->_sifields._pad, &from->_sifields._pad, SI_PAD_SIZE);
 	else {
-		switch (from->si_code >> 16) {
+		switch (to->si_code >> 16) {
 		case __SI_RT >> 16: /* This is not generated by the kernel as of now.  */
 		case __SI_MESGQ >> 16:
 			err |= __get_user(to->si_int, &from->si_int);
@@ -218,14 +218,17 @@
 		 struct old_sigaction32 __user *oact)
 {
         struct k_sigaction new_ka, old_ka;
+	unsigned long sa_handler, sa_restorer;
         int ret;
 
         if (act) {
 		compat_old_sigset_t mask;
 		if (verify_area(VERIFY_READ, act, sizeof(*act)) ||
-		    __get_user((unsigned long)new_ka.sa.sa_handler, &act->sa_handler) ||
-		    __get_user((unsigned long)new_ka.sa.sa_restorer, &act->sa_restorer))
+		    __get_user(sa_handler, &act->sa_handler) ||
+		    __get_user(sa_restorer, &act->sa_restorer))
 			return -EFAULT;
+		new_ka.sa.sa_handler = (__sighandler_t) sa_handler;
+		new_ka.sa.sa_restorer = (void (*)(void)) sa_restorer;
 		__get_user(new_ka.sa.sa_flags, &act->sa_flags);
 		__get_user(mask, &act->sa_mask);
 		siginitset(&new_ka.sa.sa_mask, mask);
@@ -234,9 +237,11 @@
         ret = do_sigaction(sig, act ? &new_ka : NULL, oact ? &old_ka : NULL);
 
 	if (!ret && oact) {
+		sa_handler = (unsigned long) old_ka.sa.sa_handler;
+		sa_restorer = (unsigned long) old_ka.sa.sa_restorer;
 		if (verify_area(VERIFY_WRITE, oact, sizeof(*oact)) ||
-		    __put_user((unsigned long)old_ka.sa.sa_handler, &oact->sa_handler) ||
-		    __put_user((unsigned long)old_ka.sa.sa_restorer, &oact->sa_restorer))
+		    __put_user(sa_handler, &oact->sa_handler) ||
+		    __put_user(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);
@@ -253,6 +258,7 @@
 	   struct sigaction32 __user *oact,  size_t sigsetsize)
 {
 	struct k_sigaction new_ka, old_ka;
+	unsigned long sa_handler;
 	int ret;
 	compat_sigset_t set32;
 
@@ -261,7 +267,7 @@
 		return -EINVAL;
 
 	if (act) {
-		ret = get_user((unsigned long)new_ka.sa.sa_handler, &act->sa_handler);
+		ret = get_user(sa_handler, &act->sa_handler);
 		ret |= __copy_from_user(&set32, &act->sa_mask,
 					sizeof(compat_sigset_t));
 		switch (_NSIG_WORDS) {
@@ -278,6 +284,7 @@
 		
 		if (ret)
 			return -EFAULT;
+		new_ka.sa.sa_handler = (__sighandler_t) sa_handler;
 	}
 
 	ret = do_sigaction(sig, act ? &new_ka : NULL, oact ? &old_ka : NULL);
@@ -311,17 +318,19 @@
 							struct pt_regs *regs)
 {
 	stack_t kss, koss;
+	unsigned long ss_sp;
 	int ret, err = 0;
 	mm_segment_t old_fs = get_fs();
 
 	if (uss) {
 		if (!access_ok(VERIFY_READ, uss, sizeof(*uss)))
 			return -EFAULT;
-		err |= __get_user((unsigned long) kss.ss_sp, &uss->ss_sp);
+		err |= __get_user(ss_sp, &uss->ss_sp);
 		err |= __get_user(kss.ss_size, &uss->ss_size);
 		err |= __get_user(kss.ss_flags, &uss->ss_flags);
 		if (err)
 			return -EFAULT;
+		kss.ss_sp = (void *) ss_sp;
 	}
 
 	set_fs (KERNEL_DS);
@@ -333,7 +342,8 @@
 	if (!ret && uoss) {
 		if (!access_ok(VERIFY_WRITE, uoss, sizeof(*uoss)))
 			return -EFAULT;
-		err |= __put_user((unsigned long) koss.ss_sp, &uoss->ss_sp);
+		ss_sp = (unsigned long) koss.ss_sp;
+		err |= __put_user(ss_sp, &uoss->ss_sp);
 		err |= __put_user(koss.ss_size, &uoss->ss_size);
 		err |= __put_user(koss.ss_flags, &uoss->ss_flags);
 		if (err)
@@ -552,9 +562,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 +612,7 @@
 	return;
 
 give_sigsegv:
-	if (sig == SIGSEGV)
-		ka->sa.sa_handler = SIG_DFL;
-	force_sig(SIGSEGV, current);
+	force_sigsegv(sig, current);
 }
 
 /*
@@ -614,19 +620,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/debug.c b/arch/s390/kernel/debug.c
--- a/arch/s390/kernel/debug.c	2004-10-18 14:55:55 -07:00
+++ b/arch/s390/kernel/debug.c	2004-10-18 14:55:55 -07:00
@@ -24,7 +24,6 @@
 
 #include <asm/debug.h>
 
-#define MIN(a,b) (((a)<(b))?(a):(b))
 #define DEBUG_PROLOG_ENTRY -1
 
 /* typedefs */
@@ -435,7 +434,7 @@
 
 	while(count < len){
 		size = debug_format_entry(p_info);
-		size = MIN((len - count), (size - entry_offset));
+		size = min((len - count), (size - entry_offset));
 
 		if(size){
 			if (copy_to_user(user_buf + count, 
@@ -723,7 +722,7 @@
 	spin_lock_irqsave(&id->lock, flags);
 	active = get_active_entry(id);
 	memset(DEBUG_DATA(active), 0, id->buf_size);
-	memcpy(DEBUG_DATA(active), buf, MIN(len, id->buf_size));
+	memcpy(DEBUG_DATA(active), buf, min(len, id->buf_size));
 	debug_finish_entry(id, active, level, 0);
 	spin_unlock_irqrestore(&id->lock, flags);
 
@@ -744,7 +743,7 @@
 	spin_lock_irqsave(&id->lock, flags);
 	active = get_active_entry(id);
 	memset(DEBUG_DATA(active), 0, id->buf_size);
-	memcpy(DEBUG_DATA(active), buf, MIN(len, id->buf_size));
+	memcpy(DEBUG_DATA(active), buf, min(len, id->buf_size));
 	debug_finish_entry(id, active, level, 1);
 	spin_unlock_irqrestore(&id->lock, flags);
 
@@ -789,7 +788,7 @@
 	curr_event=(debug_sprintf_entry_t *) DEBUG_DATA(active);
 	va_start(ap,string);
 	curr_event->string=string;
-	for(idx=0;idx<MIN(numargs,((id->buf_size / sizeof(long))-1));idx++)
+	for(idx=0;idx<min(numargs,(int)(id->buf_size / sizeof(long))-1);idx++)
 		curr_event->args[idx]=va_arg(ap,long);
 	va_end(ap);
 	debug_finish_entry(id, active, level, 0);
@@ -821,7 +820,7 @@
 	curr_event=(debug_sprintf_entry_t *)DEBUG_DATA(active);
 	va_start(ap,string);
 	curr_event->string=string;
-	for(idx=0;idx<MIN(numargs,((id->buf_size / sizeof(long))-1));idx++)
+	for(idx=0;idx<min(numargs,(int)(id->buf_size / sizeof(long))-1);idx++)
 		curr_event->args[idx]=va_arg(ap,long);
 	va_end(ap);
 	debug_finish_entry(id, active, level, 1);
@@ -1157,7 +1156,7 @@
 	}
 
 	/* number of arguments used for sprintf (without the format string) */
-	num_used_args   = MIN(DEBUG_SPRINTF_MAX_ARGS, (num_longs - 1));
+	num_used_args   = min(DEBUG_SPRINTF_MAX_ARGS, (num_longs - 1));
 
 	memset(index,0, DEBUG_SPRINTF_MAX_ARGS * sizeof(int));
 
diff -Nru a/arch/s390/kernel/ebcdic.c b/arch/s390/kernel/ebcdic.c
--- a/arch/s390/kernel/ebcdic.c	2004-10-18 14:57:05 -07:00
+++ b/arch/s390/kernel/ebcdic.c	2004-10-18 14:57:05 -07:00
@@ -391,10 +391,10 @@
 	0xF8, 0xF9, 0xFA, 0xFB, 0xFC, 0xFD, 0xFE, 0xFF
 };
 
-EXPORT_SYMBOL_NOVERS(_ascebc_500);
-EXPORT_SYMBOL_NOVERS(_ebcasc_500);
-EXPORT_SYMBOL_NOVERS(_ascebc);
-EXPORT_SYMBOL_NOVERS(_ebcasc);
-EXPORT_SYMBOL_NOVERS(_ebc_tolower);
-EXPORT_SYMBOL_NOVERS(_ebc_toupper);
+EXPORT_SYMBOL(_ascebc_500);
+EXPORT_SYMBOL(_ebcasc_500);
+EXPORT_SYMBOL(_ascebc);
+EXPORT_SYMBOL(_ebcasc);
+EXPORT_SYMBOL(_ebc_tolower);
+EXPORT_SYMBOL(_ebc_toupper);
 
diff -Nru a/arch/s390/kernel/entry.S b/arch/s390/kernel/entry.S
--- a/arch/s390/kernel/entry.S	2004-10-18 14:56:17 -07:00
+++ b/arch/s390/kernel/entry.S	2004-10-18 14:56:17 -07:00
@@ -19,6 +19,7 @@
 #include <asm/thread_info.h>
 #include <asm/offsets.h>
 #include <asm/unistd.h>
+#include <asm/page.h>
 
 /*
  * Stack layout for the system_call stack entry.
@@ -52,6 +53,9 @@
 		 _TIF_RESTART_SVC | _TIF_SINGLE_STEP )
 _TIF_WORK_INT = (_TIF_SIGPENDING | _TIF_NEED_RESCHED)
 
+STACK_SHIFT = PAGE_SHIFT + THREAD_ORDER
+STACK_SIZE  = 1 << STACK_SHIFT
+
 #define BASED(name) name-system_call(%r13)
 
 /*
@@ -86,10 +90,16 @@
 	bnz	BASED(1f)
 0:	l	%r14,__LC_ASYNC_STACK	# are we already on the async stack ?
 	slr	%r14,%r15
-	sra	%r14,13
+	sra	%r14,STACK_SHIFT
 	be	BASED(2f)
 1:	l	%r15,__LC_ASYNC_STACK
 	.endif
+#ifdef CONFIG_CHECK_STACK
+	b	BASED(3f)
+2:	tml	%r15,STACK_SIZE - CONFIG_STACK_GUARD
+	bz	BASED(stack_overflow)
+3:
+#endif
 2:	s	%r15,BASED(.Lc_spsize)	# make room for registers & psw
 	mvc	SP_PSW(8,%r15),0(%r12)	# move user PSW to stack
 	la	%r12,\psworg
@@ -99,7 +109,7 @@
 	st	%r12,SP_ILC(%r15)
 	mvc	SP_R12(16,%r15),\savearea # move %r12-%r15 to stack
 	la	%r12,0
-	st	%r12,0(%r15)		# clear back chain
+	st	%r12,__SF_BACKCHAIN(%r15)	# clear back chain
 	.endm
 
 	.macro  RESTORE_ALL sync
@@ -124,46 +134,22 @@
 __switch_to_base:
 	tm	__THREAD_per(%r3),0xe8		# new process is using per ?
 	bz	__switch_to_noper-__switch_to_base(%r1)	# if not we're fine
-        stctl   %c9,%c11,24(%r15)		# We are using per stuff
-        clc     __THREAD_per(12,%r3),24(%r15)
+        stctl   %c9,%c11,__SF_EMPTY(%r15)	# We are using per stuff
+        clc     __THREAD_per(12,%r3),__SF_EMPTY(%r15)
         be      __switch_to_noper-__switch_to_base(%r1)	# we got away w/o bashing TLB's
         lctl    %c9,%c11,__THREAD_per(%r3)	# Nope we didn't
 __switch_to_noper:
-        stm     %r6,%r15,24(%r15)       # store __switch_to registers of prev task
+        stm     %r6,%r15,__SF_GPRS(%r15)# store __switch_to registers of prev task
 	st	%r15,__THREAD_ksp(%r2)	# store kernel stack to prev->tss.ksp
 	l	%r15,__THREAD_ksp(%r3)	# load kernel stack from next->tss.ksp
-	lm	%r6,%r15,24(%r15)	# load __switch_to registers of next task
+	lm	%r6,%r15,__SF_GPRS(%r15)# load __switch_to registers of next task
 	st	%r3,__LC_CURRENT	# __LC_CURRENT = current task struct
 	l	%r3,__THREAD_info(%r3)  # load thread_info from task struct
 	st	%r3,__LC_THREAD_INFO
-	ahi	%r3,8192
+	ahi	%r3,STACK_SIZE
 	st	%r3,__LC_KERNEL_STACK	# __LC_KERNEL_STACK = new kernel stack
 	br	%r14
 
-/*
- * do_softirq calling function. We want to run the softirq functions on the
- * asynchronous interrupt stack.
- */
-	.global do_call_softirq
-do_call_softirq:
-	stnsm	24(%r15),0xfc
-	stm	%r12,%r15,28(%r15)
-	lr	%r12,%r15
-        basr    %r13,0
-do_call_base:
-	l	%r0,__LC_ASYNC_STACK
-	slr     %r0,%r15
-	sra	%r0,13
-	be	0f-do_call_base(%r13)
-	l	%r15,__LC_ASYNC_STACK
-0:	sl	%r15,.Lc_overhead-do_call_base(%r13)
-        st	%r12,0(%r15)	# store backchain
-	l	%r1,.Ldo_softirq-do_call_base(%r13)
-	basr	%r14,%r1
-	lm	%r12,%r15,28(%r12)
-	ssm	24(%r15)
-	br	%r14
-	
 __critical_start:
 /*
  * SVC interrupt handler routine. System calls are synchronous events and
@@ -304,9 +290,12 @@
 ret_from_fork:
 	l	%r13,__LC_SVC_NEW_PSW+4
 	l	%r9,__LC_THREAD_INFO	# load pointer to thread_info struct
-        l       %r1,BASED(.Lschedtail)
+	tm	SP_PSW+1(%r15),0x01	# forking a kernel thread ?
+	bo	BASED(0f)
+	st	%r15,SP_R15(%r15)	# store stack pointer for new kthread
+0:	l       %r1,BASED(.Lschedtail)
 	basr    %r14,%r1
-        stosm   24(%r15),0x03     # reenable interrupts
+        stosm   __SF_EMPTY(%r15),0x03     # reenable interrupts
 	b	BASED(sysc_return)
 
 #
@@ -457,7 +446,7 @@
 	mvc	__THREAD_per+__PER_address(4,%r1),__LC_PER_ADDRESS
 	mvc	__THREAD_per+__PER_access_id(1,%r1),__LC_PER_ACCESS_ID
 	oi	__TI_flags+3(%r9),_TIF_SINGLE_STEP # set TIF_SINGLE_STEP
-	stosm	24(%r15),0x03		# reenable interrupts
+	stosm	__SF_EMPTY(%r15),0x03	# reenable interrupts
 	b	BASED(sysc_do_svc)
 
 /*
@@ -493,16 +482,16 @@
 	l	%r1,SP_R15(%r15)
 	s	%r1,BASED(.Lc_spsize)
 	mvc	SP_PTREGS(__PT_SIZE,%r1),SP_PTREGS(%r15)
-        xc      0(4,%r1),0(%r1)        # clear back chain
+        xc      __SF_BACKCHAIN(4,%r1),__SF_BACKCHAIN(%r1) # clear back chain
 	lr	%r15,%r1
 io_resume_loop:
 	tm	__TI_flags+3(%r9),_TIF_NEED_RESCHED
 	bno	BASED(io_leave)
 	mvc     __TI_precount(4,%r9),BASED(.Lc_pactive)
-        stosm   24(%r15),0x03          # reenable interrupts
+        stosm   __SF_EMPTY(%r15),0x03  # reenable interrupts
         l       %r1,BASED(.Lschedule)
 	basr	%r14,%r1	       # call schedule
-        stnsm   24(%r15),0xfc          # disable I/O and ext. interrupts
+        stnsm   __SF_EMPTY(%r15),0xfc  # disable I/O and ext. interrupts
 	xc      __TI_precount(4,%r9),__TI_precount(%r9)
 	b	BASED(io_resume_loop)
 #endif
@@ -514,7 +503,7 @@
 	l	%r1,__LC_KERNEL_STACK
 	s	%r1,BASED(.Lc_spsize)
 	mvc	SP_PTREGS(__PT_SIZE,%r1),SP_PTREGS(%r15)
-        xc      0(4,%r1),0(%r1)        # clear back chain
+        xc      __SF_BACKCHAIN(4,%r1),__SF_BACKCHAIN(%r1) # clear back chain
 	lr	%r15,%r1
 #
 # One of the work bits is on. Find out which one.
@@ -532,9 +521,9 @@
 #	
 io_reschedule:        
         l       %r1,BASED(.Lschedule)
-        stosm   24(%r15),0x03          # reenable interrupts
+        stosm   __SF_EMPTY(%r15),0x03  # reenable interrupts
 	basr    %r14,%r1	       # call scheduler
-        stnsm   24(%r15),0xfc          # disable I/O and ext. interrupts
+        stnsm   __SF_EMPTY(%r15),0xfc  # disable I/O and ext. interrupts
 	tm	__TI_flags+3(%r9),_TIF_WORK_INT
 	bz	BASED(io_leave)        # there is no work to do
 	b	BASED(io_work_loop)
@@ -543,12 +532,12 @@
 # _TIF_SIGPENDING is set, call do_signal
 #
 io_sigpending:     
-        stosm   24(%r15),0x03          # reenable interrupts
+        stosm   __SF_EMPTY(%r15),0x03  # reenable interrupts
         la      %r2,SP_PTREGS(%r15)    # load pt_regs
         sr      %r3,%r3                # clear *oldset
         l       %r1,BASED(.Ldo_signal)
 	basr    %r14,%r1	       # call do_signal
-        stnsm   24(%r15),0xfc          # disable I/O and ext. interrupts
+        stnsm   __SF_EMPTY(%r15),0xfc  # disable I/O and ext. interrupts
 	b	BASED(io_leave)        # out of here, do NOT recheck
 
 /*
@@ -589,8 +578,8 @@
         l       %r15,__LC_SAVE_AREA+60 # load ksp
         lctl    %c0,%c15,__LC_CREGS_SAVE_AREA # get new ctl regs
         lam     %a0,%a15,__LC_AREGS_SAVE_AREA
-        stosm   0(%r15),0x04           # now we can turn dat on
-        lm      %r6,%r15,24(%r15)      # load registers from clone
+        lm      %r6,%r15,__SF_GPRS(%r15) # load registers from clone
+        stosm   __SF_EMPTY(%r15),0x04    # now we can turn dat on
         basr    %r14,0
         l       %r14,restart_addr-.(%r14)
         br      %r14                   # branch to start_secondary
@@ -611,6 +600,31 @@
 restart_go:
 #endif
 
+#ifdef CONFIG_CHECK_STACK
+/*
+ * The synchronous or the asynchronous stack overflowed. We are dead.
+ * No need to properly save the registers, we are going to panic anyway.
+ * Setup a pt_regs so that show_trace can provide a good call trace.
+ */
+stack_overflow:
+	l	%r15,__LC_PANIC_STACK	# change to panic stack
+	sl	%r15,BASED(.Lc_spsize)
+	mvc	SP_PSW(8,%r15),0(%r12)	# move user PSW to stack
+	stm	%r0,%r11,SP_R0(%r15)	# store gprs %r0-%r11 to kernel stack
+	la	%r1,__LC_SAVE_AREA
+	ch	%r12,BASED(.L0x020)	# old psw addr == __LC_SVC_OLD_PSW ?
+	be	BASED(0f)
+	ch	%r12,BASED(.L0x028)	# old psw addr == __LC_PGM_OLD_PSW ?
+	be	BASED(0f)
+	la	%r1,__LC_SAVE_AREA+16
+0:	mvc	SP_R12(16,%r15),0(%r1)	# move %r12-%r15 to stack
+        xc      __SF_BACKCHAIN(4,%r15),__SF_BACKCHAIN(%r15) # clear back chain
+	l	%r1,BASED(1f)		# branch to kernel_stack_overflow
+        la      %r2,SP_PTREGS(%r15)	# load pt_regs
+	br	%r1
+1:	.long  kernel_stack_overflow
+#endif
+
 cleanup_table_system_call:
 	.long	system_call + 0x80000000, sysc_do_svc + 0x80000000
 cleanup_table_sysc_return:
@@ -695,7 +709,6 @@
 .Ldo_IRQ:      .long  do_IRQ
 .Ldo_extint:   .long  do_extint
 .Ldo_signal:   .long  do_signal
-.Ldo_softirq:  .long  do_softirq
 .Lhandle_per:  .long  do_single_step
 .Ljump_table:  .long  pgm_check_table
 .Lschedule:    .long  schedule
diff -Nru a/arch/s390/kernel/entry64.S b/arch/s390/kernel/entry64.S
--- a/arch/s390/kernel/entry64.S	2004-10-18 14:56:17 -07:00
+++ b/arch/s390/kernel/entry64.S	2004-10-18 14:56:17 -07:00
@@ -19,6 +19,7 @@
 #include <asm/thread_info.h>
 #include <asm/offsets.h>
 #include <asm/unistd.h>
+#include <asm/page.h>
 
 /*
  * Stack layout for the system_call stack entry.
@@ -48,6 +49,9 @@
 SP_TRAP      =  STACK_FRAME_OVERHEAD + __PT_TRAP
 SP_SIZE      =  STACK_FRAME_OVERHEAD + __PT_SIZE
 
+STACK_SHIFT = PAGE_SHIFT + THREAD_ORDER
+STACK_SIZE  = 1 << STACK_SHIFT
+
 _TIF_WORK_SVC = (_TIF_SIGPENDING | _TIF_NEED_RESCHED | \
 		 _TIF_RESTART_SVC | _TIF_SINGLE_STEP )
 _TIF_WORK_INT = (_TIF_SIGPENDING | _TIF_NEED_RESCHED)
@@ -85,10 +89,16 @@
 	jnz	1f
 0:	lg	%r14,__LC_ASYNC_STACK	# are we already on the async. stack ?
 	slgr	%r14,%r15
-	srag	%r14,%r14,14
+	srag	%r14,%r14,STACK_SHIFT
 	jz	2f
 1:	lg	%r15,__LC_ASYNC_STACK	# load async stack
 	.endif
+#ifdef CONFIG_CHECK_STACK
+	j	3f
+2:	tml	%r15,STACK_SIZE - CONFIG_STACK_GUARD
+	jz	stack_overflow
+3:
+#endif
 2:	aghi    %r15,-SP_SIZE		# make room for registers & psw
 	mvc     SP_PSW(16,%r15),0(%r12)	# move user PSW to stack
 	la	%r12,\psworg
@@ -98,7 +108,7 @@
 	st	%r12,SP_ILC(%r15)
 	mvc	SP_R12(32,%r15),\savearea # move %r12-%r15 to stack
 	la	%r12,0
-	stg	%r12,0(%r15)
+	stg	%r12,__SF_BACKCHAIN(%r15)
         .endm
 
 	.macro	RESTORE_ALL sync
@@ -121,43 +131,22 @@
 __switch_to:
 	tm	__THREAD_per+4(%r3),0xe8 # is the new process using per ?
 	jz	__switch_to_noper		# if not we're fine
-        stctg   %c9,%c11,48(%r15)       # We are using per stuff
-        clc     __THREAD_per(24,%r3),48(%r15)
+        stctg   %c9,%c11,__SF_EMPTY(%r15)# We are using per stuff
+        clc     __THREAD_per(24,%r3),__SF_EMPTY(%r15)
         je      __switch_to_noper            # we got away without bashing TLB's
         lctlg   %c9,%c11,__THREAD_per(%r3)	# Nope we didn't
 __switch_to_noper:
-        stmg    %r6,%r15,48(%r15)       # store __switch_to registers of prev task
+        stmg    %r6,%r15,__SF_GPRS(%r15)# store __switch_to registers of prev task
 	stg	%r15,__THREAD_ksp(%r2)	# store kernel stack to prev->tss.ksp
 	lg	%r15,__THREAD_ksp(%r3)	# load kernel stack from next->tss.ksp
-        lmg     %r6,%r15,48(%r15)       # load __switch_to registers of next task
+        lmg     %r6,%r15,__SF_GPRS(%r15)# load __switch_to registers of next task
 	stg	%r3,__LC_CURRENT	# __LC_CURRENT = current task struct
 	lg	%r3,__THREAD_info(%r3)  # load thread_info from task struct
 	stg	%r3,__LC_THREAD_INFO
-	aghi	%r3,16384
+	aghi	%r3,STACK_SIZE
 	stg	%r3,__LC_KERNEL_STACK	# __LC_KERNEL_STACK = new kernel stack
 	br	%r14
 
-/*
- * do_softirq calling function. We want to run the softirq functions on the
- * asynchronous interrupt stack.
- */
-	.global do_call_softirq
-do_call_softirq:
-	stnsm	48(%r15),0xfc
-	stmg	%r12,%r15,56(%r15)
-	lgr	%r12,%r15
-	lg	%r0,__LC_ASYNC_STACK
-	slgr    %r0,%r15
-	srag	%r0,%r0,14
-	je	0f
-	lg	%r15,__LC_ASYNC_STACK
-0:	aghi	%r15,-STACK_FRAME_OVERHEAD
-	stg	%r12,0(%r15)		# store back chain
-	brasl	%r14,do_softirq
-	lmg	%r12,%r15,56(%r12)
-	ssm	48(%r15)
-	br	%r14
-
 __critical_start:
 /*
  * SVC interrupt handler routine. System calls are synchronous events and
@@ -304,7 +293,10 @@
 ret_from_fork:
 	lg	%r13,__LC_SVC_NEW_PSW+8
 	lg	%r9,__LC_THREAD_INFO	# load pointer to thread_info struct
-        brasl   %r14,schedule_tail
+	tm	SP_PSW+1(%r15),0x01	# forking a kernel thread ?
+	jo	0f
+	stg	%r15,SP_R15(%r15)	# store stack pointer for new kthread
+0:	brasl   %r14,schedule_tail
         stosm   24(%r15),0x03     # reenable interrupts
 	j	sysc_return
 
@@ -504,7 +496,7 @@
 	mvc	__THREAD_per+__PER_address(8,%r1),__LC_PER_ADDRESS
 	mvc	__THREAD_per+__PER_access_id(1,%r1),__LC_PER_ACCESS_ID
 	oi	__TI_flags+7(%r9),_TIF_SINGLE_STEP # set TIF_SINGLE_STEP
-	stosm	48(%r15),0x03		# reenable interrupts
+	stosm	__SF_EMPTY(%r15),0x03	# reenable interrupts
 	j	sysc_do_svc
 
 /*
@@ -539,16 +531,16 @@
 	lg	%r1,SP_R15(%r15)
 	aghi	%r1,-SP_SIZE
 	mvc	SP_PTREGS(__PT_SIZE,%r1),SP_PTREGS(%r15)
-        xc      0(8,%r1),0(%r1)        # clear back chain
+        xc      __SF_BACKCHAIN(8,%r1),__SF_BACKCHAIN(%r1) # clear back chain
 	lgr	%r15,%r1
 io_resume_loop:
 	tm	__TI_flags+7(%r9),_TIF_NEED_RESCHED
 	jno	io_leave
 	larl    %r1,.Lc_pactive
 	mvc     __TI_precount(4,%r9),0(%r1)
-        stosm   48(%r15),0x03          # reenable interrupts
+        stosm   __SF_EMPTY(%r15),0x03   # reenable interrupts
 	brasl   %r14,schedule          # call schedule
-        stnsm   48(%r15),0xfc          # disable I/O and ext. interrupts
+        stnsm   __SF_EMPTY(%r15),0xfc   # disable I/O and ext. interrupts
 	xc      __TI_precount(4,%r9),__TI_precount(%r9)
 	j	io_resume_loop
 #endif
@@ -560,7 +552,7 @@
 	lg	%r1,__LC_KERNEL_STACK
 	aghi	%r1,-SP_SIZE
 	mvc	SP_PTREGS(__PT_SIZE,%r1),SP_PTREGS(%r15)
-        xc      0(8,%r1),0(%r1)        # clear back chain
+        xc      __SF_BACKCHAIN(8,%r1),__SF_BACKCHAIN(%r1) # clear back chain
 	lgr	%r15,%r1
 #
 # One of the work bits is on. Find out which one.
@@ -577,23 +569,23 @@
 # _TIF_NEED_RESCHED is set, call schedule
 #	
 io_reschedule:        
-        stosm   48(%r15),0x03       # reenable interrupts
-        brasl   %r14,schedule       # call scheduler
-        stnsm   48(%r15),0xfc       # disable I/O and ext. interrupts
+	stosm   __SF_EMPTY(%r15),0x03	# reenable interrupts
+	brasl   %r14,schedule		# call scheduler
+	stnsm   __SF_EMPTY(%r15),0xfc	# disable I/O and ext. interrupts
 	tm	__TI_flags+7(%r9),_TIF_WORK_INT
-	jz	io_leave               # there is no work to do
+	jz	io_leave		# there is no work to do
 	j	io_work_loop
 
 #
 # _TIF_SIGPENDING is set, call do_signal
 #
 io_sigpending:     
-        stosm   48(%r15),0x03       # reenable interrupts
-        la      %r2,SP_PTREGS(%r15) # load pt_regs
-        slgr    %r3,%r3             # clear *oldset
-	brasl	%r14,do_signal      # call do_signal
-        stnsm   48(%r15),0xfc       # disable I/O and ext. interrupts
-	j	sysc_leave          # out of here, do NOT recheck
+	stosm   __SF_EMPTY(%r15),0x03	# reenable interrupts
+	la      %r2,SP_PTREGS(%r15)	# load pt_regs
+	slgr    %r3,%r3			# clear *oldset
+	brasl	%r14,do_signal		# call do_signal
+	stnsm   __SF_EMPTY(%r15),0xfc	# disable I/O and ext. interrupts
+	j	sysc_leave		# out of here, do NOT recheck
 
 /*
  * External interrupt handler routine
@@ -631,8 +623,8 @@
         lctlg   %c0,%c15,0(%r10) # get new ctl regs
         lghi    %r10,__LC_AREGS_SAVE_AREA
         lam     %a0,%a15,0(%r10)
-        stosm   0(%r15),0x04           # now we can turn dat on
-        lmg     %r6,%r15,48(%r15)      # load registers from clone
+        lmg     %r6,%r15,__SF_GPRS(%r15) # load registers from clone
+        stosm   __SF_EMPTY(%r15),0x04    # now we can turn dat on
 	jg      start_secondary
 #else
 /*
@@ -647,6 +639,29 @@
 restart_crash:
         .long  0x000a0000,0x00000000,0x00000000,0x00000000
 restart_go:
+#endif
+
+#ifdef CONFIG_CHECK_STACK
+/*
+ * The synchronous or the asynchronous stack overflowed. We are dead.
+ * No need to properly save the registers, we are going to panic anyway.
+ * Setup a pt_regs so that show_trace can provide a good call trace.
+ */
+stack_overflow:
+	lg	%r15,__LC_PANIC_STACK	# change to panic stack
+	aghi	%r1,-SP_SIZE
+	mvc	SP_PSW(16,%r15),0(%r12)	# move user PSW to stack
+	stmg	%r0,%r11,SP_R0(%r15)	# store gprs %r0-%r11 to kernel stack
+	la	%r1,__LC_SAVE_AREA
+	chi	%r12,__LC_SVC_OLD_PSW
+	je	0f
+	chi	%r12,__LC_PGM_OLD_PSW
+	je	0f
+	la	%r1,__LC_SAVE_AREA+16
+0:	mvc	SP_R12(32,%r15),0(%r1)  # move %r12-%r15 to stack
+        xc      __SF_BACKCHAIN(8,%r15),__SF_BACKCHAIN(%r15) # clear back chain
+        la      %r2,SP_PTREGS(%r15)	# load pt_regs
+	jg	kernel_stack_overflow
 #endif
 
 cleanup_table_system_call:
diff -Nru a/arch/s390/kernel/head.S b/arch/s390/kernel/head.S
--- a/arch/s390/kernel/head.S	2004-10-18 14:56:27 -07:00
+++ b/arch/s390/kernel/head.S	2004-10-18 14:56:27 -07:00
@@ -31,6 +31,8 @@
 #include <asm/setup.h>
 #include <asm/lowcore.h>
 #include <asm/offsets.h>
+#include <asm/thread_info.h>
+#include <asm/page.h>
 
 #ifndef CONFIG_IPL
         .org   0
@@ -741,10 +743,10 @@
 #
         l     %r15,.Linittu-.LPG2(%r13)
 	mvc   __LC_CURRENT(4),__TI_task(%r15)
-        ahi   %r15,8192                 # init_task_union + 8192
+        ahi   %r15,1<<(PAGE_SHIFT+THREAD_ORDER) # init_task_union + THREAD_SIZE
         st    %r15,__LC_KERNEL_STACK    # set end of kernel stack
         ahi   %r15,-96
-        xc    0(4,%r15),0(%r15)         # set backchain to zero
+        xc    __SF_BACKCHAIN(4,%r15),__SF_BACKCHAIN(%r15) # clear backchain
 
 # check control registers
         stctl  %c0,%c15,0(%r15)
diff -Nru a/arch/s390/kernel/head64.S b/arch/s390/kernel/head64.S
--- a/arch/s390/kernel/head64.S	2004-10-18 14:56:28 -07:00
+++ b/arch/s390/kernel/head64.S	2004-10-18 14:56:28 -07:00
@@ -31,6 +31,8 @@
 #include <asm/setup.h>
 #include <asm/lowcore.h>
 #include <asm/offsets.h>
+#include <asm/thread_info.h>
+#include <asm/page.h>
 
 #ifndef CONFIG_IPL
         .org   0
@@ -741,10 +743,10 @@
 	larl  %r15,init_thread_union
 	lg    %r14,__TI_task(%r15)      # cache current in lowcore
 	stg   %r14,__LC_CURRENT
-        aghi  %r15,16384                # init_task_union + 16384
+        aghi  %r15,1<<(PAGE_SHIFT+THREAD_ORDER) # init_task_union + THREAD_SIZE
         stg   %r15,__LC_KERNEL_STACK    # set end of kernel stack
         aghi  %r15,-160
-        xc    0(8,%r15),0(%r15)         # set backchain to zero
+        xc    __SF_BACKCHAIN(4,%r15),__SF_BACKCHAIN(%r15) # clear backchain
 
 # check control registers
         stctg  %c0,%c15,0(%r15)
diff -Nru a/arch/s390/kernel/irq.c b/arch/s390/kernel/irq.c
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/arch/s390/kernel/irq.c	2004-10-18 14:57:23 -07:00
@@ -0,0 +1,99 @@
+/*
+ *  arch/s390/kernel/irq.c
+ *
+ *  S390 version
+ *    Copyright (C) 2004 IBM Deutschland Entwicklung GmbH, IBM Corporation
+ *    Author(s): Martin Schwidefsky (schwidefsky@de.ibm.com),
+ *
+ * This file contains interrupt related functions.
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/kernel_stat.h>
+#include <linux/interrupt.h>
+#include <linux/seq_file.h>
+#include <linux/cpu.h>
+
+/*
+ * show_interrupts is needed by /proc/interrupts.
+ */
+int show_interrupts(struct seq_file *p, void *v)
+{
+	static const char *intrclass_names[] = { "EXT", "I/O", };
+	int i = *(loff_t *) v, j;
+
+	if (i == 0) {
+		seq_puts(p, "           ");
+		for (j=0; j<NR_CPUS; j++)
+			if (cpu_online(j))
+				seq_printf(p, "CPU%d       ",j);
+		seq_putc(p, '\n');
+	}
+
+	if (i < NR_IRQS) {
+		seq_printf(p, "%s: ", intrclass_names[i]);
+#ifndef CONFIG_SMP
+		seq_printf(p, "%10u ", kstat_irqs(i));
+#else
+		for (j = 0; j < NR_CPUS; j++)
+			if (cpu_online(j))
+				seq_printf(p, "%10u ", kstat_cpu(j).irqs[i]);
+#endif
+                seq_putc(p, '\n');
+
+        }
+
+        return 0;
+}
+
+/*
+ * For compatibilty only. S/390 specific setup of interrupts et al. is done
+ * much later in init_channel_subsystem().
+ */
+void __init
+init_IRQ(void)
+{
+	/* nothing... */
+}
+
+/*
+ * Switch to the asynchronous interrupt stack for softirq execution.
+ */
+extern void __do_softirq(void);
+
+asmlinkage void do_softirq(void)
+{
+	unsigned long flags, old, new;
+
+	if (in_interrupt())
+		return;
+
+	local_irq_save(flags);
+
+	if (local_softirq_pending()) {
+		/* Get current stack pointer. */
+		asm volatile("la %0,0(15)" : "=a" (old));
+		/* Check against async. stack address range. */
+		new = S390_lowcore.async_stack;
+		if (((new - old) >> (PAGE_SHIFT + THREAD_ORDER)) != 0) {
+			/* Need to switch to the async. stack. */
+			new -= STACK_FRAME_OVERHEAD;
+			((struct stack_frame *) new)->back_chain = old;
+
+			asm volatile("   la    15,0(%0)\n"
+				     "   basr  14,%2\n"
+				     "   la    15,0(%1)\n"
+				     : : "a" (new), "a" (old),
+				         "a" (__do_softirq)
+				     : "0", "1", "2", "3", "4", "5",
+				       "cc", "memory" );
+		} else
+			/* We are already on the async stack. */
+			__do_softirq();
+	}
+
+	local_irq_restore(flags);
+}
+
+EXPORT_SYMBOL(do_softirq);
diff -Nru a/arch/s390/kernel/process.c b/arch/s390/kernel/process.c
--- a/arch/s390/kernel/process.c	2004-10-18 14:56:49 -07:00
+++ b/arch/s390/kernel/process.c	2004-10-18 14:56:49 -07:00
@@ -58,14 +58,11 @@
  */
 unsigned long thread_saved_pc(struct task_struct *tsk)
 {
-	unsigned long bc;
+	struct stack_frame *sf;
 
-	bc = *((unsigned long *) tsk->thread.ksp);
-#ifndef CONFIG_ARCH_S390X
-	return *((unsigned long *) (bc+56));
-#else
-	return *((unsigned long *) (bc+112));
-#endif
+	sf = (struct stack_frame *) tsk->thread.ksp;
+	sf = (struct stack_frame *) sf->back_chain;
+	return sf->gprs[8];
 }
 
 /*
@@ -186,41 +183,20 @@
 
 extern void kernel_thread_starter(void);
 
-#ifndef CONFIG_ARCH_S390X
-
 __asm__(".align 4\n"
 	"kernel_thread_starter:\n"
-	"    l     15,0(8)\n"
-	"    sr    15,7\n"
-	"    stosm 24(15),3\n"
-	"    lr    2,10\n"
+	"    la    2,0(10)\n"
 	"    basr  14,9\n"
-	"    sr    2,2\n"
+	"    la    2,0\n"
 	"    br    11\n");
 
-#else /* CONFIG_ARCH_S390X */
-
-__asm__(".align 4\n"
-	"kernel_thread_starter:\n"
-	"    lg    15,0(8)\n"
-	"    sgr   15,7\n"
-	"    stosm 48(15),3\n"
-	"    lgr   2,10\n"
-	"    basr  14,9\n"
-	"    sgr   2,2\n"
-	"    br    11\n");
-
-#endif /* CONFIG_ARCH_S390X */
-
 int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags)
 {
 	struct pt_regs regs;
 
 	memset(&regs, 0, sizeof(regs));
-	regs.psw.mask = PSW_KERNEL_BITS;
+	regs.psw.mask = PSW_KERNEL_BITS | PSW_MASK_IO | PSW_MASK_EXT;
 	regs.psw.addr = (unsigned long) kernel_thread_starter | PSW_ADDR_AMODE;
-	regs.gprs[7] = STACK_FRAME_OVERHEAD + sizeof(struct pt_regs);
-	regs.gprs[8] = __LC_KERNEL_STACK;
 	regs.gprs[9] = (unsigned long) fn;
 	regs.gprs[10] = (unsigned long) arg;
 	regs.gprs[11] = (unsigned long) do_exit;
@@ -253,20 +229,13 @@
 	unsigned long unused,
         struct task_struct * p, struct pt_regs * regs)
 {
-        struct stack_frame
+        struct fake_frame
           {
-            unsigned long back_chain;
-            unsigned long eos;
-            unsigned long glue1;
-            unsigned long glue2;
-            unsigned long scratch[2];
-            unsigned long gprs[10];    /* gprs 6 -15                       */
-            unsigned int  fprs[4];     /* fpr 4 and 6                      */
-            unsigned int  empty[4];
+	    struct stack_frame sf;
             struct pt_regs childregs;
           } *frame;
 
-        frame = ((struct stack_frame *)
+        frame = ((struct fake_frame *)
 		 (THREAD_SIZE + (unsigned long) p->thread_info)) - 1;
         p->thread.ksp = (unsigned long) frame;
 	p->set_child_tid = p->clear_child_tid = NULL;
@@ -274,13 +243,13 @@
         frame->childregs = *regs;
 	frame->childregs.gprs[2] = 0;	/* child returns 0 on fork. */
         frame->childregs.gprs[15] = new_stackp;
-        frame->back_chain = frame->eos = 0;
+        frame->sf.back_chain = 0;
 
         /* new return point is ret_from_fork */
-        frame->gprs[8] = (unsigned long) ret_from_fork;
+        frame->sf.gprs[8] = (unsigned long) ret_from_fork;
 
         /* fake return stack for resume(), don't go back to schedule */
-        frame->gprs[9] = (unsigned long) frame;
+        frame->sf.gprs[9] = (unsigned long) frame;
 
 	/* Save access registers to new thread structure. */
 	save_access_regs(&p->thread.acrs[0]);
@@ -336,7 +305,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);
 }
 
@@ -423,30 +392,26 @@
 
 unsigned long get_wchan(struct task_struct *p)
 {
-	unsigned long r14, r15, bc;
-	unsigned long stack_page;
-	int count = 0;
-	if (!p || p == current || p->state == TASK_RUNNING)
+	struct stack_frame *sf, *low, *high;
+	unsigned long return_address;
+	int count;
+
+	if (!p || p == current || p->state == TASK_RUNNING || !p->thread_info)
 		return 0;
-	stack_page = (unsigned long) p->thread_info;
-	r15 = p->thread.ksp;
-	if (!stack_page || r15 < stack_page ||
-	    r15 >= THREAD_SIZE - sizeof(unsigned long) + stack_page)
+	low = (struct stack_frame *) p->thread_info;
+	high = (struct stack_frame *)
+		((unsigned long) p->thread_info + THREAD_SIZE) - 1;
+	sf = (struct stack_frame *) (p->thread.ksp & PSW_ADDR_INSN);
+	if (sf <= low || sf > high)
 		return 0;
-	bc = (*(unsigned long *) r15) & PSW_ADDR_INSN;
-	do {
-		if (bc < stack_page ||
-		    bc >= THREAD_SIZE - sizeof(unsigned long) + stack_page)
+	for (count = 0; count < 16; count++) {
+		sf = (struct stack_frame *) (sf->back_chain & PSW_ADDR_INSN);
+		if (sf <= low || sf > high)
 			return 0;
-#ifndef CONFIG_ARCH_S390X
-		r14 = (*(unsigned long *) (bc+56)) & PSW_ADDR_INSN;
-#else
-		r14 = *(unsigned long *) (bc+112);
-#endif
-		if (!in_sched_functions(r14))
-			return r14;
-		bc = (*(unsigned long *) bc) & PSW_ADDR_INSN;
-	} while (count++ < 16);
+		return_address = sf->gprs[8] & PSW_ADDR_INSN;
+		if (!in_sched_functions(return_address))
+			return return_address;
+	}
 	return 0;
 }
 
diff -Nru a/arch/s390/kernel/profile.c b/arch/s390/kernel/profile.c
--- a/arch/s390/kernel/profile.c	2004-10-18 14:56:32 -07:00
+++ b/arch/s390/kernel/profile.c	2004-10-18 14:56:32 -07:00
@@ -6,52 +6,15 @@
  *
  */
 #include <linux/proc_fs.h>
+#include <linux/profile.h>
 
 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/s390_ext.c b/arch/s390/kernel/s390_ext.c
--- a/arch/s390/kernel/s390_ext.c	2004-10-18 14:56:29 -07:00
+++ b/arch/s390/kernel/s390_ext.c	2004-10-18 14:56:29 -07:00
@@ -12,6 +12,7 @@
 #include <linux/slab.h>
 #include <linux/errno.h>
 #include <linux/kernel_stat.h>
+#include <linux/interrupt.h>
 
 #include <asm/lowcore.h>
 #include <asm/s390_ext.h>
diff -Nru a/arch/s390/kernel/s390_ksyms.c b/arch/s390/kernel/s390_ksyms.c
--- a/arch/s390/kernel/s390_ksyms.c	2004-10-18 14:56:33 -07:00
+++ b/arch/s390/kernel/s390_ksyms.c	2004-10-18 14:56:33 -07:00
@@ -23,16 +23,18 @@
 /*
  * memory management
  */
-EXPORT_SYMBOL_NOVERS(_oi_bitmap);
-EXPORT_SYMBOL_NOVERS(_ni_bitmap);
-EXPORT_SYMBOL_NOVERS(_zb_findmap);
-EXPORT_SYMBOL_NOVERS(_sb_findmap);
-EXPORT_SYMBOL_NOVERS(__copy_from_user_asm);
-EXPORT_SYMBOL_NOVERS(__copy_to_user_asm);
-EXPORT_SYMBOL_NOVERS(__clear_user_asm);
-EXPORT_SYMBOL_NOVERS(__strncpy_from_user_asm);
-EXPORT_SYMBOL_NOVERS(__strnlen_user_asm);
+EXPORT_SYMBOL(_oi_bitmap);
+EXPORT_SYMBOL(_ni_bitmap);
+EXPORT_SYMBOL(_zb_findmap);
+EXPORT_SYMBOL(_sb_findmap);
+EXPORT_SYMBOL(__copy_from_user_asm);
+EXPORT_SYMBOL(__copy_to_user_asm);
+EXPORT_SYMBOL(__copy_in_user_asm);
+EXPORT_SYMBOL(__clear_user_asm);
+EXPORT_SYMBOL(__strncpy_from_user_asm);
+EXPORT_SYMBOL(__strnlen_user_asm);
 EXPORT_SYMBOL(diag10);
+EXPORT_SYMBOL(default_storage_key);
 
 /*
  * semaphore ops
@@ -60,6 +62,5 @@
 EXPORT_SYMBOL(console_mode);
 EXPORT_SYMBOL(console_devno);
 EXPORT_SYMBOL(console_irq);
-EXPORT_SYMBOL_NOVERS(do_call_softirq);
 EXPORT_SYMBOL(sys_wait4);
 EXPORT_SYMBOL(cpcmd);
diff -Nru a/arch/s390/kernel/setup.c b/arch/s390/kernel/setup.c
--- a/arch/s390/kernel/setup.c	2004-10-18 14:55:54 -07:00
+++ b/arch/s390/kernel/setup.c	2004-10-18 14:55:54 -07:00
@@ -53,6 +53,7 @@
 unsigned int console_irq = -1;
 unsigned long memory_size = 0;
 unsigned long machine_flags = 0;
+unsigned int default_storage_key = 0;
 struct {
 	unsigned long addr, size, type;
 } memory_chunk[MEMORY_CHUNKS] = { { 0 } };
@@ -503,6 +504,10 @@
 	lc->kernel_stack = ((unsigned long) &init_thread_union) + THREAD_SIZE;
 	lc->async_stack = (unsigned long)
 		__alloc_bootmem(ASYNC_SIZE, ASYNC_SIZE, 0) + ASYNC_SIZE;
+#ifdef CONFIG_CHECK_STACK
+	lc->panic_stack = (unsigned long)
+		__alloc_bootmem(PAGE_SIZE, PAGE_SIZE, 0) + PAGE_SIZE;
+#endif
 	lc->current_task = (unsigned long) init_thread_union.thread_info.task;
 	lc->thread_info = (unsigned long) &init_thread_union;
 #ifdef CONFIG_ARCH_S390X
@@ -604,49 +609,3 @@
 	.show	= show_cpuinfo,
 };
 
-/*
- * show_interrupts is needed by /proc/interrupts.
- */
-
-static const char *intrclass_names[] = {
-	"EXT",
-	"I/O",
-};
-
-int show_interrupts(struct seq_file *p, void *v)
-{
-        int i = *(loff_t *) v, j;
-	
-	if (i == 0) {
-		seq_puts(p, "           ");
-		for (j=0; j<NR_CPUS; j++)
-			if (cpu_online(j))
-				seq_printf(p, "CPU%d       ",j);
-		seq_putc(p, '\n');
-	}
-	
-	if (i < NR_IRQS) {
-		seq_printf(p, "%s: ", intrclass_names[i]);
-#ifndef CONFIG_SMP
-		seq_printf(p, "%10u ", kstat_irqs(i));
-#else
-		for (j = 0; j < NR_CPUS; j++)
-			if (cpu_online(j))
-				seq_printf(p, "%10u ", kstat_cpu(j).irqs[i]);
-#endif
-                seq_putc(p, '\n');
-		
-        }
-	
-        return 0;
-}
-
-/*
- * For compatibilty only. S/390 specific setup of interrupts et al. is done
- * much later in init_channel_subsystem().
- */
-void __init
-init_IRQ(void)
-{
-	/* nothing... */
-}
diff -Nru a/arch/s390/kernel/signal.c b/arch/s390/kernel/signal.c
--- a/arch/s390/kernel/signal.c	2004-10-18 14:56:49 -07:00
+++ b/arch/s390/kernel/signal.c	2004-10-18 14:56:49 -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-10-18 14:55:53 -07:00
+++ b/arch/s390/kernel/smp.c	2004-10-18 14:55:53 -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;
 }
 
@@ -643,6 +637,7 @@
 {
 	struct task_struct *idle;
         struct _lowcore    *cpu_lowcore;
+	struct stack_frame *sf;
         sigp_ccode          ccode;
 	int                 curr_cpu;
 
@@ -666,9 +661,14 @@
 
 	idle = current_set[cpu];
         cpu_lowcore = lowcore_ptr[cpu];
-	cpu_lowcore->save_area[15] = idle->thread.ksp;
 	cpu_lowcore->kernel_stack = (unsigned long)
 		idle->thread_info + (THREAD_SIZE);
+	sf = (struct stack_frame *) (cpu_lowcore->kernel_stack
+				     - sizeof(struct pt_regs)
+				     - sizeof(struct stack_frame));
+	memset(sf, 0, sizeof(struct stack_frame));
+	sf->gprs[9] = (unsigned long) sf;
+	cpu_lowcore->save_area[15] = (unsigned long) sf;
 	__ctl_store(cpu_lowcore->cregs_save_area[0], 0, 15);
 	__asm__ __volatile__("stam  0,15,0(%0)"
 			     : : "a" (&cpu_lowcore->access_regs_save_area)
@@ -747,7 +747,7 @@
 
 void __init smp_prepare_cpus(unsigned int max_cpus)
 {
-	unsigned long async_stack;
+	unsigned long stack;
 	unsigned int cpu;
         int i;
 
@@ -767,12 +767,18 @@
 		lowcore_ptr[i] = (struct _lowcore *)
 			__get_free_pages(GFP_KERNEL|GFP_DMA, 
 					sizeof(void*) == 8 ? 1 : 0);
-		async_stack = __get_free_pages(GFP_KERNEL,ASYNC_ORDER);
-		if (lowcore_ptr[i] == NULL || async_stack == 0ULL)
+		stack = __get_free_pages(GFP_KERNEL,ASYNC_ORDER);
+		if (lowcore_ptr[i] == NULL || stack == 0ULL)
 			panic("smp_boot_cpus failed to allocate memory\n");
 
 		*(lowcore_ptr[i]) = S390_lowcore;
-		lowcore_ptr[i]->async_stack = async_stack + (ASYNC_SIZE);
+		lowcore_ptr[i]->async_stack = stack + (ASYNC_SIZE);
+#ifdef CONFIG_CHECK_STACK
+		stack = __get_free_pages(GFP_KERNEL,0);
+		if (stack == 0ULL)
+			panic("smp_boot_cpus failed to allocate memory\n");
+		lowcore_ptr[i]->panic_stack = stack + (PAGE_SIZE);
+#endif
 	}
 	set_prefix((u32)(unsigned long) lowcore_ptr[smp_processor_id()]);
 
diff -Nru a/arch/s390/kernel/time.c b/arch/s390/kernel/time.c
--- a/arch/s390/kernel/time.c	2004-10-18 14:55:54 -07:00
+++ b/arch/s390/kernel/time.c	2004-10-18 14:55:54 -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/traps.c b/arch/s390/kernel/traps.c
--- a/arch/s390/kernel/traps.c	2004-10-18 14:56:28 -07:00
+++ b/arch/s390/kernel/traps.c	2004-10-18 14:56:28 -07:00
@@ -67,54 +67,93 @@
 #define stack_pointer ({ void **sp; asm("la %0,0(15)" : "=&d" (sp)); sp; })
 
 #ifndef CONFIG_ARCH_S390X
-#define RET_ADDR 56
 #define FOURLONG "%08lx %08lx %08lx %08lx\n"
 static int kstack_depth_to_print = 12;
-
 #else /* CONFIG_ARCH_S390X */
-#define RET_ADDR 112
 #define FOURLONG "%016lx %016lx %016lx %016lx\n"
 static int kstack_depth_to_print = 20;
-
 #endif /* CONFIG_ARCH_S390X */
 
-void show_trace(struct task_struct *task, unsigned long * stack)
+/*
+ * For show_trace we have tree different stack to consider:
+ *   - the panic stack which is used if the kernel stack has overflown
+ *   - the asynchronous interrupt stack (cpu related)
+ *   - the synchronous kernel stack (process related)
+ * The stack trace can start at any of the three stack and can potentially
+ * touch all of them. The order is: panic stack, async stack, sync stack.
+ */
+static unsigned long
+__show_trace(unsigned long sp, unsigned long low, unsigned long high)
 {
-	unsigned long backchain, low_addr, high_addr, ret_addr;
+	struct stack_frame *sf;
+	struct pt_regs *regs;
 
-	if (!stack)
-		stack = (task == NULL) ? *stack_pointer : &(task->thread.ksp);
+	while (1) {
+		sp = sp & PSW_ADDR_INSN;
+		if (sp < low || sp > high - sizeof(*sf))
+			return sp;
+		sf = (struct stack_frame *) sp;
+		printk("([<%016lx>] ", sf->gprs[8] & PSW_ADDR_INSN);
+		print_symbol("%s)\n", sf->gprs[8] & PSW_ADDR_INSN);
+		/* Follow the backchain. */
+		while (1) {
+			low = sp;
+			sp = sf->back_chain & PSW_ADDR_INSN;
+			if (!sp)
+				break;
+			if (sp <= low || sp > high - sizeof(*sf))
+				return sp;
+			sf = (struct stack_frame *) sp;
+			printk(" [<%016lx>] ", sf->gprs[8] & PSW_ADDR_INSN);
+			print_symbol("%s\n", sf->gprs[8] & PSW_ADDR_INSN);
+		}
+		/* Zero backchain detected, check for interrupt frame. */
+		sp = (unsigned long) (sf + 1);
+		if (sp <= low || sp > high - sizeof(*regs))
+			return sp;
+		regs = (struct pt_regs *) sp;
+		printk(" [<%016lx>] ", regs->psw.addr & PSW_ADDR_INSN);
+		print_symbol("%s\n", regs->psw.addr & PSW_ADDR_INSN);
+		low = sp;
+		sp = regs->gprs[15];
+	}
+}
 
+void show_trace(struct task_struct *task, unsigned long * stack)
+{
+	register unsigned long __r15 asm ("15");
+	unsigned long sp;
+
+	sp = (unsigned long) stack;
+	if (!sp)
+		sp = task ? task->thread.ksp : __r15;
 	printk("Call Trace:\n");
-	low_addr = ((unsigned long) stack) & PSW_ADDR_INSN;
-	high_addr = (low_addr & (-THREAD_SIZE)) + THREAD_SIZE;
-	/* Skip the first frame (biased stack) */
-	backchain = *((unsigned long *) low_addr) & PSW_ADDR_INSN;
-	/* Print up to 8 lines */
-	while  (backchain > low_addr && backchain <= high_addr) {
-		ret_addr = *((unsigned long *) (backchain+RET_ADDR)) & PSW_ADDR_INSN;
-		printk(" [<%016lx>] ", ret_addr);
-		print_symbol("%s\n", ret_addr);
-		low_addr = backchain;
-		backchain = *((unsigned long *) backchain) & PSW_ADDR_INSN;
-	}
+#ifdef CONFIG_CHECK_STACK
+	sp = __show_trace(sp, S390_lowcore.panic_stack - 4096,
+			  S390_lowcore.panic_stack);
+#endif
+	sp = __show_trace(sp, S390_lowcore.async_stack - ASYNC_SIZE,
+			  S390_lowcore.async_stack);
+	if (task)
+		__show_trace(sp, (unsigned long) task->thread_info,
+			     (unsigned long) task->thread_info + THREAD_SIZE);
+	else
+		__show_trace(sp, S390_lowcore.thread_info,
+			     S390_lowcore.thread_info + THREAD_SIZE);
 	printk("\n");
 }
 
 void show_stack(struct task_struct *task, unsigned long *sp)
 {
+	register unsigned long * __r15 asm ("15");
 	unsigned long *stack;
 	int i;
 
 	// debugging aid: "show_stack(NULL);" prints the
 	// back trace for this cpu.
 
-	if (!sp) {
-		if (task)
-			sp = (unsigned long *) task->thread.ksp;
-		else
-			sp = *stack_pointer;
-	}
+	if (!sp)
+		sp = task ? (unsigned long *) task->thread.ksp : __r15;
 
 	stack = sp;
 	for (i = 0; i < kstack_depth_to_print; i++) {
@@ -591,6 +630,11 @@
 	}
 }
 
+asmlinkage void kernel_stack_overflow(struct pt_regs * regs)
+{
+	die("Kernel stack overflow", regs, 0);
+	panic("Corrupt kernel stack, can't continue.");
+}
 
 
 /* init is done in lowcore.S and head.S */
diff -Nru a/arch/s390/kernel/vmlinux.lds.S b/arch/s390/kernel/vmlinux.lds.S
--- a/arch/s390/kernel/vmlinux.lds.S	2004-10-18 14:56:28 -07:00
+++ b/arch/s390/kernel/vmlinux.lds.S	2004-10-18 14:56:28 -07:00
@@ -24,6 +24,7 @@
   .text : {
 	*(.text)
 	SCHED_TEXT
+	LOCK_TEXT
 	*(.fixup)
 	*(.gnu.warning)
 	} = 0x0700
@@ -78,9 +79,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-10-18 14:57:04 -07:00
+++ b/arch/s390/kernel/vtime.c	2004-10-18 14:57:04 -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/lib/string.c b/arch/s390/lib/string.c
--- a/arch/s390/lib/string.c	2004-10-18 14:56:28 -07:00
+++ b/arch/s390/lib/string.c	2004-10-18 14:56:28 -07:00
@@ -46,7 +46,7 @@
 {
 	return __strend(s) - s;
 }
-EXPORT_SYMBOL_NOVERS(strlen);
+EXPORT_SYMBOL(strlen);
 
 /**
  * strnlen - Find the length of a length-limited string
@@ -59,7 +59,7 @@
 {
 	return __strnend(s, n) - s;
 }
-EXPORT_SYMBOL_NOVERS(strnlen);
+EXPORT_SYMBOL(strnlen);
 
 /**
  * strcpy - Copy a %NUL terminated string
@@ -79,7 +79,7 @@
 		      : "cc", "memory" );
 	return ret;
 }
-EXPORT_SYMBOL_NOVERS(strcpy);
+EXPORT_SYMBOL(strcpy);
 
 /**
  * strlcpy - Copy a %NUL terminated string into a sized buffer
@@ -103,7 +103,7 @@
 	}
 	return ret;
 }
-EXPORT_SYMBOL_NOVERS(strlcpy);
+EXPORT_SYMBOL(strlcpy);
 
 /**
  * strncpy - Copy a length-limited, %NUL-terminated string
@@ -121,7 +121,7 @@
 	__builtin_memcpy(dest, src, len);
 	return dest;
 }
-EXPORT_SYMBOL_NOVERS(strncpy);
+EXPORT_SYMBOL(strncpy);
 
 /**
  * strcat - Append one %NUL-terminated string to another
@@ -144,7 +144,7 @@
 		      : "d" (r0), "0" (0UL) : "cc", "memory" );
 	return ret;
 }
-EXPORT_SYMBOL_NOVERS(strcat);
+EXPORT_SYMBOL(strcat);
 
 /**
  * strlcat - Append a length-limited, %NUL-terminated string to another
@@ -168,7 +168,7 @@
 	}
 	return res;
 }
-EXPORT_SYMBOL_NOVERS(strlcat);
+EXPORT_SYMBOL(strlcat);
 
 /**
  * strncat - Append a length-limited, %NUL-terminated string to another
@@ -190,7 +190,7 @@
 	__builtin_memcpy(p, src, len);
 	return dest;
 }
-EXPORT_SYMBOL_NOVERS(strncat);
+EXPORT_SYMBOL(strncat);
 
 /**
  * strcmp - Compare two strings
@@ -217,7 +217,7 @@
 		      : : "cc" );
 	return ret;
 }
-EXPORT_SYMBOL_NOVERS(strcmp);
+EXPORT_SYMBOL(strcmp);
 
 /**
  * strrchr - Find the last occurrence of a character in a string
@@ -235,7 +235,7 @@
 	       } while (--len > 0);
        return 0;
 }
-EXPORT_SYMBOL_NOVERS(strrchr);
+EXPORT_SYMBOL(strrchr);
 
 /**
  * strstr - Find the first substring in a %NUL terminated string
@@ -269,7 +269,7 @@
 	}
 	return 0;
 }
-EXPORT_SYMBOL_NOVERS(strstr);
+EXPORT_SYMBOL(strstr);
 
 /**
  * memchr - Find a character in an area of memory.
@@ -293,7 +293,7 @@
 		      : "+a" (ret), "+&a" (s) : "d" (r0) : "cc" );
 	return (void *) ret;
 }
-EXPORT_SYMBOL_NOVERS(memchr);
+EXPORT_SYMBOL(memchr);
 
 /**
  * memcmp - Compare two areas of memory
@@ -319,7 +319,7 @@
 		ret = *(char *) r2 - *(char *) r4;
 	return ret;
 }
-EXPORT_SYMBOL_NOVERS(memcmp);
+EXPORT_SYMBOL(memcmp);
 
 /**
  * memscan - Find a character in an area of memory.
@@ -340,7 +340,7 @@
 		      : "+a" (ret), "+&a" (s) : "d" (r0) : "cc" );
 	return (void *) ret;
 }
-EXPORT_SYMBOL_NOVERS(memscan);
+EXPORT_SYMBOL(memscan);
 
 /**
  * memcpy - Copy one area of memory to another
@@ -354,7 +354,7 @@
 {
 	return __builtin_memcpy(dest, src, n);
 }
-EXPORT_SYMBOL_NOVERS(memcpy);
+EXPORT_SYMBOL(memcpy);
 
 /**
  * bcopy - Copy one area of memory to another
@@ -369,7 +369,7 @@
 {
 	__builtin_memcpy(destp, srcp, n);
 }
-EXPORT_SYMBOL_NOVERS(bcopy);
+EXPORT_SYMBOL(bcopy);
 
 /**
  * memset - Fill a region of memory with the given value
@@ -393,4 +393,4 @@
 		} while (--n > 0);
 	return s;
 }
-EXPORT_SYMBOL_NOVERS(memset);
+EXPORT_SYMBOL(memset);
diff -Nru a/arch/s390/mm/Makefile b/arch/s390/mm/Makefile
--- a/arch/s390/mm/Makefile	2004-10-18 14:57:04 -07:00
+++ b/arch/s390/mm/Makefile	2004-10-18 14:57:04 -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-10-18 14:57:21 -07:00
+++ b/arch/s390/mm/fault.c	2004-10-18 14:57:21 -07:00
@@ -25,11 +25,11 @@
 #include <linux/init.h>
 #include <linux/console.h>
 #include <linux/module.h>
+#include <linux/hardirq.h>
 
 #include <asm/system.h>
 #include <asm/uaccess.h>
 #include <asm/pgtable.h>
-#include <asm/hardirq.h>
 
 #ifndef CONFIG_ARCH_S390X
 #define __FAIL_ADDR_MASK 0x7ffff000
@@ -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-10-18 14:57:21 -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/Kconfig b/arch/sh/Kconfig
--- a/arch/sh/Kconfig	2004-10-18 14:57:04 -07:00
+++ b/arch/sh/Kconfig	2004-10-18 14:57:04 -07:00
@@ -194,7 +194,7 @@
 
 choice
 	prompt "Processor subtype"
-	
+
 config CPU_SUBTYPE_SH7604
 	bool "SH7604"
 	depends on CPU_SH2
@@ -301,7 +301,7 @@
 	---help---
 	  Computers built with Hitachi SuperH processors always
 	  map the ROM starting at address zero.  But the processor
-	  does not specify the range that RAM takes.  
+	  does not specify the range that RAM takes.
 
 	  The physical memory (RAM) start address will be automatically
 	  set to 08000000, unless you selected one of the following
@@ -339,7 +339,7 @@
 # If none of the above have set memory start/size, ask the user.
 config MEMORY_OVERRIDE
 	bool "Override default load address and memory size"
-	
+
 # XXX: break these out into the board-specific configs below
 config CF_ENABLER
 	bool "Compact Flash Enabler support"
@@ -522,7 +522,7 @@
 	help
 	  Selecting this option will enable an in-kernel API for manipulating
 	  the store queues integrated in the SH-4 processors.
-	
+
 config SMP
 	bool "Symmetric multi-processing support"
 	---help---
@@ -711,7 +711,6 @@
 
 endmenu
 
-
 menu "Executable file formats"
 
 source "fs/Kconfig.binfmt"
@@ -742,161 +741,10 @@
 
 source "arch/sh/oprofile/Kconfig"
 
-menu "Kernel hacking"
-
-config MAGIC_SYSRQ
-	bool "Magic SysRq key"
-	help
-	  If you say Y here, you will have some control over the system even
-	  if the system crashes for example during kernel debugging (e.g., you
-	  will be able to flush the buffer cache to disk, reboot the system
-	  immediately or dump some status information). This is accomplished
-	  by pressing various keys while holding SysRq (Alt+PrintScreen). It
-	  also works on a serial console (on PC hardware at least), if you
-	  send a BREAK and then within 5 seconds a command keypress. The
-	  keys are documented in <file:Documentation/sysrq.txt>. Don't say Y
-	  unless you really know what this hack does.
-
-config DEBUG_SPINLOCK
-	bool "Spinlock debugging"
-	help
-	  Say Y here and build SMP to catch missing spinlock initialization
-	  and certain other kinds of spinlock errors commonly made.  This is
-	  best used in conjunction with the NMI watchdog so that spinlock
-	  deadlocks are also debuggable.
-
-config DEBUG_INFO
-        bool "Compile the kernel with debug info"
-        help
-          If you say Y here the resulting kernel image will include
-          debugging info resulting in a larger kernel image.
-          Say Y here only if you plan to use gdb to debug the kernel.
-          If you don't debug the kernel, you can say N.
-
-config SH_STANDARD_BIOS
-	bool "Use LinuxSH standard BIOS"
-	help
-	  Say Y here if your target has the gdb-sh-stub
-	  package from www.m17n.org (or any conforming standard LinuxSH BIOS)
-	  in FLASH or EPROM.  The kernel will use standard BIOS calls during
-	  boot for various housekeeping tasks (including calls to read and
-	  write characters to a system console, get a MAC address from an
-	  on-board Ethernet interface, and shut down the hardware).  Note this
-	  does not work with machines with an existing operating system in
-	  mask ROM and no flash (WindowsCE machines fall in this category).
-	  If unsure, say N.
-
-config EARLY_SCIF_CONSOLE
-	bool "Use early SCIF console"
-	depends on CPU_SH4
-
-config EARLY_PRINTK
-	bool "Early printk support"
-	depends on SH_STANDARD_BIOS || EARLY_SCIF_CONSOLE
-	help
-	  Say Y here to redirect kernel printk messages to the serial port
-	  used by the SH-IPL bootloader, starting very early in the boot
-	  process and ending when the kernel's serial console is initialised.
-	  This option is only useful porting the kernel to a new machine,
-	  when the kernel may crash or hang before the serial console is
-	  initialised. If unsure, say N.
-
-config KGDB
-	bool "Include KGDB kernel debugger"
-	help
-	  Include in-kernel hooks for kgdb, the Linux kernel source level
-	  debugger.  See <http://kgdb.sourceforge.net/> for more information.
-	  Unless you are intending to debug the kernel, say N here.
-
-menu "KGDB configuration options"
-	depends on KGDB
-
-config MORE_COMPILE_OPTIONS
-	bool "Add any additional compile options"
-	help
-	  If you want to add additional CFLAGS to the kernel build, enable this
-	  option and then enter what you would like to add in the next question.
-	  Note however that -g is already appended with the selection of KGDB.
-
-config COMPILE_OPTIONS
-	string "Additional compile arguments"
-	depends on MORE_COMPILE_OPTIONS
-
-config KGDB_NMI
-	bool "Enter KGDB on NMI"
-	default n
-
-config KGDB_THREAD
-	bool "Include KGDB thread support"
-	default y
-
-config SH_KGDB_CONSOLE
-	bool "Console messages through GDB"
-	default n
-
-config KGDB_SYSRQ
-	bool "Allow SysRq 'G' to enter KGDB"
-	default y
-
-config KGDB_KERNEL_ASSERTS
-	bool "Include KGDB kernel assertions"
-	default n
-
-comment "Serial port setup"
-
-config KGDB_DEFPORT
-	int "Port number (ttySCn)"
-	default "1"
-
-config KGDB_DEFBAUD
-	int "Baud rate"
-	default "115200"
-
-choice
-	prompt "Parity"
-	depends on KGDB
-	default KGDB_DEFPARITY_N
-
-config KGDB_DEFPARITY_N
-	bool "None"
-
-config KGDB_DEFPARITY_E
-	bool "Even"
-
-config KGDB_DEFPARITY_O
-	bool "Odd"
-
-endchoice
-
-choice
-	prompt "Data bits"
-	depends on KGDB
-	default KGDB_DEFBITS_8
-
-config KGDB_DEFBITS_8
-	bool "8"
-
-config KGDB_DEFBITS_7
-	bool "7"
-
-endchoice
-
-endmenu
-
-config FRAME_POINTER
-	bool "Compile the kernel with frame pointers"
-	default y if KGDB
-	help
-	  If you say Y here the resulting kernel image will be slightly larger
-	  and slower, but it will give very useful debugging information.
-	  If you don't debug the kernel, you can say N, but we may not be able
-	  to solve problems without frame pointers.
-
-endmenu
+source "arch/sh/Kconfig.debug"
 
 source "security/Kconfig"
 
 source "crypto/Kconfig"
 
 source "lib/Kconfig"
-
diff -Nru a/arch/sh/Kconfig.debug b/arch/sh/Kconfig.debug
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/arch/sh/Kconfig.debug	2004-10-18 14:57:21 -07:00
@@ -0,0 +1,124 @@
+menu "Kernel hacking"
+
+source "lib/Kconfig.debug"
+
+config SH_STANDARD_BIOS
+	bool "Use LinuxSH standard BIOS"
+	help
+	  Say Y here if your target has the gdb-sh-stub
+	  package from www.m17n.org (or any conforming standard LinuxSH BIOS)
+	  in FLASH or EPROM.  The kernel will use standard BIOS calls during
+	  boot for various housekeeping tasks (including calls to read and
+	  write characters to a system console, get a MAC address from an
+	  on-board Ethernet interface, and shut down the hardware).  Note this
+	  does not work with machines with an existing operating system in
+	  mask ROM and no flash (WindowsCE machines fall in this category).
+	  If unsure, say N.
+
+config EARLY_SCIF_CONSOLE
+	bool "Use early SCIF console"
+	depends on CPU_SH4
+
+config EARLY_PRINTK
+	bool "Early printk support"
+	depends on SH_STANDARD_BIOS || EARLY_SCIF_CONSOLE
+	help
+	  Say Y here to redirect kernel printk messages to the serial port
+	  used by the SH-IPL bootloader, starting very early in the boot
+	  process and ending when the kernel's serial console is initialised.
+	  This option is only useful porting the kernel to a new machine,
+	  when the kernel may crash or hang before the serial console is
+	  initialised. If unsure, say N.
+
+config KGDB
+	bool "Include KGDB kernel debugger"
+	help
+	  Include in-kernel hooks for kgdb, the Linux kernel source level
+	  debugger.  See <http://kgdb.sourceforge.net/> for more information.
+	  Unless you are intending to debug the kernel, say N here.
+
+menu "KGDB configuration options"
+	depends on KGDB
+
+config MORE_COMPILE_OPTIONS
+	bool "Add any additional compile options"
+	help
+	  If you want to add additional CFLAGS to the kernel build, enable this
+	  option and then enter what you would like to add in the next question.
+	  Note however that -g is already appended with the selection of KGDB.
+
+config COMPILE_OPTIONS
+	string "Additional compile arguments"
+	depends on MORE_COMPILE_OPTIONS
+
+config KGDB_NMI
+	bool "Enter KGDB on NMI"
+	default n
+
+config KGDB_THREAD
+	bool "Include KGDB thread support"
+	default y
+
+config SH_KGDB_CONSOLE
+	bool "Console messages through GDB"
+	default n
+
+config KGDB_SYSRQ
+	bool "Allow SysRq 'G' to enter KGDB"
+	default y
+
+config KGDB_KERNEL_ASSERTS
+	bool "Include KGDB kernel assertions"
+	default n
+
+comment "Serial port setup"
+
+config KGDB_DEFPORT
+	int "Port number (ttySCn)"
+	default "1"
+
+config KGDB_DEFBAUD
+	int "Baud rate"
+	default "115200"
+
+choice
+	prompt "Parity"
+	depends on KGDB
+	default KGDB_DEFPARITY_N
+
+config KGDB_DEFPARITY_N
+	bool "None"
+
+config KGDB_DEFPARITY_E
+	bool "Even"
+
+config KGDB_DEFPARITY_O
+	bool "Odd"
+
+endchoice
+
+choice
+	prompt "Data bits"
+	depends on KGDB
+	default KGDB_DEFBITS_8
+
+config KGDB_DEFBITS_8
+	bool "8"
+
+config KGDB_DEFBITS_7
+	bool "7"
+
+endchoice
+
+endmenu
+
+config FRAME_POINTER
+	bool "Compile the kernel with frame pointers"
+	default y if KGDB
+	help
+	  If you say Y here the resulting kernel image will be slightly larger
+	  and slower, but it will give very useful debugging information.
+	  If you don't debug the kernel, you can say N, but we may not be able
+	  to solve problems without frame pointers.
+
+endmenu
diff -Nru a/arch/sh/Makefile b/arch/sh/Makefile
--- a/arch/sh/Makefile	2004-10-18 14:56:33 -07:00
+++ b/arch/sh/Makefile	2004-10-18 14:56:33 -07:00
@@ -31,7 +31,7 @@
 cflags-$(CONFIG_CPU_SH2)		+= -m2
 cflags-$(CONFIG_CPU_SH3)		+= -m3
 cflags-$(CONFIG_CPU_SH4)		+= -m4 \
-	$(call check_gcc,-mno-implicit-fp,-m4-nofpu)
+	$(call cc-option,-mno-implicit-fp,-m4-nofpu)
 
 cflags-$(CONFIG_SH_DSP)			+= -Wa,-dsp
 cflags-$(CONFIG_SH_KGDB)		+= -g
@@ -122,7 +122,7 @@
 
 boot := arch/sh/boot
 
-AFLAGS_vmlinux.lds.o := -traditional
+CPPFLAGS_vmlinux.lds := -traditional
 
 prepare: target_links
 
diff -Nru a/arch/sh/boards/mpc1211/pci.c b/arch/sh/boards/mpc1211/pci.c
--- a/arch/sh/boards/mpc1211/pci.c	2004-10-18 14:56:50 -07:00
+++ b/arch/sh/boards/mpc1211/pci.c	2004-10-18 14:56:50 -07:00
@@ -176,14 +176,7 @@
 	dev->resource[4].end   = 0xf00f;
 	dev->resource[4].flags = IORESOURCE_IO;
 }
-
-
-/* Add future fixups here... */
-struct pci_fixup pcibios_fixups[] = {
-	{ PCI_FIXUP_HEADER, PCI_VENDOR_ID_AL,
-	  PCI_DEVICE_ID_AL_M5229, quirk_ali_ide_ports },
-	{ 0 }
-};
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_AL, PCI_DEVICE_ID_AL_M5229, quirk_ali_ide_ports);
 
 char * __devinit pcibios_setup(char *str)
 {
diff -Nru a/arch/sh/boards/overdrive/galileo.c b/arch/sh/boards/overdrive/galileo.c
--- a/arch/sh/boards/overdrive/galileo.c	2004-10-18 14:56:27 -07:00
+++ b/arch/sh/boards/overdrive/galileo.c	2004-10-18 14:56:27 -07:00
@@ -455,13 +455,7 @@
 		}
 	}
 }
-
-
-/* Add future fixups here... */
-struct pci_fixup pcibios_fixups[] = {
-	{ PCI_FIXUP_HEADER,	PCI_ANY_ID,	PCI_ANY_ID,	pci_fixup_ide_bases },
-	{ 0 }
-};
+DECLARE_PCI_FIXUP_HEADER(PCI_ANY_ID, PCI_ANY_ID, pci_fixup_ide_bases);
 
 void __init pcibios_init(void)
 {
diff -Nru a/arch/sh/boot/compressed/Makefile b/arch/sh/boot/compressed/Makefile
--- a/arch/sh/boot/compressed/Makefile	2004-10-18 14:56:32 -07:00
+++ b/arch/sh/boot/compressed/Makefile	2004-10-18 14:56:32 -07:00
@@ -22,7 +22,7 @@
 CONFIG_BOOT_LINK_OFFSET ?= 0x00800000
 IMAGE_OFFSET := $(shell printf "0x%8x" $$[0x80000000+$(CONFIG_MEMORY_START)+$(CONFIG_BOOT_LINK_OFFSET)])
 
-LDFLAGS_vmlinux := -Ttext $(IMAGE_OFFSET) -e startup -T $(obj)/../../kernel/vmlinux.lds.s
+LDFLAGS_vmlinux := -Ttext $(IMAGE_OFFSET) -e startup -T $(obj)/../../kernel/vmlinux.lds
 
 $(obj)/vmlinux: $(OBJECTS) $(obj)/piggy.o FORCE
 	$(call if_changed,ld)
diff -Nru a/arch/sh/drivers/pci/fixups-dreamcast.c b/arch/sh/drivers/pci/fixups-dreamcast.c
--- a/arch/sh/drivers/pci/fixups-dreamcast.c	2004-10-18 14:57:04 -07:00
+++ b/arch/sh/drivers/pci/fixups-dreamcast.c	2004-10-18 14:57:04 -07:00
@@ -47,11 +47,7 @@
 	}
 }
 
-struct pci_fixup pcibios_fixups[] = {
-	{ PCI_FIXUP_HEADER, PCI_ANY_ID,
-	  PCI_ANY_ID, gapspci_fixup_resources },
-	{ 0, }
-};
+DECLARE_PCI_FIXUP_HEADER(PCI_ANY_ID, PCI_ANY_ID, gapspci_fixup_resources);
 
 void __init pcibios_fixup_bus(struct pci_bus *bus)
 {
diff -Nru a/arch/sh/drivers/pci/pci-sh7751.c b/arch/sh/drivers/pci/pci-sh7751.c
--- a/arch/sh/drivers/pci/pci-sh7751.c	2004-10-18 14:56:49 -07:00
+++ b/arch/sh/drivers/pci/pci-sh7751.c	2004-10-18 14:56:49 -07:00
@@ -177,15 +177,8 @@
 		}
 	}
 }
+DECLARE_PCI_FIXUP_HEADER(PCI_ANY_ID, PCI_ANY_ID, pci_fixup_ide_bases);
 #endif
-
-/* Add future fixups here... */
-struct pci_fixup pcibios_fixups[] = {
-#if !defined(CONFIG_SH_HS7751RVOIP) && !defined(CONFIG_SH_RTS7751R2D)
-	{ PCI_FIXUP_HEADER,	PCI_ANY_ID,	PCI_ANY_ID,	pci_fixup_ide_bases },
-#endif
-	{ 0 }
-};
 
 /*
  *  Called after each bus is probed, but before its children
diff -Nru a/arch/sh/drivers/pci/pci-st40.c b/arch/sh/drivers/pci/pci-st40.c
--- a/arch/sh/drivers/pci/pci-st40.c	2004-10-18 14:56:33 -07:00
+++ b/arch/sh/drivers/pci/pci-st40.c	2004-10-18 14:56:33 -07:00
@@ -160,13 +160,7 @@
 		}
 	}
 }
-
-
-/* Add future fixups here... */
-struct pci_fixup pcibios_fixups[] = {
-	{ PCI_FIXUP_HEADER,	PCI_ANY_ID,	PCI_ANY_ID,	pci_fixup_ide_bases },
-	{ 0 }
-};
+DECLARE_PCI_FIXUP_HEADER(PCI_ANY_ID, PCI_ANY_ID, pci_fixup_ide_bases);
 
 int __init st40pci_init(unsigned memStart, unsigned memSize)
 {
diff -Nru a/arch/sh/kernel/Makefile b/arch/sh/kernel/Makefile
--- a/arch/sh/kernel/Makefile	2004-10-18 14:56:33 -07:00
+++ b/arch/sh/kernel/Makefile	2004-10-18 14:56:33 -07:00
@@ -2,7 +2,7 @@
 # Makefile for the Linux/SuperH kernel.
 #
 
-extra-y	:= head.o init_task.o vmlinux.lds.s
+extra-y	:= head.o init_task.o vmlinux.lds
 
 obj-y	:= process.o signal.o entry.o traps.o irq.o \
 	ptrace.o setup.o time.o sys_sh.o semaphore.o \
diff -Nru a/arch/sh/kernel/irq.c b/arch/sh/kernel/irq.c
--- a/arch/sh/kernel/irq.c	2004-10-18 14:56:28 -07:00
+++ b/arch/sh/kernel/irq.c	2004-10-18 14:56:28 -07:00
@@ -137,14 +137,16 @@
 int handle_IRQ_event(unsigned int irq, struct pt_regs * regs, struct irqaction * action)
 {
 	int status = 1;	/* Force the "do bottom halves" bit */
-	int retval = 0;
+	int ret, retval = 0;
 
 	if (!(action->flags & SA_INTERRUPT))
 		local_irq_enable();
 
 	do {
-		status |= action->flags;
-		retval |= action->handler(irq, action->dev_id, regs);
+		ret = action->handler(irq, action->dev_id, regs);
+		if (ret == IRQ_HANDLED)
+			status |= action->flags;
+		retval |= ret;
 		action = action->next;
 	} while (action);
 
diff -Nru a/arch/sh/kernel/process.c b/arch/sh/kernel/process.c
--- a/arch/sh/kernel/process.c	2004-10-18 14:56:48 -07:00
+++ b/arch/sh/kernel/process.c	2004-10-18 14:56:48 -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/sh_ksyms.c b/arch/sh/kernel/sh_ksyms.c
--- a/arch/sh/kernel/sh_ksyms.c	2004-10-18 14:56:17 -07:00
+++ b/arch/sh/kernel/sh_ksyms.c	2004-10-18 14:56:17 -07:00
@@ -16,7 +16,6 @@
 #include <asm/uaccess.h>
 #include <asm/checksum.h>
 #include <asm/io.h>
-#include <asm/hardirq.h>
 #include <asm/delay.h>
 #include <asm/tlbflush.h>
 #include <asm/cacheflush.h>
@@ -87,7 +86,7 @@
 EXPORT_SYMBOL(__ndelay);
 EXPORT_SYMBOL(__const_udelay);
 
-#define DECLARE_EXPORT(name) extern void name(void);EXPORT_SYMBOL_NOVERS(name)
+#define DECLARE_EXPORT(name) extern void name(void);EXPORT_SYMBOL(name)
 
 /* These symbols are generated by the compiler itself */
 DECLARE_EXPORT(__udivsi3);
diff -Nru a/arch/sh/kernel/signal.c b/arch/sh/kernel/signal.c
--- a/arch/sh/kernel/signal.c	2004-10-18 14:57:19 -07:00
+++ b/arch/sh/kernel/signal.c	2004-10-18 14:57:19 -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-10-18 14:56:29 -07:00
+++ b/arch/sh/kernel/smp.c	2004-10-18 14:56:29 -07:00
@@ -26,7 +26,6 @@
 #include <asm/atomic.h>
 #include <asm/processor.h>
 #include <asm/system.h>
-#include <asm/hardirq.h>
 #include <asm/mmu_context.h>
 #include <asm/smp.h>
 
@@ -98,18 +97,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-10-18 14:55:53 -07:00
+++ b/arch/sh/kernel/time.c	2004-10-18 14:55:53 -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-10-18 14:56:32 -07:00
+++ b/arch/sh/kernel/vmlinux.lds.S	2004-10-18 14:56:32 -07:00
@@ -23,6 +23,7 @@
   .text : {
 	*(.text)
 	SCHED_TEXT
+	LOCK_TEXT
 	*(.fixup)
 	*(.gnu.warning)
 	} = 0x0009
@@ -75,9 +76,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/fault-nommu.c b/arch/sh/mm/fault-nommu.c
--- a/arch/sh/mm/fault-nommu.c	2004-10-18 14:56:49 -07:00
+++ b/arch/sh/mm/fault-nommu.c	2004-10-18 14:56:49 -07:00
@@ -26,7 +26,6 @@
 #include <asm/io.h>
 #include <asm/uaccess.h>
 #include <asm/pgalloc.h>
-#include <asm/hardirq.h>
 #include <asm/mmu_context.h>
 #include <asm/cacheflush.h>
 
diff -Nru a/arch/sh/mm/fault.c b/arch/sh/mm/fault.c
--- a/arch/sh/mm/fault.c	2004-10-18 14:56:27 -07:00
+++ b/arch/sh/mm/fault.c	2004-10-18 14:56:27 -07:00
@@ -26,7 +26,6 @@
 #include <asm/io.h>
 #include <asm/uaccess.h>
 #include <asm/pgalloc.h>
-#include <asm/hardirq.h>
 #include <asm/mmu_context.h>
 #include <asm/cacheflush.h>
 #include <asm/kgdb.h>
diff -Nru a/arch/sh/mm/init.c b/arch/sh/mm/init.c
--- a/arch/sh/mm/init.c	2004-10-18 14:56:49 -07:00
+++ b/arch/sh/mm/init.c	2004-10-18 14:56:49 -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/sh/mm/tlb-sh3.c b/arch/sh/mm/tlb-sh3.c
--- a/arch/sh/mm/tlb-sh3.c	2004-10-18 14:56:28 -07:00
+++ b/arch/sh/mm/tlb-sh3.c	2004-10-18 14:56:28 -07:00
@@ -25,7 +25,6 @@
 #include <asm/io.h>
 #include <asm/uaccess.h>
 #include <asm/pgalloc.h>
-#include <asm/hardirq.h>
 #include <asm/mmu_context.h>
 #include <asm/cacheflush.h>
 
diff -Nru a/arch/sh/mm/tlb-sh4.c b/arch/sh/mm/tlb-sh4.c
--- a/arch/sh/mm/tlb-sh4.c	2004-10-18 14:56:48 -07:00
+++ b/arch/sh/mm/tlb-sh4.c	2004-10-18 14:56:48 -07:00
@@ -25,7 +25,6 @@
 #include <asm/io.h>
 #include <asm/uaccess.h>
 #include <asm/pgalloc.h>
-#include <asm/hardirq.h>
 #include <asm/mmu_context.h>
 #include <asm/cacheflush.h>
 
diff -Nru a/arch/sh64/Kconfig b/arch/sh64/Kconfig
--- a/arch/sh64/Kconfig	2004-10-18 14:56:49 -07:00
+++ b/arch/sh64/Kconfig	2004-10-18 14:56:49 -07:00
@@ -263,58 +263,10 @@
 
 source "arch/sh64/oprofile/Kconfig"
 
-menu "Kernel hacking"
-
-config MAGIC_SYSRQ
-	bool "Magic SysRq key"
-	help
-	  If you say Y here, you will have some control over the system even
-	  if the system crashes for example during kernel debugging (e.g., you
-	  will be able to flush the buffer cache to disk, reboot the system
-	  immediately or dump some status information). This is accomplished
-	  by pressing various keys while holding SysRq (Alt+PrintScreen). It
-	  also works on a serial console (on PC hardware at least), if you
-	  send a BREAK and then within 5 seconds a command keypress. The
-	  keys are documented in Documentation/sysrq.txt. Don't say Y unless
-	  you really know what this hack does.
-
-config EARLY_PRINTK
-	bool "Early SCIF console support"
-
-config DEBUG_KERNEL_WITH_GDB_STUB
-	bool "GDB Stub kernel debug"
-
-config SH64_PROC_TLB
-	bool "Debug: report TLB fill/purge activity through /proc/tlb"
-	depends on PROC_FS
-
-config SH64_PROC_ASIDS
-	bool "Debug: report ASIDs through /proc/asids"
-	depends on PROC_FS
-
-config SH64_SR_WATCH
-	bool "Debug: set SR.WATCH to enable hardware watchpoints and trace"
-
-config SH_ALPHANUMERIC
-	bool "Enable debug outputs to on-board alphanumeric display"
-
-config SH_NO_BSS_INIT
-	bool "Avoid zeroing BSS (to speed-up startup on suitable platforms)"
-
-config FRAME_POINTER
-	bool "Compile the kernel with frame pointers"
-	default y if KGDB
-	help
-	  If you say Y here the resulting kernel image will be slightly larger
-	  and slower, but it will give very useful debugging information.
-	  If you don't debug the kernel, you can say N, but we may not be able
-	  to solve problems without frame pointers.
-
-endmenu
+source "arch/sh64/Kconfig.debug"
 
 source "security/Kconfig"
 
 source "crypto/Kconfig"
 
 source "lib/Kconfig"
-
diff -Nru a/arch/sh64/Kconfig.debug b/arch/sh64/Kconfig.debug
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/arch/sh64/Kconfig.debug	2004-10-18 14:57:23 -07:00
@@ -0,0 +1,37 @@
+menu "Kernel hacking"
+
+source "lib/Kconfig.debug"
+
+config EARLY_PRINTK
+	bool "Early SCIF console support"
+
+config DEBUG_KERNEL_WITH_GDB_STUB
+	bool "GDB Stub kernel debug"
+
+config SH64_PROC_TLB
+	bool "Debug: report TLB fill/purge activity through /proc/tlb"
+	depends on PROC_FS
+
+config SH64_PROC_ASIDS
+	bool "Debug: report ASIDs through /proc/asids"
+	depends on PROC_FS
+
+config SH64_SR_WATCH
+	bool "Debug: set SR.WATCH to enable hardware watchpoints and trace"
+
+config SH_ALPHANUMERIC
+	bool "Enable debug outputs to on-board alphanumeric display"
+
+config SH_NO_BSS_INIT
+	bool "Avoid zeroing BSS (to speed-up startup on suitable platforms)"
+
+config FRAME_POINTER
+	bool "Compile the kernel with frame pointers"
+	default y if KGDB
+	help
+	  If you say Y here the resulting kernel image will be slightly larger
+	  and slower, but it will give very useful debugging information.
+	  If you don't debug the kernel, you can say N, but we may not be able
+	  to solve problems without frame pointers.
+
+endmenu
diff -Nru a/arch/sh64/boot/compressed/Makefile b/arch/sh64/boot/compressed/Makefile
--- a/arch/sh64/boot/compressed/Makefile	2004-10-18 14:56:49 -07:00
+++ b/arch/sh64/boot/compressed/Makefile	2004-10-18 14:56:49 -07:00
@@ -12,7 +12,7 @@
 #
 
 targets		:= vmlinux vmlinux.bin vmlinux.bin.gz \
-		   head.o misc.o cache.o piggy.o vmlinux.lds.o
+		   head.o misc.o cache.o piggy.o vmlinux.lds
 
 EXTRA_AFLAGS	:= -traditional
 
@@ -25,7 +25,7 @@
 ZIMAGE_OFFSET = $(shell printf "0x%8x" $$[$(CONFIG_MEMORY_START)+0x400000+0x10000])
 
 LDFLAGS_vmlinux := -Ttext $(ZIMAGE_OFFSET) -e startup \
-		    -T $(obj)/../../kernel/vmlinux.lds.s \
+		    -T $(obj)/../../kernel/vmlinux.lds \
 		    --no-warn-mismatch
 
 $(obj)/vmlinux: $(OBJECTS) $(obj)/piggy.o FORCE
@@ -41,6 +41,6 @@
 LDFLAGS_piggy.o := -r --format binary --oformat elf32-sh64-linux -T
 OBJCOPYFLAGS += -R .empty_zero_page
 
-$(obj)/piggy.o: $(obj)/vmlinux.lds.s $(obj)/vmlinux.bin.gz FORCE
+$(obj)/piggy.o: $(obj)/vmlinux.lds $(obj)/vmlinux.bin.gz FORCE
 	$(call if_changed,ld)
 
diff -Nru a/arch/sh64/kernel/irq.c b/arch/sh64/kernel/irq.c
--- a/arch/sh64/kernel/irq.c	2004-10-18 14:56:14 -07:00
+++ b/arch/sh64/kernel/irq.c	2004-10-18 14:56:14 -07:00
@@ -148,6 +148,7 @@
 int handle_IRQ_event(unsigned int irq, struct pt_regs * regs, struct irqaction * action)
 {
 	int status;
+	int ret;
 
 	status = 1;	/* Force the "do bottom halves" bit */
 
@@ -155,8 +156,9 @@
                 local_irq_enable();
 
 	do {
-		status |= action->flags;
-		action->handler(irq, action->dev_id, regs);
+		ret = action->handler(irq, action->dev_id, regs);
+		if (ret == IRQ_HANDLED)
+			status |= action->flags;
 		action = action->next;
 	} while (action);
 	if (status & SA_SAMPLE_RANDOM)
diff -Nru a/arch/sh64/kernel/pci_sh5.c b/arch/sh64/kernel/pci_sh5.c
--- a/arch/sh64/kernel/pci_sh5.c	2004-10-18 14:57:05 -07:00
+++ b/arch/sh64/kernel/pci_sh5.c	2004-10-18 14:57:05 -07:00
@@ -48,12 +48,7 @@
 		}
 	}
 }
-
-/* Add future fixups here... */
-struct pci_fixup pcibios_fixups[] = {
-	{ PCI_FIXUP_HEADER,	PCI_ANY_ID,	PCI_ANY_ID,	pci_fixup_ide_bases },
-	{ 0 }
-};
+DECLARE_PCI_FIXUP_HEADER(PCI_ANY_ID, PCI_ANY_ID, pci_fixup_ide_bases);
 
 char * __init pcibios_setup(char *str)
 {
diff -Nru a/arch/sh64/kernel/process.c b/arch/sh64/kernel/process.c
--- a/arch/sh64/kernel/process.c	2004-10-18 14:57:18 -07:00
+++ b/arch/sh64/kernel/process.c	2004-10-18 14:57:18 -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/ptrace.c b/arch/sh64/kernel/ptrace.c
--- a/arch/sh64/kernel/ptrace.c	2004-10-18 14:56:48 -07:00
+++ b/arch/sh64/kernel/ptrace.c	2004-10-18 14:56:48 -07:00
@@ -311,11 +311,8 @@
 	if (!(tsk->ptrace & PT_PTRACED))
 		return;
 
-	tsk->exit_code = SIGTRAP | ((current->ptrace & PT_TRACESYSGOOD)
-				    ? 0x80 : 0);
-	tsk->state = TASK_STOPPED;
-	notify_parent(tsk, 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
 	 * for normal use.  strace only continues with a signal if the
diff -Nru a/arch/sh64/kernel/sh_ksyms.c b/arch/sh64/kernel/sh_ksyms.c
--- a/arch/sh64/kernel/sh_ksyms.c	2004-10-18 14:56:13 -07:00
+++ b/arch/sh64/kernel/sh_ksyms.c	2004-10-18 14:56:13 -07:00
@@ -25,7 +25,6 @@
 #include <asm/uaccess.h>
 #include <asm/checksum.h>
 #include <asm/io.h>
-#include <asm/hardirq.h>
 #include <asm/delay.h>
 #include <asm/irq.h>
 
@@ -59,17 +58,17 @@
 EXPORT_SYMBOL(screen_info);
 #endif
 
-EXPORT_SYMBOL_NOVERS(__down);
-EXPORT_SYMBOL_NOVERS(__down_trylock);
-EXPORT_SYMBOL_NOVERS(__up);
-EXPORT_SYMBOL_NOVERS(__put_user_asm_l);
-EXPORT_SYMBOL_NOVERS(__get_user_asm_l);
-EXPORT_SYMBOL_NOVERS(memcmp);
-EXPORT_SYMBOL_NOVERS(memcpy);
-EXPORT_SYMBOL_NOVERS(memset);
-EXPORT_SYMBOL_NOVERS(memscan);
-EXPORT_SYMBOL_NOVERS(strchr);
-EXPORT_SYMBOL_NOVERS(strlen);
+EXPORT_SYMBOL(__down);
+EXPORT_SYMBOL(__down_trylock);
+EXPORT_SYMBOL(__up);
+EXPORT_SYMBOL(__put_user_asm_l);
+EXPORT_SYMBOL(__get_user_asm_l);
+EXPORT_SYMBOL(memcmp);
+EXPORT_SYMBOL(memcpy);
+EXPORT_SYMBOL(memset);
+EXPORT_SYMBOL(memscan);
+EXPORT_SYMBOL(strchr);
+EXPORT_SYMBOL(strlen);
 
 EXPORT_SYMBOL(flush_dcache_page);
 
@@ -78,7 +77,7 @@
 extern void __sdivsi3(void);
 extern void __muldi3(void);
 extern void __udivsi3(void);
-EXPORT_SYMBOL_NOVERS(__sdivsi3);
-EXPORT_SYMBOL_NOVERS(__muldi3);
-EXPORT_SYMBOL_NOVERS(__udivsi3);
+EXPORT_SYMBOL(__sdivsi3);
+EXPORT_SYMBOL(__muldi3);
+EXPORT_SYMBOL(__udivsi3);
 
diff -Nru a/arch/sh64/kernel/signal.c b/arch/sh64/kernel/signal.c
--- a/arch/sh64/kernel/signal.c	2004-10-18 14:56:29 -07:00
+++ b/arch/sh64/kernel/signal.c	2004-10-18 14:56:29 -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-10-18 14:56:32 -07:00
+++ b/arch/sh64/kernel/time.c	2004-10-18 14:56:32 -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-10-18 14:56:13 -07:00
+++ b/arch/sh64/kernel/vmlinux.lds.S	2004-10-18 14:56:13 -07:00
@@ -59,6 +59,7 @@
 	*(.text64)
         *(.text..SHmedia32)
 	SCHED_TEXT
+	LOCK_TEXT
 	*(.fixup)
 	*(.gnu.warning)
 #ifdef CONFIG_LITTLE_ENDIAN
@@ -106,9 +107,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/fault.c b/arch/sh64/mm/fault.c
--- a/arch/sh64/mm/fault.c	2004-10-18 14:56:29 -07:00
+++ b/arch/sh64/mm/fault.c	2004-10-18 14:56:29 -07:00
@@ -30,7 +30,6 @@
 #include <asm/tlb.h>
 #include <asm/uaccess.h>
 #include <asm/pgalloc.h>
-#include <asm/hardirq.h>
 #include <asm/mmu_context.h>
 #include <asm/registers.h>		/* required by inline asm statements */
 
diff -Nru a/arch/sh64/mm/init.c b/arch/sh64/mm/init.c
--- a/arch/sh64/mm/init.c	2004-10-18 14:57:21 -07:00
+++ b/arch/sh64/mm/init.c	2004-10-18 14:57:21 -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/sh64/mm/tlbmiss.c b/arch/sh64/mm/tlbmiss.c
--- a/arch/sh64/mm/tlbmiss.c	2004-10-18 14:55:55 -07:00
+++ b/arch/sh64/mm/tlbmiss.c	2004-10-18 14:55:55 -07:00
@@ -40,7 +40,6 @@
 #include <asm/io.h>
 #include <asm/uaccess.h>
 #include <asm/pgalloc.h>
-#include <asm/hardirq.h>
 #include <asm/mmu_context.h>
 #include <asm/registers.h>		/* required by inline asm statements */
 
diff -Nru a/arch/sparc/Kconfig b/arch/sparc/Kconfig
--- a/arch/sparc/Kconfig	2004-10-18 14:55:46 -07:00
+++ b/arch/sparc/Kconfig	2004-10-18 14:55:46 -07:00
@@ -23,8 +23,7 @@
 
 source "init/Kconfig"
 
-
-menu "General setup"
+menu "General machine setup"
 
 config VT
 	bool
@@ -217,8 +216,8 @@
 	bool
 	default y
 	help
-	  Enable power management and CPU standby features on supported 
-	  SPARC platforms. 
+	  Enable power management and CPU standby features on supported
+	  SPARC platforms.
 
 config SUN4
 	bool "Support for SUN4 machines (disables SUN4[CDM] support)"
@@ -380,81 +379,10 @@
 
 source "drivers/char/watchdog/Kconfig"
 
-menu "Kernel hacking"
-
-config DEBUG_KERNEL
-	bool "Kernel debugging"
-	help
-	  Say Y here if you are developing drivers or trying to debug and
-	  identify kernel problems.
-
-config DEBUG_STACK_USAGE
-	bool "Enable stack utilization instrumentation"
-	depends on DEBUG_KERNEL
-	help
-	  Enables the display of the minimum amount of free stack which each
-	  task has ever had available in the sysrq-T and sysrq-P debug output.
-
-	  This option will slow down process creation somewhat.
-
-config DEBUG_SLAB
-	bool "Debug memory allocations"
-	depends on DEBUG_KERNEL
-	help
-	  Say Y here to have the kernel do limited verification on memory
-	  allocation as well as poisoning memory on free to catch use of freed
-	  memory.
-
-config MAGIC_SYSRQ
-	bool "Magic SysRq key"
-	depends on DEBUG_KERNEL
-	help
-	  If you say Y here, you will have some control over the system even
-	  if the system crashes for example during kernel debugging (e.g., you
-	  will be able to flush the buffer cache to disk, reboot the system
-	  immediately or dump some status information). This is accomplished
-	  by pressing various keys while holding SysRq (Alt+PrintScreen). It
-	  also works on a serial console (on PC hardware at least), if you
-	  send a BREAK and then within 5 seconds a command keypress. The
-	  keys are documented in <file:Documentation/sysrq.txt>. Don't say Y
-	  unless you really know what this hack does.
-
-config DEBUG_SPINLOCK
-	bool "Spinlock debugging"
-	depends on DEBUG_KERNEL
-	help
-	  Say Y here and build SMP to catch missing spinlock initialization
-	  and certain other kinds of spinlock errors commonly made.  This is
-	  best used in conjunction with the NMI watchdog so that spinlock
-	  deadlocks are also debuggable.
-
-config DEBUG_HIGHMEM
-	bool "Highmem debugging"
-	depends on DEBUG_KERNEL && HIGHMEM
-	help
-	  This options enables additional error checking for high memory
-	  systems.  Disable for production systems.
-
-config DEBUG_SPINLOCK_SLEEP
-	bool "Sleep-inside-spinlock checking"
-	depends on DEBUG_KERNEL
-	help
-	  If you say Y here, various routines which may sleep will become very
-	  noisy if they are called with a spinlock held.	
-
-config DEBUG_BUGVERBOSE
-	bool "Verbose BUG() reporting (adds 70K)"
-	depends on DEBUG_KERNEL
-	help
-	  Say Y here to make BUG() panics output the file name and line number
-	  of the BUG call as well as the EIP and oops trace.  This aids
-	  debugging but costs about 70-100K of memory.
-
-endmenu
+source "arch/sparc/Kconfig.debug"
 
 source "security/Kconfig"
 
 source "crypto/Kconfig"
 
 source "lib/Kconfig"
-
diff -Nru a/arch/sparc/Kconfig.debug b/arch/sparc/Kconfig.debug
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/arch/sparc/Kconfig.debug	2004-10-18 14:57:24 -07:00
@@ -0,0 +1,14 @@
+menu "Kernel hacking"
+
+source "lib/Kconfig.debug"
+
+config DEBUG_STACK_USAGE
+	bool "Enable stack utilization instrumentation"
+	depends on DEBUG_KERNEL
+	help
+	  Enables the display of the minimum amount of free stack which each
+	  task has ever had available in the sysrq-T and sysrq-P debug output.
+
+	  This option will slow down process creation somewhat.
+
+endmenu
diff -Nru a/arch/sparc/Makefile b/arch/sparc/Makefile
--- a/arch/sparc/Makefile	2004-10-18 14:55:55 -07:00
+++ b/arch/sparc/Makefile	2004-10-18 14:55:55 -07:00
@@ -13,7 +13,7 @@
 
 AS              := $(AS) -32
 LDFLAGS		:= -m elf32_sparc
-CHECK		:= $(CHECK) -D__sparc__=1
+CHECKFLAGS	+= -D__sparc__
 
 #CFLAGS := $(CFLAGS) -g -pipe -fcall-used-g5 -fcall-used-g7
 CFLAGS := $(CFLAGS) -m32 -pipe -mno-fpu -fcall-used-g5 -fcall-used-g7
diff -Nru a/arch/sparc/boot/Makefile b/arch/sparc/boot/Makefile
--- a/arch/sparc/boot/Makefile	2004-10-18 14:57:03 -07:00
+++ b/arch/sparc/boot/Makefile	2004-10-18 14:57:03 -07:00
@@ -7,28 +7,52 @@
 ROOT_IMG	:= /usr/src/root.img
 ELFTOAOUT	:= elftoaout
 
-host-progs	:= piggyback btfixupprep
-targets		:= tftpboot.img btfix.o btfix.s image
+hostprogs-y	:= piggyback btfixupprep
+targets		:= tftpboot.img btfix.o btfix.S image
 
 quiet_cmd_elftoaout	= ELFTOAOUT $@
       cmd_elftoaout	= $(ELFTOAOUT) $(obj)/image -o $@
-quiet_cmd_piggy		= PIGGY $@
+quiet_cmd_piggy		= PIGGY   $@
       cmd_piggy		= $(obj)/piggyback $@ $(obj)/System.map $(ROOT_IMG)
-quiet_cmd_btfix		= BTFIX $@
+quiet_cmd_btfix		= BTFIX   $@
       cmd_btfix		= $(OBJDUMP) -x vmlinux | $(obj)/btfixupprep > $@
+quiet_cmd_sysmap        = SYSMAP  $(obj)/System.map
+      cmd_sysmap        = $(CONFIG_SHELL) $(srctree)/scripts/mksysmap
+quiet_cmd_image = LD      $@
+      cmd_image = $(LD) $(LDFLAGS) $(EXTRA_LDFLAGS) $(LDFLAGS_$(@F)) -o $@
+
+define rule_image
+	$(if $($(quiet)cmd_image),               \
+	  echo '  $($(quiet)cmd_image)' &&)      \
+	  $(cmd_image);                          \
+	$(if $($(quiet)cmd_sysmap),              \
+	  echo '  $($(quiet)cmd_sysmap)' &&)  \
+	$(cmd_sysmap) $@ $(obj)/System.map;      \
+	if [ $$? -ne 0 ]; then                   \
+		rm -f $@;                        \
+		/bin/false;                      \
+	fi;                                      \
+	echo 'cmd_$@ := $(cmd_image)' > $(@D)/.$(@F).cmd
+endef
 
 BTOBJS := $(HEAD_Y) $(INIT_Y)
 BTLIBS := $(CORE_Y) $(LIBS_Y) $(DRIVERS_Y) $(NET_Y)
-LDFLAGS_image := -T arch/sparc/kernel/vmlinux.lds.s $(BTOBJS) --start-group $(BTLIBS) --end-group $(kallsyms.o)
+LDFLAGS_image := -T arch/sparc/kernel/vmlinux.lds $(BTOBJS) \
+                  --start-group $(BTLIBS) --end-group \
+                  $(kallsyms.o) $(obj)/btfix.o
 
-# Actual linking
+# Link the final image including btfixup'ed symbols.
+# This is a replacement for the link done in the top-level Makefile.
+# Note: No dependency on the prerequisite files since that would require
+# make to try check if they are updated - and due to changes
+# in gcc options (path for example) this would result in
+# these files being recompiled for each build.
 $(obj)/image: $(obj)/btfix.o FORCE
-	$(call if_changed,ld)
-	$(NM) $@ | grep -v  '\(compiled\)\|\(\.o$$\)\|\( [aUw] \)\|\(\.\.ng$$\)\|\(LASH[RL]DI\)' | sort > $(obj)/System.map
+	$(call if_changed_rule,image)
 
 $(obj)/tftpboot.img: $(obj)/piggyback $(obj)/System.map $(obj)/image FORCE
 	$(call if_changed,elftoaout)
 	$(call if_changed,piggy)
 
-$(obj)/btfix.s: $(obj)/btfixupprep vmlinux FORCE
+$(obj)/btfix.S: $(obj)/btfixupprep vmlinux FORCE
 	$(call if_changed,btfix)
diff -Nru a/arch/sparc/kernel/Makefile b/arch/sparc/kernel/Makefile
--- a/arch/sparc/kernel/Makefile	2004-10-18 14:56:50 -07:00
+++ b/arch/sparc/kernel/Makefile	2004-10-18 14:56:50 -07:00
@@ -2,7 +2,7 @@
 # Makefile for the linux kernel.
 #
 
-extra-y		:= head.o init_task.o vmlinux.lds.s
+extra-y		:= head.o init_task.o vmlinux.lds
 
 EXTRA_AFLAGS	:= -ansi
 
diff -Nru a/arch/sparc/kernel/entry.S b/arch/sparc/kernel/entry.S
--- a/arch/sparc/kernel/entry.S	2004-10-18 14:56:29 -07:00
+++ b/arch/sparc/kernel/entry.S	2004-10-18 14:56:29 -07:00
@@ -858,7 +858,7 @@
 vac_hwflush_patch2_on:		sta	%g0, [%l3 + %l7] ASI_HWFLUSHSEG
 
 	.globl	invalid_segment_patch1, invalid_segment_patch2
-	.globl	num_context_patch1, num_context_patch2
+	.globl	num_context_patch1
 	.globl	vac_linesize_patch, vac_hwflush_patch1
 	.globl	vac_hwflush_patch2
 
diff -Nru a/arch/sparc/kernel/init_task.c b/arch/sparc/kernel/init_task.c
--- a/arch/sparc/kernel/init_task.c	2004-10-18 14:56:33 -07:00
+++ b/arch/sparc/kernel/init_task.c	2004-10-18 14:56:33 -07:00
@@ -23,6 +23,6 @@
  * in etrap.S which assumes it.
  */
 union thread_union init_thread_union
-	__attribute__((section (".text,#alloc")))
+	__attribute__((section (".text\"\n\t#")))
 	__attribute__((aligned (THREAD_SIZE)))
 	= { INIT_THREAD_INFO(init_task) };
diff -Nru a/arch/sparc/kernel/irq.c b/arch/sparc/kernel/irq.c
--- a/arch/sparc/kernel/irq.c	2004-10-18 14:55:54 -07:00
+++ b/arch/sparc/kernel/irq.c	2004-10-18 14:55:54 -07:00
@@ -45,7 +45,6 @@
 #include <asm/io.h>
 #include <asm/pgalloc.h>
 #include <asm/pgtable.h>
-#include <asm/hardirq.h>
 #include <asm/pcic.h>
 #include <asm/cacheflush.h>
 
diff -Nru a/arch/sparc/kernel/pcic.c b/arch/sparc/kernel/pcic.c
--- a/arch/sparc/kernel/pcic.c	2004-10-18 14:56:32 -07:00
+++ b/arch/sparc/kernel/pcic.c	2004-10-18 14:56:32 -07:00
@@ -36,10 +36,6 @@
 #include <asm/uaccess.h>
 
 
-struct pci_fixup pcibios_fixups[] = {
-	{ 0 }
-};
-
 unsigned int pcic_pin_to_irq(unsigned int pin, char *name);
 
 /*
diff -Nru a/arch/sparc/kernel/process.c b/arch/sparc/kernel/process.c
--- a/arch/sparc/kernel/process.c	2004-10-18 14:55:55 -07:00
+++ b/arch/sparc/kernel/process.c	2004-10-18 14:55:55 -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/ptrace.c b/arch/sparc/kernel/ptrace.c
--- a/arch/sparc/kernel/ptrace.c	2004-10-18 14:57:04 -07:00
+++ b/arch/sparc/kernel/ptrace.c	2004-10-18 14:57:04 -07:00
@@ -614,12 +614,9 @@
 		return;
 	if (!(current->ptrace & PT_PTRACED))
 		return;
-	current->exit_code = SIGTRAP | ((current->ptrace & PT_TRACESYSGOOD)
-					? 0x80 : 0);
-	current->state = TASK_STOPPED;
 	current->thread.flags ^= MAGIC_CONSTANT;
-	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
 	 * for normal use.  strace only continues with a signal if the
diff -Nru a/arch/sparc/kernel/setup.c b/arch/sparc/kernel/setup.c
--- a/arch/sparc/kernel/setup.c	2004-10-18 14:55:54 -07:00
+++ b/arch/sparc/kernel/setup.c	2004-10-18 14:55:54 -07:00
@@ -44,7 +44,6 @@
 #include <asm/kdebug.h>
 #include <asm/mbus.h>
 #include <asm/idprom.h>
-#include <asm/hardirq.h>
 #include <asm/machines.h>
 #include <asm/cpudata.h>
 #include <asm/setup.h>
diff -Nru a/arch/sparc/kernel/signal.c b/arch/sparc/kernel/signal.c
--- a/arch/sparc/kernel/signal.c	2004-10-18 14:56:48 -07:00
+++ b/arch/sparc/kernel/signal.c	2004-10-18 14:56:48 -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);
 }
 
 
@@ -635,6 +635,7 @@
 	regs->u_regs[UREG_FP] = (unsigned long) sf;
 	regs->u_regs[UREG_I0] = signo;
 	regs->u_regs[UREG_I1] = (unsigned long) &sf->info;
+	regs->u_regs[UREG_I2] = (unsigned long) &sf->info;
 
 	/* 4. signal handler */
 	regs->pc = (unsigned long) ka->sa.sa_handler;
@@ -662,7 +663,7 @@
 sigill_and_return:
 	do_exit(SIGILL);
 sigsegv:
-	do_exit(SIGSEGV);
+	force_sigsegv(signo, current);
 }
 
 static inline void
@@ -719,6 +720,7 @@
 	regs->u_regs[UREG_FP] = (unsigned long) sf;
 	regs->u_regs[UREG_I0] = signo;
 	regs->u_regs[UREG_I1] = (unsigned long) &sf->info;
+	regs->u_regs[UREG_I2] = (unsigned long) &sf->regs;
 
 	regs->pc = (unsigned long) ka->sa.sa_handler;
 	regs->npc = (regs->pc + 4);
@@ -744,7 +746,7 @@
 sigill:
 	do_exit(SIGILL);
 sigsegv:
-	do_exit(SIGSEGV);
+	force_sigsegv(signo, current);
 }
 
 /* Setup a Solaris stack frame */
@@ -874,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)
@@ -887,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)
@@ -928,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 */
@@ -1016,7 +1015,7 @@
 	return (err ? -EFAULT : 0);
 
 sigsegv_and_return:
-	do_exit(SIGSEGV);
+	force_sig(SIGSEGV, current);
 }
 
 static inline void
@@ -1034,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);
@@ -1075,6 +1072,7 @@
 {
 	siginfo_t info;
 	struct sparc_deliver_cookie cookie;
+	struct k_sigaction ka;
 	int signr;
 
 	/*
@@ -1094,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/smp.c b/arch/sparc/kernel/smp.c
--- a/arch/sparc/kernel/smp.c	2004-10-18 14:56:27 -07:00
+++ b/arch/sparc/kernel/smp.c	2004-10-18 14:56:27 -07:00
@@ -30,7 +30,6 @@
 #include <asm/pgalloc.h>
 #include <asm/pgtable.h>
 #include <asm/oplib.h>
-#include <asm/hardirq.h>
 #include <asm/cacheflush.h>
 #include <asm/tlbflush.h>
 #include <asm/cpudata.h>
diff -Nru a/arch/sparc/kernel/sparc_ksyms.c b/arch/sparc/kernel/sparc_ksyms.c
--- a/arch/sparc/kernel/sparc_ksyms.c	2004-10-18 14:55:54 -07:00
+++ b/arch/sparc/kernel/sparc_ksyms.c	2004-10-18 14:55:54 -07:00
@@ -41,7 +41,6 @@
 #include <asm/smp.h>
 #include <asm/mostek.h>
 #include <asm/ptrace.h>
-#include <asm/hardirq.h>
 #include <asm/user.h>
 #include <asm/uaccess.h>
 #include <asm/checksum.h>
@@ -214,6 +213,10 @@
 EXPORT_SYMBOL(pci_dma_sync_single_for_device);
 EXPORT_SYMBOL(pci_dma_sync_sg_for_cpu);
 EXPORT_SYMBOL(pci_dma_sync_sg_for_device);
+EXPORT_SYMBOL(pci_map_sg);
+EXPORT_SYMBOL(pci_unmap_sg);
+EXPORT_SYMBOL(pci_map_page);
+EXPORT_SYMBOL(pci_unmap_page);
 /* Actually, ioremap/iounmap are not PCI specific. But it is ok for drivers. */
 EXPORT_SYMBOL(ioremap);
 EXPORT_SYMBOL(iounmap);
@@ -297,6 +300,9 @@
 
 /* Cache flushing.  */
 EXPORT_SYMBOL(sparc_flush_page_to_ram);
+
+/* For when serial stuff is built as modules. */
+EXPORT_SYMBOL(sun_do_break);
 
 EXPORT_SYMBOL(__ret_efault);
 
diff -Nru a/arch/sparc/kernel/sun4d_smp.c b/arch/sparc/kernel/sun4d_smp.c
--- a/arch/sparc/kernel/sun4d_smp.c	2004-10-18 14:55:55 -07:00
+++ b/arch/sparc/kernel/sun4d_smp.c	2004-10-18 14:55:55 -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>
@@ -29,7 +30,6 @@
 #include <asm/pgalloc.h>
 #include <asm/pgtable.h>
 #include <asm/oplib.h>
-#include <asm/hardirq.h>
 #include <asm/sbus.h>
 #include <asm/sbi.h>
 #include <asm/tlbflush.h>
@@ -201,18 +201,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 +409,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 +426,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-10-18 14:56:50 -07:00
+++ b/arch/sparc/kernel/sun4m_smp.c	2004-10-18 14:56:50 -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>
 
@@ -28,7 +29,6 @@
 #include <asm/pgalloc.h>
 #include <asm/pgtable.h>
 #include <asm/oplib.h>
-#include <asm/hardirq.h>
 #include <asm/cpudata.h>
 
 #define IRQ_RESCHEDULE		13
@@ -173,18 +173,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 +391,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/systbls.S b/arch/sparc/kernel/systbls.S
--- a/arch/sparc/kernel/systbls.S	2004-10-18 14:56:32 -07:00
+++ b/arch/sparc/kernel/systbls.S	2004-10-18 14:56:32 -07:00
@@ -74,7 +74,7 @@
 /*260*/	.long sys_sched_getaffinity, sys_sched_setaffinity, sys_timer_settime, sys_timer_gettime, sys_timer_getoverrun
 /*265*/	.long sys_timer_delete, sys_timer_create, sys_nis_syscall, sys_io_setup, sys_io_destroy
 /*270*/	.long sys_io_submit, sys_io_cancel, sys_io_getevents, sys_mq_open, sys_mq_unlink
-/*275*/	.long sys_mq_timedsend, sys_mq_timedreceive, sys_mq_notify, sys_mq_getsetattr, sys_ni_syscall
+/*275*/	.long sys_mq_timedsend, sys_mq_timedreceive, sys_mq_notify, sys_mq_getsetattr, sys_waitid
 /*280*/	.long sys_ni_syscall, sys_ni_syscall, sys_ni_syscall
 
 #ifdef CONFIG_SUNOS_EMUL
diff -Nru a/arch/sparc/kernel/time.c b/arch/sparc/kernel/time.c
--- a/arch/sparc/kernel/time.c	2004-10-18 14:56:33 -07:00
+++ b/arch/sparc/kernel/time.c	2004-10-18 14:56:33 -07:00
@@ -79,38 +79,26 @@
 
 #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 char __copy_user_begin[], __copy_user_end[];
+	extern char __atomic_begin[], __atomic_end[];
+	extern char __bzero_begin[], __bzero_end[];
+	extern char __bitops_begin[], __bitops_end[];
+
+	unsigned long pc = regs->pc;
+
+	if (in_lock_functions(pc) ||
+	    (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 +117,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-10-18 14:55:54 -07:00
+++ b/arch/sparc/kernel/vmlinux.lds.S	2004-10-18 14:55:54 -07:00
@@ -13,6 +13,7 @@
   {
     *(.text)
     SCHED_TEXT
+    LOCK_TEXT
     *(.gnu.warning)
   } =0
   _etext = .;
@@ -46,9 +47,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-10-18 14:56:33 -07:00
+++ b/arch/sparc/mm/srmmu.c	2004-10-18 14:56: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-10-18 14:56:49 -07:00
+++ b/arch/sparc/mm/sun4c.c	2004-10-18 14:56:49 -07:00
@@ -379,7 +379,7 @@
 extern unsigned long invalid_segment_patch2, invalid_segment_patch2_ff;
 extern unsigned long invalid_segment_patch1_1ff, invalid_segment_patch2_1ff;
 extern unsigned long num_context_patch1, num_context_patch1_16;
-extern unsigned long num_context_patch2, num_context_patch2_16;
+extern unsigned long num_context_patch2_16;
 extern unsigned long vac_linesize_patch, vac_linesize_patch_32;
 extern unsigned long vac_hwflush_patch1, vac_hwflush_patch1_on;
 extern unsigned long vac_hwflush_patch2, vac_hwflush_patch2_on;
@@ -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/Kconfig b/arch/sparc64/Kconfig
--- a/arch/sparc64/Kconfig	2004-10-18 14:56:50 -07:00
+++ b/arch/sparc64/Kconfig	2004-10-18 14:56:50 -07:00
@@ -12,10 +12,13 @@
 	bool
 	default y
 
-source "init/Kconfig"
+config TIME_INTERPOLATION
+	bool
+	default y
 
+source "init/Kconfig"
 
-menu "General setup"
+menu "General machine setup"
 
 config BBC_I2C
 	tristate "UltraSPARC-III bootbus i2c controller driver"
@@ -549,7 +552,6 @@
 
 endmenu
 
-
 menu "XFree86 DRI support"
 
 config DRM
@@ -604,113 +606,10 @@
 
 source "arch/sparc64/oprofile/Kconfig"
 
-menu "Kernel hacking"
-
-config DEBUG_KERNEL
-	bool "Kernel debugging"
-	help
-	  Say Y here if you are developing drivers or trying to debug and
-	  identify kernel problems.
-
-config DEBUG_STACK_USAGE
-	bool "Enable stack utilization instrumentation"
-	depends on DEBUG_KERNEL
-	help
-	  Enables the display of the minimum amount of free stack which each
-	  task has ever had available in the sysrq-T and sysrq-P debug output.
-
-	  This option will slow down process creation somewhat.
-
-config DEBUG_SLAB
-	bool "Debug memory allocations"
-	depends on DEBUG_KERNEL
-	help
-	  Say Y here to have the kernel do limited verification on memory
-	  allocation as well as poisoning memory on free to catch use of freed
-	  memory.
-
-config MAGIC_SYSRQ
-	bool "Magic SysRq key"
-	depends on DEBUG_KERNEL
-	help
-	  If you say Y here, you will have some control over the system even
-	  if the system crashes for example during kernel debugging (e.g., you
-	  will be able to flush the buffer cache to disk, reboot the system
-	  immediately or dump some status information). This is accomplished
-	  by pressing various keys while holding SysRq (Alt+PrintScreen). It
-	  also works on a serial console (on PC hardware at least), if you
-	  send a BREAK and then within 5 seconds a command keypress. The
-	  keys are documented in <file:Documentation/sysrq.txt>. Don't say Y
-	  unless you really know what this hack does.
-
-config DEBUG_SPINLOCK
-	bool "Spinlock debugging"
-	depends on DEBUG_KERNEL
-	help
-	  Say Y here and build SMP to catch missing spinlock initialization
-	  and certain other kinds of spinlock errors commonly made.  This is
-	  best used in conjunction with the NMI watchdog so that spinlock
-	  deadlocks are also debuggable.
-
-config DEBUG_SPINLOCK_SLEEP
-	bool "Sleep-inside-spinlock checking"
-	depends DEBUG_KERNEL
-	help
-	  If you say Y here, various routines which may sleep will become very
-	  noisy if they are called with a spinlock held.	
-
-config DEBUG_BUGVERBOSE
-	bool "Verbose BUG() reporting (adds 70K)"
-	depends on DEBUG_KERNEL
-	help
-	  Say Y here to make BUG() panics output the file name and line number
-	  of the BUG call as well as the EIP and oops trace.  This aids
-	  debugging but costs about 70-100K of memory.
-
-config DEBUG_DCFLUSH
-	bool "D-cache flush debugging"
-	depends on DEBUG_KERNEL
-
-config DEBUG_INFO
-	bool "Compile the kernel with debug info"
-	depends on DEBUG_KERNEL
-	help
-          If you say Y here the resulting kernel image will include
-	  debugging info resulting in a larger kernel image.
-	  Say Y here only if you plan to use gdb to debug the kernel.
-	  If you don't debug the kernel, you can say N.
-	  
-config STACK_DEBUG
-	depends on DEBUG_KERNEL
-	bool "Stack Overflow Detection Support"
-
-config DEBUG_BOOTMEM
-	depends on DEBUG_KERNEL
-	bool "Debug BOOTMEM initialization"
-
-# We have a custom atomic_dec_and_lock() implementation but it's not
-# compatible with spinlock debugging so we need to fall back on
-# the generic version in that case.
-config HAVE_DEC_LOCK
-	bool
-	depends on SMP && !DEBUG_SPINLOCK
-	default y
-
-config MCOUNT
-	bool
-	depends on STACK_DEBUG
-	default y
-
-config FRAME_POINTER
-	bool
-	depends on MCOUNT
-	default y
-
-endmenu
+source "arch/sparc64/Kconfig.debug"
 
 source "security/Kconfig"
 
 source "crypto/Kconfig"
 
 source "lib/Kconfig"
-
diff -Nru a/arch/sparc64/Kconfig.debug b/arch/sparc64/Kconfig.debug
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/arch/sparc64/Kconfig.debug	2004-10-18 14:57:23 -07:00
@@ -0,0 +1,54 @@
+menu "Kernel hacking"
+
+source "lib/Kconfig.debug"
+
+config DEBUG_STACK_USAGE
+	bool "Enable stack utilization instrumentation"
+	depends on DEBUG_KERNEL
+	help
+	  Enables the display of the minimum amount of free stack which each
+	  task has ever had available in the sysrq-T and sysrq-P debug output.
+
+	  This option will slow down process creation somewhat.
+
+config KPROBES
+	bool "Kprobes"
+	depends on DEBUG_KERNEL
+	help
+	  Kprobes allows you to trap at almost any kernel address and
+	  execute a callback function.  register_kprobe() establishes
+	  a probepoint and specifies the callback.  Kprobes is useful
+	  for kernel debugging, non-intrusive instrumentation and testing.
+	  If in doubt, say "N".
+
+config DEBUG_DCFLUSH
+	bool "D-cache flush debugging"
+	depends on DEBUG_KERNEL
+
+config STACK_DEBUG
+	depends on DEBUG_KERNEL
+	bool "Stack Overflow Detection Support"
+
+config DEBUG_BOOTMEM
+	depends on DEBUG_KERNEL
+	bool "Debug BOOTMEM initialization"
+
+# We have a custom atomic_dec_and_lock() implementation but it's not
+# compatible with spinlock debugging so we need to fall back on
+# the generic version in that case.
+config HAVE_DEC_LOCK
+	bool
+	depends on SMP && !DEBUG_SPINLOCK
+	default y
+
+config MCOUNT
+	bool
+	depends on STACK_DEBUG
+	default y
+
+config FRAME_POINTER
+	bool
+	depends on MCOUNT
+	default y
+
+endmenu
diff -Nru a/arch/sparc64/Makefile b/arch/sparc64/Makefile
--- a/arch/sparc64/Makefile	2004-10-18 14:57:04 -07:00
+++ b/arch/sparc64/Makefile	2004-10-18 14:57:04 -07:00
@@ -8,16 +8,16 @@
 # Copyright (C) 1998 Jakub Jelinek (jj@ultra.linux.cz)
 #
 
-CHECK		:= $(CHECK) -D__sparc__=1 -D__sparc_v9__=1
+CHECKFLAGS	+= -D__sparc__ -D__sparc_v9__
 
-AFLAGS_vmlinux.lds.o += -Usparc
+CPPFLAGS_vmlinux.lds += -Usparc
 
 CC		:= $(shell if $(CC) -m64 -S -o /dev/null -xc /dev/null >/dev/null 2>&1; then echo $(CC); else echo sparc64-linux-gcc; fi )
 
-NEW_GCC := $(shell if $(CC) -m64 -mcmodel=medlow -S -o /dev/null -xc /dev/null >/dev/null 2>&1; then echo y; else echo n; fi; )
+NEW_GCC := $(call cc-option-yn, -m64 -mcmodel=medlow)
 NEW_GAS := $(shell if $(LD) -V 2>&1 | grep 'elf64_sparc' > /dev/null; then echo y; else echo n; fi)
 UNDECLARED_REGS := $(shell if $(CC) -c -x assembler /dev/null -Wa,--help | grep undeclared-regs > /dev/null; then echo y; else echo n; fi; )
-INLINE_LIMIT := $(shell if $(CC) -m64 -finline-limit=100000 -S -o /dev/null -xc /dev/null >/dev/null 2>&1; then echo y; else echo n; fi; )
+INLINE_LIMIT := $(call cc-option-yn, -m64 -finline-limit=100000)
 
 export NEW_GCC
 
diff -Nru a/arch/sparc64/boot/Makefile b/arch/sparc64/boot/Makefile
--- a/arch/sparc64/boot/Makefile	2004-10-18 14:55:53 -07:00
+++ b/arch/sparc64/boot/Makefile	2004-10-18 14:55:53 -07:00
@@ -7,7 +7,7 @@
 ROOT_IMG	:= /usr/src/root.img
 ELFTOAOUT	:= elftoaout
 
-host-progs	:= piggyback
+hostprogs-y	:= piggyback
 targets		:= image tftpboot.img vmlinux.aout
 
 quiet_cmd_elftoaout = ELF2AOUT $@
diff -Nru a/arch/sparc64/defconfig b/arch/sparc64/defconfig
--- a/arch/sparc64/defconfig	2004-10-18 14:56:28 -07:00
+++ b/arch/sparc64/defconfig	2004-10-18 14:56:28 -07:00
@@ -1,8 +1,11 @@
 #
 # Automatically generated make config: don't edit
+# Linux kernel version: 2.6.9-rc3
+# Sun Oct  3 14:28:53 2004
 #
 CONFIG_64BIT=y
 CONFIG_MMU=y
+CONFIG_TIME_INTERPOLATION=y
 
 #
 # Code maturity level options
@@ -13,6 +16,7 @@
 #
 # General setup
 #
+CONFIG_LOCALVERSION=""
 CONFIG_SWAP=y
 CONFIG_SYSVIPC=y
 CONFIG_POSIX_MQUEUE=y
@@ -33,6 +37,8 @@
 CONFIG_IOSCHED_DEADLINE=y
 CONFIG_IOSCHED_CFQ=y
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+CONFIG_SHMEM=y
+# CONFIG_TINY_SHMEM is not set
 
 #
 # Loadable module support
@@ -46,7 +52,7 @@
 CONFIG_STOP_MACHINE=y
 
 #
-# General setup
+# General machine setup
 #
 CONFIG_BBC_I2C=m
 CONFIG_VT=y
@@ -65,6 +71,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 +125,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 +161,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 +224,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
 
 #
@@ -251,7 +259,6 @@
 # CONFIG_BLK_DEV_IDEDMA_FORCED is not set
 CONFIG_IDEDMA_PCI_AUTO=y
 CONFIG_IDEDMA_ONLYDISK=y
-CONFIG_BLK_DEV_ADMA=y
 # CONFIG_BLK_DEV_AEC62XX is not set
 CONFIG_BLK_DEV_ALI15X3=y
 # CONFIG_WDC_ALI15X3 is not set
@@ -328,7 +335,8 @@
 # CONFIG_AIC79XX_DEBUG_ENABLE is not set
 CONFIG_AIC79XX_DEBUG_MASK=0
 # CONFIG_AIC79XX_REG_PRETTY_PRINT is not set
-# CONFIG_SCSI_MEGARAID is not set
+# CONFIG_MEGARAID_NEWGEN is not set
+# CONFIG_MEGARAID_LEGACY is not set
 CONFIG_SCSI_SATA=y
 CONFIG_SCSI_SATA_SVW=m
 CONFIG_SCSI_ATA_PIIX=m
@@ -353,9 +361,7 @@
 CONFIG_SCSI_SYM53C8XX_DEFAULT_TAGS=16
 CONFIG_SCSI_SYM53C8XX_MAX_TAGS=64
 # CONFIG_SCSI_SYM53C8XX_IOMAPPED is not set
-CONFIG_SCSI_IPR=m
-# CONFIG_SCSI_IPR_TRACE is not set
-# CONFIG_SCSI_IPR_DUMP is not set
+# CONFIG_SCSI_IPR is not set
 CONFIG_SCSI_QLOGIC_ISP=m
 CONFIG_SCSI_QLOGIC_FC=y
 CONFIG_SCSI_QLOGIC_FC_FIRMWARE=y
@@ -398,6 +404,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
@@ -412,7 +419,6 @@
 #
 CONFIG_FUSION=m
 CONFIG_FUSION_MAX_SGE=40
-CONFIG_FUSION_ISENSE=m
 CONFIG_FUSION_CTL=m
 CONFIG_FUSION_LAN=m
 
@@ -475,6 +481,7 @@
 CONFIG_INET_AH=y
 CONFIG_INET_ESP=y
 CONFIG_INET_IPCOMP=y
+CONFIG_INET_TUNNEL=y
 
 #
 # IP: Virtual Server Configuration
@@ -514,6 +521,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
@@ -523,6 +531,8 @@
 # IP: Netfilter Configuration
 #
 CONFIG_IP_NF_CONNTRACK=m
+CONFIG_IP_NF_CT_ACCT=y
+CONFIG_IP_NF_CT_PROTO_SCTP=m
 CONFIG_IP_NF_FTP=m
 CONFIG_IP_NF_IRC=m
 CONFIG_IP_NF_TFTP=m
@@ -548,8 +558,15 @@
 CONFIG_IP_NF_MATCH_CONNTRACK=m
 CONFIG_IP_NF_MATCH_OWNER=m
 CONFIG_IP_NF_MATCH_PHYSDEV=m
+CONFIG_IP_NF_MATCH_ADDRTYPE=m
+CONFIG_IP_NF_MATCH_REALM=m
+CONFIG_IP_NF_MATCH_SCTP=m
+CONFIG_IP_NF_MATCH_COMMENT=m
 CONFIG_IP_NF_FILTER=m
 CONFIG_IP_NF_TARGET_REJECT=m
+CONFIG_IP_NF_TARGET_LOG=m
+CONFIG_IP_NF_TARGET_ULOG=m
+CONFIG_IP_NF_TARGET_TCPMSS=m
 CONFIG_IP_NF_NAT=m
 CONFIG_IP_NF_NAT_NEEDED=y
 CONFIG_IP_NF_TARGET_MASQUERADE=m
@@ -568,18 +585,13 @@
 CONFIG_IP_NF_TARGET_DSCP=m
 CONFIG_IP_NF_TARGET_MARK=m
 CONFIG_IP_NF_TARGET_CLASSIFY=m
-CONFIG_IP_NF_TARGET_LOG=m
-CONFIG_IP_NF_TARGET_ULOG=m
-CONFIG_IP_NF_TARGET_TCPMSS=m
+CONFIG_IP_NF_RAW=m
+CONFIG_IP_NF_TARGET_NOTRACK=m
 CONFIG_IP_NF_ARPTABLES=m
 CONFIG_IP_NF_ARPFILTER=m
 CONFIG_IP_NF_ARP_MANGLE=m
 CONFIG_IP_NF_COMPAT_IPCHAINS=m
 CONFIG_IP_NF_COMPAT_IPFWADM=m
-CONFIG_IP_NF_TARGET_NOTRACK=m
-CONFIG_IP_NF_RAW=m
-CONFIG_IP_NF_MATCH_ADDRTYPE=m
-CONFIG_IP_NF_MATCH_REALM=m
 
 #
 # IPv6: Netfilter Configuration
@@ -599,6 +611,7 @@
 CONFIG_IP6_NF_MATCH_AHESP=m
 CONFIG_IP6_NF_MATCH_LENGTH=m
 CONFIG_IP6_NF_MATCH_EUI64=m
+CONFIG_IP6_NF_MATCH_PHYSDEV=m
 CONFIG_IP6_NF_FILTER=m
 CONFIG_IP6_NF_TARGET_LOG=m
 CONFIG_IP6_NF_MANGLE=m
@@ -704,6 +717,8 @@
 CONFIG_NET_CLS_RSVP6=m
 CONFIG_NET_CLS_ACT=y
 CONFIG_NET_ACT_POLICE=m
+CONFIG_NET_ACT_GACT=m
+CONFIG_GACT_PROB=y
 
 #
 # Network testing
@@ -880,6 +895,7 @@
 CONFIG_HAMACHI=m
 CONFIG_YELLOWFIN=m
 CONFIG_R8169=m
+CONFIG_R8169_NAPI=y
 CONFIG_SK98LIN=m
 CONFIG_TIGON3=m
 
@@ -1064,6 +1080,7 @@
 # CONFIG_SERIO_CT82C710 is not set
 # CONFIG_SERIO_PARKBD is not set
 CONFIG_SERIO_PCIPS2=m
+CONFIG_SERIO_RAW=m
 
 #
 # Input Device Drivers
@@ -1095,6 +1112,7 @@
 #
 CONFIG_I2C_ALGOBIT=y
 CONFIG_I2C_ALGOPCF=m
+CONFIG_I2C_ALGOPCA=m
 
 #
 # I2C Hardware Bus support
@@ -1119,6 +1137,7 @@
 CONFIG_I2C_VIA=m
 CONFIG_I2C_VIAPRO=m
 CONFIG_I2C_VOODOO3=m
+CONFIG_I2C_PCA_ISA=m
 
 #
 # Hardware Sensors Chip support
@@ -1140,6 +1159,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
@@ -1262,6 +1282,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
@@ -1473,6 +1494,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
@@ -1512,6 +1534,7 @@
 # ALSA USB devices
 #
 # CONFIG_SND_USB_AUDIO is not set
+CONFIG_SND_USB_USX2Y=m
 
 #
 # ALSA Sparc devices
@@ -1531,6 +1554,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
@@ -1596,7 +1620,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
@@ -1733,14 +1756,15 @@
 # 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_KPROBES=y
+# CONFIG_DEBUG_DCFLUSH is not set
 # CONFIG_STACK_DEBUG is not set
 # CONFIG_DEBUG_BOOTMEM is not set
 CONFIG_HAVE_DEC_LOCK=y
@@ -1761,6 +1785,7 @@
 CONFIG_CRYPTO_SHA1=y
 CONFIG_CRYPTO_SHA256=m
 CONFIG_CRYPTO_SHA512=m
+CONFIG_CRYPTO_WP512=m
 CONFIG_CRYPTO_DES=y
 CONFIG_CRYPTO_BLOWFISH=m
 CONFIG_CRYPTO_TWOFISH=m
diff -Nru a/arch/sparc64/kernel/Makefile b/arch/sparc64/kernel/Makefile
--- a/arch/sparc64/kernel/Makefile	2004-10-18 14:56:17 -07:00
+++ b/arch/sparc64/kernel/Makefile	2004-10-18 14:56:17 -07:00
@@ -5,7 +5,7 @@
 EXTRA_AFLAGS := -ansi
 EXTRA_CFLAGS := -Werror
 
-extra-y		:= head.o init_task.o vmlinux.lds.s
+extra-y		:= head.o init_task.o vmlinux.lds
 
 obj-y		:= process.o setup.o cpu.o idprom.o \
 		   traps.o devices.o auxio.o \
@@ -22,6 +22,7 @@
 obj-$(CONFIG_MODULES) += module.o
 obj-$(CONFIG_US3_FREQ) += us3_cpufreq.o
 obj-$(CONFIG_US2E_FREQ) += us2e_cpufreq.o
+obj-$(CONFIG_KPROBES) += kprobes.o
 
 ifdef CONFIG_SUNOS_EMUL
   obj-y += sys_sunos32.o sunos_ioctl32.o
diff -Nru a/arch/sparc64/kernel/auxio.c b/arch/sparc64/kernel/auxio.c
--- a/arch/sparc64/kernel/auxio.c	2004-10-18 14:56:33 -07:00
+++ b/arch/sparc64/kernel/auxio.c	2004-10-18 14:56:33 -07:00
@@ -17,7 +17,7 @@
 #include <asm/auxio.h>
 
 /* This cannot be static, as it is referenced in entry.S */
-unsigned long auxio_register = 0UL;
+void __iomem *auxio_register = 0UL;
 
 enum auxio_type {
 	AUXIO_TYPE_NODEV,
@@ -30,7 +30,7 @@
 
 static void __auxio_sbus_set(u8 bits_on, u8 bits_off)
 {
-	if(auxio_register) {
+	if (auxio_register) {
 		unsigned char regval;
 		unsigned long flags;
 		unsigned char newval;
@@ -49,7 +49,7 @@
 
 static void __auxio_ebus_set(u8 bits_on, u8 bits_off)
 {
-	if(auxio_register) {
+	if (auxio_register) {
 		unsigned char regval;
 		unsigned long flags;
 		unsigned char newval;
@@ -126,7 +126,8 @@
 	if (sdev) {
 		auxio_devtype  = AUXIO_TYPE_SBUS;
 		auxio_register = sbus_ioremap(&sdev->resource[0], 0,
-		  		sdev->reg_addrs[0].reg_size, "auxiliaryIO");
+					      sdev->reg_addrs[0].reg_size,
+					      "auxiliaryIO");
 	}
 #ifdef CONFIG_PCI
 	else {
@@ -142,7 +143,7 @@
 	ebus_done:
 		if (edev) {
 			auxio_devtype  = AUXIO_TYPE_EBUS;
-			auxio_register = (unsigned long)
+			auxio_register =
 				ioremap(edev->resource[0].start, sizeof(u32));
 		}
 	}
diff -Nru a/arch/sparc64/kernel/binfmt_elf32.c b/arch/sparc64/kernel/binfmt_elf32.c
--- a/arch/sparc64/kernel/binfmt_elf32.c	2004-10-18 14:56:50 -07:00
+++ b/arch/sparc64/kernel/binfmt_elf32.c	2004-10-18 14:56:50 -07:00
@@ -27,12 +27,12 @@
 #define ELF_CORE_COPY_REGS(__elf_regs, __pt_regs)	\
 do {	unsigned int *dest = &(__elf_regs[0]);		\
 	struct pt_regs *src = (__pt_regs);		\
-	unsigned int *sp;				\
+	unsigned int __user *sp;			\
 	int i;						\
 	for(i = 0; i < 16; i++)				\
 		dest[i] = (unsigned int) src->u_regs[i];\
 	/* Don't try this at home kids... */		\
-	sp = (unsigned int *) (src->u_regs[14] &	\
+	sp = (unsigned int __user *) (src->u_regs[14] &	\
 		0x00000000fffffffc);			\
 	for(i = 0; i < 16; i++)				\
 		__get_user(dest[i+16], &sp[i]);		\
diff -Nru a/arch/sparc64/kernel/chmc.c b/arch/sparc64/kernel/chmc.c
--- a/arch/sparc64/kernel/chmc.c	2004-10-18 14:56:27 -07:00
+++ b/arch/sparc64/kernel/chmc.c	2004-10-18 14:56:27 -07:00
@@ -72,7 +72,7 @@
 	struct obp_mem_layout	layout_prop;
 	int			layout_size;
 
-	void			*regs;
+	void __iomem		*regs;
 
 	u64			timing_control1;
 	u64			timing_control2;
diff -Nru a/arch/sparc64/kernel/etrap.S b/arch/sparc64/kernel/etrap.S
--- a/arch/sparc64/kernel/etrap.S	2004-10-18 14:56:28 -07:00
+++ b/arch/sparc64/kernel/etrap.S	2004-10-18 14:56:28 -07:00
@@ -17,7 +17,8 @@
 
 #define		TASK_REGOFF		(THREAD_SIZE-TRACEREG_SZ-STACKFRAME_SZ)
 #define		ETRAP_PSTATE1		(PSTATE_RMO | PSTATE_PRIV)
-#define		ETRAP_PSTATE2		(PSTATE_RMO | PSTATE_PEF | PSTATE_PRIV | PSTATE_IE)
+#define		ETRAP_PSTATE2		\
+		(PSTATE_RMO | PSTATE_PEF | PSTATE_PRIV | PSTATE_IE)
 
 /*
  * On entry, %g7 is return address - 0x4.
@@ -27,91 +28,91 @@
 		.text		
 		.align	64
 		.globl	etrap, etrap_irq, etraptl1
-etrap:		rdpr	%pil, %g2						! Single 	Group
+etrap:		rdpr	%pil, %g2
 etrap_irq:
-		rdpr	%tstate, %g1						! Single 	Group
-		sllx	%g2, 20, %g3						! IEU0		Group
-		andcc	%g1, TSTATE_PRIV, %g0					! IEU1
-		or	%g1, %g3, %g1						! IEU0		Group
-		bne,pn	%xcc, 1f						! CTI
-		 sub	%sp, STACKFRAME_SZ+TRACEREG_SZ-STACK_BIAS, %g2		! IEU1
-		wrpr	%g0, 7, %cleanwin					! Single	Group+4bubbles
-
-		sethi	%hi(TASK_REGOFF), %g2					! IEU0		Group		
-		sethi	%hi(TSTATE_PEF), %g3					! IEU1
-		or	%g2, %lo(TASK_REGOFF), %g2				! IEU0		Group
-		and	%g1, %g3, %g3						! IEU1
-		brnz,pn	%g3, 1f							! CTI+IEU1	Group
-		 add	%g6, %g2, %g2						! IEU0
-		wr	%g0, 0, %fprs						! Single	Group+4bubbles
-1:		rdpr	%tpc, %g3						! Single	Group
-
-		stx	%g1, [%g2 + STACKFRAME_SZ + PT_V9_TSTATE]		! Store		Group
-		rdpr	%tnpc, %g1						! Single	Group
-		stx	%g3, [%g2 + STACKFRAME_SZ + PT_V9_TPC]			! Store		Group
-		rd	%y, %g3							! Single	Group+4bubbles
-		stx	%g1, [%g2 + STACKFRAME_SZ + PT_V9_TNPC]			! Store		Group
-		st	%g3, [%g2 + STACKFRAME_SZ + PT_V9_Y]			! Store		Group
-		save	%g2, -STACK_BIAS, %sp	! Ordering here is critical	! Single	Group
-		mov	%g6, %l6						! IEU0		Group
-
-		bne,pn	%xcc, 3f						! CTI		
-		 mov	PRIMARY_CONTEXT, %l4					! IEU1
-		rdpr	%canrestore, %g3					! Single	Group+4bubbles
-		rdpr	%wstate, %g2						! Single	Group+4bubbles
-		wrpr	%g0, 0, %canrestore					! Single	Group+4bubbles
-		sll	%g2, 3, %g2						! IEU0		Group
-		mov	1, %l5							! IEU1
-		stb	%l5, [%l6 + TI_FPDEPTH]					! Store
-
-		wrpr	%g3, 0, %otherwin					! Single	Group+4bubbles
-		wrpr	%g2, 0, %wstate						! Single	Group+4bubbles
-		stxa	%g0, [%l4] ASI_DMMU					! Store		Group
-		flush	%l6							! Single	Group+9bubbles
-		wr	%g0, ASI_AIUS, %asi					! Single	Group+4bubbles
-2:		wrpr	%g0, 0x0, %tl						! Single	Group+4bubbles
-		mov	%g4, %l4						! IEU1
-		mov	%g5, %l5						! IEU0		Group
-
-		mov	%g7, %l2						! IEU1
-		wrpr	%g0, ETRAP_PSTATE1, %pstate				! Single	Group+4bubbles
-		stx	%g1, [%sp + PTREGS_OFF + PT_V9_G1]			! Store		Group
-		stx	%g2, [%sp + PTREGS_OFF + PT_V9_G2]			! Store		Group
-		stx	%g3, [%sp + PTREGS_OFF + PT_V9_G3]			! Store		Group
-		stx	%g4, [%sp + PTREGS_OFF + PT_V9_G4]			! Store		Group
-		stx	%g5, [%sp + PTREGS_OFF + PT_V9_G5]			! Store		Group
-		stx	%g6, [%sp + PTREGS_OFF + PT_V9_G6]			! Store		Group
-
-		stx	%g7, [%sp + PTREGS_OFF + PT_V9_G7]			! Store		Group
-		stx	%i0, [%sp + PTREGS_OFF + PT_V9_I0]			! Store		Group
-		stx	%i1, [%sp + PTREGS_OFF + PT_V9_I1]			! Store		Group
-		stx	%i2, [%sp + PTREGS_OFF + PT_V9_I2]			! Store		Group
-		stx	%i3, [%sp + PTREGS_OFF + PT_V9_I3]			! Store		Group
-		stx	%i4, [%sp + PTREGS_OFF + PT_V9_I4]			! Store		Group
-		stx	%i5, [%sp + PTREGS_OFF + PT_V9_I5]			! Store		Group
-
-		stx	%i6, [%sp + PTREGS_OFF + PT_V9_I6]			! Store		Group
-		stx	%i7, [%sp + PTREGS_OFF + PT_V9_I7]			! Store		Group
-		wrpr	%g0, ETRAP_PSTATE2, %pstate				! Single	Group+4bubbles
-		mov	%l6, %g6						! IEU0
-		jmpl	%l2 + 0x4, %g0						! CTI		Group
-		 ldx	[%g6 + TI_TASK], %g4					! Load
+		rdpr	%tstate, %g1
+		sllx	%g2, 20, %g3
+		andcc	%g1, TSTATE_PRIV, %g0
+		or	%g1, %g3, %g1
+		bne,pn	%xcc, 1f
+		 sub	%sp, STACKFRAME_SZ+TRACEREG_SZ-STACK_BIAS, %g2
+		wrpr	%g0, 7, %cleanwin
+
+		sethi	%hi(TASK_REGOFF), %g2
+		sethi	%hi(TSTATE_PEF), %g3
+		or	%g2, %lo(TASK_REGOFF), %g2
+		and	%g1, %g3, %g3
+		brnz,pn	%g3, 1f
+		 add	%g6, %g2, %g2
+		wr	%g0, 0, %fprs
+1:		rdpr	%tpc, %g3
+
+		stx	%g1, [%g2 + STACKFRAME_SZ + PT_V9_TSTATE]
+		rdpr	%tnpc, %g1
+		stx	%g3, [%g2 + STACKFRAME_SZ + PT_V9_TPC]
+		rd	%y, %g3
+		stx	%g1, [%g2 + STACKFRAME_SZ + PT_V9_TNPC]
+		st	%g3, [%g2 + STACKFRAME_SZ + PT_V9_Y]
+		save	%g2, -STACK_BIAS, %sp	! Ordering here is critical
+		mov	%g6, %l6
+
+		bne,pn	%xcc, 3f
+		 mov	PRIMARY_CONTEXT, %l4
+		rdpr	%canrestore, %g3
+		rdpr	%wstate, %g2
+		wrpr	%g0, 0, %canrestore
+		sll	%g2, 3, %g2
+		mov	1, %l5
+		stb	%l5, [%l6 + TI_FPDEPTH]
+
+		wrpr	%g3, 0, %otherwin
+		wrpr	%g2, 0, %wstate
+		stxa	%g0, [%l4] ASI_DMMU
+		flush	%l6
+		wr	%g0, ASI_AIUS, %asi
+2:		wrpr	%g0, 0x0, %tl
+		mov	%g4, %l4
+		mov	%g5, %l5
+
+		mov	%g7, %l2
+		wrpr	%g0, ETRAP_PSTATE1, %pstate
+		stx	%g1, [%sp + PTREGS_OFF + PT_V9_G1]
+		stx	%g2, [%sp + PTREGS_OFF + PT_V9_G2]
+		stx	%g3, [%sp + PTREGS_OFF + PT_V9_G3]
+		stx	%g4, [%sp + PTREGS_OFF + PT_V9_G4]
+		stx	%g5, [%sp + PTREGS_OFF + PT_V9_G5]
+		stx	%g6, [%sp + PTREGS_OFF + PT_V9_G6]
+
+		stx	%g7, [%sp + PTREGS_OFF + PT_V9_G7]
+		stx	%i0, [%sp + PTREGS_OFF + PT_V9_I0]
+		stx	%i1, [%sp + PTREGS_OFF + PT_V9_I1]
+		stx	%i2, [%sp + PTREGS_OFF + PT_V9_I2]
+		stx	%i3, [%sp + PTREGS_OFF + PT_V9_I3]
+		stx	%i4, [%sp + PTREGS_OFF + PT_V9_I4]
+		stx	%i5, [%sp + PTREGS_OFF + PT_V9_I5]
+
+		stx	%i6, [%sp + PTREGS_OFF + PT_V9_I6]
+		stx	%i7, [%sp + PTREGS_OFF + PT_V9_I7]
+		wrpr	%g0, ETRAP_PSTATE2, %pstate
+		mov	%l6, %g6
+		jmpl	%l2 + 0x4, %g0
+		 ldx	[%g6 + TI_TASK], %g4
 		nop
 		nop
 		nop
 
-3:		ldub	[%l6 + TI_FPDEPTH], %l5					! Load		Group
-		add	%l6, TI_FPSAVED + 1, %l4				! IEU0
-		srl	%l5, 1, %l3						! IEU0		Group
-		add	%l5, 2, %l5						! IEU1
-		stb	%l5, [%l6 + TI_FPDEPTH]					! Store
-		ba,pt	%xcc, 2b						! CTI
-		 stb	%g0, [%l4 + %l3]					! Store		Group
+3:		ldub	[%l6 + TI_FPDEPTH], %l5
+		add	%l6, TI_FPSAVED + 1, %l4
+		srl	%l5, 1, %l3
+		add	%l5, 2, %l5
+		stb	%l5, [%l6 + TI_FPDEPTH]
+		ba,pt	%xcc, 2b
+		 stb	%g0, [%l4 + %l3]
 		nop
 
 etraptl1:	/* Save tstate/tpc/tnpc of TL 1-->4 and the tl register itself.
-		 * We place this right after pt_regs on the trap stack.  The layout
-		 * is:
+		 * We place this right after pt_regs on the trap stack.
+		 * The layout is:
 		 *	0x00	TL1's TSTATE
 		 *	0x08	TL1's TPC
 		 *	0x10	TL1's TNPC
@@ -166,81 +167,81 @@
 		wrpr	%g1, %tl
 		stx	%g1, [%g2 + STACK_BIAS + 0x80]
 
-		rdpr	%tstate, %g1						! Single	Group+4bubbles
-		sub	%g2, STACKFRAME_SZ + TRACEREG_SZ - STACK_BIAS, %g2	! IEU1
-		ba,pt	%xcc, 1b						! CTI		Group
-		 andcc	%g1, TSTATE_PRIV, %g0					! IEU0
+		rdpr	%tstate, %g1
+		sub	%g2, STACKFRAME_SZ + TRACEREG_SZ - STACK_BIAS, %g2
+		ba,pt	%xcc, 1b
+		 andcc	%g1, TSTATE_PRIV, %g0
 
 		.align	64
 		.globl	scetrap
-scetrap:	rdpr	%pil, %g2						! Single 	Group
-		rdpr	%tstate, %g1						! Single 	Group
-		sllx	%g2, 20, %g3						! IEU0		Group
-		andcc	%g1, TSTATE_PRIV, %g0					! IEU1
-		or	%g1, %g3, %g1						! IEU0		Group
-		bne,pn	%xcc, 1f						! CTI
-		 sub	%sp, (STACKFRAME_SZ+TRACEREG_SZ-STACK_BIAS), %g2	! IEU1
-		wrpr	%g0, 7, %cleanwin					! Single	Group+4bubbles
-
-		sllx	%g1, 51, %g3						! IEU0		Group
-		sethi	%hi(TASK_REGOFF), %g2					! IEU1
-		or	%g2, %lo(TASK_REGOFF), %g2				! IEU0		Group
-		brlz,pn	%g3, 1f							! CTI+IEU1
-		 add	%g6, %g2, %g2						! IEU0		Group
-		wr	%g0, 0, %fprs						! Single	Group+4bubbles
-1:		rdpr	%tpc, %g3						! Single	Group
-		stx	%g1, [%g2 + STACKFRAME_SZ + PT_V9_TSTATE]		! Store		Group
-
-		rdpr	%tnpc, %g1						! Single	Group
-		stx	%g3, [%g2 + STACKFRAME_SZ + PT_V9_TPC]			! Store		Group
-		stx	%g1, [%g2 + STACKFRAME_SZ + PT_V9_TNPC]			! Store		Group
-		save	%g2, -STACK_BIAS, %sp	! Ordering here is critical	! Single	Group
-		mov	%g6, %l6						! IEU0		Group
-		bne,pn	%xcc, 2f						! CTI		
-		 mov	ASI_P, %l7						! IEU1
-		rdpr	%canrestore, %g3					! Single	Group+4bubbles
-
-		rdpr	%wstate, %g2						! Single	Group+4bubbles
-		wrpr	%g0, 0, %canrestore					! Single	Group+4bubbles
-		sll	%g2, 3, %g2						! IEU0		Group
-		mov	PRIMARY_CONTEXT, %l4					! IEU1
-		wrpr	%g3, 0, %otherwin					! Single	Group+4bubbles
-		wrpr	%g2, 0, %wstate						! Single	Group+4bubbles
-		stxa	%g0, [%l4] ASI_DMMU					! Store
-		flush	%l6							! Single	Group+9bubbles
-
-		mov	ASI_AIUS, %l7						! IEU0		Group
-2:		mov	%g4, %l4						! IEU1
-		mov	%g5, %l5						! IEU0		Group
-		add	%g7, 0x4, %l2						! IEU1
-		wrpr	%g0, ETRAP_PSTATE1, %pstate				! Single	Group+4bubbles
-		stx	%g1, [%sp + PTREGS_OFF + PT_V9_G1]			! Store		Group
-		stx	%g2, [%sp + PTREGS_OFF + PT_V9_G2]			! Store		Group
-		sllx	%l7, 24, %l7						! IEU0
-
-		stx	%g3, [%sp + PTREGS_OFF + PT_V9_G3]			! Store		Group
-		rdpr	%cwp, %l0						! Single	Group
-		stx	%g4, [%sp + PTREGS_OFF + PT_V9_G4]			! Store		Group
-		stx	%g5, [%sp + PTREGS_OFF + PT_V9_G5]			! Store		Group
-		stx	%g6, [%sp + PTREGS_OFF + PT_V9_G6]			! Store		Group
-		stx	%g7, [%sp + PTREGS_OFF + PT_V9_G7]			! Store		Group
-		or	%l7, %l0, %l7						! IEU0
-		sethi	%hi(TSTATE_RMO | TSTATE_PEF), %l0			! IEU1
-
-		or	%l7, %l0, %l7						! IEU0		Group
-		wrpr	%l2, %tnpc						! Single	Group+4bubbles
-		wrpr	%l7, (TSTATE_PRIV | TSTATE_IE), %tstate			! Single	Group+4bubbles
-		stx	%i0, [%sp + PTREGS_OFF + PT_V9_I0]			! Store		Group
-		stx	%i1, [%sp + PTREGS_OFF + PT_V9_I1]			! Store		Group
-		stx	%i2, [%sp + PTREGS_OFF + PT_V9_I2]			! Store		Group
-		stx	%i3, [%sp + PTREGS_OFF + PT_V9_I3]			! Store		Group
-		stx	%i4, [%sp + PTREGS_OFF + PT_V9_I4]			! Store		Group
-
-		stx	%i5, [%sp + PTREGS_OFF + PT_V9_I5]			! Store		Group
-		stx	%i6, [%sp + PTREGS_OFF + PT_V9_I6]			! Store		Group
-		mov	%l6, %g6						! IEU1
-		stx	%i7, [%sp + PTREGS_OFF + PT_V9_I7]			! Store		Group
-		ldx	[%g6 + TI_TASK], %g4					! Load		Group
+scetrap:	rdpr	%pil, %g2
+		rdpr	%tstate, %g1
+		sllx	%g2, 20, %g3
+		andcc	%g1, TSTATE_PRIV, %g0
+		or	%g1, %g3, %g1
+		bne,pn	%xcc, 1f
+		 sub	%sp, (STACKFRAME_SZ+TRACEREG_SZ-STACK_BIAS), %g2
+		wrpr	%g0, 7, %cleanwin
+
+		sllx	%g1, 51, %g3
+		sethi	%hi(TASK_REGOFF), %g2
+		or	%g2, %lo(TASK_REGOFF), %g2
+		brlz,pn	%g3, 1f
+		 add	%g6, %g2, %g2
+		wr	%g0, 0, %fprs
+1:		rdpr	%tpc, %g3
+		stx	%g1, [%g2 + STACKFRAME_SZ + PT_V9_TSTATE]
+
+		rdpr	%tnpc, %g1
+		stx	%g3, [%g2 + STACKFRAME_SZ + PT_V9_TPC]
+		stx	%g1, [%g2 + STACKFRAME_SZ + PT_V9_TNPC]
+		save	%g2, -STACK_BIAS, %sp	! Ordering here is critical
+		mov	%g6, %l6
+		bne,pn	%xcc, 2f
+		 mov	ASI_P, %l7
+		rdpr	%canrestore, %g3
+
+		rdpr	%wstate, %g2
+		wrpr	%g0, 0, %canrestore
+		sll	%g2, 3, %g2
+		mov	PRIMARY_CONTEXT, %l4
+		wrpr	%g3, 0, %otherwin
+		wrpr	%g2, 0, %wstate
+		stxa	%g0, [%l4] ASI_DMMU
+		flush	%l6
+
+		mov	ASI_AIUS, %l7
+2:		mov	%g4, %l4
+		mov	%g5, %l5
+		add	%g7, 0x4, %l2
+		wrpr	%g0, ETRAP_PSTATE1, %pstate
+		stx	%g1, [%sp + PTREGS_OFF + PT_V9_G1]
+		stx	%g2, [%sp + PTREGS_OFF + PT_V9_G2]
+		sllx	%l7, 24, %l7
+
+		stx	%g3, [%sp + PTREGS_OFF + PT_V9_G3]
+		rdpr	%cwp, %l0
+		stx	%g4, [%sp + PTREGS_OFF + PT_V9_G4]
+		stx	%g5, [%sp + PTREGS_OFF + PT_V9_G5]
+		stx	%g6, [%sp + PTREGS_OFF + PT_V9_G6]
+		stx	%g7, [%sp + PTREGS_OFF + PT_V9_G7]
+		or	%l7, %l0, %l7
+		sethi	%hi(TSTATE_RMO | TSTATE_PEF), %l0
+
+		or	%l7, %l0, %l7
+		wrpr	%l2, %tnpc
+		wrpr	%l7, (TSTATE_PRIV | TSTATE_IE), %tstate
+		stx	%i0, [%sp + PTREGS_OFF + PT_V9_I0]
+		stx	%i1, [%sp + PTREGS_OFF + PT_V9_I1]
+		stx	%i2, [%sp + PTREGS_OFF + PT_V9_I2]
+		stx	%i3, [%sp + PTREGS_OFF + PT_V9_I3]
+		stx	%i4, [%sp + PTREGS_OFF + PT_V9_I4]
+
+		stx	%i5, [%sp + PTREGS_OFF + PT_V9_I5]
+		stx	%i6, [%sp + PTREGS_OFF + PT_V9_I6]
+		mov	%l6, %g6
+		stx	%i7, [%sp + PTREGS_OFF + PT_V9_I7]
+		ldx	[%g6 + TI_TASK], %g4
 		done
 		nop
 		nop
diff -Nru a/arch/sparc64/kernel/head.S b/arch/sparc64/kernel/head.S
--- a/arch/sparc64/kernel/head.S	2004-10-18 14:56:28 -07:00
+++ b/arch/sparc64/kernel/head.S	2004-10-18 14:56:28 -07:00
@@ -50,6 +50,7 @@
  */
         .global root_flags, ram_flags, root_dev
         .global sparc_ramdisk_image, sparc_ramdisk_size
+	.global sparc_ramdisk_image64
 
         .ascii  "HdrS"
         .word   LINUX_VERSION_CODE
@@ -60,7 +61,7 @@
 	 * 0x0202 : Supports kernel params string
 	 * 0x0201 : Supports reboot_command
 	 */
-	.half   0x0300          /* HdrS version */
+	.half   0x0301          /* HdrS version */
 
 root_flags:
         .half   1
@@ -74,6 +75,8 @@
         .word   0
         .xword  reboot_command
 	.xword	bootstr_info
+sparc_ramdisk_image64:
+	.xword	0
 	.word	_end
 
 	/* We must be careful, 32-bit OpenBOOT will get confused if it
diff -Nru a/arch/sparc64/kernel/irq.c b/arch/sparc64/kernel/irq.c
--- a/arch/sparc64/kernel/irq.c	2004-10-18 14:57:03 -07:00
+++ b/arch/sparc64/kernel/irq.c	2004-10-18 14:57:03 -07:00
@@ -33,7 +33,6 @@
 #include <asm/oplib.h>
 #include <asm/timer.h>
 #include <asm/smp.h>
-#include <asm/hardirq.h>
 #include <asm/starfire.h>
 #include <asm/uaccess.h>
 #include <asm/cache.h>
@@ -791,16 +790,24 @@
 #endif
 			if ((flags & IBF_MULTI) == 0) {
 				struct irqaction *ap = bp->irq_info;
-				ap->handler(__irq(bp), ap->dev_id, regs);
-				random |= ap->flags & SA_SAMPLE_RANDOM;
+				int ret;
+
+				ret = ap->handler(__irq(bp), ap->dev_id, regs);
+				if (ret == IRQ_HANDLED)
+					random |= ap->flags;
 			} else {
 				void **vector = (void **)bp->irq_info;
 				int ent;
 				for (ent = 0; ent < 4; ent++) {
 					struct irqaction *ap = vector[ent];
 					if (ap != NULL) {
-						ap->handler(__irq(bp), ap->dev_id, regs);
-						random |= ap->flags & SA_SAMPLE_RANDOM;
+						int ret;
+
+						ret = ap->handler(__irq(bp),
+								  ap->dev_id,
+								  regs);
+						if (ret == IRQ_HANDLED)
+							random |= ap->flags;
 					}
 				}
 			}
@@ -813,8 +820,9 @@
 				}
 #endif
 				upa_writel(ICLR_IDLE, bp->iclr);
+
 				/* Test and add entropy */
-				if (random)
+				if (random & SA_SAMPLE_RANDOM)
 					add_interrupt_randomness(irq);
 			}
 		} else
diff -Nru a/arch/sparc64/kernel/kprobes.c b/arch/sparc64/kernel/kprobes.c
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/arch/sparc64/kernel/kprobes.c	2004-10-18 14:57:24 -07:00
@@ -0,0 +1,373 @@
+/* arch/sparc64/kernel/kprobes.c
+ *
+ * Copyright (C) 2004 David S. Miller <davem@davemloft.net>
+ */
+
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/kprobes.h>
+
+#include <asm/kdebug.h>
+#include <asm/signal.h>
+
+/* We do not have hardware single-stepping on sparc64.
+ * So we implement software single-stepping with breakpoint
+ * traps.  The top-level scheme is similar to that used
+ * in the x86 kprobes implementation.
+ *
+ * In the kprobe->insn[] array we store the original
+ * instruction at index zero and a break instruction at
+ * index one.
+ *
+ * When we hit a kprobe we:
+ * - Run the pre-handler
+ * - Remember "regs->tnpc" and interrupt level stored in
+ *   "regs->tstate" so we can restore them later
+ * - Disable PIL interrupts
+ * - Set regs->tpc to point to kprobe->insn[0]
+ * - Set regs->tnpc to point to kprobe->insn[1]
+ * - Mark that we are actively in a kprobe
+ *
+ * At this point we wait for the second breakpoint at
+ * kprobe->insn[1] to hit.  When it does we:
+ * - Run the post-handler
+ * - Set regs->tpc to "remembered" regs->tnpc stored above,
+ *   restore the PIL interrupt level in "regs->tstate" as well
+ * - Make any adjustments necessary to regs->tnpc in order
+ *   to handle relative branches correctly.  See below.
+ * - Mark that we are no longer actively in a kprobe.
+ */
+
+void arch_prepare_kprobe(struct kprobe *p)
+{
+	p->insn[0] = *p->addr;
+	p->insn[1] = BREAKPOINT_INSTRUCTION_2;
+}
+
+/* kprobe_status settings */
+#define KPROBE_HIT_ACTIVE	0x00000001
+#define KPROBE_HIT_SS		0x00000002
+
+static struct kprobe *current_kprobe;
+static unsigned long current_kprobe_orig_tnpc;
+static unsigned long current_kprobe_orig_tstate_pil;
+static unsigned int kprobe_status;
+
+static inline void prepare_singlestep(struct kprobe *p, struct pt_regs *regs)
+{
+	current_kprobe_orig_tnpc = regs->tnpc;
+	current_kprobe_orig_tstate_pil = (regs->tstate & TSTATE_PIL);
+	regs->tstate |= TSTATE_PIL;
+
+	regs->tpc = (unsigned long) &p->insn[0];
+	regs->tnpc = (unsigned long) &p->insn[1];
+}
+
+static inline void disarm_kprobe(struct kprobe *p, struct pt_regs *regs)
+{
+	*p->addr = p->opcode;
+	flushi(p->addr);
+
+	regs->tpc = (unsigned long) p->addr;
+	regs->tnpc = current_kprobe_orig_tnpc;
+	regs->tstate = ((regs->tstate & ~TSTATE_PIL) |
+			current_kprobe_orig_tstate_pil);
+}
+
+static int kprobe_handler(struct pt_regs *regs)
+{
+	struct kprobe *p;
+	void *addr = (void *) regs->tpc;
+	int ret = 0;
+
+	preempt_disable();
+
+	if (kprobe_running()) {
+		/* We *are* holding lock here, so this is safe.
+		 * Disarm the probe we just hit, and ignore it.
+		 */
+		p = get_kprobe(addr);
+		if (p) {
+			disarm_kprobe(p, regs);
+			ret = 1;
+		} else {
+			p = current_kprobe;
+			if (p->break_handler && p->break_handler(p, regs))
+				goto ss_probe;
+		}
+		/* If it's not ours, can't be delete race, (we hold lock). */
+		goto no_kprobe;
+	}
+
+	lock_kprobes();
+	p = get_kprobe(addr);
+	if (!p) {
+		unlock_kprobes();
+		if (*(u32 *)addr != BREAKPOINT_INSTRUCTION) {
+			/*
+			 * The breakpoint instruction was removed right
+			 * after we hit it.  Another cpu has removed
+			 * either a probepoint or a debugger breakpoint
+			 * at this address.  In either case, no further
+			 * handling of this interrupt is appropriate.
+			 */
+			ret = 1;
+		}
+		/* Not one of ours: let kernel handle it */
+		goto no_kprobe;
+	}
+
+	kprobe_status = KPROBE_HIT_ACTIVE;
+	current_kprobe = p;
+	if (p->pre_handler(p, regs))
+		return 1;
+
+ss_probe:
+	prepare_singlestep(p, regs);
+	kprobe_status = KPROBE_HIT_SS;
+	return 1;
+
+no_kprobe:
+	preempt_enable_no_resched();
+	return ret;
+}
+
+/* If INSN is a relative control transfer instruction,
+ * return the corrected branch destination value.
+ *
+ * The original INSN location was REAL_PC, it actually
+ * executed at PC and produced destination address NPC.
+ */
+static unsigned long relbranch_fixup(u32 insn, unsigned long real_pc,
+				     unsigned long pc, unsigned long npc)
+{
+	/* Branch not taken, no mods necessary.  */
+	if (npc == pc + 0x4UL)
+		return real_pc + 0x4UL;
+
+	/* The three cases are call, branch w/prediction,
+	 * and traditional branch.
+	 */
+	if ((insn & 0xc0000000) == 0x40000000 ||
+	    (insn & 0xc1c00000) == 0x00400000 ||
+	    (insn & 0xc1c00000) == 0x00800000) {
+		/* The instruction did all the work for us
+		 * already, just apply the offset to the correct
+		 * instruction location.
+		 */
+		return (real_pc + (npc - pc));
+	}
+
+	return real_pc + 0x4UL;
+}
+
+/* If INSN is an instruction which writes it's PC location
+ * into a destination register, fix that up.
+ */
+static void retpc_fixup(struct pt_regs *regs, u32 insn, unsigned long real_pc)
+{
+	unsigned long *slot = NULL;
+
+	/* Simplest cast is call, which always uses %o7 */
+	if ((insn & 0xc0000000) == 0x40000000) {
+		slot = &regs->u_regs[UREG_I7];
+	}
+
+	/* Jmpl encodes the register inside of the opcode */
+	if ((insn & 0xc1f80000) == 0x81c00000) {
+		unsigned long rd = ((insn >> 25) & 0x1f);
+
+		if (rd <= 15) {
+			slot = &regs->u_regs[rd];
+		} else {
+			/* Hard case, it goes onto the stack. */
+			flushw_all();
+
+			rd -= 16;
+			slot = (unsigned long *)
+				(regs->u_regs[UREG_FP] + STACK_BIAS);
+			slot += rd;
+		}
+	}
+	if (slot != NULL)
+		*slot = real_pc;
+}
+
+/*
+ * Called after single-stepping.  p->addr is the address of the
+ * instruction whose first byte has been replaced by the breakpoint
+ * instruction.  To avoid the SMP problems that can occur when we
+ * temporarily put back the original opcode to single-step, we
+ * single-stepped a copy of the instruction.  The address of this
+ * copy is p->insn.
+ *
+ * This function prepares to return from the post-single-step
+ * breakpoint trap.
+ */
+static void resume_execution(struct kprobe *p, struct pt_regs *regs)
+{
+	u32 insn = p->insn[0];
+
+	regs->tpc = current_kprobe_orig_tnpc;
+	regs->tnpc = relbranch_fixup(insn,
+				     (unsigned long) p->addr,
+				     (unsigned long) &p->insn[0],
+				     regs->tnpc);
+	retpc_fixup(regs, insn, (unsigned long) p->addr);
+
+	regs->tstate = ((regs->tstate & ~TSTATE_PIL) |
+			current_kprobe_orig_tstate_pil);
+}
+
+static inline int post_kprobe_handler(struct pt_regs *regs)
+{
+	if (!kprobe_running())
+		return 0;
+
+	if (current_kprobe->post_handler)
+		current_kprobe->post_handler(current_kprobe, regs, 0);
+
+	resume_execution(current_kprobe, regs);
+
+	unlock_kprobes();
+	preempt_enable_no_resched();
+
+	return 1;
+}
+
+/* Interrupts disabled, kprobe_lock held. */
+static inline int kprobe_fault_handler(struct pt_regs *regs, int trapnr)
+{
+	if (current_kprobe->fault_handler
+	    && current_kprobe->fault_handler(current_kprobe, regs, trapnr))
+		return 1;
+
+	if (kprobe_status & KPROBE_HIT_SS) {
+		resume_execution(current_kprobe, regs);
+
+		unlock_kprobes();
+		preempt_enable_no_resched();
+	}
+	return 0;
+}
+
+/*
+ * Wrapper routine to for handling exceptions.
+ */
+int kprobe_exceptions_notify(struct notifier_block *self, unsigned long val,
+			     void *data)
+{
+	struct die_args *args = (struct die_args *)data;
+	switch (val) {
+	case DIE_DEBUG:
+		if (kprobe_handler(args->regs))
+			return NOTIFY_STOP;
+		break;
+	case DIE_DEBUG_2:
+		if (post_kprobe_handler(args->regs))
+			return NOTIFY_STOP;
+		break;
+	case DIE_GPF:
+		if (kprobe_running() &&
+		    kprobe_fault_handler(args->regs, args->trapnr))
+			return NOTIFY_STOP;
+		break;
+	case DIE_PAGE_FAULT:
+		if (kprobe_running() &&
+		    kprobe_fault_handler(args->regs, args->trapnr))
+			return NOTIFY_STOP;
+		break;
+	default:
+		break;
+	}
+	return NOTIFY_DONE;
+}
+
+asmlinkage void kprobe_trap(unsigned long trap_level, struct pt_regs *regs)
+{
+	BUG_ON(trap_level != 0x170 && trap_level != 0x171);
+
+	if (user_mode(regs)) {
+		local_irq_enable();
+		bad_trap(regs, trap_level);
+		return;
+	}
+
+	/* trap_level == 0x170 --> ta 0x70
+	 * trap_level == 0x171 --> ta 0x71
+	 */
+	if (notify_die((trap_level == 0x170) ? DIE_DEBUG : DIE_DEBUG_2,
+		       (trap_level == 0x170) ? "debug" : "debug_2",
+		       regs, 0, trap_level, SIGTRAP) != NOTIFY_STOP)
+		bad_trap(regs, trap_level);
+}
+
+/* Jprobes support.  */
+static struct pt_regs jprobe_saved_regs;
+static struct pt_regs *jprobe_saved_regs_location;
+static struct sparc_stackf jprobe_saved_stack;
+
+int setjmp_pre_handler(struct kprobe *p, struct pt_regs *regs)
+{
+	struct jprobe *jp = container_of(p, struct jprobe, kp);
+
+	jprobe_saved_regs_location = regs;
+	memcpy(&jprobe_saved_regs, regs, sizeof(*regs));
+
+	/* Save a whole stack frame, this gets arguments
+	 * pushed onto the stack after using up all the
+	 * arg registers.
+	 */
+	memcpy(&jprobe_saved_stack,
+	       (char *) (regs->u_regs[UREG_FP] + STACK_BIAS),
+	       sizeof(jprobe_saved_stack));
+
+	regs->tpc  = (unsigned long) jp->entry;
+	regs->tnpc = ((unsigned long) jp->entry) + 0x4UL;
+	regs->tstate |= TSTATE_PIL;
+
+	return 1;
+}
+
+void jprobe_return(void)
+{
+	preempt_enable_no_resched();
+	__asm__ __volatile__(
+		".globl	jprobe_return_trap_instruction\n"
+"jprobe_return_trap_instruction:\n\t"
+		"ta 0x70");
+}
+
+extern void jprobe_return_trap_instruction(void);
+
+extern void __show_regs(struct pt_regs * regs);
+
+int longjmp_break_handler(struct kprobe *p, struct pt_regs *regs)
+{
+	u32 *addr = (u32 *) regs->tpc;
+
+	if (addr == (u32 *) jprobe_return_trap_instruction) {
+		if (jprobe_saved_regs_location != regs) {
+			printk("JPROBE: Current regs (%p) does not match "
+			       "saved regs (%p).\n",
+			       regs, jprobe_saved_regs_location);
+			printk("JPROBE: Saved registers\n");
+			__show_regs(jprobe_saved_regs_location);
+			printk("JPROBE: Current registers\n");
+			__show_regs(regs);
+			BUG();
+		}
+		/* Restore old register state.  Do pt_regs
+		 * first so that UREG_FP is the original one for
+		 * the stack frame restore.
+		 */
+		memcpy(regs, &jprobe_saved_regs, sizeof(*regs));
+
+		memcpy((char *) (regs->u_regs[UREG_FP] + STACK_BIAS),
+		       &jprobe_saved_stack,
+		       sizeof(jprobe_saved_stack));
+
+		return 1;
+	}
+	return 0;
+}
diff -Nru a/arch/sparc64/kernel/pci.c b/arch/sparc64/kernel/pci.c
--- a/arch/sparc64/kernel/pci.c	2004-10-18 14:55:46 -07:00
+++ b/arch/sparc64/kernel/pci.c	2004-10-18 14:55:46 -07:00
@@ -41,7 +41,6 @@
 #else
 
 /* List of all PCI controllers found in the system. */
-spinlock_t pci_controller_lock = SPIN_LOCK_UNLOCKED;
 struct pci_controller_info *pci_controller_root = NULL;
 
 /* Each PCI controller found gets a unique index. */
@@ -298,12 +297,9 @@
 static void __init pci_scan_each_controller_bus(void)
 {
 	struct pci_controller_info *p;
-	unsigned long flags;
 
-	spin_lock_irqsave(&pci_controller_lock, flags);
 	for (p = pci_controller_root; p; p = p->next)
 		p->scan_bus(p);
-	spin_unlock_irqrestore(&pci_controller_lock, flags);
 }
 
 /* Reorder the pci_dev chain, so that onboard devices come first
@@ -350,10 +346,6 @@
 }
 
 subsys_initcall(pcibios_init);
-
-struct pci_fixup pcibios_fixups[] = {
-	{ 0 }
-};
 
 void pcibios_fixup_bus(struct pci_bus *pbus)
 {
diff -Nru a/arch/sparc64/kernel/pci_common.c b/arch/sparc64/kernel/pci_common.c
--- a/arch/sparc64/kernel/pci_common.c	2004-10-18 14:56:21 -07:00
+++ b/arch/sparc64/kernel/pci_common.c	2004-10-18 14:56:21 -07:00
@@ -15,18 +15,13 @@
  */
 void __init pci_fixup_host_bridge_self(struct pci_bus *pbus)
 {
-	struct list_head *walk = &pbus->devices;
-
-	walk = walk->next;
-	while (walk != &pbus->devices) {
-		struct pci_dev *pdev = pci_dev_b(walk);
+	struct pci_dev *pdev;
 
+	list_for_each_entry(pdev, &pbus->devices, bus_list) {
 		if (pdev->class >> 8 == PCI_CLASS_BRIDGE_HOST) {
 			pbus->self = pdev;
 			return;
 		}
-
-		walk = walk->next;
 	}
 
 	prom_printf("PCI: Critical error, cannot find host bridge PDEV.\n");
@@ -217,31 +212,18 @@
 				    struct pci_pbm_info *pbm,
 				    int prom_node)
 {
-	struct list_head *walk = &pbus->devices;
-
-	/* This loop is coded like this because the cookie
-	 * fillin routine can delete devices from the tree.
-	 */
-	walk = walk->next;
-	while (walk != &pbus->devices) {
-		struct pci_dev *pdev = pci_dev_b(walk);
-		struct list_head *walk_next = walk->next;
+	struct pci_dev *pdev, *pdev_next;
+	struct pci_bus *this_pbus, *pbus_next;
 
+	/* This must be _safe because the cookie fillin
+	   routine can delete devices from the tree.  */
+	list_for_each_entry_safe(pdev, pdev_next, &pbus->devices, bus_list)
 		pdev_cookie_fillin(pbm, pdev, prom_node);
 
-		walk = walk_next;
-	}
-
-	walk = &pbus->children;
-	walk = walk->next;
-	while (walk != &pbus->children) {
-		struct pci_bus *this_pbus = pci_bus_b(walk);
+	list_for_each_entry_safe(this_pbus, pbus_next, &pbus->children, node) {
 		struct pcidev_cookie *pcp = this_pbus->self->sysdata;
-		struct list_head *walk_next = walk->next;
 
 		pci_fill_in_pbm_cookies(this_pbus, pbm, pcp->prom_node);
-
-		walk = walk_next;
 	}
 }
 
@@ -431,14 +413,14 @@
 void __init pci_record_assignments(struct pci_pbm_info *pbm,
 				   struct pci_bus *pbus)
 {
-	struct list_head *walk = &pbus->devices;
+	struct pci_dev *dev;
+	struct pci_bus *bus;
 
-	for (walk = walk->next; walk != &pbus->devices; walk = walk->next)
-		pdev_record_assignments(pbm, pci_dev_b(walk));
+	list_for_each_entry(dev, &pbus->devices, bus_list)
+		pdev_record_assignments(pbm, dev);
 
-	walk = &pbus->children;
-	for (walk = walk->next; walk != &pbus->children; walk = walk->next)
-		pci_record_assignments(pbm, pci_bus_b(walk));
+	list_for_each_entry(bus, &pbus->children, node)
+		pci_record_assignments(pbm, bus);
 }
 
 /* Return non-zero if PDEV has implicit I/O resources even
@@ -549,14 +531,14 @@
 void __init pci_assign_unassigned(struct pci_pbm_info *pbm,
 				  struct pci_bus *pbus)
 {
-	struct list_head *walk = &pbus->devices;
+	struct pci_dev *dev;
+	struct pci_bus *bus;
 
-	for (walk = walk->next; walk != &pbus->devices; walk = walk->next)
-		pdev_assign_unassigned(pbm, pci_dev_b(walk));
+	list_for_each_entry(dev, &pbus->devices, bus_list)
+		pdev_assign_unassigned(pbm, dev);
 
-	walk = &pbus->children;
-	for (walk = walk->next; walk != &pbus->children; walk = walk->next)
-		pci_assign_unassigned(pbm, pci_bus_b(walk));
+	list_for_each_entry(bus, &pbus->children, node)
+		pci_assign_unassigned(pbm, bus);
 }
 
 static int __init pci_intmap_match(struct pci_dev *pdev, unsigned int *interrupt)
@@ -797,14 +779,14 @@
 void __init pci_fixup_irq(struct pci_pbm_info *pbm,
 			  struct pci_bus *pbus)
 {
-	struct list_head *walk = &pbus->devices;
+	struct pci_dev *dev;
+	struct pci_bus *bus;
 
-	for (walk = walk->next; walk != &pbus->devices; walk = walk->next)
-		pdev_fixup_irq(pci_dev_b(walk));
+	list_for_each_entry(dev, &pbus->devices, bus_list)
+		pdev_fixup_irq(dev);
 
-	walk = &pbus->children;
-	for (walk = walk->next; walk != &pbus->children; walk = walk->next)
-		pci_fixup_irq(pbm, pci_bus_b(walk));
+	list_for_each_entry(bus, &pbus->children, node)
+		pci_fixup_irq(pbm, bus);
 }
 
 static void pdev_setup_busmastering(struct pci_dev *pdev, int is_66mhz)
@@ -897,7 +879,7 @@
 void pci_determine_66mhz_disposition(struct pci_pbm_info *pbm,
 				     struct pci_bus *pbus)
 {
-	struct list_head *walk;
+	struct pci_dev *pdev;
 	int all_are_66mhz;
 	u16 status;
 
@@ -906,11 +888,8 @@
 		goto out;
 	}
 
-	walk = &pbus->devices;
 	all_are_66mhz = 1;
-	for (walk = walk->next; walk != &pbus->devices; walk = walk->next) {
-		struct pci_dev *pdev = pci_dev_b(walk);
-
+	list_for_each_entry(pdev, &pbus->devices, bus_list) {
 		pci_read_config_word(pdev, PCI_STATUS, &status);
 		if (!(status & PCI_STATUS_66MHZ)) {
 			all_are_66mhz = 0;
@@ -929,17 +908,17 @@
 void pci_setup_busmastering(struct pci_pbm_info *pbm,
 			    struct pci_bus *pbus)
 {
-	struct list_head *walk = &pbus->devices;
+	struct pci_dev *dev;
+	struct pci_bus *bus;
 	int is_66mhz;
 
 	is_66mhz = pbm->is_66mhz_capable && pbm->all_devs_66mhz;
 
-	for (walk = walk->next; walk != &pbus->devices; walk = walk->next)
-		pdev_setup_busmastering(pci_dev_b(walk), is_66mhz);
+	list_for_each_entry(dev, &pbus->devices, bus_list)
+		pdev_setup_busmastering(dev, is_66mhz);
 
-	walk = &pbus->children;
-	for (walk = walk->next; walk != &pbus->children; walk = walk->next)
-		pci_setup_busmastering(pbm, pci_bus_b(walk));
+	list_for_each_entry(bus, &pbus->children, node)
+		pci_setup_busmastering(pbm, bus);
 }
 
 void pci_register_legacy_regions(struct resource *io_res,
@@ -987,10 +966,10 @@
 			       struct pci_pbm_info *pbm,
 			       struct pci_bus *pbus)
 {
-	struct list_head *walk = &pbus->devices;
+	struct pci_dev *pdev;
+	struct pci_bus *bus;
 
-	for (walk = walk->next; walk != &pbus->devices; walk = walk->next) {
-		struct pci_dev *pdev = pci_dev_b(walk);
+	list_for_each_entry(pdev, &pbus->devices, bus_list) {
 		u16 status, error_bits;
 
 		pci_read_config_word(pdev, PCI_STATUS, &status);
@@ -1005,19 +984,18 @@
 		}
 	}
 
-	walk = &pbus->children;
-	for (walk = walk->next; walk != &pbus->children; walk = walk->next)
-		pci_scan_for_target_abort(p, pbm, pci_bus_b(walk));
+	list_for_each_entry(bus, &pbus->children, node)
+		pci_scan_for_target_abort(p, pbm, bus);
 }
 
 void pci_scan_for_master_abort(struct pci_controller_info *p,
 			       struct pci_pbm_info *pbm,
 			       struct pci_bus *pbus)
 {
-	struct list_head *walk = &pbus->devices;
+	struct pci_dev *pdev;
+	struct pci_bus *bus;
 
-	for (walk = walk->next; walk != &pbus->devices; walk = walk->next) {
-		struct pci_dev *pdev = pci_dev_b(walk);
+	list_for_each_entry(pdev, &pbus->devices, bus_list) {
 		u16 status, error_bits;
 
 		pci_read_config_word(pdev, PCI_STATUS, &status);
@@ -1031,19 +1009,18 @@
 		}
 	}
 
-	walk = &pbus->children;
-	for (walk = walk->next; walk != &pbus->children; walk = walk->next)
-		pci_scan_for_master_abort(p, pbm, pci_bus_b(walk));
+	list_for_each_entry(bus, &pbus->children, node)
+		pci_scan_for_master_abort(p, pbm, bus);
 }
 
 void pci_scan_for_parity_error(struct pci_controller_info *p,
 			       struct pci_pbm_info *pbm,
 			       struct pci_bus *pbus)
 {
-	struct list_head *walk = &pbus->devices;
+	struct pci_dev *pdev;
+	struct pci_bus *bus;
 
-	for (walk = walk->next; walk != &pbus->devices; walk = walk->next) {
-		struct pci_dev *pdev = pci_dev_b(walk);
+	list_for_each_entry(pdev, &pbus->devices, bus_list) {
 		u16 status, error_bits;
 
 		pci_read_config_word(pdev, PCI_STATUS, &status);
@@ -1058,7 +1035,6 @@
 		}
 	}
 
-	walk = &pbus->children;
-	for (walk = walk->next; walk != &pbus->children; walk = walk->next)
-		pci_scan_for_parity_error(p, pbm, pci_bus_b(walk));
+	list_for_each_entry(bus, &pbus->children, node)
+		pci_scan_for_parity_error(p, pbm, bus);
 }
diff -Nru a/arch/sparc64/kernel/pci_impl.h b/arch/sparc64/kernel/pci_impl.h
--- a/arch/sparc64/kernel/pci_impl.h	2004-10-18 14:56:32 -07:00
+++ b/arch/sparc64/kernel/pci_impl.h	2004-10-18 14:56:32 -07:00
@@ -11,7 +11,6 @@
 #include <linux/spinlock.h>
 #include <asm/io.h>
 
-extern spinlock_t pci_controller_lock;
 extern struct pci_controller_info *pci_controller_root;
 
 extern int pci_num_controllers;
diff -Nru a/arch/sparc64/kernel/pci_iommu.c b/arch/sparc64/kernel/pci_iommu.c
--- a/arch/sparc64/kernel/pci_iommu.c	2004-10-18 14:55:55 -07:00
+++ b/arch/sparc64/kernel/pci_iommu.c	2004-10-18 14:55:55 -07:00
@@ -56,6 +56,39 @@
 	}
 }
 
+#define IOPTE_CONSISTENT(CTX) \
+	(IOPTE_VALID | IOPTE_CACHE | \
+	 (((CTX) << 47) & IOPTE_CONTEXT))
+
+#define IOPTE_STREAMING(CTX) \
+	(IOPTE_CONSISTENT(CTX) | IOPTE_STBUF)
+
+/* Existing mappings are never marked invalid, instead they
+ * are pointed to a dummy page.
+ */
+#define IOPTE_IS_DUMMY(iommu, iopte)	\
+	((iopte_val(*iopte) & IOPTE_PAGE) == (iommu)->dummy_page_pa)
+
+static void inline iopte_make_dummy(struct pci_iommu *iommu, iopte_t *iopte)
+{
+	unsigned long val = iopte_val(*iopte);
+
+	val &= ~IOPTE_PAGE;
+	val |= iommu->dummy_page_pa;
+
+	iopte_val(*iopte) = val;
+}
+
+void pci_iommu_table_init(struct pci_iommu *iommu, int tsbsize)
+{
+	int i;
+
+	tsbsize /= sizeof(iopte_t);
+
+	for (i = 0; i < tsbsize; i++)
+		iopte_make_dummy(iommu, &iommu->page_table[i]);
+}
+
 static iopte_t *alloc_streaming_cluster(struct pci_iommu *iommu, unsigned long npages)
 {
 	iopte_t *iopte, *limit, *first;
@@ -79,7 +112,7 @@
 	
 	first = iopte;
 	for (;;) {
-		if (iopte_val(*iopte) == 0UL) {
+		if (IOPTE_IS_DUMMY(iommu, iopte)) {
 			if ((iopte + (1 << cnum)) >= limit)
 				ent = 0;
 			else
@@ -142,12 +175,12 @@
 	iopte = iommu->page_table + (1 << (iommu->page_table_sz_bits - PBM_LOGCLUSTERS));
 	while (iopte > iommu->page_table) {
 		iopte--;
-		if (!(iopte_val(*iopte) & IOPTE_VALID)) {
+		if (IOPTE_IS_DUMMY(iommu, iopte)) {
 			unsigned long tmp = npages;
 
 			while (--tmp) {
 				iopte--;
-				if (iopte_val(*iopte) & IOPTE_VALID)
+				if (!IOPTE_IS_DUMMY(iommu, iopte))
 					break;
 			}
 			if (tmp == 0) {
@@ -162,15 +195,6 @@
 	return NULL;
 }
 
-#define IOPTE_CONSISTENT(CTX) \
-	(IOPTE_VALID | IOPTE_CACHE | \
-	 (((CTX) << 47) & IOPTE_CONTEXT))
-
-#define IOPTE_STREAMING(CTX) \
-	(IOPTE_CONSISTENT(CTX) | IOPTE_STBUF)
-
-#define IOPTE_INVALID	0UL
-
 /* Allocate and map kernel buffer of size SIZE using consistent mode
  * DMA for PCI device PDEV.  Return non-NULL cpu-side address if
  * successful and set *DMA_ADDRP to the PCI side dma address.
@@ -261,7 +285,7 @@
 		limit = (iommu->page_table +
 			 (1 << (iommu->page_table_sz_bits - PBM_LOGCLUSTERS)));
 		while (walk < limit) {
-			if (iopte_val(*walk) != IOPTE_INVALID)
+			if (!IOPTE_IS_DUMMY(iommu, walk))
 				break;
 			walk++;
 		}
@@ -280,7 +304,7 @@
 		ctx = (iopte_val(*iopte) & IOPTE_CONTEXT) >> 47UL;
 
 	for (i = 0; i < npages; i++, iopte++)
-		iopte_val(*iopte) = IOPTE_INVALID;
+		iopte_make_dummy(iommu, iopte);
 
 	if (iommu->iommu_ctxflush) {
 		pci_iommu_write(iommu->iommu_ctxflush, ctx);
@@ -376,7 +400,7 @@
 	base = iommu->page_table +
 		((bus_addr - iommu->page_table_map_base) >> IO_PAGE_SHIFT);
 #ifdef DEBUG_PCI_IOMMU
-	if (iopte_val(*base) == IOPTE_INVALID)
+	if (IOPTE_IS_DUMMY(iommu, base))
 		printk("pci_unmap_single called on non-mapped region %08x,%08x from %016lx\n",
 		       bus_addr, sz, __builtin_return_address(0));
 #endif
@@ -415,7 +439,7 @@
 	}
 
 	/* Step 2: Clear out first TSB entry. */
-	iopte_val(*base) = IOPTE_INVALID;
+	iopte_make_dummy(iommu, base);
 
 	free_streaming_cluster(iommu, bus_addr - iommu->page_table_map_base,
 			       npages, ctx);
@@ -611,7 +635,7 @@
 		((bus_addr - iommu->page_table_map_base) >> IO_PAGE_SHIFT);
 
 #ifdef DEBUG_PCI_IOMMU
-	if (iopte_val(*base) == IOPTE_INVALID)
+	if (IOPTE_IS_DUMMY(iommu, base))
 		printk("pci_unmap_sg called on non-mapped region %016lx,%d from %016lx\n", sglist->dma_address, nelems, __builtin_return_address(0));
 #endif
 
@@ -648,7 +672,7 @@
 	}
 
 	/* Step 2: Clear out first TSB entry. */
-	iopte_val(*base) = IOPTE_INVALID;
+	iopte_make_dummy(iommu, base);
 
 	free_streaming_cluster(iommu, bus_addr - iommu->page_table_map_base,
 			       npages, ctx);
diff -Nru a/arch/sparc64/kernel/pci_psycho.c b/arch/sparc64/kernel/pci_psycho.c
--- a/arch/sparc64/kernel/pci_psycho.c	2004-10-18 14:56:33 -07:00
+++ b/arch/sparc64/kernel/pci_psycho.c	2004-10-18 14:56:33 -07:00
@@ -1076,17 +1076,17 @@
 	 * bits for each PBM.
 	 */
 	tmp = psycho_read(base + PSYCHO_PCIA_CTRL);
-	tmp |= (PSYCHO_PCICTRL_SBH_ERR |
-		PSYCHO_PCICTRL_SERR |
-		PSYCHO_PCICTRL_SBH_INT |
+	tmp |= (PSYCHO_PCICTRL_SERR |
+		PSYCHO_PCICTRL_SBH_ERR |
 		PSYCHO_PCICTRL_EEN);
+	tmp &= ~(PSYCHO_PCICTRL_SBH_INT);
 	psycho_write(base + PSYCHO_PCIA_CTRL, tmp);
 		     
 	tmp = psycho_read(base + PSYCHO_PCIB_CTRL);
-	tmp |= (PSYCHO_PCICTRL_SBH_ERR |
-		PSYCHO_PCICTRL_SERR |
-		PSYCHO_PCICTRL_SBH_INT |
+	tmp |= (PSYCHO_PCICTRL_SERR |
+		PSYCHO_PCICTRL_SBH_ERR |
 		PSYCHO_PCICTRL_EEN);
+	tmp &= ~(PSYCHO_PCICTRL_SBH_INT);
 	psycho_write(base + PSYCHO_PCIB_CTRL, tmp);
 }
 
@@ -1241,6 +1241,14 @@
 	 * in pci_iommu.c
 	 */
 
+	iommu->dummy_page = __get_free_pages(GFP_KERNEL, 0);
+	if (!iommu->dummy_page) {
+		prom_printf("PSYCHO_IOMMU: Error, gfp(dummy_page) failed.\n");
+		prom_halt();
+	}
+	memset((void *)iommu->dummy_page, 0, PAGE_SIZE);
+	iommu->dummy_page_pa = (unsigned long) __pa(iommu->dummy_page);
+
 	/* Using assumed page size 8K with 128K entries we need 1MB iommu page
 	 * table (128K ioptes * 8 bytes per iopte).  This is
 	 * page order 7 on UltraSparc.
@@ -1254,7 +1262,7 @@
 	iommu->page_table_sz_bits = 17;
 	iommu->page_table_map_base = 0xc0000000;
 	iommu->dma_addr_mask = 0xffffffff;
-	memset((char *)tsbbase, 0, IO_TSB_SIZE);
+	pci_iommu_table_init(iommu, IO_TSB_SIZE);
 
 	/* We start with no consistent mappings. */
 	iommu->lowest_consistent_map =
@@ -1479,22 +1487,18 @@
 	struct linux_prom64_registers pr_regs[3];
 	struct pci_controller_info *p;
 	struct pci_iommu *iommu;
-	unsigned long flags;
 	u32 upa_portid;
 	int is_pbm_a, err;
 
 	upa_portid = prom_getintdefault(node, "upa-portid", 0xff);
 
-	spin_lock_irqsave(&pci_controller_lock, flags);
 	for(p = pci_controller_root; p; p = p->next) {
 		if (p->pbm_A.portid == upa_portid) {
-			spin_unlock_irqrestore(&pci_controller_lock, flags);
 			is_pbm_a = (p->pbm_A.prom_node == 0);
 			psycho_pbm_init(p, node, is_pbm_a);
 			return;
 		}
 	}
-	spin_unlock_irqrestore(&pci_controller_lock, flags);
 
 	p = kmalloc(sizeof(struct pci_controller_info), GFP_ATOMIC);
 	if (!p) {
@@ -1510,10 +1514,8 @@
 	memset(iommu, 0, sizeof(*iommu));
 	p->pbm_A.iommu = p->pbm_B.iommu = iommu;
 
-	spin_lock_irqsave(&pci_controller_lock, flags);
 	p->next = pci_controller_root;
 	pci_controller_root = p;
-	spin_unlock_irqrestore(&pci_controller_lock, flags);
 
 	p->pbm_A.portid = upa_portid;
 	p->pbm_B.portid = upa_portid;
diff -Nru a/arch/sparc64/kernel/pci_sabre.c b/arch/sparc64/kernel/pci_sabre.c
--- a/arch/sparc64/kernel/pci_sabre.c	2004-10-18 14:57:04 -07:00
+++ b/arch/sparc64/kernel/pci_sabre.c	2004-10-18 14:57:04 -07:00
@@ -1113,10 +1113,9 @@
 
 static void __init apb_init(struct pci_controller_info *p, struct pci_bus *sabre_bus)
 {
-	struct list_head *walk = &sabre_bus->devices;
+	struct pci_dev *pdev;
 
-	for (walk = walk->next; walk != &sabre_bus->devices; walk = walk->next) {
-		struct pci_dev *pdev = pci_dev_b(walk);
+	list_for_each_entry(pdev, &sabre_bus->devices, bus_list) {
 
 		if (pdev->vendor == PCI_VENDOR_ID_SUN &&
 		    pdev->device == PCI_DEVICE_ID_SUN_SIMBA) {
@@ -1178,10 +1177,9 @@
 static void __init sabre_scan_bus(struct pci_controller_info *p)
 {
 	static int once;
-	struct pci_bus *sabre_bus;
+	struct pci_bus *sabre_bus, *pbus;
 	struct pci_pbm_info *pbm;
 	struct pcidev_cookie *cookie;
-	struct list_head *walk;
 	int sabres_scanned;
 
 	/* The APB bridge speaks to the Sabre host PCI bridge
@@ -1217,9 +1215,7 @@
 
 	sabres_scanned = 0;
 
-	walk = &sabre_bus->children;
-	for (walk = walk->next; walk != &sabre_bus->children; walk = walk->next) {
-		struct pci_bus *pbus = pci_bus_b(walk);
+	list_for_each_entry(pbus, &sabre_bus->children, node) {
 
 		if (pbus->number == p->pbm_A.pci_first_busno) {
 			pbm = &p->pbm_A;
@@ -1293,6 +1289,14 @@
 	 * in pci_iommu.c
 	 */
 
+	iommu->dummy_page = __get_free_pages(GFP_KERNEL, 0);
+	if (!iommu->dummy_page) {
+		prom_printf("PSYCHO_IOMMU: Error, gfp(dummy_page) failed.\n");
+		prom_halt();
+	}
+	memset((void *)iommu->dummy_page, 0, PAGE_SIZE);
+	iommu->dummy_page_pa = (unsigned long) __pa(iommu->dummy_page);
+
 	tsbbase = __get_free_pages(GFP_KERNEL, order = get_order(tsbsize * 1024 * 8));
 	if (!tsbbase) {
 		prom_printf("SABRE_IOMMU: Error, gfp(tsb) failed.\n");
@@ -1301,7 +1305,7 @@
 	iommu->page_table = (iopte_t *)tsbbase;
 	iommu->page_table_map_base = dvma_offset;
 	iommu->dma_addr_mask = dma_mask;
-	memset((char *)tsbbase, 0, PAGE_SIZE << order);
+	pci_iommu_table_init(iommu, PAGE_SIZE << order);
 
 	sabre_write(p->pbm_A.controller_regs + SABRE_IOMMU_TSBBASE, __pa(tsbbase));
 
@@ -1546,7 +1550,6 @@
 	struct linux_prom64_registers pr_regs[2];
 	struct pci_controller_info *p;
 	struct pci_iommu *iommu;
-	unsigned long flags;
 	int tsbsize, err;
 	u32 busrange[2];
 	u32 vdma[2];
@@ -1594,10 +1597,8 @@
 
 	upa_portid = prom_getintdefault(pnode, "upa-portid", 0xff);
 
-	spin_lock_irqsave(&pci_controller_lock, flags);
 	p->next = pci_controller_root;
 	pci_controller_root = p;
-	spin_unlock_irqrestore(&pci_controller_lock, flags);
 
 	p->pbm_A.portid = upa_portid;
 	p->pbm_B.portid = upa_portid;
diff -Nru a/arch/sparc64/kernel/pci_schizo.c b/arch/sparc64/kernel/pci_schizo.c
--- a/arch/sparc64/kernel/pci_schizo.c	2004-10-18 14:56:48 -07:00
+++ b/arch/sparc64/kernel/pci_schizo.c	2004-10-18 14:56:48 -07:00
@@ -1171,7 +1171,7 @@
 		prom_halt();
 	}
 	bucket = __bucket(irq);
-	tmp = readl(bucket->imap);
+	tmp = upa_readl(bucket->imap);
 	upa_writel(tmp, (pbm->pbm_regs +
 			 schizo_imap_offset(SCHIZO_UE_INO) + 4));
 
@@ -1309,7 +1309,7 @@
 		prom_halt();
 	}
 	bucket = __bucket(irq);
-	tmp = readl(bucket->imap);
+	tmp = upa_readl(bucket->imap);
 	upa_writel(tmp, (pbm->pbm_regs + schizo_imap_offset(SCHIZO_UE_INO) + 4));
 
 	pbm = pbm_for_ino(p, SCHIZO_CE_INO);
@@ -1372,10 +1372,10 @@
 		    SCHIZO_PCICTRL_RTRY_ERR |
 		    SCHIZO_PCICTRL_SBH_ERR |
 		    SCHIZO_PCICTRL_SERR |
-		    SCHIZO_PCICTRL_SBH_INT |
 		    SCHIZO_PCICTRL_EEN);
 
-	err_no_mask = SCHIZO_PCICTRL_DTO_ERR;
+	err_no_mask = (SCHIZO_PCICTRL_DTO_ERR |
+		       SCHIZO_PCICTRL_SBH_INT);
 
 	/* Enable PCI Error interrupts and clear error
 	 * bits for each PBM.
@@ -1766,6 +1766,14 @@
 	 * in pci_iommu.c
 	 */
 
+	iommu->dummy_page = __get_free_pages(GFP_KERNEL, 0);
+	if (!iommu->dummy_page) {
+		prom_printf("PSYCHO_IOMMU: Error, gfp(dummy_page) failed.\n");
+		prom_halt();
+	}
+	memset((void *)iommu->dummy_page, 0, PAGE_SIZE);
+	iommu->dummy_page_pa = (unsigned long) __pa(iommu->dummy_page);
+
 	/* Using assumed page size 8K with 128K entries we need 1MB iommu page
 	 * table (128K ioptes * 8 bytes per iopte).  This is
 	 * page order 7 on UltraSparc.
@@ -1780,7 +1788,7 @@
 	iommu->page_table = (iopte_t *)tsbbase;
 	iommu->page_table_map_base = vdma[0];
 	iommu->dma_addr_mask = dma_mask;
-	memset((char *)tsbbase, 0, PAGE_SIZE << order);
+	pci_iommu_table_init(iommu, PAGE_SIZE << order);
 
 	switch (tsbsize) {
 	case 64:
@@ -2073,13 +2081,11 @@
 {
 	struct pci_controller_info *p;
 	struct pci_iommu *iommu;
-	unsigned long flags;
 	int is_pbm_a;
 	u32 portid;
 
 	portid = prom_getintdefault(node, "portid", 0xff);
 
-	spin_lock_irqsave(&pci_controller_lock, flags);
 	for(p = pci_controller_root; p; p = p->next) {
 		struct pci_pbm_info *pbm;
 
@@ -2091,13 +2097,11 @@
 		       &p->pbm_B);
 
 		if (portid_compare(pbm->portid, portid, chip_type)) {
-			spin_unlock_irqrestore(&pci_controller_lock, flags);
 			is_pbm_a = (p->pbm_A.prom_node == 0);
 			schizo_pbm_init(p, node, portid, chip_type);
 			return;
 		}
 	}
-	spin_unlock_irqrestore(&pci_controller_lock, flags);
 
 	p = kmalloc(sizeof(struct pci_controller_info), GFP_ATOMIC);
 	if (!p) {
@@ -2122,10 +2126,8 @@
 	memset(iommu, 0, sizeof(*iommu));
 	p->pbm_B.iommu = iommu;
 
-	spin_lock_irqsave(&pci_controller_lock, flags);
 	p->next = pci_controller_root;
 	pci_controller_root = p;
-	spin_unlock_irqrestore(&pci_controller_lock, flags);
 
 	p->index = pci_num_controllers++;
 	p->pbms_same_domain = 0;
diff -Nru a/arch/sparc64/kernel/power.c b/arch/sparc64/kernel/power.c
--- a/arch/sparc64/kernel/power.c	2004-10-18 14:57:03 -07:00
+++ b/arch/sparc64/kernel/power.c	2004-10-18 14:57:03 -07:00
@@ -27,7 +27,7 @@
 int scons_pwroff = 1; 
 
 #ifdef CONFIG_PCI
-static unsigned long power_reg = 0UL;
+static void __iomem *power_reg;
 
 static DECLARE_WAIT_QUEUE_HEAD(powerd_wait);
 static int button_pressed;
@@ -52,7 +52,7 @@
 {
 	if (!serial_console || scons_pwroff) {
 #ifdef CONFIG_PCI
-		if (power_reg != 0UL) {
+		if (power_reg) {
 			/* Both register bits seem to have the
 			 * same effect, so until I figure out
 			 * what the difference is...
@@ -130,8 +130,8 @@
 	return;
 
 found:
-	power_reg = (unsigned long)ioremap(edev->resource[0].start, 0x4);
-	printk("power: Control reg at %016lx ... ", power_reg);
+	power_reg = ioremap(edev->resource[0].start, 0x4);
+	printk("power: Control reg at %p ... ", power_reg);
 	poweroff_method = machine_halt;  /* able to use the standard halt */
 	if (has_button_interrupt(edev)) {
 		if (kernel_thread(powerd, NULL, CLONE_FS) < 0) {
@@ -141,8 +141,7 @@
 		printk("powerd running.\n");
 
 		if (request_irq(edev->irqs[0],
-				power_handler, SA_SHIRQ, "power",
-				(void *) power_reg) < 0)
+				power_handler, SA_SHIRQ, "power", NULL) < 0)
 			printk("power: Error, cannot register IRQ handler.\n");
 	} else {
 		printk("not using powerd.\n");
diff -Nru a/arch/sparc64/kernel/process.c b/arch/sparc64/kernel/process.c
--- a/arch/sparc64/kernel/process.c	2004-10-18 14:56:29 -07:00
+++ b/arch/sparc64/kernel/process.c	2004-10-18 14:56:29 -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/ptrace.c b/arch/sparc64/kernel/ptrace.c
--- a/arch/sparc64/kernel/ptrace.c	2004-10-18 14:57:04 -07:00
+++ b/arch/sparc64/kernel/ptrace.c	2004-10-18 14:57:04 -07:00
@@ -627,11 +627,8 @@
 		return;
 	if (!(current->ptrace & PT_PTRACED))
 		return;
-	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/sparc64/kernel/setup.c b/arch/sparc64/kernel/setup.c
--- a/arch/sparc64/kernel/setup.c	2004-10-18 14:56:28 -07:00
+++ b/arch/sparc64/kernel/setup.c	2004-10-18 14:56:28 -07:00
@@ -43,7 +43,6 @@
 #include <asm/idprom.h>
 #include <asm/head.h>
 #include <asm/starfire.h>
-#include <asm/hardirq.h>
 #include <asm/mmu_context.h>
 #include <asm/timer.h>
 #include <asm/sections.h>
diff -Nru a/arch/sparc64/kernel/signal.c b/arch/sparc64/kernel/signal.c
--- a/arch/sparc64/kernel/signal.c	2004-10-18 14:56:33 -07:00
+++ b/arch/sparc64/kernel/signal.c	2004-10-18 14:56:33 -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 */
@@ -545,6 +545,12 @@
 	regs->u_regs[UREG_I0] = signo;
 	regs->u_regs[UREG_I1] = (unsigned long) &sf->info;
 
+	/* The sigcontext is passed in this way because of how it
+	 * is defined in GLIBC's /usr/include/bits/sigcontext.h
+	 * for sparc64.  It includes the 128 bytes of siginfo_t.
+	 */
+	regs->u_regs[UREG_I2] = (unsigned long) &sf->info;
+
 	/* 5. signal handler */
 	regs->tpc = (unsigned long) ka->sa.sa_handler;
 	regs->tnpc = (regs->tpc + 4);
@@ -559,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,
@@ -568,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);
@@ -609,6 +613,7 @@
 {
 	siginfo_t info;
 	struct signal_deliver_cookie cookie;
+	struct k_sigaction ka;
 	int signr;
 	
 	cookie.restart_syscall = restart_syscall;
@@ -626,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-10-18 14:55:53 -07:00
+++ b/arch/sparc64/kernel/signal32.c	2004-10-18 14:55:53 -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).
@@ -76,9 +86,61 @@
 	__siginfo_fpu_t		fpu_state;
 };
 
+struct siginfo32 {
+	int si_signo;
+	int si_errno;
+	int si_code;
+
+	union {
+		int _pad[SI_PAD_SIZE32];
+
+		/* kill() */
+		struct {
+			compat_pid_t _pid;		/* sender's pid */
+			unsigned int _uid;		/* sender's uid */
+		} _kill;
+
+		/* POSIX.1b timers */
+		struct {
+			timer_t _tid;			/* timer id */
+			int _overrun;			/* overrun count */
+			sigval_t32 _sigval;		/* same as below */
+			int _sys_private;		/* not to be passed to user */
+		} _timer;
+
+		/* POSIX.1b signals */
+		struct {
+			compat_pid_t _pid;		/* sender's pid */
+			unsigned int _uid;		/* sender's uid */
+			sigval_t32 _sigval;
+		} _rt;
+
+		/* SIGCHLD */
+		struct {
+			compat_pid_t _pid;		/* which child */
+			unsigned int _uid;		/* sender's uid */
+			int _status;			/* exit code */
+			compat_clock_t _utime;
+			compat_clock_t _stime;
+		} _sigchld;
+
+		/* SIGILL, SIGFPE, SIGSEGV, SIGBUS, SIGEMT */
+		struct {
+			u32 _addr; /* faulting insn/memory ref. */
+			int _trapno;
+		} _sigfault;
+
+		/* SIGPOLL */
+		struct {
+			int _band;	/* POLL_IN, POLL_OUT, POLL_MSG */
+			int _fd;
+		} _sigpoll;
+	} _sifields;
+};
+
 struct rt_signal_frame32 {
 	struct sparc_stackf32	ss;
-	siginfo_t32		info;
+	struct siginfo32	info;
 	struct pt_regs32	regs;
 	compat_sigset_t		mask;
 	/* __siginfo_fpu32_t * */ u32 fpu_save;
@@ -95,11 +157,11 @@
 #define NF_ALIGNEDSZ  (((sizeof(struct new_signal_frame32) + 7) & (~7)))
 #define RT_ALIGNEDSZ  (((sizeof(struct rt_signal_frame32) + 7) & (~7)))
 
-int copy_siginfo_to_user32(siginfo_t32 __user *to, siginfo_t *from)
+int copy_siginfo_to_user32(struct siginfo32 __user *to, siginfo_t *from)
 {
 	int err;
 
-	if (!access_ok(VERIFY_WRITE, to, sizeof(siginfo_t32)))
+	if (!access_ok(VERIFY_WRITE, to, sizeof(struct siginfo32)))
 		return -EFAULT;
 
 	/* If you change siginfo_t structure, please be sure
@@ -119,7 +181,7 @@
 		case __SI_TIMER >> 16:
 			err |= __put_user(from->si_tid, &to->si_tid);
 			err |= __put_user(from->si_overrun, &to->si_overrun);
-			err |= __put_user((u32)(u64)from->si_ptr, &to->si_ptr);
+			err |= __put_user(from->si_int, &to->si_int);
 			break;
 		case __SI_CHLD >> 16:
 			err |= __put_user(from->si_utime, &to->si_utime);
@@ -145,6 +207,22 @@
 	return err;
 }
 
+/* CAUTION: This is just a very minimalist implementation for the
+ *          sake of compat_sys_rt_sigqueueinfo()
+ */
+int copy_siginfo_to_kernel32(siginfo_t *to, struct siginfo32 __user *from)
+{
+	if (!access_ok(VERIFY_WRITE, from, sizeof(struct siginfo32)))
+		return -EFAULT;
+
+	if (copy_from_user(to, from, 3*sizeof(int)) ||
+	    copy_from_user(to->_sifields._pad, from->_sifields._pad,
+			   SI_PAD_SIZE))
+		return -EFAULT;
+
+	return 0;
+}
+
 /*
  * atomically swap in the new signal mask, and wait for a signal.
  * This is really tricky on the Sparc, watch out...
@@ -299,8 +377,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 +413,7 @@
 	return;
 
 segv:
-	do_exit(SIGSEGV);
+	force_sig(SIGSEGV, current);
 }
 
 asmlinkage void do_sigreturn32(struct pt_regs *regs)
@@ -400,7 +483,7 @@
 	return;
 
 segv:
-	do_exit(SIGSEGV);
+	force_sig(SIGSEGV, current);
 }
 
 asmlinkage void do_rt_sigreturn32(struct pt_regs *regs)
@@ -447,8 +530,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 +575,7 @@
 	spin_unlock_irq(&current->sighand->siglock);
 	return;
 segv:
-	do_exit(SIGSEGV);
+	force_sig(SIGSEGV, current);
 }
 
 /* Checks if the fp is valid */
@@ -648,7 +736,7 @@
 	return;
 
 sigsegv:
-	do_exit(SIGSEGV);
+	force_sigsegv(signr, current);
 }
 
 
@@ -715,7 +803,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);
@@ -749,6 +840,7 @@
 	regs->u_regs[UREG_FP] = (unsigned long) sf;
 	regs->u_regs[UREG_I0] = signo;
 	regs->u_regs[UREG_I1] = (unsigned long) &sf->info;
+	regs->u_regs[UREG_I2] = (unsigned long) &sf->info;
 
 	/* 4. signal handler */
 	regs->tpc = (unsigned long) ka->sa.sa_handler;
@@ -795,7 +887,7 @@
 sigill:
 	do_exit(SIGILL);
 sigsegv:
-	do_exit(SIGSEGV);
+	force_sigsegv(signo, current);
 }
 
 /* Setup a Solaris stack frame */
@@ -919,7 +1011,7 @@
 	return;
 
 sigsegv:
-	do_exit(SIGSEGV);
+	force_sigsegv(signr, current);
 }
 
 asmlinkage int
@@ -1070,7 +1162,7 @@
 
 	return -EINTR;
 sigsegv:
-	do_exit(SIGSEGV);
+	return -EFAULT;
 }
 
 static void setup_rt_frame32(struct k_sigaction *ka, struct pt_regs *regs,
@@ -1119,6 +1211,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);
@@ -1157,6 +1251,7 @@
 	regs->u_regs[UREG_FP] = (unsigned long) sf;
 	regs->u_regs[UREG_I0] = signr;
 	regs->u_regs[UREG_I1] = (unsigned long) &sf->info;
+	regs->u_regs[UREG_I2] = (unsigned long) &sf->regs;
 
 	/* 4. signal handler */
 	regs->tpc = (unsigned long) ka->sa.sa_handler;
@@ -1206,7 +1301,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,
@@ -1225,8 +1320,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);
@@ -1266,21 +1359,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-10-18 14:55:53 -07:00
+++ b/arch/sparc64/kernel/smp.c	2004-10-18 14:55:53 -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>
@@ -31,7 +32,6 @@
 #include <asm/page.h>
 #include <asm/pgtable.h>
 #include <asm/oplib.h>
-#include <asm/hardirq.h>
 #include <asm/uaccess.h>
 #include <asm/timer.h>
 #include <asm/starfire.h>
@@ -303,14 +303,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 +974,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 +999,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-10-18 14:56:49 -07:00
+++ b/arch/sparc64/kernel/sparc64_ksyms.c	2004-10-18 14:56:49 -07:00
@@ -34,7 +34,6 @@
 #include <asm/pgtable.h>
 #include <asm/io.h>
 #include <asm/irq.h>
-#include <asm/hardirq.h>
 #include <asm/idprom.h>
 #include <asm/svr4.h>
 #include <asm/elf.h>
@@ -74,8 +73,6 @@
 extern void *__memscan_zero(void *, size_t);
 extern void *__memscan_generic(void *, int, size_t);
 extern int __memcmp(const void *, const void *, __kernel_size_t);
-extern int __strncmp(const char *, const char *, __kernel_size_t);
-extern __kernel_size_t __strlen(const char *);
 extern __kernel_size_t strlen(const char *);
 extern void linux_sparc_syscall(void);
 extern void rtrap(void);
@@ -144,7 +141,7 @@
 
 #if defined(CONFIG_MCOUNT)
 extern void _mcount(void);
-EXPORT_SYMBOL_NOVERS(_mcount);
+EXPORT_SYMBOL(_mcount);
 #endif
 
 /* CPU online map and active count.  */
@@ -187,8 +184,6 @@
 EXPORT_SYMBOL(___test_and_set_bit);
 EXPORT_SYMBOL(___test_and_clear_bit);
 EXPORT_SYMBOL(___test_and_change_bit);
-EXPORT_SYMBOL(___test_and_set_le_bit);
-EXPORT_SYMBOL(___test_and_clear_le_bit);
 
 /* Bit searching */
 EXPORT_SYMBOL(find_next_bit);
@@ -295,7 +290,6 @@
 EXPORT_SYMBOL(__prom_getsibling);
 
 /* sparc library symbols */
-EXPORT_SYMBOL(__strlen);
 EXPORT_SYMBOL(strlen);
 EXPORT_SYMBOL(strnlen);
 EXPORT_SYMBOL(__strlen_user);
@@ -334,7 +328,6 @@
 #endif
 
 /* Special internal versions of library functions. */
-EXPORT_SYMBOL(__memset);
 EXPORT_SYMBOL(_clear_page);
 EXPORT_SYMBOL(clear_user_page);
 EXPORT_SYMBOL(copy_user_page);
@@ -342,8 +335,7 @@
 EXPORT_SYMBOL(__memscan_zero);
 EXPORT_SYMBOL(__memscan_generic);
 EXPORT_SYMBOL(__memcmp);
-EXPORT_SYMBOL(__strncmp);
-EXPORT_SYMBOL(__memmove);
+EXPORT_SYMBOL(__memset);
 EXPORT_SYMBOL(memchr);
 
 EXPORT_SYMBOL(csum_partial);
@@ -351,9 +343,12 @@
 EXPORT_SYMBOL(ip_fast_csum);
 
 /* Moving data to/from/in userspace. */
-EXPORT_SYMBOL(__copy_to_user);
-EXPORT_SYMBOL(__copy_from_user);
-EXPORT_SYMBOL(__copy_in_user);
+EXPORT_SYMBOL(___copy_to_user);
+EXPORT_SYMBOL(___copy_from_user);
+EXPORT_SYMBOL(___copy_in_user);
+EXPORT_SYMBOL(copy_to_user_fixup);
+EXPORT_SYMBOL(copy_from_user_fixup);
+EXPORT_SYMBOL(copy_in_user_fixup);
 EXPORT_SYMBOL(__strncpy_from_user);
 EXPORT_SYMBOL(__bzero_noasi);
 
@@ -367,17 +362,24 @@
 /* No version information on this, heavily used in inline asm,
  * and will always be 'void __ret_efault(void)'.
  */
-EXPORT_SYMBOL_NOVERS(__ret_efault);
+EXPORT_SYMBOL(__ret_efault);
 
 /* No version information on these, as gcc produces such symbols. */
-EXPORT_SYMBOL_NOVERS(memcmp);
-EXPORT_SYMBOL_NOVERS(memcpy);
-EXPORT_SYMBOL_NOVERS(memset);
-EXPORT_SYMBOL_NOVERS(memmove);
+EXPORT_SYMBOL(memcmp);
+EXPORT_SYMBOL(memcpy);
+EXPORT_SYMBOL(memset);
+EXPORT_SYMBOL(memmove);
+EXPORT_SYMBOL(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);
+EXPORT_SYMBOL(VISenter);
 
 /* for input/keybdev */
 EXPORT_SYMBOL(sun_do_break);
diff -Nru a/arch/sparc64/kernel/sys32.S b/arch/sparc64/kernel/sys32.S
--- a/arch/sparc64/kernel/sys32.S	2004-10-18 14:56:16 -07:00
+++ b/arch/sparc64/kernel/sys32.S	2004-10-18 14:56:16 -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/sys_sparc32.c b/arch/sparc64/kernel/sys_sparc32.c
--- a/arch/sparc64/kernel/sys_sparc32.c	2004-10-18 14:56:33 -07:00
+++ b/arch/sparc64/kernel/sys_sparc32.c	2004-10-18 14:56:33 -07:00
@@ -1045,7 +1045,7 @@
 }
 
 asmlinkage long sys32_rt_sigtimedwait(compat_sigset_t __user *uthese,
-				      siginfo_t32 __user *uinfo,
+				      struct siginfo32 __user *uinfo,
 				      struct compat_timespec __user *uts,
 				      compat_size_t sigsetsize)
 {
@@ -1130,15 +1130,15 @@
 }
 
 asmlinkage long compat_sys_rt_sigqueueinfo(int pid, int sig,
-					   siginfo_t32 __user *uinfo)
+					   struct siginfo32 __user *uinfo)
 {
 	siginfo_t info;
 	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_to_kernel32(&info, uinfo))
 		return -EFAULT;
+
 	set_fs (KERNEL_DS);
 	ret = sys_rt_sigqueueinfo(pid, sig, (siginfo_t __user *) &info);
 	set_fs (old_fs);
@@ -1736,3 +1736,33 @@
 	return err;
 }
 
+asmlinkage long compat_sys_waitid(u32 which, u32 pid,
+				  struct siginfo32 __user *uinfo, u32 options,
+				  struct compat_rusage __user *uru)
+{
+	siginfo_t info;
+	struct rusage ru;
+	long ret;
+	mm_segment_t old_fs = get_fs();
+
+	memset(&info, 0, sizeof(info));
+
+	set_fs (KERNEL_DS);
+	ret = sys_waitid(which, pid, (siginfo_t __user *) &info,
+			 options,
+			 uru ? (struct rusage __user *) &ru : NULL);
+	set_fs (old_fs);
+
+	if (ret < 0 || info.si_signo == 0)
+		return ret;
+
+	if (uru) {
+		ret = put_compat_rusage(&ru, uru);
+		if (ret)
+			return ret;
+	}
+
+	BUG_ON(info.si_code & __SI_MASK);
+	info.si_code |= __SI_CHLD;
+	return copy_siginfo_to_user32(uinfo, &info);
+}
diff -Nru a/arch/sparc64/kernel/systbls.S b/arch/sparc64/kernel/systbls.S
--- a/arch/sparc64/kernel/systbls.S	2004-10-18 14:56:29 -07:00
+++ b/arch/sparc64/kernel/systbls.S	2004-10-18 14:56:29 -07:00
@@ -75,7 +75,7 @@
 /*260*/	.word compat_sys_sched_getaffinity, compat_sys_sched_setaffinity, sys32_timer_settime, compat_timer_gettime, sys_timer_getoverrun
 	.word sys_timer_delete, sys32_timer_create, sys_ni_syscall, compat_sys_io_setup, sys_io_destroy
 /*270*/	.word sys32_io_submit, sys_io_cancel, compat_sys_io_getevents, sys32_mq_open, sys_mq_unlink
-	.word sys_mq_timedsend, sys_mq_timedreceive, compat_sys_mq_notify, compat_sys_mq_getsetattr, sys_ni_syscall
+	.word sys_mq_timedsend, sys_mq_timedreceive, compat_sys_mq_notify, compat_sys_mq_getsetattr, compat_sys_waitid
 /*280*/	.word sys_ni_syscall, sys_ni_syscall, sys_ni_syscall
 
 #endif /* CONFIG_COMPAT */
@@ -141,7 +141,7 @@
 /*260*/	.word sys_sched_getaffinity, sys_sched_setaffinity, sys_timer_settime, sys_timer_gettime, sys_timer_getoverrun
 	.word sys_timer_delete, sys_timer_create, sys_ni_syscall, sys_io_setup, sys_io_destroy
 /*270*/	.word sys_io_submit, sys_io_cancel, sys_io_getevents, sys_mq_open, sys_mq_unlink
-	.word sys_mq_timedsend, sys_mq_timedreceive, sys_mq_notify, sys_mq_getsetattr, sys_ni_syscall
+	.word sys_mq_timedsend, sys_mq_timedreceive, sys_mq_notify, sys_mq_getsetattr, sys_waitid
 /*280*/	.word sys_ni_syscall, sys_ni_syscall, sys_ni_syscall
 
 #if defined(CONFIG_SUNOS_EMUL) || defined(CONFIG_SOLARIS_EMUL) || \
diff -Nru a/arch/sparc64/kernel/time.c b/arch/sparc64/kernel/time.c
--- a/arch/sparc64/kernel/time.c	2004-10-18 14:56:31 -07:00
+++ b/arch/sparc64/kernel/time.c	2004-10-18 14:56: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>
@@ -67,6 +68,18 @@
 
 #define TICK_PRIV_BIT	(1UL << 63)
 
+#ifdef CONFIG_SMP
+unsigned long profile_pc(struct pt_regs *regs)
+{
+	unsigned long pc = instruction_pointer(regs);
+
+	if (in_lock_functions(pc))
+		return regs->u_regs[UREG_RETPC];
+	return pc;
+}
+EXPORT_SYMBOL(profile_pc);
+#endif
+
 static void tick_disable_protection(void)
 {
 	/* Set things up so user can access tick register for profiling
@@ -418,7 +431,6 @@
 unsigned long timer_tick_offset;
 unsigned long timer_tick_compare;
 
-static unsigned long timer_ticks_per_usec_quotient;
 static unsigned long timer_ticks_per_nsec_quotient;
 
 #define TICK_SIZE (tick_nsec / 1000)
@@ -441,28 +453,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 +461,7 @@
 
 	do {
 #ifndef CONFIG_SMP
-		sparc64_do_profile(regs);
+		profile_tick(CPU_PROFILING, regs);
 #endif
 		do_timer(regs);
 
@@ -920,10 +910,10 @@
 }
 
 /* This is gets the master TICK_INT timer going. */
-static unsigned long sparc64_init_timers(irqreturn_t (*cfunc)(int, void *, struct pt_regs *))
+static unsigned long sparc64_init_timers(void)
 {
-	unsigned long pstate, clock;
-	int node, err;
+	unsigned long clock;
+	int node;
 #ifdef CONFIG_SMP
 	extern void smp_tick_init(void);
 #endif
@@ -956,6 +946,14 @@
 	smp_tick_init();
 #endif
 
+	return clock;
+}
+
+static void sparc64_start_timers(irqreturn_t (*cfunc)(int, void *, struct pt_regs *))
+{
+	unsigned long pstate;
+	int err;
+
 	/* Register IRQ handler. */
 	err = request_irq(build_irq(0, 0, 0UL, 0UL), cfunc, SA_STATIC_ALLOC,
 			  "timer", NULL);
@@ -981,8 +979,6 @@
 			     : "r" (pstate));
 
 	local_irq_enable();
-
-	return clock;
 }
 
 struct freq_table {
@@ -1034,18 +1030,27 @@
 static struct notifier_block sparc64_cpufreq_notifier_block = {
 	.notifier_call	= sparc64_cpufreq_notifier
 };
-#endif
+
+#endif /* CONFIG_CPU_FREQ */
+
+static struct time_interpolator sparc64_cpu_interpolator = {
+	.source		=	TIME_SOURCE_CPU,
+	.shift		=	16,
+};
 
 /* The quotient formula is taken from the IA64 port. */
-#define SPARC64_USEC_PER_CYC_SHIFT	30UL
 #define SPARC64_NSEC_PER_CYC_SHIFT	30UL
 void __init time_init(void)
 {
-	unsigned long clock = sparc64_init_timers(timer_interrupt);
+	unsigned long clock = sparc64_init_timers();
 
-	timer_ticks_per_usec_quotient =
-		(((1000000UL << SPARC64_USEC_PER_CYC_SHIFT) +
-		  (clock / 2)) / clock);
+	sparc64_cpu_interpolator.frequency = clock;
+	register_time_interpolator(&sparc64_cpu_interpolator);
+
+	/* Now that the interpolator is registered, it is
+	 * safe to start the timer ticking.
+	 */
+	sparc64_start_timers(timer_interrupt);
 
 	timer_ticks_per_nsec_quotient =
 		(((NSEC_PER_SEC << SPARC64_NSEC_PER_CYC_SHIFT) +
@@ -1057,17 +1062,6 @@
 #endif
 }
 
-static __inline__ unsigned long do_gettimeoffset(void)
-{
-	unsigned long ticks = tick_ops->get_tick();
-
-	ticks += timer_tick_offset;
-	ticks -= timer_tick_compare;
-
-	return (ticks * timer_ticks_per_usec_quotient)
-		>> SPARC64_USEC_PER_CYC_SHIFT;
-}
-
 unsigned long long sched_clock(void)
 {
 	unsigned long ticks = tick_ops->get_tick();
@@ -1075,100 +1069,6 @@
 	return (ticks * timer_ticks_per_nsec_quotient)
 		>> SPARC64_NSEC_PER_CYC_SHIFT;
 }
-
-int do_settimeofday(struct timespec *tv)
-{
-	time_t wtm_sec, sec = tv->tv_sec;
-	long wtm_nsec, nsec = tv->tv_nsec;
-
-	if ((unsigned long)tv->tv_nsec >= NSEC_PER_SEC)
-		return -EINVAL;
-
-	if (this_is_starfire)
-		return 0;
-
-	write_seqlock_irq(&xtime_lock);
-	/*
-	 * This is revolting. We need to set "xtime" correctly. However, the
-	 * value in this location is the value at the most recent update of
-	 * wall time.  Discover what correction gettimeofday() would have
-	 * made, and then undo it!
-	 */
-	nsec -= do_gettimeoffset() * 1000;
-	nsec -= (jiffies - wall_jiffies) * (NSEC_PER_SEC / HZ);
-
-	wtm_sec  = wall_to_monotonic.tv_sec + (xtime.tv_sec - sec);
-	wtm_nsec = wall_to_monotonic.tv_nsec + (xtime.tv_nsec - nsec);
-
-	set_normalized_timespec(&xtime, sec, nsec);
-	set_normalized_timespec(&wall_to_monotonic, wtm_sec, wtm_nsec);
-
-	time_adjust = 0;		/* stop active adjtime() */
-	time_status |= STA_UNSYNC;
-	time_maxerror = NTP_PHASE_LIMIT;
-	time_esterror = NTP_PHASE_LIMIT;
-	write_sequnlock_irq(&xtime_lock);
-	clock_was_set();
-	return 0;
-}
-
-EXPORT_SYMBOL(do_settimeofday);
-
-/* Ok, my cute asm atomicity trick doesn't work anymore.
- * There are just too many variables that need to be protected
- * now (both members of xtime, wall_jiffies, et al.)
- */
-void do_gettimeofday(struct timeval *tv)
-{
-	unsigned long seq;
-	unsigned long usec, sec;
-	unsigned long max_ntp_tick = tick_usec - tickadj;
-
-	do {
-		unsigned long lost;
-
-		seq = read_seqbegin(&xtime_lock);
-		usec = do_gettimeoffset();
-		lost = jiffies - wall_jiffies;
-
-		/*
-		 * If time_adjust is negative then NTP is slowing the clock
-		 * so make sure not to go into next possible interval.
-		 * Better to lose some accuracy than have time go backwards..
-		 */
-		if (unlikely(time_adjust < 0)) {
-			usec = min(usec, max_ntp_tick);
-
-			if (lost)
-				usec += lost * max_ntp_tick;
-		}
-		else if (unlikely(lost))
-			usec += lost * tick_usec;
-
-		sec = xtime.tv_sec;
-
-		/* Believe it or not, this divide shows up on
-		 * kernel profiles.  The problem is that it is
-		 * both 64-bit and signed.  Happily, 32-bits
-		 * of precision is all we really need and in
-		 * doing so gcc ends up emitting a cheap multiply.
-		 *
-		 * XXX Why is tv_nsec 'long' and 'signed' in
-		 * XXX the first place, can it even be negative?
-		 */
-		usec += ((unsigned int) xtime.tv_nsec / 1000U);
-	} while (read_seqretry(&xtime_lock, seq));
-
-	while (usec >= 1000000) {
-		usec -= 1000000;
-		sec++;
-	}
-
-	tv->tv_sec = sec;
-	tv->tv_usec = usec;
-}
-
-EXPORT_SYMBOL(do_gettimeofday);
 
 static int set_rtc_mmss(unsigned long nowtime)
 {
diff -Nru a/arch/sparc64/kernel/traps.c b/arch/sparc64/kernel/traps.c
--- a/arch/sparc64/kernel/traps.c	2004-10-18 14:57:04 -07:00
+++ b/arch/sparc64/kernel/traps.c	2004-10-18 14:57:04 -07:00
@@ -36,10 +36,24 @@
 #include <asm/psrcompat.h>
 #include <asm/processor.h>
 #include <asm/timer.h>
+#include <asm/kdebug.h>
 #ifdef CONFIG_KMOD
 #include <linux/kmod.h>
 #endif
 
+struct notifier_block *sparc64die_chain;
+static spinlock_t die_notifier_lock = SPIN_LOCK_UNLOCKED;
+
+int register_die_notifier(struct notifier_block *nb)
+{
+	int err = 0;
+	unsigned long flags;
+	spin_lock_irqsave(&die_notifier_lock, flags);
+	err = notifier_chain_register(&sparc64die_chain, nb);
+	spin_unlock_irqrestore(&die_notifier_lock, flags);
+	return err;
+}
+
 /* When an irrecoverable trap occurs at tl > 0, the trap entry
  * code logs the trap state registers at every level in the trap
  * stack.  It is found at (pt_regs + sizeof(pt_regs)) and the layout
@@ -71,11 +85,20 @@
 	}
 }
 
-void bad_trap (struct pt_regs *regs, long lvl)
+void do_call_debug(struct pt_regs *regs) 
+{ 
+	notify_die(DIE_CALL, "debug call", regs, 0, 255, SIGINT); 
+}
+
+void bad_trap(struct pt_regs *regs, long lvl)
 {
 	char buffer[32];
 	siginfo_t info;
 
+	if (notify_die(DIE_TRAP, "bad trap", regs,
+		       0, lvl, SIGTRAP) == NOTIFY_STOP)
+		return;
+
 	if (lvl < 0x100) {
 		sprintf(buffer, "Bad hw trap %lx at tl0\n", lvl);
 		die_if_kernel(buffer, regs);
@@ -84,7 +107,7 @@
 	lvl -= 0x100;
 	if (regs->tstate & TSTATE_PRIV) {
 		sprintf(buffer, "Kernel bad sw trap %lx", lvl);
-		die_if_kernel (buffer, regs);
+		die_if_kernel(buffer, regs);
 	}
 	if (test_thread_flag(TIF_32BIT)) {
 		regs->tpc &= 0xffffffff;
@@ -98,10 +121,14 @@
 	force_sig_info(SIGILL, &info, current);
 }
 
-void bad_trap_tl1 (struct pt_regs *regs, long lvl)
+void bad_trap_tl1(struct pt_regs *regs, long lvl)
 {
 	char buffer[32];
 	
+	if (notify_die(DIE_TRAP_TL1, "bad trap tl1", regs,
+		       0, lvl, SIGTRAP) == NOTIFY_STOP)
+		return;
+
 	dump_tl1_traplog((struct tl1_traplog *)(regs + 1));
 
 	sprintf (buffer, "Bad trap %lx at tl>0", lvl);
@@ -121,6 +148,10 @@
 {
 	siginfo_t info;
 
+	if (notify_die(DIE_TRAP, "instruction access exception", regs,
+		       0, 0x8, SIGTRAP) == NOTIFY_STOP)
+		return;
+
 	if (regs->tstate & TSTATE_PRIV) {
 		printk("instruction_access_exception: SFSR[%016lx] SFAR[%016lx], going.\n",
 		       sfsr, sfar);
@@ -141,15 +172,23 @@
 void instruction_access_exception_tl1(struct pt_regs *regs,
 				      unsigned long sfsr, unsigned long sfar)
 {
+	if (notify_die(DIE_TRAP_TL1, "instruction access exception tl1", regs,
+		       0, 0x8, SIGTRAP) == NOTIFY_STOP)
+		return;
+
 	dump_tl1_traplog((struct tl1_traplog *)(regs + 1));
 	instruction_access_exception(regs, sfsr, sfar);
 }
 
-void data_access_exception (struct pt_regs *regs,
-			    unsigned long sfsr, unsigned long sfar)
+void data_access_exception(struct pt_regs *regs,
+			   unsigned long sfsr, unsigned long sfar)
 {
 	siginfo_t info;
 
+	if (notify_die(DIE_TRAP, "data access exception", regs,
+		       0, 0x30, SIGTRAP) == NOTIFY_STOP)
+		return;
+
 	if (regs->tstate & TSTATE_PRIV) {
 		/* Test if this comes from uaccess places. */
 		unsigned long fixup;
@@ -220,6 +259,10 @@
 
 	spitfire_clean_and_reenable_l1_caches();
 
+	if (notify_die(DIE_TRAP, "instruction access exception", regs,
+		       0, 0x8, SIGTRAP) == NOTIFY_STOP)
+		return;
+
 	info.si_signo = SIGBUS;
 	info.si_errno = 0;
 	info.si_code = BUS_OBJERR;
@@ -230,6 +273,8 @@
 
 void do_dae(struct pt_regs *regs)
 {
+	siginfo_t info;
+
 #ifdef CONFIG_PCI
 	if (pci_poke_in_progress && pci_poke_cpu == smp_processor_id()) {
 		spitfire_clean_and_reenable_l1_caches();
@@ -244,7 +289,18 @@
 		return;
 	}
 #endif
-	do_iae(regs);
+	spitfire_clean_and_reenable_l1_caches();
+
+	if (notify_die(DIE_TRAP, "data access exception", regs,
+		       0, 0x30, SIGTRAP) == NOTIFY_STOP)
+		return;
+
+	info.si_signo = SIGBUS;
+	info.si_errno = 0;
+	info.si_code = BUS_OBJERR;
+	info.si_addr = (void *)0;
+	info.si_trapno = 0;
+	force_sig_info(SIGBUS, &info, current);
 }
 
 static char ecc_syndrome_table[] = {
@@ -1638,6 +1694,10 @@
 
 void do_fpieee(struct pt_regs *regs)
 {
+	if (notify_die(DIE_TRAP, "fpu exception ieee", regs,
+		       0, 0x24, SIGFPE) == NOTIFY_STOP)
+		return;
+
 	do_fpe_common(regs);
 }
 
@@ -1648,6 +1708,10 @@
 	struct fpustate *f = FPUSTATE;
 	int ret = 0;
 
+	if (notify_die(DIE_TRAP, "fpu exception other", regs,
+		       0, 0x25, SIGFPE) == NOTIFY_STOP)
+		return;
+
 	switch ((current_thread_info()->xfsr[0] & 0x1c000)) {
 	case (2 << 14): /* unfinished_FPop */
 	case (3 << 14): /* unimplemented_FPop */
@@ -1663,6 +1727,10 @@
 {
 	siginfo_t info;
 
+	if (notify_die(DIE_TRAP, "tagged arithmetic overflow", regs,
+		       0, 0x26, SIGEMT) == NOTIFY_STOP)
+		return;
+
 	if (regs->tstate & TSTATE_PRIV)
 		die_if_kernel("Penguin overflow trap from kernel mode", regs);
 	if (test_thread_flag(TIF_32BIT)) {
@@ -1681,6 +1749,10 @@
 {
 	siginfo_t info;
 
+	if (notify_die(DIE_TRAP, "integer division by zero", regs,
+		       0, 0x28, SIGFPE) == NOTIFY_STOP)
+		return;
+
 	if (regs->tstate & TSTATE_PRIV)
 		die_if_kernel("TL0: Kernel divide by zero.", regs);
 	if (test_thread_flag(TIF_32BIT)) {
@@ -1771,6 +1843,37 @@
 
 EXPORT_SYMBOL(dump_stack);
 
+static inline int is_kernel_stack(struct task_struct *task,
+				  struct reg_window *rw)
+{
+	unsigned long rw_addr = (unsigned long) rw;
+	unsigned long thread_base, thread_end;
+
+	if (rw_addr < PAGE_OFFSET) {
+		if (task != &init_task)
+			return 0;
+	}
+
+	thread_base = (unsigned long) task->thread_info;
+	thread_end = thread_base + sizeof(union thread_union);
+	if (rw_addr >= thread_base &&
+	    rw_addr < thread_end &&
+	    !(rw_addr & 0x7UL))
+		return 1;
+
+	return 0;
+}
+
+static inline struct reg_window *kernel_stack_up(struct reg_window *rw)
+{
+	unsigned long fp = rw->ins[6];
+
+	if (!fp)
+		return NULL;
+
+	return (struct reg_window *) (fp + STACK_BIAS);
+}
+
 void die_if_kernel(char *str, struct pt_regs *regs)
 {
 	static int die_counter;
@@ -1786,6 +1889,7 @@
 "                 \\__U_/\n");
 
 	printk("%s(%d): %s [#%d]\n", current->comm, current->pid, str, ++die_counter);
+	notify_die(DIE_OOPS, str, regs, 0, 255, SIGSEGV);
 	__asm__ __volatile__("flushw");
 	__show_regs(regs);
 	if (regs->tstate & TSTATE_PRIV) {
@@ -1795,17 +1899,14 @@
 		/* Stop the back trace when we hit userland or we
 		 * find some badly aligned kernel stack.
 		 */
-		while (rw					&&
-		       count++ < 30				&&
-		       (((unsigned long) rw) >= PAGE_OFFSET)	&&
-		       (char *) rw < ((char *) current)
-		       + sizeof (union thread_union) 		&&
-		       !(((unsigned long) rw) & 0x7)) {
+		while (rw &&
+		       count++ < 30&&
+		       is_kernel_stack(current, rw)) {
 			printk("Caller[%016lx]", rw->ins[7]);
 			print_symbol(": %s", rw->ins[7]);
 			printk("\n");
-			rw = (struct reg_window *)
-				(rw->ins[6] + STACK_BIAS);
+
+			rw = kernel_stack_up(rw);
 		}
 		instruction_dump ((unsigned int *) regs->tpc);
 	} else {
@@ -1834,6 +1935,10 @@
 	u32 insn;
 	siginfo_t info;
 
+	if (notify_die(DIE_TRAP, "illegal instruction", regs,
+		       0, 0x10, SIGILL) == NOTIFY_STOP)
+		return;
+
 	if (tstate & TSTATE_PRIV)
 		die_if_kernel("Kernel illegal instruction", regs);
 	if (test_thread_flag(TIF_32BIT))
@@ -1859,6 +1964,10 @@
 {
 	siginfo_t info;
 
+	if (notify_die(DIE_TRAP, "memory address unaligned", regs,
+		       0, 0x34, SIGSEGV) == NOTIFY_STOP)
+		return;
+
 	if (regs->tstate & TSTATE_PRIV) {
 		extern void kernel_unaligned_trap(struct pt_regs *regs,
 						  unsigned int insn, 
@@ -1880,6 +1989,10 @@
 void do_privop(struct pt_regs *regs)
 {
 	siginfo_t info;
+
+	if (notify_die(DIE_TRAP, "privileged operation", regs,
+		       0, 0x11, SIGILL) == NOTIFY_STOP)
+		return;
 
 	if (test_thread_flag(TIF_32BIT)) {
 		regs->tpc &= 0xffffffff;
diff -Nru a/arch/sparc64/kernel/ttable.S b/arch/sparc64/kernel/ttable.S
--- a/arch/sparc64/kernel/ttable.S	2004-10-18 14:56:33 -07:00
+++ b/arch/sparc64/kernel/ttable.S	2004-10-18 14:56:33 -07:00
@@ -158,7 +158,7 @@
 tl0_resv169:	BTRAP(0x169) BTRAP(0x16a) BTRAP(0x16b) BTRAP(0x16c)
 tl0_linux64:	LINUX_64BIT_SYSCALL_TRAP
 tl0_gsctx:	TRAP(sparc64_get_context) TRAP(sparc64_set_context)
-tl0_resv170:	BTRAP(0x170) BTRAP(0x171) BTRAP(0x172)
+tl0_resv170:	KPROBES_TRAP(0x170) KPROBES_TRAP(0x171) BTRAP(0x172)
 tl0_resv173:	BTRAP(0x173) BTRAP(0x174) BTRAP(0x175) BTRAP(0x176) BTRAP(0x177)
 tl0_resv178:	BTRAP(0x178) BTRAP(0x179) BTRAP(0x17a) BTRAP(0x17b) BTRAP(0x17c)
 tl0_resv17d:	BTRAP(0x17d) BTRAP(0x17e) BTRAP(0x17f)
diff -Nru a/arch/sparc64/kernel/vmlinux.lds.S b/arch/sparc64/kernel/vmlinux.lds.S
--- a/arch/sparc64/kernel/vmlinux.lds.S	2004-10-18 14:56:50 -07:00
+++ b/arch/sparc64/kernel/vmlinux.lds.S	2004-10-18 14:56:50 -07:00
@@ -16,6 +16,7 @@
   {
     *(.text)
     SCHED_TEXT
+    LOCK_TEXT
     *(.gnu.warning)
   } =0
   _etext = .;
@@ -52,9 +53,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-10-18 14:55:54 -07:00
+++ b/arch/sparc64/lib/Makefile	2004-10-18 14:55:54 -07:00
@@ -7,11 +7,12 @@
 
 lib-y := PeeCeeI.o copy_page.o clear_page.o strlen.o strncmp.o \
 	 memscan.o strncpy_from_user.o strlen_user.o memcmp.o checksum.o \
-	 VIScopy.o VISbzero.o VISmemset.o VIScsum.o VIScsumcopy.o \
-	 VIScsumcopyusr.o VISsave.o atomic.o rwlock.o bitops.o \
-	 U3memcpy.o U3copy_from_user.o U3copy_to_user.o \
-	 U3copy_in_user.o mcount.o ipcsum.o rwsem.o xor.o splock.o \
-	 find_bit.o
+	 VISbzero.o VISmemset.o VIScsum.o VIScsumcopy.o \
+	 VIScsumcopyusr.o VISsave.o atomic.o bitops.o \
+	 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 find_bit.o delay.o iomap.o
 
 lib-$(CONFIG_DEBUG_SPINLOCK) += debuglocks.o
 lib-$(CONFIG_HAVE_DEC_LOCK) += dec_and_lock.o
diff -Nru a/arch/sparc64/lib/PeeCeeI.c b/arch/sparc64/lib/PeeCeeI.c
--- a/arch/sparc64/lib/PeeCeeI.c	2004-10-18 14:56:49 -07:00
+++ b/arch/sparc64/lib/PeeCeeI.c	2004-10-18 14:56:49 -07:00
@@ -7,7 +7,7 @@
 #include <asm/io.h>
 #include <asm/byteorder.h>
 
-void outsb(unsigned long addr, const void *src, unsigned long count)
+void outsb(void __iomem *addr, const void *src, unsigned long count)
 {
 	const u8 *p = src;
 
@@ -15,7 +15,7 @@
 		outb(*p++, addr);
 }
 
-void outsw(unsigned long addr, const void *src, unsigned long count)
+void outsw(void __iomem *addr, const void *src, unsigned long count)
 {
 	if(count) {
 		u16 *ps = (u16 *)src;
@@ -44,7 +44,7 @@
 	}
 }
 
-void outsl(unsigned long addr, const void *src, unsigned long count)
+void outsl(void __iomem *addr, const void *src, unsigned long count)
 {
 	if(count) {
 		if((((u64)src) & 0x3) == 0) {
@@ -119,7 +119,7 @@
 	}
 }
 
-void insb(unsigned long addr, void *dst, unsigned long count)
+void insb(void __iomem *addr, void *dst, unsigned long count)
 {
 	if(count) {
 		u32 *pi;
@@ -144,7 +144,7 @@
 	}
 }
 
-void insw(unsigned long addr, void *dst, unsigned long count)
+void insw(void __iomem *addr, void *dst, unsigned long count)
 {
 	if(count) {
 		u16 *ps = dst;
@@ -169,7 +169,7 @@
 	}
 }
 
-void insl(unsigned long addr, void *dst, unsigned long count)
+void insl(void __iomem *addr, void *dst, unsigned long count)
 {
 	if(count) {
 		if((((unsigned long)dst) & 0x3) == 0) {
diff -Nru a/arch/sparc64/lib/U1copy_from_user.S b/arch/sparc64/lib/U1copy_from_user.S
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/arch/sparc64/lib/U1copy_from_user.S	2004-10-18 14:57:23 -07:00
@@ -0,0 +1,33 @@
+/* U1copy_from_user.S: UltraSparc-I/II/IIi/IIe optimized copy from userspace.
+ *
+ * Copyright (C) 1999, 2000, 2004 David S. Miller (davem@redhat.com)
+ */
+
+#define EX_LD(x)		\
+98:	x;			\
+	.section .fixup;	\
+	.align 4;		\
+99:	retl;			\
+	 mov	1, %o0;		\
+	.section __ex_table;	\
+	.align 4;		\
+	.word 98b, 99b;		\
+	.text;			\
+	.align 4;
+
+#define FUNC_NAME		___copy_from_user
+#define LOAD(type,addr,dest)	type##a [addr] %asi, dest
+#define LOAD_BLK(addr,dest)	ldda [addr] ASI_BLK_AIUS, dest
+#define EX_RETVAL(x)		0
+
+	/* Writing to %asi is _expensive_ so we hardcode it.
+	 * Reading %asi to check for KERNEL_DS is comparatively
+	 * cheap.
+	 */
+#define PREAMBLE					\
+	rd		%asi, %g1;			\
+	cmp		%g1, ASI_AIUS;			\
+	bne,pn		%icc, memcpy_user_stub;		\
+	 nop;						\
+
+#include "U1memcpy.S"
diff -Nru a/arch/sparc64/lib/U1copy_to_user.S b/arch/sparc64/lib/U1copy_to_user.S
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/arch/sparc64/lib/U1copy_to_user.S	2004-10-18 14:57:23 -07:00
@@ -0,0 +1,33 @@
+/* U1copy_to_user.S: UltraSparc-I/II/IIi/IIe optimized copy to userspace.
+ *
+ * Copyright (C) 1999, 2000, 2004 David S. Miller (davem@redhat.com)
+ */
+
+#define EX_ST(x)		\
+98:	x;			\
+	.section .fixup;	\
+	.align 4;		\
+99:	retl;			\
+	 mov	1, %o0;		\
+	.section __ex_table;	\
+	.align 4;		\
+	.word 98b, 99b;		\
+	.text;			\
+	.align 4;
+
+#define FUNC_NAME		___copy_to_user
+#define STORE(type,src,addr)	type##a src, [addr] ASI_AIUS
+#define STORE_BLK(src,addr)	stda src, [addr] ASI_BLK_AIUS
+#define EX_RETVAL(x)		0
+
+	/* Writing to %asi is _expensive_ so we hardcode it.
+	 * Reading %asi to check for KERNEL_DS is comparatively
+	 * cheap.
+	 */
+#define PREAMBLE					\
+	rd		%asi, %g1;			\
+	cmp		%g1, ASI_AIUS;			\
+	bne,pn		%icc, memcpy_user_stub;		\
+	 nop;						\
+
+#include "U1memcpy.S"
diff -Nru a/arch/sparc64/lib/U1memcpy.S b/arch/sparc64/lib/U1memcpy.S
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/arch/sparc64/lib/U1memcpy.S	2004-10-18 14:57:23 -07:00
@@ -0,0 +1,555 @@
+/* U1memcpy.S: UltraSPARC-I/II/IIi/IIe optimized memcpy.
+ *
+ * Copyright (C) 1997, 2004 David S. Miller (davem@redhat.com)
+ * Copyright (C) 1996, 1997, 1998, 1999 Jakub Jelinek (jj@ultra.linux.cz)
+ */
+
+#ifdef __KERNEL__
+#include <asm/visasm.h>
+#include <asm/asi.h>
+#else
+#define ASI_BLK_P 0xf0
+#define FPRS_FEF  0x04
+#ifdef MEMCPY_DEBUG
+#define VISEntry rd %fprs, %o5; wr %g0, FPRS_FEF, %fprs; \
+		 clr %g1; clr %g2; clr %g3; subcc %g0, %g0, %g0;
+#define VISExit and %o5, FPRS_FEF, %o5; wr %o5, 0x0, %fprs
+#else
+#define VISEntry rd %fprs, %o5; wr %g0, FPRS_FEF, %fprs
+#define VISExit and %o5, FPRS_FEF, %o5; wr %o5, 0x0, %fprs
+#endif
+#endif
+
+#ifndef EX_LD
+#define EX_LD(x)	x
+#endif
+
+#ifndef EX_ST
+#define EX_ST(x)	x
+#endif
+
+#ifndef EX_RETVAL
+#define EX_RETVAL(x)	x
+#endif
+
+#ifndef LOAD
+#define LOAD(type,addr,dest)	type [addr], dest
+#endif
+
+#ifndef LOAD_BLK
+#define LOAD_BLK(addr,dest)	ldda [addr] ASI_BLK_P, dest
+#endif
+
+#ifndef STORE
+#define STORE(type,src,addr)	type src, [addr]
+#endif
+
+#ifndef STORE_BLK
+#define STORE_BLK(src,addr)	stda src, [addr] ASI_BLK_P
+#endif
+
+#ifndef FUNC_NAME
+#define FUNC_NAME	memcpy
+#endif
+
+#ifndef PREAMBLE
+#define PREAMBLE
+#endif
+
+#ifndef XCC
+#define XCC xcc
+#endif
+
+#define FREG_FROB(f1, f2, f3, f4, f5, f6, f7, f8, f9)		\
+	faligndata		%f1, %f2, %f48;			\
+	faligndata		%f2, %f3, %f50;			\
+	faligndata		%f3, %f4, %f52;			\
+	faligndata		%f4, %f5, %f54;			\
+	faligndata		%f5, %f6, %f56;			\
+	faligndata		%f6, %f7, %f58;			\
+	faligndata		%f7, %f8, %f60;			\
+	faligndata		%f8, %f9, %f62;
+
+#define MAIN_LOOP_CHUNK(src, dest, fdest, fsrc, len, jmptgt)	\
+	EX_LD(LOAD_BLK(%src, %fdest));				\
+	EX_ST(STORE_BLK(%fsrc, %dest));				\
+	add			%src, 0x40, %src;		\
+	subcc			%len, 0x40, %len;		\
+	be,pn			%xcc, jmptgt;			\
+	 add			%dest, 0x40, %dest;		\
+
+#define LOOP_CHUNK1(src, dest, len, branch_dest)		\
+	MAIN_LOOP_CHUNK(src, dest, f0,  f48, len, branch_dest)
+#define LOOP_CHUNK2(src, dest, len, branch_dest)		\
+	MAIN_LOOP_CHUNK(src, dest, f16, f48, len, branch_dest)
+#define LOOP_CHUNK3(src, dest, len, branch_dest)		\
+	MAIN_LOOP_CHUNK(src, dest, f32, f48, len, branch_dest)
+
+#define STORE_SYNC(dest, fsrc)				\
+	EX_ST(STORE_BLK(%fsrc, %dest));			\
+	add			%dest, 0x40, %dest;
+
+#define STORE_JUMP(dest, fsrc, target)			\
+	EX_ST(STORE_BLK(%fsrc, %dest));			\
+	add			%dest, 0x40, %dest;	\
+	ba,pt			%xcc, target;
+
+#define FINISH_VISCHUNK(dest, f0, f1, left)	\
+	subcc			%left, 8, %left;\
+	bl,pn			%xcc, 95f;	\
+	 faligndata		%f0, %f1, %f48;	\
+	EX_ST(STORE(std, %f48, %dest));		\
+	add			%dest, 8, %dest;
+
+#define UNEVEN_VISCHUNK_LAST(dest, f0, f1, left)	\
+	subcc			%left, 8, %left;	\
+	bl,pn			%xcc, 95f;		\
+	 fsrc1			%f0, %f1;
+
+#define UNEVEN_VISCHUNK(dest, f0, f1, left)		\
+	UNEVEN_VISCHUNK_LAST(dest, f0, f1, left)	\
+	ba,a,pt			%xcc, 93f;
+
+	.register	%g2,#scratch
+	.register	%g3,#scratch
+
+	.text
+	.align		64
+
+	.globl		FUNC_NAME
+	.type		FUNC_NAME,#function
+FUNC_NAME:		/* %o0=dst, %o1=src, %o2=len */
+	PREAMBLE
+	mov		%o0, %g5
+	cmp		%o2, 0
+	be,pn		%XCC, 85f
+	 or		%o0, %o1, %o3
+	cmp		%o2, 16
+	blu,a,pn	%XCC, 80f
+	 or		%o3, %o2, %o3
+
+	cmp		%o2, (5 * 64)
+	blu,pt		%XCC, 70f
+	 andcc		%o3, 0x7, %g0
+
+	/* Clobbers o5/g1/g2/g3/g7/icc/xcc.  */
+	VISEntry
+
+	/* Is 'dst' already aligned on an 64-byte boundary? */
+	andcc		%o0, 0x3f, %g2
+	be,pt		%XCC, 2f
+
+	/* Compute abs((dst & 0x3f) - 0x40) into %g2.  This is the number
+	 * of bytes to copy to make 'dst' 64-byte aligned.  We pre-
+	 * subtract this from 'len'.
+	 */
+	 sub		%o0, %o1, %o4
+	sub		%g2, 0x40, %g2
+	sub		%g0, %g2, %g2
+	sub		%o2, %g2, %o2
+	andcc		%g2, 0x7, %g1
+	be,pt		%icc, 2f
+	 and		%g2, 0x38, %g2
+
+1:	subcc		%g1, 0x1, %g1
+	EX_LD(LOAD(ldub, %o1 + 0x00, %o3))
+	EX_ST(STORE(stb, %o3, %o1 + %o4))
+	bgu,pt		%XCC, 1b
+	 add		%o1, 0x1, %o1
+
+	add		%o1, %o4, %o0
+
+2:	cmp		%g2, 0x0
+	and		%o1, 0x7, %g1
+	be,pt		%icc, 3f
+	 alignaddr	%o1, %g0, %o1
+
+	EX_LD(LOAD(ldd, %o1, %f4))
+1:	EX_LD(LOAD(ldd, %o1 + 0x8, %f6))
+	add		%o1, 0x8, %o1
+	subcc		%g2, 0x8, %g2
+	faligndata	%f4, %f6, %f0
+	EX_ST(STORE(std, %f0, %o0))
+	be,pn		%icc, 3f
+	 add		%o0, 0x8, %o0
+
+	EX_LD(LOAD(ldd, %o1 + 0x8, %f4))
+	add		%o1, 0x8, %o1
+	subcc		%g2, 0x8, %g2
+	faligndata	%f6, %f4, %f0
+	EX_ST(STORE(std, %f0, %o0))
+	bne,pt		%icc, 1b
+	 add		%o0, 0x8, %o0
+
+	/* Destination is 64-byte aligned.  */
+3:	
+	membar		  #LoadStore | #StoreStore | #StoreLoad
+
+	subcc		%o2, 0x40, %o4
+	add		%o1, %g1, %g1
+	andncc		%o4, (0x40 - 1), %o4
+	srl		%g1, 3, %g2
+	sub		%o2, %o4, %g3
+	andn		%o1, (0x40 - 1), %o1
+	and		%g2, 7, %g2
+	andncc		%g3, 0x7, %g3
+	fmovd		%f0, %f2
+	sub		%g3, 0x8, %g3
+	sub		%o2, %o4, %o2
+
+	add		%g1, %o4, %g1
+	subcc		%o2, %g3, %o2
+
+	EX_LD(LOAD_BLK(%o1, %f0))
+	add		%o1, 0x40, %o1
+	add		%g1, %g3, %g1
+	EX_LD(LOAD_BLK(%o1, %f16))
+	add		%o1, 0x40, %o1
+	sub		%o4, 0x80, %o4
+	EX_LD(LOAD_BLK(%o1, %f32))
+	add		%o1, 0x40, %o1
+
+	/* There are 8 instances of the unrolled loop,
+	 * one for each possible alignment of the
+	 * source buffer.  Each loop instance is 452
+	 * bytes.
+	 */
+	sll		%g2, 3, %o3
+	sub		%o3, %g2, %o3
+	sllx		%o3, 4, %o3
+	add		%o3, %g2, %o3
+	sllx		%o3, 2, %g2
+1:	rd		%pc, %o3
+	add		%o3, %lo(1f - 1b), %o3
+	jmpl		%o3 + %g2, %g0
+	 nop
+
+	.align		64
+1:	FREG_FROB(f0, f2, f4, f6, f8, f10,f12,f14,f16)
+	LOOP_CHUNK1(o1, o0, o4, 1f)
+	FREG_FROB(f16,f18,f20,f22,f24,f26,f28,f30,f32)
+	LOOP_CHUNK2(o1, o0, o4, 2f)
+	FREG_FROB(f32,f34,f36,f38,f40,f42,f44,f46,f0)
+	LOOP_CHUNK3(o1, o0, o4, 3f)
+	ba,pt		%xcc, 1b+4
+	 faligndata	%f0, %f2, %f48
+1:	FREG_FROB(f16,f18,f20,f22,f24,f26,f28,f30,f32)
+	STORE_SYNC(o0, f48) membar #Sync
+	FREG_FROB(f32,f34,f36,f38,f40,f42,f44,f46,f0)
+	STORE_JUMP(o0, f48, 40f) membar #Sync
+2:	FREG_FROB(f32,f34,f36,f38,f40,f42,f44,f46,f0)
+	STORE_SYNC(o0, f48) membar #Sync
+	FREG_FROB(f0, f2, f4, f6, f8, f10,f12,f14,f16)
+	STORE_JUMP(o0, f48, 48f) membar #Sync
+3:	FREG_FROB(f0, f2, f4, f6, f8, f10,f12,f14,f16)
+	STORE_SYNC(o0, f48) membar #Sync
+	FREG_FROB(f16,f18,f20,f22,f24,f26,f28,f30,f32)
+	STORE_JUMP(o0, f48, 56f) membar #Sync
+
+1:	FREG_FROB(f2, f4, f6, f8, f10,f12,f14,f16,f18)
+	LOOP_CHUNK1(o1, o0, o4, 1f)
+	FREG_FROB(f18,f20,f22,f24,f26,f28,f30,f32,f34)
+	LOOP_CHUNK2(o1, o0, o4, 2f)
+	FREG_FROB(f34,f36,f38,f40,f42,f44,f46,f0, f2)
+	LOOP_CHUNK3(o1, o0, o4, 3f)
+	ba,pt		%xcc, 1b+4
+	 faligndata	%f2, %f4, %f48
+1:	FREG_FROB(f18,f20,f22,f24,f26,f28,f30,f32,f34)
+	STORE_SYNC(o0, f48) membar #Sync
+	FREG_FROB(f34,f36,f38,f40,f42,f44,f46,f0, f2)
+	STORE_JUMP(o0, f48, 41f) membar #Sync
+2:	FREG_FROB(f34,f36,f38,f40,f42,f44,f46,f0, f2)
+	STORE_SYNC(o0, f48) membar #Sync
+	FREG_FROB(f2, f4, f6, f8, f10,f12,f14,f16,f18)
+	STORE_JUMP(o0, f48, 49f) membar #Sync
+3:	FREG_FROB(f2, f4, f6, f8, f10,f12,f14,f16,f18)
+	STORE_SYNC(o0, f48) membar #Sync
+	FREG_FROB(f18,f20,f22,f24,f26,f28,f30,f32,f34)
+	STORE_JUMP(o0, f48, 57f) membar #Sync
+
+1:	FREG_FROB(f4, f6, f8, f10,f12,f14,f16,f18,f20)
+	LOOP_CHUNK1(o1, o0, o4, 1f)
+	FREG_FROB(f20,f22,f24,f26,f28,f30,f32,f34,f36)
+	LOOP_CHUNK2(o1, o0, o4, 2f)
+	FREG_FROB(f36,f38,f40,f42,f44,f46,f0, f2, f4)
+	LOOP_CHUNK3(o1, o0, o4, 3f)
+	ba,pt		%xcc, 1b+4
+	 faligndata	%f4, %f6, %f48
+1:	FREG_FROB(f20,f22,f24,f26,f28,f30,f32,f34,f36)
+	STORE_SYNC(o0, f48) membar #Sync
+	FREG_FROB(f36,f38,f40,f42,f44,f46,f0, f2, f4)
+	STORE_JUMP(o0, f48, 42f) membar #Sync
+2:	FREG_FROB(f36,f38,f40,f42,f44,f46,f0, f2, f4)
+	STORE_SYNC(o0, f48) membar #Sync
+	FREG_FROB(f4, f6, f8, f10,f12,f14,f16,f18,f20)
+	STORE_JUMP(o0, f48, 50f) membar #Sync
+3:	FREG_FROB(f4, f6, f8, f10,f12,f14,f16,f18,f20)
+	STORE_SYNC(o0, f48) membar #Sync
+	FREG_FROB(f20,f22,f24,f26,f28,f30,f32,f34,f36)
+	STORE_JUMP(o0, f48, 58f) membar #Sync
+
+1:	FREG_FROB(f6, f8, f10,f12,f14,f16,f18,f20,f22)
+	LOOP_CHUNK1(o1, o0, o4, 1f)
+	FREG_FROB(f22,f24,f26,f28,f30,f32,f34,f36,f38)
+	LOOP_CHUNK2(o1, o0, o4, 2f)
+	FREG_FROB(f38,f40,f42,f44,f46,f0, f2, f4, f6) 
+	LOOP_CHUNK3(o1, o0, o4, 3f)
+	ba,pt		%xcc, 1b+4
+	 faligndata	%f6, %f8, %f48
+1:	FREG_FROB(f22,f24,f26,f28,f30,f32,f34,f36,f38)
+	STORE_SYNC(o0, f48) membar #Sync
+	FREG_FROB(f38,f40,f42,f44,f46,f0, f2, f4, f6)
+	STORE_JUMP(o0, f48, 43f) membar #Sync
+2:	FREG_FROB(f38,f40,f42,f44,f46,f0, f2, f4, f6)
+	STORE_SYNC(o0, f48) membar #Sync
+	FREG_FROB(f6, f8, f10,f12,f14,f16,f18,f20,f22)
+	STORE_JUMP(o0, f48, 51f) membar #Sync
+3:	FREG_FROB(f6, f8, f10,f12,f14,f16,f18,f20,f22)
+	STORE_SYNC(o0, f48) membar #Sync
+	FREG_FROB(f22,f24,f26,f28,f30,f32,f34,f36,f38)
+	STORE_JUMP(o0, f48, 59f) membar #Sync
+
+1:	FREG_FROB(f8, f10,f12,f14,f16,f18,f20,f22,f24)
+	LOOP_CHUNK1(o1, o0, o4, 1f)
+	FREG_FROB(f24,f26,f28,f30,f32,f34,f36,f38,f40)
+	LOOP_CHUNK2(o1, o0, o4, 2f)
+	FREG_FROB(f40,f42,f44,f46,f0, f2, f4, f6, f8)
+	LOOP_CHUNK3(o1, o0, o4, 3f)
+	ba,pt		%xcc, 1b+4
+	 faligndata	%f8, %f10, %f48
+1:	FREG_FROB(f24,f26,f28,f30,f32,f34,f36,f38,f40)
+	STORE_SYNC(o0, f48) membar #Sync
+	FREG_FROB(f40,f42,f44,f46,f0, f2, f4, f6, f8)
+	STORE_JUMP(o0, f48, 44f) membar #Sync
+2:	FREG_FROB(f40,f42,f44,f46,f0, f2, f4, f6, f8)
+	STORE_SYNC(o0, f48) membar #Sync
+	FREG_FROB(f8, f10,f12,f14,f16,f18,f20,f22,f24)
+	STORE_JUMP(o0, f48, 52f) membar #Sync
+3:	FREG_FROB(f8, f10,f12,f14,f16,f18,f20,f22,f24)
+	STORE_SYNC(o0, f48) membar #Sync
+	FREG_FROB(f24,f26,f28,f30,f32,f34,f36,f38,f40)
+	STORE_JUMP(o0, f48, 60f) membar #Sync
+
+1:	FREG_FROB(f10,f12,f14,f16,f18,f20,f22,f24,f26)
+	LOOP_CHUNK1(o1, o0, o4, 1f)
+	FREG_FROB(f26,f28,f30,f32,f34,f36,f38,f40,f42)
+	LOOP_CHUNK2(o1, o0, o4, 2f)
+	FREG_FROB(f42,f44,f46,f0, f2, f4, f6, f8, f10)
+	LOOP_CHUNK3(o1, o0, o4, 3f)
+	ba,pt		%xcc, 1b+4
+	 faligndata	%f10, %f12, %f48
+1:	FREG_FROB(f26,f28,f30,f32,f34,f36,f38,f40,f42)
+	STORE_SYNC(o0, f48) membar #Sync
+	FREG_FROB(f42,f44,f46,f0, f2, f4, f6, f8, f10)
+	STORE_JUMP(o0, f48, 45f) membar #Sync
+2:	FREG_FROB(f42,f44,f46,f0, f2, f4, f6, f8, f10)
+	STORE_SYNC(o0, f48) membar #Sync
+	FREG_FROB(f10,f12,f14,f16,f18,f20,f22,f24,f26)
+	STORE_JUMP(o0, f48, 53f) membar #Sync
+3:	FREG_FROB(f10,f12,f14,f16,f18,f20,f22,f24,f26)
+	STORE_SYNC(o0, f48) membar #Sync
+	FREG_FROB(f26,f28,f30,f32,f34,f36,f38,f40,f42)
+	STORE_JUMP(o0, f48, 61f) membar #Sync
+
+1:	FREG_FROB(f12,f14,f16,f18,f20,f22,f24,f26,f28)
+	LOOP_CHUNK1(o1, o0, o4, 1f)
+	FREG_FROB(f28,f30,f32,f34,f36,f38,f40,f42,f44)
+	LOOP_CHUNK2(o1, o0, o4, 2f)
+	FREG_FROB(f44,f46,f0, f2, f4, f6, f8, f10,f12)
+	LOOP_CHUNK3(o1, o0, o4, 3f)
+	ba,pt		%xcc, 1b+4
+	 faligndata	%f12, %f14, %f48
+1:	FREG_FROB(f28,f30,f32,f34,f36,f38,f40,f42,f44)
+	STORE_SYNC(o0, f48) membar #Sync
+	FREG_FROB(f44,f46,f0, f2, f4, f6, f8, f10,f12)
+	STORE_JUMP(o0, f48, 46f) membar #Sync
+2:	FREG_FROB(f44,f46,f0, f2, f4, f6, f8, f10,f12)
+	STORE_SYNC(o0, f48) membar #Sync
+	FREG_FROB(f12,f14,f16,f18,f20,f22,f24,f26,f28)
+	STORE_JUMP(o0, f48, 54f) membar #Sync
+3:	FREG_FROB(f12,f14,f16,f18,f20,f22,f24,f26,f28)
+	STORE_SYNC(o0, f48) membar #Sync
+	FREG_FROB(f28,f30,f32,f34,f36,f38,f40,f42,f44)
+	STORE_JUMP(o0, f48, 62f) membar #Sync
+
+1:	FREG_FROB(f14,f16,f18,f20,f22,f24,f26,f28,f30)
+	LOOP_CHUNK1(o1, o0, o4, 1f)
+	FREG_FROB(f30,f32,f34,f36,f38,f40,f42,f44,f46)
+	LOOP_CHUNK2(o1, o0, o4, 2f)
+	FREG_FROB(f46,f0, f2, f4, f6, f8, f10,f12,f14)
+	LOOP_CHUNK3(o1, o0, o4, 3f)
+	ba,pt		%xcc, 1b+4
+	 faligndata	%f14, %f16, %f48
+1:	FREG_FROB(f30,f32,f34,f36,f38,f40,f42,f44,f46)
+	STORE_SYNC(o0, f48) membar #Sync
+	FREG_FROB(f46,f0, f2, f4, f6, f8, f10,f12,f14)
+	STORE_JUMP(o0, f48, 47f) membar #Sync
+2:	FREG_FROB(f46,f0, f2, f4, f6, f8, f10,f12,f14)
+	STORE_SYNC(o0, f48) membar #Sync
+	FREG_FROB(f14,f16,f18,f20,f22,f24,f26,f28,f30)
+	STORE_JUMP(o0, f48, 55f) membar #Sync
+3:	FREG_FROB(f14,f16,f18,f20,f22,f24,f26,f28,f30)
+	STORE_SYNC(o0, f48) membar #Sync
+	FREG_FROB(f30,f32,f34,f36,f38,f40,f42,f44,f46)
+	STORE_JUMP(o0, f48, 63f) membar #Sync
+
+40:	FINISH_VISCHUNK(o0, f0,  f2,  g3)
+41:	FINISH_VISCHUNK(o0, f2,  f4,  g3)
+42:	FINISH_VISCHUNK(o0, f4,  f6,  g3)
+43:	FINISH_VISCHUNK(o0, f6,  f8,  g3)
+44:	FINISH_VISCHUNK(o0, f8,  f10, g3)
+45:	FINISH_VISCHUNK(o0, f10, f12, g3)
+46:	FINISH_VISCHUNK(o0, f12, f14, g3)
+47:	UNEVEN_VISCHUNK(o0, f14, f0,  g3)
+48:	FINISH_VISCHUNK(o0, f16, f18, g3)
+49:	FINISH_VISCHUNK(o0, f18, f20, g3)
+50:	FINISH_VISCHUNK(o0, f20, f22, g3)
+51:	FINISH_VISCHUNK(o0, f22, f24, g3)
+52:	FINISH_VISCHUNK(o0, f24, f26, g3)
+53:	FINISH_VISCHUNK(o0, f26, f28, g3)
+54:	FINISH_VISCHUNK(o0, f28, f30, g3)
+55:	UNEVEN_VISCHUNK(o0, f30, f0,  g3)
+56:	FINISH_VISCHUNK(o0, f32, f34, g3)
+57:	FINISH_VISCHUNK(o0, f34, f36, g3)
+58:	FINISH_VISCHUNK(o0, f36, f38, g3)
+59:	FINISH_VISCHUNK(o0, f38, f40, g3)
+60:	FINISH_VISCHUNK(o0, f40, f42, g3)
+61:	FINISH_VISCHUNK(o0, f42, f44, g3)
+62:	FINISH_VISCHUNK(o0, f44, f46, g3)
+63:	UNEVEN_VISCHUNK_LAST(o0, f46, f0,  g3)
+
+93:	EX_LD(LOAD(ldd, %o1, %f2))
+	add		%o1, 8, %o1
+	subcc		%g3, 8, %g3
+	faligndata	%f0, %f2, %f8
+	EX_ST(STORE(std, %f8, %o0))
+	bl,pn		%xcc, 95f
+	 add		%o0, 8, %o0
+	EX_LD(LOAD(ldd, %o1, %f0))
+	add		%o1, 8, %o1
+	subcc		%g3, 8, %g3
+	faligndata	%f2, %f0, %f8
+	EX_ST(STORE(std, %f8, %o0))
+	bge,pt		%xcc, 93b
+	 add		%o0, 8, %o0
+
+95:	brz,pt		%o2, 2f
+	 mov		%g1, %o1
+
+1:	EX_LD(LOAD(ldub, %o1, %o3))
+	add		%o1, 1, %o1
+	subcc		%o2, 1, %o2
+	EX_ST(STORE(stb, %o3, %o0))
+	bne,pt		%xcc, 1b
+	 add		%o0, 1, %o0
+
+2:	membar		#StoreLoad | #StoreStore
+	VISExit
+	retl
+	 mov		EX_RETVAL(%g5), %o0
+
+	.align		64
+70:	/* 16 < len <= (5 * 64) */
+	bne,pn		%XCC, 75f
+	 sub		%o0, %o1, %o3
+
+72:	andn		%o2, 0xf, %o4
+	and		%o2, 0xf, %o2
+1:	EX_LD(LOAD(ldx, %o1 + 0x00, %o5))
+	EX_LD(LOAD(ldx, %o1 + 0x08, %g1))
+	subcc		%o4, 0x10, %o4
+	EX_ST(STORE(stx, %o5, %o1 + %o3))
+	add		%o1, 0x8, %o1
+	EX_ST(STORE(stx, %g1, %o1 + %o3))
+	bgu,pt		%XCC, 1b
+	 add		%o1, 0x8, %o1
+73:	andcc		%o2, 0x8, %g0
+	be,pt		%XCC, 1f
+	 nop
+	EX_LD(LOAD(ldx, %o1, %o5))
+	sub		%o2, 0x8, %o2
+	EX_ST(STORE(stx, %o5, %o1 + %o3))
+	add		%o1, 0x8, %o1
+1:	andcc		%o2, 0x4, %g0
+	be,pt		%XCC, 1f
+	 nop
+	EX_LD(LOAD(lduw, %o1, %o5))
+	sub		%o2, 0x4, %o2
+	EX_ST(STORE(stw, %o5, %o1 + %o3))
+	add		%o1, 0x4, %o1
+1:	cmp		%o2, 0
+	be,pt		%XCC, 85f
+	 nop
+	ba,pt		%xcc, 90f
+	 nop
+
+75:	andcc		%o0, 0x7, %g1
+	sub		%g1, 0x8, %g1
+	be,pn		%icc, 2f
+	 sub		%g0, %g1, %g1
+	sub		%o2, %g1, %o2
+
+1:	EX_LD(LOAD(ldub, %o1, %o5))
+	subcc		%g1, 1, %g1
+	EX_ST(STORE(stb, %o5, %o1 + %o3))
+	bgu,pt		%icc, 1b
+	 add		%o1, 1, %o1
+
+2:	add		%o1, %o3, %o0
+	andcc		%o1, 0x7, %g1
+	bne,pt		%icc, 8f
+	 sll		%g1, 3, %g1
+
+	cmp		%o2, 16
+	bgeu,pt		%icc, 72b
+	 nop
+	ba,a,pt		%xcc, 73b
+
+8:	mov		64, %o3
+	andn		%o1, 0x7, %o1
+	EX_LD(LOAD(ldx, %o1, %g2))
+	sub		%o3, %g1, %o3
+	andn		%o2, 0x7, %o4
+	sllx		%g2, %g1, %g2
+1:	EX_LD(LOAD(ldx, %o1 + 0x8, %g3))
+	subcc		%o4, 0x8, %o4
+	add		%o1, 0x8, %o1
+	srlx		%g3, %o3, %o5
+	or		%o5, %g2, %o5
+	EX_ST(STORE(stx, %o5, %o0))
+	add		%o0, 0x8, %o0
+	bgu,pt		%icc, 1b
+	 sllx		%g3, %g1, %g2
+
+	srl		%g1, 3, %g1
+	andcc		%o2, 0x7, %o2
+	be,pn		%icc, 85f
+	 add		%o1, %g1, %o1
+	ba,pt		%xcc, 90f
+	 sub		%o0, %o1, %o3
+
+	.align		64
+80:	/* 0 < len <= 16 */
+	andcc		%o3, 0x3, %g0
+	bne,pn		%XCC, 90f
+	 sub		%o0, %o1, %o3
+
+1:	EX_LD(LOAD(lduw, %o1, %g1))
+	subcc		%o2, 4, %o2
+	EX_ST(STORE(stw, %g1, %o1 + %o3))
+	bgu,pt		%XCC, 1b
+	 add		%o1, 4, %o1
+
+85:	retl
+	 mov		EX_RETVAL(%g5), %o0
+
+	.align		32
+90:	EX_LD(LOAD(ldub, %o1, %g1))
+	subcc		%o2, 1, %o2
+	EX_ST(STORE(stb, %g1, %o1 + %o3))
+	bgu,pt		%XCC, 90b
+	 add		%o1, 1, %o1
+	retl
+	 mov		EX_RETVAL(%g5), %o0
+
+	.size		FUNC_NAME, .-FUNC_NAME
diff -Nru a/arch/sparc64/lib/U3copy_from_user.S b/arch/sparc64/lib/U3copy_from_user.S
--- a/arch/sparc64/lib/U3copy_from_user.S	2004-10-18 14:56:17 -07:00
+++ b/arch/sparc64/lib/U3copy_from_user.S	2004-10-18 14:56:17 -07:00
@@ -3,410 +3,20 @@
  * Copyright (C) 1999, 2000, 2004 David S. Miller (davem@redhat.com)
  */
 
-#include <asm/visasm.h>
-#include <asm/asi.h>
-#include <asm/dcu.h>
-#include <asm/spitfire.h>
+#define EX_LD(x)		\
+98:	x;			\
+	.section .fixup;	\
+	.align 4;		\
+99:	retl;			\
+	 mov	1, %o0;		\
+	.section __ex_table;	\
+	.align 4;		\
+	.word 98b, 99b;		\
+	.text;			\
+	.align 4;
+
+#define FUNC_NAME		U3copy_from_user
+#define LOAD(type,addr,dest)	type##a [addr] %asi, dest
+#define EX_RETVAL(x)		0
 
-#define XCC xcc
-
-#define EXNV_RAW(x,y,a,b)		\
-98:	x,y;				\
-	.section .fixup;		\
-	.align 4;			\
-99:	ba U3cfu_fixup;			\
-	 a, b, %o1;			\
-	.section __ex_table;		\
-	.align 4;			\
-	.word 98b, 99b;			\
-	.text;				\
-	.align 4;
-#define EXNV(x,y,a,b)			\
-98:	x,y;				\
-	.section .fixup;		\
-	.align 4;			\
-99:	add %o1, %o3, %o0;		\
-	ba U3cfu_fixup;			\
-	 a, b, %o1;			\
-	.section __ex_table;		\
-	.align 4;			\
-	.word 98b, 99b;			\
-	.text;				\
-	.align 4;
-#define EXNV4(x,y,a,b)			\
-98:	x,y;				\
-	.section .fixup;		\
-	.align 4;			\
-99:	add %o1, %o3, %o0;		\
-	a, b, %o1;			\
-	ba U3cfu_fixup;			\
-	 add %o1, 4, %o1;		\
-	.section __ex_table;		\
-	.align 4;			\
-	.word 98b, 99b;			\
-	.text;				\
-	.align 4;
-#define EXNV8(x,y,a,b)			\
-98:	x,y;				\
-	.section .fixup;		\
-	.align 4;			\
-99:	add %o1, %o3, %o0;		\
-	a, b, %o1;			\
-	ba U3cfu_fixup;			\
-	 add %o1, 8, %o1;		\
-	.section __ex_table;		\
-	.align 4;			\
-	.word 98b, 99b;			\
-	.text;				\
-	.align 4;
-#define EX(x,y,a,b)			\
-98:	x,y;				\
-	.section .fixup;		\
-	.align 4;			\
-99:	VISExitHalf;			\
-	ba U3cfu_fixup;			\
-	 a, b, %o1;			\
-	.section __ex_table;		\
-	.align 4;			\
-	.word 98b, 99b;			\
-	.text;				\
-	.align 4;
-#define EX2(x,y)			\
-98:	x,y;				\
-	.section .fixup;		\
-	.align 4;			\
-99:	VISExitHalf;			\
-	and %o2, (0x40 - 1), %o1;	\
-	add %o1, %o4, %o1;		\
-	ba U3cfu_fixup;			\
-	 add %o1, 0x1c0, %o1;		\
-	.section __ex_table;		\
-	.align 4;			\
-	.word 98b, 99b;			\
-	.text;				\
-	.align 4;
-#define EX3(x,y)			\
-98:	x,y;				\
-	.section .fixup;		\
-	.align 4;			\
-99:	VISExitHalf;			\
-	and %o2, (0x40 - 1), %o1;	\
-	sll %g3, 6, %g3;		\
-	add %o1, 0x80, %o1;		\
-	ba U3cfu_fixup;			\
-	 add %o1, %g3, %o1;		\
-	.section __ex_table;		\
-	.align 4;			\
-	.word 98b, 99b;			\
-	.text;				\
-	.align 4;
-#define EX4(x,y)			\
-98:	x,y;				\
-	.section .fixup;		\
-	.align 4;			\
-99:	VISExitHalf;			\
-	and %o2, (0x40 - 1), %o1;	\
-	add %o1, 0x40, %o1;		\
-	ba U3cfu_fixup;			\
-	 add %o1, %g3, %o1;		\
-	.section __ex_table;		\
-	.align 4;			\
-	.word 98b, 99b;			\
-	.text;				\
-	.align 4;
-
-	.register	%g2,#scratch
-	.register	%g3,#scratch
-
-	/* Special/non-trivial issues of this code:
-	 *
-	 * 1) %o5 is preserved from VISEntryHalf to VISExitHalf
-	 * 2) Only low 32 FPU registers are used so that only the
-	 *    lower half of the FPU register set is dirtied by this
-	 *    code.  This is especially important in the kernel.
-	 * 3) This code never prefetches cachelines past the end
-	 *    of the source buffer.
-	 */
-
-	.text
-	.align	32
-
-	/* The cheetah's flexible spine, oversized liver, enlarged heart,
-	 * slender muscular body, and claws make it the swiftest hunter
-	 * in Africa and the fastest animal on land.  Can reach speeds
-	 * of up to 2.4GB per second.
-	 */
-
-	.globl	U3copy_from_user
-U3copy_from_user:	/* %o0=dst, %o1=src, %o2=len */
-	cmp		%o2, 0
-	be,pn		%XCC, 85f
-	 or		%o0, %o1, %o3
-	cmp		%o2, 16
-	bleu,a,pn	%XCC, 80f
-	 or		%o3, %o2, %o3
-
-	cmp		%o2, 256
-	blu,pt		%XCC, 70f
-	 andcc		%o3, 0x7, %g0
-
-	ba,pt		%xcc, 1f
-	 andcc		%o0, 0x3f, %g2
-
-	/* Here len >= 256 and condition codes reflect execution
-	 * of "andcc %o0, 0x7, %g2", done by caller.
-	 */
-	.align		64
-1:
-	/* Is 'dst' already aligned on an 64-byte boundary? */
-	be,pt		%XCC, 2f
-
-	/* Compute abs((dst & 0x3f) - 0x40) into %g2.  This is the number
-	 * of bytes to copy to make 'dst' 64-byte aligned.  We pre-
-	 * subtract this from 'len'.
-	 */
-	 sub		%g2, 0x40, %g2
-	sub		%g0, %g2, %g2
-	sub		%o2, %g2, %o2
-
-	/* Copy %g2 bytes from src to dst, one byte at a time. */
-1:	EXNV_RAW(lduba [%o1 + 0x00] %asi, %o3, add %o2, %g2)
-	add		%o1, 0x1, %o1
-	add		%o0, 0x1, %o0
-	subcc		%g2, 0x1, %g2
-
-	bg,pt		%XCC, 1b
-	 stb		%o3, [%o0 + -1]
-
-2:	VISEntryHalf
-	and		%o1, 0x7, %g1
-	ba,pt		%xcc, 1f
-	 alignaddr	%o1, %g0, %o1
-
-	.align		64
-1:
-	membar		#StoreLoad | #StoreStore | #LoadStore
-	prefetcha	[%o1 + 0x000] %asi, #one_read
-	prefetcha	[%o1 + 0x040] %asi, #one_read
-	andn		%o2, (0x40 - 1), %o4
-	prefetcha	[%o1 + 0x080] %asi, #one_read
-	prefetcha	[%o1 + 0x0c0] %asi, #one_read
-	EX(ldda [%o1 + 0x000] %asi, %f0, add %o2, %g0)
-	prefetcha	[%o1 + 0x100] %asi, #one_read
-	EX(ldda [%o1 + 0x008] %asi, %f2, add %o2, %g0)
-	prefetcha	[%o1 + 0x140] %asi, #one_read
-	EX(ldda [%o1 + 0x010] %asi, %f4, add %o2, %g0)
-	prefetcha	[%o1 + 0x180] %asi, #one_read
-	faligndata	%f0, %f2, %f16
-	EX(ldda [%o1 + 0x018] %asi, %f6, add %o2, %g0)
-	faligndata	%f2, %f4, %f18
-	EX(ldda [%o1 + 0x020] %asi, %f8, add %o2, %g0)
-	faligndata	%f4, %f6, %f20
-	EX(ldda [%o1 + 0x028] %asi, %f10, add %o2, %g0)
-	faligndata	%f6, %f8, %f22
-
-	EX(ldda [%o1 + 0x030] %asi, %f12, add %o2, %g0)
-	faligndata	%f8, %f10, %f24
-	EX(ldda [%o1 + 0x038] %asi, %f14, add %o2, %g0)
-	faligndata	%f10, %f12, %f26
-	EX(ldda [%o1 + 0x040] %asi, %f0, add %o2, %g0)
-
-	sub		%o4, 0x80, %o4
-	add		%o1, 0x40, %o1
-	ba,pt		%xcc, 1f
-	 srl		%o4, 6, %o3
-
-	.align		64
-1:
-	EX3(ldda [%o1 + 0x008] %asi, %f2)
-	faligndata	%f12, %f14, %f28
-	EX3(ldda [%o1 + 0x010] %asi, %f4)
-	faligndata	%f14, %f0, %f30
-	stda		%f16, [%o0] ASI_BLK_P
-	EX3(ldda [%o1 + 0x018] %asi, %f6)
-	faligndata	%f0, %f2, %f16
-
-	EX3(ldda [%o1 + 0x020] %asi, %f8)
-	faligndata	%f2, %f4, %f18
-	EX3(ldda [%o1 + 0x028] %asi, %f10)
-	faligndata	%f4, %f6, %f20
-	EX3(ldda [%o1 + 0x030] %asi, %f12)
-	faligndata	%f6, %f8, %f22
-	EX3(ldda [%o1 + 0x038] %asi, %f14)
-	faligndata	%f8, %f10, %f24
-
-	EX3(ldda [%o1 + 0x040] %asi, %f0)
-	prefetcha	[%o1 + 0x180] %asi, #one_read
-	faligndata	%f10, %f12, %f26
-	subcc		%o3, 0x01, %o3
-	add		%o1, 0x40, %o1
-	bg,pt		%XCC, 1b
-	 add		%o0, 0x40, %o0
-
-	/* Finally we copy the last full 64-byte block. */
-	EX3(ldda [%o1 + 0x008] %asi, %f2)
-	faligndata	%f12, %f14, %f28
-	EX3(ldda [%o1 + 0x010] %asi, %f4)
-	faligndata	%f14, %f0, %f30
-	stda		%f16, [%o0] ASI_BLK_P
-	EX3(ldda [%o1 + 0x018] %asi, %f6)
-	faligndata	%f0, %f2, %f16
-	EX3(ldda [%o1 + 0x020] %asi, %f8)
-	faligndata	%f2, %f4, %f18
-	EX3(ldda [%o1 + 0x028] %asi, %f10)
-	faligndata	%f4, %f6, %f20
-	EX3(ldda [%o1 + 0x030] %asi, %f12)
-	faligndata	%f6, %f8, %f22
-	EX3(ldda [%o1 + 0x038] %asi, %f14)
-	faligndata	%f8, %f10, %f24
-	cmp		%g1, 0
-	be,pt		%XCC, 1f
-	 add		%o0, 0x40, %o0
-	EX4(ldda [%o1 + 0x040] %asi, %f0)
-1:	faligndata	%f10, %f12, %f26
-	faligndata	%f12, %f14, %f28
-	faligndata	%f14, %f0, %f30
-	stda		%f16, [%o0] ASI_BLK_P
-	add		%o0, 0x40, %o0
-	add		%o1, 0x40, %o1
-
-	membar		#Sync
-
-	/* Now we copy the (len modulo 64) bytes at the end.
-	 * Note how we borrow the %f0 loaded above.
-	 *
-	 * Also notice how this code is careful not to perform a
-	 * load past the end of the src buffer.
-	 */
-	and		%o2, 0x3f, %o2
-	andcc		%o2, 0x38, %g2
-	be,pn		%XCC, 10f
-	 subcc		%g2, 0x8, %g2
-	be,pn		%XCC, 10f
-	 cmp		%g1, 0
-
-	be,a,pt		%XCC, 1f
-	 EX(ldda [%o1 + 0x00] %asi, %f0, add %o2, %g0)
-
-1:	EX(ldda [%o1 + 0x08] %asi, %f2, add %o2, %g0)
-	add		%o1, 0x8, %o1
-	sub		%o2, 0x8, %o2
-	subcc		%g2, 0x8, %g2
-	faligndata	%f0, %f2, %f8
-	std		%f8, [%o0 + 0x00]
-	be,pn		%XCC, 10f
-	 add		%o0, 0x8, %o0
-	EX(ldda [%o1 + 0x08] %asi, %f0, add %o2, %g0)
-	add		%o1, 0x8, %o1
-	sub		%o2, 0x8, %o2
-	subcc		%g2, 0x8, %g2
-	faligndata	%f2, %f0, %f8
-	std		%f8, [%o0 + 0x00]
-	bne,pn		%XCC, 1b
-	 add		%o0, 0x8, %o0
-
-	/* If anything is left, we copy it one byte at a time.
-	 * Note that %g1 is (src & 0x3) saved above before the
-	 * alignaddr was performed.
-	 */
-10:
-	cmp		%o2, 0
-	add		%o1, %g1, %o1
-	VISExitHalf
-	be,pn		%XCC, 85f
-	 sub		%o0, %o1, %o3
-
-	andcc		%g1, 0x7, %g0
-	bne,pn		%icc, 90f
-	 andcc		%o2, 0x8, %g0
-	be,pt		%icc, 1f
-	 nop
-	EXNV(ldxa [%o1] %asi, %o5, add %o2, %g0)
-	stx		%o5, [%o1 + %o3]
-	add		%o1, 0x8, %o1
-
-1:	andcc		%o2, 0x4, %g0
-	be,pt		%icc, 1f
-	 nop
-	EXNV(lduwa [%o1] %asi, %o5, and %o2, 0x7)
-	stw		%o5, [%o1 + %o3]
-	add		%o1, 0x4, %o1
-
-1:	andcc		%o2, 0x2, %g0
-	be,pt		%icc, 1f
-	 nop
-	EXNV(lduha [%o1] %asi, %o5, and %o2, 0x3)
-	sth		%o5, [%o1 + %o3]
-	add		%o1, 0x2, %o1
-
-1:	andcc		%o2, 0x1, %g0
-	be,pt		%icc, 85f
-	 nop
-	EXNV(lduba [%o1] %asi, %o5, and %o2, 0x1)
-	ba,pt		%xcc, 85f
-	 stb		%o5, [%o1 + %o3]
-
-70: /* 16 < len <= 64 */
-	bne,pn		%XCC, 90f
-	 sub		%o0, %o1, %o3
-
-	andn		%o2, 0x7, %o4
-	and		%o2, 0x7, %o2
-1:	subcc		%o4, 0x8, %o4
-	EXNV8(ldxa [%o1] %asi, %o5, add %o2, %o4)
-	stx		%o5, [%o1 + %o3]
-	bgu,pt		%XCC, 1b
-	 add		%o1, 0x8, %o1
-	andcc		%o2, 0x4, %g0
-	be,pt		%XCC, 1f
-	 nop
-	sub		%o2, 0x4, %o2
-	EXNV4(lduwa [%o1] %asi, %o5, add %o2, %g0)
-	stw		%o5, [%o1 + %o3]
-	add		%o1, 0x4, %o1
-1:	cmp		%o2, 0
-	be,pt		%XCC, 85f
-	 nop
-	ba,pt		%xcc, 90f
-	 nop
-
-80: /* 0 < len <= 16 */
-	andcc		%o3, 0x3, %g0
-	bne,pn		%XCC, 90f
-	 sub		%o0, %o1, %o3
-
-1:
-	subcc		%o2, 4, %o2
-	EXNV(lduwa [%o1] %asi, %g1, add %o2, %g0)
-	stw		%g1, [%o1 + %o3]
-	bgu,pt		%XCC, 1b
-	 add		%o1, 4, %o1
-
-85:	retl
-	 clr		%o0
-
-	.align	32
-90:
-	subcc		%o2, 1, %o2
-	EXNV(lduba [%o1] %asi, %g1, add %o2, %g0)
-	stb		%g1, [%o1 + %o3]
-	bgu,pt		%XCC, 90b
-	 add		%o1, 1, %o1
-	retl
-	 clr		%o0
-
-U3cfu_fixup:
-	/* Since this is copy_from_user(), zero out the rest of the
-	 * kernel buffer.
-	 */
-	cmp		%o1, 0
-	ble,pn		%icc, 2f
-	 mov		%o1, %g2
-
-1:	subcc		%g2, 1, %g2
-	stb		%g0, [%o0]
-	bne,pt		%icc, 1b
-	 add		%o0, 1, %o0
-
-2:	retl
-	 mov		%o1, %o0
+#include "U3memcpy.S"
diff -Nru a/arch/sparc64/lib/U3copy_in_user.S b/arch/sparc64/lib/U3copy_in_user.S
--- a/arch/sparc64/lib/U3copy_in_user.S	2004-10-18 14:56:28 -07:00
+++ /dev/null	Wed Dec 31 16:00:00 196900
@@ -1,140 +0,0 @@
-/* U3copy_in_user.S: UltraSparc-III optimized memcpy.
- *
- * Copyright (C) 1999, 2000, 2004 David S. Miller (davem@redhat.com)
- */
-
-#include <asm/visasm.h>
-#include <asm/asi.h>
-#include <asm/dcu.h>
-#include <asm/spitfire.h>
-
-#define XCC xcc
-
-#define EXNV(x,y,a,b)	\
-98:	x,y;				\
-	.section .fixup;		\
-	.align 4;			\
-99:	retl;				\
-	 a, b, %o0;			\
-	.section __ex_table;		\
-	.align 4;			\
-	.word 98b, 99b;			\
-	.text;				\
-	.align 4;
-#define EXNV1(x,y,a,b)			\
-98:	x,y;				\
-	.section .fixup;		\
-	.align 4;			\
-99:	a, b, %o0;			\
-	retl;				\
-	 add %o0, 1, %o0;		\
-	.section __ex_table;		\
-	.align 4;			\
-	.word 98b, 99b;			\
-	.text;				\
-	.align 4;
-#define EXNV4(x,y,a,b)			\
-98:	x,y;				\
-	.section .fixup;		\
-	.align 4;			\
-99:	a, b, %o0;			\
-	retl;				\
-	 add %o0, 4, %o0;		\
-	.section __ex_table;		\
-	.align 4;			\
-	.word 98b, 99b;			\
-	.text;				\
-	.align 4;
-#define EXNV8(x,y,a,b)			\
-98:	x,y;				\
-	.section .fixup;		\
-	.align 4;			\
-99:	a, b, %o0;			\
-	retl;				\
-	 add %o0, 8, %o0;		\
-	.section __ex_table;		\
-	.align 4;			\
-	.word 98b, 99b;			\
-	.text;				\
-	.align 4;
-
-	.register	%g2,#scratch
-	.register	%g3,#scratch
-
-	.text
-	.align	32
-
-	/* Don't try to get too fancy here, just nice and
-	 * simple.  This is predominantly used for well aligned
-	 * small copies in the compat layer.  It is also used
-	 * to copy register windows around during thread cloning.
-	 */
-
-	.globl	U3copy_in_user
-U3copy_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
-	 * cheap.
-	 */
-	rd		%asi, %g1
-	cmp		%g1, ASI_AIUS
-	bne,pn		%icc, U3memcpy_user_stub
-	 nop
-
-	cmp		%o2, 0
-	be,pn		%XCC, out
-	 or		%o0, %o1, %o3
-	cmp		%o2, 16
-	bleu,a,pn	%XCC, small_copy
-	 or		%o3, %o2, %o3
-
-medium_copy: /* 16 < len <= 64 */
-	andcc		%o3, 0x7, %g0
-	bne,pn		%XCC, small_copy_unaligned
-	 sub		%o0, %o1, %o3
-
-medium_copy_aligned:
-	andn		%o2, 0x7, %o4
-	and		%o2, 0x7, %o2
-1:	subcc		%o4, 0x8, %o4
-	EXNV8(ldxa [%o1] %asi, %o5, add %o4, %o2)
-	EXNV8(stxa %o5, [%o1 + %o3] ASI_AIUS, add %o4, %o2)
-	bgu,pt		%XCC, 1b
-	 add		%o1, 0x8, %o1
-	andcc		%o2, 0x4, %g0
-	be,pt		%XCC, 1f
-	 nop
-	sub		%o2, 0x4, %o2
-	EXNV4(lduwa [%o1] %asi, %o5, add %o4, %o2)
-	EXNV4(stwa %o5, [%o1 + %o3] ASI_AIUS, add %o4, %o2)
-	add		%o1, 0x4, %o1
-1:	cmp		%o2, 0
-	be,pt		%XCC, out
-	 nop
-	ba,pt		%xcc, small_copy_unaligned
-	 nop
-
-small_copy: /* 0 < len <= 16 */
-	andcc		%o3, 0x3, %g0
-	bne,pn		%XCC, small_copy_unaligned
-	 sub		%o0, %o1, %o3
-
-small_copy_aligned:
-	subcc		%o2, 4, %o2
-	EXNV4(lduwa [%o1] %asi, %g1, add %o2, %g0)
-	EXNV4(stwa %g1, [%o1 + %o3] ASI_AIUS, add %o2, %g0)
-	bgu,pt		%XCC, small_copy_aligned
-	 add		%o1, 4, %o1
-
-out:	retl
-	 clr		%o0
-
-	.align	32
-small_copy_unaligned:
-	subcc		%o2, 1, %o2
-	EXNV1(lduba [%o1] %asi, %g1, add %o2, %g0)
-	EXNV1(stba %g1, [%o1 + %o3] ASI_AIUS, add %o2, %g0)
-	bgu,pt		%XCC, small_copy_unaligned
-	 add		%o1, 1, %o1
-	retl
-	 clr		%o0
diff -Nru a/arch/sparc64/lib/U3copy_to_user.S b/arch/sparc64/lib/U3copy_to_user.S
--- a/arch/sparc64/lib/U3copy_to_user.S	2004-10-18 14:55:46 -07:00
+++ b/arch/sparc64/lib/U3copy_to_user.S	2004-10-18 14:55:46 -07:00
@@ -1,415 +1,33 @@
-/* U3copy_to_user.S: UltraSparc-III optimized memcpy.
+/* U3copy_to_user.S: UltraSparc-III optimized copy to userspace.
  *
  * Copyright (C) 1999, 2000, 2004 David S. Miller (davem@redhat.com)
  */
 
-#include <asm/visasm.h>
-#include <asm/asi.h>
-#include <asm/dcu.h>
-#include <asm/spitfire.h>
+#define EX_ST(x)		\
+98:	x;			\
+	.section .fixup;	\
+	.align 4;		\
+99:	retl;			\
+	 mov	1, %o0;		\
+	.section __ex_table;	\
+	.align 4;		\
+	.word 98b, 99b;		\
+	.text;			\
+	.align 4;
+
+#define FUNC_NAME		U3copy_to_user
+#define STORE(type,src,addr)	type##a src, [addr] ASI_AIUS
+#define STORE_BLK(src,addr)	stda src, [addr] ASI_BLK_AIUS
+#define EX_RETVAL(x)		0
 
-#define XCC xcc
-
-#define EXNV(x,y,a,b)	\
-98:	x,y;				\
-	.section .fixup;		\
-	.align 4;			\
-99:	retl;				\
-	 a, b, %o0;			\
-	.section __ex_table;		\
-	.align 4;			\
-	.word 98b, 99b;			\
-	.text;				\
-	.align 4;
-#define EXNV2(x,y,a,b)	\
-98:	x,y;				\
-	.section .fixup;		\
-	.align 4;			\
-99:	a, b, %o0;			\
-	retl;				\
-	 add %o0, 1, %o0;		\
-	.section __ex_table;		\
-	.align 4;			\
-	.word 98b, 99b;			\
-	.text;				\
-	.align 4;
-#define EXNV3(x,y,a,b)	\
-98:	x,y;				\
-	.section .fixup;		\
-	.align 4;			\
-99:	a, b, %o0;			\
-	retl;				\
-	 add %o0, 4, %o0;		\
-	.section __ex_table;		\
-	.align 4;			\
-	.word 98b, 99b;			\
-	.text;				\
-	.align 4;
-#define EXNV4(x,y,a,b)	\
-98:	x,y;				\
-	.section .fixup;		\
-	.align 4;			\
-99:	a, b, %o0;			\
-	retl;				\
-	 add %o0, 8, %o0;		\
-	.section __ex_table;		\
-	.align 4;			\
-	.word 98b, 99b;			\
-	.text;				\
-	.align 4;
-#define EX(x,y,a,b)			\
-98:	x,y;				\
-	.section .fixup;		\
-	.align 4;			\
-99:	VISExitHalf;			\
-	retl;				\
-	 a, b, %o0;			\
-	.section __ex_table;		\
-	.align 4;			\
-	.word 98b, 99b;			\
-	.text;				\
-	.align 4;
-#define EXBLK1(x,y)			\
-98:	x,y;				\
-	.section .fixup;		\
-	.align 4;			\
-99:	VISExitHalf;			\
-	add %o4, 0x1c0, %o1;		\
-	and %o2, (0x40 - 1), %o2;	\
-	retl;				\
-	 add %o1, %o2, %o0;		\
-	.section __ex_table;		\
-	.align 4;			\
-	.word 98b, 99b;			\
-	.text;				\
-	.align 4;
-#define EXBLK2(x,y)			\
-98:	x,y;				\
-	.section .fixup;		\
-	.align 4;			\
-99:	VISExitHalf;			\
-	sll %o3, 6, %o3;		\
-	and %o2, (0x40 - 1), %o2;	\
-	add %o3, 0x80, %o1;		\
-	retl;				\
-	 add %o1, %o2, %o0;		\
-	.section __ex_table;		\
-	.align 4;			\
-	.word 98b, 99b;			\
-	.text;				\
-	.align 4;
-#define EXBLK3(x,y)			\
-98:	x,y;				\
-	.section .fixup;		\
-	.align 4;			\
-99:	VISExitHalf;			\
-	and %o2, (0x40 - 1), %o2;	\
-	retl;				\
-	 add %o2, 0x80, %o0;		\
-	.section __ex_table;		\
-	.align 4;			\
-	.word 98b, 99b;			\
-	.text;				\
-	.align 4;
-#define EXBLK4(x,y)			\
-98:	x,y;				\
-	.section .fixup;		\
-	.align 4;			\
-99:	VISExitHalf;			\
-	and %o2, (0x40 - 1), %o2;	\
-	retl;				\
-	 add %o2, 0x40, %o0;		\
-	.section __ex_table;		\
-	.align 4;			\
-	.word 98b, 99b;			\
-	.text;				\
-	.align 4;
-
-	.register	%g2,#scratch
-	.register	%g3,#scratch
-
-	/* Special/non-trivial issues of this code:
-	 *
-	 * 1) %o5 is preserved from VISEntryHalf to VISExitHalf
-	 * 2) Only low 32 FPU registers are used so that only the
-	 *    lower half of the FPU register set is dirtied by this
-	 *    code.  This is especially important in the kernel.
-	 * 3) This code never prefetches cachelines past the end
-	 *    of the source buffer.
-	 */
-
-	.text
-	.align	32
-
-	/* The cheetah's flexible spine, oversized liver, enlarged heart,
-	 * slender muscular body, and claws make it the swiftest hunter
-	 * in Africa and the fastest animal on land.  Can reach speeds
-	 * of up to 2.4GB per second.
-	 */
-
-	.globl	U3copy_to_user
-U3copy_to_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
 	 * cheap.
 	 */
-	rd		%asi, %g1
-	cmp		%g1, ASI_AIUS
-	bne,pn		%icc, U3memcpy_user_stub
-	 nop
-
-	cmp		%o2, 0
-	be,pn		%XCC, 85f
-	 or		%o0, %o1, %o3
-	cmp		%o2, 16
-	bleu,a,pn	%XCC, 80f
-	 or		%o3, %o2, %o3
-
-	cmp		%o2, 256
-	blu,pt		%XCC, 70f
-	 andcc		%o3, 0x7, %g0
-
-	ba,pt		%xcc, 1f
-	 andcc		%o0, 0x3f, %g2
-
-	/* Here len >= 256 and condition codes reflect execution
-	 * of "andcc %o0, 0x7, %g2", done by caller.
-	 */
-	.align		64
-1:
-	/* Is 'dst' already aligned on an 64-byte boundary? */
-	be,pt		%XCC, 2f
-
-	/* Compute abs((dst & 0x3f) - 0x40) into %g2.  This is the number
-	 * of bytes to copy to make 'dst' 64-byte aligned.  We pre-
-	 * subtract this from 'len'.
-	 */
-	 sub		%g2, 0x40, %g2
-	sub		%g0, %g2, %g2
-	sub		%o2, %g2, %o2
-
-	/* Copy %g2 bytes from src to dst, one byte at a time. */
-1:	ldub		[%o1 + 0x00], %o3
-	add		%o1, 0x1, %o1
-	add		%o0, 0x1, %o0
-	subcc		%g2, 0x1, %g2
-
-	bg,pt		%XCC, 1b
-	 EXNV2(stba %o3, [%o0 + -1] %asi, add %o2, %g2)
-
-2:	VISEntryHalf
-	and		%o1, 0x7, %g1
-	ba,pt		%xcc, 1f
-	 alignaddr	%o1, %g0, %o1
-
-	.align		64
-1:
-	membar		#StoreLoad | #StoreStore | #LoadStore
-	prefetch	[%o1 + 0x000], #one_read
-	prefetch	[%o1 + 0x040], #one_read
-	andn		%o2, (0x40 - 1), %o4
-	prefetch	[%o1 + 0x080], #one_read
-	prefetch	[%o1 + 0x0c0], #one_read
-	ldd		[%o1 + 0x000], %f0
-	prefetch	[%o1 + 0x100], #one_read
-	ldd		[%o1 + 0x008], %f2
-	prefetch	[%o1 + 0x140], #one_read
-	ldd		[%o1 + 0x010], %f4
-	prefetch	[%o1 + 0x180], #one_read
-	faligndata	%f0, %f2, %f16
-	ldd		[%o1 + 0x018], %f6
-	faligndata	%f2, %f4, %f18
-	ldd		[%o1 + 0x020], %f8
-	faligndata	%f4, %f6, %f20
-	ldd		[%o1 + 0x028], %f10
-	faligndata	%f6, %f8, %f22
-
-	ldd		[%o1 + 0x030], %f12
-	faligndata	%f8, %f10, %f24
-	ldd		[%o1 + 0x038], %f14
-	faligndata	%f10, %f12, %f26
-	ldd		[%o1 + 0x040], %f0
-
-	sub		%o4, 0x80, %o4
-	add		%o1, 0x40, %o1
-	ba,pt		%xcc, 1f
-	 srl		%o4, 6, %o3
-
-	.align		64
-1:
-	ldd		[%o1 + 0x008], %f2
-	faligndata	%f12, %f14, %f28
-	ldd		[%o1 + 0x010], %f4
-	faligndata	%f14, %f0, %f30
-	EXBLK2(stda %f16, [%o0] ASI_BLK_AIUS)
-	ldd		[%o1 + 0x018], %f6
-	faligndata	%f0, %f2, %f16
-
-	ldd		[%o1 + 0x020], %f8
-	faligndata	%f2, %f4, %f18
-	ldd		[%o1 + 0x028], %f10
-	faligndata	%f4, %f6, %f20
-	ldd		[%o1 + 0x030], %f12
-	faligndata	%f6, %f8, %f22
-	ldd		[%o1 + 0x038], %f14
-	faligndata	%f8, %f10, %f24
-
-	ldd		[%o1 + 0x040], %f0
-	prefetch	[%o1 + 0x180], #one_read
-	faligndata	%f10, %f12, %f26
-	subcc		%o3, 0x01, %o3
-	add		%o1, 0x40, %o1
-	bg,pt		%XCC, 1b
-	 add		%o0, 0x40, %o0
-
-	/* Finally we copy the last full 64-byte block. */
-	ldd		[%o1 + 0x008], %f2
-	faligndata	%f12, %f14, %f28
-	ldd		[%o1 + 0x010], %f4
-	faligndata	%f14, %f0, %f30
-	EXBLK3(stda %f16, [%o0] ASI_BLK_AIUS)
-	ldd		[%o1 + 0x018], %f6
-	faligndata	%f0, %f2, %f16
-	ldd		[%o1 + 0x020], %f8
-	faligndata	%f2, %f4, %f18
-	ldd		[%o1 + 0x028], %f10
-	faligndata	%f4, %f6, %f20
-	ldd		[%o1 + 0x030], %f12
-	faligndata	%f6, %f8, %f22
-	ldd		[%o1 + 0x038], %f14
-	faligndata	%f8, %f10, %f24
-	cmp		%g1, 0
-	be,pt		%XCC, 1f
-	 add		%o0, 0x40, %o0
-	ldd		[%o1 + 0x040], %f0
-1:	faligndata	%f10, %f12, %f26
-	faligndata	%f12, %f14, %f28
-	faligndata	%f14, %f0, %f30
-	EXBLK4(stda %f16, [%o0] ASI_BLK_AIUS)
-	add		%o0, 0x40, %o0
-	add		%o1, 0x40, %o1
-
-	membar		#Sync
-
-	/* Now we copy the (len modulo 64) bytes at the end.
-	 * Note how we borrow the %f0 loaded above.
-	 *
-	 * Also notice how this code is careful not to perform a
-	 * load past the end of the src buffer.
-	 */
-	and		%o2, 0x3f, %o2
-	andcc		%o2, 0x38, %g2
-	be,pn		%XCC, 2f
-	 subcc		%g2, 0x8, %g2
-	be,pn		%XCC, 2f
-	 cmp		%g1, 0
-
-	be,a,pt		%XCC, 1f
-	 ldd		[%o1 + 0x00], %f0
-
-1:	ldd		[%o1 + 0x08], %f2
-	add		%o1, 0x8, %o1
-	sub		%o2, 0x8, %o2
-	subcc		%g2, 0x8, %g2
-	faligndata	%f0, %f2, %f8
-	EX(stda %f8, [%o0 + 0x00] %asi, add %o2, 0x8)
-	be,pn		%XCC, 2f
-	 add		%o0, 0x8, %o0
-	ldd		[%o1 + 0x08], %f0
-	add		%o1, 0x8, %o1
-	sub		%o2, 0x8, %o2
-	subcc		%g2, 0x8, %g2
-	faligndata	%f2, %f0, %f8
-	EX(stda %f8, [%o0 + 0x00] %asi, add %o2, 0x8)
-	bne,pn		%XCC, 1b
-	 add		%o0, 0x8, %o0
-
-	/* If anything is left, we copy it one byte at a time.
-	 * Note that %g1 is (src & 0x3) saved above before the
-	 * alignaddr was performed.
-	 */
-2:
-	cmp		%o2, 0
-	add		%o1, %g1, %o1
-	VISExitHalf
-	be,pn		%XCC, 85f
-	 sub		%o0, %o1, %o3
-
-	andcc		%g1, 0x7, %g0
-	bne,pn		%icc, 90f
-	 andcc		%o2, 0x8, %g0
-	be,pt		%icc, 1f
-	 nop
-	ldx		[%o1], %o5
-	EXNV(stxa %o5, [%o1 + %o3] ASI_AIUS, add %o2, %g0)
-	add		%o1, 0x8, %o1
-
-1:	andcc		%o2, 0x4, %g0
-	be,pt		%icc, 1f
-	 nop
-	lduw		[%o1], %o5
-	EXNV(stwa %o5, [%o1 + %o3] ASI_AIUS, and %o2, 0x7)
-	add		%o1, 0x4, %o1
-
-1:	andcc		%o2, 0x2, %g0
-	be,pt		%icc, 1f
-	 nop
-	lduh		[%o1], %o5
-	EXNV(stha %o5, [%o1 + %o3] ASI_AIUS, and %o2, 0x3)
-	add		%o1, 0x2, %o1
-
-1:	andcc		%o2, 0x1, %g0
-	be,pt		%icc, 85f
-	 nop
-	ldub		[%o1], %o5
-	ba,pt		%xcc, 85f
-	 EXNV(stba %o5, [%o1 + %o3] ASI_AIUS, and %o2, 0x1)
-
-70: /* 16 < len <= 64 */
-	bne,pn		%XCC, 90f
-	 sub		%o0, %o1, %o3
-
-	andn		%o2, 0x7, %o4
-	and		%o2, 0x7, %o2
-1:	subcc		%o4, 0x8, %o4
-	ldx		[%o1], %o5
-	EXNV4(stxa %o5, [%o1 + %o3] ASI_AIUS, add %o2, %o4)
-	bgu,pt		%XCC, 1b
-	 add		%o1, 0x8, %o1
-	andcc		%o2, 0x4, %g0
-	be,pt		%XCC, 1f
-	 nop
-	sub		%o2, 0x4, %o2
-	lduw		[%o1], %o5
-	EXNV3(stwa %o5, [%o1 + %o3] ASI_AIUS, add %o2, %g0)
-	add		%o1, 0x4, %o1
-1:	cmp		%o2, 0
-	be,pt		%XCC, 85f
-	 nop
-	ba,pt		%xcc, 90f
-	 nop
-
-80: /* 0 < len <= 16 */
-	andcc		%o3, 0x3, %g0
-	bne,pn		%XCC, 90f
-	 sub		%o0, %o1, %o3
-
-1:
-	subcc		%o2, 4, %o2
-	lduw		[%o1], %g1
-	EXNV3(stwa %g1, [%o1 + %o3] ASI_AIUS, add %o2, %g0)
-	bgu,pt		%XCC, 1b
-	 add		%o1, 4, %o1
-
-85:	retl
-	 clr		%o0
+#define PREAMBLE					\
+	rd		%asi, %g1;			\
+	cmp		%g1, ASI_AIUS;			\
+	bne,pn		%icc, memcpy_user_stub;		\
+	 nop;						\
 
-	.align	32
-90:
-	subcc		%o2, 1, %o2
-	ldub		[%o1], %g1
-	EXNV2(stba %g1, [%o1 + %o3] ASI_AIUS, add %o2, %g0)
-	bgu,pt		%XCC, 90b
-	 add		%o1, 1, %o1
-	retl
-	 clr		%o0
+#include "U3memcpy.S"
diff -Nru a/arch/sparc64/lib/U3memcpy.S b/arch/sparc64/lib/U3memcpy.S
--- a/arch/sparc64/lib/U3memcpy.S	2004-10-18 14:57:05 -07:00
+++ b/arch/sparc64/lib/U3memcpy.S	2004-10-18 14:57:05 -07:00
@@ -6,14 +6,50 @@
 #ifdef __KERNEL__
 #include <asm/visasm.h>
 #include <asm/asi.h>
-#include <asm/dcu.h>
-#include <asm/spitfire.h>
 #else
 #define ASI_BLK_P 0xf0
 #define FPRS_FEF  0x04
+#ifdef MEMCPY_DEBUG
+#define VISEntryHalf rd %fprs, %o5; wr %g0, FPRS_FEF, %fprs; \
+		     clr %g1; clr %g2; clr %g3; subcc %g0, %g0, %g0;
+#define VISExitHalf and %o5, FPRS_FEF, %o5; wr %o5, 0x0, %fprs
+#else
 #define VISEntryHalf rd %fprs, %o5; wr %g0, FPRS_FEF, %fprs
 #define VISExitHalf and %o5, FPRS_FEF, %o5; wr %o5, 0x0, %fprs
 #endif
+#endif
+
+#ifndef EX_LD
+#define EX_LD(x)	x
+#endif
+
+#ifndef EX_ST
+#define EX_ST(x)	x
+#endif
+
+#ifndef EX_RETVAL
+#define EX_RETVAL(x)	x
+#endif
+
+#ifndef LOAD
+#define LOAD(type,addr,dest)	type [addr], dest
+#endif
+
+#ifndef STORE
+#define STORE(type,src,addr)	type src, [addr]
+#endif
+
+#ifndef STORE_BLK
+#define STORE_BLK(src,addr)	stda src, [addr] ASI_BLK_P
+#endif
+
+#ifndef FUNC_NAME
+#define FUNC_NAME	U3memcpy
+#endif
+
+#ifndef PREAMBLE
+#define PREAMBLE
+#endif
 
 #ifndef XCC
 #define XCC xcc
@@ -33,7 +69,7 @@
 	 */
 
 	.text
-	.align	32
+	.align		64
 
 	/* The cheetah's flexible spine, oversized liver, enlarged heart,
 	 * slender muscular body, and claws make it the swiftest hunter
@@ -41,137 +77,158 @@
 	 * of up to 2.4GB per second.
 	 */
 
-	.globl	U3memcpy
-U3memcpy:	/* %o0=dst, %o1=src, %o2=len */
+	.globl	FUNC_NAME
+	.type	FUNC_NAME,#function
+FUNC_NAME:	/* %o0=dst, %o1=src, %o2=len */
+	PREAMBLE
 	mov		%o0, %g5
 	cmp		%o2, 0
 	be,pn		%XCC, 85f
 	 or		%o0, %o1, %o3
 	cmp		%o2, 16
-	bleu,a,pn	%XCC, 70f
+	blu,a,pn	%XCC, 80f
 	 or		%o3, %o2, %o3
 
-	cmp		%o2, 256
-	blu,pt		%XCC, 80f
+	cmp		%o2, (3 * 64)
+	blu,pt		%XCC, 70f
 	 andcc		%o3, 0x7, %g0
 
-	ba,pt		%xcc, 1f
-	 andcc		%o0, 0x3f, %g2
-
-	/* Here len >= 256 and condition codes reflect execution
-	 * of "andcc %o0, 0x7, %g2", done by caller.
+	/* Clobbers o5/g1/g2/g3/g7/icc/xcc.  We must preserve
+	 * o5 from here until we hit VISExitHalf.
 	 */
-	.align		64
-1:
+	VISEntryHalf
+
 	/* Is 'dst' already aligned on an 64-byte boundary? */
+	andcc		%o0, 0x3f, %g2
 	be,pt		%XCC, 2f
 
 	/* Compute abs((dst & 0x3f) - 0x40) into %g2.  This is the number
 	 * of bytes to copy to make 'dst' 64-byte aligned.  We pre-
 	 * subtract this from 'len'.
 	 */
-	 sub		%g2, 0x40, %g2
+	 sub		%o0, %o1, %o4
+	sub		%g2, 0x40, %g2
 	sub		%g0, %g2, %g2
 	sub		%o2, %g2, %o2
+	andcc		%g2, 0x7, %g1
+	be,pt		%icc, 2f
+	 and		%g2, 0x38, %g2
+
+1:	subcc		%g1, 0x1, %g1
+	EX_LD(LOAD(ldub, %o1 + 0x00, %o3))
+	EX_ST(STORE(stb, %o3, %o1 + %o4))
+	bgu,pt		%XCC, 1b
+	 add		%o1, 0x1, %o1
 
-	/* Copy %g2 bytes from src to dst, one byte at a time. */
-1:	ldub		[%o1 + 0x00], %o3
-	add		%o1, 0x1, %o1
-	add		%o0, 0x1, %o0
-	subcc		%g2, 0x1, %g2
-
-	bg,pt		%XCC, 1b
-	 stb		%o3, [%o0 + -1]
+	add		%o1, %o4, %o0
 
-2:	VISEntryHalf
+2:	cmp		%g2, 0x0
 	and		%o1, 0x7, %g1
-	ba,pt		%xcc, 1f
+	be,pt		%icc, 3f
 	 alignaddr	%o1, %g0, %o1
 
-	.align		64
-1:
-	membar		#StoreLoad | #StoreStore | #LoadStore
-	prefetch	[%o1 + 0x000], #one_read
-	prefetch	[%o1 + 0x040], #one_read
+	EX_LD(LOAD(ldd, %o1, %f4))
+1:	EX_LD(LOAD(ldd, %o1 + 0x8, %f6))
+	add		%o1, 0x8, %o1
+	subcc		%g2, 0x8, %g2
+	faligndata	%f4, %f6, %f0
+	EX_ST(STORE(std, %f0, %o0))
+	be,pn		%icc, 3f
+	 add		%o0, 0x8, %o0
+
+	EX_LD(LOAD(ldd, %o1 + 0x8, %f4))
+	add		%o1, 0x8, %o1
+	subcc		%g2, 0x8, %g2
+	faligndata	%f6, %f4, %f2
+	EX_ST(STORE(std, %f2, %o0))
+	bne,pt		%icc, 1b
+	 add		%o0, 0x8, %o0
+
+3:	LOAD(prefetch, %o1 + 0x000, #one_read)
+	LOAD(prefetch, %o1 + 0x040, #one_read)
 	andn		%o2, (0x40 - 1), %o4
-	prefetch	[%o1 + 0x080], #one_read
-	prefetch	[%o1 + 0x0c0], #one_read
-	ldd		[%o1 + 0x000], %f0
-	prefetch	[%o1 + 0x100], #one_read
-	ldd		[%o1 + 0x008], %f2
-	prefetch	[%o1 + 0x140], #one_read
-	ldd		[%o1 + 0x010], %f4
-	prefetch	[%o1 + 0x180], #one_read
+	LOAD(prefetch, %o1 + 0x080, #one_read)
+	LOAD(prefetch, %o1 + 0x0c0, #one_read)
+	LOAD(prefetch, %o1 + 0x100, #one_read)
+	EX_LD(LOAD(ldd, %o1 + 0x000, %f0))
+	LOAD(prefetch, %o1 + 0x140, #one_read)
+	EX_LD(LOAD(ldd, %o1 + 0x008, %f2))
+	LOAD(prefetch, %o1 + 0x180, #one_read)
+	EX_LD(LOAD(ldd, %o1 + 0x010, %f4))
+	LOAD(prefetch, %o1 + 0x1c0, #one_read)
 	faligndata	%f0, %f2, %f16
-	ldd		[%o1 + 0x018], %f6
+	EX_LD(LOAD(ldd, %o1 + 0x018, %f6))
 	faligndata	%f2, %f4, %f18
-	ldd		[%o1 + 0x020], %f8
+	EX_LD(LOAD(ldd, %o1 + 0x020, %f8))
 	faligndata	%f4, %f6, %f20
-	ldd		[%o1 + 0x028], %f10
+	EX_LD(LOAD(ldd, %o1 + 0x028, %f10))
 	faligndata	%f6, %f8, %f22
 
-	ldd		[%o1 + 0x030], %f12
+	EX_LD(LOAD(ldd, %o1 + 0x030, %f12))
 	faligndata	%f8, %f10, %f24
-	ldd		[%o1 + 0x038], %f14
+	EX_LD(LOAD(ldd, %o1 + 0x038, %f14))
 	faligndata	%f10, %f12, %f26
-	ldd		[%o1 + 0x040], %f0
+	EX_LD(LOAD(ldd, %o1 + 0x040, %f0))
 
-	sub		%o4, 0x80, %o4
+	subcc		%o4, 0x80, %o4
 	add		%o1, 0x40, %o1
-	ba,pt		%xcc, 1f
+	bgu,pt		%XCC, 1f
 	 srl		%o4, 6, %o3
+	ba,pt		%xcc, 2f
+	 nop
 
 	.align		64
 1:
-	ldd		[%o1 + 0x008], %f2
+	EX_LD(LOAD(ldd, %o1 + 0x008, %f2))
 	faligndata	%f12, %f14, %f28
-	ldd		[%o1 + 0x010], %f4
+	EX_LD(LOAD(ldd, %o1 + 0x010, %f4))
 	faligndata	%f14, %f0, %f30
-	stda		%f16, [%o0] ASI_BLK_P
-	ldd		[%o1 + 0x018], %f6
+	EX_ST(STORE_BLK(%f16, %o0))
+	EX_LD(LOAD(ldd, %o1 + 0x018, %f6))
 	faligndata	%f0, %f2, %f16
+	add		%o0, 0x40, %o0
 
-	ldd		[%o1 + 0x020], %f8
+	EX_LD(LOAD(ldd, %o1 + 0x020, %f8))
 	faligndata	%f2, %f4, %f18
-	ldd		[%o1 + 0x028], %f10
+	EX_LD(LOAD(ldd, %o1 + 0x028, %f10))
 	faligndata	%f4, %f6, %f20
-	ldd		[%o1 + 0x030], %f12
+	EX_LD(LOAD(ldd, %o1 + 0x030, %f12))
+	subcc		%o3, 0x01, %o3
 	faligndata	%f6, %f8, %f22
-	ldd		[%o1 + 0x038], %f14
-	faligndata	%f8, %f10, %f24
+	EX_LD(LOAD(ldd, %o1 + 0x038, %f14))
 
-	ldd		[%o1 + 0x040], %f0
-	prefetch	[%o1 + 0x180], #one_read
+	faligndata	%f8, %f10, %f24
+	EX_LD(LOAD(ldd, %o1 + 0x040, %f0))
+	LOAD(prefetch, %o1 + 0x1c0, #one_read)
 	faligndata	%f10, %f12, %f26
-	subcc		%o3, 0x01, %o3
-	add		%o1, 0x40, %o1
 	bg,pt		%XCC, 1b
-	 add		%o0, 0x40, %o0
+	 add		%o1, 0x40, %o1
 
 	/* Finally we copy the last full 64-byte block. */
-	ldd		[%o1 + 0x008], %f2
+2:
+	EX_LD(LOAD(ldd, %o1 + 0x008, %f2))
 	faligndata	%f12, %f14, %f28
-	ldd		[%o1 + 0x010], %f4
+	EX_LD(LOAD(ldd, %o1 + 0x010, %f4))
 	faligndata	%f14, %f0, %f30
-	stda		%f16, [%o0] ASI_BLK_P
-	ldd		[%o1 + 0x018], %f6
+	EX_ST(STORE_BLK(%f16, %o0))
+	EX_LD(LOAD(ldd, %o1 + 0x018, %f6))
 	faligndata	%f0, %f2, %f16
-	ldd		[%o1 + 0x020], %f8
+	EX_LD(LOAD(ldd, %o1 + 0x020, %f8))
 	faligndata	%f2, %f4, %f18
-	ldd		[%o1 + 0x028], %f10
+	EX_LD(LOAD(ldd, %o1 + 0x028, %f10))
 	faligndata	%f4, %f6, %f20
-	ldd		[%o1 + 0x030], %f12
+	EX_LD(LOAD(ldd, %o1 + 0x030, %f12))
 	faligndata	%f6, %f8, %f22
-	ldd		[%o1 + 0x038], %f14
+	EX_LD(LOAD(ldd, %o1 + 0x038, %f14))
 	faligndata	%f8, %f10, %f24
 	cmp		%g1, 0
 	be,pt		%XCC, 1f
 	 add		%o0, 0x40, %o0
-	ldd		[%o1 + 0x040], %f0
+	EX_LD(LOAD(ldd, %o1 + 0x040, %f0))
 1:	faligndata	%f10, %f12, %f26
 	faligndata	%f12, %f14, %f28
 	faligndata	%f14, %f0, %f30
-	stda		%f16, [%o0] ASI_BLK_P
+	EX_ST(STORE_BLK(%f16, %o0))
 	add		%o0, 0x40, %o0
 	add		%o1, 0x40, %o1
 	membar		#Sync
@@ -189,23 +246,22 @@
 	be,pn		%XCC, 2f
 	 cmp		%g1, 0
 
+	sub		%o2, %g2, %o2
 	be,a,pt		%XCC, 1f
-	 ldd		[%o1 + 0x00], %f0
+	 EX_LD(LOAD(ldd, %o1 + 0x00, %f0))
 
-1:	ldd		[%o1 + 0x08], %f2
+1:	EX_LD(LOAD(ldd, %o1 + 0x08, %f2))
 	add		%o1, 0x8, %o1
-	sub		%o2, 0x8, %o2
 	subcc		%g2, 0x8, %g2
 	faligndata	%f0, %f2, %f8
-	std		%f8, [%o0 + 0x00]
+	EX_ST(STORE(std, %f8, %o0))
 	be,pn		%XCC, 2f
 	 add		%o0, 0x8, %o0
-	ldd		[%o1 + 0x08], %f0
+	EX_LD(LOAD(ldd, %o1 + 0x08, %f0))
 	add		%o1, 0x8, %o1
-	sub		%o2, 0x8, %o2
 	subcc		%g2, 0x8, %g2
 	faligndata	%f2, %f0, %f8
-	std		%f8, [%o0 + 0x00]
+	EX_ST(STORE(std, %f8, %o0))
 	bne,pn		%XCC, 1b
 	 add		%o0, 0x8, %o0
 
@@ -225,48 +281,60 @@
 	 andcc		%o2, 0x8, %g0
 	be,pt		%icc, 1f
 	 nop
-	ldx		[%o1], %o5
-	stx		%o5, [%o1 + %o3]
+	EX_LD(LOAD(ldx, %o1, %o5))
+	EX_ST(STORE(stx, %o5, %o1 + %o3))
 	add		%o1, 0x8, %o1
 
 1:	andcc		%o2, 0x4, %g0
 	be,pt		%icc, 1f
 	 nop
-	lduw		[%o1], %o5
-	stw		%o5, [%o1 + %o3]
+	EX_LD(LOAD(lduw, %o1, %o5))
+	EX_ST(STORE(stw, %o5, %o1 + %o3))
 	add		%o1, 0x4, %o1
 
 1:	andcc		%o2, 0x2, %g0
 	be,pt		%icc, 1f
 	 nop
-	lduh		[%o1], %o5
-	sth		%o5, [%o1 + %o3]
+	EX_LD(LOAD(lduh, %o1, %o5))
+	EX_ST(STORE(sth, %o5, %o1 + %o3))
 	add		%o1, 0x2, %o1
 
 1:	andcc		%o2, 0x1, %g0
 	be,pt		%icc, 85f
 	 nop
-	ldub		[%o1], %o5
+	EX_LD(LOAD(ldub, %o1, %o5))
 	ba,pt		%xcc, 85f
-	 stb		%o5, [%o1 + %o3]
+	 EX_ST(STORE(stb, %o5, %o1 + %o3))
 
+	.align		64
 70: /* 16 < len <= 64 */
-	bne,pn		%XCC, 90f
+	bne,pn		%XCC, 75f
 	 sub		%o0, %o1, %o3
 
-	andn		%o2, 0x7, %o4
-	and		%o2, 0x7, %o2
-1:	subcc		%o4, 0x8, %o4
-	ldx		[%o1], %o5
-	stx		%o5, [%o1 + %o3]
+72:
+	andn		%o2, 0xf, %o4
+	and		%o2, 0xf, %o2
+1:	subcc		%o4, 0x10, %o4
+	EX_LD(LOAD(ldx, %o1 + 0x00, %o5))
+	EX_LD(LOAD(ldx, %o1 + 0x08, %g1))
+	EX_ST(STORE(stx, %o5, %o1 + %o3))
+	add		%o1, 0x8, %o1
+	EX_ST(STORE(stx, %g1, %o1 + %o3))
 	bgu,pt		%XCC, 1b
 	 add		%o1, 0x8, %o1
-	andcc		%o2, 0x4, %g0
+73:	andcc		%o2, 0x8, %g0
+	be,pt		%XCC, 1f
+	 nop
+	sub		%o2, 0x8, %o2
+	EX_LD(LOAD(ldx, %o1, %o5))
+	EX_ST(STORE(stx, %o5, %o1 + %o3))
+	add		%o1, 0x8, %o1
+1:	andcc		%o2, 0x4, %g0
 	be,pt		%XCC, 1f
 	 nop
 	sub		%o2, 0x4, %o2
-	lduw		[%o1], %o5
-	stw		%o5, [%o1 + %o3]
+	EX_LD(LOAD(lduw, %o1, %o5))
+	EX_ST(STORE(stw, %o5, %o1 + %o3))
 	add		%o1, 0x4, %o1
 1:	cmp		%o2, 0
 	be,pt		%XCC, 85f
@@ -274,6 +342,53 @@
 	ba,pt		%xcc, 90f
 	 nop
 
+75:
+	andcc		%o0, 0x7, %g1
+	sub		%g1, 0x8, %g1
+	be,pn		%icc, 2f
+	 sub		%g0, %g1, %g1
+	sub		%o2, %g1, %o2
+
+1:	subcc		%g1, 1, %g1
+	EX_LD(LOAD(ldub, %o1, %o5))
+	EX_ST(STORE(stb, %o5, %o1 + %o3))
+	bgu,pt		%icc, 1b
+	 add		%o1, 1, %o1
+
+2:	add		%o1, %o3, %o0
+	andcc		%o1, 0x7, %g1
+	bne,pt		%icc, 8f
+	 sll		%g1, 3, %g1
+
+	cmp		%o2, 16
+	bgeu,pt		%icc, 72b
+	 nop
+	ba,a,pt		%xcc, 73b
+
+8:	mov		64, %o3
+	andn		%o1, 0x7, %o1
+	EX_LD(LOAD(ldx, %o1, %g2))
+	sub		%o3, %g1, %o3
+	andn		%o2, 0x7, %o4
+	sllx		%g2, %g1, %g2
+1:	EX_LD(LOAD(ldx, %o1 + 0x8, %g3))
+	subcc		%o4, 0x8, %o4
+	add		%o1, 0x8, %o1
+	srlx		%g3, %o3, %o5
+	or		%o5, %g2, %o5
+	EX_ST(STORE(stx, %o5, %o0))
+	add		%o0, 0x8, %o0
+	bgu,pt		%icc, 1b
+	 sllx		%g3, %g1, %g2
+
+	srl		%g1, 3, %g1
+	andcc		%o2, 0x7, %o2
+	be,pn		%icc, 85f
+	 add		%o1, %g1, %o1
+	ba,pt		%xcc, 90f
+	 sub		%o0, %o1, %o3
+
+	.align		64
 80: /* 0 < len <= 16 */
 	andcc		%o3, 0x3, %g0
 	bne,pn		%XCC, 90f
@@ -281,34 +396,22 @@
 
 1:
 	subcc		%o2, 4, %o2
-	lduw		[%o1], %g1
-	stw		%g1, [%o1 + %o3]
+	EX_LD(LOAD(lduw, %o1, %g1))
+	EX_ST(STORE(stw, %g1, %o1 + %o3))
 	bgu,pt		%XCC, 1b
 	 add		%o1, 4, %o1
 
 85:	retl
-	 mov		%g5, %o0
+	 mov		EX_RETVAL(%g5), %o0
 
-	.align	32
+	.align		32
 90:
 	subcc		%o2, 1, %o2
-	ldub		[%o1], %g1
-	stb		%g1, [%o1 + %o3]
+	EX_LD(LOAD(ldub, %o1, %g1))
+	EX_ST(STORE(stb, %g1, %o1 + %o3))
 	bgu,pt		%XCC, 90b
 	 add		%o1, 1, %o1
 	retl
-	 mov		%g5, %o0
+	 mov		EX_RETVAL(%g5), %o0
 
-	/* 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	U3memcpy_user_stub
-U3memcpy_user_stub:
-	save		%sp, -192, %sp
-	mov		%i0, %o0
-	mov		%i1, %o1
-	call		U3memcpy
-	 mov		%i2, %o2
-	ret
-	 restore	%g0, %g0, %o0
+	.size		FUNC_NAME, .-FUNC_NAME
diff -Nru a/arch/sparc64/lib/U3patch.S b/arch/sparc64/lib/U3patch.S
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/arch/sparc64/lib/U3patch.S	2004-10-18 14:57:23 -07:00
@@ -0,0 +1,32 @@
+/* U3patch.S: Patch Ultra-I routines with Ultra-III variant.
+ *
+ * Copyright (C) 2004 David S. Miller <davem@redhat.com>
+ */
+
+#define BRANCH_ALWAYS	0x10680000
+#define NOP		0x01000000
+#define ULTRA3_DO_PATCH(OLD, NEW)	\
+	sethi	%hi(NEW), %g1; \
+	or	%g1, %lo(NEW), %g1; \
+	sethi	%hi(OLD), %g2; \
+	or	%g2, %lo(OLD), %g2; \
+	sub	%g1, %g2, %g1; \
+	sethi	%hi(BRANCH_ALWAYS), %g3; \
+	srl	%g1, 2, %g1; \
+	or	%g3, %lo(BRANCH_ALWAYS), %g3; \
+	or	%g3, %g1, %g3; \
+	stw	%g3, [%g2]; \
+	sethi	%hi(NOP), %g3; \
+	or	%g3, %lo(NOP), %g3; \
+	stw	%g3, [%g2 + 0x4]; \
+	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/VIScopy.S b/arch/sparc64/lib/VIScopy.S
--- a/arch/sparc64/lib/VIScopy.S	2004-10-18 14:55:54 -07:00
+++ /dev/null	Wed Dec 31 16:00:00 196900
@@ -1,1138 +0,0 @@
-/* $Id: VIScopy.S,v 1.27 2002/02/09 19:49:30 davem Exp $
- * VIScopy.S: High speed copy operations utilizing the UltraSparc
- *            Visual Instruction Set.
- *
- * Copyright (C) 1997 David S. Miller (davem@caip.rutgers.edu)
- * Copyright (C) 1996, 1997, 1998, 1999 Jakub Jelinek (jj@ultra.linux.cz)
- */
-
-#include "VIS.h"
-
-	/* VIS code can be used for numerous copy/set operation variants.
-	 * It can be made to work in the kernel, one single instance,
-	 * for all of memcpy, copy_to_user, and copy_from_user by setting
-	 * the ASI src/dest globals correctly.  Furthermore it can
-	 * be used for kernel-->kernel page copies as well, a hook label
-	 * is put in here just for this purpose.
-	 *
-	 * For userland, compiling this without __KERNEL__ defined makes
-	 * it work just fine as a generic libc bcopy and memcpy.
-	 * If for userland it is compiled with a 32bit gcc (but you need
-	 * -Wa,-Av9a for as), the code will just rely on lower 32bits of
-	 * IEU registers, if you compile it with 64bit gcc (ie. define
-	 * __sparc_v9__), the code will use full 64bit.
-	 */
-	 
-#ifdef __KERNEL__
-
-#include <asm/visasm.h>
-#include <asm/thread_info.h>
-
-#define FPU_CLEAN_RETL					\
-	ldub		[%g6 + TI_CURRENT_DS], %o1;	\
-	VISExit						\
-	clr		%o0;				\
-	retl;						\
-	 wr		%o1, %g0, %asi;
-#define FPU_RETL					\
-	ldub		[%g6 + TI_CURRENT_DS], %o1;	\
-	VISExit						\
-	clr		%o0;				\
-	retl;						\
-	 wr		%o1, %g0, %asi;
-#define NORMAL_RETL					\
-	ldub		[%g6 + TI_CURRENT_DS], %o1;	\
-	clr		%o0;				\
-	retl;						\
-	 wr		%o1, %g0, %asi;
-#define EX(x,y,a,b) 				\
-98: 	x,y;					\
-	.section .fixup;			\
-	.align	4;				\
-99:	ba	VIScopyfixup_ret;		\
-	 a, b, %o1;				\
-	.section __ex_table;			\
-	.align	4;				\
-	.word	98b, 99b;			\
-	.text;					\
-	.align	4;
-#define EX2(x,y,c,d,e,a,b) 			\
-98: 	x,y;					\
-	.section .fixup;			\
-	.align	4;				\
-99:	c, d, e;				\
-	ba	VIScopyfixup_ret;		\
-	 a, b, %o1;				\
-	.section __ex_table;			\
-	.align	4;				\
-	.word	98b, 99b;			\
-	.text;					\
-	.align	4;
-#define EXO2(x,y) 				\
-98: 	x,y;					\
-	.section __ex_table;			\
-	.align	4;				\
-	.word	98b, VIScopyfixup_reto2;	\
-	.text;					\
-	.align	4;
-#define EXVISN(x,y,n) 				\
-98: 	x,y;					\
-	.section __ex_table;			\
-	.align	4;				\
-	.word	98b, VIScopyfixup_vis##n;	\
-	.text;					\
-	.align	4;
-#define EXT(start,end,handler) 			\
-	.section __ex_table;			\
-	.align	4;				\
-	.word	start, 0, end, handler;		\
-	.text;					\
-	.align	4;
-#else
-#ifdef REGS_64BIT
-#define FPU_CLEAN_RETL				\
-	retl;					\
-	 mov	%g6, %o0;
-#define FPU_RETL				\
-	retl;					\
-	 mov	%g6, %o0;
-#else
-#define FPU_CLEAN_RETL				\
-	wr	%g0, FPRS_FEF, %fprs;		\
-	retl;					\
-	 mov	%g6, %o0;
-#define FPU_RETL				\
-	wr	%g0, FPRS_FEF, %fprs;		\
-	retl;					\
-	 mov	%g6, %o0;
-#endif
-#define NORMAL_RETL	\
-	retl;		\
-	 mov	%g6, %o0;
-#define EX(x,y,a,b)		x,y
-#define EX2(x,y,c,d,e,a,b)	x,y
-#define EXO2(x,y)		x,y
-#define EXVISN(x,y,n)		x,y
-#define EXT(a,b,c)
-#endif
-#define EXVIS(x,y) EXVISN(x,y,0)
-#define EXVIS1(x,y) EXVISN(x,y,1)
-#define EXVIS2(x,y) EXVISN(x,y,2)
-#define EXVIS3(x,y) EXVISN(x,y,3)
-#define EXVIS4(x,y) EXVISN(x,y,4)
-
-#define FREG_FROB(f1, f2, f3, f4, f5, f6, f7, f8, f9)		\
-	faligndata		%f1, %f2, %f48;			\
-	faligndata		%f2, %f3, %f50;			\
-	faligndata		%f3, %f4, %f52;			\
-	faligndata		%f4, %f5, %f54;			\
-	faligndata		%f5, %f6, %f56;			\
-	faligndata		%f6, %f7, %f58;			\
-	faligndata		%f7, %f8, %f60;			\
-	faligndata		%f8, %f9, %f62;
-
-#define MAIN_LOOP_CHUNK(src, dest, fdest, fsrc, len, jmptgt)	\
-	EXVIS(LDBLK		[%src] ASIBLK, %fdest);		\
-	ASI_SETDST_BLK						\
-	EXVIS(STBLK		%fsrc, [%dest] ASIBLK);		\
-	add			%src, 0x40, %src;		\
-	subcc			%len, 0x40, %len;		\
-	be,pn			%xcc, jmptgt;			\
-	 add			%dest, 0x40, %dest;		\
-	ASI_SETSRC_BLK
-
-#define LOOP_CHUNK1(src, dest, len, branch_dest)		\
-	MAIN_LOOP_CHUNK(src, dest, f0,  f48, len, branch_dest)
-#define LOOP_CHUNK2(src, dest, len, branch_dest)		\
-	MAIN_LOOP_CHUNK(src, dest, f16, f48, len, branch_dest)
-#define LOOP_CHUNK3(src, dest, len, branch_dest)		\
-	MAIN_LOOP_CHUNK(src, dest, f32, f48, len, branch_dest)
-
-#define STORE_SYNC(dest, fsrc)					\
-	EXVIS(STBLK		%fsrc, [%dest] ASIBLK);		\
-	add			%dest, 0x40, %dest;
-
-#ifdef __KERNEL__
-#define STORE_JUMP(dest, fsrc, target)				\
-	srl			asi_dest, 3, %g5;		\
-	EXVIS2(STBLK		%fsrc, [%dest] ASIBLK);		\
-	xor		       asi_dest, ASI_BLK_XOR1, asi_dest;\
-	add			%dest, 0x40, %dest;		\
-	xor			asi_dest, %g5, asi_dest;	\
-	ba,pt			%xcc, target;
-#else
-#define STORE_JUMP(dest, fsrc, target)				\
-	EXVIS2(STBLK		%fsrc, [%dest] ASIBLK);		\
-	add			%dest, 0x40, %dest;		\
-	ba,pt			%xcc, target;
-#endif
-
-#ifndef __KERNEL__
-#define VISLOOP_PAD nop; nop; nop; nop; \
-		    nop; nop; nop; nop; \
-		    nop; nop; nop; nop; \
-		    nop; nop; nop;
-#else
-#define VISLOOP_PAD
-#endif
-
-#define FINISH_VISCHUNK(dest, f0, f1, left)			\
-	ASI_SETDST_NOBLK					\
-	subcc			%left, 8, %left;		\
-	bl,pn			%xcc, vis_out;			\
-	 faligndata		%f0, %f1, %f48;			\
-	EXVIS3(STDF		%f48, [%dest] ASINORMAL);	\
-	add			%dest, 8, %dest;
-
-#define UNEVEN_VISCHUNK_LAST(dest, f0, f1, left)		\
-	subcc			%left, 8, %left;		\
-	bl,pn			%xcc, vis_out;			\
-	 fsrc1			%f0, %f1;
-#define UNEVEN_VISCHUNK(dest, f0, f1, left)			\
-	UNEVEN_VISCHUNK_LAST(dest, f0, f1, left)		\
-	ba,a,pt			%xcc, vis_out_slk;
-
-	/* Macros for non-VIS memcpy code. */
-#ifdef REGS_64BIT
-
-#define MOVE_BIGCHUNK(src, dst, offset, t0, t1, t2, t3)			\
-	ASI_SETSRC_NOBLK						\
-	LDX			[%src + offset + 0x00] ASINORMAL, %t0; 	\
-	LDX			[%src + offset + 0x08] ASINORMAL, %t1; 	\
-	LDX			[%src + offset + 0x10] ASINORMAL, %t2; 	\
-	LDX			[%src + offset + 0x18] ASINORMAL, %t3; 	\
-	ASI_SETDST_NOBLK						\
-	STW			%t0, [%dst + offset + 0x04] ASINORMAL; 	\
-	srlx			%t0, 32, %t0;				\
-	STW			%t0, [%dst + offset + 0x00] ASINORMAL; 	\
-	STW			%t1, [%dst + offset + 0x0c] ASINORMAL; 	\
-	srlx			%t1, 32, %t1;				\
-	STW			%t1, [%dst + offset + 0x08] ASINORMAL; 	\
-	STW			%t2, [%dst + offset + 0x14] ASINORMAL; 	\
-	srlx			%t2, 32, %t2;				\
-	STW			%t2, [%dst + offset + 0x10] ASINORMAL; 	\
-	STW			%t3, [%dst + offset + 0x1c] ASINORMAL;	\
-	srlx			%t3, 32, %t3;				\
-	STW			%t3, [%dst + offset + 0x18] ASINORMAL;
-
-#define MOVE_BIGALIGNCHUNK(src, dst, offset, t0, t1, t2, t3)		\
-	ASI_SETSRC_NOBLK						\
-	LDX			[%src + offset + 0x00] ASINORMAL, %t0; 	\
-	LDX			[%src + offset + 0x08] ASINORMAL, %t1; 	\
-	LDX			[%src + offset + 0x10] ASINORMAL, %t2; 	\
-	LDX			[%src + offset + 0x18] ASINORMAL, %t3; 	\
-	ASI_SETDST_NOBLK						\
-	STX			%t0, [%dst + offset + 0x00] ASINORMAL; 	\
-	STX			%t1, [%dst + offset + 0x08] ASINORMAL; 	\
-	STX			%t2, [%dst + offset + 0x10] ASINORMAL; 	\
-	STX			%t3, [%dst + offset + 0x18] ASINORMAL; 	\
-	ASI_SETSRC_NOBLK						\
-	LDX			[%src + offset + 0x20] ASINORMAL, %t0; 	\
-	LDX			[%src + offset + 0x28] ASINORMAL, %t1; 	\
-	LDX			[%src + offset + 0x30] ASINORMAL, %t2; 	\
-	LDX			[%src + offset + 0x38] ASINORMAL, %t3; 	\
-	ASI_SETDST_NOBLK						\
-	STX			%t0, [%dst + offset + 0x20] ASINORMAL; 	\
-	STX			%t1, [%dst + offset + 0x28] ASINORMAL; 	\
-	STX			%t2, [%dst + offset + 0x30] ASINORMAL; 	\
-	STX			%t3, [%dst + offset + 0x38] ASINORMAL;
-
-#define MOVE_LASTCHUNK(src, dst, offset, t0, t1, t2, t3)		\
-	ASI_SETSRC_NOBLK						\
-	LDX			[%src - offset - 0x10] ASINORMAL, %t0;	\
-	LDX			[%src - offset - 0x08] ASINORMAL, %t1; 	\
-	ASI_SETDST_NOBLK						\
-	STW			%t0, [%dst - offset - 0x0c] ASINORMAL; 	\
-	srlx			%t0, 32, %t2;				\
-	STW			%t2, [%dst - offset - 0x10] ASINORMAL; 	\
-	STW			%t1, [%dst - offset - 0x04] ASINORMAL; 	\
-	srlx			%t1, 32, %t3;				\
-	STW			%t3, [%dst - offset - 0x08] ASINORMAL;
-
-#define MOVE_LASTALIGNCHUNK(src, dst, offset, t0, t1)			\
-	ASI_SETSRC_NOBLK						\
-	LDX			[%src - offset - 0x10] ASINORMAL, %t0; 	\
-	LDX			[%src - offset - 0x08] ASINORMAL, %t1; 	\
-	ASI_SETDST_NOBLK						\
-	STX			%t0, [%dst - offset - 0x10] ASINORMAL; 	\
-	STX			%t1, [%dst - offset - 0x08] ASINORMAL;
-
-#else /* !REGS_64BIT */
-
-#define MOVE_BIGCHUNK(src, dst, offset, t0, t1, t2, t3)			\
-	lduw			[%src + offset + 0x00], %t0; 		\
-	lduw			[%src + offset + 0x04], %t1; 		\
-	lduw			[%src + offset + 0x08], %t2; 		\
-	lduw			[%src + offset + 0x0c], %t3; 		\
-	stw			%t0, [%dst + offset + 0x00]; 		\
-	stw			%t1, [%dst + offset + 0x04]; 		\
-	stw			%t2, [%dst + offset + 0x08]; 		\
-	stw			%t3, [%dst + offset + 0x0c]; 		\
-	lduw			[%src + offset + 0x10], %t0; 		\
-	lduw			[%src + offset + 0x14], %t1; 		\
-	lduw			[%src + offset + 0x18], %t2; 		\
-	lduw			[%src + offset + 0x1c], %t3; 		\
-	stw			%t0, [%dst + offset + 0x10]; 		\
-	stw			%t1, [%dst + offset + 0x14]; 		\
-	stw			%t2, [%dst + offset + 0x18]; 		\
-	stw			%t3, [%dst + offset + 0x1c];
-
-#define MOVE_LASTCHUNK(src, dst, offset, t0, t1, t2, t3)		\
-	lduw			[%src - offset - 0x10], %t0; 		\
-	lduw			[%src - offset - 0x0c], %t1; 		\
-	lduw			[%src - offset - 0x08], %t2; 		\
-	lduw			[%src - offset - 0x04], %t3; 		\
-	stw			%t0, [%dst - offset - 0x10]; 		\
-	stw			%t1, [%dst - offset - 0x0c]; 		\
-	stw			%t2, [%dst - offset - 0x08]; 		\
-	stw			%t3, [%dst - offset - 0x04];
-
-#endif /* !REGS_64BIT */
-
-#ifdef __KERNEL__
-		.section	__ex_table,#alloc
-		.section	.fixup,#alloc,#execinstr
-#endif
-
-		.text
-		.align			32
-		.globl			memcpy
-		.type			memcpy,@function
-
-		.globl			bcopy
-		.type			bcopy,@function
-
-#ifdef __KERNEL__
-memcpy_private:
-memcpy:		mov		ASI_P, asi_src			! IEU0	Group
-		brnz,pt		%o2, __memcpy_entry		! CTI
-		 mov		ASI_P, asi_dest			! IEU1
-		retl
-		 clr		%o0
-
-		.align			32
-		.globl			__copy_from_user
-		.type			__copy_from_user,@function
-__copy_from_user:rd		%asi, asi_src			! IEU0	Group
-		brnz,pt		%o2, __memcpy_entry		! CTI
-		 mov		ASI_P, asi_dest			! IEU1
-
-		.globl			__copy_to_user
-		.type			__copy_to_user,@function
-__copy_to_user:	mov		ASI_P, asi_src			! IEU0	Group
-		brnz,pt		%o2, __memcpy_entry		! CTI
-		 rd		%asi, asi_dest			! IEU1
-		retl						! CTI	Group
-		 clr		%o0				! IEU0	Group
-
-		.globl			__copy_in_user
-		.type			__copy_in_user,@function
-__copy_in_user:	rd		%asi, asi_src			! IEU0	Group
-		brnz,pt		%o2, __memcpy_entry		! CTI
-		 mov		asi_src, asi_dest		! IEU1
-		retl						! CTI	Group
-		 clr		%o0				! IEU0	Group
-#endif
-
-bcopy:		or		%o0, 0, %g3			! IEU0	Group
-		addcc		%o1, 0, %o0			! IEU1
-		brgez,pt	%o2, memcpy_private		! CTI
-		 or		%g3, 0, %o1			! IEU0	Group
-		retl						! CTI	Group brk forced
-		 clr		%o0				! IEU0
-
-
-#ifdef __KERNEL__
-#define BRANCH_ALWAYS	0x10680000
-#define NOP		0x01000000
-#define ULTRA3_DO_PATCH(OLD, NEW)	\
-	sethi	%hi(NEW), %g1; \
-	or	%g1, %lo(NEW), %g1; \
-	sethi	%hi(OLD), %g2; \
-	or	%g2, %lo(OLD), %g2; \
-	sub	%g1, %g2, %g1; \
-	sethi	%hi(BRANCH_ALWAYS), %g3; \
-	srl	%g1, 2, %g1; \
-	or	%g3, %lo(BRANCH_ALWAYS), %g3; \
-	or	%g3, %g1, %g3; \
-	stw	%g3, [%g2]; \
-	sethi	%hi(NOP), %g3; \
-	or	%g3, %lo(NOP), %g3; \
-	stw	%g3, [%g2 + 0x4]; \
-	flush	%g2;
-
-	.globl	cheetah_patch_copyops
-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)
-	ULTRA3_DO_PATCH(__copy_in_user, U3copy_in_user)
-	retl
-	 nop
-#undef BRANCH_ALWAYS
-#undef NOP
-#undef ULTRA3_DO_PATCH
-#endif /* __KERNEL__ */
-
-	.align			32
-#ifdef __KERNEL__
-	andcc			%o0, 7, %g2			! IEU1	Group
-#endif
-VIS_enter:
-	be,pt			%xcc, dest_is_8byte_aligned	! CTI
-#ifdef __KERNEL__
-	 nop							! IEU0	Group
-#else
-	 andcc			%o0, 0x38, %g5			! IEU1	Group
-#endif
-do_dest_8byte_align:
-	mov			8, %g1				! IEU0
-	sub			%g1, %g2, %g2			! IEU0	Group
-	andcc			%o0, 1, %g0			! IEU1
-	be,pt			%icc, 2f			! CTI
-	 sub			%o2, %g2, %o2			! IEU0	Group
-1:	ASI_SETSRC_NOBLK					! LSU	Group
-	EX(LDUB			[%o1] ASINORMAL, %o5, 
-				add %o2, %g2)			! Load	Group
-	add			%o1, 1, %o1			! IEU0
-	add			%o0, 1, %o0			! IEU1
-	ASI_SETDST_NOBLK					! LSU	Group
-	subcc			%g2, 1, %g2			! IEU1	Group
-	be,pn			%xcc, 3f			! CTI
-	 EX2(STB		%o5, [%o0 - 1] ASINORMAL,
-				add %g2, 1, %g2,
-				add %o2, %g2)			! Store
-2:	ASI_SETSRC_NOBLK					! LSU	Group
-	EX(LDUB			[%o1] ASINORMAL, %o5, 
-				add %o2, %g2)			! Load	Group
-	add			%o0, 2, %o0			! IEU0
-	EX2(LDUB		[%o1 + 1] ASINORMAL, %g3,
-				sub %o0, 2, %o0,
-				add %o2, %g2)			! Load	Group
-	ASI_SETDST_NOBLK					! LSU	Group
-	subcc			%g2, 2, %g2			! IEU1	Group
-	EX2(STB			%o5, [%o0 - 2] ASINORMAL,
-				add %g2, 2, %g2,
-				add %o2, %g2)			! Store
-	add			%o1, 2, %o1			! IEU0
-	bne,pt			%xcc, 2b			! CTI	Group
-	 EX2(STB		%g3, [%o0 - 1] ASINORMAL,
-				add %g2, 1, %g2,
-				add %o2, %g2)			! Store
-#ifdef __KERNEL__
-3:
-dest_is_8byte_aligned:
-	VISEntry
-	andcc			%o0, 0x38, %g5			! IEU1	Group
-#else
-3:	andcc			%o0, 0x38, %g5			! IEU1	Group
-dest_is_8byte_aligned:
-#endif
-	be,pt			%icc, dest_is_64byte_aligned	! CTI
-	 mov			64, %g1				! IEU0
-	fmovd			%f0, %f2			! FPU
-	sub			%g1, %g5, %g5			! IEU0	Group
-	ASI_SETSRC_NOBLK					! LSU	Group
-	alignaddr		%o1, %g0, %g1			! GRU	Group
-	EXO2(LDDF		[%g1] ASINORMAL, %f4)		! Load	Group
-	sub			%o2, %g5, %o2			! IEU0
-1:	EX(LDDF			[%g1 + 0x8] ASINORMAL, %f6,
-				add %o2, %g5)			! Load	Group
-	add			%g1, 0x8, %g1			! IEU0	Group
-	subcc			%g5, 8, %g5			! IEU1
-	ASI_SETDST_NOBLK					! LSU	Group
-	faligndata		%f4, %f6, %f0			! GRU	Group
-	EX2(STDF		%f0, [%o0] ASINORMAL,
-				add %g5, 8, %g5,
-				add %o2, %g5)			! Store
-	add			%o1, 8, %o1			! IEU0	Group
-	be,pn			%xcc, dest_is_64byte_aligned	! CTI
-	 add			%o0, 8, %o0			! IEU1
-	ASI_SETSRC_NOBLK					! LSU	Group
-	EX(LDDF			[%g1 + 0x8] ASINORMAL, %f4,
-				add %o2, %g5)			! Load	Group
-	add			%g1, 8, %g1			! IEU0
-	subcc			%g5, 8, %g5			! IEU1
-	ASI_SETDST_NOBLK					! LSU	Group
-	faligndata		%f6, %f4, %f0			! GRU	Group
-	EX2(STDF		%f0, [%o0] ASINORMAL,
-				add %g5, 8, %g5,
-				add %o2, %g5)			! Store
-	add			%o1, 8, %o1			! IEU0
-	ASI_SETSRC_NOBLK					! LSU	Group
-	bne,pt			%xcc, 1b			! CTI	Group
-	 add			%o0, 8, %o0			! IEU0
-dest_is_64byte_aligned:
-	membar		  #LoadStore | #StoreStore | #StoreLoad	! LSU	Group
-#ifndef __KERNEL__
-	wr			%g0, ASI_BLK_P, %asi		! LSU	Group
-#endif
-	subcc			%o2, 0x40, %g7			! IEU1	Group
-	mov			%o1, %g1			! IEU0
-	andncc			%g7, (0x40 - 1), %g7		! IEU1	Group
-	srl			%g1, 3, %g2			! IEU0
-	sub			%o2, %g7, %g3			! IEU0	Group
-	andn			%o1, (0x40 - 1), %o1		! IEU1
-	and			%g2, 7, %g2			! IEU0	Group
-	andncc			%g3, 0x7, %g3			! IEU1
-	fmovd			%f0, %f2			! FPU
-	sub			%g3, 0x10, %g3			! IEU0	Group
-	sub			%o2, %g7, %o2			! IEU1
-#ifdef __KERNEL__
-	or			asi_src, ASI_BLK_OR, asi_src	! IEU0	Group
-	or			asi_dest, ASI_BLK_OR, asi_dest	! IEU1
-#endif
-	alignaddr		%g1, %g0, %g0			! GRU	Group
-	add			%g1, %g7, %g1			! IEU0	Group
-	subcc			%o2, %g3, %o2			! IEU1
-	ASI_SETSRC_BLK						! LSU	Group
-	EXVIS1(LDBLK		[%o1 + 0x00] ASIBLK, %f0)	! LSU	Group
-	add			%g1, %g3, %g1			! IEU0
-	EXVIS1(LDBLK		[%o1 + 0x40] ASIBLK, %f16)	! LSU	Group
-	sub			%g7, 0x80, %g7			! IEU0
-	EXVIS(LDBLK		[%o1 + 0x80] ASIBLK, %f32)	! LSU	Group
-#ifdef __KERNEL__
-vispc:	sll			%g2, 9, %g2			! IEU0	Group
-	sethi			%hi(vis00), %g5			! IEU1
-	or			%g5, %lo(vis00), %g5		! IEU0	Group
-	jmpl			%g5 + %g2, %g0			! CTI	Group brk forced
-	 addcc			%o1, 0xc0, %o1			! IEU1	Group
-#else
-								! Clk1	Group 8-(
-								! Clk2	Group 8-(
-								! Clk3	Group 8-(
-								! Clk4	Group 8-(
-vispc:	rd			%pc, %g5			! PDU	Group 8-(
-	addcc			%g5, %lo(vis00 - vispc), %g5	! IEU1	Group
-	sll			%g2, 9, %g2			! IEU0
-	jmpl			%g5 + %g2, %g0			! CTI	Group brk forced
-	 addcc			%o1, 0xc0, %o1			! IEU1	Group
-#endif
-	.align			512		/* OK, here comes the fun part... */
-vis00:FREG_FROB(f0, f2, f4, f6, f8, f10,f12,f14,f16) LOOP_CHUNK1(o1, o0, g7, vis01)
-      FREG_FROB(f16,f18,f20,f22,f24,f26,f28,f30,f32) LOOP_CHUNK2(o1, o0, g7, vis02)
-      FREG_FROB(f32,f34,f36,f38,f40,f42,f44,f46,f0)  LOOP_CHUNK3(o1, o0, g7, vis03)
-      b,pt			%xcc, vis00+4; faligndata %f0, %f2, %f48
-vis01:FREG_FROB(f16,f18,f20,f22,f24,f26,f28,f30,f32) STORE_SYNC(o0, f48) membar #Sync
-      FREG_FROB(f32,f34,f36,f38,f40,f42,f44,f46,f0)  STORE_JUMP(o0, f48, finish_f0) membar #Sync
-vis02:FREG_FROB(f32,f34,f36,f38,f40,f42,f44,f46,f0)  STORE_SYNC(o0, f48) membar #Sync
-      FREG_FROB(f0, f2, f4, f6, f8, f10,f12,f14,f16) STORE_JUMP(o0, f48, finish_f16) membar #Sync
-vis03:FREG_FROB(f0, f2, f4, f6, f8, f10,f12,f14,f16) STORE_SYNC(o0, f48) membar #Sync
-      FREG_FROB(f16,f18,f20,f22,f24,f26,f28,f30,f32) STORE_JUMP(o0, f48, finish_f32) membar #Sync
-      VISLOOP_PAD
-vis10:FREG_FROB(f2, f4, f6, f8, f10,f12,f14,f16,f18) LOOP_CHUNK1(o1, o0, g7, vis11)
-      FREG_FROB(f18,f20,f22,f24,f26,f28,f30,f32,f34) LOOP_CHUNK2(o1, o0, g7, vis12)
-      FREG_FROB(f34,f36,f38,f40,f42,f44,f46,f0, f2)  LOOP_CHUNK3(o1, o0, g7, vis13)
-      b,pt			%xcc, vis10+4; faligndata %f2, %f4, %f48
-vis11:FREG_FROB(f18,f20,f22,f24,f26,f28,f30,f32,f34) STORE_SYNC(o0, f48) membar #Sync
-      FREG_FROB(f34,f36,f38,f40,f42,f44,f46,f0, f2)  STORE_JUMP(o0, f48, finish_f2) membar #Sync
-vis12:FREG_FROB(f34,f36,f38,f40,f42,f44,f46,f0, f2)  STORE_SYNC(o0, f48) membar #Sync
-      FREG_FROB(f2, f4, f6, f8, f10,f12,f14,f16,f18) STORE_JUMP(o0, f48, finish_f18) membar #Sync
-vis13:FREG_FROB(f2, f4, f6, f8, f10,f12,f14,f16,f18) STORE_SYNC(o0, f48) membar #Sync
-      FREG_FROB(f18,f20,f22,f24,f26,f28,f30,f32,f34) STORE_JUMP(o0, f48, finish_f34) membar #Sync
-      VISLOOP_PAD
-vis20:FREG_FROB(f4, f6, f8, f10,f12,f14,f16,f18,f20) LOOP_CHUNK1(o1, o0, g7, vis21)
-      FREG_FROB(f20,f22,f24,f26,f28,f30,f32,f34,f36) LOOP_CHUNK2(o1, o0, g7, vis22)
-      FREG_FROB(f36,f38,f40,f42,f44,f46,f0, f2, f4)  LOOP_CHUNK3(o1, o0, g7, vis23)
-      b,pt			%xcc, vis20+4; faligndata %f4, %f6, %f48
-vis21:FREG_FROB(f20,f22,f24,f26,f28,f30,f32,f34,f36) STORE_SYNC(o0, f48) membar #Sync
-      FREG_FROB(f36,f38,f40,f42,f44,f46,f0, f2, f4)  STORE_JUMP(o0, f48, finish_f4) membar #Sync
-vis22:FREG_FROB(f36,f38,f40,f42,f44,f46,f0, f2, f4)  STORE_SYNC(o0, f48) membar #Sync
-      FREG_FROB(f4, f6, f8, f10,f12,f14,f16,f18,f20) STORE_JUMP(o0, f48, finish_f20) membar #Sync
-vis23:FREG_FROB(f4, f6, f8, f10,f12,f14,f16,f18,f20) STORE_SYNC(o0, f48) membar #Sync
-      FREG_FROB(f20,f22,f24,f26,f28,f30,f32,f34,f36) STORE_JUMP(o0, f48, finish_f36) membar #Sync
-      VISLOOP_PAD
-vis30:FREG_FROB(f6, f8, f10,f12,f14,f16,f18,f20,f22) LOOP_CHUNK1(o1, o0, g7, vis31)
-      FREG_FROB(f22,f24,f26,f28,f30,f32,f34,f36,f38) LOOP_CHUNK2(o1, o0, g7, vis32)
-      FREG_FROB(f38,f40,f42,f44,f46,f0, f2, f4, f6)  LOOP_CHUNK3(o1, o0, g7, vis33)
-      b,pt			%xcc, vis30+4; faligndata %f6, %f8, %f48
-vis31:FREG_FROB(f22,f24,f26,f28,f30,f32,f34,f36,f38) STORE_SYNC(o0, f48) membar #Sync
-      FREG_FROB(f38,f40,f42,f44,f46,f0, f2, f4, f6)  STORE_JUMP(o0, f48, finish_f6) membar #Sync
-vis32:FREG_FROB(f38,f40,f42,f44,f46,f0, f2, f4, f6)  STORE_SYNC(o0, f48) membar #Sync
-      FREG_FROB(f6, f8, f10,f12,f14,f16,f18,f20,f22) STORE_JUMP(o0, f48, finish_f22) membar #Sync
-vis33:FREG_FROB(f6, f8, f10,f12,f14,f16,f18,f20,f22) STORE_SYNC(o0, f48) membar #Sync
-      FREG_FROB(f22,f24,f26,f28,f30,f32,f34,f36,f38) STORE_JUMP(o0, f48, finish_f38) membar #Sync
-      VISLOOP_PAD
-vis40:FREG_FROB(f8, f10,f12,f14,f16,f18,f20,f22,f24) LOOP_CHUNK1(o1, o0, g7, vis41)
-      FREG_FROB(f24,f26,f28,f30,f32,f34,f36,f38,f40) LOOP_CHUNK2(o1, o0, g7, vis42)
-      FREG_FROB(f40,f42,f44,f46,f0, f2, f4, f6, f8)  LOOP_CHUNK3(o1, o0, g7, vis43)
-      b,pt			%xcc, vis40+4; faligndata %f8, %f10, %f48
-vis41:FREG_FROB(f24,f26,f28,f30,f32,f34,f36,f38,f40) STORE_SYNC(o0, f48) membar #Sync
-      FREG_FROB(f40,f42,f44,f46,f0, f2, f4, f6, f8)  STORE_JUMP(o0, f48, finish_f8) membar #Sync
-vis42:FREG_FROB(f40,f42,f44,f46,f0, f2, f4, f6, f8)  STORE_SYNC(o0, f48) membar #Sync
-      FREG_FROB(f8, f10,f12,f14,f16,f18,f20,f22,f24) STORE_JUMP(o0, f48, finish_f24) membar #Sync
-vis43:FREG_FROB(f8, f10,f12,f14,f16,f18,f20,f22,f24) STORE_SYNC(o0, f48) membar #Sync
-      FREG_FROB(f24,f26,f28,f30,f32,f34,f36,f38,f40) STORE_JUMP(o0, f48, finish_f40) membar #Sync
-      VISLOOP_PAD
-vis50:FREG_FROB(f10,f12,f14,f16,f18,f20,f22,f24,f26) LOOP_CHUNK1(o1, o0, g7, vis51)
-      FREG_FROB(f26,f28,f30,f32,f34,f36,f38,f40,f42) LOOP_CHUNK2(o1, o0, g7, vis52)
-      FREG_FROB(f42,f44,f46,f0, f2, f4, f6, f8, f10) LOOP_CHUNK3(o1, o0, g7, vis53)
-      b,pt			%xcc, vis50+4; faligndata %f10, %f12, %f48
-vis51:FREG_FROB(f26,f28,f30,f32,f34,f36,f38,f40,f42) STORE_SYNC(o0, f48) membar #Sync
-      FREG_FROB(f42,f44,f46,f0, f2, f4, f6, f8, f10) STORE_JUMP(o0, f48, finish_f10) membar #Sync
-vis52:FREG_FROB(f42,f44,f46,f0, f2, f4, f6, f8, f10) STORE_SYNC(o0, f48) membar #Sync
-      FREG_FROB(f10,f12,f14,f16,f18,f20,f22,f24,f26) STORE_JUMP(o0, f48, finish_f26) membar #Sync
-vis53:FREG_FROB(f10,f12,f14,f16,f18,f20,f22,f24,f26) STORE_SYNC(o0, f48) membar #Sync
-      FREG_FROB(f26,f28,f30,f32,f34,f36,f38,f40,f42) STORE_JUMP(o0, f48, finish_f42) membar #Sync
-      VISLOOP_PAD
-vis60:FREG_FROB(f12,f14,f16,f18,f20,f22,f24,f26,f28) LOOP_CHUNK1(o1, o0, g7, vis61)
-      FREG_FROB(f28,f30,f32,f34,f36,f38,f40,f42,f44) LOOP_CHUNK2(o1, o0, g7, vis62)
-      FREG_FROB(f44,f46,f0, f2, f4, f6, f8, f10,f12) LOOP_CHUNK3(o1, o0, g7, vis63)
-      b,pt			%xcc, vis60+4; faligndata %f12, %f14, %f48
-vis61:FREG_FROB(f28,f30,f32,f34,f36,f38,f40,f42,f44) STORE_SYNC(o0, f48) membar #Sync
-      FREG_FROB(f44,f46,f0, f2, f4, f6, f8, f10,f12) STORE_JUMP(o0, f48, finish_f12) membar #Sync
-vis62:FREG_FROB(f44,f46,f0, f2, f4, f6, f8, f10,f12) STORE_SYNC(o0, f48) membar #Sync
-      FREG_FROB(f12,f14,f16,f18,f20,f22,f24,f26,f28) STORE_JUMP(o0, f48, finish_f28) membar #Sync
-vis63:FREG_FROB(f12,f14,f16,f18,f20,f22,f24,f26,f28) STORE_SYNC(o0, f48) membar #Sync
-      FREG_FROB(f28,f30,f32,f34,f36,f38,f40,f42,f44) STORE_JUMP(o0, f48, finish_f44) membar #Sync
-      VISLOOP_PAD
-vis70:FREG_FROB(f14,f16,f18,f20,f22,f24,f26,f28,f30) LOOP_CHUNK1(o1, o0, g7, vis71)
-      FREG_FROB(f30,f32,f34,f36,f38,f40,f42,f44,f46) LOOP_CHUNK2(o1, o0, g7, vis72)
-      FREG_FROB(f46,f0, f2, f4, f6, f8, f10,f12,f14) LOOP_CHUNK3(o1, o0, g7, vis73)
-      b,pt			%xcc, vis70+4; faligndata %f14, %f16, %f48
-vis71:FREG_FROB(f30,f32,f34,f36,f38,f40,f42,f44,f46) STORE_SYNC(o0, f48) membar #Sync
-      FREG_FROB(f46,f0, f2, f4, f6, f8, f10,f12,f14) STORE_JUMP(o0, f48, finish_f14) membar #Sync
-vis72:FREG_FROB(f46,f0, f2, f4, f6, f8, f10,f12,f14) STORE_SYNC(o0, f48) membar #Sync
-      FREG_FROB(f14,f16,f18,f20,f22,f24,f26,f28,f30) STORE_JUMP(o0, f48, finish_f30) membar #Sync
-vis73:FREG_FROB(f14,f16,f18,f20,f22,f24,f26,f28,f30) STORE_SYNC(o0, f48) membar #Sync
-      FREG_FROB(f30,f32,f34,f36,f38,f40,f42,f44,f46) STORE_JUMP(o0, f48, finish_f46) membar #Sync
-      VISLOOP_PAD
-finish_f0:	FINISH_VISCHUNK(o0, f0,  f2,  g3)
-finish_f2:	FINISH_VISCHUNK(o0, f2,  f4,  g3)
-finish_f4:	FINISH_VISCHUNK(o0, f4,  f6,  g3)
-finish_f6:	FINISH_VISCHUNK(o0, f6,  f8,  g3)
-finish_f8:	FINISH_VISCHUNK(o0, f8,  f10, g3)
-finish_f10:	FINISH_VISCHUNK(o0, f10, f12, g3)
-finish_f12:	FINISH_VISCHUNK(o0, f12, f14, g3)
-finish_f14:	UNEVEN_VISCHUNK(o0, f14, f0,  g3)
-finish_f16:	FINISH_VISCHUNK(o0, f16, f18, g3)
-finish_f18:	FINISH_VISCHUNK(o0, f18, f20, g3)
-finish_f20:	FINISH_VISCHUNK(o0, f20, f22, g3)
-finish_f22:	FINISH_VISCHUNK(o0, f22, f24, g3)
-finish_f24:	FINISH_VISCHUNK(o0, f24, f26, g3)
-finish_f26:	FINISH_VISCHUNK(o0, f26, f28, g3)
-finish_f28:	FINISH_VISCHUNK(o0, f28, f30, g3)
-finish_f30:	UNEVEN_VISCHUNK(o0, f30, f0,  g3)
-finish_f32:	FINISH_VISCHUNK(o0, f32, f34, g3)
-finish_f34:	FINISH_VISCHUNK(o0, f34, f36, g3)
-finish_f36:	FINISH_VISCHUNK(o0, f36, f38, g3)
-finish_f38:	FINISH_VISCHUNK(o0, f38, f40, g3)
-finish_f40:	FINISH_VISCHUNK(o0, f40, f42, g3)
-finish_f42:	FINISH_VISCHUNK(o0, f42, f44, g3)
-finish_f44:	FINISH_VISCHUNK(o0, f44, f46, g3)
-finish_f46:	UNEVEN_VISCHUNK_LAST(o0, f46, f0,  g3)
-vis_out_slk:
-#ifdef __KERNEL__
-	srl		asi_src, 3, %g5				! IEU0	Group
-	xor		asi_src, ASI_BLK_XOR1, asi_src		! IEU1
-	xor		asi_src, %g5, asi_src			! IEU0	Group
-#endif
-vis_slk:ASI_SETSRC_NOBLK					! LSU	Group
-	EXVIS3(LDDF	[%o1] ASINORMAL, %f2)			! Load	Group
-	add		%o1, 8, %o1				! IEU0
-	subcc		%g3, 8, %g3				! IEU1
-	ASI_SETDST_NOBLK					! LSU	Group
-	faligndata	%f0, %f2, %f8				! GRU	Group
-	EXVIS4(STDF	%f8, [%o0] ASINORMAL)			! Store
-	bl,pn		%xcc, vis_out_slp			! CTI
-	 add		%o0, 8, %o0				! IEU0	Group
-	ASI_SETSRC_NOBLK					! LSU	Group
-	EXVIS3(LDDF	[%o1] ASINORMAL, %f0)			! Load	Group
-	add		%o1, 8, %o1				! IEU0
-	subcc		%g3, 8, %g3				! IEU1
-	ASI_SETDST_NOBLK					! LSU	Group
-	faligndata	%f2, %f0, %f8				! GRU	Group
-	EXVIS4(STDF	%f8, [%o0] ASINORMAL)			! Store
-	bge,pt		%xcc, vis_slk				! CTI
-	 add		%o0, 8, %o0				! IEU0	Group
-vis_out_slp:
-#ifdef __KERNEL__
-	brz,pt		%o2, vis_ret				! CTI	Group
-	 mov		%g1, %o1				! IEU0
-	ba,pt		%xcc, vis_slp+4				! CTI	Group
-	 ASI_SETSRC_NOBLK					! LSU	Group
-#endif
-vis_out:brz,pt		%o2, vis_ret				! CTI	Group
-	 mov		%g1, %o1				! IEU0
-#ifdef __KERNEL__
-	srl		asi_src, 3, %g5				! IEU0	Group
-	xor		asi_src, ASI_BLK_XOR1, asi_src		! IEU1
-	xor		asi_src, %g5, asi_src			! IEU0	Group
-#endif
-vis_slp:ASI_SETSRC_NOBLK					! LSU	Group
-	EXO2(LDUB	[%o1] ASINORMAL, %g5)			! LOAD
-	add		%o1, 1, %o1				! IEU0
-	add		%o0, 1, %o0				! IEU1
-	ASI_SETDST_NOBLK					! LSU	Group
-	subcc		%o2, 1, %o2				! IEU1
-	bne,pt		%xcc, vis_slp				! CTI
-	 EX(STB		%g5, [%o0 - 1] ASINORMAL,
-			add %o2, 1)				! Store	Group
-vis_ret:membar		#StoreLoad | #StoreStore		! LSU	Group
-	FPU_CLEAN_RETL
-
-
-__memcpy_short:
-	andcc		%o2, 1, %g0				! IEU1	Group
-	be,pt		%icc, 2f				! CTI
-1:	 ASI_SETSRC_NOBLK					! LSU	Group
-	EXO2(LDUB	[%o1] ASINORMAL, %g5)			! LOAD	Group
-	add		%o1, 1, %o1				! IEU0
-	add		%o0, 1, %o0				! IEU1
-	ASI_SETDST_NOBLK					! LSU	Group
-	subcc		%o2, 1, %o2				! IEU1	Group
-	be,pn		%xcc, short_ret				! CTI
-	 EX(STB		%g5, [%o0 - 1] ASINORMAL,
-			add %o2, 1)				! Store
-2:	ASI_SETSRC_NOBLK					! LSU	Group
-	EXO2(LDUB	[%o1] ASINORMAL, %g5)			! LOAD	Group
-	add		%o0, 2, %o0				! IEU0
-	EX2(LDUB	[%o1 + 1] ASINORMAL, %o5,
-			sub %o0, 2, %o0,
-			add %o2, %g0)				! LOAD	Group
-	add		%o1, 2, %o1				! IEU0
-	ASI_SETDST_NOBLK					! LSU	Group
-	subcc		%o2, 2, %o2				! IEU1	Group
-	EX(STB		%g5, [%o0 - 2] ASINORMAL,
-			add %o2, 2)				! Store
-	bne,pt		%xcc, 2b				! CTI
-	 EX(STB		%o5, [%o0 - 1] ASINORMAL,
-			add %o2, 1)				! Store
-short_ret:
-	NORMAL_RETL
-
-#ifndef __KERNEL__
-memcpy_private:
-memcpy:
-#ifndef REGS_64BIT
-	srl		%o2, 0, %o2				! IEU1	Group
-#endif	
-	brz,pn		%o2, short_ret				! CTI	Group
-	 mov		%o0, %g6				! IEU0
-#endif
-__memcpy_entry:
-	cmp		%o2, 15					! IEU1	Group
-	bleu,pn		%xcc, __memcpy_short			! CTI
-	 cmp		%o2, (64 * 6)				! IEU1	Group
-	bgeu,pn		%xcc, VIS_enter				! CTI
-	 andcc		%o0, 7, %g2				! IEU1	Group
-	sub		%o0, %o1, %g5				! IEU0
-	andcc		%g5, 3, %o5				! IEU1	Group
-	bne,pn		%xcc, memcpy_noVIS_misaligned		! CTI
-	 andcc		%o1, 3, %g0				! IEU1	Group
-#ifdef REGS_64BIT
-	be,a,pt		%xcc, 3f				! CTI
-	 andcc		%o1, 4, %g0				! IEU1	Group
-	andcc		%o1, 1, %g0				! IEU1	Group
-#else /* !REGS_64BIT */
-	be,pt		%xcc, 5f				! CTI
-	 andcc		%o1, 1, %g0				! IEU1	Group
-#endif /* !REGS_64BIT */
-	be,pn		%xcc, 4f				! CTI
-	 andcc		%o1, 2, %g0				! IEU1	Group
-	ASI_SETSRC_NOBLK					! LSU	Group
-	EXO2(LDUB	[%o1] ASINORMAL, %g2)			! Load	Group
-	add		%o1, 1, %o1				! IEU0
-	add		%o0, 1, %o0				! IEU1
-	sub		%o2, 1, %o2				! IEU0	Group
-	ASI_SETDST_NOBLK					! LSU	Group
-	bne,pn		%xcc, 5f				! CTI	Group
-	 EX(STB		%g2, [%o0 - 1] ASINORMAL,
-			add %o2, 1)				! Store
-4:	ASI_SETSRC_NOBLK					! LSU	Group
-	EXO2(LDUH	[%o1] ASINORMAL, %g2)			! Load	Group
-	add		%o1, 2, %o1				! IEU0
-	add		%o0, 2, %o0				! IEU1
-	ASI_SETDST_NOBLK					! LSU	Group
-	sub		%o2, 2, %o2				! IEU0
-	EX(STH		%g2, [%o0 - 2] ASINORMAL,
-			add %o2, 2)				! Store	Group + bubble
-#ifdef REGS_64BIT
-5:	andcc		%o1, 4, %g0				! IEU1
-3:	be,a,pn		%xcc, 2f				! CTI
-	 andcc		%o2, -128, %g7				! IEU1	Group
-	ASI_SETSRC_NOBLK					! LSU	Group
-	EXO2(LDUW	[%o1] ASINORMAL, %g5)			! Load	Group
-	add		%o1, 4, %o1				! IEU0
-	add		%o0, 4, %o0				! IEU1
-	ASI_SETDST_NOBLK					! LSU	Group
-	sub		%o2, 4, %o2				! IEU0	Group
-	EX(STW		%g5, [%o0 - 4] ASINORMAL,
-			add %o2, 4)				! Store
-	andcc		%o2, -128, %g7				! IEU1	Group
-2:	be,pn		%xcc, 3f				! CTI
-	 andcc		%o0, 4, %g0				! IEU1	Group
-	be,pn		%xcc, 82f + 4				! CTI	Group
-#else /* !REGS_64BIT */
-5:	andcc		%o2, -128, %g7				! IEU1
-	be,a,pn		%xcc, 41f				! CTI
-	 andcc		%o2, 0x70, %g7				! IEU1	Group
-#endif /* !REGS_64BIT */
-5:	MOVE_BIGCHUNK(o1, o0, 0x00, g1, g3, g5, o5)
-	MOVE_BIGCHUNK(o1, o0, 0x20, g1, g3, g5, o5)
-	MOVE_BIGCHUNK(o1, o0, 0x40, g1, g3, g5, o5)
-	MOVE_BIGCHUNK(o1, o0, 0x60, g1, g3, g5, o5)
-	EXT(5b,35f,VIScopyfixup1)
-35:	subcc		%g7, 128, %g7				! IEU1	Group
-	add		%o1, 128, %o1				! IEU0
-	bne,pt		%xcc, 5b				! CTI
-	 add		%o0, 128, %o0				! IEU0	Group
-3:	andcc		%o2, 0x70, %g7				! IEU1	Group
-41:	be,pn		%xcc, 80f				! CTI
-	 andcc		%o2, 8, %g0				! IEU1	Group
-#ifdef __KERNEL__
-79:	sethi		%hi(80f), %o5				! IEU0
-	sll		%g7, 1, %g5				! IEU0	Group
-	add		%o1, %g7, %o1				! IEU1
-	srl		%g7, 1, %g2				! IEU0  Group
-	sub		%o5, %g5, %o5				! IEU1
-	sub		%o5, %g2, %o5				! IEU0  Group
-	jmpl		%o5 + %lo(80f), %g0			! CTI	Group brk forced
-	 add		%o0, %g7, %o0				! IEU0	Group
-#else
-								! Clk1 8-(
-								! Clk2 8-(
-								! Clk3 8-(
-								! Clk4 8-(
-79:	rd		%pc, %o5				! PDU	Group
-	sll		%g7, 1, %g5				! IEU0	Group
-	add		%o1, %g7, %o1				! IEU1
-	sub		%o5, %g5, %o5				! IEU0  Group
-	jmpl		%o5 + %lo(80f - 79b), %g0		! CTI	Group brk forced
-	 add		%o0, %g7, %o0				! IEU0	Group
-#endif
-36:	MOVE_LASTCHUNK(o1, o0, 0x60, g2, g3, g5, o5)
-	MOVE_LASTCHUNK(o1, o0, 0x50, g2, g3, g5, o5)
-	MOVE_LASTCHUNK(o1, o0, 0x40, g2, g3, g5, o5)
-	MOVE_LASTCHUNK(o1, o0, 0x30, g2, g3, g5, o5)
-	MOVE_LASTCHUNK(o1, o0, 0x20, g2, g3, g5, o5)
-	MOVE_LASTCHUNK(o1, o0, 0x10, g2, g3, g5, o5)
-	MOVE_LASTCHUNK(o1, o0, 0x00, g2, g3, g5, o5)
-	EXT(36b,80f,VIScopyfixup2)
-80:	be,pt		%xcc, 81f				! CTI
-	 andcc		%o2, 4, %g0				! IEU1
-#ifdef REGS_64BIT
-	ASI_SETSRC_NOBLK					! LSU	Group
-	EX(LDX		[%o1] ASINORMAL, %g2,
-			and %o2, 0xf)				! Load	Group
-	add		%o0, 8, %o0				! IEU0
-	ASI_SETDST_NOBLK					! LSU	Group
-	EX(STW		%g2, [%o0 - 0x4] ASINORMAL,
-			and %o2, 0xf)				! Store	Group
-	add		%o1, 8, %o1				! IEU1
-	srlx		%g2, 32, %g2				! IEU0	Group
-	EX2(STW		%g2, [%o0 - 0x8] ASINORMAL,
-			and %o2, 0xf, %o2,
-			sub %o2, 4)				! Store
-#else /* !REGS_64BIT */
-	lduw		[%o1], %g2				! Load	Group
-	add		%o0, 8, %o0				! IEU0
-	lduw		[%o1 + 0x4], %g3			! Load	Group
-	add		%o1, 8, %o1				! IEU0
-	stw		%g2, [%o0 - 0x8]			! Store	Group
-	stw		%g3, [%o0 - 0x4]			! Store	Group
-#endif /* !REGS_64BIT */
-81:	be,pt		%xcc, 1f				! CTI
-	 andcc		%o2, 2, %g0				! IEU1	Group
-	ASI_SETSRC_NOBLK					! LSU	Group
-	EX(LDUW		[%o1] ASINORMAL, %g2,
-			and %o2, 0x7)				! Load	Group
-	add		%o1, 4, %o1				! IEU0
-	ASI_SETDST_NOBLK					! LSU	Group
-	EX(STW		%g2, [%o0] ASINORMAL,
-			and %o2, 0x7)				! Store	Group
-	add		%o0, 4, %o0				! IEU0
-1:	be,pt		%xcc, 1f				! CTI
-	 andcc		%o2, 1, %g0				! IEU1	Group
-	ASI_SETSRC_NOBLK					! LSU	Group
-	EX(LDUH		[%o1] ASINORMAL, %g2,
-			and %o2, 0x3)				! Load	Group
-	add		%o1, 2, %o1				! IEU0
-	ASI_SETDST_NOBLK					! LSU	Group
-	EX(STH		%g2, [%o0] ASINORMAL,
-			and %o2, 0x3)				! Store	Group
-	add		%o0, 2, %o0				! IEU0
-1:	be,pt		%xcc, normal_retl			! CTI
-	 nop							! IEU1
-	ASI_SETSRC_NOBLK					! LSU	Group
-	EX(LDUB		[%o1] ASINORMAL, %g2,
-			add %g0, 1)				! Load	Group
-	ASI_SETDST_NOBLK					! LSU	Group
-	EX(STB		%g2, [%o0] ASINORMAL,
-			add %g0, 1)				! Store	Group + bubble
-normal_retl:
-	NORMAL_RETL
-
-#ifdef REGS_64BIT
-82:	MOVE_BIGALIGNCHUNK(o1, o0, 0x00, g1, g3, g5, o5)
-	MOVE_BIGALIGNCHUNK(o1, o0, 0x40, g1, g3, g5, o5)
-	EXT(82b,37f,VIScopyfixup3)
-37:	subcc		%g7, 128, %g7				! IEU1	Group
-	add		%o1, 128, %o1				! IEU0
-	bne,pt		%xcc, 82b				! CTI
-	 add		%o0, 128, %o0				! IEU0	Group
-	andcc		%o2, 0x70, %g7				! IEU1
-	be,pn		%xcc, 84f				! CTI
-	 andcc		%o2, 8, %g0				! IEU1	Group
-#ifdef __KERNEL__
-83:	srl		%g7, 1, %g5				! IEU0
-	sethi		%hi(84f), %o5				! IEU0	Group
-	add		%g7, %g5, %g5				! IEU1
-	add		%o1, %g7, %o1				! IEU0	Group
-	sub		%o5, %g5, %o5				! IEU1
-	jmpl		%o5 + %lo(84f), %g0			! CTI	Group brk forced
-	 add		%o0, %g7, %o0				! IEU0	Group
-#else
-								! Clk1 8-(
-								! Clk2 8-(
-								! Clk3 8-(
-								! Clk4 8-(
-83:	rd		%pc, %o5				! PDU	Group
-	add		%o1, %g7, %o1				! IEU0	Group
-	sub		%o5, %g7, %o5				! IEU1
-	jmpl		%o5 + %lo(84f - 83b), %g0		! CTI	Group brk forced
-	 add		%o0, %g7, %o0				! IEU0	Group
-#endif
-38:	MOVE_LASTALIGNCHUNK(o1, o0, 0x60, g2, g3)
-	MOVE_LASTALIGNCHUNK(o1, o0, 0x50, g2, g3)
-	MOVE_LASTALIGNCHUNK(o1, o0, 0x40, g2, g3)
-	MOVE_LASTALIGNCHUNK(o1, o0, 0x30, g2, g3)
-	MOVE_LASTALIGNCHUNK(o1, o0, 0x20, g2, g3)
-	MOVE_LASTALIGNCHUNK(o1, o0, 0x10, g2, g3)
-	MOVE_LASTALIGNCHUNK(o1, o0, 0x00, g2, g3)
-	EXT(38b,84f,VIScopyfixup4)
-84:	be,pt		%xcc, 85f				! CTI	Group
-	 andcc		%o2, 4, %g0				! IEU1
-	ASI_SETSRC_NOBLK					! LSU	Group
-	EX(LDX		[%o1] ASINORMAL, %g2,
-			and %o2, 0xf)				! Load	Group
-	add		%o0, 8, %o0				! IEU0
-	ASI_SETDST_NOBLK					! LSU	Group
-	add		%o1, 8, %o1				! IEU0	Group
-	EX(STX		%g2, [%o0 - 0x8] ASINORMAL,
-			and %o2, 0xf)				! Store
-85:	be,pt		%xcc, 1f				! CTI
-	 andcc		%o2, 2, %g0				! IEU1	Group
-	ASI_SETSRC_NOBLK					! LSU	Group
-	EX(LDUW		[%o1] ASINORMAL, %g2,
-			and %o2, 0x7)				! Load	Group
-	add		%o0, 4, %o0				! IEU0
-	ASI_SETDST_NOBLK					! LSU	Group
-	add		%o1, 4, %o1				! IEU0	Group
-	EX(STW		%g2, [%o0 - 0x4] ASINORMAL,
-			and %o2, 0x7)				! Store
-1:	be,pt		%xcc, 1f				! CTI
-	 andcc		%o2, 1, %g0				! IEU1	Group
-	ASI_SETSRC_NOBLK					! LSU	Group
-	EX(LDUH		[%o1] ASINORMAL, %g2,
-			and %o2, 0x3)				! Load	Group
-	add		%o0, 2, %o0				! IEU0
-	ASI_SETDST_NOBLK					! LSU	Group
-	add		%o1, 2, %o1				! IEU0	Group
-	EX(STH		%g2, [%o0 - 0x2] ASINORMAL,
-			and %o2, 0x3)				! Store
-1:	be,pt		%xcc, 1f				! CTI
-	 nop							! IEU0	Group
-	ASI_SETSRC_NOBLK					! LSU	Group
-	EX(LDUB		[%o1] ASINORMAL, %g2,
-			add %g0, 1)				! Load	Group
-	ASI_SETDST_NOBLK					! LSU	Group
-	EX(STB		%g2, [%o0] ASINORMAL,
-			add %g0, 1)				! Store	Group + bubble
-1:	NORMAL_RETL
-#endif	/* REGS_64BIT */
-
-memcpy_noVIS_misaligned:
-	brz,pt			%g2, 2f				! CTI	Group
-	 mov			8, %g1				! IEU0
-	sub			%g1, %g2, %g2			! IEU0	Group
-	sub			%o2, %g2, %o2			! IEU0	Group
-1:	ASI_SETSRC_NOBLK					! LSU	Group
-	EX(LDUB			[%o1] ASINORMAL, %g5,
-				add %o2, %g2)			! Load	Group
-	add			%o1, 1, %o1			! IEU0
-	add			%o0, 1, %o0			! IEU1
-	ASI_SETDST_NOBLK					! LSU	Group
-	subcc			%g2, 1, %g2			! IEU1	Group
-	bne,pt			%xcc, 1b			! CTI
-	 EX2(STB		%g5, [%o0 - 1] ASINORMAL,
-				add %o2, %g2, %o2,
-				add %o2, 1)			! Store
-2:
-#ifdef __KERNEL__
-	VISEntry
-#endif
-	andn			%o2, 7, %g5 			! IEU0	Group
-	and			%o2, 7, %o2			! IEU1
-	fmovd			%f0, %f2			! FPU
-	ASI_SETSRC_NOBLK					! LSU	Group
-	alignaddr		%o1, %g0, %g1			! GRU	Group
-	EXO2(LDDF		[%g1] ASINORMAL, %f4)		! Load	Group
-1:	EX(LDDF			[%g1 + 0x8] ASINORMAL, %f6,
-				add %o2, %g5)			! Load	Group
-	add			%g1, 0x8, %g1			! IEU0	Group
-	subcc			%g5, 8, %g5			! IEU1
-	ASI_SETDST_NOBLK					! LSU	Group
-	faligndata		%f4, %f6, %f0			! GRU	Group
-	EX2(STDF		%f0, [%o0] ASINORMAL,
-				add %o2, %g5, %o2,
-				add %o2, 8)			! Store
-	add			%o1, 8, %o1			! IEU0	Group
-	be,pn			%xcc, end_cruft			! CTI
-	 add			%o0, 8, %o0			! IEU1
-	ASI_SETSRC_NOBLK					! LSU	Group
-	EX(LDDF			[%g1 + 0x8] ASINORMAL, %f4,
-				add %o2, %g5)			! Load	Group
-	add			%g1, 8, %g1			! IEU0
-	subcc			%g5, 8, %g5			! IEU1
-	ASI_SETDST_NOBLK					! LSU	Group
-	faligndata		%f6, %f4, %f0			! GRU	Group
-	EX2(STDF		%f0, [%o0] ASINORMAL,
-				add %o2, %g5, %o2,
-				add %o2, 8)			! Store
-	add			%o1, 8, %o1			! IEU0
-	ASI_SETSRC_NOBLK					! LSU	Group
-	bne,pn			%xcc, 1b			! CTI	Group
-	 add			%o0, 8, %o0			! IEU0
-end_cruft:
-	brz,pn			%o2, fpu_retl			! CTI	Group
-#ifndef __KERNEL__
-	 nop							! IEU0
-#else
-	 ASI_SETSRC_NOBLK					! LSU	Group
-#endif
-	EXO2(LDUB	[%o1] ASINORMAL, %g5)			! LOAD
-	add		%o1, 1, %o1				! IEU0
-	add		%o0, 1, %o0				! IEU1
-	ASI_SETDST_NOBLK					! LSU	Group
-	subcc		%o2, 1, %o2				! IEU1
-	bne,pt		%xcc, vis_slp				! CTI
-	 EX(STB		%g5, [%o0 - 1] ASINORMAL,
-			add %o2, 1)				! Store	Group
-fpu_retl:
-	FPU_RETL
-
-#ifdef __KERNEL__
-		.section	.fixup
-		.align		4
-VIScopyfixup_reto2:
-		mov		%o2, %o1
-VIScopyfixup_ret:
-		/* If this is copy_from_user(), zero out the rest of the
-		 * kernel buffer.
-		 */
-		ldub		[%g6 + TI_CURRENT_DS], %o4
-		andcc		asi_src, 0x1, %g0
-		be,pt		%icc, 1f
-		 VISExit
-		andcc		asi_dest, 0x1, %g0
-		bne,pn		%icc, 1f
-		 nop
-		save		%sp, -160, %sp
-		mov		%i0, %o0
-		call		__bzero
-		 mov		%i1, %o1
-		restore
-1:		mov		%o1, %o0
-		retl
-		 wr		%o4, %g0, %asi
-VIScopyfixup1:	subcc		%g2, 18, %g2
-		add		%o0, 32, %o0
-		bgeu,a,pt	%icc, VIScopyfixup1
-		 sub		%g7, 32, %g7
-		sub		%o0, 32, %o0
-		rd		%pc, %g5
-		add		%g2, (18 + 16), %g2
-		ldub		[%g5 + %g2], %g2
-		ba,a,pt		%xcc, 2f
-.byte		0, 0, 0, 0, 0, 0, 0, 4, 4, 8, 12, 12, 16, 20, 20, 24, 28, 28
-		.align		4
-VIScopyfixup2:	mov		(7 * 16), %g7
-1:		subcc		%g2, 10, %g2
-		bgeu,a,pt	%icc, 1b
-		 sub		%g7, 16, %g7
-		sub		%o0, %g7, %o0
-		rd		%pc, %g5
-		add		%g2, (10 + 16), %g2
-		ldub		[%g5 + %g2], %g2
-		ba,a,pt		%xcc, 4f
-.byte		0, 0, 0, 0, 0, 4, 4, 8, 12, 12
-		.align		4
-VIScopyfixup3:	subcc		%g2, 10, %g2
-		add		%o0, 32, %o0
-		bgeu,a,pt	%icc, VIScopyfixup3
-		 sub		%g7, 32, %g7
-		sub		%o0, 32, %o0
-		rd		%pc, %g5
-		add		%g2, (10 + 16), %g2
-		ldub		[%g5 + %g2], %g2
-		ba,a,pt		%xcc, 2f
-.byte		0, 0, 0, 0, 0, 0, 0, 8, 16, 24
-		.align		4
-2:		and		%o2, 0x7f, %o2
-		sub		%g7, %g2, %g7
-		ba,pt		%xcc, VIScopyfixup_ret
-		 add		%g7, %o2, %o1
-VIScopyfixup4:	mov		(7 * 16), %g7
-3:		subcc		%g2, 6, %g2
-		bgeu,a,pt	%icc, 3b
-		 sub		%g7, 16, %g7
-		sub		%o0, %g7, %o0
-		rd		%pc, %g5
-		add		%g2, (6 + 16), %g2
-		ldub		[%g5 + %g2], %g2
-		ba,a,pt		%xcc, 4f
-.byte		0, 0, 0, 0, 0, 8
-		.align		4
-4:		and		%o2, 0xf, %o2
-		sub		%g7, %g2, %g7
-		ba,pt		%xcc, VIScopyfixup_ret
-		 add		%g7, %o2, %o1
-VIScopyfixup_vis2:
-		sub		%o2, 0x40, %o2
-VIScopyfixup_vis0:
-		add		%o2, 0x80, %o2
-VIScopyfixup_vis1:
-		add		%g7, %g3, %g7
-		ba,pt		%xcc, VIScopyfixup_ret
-		 add		%o2, %g7, %o1
-VIScopyfixup_vis4:
-		add		%g3, 8, %g3
-VIScopyfixup_vis3:
-		add		%g3, 8, %g3
-		ba,pt		%xcc, VIScopyfixup_ret
-		 add		%o2, %g3, %o1
-#endif
-
-#ifdef __KERNEL__
-		.text
-		.align		32
-
-		.globl		__memmove
-		.type		__memmove,@function
-
-		.globl		memmove
-		.type		memmove,@function
-
-memmove:
-__memmove:	cmp		%o0, %o1
-		blu,pt		%xcc, memcpy_private
-		 sub		%o0, %o1, %g5
-		add		%o1, %o2, %g3
-		cmp		%g3, %o0
-		bleu,pt		%xcc, memcpy_private
-		 add		%o1, %o2, %g5
-		add		%o0, %o2, %o5
-
-		sub		%g5, 1, %o1
-		sub		%o5, 1, %o0
-1:		ldub		[%o1], %g5
-		subcc		%o2, 1, %o2
-		sub		%o1, 1, %o1
-		stb		%g5, [%o0]
-		bne,pt		%icc, 1b
-		 sub		%o0, 1, %o0
-
-		retl
-		 clr		%o0
-#endif
diff -Nru a/arch/sparc64/lib/atomic.S b/arch/sparc64/lib/atomic.S
--- a/arch/sparc64/lib/atomic.S	2004-10-18 14:57:03 -07:00
+++ b/arch/sparc64/lib/atomic.S	2004-10-18 14:57:03 -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-10-18 14:57:03 -07:00
+++ b/arch/sparc64/lib/bitops.S	2004-10-18 14:57:03 -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,41 +69,4 @@
 2:	retl
 	 membar	#StoreLoad | #StoreStore
 	nop
-
-	.globl	___test_and_set_le_bit
-___test_and_set_le_bit:	/* %o0=nr, %o1=addr */
-	srlx	%o0, 5, %g1
-	mov	1, %g5
-	sllx	%g1, 2, %g3
-	and	%o0, 31, %g2
-	sllx	%g5, %g2, %g5
-	add	%o1, %g3, %o1
-	lduwa	[%o1] ASI_PL, %g7
-1:	andcc	%g7, %g5, %o0
-	bne,pn	%icc, 2f
-	 xor	%g7, %g5, %g1
-	casa	[%o1] ASI_PL, %g7, %g1
-	cmp	%g7, %g1
-	bne,a,pn %icc, 1b
-	 lduwa	[%o1] ASI_PL, %g7
-2:	retl
-	 membar	#StoreLoad | #StoreStore
-
-	.globl	___test_and_clear_le_bit
-___test_and_clear_le_bit:	/* %o0=nr, %o1=addr */
-	srlx	%o0, 5, %g1
-	mov	1, %g5
-	sllx	%g1, 2, %g3
-	and	%o0, 31, %g2
-	sllx	%g5, %g2, %g5
-	add	%o1, %g3, %o1
-	lduwa	[%o1] ASI_PL, %g7
-1:	andcc	%g7, %g5, %o0
-	be,pn	%icc, 2f
-	 xor	%g7, %g5, %g1
-	casa	[%o1] ASI_PL, %g7, %g1
-	cmp	%g7, %g1
-	bne,a,pn %icc, 1b
-	 lduwa	[%o1] ASI_PL, %g7
-2:	retl
-	 membar	#StoreLoad | #StoreStore
+	.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
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/arch/sparc64/lib/copy_in_user.S	2004-10-18 14:57:21 -07:00
@@ -0,0 +1,119 @@
+/* copy_in_user.S: Copy from userspace to userspace.
+ *
+ * Copyright (C) 1999, 2000, 2004 David S. Miller (davem@redhat.com)
+ */
+
+#include <asm/asi.h>
+
+#define XCC xcc
+
+#define EX(x,y)			\
+98:	x,y;			\
+	.section .fixup;	\
+	.align 4;		\
+99:	retl;			\
+	 mov 1, %o0;		\
+	.section __ex_table;	\
+	.align 4;		\
+	.word 98b, 99b;		\
+	.text;			\
+	.align 4;
+
+	.register	%g2,#scratch
+	.register	%g3,#scratch
+
+	.text
+	.align	32
+
+	/* Don't try to get too fancy here, just nice and
+	 * simple.  This is predominantly used for well aligned
+	 * small copies in the compat layer.  It is also used
+	 * to copy register windows around during thread cloning.
+	 */
+
+	.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
+	 * cheap.
+	 */
+	rd		%asi, %g1
+	cmp		%g1, ASI_AIUS
+	bne,pn		%icc, memcpy_user_stub
+	 nop
+
+	cmp		%o2, 0
+	be,pn		%XCC, 85f
+	 or		%o0, %o1, %o3
+	cmp		%o2, 16
+	bleu,a,pn	%XCC, 80f
+	 or		%o3, %o2, %o3
+
+	/* 16 < len <= 64 */
+	andcc		%o3, 0x7, %g0
+	bne,pn		%XCC, 90f
+	 sub		%o0, %o1, %o3
+
+	andn		%o2, 0x7, %o4
+	and		%o2, 0x7, %o2
+1:	subcc		%o4, 0x8, %o4
+	EX(ldxa [%o1] %asi, %o5)
+	EX(stxa %o5, [%o1 + %o3] ASI_AIUS)
+	bgu,pt		%XCC, 1b
+	 add		%o1, 0x8, %o1
+	andcc		%o2, 0x4, %g0
+	be,pt		%XCC, 1f
+	 nop
+	sub		%o2, 0x4, %o2
+	EX(lduwa [%o1] %asi, %o5)
+	EX(stwa %o5, [%o1 + %o3] ASI_AIUS)
+	add		%o1, 0x4, %o1
+1:	cmp		%o2, 0
+	be,pt		%XCC, 85f
+	 nop
+	ba,pt		%xcc, 90f
+	 nop
+
+80:	/* 0 < len <= 16 */
+	andcc		%o3, 0x3, %g0
+	bne,pn		%XCC, 90f
+	 sub		%o0, %o1, %o3
+
+82:
+	subcc		%o2, 4, %o2
+	EX(lduwa [%o1] %asi, %g1)
+	EX(stwa %g1, [%o1 + %o3] ASI_AIUS)
+	bgu,pt		%XCC, 82b
+	 add		%o1, 4, %o1
+
+85:	retl
+	 clr		%o0
+
+	.align	32
+90:
+	subcc		%o2, 1, %o2
+	EX(lduba [%o1] %asi, %g1)
+	EX(stba %g1, [%o1 + %o3] ASI_AIUS)
+	bgu,pt		%XCC, 90b
+	 add		%o1, 1, %o1
+	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
+	mov		%i1, %o1
+	call		memcpy
+	 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-10-18 14:56:49 -07:00
+++ b/arch/sparc64/lib/copy_page.S	2004-10-18 14:56:49 -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/debuglocks.c b/arch/sparc64/lib/debuglocks.c
--- a/arch/sparc64/lib/debuglocks.c	2004-10-18 14:56:33 -07:00
+++ b/arch/sparc64/lib/debuglocks.c	2004-10-18 14:56:33 -07:00
@@ -84,7 +84,7 @@
 	put_cpu();
 }
 
-int _spin_trylock(spinlock_t *lock)
+int _do_spin_trylock(spinlock_t *lock)
 {
 	unsigned long val, caller;
 	int cpu = get_cpu();
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-10-18 14:57:21 -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/iomap.c b/arch/sparc64/lib/iomap.c
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/arch/sparc64/lib/iomap.c	2004-10-18 14:57:22 -07:00
@@ -0,0 +1,48 @@
+/*
+ * Implement the sparc64 iomap interfaces
+ */
+#include <linux/pci.h>
+#include <linux/module.h>
+#include <asm/io.h>
+
+/* Create a virtual mapping cookie for an IO port range */
+void __iomem *ioport_map(unsigned long port, unsigned int nr)
+{
+	return (void __iomem *) (unsigned long) port;
+}
+
+void ioport_unmap(void __iomem *addr)
+{
+	/* Nothing to do */
+}
+EXPORT_SYMBOL(ioport_map);
+EXPORT_SYMBOL(ioport_unmap);
+
+/* Create a virtual mapping cookie for a PCI BAR (memory or IO) */
+void __iomem *pci_iomap(struct pci_dev *dev, int bar, unsigned long maxlen)
+{
+	unsigned long start = pci_resource_start(dev, bar);
+	unsigned long len = pci_resource_len(dev, bar);
+	unsigned long flags = pci_resource_flags(dev, bar);
+
+	if (!len || !start)
+		return NULL;
+	if (maxlen && len > maxlen)
+		len = maxlen;
+	if (flags & IORESOURCE_IO)
+		return ioport_map(start, len);
+	if (flags & IORESOURCE_MEM) {
+		if (flags & IORESOURCE_CACHEABLE)
+			return ioremap(start, len);
+		return ioremap_nocache(start, len);
+	}
+	/* What? */
+	return NULL;
+}
+
+void pci_iounmap(struct pci_dev *dev, void __iomem * addr)
+{
+	/* nothing to do */
+}
+EXPORT_SYMBOL(pci_iomap);
+EXPORT_SYMBOL(pci_iounmap);
diff -Nru a/arch/sparc64/lib/ipcsum.S b/arch/sparc64/lib/ipcsum.S
--- a/arch/sparc64/lib/ipcsum.S	2004-10-18 14:56:29 -07:00
+++ b/arch/sparc64/lib/ipcsum.S	2004-10-18 14:56:29 -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
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/arch/sparc64/lib/memmove.S	2004-10-18 14:57:24 -07:00
@@ -0,0 +1,33 @@
+/* memmove.S: Simple memmove implementation.
+ *
+ * Copyright (C) 1997, 2004 David S. Miller (davem@redhat.com)
+ * Copyright (C) 1996, 1997, 1998, 1999 Jakub Jelinek (jj@ultra.linux.cz)
+ */
+
+	.text
+	.align		32
+	.globl		memmove
+	.type		memmove,#function
+memmove:
+	mov		%o0, %g1
+	cmp		%o0, %o1
+	blu,pt		%xcc, memcpy
+	 sub		%o0, %o1, %g5
+	add		%o1, %o2, %g3
+	cmp		%g3, %o0
+	bleu,pt		%xcc, memcpy
+	 add		%o1, %o2, %g5
+	add		%o0, %o2, %o5
+
+	sub		%g5, 1, %o1
+	sub		%o5, 1, %o0
+1:	ldub		[%o1], %g5
+	subcc		%o2, 1, %o2
+	sub		%o1, 1, %o1
+	stb		%g5, [%o0]
+	bne,pt		%icc, 1b
+	 sub		%o0, 1, %o0
+
+	retl
+	 mov		%g1, %o0
+	.size		memmove, .-memmove
diff -Nru a/arch/sparc64/lib/rwlock.S b/arch/sparc64/lib/rwlock.S
--- a/arch/sparc64/lib/rwlock.S	2004-10-18 14:56:29 -07:00
+++ /dev/null	Wed Dec 31 16:00:00 196900
@@ -1,85 +0,0 @@
-/* $Id: rwlock.S,v 1.4 2000/09/09 00:00:34 davem Exp $
- * rwlocks.S: These things are too big to do inline.
- *
- * Copyright (C) 1999 David S. Miller (davem@redhat.com)
- */
-
-	.text
-	.align	64
-
-	/* The non-contention read lock usage is 2 cache lines. */
-
-	.globl	__read_lock, __read_unlock
-__read_lock: /* %o0 = lock_ptr */
-	ldsw		[%o0], %g5
-	brlz,pn		%g5, __read_wait_for_writer
-4:	 add		%g5, 1, %g7
-	cas		[%o0], %g5, %g7
-	cmp		%g5, %g7
-	bne,pn		%icc, __read_lock
-	 membar		#StoreLoad | #StoreStore
-99:	retl
-	 nop
-__read_unlock: /* %o0 = lock_ptr */
-	lduw		[%o0], %g5
-	sub		%g5, 1, %g7
-	cas		[%o0], %g5, %g7
-	cmp		%g5, %g7
-	be,pt		%xcc, 99b
-	 membar		#StoreLoad | #StoreStore
-	ba,a,pt		%xcc, __read_unlock
-
-__read_wait_for_writer:
-	ldsw		[%o0], %g5
-	brlz,pt		%g5, __read_wait_for_writer
-	 membar		#LoadLoad
-	ba,a,pt		%xcc, 4b
-__write_wait_for_any:
-	lduw		[%o0], %g5
-	brnz,pt		%g5, __write_wait_for_any
-	 membar		#LoadLoad
-	ba,a,pt		%xcc, 4f
-
-	.align		64
-	.globl		__write_unlock
-__write_unlock: /* %o0 = lock_ptr */
-	membar		#LoadStore | #StoreStore
-	retl
-	 stw		%g0, [%o0]
-
-	.globl		__write_lock
-__write_lock: /* %o0 = lock_ptr */
-	sethi		%hi(0x80000000), %g2
-
-1:	lduw		[%o0], %g5
-	brnz,pn		%g5, __write_wait_for_any
-4:	 or		%g5, %g2, %g7
-	cas		[%o0], %g5, %g7
-
-	cmp		%g5, %g7
-	be,pt		%icc, 99b
-	 membar		#StoreLoad | #StoreStore
-	ba,a,pt		%xcc, 1b
-
-	.globl		__write_trylock
-__write_trylock: /* %o0 = lock_ptr */
-	sethi		%hi(0x80000000), %g2
-1:	lduw		[%o0], %g5
-	brnz,pn		%g5, __write_trylock_fail
-4:	 or		%g5, %g2, %g7
-
-	cas		[%o0], %g5, %g7
-	cmp		%g5, %g7
-	be,pt		%icc, __write_trylock_succeed
-	 membar		#StoreLoad | #StoreStore
-
-	ba,pt		%xcc, 1b
-	 nop
-__write_trylock_succeed:
-	retl
-	 mov		1, %o0
-
-__write_trylock_fail:
-	retl
-	 mov		0, %o0
-
diff -Nru a/arch/sparc64/lib/splock.S b/arch/sparc64/lib/splock.S
--- a/arch/sparc64/lib/splock.S	2004-10-18 14:56:50 -07:00
+++ /dev/null	Wed Dec 31 16:00:00 196900
@@ -1,35 +0,0 @@
-/* splock.S: Spinlock primitives too large to inline.
- *
- * Copyright (C) 2004 David S. Miller (davem@redhat.com)
- */
-
-	.text
-	.align	64
-
-	.globl		_raw_spin_lock
-_raw_spin_lock:		/* %o0 = lock_ptr */
-1:	ldstub		[%o0], %g7
-	brnz,pn		%g7, 2f
-	 membar		#StoreLoad | #StoreStore
-	retl
-	 nop
-2:	ldub		[%o0], %g7
-	brnz,pt		%g7, 2b
-	 membar		#LoadLoad
-	ba,a,pt		%xcc, 1b
-
-	.globl	_raw_spin_lock_flags
-_raw_spin_lock_flags:	/* %o0 = lock_ptr, %o1 = irq_flags */
-1:	ldstub		[%o0], %g7
-	brnz,pn		%g7, 2f
-	 membar		#StoreLoad | #StoreStore
-	retl
-	 nop
-
-2:	rdpr		%pil, %g2		! Save PIL
-	wrpr		%o1, %pil		! Set previous PIL
-3:	ldub		[%o0], %g7		! Spin on lock set
-	brnz,pt		%g7, 3b
-	 membar		#LoadLoad
-	ba,pt		%xcc, 1b		! Retry lock acquire
-	 wrpr		%g2, %pil		! Restore PIL
diff -Nru a/arch/sparc64/lib/strlen.S b/arch/sparc64/lib/strlen.S
--- a/arch/sparc64/lib/strlen.S	2004-10-18 14:56:27 -07:00
+++ b/arch/sparc64/lib/strlen.S	2004-10-18 14:56:27 -07:00
@@ -9,9 +9,9 @@
 #define HI_MAGIC 0x80808080
 
 	.align	32
-	.global strlen, __strlen
+	.globl	strlen
+	.type	strlen,#function
 strlen:
-__strlen:
 	mov	%o0, %o1
 	andcc	%o0, 3, %g0
 	be,pt	%icc, 9f
@@ -76,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-10-18 14:56:33 -07:00
+++ b/arch/sparc64/lib/strncmp.S	2004-10-18 14:56:33 -07:00
@@ -7,9 +7,9 @@
 #include <asm/asi.h>
 
 	.text
-	.align 4
-	.global __strncmp, strncmp
-__strncmp:
+	.align	32
+	.globl	strncmp
+	.type	strncmp,#function
 strncmp:
 	brlez,pn %o2, 3f
 	 lduba	[%o0] (ASI_PNF), %o3
@@ -29,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	2004-10-18 14:57:04 -07:00
+++ b/arch/sparc64/lib/strncpy_from_user.S	2004-10-18 14:57:04 -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/user_fixup.c b/arch/sparc64/lib/user_fixup.c
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/arch/sparc64/lib/user_fixup.c	2004-10-18 14:57:23 -07:00
@@ -0,0 +1,68 @@
+/* user_fixup.c: Fix up user copy faults.
+ *
+ * Copyright (C) 2004 David S. Miller <davem@redhat.com>
+ */
+
+#include <linux/compiler.h>
+#include <linux/kernel.h>
+#include <linux/string.h>
+#include <linux/errno.h>
+#include <asm/uaccess.h>
+
+/* Calculating the exact fault address when using
+ * block loads and stores can be very complicated.
+ * Instead of trying to be clever and handling all
+ * of the cases, just fix things up simply here.
+ */
+
+unsigned long copy_from_user_fixup(void *to, const void __user *from, unsigned long size)
+{
+	char *dst = to;
+	const char __user *src = from;
+
+	while (size--) {
+		if (__get_user(*dst, src))
+			break;
+		dst++;
+		src++;
+	}
+
+	if (size)
+		memset(dst, 0, size);
+
+	return size;
+}
+
+unsigned long copy_to_user_fixup(void __user *to, const void *from, unsigned long size)
+{
+	char __user *dst = to;
+	const char *src = from;
+
+	while (size--) {
+		if (__put_user(*src, dst))
+			break;
+		dst++;
+		src++;
+	}
+
+	return size;
+}
+
+unsigned long copy_in_user_fixup(void __user *to, void __user *from, unsigned long size)
+{
+	char __user *dst = to;
+	char __user *src = from;
+
+	while (size--) {
+		char tmp;
+
+		if (__get_user(tmp, src))
+			break;
+		if (__put_user(tmp, dst))
+			break;
+		dst++;
+		src++;
+	}
+
+	return size;
+}
diff -Nru a/arch/sparc64/lib/xor.S b/arch/sparc64/lib/xor.S
--- a/arch/sparc64/lib/xor.S	2004-10-18 14:57:04 -07:00
+++ b/arch/sparc64/lib/xor.S	2004-10-18 14:57:04 -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/fault.c b/arch/sparc64/mm/fault.c
--- a/arch/sparc64/mm/fault.c	2004-10-18 14:57:04 -07:00
+++ b/arch/sparc64/mm/fault.c	2004-10-18 14:57:04 -07:00
@@ -27,6 +27,7 @@
 #include <asm/asi.h>
 #include <asm/lsu.h>
 #include <asm/sections.h>
+#include <asm/kdebug.h>
 
 #define ELEMENTS(arr) (sizeof (arr)/sizeof (arr[0]))
 
@@ -147,6 +148,9 @@
 	printk(KERN_ALERT "tsk->{mm,active_mm}->pgd = %016lx\n",
 	       (tsk->mm ? (unsigned long) tsk->mm->pgd :
 		          (unsigned long) tsk->active_mm->pgd));
+	if (notify_die(DIE_GPF, "general protection fault", regs,
+		       0, 0, SIGSEGV) == NOTIFY_STOP)
+		return;
 	die_if_kernel("Oops", regs);
 }
 
@@ -318,8 +322,13 @@
 	int si_code, fault_code;
 	unsigned long address;
 
-	si_code = SEGV_MAPERR;
 	fault_code = get_thread_fault_code();
+
+	if (notify_die(DIE_PAGE_FAULT, "page_fault", regs,
+		       fault_code, 0, SIGSEGV) == NOTIFY_STOP)
+		return;
+
+	si_code = SEGV_MAPERR;
 	address = current_thread_info()->fault_address;
 
 	if ((fault_code & FAULT_CODE_ITLB) &&
diff -Nru a/arch/sparc64/mm/init.c b/arch/sparc64/mm/init.c
--- a/arch/sparc64/mm/init.c	2004-10-18 14:56:28 -07:00
+++ b/arch/sparc64/mm/init.c	2004-10-18 14:56:28 -07:00
@@ -68,6 +68,7 @@
 extern char  _start[], _end[];
 
 /* Initial ramdisk setup */
+extern unsigned long sparc_ramdisk_image64;
 extern unsigned int sparc_ramdisk_image;
 extern unsigned int sparc_ramdisk_size;
 
@@ -1279,10 +1280,12 @@
 
 #ifdef CONFIG_BLK_DEV_INITRD
 	/* Now have to check initial ramdisk, so that bootmap does not overwrite it */
-	if (sparc_ramdisk_image) {
-		if (sparc_ramdisk_image >= (unsigned long)_end - 2 * PAGE_SIZE)
-			sparc_ramdisk_image -= KERNBASE;
-		initrd_start = sparc_ramdisk_image + phys_base;
+	if (sparc_ramdisk_image || sparc_ramdisk_image64) {
+		unsigned long ramdisk_image = sparc_ramdisk_image ?
+			sparc_ramdisk_image : sparc_ramdisk_image64;
+		if (ramdisk_image >= (unsigned long)_end - 2 * PAGE_SIZE)
+			ramdisk_image -= KERNBASE;
+		initrd_start = ramdisk_image + phys_base;
 		initrd_end = initrd_start + sparc_ramdisk_size;
 		if (initrd_end > end_of_phys_memory) {
 			printk(KERN_CRIT "initrd extends beyond end of memory "
@@ -1325,6 +1328,10 @@
 		size = initrd_end - initrd_start;
 
 		/* Resert the initrd image area. */
+#ifdef CONFIG_DEBUG_BOOTMEM
+		prom_printf("reserve_bootmem(initrd): base[%llx] size[%lx]\n",
+			initrd_start, initrd_end);
+#endif
 		reserve_bootmem(initrd_start, size);
 		*pages_avail -= PAGE_ALIGN(size) >> PAGE_SHIFT;
 
@@ -1377,7 +1384,7 @@
 	if ((real_end > ((unsigned long)KERNBASE + 0x400000)))
 		bigkernel = 1;
 #ifdef CONFIG_BLK_DEV_INITRD
-	if (sparc_ramdisk_image)
+	if (sparc_ramdisk_image || sparc_ramdisk_image64)
 		real_end = (PAGE_ALIGN(real_end) + PAGE_ALIGN(sparc_ramdisk_size));
 #endif
 
@@ -1502,7 +1509,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/sparc64/solaris/misc.c b/arch/sparc64/solaris/misc.c
--- a/arch/sparc64/solaris/misc.c	2004-10-18 14:57:04 -07:00
+++ b/arch/sparc64/solaris/misc.c	2004-10-18 14:57:04 -07:00
@@ -137,21 +137,34 @@
 	return sunos_brk(brk);
 }
 
-#define set_utsfield(to, from, dotchop, countfrom) {			\
-	char *p; 							\
-	int i, len = (countfrom) ? 					\
-		((sizeof(to) > sizeof(from) ? 				\
-			sizeof(from) : sizeof(to))) : sizeof(to); 	\
-	if (copy_to_user(to, from, len))				\
-		return -EFAULT;						\
-	if (dotchop) 							\
-		for (p=from,i=0; *p && *p != '.' && --len; p++,i++); 	\
-	else 								\
-		i = len - 1; 						\
-	if (__put_user('\0', (char __user *)((to)+i)))			\
-		return -EFAULT;						\
+static int __set_utsfield(char __user *to, int to_size,
+			  const char *from, int from_size,
+			  int dotchop, int countfrom)
+{
+	int len = countfrom ? (to_size > from_size ?
+			       from_size : to_size) : to_size;
+	int off;
+
+	if (copy_to_user(to, from, len))
+		return -EFAULT;
+
+	off = len < to_size? len: len - 1;
+	if (dotchop) {
+		const char *p = strnchr(from, len, '.');
+		if (p) off = p - from;
+	}
+
+	if (__put_user('\0', to + off))
+		return -EFAULT;
+
+	return 0;
 }
 
+#define set_utsfield(to, from, dotchop, countfrom) \
+	__set_utsfield((to), sizeof(to), \
+		       (from), sizeof(from), \
+		       (dotchop), (countfrom))
+
 struct sol_uname {
 	char sysname[9];
 	char nodename[9];
@@ -219,17 +232,20 @@
 asmlinkage int solaris_utssys(u32 buf, u32 flags, int which, u32 buf2)
 {
 	struct sol_uname __user *v = A(buf);
+	int err;
+
 	switch (which) {
 	case 0:	/* old uname */
 		/* Let's cheat */
-		set_utsfield(v->sysname, "SunOS", 1, 0);
+		err  = set_utsfield(v->sysname, "SunOS", 1, 0);
 		down_read(&uts_sem);
-		set_utsfield(v->nodename, system_utsname.nodename, 1, 1);
+		err |= set_utsfield(v->nodename, system_utsname.nodename,
+				    1, 1);
 		up_read(&uts_sem);
-		set_utsfield(v->release, "2.6", 0, 0);
-		set_utsfield(v->version, "Generic", 0, 0);
-		set_utsfield(v->machine, machine(), 0, 0);
-		return 0;
+		err |= set_utsfield(v->release, "2.6", 0, 0);
+		err |= set_utsfield(v->version, "Generic", 0, 0);
+		err |= set_utsfield(v->machine, machine(), 0, 0);
+		return (err ? -EFAULT : 0);
 	case 2: /* ustat */
 		return -ENOSYS;
 	case 3: /* fusers */
@@ -242,15 +258,18 @@
 asmlinkage int solaris_utsname(u32 buf)
 {
 	struct sol_utsname __user *v = A(buf);
+	int err;
+
 	/* Why should we not lie a bit? */
 	down_read(&uts_sem);
-	set_utsfield(v->sysname, "SunOS", 0, 0);
-	set_utsfield(v->nodename, system_utsname.nodename, 1, 1);
-	set_utsfield(v->release, "5.6", 0, 0);
-	set_utsfield(v->version, "Generic", 0, 0);
-	set_utsfield(v->machine, machine(), 0, 0);
+	err  = set_utsfield(v->sysname, "SunOS", 0, 0);
+	err |= set_utsfield(v->nodename, system_utsname.nodename, 1, 1);
+	err |= set_utsfield(v->release, "5.6", 0, 0);
+	err |= set_utsfield(v->version, "Generic", 0, 0);
+	err |= set_utsfield(v->machine, machine(), 0, 0);
 	up_read(&uts_sem);
-	return 0;
+
+	return (err ? -EFAULT : 0);
 }
 
 #define SI_SYSNAME		1       /* return name of operating system */
diff -Nru a/arch/um/Kconfig b/arch/um/Kconfig
--- a/arch/um/Kconfig	2004-10-18 14:56:31 -07:00
+++ b/arch/um/Kconfig	2004-10-18 14:56:31 -07:00
@@ -34,7 +34,7 @@
 	help
 	This option controls whether tracing thread support is compiled
 	into UML.  Normally, this should be set to Y.  If you intend to
-	use only skas mode (and the host has the skas patch applied to it), 
+	use only skas mode (and the host has the skas patch applied to it),
 	then it is OK to say N here.
 
 config STATIC_LINK
@@ -45,7 +45,7 @@
 	If CONFIG_MODE_TT is disabled, then this option gives you the ability
 	to force a static link of UML.  Normally, if only skas mode is built
 	in to UML, it will be linked as a shared binary.  This is inconvenient
-	for use in a chroot jail.  So, if you intend to run UML inside a 
+	for use in a chroot jail.  So, if you intend to run UML inside a
 	chroot, and you disable CONFIG_MODE_TT, you probably want to say Y
 	here.
 
@@ -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"
 
@@ -82,9 +96,22 @@
         For more information, see
         <http://user-mode-linux.sourceforge.net/hostfs.html>.
 
-        If you'd like to be able to work with files stored on the host, 
+        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"
@@ -102,15 +129,12 @@
 
         It is safe to say 'Y' here.
 
-config MAGIC_SYSRQ
-	bool "Magic SysRq key"
-	depends on MCONSOLE
-
 config HOST_2G_2G
 	bool "2G/2G host address space split"
 
-config UML_SMP
+config SMP
 	bool "Symmetric multi-processing support"
+	default n
 	help
         This option enables UML SMP support.  UML implements virtual SMP by
         allowing as many processes to run simultaneously on the host as
@@ -119,13 +143,8 @@
         will appear to be running simultaneously.  If the host is a
         multiprocessor, then UML processes may run simultaneously, depending
         on the host scheduler.
-        CONFIG_SMP will be set to whatever this option is set to.
         It is safe to leave this unchanged.
 
-config SMP
-	bool
-	default UML_SMP
-
 config NR_CPUS
 	int "Maximum number of CPUs (2-32)"
 	range 2 32
@@ -140,11 +159,11 @@
         in.  Normally, this is zero, meaning that it will run directly on the
         host.  Setting it to one will build a UML that can run inside a UML
         that is running on the host.  Generally, if you intend this UML to run
-        inside another UML, set CONFIG_NEST_LEVEL to one more than the host 
+        inside another UML, set CONFIG_NEST_LEVEL to one more than the host
         UML.
 
-        Note that if the hosting UML has its CONFIG_KERNEL_HALF_GIGS set to 
-        greater than one, then the guest UML should have its CONFIG_NEST_LEVEL 
+        Note that if the hosting UML has its CONFIG_KERNEL_HALF_GIGS set to
+        greater than one, then the guest UML should have its CONFIG_NEST_LEVEL
         set to the host's CONFIG_NEST_LEVEL + CONFIG_KERNEL_HALF_GIGS.
         Only change this if you are running nested UMLs.
 
@@ -159,6 +178,7 @@
 
 config HIGHMEM
 	bool "Highmem support"
+	depends on BROKEN
 
 config KERNEL_STACK_ORDER
 	int "Kernel stack size order"
@@ -168,6 +188,17 @@
 	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
 
 source "init/Kconfig"
@@ -195,6 +226,7 @@
 source "lib/Kconfig"
 
 menu "SCSI support"
+depends on BROKEN
 
 config SCSI
 	tristate "SCSI support"
@@ -211,61 +243,8 @@
 
 source "drivers/md/Kconfig"
 
-source "drivers/mtd/Kconfig"
-
-
-menu "Kernel hacking"
-
-config DEBUG_SLAB
-	bool "Debug memory allocations"
-
-config DEBUG_SPINLOCK
-	bool "Debug spinlocks usage"
-
-config DEBUG_INFO
-	bool "Enable kernel debugging symbols"
-	help
-        When this is enabled, the User-Mode Linux binary will include
-        debugging symbols.  This enlarges the binary by a few megabytes,
-        but aids in tracking down kernel problems in UML.  It is required
-        if you intend to do any kernel development.
-
-        If you're truly short on disk space or don't expect to report any
-        bugs back to the UML developers, say N, otherwise say Y.
-
-config FRAME_POINTER
-	bool
-	default y if DEBUG_INFO
-
-config PT_PROXY
-	bool "Enable ptrace proxy"
-	depends on XTERM_CHAN && DEBUG_INFO
-
-config GPROF
-	bool "Enable gprof support"
-	depends on DEBUG_INFO
-	help
-        This allows profiling of a User-Mode Linux kernel with the gprof
-        utility.
-
-        See <http://user-mode-linux.sourceforge.net/gprof.html> for more
-        details.
-
-        If you're involved in UML kernel development and want to use gprof,
-        say Y.  If you're unsure, say N.
-
-config GCOV
-	bool "Enable gcov support"
-	depends on DEBUG_INFO
-	help
-        This option allows developers to retrieve coverage data from a UML
-        session.
-
-        See <http://user-mode-linux.sourceforge.net/gprof.html> for more
-        details.
-
-        If you're involved in UML kernel development and want to use gcov,
-        say Y.  If you're unsure, say N.
-
-endmenu
+if BROKEN
+	source "drivers/mtd/Kconfig"
+endif
 
+source "arch/um/Kconfig.debug"
diff -Nru a/arch/um/Kconfig.debug b/arch/um/Kconfig.debug
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/arch/um/Kconfig.debug	2004-10-18 14:57:22 -07:00
@@ -0,0 +1,43 @@
+menu "Kernel hacking"
+
+source "lib/Kconfig.debug"
+
+config FRAME_POINTER
+	bool
+	default y if DEBUG_INFO
+
+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"
+	depends on DEBUG_INFO
+	help
+        This allows profiling of a User-Mode Linux kernel with the gprof
+        utility.
+
+        See <http://user-mode-linux.sourceforge.net/gprof.html> for more
+        details.
+
+        If you're involved in UML kernel development and want to use gprof,
+        say Y.  If you're unsure, say N.
+
+config GCOV
+	bool "Enable gcov support"
+	depends on DEBUG_INFO
+	help
+        This option allows developers to retrieve coverage data from a UML
+        session.
+
+        See <http://user-mode-linux.sourceforge.net/gprof.html> for more
+        details.
+
+        If you're involved in UML kernel development and want to use gcov,
+        say Y.  If you're unsure, say N.
+
+endmenu
diff -Nru a/arch/um/Kconfig_block b/arch/um/Kconfig_block
--- a/arch/um/Kconfig_block	2004-10-18 14:56:48 -07:00
+++ b/arch/um/Kconfig_block	2004-10-18 14:56:48 -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"
 
@@ -50,6 +54,7 @@
 
 config MMAPPER
 	tristate "Example IO memory driver"
+	depends on BROKEN
 	help
         The User-Mode Linux port can provide support for IO Memory
         emulation with this option.  This allows a host file to be
diff -Nru a/arch/um/Kconfig_char b/arch/um/Kconfig_char
--- a/arch/um/Kconfig_char	2004-10-18 14:56:29 -07:00
+++ b/arch/um/Kconfig_char	2004-10-18 14:56:29 -07:00
@@ -72,6 +72,10 @@
         well, since UML's gdb currently requires an xterm.
         It is safe to say 'Y' here.
 
+config NOCONFIG_CHAN
+	bool
+	default !(XTERM_CHAN && TTY_CHAN && PTY_CHAN && PORT_CHAN && FD_CHAN && NULL_CHAN)
+
 config CON_ZERO_CHAN
 	string "Default main console channel initialization"
 	default "fd:0,fd:1"
@@ -108,11 +112,55 @@
 
 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.
+
+	  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.
 
-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, 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 WATCHDOG
 	bool "Watchdog Timer Support"
diff -Nru a/arch/um/Kconfig_net b/arch/um/Kconfig_net
--- a/arch/um/Kconfig_net	2004-10-18 14:56:33 -07:00
+++ b/arch/um/Kconfig_net	2004-10-18 14:56:33 -07:00
@@ -1,5 +1,5 @@
 
-menu "Network Devices"
+menu "UML Network Devices"
 	depends on NET
 
 # UML virtual driver
@@ -135,7 +135,7 @@
 
 config UML_NET_PCAP
 	bool "pcap transport"
-	depends on UML_NET
+	depends on UML_NET && BROKEN
 	help
 	The pcap transport makes a pcap packet stream on the host look
 	like an ethernet device inside UML.  This is useful for making 
@@ -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-10-18 14:56:33 -07:00
+++ b/arch/um/Makefile	2004-10-18 14:56:33 -07:00
@@ -5,35 +5,25 @@
 
 ARCH_DIR = arch/um
 OS := $(shell uname -s)
+#We require it or things break.
+SHELL := /bin/bash
 
-# Recalculate MODLIB to reflect the EXTRAVERSION changes (via KERNELRELEASE)
-# The way the toplevel Makefile is written EXTRAVERSION is not supposed
-# to be changed outside the toplevel Makefile, but recalculating MODLIB is
-# a sufficient workaround until we no longer need architecture dependent
-# EXTRAVERSION...
-MODLIB := $(INSTALL_MOD_PATH)/lib/modules/$(KERNELRELEASE)
+filechk_gen_header = $<
 
-ifeq ($(CONFIG_DEBUG_INFO),y)
-CFLAGS := $(subst -fomit-frame-pointer,,$(CFLAGS))
-endif
-
-core-y			+= $(ARCH_DIR)/kernel/		 \
-			   $(ARCH_DIR)/drivers/          \
+core-y			+= $(ARCH_DIR)/kernel/		\
+			   $(ARCH_DIR)/drivers/		\
 			   $(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)
-
 MAKEFILE-$(CONFIG_MODE_TT) += Makefile-tt
 MAKEFILE-$(CONFIG_MODE_SKAS) += Makefile-skas
 
@@ -41,9 +31,11 @@
   include $(addprefix $(ARCH_DIR)/,$(MAKEFILE-y))
 endif
 
-EXTRAVERSION := $(EXTRAVERSION)-1um
+ARCH_INCLUDE	:= -I$(ARCH_DIR)/include
+SYS_DIR		:= $(ARCH_DIR)/include/sysdep-$(SUBARCH)
 
-ARCH_INCLUDE = -I$(ARCH_DIR)/include
+include $(ARCH_DIR)/Makefile-$(SUBARCH)
+include $(ARCH_DIR)/Makefile-os-$(OS)
 
 # -Derrno=kernel_errno - This turns all kernel references to errno into
 # kernel_errno to separate them from the libc errno.  This allows -fno-common
@@ -52,32 +44,32 @@
 
 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 cc-option,-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) : $(ARCH_DIR)/include/skas_ptregs.h
 endif
 
-include/linux/version.h: arch/$(ARCH)/Makefile
-
-$(ARCH_DIR)/vmlinux.lds.S :
-	touch $@
-
-prepare: $(ARCH_SYMLINKS) $(SYS_HEADERS) $(GEN_HEADERS)
-
-LDFLAGS_vmlinux = -r
-
-vmlinux: $(ARCH_DIR)/main.o 
+prepare: $(ARCH_SYMLINKS) $(SYS_HEADERS) $(GEN_HEADERS) \
+	$(ARCH_DIR)/kernel/vmlinux.lds.S
 
 # These aren't in Makefile-tt because they are needed in the !CONFIG_MODE_TT +
 # CONFIG_MODE_SKAS + CONFIG_STATIC_LINK case.
 
 LINK_TT = -static
-LD_SCRIPT_TT := uml.lds.s
+LD_SCRIPT_TT := uml.lds.S
 
 ifeq ($(CONFIG_STATIC_LINK),y)
   LINK-y += $(LINK_TT)
@@ -98,82 +90,99 @@
 CONFIG_KERNEL_STACK_ORDER ?= 2
 STACK_SIZE := $(shell echo $$[ 4096 * (1 << $(CONFIG_KERNEL_STACK_ORDER)) ] )
 
-AFLAGS_vmlinux.lds.o = -U$(SUBARCH) \
-	-DSTART=$$(($(TOP_ADDR) - $(SIZE))) -DELF_ARCH=$(ELF_ARCH) \
-	-DELF_FORMAT=\"$(ELF_FORMAT)\" $(CPP_MODE_TT) \
-	-DKERNEL_STACK_SIZE=$(STACK_SIZE)
-
-AFLAGS_$(LD_SCRIPT-y:.s=).o = $(AFLAGS_vmlinux.lds.o) -P -C -Uum
-
-LD_SCRIPT-y := $(ARCH_DIR)/$(LD_SCRIPT-y)
+ifndef START
+  START = $$(($(TOP_ADDR) - $(SIZE)))
+endif
 
-$(LD_SCRIPT-y) : $(LD_SCRIPT-y:.s=.S) scripts FORCE
-	$(call if_changed_dep,as_s_S)
+CPPFLAGS_vmlinux.lds = $(shell echo -U$(SUBARCH) \
+	-DSTART=$(START) -DELF_ARCH=$(ELF_ARCH) \
+	-DELF_FORMAT=\"$(ELF_FORMAT)\" $(CPP_MODE_TT) \
+	-DKERNEL_STACK_SIZE=$(STACK_SIZE))
 
-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
+CFLAGS_vmlinux = $(LINK-y) $(LINK_WRAPS)
+define cmd_vmlinux__
+	$(CC) $(CFLAGS_vmlinux) -o $@ \
+	-Wl,-T,$(vmlinux-lds) $(vmlinux-init) \
+	-Wl,--start-group $(vmlinux-main) -Wl,--end-group \
+	-L/usr/lib -lutil \
+	$(filter-out $(vmlinux-lds) $(vmlinux-init) $(vmlinux-main) FORCE ,$^)
+endef
 
 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
 
-CLEAN_FILES += linux x.i gmon.out $(ARCH_DIR)/uml.lds.s \
-	$(ARCH_DIR)/dyn_link.ld.s $(GEN_HEADERS)
+#When cleaning we don't include .config, so we don't include
+#TT or skas makefiles and don't clean skas_ptregs.h.
+CLEAN_FILES += linux x.i gmon.out $(ARCH_DIR)/include/uml-config.h \
+	$(GEN_HEADERS) $(ARCH_DIR)/include/skas_ptregs.h
 
-$(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)) $(ARCH_DIR)/os
 
 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' \
+	@:
+
+archclean:
+	$(Q)$(MAKE) $(clean)=$(ARCH_DIR)/util
+	@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
+#We need to re-preprocess this when the symlink dest changes.
+#So we touch it.
+$(ARCH_DIR)/kernel/vmlinux.lds.S: FORCE
+	@echo '  SYMLINK $@'
+	$(Q)ln -sf $(LD_SCRIPT-y) $@
+	$(Q)touch $@
 
 $(SYMLINK_HEADERS):
-	cd $(TOPDIR)/$(dir $@) ; \
+	@echo '  SYMLINK $@'
+	$(Q)cd $(TOPDIR)/$(dir $@) ; \
 	ln -sf $(basename $(notdir $@))-$(SUBARCH)$(suffix $@) $(notdir $@)
 
 include/asm-um/arch:
-	cd $(TOPDIR)/include/asm-um && ln -sf ../asm-$(SUBARCH) arch
+	@echo '  SYMLINK $@'
+	$(Q)cd $(TOPDIR)/include/asm-um && ln -sf ../asm-$(SUBARCH) arch
 
 $(ARCH_DIR)/include/sysdep:
-	cd $(ARCH_DIR)/include && ln -sf sysdep-$(SUBARCH) sysdep
+	@echo '  SYMLINK $@'
+	$(Q)cd $(ARCH_DIR)/include && ln -sf sysdep-$(SUBARCH) sysdep
 
 $(ARCH_DIR)/os:
-	cd $(ARCH_DIR) && ln -sf os-$(OS) os
+	@echo '  SYMLINK $@'
+	$(Q)cd $(ARCH_DIR) && ln -sf os-$(OS) os
+
+# Generated files
+define filechk_umlconfig
+	sed 's/ CONFIG/ UML_CONFIG/'
+endef
+
+$(ARCH_DIR)/include/uml-config.h : include/linux/autoconf.h
+	$(call filechk,umlconfig)
+
+$(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)/include/uml-config.h :
-	sed 's/ CONFIG/ UML_CONFIG/' $(TOPDIR)/include/linux/autoconf.h > $@
+$(ARCH_DIR)/include/skas_ptregs.h: $(ARCH_DIR)/kernel/skas/util/mk_ptregs
+	$(call filechk,gen_header)
 
-$(ARCH_DIR)/include/task.h : $(ARCH_DIR)/util/mk_task
-	$< > $@
+$(ARCH_DIR)/util/mk_task $(ARCH_DIR)/util/mk_constants: $(ARCH_DIR)/util \
+	FORCE ;
 
-$(ARCH_DIR)/include/kern_constants.h : $(ARCH_DIR)/util/mk_constants
-	$< > $@
+$(ARCH_DIR)/kernel/skas/util/mk_ptregs: $(ARCH_DIR)/kernel/skas/util FORCE ;
 
-$(ARCH_DIR)/util/mk_task : $(ARCH_DIR)/kernel/skas/include/skas_ptregs.h \
-	$(ARCH_DIR)/util FORCE ;
+$(ARCH_DIR)/util: scripts_basic $(SYS_DIR)/sc.h FORCE
+	$(Q)$(MAKE) $(build)=$@
 
-$(ARCH_DIR)/util: FORCE
-	@$(call descend,$@,)
+$(ARCH_DIR)/kernel/skas/util: scripts_basic FORCE
+	$(Q)$(MAKE) $(build)=$@
 
 export SUBARCH USER_CFLAGS OS
diff -Nru a/arch/um/Makefile-i386 b/arch/um/Makefile-i386
--- a/arch/um/Makefile-i386	2004-10-18 14:56:49 -07:00
+++ b/arch/um/Makefile-i386	2004-10-18 14:56:49 -07:00
@@ -1,37 +1,45 @@
 ifeq ($(CONFIG_HOST_2G_2G), y)
-TOP_ADDR = 0x80000000
+TOP_ADDR := 0x80000000
 else
-TOP_ADDR = 0xc0000000
+TOP_ADDR := 0xc0000000
+endif
+
+ifeq ($(CONFIG_MODE_SKAS),y)
+  ifneq ($(CONFIG_MODE_TT),y)
+     START := 0x8048000
+  endif
 endif
 
 CFLAGS += -U__$(SUBARCH)__ -U$(SUBARCH)
-ELF_ARCH = $(SUBARCH)
-ELF_FORMAT = elf32-$(SUBARCH)
+
+ifneq ($(CONFIG_GPROF),y)
+ARCH_CFLAGS += -DUM_FASTCALL
+endif
+
+ELF_ARCH := $(SUBARCH)
+ELF_FORMAT := elf32-$(SUBARCH)
 
 OBJCOPYFLAGS  := -O binary -R .note -R .comment -S
-LDFLAGS_BLOB	:= --format binary --oformat elf32-i386
 
-SYS_DIR		:= $(ARCH_DIR)/include/sysdep-i386
 SYS_UTIL_DIR	:= $(ARCH_DIR)/sys-i386/util
 
-SYS_HEADERS = $(SYS_DIR)/sc.h $(SYS_DIR)/thread.h
+SYS_HEADERS := $(SYS_DIR)/sc.h $(SYS_DIR)/thread.h
 
 prepare: $(SYS_HEADERS)
 
 $(SYS_DIR)/sc.h: $(SYS_UTIL_DIR)/mk_sc
-	$< > $@
+	$(call filechk,gen_header)
 
 $(SYS_DIR)/thread.h: $(SYS_UTIL_DIR)/mk_thread 
-	$< > $@
+	$(call filechk,gen_header)
 
-$(SYS_UTIL_DIR)/mk_sc: FORCE ; 
-	@$(call descend,$(SYS_UTIL_DIR),$@)
+$(SYS_UTIL_DIR)/mk_sc: scripts_basic 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: scripts_basic $(ARCH_SYMLINKS) $(GEN_HEADERS) FORCE
+	$(Q)$(MAKE) $(build)=$(SYS_UTIL_DIR) $@
 
-$(SYS_UTIL_DIR): include/asm FORCE
-	@$(call descend,$@,)
+$(SYS_UTIL_DIR): scripts_basic include/asm FORCE
+	$(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-10-18 14:56:29 -07:00
+++ b/arch/um/Makefile-skas	2004-10-18 14:56:29 -07:00
@@ -9,12 +9,9 @@
 CFLAGS-$(CONFIG_GPROF) += $(PROFILE)
 LINK-$(CONFIG_GPROF) += $(PROFILE)
 
-MODE_INCLUDE += -I$(TOPDIR)/$(ARCH_DIR)/kernel/skas/include
+MODE_INCLUDE += -I$(srctree)/$(ARCH_DIR)/kernel/skas/include
 
 LINK_SKAS = -Wl,-rpath,/lib 
-LD_SCRIPT_SKAS = dyn.lds.s
+LD_SCRIPT_SKAS = dyn.lds.S
 
-GEN_HEADERS += $(ARCH_DIR)/kernel/skas/include/skas_ptregs.h
-
-$(ARCH_DIR)/kernel/skas/include/skas_ptregs.h :
-	$(MAKE) -C $(ARCH_DIR)/kernel/skas include/skas_ptregs.h
+GEN_HEADERS += $(ARCH_DIR)/include/skas_ptregs.h
diff -Nru a/arch/um/Makefile-tt b/arch/um/Makefile-tt
--- a/arch/um/Makefile-tt	2004-10-18 14:56:49 -07:00
+++ b/arch/um/Makefile-tt	2004-10-18 14:56:49 -07:00
@@ -3,5 +3,4 @@
 # Licensed under the GPL
 #
 
-MODE_INCLUDE += -I$(TOPDIR)/$(ARCH_DIR)/kernel/tt/include
-
+MODE_INCLUDE += -I$(srctree)/$(ARCH_DIR)/kernel/tt/include
diff -Nru a/arch/um/config.release b/arch/um/config.release
--- a/arch/um/config.release	2004-10-18 14:57:04 -07:00
+++ b/arch/um/config.release	2004-10-18 14:57:04 -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-10-18 14:56:33 -07:00
+++ b/arch/um/defconfig	2004-10-18 14:56:33 -07:00
@@ -1,47 +1,79 @@
 #
 # Automatically generated make config: don't edit
+# Linux kernel version: 2.6.9-rc2-mm1
+# Thu Sep 16 23:44:48 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_LOCALVERSION=""
+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_KOBJECT_UEVENT=y
+# 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_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+CONFIG_SHMEM=y
+# CONFIG_TINY_SHMEM 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 +90,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 +102,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 +112,7 @@
 CONFIG_NETDEVICES=y
 
 #
-# Network Devices
+# UML Network Devices
 #
 CONFIG_UML_NET=y
 CONFIG_UML_NET_ETHERTAP=y
@@ -88,22 +122,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 +133,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 +142,25 @@
 # 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_INET_TUNNEL 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 +172,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 +201,130 @@
 #
 
 #
-# 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
+
+#
+# Caches
+#
+# CONFIG_CACHEFS is not set
+
+#
+# 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 +332,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 +361,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 +380,7 @@
 #
 # Security options
 #
+# CONFIG_KEYS is not set
 # CONFIG_SECURITY is not set
 
 #
@@ -311,33 +391,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 +420,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 +469,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	2004-10-18 14:56:33 -07:00
+++ b/arch/um/drivers/Makefile	2004-10-18 14:56:33 -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	2004-10-18 14:57:04 -07:00
+++ b/arch/um/drivers/chan_kern.c	2004-10-18 14:57:04 -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,7 +17,9 @@
 #include "irq_user.h"
 #include "sigio.h"
 #include "line.h"
+#include "os.h"
 
+#ifdef CONFIG_NOCONFIG_CHAN
 static void *not_configged_init(char *str, int device, struct chan_opts *opts)
 {
 	printk(KERN_ERR "Using a channel type which is configured out of "
@@ -85,6 +88,55 @@
 	.free		= not_configged_free,
 	.winch		= 0,
 };
+#endif /* CONFIG_NOCONFIG_CHAN */
+
+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);
+}
+
+/* XXX Trivial wrapper around os_write_file */
+
+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)
 {
@@ -265,6 +317,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 +477,8 @@
 		INIT_LIST_HEAD(chans);
 	}
 
-	if((out = strchr(str, ',')) != NULL){
+	out = strchr(str, ',');
+	if(out != NULL){
 		in = str;
 		*out = '\0';
 		out++;
@@ -475,12 +533,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	2004-10-18 14:55:54 -07:00
+++ b/arch/um/drivers/chan_user.c	2004-10-18 14:55:54 -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-10-18 14:57:24 -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-10-18 14:57:24 -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-10-18 14:57:23 -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 {
+	__u32 magic;
+	__u32 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	2004-10-18 14:56:28 -07:00
+++ b/arch/um/drivers/daemon_user.c	2004-10-18 14:56:28 -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	2004-10-18 14:57:04 -07:00
+++ b/arch/um/drivers/fd.c	2004-10-18 14:57:04 -07:00
@@ -7,6 +7,7 @@
 #include <stdlib.h>
 #include <unistd.h>
 #include <termios.h>
+#include <errno.h>
 #include "user.h"
 #include "user_util.h"
 #include "chan_user.h"
@@ -35,7 +36,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);
@@ -44,10 +46,16 @@
 int fd_open(int input, int output, int primary, void *d, char **dev_out)
 {
 	struct fd_chan *data = d;
+	int err;
 
 	if(data->raw && isatty(data->fd)){
-		tcgetattr(data->fd, &data->tt);
-		raw(data->fd, 0);
+		CATCH_EINTR(err = tcgetattr(data->fd, &data->tt));
+		if(err)
+			return(err);
+
+		err = raw(data->fd);
+		if(err)
+			return(err);
 	}
 	sprintf(data->str, "%d", data->fd);
 	*dev_out = data->str;
@@ -57,9 +65,13 @@
 void fd_close(int fd, void *d)
 {
 	struct fd_chan *data = d;
+	int err;
 
 	if(data->raw && isatty(fd)){
-		tcsetattr(fd, TCSAFLUSH, &data->tt);
+		CATCH_EINTR(err = tcsetattr(fd, TCSAFLUSH, &data->tt));
+		if(err)
+			printk("Failed to restore terminal state - "
+			       "errno = %d\n", -err);
 		data->raw = 0;
 	}
 }
diff -Nru a/arch/um/drivers/harddog_user.c b/arch/um/drivers/harddog_user.c
--- a/arch/um/drivers/harddog_user.c	2004-10-18 14:56:28 -07:00
+++ b/arch/um/drivers/harddog_user.c	2004-10-18 14:56:28 -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	2004-10-18 14:57:04 -07:00
+++ b/arch/um/drivers/hostaudio_kern.c	2004-10-18 14:57:04 -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,56 @@
 			      loff_t *ppos)
 {
         struct hostaudio_state *state = file->private_data;
+	void *kbuf;
+	int err;
 
 #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);
+
+	err = os_read_file(state->fd, kbuf, count);
+	if(err < 0)
+		goto out;
+
+	if(copy_to_user(buffer, kbuf, err))
+		err = -EFAULT;
+
+ out:
+	kfree(kbuf);
+	return(err);
 }
 
 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 err;
 
 #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);
+
+	err = -EFAULT;
+	if(copy_from_user(kbuf, buffer, count))
+		goto out;
+
+	err = os_write_file(state->fd, kbuf, count);
+	if(err < 0)
+		goto out;
+	*ppos += err;
+
+ out:
+	kfree(kbuf);
+	return(err);
 }
 
 static unsigned int hostaudio_poll(struct file *file, 
@@ -86,12 +139,43 @@
 			   unsigned int cmd, unsigned long arg)
 {
         struct hostaudio_state *state = file->private_data;
+	unsigned long data = 0;
+	int err;
 
 #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;
+	}
+
+	err = 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(err);
 }
 
 static int hostaudio_open(struct inode *inode, struct file *file)
@@ -105,17 +189,19 @@
 #endif
 
         state = kmalloc(sizeof(struct hostaudio_state), GFP_KERNEL);
-        if(state == NULL) return(-ENOMEM);
+        if(state == NULL)
+		return(-ENOMEM);
 
         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){
 		kfree(state);
 		return(ret);
         }
 
+	state->fd = ret;
         file->private_data = state;
         return(0);
 }
@@ -123,16 +209,15 @@
 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);
+		os_close_file(state->fd);
         kfree(state);
 
-        return(ret);
+	return(0);
 }
 
 /* /dev/mixer file operations */
@@ -146,7 +231,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,9 +250,11 @@
         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);
         }
@@ -179,16 +266,15 @@
 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);
+		os_close_file(state->fd);
         kfree(state);
 
-        return(ret);
+	return(0);
 }
 
 
@@ -225,7 +311,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	2004-10-18 14:56:48 -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	2004-10-18 14:57:03 -07:00
+++ b/arch/um/drivers/line.c	2004-10-18 14:57:03 -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);
@@ -56,10 +73,11 @@
 	else {
 		memcpy(line->tail, buf, end);
 		buf += end;
-		len -= end;
-		memcpy(line->buffer, buf, len);
-		line->tail = line->buffer + len;
+		memcpy(line->buffer, buf, len - end);
+		line->tail = line->buffer + len - end;
 	}
+
+	return(len);
 }
 
 static int flush_buffer(struct line *line)
@@ -95,7 +113,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 +122,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 +137,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 +192,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,20 +324,20 @@
 		if(*end != '='){
 			printk(KERN_ERR "line_setup failed to parse \"%s\"\n", 
 			       init);
-			return(1);
+			return(0);
 		}
 		init = end;
 	}
 	init++;
 	if((n >= 0) && (n >= num)){
 		printk("line_setup - %d out of range ((0 ... %d) allowed)\n",
-		       n, num);
-		return(1);
+		       n, num - 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 +351,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 +365,7 @@
 			}
 		}
 	}
-	return(0);
+	return(1);
 }
 
 int line_config(struct line *lines, int num, char *str)
@@ -357,7 +376,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 +388,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 +398,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 +415,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 +438,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 +459,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 +492,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 +520,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 +559,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	2004-10-18 14:56:32 -07:00
+++ b/arch/um/drivers/mcast_user.c	2004-10-18 14:56:32 -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	2004-10-18 14:55:54 -07:00
+++ b/arch/um/drivers/mconsole_kern.c	2004-10-18 14:55:54 -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)
@@ -47,27 +51,26 @@
 
 LIST_HEAD(mc_requests);
 
-void mc_work_proc(void *unused)
+static void mc_work_proc(void *unused)
 {
 	struct mconsole_entry *req;
 	unsigned long flags;
-	int done;
 
-	do {
+	while(!list_empty(&mc_requests)){
 		local_save_flags(flags);
 		req = list_entry(mc_requests.next, struct mconsole_entry, 
 				 list);
 		list_del(&req->list);
-		done = list_empty(&mc_requests);
 		local_irq_restore(flags);
 		req->request.cmd->handler(&req->request);
 		kfree(req);
-	} while(!done);
+	}
 }
 
 DECLARE_WORK(mconsole_work, mc_work_proc, NULL);
 
-void mconsole_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t mconsole_interrupt(int irq, void *dev_id,
+				      struct pt_regs *regs)
 {
 	int fd;
 	struct mconsole_entry *new;
@@ -75,9 +78,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 {
@@ -86,8 +90,10 @@
 			}
 		}
 	}
-	if(!list_empty(&mc_requests)) schedule_work(&mconsole_work);
+	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)
@@ -279,8 +374,8 @@
 	ptr += strlen("sysrq");
 	while(isspace(*ptr)) ptr++;
 
-	handle_sysrq(*ptr, &current->thread.regs, NULL);
 	mconsole_reply(req, "", 0, 0);
+	handle_sysrq(*ptr, &current->thread.regs, NULL);
 }
 #else
 void mconsole_sysrq(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	2004-10-18 14:56:16 -07:00
+++ b/arch/um/drivers/mconsole_user.c	2004-10-18 14:56:16 -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	2004-10-18 14:55:55 -07:00
+++ b/arch/um/drivers/mmapper_kern.c	2004-10-18 14:55:55 -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-10-18 14:56:29 -07:00
+++ b/arch/um/drivers/net_kern.c	2004-10-18 14:56:29 -07:00
@@ -19,6 +19,8 @@
 #include "linux/inetdevice.h"
 #include "linux/ctype.h"
 #include "linux/bootmem.h"
+#include "linux/ethtool.h"
+#include "asm/uaccess.h"
 #include "user_util.h"
 #include "kern_util.h"
 #include "net_kern.h"
@@ -26,6 +28,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 +40,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 +65,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 +87,7 @@
 
  out:
 	spin_unlock(&lp->lock);
+	return(IRQ_HANDLED);
 }
 
 static int uml_net_open(struct net_device *dev)
@@ -124,6 +129,13 @@
 	spin_lock(&opened_lock);
 	list_add(&lp->list, &opened);
 	spin_unlock(&opened_lock);
+
+	/* clear buffer - it can happen that the host side of the interface
+	 * is full when we get here.  In this case, new data is never queued,
+	 * SIGIOs never arrive, and the net never works.
+	 */
+	while((err = uml_net_rx(dev)) > 0) ;
+
  out:
 	spin_unlock(&lp->lock);
 	return(err);
@@ -237,7 +249,30 @@
 
 static int uml_net_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
 {
-	return(-EINVAL);
+	static const struct ethtool_drvinfo info = {
+		.cmd     = ETHTOOL_GDRVINFO,
+		.driver  = "uml virtual ethernet",
+		.version = "42",
+	};
+	void *useraddr;
+	u32 ethcmd;
+
+	switch (cmd) {
+	case SIOCETHTOOL:
+		useraddr = ifr->ifr_data;
+		if (copy_from_user(&ethcmd, useraddr, sizeof(ethcmd)))
+			return -EFAULT;
+		switch (ethcmd) {
+		case ETHTOOL_GDRVINFO:
+			if (copy_to_user(useraddr, &info, sizeof(info)))
+				return -EFAULT;
+			return 0;
+		default:
+			return -EOPNOTSUPP;
+		}
+	default:
+		return -EINVAL;
+	}
 }
 
 void uml_net_user_timer_expire(unsigned long _conn)
@@ -250,37 +285,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 +294,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 +336,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 +362,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 +617,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	2004-10-18 14:56:17 -07:00
+++ b/arch/um/drivers/net_user.c	2004-10-18 14:56:17 -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	2004-10-18 14:55:54 -07:00
+++ b/arch/um/drivers/null.c	2004-10-18 14:55:54 -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	2004-10-18 14:55:54 -07:00
+++ b/arch/um/drivers/port_kern.c	2004-10-18 14:55:54 -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	2004-10-18 14:56:33 -07:00
+++ b/arch/um/drivers/port_user.c	2004-10-18 14:56:33 -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,
@@ -74,12 +76,17 @@
 int port_open(int input, int output, int primary, void *d, char **dev_out)
 {
 	struct port_chan *data = d;
-	int fd;
+	int fd, err;
 
 	fd = port_wait(data->kernel_data);
 	if((fd >= 0) && data->raw){
-		tcgetattr(fd, &data->tt);
-		raw(fd, 0);
+		CATCH_EINTR(err = tcgetattr(fd, &data->tt));
+		if(err)
+			return(err);
+
+		err = raw(fd);
+		if(err)
+			return(err);
 	}
 	*dev_out = data->dev;
 	return(fd);
@@ -90,7 +97,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 +137,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 +164,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 +177,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 +198,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	2004-10-18 14:57:03 -07:00
+++ b/arch/um/drivers/pty.c	2004-10-18 14:57:03 -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 });
@@ -37,15 +38,21 @@
 {
 	struct pty_chan *data = d;
 	char *dev;
-	int fd;
+	int fd, err;
 
-	if((fd = get_pty()) < 0){
+	fd = get_pty();
+	if(fd < 0){
 		printk("open_pts : Failed to open pts\n");
 		return(-errno);
 	}
 	if(data->raw){
-		tcgetattr(fd, &data->tt);
-		raw(fd, 0);
+		CATCH_EINTR(err = tcgetattr(fd, &data->tt));
+		if(err)
+			return(err);
+
+		err = raw(fd);
+		if(err)
+			return(err);
 	}
 
 	dev = ptsname(fd);
@@ -57,29 +64,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);
 			}
 		}
 	}
@@ -89,13 +94,19 @@
 int pty_open(int input, int output, int primary, void *d, char **dev_out)
 {
 	struct pty_chan *data = d;
-	int fd;
+	int fd, err;
 	char dev[sizeof("/dev/ptyxx\0")] = "/dev/ptyxx";
 
 	fd = getmaster(dev);
-	if(fd < 0) return(-errno);
+	if(fd < 0)
+		return(-errno);
+
+	if(data->raw){
+		err = raw(fd);
+		if(err)
+			return(err);
+	}
 	
-	if(data->raw) raw(fd, 0);
 	if(data->announce) (*data->announce)(dev, data->dev);
 
 	sprintf(data->dev_name, "%s", dev);
diff -Nru a/arch/um/drivers/slip_user.c b/arch/um/drivers/slip_user.c
--- a/arch/um/drivers/slip_user.c	2004-10-18 14:57:03 -07:00
+++ b/arch/um/drivers/slip_user.c	2004-10-18 14:57:03 -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	2004-10-18 14:56:48 -07:00
+++ b/arch/um/drivers/slirp_user.c	2004-10-18 14:56:48 -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	2004-10-18 14:56:32 -07:00
+++ b/arch/um/drivers/ssl.c	2004-10-18 14:56:32 -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	2004-10-18 14:56:20 -07:00
+++ b/arch/um/drivers/stdio_console.c	2004-10-18 14:56:20 -07:00
@@ -17,8 +17,8 @@
 #include "linux/init.h"
 #include "linux/interrupt.h"
 #include "linux/slab.h"
+#include "linux/hardirq.h"
 #include "asm/current.h"
-#include "asm/hardirq.h"
 #include "asm/irq.h"
 #include "stdio_console.h"
 #include "line.h"
@@ -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,52 +189,53 @@
 	return(0);
 }
 
-__initcall(stdio_init);
+late_initcall(stdio_init);
 
-static void console_write(struct console *console, const char *string, 
+static void uml_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 *uml_console_device(struct console *c, int *index)
 {
 	*index = c->index;
 	return console_driver;
 }
 
-static int console_setup(struct console *co, char *options)
+static int uml_console_setup(struct console *co, char *options)
 {
 	return(0);
 }
 
-static struct console stdiocons = INIT_CONSOLE("tty", console_write, 
-					       console_device, console_setup,
-					       CON_PRINTBUFFER);
+static struct console stdiocons = {
+	name:		"tty",
+	write:		uml_console_write,
+	device:		uml_console_device,
+	setup:		uml_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	2004-10-18 14:56:28 -07:00
+++ b/arch/um/drivers/tty.c	2004-10-18 14:56:28 -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 });
@@ -41,13 +41,18 @@
 int tty_open(int input, int output, int primary, void *d, char **dev_out)
 {
 	struct tty_chan *data = d;
-	int fd;
+	int fd, err;
 
 	fd = os_open_file(data->dev, of_set_rw(OPENFLAGS(), input, output), 0);
 	if(fd < 0) return(fd);
 	if(data->raw){
-		tcgetattr(fd, &data->tt);
-		raw(fd, 0);
+		CATCH_EINTR(err = tcgetattr(fd, &data->tt));
+		if(err)
+			return(err);
+
+		err = raw(fd);
+		if(err)
+			return(err);
 	}
 
 	*dev_out = data->dev;
diff -Nru a/arch/um/drivers/ubd_kern.c b/arch/um/drivers/ubd_kern.c
--- a/arch/um/drivers/ubd_kern.c	2004-10-18 14:56:31 -07:00
+++ b/arch/um/drivers/ubd_kern.c	2004-10-18 14:56:31 -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, from 0 to %d)\n", n, MAX_DEV, MAX_DEV - 1);
 		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;
 }
@@ -343,14 +396,13 @@
  */
 int intr_count = 0;
 
-static void ubd_finish(struct request *req, int error)
+/* call ubd_finish if you need to serialize */
+static void __ubd_finish(struct request *req, int error)
 {
 	int nsect;
 
 	if(error){
- 		spin_lock(&ubd_io_lock);
 		end_request(req, 0);
- 		spin_unlock(&ubd_io_lock);
 		return;
 	}
 	nsect = req->current_nr_sectors;
@@ -359,41 +411,57 @@
 	req->errors = 0;
 	req->nr_sectors -= nsect;
 	req->current_nr_sectors = 0;
-	spin_lock(&ubd_io_lock);
 	end_request(req, 1);
+}
+
+static inline void ubd_finish(struct request *req, int error)
+{
+ 	spin_lock(&ubd_io_lock);
+	__ubd_finish(req, error);
 	spin_unlock(&ubd_io_lock);
 }
 
+/* Called without ubd_io_lock held */
 static void ubd_handler(void)
 {
 	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 +485,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 +501,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 +529,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 +559,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 +598,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 +650,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 +693,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];
@@ -667,9 +754,7 @@
 		return -1;
 	}
 		
-	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);
@@ -688,9 +773,11 @@
 	unsigned long stack;
 	int err;
 
+	/* Set by CONFIG_BLK_DEV_UBD_SYNC or ubd=sync.*/
 	if(global_openflags.s){
-		printk(KERN_INFO "ubd : Synchronous mode\n");
-		return(0);
+		printk(KERN_INFO "ubd: Synchronous mode\n");
+		/* Letting ubd=sync be like using ubd#s= instead of ubd#= is
+		 * enough. So use anyway the io thread. */
 	}
 	stack = alloc_stack(0, 0);
 	io_pid = start_io_thread(stack + PAGE_SIZE - sizeof(void *), 
@@ -699,12 +786,13 @@
 		printk(KERN_ERR 
 		       "ubd : Failed to start I/O thread (errno = %d) - "
 		       "falling back to synchronous I/O\n", -io_pid);
+		io_pid = -1;
 		return(0);
 	}
 	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 +802,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,91 +831,211 @@
 	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)
 {
-        int i, update_bitmap, sector = req->offset >> 9;
+	__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)
+{
+	__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);
 }
 
+/* Called with ubd_io_lock held */
 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);
- 		spin_lock(&ubd_io_lock);
 		end_request(req, 0);
- 		spin_unlock(&ubd_io_lock);
 		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);
 }
 
+/* Called with ubd_io_lock held */
 static void do_ubd_request(request_queue_t *q)
 {
 	struct io_thread_req io_req;
@@ -841,18 +1043,17 @@
 	int err, n;
 
 	if(thread_fd == -1){
-		while(!list_empty(&q->queue_head)){
-			req = elv_next_request(q);
+		while((req = elv_next_request(q)) != NULL){
 			err = prepare_request(req, &io_req);
 			if(!err){
 				do_io(&io_req);
-				ubd_finish(req, io_req.error);
+				__ubd_finish(req, io_req.error);
 			}
 		}
 	}
 	else {
-		if(do_ubd || list_empty(&q->queue_head)) return;
-		req = elv_next_request(q);
+		if(do_ubd || (req = elv_next_request(q)) == NULL)
+			return;
 		err = prepare_request(req, &io_req);
 		if(!err){
 			do_ubd = ubd_handler;
@@ -870,7 +1071,6 @@
 {
 	struct hd_geometry *loc = (struct hd_geometry *) arg;
 	struct ubd *dev = inode->i_bdev->bd_disk->private_data;
-	int err;
 	struct hd_driveid ubd_id = {
 		.cyls		= 0,
 		.heads		= 128,
@@ -885,35 +1085,9 @@
 		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:
-		if(!capable(CAP_SYS_ADMIN)) return(-EACCES);
-		if((arg > 1) || (inode->i_bdev->bd_contains != inode->i_bdev))
-			return(-EINVAL);
-		return(0);
-
-	case HDIO_GET_UNMASKINTR:
-		if(!arg)  return(-EINVAL);
-		err = verify_area(VERIFY_WRITE, (long *) arg, sizeof(long));
-		if(err)
-			return(err);
-		return(0);
-
-	case HDIO_GET_MULTCOUNT:
-		if(!arg)  return(-EINVAL);
-		err = verify_area(VERIFY_WRITE, (long *) arg, sizeof(long));
-		if(err)
-			return(err);
-		return(0);
-
-	case HDIO_SET_MULTCOUNT:
-		if(!capable(CAP_SYS_ADMIN)) return(-EACCES);
-		if(inode->i_bdev->bd_contains != inode->i_bdev)
-			return(-EINVAL);
-		return(0);
-
 	case HDIO_GET_IDENTITY:
 		ubd_id.cyls = dev->size / (128 * 32 * 512);
 		if(copy_to_user((char *) arg, (char *) &ubd_id, 
@@ -934,6 +1108,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	2004-10-18 14:56:20 -07:00
+++ b/arch/um/drivers/ubd_user.c	2004-10-18 14:56:20 -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,20 @@
 		    NULL);
 	if(pid < 0){
 		printk("start_io_thread - clone failed : errno = %d\n", errno);
-		return(-errno);
-	}
-	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);
+		err = -errno;
+		goto out_close;
 	}
 
-	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	2004-10-18 14:55:54 -07:00
+++ b/arch/um/drivers/xterm.c	2004-10-18 14:55:54 -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, 
@@ -83,6 +83,7 @@
 "    are 'xterm=gnome-terminal,-t,-x'.\n\n"
 );
 
+/* XXX This badly needs some cleaning up in the error paths */
 int xterm_open(int input, int output, int primary, void *d, char **dev_out)
 {
 	struct xterm_chan *data = d;
@@ -93,7 +94,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 +107,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,20 +129,32 @@
 	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;
 	}
 
-	tcgetattr(new, &data->tt);
-	if(data->raw) raw(new, 0);
+	CATCH_EINTR(err = tcgetattr(new, &data->tt));
+	if(err){
+		new = err;
+		goto out;
+	}
+
+	if(data->raw){
+		err = raw(new);
+		if(err){
+			new = err;
+			goto out;
+		}
+	}
 
 	data->pid = pid;
 	*dev_out = NULL;
@@ -160,7 +173,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	2004-10-18 14:56:48 -07:00
+++ b/arch/um/drivers/xterm_kern.c	2004-10-18 14:56:48 -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	2004-10-18 14:56:32 -07:00
+++ /dev/null	Wed Dec 31 16:00:00 196900
@@ -1,167 +0,0 @@
-OUTPUT_FORMAT(ELF_FORMAT)
-OUTPUT_ARCH(ELF_ARCH)
-ENTRY(_start)
-jiffies = jiffies_64;
-
-SEARCH_DIR("/usr/local/i686-pc-linux-gnu/lib"); SEARCH_DIR("/usr/local/lib"); SEARCH_DIR("/lib"); SEARCH_DIR("/usr/lib");
-/* Do we need any of these for elf?
-   __DYNAMIC = 0;    */
-SECTIONS
-{
-  . = START + SIZEOF_HEADERS;
-  .interp         : { *(.interp) }
-  . = ALIGN(4096);
-  __binary_start = .;
-  . = ALIGN(4096);		/* Init code and data */
-  _stext = .;
-  __init_begin = .;
-  .text.init : { *(.text.init) }
-
-  . = ALIGN(4096);
-
-  /* Read-only sections, merged into text segment: */
-  .hash           : { *(.hash) }
-  .dynsym         : { *(.dynsym) }
-  .dynstr         : { *(.dynstr) }
-  .gnu.version    : { *(.gnu.version) }
-  .gnu.version_d  : { *(.gnu.version_d) }
-  .gnu.version_r  : { *(.gnu.version_r) }
-  .rel.init       : { *(.rel.init) }
-  .rela.init      : { *(.rela.init) }
-  .rel.text       : { *(.rel.text .rel.text.* .rel.gnu.linkonce.t.*) }
-  .rela.text      : { *(.rela.text .rela.text.* .rela.gnu.linkonce.t.*) }
-  .rel.fini       : { *(.rel.fini) }
-  .rela.fini      : { *(.rela.fini) }
-  .rel.rodata     : { *(.rel.rodata .rel.rodata.* .rel.gnu.linkonce.r.*) }
-  .rela.rodata    : { *(.rela.rodata .rela.rodata.* .rela.gnu.linkonce.r.*) }
-  .rel.data       : { *(.rel.data .rel.data.* .rel.gnu.linkonce.d.*) }
-  .rela.data      : { *(.rela.data .rela.data.* .rela.gnu.linkonce.d.*) }
-  .rel.tdata	  : { *(.rel.tdata .rel.tdata.* .rel.gnu.linkonce.td.*) }
-  .rela.tdata	  : { *(.rela.tdata .rela.tdata.* .rela.gnu.linkonce.td.*) }
-  .rel.tbss	  : { *(.rel.tbss .rel.tbss.* .rel.gnu.linkonce.tb.*) }
-  .rela.tbss	  : { *(.rela.tbss .rela.tbss.* .rela.gnu.linkonce.tb.*) }
-  .rel.ctors      : { *(.rel.ctors) }
-  .rela.ctors     : { *(.rela.ctors) }
-  .rel.dtors      : { *(.rel.dtors) }
-  .rela.dtors     : { *(.rela.dtors) }
-  .rel.got        : { *(.rel.got) }
-  .rela.got       : { *(.rela.got) }
-  .rel.bss        : { *(.rel.bss .rel.bss.* .rel.gnu.linkonce.b.*) }
-  .rela.bss       : { *(.rela.bss .rela.bss.* .rela.gnu.linkonce.b.*) }
-  .rel.plt        : { *(.rel.plt) }
-  .rela.plt       : { *(.rela.plt) }
-  .init           : {
-    KEEP (*(.init))
-  } =0x90909090
-  .plt            : { *(.plt) }
-  .text           : {
-    *(.text .stub .text.* .gnu.linkonce.t.*)
-    /* .gnu.warning sections are handled specially by elf32.em.  */
-    *(.gnu.warning)
-  } =0x90909090
-  .fini           : {
-    KEEP (*(.fini))
-  } =0x90909090
-
-  .kstrtab : { *(.kstrtab) }
-
-  #include "asm/common.lds.S"
-
-  .data.init : { *(.data.init) }
-
-  /* Ensure the __preinit_array_start label is properly aligned.  We
-     could instead move the label definition inside the section, but
-     the linker would then create the section even if it turns out to
-     be empty, which isn't pretty.  */
-  . = ALIGN(32 / 8);
-  .preinit_array     : { *(.preinit_array) }
-  .init_array     : { *(.init_array) }
-  .fini_array     : { *(.fini_array) }
-  .data           : {
-    . = ALIGN(KERNEL_STACK_SIZE);		/* init_task */
-    *(.data.init_task)
-    *(.data .data.* .gnu.linkonce.d.*)
-    SORT(CONSTRUCTORS)
-  }
-  .data1          : { *(.data1) }
-  .tdata	  : { *(.tdata .tdata.* .gnu.linkonce.td.*) }
-  .tbss		  : { *(.tbss .tbss.* .gnu.linkonce.tb.*) *(.tcommon) }
-  .eh_frame       : { KEEP (*(.eh_frame)) }
-  .gcc_except_table   : { *(.gcc_except_table) }
-  .dynamic        : { *(.dynamic) }
-  .ctors          : {
-    /* gcc uses crtbegin.o to find the start of
-       the constructors, so we make sure it is
-       first.  Because this is a wildcard, it
-       doesn't matter if the user does not
-       actually link against crtbegin.o; the
-       linker won't look for a file to match a
-       wildcard.  The wildcard also means that it
-       doesn't matter which directory crtbegin.o
-       is in.  */
-    KEEP (*crtbegin.o(.ctors))
-    /* We don't want to include the .ctor section from
-       from the crtend.o file until after the sorted ctors.
-       The .ctor section from the crtend file contains the
-       end of ctors marker and it must be last */
-    KEEP (*(EXCLUDE_FILE (*crtend.o ) .ctors))
-    KEEP (*(SORT(.ctors.*)))
-    KEEP (*(.ctors))
-  }
-  .dtors          : {
-    KEEP (*crtbegin.o(.dtors))
-    KEEP (*(EXCLUDE_FILE (*crtend.o ) .dtors))
-    KEEP (*(SORT(.dtors.*)))
-    KEEP (*(.dtors))
-  }
-  .jcr            : { KEEP (*(.jcr)) }
-  .got            : { *(.got.plt) *(.got) }
-  _edata = .;
-  PROVIDE (edata = .);
-  __bss_start = .;
-  .bss            : {
-   *(.dynbss)
-   *(.bss .bss.* .gnu.linkonce.b.*)
-   *(COMMON)
-   /* Align here to ensure that the .bss section occupies space up to
-      _end.  Align after .bss to ensure correct alignment even if the
-      .bss section disappears because there are no input sections.  */
-   . = ALIGN(32 / 8);
-  . = ALIGN(32 / 8);
-  }
-  _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) }
-  /* 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 .gnu.linkonce.wi.*) }
-  .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) }
-}
diff -Nru a/arch/um/include/2_5compat.h b/arch/um/include/2_5compat.h
--- a/arch/um/include/2_5compat.h	2004-10-18 14:56:29 -07:00
+++ b/arch/um/include/2_5compat.h	2004-10-18 14:56:29 -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/Makefile b/arch/um/include/Makefile
--- a/arch/um/include/Makefile	2004-10-18 14:57:04 -07:00
+++ /dev/null	Wed Dec 31 16:00:00 196900
@@ -1,7 +0,0 @@
-all : sc.h
-
-sc.h : ../util/mk_sc
-	../util/mk_sc > $@
-
-../util/mk_sc :
-	$(MAKE) -C ../util mk_sc
diff -Nru a/arch/um/include/hostaudio.h b/arch/um/include/hostaudio.h
--- a/arch/um/include/hostaudio.h	2004-10-18 14:56:32 -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-10-18 14:57:21 -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/irq_user.h b/arch/um/include/irq_user.h
--- a/arch/um/include/irq_user.h	2004-10-18 14:56:33 -07:00
+++ b/arch/um/include/irq_user.h	2004-10-18 14:56:33 -07:00
@@ -14,6 +14,7 @@
 extern void free_irq_by_fd(int fd);
 extern void reactivate_fd(int fd, int irqnum);
 extern void deactivate_fd(int fd, int irqnum);
+extern int deactivate_all_fds(void);
 extern void forward_interrupts(int pid);
 extern void init_irq_signals(int on_sigstack);
 extern void forward_ipi(int fd, int pid);
diff -Nru a/arch/um/include/kern_util.h b/arch/um/include/kern_util.h
--- a/arch/um/include/kern_util.h	2004-10-18 14:56:28 -07:00
+++ b/arch/um/include/kern_util.h	2004-10-18 14:56:28 -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	2004-10-18 14:56:49 -07:00
+++ b/arch/um/include/line.h	2004-10-18 14:56:49 -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	2004-10-18 14:56:29 -07:00
+++ b/arch/um/include/mconsole.h	2004-10-18 14:56:29 -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	2004-10-18 14:57:04 -07:00
+++ b/arch/um/include/mem.h	2004-10-18 14:57:04 -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-10-18 14:57:21 -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	2004-10-18 14:56:33 -07:00
+++ b/arch/um/include/mem_user.h	2004-10-18 14:56:33 -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	2004-10-18 14:56:18 -07:00
+++ b/arch/um/include/os.h	2004-10-18 14:56: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,48 @@
 	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_clear_fd_async(int fd);
 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 +160,13 @@
 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);
+extern unsigned long long os_usecs(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	2004-10-18 14:55:54 -07:00
+++ b/arch/um/include/signal_user.h	2004-10-18 14:55:54 -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	2004-10-18 14:57:03 -07:00
+++ b/arch/um/include/skas_ptrace.h	2004-10-18 14:57:03 -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	2004-10-18 14:57:19 -07:00
+++ b/arch/um/include/sysdep-i386/checksum.h	2004-10-18 14:57:19 -07:00
@@ -5,6 +5,7 @@
 #ifndef __UM_SYSDEP_CHECKSUM_H
 #define __UM_SYSDEP_CHECKSUM_H
 
+#include "linux/in6.h"
 #include "linux/string.h"
 
 /*
@@ -102,7 +103,8 @@
 	   are modified, we must also specify them as outputs, or gcc
 	   will assume they contain their original values. */
 	: "=r" (sum), "=r" (iph), "=r" (ihl)
-	: "1" (iph), "2" (ihl));
+	: "1" (iph), "2" (ihl)
+	: "memory");
 	return(sum);
 }
 
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	2004-10-18 14:57:04 -07:00
+++ b/arch/um/include/sysdep-i386/frame_user.h	2004-10-18 14:57:04 -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	2004-10-18 14:56:48 -07:00
+++ b/arch/um/include/sysdep-i386/sigcontext.h	2004-10-18 14:56:48 -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	2004-10-18 14:55:55 -07:00
+++ b/arch/um/include/sysdep-i386/syscalls.h	2004-10-18 14:55:55 -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/time_user.h b/arch/um/include/time_user.h
--- a/arch/um/include/time_user.h	2004-10-18 14:56:17 -07:00
+++ b/arch/um/include/time_user.h	2004-10-18 14:56:17 -07:00
@@ -11,6 +11,7 @@
 extern void set_interval(int timer_type);
 extern void idle_sleep(int secs);
 extern void enable_timer(void);
+extern void disable_timer(void);
 extern unsigned long time_lock(void);
 extern void time_unlock(unsigned long);
 
diff -Nru a/arch/um/include/ubd_user.h b/arch/um/include/ubd_user.h
--- a/arch/um/include/ubd_user.h	2004-10-18 14:56:32 -07:00
+++ b/arch/um/include/ubd_user.h	2004-10-18 14:56:32 -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	2004-10-18 14:56:48 -07:00
+++ b/arch/um/include/um_uaccess.h	2004-10-18 14:56:48 -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	2004-10-18 14:55:54 -07:00
+++ b/arch/um/include/user.h	2004-10-18 14:55:54 -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	2004-10-18 14:55:55 -07:00
+++ b/arch/um/include/user_util.h	2004-10-18 14:55:55 -07:00
@@ -8,14 +8,14 @@
 
 #include "sysdep/ptrace.h"
 
+#define CATCH_EINTR(expr) while (((expr) < 0) && (errno == EINTR))
+
 extern int mode_tt;
 
 extern int grantpt(int __fd);
 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 +59,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);
@@ -76,7 +74,6 @@
 extern void tracer_panic(char *msg, ...);
 extern char *get_umid(int only_if_set);
 extern void do_longjmp(void *p, int val);
-extern void suspend_new_thread(int fd);
 extern int detach(int pid, int sig);
 extern int attach(int pid);
 extern void kill_child_dead(int pid);
@@ -86,11 +83,15 @@
 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 setjmp_wrapper(void (*proc)(void *, void *), ...);
+extern int raw(int fd);
+
 #endif
 
 /*
diff -Nru a/arch/um/kernel/Makefile b/arch/um/kernel/Makefile
--- a/arch/um/kernel/Makefile	2004-10-18 14:56:48 -07:00
+++ b/arch/um/kernel/Makefile	2004-10-18 14:56:48 -07:00
@@ -3,15 +3,16 @@
 # Licensed under the GPL
 #
 
-extra-y := vmlinux.lds.s
+extra-y := vmlinux.lds
+clean-files := vmlinux.lds.S
 
 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 +25,19 @@
 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 frame.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))
+CFLAGS_frame.o := -fno-omit-frame-pointer
 
 $(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 $$_ }'
-
-$(obj)/config.c : $(src)/config.c.in $(TOPDIR)/.config
-	$(PERL) -e $(QUOTE) < $(src)/config.c.in > $@
-
-$(obj)/config.o : $(obj)/config.c
-
-clean:
-	rm -f config.c
-	for dir in $(subdir-y) ; do $(MAKE) -C $$dir clean; done
-
-modules:
-
-fastdep:
+	$(CC) $(USER_CFLAGS) $(CFLAGS_$(notdir $@)) -c -o $@ $<
 
-dep:
+QUOTE = 'my $$config=`cat $(TOPDIR)/.config`; $$config =~ s/"/\\"/g ; $$config =~ s/\n/\\n"\n"/g ; while(<STDIN>) { $$_ =~ s/CONFIG/$$config/; print $$_ }'
 
-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	2004-10-18 14:56:48 -07:00
+++ b/arch/um/kernel/config.c.in	2004-10-18 14:56:48 -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/dyn.lds.S b/arch/um/kernel/dyn.lds.S
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/arch/um/kernel/dyn.lds.S	2004-10-18 14:56:32 -07:00
@@ -0,0 +1,171 @@
+#include <asm-generic/vmlinux.lds.h>
+
+OUTPUT_FORMAT(ELF_FORMAT)
+OUTPUT_ARCH(ELF_ARCH)
+ENTRY(_start)
+jiffies = jiffies_64;
+
+SECTIONS
+{
+  . = START + SIZEOF_HEADERS;
+  .interp         : { *(.interp) }
+  __binary_start = .;
+  . = ALIGN(4096);		/* Init code and data */
+  _stext = .;
+  __init_begin = .;
+  .init.text : {
+	_sinittext = .;
+	*(.init.text)
+	_einittext = .;
+  }
+
+  . = ALIGN(4096);
+
+  /* Read-only sections, merged into text segment: */
+  .hash           : { *(.hash) }
+  .dynsym         : { *(.dynsym) }
+  .dynstr         : { *(.dynstr) }
+  .gnu.version    : { *(.gnu.version) }
+  .gnu.version_d  : { *(.gnu.version_d) }
+  .gnu.version_r  : { *(.gnu.version_r) }
+  .rel.init       : { *(.rel.init) }
+  .rela.init      : { *(.rela.init) }
+  .rel.text       : { *(.rel.text .rel.text.* .rel.gnu.linkonce.t.*) }
+  .rela.text      : { *(.rela.text .rela.text.* .rela.gnu.linkonce.t.*) }
+  .rel.fini       : { *(.rel.fini) }
+  .rela.fini      : { *(.rela.fini) }
+  .rel.rodata     : { *(.rel.rodata .rel.rodata.* .rel.gnu.linkonce.r.*) }
+  .rela.rodata    : { *(.rela.rodata .rela.rodata.* .rela.gnu.linkonce.r.*) }
+  .rel.data       : { *(.rel.data .rel.data.* .rel.gnu.linkonce.d.*) }
+  .rela.data      : { *(.rela.data .rela.data.* .rela.gnu.linkonce.d.*) }
+  .rel.tdata	  : { *(.rel.tdata .rel.tdata.* .rel.gnu.linkonce.td.*) }
+  .rela.tdata	  : { *(.rela.tdata .rela.tdata.* .rela.gnu.linkonce.td.*) }
+  .rel.tbss	  : { *(.rel.tbss .rel.tbss.* .rel.gnu.linkonce.tb.*) }
+  .rela.tbss	  : { *(.rela.tbss .rela.tbss.* .rela.gnu.linkonce.tb.*) }
+  .rel.ctors      : { *(.rel.ctors) }
+  .rela.ctors     : { *(.rela.ctors) }
+  .rel.dtors      : { *(.rel.dtors) }
+  .rela.dtors     : { *(.rela.dtors) }
+  .rel.got        : { *(.rel.got) }
+  .rela.got       : { *(.rela.got) }
+  .rel.bss        : { *(.rel.bss .rel.bss.* .rel.gnu.linkonce.b.*) }
+  .rela.bss       : { *(.rela.bss .rela.bss.* .rela.gnu.linkonce.b.*) }
+  .rel.plt        : { *(.rel.plt) }
+  .rela.plt       : { *(.rela.plt) }
+  .init           : {
+    KEEP (*(.init))
+  } =0x90909090
+  .plt            : { *(.plt) }
+  .text           : {
+    *(.text)
+    SCHED_TEXT
+    *(.stub .text.* .gnu.linkonce.t.*)
+    /* .gnu.warning sections are handled specially by elf32.em.  */
+    *(.gnu.warning)
+  } =0x90909090
+  .fini           : {
+    KEEP (*(.fini))
+  } =0x90909090
+
+  .kstrtab : { *(.kstrtab) }
+
+  #include "asm/common.lds.S"
+
+  init.data : { *(.init.data) }
+
+  /* Ensure the __preinit_array_start label is properly aligned.  We
+     could instead move the label definition inside the section, but
+     the linker would then create the section even if it turns out to
+     be empty, which isn't pretty.  */
+  . = ALIGN(32 / 8);
+  .preinit_array     : { *(.preinit_array) }
+  .init_array     : { *(.init_array) }
+  .fini_array     : { *(.fini_array) }
+  .data           : {
+    . = ALIGN(KERNEL_STACK_SIZE);		/* init_task */
+    *(.data.init_task)
+    *(.data .data.* .gnu.linkonce.d.*)
+    SORT(CONSTRUCTORS)
+  }
+  .data1          : { *(.data1) }
+  .tdata	  : { *(.tdata .tdata.* .gnu.linkonce.td.*) }
+  .tbss		  : { *(.tbss .tbss.* .gnu.linkonce.tb.*) *(.tcommon) }
+  .eh_frame       : { KEEP (*(.eh_frame)) }
+  .gcc_except_table   : { *(.gcc_except_table) }
+  .dynamic        : { *(.dynamic) }
+  .ctors          : {
+    /* gcc uses crtbegin.o to find the start of
+       the constructors, so we make sure it is
+       first.  Because this is a wildcard, it
+       doesn't matter if the user does not
+       actually link against crtbegin.o; the
+       linker won't look for a file to match a
+       wildcard.  The wildcard also means that it
+       doesn't matter which directory crtbegin.o
+       is in.  */
+    KEEP (*crtbegin.o(.ctors))
+    /* We don't want to include the .ctor section from
+       from the crtend.o file until after the sorted ctors.
+       The .ctor section from the crtend file contains the
+       end of ctors marker and it must be last */
+    KEEP (*(EXCLUDE_FILE (*crtend.o ) .ctors))
+    KEEP (*(SORT(.ctors.*)))
+    KEEP (*(.ctors))
+  }
+  .dtors          : {
+    KEEP (*crtbegin.o(.dtors))
+    KEEP (*(EXCLUDE_FILE (*crtend.o ) .dtors))
+    KEEP (*(SORT(.dtors.*)))
+    KEEP (*(.dtors))
+  }
+  .jcr            : { KEEP (*(.jcr)) }
+  .got            : { *(.got.plt) *(.got) }
+  _edata = .;
+  PROVIDE (edata = .);
+  __bss_start = .;
+  .bss            : {
+   *(.dynbss)
+   *(.bss .bss.* .gnu.linkonce.b.*)
+   *(COMMON)
+   /* Align here to ensure that the .bss section occupies space up to
+      _end.  Align after .bss to ensure correct alignment even if the
+      .bss section disappears because there are no input sections.  */
+   . = ALIGN(32 / 8);
+  . = ALIGN(32 / 8);
+  }
+  _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) }
+  /* 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 .gnu.linkonce.wi.*) }
+  .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) }
+}
diff -Nru a/arch/um/kernel/exec_kern.c b/arch/um/kernel/exec_kern.c
--- a/arch/um/kernel/exec_kern.c	2004-10-18 14:56:27 -07:00
+++ b/arch/um/kernel/exec_kern.c	2004-10-18 14:56:27 -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	2004-10-18 14:56:28 -07:00
+++ b/arch/um/kernel/frame.c	2004-10-18 14:56:28 -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	2004-10-18 14:57:19 -07:00
+++ b/arch/um/kernel/frame_kern.c	2004-10-18 14:57:19 -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	2004-10-18 14:56:31 -07:00
+++ b/arch/um/kernel/helper.c	2004-10-18 14:56:31 -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, 
@@ -116,10 +132,12 @@
 		return(-errno);
 	}
 	if(stack_out == NULL){
-		pid = waitpid(pid, &status, 0);
-		if(pid < 0)
+		CATCH_EINTR(pid = waitpid(pid, &status, 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);
@@ -133,7 +151,7 @@
 {
 	int ret;
 
-	ret = waitpid(pid, NULL, WNOHANG);
+	CATCH_EINTR(ret = waitpid(pid, NULL, WNOHANG));
 	if(ret < 0){
 		printk("helper_wait : waitpid failed, errno = %d\n", errno);
 		return(-errno);
diff -Nru a/arch/um/kernel/init_task.c b/arch/um/kernel/init_task.c
--- a/arch/um/kernel/init_task.c	2004-10-18 14:57:05 -07:00
+++ b/arch/um/kernel/init_task.c	2004-10-18 14:57:05 -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	2004-10-18 14:56:17 -07:00
+++ b/arch/um/kernel/initrd_user.c	2004-10-18 14:56:17 -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-10-18 14:56:49 -07:00
+++ b/arch/um/kernel/irq.c	2004-10-18 14:56:49 -07:00
@@ -18,9 +18,10 @@
 #include "linux/proc_fs.h"
 #include "linux/init.h"
 #include "linux/seq_file.h"
+#include "linux/profile.h"
+#include "linux/hardirq.h"
 #include "asm/irq.h"
 #include "asm/hw_irq.h"
-#include "asm/hardirq.h"
 #include "asm/atomic.h"
 #include "asm/signal.h"
 #include "asm/system.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;
 }
 
 /*
@@ -155,13 +147,16 @@
 		     struct irqaction * action)
 {
 	int status = 1;	/* Force the "do bottom halves" bit */
+	int ret, retval = 0;
 
 	if (!(action->flags & SA_INTERRUPT))
 		local_irq_enable();
 
 	do {
-		status |= action->flags;
-		action->handler(irq, action->dev_id, regs);
+		ret = action->handler(irq, action->dev_id, regs);
+		if (ret == IRQ_HANDLED)
+			status |= action->flags;
+		retval |= ret;
 		action = action->next;
 	} while (action);
 	if (status & SA_SAMPLE_RANDOM)
@@ -169,7 +164,7 @@
 
 	local_irq_disable();
 
-	return status;
+	return retval;
 }
 
 /*
@@ -282,13 +277,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 +379,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,16 +427,22 @@
 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);
 }
+EXPORT_SYMBOL(um_request_irq);
+EXPORT_SYMBOL(reactivate_fd);
 
 /* this was setup_x86_irq but it seems pretty generic */
 int setup_irq(unsigned int irq, struct irqaction * new)
@@ -474,7 +474,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 +587,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 +602,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 +615,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 +643,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	2004-10-18 14:56:29 -07:00
+++ b/arch/um/kernel/irq_user.c	2004-10-18 14:56:29 -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);
@@ -364,36 +364,47 @@
 	irq_unlock(flags);
 }
 
-void forward_ipi(int fd, int pid)
+int deactivate_all_fds(void)
 {
-	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);
-		}
+	struct irq_fd *irq;
+	int err;
+
+	for(irq=active_fds;irq != NULL;irq = irq->next){
+		err = os_clear_fd_async(irq->fd);
+		if(err)
+			return(err);
 	}
+
+	return(0);
+}
+
+void forward_ipi(int fd, int pid)
+{
+	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	2004-10-18 14:55:54 -07:00
+++ b/arch/um/kernel/ksyms.c	2004-10-18 14:55:54 -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,67 @@
 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(uml_strdup);
+
+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.
  */
@@ -75,10 +109,10 @@
 /* required for SMP */
 
 extern void FASTCALL( __write_lock_failed(rwlock_t *rw));
-EXPORT_SYMBOL_NOVERS(__write_lock_failed);
+EXPORT_SYMBOL(__write_lock_failed);
 
 extern void FASTCALL( __read_lock_failed(rwlock_t *rw));
-EXPORT_SYMBOL_NOVERS(__read_lock_failed);
+EXPORT_SYMBOL(__read_lock_failed);
 
 #endif
 
@@ -90,3 +124,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-10-18 14:56:49 -07:00
@@ -0,0 +1,249 @@
+/*
+ * 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){
+		int err;
+
+		printf("\n");
+
+		/* Let any pending signals fire, then disable them.  This
+		 * ensures that they won't be delivered after the exec, when
+		 * they are definitely not expected.
+		 */
+		unblock_signals();
+		disable_timer();
+		err = deactivate_all_fds();
+		if(err)
+			printf("deactivate_all_fds failed, errno = %d\n",
+			       -err);
+
+		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.
+	 *
+	 * CAN_KMALLOC is checked because it would be bad to free a buffer
+	 * with kmalloc/vmalloc after they have been turned off during
+	 * shutdown.
+	 */
+
+	if((addr >= uml_physmem) && (addr < high_physmem)){
+		if(CAN_KMALLOC())
+			kfree(ptr);
+	}
+	else if((addr >= start_vm) && (addr < end_vm)){
+		if(CAN_KMALLOC())
+			vfree(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-10-18 14:56:28 -07:00
+++ b/arch/um/kernel/mem.c	2004-10-18 14:56:28 -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	2004-10-18 14:56:32 -07:00
+++ b/arch/um/kernel/mem_user.c	2004-10-18 14:56:32 -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,147 @@
 #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, size;
 
 	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;
+	}
+
+	size = (buf.ust_size + UM_KERN_PAGE_SIZE) & ~(UM_KERN_PAGE_SIZE - 1);
+
+	*new = ((struct iomem_region) { .next		= iomem_regions,
+					.driver		= driver,
+					.fd		= fd,
+					.size		= 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 +194,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/mprot.h b/arch/um/kernel/mprot.h
--- a/arch/um/kernel/mprot.h	2004-10-18 14:56:29 -07:00
+++ /dev/null	Wed Dec 31 16:00:00 196900
@@ -1,6 +0,0 @@
-#ifndef __MPROT_H__
-#define __MPROT_H__
-
-extern void no_access(unsigned long addr, unsigned int len);
-
-#endif
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-10-18 14:57:23 -07:00
@@ -0,0 +1,478 @@
+/*
+ * Copyright (C) 2000 - 2003 Jeff Dike (jdike@addtoit.com)
+ * Licensed under the GPL
+ */
+
+#include "linux/mm.h"
+#include "linux/rbtree.h"
+#include "linux/slab.h"
+#include "linux/vmalloc.h"
+#include "linux/bootmem.h"
+#include "linux/module.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"
+
+struct phys_desc {
+	struct rb_node rb;
+	int fd;
+	__u64 offset;
+	void *virt;
+	unsigned long phys;
+	struct list_head list;
+};
+
+static struct rb_root phys_mappings = RB_ROOT;
+
+static struct rb_node **find_rb(void *virt)
+{
+	struct rb_node **n = &phys_mappings.rb_node;
+	struct phys_desc *d;
+
+	while(*n != NULL){
+		d = rb_entry(*n, struct phys_desc, rb);
+		if(d->virt == virt)
+			return(n);
+
+		if(d->virt > virt)
+			n = &(*n)->rb_left;
+		else
+			n = &(*n)->rb_right;
+	}
+
+	return(n);
+}
+
+static struct phys_desc *find_phys_mapping(void *virt)
+{
+	struct rb_node **n = find_rb(virt);
+
+	if(*n == NULL)
+		return(NULL);
+
+	return(rb_entry(*n, struct phys_desc, rb));
+}
+
+static void insert_phys_mapping(struct phys_desc *desc)
+{
+	struct rb_node **n = find_rb(desc->virt);
+
+	if(*n != NULL)
+		panic("Physical remapping for %p already present",
+		      desc->virt);
+
+	rb_link_node(&desc->rb, (*n)->rb_parent, n);
+	rb_insert_color(&desc->rb, &phys_mappings);
+}
+
+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);
+	desc = find_phys_mapping(virt);
+  	if(desc != 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)
+		{ .fd =			fd,
+		  .offset =		offset,
+		  .virt =		virt,
+		  .phys =		__pa(virt),
+		  .list = 		LIST_HEAD_INIT(desc->list) });
+	insert_phys_mapping(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;
+
+	rb_erase(&desc->rb, &phys_mappings);
+	kfree(desc);
+ out:
+	return(err);
+}
+
+static int physmem_fd = -1;
+
+static void remove_mapping(struct phys_desc *desc)
+{
+	void *virt = desc->virt;
+	int err;
+
+	rb_erase(&desc->rb, &phys_mappings);
+	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_phys_mapping(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);
+}
+
+EXPORT_SYMBOL(physmem_forget_descriptor);
+EXPORT_SYMBOL(physmem_remove_mapping);
+EXPORT_SYMBOL(physmem_subst_mapping);
+
+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)
+{
+  	struct phys_desc *desc = find_phys_mapping(virt);
+
+	return(desc != 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) {
+		if(err == -ENOMEM)
+			printk("try increasing the host's "
+			       "/proc/sys/vm/max_map_count to <physical "
+			       "memory size>/4096\n");
+		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_phys_mapping(__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	2004-10-18 14:56:50 -07:00
+++ b/arch/um/kernel/process.c	2004-10-18 14:56:50 -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"
@@ -47,7 +46,7 @@
 	int flags = 0, pages;
 
 	if(sig_stack != NULL){
-		pages = (1 << UML_CONFIG_KERNEL_STACK_ORDER) - 2;
+		pages = (1 << UML_CONFIG_KERNEL_STACK_ORDER);
 		set_sigstack(sig_stack, pages * page_size());
 		flags = SA_ONSTACK;
 	}
@@ -71,8 +70,7 @@
 	set_handler(SIGWINCH, (__sighandler_t) sig_handler, flags, 
 		    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);
+		    flags, SIGUSR1, SIGIO, SIGWINCH, SIGALRM, SIGVTALRM, -1);
 	signal(SIGHUP, SIG_IGN);
 
 	init_irq_signals(altstack);
@@ -122,24 +120,19 @@
 
 	/* 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(!WIFSIGNALED(status) || (WTERMSIG(status) != SIGKILL))
-		panic("outer trampoline didn't exit with SIGKILL");
-
-	return(arg.pid);
-}
+	if(new_pid < 0)
+		return(new_pid);
 
-void suspend_new_thread(int fd)
-{
-	char c;
+	CATCH_EINTR(err = waitpid(new_pid, &status, 0));
+	if(err < 0)
+		panic("Waiting for outer trampoline failed - errno = %d",
+		      errno);
 
-	os_stop_process(os_getpid());
+	if(!WIFSIGNALED(status) || (WTERMSIG(status) != SIGKILL))
+		panic("outer trampoline didn't exit with SIGKILL, "
+		      "status = %d", status);
 
-	if(read(fd, &c, sizeof(c)) != sizeof(c))
-		panic("read failed in suspend_new_thread");
+	return(arg.pid);
 }
 
 static int ptrace_child(void *arg)
@@ -168,7 +161,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 +178,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 +186,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 +258,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,15 +278,16 @@
 	}
 	stop_ptraced_child(pid, stack, 0);
 	printk("OK\n");
+	check_sysemu();
 }
 
 int run_kernel_thread(int (*fn)(void *), void *arg, void **jmp_ptr)
 {
-	jmp_buf buf;
+	sigjmp_buf buf;
 	int n;
 
 	*jmp_ptr = &buf;
-	n = setjmp(buf);
+	n = sigsetjmp(buf, 1);
 	if(n != 0)
 		return(n);
 	(*fn)(arg);
@@ -273,7 +327,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	2004-10-18 14:56:32 -07:00
+++ b/arch/um/kernel/process_kern.c	2004-10-18 14:56:32 -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,13 +157,15 @@
 	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)
 {
 	p->thread = (struct thread_struct) INIT_THREAD;
-	p->thread.kernel_stack = 
-		(unsigned long) p->thread_info + 2 * PAGE_SIZE;
 	return(CHOOSE_MODE_PROC(copy_thread_tt, copy_thread_skas, nr, 
 				clone_flags, sp, stack_top, p, regs));
 }
@@ -190,7 +192,7 @@
 
 void default_idle(void)
 {
-	idle_timer();
+	uml_idle_timer();
 
 	atomic_inc(&init_mm.mm_count);
 	current->mm = &init_mm;
@@ -299,6 +301,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);
@@ -318,8 +325,7 @@
 	unsigned long stack;
 
 	stack = sp & (PAGE_MASK << CONFIG_KERNEL_STACK_ORDER);
-	stack += 2 * PAGE_SIZE;
-	return(stack != current->thread.kernel_stack);
+	return(stack != (unsigned long) current_thread);
 }
 
 extern void remove_umid_dir(void);
@@ -367,10 +373,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 +396,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	2004-10-18 14:57:19 -07:00
+++ b/arch/um/kernel/ptrace.c	2004-10-18 14:57:19 -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;
@@ -292,7 +287,7 @@
 	}
 #endif
 	default:
-		ret = -EIO;
+		ret = ptrace_request(child, request, addr, data);
 		break;
 	}
  out_tsk:
@@ -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	2004-10-18 14:56:32 -07:00
+++ b/arch/um/kernel/reboot.c	2004-10-18 14:56:32 -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	2004-10-18 14:56:27 -07:00
+++ b/arch/um/kernel/sigio_kern.c	2004-10-18 14:56:27 -07:00
@@ -6,26 +6,33 @@
 #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)
+static 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)
 {
-	if(um_request_irq(SIGIO_WRITE_IRQ, fd, IRQ_READ, sigio_interrupt,
+	int err;
+
+	err = um_request_irq(SIGIO_WRITE_IRQ, fd, IRQ_READ, sigio_interrupt,
 			  SA_INTERRUPT | SA_SAMPLE_RANDOM, "write sigio", 
-			  NULL)){
-		printk("write_sigio_irq : um_request_irq failed\n");
+			     NULL);
+	if(err){
+		printk("write_sigio_irq : um_request_irq failed, err = %d\n",
+		       err);
 		return(-1);
 	}
 	sigio_irq_fd = fd;
diff -Nru a/arch/um/kernel/sigio_user.c b/arch/um/kernel/sigio_user.c
--- a/arch/um/kernel/sigio_user.c	2004-10-18 14:57:04 -07:00
+++ b/arch/um/kernel/sigio_user.c	2004-10-18 14:57:04 -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,14 @@
 		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);
+	/* Not now, but complain so we now where we failed. */
+	err = raw(master);
+	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 +87,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 +102,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 +130,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 +192,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 +208,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 +242,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 +261,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 +359,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 +389,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 +402,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	2004-10-18 14:56:33 -07:00
+++ b/arch/um/kernel/signal_kern.c	2004-10-18 14:56:33 -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/signal_user.c b/arch/um/kernel/signal_user.c
--- a/arch/um/kernel/signal_user.c	2004-10-18 14:56:48 -07:00
+++ b/arch/um/kernel/signal_user.c	2004-10-18 14:56:48 -07:00
@@ -80,6 +80,12 @@
 	change_signals(SIG_UNBLOCK);
 }
 
+/* These are the asynchronous signals.  SIGVTALRM and SIGARLM are handled
+ * together under SIGVTALRM_BIT.  SIGPROF is excluded because we want to
+ * be able to profile all of UML, not just the non-critical sections.  If
+ * profiling is not thread-safe, then that is not my problem.  We can disable
+ * profiling when SMP is enabled in that case.
+ */
 #define SIGIO_BIT 0
 #define SIGVTALRM_BIT 1
 
@@ -114,6 +120,11 @@
 		sigaddset(&mask, SIGVTALRM);
 		sigaddset(&mask, SIGALRM);
 	}
+
+	/* This is safe - sigprocmask is guaranteed to copy locally the
+	 * value of new_set, do his work and then, at the end, write to
+	 * old_set.
+	 */
 	if(sigprocmask(SIG_UNBLOCK, &mask, &mask) < 0)
 		panic("Failed to enable signals");
 	ret = enable_mask(&mask);
diff -Nru a/arch/um/kernel/skas/Makefile b/arch/um/kernel/skas/Makefile
--- a/arch/um/kernel/skas/Makefile	2004-10-18 14:56:28 -07:00
+++ b/arch/um/kernel/skas/Makefile	2004-10-18 14:56:28 -07:00
@@ -3,22 +3,14 @@
 # Licensed under the GPL
 #
 
-obj-y = exec_kern.o exec_user.o mem.o mem_user.o mmu.o process.o \
+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)/
+
+subdir-y := util
 
 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
-
 $(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	2004-10-18 14:56:17 -07:00
+++ b/arch/um/kernel/skas/exec_user.c	2004-10-18 14:56:17 -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	2004-10-18 14:56:32 -07:00
+++ b/arch/um/kernel/skas/include/mode.h	2004-10-18 14:56:32 -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	2004-10-18 14:55:55 -07:00
+++ b/arch/um/kernel/skas/include/ptrace-skas.h	2004-10-18 14:55:55 -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	2004-10-18 14:56:27 -07:00
+++ b/arch/um/kernel/skas/include/skas.h	2004-10-18 14:56:27 -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	2004-10-18 14:56:29 -07:00
+++ b/arch/um/kernel/skas/include/uaccess.h	2004-10-18 14:56:29 -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	2004-10-18 14:56:28 -07:00
+++ b/arch/um/kernel/skas/mem_user.c	2004-10-18 14:56:28 -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	2004-10-18 14:57:19 -07:00
+++ b/arch/um/kernel/skas/mmu.c	2004-10-18 14:57:19 -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	2004-10-18 14:57:04 -07:00
+++ b/arch/um/kernel/skas/process.c	2004-10-18 14:57:04 -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 = 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);
+		err = ptrace(PTRACE_SYSCALL, pid, 0, 0);
+		if(err < 0)
+			panic("handle_trap - continuing to end of syscall failed, "
+			      "errno = %d\n", errno);
+
+		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,45 +187,66 @@
 
 		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))
 {
-	jmp_buf switch_buf, fork_buf;
+	unsigned long flags;
+	sigjmp_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();
 }
 
 void thread_wait(void *sw, void *fb)
 {
-	jmp_buf buf, **switch_buf = sw, *fork_buf;
+	sigjmp_buf buf, **switch_buf = sw, *fork_buf;
 
 	*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,42 +286,43 @@
 		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)
 {
-	jmp_buf my_buf, **me_ptr = me, *next_buf = next;
+	sigjmp_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;
+static sigjmp_buf initial_jmpbuf;
 
 /* XXX Make these percpu */
 static void (*cb_proc)(void *arg);
 static void *cb_arg;
-static jmp_buf *cb_back;
+static sigjmp_buf *cb_back;
 
 int start_idle_thread(void *stack, void *switch_buf_ptr, void **fork_buf_ptr)
 {
-	jmp_buf **switch_buf = switch_buf_ptr;
+	sigjmp_buf **switch_buf = switch_buf_ptr;
 	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)
@@ -297,15 +347,15 @@
 
 void initial_thread_cb_skas(void (*proc)(void *), void *arg)
 {
-	jmp_buf here;
+	sigjmp_buf here;
 
 	cb_proc = proc;
 	cb_arg = arg;
 	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,40 +366,21 @@
 void halt_skas(void)
 {
 	block_signals();
-	longjmp(initial_jmpbuf, 3);
+	siglongjmp(initial_jmpbuf, 3);
 }
 
 void reboot_skas(void)
 {
 	block_signals();
-	longjmp(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);
-
-	if(fd < 0)
-		return(-errno);
-
-	if(from != -1){
-		copy = ((struct proc_mm_op) { .op 	= MM_COPY_SEGMENTS,
-					      .u 	= 
-					      { .copy_segments	= from } } );
-		n = os_write_file(fd, &copy, sizeof(copy));
-		if(n != sizeof(copy)) 
-			printk("new_mm : /proc/mm copy_segments failed, "
-			       "errno = %d\n", errno);
-	}
-	return(fd);
+	siglongjmp(initial_jmpbuf, 4);
 }
 
 void switch_mm_skas(int mm_fd)
 {
 	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 +388,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	2004-10-18 14:57:19 -07:00
+++ b/arch/um/kernel/skas/process_kern.c	2004-10-18 14:57:19 -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"
@@ -16,6 +22,62 @@
 #include "frame.h"
 #include "kern.h"
 #include "mode.h"
+#include "proc_mm.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)
 {
@@ -61,11 +123,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 +157,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);
 }
@@ -128,15 +192,36 @@
 		handler = new_thread_handler;
 	}
 
-	new_thread((void *) p->thread.kernel_stack, 
-		   &p->thread.mode.skas.switch_buf, 
+	new_thread(p->thread_info, &p->thread.mode.skas.switch_buf,
 		   &p->thread.mode.skas.fork_buf, handler);
 	return(0);
 }
 
+int new_mm(int from)
+{
+	struct proc_mm_op copy;
+	int n, fd;
+
+	fd = os_open_file("/proc/mm", of_cloexec(of_write(OPENFLAGS())), 0);
+	if(fd < 0)
+		return(fd);
+
+	if(from != -1){
+		copy = ((struct proc_mm_op) { .op 	= MM_COPY_SEGMENTS,
+					      .u 	=
+					      { .copy_segments	= from } } );
+		n = os_write_file(fd, &copy, sizeof(copy));
+		if(n != sizeof(copy))
+			printk("new_mm : /proc/mm copy_segments failed, "
+			       "err = %d\n", -n);
+	}
+
+	return(fd);
+}
+
 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,27 +245,29 @@
 
 int start_uml_skas(void)
 {
-	start_userspace();
+	start_userspace(0);
 	capture_signal_stack();
 
 	init_new_thread_signals(1);
-	idle_timer();
+	uml_idle_timer();
 
 	init_task.thread.request.u.thread.proc = start_kernel_proc;
 	init_task.thread.request.u.thread.arg = NULL;
-	return(start_idle_thread((void *) init_task.thread.kernel_stack,
+	return(start_idle_thread(init_task.thread_info,
 				 &init_task.thread.mode.skas.switch_buf,
 				 &init_task.thread.mode.skas.fork_buf));
 }
 
 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	2004-10-18 14:57:03 -07:00
+++ b/arch/um/kernel/skas/sys-i386/Makefile	2004-10-18 14:57:03 -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	2004-10-18 14:55:54 -07:00
+++ b/arch/um/kernel/skas/sys-i386/sigcontext.c	2004-10-18 14:55:54 -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	2004-10-18 14:56:33 -07:00
+++ b/arch/um/kernel/skas/syscall_kern.c	2004-10-18 14:56:33 -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	2004-10-18 14:57:04 -07:00
+++ b/arch/um/kernel/skas/syscall_user.c	2004-10-18 14:57:04 -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/tlb.c b/arch/um/kernel/skas/tlb.c
--- a/arch/um/kernel/skas/tlb.c	2004-10-18 14:56:32 -07:00
+++ b/arch/um/kernel/skas/tlb.c	2004-10-18 14:56:32 -07:00
@@ -77,7 +77,7 @@
 	int updated = 0, err;
 
 	mm = &init_mm;
-	for(addr = start_vm; addr < end_vm;){
+	for(addr = start; addr < end;){
 		pgd = pgd_offset(mm, addr);
 		pmd = pmd_offset(pgd, addr);
 		if(pmd_present(*pmd)){
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	2004-10-18 14:56:29 -07:00
+++ b/arch/um/kernel/skas/trap_user.c	2004-10-18 14:56:29 -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
  */
 
@@ -19,8 +19,10 @@
 	struct skas_regs *r;
 	struct signal_info *info;
 	int save_errno = errno;
+	int save_user;
 
 	r = &TASK_REGS(get_current())->skas;
+	save_user = r->is_user;
 	r->is_user = 0;
 	r->fault_addr = SC_FAULT_ADDR(sc);
 	r->fault_type = SC_FAULT_TYPE(sc);
@@ -33,16 +35,13 @@
 	(*info->handler)(sig, (union uml_pt_regs *) r);
 
 	errno = save_errno;
+	r->is_user = save_user;
 }
 
-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-10-18 14:57:24 -07:00
@@ -0,0 +1,250 @@
+/*
+ * 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"
+#include "user_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 void do_buffer_op(void *jmpbuf, void *arg_ptr)
+{
+	va_list args = *((va_list *) arg_ptr);
+	unsigned long addr = va_arg(args, unsigned long);
+	int len = va_arg(args, int);
+	int is_write = va_arg(args, int);
+	int (*op)(unsigned long, int, void *) = va_arg(args, void *);
+	void *arg = va_arg(args, void *);
+	int *res = va_arg(args, int *);
+	int size = min(PAGE_ALIGN(addr) - addr, (unsigned long) len);
+	int remain = len, n;
+
+	current->thread.fault_catcher = jmpbuf;
+	n = do_op(addr, size, is_write, op, arg);
+	if(n != 0){
+		*res = (n < 0 ? remain : 0);
+		goto out;
+	}
+
+	addr += size;
+	remain -= size;
+	if(remain == 0){
+		*res = 0;
+		goto out;
+	}
+
+	while(addr < ((addr + remain) & PAGE_MASK)){
+		n = do_op(addr, PAGE_SIZE, is_write, op, arg);
+		if(n != 0){
+			*res = (n < 0 ? remain : 0);
+			goto out;
+		}
+
+		addr += PAGE_SIZE;
+		remain -= PAGE_SIZE;
+	}
+	if(remain == 0){
+		*res = 0;
+		goto out;
+	}
+
+	n = do_op(addr, remain, is_write, op, arg);
+	if(n != 0)
+		*res = (n < 0 ? remain : 0);
+	else *res = 0;
+ out:
+	current->thread.fault_catcher = NULL;
+}
+
+static int buffer_op(unsigned long addr, int len, int is_write,
+		     int (*op)(unsigned long addr, int len, void *arg),
+		     void *arg)
+{
+	int faulted, res;
+
+	faulted = setjmp_wrapper(do_buffer_op, addr, len, is_write, op, arg,
+				 &res);
+	if(!faulted)
+		return(res);
+
+	return(addr + len - (unsigned long) current->thread.fault_addr);
+}
+
+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	2004-10-18 14:56:50 -07:00
+++ b/arch/um/kernel/skas/util/Makefile	2004-10-18 14:56:50 -07:00
@@ -1,10 +1,2 @@
-all: mk_ptregs
-
-mk_ptregs : mk_ptregs.o
-	$(CC) -o mk_ptregs mk_ptregs.o
-
-mk_ptregs.o : mk_ptregs.c
-	$(CC) -c $< 
-
-clean : 
-	$(RM) -f mk_ptregs *.o *~
+hostprogs-y		:= mk_ptregs
+always			:= $(hostprogs-y)
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	2004-10-18 14:56:29 -07:00
+++ b/arch/um/kernel/skas/util/mk_ptregs.c	2004-10-18 14:56:29 -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-10-18 14:56:19 -07:00
+++ b/arch/um/kernel/smp.c	2004-10-18 14:56:19 -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
 
@@ -12,10 +18,10 @@
 #include "linux/threads.h"
 #include "linux/interrupt.h"
 #include "linux/err.h"
+#include "linux/hardirq.h"
 #include "asm/smp.h"
 #include "asm/processor.h"
 #include "asm/spinlock.h"
-#include "asm/hardirq.h"
 #include "user_util.h"
 #include "kern_util.h"
 #include "kern.h"
@@ -23,9 +29,11 @@
 #include "os.h"
 
 /* CPU online map, set by smp_boot_cpus */
-unsigned long cpu_online_map = cpumask_of_cpu(0);
+cpumask_t cpu_online_map = CPU_MASK_NONE;
+cpumask_t cpu_possible_map = CPU_MASK_NONE;
 
 EXPORT_SYMBOL(cpu_online_map);
+EXPORT_SYMBOL(cpu_possible_map);
 
 /* Per CPU bogomips and other parameters
  * The only piece used here is the ipi pipe, which is set before SMP is
@@ -33,14 +41,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 +55,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 +107,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 +126,21 @@
 {
 	struct task_struct *idle;
 	unsigned long waittime;
-	int err, cpu;
+	int err, cpu, me = smp_processor_id();
+	int i;
 
-	cpu_set(0, cpu_online_map);
-	cpu_set(0, smp_callin_map);
+	for (i = 0; i < ncpus; ++i)
+		cpu_set(i, cpu_possible_map);
 
-	err = os_pipe(cpu_data[0].ipi_pipe, 1, 1);
-	if(err)	panic("CPU#0 failed to create IPI pipe, errno = %d", -err);
+	cpu_clear(me, cpu_online_map);
+	cpu_set(me, cpu_online_map);
+	cpu_set(me, cpu_callin_map);
+
+	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 +152,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 +188,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 +248,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-10-18 14:56:50 -07:00
+++ b/arch/um/kernel/sys_call_table.c	2004-10-18 14:56:50 -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,49 @@
 #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 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 +63,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-10-18 14:56:48 -07:00
+++ b/arch/um/kernel/syscall_kern.c	2004-10-18 14:56:48 -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,23 @@
 
 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);
-}
-
-long sys_clone(unsigned long clone_flags, unsigned long newsp)
-{
-	struct task_struct *p;
-
-	current->thread.forking = 1;
-	p = do_fork(clone_flags, newsp, NULL, 0, NULL, NULL);
-	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 +127,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 +214,7 @@
 		return sys_shmctl (first, second,
 				   (struct shmid_ds *) ptr);
 	default:
-		return -EINVAL;
+		return -ENOSYS;
 	}
 }
 
@@ -301,11 +261,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-10-18 14:56:28 -07:00
+++ b/arch/um/kernel/sysrq.c	2004-10-18 14:56:28 -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	2004-10-18 14:56:32 -07:00
+++ b/arch/um/kernel/tempfile.c	2004-10-18 14:56:32 -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-10-18 14:56:17 -07:00
+++ b/arch/um/kernel/time.c	2004-10-18 14:56:17 -07:00
@@ -4,24 +4,33 @@
  */
 
 #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 "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)
@@ -44,6 +53,15 @@
 		       errno);
 }
 
+void disable_timer(void)
+{
+	struct itimerval disable = ((struct itimerval) { { 0, 0 }, { 0, 0 }});
+	if((setitimer(ITIMER_VIRTUAL, &disable, NULL) < 0) ||
+	   (setitimer(ITIMER_REAL, &disable, NULL) < 0))
+		printk("disnable_timer - setitimer failed, errno = %d\n",
+		       errno);
+}
+
 void switch_timers(int to_real)
 {
 	struct itimerval disable = ((struct itimerval) { { 0, 0 }, { 0, 0 }});
@@ -66,7 +84,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 +94,23 @@
 	set_interval(ITIMER_REAL);
 }
 
+extern int do_posix_clock_monotonic_gettime(struct timespec *tp);
+
 void time_init(void)
 {
+	struct timespec now;
+
 	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 +123,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 +139,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	2004-10-18 14:56:33 -07:00
+++ b/arch/um/kernel/time_kern.c	2004-10-18 14:56:33 -07:00
@@ -20,6 +20,7 @@
 #include "user_util.h"
 #include "time_user.h"
 #include "mode.h"
+#include "os.h"
 
 u64 jiffies_64;
 
@@ -30,22 +31,63 @@
 	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_usecs;
+#ifdef CONFIG_UML_REAL_TIME_CLOCK
+static long long delta;   		/* Deviation per interval */
+#endif
+
+#define MILLION 1000000
 
 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
+		/* We've had 1 tick */
+		unsigned long long usecs = os_usecs();
+
+		delta += usecs - prev_usecs;
+		prev_usecs = usecs;
+
+		/* Protect against the host clock being set backwards */
+		if(delta < 0)
+			delta = 0;
+
+		ticks += (delta * HZ) / MILLION;
+		delta -= (ticks * MILLION) / HZ;
+#else
+		ticks = 1;
+#endif
+	}
+	else {
+		prev_usecs = os_usecs();
+		first_tick = 1;
+	}
+
+	while(ticks > 0){
+		do_IRQ(TIMER_IRQ, regs);
+		ticks--;
+	}
 }
 
 void boot_timer_handler(int sig)
@@ -58,12 +100,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 +126,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;
 }
@@ -110,7 +155,7 @@
 {
 	int i, n;
 
-	n = (loops_per_jiffy * HZ * usecs) / 1000000;
+	n = (loops_per_jiffy * HZ * usecs) / MILLION;
 	for(i=0;i<n;i++) ;
 }
 
@@ -118,16 +163,18 @@
 {
 	int i, n;
 
-	n = (loops_per_jiffy * HZ * usecs) / 1000000;
+	n = (loops_per_jiffy * HZ * usecs) / MILLION;
 	for(i=0;i<n;i++) ;
 }
 
 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 +183,7 @@
 unsigned long time_lock(void)
 {
 	unsigned long flags;
+
 	spin_lock_irqsave(&timer_spinlock, flags);
 	return(flags);
 }
@@ -150,8 +198,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 +207,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	2004-10-18 14:55:54 -07:00
+++ b/arch/um/kernel/trap_kern.c	2004-10-18 14:55:54 -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	2004-10-18 14:56:29 -07:00
+++ b/arch/um/kernel/trap_user.c	2004-10-18 14:56:29 -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);
@@ -121,9 +127,9 @@
 
 void do_longjmp(void *b, int val)
 {
-	jmp_buf *buf = b;
+	sigjmp_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	2004-10-18 14:56:32 -07:00
+++ b/arch/um/kernel/tt/Makefile	2004-10-18 14:56:32 -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	2004-10-18 14:56:17 -07:00
+++ b/arch/um/kernel/tt/exec_kern.c	2004-10-18 14:56:17 -07:00
@@ -14,9 +14,11 @@
 #include "kern_util.h"
 #include "irq_user.h"
 #include "time_user.h"
+#include "signal_user.h"
 #include "mem_user.h"
 #include "os.h"
 #include "tlb.h"
+#include "mode.h"
 
 static int exec_tramp(void *sig_stack)
 {
@@ -38,8 +40,7 @@
 		do_exit(SIGKILL);
 	}
 		
-	new_pid = start_fork_tramp((void *) current->thread.kernel_stack,
-				   stack, 0, exec_tramp);
+	new_pid = start_fork_tramp(current->thread_info, stack, 0, exec_tramp);
 	if(new_pid < 0){
 		printk(KERN_ERR 
 		       "flush_thread : new thread failed, errno = %d\n",
@@ -47,17 +48,19 @@
 		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());
+	change_sig(SIGUSR1, 1);
 
+	change_sig(SIGUSR1, 0);
 	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	2004-10-18 14:56:49 -07:00
+++ b/arch/um/kernel/tt/exec_user.c	2004-10-18 14:56:49 -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	2004-10-18 14:56:33 -07:00
+++ b/arch/um/kernel/tt/include/mode.h	2004-10-18 14:56:33 -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	2004-10-18 14:56:33 -07:00
+++ b/arch/um/kernel/tt/include/uaccess.h	2004-10-18 14:56:33 -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	2004-10-18 14:56:29 -07:00
+++ b/arch/um/kernel/tt/mem.c	2004-10-18 14:56: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	2004-10-18 14:56:27 -07:00
+++ b/arch/um/kernel/tt/mem_user.c	2004-10-18 14:56:27 -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	2004-10-18 14:56:49 -07:00
+++ b/arch/um/kernel/tt/process_kern.c	2004-10-18 14:56:49 -07:00
@@ -28,7 +28,7 @@
 
 void *switch_to_tt(void *prev, void *next, void *last)
 {
-	struct task_struct *from, *to;
+	struct task_struct *from, *to, *prev_sched;
 	unsigned long flags;
 	int err, vtalrm, alrm, prof, cpu;
 	char c;
@@ -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))
@@ -72,6 +72,18 @@
 	if(err != sizeof(c))
 		panic("read of switch_pipe failed, errno = %d", -err);
 
+	/* If the process that we have just scheduled away from has exited,
+	 * then it needs to be killed here.  The reason is that, even though
+	 * it will kill itself when it next runs, that may be too late.  Its
+	 * stack will be freed, possibly before then, and if that happens,
+	 * we have a use-after-free situation.  So, it gets killed here
+	 * in case it has not already killed itself.
+	 */
+	prev_sched = current->thread.prev_sched;
+	if((prev_sched->state == TASK_ZOMBIE) ||
+	   (prev_sched->state == TASK_DEAD))
+		os_kill_process(prev_sched->thread.mode.tt.extern_pid, 1);
+
 	/* This works around a nasty race with 'jail'.  If we are switching
 	 * between two threads of a threaded app and the incoming process 
 	 * runs before the outgoing process reaches the read, and it makes
@@ -104,50 +116,92 @@
 
 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 suspend_new_thread(int fd)
+{
+	int err;
+	char c;
+
+	os_stop_process(os_getpid());
+	err = os_read_file(fd, &c, sizeof(c));
+	if(err != sizeof(c))
+		panic("read failed in suspend_new_thread, err = %d", -err);
 }
 
 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);
+
+	/* XXX No set_user_mode here because a newly execed process will
+	 * immediately segfault on its non-existent IP, coming straight back
+	 * to the signal handler, which will call set_user_mode on its way
+	 * out.  This should probably change since it's confusing.
+	 */
 }
 
 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());
+	change_sig(SIGUSR1, 1);
 	return(0);
 }
 
@@ -156,7 +210,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 +219,33 @@
  	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());
+	change_sig(SIGUSR1, 1);
 	return(0);
 }
 
@@ -213,8 +265,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);
 	}
 
@@ -227,8 +279,7 @@
 
 	clone_flags &= CLONE_VM;
 	p->thread.temp_stack = stack;
-	new_pid = start_fork_tramp((void *) p->thread.kernel_stack, stack,
-				   clone_flags, tramp);
+	new_pid = start_fork_tramp(p->thread_info, stack, clone_flags, tramp);
 	if(new_pid < 0){
 		printk(KERN_ERR "copy_thread : clone failed - errno = %d\n", 
 		       -new_pid);
@@ -246,19 +297,30 @@
 	current->thread.request.op = OP_FORK;
 	current->thread.request.u.fork.pid = new_pid;
 	os_usr1_process(os_getpid());
-	return(0);
+
+	/* Enable the signal and then disable it to ensure that it is handled
+	 * here, and nowhere else.
+	 */
+	change_sig(SIGUSR1, 1);
+
+	change_sig(SIGUSR1, 0);
+	err = 0;
+ out:
+	return(err);
 }
 
 void reboot_tt(void)
 {
 	current->thread.request.op = OP_REBOOT;
 	os_usr1_process(os_getpid());
+	change_sig(SIGUSR1, 1);
 }
 
 void halt_tt(void)
 {
 	current->thread.request.op = OP_HALT;
 	os_usr1_process(os_getpid());
+	change_sig(SIGUSR1, 1);
 }
 
 void kill_off_processes_tt(void)
@@ -285,6 +347,9 @@
 		current->thread.request.u.cb.proc = proc;
 		current->thread.request.u.cb.arg = arg;
 		os_usr1_process(os_getpid());
+		change_sig(SIGUSR1, 1);
+
+		change_sig(SIGUSR1, 0);
 	}
 }
 
@@ -377,8 +442,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);
 
@@ -454,8 +519,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)
@@ -479,9 +545,9 @@
 	void *sp;
 	int pages;
 
-	pages = (1 << CONFIG_KERNEL_STACK_ORDER) - 2;
-	sp = (void *) init_task.thread.kernel_stack + pages * PAGE_SIZE - 
-		sizeof(unsigned long);
+	pages = (1 << CONFIG_KERNEL_STACK_ORDER);
+	sp = (void *) ((unsigned long) init_task.thread_info) +
+		pages * PAGE_SIZE - sizeof(unsigned long);
 	return(tracer(start_kernel_proc, sp));
 }
 
diff -Nru a/arch/um/kernel/tt/ptproxy/Makefile b/arch/um/kernel/tt/ptproxy/Makefile
--- a/arch/um/kernel/tt/ptproxy/Makefile	2004-10-18 14:56:28 -07:00
+++ b/arch/um/kernel/tt/ptproxy/Makefile	2004-10-18 14:56:28 -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	2004-10-18 14:56:33 -07:00
+++ b/arch/um/kernel/tt/ptproxy/proxy.c	2004-10-18 14:56:33 -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	2004-10-18 14:56:49 -07:00
+++ b/arch/um/kernel/tt/ptproxy/sysdep.c	2004-10-18 14:56:49 -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	2004-10-18 14:56:50 -07:00
+++ b/arch/um/kernel/tt/ptproxy/wait.c	2004-10-18 14:56:50 -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	2004-10-18 14:56:29 -07:00
+++ b/arch/um/kernel/tt/sys-i386/Makefile	2004-10-18 14:56:29 -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	2004-10-18 14:55:53 -07:00
+++ b/arch/um/kernel/tt/syscall_kern.c	2004-10-18 14:55:53 -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	2004-10-18 14:56:33 -07:00
+++ b/arch/um/kernel/tt/syscall_user.c	2004-10-18 14:56:33 -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	2004-10-18 14:55:54 -07:00
+++ b/arch/um/kernel/tt/tlb.c	2004-10-18 14:55:54 -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	2004-10-18 14:55:54 -07:00
+++ b/arch/um/kernel/tt/tracer.c	2004-10-18 14:55:54 -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);
 			}
@@ -329,7 +330,8 @@
 					continue;
 				}
 				tracing = 0;
-				if(do_syscall(task, pid)) sig = SIGUSR2;
+				if(do_syscall(task, pid))
+					sig = SIGUSR2;
 				else clear_singlestep(task);
 				break;
 			case SIGPROF:
@@ -401,7 +403,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/trap_user.c b/arch/um/kernel/tt/trap_user.c
--- a/arch/um/kernel/tt/trap_user.c	2004-10-18 14:56:33 -07:00
+++ b/arch/um/kernel/tt/trap_user.c	2004-10-18 14:56:33 -07:00
@@ -23,6 +23,13 @@
 
 	unprotect_kernel_mem();
 
+	/* This is done because to allow SIGSEGV to be delivered inside a SEGV
+	 * handler.  This can happen in copy_user, and if SEGV is disabled,
+	 * the process will die.
+	 */
+	if(sig == SIGSEGV)
+		change_sig(SIGSEGV, 1);
+
 	r = &TASK_REGS(get_current())->tt;
 	save_regs = *r;
 	is_user = user_context(SC_SP(sc));
@@ -30,7 +37,6 @@
 	if(sig != SIGUSR2) 
 		r->syscall = -1;
 
-	change_sig(SIGUSR1, 1);
 	info = &sig_info[sig];
 	if(!info->is_irq) unblock_signals();
 
@@ -39,7 +45,6 @@
 	if(is_user){
 		interrupt_end();
 		block_signals();
-		change_sig(SIGUSR1, 0);
 		set_user_mode(NULL);
 	}
 	*r = save_regs;
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-10-18 14:57:22 -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	2004-10-18 14:56:28 -07:00
+++ b/arch/um/kernel/tt/uaccess_user.c	2004-10-18 14:56:28 -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;
+	sigjmp_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	2004-10-18 14:56:49 -07:00
+++ b/arch/um/kernel/tt/unmap.c	2004-10-18 14:56:49 -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	2004-10-18 14:56:33 -07:00
+++ b/arch/um/kernel/tty_log.c	2004-10-18 14:56:33 -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	2004-10-18 14:56:48 -07:00
+++ b/arch/um/kernel/uaccess_user.c	2004-10-18 14:56:48 -07:00
@@ -18,9 +18,9 @@
 {
 	unsigned long *faddrp = (unsigned long *) fault_addr, ret;
 
-	jmp_buf jbuf;
+	sigjmp_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-10-18 14:56:49 -07:00
+++ b/arch/um/kernel/um_arch.c	2004-10-18 14:56:49 -07:00
@@ -27,7 +27,6 @@
 #include "user_util.h"
 #include "kern_util.h"
 #include "kern.h"
-#include "mprot.h"
 #include "mem_user.h"
 #include "mem.h"
 #include "umid.h"
@@ -38,13 +37,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 +57,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 +142,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 +187,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 +218,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 +229,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,15 +299,15 @@
 
 /* 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)
 
 int linux_main(int argc, char **argv)
 {
-	unsigned long avail;
+	unsigned long avail, diff;
 	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;
@@ -315,6 +323,16 @@
 
 	brk_start = (unsigned long) sbrk(0);
 	CHOOSE_MODE_PROC(before_mem_tt, before_mem_skas, brk_start);
+	/* Increase physical memory size for exec-shield users
+	so they actually get what they asked for. This should
+	add zero for non-exec shield users */
+
+	diff = UML_ROUND_UP(brk_start) - UML_ROUND_UP(&_end);
+	if(diff > 1024 * 1024){
+		printf("Adding %ld bytes to physical memory to account for "
+		       "exec-shield gap\n", diff);
+		physmem_size += UML_ROUND_UP(brk_start) - UML_ROUND_UP(&_end);
+	}
 
 	uml_physmem = uml_start;
 
@@ -328,12 +346,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 +365,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 +387,23 @@
 		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 +428,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	2004-10-18 14:57:03 -07:00
+++ b/arch/um/kernel/umid.c	2004-10-18 14:57:03 -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 %d "
+			   "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);
@@ -195,17 +199,20 @@
 static int __init set_uml_dir(char *name, int *add)
 {
 	if((strlen(name) > 0) && (name[strlen(name) - 1] != '/')){
-		uml_dir = malloc(strlen(name) + 1);
+		uml_dir = malloc(strlen(name) + 2);
 		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 here because do_initcalls doesn't look at
+			 * the return value.
+			 */
 			return(0);
 		}
 		sprintf(uml_dir, "%s/", name);
 	}
 	else uml_dir = name;
-	return 0;
+	return(0);
 }
 
 static int __init make_uml_dir(void)
@@ -217,7 +224,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 +239,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 +304,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-10-18 14:56:29 -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	2004-10-18 14:57:03 -07: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-10-18 14:56:16 -07:00
+++ b/arch/um/kernel/user_util.c	2004-10-18 14:56:16 -07:00
@@ -5,10 +5,10 @@
 
 #include <stdio.h>
 #include <stdlib.h>
-#include <fcntl.h>
 #include <unistd.h>
 #include <limits.h>
-#include <sys/mman.h> 
+#include <setjmp.h>
+#include <sys/mman.h>
 #include <sys/stat.h>
 #include <sys/ptrace.h>
 #include <sys/utsname.h>
@@ -81,19 +81,19 @@
 	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);
 			}
 			else if(WIFEXITED(status)) 
-				printk("process exited with status %d\n", 
-				       WEXITSTATUS(status));
+				printk("process %d exited with status %d\n",
+				       pid, WEXITSTATUS(status));
 			else if(WIFSIGNALED(status))
-				printk("process exited with signal %d\n", 
-				       WTERMSIG(status));
+				printk("process %d exited with signal %d\n",
+				       pid, WTERMSIG(status));
 			else if((WSTOPSIG(status) == SIGVTALRM) ||
 				(WSTOPSIG(status) == SIGALRM) ||
 				(WSTOPSIG(status) == SIGIO) ||
@@ -109,8 +109,8 @@
 				ptrace(cont_type, pid, 0, WSTOPSIG(status));
 				continue;
 			}
-			else printk("process stopped with signal %d\n", 
-				    WSTOPSIG(status));
+			else printk("process %d stopped with signal %d\n",
+				    pid, WSTOPSIG(status));
 			panic("wait_for_stop failed to wait for %d to stop "
 			      "with %d\n", pid, sig);
 		}
@@ -118,29 +118,27 @@
 	}
 }
 
-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)
 {
 	struct termios tt;
 	int err;
 
-	tcgetattr(fd, &tt);
+	CATCH_EINTR(err = tcgetattr(fd, &tt));
+	if (err < 0) {
+			printk("tcgetattr failed, errno = %d\n", errno);
+		return(-errno);
+	}
+
 	cfmakeraw(&tt);
-	err = tcsetattr(fd, TCSANOW, &tt);
-	if((err < 0) && complain){
-		printk("tcsetattr failed, errno = %d\n", errno);
+
+ 	CATCH_EINTR(err = tcsetattr(fd, TCSADRAIN, &tt));
+	if (err < 0) {
+			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);
 }
 
@@ -161,6 +159,21 @@
 	uname(&host);
 	sprintf(host_info, "%s %s %s %s %s", host.sysname, host.nodename,
 		host.release, host.version, host.machine);
+}
+
+int setjmp_wrapper(void (*proc)(void *, void *), ...)
+{
+        va_list args;
+	sigjmp_buf buf;
+	int n;
+
+	n = sigsetjmp(buf, 1);
+	if(n == 0){
+		va_start(args, proc);
+		(*proc)(&buf, &args);
+	}
+	va_end(args);
+	return(n);
 }
 
 /*
diff -Nru a/arch/um/kernel/vmlinux.lds.S b/arch/um/kernel/vmlinux.lds.S
--- a/arch/um/kernel/vmlinux.lds.S	2004-10-18 14:55:46 -07:00
+++ /dev/null	Wed Dec 31 16:00:00 196900
@@ -1,11 +0,0 @@
-#include <asm-generic/vmlinux.lds.h>
-	
-OUTPUT_FORMAT(ELF_FORMAT)
-OUTPUT_ARCH(ELF_ARCH)
-ENTRY(_start)
-jiffies = jiffies_64;
-
-SECTIONS
-{
-#include "asm/common.lds.S"
-}
diff -Nru a/arch/um/main.c b/arch/um/main.c
--- a/arch/um/main.c	2004-10-18 14:56:49 -07: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	2004-10-18 14:56:33 -07:00
+++ b/arch/um/os-Linux/Makefile	2004-10-18 14:56:33 -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 time.o tty.o user_syms.o drivers/
 
-USER_OBJS := $(foreach file,file.o process.o tty.o,$(obj)/$(file))
+USER_OBJS := $(foreach file,file.o process.o time.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	2004-10-18 14:55:54 -07:00
+++ b/arch/um/os-Linux/drivers/ethertap_kern.c	2004-10-18 14:55:54 -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	2004-10-18 14:56:32 -07:00
+++ b/arch/um/os-Linux/drivers/ethertap_user.c	2004-10-18 14:56:32 -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	2004-10-18 14:57:05 -07:00
+++ b/arch/um/os-Linux/drivers/tuntap_user.c	2004-10-18 14:57:05 -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	2004-10-18 14:57:04 -07:00
+++ b/arch/um/os-Linux/file.c	2004-10-18 14:57:04 -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,236 @@
 #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)
+{
+	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;
+
+	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);
+	}
+
+	return(0);
+}
+
+int os_mode_fd(int fd, int mode)
 {
-	struct stat64 buf;
+	int err;
+
+	do {
+		err = fchmod(fd, mode);
+	} while((err < 0) && (errno==EINTR)) ;
 
-	if(stat64(file, &buf) == -1)
+	if(err < 0)
 		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_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 +268,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 +293,7 @@
 
 	err = connect(fd, (struct sockaddr *) &sock, sizeof(sock));
 	if(err)
-		return(err);
+		return(-errno);
 
 	return(fd);
 }
@@ -109,88 +312,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)
@@ -219,6 +496,16 @@
 	return(0);
 }
 
+int os_clear_fd_async(int fd)
+{
+	int flags = fcntl(fd, F_GETFL);
+
+	flags &= ~(O_ASYNC | O_NONBLOCK);
+	if(fcntl(fd, F_SETFL, flags) < 0)
+		return(-errno);
+	return(0);
+}
+
 int os_set_fd_block(int fd, int blocking)
 {
 	int flags;
@@ -270,7 +557,7 @@
 		return(-EINVAL);
 	}
 	err = shutdown(fd, what);
-	if(err)
+	if(err < 0)
 		return(-errno);
 	return(0);
 }
@@ -315,7 +602,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 +614,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 +628,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	2004-10-18 14:55:55 -07:00
+++ b/arch/um/os-Linux/process.c	2004-10-18 14:55:55 -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 %ld", &pc) != 1){
+		  "%*d %*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,7 +90,7 @@
 {
 	kill(pid, SIGKILL);
 	if(reap_child)
-		waitpid(pid, NULL, 0);
+		CATCH_EINTR(waitpid(pid, NULL, 0));
 		
 }
 
@@ -95,7 +104,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 +113,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 +135,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/time.c b/arch/um/os-Linux/time.c
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/arch/um/os-Linux/time.c	2004-10-18 14:57:23 -07:00
@@ -0,0 +1,21 @@
+#include <stdlib.h>
+#include <sys/time.h>
+
+unsigned long long os_usecs(void)
+{
+	struct timeval tv;
+
+	gettimeofday(&tv, NULL);
+	return((unsigned long long) tv.tv_sec * 1000000 + tv.tv_usec);
+}
+
+/*
+ * 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/tty.c b/arch/um/os-Linux/tty.c
--- a/arch/um/os-Linux/tty.c	2004-10-18 14:56:33 -07:00
+++ b/arch/um/os-Linux/tty.c	2004-10-18 14:56:33 -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-10-18 14:57:23 -07:00
@@ -0,0 +1,90 @@
+#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 *memmove(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(memmove);
+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	2004-10-18 14:56:13 -07:00
+++ b/arch/um/sys-i386/Makefile	2004-10-18 14:56:13 -07:00
@@ -1,14 +1,21 @@
-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
 
 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
+
+# this needs to be before the foreach, because clean-files does not accept
+# complete paths like $(src)/$f.
+clean-files := $(SYMLINKS)
+
 SYMLINKS := $(foreach f,$(SYMLINKS),$(src)/$f)
 
+bitops.c-dir = lib
 semaphore.c-dir = kernel
 highmem.c-dir = mm
 module.c-dir = kernel
@@ -24,19 +31,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	2004-10-18 14:57:21 -07:00
+++ b/arch/um/sys-i386/bugs.c	2004-10-18 14:57:21 -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,48 +137,76 @@
  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)
 {
-	unsigned long ip;
+	unsigned char tmp[2];
 
 	/* This is testing for a cmov (0x0f 0x4x) instruction causing a
 	 * SIGILL in init.
 	 */
 	if((sig != SIGILL) || (TASK_PID(get_current()) != 1)) return(0);
 
-	ip = UPT_IP(regs);
-	if((*((char *) ip) != 0x0f) || ((*((char *) (ip + 1)) & 0xf0) != 0x40))
+	if (copy_from_user_proc(tmp, (void *) UPT_IP(regs), 2))
+		panic("SIGILL in init, could not read instructions!\n");
+	if((tmp[0] != 0x0f) || ((tmp[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	2004-10-18 14:57:04 -07: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	2004-10-18 14:56:32 -07:00
+++ b/arch/um/sys-i386/fault.c	2004-10-18 14:56:32 -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/ldt.c b/arch/um/sys-i386/ldt.c
--- a/arch/um/sys-i386/ldt.c	2004-10-18 14:56:29 -07:00
+++ b/arch/um/sys-i386/ldt.c	2004-10-18 14:56:29 -07:00
@@ -13,6 +13,8 @@
 #ifdef CONFIG_MODE_TT
 extern int modify_ldt(int func, void *ptr, unsigned long bytecount);
 
+/* XXX this needs copy_to_user and copy_from_user */
+
 int sys_modify_ldt_tt(int func, void *ptr, unsigned long bytecount)
 {
 	if(verify_area(VERIFY_READ, ptr, bytecount)) return(-EFAULT);
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	2004-10-18 14:57:19 -07:00
+++ b/arch/um/sys-i386/ptrace_user.c	2004-10-18 14:57:19 -07:00
@@ -39,10 +39,11 @@
 	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, value = 0x%x, errno = %d\n", i,
+			       regs[i], errno);
 	}
 }
 
@@ -54,7 +55,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/syscalls.c b/arch/um/sys-i386/syscalls.c
--- a/arch/um/sys-i386/syscalls.c	2004-10-18 14:56:32 -07:00
+++ b/arch/um/sys-i386/syscalls.c	2004-10-18 14:56:32 -07:00
@@ -3,6 +3,7 @@
  * Licensed under the GPL
  */
 
+#include "linux/sched.h"
 #include "asm/mman.h"
 #include "asm/uaccess.h"
 #include "asm/unistd.h"
@@ -54,6 +55,27 @@
 		return -EFAULT;
 	/* sys_select() does the appropriate kernel locking */
 	return sys_select(a.n, a.inp, a.outp, a.exp, a.tvp);
+}
+
+/* The i386 version skips reading from %esi, the fourth argument. So we must do
+ * this, too.
+ */
+int sys_clone(unsigned long clone_flags, unsigned long newsp, int *parent_tid,
+	      int unused, int *child_tid)
+{
+	long ret;
+
+	/* XXX: normal arch do here this pass, and also pass the regs to
+	 * do_fork, instead of NULL. Currently the arch-independent code
+	 * ignores these values, while the UML code (actually it's
+	 * copy_thread) does the right thing. But this should change,
+	 probably. */
+	/*if (!newsp)
+		newsp = UPT_SP(current->thread.regs);*/
+	current->thread.forking = 1;
+	ret = do_fork(clone_flags, newsp, NULL, 0, parent_tid, child_tid);
+	current->thread.forking = 0;
+	return(ret);
 }
 
 /*
diff -Nru a/arch/um/sys-i386/util/Makefile b/arch/um/sys-i386/util/Makefile
--- a/arch/um/sys-i386/util/Makefile	2004-10-18 14:57:04 -07:00
+++ b/arch/um/sys-i386/util/Makefile	2004-10-18 14:57:04 -07:00
@@ -1,17 +1,8 @@
 
-host-progs	:= mk_sc
-always		:= $(host-progs) 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 $@ $<
-
-clean :
-	$(RM) -f $(build-targets)
-
-archmrproper : clean
+HOSTCFLAGS_mk_thread_kern.o	:= $(CFLAGS) $(CPPFLAGS)
+HOSTCFLAGS_mk_thread_user.o	:= $(USER_CFLAGS)
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	2004-10-18 14:57:03 -07:00
+++ b/arch/um/sys-i386/util/mk_sc.c	2004-10-18 14:57:03 -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	2004-10-18 14:55:54 -07:00
+++ b/arch/um/sys-ia64/Makefile	2004-10-18 14:55:54 -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	2004-10-18 14:56:29 -07:00
+++ b/arch/um/sys-ppc/Makefile	2004-10-18 14:56:29 -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	2004-10-18 14:56:29 -07: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	2004-10-18 14:57:04 -07:00
+++ b/arch/um/util/Makefile	2004-10-18 14:57:04 -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	2004-10-18 14:55:54 -07:00
+++ b/arch/um/util/mk_constants_kern.c	2004-10-18 14:55:54 -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/Kconfig b/arch/v850/Kconfig
--- a/arch/v850/Kconfig	2004-10-18 14:56:29 -07:00
+++ b/arch/v850/Kconfig	2004-10-18 14:56:29 -07:00
@@ -68,7 +68,6 @@
       	     bool "Anna"
    endchoice
 
-
    #### V850E processor-specific config
 
    # All CPUs currently supported use the v850e architecture
@@ -153,7 +152,6 @@
    	  bool
 	  default RTE_MB_A_PCI
 
-
    #### Some feature-specific configs
 
    # Everything except for the GDB simulator uses the same interrupt controller
@@ -181,7 +179,6 @@
    	  bool
 	  default !V850E_CACHE && !V850E2_CACHE
 
-
    #### Misc config
 
    config ROM_KERNEL
@@ -305,34 +302,7 @@
 
 source "drivers/usb/Kconfig"
 
-
-menu "Kernel hacking"
-
-config DEBUG_KERNEL
-	bool "Kernel debugging"
-
-config DEBUG_INFO
-	bool "Compile the kernel with debug info"
-	depends on DEBUG_KERNEL
-	help
-          If you say Y here the resulting kernel image will include
-	  debugging info resulting in a larger kernel image.
-	  Say Y here only if you plan to use gdb to debug the kernel.
-	  If you don't debug the kernel, you can say N.
-
-config MAGIC_SYSRQ
-	bool "Magic SysRq key"
-	depends on DEBUG_KERNEL
-	help
-	  Enables console device to interprent special characters as
-	  commands to dump state information.
-
-config NO_KERNEL_MSG
-	bool "Suppress Kernel BUG Messages"
-	help
-	  Do not output any debug BUG messages within the kernel.
-
-endmenu
+source "arch/v850/Kconfig.debug"
 
 source "security/Kconfig"
 
diff -Nru a/arch/v850/Kconfig.debug b/arch/v850/Kconfig.debug
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/arch/v850/Kconfig.debug	2004-10-18 14:57:22 -07:00
@@ -0,0 +1,10 @@
+menu "Kernel hacking"
+
+source "lib/Kconfig.debug"
+
+config NO_KERNEL_MSG
+	bool "Suppress Kernel BUG Messages"
+	help
+	  Do not output any debug BUG messages within the kernel.
+
+endmenu
diff -Nru a/arch/v850/kernel/Makefile b/arch/v850/kernel/Makefile
--- a/arch/v850/kernel/Makefile	2004-10-18 14:57:05 -07:00
+++ b/arch/v850/kernel/Makefile	2004-10-18 14:57:05 -07:00
@@ -9,7 +9,7 @@
 # for more details.
 #
 
-extra-y := head.o init_task.o vmlinux.lds.s
+extra-y := head.o init_task.o vmlinux.lds
 
 obj-y += intv.o entry.o process.o syscalls.o time.o semaphore.o setup.o \
 	 signal.o irq.o mach.o ptrace.o bug.o
diff -Nru a/arch/v850/kernel/asm-consts.c b/arch/v850/kernel/asm-consts.c
--- a/arch/v850/kernel/asm-consts.c	2004-10-18 14:56:27 -07:00
+++ b/arch/v850/kernel/asm-consts.c	2004-10-18 14:56:27 -07:00
@@ -12,8 +12,8 @@
 #include <linux/sched.h>
 #include <linux/kernel_stat.h>
 #include <linux/ptrace.h>
+#include <linux/hardirq.h>
 #include <asm/irq.h>
-#include <asm/hardirq.h>
 #include <asm/errno.h>
 
 #define DEFINE(sym, val) \
diff -Nru a/arch/v850/kernel/irq.c b/arch/v850/kernel/irq.c
--- a/arch/v850/kernel/irq.c	2004-10-18 14:56:49 -07:00
+++ b/arch/v850/kernel/irq.c	2004-10-18 14:56:49 -07:00
@@ -141,13 +141,15 @@
 int handle_IRQ_event(unsigned int irq, struct pt_regs * regs, struct irqaction * action)
 {
 	int status = 1; /* Force the "do bottom halves" bit */
+	int ret;
 
 	if (!(action->flags & SA_INTERRUPT))
 		local_irq_enable();
 
 	do {
-		status |= action->flags;
-		action->handler(irq, action->dev_id, regs);
+		ret = action->handler(irq, action->dev_id, regs);
+		if (ret == IRQ_HANDLED)
+			status |= action->flags;
 		action = action->next;
 	} while (action);
 	if (status & SA_SAMPLE_RANDOM)
diff -Nru a/arch/v850/kernel/ptrace.c b/arch/v850/kernel/ptrace.c
--- a/arch/v850/kernel/ptrace.c	2004-10-18 14:56:32 -07:00
+++ b/arch/v850/kernel/ptrace.c	2004-10-18 14:56:32 -07:00
@@ -147,14 +147,8 @@
 		rval = ptrace_attach(child);
 		goto out_tsk;
 	}
-	rval = -ESRCH;
-	if (!(child->ptrace & PT_PTRACED))
-		goto out_tsk;
-	if (child->state != TASK_STOPPED) {
-		if (request != PTRACE_KILL)
-			goto out_tsk;
-	}
-	if (child->parent != current)
+	ret = ptrace_check_attach(child, request == PTRACE_KILL);
+	if (ret < 0)
 		goto out_tsk;
 
 	switch (request) {
@@ -269,11 +263,8 @@
 		return;
 	/* 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
 	 * for normal use.  strace only continues with a signal if the
diff -Nru a/arch/v850/kernel/rte_mb_a_pci.c b/arch/v850/kernel/rte_mb_a_pci.c
--- a/arch/v850/kernel/rte_mb_a_pci.c	2004-10-18 14:56:27 -07:00
+++ b/arch/v850/kernel/rte_mb_a_pci.c	2004-10-18 14:56:27 -07:00
@@ -322,8 +322,6 @@
 
 /* Stubs for things we don't use.  */
 
-struct pci_fixup pcibios_fixups[] = { { 0 } };
-
 /* Called after each bus is probed, but before its children are examined. */
 void pcibios_fixup_bus(struct pci_bus *b)
 {
diff -Nru a/arch/v850/kernel/setup.c b/arch/v850/kernel/setup.c
--- a/arch/v850/kernel/setup.c	2004-10-18 14:56:29 -07:00
+++ b/arch/v850/kernel/setup.c	2004-10-18 14:56:29 -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	2004-10-18 14:57:05 -07:00
+++ b/arch/v850/kernel/signal.c	2004-10-18 14:57:05 -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-10-18 14:56:33 -07:00
+++ b/arch/v850/kernel/time.c	2004-10-18 14:56:33 -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/v850_ksyms.c b/arch/v850/kernel/v850_ksyms.c
--- a/arch/v850/kernel/v850_ksyms.c	2004-10-18 14:56:33 -07:00
+++ b/arch/v850/kernel/v850_ksyms.c	2004-10-18 14:56:33 -07:00
@@ -14,7 +14,6 @@
 #include <asm/io.h>
 #include <asm/semaphore.h>
 #include <asm/checksum.h>
-#include <asm/hardirq.h>
 #include <asm/current.h>
 
 
@@ -37,29 +36,29 @@
 EXPORT_SYMBOL (ip_fast_csum);
 
 /* string / mem functions */
-EXPORT_SYMBOL_NOVERS (strcpy);
-EXPORT_SYMBOL_NOVERS (strncpy);
-EXPORT_SYMBOL_NOVERS (strcat);
-EXPORT_SYMBOL_NOVERS (strncat);
-EXPORT_SYMBOL_NOVERS (strcmp);
-EXPORT_SYMBOL_NOVERS (strncmp);
-EXPORT_SYMBOL_NOVERS (strchr);
-EXPORT_SYMBOL_NOVERS (strlen);
-EXPORT_SYMBOL_NOVERS (strnlen);
-EXPORT_SYMBOL_NOVERS (strpbrk);
-EXPORT_SYMBOL_NOVERS (strrchr);
-EXPORT_SYMBOL_NOVERS (strstr);
-EXPORT_SYMBOL_NOVERS (memset);
-EXPORT_SYMBOL_NOVERS (memcpy);
-EXPORT_SYMBOL_NOVERS (memmove);
-EXPORT_SYMBOL_NOVERS (memcmp);
-EXPORT_SYMBOL_NOVERS (memscan);
+EXPORT_SYMBOL (strcpy);
+EXPORT_SYMBOL (strncpy);
+EXPORT_SYMBOL (strcat);
+EXPORT_SYMBOL (strncat);
+EXPORT_SYMBOL (strcmp);
+EXPORT_SYMBOL (strncmp);
+EXPORT_SYMBOL (strchr);
+EXPORT_SYMBOL (strlen);
+EXPORT_SYMBOL (strnlen);
+EXPORT_SYMBOL (strpbrk);
+EXPORT_SYMBOL (strrchr);
+EXPORT_SYMBOL (strstr);
+EXPORT_SYMBOL (memset);
+EXPORT_SYMBOL (memcpy);
+EXPORT_SYMBOL (memmove);
+EXPORT_SYMBOL (memcmp);
+EXPORT_SYMBOL (memscan);
 
 /* semaphores */
-EXPORT_SYMBOL_NOVERS (__down);
-EXPORT_SYMBOL_NOVERS (__down_interruptible);
-EXPORT_SYMBOL_NOVERS (__down_trylock);
-EXPORT_SYMBOL_NOVERS (__up);
+EXPORT_SYMBOL (__down);
+EXPORT_SYMBOL (__down_interruptible);
+EXPORT_SYMBOL (__down_trylock);
+EXPORT_SYMBOL (__up);
 
 /*
  * libgcc functions - functions that are used internally by the
@@ -72,8 +71,8 @@
 extern void __muldi3 (void);
 extern void __negdi2 (void);
 
-EXPORT_SYMBOL_NOVERS (__ashldi3);
-EXPORT_SYMBOL_NOVERS (__ashrdi3);
-EXPORT_SYMBOL_NOVERS (__lshrdi3);
-EXPORT_SYMBOL_NOVERS (__muldi3);
-EXPORT_SYMBOL_NOVERS (__negdi2);
+EXPORT_SYMBOL (__ashldi3);
+EXPORT_SYMBOL (__ashrdi3);
+EXPORT_SYMBOL (__lshrdi3);
+EXPORT_SYMBOL (__muldi3);
+EXPORT_SYMBOL (__negdi2);
diff -Nru a/arch/v850/kernel/vmlinux.lds.S b/arch/v850/kernel/vmlinux.lds.S
--- a/arch/v850/kernel/vmlinux.lds.S	2004-10-18 14:56:33 -07:00
+++ b/arch/v850/kernel/vmlinux.lds.S	2004-10-18 14:56:33 -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-10-18 14:56:49 -07:00
+++ b/arch/x86_64/Kconfig	2004-10-18 14:56:49 -07:00
@@ -4,7 +4,7 @@
 #
 # Note: ISA is disabled and will hopefully never be enabled.
 # If you managed to buy an ISA x86-64 box you'll have to fix all the
-# ISA drivers you need yourself. 
+# ISA drivers you need yourself.
 #
 
 mainmenu "Linux Kernel Configuration"
@@ -57,7 +57,7 @@
 	  it is not recommended because it looks ugly and doesn't cooperate
 	  with klogd/syslogd or the X server. You should normally N here,
 	  unless you want to debug such a crash.
-	  
+
 config HPET_TIMER
 	bool
 	default y
@@ -78,6 +78,10 @@
 	bool
 	default y
 
+config GENERIC_IOMAP
+	bool
+	default y
+
 source "init/Kconfig"
 
 
@@ -90,14 +94,14 @@
 config MK8
 	bool "AMD-Opteron/Athlon64"
 	help
-	  Optimize for AMD Opteron/Athlon64/Hammer/K8 CPUs. 
+	  Optimize for AMD Opteron/Athlon64/Hammer/K8 CPUs.
 
 config MPSC
-       bool "Intel x86-64" 
+       bool "Intel x86-64"
        help
 	  Optimize for Intel IA32 with 64bit extension CPUs
 	  (Prescott/Nocona/Potomac)
-       
+
 config GENERIC_CPU
 	bool "Generic-x86-64"
 	help
@@ -130,8 +134,8 @@
 	tristate "/dev/cpu/microcode - Intel CPU microcode support"
 	---help---
 	  If you say Y here the 'File systems' section, you will be
-	  able to update the microcode on Intel processors. You will 
-	  obviously need the actual microcode binary data itself which is 
+	  able to update the microcode on Intel processors. You will
+	  obviously need the actual microcode binary data itself which is
 	  not shipped with the Linux kernel.
 
 	  For latest news and information on obtaining all the required
@@ -165,7 +169,7 @@
 	bool
 	depends on SMP && !MK8
 	default y
-       
+
 config MATH_EMULATION
 	bool
 
@@ -231,13 +235,13 @@
 	  be preempted even if it is in kernel mode executing a system call.
 	  This allows applications to run more reliably even when the system is
 	  under load. On contrary it may also break your drivers and add
-	  priority inheritance problems to your system. Don't select it if 
+	  priority inheritance problems to your system. Don't select it if
 	  you rely on a stable system or have slightly obscure hardware.
 	  It's also not very well tested on x86-64 currently.
 	  You have been warned.
 
-	  Say Y here if you are feeling brave and building a kernel for a 
-	  desktop, embedded or real-time system.  Say N if you are unsure. 
+	  Say Y here if you are feeling brave and building a kernel for a
+	  desktop, embedded or real-time system.  Say N if you are unsure.
 
 config SCHED_SMT
 	bool "SMT (Hyperthreading) scheduler support"
@@ -297,7 +301,7 @@
 	  properly with 32-bit PCI devices that do not support DAC (Double Address
 	  Cycle). The IOMMU can be turned off at runtime with the iommu=off parameter.
 	  Normally the kernel will take the right choice by itself.
-	  If unsure say Y 
+	  If unsure, say Y.
 
 # need this always enabled with GART_IOMMU for the VIA workaround
 config SWIOTLB
@@ -310,13 +314,18 @@
 	depends on !GART_IOMMU && !SWIOTLB
 	default y
 	help
-	  Don't use IOMMU code. This will cause problems when you have more than 4GB 
+	  Don't use IOMMU code. This will cause problems when you have more than 4GB
 	  of memory and any 32-bit devices. Don't turn on unless you know what you
 	  are doing.
 
 config X86_MCE
-	bool
+	bool "Machine check support" if EMBEDDED
 	default y
+	help
+	   Include a machine check error handler to report hardware errors.
+	   This version will require the mcelog utility to decode some
+	   machine check error logs. See
+	   ftp://ftp.x86-64.org/pub/linux/tools/mcelog
 
 endmenu
 
@@ -336,17 +345,27 @@
 config PCI
 	bool "PCI support"
 
-# x86-64 doesn't support PCI BIOS access from long mode so always go direct. 
+# x86-64 doesn't support PCI BIOS access from long mode so always go direct.
 config PCI_DIRECT
 	bool
 	depends on PCI
 	default y
 
-config PCI_MMCONFIG 
-	bool "Support mmconfig PCI config space access" 
+config PCI_MMCONFIG
+	bool "Support mmconfig PCI config space access"
 	depends on PCI
 	select ACPI_BOOT
 
+config UNORDERED_IO
+       bool "Unordered IO mapping access"
+       depends on EXPERIMENTAL
+       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"
@@ -398,110 +417,10 @@
 
 source "arch/x86_64/oprofile/Kconfig"
 
-menu "Kernel hacking"
-
-config DEBUG_KERNEL
-	bool "Kernel debugging"
-	help
-	  Say Y here if you are developing drivers or trying to debug and
-	  identify kernel problems.
-
-config DEBUG_SLAB
-	bool "Debug memory allocations"
-	depends on DEBUG_KERNEL
-	help
-	  Say Y here to have the kernel do limited verification on memory
-	  allocation as well as poisoning memory on free to catch use of freed
-	  memory.
-
-config MAGIC_SYSRQ
-	bool "Magic SysRq key"
-	help
-	  If you say Y here, you will have some control over the system even
-	  if the system crashes for example during kernel debugging (e.g., you
-	  will be able to flush the buffer cache to disk, reboot the system
-	  immediately or dump some status information). This is accomplished
-	  by pressing various keys while holding SysRq (Alt+PrintScreen). It
-	  also works on a serial console (on PC hardware at least), if you
-	  send a BREAK and then within 5 seconds a command keypress. The
-	  keys are documented in <file:Documentation/sysrq.txt>. Don't say Y
-	  unless you really know what this hack does.
-
-config DEBUG_SPINLOCK
-	bool "Spinlock debugging"
-	depends on DEBUG_KERNEL
-	help
-	  Say Y here and build SMP to catch missing spinlock initialization
-	  and certain other kinds of spinlock errors commonly made.  This is
-	  best used in conjunction with the NMI watchdog so that spinlock
-	  deadlocks are also debuggable.
-
-# !SMP for now because the context switch early causes GPF in segment reloading
-# and the GS base checking does the wrong thing then, causing a hang.
-config CHECKING
-	bool "Additional run-time checks"
-	depends on DEBUG_KERNEL && !SMP
-	help
-	  Enables some internal consistency checks for kernel debugging.
-	  You should normally say N.
-
-config INIT_DEBUG
-	bool "Debug __init statements"
-	depends on DEBUG_KERNEL
-	help
-	  Fill __init and __initdata at the end of boot. This helps debugging
-	  illegal uses of __init and __initdata after initialization.	  
-
-config DEBUG_INFO
-	bool "Compile the kernel with debug info"
-	depends on DEBUG_KERNEL
-	help
-          If you say Y here the resulting kernel image will include
-	  debugging info resulting in a larger kernel image.
-	  Say Y here only if you plan to use gdb to debug the kernel.
-	  Please note that this option requires new binutils.
-	  If you don't debug the kernel, you can say N.
-	  
-config FRAME_POINTER
-       bool "Compile the kernel with frame pointers"
-       help
-	 Compile the kernel with frame pointers. This may help for some 
-	 debugging with external debuggers. Note the standard oops backtracer 
-	 doesn't make use of this  and the x86-64 kernel doesn't ensure an consistent
-	 frame pointer through inline assembly (semaphores etc.)
-	 Normally you should say N.
-
-config IOMMU_DEBUG
-       depends on GART_IOMMU && DEBUG_KERNEL
-       bool "Enable IOMMU debugging"
-       help
-         Force the IOMMU to on even when you have less than 4GB of
-	 memory and add debugging code. On overflow always panic. And
-	 allow to enable IOMMU leak tracing. Can be disabled at boot
-	 time with iommu=noforce. This will also enable scatter gather
-	 list merging.  Currently not recommended for production
-	 code. When you use it make sure you have a big enough
-	 IOMMU/AGP aperture.  Most of the options enabled by this can
-	 be set more finegrained using the iommu= command line
-	 options. See Documentation/x86_64/boot-options.txt for more
-	 details.
-
-config IOMMU_LEAK
-       bool "IOMMU leak tracing"
-       depends on DEBUG_KERNEL
-       depends on IOMMU_DEBUG
-       help
-         Add a simple leak tracer to the IOMMU code. This is useful when you
-	 are debugging a buggy device driver that leaks IOMMU mappings.
-       
-#config X86_REMOTE_DEBUG
-#       bool "kgdb debugging stub"
-
-endmenu
+source "arch/x86_64/Kconfig.debug"
 
 source "security/Kconfig"
 
 source "crypto/Kconfig"
 
 source "lib/Kconfig"
-
diff -Nru a/arch/x86_64/Kconfig.debug b/arch/x86_64/Kconfig.debug
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/arch/x86_64/Kconfig.debug	2004-10-18 14:57:22 -07:00
@@ -0,0 +1,59 @@
+menu "Kernel hacking"
+
+source "lib/Kconfig.debug"
+
+# !SMP for now because the context switch early causes GPF in segment reloading
+# and the GS base checking does the wrong thing then, causing a hang.
+config CHECKING
+	bool "Additional run-time checks"
+	depends on DEBUG_KERNEL && !SMP
+	help
+	  Enables some internal consistency checks for kernel debugging.
+	  You should normally say N.
+
+config INIT_DEBUG
+	bool "Debug __init statements"
+	depends on DEBUG_KERNEL
+	help
+	  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 IOMMU_DEBUG
+       depends on GART_IOMMU && DEBUG_KERNEL
+       bool "Enable IOMMU debugging"
+       help
+         Force the IOMMU to on even when you have less than 4GB of
+	 memory and add debugging code. On overflow always panic. And
+	 allow to enable IOMMU leak tracing. Can be disabled at boot
+	 time with iommu=noforce. This will also enable scatter gather
+	 list merging.  Currently not recommended for production
+	 code. When you use it make sure you have a big enough
+	 IOMMU/AGP aperture.  Most of the options enabled by this can
+	 be set more finegrained using the iommu= command line
+	 options. See Documentation/x86_64/boot-options.txt for more
+	 details.
+
+config IOMMU_LEAK
+       bool "IOMMU leak tracing"
+       depends on DEBUG_KERNEL
+       depends on IOMMU_DEBUG
+       help
+         Add a simple leak tracer to the IOMMU code. This is useful when you
+	 are debugging a buggy device driver that leaks IOMMU mappings.
+
+#config X86_REMOTE_DEBUG
+#       bool "kgdb debugging stub"
+
+endmenu
diff -Nru a/arch/x86_64/Makefile b/arch/x86_64/Makefile
--- a/arch/x86_64/Makefile	2004-10-18 14:57:03 -07:00
+++ b/arch/x86_64/Makefile	2004-10-18 14:57:03 -07:00
@@ -37,10 +37,10 @@
 OBJCOPYFLAGS	:= -O binary -R .note -R .comment -S
 LDFLAGS_vmlinux := -e stext
 
-CHECK           := $(CHECK) -D__x86_64__=1
+CHECKFLAGS      += -D__x86_64__ -m64
 
-cflags-$(CONFIG_MK8) += $(call check_gcc,-march=k8,)
-cflags-$(CONFIG_MPSC) += $(call check_gcc,-march=nocona,)
+cflags-$(CONFIG_MK8) += $(call cc-option,-march=k8)
+cflags-$(CONFIG_MPSC) += $(call cc-option,-march=nocona)
 CFLAGS += $(cflags-y)
 
 CFLAGS += -mno-red-zone
@@ -54,11 +54,11 @@
 CFLAGS += -fno-asynchronous-unwind-tables
 # -fweb shrinks the kernel a bit, but the difference is very small
 # it also messes up debugging, so don't use it for now.
-#CFLAGS += $(call check_gcc,-fweb,)
+#CFLAGS += $(call cc-option,-fweb)
 endif
 # -funit-at-a-time shrinks the kernel .text considerably
 # unfortunately it makes reading oopses harder.
-CFLAGS += $(call check_gcc,-funit-at-a-time,)
+CFLAGS += $(call cc-option,-funit-at-a-time)
 
 head-y := arch/x86_64/kernel/head.o arch/x86_64/kernel/head64.o arch/x86_64/kernel/init_task.o
 
@@ -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/boot/Makefile b/arch/x86_64/boot/Makefile
--- a/arch/x86_64/boot/Makefile	2004-10-18 14:56:28 -07:00
+++ b/arch/x86_64/boot/Makefile	2004-10-18 14:56:28 -07:00
@@ -30,7 +30,7 @@
 
 EXTRA_CFLAGS := -m32
 
-host-progs	:= tools/build
+hostprogs-y	:= tools/build
 subdir-		:= compressed/	#Let make clean descend in compressed/
 # ---------------------------------------------------------------------------
 
diff -Nru a/arch/x86_64/boot/video.S b/arch/x86_64/boot/video.S
--- a/arch/x86_64/boot/video.S	2004-10-18 14:56:32 -07:00
+++ b/arch/x86_64/boot/video.S	2004-10-18 14:56:32 -07:00
@@ -66,6 +66,7 @@
 #define VIDEO_80x30 0x0f05
 #define VIDEO_80x34 0x0f06
 #define VIDEO_80x60 0x0f07
+#define VIDEO_GFX_HACK 0x0f08
 #define VIDEO_LAST_SPECIAL 0x0f09
 
 /* Video modes given by resolution */
@@ -97,7 +98,6 @@
 #define PARAM_LFB_PAGES		0x32
 #define PARAM_VESA_ATTRIB	0x34
 
-
 /* Define DO_STORE according to CONFIG_VIDEO_RETAIN */
 #ifdef CONFIG_VIDEO_RETAIN
 #define DO_STORE call store_screen
@@ -133,6 +133,7 @@
 #ifdef CONFIG_VIDEO_RETAIN
 	call	restore_screen			# Restore screen contents
 #endif /* CONFIG_VIDEO_RETAIN */
+	call	store_edid
 #endif /* CONFIG_VIDEO_SELECT */
 	call	mode_params			# Store mode parameters
 	popw	%ds				# Restore original DS
@@ -231,6 +232,41 @@
 	xorl	%eax, %eax
 	movw	18(%di), %ax
 	movl	%eax, %fs:(PARAM_LFB_SIZE)
+
+# switching the DAC to 8-bit is for <= 8 bpp only
+	movw	%fs:(PARAM_LFB_DEPTH), %ax
+	cmpw	$8, %ax
+	jg	dac_done
+
+# get DAC switching capability
+	xorl	%eax, %eax
+	movb	10(%di), %al
+	testb	$1, %al
+	jz	dac_set
+
+# attempt to switch DAC to 8-bit
+	movw	$0x4f08, %ax
+	movw	$0x0800, %bx
+	int	$0x10
+	cmpw	$0x004f, %ax
+	jne     dac_set
+	movb    %bh, dac_size		# store actual DAC size
+
+dac_set:
+# set color size to DAC size
+	movb	dac_size, %al
+	movb	%al, %fs:(PARAM_LFB_COLORS+0)
+	movb	%al, %fs:(PARAM_LFB_COLORS+2)
+	movb	%al, %fs:(PARAM_LFB_COLORS+4)
+	movb	%al, %fs:(PARAM_LFB_COLORS+6)
+
+# set color offsets to 0
+	movb	$0, %fs:(PARAM_LFB_COLORS+1)
+	movb	$0, %fs:(PARAM_LFB_COLORS+3)
+	movb	$0, %fs:(PARAM_LFB_COLORS+5)
+	movb	$0, %fs:(PARAM_LFB_COLORS+7)
+
+dac_done:
 # get protected mode interface informations
 	movw	$0x4f0a, %ax
 	xorw	%bx, %bx
@@ -440,7 +476,7 @@
 
 # Setting of user mode (AX=mode ID) => CF=success
 mode_set:
-       	movw    %ax, %fs:(0x01fa)
+	movw	%ax, %fs:(0x01fa)		# Store mode for use in acpi_wakeup.S
 	movw	%ax, %bx
 	cmpb	$0xff, %ah
 	jz	setalias
@@ -744,7 +780,15 @@
 	movw	$0x503c, force_size
 	jmp	setvde
 
+# Special hack for ThinkPad graphics
 set_gfx:
+#ifdef CONFIG_VIDEO_GFX_HACK
+	movw	$VIDEO_GFX_BIOS_AX, %ax
+	movw	$VIDEO_GFX_BIOS_BX, %bx
+	int	$0x10
+	movw	$VIDEO_GFX_DUMMY_RESOLUTION, force_size
+	stc
+#endif
 	ret
 
 #ifdef CONFIG_VIDEO_RETAIN
@@ -969,6 +1013,10 @@
 	.word	0x5022				# 80x34
 	.word	VIDEO_80x60
 	.word	0x503c				# 80x60
+#ifdef CONFIG_VIDEO_GFX_HACK
+	.word	VIDEO_GFX_HACK
+	.word	VIDEO_GFX_DUMMY_RESOLUTION
+#endif
 
 vga_modes_end:
 # Detect VESA modes.
@@ -1875,6 +1923,39 @@
 	popw	%ax
 	ret
 
+store_edid:
+	pushw	%es				# just save all registers
+	pushw	%ax
+	pushw	%bx
+	pushw   %cx
+	pushw	%dx
+	pushw   %di
+
+	pushw	%fs
+	popw    %es
+
+	movl	$0x13131313, %eax		# memset block with 0x13
+	movw    $32, %cx
+	movw	$0x440, %di
+	cld
+	rep
+	stosl
+
+	movw	$0x4f15, %ax                    # do VBE/DDC
+	movw	$0x01, %bx
+	movw	$0x00, %cx
+	movw    $0x01, %dx
+	movw	$0x440, %di
+	int	$0x10
+
+	popw	%di				# restore all registers
+	popw	%dx
+	popw	%cx
+	popw	%bx
+	popw	%ax
+	popw	%es
+	ret
+
 # VIDEO_SELECT-only variables
 mt_end:		.word	0	# End of video mode table if built
 edit_buf:	.space	6	# Line editor buffer
@@ -1883,6 +1964,7 @@
 do_restore:	.byte	0	# Screen contents altered during mode change
 svga_prefix:	.byte	VIDEO_FIRST_BIOS>>8	# Default prefix for BIOS modes
 graphic_mode:	.byte	0	# Graphic mode with a linear frame buffer
+dac_size:	.byte	6	# DAC bit depth
 
 # Status messages
 keymsg:		.ascii	"Press <RETURN> to see video modes available, "
diff -Nru a/arch/x86_64/defconfig b/arch/x86_64/defconfig
--- a/arch/x86_64/defconfig	2004-10-18 14:56:48 -07:00
+++ b/arch/x86_64/defconfig	2004-10-18 14:56:48 -07:00
@@ -1,5 +1,7 @@
 #
 # Automatically generated make config: don't edit
+# Linux kernel version: 2.6.9-rc1-bk19
+# Sun Sep 12 23:13:23 2004
 #
 CONFIG_X86_64=y
 CONFIG_64BIT=y
@@ -17,11 +19,11 @@
 #
 CONFIG_EXPERIMENTAL=y
 CONFIG_CLEAN_COMPILE=y
-CONFIG_STANDALONE=y
 
 #
 # General setup
 #
+CONFIG_LOCALVERSION=""
 CONFIG_SWAP=y
 CONFIG_SYSVIPC=y
 CONFIG_POSIX_MQUEUE=y
@@ -35,6 +37,7 @@
 # CONFIG_EMBEDDED is not set
 CONFIG_KALLSYMS=y
 CONFIG_KALLSYMS_ALL=y
+# CONFIG_KALLSYMS_EXTRA_PASS is not set
 CONFIG_FUTEX=y
 CONFIG_EPOLL=y
 CONFIG_IOSCHED_NOOP=y
@@ -42,6 +45,8 @@
 CONFIG_IOSCHED_DEADLINE=y
 CONFIG_IOSCHED_CFQ=y
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+CONFIG_SHMEM=y
+# CONFIG_TINY_SHMEM is not set
 
 #
 # Loadable module support
@@ -123,6 +128,8 @@
 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
 
@@ -144,6 +151,8 @@
 #
 # Generic Driver Options
 #
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
 # CONFIG_DEBUG_DRIVER is not set
 
 #
@@ -171,7 +180,8 @@
 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_UB is not set
 CONFIG_BLK_DEV_RAM=y
 CONFIG_BLK_DEV_RAM_SIZE=4096
 CONFIG_BLK_DEV_INITRD=y
@@ -186,10 +196,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
@@ -273,16 +283,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_MEGARAID is not set
+CONFIG_SCSI_AIC79XX=y
+CONFIG_AIC79XX_CMDS_PER_DEVICE=32
+CONFIG_AIC79XX_RESET_DELAY_MS=4000
+# 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 is not set
+# CONFIG_MEGARAID_NEWGEN is not set
+# CONFIG_MEGARAID_LEGACY 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 +308,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
@@ -324,7 +341,6 @@
 #
 CONFIG_FUSION=y
 CONFIG_FUSION_MAX_SGE=40
-# CONFIG_FUSION_ISENSE is not set
 # CONFIG_FUSION_CTL is not set
 
 #
@@ -362,11 +378,13 @@
 # CONFIG_INET_AH is not set
 # CONFIG_INET_ESP is not set
 # CONFIG_INET_IPCOMP is not set
+# CONFIG_INET_TUNNEL is not set
 CONFIG_IPV6=y
 # CONFIG_IPV6_PRIVACY is not set
 # CONFIG_INET6_AH is not set
 # CONFIG_INET6_ESP is not set
 # CONFIG_INET6_IPCOMP is not set
+# CONFIG_INET6_TUNNEL is not set
 # CONFIG_IPV6_TUNNEL is not set
 # CONFIG_NETFILTER is not set
 
@@ -392,6 +410,7 @@
 # QoS and/or fair queueing
 #
 # CONFIG_NET_SCHED is not set
+# CONFIG_NET_CLS_ROUTE is not set
 
 #
 # Network testing
@@ -452,6 +471,7 @@
 # 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)
@@ -575,7 +595,6 @@
 CONFIG_UNIX98_PTYS=y
 CONFIG_LEGACY_PTYS=y
 CONFIG_LEGACY_PTY_COUNT=256
-# CONFIG_QIC02_TAPE is not set
 
 #
 # IPMI
@@ -602,6 +621,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 +633,11 @@
 # CONFIG_I2C is not set
 
 #
+# Dallas's 1-wire bus
+#
+# CONFIG_W1 is not set
+
+#
 # Misc devices
 #
 # CONFIG_IBM_ASM is not set
@@ -635,7 +662,6 @@
 # Console display driver support
 #
 CONFIG_VGA_CONSOLE=y
-# CONFIG_MDA_CONSOLE is not set
 CONFIG_DUMMY_CONSOLE=y
 
 #
@@ -686,6 +712,8 @@
 CONFIG_USB_DEVICEFS=y
 # CONFIG_USB_BANDWIDTH is not set
 # CONFIG_USB_DYNAMIC_MINORS is not set
+# CONFIG_USB_SUSPEND is not set
+# CONFIG_USB_OTG is not set
 
 #
 # USB Host Controller Drivers
@@ -706,6 +734,7 @@
 CONFIG_USB_PRINTER=y
 CONFIG_USB_STORAGE=y
 # CONFIG_USB_STORAGE_DEBUG is not set
+# CONFIG_USB_STORAGE_RW_DETECT is not set
 # CONFIG_USB_STORAGE_DATAFAB is not set
 # CONFIG_USB_STORAGE_FREECOM is not set
 # CONFIG_USB_STORAGE_ISD200 is not set
@@ -830,7 +859,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
 
 #
@@ -879,6 +909,7 @@
 CONFIG_EXPORTFS=y
 CONFIG_SUNRPC=y
 # CONFIG_RPCSEC_GSS_KRB5 is not set
+# CONFIG_RPCSEC_GSS_SPKM3 is not set
 # CONFIG_SMB_FS is not set
 # CONFIG_CIFS is not set
 # CONFIG_NCP_FS is not set
@@ -906,12 +937,14 @@
 # Kernel hacking
 #
 CONFIG_DEBUG_KERNEL=y
-# CONFIG_DEBUG_SLAB is not set
 CONFIG_MAGIC_SYSRQ=y
+# CONFIG_DEBUG_SLAB is not set
 # CONFIG_DEBUG_SPINLOCK is not set
-# CONFIG_INIT_DEBUG is not set
+# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
 # CONFIG_DEBUG_INFO is not set
 # CONFIG_FRAME_POINTER is not set
+# CONFIG_INIT_DEBUG is not set
+# CONFIG_SCHEDSTATS is not set
 # CONFIG_IOMMU_DEBUG is not set
 
 #
@@ -927,5 +960,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-10-18 14:55:54 -07:00
+++ b/arch/x86_64/ia32/ia32_binfmt.c	2004-10-18 14:55:54 -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-10-18 14:56:32 -07:00
+++ b/arch/x86_64/ia32/ia32_ioctl.c	2004-10-18 14:56:32 -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-10-18 14:57:04 -07:00
+++ b/arch/x86_64/ia32/ia32_signal.c	2004-10-18 14:57:04 -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;
 }	
 
@@ -342,6 +347,7 @@
 		 struct pt_regs *regs, unsigned int mask)
 {
 	int tmp, err = 0;
+	u32 eflags;
 
 	tmp = 0;
 	__asm__("movl %%gs,%0" : "=r"(tmp): "0"(tmp));
@@ -366,7 +372,11 @@
 	err |= __put_user(current->thread.trap_no, &sc->trapno);
 	err |= __put_user(current->thread.error_code, &sc->err);
 	err |= __put_user((u32)regs->rip, &sc->eip);
-	err |= __put_user((u32)regs->eflags, &sc->eflags);
+	eflags = regs->eflags;
+	if (current->ptrace & PT_PTRACED) {
+		eflags &= ~TF_MASK;
+	}
+	err |= __put_user((u32)eflags, &sc->eflags);
 	err |= __put_user((u32)regs->rsp, &sc->esp_at_signal);
 
 	tmp = save_i387_ia32(current, fpstate, regs, 0);
@@ -484,7 +494,13 @@
 	regs->ss = __USER32_DS; 
 
 	set_fs(USER_DS);
-	regs->eflags &= ~TF_MASK;
+	if (regs->eflags & TF_MASK) {
+		if (current->ptrace & PT_PTRACED) {
+			ptrace_notify(SIGTRAP);
+		} else {
+			regs->eflags &= ~TF_MASK;
+		}
+	}
 
 #if DEBUG_SIG
 	printk("SIG deliver (%s:%d): sp=%p pc=%p ra=%p\n",
@@ -494,9 +510,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,
@@ -580,7 +594,13 @@
 	regs->ss = __USER32_DS; 
 
 	set_fs(USER_DS);
-	regs->eflags &= ~TF_MASK;
+	if (regs->eflags & TF_MASK) {
+		if (current->ptrace & PT_PTRACED) {
+			ptrace_notify(SIGTRAP);
+		} else {
+			regs->eflags &= ~TF_MASK;
+		}
+	}
 
 #if DEBUG_SIG
 	printk("SIG deliver (%s:%d): sp=%p pc=%p ra=%p\n",
@@ -590,8 +610,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-10-18 14:56:29 -07:00
+++ b/arch/x86_64/ia32/ia32entry.S	2004-10-18 14:56:29 -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
@@ -589,6 +586,7 @@
 	.quad compat_sys_mq_notify
 	.quad compat_sys_mq_getsetattr
 	.quad quiet_ni_syscall		/* reserved for kexec */
+	.quad sys32_waitid
 	/* don't forget to change IA32_NR_syscalls */
 ia32_syscall_end:		
 	.rept IA32_NR_syscalls-(ia32_syscall_end-ia32_sys_call_table)/8
diff -Nru a/arch/x86_64/ia32/ptrace32.c b/arch/x86_64/ia32/ptrace32.c
--- a/arch/x86_64/ia32/ptrace32.c	2004-10-18 14:56:27 -07:00
+++ b/arch/x86_64/ia32/ptrace32.c	2004-10-18 14:56:27 -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-10-18 14:56:29 -07:00
+++ b/arch/x86_64/ia32/sys_ia32.c	2004-10-18 14:56:29 -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,47 @@
 	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);
+}
+
+asmlinkage long sys32_waitid(int which, compat_pid_t pid,
+			     siginfo_t32 __user *uinfo, int options,
+			     struct compat_rusage __user *uru)
+{
+	siginfo_t info;
+	struct rusage ru;
+	long ret;
+	mm_segment_t old_fs = get_fs();
+
+	info.si_signo = 0;
+	set_fs (KERNEL_DS);
+	ret = sys_waitid(which, pid, (siginfo_t __user *) &info, options,
+			 uru ? &ru : NULL);
+	set_fs (old_fs);
+
+	if (ret < 0 || info.si_signo == 0)
+		return ret;
+
+	if (uru && (ret = put_compat_rusage(&ru, uru)))
+		return ret;
+
+	BUG_ON(info.si_code & __SI_MASK);
+	info.si_code |= __SI_CHLD;
+	return ia32_copy_siginfo_to_user(uinfo, &info);
 }
 
 /*
@@ -1262,7 +1288,7 @@
 		if (fd >= 0) {
 			struct file *f = filp_open(tmp, flags, mode);
 			error = PTR_ERR(f);
-			if (unlikely(IS_ERR(f))) {
+			if (IS_ERR(f)) {
 				put_unused_fd(fd); 
 				fd = error;
 			} else
@@ -1336,6 +1362,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/ia32/syscall32.c b/arch/x86_64/ia32/syscall32.c
--- a/arch/x86_64/ia32/syscall32.c	2004-10-18 14:56:33 -07:00
+++ b/arch/x86_64/ia32/syscall32.c	2004-10-18 14:56:33 -07:00
@@ -30,16 +30,20 @@
 char *syscall32_page; 
 static int use_sysenter __initdata = -1;
 
-/* RED-PEN: This knows too much about high level VM */ 
-/* Alternative would be to generate a vma with appropriate backing options
-   and let it be handled by generic VM */ 
-int map_syscall32(struct mm_struct *mm, unsigned long address) 
+/*
+ * Map the 32bit vsyscall page on demand.
+ *
+ * RED-PEN: This knows too much about high level VM.
+ *
+ * Alternative would be to generate a vma with appropriate backing options
+ * and let it be handled by generic VM.
+ */
+int __map_syscall32(struct mm_struct *mm, unsigned long address)
 { 
 	pte_t *pte;
 	pmd_t *pmd;
 	int err = 0;
 
-	down_read(&mm->mmap_sem);
 	spin_lock(&mm->page_table_lock); 
 	pmd = pmd_alloc(mm, pgd_offset(mm, address), address); 
 	if (pmd && (pte = pte_alloc_map(mm, pmd, address)) != NULL) { 
@@ -54,6 +58,14 @@
 	} else
 		err = -ENOMEM; 
 	spin_unlock(&mm->page_table_lock);
+	return err;
+}
+
+int map_syscall32(struct mm_struct *mm, unsigned long address)
+{
+	int err;
+	down_read(&mm->mmap_sem);
+	err = __map_syscall32(mm, address);
 	up_read(&mm->mmap_sem);
 	return err;
 }
@@ -76,7 +88,8 @@
 	
 __initcall(init_syscall32); 
 
-void __init syscall32_cpu_init(void)
+/* May not be __init: called during resume */
+void syscall32_cpu_init(void)
 {
 	if (use_sysenter < 0)
  		use_sysenter = (boot_cpu_data.x86_vendor == X86_VENDOR_INTEL);
diff -Nru a/arch/x86_64/kernel/Makefile b/arch/x86_64/kernel/Makefile
--- a/arch/x86_64/kernel/Makefile	2004-10-18 14:56:49 -07:00
+++ b/arch/x86_64/kernel/Makefile	2004-10-18 14:56:49 -07:00
@@ -2,7 +2,7 @@
 # Makefile for the linux kernel.
 #
 
-extra-y 	:= head.o head64.o init_task.o vmlinux.lds.s
+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 \
@@ -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-10-18 14:56:49 -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.s
-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-10-18 14:56:49 -07:00
+++ b/arch/x86_64/kernel/aperture.c	2004-10-18 14:56:49 -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-10-18 14:56:11 -07:00
+++ b/arch/x86_64/kernel/apic.c	2004-10-18 14:56:11 -07:00
@@ -33,6 +33,8 @@
 #include <asm/mpspec.h>
 #include <asm/pgalloc.h>
 
+int apic_verbosity;
+
 int disable_apic_timer __initdata;
 
 /* Using APIC to generate smp_local_timer_interrupt? */
@@ -123,7 +125,7 @@
 		 * PIC mode, enable APIC mode in the IMCR, i.e.
 		 * connect BSP's local APIC to INT and NMI lines.
 		 */
-		printk(KERN_INFO "leaving PIC mode, enabling APIC mode.\n");
+		apic_printk(APIC_VERBOSE, "leaving PIC mode, enabling APIC mode.\n");
 		outb(0x70, 0x22);
 		outb(0x01, 0x23);
 	}
@@ -138,7 +140,7 @@
 		 * interrupts, including IPIs, won't work beyond
 		 * this point!  The only exception are INIT IPIs.
 		 */
-		printk(KERN_INFO "disabling APIC mode, entering PIC mode.\n");
+		apic_printk(APIC_QUIET, "disabling APIC mode, entering PIC mode.\n");
 		outb(0x70, 0x22);
 		outb(0x00, 0x23);
 	}
@@ -172,10 +174,10 @@
 	 * The version register is read-only in a real APIC.
 	 */
 	reg0 = apic_read(APIC_LVR);
-	Dprintk("Getting VERSION: %x\n", reg0);
+	apic_printk(APIC_DEBUG, "Getting VERSION: %x\n", reg0);
 	apic_write(APIC_LVR, reg0 ^ APIC_LVR_MASK);
 	reg1 = apic_read(APIC_LVR);
-	Dprintk("Getting VERSION: %x\n", reg1);
+	apic_printk(APIC_DEBUG, "Getting VERSION: %x\n", reg1);
 
 	/*
 	 * The two version reads above should print the same
@@ -199,10 +201,10 @@
 	 * The ID register is read/write in a real APIC.
 	 */
 	reg0 = apic_read(APIC_ID);
-	Dprintk("Getting ID: %x\n", reg0);
+	apic_printk(APIC_DEBUG, "Getting ID: %x\n", reg0);
 	apic_write(APIC_ID, reg0 ^ APIC_ID_MASK);
 	reg1 = apic_read(APIC_ID);
-	Dprintk("Getting ID: %x\n", reg1);
+	apic_printk(APIC_DEBUG, "Getting ID: %x\n", reg1);
 	apic_write(APIC_ID, reg0);
 	if (reg1 != (reg0 ^ APIC_ID_MASK))
 		return 0;
@@ -213,9 +215,9 @@
 	 * compatibility mode, but most boxes are anymore.
 	 */
 	reg0 = apic_read(APIC_LVT0);
-	Dprintk("Getting LVT0: %x\n", reg0);
+	apic_printk(APIC_DEBUG,"Getting LVT0: %x\n", reg0);
 	reg1 = apic_read(APIC_LVT1);
-	Dprintk("Getting LVT1: %x\n", reg1);
+	apic_printk(APIC_DEBUG, "Getting LVT1: %x\n", reg1);
 
 	return 1;
 }
@@ -227,7 +229,7 @@
 	 */
 	apic_wait_icr_idle();
 
-	Dprintk("Synchronizing Arb IDs.\n");
+	apic_printk(APIC_DEBUG, "Synchronizing Arb IDs.\n");
 	apic_write_around(APIC_ICR, APIC_DEST_ALLINC | APIC_INT_LEVELTRIG
 				| APIC_DM_INIT);
 }
@@ -388,10 +390,10 @@
 	value = apic_read(APIC_LVT0) & APIC_LVT_MASKED;
 	if (!smp_processor_id() && (pic_mode || !value)) {
 		value = APIC_DM_EXTINT;
-		Dprintk(KERN_INFO "enabled ExtINT on CPU#%d\n", smp_processor_id());
+		apic_printk(APIC_VERBOSE, "enabled ExtINT on CPU#%d\n", smp_processor_id());
 	} else {
 		value = APIC_DM_EXTINT | APIC_LVT_MASKED;
-		Dprintk(KERN_INFO "masked ExtINT on CPU#%d\n", smp_processor_id());
+		apic_printk(APIC_VERBOSE, "masked ExtINT on CPU#%d\n", smp_processor_id());
 	}
 	apic_write_around(APIC_LVT0, value);
 
@@ -407,12 +409,11 @@
 	apic_write_around(APIC_LVT1, value);
 
 	if (APIC_INTEGRATED(ver) && !esr_disable) {		/* !82489DX */
+		unsigned oldvalue;
 		maxlvt = get_maxlvt();
 		if (maxlvt > 3)		/* Due to the Pentium erratum 3AP. */
 			apic_write(APIC_ESR, 0);
-		value = apic_read(APIC_ESR);
-		Dprintk("ESR value before enabling vector: %08x\n", value);
-
+		oldvalue = apic_read(APIC_ESR);
 		value = ERROR_APIC_VECTOR;      // enables sending errors
 		apic_write_around(APIC_LVTERR, value);
 		/*
@@ -421,7 +422,10 @@
 		if (maxlvt > 3)
 			apic_write(APIC_ESR, 0);
 		value = apic_read(APIC_ESR);
-		Dprintk("ESR value after enabling vector: %08x\n", value);
+		if (value != oldvalue)
+			apic_printk(APIC_VERBOSE,
+			"ESR value after enabling vector: %08x, after %08x\n",
+			oldvalue, value);
 	} else {
 		if (esr_disable)	
 			/* 
@@ -430,9 +434,9 @@
 			 * ESR disabled - we can't do anything useful with the
 			 * errors anyway - mbligh
 			 */
-			printk("Leaving ESR disabled.\n");
+			apic_printk(APIC_DEBUG, "Leaving ESR disabled.\n");
 		else 
-			printk("No ESR for 82489DX.\n");
+			apic_printk(APIC_DEBUG, "No ESR for 82489DX.\n");
 	}
 
 	nmi_watchdog_default();
@@ -564,6 +568,21 @@
 
 #endif	/* CONFIG_PM */
 
+static int __init apic_set_verbosity(char *str)
+{
+	if (strcmp("debug", str) == 0)
+		apic_verbosity = APIC_DEBUG;
+	else if (strcmp("verbose", str) == 0)
+		apic_verbosity = APIC_VERBOSE;
+	else
+		printk(KERN_WARNING "APIC Verbosity level %s not recognised"
+				" use apic=verbose or apic=debug", str);
+
+	return 0;
+}
+
+__setup("apic=", apic_set_verbosity);
+
 /*
  * Detect and enable local APICs on non-SMP boards.
  * Original code written by Keir Fraser.
@@ -599,7 +618,7 @@
 		apic_phys = mp_lapic_addr;
 
 	set_fixmap_nocache(FIX_APIC_BASE, apic_phys);
-	Dprintk("mapped APIC to %16lx (%16lx)\n", APIC_BASE, apic_phys);
+	apic_printk(APIC_VERBOSE,"mapped APIC to %16lx (%16lx)\n", APIC_BASE, apic_phys);
 
 	/*
 	 * Fetch the APIC ID of the BSP in case we have a
@@ -621,7 +640,7 @@
 				ioapic_phys = __pa(ioapic_phys);
 			}
 			set_fixmap_nocache(idx, ioapic_phys);
-			Dprintk("mapped IOAPIC to %016lx (%016lx)\n",
+			apic_printk(APIC_VERBOSE,"mapped IOAPIC to %016lx (%016lx)\n",
 					__fix_to_virt(idx), ioapic_phys);
 			idx++;
 		}
@@ -836,8 +855,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
@@ -962,7 +980,7 @@
 	   6: Received illegal vector
 	   7: Illegal register address
 	*/
-	printk (KERN_INFO "APIC error on CPU%d: %02x(%02x)\n",
+	printk (KERN_DEBUG "APIC error on CPU%d: %02x(%02x)\n",
 	        smp_processor_id(), v , v1);
 	irq_exit();
 }
diff -Nru a/arch/x86_64/kernel/asm-offsets.c b/arch/x86_64/kernel/asm-offsets.c
--- a/arch/x86_64/kernel/asm-offsets.c	2004-10-18 14:56:32 -07:00
+++ b/arch/x86_64/kernel/asm-offsets.c	2004-10-18 14:56:32 -07:00
@@ -7,8 +7,8 @@
 #include <linux/sched.h> 
 #include <linux/stddef.h>
 #include <linux/errno.h> 
+#include <linux/hardirq.h>
 #include <asm/pda.h>
-#include <asm/hardirq.h>
 #include <asm/processor.h>
 #include <asm/segment.h>
 #include <asm/thread_info.h>
diff -Nru a/arch/x86_64/kernel/cpufreq/Kconfig b/arch/x86_64/kernel/cpufreq/Kconfig
--- a/arch/x86_64/kernel/cpufreq/Kconfig	2004-10-18 14:57:04 -07:00
+++ b/arch/x86_64/kernel/cpufreq/Kconfig	2004-10-18 14:57:04 -07:00
@@ -41,4 +41,58 @@
 
 	  If in doubt, say N.
 
+config X86_POWERNOW_K8_ACPI
+	bool
+	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	2004-10-18 14:56:28 -07:00
+++ b/arch/x86_64/kernel/cpufreq/Makefile	2004-10-18 14:56:28 -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-10-18 14:56:27 -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-10-18 14:56:48 -07:00
+++ b/arch/x86_64/kernel/early_printk.c	2004-10-18 14:56:48 -07:00
@@ -8,7 +8,7 @@
 /* Simple VGA output */
 
 #ifdef __i386__
-#define VGABASE		__pa(__PAGE_OFFSET + 0xb8000UL)
+#define VGABASE		(__ISA_IO_base + 0xb8000)
 #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-10-18 14:56:28 -07:00
+++ b/arch/x86_64/kernel/entry.S	2004-10-18 14:56:28 -07:00
@@ -297,7 +297,7 @@
 	sti
 	SAVE_REST
 	/* Check for syscall exit trace */	
-	testl $(_TIF_SYSCALL_TRACE|_TIF_SYSCALL_AUDIT),%edx
+	testl $(_TIF_SYSCALL_TRACE|_TIF_SYSCALL_AUDIT|_TIF_SINGLESTEP),%edx
 	jz int_signal
 	pushq %rdi
 	leaq 8(%rsp),%rdi	# &ptregs -> arg1	
@@ -305,6 +305,7 @@
 	popq %rdi
 	btr  $TIF_SYSCALL_TRACE,%edi
 	btr  $TIF_SYSCALL_AUDIT,%edi
+	btr  $TIF_SINGLESTEP,%edi
 	jmp int_restore_rest
 	
 int_signal:
@@ -323,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
@@ -385,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/i8259.c b/arch/x86_64/kernel/i8259.c
--- a/arch/x86_64/kernel/i8259.c	2004-10-18 14:56:13 -07:00
+++ b/arch/x86_64/kernel/i8259.c	2004-10-18 14:56:13 -07:00
@@ -329,7 +329,7 @@
 		 * lets ACK and report it. [once per IRQ]
 		 */
 		if (!(spurious_irq_mask & irqmask)) {
-			printk("spurious 8259A interrupt: IRQ%d.\n", irq);
+			printk(KERN_DEBUG "spurious 8259A interrupt: IRQ%d.\n", irq);
 			spurious_irq_mask |= irqmask;
 		}
 		atomic_inc(&irq_err_count);
@@ -342,7 +342,7 @@
 	}
 }
 
-void __init init_8259A(int auto_eoi)
+void init_8259A(int auto_eoi)
 {
 	unsigned long flags;
 
@@ -384,6 +384,57 @@
 
 	spin_unlock_irqrestore(&i8259A_lock, flags);
 }
+
+static char irq_trigger[2];
+/**
+ * ELCR registers (0x4d0, 0x4d1) control edge/level of IRQ
+ */
+static void restore_ELCR(char *trigger)
+{
+	outb(trigger[0], 0x4d0);
+	outb(trigger[1], 0x4d1);
+}
+
+static void save_ELCR(char *trigger)
+{
+	/* IRQ 0,1,2,8,13 are marked as reserved */
+	trigger[0] = inb(0x4d0) & 0xF8;
+	trigger[1] = inb(0x4d1) & 0xDE;
+}
+
+static int i8259A_resume(struct sys_device *dev)
+{
+	init_8259A(0);
+	restore_ELCR(irq_trigger);
+	return 0;
+}
+
+static int i8259A_suspend(struct sys_device *dev, u32 state)
+{
+	save_ELCR(irq_trigger);
+	return 0;
+}
+
+static struct sysdev_class i8259_sysdev_class = {
+	set_kset_name("i8259"),
+	.suspend = i8259A_suspend,
+	.resume = i8259A_resume,
+};
+
+static struct sys_device device_i8259A = {
+	.id	= 0,
+	.cls	= &i8259_sysdev_class,
+};
+
+static int __init i8259A_init_sysfs(void)
+{
+	int error = sysdev_class_register(&i8259_sysdev_class);
+	if (!error)
+		error = sysdev_register(&device_i8259A);
+	return error;
+}
+
+device_initcall(i8259A_init_sysfs);
 
 /*
  * IRQ2 is cascade interrupt to second interrupt controller
diff -Nru a/arch/x86_64/kernel/init_task.c b/arch/x86_64/kernel/init_task.c
--- a/arch/x86_64/kernel/init_task.c	2004-10-18 14:56:32 -07:00
+++ b/arch/x86_64/kernel/init_task.c	2004-10-18 14:56:32 -07:00
@@ -44,8 +44,7 @@
  * section. Since TSS's are completely CPU-local, we want them
  * on exact cacheline boundaries, to eliminate cacheline ping-pong.
  */ 
-struct tss_struct init_tss[NR_CPUS] __cacheline_aligned;
-
+DEFINE_PER_CPU(struct tss_struct, init_tss) ____cacheline_maxaligned_in_smp;
 
 #define ALIGN_TO_4K __attribute__((section(".data.init_task")))
 
diff -Nru a/arch/x86_64/kernel/io_apic.c b/arch/x86_64/kernel/io_apic.c
--- a/arch/x86_64/kernel/io_apic.c	2004-10-18 14:56:32 -07:00
+++ b/arch/x86_64/kernel/io_apic.c	2004-10-18 14:56:32 -07:00
@@ -30,12 +30,15 @@
 #include <linux/smp_lock.h>
 #include <linux/mc146818rtc.h>
 #include <linux/acpi.h>
+#include <linux/sysdev.h>
 
 #include <asm/io.h>
 #include <asm/smp.h>
 #include <asm/desc.h>
 #include <asm/proto.h>
 
+#define __apicdebuginit  __init
+
 int sis_apic_bug; /* not actually supported, dummy for compile */
 
 #undef APIC_LOCKUP_DEBUG
@@ -292,13 +295,13 @@
 		pirq_entries[i] = -1;
 
 	pirqs_enabled = 1;
-	printk(KERN_INFO "PIRQ redirection, working around broken MP-BIOS.\n");
+	apic_printk(APIC_VERBOSE, "PIRQ redirection, working around broken MP-BIOS.\n");
 	max = MAX_PIRQS;
 	if (ints[0] < MAX_PIRQS)
 		max = ints[0];
 
 	for (i = 0; i < max; i++) {
-		printk(KERN_DEBUG "... PIRQ%d -> IRQ %d\n", i, ints[i+1]);
+		apic_printk(APIC_VERBOSE, "... PIRQ%d -> IRQ %d\n", i, ints[i+1]);
 		/*
 		 * PIRQs are mapped upside down, usually.
 		 */
@@ -357,10 +360,10 @@
 {
 	int apic, i, best_guess = -1;
 
-	Dprintk("querying PCI -> IRQ mapping bus:%d, slot:%d, pin:%d.\n",
+	apic_printk(APIC_DEBUG, "querying PCI -> IRQ mapping bus:%d, slot:%d, pin:%d.\n",
 		bus, slot, pin);
 	if (mp_bus_id_to_pci_bus[bus] == -1) {
-		printk(KERN_WARNING "PCI BIOS passed nonexistent PCI bus %d!\n", bus);
+		apic_printk(APIC_VERBOSE, "PCI BIOS passed nonexistent PCI bus %d!\n", bus);
 		return -1;
 	}
 	for (i = 0; i < mp_irq_entries; i++) {
@@ -402,7 +405,7 @@
 		unsigned int port = 0x4d0 + (irq >> 3);
 		return (inb(port) >> (irq & 7)) & 1;
 	}
-	printk(KERN_INFO "Broken MPtable reports ISA irq %d\n", irq);
+	apic_printk(APIC_VERBOSE, "Broken MPtable reports ISA irq %d\n", irq);
 	return 0;
 }
 
@@ -625,10 +628,10 @@
 	if ((pin >= 16) && (pin <= 23)) {
 		if (pirq_entries[pin-16] != -1) {
 			if (!pirq_entries[pin-16]) {
-				printk(KERN_DEBUG "disabling PIRQ%d\n", pin-16);
+				apic_printk(APIC_VERBOSE, "disabling PIRQ%d\n", pin-16);
 			} else {
 				irq = pirq_entries[pin-16];
-				printk(KERN_DEBUG "using PIRQ%d -> IRQ %d\n",
+				apic_printk(APIC_VERBOSE, "using PIRQ%d -> IRQ %d\n",
 						pin-16, irq);
 			}
 		}
@@ -719,7 +722,7 @@
 	int apic, pin, idx, irq, first_notcon = 1, vector;
 	unsigned long flags;
 
-	printk(KERN_DEBUG "init IO_APIC IRQs\n");
+	apic_printk(APIC_VERBOSE, KERN_DEBUG "init IO_APIC IRQs\n");
 
 	for (apic = 0; apic < nr_ioapics; apic++) {
 	for (pin = 0; pin < nr_ioapic_registers[apic]; pin++) {
@@ -732,15 +735,15 @@
 		entry.delivery_mode = dest_LowestPrio;
 		entry.dest_mode = INT_DELIVERY_MODE;
 		entry.mask = 0;				/* enable IRQ */
-		entry.dest.logical.logical_dest = TARGET_CPUS;
+		entry.dest.logical.logical_dest = cpu_mask_to_apicid(TARGET_CPUS);
 
 		idx = find_irq_entry(apic,pin,mp_INT);
 		if (idx == -1) {
 			if (first_notcon) {
-				printk(KERN_DEBUG " IO-APIC (apicid-pin) %d-%d", mp_ioapics[apic].mpc_apicid, pin);
+				apic_printk(APIC_VERBOSE, KERN_DEBUG " IO-APIC (apicid-pin) %d-%d", mp_ioapics[apic].mpc_apicid, pin);
 				first_notcon = 0;
 			} else
-				printk(", %d-%d", mp_ioapics[apic].mpc_apicid, pin);
+				apic_printk(APIC_VERBOSE, ", %d-%d", mp_ioapics[apic].mpc_apicid, pin);
 			continue;
 		}
 
@@ -750,7 +753,7 @@
 		if (irq_trigger(idx)) {
 			entry.trigger = 1;
 			entry.mask = 1;
-			entry.dest.logical.logical_dest = TARGET_CPUS;
+			entry.dest.logical.logical_dest = cpu_mask_to_apicid(TARGET_CPUS);
 		}
 
 		irq = pin_2_irq(idx, apic, pin);
@@ -775,7 +778,7 @@
 	}
 
 	if (!first_notcon)
-		printk(" not connected.\n");
+		apic_printk(APIC_VERBOSE," not connected.\n");
 }
 
 /*
@@ -800,7 +803,7 @@
 	 */
 	entry.dest_mode = INT_DELIVERY_MODE;
 	entry.mask = 0;					/* unmask IRQ now */
-	entry.dest.logical.logical_dest = TARGET_CPUS;
+	entry.dest.logical.logical_dest = cpu_mask_to_apicid(TARGET_CPUS);
 	entry.delivery_mode = dest_LowestPrio;
 	entry.polarity = 0;
 	entry.trigger = 0;
@@ -825,13 +828,9 @@
 
 void __init UNEXPECTED_IO_APIC(void)
 {
-#if 0
-	printk(KERN_WARNING " WARNING: unexpected IO-APIC, please mail\n");
-	printk(KERN_WARNING "          to linux-smp@vger.kernel.org\n");
-#endif
 }
 
-void __init print_IO_APIC(void)
+void __apicdebuginit print_IO_APIC(void)
 {
 	int apic, i;
 	union IO_APIC_reg_00 reg_00;
@@ -839,7 +838,10 @@
 	union IO_APIC_reg_02 reg_02;
 	unsigned long flags;
 
- 	printk(KERN_DEBUG "number of MP IRQ sources: %d.\n", mp_irq_entries);
+	if (apic_verbosity == APIC_QUIET)
+		return;
+
+	printk(KERN_DEBUG "number of MP IRQ sources: %d.\n", mp_irq_entries);
 	for (i = 0; i < nr_ioapics; i++)
 		printk(KERN_DEBUG "number of IO-APIC #%d registers: %d.\n",
 		       mp_ioapics[i].mpc_apicid, nr_ioapic_registers[i]);
@@ -955,11 +957,14 @@
 	return;
 }
 
-static void print_APIC_bitfield (int base)
+static __apicdebuginit void print_APIC_bitfield (int base)
 {
 	unsigned int v;
 	int i, j;
 
+	if (apic_verbosity == APIC_QUIET)
+		return;
+
 	printk(KERN_DEBUG "0123456789abcdef0123456789abcdef\n" KERN_DEBUG);
 	for (i = 0; i < 8; i++) {
 		v = apic_read(base + i*0x10);
@@ -973,10 +978,13 @@
 	}
 }
 
-void /*__init*/ print_local_APIC(void * dummy)
+void __apicdebuginit print_local_APIC(void * dummy)
 {
 	unsigned int v, ver, maxlvt;
 
+	if (apic_verbosity == APIC_QUIET)
+		return;
+
 	printk("\n" KERN_DEBUG "printing local APIC contents on CPU#%d/%d:\n",
 		smp_processor_id(), hard_smp_processor_id());
 	v = apic_read(APIC_ID);
@@ -1058,12 +1066,15 @@
 	on_each_cpu(print_local_APIC, NULL, 1, 1);
 }
 
-void /*__init*/ print_PIC(void)
+void __apicdebuginit print_PIC(void)
 {
 	extern spinlock_t i8259A_lock;
 	unsigned int v;
 	unsigned long flags;
 
+	if (apic_verbosity == APIC_QUIET)
+		return;
+
 	printk(KERN_DEBUG "\nprinting PIC contents\n");
 
 	spin_lock_irqsave(&i8259A_lock, flags);
@@ -1160,9 +1171,9 @@
 		old_id = mp_ioapics[apic].mpc_apicid;
 
 		if (mp_ioapics[apic].mpc_apicid >= 0xf) {
-			printk(KERN_ERR "BIOS bug, IO-APIC#%d ID is %d in the MPC table!...\n",
+			apic_printk(APIC_QUIET,KERN_ERR "BIOS bug, IO-APIC#%d ID is %d in the MPC table!...\n",
 				apic, mp_ioapics[apic].mpc_apicid);
-			printk(KERN_ERR "... fixing up to %d. (tell your hw vendor)\n",
+			apic_printk(APIC_QUIET,KERN_ERR "... fixing up to %d. (tell your hw vendor)\n",
 				reg_00.bits.ID);
 			mp_ioapics[apic].mpc_apicid = reg_00.bits.ID;
 		}
@@ -1205,7 +1216,7 @@
 		 * Read the right value from the MPC table and
 		 * write it into the ID register.
 	 	 */
-		printk(KERN_INFO "...changing IO-APIC physical APIC ID to %d ...",
+		apic_printk(APIC_VERBOSE,KERN_INFO "...changing IO-APIC physical APIC ID to %d ...",
 				mp_ioapics[apic].mpc_apicid);
 
 		reg_00.bits.ID = mp_ioapics[apic].mpc_apicid;
@@ -1220,9 +1231,9 @@
 		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
-			printk(" ok.\n");
+			apic_printk(APIC_VERBOSE," ok.\n");
 	}
 }
 
@@ -1671,7 +1682,7 @@
 	pin1 = find_isa_irq_pin(0, mp_INT);
 	pin2 = find_isa_irq_pin(0, mp_ExtINT);
 
-	printk(KERN_INFO "..TIMER: vector=0x%02X pin1=%d pin2=%d\n", vector, pin1, pin2);
+	apic_printk(APIC_VERBOSE,KERN_INFO "..TIMER: vector=0x%02X pin1=%d pin2=%d\n", vector, pin1, pin2);
 
 	if (pin1 != -1) {
 		/*
@@ -1689,12 +1700,12 @@
 			return;
 		}
 		clear_IO_APIC_pin(0, pin1);
-		printk(KERN_ERR "..MP-BIOS bug: 8254 timer not connected to IO-APIC\n");
+		apic_printk(APIC_QUIET,KERN_ERR "..MP-BIOS bug: 8254 timer not connected to IO-APIC\n");
 	}
 
-	printk(KERN_INFO "...trying to set up timer (IRQ0) through the 8259A ... ");
+	apic_printk(APIC_VERBOSE,KERN_INFO "...trying to set up timer (IRQ0) through the 8259A ... ");
 	if (pin2 != -1) {
-		printk("\n..... (found pin %d) ...", pin2);
+		apic_printk(APIC_VERBOSE,"\n..... (found pin %d) ...", pin2);
 		/*
 		 * legacy devices should be connected to IO APIC #0
 		 */
@@ -1720,7 +1731,7 @@
 		nmi_watchdog = 0;
 	}
 
-	printk(KERN_INFO "...trying to set up timer as Virtual Wire IRQ...");
+	apic_printk(APIC_VERBOSE, KERN_INFO "...trying to set up timer as Virtual Wire IRQ...");
 
 	disable_8259A_irq(0);
 	irq_desc[0].handler = &lapic_irq_type;
@@ -1728,13 +1739,13 @@
 	enable_8259A_irq(0);
 
 	if (timer_irq_works()) {
-		printk(" works.\n");
+		apic_printk(APIC_QUIET, " works.\n");
 		return;
 	}
 	apic_write_around(APIC_LVT0, APIC_LVT_MASKED | APIC_DM_FIXED | vector);
-	printk(" failed.\n");
+	apic_printk(APIC_VERBOSE," failed.\n");
 
-	printk(KERN_INFO "...trying to set up timer as ExtINT IRQ...");
+	apic_printk(APIC_VERBOSE, KERN_INFO "...trying to set up timer as ExtINT IRQ...");
 
 	init_8259A(0);
 	make_8259A_irq(0);
@@ -1743,10 +1754,10 @@
 	unlock_ExtINT_logic();
 
 	if (timer_irq_works()) {
-		printk(" works.\n");
+		apic_printk(APIC_VERBOSE," works.\n");
 		return;
 	}
-	printk(" failed :(.\n");
+	apic_printk(APIC_VERBOSE," failed :(.\n");
 	panic("IO-APIC + timer doesn't work! Try using the 'noapic' kernel parameter\n");
 }
 
@@ -1768,7 +1779,7 @@
 	else
 		io_apic_irqs = ~PIC_IRQS;
 
-	printk("ENABLING IO-APIC IRQs\n");
+	apic_printk(APIC_VERBOSE, "ENABLING IO-APIC IRQs\n");
 
 	/*
 	 * Set up the IO-APIC IRQ routing table.
@@ -1783,6 +1794,98 @@
 		print_IO_APIC();
 }
 
+struct sysfs_ioapic_data {
+	struct sys_device dev;
+	struct IO_APIC_route_entry entry[0];
+};
+static struct sysfs_ioapic_data * mp_ioapic_data[MAX_IO_APICS];
+
+static int ioapic_suspend(struct sys_device *dev, u32 state)
+{
+	struct IO_APIC_route_entry *entry;
+	struct sysfs_ioapic_data *data;
+	unsigned long flags;
+	int i;
+
+	data = container_of(dev, struct sysfs_ioapic_data, dev);
+	entry = data->entry;
+	spin_lock_irqsave(&ioapic_lock, flags);
+	for (i = 0; i < nr_ioapic_registers[dev->id]; i ++, entry ++ ) {
+		*(((int *)entry) + 1) = io_apic_read(dev->id, 0x11 + 2 * i);
+		*(((int *)entry) + 0) = io_apic_read(dev->id, 0x10 + 2 * i);
+	}
+	spin_unlock_irqrestore(&ioapic_lock, flags);
+
+	return 0;
+}
+
+static int ioapic_resume(struct sys_device *dev)
+{
+	struct IO_APIC_route_entry *entry;
+	struct sysfs_ioapic_data *data;
+	unsigned long flags;
+	union IO_APIC_reg_00 reg_00;
+	int i;
+
+	data = container_of(dev, struct sysfs_ioapic_data, dev);
+	entry = data->entry;
+
+	spin_lock_irqsave(&ioapic_lock, flags);
+	reg_00.raw = io_apic_read(dev->id, 0);
+	if (reg_00.bits.ID != mp_ioapics[dev->id].mpc_apicid) {
+		reg_00.bits.ID = mp_ioapics[dev->id].mpc_apicid;
+		io_apic_write(dev->id, 0, reg_00.raw);
+	}
+	for (i = 0; i < nr_ioapic_registers[dev->id]; i ++, entry ++ ) {
+		io_apic_write(dev->id, 0x11+2*i, *(((int *)entry)+1));
+		io_apic_write(dev->id, 0x10+2*i, *(((int *)entry)+0));
+	}
+	spin_unlock_irqrestore(&ioapic_lock, flags);
+
+	return 0;
+}
+
+static struct sysdev_class ioapic_sysdev_class = {
+	set_kset_name("ioapic"),
+	.suspend = ioapic_suspend,
+	.resume = ioapic_resume,
+};
+
+static int __init ioapic_init_sysfs(void)
+{
+	struct sys_device * dev;
+	int i, size, error = 0;
+
+	error = sysdev_class_register(&ioapic_sysdev_class);
+	if (error)
+		return error;
+
+	for (i = 0; i < nr_ioapics; i++ ) {
+		size = sizeof(struct sys_device) + nr_ioapic_registers[i]
+			* sizeof(struct IO_APIC_route_entry);
+		mp_ioapic_data[i] = kmalloc(size, GFP_KERNEL);
+		if (!mp_ioapic_data[i]) {
+			printk(KERN_ERR "Can't suspend/resume IOAPIC %d\n", i);
+			continue;
+		}
+		memset(mp_ioapic_data[i], 0, size);
+		dev = &mp_ioapic_data[i]->dev;
+		dev->id = i;
+		dev->cls = &ioapic_sysdev_class;
+		error = sysdev_register(dev);
+		if (error) {
+			kfree(mp_ioapic_data[i]);
+			mp_ioapic_data[i] = NULL;
+			printk(KERN_ERR "Can't suspend/resume IOAPIC %d\n", i);
+			continue;
+		}
+	}
+
+	return 0;
+}
+
+device_initcall(ioapic_init_sysfs);
+
 /* --------------------------------------------------------------------------
                           ACPI-based IOAPIC Configuration
    -------------------------------------------------------------------------- */
@@ -1815,7 +1918,7 @@
 	spin_unlock_irqrestore(&ioapic_lock, flags);
 
 	if (apic_id >= IO_APIC_MAX_ID) {
-		printk(KERN_WARNING "IOAPIC[%d]: Invalid apic_id %d, trying "
+		apic_printk(APIC_QUIET, KERN_WARNING "IOAPIC[%d]: Invalid apic_id %d, trying "
 			"%d\n", ioapic, apic_id, reg_00.bits.ID);
 		apic_id = reg_00.bits.ID;
 	}
@@ -1834,7 +1937,7 @@
 		if (i == IO_APIC_MAX_ID)
 			panic("Max apic_id exceeded!\n");
 
-		printk(KERN_WARNING "IOAPIC[%d]: apic_id %d already used, "
+		apic_printk(APIC_VERBOSE, KERN_WARNING "IOAPIC[%d]: apic_id %d already used, "
 			"trying %d\n", ioapic, apic_id, i);
 
 		apic_id = i;
@@ -1855,7 +1958,7 @@
 			panic("IOAPIC[%d]: Unable change apic_id!\n", ioapic);
 	}
 
-	printk(KERN_INFO "IOAPIC[%d]: Assigned apic_id %d\n", ioapic, apic_id);
+	apic_printk(APIC_VERBOSE,KERN_INFO "IOAPIC[%d]: Assigned apic_id %d\n", ioapic, apic_id);
 
 	return apic_id;
 }
@@ -1893,7 +1996,7 @@
 	unsigned long flags;
 
 	if (!IO_APIC_IRQ(irq)) {
-		printk(KERN_ERR "IOAPIC[%d]: Invalid reference to IRQ 0\n",
+		apic_printk(APIC_QUIET,KERN_ERR "IOAPIC[%d]: Invalid reference to IRQ 0\n",
 			ioapic);
 		return -EINVAL;
 	}
@@ -1908,7 +2011,7 @@
 
 	entry.delivery_mode = dest_LowestPrio;
 	entry.dest_mode = INT_DELIVERY_MODE;
-	entry.dest.logical.logical_dest = TARGET_CPUS;
+	entry.dest.logical.logical_dest = cpu_mask_to_apicid(TARGET_CPUS);
 	entry.trigger = edge_level;
 	entry.polarity = active_high_low;
 	entry.mask = 1;					 /* Disabled (masked) */
@@ -1921,20 +2024,12 @@
 
 	entry.vector = assign_irq_vector(irq);
 
-	printk(KERN_DEBUG "IOAPIC[%d]: Set PCI routing entry (%d-%d -> 0x%x -> "
+	apic_printk(APIC_VERBOSE,KERN_DEBUG "IOAPIC[%d]: Set PCI routing entry (%d-%d -> 0x%x -> "
 		"IRQ %d Mode:%i Active:%i)\n", ioapic, 
 	       mp_ioapics[ioapic].mpc_apicid, pin, entry.vector, irq,
 	       edge_level, active_high_low);
 
- 	if (use_pci_vector() && !platform_legacy_irq(irq))
-		irq = IO_APIC_VECTOR(irq);
-	if (edge_level) {
-		irq_desc[irq].handler = &ioapic_level_type;
-	} else {
-		irq_desc[irq].handler = &ioapic_edge_type;
-	}
-
-	set_intr_gate(entry.vector, interrupt[irq]);
+	ioapic_register_intr(irq, entry.vector, edge_level);
 
 	if (!ioapic && (irq < 16))
 		disable_8259A_irq(irq);
@@ -1966,3 +2061,28 @@
 	apic_write_around(APIC_ICR, cfg);
 }
 #endif
+
+
+/*
+ * This function currently is only a helper for the i386 smp boot process where
+ * we need to reprogram the ioredtbls to cater for the cpus which have come online
+ * so mask in all cases should simply be TARGET_CPUS
+ */
+void __init setup_ioapic_dest(void)
+{
+	int pin, ioapic, irq, irq_entry;
+
+	if (skip_ioapic_setup == 1)
+		return;
+
+	for (ioapic = 0; ioapic < nr_ioapics; ioapic++) {
+		for (pin = 0; pin < nr_ioapic_registers[ioapic]; pin++) {
+			irq_entry = find_irq_entry(ioapic, pin, mp_INT);
+			if (irq_entry == -1)
+				continue;
+			irq = pin_2_irq(irq_entry, ioapic, pin);
+			set_ioapic_affinity_irq(irq, TARGET_CPUS);
+		}
+
+	}
+}
diff -Nru a/arch/x86_64/kernel/ioport.c b/arch/x86_64/kernel/ioport.c
--- a/arch/x86_64/kernel/ioport.c	2004-10-18 14:56:20 -07:00
+++ b/arch/x86_64/kernel/ioport.c	2004-10-18 14:56:20 -07:00
@@ -28,12 +28,12 @@
 			clear_bit(i, bitmap); 
 }
 
-
 /*
  * this changes the io permissions bitmap in the current task.
  */
 asmlinkage long sys_ioperm(unsigned long from, unsigned long num, int turn_on)
 {
+	unsigned int i, max_long, bytes, bytes_updated;
 	struct thread_struct * t = &current->thread;
 	struct tss_struct * tss;
 	unsigned long *bitmap;
@@ -59,16 +59,34 @@
 
 	/*
 	 * do it in the per-thread copy and in the TSS ...
+	 *
+	 * Disable preemption via get_cpu() - we must not switch away
+	 * because the ->io_bitmap_max value must match the bitmap
+	 * contents:
 	 */
+	tss = &per_cpu(init_tss, get_cpu());
+
 	set_bitmap(t->io_bitmap_ptr, from, num, !turn_on);
-	tss = init_tss + get_cpu();
-	if (tss->io_bitmap_base == IO_BITMAP_OFFSET) { /* already active? */
-		set_bitmap(tss->io_bitmap, from, num, !turn_on);
-	} else {
-		memcpy(tss->io_bitmap, t->io_bitmap_ptr, IO_BITMAP_BYTES);
-		tss->io_bitmap_base = IO_BITMAP_OFFSET; /* Activate it in the TSS */
-	}
+
+	/*
+	 * Search for a (possibly new) maximum. This is simple and stupid,
+	 * to keep it obviously correct:
+	 */
+	max_long = 0;
+	for (i = 0; i < IO_BITMAP_LONGS; i++)
+		if (t->io_bitmap_ptr[i] != ~0UL)
+			max_long = i;
+
+	bytes = (max_long + 1) * sizeof(long);
+	bytes_updated = max(bytes, t->io_bitmap_max);
+
+	t->io_bitmap_max = bytes;
+
+	/* Update the TSS: */
+	memcpy(tss->io_bitmap, t->io_bitmap_ptr, bytes_updated);
+
 	put_cpu();
+
 	return 0;
 }
 
@@ -83,9 +101,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 +112,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-10-18 14:56:29 -07:00
+++ b/arch/x86_64/kernel/irq.c	2004-10-18 14:56:29 -07:00
@@ -213,13 +213,15 @@
 int handle_IRQ_event(unsigned int irq, struct pt_regs * regs, struct irqaction * action)
 {
 	int status = 1; /* Force the "do bottom halves" bit */
+	int ret;
 
 	if (!(action->flags & SA_INTERRUPT))
 		local_irq_enable();
 
 	do {
-		status |= action->flags;
-		action->handler(irq, action->dev_id, regs);
+		ret = action->handler(irq, action->dev_id, regs);
+		if (ret == IRQ_HANDLED)
+			status |= action->flags;
 		action = action->next;
 	} while (action);
 	if (status & SA_SAMPLE_RANDOM)
@@ -862,31 +864,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 +899,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 +915,3 @@
 	for (i = 0; i < NR_IRQS; i++)
 		register_irq_proc(i);
 }
-
diff -Nru a/arch/x86_64/kernel/ldt.c b/arch/x86_64/kernel/ldt.c
--- a/arch/x86_64/kernel/ldt.c	2004-10-18 14:57:03 -07:00
+++ b/arch/x86_64/kernel/ldt.c	2004-10-18 14:57:03 -07:00
@@ -135,6 +135,7 @@
 		return 0;
 	if (bytecount > LDT_ENTRY_SIZE*LDT_ENTRIES)
 		bytecount = LDT_ENTRY_SIZE*LDT_ENTRIES;
+
 	down(&mm->context.sem);
 	size = mm->context.size*LDT_ENTRY_SIZE;
 	if (size > bytecount)
@@ -145,12 +146,17 @@
 		err = -EFAULT;
 	up(&mm->context.sem);
 	if (err < 0)
-	return err;
+		goto error_return;
 	if (size != bytecount) {
 		/* zero-fill the rest */
-		clear_user(ptr+size, bytecount-size);
+		if (clear_user(ptr+size, bytecount-size) != 0) {
+			err = -EFAULT;
+			goto error_return;
+		}
 	}
 	return bytecount;
+error_return:
+	return err;
 }
 
 static int read_default_ldt(void __user * ptr, unsigned long bytecount)
diff -Nru a/arch/x86_64/kernel/mce.c b/arch/x86_64/kernel/mce.c
--- a/arch/x86_64/kernel/mce.c	2004-10-18 14:56:27 -07:00
+++ b/arch/x86_64/kernel/mce.c	2004-10-18 14:56:27 -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;
@@ -48,8 +49,7 @@
 	mce->finished = 0;
 	smp_wmb();
 	for (;;) {
-		entry = mcelog.next;
-		read_barrier_depends();
+		entry = rcu_dereference(mcelog.next);
 		/* When the buffer fills up discard new entries. Assume 
 		   that the earlier errors are the more interesting. */
 		if (entry >= MCE_LOG_LEN) {
@@ -72,7 +72,8 @@
 
 static void print_mce(struct mce *m)
 {
-	printk(KERN_EMERG 
+	printk(KERN_EMERG "\n"
+	       KERN_EMERG
 	       "CPU %d: Machine Check Exception: %16Lx Bank %d: %016Lx\n",
 	       m->cpu, m->mcgstatus, m->bank, m->status);
 	if (m->rip) {
@@ -101,7 +102,7 @@
 		if (time_before(tsc, start))
 			continue;
 		print_mce(&mcelog.entry[i]); 
-		if (mcelog.entry[i].tsc == backup->tsc)
+		if (backup && mcelog.entry[i].tsc == backup->tsc)
 			backup = NULL;
 	}
 	if (backup)
@@ -114,9 +115,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);
 }
 
 /* 
@@ -128,8 +128,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);
@@ -139,17 +140,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])
@@ -157,52 +152,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 
@@ -215,18 +220,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);
 }
 
@@ -269,22 +271,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 */
@@ -308,7 +313,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);
@@ -333,9 +340,8 @@
 	int i, err;
 
 	down(&mce_read_sem); 
-	next = mcelog.next;
-	read_barrier_depends();
-		
+	next = rcu_dereference(mcelog.next);
+
 	/* Only supports full reads right now */
 	if (*off != 0 || usize < MCE_LOG_LEN*sizeof(struct mce)) { 
 		up(&mce_read_sem);
@@ -412,15 +418,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;
@@ -436,7 +443,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;
 }
@@ -465,7 +471,7 @@
 /* Why are there no generic functions for this? */
 #define ACCESSOR(name, var, start) \
 	static ssize_t show_ ## name(struct sys_device *s, char *buf) { 	   	   \
-		return sprintf(buf, "%lu\n", (unsigned long)var);		   \
+		return sprintf(buf, "%lx\n", (unsigned long)var);		   \
 	} 									   \
 	static ssize_t set_ ## name(struct sys_device *s,const char *buf,size_t siz) { \
 		char *end; 							   \
@@ -494,7 +500,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-10-18 14:56:15 -07:00
+++ b/arch/x86_64/kernel/msr.c	2004-10-18 14:56:15 -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/nmi.c b/arch/x86_64/kernel/nmi.c
--- a/arch/x86_64/kernel/nmi.c	2004-10-18 14:56:29 -07:00
+++ b/arch/x86_64/kernel/nmi.c	2004-10-18 14:56:29 -07:00
@@ -390,7 +390,8 @@
 		 */
 		alert_counter[cpu]++;
 		if (alert_counter[cpu] == 5*nmi_hz) {
-			if (notify_die(DIE_NMI, "nmi", regs, reason, 2, SIGINT) == NOTIFY_BAD) { 
+			if (notify_die(DIE_NMI, "nmi", regs, reason, 2, SIGINT)
+							== NOTIFY_STOP) {
 				alert_counter[cpu] = 0; 
 				return;
 			} 
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-10-18 14:57:03 -07:00
+++ b/arch/x86_64/kernel/pci-dma.c	2004-10-18 14:57:03 -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-10-18 14:56:29 -07:00
+++ b/arch/x86_64/kernel/pci-gart.c	2004-10-18 14:56:29 -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-10-18 14:57:19 -07:00
+++ b/arch/x86_64/kernel/pci-nommu.c	2004-10-18 14:57:19 -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-10-18 14:56:32 -07:00
+++ b/arch/x86_64/kernel/process.c	2004-10-18 14:56:32 -07:00
@@ -130,11 +130,20 @@
 {
 	/* endless idle loop with no priority at all */
 	while (1) {
-		void (*idle)(void) = pm_idle;
-		if (!idle)
-			idle = default_idle;
-		while (!need_resched())
+		while (!need_resched()) {
+			void (*idle)(void);
+			/*
+			 * Mark this as an RCU critical section so that
+			 * synchronize_kernel() in the unload path waits
+			 * for our completion.
+			 */
+			rcu_read_lock();
+			idle = pm_idle;
+			if (!idle)
+				idle = default_idle;
 			idle();
+			rcu_read_unlock();
+		}
 		schedule();
 	}
 }
@@ -168,9 +177,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 +186,7 @@
 			}
 			pm_idle = mwait_idle;
 		}
-		return;
 	}
-	pm_idle = default_idle;
-	return;
 }
 
 static int __init idle_setup (char *str)
@@ -255,11 +259,17 @@
 void exit_thread(void)
 {
 	struct task_struct *me = current;
+	struct thread_struct *t = &me->thread;
 	if (me->thread.io_bitmap_ptr) { 
-		struct tss_struct *tss = init_tss + get_cpu();
-		kfree(me->thread.io_bitmap_ptr); 
-		me->thread.io_bitmap_ptr = NULL;
-		tss->io_bitmap_base = INVALID_IO_BITMAP_OFFSET;
+		struct tss_struct *tss = &per_cpu(init_tss, get_cpu());
+
+		kfree(t->io_bitmap_ptr);
+		t->io_bitmap_ptr = NULL;
+		/*
+		 * Careful, clear this in the TSS too:
+		 */
+		memset(tss->io_bitmap, 0xff, t->io_bitmap_max);
+		t->io_bitmap_max = 0;
 		put_cpu();
 	}
 }
@@ -367,8 +377,10 @@
 
 	if (unlikely(me->thread.io_bitmap_ptr != NULL)) { 
 		p->thread.io_bitmap_ptr = kmalloc(IO_BITMAP_BYTES, GFP_KERNEL);
-		if (!p->thread.io_bitmap_ptr) 
+		if (!p->thread.io_bitmap_ptr) {
+			p->thread.io_bitmap_max = 0;
 			return -ENOMEM;
+		}
 		memcpy(p->thread.io_bitmap_ptr, me->thread.io_bitmap_ptr, IO_BITMAP_BYTES);
 	} 
 
@@ -387,8 +399,10 @@
 	}
 	err = 0;
 out:
-	if (err && p->thread.io_bitmap_ptr)
+	if (err && p->thread.io_bitmap_ptr) {
 		kfree(p->thread.io_bitmap_ptr);
+		p->thread.io_bitmap_max = 0;
+	}
 	return err;
 }
 
@@ -409,7 +423,7 @@
 	struct thread_struct *prev = &prev_p->thread,
 				 *next = &next_p->thread;
 	int cpu = smp_processor_id();  
-	struct tss_struct *tss = init_tss + cpu;
+	struct tss_struct *tss = &per_cpu(init_tss, cpu);
 
 	unlazy_fpu(prev_p);
 
@@ -495,22 +509,18 @@
 	 * Handle the IO bitmap 
 	 */ 
 	if (unlikely(prev->io_bitmap_ptr || next->io_bitmap_ptr)) {
-		if (next->io_bitmap_ptr) {
+		if (next->io_bitmap_ptr)
 			/*
-			 * 2 cachelines copy ... not good, but not that
-			 * bad either. Anyone got something better?
-			 * This only affects processes which use ioperm().
-			 */
-			memcpy(tss->io_bitmap, next->io_bitmap_ptr, IO_BITMAP_BYTES);
-			tss->io_bitmap_base = IO_BITMAP_OFFSET;
-		} else {
+			 * Copy the relevant range of the IO bitmap.
+			 * Normally this is 128 bytes or less:
+ 			 */
+			memcpy(tss->io_bitmap, next->io_bitmap_ptr,
+				max(prev->io_bitmap_max, next->io_bitmap_max));
+		else {
 			/*
-			 * a bitmap offset pointing outside of the TSS limit
-			 * causes a nicely controllable SIGSEGV if a process
-			 * tries to use a port IO instruction. The first
-			 * sys_ioperm() call sets up the bitmap properly.
+			 * Clear any possible leftover bits:
 			 */
-			tss->io_bitmap_base = INVALID_IO_BITMAP_OFFSET;
+			memset(tss->io_bitmap, 0xff, prev->io_bitmap_max);
 		}
 	}
 
@@ -546,17 +556,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 +578,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-10-18 14:56:28 -07:00
+++ b/arch/x86_64/kernel/ptrace.c	2004-10-18 14:56:28 -07:00
@@ -88,6 +88,7 @@
 { 
 	long tmp;
 
+	clear_tsk_thread_flag(child, TIF_SINGLESTEP);
 	tmp = get_stack_long(child, EFL_OFFSET) & ~TRAP_FLAG;
 	put_stack_long(child, EFL_OFFSET, tmp);
 }
@@ -344,6 +345,7 @@
 			set_tsk_thread_flag(child,TIF_SYSCALL_TRACE);
 		else
 			clear_tsk_thread_flag(child,TIF_SYSCALL_TRACE);
+		clear_tsk_thread_flag(child, TIF_SINGLESTEP);
 		child->exit_code = data;
 	/* make sure the single step bit is not set. */
 		tmp = get_stack_long(child, EFL_OFFSET);
@@ -395,6 +397,7 @@
 		ret = 0;
 		if (child->state == TASK_ZOMBIE)	/* already dead */
 			break;
+		clear_tsk_thread_flag(child, TIF_SINGLESTEP);
 		child->exit_code = SIGKILL;
 		/* make sure the single step bit is not set. */
 		tmp = get_stack_long(child, EFL_OFFSET) & ~TRAP_FLAG;
@@ -416,6 +419,7 @@
 		}
 		tmp = get_stack_long(child, EFL_OFFSET) | TRAP_FLAG;
 		put_stack_long(child, EFL_OFFSET, tmp);
+		set_tsk_thread_flag(child, TIF_SINGLESTEP);
 		child->exit_code = data;
 		/* give it a chance to run. */
 		wake_up_process(child);
@@ -429,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;
 	}
 
@@ -528,7 +534,8 @@
 	if (unlikely(current->audit_context))
 		audit_syscall_exit(current, regs->rax);
 
-	if (test_thread_flag(TIF_SYSCALL_TRACE)
+	if ((test_thread_flag(TIF_SYSCALL_TRACE)
+	     || test_thread_flag(TIF_SINGLESTEP))
 	    && (current->ptrace & PT_PTRACED))
 		syscall_trace(regs);
 }
diff -Nru a/arch/x86_64/kernel/setup.c b/arch/x86_64/kernel/setup.c
--- a/arch/x86_64/kernel/setup.c	2004-10-18 14:55:54 -07:00
+++ b/arch/x86_64/kernel/setup.c	2004-10-18 14:55:54 -07:00
@@ -71,7 +71,7 @@
 #ifdef	CONFIG_ACPI_BOOT
 extern int __initdata acpi_ht;
 extern acpi_interrupt_flags	acpi_sci_flags;
-/* int __initdata acpi_force = 0; */
+int __initdata acpi_force = 0;
 #endif
 
 /* For PCI or other memory-mapped resources */
@@ -79,8 +79,10 @@
 
 unsigned long saved_video_mode;
 
+#ifdef CONFIG_SWIOTLB
 int swiotlb;
 EXPORT_SYMBOL(swiotlb);
+#endif
 
 /*
  * Setup options
@@ -105,7 +107,8 @@
 struct resource standard_io_resources[] = {
 	{ "dma1", 0x00, 0x1f, IORESOURCE_BUSY | IORESOURCE_IO },
 	{ "pic1", 0x20, 0x21, IORESOURCE_BUSY | IORESOURCE_IO },
-	{ "timer", 0x40, 0x5f, IORESOURCE_BUSY | IORESOURCE_IO },
+	{ "timer0", 0x40, 0x43, IORESOURCE_BUSY | IORESOURCE_IO },
+	{ "timer1", 0x50, 0x53, IORESOURCE_BUSY | IORESOURCE_IO },
 	{ "keyboard", 0x60, 0x6f, IORESOURCE_BUSY | IORESOURCE_IO },
 	{ "dma page reg", 0x80, 0x8f, IORESOURCE_BUSY | IORESOURCE_IO },
 	{ "pic2", 0xa0, 0xa1, IORESOURCE_BUSY | IORESOURCE_IO },
@@ -248,14 +251,14 @@
 
 		if (!memcmp(from, "acpi=force", 10)) { 
 			/* add later when we do DMI horrors: */
-			/* acpi_force = 1; */	
+			acpi_force = 1;
 			acpi_disabled = 0;
 		}
 
 		/* acpi=ht just means: do ACPI MADT parsing 
 		   at bootup, but don't enable the full ACPI interpreter */
 		if (!memcmp(from, "acpi=ht", 7)) { 
-			/* if (!acpi_force) */
+			if (!acpi_force)
 				disable_acpi();
 			acpi_ht = 1; 
 		}
@@ -423,6 +426,20 @@
 }
 #endif
 
+#define EBDA_ADDR_POINTER 0x40E
+static void __init reserve_ebda_region(void)
+{
+	unsigned int addr;
+	/** 
+	 * there is a real-mode segmented pointer pointing to the 
+	 * 4K EBDA area at 0x40E
+	 */
+	addr = *(unsigned short *)phys_to_virt(EBDA_ADDR_POINTER);
+	addr <<= 4;
+	if (addr)
+		reserve_bootmem_generic(addr, PAGE_SIZE);
+}
+
 void __init setup_arch(char **cmdline_p)
 {
 	unsigned long low_mem_size;
@@ -487,6 +504,9 @@
 	 */
 	reserve_bootmem_generic(0, PAGE_SIZE);
 
+	/* reserve ebda region */
+	reserve_ebda_region();
+
 #ifdef CONFIG_SMP
 	/*
 	 * But first pinch a few for the stack/trampoline stuff
@@ -662,6 +682,26 @@
 		} 
 	} 
 	display_cacheinfo(c);
+
+	if (c->cpuid_level >= 0x80000008) {
+		c->x86_num_cores = (cpuid_ecx(0x80000008) & 0xff) + 1;
+		if (c->x86_num_cores & (c->x86_num_cores - 1))
+			c->x86_num_cores = 1;
+
+#ifdef CONFIG_NUMA
+		/* On a dual core setup the lower bits of apic id
+		   distingush the cores. Fix up the CPU<->node mappings
+		   here based on that.
+		   Assumes number of cores is a power of two. */
+		if (c->x86_num_cores > 1) {
+			int cpu = c->x86_apicid;
+			cpu_to_node[cpu] = cpu >> hweight32(c->x86_num_cores - 1);
+			printk(KERN_INFO "CPU %d -> Node %d\n",
+			       cpu, cpu_to_node[cpu]);
+		}
+#endif
+	}
+
 	return r;
 }
 
@@ -705,7 +745,7 @@
 		}
 		if (index_lsb != index_msb )
 			index_msb++;
-		initial_apic_id = ebx >> 24 & 0xff;
+		initial_apic_id = hard_smp_processor_id();
 		phys_proc_id[cpu] = initial_apic_id >> index_msb;
 		
 		printk(KERN_INFO  "CPU: Physical Processor ID: %d\n",
@@ -748,6 +788,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 },
@@ -885,6 +926,8 @@
 	c->x86_model_id[0] = '\0';  /* Unset */
 	c->x86_clflush_size = 64;
 	c->x86_cache_alignment = c->x86_clflush_size;
+	c->x86_num_cores = 1;
+	c->x86_apicid = c == &boot_cpu_data ? 0 : c - cpu_data;
 	memset(&c->x86_capability, 0, sizeof c->x86_capability);
 
 	/* Get vendor name */
@@ -912,6 +955,7 @@
 		} 
 		if (c->x86_capability[0] & (1<<19)) 
 			c->x86_clflush_size = ((misc >> 8) & 0xff) * 8;
+		c->x86_apicid = misc >> 24;
 	} else {
 		/* Have CPUID level 0 only - unheard of */
 		c->x86 = 4;
@@ -931,8 +975,10 @@
 	/* AMD-defined flags: level 0x80000001 */
 	xlvl = cpuid_eax(0x80000000);
 	if ( (xlvl & 0xffff0000) == 0x80000000 ) {
-		if ( xlvl >= 0x80000001 )
+		if ( xlvl >= 0x80000001 ) {
 			c->x86_capability[1] = cpuid_edx(0x80000001);
+			c->x86_capability[5] = cpuid_ecx(0x80000001);
+		}
 		if ( xlvl >= 0x80000004 )
 			get_model_name(c); /* Default name */
 	}
@@ -1042,8 +1088,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,
 	};
@@ -1131,6 +1177,9 @@
 					seq_printf(m, " [%d]", i);
 			}
 	}
+
+	if (c->x86_num_cores > 1)
+		seq_printf(m, "cpu cores\t: %d\n", c->x86_num_cores);
 
 	seq_printf(m, "\n\n"); 
 
diff -Nru a/arch/x86_64/kernel/setup64.c b/arch/x86_64/kernel/setup64.c
--- a/arch/x86_64/kernel/setup64.c	2004-10-18 14:56:27 -07:00
+++ b/arch/x86_64/kernel/setup64.c	2004-10-18 14:56:27 -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); 
@@ -193,7 +195,8 @@
 char boot_exception_stacks[N_EXCEPTION_STACKS * EXCEPTION_STKSZ] 
 __attribute__((section(".bss.page_aligned")));
 
-void __init syscall_init(void)
+/* May not be marked __init: used by software suspend */
+void syscall_init(void)
 {
 	/* 
 	 * LSTAR and STAR live in a bit strange symbiosis.
@@ -235,10 +238,11 @@
 #else
 	int cpu = smp_processor_id();
 #endif
-	struct tss_struct * t = &init_tss[cpu];
+	struct tss_struct *t = &per_cpu(init_tss, cpu);
 	unsigned long v; 
 	char *estacks = NULL; 
 	struct task_struct *me;
+	int i;
 
 	/* CPU 0 is initialised in head64.c */
 	if (cpu != 0) {
@@ -302,12 +306,13 @@
 		t->ist[v] = (unsigned long)estacks;
 	}
 
-	t->io_bitmap_base = INVALID_IO_BITMAP_OFFSET;
+	t->io_bitmap_base = offsetof(struct tss_struct, io_bitmap);
 	/*
-	 * This is required because the CPU will access up to
+	 * <= is required because the CPU will access up to
 	 * 8 bits beyond the end of the IO permission bitmap.
 	 */
-	t->io_bitmap[IO_BITMAP_LONGS] = ~0UL;
+	for (i = 0; i <= IO_BITMAP_LONGS; i++)
+		t->io_bitmap[i] = ~0UL;
 
 	atomic_inc(&init_mm.mm_count);
 	me->active_mm = &init_mm;
diff -Nru a/arch/x86_64/kernel/signal.c b/arch/x86_64/kernel/signal.c
--- a/arch/x86_64/kernel/signal.c	2004-10-18 14:56:48 -07:00
+++ b/arch/x86_64/kernel/signal.c	2004-10-18 14:56:48 -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;
 }	
 
@@ -180,6 +181,7 @@
 setup_sigcontext(struct sigcontext __user *sc, struct pt_regs *regs, unsigned long mask, struct task_struct *me)
 {
 	int err = 0;
+	unsigned long eflags;
 
 	err |= __put_user(0, &sc->gs);
 	err |= __put_user(0, &sc->fs);
@@ -203,7 +205,11 @@
 	err |= __put_user(me->thread.trap_no, &sc->trapno);
 	err |= __put_user(me->thread.error_code, &sc->err);
 	err |= __put_user(regs->rip, &sc->rip);
-	err |= __put_user(regs->eflags, &sc->eflags);
+	eflags = regs->eflags;
+	if (current->ptrace & PT_PTRACED) {
+		eflags &= ~TF_MASK;
+	}
+	err |= __put_user(eflags, &sc->eflags);
 	err |= __put_user(mask, &sc->oldmask);
 	err |= __put_user(me->thread.cr2, &sc->cr2);
 
@@ -287,7 +293,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; 
 	}
 
@@ -318,7 +324,13 @@
 	regs->rsp = (unsigned long)frame;
 
 	set_fs(USER_DS);
-	regs->eflags &= ~TF_MASK;
+	if (regs->eflags & TF_MASK) {
+		if (current->ptrace & PT_PTRACED) {
+			ptrace_notify(SIGTRAP);
+		} else {
+			regs->eflags &= ~TF_MASK;
+		}
+	}
 
 #ifdef DEBUG_SIG
 	printk("SIG deliver (%s:%d): sp=%p pc=%p ra=%p\n",
@@ -328,9 +340,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 +348,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 +387,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 +403,7 @@
  */
 int do_signal(struct pt_regs *regs, sigset_t *oldset)
 {
+	struct k_sigaction ka;
 	siginfo_t info;
 	int signr;
 
@@ -419,7 +425,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 +436,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/smp.c b/arch/x86_64/kernel/smp.c
--- a/arch/x86_64/kernel/smp.c	2004-10-18 14:57:19 -07:00
+++ b/arch/x86_64/kernel/smp.c	2004-10-18 14:57:19 -07:00
@@ -382,30 +382,14 @@
  * this function sends a 'generic call function' IPI to all other CPUs
  * in the system.
  */
-
-int smp_call_function (void (*func) (void *info), void *info, int nonatomic,
-			int wait)
-/*
- * [SUMMARY] Run a function on all other CPUs.
- * <func> The function to run. This must be fast and non-blocking.
- * <info> An arbitrary pointer to pass to the function.
- * <nonatomic> currently unused.
- * <wait> If true, wait (atomically) until function has completed on other CPUs.
- * [RETURNS] 0 on success, else a negative status code. Does not return until
- * remote CPUs are nearly ready to execute <<func>> or are or have executed.
- *
- * You must not call this function with disabled interrupts or from a
- * hardware interrupt handler or from a bottom half handler.
- */
+static void __smp_call_function (void (*func) (void *info), void *info,
+				int nonatomic, int wait)
 {
 	struct call_data_struct data;
 	int cpus = num_online_cpus()-1;
 
 	if (!cpus)
-		return 0;
-
-	/* Can deadlock when called with interrupts disabled */
-	WARN_ON(irqs_disabled());
+		return;
 
 	data.func = func;
 	data.info = info;
@@ -414,7 +398,6 @@
 	if (wait)
 		atomic_set(&data.finished, 0);
 
-	spin_lock(&call_lock);
 	call_data = &data;
 	wmb();
 	/* Send a message to all other CPUs and wait for them to respond */
@@ -427,8 +410,29 @@
 	if (wait)
 		while (atomic_read(&data.finished) != cpus)
 			barrier();
-	spin_unlock(&call_lock);
+}
 
+/*
+ * smp_call_function - run a function on all other CPUs.
+ * @func: The function to run. This must be fast and non-blocking.
+ * @info: An arbitrary pointer to pass to the function.
+ * @nonatomic: currently unused.
+ * @wait: If true, wait (atomically) until function has completed on other
+ *        CPUs.
+ *
+ * Returns 0 on success, else a negative status code. Does not return until
+ * remote CPUs are nearly ready to execute func or are or have executed.
+ *
+ * You must not call this function with disabled interrupts or from a
+ * hardware interrupt handler or from a bottom half handler.
+ * Actually there are a few legal cases, like panic.
+ */
+int smp_call_function (void (*func) (void *info), void *info, int nonatomic,
+			int wait)
+{
+	spin_lock(&call_lock);
+	__smp_call_function(func,info,nonatomic,wait);
+	spin_unlock(&call_lock);
 	return 0;
 }
 
@@ -452,7 +456,16 @@
 
 void smp_send_stop(void)
 {
-	smp_call_function(smp_really_stop_cpu, NULL, 1, 0);
+	int nolock = 0;
+	/* Don't deadlock on the call lock in panic */
+	if (!spin_trylock(&call_lock)) {
+		udelay(100);
+		/* ignore locking because we have paniced anyways */
+		nolock = 1;
+	}
+	__smp_call_function(smp_really_stop_cpu, NULL, 1, 0);
+	if (!nolock)
+		spin_unlock(&call_lock);
 	smp_stop_cpu();
 }
 
diff -Nru a/arch/x86_64/kernel/smpboot.c b/arch/x86_64/kernel/smpboot.c
--- a/arch/x86_64/kernel/smpboot.c	2004-10-18 14:57:05 -07:00
+++ b/arch/x86_64/kernel/smpboot.c	2004-10-18 14:57:05 -07:00
@@ -43,6 +43,7 @@
 #include <linux/irq.h>
 #include <linux/bootmem.h>
 #include <linux/thread_info.h>
+#include <linux/module.h>
 
 #include <linux/delay.h>
 #include <linux/mc146818rtc.h>
@@ -62,6 +63,7 @@
 
 /* which logical CPU number maps to which CPU (physical APIC ID) */
 volatile char x86_cpu_to_apicid[NR_CPUS];
+EXPORT_SYMBOL(x86_cpu_to_apicid);
 
 static cpumask_t cpu_callin_map;
 cpumask_t cpu_callout_map;
@@ -390,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)
 {
@@ -573,26 +565,17 @@
 	 * 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;
 
 	start_rip = setup_trampoline();
 
 	init_rsp = idle->thread.rsp; 
-	init_tss[cpu].rsp0 = init_rsp;
+	per_cpu(init_tss,cpu).rsp0 = init_rsp;
 	initial_code = start_secondary;
 	clear_ti_thread_flag(idle->thread_info, TIF_FORK);
 
@@ -967,6 +950,9 @@
 
 void __init smp_cpus_done(unsigned int max_cpus)
 {
+#ifdef CONFIG_X86_IO_APIC
+	setup_ioapic_dest();
+#endif
 	zap_low_mappings();
 }
 
diff -Nru a/arch/x86_64/kernel/suspend.c b/arch/x86_64/kernel/suspend.c
--- a/arch/x86_64/kernel/suspend.c	2004-10-18 14:56:31 -07:00
+++ b/arch/x86_64/kernel/suspend.c	2004-10-18 14:56:31 -07:00
@@ -129,7 +129,7 @@
 void fix_processor_context(void)
 {
 	int cpu = smp_processor_id();
-	struct tss_struct * t = init_tss + cpu;
+	struct tss_struct *t = &per_cpu(init_tss, cpu);
 
 	set_tss_desc(cpu,t);	/* This just modifies memory; should not be neccessary. But... This is neccessary, because 386 hardware has concept of busy TSS or some similar stupidity. */
 
diff -Nru a/arch/x86_64/kernel/suspend_asm.S b/arch/x86_64/kernel/suspend_asm.S
--- a/arch/x86_64/kernel/suspend_asm.S	2004-10-18 14:57:03 -07:00
+++ b/arch/x86_64/kernel/suspend_asm.S	2004-10-18 14:57:03 -07:00
@@ -1,22 +1,18 @@
-/* originally gcc generated, but now changed. don't overwrite. */
+/* Originally gcc generated, modified by hand
+ *
+ * This may not use any stack, nor any variable that is not "NoSave":
+ *
+ * Its rewriting one kernel image with another. What is stack in "old"
+ * image could very well be data page in "new" image, and overwriting
+ * your own stack under you is bad idea.
+ */
 	
 	.text
 #include <linux/linkage.h>
 #include <asm/segment.h>
 #include <asm/page.h>
 
-/* Input:
- * rdi	resume flag 
- */	
-			
-ENTRY(do_magic)
-.LFB5:
-	subq	$8, %rsp
-.LCFI2:
-	testl	%edi, %edi
-	jne	.L90
-	call	do_magic_suspend_1
-	call	save_processor_state
+ENTRY(swsusp_arch_suspend)
 
 	movq %rsp, saved_context_esp(%rip)
 	movq %rax, saved_context_eax(%rip)
@@ -36,36 +32,35 @@
 	movq %r15, saved_context_r15(%rip)
 	pushfq ; popq saved_context_eflags(%rip)
 
-	addq	$8, %rsp
-	jmp	do_magic_suspend_2
-.L90:
+	call swsusp_save
+	ret
+
+ENTRY(swsusp_arch_resume)
 	/* set up cr3 */	
 	leaq	init_level4_pgt(%rip),%rax
 	subq	$__START_KERNEL_map,%rax
-	movq %rax,%cr3
+	movq	%rax,%cr3
 
 	movq	mmu_cr4_features(%rip), %rax
 	movq	%rax, %rdx
-	
 	andq	$~(1<<7), %rdx	# PGE
-	movq %rdx, %cr4;  # turn off PGE     
-	movq %cr3, %rcx;  # flush TLB        
-	movq %rcx, %cr3;                     
-	movq %rax, %cr4;  # turn PGE back on 
+	movq	%rdx, %cr4;  # turn off PGE
+	movq	%cr3, %rcx;  # flush TLB
+	movq	%rcx, %cr3;
+	movq	%rax, %cr4;  # turn PGE back on
 
-	call	do_magic_resume_1
 	movl	nr_copy_pages(%rip), %eax
 	xorl	%ecx, %ecx
-	movq	$0, loop(%rip)
+	movq	$0, %r10
 	testl	%eax, %eax
-	je	.L108
+	jz	done
 .L105:
 	xorl	%esi, %esi
-	movq	$0, loop2(%rip)
+	movq	$0, %r11
 	jmp	.L104
 	.p2align 4,,7
-.L111:
-	movq	loop(%rip), %rcx
+copy_one_page:
+	movq	%r10, %rcx
 .L104:
 	movq	pagedir_nosave(%rip), %rdx
 	movq	%rcx, %rax
@@ -75,27 +70,26 @@
 	movzbl	(%rsi,%rax), %eax
 	movb	%al, (%rsi,%rcx)
 
-	movq %cr3, %rax;  # flush TLB 
-	movq %rax, %cr3;              
+	movq	%cr3, %rax;  # flush TLB
+	movq	%rax, %cr3;
 
-	movq	loop2(%rip), %rax
+	movq	%r11, %rax
 	incq	%rax
 	cmpq	$4095, %rax
 	movq	%rax, %rsi
-	movq	%rax, loop2(%rip)
-	jbe	.L111
-	movq	loop(%rip), %rax
+	movq	%rax, %r11
+	jbe	copy_one_page
+	movq	%r10, %rax
 	incq	%rax
 	movq	%rax, %rcx
-	movq	%rax, loop(%rip)
+	movq	%rax, %r10
 	mov	nr_copy_pages(%rip), %eax
 	cmpq	%rax, %rcx
 	jb	.L105
-.L108:
-	.align 4
+done:
 	movl	$24, %eax
+	movl	%eax, %ds
 
-	movl %eax, %ds
 	movq saved_context_esp(%rip), %rsp
 	movq saved_context_ebp(%rip), %rbp
 	movq saved_context_eax(%rip), %rax
@@ -113,13 +107,5 @@
 	movq saved_context_r14(%rip), %r14
 	movq saved_context_r15(%rip), %r15
 	pushq saved_context_eflags(%rip) ; popfq
-	call	restore_processor_state
-	addq	$8, %rsp
-	jmp	do_magic_resume_2
-
-	.section .data.nosave
-loop:
-	.quad 0
-loop2:	
-	.quad 0		
-	.previous
+	call	swsusp_restore
+	ret
diff -Nru a/arch/x86_64/kernel/time.c b/arch/x86_64/kernel/time.c
--- a/arch/x86_64/kernel/time.c	2004-10-18 14:56:48 -07:00
+++ b/arch/x86_64/kernel/time.c	2004-10-18 14:56:48 -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>
@@ -33,6 +32,7 @@
 #include <asm/timex.h>
 #include <asm/proto.h>
 #include <asm/hpet.h>
+#include <asm/sections.h>
 #include <linux/cpufreq.h>
 #ifdef CONFIG_X86_LOCAL_APIC
 #include <asm/apic.h>
@@ -42,6 +42,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 +86,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 +123,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
@@ -176,6 +180,28 @@
 
 EXPORT_SYMBOL(do_settimeofday);
 
+unsigned long profile_pc(struct pt_regs *regs)
+{
+	unsigned long pc = instruction_pointer(regs);
+
+	/* Assume the lock function has either no stack frame or only a single word.
+	   This checks if the address on the stack looks like a kernel text address.
+	   There is a small window for false hits, but in that case the tick
+	   is just accounted to the spinlock function.
+	   Better would be to write these functions in assembler again
+	   and check exactly. */
+	if (in_lock_functions(pc)) {
+		char *v = *(char **)regs->rsp;
+		if ((v >= _stext && v <= _etext) ||
+			(v >= _sinittext && v <= _einittext) ||
+			(v >= (char *)MODULES_VADDR  && v <= (char *)MODULES_END))
+			return (unsigned long)v;
+		return ((unsigned long *)regs->rsp)[1];
+	}
+	return pc;
+}
+EXPORT_SYMBOL(profile_pc);
+
 /*
  * In order to set the CMOS clock precisely, set_rtc_mmss has to be called 500
  * ms after the second nowtime has started, because when nowtime is written
@@ -214,7 +240,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;
@@ -293,19 +319,56 @@
 }
 EXPORT_SYMBOL(monotonic_clock);
 
+static noinline void handle_lost_ticks(int lost, struct pt_regs *regs)
+{
+    static long lost_count;
+    static int warned;
+
+    if (report_lost_ticks) {
+	    printk(KERN_WARNING "time.c: Lost %d timer "
+		   "tick(s)! ", lost);
+	    print_symbol("rip %s)\n", regs->rip);
+    }
+
+    if (lost_count == 100 && !warned) {
+	    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);
+	    if (vxtime.mode == VXTIME_TSC && vxtime.hpet_address) {
+		    printk(KERN_WARNING "Falling back to HPET\n");
+		    vxtime.last = hpet_readl(HPET_T0_CMP) - hpet_tick;
+		    vxtime.mode = VXTIME_HPET;
+		    do_gettimeoffset = do_gettimeoffset_hpet;
+	    }
+	    /* else should fall back to PIT, but code missing. */
+	    warned = 1;
+    } else
+	    lost_count++;
+
+#ifdef CONFIG_CPU_FREQ
+    /* In some cases the CPU can change frequency without us noticing
+       (like going into thermal throttle)
+       Give cpufreq a change to catch up. */
+    if ((lost_count+1) % 25 == 0) {
+	    cpufreq_delayed_get();
+    }
+#endif
+}
 
 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 +417,8 @@
 				(((long) offset << 32) / vxtime.tsc_quot) - 1;
 	}
 
-	if (lost) {
-		if (report_lost_ticks) {
-			printk(KERN_WARNING "time.c: Lost %ld timer "
-			       "tick(s)! ", lost);
-			print_symbol("rip %s)\n", regs->rip);
-		}
+	if (lost > 0) {
+		handle_lost_ticks(lost, regs);
 		jiffies += lost;
 	}
 
@@ -376,7 +435,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 +568,38 @@
    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)
+{
+	static int warned;
+	if (cpufreq_init && !cpufreq_delayed_issched) {
+		cpufreq_delayed_issched = 1;
+		if (!warned) {
+			warned = 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 +609,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 +633,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 +645,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
 
 /*
@@ -705,9 +813,9 @@
                 outl(0x800038a0, 0xcf8);
                 outl(0xff000001, 0xcfc);
                 outl(0x800038a0, 0xcf8);
-                hpet_address = inl(0xcfc) & 0xfffffffe;
+                vxtime.hpet_address = inl(0xcfc) & 0xfffffffe;
 		printk(KERN_WARNING "time.c: WARNING: Enabled HPET "
-		       "at %#lx.\n", hpet_address);
+		       "at %#lx.\n", vxtime.hpet_address);
         }
 #endif
 	if (nohpet)
@@ -725,8 +833,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 +850,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)
@@ -781,11 +884,12 @@
 
 static int time_resume(struct sys_device *dev)
 {
+	unsigned long flags;
 	unsigned long sec = get_cmos_time() + clock_cmos_diff;
-	write_seqlock_irq(&xtime_lock);
+	write_seqlock_irqsave(&xtime_lock,flags);
 	xtime.tv_sec = sec;
 	xtime.tv_nsec = 0;
-	write_sequnlock_irq(&xtime_lock);
+	write_sequnlock_irqrestore(&xtime_lock,flags);
 	return 0;
 }
 
@@ -1037,6 +1141,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-10-18 14:55:54 -07:00
+++ b/arch/x86_64/kernel/traps.c	2004-10-18 14:55:54 -07:00
@@ -110,9 +110,10 @@
 { 
 	int k;
 	for (k = 0; k < N_EXCEPTION_STACKS; k++) {
-		unsigned long end = init_tss[cpu].ist[k] + EXCEPTION_STKSZ; 
+		struct tss_struct *tss = &per_cpu(init_tss, cpu);
+		unsigned long end = tss->ist[k] + EXCEPTION_STKSZ;
 
-		if (stack >= init_tss[cpu].ist[k]  && stack <= end) 
+		if (stack >= tss->ist[k]  && stack <= end)
 			return (unsigned long *)end;
 	}
 	return NULL;
@@ -352,7 +353,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 */
@@ -436,7 +437,8 @@
 #define DO_ERROR(trapnr, signr, str, name) \
 asmlinkage void do_##name(struct pt_regs * regs, long error_code) \
 { \
-	if (notify_die(DIE_TRAP, str, regs, error_code, trapnr, signr) == NOTIFY_BAD) \
+	if (notify_die(DIE_TRAP, str, regs, error_code, trapnr, signr) \
+							== NOTIFY_STOP) \
 		return; \
 	do_trap(trapnr, signr, str, regs, error_code, NULL); \
 }
@@ -449,7 +451,8 @@
 	info.si_errno = 0; \
 	info.si_code = sicode; \
 	info.si_addr = (void __user *)siaddr; \
-	if (notify_die(DIE_TRAP, str, regs, error_code, trapnr, signr) == NOTIFY_BAD) \
+	if (notify_die(DIE_TRAP, str, regs, error_code, trapnr, signr) \
+							== NOTIFY_STOP) \
 		return; \
 	do_trap(trapnr, signr, str, regs, error_code, &info); \
 }
@@ -463,14 +466,15 @@
 DO_ERROR( 9, SIGFPE,  "coprocessor segment overrun", coprocessor_segment_overrun)
 DO_ERROR(10, SIGSEGV, "invalid TSS", invalid_TSS)
 DO_ERROR(11, SIGBUS,  "segment not present", segment_not_present)
-DO_ERROR_INFO(17, SIGBUS, "alignment check", alignment_check, BUS_ADRALN, get_cr2())
+DO_ERROR_INFO(17, SIGBUS, "alignment check", alignment_check, BUS_ADRALN, 0)
 DO_ERROR(18, SIGSEGV, "reserved", reserved)
 
 #define DO_ERROR_STACK(trapnr, signr, str, name) \
 asmlinkage void *do_##name(struct pt_regs * regs, long error_code) \
 { \
 	struct pt_regs *pr = ((struct pt_regs *)(current->thread.rsp0))-1; \
-	if (notify_die(DIE_TRAP, str, regs, error_code, trapnr, signr) == NOTIFY_BAD) \
+	if (notify_die(DIE_TRAP, str, regs, error_code, trapnr, signr) \
+							== NOTIFY_STOP) \
 		return regs; \
 	if (regs->cs & 3) { \
 		memcpy(pr, regs, sizeof(struct pt_regs)); \
@@ -513,7 +517,7 @@
 		tsk->thread.error_code = error_code;
 		tsk->thread.trap_no = 13;
 		force_sig(SIGSEGV, tsk);
-	return;
+		return;
 	} 
 
 	/* kernel gp */
@@ -564,7 +568,8 @@
 	unsigned char reason = inb(0x61);
 
 	if (!(reason & 0xc0)) {
-		if (notify_die(DIE_NMI_IPI, "nmi_ipi", regs, reason, 0, SIGINT) == NOTIFY_BAD)
+		if (notify_die(DIE_NMI_IPI, "nmi_ipi", regs, reason, 0, SIGINT)
+								== NOTIFY_STOP)
 			return;
 #ifdef CONFIG_X86_LOCAL_APIC
 		/*
@@ -579,7 +584,7 @@
 		unknown_nmi_error(reason, regs);
 		return;
 	}
-	if (notify_die(DIE_NMI, "nmi", regs, reason, 0, SIGINT) == NOTIFY_BAD)
+	if (notify_die(DIE_NMI, "nmi", regs, reason, 0, SIGINT) == NOTIFY_STOP)
 		return; 
 	if (reason & 0x80)
 		mem_parity_error(reason, regs);
@@ -670,27 +675,53 @@
 	return regs;
 
 clear_TF_reenable:
-	printk("clear_tf_reenable\n");
 	set_tsk_thread_flag(tsk, TIF_SINGLESTEP);
 
 clear_TF:
 	/* RED-PEN could cause spurious errors */
 	if (notify_die(DIE_DEBUG, "debug2", regs, condition, 1, SIGTRAP) 
-	    != NOTIFY_BAD)
+								!= NOTIFY_STOP)
 	regs->eflags &= ~TF_MASK;
 	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 +771,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 +828,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-10-18 14:55:54 -07:00
+++ b/arch/x86_64/kernel/vmlinux.lds.S	2004-10-18 14:55:54 -07:00
@@ -16,6 +16,7 @@
   .text : {
 	*(.text)
 	SCHED_TEXT
+	LOCK_TEXT
 	*(.fixup)
 	*(.gnu.warning)
 	} = 0x9090
@@ -91,9 +92,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-10-18 14:56:13 -07:00
+++ b/arch/x86_64/kernel/x8664_ksyms.c	2004-10-18 14:56:13 -07:00
@@ -21,7 +21,6 @@
 #include <asm/uaccess.h>
 #include <asm/checksum.h>
 #include <asm/io.h>
-#include <asm/hardirq.h>
 #include <asm/delay.h>
 #include <asm/irq.h>
 #include <asm/mmx.h>
@@ -63,10 +62,10 @@
 EXPORT_SYMBOL(pm_power_off);
 EXPORT_SYMBOL(get_cmos_time);
 
-EXPORT_SYMBOL_NOVERS(__down_failed);
-EXPORT_SYMBOL_NOVERS(__down_failed_interruptible);
-EXPORT_SYMBOL_NOVERS(__down_failed_trylock);
-EXPORT_SYMBOL_NOVERS(__up_wakeup);
+EXPORT_SYMBOL(__down_failed);
+EXPORT_SYMBOL(__down_failed_interruptible);
+EXPORT_SYMBOL(__down_failed_trylock);
+EXPORT_SYMBOL(__up_wakeup);
 /* Networking helper routines. */
 EXPORT_SYMBOL(csum_partial_copy_nocheck);
 EXPORT_SYMBOL(ip_compute_csum);
@@ -76,14 +75,14 @@
 EXPORT_SYMBOL(__delay);
 EXPORT_SYMBOL(__const_udelay);
 
-EXPORT_SYMBOL_NOVERS(__get_user_1);
-EXPORT_SYMBOL_NOVERS(__get_user_2);
-EXPORT_SYMBOL_NOVERS(__get_user_4);
-EXPORT_SYMBOL_NOVERS(__get_user_8);
-EXPORT_SYMBOL_NOVERS(__put_user_1);
-EXPORT_SYMBOL_NOVERS(__put_user_2);
-EXPORT_SYMBOL_NOVERS(__put_user_4);
-EXPORT_SYMBOL_NOVERS(__put_user_8);
+EXPORT_SYMBOL(__get_user_1);
+EXPORT_SYMBOL(__get_user_2);
+EXPORT_SYMBOL(__get_user_4);
+EXPORT_SYMBOL(__get_user_8);
+EXPORT_SYMBOL(__put_user_1);
+EXPORT_SYMBOL(__put_user_2);
+EXPORT_SYMBOL(__put_user_4);
+EXPORT_SYMBOL(__put_user_8);
 
 EXPORT_SYMBOL(strpbrk);
 EXPORT_SYMBOL(strstr);
@@ -108,18 +107,15 @@
 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
 EXPORT_SYMBOL(cpu_data);
 EXPORT_SYMBOL(cpu_online_map);
-EXPORT_SYMBOL_NOVERS(__write_lock_failed);
-EXPORT_SYMBOL_NOVERS(__read_lock_failed);
+EXPORT_SYMBOL(__write_lock_failed);
+EXPORT_SYMBOL(__read_lock_failed);
 
 EXPORT_SYMBOL(synchronize_irq);
 EXPORT_SYMBOL(smp_call_function);
@@ -164,28 +160,35 @@
 extern char * strcat(char *, const char *);
 extern int memcmp(const void * cs,const void * ct,size_t count);
 
-EXPORT_SYMBOL_NOVERS(memset);
-EXPORT_SYMBOL_NOVERS(strlen);
-EXPORT_SYMBOL_NOVERS(memmove);
-EXPORT_SYMBOL_NOVERS(strcpy);
-EXPORT_SYMBOL_NOVERS(strncmp);
-EXPORT_SYMBOL_NOVERS(strncpy);
-EXPORT_SYMBOL_NOVERS(strchr);
-EXPORT_SYMBOL_NOVERS(strcmp); 
-EXPORT_SYMBOL_NOVERS(strcat);
-EXPORT_SYMBOL_NOVERS(strncat);
-EXPORT_SYMBOL_NOVERS(memchr);
-EXPORT_SYMBOL_NOVERS(strrchr);
-EXPORT_SYMBOL_NOVERS(strnlen);
-EXPORT_SYMBOL_NOVERS(memscan);
-EXPORT_SYMBOL_NOVERS(memcpy);
-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);
+EXPORT_SYMBOL(memset);
+EXPORT_SYMBOL(strlen);
+EXPORT_SYMBOL(memmove);
+EXPORT_SYMBOL(strcpy);
+EXPORT_SYMBOL(strncmp);
+EXPORT_SYMBOL(strncpy);
+EXPORT_SYMBOL(strchr);
+EXPORT_SYMBOL(strcmp);
+EXPORT_SYMBOL(strcat);
+EXPORT_SYMBOL(strncat);
+EXPORT_SYMBOL(memchr);
+EXPORT_SYMBOL(strrchr);
+EXPORT_SYMBOL(strnlen);
+EXPORT_SYMBOL(memscan);
+EXPORT_SYMBOL(memcpy);
+EXPORT_SYMBOL(__memcpy);
+EXPORT_SYMBOL(memcmp);
+
+#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);
 
@@ -201,7 +204,7 @@
 #endif
 
 extern void do_softirq_thunk(void);
-EXPORT_SYMBOL_NOVERS(do_softirq_thunk);
+EXPORT_SYMBOL(do_softirq_thunk);
 
 void out_of_line_bug(void);
 EXPORT_SYMBOL(out_of_line_bug);
@@ -211,10 +214,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-10-18 14:56:15 -07:00
+++ b/arch/x86_64/lib/Makefile	2004-10-18 14:56:15 -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-10-18 14:57:22 -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	2004-10-18 14:56:29 -07:00
+++ b/arch/x86_64/lib/bitstr.c	2004-10-18 14:56:29 -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/csum-wrappers.c b/arch/x86_64/lib/csum-wrappers.c
--- a/arch/x86_64/lib/csum-wrappers.c	2004-10-18 14:55:53 -07:00
+++ b/arch/x86_64/lib/csum-wrappers.c	2004-10-18 14:55:53 -07:00
@@ -22,6 +22,7 @@
 csum_partial_copy_from_user(const char __user *src, char *dst, 
 			    int len, unsigned int isum, int *errp)
 { 
+	might_sleep();
 	*errp = 0;
 	if (likely(access_ok(VERIFY_READ,src, len))) { 
 		/* Why 6, not 7? To handle odd addresses aligned we
@@ -69,6 +70,7 @@
 csum_partial_copy_to_user(const char *src, char __user *dst, 
 			  int len, unsigned int isum, int *errp)
 { 
+	might_sleep();
 	if (unlikely(!access_ok(VERIFY_WRITE, dst, len))) {
 		*errp = -EFAULT;
 		return 0; 
diff -Nru a/arch/x86_64/lib/memmove.c b/arch/x86_64/lib/memmove.c
--- a/arch/x86_64/lib/memmove.c	2004-10-18 14:56:28 -07:00
+++ b/arch/x86_64/lib/memmove.c	2004-10-18 14:56:28 -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/lib/usercopy.c b/arch/x86_64/lib/usercopy.c
--- a/arch/x86_64/lib/usercopy.c	2004-10-18 14:55:54 -07:00
+++ b/arch/x86_64/lib/usercopy.c	2004-10-18 14:55:54 -07:00
@@ -14,6 +14,7 @@
 #define __do_strncpy_from_user(dst,src,count,res)			   \
 do {									   \
 	long __d0, __d1, __d2;						   \
+	might_sleep();							   \
 	__asm__ __volatile__(						   \
 		"	testq %1,%1\n"					   \
 		"	jz 2f\n"					   \
@@ -63,6 +64,7 @@
 unsigned long __clear_user(void __user *addr, unsigned long size)
 {
 	long __d0;
+	might_sleep();
 	/* no memory constraint because it doesn't change any memory gcc knows
 	   about */
 	asm volatile(
diff -Nru a/arch/x86_64/mm/fault.c b/arch/x86_64/mm/fault.c
--- a/arch/x86_64/mm/fault.c	2004-10-18 14:55:54 -07:00
+++ b/arch/x86_64/mm/fault.c	2004-10-18 14:55:54 -07:00
@@ -27,7 +27,6 @@
 #include <asm/system.h>
 #include <asm/uaccess.h>
 #include <asm/pgalloc.h>
-#include <asm/hardirq.h>
 #include <asm/smp.h>
 #include <asm/tlbflush.h>
 #include <asm/proto.h>
@@ -58,16 +57,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 +218,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 +280,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
@@ -282,7 +315,27 @@
 		goto bad_area_nosemaphore;
 
  again:
-	down_read(&mm->mmap_sem);
+	/* When running in the kernel we expect faults to occur only to
+	 * addresses in user space.  All other faults represent errors in the
+	 * kernel and should generate an OOPS.  Unfortunatly, in the case of an
+	 * erroneous fault occuring in a code path which already holds mmap_sem
+	 * we will deadlock attempting to validate the fault against the
+	 * address space.  Luckily the kernel only validly references user
+	 * space from well defined areas of code, which are listed in the
+	 * exceptions table.
+	 *
+	 * As the vast majority of faults will be valid we will only perform
+	 * the source reference check when there is a possibilty of a deadlock.
+	 * Attempt to lock the address space, if we cannot we then validate the
+	 * source.  If this is invalid we can skip the address space check,
+	 * thus avoiding the deadlock.
+	 */
+	if (!down_read_trylock(&mm->mmap_sem)) {
+		if ((error_code & 4) == 0 &&
+		    !search_exception_tables(regs->rip))
+			goto bad_area_nosemaphore;
+		down_read(&mm->mmap_sem);
+	}
 
 	vma = find_vma(mm, address);
 	if (!vma)
@@ -351,18 +404,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 +429,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 +460,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 +534,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 +546,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-10-18 14:56:17 -07:00
+++ b/arch/x86_64/mm/init.c	2004-10-18 14:56:17 -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/ioremap.c b/arch/x86_64/mm/ioremap.c
--- a/arch/x86_64/mm/ioremap.c	2004-10-18 14:57:04 -07:00
+++ b/arch/x86_64/mm/ioremap.c	2004-10-18 14:57:04 -07:00
@@ -111,7 +111,7 @@
  * have to convert them into an offset in a page-aligned mapping, but the
  * caller shouldn't need to know that small detail.
  */
-void * __ioremap(unsigned long phys_addr, unsigned long size, unsigned long flags)
+void __iomem * __ioremap(unsigned long phys_addr, unsigned long size, unsigned long flags)
 {
 	void * addr;
 	struct vm_struct * area;
@@ -126,7 +126,7 @@
 	 * Don't remap the low PCI/ISA area, it's always mapped..
 	 */
 	if (phys_addr >= 0xA0000 && last_addr < 0x100000)
-		return phys_to_virt(phys_addr);
+		return (__force void __iomem *)phys_to_virt(phys_addr);
 
 	/*
 	 * Don't allow anybody to remap normal RAM that we're using..
@@ -164,7 +164,7 @@
 		vunmap(addr);
 		return NULL;
 	}
-	return (void *) (offset + (char *)addr);
+	return (__force void __iomem *) (offset + (char *)addr);
 }
 
 /**
@@ -189,9 +189,9 @@
  * Must be freed with iounmap.
  */
 
-void *ioremap_nocache (unsigned long phys_addr, unsigned long size)
+void __iomem *ioremap_nocache (unsigned long phys_addr, unsigned long size)
 {
-	void *p = __ioremap(phys_addr, size, _PAGE_PCD);
+	void __iomem *p = __ioremap(phys_addr, size, _PAGE_PCD);
 	if (!p) 
 		return p; 
 
@@ -212,7 +212,7 @@
 	return p;					
 }
 
-void iounmap(void *addr)
+void iounmap(void __iomem *addr)
 {
 	struct vm_struct *p;
 	if (addr <= high_memory) 
diff -Nru a/arch/x86_64/mm/k8topology.c b/arch/x86_64/mm/k8topology.c
--- a/arch/x86_64/mm/k8topology.c	2004-10-18 14:57:04 -07:00
+++ b/arch/x86_64/mm/k8topology.c	2004-10-18 14:57:04 -07:00
@@ -100,8 +100,8 @@
 		limit <<= 24; 
 		limit |= (1<<24)-1;
 
-		if (limit > end_pfn_map << PAGE_SHIFT) 
-			limit = end_pfn_map << PAGE_SHIFT; 
+		if (limit > end_pfn << PAGE_SHIFT)
+			limit = end_pfn << PAGE_SHIFT;
 		if (limit <= base)
 			continue; 
 			
diff -Nru a/arch/x86_64/mm/numa.c b/arch/x86_64/mm/numa.c
--- a/arch/x86_64/mm/numa.c	2004-10-18 14:56:49 -07:00
+++ b/arch/x86_64/mm/numa.c	2004-10-18 14:56:49 -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); 
 } 
 
@@ -162,10 +162,58 @@
 	set_bit(0, &node_to_cpumask[cpu_to_node(0)]);
 }
 
+int numa_fake __initdata = 0;
+
+/* Numa emulation */
+static int numa_emulation(unsigned long start_pfn, unsigned long end_pfn)
+{
+ 	int i;
+ 	struct node nodes[MAXNODE];
+ 	unsigned long sz = ((end_pfn - start_pfn)<<PAGE_SHIFT) / numa_fake;
+
+ 	/* Kludge needed for the hash function */
+ 	if (hweight64(sz) > 1) {
+ 		unsigned long x = 1;
+ 		while ((x << 1) < sz)
+ 			x <<= 1;
+ 		if (x < sz/2)
+ 			printk("Numa emulation unbalanced. Complain to maintainer\n");
+ 		sz = x;
+ 	}
+
+ 	memset(&nodes,0,sizeof(nodes));
+ 	for (i = 0; i < numa_fake; i++) {
+ 		nodes[i].start = (start_pfn<<PAGE_SHIFT) + i*sz;
+ 		if (i == numa_fake-1)
+ 			sz = (end_pfn<<PAGE_SHIFT) - nodes[i].start;
+ 		nodes[i].end = nodes[i].start + sz;
+ 		if (i != numa_fake-1)
+ 			nodes[i].end--;
+ 		printk(KERN_INFO "Faking node %d at %016Lx-%016Lx (%LuMB)\n",
+ 		       i,
+ 		       nodes[i].start, nodes[i].end,
+ 		       (nodes[i].end - nodes[i].start) >> 20);
+ 	}
+ 	numnodes = numa_fake;
+ 	memnode_shift = compute_hash_shift(nodes);
+ 	if (memnode_shift < 0) {
+ 		memnode_shift = 0;
+ 		printk(KERN_ERR "No NUMA hash function found. Emulation disabled.\n");
+ 		return -1;
+ 	}
+ 	for (i = 0; i < numa_fake; i++)
+ 		setup_node_bootmem(i, nodes[i].start, nodes[i].end);
+ 	numa_init_array();
+ 	return 0;
+}
+
 void __init numa_initmem_init(unsigned long start_pfn, unsigned long end_pfn)
 { 
 	int i;
 
+	if (numa_fake && !numa_emulation(start_pfn, end_pfn))
+ 		return;
+
 #ifdef CONFIG_K8_NUMA
 	if (!numa_off && !k8_scan_nodes(start_pfn<<PAGE_SHIFT, end_pfn<<PAGE_SHIFT))
 		return;
@@ -214,8 +262,13 @@
 /* [numa=off] */
 __init int numa_setup(char *opt) 
 { 
-	if (!strncmp(opt,"off",3))
+	if (!strcmp(opt,"off"))
 		numa_off = 1;
+	if(!strncmp(opt, "fake=", 5)) {
+		numa_fake = simple_strtoul(opt+5,NULL,0); ;
+		if (numa_fake >= MAX_NUMNODES)
+			numa_fake = MAX_NUMNODES;
+	}
 	return 1;
 } 
 
diff -Nru a/arch/x86_64/pci/Makefile b/arch/x86_64/pci/Makefile
--- a/arch/x86_64/pci/Makefile	2004-10-18 14:56:15 -07:00
+++ b/arch/x86_64/pci/Makefile	2004-10-18 14:56:15 -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-10-18 14:57:24 -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-10-18 14:57:23 -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-10-18 14:57:03 -07:00
+++ b/crypto/Kconfig	2004-10-18 14:57:03 -07:00
@@ -67,6 +67,18 @@
 	  This code also includes SHA-384, a 384 bit hash with 192 bits
 	  of security against collision attacks.
 
+config CRYPTO_WP512
+	tristate "Whirlpool digest algorithms"
+	depends on CRYPTO
+	help
+	  Whirlpool hash algorithm 512, 384 and 256-bit hashes
+
+	  Whirlpool-512 is part of the NESSIE cryptographic primtives.
+	  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
@@ -182,7 +194,7 @@
 	  many rounds for security.  It is very fast and uses
 	  little memory.
 
-	  Xtendend Tiny Encryption Algorithm is a modifcation to
+	  Xtendend Tiny Encryption Algorithm is a modification to
 	  the TEA algorithm to address a potential key weakness
 	  in the TEA algorithm.
 
diff -Nru a/crypto/Makefile b/crypto/Makefile
--- a/crypto/Makefile	2004-10-18 14:57:04 -07:00
+++ b/crypto/Makefile	2004-10-18 14:57:04 -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_WP512) += wp512.o
 obj-$(CONFIG_CRYPTO_DES) += des.o
 obj-$(CONFIG_CRYPTO_BLOWFISH) += blowfish.o
 obj-$(CONFIG_CRYPTO_TWOFISH) += twofish.o
diff -Nru a/crypto/aes.c b/crypto/aes.c
--- a/crypto/aes.c	2004-10-18 14:57:19 -07:00
+++ b/crypto/aes.c	2004-10-18 14:57:19 -07:00
@@ -102,10 +102,10 @@
 #define E_KEY ctx->E
 #define D_KEY ctx->D
 
-static u8 pow_tab[256];
-static u8 log_tab[256];
-static u8 sbx_tab[256];
-static u8 isb_tab[256];
+static u8 pow_tab[256] __initdata;
+static u8 log_tab[256] __initdata;
+static u8 sbx_tab[256] __initdata;
+static u8 isb_tab[256] __initdata;
 static u32 rco_tab[10];
 static u32 ft_tab[4][256];
 static u32 it_tab[4][256];
@@ -113,7 +113,7 @@
 static u32 fl_tab[4][256];
 static u32 il_tab[4][256];
 
-static inline u8
+static inline u8 __init
 f_mult (u8 a, u8 b)
 {
 	u8 aa = log_tab[a], cc = aa + log_tab[b];
@@ -153,14 +153,14 @@
              il_tab[2][byte(bi[(n + 2) & 3],2)] ^		\
              il_tab[3][byte(bi[(n + 1) & 3],3)] ^ *(k + n)
 
-static void
+static void __init
 gen_tabs (void)
 {
 	u32 i, t;
 	u8 p, q;
 
 	/* log and power tables for GF(2**8) finite field with
-	   0x011b as modular polynomial - the simplest prmitive
+	   0x011b as modular polynomial - the simplest primitive
 	   root is 0x03, used here to generate the tables */
 
 	for (i = 0, p = 1; i < 256; ++i) {
diff -Nru a/crypto/api.c b/crypto/api.c
--- a/crypto/api.c	2004-10-18 14:57:04 -07:00
+++ b/crypto/api.c	2004-10-18 14:57:04 -07:00
@@ -155,8 +155,12 @@
 
 void crypto_free_tfm(struct crypto_tfm *tfm)
 {
+	struct crypto_alg *alg = tfm->__crt_alg;
+	int size = sizeof(*tfm) + alg->cra_ctxsize;
+
 	crypto_exit_ops(tfm);
-	crypto_alg_put(tfm->__crt_alg);
+	crypto_alg_put(alg);
+	memset(tfm, 0, size);
 	kfree(tfm);
 }
 
diff -Nru a/crypto/arc4.c b/crypto/arc4.c
--- a/crypto/arc4.c	2004-10-18 14:55:55 -07:00
+++ b/crypto/arc4.c	2004-10-18 14:55:55 -07:00
@@ -3,7 +3,7 @@
  *
  * ARC4 Cipher Algorithm
  *
- * Jon Oberheide <jon@focalhost.com>
+ * Jon Oberheide <jon@oberheide.org>
  *
  * 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
@@ -100,4 +100,4 @@
 
 MODULE_LICENSE("GPL");
 MODULE_DESCRIPTION("ARC4 Cipher Algorithm");
-MODULE_AUTHOR("Jon Oberheide <jon@focalhost.com>");
+MODULE_AUTHOR("Jon Oberheide <jon@oberheide.org>");
diff -Nru a/crypto/blowfish.c b/crypto/blowfish.c
--- a/crypto/blowfish.c	2004-10-18 14:56:17 -07:00
+++ b/crypto/blowfish.c	2004-10-18 14:56:17 -07:00
@@ -3,9 +3,9 @@
  *
  * Blowfish Cipher Algorithm, by Bruce Schneier.
  * http://www.counterpane.com/blowfish.html
- * 
- * Adapated from Kerneli implementation.
- * 
+ *
+ * Adapted from Kerneli implementation.
+ *
  * Copyright (c) Herbert Valerio Riedel <hvr@hvrlab.org>
  * Copyright (c) Kyle McMartin <kyle@debian.org>
  * Copyright (c) 2002 James Morris <jmorris@intercode.com.au>
diff -Nru a/crypto/internal.h b/crypto/internal.h
--- a/crypto/internal.h	2004-10-18 14:55:54 -07:00
+++ b/crypto/internal.h	2004-10-18 14:55:54 -07:00
@@ -17,7 +17,6 @@
 #include <linux/interrupt.h>
 #include <linux/init.h>
 #include <linux/kmod.h>
-#include <asm/hardirq.h>
 #include <asm/kmap_types.h>
 
 extern enum km_type crypto_km_types[];
diff -Nru a/crypto/scatterwalk.c b/crypto/scatterwalk.c
--- a/crypto/scatterwalk.c	2004-10-18 14:56:32 -07:00
+++ b/crypto/scatterwalk.c	2004-10-18 14:56:32 -07:00
@@ -70,7 +70,7 @@
 {
 	/* walk->data may be pointing the first byte of the next page;
 	   however, we know we transfered at least one byte.  So,
-	   walk->data - 1 will be a virutual address in the mapped page. */
+	   walk->data - 1 will be a virtual address in the mapped page. */
 
 	if (out)
 		flush_dcache_page(walk->page);
diff -Nru a/crypto/tcrypt.c b/crypto/tcrypt.c
--- a/crypto/tcrypt.c	2004-10-18 14:56:49 -07:00
+++ b/crypto/tcrypt.c	2004-10-18 14:56:49 -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", 
+	"wp512", "wp384", "wp256", NULL
 };
 
 static void
@@ -680,6 +682,9 @@
 
 		test_hash("sha384", sha384_tv_template, SHA384_TEST_VECTORS);
 		test_hash("sha512", sha512_tv_template, SHA512_TEST_VECTORS);
+		test_hash("wp512", wp512_tv_template, WP512_TEST_VECTORS);
+		test_hash("wp384", wp384_tv_template, WP384_TEST_VECTORS);
+		test_hash("wp256", wp256_tv_template, WP256_TEST_VECTORS);
 		test_deflate();
 		test_crc32c();
 #ifdef CONFIG_CRYPTO_HMAC
@@ -791,6 +796,19 @@
 		test_cipher ("khazad", MODE_ECB, DECRYPT, khazad_dec_tv_template, KHAZAD_DEC_TEST_VECTORS);
 		break;
 
+	case 22:
+		test_hash("wp512", wp512_tv_template, WP512_TEST_VECTORS);
+		break;
+
+	case 23:
+		test_hash("wp384", wp384_tv_template, WP384_TEST_VECTORS);
+		break;
+
+	case 24:
+		test_hash("wp256", wp256_tv_template, WP256_TEST_VECTORS);
+		break;
+
+
 #ifdef CONFIG_CRYPTO_HMAC
 	case 100:
 		test_hmac("md5", hmac_md5_tv_template, HMAC_MD5_TEST_VECTORS);
@@ -846,7 +864,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-10-18 14:57:03 -07:00
+++ b/crypto/tcrypt.h	2004-10-18 14:57:03 -07:00
@@ -301,6 +301,259 @@
 	},
 };
 
+
+/*
+ * WHIRLPOOL test vectors from Whirlpool package 
+ * by Vincent Rijmen and Paulo S. L. M. Barreto as part of the NESSIE
+ * submission
+ */
+#define WP512_TEST_VECTORS	8
+
+struct hash_testvec wp512_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 },
+	},
+};
+
+#define WP384_TEST_VECTORS	8
+
+struct hash_testvec wp384_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 },
+
+
+	}, {
+		.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 },
+	}, {
+		.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 },
+	}, {
+		.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 },
+	}, {
+		.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 },
+	}, {
+		.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 },
+	}, {
+		.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 },
+	}, {
+		.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 },
+	},
+};
+
+#define WP256_TEST_VECTORS	8
+
+struct hash_testvec wp256_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 },
+
+
+	}, {
+		.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 },
+	}, {
+		.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 },
+	}, {
+		.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 },
+	}, {
+		.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 },
+	}, {
+		.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 },
+	}, {
+		.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 },
+	}, {
+		.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 },
+	},
+};
+
+
 #ifdef CONFIG_CRYPTO_HMAC
 /*
  * HMAC-MD5 test vectors from RFC2202
@@ -1186,7 +1439,7 @@
 
 /*
  * Serpent test vectors.  These are backwards because Serpent writes
- * octect sequences in right-to-left mode.
+ * octet sequences in right-to-left mode.
  */
 #define SERPENT_ENC_TEST_VECTORS	4
 #define SERPENT_DEC_TEST_VECTORS	4
diff -Nru a/crypto/tea.c b/crypto/tea.c
--- a/crypto/tea.c	2004-10-18 14:57:19 -07:00
+++ b/crypto/tea.c	2004-10-18 14:57:19 -07:00
@@ -154,7 +154,7 @@
 
 	while (sum != limit) {
 		y += (z << 4 ^ z >> 5) + (z ^ sum) + ctx->KEY[sum&3]; 
-		sum += TEA_DELTA;
+		sum += XTEA_DELTA;
 		z += (y << 4 ^ y >> 5) + (y ^ sum) + ctx->KEY[sum>>11 &3]; 
 	}
 	
diff -Nru a/crypto/twofish.c b/crypto/twofish.c
--- a/crypto/twofish.c	2004-10-18 14:57:05 -07:00
+++ b/crypto/twofish.c	2004-10-18 14:57:05 -07:00
@@ -1,7 +1,7 @@
 /*
  * Twofish for CryptoAPI
  *
- * Originaly Twofish for GPG
+ * Originally Twofish for GPG
  * By Matthew Skala <mskala@ansuz.sooke.bc.ca>, July 26, 1998
  * 256-bit key length added March 20, 1999
  * Some modifications to reduce the text size by Werner Koch, April, 1998
@@ -514,7 +514,7 @@
  * preprocessed through q0 and q1 respectively; for longer keys they are the
  * output of previous stages.  j is the index of the first key byte to use.
  * CALC_K computes a pair of subkeys for 128-bit Twofish, by calling CALC_K_2
- * twice, doing the Psuedo-Hadamard Transform, and doing the necessary
+ * twice, doing the Pseudo-Hadamard Transform, and doing the necessary
  * rotations.  Its parameters are: a, the array to write the results into,
  * j, the index of the first output entry, k and l, the preprocessed indices
  * for index 2i, and m and n, the preprocessed indices for index 2i+1.
diff -Nru a/crypto/wp512.c b/crypto/wp512.c
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/crypto/wp512.c	2004-10-18 14:57:24 -07:00
@@ -0,0 +1,1208 @@
+/*
+ * 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 WP512_DIGEST_SIZE 64
+#define WP384_DIGEST_SIZE 48
+#define WP256_DIGEST_SIZE 32
+
+#define WP512_BLOCK_SIZE  64
+#define WP512_LENGTHBYTES 32
+
+#define WHIRLPOOL_ROUNDS 10
+
+struct wp512_ctx {
+	u8  bitLength[WP512_LENGTHBYTES];
+	u8  buffer[WP512_BLOCK_SIZE];
+	int bufferBits;
+	int bufferPos;
+	u64 hash[WP512_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 wp512_process_buffer(struct wp512_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 wp512_init (void *ctx) {
+	int i;
+	struct wp512_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 wp512_update(void *ctx, const u8 *source, unsigned int len)
+{
+
+	struct wp512_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 == WP512_BLOCK_SIZE * 8) {
+			wp512_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 == WP512_BLOCK_SIZE * 8) {
+			wp512_process_buffer(wctx);
+			bufferBits = bufferPos = 0;
+		}
+		buffer[bufferPos] = b << (8 - bufferRem);
+		bufferBits += (int)bits_len;
+	}
+
+	wctx->bufferBits   = bufferBits;
+	wctx->bufferPos    = bufferPos;
+
+}
+
+static void wp512_final(void *ctx, u8 *out)
+{
+	struct wp512_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 > WP512_BLOCK_SIZE - WP512_LENGTHBYTES) {
+   		if (bufferPos < WP512_BLOCK_SIZE) {
+	   	memset(&buffer[bufferPos], 0, WP512_BLOCK_SIZE - bufferPos);
+   		}
+   		wp512_process_buffer(wctx);
+   		bufferPos = 0;
+   	}
+   	if (bufferPos < WP512_BLOCK_SIZE - WP512_LENGTHBYTES) {
+   		memset(&buffer[bufferPos], 0,
+			  (WP512_BLOCK_SIZE - WP512_LENGTHBYTES) - bufferPos);
+   	}
+   	bufferPos = WP512_BLOCK_SIZE - WP512_LENGTHBYTES;
+   	memcpy(&buffer[WP512_BLOCK_SIZE - WP512_LENGTHBYTES],
+		   bitLength, WP512_LENGTHBYTES);
+   	wp512_process_buffer(wctx);
+   	for (i = 0; i < WP512_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 void wp384_final(void *ctx, u8 *out)
+{
+	struct wp512_ctx *wctx = ctx;
+	u8 D[64];
+
+	wp512_final (wctx, D);
+	memcpy (out, D, WP384_DIGEST_SIZE);
+	memset (D, 0, WP512_DIGEST_SIZE);
+}
+
+static void wp256_final(void *ctx, u8 *out)
+{
+	struct wp512_ctx *wctx = ctx;
+	u8 D[64];
+
+	wp512_final (wctx, D);
+	memcpy (out, D, WP256_DIGEST_SIZE);
+	memset (D, 0, WP512_DIGEST_SIZE);
+}
+
+static struct crypto_alg wp512 = {
+	.cra_name	=	"wp512",
+	.cra_flags	=	CRYPTO_ALG_TYPE_DIGEST,
+	.cra_blocksize	=	WP512_BLOCK_SIZE,
+	.cra_ctxsize	=	sizeof(struct wp512_ctx),
+	.cra_module	=	THIS_MODULE,
+	.cra_list       =       LIST_HEAD_INIT(wp512.cra_list),	
+	.cra_u		=	{ .digest = {
+	.dia_digestsize	=	WP512_DIGEST_SIZE,
+	.dia_init   	= 	wp512_init,
+	.dia_update 	=	wp512_update,
+	.dia_final  	=	wp512_final } }
+};
+
+static struct crypto_alg wp384 = {
+	.cra_name	=	"wp384",
+	.cra_flags	=	CRYPTO_ALG_TYPE_DIGEST,
+	.cra_blocksize	=	WP512_BLOCK_SIZE,
+	.cra_ctxsize	=	sizeof(struct wp512_ctx),
+	.cra_module	=	THIS_MODULE,
+	.cra_list       =       LIST_HEAD_INIT(wp384.cra_list),	
+	.cra_u		=	{ .digest = {
+	.dia_digestsize	=	WP384_DIGEST_SIZE,
+	.dia_init   	= 	wp512_init,
+	.dia_update 	=	wp512_update,
+	.dia_final  	=	wp384_final } }
+};
+
+static struct crypto_alg wp256 = {
+	.cra_name	=	"wp256",
+	.cra_flags	=	CRYPTO_ALG_TYPE_DIGEST,
+	.cra_blocksize	=	WP512_BLOCK_SIZE,
+	.cra_ctxsize	=	sizeof(struct wp512_ctx),
+	.cra_module	=	THIS_MODULE,
+	.cra_list       =       LIST_HEAD_INIT(wp256.cra_list),	
+	.cra_u		=	{ .digest = {
+	.dia_digestsize	=	WP256_DIGEST_SIZE,
+	.dia_init   	= 	wp512_init,
+	.dia_update 	=	wp512_update,
+	.dia_final  	=	wp256_final } }
+};
+
+static int __init init(void)
+{
+	int ret = 0;
+
+	ret = crypto_register_alg(&wp512);
+
+	if (ret < 0)
+		goto out;
+
+	ret = crypto_register_alg(&wp384);
+	if (ret < 0)
+	{
+		crypto_unregister_alg(&wp512);
+		goto out;
+	}
+
+	ret = crypto_register_alg(&wp256);
+	if (ret < 0)
+	{
+		crypto_unregister_alg(&wp512);
+		crypto_unregister_alg(&wp384);
+	}
+out:
+	return ret;
+}
+
+static void __exit fini(void)
+{
+	crypto_unregister_alg(&wp512);
+	crypto_unregister_alg(&wp384);
+	crypto_unregister_alg(&wp256);
+}
+
+MODULE_ALIAS("wp384");
+MODULE_ALIAS("wp256");
+
+module_init(init);
+module_exit(fini);
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("Whirlpool Message Digest Algorithm");
diff -Nru a/drivers/Makefile b/drivers/Makefile
--- a/drivers/Makefile	2004-10-18 14:56:49 -07:00
+++ b/drivers/Makefile	2004-10-18 14:56:49 -07:00
@@ -7,6 +7,7 @@
 
 obj-$(CONFIG_PCI)		+= pci/
 obj-$(CONFIG_PARISC)		+= parisc/
+obj-y				+= video/
 obj-$(CONFIG_ACPI_BOOT)		+= acpi/
 # PnP must come after ACPI since it will eventually need to check if acpi
 # was used and do nothing if so
@@ -15,6 +16,13 @@
 # char/ comes before serial/ etc so that the VT console is the boot-time
 # default.
 obj-y				+= char/
+
+# i810fb depends on char/agp/
+obj-$(CONFIG_FB_I810)           += video/i810/
+
+# we also need input/serio early so serio bus is initialized by the time
+# serial drivers start registering their serio ports
+obj-$(CONFIG_SERIO)		+= input/serio/
 obj-y				+= serial/
 obj-$(CONFIG_PARPORT)		+= parport/
 obj-y				+= base/ block/ misc/ net/ media/
@@ -26,7 +34,7 @@
 obj-$(CONFIG_SCSI)		+= scsi/
 obj-$(CONFIG_FUSION)		+= message/
 obj-$(CONFIG_IEEE1394)		+= ieee1394/
-obj-y				+= cdrom/ video/
+obj-y				+= cdrom/
 obj-$(CONFIG_MTD)		+= mtd/
 obj-$(CONFIG_PCMCIA)		+= pcmcia/
 obj-$(CONFIG_DIO)		+= dio/
@@ -39,7 +47,6 @@
 obj-$(CONFIG_USB_GADGET)	+= usb/gadget/
 obj-$(CONFIG_INPUT)		+= input/
 obj-$(CONFIG_GAMEPORT)		+= input/gameport/
-obj-$(CONFIG_SERIO)		+= input/serio/
 obj-$(CONFIG_I2O)		+= message/
 obj-$(CONFIG_I2C)		+= i2c/
 obj-$(CONFIG_W1)		+= w1/
@@ -50,4 +57,5 @@
 obj-$(CONFIG_MCA)		+= mca/
 obj-$(CONFIG_EISA)		+= eisa/
 obj-$(CONFIG_CPU_FREQ)		+= cpufreq/
+obj-$(CONFIG_MMC)		+= mmc/
 obj-y				+= firmware/
diff -Nru a/drivers/acpi/Kconfig b/drivers/acpi/Kconfig
--- a/drivers/acpi/Kconfig	2004-10-18 14:57:04 -07:00
+++ b/drivers/acpi/Kconfig	2004-10-18 14:57:04 -07:00
@@ -204,6 +204,32 @@
 	  If you have a legacy free Toshiba laptop (such as the Libretto L1
 	  series), say Y.
 
+config ACPI_CUSTOM_DSDT
+	bool "Include Custom DSDT"
+	depends on X86 && ACPI_INTERPRETER && !STANDALONE
+	default n 
+	help
+	  Thist option is to load a custom ACPI DSDT
+	  If you don't know what that is, say N.
+
+config ACPI_CUSTOM_DSDT_FILE
+	string "Custom DSDT Table file to include"
+	depends on ACPI_CUSTOM_DSDT
+	default ""
+	help
+	  Enter the full path name to the file wich includes the AmlCode declaration.
+
+config ACPI_BLACKLIST_YEAR
+	int "Disable ACPI for systems before Jan 1st this year"
+	default 0
+	help
+	  enter a 4-digit year, eg. 2001 to disable ACPI by default
+	  on platforms with DMI BIOS date before January 1st that year.
+	  "acpi=force" can be used to override this mechanism.
+
+	  Enter 0 to disable this mechanism and allow ACPI to
+	  run by default no matter what the year.  (default)
+
 config ACPI_DEBUG
 	bool "Debug Statements"
 	depends on ACPI_INTERPRETER
diff -Nru a/drivers/acpi/Makefile b/drivers/acpi/Makefile
--- a/drivers/acpi/Makefile	2004-10-18 14:57:04 -07:00
+++ b/drivers/acpi/Makefile	2004-10-18 14:57:04 -07:00
@@ -47,4 +47,4 @@
 obj-$(CONFIG_ACPI_NUMA)		+= numa.o
 obj-$(CONFIG_ACPI_ASUS)		+= asus_acpi.o
 obj-$(CONFIG_ACPI_TOSHIBA)	+= toshiba_acpi.o
-obj-$(CONFIG_ACPI_BUS)		+= scan.o 
+obj-$(CONFIG_ACPI_BUS)		+= scan.o motherboard.o
diff -Nru a/drivers/acpi/acpi_ksyms.c b/drivers/acpi/acpi_ksyms.c
--- a/drivers/acpi/acpi_ksyms.c	2004-10-18 14:57:19 -07:00
+++ b/drivers/acpi/acpi_ksyms.c	2004-10-18 14:57:19 -07:00
@@ -84,6 +84,8 @@
 EXPORT_SYMBOL(acpi_enable_event);
 EXPORT_SYMBOL(acpi_disable_event);
 EXPORT_SYMBOL(acpi_clear_event);
+EXPORT_SYMBOL(acpi_set_gpe_type);
+EXPORT_SYMBOL(acpi_enable_gpe);
 EXPORT_SYMBOL(acpi_get_timer_duration);
 EXPORT_SYMBOL(acpi_get_timer);
 EXPORT_SYMBOL(acpi_get_sleep_type_data);
diff -Nru a/drivers/acpi/asus_acpi.c b/drivers/acpi/asus_acpi.c
--- a/drivers/acpi/asus_acpi.c	2004-10-18 14:56:28 -07:00
+++ b/drivers/acpi/asus_acpi.c	2004-10-18 14:56:28 -07:00
@@ -42,7 +42,7 @@
 #include <acpi/acpi_bus.h>
 #include <asm/uaccess.h>
 
-#define ASUS_ACPI_VERSION "0.28"
+#define ASUS_ACPI_VERSION "0.29"
 
 #define PROC_ASUS       "asus"	//the directory
 #define PROC_MLED       "mled"
@@ -123,14 +123,18 @@
 		L3C,      //L3800C
 		L3D,      //L3400D
 		L3H,      //L3H, but also L2000E
+		L4R,      //L4500R
 		L5x,      //L5800C 
 		L8L,      //L8400L
 		M1A,      //M1300A
 		M2E,      //M2400E, L4400L
+		M6N,      //M6800N
+		M6R,      //M6700R
 		P30,	  //Samsung P30
 		S1x,      //S1300A, but also L1400B and M2400A (L84F)
 		S2x,      //S200 (J1 reported), Victor MP-XP7210
-		xxN,      //M2400N, M3700N, M6800N, S1300N, S5200N (Centrino)
+		xxN,      //M2400N, M3700N, M5200N, S1300N, S5200N, W1OOON
+			  //(Centrino)
 		END_MODEL
 	} model;              //Models currently supported
 	u16 event_count[128]; //count for each event TODO make this better
@@ -247,6 +251,19 @@
 	},
 
 	{
+		.name              = "L4R",
+		.mt_mled           = "MLED",
+		.mt_wled           = "WLED",
+		.wled_status       = "\\_SB.PCI0.SBRG.SG13",
+		.mt_lcd_switch     = xxN_PREFIX "_Q10",
+		.lcd_status        = "\\_SB.PCI0.SBSM.SEO4",
+		.brightness_set    = "SPLV",
+		.brightness_get    = "GPLV", 
+		.display_set       = "SDSP",
+		.display_get       = "\\_SB.PCI0.P0P1.VGA.GETD"
+	},
+
+	{
 		.name              = "L5x",
 		.mt_mled           = "MLED",
 /* WLED present, but not controlled by ACPI */
@@ -289,6 +306,31 @@
 	},
 
 	{
+		.name              = "M6N",
+		.mt_mled           = "MLED",
+		.mt_wled           = "WLED",
+		.wled_status       = "\\_SB.PCI0.SBRG.SG13",
+		.mt_lcd_switch     = xxN_PREFIX "_Q10",
+		.lcd_status        = "\\_SB.BKLT",
+		.brightness_set    = "SPLV",
+		.brightness_get    = "GPLV",
+		.display_set       = "SDSP",
+		.display_get       = "\\SSTE"
+	},
+	{
+		.name              = "M6R",
+		.mt_mled           = "MLED",
+		.mt_wled           = "WLED",
+		.mt_lcd_switch     = xxN_PREFIX "_Q10",
+		.lcd_status        = "\\_SB.PCI0.SBSM.SEO4",
+		.brightness_set    = "SPLV",
+		.brightness_get    = "GPLV",
+		.display_set       = "SDSP",
+		.display_get       = "\\SSTE"
+	},
+
+
+	{
 		.name              = "P30",
 		.mt_wled           = "WLED",
 		.mt_lcd_switch     = P30_PREFIX "_Q0E",
@@ -344,6 +386,9 @@
  */
 static struct acpi_table_header *asus_info;
 
+/* The actual device the driver binds to */
+static struct asus_hotk *hotk;
+
 /*
  * The hotkey driver declaration
  */
@@ -408,7 +453,6 @@
 {
 	int len = 0;
 	int temp;
-	struct asus_hotk *hotk = (struct asus_hotk *) data;
 	char buf[16];		//enough for all info
 	/*
 	 * We use the easy way, we don't care of off and count, so we don't set eof
@@ -428,7 +472,7 @@
 		len += sprintf(page + len, "SFUN value         : 0x%04x\n", temp);
 	/*
 	 * Another value for userspace: the ASYM method returns 0x02 for
-	 * battery low and 0x04 for battery critical, it's readings tend to be
+	 * battery low and 0x04 for battery critical, its readings tend to be
 	 * more accurate than those provided by _BST. 
 	 * Note: since not all the laptops provide this method, errors are
 	 * silently ignored.
@@ -467,7 +511,7 @@
 
 /* Generic LED functions */
 static int
-read_led(struct asus_hotk *hotk, const char *ledname, int ledmask)
+read_led(const char *ledname, int ledmask)
 {
 	if (ledname) {
 		int led_status;
@@ -498,7 +542,7 @@
 
 /* FIXME: kill extraneous args so it can be called independently */
 static int
-write_led(const char __user *buffer, unsigned long count, struct asus_hotk *hotk, 
+write_led(const char __user *buffer, unsigned long count,
           char *ledname, int ledmask, int invert)
 {
 	int value;
@@ -528,8 +572,7 @@
 proc_read_mled(char *page, char **start, off_t off, int count, int *eof,
 	       void *data)
 {
-	struct asus_hotk *hotk = (struct asus_hotk *) data;
-	return sprintf(page, "%d\n", read_led(hotk, hotk->methods->mled_status, MLED_ON));
+	return sprintf(page, "%d\n", read_led(hotk->methods->mled_status, MLED_ON));
 }
 
 
@@ -537,8 +580,7 @@
 proc_write_mled(struct file *file, const char __user *buffer,
 		unsigned long count, void *data)
 {
-	struct asus_hotk *hotk = (struct asus_hotk *) data;
-	return write_led(buffer, count, hotk, hotk->methods->mt_mled, MLED_ON, 1);
+	return write_led(buffer, count, hotk->methods->mt_mled, MLED_ON, 1);
 }
 
 /*
@@ -548,16 +590,14 @@
 proc_read_wled(char *page, char **start, off_t off, int count, int *eof,
 	       void *data)
 {
-	struct asus_hotk *hotk = (struct asus_hotk *) data;
-	return sprintf(page, "%d\n", read_led(hotk, hotk->methods->wled_status, WLED_ON));
+	return sprintf(page, "%d\n", read_led(hotk->methods->wled_status, WLED_ON));
 }
 
 static int
 proc_write_wled(struct file *file, const char __user *buffer,
 		unsigned long count, void *data)
 {
-	struct asus_hotk *hotk = (struct asus_hotk *) data;
-	return write_led(buffer, count, hotk, hotk->methods->mt_wled, WLED_ON, 0);
+	return write_led(buffer, count, hotk->methods->mt_wled, WLED_ON, 0);
 }
 
 /*
@@ -567,21 +607,18 @@
 proc_read_tled(char *page, char **start, off_t off, int count, int *eof,
 	       void *data)
 {
-	struct asus_hotk *hotk = (struct asus_hotk *) data;
-	return sprintf(page, "%d\n", read_led(hotk, hotk->methods->tled_status, TLED_ON));
+	return sprintf(page, "%d\n", read_led(hotk->methods->tled_status, TLED_ON));
 }
 
 static int
 proc_write_tled(struct file *file, const char __user *buffer,
 		unsigned long count, void *data)
 {
-	struct asus_hotk *hotk = (struct asus_hotk *) data;
-	return write_led(buffer, count, hotk, hotk->methods->mt_tled, TLED_ON, 0);
+	return write_led(buffer, count, hotk->methods->mt_tled, TLED_ON, 0);
 }
 
 
-
-static int get_lcd_state(struct asus_hotk *hotk)
+static int get_lcd_state(void)
 {
 	int lcd = 0;
 
@@ -622,13 +659,13 @@
 	return (lcd & 1);
 }
 
-static int set_lcd_state(struct asus_hotk *hotk, int value)
+static int set_lcd_state(int value)
 {
 	int lcd = 0;
 	acpi_status status = 0;
 
 	lcd = value ? 1 : 0;
-	if (lcd != get_lcd_state(hotk)) {
+	if (lcd != get_lcd_state()) {
 		/* switch */
 		if (hotk->model != L3H) {
 			status =
@@ -651,7 +688,7 @@
 proc_read_lcd(char *page, char **start, off_t off, int count, int *eof,
 	      void *data)
 {
-	return sprintf(page, "%d\n", get_lcd_state((struct asus_hotk *) data));
+	return sprintf(page, "%d\n", get_lcd_state());
 }
 
 
@@ -660,16 +697,15 @@
 	       unsigned long count, void *data)
 {
 	int value;
-	struct asus_hotk *hotk = (struct asus_hotk *) data;
 	
 	count = parse_arg(buffer, count, &value);
 	if (count > 0)
-		set_lcd_state(hotk, value);
+		set_lcd_state(value);
 	return count;
 }
 
 
-static int read_brightness(struct asus_hotk *hotk)
+static int read_brightness(void)
 {
 	int value;
 	
@@ -689,7 +725,7 @@
 /*
  * Change the brightness level
  */
-static void set_brightness(int value, struct asus_hotk *hotk)
+static void set_brightness(int value)
 {
 	acpi_status status = 0;
 
@@ -702,7 +738,7 @@
 	}
 
 	/* No SPLV method if we are here, act as appropriate */
-	value -= read_brightness(hotk);
+	value -= read_brightness();
 	while (value != 0) {
 		status = acpi_evaluate_object(NULL, (value > 0) ? 
 					      hotk->methods->brightness_up : 
@@ -719,8 +755,7 @@
 proc_read_brn(char *page, char **start, off_t off, int count, int *eof,
 	      void *data)
 {
-	struct asus_hotk *hotk = (struct asus_hotk *) data;
-	return sprintf(page, "%d\n", read_brightness(hotk));
+	return sprintf(page, "%d\n", read_brightness());
 }
 
 static int
@@ -728,13 +763,12 @@
 	       unsigned long count, void *data)
 {
 	int value;
-	struct asus_hotk *hotk = (struct asus_hotk *) data;
 
 	count = parse_arg(buffer, count, &value);
 	if (count > 0) {
 		value = (0 < value) ? ((15 < value) ? 15 : value) : 0;
 			/* 0 <= value <= 15 */
-		set_brightness(value, hotk);
+		set_brightness(value);
 	} else if (count < 0) {
 		printk(KERN_WARNING "Asus ACPI: Error reading user input\n");
 	}
@@ -742,7 +776,7 @@
 	return count;
 }
 
-static void set_display(int value, struct asus_hotk *hotk)
+static void set_display(int value)
 {
 	/* no sanity check needed for now */
 	if (!write_acpi_int(hotk->handle, hotk->methods->display_set, 
@@ -760,10 +794,10 @@
 	      void *data)
 {
 	int value = 0;
-	struct asus_hotk *hotk = (struct asus_hotk *) data;
 	
 	if (!read_acpi_int(hotk->handle, hotk->methods->display_get, &value))
 		printk(KERN_WARNING "Asus ACPI: Error reading display status\n");
+	value &= 0x07; /* needed for some models, shouldn't hurt others */
 	return sprintf(page, "%d\n", value);
 }
 
@@ -778,11 +812,10 @@
 	       unsigned long count, void *data)
 {
 	int value;
-	struct asus_hotk *hotk = (struct asus_hotk *) data;
 
 	count = parse_arg(buffer, count, &value);
 	if (count > 0)
-		set_display(value, hotk);
+		set_display(value);
 	else if (count < 0)
 		printk(KERN_WARNING "Asus ACPI: Error reading user input\n");
 
@@ -817,7 +850,6 @@
 static int __init asus_hotk_add_fs(struct acpi_device *device)
 {
 	struct proc_dir_entry *proc;
-	struct asus_hotk *hotk = acpi_driver_data(device);
 	mode_t mode;
 	
 	/*
@@ -869,13 +901,12 @@
 	}
 	
 	if ((hotk->methods->brightness_up && hotk->methods->brightness_down) ||
-	    (hotk->methods->brightness_get && hotk->methods->brightness_get)) {
+	    (hotk->methods->brightness_get && hotk->methods->brightness_set)) {
 		asus_proc_add(PROC_BRN, &proc_write_brn, &proc_read_brn, mode, device);
 	}
 
 	if (hotk->methods->display_set) {
 		asus_proc_add(PROC_DISP, &proc_write_disp, &proc_read_disp, mode, device);
-
 	}
 
 	return 0;
@@ -883,10 +914,7 @@
 
 static int asus_hotk_remove_fs(struct acpi_device* device)
 {
-	struct asus_hotk* hotk = acpi_driver_data(device);
-
-
-	if(acpi_device_dir(device)){
+	if(acpi_device_dir(device)) {
 		remove_proc_entry(PROC_INFO,acpi_device_dir(device));
 		if (hotk->methods->mt_wled)
 			remove_proc_entry(PROC_WLED,acpi_device_dir(device));
@@ -894,11 +922,12 @@
 			remove_proc_entry(PROC_MLED,acpi_device_dir(device));
 		if (hotk->methods->mt_tled)
 			remove_proc_entry(PROC_TLED,acpi_device_dir(device));
-		if (hotk->methods->mt_lcd_switch && hotk->methods->lcd_status) 
+		if (hotk->methods->mt_lcd_switch && hotk->methods->lcd_status)
 			remove_proc_entry(PROC_LCD, acpi_device_dir(device));
-		if ((hotk->methods->brightness_up && hotk->methods->brightness_down) || (hotk->methods->brightness_get && hotk->methods->brightness_get)) 
+		if ((hotk->methods->brightness_up && hotk->methods->brightness_down) ||
+		    (hotk->methods->brightness_get && hotk->methods->brightness_set))
 			remove_proc_entry(PROC_BRN, acpi_device_dir(device));
-		if (hotk->methods->display_set) 
+		if (hotk->methods->display_set)
 			remove_proc_entry(PROC_DISP, acpi_device_dir(device));
 	}
 	return 0;
@@ -907,11 +936,7 @@
 
 static void asus_hotk_notify(acpi_handle handle, u32 event, void *data)
 {
-	/* TODO Find a better way to handle events count. Here, in data, we receive
-	 * the hotk, so we can do anything!
-	 */
-	struct asus_hotk *hotk = (struct asus_hotk *) data;
-
+	/* TODO Find a better way to handle events count.*/
 	if (!hotk)
 		return;
 
@@ -931,7 +956,7 @@
  * This function is used to initialize the hotk with right values. In this
  * method, we can make all the detection we want, and modify the hotk struct
  */
-static int __init asus_hotk_get_info(struct asus_hotk *hotk)
+static int __init asus_hotk_get_info(void)
 {
 	struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
 	struct acpi_buffer dsdt = { ACPI_ALLOCATE_BUFFER, NULL };
@@ -998,11 +1023,19 @@
 		hotk->model = L3C;
 	else if (strncmp(model->string.pointer, "L8L", 3) == 0)
 		hotk->model = L8L;
+	else if (strncmp(model->string.pointer, "L4R", 3) == 0)
+		hotk->model = L4R;
+	else if (strncmp(model->string.pointer, "M6N", 3) == 0)
+		hotk->model = M6N;
+	else if (strncmp(model->string.pointer, "M6R", 3) == 0)
+		hotk->model = M6R;
 	else if (strncmp(model->string.pointer, "M2N", 3) == 0 ||
 		 strncmp(model->string.pointer, "M3N", 3) == 0 ||
+		 strncmp(model->string.pointer, "M5N", 3) == 0 ||
 		 strncmp(model->string.pointer, "M6N", 3) == 0 ||
 		 strncmp(model->string.pointer, "S1N", 3) == 0 ||
-		 strncmp(model->string.pointer, "S5N", 3) == 0)
+		 strncmp(model->string.pointer, "S5N", 3) == 0 ||
+                 strncmp(model->string.pointer, "W1N", 3) == 0)
 		hotk->model = xxN;
 	else if (strncmp(model->string.pointer, "M1", 2) == 0)
 		hotk->model = M1A;
@@ -1025,7 +1058,6 @@
 		hotk->model = L5x;
 
 	if (hotk->model == END_MODEL) {
-		/* By default use the same values, as I don't know others */
 		printk("unsupported, trying default values, supply the "
 		       "developers with your DSDT\n");
 		hotk->model = M2E;
@@ -1040,16 +1072,14 @@
 		hotk->methods->lcd_status = NULL; 
 	/* L2B is similar enough to L3C to use its settings, with this only 
 	   exception */
-	else if (strncmp(model->string.pointer, "S5N", 3) == 0)
+	else if (strncmp(model->string.pointer, "S5N", 3) == 0 ||
+		 strncmp(model->string.pointer, "M5N", 3) == 0)
 		hotk->methods->mt_mled = NULL; 
-	/* S5N has no MLED */
-	else if (strncmp(model->string.pointer, "M6N", 3) == 0) {
-		hotk->methods->display_get = NULL; //TODO
-		hotk->methods->lcd_status = "\\_SB.BKLT";
-		hotk->methods->mt_wled = "WLED";
-		hotk->methods->wled_status = "\\_SB.PCI0.SBRG.SG13";
-	/* M6N differs slightly and has a usable WLED */
-	}
+	/* S5N and M5N have no MLED */
+	else if (strncmp(model->string.pointer, "M2N", 3) == 0 ||
+		 strncmp(model->string.pointer, "W1N", 3) == 0)
+		hotk->methods->mt_wled = "WLED"; 
+	/* M2N and W1N have a usable WLED */
 	else if (asus_info) {
 		if (strncmp(asus_info->oem_table_id, "L1", 2) == 0)
 			hotk->methods->mled_status = NULL;
@@ -1062,20 +1092,16 @@
 }
 
 
-
-static int __init asus_hotk_check(struct asus_hotk *hotk)
+static int __init asus_hotk_check(void)
 {
 	int result = 0;
 
-	if (!hotk)
-		return(-EINVAL);
-
 	result = acpi_bus_get_status(hotk->device);
 	if (result)
 		return(result);
 
 	if (hotk->device->status.present) {
-		result = asus_hotk_get_info(hotk);
+		result = asus_hotk_get_info();
 	} else {
 		printk(KERN_ERR "  Hotkey device not present, aborting\n");
 		return(-EINVAL);
@@ -1085,10 +1111,8 @@
 }
 
 
-
 static int __init asus_hotk_add(struct acpi_device *device)
 {
-	struct asus_hotk *hotk = NULL;
 	acpi_status status = AE_OK;
 	int result;
 
@@ -1111,7 +1135,7 @@
 	hotk->device = device;
 
 
-	result = asus_hotk_check(hotk);
+	result = asus_hotk_check();
 	if (result)
 		goto end;
 
@@ -1152,16 +1176,14 @@
 	return(result);
 }
 
+
 static int asus_hotk_remove(struct acpi_device *device, int type)
 {
 	acpi_status status = 0;
-	struct asus_hotk *hotk = NULL;
 
 	if (!device || !acpi_driver_data(device))
 		return(-EINVAL);
 
-	hotk = (struct asus_hotk *) acpi_driver_data(device);
-
 	status = acpi_remove_notify_handler(hotk->handle, ACPI_SYSTEM_NOTIFY,
 					    asus_hotk_notify);
 	if (ACPI_FAILURE(status))
@@ -1179,20 +1201,24 @@
 {
 	int result;
 
+	if (acpi_disabled)
+		return -ENODEV;
+
 	asus_proc_dir = proc_mkdir(PROC_ASUS, acpi_root_dir);
 	if (!asus_proc_dir) {
 		printk(KERN_ERR "Asus ACPI: Unable to create /proc entry\n");
-		return(-ENODEV);
+		return -ENODEV;
 	}
 	asus_proc_dir->owner = THIS_MODULE;
 
 	result = acpi_bus_register_driver(&asus_hotk_driver);
-	if (result < 0) {
+	if (result < 1) {
+		acpi_bus_unregister_driver(&asus_hotk_driver);
 		remove_proc_entry(PROC_ASUS, acpi_root_dir);
-		return(-ENODEV);
+		return -ENODEV;
 	}
 
-	return(0);
+	return 0;
 }
 
 
diff -Nru a/drivers/acpi/blacklist.c b/drivers/acpi/blacklist.c
--- a/drivers/acpi/blacklist.c	2004-10-18 14:55:54 -07:00
+++ b/drivers/acpi/blacklist.c	2004-10-18 14:55:54 -07:00
@@ -2,7 +2,9 @@
  *  blacklist.c
  *
  *  Check to see if the given machine has a known bad ACPI BIOS
+ *  or if the BIOS is too old.
  *
+ *  Copyright (C) 2004 Len Brown <len.brown@intel.com>
  *  Copyright (C) 2002 Andy Grover <andrew.grover@intel.com>
  *
  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -30,6 +32,7 @@
 #include <linux/init.h>
 #include <linux/acpi.h>
 #include <acpi/acpi_bus.h>
+#include <linux/dmi.h>
 
 enum acpi_blacklist_predicates
 {
@@ -56,20 +59,6 @@
  */
 static struct acpi_blacklist_item acpi_blacklist[] __initdata =
 {
-	/* Portege 7020, BIOS 8.10 */
-	{"TOSHIB", "7020CT  ", 0x19991112, ACPI_DSDT, all_versions, "Implicit Return", 0},
-	/* Portege 4030 */
-	{"TOSHIB", "4030    ", 0x19991112, ACPI_DSDT, all_versions, "Implicit Return", 0},
-	/* Portege 310/320, BIOS 7.1 */
-	{"TOSHIB", "310     ", 0x19990511, ACPI_DSDT, all_versions, "Implicit Return", 0},
-	/* Seattle 2, old bios rev. */
-	{"INTEL ", "440BX   ", 0x00001000, ACPI_DSDT, less_than_or_equal, "Field beyond end of region", 0},
-	/* ASUS K7M */
-	{"ASUS  ", "K7M     ", 0x00001000, ACPI_DSDT, less_than_or_equal, "Field beyond end of region", 0},
-	/* Intel 810 Motherboard? */
-	{"MNTRAL", "MO81010A", 0x00000012, ACPI_DSDT, less_than_or_equal, "Field beyond end of region", 0},
-	/* Compaq Presario 711FR */
-	{"COMAPQ", "EAGLES", 0x06040000, ACPI_DSDT, less_than_or_equal, "SCI issues (C2 disabled)", 0},
 	/* Compaq Presario 1700 */
 	{"PTLTD ", "  DSDT  ", 0x06040000, ACPI_DSDT, less_than_or_equal, "Multiple problems", 1},
 	/* Sony FX120, FX140, FX150? */
@@ -84,6 +73,45 @@
 };
 
 
+#if	CONFIG_ACPI_BLACKLIST_YEAR
+
+static int __init
+blacklist_by_year(void)
+{
+	int year;
+	char *s = dmi_get_system_info(DMI_BIOS_DATE);
+
+	if (!s)
+		return 0;
+	if (!*s)
+		return 0;
+
+	s = strrchr(s, '/');
+	if (!s)
+		return 0;
+
+	s += 1;
+
+	year = simple_strtoul(s,NULL,0); 
+
+	if (year < 100) {		/* 2-digit year */
+		year += 1900;
+		if (year < 1996)	/* no dates < spec 1.0 */
+			year += 100;
+	}
+
+	if (year < CONFIG_ACPI_BLACKLIST_YEAR) {
+		printk(KERN_ERR PREFIX "BIOS age (%d) fails cutoff (%d), " 
+			"acpi=force is required to enable ACPI\n",
+			year, CONFIG_ACPI_BLACKLIST_YEAR);
+		return 1;
+	}
+	return 0;
+}
+#else
+static inline int blacklist_by_year(void) { return 0; }
+#endif
+
 int __init
 acpi_blacklisted(void)
 {
@@ -133,6 +161,8 @@
 			i++;
 		}
 	}
+
+	blacklisted += blacklist_by_year();
 
 	return blacklisted;
 }
diff -Nru a/drivers/acpi/bus.c b/drivers/acpi/bus.c
--- a/drivers/acpi/bus.c	2004-10-18 14:56:33 -07:00
+++ b/drivers/acpi/bus.c	2004-10-18 14:56:33 -07:00
@@ -590,14 +590,20 @@
 }
 
 
-static int __init
-acpi_bus_init (void)
+void __init
+acpi_early_init (void)
 {
-	int			result = 0;
 	acpi_status		status = AE_OK;
 	struct acpi_buffer	buffer = {sizeof(acpi_fadt), &acpi_fadt};
 
-	ACPI_FUNCTION_TRACE("acpi_bus_init");
+	ACPI_FUNCTION_TRACE("acpi_early_init");
+
+	if (acpi_disabled)
+		return;
+
+	/* enable workarounds, unless strict ACPI spec. compliance */
+	if (!acpi_strict)
+		acpi_gbl_enable_interpreter_slack = TRUE;
 
 	status = acpi_initialize_subsystem();
 	if (ACPI_FAILURE(status)) {
@@ -617,7 +623,7 @@
 	status = acpi_get_table(ACPI_TABLE_FADT, 1, &buffer);
 	if (ACPI_FAILURE(status)) {
 		printk(KERN_ERR PREFIX "Unable to get the FADT\n");
-		goto error1;
+		goto error0;
 	}
 
 #ifdef CONFIG_X86
@@ -640,12 +646,40 @@
 	}
 #endif
 
-	status = acpi_enable_subsystem(ACPI_FULL_INITIALIZATION);
+	status = acpi_enable_subsystem(~(ACPI_NO_HARDWARE_INIT | ACPI_NO_ACPI_ENABLE));
+	if (ACPI_FAILURE(status)) {
+		printk(KERN_ERR PREFIX "Unable to enable ACPI\n");
+		goto error0;
+	}
+
+	return;
+
+error0:
+	disable_acpi();
+	return;
+}
+
+static int __init
+acpi_bus_init (void)
+{
+	int			result = 0;
+	acpi_status		status = AE_OK;
+	extern acpi_status	acpi_os_initialize1(void);
+
+	ACPI_FUNCTION_TRACE("acpi_bus_init");
+
+	status = acpi_os_initialize1();
+
+	status = acpi_enable_subsystem(ACPI_NO_HARDWARE_INIT | ACPI_NO_ACPI_ENABLE);
 	if (ACPI_FAILURE(status)) {
 		printk(KERN_ERR PREFIX "Unable to start the ACPI Interpreter\n");
 		goto error1;
 	}
 
+	if (ACPI_FAILURE(status)) {
+		printk(KERN_ERR PREFIX "Unable to initialize ACPI OS objects\n");
+		goto error1;
+	}
 #ifdef CONFIG_ACPI_EC
 	/*
 	 * ACPI 2.0 requires the EC driver to be loaded and work before
@@ -693,7 +727,6 @@
 	/* Mimic structured exception handling */
 error1:
 	acpi_terminate();
-error0:
 	return_VALUE(-ENODEV);
 }
 
@@ -707,9 +740,6 @@
 
 	printk(KERN_INFO PREFIX "Subsystem revision %08x\n",
 		ACPI_CA_VERSION);
-
-	/* Initial core debug level excludes drivers, so include them now */
-	acpi_set_debug(ACPI_DEBUG_LOW);
 
 	if (acpi_disabled) {
 		printk(KERN_INFO PREFIX "Interpreter disabled.\n");
diff -Nru a/drivers/acpi/button.c b/drivers/acpi/button.c
--- a/drivers/acpi/button.c	2004-10-18 14:55:54 -07:00
+++ b/drivers/acpi/button.c	2004-10-18 14:55:54 -07:00
@@ -456,6 +456,15 @@
 		goto end;
 	}
 
+	if (device->wakeup.flags.valid) {
+		/* Button's GPE is run-wake GPE */
+		acpi_set_gpe_type(device->wakeup.gpe_device, 
+			device->wakeup.gpe_number, ACPI_GPE_TYPE_WAKE_RUN);
+		acpi_enable_gpe(device->wakeup.gpe_device, 
+			device->wakeup.gpe_number, ACPI_NOT_ISR);
+		device->wakeup.state.enabled = 1;
+	}
+
 	printk(KERN_INFO PREFIX "%s [%s]\n", 
 		acpi_device_name(device), acpi_device_bid(device));
 
diff -Nru a/drivers/acpi/debug.c b/drivers/acpi/debug.c
--- a/drivers/acpi/debug.c	2004-10-18 14:56:48 -07:00
+++ b/drivers/acpi/debug.c	2004-10-18 14:56:48 -07:00
@@ -4,6 +4,7 @@
 
 #include <linux/proc_fs.h>
 #include <linux/init.h>
+#include <linux/moduleparam.h>
 #include <asm/uaccess.h>
 #include <acpi/acpi_drivers.h>
 
@@ -13,6 +14,81 @@
 #define ACPI_SYSTEM_FILE_DEBUG_LAYER	"debug_layer"
 #define ACPI_SYSTEM_FILE_DEBUG_LEVEL	"debug_level"
 
+#ifdef MODULE_PARAM_PREFIX
+#undef MODULE_PARAM_PREFIX
+#endif
+
+#define MODULE_PARAM_PREFIX
+module_param(acpi_dbg_layer, uint, 0400);
+module_param(acpi_dbg_level, uint, 0400);
+
+struct acpi_dlayer {
+	const char *name;
+	unsigned long value;
+};
+struct acpi_dlevel {
+	const char *name;
+	unsigned long value;
+};
+#define ACPI_DEBUG_INIT(v)	{ .name = #v, .value = v }
+
+const struct acpi_dlayer acpi_debug_layers[] =
+{
+	ACPI_DEBUG_INIT(ACPI_UTILITIES),
+	ACPI_DEBUG_INIT(ACPI_HARDWARE),
+	ACPI_DEBUG_INIT(ACPI_EVENTS),
+	ACPI_DEBUG_INIT(ACPI_TABLES),
+	ACPI_DEBUG_INIT(ACPI_NAMESPACE),
+	ACPI_DEBUG_INIT(ACPI_PARSER),
+	ACPI_DEBUG_INIT(ACPI_DISPATCHER),
+	ACPI_DEBUG_INIT(ACPI_EXECUTER),
+	ACPI_DEBUG_INIT(ACPI_RESOURCES),
+	ACPI_DEBUG_INIT(ACPI_CA_DEBUGGER),
+	ACPI_DEBUG_INIT(ACPI_OS_SERVICES),
+	ACPI_DEBUG_INIT(ACPI_CA_DISASSEMBLER),
+	ACPI_DEBUG_INIT(ACPI_COMPILER),
+	ACPI_DEBUG_INIT(ACPI_TOOLS),
+};
+
+const struct acpi_dlevel acpi_debug_levels[] =
+{
+	ACPI_DEBUG_INIT(ACPI_LV_ERROR),
+	ACPI_DEBUG_INIT(ACPI_LV_WARN),
+	ACPI_DEBUG_INIT(ACPI_LV_INIT),
+	ACPI_DEBUG_INIT(ACPI_LV_DEBUG_OBJECT),
+	ACPI_DEBUG_INIT(ACPI_LV_INFO),
+
+	ACPI_DEBUG_INIT(ACPI_LV_INIT_NAMES),
+	ACPI_DEBUG_INIT(ACPI_LV_PARSE),
+	ACPI_DEBUG_INIT(ACPI_LV_LOAD),
+	ACPI_DEBUG_INIT(ACPI_LV_DISPATCH),
+	ACPI_DEBUG_INIT(ACPI_LV_EXEC),
+	ACPI_DEBUG_INIT(ACPI_LV_NAMES),
+	ACPI_DEBUG_INIT(ACPI_LV_OPREGION),
+	ACPI_DEBUG_INIT(ACPI_LV_BFIELD),
+	ACPI_DEBUG_INIT(ACPI_LV_TABLES),
+	ACPI_DEBUG_INIT(ACPI_LV_VALUES),
+	ACPI_DEBUG_INIT(ACPI_LV_OBJECTS),
+	ACPI_DEBUG_INIT(ACPI_LV_RESOURCES),
+	ACPI_DEBUG_INIT(ACPI_LV_USER_REQUESTS),
+	ACPI_DEBUG_INIT(ACPI_LV_PACKAGE),
+
+	ACPI_DEBUG_INIT(ACPI_LV_ALLOCATIONS),
+	ACPI_DEBUG_INIT(ACPI_LV_FUNCTIONS),
+	ACPI_DEBUG_INIT(ACPI_LV_OPTIMIZATIONS),
+
+	ACPI_DEBUG_INIT(ACPI_LV_MUTEX),
+	ACPI_DEBUG_INIT(ACPI_LV_THREADS),
+	ACPI_DEBUG_INIT(ACPI_LV_IO),
+	ACPI_DEBUG_INIT(ACPI_LV_INTERRUPTS),
+
+	ACPI_DEBUG_INIT(ACPI_LV_AML_DISASSEMBLE),
+	ACPI_DEBUG_INIT(ACPI_LV_VERBOSE_INFO),
+	ACPI_DEBUG_INIT(ACPI_LV_FULL_TABLES),
+	ACPI_DEBUG_INIT(ACPI_LV_EVENTS),             
+};
+#define NUM_OF(v)	( sizeof(v)/sizeof(v[0]) )
+
 static int
 acpi_system_read_debug (
 	char			*page,
@@ -24,16 +100,41 @@
 {
 	char			*p = page;
 	int 			size = 0;
+	int			i;
 
 	if (off != 0)
 		goto end;
 
+	p += sprintf(p, "%-25s\tHex        SET\n", "Description");
+
 	switch ((unsigned long) data) {
 	case 0:
-		p += sprintf(p, "0x%08x\n", acpi_dbg_layer);
+		for (i = 0; i < NUM_OF(acpi_debug_layers); i++) {
+			p += sprintf(p, "%-25s\t0x%08lX [%c]\n",
+				acpi_debug_layers[i].name,
+				acpi_debug_layers[i].value,
+				(acpi_dbg_layer & acpi_debug_layers[i].value) ?
+				'*' : ' ');
+		}
+		p += sprintf(p, "%-25s\t0x%08X [%c]\n", "ACPI_ALL_DRIVERS",
+			ACPI_ALL_DRIVERS,
+			(acpi_dbg_layer & ACPI_ALL_DRIVERS) == ACPI_ALL_DRIVERS?
+			'*' : (acpi_dbg_layer & ACPI_ALL_DRIVERS) == 0 ?
+			' ' : '-');
+		p += sprintf(p,
+			"--\ndebug_layer = 0x%08X (* = enabled, - = partial)\n",
+			acpi_dbg_layer);
 		break;
 	case 1:
-		p += sprintf(p, "0x%08x\n", acpi_dbg_level);
+		for (i = 0; i < NUM_OF(acpi_debug_levels); i++) {
+			p += sprintf(p, "%-25s\t0x%08lX [%c]\n",
+				acpi_debug_levels[i].name,
+				acpi_debug_levels[i].value,
+				(acpi_dbg_level & acpi_debug_levels[i].value) ?
+				'*' : ' ');
+		}
+		p += sprintf(p, "--\ndebug_level = 0x%08X (* = enabled)\n",
+				acpi_dbg_level);
 		break;
 	default:
 		p += sprintf(p, "Invalid debug option\n");
diff -Nru a/drivers/acpi/dispatcher/dsmethod.c b/drivers/acpi/dispatcher/dsmethod.c
--- a/drivers/acpi/dispatcher/dsmethod.c	2004-10-18 14:56:31 -07:00
+++ b/drivers/acpi/dispatcher/dsmethod.c	2004-10-18 14:56:31 -07:00
@@ -58,15 +58,12 @@
  *
  * FUNCTION:    acpi_ds_parse_method
  *
- * PARAMETERS:  obj_handle      - Node of the method
- *              Level           - Current nesting level
- *              Context         - Points to a method counter
- *              return_value    - Not used
+ * PARAMETERS:  obj_handle      - Method node
  *
  * RETURN:      Status
  *
- * DESCRIPTION: Call the parser and parse the AML that is
- *              associated with the method.
+ * DESCRIPTION: Call the parser and parse the AML that is associated with the
+ *              method.
  *
  * MUTEX:       Assumes parser is locked
  *
@@ -145,8 +142,9 @@
 		return_ACPI_STATUS (AE_NO_MEMORY);
 	}
 
-	status = acpi_ds_init_aml_walk (walk_state, op, node, obj_desc->method.aml_start,
-			  obj_desc->method.aml_length, NULL, NULL, 1);
+	status = acpi_ds_init_aml_walk (walk_state, op, node,
+			  obj_desc->method.aml_start,
+			  obj_desc->method.aml_length, NULL, 1);
 	if (ACPI_FAILURE (status)) {
 		acpi_ds_delete_walk_state (walk_state);
 		return_ACPI_STATUS (status);
@@ -190,8 +188,6 @@
  *              increments the thread count, and waits at the method semaphore
  *              for clearance to execute.
  *
- * MUTEX:       Locks/unlocks parser.
- *
  ******************************************************************************/
 
 acpi_status
@@ -250,7 +246,8 @@
  *
  * FUNCTION:    acpi_ds_call_control_method
  *
- * PARAMETERS:  walk_state          - Current state of the walk
+ * PARAMETERS:  Thread              - Info for this thread
+ *              this_walk_state     - Current walk state
  *              Op                  - Current Op to be walked
  *
  * RETURN:      Status
@@ -267,8 +264,9 @@
 {
 	acpi_status                     status;
 	struct acpi_namespace_node      *method_node;
-	union acpi_operand_object       *obj_desc;
 	struct acpi_walk_state          *next_walk_state;
+	union acpi_operand_object       *obj_desc;
+	struct acpi_parameter_info      info;
 	u32                             i;
 
 
@@ -309,7 +307,6 @@
 			return_ACPI_STATUS (AE_NO_MEMORY);
 		}
 
-
 		/* Create and init a Root Node */
 
 		op = acpi_ps_create_scope_op ();
@@ -320,7 +317,7 @@
 
 		status = acpi_ds_init_aml_walk (next_walk_state, op, method_node,
 				  obj_desc->method.aml_start, obj_desc->method.aml_length,
-				  NULL, NULL, 1);
+				  NULL, 1);
 		if (ACPI_FAILURE (status)) {
 			acpi_ds_delete_walk_state (next_walk_state);
 			goto cleanup;
@@ -348,9 +345,12 @@
 	 */
 	this_walk_state->operands [this_walk_state->num_operands] = NULL;
 
+	info.parameters = &this_walk_state->operands[0];
+	info.parameter_type = ACPI_PARAM_ARGS;
+
 	status = acpi_ds_init_aml_walk (next_walk_state, NULL, method_node,
 			  obj_desc->method.aml_start, obj_desc->method.aml_length,
-			  &this_walk_state->operands[0], NULL, 3);
+			  &info, 3);
 	if (ACPI_FAILURE (status)) {
 		goto cleanup;
 	}
@@ -382,7 +382,7 @@
 	/* On error, we must delete the new walk state */
 
 cleanup:
-	if (next_walk_state->method_desc) {
+	if (next_walk_state && (next_walk_state->method_desc)) {
 		/* Decrement the thread count on the method parse tree */
 
 	   next_walk_state->method_desc->method.thread_count--;
@@ -397,12 +397,13 @@
  *
  * FUNCTION:    acpi_ds_restart_control_method
  *
- * PARAMETERS:  walk_state          - State of the method when it was preempted
- *              Op                  - Pointer to new current op
+ * PARAMETERS:  walk_state          - State for preempted method (caller)
+ *              return_desc         - Return value from the called method
  *
  * RETURN:      Status
  *
- * DESCRIPTION: Restart a method that was preempted
+ * DESCRIPTION: Restart a method that was preempted by another (nested) method
+ *              invocation.  Handle the return value (if any) from the callee.
  *
  ******************************************************************************/
 
@@ -417,17 +418,35 @@
 	ACPI_FUNCTION_TRACE_PTR ("ds_restart_control_method", walk_state);
 
 
+	ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH,
+		"****Restart [%4.4s] Op %p return_value_from_callee %p\n",
+		(char *) &walk_state->method_node->name, walk_state->method_call_op,
+		return_desc));
+
+	ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH,
+		"    return_from_this_method_used?=%X res_stack %p Walk %p\n",
+		walk_state->return_used,
+		walk_state->results, walk_state));
+
+	/* Did the called method return a value? */
+
 	if (return_desc) {
+		/* Are we actually going to use the return value? */
+
 		if (walk_state->return_used) {
-			/*
-			 * Get the return value (if any) from the previous method.
-			 * NULL if no return value
-			 */
+			/* Save the return value from the previous method */
+
 			status = acpi_ds_result_push (return_desc, walk_state);
 			if (ACPI_FAILURE (status)) {
 				acpi_ut_remove_reference (return_desc);
 				return_ACPI_STATUS (status);
 			}
+
+			/*
+			 * Save as THIS method's return value in case it is returned
+			 * immediately to yet another method
+			 */
+			walk_state->return_desc = return_desc;
 		}
 		else {
 			/*
@@ -437,11 +456,6 @@
 			acpi_ut_remove_reference (return_desc);
 		}
 	}
-
-	ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH,
-		"Method=%p Return=%p return_used?=%X res_stack=%p State=%p\n",
-		walk_state->method_call_op, return_desc, walk_state->return_used,
-		walk_state->results, walk_state));
 
 	return_ACPI_STATUS (AE_OK);
 }
diff -Nru a/drivers/acpi/dispatcher/dsmthdat.c b/drivers/acpi/dispatcher/dsmthdat.c
--- a/drivers/acpi/dispatcher/dsmthdat.c	2004-10-18 14:56:28 -07:00
+++ b/drivers/acpi/dispatcher/dsmthdat.c	2004-10-18 14:56:28 -07:00
@@ -656,11 +656,13 @@
 						new_obj_desc, current_obj_desc));
 
 				/*
-				 * Store this object to the Node
-				 * (perform the indirect store)
+				 * Store this object to the Node (perform the indirect store)
+				 * NOTE: No implicit conversion is performed, as per the ACPI
+				 * specification rules on storing to Locals/Args.
 				 */
 				status = acpi_ex_store_object_to_node (new_obj_desc,
-						 current_obj_desc->reference.object, walk_state);
+						 current_obj_desc->reference.object, walk_state,
+						 ACPI_NO_IMPLICIT_CONVERSION);
 
 				/* Remove local reference if we copied the object above */
 
diff -Nru a/drivers/acpi/dispatcher/dsopcode.c b/drivers/acpi/dispatcher/dsopcode.c
--- a/drivers/acpi/dispatcher/dsopcode.c	2004-10-18 14:56:49 -07:00
+++ b/drivers/acpi/dispatcher/dsopcode.c	2004-10-18 14:56:49 -07:00
@@ -79,7 +79,6 @@
 	acpi_status                     status;
 	union acpi_parse_object         *op;
 	struct acpi_walk_state          *walk_state;
-	union acpi_parse_object         *arg;
 
 
 	ACPI_FUNCTION_TRACE ("ds_execute_arguments");
@@ -105,7 +104,7 @@
 	}
 
 	status = acpi_ds_init_aml_walk (walk_state, op, NULL, aml_start,
-			  aml_length, NULL, NULL, 1);
+			  aml_length, NULL, 1);
 	if (ACPI_FAILURE (status)) {
 		acpi_ds_delete_walk_state (walk_state);
 		return_ACPI_STATUS (status);
@@ -126,9 +125,7 @@
 
 	/* Get and init the Op created above */
 
-	arg = op->common.value.arg;
 	op->common.node = node;
-	arg->common.node = node;
 	acpi_ps_delete_parse_tree (op);
 
 	/* Evaluate the deferred arguments */
@@ -150,7 +147,7 @@
 	/* Execute the opcode and arguments */
 
 	status = acpi_ds_init_aml_walk (walk_state, op, NULL, aml_start,
-			  aml_length, NULL, NULL, 3);
+			  aml_length, NULL, 3);
 	if (ACPI_FAILURE (status)) {
 		acpi_ds_delete_walk_state (walk_state);
 		return_ACPI_STATUS (status);
diff -Nru a/drivers/acpi/dispatcher/dsutils.c b/drivers/acpi/dispatcher/dsutils.c
--- a/drivers/acpi/dispatcher/dsutils.c	2004-10-18 14:56:29 -07:00
+++ b/drivers/acpi/dispatcher/dsutils.c	2004-10-18 14:56:29 -07:00
@@ -60,11 +60,10 @@
  *
  * FUNCTION:    acpi_ds_is_result_used
  *
- * PARAMETERS:  Op
- *              result_obj
- *              walk_state
+ * PARAMETERS:  Op                  - Current Op
+ *              walk_state          - Current State
  *
- * RETURN:      Status
+ * RETURN:      TRUE if result is used, FALSE otherwise
  *
  * DESCRIPTION: Check if a result object will be used by the parent
  *
@@ -89,18 +88,39 @@
 	}
 
 	/*
-	 * If there is no parent, the result can't possibly be used!
-	 * (An executing method typically has no parent, since each
-	 * method is parsed separately)  However, a method that is
-	 * invoked from another method has a parent.
+	 * If there is no parent, we are executing at the method level.
+	 * An executing method typically has no parent, since each method
+	 * is parsed separately.
 	 */
 	if (!op->common.parent) {
+		/*
+		 * If this is the last statement in the method, we know it is not a
+		 * Return() operator (would not come here.) The following code is the
+		 * optional support for a so-called "implicit return". Some AML code
+		 * assumes that the last value of the method is "implicitly" returned
+		 * to the caller. Just save the last result as the return value.
+		 * NOTE: this is optional because the ASL language does not actually
+		 * support this behavior.
+		 */
+		if ((acpi_gbl_enable_interpreter_slack) &&
+			(walk_state->parser_state.aml >= walk_state->parser_state.aml_end)) {
+			ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH,
+					"Result of [%s] will be implicitly returned\n",
+					acpi_ps_get_opcode_name (op->common.aml_opcode)));
+
+			/* Use the top of the result stack as the implicit return value */
+
+			walk_state->return_desc = walk_state->results->results.obj_desc[0];
+			return_VALUE (TRUE);
+		}
+
+		/* No parent, the return value cannot possibly be used */
+
 		return_VALUE (FALSE);
 	}
 
-	/*
-	 * Get info on the parent.  The root Op is AML_SCOPE
-	 */
+	/* Get info on the parent. The root_op is AML_SCOPE */
+
 	parent_info = acpi_ps_get_opcode_info (op->common.parent->common.aml_opcode);
 	if (parent_info->class == AML_CLASS_UNKNOWN) {
 		ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Unknown parent opcode. Op=%p\n", op));
@@ -204,9 +224,9 @@
  *
  * FUNCTION:    acpi_ds_delete_result_if_not_used
  *
- * PARAMETERS:  Op
- *              result_obj
- *              walk_state
+ * PARAMETERS:  Op              - Current parse Op
+ *              result_obj      - Result of the operation
+ *              walk_state      - Current state
  *
  * RETURN:      Status
  *
@@ -338,8 +358,9 @@
  *
  * FUNCTION:    acpi_ds_create_operand
  *
- * PARAMETERS:  walk_state
- *              Arg
+ * PARAMETERS:  walk_state      - Current walk state
+ *              Arg             - Parse object for the argument
+ *              arg_index       - Which argument (zero based)
  *
  * RETURN:      Status
  *
diff -Nru a/drivers/acpi/dispatcher/dswload.c b/drivers/acpi/dispatcher/dswload.c
--- a/drivers/acpi/dispatcher/dswload.c	2004-10-18 14:55:54 -07:00
+++ b/drivers/acpi/dispatcher/dswload.c	2004-10-18 14:55:54 -07:00
@@ -50,6 +50,9 @@
 #include <acpi/acnamesp.h>
 #include <acpi/acevents.h>
 
+#ifdef _ACPI_ASL_COMPILER
+#include <acpi/acdisasm.h>
+#endif
 
 #define _COMPONENT          ACPI_DISPATCHER
 	 ACPI_MODULE_NAME    ("dswload")
@@ -180,7 +183,17 @@
 		status = acpi_ns_lookup (walk_state->scope_info, path, object_type,
 				  ACPI_IMODE_EXECUTE, ACPI_NS_SEARCH_PARENT, walk_state, &(node));
 		if (ACPI_FAILURE (status)) {
+#ifdef _ACPI_ASL_COMPILER
+			if (status == AE_NOT_FOUND) {
+				acpi_dm_add_to_external_list (path);
+				status = AE_OK;
+			}
+			else {
+				ACPI_REPORT_NSERROR (path, status);
+			}
+#else
 			ACPI_REPORT_NSERROR (path, status);
+#endif
 			return (status);
 		}
 
@@ -529,7 +542,16 @@
 		status = acpi_ns_lookup (walk_state->scope_info, buffer_ptr, object_type,
 				  ACPI_IMODE_EXECUTE, ACPI_NS_SEARCH_PARENT, walk_state, &(node));
 		if (ACPI_FAILURE (status)) {
+#ifdef _ACPI_ASL_COMPILER
+			if (status == AE_NOT_FOUND) {
+				status = AE_OK;
+			}
+			else {
+				ACPI_REPORT_NSERROR (buffer_ptr, status);
+			}
+#else
 			ACPI_REPORT_NSERROR (buffer_ptr, status);
+#endif
 			return_ACPI_STATUS (status);
 		}
 		/*
diff -Nru a/drivers/acpi/dispatcher/dswstate.c b/drivers/acpi/dispatcher/dswstate.c
--- a/drivers/acpi/dispatcher/dswstate.c	2004-10-18 14:56:50 -07:00
+++ b/drivers/acpi/dispatcher/dswstate.c	2004-10-18 14:56:50 -07:00
@@ -906,8 +906,7 @@
 	struct acpi_namespace_node      *method_node,
 	u8                              *aml_start,
 	u32                             aml_length,
-	union acpi_operand_object       **params,
-	union acpi_operand_object       **return_obj_desc,
+	struct acpi_parameter_info      *info,
 	u32                             pass_number)
 {
 	acpi_status                     status;
@@ -926,8 +925,17 @@
 	/* The next_op of the next_walk will be the beginning of the method */
 
 	walk_state->next_op             = NULL;
-	walk_state->params              = params;
-	walk_state->caller_return_desc  = return_obj_desc;
+
+	if (info) {
+		if (info->parameter_type == ACPI_PARAM_GPE) {
+			walk_state->gpe_event_info = ACPI_CAST_PTR (struct acpi_gpe_event_info,
+					   info->parameters);
+		}
+		else {
+			walk_state->params              = info->parameters;
+			walk_state->caller_return_desc  = &info->return_object;
+		}
+	}
 
 	status = acpi_ps_init_scope (&walk_state->parser_state, op);
 	if (ACPI_FAILURE (status)) {
@@ -949,7 +957,7 @@
 
 		/* Init the method arguments */
 
-		status = acpi_ds_method_data_init_args (params, ACPI_METHOD_NUM_ARGS, walk_state);
+		status = acpi_ds_method_data_init_args (walk_state->params, ACPI_METHOD_NUM_ARGS, walk_state);
 		if (ACPI_FAILURE (status)) {
 			return_ACPI_STATUS (status);
 		}
diff -Nru a/drivers/acpi/ec.c b/drivers/acpi/ec.c
--- a/drivers/acpi/ec.c	2004-10-18 14:56:32 -07:00
+++ b/drivers/acpi/ec.c	2004-10-18 14:56:32 -07:00
@@ -381,7 +381,7 @@
 	acpi_enable_gpe(NULL, ec->gpe_bit, ACPI_NOT_ISR);
 }
 
-static void
+static u32
 acpi_ec_gpe_handler (
 	void			*data)
 {
@@ -389,12 +389,17 @@
 	struct acpi_ec		*ec = (struct acpi_ec *) data;
 
 	if (!ec)
-		return;
+		return ACPI_INTERRUPT_NOT_HANDLED;
 
 	acpi_disable_gpe(NULL, ec->gpe_bit, ACPI_ISR);
 
 	status = acpi_os_queue_for_execution(OSD_PRIORITY_GPE,
 		acpi_ec_gpe_query, ec);
+
+	if (status == AE_OK)
+		return ACPI_INTERRUPT_HANDLED;
+	else
+		return ACPI_INTERRUPT_NOT_HANDLED;
 }
 
 /* --------------------------------------------------------------------------
@@ -729,6 +734,8 @@
 	if (ACPI_FAILURE(status)) {
 		return_VALUE(-ENODEV);
 	}
+	acpi_set_gpe_type (NULL, ec->gpe_bit, ACPI_GPE_TYPE_RUNTIME);
+	acpi_enable_gpe (NULL, ec->gpe_bit, ACPI_NOT_ISR);
 
 	status = acpi_install_address_space_handler (ec->handle,
 			ACPI_ADR_SPACE_EC, &acpi_ec_space_handler,
@@ -814,6 +821,8 @@
 	if (ACPI_FAILURE(status)) {
 		goto error;
 	}
+	acpi_set_gpe_type (NULL, ec_ecdt->gpe_bit, ACPI_GPE_TYPE_RUNTIME);
+	acpi_enable_gpe (NULL, ec_ecdt->gpe_bit, ACPI_NOT_ISR);
 
 	status = acpi_install_address_space_handler (ACPI_ROOT_OBJECT,
 			ACPI_ADR_SPACE_EC, &acpi_ec_space_handler,
diff -Nru a/drivers/acpi/events/evevent.c b/drivers/acpi/events/evevent.c
--- a/drivers/acpi/events/evevent.c	2004-10-18 14:56:50 -07:00
+++ b/drivers/acpi/events/evevent.c	2004-10-18 14:56:50 -07:00
@@ -50,7 +50,7 @@
 
 /*******************************************************************************
  *
- * FUNCTION:    acpi_ev_initialize
+ * FUNCTION:    acpi_ev_initialize_events
  *
  * PARAMETERS:  None
  *
@@ -61,13 +61,13 @@
  ******************************************************************************/
 
 acpi_status
-acpi_ev_initialize (
+acpi_ev_initialize_events (
 	void)
 {
 	acpi_status                     status;
 
 
-	ACPI_FUNCTION_TRACE ("ev_initialize");
+	ACPI_FUNCTION_TRACE ("ev_initialize_events");
 
 
 	/* Make sure we have ACPI tables */
@@ -104,7 +104,7 @@
 
 /*******************************************************************************
  *
- * FUNCTION:    acpi_ev_handler_initialize
+ * FUNCTION:    acpi_ev_install_xrupt_handlers
  *
  * PARAMETERS:  None
  *
@@ -115,13 +115,13 @@
  ******************************************************************************/
 
 acpi_status
-acpi_ev_handler_initialize (
+acpi_ev_install_xrupt_handlers (
 	void)
 {
 	acpi_status                     status;
 
 
-	ACPI_FUNCTION_TRACE ("ev_handler_initialize");
+	ACPI_FUNCTION_TRACE ("ev_install_xrupt_handlers");
 
 
 	/* Install the SCI handler */
diff -Nru a/drivers/acpi/events/evgpe.c b/drivers/acpi/events/evgpe.c
--- a/drivers/acpi/events/evgpe.c	2004-10-18 14:56:33 -07:00
+++ b/drivers/acpi/events/evgpe.c	2004-10-18 14:56:33 -07:00
@@ -51,6 +51,253 @@
 
 /*******************************************************************************
  *
+ * FUNCTION:    acpi_ev_set_gpe_type
+ *
+ * PARAMETERS:  gpe_event_info          - GPE to set
+ *              Type                    - New type
+ *
+ * RETURN:      Status
+ *
+ * DESCRIPTION: Sets the new type for the GPE (wake, run, or wake/run)
+ *
+ ******************************************************************************/
+
+acpi_status
+acpi_ev_set_gpe_type (
+	struct acpi_gpe_event_info      *gpe_event_info,
+	u8                              type)
+{
+	acpi_status                     status;
+
+
+	ACPI_FUNCTION_TRACE ("ev_set_gpe_type");
+
+
+	/* Validate type and update register enable masks */
+
+	switch (type) {
+	case ACPI_GPE_TYPE_WAKE:
+	case ACPI_GPE_TYPE_RUNTIME:
+	case ACPI_GPE_TYPE_WAKE_RUN:
+		break;
+
+	default:
+		return_ACPI_STATUS (AE_BAD_PARAMETER);
+	}
+
+	/* Disable the GPE if currently enabled */
+
+	status = acpi_ev_disable_gpe (gpe_event_info);
+
+	/* Type was validated above */
+
+	gpe_event_info->flags &= ~ACPI_GPE_TYPE_MASK; /* Clear type bits */
+	gpe_event_info->flags |= type;              /* Insert type */
+	return_ACPI_STATUS (status);
+}
+
+
+/*******************************************************************************
+ *
+ * FUNCTION:    acpi_ev_update_gpe_enable_masks
+ *
+ * PARAMETERS:  gpe_event_info          - GPE to update
+ *              Type                    - What to do: ACPI_GPE_DISABLE or
+ *                                        ACPI_GPE_ENABLE
+ *
+ * RETURN:      Status
+ *
+ * DESCRIPTION: Updates GPE register enable masks based on the GPE type
+ *
+ ******************************************************************************/
+
+acpi_status
+acpi_ev_update_gpe_enable_masks (
+	struct acpi_gpe_event_info      *gpe_event_info,
+	u8                              type)
+{
+	struct acpi_gpe_register_info   *gpe_register_info;
+	u8                              register_bit;
+
+
+	ACPI_FUNCTION_TRACE ("ev_update_gpe_enable_masks");
+
+
+	gpe_register_info = gpe_event_info->register_info;
+	if (!gpe_register_info) {
+		return_ACPI_STATUS (AE_NOT_EXIST);
+	}
+	register_bit = gpe_event_info->register_bit;
+
+	/* 1) Disable case.  Simply clear all enable bits */
+
+	if (type == ACPI_GPE_DISABLE) {
+		ACPI_CLEAR_BIT (gpe_register_info->enable_for_wake, register_bit);
+		ACPI_CLEAR_BIT (gpe_register_info->enable_for_run, register_bit);
+		return_ACPI_STATUS (AE_OK);
+	}
+
+	/* 2) Enable case.  Set/Clear the appropriate enable bits */
+
+	switch (gpe_event_info->flags & ACPI_GPE_TYPE_MASK) {
+	case ACPI_GPE_TYPE_WAKE:
+		ACPI_SET_BIT   (gpe_register_info->enable_for_wake, register_bit);
+		ACPI_CLEAR_BIT (gpe_register_info->enable_for_run, register_bit);
+		break;
+
+	case ACPI_GPE_TYPE_RUNTIME:
+		ACPI_CLEAR_BIT (gpe_register_info->enable_for_wake, register_bit);
+		ACPI_SET_BIT   (gpe_register_info->enable_for_run, register_bit);
+		break;
+
+	case ACPI_GPE_TYPE_WAKE_RUN:
+		ACPI_SET_BIT   (gpe_register_info->enable_for_wake, register_bit);
+		ACPI_SET_BIT   (gpe_register_info->enable_for_run, register_bit);
+		break;
+
+	default:
+		return_ACPI_STATUS (AE_BAD_PARAMETER);
+	}
+
+	return_ACPI_STATUS (AE_OK);
+}
+
+
+/*******************************************************************************
+ *
+ * FUNCTION:    acpi_ev_enable_gpe
+ *
+ * PARAMETERS:  gpe_event_info          - GPE to enable
+ *              write_to_hardware       - Enable now, or just mark data structs
+ *                                        (WAKE GPEs should be deferred)
+ *
+ * RETURN:      Status
+ *
+ * DESCRIPTION: Enable a GPE based on the GPE type
+ *
+ ******************************************************************************/
+
+acpi_status
+acpi_ev_enable_gpe (
+	struct acpi_gpe_event_info      *gpe_event_info,
+	u8                              write_to_hardware)
+{
+	acpi_status                     status;
+
+
+	ACPI_FUNCTION_TRACE ("ev_enable_gpe");
+
+
+	/* Make sure HW enable masks are updated */
+
+	status = acpi_ev_update_gpe_enable_masks (gpe_event_info, ACPI_GPE_ENABLE);
+	if (ACPI_FAILURE (status)) {
+		return_ACPI_STATUS (status);
+	}
+
+	/* Mark wake-enabled or HW enable, or both */
+
+	switch (gpe_event_info->flags & ACPI_GPE_TYPE_MASK) {
+	case ACPI_GPE_TYPE_WAKE:
+
+		ACPI_SET_BIT (gpe_event_info->flags, ACPI_GPE_WAKE_ENABLED);
+		break;
+
+	case ACPI_GPE_TYPE_WAKE_RUN:
+
+		ACPI_SET_BIT (gpe_event_info->flags, ACPI_GPE_WAKE_ENABLED);
+
+		/*lint -fallthrough */
+
+	case ACPI_GPE_TYPE_RUNTIME:
+
+		ACPI_SET_BIT (gpe_event_info->flags, ACPI_GPE_RUN_ENABLED);
+
+		if (write_to_hardware) {
+			/* Clear the GPE (of stale events), then enable it */
+
+			status = acpi_hw_clear_gpe (gpe_event_info);
+			if (ACPI_FAILURE (status)) {
+				return_ACPI_STATUS (status);
+			}
+
+			/* Enable the requested runtime GPE */
+
+			status = acpi_hw_write_gpe_enable_reg (gpe_event_info);
+		}
+		break;
+
+	default:
+		return_ACPI_STATUS (AE_BAD_PARAMETER);
+	}
+
+	return_ACPI_STATUS (AE_OK);
+}
+
+
+/*******************************************************************************
+ *
+ * FUNCTION:    acpi_ev_disable_gpe
+ *
+ * PARAMETERS:  gpe_event_info          - GPE to disable
+ *
+ * RETURN:      Status
+ *
+ * DESCRIPTION: Disable a GPE based on the GPE type
+ *
+ ******************************************************************************/
+
+acpi_status
+acpi_ev_disable_gpe (
+	struct acpi_gpe_event_info      *gpe_event_info)
+{
+	acpi_status                     status;
+
+
+	ACPI_FUNCTION_TRACE ("ev_disable_gpe");
+
+
+	if (!(gpe_event_info->flags & ACPI_GPE_ENABLE_MASK)) {
+		return_ACPI_STATUS (AE_OK);
+	}
+
+	/* Make sure HW enable masks are updated */
+
+	status = acpi_ev_update_gpe_enable_masks (gpe_event_info, ACPI_GPE_DISABLE);
+	if (ACPI_FAILURE (status)) {
+		return_ACPI_STATUS (status);
+	}
+
+	/* Mark wake-disabled or HW disable, or both */
+
+	switch (gpe_event_info->flags & ACPI_GPE_TYPE_MASK) {
+	case ACPI_GPE_TYPE_WAKE:
+		ACPI_CLEAR_BIT (gpe_event_info->flags, ACPI_GPE_WAKE_ENABLED);
+		break;
+
+	case ACPI_GPE_TYPE_WAKE_RUN:
+		ACPI_CLEAR_BIT (gpe_event_info->flags, ACPI_GPE_WAKE_ENABLED);
+
+		/*lint -fallthrough */
+
+	case ACPI_GPE_TYPE_RUNTIME:
+
+		/* Disable the requested runtime GPE */
+
+		ACPI_CLEAR_BIT (gpe_event_info->flags, ACPI_GPE_RUN_ENABLED);
+		status = acpi_hw_write_gpe_enable_reg (gpe_event_info);
+		break;
+
+	default:
+		return_ACPI_STATUS (AE_BAD_PARAMETER);
+	}
+
+	return_ACPI_STATUS (AE_OK);
+}
+
+
+/*******************************************************************************
+ *
  * FUNCTION:    acpi_ev_get_gpe_event_info
  *
  * PARAMETERS:  gpe_device          - Device node.  NULL for GPE0/GPE1
@@ -139,11 +386,12 @@
 	u32                             int_status = ACPI_INTERRUPT_NOT_HANDLED;
 	u8                              enabled_status_byte;
 	struct acpi_gpe_register_info   *gpe_register_info;
-	u32                             in_value;
+	u32                             status_reg;
+	u32                             enable_reg;
 	acpi_status                     status;
 	struct acpi_gpe_block_info      *gpe_block;
-	u32                             i;
-	u32                             j;
+	acpi_native_uint                i;
+	acpi_native_uint                j;
 
 
 	ACPI_FUNCTION_NAME ("ev_gpe_detect");
@@ -171,33 +419,32 @@
 
 			/* Read the Status Register */
 
-			status = acpi_hw_low_level_read (ACPI_GPE_REGISTER_WIDTH, &in_value,
+			status = acpi_hw_low_level_read (ACPI_GPE_REGISTER_WIDTH, &status_reg,
 					 &gpe_register_info->status_address);
-			gpe_register_info->status = (u8) in_value;
 			if (ACPI_FAILURE (status)) {
 				goto unlock_and_exit;
 			}
 
 			/* Read the Enable Register */
 
-			status = acpi_hw_low_level_read (ACPI_GPE_REGISTER_WIDTH, &in_value,
+			status = acpi_hw_low_level_read (ACPI_GPE_REGISTER_WIDTH, &enable_reg,
 					 &gpe_register_info->enable_address);
-			gpe_register_info->enable = (u8) in_value;
 			if (ACPI_FAILURE (status)) {
 				goto unlock_and_exit;
 			}
 
 			ACPI_DEBUG_PRINT ((ACPI_DB_INTERRUPTS,
 				"GPE pair: Status %8.8X%8.8X = %02X, Enable %8.8X%8.8X = %02X\n",
-				ACPI_FORMAT_UINT64 (gpe_register_info->status_address.address),
-				gpe_register_info->status,
-				ACPI_FORMAT_UINT64 (gpe_register_info->enable_address.address),
-				gpe_register_info->enable));
+				ACPI_FORMAT_UINT64 (
+					gpe_register_info->status_address.address),
+					status_reg,
+				ACPI_FORMAT_UINT64 (
+					gpe_register_info->enable_address.address),
+					enable_reg));
 
 			/* First check if there is anything active at all in this register */
 
-			enabled_status_byte = (u8) (gpe_register_info->status &
-					   gpe_register_info->enable);
+			enabled_status_byte = (u8) (status_reg & enable_reg);
 			if (!enabled_status_byte) {
 				/* No active GPEs in this register, move on */
 
@@ -216,7 +463,7 @@
 					 */
 					int_status |= acpi_ev_gpe_dispatch (
 							  &gpe_block->event_info[(i * ACPI_GPE_REGISTER_WIDTH) + j],
-							  j + gpe_register_info->base_gpe_number);
+							  (u32) j + gpe_register_info->base_gpe_number);
 				}
 			}
 		}
@@ -255,6 +502,7 @@
 	u32                             gpe_number = 0;
 	acpi_status                     status;
 	struct acpi_gpe_event_info      local_gpe_event_info;
+	struct acpi_parameter_info      info;
 
 
 	ACPI_FUNCTION_TRACE ("ev_asynch_execute_gpe_method");
@@ -272,6 +520,10 @@
 		return_VOID;
 	}
 
+	/* Set the GPE flags for return to enabled state */
+
+	(void) acpi_ev_enable_gpe (gpe_event_info, FALSE);
+
 	/*
 	 * Take a snapshot of the GPE info for this level - we copy the
 	 * info to prevent a race condition with remove_handler/remove_block.
@@ -283,23 +535,33 @@
 		return_VOID;
 	}
 
-	if (local_gpe_event_info.method_node) {
+	/*
+	 * Must check for control method type dispatch one more
+	 * time to avoid race with ev_gpe_install_handler
+	 */
+	if ((local_gpe_event_info.flags & ACPI_GPE_DISPATCH_MASK) == ACPI_GPE_DISPATCH_METHOD) {
 		/*
-		 * Invoke the GPE Method (_Lxx, _Exx):
-		 * (Evaluate the _Lxx/_Exx control method that corresponds to this GPE.)
+		 * Invoke the GPE Method (_Lxx, _Exx) i.e., evaluate the _Lxx/_Exx
+		 * control method that corresponds to this GPE
 		 */
-		status = acpi_ns_evaluate_by_handle (local_gpe_event_info.method_node, NULL, NULL);
+		info.node = local_gpe_event_info.dispatch.method_node;
+		info.parameters = ACPI_CAST_PTR (union acpi_operand_object *, gpe_event_info);
+		info.parameter_type = ACPI_PARAM_GPE;
+
+		status = acpi_ns_evaluate_by_handle (&info);
 		if (ACPI_FAILURE (status)) {
-			ACPI_REPORT_ERROR (("%s while evaluating method [%4.4s] for GPE[%2X]\n",
+			ACPI_REPORT_ERROR ((
+				"%s while evaluating method [%4.4s] for GPE[%2X]\n",
 				acpi_format_exception (status),
-				acpi_ut_get_node_name (local_gpe_event_info.method_node), gpe_number));
+				acpi_ut_get_node_name (local_gpe_event_info.dispatch.method_node),
+				gpe_number));
 		}
 	}
 
 	if ((local_gpe_event_info.flags & ACPI_GPE_XRUPT_TYPE_MASK) == ACPI_GPE_LEVEL_TRIGGERED) {
 		/*
-		 * GPE is level-triggered, we clear the GPE status bit after handling
-		 * the event.
+		 * GPE is level-triggered, we clear the GPE status bit after
+		 * handling the event.
 		 */
 		status = acpi_hw_clear_gpe (&local_gpe_event_info);
 		if (ACPI_FAILURE (status)) {
@@ -309,7 +571,7 @@
 
 	/* Enable this GPE */
 
-	(void) acpi_hw_enable_gpe (&local_gpe_event_info);
+	(void) acpi_hw_write_gpe_enable_reg (&local_gpe_event_info);
 	return_VOID;
 }
 
@@ -354,6 +616,15 @@
 		}
 	}
 
+	/* Save current system state */
+
+	if (acpi_gbl_system_awake_and_running) {
+		ACPI_SET_BIT (gpe_event_info->flags, ACPI_GPE_SYSTEM_RUNNING);
+	}
+	else {
+		ACPI_CLEAR_BIT (gpe_event_info->flags, ACPI_GPE_SYSTEM_RUNNING);
+	}
+
 	/*
 	 * Dispatch the GPE to either an installed handler, or the control
 	 * method associated with this GPE (_Lxx or _Exx).
@@ -361,10 +632,15 @@
 	 * If there is neither a handler nor a method, we disable the level to
 	 * prevent further events from coming in here.
 	 */
-	if (gpe_event_info->handler) {
-		/* Invoke the installed handler (at interrupt level) */
+	switch (gpe_event_info->flags & ACPI_GPE_DISPATCH_MASK) {
+	case ACPI_GPE_DISPATCH_HANDLER:
 
-		gpe_event_info->handler (gpe_event_info->context);
+		/*
+		 * Invoke the installed handler (at interrupt level)
+		 * Ignore return status for now.  TBD: leave GPE disabled on error?
+		 */
+		(void) gpe_event_info->dispatch.handler->address (
+				  gpe_event_info->dispatch.handler->context);
 
 		/* It is now safe to clear level-triggered events. */
 
@@ -377,13 +653,15 @@
 				return_VALUE (ACPI_INTERRUPT_NOT_HANDLED);
 			}
 		}
-	}
-	else if (gpe_event_info->method_node) {
+		break;
+
+	case ACPI_GPE_DISPATCH_METHOD:
+
 		/*
 		 * Disable GPE, so it doesn't keep firing before the method has a
 		 * chance to run.
 		 */
-		status = acpi_hw_disable_gpe (gpe_event_info);
+		status = acpi_ev_disable_gpe (gpe_event_info);
 		if (ACPI_FAILURE (status)) {
 			ACPI_REPORT_ERROR ((
 				"acpi_ev_gpe_dispatch: Unable to disable GPE[%2X]\n",
@@ -402,8 +680,10 @@
 				"acpi_ev_gpe_dispatch: Unable to queue handler for GPE[%2X], event is disabled\n",
 				gpe_number));
 		}
-	}
-	else {
+		break;
+
+	default:
+
 		/* No handler or method to run! */
 
 		ACPI_REPORT_ERROR ((
@@ -414,15 +694,68 @@
 		 * Disable the GPE.  The GPE will remain disabled until the ACPI
 		 * Core Subsystem is restarted, or a handler is installed.
 		 */
-		status = acpi_hw_disable_gpe (gpe_event_info);
+		status = acpi_ev_disable_gpe (gpe_event_info);
 		if (ACPI_FAILURE (status)) {
 			ACPI_REPORT_ERROR ((
 				"acpi_ev_gpe_dispatch: Unable to disable GPE[%2X]\n",
 				gpe_number));
 			return_VALUE (ACPI_INTERRUPT_NOT_HANDLED);
 		}
+		break;
 	}
 
 	return_VALUE (ACPI_INTERRUPT_HANDLED);
 }
+
+
+#ifdef ACPI_GPE_NOTIFY_CHECK
+
+/*******************************************************************************
+ * TBD: NOT USED, PROTOTYPE ONLY AND WILL PROBABLY BE REMOVED
+ *
+ * FUNCTION:    acpi_ev_check_for_wake_only_gpe
+ *
+ * PARAMETERS:  gpe_event_info  - info for this GPE
+ *
+ * RETURN:      Status
+ *
+ * DESCRIPTION: Determine if a a GPE is "wake-only".
+ *
+ *              Called from Notify() code in interpreter when a "device_wake"
+ *              Notify comes in.
+ *
+ ******************************************************************************/
+
+acpi_status
+acpi_ev_check_for_wake_only_gpe (
+	struct acpi_gpe_event_info      *gpe_event_info)
+{
+	acpi_status                     status;
+
+
+	ACPI_FUNCTION_TRACE ("ev_check_for_wake_only_gpe");
+
+
+	if ((gpe_event_info) &&  /* Only >0 for _Lxx/_Exx */
+	   ((gpe_event_info->flags & ACPI_GPE_SYSTEM_MASK) == ACPI_GPE_SYSTEM_RUNNING)) /* System state at GPE time */ {
+		/* This must be a wake-only GPE, disable it */
+
+		status = acpi_ev_disable_gpe (gpe_event_info);
+
+		/* Set GPE to wake-only.  Do not change wake disabled/enabled status */
+
+		acpi_ev_set_gpe_type (gpe_event_info, ACPI_GPE_TYPE_WAKE);
+
+		ACPI_REPORT_INFO (("GPE %p was updated from wake/run to wake-only\n",
+				gpe_event_info));
+
+		/* This was a wake-only GPE */
+
+		return_ACPI_STATUS (AE_WAKE_ONLY_GPE);
+	}
+
+	return_ACPI_STATUS (AE_OK);
+}
+#endif
+
 
diff -Nru a/drivers/acpi/events/evgpeblk.c b/drivers/acpi/events/evgpeblk.c
--- a/drivers/acpi/events/evgpeblk.c	2004-10-18 14:56:32 -07:00
+++ b/drivers/acpi/events/evgpeblk.c	2004-10-18 14:56:32 -07:00
@@ -53,7 +53,7 @@
  *
  * FUNCTION:    acpi_ev_valid_gpe_event
  *
- * PARAMETERS:  gpe_event_info - Info for this GPE
+ * PARAMETERS:  gpe_event_info              - Info for this GPE
  *
  * RETURN:      TRUE if the gpe_event is valid
  *
@@ -105,17 +105,18 @@
  * FUNCTION:    acpi_ev_walk_gpe_list
  *
  * PARAMETERS:  gpe_walk_callback   - Routine called for each GPE block
+ *              Flags               - ACPI_NOT_ISR or ACPI_ISR
  *
  * RETURN:      Status
  *
  * DESCRIPTION: Walk the GPE lists.
- *              FUNCTION MUST BE CALLED WITH INTERRUPTS DISABLED
  *
  ******************************************************************************/
 
 acpi_status
 acpi_ev_walk_gpe_list (
-	ACPI_GPE_CALLBACK       gpe_walk_callback)
+	ACPI_GPE_CALLBACK       gpe_walk_callback,
+	u32                             flags)
 {
 	struct acpi_gpe_block_info      *gpe_block;
 	struct acpi_gpe_xrupt_info      *gpe_xrupt_info;
@@ -125,7 +126,7 @@
 	ACPI_FUNCTION_TRACE ("ev_walk_gpe_list");
 
 
-	acpi_os_acquire_lock (acpi_gbl_gpe_lock, ACPI_ISR);
+	acpi_os_acquire_lock (acpi_gbl_gpe_lock, flags);
 
 	/* Walk the interrupt level descriptor list */
 
@@ -149,11 +150,58 @@
 	}
 
 unlock_and_exit:
-	acpi_os_release_lock (acpi_gbl_gpe_lock, ACPI_ISR);
+	acpi_os_release_lock (acpi_gbl_gpe_lock, flags);
 	return_ACPI_STATUS (status);
 }
 
 
+/******************************************************************************
+ *
+ * FUNCTION:    acpi_ev_delete_gpe_handlers
+ *
+ * PARAMETERS:  gpe_xrupt_info      - GPE Interrupt info
+ *              gpe_block           - Gpe Block info
+ *
+ * RETURN:      Status
+ *
+ * DESCRIPTION: Delete all Handler objects found in the GPE data structs.
+ *              Used only prior to termination.
+ *
+ ******************************************************************************/
+
+acpi_status
+acpi_ev_delete_gpe_handlers (
+	struct acpi_gpe_xrupt_info      *gpe_xrupt_info,
+	struct acpi_gpe_block_info      *gpe_block)
+{
+	struct acpi_gpe_event_info      *gpe_event_info;
+	acpi_native_uint                i;
+	acpi_native_uint                j;
+
+
+	ACPI_FUNCTION_TRACE ("ev_delete_gpe_handlers");
+
+
+	/* Examine each GPE Register within the block */
+
+	for (i = 0; i < gpe_block->register_count; i++) {
+		/* Now look at the individual GPEs in this byte register */
+
+		for (j = 0; j < ACPI_GPE_REGISTER_WIDTH; j++) {
+			gpe_event_info = &gpe_block->event_info[(i * ACPI_GPE_REGISTER_WIDTH) + j];
+
+			if ((gpe_event_info->flags & ACPI_GPE_DISPATCH_MASK) == ACPI_GPE_DISPATCH_HANDLER) {
+				ACPI_MEM_FREE (gpe_event_info->dispatch.handler);
+				gpe_event_info->dispatch.handler = NULL;
+				gpe_event_info->flags &= ~ACPI_GPE_DISPATCH_MASK;
+			}
+		}
+	}
+
+	return_ACPI_STATUS (AE_OK);
+}
+
+
 /*******************************************************************************
  *
  * FUNCTION:    acpi_ev_save_method_info
@@ -188,6 +236,7 @@
 	u32                             gpe_number;
 	char                            name[ACPI_NAME_SIZE + 1];
 	u8                              type;
+	acpi_status                     status;
 
 
 	ACPI_FUNCTION_TRACE ("ev_save_method_info");
@@ -206,16 +255,16 @@
 	 * 2) Edge/Level determination is based on the 2nd character
 	 *    of the method name
 	 *
-	 * NOTE: Default GPE type is RUNTIME.  May be changed later to WAKE if a
-	 * _PRW object is found that points to this GPE.
+	 * NOTE: Default GPE type is RUNTIME.  May be changed later to WAKE
+	 * if a _PRW object is found that points to this GPE.
 	 */
 	switch (name[1]) {
 	case 'L':
-		type = ACPI_GPE_LEVEL_TRIGGERED | ACPI_GPE_TYPE_RUNTIME;
+		type = ACPI_GPE_LEVEL_TRIGGERED;
 		break;
 
 	case 'E':
-		type = ACPI_GPE_EDGE_TRIGGERED | ACPI_GPE_TYPE_RUNTIME;
+		type = ACPI_GPE_EDGE_TRIGGERED;
 		break;
 
 	default:
@@ -253,27 +302,35 @@
 
 	/*
 	 * Now we can add this information to the gpe_event_info block
-	 * for use during dispatch of this GPE.
+	 * for use during dispatch of this GPE.  Default type is RUNTIME, although
+	 * this may change when the _PRW methods are executed later.
 	 */
 	gpe_event_info = &gpe_block->event_info[gpe_number - gpe_block->block_base_number];
 
-	gpe_event_info->flags    = type;
-	gpe_event_info->method_node = (struct acpi_namespace_node *) obj_handle;
+	gpe_event_info->flags = (u8) (type | ACPI_GPE_DISPATCH_METHOD |
+			   ACPI_GPE_TYPE_RUNTIME);
+
+	gpe_event_info->dispatch.method_node = (struct acpi_namespace_node *) obj_handle;
+
+	/* Update enable mask, but don't enable the HW GPE as of yet */
+
+	status = acpi_ev_enable_gpe (gpe_event_info, FALSE);
 
 	ACPI_DEBUG_PRINT ((ACPI_DB_LOAD,
 		"Registered GPE method %s as GPE number 0x%.2X\n",
 		name, gpe_number));
-	return_ACPI_STATUS (AE_OK);
+	return_ACPI_STATUS (status);
 }
 
 
 /*******************************************************************************
  *
- * FUNCTION:    acpi_ev_get_gpe_type
+ * FUNCTION:    acpi_ev_match_prw_and_gpe
  *
  * PARAMETERS:  Callback from walk_namespace
  *
- * RETURN:      Status
+ * RETURN:      Status.  NOTE: We ignore errors so that the _PRW walk is
+ *              not aborted on a single _PRW failure.
  *
  * DESCRIPTION: Called from acpi_walk_namespace. Expects each object to be a
  *              Device.  Run the _PRW method.  If present, extract the GPE
@@ -282,7 +339,7 @@
  ******************************************************************************/
 
 static acpi_status
-acpi_ev_get_gpe_type (
+acpi_ev_match_prw_and_gpe (
 	acpi_handle                     obj_handle,
 	u32                             level,
 	void                            *info,
@@ -299,19 +356,18 @@
 	acpi_status                     status;
 
 
-	ACPI_FUNCTION_TRACE ("ev_get_gpe_type");
+	ACPI_FUNCTION_TRACE ("ev_match_prw_and_gpe");
 
 
 	/* Check for a _PRW method under this device */
 
 	status = acpi_ut_evaluate_object (obj_handle, METHOD_NAME__PRW,
 			 ACPI_BTYPE_PACKAGE, &pkg_desc);
-	if (status == AE_NOT_FOUND) {
+	if (ACPI_FAILURE (status)) {
+		/* Ignore all errors from _PRW, we don't want to abort the subsystem */
+
 		return_ACPI_STATUS (AE_OK);
 	}
-	else if (ACPI_FAILURE (status)) {
-		return_ACPI_STATUS (status);
-	}
 
 	/* The returned _PRW package must have at least two elements */
 
@@ -370,16 +426,21 @@
 	if ((gpe_device == target_gpe_device) &&
 		(gpe_number >= gpe_block->block_base_number) &&
 		(gpe_number < gpe_block->block_base_number + (gpe_block->register_count * 8))) {
-		/* Mark GPE for WAKE but DISABLED (even for wake) */
-
 		gpe_event_info = &gpe_block->event_info[gpe_number - gpe_block->block_base_number];
-		gpe_event_info->flags |= ACPI_GPE_TYPE_WAKE;
+
+		/* Mark GPE for WAKE-ONLY but WAKE_DISABLED */
+
+		gpe_event_info->flags &= ~(ACPI_GPE_WAKE_ENABLED | ACPI_GPE_RUN_ENABLED);
+		status = acpi_ev_set_gpe_type (gpe_event_info, ACPI_GPE_TYPE_WAKE);
+		if (ACPI_FAILURE (status)) {
+			goto cleanup;
+		}
+		status = acpi_ev_update_gpe_enable_masks (gpe_event_info, ACPI_GPE_DISABLE);
 	}
 
 cleanup:
 	acpi_ut_remove_reference (pkg_desc);
-
-	return_ACPI_STATUS (status);
+	return_ACPI_STATUS (AE_OK);
 }
 
 
@@ -742,7 +803,7 @@
 		/* Init the event_info for each GPE within this register */
 
 		for (j = 0; j < ACPI_GPE_REGISTER_WIDTH; j++) {
-			this_event->bit_mask = acpi_gbl_decode_to8bit[j];
+			this_event->register_bit = acpi_gbl_decode_to8bit[j];
 			this_event->register_info = this_register;
 			this_event++;
 		}
@@ -817,6 +878,7 @@
 	acpi_status                     status;
 	struct acpi_gpe_walk_info       gpe_info;
 
+
 	ACPI_FUNCTION_TRACE ("ev_create_gpe_block");
 
 
@@ -835,6 +897,7 @@
 
 	gpe_block->register_count = register_count;
 	gpe_block->block_base_number = gpe_block_base_number;
+	gpe_block->node           = gpe_device;
 
 	ACPI_MEMCPY (&gpe_block->block_address, gpe_block_address, sizeof (struct acpi_generic_address));
 
@@ -854,18 +917,6 @@
 		return_ACPI_STATUS (status);
 	}
 
-	/* Dump info about this GPE block */
-
-	ACPI_DEBUG_PRINT ((ACPI_DB_INIT,
-		"GPE %02d to %02d [%4.4s] %d regs at %8.8X%8.8X on int %d\n",
-		gpe_block->block_base_number,
-		(u32) (gpe_block->block_base_number +
-				((gpe_block->register_count * ACPI_GPE_REGISTER_WIDTH) -1)),
-		gpe_device->name.ascii,
-		gpe_block->register_count,
-		ACPI_FORMAT_UINT64 (gpe_block->block_address.address),
-		interrupt_level));
-
 	/* Find all GPE methods (_Lxx, _Exx) for this block */
 
 	status = acpi_ns_walk_namespace (ACPI_TYPE_METHOD, gpe_device,
@@ -873,27 +924,28 @@
 			  gpe_block, NULL);
 
 	/*
-	 * Runtime option: Should Wake GPEs be enabled at runtime?  The default is
-	 * No,they should only be enabled just as the machine goes to sleep.
+	 * Runtime option: Should Wake GPEs be enabled at runtime?  The default
+	 * is No,they should only be enabled just as the machine goes to sleep.
 	 */
 	if (acpi_gbl_leave_wake_gpes_disabled) {
 		/*
-		 * Differentiate RUNTIME vs WAKE GPEs, via the _PRW control methods. (Each
-		 * GPE that has one or more _PRWs that reference it is by definition a
-		 * WAKE GPE and will not be enabled while the machine is running.)
+		 * Differentiate RUNTIME vs WAKE GPEs, via the _PRW control methods.
+		 * (Each GPE that has one or more _PRWs that reference it is by
+		 * definition a WAKE GPE and will not be enabled while the machine
+		 * is running.)
 		 */
 		gpe_info.gpe_block = gpe_block;
 		gpe_info.gpe_device = gpe_device;
 
 		status = acpi_ns_walk_namespace (ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT,
-				  ACPI_UINT32_MAX, ACPI_NS_WALK_UNLOCK, acpi_ev_get_gpe_type,
+				  ACPI_UINT32_MAX, ACPI_NS_WALK_UNLOCK, acpi_ev_match_prw_and_gpe,
 				  &gpe_info, NULL);
 	}
 
 	/*
-	 * Enable all GPEs in this block that are 1) "runtime" GPEs, and 2) have
-	 * a corresponding _Lxx or _Exx method.  All other GPEs must be enabled via
-	 * the acpi_enable_gpe() external interface.
+	 * Enable all GPEs in this block that are 1) "runtime" or "run/wake" GPEs,
+	 * and 2) have a corresponding _Lxx or _Exx method.  All other GPEs must
+	 * be enabled via the acpi_enable_gpe() external interface.
 	 */
 	wake_gpe_count = 0;
 	gpe_enabled_count = 0;
@@ -903,23 +955,35 @@
 			/* Get the info block for this particular GPE */
 
 			gpe_event_info = &gpe_block->event_info[(i * ACPI_GPE_REGISTER_WIDTH) + j];
-			if ((gpe_event_info->method_node) &&
-			   ((gpe_event_info->flags & ACPI_GPE_TYPE_MASK) == ACPI_GPE_TYPE_RUNTIME)) {
-				/* Enable this GPE, it is 1) RUNTIME and 2) has an _Lxx or _Exx method */
-
-				status = acpi_hw_enable_gpe (gpe_event_info);
-				if (ACPI_FAILURE (status)) {
-					return_ACPI_STATUS (status);
-				}
+
+			if (((gpe_event_info->flags & ACPI_GPE_DISPATCH_MASK) == ACPI_GPE_DISPATCH_METHOD) &&
+				 (gpe_event_info->flags & ACPI_GPE_TYPE_RUNTIME)) {
 				gpe_enabled_count++;
 			}
 
-			if ((gpe_event_info->flags & ACPI_GPE_TYPE_MASK) == ACPI_GPE_TYPE_WAKE) {
+			if (gpe_event_info->flags & ACPI_GPE_TYPE_WAKE) {
 				wake_gpe_count++;
 			}
 		}
 	}
 
+	/* Dump info about this GPE block */
+
+	ACPI_DEBUG_PRINT ((ACPI_DB_INIT,
+		"GPE %02X to %02X [%4.4s] %u regs at %8.8X%8.8X on int 0x%X\n",
+		(u32) gpe_block->block_base_number,
+		(u32) (gpe_block->block_base_number +
+				((gpe_block->register_count * ACPI_GPE_REGISTER_WIDTH) -1)),
+		gpe_device->name.ascii,
+		gpe_block->register_count,
+		ACPI_FORMAT_UINT64 (gpe_block->block_address.address),
+		interrupt_level));
+
+
+	/* Enable all valid GPEs found above */
+
+	status = acpi_hw_enable_runtime_gpe_block (NULL, gpe_block);
+
 	ACPI_DEBUG_PRINT ((ACPI_DB_INIT,
 			"Found %u Wake, Enabled %u Runtime GPEs in this block\n",
 			wake_gpe_count, gpe_enabled_count));
@@ -1056,7 +1120,8 @@
 	if ((register_count0 + register_count1) == 0) {
 		/* GPEs are not required by ACPI, this is OK */
 
-		ACPI_REPORT_INFO (("There are no GPE blocks defined in the FADT\n"));
+		ACPI_DEBUG_PRINT ((ACPI_DB_INIT,
+				"There are no GPE blocks defined in the FADT\n"));
 		status = AE_OK;
 		goto cleanup;
 	}
diff -Nru a/drivers/acpi/events/evmisc.c b/drivers/acpi/events/evmisc.c
--- a/drivers/acpi/events/evmisc.c	2004-10-18 14:56:33 -07:00
+++ b/drivers/acpi/events/evmisc.c	2004-10-18 14:56:33 -07:00
@@ -88,9 +88,10 @@
  *
  * FUNCTION:    acpi_ev_queue_notify_request
  *
- * PARAMETERS:
+ * PARAMETERS:  Node            - NS node for the notified object
+ *              notify_value    - Value from the Notify() request
  *
- * RETURN:      None.
+ * RETURN:      Status
  *
  * DESCRIPTION: Dispatch a device notification event to a previously
  *              installed handler.
@@ -139,14 +140,12 @@
 				acpi_notify_value_names[notify_value]));
 	}
 	else {
-		ACPI_DEBUG_PRINT ((ACPI_DB_INFO,
-				"notify value: 0x%2.2x **Device Specific**\n",
+		ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Notify value: 0x%2.2X **Device Specific**\n",
 				notify_value));
 	}
 
-	/*
-	 * Get the notify object attached to the NS Node
-	 */
+	/* Get the notify object attached to the NS Node */
+
 	obj_desc = acpi_ns_get_attached_object (node);
 	if (obj_desc) {
 		/* We have the notify object, Get the right handler */
@@ -194,11 +193,13 @@
 	}
 
 	if (!handler_obj) {
-		/* There is no per-device notify handler for this device */
-
+		/*
+		 * There is no per-device notify handler for this device.
+		 * This may or may not be a problem.
+		 */
 		ACPI_DEBUG_PRINT ((ACPI_DB_INFO,
-			"No notify handler for [%4.4s] node %p\n",
-			acpi_ut_get_node_name (node), node));
+			"No notify handler for Notify(%4.4s, %X) node %p\n",
+			acpi_ut_get_node_name (node), notify_value, node));
 	}
 
 	return (status);
@@ -209,7 +210,7 @@
  *
  * FUNCTION:    acpi_ev_notify_dispatch
  *
- * PARAMETERS:
+ * PARAMETERS:  Context         - To be passsed to the notify handler
  *
  * RETURN:      None.
  *
@@ -276,6 +277,8 @@
  *
  * FUNCTION:    acpi_ev_global_lock_thread
  *
+ * PARAMETERS:  Context         - From thread interface, not used
+ *
  * RETURN:      None
  *
  * DESCRIPTION: Invoked by SCI interrupt handler upon acquisition of the
@@ -309,7 +312,9 @@
  *
  * FUNCTION:    acpi_ev_global_lock_handler
  *
- * RETURN:      Status
+ * PARAMETERS:  Context         - From thread interface, not used
+ *
+ * RETURN:      ACPI_INTERRUPT_HANDLED or ACPI_INTERRUPT_NOT_HANDLED
  *
  * DESCRIPTION: Invoked directly from the SCI handler when a global lock
  *              release interrupt occurs.  Grab the global lock and queue
@@ -356,6 +361,8 @@
  *
  * FUNCTION:    acpi_ev_init_global_lock_handler
  *
+ * PARAMETERS:  None
+ *
  * RETURN:      Status
  *
  * DESCRIPTION: Install a handler for the global lock release event
@@ -395,6 +402,8 @@
  *
  * FUNCTION:    acpi_ev_acquire_global_lock
  *
+ * PARAMETERS:  Timeout         - Max time to wait for the lock, in millisec.
+ *
  * RETURN:      Status
  *
  * DESCRIPTION: Attempt to gain ownership of the Global Lock.
@@ -462,6 +471,10 @@
  *
  * FUNCTION:    acpi_ev_release_global_lock
  *
+ * PARAMETERS:  None
+ *
+ * RETURN:      Status
+ *
  * DESCRIPTION: Releases ownership of the Global Lock.
  *
  ******************************************************************************/
@@ -548,7 +561,7 @@
 
 		/* Disable all GPEs in all GPE blocks */
 
-		status = acpi_ev_walk_gpe_list (acpi_hw_disable_gpe_block);
+		status = acpi_ev_walk_gpe_list (acpi_hw_disable_gpe_block, ACPI_NOT_ISR);
 
 		/* Remove SCI handler */
 
@@ -557,6 +570,10 @@
 			ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Could not remove SCI handler\n"));
 		}
 	}
+
+	/* Deallocate all handler objects installed within GPE info structs */
+
+	status = acpi_ev_walk_gpe_list (acpi_ev_delete_gpe_handlers, ACPI_NOT_ISR);
 
 	/* Return to original mode if necessary */
 
diff -Nru a/drivers/acpi/events/evregion.c b/drivers/acpi/events/evregion.c
--- a/drivers/acpi/events/evregion.c	2004-10-18 14:56:48 -07:00
+++ b/drivers/acpi/events/evregion.c	2004-10-18 14:56:48 -07:00
@@ -61,7 +61,7 @@
 
 /*******************************************************************************
  *
- * FUNCTION:    acpi_ev_init_address_spaces
+ * FUNCTION:    acpi_ev_install_region_handlers
  *
  * PARAMETERS:  None
  *
@@ -72,15 +72,20 @@
  ******************************************************************************/
 
 acpi_status
-acpi_ev_init_address_spaces (
+acpi_ev_install_region_handlers (
 	void) {
 	acpi_status                     status;
 	acpi_native_uint                i;
 
 
-	ACPI_FUNCTION_TRACE ("ev_init_address_spaces");
+	ACPI_FUNCTION_TRACE ("ev_install_region_handlers");
 
 
+	status = acpi_ut_acquire_mutex (ACPI_MTX_NAMESPACE);
+	if (ACPI_FAILURE (status)) {
+		return_ACPI_STATUS (status);
+	}
+
 	/*
 	 * All address spaces (PCI Config, EC, SMBus) are scope dependent
 	 * and registration must occur for a specific device.
@@ -99,9 +104,8 @@
 	 * has already been installed (via acpi_install_address_space_handler).
 	 * Similar for AE_SAME_HANDLER.
 	 */
-
 	for (i = 0; i < ACPI_NUM_DEFAULT_SPACES; i++) {
-		status = acpi_install_address_space_handler ((acpi_handle) acpi_gbl_root_node,
+		status = acpi_ev_install_space_handler (acpi_gbl_root_node,
 				  acpi_gbl_default_address_spaces[i],
 				  ACPI_DEFAULT_HANDLER, NULL, NULL);
 		switch (status) {
@@ -111,15 +115,63 @@
 
 			/* These exceptions are all OK */
 
+			status = AE_OK;
 			break;
 
 		default:
 
-			return_ACPI_STATUS (status);
+			goto unlock_and_exit;
 		}
 	}
 
-	return_ACPI_STATUS (AE_OK);
+unlock_and_exit:
+	(void) acpi_ut_release_mutex (ACPI_MTX_NAMESPACE);
+	return_ACPI_STATUS (status);
+}
+
+
+/*******************************************************************************
+ *
+ * FUNCTION:    acpi_ev_initialize_op_regions
+ *
+ * PARAMETERS:  None
+ *
+ * RETURN:      Status
+ *
+ * DESCRIPTION: Execute _REG methods for all Operation Regions that have
+ *              an installed default region handler.
+ *
+ ******************************************************************************/
+
+acpi_status
+acpi_ev_initialize_op_regions (
+	void)
+{
+	acpi_status                     status;
+	acpi_native_uint                i;
+
+
+	ACPI_FUNCTION_TRACE ("ev_initialize_op_regions");
+
+
+	status = acpi_ut_acquire_mutex (ACPI_MTX_NAMESPACE);
+	if (ACPI_FAILURE (status)) {
+		return_ACPI_STATUS (status);
+	}
+
+	/*
+	 * Run the _REG methods for op_regions in each default address space
+	 */
+	for (i = 0; i < ACPI_NUM_DEFAULT_SPACES; i++) {
+		/* TBD: Make sure handler is the DEFAULT handler, otherwise
+		 * _REG will have already been run.
+		 */
+		status = acpi_ev_execute_reg_methods (acpi_gbl_root_node,
+				  acpi_gbl_default_address_spaces[i]);
+	}
+
+	(void) acpi_ut_release_mutex (ACPI_MTX_NAMESPACE);
+	return_ACPI_STATUS (status);
 }
 
 
@@ -128,7 +180,7 @@
  * FUNCTION:    acpi_ev_execute_reg_method
  *
  * PARAMETERS:  region_obj          - Object structure
- *              Function            - On (1) or Off (0)
+ *              Function            - Passed to _REG:  On (1) or Off (0)
  *
  * RETURN:      Status
  *
@@ -138,11 +190,12 @@
 
 acpi_status
 acpi_ev_execute_reg_method (
-	union acpi_operand_object      *region_obj,
+	union acpi_operand_object       *region_obj,
 	u32                             function)
 {
-	union acpi_operand_object      *params[3];
-	union acpi_operand_object      *region_obj2;
+	struct acpi_parameter_info      info;
+	union acpi_operand_object       *params[3];
+	union acpi_operand_object       *region_obj2;
 	acpi_status                     status;
 
 
@@ -159,10 +212,11 @@
 	}
 
 	/*
-	 * _REG method has two arguments
-	 * Arg0:   Integer: Operation region space ID
+	 * The _REG method has two arguments:
+	 *
+	 * Arg0, Integer: Operation region space ID
 	 *          Same value as region_obj->Region.space_id
-	 * Arg1:   Integer: connection status
+	 * Arg1, Integer: connection status
 	 *          1 for connecting the handler,
 	 *          0 for disconnecting the handler
 	 *          Passed as a parameter
@@ -178,16 +232,21 @@
 		goto cleanup;
 	}
 
-	/* Set up the parameter objects */
+	/* Setup the parameter objects */
 
 	params[0]->integer.value = region_obj->region.space_id;
 	params[1]->integer.value = function;
 	params[2] = NULL;
 
+	info.node = region_obj2->extra.method_REG;
+	info.parameters = params;
+	info.parameter_type = ACPI_PARAM_ARGS;
+
 	/* Execute the method, no return value */
 
-	ACPI_DEBUG_EXEC(acpi_ut_display_init_pathname (ACPI_TYPE_METHOD, region_obj2->extra.method_REG, NULL));
-	status = acpi_ns_evaluate_by_handle (region_obj2->extra.method_REG, params, NULL);
+	ACPI_DEBUG_EXEC (acpi_ut_display_init_pathname (
+			   ACPI_TYPE_METHOD, info.node, NULL));
+	status = acpi_ns_evaluate_by_handle (&info);
 
 	acpi_ut_remove_reference (params[1]);
 
@@ -203,7 +262,6 @@
  * FUNCTION:    acpi_ev_address_space_dispatch
  *
  * PARAMETERS:  region_obj          - Internal region object
- *              space_id            - ID of the address space (0-255)
  *              Function            - Read or Write operation
  *              Address             - Where in the space to read or write
  *              bit_width           - Field width in bits (8, 16, 32, or 64)
@@ -326,7 +384,7 @@
 		ACPI_FORMAT_UINT64 (address),
 		acpi_ut_get_region_name (region_obj->region.space_id)));
 
-	if (!(handler_desc->address_space.flags & ACPI_ADDR_HANDLER_DEFAULT_INSTALLED)) {
+	if (!(handler_desc->address_space.hflags & ACPI_ADDR_HANDLER_DEFAULT_INSTALLED)) {
 		/*
 		 * For handlers other than the default (supplied) handlers, we must
 		 * exit the interpreter because the handler *might* block -- we don't
@@ -347,7 +405,7 @@
 			acpi_format_exception (status)));
 	}
 
-	if (!(handler_desc->address_space.flags & ACPI_ADDR_HANDLER_DEFAULT_INSTALLED)) {
+	if (!(handler_desc->address_space.hflags & ACPI_ADDR_HANDLER_DEFAULT_INSTALLED)) {
 		/*
 		 * We just returned from a non-default handler, we must re-enter the
 		 * interpreter
@@ -366,8 +424,8 @@
  *
  * FUNCTION:    acpi_ev_detach_region
  *
- * PARAMETERS:  region_obj      - Region Object
- *              acpi_ns_is_locked - Namespace Region Already Locked?
+ * PARAMETERS:  region_obj          - Region Object
+ *              acpi_ns_is_locked   - Namespace Region Already Locked?
  *
  * RETURN:      None
  *
@@ -501,9 +559,9 @@
  *
  * FUNCTION:    acpi_ev_attach_region
  *
- * PARAMETERS:  handler_obj     - Handler Object
- *              region_obj      - Region Object
- *              acpi_ns_is_locked - Namespace Region Already Locked?
+ * PARAMETERS:  handler_obj         - Handler Object
+ *              region_obj          - Region Object
+ *              acpi_ns_is_locked   - Namespace Region Already Locked?
  *
  * RETURN:      None
  *
@@ -676,6 +734,273 @@
 	return (status);
 }
 
+
+/*******************************************************************************
+ *
+ * FUNCTION:    acpi_ev_install_space_handler
+ *
+ * PARAMETERS:  Node            - Namespace node for the device
+ *              space_id        - The address space ID
+ *              Handler         - Address of the handler
+ *              Setup           - Address of the setup function
+ *              Context         - Value passed to the handler on each access
+ *
+ * RETURN:      Status
+ *
+ * DESCRIPTION: Install a handler for all op_regions of a given space_id.
+ *              Assumes namespace is locked
+ *
+ ******************************************************************************/
+
+acpi_status
+acpi_ev_install_space_handler (
+	struct acpi_namespace_node      *node,
+	acpi_adr_space_type             space_id,
+	acpi_adr_space_handler          handler,
+	acpi_adr_space_setup            setup,
+	void                            *context)
+{
+	union acpi_operand_object       *obj_desc;
+	union acpi_operand_object       *handler_obj;
+	acpi_status                     status;
+	acpi_object_type                type;
+	u16                             flags = 0;
+
+
+	ACPI_FUNCTION_TRACE ("ev_install_space_handler");
+
+
+	/*
+	 * This registration is valid for only the types below
+	 * and the root.  This is where the default handlers
+	 * get placed.
+	 */
+	if ((node->type != ACPI_TYPE_DEVICE)     &&
+		(node->type != ACPI_TYPE_PROCESSOR)  &&
+		(node->type != ACPI_TYPE_THERMAL)    &&
+		(node != acpi_gbl_root_node)) {
+		status = AE_BAD_PARAMETER;
+		goto unlock_and_exit;
+	}
+
+	if (handler == ACPI_DEFAULT_HANDLER) {
+		flags = ACPI_ADDR_HANDLER_DEFAULT_INSTALLED;
+
+		switch (space_id) {
+		case ACPI_ADR_SPACE_SYSTEM_MEMORY:
+			handler = acpi_ex_system_memory_space_handler;
+			setup   = acpi_ev_system_memory_region_setup;
+			break;
+
+		case ACPI_ADR_SPACE_SYSTEM_IO:
+			handler = acpi_ex_system_io_space_handler;
+			setup   = acpi_ev_io_space_region_setup;
+			break;
+
+		case ACPI_ADR_SPACE_PCI_CONFIG:
+			handler = acpi_ex_pci_config_space_handler;
+			setup   = acpi_ev_pci_config_region_setup;
+			break;
+
+		case ACPI_ADR_SPACE_CMOS:
+			handler = acpi_ex_cmos_space_handler;
+			setup   = acpi_ev_cmos_region_setup;
+			break;
+
+		case ACPI_ADR_SPACE_PCI_BAR_TARGET:
+			handler = acpi_ex_pci_bar_space_handler;
+			setup   = acpi_ev_pci_bar_region_setup;
+			break;
+
+		case ACPI_ADR_SPACE_DATA_TABLE:
+			handler = acpi_ex_data_table_space_handler;
+			setup   = NULL;
+			break;
+
+		default:
+			status = AE_BAD_PARAMETER;
+			goto unlock_and_exit;
+		}
+	}
+
+	/* If the caller hasn't specified a setup routine, use the default */
+
+	if (!setup) {
+		setup = acpi_ev_default_region_setup;
+	}
+
+	/* Check for an existing internal object */
+
+	obj_desc = acpi_ns_get_attached_object (node);
+	if (obj_desc) {
+		/*
+		 * The attached device object already exists.
+		 * Make sure the handler is not already installed.
+		 */
+		handler_obj = obj_desc->device.handler;
+
+		/* Walk the handler list for this device */
+
+		while (handler_obj) {
+			/* Same space_id indicates a handler already installed */
+
+			if (handler_obj->address_space.space_id == space_id) {
+				if (handler_obj->address_space.handler == handler) {
+					/*
+					 * It is (relatively) OK to attempt to install the SAME
+					 * handler twice. This can easily happen with PCI_Config space.
+					 */
+					status = AE_SAME_HANDLER;
+					goto unlock_and_exit;
+				}
+				else {
+					/* A handler is already installed */
+
+					status = AE_ALREADY_EXISTS;
+				}
+				goto unlock_and_exit;
+			}
+
+			/* Walk the linked list of handlers */
+
+			handler_obj = handler_obj->address_space.next;
+		}
+	}
+	else {
+		ACPI_DEBUG_PRINT ((ACPI_DB_OPREGION,
+			"Creating object on Device %p while installing handler\n", node));
+
+		/* obj_desc does not exist, create one */
+
+		if (node->type == ACPI_TYPE_ANY) {
+			type = ACPI_TYPE_DEVICE;
+		}
+		else {
+			type = node->type;
+		}
+
+		obj_desc = acpi_ut_create_internal_object (type);
+		if (!obj_desc) {
+			status = AE_NO_MEMORY;
+			goto unlock_and_exit;
+		}
+
+		/* Init new descriptor */
+
+		obj_desc->common.type = (u8) type;
+
+		/* Attach the new object to the Node */
+
+		status = acpi_ns_attach_object (node, obj_desc, type);
+
+		/* Remove local reference to the object */
+
+		acpi_ut_remove_reference (obj_desc);
+
+		if (ACPI_FAILURE (status)) {
+			goto unlock_and_exit;
+		}
+	}
+
+	ACPI_DEBUG_PRINT ((ACPI_DB_OPREGION,
+		"Installing address handler for region %s(%X) on Device %4.4s %p(%p)\n",
+		acpi_ut_get_region_name (space_id), space_id,
+		acpi_ut_get_node_name (node), node, obj_desc));
+
+	/*
+	 * Install the handler
+	 *
+	 * At this point there is no existing handler.
+	 * Just allocate the object for the handler and link it
+	 * into the list.
+	 */
+	handler_obj = acpi_ut_create_internal_object (ACPI_TYPE_LOCAL_ADDRESS_HANDLER);
+	if (!handler_obj) {
+		status = AE_NO_MEMORY;
+		goto unlock_and_exit;
+	}
+
+	/* Init handler obj */
+
+	handler_obj->address_space.space_id  = (u8) space_id;
+	handler_obj->address_space.hflags    = flags;
+	handler_obj->address_space.region_list = NULL;
+	handler_obj->address_space.node      = node;
+	handler_obj->address_space.handler   = handler;
+	handler_obj->address_space.context   = context;
+	handler_obj->address_space.setup     = setup;
+
+	/* Install at head of Device.address_space list */
+
+	handler_obj->address_space.next      = obj_desc->device.handler;
+
+	/*
+	 * The Device object is the first reference on the handler_obj.
+	 * Each region that uses the handler adds a reference.
+	 */
+	obj_desc->device.handler = handler_obj;
+
+	/*
+	 * Walk the namespace finding all of the regions this
+	 * handler will manage.
+	 *
+	 * Start at the device and search the branch toward
+	 * the leaf nodes until either the leaf is encountered or
+	 * a device is detected that has an address handler of the
+	 * same type.
+	 *
+	 * In either case, back up and search down the remainder
+	 * of the branch
+	 */
+	status = acpi_ns_walk_namespace (ACPI_TYPE_ANY, node, ACPI_UINT32_MAX,
+			  ACPI_NS_WALK_UNLOCK, acpi_ev_install_handler,
+			  handler_obj, NULL);
+
+unlock_and_exit:
+	return_ACPI_STATUS (status);
+}
+
+
+/*******************************************************************************
+ *
+ * FUNCTION:    acpi_ev_execute_reg_methods
+ *
+ * PARAMETERS:  Node            - Namespace node for the device
+ *              space_id        - The address space ID
+ *
+ * RETURN:      Status
+ *
+ * DESCRIPTION: Run all _REG methods for the input Space ID;
+ *              Note: assumes namespace is locked, or system init time.
+ *
+ ******************************************************************************/
+
+acpi_status
+acpi_ev_execute_reg_methods (
+	struct acpi_namespace_node      *node,
+	acpi_adr_space_type             space_id)
+{
+	acpi_status                     status;
+
+
+	ACPI_FUNCTION_TRACE ("ev_execute_reg_methods");
+
+
+	/*
+	 * Run all _REG methods for all Operation Regions for this
+	 * space ID.  This is a separate walk in order to handle any
+	 * interdependencies between regions and _REG methods.  (i.e. handlers
+	 * must be installed for all regions of this Space ID before we
+	 * can run any _REG methods)
+	 */
+	status = acpi_ns_walk_namespace (ACPI_TYPE_ANY, node, ACPI_UINT32_MAX,
+			  ACPI_NS_WALK_UNLOCK, acpi_ev_reg_run,
+			  &space_id, NULL);
+
+	return_ACPI_STATUS (status);
+}
+
+
 /*******************************************************************************
  *
  * FUNCTION:    acpi_ev_reg_run
@@ -693,19 +1018,13 @@
 	void                            *context,
 	void                            **return_value)
 {
-	union acpi_operand_object       *handler_obj;
 	union acpi_operand_object       *obj_desc;
 	struct acpi_namespace_node      *node;
+	acpi_adr_space_type             space_id;
 	acpi_status                     status;
 
 
-	handler_obj = (union acpi_operand_object   *) context;
-
-	/* Parameter validation */
-
-	if (!handler_obj) {
-		return (AE_OK);
-	}
+	space_id = *ACPI_CAST_PTR (acpi_adr_space_type, context);
 
 	/* Convert and validate the device handle */
 
@@ -732,10 +1051,9 @@
 		return (AE_OK);
 	}
 
-
 	/* Object is a Region */
 
-	if (obj_desc->region.space_id != handler_obj->address_space.space_id) {
+	if (obj_desc->region.space_id != space_id) {
 		/*
 		 * This region is for a different address space
 		 * -- just ignore it
diff -Nru a/drivers/acpi/events/evrgnini.c b/drivers/acpi/events/evrgnini.c
--- a/drivers/acpi/events/evrgnini.c	2004-10-18 14:55:54 -07:00
+++ b/drivers/acpi/events/evrgnini.c	2004-10-18 14:55:54 -07:00
@@ -54,7 +54,7 @@
  *
  * FUNCTION:    acpi_ev_system_memory_region_setup
  *
- * PARAMETERS:  region_obj          - Region we are interested in
+ * PARAMETERS:  Handle              - Region we are interested in
  *              Function            - Start or stop
  *              handler_context     - Address space handler context
  *              region_context      - Region specific context
@@ -108,7 +108,7 @@
  *
  * FUNCTION:    acpi_ev_io_space_region_setup
  *
- * PARAMETERS:  region_obj          - Region we are interested in
+ * PARAMETERS:  Handle              - Region we are interested in
  *              Function            - Start or stop
  *              handler_context     - Address space handler context
  *              region_context      - Region specific context
@@ -144,7 +144,7 @@
  *
  * FUNCTION:    acpi_ev_pci_config_region_setup
  *
- * PARAMETERS:  region_obj          - Region we are interested in
+ * PARAMETERS:  Handle             - Region we are interested in
  *              Function            - Start or stop
  *              handler_context     - Address space handler context
  *              region_context      - Region specific context
@@ -317,7 +317,7 @@
  *
  * FUNCTION:    acpi_ev_pci_bar_region_setup
  *
- * PARAMETERS:  region_obj          - Region we are interested in
+ * PARAMETERS:  Handle              - Region we are interested in
  *              Function            - Start or stop
  *              handler_context     - Address space handler context
  *              region_context      - Region specific context
@@ -348,7 +348,7 @@
  *
  * FUNCTION:    acpi_ev_cmos_region_setup
  *
- * PARAMETERS:  region_obj          - Region we are interested in
+ * PARAMETERS:  Handle              - Region we are interested in
  *              Function            - Start or stop
  *              handler_context     - Address space handler context
  *              region_context      - Region specific context
@@ -379,7 +379,7 @@
  *
  * FUNCTION:    acpi_ev_default_region_setup
  *
- * PARAMETERS:  region_obj          - Region we are interested in
+ * PARAMETERS:  Handle              - Region we are interested in
  *              Function            - Start or stop
  *              handler_context     - Address space handler context
  *              region_context      - Region specific context
diff -Nru a/drivers/acpi/events/evxface.c b/drivers/acpi/events/evxface.c
--- a/drivers/acpi/events/evxface.c	2004-10-18 14:56:33 -07:00
+++ b/drivers/acpi/events/evxface.c	2004-10-18 14:56:33 -07:00
@@ -188,6 +188,7 @@
  *              handler_type    - The type of handler:
  *                                  ACPI_SYSTEM_NOTIFY: system_handler (00-7f)
  *                                  ACPI_DEVICE_NOTIFY: driver_handler (80-ff)
+ *                                  ACPI_ALL_NOTIFY:  both system and device
  *              Handler         - Address of the handler
  *              Context         - Value passed to the handler on each GPE
  *
@@ -243,20 +244,21 @@
 	if (device == ACPI_ROOT_OBJECT) {
 		/* Make sure the handler is not already installed */
 
-		if (((handler_type == ACPI_SYSTEM_NOTIFY) &&
-				acpi_gbl_system_notify.handler)        ||
-			((handler_type == ACPI_DEVICE_NOTIFY) &&
+		if (((handler_type & ACPI_SYSTEM_NOTIFY) &&
+				acpi_gbl_system_notify.handler)     ||
+			((handler_type & ACPI_DEVICE_NOTIFY) &&
 				acpi_gbl_device_notify.handler)) {
 			status = AE_ALREADY_EXISTS;
 			goto unlock_and_exit;
 		}
 
-		if (handler_type == ACPI_SYSTEM_NOTIFY) {
+		if (handler_type & ACPI_SYSTEM_NOTIFY) {
 			acpi_gbl_system_notify.node  = node;
 			acpi_gbl_system_notify.handler = handler;
 			acpi_gbl_system_notify.context = context;
 		}
-		else /* ACPI_DEVICE_NOTIFY */ {
+
+		if (handler_type & ACPI_DEVICE_NOTIFY) {
 			acpi_gbl_device_notify.node  = node;
 			acpi_gbl_device_notify.handler = handler;
 			acpi_gbl_device_notify.context = context;
@@ -284,9 +286,9 @@
 		if (obj_desc) {
 			/* Object exists - make sure there's no handler */
 
-			if (((handler_type == ACPI_SYSTEM_NOTIFY) &&
+			if (((handler_type & ACPI_SYSTEM_NOTIFY) &&
 					obj_desc->common_notify.system_notify) ||
-				((handler_type == ACPI_DEVICE_NOTIFY) &&
+				((handler_type & ACPI_DEVICE_NOTIFY) &&
 					obj_desc->common_notify.device_notify)) {
 				status = AE_ALREADY_EXISTS;
 				goto unlock_and_exit;
@@ -308,7 +310,6 @@
 			/* Remove local reference to the object */
 
 			acpi_ut_remove_reference (obj_desc);
-
 			if (ACPI_FAILURE (status)) {
 				goto unlock_and_exit;
 			}
@@ -326,12 +327,19 @@
 		notify_obj->notify.handler = handler;
 		notify_obj->notify.context = context;
 
-		if (handler_type == ACPI_SYSTEM_NOTIFY) {
+		if (handler_type & ACPI_SYSTEM_NOTIFY) {
 			obj_desc->common_notify.system_notify = notify_obj;
 		}
-		else /* ACPI_DEVICE_NOTIFY */ {
+
+		if (handler_type & ACPI_DEVICE_NOTIFY) {
 			obj_desc->common_notify.device_notify = notify_obj;
 		}
+
+		if (handler_type == ACPI_ALL_NOTIFY) {
+			/* Extra ref if installed in both */
+
+			acpi_ut_add_reference (notify_obj);
+		}
 	}
 
 
@@ -349,7 +357,9 @@
  *              handler_type    - The type of handler:
  *                                  ACPI_SYSTEM_NOTIFY: system_handler (00-7f)
  *                                  ACPI_DEVICE_NOTIFY: driver_handler (80-ff)
+ *                                  ACPI_ALL_NOTIFY:  both system and device
  *              Handler         - Address of the handler
+ *
  * RETURN:      Status
  *
  * DESCRIPTION: Remove a handler for notifies on an ACPI device
@@ -392,15 +402,14 @@
 		goto unlock_and_exit;
 	}
 
-	/*
-	 * Root Object
-	 */
+	/* Root Object */
+
 	if (device == ACPI_ROOT_OBJECT) {
 		ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Removing notify handler for ROOT object.\n"));
 
-		if (((handler_type == ACPI_SYSTEM_NOTIFY) &&
-			  !acpi_gbl_system_notify.handler) ||
-			((handler_type == ACPI_DEVICE_NOTIFY) &&
+		if (((handler_type & ACPI_SYSTEM_NOTIFY) &&
+			  !acpi_gbl_system_notify.handler)      ||
+			((handler_type & ACPI_DEVICE_NOTIFY) &&
 			  !acpi_gbl_device_notify.handler)) {
 			status = AE_NOT_EXIST;
 			goto unlock_and_exit;
@@ -415,21 +424,21 @@
 			return_ACPI_STATUS (status);
  		}
 
-		if (handler_type == ACPI_SYSTEM_NOTIFY) {
+		if (handler_type & ACPI_SYSTEM_NOTIFY) {
 			acpi_gbl_system_notify.node  = NULL;
 			acpi_gbl_system_notify.handler = NULL;
 			acpi_gbl_system_notify.context = NULL;
 		}
-		else {
+
+		if (handler_type & ACPI_DEVICE_NOTIFY) {
 			acpi_gbl_device_notify.node  = NULL;
 			acpi_gbl_device_notify.handler = NULL;
 			acpi_gbl_device_notify.context = NULL;
 		}
 	}
 
-	/*
-	 * All Other Objects
-	 */
+	/* All Other Objects */
+
 	else {
 		/* Notifies allowed on this object? */
 
@@ -448,38 +457,47 @@
 
 		/* Object exists - make sure there's an existing handler */
 
-		if (handler_type == ACPI_SYSTEM_NOTIFY) {
+		if (handler_type & ACPI_SYSTEM_NOTIFY) {
 			notify_obj = obj_desc->common_notify.system_notify;
-		}
-		else {
-			notify_obj = obj_desc->common_notify.device_notify;
-		}
+			if ((!notify_obj) ||
+				 (notify_obj->notify.handler != handler)) {
+				status = AE_BAD_PARAMETER;
+				goto unlock_and_exit;
+			}
+			/* Make sure all deferred tasks are completed */
 
-		if ((!notify_obj) ||
-			(notify_obj->notify.handler != handler)) {
-			status = AE_BAD_PARAMETER;
-			goto unlock_and_exit;
-		}
+			(void) acpi_ut_release_mutex (ACPI_MTX_NAMESPACE);
+			acpi_os_wait_events_complete(NULL);
+			status = acpi_ut_acquire_mutex (ACPI_MTX_NAMESPACE);
+			if (ACPI_FAILURE (status)) {
+				return_ACPI_STATUS (status);
+ 			}
 
-		/* Make sure all deferred tasks are completed */
+			/* Remove the handler */
+			obj_desc->common_notify.system_notify = NULL;
+			acpi_ut_remove_reference (notify_obj);
+		}
 
-		(void) acpi_ut_release_mutex (ACPI_MTX_NAMESPACE);
-		acpi_os_wait_events_complete(NULL);
-		status = acpi_ut_acquire_mutex (ACPI_MTX_NAMESPACE);
-		if (ACPI_FAILURE (status)) {
-			return_ACPI_STATUS (status);
- 		}
+		if (handler_type & ACPI_DEVICE_NOTIFY) {
+			notify_obj = obj_desc->common_notify.device_notify;
+			if ((!notify_obj) ||
+				 (notify_obj->notify.handler != handler)) {
+				status = AE_BAD_PARAMETER;
+				goto unlock_and_exit;
+			}
+			/* Make sure all deferred tasks are completed */
 
-		/* Remove the handler */
+			(void) acpi_ut_release_mutex (ACPI_MTX_NAMESPACE);
+			acpi_os_wait_events_complete(NULL);
+			status = acpi_ut_acquire_mutex (ACPI_MTX_NAMESPACE);
+			if (ACPI_FAILURE (status)) {
+				return_ACPI_STATUS (status);
+ 			}
 
-		if (handler_type == ACPI_SYSTEM_NOTIFY) {
-			obj_desc->common_notify.system_notify = NULL;
-		}
-		else {
+			/* Remove the handler */
 			obj_desc->common_notify.device_notify = NULL;
+			acpi_ut_remove_reference (notify_obj);
 		}
-
-		acpi_ut_remove_reference (notify_obj);
 	}
 
 
@@ -497,7 +515,7 @@
  *              gpe_block       - GPE block (NULL == FADT GPEs)
  *              Type            - Whether this GPE should be treated as an
  *                                edge- or level-triggered interrupt.
- *              Handler         - Address of the handler
+ *              Address         - Address of the handler
  *              Context         - Value passed to the handler on each GPE
  *
  * RETURN:      Status
@@ -511,11 +529,12 @@
 	acpi_handle                     gpe_device,
 	u32                             gpe_number,
 	u32                             type,
-	acpi_gpe_handler                handler,
+	acpi_event_handler              address,
 	void                            *context)
 {
-	acpi_status                     status;
 	struct acpi_gpe_event_info      *gpe_event_info;
+	struct acpi_handler_info        *handler;
+	acpi_status                     status;
 
 
 	ACPI_FUNCTION_TRACE ("acpi_install_gpe_handler");
@@ -523,7 +542,7 @@
 
 	/* Parameter validation */
 
-	if (!handler) {
+	if ((!address) || (type > ACPI_GPE_XRUPT_TYPE_MASK)) {
 		return_ACPI_STATUS (AE_BAD_PARAMETER);
 	}
 
@@ -542,27 +561,41 @@
 
 	/* Make sure that there isn't a handler there already */
 
-	if (gpe_event_info->handler) {
+	if ((gpe_event_info->flags & ACPI_GPE_DISPATCH_MASK) == ACPI_GPE_DISPATCH_HANDLER) {
 		status = AE_ALREADY_EXISTS;
 		goto unlock_and_exit;
 	}
 
-	/* Install the handler */
+	/* Allocate and init handler object */
 
-	acpi_os_acquire_lock (acpi_gbl_gpe_lock, ACPI_NOT_ISR);
-	gpe_event_info->handler = handler;
-	gpe_event_info->context = context;
-	gpe_event_info->flags = (u8) type;
-	acpi_os_release_lock (acpi_gbl_gpe_lock, ACPI_NOT_ISR);
+	handler = ACPI_MEM_CALLOCATE (sizeof (struct acpi_handler_info));
+	if (!handler) {
+		status = AE_NO_MEMORY;
+		goto unlock_and_exit;
+	}
 
-	/* Clear the GPE (of stale events), the enable it */
+	handler->address    = address;
+	handler->context    = context;
+	handler->method_node = gpe_event_info->dispatch.method_node;
 
-	status = acpi_hw_clear_gpe (gpe_event_info);
+	/* Disable the GPE before installing the handler */
+
+	status = acpi_ev_disable_gpe (gpe_event_info);
 	if (ACPI_FAILURE (status)) {
 		goto unlock_and_exit;
 	}
 
-	status = acpi_hw_enable_gpe (gpe_event_info);
+	/* Install the handler */
+
+	acpi_os_acquire_lock (acpi_gbl_gpe_lock, ACPI_NOT_ISR);
+	gpe_event_info->dispatch.handler = handler;
+
+	/* Setup up dispatch flags to indicate handler (vs. method) */
+
+	gpe_event_info->flags &= ~(ACPI_GPE_XRUPT_TYPE_MASK | ACPI_GPE_DISPATCH_MASK); /* Clear bits */
+	gpe_event_info->flags |= (u8) (type | ACPI_GPE_DISPATCH_HANDLER);
+
+	acpi_os_release_lock (acpi_gbl_gpe_lock, ACPI_NOT_ISR);
 
 
 unlock_and_exit:
@@ -577,7 +610,7 @@
  *
  * PARAMETERS:  gpe_number      - The event to remove a handler
  *              gpe_block       - GPE block (NULL == FADT GPEs)
- *              Handler         - Address of the handler
+ *              Address         - Address of the handler
  *
  * RETURN:      Status
  *
@@ -589,10 +622,11 @@
 acpi_remove_gpe_handler (
 	acpi_handle                     gpe_device,
 	u32                             gpe_number,
-	acpi_gpe_handler                handler)
+	acpi_event_handler              address)
 {
-	acpi_status                     status;
 	struct acpi_gpe_event_info      *gpe_event_info;
+	struct acpi_handler_info        *handler;
+	acpi_status                     status;
 
 
 	ACPI_FUNCTION_TRACE ("acpi_remove_gpe_handler");
@@ -600,7 +634,7 @@
 
 	/* Parameter validation */
 
-	if (!handler) {
+	if (!address) {
 		return_ACPI_STATUS (AE_BAD_PARAMETER);
 	}
 
@@ -617,21 +651,27 @@
 		goto unlock_and_exit;
 	}
 
-	/* Disable the GPE before removing the handler */
+	/* Make sure that a handler is indeed installed */
 
-	status = acpi_hw_disable_gpe (gpe_event_info);
-	if (ACPI_FAILURE (status)) {
+	if ((gpe_event_info->flags & ACPI_GPE_DISPATCH_MASK) != ACPI_GPE_DISPATCH_HANDLER) {
+		status = AE_NOT_EXIST;
 		goto unlock_and_exit;
 	}
 
 	/* Make sure that the installed handler is the same */
 
-	if (gpe_event_info->handler != handler) {
-		(void) acpi_hw_enable_gpe (gpe_event_info);
+	if (gpe_event_info->dispatch.handler->address != address) {
 		status = AE_BAD_PARAMETER;
 		goto unlock_and_exit;
 	}
 
+	/* Disable the GPE before removing the handler */
+
+	status = acpi_ev_disable_gpe (gpe_event_info);
+	if (ACPI_FAILURE (status)) {
+		goto unlock_and_exit;
+	}
+
 	/* Make sure all deferred tasks are completed */
 
 	(void) acpi_ut_release_mutex (ACPI_MTX_EVENTS);
@@ -644,9 +684,20 @@
 	/* Remove the handler */
 
 	acpi_os_acquire_lock (acpi_gbl_gpe_lock, ACPI_NOT_ISR);
-	gpe_event_info->handler = NULL;
-	gpe_event_info->context = NULL;
+	handler = gpe_event_info->dispatch.handler;
+
+	/* Restore Method node (if any), set dispatch flags */
+
+	gpe_event_info->dispatch.method_node = handler->method_node;
+	gpe_event_info->flags &= ~ACPI_GPE_DISPATCH_MASK; /* Clear bits */
+	if (handler->method_node) {
+		gpe_event_info->flags |= ACPI_GPE_DISPATCH_METHOD;
+	}
 	acpi_os_release_lock (acpi_gbl_gpe_lock, ACPI_NOT_ISR);
+
+	/* Now we can free the handler object */
+
+	ACPI_MEM_FREE (handler);
 
 
 unlock_and_exit:
diff -Nru a/drivers/acpi/events/evxfevnt.c b/drivers/acpi/events/evxfevnt.c
--- a/drivers/acpi/events/evxfevnt.c	2004-10-18 14:56:27 -07:00
+++ b/drivers/acpi/events/evxfevnt.c	2004-10-18 14:56:27 -07:00
@@ -204,12 +204,11 @@
 
 /*******************************************************************************
  *
- * FUNCTION:    acpi_enable_gpe
+ * FUNCTION:    acpi_set_gpe_type
  *
  * PARAMETERS:  gpe_device      - Parent GPE Device
  *              gpe_number      - GPE level within the GPE block
- *              Flags           - Just enable, or also wake enable?
- *                                Called from ISR or not
+ *              Type            - New GPE type
  *
  * RETURN:      Status
  *
@@ -218,26 +217,17 @@
  ******************************************************************************/
 
 acpi_status
-acpi_enable_gpe (
+acpi_set_gpe_type (
 	acpi_handle                     gpe_device,
 	u32                             gpe_number,
-	u32                             flags)
+	u8                              type)
 {
 	acpi_status                     status = AE_OK;
 	struct acpi_gpe_event_info      *gpe_event_info;
 
 
-	ACPI_FUNCTION_TRACE ("acpi_enable_gpe");
-
-
-	/* Use semaphore lock if not executing at interrupt level */
+	ACPI_FUNCTION_TRACE ("acpi_set_gpe_type");
 
-	if (flags & ACPI_NOT_ISR) {
-		status = acpi_ut_acquire_mutex (ACPI_MTX_EVENTS);
-		if (ACPI_FAILURE (status)) {
-			return_ACPI_STATUS (status);
-		}
-	}
 
 	/* Ensure that we have a valid GPE number */
 
@@ -247,91 +237,72 @@
 		goto unlock_and_exit;
 	}
 
-	/* Check for Wake vs Runtime GPE */
-
-	if (flags & ACPI_EVENT_WAKE_ENABLE) {
-		/* Ensure the requested wake GPE is disabled */
-
-		status = acpi_hw_disable_gpe (gpe_event_info);
-		if (ACPI_FAILURE (status)) {
-			goto unlock_and_exit;
-		}
-
-		/* Defer Enable of Wake GPE until sleep time */
-
-		acpi_hw_enable_gpe_for_wakeup (gpe_event_info);
+	if ((gpe_event_info->flags & ACPI_GPE_TYPE_MASK) == type) {
+		return_ACPI_STATUS (AE_OK);
 	}
-	else {
-		/* Enable the requested runtime GPE  */
 
-		status = acpi_hw_enable_gpe (gpe_event_info);
-		if (ACPI_FAILURE (status)) {
-			goto unlock_and_exit;
-		}
-	}
+	/* Set the new type (will disable GPE if currently enabled) */
 
+	status = acpi_ev_set_gpe_type (gpe_event_info, type);
 
 unlock_and_exit:
-	if (flags & ACPI_NOT_ISR) {
-		(void) acpi_ut_release_mutex (ACPI_MTX_EVENTS);
-	}
 	return_ACPI_STATUS (status);
 }
 
 
 /*******************************************************************************
  *
- * FUNCTION:    acpi_disable_event
+ * FUNCTION:    acpi_enable_gpe
  *
- * PARAMETERS:  Event           - The fixed eventto be enabled
- *              Flags           - Reserved
+ * PARAMETERS:  gpe_device      - Parent GPE Device
+ *              gpe_number      - GPE level within the GPE block
+ *              Flags           - Just enable, or also wake enable?
+ *                                Called from ISR or not
  *
  * RETURN:      Status
  *
- * DESCRIPTION: Disable an ACPI event (fixed)
+ * DESCRIPTION: Enable an ACPI event (general purpose)
  *
  ******************************************************************************/
 
 acpi_status
-acpi_disable_event (
-	u32                             event,
+acpi_enable_gpe (
+	acpi_handle                     gpe_device,
+	u32                             gpe_number,
 	u32                             flags)
 {
 	acpi_status                     status = AE_OK;
-	u32                             value;
+	struct acpi_gpe_event_info      *gpe_event_info;
 
 
-	ACPI_FUNCTION_TRACE ("acpi_disable_event");
+	ACPI_FUNCTION_TRACE ("acpi_enable_gpe");
 
 
-	/* Decode the Fixed Event */
+	/* Use semaphore lock if not executing at interrupt level */
 
-	if (event > ACPI_EVENT_MAX) {
-		return_ACPI_STATUS (AE_BAD_PARAMETER);
+	if (flags & ACPI_NOT_ISR) {
+		status = acpi_ut_acquire_mutex (ACPI_MTX_EVENTS);
+		if (ACPI_FAILURE (status)) {
+			return_ACPI_STATUS (status);
+		}
 	}
 
-	/*
-	 * Disable the requested fixed event (by writing a zero to the
-	 * enable register bit)
-	 */
-	status = acpi_set_register (acpi_gbl_fixed_event_info[event].enable_register_id,
-			 0, ACPI_MTX_LOCK);
-	if (ACPI_FAILURE (status)) {
-		return_ACPI_STATUS (status);
-	}
+	/* Ensure that we have a valid GPE number */
 
-	status = acpi_get_register (acpi_gbl_fixed_event_info[event].enable_register_id,
-			 &value, ACPI_MTX_LOCK);
-	if (ACPI_FAILURE (status)) {
-		return_ACPI_STATUS (status);
+	gpe_event_info = acpi_ev_get_gpe_event_info (gpe_device, gpe_number);
+	if (!gpe_event_info) {
+		status = AE_BAD_PARAMETER;
+		goto unlock_and_exit;
 	}
 
-	if (value != 0) {
-		ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
-			"Could not disable %s events\n", acpi_ut_get_event_name (event)));
-		return_ACPI_STATUS (AE_NO_HARDWARE_RESPONSE);
-	}
+	/* Perform the enable */
+
+	status = acpi_ev_enable_gpe (gpe_event_info, TRUE);
 
+unlock_and_exit:
+	if (flags & ACPI_NOT_ISR) {
+		(void) acpi_ut_release_mutex (ACPI_MTX_EVENTS);
+	}
 	return_ACPI_STATUS (status);
 }
 
@@ -342,7 +313,7 @@
  *
  * PARAMETERS:  gpe_device      - Parent GPE Device
  *              gpe_number      - GPE level within the GPE block
- *              Flags           - Just enable, or also wake enable?
+ *              Flags           - Just disable, or also wake disable?
  *                                Called from ISR or not
  *
  * RETURN:      Status
@@ -381,21 +352,69 @@
 		goto unlock_and_exit;
 	}
 
+	status = acpi_ev_disable_gpe (gpe_event_info);
+
+unlock_and_exit:
+	if (flags & ACPI_NOT_ISR) {
+		(void) acpi_ut_release_mutex (ACPI_MTX_EVENTS);
+	}
+	return_ACPI_STATUS (status);
+}
+
+
+/*******************************************************************************
+ *
+ * FUNCTION:    acpi_disable_event
+ *
+ * PARAMETERS:  Event           - The fixed eventto be enabled
+ *              Flags           - Reserved
+ *
+ * RETURN:      Status
+ *
+ * DESCRIPTION: Disable an ACPI event (fixed)
+ *
+ ******************************************************************************/
+
+acpi_status
+acpi_disable_event (
+	u32                             event,
+	u32                             flags)
+{
+	acpi_status                     status = AE_OK;
+	u32                             value;
+
+
+	ACPI_FUNCTION_TRACE ("acpi_disable_event");
+
+
+	/* Decode the Fixed Event */
+
+	if (event > ACPI_EVENT_MAX) {
+		return_ACPI_STATUS (AE_BAD_PARAMETER);
+	}
+
 	/*
-	 * Only disable the requested GPE number for wake if specified.
-	 * Otherwise, turn it totally off
+	 * Disable the requested fixed event (by writing a zero to the
+	 * enable register bit)
 	 */
-	if (flags & ACPI_EVENT_WAKE_DISABLE) {
-		acpi_hw_disable_gpe_for_wakeup (gpe_event_info);
+	status = acpi_set_register (acpi_gbl_fixed_event_info[event].enable_register_id,
+			 0, ACPI_MTX_LOCK);
+	if (ACPI_FAILURE (status)) {
+		return_ACPI_STATUS (status);
 	}
-	else {
-		status = acpi_hw_disable_gpe (gpe_event_info);
+
+	status = acpi_get_register (acpi_gbl_fixed_event_info[event].enable_register_id,
+			 &value, ACPI_MTX_LOCK);
+	if (ACPI_FAILURE (status)) {
+		return_ACPI_STATUS (status);
 	}
 
-unlock_and_exit:
-	if (flags & ACPI_NOT_ISR) {
-		(void) acpi_ut_release_mutex (ACPI_MTX_EVENTS);
+	if (value != 0) {
+		ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
+			"Could not disable %s events\n", acpi_ut_get_event_name (event)));
+		return_ACPI_STATUS (AE_NO_HARDWARE_RESPONSE);
 	}
+
 	return_ACPI_STATUS (status);
 }
 
diff -Nru a/drivers/acpi/events/evxfregn.c b/drivers/acpi/events/evxfregn.c
--- a/drivers/acpi/events/evxfregn.c	2004-10-18 14:56:13 -07:00
+++ b/drivers/acpi/events/evxfregn.c	2004-10-18 14:56:13 -07:00
@@ -46,7 +46,6 @@
 #include <acpi/acpi.h>
 #include <acpi/acnamesp.h>
 #include <acpi/acevents.h>
-#include <acpi/acinterp.h>
 
 #define _COMPONENT          ACPI_EVENTS
 	 ACPI_MODULE_NAME    ("evxfregn")
@@ -76,12 +75,8 @@
 	acpi_adr_space_setup            setup,
 	void                            *context)
 {
-	union acpi_operand_object       *obj_desc;
-	union acpi_operand_object       *handler_obj;
 	struct acpi_namespace_node      *node;
 	acpi_status                     status;
-	acpi_object_type                type;
-	u16                             flags = 0;
 
 
 	ACPI_FUNCTION_TRACE ("acpi_install_address_space_handler");
@@ -106,202 +101,16 @@
 		goto unlock_and_exit;
 	}
 
-	/*
-	 * This registration is valid for only the types below
-	 * and the root.  This is where the default handlers
-	 * get placed.
-	 */
-	if ((node->type != ACPI_TYPE_DEVICE)     &&
-		(node->type != ACPI_TYPE_PROCESSOR)  &&
-		(node->type != ACPI_TYPE_THERMAL)    &&
-		(node != acpi_gbl_root_node)) {
-		status = AE_BAD_PARAMETER;
-		goto unlock_and_exit;
-	}
-
-	if (handler == ACPI_DEFAULT_HANDLER) {
-		flags = ACPI_ADDR_HANDLER_DEFAULT_INSTALLED;
-
-		switch (space_id) {
-		case ACPI_ADR_SPACE_SYSTEM_MEMORY:
-			handler = acpi_ex_system_memory_space_handler;
-			setup   = acpi_ev_system_memory_region_setup;
-			break;
-
-		case ACPI_ADR_SPACE_SYSTEM_IO:
-			handler = acpi_ex_system_io_space_handler;
-			setup   = acpi_ev_io_space_region_setup;
-			break;
-
-		case ACPI_ADR_SPACE_PCI_CONFIG:
-			handler = acpi_ex_pci_config_space_handler;
-			setup   = acpi_ev_pci_config_region_setup;
-			break;
-
-		case ACPI_ADR_SPACE_CMOS:
-			handler = acpi_ex_cmos_space_handler;
-			setup   = acpi_ev_cmos_region_setup;
-			break;
-
-		case ACPI_ADR_SPACE_PCI_BAR_TARGET:
-			handler = acpi_ex_pci_bar_space_handler;
-			setup   = acpi_ev_pci_bar_region_setup;
-			break;
-
-		case ACPI_ADR_SPACE_DATA_TABLE:
-			handler = acpi_ex_data_table_space_handler;
-			setup   = NULL;
-			break;
-
-		default:
-			status = AE_BAD_PARAMETER;
-			goto unlock_and_exit;
-		}
-	}
-
-	/* If the caller hasn't specified a setup routine, use the default */
-
-	if (!setup) {
-		setup = acpi_ev_default_region_setup;
-	}
-
-	/* Check for an existing internal object */
-
-	obj_desc = acpi_ns_get_attached_object (node);
-	if (obj_desc) {
-		/*
-		 * The attached device object already exists.
-		 * Make sure the handler is not already installed.
-		 */
-		handler_obj = obj_desc->device.handler;
-
-		/* Walk the handler list for this device */
-
-		while (handler_obj) {
-			/* Same space_id indicates a handler already installed */
-
-			if(handler_obj->address_space.space_id == space_id) {
-				if (handler_obj->address_space.handler == handler) {
-					/*
-					 * It is (relatively) OK to attempt to install the SAME
-					 * handler twice. This can easily happen with PCI_Config space.
-					 */
-					status = AE_SAME_HANDLER;
-					goto unlock_and_exit;
-				}
-				else {
-					/* A handler is already installed */
-
-					status = AE_ALREADY_EXISTS;
-				}
-				goto unlock_and_exit;
-			}
-
-			/* Walk the linked list of handlers */
-
-			handler_obj = handler_obj->address_space.next;
-		}
-	}
-	else {
-		ACPI_DEBUG_PRINT ((ACPI_DB_OPREGION,
-			"Creating object on Device %p while installing handler\n", node));
-
-		/* obj_desc does not exist, create one */
-
-		if (node->type == ACPI_TYPE_ANY) {
-			type = ACPI_TYPE_DEVICE;
-		}
-		else {
-			type = node->type;
-		}
-
-		obj_desc = acpi_ut_create_internal_object (type);
-		if (!obj_desc) {
-			status = AE_NO_MEMORY;
-			goto unlock_and_exit;
-		}
-
-		/* Init new descriptor */
-
-		obj_desc->common.type = (u8) type;
-
-		/* Attach the new object to the Node */
+	/* Install the handler for all Regions for this Space ID */
 
-		status = acpi_ns_attach_object (node, obj_desc, type);
-
-		/* Remove local reference to the object */
-
-		acpi_ut_remove_reference (obj_desc);
-
-		if (ACPI_FAILURE (status)) {
-			goto unlock_and_exit;
-		}
-	}
-
-	ACPI_DEBUG_PRINT ((ACPI_DB_OPREGION,
-		"Installing address handler for region %s(%X) on Device %4.4s %p(%p)\n",
-		acpi_ut_get_region_name (space_id), space_id,
-		acpi_ut_get_node_name (node), node, obj_desc));
-
-	/*
-	 * Install the handler
-	 *
-	 * At this point there is no existing handler.
-	 * Just allocate the object for the handler and link it
-	 * into the list.
-	 */
-	handler_obj = acpi_ut_create_internal_object (ACPI_TYPE_LOCAL_ADDRESS_HANDLER);
-	if (!handler_obj) {
-		status = AE_NO_MEMORY;
+	status = acpi_ev_install_space_handler (node, space_id, handler, setup, context);
+	if (ACPI_FAILURE (status)) {
 		goto unlock_and_exit;
 	}
 
-	/* Init handler obj */
+	/* Run all _REG methods for this address space */
 
-	handler_obj->address_space.space_id  = (u8) space_id;
-	handler_obj->address_space.hflags    = flags;
-	handler_obj->address_space.region_list = NULL;
-	handler_obj->address_space.node      = node;
-	handler_obj->address_space.handler   = handler;
-	handler_obj->address_space.context   = context;
-	handler_obj->address_space.setup     = setup;
-
-	/* Install at head of Device.address_space list */
-
-	handler_obj->address_space.next      = obj_desc->device.handler;
-
-	/*
-	 * The Device object is the first reference on the handler_obj.
-	 * Each region that uses the handler adds a reference.
-	 */
-	obj_desc->device.handler = handler_obj;
-
-	/*
-	 * Walk the namespace finding all of the regions this
-	 * handler will manage.
-	 *
-	 * Start at the device and search the branch toward
-	 * the leaf nodes until either the leaf is encountered or
-	 * a device is detected that has an address handler of the
-	 * same type.
-	 *
-	 * In either case, back up and search down the remainder
-	 * of the branch
-	 */
-	status = acpi_ns_walk_namespace (ACPI_TYPE_ANY, device, ACPI_UINT32_MAX,
-			  ACPI_NS_WALK_UNLOCK, acpi_ev_install_handler,
-			  handler_obj, NULL);
-
-	/*
-	 * Now we can run the _REG methods for all Regions for this
-	 * space ID.  This is a separate walk in order to handle any
-	 * interdependencies between regions and _REG methods.  (i.e. handlers
-	 * must be installed for all regions of this Space ID before we
-	 * can run any _REG methods.
-	 */
-	status = acpi_ns_walk_namespace (ACPI_TYPE_ANY, device, ACPI_UINT32_MAX,
-			  ACPI_NS_WALK_UNLOCK, acpi_ev_reg_run,
-			  handler_obj, NULL);
+	status = acpi_ev_execute_reg_methods (node, space_id);
 
 unlock_and_exit:
 	(void) acpi_ut_release_mutex (ACPI_MTX_NAMESPACE);
diff -Nru a/drivers/acpi/executer/exconfig.c b/drivers/acpi/executer/exconfig.c
--- a/drivers/acpi/executer/exconfig.c	2004-10-18 14:56:33 -07:00
+++ b/drivers/acpi/executer/exconfig.c	2004-10-18 14:56:33 -07:00
@@ -48,6 +48,7 @@
 #include <acpi/acnamesp.h>
 #include <acpi/acevents.h>
 #include <acpi/actables.h>
+#include <acpi/acdispat.h>
 
 
 #define _COMPONENT          ACPI_EXECUTER
@@ -285,7 +286,7 @@
 	union acpi_operand_object       *ddb_handle;
 	union acpi_operand_object       *buffer_desc = NULL;
 	struct acpi_table_header        *table_ptr = NULL;
-	u8                              *table_data_ptr;
+	acpi_physical_address           address;
 	struct acpi_table_header        table_header;
 	u32                             i;
 
@@ -300,18 +301,39 @@
 		ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "Load from Region %p %s\n",
 			obj_desc, acpi_ut_get_object_type_name (obj_desc)));
 
-		/* Get the table header */
+		/*
+		 * If the Region Address and Length have not been previously evaluated,
+		 * evaluate them now and save the results.
+		 */
+		if (!(obj_desc->common.flags & AOPOBJ_DATA_VALID)) {
+			status = acpi_ds_get_region_arguments (obj_desc);
+			if (ACPI_FAILURE (status)) {
+				return_ACPI_STATUS (status);
+			}
+		}
+
+		/* Get the base physical address of the region */
+
+		address = obj_desc->region.address;
+
+		/* Get the table length from the table header */
 
 		table_header.length = 0;
-		for (i = 0; i < sizeof (struct acpi_table_header); i++) {
+		for (i = 0; i < 8; i++) {
 			status = acpi_ev_address_space_dispatch (obj_desc, ACPI_READ,
-					   (acpi_physical_address) i, 8,
+					   (acpi_physical_address) (i + address), 8,
 					   ((u8 *) &table_header) + i);
 			if (ACPI_FAILURE (status)) {
 				return_ACPI_STATUS (status);
 			}
 		}
 
+		/* Sanity check the table length */
+
+		if (table_header.length < sizeof (struct acpi_table_header)) {
+			return_ACPI_STATUS (AE_BAD_HEADER);
+		}
+
 		/* Allocate a buffer for the entire table */
 
 		table_ptr = ACPI_MEM_ALLOCATE (table_header.length);
@@ -319,17 +341,12 @@
 			return_ACPI_STATUS (AE_NO_MEMORY);
 		}
 
-		/* Copy the header to the buffer */
-
-		ACPI_MEMCPY (table_ptr, &table_header, sizeof (struct acpi_table_header));
-		table_data_ptr = ACPI_PTR_ADD (u8, table_ptr, sizeof (struct acpi_table_header));
-
-		/* Get the table from the op region */
+		/* Get the entire table from the op region */
 
 		for (i = 0; i < table_header.length; i++) {
 			status = acpi_ev_address_space_dispatch (obj_desc, ACPI_READ,
-					   (acpi_physical_address) i, 8,
-					   ((u8 *) table_data_ptr + i));
+					   (acpi_physical_address) (i + address), 8,
+					   ((u8 *) table_ptr + i));
 			if (ACPI_FAILURE (status)) {
 				goto cleanup;
 			}
@@ -355,6 +372,12 @@
 		}
 
 		table_ptr = ACPI_CAST_PTR (struct acpi_table_header, buffer_desc->buffer.pointer);
+
+		 /* Sanity check the table length */
+
+		if (table_ptr->length < sizeof (struct acpi_table_header)) {
+			return_ACPI_STATUS (AE_BAD_HEADER);
+		}
 		break;
 
 
diff -Nru a/drivers/acpi/executer/exfldio.c b/drivers/acpi/executer/exfldio.c
--- a/drivers/acpi/executer/exfldio.c	2004-10-18 14:56:28 -07:00
+++ b/drivers/acpi/executer/exfldio.c	2004-10-18 14:56:28 -07:00
@@ -130,6 +130,21 @@
 	if (rgn_desc->region.length < (obj_desc->common_field.base_byte_offset
 			   + field_datum_byte_offset
 			   + obj_desc->common_field.access_byte_width)) {
+		if (acpi_gbl_enable_interpreter_slack) {
+			/*
+			 * Slack mode only:  We will go ahead and allow access to this
+			 * field if it is within the region length rounded up to the next
+			 * access width boundary.
+			 */
+			if (ACPI_ROUND_UP (rgn_desc->region.length,
+					   obj_desc->common_field.access_byte_width) >=
+				(obj_desc->common_field.base_byte_offset +
+				 obj_desc->common_field.access_byte_width +
+				 field_datum_byte_offset)) {
+				return_ACPI_STATUS (AE_OK);
+			}
+		}
+
 		if (rgn_desc->region.length < obj_desc->common_field.access_byte_width) {
 			/*
 			 * This is the case where the access_type (acc_word, etc.) is wider
@@ -154,40 +169,7 @@
 			field_datum_byte_offset, obj_desc->common_field.access_byte_width,
 			acpi_ut_get_node_name (rgn_desc->region.node), rgn_desc->region.length));
 
-		if (!acpi_strict) {
-			/*
-			 * Allow access to the field if it is within the region size
-			 * rounded up to a multiple of the access byte width.  This
-			 * overcomes "off-by-one" programming errors in the AML often
-			 * found in Toshiba laptops.  These errors were allowed by
-			 * the Microsoft ASL compiler.
-			 */
-			u32 rounded_length = ACPI_ROUND_UP(rgn_desc->region.length,
-									obj_desc->common_field.access_byte_width);
-
-			if (rounded_length < (obj_desc->common_field.base_byte_offset
-						+ field_datum_byte_offset
-						+ obj_desc->common_field.access_byte_width)) {
-				return_ACPI_STATUS (AE_AML_REGION_LIMIT);
-			} else {
-				static int	warn_once = 1;
-				if (warn_once) {
-					// Could also associate a flag with each field, and
-					// warn once for each field.
-					ACPI_REPORT_WARNING((
-						"The ACPI AML in your computer contains errors, "
-						"please nag the manufacturer to correct it.\n"));
-					ACPI_REPORT_WARNING((
-						"Allowing relaxed access to fields; "
-						"turn on CONFIG_ACPI_DEBUG for details.\n"));
-					warn_once = 0;
-				}
-				return_ACPI_STATUS (AE_OK);
-			}
-		}
-		else {
-			return_ACPI_STATUS (AE_AML_REGION_LIMIT);
-		}
+		return_ACPI_STATUS (AE_AML_REGION_LIMIT);
 	}
 
 	return_ACPI_STATUS (AE_OK);
@@ -277,7 +259,7 @@
 				rgn_desc->region.space_id));
 		}
 		else if (status == AE_NOT_EXIST) {
-			ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
+			ACPI_REPORT_ERROR ((
 				"Region %s(%X) has no handler\n",
 				acpi_ut_get_region_name (rgn_desc->region.space_id),
 				rgn_desc->region.space_id));
@@ -766,14 +748,83 @@
 
 /*******************************************************************************
  *
+ * FUNCTION:    acpi_ex_common_buffer_setup
+ *
+ * PARAMETERS:  obj_desc            - Field object
+ *              buffer_length       - Length of caller's buffer
+ *              datum_count         - Where the datum_count is returned
+ *
+ * RETURN:      Status, datum_count
+ *
+ * DESCRIPTION: Common code to validate the incoming buffer size and compute
+ *              the number of field "datums" that must be read or written.
+ *              A "datum" is the smallest unit that can be read or written
+ *              to the field, it is either 1,2,4, or 8 bytes.
+ *
+ ******************************************************************************/
+
+acpi_status
+acpi_ex_common_buffer_setup (
+	union acpi_operand_object       *obj_desc,
+	u32                             buffer_length,
+	u32                             *datum_count)
+{
+	u32                             byte_field_length;
+	u32                             actual_byte_field_length;
+
+
+	ACPI_FUNCTION_TRACE ("ex_common_buffer_setup");
+
+
+	/*
+	 * Incoming buffer must be at least as long as the field, we do not
+	 * allow "partial" field reads/writes.  We do not care if the buffer is
+	 * larger than the field, this typically happens when an integer is
+	 * read/written to a field that is actually smaller than an integer.
+	 */
+	byte_field_length = ACPI_ROUND_BITS_UP_TO_BYTES (
+			 obj_desc->common_field.bit_length);
+	if (byte_field_length > buffer_length) {
+		ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD,
+			"Field size %X (bytes) is too large for buffer (%X)\n",
+			byte_field_length, buffer_length));
+
+		return_ACPI_STATUS (AE_BUFFER_OVERFLOW);
+	}
+
+	/*
+	 * Create "actual" field byte count (minimum number of bytes that
+	 * must be read), then convert to datum count (minimum number
+	 * of datum-sized units that must be read)
+	 */
+	actual_byte_field_length = ACPI_ROUND_BITS_UP_TO_BYTES (
+			  obj_desc->common_field.start_field_bit_offset +
+			  obj_desc->common_field.bit_length);
+
+
+	*datum_count = ACPI_ROUND_UP_TO (actual_byte_field_length,
+			   obj_desc->common_field.access_byte_width);
+
+	ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD,
+		"buffer_bytes %X, actual_bytes %X, Datums %X, byte_gran %X\n",
+		byte_field_length, actual_byte_field_length,
+		*datum_count, obj_desc->common_field.access_byte_width));
+
+	return_ACPI_STATUS (AE_OK);
+}
+
+
+/*******************************************************************************
+ *
  * FUNCTION:    acpi_ex_extract_from_field
  *
- * PARAMETERS:  *obj_desc           - Field to be read
- *              *Value              - Where to store value
+ * PARAMETERS:  obj_desc            - Field to be read
+ *              Buffer              - Where to store the field data
+ *              buffer_length       - Length of Buffer
  *
  * RETURN:      Status
  *
- * DESCRIPTION: Retrieve the value of the given field
+ * DESCRIPTION: Retrieve the current value of the given field
  *
  ******************************************************************************/
 
@@ -789,7 +840,6 @@
 	acpi_integer                    previous_raw_datum = 0;
 	acpi_integer                    this_raw_datum = 0;
 	acpi_integer                    merged_datum = 0;
-	u32                             byte_field_length;
 	u32                             datum_count;
 	u32                             i;
 
@@ -797,39 +847,13 @@
 	ACPI_FUNCTION_TRACE ("ex_extract_from_field");
 
 
-	/*
-	 * The field must fit within the caller's buffer
-	 */
-	byte_field_length = ACPI_ROUND_BITS_UP_TO_BYTES (obj_desc->common_field.bit_length);
-	if (byte_field_length > buffer_length) {
-		ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD,
-			"Field size %X (bytes) too large for buffer (%X)\n",
-			byte_field_length, buffer_length));
-
-		return_ACPI_STATUS (AE_BUFFER_OVERFLOW);
-	}
-
-	/* Convert field byte count to datum count, round up if necessary */
-
-	datum_count = ACPI_ROUND_UP_TO (byte_field_length,
-			   obj_desc->common_field.access_byte_width);
+	/* Validate buffer, compute number of datums */
 
-	/*
-	 * If the field is not aligned on a datum boundary and does not
-	 * fit within a single datum, we must read an extra datum.
-	 *
-	 * We could just split the aligned and non-aligned cases since the
-	 * aligned case is so very simple, but this would require more code.
-	 */
-	if ((obj_desc->common_field.end_field_valid_bits != 0)    &&
-		(!(obj_desc->common_field.flags & AOPOBJ_SINGLE_DATUM))) {
-		datum_count++;
+	status = acpi_ex_common_buffer_setup (obj_desc, buffer_length, &datum_count);
+	if (ACPI_FAILURE (status)) {
+		return_ACPI_STATUS (status);
 	}
 
-	ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD,
-		"byte_len %X, datum_len %X, byte_gran %X\n",
-		byte_field_length, datum_count,obj_desc->common_field.access_byte_width));
-
 	/*
 	 * Clear the caller's buffer (the whole buffer length as given)
 	 * This is very important, especially in the cases where the buffer
@@ -942,12 +966,13 @@
  *
  * FUNCTION:    acpi_ex_insert_into_field
  *
- * PARAMETERS:  *obj_desc           - Field to be set
- *              Buffer              - Value to store
+ * PARAMETERS:  obj_desc            - Field to be written
+ *              Buffer              - Data to be written
+ *              buffer_length       - Length of Buffer
  *
  * RETURN:      Status
  *
- * DESCRIPTION: Store the value into the given field
+ * DESCRIPTION: Store the Buffer contents into the given field
  *
  ******************************************************************************/
 
@@ -964,41 +989,18 @@
 	acpi_integer                    merged_datum;
 	acpi_integer                    previous_raw_datum;
 	acpi_integer                    this_raw_datum;
-	u32                             byte_field_length;
 	u32                             datum_count;
 
 
 	ACPI_FUNCTION_TRACE ("ex_insert_into_field");
 
 
-	/*
-	 * Incoming buffer must be at least as long as the field, we do not
-	 * allow "partial" field writes.  We do not care if the buffer is
-	 * larger than the field, this typically happens when an integer is
-	 * written to a field that is actually smaller than an integer.
-	 */
-	byte_field_length = ACPI_ROUND_BITS_UP_TO_BYTES (
-			 obj_desc->common_field.bit_length);
-	if (buffer_length < byte_field_length) {
-		ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD,
-			"Buffer length %X too small for field %X\n",
-			buffer_length, byte_field_length));
+	/* Validate buffer, compute number of datums */
 
-		return_ACPI_STATUS (AE_BUFFER_OVERFLOW);
+	status = acpi_ex_common_buffer_setup (obj_desc, buffer_length, &datum_count);
+	if (ACPI_FAILURE (status)) {
+		return_ACPI_STATUS (status);
 	}
-
-	byte_field_length = ACPI_ROUND_BITS_UP_TO_BYTES (
-			 obj_desc->common_field.start_field_bit_offset +
-			 obj_desc->common_field.bit_length);
-
-	/* Convert byte count to datum count, round up if necessary */
-
-	datum_count = ACPI_ROUND_UP_TO (byte_field_length,
-			  obj_desc->common_field.access_byte_width);
-
-	ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD,
-		"Bytes %X, Datums %X, byte_gran %X\n",
-		byte_field_length, datum_count, obj_desc->common_field.access_byte_width));
 
 	/*
 	 * Break the request into up to three parts (similar to an I/O request):
diff -Nru a/drivers/acpi/executer/exmisc.c b/drivers/acpi/executer/exmisc.c
--- a/drivers/acpi/executer/exmisc.c	2004-10-18 14:56:50 -07:00
+++ b/drivers/acpi/executer/exmisc.c	2004-10-18 14:56:50 -07:00
@@ -389,6 +389,8 @@
 	acpi_integer                    operand1)
 {
 
+	ACPI_FUNCTION_ENTRY ();
+
 
 	switch (opcode) {
 	case AML_ADD_OP:                /* Add (Operand0, Operand1, Result) */
@@ -452,15 +454,17 @@
  * FUNCTION:    acpi_ex_do_logical_op
  *
  * PARAMETERS:  Opcode              - AML opcode
- *              Operand0            - Integer operand #0
- *              Operand1            - Integer operand #1
+ *              obj_desc0           - operand #0
+ *              obj_desc1           - operand #1
  *
  * RETURN:      TRUE/FALSE result of the operation
  *
  * DESCRIPTION: Execute a logical AML opcode. The purpose of having all of the
  *              functions here is to prevent a lot of pointer dereferencing
  *              to obtain the operands and to simplify the generation of the
- *              logical value.
+ *              logical value.  Both operands must already be validated as
+ *              1) Both the same type, and
+ *              2) Either Integer, Buffer, or String type.
  *
  *              Note: cleanest machine code seems to be produced by the code
  *              below, rather than using statements of the form:
@@ -471,54 +475,137 @@
 u8
 acpi_ex_do_logical_op (
 	u16                             opcode,
-	acpi_integer                    operand0,
-	acpi_integer                    operand1)
+	union acpi_operand_object       *obj_desc0,
+	union acpi_operand_object       *obj_desc1)
 {
+	acpi_integer                    operand0;
+	acpi_integer                    operand1;
+	u8                              *ptr0;
+	u8                              *ptr1;
+	u32                             length0;
+	u32                             length1;
+	u32                             i;
 
 
-	switch (opcode) {
+	ACPI_FUNCTION_ENTRY ();
 
-	case AML_LAND_OP:               /* LAnd (Operand0, Operand1) */
 
-		if (operand0 && operand1) {
-			return (TRUE);
-		}
-		break;
+	if (ACPI_GET_OBJECT_TYPE (obj_desc0) == ACPI_TYPE_INTEGER) {
+		/* Both operands are of type integer */
 
+		operand0 = obj_desc0->integer.value;
+		operand1 = obj_desc1->integer.value;
 
-	case AML_LEQUAL_OP:             /* LEqual (Operand0, Operand1) */
+		switch (opcode) {
+		case AML_LAND_OP:               /* LAnd (Operand0, Operand1) */
 
-		if (operand0 == operand1) {
-			return (TRUE);
-		}
-		break;
+			if (operand0 && operand1) {
+				return (TRUE);
+			}
+			break;
 
+		case AML_LEQUAL_OP:             /* LEqual (Operand0, Operand1) */
 
-	case AML_LGREATER_OP:           /* LGreater (Operand0, Operand1) */
+			if (operand0 == operand1) {
+				return (TRUE);
+			}
+			break;
 
-		if (operand0 > operand1) {
-			return (TRUE);
-		}
-		break;
+		case AML_LGREATER_OP:           /* LGreater (Operand0, Operand1) */
 
+			if (operand0 > operand1) {
+				return (TRUE);
+			}
+			break;
 
-	case AML_LLESS_OP:              /* LLess (Operand0, Operand1) */
+		case AML_LLESS_OP:              /* LLess (Operand0, Operand1) */
 
-		if (operand0 < operand1) {
-			return (TRUE);
-		}
-		break;
+			if (operand0 < operand1) {
+				return (TRUE);
+			}
+			break;
 
+		case AML_LOR_OP:                 /* LOr (Operand0, Operand1) */
 
-	case AML_LOR_OP:                 /* LOr (Operand0, Operand1) */
+			if (operand0 || operand1) {
+				return (TRUE);
+			}
+			break;
 
-		if (operand0 || operand1) {
-			return (TRUE);
+		default:
+			break;
 		}
-		break;
+	}
+	else {
+		/*
+		 * Case for Buffer/String objects.
+		 * NOTE: takes advantage of common Buffer/String object fields
+		 */
+		length0 = obj_desc0->buffer.length;
+		ptr0    = obj_desc0->buffer.pointer;
+
+		length1 = obj_desc1->buffer.length;
+		ptr1    = obj_desc1->buffer.pointer;
+
+		switch (opcode) {
+		case AML_LEQUAL_OP:             /* LEqual (Operand0, Operand1) */
+
+			/* Length and all bytes must be equal */
+
+			if (length0 != length1) {
+				return (FALSE);
+			}
+
+			for (i = 0; i < length0; i++) {
+				if (ptr0[i] != ptr1[i]) {
+					return (FALSE);
+				}
+			}
+			return (TRUE);
 
-	default:
-		break;
+		case AML_LGREATER_OP:           /* LGreater (Operand0, Operand1) */
+
+			/* Lexicographic compare:  Scan the 1-to-1 data */
+
+			for (i = 0; (i < length0) && (i < length1); i++) {
+				if (ptr0[i] > ptr1[i]) {
+					return (TRUE);
+				}
+			}
+
+			/* Bytes match, now check lengths */
+
+			if (length0 > length1) {
+				return (TRUE);
+			}
+
+			/* Length0 <= Length1 */
+
+			return (FALSE);
+
+		case AML_LLESS_OP:              /* LLess (Operand0, Operand1) */
+
+			/* Lexicographic compare:  Scan the 1-to-1 data */
+
+			for (i = 0; (i < length0) && (i < length1); i++) {
+				if (ptr0[i] < ptr1[i]) {
+					return (TRUE);
+				}
+			}
+
+			/* Bytes match, now check lengths */
+
+			if (length0 < length1) {
+				return (TRUE);
+			}
+
+			/* Length0 >= Length1 */
+
+			return (FALSE);
+
+		default:
+			break;
+		}
 	}
 
 	return (FALSE);
diff -Nru a/drivers/acpi/executer/exmutex.c b/drivers/acpi/executer/exmutex.c
--- a/drivers/acpi/executer/exmutex.c	2004-10-18 14:56:49 -07:00
+++ b/drivers/acpi/executer/exmutex.c	2004-10-18 14:56:49 -07:00
@@ -54,7 +54,7 @@
  *
  * FUNCTION:    acpi_ex_unlink_mutex
  *
- * PARAMETERS:  *obj_desc           - The mutex to be unlinked
+ * PARAMETERS:  obj_desc            - The mutex to be unlinked
  *
  * RETURN:      Status
  *
@@ -73,6 +73,8 @@
 		return;
 	}
 
+	/* Doubly linked list */
+
 	if (obj_desc->mutex.next) {
 		(obj_desc->mutex.next)->mutex.prev = obj_desc->mutex.prev;
 	}
@@ -90,8 +92,8 @@
  *
  * FUNCTION:    acpi_ex_link_mutex
  *
- * PARAMETERS:  *obj_desc           - The mutex to be linked
- *              *list_head          - head of the "acquired_mutex" list
+ * PARAMETERS:  obj_desc            - The mutex to be linked
+ *              list_head           - head of the "acquired_mutex" list
  *
  * RETURN:      Status
  *
@@ -130,8 +132,8 @@
  *
  * FUNCTION:    acpi_ex_acquire_mutex
  *
- * PARAMETERS:  *time_desc          - The 'time to delay' object descriptor
- *              *obj_desc           - The object descriptor for this op
+ * PARAMETERS:  time_desc           - The 'time to delay' object descriptor
+ *              obj_desc            - The object descriptor for this op
  *
  * RETURN:      Status
  *
@@ -173,9 +175,8 @@
 		return_ACPI_STATUS (AE_AML_MUTEX_ORDER);
 	}
 
-	/*
-	 * Support for multiple acquires by the owning thread
-	 */
+	/* Support for multiple acquires by the owning thread */
+
 	if (obj_desc->mutex.owner_thread) {
 		/* Special case for Global Lock, allow all threads */
 
@@ -199,10 +200,11 @@
 		return_ACPI_STATUS (status);
 	}
 
-	/* Have the mutex, update mutex and walk info */
+	/* Have the mutex: update mutex and walk info and save the sync_level */
 
-	obj_desc->mutex.owner_thread    = walk_state->thread;
+	obj_desc->mutex.owner_thread     = walk_state->thread;
 	obj_desc->mutex.acquisition_depth = 1;
+	obj_desc->mutex.original_sync_level = walk_state->thread->current_sync_level;
 
 	walk_state->thread->current_sync_level = obj_desc->mutex.sync_level;
 
@@ -218,7 +220,7 @@
  *
  * FUNCTION:    acpi_ex_release_mutex
  *
- * PARAMETERS:  *obj_desc           - The object descriptor for this op
+ * PARAMETERS:  obj_desc            - The object descriptor for this op
  *
  * RETURN:      Status
  *
@@ -281,9 +283,8 @@
 		return_ACPI_STATUS (AE_AML_MUTEX_ORDER);
 	}
 
-	/*
-	 * Match multiple Acquires with multiple Releases
-	 */
+	/* Match multiple Acquires with multiple Releases */
+
 	obj_desc->mutex.acquisition_depth--;
 	if (obj_desc->mutex.acquisition_depth != 0) {
 		/* Just decrement the depth and return */
@@ -299,10 +300,10 @@
 
 	status = acpi_ex_system_release_mutex (obj_desc);
 
-	/* Update the mutex and walk state */
+	/* Update the mutex and walk state, restore sync_level before acquire */
 
 	obj_desc->mutex.owner_thread = NULL;
-	walk_state->thread->current_sync_level = obj_desc->mutex.sync_level;
+	walk_state->thread->current_sync_level = obj_desc->mutex.original_sync_level;
 
 	return_ACPI_STATUS (status);
 }
@@ -312,7 +313,7 @@
  *
  * FUNCTION:    acpi_ex_release_all_mutexes
  *
- * PARAMETERS:  *mutex_list           - Head of the mutex list
+ * PARAMETERS:  mutex_list            - Head of the mutex list
  *
  * RETURN:      Status
  *
@@ -332,9 +333,8 @@
 	ACPI_FUNCTION_ENTRY ();
 
 
-	/*
-	 * Traverse the list of owned mutexes, releasing each one.
-	 */
+	/* Traverse the list of owned mutexes, releasing each one */
+
 	while (next) {
 		this = next;
 		next = this->mutex.next;
@@ -352,7 +352,11 @@
 
 		/* Mark mutex unowned */
 
-		this->mutex.owner_thread     = NULL;
+		this->mutex.owner_thread = NULL;
+
+		/* Update Thread sync_level (Last mutex is the important one) */
+
+		thread->current_sync_level = this->mutex.original_sync_level;
 	}
 }
 
diff -Nru a/drivers/acpi/executer/exoparg2.c b/drivers/acpi/executer/exoparg2.c
--- a/drivers/acpi/executer/exoparg2.c	2004-10-18 14:56:32 -07:00
+++ b/drivers/acpi/executer/exoparg2.c	2004-10-18 14:56:32 -07:00
@@ -97,6 +97,7 @@
 {
 	union acpi_operand_object       **operand = &walk_state->operands[0];
 	struct acpi_namespace_node      *node;
+	u32                             value;
 	acpi_status                     status = AE_OK;
 
 
@@ -113,16 +114,46 @@
 
 		node = (struct acpi_namespace_node *) operand[0];
 
+		/* Second value is the notify value */
+
+		value = (u32) operand[1]->integer.value;
+
 		/* Notifies allowed on this object? */
 
 		if (!acpi_ev_is_notify_object (node)) {
-			ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Unexpected notify object type [%s]\n",
+			ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
+					"Unexpected notify object type [%s]\n",
 					acpi_ut_get_type_name (node->type)));
 
 			status = AE_AML_OPERAND_TYPE;
 			break;
 		}
 
+#ifdef ACPI_GPE_NOTIFY_CHECK
+		/*
+		 * GPE method wake/notify check.  Here, we want to ensure that we
+		 * don't receive any "device_wake" Notifies from a GPE _Lxx or _Exx
+		 * GPE method during system runtime.  If we do, the GPE is marked
+		 * as "wake-only" and disabled.
+		 *
+		 * 1) Is the Notify() value == device_wake?
+		 * 2) Is this a GPE deferred method?  (An _Lxx or _Exx method)
+		 * 3) Did the original GPE happen at system runtime?
+		 *    (versus during wake)
+		 *
+		 * If all three cases are true, this is a wake-only GPE that should
+		 * be disabled at runtime.
+		 */
+		if (value == 2)     /* device_wake */ {
+			status = acpi_ev_check_for_wake_only_gpe (walk_state->gpe_event_info);
+			if (ACPI_FAILURE (status)) {
+				/* AE_WAKE_ONLY_GPE only error, means ignore this notify */
+
+				return_ACPI_STATUS (AE_OK)
+			}
+		}
+#endif
+
 		/*
 		 * Dispatch the notify to the appropriate handler
 		 * NOTE: the request is queued for execution after this method
@@ -130,8 +161,7 @@
 		 * from this thread -- because handlers may in turn run other
 		 * control methods.
 		 */
-		status = acpi_ev_queue_notify_request (node,
-				  (u32) operand[1]->integer.value);
+		status = acpi_ev_queue_notify_request (node, value);
 		break;
 
 
@@ -543,9 +573,17 @@
 	 * Execute the Opcode
 	 */
 	if (walk_state->op_info->flags & AML_LOGICAL) /* logical_op (Operand0, Operand1) */ {
+		/* Both operands must be of the same type */
+
+		if (ACPI_GET_OBJECT_TYPE (operand[0]) !=
+			ACPI_GET_OBJECT_TYPE (operand[1])) {
+			status = AE_AML_OPERAND_TYPE;
+			goto cleanup;
+		}
+
 		logical_result = acpi_ex_do_logical_op (walk_state->opcode,
-				 operand[0]->integer.value,
-				 operand[1]->integer.value);
+				 operand[0],
+				 operand[1]);
 		goto store_logical_result;
 	}
 
diff -Nru a/drivers/acpi/executer/exresolv.c b/drivers/acpi/executer/exresolv.c
--- a/drivers/acpi/executer/exresolv.c	2004-10-18 14:56:28 -07:00
+++ b/drivers/acpi/executer/exresolv.c	2004-10-18 14:56:28 -07:00
@@ -187,15 +187,15 @@
 				return_ACPI_STATUS (status);
 			}
 
+			ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "[Arg/Local %X] value_obj is %p\n",
+				stack_desc->reference.offset, obj_desc));
+
 			/*
 			 * Now we can delete the original Reference Object and
-			 * replace it with the resolve value
+			 * replace it with the resolved value
 			 */
 			acpi_ut_remove_reference (stack_desc);
 			*stack_ptr = obj_desc;
-
-			ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "[Arg/Local %d] value_obj is %p\n",
-				stack_desc->reference.offset, obj_desc));
 			break;
 
 
diff -Nru a/drivers/acpi/executer/exstore.c b/drivers/acpi/executer/exstore.c
--- a/drivers/acpi/executer/exstore.c	2004-10-18 14:56:29 -07:00
+++ b/drivers/acpi/executer/exstore.c	2004-10-18 14:56:29 -07:00
@@ -102,7 +102,8 @@
 		 * Storing an object into a Named node.
 		 */
 		status = acpi_ex_store_object_to_node (source_desc,
-				 (struct acpi_namespace_node *) dest_desc, walk_state);
+				 (struct acpi_namespace_node *) dest_desc, walk_state,
+				 ACPI_IMPLICIT_CONVERSION);
 
 		return_ACPI_STATUS (status);
 	}
@@ -153,7 +154,7 @@
 		/* Storing an object into a Name "container" */
 
 		status = acpi_ex_store_object_to_node (source_desc, ref_desc->reference.object,
-				  walk_state);
+				  walk_state, ACPI_IMPLICIT_CONVERSION);
 		break;
 
 
@@ -399,6 +400,7 @@
  * PARAMETERS:  source_desc             - Value to be stored
  *              Node                    - Named object to receive the value
  *              walk_state              - Current walk state
+ *              implicit_conversion     - Perform implicit conversion (yes/no)
  *
  * RETURN:      Status
  *
@@ -421,7 +423,8 @@
 acpi_ex_store_object_to_node (
 	union acpi_operand_object       *source_desc,
 	struct acpi_namespace_node      *node,
-	struct acpi_walk_state          *walk_state)
+	struct acpi_walk_state          *walk_state,
+	u8                              implicit_conversion)
 {
 	acpi_status                     status = AE_OK;
 	union acpi_operand_object       *target_desc;
@@ -449,6 +452,14 @@
 	status = acpi_ex_resolve_object (&source_desc, target_type, walk_state);
 	if (ACPI_FAILURE (status)) {
 		return_ACPI_STATUS (status);
+	}
+
+	/* If no implicit conversion, drop into the default case below */
+
+	if (!implicit_conversion) {
+		/* Force execution of default (no implicit conversion) */
+
+		target_type = ACPI_TYPE_ANY;
 	}
 
 	/*
diff -Nru a/drivers/acpi/hardware/hwgpe.c b/drivers/acpi/hardware/hwgpe.c
--- a/drivers/acpi/hardware/hwgpe.c	2004-10-18 14:55:54 -07:00
+++ b/drivers/acpi/hardware/hwgpe.c	2004-10-18 14:55:54 -07:00
@@ -51,104 +51,24 @@
 
 /******************************************************************************
  *
- * FUNCTION:    acpi_hw_enable_gpe
+ * FUNCTION:    acpi_hw_write_gpe_enable_reg
  *
  * PARAMETERS:  gpe_event_info      - Info block for the GPE to be enabled
  *
  * RETURN:      Status
  *
- * DESCRIPTION: Enable a single GPE.
+ * DESCRIPTION: Write a GPE enable register.  Note: The bit for this GPE must
+ *              already be cleared or set in the parent register
+ *              enable_for_run mask.
  *
  ******************************************************************************/
 
 acpi_status
-acpi_hw_enable_gpe (
-	struct acpi_gpe_event_info      *gpe_event_info)
-{
-	u32                             in_byte;
-	acpi_status                     status;
-
-
-	ACPI_FUNCTION_ENTRY ();
-
-
-	/*
-	 * Read the current value of the register, set the appropriate bit
-	 * to enable the GPE, and write out the new register.
-	 */
-	status = acpi_hw_low_level_read (8, &in_byte,
-			  &gpe_event_info->register_info->enable_address);
-	if (ACPI_FAILURE (status)) {
-		return (status);
-	}
-
-	/* Write with the new GPE bit enabled */
-
-	status = acpi_hw_low_level_write (8, (in_byte | gpe_event_info->bit_mask),
-			  &gpe_event_info->register_info->enable_address);
-
-	return (status);
-}
-
-
-/******************************************************************************
- *
- * FUNCTION:    acpi_hw_enable_gpe_for_wakeup
- *
- * PARAMETERS:  gpe_event_info      - Info block for the GPE to be enabled
- *
- * RETURN:      None
- *
- * DESCRIPTION: Keep track of which GPEs the OS has requested not be
- *              disabled when going to sleep.
- *
- ******************************************************************************/
-
-void
-acpi_hw_enable_gpe_for_wakeup (
+acpi_hw_write_gpe_enable_reg (
 	struct acpi_gpe_event_info      *gpe_event_info)
 {
 	struct acpi_gpe_register_info   *gpe_register_info;
-
-
-	ACPI_FUNCTION_ENTRY ();
-
-
-	/* Get the info block for the entire GPE register */
-
-	gpe_register_info = gpe_event_info->register_info;
-	if (!gpe_register_info) {
-		return;
-	}
-
-	/*
-	 * Set the bit so we will not enable this GPE when sleeping (and disable
-	 * it upon wake)
-	 */
-	gpe_register_info->wake_enable |= gpe_event_info->bit_mask;
-	gpe_event_info->flags |= (ACPI_GPE_TYPE_WAKE | ACPI_GPE_ENABLED);
-}
-
-
-/******************************************************************************
- *
- * FUNCTION:    acpi_hw_disable_gpe
- *
- * PARAMETERS:  gpe_event_info      - Info block for the GPE to be disabled
- *
- * RETURN:      Status
- *
- * DESCRIPTION: Disable a single GPE.
- *
- ******************************************************************************/
-
-acpi_status
-acpi_hw_disable_gpe (
-	struct acpi_gpe_event_info      *gpe_event_info)
-{
-	u32                             in_byte;
 	acpi_status                     status;
-	struct acpi_gpe_register_info   *gpe_register_info;
 
 
 	ACPI_FUNCTION_ENTRY ();
@@ -158,67 +78,15 @@
 
 	gpe_register_info = gpe_event_info->register_info;
 	if (!gpe_register_info) {
-		return (AE_BAD_PARAMETER);
-	}
-
-	/*
-	 * Read the current value of the register, clear the appropriate bit,
-	 * and write out the new register value to disable the GPE.
-	 */
-	status = acpi_hw_low_level_read (8, &in_byte,
-			  &gpe_register_info->enable_address);
-	if (ACPI_FAILURE (status)) {
-		return (status);
+		return (AE_NOT_EXIST);
 	}
 
-	/* Write the byte with this GPE bit cleared */
+	/* Write the entire GPE (runtime) enable register */
 
-	status = acpi_hw_low_level_write (8, (in_byte & ~(gpe_event_info->bit_mask)),
+	status = acpi_hw_low_level_write (8, gpe_register_info->enable_for_run,
 			  &gpe_register_info->enable_address);
-	if (ACPI_FAILURE (status)) {
-		return (status);
-	}
-
-	/* Make sure this GPE is disabled for wake, also */
-
-	acpi_hw_disable_gpe_for_wakeup (gpe_event_info);
-	return (AE_OK);
-}
-
-
-/******************************************************************************
- *
- * FUNCTION:    acpi_hw_disable_gpe_for_wakeup
- *
- * PARAMETERS:  gpe_event_info      - Info block for the GPE to be disabled
- *
- * RETURN:      None
- *
- * DESCRIPTION: Keep track of which GPEs the OS has requested not be
- *              disabled when going to sleep.
- *
- ******************************************************************************/
 
-void
-acpi_hw_disable_gpe_for_wakeup (
-	struct acpi_gpe_event_info      *gpe_event_info)
-{
-	struct acpi_gpe_register_info   *gpe_register_info;
-
-
-	ACPI_FUNCTION_ENTRY ();
-
-
-	/* Get the info block for the entire GPE register */
-
-	gpe_register_info = gpe_event_info->register_info;
-	if (!gpe_register_info) {
-		return;
-	}
-
-	/* Clear the bit so we will disable this when sleeping */
-
-	gpe_register_info->wake_enable &= ~(gpe_event_info->bit_mask);
+	return (status);
 }
 
 
@@ -228,7 +96,7 @@
  *
  * PARAMETERS:  gpe_event_info      - Info block for the GPE to be cleared
  *
- * RETURN:      status_status
+ * RETURN:      Status
  *
  * DESCRIPTION: Clear the status bit for a single GPE.
  *
@@ -248,7 +116,7 @@
 	 * Write a one to the appropriate bit in the status register to
 	 * clear this GPE.
 	 */
-	status = acpi_hw_low_level_write (8, gpe_event_info->bit_mask,
+	status = acpi_hw_low_level_write (8, gpe_event_info->register_bit,
 			  &gpe_event_info->register_info->status_address);
 
 	return (status);
@@ -274,7 +142,7 @@
 	acpi_event_status               *event_status)
 {
 	u32                             in_byte;
-	u8                              bit_mask;
+	u8                              register_bit;
 	struct acpi_gpe_register_info   *gpe_register_info;
 	acpi_status                     status;
 	acpi_event_status               local_event_status = 0;
@@ -293,33 +161,28 @@
 
 	/* Get the register bitmask for this GPE */
 
-	bit_mask = gpe_event_info->bit_mask;
-
-	/* GPE Enabled? */
+	register_bit = gpe_event_info->register_bit;
 
-	status = acpi_hw_low_level_read (8, &in_byte, &gpe_register_info->enable_address);
-	if (ACPI_FAILURE (status)) {
-		goto unlock_and_exit;
-	}
+	/* GPE currently enabled? (enabled for runtime?) */
 
-	if (bit_mask & in_byte) {
+	if (register_bit & gpe_register_info->enable_for_run) {
 		local_event_status |= ACPI_EVENT_FLAG_ENABLED;
 	}
 
-	/* GPE Enabled for wake? */
+	/* GPE enabled for wake? */
 
-	if (bit_mask & gpe_register_info->wake_enable) {
+	if (register_bit & gpe_register_info->enable_for_wake) {
 		local_event_status |= ACPI_EVENT_FLAG_WAKE_ENABLED;
 	}
 
-	/* GPE active (set)? */
+	/* GPE currently active (status bit == 1)? */
 
 	status = acpi_hw_low_level_read (8, &in_byte, &gpe_register_info->status_address);
 	if (ACPI_FAILURE (status)) {
 		goto unlock_and_exit;
 	}
 
-	if (bit_mask & in_byte) {
+	if (register_bit & in_byte) {
 		local_event_status |= ACPI_EVENT_FLAG_SET;
 	}
 
@@ -411,64 +274,43 @@
 
 /******************************************************************************
  *
- * FUNCTION:    acpi_hw_prepare_gpe_block_for_sleep
+ * FUNCTION:    acpi_hw_enable_runtime_gpe_block
  *
  * PARAMETERS:  gpe_xrupt_info      - GPE Interrupt info
  *              gpe_block           - Gpe Block info
  *
  * RETURN:      Status
  *
- * DESCRIPTION: Disable all runtime GPEs and enable all wakeup GPEs -- within
- *              a single GPE block
+ * DESCRIPTION: Enable all "runtime" GPEs within a GPE block. (Includes
+ *              combination wake/run GPEs.)
  *
  ******************************************************************************/
 
-static acpi_status
-acpi_hw_prepare_gpe_block_for_sleep (
+acpi_status
+acpi_hw_enable_runtime_gpe_block (
 	struct acpi_gpe_xrupt_info      *gpe_xrupt_info,
 	struct acpi_gpe_block_info      *gpe_block)
 {
 	u32                             i;
-	struct acpi_gpe_register_info   *gpe_register_info;
-	u32                             in_value;
 	acpi_status                     status;
 
 
-	/* Get the register info for the entire GPE block */
-
-	gpe_register_info = gpe_block->register_info;
+	/* NOTE: assumes that all GPEs are currently disabled */
 
 	/* Examine each GPE Register within the block */
 
 	for (i = 0; i < gpe_block->register_count; i++) {
-		/*
-		 * Read the enabled/disabled status of all GPEs. We
-		 * will be using it to restore all the GPEs later.
-		 *
-		 * NOTE:  Wake GPEs are are ALL disabled at this time, so when we wake
-		 * and restore this register, they will be automatically disabled.
-		 */
-		status = acpi_hw_low_level_read (8, &in_value,
-				 &gpe_register_info->enable_address);
-		if (ACPI_FAILURE (status)) {
-			return (status);
+		if (!gpe_block->register_info[i].enable_for_run) {
+			continue;
 		}
 
-		gpe_register_info->enable = (u8) in_value;
+		/* Enable all "runtime" GPEs in this register */
 
-		/*
-		 * 1) Disable all runtime GPEs
-		 * 2) Enable all wakeup GPEs
-		 */
-		status = acpi_hw_low_level_write (8, gpe_register_info->wake_enable,
-				&gpe_register_info->enable_address);
+		status = acpi_hw_low_level_write (8, gpe_block->register_info[i].enable_for_run,
+				 &gpe_block->register_info[i].enable_address);
 		if (ACPI_FAILURE (status)) {
 			return (status);
 		}
-
-		/* Point to next GPE register */
-
-		gpe_register_info++;
 	}
 
 	return (AE_OK);
@@ -477,122 +319,125 @@
 
 /******************************************************************************
  *
- * FUNCTION:    acpi_hw_prepare_gpes_for_sleep
+ * FUNCTION:    acpi_hw_enable_wakeup_gpe_block
  *
- * PARAMETERS:  None
+ * PARAMETERS:  gpe_xrupt_info      - GPE Interrupt info
+ *              gpe_block           - Gpe Block info
  *
  * RETURN:      Status
  *
- * DESCRIPTION: Disable all runtime GPEs, enable all wake GPEs.
- *              Called with interrupts disabled. The interrupt handler also
- *              modifies gpe_register_info->Enable, so it should not be
- *              given the chance to run until after the runtime GPEs are
- *              re-enabled.
+ * DESCRIPTION: Enable all "wake" GPEs within a GPE block.  (Includes
+ *              combination wake/run GPEs.)
  *
  ******************************************************************************/
 
 acpi_status
-acpi_hw_prepare_gpes_for_sleep (
-	void)
+acpi_hw_enable_wakeup_gpe_block (
+	struct acpi_gpe_xrupt_info      *gpe_xrupt_info,
+	struct acpi_gpe_block_info      *gpe_block)
 {
+	u32                             i;
 	acpi_status                     status;
 
 
-	ACPI_FUNCTION_ENTRY ();
+	/* Examine each GPE Register within the block */
 
+	for (i = 0; i < gpe_block->register_count; i++) {
+		if (!gpe_block->register_info[i].enable_for_wake) {
+			continue;
+		}
 
-	status = acpi_ev_walk_gpe_list (acpi_hw_prepare_gpe_block_for_sleep);
-	return (status);
+		/* Enable all "wake" GPEs in this register */
+
+		status = acpi_hw_low_level_write (8, gpe_block->register_info[i].enable_for_wake,
+				 &gpe_block->register_info[i].enable_address);
+		if (ACPI_FAILURE (status)) {
+			return (status);
+		}
+	}
+
+	return (AE_OK);
 }
 
 
 /******************************************************************************
  *
- * FUNCTION:    acpi_hw_restore_gpe_block_on_wake
+ * FUNCTION:    acpi_hw_disable_all_gpes
  *
- * PARAMETERS:  gpe_xrupt_info      - GPE Interrupt info
- *              gpe_block           - Gpe Block info
+ * PARAMETERS:  Flags           - ACPI_NOT_ISR or ACPI_ISR
  *
  * RETURN:      Status
  *
- * DESCRIPTION: Enable all runtime GPEs and disable all wake GPEs -- in one
- *              GPE block
+ * DESCRIPTION: Disable and clear all GPEs
  *
  ******************************************************************************/
 
-static acpi_status
-acpi_hw_restore_gpe_block_on_wake (
-	struct acpi_gpe_xrupt_info      *gpe_xrupt_info,
-	struct acpi_gpe_block_info      *gpe_block)
+acpi_status
+acpi_hw_disable_all_gpes (
+	u32                             flags)
 {
-	u32                             i;
-	struct acpi_gpe_register_info   *gpe_register_info;
 	acpi_status                     status;
 
 
-	/* This callback processes one entire GPE block */
+	ACPI_FUNCTION_TRACE ("hw_disable_all_gpes");
 
-	/* Get the register info for the entire GPE block */
 
-	gpe_register_info = gpe_block->register_info;
+	status = acpi_ev_walk_gpe_list (acpi_hw_disable_gpe_block, flags);
+	status = acpi_ev_walk_gpe_list (acpi_hw_clear_gpe_block, flags);
+	return_ACPI_STATUS (status);
+}
 
-	/* Examine each GPE register within the block */
 
-	for (i = 0; i < gpe_block->register_count; i++) {
-		/* Clear the entire status register */
+/******************************************************************************
+ *
+ * FUNCTION:    acpi_hw_enable_all_runtime_gpes
+ *
+ * PARAMETERS:  Flags           - ACPI_NOT_ISR or ACPI_ISR
+ *
+ * RETURN:      Status
+ *
+ * DESCRIPTION: Enable all GPEs of the given type
+ *
+ ******************************************************************************/
 
-		status = acpi_hw_low_level_write (8, 0xFF,
-				 &gpe_block->register_info[i].status_address);
-		if (ACPI_FAILURE (status)) {
-			return (status);
-		}
+acpi_status
+acpi_hw_enable_all_runtime_gpes (
+	u32                             flags)
+{
+	acpi_status                     status;
 
-		/*
-		 * Restore the GPE Enable register, which will do the following:
-		 *
-		 * 1) Disable all wakeup GPEs
-		 * 2) Enable all runtime GPEs
-		 *
-		 *  (On sleep, we saved the enabled status of all GPEs)
-		 */
-		status = acpi_hw_low_level_write (8, gpe_register_info->enable,
-				 &gpe_register_info->enable_address);
-		if (ACPI_FAILURE (status)) {
-			return (status);
-		}
 
-		/* Point to next GPE register */
+	ACPI_FUNCTION_TRACE ("hw_enable_all_runtime_gpes");
 
-		gpe_register_info++;
-	}
 
-	return (AE_OK);
+	status = acpi_ev_walk_gpe_list (acpi_hw_enable_runtime_gpe_block, flags);
+	return_ACPI_STATUS (status);
 }
 
 
 /******************************************************************************
  *
- * FUNCTION:    acpi_hw_restore_gpes_on_wake
+ * FUNCTION:    acpi_hw_enable_all_wakeup_gpes
  *
- * PARAMETERS:  None
+ * PARAMETERS:  Flags           - ACPI_NOT_ISR or ACPI_ISR
  *
  * RETURN:      Status
  *
- * DESCRIPTION: Enable all runtime GPEs and disable all wake GPEs -- in all
- *              GPE blocks
+ * DESCRIPTION: Enable all GPEs of the given type
  *
  ******************************************************************************/
 
 acpi_status
-acpi_hw_restore_gpes_on_wake (
-	void)
+acpi_hw_enable_all_wakeup_gpes (
+	u32                             flags)
 {
 	acpi_status                     status;
 
 
-	ACPI_FUNCTION_ENTRY ();
+	ACPI_FUNCTION_TRACE ("hw_enable_all_wakeup_gpes");
 
 
-	status = acpi_ev_walk_gpe_list (acpi_hw_restore_gpe_block_on_wake);
-	return (status);
+	status = acpi_ev_walk_gpe_list (acpi_hw_enable_wakeup_gpe_block, flags);
+	return_ACPI_STATUS (status);
 }
+
diff -Nru a/drivers/acpi/hardware/hwregs.c b/drivers/acpi/hardware/hwregs.c
--- a/drivers/acpi/hardware/hwregs.c	2004-10-18 14:56:50 -07:00
+++ b/drivers/acpi/hardware/hwregs.c	2004-10-18 14:56:50 -07:00
@@ -61,6 +61,7 @@
  * RETURN:      none
  *
  * DESCRIPTION: Clears all fixed and general purpose status bits
+ *              THIS FUNCTION MUST BE CALLED WITH INTERRUPTS DISABLED
  *
  ******************************************************************************/
 
@@ -103,7 +104,7 @@
 
 	/* Clear the GPE Bits in all GPE registers in all GPE blocks */
 
-	status = acpi_ev_walk_gpe_list (acpi_hw_clear_gpe_block);
+	status = acpi_ev_walk_gpe_list (acpi_hw_clear_gpe_block, ACPI_ISR);
 
 unlock_and_exit:
 	if (flags & ACPI_MTX_LOCK) {
@@ -135,7 +136,7 @@
 	u8                              *sleep_type_b)
 {
 	acpi_status                     status = AE_OK;
-	union acpi_operand_object       *obj_desc;
+	struct acpi_parameter_info      info;
 
 
 	ACPI_FUNCTION_TRACE ("acpi_get_sleep_type_data");
@@ -152,8 +153,9 @@
 	/*
 	 * Evaluate the namespace object containing the values for this state
 	 */
+	info.parameters = NULL;
 	status = acpi_ns_evaluate_by_name ((char *) acpi_gbl_sleep_state_names[sleep_state],
-			  NULL, &obj_desc);
+			  &info);
 	if (ACPI_FAILURE (status)) {
 		ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "%s while evaluating sleep_state [%s]\n",
 			acpi_format_exception (status), acpi_gbl_sleep_state_names[sleep_state]));
@@ -163,48 +165,50 @@
 
 	/* Must have a return object */
 
-	if (!obj_desc) {
+	if (!info.return_object) {
 		ACPI_REPORT_ERROR (("Missing Sleep State object\n"));
 		status = AE_NOT_EXIST;
 	}
 
 	/* It must be of type Package */
 
-	else if (ACPI_GET_OBJECT_TYPE (obj_desc) != ACPI_TYPE_PACKAGE) {
+	else if (ACPI_GET_OBJECT_TYPE (info.return_object) != ACPI_TYPE_PACKAGE) {
 		ACPI_REPORT_ERROR (("Sleep State object not a Package\n"));
 		status = AE_AML_OPERAND_TYPE;
 	}
 
 	/* The package must have at least two elements */
 
-	else if (obj_desc->package.count < 2) {
+	else if (info.return_object->package.count < 2) {
 		ACPI_REPORT_ERROR (("Sleep State package does not have at least two elements\n"));
 		status = AE_AML_NO_OPERAND;
 	}
 
 	/* The first two elements must both be of type Integer */
 
-	else if ((ACPI_GET_OBJECT_TYPE (obj_desc->package.elements[0]) != ACPI_TYPE_INTEGER) ||
-			 (ACPI_GET_OBJECT_TYPE (obj_desc->package.elements[1]) != ACPI_TYPE_INTEGER)) {
+	else if ((ACPI_GET_OBJECT_TYPE (info.return_object->package.elements[0]) != ACPI_TYPE_INTEGER) ||
+			 (ACPI_GET_OBJECT_TYPE (info.return_object->package.elements[1]) != ACPI_TYPE_INTEGER)) {
 		ACPI_REPORT_ERROR (("Sleep State package elements are not both Integers (%s, %s)\n",
-			acpi_ut_get_object_type_name (obj_desc->package.elements[0]),
-			acpi_ut_get_object_type_name (obj_desc->package.elements[1])));
+			acpi_ut_get_object_type_name (info.return_object->package.elements[0]),
+			acpi_ut_get_object_type_name (info.return_object->package.elements[1])));
 		status = AE_AML_OPERAND_TYPE;
 	}
 	else {
 		/*
 		 * Valid _Sx_ package size, type, and value
 		 */
-		*sleep_type_a = (u8) (obj_desc->package.elements[0])->integer.value;
-		*sleep_type_b = (u8) (obj_desc->package.elements[1])->integer.value;
+		*sleep_type_a = (u8) (info.return_object->package.elements[0])->integer.value;
+		*sleep_type_b = (u8) (info.return_object->package.elements[1])->integer.value;
 	}
 
 	if (ACPI_FAILURE (status)) {
-		ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "While evaluating sleep_state [%s], bad Sleep object %p type %s\n",
-			acpi_gbl_sleep_state_names[sleep_state], obj_desc, acpi_ut_get_object_type_name (obj_desc)));
+		ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
+			"While evaluating sleep_state [%s], bad Sleep object %p type %s\n",
+			acpi_gbl_sleep_state_names[sleep_state], info.return_object,
+			acpi_ut_get_object_type_name (info.return_object)));
 	}
 
-	acpi_ut_remove_reference (obj_desc);
+	acpi_ut_remove_reference (info.return_object);
 	return_ACPI_STATUS (status);
 }
 
@@ -245,8 +249,8 @@
  *              return_value    - Value that was read from the register
  *              Flags           - Lock the hardware or not
  *
- * RETURN:      Value is read from specified Register.  Value returned is
- *              normalized to bit0 (is shifted all the way right)
+ * RETURN:      Status and the value read from specified Register.  Value
+ *              returned is normalized to bit0 (is shifted all the way right)
  *
  * DESCRIPTION: ACPI bit_register read function.
  *
@@ -280,6 +284,8 @@
 		}
 	}
 
+	/* Read from the register */
+
 	status = acpi_hw_register_read (ACPI_MTX_DO_NOT_LOCK,
 			  bit_reg_info->parent_register, &register_value);
 
@@ -309,10 +315,10 @@
  *
  * PARAMETERS:  register_id     - ID of ACPI bit_register to access
  *              Value           - (only used on write) value to write to the
- *                                Register, NOT pre-normalized to the bit pos.
+ *                                Register, NOT pre-normalized to the bit pos
  *              Flags           - Lock the hardware or not
  *
- * RETURN:      None
+ * RETURN:      Status
  *
  * DESCRIPTION: ACPI Bit Register write function.
  *
@@ -457,10 +463,11 @@
  *
  * FUNCTION:    acpi_hw_register_read
  *
- * PARAMETERS:  use_lock               - Mutex hw access.
- *              register_id            - register_iD + Offset.
+ * PARAMETERS:  use_lock            - Mutex hw access
+ *              register_id         - register_iD + Offset
+ *              return_value        - Value that was read from the register
  *
- * RETURN:      Value read or written.
+ * RETURN:      Status and the value read.
  *
  * DESCRIPTION: Acpi register read function.  Registers are read at the
  *              given offset.
@@ -568,10 +575,11 @@
  *
  * FUNCTION:    acpi_hw_register_write
  *
- * PARAMETERS:  use_lock               - Mutex hw access.
- *              register_id            - register_iD + Offset.
+ * PARAMETERS:  use_lock            - Mutex hw access
+ *              register_id         - register_iD + Offset
+ *              Value               - The value to write
  *
- * RETURN:      Value read or written.
+ * RETURN:      Status
  *
  * DESCRIPTION: Acpi register Write function.  Registers are written at the
  *              given offset.
@@ -687,11 +695,11 @@
  *
  * PARAMETERS:  Width               - 8, 16, or 32
  *              Value               - Where the value is returned
- *              Register            - GAS register structure
+ *              Reg                 - GAS register structure
  *
  * RETURN:      Status
  *
- * DESCRIPTION: Read from either memory, IO, or PCI config space.
+ * DESCRIPTION: Read from either memory or IO space.
  *
  ******************************************************************************/
 
@@ -701,8 +709,6 @@
 	u32                             *value,
 	struct acpi_generic_address     *reg)
 {
-	struct acpi_pci_id              pci_id;
-	u16                             pci_register;
 	acpi_status                     status;
 
 
@@ -721,8 +727,8 @@
 	*value = 0;
 
 	/*
-	 * Three address spaces supported:
-	 * Memory, IO, or PCI_Config.
+	 * Two address spaces supported: Memory or IO.
+	 * PCI_Config is not supported here because the GAS struct is insufficient
 	 */
 	switch (reg->address_space_id) {
 	case ACPI_ADR_SPACE_SYSTEM_MEMORY:
@@ -740,19 +746,6 @@
 		break;
 
 
-	case ACPI_ADR_SPACE_PCI_CONFIG:
-
-		pci_id.segment = 0;
-		pci_id.bus     = 0;
-		pci_id.device  = ACPI_PCI_DEVICE (reg->address);
-		pci_id.function = ACPI_PCI_FUNCTION (reg->address);
-		pci_register   = (u16) ACPI_PCI_REGISTER (reg->address);
-
-		status = acpi_os_read_pci_configuration (&pci_id, pci_register,
-				 value, width);
-		break;
-
-
 	default:
 		ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
 			"Unsupported address space: %X\n", reg->address_space_id));
@@ -774,11 +767,11 @@
  *
  * PARAMETERS:  Width               - 8, 16, or 32
  *              Value               - To be written
- *              Register            - GAS register structure
+ *              Reg                 - GAS register structure
  *
  * RETURN:      Status
  *
- * DESCRIPTION: Write to either memory, IO, or PCI config space.
+ * DESCRIPTION: Write to either memory or IO space.
  *
  ******************************************************************************/
 
@@ -788,8 +781,6 @@
 	u32                             value,
 	struct acpi_generic_address     *reg)
 {
-	struct acpi_pci_id              pci_id;
-	u16                             pci_register;
 	acpi_status                     status;
 
 
@@ -807,8 +798,8 @@
 	}
 
 	/*
-	 * Three address spaces supported:
-	 * Memory, IO, or PCI_Config.
+	 * Two address spaces supported: Memory or IO.
+	 * PCI_Config is not supported here because the GAS struct is insufficient
 	 */
 	switch (reg->address_space_id) {
 	case ACPI_ADR_SPACE_SYSTEM_MEMORY:
@@ -823,19 +814,6 @@
 
 		status = acpi_os_write_port ((acpi_io_address) reg->address,
 				 value, width);
-		break;
-
-
-	case ACPI_ADR_SPACE_PCI_CONFIG:
-
-		pci_id.segment = 0;
-		pci_id.bus     = 0;
-		pci_id.device  = ACPI_PCI_DEVICE (reg->address);
-		pci_id.function = ACPI_PCI_FUNCTION (reg->address);
-		pci_register   = (u16) ACPI_PCI_REGISTER (reg->address);
-
-		status = acpi_os_write_pci_configuration (&pci_id, pci_register,
-				 (acpi_integer) value, width);
 		break;
 
 
diff -Nru a/drivers/acpi/hardware/hwsleep.c b/drivers/acpi/hardware/hwsleep.c
--- a/drivers/acpi/hardware/hwsleep.c	2004-10-18 14:55:54 -07:00
+++ b/drivers/acpi/hardware/hwsleep.c	2004-10-18 14:55:54 -07:00
@@ -265,19 +265,21 @@
 	sleep_type_reg_info = acpi_hw_get_bit_register_info (ACPI_BITREG_SLEEP_TYPE_A);
 	sleep_enable_reg_info = acpi_hw_get_bit_register_info (ACPI_BITREG_SLEEP_ENABLE);
 
-	if (sleep_state != ACPI_STATE_S5) {
-		/* Clear wake status */
+	/* Clear wake status */
 
-		status = acpi_set_register (ACPI_BITREG_WAKE_STATUS, 1, ACPI_MTX_DO_NOT_LOCK);
-		if (ACPI_FAILURE (status)) {
-			return_ACPI_STATUS (status);
-		}
+	status = acpi_set_register (ACPI_BITREG_WAKE_STATUS, 1, ACPI_MTX_DO_NOT_LOCK);
+	if (ACPI_FAILURE (status)) {
+		return_ACPI_STATUS (status);
+	}
 
-		status = acpi_hw_clear_acpi_status (ACPI_MTX_DO_NOT_LOCK);
-		if (ACPI_FAILURE (status)) {
-			return_ACPI_STATUS (status);
-		}
+	/* Clear all fixed and general purpose status bits */
 
+	status = acpi_hw_clear_acpi_status (ACPI_MTX_DO_NOT_LOCK);
+	if (ACPI_FAILURE (status)) {
+		return_ACPI_STATUS (status);
+	}
+
+	if (sleep_state != ACPI_STATE_S5) {
 		/* Disable BM arbitration */
 
 		status = acpi_set_register (ACPI_BITREG_ARB_DISABLE, 1, ACPI_MTX_DO_NOT_LOCK);
@@ -287,10 +289,16 @@
 	}
 
 	/*
-	 * 1) Disable all runtime GPEs
+	 * 1) Disable/Clear all GPEs
 	 * 2) Enable all wakeup GPEs
 	 */
-	status = acpi_hw_prepare_gpes_for_sleep ();
+	status = acpi_hw_disable_all_gpes (ACPI_ISR);
+	if (ACPI_FAILURE (status)) {
+		return_ACPI_STATUS (status);
+	}
+	acpi_gbl_system_awake_and_running = FALSE;
+
+	status = acpi_hw_enable_all_wakeup_gpes (ACPI_ISR);
 	if (ACPI_FAILURE (status)) {
 		return_ACPI_STATUS (status);
 	}
@@ -420,10 +428,16 @@
 	}
 
 	/*
-	 * 1) Disable all runtime GPEs
+	 * 1) Disable/Clear all GPEs
 	 * 2) Enable all wakeup GPEs
 	 */
-	status = acpi_hw_prepare_gpes_for_sleep ();
+	status = acpi_hw_disable_all_gpes (ACPI_ISR);
+	if (ACPI_FAILURE (status)) {
+		return_ACPI_STATUS (status);
+	}
+	acpi_gbl_system_awake_and_running = FALSE;
+
+	status = acpi_hw_enable_all_wakeup_gpes (ACPI_ISR);
 	if (ACPI_FAILURE (status)) {
 		return_ACPI_STATUS (status);
 	}
@@ -453,6 +467,7 @@
  * RETURN:      Status
  *
  * DESCRIPTION: Perform OS-independent ACPI cleanup after a sleep
+ *              Called with interrupts ENABLED.
  *
  ******************************************************************************/
 
@@ -540,19 +555,25 @@
 
 	/*
 	 * Restore the GPEs:
-	 * 1) Disable all wakeup GPEs
+	 * 1) Disable/Clear all GPEs
 	 * 2) Enable all runtime GPEs
 	 */
-	status = acpi_hw_restore_gpes_on_wake ();
+	status = acpi_hw_disable_all_gpes (ACPI_NOT_ISR);
+	if (ACPI_FAILURE (status)) {
+		return_ACPI_STATUS (status);
+	}
+	acpi_gbl_system_awake_and_running = TRUE;
+
+	status = acpi_hw_enable_all_runtime_gpes (ACPI_NOT_ISR);
 	if (ACPI_FAILURE (status)) {
 		return_ACPI_STATUS (status);
 	}
 
 	/* Enable power button */
 
-	acpi_set_register(acpi_gbl_fixed_event_info[ACPI_EVENT_POWER_BUTTON].enable_register_id,
+	(void) acpi_set_register(acpi_gbl_fixed_event_info[ACPI_EVENT_POWER_BUTTON].enable_register_id,
 			1, ACPI_MTX_DO_NOT_LOCK);
-	acpi_set_register(acpi_gbl_fixed_event_info[ACPI_EVENT_POWER_BUTTON].status_register_id,
+	(void) acpi_set_register(acpi_gbl_fixed_event_info[ACPI_EVENT_POWER_BUTTON].status_register_id,
 			1, ACPI_MTX_DO_NOT_LOCK);
 
 	/* Enable BM arbitration */
diff -Nru a/drivers/acpi/hardware/hwtimer.c b/drivers/acpi/hardware/hwtimer.c
--- a/drivers/acpi/hardware/hwtimer.c	2004-10-18 14:55:55 -07:00
+++ b/drivers/acpi/hardware/hwtimer.c	2004-10-18 14:55:55 -07:00
@@ -52,11 +52,11 @@
  *
  * FUNCTION:    acpi_get_timer_resolution
  *
- * PARAMETERS:  none
+ * PARAMETERS:  Resolution          - Where the resolution is returned
  *
- * RETURN:      Number of bits of resolution in the PM Timer (24 or 32).
+ * RETURN:      Status and timer resolution
  *
- * DESCRIPTION: Obtains resolution of the ACPI PM Timer.
+ * DESCRIPTION: Obtains resolution of the ACPI PM Timer (24 or 32 bits).
  *
  ******************************************************************************/
 
@@ -86,11 +86,11 @@
  *
  * FUNCTION:    acpi_get_timer
  *
- * PARAMETERS:  none
+ * PARAMETERS:  Ticks               - Where the timer value is returned
  *
- * RETURN:      Current value of the ACPI PM Timer (in ticks).
+ * RETURN:      Status and current ticks
  *
- * DESCRIPTION: Obtains current value of ACPI PM Timer.
+ * DESCRIPTION: Obtains current value of ACPI PM Timer (in ticks).
  *
  ******************************************************************************/
 
@@ -118,11 +118,11 @@
  *
  * FUNCTION:    acpi_get_timer_duration
  *
- * PARAMETERS:  start_ticks
- *              end_ticks
- *              time_elapsed
+ * PARAMETERS:  start_ticks         - Starting timestamp
+ *              end_ticks           - End timestamp
+ *              time_elapsed        - Where the elapsed time is returned
  *
- * RETURN:      time_elapsed
+ * RETURN:      Status and time_elapsed
  *
  * DESCRIPTION: Computes the time elapsed (in microseconds) between two
  *              PM Timer time stamps, taking into account the possibility of
@@ -136,7 +136,7 @@
  *              Note that this function accommodates only a single timer
  *              rollover.  Thus for 24-bit timers, this function should only
  *              be used for calculating durations less than ~4.6 seconds
- *              (~20 minutes for 32-bit timers) -- calculations below
+ *              (~20 minutes for 32-bit timers) -- calculations below:
  *
  *              2**24 Ticks / 3,600,000 Ticks/Sec = 4.66 sec
  *              2**32 Ticks / 3,600,000 Ticks/Sec = 1193 sec or 19.88 minutes
@@ -164,7 +164,6 @@
 
 	/*
 	 * Compute Tick Delta:
-	 * -------------------
 	 * Handle (max one) timer rollovers on 24- versus 32-bit timers.
 	 */
 	if (start_ticks < end_ticks) {
@@ -188,10 +187,7 @@
 	}
 
 	/*
-	 * Compute Duration:
-	 * -----------------
-	 *
-	 * Requires a 64-bit divide:
+	 * Compute Duration (Requires a 64-bit divide):
 	 *
 	 * time_elapsed = (delta_ticks * 1000000) / PM_TIMER_FREQUENCY;
 	 */
diff -Nru a/drivers/acpi/motherboard.c b/drivers/acpi/motherboard.c
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/drivers/acpi/motherboard.c	2004-10-18 14:57:23 -07:00
@@ -0,0 +1,177 @@
+/* 
+ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ *  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.
+ *
+ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ */
+
+/* Purpose: Prevent PCMCIA cards from using motherboard resources. */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/types.h>
+#include <linux/pci.h>
+#include <linux/ioport.h>
+#include <asm/io.h>
+
+#include <acpi/acpi_bus.h>
+#include <acpi/acpi_drivers.h>
+
+#define _COMPONENT		ACPI_SYSTEM_COMPONENT
+ACPI_MODULE_NAME		("acpi_motherboard")
+
+/* Dell use PNP0C01 instead of PNP0C02 */
+#define ACPI_MB_HID1			"PNP0C01"
+#define ACPI_MB_HID2			"PNP0C02"
+
+/**
+ * Doesn't care about legacy IO ports, only IO ports beyond 0x1000 are reserved
+ * Doesn't care about the failure of 'request_region', since other may reserve 
+ * the io ports as well
+ */
+#define IS_RESERVED_ADDR(base, len) \
+	(((len) > 0) && ((base) > 0) && ((base) + (len) < IO_SPACE_LIMIT) \
+	&& ((base) + (len) > PCIBIOS_MIN_IO))
+
+/*
+ * Clearing the flag (IORESOURCE_BUSY) allows drivers to use
+ * the io ports if they really know they can use it, while
+ * still preventing hotplug PCI devices from using it. 
+ */
+
+static acpi_status
+acpi_reserve_io_ranges (struct acpi_resource *res, void *data)
+{
+	struct resource *requested_res = NULL;
+
+	ACPI_FUNCTION_TRACE("acpi_reserve_io_ranges");
+
+	if (res->id == ACPI_RSTYPE_IO) {
+		struct acpi_resource_io *io_res = &res->data.io;
+
+		if (io_res->min_base_address != io_res->max_base_address)
+			return AE_OK;
+		if (IS_RESERVED_ADDR(io_res->min_base_address, io_res->range_length)) {
+			ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Motherboard resources 0x%08x - 0x%08x\n",
+				io_res->min_base_address, 
+				io_res->min_base_address + io_res->range_length));
+			requested_res = request_region(io_res->min_base_address, 
+				io_res->range_length, "motherboard");
+		}
+	} else if (res->id == ACPI_RSTYPE_FIXED_IO) {
+		struct acpi_resource_fixed_io *fixed_io_res = &res->data.fixed_io;
+
+		if (IS_RESERVED_ADDR(fixed_io_res->base_address, fixed_io_res->range_length)) {
+			ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Motherboard resources 0x%08x - 0x%08x\n",
+				fixed_io_res->base_address, 
+				fixed_io_res->base_address + fixed_io_res->range_length));
+			requested_res = request_region(fixed_io_res->base_address, 
+				fixed_io_res->range_length, "motherboard");
+		}
+	} else {
+		/* Memory mapped IO? */
+	}
+
+	if (requested_res)
+		requested_res->flags &= ~IORESOURCE_BUSY;
+	return AE_OK;
+}
+
+static int acpi_motherboard_add (struct acpi_device *device)
+{
+	if (!device)
+		return -EINVAL;
+	acpi_walk_resources(device->handle, METHOD_NAME__CRS, 
+		acpi_reserve_io_ranges, NULL);
+
+	return 0;
+}
+
+static struct acpi_driver acpi_motherboard_driver1 = {
+	.name =		"motherboard",
+	.class =	"",
+	.ids =		ACPI_MB_HID1,
+	.ops =	{
+		.add =		acpi_motherboard_add,
+	},
+};
+
+static struct acpi_driver acpi_motherboard_driver2 = {
+	.name =		"motherboard",
+	.class =	"",
+	.ids =		ACPI_MB_HID2,
+	.ops =	{
+		.add =		acpi_motherboard_add,
+	},
+};
+
+static void __init
+acpi_reserve_resources (void)
+{
+	if (acpi_gbl_FADT->xpm1a_evt_blk.address && acpi_gbl_FADT->pm1_evt_len)
+		request_region(acpi_gbl_FADT->xpm1a_evt_blk.address, 
+			acpi_gbl_FADT->pm1_evt_len, "PM1a_EVT_BLK");
+
+	if (acpi_gbl_FADT->xpm1b_evt_blk.address && acpi_gbl_FADT->pm1_evt_len)
+		request_region(acpi_gbl_FADT->xpm1b_evt_blk.address,
+			acpi_gbl_FADT->pm1_evt_len, "PM1b_EVT_BLK");
+
+	if (acpi_gbl_FADT->xpm1a_cnt_blk.address && acpi_gbl_FADT->pm1_cnt_len)
+		request_region(acpi_gbl_FADT->xpm1a_cnt_blk.address, 
+			acpi_gbl_FADT->pm1_cnt_len, "PM1a_CNT_BLK");
+
+	if (acpi_gbl_FADT->xpm1b_cnt_blk.address && acpi_gbl_FADT->pm1_cnt_len)
+		request_region(acpi_gbl_FADT->xpm1b_cnt_blk.address, 
+			acpi_gbl_FADT->pm1_cnt_len, "PM1b_CNT_BLK");
+
+	if (acpi_gbl_FADT->xpm_tmr_blk.address && acpi_gbl_FADT->pm_tm_len == 4)
+		request_region(acpi_gbl_FADT->xpm_tmr_blk.address,
+			4, "PM_TMR");
+
+	if (acpi_gbl_FADT->xpm2_cnt_blk.address && acpi_gbl_FADT->pm2_cnt_len)
+		request_region(acpi_gbl_FADT->xpm2_cnt_blk.address,
+			acpi_gbl_FADT->pm2_cnt_len, "PM2_CNT_BLK");
+
+	/* Length of GPE blocks must be a non-negative multiple of 2 */
+
+	if (acpi_gbl_FADT->xgpe0_blk.address && acpi_gbl_FADT->gpe0_blk_len &&
+			!(acpi_gbl_FADT->gpe0_blk_len & 0x1))
+		request_region(acpi_gbl_FADT->xgpe0_blk.address,
+			acpi_gbl_FADT->gpe0_blk_len, "GPE0_BLK");
+
+	if (acpi_gbl_FADT->xgpe1_blk.address && acpi_gbl_FADT->gpe1_blk_len &&
+			!(acpi_gbl_FADT->gpe1_blk_len & 0x1))
+		request_region(acpi_gbl_FADT->xgpe1_blk.address,
+			acpi_gbl_FADT->gpe1_blk_len, "GPE1_BLK");
+}
+
+static int __init acpi_motherboard_init(void)
+{
+	acpi_bus_register_driver(&acpi_motherboard_driver1);
+	acpi_bus_register_driver(&acpi_motherboard_driver2);
+	/* 
+	 * Guarantee motherboard IO reservation first
+	 * This module must run after scan.c
+	 */
+	if (!acpi_disabled)
+		acpi_reserve_resources ();
+	return 0;
+}
+
+/**
+ * Reserve motherboard resources after PCI claim BARs,
+ * but before PCI assign resources for uninitialized PCI devices
+ */
+fs_initcall(acpi_motherboard_init);
diff -Nru a/drivers/acpi/namespace/nsaccess.c b/drivers/acpi/namespace/nsaccess.c
--- a/drivers/acpi/namespace/nsaccess.c	2004-10-18 14:57:04 -07:00
+++ b/drivers/acpi/namespace/nsaccess.c	2004-10-18 14:57:04 -07:00
@@ -193,7 +193,7 @@
 			case ACPI_TYPE_MUTEX:
 
 				obj_desc->mutex.node = new_node;
-				obj_desc->mutex.sync_level = (u16) ACPI_STRTOUL
+				obj_desc->mutex.sync_level = (u8) ACPI_STRTOUL
 						  (val, NULL, 10);
 
 				if (ACPI_STRCMP (init_val->name, "_GL_") == 0) {
diff -Nru a/drivers/acpi/namespace/nsalloc.c b/drivers/acpi/namespace/nsalloc.c
--- a/drivers/acpi/namespace/nsalloc.c	2004-10-18 14:56:32 -07:00
+++ b/drivers/acpi/namespace/nsalloc.c	2004-10-18 14:56:32 -07:00
@@ -267,7 +267,7 @@
 	else {
 #ifdef ACPI_ALPHABETIC_NAMESPACE
 		/*
-		 * Walk the list whilst searching for the the correct
+		 * Walk the list whilst searching for the correct
 		 * alphabetic placement.
 		 */
 		previous_child_node = NULL;
diff -Nru a/drivers/acpi/namespace/nseval.c b/drivers/acpi/namespace/nseval.c
--- a/drivers/acpi/namespace/nseval.c	2004-10-18 14:56:29 -07:00
+++ b/drivers/acpi/namespace/nseval.c	2004-10-18 14:56:29 -07:00
@@ -77,13 +77,10 @@
 
 acpi_status
 acpi_ns_evaluate_relative (
-	struct acpi_namespace_node      *handle,
 	char                            *pathname,
-	union acpi_operand_object       **params,
-	union acpi_operand_object       **return_object)
+	struct acpi_parameter_info      *info)
 {
 	acpi_status                     status;
-	struct acpi_namespace_node      *prefix_node;
 	struct acpi_namespace_node      *node = NULL;
 	union acpi_generic_state        *scope_info;
 	char                            *internal_path = NULL;
@@ -95,7 +92,7 @@
 	/*
 	 * Must have a valid object handle
 	 */
-	if (!handle) {
+	if (!info || !info->node) {
 		return_ACPI_STATUS (AE_BAD_PARAMETER);
 	}
 
@@ -118,8 +115,8 @@
 		goto cleanup;
 	}
 
-	prefix_node = acpi_ns_map_handle_to_node (handle);
-	if (!prefix_node) {
+	info->node = acpi_ns_map_handle_to_node (info->node);
+	if (!info->node) {
 		(void) acpi_ut_release_mutex (ACPI_MTX_NAMESPACE);
 		status = AE_BAD_PARAMETER;
 		goto cleanup;
@@ -127,7 +124,7 @@
 
 	/* Lookup the name in the namespace */
 
-	scope_info->scope.node = prefix_node;
+	scope_info->scope.node = info->node;
 	status = acpi_ns_lookup (scope_info, internal_path, ACPI_TYPE_ANY,
 			 ACPI_IMODE_EXECUTE, ACPI_NS_NO_UPSEARCH, NULL,
 			 &node);
@@ -147,7 +144,8 @@
 	ACPI_DEBUG_PRINT ((ACPI_DB_NAMES, "%s [%p] Value %p\n",
 		pathname, node, acpi_ns_get_attached_object (node)));
 
-	status = acpi_ns_evaluate_by_handle (node, params, return_object);
+	info->node = node;
+	status = acpi_ns_evaluate_by_handle (info);
 
 	ACPI_DEBUG_PRINT ((ACPI_DB_NAMES, "*** Completed eval of object %s ***\n",
 		pathname));
@@ -166,6 +164,7 @@
  * FUNCTION:    acpi_ns_evaluate_by_name
  *
  * PARAMETERS:  Pathname            - Fully qualified pathname to the object
+ *              Info                - Contains:
  *              return_object       - Where to put method's return value (if
  *                                    any).  If NULL, no value is returned.
  *              Params              - List of parameters to pass to the method,
@@ -184,11 +183,9 @@
 acpi_status
 acpi_ns_evaluate_by_name (
 	char                            *pathname,
-	union acpi_operand_object       **params,
-	union acpi_operand_object       **return_object)
+	struct acpi_parameter_info      *info)
 {
 	acpi_status                     status;
-	struct acpi_namespace_node      *node = NULL;
 	char                            *internal_path = NULL;
 
 
@@ -211,7 +208,7 @@
 
 	status = acpi_ns_lookup (NULL, internal_path, ACPI_TYPE_ANY,
 			 ACPI_IMODE_EXECUTE, ACPI_NS_NO_UPSEARCH, NULL,
-			 &node);
+			 &info->node);
 
 	(void) acpi_ut_release_mutex (ACPI_MTX_NAMESPACE);
 
@@ -226,9 +223,9 @@
 	 * to evaluate it.
 	 */
 	ACPI_DEBUG_PRINT ((ACPI_DB_NAMES, "%s [%p] Value %p\n",
-		pathname, node, acpi_ns_get_attached_object (node)));
+		pathname, info->node, acpi_ns_get_attached_object (info->node)));
 
-	status = acpi_ns_evaluate_by_handle (node, params, return_object);
+	status = acpi_ns_evaluate_by_handle (info);
 
 	ACPI_DEBUG_PRINT ((ACPI_DB_NAMES, "*** Completed eval of object %s ***\n",
 		pathname));
@@ -254,6 +251,7 @@
  *              Params              - List of parameters to pass to the method,
  *                                    terminated by NULL.  Params itself may be
  *                                    NULL if no parameters are being passed.
+ *              param_type          - Type of Parameter list
  *              return_object       - Where to put method's return value (if
  *                                    any).  If NULL, no value is returned.
  *
@@ -267,13 +265,9 @@
 
 acpi_status
 acpi_ns_evaluate_by_handle (
-	struct acpi_namespace_node      *handle,
-	union acpi_operand_object       **params,
-	union acpi_operand_object       **return_object)
+	struct acpi_parameter_info      *info)
 {
-	struct acpi_namespace_node      *node;
 	acpi_status                     status;
-	union acpi_operand_object       *local_return_object;
 
 
 	ACPI_FUNCTION_TRACE ("ns_evaluate_by_handle");
@@ -287,15 +281,13 @@
 
 	/* Parameter Validation */
 
-	if (!handle) {
+	if (!info) {
 		return_ACPI_STATUS (AE_BAD_PARAMETER);
 	}
 
-	if (return_object) {
-		/* Initialize the return value to an invalid object */
+	/* Initialize the return value to an invalid object */
 
-		*return_object = NULL;
-	}
+	info->return_object = NULL;
 
 	/* Get the prefix handle and Node */
 
@@ -304,8 +296,8 @@
 		return_ACPI_STATUS (status);
 	}
 
-	node = acpi_ns_map_handle_to_node (handle);
-	if (!node) {
+	info->node = acpi_ns_map_handle_to_node (info->node);
+	if (!info->node) {
 		(void) acpi_ut_release_mutex (ACPI_MTX_NAMESPACE);
 		return_ACPI_STATUS (AE_BAD_PARAMETER);
 	}
@@ -315,8 +307,8 @@
 	 * so that proper scoping context will be established
 	 * before execution.
 	 */
-	if (acpi_ns_get_type (node) == ACPI_TYPE_LOCAL_METHOD_ALIAS) {
-		node = ACPI_CAST_PTR (struct acpi_namespace_node, node->object);
+	if (acpi_ns_get_type (info->node) == ACPI_TYPE_LOCAL_METHOD_ALIAS) {
+		info->node = ACPI_CAST_PTR (struct acpi_namespace_node, info->node->object);
 	}
 
 	/*
@@ -328,19 +320,18 @@
 	 * In both cases, the namespace is unlocked by the
 	 *  acpi_ns* procedure
 	 */
-	if (acpi_ns_get_type (node) == ACPI_TYPE_METHOD) {
+	if (acpi_ns_get_type (info->node) == ACPI_TYPE_METHOD) {
 		/*
 		 * Case 1) We have an actual control method to execute
 		 */
-		status = acpi_ns_execute_control_method (node, params,
-				 &local_return_object);
+		status = acpi_ns_execute_control_method (info);
 	}
 	else {
 		/*
 		 * Case 2) Object is NOT a method, just return its
 		 * current value
 		 */
-		status = acpi_ns_get_object_value (node, &local_return_object);
+		status = acpi_ns_get_object_value (info);
 	}
 
 	/*
@@ -348,20 +339,6 @@
 	 * be dealt with
 	 */
 	if (status == AE_CTRL_RETURN_VALUE) {
-		/*
-		 * If the Method returned a value and the caller
-		 * provided a place to store a returned value, Copy
-		 * the returned value to the object descriptor provided
-		 * by the caller.
-		 */
-		if (return_object) {
-			/*
-			 * Valid return object, copy the pointer to
-			 * the returned object
-			 */
-			*return_object = local_return_object;
-		}
-
 		/* Map AE_CTRL_RETURN_VALUE to AE_OK, we are done with it */
 
 		status = AE_OK;
@@ -396,9 +373,7 @@
 
 acpi_status
 acpi_ns_execute_control_method (
-	struct acpi_namespace_node      *method_node,
-	union acpi_operand_object       **params,
-	union acpi_operand_object       **return_obj_desc)
+	struct acpi_parameter_info      *info)
 {
 	acpi_status                     status;
 	union acpi_operand_object       *obj_desc;
@@ -409,7 +384,7 @@
 
 	/* Verify that there is a method associated with this object */
 
-	obj_desc = acpi_ns_get_attached_object (method_node);
+	obj_desc = acpi_ns_get_attached_object (info->node);
 	if (!obj_desc) {
 		ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "No attached method object\n"));
 
@@ -417,7 +392,7 @@
 		return_ACPI_STATUS (AE_NULL_OBJECT);
 	}
 
-	ACPI_DUMP_PATHNAME (method_node, "Execute Method:",
+	ACPI_DUMP_PATHNAME (info->node, "Execute Method:",
 		ACPI_LV_INFO, _COMPONENT);
 
 	ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "Method at AML address %p Length %X\n",
@@ -444,7 +419,7 @@
 		return_ACPI_STATUS (status);
 	}
 
-	status = acpi_psx_execute (method_node, params, return_obj_desc);
+	status = acpi_psx_execute (info);
 	acpi_ex_exit_interpreter ();
 
 	return_ACPI_STATUS (status);
@@ -468,11 +443,10 @@
 
 acpi_status
 acpi_ns_get_object_value (
-	struct acpi_namespace_node      *node,
-	union acpi_operand_object       **return_obj_desc)
+	struct acpi_parameter_info      *info)
 {
 	acpi_status                     status = AE_OK;
-	struct acpi_namespace_node      *resolved_node = node;
+	struct acpi_namespace_node      *resolved_node = info->node;
 
 
 	ACPI_FUNCTION_TRACE ("ns_get_object_value");
@@ -518,9 +492,9 @@
 
 		if (ACPI_SUCCESS (status)) {
 			status = AE_CTRL_RETURN_VALUE;
-			*return_obj_desc = ACPI_CAST_PTR (union acpi_operand_object, resolved_node);
+			info->return_object = ACPI_CAST_PTR (union acpi_operand_object, resolved_node);
 			ACPI_DEBUG_PRINT ((ACPI_DB_NAMES, "Returning object %p [%s]\n",
-				*return_obj_desc, acpi_ut_get_object_type_name (*return_obj_desc)));
+				info->return_object, acpi_ut_get_object_type_name (info->return_object)));
 		}
 	}
 
diff -Nru a/drivers/acpi/namespace/nsinit.c b/drivers/acpi/namespace/nsinit.c
--- a/drivers/acpi/namespace/nsinit.c	2004-10-18 14:56:28 -07:00
+++ b/drivers/acpi/namespace/nsinit.c	2004-10-18 14:56:28 -07:00
@@ -149,7 +149,7 @@
 		return_ACPI_STATUS (status);
 	}
 
-	/* Walk namespace for all objects of type Device or Processor */
+	/* Walk namespace for all objects */
 
 	status = acpi_ns_walk_namespace (ACPI_TYPE_ANY, ACPI_ROOT_OBJECT,
 			  ACPI_UINT32_MAX, TRUE, acpi_ns_init_one_device, &info, NULL);
@@ -337,25 +337,29 @@
 	void                            *context,
 	void                            **return_value)
 {
-	acpi_status                     status;
-	struct acpi_namespace_node     *node;
-	u32                             flags;
 	struct acpi_device_walk_info   *info = (struct acpi_device_walk_info *) context;
+	struct acpi_parameter_info      pinfo;
+	u32                             flags;
+	acpi_status                     status;
 
 
 	ACPI_FUNCTION_TRACE ("ns_init_one_device");
 
 
-	node = acpi_ns_map_handle_to_node (obj_handle);
-	if (!node) {
+	pinfo.parameters = NULL;
+	pinfo.parameter_type = ACPI_PARAM_ARGS;
+
+	pinfo.node = acpi_ns_map_handle_to_node (obj_handle);
+	if (!pinfo.node) {
 		return_ACPI_STATUS (AE_BAD_PARAMETER);
 	}
 
 	/*
-	 * We will run _STA/_INI on Devices and Processors only
+	 * We will run _STA/_INI on Devices, Processors and thermal_zones only
 	 */
-	if ((node->type != ACPI_TYPE_DEVICE) &&
-		(node->type != ACPI_TYPE_PROCESSOR)) {
+	if ((pinfo.node->type != ACPI_TYPE_DEVICE)      &&
+		(pinfo.node->type != ACPI_TYPE_PROCESSOR)   &&
+		(pinfo.node->type != ACPI_TYPE_THERMAL)) {
 		return_ACPI_STATUS (AE_OK);
 	}
 
@@ -368,17 +372,17 @@
 	/*
 	 * Run _STA to determine if we can run _INI on the device.
 	 */
-	ACPI_DEBUG_EXEC (acpi_ut_display_init_pathname (ACPI_TYPE_METHOD, node, "_STA"));
-	status = acpi_ut_execute_STA (node, &flags);
+	ACPI_DEBUG_EXEC (acpi_ut_display_init_pathname (ACPI_TYPE_METHOD, pinfo.node, "_STA"));
+	status = acpi_ut_execute_STA (pinfo.node, &flags);
 
 	if (ACPI_FAILURE (status)) {
-		if (node->type == ACPI_TYPE_DEVICE) {
+		if (pinfo.node->type == ACPI_TYPE_DEVICE) {
 			/* Ignore error and move on to next device */
 
 			return_ACPI_STATUS (AE_OK);
 		}
 
-		/* _STA is not required for Processor objects */
+		/* _STA is not required for Processor or thermal_zone objects */
 	}
 	else {
 		info->num_STA++;
@@ -393,22 +397,22 @@
 	/*
 	 * The device is present. Run _INI.
 	 */
-	ACPI_DEBUG_EXEC (acpi_ut_display_init_pathname (ACPI_TYPE_METHOD, obj_handle, "_INI"));
-	status = acpi_ns_evaluate_relative (obj_handle, "_INI", NULL, NULL);
+	ACPI_DEBUG_EXEC (acpi_ut_display_init_pathname (ACPI_TYPE_METHOD, pinfo.node, "_INI"));
+	status = acpi_ns_evaluate_relative ("_INI", &pinfo);
 	if (ACPI_FAILURE (status)) {
 		/* No _INI (AE_NOT_FOUND) means device requires no initialization */
 
 		if (status != AE_NOT_FOUND) {
 			/* Ignore error and move on to next device */
 
-	#ifdef ACPI_DEBUG_OUTPUT
-			char                *scope_name = acpi_ns_get_external_pathname (obj_handle);
+#ifdef ACPI_DEBUG_OUTPUT
+			char                *scope_name = acpi_ns_get_external_pathname (pinfo.node);
 
 			ACPI_DEBUG_PRINT ((ACPI_DB_WARN, "%s._INI failed: %s\n",
 					scope_name, acpi_format_exception (status)));
 
 			ACPI_MEM_FREE (scope_name);
-	#endif
+#endif
 		}
 
 		status = AE_OK;
@@ -422,7 +426,7 @@
 	if (acpi_gbl_init_handler) {
 		/* External initialization handler is present, call it */
 
-		status = acpi_gbl_init_handler (obj_handle, ACPI_INIT_DEVICE_INI);
+		status = acpi_gbl_init_handler (pinfo.node, ACPI_INIT_DEVICE_INI);
 	}
 
 
diff -Nru a/drivers/acpi/namespace/nsparse.c b/drivers/acpi/namespace/nsparse.c
--- a/drivers/acpi/namespace/nsparse.c	2004-10-18 14:55:55 -07:00
+++ b/drivers/acpi/namespace/nsparse.c	2004-10-18 14:55:55 -07:00
@@ -94,8 +94,9 @@
 		return_ACPI_STATUS (AE_NO_MEMORY);
 	}
 
-	status = acpi_ds_init_aml_walk (walk_state, parse_root, NULL, table_desc->aml_start,
-			  table_desc->aml_length, NULL, NULL, pass_number);
+	status = acpi_ds_init_aml_walk (walk_state, parse_root, NULL,
+			  table_desc->aml_start, table_desc->aml_length,
+			  NULL, pass_number);
 	if (ACPI_FAILURE (status)) {
 		acpi_ds_delete_walk_state (walk_state);
 		return_ACPI_STATUS (status);
diff -Nru a/drivers/acpi/namespace/nsxfeval.c b/drivers/acpi/namespace/nsxfeval.c
--- a/drivers/acpi/namespace/nsxfeval.c	2004-10-18 14:57:04 -07:00
+++ b/drivers/acpi/namespace/nsxfeval.c	2004-10-18 14:57:04 -07:00
@@ -174,8 +174,7 @@
 {
 	acpi_status                     status;
 	acpi_status                     status2;
-	union acpi_operand_object       **internal_params = NULL;
-	union acpi_operand_object       *internal_return_obj = NULL;
+	struct acpi_parameter_info      info;
 	acpi_size                       buffer_space_needed;
 	u32                             i;
 
@@ -183,6 +182,11 @@
 	ACPI_FUNCTION_TRACE ("acpi_evaluate_object");
 
 
+	info.node = handle;
+	info.parameters = NULL;
+	info.return_object = NULL;
+	info.parameter_type = ACPI_PARAM_ARGS;
+
 	/*
 	 * If there are parameters to be passed to the object
 	 * (which must be a control method), the external objects
@@ -193,9 +197,10 @@
 		 * Allocate a new parameter block for the internal objects
 		 * Add 1 to count to allow for null terminated internal list
 		 */
-		internal_params = ACPI_MEM_CALLOCATE (((acpi_size) external_params->count + 1) *
-				  sizeof (void *));
-		if (!internal_params) {
+		info.parameters = ACPI_MEM_CALLOCATE (
+				 ((acpi_size) external_params->count + 1) *
+				 sizeof (void *));
+		if (!info.parameters) {
 			return_ACPI_STATUS (AE_NO_MEMORY);
 		}
 
@@ -205,15 +210,16 @@
 		 */
 		for (i = 0; i < external_params->count; i++) {
 			status = acpi_ut_copy_eobject_to_iobject (&external_params->pointer[i],
-					  &internal_params[i]);
+					  &info.parameters[i]);
 			if (ACPI_FAILURE (status)) {
-				acpi_ut_delete_internal_object_list (internal_params);
+				acpi_ut_delete_internal_object_list (info.parameters);
 				return_ACPI_STATUS (status);
 			}
 		}
-		internal_params[external_params->count] = NULL;
+		info.parameters[external_params->count] = NULL;
 	}
 
+
 	/*
 	 * Three major cases:
 	 * 1) Fully qualified pathname
@@ -225,8 +231,7 @@
 		/*
 		 *  The path is fully qualified, just evaluate by name
 		 */
-		status = acpi_ns_evaluate_by_name (pathname, internal_params,
-				 &internal_return_obj);
+		status = acpi_ns_evaluate_by_name (pathname, &info);
 	}
 	else if (!handle) {
 		/*
@@ -256,15 +261,13 @@
 			 * The null pathname case means the handle is for
 			 * the actual object to be evaluated
 			 */
-			status = acpi_ns_evaluate_by_handle (handle, internal_params,
-					  &internal_return_obj);
+			status = acpi_ns_evaluate_by_handle (&info);
 		}
 		else {
 		   /*
 			* Both a Handle and a relative Pathname
 			*/
-			status = acpi_ns_evaluate_relative (handle, pathname, internal_params,
-					  &internal_return_obj);
+			status = acpi_ns_evaluate_relative (pathname, &info);
 		}
 	}
 
@@ -274,11 +277,11 @@
 	 * copy the return value to an external object.
 	 */
 	if (return_buffer) {
-		if (!internal_return_obj) {
+		if (!info.return_object) {
 			return_buffer->length = 0;
 		}
 		else {
-			if (ACPI_GET_DESCRIPTOR_TYPE (internal_return_obj) == ACPI_DESC_TYPE_NAMED) {
+			if (ACPI_GET_DESCRIPTOR_TYPE (info.return_object) == ACPI_DESC_TYPE_NAMED) {
 				/*
 				 * If we received a NS Node as a return object, this means that
 				 * the object we are evaluating has nothing interesting to
@@ -288,7 +291,7 @@
 				 * support for various types at a later date if necessary.
 				 */
 				status = AE_TYPE;
-				internal_return_obj = NULL; /* No need to delete a NS Node */
+				info.return_object = NULL;  /* No need to delete a NS Node */
 				return_buffer->length = 0;
 			}
 
@@ -297,7 +300,7 @@
 				 * Find out how large a buffer is needed
 				 * to contain the returned object
 				 */
-				status = acpi_ut_get_object_size (internal_return_obj,
+				status = acpi_ut_get_object_size (info.return_object,
 						   &buffer_space_needed);
 				if (ACPI_SUCCESS (status)) {
 					/* Validate/Allocate/Clear caller buffer */
@@ -309,13 +312,14 @@
 						 */
 						ACPI_DEBUG_PRINT ((ACPI_DB_INFO,
 							"Needed buffer size %X, %s\n",
-							(u32) buffer_space_needed, acpi_format_exception (status)));
+							(u32) buffer_space_needed,
+							acpi_format_exception (status)));
 					}
 					else {
 						/*
 						 *  We have enough space for the object, build it
 						 */
-						status = acpi_ut_copy_iobject_to_eobject (internal_return_obj,
+						status = acpi_ut_copy_iobject_to_eobject (info.return_object,
 								  return_buffer);
 					}
 				}
@@ -323,7 +327,7 @@
 		}
 	}
 
-	if (internal_return_obj) {
+	if (info.return_object) {
 		/*
 		 * Delete the internal return object.  NOTE: Interpreter
 		 * must be locked to avoid race condition.
@@ -334,7 +338,7 @@
 			 * Delete the internal return object. (Or at least
 			 * decrement the reference count by one)
 			 */
-			acpi_ut_remove_reference (internal_return_obj);
+			acpi_ut_remove_reference (info.return_object);
 			acpi_ex_exit_interpreter ();
 		}
 	}
@@ -342,10 +346,10 @@
 	/*
 	 * Free the input parameter list (if we created one),
 	 */
-	if (internal_params) {
+	if (info.parameters) {
 		/* Free the allocated parameter block */
 
-		acpi_ut_delete_internal_object_list (internal_params);
+		acpi_ut_delete_internal_object_list (info.parameters);
 	}
 
 	return_ACPI_STATUS (status);
diff -Nru a/drivers/acpi/namespace/nsxfname.c b/drivers/acpi/namespace/nsxfname.c
--- a/drivers/acpi/namespace/nsxfname.c	2004-10-18 14:56:19 -07:00
+++ b/drivers/acpi/namespace/nsxfname.c	2004-10-18 14:56:19 -07:00
@@ -281,7 +281,7 @@
 	if (info.type == ACPI_TYPE_DEVICE) {
 		/*
 		 * Get extra info for ACPI Devices objects only:
-		 * Run the Device _HID, _UID, _CID, _STA, and _ADR methods.
+		 * Run the Device _HID, _UID, _CID, _STA, _ADR and _sx_d methods.
 		 *
 		 * Note: none of these methods are required, so they may or may
 		 * not be present for this device.  The Info.Valid bitfield is used
@@ -330,7 +330,7 @@
 
 		status = acpi_ut_execute_sxds (node, info.highest_dstates);
 		if (ACPI_SUCCESS (status)) {
-			info.valid |= ACPI_VALID_STA;
+			info.valid |= ACPI_VALID_SXDS;
 		}
 
 		status = AE_OK;
diff -Nru a/drivers/acpi/numa.c b/drivers/acpi/numa.c
--- a/drivers/acpi/numa.c	2004-10-18 14:56:49 -07:00
+++ b/drivers/acpi/numa.c	2004-10-18 14:56:49 -07:00
@@ -51,6 +51,7 @@
 	switch (header->type) {
 
 	case ACPI_SRAT_PROCESSOR_AFFINITY:
+#ifdef ACPI_DEBUG_OUTPUT
 	{
 		struct acpi_table_processor_affinity *p =
 			(struct acpi_table_processor_affinity*) header;
@@ -58,9 +59,11 @@
 		       p->apic_id, p->lsapic_eid, p->proximity_domain,
 		       p->flags.enabled?"enabled":"disabled"));
 	}
+#endif /* ACPI_DEBUG_OUTPUT */
 		break;
 
 	case ACPI_SRAT_MEMORY_AFFINITY:
+#ifdef ACPI_DEBUG_OUTPUT
 	{
 		struct acpi_table_memory_affinity *p =
 			(struct acpi_table_memory_affinity*) header;
@@ -70,6 +73,7 @@
 		       p->flags.enabled ? "enabled" : "disabled",
 		       p->flags.hot_pluggable ? " hot-pluggable" : ""));
 	}
+#endif /* ACPI_DEBUG_OUTPUT */
 		break;
 
 	default:
@@ -94,8 +98,6 @@
 	/* downcast just for %llu vs %lu for i386/ia64  */
 	localities = (u32) slit->localities;
 
-	printk(KERN_INFO PREFIX "SLIT localities %ux%u\n", localities, localities);
-
 	acpi_numa_slit_init(slit);
 
 	return 0;
@@ -103,7 +105,9 @@
 
 
 static int __init
-acpi_parse_processor_affinity (acpi_table_entry_header *header)
+acpi_parse_processor_affinity (
+	acpi_table_entry_header *header,
+	const unsigned long end)
 {
 	struct acpi_table_processor_affinity *processor_affinity;
 
@@ -121,7 +125,9 @@
 
 
 static int __init
-acpi_parse_memory_affinity (acpi_table_entry_header *header)
+acpi_parse_memory_affinity (
+	acpi_table_entry_header *header,
+	const unsigned long end)
 {
 	struct acpi_table_memory_affinity *memory_affinity;
 
@@ -147,8 +153,6 @@
 		return -EINVAL;
 
 	srat = (struct acpi_table_srat *) __va(phys_addr);
-
-	printk(KERN_INFO PREFIX "SRAT revision %d\n", srat->table_revision);
 
 	return 0;
 }
diff -Nru a/drivers/acpi/osl.c b/drivers/acpi/osl.c
--- a/drivers/acpi/osl.c	2004-10-18 14:56:49 -07:00
+++ b/drivers/acpi/osl.c	2004-10-18 14:56:49 -07:00
@@ -51,10 +51,13 @@
 
 struct acpi_os_dpc
 {
-    OSD_EXECUTION_CALLBACK  function;
+    acpi_osd_exec_callback  function;
     void		    *context;
 };
 
+#ifdef CONFIG_ACPI_CUSTOM_DSDT
+#include CONFIG_ACPI_CUSTOM_DSDT_FILE
+#endif
 
 #ifdef ENABLE_DEBUGGER
 #include <linux/kdb.h>
@@ -64,13 +67,19 @@
 #endif /*ENABLE_DEBUGGER*/
 
 static unsigned int acpi_irq_irq;
-static OSD_HANDLER acpi_irq_handler;
+static acpi_osd_handler acpi_irq_handler;
 static void *acpi_irq_context;
 static struct workqueue_struct *kacpid_wq;
 
 acpi_status
 acpi_os_initialize(void)
 {
+	return AE_OK;
+}
+
+acpi_status
+acpi_os_initialize1(void)
+{
 	/*
 	 * Initialize PCI configuration space access, as we'll need to access
 	 * it while walking the namespace (bus 0 and root bridges w/ _BBNs).
@@ -165,11 +174,11 @@
 }
 
 acpi_status
-acpi_os_map_memory(acpi_physical_address phys, acpi_size size, void **virt)
+acpi_os_map_memory(acpi_physical_address phys, acpi_size size, void __iomem **virt)
 {
 	if (efi_enabled) {
 		if (EFI_MEMORY_WB & efi_mem_attributes(phys)) {
-			*virt = phys_to_virt(phys);
+			*virt = (void __iomem *) phys_to_virt(phys);
 		} else {
 			*virt = ioremap(phys, size);
 		}
@@ -191,7 +200,7 @@
 }
 
 void
-acpi_os_unmap_memory(void *virt, acpi_size size)
+acpi_os_unmap_memory(void __iomem *virt, acpi_size size)
 {
 	iounmap(virt);
 }
@@ -235,7 +244,14 @@
 	if (!existing_table || !new_table)
 		return AE_BAD_PARAMETER;
 
+#ifdef CONFIG_ACPI_CUSTOM_DSDT
+	if (strncmp(existing_table->signature, "DSDT", 4) == 0)
+		*new_table = (struct acpi_table_header*)AmlCode;
+	else
+		*new_table = NULL;
+#else
 	*new_table = NULL;
+#endif
 	return AE_OK;
 }
 
@@ -246,7 +262,7 @@
 }
 
 acpi_status
-acpi_os_install_interrupt_handler(u32 gsi, OSD_HANDLER handler, void *context)
+acpi_os_install_interrupt_handler(u32 gsi, acpi_osd_handler handler, void *context)
 {
 	unsigned int irq;
 
@@ -274,7 +290,7 @@
 }
 
 acpi_status
-acpi_os_remove_interrupt_handler(u32 irq, OSD_HANDLER handler)
+acpi_os_remove_interrupt_handler(u32 irq, acpi_osd_handler handler)
 {
 	if (irq) {
 		free_irq(irq, acpi_irq);
@@ -370,30 +386,31 @@
 	u32			width)
 {
 	u32			dummy;
-	void			*virt_addr;
+	void __iomem		*virt_addr;
 	int			iomem = 0;
 
 	if (efi_enabled) {
 		if (EFI_MEMORY_WB & efi_mem_attributes(phys_addr)) {
-			virt_addr = phys_to_virt(phys_addr);
+			/* HACK ALERT! We can use readb/w/l on real memory too.. */
+			virt_addr = (void __iomem *) phys_to_virt(phys_addr);
 		} else {
 			iomem = 1;
 			virt_addr = ioremap(phys_addr, width);
 		}
 	} else
-		virt_addr = phys_to_virt(phys_addr);
+		virt_addr = (void __iomem *) phys_to_virt(phys_addr);
 	if (!value)
 		value = &dummy;
 
 	switch (width) {
 	case 8:
-		*(u8*) value = *(u8*) virt_addr;
+		*(u8*) value = readb(virt_addr);
 		break;
 	case 16:
-		*(u16*) value = *(u16*) virt_addr;
+		*(u16*) value = readw(virt_addr);
 		break;
 	case 32:
-		*(u32*) value = *(u32*) virt_addr;
+		*(u32*) value = readl(virt_addr);
 		break;
 	default:
 		BUG();
@@ -413,28 +430,29 @@
 	u32			value,
 	u32			width)
 {
-	void			*virt_addr;
+	void __iomem		*virt_addr;
 	int			iomem = 0;
 
 	if (efi_enabled) {
 		if (EFI_MEMORY_WB & efi_mem_attributes(phys_addr)) {
-			virt_addr = phys_to_virt(phys_addr);
+			/* HACK ALERT! We can use writeb/w/l on real memory too */
+			virt_addr = (void __iomem *) phys_to_virt(phys_addr);
 		} else {
 			iomem = 1;
 			virt_addr = ioremap(phys_addr, width);
 		}
 	} else
-		virt_addr = phys_to_virt(phys_addr);
+		virt_addr = (void __iomem *) phys_to_virt(phys_addr);
 
 	switch (width) {
 	case 8:
-		*(u8*) virt_addr = value;
+		writeb(value, virt_addr);
 		break;
 	case 16:
-		*(u16*) virt_addr = value;
+		writew(value, virt_addr);
 		break;
 	case 32:
-		*(u32*) virt_addr = value;
+		writel(value, virt_addr);
 		break;
 	default:
 		BUG();
@@ -470,6 +488,8 @@
 		return AE_ERROR;
 	}
 
+	BUG_ON(!raw_pci_ops);
+
 	result = raw_pci_ops->read(pci_id->segment, pci_id->bus,
 				PCI_DEVFN(pci_id->device, pci_id->function),
 				reg, size, value);
@@ -496,6 +516,8 @@
 		return AE_ERROR;
 	}
 
+	BUG_ON(!raw_pci_ops);
+
 	result = raw_pci_ops->write(pci_id->segment, pci_id->bus,
 				PCI_DEVFN(pci_id->device, pci_id->function),
 				reg, size, value);
@@ -624,7 +646,7 @@
 acpi_status
 acpi_os_queue_for_execution(
 	u32			priority,
-	OSD_EXECUTION_CALLBACK	function,
+	acpi_osd_exec_callback	function,
 	void			*context)
 {
 	acpi_status 		status = AE_OK;
@@ -952,7 +974,7 @@
 {
 #if defined(__i386__) || defined(__x86_64__) 
 	char tmp;
-	return !__get_user(tmp, (char *)ptr) && !__get_user(tmp, (char *)ptr + len - 1);
+	return !__get_user(tmp, (char __user *)ptr) && !__get_user(tmp, (char __user *)ptr + len - 1);
 #endif
 	return 1;
 }
@@ -1066,15 +1088,15 @@
  * Run-time events on the same GPE this flag is available
  * to tell Linux to keep the wake-time GPEs enabled at run-time.
  */
-static int __init
-acpi_leave_gpes_disabled_setup(char *str)
+int __init
+acpi_wake_gpes_always_on_setup(char *str)
 {
-	printk(KERN_INFO PREFIX "leave wake GPEs disabled\n");
+	printk(KERN_INFO PREFIX "wake GPEs not disabled\n");
 
-	acpi_gbl_leave_wake_gpes_disabled = TRUE;
+	acpi_gbl_leave_wake_gpes_disabled = FALSE;
 
 	return 1;
 }
 
-__setup("acpi_leave_gpes_disabled", acpi_leave_gpes_disabled_setup);
+__setup("acpi_wake_gpes_always_on", acpi_wake_gpes_always_on_setup);
 
diff -Nru a/drivers/acpi/parser/psopcode.c b/drivers/acpi/parser/psopcode.c
--- a/drivers/acpi/parser/psopcode.c	2004-10-18 14:56:13 -07:00
+++ b/drivers/acpi/parser/psopcode.c	2004-10-18 14:56:13 -07:00
@@ -251,7 +251,7 @@
 #define ARGI_CREATE_FIELD_OP            ARGI_LIST4 (ARGI_BUFFER,     ARGI_INTEGER,       ARGI_INTEGER,      ARGI_REFERENCE)
 #define ARGI_CREATE_QWORD_FIELD_OP      ARGI_LIST3 (ARGI_BUFFER,     ARGI_INTEGER,       ARGI_REFERENCE)
 #define ARGI_CREATE_WORD_FIELD_OP       ARGI_LIST3 (ARGI_BUFFER,     ARGI_INTEGER,       ARGI_REFERENCE)
-#define ARGI_DATA_REGION_OP             ARGI_LIST3 (ARGI_STRING,     ARGI_STRING,       ARGI_STRING)
+#define ARGI_DATA_REGION_OP             ARGI_LIST3 (ARGI_STRING,     ARGI_STRING,        ARGI_STRING)
 #define ARGI_DEBUG_OP                   ARG_NONE
 #define ARGI_DECREMENT_OP               ARGI_LIST1 (ARGI_INTEGER_REF)
 #define ARGI_DEREF_OF_OP                ARGI_LIST1 (ARGI_REF_OR_STRING)
@@ -270,10 +270,10 @@
 #define ARGI_INDEX_FIELD_OP             ARGI_INVALID_OPCODE
 #define ARGI_INDEX_OP                   ARGI_LIST3 (ARGI_COMPLEXOBJ, ARGI_INTEGER,       ARGI_TARGETREF)
 #define ARGI_LAND_OP                    ARGI_LIST2 (ARGI_INTEGER,    ARGI_INTEGER)
-#define ARGI_LEQUAL_OP                  ARGI_LIST2 (ARGI_INTEGER,    ARGI_INTEGER)
-#define ARGI_LGREATER_OP                ARGI_LIST2 (ARGI_INTEGER,    ARGI_INTEGER)
+#define ARGI_LEQUAL_OP                  ARGI_LIST2 (ARGI_COMPUTEDATA,ARGI_COMPUTEDATA)
+#define ARGI_LGREATER_OP                ARGI_LIST2 (ARGI_COMPUTEDATA,ARGI_COMPUTEDATA)
 #define ARGI_LGREATEREQUAL_OP           ARGI_INVALID_OPCODE
-#define ARGI_LLESS_OP                   ARGI_LIST2 (ARGI_INTEGER,    ARGI_INTEGER)
+#define ARGI_LLESS_OP                   ARGI_LIST2 (ARGI_COMPUTEDATA,ARGI_COMPUTEDATA)
 #define ARGI_LLESSEQUAL_OP              ARGI_INVALID_OPCODE
 #define ARGI_LNOT_OP                    ARGI_LIST1 (ARGI_INTEGER)
 #define ARGI_LNOTEQUAL_OP               ARGI_INVALID_OPCODE
diff -Nru a/drivers/acpi/parser/psxface.c b/drivers/acpi/parser/psxface.c
--- a/drivers/acpi/parser/psxface.c	2004-10-18 14:56:49 -07:00
+++ b/drivers/acpi/parser/psxface.c	2004-10-18 14:56:49 -07:00
@@ -57,7 +57,7 @@
  *
  * FUNCTION:    acpi_psx_execute
  *
- * PARAMETERS:  method_node         - A method object containing both the AML
+ * PARAMETERS:  Info->Node          - A method object containing both the AML
  *                                    address and length.
  *              **Params            - List of parameters to pass to method,
  *                                    terminated by NULL. Params itself may be
@@ -73,9 +73,7 @@
 
 acpi_status
 acpi_psx_execute (
-	struct acpi_namespace_node      *method_node,
-	union acpi_operand_object       **params,
-	union acpi_operand_object       **return_obj_desc)
+	struct acpi_parameter_info      *info)
 {
 	acpi_status                     status;
 	union acpi_operand_object       *obj_desc;
@@ -89,29 +87,30 @@
 
 	/* Validate the Node and get the attached object */
 
-	if (!method_node) {
+	if (!info || !info->node) {
 		return_ACPI_STATUS (AE_NULL_ENTRY);
 	}
 
-	obj_desc = acpi_ns_get_attached_object (method_node);
+	obj_desc = acpi_ns_get_attached_object (info->node);
 	if (!obj_desc) {
 		return_ACPI_STATUS (AE_NULL_OBJECT);
 	}
 
 	/* Init for new method, wait on concurrency semaphore */
 
-	status = acpi_ds_begin_method_execution (method_node, obj_desc, NULL);
+	status = acpi_ds_begin_method_execution (info->node, obj_desc, NULL);
 	if (ACPI_FAILURE (status)) {
 		return_ACPI_STATUS (status);
 	}
 
-	if (params) {
+	if ((info->parameter_type == ACPI_PARAM_ARGS) &&
+		(info->parameters)) {
 		/*
 		 * The caller "owns" the parameters, so give each one an extra
 		 * reference
 		 */
-		for (i = 0; params[i]; i++) {
-			acpi_ut_add_reference (params[i]);
+		for (i = 0; info->parameters[i]; i++) {
+			acpi_ut_add_reference (info->parameters[i]);
 		}
 	}
 
@@ -121,7 +120,7 @@
 	 */
 	ACPI_DEBUG_PRINT ((ACPI_DB_PARSE,
 		"**** Begin Method Parse **** Entry=%p obj=%p\n",
-		method_node, obj_desc));
+		info->node, obj_desc));
 
 	/* Create and init a Root Node */
 
@@ -147,8 +146,9 @@
 		goto cleanup2;
 	}
 
-	status = acpi_ds_init_aml_walk (walk_state, op, method_node, obj_desc->method.aml_start,
-			  obj_desc->method.aml_length, NULL, NULL, 1);
+	status = acpi_ds_init_aml_walk (walk_state, op, info->node,
+			  obj_desc->method.aml_start,
+			  obj_desc->method.aml_length, NULL, 1);
 	if (ACPI_FAILURE (status)) {
 		goto cleanup3;
 	}
@@ -159,7 +159,6 @@
 	acpi_ps_delete_parse_tree (op);
 	if (ACPI_FAILURE (status)) {
 		goto cleanup1; /* Walk state is already deleted */
-
 	}
 
 	/*
@@ -167,7 +166,7 @@
 	 */
 	ACPI_DEBUG_PRINT ((ACPI_DB_PARSE,
 		"**** Begin Method Execution **** Entry=%p obj=%p\n",
-		method_node, obj_desc));
+		info->node, obj_desc));
 
 	/* Create and init a Root Node */
 
@@ -179,8 +178,8 @@
 
 	/* Init new op with the method name and pointer back to the NS node */
 
-	acpi_ps_set_name (op, method_node->name.integer);
-	op->common.node = method_node;
+	acpi_ps_set_name (op, info->node->name.integer);
+	op->common.node = info->node;
 
 	/* Create and initialize a new walk state */
 
@@ -190,8 +189,9 @@
 		goto cleanup2;
 	}
 
-	status = acpi_ds_init_aml_walk (walk_state, op, method_node, obj_desc->method.aml_start,
-			  obj_desc->method.aml_length, params, return_obj_desc, 3);
+	status = acpi_ds_init_aml_walk (walk_state, op, info->node,
+			  obj_desc->method.aml_start,
+			  obj_desc->method.aml_length, info, 3);
 	if (ACPI_FAILURE (status)) {
 		goto cleanup3;
 	}
@@ -210,13 +210,14 @@
 	acpi_ps_delete_parse_tree (op);
 
 cleanup1:
-	if (params) {
+	if ((info->parameter_type == ACPI_PARAM_ARGS) &&
+		(info->parameters)) {
 		/* Take away the extra reference that we gave the parameters above */
 
-		for (i = 0; params[i]; i++) {
+		for (i = 0; info->parameters[i]; i++) {
 			/* Ignore errors, just do them all */
 
-			(void) acpi_ut_update_object_reference (params[i], REF_DECREMENT);
+			(void) acpi_ut_update_object_reference (info->parameters[i], REF_DECREMENT);
 		}
 	}
 
@@ -228,10 +229,10 @@
 	 * If the method has returned an object, signal this to the caller with
 	 * a control exception code
 	 */
-	if (*return_obj_desc) {
+	if (info->return_object) {
 		ACPI_DEBUG_PRINT ((ACPI_DB_PARSE, "Method returned obj_desc=%p\n",
-			*return_obj_desc));
-		ACPI_DUMP_STACK_ENTRY (*return_obj_desc);
+			info->return_object));
+		ACPI_DUMP_STACK_ENTRY (info->return_object);
 
 		status = AE_CTRL_RETURN_VALUE;
 	}
diff -Nru a/drivers/acpi/pci_link.c b/drivers/acpi/pci_link.c
--- a/drivers/acpi/pci_link.c	2004-10-18 14:55:54 -07:00
+++ b/drivers/acpi/pci_link.c	2004-10-18 14:55:54 -07:00
@@ -29,6 +29,7 @@
  *	   for IRQ management (e.g. start()->_SRS).
  */
 
+#include <linux/sysdev.h>
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/init.h>
@@ -71,7 +72,7 @@
 	u8			active;			/* Current IRQ */
 	u8			edge_level;		/* All IRQs */
 	u8			active_high_low;	/* All IRQs */
-	u8			setonboot;
+	u8			initialized;
 	u8			resource_type;
 	u8			possible_count;
 	u8			possible[ACPI_PCI_LINK_MAX_POSSIBLE];
@@ -447,7 +448,7 @@
 #define PIRQ_PENALTY_ISA_USED		(16*16*16*16*16)
 #define PIRQ_PENALTY_ISA_ALWAYS		(16*16*16*16*16*16)
 
-static int __initdata acpi_irq_penalty[ACPI_MAX_IRQS] = {
+static int acpi_irq_penalty[ACPI_MAX_IRQS] = {
 	PIRQ_PENALTY_ISA_ALWAYS,	/* IRQ0 timer */
 	PIRQ_PENALTY_ISA_ALWAYS,	/* IRQ1 keyboard */
 	PIRQ_PENALTY_ISA_ALWAYS,	/* IRQ2 cascade */
@@ -467,7 +468,7 @@
 			/* >IRQ15 */
 };
 
-int
+int __init
 acpi_irq_penalty_init(void)
 {
 	struct list_head	*node = NULL;
@@ -517,7 +518,7 @@
 
 	ACPI_FUNCTION_TRACE("acpi_pci_link_allocate");
 
-	if (link->irq.setonboot)
+	if (link->irq.initialized)
 		return_VALUE(0);
 
 	/*
@@ -571,7 +572,7 @@
 			acpi_device_bid(link->device), link->irq.active);
 	}
 
-	link->irq.setonboot = 1;
+	link->irq.initialized = 1;
 
 	return_VALUE(0);
 }
@@ -695,6 +696,42 @@
 
 
 static int
+acpi_pci_link_resume (
+	struct acpi_pci_link	*link)
+{
+	ACPI_FUNCTION_TRACE("acpi_pci_link_resume");
+	
+	if (link->irq.active && link->irq.initialized)
+		return_VALUE(acpi_pci_link_set(link, link->irq.active));
+	else
+		return_VALUE(0);
+}
+
+
+static int
+irqrouter_resume(
+	struct sys_device *dev)
+{
+	struct list_head        *node = NULL;
+	struct acpi_pci_link    *link = NULL;
+
+	ACPI_FUNCTION_TRACE("irqrouter_resume");
+
+	list_for_each(node, &acpi_link.entries) {
+
+		link = list_entry(node, struct acpi_pci_link, node);
+		if (!link) {
+			ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Invalid link context\n"));
+			continue;
+		}
+
+		acpi_pci_link_resume(link);
+	}
+	return_VALUE(0);
+}
+
+
+static int
 acpi_pci_link_remove (
 	struct acpi_device	*device,
 	int			type)
@@ -786,11 +823,42 @@
 __setup("acpi_irq_balance", acpi_irq_balance_set);
 
 
+static struct sysdev_class irqrouter_sysdev_class = {
+        set_kset_name("irqrouter"),
+        .resume = irqrouter_resume,
+};
+
+
+static struct sys_device device_irqrouter = {
+	.id     = 0,
+	.cls    = &irqrouter_sysdev_class,
+};
+
+
+static int __init irqrouter_init_sysfs(void)
+{
+	int error;
+
+	ACPI_FUNCTION_TRACE("irqrouter_init_sysfs");
+
+	if (acpi_disabled || acpi_noirq)
+		return_VALUE(0);
+
+	error = sysdev_class_register(&irqrouter_sysdev_class);
+	if (!error)
+		error = sysdev_register(&device_irqrouter);
+
+	return_VALUE(error);
+}                                        
+
+device_initcall(irqrouter_init_sysfs);
+
+
 static int __init acpi_pci_link_init (void)
 {
 	ACPI_FUNCTION_TRACE("acpi_pci_link_init");
 
-	if (acpi_pci_disabled)
+	if (acpi_noirq)
 		return_VALUE(0);
 
 	acpi_link.count = 0;
diff -Nru a/drivers/acpi/power.c b/drivers/acpi/power.c
--- a/drivers/acpi/power.c	2004-10-18 14:56:32 -07:00
+++ b/drivers/acpi/power.c	2004-10-18 14:56:32 -07:00
@@ -288,6 +288,86 @@
 	return_VALUE(0);
 }
 
+/*
+ * Prepare a wakeup device, two steps (Ref ACPI 2.0:P229):
+ * 1. Power on the power resources required for the wakeup device 
+ * 2. Enable _PSW (power state wake) for the device if present
+ */
+int acpi_enable_wakeup_device_power (struct acpi_device *dev)
+{
+	union acpi_object 		arg = {ACPI_TYPE_INTEGER};
+	struct acpi_object_list	arg_list = {1, &arg};
+	acpi_status			status = AE_OK;
+	int					i;
+	int 					ret = 0;
+
+	ACPI_FUNCTION_TRACE("acpi_enable_wakeup_device_power");
+	if (!dev || !dev->wakeup.flags.valid)
+		return -1;
+
+	arg.integer.value = 1;
+	/* Open power resource */
+	for (i = 0; i < dev->wakeup.resources.count; i++) {
+		ret = acpi_power_on(dev->wakeup.resources.handles[i]);
+		if (ret) {
+			ACPI_DEBUG_PRINT((ACPI_DB_ERROR, 
+				"Error transition power state\n"));
+			dev->wakeup.flags.valid = 0;
+			return -1;
+		}
+	}
+
+	/* Execute PSW */
+	status = acpi_evaluate_object(dev->handle, "_PSW", &arg_list, NULL);
+	if (ACPI_FAILURE(status) && (status != AE_NOT_FOUND)) {
+		ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Error evaluate _PSW\n"));
+		dev->wakeup.flags.valid = 0;
+		ret = -1;
+	}
+
+	return ret;
+}
+
+/*
+ * Shutdown a wakeup device, counterpart of above method
+ * 1. Disable _PSW (power state wake)
+ * 2. Shutdown down the power resources
+ */
+int acpi_disable_wakeup_device_power (struct acpi_device *dev)
+{
+	union acpi_object 		arg = {ACPI_TYPE_INTEGER};
+	struct acpi_object_list	arg_list = {1, &arg};
+	acpi_status			status = AE_OK;
+	int					i;
+	int 					ret = 0;
+
+	ACPI_FUNCTION_TRACE("acpi_disable_wakeup_device_power");
+
+	if (!dev || !dev->wakeup.flags.valid)
+		return -1;
+
+	arg.integer.value = 0;	
+	/* Execute PSW */
+	status = acpi_evaluate_object(dev->handle, "_PSW", &arg_list, NULL);
+	if (ACPI_FAILURE(status) && (status != AE_NOT_FOUND)) {
+		ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Error evaluate _PSW\n"));
+		dev->wakeup.flags.valid = 0;
+		return -1;
+	}
+
+	/* Close power resource */
+	for (i = 0; i < dev->wakeup.resources.count; i++) {
+		ret = acpi_power_off_device(dev->wakeup.resources.handles[i]);
+		if (ret) {
+			ACPI_DEBUG_PRINT((ACPI_DB_ERROR, 
+				"Error transition power state\n"));
+			dev->wakeup.flags.valid = 0;
+			return -1;
+		}
+	}
+
+	return ret;
+}
 
 /* --------------------------------------------------------------------------
                              Device Power Management
diff -Nru a/drivers/acpi/processor.c b/drivers/acpi/processor.c
--- a/drivers/acpi/processor.c	2004-10-18 14:56:48 -07:00
+++ b/drivers/acpi/processor.c	2004-10-18 14:56:48 -07:00
@@ -44,6 +44,9 @@
 #include <asm/system.h>
 #include <asm/delay.h>
 #include <asm/uaccess.h>
+#include <asm/processor.h>
+#include <asm/smp.h>
+#include <asm/acpi.h>
 
 #include <acpi/acpi_bus.h>
 #include <acpi/acpi_drivers.h>
@@ -859,7 +862,6 @@
  * _PCT and _PSS structures are read out and written into struct
  * acpi_processor_performance.
  */
-
 static int acpi_processor_set_pdc (struct acpi_processor *pr)
 {
 	acpi_status             status = AE_OK;
@@ -1047,6 +1049,8 @@
 	if (!pr || !pr->performance || !pr->handle)
 		return_VALUE(-EINVAL);
 
+	acpi_processor_set_pdc(pr);
+
 	status = acpi_get_handle(pr->handle, "_PCT", &handle);
 	if (ACPI_FAILURE(status)) {
 		ACPI_DEBUG_PRINT((ACPI_DB_INFO, 
@@ -1054,8 +1058,6 @@
 		return_VALUE(-ENODEV);
 	}
 
-	acpi_processor_set_pdc(pr);
-
 	result = acpi_processor_get_performance_control(pr);
 	if (result)
 		return_VALUE(result);
@@ -1121,7 +1123,7 @@
 						PDE(inode)->data);
 }
 
-static int
+static ssize_t
 acpi_processor_write_performance (
         struct file		*file,
         const char		__user *buffer,
@@ -2146,6 +2148,37 @@
 	return_VALUE(0);
 }
 
+/* Use the acpiid in MADT to map cpus in case of SMP */
+#ifndef CONFIG_SMP
+#define convert_acpiid_to_cpu(acpi_id) (0xff)
+#else
+
+#ifdef CONFIG_IA64
+#define arch_acpiid_to_apicid 	ia64_acpiid_to_sapicid
+#define arch_cpu_to_apicid 	ia64_cpu_to_sapicid
+#define ARCH_BAD_APICID		(0xffff)
+#else
+#define arch_acpiid_to_apicid 	x86_acpiid_to_apicid
+#define arch_cpu_to_apicid 	x86_cpu_to_apicid
+#define ARCH_BAD_APICID		(0xff)
+#endif
+
+static u8 convert_acpiid_to_cpu(u8 acpi_id)
+{
+	u16 apic_id;
+	int i;
+	
+	apic_id = arch_acpiid_to_apicid[acpi_id];
+	if (apic_id == ARCH_BAD_APICID)
+		return -1;
+
+	for (i = 0; i < NR_CPUS; i++) {
+		if (arch_cpu_to_apicid[i] == apic_id)
+			return i;
+	}
+	return -1;
+}
+#endif
 
 /* --------------------------------------------------------------------------
                                  Driver Interface
@@ -2158,7 +2191,8 @@
 	acpi_status		status = 0;
 	union acpi_object	object = {0};
 	struct acpi_buffer	buffer = {sizeof(union acpi_object), &object};
-	static int		cpu_index = 0;
+	u8			cpu_index;
+	static int		cpu0_initialized;
 
 	ACPI_FUNCTION_TRACE("acpi_processor_get_info");
 
@@ -2168,13 +2202,6 @@
 	if (num_online_cpus() > 1)
 		errata.smp = TRUE;
 
-	/*
-	 *  Extra Processor objects may be enumerated on MP systems with
-	 *  less than the max # of CPUs. They should be ignored.
-	 */
-	if ((cpu_index + 1) > num_online_cpus())
-		return_VALUE(-ENODEV);
-
 	acpi_processor_errata(pr);
 
 	/*
@@ -2206,9 +2233,27 @@
 	 * TBD: Synch processor ID (via LAPIC/LSAPIC structures) on SMP.
 	 *	>>> 'acpi_get_processor_id(acpi_id, &id)' in arch/xxx/acpi.c
 	 */
-	pr->id = cpu_index++;
 	pr->acpi_id = object.processor.proc_id;
 
+	cpu_index = convert_acpiid_to_cpu(pr->acpi_id);
+
+	if ( !cpu0_initialized && (cpu_index == 0xff)) {
+		/* Handle UP system running SMP kernel, with no LAPIC in MADT */
+		cpu_index = 0;
+	} else if (cpu_index > num_online_cpus()) {
+		/*
+		 *  Extra Processor objects may be enumerated on MP systems with
+		 *  less than the max # of CPUs. They should be ignored.
+		 */
+		ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+			"Error getting cpuindex for acpiid 0x%x\n",
+			pr->acpi_id));
+		return_VALUE(-ENODEV);
+	}
+	cpu0_initialized = 1;
+
+	pr->id = cpu_index;
+
 	ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Processor [%d:%d]\n", pr->id, 
 		pr->acpi_id));
 
@@ -2234,7 +2279,6 @@
 		 * (In particular, allocating the IO range for Cardbus)
 		 */
 		request_region(pr->throttling.address, 6, "ACPI CPU throttle");
-		request_region(acpi_fadt.xpm_tmr_blk.address, 4, "ACPI timer");
 	}
 
 	acpi_processor_get_power_info(pr);
@@ -2373,8 +2417,15 @@
 	pr = (struct acpi_processor *) acpi_driver_data(device);
 
 	/* Unregister the idle handler when processor #0 is removed. */
-	if (pr->id == 0)
+	if (pr->id == 0) {
 		pm_idle = pm_idle_save;
+		/*
+		 * We are about to unload the current idle thread pm callback
+		 * (pm_idle), Wait for all processors to update cached/local
+		 * copies of pm_idle before proceeding.
+		 */
+		synchronize_kernel();
+	}
 
 	status = acpi_remove_notify_handler(pr->handle, ACPI_DEVICE_NOTIFY, 
 		acpi_processor_notify);
diff -Nru a/drivers/acpi/resources/rsutils.c b/drivers/acpi/resources/rsutils.c
--- a/drivers/acpi/resources/rsutils.c	2004-10-18 14:55:54 -07:00
+++ b/drivers/acpi/resources/rsutils.c	2004-10-18 14:55:54 -07:00
@@ -289,6 +289,7 @@
 	acpi_handle                     handle,
 	struct acpi_buffer              *in_buffer)
 {
+	struct acpi_parameter_info      info;
 	union acpi_operand_object       *params[2];
 	acpi_status                     status;
 	struct acpi_buffer              buffer;
@@ -329,10 +330,14 @@
 	params[0]->common.flags   = AOPOBJ_DATA_VALID;
 	params[1] = NULL;
 
+	info.node = handle;
+	info.parameters = params;
+	info.parameter_type = ACPI_PARAM_ARGS;
+
 	/*
 	 * Execute the method, no return value
 	 */
-	status = acpi_ns_evaluate_relative (handle, "_SRS", params, NULL);
+	status = acpi_ns_evaluate_relative ("_SRS", &info);
 
 	/*
 	 * Clean up and return the status from acpi_ns_evaluate_relative
diff -Nru a/drivers/acpi/resources/rsxface.c b/drivers/acpi/resources/rsxface.c
--- a/drivers/acpi/resources/rsxface.c	2004-10-18 14:56:48 -07:00
+++ b/drivers/acpi/resources/rsxface.c	2004-10-18 14:56:48 -07:00
@@ -259,7 +259,8 @@
 	/* Setup pointers */
 
 	resource  = (struct acpi_resource *) buffer.pointer;
-	buffer_end = (struct acpi_resource *) ((u8 *) buffer.pointer + buffer.length);
+	buffer_end = ACPI_CAST_PTR (struct acpi_resource,
+			  ((u8 *) buffer.pointer + buffer.length));
 
 	/* Walk the resource list */
 
diff -Nru a/drivers/acpi/scan.c b/drivers/acpi/scan.c
--- a/drivers/acpi/scan.c	2004-10-18 14:56:29 -07:00
+++ b/drivers/acpi/scan.c	2004-10-18 14:56:29 -07:00
@@ -23,7 +23,8 @@
 #define ACPI_BUS_DEVICE_NAME		"System Bus"
 
 static LIST_HEAD(acpi_device_list);
-static spinlock_t acpi_device_lock = SPIN_LOCK_UNLOCKED;
+spinlock_t acpi_device_lock = SPIN_LOCK_UNLOCKED;
+LIST_HEAD(acpi_wakeup_device_list);
 
 static void acpi_device_release(struct kobject * kobj)
 {
@@ -115,9 +116,6 @@
 	status = acpi_get_handle(device->handle, "_IRC", &handle);
 	if (ACPI_SUCCESS(status))
 		device->power.flags.inrush_current = 1;
-	status = acpi_get_handle(device->handle, "_PRW", &handle);
-	if (ACPI_SUCCESS(status))
-		device->power.flags.wake_capable = 1;
 
 	/*
 	 * Enumerate supported power management states
@@ -163,6 +161,127 @@
 	return 0;
 }
 
+static int
+acpi_match_ids (
+	struct acpi_device	*device,
+	char			*ids)
+{
+	int error = 0;
+	struct acpi_buffer buffer = {ACPI_ALLOCATE_BUFFER, NULL};
+
+	if (device->flags.hardware_id)
+		if (strstr(ids, device->pnp.hardware_id))
+			goto Done;
+
+	if (device->flags.compatible_ids) {
+		struct acpi_compatible_id_list *cid_list = device->pnp.cid_list;
+		int i;
+
+		/* compare multiple _CID entries against driver ids */
+		for (i = 0; i < cid_list->count; i++)
+		{
+			if (strstr(ids, cid_list->id[i].value))
+				goto Done;
+		}
+	}
+	error = -ENOENT;
+
+ Done:
+	if (buffer.pointer)
+		acpi_os_free(buffer.pointer);
+	return error;
+}
+
+static acpi_status
+acpi_bus_extract_wakeup_device_power_package (
+	struct acpi_device	*device,
+	union acpi_object	*package)
+{
+	int 	 i = 0;
+	union acpi_object	*element = NULL;
+
+	if (!device || !package || (package->package.count < 2))
+		return AE_BAD_PARAMETER;
+
+	element = &(package->package.elements[0]);
+	if (!element)
+		return AE_BAD_PARAMETER;
+	if (element->type == ACPI_TYPE_PACKAGE) {
+		if ((element->package.count < 2) ||
+			(element->package.elements[0].type != ACPI_TYPE_LOCAL_REFERENCE) ||
+			(element->package.elements[1].type != ACPI_TYPE_INTEGER))
+			return AE_BAD_DATA;
+		device->wakeup.gpe_device = element->package.elements[0].reference.handle;
+		device->wakeup.gpe_number = (u32)element->package.elements[1].integer.value;
+	}else if (element->type == ACPI_TYPE_INTEGER) {
+		device->wakeup.gpe_number = element->integer.value;
+	}else
+		return AE_BAD_DATA;
+
+	element = &(package->package.elements[1]);
+	if (element->type != ACPI_TYPE_INTEGER) {
+		return AE_BAD_DATA;
+	}
+	device->wakeup.sleep_state = element->integer.value;
+
+	if ((package->package.count - 2) > ACPI_MAX_HANDLES) {
+		return AE_NO_MEMORY;
+	}
+	device->wakeup.resources.count = package->package.count - 2;
+	for (i=0; i < device->wakeup.resources.count; i++) {
+		element = &(package->package.elements[i + 2]);
+		if (element->type != ACPI_TYPE_ANY ) {
+			return AE_BAD_DATA;
+		}
+
+		device->wakeup.resources.handles[i] = element->reference.handle;
+	}
+
+	return AE_OK;
+}
+
+static int
+acpi_bus_get_wakeup_device_flags (
+	struct acpi_device	*device)
+{
+	acpi_status	status = 0;
+	struct acpi_buffer	buffer = {ACPI_ALLOCATE_BUFFER, NULL};
+	union acpi_object	*package = NULL;
+
+	ACPI_FUNCTION_TRACE("acpi_bus_get_wakeup_flags");
+
+	/* _PRW */
+	status = acpi_evaluate_object(device->handle, "_PRW", NULL, &buffer);
+	if (ACPI_FAILURE(status)) {
+		ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Error evaluating _PRW\n"));
+		goto end;
+	}
+
+	package = (union acpi_object *) buffer.pointer;
+	status = acpi_bus_extract_wakeup_device_power_package(device, package);
+	if (ACPI_FAILURE(status)) {
+		ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Error extracting _PRW package\n"));
+		goto end;
+	}
+
+	acpi_os_free(buffer.pointer);
+
+	device->wakeup.flags.valid = 1;
+	/* Power button, Lid switch always enable wakeup*/
+	if (!acpi_match_ids(device, "PNP0C0D,PNP0C0C,PNP0C0E"))
+		device->wakeup.flags.run_wake = 1;
+
+	/* TBD: lock */
+	INIT_LIST_HEAD(&device->wakeup_list);
+	spin_lock(&acpi_device_lock);
+	list_add_tail(&device->wakeup_list, &acpi_wakeup_device_list);
+	spin_unlock(&acpi_device_lock);
+
+end:
+	if (ACPI_FAILURE(status))
+		device->flags.wake_capable = 0;
+	return 0;
+}
 
 /* --------------------------------------------------------------------------
                               Performance Management
@@ -195,30 +314,7 @@
 	struct acpi_device	*device,
 	struct acpi_driver	*driver)
 {
-	int error = 0;
-	struct acpi_buffer buffer = {ACPI_ALLOCATE_BUFFER, NULL};
-
-	if (device->flags.hardware_id)
-		if (strstr(driver->ids, device->pnp.hardware_id))
-			goto Done;
-
-	if (device->flags.compatible_ids) {
-		struct acpi_compatible_id_list *cid_list = device->pnp.cid_list;
-		int i;
-
-		/* compare multiple _CID entries against driver ids */
-		for (i = 0; i < cid_list->count; i++)
-		{
-			if (strstr(driver->ids, cid_list->id[i].value))
-				goto Done;
-		}
-	}
-	error = -ENOENT;
-
- Done:
-	if (buffer.pointer)
-		acpi_os_free(buffer.pointer);
-	return error;
+	return acpi_match_ids(device, driver->ids);
 }
 
 
@@ -276,6 +372,7 @@
 static int acpi_driver_attach(struct acpi_driver * drv)
 {
 	struct list_head * node, * next;
+	int count = 0;
 
 	ACPI_FUNCTION_TRACE("acpi_driver_attach");
 
@@ -290,6 +387,7 @@
 		if (!acpi_bus_match(dev, drv)) {
 			if (!acpi_bus_driver_init(dev, drv)) {
 				atomic_inc(&drv->references);
+				count++;
 				ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Found driver [%s] for device [%s]\n",
 						  drv->name, dev->pnp.bus_id));
 			}
@@ -297,7 +395,7 @@
 		spin_lock(&acpi_device_lock);
 	}
 	spin_unlock(&acpi_device_lock);
-	return_VALUE(0);
+	return_VALUE(count);
 }
 
 static int acpi_driver_detach(struct acpi_driver * drv)
@@ -328,28 +426,30 @@
  * acpi_bus_register_driver 
  * ------------------------ 
  * Registers a driver with the ACPI bus.  Searches the namespace for all
- * devices that match the driver's criteria and binds.
+ * devices that match the driver's criteria and binds.  Returns the
+ * number of devices that were claimed by the driver, or a negative
+ * error status for failure.
  */
 int
 acpi_bus_register_driver (
 	struct acpi_driver	*driver)
 {
-	int error = 0;
+	int count;
 
 	ACPI_FUNCTION_TRACE("acpi_bus_register_driver");
 
 	if (acpi_disabled)
 		return_VALUE(-ENODEV);
 
-	if (driver) {
-		spin_lock(&acpi_device_lock);
-		list_add_tail(&driver->node, &acpi_bus_drivers);
-		spin_unlock(&acpi_device_lock);
-		acpi_driver_attach(driver);
-	} else
-		error = -EINVAL;
+	if (!driver)
+		return_VALUE(-EINVAL);
 
-	return_VALUE(error);
+	spin_lock(&acpi_device_lock);
+	list_add_tail(&driver->node, &acpi_bus_drivers);
+	spin_unlock(&acpi_device_lock);
+	count = acpi_driver_attach(driver);
+
+	return_VALUE(count);
 }
 
 
@@ -469,6 +569,11 @@
 	if (ACPI_SUCCESS(status))
 		device->flags.power_manageable = 1;
 
+	/* Presence of _PRW indicates wake capable */
+	status = acpi_get_handle(device->handle, "_PRW", &temp);
+	if (ACPI_SUCCESS(status))
+		device->flags.wake_capable = 1;
+
 	/* TBD: Peformance management */
 
 	return_VALUE(0);
@@ -736,6 +841,16 @@
 	 */
 	if (device->flags.power_manageable) {
 		result = acpi_bus_get_power_flags(device);
+		if (result)
+			goto end;
+	}
+
+ 	/*
+	 * Wakeup device management
+	 *-----------------------
+	 */
+	if (device->flags.wake_capable) {
+		result = acpi_bus_get_wakeup_device_flags(device);
 		if (result)
 			goto end;
 	}
diff -Nru a/drivers/acpi/sleep/Makefile b/drivers/acpi/sleep/Makefile
--- a/drivers/acpi/sleep/Makefile	2004-10-18 14:56:49 -07:00
+++ b/drivers/acpi/sleep/Makefile	2004-10-18 14:56:49 -07:00
@@ -1,5 +1,5 @@
 obj-y					:= poweroff.o
-obj-$(CONFIG_ACPI_SLEEP)		+= main.o
+obj-$(CONFIG_ACPI_SLEEP)		+= main.o wakeup.o
 obj-$(CONFIG_ACPI_SLEEP_PROC_FS)	+= proc.o
 
 EXTRA_CFLAGS += $(ACPI_CFLAGS)
diff -Nru a/drivers/acpi/sleep/main.c b/drivers/acpi/sleep/main.c
--- a/drivers/acpi/sleep/main.c	2004-10-18 14:55:54 -07:00
+++ b/drivers/acpi/sleep/main.c	2004-10-18 14:55:54 -07:00
@@ -35,16 +35,16 @@
 
 /**
  *	acpi_pm_prepare - Do preliminary suspend work.
- *	@state:		suspend state we're entering.
+ *	@pm_state:		suspend state we're entering.
  *
  *	Make sure we support the state. If we do, and we need it, set the
  *	firmware waking vector and do arch-specific nastiness to get the 
  *	wakeup code to the waking vector. 
  */
 
-static int acpi_pm_prepare(u32 state)
+static int acpi_pm_prepare(u32 pm_state)
 {
-	u32 acpi_state = acpi_suspend_states[state];
+	u32 acpi_state = acpi_suspend_states[pm_state];
 
 	if (!sleep_states[acpi_state])
 		return -EPERM;
@@ -52,13 +52,14 @@
 	/* do we have a wakeup address for S2 and S3? */
 	/* Here, we support only S4BIOS, those we set the wakeup address */
 	/* S4OS is only supported for now via swsusp.. */
-	if (state == PM_SUSPEND_MEM || state == PM_SUSPEND_DISK) {
+	if (pm_state == PM_SUSPEND_MEM || pm_state == PM_SUSPEND_DISK) {
 		if (!acpi_wakeup_address)
 			return -EFAULT;
 		acpi_set_firmware_waking_vector(
 			(acpi_physical_address) acpi_wakeup_address);
 	}
 	ACPI_FLUSH_CPU_CACHE();
+	acpi_enable_wakeup_device_prep(acpi_state);
 	acpi_enter_sleep_state_prep(acpi_state);
 	return 0;
 }
@@ -66,23 +67,23 @@
 
 /**
  *	acpi_pm_enter - Actually enter a sleep state.
- *	@state:		State we're entering.
+ *	@pm_state:		State we're entering.
  *
  *	Flush caches and go to sleep. For STR or STD, we have to call 
  *	arch-specific assembly, which in turn call acpi_enter_sleep_state().
  *	It's unfortunate, but it works. Please fix if you're feeling frisky.
  */
 
-static int acpi_pm_enter(u32 state)
+static int acpi_pm_enter(u32 pm_state)
 {
 	acpi_status status = AE_OK;
 	unsigned long flags = 0;
-	u32 acpi_state = acpi_suspend_states[state];
+	u32 acpi_state = acpi_suspend_states[pm_state];
 
 	ACPI_FLUSH_CPU_CACHE();
 
 	/* Do arch specific saving of state. */
-	if (state > PM_SUSPEND_STANDBY) {
+	if (pm_state > PM_SUSPEND_STANDBY) {
 		int error = acpi_save_state_mem();
 		if (error)
 			return error;
@@ -90,7 +91,8 @@
 
 
 	local_irq_save(flags);
-	switch (state)
+	acpi_enable_wakeup_device(acpi_state);
+	switch (pm_state)
 	{
 	case PM_SUSPEND_STANDBY:
 		barrier();
@@ -118,7 +120,7 @@
 	 * And, in the case of the latter, the memory image should have already
 	 * been loaded from disk.
 	 */
-	if (state > PM_SUSPEND_STANDBY)
+	if (pm_state > PM_SUSPEND_STANDBY)
 		acpi_restore_state_mem();
 
 
@@ -128,15 +130,18 @@
 
 /**
  *	acpi_pm_finish - Finish up suspend sequence.
- *	@state:		State we're coming out of.
+ *	@pm_state:		State we're coming out of.
  *
  *	This is called after we wake back up (or if entering the sleep state
  *	failed). 
  */
 
-static int acpi_pm_finish(u32 state)
+static int acpi_pm_finish(u32 pm_state)
 {
-	acpi_leave_sleep_state(state);
+	u32 acpi_state = acpi_suspend_states[pm_state];
+
+	acpi_leave_sleep_state(acpi_state);
+	acpi_disable_wakeup_device(acpi_state);
 
 	/* reset firmware waking vector */
 	acpi_set_firmware_waking_vector((acpi_physical_address) 0);
@@ -199,7 +204,7 @@
 		return 0;
 
 	printk(KERN_INFO PREFIX "(supports");
-	for (i=0; i<ACPI_S_STATE_COUNT; i++) {
+	for (i=0; i < ACPI_S_STATE_COUNT; i++) {
 		acpi_status status;
 		u8 type_a, type_b;
 		status = acpi_get_sleep_type_data(i, &type_a, &type_b);
@@ -212,7 +217,8 @@
 				sleep_states[i] = 1;
 				printk(" S4bios");
 				acpi_pm_ops.pm_disk_mode = PM_DISK_FIRMWARE;
-			} else if (sleep_states[i])
+			}
+			if (sleep_states[i])
 				acpi_pm_ops.pm_disk_mode = PM_DISK_PLATFORM;
 		}
 	}
diff -Nru a/drivers/acpi/sleep/proc.c b/drivers/acpi/sleep/proc.c
--- a/drivers/acpi/sleep/proc.c	2004-10-18 14:56:48 -07:00
+++ b/drivers/acpi/sleep/proc.c	2004-10-18 14:56:48 -07:00
@@ -15,6 +15,7 @@
 
 #define ACPI_SYSTEM_FILE_SLEEP		"sleep"
 #define ACPI_SYSTEM_FILE_ALARM		"alarm"
+#define ACPI_SYSTEM_FILE_WAKEUP_DEVICE   "wakeup"
 
 #define _COMPONENT		ACPI_SYSTEM_COMPONENT
 ACPI_MODULE_NAME		("sleep")
@@ -352,6 +353,84 @@
 	return_VALUE(result ? result : count);
 }
 
+extern struct list_head	acpi_wakeup_device_list;
+extern spinlock_t acpi_device_lock;
+
+static int
+acpi_system_wakeup_device_seq_show(struct seq_file *seq, void *offset)
+{
+	struct list_head * node, * next;
+
+	seq_printf(seq, "Device	Sleep state	Status\n");
+
+	spin_lock(&acpi_device_lock);
+	list_for_each_safe(node, next, &acpi_wakeup_device_list) {
+		struct acpi_device * dev = container_of(node, struct acpi_device, wakeup_list);
+
+		if (!dev->wakeup.flags.valid)
+			continue;
+		spin_unlock(&acpi_device_lock);
+		if (dev->wakeup.flags.run_wake)
+			seq_printf(seq, "%4s	%4d		%8s\n",
+				dev->pnp.bus_id, (u32) dev->wakeup.sleep_state,
+				dev->wakeup.state.enabled ? "*enabled" : "*disabled");
+		else
+			seq_printf(seq, "%4s	%4d		%8s\n",
+				dev->pnp.bus_id, (u32) dev->wakeup.sleep_state,
+				dev->wakeup.state.enabled ? "enabled" : "disabled");
+		spin_lock(&acpi_device_lock);
+	}
+	spin_unlock(&acpi_device_lock);
+	return 0;
+}
+
+static ssize_t
+acpi_system_write_wakeup_device (
+	struct file		*file,
+	const char __user	*buffer,
+	size_t			count,
+	loff_t			*ppos)
+{
+	struct list_head * node, * next;
+	char		strbuf[5];
+	char		str[5] = "";
+	int 		len = count;
+
+	if (len > 4) len = 4;
+
+	if (copy_from_user(strbuf, buffer, len))
+		return -EFAULT;
+	strbuf[len] = '\0';
+	sscanf(strbuf, "%s", str);
+
+	spin_lock(&acpi_device_lock);
+	list_for_each_safe(node, next, &acpi_wakeup_device_list) {
+		struct acpi_device * dev = container_of(node, struct acpi_device, wakeup_list);
+		if (!dev->wakeup.flags.valid)
+			continue;
+
+		if (!strncmp(dev->pnp.bus_id, str, 4)) {
+			dev->wakeup.state.enabled = dev->wakeup.state.enabled ? 0:1;
+			break;
+		}
+	}
+	spin_unlock(&acpi_device_lock);
+	return count;
+}
+
+static int
+acpi_system_wakeup_device_open_fs(struct inode *inode, struct file *file)
+{
+	return single_open(file, acpi_system_wakeup_device_seq_show, PDE(inode)->data);
+}
+
+static struct file_operations acpi_system_wakeup_device_fops = {
+	.open		= acpi_system_wakeup_device_open_fs,
+	.read		= seq_read,
+	.write		= acpi_system_write_wakeup_device,
+	.llseek		= seq_lseek,
+	.release	= single_release,
+};
 
 static struct file_operations acpi_system_sleep_fops = {
 	.open		= acpi_system_sleep_open_fs,
@@ -388,6 +467,13 @@
 		S_IFREG|S_IRUGO|S_IWUSR, acpi_root_dir);
 	if (entry)
 		entry->proc_fops = &acpi_system_alarm_fops;
+
+	/* 'wakeup device' [R/W]*/
+	entry = create_proc_entry(ACPI_SYSTEM_FILE_WAKEUP_DEVICE,
+				  S_IFREG|S_IRUGO|S_IWUSR, acpi_root_dir);
+	if (entry)
+		entry->proc_fops = &acpi_system_wakeup_device_fops;
+
 	return 0;
 }
 
diff -Nru a/drivers/acpi/sleep/sleep.h b/drivers/acpi/sleep/sleep.h
--- a/drivers/acpi/sleep/sleep.h	2004-10-18 14:56:49 -07:00
+++ b/drivers/acpi/sleep/sleep.h	2004-10-18 14:56:49 -07:00
@@ -2,3 +2,6 @@
 extern u8 sleep_states[];
 extern int acpi_suspend (u32 state);
 
+extern void acpi_enable_wakeup_device_prep(u8 sleep_state);
+extern void acpi_enable_wakeup_device(u8 sleep_state);
+extern void acpi_disable_wakeup_device(u8 sleep_state);
diff -Nru a/drivers/acpi/sleep/wakeup.c b/drivers/acpi/sleep/wakeup.c
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/drivers/acpi/sleep/wakeup.c	2004-10-18 14:57:24 -07:00
@@ -0,0 +1,181 @@
+/*
+ * wakeup.c - support wakeup devices
+ */
+
+#include <linux/init.h>
+#include <linux/acpi.h>
+#include <acpi/acpi_drivers.h>
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <acpi/acevents.h>
+#include "sleep.h"
+
+#define _COMPONENT		ACPI_SYSTEM_COMPONENT
+ACPI_MODULE_NAME		("wakeup_devices")
+
+/**
+ * acpi_enable_wakeup_device_prep - prepare wakeup devices
+ *	@sleep_state:	ACPI state
+ * Enable all wakup devices power if the devices' wakeup level
+ * is higher than requested sleep level
+ */
+extern struct list_head	acpi_wakeup_device_list;
+extern spinlock_t acpi_device_lock;
+
+void
+acpi_enable_wakeup_device_prep(
+	u8		sleep_state)
+{
+	struct list_head * node, * next;
+
+	ACPI_FUNCTION_TRACE("acpi_enable_wakeup_device_prep");
+
+	spin_lock(&acpi_device_lock);
+	list_for_each_safe(node, next, &acpi_wakeup_device_list) {
+		struct acpi_device * dev = container_of(node, 
+			struct acpi_device, wakeup_list);
+		
+		if (!dev->wakeup.flags.valid || 
+			!dev->wakeup.state.enabled ||
+			(sleep_state > (u32) dev->wakeup.sleep_state))
+			continue;
+
+		spin_unlock(&acpi_device_lock);
+		acpi_enable_wakeup_device_power(dev);
+		spin_lock(&acpi_device_lock);
+	}
+	spin_unlock(&acpi_device_lock);
+}
+
+/**
+ * acpi_enable_wakeup_device - enable wakeup devices
+ *	@sleep_state:	ACPI state
+ * Enable all wakup devices's GPE
+ */
+void
+acpi_enable_wakeup_device(
+	u8		sleep_state)
+{
+	struct list_head * node, * next;
+
+	/* 
+	 * Caution: this routine must be invoked when interrupt is disabled 
+	 * Refer ACPI2.0: P212
+	 */
+	ACPI_FUNCTION_TRACE("acpi_enable_wakeup_device");
+	spin_lock(&acpi_device_lock);
+	list_for_each_safe(node, next, &acpi_wakeup_device_list) {
+		struct acpi_device * dev = container_of(node, 
+			struct acpi_device, wakeup_list);
+
+		/* If users want to disable run-wake GPE,
+		 * we only disable it for wake and leave it for runtime
+		 */
+		if (dev->wakeup.flags.run_wake && !dev->wakeup.state.enabled) {
+			spin_unlock(&acpi_device_lock);
+			acpi_set_gpe_type(dev->wakeup.gpe_device, 
+				dev->wakeup.gpe_number, ACPI_GPE_TYPE_RUNTIME);
+			/* Re-enable it, since set_gpe_type will disable it */
+			acpi_enable_gpe(dev->wakeup.gpe_device, 
+				dev->wakeup.gpe_number, ACPI_ISR);
+			spin_lock(&acpi_device_lock);
+			continue;
+		}
+
+		if (!dev->wakeup.flags.valid ||
+			!dev->wakeup.state.enabled ||
+			(sleep_state > (u32) dev->wakeup.sleep_state))
+			continue;
+
+		spin_unlock(&acpi_device_lock);
+		/* run-wake GPE has been enabled */
+		if (!dev->wakeup.flags.run_wake)
+			acpi_enable_gpe(dev->wakeup.gpe_device, 
+				dev->wakeup.gpe_number, ACPI_ISR);
+		dev->wakeup.state.active = 1;
+		spin_lock(&acpi_device_lock);
+	}
+	spin_unlock(&acpi_device_lock);
+}
+
+/**
+ * acpi_disable_wakeup_device - disable devices' wakeup capability
+ *	@sleep_state:	ACPI state
+ * Disable all wakup devices's GPE and wakeup capability
+ */
+void
+acpi_disable_wakeup_device (
+	u8		sleep_state)
+{
+	struct list_head * node, * next;
+
+	ACPI_FUNCTION_TRACE("acpi_disable_wakeup_device");
+
+	spin_lock(&acpi_device_lock);
+	list_for_each_safe(node, next, &acpi_wakeup_device_list) {
+		struct acpi_device * dev = container_of(node, 
+			struct acpi_device, wakeup_list);
+
+		if (dev->wakeup.flags.run_wake && !dev->wakeup.state.enabled) {
+			spin_unlock(&acpi_device_lock);
+			acpi_set_gpe_type(dev->wakeup.gpe_device, 
+				dev->wakeup.gpe_number, ACPI_GPE_TYPE_WAKE_RUN);
+			/* Re-enable it, since set_gpe_type will disable it */
+			acpi_enable_gpe(dev->wakeup.gpe_device, 
+				dev->wakeup.gpe_number, ACPI_NOT_ISR);
+			spin_lock(&acpi_device_lock);
+			continue;
+		}
+
+		if (!dev->wakeup.flags.valid || 
+			!dev->wakeup.state.active ||
+			(sleep_state > (u32) dev->wakeup.sleep_state))
+			continue;
+
+		spin_unlock(&acpi_device_lock);
+		acpi_disable_wakeup_device_power(dev);
+		/* Never disable run-wake GPE */
+		if (!dev->wakeup.flags.run_wake) {
+			acpi_disable_gpe(dev->wakeup.gpe_device, 
+				dev->wakeup.gpe_number, ACPI_NOT_ISR);
+			acpi_clear_gpe(dev->wakeup.gpe_device, 
+				dev->wakeup.gpe_number, ACPI_NOT_ISR);
+		}
+		dev->wakeup.state.active = 0;
+		spin_lock(&acpi_device_lock);
+	}
+	spin_unlock(&acpi_device_lock);
+}
+
+static int __init acpi_wakeup_device_init(void)
+{
+	struct list_head * node, * next;
+
+	if (acpi_disabled)
+		return 0;
+	printk("ACPI wakeup devices: \n");
+
+	spin_lock(&acpi_device_lock);
+	list_for_each_safe(node, next, &acpi_wakeup_device_list) {
+		struct acpi_device * dev = container_of(node, 
+			struct acpi_device, wakeup_list);
+		
+		/* In case user doesn't load button driver */
+		if (dev->wakeup.flags.run_wake && !dev->wakeup.state.enabled) {
+			spin_unlock(&acpi_device_lock);
+			acpi_set_gpe_type(dev->wakeup.gpe_device, 
+				dev->wakeup.gpe_number, ACPI_GPE_TYPE_WAKE_RUN);
+			acpi_enable_gpe(dev->wakeup.gpe_device, 
+				dev->wakeup.gpe_number, ACPI_NOT_ISR);
+			dev->wakeup.state.enabled = 1;
+			spin_lock(&acpi_device_lock);
+		}
+		printk("%4s ", dev->pnp.bus_id);
+	}
+	spin_unlock(&acpi_device_lock);
+	printk("\n");
+
+	return 0;
+}
+
+late_initcall(acpi_wakeup_device_init);
diff -Nru a/drivers/acpi/tables/tbxfroot.c b/drivers/acpi/tables/tbxfroot.c
--- a/drivers/acpi/tables/tbxfroot.c	2004-10-18 14:56:49 -07:00
+++ b/drivers/acpi/tables/tbxfroot.c	2004-10-18 14:56:49 -07:00
@@ -115,17 +115,14 @@
  *              Instance        - the non zero instance of the table, allows
  *                                support for multiple tables of the same type
  *              Flags           - Physical/Virtual support
- *              ret_buffer      - pointer to a structure containing a buffer to
- *                                receive the table
+ *              table_pointer   - Where a buffer containing the table is
+ *                                returned
  *
  * RETURN:      Status
  *
- * DESCRIPTION: This function is called to get an ACPI table.  The caller
- *              supplies an out_buffer large enough to contain the entire ACPI
- *              table.  Upon completion
- *              the out_buffer->Length field will indicate the number of bytes
- *              copied into the out_buffer->buf_ptr buffer. This table will be
- *              a complete table including the header.
+ * DESCRIPTION: This function is called to get an ACPI table. A buffer is
+ *              allocated for the table and returned in table_pointer.
+ *              This table will be a complete table including the header.
  *
  ******************************************************************************/
 
@@ -136,12 +133,11 @@
 	u32                             flags,
 	struct acpi_table_header        **table_pointer)
 {
-	struct acpi_pointer             rsdp_address;
-	struct acpi_pointer             address;
 	acpi_status                     status;
-	struct acpi_table_header        header;
-	struct acpi_table_desc          table_info;
-	struct acpi_table_desc          rsdt_info;
+	struct acpi_pointer             address;
+	struct acpi_table_header        *header = NULL;
+	struct acpi_table_desc          *table_info = NULL;
+	struct acpi_table_desc          *rsdt_info;
 	u32                             table_count;
 	u32                             i;
 	u32                             j;
@@ -152,45 +148,41 @@
 
 	/*
 	 * Ensure that at least the table manager is initialized.  We don't
-	 * require that the entire ACPI subsystem is up for this interface
-	 */
-
-	/*
-	 *  If we have a buffer, we must have a length too
+	 * require that the entire ACPI subsystem is up for this interface.
+	 * If we have a buffer, we must have a length too
 	 */
-	if ((instance == 0)                 ||
-		(!signature)                    ||
+	if ((instance == 0)     ||
+		(!signature)        ||
 		(!table_pointer)) {
 		return_ACPI_STATUS (AE_BAD_PARAMETER);
 	}
 
-	rsdt_info.pointer = NULL;
+	/* Ensure that we have a RSDP */
 
 	if (!acpi_gbl_RSDP) {
 		/* Get the RSDP */
 
-		status = acpi_os_get_root_pointer (flags, &rsdp_address);
+		status = acpi_os_get_root_pointer (flags, &address);
 		if (ACPI_FAILURE (status)) {
-			ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "RSDP  not found\n"));
+			ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "RSDP not found\n"));
 			return_ACPI_STATUS (AE_NO_ACPI_TABLES);
 		}
 
 		/* Map and validate the RSDP */
 
 		if ((flags & ACPI_MEMORY_MODE) == ACPI_LOGICAL_ADDRESSING) {
-			status = acpi_os_map_memory (rsdp_address.pointer.physical, sizeof (struct rsdp_descriptor),
+			status = acpi_os_map_memory (address.pointer.physical, sizeof (struct rsdp_descriptor),
 					  (void *) &acpi_gbl_RSDP);
 			if (ACPI_FAILURE (status)) {
 				return_ACPI_STATUS (status);
 			}
 		}
 		else {
-			acpi_gbl_RSDP = rsdp_address.pointer.logical;
+			acpi_gbl_RSDP = address.pointer.logical;
 		}
 
-		/*
-		 *  The signature and checksum must both be correct
-		 */
+		/* The signature and checksum must both be correct */
+
 		if (ACPI_STRNCMP ((char *) acpi_gbl_RSDP, RSDP_SIG, sizeof (RSDP_SIG)-1) != 0) {
 			/* Nope, BAD Signature */
 
@@ -204,10 +196,9 @@
 		}
 	}
 
-	/* Get the RSDT and validate it */
+	/* Get the RSDT address via the RSDP */
 
 	acpi_tb_get_rsdt_address (&address);
-
 	ACPI_DEBUG_PRINT ((ACPI_DB_INFO,
 		"RSDP located at %p, RSDT physical=%8.8X%8.8X \n",
 		acpi_gbl_RSDP,
@@ -217,20 +208,40 @@
 
 	address.pointer_type |= flags;
 
-	status = acpi_tb_get_table (&address, &rsdt_info);
+	/* Get and validate the RSDT */
+
+	rsdt_info = ACPI_MEM_CALLOCATE (sizeof (struct acpi_table_desc));
+	if (!rsdt_info) {
+		return_ACPI_STATUS (AE_NO_MEMORY);
+	}
+
+	status = acpi_tb_get_table (&address, rsdt_info);
 	if (ACPI_FAILURE (status)) {
-		return_ACPI_STATUS (status);
+		goto cleanup;
 	}
 
-	status = acpi_tb_validate_rsdt (rsdt_info.pointer);
+	status = acpi_tb_validate_rsdt (rsdt_info->pointer);
 	if (ACPI_FAILURE (status)) {
 		goto cleanup;
 	}
 
-	/* Get the number of table pointers within the RSDT */
+	/* Allocate a scratch table header and table descriptor */
 
-	table_count = acpi_tb_get_table_count (acpi_gbl_RSDP, rsdt_info.pointer);
+	header = ACPI_MEM_ALLOCATE (sizeof (struct acpi_table_header));
+	if (!header) {
+		status = AE_NO_MEMORY;
+		goto cleanup;
+	}
 
+	table_info = ACPI_MEM_ALLOCATE (sizeof (struct acpi_table_desc));
+	if (!table_info) {
+		status = AE_NO_MEMORY;
+		goto cleanup;
+	}
+
+	/* Get the number of table pointers within the RSDT */
+
+	table_count = acpi_tb_get_table_count (acpi_gbl_RSDP, rsdt_info->pointer);
 	address.pointer_type = acpi_gbl_table_flags | flags;
 
 	/*
@@ -241,35 +252,36 @@
 		/* Get the next table pointer, handle RSDT vs. XSDT */
 
 		if (acpi_gbl_RSDP->revision < 2) {
-			address.pointer.value = (ACPI_CAST_PTR (RSDT_DESCRIPTOR, rsdt_info.pointer))->table_offset_entry[i];
+			address.pointer.value = (ACPI_CAST_PTR (
+				RSDT_DESCRIPTOR, rsdt_info->pointer))->table_offset_entry[i];
 		}
 		else {
-			address.pointer.value =
-				(ACPI_CAST_PTR (XSDT_DESCRIPTOR, rsdt_info.pointer))->table_offset_entry[i];
+			address.pointer.value = (ACPI_CAST_PTR (
+				XSDT_DESCRIPTOR, rsdt_info->pointer))->table_offset_entry[i];
 		}
 
 		/* Get the table header */
 
-		status = acpi_tb_get_table_header (&address, &header);
+		status = acpi_tb_get_table_header (&address, header);
 		if (ACPI_FAILURE (status)) {
 			goto cleanup;
 		}
 
 		/* Compare table signatures and table instance */
 
-		if (!ACPI_STRNCMP (header.signature, signature, ACPI_NAME_SIZE)) {
+		if (!ACPI_STRNCMP (header->signature, signature, ACPI_NAME_SIZE)) {
 			/* An instance of the table was found */
 
 			j++;
 			if (j >= instance) {
 				/* Found the correct instance, get the entire table */
 
-				status = acpi_tb_get_table_body (&address, &header, &table_info);
+				status = acpi_tb_get_table_body (&address, header, table_info);
 				if (ACPI_FAILURE (status)) {
 					goto cleanup;
 				}
 
-				*table_pointer = table_info.pointer;
+				*table_pointer = table_info->pointer;
 				goto cleanup;
 			}
 		}
@@ -281,7 +293,15 @@
 
 
 cleanup:
-	acpi_os_unmap_memory (rsdt_info.pointer, (acpi_size) rsdt_info.pointer->length);
+	acpi_os_unmap_memory (rsdt_info->pointer, (acpi_size) rsdt_info->pointer->length);
+	ACPI_MEM_FREE (rsdt_info);
+
+	if (header) {
+		ACPI_MEM_FREE (header);
+	}
+	if (table_info) {
+		ACPI_MEM_FREE (table_info);
+	}
 	return_ACPI_STATUS (status);
 }
 
@@ -389,14 +409,17 @@
  *              Flags                   - Current memory mode (logical vs.
  *                                        physical addressing)
  *
- * RETURN:      Status
+ * RETURN:      Status, RSDP physical address
  *
  * DESCRIPTION: search lower 1_mbyte of memory for the root system descriptor
  *              pointer structure.  If it is found, set *RSDP to point to it.
  *
- *              NOTE: The RSDp must be either in the first 1_k of the Extended
- *              BIOS Data Area or between E0000 and FFFFF (ACPI 1.0 section
- *              5.2.2; assertion #421).
+ *              NOTE1: The RSDp must be either in the first 1_k of the Extended
+ *              BIOS Data Area or between E0000 and FFFFF (From ACPI Spec.)
+ *              Only a 32-bit physical address is necessary.
+ *
+ *              NOTE2: This function is always available, regardless of the
+ *              initialization state of the rest of ACPI.
  *
  ******************************************************************************/
 
@@ -407,8 +430,8 @@
 {
 	u8                              *table_ptr;
 	u8                              *mem_rover;
-	u64                             phys_addr;
-	acpi_status                     status = AE_OK;
+	u32                             physical_address;
+	acpi_status                     status;
 
 
 	ACPI_FUNCTION_TRACE ("tb_find_rsdp");
@@ -419,36 +442,57 @@
 	 */
 	if ((flags & ACPI_MEMORY_MODE) == ACPI_LOGICAL_ADDRESSING) {
 		/*
-		 * 1) Search EBDA (low memory) paragraphs
+		 * 1a) Get the location of the EBDA
 		 */
-		status = acpi_os_map_memory ((u64) ACPI_LO_RSDP_WINDOW_BASE, ACPI_LO_RSDP_WINDOW_SIZE,
+		status = acpi_os_map_memory ((acpi_physical_address) ACPI_EBDA_PTR_LOCATION,
+				  ACPI_EBDA_PTR_LENGTH,
 				  (void *) &table_ptr);
 		if (ACPI_FAILURE (status)) {
-			ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Could not map memory at %X for length %X\n",
-				ACPI_LO_RSDP_WINDOW_BASE, ACPI_LO_RSDP_WINDOW_SIZE));
+			ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Could not map memory at %8.8X for length %X\n",
+				ACPI_EBDA_PTR_LOCATION, ACPI_EBDA_PTR_LENGTH));
 			return_ACPI_STATUS (status);
 		}
 
-		mem_rover = acpi_tb_scan_memory_for_rsdp (table_ptr, ACPI_LO_RSDP_WINDOW_SIZE);
-		acpi_os_unmap_memory (table_ptr, ACPI_LO_RSDP_WINDOW_SIZE);
+		ACPI_MOVE_16_TO_32 (&physical_address, table_ptr);
+		physical_address <<= 4;                 /* Convert segment to physical address */
+		acpi_os_unmap_memory (table_ptr, ACPI_EBDA_PTR_LENGTH);
+
+		/* EBDA present? */
+
+		if (physical_address > 0x400) {
+			/*
+			 * 1b) Search EBDA paragraphs (EBDa is required to be a minimum of 1_k length)
+			 */
+			status = acpi_os_map_memory ((acpi_physical_address) physical_address,
+					  ACPI_EBDA_WINDOW_SIZE,
+					  (void *) &table_ptr);
+			if (ACPI_FAILURE (status)) {
+				ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Could not map memory at %8.8X for length %X\n",
+					physical_address, ACPI_EBDA_WINDOW_SIZE));
+				return_ACPI_STATUS (status);
+			}
 
-		if (mem_rover) {
-			/* Found it, return the physical address */
+			mem_rover = acpi_tb_scan_memory_for_rsdp (table_ptr, ACPI_EBDA_WINDOW_SIZE);
+			acpi_os_unmap_memory (table_ptr, ACPI_EBDA_WINDOW_SIZE);
 
-			phys_addr = ACPI_LO_RSDP_WINDOW_BASE;
-			phys_addr += ACPI_PTR_DIFF (mem_rover,table_ptr);
+			if (mem_rover) {
+				/* Found it, return the physical address */
 
-			table_info->physical_address = phys_addr;
-			return_ACPI_STATUS (AE_OK);
+				physical_address += ACPI_PTR_DIFF (mem_rover, table_ptr);
+
+				table_info->physical_address = (acpi_physical_address) physical_address;
+				return_ACPI_STATUS (AE_OK);
+			}
 		}
 
 		/*
-		 * 2) Search upper memory: 16-byte boundaries in E0000h-F0000h
+		 * 2) Search upper memory: 16-byte boundaries in E0000h-FFFFFh
 		 */
-		status = acpi_os_map_memory ((u64) ACPI_HI_RSDP_WINDOW_BASE, ACPI_HI_RSDP_WINDOW_SIZE,
+		status = acpi_os_map_memory ((acpi_physical_address) ACPI_HI_RSDP_WINDOW_BASE,
+				  ACPI_HI_RSDP_WINDOW_SIZE,
 				  (void *) &table_ptr);
 		if (ACPI_FAILURE (status)) {
-			ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Could not map memory at %X for length %X\n",
+			ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Could not map memory at %8.8X for length %X\n",
 				ACPI_HI_RSDP_WINDOW_BASE, ACPI_HI_RSDP_WINDOW_SIZE));
 			return_ACPI_STATUS (status);
 		}
@@ -459,10 +503,9 @@
 		if (mem_rover) {
 			/* Found it, return the physical address */
 
-			phys_addr = ACPI_HI_RSDP_WINDOW_BASE;
-			phys_addr += ACPI_PTR_DIFF (mem_rover, table_ptr);
+			physical_address = ACPI_HI_RSDP_WINDOW_BASE + ACPI_PTR_DIFF (mem_rover, table_ptr);
 
-			table_info->physical_address = phys_addr;
+			table_info->physical_address = (acpi_physical_address) physical_address;
 			return_ACPI_STATUS (AE_OK);
 		}
 	}
@@ -472,19 +515,29 @@
 	 */
 	else {
 		/*
-		 * 1) Search EBDA (low memory) paragraphs
+		 * 1a) Get the location of the EBDA
 		 */
-		mem_rover = acpi_tb_scan_memory_for_rsdp (ACPI_PHYSADDR_TO_PTR (ACPI_LO_RSDP_WINDOW_BASE),
-				  ACPI_LO_RSDP_WINDOW_SIZE);
-		if (mem_rover) {
-			/* Found it, return the physical address */
+		ACPI_MOVE_16_TO_32 (&physical_address, ACPI_EBDA_PTR_LOCATION);
+		physical_address <<= 4;     /* Convert segment to physical address */
 
-			table_info->physical_address = ACPI_TO_INTEGER (mem_rover);
-			return_ACPI_STATUS (AE_OK);
+		/* EBDA present? */
+
+		if (physical_address > 0x400) {
+			/*
+			 * 1b) Search EBDA paragraphs (EBDa is required to be a minimum of 1_k length)
+			 */
+			mem_rover = acpi_tb_scan_memory_for_rsdp (ACPI_PHYSADDR_TO_PTR (physical_address),
+					  ACPI_EBDA_WINDOW_SIZE);
+			if (mem_rover) {
+				/* Found it, return the physical address */
+
+				table_info->physical_address = ACPI_TO_INTEGER (mem_rover);
+				return_ACPI_STATUS (AE_OK);
+			}
 		}
 
 		/*
-		 * 2) Search upper memory: 16-byte boundaries in E0000h-F0000h
+		 * 2) Search upper memory: 16-byte boundaries in E0000h-FFFFFh
 		 */
 		mem_rover = acpi_tb_scan_memory_for_rsdp (ACPI_PHYSADDR_TO_PTR (ACPI_HI_RSDP_WINDOW_BASE),
 				  ACPI_HI_RSDP_WINDOW_SIZE);
diff -Nru a/drivers/acpi/tables.c b/drivers/acpi/tables.c
--- a/drivers/acpi/tables.c	2004-10-18 14:56:28 -07:00
+++ b/drivers/acpi/tables.c	2004-10-18 14:56:28 -07:00
@@ -101,7 +101,7 @@
 	else
 		name = header->signature;
 
-	printk(KERN_INFO PREFIX "%.4s (v%3.3d %6.6s %8.8s 0x%08x %.4s 0x%08x) @ 0x%p\n",
+	printk(KERN_DEBUG PREFIX "%.4s (v%3.3d %6.6s %8.8s 0x%08x %.4s 0x%08x) @ 0x%p\n",
 		name, header->revision, header->oem_id,
 		header->oem_table_id, header->oem_revision,
 		header->asl_compiler_id, header->asl_compiler_revision,
@@ -587,7 +587,7 @@
 		return -ENODEV;
 	}
 
-	printk(KERN_INFO PREFIX "RSDP (v%3.3d %6.6s                                    ) @ 0x%p\n",
+	printk(KERN_DEBUG PREFIX "RSDP (v%3.3d %6.6s                                ) @ 0x%p\n",
 		rsdp->revision, rsdp->oem_id, (void *) rsdp_phys);
 
 	if (rsdp->revision < 2)
diff -Nru a/drivers/acpi/thermal.c b/drivers/acpi/thermal.c
--- a/drivers/acpi/thermal.c	2004-10-18 14:56:50 -07:00
+++ b/drivers/acpi/thermal.c	2004-10-18 14:56:50 -07:00
@@ -60,6 +60,7 @@
 #define ACPI_THERMAL_NOTIFY_HOT		0xF1
 #define ACPI_THERMAL_MODE_ACTIVE	0x00
 #define ACPI_THERMAL_MODE_PASSIVE	0x01
+#define ACPI_THERMAL_MODE_CRT   	0xff
 #define ACPI_THERMAL_PATH_POWEROFF	"/sbin/poweroff"
 
 #define ACPI_THERMAL_MAX_ACTIVE	10
@@ -160,6 +161,7 @@
 	unsigned long		last_temperature;
 	unsigned long		polling_frequency;
 	u8			cooling_mode;
+	volatile u8		zombie;
 	struct acpi_thermal_flags flags;
 	struct acpi_thermal_state state;
 	struct acpi_thermal_trips trips;
@@ -289,13 +291,6 @@
 	status = acpi_get_handle(tz->handle, "_SCP", &handle);
 	if (ACPI_FAILURE(status)) {
 		ACPI_DEBUG_PRINT((ACPI_DB_INFO, "_SCP not present\n"));
-		status = acpi_get_handle(tz->handle, "_PSV", &handle);
-		if(!ACPI_FAILURE(status)) {
-			tz->cooling_mode = 1;
-			ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Cooling mode [%s]\n", 
-				mode?"passive":"active"));
-			return_VALUE(0);
-		}
 		return_VALUE(-ENODEV);
 	}
 
@@ -653,7 +648,10 @@
 acpi_thermal_run (
 	unsigned long		data)
 {
-	acpi_os_queue_for_execution(OSD_PRIORITY_GPE,  acpi_thermal_check, (void *) data);
+	struct acpi_thermal *tz = (struct acpi_thermal *)data;
+	if (!tz->zombie)
+		acpi_os_queue_for_execution(OSD_PRIORITY_GPE,  
+			acpi_thermal_check, (void *) data);
 }
 
 
@@ -665,7 +663,7 @@
 	struct acpi_thermal	*tz = (struct acpi_thermal *) data;
 	unsigned long		sleep_time = 0;
 	int			i = 0;
-	struct acpi_thermal_state state = tz->state;
+	struct acpi_thermal_state state;
 
 	ACPI_FUNCTION_TRACE("acpi_thermal_check");
 
@@ -674,6 +672,8 @@
 		return_VOID;
 	}
 
+	state = tz->state;
+
 	result = acpi_thermal_get_temperature(tz);
 	if (result)
 		return_VOID;
@@ -899,8 +899,10 @@
 	struct seq_file		*m = (struct seq_file *)file->private_data;
 	struct acpi_thermal	*tz = (struct acpi_thermal *)m->private;
 
-	char			limit_string[25] = {'\0'};
-	int			critical, hot, passive, active0, active1;
+	char			limit_string[65] = {'\0'};
+	int			num, critical, hot, passive;
+	int			active[ACPI_THERMAL_MAX_ACTIVE];
+	int			i = 0;
 
 	ACPI_FUNCTION_TRACE("acpi_thermal_write_trip_points");
 
@@ -916,7 +918,11 @@
 	
 	limit_string[count] = '\0';
 
-	if (sscanf(limit_string, "%d:%d:%d:%d:%d", &critical, &hot, &passive, &active0, &active1) != 5) {
+	num = sscanf(limit_string, "%d:%d:%d:%d:%d:%d:%d:%d:%d:%d:%d:%d:%d",
+				&critical, &hot, &passive,
+				&active[0], &active[1], &active[2], &active[3], &active[4],
+				&active[5], &active[6], &active[7], &active[8], &active[9]);
+	if(!(num >=5 && num < (ACPI_THERMAL_MAX_ACTIVE + 3))) {
 		ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Invalid data format\n"));
 		return_VALUE(-EINVAL);
 	}
@@ -924,8 +930,11 @@
 	tz->trips.critical.temperature = CELSIUS_TO_KELVIN(critical);
 	tz->trips.hot.temperature = CELSIUS_TO_KELVIN(hot);
 	tz->trips.passive.temperature = CELSIUS_TO_KELVIN(passive);
-	tz->trips.active[0].temperature = CELSIUS_TO_KELVIN(active0);
-	tz->trips.active[1].temperature = CELSIUS_TO_KELVIN(active1);
+	for (i = 0; i < num - 3; i++) {
+		if (!(tz->trips.active[i].flags.valid))
+			break;
+		tz->trips.active[i].temperature = CELSIUS_TO_KELVIN(active[i]);
+	}
 	
 	return_VALUE(count);
 }
@@ -941,12 +950,14 @@
 		goto end;
 
 	if (!tz->flags.cooling_mode) {
-		seq_puts(seq, "<not supported>\n");
-		goto end;
+		seq_puts(seq, "<setting not supported>\n");
 	}
 
-	seq_printf(seq, "cooling mode:            %s\n",
-		tz->cooling_mode?"passive":"active");
+	if ( tz->cooling_mode == ACPI_THERMAL_MODE_CRT )
+		seq_printf(seq, "cooling mode:	critical\n");
+	else
+		seq_printf(seq, "cooling mode:	%s\n",
+			tz->cooling_mode?"passive":"active");
 
 end:
 	return 0;
@@ -988,6 +999,8 @@
 	if (result)
 		return_VALUE(result);
 
+	acpi_thermal_check(tz);
+
 	return_VALUE(count);
 }
 
@@ -1225,16 +1238,34 @@
 	if (result)
 		return_VALUE(result);
 
-	/* Set the cooling mode [_SCP] to active cooling (default) */
-	result = acpi_thermal_set_cooling_mode(tz, ACPI_THERMAL_MODE_ACTIVE);
-	if (!result)
-		tz->flags.cooling_mode = 1;
-
 	/* Get trip points [_CRT, _PSV, etc.] (required) */
 	result = acpi_thermal_get_trip_points(tz);
 	if (result)
 		return_VALUE(result);
 
+	/* Set the cooling mode [_SCP] to active cooling (default) */
+	result = acpi_thermal_set_cooling_mode(tz, ACPI_THERMAL_MODE_ACTIVE);
+	if (!result) 
+		tz->flags.cooling_mode = 1;
+	else { 
+		/* Oh,we have not _SCP method.
+		   Generally show cooling_mode by _ACx, _PSV,spec 12.2*/
+		tz->flags.cooling_mode = 0;
+		if ( tz->trips.active[0].flags.valid && tz->trips.passive.flags.valid ) {
+			if ( tz->trips.passive.temperature > tz->trips.active[0].temperature )
+				tz->cooling_mode = ACPI_THERMAL_MODE_ACTIVE;
+			else 
+				tz->cooling_mode = ACPI_THERMAL_MODE_PASSIVE;
+		} else if ( !tz->trips.active[0].flags.valid && tz->trips.passive.flags.valid ) {
+			tz->cooling_mode = ACPI_THERMAL_MODE_PASSIVE;
+		} else if ( tz->trips.active[0].flags.valid && !tz->trips.passive.flags.valid ) {
+			tz->cooling_mode = ACPI_THERMAL_MODE_ACTIVE;
+		} else {
+			/* _ACx and _PSV are optional, but _CRT is required */
+			tz->cooling_mode = ACPI_THERMAL_MODE_CRT;
+		}
+	}
+
 	/* Get default polling frequency [_TZP] (optional) */
 	if (tzp)
 		tz->polling_frequency = tzp;
@@ -1324,8 +1355,14 @@
 
 	tz = (struct acpi_thermal *) acpi_driver_data(device);
 
-	if (timer_pending(&(tz->timer)))
-		del_timer(&(tz->timer));
+	/* avoid timer adding new defer task */
+	tz->zombie = 1;
+	/* wait for running timer (on other CPUs) finish */
+	del_timer_sync(&(tz->timer));
+	/* synchronize deferred task */
+	acpi_os_wait_events_complete(NULL);
+	/* deferred task may reinsert timer */
+	del_timer_sync(&(tz->timer));
 
 	status = acpi_remove_notify_handler(tz->handle,
 		ACPI_DEVICE_NOTIFY, acpi_thermal_notify);
@@ -1347,6 +1384,7 @@
 
 	acpi_thermal_remove_fs(device);
 
+	kfree(tz);
 	return_VALUE(0);
 }
 
diff -Nru a/drivers/acpi/utilities/utalloc.c b/drivers/acpi/utilities/utalloc.c
--- a/drivers/acpi/utilities/utalloc.c	2004-10-18 14:55:55 -07:00
+++ b/drivers/acpi/utilities/utalloc.c	2004-10-18 14:55:55 -07:00
@@ -259,8 +259,8 @@
  *
  * FUNCTION:    acpi_ut_initialize_buffer
  *
- * PARAMETERS:  required_length     - Length needed
- *              Buffer              - Buffer to be validated
+ * PARAMETERS:  Buffer              - Buffer to be validated
+ *              required_length     - Length needed
  *
  * RETURN:      Status
  *
@@ -603,7 +603,8 @@
  *
  * FUNCTION:    acpi_ut_find_allocation
  *
- * PARAMETERS:  Allocation             - Address of allocated memory
+ * PARAMETERS:  list_id                 - Memory list to search
+ *              Allocation              - Address of allocated memory
  *
  * RETURN:      A list element if found; NULL otherwise.
  *
@@ -646,7 +647,8 @@
  *
  * FUNCTION:    acpi_ut_track_allocation
  *
- * PARAMETERS:  Allocation          - Address of allocated memory
+ * PARAMETERS:  list_id             - Memory list to search
+ *              Allocation          - Address of allocated memory
  *              Size                - Size of the allocation
  *              alloc_type          - MEM_MALLOC or MEM_CALLOC
  *              Component           - Component type of caller
@@ -733,7 +735,8 @@
  *
  * FUNCTION:    acpi_ut_remove_allocation
  *
- * PARAMETERS:  Allocation          - Address of allocated memory
+ * PARAMETERS:  list_id             - Memory list to search
+ *              Allocation          - Address of allocated memory
  *              Component           - Component type of caller
  *              Module              - Source file name of caller
  *              Line                - Line number of caller
diff -Nru a/drivers/acpi/utilities/uteval.c b/drivers/acpi/utilities/uteval.c
--- a/drivers/acpi/utilities/uteval.c	2004-10-18 14:55:54 -07:00
+++ b/drivers/acpi/utilities/uteval.c	2004-10-18 14:55:54 -07:00
@@ -133,7 +133,7 @@
 	u32                             expected_return_btypes,
 	union acpi_operand_object       **return_desc)
 {
-	union acpi_operand_object       *obj_desc;
+	struct acpi_parameter_info      info;
 	acpi_status                     status;
 	u32                             return_btype;
 
@@ -141,9 +141,13 @@
 	ACPI_FUNCTION_TRACE ("ut_evaluate_object");
 
 
+	info.node = prefix_node;
+	info.parameters = NULL;
+	info.parameter_type = ACPI_PARAM_ARGS;
+
 	/* Evaluate the object/method */
 
-	status = acpi_ns_evaluate_relative (prefix_node, path, NULL, &obj_desc);
+	status = acpi_ns_evaluate_relative (path, &info);
 	if (ACPI_FAILURE (status)) {
 		if (status == AE_NOT_FOUND) {
 			ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "[%4.4s.%s] was not found\n",
@@ -159,7 +163,7 @@
 
 	/* Did we get a return object? */
 
-	if (!obj_desc) {
+	if (!info.return_object) {
 		if (expected_return_btypes) {
 			ACPI_REPORT_METHOD_ERROR ("No object was returned from",
 				prefix_node, path, AE_NOT_EXIST);
@@ -172,7 +176,7 @@
 
 	/* Map the return object type to the bitmapped type */
 
-	switch (ACPI_GET_OBJECT_TYPE (obj_desc)) {
+	switch (ACPI_GET_OBJECT_TYPE (info.return_object)) {
 	case ACPI_TYPE_INTEGER:
 		return_btype = ACPI_BTYPE_INTEGER;
 		break;
@@ -202,17 +206,17 @@
 
 		ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
 			"Type returned from %s was incorrect: %X\n",
-			path, ACPI_GET_OBJECT_TYPE (obj_desc)));
+			path, ACPI_GET_OBJECT_TYPE (info.return_object)));
 
 		/* On error exit, we must delete the return object */
 
-		acpi_ut_remove_reference (obj_desc);
+		acpi_ut_remove_reference (info.return_object);
 		return_ACPI_STATUS (AE_TYPE);
 	}
 
 	/* Object type is OK, return it */
 
-	*return_desc = obj_desc;
+	*return_desc = info.return_object;
 	return_ACPI_STATUS (AE_OK);
 }
 
diff -Nru a/drivers/acpi/utilities/utglobal.c b/drivers/acpi/utilities/utglobal.c
--- a/drivers/acpi/utilities/utglobal.c	2004-10-18 14:55:55 -07:00
+++ b/drivers/acpi/utilities/utglobal.c	2004-10-18 14:55:55 -07:00
@@ -142,16 +142,11 @@
  */
 
 /* Debug switch - level and trace mask */
-
-#ifdef ACPI_DEBUG_OUTPUT
-u32                                 acpi_dbg_level = ACPI_DEBUG_DEFAULT;
-#else
-u32                                 acpi_dbg_level = ACPI_NORMAL_DEFAULT;
-#endif
+u32                                 acpi_dbg_level = 0;
 
 /* Debug switch - layer (component) mask */
 
-u32                                 acpi_dbg_layer = ACPI_COMPONENT_DEFAULT;
+u32                                 acpi_dbg_layer = 0;
 u32                                 acpi_gbl_nesting_level = 0;
 
 
@@ -171,27 +166,40 @@
 
 const u8                            acpi_gbl_decode_to8bit [8] = {1,2,4,8,16,32,64,128};
 
-const char                          *acpi_gbl_sleep_state_names[ACPI_S_STATE_COUNT] = {
-			  "\\_S0_",
-			  "\\_S1_",
-			  "\\_S2_",
-			  "\\_S3_",
-			  "\\_S4_",
-			  "\\_S5_"};
-
-const char                          *acpi_gbl_highest_dstate_names[4] = {
-					   "_S1D",
-					   "_S2D",
-					   "_S3D",
-					   "_S4D"};
-
-/* Strings supported by the _OSI predefined (internal) method */
-
-const char                          *acpi_gbl_valid_osi_strings[ACPI_NUM_OSI_STRINGS] = {
-							 "Linux",
-							 "Windows 2000",
-							 "Windows 2001",
-							 "Windows 2001.1"};
+const char                          *acpi_gbl_sleep_state_names[ACPI_S_STATE_COUNT] =
+{
+	"\\_S0_",
+	"\\_S1_",
+	"\\_S2_",
+	"\\_S3_",
+	"\\_S4_",
+	"\\_S5_"
+};
+
+const char                          *acpi_gbl_highest_dstate_names[4] =
+{
+	"_S1D",
+	"_S2D",
+	"_S3D",
+	"_S4D"
+};
+
+/*
+ * Strings supported by the _OSI predefined (internal) method.
+ * When adding strings, be sure to update ACPI_NUM_OSI_STRINGS.
+ */
+const char                          *acpi_gbl_valid_osi_strings[ACPI_NUM_OSI_STRINGS] =
+{
+	"Linux",
+	"Windows 2000",
+	"Windows 2001",
+	"Windows 2001.1",
+	"Windows 2001 SP0",
+	"Windows 2001 SP1",
+	"Windows 2001 SP2",
+	"Windows 2001 SP3",
+	"Windows 2001 SP4"
+};
 
 
 /******************************************************************************
@@ -213,7 +221,7 @@
 	{"_PR_",    ACPI_TYPE_LOCAL_SCOPE,      NULL},
 	{"_SB_",    ACPI_TYPE_DEVICE,           NULL},
 	{"_SI_",    ACPI_TYPE_LOCAL_SCOPE,      NULL},
-	{"_TZ_",    ACPI_TYPE_LOCAL_SCOPE,      NULL},
+	{"_TZ_",    ACPI_TYPE_THERMAL,          NULL},
 	{"_REV",    ACPI_TYPE_INTEGER,          "2"},
 	{"_OS_",    ACPI_TYPE_STRING,           ACPI_OS_NAME},
 	{"_GL_",    ACPI_TYPE_MUTEX,            "0"},
@@ -561,26 +569,37 @@
 	struct acpi_namespace_node      *node = (struct acpi_namespace_node *) object;
 
 
+	/* Must return a string of exactly 4 characters == ACPI_NAME_SIZE */
+
 	if (!object)
 	{
-		return ("NULL NODE");
+		return ("NULL");
 	}
 
-	if (object == ACPI_ROOT_OBJECT)
+	/* Check for Root node */
+
+	if ((object == ACPI_ROOT_OBJECT) ||
+		(object == acpi_gbl_root_node))
 	{
-		node = acpi_gbl_root_node;
+		return ("\"\\\" ");
 	}
 
+	/* Descriptor must be a namespace node */
+
 	if (node->descriptor != ACPI_DESC_TYPE_NAMED)
 	{
-		return ("****");
+		return ("####");
 	}
 
+	/* Name must be a valid ACPI name */
+
 	if (!acpi_ut_valid_acpi_name (* (u32 *) node->name.ascii))
 	{
-		return ("----");
+		return ("????");
 	}
 
+	/* Return the name */
+
 	return (node->name.ascii);
 }
 
@@ -783,10 +802,6 @@
 
 	ACPI_FUNCTION_TRACE ("ut_init_globals");
 
-	/* Runtime configuration */
-
-	acpi_gbl_create_osi_method = TRUE;
-	acpi_gbl_all_methods_serialized = FALSE;
 
 	/* Memory allocation and cache lists */
 
@@ -880,6 +895,7 @@
 	/* Hardware oriented */
 
 	acpi_gbl_events_initialized         = FALSE;
+	acpi_gbl_system_awake_and_running   = TRUE;
 
 	/* Namespace */
 
diff -Nru a/drivers/acpi/utilities/utxface.c b/drivers/acpi/utilities/utxface.c
--- a/drivers/acpi/utilities/utxface.c	2004-10-18 14:55:55 -07:00
+++ b/drivers/acpi/utilities/utxface.c	2004-10-18 14:55:55 -07:00
@@ -157,9 +157,8 @@
 		}
 	}
 
-	/*
-	 * Enable ACPI mode
-	 */
+	/* Enable ACPI mode */
+
 	if (!(flags & ACPI_NO_ACPI_ENABLE)) {
 		ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "[Init] Going into ACPI mode\n"));
 
@@ -173,7 +172,21 @@
 	}
 
 	/*
-	 * Initialize ACPI Event handling
+	 * Install the default op_region handlers. These are installed unless
+	 * other handlers have already been installed via the
+	 * install_address_space_handler interface.
+	 */
+	if (!(flags & ACPI_NO_ADDRESS_SPACE_INIT)) {
+		ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "[Init] Installing default address space handlers\n"));
+
+		status = acpi_ev_install_region_handlers ();
+		if (ACPI_FAILURE (status)) {
+			return_ACPI_STATUS (status);
+		}
+	}
+
+	/*
+	 * Initialize ACPI Event handling (Fixed and General Purpose)
 	 *
 	 * NOTE: We must have the hardware AND events initialized before we can execute
 	 * ANY control methods SAFELY.  Any control method can require ACPI hardware
@@ -182,18 +195,18 @@
 	if (!(flags & ACPI_NO_EVENT_INIT)) {
 		ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "[Init] Initializing ACPI events\n"));
 
-		status = acpi_ev_initialize ();
+		status = acpi_ev_initialize_events ();
 		if (ACPI_FAILURE (status)) {
 			return_ACPI_STATUS (status);
 		}
 	}
 
-	/* Install the SCI handler, Global Lock handler, and GPE handlers */
+	/* Install the SCI handler and Global Lock handler */
 
 	if (!(flags & ACPI_NO_HANDLER_INIT)) {
-		ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "[Init] Installing SCI/GL/GPE handlers\n"));
+		ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "[Init] Installing SCI/GL handlers\n"));
 
-		status = acpi_ev_handler_initialize ();
+		status = acpi_ev_install_xrupt_handlers ();
 		if (ACPI_FAILURE (status)) {
 			return_ACPI_STATUS (status);
 		}
@@ -226,18 +239,16 @@
 
 
 	/*
-	 * Install the default op_region handlers. These are installed unless
-	 * other handlers have already been installed via the
-	 * install_address_space_handler interface.
+	 * Run all _REG methods
 	 *
-	 * NOTE: This will cause _REG methods to be run.  Any objects accessed
+	 * NOTE: Any objects accessed
 	 * by the _REG methods will be automatically initialized, even if they
 	 * contain executable AML (see call to acpi_ns_initialize_objects below).
 	 */
 	if (!(flags & ACPI_NO_ADDRESS_SPACE_INIT)) {
-		ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "[Init] Installing default address space handlers\n"));
+		ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "[Init] Executing _REG op_region methods\n"));
 
-		status = acpi_ev_init_address_spaces ();
+		status = acpi_ev_initialize_op_regions ();
 		if (ACPI_FAILURE (status)) {
 			return_ACPI_STATUS (status);
 		}
@@ -249,7 +260,7 @@
 	 * objects: operation_regions, buffer_fields, Buffers, and Packages.
 	 */
 	if (!(flags & ACPI_NO_OBJECT_INIT)) {
-		ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "[Init] Initializing ACPI Objects\n"));
+		ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "[Init] Completing Initialization of ACPI Objects\n"));
 
 		status = acpi_ns_initialize_objects ();
 		if (ACPI_FAILURE (status)) {
diff -Nru a/drivers/atm/Makefile b/drivers/atm/Makefile
--- a/drivers/atm/Makefile	2004-10-18 14:55:54 -07:00
+++ b/drivers/atm/Makefile	2004-10-18 14:55:54 -07:00
@@ -3,7 +3,7 @@
 #
 
 fore_200e-objs	:= fore200e.o
-host-progs	:= fore200e_mkfirm
+hostprogs-y	:= fore200e_mkfirm
 
 # Files generated that shall be removed upon make clean
 clean-files := atmsar11.bin atmsar11.bin1 atmsar11.bin2 pca200e.bin \
diff -Nru a/drivers/atm/ambassador.c b/drivers/atm/ambassador.c
--- a/drivers/atm/ambassador.c	2004-10-18 14:55:55 -07:00
+++ b/drivers/atm/ambassador.c	2004-10-18 14:55:55 -07:00
@@ -2291,11 +2291,10 @@
 
 	// read resources from PCI configuration space
 	u8 irq = pci_dev->irq;
-	u32 * membase = bus_to_virt (pci_resource_start (pci_dev, 0));
-	u32 iobase = pci_resource_start (pci_dev, 1);
 
 	PRINTD (DBG_INFO, "found Madge ATM adapter (amb) at"
-		" IO %x, IRQ %u, MEM %p", iobase, irq, membase);
+		" IO %x, IRQ %u, MEM %p", pci_resource_start(pci_dev, 1),
+		irq, bus_to_virt(pci_resource_start(pci_dev, 0)));
 
 	// check IO region
 	err = pci_request_region(pci_dev, 1, DEV_LABEL);
diff -Nru a/drivers/atm/eni.c b/drivers/atm/eni.c
--- a/drivers/atm/eni.c	2004-10-18 14:56:18 -07:00
+++ b/drivers/atm/eni.c	2004-10-18 14:56:18 -07:00
@@ -173,7 +173,7 @@
 	int i;
 
 	for (i = 0; i < eni_dev->free_len; i++)
-		printk(KERN_DEBUG "  %d: 0x%lx %d\n",i,
+		printk(KERN_DEBUG "  %d: %p %d\n",i,
 		    eni_dev->free_list[i].start,
 		    1 << eni_dev->free_list[i].order);
 }
@@ -191,19 +191,19 @@
 	printk(KERN_NOTICE "TX buffers\n");
 	for (i = 0; i < NR_CHAN; i++)
 		if (eni_dev->tx[i].send)
-			printk(KERN_NOTICE "  TX %d @ 0x%lx: %ld\n",i,
+			printk(KERN_NOTICE "  TX %d @ %p: %ld\n",i,
 			    eni_dev->tx[i].send,eni_dev->tx[i].words*4);
 	printk(KERN_NOTICE "RX buffers\n");
 	for (i = 0; i < 1024; i++)
 		if (eni_dev->rx_map[i] && ENI_VCC(eni_dev->rx_map[i])->rx)
-			printk(KERN_NOTICE "  RX %d @ 0x%lx: %ld\n",i,
+			printk(KERN_NOTICE "  RX %d @ %p: %ld\n",i,
 			    ENI_VCC(eni_dev->rx_map[i])->recv,
 			    ENI_VCC(eni_dev->rx_map[i])->words*4);
 	printk(KERN_NOTICE "----\n");
 }
 
 
-static void eni_put_free(struct eni_dev *eni_dev,unsigned long start,
+static void eni_put_free(struct eni_dev *eni_dev, void __iomem *start,
     unsigned long size)
 {
 	struct eni_free *list;
@@ -215,17 +215,17 @@
 	len = eni_dev->free_len;
 	while (size) {
 		if (len >= eni_dev->free_list_size) {
-			printk(KERN_CRIT "eni_put_free overflow (0x%lx,%ld)\n",
+			printk(KERN_CRIT "eni_put_free overflow (%p,%ld)\n",
 			    start,size);
 			break;
 		}
-		for (order = 0; !((start | size) & (1 << order)); order++);
+		for (order = 0; !(((unsigned long)start | size) & (1 << order)); order++);
 		if (MID_MIN_BUF_SIZE > (1 << order)) {
 			printk(KERN_CRIT "eni_put_free: order %d too small\n",
 			    order);
 			break;
 		}
-		list[len].start = start;
+		list[len].start = (void __iomem *) start;
 		list[len].order = order;
 		len++;
 		start += 1 << order;
@@ -236,10 +236,10 @@
 }
 
 
-static unsigned long eni_alloc_mem(struct eni_dev *eni_dev,unsigned long *size)
+static void __iomem *eni_alloc_mem(struct eni_dev *eni_dev, unsigned long *size)
 {
 	struct eni_free *list;
-	unsigned long start;
+	void __iomem *start;
 	int len,i,order,best_order,index;
 
 	list = eni_dev->free_list;
@@ -273,7 +273,7 @@
 }
 
 
-static void eni_free_mem(struct eni_dev *eni_dev,unsigned long start,
+static void eni_free_mem(struct eni_dev *eni_dev, void __iomem *start,
     unsigned long size)
 {
 	struct eni_free *list;
@@ -283,20 +283,20 @@
 	list = eni_dev->free_list;
 	len = eni_dev->free_len;
 	for (order = -1; size; order++) size >>= 1;
-	DPRINTK("eni_free_mem: 0x%lx+0x%lx (order %d)\n",start,size,order);
+	DPRINTK("eni_free_mem: %p+0x%lx (order %d)\n",start,size,order);
 	for (i = 0; i < len; i++)
-		if (list[i].start == (start^(1 << order)) &&
+		if (((unsigned long) list[i].start) == ((unsigned long)start^(1 << order)) &&
 		    list[i].order == order) {
 			DPRINTK("match[%d]: 0x%lx/0x%lx(0x%x), %d/%d\n",i,
 			    list[i].start,start,1 << order,list[i].order,order);
 			list[i] = list[--len];
-			start &= ~(unsigned long) (1 << order);
+			start = (void __iomem *) ((unsigned long) start & ~(unsigned long) (1 << order));
 			order++;
 			i = -1;
 			continue;
 		}
 	if (len >= eni_dev->free_list_size) {
-		printk(KERN_ALERT "eni_free_mem overflow (0x%lx,%d)\n",start,
+		printk(KERN_ALERT "eni_free_mem overflow (%p,%d)\n",start,
 		    order);
 		return;
 	}
@@ -333,7 +333,7 @@
 	printk(KERN_ALERT "  host descr 0x%lx, rx pos 0x%lx, descr value "
 	    "0x%x\n",eni_vcc->descr,eni_vcc->rx_pos,
 	    (unsigned) readl(eni_vcc->recv+eni_vcc->descr*4));
-	printk(KERN_ALERT "  last 0x%p, servicing %d\n",eni_vcc->last,
+	printk(KERN_ALERT "  last %p, servicing %d\n",eni_vcc->last,
 	    eni_vcc->servicing);
 	EVENT("---dump ends here---\n",0,0);
 	printk(KERN_NOTICE "---recent events---\n");
@@ -617,7 +617,8 @@
 
 static inline int rx_vcc(struct atm_vcc *vcc)
 {
-	unsigned long vci_dsc,tmp;
+	void __iomem *vci_dsc;
+	unsigned long tmp;
 	struct eni_vcc *eni_vcc;
 
 	eni_vcc = ENI_VCC(vcc);
@@ -728,7 +729,7 @@
 	struct eni_vcc *eni_vcc;
 	struct atm_vcc *vcc;
 	struct sk_buff *skb;
-	unsigned long vci_dsc;
+	void __iomem *vci_dsc;
 	int first;
 
 	eni_dev = ENI_DEV(dev);
@@ -808,7 +809,7 @@
 
 static int open_rx_second(struct atm_vcc *vcc)
 {
-	unsigned long here;
+	void __iomem *here;
 	struct eni_dev *eni_dev;
 	struct eni_vcc *eni_vcc;
 	unsigned long size;
@@ -840,7 +841,7 @@
 static void close_rx(struct atm_vcc *vcc)
 {
 	DECLARE_WAITQUEUE(wait,current);
-	unsigned long here;
+	void __iomem *here;
 	struct eni_dev *eni_dev;
 	struct eni_vcc *eni_vcc;
 
@@ -1289,7 +1290,8 @@
 	struct eni_dev *eni_dev = ENI_DEV(vcc->dev);
 	struct eni_vcc *eni_vcc = ENI_VCC(vcc);
 	struct eni_tx *tx;
-	unsigned long size,mem;
+	unsigned long size;
+	void __iomem *mem;
 	int rate,ubr,unlimited,new_tx;
 	int pre,res,order;
 	int error;
@@ -1687,9 +1689,9 @@
 #undef GET_SEPROM
 
 
-static int __devinit get_esi_fpga(struct atm_dev *dev,unsigned long base)
+static int __devinit get_esi_fpga(struct atm_dev *dev, void __iomem *base)
 {
-	unsigned long mac_base;
+	void __iomem *mac_base;
 	int i;
 
 	mac_base = base+EPROM_SIZE-sizeof(struct midway_eprom);
@@ -1703,7 +1705,8 @@
 	struct midway_eprom *eprom;
 	struct eni_dev *eni_dev;
 	struct pci_dev *pci_dev;
-	unsigned long real_base,base;
+	unsigned long real_base;
+	void __iomem *base;
 	unsigned char revision;
 	int error,i,last;
 
@@ -1730,13 +1733,13 @@
 	}
 	printk(KERN_NOTICE DEV_LABEL "(itf %d): rev.%d,base=0x%lx,irq=%d,",
 	    dev->number,revision,real_base,eni_dev->irq);
-	if (!(base = (unsigned long) ioremap_nocache(real_base,MAP_MAX_SIZE))) {
+	if (!(base = ioremap_nocache(real_base,MAP_MAX_SIZE))) {
 		printk("\n");
 		printk(KERN_ERR DEV_LABEL "(itf %d): can't set up page "
 		    "mapping\n",dev->number);
 		return error;
 	}
-	eni_dev->base_diff = real_base-base;
+	eni_dev->base_diff = real_base - (unsigned long) base;
 	/* id may not be present in ASIC Tonga boards - check this @@@ */
 	if (!eni_dev->asic) {
 		eprom = (struct midway_eprom *) (base+EPROM_SIZE-sizeof(struct
@@ -1790,7 +1793,9 @@
 static int __devinit eni_start(struct atm_dev *dev)
 {
 	struct eni_dev *eni_dev;
-	unsigned long buf,buffer_mem;
+	
+	void __iomem *buf;
+	unsigned long buffer_mem;
 	int error;
 
 	DPRINTK(">eni_start\n");
@@ -1828,7 +1833,7 @@
 	tasklet_init(&eni_dev->task,eni_tasklet,(unsigned long) dev);
 	eni_dev->events = 0;
 	/* initialize memory management */
-	buffer_mem = eni_dev->mem-(buf-eni_dev->ram);
+	buffer_mem = eni_dev->mem - (buf - eni_dev->ram);
 	eni_dev->free_list_size = buffer_mem/MID_MIN_BUF_SIZE/2;
 	eni_dev->free_list = (struct eni_free *) kmalloc(
 	    sizeof(struct eni_free)*(eni_dev->free_list_size+1),GFP_KERNEL);
@@ -1955,7 +1960,7 @@
 	 */
 	tasklet_disable(&eni_dev->task);
 	skb_queue_walk(&eni_dev->tx_queue, skb) {
-		unsigned long dsc;
+		void __iomem *dsc;
 
 		if (ATM_SKB(skb)->vcc != vcc) continue;
 		dsc = tx->send+ENI_PRV_POS(skb)*4;
@@ -2136,9 +2141,9 @@
 
 		if (!tx->send) continue;
 		if (!--left) {
-			return sprintf(page,"tx[%d]:    0x%06lx-0x%06lx "
+			return sprintf(page,"tx[%d]:    0x%ld-0x%ld "
 			    "(%6ld bytes), rsv %d cps, shp %d cps%s\n",i,
-			    tx->send-eni_dev->ram,
+			    (unsigned long) (tx->send - eni_dev->ram),
 			    tx->send-eni_dev->ram+tx->words*4-1,tx->words*4,
 			    tx->reserved,tx->shaping,
 			    tx == eni_dev->ubr ? " (UBR)" : "");
@@ -2162,9 +2167,9 @@
 			if (--left) continue;
 			length = sprintf(page,"vcc %4d: ",vcc->vci);
 			if (eni_vcc->rx) {
-				length += sprintf(page+length,"0x%06lx-0x%06lx "
+				length += sprintf(page+length,"0x%ld-0x%ld "
 				    "(%6ld bytes)",
-				    eni_vcc->recv-eni_dev->ram,
+				    (unsigned long) (eni_vcc->recv - eni_dev->ram),
 				    eni_vcc->recv-eni_dev->ram+eni_vcc->words*4-1,
 				    eni_vcc->words*4);
 				if (eni_vcc->tx) length += sprintf(page+length,", ");
@@ -2183,8 +2188,8 @@
 		unsigned long offset;
 
 		if (--left) continue;
-		offset = eni_dev->ram+eni_dev->base_diff;
-		return sprintf(page,"free      0x%06lx-0x%06lx (%6d bytes)\n",
+		offset = (unsigned long) eni_dev->ram+eni_dev->base_diff;
+		return sprintf(page,"free      %p-%p (%6d bytes)\n",
 		    fe->start-offset,fe->start-offset+(1 << fe->order)-1,
 		    1 << fe->order);
 	}
diff -Nru a/drivers/atm/eni.h b/drivers/atm/eni.h
--- a/drivers/atm/eni.h	2004-10-18 14:56:33 -07:00
+++ b/drivers/atm/eni.h	2004-10-18 14:56:33 -07:00
@@ -33,12 +33,12 @@
 
 
 struct eni_free {
-	unsigned long start;		/* counting in bytes */
+	void __iomem *start;		/* counting in bytes */
 	int order;
 };
 
 struct eni_tx {
-	unsigned long send;		/* base, 0 if unused */
+	void __iomem *send;		/* base, 0 if unused */
 	int prescaler;			/* shaping prescaler */
 	int resolution;			/* shaping divider */
 	unsigned long tx_pos;		/* current TX write position */
@@ -51,7 +51,7 @@
 
 struct eni_vcc {
 	int (*rx)(struct atm_vcc *vcc);	/* RX function, NULL if none */
-	unsigned long recv;		/* receive buffer */
+	void __iomem *recv;		/* receive buffer */
 	unsigned long words;		/* its size in words */
 	unsigned long descr;		/* next descriptor (RX) */
 	unsigned long rx_pos;		/* current RX descriptor pos */
@@ -72,13 +72,13 @@
 	u32 events;			/* pending events */
 	/*-------------------------------- base pointers into Midway address
 					   space */
-	unsigned long phy;		/* PHY interface chip registers */
-	unsigned long reg;		/* register base */
-	unsigned long ram;		/* RAM base */
-	unsigned long vci;		/* VCI table */
-	unsigned long rx_dma;		/* RX DMA queue */
-	unsigned long tx_dma;		/* TX DMA queue */
-	unsigned long service;		/* service list */
+	void __iomem *phy;		/* PHY interface chip registers */
+	void __iomem *reg;		/* register base */
+	void __iomem *ram;		/* RAM base */
+	void __iomem *vci;		/* VCI table */
+	void __iomem *rx_dma;		/* RX DMA queue */
+	void __iomem *tx_dma;		/* TX DMA queue */
+	void __iomem *service;		/* service list */
 	/*-------------------------------- TX part */
 	struct eni_tx tx[NR_CHAN];	/* TX channels */
 	struct eni_tx *ubr;		/* UBR channel */
diff -Nru a/drivers/atm/firestream.c b/drivers/atm/firestream.c
--- a/drivers/atm/firestream.c	2004-10-18 14:55:55 -07:00
+++ b/drivers/atm/firestream.c	2004-10-18 14:55:55 -07:00
@@ -1667,7 +1667,7 @@
 
 	dev->hw_base = pci_resource_start(pci_dev, 0);
 
-	dev->base = (ulong) ioremap(dev->hw_base, 0x1000);
+	dev->base = ioremap(dev->hw_base, 0x1000);
 
 	reset_chip (dev);
   
@@ -1704,8 +1704,7 @@
 		}
 
 		/* Try again after 10ms. */
-		set_current_state(TASK_UNINTERRUPTIBLE);
-		schedule_timeout ((HZ+99)/100);
+		msleep(10);
 	}
 
 	if (!to) {
diff -Nru a/drivers/atm/firestream.h b/drivers/atm/firestream.h
--- a/drivers/atm/firestream.h	2004-10-18 14:56:49 -07:00
+++ b/drivers/atm/firestream.h	2004-10-18 14:56:49 -07:00
@@ -477,7 +477,7 @@
 	struct timer_list timer;
 
 	unsigned long hw_base;		/* mem base address */
-	unsigned long base;             /* Mapping of base address */
+	void __iomem *base;             /* Mapping of base address */
 	int channo;
 	unsigned long channel_mask;
 
diff -Nru a/drivers/atm/fore200e.h b/drivers/atm/fore200e.h
--- a/drivers/atm/fore200e.h	2004-10-18 14:56:32 -07:00
+++ b/drivers/atm/fore200e.h	2004-10-18 14:56:32 -07:00
@@ -565,7 +565,7 @@
 typedef struct chunk {
     void* alloc_addr;    /* base address of allocated chunk */
     void* align_addr;    /* base address of aligned chunk   */
-    u32   dma_addr;      /* DMA address of aligned chunk    */
+    dma_addr_t dma_addr; /* DMA address of aligned chunk    */
     int   direction;     /* direction of DMA mapping        */
     u32   alloc_size;    /* length of allocated chunk       */
     u32   align_size;    /* length of aligned chunk         */
diff -Nru a/drivers/atm/he.c b/drivers/atm/he.c
--- a/drivers/atm/he.c	2004-10-18 14:56:13 -07:00
+++ b/drivers/atm/he.c	2004-10-18 14:56:13 -07:00
@@ -1007,6 +1007,7 @@
 {
 	struct he_dev *he_dev;
 	struct pci_dev *pci_dev;
+	unsigned long membase;
 
 	u16 command;
 	u32 gen_cntl_0, host_cntl, lb_swap;
@@ -1019,8 +1020,8 @@
 	he_dev = HE_DEV(dev);
 	pci_dev = he_dev->pci_dev;
 
-	he_dev->membase = pci_dev->resource[0].start;
-	HPRINTK("membase = 0x%lx  irq = %d.\n", he_dev->membase, pci_dev->irq);
+	membase = pci_resource_start(pci_dev, 0);
+	HPRINTK("membase = 0x%lx  irq = %d.\n", membase, pci_dev->irq);
 
 	/*
 	 * pci bus controller initialization 
@@ -1080,7 +1081,7 @@
 			hprintk("can't set latency timer to %d\n", timer);
 	}
 
-	if (!(he_dev->membase = (unsigned long) ioremap(he_dev->membase, HE_REGMAP_SIZE))) {
+	if (!(he_dev->membase = ioremap(membase, HE_REGMAP_SIZE))) {
 		hprintk("can't set up page mapping\n");
 		return -EINVAL;
 	}
@@ -1962,7 +1963,7 @@
 	struct he_tpd *tpd;
 	int slot, updated = 0;
 #ifdef USE_TPD_POOL
-	struct list_head *p;
+	struct he_tpd *__tpd;
 #endif
 
 	/* 2.1.6 transmit buffer return queue */
@@ -1977,8 +1978,7 @@
 			TBRQ_MULTIPLE(he_dev->tbrq_head) ? " MULTIPLE" : "");
 #ifdef USE_TPD_POOL
 		tpd = NULL;
-		list_for_each(p, &he_dev->outstanding_tpds) {
-			struct he_tpd *__tpd = list_entry(p, struct he_tpd, entry);
+		list_for_each_entry(__tpd, &he_dev->outstanding_tpds, entry) {
 			if (TPD_ADDR(__tpd->status) == TBRQ_TPD(he_dev->tbrq_head)) {
 				tpd = __tpd;
 				list_del(&__tpd->entry);
@@ -2595,9 +2595,8 @@
 
 		while (((tx_inuse = atomic_read(&vcc->sk->sk_wmem_alloc)) > 0) &&
 		       (retry < MAX_RETRY)) {
-			set_current_state(TASK_UNINTERRUPTIBLE);
-			(void) schedule_timeout(sleep);
-			if (sleep < HZ)
+			msleep(sleep);
+			if (sleep < 250)
 				sleep = sleep * 2;
 
 			++retry;
diff -Nru a/drivers/atm/he.h b/drivers/atm/he.h
--- a/drivers/atm/he.h	2004-10-18 14:56:31 -07:00
+++ b/drivers/atm/he.h	2004-10-18 14:56:31 -07:00
@@ -265,7 +265,7 @@
 struct he_dev {
 	unsigned int number;
 	unsigned int irq;
-	unsigned long membase;
+	void __iomem *membase;
 
 	char prod_id[30];
 	char mac_addr[6];
diff -Nru a/drivers/atm/idt77252.c b/drivers/atm/idt77252.c
--- a/drivers/atm/idt77252.c	2004-10-18 14:56:29 -07:00
+++ b/drivers/atm/idt77252.c	2004-10-18 14:56:29 -07:00
@@ -2516,7 +2516,7 @@
 	struct vc_map *vc = vcc->dev_data;
 	unsigned long flags;
 	unsigned long addr;
-	int timeout;
+	unsigned long timeout;
 
 	down(&card->mutex);
 
@@ -2566,9 +2566,9 @@
 		}
 		spin_unlock_irqrestore(&vc->lock, flags);
 
-		timeout = 5 * HZ;
+		timeout = 5 * 1000;
 		while (atomic_read(&vc->scq->used) > 0) {
-			timeout = schedule_timeout(timeout);
+			timeout = msleep_interruptible(timeout);
 			if (!timeout)
 				break;
 		}
@@ -3164,7 +3164,7 @@
 
 	for (i = 0; i < 4; i++) {
 		if (card->fbq[i])
-			iounmap((void *) card->fbq[i]);
+			iounmap(card->fbq[i]);
 	}
 
 	if (card->membase)
@@ -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));
 
@@ -3715,26 +3722,24 @@
 	card->tst_timer.function = tst_timer;
 
 	/* Do the I/O remapping... */
-	card->membase = (unsigned long) ioremap(membase, 1024);
+	card->membase = 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,22 +3748,19 @@
 	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 */
 
 	card->sramsize = probe_sram(card);
 
 	for (i = 0; i < 4; i++) {
-		card->fbq[i] = (unsigned long)
-			    ioremap(srambase | 0x200000 | (i << 18), 4);
+		card->fbq[i] = 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 +3771,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 +3784,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 +3793,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 +3862,7 @@
 		if (dev->phy->stop)
 			dev->phy->stop(dev);
 		deinit_card(card);
+		pci_disable_device(card->pcidev);
 		kfree(card);
 	}
 
diff -Nru a/drivers/atm/idt77252.h b/drivers/atm/idt77252.h
--- a/drivers/atm/idt77252.h	2004-10-18 14:56:49 -07:00
+++ b/drivers/atm/idt77252.h	2004-10-18 14:56:49 -07:00
@@ -355,9 +355,9 @@
 	struct pci_dev		*pcidev;	/* PCI handle (desriptor) */
 	struct atm_dev		*atmdev;	/* ATM device desriptor */
 
-	unsigned long		membase;	/* SAR's memory base address */
+	void __iomem		*membase;	/* SAR's memory base address */
 	unsigned long		srambase;	/* SAR's sram  base address */
-	unsigned long		fbq[4];		/* FBQ fill addresses */
+	void __iomem		*fbq[4];	/* FBQ fill addresses */
 
 	struct semaphore	mutex;
 	spinlock_t		cmd_lock;	/* for r/w utility/sram */
diff -Nru a/drivers/atm/lanai.c b/drivers/atm/lanai.c
--- a/drivers/atm/lanai.c	2004-10-18 14:56:27 -07:00
+++ b/drivers/atm/lanai.c	2004-10-18 14:56:27 -07:00
@@ -191,7 +191,7 @@
 #define LANAI_EEPROM_SIZE	(128)
 
 typedef int vci_t;
-typedef unsigned long bus_addr_t;
+typedef void __iomem *bus_addr_t;
 
 /* DMA buffer in host memory for TX, RX, or service list. */
 struct lanai_buffer {
@@ -471,7 +471,7 @@
 static inline bus_addr_t reg_addr(const struct lanai_dev *lanai,
 	enum lanai_register reg)
 {
-	return lanai->base + (bus_addr_t) reg;
+	return lanai->base + reg;
 }
 
 static inline u32 reg_read(const struct lanai_dev *lanai,
@@ -651,7 +651,7 @@
 {
 	u32 val;
 	APRINTK(lvcc->vbase != 0, "cardvcc_read: unbound vcc!\n");
-	val= readl(lvcc->vbase + (bus_addr_t) offset);
+	val= readl(lvcc->vbase + offset);
 	RWDEBUG("VR vci=%04d 0x%02X = 0x%08X\n",
 	    lvcc->vci, (int) offset, val);
 	return val;
@@ -666,7 +666,7 @@
 	    (unsigned int) val, lvcc->vci, (unsigned int) offset);
 	RWDEBUG("VW vci=%04d 0x%02X > 0x%08X\n",
 	    lvcc->vci, (unsigned int) offset, (unsigned int) val);
-	writel(val, lvcc->vbase + (bus_addr_t) offset);
+	writel(val, lvcc->vbase + offset);
 }
 
 /* -------------------- COMPUTE SIZE OF AN AAL5 PDU: */
@@ -813,7 +813,7 @@
 			DPRINTK("read, write = %d, %d\n", read, write);
 			break;
 		}
-		schedule_timeout(HZ / 25);
+		msleep(40);
 	}
 	/* 15.2.2 - clear out all tx registers */
 	cardvcc_write(lvcc, 0, vcc_txreadptr);
@@ -2177,7 +2177,7 @@
 	/* 3.2: PCI initialization */
 	if ((result = lanai_pci_start(lanai)) != 0)
 		goto error;
-	raw_base = (bus_addr_t) lanai->pci->resource[0].start;
+	raw_base = lanai->pci->resource[0].start;
 	lanai->base = (bus_addr_t) ioremap(raw_base, LANAI_MAPPING_SIZE);
 	if (lanai->base == 0) {
 		printk(KERN_ERR DEV_LABEL ": couldn't remap I/O space\n");
diff -Nru a/drivers/atm/nicstar.c b/drivers/atm/nicstar.c
--- a/drivers/atm/nicstar.c	2004-10-18 14:56:17 -07:00
+++ b/drivers/atm/nicstar.c	2004-10-18 14:56:17 -07:00
@@ -467,6 +467,7 @@
    u32 u32d[4];
    u32 ns_cfg_rctsize;
    int bcount;
+   unsigned long membase;
 
    error = 0;
 
@@ -494,8 +495,8 @@
    card->index = i;
    card->atmdev = NULL;
    card->pcidev = pcidev;
-   card->membase = pci_resource_start(pcidev, 1);
-   card->membase = (unsigned long) ioremap(card->membase, NS_IOREMAP_SIZE);
+   membase = pci_resource_start(pcidev, 1);
+   card->membase = ioremap(membase, NS_IOREMAP_SIZE);
    if (card->membase == 0)
    {
       printk("nicstar%d: can't ioremap() membase.\n",i);
diff -Nru a/drivers/atm/nicstar.h b/drivers/atm/nicstar.h
--- a/drivers/atm/nicstar.h	2004-10-18 14:56:27 -07:00
+++ b/drivers/atm/nicstar.h	2004-10-18 14:56:27 -07:00
@@ -763,7 +763,7 @@
 {
    int index;				/* Card ID to the device driver */
    int sram_size;			/* In k x 32bit words. 32 or 128 */
-   unsigned long membase;			/* Card's memory base address */
+   void __iomem *membase;		/* Card's memory base address */
    unsigned long max_pcr;
    int rct_size;			/* Number of entries */
    int vpibits;
diff -Nru a/drivers/atm/nicstarmac.c b/drivers/atm/nicstarmac.c
--- a/drivers/atm/nicstarmac.c	2004-10-18 14:57:04 -07:00
+++ b/drivers/atm/nicstarmac.c	2004-10-18 14:57:04 -07:00
@@ -162,7 +162,7 @@
  */
  
 static u_int8_t 
-read_eprom_byte(u_int32_t base, u_int8_t offset)
+read_eprom_byte(virt_addr_t base, u_int8_t offset)
 {
    u_int32_t val = 0;
    int i,j=0;
diff -Nru a/drivers/atm/nicstarmac.h b/drivers/atm/nicstarmac.h
--- a/drivers/atm/nicstarmac.h	2004-10-18 14:55:55 -07:00
+++ b/drivers/atm/nicstarmac.h	2004-10-18 14:55:55 -07:00
@@ -7,7 +7,7 @@
  ******************************************************************************/
 
 
-typedef unsigned int virt_addr_t;
+typedef void __iomem *virt_addr_t;
 
 u_int32_t nicstar_read_eprom_status( virt_addr_t base );
 void nicstar_init_eprom( virt_addr_t base );
diff -Nru a/drivers/base/class.c b/drivers/base/class.c
--- a/drivers/base/class.c	2004-10-18 14:57:04 -07:00
+++ b/drivers/base/class.c	2004-10-18 14:57:04 -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/firmware_class.c b/drivers/base/firmware_class.c
--- a/drivers/base/firmware_class.c	2004-10-18 14:55:53 -07:00
+++ b/drivers/base/firmware_class.c	2004-10-18 14:55:53 -07:00
@@ -12,7 +12,7 @@
 #include <linux/init.h>
 #include <linux/timer.h>
 #include <linux/vmalloc.h>
-#include <asm/hardirq.h>
+#include <linux/interrupt.h>
 #include <linux/bitops.h>
 #include <asm/semaphore.h>
 
@@ -235,6 +235,8 @@
 	struct firmware *fw;
 	ssize_t retval;
 
+	if (!capable(CAP_SYS_RAWIO))
+		return -EPERM;
 	down(&fw_lock);
 	fw = fw_priv->fw;
 	if (test_bit(FW_STATUS_DONE, &fw_priv->status)) {
diff -Nru a/drivers/base/node.c b/drivers/base/node.c
--- a/drivers/base/node.c	2004-10-18 14:56:13 -07:00
+++ b/drivers/base/node.c	2004-10-18 14:56:13 -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/DAC960.c b/drivers/block/DAC960.c
--- a/drivers/block/DAC960.c	2004-10-18 14:56:49 -07:00
+++ b/drivers/block/DAC960.c	2004-10-18 14:56:49 -07:00
@@ -288,12 +288,17 @@
 		Controller->PCIDevice,
 	DAC960_V2_ScatterGatherLimit * sizeof(DAC960_V2_ScatterGatherSegment_T),
 	sizeof(DAC960_V2_ScatterGatherSegment_T), 0);
+      if (ScatterGatherPool == NULL)
+	    return DAC960_Failure(Controller,
+			"AUXILIARY STRUCTURE CREATION (SG)");
       RequestSensePool = pci_pool_create("DAC960_V2_RequestSense",
 		Controller->PCIDevice, sizeof(DAC960_SCSI_RequestSense_T),
 		sizeof(int), 0);
-      if (ScatterGatherPool == NULL || RequestSensePool == NULL)
+      if (RequestSensePool == NULL) {
+	    pci_pool_destroy(ScatterGatherPool);
 	    return DAC960_Failure(Controller,
 			"AUXILIARY STRUCTURE CREATION (SG)");
+      }
       Controller->ScatterGatherPool = ScatterGatherPool;
       Controller->V2.RequestSensePool = RequestSensePool;
     }
@@ -535,7 +540,7 @@
 static void DAC960_BA_QueueCommand(DAC960_Command_T *Command)
 {
   DAC960_Controller_T *Controller = Command->Controller;
-  void *ControllerBaseAddress = Controller->BaseAddress;
+  void __iomem *ControllerBaseAddress = Controller->BaseAddress;
   DAC960_V2_CommandMailbox_T *CommandMailbox = &Command->V2.CommandMailbox;
   DAC960_V2_CommandMailbox_T *NextCommandMailbox =
     Controller->V2.NextCommandMailbox;
@@ -560,7 +565,7 @@
 static void DAC960_LP_QueueCommand(DAC960_Command_T *Command)
 {
   DAC960_Controller_T *Controller = Command->Controller;
-  void *ControllerBaseAddress = Controller->BaseAddress;
+  void __iomem *ControllerBaseAddress = Controller->BaseAddress;
   DAC960_V2_CommandMailbox_T *CommandMailbox = &Command->V2.CommandMailbox;
   DAC960_V2_CommandMailbox_T *NextCommandMailbox =
     Controller->V2.NextCommandMailbox;
@@ -586,7 +591,7 @@
 static void DAC960_LA_QueueCommandDualMode(DAC960_Command_T *Command)
 {
   DAC960_Controller_T *Controller = Command->Controller;
-  void *ControllerBaseAddress = Controller->BaseAddress;
+  void __iomem *ControllerBaseAddress = Controller->BaseAddress;
   DAC960_V1_CommandMailbox_T *CommandMailbox = &Command->V1.CommandMailbox;
   DAC960_V1_CommandMailbox_T *NextCommandMailbox =
     Controller->V1.NextCommandMailbox;
@@ -612,7 +617,7 @@
 static void DAC960_LA_QueueCommandSingleMode(DAC960_Command_T *Command)
 {
   DAC960_Controller_T *Controller = Command->Controller;
-  void *ControllerBaseAddress = Controller->BaseAddress;
+  void __iomem *ControllerBaseAddress = Controller->BaseAddress;
   DAC960_V1_CommandMailbox_T *CommandMailbox = &Command->V1.CommandMailbox;
   DAC960_V1_CommandMailbox_T *NextCommandMailbox =
     Controller->V1.NextCommandMailbox;
@@ -638,7 +643,7 @@
 static void DAC960_PG_QueueCommandDualMode(DAC960_Command_T *Command)
 {
   DAC960_Controller_T *Controller = Command->Controller;
-  void *ControllerBaseAddress = Controller->BaseAddress;
+  void __iomem *ControllerBaseAddress = Controller->BaseAddress;
   DAC960_V1_CommandMailbox_T *CommandMailbox = &Command->V1.CommandMailbox;
   DAC960_V1_CommandMailbox_T *NextCommandMailbox =
     Controller->V1.NextCommandMailbox;
@@ -664,7 +669,7 @@
 static void DAC960_PG_QueueCommandSingleMode(DAC960_Command_T *Command)
 {
   DAC960_Controller_T *Controller = Command->Controller;
-  void *ControllerBaseAddress = Controller->BaseAddress;
+  void __iomem *ControllerBaseAddress = Controller->BaseAddress;
   DAC960_V1_CommandMailbox_T *CommandMailbox = &Command->V1.CommandMailbox;
   DAC960_V1_CommandMailbox_T *NextCommandMailbox =
     Controller->V1.NextCommandMailbox;
@@ -689,7 +694,7 @@
 static void DAC960_PD_QueueCommand(DAC960_Command_T *Command)
 {
   DAC960_Controller_T *Controller = Command->Controller;
-  void *ControllerBaseAddress = Controller->BaseAddress;
+  void __iomem *ControllerBaseAddress = Controller->BaseAddress;
   DAC960_V1_CommandMailbox_T *CommandMailbox = &Command->V1.CommandMailbox;
   CommandMailbox->Common.CommandIdentifier = Command->CommandIdentifier;
   while (DAC960_PD_MailboxFullP(ControllerBaseAddress))
@@ -706,7 +711,7 @@
 static void DAC960_P_QueueCommand(DAC960_Command_T *Command)
 {
   DAC960_Controller_T *Controller = Command->Controller;
-  void *ControllerBaseAddress = Controller->BaseAddress;
+  void __iomem *ControllerBaseAddress = Controller->BaseAddress;
   DAC960_V1_CommandMailbox_T *CommandMailbox = &Command->V1.CommandMailbox;
   CommandMailbox->Common.CommandIdentifier = Command->CommandIdentifier;
   switch (CommandMailbox->Common.CommandOpcode)
@@ -1127,7 +1132,7 @@
 static boolean DAC960_V1_EnableMemoryMailboxInterface(DAC960_Controller_T
 						      *Controller)
 {
-  void *ControllerBaseAddress = Controller->BaseAddress;
+  void __iomem *ControllerBaseAddress = Controller->BaseAddress;
   DAC960_HardwareType_T hw_type = Controller->HardwareType;
   struct pci_dev *PCI_Device = Controller->PCIDevice;
   struct dma_loaf *DmaPages = &Controller->DmaPages;
@@ -1333,7 +1338,7 @@
 static boolean DAC960_V2_EnableMemoryMailboxInterface(DAC960_Controller_T
 						      *Controller)
 {
-  void *ControllerBaseAddress = Controller->BaseAddress;
+  void __iomem *ControllerBaseAddress = Controller->BaseAddress;
   struct pci_dev *PCI_Device = Controller->PCIDevice;
   struct dma_loaf *DmaPages = &Controller->DmaPages;
   size_t DmaPagesSize;
@@ -2674,7 +2679,7 @@
   unsigned char DeviceFunction = PCI_Device->devfn;
   unsigned char ErrorStatus, Parameter0, Parameter1;
   unsigned int IRQ_Channel = PCI_Device->irq;
-  void *BaseAddress;
+  void __iomem *BaseAddress;
   int i;
 
   Controller = (DAC960_Controller_T *)
@@ -5196,7 +5201,7 @@
 				       struct pt_regs *InterruptRegisters)
 {
   DAC960_Controller_T *Controller = (DAC960_Controller_T *) DeviceIdentifier;
-  void *ControllerBaseAddress = Controller->BaseAddress;
+  void __iomem *ControllerBaseAddress = Controller->BaseAddress;
   DAC960_V2_StatusMailbox_T *NextStatusMailbox;
   unsigned long flags;
 
@@ -5239,7 +5244,7 @@
 				       struct pt_regs *InterruptRegisters)
 {
   DAC960_Controller_T *Controller = (DAC960_Controller_T *) DeviceIdentifier;
-  void *ControllerBaseAddress = Controller->BaseAddress;
+  void __iomem *ControllerBaseAddress = Controller->BaseAddress;
   DAC960_V2_StatusMailbox_T *NextStatusMailbox;
   unsigned long flags;
 
@@ -5282,7 +5287,7 @@
 				       struct pt_regs *InterruptRegisters)
 {
   DAC960_Controller_T *Controller = (DAC960_Controller_T *) DeviceIdentifier;
-  void *ControllerBaseAddress = Controller->BaseAddress;
+  void __iomem *ControllerBaseAddress = Controller->BaseAddress;
   DAC960_V1_StatusMailbox_T *NextStatusMailbox;
   unsigned long flags;
 
@@ -5321,7 +5326,7 @@
 				       struct pt_regs *InterruptRegisters)
 {
   DAC960_Controller_T *Controller = (DAC960_Controller_T *) DeviceIdentifier;
-  void *ControllerBaseAddress = Controller->BaseAddress;
+  void __iomem *ControllerBaseAddress = Controller->BaseAddress;
   DAC960_V1_StatusMailbox_T *NextStatusMailbox;
   unsigned long flags;
 
@@ -5360,7 +5365,7 @@
 				       struct pt_regs *InterruptRegisters)
 {
   DAC960_Controller_T *Controller = (DAC960_Controller_T *) DeviceIdentifier;
-  void *ControllerBaseAddress = Controller->BaseAddress;
+  void __iomem *ControllerBaseAddress = Controller->BaseAddress;
   unsigned long flags;
 
   spin_lock_irqsave(&Controller->queue_lock, flags);
@@ -5399,7 +5404,7 @@
 				      struct pt_regs *InterruptRegisters)
 {
   DAC960_Controller_T *Controller = (DAC960_Controller_T *) DeviceIdentifier;
-  void *ControllerBaseAddress = Controller->BaseAddress;
+  void __iomem *ControllerBaseAddress = Controller->BaseAddress;
   unsigned long flags;
 
   spin_lock_irqsave(&Controller->queue_lock, flags);
diff -Nru a/drivers/block/DAC960.h b/drivers/block/DAC960.h
--- a/drivers/block/DAC960.h	2004-10-18 14:56:49 -07:00
+++ b/drivers/block/DAC960.h	2004-10-18 14:56:49 -07:00
@@ -2282,8 +2282,8 @@
 
 typedef struct DAC960_Controller
 {
-  void *BaseAddress;
-  void *MemoryMappedAddress;
+  void __iomem *BaseAddress;
+  void __iomem *MemoryMappedAddress;
   DAC960_FirmwareType_T FirmwareType;
   DAC960_HardwareType_T HardwareType;
   DAC960_IO_Address_T IO_Address;
@@ -2527,7 +2527,7 @@
  * dma_addr_t.
  */
 static inline
-void dma_addr_writeql(dma_addr_t addr, void *write_address)
+void dma_addr_writeql(dma_addr_t addr, void __iomem *write_address)
 {
 	union {
 		u64 wq;
@@ -2643,7 +2643,7 @@
 */
 
 static inline
-void DAC960_BA_HardwareMailboxNewCommand(void *ControllerBaseAddress)
+void DAC960_BA_HardwareMailboxNewCommand(void __iomem *ControllerBaseAddress)
 {
   DAC960_BA_InboundDoorBellRegister_T InboundDoorBellRegister;
   InboundDoorBellRegister.All = 0;
@@ -2653,7 +2653,7 @@
 }
 
 static inline
-void DAC960_BA_AcknowledgeHardwareMailboxStatus(void *ControllerBaseAddress)
+void DAC960_BA_AcknowledgeHardwareMailboxStatus(void __iomem *ControllerBaseAddress)
 {
   DAC960_BA_InboundDoorBellRegister_T InboundDoorBellRegister;
   InboundDoorBellRegister.All = 0;
@@ -2663,7 +2663,7 @@
 }
 
 static inline
-void DAC960_BA_GenerateInterrupt(void *ControllerBaseAddress)
+void DAC960_BA_GenerateInterrupt(void __iomem *ControllerBaseAddress)
 {
   DAC960_BA_InboundDoorBellRegister_T InboundDoorBellRegister;
   InboundDoorBellRegister.All = 0;
@@ -2673,7 +2673,7 @@
 }
 
 static inline
-void DAC960_BA_ControllerReset(void *ControllerBaseAddress)
+void DAC960_BA_ControllerReset(void __iomem *ControllerBaseAddress)
 {
   DAC960_BA_InboundDoorBellRegister_T InboundDoorBellRegister;
   InboundDoorBellRegister.All = 0;
@@ -2683,7 +2683,7 @@
 }
 
 static inline
-void DAC960_BA_MemoryMailboxNewCommand(void *ControllerBaseAddress)
+void DAC960_BA_MemoryMailboxNewCommand(void __iomem *ControllerBaseAddress)
 {
   DAC960_BA_InboundDoorBellRegister_T InboundDoorBellRegister;
   InboundDoorBellRegister.All = 0;
@@ -2693,7 +2693,7 @@
 }
 
 static inline
-boolean DAC960_BA_HardwareMailboxFullP(void *ControllerBaseAddress)
+boolean DAC960_BA_HardwareMailboxFullP(void __iomem *ControllerBaseAddress)
 {
   DAC960_BA_InboundDoorBellRegister_T InboundDoorBellRegister;
   InboundDoorBellRegister.All =
@@ -2702,7 +2702,7 @@
 }
 
 static inline
-boolean DAC960_BA_InitializationInProgressP(void *ControllerBaseAddress)
+boolean DAC960_BA_InitializationInProgressP(void __iomem *ControllerBaseAddress)
 {
   DAC960_BA_InboundDoorBellRegister_T InboundDoorBellRegister;
   InboundDoorBellRegister.All =
@@ -2711,7 +2711,7 @@
 }
 
 static inline
-void DAC960_BA_AcknowledgeHardwareMailboxInterrupt(void *ControllerBaseAddress)
+void DAC960_BA_AcknowledgeHardwareMailboxInterrupt(void __iomem *ControllerBaseAddress)
 {
   DAC960_BA_OutboundDoorBellRegister_T OutboundDoorBellRegister;
   OutboundDoorBellRegister.All = 0;
@@ -2721,7 +2721,7 @@
 }
 
 static inline
-void DAC960_BA_AcknowledgeMemoryMailboxInterrupt(void *ControllerBaseAddress)
+void DAC960_BA_AcknowledgeMemoryMailboxInterrupt(void __iomem *ControllerBaseAddress)
 {
   DAC960_BA_OutboundDoorBellRegister_T OutboundDoorBellRegister;
   OutboundDoorBellRegister.All = 0;
@@ -2731,7 +2731,7 @@
 }
 
 static inline
-void DAC960_BA_AcknowledgeInterrupt(void *ControllerBaseAddress)
+void DAC960_BA_AcknowledgeInterrupt(void __iomem *ControllerBaseAddress)
 {
   DAC960_BA_OutboundDoorBellRegister_T OutboundDoorBellRegister;
   OutboundDoorBellRegister.All = 0;
@@ -2742,7 +2742,7 @@
 }
 
 static inline
-boolean DAC960_BA_HardwareMailboxStatusAvailableP(void *ControllerBaseAddress)
+boolean DAC960_BA_HardwareMailboxStatusAvailableP(void __iomem *ControllerBaseAddress)
 {
   DAC960_BA_OutboundDoorBellRegister_T OutboundDoorBellRegister;
   OutboundDoorBellRegister.All =
@@ -2751,7 +2751,7 @@
 }
 
 static inline
-boolean DAC960_BA_MemoryMailboxStatusAvailableP(void *ControllerBaseAddress)
+boolean DAC960_BA_MemoryMailboxStatusAvailableP(void __iomem *ControllerBaseAddress)
 {
   DAC960_BA_OutboundDoorBellRegister_T OutboundDoorBellRegister;
   OutboundDoorBellRegister.All =
@@ -2760,7 +2760,7 @@
 }
 
 static inline
-void DAC960_BA_EnableInterrupts(void *ControllerBaseAddress)
+void DAC960_BA_EnableInterrupts(void __iomem *ControllerBaseAddress)
 {
   DAC960_BA_InterruptMaskRegister_T InterruptMaskRegister;
   InterruptMaskRegister.All = 0xFF;
@@ -2771,7 +2771,7 @@
 }
 
 static inline
-void DAC960_BA_DisableInterrupts(void *ControllerBaseAddress)
+void DAC960_BA_DisableInterrupts(void __iomem *ControllerBaseAddress)
 {
   DAC960_BA_InterruptMaskRegister_T InterruptMaskRegister;
   InterruptMaskRegister.All = 0xFF;
@@ -2782,7 +2782,7 @@
 }
 
 static inline
-boolean DAC960_BA_InterruptsEnabledP(void *ControllerBaseAddress)
+boolean DAC960_BA_InterruptsEnabledP(void __iomem *ControllerBaseAddress)
 {
   DAC960_BA_InterruptMaskRegister_T InterruptMaskRegister;
   InterruptMaskRegister.All =
@@ -2805,7 +2805,7 @@
 
 
 static inline
-void DAC960_BA_WriteHardwareMailbox(void *ControllerBaseAddress,
+void DAC960_BA_WriteHardwareMailbox(void __iomem *ControllerBaseAddress,
 				    dma_addr_t CommandMailboxDMA)
 {
 	dma_addr_writeql(CommandMailboxDMA,
@@ -2814,19 +2814,19 @@
 }
 
 static inline DAC960_V2_CommandIdentifier_T
-DAC960_BA_ReadCommandIdentifier(void *ControllerBaseAddress)
+DAC960_BA_ReadCommandIdentifier(void __iomem *ControllerBaseAddress)
 {
   return readw(ControllerBaseAddress + DAC960_BA_CommandStatusOffset);
 }
 
 static inline DAC960_V2_CommandStatus_T
-DAC960_BA_ReadCommandStatus(void *ControllerBaseAddress)
+DAC960_BA_ReadCommandStatus(void __iomem *ControllerBaseAddress)
 {
   return readw(ControllerBaseAddress + DAC960_BA_CommandStatusOffset + 2);
 }
 
 static inline boolean
-DAC960_BA_ReadErrorStatus(void *ControllerBaseAddress,
+DAC960_BA_ReadErrorStatus(void __iomem *ControllerBaseAddress,
 			  unsigned char *ErrorStatus,
 			  unsigned char *Parameter0,
 			  unsigned char *Parameter1)
@@ -2948,7 +2948,7 @@
 */
 
 static inline
-void DAC960_LP_HardwareMailboxNewCommand(void *ControllerBaseAddress)
+void DAC960_LP_HardwareMailboxNewCommand(void __iomem *ControllerBaseAddress)
 {
   DAC960_LP_InboundDoorBellRegister_T InboundDoorBellRegister;
   InboundDoorBellRegister.All = 0;
@@ -2958,7 +2958,7 @@
 }
 
 static inline
-void DAC960_LP_AcknowledgeHardwareMailboxStatus(void *ControllerBaseAddress)
+void DAC960_LP_AcknowledgeHardwareMailboxStatus(void __iomem *ControllerBaseAddress)
 {
   DAC960_LP_InboundDoorBellRegister_T InboundDoorBellRegister;
   InboundDoorBellRegister.All = 0;
@@ -2968,7 +2968,7 @@
 }
 
 static inline
-void DAC960_LP_GenerateInterrupt(void *ControllerBaseAddress)
+void DAC960_LP_GenerateInterrupt(void __iomem *ControllerBaseAddress)
 {
   DAC960_LP_InboundDoorBellRegister_T InboundDoorBellRegister;
   InboundDoorBellRegister.All = 0;
@@ -2978,7 +2978,7 @@
 }
 
 static inline
-void DAC960_LP_ControllerReset(void *ControllerBaseAddress)
+void DAC960_LP_ControllerReset(void __iomem *ControllerBaseAddress)
 {
   DAC960_LP_InboundDoorBellRegister_T InboundDoorBellRegister;
   InboundDoorBellRegister.All = 0;
@@ -2988,7 +2988,7 @@
 }
 
 static inline
-void DAC960_LP_MemoryMailboxNewCommand(void *ControllerBaseAddress)
+void DAC960_LP_MemoryMailboxNewCommand(void __iomem *ControllerBaseAddress)
 {
   DAC960_LP_InboundDoorBellRegister_T InboundDoorBellRegister;
   InboundDoorBellRegister.All = 0;
@@ -2998,7 +2998,7 @@
 }
 
 static inline
-boolean DAC960_LP_HardwareMailboxFullP(void *ControllerBaseAddress)
+boolean DAC960_LP_HardwareMailboxFullP(void __iomem *ControllerBaseAddress)
 {
   DAC960_LP_InboundDoorBellRegister_T InboundDoorBellRegister;
   InboundDoorBellRegister.All =
@@ -3007,7 +3007,7 @@
 }
 
 static inline
-boolean DAC960_LP_InitializationInProgressP(void *ControllerBaseAddress)
+boolean DAC960_LP_InitializationInProgressP(void __iomem *ControllerBaseAddress)
 {
   DAC960_LP_InboundDoorBellRegister_T InboundDoorBellRegister;
   InboundDoorBellRegister.All =
@@ -3016,7 +3016,7 @@
 }
 
 static inline
-void DAC960_LP_AcknowledgeHardwareMailboxInterrupt(void *ControllerBaseAddress)
+void DAC960_LP_AcknowledgeHardwareMailboxInterrupt(void __iomem *ControllerBaseAddress)
 {
   DAC960_LP_OutboundDoorBellRegister_T OutboundDoorBellRegister;
   OutboundDoorBellRegister.All = 0;
@@ -3026,7 +3026,7 @@
 }
 
 static inline
-void DAC960_LP_AcknowledgeMemoryMailboxInterrupt(void *ControllerBaseAddress)
+void DAC960_LP_AcknowledgeMemoryMailboxInterrupt(void __iomem *ControllerBaseAddress)
 {
   DAC960_LP_OutboundDoorBellRegister_T OutboundDoorBellRegister;
   OutboundDoorBellRegister.All = 0;
@@ -3036,7 +3036,7 @@
 }
 
 static inline
-void DAC960_LP_AcknowledgeInterrupt(void *ControllerBaseAddress)
+void DAC960_LP_AcknowledgeInterrupt(void __iomem *ControllerBaseAddress)
 {
   DAC960_LP_OutboundDoorBellRegister_T OutboundDoorBellRegister;
   OutboundDoorBellRegister.All = 0;
@@ -3047,7 +3047,7 @@
 }
 
 static inline
-boolean DAC960_LP_HardwareMailboxStatusAvailableP(void *ControllerBaseAddress)
+boolean DAC960_LP_HardwareMailboxStatusAvailableP(void __iomem *ControllerBaseAddress)
 {
   DAC960_LP_OutboundDoorBellRegister_T OutboundDoorBellRegister;
   OutboundDoorBellRegister.All =
@@ -3056,7 +3056,7 @@
 }
 
 static inline
-boolean DAC960_LP_MemoryMailboxStatusAvailableP(void *ControllerBaseAddress)
+boolean DAC960_LP_MemoryMailboxStatusAvailableP(void __iomem *ControllerBaseAddress)
 {
   DAC960_LP_OutboundDoorBellRegister_T OutboundDoorBellRegister;
   OutboundDoorBellRegister.All =
@@ -3065,7 +3065,7 @@
 }
 
 static inline
-void DAC960_LP_EnableInterrupts(void *ControllerBaseAddress)
+void DAC960_LP_EnableInterrupts(void __iomem *ControllerBaseAddress)
 {
   DAC960_LP_InterruptMaskRegister_T InterruptMaskRegister;
   InterruptMaskRegister.All = 0xFF;
@@ -3075,7 +3075,7 @@
 }
 
 static inline
-void DAC960_LP_DisableInterrupts(void *ControllerBaseAddress)
+void DAC960_LP_DisableInterrupts(void __iomem *ControllerBaseAddress)
 {
   DAC960_LP_InterruptMaskRegister_T InterruptMaskRegister;
   InterruptMaskRegister.All = 0xFF;
@@ -3085,7 +3085,7 @@
 }
 
 static inline
-boolean DAC960_LP_InterruptsEnabledP(void *ControllerBaseAddress)
+boolean DAC960_LP_InterruptsEnabledP(void __iomem *ControllerBaseAddress)
 {
   DAC960_LP_InterruptMaskRegister_T InterruptMaskRegister;
   InterruptMaskRegister.All =
@@ -3107,7 +3107,7 @@
 }
 
 static inline
-void DAC960_LP_WriteHardwareMailbox(void *ControllerBaseAddress,
+void DAC960_LP_WriteHardwareMailbox(void __iomem *ControllerBaseAddress,
 				    dma_addr_t CommandMailboxDMA)
 {
 	dma_addr_writeql(CommandMailboxDMA,
@@ -3116,19 +3116,19 @@
 }
 
 static inline DAC960_V2_CommandIdentifier_T
-DAC960_LP_ReadCommandIdentifier(void *ControllerBaseAddress)
+DAC960_LP_ReadCommandIdentifier(void __iomem *ControllerBaseAddress)
 {
   return readw(ControllerBaseAddress + DAC960_LP_CommandStatusOffset);
 }
 
 static inline DAC960_V2_CommandStatus_T
-DAC960_LP_ReadCommandStatus(void *ControllerBaseAddress)
+DAC960_LP_ReadCommandStatus(void __iomem *ControllerBaseAddress)
 {
   return readw(ControllerBaseAddress + DAC960_LP_CommandStatusOffset + 2);
 }
 
 static inline boolean
-DAC960_LP_ReadErrorStatus(void *ControllerBaseAddress,
+DAC960_LP_ReadErrorStatus(void __iomem *ControllerBaseAddress,
 			  unsigned char *ErrorStatus,
 			  unsigned char *Parameter0,
 			  unsigned char *Parameter1)
@@ -3262,7 +3262,7 @@
 */
 
 static inline
-void DAC960_LA_HardwareMailboxNewCommand(void *ControllerBaseAddress)
+void DAC960_LA_HardwareMailboxNewCommand(void __iomem *ControllerBaseAddress)
 {
   DAC960_LA_InboundDoorBellRegister_T InboundDoorBellRegister;
   InboundDoorBellRegister.All = 0;
@@ -3272,7 +3272,7 @@
 }
 
 static inline
-void DAC960_LA_AcknowledgeHardwareMailboxStatus(void *ControllerBaseAddress)
+void DAC960_LA_AcknowledgeHardwareMailboxStatus(void __iomem *ControllerBaseAddress)
 {
   DAC960_LA_InboundDoorBellRegister_T InboundDoorBellRegister;
   InboundDoorBellRegister.All = 0;
@@ -3282,7 +3282,7 @@
 }
 
 static inline
-void DAC960_LA_GenerateInterrupt(void *ControllerBaseAddress)
+void DAC960_LA_GenerateInterrupt(void __iomem *ControllerBaseAddress)
 {
   DAC960_LA_InboundDoorBellRegister_T InboundDoorBellRegister;
   InboundDoorBellRegister.All = 0;
@@ -3292,7 +3292,7 @@
 }
 
 static inline
-void DAC960_LA_ControllerReset(void *ControllerBaseAddress)
+void DAC960_LA_ControllerReset(void __iomem *ControllerBaseAddress)
 {
   DAC960_LA_InboundDoorBellRegister_T InboundDoorBellRegister;
   InboundDoorBellRegister.All = 0;
@@ -3302,7 +3302,7 @@
 }
 
 static inline
-void DAC960_LA_MemoryMailboxNewCommand(void *ControllerBaseAddress)
+void DAC960_LA_MemoryMailboxNewCommand(void __iomem *ControllerBaseAddress)
 {
   DAC960_LA_InboundDoorBellRegister_T InboundDoorBellRegister;
   InboundDoorBellRegister.All = 0;
@@ -3312,7 +3312,7 @@
 }
 
 static inline
-boolean DAC960_LA_HardwareMailboxFullP(void *ControllerBaseAddress)
+boolean DAC960_LA_HardwareMailboxFullP(void __iomem *ControllerBaseAddress)
 {
   DAC960_LA_InboundDoorBellRegister_T InboundDoorBellRegister;
   InboundDoorBellRegister.All =
@@ -3321,7 +3321,7 @@
 }
 
 static inline
-boolean DAC960_LA_InitializationInProgressP(void *ControllerBaseAddress)
+boolean DAC960_LA_InitializationInProgressP(void __iomem *ControllerBaseAddress)
 {
   DAC960_LA_InboundDoorBellRegister_T InboundDoorBellRegister;
   InboundDoorBellRegister.All =
@@ -3330,7 +3330,7 @@
 }
 
 static inline
-void DAC960_LA_AcknowledgeHardwareMailboxInterrupt(void *ControllerBaseAddress)
+void DAC960_LA_AcknowledgeHardwareMailboxInterrupt(void __iomem *ControllerBaseAddress)
 {
   DAC960_LA_OutboundDoorBellRegister_T OutboundDoorBellRegister;
   OutboundDoorBellRegister.All = 0;
@@ -3340,7 +3340,7 @@
 }
 
 static inline
-void DAC960_LA_AcknowledgeMemoryMailboxInterrupt(void *ControllerBaseAddress)
+void DAC960_LA_AcknowledgeMemoryMailboxInterrupt(void __iomem *ControllerBaseAddress)
 {
   DAC960_LA_OutboundDoorBellRegister_T OutboundDoorBellRegister;
   OutboundDoorBellRegister.All = 0;
@@ -3350,7 +3350,7 @@
 }
 
 static inline
-void DAC960_LA_AcknowledgeInterrupt(void *ControllerBaseAddress)
+void DAC960_LA_AcknowledgeInterrupt(void __iomem *ControllerBaseAddress)
 {
   DAC960_LA_OutboundDoorBellRegister_T OutboundDoorBellRegister;
   OutboundDoorBellRegister.All = 0;
@@ -3361,7 +3361,7 @@
 }
 
 static inline
-boolean DAC960_LA_HardwareMailboxStatusAvailableP(void *ControllerBaseAddress)
+boolean DAC960_LA_HardwareMailboxStatusAvailableP(void __iomem *ControllerBaseAddress)
 {
   DAC960_LA_OutboundDoorBellRegister_T OutboundDoorBellRegister;
   OutboundDoorBellRegister.All =
@@ -3370,7 +3370,7 @@
 }
 
 static inline
-boolean DAC960_LA_MemoryMailboxStatusAvailableP(void *ControllerBaseAddress)
+boolean DAC960_LA_MemoryMailboxStatusAvailableP(void __iomem *ControllerBaseAddress)
 {
   DAC960_LA_OutboundDoorBellRegister_T OutboundDoorBellRegister;
   OutboundDoorBellRegister.All =
@@ -3379,7 +3379,7 @@
 }
 
 static inline
-void DAC960_LA_EnableInterrupts(void *ControllerBaseAddress)
+void DAC960_LA_EnableInterrupts(void __iomem *ControllerBaseAddress)
 {
   DAC960_LA_InterruptMaskRegister_T InterruptMaskRegister;
   InterruptMaskRegister.All = 0xFF;
@@ -3389,7 +3389,7 @@
 }
 
 static inline
-void DAC960_LA_DisableInterrupts(void *ControllerBaseAddress)
+void DAC960_LA_DisableInterrupts(void __iomem *ControllerBaseAddress)
 {
   DAC960_LA_InterruptMaskRegister_T InterruptMaskRegister;
   InterruptMaskRegister.All = 0xFF;
@@ -3399,7 +3399,7 @@
 }
 
 static inline
-boolean DAC960_LA_InterruptsEnabledP(void *ControllerBaseAddress)
+boolean DAC960_LA_InterruptsEnabledP(void __iomem *ControllerBaseAddress)
 {
   DAC960_LA_InterruptMaskRegister_T InterruptMaskRegister;
   InterruptMaskRegister.All =
@@ -3422,7 +3422,7 @@
 }
 
 static inline
-void DAC960_LA_WriteHardwareMailbox(void *ControllerBaseAddress,
+void DAC960_LA_WriteHardwareMailbox(void __iomem *ControllerBaseAddress,
 				    DAC960_V1_CommandMailbox_T *CommandMailbox)
 {
   writel(CommandMailbox->Words[0],
@@ -3436,20 +3436,20 @@
 }
 
 static inline DAC960_V1_CommandIdentifier_T
-DAC960_LA_ReadStatusCommandIdentifier(void *ControllerBaseAddress)
+DAC960_LA_ReadStatusCommandIdentifier(void __iomem *ControllerBaseAddress)
 {
   return readb(ControllerBaseAddress
 	       + DAC960_LA_StatusCommandIdentifierRegOffset);
 }
 
 static inline DAC960_V1_CommandStatus_T
-DAC960_LA_ReadStatusRegister(void *ControllerBaseAddress)
+DAC960_LA_ReadStatusRegister(void __iomem *ControllerBaseAddress)
 {
   return readw(ControllerBaseAddress + DAC960_LA_StatusRegisterOffset);
 }
 
 static inline boolean
-DAC960_LA_ReadErrorStatus(void *ControllerBaseAddress,
+DAC960_LA_ReadErrorStatus(void __iomem *ControllerBaseAddress,
 			  unsigned char *ErrorStatus,
 			  unsigned char *Parameter0,
 			  unsigned char *Parameter1)
@@ -3583,7 +3583,7 @@
 */
 
 static inline
-void DAC960_PG_HardwareMailboxNewCommand(void *ControllerBaseAddress)
+void DAC960_PG_HardwareMailboxNewCommand(void __iomem *ControllerBaseAddress)
 {
   DAC960_PG_InboundDoorBellRegister_T InboundDoorBellRegister;
   InboundDoorBellRegister.All = 0;
@@ -3593,7 +3593,7 @@
 }
 
 static inline
-void DAC960_PG_AcknowledgeHardwareMailboxStatus(void *ControllerBaseAddress)
+void DAC960_PG_AcknowledgeHardwareMailboxStatus(void __iomem *ControllerBaseAddress)
 {
   DAC960_PG_InboundDoorBellRegister_T InboundDoorBellRegister;
   InboundDoorBellRegister.All = 0;
@@ -3603,7 +3603,7 @@
 }
 
 static inline
-void DAC960_PG_GenerateInterrupt(void *ControllerBaseAddress)
+void DAC960_PG_GenerateInterrupt(void __iomem *ControllerBaseAddress)
 {
   DAC960_PG_InboundDoorBellRegister_T InboundDoorBellRegister;
   InboundDoorBellRegister.All = 0;
@@ -3613,7 +3613,7 @@
 }
 
 static inline
-void DAC960_PG_ControllerReset(void *ControllerBaseAddress)
+void DAC960_PG_ControllerReset(void __iomem *ControllerBaseAddress)
 {
   DAC960_PG_InboundDoorBellRegister_T InboundDoorBellRegister;
   InboundDoorBellRegister.All = 0;
@@ -3623,7 +3623,7 @@
 }
 
 static inline
-void DAC960_PG_MemoryMailboxNewCommand(void *ControllerBaseAddress)
+void DAC960_PG_MemoryMailboxNewCommand(void __iomem *ControllerBaseAddress)
 {
   DAC960_PG_InboundDoorBellRegister_T InboundDoorBellRegister;
   InboundDoorBellRegister.All = 0;
@@ -3633,7 +3633,7 @@
 }
 
 static inline
-boolean DAC960_PG_HardwareMailboxFullP(void *ControllerBaseAddress)
+boolean DAC960_PG_HardwareMailboxFullP(void __iomem *ControllerBaseAddress)
 {
   DAC960_PG_InboundDoorBellRegister_T InboundDoorBellRegister;
   InboundDoorBellRegister.All =
@@ -3642,7 +3642,7 @@
 }
 
 static inline
-boolean DAC960_PG_InitializationInProgressP(void *ControllerBaseAddress)
+boolean DAC960_PG_InitializationInProgressP(void __iomem *ControllerBaseAddress)
 {
   DAC960_PG_InboundDoorBellRegister_T InboundDoorBellRegister;
   InboundDoorBellRegister.All =
@@ -3651,7 +3651,7 @@
 }
 
 static inline
-void DAC960_PG_AcknowledgeHardwareMailboxInterrupt(void *ControllerBaseAddress)
+void DAC960_PG_AcknowledgeHardwareMailboxInterrupt(void __iomem *ControllerBaseAddress)
 {
   DAC960_PG_OutboundDoorBellRegister_T OutboundDoorBellRegister;
   OutboundDoorBellRegister.All = 0;
@@ -3661,7 +3661,7 @@
 }
 
 static inline
-void DAC960_PG_AcknowledgeMemoryMailboxInterrupt(void *ControllerBaseAddress)
+void DAC960_PG_AcknowledgeMemoryMailboxInterrupt(void __iomem *ControllerBaseAddress)
 {
   DAC960_PG_OutboundDoorBellRegister_T OutboundDoorBellRegister;
   OutboundDoorBellRegister.All = 0;
@@ -3671,7 +3671,7 @@
 }
 
 static inline
-void DAC960_PG_AcknowledgeInterrupt(void *ControllerBaseAddress)
+void DAC960_PG_AcknowledgeInterrupt(void __iomem *ControllerBaseAddress)
 {
   DAC960_PG_OutboundDoorBellRegister_T OutboundDoorBellRegister;
   OutboundDoorBellRegister.All = 0;
@@ -3682,7 +3682,7 @@
 }
 
 static inline
-boolean DAC960_PG_HardwareMailboxStatusAvailableP(void *ControllerBaseAddress)
+boolean DAC960_PG_HardwareMailboxStatusAvailableP(void __iomem *ControllerBaseAddress)
 {
   DAC960_PG_OutboundDoorBellRegister_T OutboundDoorBellRegister;
   OutboundDoorBellRegister.All =
@@ -3691,7 +3691,7 @@
 }
 
 static inline
-boolean DAC960_PG_MemoryMailboxStatusAvailableP(void *ControllerBaseAddress)
+boolean DAC960_PG_MemoryMailboxStatusAvailableP(void __iomem *ControllerBaseAddress)
 {
   DAC960_PG_OutboundDoorBellRegister_T OutboundDoorBellRegister;
   OutboundDoorBellRegister.All =
@@ -3700,7 +3700,7 @@
 }
 
 static inline
-void DAC960_PG_EnableInterrupts(void *ControllerBaseAddress)
+void DAC960_PG_EnableInterrupts(void __iomem *ControllerBaseAddress)
 {
   DAC960_PG_InterruptMaskRegister_T InterruptMaskRegister;
   InterruptMaskRegister.All = 0;
@@ -3712,7 +3712,7 @@
 }
 
 static inline
-void DAC960_PG_DisableInterrupts(void *ControllerBaseAddress)
+void DAC960_PG_DisableInterrupts(void __iomem *ControllerBaseAddress)
 {
   DAC960_PG_InterruptMaskRegister_T InterruptMaskRegister;
   InterruptMaskRegister.All = 0;
@@ -3724,7 +3724,7 @@
 }
 
 static inline
-boolean DAC960_PG_InterruptsEnabledP(void *ControllerBaseAddress)
+boolean DAC960_PG_InterruptsEnabledP(void __iomem *ControllerBaseAddress)
 {
   DAC960_PG_InterruptMaskRegister_T InterruptMaskRegister;
   InterruptMaskRegister.All =
@@ -3747,7 +3747,7 @@
 }
 
 static inline
-void DAC960_PG_WriteHardwareMailbox(void *ControllerBaseAddress,
+void DAC960_PG_WriteHardwareMailbox(void __iomem *ControllerBaseAddress,
 				    DAC960_V1_CommandMailbox_T *CommandMailbox)
 {
   writel(CommandMailbox->Words[0],
@@ -3761,20 +3761,20 @@
 }
 
 static inline DAC960_V1_CommandIdentifier_T
-DAC960_PG_ReadStatusCommandIdentifier(void *ControllerBaseAddress)
+DAC960_PG_ReadStatusCommandIdentifier(void __iomem *ControllerBaseAddress)
 {
   return readb(ControllerBaseAddress
 	       + DAC960_PG_StatusCommandIdentifierRegOffset);
 }
 
 static inline DAC960_V1_CommandStatus_T
-DAC960_PG_ReadStatusRegister(void *ControllerBaseAddress)
+DAC960_PG_ReadStatusRegister(void __iomem *ControllerBaseAddress)
 {
   return readw(ControllerBaseAddress + DAC960_PG_StatusRegisterOffset);
 }
 
 static inline boolean
-DAC960_PG_ReadErrorStatus(void *ControllerBaseAddress,
+DAC960_PG_ReadErrorStatus(void __iomem *ControllerBaseAddress,
 			  unsigned char *ErrorStatus,
 			  unsigned char *Parameter0,
 			  unsigned char *Parameter1)
@@ -3903,7 +3903,7 @@
 */
 
 static inline
-void DAC960_PD_NewCommand(void *ControllerBaseAddress)
+void DAC960_PD_NewCommand(void __iomem *ControllerBaseAddress)
 {
   DAC960_PD_InboundDoorBellRegister_T InboundDoorBellRegister;
   InboundDoorBellRegister.All = 0;
@@ -3913,7 +3913,7 @@
 }
 
 static inline
-void DAC960_PD_AcknowledgeStatus(void *ControllerBaseAddress)
+void DAC960_PD_AcknowledgeStatus(void __iomem *ControllerBaseAddress)
 {
   DAC960_PD_InboundDoorBellRegister_T InboundDoorBellRegister;
   InboundDoorBellRegister.All = 0;
@@ -3923,7 +3923,7 @@
 }
 
 static inline
-void DAC960_PD_GenerateInterrupt(void *ControllerBaseAddress)
+void DAC960_PD_GenerateInterrupt(void __iomem *ControllerBaseAddress)
 {
   DAC960_PD_InboundDoorBellRegister_T InboundDoorBellRegister;
   InboundDoorBellRegister.All = 0;
@@ -3933,7 +3933,7 @@
 }
 
 static inline
-void DAC960_PD_ControllerReset(void *ControllerBaseAddress)
+void DAC960_PD_ControllerReset(void __iomem *ControllerBaseAddress)
 {
   DAC960_PD_InboundDoorBellRegister_T InboundDoorBellRegister;
   InboundDoorBellRegister.All = 0;
@@ -3943,7 +3943,7 @@
 }
 
 static inline
-boolean DAC960_PD_MailboxFullP(void *ControllerBaseAddress)
+boolean DAC960_PD_MailboxFullP(void __iomem *ControllerBaseAddress)
 {
   DAC960_PD_InboundDoorBellRegister_T InboundDoorBellRegister;
   InboundDoorBellRegister.All =
@@ -3952,7 +3952,7 @@
 }
 
 static inline
-boolean DAC960_PD_InitializationInProgressP(void *ControllerBaseAddress)
+boolean DAC960_PD_InitializationInProgressP(void __iomem *ControllerBaseAddress)
 {
   DAC960_PD_InboundDoorBellRegister_T InboundDoorBellRegister;
   InboundDoorBellRegister.All =
@@ -3961,7 +3961,7 @@
 }
 
 static inline
-void DAC960_PD_AcknowledgeInterrupt(void *ControllerBaseAddress)
+void DAC960_PD_AcknowledgeInterrupt(void __iomem *ControllerBaseAddress)
 {
   DAC960_PD_OutboundDoorBellRegister_T OutboundDoorBellRegister;
   OutboundDoorBellRegister.All = 0;
@@ -3971,7 +3971,7 @@
 }
 
 static inline
-boolean DAC960_PD_StatusAvailableP(void *ControllerBaseAddress)
+boolean DAC960_PD_StatusAvailableP(void __iomem *ControllerBaseAddress)
 {
   DAC960_PD_OutboundDoorBellRegister_T OutboundDoorBellRegister;
   OutboundDoorBellRegister.All =
@@ -3980,7 +3980,7 @@
 }
 
 static inline
-void DAC960_PD_EnableInterrupts(void *ControllerBaseAddress)
+void DAC960_PD_EnableInterrupts(void __iomem *ControllerBaseAddress)
 {
   DAC960_PD_InterruptEnableRegister_T InterruptEnableRegister;
   InterruptEnableRegister.All = 0;
@@ -3990,7 +3990,7 @@
 }
 
 static inline
-void DAC960_PD_DisableInterrupts(void *ControllerBaseAddress)
+void DAC960_PD_DisableInterrupts(void __iomem *ControllerBaseAddress)
 {
   DAC960_PD_InterruptEnableRegister_T InterruptEnableRegister;
   InterruptEnableRegister.All = 0;
@@ -4000,7 +4000,7 @@
 }
 
 static inline
-boolean DAC960_PD_InterruptsEnabledP(void *ControllerBaseAddress)
+boolean DAC960_PD_InterruptsEnabledP(void __iomem *ControllerBaseAddress)
 {
   DAC960_PD_InterruptEnableRegister_T InterruptEnableRegister;
   InterruptEnableRegister.All =
@@ -4009,7 +4009,7 @@
 }
 
 static inline
-void DAC960_PD_WriteCommandMailbox(void *ControllerBaseAddress,
+void DAC960_PD_WriteCommandMailbox(void __iomem *ControllerBaseAddress,
 				   DAC960_V1_CommandMailbox_T *CommandMailbox)
 {
   writel(CommandMailbox->Words[0],
@@ -4023,20 +4023,20 @@
 }
 
 static inline DAC960_V1_CommandIdentifier_T
-DAC960_PD_ReadStatusCommandIdentifier(void *ControllerBaseAddress)
+DAC960_PD_ReadStatusCommandIdentifier(void __iomem *ControllerBaseAddress)
 {
   return readb(ControllerBaseAddress
 	       + DAC960_PD_StatusCommandIdentifierRegOffset);
 }
 
 static inline DAC960_V1_CommandStatus_T
-DAC960_PD_ReadStatusRegister(void *ControllerBaseAddress)
+DAC960_PD_ReadStatusRegister(void __iomem *ControllerBaseAddress)
 {
   return readw(ControllerBaseAddress + DAC960_PD_StatusRegisterOffset);
 }
 
 static inline boolean
-DAC960_PD_ReadErrorStatus(void *ControllerBaseAddress,
+DAC960_PD_ReadErrorStatus(void __iomem *ControllerBaseAddress,
 			  unsigned char *ErrorStatus,
 			  unsigned char *Parameter0,
 			  unsigned char *Parameter1)
diff -Nru a/drivers/block/Kconfig b/drivers/block/Kconfig
--- a/drivers/block/Kconfig	2004-10-18 14:56:18 -07:00
+++ b/drivers/block/Kconfig	2004-10-18 14:56:18 -07:00
@@ -166,7 +166,7 @@
 
 config CISS_SCSI_TAPE
 	bool "SCSI tape drive support for Smart Array 5xxx"
-	depends on BLK_CPQ_CISS_DA && SCSI
+	depends on BLK_CPQ_CISS_DA && SCSI && PROC_FS
 	help
 	  When enabled (Y), this option allows SCSI tape drives and SCSI medium
 	  changers (tape robots) to be accessed via a Compaq 5xxx array 
@@ -300,6 +300,15 @@
 	  Promise SATA SX8 controllers.
 
 	  Use devices /dev/sx8/$N and /dev/sx8/$Np$M.
+
+config BLK_DEV_UB
+	tristate "Low Performance USB Block driver"
+	depends on USB
+	help
+	  This driver supports certain USB attached storage devices
+	  such as flash keys.
+
+	  If unsure, say N.
 
 config BLK_DEV_RAM
 	tristate "RAM disk support"
diff -Nru a/drivers/block/Makefile b/drivers/block/Makefile
--- a/drivers/block/Makefile	2004-10-18 14:56:49 -07:00
+++ b/drivers/block/Makefile	2004-10-18 14:56:49 -07:00
@@ -42,4 +42,5 @@
 
 obj-$(CONFIG_VIODASD)		+= viodasd.o
 obj-$(CONFIG_BLK_DEV_SX8)	+= sx8.o
+obj-$(CONFIG_BLK_DEV_UB)	+= ub.o
 
diff -Nru a/drivers/block/amiflop.c b/drivers/block/amiflop.c
--- a/drivers/block/amiflop.c	2004-10-18 14:56:29 -07:00
+++ b/drivers/block/amiflop.c	2004-10-18 14:56:29 -07:00
@@ -386,16 +386,6 @@
 	fd_select(drive);
 	udelay (1);
 	fd_deselect(drive);
-
-#ifdef MODULE
-/*
-  this is the last interrupt for any drive access, happens after
-  release (from floppy_off). So we have to wait until now to decrease
-  the use count.
-*/
-	if (decusecount)
-		MOD_DEC_USE_COUNT;
-#endif
 }
 
 static void floppy_off (unsigned int nr)
@@ -1590,10 +1580,6 @@
 	local_irq_save(flags);
 	fd_ref[drive]++;
 	fd_device[drive] = system;
-#ifdef MODULE
-	if (unit[drive].motor == 0)
-		MOD_INC_USE_COUNT;
-#endif
 	local_irq_restore(flags);
 
 	unit[drive].dtype=&data_types[system];
@@ -1839,6 +1825,7 @@
 	return amiga_floppy_init();
 }
 
+#if 0 /* not safe to unload */
 void cleanup_module(void)
 {
 	int i;
@@ -1859,4 +1846,5 @@
 	release_mem_region(CUSTOM_PHYSADDR+0x20, 8);
 	unregister_blkdev(FLOPPY_MAJOR, "fd");
 }
+#endif
 #endif
diff -Nru a/drivers/block/cciss.c b/drivers/block/cciss.c
--- a/drivers/block/cciss.c	2004-10-18 14:57:04 -07:00
+++ b/drivers/block/cciss.c	2004-10-18 14:57:04 -07:00
@@ -46,14 +46,14 @@
 #include <linux/completion.h>
 
 #define CCISS_DRIVER_VERSION(maj,min,submin) ((maj<<16)|(min<<8)|(submin))
-#define DRIVER_NAME "Compaq CISS Driver (v 2.6.2)"
+#define DRIVER_NAME "HP CISS Driver (v 2.6.2)"
 #define DRIVER_VERSION CCISS_DRIVER_VERSION(2,6,2)
 
 /* Embedded module documentation macros - see modules.h */
 MODULE_AUTHOR("Hewlett-Packard Company");
 MODULE_DESCRIPTION("Driver for HP Controller SA5xxx SA6xxx version 2.6.2");
 MODULE_SUPPORTED_DEVICE("HP SA5i SA5i+ SA532 SA5300 SA5312 SA641 SA642 SA6400"
-			" SA6i");
+			" SA6i V100");
 MODULE_LICENSE("GPL");
 
 #include "cciss_cmd.h"
@@ -82,7 +82,7 @@
 		0x0E11, 0x4091, 0, 0, 0},
 	{ PCI_VENDOR_ID_COMPAQ, PCI_DEVICE_ID_COMPAQ_CISSC,
 		0x0E11, 0x409E, 0, 0, 0},
-	{ PCI_VENDOR_ID_COMPAQ, PCI_DEVICE_ID_COMPAQ_CISSC,
+	{ PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_CISS,
 		0x103C, 0x3211, 0, 0, 0},
 	{0,}
 };
@@ -115,7 +115,7 @@
 /*define how many times we will try a command because of bus resets */
 #define MAX_CMD_RETRIES 3
 
-#define READ_AHEAD 	 256
+#define READ_AHEAD 	 1024
 #define NR_CMDS		 384 /* #commands that can be outstanding */
 #define MAX_CTLR 8
 
@@ -192,10 +192,10 @@
 /*
  * Report information about this controller.
  */
-#define ENG_GIG 1048576000
+#define ENG_GIG 1000000000
 #define ENG_GIG_FACTOR (ENG_GIG/512)
 #define RAID_UNKNOWN 6
-static const char *raid_label[] = {"0","4","1(0+1)","5","5+1","ADG",
+static const char *raid_label[] = {"0","4","1(1+0)","5","5+1","ADG",
 	                                   "UNKNOWN"};
 
 static struct proc_dir_entry *proc_cciss;
@@ -209,7 +209,7 @@
         ctlr_info_t *h = (ctlr_info_t*)data;
         drive_info_struct *drv;
 	unsigned long flags;
-	unsigned int vol_sz, vol_sz_frac;
+        sector_t vol_sz, vol_sz_frac;
 
         ctlr = h->ctlr;
 
@@ -246,32 +246,21 @@
         pos += size; len += size;
 	cciss_proc_tape_report(ctlr, buffer, &pos, &len);
 	for(i=0; i<=h->highest_lun; i++) {
-		sector_t tmp;
 
                 drv = &h->drv[i];
 		if (drv->block_size == 0)
 			continue;
-		vol_sz = drv->nr_blocks;
-		sector_div(vol_sz, ENG_GIG_FACTOR);
-
-		/*
-		 * Awkwardly do this:
-		 * vol_sz_frac =
-		 *     (drv->nr_blocks%ENG_GIG_FACTOR)*100/ENG_GIG_FACTOR;
-		 */
-		tmp = drv->nr_blocks;
-		vol_sz_frac = sector_div(tmp, ENG_GIG_FACTOR);
-
-		/* Now, vol_sz_frac = (drv->nr_blocks%ENG_GIG_FACTOR) */
 
+		vol_sz = drv->nr_blocks;
+		vol_sz_frac = sector_div(vol_sz, ENG_GIG_FACTOR);
 		vol_sz_frac *= 100;
 		sector_div(vol_sz_frac, ENG_GIG_FACTOR);
 
 		if (drv->raid_level > 5)
 			drv->raid_level = RAID_UNKNOWN;
 		size = sprintf(buffer+len, "cciss/c%dd%d:"
-				"\t%4d.%02dGB\tRAID %s\n",
-				ctlr, i, vol_sz,vol_sz_frac,
+				"\t%4u.%02uGB\tRAID %s\n",
+				ctlr, i, (int)vol_sz, (int)vol_sz_frac,
 				raid_label[drv->raid_level]);
                 pos += size; len += size;
         }
@@ -578,7 +567,7 @@
 	err = sys_ioctl(fd, CCISS_PASSTHRU, (unsigned long) p);
 	if (err)
 		return err;
-	err |= copy_in_user(&arg32->error_info, &p->error_info, sizeof(&arg32->error_info));
+	err |= copy_in_user(&arg32->error_info, &p->error_info, sizeof(arg32->error_info));
 	if (err)
 		return -EFAULT;
 	return err;
@@ -610,7 +599,7 @@
 	err = sys_ioctl(fd, CCISS_BIG_PASSTHRU, (unsigned long) p);
 	if (err)
 		return err;
-	err |= copy_in_user(&arg32->error_info, &p->error_info, sizeof(&arg32->error_info));
+	err |= copy_in_user(&arg32->error_info, &p->error_info, sizeof(arg32->error_info));
 	if (err)
 		return -EFAULT;
 	return err;
@@ -866,6 +855,8 @@
 				kfree(buff);
 				return -EFAULT;
 			}
+		} else {
+			memset(buff, 0, iocommand.buf_size);
 		}
 		if ((c = cmd_alloc(host , 0)) == NULL)
 		{
@@ -1012,6 +1003,8 @@
 				copy_from_user(buff[sg_used], data_ptr, sz)) {
 					status = -ENOMEM;
 					goto cleanup1;			
+			} else {
+				memset(buff[sg_used], 0, sz);
 			}
 			left -= sz;
 			data_ptr += sz;
@@ -1477,12 +1470,19 @@
 			drv->sectors = 32; // Sectors per track
 			drv->cylinders = total_size / 255 / 32;
 		} else {
+			unsigned int t;
+
 			drv->block_size = block_size;
 			drv->nr_blocks = total_size;
 			drv->heads = inq_buff->data_byte[6];
 			drv->sectors = inq_buff->data_byte[7];
 			drv->cylinders = (inq_buff->data_byte[4] & 0xff) << 8;
 			drv->cylinders += inq_buff->data_byte[5];
+			drv->raid_level = inq_buff->data_byte[8];
+			t = drv->heads * drv->sectors;
+			if (t > 1) {
+				drv->cylinders = total_size/t;
+			}
 		}
 	} else { /* Get geometry failed */
 		printk(KERN_WARNING "cciss: reading geometry failed, "
@@ -1509,8 +1509,8 @@
 		return_code = sendcmd(CCISS_READ_CAPACITY,
 			ctlr, buf, sizeof(*buf), 1, logvol, 0, NULL, TYPE_CMD);
 	if (return_code == IO_OK) {
-		*total_size = be32_to_cpu(*((__u32 *) &buf->total_size[0]))+1;
-		*block_size = be32_to_cpu(*((__u32 *) &buf->block_size[0]));
+		*total_size = be32_to_cpu(*((__be32 *) &buf->total_size[0]))+1;
+		*block_size = be32_to_cpu(*((__be32 *) &buf->block_size[0]));
 	} else { /* read capacity command failed */
 		printk(KERN_WARNING "cciss: read capacity failed\n");
 		*total_size = 0;
@@ -1844,13 +1844,13 @@
 /*
  * Map (physical) PCI mem into (virtual) kernel space
  */
-static ulong remap_pci_mem(ulong base, ulong size)
+static void __iomem *remap_pci_mem(ulong base, ulong size)
 {
         ulong page_base        = ((ulong) base) & PAGE_MASK;
         ulong page_offs        = ((ulong) base) - page_base;
-        ulong page_remapped    = (ulong) ioremap(page_base, page_offs+size);
+        void __iomem *page_remapped = ioremap(page_base, page_offs+size);
 
-        return (ulong) (page_remapped ? (page_remapped + page_offs) : 0UL);
+        return page_remapped ? (page_remapped + page_offs) : NULL;
 }
 
 /* 
@@ -2300,7 +2300,6 @@
 static int cciss_pci_init(ctlr_info_t *c, struct pci_dev *pdev)
 {
 	ushort subsystem_vendor_id, subsystem_device_id, command;
-	unchar irq = pdev->irq;
 	__u32 board_id, scratchpad = 0;
 	__u64 cfg_offset;
 	__u32 cfg_base_addr;
@@ -2359,11 +2358,11 @@
 
 #ifdef CCISS_DEBUG
 	printk("command = %x\n", command);
-	printk("irq = %x\n", irq);
+	printk("irq = %x\n", pdev->irq);
 	printk("board_id = %x\n", board_id);
 #endif /* CCISS_DEBUG */ 
 
-	c->intr = irq;
+	c->intr = pdev->irq;
 
 	/*
 	 * Memory base addr is first addr , the second points to the config
@@ -2411,9 +2410,9 @@
 #ifdef CCISS_DEBUG
 	printk("cfg offset = %x\n", cfg_offset);
 #endif /* CCISS_DEBUG */
-	c->cfgtable = (CfgTable_struct *) 
-		remap_pci_mem(pci_resource_start(pdev, cfg_base_addr_index)
-				+ cfg_offset, sizeof(CfgTable_struct));
+	c->cfgtable =  remap_pci_mem(pci_resource_start(pdev,
+				cfg_base_addr_index) + cfg_offset,
+				sizeof(CfgTable_struct));
 	c->board_id = board_id;
 
 #ifdef CCISS_DEBUG
@@ -2825,7 +2824,7 @@
 	}
 	free_irq(hba[i]->intr, hba[i]);
 	pci_set_drvdata(pdev, NULL);
-	iounmap((void*)hba[i]->vaddr);
+	iounmap(hba[i]->vaddr);
 	cciss_unregister_scsi(i);  /* unhook from SCSI subsystem */
 	unregister_blkdev(COMPAQ_CISS_MAJOR+i, hba[i]->devname);
 	remove_proc_entry(hba[i]->devname, proc_cciss);	
diff -Nru a/drivers/block/cciss.h b/drivers/block/cciss.h
--- a/drivers/block/cciss.h	2004-10-18 14:55:53 -07:00
+++ b/drivers/block/cciss.h	2004-10-18 14:55:53 -07:00
@@ -43,12 +43,12 @@
 	char	firm_ver[4]; // Firmware version 
 	struct pci_dev *pdev;
 	__u32	board_id;
-	unsigned long vaddr;
+	void __iomem *vaddr;
 	unsigned long paddr;
 	unsigned long io_mem_addr;
 	unsigned long io_mem_length;
-	CfgTable_struct *cfgtable;
-	int	intr;
+	CfgTable_struct __iomem *cfgtable;
+	unsigned int intr;
 	int	interrupts_enabled;
 	int 	max_commands;
 	int	commands_outstanding;
diff -Nru a/drivers/block/cpqarray.c b/drivers/block/cpqarray.c
--- a/drivers/block/cpqarray.c	2004-10-18 14:55:55 -07:00
+++ b/drivers/block/cpqarray.c	2004-10-18 14:55:55 -07:00
@@ -138,7 +138,7 @@
 
 int cpqarray_init_step2(void);
 static int cpqarray_pci_init(ctlr_info_t *c, struct pci_dev *pdev);
-static void *remap_pci_mem(ulong base, ulong size);
+static void __iomem *remap_pci_mem(ulong base, ulong size);
 static int cpqarray_eisa_detect(void);
 static int pollcomplete(int ctlr);
 static void getgeometry(int ctlr);
@@ -551,10 +551,10 @@
 }
 
 static struct pci_driver cpqarray_pci_driver = {
-	name:   "cpqarray",
-	probe:  cpqarray_init_one,
-	remove:  __devexit_p(cpqarray_remove_one_pci),
-	id_table:  cpqarray_pci_device_id,
+	.name = "cpqarray",
+	.probe = cpqarray_init_one,
+	.remove = __devexit_p(cpqarray_remove_one_pci),
+	.id_table = cpqarray_pci_device_id,
 };
 
 /*
@@ -722,11 +722,11 @@
 /*
  * Map (physical) PCI mem into (virtual) kernel space
  */
-static void *remap_pci_mem(ulong base, ulong size)
+static void __iomem *remap_pci_mem(ulong base, ulong size)
 {
         ulong page_base        = ((ulong) base) & PAGE_MASK;
         ulong page_offs        = ((ulong) base) - page_base;
-        void *page_remapped    = ioremap(page_base, page_offs+size);
+        void __iomem *page_remapped    = ioremap(page_base, page_offs+size);
 
         return (page_remapped ? (page_remapped + page_offs) : NULL);
 }
diff -Nru a/drivers/block/cpqarray.h b/drivers/block/cpqarray.h
--- a/drivers/block/cpqarray.h	2004-10-18 14:56:33 -07:00
+++ b/drivers/block/cpqarray.h	2004-10-18 14:56:33 -07:00
@@ -90,7 +90,7 @@
 	__u32	board_id;
 	char	*product_name;	
 
-	void *vaddr;
+	void __iomem *vaddr;
 	unsigned long paddr;
 	unsigned long io_mem_addr;
 	unsigned long io_mem_length;
diff -Nru a/drivers/block/genhd.c b/drivers/block/genhd.c
--- a/drivers/block/genhd.c	2004-10-18 14:56:29 -07:00
+++ b/drivers/block/genhd.c	2004-10-18 14:56:29 -07:00
@@ -365,7 +365,9 @@
 
 static ssize_t disk_stats_read(struct gendisk * disk, char *page)
 {
+	preempt_disable();
 	disk_round_stats(disk);
+	preempt_enable();
 	return sprintf(page,
 		"%8u %8u %8llu %8u "
 		"%8u %8u %8llu %8u "
@@ -494,7 +496,9 @@
 				"\n\n");
 	*/
  
+	preempt_disable();
 	disk_round_stats(gp);
+	preempt_enable();
 	seq_printf(s, "%4d %4d %s %u %u %llu %u %u %u %llu %u %u %u %u\n",
 		gp->major, n + gp->first_minor, disk_name(gp, n, buf),
 		disk_stat_read(gp, reads), disk_stat_read(gp, read_merges),
diff -Nru a/drivers/block/ioctl.c b/drivers/block/ioctl.c
--- a/drivers/block/ioctl.c	2004-10-18 14:55:54 -07:00
+++ b/drivers/block/ioctl.c	2004-10-18 14:55:54 -07:00
@@ -194,7 +194,8 @@
 			return -EACCES;
 		if (disk->fops->ioctl) {
 			ret = disk->fops->ioctl(inode, file, cmd, arg);
-			if (ret != -EINVAL)
+			/* -EINVAL to handle old uncorrected drivers */
+			if (ret != -EINVAL && ret != -ENOTTY)
 				return ret;
 		}
 		fsync_bdev(bdev);
diff -Nru a/drivers/block/ll_rw_blk.c b/drivers/block/ll_rw_blk.c
--- a/drivers/block/ll_rw_blk.c	2004-10-18 14:55:54 -07:00
+++ b/drivers/block/ll_rw_blk.c	2004-10-18 14:55:54 -07:00
@@ -154,6 +154,8 @@
 	return ret;
 }
 
+EXPORT_SYMBOL(blk_get_backing_dev_info);
+
 void blk_queue_activity_fn(request_queue_t *q, activity_fn *fn, void *data)
 {
 	q->activity_fn = fn;
@@ -263,6 +265,45 @@
 EXPORT_SYMBOL(blk_queue_make_request);
 
 /**
+ * blk_queue_ordered - does this queue support ordered writes
+ * @q:     the request queue
+ * @flag:  see below
+ *
+ * Description:
+ *   For journalled file systems, doing ordered writes on a commit
+ *   block instead of explicitly doing wait_on_buffer (which is bad
+ *   for performance) can be a big win. Block drivers supporting this
+ *   feature should call this function and indicate so.
+ *
+ **/
+void blk_queue_ordered(request_queue_t *q, int flag)
+{
+	if (flag)
+		set_bit(QUEUE_FLAG_ORDERED, &q->queue_flags);
+	else
+		clear_bit(QUEUE_FLAG_ORDERED, &q->queue_flags);
+}
+
+EXPORT_SYMBOL(blk_queue_ordered);
+
+/**
+ * blk_queue_issue_flush_fn - set function for issuing a flush
+ * @q:     the request queue
+ * @iff:   the function to be called issuing the flush
+ *
+ * Description:
+ *   If a driver supports issuing a flush command, the support is notified
+ *   to the block layer by defining it through this call.
+ *
+ **/
+void blk_queue_issue_flush_fn(request_queue_t *q, issue_flush_fn *iff)
+{
+	q->issue_flush_fn = iff;
+}
+
+EXPORT_SYMBOL(blk_queue_issue_flush_fn);
+
+/**
  * blk_queue_bounce_limit - set bounce buffer limit for queue
  * @q:  the request queue for the device
  * @dma_addr:   bus address limit
@@ -311,7 +352,7 @@
 		printk("%s: set to minimum %d\n", __FUNCTION__, max_sectors);
 	}
 
-	q->max_sectors = max_sectors;
+	q->max_sectors = q->max_hw_sectors = max_sectors;
 }
 
 EXPORT_SYMBOL(blk_queue_max_sectors);
@@ -413,7 +454,8 @@
 void blk_queue_stack_limits(request_queue_t *t, request_queue_t *b)
 {
 	/* zero is "infinity" */
-	t->max_sectors = min_not_zero(t->max_sectors,b->max_sectors);
+	t->max_sectors = t->max_hw_sectors =
+		min_not_zero(t->max_sectors,b->max_sectors);
 
 	t->max_phys_segments = min(t->max_phys_segments,b->max_phys_segments);
 	t->max_hw_segments = min(t->max_hw_segments,b->max_hw_segments);
@@ -482,15 +524,14 @@
 EXPORT_SYMBOL(blk_queue_find_tag);
 
 /**
- * blk_queue_free_tags - release tag maintenance info
+ * __blk_queue_free_tags - release tag maintenance info
  * @q:  the request queue for the device
  *
  *  Notes:
  *    blk_cleanup_queue() will take care of calling this function, if tagging
- *    has been used. So there's usually no need to call this directly, unless
- *    tagging is just being disabled but the queue remains in function.
+ *    has been used. So there's no need to call this directly.
  **/
-void blk_queue_free_tags(request_queue_t *q)
+static void __blk_queue_free_tags(request_queue_t *q)
 {
 	struct blk_queue_tag *bqt = q->queue_tags;
 
@@ -514,12 +555,27 @@
 	q->queue_flags &= ~(1 << QUEUE_FLAG_QUEUED);
 }
 
+/**
+ * blk_queue_free_tags - release tag maintenance info
+ * @q:  the request queue for the device
+ *
+ *  Notes:
+ *	This is used to disabled tagged queuing to a device, yet leave
+ *	queue in function.
+ **/
+void blk_queue_free_tags(request_queue_t *q)
+{
+	clear_bit(QUEUE_FLAG_QUEUED, &q->queue_flags);
+}
+
 EXPORT_SYMBOL(blk_queue_free_tags);
 
 static int
 init_tag_map(request_queue_t *q, struct blk_queue_tag *tags, int depth)
 {
 	int bits, i;
+	struct request **tag_index;
+	unsigned long *tag_map;
 
 	if (depth > q->nr_requests * 2) {
 		depth = q->nr_requests * 2;
@@ -527,32 +583,31 @@
 				__FUNCTION__, depth);
 	}
 
-	tags->tag_index = kmalloc(depth * sizeof(struct request *), GFP_ATOMIC);
-	if (!tags->tag_index)
+	tag_index = kmalloc(depth * sizeof(struct request *), GFP_ATOMIC);
+	if (!tag_index)
 		goto fail;
 
 	bits = (depth / BLK_TAGS_PER_LONG) + 1;
-	tags->tag_map = kmalloc(bits * sizeof(unsigned long), GFP_ATOMIC);
-	if (!tags->tag_map)
+	tag_map = kmalloc(bits * sizeof(unsigned long), GFP_ATOMIC);
+	if (!tag_map)
 		goto fail;
 
-	memset(tags->tag_index, 0, depth * sizeof(struct request *));
-	memset(tags->tag_map, 0, bits * sizeof(unsigned long));
+	memset(tag_index, 0, depth * sizeof(struct request *));
+	memset(tag_map, 0, bits * sizeof(unsigned long));
 	tags->max_depth = depth;
 	tags->real_max_depth = bits * BITS_PER_LONG;
+	tags->tag_index = tag_index;
+	tags->tag_map = tag_map;
 
 	/*
 	 * set the upper bits if the depth isn't a multiple of the word size
 	 */
 	for (i = depth; i < bits * BLK_TAGS_PER_LONG; i++)
-		__set_bit(i, tags->tag_map);
+		__set_bit(i, tag_map);
 
-	INIT_LIST_HEAD(&tags->busy_list);
-	tags->busy = 0;
-	atomic_set(&tags->refcnt, 1);
 	return 0;
 fail:
-	kfree(tags->tag_index);
+	kfree(tag_index);
 	return -ENOMEM;
 }
 
@@ -564,13 +619,26 @@
 int blk_queue_init_tags(request_queue_t *q, int depth,
 			struct blk_queue_tag *tags)
 {
-	if (!tags) {
+	int rc;
+
+	BUG_ON(tags && q->queue_tags && tags != q->queue_tags);
+
+	if (!tags && !q->queue_tags) {
 		tags = kmalloc(sizeof(struct blk_queue_tag), GFP_ATOMIC);
 		if (!tags)
 			goto fail;
 
 		if (init_tag_map(q, tags, depth))
 			goto fail;
+
+		INIT_LIST_HEAD(&tags->busy_list);
+		tags->busy = 0;
+		atomic_set(&tags->refcnt, 1);
+	} else if (q->queue_tags) {
+		if ((rc = blk_queue_resize_tags(q, depth)))
+			return rc;
+		set_bit(QUEUE_FLAG_QUEUED, &q->queue_flags);
+		return 0;
 	} else
 		atomic_inc(&tags->refcnt);
 
@@ -1335,8 +1403,8 @@
 	if (rl->rq_pool)
 		mempool_destroy(rl->rq_pool);
 
-	if (blk_queue_tagged(q))
-		blk_queue_free_tags(q);
+	if (q->queue_tags)
+		__blk_queue_free_tags(q);
 
 	kmem_cache_free(requestq_cachep, q);
 }
@@ -1925,10 +1993,11 @@
 	}
 
 	rq->flags |= REQ_NOMERGE;
-	rq->waiting = &wait;
+	if (!rq->waiting)
+		rq->waiting = &wait;
 	elv_add_request(q, rq, ELEVATOR_INSERT_BACK, 1);
 	generic_unplug_device(q);
-	wait_for_completion(&wait);
+	wait_for_completion(rq->waiting);
 	rq->waiting = NULL;
 
 	if (rq->errors)
@@ -1939,6 +2008,72 @@
 
 EXPORT_SYMBOL(blk_execute_rq);
 
+/**
+ * blkdev_issue_flush - queue a flush
+ * @bdev:	blockdev to issue flush for
+ * @error_sector:	error sector
+ *
+ * Description:
+ *    Issue a flush for the block device in question. Caller can supply
+ *    room for storing the error offset in case of a flush error, if they
+ *    wish to.  Caller must run wait_for_completion() on its own.
+ */
+int blkdev_issue_flush(struct block_device *bdev, sector_t *error_sector)
+{
+	request_queue_t *q;
+
+	if (bdev->bd_disk == NULL)
+		return -ENXIO;
+
+	q = bdev_get_queue(bdev);
+	if (!q)
+		return -ENXIO;
+	if (!q->issue_flush_fn)
+		return -EOPNOTSUPP;
+
+	return q->issue_flush_fn(q, bdev->bd_disk, error_sector);
+}
+
+EXPORT_SYMBOL(blkdev_issue_flush);
+
+/**
+ * blkdev_scsi_issue_flush_fn - issue flush for SCSI devices
+ * @q:		device queue
+ * @disk:	gendisk
+ * @error_sector:	error offset
+ *
+ * Description:
+ *    Devices understanding the SCSI command set, can use this function as
+ *    a helper for issuing a cache flush. Note: driver is required to store
+ *    the error offset (in case of error flushing) in ->sector of struct
+ *    request.
+ */
+int blkdev_scsi_issue_flush_fn(request_queue_t *q, struct gendisk *disk,
+			       sector_t *error_sector)
+{
+	struct request *rq = blk_get_request(q, WRITE, __GFP_WAIT);
+	int ret;
+
+	rq->flags |= REQ_BLOCK_PC | REQ_SOFTBARRIER;
+	rq->sector = 0;
+	memset(rq->cmd, 0, sizeof(rq->cmd));
+	rq->cmd[0] = 0x35;
+	rq->cmd_len = 12;
+	rq->data = NULL;
+	rq->data_len = 0;
+	rq->timeout = 60 * HZ;
+
+	ret = blk_execute_rq(q, disk, rq);
+
+	if (ret && error_sector)
+		*error_sector = rq->sector;
+
+	blk_put_request(rq);
+	return ret;
+}
+
+EXPORT_SYMBOL(blkdev_scsi_issue_flush_fn);
+
 void drive_stat_acct(struct request *rq, int nr_sectors, int new_io)
 {
 	int rw = rq_data_dir(rq);
@@ -2192,7 +2327,7 @@
 static int __make_request(request_queue_t *q, struct bio *bio)
 {
 	struct request *req, *freereq = NULL;
-	int el_ret, rw, nr_sectors, cur_nr_sectors, barrier, ra;
+	int el_ret, rw, nr_sectors, cur_nr_sectors, barrier, err;
 	sector_t sector;
 
 	sector = bio->bi_sector;
@@ -2210,9 +2345,11 @@
 
 	spin_lock_prefetch(q->queue_lock);
 
-	barrier = test_bit(BIO_RW_BARRIER, &bio->bi_rw);
-
-	ra = bio->bi_rw & (1 << BIO_RW_AHEAD);
+	barrier = bio_barrier(bio);
+	if (barrier && !(q->queue_flags & (1 << QUEUE_FLAG_ORDERED))) {
+		err = -EOPNOTSUPP;
+		goto end_io;
+	}
 
 again:
 	spin_lock_irq(q->queue_lock);
@@ -2292,7 +2429,8 @@
 			/*
 			 * READA bit set
 			 */
-			if (ra)
+			err = -EWOULDBLOCK;
+			if (bio_rw_ahead(bio))
 				goto end_io;
 	
 			freereq = get_request_wait(q, rw);
@@ -2303,10 +2441,9 @@
 	req->flags |= REQ_CMD;
 
 	/*
-	 * inherit FAILFAST from bio and don't stack up
-	 * retries for read ahead
+	 * inherit FAILFAST from bio (for read-ahead, and explicit FAILFAST)
 	 */
-	if (ra || test_bit(BIO_RW_FAILFAST, &bio->bi_rw))	
+	if (bio_rw_ahead(bio) || bio_failfast(bio))
 		req->flags |= REQ_FAILFAST;
 
 	/*
@@ -2340,7 +2477,7 @@
 	return 0;
 
 end_io:
-	bio_endio(bio, nr_sectors << 9, -EWOULDBLOCK);
+	bio_endio(bio, nr_sectors << 9, err);
 	return 0;
 }
 
@@ -2399,6 +2536,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) {
@@ -2446,11 +2584,11 @@
 			break;
 		}
 
-		if (unlikely(bio_sectors(bio) > q->max_sectors)) {
+		if (unlikely(bio_sectors(bio) > q->max_hw_sectors)) {
 			printk("bio too big device %s (%u > %u)\n", 
 				bdevname(bio->bi_bdev, b),
 				bio_sectors(bio),
-				q->max_sectors);
+				q->max_hw_sectors);
 			goto end_io;
 		}
 
@@ -2647,10 +2785,17 @@
 static int __end_that_request_first(struct request *req, int uptodate,
 				    int nr_bytes)
 {
-	int total_bytes, bio_nbytes, error = 0, next_idx = 0;
+	int total_bytes, bio_nbytes, error, next_idx = 0;
 	struct bio *bio;
 
 	/*
+	 * extend uptodate bool to allow < 0 value to be direct io error
+	 */
+	error = 0;
+	if (end_io_error(uptodate))
+		error = !uptodate ? -EIO : uptodate;
+
+	/*
 	 * for a REQ_BLOCK_PC request, we want to carry any eventual
 	 * sense key with us all the way through
 	 */
@@ -2658,7 +2803,6 @@
 		req->errors = 0;
 
 	if (!uptodate) {
-		error = -EIO;
 		if (blk_fs_request(req) && !(req->flags & REQ_QUIET))
 			printk("end_request: I/O error, dev %s, sector %llu\n",
 				req->rq_disk ? req->rq_disk->disk_name : "?",
@@ -2741,7 +2885,7 @@
 /**
  * end_that_request_first - end I/O on a request
  * @req:      the request being processed
- * @uptodate: 0 for I/O error
+ * @uptodate: 1 for success, 0 for I/O error, < 0 for specific error
  * @nr_sectors: number of sectors to end I/O on
  *
  * Description:
@@ -2762,7 +2906,7 @@
 /**
  * end_that_request_chunk - end I/O on a request
  * @req:      the request being processed
- * @uptodate: 0 for I/O error
+ * @uptodate: 1 for success, 0 for I/O error, < 0 for specific error
  * @nr_bytes: number of bytes to complete
  *
  * Description:
@@ -3063,13 +3207,61 @@
 	unsigned long ra_kb;
 	ssize_t ret = queue_var_store(&ra_kb, page, count);
 
+	spin_lock_irq(q->queue_lock);
 	if (ra_kb > (q->max_sectors >> 1))
 		ra_kb = (q->max_sectors >> 1);
 
 	q->backing_dev_info.ra_pages = ra_kb >> (PAGE_CACHE_SHIFT - 10);
+	spin_unlock_irq(q->queue_lock);
+
+	return ret;
+}
+
+static ssize_t queue_max_sectors_show(struct request_queue *q, char *page)
+{
+	int max_sectors_kb = q->max_sectors >> 1;
+
+	return queue_var_show(max_sectors_kb, (page));
+}
+
+static ssize_t
+queue_max_sectors_store(struct request_queue *q, const char *page, size_t count)
+{
+	unsigned long max_sectors_kb,
+			max_hw_sectors_kb = q->max_hw_sectors >> 1,
+			page_kb = 1 << (PAGE_CACHE_SHIFT - 10);
+	ssize_t ret = queue_var_store(&max_sectors_kb, page, count);
+	int ra_kb;
+
+	if (max_sectors_kb > max_hw_sectors_kb || max_sectors_kb < page_kb)
+		return -EINVAL;
+	/*
+	 * Take the queue lock to update the readahead and max_sectors
+	 * values synchronously:
+	 */
+	spin_lock_irq(q->queue_lock);
+	/*
+	 * Trim readahead window as well, if necessary:
+	 */
+	ra_kb = q->backing_dev_info.ra_pages << (PAGE_CACHE_SHIFT - 10);
+	if (ra_kb > max_sectors_kb)
+		q->backing_dev_info.ra_pages =
+				max_sectors_kb >> (PAGE_CACHE_SHIFT - 10);
+
+	q->max_sectors = max_sectors_kb << 1;
+	spin_unlock_irq(q->queue_lock);
+
 	return ret;
 }
 
+static ssize_t queue_max_hw_sectors_show(struct request_queue *q, char *page)
+{
+	int max_hw_sectors_kb = q->max_hw_sectors >> 1;
+
+	return queue_var_show(max_hw_sectors_kb, (page));
+}
+
+
 static struct queue_sysfs_entry queue_requests_entry = {
 	.attr = {.name = "nr_requests", .mode = S_IRUGO | S_IWUSR },
 	.show = queue_requests_show,
@@ -3082,9 +3274,22 @@
 	.store = queue_ra_store,
 };
 
+static struct queue_sysfs_entry queue_max_sectors_entry = {
+	.attr = {.name = "max_sectors_kb", .mode = S_IRUGO | S_IWUSR },
+	.show = queue_max_sectors_show,
+	.store = queue_max_sectors_store,
+};
+
+static struct queue_sysfs_entry queue_max_hw_sectors_entry = {
+	.attr = {.name = "max_hw_sectors_kb", .mode = S_IRUGO },
+	.show = queue_max_hw_sectors_show,
+};
+
 static struct attribute *default_attrs[] = {
 	&queue_requests_entry.attr,
 	&queue_ra_entry.attr,
+	&queue_max_hw_sectors_entry.attr,
+	&queue_max_sectors_entry.attr,
 	NULL,
 };
 
diff -Nru a/drivers/block/nbd.c b/drivers/block/nbd.c
--- a/drivers/block/nbd.c	2004-10-18 14:56:19 -07:00
+++ b/drivers/block/nbd.c	2004-10-18 14:56:19 -07:00
@@ -128,23 +128,11 @@
 {
 	int uptodate = (req->errors == 0) ? 1 : 0;
 	request_queue_t *q = req->q;
-	struct nbd_device *lo = req->rq_disk->private_data;
 	unsigned long flags;
 
 	dprintk(DBG_BLKDEV, "%s: request %p: %s\n", req->rq_disk->disk_name,
 			req, uptodate? "done": "failed");
 
-	spin_lock(&lo->queue_lock);
-	while (req->ref_count > 1) { /* still in send */
-		spin_unlock(&lo->queue_lock);
-		printk(KERN_DEBUG "%s: request %p still in use (%d), waiting\n",
-		    lo->disk->disk_name, req, req->ref_count);
-		set_current_state(TASK_UNINTERRUPTIBLE);
-		schedule_timeout(HZ); /* wait a second */
-		spin_lock(&lo->queue_lock);
-	}
-	spin_unlock(&lo->queue_lock);
-
 	spin_lock_irqsave(q->queue_lock, flags);
 	if (!end_that_request_first(req, uptodate, req->nr_sectors)) {
 		end_that_request_last(req);
@@ -228,7 +216,7 @@
 	return result;
 }
 
-void nbd_send_req(struct nbd_device *lo, struct request *req)
+static int nbd_send_req(struct nbd_device *lo, struct request *req)
 {
 	int result, i, flags;
 	struct nbd_request request;
@@ -288,11 +276,11 @@
 		}
 	}
 	up(&lo->tx_lock);
-	return;
+	return 0;
 
 error_out:
 	up(&lo->tx_lock);
-	req->errors++;
+	return 1;
 }
 
 static struct request *nbd_find_request(struct nbd_device *lo, char *handle)
@@ -477,26 +465,19 @@
 		}
 
 		list_add(&req->queuelist, &lo->queue_head);
-		req->ref_count++; /* make sure req does not get freed */
 		spin_unlock(&lo->queue_lock);
 
-		nbd_send_req(lo, req);
-
-		if (req->errors) {
+		if (nbd_send_req(lo, req) != 0) {
 			printk(KERN_ERR "%s: Request send failed\n",
 					lo->disk->disk_name);
-			spin_lock(&lo->queue_lock);
-			list_del_init(&req->queuelist);
-			req->ref_count--;
-			spin_unlock(&lo->queue_lock);
-			nbd_end_request(req);
-			spin_lock_irq(q->queue_lock);
-			continue;
+			if (nbd_find_request(lo, (char *)&req) != NULL) {
+				/* we still own req */
+				req->errors++;
+				nbd_end_request(req);
+			} else /* we're racing with nbd_clear_que */
+				printk(KERN_DEBUG "nbd: can't find req\n");
 		}
 
-		spin_lock(&lo->queue_lock);
-		req->ref_count--;
-		spin_unlock(&lo->queue_lock);
 		spin_lock_irq(q->queue_lock);
 		continue;
 
diff -Nru a/drivers/block/rd.c b/drivers/block/rd.c
--- a/drivers/block/rd.c	2004-10-18 14:56:33 -07:00
+++ b/drivers/block/rd.c	2004-10-18 14:56:33 -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-10-18 14:57:04 -07:00
+++ b/drivers/block/scsi_ioctl.c	2004-10-18 14:57:04 -07:00
@@ -127,12 +127,16 @@
 		safe_for_read(MODE_SENSE),
 		safe_for_read(MODE_SENSE_10),
 		safe_for_read(START_STOP),
+		safe_for_read(GPCMD_VERIFY_10),
+		safe_for_read(VERIFY_16),
+		safe_for_read(READ_BUFFER),
 
 		/* Audio CD commands */
 		safe_for_read(GPCMD_PLAY_CD),
 		safe_for_read(GPCMD_PLAY_AUDIO_10),
 		safe_for_read(GPCMD_PLAY_AUDIO_MSF),
 		safe_for_read(GPCMD_PLAY_AUDIO_TI),
+		safe_for_read(GPCMD_PAUSE_RESUME),
 
 		/* CD/DVD data reading */
 		safe_for_read(GPCMD_READ_CD),
@@ -146,6 +150,12 @@
 		safe_for_read(GPCMD_READ_TOC_PMA_ATIP),
 		safe_for_read(GPCMD_REPORT_KEY),
 		safe_for_read(GPCMD_SCAN),
+		safe_for_read(GPCMD_GET_CONFIGURATION),
+		safe_for_read(GPCMD_READ_FORMAT_CAPACITIES),
+		safe_for_read(GPCMD_GET_EVENT_STATUS_NOTIFICATION),
+		safe_for_read(GPCMD_GET_PERFORMANCE),
+		safe_for_read(GPCMD_SEEK),
+		safe_for_read(GPCMD_STOP_PLAY_SCAN),
 
 		/* Basic writing commands */
 		safe_for_write(WRITE_6),
@@ -154,8 +164,25 @@
 		safe_for_write(WRITE_12),
 		safe_for_write(WRITE_VERIFY_12),
 		safe_for_write(WRITE_16),
-		safe_for_write(WRITE_BUFFER),
 		safe_for_write(WRITE_LONG),
+		safe_for_write(ERASE),
+		safe_for_write(GPCMD_MODE_SELECT_10),
+		safe_for_write(MODE_SELECT),
+		safe_for_write(GPCMD_BLANK),
+		safe_for_write(GPCMD_CLOSE_TRACK),
+		safe_for_write(GPCMD_FLUSH_CACHE),
+		safe_for_write(GPCMD_FORMAT_UNIT),
+		safe_for_write(GPCMD_REPAIR_RZONE_TRACK),
+		safe_for_write(GPCMD_RESERVE_RZONE_TRACK),
+		safe_for_write(GPCMD_SEND_DVD_STRUCTURE),
+		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),
+		safe_for_write(GPCMD_SET_STREAMING),
 	};
 	unsigned char type = cmd_type[cmd[0]];
 
@@ -511,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/sx8.c b/drivers/block/sx8.c
--- a/drivers/block/sx8.c	2004-10-18 14:57:20 -07:00
+++ b/drivers/block/sx8.c	2004-10-18 14:57:20 -07:00
@@ -242,7 +242,7 @@
 
 struct carm_host {
 	unsigned long			flags;
-	void				*mmio;
+	void				__iomem *mmio;
 	void				*shm;
 	dma_addr_t			shm_dma;
 
@@ -283,13 +283,13 @@
 };
 
 struct carm_response {
-	u32 ret_handle;
-	u32 status;
+	__le32 ret_handle;
+	__le32 status;
 }  __attribute__((packed));
 
 struct carm_msg_sg {
-	u32 start;
-	u32 len;
+	__le32 start;
+	__le32 len;
 }  __attribute__((packed));
 
 struct carm_msg_rw {
@@ -297,10 +297,10 @@
 	u8 id;
 	u8 sg_count;
 	u8 sg_type;
-	u32 handle;
-	u32 lba;
-	u16 lba_count;
-	u16 lba_high;
+	__le32 handle;
+	__le32 lba;
+	__le16 lba_count;
+	__le16 lba_high;
 	struct carm_msg_sg sg[32];
 }  __attribute__((packed));
 
@@ -309,15 +309,15 @@
 	u8 subtype;
 	u8 n_sg;
 	u8 sg_type;
-	u32 handle;
-	u32 addr;
-	u32 len;
-	u32 evt_pool;
-	u32 n_evt;
-	u32 rbuf_pool;
-	u32 n_rbuf;
-	u32 msg_pool;
-	u32 n_msg;
+	__le32 handle;
+	__le32 addr;
+	__le32 len;
+	__le32 evt_pool;
+	__le32 n_evt;
+	__le32 rbuf_pool;
+	__le32 n_rbuf;
+	__le32 msg_pool;
+	__le32 n_msg;
 	struct carm_msg_sg sg[8];
 }  __attribute__((packed));
 
@@ -326,8 +326,8 @@
 	u8 subtype;
 	u8 array_id;
 	u8 reserved1;
-	u32 handle;
-	u32 data_addr;
+	__le32 handle;
+	__le32 data_addr;
 	u32 reserved2;
 }  __attribute__((packed));
 
@@ -335,48 +335,48 @@
 	u8 type;
 	u8 subtype;
 	u16 reserved1;
-	u32 handle;
+	__le32 handle;
 	u32 reserved2;
-	u32 timestamp;
+	__le32 timestamp;
 }  __attribute__((packed));
 
 struct carm_msg_get_fw_ver {
 	u8 type;
 	u8 subtype;
 	u16 reserved1;
-	u32 handle;
-	u32 data_addr;
+	__le32 handle;
+	__le32 data_addr;
 	u32 reserved2;
 }  __attribute__((packed));
 
 struct carm_fw_ver {
-	u32 version;
+	__le32 version;
 	u8 features;
 	u8 reserved1;
 	u16 reserved2;
 }  __attribute__((packed));
 
 struct carm_array_info {
-	u32 size;
+	__le32 size;
 
-	u16 size_hi;
-	u16 stripe_size;
+	__le16 size_hi;
+	__le16 stripe_size;
 
-	u32 mode;
+	__le32 mode;
 
-	u16 stripe_blk_sz;
-	u16 reserved1;
+	__le16 stripe_blk_sz;
+	__le16 reserved1;
 
-	u16 cyl;
-	u16 head;
+	__le16 cyl;
+	__le16 head;
 
-	u16 sect;
+	__le16 sect;
 	u8 array_id;
 	u8 reserved2;
 
 	char name[40];
 
-	u32 array_status;
+	__le32 array_status;
 
 	/* device list continues beyond this point? */
 }  __attribute__((packed));
@@ -451,7 +451,7 @@
 	return -ENOENT;
 }
 
-static void carm_init_buckets(void *mmio)
+static void carm_init_buckets(void __iomem *mmio)
 {
 	unsigned int i;
 
@@ -474,7 +474,7 @@
 static int carm_send_msg(struct carm_host *host,
 			 struct carm_request *crq)
 {
-	void *mmio = host->mmio;
+	void __iomem *mmio = host->mmio;
 	u32 msg = (u32) carm_ref_msg_dma(host, crq->tag);
 	u32 cm_bucket = crq->msg_bucket;
 	u32 tmp;
@@ -965,7 +965,7 @@
 	port = &host->port[cur_port];
 
 	lo = (u64) le32_to_cpu(desc->size);
-	hi = (u64) le32_to_cpu(desc->size_hi);
+	hi = (u64) le16_to_cpu(desc->size_hi);
 
 	port->capacity = lo | (hi << 32);
 	port->dev_geom_head = le16_to_cpu(desc->head);
@@ -1060,7 +1060,7 @@
 }
 
 static inline void carm_handle_resp(struct carm_host *host,
-				    u32 ret_handle_le, u32 status)
+				    __le32 ret_handle_le, u32 status)
 {
 	u32 handle = le32_to_cpu(ret_handle_le);
 	unsigned int msg_idx;
@@ -1158,7 +1158,7 @@
 
 static inline void carm_handle_responses(struct carm_host *host)
 {
-	void *mmio = host->mmio;
+	void __iomem *mmio = host->mmio;
 	struct carm_response *resp = (struct carm_response *) host->shm;
 	unsigned int work = 0;
 	unsigned int idx = host->resp_idx % RMSG_Q_LEN;
@@ -1176,7 +1176,7 @@
 		else if ((status & (1 << 31)) == 0) {
 			VPRINTK("handling msg response on index %u\n", idx);
 			carm_handle_resp(host, resp[idx].ret_handle, status);
-			resp[idx].status = 0xffffffff;
+			resp[idx].status = cpu_to_le32(0xffffffff);
 		}
 
 		/* asynchronous events the hardware throws our way */
@@ -1185,7 +1185,7 @@
 			u8 evt_type = *evt_type_ptr;
 			printk(KERN_WARNING DRV_NAME "(%s): unhandled event type %d\n",
 			       pci_name(host->pdev), (int) evt_type);
-			resp[idx].status = 0xffffffff;
+			resp[idx].status = cpu_to_le32(0xffffffff);
 		}
 
 		idx = NEXT_RESP(idx);
@@ -1199,7 +1199,7 @@
 static irqreturn_t carm_interrupt(int irq, void *__host, struct pt_regs *regs)
 {
 	struct carm_host *host = __host;
-	void *mmio;
+	void __iomem *mmio;
 	u32 mask;
 	int handled = 0;
 	unsigned long flags;
@@ -1364,7 +1364,7 @@
 		schedule_work(&host->fsm_task);
 }
 
-static int carm_init_wait(void *mmio, u32 bits, unsigned int test_bit)
+static int carm_init_wait(void __iomem *mmio, u32 bits, unsigned int test_bit)
 {
 	unsigned int i;
 
@@ -1390,19 +1390,19 @@
 
 static void carm_init_responses(struct carm_host *host)
 {
-	void *mmio = host->mmio;
+	void __iomem *mmio = host->mmio;
 	unsigned int i;
 	struct carm_response *resp = (struct carm_response *) host->shm;
 
 	for (i = 0; i < RMSG_Q_LEN; i++)
-		resp[i].status = 0xffffffff;
+		resp[i].status = cpu_to_le32(0xffffffff);
 
 	writel(0, mmio + CARM_RESP_IDX);
 }
 
 static int carm_init_host(struct carm_host *host)
 {
-	void *mmio = host->mmio;
+	void __iomem *mmio = host->mmio;
 	u32 tmp;
 	u8 tmp8;
 	int rc;
@@ -1414,7 +1414,7 @@
 	tmp8 = readb(mmio + CARM_INITC);
 	if (tmp8 & 0x01) {
 		tmp8 &= ~0x01;
-		writeb(tmp8, CARM_INITC);
+		writeb(tmp8, mmio + CARM_INITC);
 		readb(mmio + CARM_INITC);	/* flush */
 
 		DPRINTK("snooze...\n");
diff -Nru a/drivers/block/ub.c b/drivers/block/ub.c
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/drivers/block/ub.c	2004-10-18 14:57:24 -07:00
@@ -0,0 +1,2097 @@
+/*
+ * The low performance USB storage driver (ub).
+ *
+ * Copyright (c) 1999, 2000 Matthew Dharm (mdharm-usb@one-eyed-alien.net)
+ * Copyright (C) 2004 Pete Zaitcev (zaitcev@yahoo.com)
+ *
+ * This work is a part of Linux kernel, is derived from it,
+ * and is not licensed separately. See file COPYING for details.
+ *
+ * TODO (sorted by decreasing priority)
+ *  -- ZIP does "ub: resid 18 len 0 act 0" and whole transport quits (toggles?)
+ *  -- set readonly flag for CDs, set removable flag for CF readers
+ *  -- do inquiry and verify we got a disk and not a tape (for LUN mismatch)
+ *  -- support pphaneuf's SDDR-75 with two LUNs (also broken capacity...)
+ *  -- special case some senses, e.g. 3a/0 -> no media present, reduce retries
+ *  -- do something about spin-down devices, they are extremely dangerous
+ *     (ZIP is one. Needs spin-up command as well.)
+ *  -- verify the 13 conditions and do bulk resets
+ *  -- normal pool of commands instead of cmdv[]?
+ *  -- kill last_pipe and simply do two-state clearing on both pipes
+ *  -- verify protocol (bulk) from USB descriptors (maybe...)
+ *  -- highmem and sg
+ *  -- move top_sense and work_bcs into separate allocations (if they survive)
+ *     for cache purists and esoteric architectures.
+ *  -- prune comments, they are too volumnous
+ *  -- Exterminate P3 printks
+ *  -- Resove XXX's
+ */
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/usb.h>
+#include <linux/blkdev.h>
+#include <linux/devfs_fs_kernel.h>
+#include <linux/timer.h>
+#include <scsi/scsi.h>
+
+#define DRV_NAME "ub"
+#define DEVFS_NAME DRV_NAME
+
+#define UB_MAJOR 125	/* Stolen from Experimental range for a week - XXX */
+
+/*
+ * Definitions which have to be scattered once we understand the layout better.
+ */
+
+/* Transport (despite PR in the name) */
+#define US_PR_BULK	0x50		/* bulk only */
+
+/* Protocol */
+#define US_SC_SCSI	0x06		/* Transparent */
+
+/*
+ */
+#define UB_MINORS_PER_MAJOR	8
+
+#define UB_MAX_CDB_SIZE      16		/* Corresponds to Bulk */
+
+#define UB_SENSE_SIZE  18
+
+/*
+ */
+
+/* command block wrapper */
+struct bulk_cb_wrap {
+	u32	Signature;		/* contains 'USBC' */
+	u32	Tag;			/* unique per command id */
+	u32	DataTransferLength;	/* size of data */
+	u8	Flags;			/* direction in bit 0 */
+	u8	Lun;			/* LUN normally 0 */
+	u8	Length;			/* of of the CDB */
+	u8	CDB[UB_MAX_CDB_SIZE];	/* max command */
+};
+
+#define US_BULK_CB_WRAP_LEN	31
+#define US_BULK_CB_SIGN		0x43425355	/*spells out USBC */
+#define US_BULK_FLAG_IN		1
+#define US_BULK_FLAG_OUT	0
+
+/* command status wrapper */
+struct bulk_cs_wrap {
+	u32	Signature;		/* should = 'USBS' */
+	u32	Tag;			/* same as original command */
+	u32	Residue;		/* amount not transferred */
+	u8	Status;			/* see below */
+};
+
+#define US_BULK_CS_WRAP_LEN	13
+#define US_BULK_CS_SIGN		0x53425355	/* spells out 'USBS' */
+/* This is for Olympus Camedia digital cameras */
+#define US_BULK_CS_OLYMPUS_SIGN	0x55425355	/* spells out 'USBU' */
+#define US_BULK_STAT_OK		0
+#define US_BULK_STAT_FAIL	1
+#define US_BULK_STAT_PHASE	2
+
+/* bulk-only class specific requests */
+#define US_BULK_RESET_REQUEST	0xff
+#define US_BULK_GET_MAX_LUN	0xfe
+
+/*
+ */
+struct ub_dev;
+
+#define UB_MAX_REQ_SG	1
+#define UB_MAX_SECTORS 64
+
+/*
+ * 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 */
+
+/*
+ * An instance of a SCSI command in transit.
+ */
+#define UB_DIR_NONE	0
+#define UB_DIR_READ	1
+#define UB_DIR_ILLEGAL2	2
+#define UB_DIR_WRITE	3
+
+#define UB_DIR_CHAR(c)  (((c)==UB_DIR_WRITE)? 'w': \
+			 (((c)==UB_DIR_READ)? 'r': 'n'))
+
+enum ub_scsi_cmd_state {
+	UB_CMDST_INIT,			/* Initial state */
+	UB_CMDST_CMD,			/* Command submitted */
+	UB_CMDST_DATA,			/* Data phase */
+	UB_CMDST_CLR2STS,		/* Clearing before requesting status */
+	UB_CMDST_STAT,			/* Status phase */
+	UB_CMDST_CLEAR,			/* Clearing a stall (halt, actually) */
+	UB_CMDST_SENSE,			/* Sending Request Sense */
+	UB_CMDST_DONE			/* Final state */
+};
+
+static char *ub_scsi_cmd_stname[] = {
+	".  ",
+	"Cmd",
+	"dat",
+	"c2s",
+	"sts",
+	"clr",
+	"Sen",
+	"fin"
+};
+
+struct ub_scsi_cmd {
+	unsigned char cdb[UB_MAX_CDB_SIZE];
+	unsigned char cdb_len;
+
+	unsigned char dir;		/* 0 - none, 1 - read, 3 - write. */
+	unsigned char trace_index;
+	enum ub_scsi_cmd_state state;
+	unsigned int tag;
+	struct ub_scsi_cmd *next;
+
+	int error;			/* Return code - valid upon done */
+	int act_len;			/* Return size */
+
+	int stat_count;			/* Retries getting status. */
+
+	/*
+	 * We do not support transfers from highmem pages
+	 * because the underlying USB framework does not do what we need.
+	 */
+	char *data;			/* Requested buffer */
+	unsigned int len;		/* Requested length */
+	// struct scatterlist sgv[UB_MAX_REQ_SG];
+
+	void (*done)(struct ub_dev *, struct ub_scsi_cmd *);
+	void *back;
+};
+
+/*
+ */
+struct ub_capacity {
+	unsigned long nsec;		/* Linux size - 512 byte sectors */
+	unsigned int bsize;		/* Linux hardsect_size */
+	unsigned int bshift;		/* Shift between 512 and hard sects */
+};
+
+/*
+ * The SCSI command tracing structure.
+ */
+
+#define SCMD_ST_HIST_SZ   8
+#define SCMD_TRACE_SZ    15	/* No more than 256 (trace_index) */
+
+struct ub_scsi_cmd_trace {
+	int hcur;
+	unsigned int tag;
+	unsigned int req_size, act_size;
+	unsigned char op;
+	unsigned char dir;
+	unsigned char key, asc, ascq;
+	char st_hst[SCMD_ST_HIST_SZ];	
+};
+
+struct ub_scsi_trace {
+	int cur;
+	struct ub_scsi_cmd_trace vec[SCMD_TRACE_SZ];
+};
+
+/*
+ * This is a direct take-off from linux/include/completion.h
+ * The difference is that I do not wait on this thing, just poll.
+ * When I want to wait (ub_probe), I just use the stock completion.
+ *
+ * Note that INIT_COMPLETION takes no lock. It is correct. But why
+ * in the bloody hell that thing takes struct instead of pointer to struct
+ * is quite beyond me. I just copied it from the stock completion.
+ */
+struct ub_completion {
+	unsigned int done;
+	spinlock_t lock;
+};
+
+static inline void ub_init_completion(struct ub_completion *x)
+{
+	x->done = 0;
+	spin_lock_init(&x->lock);
+}
+
+#define UB_INIT_COMPLETION(x)	((x).done = 0)
+
+static void ub_complete(struct ub_completion *x)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&x->lock, flags);
+	x->done++;
+	spin_unlock_irqrestore(&x->lock, flags);
+}
+
+static int ub_is_completed(struct ub_completion *x)
+{
+	unsigned long flags;
+	int ret;
+
+	spin_lock_irqsave(&x->lock, flags);
+	ret = x->done;
+	spin_unlock_irqrestore(&x->lock, flags);
+	return ret;
+}
+
+/*
+ */
+struct ub_scsi_cmd_queue {
+	int qlen, qmax;
+	struct ub_scsi_cmd *head, *tail;
+};
+
+/*
+ * The UB device instance.
+ */
+struct ub_dev {
+	spinlock_t lock;
+	int id;				/* Number among ub's */
+	atomic_t poison;		/* The USB device is disconnected */
+	int openc;			/* protected by ub_lock! */
+					/* kref is too implicit for our taste */
+	unsigned int tagcnt;
+	int changed;			/* Media was changed */
+	int removable;
+	int readonly;
+	char name[8];
+	struct usb_device *dev;
+	struct usb_interface *intf;
+
+	struct ub_capacity capacity; 
+	struct gendisk *disk;
+
+	unsigned int send_bulk_pipe;	/* cached pipe values */
+	unsigned int recv_bulk_pipe;
+	unsigned int send_ctrl_pipe;
+	unsigned int recv_ctrl_pipe;
+
+	struct tasklet_struct tasklet;
+
+	/* XXX Use Ingo's mempool (once we have more than one) */
+	int cmda[1];
+	struct ub_scsi_cmd cmdv[1];
+
+	struct ub_scsi_cmd_queue cmd_queue;
+	struct ub_scsi_cmd top_rqs_cmd;	/* REQUEST SENSE */
+	unsigned char top_sense[UB_SENSE_SIZE];
+
+	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;
+	struct usb_ctrlrequest work_cr;
+
+	struct ub_scsi_trace tr;
+};
+
+/*
+ */
+static void ub_rw_cmd_done(struct ub_dev *sc, struct ub_scsi_cmd *cmd);
+static void ub_end_rq(struct request *rq, int uptodate);
+static int ub_submit_scsi(struct ub_dev *sc, struct ub_scsi_cmd *cmd);
+static void ub_urb_complete(struct urb *urb, struct pt_regs *pt);
+static void ub_scsi_action(unsigned long _dev);
+static void ub_scsi_dispatch(struct ub_dev *sc);
+static void ub_scsi_urb_compl(struct ub_dev *sc, struct ub_scsi_cmd *cmd);
+static void ub_state_done(struct ub_dev *sc, struct ub_scsi_cmd *cmd, int rc);
+static void ub_state_stat(struct ub_dev *sc, struct ub_scsi_cmd *cmd);
+static void ub_state_sense(struct ub_dev *sc, struct ub_scsi_cmd *cmd);
+static int ub_submit_clear_stall(struct ub_dev *sc, struct ub_scsi_cmd *cmd,
+    int stalled_pipe);
+static void ub_top_sense_done(struct ub_dev *sc, struct ub_scsi_cmd *scmd);
+static int ub_sync_tur(struct ub_dev *sc);
+static int ub_sync_read_cap(struct ub_dev *sc, struct ub_capacity *ret);
+
+/*
+ */
+static struct usb_device_id ub_usb_ids[] = {
+	// { USB_DEVICE_VER(0x0781, 0x0002, 0x0009, 0x0009) },	/* SDDR-31 */
+	{ USB_INTERFACE_INFO(USB_CLASS_MASS_STORAGE, US_SC_SCSI, US_PR_BULK) },
+	{ }
+};
+
+MODULE_DEVICE_TABLE(usb, ub_usb_ids);
+
+/*
+ * Find me a way to identify "next free minor" for add_disk(),
+ * and the array disappears the next day. However, the number of
+ * hosts has something to do with the naming and /proc/partitions.
+ * This has to be thought out in detail before changing.
+ * If UB_MAX_HOST was 1000, we'd use a bitmap. Or a better data structure.
+ */
+#define UB_MAX_HOSTS  26
+static char ub_hostv[UB_MAX_HOSTS];
+static spinlock_t ub_lock = SPIN_LOCK_UNLOCKED;	/* Locks globals and ->openc */
+
+/*
+ * The SCSI command tracing procedures.
+ */
+
+static void ub_cmdtr_new(struct ub_dev *sc, struct ub_scsi_cmd *cmd)
+{
+	int n;
+	struct ub_scsi_cmd_trace *t;
+
+	if ((n = sc->tr.cur + 1) == SCMD_TRACE_SZ) n = 0;
+	t = &sc->tr.vec[n];
+
+	memset(t, 0, sizeof(struct ub_scsi_cmd_trace));
+	t->tag = cmd->tag;
+	t->op = cmd->cdb[0];
+	t->dir = cmd->dir;
+	t->req_size = cmd->len;
+	t->st_hst[0] = cmd->state;
+
+	sc->tr.cur = n;
+	cmd->trace_index = n;
+}
+
+static void ub_cmdtr_state(struct ub_dev *sc, struct ub_scsi_cmd *cmd)
+{
+	int n;
+	struct ub_scsi_cmd_trace *t;
+
+	t = &sc->tr.vec[cmd->trace_index];
+	if (t->tag == cmd->tag) {
+		if ((n = t->hcur + 1) == SCMD_ST_HIST_SZ) n = 0;
+		t->st_hst[n] = cmd->state;
+		t->hcur = n;
+	}
+}
+
+static void ub_cmdtr_act_len(struct ub_dev *sc, struct ub_scsi_cmd *cmd)
+{
+	struct ub_scsi_cmd_trace *t;
+
+	t = &sc->tr.vec[cmd->trace_index];
+	if (t->tag == cmd->tag)
+		t->act_size = cmd->act_len;
+}
+
+static void ub_cmdtr_sense(struct ub_dev *sc, struct ub_scsi_cmd *cmd,
+    unsigned char *sense)
+{
+	struct ub_scsi_cmd_trace *t;
+
+	t = &sc->tr.vec[cmd->trace_index];
+	if (t->tag == cmd->tag) {
+		t->key = sense[2] & 0x0F;
+		t->asc = sense[12];
+		t->ascq = sense[13];
+	}
+}
+
+static ssize_t ub_diag_show(struct device *dev, char *page)
+{
+	struct usb_interface *intf;
+	struct ub_dev *sc;
+	int cnt;
+	unsigned long flags;
+	int nc, nh;
+	int i, j;
+	struct ub_scsi_cmd_trace *t;
+
+	intf = to_usb_interface(dev);
+	sc = usb_get_intfdata(intf);
+	if (sc == NULL)
+		return 0;
+
+	cnt = 0;
+	spin_lock_irqsave(&sc->lock, flags);
+
+	cnt += sprintf(page + cnt,
+	    "qlen %d qmax %d changed %d removable %d readonly %d\n",
+	    sc->cmd_queue.qlen, sc->cmd_queue.qmax,
+	    sc->changed, sc->removable, sc->readonly);
+
+	if ((nc = sc->tr.cur + 1) == SCMD_TRACE_SZ) nc = 0;
+	for (j = 0; j < SCMD_TRACE_SZ; j++) {
+		t = &sc->tr.vec[nc];
+
+		cnt += sprintf(page + cnt, "%08x %02x", t->tag, t->op);
+		if (t->op == REQUEST_SENSE) {
+			cnt += sprintf(page + cnt, " [sense %x %02x %02x]",
+					t->key, t->asc, t->ascq);
+		} else {
+			cnt += sprintf(page + cnt, " %c", UB_DIR_CHAR(t->dir));
+			cnt += sprintf(page + cnt, " [%5d %5d]",
+					t->req_size, t->act_size);
+		}
+		if ((nh = t->hcur + 1) == SCMD_ST_HIST_SZ) nh = 0;
+		for (i = 0; i < SCMD_ST_HIST_SZ; i++) {
+			cnt += sprintf(page + cnt, " %s",
+					ub_scsi_cmd_stname[(int)t->st_hst[nh]]);
+			if (++nh == SCMD_ST_HIST_SZ) nh = 0;
+		}
+		cnt += sprintf(page + cnt, "\n");
+
+		if (++nc == SCMD_TRACE_SZ) nc = 0;
+	}
+
+	spin_unlock_irqrestore(&sc->lock, flags);
+	return cnt;
+}
+
+static DEVICE_ATTR(diag, S_IRUGO, ub_diag_show, NULL); /* N.B. World readable */
+
+/*
+ * The id allocator.
+ *
+ * This also stores the host for indexing by minor, which is somewhat dirty.
+ */
+static int ub_id_get(void)
+{
+	unsigned long flags;
+	int i;
+
+	spin_lock_irqsave(&ub_lock, flags);
+	for (i = 0; i < UB_MAX_HOSTS; i++) {
+		if (ub_hostv[i] == 0) {
+			ub_hostv[i] = 1;
+			spin_unlock_irqrestore(&ub_lock, flags);
+			return i;
+		}
+	}
+	spin_unlock_irqrestore(&ub_lock, flags);
+	return -1;
+}
+
+static void ub_id_put(int id)
+{
+
+	if (id < 0 || id >= UB_MAX_HOSTS) {
+		printk(KERN_ERR DRV_NAME ": bad host ID %d\n", id);
+		return;
+	}
+	if (ub_hostv[id] == 0) {
+		printk(KERN_ERR DRV_NAME ": freeing free host ID %d\n", id);
+		return;
+	}
+	ub_hostv[id] = 0;
+}
+
+/*
+ * Final cleanup and deallocation.
+ * This must be called with ub_lock taken.
+ */
+static void ub_cleanup(struct ub_dev *sc)
+{
+	ub_id_put(sc->id);
+	kfree(sc);
+}
+
+/*
+ * The "command allocator".
+ */
+static struct ub_scsi_cmd *ub_get_cmd(struct ub_dev *sc)
+{
+	struct ub_scsi_cmd *ret;
+
+	if (sc->cmda[0])
+		return NULL;
+	ret = &sc->cmdv[0];
+	sc->cmda[0] = 1;
+	return ret;
+}
+
+static void ub_put_cmd(struct ub_dev *sc, struct ub_scsi_cmd *cmd)
+{
+	if (cmd != &sc->cmdv[0]) {
+		printk(KERN_WARNING "%s: releasing a foreign cmd %p\n",
+		    sc->name, cmd);
+		return;
+	}
+	if (!sc->cmda[0]) {
+		printk(KERN_WARNING "%s: releasing a free cmd\n", sc->name);
+		return;
+	}
+	sc->cmda[0] = 0;
+}
+
+/*
+ * The command queue.
+ */
+static void ub_cmdq_add(struct ub_dev *sc, struct ub_scsi_cmd *cmd)
+{
+	struct ub_scsi_cmd_queue *t = &sc->cmd_queue;
+
+	if (t->qlen++ == 0) {
+		t->head = cmd;
+		t->tail = cmd;
+	} else {
+		t->tail->next = cmd;
+		t->tail = cmd;
+	}
+
+	if (t->qlen > t->qmax)
+		t->qmax = t->qlen;
+}
+
+static void ub_cmdq_insert(struct ub_dev *sc, struct ub_scsi_cmd *cmd)
+{
+	struct ub_scsi_cmd_queue *t = &sc->cmd_queue;
+
+	if (t->qlen++ == 0) {
+		t->head = cmd;
+		t->tail = cmd;
+	} else {
+		cmd->next = t->head;
+		t->head = cmd;
+	}
+
+	if (t->qlen > t->qmax)
+		t->qmax = t->qlen;
+}
+
+static struct ub_scsi_cmd *ub_cmdq_pop(struct ub_dev *sc)
+{
+	struct ub_scsi_cmd_queue *t = &sc->cmd_queue;
+	struct ub_scsi_cmd *cmd;
+
+	if (t->qlen == 0)
+		return NULL;
+	if (--t->qlen == 0)
+		t->tail = NULL;
+	cmd = t->head;
+	t->head = cmd->next;
+	cmd->next = NULL;
+	return cmd;
+}
+
+#define ub_cmdq_peek(sc)  ((sc)->cmd_queue.head)
+
+/*
+ * The request function is our main entry point
+ */
+
+static inline int ub_bd_rq_fn_1(request_queue_t *q)
+{
+#if 0
+	int writing = 0, pci_dir, i, n_elem;
+	u32 tmp;
+	unsigned int msg_size;
+#endif
+	struct ub_dev *sc = q->queuedata;
+	struct request *rq;
+#if 0 /* We use rq->buffer for now */
+	struct scatterlist *sg;
+	int n_elem;
+#endif
+	struct ub_scsi_cmd *cmd;
+	int ub_dir;
+	unsigned int block, nblks;
+	int rc;
+
+	if ((rq = elv_next_request(q)) == NULL)
+		return 1;
+
+	if (atomic_read(&sc->poison) || sc->changed) {
+		blkdev_dequeue_request(rq);
+		ub_end_rq(rq, 0);
+		return 0;
+	}
+
+	if ((cmd = ub_get_cmd(sc)) == NULL) {
+		blk_stop_queue(q);
+		return 1;
+	}
+
+	blkdev_dequeue_request(rq);
+
+	if (rq_data_dir(rq) == WRITE)
+		ub_dir = UB_DIR_WRITE;
+	else
+		ub_dir = UB_DIR_READ;
+
+	/*
+	 * get scatterlist from block layer
+	 */
+#if 0 /* We use rq->buffer for now */
+	sg = &cmd->sgv[0];
+	n_elem = blk_rq_map_sg(q, rq, sg);
+	if (n_elem <= 0) {
+		ub_put_cmd(sc, cmd);
+		ub_end_rq(rq, 0);
+		blk_start_queue(q);
+		return 0;		/* request with no s/g entries? */
+	}
+
+	if (n_elem != 1) {		/* Paranoia */
+		printk(KERN_WARNING "%s: request with %d segments\n",
+		    sc->name, n_elem);
+		ub_put_cmd(sc, cmd);
+		ub_end_rq(rq, 0);
+		blk_start_queue(q);
+		return 0;
+	}
+#endif
+	/*
+	 * XXX Unfortunately, this check does not work. It is quite possible
+	 * to get bogus non-null rq->buffer if you allow sg by mistake.
+	 */
+	if (rq->buffer == NULL) {
+		/*
+		 * This must not happen if we set the queue right.
+		 * The block level must create bounce buffers for us.
+		 */
+		static int do_print = 1;
+		if (do_print) {
+			printk(KERN_WARNING "%s: unmapped request\n", sc->name);
+			do_print = 0;
+		}
+		ub_put_cmd(sc, cmd);
+		ub_end_rq(rq, 0);
+		blk_start_queue(q);
+		return 0;
+	}
+
+	/*
+	 * build the command
+	 */
+	block = rq->sector;
+	nblks = rq->nr_sectors;
+
+	memset(cmd, 0, sizeof(struct ub_scsi_cmd));
+	cmd->cdb[0] = (ub_dir == UB_DIR_READ)? READ_10: WRITE_10;
+	/* 10-byte uses 4 bytes of LBA: 2147483648KB, 2097152MB, 2048GB */
+	cmd->cdb[2] = block >> 24;
+	cmd->cdb[3] = block >> 16;
+	cmd->cdb[4] = block >> 8;
+	cmd->cdb[5] = block;
+	cmd->cdb[7] = nblks >> 8;
+	cmd->cdb[8] = nblks;
+	cmd->cdb_len = 10;
+	cmd->dir = ub_dir;
+	cmd->state = UB_CMDST_INIT;
+	cmd->data = rq->buffer;
+	cmd->len = nblks * 512;
+	cmd->done = ub_rw_cmd_done;
+	cmd->back = rq;
+
+	cmd->tag = sc->tagcnt++;
+	if ((rc = ub_submit_scsi(sc, cmd)) != 0) {
+		ub_put_cmd(sc, cmd);
+		ub_end_rq(rq, 0);
+		blk_start_queue(q);
+		return 0;
+	}
+
+	return 0;
+}
+
+static void ub_bd_rq_fn(request_queue_t *q)
+{
+	do { } while (ub_bd_rq_fn_1(q) == 0);
+}
+
+static void ub_rw_cmd_done(struct ub_dev *sc, struct ub_scsi_cmd *cmd)
+{
+	struct request *rq = cmd->back;
+	struct gendisk *disk = sc->disk;
+	request_queue_t *q = disk->queue;
+	int uptodate;
+
+	if (cmd->error == 0)
+		uptodate = 1;
+	else
+		uptodate = 0;
+
+	ub_put_cmd(sc, cmd);
+	ub_end_rq(rq, uptodate);
+	blk_start_queue(q);
+}
+
+static void ub_end_rq(struct request *rq, int uptodate)
+{
+	int rc;
+
+	rc = end_that_request_first(rq, uptodate, rq->hard_nr_sectors);
+	// assert(rc == 0);
+	end_that_request_last(rq);
+}
+
+/*
+ * Submit a regular SCSI operation (not an auto-sense).
+ *
+ * The Iron Law of Good Submit Routine is:
+ * Zero return - callback is done, Nonzero return - callback is not done.
+ * No exceptions.
+ *
+ * Host is assumed locked.
+ *
+ * XXX We only support Bulk for the moment.
+ */
+static int ub_submit_scsi(struct ub_dev *sc, struct ub_scsi_cmd *cmd)
+{
+
+	if (cmd->state != UB_CMDST_INIT ||
+	    (cmd->dir != UB_DIR_NONE && cmd->len == 0)) {
+		return -EINVAL;
+	}
+
+	ub_cmdq_add(sc, cmd);
+	/*
+	 * We can call ub_scsi_dispatch(sc) right away here, but it's a little
+	 * safer to jump to a tasklet, in case upper layers do something silly.
+	 */
+	tasklet_schedule(&sc->tasklet);
+	return 0;
+}
+
+/*
+ * Submit the first URB for the queued command.
+ * This function does not deal with queueing in any way.
+ */
+static int ub_scsi_cmd_start(struct ub_dev *sc, struct ub_scsi_cmd *cmd)
+{
+	struct bulk_cb_wrap *bcb;
+	int rc;
+
+	bcb = &sc->work_bcb;
+
+	/* set up the command wrapper */
+	bcb->Signature = cpu_to_le32(US_BULK_CB_SIGN);
+	bcb->Tag = cmd->tag;		/* Endianness is not important */
+	bcb->DataTransferLength = cpu_to_le32(cmd->len);
+	bcb->Flags = (cmd->dir == UB_DIR_READ) ? 0x80 : 0;
+	bcb->Lun = 0;			/* No multi-LUN yet */
+	bcb->Length = cmd->cdb_len;
+
+	/* copy the command payload */
+	memcpy(bcb->CDB, cmd->cdb, UB_MAX_CDB_SIZE);
+
+	UB_INIT_COMPLETION(sc->work_done);
+
+	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.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;
+	}
+
+	cmd->state = UB_CMDST_CMD;
+	ub_cmdtr_state(sc, cmd);
+	return 0;
+}
+
+/*
+ * 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
+ * the sc->lock taken) and from an interrupt (while we do NOT have
+ * the sc->lock taken). Therefore, bounce this off to a tasklet.
+ */
+static void ub_urb_complete(struct urb *urb, struct pt_regs *pt)
+{
+	struct ub_dev *sc = urb->context;
+
+	ub_complete(&sc->work_done);
+	tasklet_schedule(&sc->tasklet);
+}
+
+static void ub_scsi_action(unsigned long _dev)
+{
+	struct ub_dev *sc = (struct ub_dev *) _dev;
+	unsigned long flags;
+
+	spin_lock_irqsave(&sc->lock, flags);
+	ub_scsi_dispatch(sc);
+	spin_unlock_irqrestore(&sc->lock, flags);
+}
+
+static void ub_scsi_dispatch(struct ub_dev *sc)
+{
+	struct ub_scsi_cmd *cmd;
+	int rc;
+
+	while ((cmd = ub_cmdq_peek(sc)) != NULL) {
+		if (cmd->state == UB_CMDST_DONE) {
+			ub_cmdq_pop(sc);
+			(*cmd->done)(sc, cmd);
+		} else if (cmd->state == UB_CMDST_INIT) {
+			ub_cmdtr_new(sc, cmd);
+			if ((rc = ub_scsi_cmd_start(sc, cmd)) == 0)
+				break;
+			cmd->error = rc;
+			cmd->state = UB_CMDST_DONE;
+			ub_cmdtr_state(sc, cmd);
+		} else {
+			if (!ub_is_completed(&sc->work_done))
+				break;
+			ub_scsi_urb_compl(sc, cmd);
+		}
+	}
+}
+
+static void ub_scsi_urb_compl(struct ub_dev *sc, struct ub_scsi_cmd *cmd)
+{
+	struct urb *urb = &sc->work_urb;
+	struct bulk_cs_wrap *bcs;
+	int pipe;
+	int rc;
+
+/* P3 */ /** printk("ub: urb status %d pipe 0x%08x len %d act %d\n",
+ urb->status, urb->pipe, urb->transfer_buffer_length, urb->actual_length); **/
+
+	if (atomic_read(&sc->poison)) {
+		/* A little too simplistic, I feel... */
+		goto Bad_End;
+	}
+
+	if (cmd->state == UB_CMDST_CLEAR) {
+		if (urb->status == -EPIPE) {
+			/*
+			 * STALL while clearning STALL.
+			 * A STALL is illegal on a control pipe!
+			 * XXX Might try to reset the device here and retry.
+			 */
+			printk(KERN_NOTICE "%s: "
+			    "stall on control pipe for device %u\n",
+			    sc->name, sc->dev->devnum);
+			goto Bad_End;
+		}
+
+		/*
+		 * We ignore the result for the halt clear.
+		 */
+
+		/* reset the endpoint toggle */
+		usb_settoggle(sc->dev, usb_pipeendpoint(sc->last_pipe),
+			usb_pipeout(sc->last_pipe), 0);
+
+		ub_state_sense(sc, cmd);
+
+	} else if (cmd->state == UB_CMDST_CLR2STS) {
+		if (urb->status == -EPIPE) {
+			/*
+			 * STALL while clearning STALL.
+			 * A STALL is illegal on a control pipe!
+			 * XXX Might try to reset the device here and retry.
+			 */
+			printk(KERN_NOTICE "%s: "
+			    "stall on control pipe for device %u\n",
+			    sc->name, sc->dev->devnum);
+			goto Bad_End;
+		}
+
+		/*
+		 * We ignore the result for the halt clear.
+		 */
+
+		/* reset the endpoint toggle */
+		usb_settoggle(sc->dev, usb_pipeendpoint(sc->last_pipe),
+			usb_pipeout(sc->last_pipe), 0);
+
+		ub_state_stat(sc, cmd);
+
+	} else if (cmd->state == UB_CMDST_CMD) {
+		if (urb->status == -EPIPE) {
+			rc = ub_submit_clear_stall(sc, cmd, sc->last_pipe);
+			if (rc != 0) {
+				printk(KERN_NOTICE "%s: "
+				    "unable to submit clear for device %u (%d)\n",
+				    sc->name, sc->dev->devnum, rc);
+				/*
+				 * This is typically ENOMEM or some other such shit.
+				 * Retrying is pointless. Just do Bad End on it...
+				 */
+				goto Bad_End;
+			}
+			cmd->state = UB_CMDST_CLEAR;
+			ub_cmdtr_state(sc, cmd);
+			return;
+		}
+		if (urb->status != 0)
+			goto Bad_End;
+		if (urb->actual_length != US_BULK_CB_WRAP_LEN) {
+			/* XXX Must do reset here to unconfuse the device */
+			goto Bad_End;
+		}
+
+		if (cmd->dir == UB_DIR_NONE) {
+			ub_state_stat(sc, cmd);
+			return;
+		}
+
+		UB_INIT_COMPLETION(sc->work_done);
+
+		if (cmd->dir == UB_DIR_READ)
+			pipe = sc->recv_bulk_pipe;
+		else
+			pipe = sc->send_bulk_pipe;
+		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.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;
+		}
+
+		cmd->state = UB_CMDST_DATA;
+		ub_cmdtr_state(sc, cmd);
+
+	} else if (cmd->state == UB_CMDST_DATA) {
+		if (urb->status == -EPIPE) {
+			rc = ub_submit_clear_stall(sc, cmd, sc->last_pipe);
+			if (rc != 0) {
+				printk(KERN_NOTICE "%s: "
+				    "unable to submit clear for device %u (%d)\n",
+				    sc->name, sc->dev->devnum, rc);
+				/*
+				 * This is typically ENOMEM or some other such shit.
+				 * Retrying is pointless. Just do Bad End on it...
+				 */
+				goto Bad_End;
+			}
+			cmd->state = UB_CMDST_CLR2STS;
+			ub_cmdtr_state(sc, cmd);
+			return;
+		}
+		if (urb->status == -EOVERFLOW) {
+			/*
+			 * A babble? Failure, but we must transfer CSW now.
+			 */
+			cmd->error = -EOVERFLOW;	/* A cheap trick... */
+		} else {
+			if (urb->status != 0)
+				goto Bad_End;
+		}
+
+		cmd->act_len = urb->actual_length;
+		ub_cmdtr_act_len(sc, cmd);
+
+		ub_state_stat(sc, cmd);
+
+	} else if (cmd->state == UB_CMDST_STAT) {
+		if (urb->status == -EPIPE) {
+			rc = ub_submit_clear_stall(sc, cmd, sc->last_pipe);
+			if (rc != 0) {
+				printk(KERN_NOTICE "%s: "
+				    "unable to submit clear for device %u (%d)\n",
+				    sc->name, sc->dev->devnum, rc);
+				/*
+				 * This is typically ENOMEM or some other such shit.
+				 * Retrying is pointless. Just do Bad End on it...
+				 */
+				goto Bad_End;
+			}
+			cmd->state = UB_CMDST_CLEAR;
+			ub_cmdtr_state(sc, cmd);
+			return;
+		}
+		if (urb->status != 0)
+			goto Bad_End;
+
+		if (urb->actual_length == 0) {
+			/*
+			 * Some broken devices add unnecessary zero-length
+			 * packets to the end of their data transfers.
+			 * Such packets show up as 0-length CSWs. If we
+			 * encounter such a thing, try to read the CSW again.
+			 */
+			if (++cmd->stat_count >= 4) {
+				printk(KERN_NOTICE "%s: "
+				    "unable to get CSW on device %u\n",
+				    sc->name, sc->dev->devnum);
+				goto Bad_End;
+			}
+
+			/*
+			 * ub_state_stat only not dropping the count...
+			 */
+			UB_INIT_COMPLETION(sc->work_done);
+
+			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.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;
+			}
+			return;
+		}
+
+		/*
+		 * Check the returned Bulk protocol status.
+		 */
+
+		bcs = &sc->work_bcs;
+		rc = le32_to_cpu(bcs->Residue);
+		if (rc != cmd->len - cmd->act_len) {
+			/*
+			 * It is all right to transfer less, the caller has
+			 * to check. But it's not all right if the device
+			 * counts disagree with our counts.
+			 */
+			/* P3 */ printk("%s: resid %d len %d act %d\n",
+			    sc->name, rc, cmd->len, cmd->act_len);
+			goto Bad_End;
+		}
+
+		if (bcs->Signature != cpu_to_le32(US_BULK_CS_SIGN) &&
+		    bcs->Signature != cpu_to_le32(US_BULK_CS_OLYMPUS_SIGN)) {
+			/* XXX Rate-limit, even for P3 tagged */
+			/* P3 */ printk("ub: signature 0x%x\n", bcs->Signature);
+			/* Windows ignores signatures, so do we. */
+		}
+
+		if (bcs->Tag != cmd->tag) {
+			/* P3 */ printk("%s: tag orig 0x%x reply 0x%x\n",
+			    sc->name, cmd->tag, bcs->Tag);
+			goto Bad_End;
+		}
+
+		switch (bcs->Status) {
+		case US_BULK_STAT_OK:
+			break;
+		case US_BULK_STAT_FAIL:
+			ub_state_sense(sc, cmd);
+			return;
+		case US_BULK_STAT_PHASE:
+			/* XXX We must reset the transport here */
+			/* P3 */ printk("%s: status PHASE\n", sc->name);
+			goto Bad_End;
+		default:
+			printk(KERN_INFO "%s: unknown CSW status 0x%x\n",
+			    sc->name, bcs->Status);
+			goto Bad_End;
+		}
+
+		/* Not zeroing error to preserve a babble indicator */
+		cmd->state = UB_CMDST_DONE;
+		ub_cmdtr_state(sc, cmd);
+		ub_cmdq_pop(sc);
+		(*cmd->done)(sc, cmd);
+
+	} else if (cmd->state == UB_CMDST_SENSE) {
+		/* 
+		 * We do not look at sense, because even if there was no sense,
+		 * we get into UB_CMDST_SENSE from a STALL or CSW FAIL only.
+		 * We request sense because we want to clear CHECK CONDITION
+		 * on devices with delusions of SCSI, and not because we
+		 * are curious in any way about the sense itself.
+		 */
+		/* if ((cmd->top_sense[2] & 0x0F) == NO_SENSE) { foo } */
+
+		ub_state_done(sc, cmd, -EIO);
+	} else {
+		printk(KERN_WARNING "%s: "
+		    "wrong command state %d on device %u\n",
+		    sc->name, cmd->state, sc->dev->devnum);
+		goto Bad_End;
+	}
+	return;
+
+Bad_End: /* Little Excel is dead */
+	ub_state_done(sc, cmd, -EIO);
+}
+
+/*
+ * Factorization helper for the command state machine:
+ * Finish the command.
+ */
+static void ub_state_done(struct ub_dev *sc, struct ub_scsi_cmd *cmd, int rc)
+{
+
+	cmd->error = rc;
+	cmd->state = UB_CMDST_DONE;
+	ub_cmdtr_state(sc, cmd);
+	ub_cmdq_pop(sc);
+	(*cmd->done)(sc, cmd);
+}
+
+/*
+ * Factorization helper for the command state machine:
+ * Submit a CSW read and go to STAT state.
+ */
+static void ub_state_stat(struct ub_dev *sc, struct ub_scsi_cmd *cmd)
+{
+	int rc;
+
+	UB_INIT_COMPLETION(sc->work_done);
+
+	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.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;
+	}
+
+	cmd->stat_count = 0;
+	cmd->state = UB_CMDST_STAT;
+	ub_cmdtr_state(sc, cmd);
+}
+
+/*
+ * Factorization helper for the command state machine:
+ * Submit a REQUEST SENSE and go to SENSE state.
+ */
+static void ub_state_sense(struct ub_dev *sc, struct ub_scsi_cmd *cmd)
+{
+	struct ub_scsi_cmd *scmd;
+	int rc;
+
+	if (cmd->cdb[0] == REQUEST_SENSE) {
+		rc = -EPIPE;
+		goto error;
+	}
+
+	memset(&sc->top_sense, 0, UB_SENSE_SIZE);
+	scmd = &sc->top_rqs_cmd;
+	scmd->cdb[0] = REQUEST_SENSE;
+	scmd->cdb_len = 6;
+	scmd->dir = UB_DIR_READ;
+	scmd->state = UB_CMDST_INIT;
+	scmd->data = sc->top_sense;
+	scmd->len = UB_SENSE_SIZE;
+	scmd->done = ub_top_sense_done;
+	scmd->back = cmd;
+
+	scmd->tag = sc->tagcnt++;
+
+	cmd->state = UB_CMDST_SENSE;
+	ub_cmdtr_state(sc, cmd);
+
+	ub_cmdq_insert(sc, scmd);
+	return;
+
+error:
+	ub_state_done(sc, cmd, rc);
+}
+
+/*
+ * A helper for the command's state machine:
+ * Submit a stall clear.
+ */
+static int ub_submit_clear_stall(struct ub_dev *sc, struct ub_scsi_cmd *cmd,
+    int stalled_pipe)
+{
+	int endp;
+	struct usb_ctrlrequest *cr;
+	int rc;
+
+	endp = usb_pipeendpoint(stalled_pipe);
+	if (usb_pipein (stalled_pipe))
+		endp |= USB_DIR_IN;
+
+	cr = &sc->work_cr;
+	cr->bRequestType = USB_RECIP_ENDPOINT;
+	cr->bRequest = USB_REQ_CLEAR_FEATURE;
+	cr->wValue = cpu_to_le16(USB_ENDPOINT_HALT);
+	cr->wIndex = cpu_to_le16(endp);
+	cr->wLength = cpu_to_le16(0);
+
+	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.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;
+	}
+	return 0;
+}
+
+/*
+ */
+static void ub_top_sense_done(struct ub_dev *sc, struct ub_scsi_cmd *scmd)
+{
+	unsigned char *sense = scmd->data;
+	struct ub_scsi_cmd *cmd;
+
+	ub_cmdtr_sense(sc, scmd, sense);
+
+	if ((cmd = ub_cmdq_peek(sc)) == NULL) {
+		printk(KERN_WARNING "%s: sense done while idle\n", sc->name);
+		return;
+	}
+	if (cmd != scmd->back) {
+		printk(KERN_WARNING "%s: "
+		    "sense done for wrong command 0x%x on device %u\n",
+		    sc->name, cmd->tag, sc->dev->devnum);
+		return;
+	}
+	if (cmd->state != UB_CMDST_SENSE) {
+		printk(KERN_WARNING "%s: "
+		    "sense done with bad cmd state %d on device %u\n",
+		    sc->name, cmd->state, sc->dev->devnum);
+		return;
+	}
+
+	ub_scsi_urb_compl(sc, cmd);
+}
+
+#if 0
+/* Determine what the maximum LUN supported is */
+int usb_stor_Bulk_max_lun(struct us_data *us)
+{
+	int result;
+
+	/* issue the command */
+	result = usb_stor_control_msg(us, us->recv_ctrl_pipe,
+				 US_BULK_GET_MAX_LUN, 
+				 USB_DIR_IN | USB_TYPE_CLASS | 
+				 USB_RECIP_INTERFACE,
+				 0, us->ifnum, us->iobuf, 1, HZ);
+
+	/* 
+	 * Some devices (i.e. Iomega Zip100) need this -- apparently
+	 * the bulk pipes get STALLed when the GetMaxLUN request is
+	 * processed.   This is, in theory, harmless to all other devices
+	 * (regardless of if they stall or not).
+	 */
+	if (result < 0) {
+		usb_stor_clear_halt(us, us->recv_bulk_pipe);
+		usb_stor_clear_halt(us, us->send_bulk_pipe);
+	}
+
+	US_DEBUGP("GetMaxLUN command result is %d, data is %d\n", 
+		  result, us->iobuf[0]);
+
+	/* if we have a successful request, return the result */
+	if (result == 1)
+		return us->iobuf[0];
+
+	/* return the default -- no LUNs */
+	return 0;
+}
+#endif
+
+/*
+ * This is called from a process context.
+ */
+static void ub_revalidate(struct ub_dev *sc)
+{
+
+	sc->readonly = 0;	/* XXX Query this from the device */
+
+	/*
+	 * XXX sd.c sets capacity to zero in such case. However, it doesn't
+	 * work for us. In case of zero capacity, block layer refuses to
+	 * have the /dev/uba opened (why?) Set capacity to some random value.
+	 */
+	sc->capacity.nsec = 50;
+	sc->capacity.bsize = 512;
+	sc->capacity.bshift = 0;
+
+	if (ub_sync_tur(sc) != 0)
+		return;			/* Not ready */
+	sc->changed = 0;
+
+	if (ub_sync_read_cap(sc, &sc->capacity) != 0) {
+		/*
+		 * The retry here means something is wrong, either with the
+		 * device, with the transport, or with our code.
+		 * We keep this because sd.c has retries for capacity.
+		 */
+		if (ub_sync_read_cap(sc, &sc->capacity) != 0) {
+			sc->capacity.nsec = 100;
+			sc->capacity.bsize = 512;
+			sc->capacity.bshift = 0;
+		}
+	}
+}
+
+/*
+ * The open funcion.
+ * This is mostly needed to keep refcounting, but also to support
+ * media checks on removable media drives.
+ */
+static int ub_bd_open(struct inode *inode, struct file *filp)
+{
+	struct gendisk *disk = inode->i_bdev->bd_disk;
+	struct ub_dev *sc;
+	unsigned long flags;
+	int rc;
+
+	if ((sc = disk->private_data) == NULL)
+		return -ENXIO;
+	spin_lock_irqsave(&ub_lock, flags);
+	if (atomic_read(&sc->poison)) {
+		spin_unlock_irqrestore(&ub_lock, flags);
+		return -ENXIO;
+	}
+	sc->openc++;
+	spin_unlock_irqrestore(&ub_lock, flags);
+
+	if (sc->removable || sc->readonly)
+		check_disk_change(inode->i_bdev);
+
+	/* XXX sd.c and floppy.c bail on open if media is not present. */
+
+	if (sc->readonly && (filp->f_mode & FMODE_WRITE)) {
+		rc = -EROFS;
+		goto err_open;
+	}
+
+	return 0;
+
+err_open:
+	spin_lock_irqsave(&ub_lock, flags);
+	--sc->openc;
+	if (sc->openc == 0 && atomic_read(&sc->poison))
+		ub_cleanup(sc);
+	spin_unlock_irqrestore(&ub_lock, flags);
+	return rc;
+}
+
+/*
+ */
+static int ub_bd_release(struct inode *inode, struct file *filp)
+{
+	struct gendisk *disk = inode->i_bdev->bd_disk;
+	struct ub_dev *sc = disk->private_data;
+	unsigned long flags;
+
+	spin_lock_irqsave(&ub_lock, flags);
+	--sc->openc;
+	if (sc->openc == 0 && atomic_read(&sc->poison))
+		ub_cleanup(sc);
+	spin_unlock_irqrestore(&ub_lock, flags);
+	return 0;
+}
+
+/*
+ * The ioctl interface.
+ */
+static int ub_bd_ioctl(struct inode *inode, struct file *filp,
+    unsigned int cmd, unsigned long arg)
+{
+// void __user *usermem = (void *) arg;
+// struct carm_port *port = ino->i_bdev->bd_disk->private_data;
+// struct hd_geometry geom;
+
+#if 0
+	switch (cmd) {
+	case HDIO_GETGEO:
+		if (usermem == NULL)		// XXX Bizzare. Why?
+			return -EINVAL;
+
+		geom.heads = (u8) port->dev_geom_head;
+		geom.sectors = (u8) port->dev_geom_sect;
+		geom.cylinders = port->dev_geom_cyl;
+		geom.start = get_start_sect(ino->i_bdev);
+
+		if (copy_to_user(usermem, &geom, sizeof(geom)))
+			return -EFAULT;
+		return 0;
+
+	default: ;
+	}
+#endif
+
+	return -ENOTTY;
+}
+
+/*
+ * This is called once a new disk was seen by the block layer or by ub_probe().
+ * The main onjective here is to discover the features of the media such as
+ * the capacity, read-only status, etc. USB storage generally does not
+ * need to be spun up, but if we needed it, this would be the place.
+ *
+ * This call can sleep.
+ *
+ * The return code is not used.
+ */
+static int ub_bd_revalidate(struct gendisk *disk)
+{
+	struct ub_dev *sc = disk->private_data;
+
+	ub_revalidate(sc);
+	/* This is pretty much a long term P3 */
+	printk(KERN_INFO "%s: device %u capacity nsec %ld bsize %u\n",
+	    sc->name, sc->dev->devnum, sc->capacity.nsec, sc->capacity.bsize);
+
+	set_capacity(disk, sc->capacity.nsec);
+	// set_disk_ro(sdkp->disk, sc->readonly);
+	return 0;
+}
+
+/*
+ * The check is called by the block layer to verify if the media
+ * is still available. It is supposed to be harmless, lightweight and
+ * non-intrusive in case the media was not changed.
+ *
+ * This call can sleep.
+ *
+ * The return code is bool!
+ */
+static int ub_bd_media_changed(struct gendisk *disk)
+{
+	struct ub_dev *sc = disk->private_data;
+
+	if (!sc->removable)
+		return 0;
+
+	/*
+	 * We clean checks always after every command, so this is not
+	 * as dangerous as it looks. If the TEST_UNIT_READY fails here,
+	 * the device is actually not ready with operator or software
+	 * intervention required. One dangerous item might be a drive which
+	 * spins itself down, and come the time to write dirty pages, this
+	 * will fail, then block layer discards the data. Since we never
+	 * spin drives up, such devices simply cannot be used with ub anyway.
+	 */
+	if (ub_sync_tur(sc) != 0) {
+		sc->changed = 1;
+		/* P3 */ printk("%s: made changed\n", sc->name);
+		return 1;
+	}
+
+	/* The sd.c clears this before returning (one-shot flag). Why? */
+	/* P3 */ printk("%s: %s changed\n", sc->name,
+	    sc->changed? "is": "was not");
+	return sc->changed;
+}
+
+static struct block_device_operations ub_bd_fops = {
+	.owner		= THIS_MODULE,
+	.open		= ub_bd_open,
+	.release	= ub_bd_release,
+	.ioctl		= ub_bd_ioctl,
+	.media_changed	= ub_bd_media_changed,
+	.revalidate_disk = ub_bd_revalidate,
+};
+
+/*
+ * Common ->done routine for commands executed synchronously.
+ */
+static void ub_probe_done(struct ub_dev *sc, struct ub_scsi_cmd *cmd)
+{
+	struct completion *cop = cmd->back;
+	complete(cop);
+}
+
+/*
+ * Test if the device has a check condition on it, synchronously.
+ */
+static int ub_sync_tur(struct ub_dev *sc)
+{
+	struct ub_scsi_cmd *cmd;
+	enum { ALLOC_SIZE = sizeof(struct ub_scsi_cmd) };
+	unsigned long flags;
+	struct completion compl;
+	int rc;
+
+	init_completion(&compl);
+
+	rc = -ENOMEM;
+	if ((cmd = kmalloc(ALLOC_SIZE, GFP_KERNEL)) == NULL)
+		goto err_alloc;
+	memset(cmd, 0, ALLOC_SIZE);
+
+	cmd->cdb[0] = TEST_UNIT_READY;
+	cmd->cdb_len = 6;
+	cmd->dir = UB_DIR_NONE;
+	cmd->state = UB_CMDST_INIT;
+	cmd->done = ub_probe_done;
+	cmd->back = &compl;
+
+	spin_lock_irqsave(&sc->lock, flags);
+	cmd->tag = sc->tagcnt++;
+
+	rc = ub_submit_scsi(sc, cmd);
+	spin_unlock_irqrestore(&sc->lock, flags);
+
+	if (rc != 0) {
+		printk("ub: testing ready: submit error (%d)\n", rc); /* P3 */
+		goto err_submit;
+	}
+
+	wait_for_completion(&compl);
+
+	rc = cmd->error;
+
+err_submit:
+	kfree(cmd);
+err_alloc:
+	return rc;
+}
+
+/*
+ * Read the SCSI capacity synchronously (for probing).
+ */
+static int ub_sync_read_cap(struct ub_dev *sc, struct ub_capacity *ret)
+{
+	struct ub_scsi_cmd *cmd;
+	char *p;
+	enum { ALLOC_SIZE = sizeof(struct ub_scsi_cmd) + 8 };
+	unsigned long flags;
+	unsigned int bsize, shift;
+	unsigned long nsec;
+	struct completion compl;
+	int rc;
+
+	init_completion(&compl);
+
+	rc = -ENOMEM;
+	if ((cmd = kmalloc(ALLOC_SIZE, GFP_KERNEL)) == NULL)
+		goto err_alloc;
+	memset(cmd, 0, ALLOC_SIZE);
+	p = (char *)cmd + sizeof(struct ub_scsi_cmd);
+
+	cmd->cdb[0] = 0x25;
+	cmd->cdb_len = 10;
+	cmd->dir = UB_DIR_READ;
+	cmd->state = UB_CMDST_INIT;
+	cmd->data = p;
+	cmd->len = 8;
+	cmd->done = ub_probe_done;
+	cmd->back = &compl;
+
+	spin_lock_irqsave(&sc->lock, flags);
+	cmd->tag = sc->tagcnt++;
+
+	rc = ub_submit_scsi(sc, cmd);
+	spin_unlock_irqrestore(&sc->lock, flags);
+
+	if (rc != 0) {
+		printk("ub: reading capacity: submit error (%d)\n", rc); /* P3 */
+		goto err_submit;
+	}
+
+	wait_for_completion(&compl);
+
+	if (cmd->error != 0) {
+		printk("ub: reading capacity: error %d\n", cmd->error); /* P3 */
+		rc = -EIO;
+		goto err_read;
+	}
+	if (cmd->act_len != 8) {
+		printk("ub: reading capacity: size %d\n", cmd->act_len); /* P3 */
+		rc = -EIO;
+		goto err_read;
+	}
+
+	/* sd.c special-cases sector size of 0 to mean 512. Needed? Safe? */
+	nsec = be32_to_cpu(*(u32 *)p) + 1;
+	bsize = be32_to_cpu(*(u32 *)(p + 4));
+	switch (bsize) {
+	case 512:	shift = 0;	break;
+	case 1024:	shift = 1;	break;
+	case 2048:	shift = 2;	break;
+	case 4096:	shift = 3;	break;
+	default:
+		printk("ub: Bad sector size %u\n", bsize); /* P3 */
+		rc = -EDOM;
+		goto err_inv_bsize;
+	}
+
+	ret->bsize = bsize;
+	ret->bshift = shift;
+	ret->nsec = nsec << shift;
+	rc = 0;
+
+err_inv_bsize:
+err_read:
+err_submit:
+	kfree(cmd);
+err_alloc:
+	return rc;
+}
+
+/*
+ */
+static void ub_probe_urb_complete(struct urb *urb, struct pt_regs *pt)
+{
+	struct completion *cop = urb->context;
+	complete(cop);
+}
+
+static void ub_probe_timeout(unsigned long arg)
+{
+	struct completion *cop = (struct completion *) arg;
+	complete(cop);
+}
+
+/*
+ * Clear initial stalls.
+ */
+static int ub_probe_clear_stall(struct ub_dev *sc, int stalled_pipe)
+{
+	int endp;
+	struct usb_ctrlrequest *cr;
+	struct completion compl;
+	struct timer_list timer;
+	int rc;
+
+	init_completion(&compl);
+
+	endp = usb_pipeendpoint(stalled_pipe);
+	if (usb_pipein (stalled_pipe))
+		endp |= USB_DIR_IN;
+
+	cr = &sc->work_cr;
+	cr->bRequestType = USB_RECIP_ENDPOINT;
+	cr->bRequest = USB_REQ_CLEAR_FEATURE;
+	cr->wValue = cpu_to_le16(USB_ENDPOINT_HALT);
+	cr->wIndex = cpu_to_le16(endp);
+	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.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);
+
+	return 0;
+}
+
+/*
+ * Get the pipe settings.
+ */
+static int ub_get_pipes(struct ub_dev *sc, struct usb_device *dev,
+    struct usb_interface *intf)
+{
+	struct usb_host_interface *altsetting = intf->cur_altsetting;
+	struct usb_endpoint_descriptor *ep_in = NULL;
+	struct usb_endpoint_descriptor *ep_out = NULL;
+	struct usb_endpoint_descriptor *ep;
+	int i;
+
+	/*
+	 * Find the endpoints we need.
+	 * We are expecting a minimum of 2 endpoints - in and out (bulk).
+	 * We will ignore any others.
+	 */
+	for (i = 0; i < altsetting->desc.bNumEndpoints; i++) {
+		ep = &altsetting->endpoint[i].desc;
+
+		/* Is it a BULK endpoint? */
+		if ((ep->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK)
+				== USB_ENDPOINT_XFER_BULK) {
+			/* BULK in or out? */
+			if (ep->bEndpointAddress & USB_DIR_IN)
+				ep_in = ep;
+			else
+				ep_out = ep;
+		}
+	}
+
+	if (ep_in == NULL || ep_out == NULL) {
+		printk(KERN_NOTICE "%s: device %u failed endpoint check\n",
+		    sc->name, sc->dev->devnum);
+		return -EIO;
+	}
+
+	/* Calculate and store the pipe values */
+	sc->send_ctrl_pipe = usb_sndctrlpipe(dev, 0);
+	sc->recv_ctrl_pipe = usb_rcvctrlpipe(dev, 0);
+	sc->send_bulk_pipe = usb_sndbulkpipe(dev,
+		ep_out->bEndpointAddress & USB_ENDPOINT_NUMBER_MASK);
+	sc->recv_bulk_pipe = usb_rcvbulkpipe(dev, 
+		ep_in->bEndpointAddress & USB_ENDPOINT_NUMBER_MASK);
+
+	return 0;
+}
+
+/*
+ * Probing is done in the process context, which allows us to cheat
+ * and not to build a state machine for the discovery.
+ */
+static int ub_probe(struct usb_interface *intf,
+    const struct usb_device_id *dev_id)
+{
+	struct ub_dev *sc;
+	request_queue_t *q;
+	struct gendisk *disk;
+	int rc;
+
+	rc = -ENOMEM;
+	if ((sc = kmalloc(sizeof(struct ub_dev), GFP_KERNEL)) == NULL)
+		goto err_core;
+	memset(sc, 0, sizeof(struct ub_dev));
+	spin_lock_init(&sc->lock);
+	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... */
+
+	rc = -ENOSR;
+	if ((sc->id = ub_id_get()) == -1)
+		goto err_id;
+	snprintf(sc->name, 8, DRV_NAME "%c", sc->id + 'a');
+
+	sc->dev = interface_to_usbdev(intf);
+	sc->intf = intf;
+	// sc->ifnum = intf->cur_altsetting->desc.bInterfaceNumber;
+
+	usb_set_intfdata(intf, sc);
+	usb_get_dev(sc->dev);
+	// usb_get_intf(sc->intf);	/* Do we need this? */
+
+	/* XXX Verify that we can handle the device (from descriptors) */
+
+	ub_get_pipes(sc, sc->dev, intf);
+
+	if (device_create_file(&sc->intf->dev, &dev_attr_diag) != 0)
+		goto err_diag;
+
+	/*
+	 * At this point, all USB initialization is done, do upper layer.
+	 * We really hate halfway initialized structures, so from the
+	 * invariants perspective, this ub_dev is fully constructed at
+	 * this point.
+	 */
+
+	/*
+	 * This is needed to clear toggles. It is a problem only if we do
+	 * `rmmod ub && modprobe ub` without disconnects, but we like that.
+	 */
+	ub_probe_clear_stall(sc, sc->recv_bulk_pipe);
+	ub_probe_clear_stall(sc, sc->send_bulk_pipe);
+
+	/*
+	 * The way this is used by the startup code is a little specific.
+	 * A SCSI check causes a USB stall. Our common case code sees it
+	 * and clears the check, after which the device is ready for use.
+	 * But if a check was not present, any command other than
+	 * TEST_UNIT_READY ends with a lockup (including REQUEST_SENSE).
+	 *
+	 * If we neglect to clear the SCSI check, the first real command fails
+	 * (which is the capacity readout). We clear that and retry, but why
+	 * causing spurious retries for no reason.
+	 *
+	 * Revalidation may start with its own TEST_UNIT_READY, but that one
+	 * has to succeed, so we clear checks with an additional one here.
+	 * In any case it's not our business how revaliadation is implemented.
+	 */
+	ub_sync_tur(sc);
+
+	sc->removable = 1;		/* XXX Query this from the device */
+
+	ub_revalidate(sc);
+	/* This is pretty much a long term P3 */
+	printk(KERN_INFO "%s: device %u capacity nsec %ld bsize %u\n",
+	    sc->name, sc->dev->devnum, sc->capacity.nsec, sc->capacity.bsize);
+
+	/*
+	 * Just one disk per sc currently, but maybe more.
+	 */
+	rc = -ENOMEM;
+	if ((disk = alloc_disk(UB_MINORS_PER_MAJOR)) == NULL)
+		goto err_diskalloc;
+
+	sc->disk = disk;
+	sprintf(disk->disk_name, DRV_NAME "%c", sc->id + 'a');
+	sprintf(disk->devfs_name, DEVFS_NAME "/%c", sc->id + 'a');
+	disk->major = UB_MAJOR;
+	disk->first_minor = sc->id * UB_MINORS_PER_MAJOR;
+	disk->fops = &ub_bd_fops;
+	disk->private_data = sc;
+	disk->driverfs_dev = &intf->dev;
+
+	rc = -ENOMEM;
+	if ((q = blk_init_queue(ub_bd_rq_fn, &sc->lock)) == NULL)
+		goto err_blkqinit;
+
+	disk->queue = q;
+
+        // blk_queue_bounce_limit(q, hba[i]->pdev->dma_mask);
+	blk_queue_max_hw_segments(q, UB_MAX_REQ_SG);
+	blk_queue_max_phys_segments(q, UB_MAX_REQ_SG);
+	// blk_queue_segment_boundary(q, CARM_SG_BOUNDARY);
+	blk_queue_max_sectors(q, UB_MAX_SECTORS);
+	// blk_queue_hardsect_size(q, xxxxx);
+
+	/*
+	 * This is a serious infraction, caused by a deficiency in the
+	 * USB sg interface (usb_sg_wait()). We plan to remove this once
+	 * we get mileage on the driver and can justify a change to USB API.
+	 * See blk_queue_bounce_limit() to understand this part.
+	 *
+	 * XXX And I still need to be aware of the DMA mask in the HC.
+	 */
+	q->bounce_pfn = blk_max_low_pfn;
+	q->bounce_gfp = GFP_NOIO;
+
+	q->queuedata = sc;
+
+	set_capacity(disk, sc->capacity.nsec);
+	if (sc->removable)
+		disk->flags |= GENHD_FL_REMOVABLE;
+
+	add_disk(disk);
+
+	return 0;
+
+err_blkqinit:
+	put_disk(disk);
+err_diskalloc:
+	device_remove_file(&sc->intf->dev, &dev_attr_diag);
+err_diag:
+	usb_set_intfdata(intf, NULL);
+	// usb_put_intf(sc->intf);
+	usb_put_dev(sc->dev);
+	spin_lock_irq(&ub_lock);
+	ub_id_put(sc->id);
+	spin_unlock_irq(&ub_lock);
+err_id:
+	kfree(sc);
+err_core:
+	return rc;
+}
+
+static void ub_disconnect(struct usb_interface *intf)
+{
+	struct ub_dev *sc = usb_get_intfdata(intf);
+	struct gendisk *disk = sc->disk;
+	request_queue_t *q = disk->queue;
+	unsigned long flags;
+
+	/*
+	 * Fence stall clearnings, operations triggered by unlinkings and so on.
+	 * We do not attempt to unlink any URBs, because we do not trust the
+	 * unlink paths in HC drivers. Also, we get -84 upon disconnect anyway.
+	 */
+	atomic_set(&sc->poison, 1);
+
+	/*
+	 * Blow away queued commands.
+	 *
+	 * Actually, this never works, because before we get here
+	 * the HCD terminates outstanding URB(s). It causes our
+	 * SCSI command queue to advance, commands fail to submit,
+	 * and the whole queue drains. So, we just use this code to
+	 * print warnings.
+	 */
+	spin_lock_irqsave(&sc->lock, flags);
+	{
+		struct ub_scsi_cmd *cmd;
+		int cnt = 0;
+		while ((cmd = ub_cmdq_pop(sc)) != NULL) {
+			cmd->error = -ENOTCONN;
+			cmd->state = UB_CMDST_DONE;
+			ub_cmdtr_state(sc, cmd);
+			ub_cmdq_pop(sc);
+			(*cmd->done)(sc, cmd);
+			cnt++;
+		}
+		if (cnt != 0) {
+			printk(KERN_WARNING "%s: "
+			    "%d was queued after shutdown\n", sc->name, cnt);
+		}
+	}
+	spin_unlock_irqrestore(&sc->lock, flags);
+
+	/*
+	 * Unregister the upper layer, this waits for all commands to end.
+	 */
+	if (disk->flags & GENHD_FL_UP)
+		del_gendisk(disk);
+	if (q)
+		blk_cleanup_queue(q);
+
+	/*
+	 * If we zero disk->private_data BEFORE put_disk, we have to check
+	 * for NULL all over the place in open, release, check_media and
+	 * revalidate, because the block level semaphore is well inside the
+	 * put_disk. But we cannot zero after the call, because *disk is gone.
+	 * The sd.c is blatantly racy in this area.
+	 */
+	/* disk->private_data = NULL; */
+	put_disk(disk);
+	sc->disk = NULL;
+
+	/*
+	 * We really expect blk_cleanup_queue() to wait, so no amount
+	 * of paranoya is too much.
+	 *
+	 * Taking a lock on a structure which is about to be freed
+	 * is very nonsensual. Here it is largely a way to do a debug freeze,
+	 * and a bracket which shows where the nonsensual code segment ends.
+	 *
+	 * Testing for -EINPROGRESS is always a bug, so we are bending
+	 * the rules a little.
+	 */
+	spin_lock_irqsave(&sc->lock, flags);
+	if (sc->work_urb.status == -EINPROGRESS) {	/* janitors: ignore */
+		printk(KERN_WARNING "%s: "
+		    "URB is active after disconnect\n", sc->name);
+	}
+	spin_unlock_irqrestore(&sc->lock, flags);
+
+	/*
+	 * At this point there must be no commands coming from anyone
+	 * and no URBs left in transit.
+	 */
+
+	device_remove_file(&sc->intf->dev, &dev_attr_diag);
+	usb_set_intfdata(intf, NULL);
+	// usb_put_intf(sc->intf);
+	sc->intf = NULL;
+	usb_put_dev(sc->dev);
+	sc->dev = NULL;
+
+	spin_lock_irqsave(&ub_lock, flags);
+	if (sc->openc == 0)
+		ub_cleanup(sc);
+	spin_unlock_irqrestore(&ub_lock, flags);
+}
+
+struct usb_driver ub_driver = {
+	.owner =	THIS_MODULE,
+	.name =		"ub",
+	.probe =	ub_probe,
+	.disconnect =	ub_disconnect,
+	.id_table =	ub_usb_ids,
+};
+
+static int __init ub_init(void)
+{
+	int rc;
+
+	/* P3 */ printk("ub: sizeof ub_scsi_cmd %zu ub_dev %zu\n",
+			sizeof(struct ub_scsi_cmd), sizeof(struct ub_dev));
+
+	if ((rc = register_blkdev(UB_MAJOR, DRV_NAME)) != 0)
+		goto err_regblkdev;
+	devfs_mk_dir(DEVFS_NAME);
+
+	if ((rc = usb_register(&ub_driver)) != 0)
+		goto err_register;
+
+	return 0;
+
+err_register:
+	devfs_remove(DEVFS_NAME);
+	unregister_blkdev(UB_MAJOR, DRV_NAME);
+err_regblkdev:
+	return rc;
+}
+
+static void __exit ub_exit(void)
+{
+	usb_deregister(&ub_driver);
+
+	devfs_remove(DEVFS_NAME);
+	unregister_blkdev(UB_MAJOR, DRV_NAME);
+}
+
+module_init(ub_init);
+module_exit(ub_exit);
+
+MODULE_LICENSE("GPL");
diff -Nru a/drivers/block/umem.c b/drivers/block/umem.c
--- a/drivers/block/umem.c	2004-10-18 14:57:04 -07:00
+++ b/drivers/block/umem.c	2004-10-18 14:57:04 -07:00
@@ -108,11 +108,11 @@
 	int		irq;
 
 	unsigned long	csr_base;
-	unsigned char	*csr_remap;
+	unsigned char	__iomem *csr_remap;
 	unsigned long	csr_len;
 #ifdef CONFIG_MM_MAP_MEMORY
 	unsigned long	mem_base;
-	unsigned char	*mem_remap;
+	unsigned char	__iomem *mem_remap;
 	unsigned long	mem_len;
 #endif
 
@@ -926,7 +926,7 @@
 		goto failed_req_mem;
 	}
 
-	if (!(card->mem_remap = (unsigned char *)ioremap(card->mem_base, cards->mem_len))) {
+	if (!(card->mem_remap = ioremap(card->mem_base, cards->mem_len))) {
 		printk(KERN_ERR "MM%d: Unable to remap memory region\n", card->card_number);
 		ret = -ENOMEM;
 
@@ -1107,12 +1107,12 @@
 				    card->mm_pages[1].page_dma);
  failed_magic:
 #ifdef CONFIG_MM_MAP_MEMORY
-	iounmap((void *) card->mem_remap);
+	iounmap(card->mem_remap);
  failed_remap_mem:
 	release_mem_region(card->mem_base, card->mem_len);
  failed_req_mem:
 #endif
-	iounmap((void *) card->csr_remap);
+	iounmap(card->csr_remap);
  failed_remap_csr:
 	release_mem_region(card->csr_base, card->csr_len);
  failed_req_csr:
diff -Nru a/drivers/bluetooth/hci_ldisc.c b/drivers/bluetooth/hci_ldisc.c
--- a/drivers/bluetooth/hci_ldisc.c	2004-10-18 14:56:49 -07:00
+++ b/drivers/bluetooth/hci_ldisc.c	2004-10-18 14:56:49 -07:00
@@ -188,9 +188,7 @@
 	}
 
 	/* Flush any pending characters in the driver and discipline. */
-	if (tty->ldisc.flush_buffer)
-		tty->ldisc.flush_buffer(tty);
-
+	tty_ldisc_flush(tty);
 	if (tty->driver->flush_buffer)
 		tty->driver->flush_buffer(tty);
 
@@ -280,7 +278,9 @@
 
 	spin_lock_init(&hu->rx_lock);
 
-	/* Flush any pending characters in the driver and line discipline */
+	/* Flush any pending characters in the driver and line discipline. */
+	/* FIXME: why is this needed. Note don't use ldisc_ref here as the
+	   open path is before the ldisc is referencable */
 	if (tty->ldisc.flush_buffer)
 		tty->ldisc.flush_buffer(tty);
 
diff -Nru a/drivers/bluetooth/hci_usb.c b/drivers/bluetooth/hci_usb.c
--- a/drivers/bluetooth/hci_usb.c	2004-10-18 14:57:04 -07:00
+++ b/drivers/bluetooth/hci_usb.c	2004-10-18 14:57:04 -07:00
@@ -96,7 +96,7 @@
 	{ USB_DEVICE(0x0a5c, 0x2033), .driver_info = HCI_IGNORE },
 
 	/* Broadcom BCM2035 */
-	{ USB_DEVICE(0x0a5c, 0x200a), .driver_info = HCI_RESET },
+	{ USB_DEVICE(0x0a5c, 0x200a), .driver_info = HCI_RESET | HCI_BROKEN_ISOC },
 
 	/* ISSC Bluetooth Adapter v3.1 */
 	{ USB_DEVICE(0x1131, 0x1001), .driver_info = HCI_RESET },
diff -Nru a/drivers/cdrom/cdrom.c b/drivers/cdrom/cdrom.c
--- a/drivers/cdrom/cdrom.c	2004-10-18 14:56:11 -07:00
+++ b/drivers/cdrom/cdrom.c	2004-10-18 14:56:11 -07:00
@@ -354,6 +354,19 @@
 #endif /* CONFIG_SYSCTL */ 
 static struct cdrom_device_info *topCdromPtr;
 
+static int cdrom_dummy_generic_packet(struct cdrom_device_info *cdi,
+				      struct packet_command *cgc)
+{
+	if (cgc->sense) {
+		cgc->sense->sense_key = 0x05;
+		cgc->sense->asc = 0x20;
+		cgc->sense->ascq = 0x00;
+	}
+
+	cgc->stat = -EIO;
+	return -EIO;
+}
+
 /* This macro makes sure we don't have to check on cdrom_device_ops
  * existence in the run-time routines below. Change_capability is a
  * hack to have the capability flags defined const, while we can still
@@ -411,6 +424,9 @@
 	else
 		cdi->cdda_method = CDDA_OLD;
 
+	if (!cdo->generic_packet)
+		cdo->generic_packet = cdrom_dummy_generic_packet;
+
 	cdinfo(CD_REG_UNREG, "drive \"/dev/%s\" registered\n", cdi->name);
 	spin_lock(&cdrom_lock);
 	cdi->next = topCdromPtr; 	
@@ -472,6 +488,9 @@
 	if (be16_to_cpu(eh->data_len) < sizeof(*med))
 		return 1;
 
+	if (eh->nea || eh->notification_class != 0x4)
+		return 1;
+
 	memcpy(med, &buffer[sizeof(*eh)], sizeof(*med));
 	return 0;
 }
@@ -605,13 +624,16 @@
 static int cdrom_mrw_exit(struct cdrom_device_info *cdi)
 {
 	disc_information di;
-	int ret = 0;
+	int ret;
 
-	if (cdrom_get_disc_info(cdi, &di))
+	ret = cdrom_get_disc_info(cdi, &di);
+	if (ret < 0 || ret < (int)offsetof(typeof(di),disc_type))
 		return 1;
 
+	ret = 0;
 	if (di.mrw_status == CDM_MRW_BGFORMAT_ACTIVE) {
-		printk(KERN_INFO "cdrom: issuing MRW back ground format suspend\n");
+		printk(KERN_INFO "cdrom: issuing MRW back ground "
+				"format suspend\n");
 		ret = cdrom_mrw_bgformat_susp(cdi, 0);
 	}
 
@@ -715,8 +737,10 @@
 static int cdrom_media_erasable(struct cdrom_device_info *cdi)
 {
 	disc_information di;
+	int ret;
 
-	if (cdrom_get_disc_info(cdi, &di))
+	ret = cdrom_get_disc_info(cdi, &di);
+	if (ret < 0 || ret < offsetof(typeof(di), n_first_track))
 		return -1;
 
 	return di.erasable;
@@ -752,7 +776,8 @@
 		return 1;
 	}
 
-	if (cdrom_get_disc_info(cdi, &di))
+	ret = cdrom_get_disc_info(cdi, &di);
+	if (ret < 0 || ret < offsetof(typeof(di),disc_type))
 		return 1;
 
 	if (!di.erasable)
@@ -766,10 +791,12 @@
 	 * 3	-	MRW formatting complete
 	 */
 	ret = 0;
-	printk(KERN_INFO "cdrom open: mrw_status '%s'\n", mrw_format_status[di.mrw_status]);
+	printk(KERN_INFO "cdrom open: mrw_status '%s'\n",
+			mrw_format_status[di.mrw_status]);
 	if (!di.mrw_status)
 		ret = 1;
-	else if (di.mrw_status == CDM_MRW_BGFORMAT_INACTIVE && mrw_format_restart)
+	else if (di.mrw_status == CDM_MRW_BGFORMAT_INACTIVE &&
+			mrw_format_restart)
 		ret = cdrom_mrw_bgformat(cdi, 1);
 
 	return ret;
@@ -1922,7 +1949,8 @@
 			       int lba, int nframes)
 {
 	struct packet_command cgc;
-	int nr, ret;
+	int ret = 0;
+	int nr;
 
 	cdi->last_sense = 0;
 
@@ -1944,8 +1972,8 @@
 		return -ENOMEM;
 
 	if (!access_ok(VERIFY_WRITE, ubuf, nframes * CD_FRAMESIZE_RAW)) {
-		kfree(cgc.buffer);
-		return -EFAULT;
+		ret = -EFAULT;
+		goto out;
 	}
 
 	cgc.data_direction = CGC_DATA_READ;
@@ -1956,13 +1984,17 @@
 		ret = cdrom_read_block(cdi, &cgc, lba, nr, 1, CD_FRAMESIZE_RAW);
 		if (ret)
 			break;
-		__copy_to_user(ubuf, cgc.buffer, CD_FRAMESIZE_RAW * nr);
+		if (__copy_to_user(ubuf, cgc.buffer, CD_FRAMESIZE_RAW * nr)) {
+			ret = -EFAULT;
+			break;
+		}
 		ubuf += CD_FRAMESIZE_RAW * nr;
 		nframes -= nr;
 		lba += nr;
 	}
+out:
 	kfree(cgc.buffer);
-	return 0;
+	return ret;
 }
 
 static int cdrom_read_cdda_bpc(struct cdrom_device_info *cdi, __u8 __user *ubuf,
@@ -2504,7 +2536,7 @@
 	struct cdrom_device_ops *cdo = cdi->ops;
 	struct packet_command cgc;
 	struct request_sense sense;
-	char buffer[32];
+	unsigned char buffer[32];
 	int ret = 0;
 
 	memset(&cgc, 0, sizeof(cgc));
@@ -2631,8 +2663,9 @@
 	case CDROMVOLCTRL:
 	case CDROMVOLREAD: {
 		struct cdrom_volctrl volctrl;
-		char mask[32];
+		char mask[sizeof(buffer)];
 		unsigned short offset;
+
 		cdinfo(CD_DO_IOCTL, "entering CDROMVOLUME\n");
 
 		IOCTL_IN(arg, struct cdrom_volctrl, volctrl);
@@ -2642,17 +2675,27 @@
 		if ((ret = cdrom_mode_sense(cdi, &cgc, GPMODE_AUDIO_CTL_PAGE, 0)))
 		    return ret;
 		
-		/* some drives have longer pages, adjust and reread. */
-		if (buffer[1] > cgc.buflen) {
-			cgc.buflen = buffer[1] + 2;
-			if ((ret = cdrom_mode_sense(cdi, &cgc, 
-					GPMODE_AUDIO_CTL_PAGE, 0))) 
-			    return ret;
+		/* originally the code depended on buffer[1] to determine
+		   how much data is available for transfer. buffer[1] is
+		   unfortunately ambigious and the only reliable way seem
+		   to be to simply skip over the block descriptor... */
+		offset = 8 + be16_to_cpu(*(unsigned short *)(buffer+6));
+
+		if (offset + 16 > sizeof(buffer))
+			return -E2BIG;
+
+		if (offset + 16 > cgc.buflen) {
+			cgc.buflen = offset+16;
+			ret = cdrom_mode_sense(cdi, &cgc,
+						GPMODE_AUDIO_CTL_PAGE, 0);
+			if (ret)
+				return ret;
 		}
-		
-		/* get the offset from the length of the page. length
-		   is measure from byte 2 an on, thus the 14. */
-		offset = buffer[1] - 14;
+
+		/* sanity check */
+		if ((buffer[offset] & 0x3f) != GPMODE_AUDIO_CTL_PAGE ||
+				buffer[offset+1] < 14)
+			return -EINVAL;
 
 		/* now we have the current volume settings. if it was only
 		   a CDROMVOLREAD, return these values */
@@ -2677,7 +2720,8 @@
 		buffer[offset+15] = volctrl.channel3 & mask[offset+15];
 
 		/* set volume */
-		cgc.buffer = buffer;
+		cgc.buffer = buffer + offset - 8;
+		memset(cgc.buffer, 0, 8);
 		return cdrom_mode_select(cdi, &cgc);
 		}
 
@@ -2760,7 +2804,7 @@
 {
 	struct cdrom_device_ops *cdo = cdi->ops;
 	struct packet_command cgc;
-	int ret;
+	int ret, buflen;
 
 	init_cdrom_command(&cgc, ti, 8, CGC_DATA_READ);
 	cgc.cmd[0] = GPCMD_READ_TRACK_RZONE_INFO;
@@ -2773,14 +2817,18 @@
 	if ((ret = cdo->generic_packet(cdi, &cgc)))
 		return ret;
 	
-	cgc.buflen = be16_to_cpu(ti->track_information_length) +
+	buflen = be16_to_cpu(ti->track_information_length) +
 		     sizeof(ti->track_information_length);
 
-	if (cgc.buflen > sizeof(track_information))
-		cgc.buflen = sizeof(track_information);
+	if (buflen > sizeof(track_information))
+		buflen = sizeof(track_information);
 
-	cgc.cmd[8] = cgc.buflen;
-	return cdo->generic_packet(cdi, &cgc);
+	cgc.cmd[8] = cgc.buflen = buflen;
+	if ((ret = cdo->generic_packet(cdi, &cgc)))
+		return ret;
+
+	/* return actual fill size */
+	return buflen;
 }
 
 /* requires CD R/RW */
@@ -2788,7 +2836,7 @@
 {
 	struct cdrom_device_ops *cdo = cdi->ops;
 	struct packet_command cgc;
-	int ret;
+	int ret, buflen;
 
 	/* set up command and get the disc info */
 	init_cdrom_command(&cgc, di, sizeof(*di), CGC_DATA_READ);
@@ -2802,14 +2850,18 @@
 	/* not all drives have the same disc_info length, so requeue
 	 * packet with the length the drive tells us it can supply
 	 */
-	cgc.buflen = be16_to_cpu(di->disc_information_length) +
+	buflen = be16_to_cpu(di->disc_information_length) +
 		     sizeof(di->disc_information_length);
 
-	if (cgc.buflen > sizeof(disc_information))
-		cgc.buflen = sizeof(disc_information);
+	if (buflen > sizeof(disc_information))
+		buflen = sizeof(disc_information);
 
-	cgc.cmd[8] = cgc.buflen;
-	return cdo->generic_packet(cdi, &cgc);
+	cgc.cmd[8] = cgc.buflen = buflen;
+	if ((ret = cdo->generic_packet(cdi, &cgc)))
+		return ret;
+
+	/* return actual fill size */
+	return buflen;
 }
 
 /* return the last written block on the CD-R media. this is for the udf
@@ -2820,27 +2872,37 @@
 	disc_information di;
 	track_information ti;
 	__u32 last_track;
-	int ret = -1;
+	int ret = -1, ti_size;
 
 	if (!CDROM_CAN(CDC_GENERIC_PACKET))
 		goto use_toc;
 
-	if ((ret = cdrom_get_disc_info(cdi, &di)))
+	ret = cdrom_get_disc_info(cdi, &di);
+	if (ret < (int)(offsetof(typeof(di), last_track_lsb)
+			+ sizeof(di.last_track_lsb)))
 		goto use_toc;
 
+	/* if unit didn't return msb, it's zeroed by cdrom_get_disc_info */
 	last_track = (di.last_track_msb << 8) | di.last_track_lsb;
-	if ((ret = cdrom_get_track_info(cdi, last_track, 1, &ti)))
+	ti_size = cdrom_get_track_info(cdi, last_track, 1, &ti);
+	if (ti_size < (int)offsetof(typeof(ti), track_start))
 		goto use_toc;
 
 	/* if this track is blank, try the previous. */
 	if (ti.blank) {
-		last_track--;
-		if ((ret = cdrom_get_track_info(cdi, last_track, 1, &ti)))
+		if (last_track==1)
 			goto use_toc;
+		last_track--;
+		ti_size = cdrom_get_track_info(cdi, last_track, 1, &ti);
 	}
 
+	if (ti_size < (int)(offsetof(typeof(ti), track_size)
+				+ sizeof(ti.track_size)))
+		goto use_toc;
+
 	/* if last recorded field is valid, return it. */
-	if (ti.lra_v) {
+	if (ti.lra_v && ti_size >= (int)(offsetof(typeof(ti), last_rec_address)
+				+ sizeof(ti.last_rec_address))) {
 		*last_written = be32_to_cpu(ti.last_rec_address);
 	} else {
 		/* make it up instead */
@@ -2853,11 +2915,12 @@
 
 	/* this is where we end up if the drive either can't do a
 	   GPCMD_READ_DISC_INFO or GPCMD_READ_TRACK_RZONE_INFO or if
-	   it fails. then we return the toc contents. */
+	   it doesn't give enough information or fails. then we return
+	   the toc contents. */
 use_toc:
 	toc.cdte_format = CDROM_MSF;
 	toc.cdte_track = CDROM_LEADOUT;
-	if (cdi->ops->audio_ioctl(cdi, CDROMREADTOCENTRY, &toc))
+	if ((ret = cdi->ops->audio_ioctl(cdi, CDROMREADTOCENTRY, &toc)))
 		return ret;
 	sanitize_format(&toc.cdte_addr, &toc.cdte_format, CDROM_LBA);
 	*last_written = toc.cdte_addr.lba;
@@ -2870,32 +2933,38 @@
 	disc_information di;
 	track_information ti;
 	__u16 last_track;
-	int ret = -1;
+	int ret, ti_size;
 
 	if (!CDROM_CAN(CDC_GENERIC_PACKET))
 		goto use_last_written;
 
-	if ((ret = cdrom_get_disc_info(cdi, &di)))
+	ret = cdrom_get_disc_info(cdi, &di);
+	if (ret < 0 || ret < offsetof(typeof(di), last_track_lsb)
+				+ sizeof(di.last_track_lsb))
 		goto use_last_written;
 
+	/* if unit didn't return msb, it's zeroed by cdrom_get_disc_info */
 	last_track = (di.last_track_msb << 8) | di.last_track_lsb;
-	if ((ret = cdrom_get_track_info(cdi, last_track, 1, &ti)))
+	ti_size = cdrom_get_track_info(cdi, last_track, 1, &ti);
+	if (ti_size < 0 || ti_size < offsetof(typeof(ti), track_start))
 		goto use_last_written;
 
         /* if this track is blank, try the previous. */
 	if (ti.blank) {
+		if (last_track == 1)
+			goto use_last_written;
 		last_track--;
-		if ((ret = cdrom_get_track_info(cdi, last_track, 1, &ti)))
+		ti_size = cdrom_get_track_info(cdi, last_track, 1, &ti);
+		if (ti_size < 0)
 			goto use_last_written;
 	}
 
 	/* if next recordable address field is valid, use it. */
-	if (ti.nwa_v)
+	if (ti.nwa_v && ti_size >= offsetof(typeof(ti), next_writable)
+				+ sizeof(ti.next_writable)) {
 		*next_writable = be32_to_cpu(ti.next_writable);
-	else
-		goto use_last_written;
-
-	return 0;
+		return 0;
+	}
 
 use_last_written:
 	if ((ret = cdrom_get_last_written(cdi, next_writable))) {
diff -Nru a/drivers/cdrom/cdu31a.c b/drivers/cdrom/cdu31a.c
--- a/drivers/cdrom/cdu31a.c	2004-10-18 14:56:48 -07:00
+++ b/drivers/cdrom/cdu31a.c	2004-10-18 14:56:48 -07:00
@@ -729,8 +729,7 @@
 		       res_reg[1]);
 	}
 
-	current->state = TASK_INTERRUPTIBLE;
-	schedule_timeout(2 * HZ);
+	msleep(2000);
 
 	sony_get_toc();
 }
@@ -960,8 +959,7 @@
 	if (((result_buffer[0] & 0xf0) == 0x20)
 	    && (num_retries < MAX_CDU31A_RETRIES)) {
 		num_retries++;
-		current->state = TASK_INTERRUPTIBLE;
-		schedule_timeout(HZ / 10);	/* Wait .1 seconds on retries */
+		msleep(100);
 		goto retry_cd_operation;
 	}
 
diff -Nru a/drivers/cdrom/mcd.c b/drivers/cdrom/mcd.c
--- a/drivers/cdrom/mcd.c	2004-10-18 14:56:33 -07:00
+++ b/drivers/cdrom/mcd.c	2004-10-18 14:56:33 -07:00
@@ -1021,10 +1021,9 @@
 		st = statusCmd();	/* check drive status */
 		if (st == -1)
 			goto err_out;	/* drive doesn't respond */
-		if ((st & MST_READY) == 0) {	/* no disk? wait a sec... */
-			current->state = TASK_INTERRUPTIBLE;
-			schedule_timeout(HZ);
-		}
+		if ((st & MST_READY) == 0) 	/* no disk? wait a sec... */
+			msleep(1000);
+
 	} while (((st & MST_READY) == 0) && count++ < MCD_RETRY_ATTEMPTS);
 
 	if (updateToc() < 0)
diff -Nru a/drivers/cdrom/viocd.c b/drivers/cdrom/viocd.c
--- a/drivers/cdrom/viocd.c	2004-10-18 14:57:04 -07:00
+++ b/drivers/cdrom/viocd.c	2004-10-18 14:57:04 -07:00
@@ -121,7 +121,10 @@
 };
 
 static struct capability_entry capability_table[] __initdata = {
-	{ "6330", CDC_LOCK | CDC_DVD_RAM },
+	{ "6330", CDC_LOCK | CDC_DVD_RAM | CDC_RAM },
+	{ "6331", CDC_LOCK | CDC_DVD_RAM | CDC_RAM },
+	{ "6333", CDC_LOCK | CDC_DVD_RAM | CDC_RAM },
+	{ "632A", CDC_LOCK | CDC_DVD_RAM | CDC_RAM },
 	{ "6321", CDC_LOCK },
 	{ "632B", 0 },
 	{ NULL  , CDC_LOCK },
@@ -332,10 +335,19 @@
 	struct disk_info *diskinfo = req->rq_disk->private_data;
 	u64 len;
 	dma_addr_t dmaaddr;
+	int direction;
+	u16 cmd;
 	struct scatterlist sg;
 
 	BUG_ON(req->nr_phys_segments > 1);
-	BUG_ON(rq_data_dir(req) != READ);
+
+	if (rq_data_dir(req) == READ) {
+		direction = DMA_FROM_DEVICE;
+		cmd = viomajorsubtype_cdio | viocdread;
+	} else {
+		direction = DMA_TO_DEVICE;
+		cmd = viomajorsubtype_cdio | viocdwrite;
+	}
 
         if (blk_rq_map_sg(req->q, req, &sg) == 0) {
 		printk(VIOCD_KERN_WARNING
@@ -343,7 +355,7 @@
 		return -1;
 	}
 
-	if (dma_map_sg(diskinfo->dev, &sg, 1, DMA_FROM_DEVICE) == 0) {
+	if (dma_map_sg(diskinfo->dev, &sg, 1, direction) == 0) {
 		printk(VIOCD_KERN_WARNING "error allocating sg tce\n");
 		return -1;
 	}
@@ -351,8 +363,7 @@
 	len = sg_dma_len(&sg);
 
 	hvrc = HvCallEvent_signalLpEventFast(viopath_hostLp,
-			HvLpEvent_Type_VirtualIo,
-			viomajorsubtype_cdio | viocdread,
+			HvLpEvent_Type_VirtualIo, cmd,
 			HvLpEvent_AckInd_DoAck,
 			HvLpEvent_AckType_ImmediateAck,
 			viopath_sourceinst(viopath_hostLp),
@@ -457,6 +468,41 @@
 	return 0;
 }
 
+static int viocd_packet(struct cdrom_device_info *cdi,
+		struct packet_command *cgc)
+{
+	unsigned int buflen = cgc->buflen;
+	int ret = -EIO;
+
+	switch (cgc->cmd[0]) {
+	case GPCMD_READ_DISC_INFO:
+		{
+			disc_information *di = (disc_information *)cgc->buffer;
+
+			if (buflen >= 2) {
+				di->disc_information_length = cpu_to_be16(1);
+				ret = 0;
+			}
+			if (buflen >= 3)
+				di->erasable =
+					(cdi->ops->capability & ~cdi->mask
+					 & (CDC_DVD_RAM | CDC_RAM)) != 0;
+		}
+		break;
+	default:
+		if (cgc->sense) {
+			/* indicate Unknown code */
+			cgc->sense->sense_key = 0x05;
+			cgc->sense->asc = 0x20;
+			cgc->sense->ascq = 0x00;
+		}
+		break;
+	}
+
+	cgc->stat = ret;
+	return ret;
+}
+
 /* This routine handles incoming CD LP events */
 static void vio_handle_cd_event(struct HvLpEvent *event)
 {
@@ -510,6 +556,7 @@
 	case viocdclose:
 		break;
 
+	case viocdwrite:
 	case viocdread:
 		/*
 		 * Since this is running in interrupt mode, we need to
@@ -518,7 +565,8 @@
 		di = &viocd_diskinfo[bevent->disk];
 		spin_lock_irqsave(&viocd_reqlock, flags);
 		dma_unmap_single(di->dev, bevent->token, bevent->len,
-				DMA_FROM_DEVICE);
+				((event->xSubtype & VIOMINOR_SUBTYPE_MASK) == viocdread)
+				?  DMA_FROM_DEVICE : DMA_TO_DEVICE);
 		req = (struct request *)bevent->event.xCorrelationToken;
 		rwreq--;
 
@@ -555,7 +603,8 @@
 	.release = viocd_release,
 	.media_changed = viocd_media_changed,
 	.lock_door = viocd_lock_door,
-	.capability = CDC_CLOSE_TRAY | CDC_OPEN_TRAY | CDC_LOCK | CDC_SELECT_SPEED | CDC_SELECT_DISC | CDC_MULTI_SESSION | CDC_MCN | CDC_MEDIA_CHANGED | CDC_PLAY_AUDIO | CDC_RESET | CDC_IOCTLS | CDC_DRIVE_STATUS | CDC_GENERIC_PACKET | CDC_CD_R | CDC_CD_RW | CDC_DVD | CDC_DVD_R | CDC_DVD_RAM
+	.generic_packet = viocd_packet,
+	.capability = CDC_CLOSE_TRAY | CDC_OPEN_TRAY | CDC_LOCK | CDC_SELECT_SPEED | CDC_SELECT_DISC | CDC_MULTI_SESSION | CDC_MCN | CDC_MEDIA_CHANGED | CDC_PLAY_AUDIO | CDC_RESET | CDC_IOCTLS | CDC_DRIVE_STATUS | CDC_GENERIC_PACKET | CDC_CD_R | CDC_CD_RW | CDC_DVD | CDC_DVD_R | CDC_DVD_RAM | CDC_RAM
 };
 
 static int __init find_capability(const char *type)
diff -Nru a/drivers/char/Kconfig b/drivers/char/Kconfig
--- a/drivers/char/Kconfig	2004-10-18 14:55:54 -07:00
+++ b/drivers/char/Kconfig	2004-10-18 14:55:54 -07:00
@@ -59,7 +59,7 @@
 
 config HW_CONSOLE
 	bool
-	depends on VT && !S390 && !UM
+	depends on VT && !S390 && !USERMODE
 	default y
 
 config SERIAL_NONSTANDARD
@@ -424,6 +424,14 @@
 	  will also be built as a module. This has to be loaded before
 	  "ser_a2232". If you want to do this, answer M here.
 
+config SGI_SNSC
+	bool "SGI Altix system controller communication support"
+	depends on (IA64_SGI_SN2 || IA64_GENERIC)
+	help
+	  If you have an SGI Altix and you want to enable system
+	  controller communication from user space (you want this!),
+	  say Y.  Otherwise, say N.
+
 source "drivers/serial/Kconfig"
 
 config UNIX98_PTYS
@@ -587,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"
@@ -778,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
@@ -1005,6 +980,14 @@
 	  The hangcheck-timer module detects when the system has gone
 	  out to lunch past a certain margin.  It can reboot the system
 	  or merely print a warning.
+
+config MMTIMER
+	tristate "MMTIMER Memory mapped RTC for SGI Altix"
+	depends on IA64_GENERIC || IA64_SGI_SN2
+	default y
+	help
+	  The mmtimer device allows direct userspace access to the
+	  Altix system timer.
 
 endmenu
 
diff -Nru a/drivers/char/Makefile b/drivers/char/Makefile
--- a/drivers/char/Makefile	2004-10-18 14:57:04 -07:00
+++ b/drivers/char/Makefile	2004-10-18 14:57:04 -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
@@ -39,8 +42,10 @@
 obj-$(CONFIG_AMIGA_BUILTIN_SERIAL) += amiserial.o
 obj-$(CONFIG_SX)		+= sx.o generic_serial.o
 obj-$(CONFIG_RIO)		+= rio/ generic_serial.o
-obj-$(CONFIG_HVC_CONSOLE)	+= hvc_console.o
+obj-$(CONFIG_HVC_CONSOLE)	+= hvc_console.o hvsi.o
 obj-$(CONFIG_RAW_DRIVER)	+= raw.o
+obj-$(CONFIG_SGI_SNSC)		+= snsc.o
+obj-$(CONFIG_MMTIMER)		+= mmtimer.o
 obj-$(CONFIG_VIOCONS) += viocons.o
 obj-$(CONFIG_VIOTAPE)		+= viotape.o
 obj-$(CONFIG_HVCS)		+= hvcs.o
diff -Nru a/drivers/char/agp/Kconfig b/drivers/char/agp/Kconfig
--- a/drivers/char/agp/Kconfig	2004-10-18 14:56:33 -07:00
+++ b/drivers/char/agp/Kconfig	2004-10-18 14:56:33 -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
@@ -130,7 +130,7 @@
 	depends on AGP && X86 && !X86_64
 	help
 	  This option gives you AGP support for the GLX component of
-	  XFree86 4.x on VIA MPV3/Apollo Pro chipsets.
+	  XFree86 4.x on VIA MVP3/Apollo Pro chipsets.
 
 	  You should say Y here if you use XFree86 3.3.6 or 4.x and want to
 	  use GLX or DRI.  If unsure, say N.
diff -Nru a/drivers/char/agp/agp.h b/drivers/char/agp/agp.h
--- a/drivers/char/agp/agp.h	2004-10-18 14:56:29 -07:00
+++ b/drivers/char/agp/agp.h	2004-10-18 14:56:29 -07:00
@@ -123,7 +123,7 @@
 	void *current_size;
 	void *dev_private_data;
 	struct pci_dev *dev;
-	u32 *gatt_table;
+	u32 __iomem *gatt_table;
 	u32 *gatt_table_real;
 	unsigned long scratch_page;
 	unsigned long scratch_page_real;
diff -Nru a/drivers/char/agp/amd-k7-agp.c b/drivers/char/agp/amd-k7-agp.c
--- a/drivers/char/agp/amd-k7-agp.c	2004-10-18 14:57:05 -07:00
+++ b/drivers/char/agp/amd-k7-agp.c	2004-10-18 14:57:05 -07:00
@@ -24,11 +24,11 @@
 
 struct amd_page_map {
 	unsigned long *real;
-	unsigned long *remapped;
+	unsigned long __iomem *remapped;
 };
 
 static struct _amd_irongate_private {
-	volatile u8 *registers;
+	volatile u8 __iomem *registers;
 	struct amd_page_map **gatt_pages;
 	int num_tables;
 } amd_irongate_private;
@@ -54,7 +54,7 @@
 	global_cache_flush();
 
 	for (i = 0; i < PAGE_SIZE / sizeof(unsigned long); i++)
-		page_map->remapped[i] = agp_bridge->scratch_page;
+		writel(agp_bridge->scratch_page, page_map->remapped+i);
 
 	return 0;
 }
@@ -151,7 +151,7 @@
 	}
 
 	agp_bridge->gatt_table_real = (u32 *)page_dir.real;
-	agp_bridge->gatt_table = (u32 *)page_dir.remapped;
+	agp_bridge->gatt_table = (u32 __iomem *)page_dir.remapped;
 	agp_bridge->gatt_bus_addr = virt_to_phys(page_dir.real);
 
 	/* Get the address for the gart region.
@@ -165,9 +165,8 @@
 
 	/* Calculate the agp offset */
 	for (i = 0; i < value->num_entries / 1024; i++, addr += 0x00400000) {
-		page_dir.remapped[GET_PAGE_DIR_OFF(addr)] =
-			virt_to_phys(amd_irongate_private.gatt_pages[i]->real);
-		page_dir.remapped[GET_PAGE_DIR_OFF(addr)] |= 0x00000001;
+		writel(virt_to_phys(amd_irongate_private.gatt_pages[i]->real) | 1,
+			page_dir.remapped+GET_PAGE_DIR_OFF(addr));
 	}
 
 	return 0;
@@ -178,7 +177,7 @@
 	struct amd_page_map page_dir;
 
 	page_dir.real = (unsigned long *)agp_bridge->gatt_table_real;
-	page_dir.remapped = (unsigned long *)agp_bridge->gatt_table;
+	page_dir.remapped = (unsigned long __iomem *)agp_bridge->gatt_table;
 
 	amd_free_gatt_pages();
 	amd_free_page_map(&page_dir);
@@ -218,7 +217,7 @@
 	/* Get the memory mapped registers */
 	pci_read_config_dword(agp_bridge->dev, AMD_MMBASE, &temp);
 	temp = (temp & PCI_BASE_ADDRESS_MEM_MASK);
-	amd_irongate_private.registers = (volatile u8 *) ioremap(temp, 4096);
+	amd_irongate_private.registers = (volatile u8 __iomem *) ioremap(temp, 4096);
 
 	/* Write out the address of the gatt table */
 	OUTREG32(amd_irongate_private.registers, AMD_ATTBASE,
@@ -263,7 +262,7 @@
 	pci_read_config_dword(agp_bridge->dev, AMD_APSIZE, &temp);
 	temp = ((temp & ~(0x0000000f)) | previous_size->size_value);
 	pci_write_config_dword(agp_bridge->dev, AMD_APSIZE, temp);
-	iounmap((void *) amd_irongate_private.registers);
+	iounmap((void __iomem *) amd_irongate_private.registers);
 }
 
 /*
@@ -282,7 +281,7 @@
 static int amd_insert_memory(struct agp_memory *mem, off_t pg_start, int type)
 {
 	int i, j, num_entries;
-	unsigned long *cur_gatt;
+	unsigned long __iomem *cur_gatt;
 	unsigned long addr;
 
 	num_entries = A_SIZE_LVL2(agp_bridge->current_size)->num_entries;
@@ -297,7 +296,7 @@
 	while (j < (pg_start + mem->page_count)) {
 		addr = (j * PAGE_SIZE) + agp_bridge->gart_bus_addr;
 		cur_gatt = GET_GATT(addr);
-		if (!PGE_EMPTY(agp_bridge, cur_gatt[GET_GATT_OFF(addr)]))
+		if (!PGE_EMPTY(agp_bridge, readl(cur_gatt+GET_GATT_OFF(addr))))
 			return -EBUSY;
 		j++;
 	}
@@ -310,8 +309,7 @@
 	for (i = 0, j = pg_start; i < mem->page_count; i++, j++) {
 		addr = (j * PAGE_SIZE) + agp_bridge->gart_bus_addr;
 		cur_gatt = GET_GATT(addr);
-		cur_gatt[GET_GATT_OFF(addr)] =
-			agp_generic_mask_memory(mem->memory[i], mem->type);
+		writel(agp_generic_mask_memory(mem->memory[i], mem->type), cur_gatt+GET_GATT_OFF(addr));
 	}
 	amd_irongate_tlbflush(mem);
 	return 0;
@@ -320,7 +318,7 @@
 static int amd_remove_memory(struct agp_memory *mem, off_t pg_start, int type)
 {
 	int i;
-	unsigned long *cur_gatt;
+	unsigned long __iomem *cur_gatt;
 	unsigned long addr;
 
 	if (type != 0 || mem->type != 0)
@@ -329,8 +327,7 @@
 	for (i = pg_start; i < (mem->page_count + pg_start); i++) {
 		addr = (i * PAGE_SIZE) + agp_bridge->gart_bus_addr;
 		cur_gatt = GET_GATT(addr);
-		cur_gatt[GET_GATT_OFF(addr)] = 
-			(unsigned long) agp_bridge->scratch_page;
+		writel(agp_bridge->scratch_page, cur_gatt+GET_GATT_OFF(addr));
 	}
 
 	amd_irongate_tlbflush(mem);
diff -Nru a/drivers/char/agp/amd64-agp.c b/drivers/char/agp/amd64-agp.c
--- a/drivers/char/agp/amd64-agp.c	2004-10-18 14:56:48 -07:00
+++ b/drivers/char/agp/amd64-agp.c	2004-10-18 14:56:48 -07:00
@@ -73,7 +73,7 @@
 static int amd64_insert_memory(struct agp_memory *mem, off_t pg_start, int type)
 {
 	int i, j, num_entries;
-	long tmp;
+	long long tmp;
 	u32 pte;
 
 	num_entries = agp_num_entries();
@@ -90,7 +90,7 @@
 
 	/* gatt table should be empty. */
 	while (j < (pg_start + mem->page_count)) {
-		if (!PGE_EMPTY(agp_bridge, agp_bridge->gatt_table[j]))
+		if (!PGE_EMPTY(agp_bridge, readl(agp_bridge->gatt_table+j)))
 			return -EBUSY;
 		j++;
 	}
@@ -108,7 +108,7 @@
 		pte |=(tmp & 0x00000000fffff000ULL);
 		pte |= GPTE_VALID | GPTE_COHERENT;
 
-		agp_bridge->gatt_table[j] = pte;
+		writel(pte, agp_bridge->gatt_table+j);
 	}
 	amd64_tlbflush(mem);
 	return 0;
@@ -675,4 +675,4 @@
 
 MODULE_AUTHOR("Dave Jones <davej@codemonkey.org.uk>, Andi Kleen");
 MODULE_PARM(agp_try_unsupported, "1i");
-MODULE_LICENSE("GPL and additional rights");
+MODULE_LICENSE("GPL");
diff -Nru a/drivers/char/agp/ati-agp.c b/drivers/char/agp/ati-agp.c
--- a/drivers/char/agp/ati-agp.c	2004-10-18 14:56:48 -07:00
+++ b/drivers/char/agp/ati-agp.c	2004-10-18 14:56:48 -07:00
@@ -42,11 +42,11 @@
 
 typedef struct _ati_page_map {
 	unsigned long *real;
-        unsigned long *remapped;
+	unsigned long __iomem *remapped;
 } ati_page_map;
 
 static struct _ati_generic_private {
-	volatile u8 *registers;
+	volatile u8 __iomem *registers;
 	ati_page_map **gatt_pages;
 	int num_tables;
 } ati_generic_private;
@@ -76,7 +76,7 @@
 	global_cache_flush();
 
 	for(i = 0; i < PAGE_SIZE / sizeof(unsigned long); i++)
-		page_map->remapped[i] = agp_bridge->scratch_page;
+		writel(agp_bridge->scratch_page, page_map->remapped+i);
 
 	return 0;
 }
@@ -206,7 +206,7 @@
 		temp = ((temp & ~(0x0000000f)) | previous_size->size_value);
 		pci_write_config_dword(agp_bridge->dev, ATI_RS300_APSIZE, temp);
 	}
-	iounmap((void *) ati_generic_private.registers);
+	iounmap((volatile u8 __iomem *)ati_generic_private.registers);
 }
 
 
@@ -217,7 +217,7 @@
 	/* Get the memory mapped registers */
 	pci_read_config_dword(agp_bridge->dev, ATI_GART_MMBASE_ADDR, &temp);
 	temp = (temp & 0xfffff000);
-	ati_generic_private.registers = (volatile u8 *) ioremap(temp, 4096);
+	ati_generic_private.registers = (volatile u8 __iomem *) ioremap(temp, 4096);
 
 	if (is_r200())
        	pci_write_config_dword(agp_bridge->dev, ATI_RS100_IG_AGPMODE, 0x20000);
@@ -261,7 +261,7 @@
 			     off_t pg_start, int type)
 {
 	int i, j, num_entries;
-	unsigned long *cur_gatt;
+	unsigned long __iomem *cur_gatt;
 	unsigned long addr;
 
 	num_entries = A_SIZE_LVL2(agp_bridge->current_size)->num_entries;
@@ -276,7 +276,7 @@
 	while (j < (pg_start + mem->page_count)) {
 		addr = (j * PAGE_SIZE) + agp_bridge->gart_bus_addr;
 		cur_gatt = GET_GATT(addr);
-		if (!PGE_EMPTY(agp_bridge,cur_gatt[GET_GATT_OFF(addr)]))
+		if (!PGE_EMPTY(agp_bridge,readl(cur_gatt+GET_GATT_OFF(addr))))
 			return -EBUSY;
 		j++;
 	}
@@ -290,8 +290,7 @@
 	for (i = 0, j = pg_start; i < mem->page_count; i++, j++) {
 		addr = (j * PAGE_SIZE) + agp_bridge->gart_bus_addr;
 		cur_gatt = GET_GATT(addr);
-		cur_gatt[GET_GATT_OFF(addr)] =
-			agp_bridge->driver->mask_memory(mem->memory[i], mem->type);
+		writel(agp_bridge->driver->mask_memory(mem->memory[i], mem->type), cur_gatt+GET_GATT_OFF(addr));
 	}
 	agp_bridge->driver->tlb_flush(mem);
 	return 0;
@@ -301,7 +300,7 @@
 			     int type)
 {
 	int i;
-	unsigned long *cur_gatt;
+	unsigned long __iomem *cur_gatt;
 	unsigned long addr;
 
 	if (type != 0 || mem->type != 0) {
@@ -310,8 +309,7 @@
 	for (i = pg_start; i < (mem->page_count + pg_start); i++) {
 		addr = (i * PAGE_SIZE) + agp_bridge->gart_bus_addr;
 		cur_gatt = GET_GATT(addr);
-		cur_gatt[GET_GATT_OFF(addr)] =
-			(unsigned long) agp_bridge->scratch_page;
+		writel(agp_bridge->scratch_page, cur_gatt+GET_GATT_OFF(addr));
 	}
 
 	agp_bridge->driver->tlb_flush(mem);
@@ -340,7 +338,7 @@
 	}
 
 	agp_bridge->gatt_table_real = (u32 *)page_dir.real;
-	agp_bridge->gatt_table = (u32 *)page_dir.remapped;
+	agp_bridge->gatt_table = (u32 __iomem *) page_dir.remapped;
 	agp_bridge->gatt_bus_addr = virt_to_bus(page_dir.real);
 
 	/* Write out the size register */
@@ -371,9 +369,8 @@
 
 	/* Calculate the agp offset */
 	for(i = 0; i < value->num_entries / 1024; i++, addr += 0x00400000) {
-		page_dir.remapped[GET_PAGE_DIR_OFF(addr)] =
-			virt_to_bus(ati_generic_private.gatt_pages[i]->real);
-		page_dir.remapped[GET_PAGE_DIR_OFF(addr)] |= 0x00000001;
+		writel(virt_to_bus(ati_generic_private.gatt_pages[i]->real) | 1,
+			page_dir.remapped+GET_PAGE_DIR_OFF(addr));
 	}
 
 	return 0;
@@ -384,7 +381,7 @@
 	ati_page_map page_dir;
 
 	page_dir.real = (unsigned long *)agp_bridge->gatt_table_real;
-	page_dir.remapped = (unsigned long *)agp_bridge->gatt_table;
+	page_dir.remapped = (unsigned long __iomem *)agp_bridge->gatt_table;
 
 	ati_free_gatt_pages();
 	ati_free_page_map(&page_dir);
diff -Nru a/drivers/char/agp/generic.c b/drivers/char/agp/generic.c
--- a/drivers/char/agp/generic.c	2004-10-18 14:56:28 -07:00
+++ b/drivers/char/agp/generic.c	2004-10-18 14:56:28 -07:00
@@ -35,6 +35,7 @@
 #include <linux/pm.h>
 #include <linux/agp_backend.h>
 #include <linux/vmalloc.h>
+#include <asm/io.h>
 #include "agp.h"
 
 __u32 *agp_gatt_table;
@@ -737,7 +738,7 @@
 
 	/* AK: bogus, should encode addresses > 4GB */
 	for (i = 0; i < num_entries; i++)
-		agp_bridge->gatt_table[i] = (unsigned long) agp_bridge->scratch_page;
+		writel(agp_bridge->scratch_page, agp_bridge->gatt_table+i);
 
 	return 0;
 }
@@ -843,9 +844,8 @@
 	j = pg_start;
 
 	while (j < (pg_start + mem->page_count)) {
-		if (!PGE_EMPTY(agp_bridge, agp_bridge->gatt_table[j])) {
+		if (!PGE_EMPTY(agp_bridge, readl(agp_bridge->gatt_table+j)))
 			return -EBUSY;
-		}
 		j++;
 	}
 
@@ -855,9 +855,7 @@
 	}
 
 	for (i = 0, j = pg_start; i < mem->page_count; i++, j++)
-		agp_bridge->gatt_table[j] =
-				agp_bridge->driver->mask_memory(
-						mem->memory[i], mem->type);
+		writel(agp_bridge->driver->mask_memory(mem->memory[i], mem->type), agp_bridge->gatt_table+j);
 
 	agp_bridge->driver->tlb_flush(mem);
 	return 0;
@@ -875,10 +873,8 @@
 	}
 
 	/* AK: bogus, should encode addresses > 4GB */
-	for (i = pg_start; i < (mem->page_count + pg_start); i++) {
-		agp_bridge->gatt_table[i] =
-		    (unsigned long) agp_bridge->scratch_page;
-	}
+	for (i = pg_start; i < (mem->page_count + pg_start); i++)
+		writel(agp_bridge->scratch_page, agp_bridge->gatt_table+i);
 
 	agp_bridge->driver->tlb_flush(mem);
 	return 0;
diff -Nru a/drivers/char/agp/hp-agp.c b/drivers/char/agp/hp-agp.c
--- a/drivers/char/agp/hp-agp.c	2004-10-18 14:56:49 -07:00
+++ b/drivers/char/agp/hp-agp.c	2004-10-18 14:56:49 -07:00
@@ -59,8 +59,8 @@
 };
 
 static struct _hp_private {
-	volatile u8 *ioc_regs;
-	volatile u8 *lba_regs;
+	volatile u8 __iomem *ioc_regs;
+	volatile u8 __iomem *lba_regs;
 	int lba_cap_offset;
 	u64 *io_pdir;		// PDIR for entire IOVA
 	u64 *gatt;		// PDIR just for GART (subset of above)
@@ -97,7 +97,7 @@
 		default:
 			printk(KERN_ERR PFX "Invalid IOTLB page size "
 			       "configuration 0x%x\n", hp->io_tlb_ps);
-			hp->gatt = 0;
+			hp->gatt = NULL;
 			hp->gatt_entries = 0;
 			return -ENODEV;
 	}
@@ -115,7 +115,7 @@
 
 	if (hp->gatt[0] != HP_ZX1_SBA_IOMMU_COOKIE) {
 		/* Normal case when no AGP device in system */
-	    	hp->gatt = 0;
+	    	hp->gatt = NULL;
 		hp->gatt_entries = 0;
 		printk(KERN_ERR PFX "No reserved IO PDIR entry found; "
 		       "GART disabled\n");
@@ -183,7 +183,7 @@
 }
 
 static int
-hp_zx1_lba_find_capability (volatile u8 *hpa, int cap)
+hp_zx1_lba_find_capability (volatile u8 __iomem *hpa, int cap)
 {
 	u16 status;
 	u8 pos, id;
@@ -267,10 +267,10 @@
 	if (hp->ioc_regs) {
 		if (hp->io_pdir_owner)
 			OUTREG64(hp->ioc_regs, HP_ZX1_IBASE, 0);
-		iounmap((void *) hp->ioc_regs);
+		iounmap(hp->ioc_regs);
 	}
 	if (hp->lba_regs)
-		iounmap((void *) hp->lba_regs);
+		iounmap(hp->lba_regs);
 }
 
 static void
@@ -294,7 +294,7 @@
 		if (!hp->io_pdir) {
 			printk(KERN_ERR PFX "Couldn't allocate contiguous "
 				"memory for I/O PDIR\n");
-			hp->gatt = 0;
+			hp->gatt = NULL;
 			hp->gatt_entries = 0;
 			return -ENOMEM;
 		}
diff -Nru a/drivers/char/agp/intel-agp.c b/drivers/char/agp/intel-agp.c
--- a/drivers/char/agp/intel-agp.c	2004-10-18 14:56:31 -07:00
+++ b/drivers/char/agp/intel-agp.c	2004-10-18 14:56:31 -07:00
@@ -69,7 +69,7 @@
 
 static struct _intel_i810_private {
 	struct pci_dev *i810_dev;	/* device one */
-	volatile u8 *registers;
+	volatile u8 __iomem *registers;
 	int num_dcache_entries;
 } intel_i810_private;
 
@@ -111,7 +111,7 @@
 	pci_read_config_dword(intel_i810_private.i810_dev, I810_MMADDR, &temp);
 	temp &= 0xfff80000;
 
-	intel_i810_private.registers = (volatile u8 *) ioremap(temp, 128 * 4096);
+	intel_i810_private.registers = ioremap(temp, 128 * 4096);
 	if (!intel_i810_private.registers) {
 		printk(KERN_ERR PFX "Unable to remap memory.\n");
 		return -ENOMEM;
@@ -142,7 +142,7 @@
 static void intel_i810_cleanup(void)
 {
 	OUTREG32(intel_i810_private.registers, I810_PGETBL_CTL, 0);
-	iounmap((void *) intel_i810_private.registers);
+	iounmap(intel_i810_private.registers);
 }
 
 static void intel_i810_tlbflush(struct agp_memory *mem)
@@ -162,11 +162,11 @@
 
 	page = alloc_pages(GFP_KERNEL, 2);
 	if (page == NULL) {
-		return 0;
+		return NULL;
 	}
 	if (change_page_attr(page, 4, PAGE_KERNEL_NOCACHE) < 0) {
-		__free_page(page); 
-		return 0;
+		__free_page(page);
+		return NULL;
 	}
 	get_page(page);
 	SetPageLocked(page);
@@ -180,7 +180,7 @@
 
 	if (addr == NULL)
 		return;
-	
+
 	page = virt_to_page(addr);
 	change_page_attr(page, 4, PAGE_KERNEL);
 	put_page(page);
@@ -202,7 +202,7 @@
 		return -EINVAL;
 	}
 	for (j = pg_start; j < (pg_start + mem->page_count); j++) {
-		if (!PGE_EMPTY(agp_bridge, agp_bridge->gatt_table[j]))
+		if (!PGE_EMPTY(agp_bridge, readl(agp_bridge->gatt_table+j)))
 			return -EBUSY;
 	}
 
@@ -330,7 +330,7 @@
 		if (curr->page_count == 4)
 			i8xx_destroy_pages(phys_to_virt(curr->memory[0]));
 		else
-	   		agp_bridge->driver->agp_destroy_page(
+			agp_bridge->driver->agp_destroy_page(
 				 phys_to_virt(curr->memory[0]));
 		vfree(curr->memory);
 	}
@@ -353,8 +353,8 @@
 
 static struct _intel_i830_private {
 	struct pci_dev *i830_dev;		/* device one */
-	volatile u8 *registers;
-	volatile u32 *gtt;		/* I915G */
+	volatile u8 __iomem *registers;
+	volatile u32 __iomem *gtt;		/* I915G */
 	int gtt_entries;
 } intel_i830_private;
 
@@ -371,7 +371,7 @@
 
 	/* We obtain the size of the GTT, which is also stored (for some
 	 * reason) at the top of stolen memory. Then we add 4KB to that
- 	 * for the video BIOS popup, which is also stored in there. */
+	 * for the video BIOS popup, which is also stored in there. */
 	size = agp_bridge->driver->fetch_size() + 4;
 
 	if (agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82830_HB ||
@@ -461,7 +461,7 @@
 	pci_read_config_dword(intel_i830_private.i830_dev,I810_MMADDR,&temp);
 	temp &= 0xfff80000;
 
-	intel_i830_private.registers = (volatile u8 *) ioremap(temp,128 * 4096);
+	intel_i830_private.registers = ioremap(temp,128 * 4096);
 	if (!intel_i830_private.registers)
 		return (-ENOMEM);
 
@@ -544,7 +544,7 @@
 
 static void intel_i830_cleanup(void)
 {
-	iounmap((void *) intel_i830_private.registers);
+	iounmap(intel_i830_private.registers);
 }
 
 static int intel_i830_insert_entries(struct agp_memory *mem,off_t pg_start,
@@ -649,8 +649,8 @@
 
 static void intel_i915_cleanup(void)
 {
-	iounmap((void *) intel_i830_private.gtt);
-	iounmap((void *) intel_i830_private.registers);
+	iounmap(intel_i830_private.gtt);
+	iounmap(intel_i830_private.registers);
 }
 
 static int intel_i915_insert_entries(struct agp_memory *mem,off_t pg_start,
@@ -746,18 +746,18 @@
 	size = agp_bridge->current_size;
 	page_order = size->page_order;
 	num_entries = size->num_entries;
-	agp_bridge->gatt_table_real = 0;
+	agp_bridge->gatt_table_real = NULL;
 
 	pci_read_config_dword(intel_i830_private.i830_dev, I915_MMADDR, &temp);
 	pci_read_config_dword(intel_i830_private.i830_dev, I915_PTEADDR,&temp2);
 
-	intel_i830_private.gtt = (volatile u32 *) ioremap(temp2, 256 * 1024);
-	if (!intel_i830_private.gtt) 
+	intel_i830_private.gtt = ioremap(temp2, 256 * 1024);
+	if (!intel_i830_private.gtt)
 		return (-ENOMEM);
 
 	temp &= 0xfff80000;
 
-	intel_i830_private.registers = (volatile u8 *) ioremap(temp,128 * 4096);
+	intel_i830_private.registers = ioremap(temp,128 * 4096);
 	if (!intel_i830_private.registers)
 		return (-ENOMEM);
 
@@ -921,7 +921,7 @@
 
 	/* aperture size */
 	pci_write_config_byte(agp_bridge->dev, INTEL_APSIZE,
-			current_size->size_value); 
+			current_size->size_value);
 
 	/* address to map to */
 	pci_read_config_dword(agp_bridge->dev, AGP_APBASE, &temp);
@@ -933,7 +933,7 @@
 	pci_write_config_dword(agp_bridge->dev, INTEL_ATTBASE, addr);
 
 	/* agpctrl */
-	pci_write_config_dword(agp_bridge->dev, INTEL_AGPCTRL, 0x0000); 
+	pci_write_config_dword(agp_bridge->dev, INTEL_AGPCTRL, 0x0000);
 
 	/* apcont */
 	pci_read_config_byte(agp_bridge->dev, INTEL_815_APCONT, &temp2);
@@ -956,7 +956,7 @@
 
 	previous_size = A_SIZE_8(agp_bridge->previous_size);
 	pci_read_config_byte(agp_bridge->dev, INTEL_I820_RDCR, &temp);
-	pci_write_config_byte(agp_bridge->dev, INTEL_I820_RDCR, 
+	pci_write_config_byte(agp_bridge->dev, INTEL_I820_RDCR,
 			temp & ~(1 << 1));
 	pci_write_config_byte(agp_bridge->dev, INTEL_APSIZE,
 			previous_size->size_value);
@@ -966,23 +966,23 @@
 static int intel_820_configure(void)
 {
 	u32 temp;
- 	u8 temp2; 
+	u8 temp2;
 	struct aper_size_info_8 *current_size;
 
 	current_size = A_SIZE_8(agp_bridge->current_size);
 
 	/* aperture size */
-	pci_write_config_byte(agp_bridge->dev, INTEL_APSIZE, current_size->size_value); 
+	pci_write_config_byte(agp_bridge->dev, INTEL_APSIZE, current_size->size_value);
 
 	/* address to map to */
 	pci_read_config_dword(agp_bridge->dev, AGP_APBASE, &temp);
 	agp_bridge->gart_bus_addr = (temp & PCI_BASE_ADDRESS_MEM_MASK);
 
 	/* attbase - aperture base */
-	pci_write_config_dword(agp_bridge->dev, INTEL_ATTBASE, agp_bridge->gatt_bus_addr); 
+	pci_write_config_dword(agp_bridge->dev, INTEL_ATTBASE, agp_bridge->gatt_bus_addr);
 
 	/* agpctrl */
-	pci_write_config_dword(agp_bridge->dev, INTEL_AGPCTRL, 0x0000); 
+	pci_write_config_dword(agp_bridge->dev, INTEL_AGPCTRL, 0x0000);
 
 	/* global enable aperture access */
 	/* This flag is not accessed through MCHCFG register as in */
@@ -990,7 +990,7 @@
 	pci_read_config_byte(agp_bridge->dev, INTEL_I820_RDCR, &temp2);
 	pci_write_config_byte(agp_bridge->dev, INTEL_I820_RDCR, temp2 | (1 << 1));
 	/* clear any possible AGP-related error conditions */
-	pci_write_config_word(agp_bridge->dev, INTEL_I820_ERRSTS, 0x001c); 
+	pci_write_config_word(agp_bridge->dev, INTEL_I820_ERRSTS, 0x001c);
 	return 0;
 }
 
@@ -1003,23 +1003,23 @@
 	current_size = A_SIZE_8(agp_bridge->current_size);
 
 	/* aperture size */
-	pci_write_config_byte(agp_bridge->dev, INTEL_APSIZE, current_size->size_value); 
+	pci_write_config_byte(agp_bridge->dev, INTEL_APSIZE, current_size->size_value);
 
 	/* address to map to */
 	pci_read_config_dword(agp_bridge->dev, AGP_APBASE, &temp);
 	agp_bridge->gart_bus_addr = (temp & PCI_BASE_ADDRESS_MEM_MASK);
 
 	/* attbase - aperture base */
-	pci_write_config_dword(agp_bridge->dev, INTEL_ATTBASE, agp_bridge->gatt_bus_addr); 
+	pci_write_config_dword(agp_bridge->dev, INTEL_ATTBASE, agp_bridge->gatt_bus_addr);
 
 	/* agpctrl */
-	pci_write_config_dword(agp_bridge->dev, INTEL_AGPCTRL, 0x0000); 
+	pci_write_config_dword(agp_bridge->dev, INTEL_AGPCTRL, 0x0000);
 
 	/* mcgcfg */
 	pci_read_config_word(agp_bridge->dev, INTEL_I840_MCHCFG, &temp2);
 	pci_write_config_word(agp_bridge->dev, INTEL_I840_MCHCFG, temp2 | (1 << 9));
 	/* clear any possible error conditions */
-	pci_write_config_word(agp_bridge->dev, INTEL_I840_ERRSTS, 0xc000); 
+	pci_write_config_word(agp_bridge->dev, INTEL_I840_ERRSTS, 0xc000);
 	return 0;
 }
 
@@ -1032,23 +1032,23 @@
 	current_size = A_SIZE_8(agp_bridge->current_size);
 
 	/* aperture size */
-	pci_write_config_byte(agp_bridge->dev, INTEL_APSIZE, current_size->size_value); 
+	pci_write_config_byte(agp_bridge->dev, INTEL_APSIZE, current_size->size_value);
 
 	/* address to map to */
 	pci_read_config_dword(agp_bridge->dev, AGP_APBASE, &temp);
 	agp_bridge->gart_bus_addr = (temp & PCI_BASE_ADDRESS_MEM_MASK);
 
 	/* attbase - aperture base */
-	pci_write_config_dword(agp_bridge->dev, INTEL_ATTBASE, agp_bridge->gatt_bus_addr); 
+	pci_write_config_dword(agp_bridge->dev, INTEL_ATTBASE, agp_bridge->gatt_bus_addr);
 
 	/* agpctrl */
-	pci_write_config_dword(agp_bridge->dev, INTEL_AGPCTRL, 0x0000); 
+	pci_write_config_dword(agp_bridge->dev, INTEL_AGPCTRL, 0x0000);
 
 	/* agpm */
 	pci_read_config_byte(agp_bridge->dev, INTEL_I845_AGPM, &temp2);
 	pci_write_config_byte(agp_bridge->dev, INTEL_I845_AGPM, temp2 | (1 << 1));
 	/* clear any possible error conditions */
-	pci_write_config_word(agp_bridge->dev, INTEL_I845_ERRSTS, 0x001c); 
+	pci_write_config_word(agp_bridge->dev, INTEL_I845_ERRSTS, 0x001c);
 	return 0;
 }
 
@@ -1061,23 +1061,23 @@
 	current_size = A_SIZE_8(agp_bridge->current_size);
 
 	/* aperture size */
-	pci_write_config_byte(agp_bridge->dev, INTEL_APSIZE, current_size->size_value); 
+	pci_write_config_byte(agp_bridge->dev, INTEL_APSIZE, current_size->size_value);
 
 	/* address to map to */
 	pci_read_config_dword(agp_bridge->dev, AGP_APBASE, &temp);
 	agp_bridge->gart_bus_addr = (temp & PCI_BASE_ADDRESS_MEM_MASK);
 
 	/* attbase - aperture base */
-	pci_write_config_dword(agp_bridge->dev, INTEL_ATTBASE, agp_bridge->gatt_bus_addr); 
+	pci_write_config_dword(agp_bridge->dev, INTEL_ATTBASE, agp_bridge->gatt_bus_addr);
 
 	/* agpctrl */
-	pci_write_config_dword(agp_bridge->dev, INTEL_AGPCTRL, 0x0000); 
+	pci_write_config_dword(agp_bridge->dev, INTEL_AGPCTRL, 0x0000);
 
 	/* mcgcfg */
 	pci_read_config_word(agp_bridge->dev, INTEL_I850_MCHCFG, &temp2);
 	pci_write_config_word(agp_bridge->dev, INTEL_I850_MCHCFG, temp2 | (1 << 9));
 	/* clear any possible AGP-related error conditions */
-	pci_write_config_word(agp_bridge->dev, INTEL_I850_ERRSTS, 0x001c); 
+	pci_write_config_word(agp_bridge->dev, INTEL_I850_ERRSTS, 0x001c);
 	return 0;
 }
 
@@ -1163,7 +1163,7 @@
 	/* mchcfg */
 	pci_read_config_word(agp_bridge->dev, INTEL_I7505_MCHCFG, &temp2);
 	pci_write_config_word(agp_bridge->dev, INTEL_I7505_MCHCFG, temp2 | (1 << 9));
-	
+
 	return 0;
 }
 
@@ -1178,7 +1178,7 @@
 	{64, 16384, 4, 0},
 	{32, 8192, 3, 8},
 };
-	
+
 static struct aper_size_info_8 intel_8xx_sizes[7] =
 {
 	{256, 65536, 6, 0},
@@ -1201,7 +1201,7 @@
 	{4, 1024, 0, 63}
 };
 
-static struct aper_size_info_8 intel_830mp_sizes[4] = 
+static struct aper_size_info_8 intel_830mp_sizes[4] =
 {
 	{256, 65536, 6, 0},
 	{128, 32768, 5, 32},
@@ -1283,7 +1283,7 @@
 	.owner			= THIS_MODULE,
 	.aperture_sizes		= intel_i830_sizes,
 	.size_type		= FIXED_APER_SIZE,
-	.num_aperture_sizes 	= 3,
+	.num_aperture_sizes	= 3,
 	.needs_scratch_page	= TRUE,
 	.configure		= intel_i830_configure,
 	.fetch_size		= intel_i830_fetch_size,
@@ -1445,7 +1445,7 @@
 	.owner			= THIS_MODULE,
 	.aperture_sizes		= intel_i830_sizes,
 	.size_type		= FIXED_APER_SIZE,
-	.num_aperture_sizes 	= 3,
+	.num_aperture_sizes	= 3,
 	.needs_scratch_page	= TRUE,
 	.configure		= intel_i915_configure,
 	.fetch_size		= intel_i915_fetch_size,
@@ -1489,18 +1489,13 @@
 	.agp_destroy_page	= agp_generic_destroy_page,
 };
 
-static int find_i810(u16 device, const char *name)
+static int find_i810(u16 device)
 {
 	struct pci_dev *i810_dev;
 
 	i810_dev = pci_find_device(PCI_VENDOR_ID_INTEL, device, NULL);
-	if (!i810_dev) {
-		printk(KERN_ERR PFX "Detected an Intel %s Chipset, "
-				"but could not find the secondary device.\n",
-				name);
+	if (!i810_dev)
 		return 0;
-	}
-
 	intel_i810_private.i810_dev = i810_dev;
 	return 1;
 }
@@ -1550,29 +1545,29 @@
 		name = "440GX";
 		break;
 	case PCI_DEVICE_ID_INTEL_82810_MC1:
-		if (!find_i810(PCI_DEVICE_ID_INTEL_82810_IG1, "i810"))
+		name = "i810";
+		if (!find_i810(PCI_DEVICE_ID_INTEL_82810_IG1))
 			goto fail;
 		bridge->driver = &intel_810_driver;
-		name = "i810";
 		break;
 	case PCI_DEVICE_ID_INTEL_82810_MC3:
-		if (!find_i810(PCI_DEVICE_ID_INTEL_82810_IG3, "i810 DC100"))
+		name = "i810 DC100";
+		if (!find_i810(PCI_DEVICE_ID_INTEL_82810_IG3))
 			goto fail;
 		bridge->driver = &intel_810_driver;
-		name = "i810 DC100";
 		break;
 	case PCI_DEVICE_ID_INTEL_82810E_MC:
-		if (!find_i810(PCI_DEVICE_ID_INTEL_82810E_IG, "i810 E"))
+		name = "i810 E";
+		if (!find_i810(PCI_DEVICE_ID_INTEL_82810E_IG))
 			goto fail;
 		bridge->driver = &intel_810_driver;
-		name = "i810 E";
 		break;
 	 case PCI_DEVICE_ID_INTEL_82815_MC:
 		/*
 		 * The i815 can operate either as an i810 style
 		 * integrated device, or as an AGP4X motherboard.
 		 */
-		if (find_i810(PCI_DEVICE_ID_INTEL_82815_CGC, "i815"))
+		if (find_i810(PCI_DEVICE_ID_INTEL_82815_CGC))
 			bridge->driver = &intel_810_driver;
 		else
 			bridge->driver = &intel_815_driver;
@@ -1708,7 +1703,10 @@
 
 	pci_set_drvdata(pdev, bridge);
 	return agp_add_bridge(bridge);
- fail:
+
+fail:
+	printk(KERN_ERR PFX "Detected an Intel %s chipset, "
+		"but could not find the secondary device.\n", name);
 	agp_put_bridge(bridge);
 	return -ENODEV;
 }
@@ -1724,7 +1722,7 @@
 static int agp_intel_resume(struct pci_dev *pdev)
 {
 	struct agp_bridge_data *bridge = pci_get_drvdata(pdev);
-	
+
 	pci_restore_state(pdev, pdev->saved_config_space);
 
 	if (bridge->driver == &intel_generic_driver)
@@ -1741,7 +1739,7 @@
 
 static struct pci_device_id agp_intel_pci_table[] = {
 #define ID(x)						\
-	{ 						\
+	{						\
 	.class		= (PCI_CLASS_BRIDGE_HOST << 8),	\
 	.class_mask	= ~0,				\
 	.vendor		= PCI_VENDOR_ID_INTEL,		\
@@ -1769,7 +1767,8 @@
 	ID(PCI_DEVICE_ID_INTEL_82865_HB),
 	ID(PCI_DEVICE_ID_INTEL_82875_HB),
 	ID(PCI_DEVICE_ID_INTEL_7505_0),
-	ID(PCI_DEVICE_ID_INTEL_7205_0),	
+	ID(PCI_DEVICE_ID_INTEL_7205_0),
+	ID(PCI_DEVICE_ID_INTEL_82915G_HB),
 	{ }
 };
 
@@ -1779,7 +1778,7 @@
 	.name		= "agpgart-intel",
 	.id_table	= agp_intel_pci_table,
 	.probe		= agp_intel_probe,
-	.remove		= agp_intel_remove,
+	.remove		= __devexit_p(agp_intel_remove),
 	.resume		= agp_intel_resume,
 };
 
diff -Nru a/drivers/char/agp/intel-mch-agp.c b/drivers/char/agp/intel-mch-agp.c
--- a/drivers/char/agp/intel-mch-agp.c	2004-10-18 14:55:55 -07:00
+++ b/drivers/char/agp/intel-mch-agp.c	2004-10-18 14:55:55 -07:00
@@ -84,7 +84,7 @@
 
 static struct _intel_i830_private {
 	struct pci_dev *i830_dev;		/* device one */
-	volatile u8 *registers;
+	volatile u8 __iomem *registers;
 	int gtt_entries;
 } intel_i830_private;
 
@@ -172,7 +172,7 @@
 	pci_read_config_dword(intel_i830_private.i830_dev,I810_MMADDR,&temp);
 	temp &= 0xfff80000;
 
-	intel_i830_private.registers = (volatile u8 *) ioremap(temp,128 * 4096);
+	intel_i830_private.registers = (volatile u8 __iomem*) ioremap(temp,128 * 4096);
 	if (!intel_i830_private.registers)
 		return (-ENOMEM);
 
@@ -255,7 +255,7 @@
 
 static void intel_i830_cleanup(void)
 {
-	iounmap((void *) intel_i830_private.registers);
+	iounmap((void __iomem *) intel_i830_private.registers);
 }
 
 static int intel_i830_insert_entries(struct agp_memory *mem,off_t pg_start,
@@ -633,5 +633,5 @@
 module_exit(agp_intelmch_cleanup);
 
 MODULE_AUTHOR("Dave Jones <davej@codemonkey.org.uk>");
-MODULE_LICENSE("GPL and additional rights");
+MODULE_LICENSE("GPL");
 
diff -Nru a/drivers/char/agp/nvidia-agp.c b/drivers/char/agp/nvidia-agp.c
--- a/drivers/char/agp/nvidia-agp.c	2004-10-18 14:56:17 -07:00
+++ b/drivers/char/agp/nvidia-agp.c	2004-10-18 14:56:17 -07:00
@@ -28,7 +28,7 @@
 	struct pci_dev *dev_1;
 	struct pci_dev *dev_2;
 	struct pci_dev *dev_3;
-	volatile u32 *aperture;
+	volatile u32 __iomem *aperture;
 	int num_active_entries;
 	off_t pg_offset;
 	u32 wbc_mask;
@@ -154,7 +154,7 @@
 
 	/* map aperture */
 	nvidia_private.aperture =
-		(volatile u32 *) ioremap(apbase, 33 * PAGE_SIZE);
+		(volatile u32 __iomem *) ioremap(apbase, 33 * PAGE_SIZE);
 
 	return 0;
 }
@@ -173,7 +173,7 @@
 	pci_write_config_dword(nvidia_private.dev_2, NVIDIA_2_GARTCTRL, temp & ~(0x11));
 
 	/* unmap aperture */
-	iounmap((void *) nvidia_private.aperture);
+	iounmap((void __iomem *) nvidia_private.aperture);
 
 	/* restore previous aperture size */
 	previous_size = A_SIZE_8(agp_bridge->previous_size);
@@ -206,7 +206,7 @@
 		return -EINVAL;
 	
 	for(j = pg_start; j < (pg_start + mem->page_count); j++) {
-		if (!PGE_EMPTY(agp_bridge, agp_bridge->gatt_table[nvidia_private.pg_offset + j]))
+		if (!PGE_EMPTY(agp_bridge, readl(agp_bridge->gatt_table+nvidia_private.pg_offset+j)))
 			return -EBUSY;
 	}
 
@@ -215,9 +215,8 @@
 		mem->is_flushed = TRUE;
 	}
 	for (i = 0, j = pg_start; i < mem->page_count; i++, j++)
-		agp_bridge->gatt_table[nvidia_private.pg_offset + j] =
-				agp_bridge->driver->mask_memory(mem->memory[i], mem->type);
-
+		writel(agp_bridge->driver->mask_memory(mem->memory[i], mem->type),
+			agp_bridge->gatt_table+nvidia_private.pg_offset+j);
 	agp_bridge->driver->tlb_flush(mem);
 	return 0;
 }
@@ -229,11 +228,9 @@
 
 	if ((type != 0) || (mem->type != 0))
 		return -EINVAL;
-	
-	for (i = pg_start; i < (mem->page_count + pg_start); i++) {
-		agp_bridge->gatt_table[nvidia_private.pg_offset + i] =
-		    (unsigned long) agp_bridge->scratch_page;
-	}
+
+	for (i = pg_start; i < (mem->page_count + pg_start); i++)
+		writel(agp_bridge->scratch_page, agp_bridge->gatt_table+nvidia_private.pg_offset+i);
 
 	agp_bridge->driver->tlb_flush(mem);
 	return 0;
@@ -265,9 +262,9 @@
 
 	/* flush TLB entries */
 	for(i = 0; i < 32 + 1; i++)
-		temp = nvidia_private.aperture[i * PAGE_SIZE / sizeof(u32)];
+		temp = readl(nvidia_private.aperture+(i * PAGE_SIZE / sizeof(u32)));
 	for(i = 0; i < 32 + 1; i++)
-		temp = nvidia_private.aperture[i * PAGE_SIZE / sizeof(u32)];
+		temp = readl(nvidia_private.aperture+(i * PAGE_SIZE / sizeof(u32)));
 }
 
 
diff -Nru a/drivers/char/agp/sis-agp.c b/drivers/char/agp/sis-agp.c
--- a/drivers/char/agp/sis-agp.c	2004-10-18 14:55:54 -07:00
+++ b/drivers/char/agp/sis-agp.c	2004-10-18 14:55:54 -07:00
@@ -169,6 +169,10 @@
 		.chipset_name	= "630",
 	},
 	{
+		.device_id	= PCI_DEVICE_ID_SI_635,
+		.chipset_name	= "635",
+	},
+	{
 		.device_id	= PCI_DEVICE_ID_SI_645,
 		.chipset_name	= "645",
 	},
diff -Nru a/drivers/char/agp/sworks-agp.c b/drivers/char/agp/sworks-agp.c
--- a/drivers/char/agp/sworks-agp.c	2004-10-18 14:56:28 -07:00
+++ b/drivers/char/agp/sworks-agp.c	2004-10-18 14:56:28 -07:00
@@ -27,12 +27,12 @@
 
 struct serverworks_page_map {
 	unsigned long *real;
-	unsigned long *remapped;
+	unsigned long __iomem *remapped;
 };
 
 static struct _serverworks_private {
 	struct pci_dev *svrwrks_dev;	/* device one */
-	volatile u8 *registers;
+	volatile u8 __iomem *registers;
 	struct serverworks_page_map **gatt_pages;
 	int num_tables;
 	struct serverworks_page_map scratch_dir;
@@ -61,9 +61,8 @@
 	}
 	global_cache_flush();
 
-	for(i = 0; i < PAGE_SIZE / sizeof(unsigned long); i++) {
-		page_map->remapped[i] = agp_bridge->scratch_page;
-	}
+	for(i = 0; i < PAGE_SIZE / sizeof(unsigned long); i++)
+		writel(agp_bridge->scratch_page, page_map->remapped+i);
 
 	return 0;
 }
@@ -162,10 +161,8 @@
 	}
 	/* Create a fake scratch directory */
 	for(i = 0; i < 1024; i++) {
-		serverworks_private.scratch_dir.remapped[i] = (unsigned long) agp_bridge->scratch_page;
-		page_dir.remapped[i] =
-			virt_to_phys(serverworks_private.scratch_dir.real);
-		page_dir.remapped[i] |= 0x00000001;
+		writel(agp_bridge->scratch_page, serverworks_private.scratch_dir.remapped+i);
+		writel(virt_to_phys(serverworks_private.scratch_dir.real) | 1, page_dir.remapped+i);
 	}
 
 	retval = serverworks_create_gatt_pages(value->num_entries / 1024);
@@ -176,7 +173,7 @@
 	}
 
 	agp_bridge->gatt_table_real = (u32 *)page_dir.real;
-	agp_bridge->gatt_table = (u32 *)page_dir.remapped;
+	agp_bridge->gatt_table = (u32 __iomem *)page_dir.remapped;
 	agp_bridge->gatt_bus_addr = virt_to_phys(page_dir.real);
 
 	/* Get the address for the gart region.
@@ -189,11 +186,8 @@
 
 	/* Calculate the agp offset */	
 
-	for(i = 0; i < value->num_entries / 1024; i++) {
-		page_dir.remapped[i] =
-			virt_to_phys(serverworks_private.gatt_pages[i]->real);
-		page_dir.remapped[i] |= 0x00000001;
-	}
+	for(i = 0; i < value->num_entries / 1024; i++)
+		writel(virt_to_phys(serverworks_private.gatt_pages[i]->real)|1, page_dir.remapped+i);
 
 	return 0;
 }
@@ -203,7 +197,7 @@
 	struct serverworks_page_map page_dir;
    
 	page_dir.real = (unsigned long *)agp_bridge->gatt_table_real;
-	page_dir.remapped = (unsigned long *)agp_bridge->gatt_table;
+	page_dir.remapped = (unsigned long __iomem *)agp_bridge->gatt_table;
 
 	serverworks_free_gatt_pages();
 	serverworks_free_page_map(&page_dir);
@@ -269,7 +263,7 @@
 	/* Get the memory mapped registers */
 	pci_read_config_dword(agp_bridge->dev, serverworks_private.mm_addr_ofs, &temp);
 	temp = (temp & PCI_BASE_ADDRESS_MEM_MASK);
-	serverworks_private.registers = (volatile u8 *) ioremap(temp, 4096);
+	serverworks_private.registers = (volatile u8 __iomem *) ioremap(temp, 4096);
 	if (!serverworks_private.registers) {
 		printk (KERN_ERR PFX "Unable to ioremap() memory.\n");
 		return -ENOMEM;
@@ -311,14 +305,14 @@
 
 static void serverworks_cleanup(void)
 {
-	iounmap((void *) serverworks_private.registers);
+	iounmap((void __iomem *) serverworks_private.registers);
 }
 
 static int serverworks_insert_memory(struct agp_memory *mem,
 			     off_t pg_start, int type)
 {
 	int i, j, num_entries;
-	unsigned long *cur_gatt;
+	unsigned long __iomem *cur_gatt;
 	unsigned long addr;
 
 	num_entries = A_SIZE_LVL2(agp_bridge->current_size)->num_entries;
@@ -334,9 +328,8 @@
 	while (j < (pg_start + mem->page_count)) {
 		addr = (j * PAGE_SIZE) + agp_bridge->gart_bus_addr;
 		cur_gatt = SVRWRKS_GET_GATT(addr);
-		if (!PGE_EMPTY(agp_bridge, cur_gatt[GET_GATT_OFF(addr)])) {
+		if (!PGE_EMPTY(agp_bridge, readl(cur_gatt+GET_GATT_OFF(addr))))
 			return -EBUSY;
-		}
 		j++;
 	}
 
@@ -348,8 +341,7 @@
 	for (i = 0, j = pg_start; i < mem->page_count; i++, j++) {
 		addr = (j * PAGE_SIZE) + agp_bridge->gart_bus_addr;
 		cur_gatt = SVRWRKS_GET_GATT(addr);
-		cur_gatt[GET_GATT_OFF(addr)] =
-			agp_bridge->driver->mask_memory(mem->memory[i], mem->type);
+		writel(agp_bridge->driver->mask_memory(mem->memory[i], mem->type), cur_gatt+GET_GATT_OFF(addr));
 	}
 	serverworks_tlbflush(mem);
 	return 0;
@@ -359,7 +351,7 @@
 			     int type)
 {
 	int i;
-	unsigned long *cur_gatt;
+	unsigned long __iomem *cur_gatt;
 	unsigned long addr;
 
 	if (type != 0 || mem->type != 0) {
@@ -372,8 +364,7 @@
 	for (i = pg_start; i < (mem->page_count + pg_start); i++) {
 		addr = (i * PAGE_SIZE) + agp_bridge->gart_bus_addr;
 		cur_gatt = SVRWRKS_GET_GATT(addr);
-		cur_gatt[GET_GATT_OFF(addr)] = 
-			(unsigned long) agp_bridge->scratch_page;
+		writel(agp_bridge->scratch_page, cur_gatt+GET_GATT_OFF(addr));
 	}
 
 	serverworks_tlbflush(mem);
diff -Nru a/drivers/char/agp/via-agp.c b/drivers/char/agp/via-agp.c
--- a/drivers/char/agp/via-agp.c	2004-10-18 14:56:50 -07:00
+++ b/drivers/char/agp/via-agp.c	2004-10-18 14:56:50 -07:00
@@ -438,6 +438,33 @@
 	agp_put_bridge(bridge);
 }
 
+#ifdef CONFIG_PM
+
+static int agp_via_suspend(struct pci_dev *pdev, u32 state)
+{
+	pci_save_state (pdev, pdev->saved_config_space);
+	pci_set_power_state (pdev, 3);
+
+	return 0;
+}
+
+static int agp_via_resume(struct pci_dev *pdev)
+{
+	struct agp_bridge_data *bridge = pci_get_drvdata(pdev);
+
+	pci_set_power_state (pdev, 0);
+	pci_restore_state(pdev, pdev->saved_config_space);
+
+	if (bridge->driver == &via_agp3_driver)
+		return via_configure_agp3();
+	else if (bridge->driver == &via_driver)
+		return via_configure();
+
+	return 0;
+}
+
+#endif /* CONFIG_PM */
+
 /* must be the same order as name table above */
 static struct pci_device_id agp_via_pci_table[] = {
 #define ID(x) \
@@ -487,6 +514,10 @@
 	.id_table	= agp_via_pci_table,
 	.probe		= agp_via_probe,
 	.remove		= agp_via_remove,
+#ifdef CONFIG_PM
+	.suspend	= agp_via_suspend,
+	.resume		= agp_via_resume,
+#endif
 };
 
 
@@ -503,5 +534,5 @@
 module_init(agp_via_init);
 module_exit(agp_via_cleanup);
 
-MODULE_LICENSE("GPL and additional rights");
+MODULE_LICENSE("GPL");
 MODULE_AUTHOR("Dave Jones <davej@codemonkey.org.uk>");
diff -Nru a/drivers/char/amiserial.c b/drivers/char/amiserial.c
--- a/drivers/char/amiserial.c	2004-10-18 14:57:05 -07:00
+++ b/drivers/char/amiserial.c	2004-10-18 14:57:05 -07:00
@@ -118,10 +118,6 @@
 
 #define NR_PORTS	(sizeof(rs_table)/sizeof(struct serial_state))
 
-#ifndef MIN
-#define MIN(a,b)	((a) < (b) ? (a) : (b))
-#endif
-
 /*
  * tmp_buf is used as a temporary buffer by serial_write.  We need to
  * lock it in case the copy_from_user blocks while swapping in a page,
@@ -430,7 +426,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))
@@ -557,9 +553,7 @@
 		return;
 
 	if (test_and_clear_bit(RS_EVENT_WRITE_WAKEUP, &info->event)) {
-		if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
-		    tty->ldisc.write_wakeup)
-			(tty->ldisc.write_wakeup)(tty);
+		tty_wakeup(tty);
 		wake_up_interruptible(&tty->write_wait);
 	}
 }
@@ -1023,9 +1017,7 @@
 	info->xmit.head = info->xmit.tail = 0;
 	local_irq_restore(flags);
 	wake_up_interruptible(&tty->write_wait);
-	if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
-	    tty->ldisc.write_wakeup)
-		(tty->ldisc.write_wakeup)(tty);
+	tty_wakeup(tty);
 }
 
 /*
@@ -1564,8 +1556,8 @@
 	shutdown(info);
 	if (tty->driver->flush_buffer)
 		tty->driver->flush_buffer(tty);
-	if (tty->ldisc.flush_buffer)
-		tty->ldisc.flush_buffer(tty);
+		
+	tty_ldisc_flush(tty);
 	tty->closing = 0;
 	info->event = 0;
 	info->tty = 0;
@@ -1610,7 +1602,7 @@
 	if (char_time == 0)
 		char_time = 1;
 	if (timeout)
-	  char_time = MIN(char_time, timeout);
+	  char_time = min_t(unsigned long, char_time, timeout);
 	/*
 	 * If the transmitter hasn't cleared in twice the approximate
 	 * amount of time to send the entire FIFO, it probably won't
@@ -2095,7 +2087,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/applicom.c b/drivers/char/applicom.c
--- a/drivers/char/applicom.c	2004-10-18 14:57:04 -07:00
+++ b/drivers/char/applicom.c	2004-10-18 14:57:04 -07:00
@@ -89,7 +89,7 @@
 
 static struct applicom_board {
 	unsigned long PhysIO;
-	unsigned long RamIO;
+	void __iomem *RamIO;
 	wait_queue_head_t FlagSleepSend;
 	long irq;
 	spinlock_t mutex;
@@ -127,7 +127,7 @@
 
 static int dummy;	/* dev_id for request_irq() */
 
-static int ac_register_board(unsigned long physloc, unsigned long loc, 
+static int ac_register_board(unsigned long physloc, void __iomem *loc, 
 		      unsigned char boardno)
 {
 	volatile unsigned char byte_reset_it;
@@ -179,11 +179,11 @@
 
 		if (!apbs[i].RamIO)
 			continue;
-		
-		iounmap((void *) apbs[i].RamIO);
 
 		if (apbs[i].irq)
 			free_irq(apbs[i].irq, &dummy);
+
+		iounmap(apbs[i].RamIO);
 	}
 }
 
@@ -193,7 +193,7 @@
 {
 	int i, numisa = 0;
 	struct pci_dev *dev = NULL;
-	void *RamIO;
+	void __iomem *RamIO;
 	int boardno;
 
 	printk(KERN_INFO "Applicom driver: $Id: ac.c,v 1.30 2000/03/22 16:03:57 dwmw2 Exp $\n");
@@ -223,8 +223,8 @@
 		       applicom_pci_devnames[dev->device-1], dev->resource[0].start, 
 		       dev->irq);
 
-		if (!(boardno = ac_register_board(dev->resource[0].start,
-						  (unsigned long)RamIO,0))) {
+		boardno = ac_register_board(dev->resource[0].start, RamIO,0);
+		if (!boardno) {
 			printk(KERN_INFO "ac.o: PCI Applicom device doesn't have correct signature.\n");
 			iounmap(RamIO);
 			pci_disable_device(dev);
@@ -235,7 +235,7 @@
 			printk(KERN_INFO "Could not allocate IRQ %d for PCI Applicom device.\n", dev->irq);
 			iounmap(RamIO);
 			pci_disable_device(dev);
-			apbs[boardno - 1].RamIO = 0;
+			apbs[boardno - 1].RamIO = NULL;
 			continue;
 		}
 
@@ -270,7 +270,7 @@
 		}
 
 		if (!(boardno = ac_register_board((unsigned long)mem+ (LEN_RAM_IO*i),
-						  (unsigned long)RamIO,i+1))) {
+						  RamIO,i+1))) {
 			iounmap(RamIO);
 			continue;
 		}
@@ -280,8 +280,8 @@
 		if (!numisa) {
 			if (request_irq(irq, &ac_interrupt, SA_SHIRQ, "Applicom ISA", &dummy)) {
 				printk(KERN_WARNING "Could not allocate IRQ %d for ISA Applicom device.\n", irq);
-				iounmap((void *) RamIO);
-				apbs[boardno - 1].RamIO = 0;
+				iounmap(RamIO);
+				apbs[boardno - 1].RamIO = NULL;
 			}
 			else
 				apbs[boardno - 1].irq = irq;
@@ -449,7 +449,7 @@
 	   because it works with 2.2 still */
 	{
 		unsigned char *from = (unsigned char *) &tmpmailbox;
-		unsigned long to = (unsigned long) apbs[IndexCard].RamIO + RAM_FROM_PC;
+		void __iomem *to = apbs[IndexCard].RamIO + RAM_FROM_PC;
 		int c;
 
 		for (c = 0; c < sizeof(struct mailbox); c++)
@@ -470,7 +470,7 @@
 static int do_ac_read(int IndexCard, char __user *buf,
 		struct st_ram_io *st_loc, struct mailbox *mailbox)
 {
-	unsigned long from = (unsigned long)apbs[IndexCard].RamIO + RAM_TO_PC;
+	void __iomem *from = apbs[IndexCard].RamIO + RAM_TO_PC;
 	unsigned char *to = (unsigned char *)&mailbox;
 #ifdef DEBUG
 	int c;
@@ -685,7 +685,7 @@
 {				/* @ ADG ou ATO selon le cas */
 	int i;
 	unsigned char IndexCard;
-	unsigned long pmem;
+	void __iomem *pmem;
 	int ret = 0;
 	volatile unsigned char byte_reset_it;
 	struct st_ram_io *adgl;
diff -Nru a/drivers/char/busmouse.c b/drivers/char/busmouse.c
--- a/drivers/char/busmouse.c	2004-10-18 14:56:49 -07:00
+++ /dev/null	Wed Dec 31 16:00:00 196900
@@ -1,456 +0,0 @@
-/*
- * linux/drivers/char/busmouse.c
- *
- * Copyright (C) 1995 - 1998 Russell King <linux@arm.linux.org.uk>
- *  Protocol taken from original busmouse.c
- *  read() waiting taken from psaux.c
- *
- * Medium-level interface for quadrature or bus mice.
- */
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/sched.h>
-#include <linux/signal.h>
-#include <linux/slab.h>
-#include <linux/errno.h>
-#include <linux/mm.h>
-#include <linux/poll.h>
-#include <linux/miscdevice.h>
-#include <linux/random.h>
-#include <linux/init.h>
-#include <linux/smp_lock.h>
-
-#include <asm/uaccess.h>
-#include <asm/system.h>
-#include <asm/io.h>
-
-#include "busmouse.h"
-
-/* Uncomment this if your mouse drivers expect the kernel to
- * return with EAGAIN if the mouse does not have any events
- * available, even if the mouse is opened in blocking mode.
- * Please report use of this "feature" to the author using the
- * above address.
- */
-/*#define BROKEN_MOUSE*/
-
-struct busmouse_data {
-	struct miscdevice	miscdev;
-	struct busmouse		*ops;
-	spinlock_t		lock;
-
-	wait_queue_head_t	wait;
-	struct fasync_struct	*fasyncptr;
-	char			active;
-	char			buttons;
-	char			ready;
-	int			dxpos;
-	int			dypos;
-};
-
-#define NR_MICE			15
-#define FIRST_MOUSE		0
-#define DEV_TO_MOUSE(inode)	MINOR_TO_MOUSE(iminor(inode))
-#define MINOR_TO_MOUSE(minor)	((minor) - FIRST_MOUSE)
-
-/*
- *	List of mice and guarding semaphore. You must take the semaphore
- *	before you take the misc device semaphore if you need both
- */
- 
-static struct busmouse_data *busmouse_data[NR_MICE];
-static DECLARE_MUTEX(mouse_sem);
-
-/**
- *	busmouse_add_movement - notification of a change of mouse position
- *	@mousedev: mouse number
- *	@dx: delta X movement
- *	@dy: delta Y movement
- *	@buttons: new button state
- *
- *	Updates the mouse position and button information. The mousedev
- *	parameter is the value returned from register_busmouse. The
- *	movement information is updated, and the new button state is
- *	saved.  A waiting user thread is woken.
- */
- 
-void busmouse_add_movementbuttons(int mousedev, int dx, int dy, int buttons)
-{
-	struct busmouse_data *mse = busmouse_data[mousedev];
-	int changed;
-
-	spin_lock(&mse->lock);
-	changed = (dx != 0 || dy != 0 || mse->buttons != buttons);
-
-	if (changed) {
-		add_mouse_randomness((buttons << 16) + (dy << 8) + dx);
-
-		mse->buttons = buttons;
-		mse->dxpos += dx;
-		mse->dypos += dy;
-		mse->ready = 1;
-
-		/*
-		 * keep dx/dy reasonable, but still able to track when X (or
-		 * whatever) must page or is busy (i.e. long waits between
-		 * reads)
-		 */
-		if (mse->dxpos < -2048)
-			mse->dxpos = -2048;
-		if (mse->dxpos > 2048)
-			mse->dxpos = 2048;
-		if (mse->dypos < -2048)
-			mse->dypos = -2048;
-		if (mse->dypos > 2048)
-			mse->dypos = 2048;
-	}
-
-	spin_unlock(&mse->lock);
-
-	if (changed) {
-		wake_up(&mse->wait);
-
-		kill_fasync(&mse->fasyncptr, SIGIO, POLL_IN);
-	}
-}
-
-/**
- *	busmouse_add_movement - notification of a change of mouse position
- *	@mousedev: mouse number
- *	@dx: delta X movement
- *	@dy: delta Y movement
- *
- *	Updates the mouse position. The mousedev parameter is the value
- *	returned from register_busmouse. The movement information is
- *	updated, and a waiting user thread is woken.
- */
- 
-void busmouse_add_movement(int mousedev, int dx, int dy)
-{
-	struct busmouse_data *mse = busmouse_data[mousedev];
-
-	busmouse_add_movementbuttons(mousedev, dx, dy, mse->buttons);
-}
-
-/**
- *	busmouse_add_buttons - notification of a change of button state
- *	@mousedev: mouse number
- *	@clear: mask of buttons to clear
- *	@eor: mask of buttons to change
- *
- *	Updates the button state. The mousedev parameter is the value
- *	returned from register_busmouse. The buttons are updated by:
- *		new_state = (old_state & ~clear) ^ eor
- *	A waiting user thread is woken up.
- */
- 
-void busmouse_add_buttons(int mousedev, int clear, int eor)
-{
-	struct busmouse_data *mse = busmouse_data[mousedev];
-
-	busmouse_add_movementbuttons(mousedev, 0, 0, (mse->buttons & ~clear) ^ eor);
-}
-
-static int busmouse_fasync(int fd, struct file *filp, int on)
-{
-	struct busmouse_data *mse = (struct busmouse_data *)filp->private_data;
-	int retval;
-
-	retval = fasync_helper(fd, filp, on, &mse->fasyncptr);
-	if (retval < 0)
-		return retval;
-	return 0;
-}
-
-static int busmouse_release(struct inode *inode, struct file *file)
-{
-	struct busmouse_data *mse = (struct busmouse_data *)file->private_data;
-	int ret = 0;
-
-	lock_kernel();
-	busmouse_fasync(-1, file, 0);
-
-	down(&mouse_sem); /* to protect mse->active */
-	if (--mse->active == 0) {
-		if (mse->ops->release)
-			ret = mse->ops->release(inode, file);
-		module_put(mse->ops->owner);
-		mse->ready = 0;
-	}
-	unlock_kernel();
-	up( &mouse_sem);
-	
-	return ret;
-}
-
-static int busmouse_open(struct inode *inode, struct file *file)
-{
-	struct busmouse_data *mse;
-	unsigned int mousedev;
-	int ret;
-
-	mousedev = DEV_TO_MOUSE(inode);
-	if (mousedev >= NR_MICE)
-		return -EINVAL;
-
-	down(&mouse_sem);
-	mse = busmouse_data[mousedev];
-	ret = -ENODEV;
-	if (!mse || !mse->ops)	/* shouldn't happen, but... */
-		goto end;
-
-	if (!try_module_get(mse->ops->owner))
-		goto end;
-
-	ret = 0;
-	if (mse->ops->open) {
-		ret = mse->ops->open(inode, file);
-		if (ret)
-			module_put(mse->ops->owner);
-	}
-
-	if (ret)
-		goto end;
-
-	file->private_data = mse;
-
-	if (mse->active++)
-		goto end;
-
-	spin_lock_irq(&mse->lock);
-
-	mse->ready   = 0;
-	mse->dxpos   = 0;
-	mse->dypos   = 0;
-	mse->buttons = mse->ops->init_button_state;
-
-	spin_unlock_irq(&mse->lock);
-end:
-	up(&mouse_sem);
-	return ret;
-}
-
-static ssize_t busmouse_write(struct file *file, const char *buffer, size_t count, loff_t *ppos)
-{
-	return -EINVAL;
-}
-
-static ssize_t busmouse_read(struct file *file, char *buffer, size_t count, loff_t *ppos)
-{
-	struct busmouse_data *mse = (struct busmouse_data *)file->private_data;
-	DECLARE_WAITQUEUE(wait, current);
-	int dxpos, dypos, buttons;
-
-	if (count < 3)
-		return -EINVAL;
-
-	spin_lock_irq(&mse->lock);
-
-	if (!mse->ready) {
-#ifdef BROKEN_MOUSE
-		spin_unlock_irq(&mse->lock);
-		return -EAGAIN;
-#else
-		if (file->f_flags & O_NONBLOCK) {
-			spin_unlock_irq(&mse->lock);
-			return -EAGAIN;
-		}
-
-		add_wait_queue(&mse->wait, &wait);
-repeat:
-		set_current_state(TASK_INTERRUPTIBLE);
-		if (!mse->ready && !signal_pending(current)) {
-			spin_unlock_irq(&mse->lock);
-			schedule();
-			spin_lock_irq(&mse->lock);
-			goto repeat;
-		}
-
-		current->state = TASK_RUNNING;
-		remove_wait_queue(&mse->wait, &wait);
-
-		if (signal_pending(current)) {
-			spin_unlock_irq(&mse->lock);
-			return -ERESTARTSYS;
-		}
-#endif
-	}
-
-	dxpos = mse->dxpos;
-	dypos = mse->dypos;
-	buttons = mse->buttons;
-
-	if (dxpos < -127)
-		dxpos =- 127;
-	if (dxpos > 127)
-		dxpos = 127;
-	if (dypos < -127)
-		dypos =- 127;
-	if (dypos > 127)
-		dypos = 127;
-
-	mse->dxpos -= dxpos;
-	mse->dypos -= dypos;
-
-	/* This is something that many drivers have apparantly
-	 * forgotten...  If the X and Y positions still contain
-	 * information, we still have some info ready for the
-	 * user program...
-	 */
-	mse->ready = mse->dxpos || mse->dypos;
-
-	spin_unlock_irq(&mse->lock);
-
-	/* Write out data to the user.  Format is:
-	 *   byte 0 - identifer (0x80) and (inverted) mouse buttons
-	 *   byte 1 - X delta position +/- 127
-	 *   byte 2 - Y delta position +/- 127
-	 */
-	if (put_user((char)buttons | 128, buffer) ||
-	    put_user((char)dxpos, buffer + 1) ||
-	    put_user((char)dypos, buffer + 2))
-		return -EFAULT;
-
-	if (count > 3 && clear_user(buffer + 3, count - 3))
-		return -EFAULT;
-
-	file->f_dentry->d_inode->i_atime = CURRENT_TIME;
-
-	return count;
-}
-
-/* No kernel lock held - fine */
-static unsigned int busmouse_poll(struct file *file, poll_table *wait)
-{
-	struct busmouse_data *mse = (struct busmouse_data *)file->private_data;
-
-	poll_wait(file, &mse->wait, wait);
-
-	if (mse->ready)
-		return POLLIN | POLLRDNORM;
-
-	return 0;
-}
-
-struct file_operations busmouse_fops=
-{
-	.owner		= THIS_MODULE,
-	.read		= busmouse_read,
-	.write		= busmouse_write,
-	.poll		= busmouse_poll,
-	.open		= busmouse_open,
-	.release	= busmouse_release,
-	.fasync		= busmouse_fasync,
-};
-
-/**
- *	register_busmouse - register a bus mouse interface
- *	@ops: busmouse structure for the mouse
- *
- *	Registers a mouse with the driver. The return is mouse number on
- *	success and a negative errno code on an error. The passed ops
- *	structure most not be freed until the mouser is unregistered
- */
- 
-int register_busmouse(struct busmouse *ops)
-{
-	unsigned int msedev = MINOR_TO_MOUSE(ops->minor);
-	struct busmouse_data *mse;
-	int ret = -EINVAL;
-
-	if (msedev >= NR_MICE) {
-		printk(KERN_ERR "busmouse: trying to allocate mouse on minor %d\n",
-		       ops->minor);
-		goto out;
-	}
-
-	ret = -ENOMEM;
-	mse = kmalloc(sizeof(*mse), GFP_KERNEL);
-	if (!mse)
-		goto out;
-
-	down(&mouse_sem);
-	ret = -EBUSY;
-	if (busmouse_data[msedev])
-		goto freemem;
-
-	memset(mse, 0, sizeof(*mse));
-
-	mse->miscdev.minor = ops->minor;
-	mse->miscdev.name = ops->name;
-	mse->miscdev.fops = &busmouse_fops;
-	mse->ops = ops;
-	mse->lock = (spinlock_t)SPIN_LOCK_UNLOCKED;
-	init_waitqueue_head(&mse->wait);
-
-
-	ret = misc_register(&mse->miscdev);
-
-	if (ret < 0) 
-		goto freemem;
-
-	busmouse_data[msedev] = mse;
-	ret = msedev;
-out:
-	up(&mouse_sem);
-	return ret;
-
-
-freemem:
-	kfree(mse);
-	goto out;
-}
-
-/**
- *	unregister_busmouse - unregister a bus mouse interface
- *	@mousedev: Mouse number to release
- *
- *	Unregister a previously installed mouse handler. The mousedev
- *	passed is the return code from a previous call to register_busmouse
- */
- 
-
-int unregister_busmouse(int mousedev)
-{
-	int err = -EINVAL;
-
-	if (mousedev < 0)
-		return 0;
-	if (mousedev >= NR_MICE) {
-		printk(KERN_ERR "busmouse: trying to free mouse on"
-		       " mousedev %d\n", mousedev);
-		return -EINVAL;
-	}
-
-	down(&mouse_sem);
-	
-	if (!busmouse_data[mousedev]) {
-		printk(KERN_WARNING "busmouse: trying to free free mouse"
-		       " on mousedev %d\n", mousedev);
-		goto fail;
-	}
-
-	if (busmouse_data[mousedev]->active) {
-		printk(KERN_ERR "busmouse: trying to free active mouse"
-		       " on mousedev %d\n", mousedev);
-		goto fail;
-	}
-
-	err = misc_deregister(&busmouse_data[mousedev]->miscdev);
-
-	kfree(busmouse_data[mousedev]);
-	busmouse_data[mousedev] = NULL;
-fail:
-	up(&mouse_sem);
-	return err;
-}
-
-EXPORT_SYMBOL(busmouse_add_movementbuttons);
-EXPORT_SYMBOL(busmouse_add_movement);
-EXPORT_SYMBOL(busmouse_add_buttons);
-EXPORT_SYMBOL(register_busmouse);
-EXPORT_SYMBOL(unregister_busmouse);
-
-MODULE_ALIAS_MISCDEV(BUSMOUSE_MINOR);
-MODULE_LICENSE("GPL");
diff -Nru a/drivers/char/busmouse.h b/drivers/char/busmouse.h
--- a/drivers/char/busmouse.h	2004-10-18 14:55:54 -07:00
+++ /dev/null	Wed Dec 31 16:00:00 196900
@@ -1,27 +0,0 @@
-/*
- * linux/drivers/char/busmouse.h
- *
- * Copyright (C) 1995 - 1998 Russell King
- *
- * Prototypes for generic busmouse interface
- */
-#ifndef BUSMOUSE_H
-#define BUSMOUSE_H
-
-struct busmouse {
-	int minor;
-	const char *name;
-	struct module *owner;
-	int (*open)(struct inode * inode, struct file * file);
-	int (*release)(struct inode * inode, struct file * file);
-	int init_button_state;
-};
-
-extern void busmouse_add_movementbuttons(int mousedev, int dx, int dy, int buttons);
-extern void busmouse_add_movement(int mousedev, int dx, int dy);
-extern void busmouse_add_buttons(int mousedev, int clear, int eor);
-
-extern int register_busmouse(struct busmouse *ops);
-extern int unregister_busmouse(int mousedev);
-
-#endif
diff -Nru a/drivers/char/cyclades.c b/drivers/char/cyclades.c
--- a/drivers/char/cyclades.c	2004-10-18 14:56:17 -07:00
+++ b/drivers/char/cyclades.c	2004-10-18 14:56:17 -07:00
@@ -682,13 +682,13 @@
 #define IS_CYC_Z(card) ((card).num_chips == -1)
 
 #define Z_FPGA_CHECK(card) \
-    ((cy_readl(&((struct RUNTIME_9060 *) \
+    ((cy_readl(&((struct RUNTIME_9060 __iomem *) \
 		 ((card).ctl_addr))->init_ctrl) & (1<<17)) != 0)
 
-#define ISZLOADED(card)	(((ZO_V1==cy_readl(&((struct RUNTIME_9060 *) \
+#define ISZLOADED(card)	(((ZO_V1==cy_readl(&((struct RUNTIME_9060 __iomem *) \
 			((card).ctl_addr))->mail_box_0)) || \
 			Z_FPGA_CHECK(card)) && \
-			(ZFIRM_ID==cy_readl(&((struct FIRM_ID *) \
+			(ZFIRM_ID==cy_readl(&((struct FIRM_ID __iomem *) \
 			((card).base_addr+ID_ADDRESS))->signature)))
 
 #ifndef SERIAL_XMIT_SIZE
@@ -712,16 +712,16 @@
    boot options line.  The form is "cyclades=address,address..."
 */
 
-static unsigned char *cy_isa_addresses[] = {
-        (unsigned char *) 0xD0000,
-        (unsigned char *) 0xD2000,
-        (unsigned char *) 0xD4000,
-        (unsigned char *) 0xD6000,
-        (unsigned char *) 0xD8000,
-        (unsigned char *) 0xDA000,
-        (unsigned char *) 0xDC000,
-        (unsigned char *) 0xDE000,
-        NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL
+static unsigned int cy_isa_addresses[] = {
+        0xD0000,
+        0xD2000,
+        0xD4000,
+        0xD6000,
+        0xD8000,
+        0xDA000,
+        0xDC000,
+        0xDE000,
+        0,0,0,0,0,0,0,0
 };
 #define NR_ISA_ADDRS (sizeof(cy_isa_addresses)/sizeof(unsigned char*))
 
@@ -854,7 +854,7 @@
 static void set_line_char(struct cyclades_port *);
 static int cyz_issue_cmd(struct cyclades_card *, uclong, ucchar, uclong);
 #ifdef CONFIG_ISA
-static unsigned detect_isa_irq (volatile ucchar *);
+static unsigned detect_isa_irq(void __iomem *);
 #endif /* CONFIG_ISA */
 
 static int cyclades_get_proc_info(char *, char **, off_t , int , int *, void *);
@@ -970,10 +970,7 @@
 	wake_up_interruptible(&info->delta_msr_wait);
     }
     if (test_and_clear_bit(Cy_EVENT_WRITE_WAKEUP, &info->event)) {
-        if((tty->flags & (1<< TTY_DO_WRITE_WAKEUP))
-        && tty->ldisc.write_wakeup){
-            (tty->ldisc.write_wakeup)(tty);
-        }
+        tty_wakeup(tty);
         wake_up_interruptible(&tty->write_wait);
     }
 #ifdef Z_WAKE
@@ -995,7 +992,7 @@
    This function is only called from inside spinlock-protected code.
  */
 static int
-cyy_issue_cmd(volatile ucchar *base_addr, u_char cmd, int index)
+cyy_issue_cmd(void __iomem *base_addr, u_char cmd, int index)
 {
   volatile int  i;
 
@@ -1011,7 +1008,7 @@
     if (i == 100)	return (-1);
 
     /* Issue the new command */
-    cy_writeb((u_long)base_addr+(CyCCR<<index), cmd);
+    cy_writeb(base_addr+(CyCCR<<index), cmd);
 
     return(0);
 } /* cyy_issue_cmd */
@@ -1019,7 +1016,7 @@
 #ifdef CONFIG_ISA
 /* ISA interrupt detection code */
 static unsigned 
-detect_isa_irq (volatile ucchar *address)
+detect_isa_irq(void __iomem *address)
 {
   int irq;
   unsigned long irqs, flags;
@@ -1030,7 +1027,7 @@
     irq = probe_irq_off(probe_irq_on());
 
     /* Clear interrupts on the board first */
-    cy_writeb((u_long)address + (Cy_ClrIntr<<index), 0);
+    cy_writeb(address + (Cy_ClrIntr<<index), 0);
 			      /* Cy_ClrIntr is 0x1800 */
 
     irqs = probe_irq_on();
@@ -1039,11 +1036,11 @@
 
     /* Enable the Tx interrupts on the CD1400 */
     local_irq_save(flags);
-	cy_writeb((u_long)address + (CyCAR<<index), 0);
+	cy_writeb(address + (CyCAR<<index), 0);
 	cyy_issue_cmd(address, CyCHAN_CTL|CyENB_XMTR, index);
 
-	cy_writeb((u_long)address + (CyCAR<<index), 0);
-	cy_writeb((u_long)address + (CySRER<<index), 
+	cy_writeb(address + (CyCAR<<index), 0);
+	cy_writeb(address + (CySRER<<index), 
 		cy_readb(address + (CySRER<<index)) | CyTxRdy);
     local_irq_restore(flags);
 
@@ -1056,12 +1053,12 @@
     /* Clean up */
     save_xir = (u_char) cy_readb(address + (CyTIR<<index));
     save_car = cy_readb(address + (CyCAR<<index));
-    cy_writeb((u_long)address + (CyCAR<<index), (save_xir & 0x3));
-    cy_writeb((u_long)address + (CySRER<<index),
+    cy_writeb(address + (CyCAR<<index), (save_xir & 0x3));
+    cy_writeb(address + (CySRER<<index),
 	cy_readb(address + (CySRER<<index)) & ~CyTxRdy);
-    cy_writeb((u_long)address + (CyTIR<<index), (save_xir & 0x3f));
-    cy_writeb((u_long)address + (CyCAR<<index), (save_car));
-    cy_writeb((u_long)address + (Cy_ClrIntr<<index), 0);
+    cy_writeb(address + (CyTIR<<index), (save_xir & 0x3f));
+    cy_writeb(address + (CyCAR<<index), (save_car));
+    cy_writeb(address + (Cy_ClrIntr<<index), 0);
 			      /* Cy_ClrIntr is 0x1800 */
 
     return (irq > 0)? irq : 0;
@@ -1079,7 +1076,7 @@
   int status;
   struct cyclades_card *cinfo;
   struct cyclades_port *info;
-  volatile unsigned char *base_addr, *card_base_addr;
+  void __iomem *base_addr, *card_base_addr;
   int chip;
   int save_xir, channel, save_car;
   char data;
@@ -1098,7 +1095,7 @@
         return IRQ_NONE; /* spurious interrupt */
     }
 
-    card_base_addr = (unsigned char *)cinfo->base_addr;
+    card_base_addr = cinfo->base_addr;
     index = cinfo->bus_index;
 
 
@@ -1110,8 +1107,7 @@
     do{
         had_work = 0;
         for ( chip = 0 ; chip < cinfo->num_chips ; chip ++) {
-            base_addr = (unsigned char *)
-		       (cinfo->base_addr + (cy_chip_offset[chip]<<index));
+            base_addr = cinfo->base_addr + (cy_chip_offset[chip]<<index);
             too_many = 0;
             while ( (status = cy_readb(base_addr+(CySVRR<<index))) != 0x00) {
                 had_work++;
@@ -1135,7 +1131,7 @@
                     info = &cy_port[i];
                     info->last_active = jiffies;
                     save_car = cy_readb(base_addr+(CyCAR<<index));
-                    cy_writeb((u_long)base_addr+(CyCAR<<index), save_xir);
+                    cy_writeb(base_addr+(CyCAR<<index), save_xir);
 
                     /* if there is nowhere to put the data, discard it */
                     if(info->tty == 0){
@@ -1264,8 +1260,8 @@
                         schedule_delayed_work(&tty->flip.work, 1);
                     }
                     /* end of service */
-                    cy_writeb((u_long)base_addr+(CyRIR<<index), (save_xir & 0x3f));
-                    cy_writeb((u_long)base_addr+(CyCAR<<index), (save_car));
+                    cy_writeb(base_addr+(CyRIR<<index), (save_xir & 0x3f));
+                    cy_writeb(base_addr+(CyCAR<<index), (save_car));
 		    spin_unlock(&cinfo->card_lock);
                 }
 
@@ -1284,18 +1280,18 @@
                     channel = (u_short ) (save_xir & CyIRChannel);
                     i = channel + chip * 4 + cinfo->first_line;
                     save_car = cy_readb(base_addr+(CyCAR<<index));
-                    cy_writeb((u_long)base_addr+(CyCAR<<index), save_xir);
+                    cy_writeb(base_addr+(CyCAR<<index), save_xir);
 
                     /* validate the port# (as configured and open) */
                     if( (i < 0) || (NR_PORTS <= i) ){
-                        cy_writeb((u_long)base_addr+(CySRER<<index),
+                        cy_writeb(base_addr+(CySRER<<index),
                              cy_readb(base_addr+(CySRER<<index)) & ~CyTxRdy);
                         goto txend;
                     }
                     info = &cy_port[i];
                     info->last_active = jiffies;
                     if(info->tty == 0){
-                        cy_writeb((u_long)base_addr+(CySRER<<index),
+                        cy_writeb(base_addr+(CySRER<<index),
                              cy_readb(base_addr+(CySRER<<index)) & ~CyTxRdy);
                         goto txdone;
                     }
@@ -1305,7 +1301,7 @@
 
                     if(info->x_char) { /* send special char */
                         outch = info->x_char;
-                        cy_writeb((u_long)base_addr+(CyTDR<<index), outch);
+                        cy_writeb(base_addr+(CyTDR<<index), outch);
                         char_count--;
 			info->icount.tx++;
                         info->x_char = 0;
@@ -1313,14 +1309,14 @@
 
                     if (info->breakon || info->breakoff) {
 			if (info->breakon) {
-			    cy_writeb((u_long)base_addr + (CyTDR<<index), 0); 
-			    cy_writeb((u_long)base_addr + (CyTDR<<index), 0x81);
+			    cy_writeb(base_addr + (CyTDR<<index), 0); 
+			    cy_writeb(base_addr + (CyTDR<<index), 0x81);
 			    info->breakon = 0;
                             char_count -= 2;
 			}
 			if (info->breakoff) {
-			    cy_writeb((u_long)base_addr + (CyTDR<<index), 0); 
-			    cy_writeb((u_long)base_addr + (CyTDR<<index), 0x83);
+			    cy_writeb(base_addr + (CyTDR<<index), 0); 
+			    cy_writeb(base_addr + (CyTDR<<index), 0x83);
 			    info->breakoff = 0;
                             char_count -= 2;
 			}
@@ -1329,11 +1325,11 @@
                     while (char_count-- > 0){
 			if (!info->xmit_cnt){
 			    if (cy_readb(base_addr+(CySRER<<index))&CyTxMpty) {
-				cy_writeb((u_long)base_addr+(CySRER<<index),
+				cy_writeb(base_addr+(CySRER<<index),
 					  cy_readb(base_addr+(CySRER<<index)) &
 					  ~CyTxMpty);
 			    } else {
-				cy_writeb((u_long)base_addr+(CySRER<<index),
+				cy_writeb(base_addr+(CySRER<<index),
 					  ((cy_readb(base_addr+(CySRER<<index))
 					    & ~CyTxRdy)
 					   | CyTxMpty));
@@ -1341,13 +1337,13 @@
 			    goto txdone;
 			}
 			if (info->xmit_buf == 0){
-                            cy_writeb((u_long)base_addr+(CySRER<<index),
+                            cy_writeb(base_addr+(CySRER<<index),
 				cy_readb(base_addr+(CySRER<<index)) & 
 					~CyTxRdy);
                             goto txdone;
 			}
 			if (info->tty->stopped || info->tty->hw_stopped){
-                            cy_writeb((u_long)base_addr+(CySRER<<index),
+                            cy_writeb(base_addr+(CySRER<<index),
 				cy_readb(base_addr+(CySRER<<index)) & 
 					~CyTxRdy);
                             goto txdone;
@@ -1368,16 +1364,16 @@
                             info->xmit_cnt--;
                             info->xmit_tail = (info->xmit_tail + 1)
                                                       & (SERIAL_XMIT_SIZE - 1);
-                            cy_writeb((u_long)base_addr+(CyTDR<<index), outch);
+                            cy_writeb(base_addr+(CyTDR<<index), outch);
 			    info->icount.tx++;
                         }else{
                             if(char_count > 1){
                                 info->xmit_cnt--;
                                 info->xmit_tail = (info->xmit_tail + 1)
 						      & (SERIAL_XMIT_SIZE - 1);
-                                cy_writeb((u_long)base_addr+(CyTDR<<index), 
+                                cy_writeb(base_addr+(CyTDR<<index), 
 					  outch);
-                                cy_writeb((u_long)base_addr+(CyTDR<<index), 0);
+                                cy_writeb(base_addr+(CyTDR<<index), 0);
 				info->icount.tx++;
                                 char_count--;
                             }else{
@@ -1391,9 +1387,9 @@
                     }
         txend:
                     /* end of service */
-                    cy_writeb((u_long)base_addr+(CyTIR<<index), 
+                    cy_writeb(base_addr+(CyTIR<<index), 
 			      (save_xir & 0x3f));
-                    cy_writeb((u_long)base_addr+(CyCAR<<index), (save_car));
+                    cy_writeb(base_addr+(CyCAR<<index), (save_car));
 		    spin_unlock(&cinfo->card_lock);
                 }
 
@@ -1407,7 +1403,7 @@
 		                           + cinfo->first_line];
                     info->last_active = jiffies;
                     save_car = cy_readb(base_addr+(CyCAR<<index));
-                    cy_writeb((u_long)base_addr+(CyCAR<<index), save_xir);
+                    cy_writeb(base_addr+(CyCAR<<index), save_xir);
 
                     mdm_change = cy_readb(base_addr+(CyMISR<<index));
                     mdm_status = cy_readb(base_addr+(CyMSVR1<<index));
@@ -1442,7 +1438,7 @@
                                     /* cy_start isn't used
 				         because... !!! */
                                     info->tty->hw_stopped = 0;
-                                  cy_writeb((u_long)base_addr+(CySRER<<index),
+                                  cy_writeb(base_addr+(CySRER<<index),
                                        cy_readb(base_addr+(CySRER<<index)) | 
                                        CyTxRdy);
                                     cy_sched_event(info,
@@ -1453,7 +1449,7 @@
                                     /* cy_stop isn't used
 				         because ... !!! */
                                     info->tty->hw_stopped = 1;
-                                  cy_writeb((u_long)base_addr+(CySRER<<index),
+                                  cy_writeb(base_addr+(CySRER<<index),
                                        cy_readb(base_addr+(CySRER<<index)) & 
                                        ~CyTxRdy);
                                 }
@@ -1465,9 +1461,9 @@
                         }
                     }
                     /* end of service */
-                    cy_writeb((u_long)base_addr+(CyMIR<<index), 
+                    cy_writeb(base_addr+(CyMIR<<index), 
 			      (save_xir & 0x3f));
-                    cy_writeb((u_long)base_addr+(CyCAR<<index), save_car);
+                    cy_writeb(base_addr+(CyCAR<<index), save_car);
 		    spin_unlock(&cinfo->card_lock);
                 }
             }          /* end while status != 0 */
@@ -1476,7 +1472,7 @@
 
    /* clear interrupts */
    spin_lock(&cinfo->card_lock);
-   cy_writeb((u_long)card_base_addr + (Cy_ClrIntr<<index), 0);
+   cy_writeb(card_base_addr + (Cy_ClrIntr<<index), 0);
                                 /* Cy_ClrIntr is 0x1800 */
    spin_unlock(&cinfo->card_lock);
    return IRQ_HANDLED;
@@ -1491,27 +1487,25 @@
 cyz_fetch_msg( struct cyclades_card *cinfo,
 	    uclong *channel, ucchar *cmd, uclong *param)
 {
-  struct FIRM_ID *firm_id;
-  struct ZFW_CTRL *zfw_ctrl;
-  struct BOARD_CTRL *board_ctrl;
+  struct FIRM_ID __iomem *firm_id;
+  struct ZFW_CTRL __iomem *zfw_ctrl;
+  struct BOARD_CTRL __iomem *board_ctrl;
   unsigned long loc_doorbell;
 
-    firm_id = (struct FIRM_ID *)(cinfo->base_addr + ID_ADDRESS);
+    firm_id = cinfo->base_addr + ID_ADDRESS;
     if (!ISZLOADED(*cinfo)){
 	return (-1);
     }
-    zfw_ctrl = (struct ZFW_CTRL *)
-		(cinfo->base_addr + 
-		 (cy_readl(&firm_id->zfwctrl_addr) & 0xfffff));
+    zfw_ctrl = cinfo->base_addr + (cy_readl(&firm_id->zfwctrl_addr) & 0xfffff);
     board_ctrl = &zfw_ctrl->board_ctrl;
 
-    loc_doorbell = cy_readl(&((struct RUNTIME_9060 *)
+    loc_doorbell = cy_readl(&((struct RUNTIME_9060 __iomem *)
                      (cinfo->ctl_addr))->loc_doorbell);
     if (loc_doorbell){
 	*cmd = (char)(0xff & loc_doorbell);
 	*channel = cy_readl(&board_ctrl->fwcmd_channel);
 	*param = (uclong)cy_readl(&board_ctrl->fwcmd_param);
-	cy_writel(&((struct RUNTIME_9060 *)(cinfo->ctl_addr))->loc_doorbell, 
+	cy_writel(&((struct RUNTIME_9060 __iomem *)(cinfo->ctl_addr))->loc_doorbell, 
                  0xffffffff);
 	return 1;
     }
@@ -1522,40 +1516,38 @@
 cyz_issue_cmd( struct cyclades_card *cinfo,
 	    uclong channel, ucchar cmd, uclong param)
 {
-  struct FIRM_ID *firm_id;
-  struct ZFW_CTRL *zfw_ctrl;
-  struct BOARD_CTRL *board_ctrl;
-  volatile uclong *pci_doorbell;
+  struct FIRM_ID __iomem *firm_id;
+  struct ZFW_CTRL __iomem *zfw_ctrl;
+  struct BOARD_CTRL __iomem *board_ctrl;
+  unsigned long __iomem *pci_doorbell;
   int index;
 
-    firm_id = (struct FIRM_ID *)(cinfo->base_addr + ID_ADDRESS);
+    firm_id = cinfo->base_addr + ID_ADDRESS;
     if (!ISZLOADED(*cinfo)){
 	return (-1);
     }
-    zfw_ctrl = (struct ZFW_CTRL *)
-		(cinfo->base_addr + 
-		 (cy_readl(&firm_id->zfwctrl_addr) & 0xfffff));
+    zfw_ctrl = cinfo->base_addr + (cy_readl(&firm_id->zfwctrl_addr) & 0xfffff);
     board_ctrl = &zfw_ctrl->board_ctrl;
 
     index = 0;
-    pci_doorbell = (uclong *)(&((struct RUNTIME_9060 *)
-                               (cinfo->ctl_addr))->pci_doorbell);
+    pci_doorbell = &((struct RUNTIME_9060 __iomem *) (cinfo->ctl_addr))->pci_doorbell;
     while( (cy_readl(pci_doorbell) & 0xff) != 0){
         if (index++ == 1000){
 	    return((int)(cy_readl(pci_doorbell) & 0xff));
         }
 	udelay(50L);
     }
-    cy_writel((u_long)&board_ctrl->hcmd_channel, channel);
-    cy_writel((u_long)&board_ctrl->hcmd_param , param);
-    cy_writel((u_long)pci_doorbell, (long)cmd);
+    cy_writel(&board_ctrl->hcmd_channel, channel);
+    cy_writel(&board_ctrl->hcmd_param , param);
+    cy_writel(pci_doorbell, (long)cmd);
 
     return(0);
 } /* cyz_issue_cmd */
 
 static void
-cyz_handle_rx(struct cyclades_port *info, volatile struct CH_CTRL *ch_ctrl,
-	      volatile struct BUF_CTRL *buf_ctrl)
+cyz_handle_rx(struct cyclades_port *info,
+	      volatile struct CH_CTRL __iomem *ch_ctrl,
+	      volatile struct BUF_CTRL __iomem *buf_ctrl)
 {
   struct cyclades_card *cinfo = &cy_card[info->card];
   struct tty_struct *tty = info->tty;
@@ -1652,8 +1644,9 @@
 }
 
 static void
-cyz_handle_tx(struct cyclades_port *info, volatile struct CH_CTRL *ch_ctrl,
-	      volatile struct BUF_CTRL *buf_ctrl)
+cyz_handle_tx(struct cyclades_port *info,
+	      volatile struct CH_CTRL __iomem *ch_ctrl,
+	      volatile struct BUF_CTRL __iomem *buf_ctrl)
 {
   struct cyclades_card *cinfo = &cy_card[info->card];
   struct tty_struct *tty = info->tty;
@@ -1740,11 +1733,11 @@
 {
   struct tty_struct *tty;
   struct cyclades_port *info;
-  static volatile struct FIRM_ID *firm_id;
-  static volatile struct ZFW_CTRL *zfw_ctrl;
-  static volatile struct BOARD_CTRL *board_ctrl;
-  static volatile struct CH_CTRL *ch_ctrl;
-  static volatile struct BUF_CTRL *buf_ctrl;
+  static volatile struct FIRM_ID __iomem *firm_id;
+  static volatile struct ZFW_CTRL __iomem *zfw_ctrl;
+  static volatile struct BOARD_CTRL __iomem *board_ctrl;
+  static volatile struct CH_CTRL __iomem *ch_ctrl;
+  static volatile struct BUF_CTRL __iomem *buf_ctrl;
   uclong channel;
   ucchar cmd;
   uclong param;
@@ -1752,13 +1745,11 @@
   int special_count;
   int delta_count;
 
-    firm_id = (struct FIRM_ID *)(cinfo->base_addr + ID_ADDRESS);
-    zfw_ctrl = (struct ZFW_CTRL *)
-		(cinfo->base_addr + 
-		 (cy_readl(&firm_id->zfwctrl_addr) & 0xfffff));
-    board_ctrl = &(zfw_ctrl->board_ctrl);
+    firm_id = cinfo->base_addr + ID_ADDRESS;
+    zfw_ctrl = cinfo->base_addr + (cy_readl(&firm_id->zfwctrl_addr) & 0xfffff);
+    board_ctrl = &zfw_ctrl->board_ctrl;
     fw_ver = cy_readl(&board_ctrl->fw_version);
-    hw_ver = cy_readl(&((struct RUNTIME_9060 *)(cinfo->ctl_addr))->mail_box_0);
+    hw_ver = cy_readl(&((struct RUNTIME_9060 __iomem *)(cinfo->ctl_addr))->mail_box_0);
 
 
     while(cyz_fetch_msg(cinfo, &channel, &cmd, &param) == 1) {
@@ -1925,10 +1916,8 @@
 	if (!IS_CYC_Z(*cinfo)) continue;
 	if (!ISZLOADED(*cinfo)) continue;
 
-	firm_id = (struct FIRM_ID *)(cinfo->base_addr + ID_ADDRESS);
-	zfw_ctrl = (struct ZFW_CTRL *)
-		    (cinfo->base_addr + 
-		     (cy_readl(&firm_id->zfwctrl_addr) & 0xfffff));
+	firm_id = cinfo->base_addr + ID_ADDRESS;
+	zfw_ctrl = cinfo->base_addr + (cy_readl(&firm_id->zfwctrl_addr) & 0xfffff);
 	board_ctrl = &(zfw_ctrl->board_ctrl);
 
 	/* Skip first polling cycle to avoid racing conditions with the FW */
@@ -1972,7 +1961,7 @@
 {
   unsigned long flags;
   int retval = 0;
-  unsigned char *base_addr;
+  void __iomem *base_addr;
   int card,chip,channel,index;
   unsigned long page;
 
@@ -2011,8 +2000,7 @@
 	chip = channel>>2;
 	channel &= 0x03;
 	index = cy_card[card].bus_index;
-	base_addr = (unsigned char*)
-		   (cy_card[card].base_addr + (cy_chip_offset[chip]<<index));
+	base_addr = cy_card[card].base_addr + (cy_chip_offset[chip]<<index);
 
 #ifdef CY_DEBUG_OPEN
 	printk("cyc startup card %d, chip %d, channel %d, base_addr %lx\n",
@@ -2021,16 +2009,16 @@
 
 	CY_LOCK(info, flags);
 
-	cy_writeb((ulong)base_addr+(CyCAR<<index), (u_char)channel);
+	cy_writeb(base_addr+(CyCAR<<index), (u_char)channel);
 
-	cy_writeb((ulong)base_addr+(CyRTPR<<index), (info->default_timeout
+	cy_writeb(base_addr+(CyRTPR<<index), (info->default_timeout
 		 ? info->default_timeout : 0x02)); /* 10ms rx timeout */
 
 	cyy_issue_cmd(base_addr,CyCHAN_CTL|CyENB_RCVR|CyENB_XMTR,index);
 
-	cy_writeb((ulong)base_addr+(CyCAR<<index), (u_char)channel);
-	cy_writeb((ulong)base_addr+(CyMSVR1<<index), CyRTS);
-	cy_writeb((ulong)base_addr+(CyMSVR2<<index), CyDTR);
+	cy_writeb(base_addr+(CyCAR<<index), (u_char)channel);
+	cy_writeb(base_addr+(CyMSVR1<<index), CyRTS);
+	cy_writeb(base_addr+(CyMSVR2<<index), CyDTR);
 
 #ifdef CY_DEBUG_DTR
 	printk("cyc:startup raising DTR\n");
@@ -2039,7 +2027,7 @@
                 cy_readb(base_addr+(CyMSVR2<<index)));
 #endif
 
-	cy_writeb((u_long)base_addr+(CySRER<<index),
+	cy_writeb(base_addr+(CySRER<<index),
 		cy_readb(base_addr+(CySRER<<index)) | CyRxData);
 	info->flags |= ASYNC_INITIALIZED;
 
@@ -2056,22 +2044,20 @@
 	CY_UNLOCK(info, flags);
 
     } else {
-      struct FIRM_ID *firm_id;
-      struct ZFW_CTRL *zfw_ctrl;
-      struct BOARD_CTRL *board_ctrl;
-      struct CH_CTRL *ch_ctrl;
+      struct FIRM_ID __iomem *firm_id;
+      struct ZFW_CTRL __iomem *zfw_ctrl;
+      struct BOARD_CTRL __iomem *board_ctrl;
+      struct CH_CTRL __iomem *ch_ctrl;
       int retval;
 
-	base_addr = (unsigned char*) (cy_card[card].base_addr);
+	base_addr = cy_card[card].base_addr;
 
-        firm_id = (struct FIRM_ID *) (base_addr + ID_ADDRESS);
+        firm_id = base_addr + ID_ADDRESS;
         if (!ISZLOADED(cy_card[card])){
 	    return -ENODEV;
 	}
 
-	zfw_ctrl = (struct ZFW_CTRL *)
-		    (cy_card[card].base_addr + 
-		     (cy_readl(&firm_id->zfwctrl_addr) & 0xfffff));
+	zfw_ctrl = cy_card[card].base_addr + (cy_readl(&firm_id->zfwctrl_addr) & 0xfffff);
 	board_ctrl = &zfw_ctrl->board_ctrl;
 	ch_ctrl = zfw_ctrl->ch_ctrl;
 
@@ -2163,7 +2149,7 @@
 start_xmit( struct cyclades_port *info )
 {
   unsigned long flags;
-  unsigned char *base_addr;
+  void __iomem *base_addr;
   int card,chip,channel,index;
 
     card = info->card;
@@ -2172,13 +2158,11 @@
 	chip = channel>>2;
 	channel &= 0x03;
 	index = cy_card[card].bus_index;
-	base_addr = (unsigned char*)
-		       (cy_card[card].base_addr
-		       + (cy_chip_offset[chip]<<index));
+	base_addr = cy_card[card].base_addr + (cy_chip_offset[chip]<<index);
 
 	CY_LOCK(info, flags);
-	    cy_writeb((u_long)base_addr+(CyCAR<<index), channel);
-	    cy_writeb((u_long)base_addr+(CySRER<<index), 
+	    cy_writeb(base_addr+(CyCAR<<index), channel);
+	    cy_writeb(base_addr+(CySRER<<index), 
                cy_readb(base_addr+(CySRER<<index)) | CyTxRdy);
 	CY_UNLOCK(info, flags);
     } else {
@@ -2206,7 +2190,7 @@
 shutdown(struct cyclades_port * info)
 {
   unsigned long flags;
-  unsigned char *base_addr;
+  void __iomem *base_addr;
   int card,chip,channel,index;
 
     if (!(info->flags & ASYNC_INITIALIZED)){
@@ -2219,9 +2203,7 @@
 	chip = channel>>2;
 	channel &= 0x03;
 	index = cy_card[card].bus_index;
-	base_addr = (unsigned char*)
-		       (cy_card[card].base_addr
-		       + (cy_chip_offset[chip]<<index));
+	base_addr = cy_card[card].base_addr + (cy_chip_offset[chip]<<index);
 
 #ifdef CY_DEBUG_OPEN
     printk("cyc shutdown Y card %d, chip %d, channel %d, base_addr %lx\n",
@@ -2239,10 +2221,10 @@
 		info->xmit_buf = NULL;
 		free_page((unsigned long) temp);
 	    }
-	    cy_writeb((u_long)base_addr+(CyCAR<<index), (u_char)channel);
+	    cy_writeb(base_addr+(CyCAR<<index), (u_char)channel);
 	    if (!info->tty || (info->tty->termios->c_cflag & HUPCL)) {
-		cy_writeb((u_long)base_addr+(CyMSVR1<<index), ~CyRTS);
-		cy_writeb((u_long)base_addr+(CyMSVR2<<index), ~CyDTR);
+		cy_writeb(base_addr+(CyMSVR1<<index), ~CyRTS);
+		cy_writeb(base_addr+(CyMSVR2<<index), ~CyDTR);
 #ifdef CY_DEBUG_DTR
 		printk("cyc shutdown dropping DTR\n");
 		printk("     status: 0x%x, 0x%x\n",
@@ -2260,27 +2242,25 @@
 	    info->flags &= ~ASYNC_INITIALIZED;
 	CY_UNLOCK(info, flags);
     } else {
-      struct FIRM_ID *firm_id;
-      struct ZFW_CTRL *zfw_ctrl;
-      struct BOARD_CTRL *board_ctrl;
-      struct CH_CTRL *ch_ctrl;
+      struct FIRM_ID __iomem *firm_id;
+      struct ZFW_CTRL __iomem *zfw_ctrl;
+      struct BOARD_CTRL __iomem *board_ctrl;
+      struct CH_CTRL __iomem *ch_ctrl;
       int retval;
 
-	base_addr = (unsigned char*) (cy_card[card].base_addr);
+	base_addr = cy_card[card].base_addr;
 #ifdef CY_DEBUG_OPEN
     printk("cyc shutdown Z card %d, channel %d, base_addr %lx\n",
 		card, channel, (long)base_addr);
 #endif
 
-        firm_id = (struct FIRM_ID *) (base_addr + ID_ADDRESS);
+        firm_id = base_addr + ID_ADDRESS;
         if (!ISZLOADED(cy_card[card])) {
 	    return;
 	}
 
-	zfw_ctrl = (struct ZFW_CTRL *)
-		    (cy_card[card].base_addr + 
-		     (cy_readl(&firm_id->zfwctrl_addr) & 0xfffff));
-	board_ctrl = &(zfw_ctrl->board_ctrl);
+	zfw_ctrl = cy_card[card].base_addr + (cy_readl(&firm_id->zfwctrl_addr) & 0xfffff);
+	board_ctrl = &zfw_ctrl->board_ctrl;
 	ch_ctrl = zfw_ctrl->ch_ctrl;
 
 	CY_LOCK(info, flags);
@@ -2293,7 +2273,7 @@
 	    }
 	    
 	    if (!info->tty || (info->tty->termios->c_cflag & HUPCL)) {
-		cy_writel((u_long)&ch_ctrl[channel].rs_control,
+		cy_writel(&ch_ctrl[channel].rs_control,
                    (uclong)(cy_readl(&ch_ctrl[channel].rs_control) & 
                    ~(C_RS_RTS | C_RS_DTR)));
 		retval = cyz_issue_cmd(&cy_card[info->card],
@@ -2337,7 +2317,7 @@
   unsigned long flags;
   int chip, channel,index;
   int retval;
-  char *base_addr;
+  void __iomem *base_addr;
 
     cinfo = &cy_card[info->card];
     channel = info->line - cinfo->first_line;
@@ -2390,15 +2370,14 @@
 	chip = channel>>2;
 	channel &= 0x03;
 	index = cinfo->bus_index;
-	base_addr = (char *)(cinfo->base_addr
-			    + (cy_chip_offset[chip]<<index));
+	base_addr = cinfo->base_addr + (cy_chip_offset[chip]<<index);
 
 	while (1) {
 	    CY_LOCK(info, flags);
 		if ((tty->termios->c_cflag & CBAUD)){
-		    cy_writeb((u_long)base_addr+(CyCAR<<index), (u_char)channel);
-		    cy_writeb((u_long)base_addr+(CyMSVR1<<index), CyRTS);
-		    cy_writeb((u_long)base_addr+(CyMSVR2<<index), CyDTR);
+		    cy_writeb(base_addr+(CyCAR<<index), (u_char)channel);
+		    cy_writeb(base_addr+(CyMSVR1<<index), CyRTS);
+		    cy_writeb(base_addr+(CyMSVR2<<index), CyDTR);
 #ifdef CY_DEBUG_DTR
 		    printk("cyc:block_til_ready raising DTR\n");
 		    printk("     status: 0x%x, 0x%x\n",
@@ -2417,7 +2396,7 @@
 	    }
 
 	    CY_LOCK(info, flags);
-		cy_writeb((u_long)base_addr+(CyCAR<<index), (u_char)channel);
+		cy_writeb(base_addr+(CyCAR<<index), (u_char)channel);
 		if (!(info->flags & ASYNC_CLOSING)
 		&& (C_CLOCAL(tty)
 		    || (cy_readb(base_addr+(CyMSVR1<<index)) & CyDCD))) {
@@ -2437,23 +2416,21 @@
 	    schedule();
 	}
     } else {
-      struct FIRM_ID *firm_id;
-      struct ZFW_CTRL *zfw_ctrl;
-      struct BOARD_CTRL *board_ctrl;
-      struct CH_CTRL *ch_ctrl;
+      struct FIRM_ID __iomem *firm_id;
+      struct ZFW_CTRL __iomem *zfw_ctrl;
+      struct BOARD_CTRL __iomem *board_ctrl;
+      struct CH_CTRL __iomem *ch_ctrl;
       int retval;
 
-	base_addr = (char *)(cinfo->base_addr);
-	firm_id = (struct FIRM_ID *)
-			(base_addr + ID_ADDRESS);
+	base_addr = cinfo->base_addr;
+	firm_id = base_addr + ID_ADDRESS;
         if (!ISZLOADED(*cinfo)){
             current->state = TASK_RUNNING;
 	    remove_wait_queue(&info->open_wait, &wait);
 	    return -EINVAL;
 	}
 
-	zfw_ctrl = (struct ZFW_CTRL *)
-		    (base_addr + (cy_readl(&firm_id->zfwctrl_addr) & 0xfffff));
+	zfw_ctrl = base_addr + (cy_readl(&firm_id->zfwctrl_addr) & 0xfffff);
 	board_ctrl = &zfw_ctrl->board_ctrl;
 	ch_ctrl = zfw_ctrl->ch_ctrl;
 
@@ -2543,11 +2520,10 @@
     */
     if (IS_CYC_Z(cy_card[info->card])) {
 	struct cyclades_card *cinfo = &cy_card[info->card];
-	struct FIRM_ID *firm_id = (struct FIRM_ID *)
-        	(cinfo->base_addr + ID_ADDRESS);
+	struct FIRM_ID __iomem *firm_id = cinfo->base_addr + ID_ADDRESS;
 
         if (!ISZLOADED(*cinfo)) {
-	    if (((ZE_V1 ==cy_readl(&((struct RUNTIME_9060 *)
+	    if (((ZE_V1 ==cy_readl(&((struct RUNTIME_9060 __iomem *)
 		(cinfo->ctl_addr))->mail_box_0)) &&
 		Z_FPGA_CHECK (*cinfo)) &&
 		(ZFIRM_HLT == cy_readl (&firm_id->signature)))
@@ -2564,12 +2540,10 @@
 	       interrupts should be enabled as soon as the first open happens 
 	       to one of its ports. */
             if (!cinfo->intr_enabled) {
-		struct ZFW_CTRL *zfw_ctrl;
-		struct BOARD_CTRL *board_ctrl;
+		struct ZFW_CTRL __iomem *zfw_ctrl;
+		struct BOARD_CTRL __iomem *board_ctrl;
 
-		zfw_ctrl = (struct ZFW_CTRL *)
-		 (cinfo->base_addr +
-		  (cy_readl (&firm_id->zfwctrl_addr) & 0xfffff));
+		zfw_ctrl = cinfo->base_addr + (cy_readl (&firm_id->zfwctrl_addr) & 0xfffff);
 
 		board_ctrl = &zfw_ctrl->board_ctrl;
 
@@ -2661,7 +2635,7 @@
 cy_wait_until_sent(struct tty_struct *tty, int timeout)
 {
   struct cyclades_port * info = (struct cyclades_port *)tty->driver_data;
-  unsigned char *base_addr;
+  void __iomem *base_addr;
   int card,chip,channel,index;
   unsigned long orig_jiffies;
   int char_time;
@@ -2711,8 +2685,7 @@
 	chip = channel>>2;
 	channel &= 0x03;
 	index = cy_card[card].bus_index;
-	base_addr = (unsigned char *)
-		(cy_card[card].base_addr + (cy_chip_offset[chip]<<index));
+	base_addr = cy_card[card].base_addr + (cy_chip_offset[chip]<<index);
 	while (cy_readb(base_addr+(CySRER<<index)) & CyTxRdy) {
 #ifdef CY_DEBUG_WAIT_UNTIL_SENT
 	    printk("Not clean (jiff=%lu)...", jiffies);
@@ -2805,13 +2778,11 @@
     if (!IS_CYC_Z(cy_card[info->card])) {
 	int channel = info->line - cy_card[info->card].first_line;
 	int index = cy_card[info->card].bus_index;
-	unsigned char *base_addr = (unsigned char *)
-			(cy_card[info->card].base_addr +
-			 (cy_chip_offset[channel>>2] <<index));
+	void __iomem *base_addr = cy_card[info->card].base_addr + (cy_chip_offset[channel>>2] << index);
 	/* Stop accepting input */
 	channel &= 0x03;
-	cy_writeb((ulong)base_addr+(CyCAR<<index), (u_char)channel);
-	cy_writeb((u_long)base_addr+(CySRER<<index),
+	cy_writeb(base_addr+(CyCAR<<index), (u_char)channel);
+	cy_writeb(base_addr+(CySRER<<index),
 			cy_readb(base_addr+(CySRER<<index)) & ~CyRxData);
 	if (info->flags & ASYNC_INITIALIZED) {
 	    /* Waiting for on-board buffers to be empty before closing 
@@ -2823,12 +2794,10 @@
     } else {
 #ifdef Z_WAKE
 	/* Waiting for on-board buffers to be empty before closing the port */
-	unsigned char *base_addr = (unsigned char *) 
-					cy_card[info->card].base_addr;
-	struct FIRM_ID *firm_id = (struct FIRM_ID *) (base_addr + ID_ADDRESS);
-	struct ZFW_CTRL *zfw_ctrl = (struct ZFW_CTRL *)
-		(base_addr + (cy_readl(&firm_id->zfwctrl_addr) & 0xfffff));
-	struct CH_CTRL *ch_ctrl = zfw_ctrl->ch_ctrl;
+	void __iomem *base_addr = cy_card[info->card].base_addr;
+	struct FIRM_ID __iomem *firm_id = base_addr + ID_ADDRESS;
+	struct ZFW_CTRL __iomem *zfw_ctrl = base_addr + (cy_readl(&firm_id->zfwctrl_addr) & 0xfffff);
+	struct CH_CTRL __iomem *ch_ctrl = zfw_ctrl->ch_ctrl;
 	int channel = info->line - cy_card[info->card].first_line;
 	int retval;
 
@@ -2850,8 +2819,7 @@
     shutdown(info);
     if (tty->driver->flush_buffer)
         tty->driver->flush_buffer(tty);
-    if (tty->ldisc.flush_buffer)
-        tty->ldisc.flush_buffer(tty);
+    tty_ldisc_flush(tty);        
     CY_LOCK(info, flags);
 
     tty->closing = 0;
@@ -3088,10 +3056,8 @@
 	int char_count;
 	volatile uclong tx_put, tx_get, tx_bufsize;
 
-	firm_id = (struct FIRM_ID *)(cy_card[card].base_addr + ID_ADDRESS);
-	zfw_ctrl = (struct ZFW_CTRL *)
-		    (cy_card[card].base_addr + 
-		     (cy_readl(&firm_id->zfwctrl_addr) & 0xfffff));
+	firm_id = cy_card[card].base_addr + ID_ADDRESS;
+	zfw_ctrl = cy_card[card].base_addr + (cy_readl(&firm_id->zfwctrl_addr) & 0xfffff);
 	ch_ctrl = &(zfw_ctrl->ch_ctrl[channel]);
 	buf_ctrl = &(zfw_ctrl->buf_ctrl[channel]);
 
@@ -3151,7 +3117,7 @@
 set_line_char(struct cyclades_port * info)
 {
   unsigned long flags;
-  unsigned char *base_addr;
+  void __iomem *base_addr;
   int card,chip,channel,index;
   unsigned cflag, iflag;
   unsigned short chip_number;
@@ -3303,76 +3269,74 @@
 
 	chip = channel>>2;
 	channel &= 0x03;
-	base_addr = (unsigned char*)
-		       (cy_card[card].base_addr
-		       + (cy_chip_offset[chip]<<index));
+	base_addr = cy_card[card].base_addr + (cy_chip_offset[chip]<<index);
 
 	CY_LOCK(info, flags);
-	    cy_writeb((u_long)base_addr+(CyCAR<<index), (u_char)channel);
+	    cy_writeb(base_addr+(CyCAR<<index), (u_char)channel);
 
 	   /* tx and rx baud rate */
 
-	    cy_writeb((u_long)base_addr+(CyTCOR<<index), info->tco);
-	    cy_writeb((u_long)base_addr+(CyTBPR<<index), info->tbpr);
-	    cy_writeb((u_long)base_addr+(CyRCOR<<index), info->rco);
-	    cy_writeb((u_long)base_addr+(CyRBPR<<index), info->rbpr);
+	    cy_writeb(base_addr+(CyTCOR<<index), info->tco);
+	    cy_writeb(base_addr+(CyTBPR<<index), info->tbpr);
+	    cy_writeb(base_addr+(CyRCOR<<index), info->rco);
+	    cy_writeb(base_addr+(CyRBPR<<index), info->rbpr);
 
 	    /* set line characteristics  according configuration */
 
-	    cy_writeb((u_long)base_addr+(CySCHR1<<index), 
+	    cy_writeb(base_addr+(CySCHR1<<index), 
 		      START_CHAR(info->tty));
-	    cy_writeb((u_long)base_addr+(CySCHR2<<index), 
+	    cy_writeb(base_addr+(CySCHR2<<index), 
 		      STOP_CHAR(info->tty));
-	    cy_writeb((u_long)base_addr+(CyCOR1<<index), info->cor1);
-	    cy_writeb((u_long)base_addr+(CyCOR2<<index), info->cor2);
-	    cy_writeb((u_long)base_addr+(CyCOR3<<index), info->cor3);
-	    cy_writeb((u_long)base_addr+(CyCOR4<<index), info->cor4);
-	    cy_writeb((u_long)base_addr+(CyCOR5<<index), info->cor5);
+	    cy_writeb(base_addr+(CyCOR1<<index), info->cor1);
+	    cy_writeb(base_addr+(CyCOR2<<index), info->cor2);
+	    cy_writeb(base_addr+(CyCOR3<<index), info->cor3);
+	    cy_writeb(base_addr+(CyCOR4<<index), info->cor4);
+	    cy_writeb(base_addr+(CyCOR5<<index), info->cor5);
 
 	    cyy_issue_cmd(base_addr,
 		     CyCOR_CHANGE|CyCOR1ch|CyCOR2ch|CyCOR3ch,index);
 
-	    cy_writeb((u_long)base_addr+(CyCAR<<index), 
+	    cy_writeb(base_addr+(CyCAR<<index), 
 		      (u_char)channel); /* !!! Is this needed? */
-	    cy_writeb((u_long)base_addr+(CyRTPR<<index), (info->default_timeout
+	    cy_writeb(base_addr+(CyRTPR<<index), (info->default_timeout
 					         ? info->default_timeout
 					         : 0x02)); /* 10ms rx timeout */
 
 	    if (C_CLOCAL(info->tty)) {
 		/* without modem intr */
-		cy_writeb((u_long)base_addr+(CySRER<<index),
+		cy_writeb(base_addr+(CySRER<<index),
                    cy_readb(base_addr+(CySRER<<index)) | CyMdmCh); 
 					/* act on 1->0 modem transitions */
                 if ((cflag & CRTSCTS) && info->rflow) {
-                        cy_writeb((u_long)base_addr+(CyMCOR1<<index), 
+                        cy_writeb(base_addr+(CyMCOR1<<index), 
                                   (CyCTS|rflow_thr[i]));
                 } else {
-                        cy_writeb((u_long)base_addr+(CyMCOR1<<index), CyCTS);
+                        cy_writeb(base_addr+(CyMCOR1<<index), CyCTS);
                 }
 					/* act on 0->1 modem transitions */
-		cy_writeb((u_long)base_addr+(CyMCOR2<<index), CyCTS);
+		cy_writeb(base_addr+(CyMCOR2<<index), CyCTS);
 	    } else {
 		/* without modem intr */
-		cy_writeb((u_long)base_addr+(CySRER<<index),
+		cy_writeb(base_addr+(CySRER<<index),
                    cy_readb(base_addr+(CySRER<<index)) | CyMdmCh); 
 					/* act on 1->0 modem transitions */
                 if ((cflag & CRTSCTS) && info->rflow) {
-			cy_writeb((u_long)base_addr+(CyMCOR1<<index), 
+			cy_writeb(base_addr+(CyMCOR1<<index), 
         	                  (CyDSR|CyCTS|CyRI|CyDCD|rflow_thr[i]));
                 } else {
-			cy_writeb((u_long)base_addr+(CyMCOR1<<index), 
+			cy_writeb(base_addr+(CyMCOR1<<index), 
                                   CyDSR|CyCTS|CyRI|CyDCD);
                 }
 					/* act on 0->1 modem transitions */
-		cy_writeb((u_long)base_addr+(CyMCOR2<<index), 
+		cy_writeb(base_addr+(CyMCOR2<<index), 
 			  CyDSR|CyCTS|CyRI|CyDCD);
 	    }
 
 	    if(i == 0){ /* baud rate is zero, turn off line */
 	        if (info->rtsdtr_inv) {
-			cy_writeb((u_long)base_addr+(CyMSVR1<<index), ~CyRTS);
+			cy_writeb(base_addr+(CyMSVR1<<index), ~CyRTS);
 		} else {
-                        cy_writeb((u_long)base_addr+(CyMSVR2<<index), ~CyDTR);
+                        cy_writeb(base_addr+(CyMSVR2<<index), ~CyDTR);
 		}
 #ifdef CY_DEBUG_DTR
 		printk("cyc:set_line_char dropping DTR\n");
@@ -3382,9 +3346,9 @@
 #endif
 	    }else{
                 if (info->rtsdtr_inv) {
-			cy_writeb((u_long)base_addr+(CyMSVR1<<index), CyRTS);
+			cy_writeb(base_addr+(CyMSVR1<<index), CyRTS);
                 } else {
-			cy_writeb((u_long)base_addr+(CyMSVR2<<index), CyDTR);
+			cy_writeb(base_addr+(CyMSVR2<<index), CyDTR);
                 }
 #ifdef CY_DEBUG_DTR
 		printk("cyc:set_line_char raising DTR\n");
@@ -3400,23 +3364,20 @@
 	CY_UNLOCK(info, flags);
 
     } else {
-      struct FIRM_ID *firm_id;
-      struct ZFW_CTRL *zfw_ctrl;
-      struct BOARD_CTRL *board_ctrl;
-      struct CH_CTRL *ch_ctrl;
-      struct BUF_CTRL *buf_ctrl;
+      struct FIRM_ID __iomem *firm_id;
+      struct ZFW_CTRL __iomem *zfw_ctrl;
+      struct BOARD_CTRL __iomem *board_ctrl;
+      struct CH_CTRL __iomem *ch_ctrl;
+      struct BUF_CTRL __iomem *buf_ctrl;
       uclong sw_flow;
       int retval;
 
-        firm_id = (struct FIRM_ID *)
-			(cy_card[card].base_addr + ID_ADDRESS);
+        firm_id = cy_card[card].base_addr + ID_ADDRESS;
         if (!ISZLOADED(cy_card[card])) {
 	    return;
 	}
 
-	zfw_ctrl = (struct ZFW_CTRL *)
-		    (cy_card[card].base_addr + 
-		     (cy_readl(&firm_id->zfwctrl_addr) & 0xfffff));
+	zfw_ctrl = cy_card[card].base_addr + (cy_readl(&firm_id->zfwctrl_addr) & 0xfffff);
 	board_ctrl = &zfw_ctrl->board_ctrl;
 	ch_ctrl = &(zfw_ctrl->ch_ctrl[channel]);
 	buf_ctrl = &zfw_ctrl->buf_ctrl[channel];
@@ -3617,7 +3578,7 @@
     unsigned char status;
     unsigned int result;
     unsigned long flags;
-    unsigned char *base_addr;
+    void __iomem *base_addr;
 
     card = info->card;
     channel = (info->line) - (cy_card[card].first_line);
@@ -3625,8 +3586,7 @@
 	chip = channel>>2;
 	channel &= 0x03;
 	index = cy_card[card].bus_index;
-	base_addr = (unsigned char *)
-		     (cy_card[card].base_addr + (cy_chip_offset[chip]<<index));
+	base_addr = cy_card[card].base_addr + (cy_chip_offset[chip]<<index);
 
 	CY_LOCK(info, flags);
 	status = cy_readb(base_addr+(CySRER<<index)) & (CyTxRdy|CyTxMpty);
@@ -3644,15 +3604,15 @@
 {
   struct cyclades_port * info = (struct cyclades_port *)tty->driver_data;
   int card,chip,channel,index;
-  unsigned char *base_addr;
+  void __iomem *base_addr;
   unsigned long flags;
   unsigned char status;
   unsigned long lstatus;
   unsigned int result;
-  struct FIRM_ID *firm_id;
-  struct ZFW_CTRL *zfw_ctrl;
-  struct BOARD_CTRL *board_ctrl;
-  struct CH_CTRL *ch_ctrl;
+  struct FIRM_ID __iomem *firm_id;
+  struct ZFW_CTRL __iomem *zfw_ctrl;
+  struct BOARD_CTRL __iomem *board_ctrl;
+  struct CH_CTRL __iomem *ch_ctrl;
 
     if (serial_paranoia_check(info, tty->name, __FUNCTION__))
 	return -ENODEV;
@@ -3663,12 +3623,10 @@
 	chip = channel>>2;
 	channel &= 0x03;
 	index = cy_card[card].bus_index;
-	base_addr = (unsigned char*)
-		       (cy_card[card].base_addr
-		       + (cy_chip_offset[chip]<<index));
+	base_addr = cy_card[card].base_addr + (cy_chip_offset[chip]<<index);
 
 	CY_LOCK(info, flags);
-	    cy_writeb((u_long)base_addr+(CyCAR<<index), (u_char)channel);
+	    cy_writeb(base_addr+(CyCAR<<index), (u_char)channel);
 	    status = cy_readb(base_addr+(CyMSVR1<<index));
 	    status |= cy_readb(base_addr+(CyMSVR2<<index));
 	CY_UNLOCK(info, flags);
@@ -3685,18 +3643,15 @@
 		 | ((status  & CyDSR) ? TIOCM_DSR : 0)
 		 | ((status  & CyCTS) ? TIOCM_CTS : 0);
     } else {
-	base_addr = (unsigned char*) (cy_card[card].base_addr);
+	base_addr = cy_card[card].base_addr;
 
         if (cy_card[card].num_chips != -1){
 	    return -EINVAL;
 	}
 
-	firm_id = (struct FIRM_ID *)
-		    (cy_card[card].base_addr + ID_ADDRESS);
+	firm_id = cy_card[card].base_addr + ID_ADDRESS;
         if (ISZLOADED(cy_card[card])) {
-	    zfw_ctrl = (struct ZFW_CTRL *)
-			(cy_card[card].base_addr + 
-			 (cy_readl(&firm_id->zfwctrl_addr) & 0xfffff));
+	    zfw_ctrl = cy_card[card].base_addr + (cy_readl(&firm_id->zfwctrl_addr) & 0xfffff);
 	    board_ctrl = &zfw_ctrl->board_ctrl;
 	    ch_ctrl = zfw_ctrl->ch_ctrl;
 	    lstatus = cy_readl(&ch_ctrl[channel].rs_status);
@@ -3722,12 +3677,12 @@
 {
   struct cyclades_port * info = (struct cyclades_port *)tty->driver_data;
   int card,chip,channel,index;
-  unsigned char *base_addr;
+  void __iomem *base_addr;
   unsigned long flags;
-  struct FIRM_ID *firm_id;
-  struct ZFW_CTRL *zfw_ctrl;
-  struct BOARD_CTRL *board_ctrl;
-  struct CH_CTRL *ch_ctrl;
+  struct FIRM_ID __iomem *firm_id;
+  struct ZFW_CTRL __iomem *zfw_ctrl;
+  struct BOARD_CTRL __iomem *board_ctrl;
+  struct CH_CTRL __iomem *ch_ctrl;
   int retval;
 
     if (serial_paranoia_check(info, tty->name, __FUNCTION__))
@@ -3739,37 +3694,35 @@
 	chip = channel>>2;
 	channel &= 0x03;
 	index = cy_card[card].bus_index;
-	base_addr = (unsigned char*)
-		       (cy_card[card].base_addr
-		       + (cy_chip_offset[chip]<<index));
+	base_addr = cy_card[card].base_addr + (cy_chip_offset[chip]<<index);
 
 	if (set & TIOCM_RTS){
 		CY_LOCK(info, flags);
-	        cy_writeb((u_long)base_addr+(CyCAR<<index), (u_char)channel);
+	        cy_writeb(base_addr+(CyCAR<<index), (u_char)channel);
                 if (info->rtsdtr_inv) {
-			cy_writeb((u_long)base_addr+(CyMSVR2<<index), CyDTR);
+			cy_writeb(base_addr+(CyMSVR2<<index), CyDTR);
                 } else {
-			cy_writeb((u_long)base_addr+(CyMSVR1<<index), CyRTS);
+			cy_writeb(base_addr+(CyMSVR1<<index), CyRTS);
                 }
 		CY_UNLOCK(info, flags);
 	}
 	if (clear & TIOCM_RTS) {
 		CY_LOCK(info, flags);
-		cy_writeb((u_long)base_addr+(CyCAR<<index), (u_char)channel);
+		cy_writeb(base_addr+(CyCAR<<index), (u_char)channel);
                 if (info->rtsdtr_inv) {
-			cy_writeb((u_long)base_addr+(CyMSVR2<<index), ~CyDTR);
+			cy_writeb(base_addr+(CyMSVR2<<index), ~CyDTR);
                 } else {
-			cy_writeb((u_long)base_addr+(CyMSVR1<<index), ~CyRTS);
+			cy_writeb(base_addr+(CyMSVR1<<index), ~CyRTS);
                 }
 		CY_UNLOCK(info, flags);
 	}
 	if (set & TIOCM_DTR){
 		CY_LOCK(info, flags);
-		cy_writeb((u_long)base_addr+(CyCAR<<index), (u_char)channel);
+		cy_writeb(base_addr+(CyCAR<<index), (u_char)channel);
                 if (info->rtsdtr_inv) {
-			cy_writeb((u_long)base_addr+(CyMSVR1<<index), CyRTS);
+			cy_writeb(base_addr+(CyMSVR1<<index), CyRTS);
                 } else {
-			cy_writeb((u_long)base_addr+(CyMSVR2<<index), CyDTR);
+			cy_writeb(base_addr+(CyMSVR2<<index), CyDTR);
                 }
 #ifdef CY_DEBUG_DTR
 		printk("cyc:set_modem_info raising DTR\n");
@@ -3781,11 +3734,11 @@
 	}
 	if (clear & TIOCM_DTR) {
 		CY_LOCK(info, flags);
-		cy_writeb((u_long)base_addr+(CyCAR<<index), (u_char)channel);
+		cy_writeb(base_addr+(CyCAR<<index), (u_char)channel);
                 if (info->rtsdtr_inv) {
-			cy_writeb((u_long)base_addr+(CyMSVR1<<index), ~CyRTS);
+			cy_writeb(base_addr+(CyMSVR1<<index), ~CyRTS);
                 } else {
-			cy_writeb((u_long)base_addr+(CyMSVR2<<index), ~CyDTR);
+			cy_writeb(base_addr+(CyMSVR2<<index), ~CyDTR);
                 }
 
 #ifdef CY_DEBUG_DTR
@@ -3797,14 +3750,11 @@
 		CY_UNLOCK(info, flags);
 	}
     } else {
-	base_addr = (unsigned char*) (cy_card[card].base_addr);
+	base_addr = cy_card[card].base_addr;
 
-	firm_id = (struct FIRM_ID *)
-		    (cy_card[card].base_addr + ID_ADDRESS);
+	firm_id = cy_card[card].base_addr + ID_ADDRESS;
         if (ISZLOADED(cy_card[card])) {
-	    zfw_ctrl = (struct ZFW_CTRL *)
-			(cy_card[card].base_addr + 
-			 (cy_readl(&firm_id->zfwctrl_addr) & 0xfffff));
+	    zfw_ctrl = cy_card[card].base_addr + (cy_readl(&firm_id->zfwctrl_addr) & 0xfffff);
 	    board_ctrl = &zfw_ctrl->board_ctrl;
 	    ch_ctrl = zfw_ctrl->ch_ctrl;
 
@@ -3930,7 +3880,7 @@
 static int
 set_threshold(struct cyclades_port * info, unsigned long value)
 {
-  unsigned char *base_addr;
+  void __iomem *base_addr;
   int card,channel,chip,index;
   unsigned long flags;
    
@@ -3940,15 +3890,13 @@
 	chip = channel>>2;
 	channel &= 0x03;
 	index = cy_card[card].bus_index;
-	base_addr = (unsigned char*)
-		       (cy_card[card].base_addr
-		       + (cy_chip_offset[chip]<<index));
+	base_addr = cy_card[card].base_addr + (cy_chip_offset[chip]<<index);
 
 	info->cor3 &= ~CyREC_FIFO;
 	info->cor3 |= value & CyREC_FIFO;
 
 	CY_LOCK(info, flags);
-	    cy_writeb((u_long)base_addr+(CyCOR3<<index), info->cor3);
+	    cy_writeb(base_addr+(CyCOR3<<index), info->cor3);
 	    cyy_issue_cmd(base_addr,CyCOR_CHANGE|CyCOR3ch,index);
 	CY_UNLOCK(info, flags);
     } else {
@@ -3961,7 +3909,7 @@
 static int
 get_threshold(struct cyclades_port * info, unsigned long __user *value)
 {
-  unsigned char *base_addr;
+  void __iomem *base_addr;
   int card,channel,chip,index;
   unsigned long tmp;
    
@@ -3971,9 +3919,7 @@
 	chip = channel>>2;
 	channel &= 0x03;
 	index = cy_card[card].bus_index;
-	base_addr = (unsigned char*)
-		       (cy_card[card].base_addr
-		       + (cy_chip_offset[chip]<<index));
+	base_addr = cy_card[card].base_addr + (cy_chip_offset[chip]<<index);
 
 	tmp = cy_readb(base_addr+(CyCOR3<<index)) & CyREC_FIFO;
 	return put_user(tmp,value);
@@ -4002,7 +3948,7 @@
 static int
 set_timeout(struct cyclades_port * info, unsigned long value)
 {
-  unsigned char *base_addr;
+  void __iomem *base_addr;
   int card,channel,chip,index;
   unsigned long flags;
    
@@ -4012,12 +3958,10 @@
 	chip = channel>>2;
 	channel &= 0x03;
 	index = cy_card[card].bus_index;
-	base_addr = (unsigned char*)
-		       (cy_card[card].base_addr
-		       + (cy_chip_offset[chip]<<index));
+	base_addr = cy_card[card].base_addr + (cy_chip_offset[chip]<<index);
 
 	CY_LOCK(info, flags);
-	    cy_writeb((u_long)base_addr+(CyRTPR<<index), value & 0xff);
+	    cy_writeb(base_addr+(CyRTPR<<index), value & 0xff);
 	CY_UNLOCK(info, flags);
     } else {
 	// Nothing to do!
@@ -4029,7 +3973,7 @@
 static int
 get_timeout(struct cyclades_port * info, unsigned long __user *value)
 {
-  unsigned char *base_addr;
+  void __iomem *base_addr;
   int card,channel,chip,index;
   unsigned long tmp;
    
@@ -4039,9 +3983,7 @@
 	chip = channel>>2;
 	channel &= 0x03;
 	index = cy_card[card].bus_index;
-	base_addr = (unsigned char*)
-		       (cy_card[card].base_addr
-		       + (cy_chip_offset[chip]<<index));
+	base_addr = cy_card[card].base_addr + (cy_chip_offset[chip]<<index);
 
 	tmp = cy_readb(base_addr+(CyRTPR<<index));
 	return put_user(tmp,value);
@@ -4329,7 +4271,7 @@
 {
   struct cyclades_port *info = (struct cyclades_port *)tty->driver_data;
   unsigned long flags;
-  unsigned char *base_addr;
+  void __iomem *base_addr;
   int card,chip,channel,index;
 
 #ifdef CY_DEBUG_THROTTLE
@@ -4359,16 +4301,14 @@
             chip = channel>>2;
             channel &= 0x03;
             index = cy_card[card].bus_index;
-            base_addr = (unsigned char*)
-             (cy_card[card].base_addr
-               + (cy_chip_offset[chip]<<index));
+            base_addr = cy_card[card].base_addr + (cy_chip_offset[chip]<<index);
 
             CY_LOCK(info, flags);
-            cy_writeb((u_long)base_addr+(CyCAR<<index), (u_char)channel);
+            cy_writeb(base_addr+(CyCAR<<index), (u_char)channel);
             if (info->rtsdtr_inv) {
-                cy_writeb((u_long)base_addr+(CyMSVR2<<index), ~CyDTR);
+                cy_writeb(base_addr+(CyMSVR2<<index), ~CyDTR);
              } else {
-                cy_writeb((u_long)base_addr+(CyMSVR1<<index), ~CyRTS);
+                cy_writeb(base_addr+(CyMSVR1<<index), ~CyRTS);
 	     }
 	    CY_UNLOCK(info, flags);
 	} else {
@@ -4390,7 +4330,7 @@
 {
   struct cyclades_port *info = (struct cyclades_port *)tty->driver_data;
   unsigned long flags;
-  unsigned char *base_addr;
+  void __iomem *base_addr;
   int card,chip,channel,index;
 
 #ifdef CY_DEBUG_THROTTLE
@@ -4419,16 +4359,14 @@
 	    chip = channel>>2;
 	    channel &= 0x03;
 	    index = cy_card[card].bus_index;
-	    base_addr = (unsigned char*)
-         	       (cy_card[card].base_addr
-		       + (cy_chip_offset[chip]<<index));
+	    base_addr = cy_card[card].base_addr + (cy_chip_offset[chip]<<index);
 
 	    CY_LOCK(info, flags);
-	    cy_writeb((u_long)base_addr+(CyCAR<<index), (u_char)channel);
+	    cy_writeb(base_addr+(CyCAR<<index), (u_char)channel);
 	    if (info->rtsdtr_inv) {
-		    cy_writeb((u_long)base_addr+(CyMSVR2<<index), CyDTR);
+		    cy_writeb(base_addr+(CyMSVR2<<index), CyDTR);
 	    } else {
-		    cy_writeb((u_long)base_addr+(CyMSVR1<<index), CyRTS);
+		    cy_writeb(base_addr+(CyMSVR1<<index), CyRTS);
 	    }
 	    CY_UNLOCK(info, flags);
         } else {
@@ -4448,7 +4386,7 @@
 {
   struct cyclades_card *cinfo;
   struct cyclades_port *info = (struct cyclades_port *)tty->driver_data;
-  unsigned char *base_addr;
+  void __iomem *base_addr;
   int chip,channel,index;
   unsigned long flags;
 
@@ -4465,14 +4403,12 @@
         index = cinfo->bus_index;
         chip = channel>>2;
         channel &= 0x03;
-        base_addr = (unsigned char*)
-                   (cy_card[info->card].base_addr
-                           + (cy_chip_offset[chip]<<index));
+        base_addr = cy_card[info->card].base_addr + (cy_chip_offset[chip]<<index);
 
 	CY_LOCK(info, flags);
-            cy_writeb((u_long)base_addr+(CyCAR<<index),
+            cy_writeb(base_addr+(CyCAR<<index),
 	       (u_char)(channel & 0x0003)); /* index channel */
-            cy_writeb((u_long)base_addr+(CySRER<<index), 
+            cy_writeb(base_addr+(CySRER<<index), 
                cy_readb(base_addr+(CySRER<<index)) & ~CyTxRdy);
 	CY_UNLOCK(info, flags);
     } else {
@@ -4488,7 +4424,7 @@
 {
   struct cyclades_card *cinfo;
   struct cyclades_port *info = (struct cyclades_port *)tty->driver_data;
-  unsigned char *base_addr;
+  void __iomem *base_addr;
   int chip,channel,index;
   unsigned long flags;
 
@@ -4505,14 +4441,12 @@
     if (!IS_CYC_Z(*cinfo)) {
         chip = channel>>2;
         channel &= 0x03;
-        base_addr = (unsigned char*)
-                       (cy_card[info->card].base_addr
-		       + (cy_chip_offset[chip]<<index));
+        base_addr = cy_card[info->card].base_addr + (cy_chip_offset[chip]<<index);
 
 	CY_LOCK(info, flags);
-            cy_writeb((u_long)base_addr+(CyCAR<<index),
+            cy_writeb(base_addr+(CyCAR<<index),
 	       (u_char)(channel & 0x0003)); /* index channel */
-            cy_writeb((u_long)base_addr+(CySRER<<index), 
+            cy_writeb(base_addr+(CySRER<<index), 
                cy_readb(base_addr+(CySRER<<index)) | CyTxRdy);
 	CY_UNLOCK(info, flags);
     } else {
@@ -4554,10 +4488,8 @@
 	}
 	CY_UNLOCK(info, flags);
     }
+    tty_wakeup(tty);
     wake_up_interruptible(&tty->write_wait);
-    if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP))
-	&& tty->ldisc.write_wakeup)
-	    (tty->ldisc.write_wakeup)(tty);
 } /* cy_flush_buffer */
 
 
@@ -4600,20 +4532,19 @@
 /* initialize chips on Cyclom-Y card -- return number of valid
    chips (which is number of ports/4) */
 static unsigned short __init
-cyy_init_card(volatile ucchar *true_base_addr,int index)
+cyy_init_card(void __iomem *true_base_addr,int index)
 {
   unsigned int chip_number;
-  volatile ucchar* base_addr;
+  void __iomem *base_addr;
 
-    cy_writeb((u_long)true_base_addr+(Cy_HwReset<<index), 0); 
+    cy_writeb(true_base_addr+(Cy_HwReset<<index), 0); 
 						/* Cy_HwReset is 0x1400 */
-    cy_writeb((u_long)true_base_addr+(Cy_ClrIntr<<index), 0); 
+    cy_writeb(true_base_addr+(Cy_ClrIntr<<index), 0); 
 						/* Cy_ClrIntr is 0x1800 */
     udelay(500L);
 
     for(chip_number=0; chip_number<CyMAX_CHIPS_PER_CARD; chip_number++){
-        base_addr = true_base_addr
-	               + (cy_chip_offset[chip_number]<<index);
+        base_addr = true_base_addr + (cy_chip_offset[chip_number]<<index);
         mdelay(1);
         if(cy_readb(base_addr+(CyCCR<<index)) != 0x00){
             /*************
@@ -4623,7 +4554,7 @@
             return chip_number;
         }
 
-        cy_writeb((u_long)base_addr+(CyGFRCR<<index), 0);
+        cy_writeb(base_addr+(CyGFRCR<<index), 0);
         udelay(10L);
 
         /* The Cyclom-16Y does not decode address bit 9 and therefore
@@ -4639,7 +4570,7 @@
             return chip_number;
         }
 
-        cy_writeb((u_long)base_addr+(CyCCR<<index), CyCHIP_RESET);
+        cy_writeb(base_addr+(CyCCR<<index), CyCHIP_RESET);
         mdelay(1);
 
         if(cy_readb(base_addr+(CyGFRCR<<index)) == 0x00){
@@ -4658,15 +4589,15 @@
             */
             return chip_number;
         }
-        cy_writeb((u_long)base_addr+(CyGCR<<index), CyCH0_SERIAL);
+        cy_writeb(base_addr+(CyGCR<<index), CyCH0_SERIAL);
         if (cy_readb(base_addr+(CyGFRCR<<index)) >= CD1400_REV_J){
 	    /* It is a CD1400 rev. J or later */
 	    /* Impossible to reach 5ms with this chip. 
 	       Changed to 2ms instead (f = 500 Hz). */
-	    cy_writeb((u_long)base_addr+(CyPPR<<index), CyCLOCK_60_2MS);
+	    cy_writeb(base_addr+(CyPPR<<index), CyCLOCK_60_2MS);
 	} else {
 	    /* f = 200 Hz */
-	    cy_writeb((u_long)base_addr+(CyPPR<<index), CyCLOCK_25_5MS);
+	    cy_writeb(base_addr+(CyPPR<<index), CyCLOCK_25_5MS);
 	}
 
     /*
@@ -4689,7 +4620,7 @@
 {
 #ifdef CONFIG_ISA
   unsigned short	cy_isa_irq,nboard;
-  volatile ucchar	*cy_isa_address;
+  void __iomem		*cy_isa_address;
   unsigned short	i,j,cy_isa_nchan;
 #ifdef MODULE
   int isparam = 0;
@@ -4702,7 +4633,7 @@
 	for(i = 0 ; i < NR_CARDS; i++) {
 	    if (maddr[i] || i) {
 		isparam = 1;
-		cy_isa_addresses[i] = (ucchar *)maddr[i];
+		cy_isa_addresses[i] = maddr[i];
 	    }
 	    if (!maddr[i])
 		break;
@@ -4711,15 +4642,13 @@
 
         /* scan the address table probing for Cyclom-Y/ISA boards */
         for (i = 0 ; i < NR_ISA_ADDRS ; i++) {
-                cy_isa_address = cy_isa_addresses[i];
-                if (cy_isa_address  == 0x0000) {
+        	unsigned int isa_address = cy_isa_addresses[i];
+                if (isa_address  == 0x0000) {
                         return(nboard);
                 }
 
                 /* probe for CD1400... */
-#if !defined(__alpha__)
-		cy_isa_address = ioremap((ulong)cy_isa_address, CyISA_Ywin);
-#endif
+		cy_isa_address = ioremap(isa_address, CyISA_Ywin);
                 cy_isa_nchan = CyPORTS_PER_CHIP * 
                      cyy_init_card(cy_isa_address,0);
                 if (cy_isa_nchan == 0) {
@@ -4771,8 +4700,8 @@
                 }
 
                 /* set cy_card */
-                cy_card[j].base_addr = (u_long) cy_isa_address;
-                cy_card[j].ctl_addr = 0;
+                cy_card[j].base_addr = cy_isa_address;
+                cy_card[j].ctl_addr = NULL;
                 cy_card[j].irq = (int) cy_isa_irq;
                 cy_card[j].bus_index = 0;
                 cy_card[j].first_line = cy_next_channel;
@@ -4795,7 +4724,7 @@
 } /* cy_detect_isa */
 
 static void 
-plx_init(uclong addr, uclong initctl)
+plx_init(void __iomem *addr, uclong initctl)
 {
     /* Reset PLX */
     cy_writel(addr + initctl, cy_readl(addr + initctl) | 0x40000000);
@@ -4823,11 +4752,12 @@
   unsigned char		cyy_rev_id;
   unsigned char		cy_pci_irq = 0;
   uclong		cy_pci_phys0, cy_pci_phys2;
-  uclong		cy_pci_addr0, cy_pci_addr2;
+  void __iomem		*cy_pci_addr0, *cy_pci_addr2;
   unsigned short	i,j,cy_pci_nchan, plx_ver;
   unsigned short	device_id,dev_index = 0;
   uclong		mailbox;
-  uclong		Ze_addr0[NR_CARDS], Ze_addr2[NR_CARDS], ZeIndex = 0;
+  uclong		ZeIndex = 0;
+  void __iomem		*Ze_addr0[NR_CARDS], *Ze_addr2[NR_CARDS];
   uclong		Ze_phys0[NR_CARDS], Ze_phys2[NR_CARDS];
   unsigned char		Ze_irq[NR_CARDS];
   struct pci_dev	*Ze_pdev[NR_CARDS];
@@ -4896,15 +4826,15 @@
 	            continue;
                 }
 #endif
-		cy_pci_addr0 = (ulong)ioremap(cy_pci_phys0, CyPCI_Yctl);
-		cy_pci_addr2 = (ulong)ioremap(cy_pci_phys2, CyPCI_Ywin);
+		cy_pci_addr0 = ioremap(cy_pci_phys0, CyPCI_Yctl);
+		cy_pci_addr2 = ioremap(cy_pci_phys2, CyPCI_Ywin);
 
 #ifdef CY_PCI_DEBUG
             printk("Cyclom-Y/PCI: relocate winaddr=0x%lx ctladdr=0x%lx\n",
 		(u_long)cy_pci_addr2, (u_long)cy_pci_addr0);
 #endif
                 cy_pci_nchan = (unsigned short)(CyPORTS_PER_CHIP * 
-                       cyy_init_card((volatile ucchar *)cy_pci_addr2, 1));
+                       cyy_init_card(cy_pci_addr2, 1));
                 if(cy_pci_nchan == 0) {
                         printk("Cyclom-Y PCI host card with ");
                         printk("no Serial-Modules at 0x%lx.\n",
@@ -4945,8 +4875,8 @@
                 /* set cy_card */
                 cy_card[j].base_phys = (ulong)cy_pci_phys2;
                 cy_card[j].ctl_phys = (ulong)cy_pci_phys0;
-                cy_card[j].base_addr = (ulong)cy_pci_addr2;
-                cy_card[j].ctl_addr = (ulong)cy_pci_addr0;
+                cy_card[j].base_addr = cy_pci_addr2;
+                cy_card[j].ctl_addr = cy_pci_addr0;
                 cy_card[j].irq = (int) cy_pci_irq;
                 cy_card[j].bus_index = 1;
                 cy_card[j].first_line = cy_next_channel;
@@ -5006,7 +4936,7 @@
             printk("Cyclades-Z/PCI: found winaddr=0x%lx ctladdr=0x%lx\n",
                 (ulong)cy_pci_phys2, (ulong)cy_pci_phys0);
 #endif
-		cy_pci_addr0 = (ulong)ioremap(cy_pci_phys0, CyPCI_Zctl);
+		cy_pci_addr0 = ioremap(cy_pci_phys0, CyPCI_Zctl);
 
 		/* Disable interrupts on the PLX before resetting it */
 		cy_writew(cy_pci_addr0+0x68,
@@ -5019,7 +4949,7 @@
 		   This will remain here until we find a permanent fix. */
 		pci_write_config_byte(pdev, PCI_INTERRUPT_LINE, cy_pci_irq);
 
-		mailbox = (uclong)cy_readl(&((struct RUNTIME_9060 *) 
+		mailbox = (uclong)cy_readl(&((struct RUNTIME_9060 __iomem *) 
 			   cy_pci_addr0)->mail_box_0);
 
 		if (pci_resource_flags(pdev, 2) & IORESOURCE_IO) {
@@ -5037,7 +4967,7 @@
 		}
 	
 		if (mailbox == ZE_V1) {
-		    cy_pci_addr2 = (ulong)ioremap(cy_pci_phys2, CyPCI_Ze_win);
+		    cy_pci_addr2 = ioremap(cy_pci_phys2, CyPCI_Ze_win);
 		    if (ZeIndex == NR_CARDS) {
 			printk("Cyclades-Ze/PCI found at 0x%lx ",
 				(ulong)cy_pci_phys2);
@@ -5055,7 +4985,7 @@
 		    i--;
 		    continue;
 		} else {
-		    cy_pci_addr2 = (ulong)ioremap(cy_pci_phys2, CyPCI_Zwin);
+		    cy_pci_addr2 = ioremap(cy_pci_phys2, CyPCI_Zwin);
 		}
 
 #ifdef CY_PCI_DEBUG
@@ -5082,7 +5012,7 @@
 	     */
 		PAUSE
 		if ((mailbox == ZO_V1) || (mailbox == ZO_V2))
-		    cy_writel((ulong)(cy_pci_addr2+ID_ADDRESS), 0L);
+		    cy_writel(cy_pci_addr2 + ID_ADDRESS, 0L);
 
                 /* This must be a Cyclades-8Zo/PCI.  The extendable
                    version will have a different device_id and will
@@ -5172,7 +5102,7 @@
 		Ze_pdev[j] = Ze_pdev[j+1];
 	    }
 	    ZeIndex--;
-		mailbox = (uclong)cy_readl(&((struct RUNTIME_9060 *) 
+		mailbox = (uclong)cy_readl(&((struct RUNTIME_9060 __iomem *) 
 					   cy_pci_addr0)->mail_box_0);
 #ifdef CY_PCI_DEBUG
             printk("Cyclades-Z/PCI: relocate winaddr=0x%lx ctladdr=0x%lx\n",
@@ -5413,7 +5343,7 @@
 
     for (i = 0; i < NR_CARDS; i++) {
             /* base_addr=0 indicates board not found */
-            cy_card[i].base_addr = 0;
+            cy_card[i].base_addr = NULL;
     }
 
     /* the code below is responsible to find the boards. Each different
@@ -5435,7 +5365,7 @@
     for (i = 0 ; i < NR_CARDS ; i++) {
         if (cy_card[i].base_addr == 0) {
                 cy_card[i].first_line = -1;
-                cy_card[i].ctl_addr = 0;
+                cy_card[i].ctl_addr = NULL;
                 cy_card[i].irq = 0;
                 cy_card[i].bus_index = 0;
                 cy_card[i].first_line = 0;
@@ -5453,7 +5383,7 @@
             cinfo = &cy_card[board];
             if (cinfo->num_chips == -1) { /* Cyclades-Z */
 		number_z_boards++;
-		mailbox = cy_readl(&((struct RUNTIME_9060 *)
+		mailbox = cy_readl(&((struct RUNTIME_9060 __iomem *)
 			     cy_card[board].ctl_addr)->mail_box_0);
 		nports = (mailbox == ZE_V1) ? ZE_V1_NPORTS : 8;
 		cinfo->intr_enabled = 0;
@@ -5623,10 +5553,10 @@
     put_tty_driver(cy_serial_driver);
 
     for (i = 0; i < NR_CARDS; i++) {
-        if (cy_card[i].base_addr != 0) {
-	    iounmap((void *)cy_card[i].base_addr);
-	    if (cy_card[i].ctl_addr != 0)
-		iounmap((void *)cy_card[i].ctl_addr);
+        if (cy_card[i].base_addr) {
+	    iounmap(cy_card[i].base_addr);
+	    if (cy_card[i].ctl_addr)
+		iounmap(cy_card[i].ctl_addr);
 	    if (cy_card[i].irq
 #ifndef CONFIG_CYZ_INTR
 		&& cy_card[i].num_chips != -1 /* not a Z card */
diff -Nru a/drivers/char/drm/Kconfig b/drivers/char/drm/Kconfig
--- a/drivers/char/drm/Kconfig	2004-10-18 14:56:50 -07:00
+++ b/drivers/char/drm/Kconfig	2004-10-18 14:56:50 -07:00
@@ -24,14 +24,14 @@
 
 config DRM_GAMMA
 	tristate "3dlabs GMX 2000"
-	depends on DRM
+	depends on DRM && BROKEN
 	help
 	  This is the old gamma driver, please tell me if it might actually
 	  work.
 
 config DRM_R128
 	tristate "ATI Rage 128"
-	depends on DRM
+	depends on DRM && PCI
 	help
 	  Choose this option if you have an ATI Rage 128 graphics card.  If M
 	  is selected, the module will be called r128.  AGP support for
@@ -39,7 +39,7 @@
 
 config DRM_RADEON
 	tristate "ATI Radeon"
-	depends on DRM
+	depends on DRM && PCI
 	help
 	  Choose this option if you have an ATI Radeon graphics card.  There
 	  are both PCI and AGP versions.  You don't need to choose this to
@@ -55,14 +55,29 @@
 	  selected, the module will be called i810.  AGP support is required
 	  for this driver to work.
 
-config DRM_I830
-	tristate "Intel 830M, 845G, 852GM, 855GM, 865G"
+choice
+	prompt "Intel 830M, 845G, 852GM, 855GM, 865G"
 	depends on DRM && AGP && AGP_INTEL
+	optional
+
+config DRM_I830
+	tristate "i830 driver"
 	help
 	  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 "i915 driver"
+	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.
+	
+endchoice
 
 config DRM_MGA
 	tristate "Matrox g200/g400"
diff -Nru a/drivers/char/drm/Makefile b/drivers/char/drm/Makefile
--- a/drivers/char/drm/Makefile	2004-10-18 14:57:04 -07:00
+++ b/drivers/char/drm/Makefile	2004-10-18 14:57:04 -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/drmP.h b/drivers/char/drm/drmP.h
--- a/drivers/char/drm/drmP.h	2004-10-18 14:56:49 -07:00
+++ b/drivers/char/drm/drmP.h	2004-10-18 14:56:49 -07:00
@@ -73,42 +73,26 @@
 #include <asm/pgalloc.h>
 #include "drm.h"
 
-#include "drm_os_linux.h"
+#define __OS_HAS_AGP (defined(CONFIG_AGP) || (defined(CONFIG_AGP_MODULE) && defined(MODULE)))
+#define __OS_HAS_MTRR (defined(CONFIG_MTRR))
 
+#include "drm_os_linux.h"
 
 /***********************************************************************/
 /** \name DRM template customization defaults */
 /*@{*/
 
-#ifndef __HAVE_AGP
-#define __HAVE_AGP		0
-#endif
-#ifndef __HAVE_MTRR
-#define __HAVE_MTRR		0
-#endif
-#ifndef __HAVE_CTX_BITMAP
-#define __HAVE_CTX_BITMAP	0
-#endif
-#ifndef __HAVE_DMA
-#define __HAVE_DMA		0
-#endif
-#ifndef __HAVE_IRQ
-#define __HAVE_IRQ		0
-#endif
-#ifndef __HAVE_DMA_WAITLIST
-#define __HAVE_DMA_WAITLIST	0
-#endif
-#ifndef __HAVE_DMA_FREELIST
-#define __HAVE_DMA_FREELIST	0
-#endif
-
-#define __REALLY_HAVE_AGP	(__HAVE_AGP && (defined(CONFIG_AGP) || \
-						defined(CONFIG_AGP_MODULE)))
-#define __REALLY_HAVE_MTRR	(__HAVE_MTRR && defined(CONFIG_MTRR))
-#define __REALLY_HAVE_SG	(__HAVE_SG)
-
-/*@}*/
-
+/* driver capabilities and requirements mask */
+#define DRIVER_USE_AGP     0x1
+#define DRIVER_REQUIRE_AGP 0x2
+#define DRIVER_USE_MTRR    0x4
+#define DRIVER_PCI_DMA     0x8
+#define DRIVER_SG          0x10
+#define DRIVER_HAVE_DMA    0x20
+#define DRIVER_HAVE_IRQ    0x40
+#define DRIVER_IRQ_SHARED  0x80
+#define DRIVER_IRQ_VBL     0x100
+#define DRIVER_DMA_QUEUE   0x200
 
 /***********************************************************************/
 /** \name Begin the DRM... */
@@ -266,54 +250,6 @@
 
 
 /***********************************************************************/
-/** \name Mapping helper macros */
-/*@{*/
-
-#define DRM_IOREMAP(map, dev)							\
-	(map)->handle = DRM(ioremap)( (map)->offset, (map)->size, (dev) )
-
-#define DRM_IOREMAP_NOCACHE(map, dev)						\
-	(map)->handle = DRM(ioremap_nocache)((map)->offset, (map)->size, (dev))
-
-#define DRM_IOREMAPFREE(map, dev)						\
-	do {									\
-		if ( (map)->handle && (map)->size )				\
-			DRM(ioremapfree)( (map)->handle, (map)->size, (dev) );	\
-	} while (0)
-
-/**
- * Find mapping.
- *
- * \param _map matching mapping if found, untouched otherwise.
- * \param _o offset.
- *
- * Expects the existence of a local variable named \p dev pointing to the
- * drm_device structure.
- */
-#define DRM_FIND_MAP(_map, _o)								\
-do {											\
-	struct list_head *_list;							\
-	list_for_each( _list, &dev->maplist->head ) {					\
-		drm_map_list_t *_entry = list_entry( _list, drm_map_list_t, head );	\
-		if ( _entry->map &&							\
-		     _entry->map->offset == (_o) ) {					\
-			(_map) = _entry->map;						\
-			break;								\
- 		}									\
-	}										\
-} while(0)
-
-/**
- * Drop mapping.
- *
- * \sa #DRM_FIND_MAP.
- */
-#define DRM_DROP_MAP(_map)
-
-/*@}*/
-
-
-/***********************************************************************/
 /** \name Internal types and structures */
 /*@{*/
 
@@ -473,9 +409,7 @@
 	struct drm_device *dev;
 	int 		  remove_auth_on_close;
 	unsigned long     lock_count;
-#ifdef DRIVER_FILE_FIELDS
-	DRIVER_FILE_FIELDS;
-#endif
+	void              *driver_priv;
 } drm_file_t;
 
 /** Wait queue */
@@ -524,16 +458,8 @@
 		_DRM_DMA_USE_SG  = 0x02
 	} flags;
 
-	/** \name DMA support */
-	/*@{*/
-	drm_buf_t	  *this_buffer;	/**< Buffer being sent */
-	drm_buf_t	  *next_buffer; /**< Selected buffer to send */
-	drm_queue_t	  *next_queue;	/**< Queue from which buffer selected*/
-	wait_queue_head_t waiting;	/**< Processes waiting on free bufs */
-	/*@}*/
 } drm_device_dma_t;
 
-#if __REALLY_HAVE_AGP
 /** 
  * AGP memory entry.  Stored as a doubly linked list.
  */
@@ -562,7 +488,6 @@
 	int		   cant_use_aperture;
 	unsigned long	   page_mask;
 } drm_agp_head_t;
-#endif
 
 /**
  * Scatter-gather memory.
@@ -599,7 +524,6 @@
 	drm_file_t		*tag;   /**< associated fd private data */
 } drm_ctx_list_t;
 
-#ifdef __HAVE_VBL_IRQ
 
 typedef struct drm_vbl_sig {
 	struct list_head	head;
@@ -608,8 +532,40 @@
 	struct task_struct	*task;
 } drm_vbl_sig_t;
 
-#endif
 
+/** 
+ * DRM device functions structure
+ */
+struct drm_device;
+
+struct drm_driver_fn {
+	int (*preinit)(struct drm_device *);
+	int (*postinit)(struct drm_device *);
+	void (*prerelease)(struct drm_device *, struct file *filp);
+	void (*pretakedown)(struct drm_device *);
+	int (*postcleanup)(struct drm_device *);
+	int (*presetup)(struct drm_device *);
+	int (*postsetup)(struct drm_device *);
+	int (*open_helper)(struct drm_device *, drm_file_t *);
+	void (*free_filp_priv)(struct drm_device *, drm_file_t *);
+	void (*release)(struct drm_device *, struct file *filp);
+	void (*dma_ready)(struct drm_device *);
+	int (*dma_quiescent)(struct drm_device *);
+	int (*context_ctor)(struct drm_device *dev, int context);
+ 	int (*context_dtor)(struct drm_device *dev, int context);
+ 	int (*kernel_context_switch)(struct drm_device *dev, int old, int new);
+	void (*kernel_context_switch_unlock)(struct drm_device *dev, drm_lock_t *lock);
+	int (*vblank_wait)(struct drm_device *dev, unsigned int *sequence);
+	/* these have to be filled in */
+	irqreturn_t (*irq_handler)( DRM_IRQ_ARGS );
+ 	void (*irq_preinstall)(struct drm_device *dev);
+ 	void (*irq_postinstall)(struct drm_device *dev);
+ 	void (*irq_uninstall)(struct drm_device *dev);
+	void (*reclaim_buffers)(struct file *filp);
+	unsigned long (*get_map_ofs)(drm_map_t *map);
+	unsigned long (*get_reg_ofs)(struct drm_device *dev);
+	void (*set_version)(struct drm_device *dev, drm_set_version_t *sv);
+};
 /**
  * DRM device structure.
  */
@@ -698,13 +654,13 @@
 	struct work_struct	work;
 	/** \name VBLANK IRQ support */
 	/*@{*/
-#ifdef __HAVE_VBL_IRQ
+
    	wait_queue_head_t vbl_queue;	/**< VBLANK wait queue */
    	atomic_t          vbl_received;
 	spinlock_t        vbl_lock;
 	drm_vbl_sig_t     vbl_sigs;	/**< signal list to send on VBLANK */
 	unsigned int      vbl_pending;
-#endif
+
 	/*@}*/
 	cycles_t	  ctx_start;
 	cycles_t	  lck_start;
@@ -717,9 +673,7 @@
 	wait_queue_head_t buf_readers;	/**< Processes waiting to read */
 	wait_queue_head_t buf_writers;	/**< Processes waiting to ctx switch */
 
-#if __REALLY_HAVE_AGP
 	drm_agp_head_t    *agp;	/**< AGP data */
-#endif
 
 	struct pci_dev    *pdev;	/**< PCI device structure */
 	int               pci_domain;	/**< PCI bus domain number */
@@ -738,8 +692,37 @@
 	void		  *dev_private; /**< device private data */
 	drm_sigdata_t     sigdata; /**< For block_all_signals */
 	sigset_t          sigmask;
+
+	struct            drm_driver_fn fn_tbl;
+	drm_local_map_t   *agp_buffer_map;
+	int               dev_priv_size;
+	u32               driver_features;
 } drm_device_t;
 
+static __inline__ int drm_core_check_feature(struct drm_device *dev, int feature)
+{
+	return ((dev->driver_features & feature) ? 1 : 0);
+}
+
+#if __OS_HAS_AGP
+static inline int drm_core_has_AGP(struct drm_device *dev)
+{
+  return drm_core_check_feature(dev, DRIVER_USE_AGP);
+}
+#else
+#define drm_core_has_AGP(dev) (0)
+#endif
+
+#if __OS_HAS_MTRR
+static inline int drm_core_has_MTRR(struct drm_device *dev)
+{
+  return drm_core_check_feature(dev, DRIVER_USE_MTRR);
+}
+#else
+#define drm_core_has_MTRR(dev) (0)
+#endif
+
+extern void DRM(driver_register_fns)(struct drm_device *dev);
 
 /******************************************************************/
 /** \name Internal function definitions */
@@ -795,12 +778,10 @@
 					   drm_device_t *dev);
 extern void	     DRM(ioremapfree)(void *pt, unsigned long size, drm_device_t *dev);
 
-#if __REALLY_HAVE_AGP
 extern DRM_AGP_MEM   *DRM(alloc_agp)(int pages, u32 type);
 extern int           DRM(free_agp)(DRM_AGP_MEM *handle, int pages);
 extern int           DRM(bind_agp)(DRM_AGP_MEM *handle, unsigned int start);
 extern int           DRM(unbind_agp)(DRM_AGP_MEM *handle);
-#endif
 
 				/* Misc. IOCTL support (drm_ioctl.h) */
 extern int	     DRM(irq_by_busid)(struct inode *inode, struct file *filp,
@@ -837,10 +818,8 @@
 extern int	     DRM(context_switch)(drm_device_t *dev, int old, int new);
 extern int	     DRM(context_switch_complete)(drm_device_t *dev, int new);
 
-#if __HAVE_CTX_BITMAP
 extern int	     DRM(ctxbitmap_init)( drm_device_t *dev );
 extern void	     DRM(ctxbitmap_cleanup)( drm_device_t *dev );
-#endif
 
 extern int	     DRM(setsareactx)( struct inode *inode, struct file *filp,
 				       unsigned int cmd, unsigned long arg );
@@ -884,7 +863,6 @@
 				  unsigned int cmd, unsigned long arg );
 extern int	     DRM(rmmap)( struct inode *inode, struct file *filp,
 				 unsigned int cmd, unsigned long arg );
-#if __HAVE_DMA
 extern int	     DRM(addbufs)( struct inode *inode, struct file *filp,
 				   unsigned int cmd, unsigned long arg );
 extern int	     DRM(infobufs)( struct inode *inode, struct file *filp,
@@ -901,33 +879,22 @@
 extern void	     DRM(dma_takedown)(drm_device_t *dev);
 extern void	     DRM(free_buffer)(drm_device_t *dev, drm_buf_t *buf);
 extern void	     DRM(reclaim_buffers)( struct file *filp );
-#endif /* __HAVE_DMA */
 
 				/* IRQ support (drm_irq.h) */
-#if __HAVE_IRQ || __HAVE_DMA
 extern int           DRM(control)( struct inode *inode, struct file *filp,
 				   unsigned int cmd, unsigned long arg );
-#endif
-#if __HAVE_IRQ
 extern int           DRM(irq_install)( drm_device_t *dev );
 extern int           DRM(irq_uninstall)( drm_device_t *dev );
 extern irqreturn_t   DRM(irq_handler)( DRM_IRQ_ARGS );
 extern void          DRM(driver_irq_preinstall)( drm_device_t *dev );
 extern void          DRM(driver_irq_postinstall)( drm_device_t *dev );
 extern void          DRM(driver_irq_uninstall)( drm_device_t *dev );
-#ifdef __HAVE_VBL_IRQ
+
 extern int           DRM(wait_vblank)(struct inode *inode, struct file *filp,
 				      unsigned int cmd, unsigned long arg);
 extern int           DRM(vblank_wait)(drm_device_t *dev, unsigned int *vbl_seq);
 extern void          DRM(vbl_send_signals)( drm_device_t *dev );
-#endif
-#ifdef __HAVE_IRQ_BH
-extern void          DRM(irq_immediate_bh)( void *dev );
-#endif
-#endif
 
-
-#if __REALLY_HAVE_AGP
 				/* AGP/GART support (drm_agpsupport.h) */
 extern drm_agp_head_t *DRM(agp_init)(void);
 extern void           DRM(agp_uninit)(void);
@@ -952,7 +919,6 @@
 extern int            DRM(agp_free_memory)(DRM_AGP_MEM *handle);
 extern int            DRM(agp_bind_memory)(DRM_AGP_MEM *handle, off_t start);
 extern int            DRM(agp_unbind_memory)(DRM_AGP_MEM *handle);
-#endif
 
 				/* Stub support (drm_stub.h) */
 int                   DRM(stub_register)(const char *name,
@@ -969,14 +935,12 @@
 					struct proc_dir_entry *root,
 					struct proc_dir_entry *dev_root);
 
-#ifdef __HAVE_SG
 				/* Scatter Gather Support (drm_scatter.h) */
 extern void           DRM(sg_cleanup)(drm_sg_mem_t *entry);
 extern int            DRM(sg_alloc)(struct inode *inode, struct file *filp,
 				    unsigned int cmd, unsigned long arg);
 extern int            DRM(sg_free)(struct inode *inode, struct file *filp,
 				   unsigned int cmd, unsigned long arg);
-#endif
 
                                /* ATI PCIGART support (ati_pcigart.h) */
 extern int            DRM(ati_pcigart_init)(drm_device_t *dev,
@@ -986,7 +950,44 @@
 					       unsigned long addr,
 					       dma_addr_t bus_addr);
 
+
+/* Inline replacements for DRM_IOREMAP macros */
+static __inline__ void drm_core_ioremap(struct drm_map *map, struct drm_device *dev)
+{
+	map->handle = DRM(ioremap)( map->offset, map->size, dev );
+}
+
+static __inline__ void drm_core_ioremap_nocache(struct drm_map *map, struct drm_device *dev)
+{
+	map->handle = DRM(ioremap_nocache)(map->offset, map->size, dev);
+}
+
+static __inline__ void drm_core_ioremapfree(struct drm_map *map, struct drm_device *dev)
+{
+	if ( map->handle && map->size )
+		DRM(ioremapfree)( map->handle, map->size, dev );
+}
+
+static __inline__ struct drm_map *drm_core_findmap(struct drm_device *dev, unsigned long offset)
+{
+	struct list_head *_list;
+	list_for_each( _list, &dev->maplist->head ) {
+		drm_map_list_t *_entry = list_entry( _list, drm_map_list_t, head );
+		if ( _entry->map &&
+		     _entry->map->offset == offset ) {
+			return _entry->map;
+		}
+	}
+	return NULL;
+}
+
+static __inline__ void drm_core_dropmap(struct drm_map *map)
+{
+}
 /*@}*/
+
+extern unsigned long DRM(core_get_map_ofs)(drm_map_t *map);
+extern unsigned long DRM(core_get_reg_ofs)(struct drm_device *dev);
 
 #endif /* __KERNEL__ */
 #endif
diff -Nru a/drivers/char/drm/drm_agpsupport.h b/drivers/char/drm/drm_agpsupport.h
--- a/drivers/char/drm/drm_agpsupport.h	2004-10-18 14:55:46 -07:00
+++ b/drivers/char/drm/drm_agpsupport.h	2004-10-18 14:55:46 -07:00
@@ -34,8 +34,7 @@
 #include "drmP.h"
 #include <linux/module.h>
 
-#if __REALLY_HAVE_AGP
-
+#if __OS_HAS_AGP
 
 #define DRM_AGP_GET (drm_agp_t *)inter_module_get("drm_agp")
 #define DRM_AGP_PUT inter_module_put("drm_agp")
@@ -466,4 +465,4 @@
 	return drm_agp->unbind_memory(handle);
 }
 
-#endif /* __REALLY_HAVE_AGP */
+#endif /* __OS_HAS_AGP */
diff -Nru a/drivers/char/drm/drm_bufs.h b/drivers/char/drm/drm_bufs.h
--- a/drivers/char/drm/drm_bufs.h	2004-10-18 14:56:19 -07:00
+++ b/drivers/char/drm/drm_bufs.h	2004-10-18 14:56:19 -07:00
@@ -36,26 +36,6 @@
 #include <linux/vmalloc.h>
 #include "drmP.h"
 
-#ifndef __HAVE_PCI_DMA
-#define __HAVE_PCI_DMA		0
-#endif
-
-#ifndef __HAVE_SG
-#define __HAVE_SG		0
-#endif
-
-#ifndef DRIVER_BUF_PRIV_T
-#define DRIVER_BUF_PRIV_T		u32
-#endif
-#ifndef DRIVER_AGP_BUFFERS_MAP
-#if __HAVE_AGP && __HAVE_DMA
-#error "You must define DRIVER_AGP_BUFFERS_MAP()"
-#else
-#define DRIVER_AGP_BUFFERS_MAP( dev )	NULL
-#endif
-#endif
-
-
 /**
  * Compute size order.  Returns the exponent of the smaller power of two which
  * is greater or equal to given number.
@@ -142,13 +122,13 @@
 #ifdef __alpha__
 		map->offset += dev->hose->mem_space->start;
 #endif
-#if __REALLY_HAVE_MTRR
-		if ( map->type == _DRM_FRAME_BUFFER ||
-		     (map->flags & _DRM_WRITE_COMBINING) ) {
-			map->mtrr = mtrr_add( map->offset, map->size,
-					      MTRR_TYPE_WRCOMB, 1 );
+		if (drm_core_has_MTRR(dev)) {
+			if ( map->type == _DRM_FRAME_BUFFER ||
+			     (map->flags & _DRM_WRITE_COMBINING) ) {
+				map->mtrr = mtrr_add( map->offset, map->size,
+						      MTRR_TYPE_WRCOMB, 1 );
+			}
 		}
-#endif
 		if (map->type == _DRM_REGISTERS)
 			map->handle = DRM(ioremap)( map->offset, map->size,
 						    dev );
@@ -174,15 +154,15 @@
 			dev->lock.hw_lock = map->handle; /* Pointer to lock */
 		}
 		break;
-#if __REALLY_HAVE_AGP
 	case _DRM_AGP:
+		if (drm_core_has_AGP(dev)) {
 #ifdef __alpha__
-		map->offset += dev->hose->mem_space->start;
+			map->offset += dev->hose->mem_space->start;
 #endif
-		map->offset += dev->agp->base;
-		map->mtrr   = dev->agp->agp_mtrr; /* for getmap */
+			map->offset += dev->agp->base;
+			map->mtrr   = dev->agp->agp_mtrr; /* for getmap */
+		}
 		break;
-#endif
 	case _DRM_SCATTER_GATHER:
 		if (!dev->sg) {
 			DRM(free)(map, sizeof(*map), DRM_MEM_MAPS);
@@ -282,15 +262,15 @@
 		switch (map->type) {
 		case _DRM_REGISTERS:
 		case _DRM_FRAME_BUFFER:
-#if __REALLY_HAVE_MTRR
-			if (map->mtrr >= 0) {
-				int retcode;
-				retcode = mtrr_del(map->mtrr,
-						   map->offset,
-						   map->size);
-				DRM_DEBUG("mtrr_del = %d\n", retcode);
+		  if (drm_core_has_MTRR(dev)) {
+				if (map->mtrr >= 0) {
+					int retcode;
+					retcode = mtrr_del(map->mtrr,
+							   map->offset,
+							   map->size);
+					DRM_DEBUG("mtrr_del = %d\n", retcode);
+				}
 			}
-#endif
 			DRM(ioremapfree)(map->handle, map->size, dev);
 			break;
 		case _DRM_SHM:
@@ -306,8 +286,6 @@
 	return 0;
 }
 
-#if __HAVE_DMA
-
 /**
  * Cleanup after an error on one of the addbufs() functions.
  *
@@ -348,15 +326,11 @@
 			  sizeof(*entry->buflist),
 			  DRM_MEM_BUFS);
 
-#if __HAVE_DMA_FREELIST
-	   	DRM(freelist_destroy)(&entry->freelist);
-#endif
-
 		entry->buf_count = 0;
 	}
 }
 
-#if __REALLY_HAVE_AGP
+#if __OS_HAS_AGP
 /**
  * Add AGP buffers for DMA transfers (ioctl).
  *
@@ -473,8 +447,8 @@
 		init_waitqueue_head( &buf->dma_wait );
 		buf->filp    = NULL;
 
-		buf->dev_priv_size = sizeof(DRIVER_BUF_PRIV_T);
-		buf->dev_private = DRM(alloc)( sizeof(DRIVER_BUF_PRIV_T),
+		buf->dev_priv_size = dev->dev_priv_size;
+		buf->dev_private = DRM(alloc)( buf->dev_priv_size,
 					       DRM_MEM_BUFS );
 		if(!buf->dev_private) {
 			/* Set count correctly so we free the proper amount. */
@@ -520,12 +494,6 @@
 	DRM_DEBUG( "dma->buf_count : %d\n", dma->buf_count );
 	DRM_DEBUG( "entry->buf_count : %d\n", entry->buf_count );
 
-#if __HAVE_DMA_FREELIST
-	DRM(freelist_create)( &entry->freelist, entry->buf_count );
-	for ( i = 0 ; i < entry->buf_count ; i++ ) {
-		DRM(freelist_put)( dev, &entry->freelist, &entry->buflist[i] );
-	}
-#endif
 	up( &dev->struct_sem );
 
 	request.count = entry->buf_count;
@@ -539,9 +507,8 @@
 	atomic_dec( &dev->buf_alloc );
 	return 0;
 }
-#endif /* __REALLY_HAVE_AGP */
+#endif /* __OS_HAS_AGP */
 
-#if __HAVE_PCI_DMA
 int DRM(addbufs_pci)( struct inode *inode, struct file *filp,
 		      unsigned int cmd, unsigned long arg )
 {
@@ -566,6 +533,7 @@
 	drm_buf_t **temp_buflist;
 	drm_buf_desc_t __user *argp = (void __user *)arg;
 
+	if (!drm_core_check_feature(dev, DRIVER_PCI_DMA)) return -EINVAL;
 	if ( !dma ) return -EINVAL;
 
 	if ( copy_from_user( &request, argp, sizeof(request) ) )
@@ -697,8 +665,8 @@
 			init_waitqueue_head( &buf->dma_wait );
 			buf->filp    = NULL;
 
-			buf->dev_priv_size = sizeof(DRIVER_BUF_PRIV_T);
-			buf->dev_private = DRM(alloc)( sizeof(DRIVER_BUF_PRIV_T),
+			buf->dev_priv_size = dev->dev_priv_size;
+			buf->dev_private = DRM(alloc)( dev->dev_priv_size,
 						       DRM_MEM_BUFS );
 			if(!buf->dev_private) {
 				/* Set count correctly so we free the proper amount. */
@@ -758,12 +726,6 @@
 	dma->page_count += entry->seg_count << page_order;
 	dma->byte_count += PAGE_SIZE * (entry->seg_count << page_order);
 
-#if __HAVE_DMA_FREELIST
-	DRM(freelist_create)( &entry->freelist, entry->buf_count );
-	for ( i = 0 ; i < entry->buf_count ; i++ ) {
-		DRM(freelist_put)( dev, &entry->freelist, &entry->buflist[i] );
-	}
-#endif
 	up( &dev->struct_sem );
 
 	request.count = entry->buf_count;
@@ -776,9 +738,7 @@
 	return 0;
 
 }
-#endif /* __HAVE_PCI_DMA */
 
-#if __HAVE_SG
 int DRM(addbufs_sg)( struct inode *inode, struct file *filp,
                      unsigned int cmd, unsigned long arg )
 {
@@ -801,6 +761,8 @@
 	int i;
 	drm_buf_t **temp_buflist;
 
+	if (!drm_core_check_feature(dev, DRIVER_SG)) return -EINVAL;
+	
 	if ( !dma ) return -EINVAL;
 
 	if ( copy_from_user( &request, argp, sizeof(request) ) )
@@ -881,8 +843,8 @@
 		init_waitqueue_head( &buf->dma_wait );
 		buf->filp    = NULL;
 
-		buf->dev_priv_size = sizeof(DRIVER_BUF_PRIV_T);
-		buf->dev_private = DRM(alloc)( sizeof(DRIVER_BUF_PRIV_T),
+		buf->dev_priv_size = dev->dev_priv_size;
+		buf->dev_private = DRM(alloc)( dev->dev_priv_size,
 					       DRM_MEM_BUFS );
 		if(!buf->dev_private) {
 			/* Set count correctly so we free the proper amount. */
@@ -929,12 +891,6 @@
 	DRM_DEBUG( "dma->buf_count : %d\n", dma->buf_count );
 	DRM_DEBUG( "entry->buf_count : %d\n", entry->buf_count );
 
-#if __HAVE_DMA_FREELIST
-	DRM(freelist_create)( &entry->freelist, entry->buf_count );
-	for ( i = 0 ; i < entry->buf_count ; i++ ) {
-		DRM(freelist_put)( dev, &entry->freelist, &entry->buflist[i] );
-	}
-#endif
 	up( &dev->struct_sem );
 
 	request.count = entry->buf_count;
@@ -948,7 +904,6 @@
 	atomic_dec( &dev->buf_alloc );
 	return 0;
 }
-#endif /* __HAVE_SG */
 
 /**
  * Add buffers for DMA transfers (ioctl).
@@ -968,26 +923,25 @@
 		  unsigned int cmd, unsigned long arg )
 {
 	drm_buf_desc_t request;
+	drm_file_t *priv = filp->private_data;
+	drm_device_t *dev = priv->dev;
+	
+	if (!drm_core_check_feature(dev, DRIVER_HAVE_DMA))
+		return -EINVAL;
 
 	if ( copy_from_user( &request, (drm_buf_desc_t __user *)arg,
 			     sizeof(request) ) )
 		return -EFAULT;
 
-#if __REALLY_HAVE_AGP
+#if __OS_HAS_AGP
 	if ( request.flags & _DRM_AGP_BUFFER )
 		return DRM(addbufs_agp)( inode, filp, cmd, arg );
 	else
 #endif
-#if __HAVE_SG
 	if ( request.flags & _DRM_SG_BUFFER )
 		return DRM(addbufs_sg)( inode, filp, cmd, arg );
 	else
-#endif
-#if __HAVE_PCI_DMA
 		return DRM(addbufs_pci)( inode, filp, cmd, arg );
-#else
-		return -EINVAL;
-#endif
 }
 
 
@@ -1019,6 +973,9 @@
 	int i;
 	int count;
 
+	if (!drm_core_check_feature(dev, DRIVER_HAVE_DMA))
+		return -EINVAL;
+
 	if ( !dma ) return -EINVAL;
 
 	spin_lock( &dev->count_lock );
@@ -1100,6 +1057,9 @@
 	int order;
 	drm_buf_entry_t *entry;
 
+	if (!drm_core_check_feature(dev, DRIVER_HAVE_DMA))
+		return -EINVAL;
+
 	if ( !dma ) return -EINVAL;
 
 	if ( copy_from_user( &request,
@@ -1147,6 +1107,9 @@
 	int idx;
 	drm_buf_t *buf;
 
+	if (!drm_core_check_feature(dev, DRIVER_HAVE_DMA))
+		return -EINVAL;
+
 	if ( !dma ) return -EINVAL;
 
 	if ( copy_from_user( &request,
@@ -1204,6 +1167,9 @@
 	drm_buf_map_t request;
 	int i;
 
+	if (!drm_core_check_feature(dev, DRIVER_HAVE_DMA))
+		return -EINVAL;
+
 	if ( !dma ) return -EINVAL;
 
 	spin_lock( &dev->count_lock );
@@ -1218,9 +1184,9 @@
 		return -EFAULT;
 
 	if ( request.count >= dma->buf_count ) {
-		if ( (__HAVE_AGP && (dma->flags & _DRM_DMA_USE_AGP)) ||
-		     (__HAVE_SG && (dma->flags & _DRM_DMA_USE_SG)) ) {
-			drm_map_t *map = DRIVER_AGP_BUFFERS_MAP( dev );
+		if ((drm_core_has_AGP(dev) && (dma->flags & _DRM_DMA_USE_AGP)) ||
+		    (drm_core_check_feature(dev, DRIVER_SG) && (dma->flags & _DRM_DMA_USE_SG)) ) {
+			drm_map_t *map = dev->agp_buffer_map;
 
 			if ( !map ) {
 				retcode = -EINVAL;
@@ -1301,4 +1267,3 @@
 	return retcode;
 }
 
-#endif /* __HAVE_DMA */
diff -Nru a/drivers/char/drm/drm_context.h b/drivers/char/drm/drm_context.h
--- a/drivers/char/drm/drm_context.h	2004-10-18 14:55:46 -07:00
+++ b/drivers/char/drm/drm_context.h	2004-10-18 14:55:46 -07:00
@@ -42,11 +42,6 @@
 
 #include "drmP.h"
 
-#if !__HAVE_CTX_BITMAP
-#error "__HAVE_CTX_BITMAP must be defined"
-#endif
-
-
 /******************************************************************/
 /** \name Context bitmap support */
 /*@{*/
@@ -419,10 +414,13 @@
 				/* Should this return -EBUSY instead? */
 		return -ENOMEM;
 	}
-#ifdef DRIVER_CTX_CTOR
+
 	if ( ctx.handle != DRM_KERNEL_CONTEXT )
-		DRIVER_CTX_CTOR(ctx.handle); /* XXX: also pass dev ? */
-#endif
+	{
+		if (dev->fn_tbl.context_ctor)
+			dev->fn_tbl.context_ctor(dev, ctx.handle);
+	}
+
 	ctx_entry = DRM(alloc)( sizeof(*ctx_entry), DRM_MEM_CTXLIST );
 	if ( !ctx_entry ) {
 		DRM_DEBUG("out of memory\n");
@@ -554,9 +552,8 @@
 		priv->remove_auth_on_close = 1;
 	}
 	if ( ctx.handle != DRM_KERNEL_CONTEXT ) {
-#ifdef DRIVER_CTX_DTOR
-		DRIVER_CTX_DTOR(ctx.handle); /* XXX: also pass dev ? */
-#endif
+		if (dev->fn_tbl.context_dtor)
+			dev->fn_tbl.context_dtor(dev, ctx.handle);
 		DRM(ctxbitmap_free)( dev, ctx.handle );
 	}
 
@@ -578,3 +575,4 @@
 }
 
 /*@}*/
+
diff -Nru a/drivers/char/drm/drm_core.h b/drivers/char/drm/drm_core.h
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/drivers/char/drm/drm_core.h	2004-10-18 14:57:23 -07:00
@@ -0,0 +1,40 @@
+/*
+ * Copyright 2004 Jon Smirl <jonsmirl@gmail.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sub license,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+ * VIA, S3 GRAPHICS, AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+#include "drm_auth.h"
+#include "drm_agpsupport.h"
+#include "drm_bufs.h"
+#include "drm_context.h"
+#include "drm_dma.h"
+#include "drm_irq.h"
+#include "drm_drawable.h"
+#include "drm_drv.h"
+#include "drm_fops.h"
+#include "drm_init.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"
+#include "drm_scatter.h"
diff -Nru a/drivers/char/drm/drm_dma.h b/drivers/char/drm/drm_dma.h
--- a/drivers/char/drm/drm_dma.h	2004-10-18 14:56:33 -07:00
+++ b/drivers/char/drm/drm_dma.h	2004-10-18 14:56:33 -07:00
@@ -35,16 +35,6 @@
 
 #include "drmP.h"
 
-
-#ifndef __HAVE_DMA_WAITQUEUE
-#define __HAVE_DMA_WAITQUEUE	0
-#endif
-#ifndef __HAVE_DMA_RECLAIM
-#define __HAVE_DMA_RECLAIM	0
-#endif
-
-#if __HAVE_DMA
-
 /**
  * Initialize the DMA data.
  * 
@@ -116,9 +106,6 @@
 				  dma->bufs[i].buf_count *
 				  sizeof(*dma->bufs[0].buflist),
 				  DRM_MEM_BUFS);
-#if __HAVE_DMA_FREELIST
-		   	DRM(freelist_destroy)(&dma->bufs[i].freelist);
-#endif
 		}
 	}
 
@@ -155,22 +142,11 @@
 	buf->filp     = NULL;
 	buf->used     = 0;
 
-	if ( __HAVE_DMA_WAITQUEUE && waitqueue_active(&buf->dma_wait)) {
+	if (drm_core_check_feature(dev, DRIVER_DMA_QUEUE) && waitqueue_active(&buf->dma_wait)) {
 		wake_up_interruptible(&buf->dma_wait);
 	}
-#if __HAVE_DMA_FREELIST
-	else {
-		drm_device_dma_t *dma = dev->dma;
-				/* If processes are waiting, the last one
-				   to wake will put the buffer on the free
-				   list.  If no processes are waiting, we
-				   put the buffer on the freelist here. */
-		DRM(freelist_put)(dev, &dma->bufs[buf->order].freelist, buf);
-	}
-#endif
 }
 
-#if !__HAVE_DMA_RECLAIM
 /**
  * Reclaim the buffers.
  *
@@ -178,7 +154,7 @@
  *
  * Frees each buffer associated with \p filp not already on the hardware.
  */
-void DRM(reclaim_buffers)( struct file *filp )
+void DRM(core_reclaim_buffers)( struct file *filp )
 {
 	drm_file_t    *priv   = filp->private_data;
 	drm_device_t  *dev    = priv->dev;
@@ -202,29 +178,4 @@
 		}
 	}
 }
-#endif
-
-#if !__HAVE_IRQ
-/* This stub DRM_IOCTL_CONTROL handler is for the drivers that used to require
- * IRQs for DMA but no longer do.  It maintains compatibility with the X Servers
- * that try to use the control ioctl by simply returning success.
- */
-int DRM(control)( struct inode *inode, struct file *filp,
-		  unsigned int cmd, unsigned long arg )
-{
-	drm_control_t ctl;
-
-	if ( copy_from_user( &ctl, (drm_control_t __user *)arg, sizeof(ctl) ) )
-		return -EFAULT;
-
-	switch ( ctl.func ) {
-	case DRM_INST_HANDLER:
-	case DRM_UNINST_HANDLER:
-		return 0;
-	default:
-		return -EINVAL;
-	}
-}
-#endif
 
-#endif /* __HAVE_DMA */
diff -Nru a/drivers/char/drm/drm_drv.h b/drivers/char/drm/drm_drv.h
--- a/drivers/char/drm/drm_drv.h	2004-10-18 14:56:49 -07:00
+++ b/drivers/char/drm/drm_drv.h	2004-10-18 14:56:49 -07:00
@@ -52,97 +52,9 @@
  * OTHER DEALINGS IN THE SOFTWARE.
  */
 
-#ifndef __MUST_HAVE_AGP
-#define __MUST_HAVE_AGP			0
-#endif
-#ifndef __HAVE_CTX_BITMAP
-#define __HAVE_CTX_BITMAP		0
-#endif
-#ifndef __HAVE_IRQ
-#define __HAVE_IRQ			0
-#endif
-#ifndef __HAVE_DMA_QUEUE
-#define __HAVE_DMA_QUEUE		0
-#endif
-#ifndef __HAVE_MULTIPLE_DMA_QUEUES
-#define __HAVE_MULTIPLE_DMA_QUEUES	0
-#endif
-#ifndef __HAVE_DMA_SCHEDULE
-#define __HAVE_DMA_SCHEDULE		0
-#endif
-#ifndef __HAVE_DMA_FLUSH
-#define __HAVE_DMA_FLUSH		0
-#endif
-#ifndef __HAVE_DMA_READY
-#define __HAVE_DMA_READY		0
-#endif
-#ifndef __HAVE_DMA_QUIESCENT
-#define __HAVE_DMA_QUIESCENT		0
-#endif
-#ifndef __HAVE_RELEASE
-#define __HAVE_RELEASE			0
-#endif
-#ifndef __HAVE_COUNTERS
-#define __HAVE_COUNTERS			0
-#endif
-#ifndef __HAVE_SG
-#define __HAVE_SG			0
-#endif
-/* __HAVE_KERNEL_CTX_SWITCH isn't used by any of the drm modules in
- * the DRI cvs tree, but it is required by the kernel tree's sparc
- * driver.
- */
-#ifndef __HAVE_KERNEL_CTX_SWITCH
-#define __HAVE_KERNEL_CTX_SWITCH	0
-#endif
-#ifndef __HAVE_DRIVER_FOPS_READ
-#define __HAVE_DRIVER_FOPS_READ		0
-#endif
-#ifndef __HAVE_DRIVER_FOPS_POLL
-#define __HAVE_DRIVER_FOPS_POLL		0
-#endif
-
-#ifndef DRIVER_PREINIT
-#define DRIVER_PREINIT()
-#endif
-#ifndef DRIVER_POSTINIT
-#define DRIVER_POSTINIT()
-#endif
-#ifndef DRIVER_PRERELEASE
-#define DRIVER_PRERELEASE()
-#endif
-#ifndef DRIVER_PRETAKEDOWN
-#define DRIVER_PRETAKEDOWN()
-#endif
-#ifndef DRIVER_POSTCLEANUP
-#define DRIVER_POSTCLEANUP()
-#endif
-#ifndef DRIVER_PRESETUP
-#define DRIVER_PRESETUP()
-#endif
-#ifndef DRIVER_POSTSETUP
-#define DRIVER_POSTSETUP()
-#endif
 #ifndef DRIVER_IOCTLS
 #define DRIVER_IOCTLS
 #endif
-#ifndef DRIVER_OPEN_HELPER
-#define DRIVER_OPEN_HELPER( priv, dev )
-#endif
-#ifndef DRIVER_FOPS
-#define DRIVER_FOPS				\
-static struct file_operations	DRM(fops) = {	\
-	.owner   = THIS_MODULE,			\
-	.open	 = DRM(open),			\
-	.flush	 = DRM(flush),			\
-	.release = DRM(release),		\
-	.ioctl	 = DRM(ioctl),			\
-	.mmap	 = DRM(mmap),			\
-	.fasync  = DRM(fasync),			\
-	.poll	 = DRM(poll),			\
-	.read	 = DRM(read),			\
-}
-#endif
 
 #ifndef MODULE
 /** Use an additional macro to avoid preprocessor troubles */
@@ -166,16 +78,24 @@
 static drm_device_t	DRM(device)[MAX_DEVICES];
 static int		DRM(numdevs) = 0;
 
-DRIVER_FOPS;
+struct file_operations	DRM(fops) = {
+	.owner   = THIS_MODULE,
+	.open	 = DRM(open),
+	.flush	 = DRM(flush),
+	.release = DRM(release),
+	.ioctl	 = DRM(ioctl),
+	.mmap	 = DRM(mmap),
+	.fasync  = DRM(fasync),
+	.poll	 = DRM(poll),
+	.read	 = DRM(read),
+};
 
 /** Ioctl table */
-static drm_ioctl_desc_t		  DRM(ioctls)[] = {
+drm_ioctl_desc_t		  DRM(ioctls)[] = {
 	[DRM_IOCTL_NR(DRM_IOCTL_VERSION)]       = { DRM(version),     0, 0 },
 	[DRM_IOCTL_NR(DRM_IOCTL_GET_UNIQUE)]    = { DRM(getunique),   0, 0 },
 	[DRM_IOCTL_NR(DRM_IOCTL_GET_MAGIC)]     = { DRM(getmagic),    0, 0 },
-#if __HAVE_IRQ
 	[DRM_IOCTL_NR(DRM_IOCTL_IRQ_BUSID)]     = { DRM(irq_by_busid), 0, 1 },
-#endif
 	[DRM_IOCTL_NR(DRM_IOCTL_GET_MAP)]       = { DRM(getmap),      0, 0 },
 	[DRM_IOCTL_NR(DRM_IOCTL_GET_CLIENT)]    = { DRM(getclient),   0, 0 },
 	[DRM_IOCTL_NR(DRM_IOCTL_GET_STATS)]     = { DRM(getstats),    0, 0 },
@@ -189,10 +109,8 @@
 	[DRM_IOCTL_NR(DRM_IOCTL_ADD_MAP)]       = { DRM(addmap),      1, 1 },
 	[DRM_IOCTL_NR(DRM_IOCTL_RM_MAP)]        = { DRM(rmmap),       1, 0 },
 
-#if __HAVE_CTX_BITMAP
 	[DRM_IOCTL_NR(DRM_IOCTL_SET_SAREA_CTX)] = { DRM(setsareactx), 1, 1 },
 	[DRM_IOCTL_NR(DRM_IOCTL_GET_SAREA_CTX)] = { DRM(getsareactx), 1, 0 },
-#endif
 
 	[DRM_IOCTL_NR(DRM_IOCTL_ADD_CTX)]       = { DRM(addctx),      1, 1 },
 	[DRM_IOCTL_NR(DRM_IOCTL_RM_CTX)]        = { DRM(rmctx),       1, 1 },
@@ -208,26 +126,18 @@
 	[DRM_IOCTL_NR(DRM_IOCTL_LOCK)]	        = { DRM(lock),        1, 0 },
 	[DRM_IOCTL_NR(DRM_IOCTL_UNLOCK)]        = { DRM(unlock),      1, 0 },
 
-#if __HAVE_DMA_FLUSH
-	/* Gamma only, really */
-	[DRM_IOCTL_NR(DRM_IOCTL_FINISH)]        = { DRM(finish),      1, 0 },
-#else
 	[DRM_IOCTL_NR(DRM_IOCTL_FINISH)]        = { DRM(noop),      1, 0 },
-#endif
 
-#if __HAVE_DMA
 	[DRM_IOCTL_NR(DRM_IOCTL_ADD_BUFS)]      = { DRM(addbufs),     1, 1 },
 	[DRM_IOCTL_NR(DRM_IOCTL_MARK_BUFS)]     = { DRM(markbufs),    1, 1 },
 	[DRM_IOCTL_NR(DRM_IOCTL_INFO_BUFS)]     = { DRM(infobufs),    1, 0 },
 	[DRM_IOCTL_NR(DRM_IOCTL_MAP_BUFS)]      = { DRM(mapbufs),     1, 0 },
 	[DRM_IOCTL_NR(DRM_IOCTL_FREE_BUFS)]     = { DRM(freebufs),    1, 0 },
 	/* The DRM_IOCTL_DMA ioctl should be defined by the driver. */
-#endif
-#if __HAVE_IRQ || __HAVE_DMA
+
 	[DRM_IOCTL_NR(DRM_IOCTL_CONTROL)]       = { DRM(control),     1, 1 },
-#endif
 
-#if __REALLY_HAVE_AGP
+#if __OS_HAS_AGP
 	[DRM_IOCTL_NR(DRM_IOCTL_AGP_ACQUIRE)]   = { DRM(agp_acquire), 1, 1 },
 	[DRM_IOCTL_NR(DRM_IOCTL_AGP_RELEASE)]   = { DRM(agp_release), 1, 1 },
 	[DRM_IOCTL_NR(DRM_IOCTL_AGP_ENABLE)]    = { DRM(agp_enable),  1, 1 },
@@ -238,14 +148,10 @@
 	[DRM_IOCTL_NR(DRM_IOCTL_AGP_UNBIND)]    = { DRM(agp_unbind),  1, 1 },
 #endif
 
-#if __HAVE_SG
 	[DRM_IOCTL_NR(DRM_IOCTL_SG_ALLOC)]      = { DRM(sg_alloc),    1, 1 },
 	[DRM_IOCTL_NR(DRM_IOCTL_SG_FREE)]       = { DRM(sg_free),     1, 1 },
-#endif
 
-#ifdef __HAVE_VBL_IRQ
 	[DRM_IOCTL_NR(DRM_IOCTL_WAIT_VBLANK)]   = { DRM(wait_vblank), 0, 0 },
-#endif
 
 	DRIVER_IOCTLS
 };
@@ -264,56 +170,26 @@
 static int DRM(setup)( drm_device_t *dev )
 {
 	int i;
+	int ret;
+
+	if (dev->fn_tbl.presetup)
+	{
+		ret=dev->fn_tbl.presetup(dev);
+		if (ret!=0) 
+			return ret;
+	}
 
-	DRIVER_PRESETUP();
 	atomic_set( &dev->ioctl_count, 0 );
 	atomic_set( &dev->vma_count, 0 );
 	dev->buf_use = 0;
 	atomic_set( &dev->buf_alloc, 0 );
 
-#if __HAVE_DMA
-	i = DRM(dma_setup)( dev );
-	if ( i < 0 )
-		return i;
-#endif
-
-	dev->counters  = 6 + __HAVE_COUNTERS;
-	dev->types[0]  = _DRM_STAT_LOCK;
-	dev->types[1]  = _DRM_STAT_OPENS;
-	dev->types[2]  = _DRM_STAT_CLOSES;
-	dev->types[3]  = _DRM_STAT_IOCTLS;
-	dev->types[4]  = _DRM_STAT_LOCKS;
-	dev->types[5]  = _DRM_STAT_UNLOCKS;
-#ifdef __HAVE_COUNTER6
-	dev->types[6]  = __HAVE_COUNTER6;
-#endif
-#ifdef __HAVE_COUNTER7
-	dev->types[7]  = __HAVE_COUNTER7;
-#endif
-#ifdef __HAVE_COUNTER8
-	dev->types[8]  = __HAVE_COUNTER8;
-#endif
-#ifdef __HAVE_COUNTER9
-	dev->types[9]  = __HAVE_COUNTER9;
-#endif
-#ifdef __HAVE_COUNTER10
-	dev->types[10] = __HAVE_COUNTER10;
-#endif
-#ifdef __HAVE_COUNTER11
-	dev->types[11] = __HAVE_COUNTER11;
-#endif
-#ifdef __HAVE_COUNTER12
-	dev->types[12] = __HAVE_COUNTER12;
-#endif
-#ifdef __HAVE_COUNTER13
-	dev->types[13] = __HAVE_COUNTER13;
-#endif
-#ifdef __HAVE_COUNTER14
-	dev->types[14] = __HAVE_COUNTER14;
-#endif
-#ifdef __HAVE_COUNTER15
-	dev->types[14] = __HAVE_COUNTER14;
-#endif
+	if (drm_core_check_feature(dev, DRIVER_HAVE_DMA))
+	{
+		i = DRM(dma_setup)( dev );
+		if ( i < 0 )
+			return i;
+	}
 
 	for ( i = 0 ; i < DRM_ARRAY_SIZE(dev->counts) ; i++ )
 		atomic_set( &dev->counts[i], 0 );
@@ -371,7 +247,9 @@
 	 * drm_select_queue fails between the time the interrupt is
 	 * initialized and the time the queues are initialized.
 	 */
-	DRIVER_POSTSETUP();
+	if (dev->fn_tbl.postsetup)
+		dev->fn_tbl.postsetup(dev);
+
 	return 0;
 }
 
@@ -396,10 +274,10 @@
 
 	DRM_DEBUG( "\n" );
 
-	DRIVER_PRETAKEDOWN();
-#if __HAVE_IRQ
+	if (dev->fn_tbl.pretakedown)
+	  dev->fn_tbl.pretakedown(dev);
+
 	if ( dev->irq_enabled ) DRM(irq_uninstall)( dev );
-#endif
 
 	down( &dev->struct_sem );
 	del_timer( &dev->timer );
@@ -425,9 +303,8 @@
 		dev->magiclist[i].head = dev->magiclist[i].tail = NULL;
 	}
 
-#if __REALLY_HAVE_AGP
 				/* Clear AGP information */
-	if ( dev->agp ) {
+	if (drm_core_has_AGP(dev) && dev->agp) {
 		drm_agp_mem_t *entry;
 		drm_agp_mem_t *nexte;
 
@@ -446,7 +323,6 @@
 		dev->agp->acquired = 0;
 		dev->agp->enabled  = 0;
 	}
-#endif
 
 				/* Clear vma list (only built for debugging) */
 	if ( dev->vmalist ) {
@@ -465,15 +341,15 @@
 				switch ( map->type ) {
 				case _DRM_REGISTERS:
 				case _DRM_FRAME_BUFFER:
-#if __REALLY_HAVE_MTRR
-					if ( map->mtrr >= 0 ) {
-						int retcode;
-						retcode = mtrr_del( map->mtrr,
-								    map->offset,
-								    map->size );
-						DRM_DEBUG( "mtrr_del=%d\n", retcode );
+					if (drm_core_has_MTRR(dev)) {
+						if ( map->mtrr >= 0 ) {
+							int retcode;
+							retcode = mtrr_del( map->mtrr,
+									    map->offset,
+									    map->size );
+							DRM_DEBUG( "mtrr_del=%d\n", retcode );
+						}
 					}
-#endif
 					DRM(ioremapfree)( map->handle, map->size, dev );
 					break;
 				case _DRM_SHM:
@@ -486,15 +362,11 @@
 					 */
 					break;
 				case _DRM_SCATTER_GATHER:
-					/* Handle it, but do nothing, if HAVE_SG
-					 * isn't defined.
-					 */
-#if __HAVE_SG
-					if(dev->sg) {
+					/* Handle it */
+					if (drm_core_check_feature(dev, DRIVER_SG) && dev->sg) {
 						DRM(sg_cleanup)(dev->sg);
 						dev->sg = NULL;
 					}
-#endif
 					break;
 				}
 				DRM(free)(map, sizeof(*map), DRM_MEM_MAPS);
@@ -506,12 +378,8 @@
 		dev->maplist = NULL;
  	}
 
-#if __HAVE_DMA_QUEUE || __HAVE_MULTIPLE_DMA_QUEUES
-	if ( dev->queuelist ) {
+	if (drm_core_check_feature(dev, DRIVER_DMA_QUEUE) && dev->queuelist ) {
 		for ( i = 0 ; i < dev->queue_count ; i++ ) {
-#if __HAVE_DMA_WAITLIST
-			DRM(waitlist_destroy)( &dev->queuelist[i]->waitlist );
-#endif
 			if ( dev->queuelist[i] ) {
 				DRM(free)( dev->queuelist[i],
 					  sizeof(*dev->queuelist[0]),
@@ -525,11 +393,10 @@
 		dev->queuelist = NULL;
 	}
 	dev->queue_count = 0;
-#endif
 
-#if __HAVE_DMA
-	DRM(dma_takedown)( dev );
-#endif
+	if (drm_core_check_feature(dev, DRIVER_HAVE_DMA))
+		DRM(dma_takedown)( dev );
+
 	if ( dev->lock.hw_lock ) {
 		dev->sigdata.lock = dev->lock.hw_lock = NULL; /* SHM removed */
 		dev->lock.filp = NULL;
@@ -540,6 +407,13 @@
 	return 0;
 }
 
+static void DRM(init_fn_table)(struct drm_device *dev)
+{
+	dev->fn_tbl.reclaim_buffers = DRM(core_reclaim_buffers);
+	dev->fn_tbl.get_map_ofs = DRM(core_get_map_ofs);
+	dev->fn_tbl.get_reg_ofs = DRM(core_get_reg_ofs);
+}
+
 #include "drm_pciids.h"
 
 static struct pci_device_id DRM(pciidlist)[] = {
@@ -549,9 +423,7 @@
 static int DRM(probe)(struct pci_dev *pdev)
 {
 	drm_device_t *dev;
-#if __HAVE_CTX_BITMAP
 	int retcode;
-#endif
 	int i;
 	int is_compat = 0;
 
@@ -569,6 +441,9 @@
 	if (DRM(numdevs) >= MAX_DEVICES)
 		return -ENODEV;
 
+	if ((retcode=pci_enable_device(pdev)))
+		return retcode;
+
 	dev = &(DRM(device)[DRM(numdevs)]);
 
 	memset( (void *)dev, 0, sizeof(*dev) );
@@ -594,36 +469,51 @@
 	dev->pci_func = PCI_FUNC(pdev->devfn);
 	dev->irq = pdev->irq;
 
-	DRIVER_PREINIT();
+	/* dev_priv_size can be changed by a driver in driver_register_fns */
+	dev->dev_priv_size = sizeof(u32);
 
-#if __REALLY_HAVE_AGP
-	dev->agp = DRM(agp_init)();
-#if __MUST_HAVE_AGP
-	if ( dev->agp == NULL ) {
-		DRM_ERROR( "Cannot initialize the agpgart module.\n" );
-		DRM(stub_unregister)(dev->minor);
-		DRM(takedown)( dev );
-		return -EINVAL;
+	/* the DRM has 6 basic counters - drivers add theirs in register_fns */
+	dev->counters = 6;
+	dev->types[0]  = _DRM_STAT_LOCK;
+	dev->types[1]  = _DRM_STAT_OPENS;
+	dev->types[2]  = _DRM_STAT_CLOSES;
+	dev->types[3]  = _DRM_STAT_IOCTLS;
+	dev->types[4]  = _DRM_STAT_LOCKS;
+	dev->types[5]  = _DRM_STAT_UNLOCKS;
+
+	DRM(init_fn_table)(dev);
+
+	DRM(driver_register_fns)(dev);
+
+	if (dev->fn_tbl.preinit)
+	  dev->fn_tbl.preinit(dev);
+
+	if (drm_core_has_AGP(dev))
+	{
+		dev->agp = DRM(agp_init)();
+		if (drm_core_check_feature(dev, DRIVER_REQUIRE_AGP) && (dev->agp == NULL)) {
+			DRM_ERROR( "Cannot initialize the agpgart module.\n" );
+			DRM(stub_unregister)(dev->minor);
+			DRM(takedown)( dev );
+			return -EINVAL;
+		}
+		if (drm_core_has_MTRR(dev)) {
+			if (dev->agp)
+				dev->agp->agp_mtrr = mtrr_add( dev->agp->agp_info.aper_base,
+							       dev->agp->agp_info.aper_size*1024*1024,
+							       MTRR_TYPE_WRCOMB,
+							       1 );
+		}
 	}
-#endif
-#if __REALLY_HAVE_MTRR
-	if (dev->agp)
-		dev->agp->agp_mtrr = mtrr_add( dev->agp->agp_info.aper_base,
-					dev->agp->agp_info.aper_size*1024*1024,
-					MTRR_TYPE_WRCOMB,
-					1 );
-#endif
-#endif
 
-#if __HAVE_CTX_BITMAP
 	retcode = DRM(ctxbitmap_init)( dev );
 	if( retcode ) {
 		DRM_ERROR( "Cannot allocate memory for context bitmap.\n" );
 		DRM(stub_unregister)(dev->minor);
 		DRM(takedown)( dev );
 		return retcode;
- 	}
-#endif
+	}
+
 	DRM(numdevs)++; /* no errors, mark it reserved */
 	
 	DRM_INFO( "Initialized %s %d.%d.%d %s on minor %d: %s\n",
@@ -635,7 +525,8 @@
 		dev->minor,
 		pci_pretty_name(pdev));
 
-	DRIVER_POSTINIT();
+	if (dev->fn_tbl.postinit)
+	  dev->fn_tbl.postinit(dev);
 
 	return 0;
 }
@@ -695,31 +586,30 @@
 				DRM_INFO( "Module unloaded\n" );
 			}
 		}
-#if __HAVE_CTX_BITMAP
+
 		DRM(ctxbitmap_cleanup)( dev );
-#endif
 
-#if __REALLY_HAVE_AGP && __REALLY_HAVE_MTRR
-		if ( dev->agp && dev->agp->agp_mtrr >= 0) {
+		if (drm_core_has_MTRR(dev) && drm_core_has_AGP(dev) &&
+		    dev->agp && dev->agp->agp_mtrr >= 0) {
 			int retval;
 			retval = mtrr_del( dev->agp->agp_mtrr,
 				   dev->agp->agp_info.aper_base,
 				   dev->agp->agp_info.aper_size*1024*1024 );
 			DRM_DEBUG( "mtrr_del=%d\n", retval );
 		}
-#endif
 
 		DRM(takedown)( dev );
 
-#if __REALLY_HAVE_AGP
-		if ( dev->agp ) {
+		if (drm_core_has_AGP(dev) && dev->agp ) {
 			DRM(agp_uninit)();
 			DRM(free)( dev->agp, sizeof(*dev->agp), DRM_MEM_AGPLISTS );
 			dev->agp = NULL;
 		}
-#endif
+
+		if (dev->fn_tbl.postcleanup)
+		  dev->fn_tbl.postcleanup(dev);
+
 	}
-	DRIVER_POSTCLEANUP();
 	DRM(numdevs) = 0;
 }
 
@@ -834,7 +724,8 @@
 
 	DRM_DEBUG( "open_count = %d\n", dev->open_count );
 
-	DRIVER_PRERELEASE();
+	if (dev->fn_tbl.prerelease)
+		dev->fn_tbl.prerelease(dev, filp);
 
 	/* ========================================================
 	 * Begin inline drm_release
@@ -849,9 +740,10 @@
 		DRM_DEBUG( "File %p released, freeing lock for context %d\n",
 			filp,
 			_DRM_LOCKING_CONTEXT(dev->lock.hw_lock->lock) );
-#if __HAVE_RELEASE
-		DRIVER_RELEASE();
-#endif
+		
+		if (dev->fn_tbl.release)
+			dev->fn_tbl.release(dev, filp);
+
 		DRM(lock_free)( dev, &dev->lock.hw_lock->lock,
 				_DRM_LOCKING_CONTEXT(dev->lock.hw_lock->lock) );
 
@@ -860,14 +752,13 @@
                                    processed via a callback to the X
                                    server. */
 	}
-#if __HAVE_RELEASE
-	else if ( priv->lock_count && dev->lock.hw_lock ) {
+	else if ( dev->fn_tbl.release && priv->lock_count && dev->lock.hw_lock ) {
 		/* The lock is required to reclaim buffers */
 		DECLARE_WAITQUEUE( entry, current );
 
 		add_wait_queue( &dev->lock.lock_queue, &entry );
 		for (;;) {
-			current->state = TASK_INTERRUPTIBLE;
+			__set_current_state(TASK_INTERRUPTIBLE);
 			if ( !dev->lock.hw_lock ) {
 				/* Device has been unregistered */
 				retcode = -EINTR;
@@ -887,17 +778,20 @@
 				break;
 			}
 		}
-		current->state = TASK_RUNNING;
+		__set_current_state(TASK_RUNNING);
 		remove_wait_queue( &dev->lock.lock_queue, &entry );
 		if( !retcode ) {
-			DRIVER_RELEASE();
+			if (dev->fn_tbl.release)
+				dev->fn_tbl.release(dev, filp);
 			DRM(lock_free)( dev, &dev->lock.hw_lock->lock,
 					DRM_KERNEL_CONTEXT );
 		}
 	}
-#elif __HAVE_DMA
-	DRM(reclaim_buffers)( filp );
-#endif
+	
+	if (drm_core_check_feature(dev, DRIVER_HAVE_DMA))
+	{
+		dev->fn_tbl.reclaim_buffers(filp);
+	}
 
 	DRM(fasync)( -1, filp, 0 );
 
@@ -908,14 +802,14 @@
 		list_for_each_entry_safe( pos, n, &dev->ctxlist->head, head ) {
 			if ( pos->tag == priv &&
 			     pos->handle != DRM_KERNEL_CONTEXT ) {
-#ifdef DRIVER_CTX_DTOR
-				DRIVER_CTX_DTOR(pos->handle);
-#endif
-#if __HAVE_CTX_BITMAP
+				if (dev->fn_tbl.context_dtor)
+					dev->fn_tbl.context_dtor(dev, pos->handle);
+
 				DRM(ctxbitmap_free)( dev, pos->handle );
-#endif
+
 				list_del( &pos->head );
 				DRM(free)( pos, sizeof(*pos), DRM_MEM_CTXLIST );
+				--dev->ctx_count;
 			}
 		}
 	}
@@ -941,6 +835,9 @@
 	}
 	up( &dev->struct_sem );
 	
+	if (dev->fn_tbl.free_filp_priv)
+		dev->fn_tbl.free_filp_priv(dev, priv);
+
 	DRM(free)( priv, sizeof(*priv), DRM_MEM_FILES );
 
 	/* ========================================================
@@ -1039,9 +936,6 @@
         DECLARE_WAITQUEUE( entry, current );
         drm_lock_t lock;
         int ret = 0;
-#if __HAVE_MULTIPLE_DMA_QUEUES
-	drm_queue_t *q;
-#endif
 
 	++priv->lock_count;
 
@@ -1058,83 +952,61 @@
 		   lock.context, current->pid,
 		   dev->lock.hw_lock->lock, lock.flags );
 
-#if __HAVE_DMA_QUEUE
-        if ( lock.context < 0 )
-                return -EINVAL;
-#elif __HAVE_MULTIPLE_DMA_QUEUES
-        if ( lock.context < 0 || lock.context >= dev->queue_count )
-                return -EINVAL;
-	q = dev->queuelist[lock.context];
-#endif
-
-#if __HAVE_DMA_FLUSH
-	ret = DRM(flush_block_and_flush)( dev, lock.context, lock.flags );
-#endif
-        if ( !ret ) {
-                add_wait_queue( &dev->lock.lock_queue, &entry );
-                for (;;) {
-                        current->state = TASK_INTERRUPTIBLE;
-                        if ( !dev->lock.hw_lock ) {
-                                /* Device has been unregistered */
-                                ret = -EINTR;
-                                break;
-                        }
-                        if ( DRM(lock_take)( &dev->lock.hw_lock->lock,
-					     lock.context ) ) {
-                                dev->lock.filp      = filp;
-                                dev->lock.lock_time = jiffies;
-                                atomic_inc( &dev->counts[_DRM_STAT_LOCKS] );
-                                break;  /* Got lock */
-                        }
-
-                                /* Contention */
-                        schedule();
-                        if ( signal_pending( current ) ) {
-                                ret = -ERESTARTSYS;
-                                break;
-                        }
-                }
-                current->state = TASK_RUNNING;
-                remove_wait_queue( &dev->lock.lock_queue, &entry );
-        }
-
-#if __HAVE_DMA_FLUSH
-	DRM(flush_unblock)( dev, lock.context, lock.flags ); /* cleanup phase */
-#endif
-
-        if ( !ret ) {
-		sigemptyset( &dev->sigmask );
-		sigaddset( &dev->sigmask, SIGSTOP );
-		sigaddset( &dev->sigmask, SIGTSTP );
-		sigaddset( &dev->sigmask, SIGTTIN );
-		sigaddset( &dev->sigmask, SIGTTOU );
-		dev->sigdata.context = lock.context;
-		dev->sigdata.lock    = dev->lock.hw_lock;
-		block_all_signals( DRM(notifier),
-				   &dev->sigdata, &dev->sigmask );
-
-#if __HAVE_DMA_READY
-                if ( lock.flags & _DRM_LOCK_READY ) {
-			DRIVER_DMA_READY();
-		}
-#endif
-#if __HAVE_DMA_QUIESCENT
-                if ( lock.flags & _DRM_LOCK_QUIESCENT ) {
-			DRIVER_DMA_QUIESCENT();
+	if (drm_core_check_feature(dev, DRIVER_DMA_QUEUE))
+		if ( lock.context < 0 )
+			return -EINVAL;
+
+	add_wait_queue( &dev->lock.lock_queue, &entry );
+	for (;;) {
+		__set_current_state(TASK_INTERRUPTIBLE);
+		if ( !dev->lock.hw_lock ) {
+			/* Device has been unregistered */
+			ret = -EINTR;
+			break;
 		}
-#endif
-		/* __HAVE_KERNEL_CTX_SWITCH isn't used by any of the
-		 * drm modules in the DRI cvs tree, but it is required
-		 * by the Sparc driver.
-		 */
-#if __HAVE_KERNEL_CTX_SWITCH
-		if ( dev->last_context != lock.context ) {
-			DRM(context_switch)(dev, dev->last_context,
-					    lock.context);
+		if ( DRM(lock_take)( &dev->lock.hw_lock->lock,
+				     lock.context ) ) {
+			dev->lock.filp      = filp;
+			dev->lock.lock_time = jiffies;
+			atomic_inc( &dev->counts[_DRM_STAT_LOCKS] );
+			break;  /* Got lock */
+		}
+		
+		/* Contention */
+		schedule();
+		if ( signal_pending( current ) ) {
+			ret = -ERESTARTSYS;
+			break;
 		}
-#endif
-        }
+	}
+	__set_current_state(TASK_RUNNING);
+	remove_wait_queue( &dev->lock.lock_queue, &entry );
 
+	sigemptyset( &dev->sigmask );
+	sigaddset( &dev->sigmask, SIGSTOP );
+	sigaddset( &dev->sigmask, SIGTSTP );
+	sigaddset( &dev->sigmask, SIGTTIN );
+	sigaddset( &dev->sigmask, SIGTTOU );
+	dev->sigdata.context = lock.context;
+	dev->sigdata.lock    = dev->lock.hw_lock;
+	block_all_signals( DRM(notifier),
+			   &dev->sigdata, &dev->sigmask );
+	
+	if (dev->fn_tbl.dma_ready && (lock.flags & _DRM_LOCK_READY))
+		dev->fn_tbl.dma_ready(dev);
+	
+	if ( dev->fn_tbl.dma_quiescent && (lock.flags & _DRM_LOCK_QUIESCENT ))
+		return dev->fn_tbl.dma_quiescent(dev);
+	
+	/* dev->fn_tbl.kernel_context_switch isn't used by any of the x86 
+	 *  drivers but is used by the Sparc driver.
+	 */
+	
+	if (dev->fn_tbl.kernel_context_switch && 
+	    dev->last_context != lock.context) {
+	  dev->fn_tbl.kernel_context_switch(dev, dev->last_context, 
+					    lock.context);
+	}
         DRM_DEBUG( "%d %s\n", lock.context, ret ? "interrupted" : "has lock" );
 
         return ret;
@@ -1169,40 +1041,20 @@
 
 	atomic_inc( &dev->counts[_DRM_STAT_UNLOCKS] );
 
-	/* __HAVE_KERNEL_CTX_SWITCH isn't used by any of the drm
-	 * modules in the DRI cvs tree, but it is required by the
-	 * Sparc driver.
-	 */
-#if __HAVE_KERNEL_CTX_SWITCH
-	/* We no longer really hold it, but if we are the next
-	 * agent to request it then we should just be able to
-	 * take it immediately and not eat the ioctl.
+	/* kernel_context_switch isn't used by any of the x86 drm
+	 * modules but is required by the Sparc driver.
 	 */
-	dev->lock.filp = NULL;
-	{
-		__volatile__ unsigned int *plock = &dev->lock.hw_lock->lock;
-		unsigned int old, new, prev, ctx;
-
-		ctx = lock.context;
-		do {
-			old  = *plock;
-			new  = ctx;
-			prev = cmpxchg(plock, old, new);
-		} while (prev != old);
-	}
-	wake_up_interruptible(&dev->lock.lock_queue);
-#else
-	DRM(lock_transfer)( dev, &dev->lock.hw_lock->lock,
-			    DRM_KERNEL_CONTEXT );
-#if __HAVE_DMA_SCHEDULE
-	DRM(dma_schedule)( dev, 1 );
-#endif
-
-	if ( DRM(lock_free)( dev, &dev->lock.hw_lock->lock,
-			     DRM_KERNEL_CONTEXT ) ) {
-		DRM_ERROR( "\n" );
+	if (dev->fn_tbl.kernel_context_switch_unlock)
+		dev->fn_tbl.kernel_context_switch_unlock(dev, &lock);
+	else {
+		DRM(lock_transfer)( dev, &dev->lock.hw_lock->lock, 
+				    DRM_KERNEL_CONTEXT );
+		
+		if ( DRM(lock_free)( dev, &dev->lock.hw_lock->lock,
+				     DRM_KERNEL_CONTEXT ) ) {
+			DRM_ERROR( "\n" );
+		}
 	}
-#endif /* !__HAVE_KERNEL_CTX_SWITCH */
 
 	unblock_all_signals();
 	return 0;
diff -Nru a/drivers/char/drm/drm_fops.h b/drivers/char/drm/drm_fops.h
--- a/drivers/char/drm/drm_fops.h	2004-10-18 14:56:32 -07:00
+++ b/drivers/char/drm/drm_fops.h	2004-10-18 14:56:32 -07:00
@@ -53,6 +53,7 @@
 {
 	int	     minor = iminor(inode);
 	drm_file_t   *priv;
+	int ret;
 
 	if (filp->f_flags & O_EXCL)   return -EBUSY; /* No exclusive opens */
 	if (!DRM(cpu_valid)())        return -EINVAL;
@@ -72,7 +73,11 @@
 	priv->authenticated = capable(CAP_SYS_ADMIN);
 	priv->lock_count    = 0;
 
-	DRIVER_OPEN_HELPER( priv, dev );
+	if (dev->fn_tbl.open_helper) {
+		ret=dev->fn_tbl.open_helper(dev, priv);
+		if (ret < 0)
+			goto out_free;
+	}
 
 	down(&dev->struct_sem);
 	if (!dev->file_last) {
@@ -104,6 +109,10 @@
 #endif
 
 	return 0;
+out_free:
+	DRM(free)(priv, sizeof(*priv), DRM_MEM_FILES);
+	filp->private_data=NULL;
+	return ret;
 }
 
 /** No-op. */
@@ -130,19 +139,15 @@
 	return 0;
 }
 
-#if !__HAVE_DRIVER_FOPS_POLL
 /** No-op. */
 unsigned int DRM(poll)(struct file *filp, struct poll_table_struct *wait)
 {
 	return 0;
 }
-#endif
 
 
-#if !__HAVE_DRIVER_FOPS_READ
 /** No-op. */
 ssize_t DRM(read)(struct file *filp, char __user *buf, size_t count, loff_t *off)
 {
 	return 0;
 }
-#endif
diff -Nru a/drivers/char/drm/drm_ioctl.h b/drivers/char/drm/drm_ioctl.h
--- a/drivers/char/drm/drm_ioctl.h	2004-10-18 14:56:20 -07:00
+++ b/drivers/char/drm/drm_ioctl.h	2004-10-18 14:56:20 -07:00
@@ -341,9 +341,9 @@
 		if (sv.drm_dd_major != DRIVER_MAJOR ||
 		    sv.drm_dd_minor < 0 || sv.drm_dd_minor > DRIVER_MINOR)
 			return EINVAL;
-#ifdef DRIVER_SETVERSION
-		DRIVER_SETVERSION(dev, &sv);
-#endif
+
+		if (dev->fn_tbl.set_version)
+			dev->fn_tbl.set_version(dev, &sv);
 	}
 	return 0;
 }
diff -Nru a/drivers/char/drm/drm_irq.h b/drivers/char/drm/drm_irq.h
--- a/drivers/char/drm/drm_irq.h	2004-10-18 14:56:33 -07:00
+++ b/drivers/char/drm/drm_irq.h	2004-10-18 14:56:33 -07:00
@@ -37,16 +37,6 @@
 
 #include <linux/interrupt.h>	/* For task queue support */
 
-#ifndef __HAVE_SHARED_IRQ
-#define __HAVE_SHARED_IRQ	0
-#endif
-
-#if __HAVE_SHARED_IRQ
-#define DRM_IRQ_TYPE		SA_SHIRQ
-#else
-#define DRM_IRQ_TYPE		0
-#endif
-
 /**
  * Get interrupt from bus id.
  * 
@@ -68,6 +58,9 @@
 	drm_irq_busid_t __user *argp = (void __user *)arg;
 	drm_irq_busid_t p;
 
+	if (!drm_core_check_feature(dev, DRIVER_HAVE_IRQ))
+		return -EINVAL;
+
 	if (copy_from_user(&p, argp, sizeof(p)))
 		return -EFAULT;
 
@@ -86,8 +79,6 @@
 	return 0;
 }
 
-#if __HAVE_IRQ
-
 /**
  * Install IRQ handler.
  *
@@ -101,7 +92,11 @@
 int DRM(irq_install)( drm_device_t *dev )
 {
 	int ret;
- 
+	unsigned long sh_flags=0;
+
+	if (!drm_core_check_feature(dev, DRIVER_HAVE_IRQ))
+		return -EINVAL;
+
 	if ( dev->irq == 0 )
 		return -EINVAL;
 
@@ -122,32 +117,25 @@
 
 	DRM_DEBUG( "%s: irq=%d\n", __FUNCTION__, dev->irq );
 
-#if __HAVE_DMA
-	dev->dma->next_buffer = NULL;
-	dev->dma->next_queue = NULL;
-	dev->dma->this_buffer = NULL;
-#endif
-
-#ifdef __HAVE_IRQ_BH
-	INIT_WORK(&dev->work, DRM(irq_immediate_bh), dev);
-#endif
-
-#ifdef __HAVE_VBL_IRQ
-	init_waitqueue_head(&dev->vbl_queue);
-
-	spin_lock_init( &dev->vbl_lock );
-
-	INIT_LIST_HEAD( &dev->vbl_sigs.head );
-
-	dev->vbl_pending = 0;
-#endif
+	if (drm_core_check_feature(dev, DRIVER_IRQ_VBL)) {
+		init_waitqueue_head(&dev->vbl_queue);
+		
+		spin_lock_init( &dev->vbl_lock );
+		
+		INIT_LIST_HEAD( &dev->vbl_sigs.head );
+		
+		dev->vbl_pending = 0;
+	}
 
 				/* Before installing handler */
-	DRM(driver_irq_preinstall)(dev);
+	dev->fn_tbl.irq_preinstall(dev);
 
 				/* Install handler */
-	ret = request_irq( dev->irq, DRM(irq_handler),
-			   DRM_IRQ_TYPE, dev->devname, dev );
+	if (drm_core_check_feature(dev, DRIVER_IRQ_SHARED))
+		sh_flags = SA_SHIRQ;
+	
+	ret = request_irq( dev->irq, dev->fn_tbl.irq_handler,
+			   sh_flags, dev->devname, dev );
 	if ( ret < 0 ) {
 		down( &dev->struct_sem );
 		dev->irq_enabled = 0;
@@ -156,7 +144,7 @@
 	}
 
 				/* After installing handler */
-	DRM(driver_irq_postinstall)(dev);
+	dev->fn_tbl.irq_postinstall(dev);
 
 	return 0;
 }
@@ -172,6 +160,9 @@
 {
 	int irq_enabled;
 
+	if (!drm_core_check_feature(dev, DRIVER_HAVE_IRQ))
+		return -EINVAL;
+
 	down( &dev->struct_sem );
 	irq_enabled = dev->irq_enabled;
 	dev->irq_enabled = 0;
@@ -182,7 +173,7 @@
 
 	DRM_DEBUG( "%s: irq=%d\n", __FUNCTION__, dev->irq );
 
-	DRM(driver_irq_uninstall)( dev );
+	dev->fn_tbl.irq_uninstall(dev);
 
 	free_irq( dev->irq, dev );
 
@@ -206,25 +197,29 @@
 	drm_file_t *priv = filp->private_data;
 	drm_device_t *dev = priv->dev;
 	drm_control_t ctl;
+	
+	/* if we haven't irq we fallback for compatibility reasons - this used to be a separate function in drm_dma.h */
 
 	if ( copy_from_user( &ctl, (drm_control_t __user *)arg, sizeof(ctl) ) )
 		return -EFAULT;
 
 	switch ( ctl.func ) {
 	case DRM_INST_HANDLER:
+		if (!drm_core_check_feature(dev, DRIVER_HAVE_IRQ))
+			return 0;
 		if (dev->if_version < DRM_IF_VERSION(1, 2) &&
 		    ctl.irq != dev->irq)
 			return -EINVAL;
 		return DRM(irq_install)( dev );
 	case DRM_UNINST_HANDLER:
+		if (!drm_core_check_feature(dev, DRIVER_HAVE_IRQ))
+			return 0;
 		return DRM(irq_uninstall)( dev );
 	default:
 		return -EINVAL;
 	}
 }
 
-#ifdef __HAVE_VBL_IRQ
-
 /**
  * Wait for VBLANK.
  *
@@ -254,6 +249,9 @@
 	int ret = 0;
 	unsigned int flags;
 
+	if (!drm_core_check_feature(dev, DRIVER_IRQ_VBL))
+		return -EINVAL;
+
 	if (!dev->irq)
 		return -EINVAL;
 
@@ -318,7 +316,8 @@
 
 		spin_unlock_irqrestore( &dev->vbl_lock, irqflags );
 	} else {
-		ret = DRM(vblank_wait)( dev, &vblwait.request.sequence );
+		if (dev->fn_tbl.vblank_wait)
+			ret = dev->fn_tbl.vblank_wait( dev, &vblwait.request.sequence );
 
 		do_gettimeofday( &now );
 		vblwait.reply.tval_sec = now.tv_sec;
@@ -366,6 +365,4 @@
 	spin_unlock_irqrestore( &dev->vbl_lock, flags );
 }
 
-#endif	/* __HAVE_VBL_IRQ */
 
-#endif /* __HAVE_IRQ */
diff -Nru a/drivers/char/drm/drm_memory.h b/drivers/char/drm/drm_memory.h
--- a/drivers/char/drm/drm_memory.h	2004-10-18 14:56:16 -07:00
+++ b/drivers/char/drm/drm_memory.h	2004-10-18 14:56:16 -07:00
@@ -44,7 +44,7 @@
  */
 #define DEBUG_MEMORY 0
 
-#if __REALLY_HAVE_AGP
+#if __OS_HAS_AGP
 
 #include <linux/vmalloc.h>
 
@@ -130,46 +130,56 @@
 	return pte_pfn(*ptep) << PAGE_SHIFT;
 }
 
-#endif /* __REALLY_HAVE_AGP */
+#else /* __OS_HAS_AGP */
+
+static inline drm_map_t *drm_lookup_map(unsigned long offset, unsigned long size, drm_device_t *dev)
+{
+  return NULL;
+}
+
+static inline void *agp_remap(unsigned long offset, unsigned long size, drm_device_t *dev)
+{
+  return NULL;
+}
+
+static inline unsigned long drm_follow_page (void *vaddr)
+{
+  return 0;
+}
+
+#endif
 
 static inline void *drm_ioremap(unsigned long offset, unsigned long size, drm_device_t *dev)
 {
-#if __REALLY_HAVE_AGP
-	if (dev->agp && dev->agp->cant_use_aperture) {
+	if (drm_core_has_AGP(dev) && dev->agp && dev->agp->cant_use_aperture) {
 		drm_map_t *map = drm_lookup_map(offset, size, dev);
 
 		if (map && map->type == _DRM_AGP)
 			return agp_remap(offset, size, dev);
 	}
-#endif
-
 	return ioremap(offset, size);
 }
 
 static inline void *drm_ioremap_nocache(unsigned long offset, unsigned long size,
 					drm_device_t *dev)
 {
-#if __REALLY_HAVE_AGP
-	if (dev->agp && dev->agp->cant_use_aperture) {
+	if (drm_core_has_AGP(dev) && dev->agp && dev->agp->cant_use_aperture) {
 		drm_map_t *map = drm_lookup_map(offset, size, dev);
 
 		if (map && map->type == _DRM_AGP)
 			return agp_remap(offset, size, dev);
 	}
-#endif
-
 	return ioremap_nocache(offset, size);
 }
 
 static inline void drm_ioremapfree(void *pt, unsigned long size, drm_device_t *dev)
 {
-#if __REALLY_HAVE_AGP
 	/*
 	 * This is a bit ugly.  It would be much cleaner if the DRM API would use separate
 	 * routines for handling mappings in the AGP space.  Hopefully this can be done in
 	 * a future revision of the interface...
 	 */
-	if (dev->agp && dev->agp->cant_use_aperture
+	if (drm_core_has_AGP(dev) && dev->agp && dev->agp->cant_use_aperture
 	    && ((unsigned long) pt >= VMALLOC_START && (unsigned long) pt < VMALLOC_END))
 	{
 		unsigned long offset;
@@ -182,11 +192,11 @@
 			return;
 		}
 	}
-#endif
 
 	iounmap(pt);
 }
 
+
 #if DEBUG_MEMORY
 #include "drm_memory_debug.h"
 #else
@@ -331,7 +341,7 @@
 	drm_ioremapfree(pt, size, dev);
 }
 
-#if __REALLY_HAVE_AGP
+#if __OS_HAS_AGP
 /** Wrapper around agp_allocate_memory() */
 DRM_AGP_MEM *DRM(alloc_agp)(int pages, u32 type)
 {
diff -Nru a/drivers/char/drm/drm_memory_debug.h b/drivers/char/drm/drm_memory_debug.h
--- a/drivers/char/drm/drm_memory_debug.h	2004-10-18 14:56:13 -07:00
+++ b/drivers/char/drm/drm_memory_debug.h	2004-10-18 14:56:13 -07:00
@@ -352,7 +352,7 @@
 	}
 }
 
-#if __REALLY_HAVE_AGP
+#if __OS_HAS_AGP
 
 DRM_AGP_MEM *DRM(alloc_agp)(int pages, u32 type)
 {
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-10-18 14:57:03 -07:00
+++ b/drivers/char/drm/drm_os_linux.h	2004-10-18 14:57:03 -07:00
@@ -16,13 +16,17 @@
 #define DRM_CURRENTPID			current->pid
 #define DRM_UDELAY(d)			udelay(d)
 /** Read a byte from a MMIO region */
-#define DRM_READ8(map, offset)		readb(((unsigned long)(map)->handle) + (offset))
+#define DRM_READ8(map, offset)		readb(((void __iomem *)(map)->handle) + (offset))
+/** Read a word from a MMIO region */
+#define DRM_READ16(map, offset)         readw(((void __iomem *)(map)->handle) + (offset))
 /** Read a dword from a MMIO region */
-#define DRM_READ32(map, offset)		readl(((unsigned long)(map)->handle) + (offset))
+#define DRM_READ32(map, offset)		readl(((void __iomem *)(map)->handle) + (offset))
 /** Write a byte into a MMIO region */
-#define DRM_WRITE8(map, offset, val)	writeb(val, ((unsigned long)(map)->handle) + (offset))
+#define DRM_WRITE8(map, offset, val)	writeb(val, ((void __iomem *)(map)->handle) + (offset))
+/** Write a word into a MMIO region */
+#define DRM_WRITE16(map, offset, val)   writew(val, ((void __iomem *)(map)->handle) + (offset))
 /** Write a dword into a MMIO region */
-#define DRM_WRITE32(map, offset, val)	writel(val, ((unsigned long)(map)->handle) + (offset))
+#define DRM_WRITE32(map, offset, val)	writel(val, ((void __iomem *)(map)->handle) + (offset))
 /** Read memory barrier */
 #define DRM_READMEMORYBARRIER()		rmb()
 /** Write memory barrier */
@@ -37,8 +41,34 @@
 #define DRM_IRQ_ARGS		int irq, void *arg, struct pt_regs *regs
 
 /** AGP types */
+#if __OS_HAS_AGP
 #define DRM_AGP_MEM		struct agp_memory
 #define DRM_AGP_KERN		struct agp_kern_info
+#else
+/* define some dummy types for non AGP supporting kernels */
+struct no_agp_kern {
+  unsigned long aper_base;
+  unsigned long aper_size;
+};
+#define DRM_AGP_MEM             int
+#define DRM_AGP_KERN            struct no_agp_kern
+#endif
+
+#if !(__OS_HAS_MTRR)
+static __inline__ int mtrr_add (unsigned long base, unsigned long size,
+                                unsigned int type, char increment)
+{
+	return -ENODEV;
+}
+
+static __inline__ int mtrr_del (int reg, unsigned long base,
+                                unsigned long size)
+{
+	return -ENODEV;
+}
+#define MTRR_TYPE_WRCOMB     1
+
+#endif
 
 /** Task queue handler arguments */
 #define DRM_TASKQUEUE_ARGS	void *arg
@@ -104,7 +134,7 @@
 	add_wait_queue(&(queue), &entry);			\
 								\
 	for (;;) {						\
-		current->state = TASK_INTERRUPTIBLE;		\
+		__set_current_state(TASK_INTERRUPTIBLE);	\
 		if (condition)					\
 			break;					\
 		if (time_after_eq(jiffies, end)) {		\
@@ -117,7 +147,7 @@
 			break;					\
 		}						\
 	}							\
-	current->state = TASK_RUNNING;				\
+	__set_current_state(TASK_RUNNING);			\
 	remove_wait_queue(&(queue), &entry);			\
 } while (0)
 
diff -Nru a/drivers/char/drm/drm_pciids.h b/drivers/char/drm/drm_pciids.h
--- a/drivers/char/drm/drm_pciids.h	2004-10-18 14:56:29 -07:00
+++ b/drivers/char/drm/drm_pciids.h	2004-10-18 14:56:29 -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/drm_scatter.h b/drivers/char/drm/drm_scatter.h
--- a/drivers/char/drm/drm_scatter.h	2004-10-18 14:56:33 -07:00
+++ b/drivers/char/drm/drm_scatter.h	2004-10-18 14:56:33 -07:00
@@ -73,6 +73,9 @@
 
 	DRM_DEBUG( "%s\n", __FUNCTION__ );
 
+	if (!drm_core_check_feature(dev, DRIVER_SG))
+		return -EINVAL;
+
 	if ( dev->sg )
 		return -EINVAL;
 
@@ -205,6 +208,9 @@
 	drm_device_t *dev = priv->dev;
 	drm_scatter_gather_t request;
 	drm_sg_mem_t *entry;
+
+	if (!drm_core_check_feature(dev, DRIVER_SG))
+		return -EINVAL;
 
 	if ( copy_from_user( &request,
 			     (drm_scatter_gather_t __user *)arg,
diff -Nru a/drivers/char/drm/drm_vm.h b/drivers/char/drm/drm_vm.h
--- a/drivers/char/drm/drm_vm.h	2004-10-18 14:57:05 -07:00
+++ b/drivers/char/drm/drm_vm.h	2004-10-18 14:57:05 -07:00
@@ -46,10 +46,10 @@
  * Find the right map and if it's AGP memory find the real physical page to
  * map, get the page, increment the use count and return it.
  */
+#if __OS_HAS_AGP
 static __inline__ struct page *DRM(do_vm_nopage)(struct vm_area_struct *vma,
 						 unsigned long address)
 {
-#if __REALLY_HAVE_AGP
 	drm_file_t *priv  = vma->vm_file->private_data;
 	drm_device_t *dev = priv->dev;
 	drm_map_t *map    = NULL;
@@ -59,6 +59,8 @@
 	/*
          * Find the right map
          */
+	if (!drm_core_has_AGP(dev))
+		goto vm_nopage_error;
 
 	if(!dev->agp || !dev->agp->cant_use_aperture) goto vm_nopage_error;
 
@@ -107,10 +109,15 @@
 		return page;
         }
 vm_nopage_error:
-#endif /* __REALLY_HAVE_AGP */
-
 	return NOPAGE_SIGBUS;		/* Disallow mremap */
 }
+#else /* __OS_HAS_AGP */
+static __inline__ struct page *DRM(do_vm_nopage)(struct vm_area_struct *vma,
+						 unsigned long address)
+{
+	return NOPAGE_SIGBUS;
+}
+#endif /* __OS_HAS_AGP */
 
 /**
  * \c nopage method for shared virtual memory.
@@ -201,15 +208,13 @@
 			switch (map->type) {
 			case _DRM_REGISTERS:
 			case _DRM_FRAME_BUFFER:
-#if __REALLY_HAVE_MTRR
-				if (map->mtrr >= 0) {
+				if (drm_core_has_MTRR(dev) && map->mtrr >= 0) {
 					int retcode;
 					retcode = mtrr_del(map->mtrr,
 							   map->offset,
 							   map->size);
 					DRM_DEBUG("mtrr_del = %d\n", retcode);
 				}
-#endif
 				DRM(ioremapfree)(map->handle, map->size, dev);
 				break;
 			case _DRM_SHM:
@@ -488,18 +493,19 @@
 	return 0;
 }
 
-#ifndef DRIVER_GET_MAP_OFS
-#define DRIVER_GET_MAP_OFS()	(map->offset)
-#endif
+unsigned long DRM(core_get_map_ofs)(drm_map_t *map)
+{
+	return map->offset;
+}
 
-#ifndef DRIVER_GET_REG_OFS
+unsigned long DRM(core_get_reg_ofs)(struct drm_device *dev)
+{
 #ifdef __alpha__
-#define DRIVER_GET_REG_OFS()	(dev->hose->dense_mem_base -	\
-				 dev->hose->mem_space->start)
+	return dev->hose->dense_mem_base - dev->hose->mem_space->start;
 #else
-#define DRIVER_GET_REG_OFS()	0
-#endif
+	return 0;
 #endif
+}
 
 /**
  * mmap DMA memory.
@@ -533,7 +539,7 @@
 	 * --BenH.
 	 */
 	if (!VM_OFFSET(vma)
-#if __REALLY_HAVE_AGP
+#if __OS_HAS_AGP
 	    && (!dev->agp || dev->agp->agp_info.device->vendor != PCI_VENDOR_ID_APPLE)
 #endif
 	    )
@@ -552,7 +558,7 @@
 		r_list = list_entry(list, drm_map_list_t, head);
 		map = r_list->map;
 		if (!map) continue;
-		off = DRIVER_GET_MAP_OFS();
+		off = dev->fn_tbl.get_map_ofs(map);
 		if (off == VM_OFFSET(vma)) break;
 	}
 
@@ -577,8 +583,7 @@
 
 	switch (map->type) {
         case _DRM_AGP:
-#if __REALLY_HAVE_AGP
-	  if (dev->agp->cant_use_aperture) {
+	  if (drm_core_has_AGP(dev) && dev->agp->cant_use_aperture) {
                 /*
                  * On some platforms we can't talk to bus dma address from the CPU, so for
                  * memory of type DRM_AGP, we'll deal with sorting out the real physical
@@ -590,7 +595,6 @@
                 vma->vm_ops = &DRM(vm_ops);
                 break;
 	  }
-#endif
                 /* fall through to _DRM_FRAME_BUFFER... */        
 	case _DRM_FRAME_BUFFER:
 	case _DRM_REGISTERS:
@@ -609,7 +613,7 @@
 		if (map->type != _DRM_AGP)
 			vma->vm_page_prot = pgprot_writecombine(vma->vm_page_prot);
 #endif
-		offset = DRIVER_GET_REG_OFS();
+		offset = dev->fn_tbl.get_reg_ofs(dev);
 #ifdef __sparc__
 		if (io_remap_page_range(DRM_RPR_ARG(vma) vma->vm_start,
 					VM_OFFSET(vma) + offset,
diff -Nru a/drivers/char/drm/ffb.h b/drivers/char/drm/ffb.h
--- a/drivers/char/drm/ffb.h	2004-10-18 14:56:33 -07:00
+++ b/drivers/char/drm/ffb.h	2004-10-18 14:56:33 -07:00
@@ -8,9 +8,5 @@
  */
 #define DRM(x) ffb_##x
 
-/* General customization:
- */
-#define __HAVE_KERNEL_CTX_SWITCH	1
-#define __HAVE_RELEASE			1
 #endif
 
diff -Nru a/drivers/char/drm/ffb_context.c b/drivers/char/drm/ffb_context.c
--- a/drivers/char/drm/ffb_context.c	2004-10-18 14:56:33 -07:00
+++ b/drivers/char/drm/ffb_context.c	2004-10-18 14:56:33 -07:00
@@ -354,7 +354,7 @@
 	} while (--limit);
 }
 
-int DRM(context_switch)(drm_device_t *dev, int old, int new)
+int ffb_driver_context_switch(drm_device_t *dev, int old, int new)
 {
 	ffb_dev_priv_t *fpriv = (ffb_dev_priv_t *) dev->dev_private;
 
@@ -380,7 +380,7 @@
         return 0;
 }
 
-int DRM(resctx)(struct inode *inode, struct file *filp, unsigned int cmd,
+int ffb_driver_resctx(struct inode *inode, struct file *filp, unsigned int cmd,
 		unsigned long arg)
 {
 	drm_ctx_res_t	res;
@@ -407,7 +407,7 @@
 }
 
 
-int DRM(addctx)(struct inode *inode, struct file *filp, unsigned int cmd,
+int ffb_driver_addctx(struct inode *inode, struct file *filp, unsigned int cmd,
 		unsigned long arg)
 {
 	drm_file_t	*priv	= filp->private_data;
@@ -428,7 +428,7 @@
 	return 0;
 }
 
-int DRM(modctx)(struct inode *inode, struct file *filp, unsigned int cmd,
+int ffb_driver_modctx(struct inode *inode, struct file *filp, unsigned int cmd,
 		unsigned long arg)
 {
 	drm_file_t	*priv	= filp->private_data;
@@ -457,7 +457,7 @@
 	return 0;
 }
 
-int DRM(getctx)(struct inode *inode, struct file *filp, unsigned int cmd,
+int ffb_driver_getctx(struct inode *inode, struct file *filp, unsigned int cmd,
 		unsigned long arg)
 {
 	drm_file_t	*priv	= filp->private_data;
@@ -489,7 +489,7 @@
 	return 0;
 }
 
-int DRM(switchctx)(struct inode *inode, struct file *filp, unsigned int cmd,
+int ffb_driver_switchctx(struct inode *inode, struct file *filp, unsigned int cmd,
 		   unsigned long arg)
 {
 	drm_file_t	*priv	= filp->private_data;
@@ -499,10 +499,10 @@
 	if (copy_from_user(&ctx, (drm_ctx_t  __user *)arg, sizeof(ctx)))
 		return -EFAULT;
 	DRM_DEBUG("%d\n", ctx.handle);
-	return DRM(context_switch)(dev, dev->last_context, ctx.handle);
+	return ffb_driver_context_switch(dev, dev->last_context, ctx.handle);
 }
 
-int DRM(newctx)(struct inode *inode, struct file *filp, unsigned int cmd,
+int ffb_driver_newctx(struct inode *inode, struct file *filp, unsigned int cmd,
 		unsigned long arg)
 {
 	drm_ctx_t	ctx;
@@ -514,7 +514,7 @@
 	return 0;
 }
 
-int DRM(rmctx)(struct inode *inode, struct file *filp, unsigned int cmd,
+int ffb_driver_rmctx(struct inode *inode, struct file *filp, unsigned int cmd,
 	       unsigned long arg)
 {
 	drm_ctx_t	ctx;
@@ -536,4 +536,16 @@
 		fpriv->hw_state[idx] = NULL;
 	}
 	return 0;
+}
+
+void ffb_set_context_ioctls(void)
+{
+	DRM(ioctls)[DRM_IOCTL_NR(DRM_IOCTL_ADD_CTX)].func = ffb_driver_addctx;
+	DRM(ioctls)[DRM_IOCTL_NR(DRM_IOCTL_RM_CTX)].func = ffb_driver_rmctx;
+	DRM(ioctls)[DRM_IOCTL_NR(DRM_IOCTL_MOD_CTX)].func = ffb_driver_modctx;
+	DRM(ioctls)[DRM_IOCTL_NR(DRM_IOCTL_GET_CTX)].func = ffb_driver_getctx;
+	DRM(ioctls)[DRM_IOCTL_NR(DRM_IOCTL_SWITCH_CTX)].func = ffb_driver_switchctx;
+	DRM(ioctls)[DRM_IOCTL_NR(DRM_IOCTL_NEW_CTX)].func = ffb_driver_newctx;
+	DRM(ioctls)[DRM_IOCTL_NR(DRM_IOCTL_RES_CTX)].func = ffb_driver_resctx;
+
 }
diff -Nru a/drivers/char/drm/ffb_drv.c b/drivers/char/drm/ffb_drv.c
--- a/drivers/char/drm/ffb_drv.c	2004-10-18 14:57:05 -07:00
+++ b/drivers/char/drm/ffb_drv.c	2004-10-18 14:57:05 -07:00
@@ -26,58 +26,6 @@
 #define DRIVER_MINOR		0
 #define DRIVER_PATCHLEVEL	1
 
-#define DRIVER_FOPS						\
-static struct file_operations	DRM(fops) = {			\
-	.owner   		= THIS_MODULE,			\
-	.open	 		= DRM(open),			\
-	.flush	 		= DRM(flush),			\
-	.release 		= DRM(release),			\
-	.ioctl	 		= DRM(ioctl),			\
-	.mmap	 		= DRM(mmap),			\
-	.read	 		= DRM(read),			\
-	.fasync	 		= DRM(fasync),			\
-	.poll	 		= DRM(poll),			\
-	.get_unmapped_area	= ffb_get_unmapped_area,		\
-}
-
-#define DRIVER_COUNT_CARDS()	ffb_count_card_instances()
-/* Allocate private structure and fill it */
-#define DRIVER_PRESETUP()	do {		\
-	int _ret;				\
-	_ret = ffb_presetup(dev);		\
-	if (_ret != 0) return _ret;		\
-} while(0)
-
-/* Free private structure */
-#define DRIVER_PRETAKEDOWN()	do {				\
-	if (dev->dev_private) kfree(dev->dev_private);		\
-} while(0)
-
-#define DRIVER_POSTCLEANUP()	do {				\
-	if (ffb_position != NULL) kfree(ffb_position);		\
-} while(0)
-
-/* We have to free up the rogue hw context state holding error or 
- * else we will leak it.
- */
-#define DRIVER_RELEASE()	do {					\
-	ffb_dev_priv_t *fpriv = (ffb_dev_priv_t *) dev->dev_private;	\
-	int context = _DRM_LOCKING_CONTEXT(dev->lock.hw_lock->lock);	\
-	int idx;							\
-									\
-	idx = context - 1;						\
-	if (fpriv &&							\
-	    context != DRM_KERNEL_CONTEXT &&				\
-	    fpriv->hw_state[idx] != NULL) {				\
-		kfree(fpriv->hw_state[idx]);				\
-		fpriv->hw_state[idx] = NULL;				\
-	}								\
-} while(0)
-
-/* For mmap customization */
-#define DRIVER_GET_MAP_OFS()	(map->offset & 0xffffffff)
-#define DRIVER_GET_REG_OFS()	ffb_get_reg_offset(dev)
-
 typedef struct _ffb_position_t {
 	int node;
 	int root;
@@ -192,63 +140,6 @@
 	return 0;
 }
 
-static int __init ffb_count_siblings(int root)
-{
-	int node, child, count = 0;
-
-	child = prom_getchild(root);
-	for (node = prom_searchsiblings(child, "SUNW,ffb"); node;
-	     node = prom_searchsiblings(prom_getsibling(node), "SUNW,ffb"))
-		count++;
-
-	return count;
-}
-
-static int __init ffb_scan_siblings(int root, int instance)
-{
-	int node, child;
-
-	child = prom_getchild(root);
-	for (node = prom_searchsiblings(child, "SUNW,ffb"); node;
-	     node = prom_searchsiblings(prom_getsibling(node), "SUNW,ffb")) {
-		ffb_position[instance].node = node;
-		ffb_position[instance].root = root;
-		instance++;
-	}
-
-	return instance;
-}
-
-static int ffb_presetup(drm_device_t *);
-
-static int __init ffb_count_card_instances(void)
-{
-	int root, total, instance;
-
-	total = ffb_count_siblings(prom_root_node);
-	root = prom_getchild(prom_root_node);
-	for (root = prom_searchsiblings(root, "upa"); root;
-	     root = prom_searchsiblings(prom_getsibling(root), "upa"))
-		total += ffb_count_siblings(root);
-
-	ffb_position = kmalloc(sizeof(ffb_position_t) * total, GFP_KERNEL);
-
-	/* Actual failure will be caught during ffb_presetup b/c we can't catch
-	 * it easily here.
-	 */
-	if (!ffb_position)
-		return -ENOMEM;
-
-	instance = ffb_scan_siblings(prom_root_node, 0);
-
-	root = prom_getchild(prom_root_node);
-	for (root = prom_searchsiblings(root, "upa"); root;
-	     root = prom_searchsiblings(prom_getsibling(root), "upa"))
-		instance = ffb_scan_siblings(root, instance);
-
-	return total;
-}
-
 static drm_map_t *ffb_find_map(struct file *filp, unsigned long off)
 {
 	drm_file_t	*priv	= filp->private_data;
@@ -275,11 +166,11 @@
 	return NULL;
 }
 
-static unsigned long ffb_get_unmapped_area(struct file *filp,
-					   unsigned long hint,
-					   unsigned long len,
-					   unsigned long pgoff,
-					   unsigned long flags)
+unsigned long ffb_get_unmapped_area(struct file *filp,
+				    unsigned long hint,
+				    unsigned long len,
+				    unsigned long pgoff,
+				    unsigned long flags)
 {
 	drm_map_t *map = ffb_find_map(filp, pgoff << PAGE_SHIFT);
 	unsigned long addr = -ENOMEM;
@@ -319,21 +210,7 @@
 	return addr;
 }
 
-static unsigned long ffb_get_reg_offset(drm_device_t *dev)
-{
-	ffb_dev_priv_t *ffb_priv = (ffb_dev_priv_t *)dev->dev_private;
-
-	if (ffb_priv)
-		return ffb_priv->card_phys_base;
-
-	return 0;
-}
-
-#include "drm_auth.h"
-#include "drm_bufs.h"
-#include "drm_dma.h"
-#include "drm_drawable.h"
-#include "drm_drv.h"
+#include "drm_core.h"
 
 /* This functions must be here since it references DRM(numdevs)
  * which drm_drv.h declares.
@@ -372,11 +249,74 @@
 	return ret;
 }
 
-#include "drm_fops.h"
-#include "drm_init.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"
+static void ffb_driver_release(drm_device_t *dev, struct file *filp)
+{
+	ffb_dev_priv_t *fpriv = (ffb_dev_priv_t *) dev->dev_private;
+	int context = _DRM_LOCKING_CONTEXT(dev->lock.hw_lock->lock);
+	int idx;
+
+	idx = context - 1;
+	if (fpriv &&
+	    context != DRM_KERNEL_CONTEXT &&
+	    fpriv->hw_state[idx] != NULL) {
+		kfree(fpriv->hw_state[idx]);
+		fpriv->hw_state[idx] = NULL;
+	}	
+}
+
+static void ffb_driver_pretakedown(drm_device_t *dev)
+{
+	if (dev->dev_private) kfree(dev->dev_private);
+}
+
+static int ffb_driver_postcleanup(drm_device_t *dev)
+{
+	if (ffb_position != NULL) kfree(ffb_position);
+	return 0;
+}
+
+static void ffb_driver_kernel_context_switch_unlock(struct drm_device *dev, drm_lock_t *lock)
+{
+	dev->lock.filp = 0;
+	{
+		__volatile__ unsigned int *plock = &dev->lock.hw_lock->lock;
+		unsigned int old, new, prev, ctx;
+		
+		ctx = lock->context;
+		do {
+			old  = *plock;
+			new  = ctx;
+			prev = cmpxchg(plock, old, new);
+		} while (prev != old);
+	}
+	wake_up_interruptible(&dev->lock.lock_queue);
+}
+
+static unsigned long ffb_driver_get_map_ofs(drm_map_t *map)
+{
+	return (map->offset & 0xffffffff);
+}
+
+static unsigned long ffb_driver_get_reg_ofs(drm_device_t *dev)
+{
+       ffb_dev_priv_t *ffb_priv = (ffb_dev_priv_t *)dev->dev_private;
+       
+       if (ffb_priv)
+               return ffb_priv->card_phys_base;
+       
+       return 0;
+}
+
+void ffb_driver_register_fns(drm_device_t *dev)
+{
+	ffb_set_context_ioctls();
+	DRM(fops).get_unmapped_area = ffb_get_unmapped_area;
+	dev->fn_tbl.release = ffb_driver_release;
+	dev->fn_tbl.presetup = ffb_presetup;
+	dev->fn_tbl.pretakedown = ffb_driver_pretakedown;
+	dev->fn_tbl.postcleanup = ffb_driver_postcleanup;
+	dev->fn_tbl.kernel_context_switch = ffb_context_switch;
+	dev->fn_tbl.kernel_context_switch_unlock = ffb_driver_kernel_context_switch_unlock;
+	dev->fn_tbl.get_map_ofs = ffb_driver_get_map_ofs;
+	dev->fn_tbl.get_reg_ofs = ffb_driver_get_reg_ofs;
+}
diff -Nru a/drivers/char/drm/ffb_drv.h b/drivers/char/drm/ffb_drv.h
--- a/drivers/char/drm/ffb_drv.h	2004-10-18 14:56:17 -07:00
+++ b/drivers/char/drm/ffb_drv.h	2004-10-18 14:56:17 -07:00
@@ -274,3 +274,13 @@
 	/* Context table. */
 	struct ffb_hw_context	*hw_state[FFB_MAX_CTXS];
 } ffb_dev_priv_t;
+
+extern struct file_operations DRM(fops);
+extern unsigned long ffb_get_unmapped_area(struct file *filp,
+					   unsigned long hint,
+					   unsigned long len,
+					   unsigned long pgoff,
+					   unsigned long flags);
+extern void ffb_set_context_ioctls(void);
+extern drm_ioctl_desc_t DRM(ioctls)[];
+
diff -Nru a/drivers/char/drm/gamma.h b/drivers/char/drm/gamma.h
--- a/drivers/char/drm/gamma.h	2004-10-18 14:55:53 -07:00
+++ b/drivers/char/drm/gamma.h	2004-10-18 14:55:53 -07:00
@@ -36,8 +36,6 @@
 
 /* General customization:
  */
-#define __HAVE_MTRR			1
-
 #define DRIVER_AUTHOR		"VA Linux Systems Inc."
 
 #define DRIVER_NAME		"gamma"
@@ -71,44 +69,9 @@
 
 /* DMA customization:
  */
-#define __HAVE_DMA			1
-#define __HAVE_AGP			1
-#define __MUST_HAVE_AGP			0
-#define __HAVE_OLD_DMA			1
-#define __HAVE_PCI_DMA			1
-
-#define __HAVE_DRIVER_FOPS_READ		1
-#define __HAVE_DRIVER_FOPS_POLL		1
-
 #define __HAVE_MULTIPLE_DMA_QUEUES	1
 #define __HAVE_DMA_WAITQUEUE		1
 
-#define __HAVE_DMA_WAITLIST		1
-#define __HAVE_DMA_FREELIST		1
-
-#define __HAVE_DMA_FLUSH		1
-#define __HAVE_DMA_SCHEDULE		1
-
-#define __HAVE_DMA_READY		1
-#define DRIVER_DMA_READY() do {						\
-	gamma_dma_ready(dev);						\
-} while (0)
-
-#define __HAVE_DMA_QUIESCENT		1
-#define DRIVER_DMA_QUIESCENT() do {					\
-	drm_gamma_private_t *dev_priv =					\
-		(drm_gamma_private_t *)dev->dev_private;		\
-	if (dev_priv->num_rast == 2)					\
-		gamma_dma_quiescent_dual(dev);				\
-	else gamma_dma_quiescent_single(dev);				\
-	return 0;							\
-} while (0)
-
-#define __HAVE_IRQ			1
-#define __HAVE_IRQ_BH			1
-
-#define DRIVER_AGP_BUFFERS_MAP( dev )					\
-	((drm_gamma_private_t *)((dev)->dev_private))->buffers
-
+/* removed from DRM HAVE_DMA_FREELIST & HAVE_DMA_SCHEDULE */
 
 #endif /* __GAMMA_H__ */
diff -Nru a/drivers/char/drm/gamma_context.h b/drivers/char/drm/gamma_context.h
--- a/drivers/char/drm/gamma_context.h	2004-10-18 14:56:28 -07:00
+++ b/drivers/char/drm/gamma_context.h	2004-10-18 14:56:28 -07:00
@@ -42,7 +42,7 @@
    the circular buffer), is based on Alessandro Rubini's LINUX DEVICE
    DRIVERS (Cambridge: O'Reilly, 1998), pages 111-113. */
 
-ssize_t DRM(read)(struct file *filp, char __user *buf, size_t count, loff_t *off)
+ssize_t gamma_fops_read(struct file *filp, char __user *buf, size_t count, loff_t *off)
 {
 	drm_file_t    *priv   = filp->private_data;
 	drm_device_t  *dev    = priv->dev;
@@ -128,7 +128,7 @@
 	return 0;
 }
 
-unsigned int DRM(poll)(struct file *filp, struct poll_table_struct *wait)
+unsigned int gamma_fops_poll(struct file *filp, struct poll_table_struct *wait)
 {
 	drm_file_t   *priv = filp->private_data;
 	drm_device_t *dev  = priv->dev;
diff -Nru a/drivers/char/drm/gamma_dma.c b/drivers/char/drm/gamma_dma.c
--- a/drivers/char/drm/gamma_dma.c	2004-10-18 14:57:03 -07:00
+++ b/drivers/char/drm/gamma_dma.c	2004-10-18 14:57:03 -07:00
@@ -116,7 +116,7 @@
 	return (!GAMMA_READ(GAMMA_DMACOUNT));
 }
 
-irqreturn_t gamma_irq_handler( DRM_IRQ_ARGS )
+irqreturn_t gamma_driver_irq_handler( DRM_IRQ_ARGS )
 {
 	drm_device_t	 *dev = (drm_device_t *)arg;
 	drm_device_dma_t *dma = dev->dma;
@@ -639,12 +639,12 @@
  			break;
  		}
  	}
-
-	DRM_FIND_MAP( dev_priv->mmio0, init->mmio0 );
-	DRM_FIND_MAP( dev_priv->mmio1, init->mmio1 );
-	DRM_FIND_MAP( dev_priv->mmio2, init->mmio2 );
-	DRM_FIND_MAP( dev_priv->mmio3, init->mmio3 );
-
+	
+	dev_priv->mmio0 = drm_core_findmap(dev, init->mmio0);
+	dev_priv->mmio1 = drm_core_findmap(dev, init->mmio1);
+	dev_priv->mmio2 = drm_core_findmap(dev, init->mmio2);
+	dev_priv->mmio3 = drm_core_findmap(dev, init->mmio3);
+	
 	dev_priv->sarea_priv = (drm_gamma_sarea_t *)
 		((u8 *)dev_priv->sarea->handle +
 		 init->sarea_priv_offset);
@@ -661,9 +661,8 @@
 
 		buf = dma->buflist[GLINT_DRI_BUF_COUNT];
 	} else {
-		DRM_FIND_MAP( dev_priv->buffers, init->buffers_offset );
-
-		DRM_IOREMAP( dev_priv->buffers, dev );
+		dev->agp_buffer_map = drm_core_findmap(dev, init->buffers_offset);
+		drm_core_ioremap( dev->agp_buffer_map, dev);
 
 		buf = dma->buflist[GLINT_DRI_BUF_COUNT];
 		pgt = buf->address;
@@ -690,19 +689,18 @@
 {
 	DRM_DEBUG( "%s\n", __FUNCTION__ );
 
-#if __HAVE_IRQ
 	/* 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_enabled ) DRM(irq_uninstall)(dev);
-#endif
+	if (drm_core_check_feature(dev, DRIVER_HAVE_IRQ))
+		if ( dev->irq_enabled ) 
+			DRM(irq_uninstall)(dev);
 
 	if ( dev->dev_private ) {
-		drm_gamma_private_t *dev_priv = dev->dev_private;
 
-		if ( dev_priv->buffers != NULL )
-			DRM_IOREMAPFREE( dev_priv->buffers, dev );
+		if ( dev->agp_buffer_map != NULL )
+			drm_core_ioremapfree( dev->agp_buffer_map, dev );
 
 		DRM(free)( dev->dev_private, sizeof(drm_gamma_private_t),
 			   DRM_MEM_DRIVER );
@@ -868,7 +866,7 @@
 	return 0;
 }
 
-void DRM(driver_irq_preinstall)( drm_device_t *dev ) {
+void gamma_driver_irq_preinstall( drm_device_t *dev ) {
 	drm_gamma_private_t *dev_priv =
 				(drm_gamma_private_t *)dev->dev_private;
 
@@ -879,7 +877,7 @@
 	GAMMA_WRITE( GAMMA_GDMACONTROL,		0x00000000 );
 }
 
-void DRM(driver_irq_postinstall)( drm_device_t *dev ) {
+void gamma_driver_irq_postinstall( drm_device_t *dev ) {
 	drm_gamma_private_t *dev_priv =
 				(drm_gamma_private_t *)dev->dev_private;
 
@@ -891,7 +889,7 @@
 	GAMMA_WRITE( GAMMA_GDELAYTIMER,		0x00039090 );
 }
 
-void DRM(driver_irq_uninstall)( drm_device_t *dev ) {
+void gamma_driver_irq_uninstall( drm_device_t *dev ) {
 	drm_gamma_private_t *dev_priv =
 				(drm_gamma_private_t *)dev->dev_private;
 	if (!dev_priv)
@@ -903,4 +901,46 @@
 	GAMMA_WRITE( GAMMA_GDELAYTIMER,		0x00000000 );
 	GAMMA_WRITE( GAMMA_COMMANDINTENABLE,	0x00000000 );
 	GAMMA_WRITE( GAMMA_GINTENABLE,		0x00000000 );
+}
+
+extern drm_ioctl_desc_t DRM(ioctls)[];
+
+static int gamma_driver_preinit(drm_device_t *dev)
+{
+	/* reset the finish ioctl */
+	DRM(ioctls)[DRM_IOCTL_NR(DRM_IOCTL_FINISH)].func = DRM(finish);
+	return 0;
+}
+
+static void gamma_driver_pretakedown(drm_device_t *dev)
+{
+	gamma_do_cleanup_dma(dev);
+}
+
+static void gamma_driver_dma_ready(drm_device_t *dev)
+{
+	gamma_dma_ready(dev);
+}
+
+static int gamma_driver_dma_quiescent(drm_device_t *dev)
+{
+	drm_gamma_private_t *dev_priv =	(
+		drm_gamma_private_t *)dev->dev_private;
+	if (dev_priv->num_rast == 2)
+		gamma_dma_quiescent_dual(dev);
+	else gamma_dma_quiescent_single(dev);
+	return 0;
+}
+
+void gamma_driver_register_fns(drm_device_t *dev)
+{
+	dev->driver_features = DRIVER_USE_AGP | DRIVER_USE_MTRR | DRIVER_PCI_DMA | DRIVER_HAVE_DMA | DRIVER_HAVE_IRQ;
+	DRM(fops).read = gamma_fops_read;
+	DRM(fops).poll = gamma_fops_poll;
+	dev->fn_tbl.preinit = gamma_driver_preinit;
+	dev->fn_tbl.pretakedown = gamma_driver_pretakedown;
+	dev->fn_tbl.dma_ready = gamma_driver_dma_ready;
+	dev->fn_tbl.dma_quiescent = gamma_driver_dma_quiescent;
+	dev->fn_tbl.dma_flush_block_and_flush = gamma_flush_block_and_flush;
+	dev->fn_tbl.dma_flush_unblock = gamma_flush_unblock;
 }
diff -Nru a/drivers/char/drm/gamma_drv.c b/drivers/char/drm/gamma_drv.c
--- a/drivers/char/drm/gamma_drv.c	2004-10-18 14:57:03 -07:00
+++ b/drivers/char/drm/gamma_drv.c	2004-10-18 14:57:03 -07:00
@@ -56,3 +56,4 @@
 #include "drm_proc.h"
 #include "drm_vm.h"
 #include "drm_stub.h"
+#include "drm_scatter.h"
diff -Nru a/drivers/char/drm/gamma_drv.h b/drivers/char/drm/gamma_drv.h
--- a/drivers/char/drm/gamma_drv.h	2004-10-18 14:56:29 -07:00
+++ b/drivers/char/drm/gamma_drv.h	2004-10-18 14:56:29 -07:00
@@ -35,7 +35,6 @@
 typedef struct drm_gamma_private {
 	drm_gamma_sarea_t *sarea_priv;
 	drm_map_t *sarea;
-	drm_map_t *buffers;
 	drm_map_t *mmio0;
 	drm_map_t *mmio1;
 	drm_map_t *mmio2;
@@ -91,6 +90,10 @@
 				       drm_buf_t *buf);
 extern drm_buf_t     *DRM(freelist_get)(drm_freelist_t *bl, int block);
 
+/* externs for gamma changes to the ops */
+extern struct file_operations DRM(fops);
+extern unsigned int gamma_fops_poll(struct file *filp, struct poll_table_struct *wait);
+extern ssize_t gamma_fops_read(struct file *filp, char __user *buf, size_t count, loff_t *off);
 
 
 #define GLINT_DRI_BUF_COUNT 256
diff -Nru a/drivers/char/drm/i810.h b/drivers/char/drm/i810.h
--- a/drivers/char/drm/i810.h	2004-10-18 14:56:28 -07:00
+++ b/drivers/char/drm/i810.h	2004-10-18 14:56:28 -07:00
@@ -36,10 +36,6 @@
 
 /* General customization:
  */
-#define __HAVE_AGP		1
-#define __MUST_HAVE_AGP		1
-#define __HAVE_MTRR		1
-#define __HAVE_CTX_BITMAP	1
 
 #define DRIVER_AUTHOR		"VA Linux Systems Inc."
 
@@ -77,48 +73,5 @@
 	[DRM_IOCTL_NR(DRM_IOCTL_I810_MC)]      = { i810_dma_mc,     1, 1 }, \
 	[DRM_IOCTL_NR(DRM_IOCTL_I810_RSTATUS)] = { i810_rstatus,    1, 0 }, \
 	[DRM_IOCTL_NR(DRM_IOCTL_I810_FLIP)] =    { i810_flip_bufs,  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 __HAVE_RELEASE		1
-#define DRIVER_RELEASE() do {						\
-	i810_reclaim_buffers( filp );					\
-} while (0)
-
-#define DRIVER_PRETAKEDOWN() do {					\
-	i810_dma_cleanup( dev );					\
-} while (0)
-
-/* DMA customization:
- */
-#define __HAVE_DMA		1
-#define __HAVE_DMA_QUEUE	1
-#define __HAVE_DMA_WAITLIST	0
-#define __HAVE_DMA_RECLAIM	1
-
-#define __HAVE_DMA_QUIESCENT	1
-#define DRIVER_DMA_QUIESCENT() do {					\
-	i810_dma_quiescent( dev );					\
-} while (0)
-
-/* Don't need an irq any more.  The template code will make sure that
- * a noop stub is generated for compatibility.
- */
-/* XXX: Add vblank support? */
-#define __HAVE_IRQ		0
-
-/* Buffer customization:
- */
-
-#define DRIVER_BUF_PRIV_T	drm_i810_buf_priv_t
-
-#define DRIVER_AGP_BUFFERS_MAP( dev )					\
-	((drm_i810_private_t *)((dev)->dev_private))->buffer_map
 
 #endif
diff -Nru a/drivers/char/drm/i810_dma.c b/drivers/char/drm/i810_dma.c
--- a/drivers/char/drm/i810_dma.c	2004-10-18 14:56:28 -07:00
+++ b/drivers/char/drm/i810_dma.c	2004-10-18 14:56:28 -07:00
@@ -232,13 +232,12 @@
 {
 	drm_device_dma_t *dma = dev->dma;
 
-#if __HAVE_IRQ
 	/* 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_enabled ) DRM(irq_uninstall)(dev);
-#endif
+	if (drm_core_check_feature(dev, DRIVER_HAVE_IRQ) && dev->irq_enabled)
+		DRM(irq_uninstall)(dev);
 
 	if (dev->dev_private) {
 		int i;
@@ -364,15 +363,15 @@
 	   	DRM_ERROR("can not find sarea!\n");
 	   	return -EINVAL;
 	}
-	DRM_FIND_MAP( dev_priv->mmio_map, init->mmio_offset );
+	dev_priv->mmio_map = drm_core_findmap(dev, init->mmio_offset);
 	if (!dev_priv->mmio_map) {
 		dev->dev_private = (void *)dev_priv;
 	   	i810_dma_cleanup(dev);
 	   	DRM_ERROR("can not find mmio map!\n");
 	   	return -EINVAL;
 	}
-	DRM_FIND_MAP( dev_priv->buffer_map, init->buffers_offset );
-	if (!dev_priv->buffer_map) {
+	dev->agp_buffer_map = drm_core_findmap(dev, init->buffers_offset);
+	if (!dev->agp_buffer_map) {
 		dev->dev_private = (void *)dev_priv;
 	   	i810_dma_cleanup(dev);
 	   	DRM_ERROR("can not find dma buffer map!\n");
@@ -844,13 +843,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;
 		}
 
@@ -1391,3 +1387,36 @@
 	i810_dma_dispatch_flip( dev );
    	return 0;
 }
+
+static void i810_driver_pretakedown(drm_device_t *dev)
+{
+	i810_dma_cleanup( dev );
+}
+
+static void i810_driver_release(drm_device_t *dev, struct file *filp)
+{
+	i810_reclaim_buffers(filp);
+}
+
+static int i810_driver_dma_quiescent(drm_device_t *dev)
+{
+	i810_dma_quiescent( dev );
+	return 0;
+}
+
+void i810_driver_register_fns(drm_device_t *dev)
+{
+	dev->driver_features = DRIVER_USE_AGP | DRIVER_REQUIRE_AGP | DRIVER_USE_MTRR | DRIVER_HAVE_DMA | DRIVER_DMA_QUEUE;
+	dev->dev_priv_size = sizeof(drm_i810_buf_priv_t);
+	dev->fn_tbl.pretakedown = i810_driver_pretakedown;
+	dev->fn_tbl.release = i810_driver_release;
+	dev->fn_tbl.dma_quiescent = i810_driver_dma_quiescent;
+	dev->fn_tbl.reclaim_buffers = i810_reclaim_buffers;
+
+	dev->counters += 4;
+	dev->types[6] = _DRM_STAT_IRQ;
+	dev->types[7] = _DRM_STAT_PRIMARY;
+	dev->types[8] = _DRM_STAT_SECONDARY;
+	dev->types[9] = _DRM_STAT_DMA;
+}
+
diff -Nru a/drivers/char/drm/i810_drv.c b/drivers/char/drm/i810_drv.c
--- a/drivers/char/drm/i810_drv.c	2004-10-18 14:57:04 -07:00
+++ b/drivers/char/drm/i810_drv.c	2004-10-18 14:57:04 -07:00
@@ -37,19 +37,4 @@
 #include "i810_drm.h"
 #include "i810_drv.h"
 
-#include "drm_agpsupport.h"
-#include "drm_auth.h"
-#include "drm_bufs.h"
-#include "drm_context.h"
-#include "drm_dma.h"
-#include "drm_drawable.h"
-#include "drm_drv.h"
-
-#include "drm_fops.h"
-#include "drm_init.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"
+#include "drm_core.h"
diff -Nru a/drivers/char/drm/i810_drv.h b/drivers/char/drm/i810_drv.h
--- a/drivers/char/drm/i810_drv.h	2004-10-18 14:57:04 -07:00
+++ b/drivers/char/drm/i810_drv.h	2004-10-18 14:57:04 -07:00
@@ -53,7 +53,6 @@
 
 typedef struct drm_i810_private {
 	drm_map_t *sarea_map;
-	drm_map_t *buffer_map;
 	drm_map_t *mmio_map;
 
 	drm_i810_sarea_t *sarea_priv;
diff -Nru a/drivers/char/drm/i830.h b/drivers/char/drm/i830.h
--- a/drivers/char/drm/i830.h	2004-10-18 14:56:28 -07:00
+++ b/drivers/char/drm/i830.h	2004-10-18 14:56:28 -07:00
@@ -36,10 +36,6 @@
 
 /* General customization:
  */
-#define __HAVE_AGP		1
-#define __MUST_HAVE_AGP		1
-#define __HAVE_MTRR		1
-#define __HAVE_CTX_BITMAP	1
 
 #define DRIVER_AUTHOR		"VA Linux Systems Inc."
 
@@ -77,57 +73,11 @@
 	[DRM_IOCTL_NR(DRM_IOCTL_I830_GETPARAM)] = { i830_getparam,  1, 0 }, \
 	[DRM_IOCTL_NR(DRM_IOCTL_I830_SETPARAM)] = { i830_setparam,  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 __HAVE_RELEASE		1
-#define DRIVER_RELEASE() do {						\
-	i830_reclaim_buffers( filp );					\
-} while (0)
-
-#define DRIVER_PRETAKEDOWN() do {					\
-	i830_dma_cleanup( dev );					\
-} while (0)
-
-/* DMA customization:
- */
-#define __HAVE_DMA		1
-#define __HAVE_DMA_QUEUE	1
-#define __HAVE_DMA_WAITLIST	0
-#define __HAVE_DMA_RECLAIM	1
-
-#define __HAVE_DMA_QUIESCENT	1
-#define DRIVER_DMA_QUIESCENT() do {					\
-	i830_dma_quiescent( dev );					\
-} while (0)
-
-
 /* Driver will work either way: IRQ's save cpu time when waiting for
  * the card, but are subject to subtle interactions between bios,
  * hardware and the driver.
  */
 /* XXX: Add vblank support? */
 #define USE_IRQS 0
-
-#if USE_IRQS
-#define __HAVE_IRQ		1
-#define __HAVE_SHARED_IRQ	1
-#else
-#define __HAVE_IRQ          0
-#endif
-
-
-/* Buffer customization:
- */
-
-#define DRIVER_BUF_PRIV_T	drm_i830_buf_priv_t
-
-#define DRIVER_AGP_BUFFERS_MAP( dev )					\
-	((drm_i830_private_t *)((dev)->dev_private))->buffer_map
 
 #endif
diff -Nru a/drivers/char/drm/i830_dma.c b/drivers/char/drm/i830_dma.c
--- a/drivers/char/drm/i830_dma.c	2004-10-18 14:55:54 -07:00
+++ b/drivers/char/drm/i830_dma.c	2004-10-18 14:55:54 -07:00
@@ -233,13 +233,11 @@
 {
 	drm_device_dma_t *dma = dev->dma;
 
-#if __HAVE_IRQ
 	/* 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_enabled ) DRM(irq_uninstall)(dev);
-#endif
 
 	if (dev->dev_private) {
 		int i;
@@ -371,15 +369,15 @@
 		DRM_ERROR("can not find sarea!\n");
 		return -EINVAL;
 	}
-	DRM_FIND_MAP( dev_priv->mmio_map, init->mmio_offset );
+	dev_priv->mmio_map = drm_core_findmap(dev, init->mmio_offset);
 	if(!dev_priv->mmio_map) {
 		dev->dev_private = (void *)dev_priv;
 		i830_dma_cleanup(dev);
 		DRM_ERROR("can not find mmio map!\n");
 		return -EINVAL;
 	}
-	DRM_FIND_MAP( dev_priv->buffer_map, init->buffers_offset );
-	if(!dev_priv->buffer_map) {
+	dev->agp_buffer_map = drm_core_findmap(dev, init->buffers_offset);
+	if(!dev->agp_buffer_map) {
 		dev->dev_private = (void *)dev_priv;
 		i830_dma_cleanup(dev);
 		DRM_ERROR("can not find dma buffer map!\n");
@@ -1166,19 +1164,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;
 		}
 
@@ -1582,3 +1580,45 @@
 
 	return 0;
 }
+
+
+static void i830_driver_pretakedown(drm_device_t *dev)
+{
+	i830_dma_cleanup( dev );
+}
+
+static void i830_driver_release(drm_device_t *dev, struct file *filp)
+{
+	i830_reclaim_buffers(filp);
+}
+
+static int i830_driver_dma_quiescent(drm_device_t *dev)
+{
+	i830_dma_quiescent( dev );
+	return 0;
+}
+
+void i830_driver_register_fns(drm_device_t *dev)
+{
+	dev->driver_features = DRIVER_USE_AGP | DRIVER_REQUIRE_AGP | DRIVER_USE_MTRR | DRIVER_HAVE_DMA | DRIVER_DMA_QUEUE;
+#if USE_IRQS
+	dev->driver_features |= DRIVER_HAVE_IRQ | DRIVER_SHARED_IRQ;
+#endif
+	dev->dev_priv_size = sizeof(drm_i830_buf_priv_t);
+	dev->fn_tbl.pretakedown = i830_driver_pretakedown;
+	dev->fn_tbl.release = i830_driver_release;
+	dev->fn_tbl.dma_quiescent = i830_driver_dma_quiescent;
+	dev->fn_tbl.reclaim_buffers = i830_reclaim_buffers;
+#if USE_IRQS
+	dev->fn_tbl.irq_preinstall = i830_driver_irq_preinstall;
+	dev->fn_tbl.irq_postinstall = i830_driver_irq_postinstall;
+	dev->fn_tbl.irq_uninstall = i830_driver_irq_uninstall;
+	dev->fn_tbl.irq_handler = i830_driver_irq_handler;
+#endif
+	dev->counters += 4;
+	dev->types[6] = _DRM_STAT_IRQ;
+	dev->types[7] = _DRM_STAT_PRIMARY;
+	dev->types[8] = _DRM_STAT_SECONDARY;
+	dev->types[9] = _DRM_STAT_DMA;
+}
+
diff -Nru a/drivers/char/drm/i830_drv.c b/drivers/char/drm/i830_drv.c
--- a/drivers/char/drm/i830_drv.c	2004-10-18 14:56:28 -07:00
+++ b/drivers/char/drm/i830_drv.c	2004-10-18 14:56:28 -07:00
@@ -39,20 +39,4 @@
 #include "i830_drm.h"
 #include "i830_drv.h"
 
-#include "drm_agpsupport.h"
-#include "drm_auth.h"
-#include "drm_bufs.h"
-#include "drm_context.h"
-#include "drm_dma.h"
-#include "drm_drawable.h"
-#include "drm_drv.h"
-
-#include "drm_fops.h"
-#include "drm_init.h"
-#include "drm_ioctl.h"
-#include "drm_irq.h"
-#include "drm_lock.h"
-#include "drm_memory.h"
-#include "drm_proc.h"
-#include "drm_vm.h"
-#include "drm_stub.h"
+#include "drm_core.h"
diff -Nru a/drivers/char/drm/i830_drv.h b/drivers/char/drm/i830_drv.h
--- a/drivers/char/drm/i830_drv.h	2004-10-18 14:56:48 -07:00
+++ b/drivers/char/drm/i830_drv.h	2004-10-18 14:56:48 -07:00
@@ -53,7 +53,6 @@
 
 typedef struct drm_i830_private {
 	drm_map_t *sarea_map;
-	drm_map_t *buffer_map;
 	drm_map_t *mmio_map;
 
 	drm_i830_sarea_t *sarea_priv;
@@ -137,6 +136,10 @@
 extern int i830_wait_irq(drm_device_t *dev, int irq_nr);
 extern int i830_emit_irq(drm_device_t *dev);
 
+extern irqreturn_t i830_driver_irq_handler( DRM_IRQ_ARGS );
+extern void i830_driver_irq_preinstall( drm_device_t *dev );
+extern void i830_driver_irq_postinstall( drm_device_t *dev );
+extern void i830_driver_irq_uninstall( drm_device_t *dev );
 
 #define I830_BASE(reg)		((unsigned long) \
 				dev_priv->mmio_map->handle)
diff -Nru a/drivers/char/drm/i830_irq.c b/drivers/char/drm/i830_irq.c
--- a/drivers/char/drm/i830_irq.c	2004-10-18 14:56:49 -07:00
+++ b/drivers/char/drm/i830_irq.c	2004-10-18 14:56:49 -07:00
@@ -35,7 +35,7 @@
 #include <linux/delay.h>
 
 
-irqreturn_t DRM(irq_handler)( DRM_IRQ_ARGS )
+irqreturn_t i830_driver_irq_handler( DRM_IRQ_ARGS )
 {
 	drm_device_t	 *dev = (drm_device_t *)arg;
       	drm_i830_private_t *dev_priv = (drm_i830_private_t *)dev->dev_private;
@@ -92,7 +92,7 @@
 	add_wait_queue(&dev_priv->irq_queue, &entry);
 
 	for (;;) {
-		current->state = TASK_INTERRUPTIBLE;
+		__set_current_state(TASK_INTERRUPTIBLE);
 	   	if (atomic_read(&dev_priv->irq_received) >= irq_nr) 
 		   break;
 		if((signed)(end - jiffies) <= 0) {
@@ -112,7 +112,7 @@
 		}
 	}
 
-	current->state = TASK_RUNNING;
+	__set_current_state(TASK_RUNNING);
 	remove_wait_queue(&dev_priv->irq_queue, &entry);
 	return ret;
 }
@@ -178,7 +178,7 @@
 
 /* drm_dma.h hooks
 */
-void DRM(driver_irq_preinstall)( drm_device_t *dev ) {
+void i830_driver_irq_preinstall( drm_device_t *dev ) {
 	drm_i830_private_t *dev_priv =
 		(drm_i830_private_t *)dev->dev_private;
 
@@ -190,14 +190,14 @@
 	init_waitqueue_head(&dev_priv->irq_queue);
 }
 
-void DRM(driver_irq_postinstall)( drm_device_t *dev ) {
+void i830_driver_irq_postinstall( drm_device_t *dev ) {
 	drm_i830_private_t *dev_priv =
 		(drm_i830_private_t *)dev->dev_private;
 
 	I830_WRITE16( I830REG_INT_ENABLE_R, 0x2 );
 }
 
-void DRM(driver_irq_uninstall)( drm_device_t *dev ) {
+void i830_driver_irq_uninstall( drm_device_t *dev ) {
 	drm_i830_private_t *dev_priv =
 		(drm_i830_private_t *)dev->dev_private;
 	if (!dev_priv)
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-10-18 14:57:21 -07:00
@@ -0,0 +1,53 @@
+/* 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 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 }
+
+/* We use our own dma mechanisms, not the drm template code.  However,
+ * the shared IRQ code is useful to us:
+ */
+#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-10-18 14:57:23 -07:00
@@ -0,0 +1,755 @@
+/* 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_core_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);
+	}
+
+	dev_priv->mmio_map = drm_core_findmap(dev, 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_core_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:
+			switch ((cmd>>16)&0xff) {
+			case 0x3:
+				return (cmd & 0x1f) + 2;
+			case 0x4:
+				return (cmd & 0xf) + 2;
+			default:
+				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;
+}
+
+static void i915_driver_pretakedown(drm_device_t *dev)
+{
+	if ( dev->dev_private ) {
+		drm_i915_private_t *dev_priv = dev->dev_private;
+	        i915_mem_takedown( &(dev_priv->agp_heap) );
+ 	}
+	i915_dma_cleanup( dev );
+}
+
+static void i915_driver_prerelease(drm_device_t *dev, DRMFILE filp)
+{
+	if ( dev->dev_private ) {
+		drm_i915_private_t *dev_priv = dev->dev_private;
+                i915_mem_release( dev, filp, dev_priv->agp_heap );
+	}
+}
+
+void i915_driver_register_fns(drm_device_t *dev)
+{
+	dev->driver_features = DRIVER_USE_AGP | DRIVER_REQUIRE_AGP | DRIVER_USE_MTRR | DRIVER_HAVE_IRQ | DRIVER_IRQ_SHARED;
+	dev->fn_tbl.pretakedown = i915_driver_pretakedown;
+	dev->fn_tbl.prerelease = i915_driver_prerelease;
+	dev->fn_tbl.irq_preinstall = i915_driver_irq_preinstall;
+	dev->fn_tbl.irq_postinstall = i915_driver_irq_postinstall;
+	dev->fn_tbl.irq_uninstall = i915_driver_irq_uninstall;
+	dev->fn_tbl.irq_handler = i915_driver_irq_handler;
+	
+	dev->counters += 4;
+	dev->types[6] = _DRM_STAT_IRQ;
+	dev->types[7] = _DRM_STAT_PRIMARY;
+	dev->types[8] = _DRM_STAT_SECONDARY;
+	dev->types[9] = _DRM_STAT_DMA;
+}
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-10-18 14:57:23 -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-10-18 14:57:23 -07:00
@@ -0,0 +1,17 @@
+/* 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_core.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-10-18 14:57:24 -07:00
@@ -0,0 +1,219 @@
+/* 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);
+
+extern irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS);
+extern void i915_driver_irq_preinstall(drm_device_t *dev);
+extern void i915_driver_irq_postinstall(drm_device_t *dev);
+extern void i915_driver_irq_uninstall(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-10-18 14:57:23 -07:00
@@ -0,0 +1,165 @@
+/* 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 i915_driver_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 i915_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 i915_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 i915_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-10-18 14:57:23 -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/mga.h b/drivers/char/drm/mga.h
--- a/drivers/char/drm/mga.h	2004-10-18 14:57:19 -07:00
+++ b/drivers/char/drm/mga.h	2004-10-18 14:57:19 -07:00
@@ -36,10 +36,6 @@
 
 /* General customization:
  */
-#define __HAVE_AGP		1
-#define __MUST_HAVE_AGP		1
-#define __HAVE_MTRR		1
-#define __HAVE_CTX_BITMAP	1
 
 #define DRIVER_AUTHOR		"Gareth Hughes, VA Linux Systems Inc."
 
@@ -63,36 +59,5 @@
 	[DRM_IOCTL_NR(DRM_IOCTL_MGA_ILOAD)]   = { mga_dma_iload,   1, 0 }, \
 	[DRM_IOCTL_NR(DRM_IOCTL_MGA_BLIT)]    = { mga_dma_blit,    1, 0 }, \
 	[DRM_IOCTL_NR(DRM_IOCTL_MGA_GETPARAM)]= { mga_getparam,    1, 0 },
-
-#define __HAVE_COUNTERS         3
-#define __HAVE_COUNTER6         _DRM_STAT_IRQ
-#define __HAVE_COUNTER7         _DRM_STAT_PRIMARY
-#define __HAVE_COUNTER8         _DRM_STAT_SECONDARY
-
-/* Driver customization:
- */
-#define DRIVER_PRETAKEDOWN() do {					\
-	mga_do_cleanup_dma( dev );					\
-} while (0)
-
-/* DMA customization:
- */
-#define __HAVE_DMA		1
-#define __HAVE_IRQ		1
-#define __HAVE_VBL_IRQ		1
-#define __HAVE_SHARED_IRQ       1
-
-#define __HAVE_DMA_QUIESCENT	1
-#define DRIVER_DMA_QUIESCENT() do {					\
-	drm_mga_private_t *dev_priv = dev->dev_private;			\
-	return mga_do_wait_for_idle( dev_priv );			\
-} while (0)
-
-/* Buffer customization:
- */
-#define DRIVER_BUF_PRIV_T	drm_mga_buf_priv_t
-
-#define DRIVER_AGP_BUFFERS_MAP( dev )					\
-	((drm_mga_private_t *)((dev)->dev_private))->buffers
 
 #endif
diff -Nru a/drivers/char/drm/mga_dma.c b/drivers/char/drm/mga_dma.c
--- a/drivers/char/drm/mga_dma.c	2004-10-18 14:56:50 -07:00
+++ b/drivers/char/drm/mga_dma.c	2004-10-18 14:56:50 -07:00
@@ -500,7 +500,7 @@
 		return DRM_ERR(EINVAL);
 	}
 
-	DRM_FIND_MAP( dev_priv->mmio, init->mmio_offset );
+	dev_priv->mmio = drm_core_findmap(dev, init->mmio_offset);
 	if(!dev_priv->mmio) {
 		DRM_ERROR( "failed to find mmio region!\n" );
 		/* Assign dev_private so we can do cleanup. */
@@ -508,7 +508,7 @@
 		mga_do_cleanup_dma( dev );
 		return DRM_ERR(EINVAL);
 	}
-	DRM_FIND_MAP( dev_priv->status, init->status_offset );
+	dev_priv->status = drm_core_findmap(dev, init->status_offset);
 	if(!dev_priv->status) {
 		DRM_ERROR( "failed to find status page!\n" );
 		/* Assign dev_private so we can do cleanup. */
@@ -516,8 +516,7 @@
 		mga_do_cleanup_dma( dev );
 		return DRM_ERR(EINVAL);
 	}
-
-	DRM_FIND_MAP( dev_priv->warp, init->warp_offset );
+	dev_priv->warp = drm_core_findmap(dev, init->warp_offset);
 	if(!dev_priv->warp) {
 		DRM_ERROR( "failed to find warp microcode region!\n" );
 		/* Assign dev_private so we can do cleanup. */
@@ -525,7 +524,7 @@
 		mga_do_cleanup_dma( dev );
 		return DRM_ERR(EINVAL);
 	}
-	DRM_FIND_MAP( dev_priv->primary, init->primary_offset );
+	dev_priv->primary = drm_core_findmap(dev, init->primary_offset);
 	if(!dev_priv->primary) {
 		DRM_ERROR( "failed to find primary dma region!\n" );
 		/* Assign dev_private so we can do cleanup. */
@@ -533,8 +532,8 @@
 		mga_do_cleanup_dma( dev );
 		return DRM_ERR(EINVAL);
 	}
-	DRM_FIND_MAP( dev_priv->buffers, init->buffers_offset );
-	if(!dev_priv->buffers) {
+	dev->agp_buffer_map = drm_core_findmap(dev, init->buffers_offset);
+	if(!dev->agp_buffer_map) {
 		DRM_ERROR( "failed to find dma buffer region!\n" );
 		/* Assign dev_private so we can do cleanup. */
 		dev->dev_private = (void *)dev_priv;
@@ -546,13 +545,13 @@
 		(drm_mga_sarea_t *)((u8 *)dev_priv->sarea->handle +
 				    init->sarea_priv_offset);
 
-	DRM_IOREMAP( dev_priv->warp, dev );
-	DRM_IOREMAP( dev_priv->primary, dev );
-	DRM_IOREMAP( dev_priv->buffers, dev );
+	drm_core_ioremap( dev_priv->warp, dev );
+	drm_core_ioremap( dev_priv->primary, dev );
+	drm_core_ioremap( dev->agp_buffer_map, dev );
 
 	if(!dev_priv->warp->handle ||
 	   !dev_priv->primary->handle ||
-	   !dev_priv->buffers->handle ) {
+	   !dev->agp_buffer_map->handle ) {
 		DRM_ERROR( "failed to ioremap agp regions!\n" );
 		/* Assign dev_private so we can do cleanup. */
 		dev->dev_private = (void *)dev_priv;
@@ -631,23 +630,21 @@
 {
 	DRM_DEBUG( "\n" );
 
-#if __HAVE_IRQ
 	/* 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_enabled ) DRM(irq_uninstall)(dev);
-#endif
 
 	if ( dev->dev_private ) {
 		drm_mga_private_t *dev_priv = dev->dev_private;
 
 		if ( dev_priv->warp != NULL )
-			DRM_IOREMAPFREE( dev_priv->warp, dev );
+			drm_core_ioremapfree( dev_priv->warp, dev );
 		if ( dev_priv->primary != NULL )
-			DRM_IOREMAPFREE( dev_priv->primary, dev );
-		if ( dev_priv->buffers != NULL )
-			DRM_IOREMAPFREE( dev_priv->buffers, dev );
+			drm_core_ioremapfree( dev_priv->primary, dev );
+		if ( dev->agp_buffer_map != NULL )
+			drm_core_ioremapfree( dev->agp_buffer_map, dev );
 
 		if ( dev_priv->head != NULL ) {
 			mga_freelist_cleanup( dev );
@@ -799,4 +796,32 @@
 	DRM_COPY_TO_USER_IOCTL( argp, d, sizeof(d) );
 
 	return ret;
+}
+
+static void mga_driver_pretakedown(drm_device_t *dev)
+{
+	mga_do_cleanup_dma( dev );
+}
+
+static int mga_driver_dma_quiescent(drm_device_t *dev)
+{
+	drm_mga_private_t *dev_priv = dev->dev_private;
+	return mga_do_wait_for_idle( dev_priv );
+}
+
+void mga_driver_register_fns(drm_device_t *dev)
+{
+	dev->driver_features = DRIVER_USE_AGP | DRIVER_REQUIRE_AGP | DRIVER_USE_MTRR | DRIVER_HAVE_DMA | DRIVER_HAVE_IRQ | DRIVER_IRQ_SHARED | DRIVER_IRQ_VBL;
+	dev->fn_tbl.pretakedown = mga_driver_pretakedown;
+	dev->fn_tbl.dma_quiescent = mga_driver_dma_quiescent;
+	dev->fn_tbl.vblank_wait = mga_driver_vblank_wait;
+	dev->fn_tbl.irq_preinstall = mga_driver_irq_preinstall;
+	dev->fn_tbl.irq_postinstall = mga_driver_irq_postinstall;
+	dev->fn_tbl.irq_uninstall = mga_driver_irq_uninstall;
+	dev->fn_tbl.irq_handler = mga_driver_irq_handler;
+	
+	dev->counters += 3;
+	dev->types[6] = _DRM_STAT_IRQ;
+	dev->types[7] = _DRM_STAT_PRIMARY;
+	dev->types[8] = _DRM_STAT_SECONDARY;
 }
diff -Nru a/drivers/char/drm/mga_drv.c b/drivers/char/drm/mga_drv.c
--- a/drivers/char/drm/mga_drv.c	2004-10-18 14:56:29 -07:00
+++ b/drivers/char/drm/mga_drv.c	2004-10-18 14:56:29 -07:00
@@ -35,19 +35,4 @@
 #include "drm.h"
 #include "mga_drm.h"
 #include "mga_drv.h"
-#include "drm_agpsupport.h"
-#include "drm_auth.h"
-#include "drm_bufs.h"
-#include "drm_context.h"
-#include "drm_dma.h"
-#include "drm_drawable.h"
-#include "drm_drv.h"
-#include "drm_fops.h"
-#include "drm_init.h"
-#include "drm_ioctl.h"
-#include "drm_irq.h"
-#include "drm_lock.h"
-#include "drm_memory.h"
-#include "drm_proc.h"
-#include "drm_vm.h"
-#include "drm_stub.h"
+#include "drm_core.h"
diff -Nru a/drivers/char/drm/mga_drv.h b/drivers/char/drm/mga_drv.h
--- a/drivers/char/drm/mga_drv.h	2004-10-18 14:57:03 -07:00
+++ b/drivers/char/drm/mga_drv.h	2004-10-18 14:57:03 -07:00
@@ -130,6 +130,12 @@
 extern int mga_warp_install_microcode( drm_mga_private_t *dev_priv );
 extern int mga_warp_init( drm_mga_private_t *dev_priv );
 
+extern int mga_driver_vblank_wait(drm_device_t *dev, unsigned int *sequence);
+extern irqreturn_t mga_driver_irq_handler( DRM_IRQ_ARGS );
+extern void mga_driver_irq_preinstall( drm_device_t *dev );
+extern void mga_driver_irq_postinstall( drm_device_t *dev );
+extern void mga_driver_irq_uninstall( drm_device_t *dev );
+
 #define mga_flush_write_combine()	DRM_WRITEMEMORYBARRIER()
 
 #if defined(__linux__) && defined(__alpha__)
diff -Nru a/drivers/char/drm/mga_irq.c b/drivers/char/drm/mga_irq.c
--- a/drivers/char/drm/mga_irq.c	2004-10-18 14:55:53 -07:00
+++ b/drivers/char/drm/mga_irq.c	2004-10-18 14:55:53 -07:00
@@ -36,7 +36,7 @@
 #include "mga_drm.h"
 #include "mga_drv.h"
 
-irqreturn_t mga_irq_handler( DRM_IRQ_ARGS )
+irqreturn_t mga_driver_irq_handler( DRM_IRQ_ARGS )
 {
 	drm_device_t *dev = (drm_device_t *) arg;
 	drm_mga_private_t *dev_priv = 
@@ -56,7 +56,7 @@
 	return IRQ_NONE;
 }
 
-int mga_vblank_wait(drm_device_t *dev, unsigned int *sequence)
+int mga_driver_vblank_wait(drm_device_t *dev, unsigned int *sequence)
 {
 	unsigned int cur_vblank;
 	int ret = 0;
diff -Nru a/drivers/char/drm/r128.h b/drivers/char/drm/r128.h
--- a/drivers/char/drm/r128.h	2004-10-18 14:56:28 -07:00
+++ b/drivers/char/drm/r128.h	2004-10-18 14:56:28 -07:00
@@ -36,13 +36,6 @@
 
 /* General customization:
  */
-#define __HAVE_AGP		1
-#define __MUST_HAVE_AGP		0
-#define __HAVE_MTRR		1
-#define __HAVE_CTX_BITMAP	1
-#define __HAVE_SG		1
-#define __HAVE_PCI_DMA		1
-
 #define DRIVER_AUTHOR		"Gareth Hughes, VA Linux Systems Inc."
 
 #define DRIVER_NAME		"r128"
@@ -78,43 +71,5 @@
    [DRM_IOCTL_NR(DRM_IOCTL_R128_STIPPLE)]    = { r128_cce_stipple,  1, 0 }, \
    [DRM_IOCTL_NR(DRM_IOCTL_R128_INDIRECT)]   = { r128_cce_indirect, 1, 1 }, \
    [DRM_IOCTL_NR(DRM_IOCTL_R128_GETPARAM)]   = { r128_getparam, 1, 0 },
-
-/* Driver customization:
- */
-#define DRIVER_PRERELEASE() do {					\
-	if ( dev->dev_private ) {					\
-		drm_r128_private_t *dev_priv = dev->dev_private;	\
-		if ( dev_priv->page_flipping ) {			\
-			r128_do_cleanup_pageflip( dev );		\
-		}							\
-	}								\
-} while (0)
-
-#define DRIVER_PRETAKEDOWN() do {					\
-	r128_do_cleanup_cce( dev );					\
-} while (0)
-
-/* DMA customization:
- */
-#define __HAVE_DMA		1
-#define __HAVE_IRQ		1
-#define __HAVE_VBL_IRQ		1
-#define __HAVE_SHARED_IRQ       1
-
-#if 0
-/* GH: Remove this for now... */
-#define __HAVE_DMA_QUIESCENT	1
-#define DRIVER_DMA_QUIESCENT() do {					\
-	drm_r128_private_t *dev_priv = dev->dev_private;		\
-	return r128_do_cce_idle( dev_priv );				\
-} while (0)
-#endif
-
-/* Buffer customization:
- */
-#define DRIVER_BUF_PRIV_T	drm_r128_buf_priv_t
-
-#define DRIVER_AGP_BUFFERS_MAP( dev )					\
-	((drm_r128_private_t *)((dev)->dev_private))->buffers
 
 #endif
diff -Nru a/drivers/char/drm/r128_cce.c b/drivers/char/drm/r128_cce.c
--- a/drivers/char/drm/r128_cce.c	2004-10-18 14:56:11 -07:00
+++ b/drivers/char/drm/r128_cce.c	2004-10-18 14:56:11 -07:00
@@ -322,7 +322,7 @@
 	/* The manual (p. 2) says this address is in "VM space".  This
 	 * means it's an offset from the start of AGP space.
 	 */
-#if __REALLY_HAVE_AGP
+#if __OS_HAS_AGP
 	if ( !dev_priv->is_pci )
 		ring_start = dev_priv->cce_ring->offset - dev->agp->base;
 	else
@@ -467,29 +467,29 @@
 		return DRM_ERR(EINVAL);
 	}
 
-	DRM_FIND_MAP( dev_priv->mmio, init->mmio_offset );
+	dev_priv->mmio = drm_core_findmap(dev, init->mmio_offset);
 	if(!dev_priv->mmio) {
 		DRM_ERROR("could not find mmio region!\n");
 		dev->dev_private = (void *)dev_priv;
 		r128_do_cleanup_cce( dev );
 		return DRM_ERR(EINVAL);
 	}
-	DRM_FIND_MAP( dev_priv->cce_ring, init->ring_offset );
+	dev_priv->cce_ring = drm_core_findmap(dev, init->ring_offset);
 	if(!dev_priv->cce_ring) {
 		DRM_ERROR("could not find cce ring region!\n");
 		dev->dev_private = (void *)dev_priv;
 		r128_do_cleanup_cce( dev );
 		return DRM_ERR(EINVAL);
 	}
-	DRM_FIND_MAP( dev_priv->ring_rptr, init->ring_rptr_offset );
+	dev_priv->ring_rptr = drm_core_findmap(dev, init->ring_rptr_offset);
 	if(!dev_priv->ring_rptr) {
 		DRM_ERROR("could not find ring read pointer!\n");
 		dev->dev_private = (void *)dev_priv;
 		r128_do_cleanup_cce( dev );
 		return DRM_ERR(EINVAL);
 	}
-	DRM_FIND_MAP( dev_priv->buffers, init->buffers_offset );
-	if(!dev_priv->buffers) {
+	dev->agp_buffer_map = drm_core_findmap(dev, init->buffers_offset);
+	if(!dev->agp_buffer_map) {
 		DRM_ERROR("could not find dma buffer region!\n");
 		dev->dev_private = (void *)dev_priv;
 		r128_do_cleanup_cce( dev );
@@ -497,8 +497,7 @@
 	}
 
 	if ( !dev_priv->is_pci ) {
-		DRM_FIND_MAP( dev_priv->agp_textures,
-			      init->agp_textures_offset );
+		dev_priv->agp_textures = drm_core_findmap(dev, init->agp_textures_offset);
 		if(!dev_priv->agp_textures) {
 			DRM_ERROR("could not find agp texture region!\n");
 			dev->dev_private = (void *)dev_priv;
@@ -511,14 +510,14 @@
 		(drm_r128_sarea_t *)((u8 *)dev_priv->sarea->handle +
 				     init->sarea_priv_offset);
 
-#if __REALLY_HAVE_AGP
+#if __OS_HAS_AGP
 	if ( !dev_priv->is_pci ) {
-		DRM_IOREMAP( dev_priv->cce_ring, dev );
-		DRM_IOREMAP( dev_priv->ring_rptr, dev );
-		DRM_IOREMAP( dev_priv->buffers, dev );
+		drm_core_ioremap( dev_priv->cce_ring, dev );
+		drm_core_ioremap( dev_priv->ring_rptr, dev );
+		drm_core_ioremap( dev->agp_buffer_map, dev );
 		if(!dev_priv->cce_ring->handle ||
 		   !dev_priv->ring_rptr->handle ||
-		   !dev_priv->buffers->handle) {
+		   !dev->agp_buffer_map->handle) {
 			DRM_ERROR("Could not ioremap agp regions!\n");
 			dev->dev_private = (void *)dev_priv;
 			r128_do_cleanup_cce( dev );
@@ -531,10 +530,10 @@
 			(void *)dev_priv->cce_ring->offset;
 		dev_priv->ring_rptr->handle =
 			(void *)dev_priv->ring_rptr->offset;
-		dev_priv->buffers->handle = (void *)dev_priv->buffers->offset;
+		dev->agp_buffer_map->handle = (void *)dev->agp_buffer_map->offset;
 	}
 
-#if __REALLY_HAVE_AGP
+#if __OS_HAS_AGP
 	if ( !dev_priv->is_pci )
 		dev_priv->cce_buffers_offset = dev->agp->base;
 	else
@@ -559,7 +558,7 @@
 	R128_WRITE( R128_LAST_DISPATCH_REG,
 		    dev_priv->sarea_priv->last_dispatch );
 
-#if __REALLY_HAVE_AGP
+#if __OS_HAS_AGP
 	if ( dev_priv->is_pci ) {
 #endif
 		if (!DRM(ati_pcigart_init)( dev, &dev_priv->phys_pci_gart,
@@ -570,7 +569,7 @@
 			return DRM_ERR(ENOMEM);
 		}
 		R128_WRITE( R128_PCI_GART_PAGE, dev_priv->bus_pci_gart );
-#if __REALLY_HAVE_AGP
+#if __OS_HAS_AGP
 	}
 #endif
 
@@ -587,25 +586,23 @@
 int r128_do_cleanup_cce( drm_device_t *dev )
 {
 
-#if __HAVE_IRQ
 	/* 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_enabled ) DRM(irq_uninstall)(dev);
-#endif
 
 	if ( dev->dev_private ) {
 		drm_r128_private_t *dev_priv = dev->dev_private;
 
-#if __REALLY_HAVE_AGP
+#if __OS_HAS_AGP
 		if ( !dev_priv->is_pci ) {
 			if ( dev_priv->cce_ring != NULL )
-				DRM_IOREMAPFREE( dev_priv->cce_ring, dev );
+				drm_core_ioremapfree( dev_priv->cce_ring, dev );
 			if ( dev_priv->ring_rptr != NULL )
-				DRM_IOREMAPFREE( dev_priv->ring_rptr, dev );
-			if ( dev_priv->buffers != NULL )
-				DRM_IOREMAPFREE( dev_priv->buffers, dev );
+				drm_core_ioremapfree( dev_priv->ring_rptr, dev );
+			if ( dev->agp_buffer_map != NULL )
+				drm_core_ioremapfree( dev->agp_buffer_map, dev );
 		} else
 #endif
 		{
diff -Nru a/drivers/char/drm/r128_drv.c b/drivers/char/drm/r128_drv.c
--- a/drivers/char/drm/r128_drv.c	2004-10-18 14:56:27 -07:00
+++ b/drivers/char/drm/r128_drv.c	2004-10-18 14:56:27 -07:00
@@ -37,20 +37,4 @@
 #include "r128_drv.h"
 #include "ati_pcigart.h"
 
-#include "drm_agpsupport.h"
-#include "drm_auth.h"
-#include "drm_bufs.h"
-#include "drm_context.h"
-#include "drm_dma.h"
-#include "drm_drawable.h"
-#include "drm_drv.h"
-#include "drm_fops.h"
-#include "drm_init.h"
-#include "drm_ioctl.h"
-#include "drm_irq.h"
-#include "drm_lock.h"
-#include "drm_memory.h"
-#include "drm_proc.h"
-#include "drm_vm.h"
-#include "drm_stub.h"
-#include "drm_scatter.h"
+#include "drm_core.h"
diff -Nru a/drivers/char/drm/r128_drv.h b/drivers/char/drm/r128_drv.h
--- a/drivers/char/drm/r128_drv.h	2004-10-18 14:57:05 -07:00
+++ b/drivers/char/drm/r128_drv.h	2004-10-18 14:57:05 -07:00
@@ -100,7 +100,6 @@
 	drm_local_map_t *mmio;
 	drm_local_map_t *cce_ring;
 	drm_local_map_t *ring_rptr;
-	drm_local_map_t *buffers;
 	drm_local_map_t *agp_textures;
 } drm_r128_private_t;
 
@@ -143,6 +142,12 @@
 extern int r128_cce_stipple( DRM_IOCTL_ARGS );
 extern int r128_cce_indirect( DRM_IOCTL_ARGS );
 
+extern int r128_driver_vblank_wait(drm_device_t *dev, unsigned int *sequence);
+
+extern irqreturn_t r128_driver_irq_handler( DRM_IRQ_ARGS );
+extern void r128_driver_irq_preinstall( drm_device_t *dev );
+extern void r128_driver_irq_postinstall( drm_device_t *dev );
+extern void r128_driver_irq_uninstall( drm_device_t *dev );
 
 /* Register definitions, register access macros and drmAddMap constants
  * for Rage 128 kernel driver.
diff -Nru a/drivers/char/drm/r128_irq.c b/drivers/char/drm/r128_irq.c
--- a/drivers/char/drm/r128_irq.c	2004-10-18 14:57:18 -07:00
+++ b/drivers/char/drm/r128_irq.c	2004-10-18 14:57:18 -07:00
@@ -36,7 +36,7 @@
 #include "r128_drm.h"
 #include "r128_drv.h"
 
-irqreturn_t r128_irq_handler( DRM_IRQ_ARGS )
+irqreturn_t r128_driver_irq_handler( DRM_IRQ_ARGS )
 {
 	drm_device_t *dev = (drm_device_t *) arg;
 	drm_r128_private_t *dev_priv = 
@@ -56,7 +56,7 @@
 	return IRQ_NONE;
 }
 
-int DRM(vblank_wait)(drm_device_t *dev, unsigned int *sequence)
+int r128_driver_vblank_wait(drm_device_t *dev, unsigned int *sequence)
 {
 	unsigned int cur_vblank;
 	int ret = 0;
diff -Nru a/drivers/char/drm/r128_state.c b/drivers/char/drm/r128_state.c
--- a/drivers/char/drm/r128_state.c	2004-10-18 14:56:13 -07:00
+++ b/drivers/char/drm/r128_state.c	2004-10-18 14:56:13 -07:00
@@ -667,7 +667,7 @@
 		 */
 		if ( dwords & 1 ) {
 			u32 *data = (u32 *)
-				((char *)dev_priv->buffers->handle
+				((char *)dev->agp_buffer_map->handle
 				 + buf->offset + start);
 			data[dwords++] = cpu_to_le32( R128_CCE_PACKET2 );
 		}
@@ -713,7 +713,7 @@
 	drm_r128_buf_priv_t *buf_priv = buf->dev_private;
 	drm_r128_sarea_t *sarea_priv = dev_priv->sarea_priv;
 	int format = sarea_priv->vc_format;
-	int offset = dev_priv->buffers->offset - dev_priv->cce_buffers_offset;
+	int offset = dev->agp_buffer_map->offset - dev_priv->cce_buffers_offset;
 	int prim = buf_priv->prim;
 	u32 *data;
 	int dwords;
@@ -733,7 +733,7 @@
 
 		dwords = (end - start + 3) / sizeof(u32);
 
-		data = (u32 *)((char *)dev_priv->buffers->handle
+		data = (u32 *)((char *)dev->agp_buffer_map->handle
 			       + buf->offset + start);
 
 		data[0] = cpu_to_le32( CCE_PACKET3( R128_3D_RNDR_GEN_INDX_PRIM,
@@ -857,7 +857,7 @@
 
 	dwords = (blit->width * blit->height) >> dword_shift;
 
-	data = (u32 *)((char *)dev_priv->buffers->handle + buf->offset);
+	data = (u32 *)((char *)dev->agp_buffer_map->handle + buf->offset);
 
 	data[0] = cpu_to_le32( CCE_PACKET3( R128_CNTL_HOSTDATA_BLT, dwords + 6 ) );
 	data[1] = cpu_to_le32( (R128_GMC_DST_PITCH_OFFSET_CNTL |
@@ -1693,4 +1693,32 @@
 	}
 	
 	return 0;
+}
+
+static void r128_driver_prerelease(drm_device_t *dev, DRMFILE filp)
+{
+	if ( dev->dev_private ) {
+		drm_r128_private_t *dev_priv = dev->dev_private;
+		if ( dev_priv->page_flipping ) {
+			r128_do_cleanup_pageflip( dev );
+		}
+	}			
+}
+
+static void r128_driver_pretakedown(drm_device_t *dev)
+{
+	r128_do_cleanup_cce( dev );
+}
+
+void r128_driver_register_fns(drm_device_t *dev)
+{
+	dev->driver_features = DRIVER_USE_AGP | DRIVER_USE_MTRR | DRIVER_PCI_DMA | DRIVER_SG | DRIVER_HAVE_DMA | DRIVER_HAVE_IRQ | DRIVER_IRQ_SHARED | DRIVER_IRQ_VBL;
+	dev->dev_priv_size = sizeof(drm_r128_buf_priv_t);
+	dev->fn_tbl.prerelease = r128_driver_prerelease;
+	dev->fn_tbl.pretakedown = r128_driver_pretakedown;
+	dev->fn_tbl.vblank_wait = r128_driver_vblank_wait;
+	dev->fn_tbl.irq_preinstall = r128_driver_irq_preinstall;
+	dev->fn_tbl.irq_postinstall = r128_driver_irq_postinstall;
+	dev->fn_tbl.irq_uninstall = r128_driver_irq_uninstall;
+	dev->fn_tbl.irq_handler = r128_driver_irq_handler;
 }
diff -Nru a/drivers/char/drm/radeon.h b/drivers/char/drm/radeon.h
--- a/drivers/char/drm/radeon.h	2004-10-18 14:57:03 -07:00
+++ b/drivers/char/drm/radeon.h	2004-10-18 14:57:03 -07:00
@@ -37,12 +37,6 @@
 
 /* General customization:
  */
-#define __HAVE_AGP		1
-#define __MUST_HAVE_AGP		0
-#define __HAVE_MTRR		1
-#define __HAVE_CTX_BITMAP	1
-#define __HAVE_SG		1
-#define __HAVE_PCI_DMA		1
 
 #define DRIVER_AUTHOR		"Gareth Hughes, Keith Whitwell, others."
 
@@ -114,60 +108,5 @@
  [DRM_IOCTL_NR(DRM_IOCTL_RADEON_IRQ_EMIT)]   = { radeon_irq_emit,    1, 0 }, \
  [DRM_IOCTL_NR(DRM_IOCTL_RADEON_IRQ_WAIT)]   = { radeon_irq_wait,    1, 0 }, \
  [DRM_IOCTL_NR(DRM_IOCTL_RADEON_SETPARAM)]   = { radeon_cp_setparam, 1, 0 }, \
-
-#define DRIVER_FILE_FIELDS						\
-	int64_t radeon_fb_delta;					\
-
-#define DRIVER_OPEN_HELPER( filp_priv, dev )				\
-do {									\
-	drm_radeon_private_t *dev_priv = dev->dev_private;		\
-	if ( dev_priv )							\
-		filp_priv->radeon_fb_delta = dev_priv->fb_location;	\
-	else								\
-		filp_priv->radeon_fb_delta = 0;				\
-} while( 0 )
-
-/* When a client dies:
- *    - Check for and clean up flipped page state
- *    - Free any alloced GART memory.
- *
- * DRM infrastructure takes care of reclaiming dma buffers.
- */
-#define DRIVER_PRERELEASE() 						\
-do {									\
-	if ( dev->dev_private ) {					\
-		drm_radeon_private_t *dev_priv = dev->dev_private;	\
-		if ( dev_priv->page_flipping ) {			\
-			radeon_do_cleanup_pageflip( dev );		\
-		}							\
-		radeon_mem_release( filp, dev_priv->gart_heap );	\
-		radeon_mem_release( filp, dev_priv->fb_heap );		\
-	}								\
-} while (0)
-
-/* When the last client dies, shut down the CP and free dev->dev_priv.
- */
-/* #define __HAVE_RELEASE 1 */
-#define DRIVER_PRETAKEDOWN()			\
-do {						\
-    radeon_do_release( dev );			\
-} while (0)
-
-
-
-/* DMA customization:
- */
-#define __HAVE_DMA		1
-#define __HAVE_IRQ		1
-#define __HAVE_VBL_IRQ		1
-#define __HAVE_SHARED_IRQ       1
-
-
-/* Buffer customization:
- */
-#define DRIVER_BUF_PRIV_T	drm_radeon_buf_priv_t
-
-#define DRIVER_AGP_BUFFERS_MAP( dev )				\
-	((drm_radeon_private_t *)((dev)->dev_private))->buffers
 
 #endif
diff -Nru a/drivers/char/drm/radeon_cp.c b/drivers/char/drm/radeon_cp.c
--- a/drivers/char/drm/radeon_cp.c	2004-10-18 14:56:17 -07:00
+++ b/drivers/char/drm/radeon_cp.c	2004-10-18 14:56:17 -07:00
@@ -858,7 +858,7 @@
 		      ( ( dev_priv->gart_vm_start - 1 ) & 0xffff0000 )
 		    | ( dev_priv->fb_location >> 16 ) );
 
-#if __REALLY_HAVE_AGP
+#if __OS_HAS_AGP
 	if ( !dev_priv->is_pci ) {
 		RADEON_WRITE( RADEON_MC_AGP_LOCATION,
 			      (((dev_priv->gart_vm_start - 1 +
@@ -885,7 +885,7 @@
 	SET_RING_HEAD( dev_priv, cur_read_ptr );
 	dev_priv->ring.tail = cur_read_ptr;
 
-#if __REALLY_HAVE_AGP
+#if __OS_HAS_AGP
 	if ( !dev_priv->is_pci ) {
 		RADEON_WRITE( RADEON_CP_RB_RPTR_ADDR,
 			      dev_priv->ring_rptr->offset
@@ -1118,29 +1118,29 @@
 		return DRM_ERR(EINVAL);
 	}
 
-	DRM_FIND_MAP( dev_priv->mmio, init->mmio_offset );
+	dev_priv->mmio = drm_core_findmap(dev, init->mmio_offset);
 	if(!dev_priv->mmio) {
 		DRM_ERROR("could not find mmio region!\n");
 		dev->dev_private = (void *)dev_priv;
 		radeon_do_cleanup_cp(dev);
 		return DRM_ERR(EINVAL);
 	}
-	DRM_FIND_MAP( dev_priv->cp_ring, init->ring_offset );
+	dev_priv->cp_ring = drm_core_findmap(dev, init->ring_offset);
 	if(!dev_priv->cp_ring) {
 		DRM_ERROR("could not find cp ring region!\n");
 		dev->dev_private = (void *)dev_priv;
 		radeon_do_cleanup_cp(dev);
 		return DRM_ERR(EINVAL);
 	}
-	DRM_FIND_MAP( dev_priv->ring_rptr, init->ring_rptr_offset );
+	dev_priv->ring_rptr = drm_core_findmap(dev, init->ring_rptr_offset);
 	if(!dev_priv->ring_rptr) {
 		DRM_ERROR("could not find ring read pointer!\n");
 		dev->dev_private = (void *)dev_priv;
 		radeon_do_cleanup_cp(dev);
 		return DRM_ERR(EINVAL);
 	}
-	DRM_FIND_MAP( dev_priv->buffers, init->buffers_offset );
-	if(!dev_priv->buffers) {
+	dev->agp_buffer_map = drm_core_findmap(dev, init->buffers_offset);
+	if(!dev->agp_buffer_map) {
 		DRM_ERROR("could not find dma buffer region!\n");
 		dev->dev_private = (void *)dev_priv;
 		radeon_do_cleanup_cp(dev);
@@ -1148,7 +1148,7 @@
 	}
 
 	if ( init->gart_textures_offset ) {
-		DRM_FIND_MAP( dev_priv->gart_textures, init->gart_textures_offset );
+		dev_priv->gart_textures = drm_core_findmap(dev, init->gart_textures_offset);
 		if ( !dev_priv->gart_textures ) {
 			DRM_ERROR("could not find GART texture region!\n");
 			dev->dev_private = (void *)dev_priv;
@@ -1161,14 +1161,14 @@
 		(drm_radeon_sarea_t *)((u8 *)dev_priv->sarea->handle +
 				       init->sarea_priv_offset);
 
-#if __REALLY_HAVE_AGP
+#if __OS_HAS_AGP
 	if ( !dev_priv->is_pci ) {
-		DRM_IOREMAP( dev_priv->cp_ring, dev );
-		DRM_IOREMAP( dev_priv->ring_rptr, dev );
-		DRM_IOREMAP( dev_priv->buffers, dev );
+		drm_core_ioremap( dev_priv->cp_ring, dev );
+		drm_core_ioremap( dev_priv->ring_rptr, dev );
+		drm_core_ioremap( dev->agp_buffer_map, dev );
 		if(!dev_priv->cp_ring->handle ||
 		   !dev_priv->ring_rptr->handle ||
-		   !dev_priv->buffers->handle) {
+		   !dev->agp_buffer_map->handle) {
 			DRM_ERROR("could not find ioremap agp regions!\n");
 			dev->dev_private = (void *)dev_priv;
 			radeon_do_cleanup_cp(dev);
@@ -1181,14 +1181,14 @@
 			(void *)dev_priv->cp_ring->offset;
 		dev_priv->ring_rptr->handle =
 			(void *)dev_priv->ring_rptr->offset;
-		dev_priv->buffers->handle = (void *)dev_priv->buffers->offset;
+		dev->agp_buffer_map->handle = (void *)dev->agp_buffer_map->offset;
 
 		DRM_DEBUG( "dev_priv->cp_ring->handle %p\n",
 			   dev_priv->cp_ring->handle );
 		DRM_DEBUG( "dev_priv->ring_rptr->handle %p\n",
 			   dev_priv->ring_rptr->handle );
-		DRM_DEBUG( "dev_priv->buffers->handle %p\n",
-			   dev_priv->buffers->handle );
+		DRM_DEBUG( "dev->agp_buffer_map->handle %p\n",
+			   dev->agp_buffer_map->handle );
 	}
 
 	dev_priv->fb_location = ( RADEON_READ( RADEON_MC_FB_LOCATION )
@@ -1211,14 +1211,14 @@
 	dev_priv->gart_vm_start = dev_priv->fb_location
 				+ RADEON_READ( RADEON_CONFIG_APER_SIZE );
 
-#if __REALLY_HAVE_AGP
+#if __OS_HAS_AGP
 	if ( !dev_priv->is_pci )
-		dev_priv->gart_buffers_offset = (dev_priv->buffers->offset
+		dev_priv->gart_buffers_offset = (dev->agp_buffer_map->offset
 						- dev->agp->base
 						+ dev_priv->gart_vm_start);
 	else
 #endif
-		dev_priv->gart_buffers_offset = (dev_priv->buffers->offset
+		dev_priv->gart_buffers_offset = (dev->agp_buffer_map->offset
 						- dev->sg->handle
 						+ dev_priv->gart_vm_start);
 
@@ -1240,7 +1240,7 @@
 
 	dev_priv->ring.high_mark = RADEON_RING_HIGH_MARK;
 
-#if __REALLY_HAVE_AGP
+#if __OS_HAS_AGP
 	if ( !dev_priv->is_pci ) {
 		/* Turn off PCI GART */
 		radeon_set_pcigart( dev_priv, 0 );
@@ -1275,25 +1275,23 @@
 {
 	DRM_DEBUG( "\n" );
 
-#if __HAVE_IRQ
 	/* 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_enabled ) DRM(irq_uninstall)(dev);
-#endif
 
 	if ( dev->dev_private ) {
 		drm_radeon_private_t *dev_priv = dev->dev_private;
 
-#if __REALLY_HAVE_AGP
+#if __OS_HAS_AGP
 		if ( !dev_priv->is_pci ) {
 			if ( dev_priv->cp_ring != NULL )
-				DRM_IOREMAPFREE( dev_priv->cp_ring, dev );
+				drm_core_ioremapfree( dev_priv->cp_ring, dev );
 			if ( dev_priv->ring_rptr != NULL )
-				DRM_IOREMAPFREE( dev_priv->ring_rptr, dev );
-			if ( dev_priv->buffers != NULL )
-				DRM_IOREMAPFREE( dev_priv->buffers, dev );
+				drm_core_ioremapfree( dev_priv->ring_rptr, dev );
+			if ( dev->agp_buffer_map != NULL )
+				drm_core_ioremapfree( dev->agp_buffer_map, dev );
 		} else
 #endif
 		{
@@ -1329,7 +1327,7 @@
 
 	DRM_DEBUG("Starting radeon_do_resume_cp()\n");
 
-#if __REALLY_HAVE_AGP
+#if __OS_HAS_AGP
 	if ( !dev_priv->is_pci ) {
 		/* Turn off PCI GART */
 		radeon_set_pcigart( dev_priv, 0 );
diff -Nru a/drivers/char/drm/radeon_drv.c b/drivers/char/drm/radeon_drv.c
--- a/drivers/char/drm/radeon_drv.c	2004-10-18 14:56:48 -07:00
+++ b/drivers/char/drm/radeon_drv.c	2004-10-18 14:56:48 -07:00
@@ -38,20 +38,4 @@
 #include "radeon_drv.h"
 #include "ati_pcigart.h"
 
-#include "drm_agpsupport.h"
-#include "drm_auth.h"
-#include "drm_bufs.h"
-#include "drm_context.h"
-#include "drm_dma.h"
-#include "drm_drawable.h"
-#include "drm_drv.h"
-#include "drm_fops.h"
-#include "drm_init.h"
-#include "drm_ioctl.h"
-#include "drm_irq.h"
-#include "drm_lock.h"
-#include "drm_memory.h"
-#include "drm_proc.h"
-#include "drm_vm.h"
-#include "drm_stub.h"
-#include "drm_scatter.h"
+#include "drm_core.h"
diff -Nru a/drivers/char/drm/radeon_drv.h b/drivers/char/drm/radeon_drv.h
--- a/drivers/char/drm/radeon_drv.h	2004-10-18 14:56:32 -07:00
+++ b/drivers/char/drm/radeon_drv.h	2004-10-18 14:56:32 -07:00
@@ -60,6 +60,9 @@
 	u32 se_cntl;
 } drm_radeon_depth_clear_t;
 
+struct drm_radeon_driver_file_fields {
+	int64_t radeon_fb_delta;
+};
 
 struct mem_block {
 	struct mem_block *next;
@@ -138,7 +141,6 @@
 	drm_local_map_t *mmio;
 	drm_local_map_t *cp_ring;
 	drm_local_map_t *ring_rptr;
-	drm_local_map_t *buffers;
 	drm_local_map_t *gart_textures;
 
 	struct mem_block *gart_heap;
@@ -203,6 +205,11 @@
 extern int radeon_emit_irq(drm_device_t *dev);
 
 extern void radeon_do_release(drm_device_t *dev);
+extern int radeon_driver_vblank_wait(drm_device_t *dev, unsigned int *sequence);
+extern irqreturn_t radeon_driver_irq_handler( DRM_IRQ_ARGS );
+extern void radeon_driver_irq_preinstall( drm_device_t *dev );
+extern void radeon_driver_irq_postinstall( drm_device_t *dev );
+extern void radeon_driver_irq_uninstall( drm_device_t *dev );
 
 /* Flags for stats.boxes
  */
diff -Nru a/drivers/char/drm/radeon_irq.c b/drivers/char/drm/radeon_irq.c
--- a/drivers/char/drm/radeon_irq.c	2004-10-18 14:57:04 -07:00
+++ b/drivers/char/drm/radeon_irq.c	2004-10-18 14:57:04 -07:00
@@ -54,7 +54,7 @@
  * tied to dma at all, this is just a hangover from dri prehistory.
  */
 
-irqreturn_t DRM(irq_handler)( DRM_IRQ_ARGS )
+irqreturn_t radeon_driver_irq_handler( DRM_IRQ_ARGS )
 {
 	drm_device_t *dev = (drm_device_t *) arg;
 	drm_radeon_private_t *dev_priv = 
@@ -141,7 +141,7 @@
 }
 
 
-int DRM(vblank_wait)(drm_device_t *dev, unsigned int *sequence)
+int radeon_driver_vblank_wait(drm_device_t *dev, unsigned int *sequence)
 {
   	drm_radeon_private_t *dev_priv = 
 	   (drm_radeon_private_t *)dev->dev_private;
diff -Nru a/drivers/char/drm/radeon_state.c b/drivers/char/drm/radeon_state.c
--- a/drivers/char/drm/radeon_state.c	2004-10-18 14:56:50 -07:00
+++ b/drivers/char/drm/radeon_state.c	2004-10-18 14:56:50 -07:00
@@ -43,12 +43,14 @@
 						     drm_file_t *filp_priv,
 						     u32 *offset ) {
 	u32 off = *offset;
+	struct drm_radeon_driver_file_fields *radeon_priv;
 
 	if ( off >= dev_priv->fb_location &&
 	     off < ( dev_priv->gart_vm_start + dev_priv->gart_size ) )
 		return 0;
 
-	off += filp_priv->radeon_fb_delta;
+	radeon_priv = filp_priv->driver_priv;
+	off += radeon_priv->radeon_fb_delta;
 
 	DRM_DEBUG( "offset fixed up to 0x%x\n", off );
 
@@ -1247,7 +1249,7 @@
 		 */
 		if ( dwords & 1 ) {
 			u32 *data = (u32 *)
-				((char *)dev_priv->buffers->handle
+				((char *)dev->agp_buffer_map->handle
 				 + buf->offset + start);
 			data[dwords++] = RADEON_CP_PACKET2;
 		}
@@ -1301,7 +1303,7 @@
 
 	dwords = (prim->finish - prim->start + 3) / sizeof(u32);
 
-	data = (u32 *)((char *)dev_priv->buffers->handle +
+	data = (u32 *)((char *)dev->agp_buffer_map->handle +
 		       elt_buf->offset + prim->start);
 
 	data[0] = CP_PACKET3( RADEON_3D_RNDR_GEN_INDX_PRIM, dwords-2 );
@@ -1445,7 +1447,7 @@
 
 		/* Dispatch the indirect buffer.
 		 */
-		buffer = (u32*)((char*)dev_priv->buffers->handle + buf->offset);
+		buffer = (u32*)((char*)dev->agp_buffer_map->handle + buf->offset);
 		dwords = size / 4;
 		buffer[0] = CP_PACKET3( RADEON_CNTL_HOSTDATA_BLT, dwords + 6 );
 		buffer[1] = (RADEON_GMC_DST_PITCH_OFFSET_CNTL |
@@ -1665,11 +1667,6 @@
 
 	LOCK_TEST_WITH_RETURN( dev, filp );
 
-	if ( !dev_priv ) {
-		DRM_ERROR( "%s called with no initialization\n", __FUNCTION__ );
-		return DRM_ERR(EINVAL);
-	}
-
 	DRM_GET_PRIV_WITH_RETURN( filp_priv, filp );
 
 	DRM_COPY_FROM_USER_IOCTL( vertex, (drm_radeon_vertex_t __user *)data,
@@ -2525,6 +2522,7 @@
 	drm_radeon_private_t *dev_priv = dev->dev_private;
 	drm_file_t *filp_priv;
 	drm_radeon_setparam_t sp;
+	struct drm_radeon_driver_file_fields *radeon_priv;
 
 	if ( !dev_priv ) {
 		DRM_ERROR( "%s called with no initialization\n", __FUNCTION__ );
@@ -2538,7 +2536,8 @@
 
 	switch( sp.param ) {
 	case RADEON_SETPARAM_FB_LOCATION:
-		filp_priv->radeon_fb_delta = dev_priv->fb_location - sp.value;
+		radeon_priv = filp_priv->driver_priv;
+		radeon_priv->radeon_fb_delta = dev_priv->fb_location - sp.value;
 		break;
 	default:
 		DRM_DEBUG( "Invalid parameter %d\n", sp.param );
@@ -2546,4 +2545,68 @@
 	}
 
 	return 0;
+}
+
+/* When a client dies:
+ *    - Check for and clean up flipped page state
+ *    - Free any alloced GART memory.
+ *
+ * DRM infrastructure takes care of reclaiming dma buffers.
+ */
+static void radeon_driver_prerelease(drm_device_t *dev, DRMFILE filp)
+{
+	if ( dev->dev_private ) {				
+		drm_radeon_private_t *dev_priv = dev->dev_private; 
+		if ( dev_priv->page_flipping ) {		
+			radeon_do_cleanup_pageflip( dev );	
+		}						
+		radeon_mem_release( filp, dev_priv->gart_heap ); 
+		radeon_mem_release( filp, dev_priv->fb_heap );	
+	}				
+}
+
+static void radeon_driver_pretakedown(drm_device_t *dev)
+{
+	radeon_do_release(dev);
+}
+
+static int radeon_driver_open_helper(drm_device_t *dev, drm_file_t *filp_priv)
+{
+	drm_radeon_private_t *dev_priv = dev->dev_private;
+	struct drm_radeon_driver_file_fields *radeon_priv;
+	
+	radeon_priv = (struct drm_radeon_driver_file_fields *)DRM(alloc)(sizeof(*radeon_priv), DRM_MEM_FILES);
+	
+	if (!radeon_priv)
+		return -ENOMEM;
+
+	filp_priv->driver_priv = radeon_priv;
+	if ( dev_priv )
+		radeon_priv->radeon_fb_delta = dev_priv->fb_location;
+	else
+		radeon_priv->radeon_fb_delta = 0;
+	return 0;
+}
+
+
+static void radeon_driver_free_filp_priv(drm_device_t *dev, drm_file_t *filp_priv)
+{
+	 struct drm_radeon_driver_file_fields *radeon_priv = filp_priv->driver_priv;
+	 
+	 DRM(free)(radeon_priv, sizeof(*radeon_priv), DRM_MEM_FILES);
+}
+
+void radeon_driver_register_fns(struct drm_device *dev)
+{	
+	dev->driver_features = DRIVER_USE_AGP | DRIVER_USE_MTRR | DRIVER_PCI_DMA | DRIVER_SG | DRIVER_HAVE_IRQ | DRIVER_HAVE_DMA | DRIVER_IRQ_SHARED | DRIVER_IRQ_VBL;
+	dev->dev_priv_size = sizeof(drm_radeon_buf_priv_t);
+	dev->fn_tbl.prerelease = radeon_driver_prerelease;
+	dev->fn_tbl.pretakedown = radeon_driver_pretakedown;
+	dev->fn_tbl.open_helper = radeon_driver_open_helper;
+	dev->fn_tbl.free_filp_priv = radeon_driver_free_filp_priv;
+	dev->fn_tbl.vblank_wait = radeon_driver_vblank_wait;
+ 	dev->fn_tbl.irq_preinstall = radeon_driver_irq_preinstall;
+ 	dev->fn_tbl.irq_postinstall = radeon_driver_irq_postinstall;
+ 	dev->fn_tbl.irq_uninstall = radeon_driver_irq_uninstall;
+ 	dev->fn_tbl.irq_handler = radeon_driver_irq_handler;
 }
diff -Nru a/drivers/char/drm/sis.h b/drivers/char/drm/sis.h
--- a/drivers/char/drm/sis.h	2004-10-18 14:57:04 -07:00
+++ b/drivers/char/drm/sis.h	2004-10-18 14:57:04 -07:00
@@ -41,10 +41,6 @@
 
 /* General customization:
  */
-#define __HAVE_AGP		1
-#define __MUST_HAVE_AGP		0
-#define __HAVE_MTRR		1
-#define __HAVE_CTX_BITMAP	1
 
 #define DRIVER_AUTHOR		"SIS"
 #define DRIVER_NAME		"sis"
@@ -61,18 +57,5 @@
 	[DRM_IOCTL_NR(DRM_IOCTL_SIS_AGP_ALLOC)] = { sis_ioctl_agp_alloc, 1, 0 }, \
 	[DRM_IOCTL_NR(DRM_IOCTL_SIS_AGP_FREE)]	= { sis_ioctl_agp_free,	1, 0 }, \
 	[DRM_IOCTL_NR(DRM_IOCTL_SIS_FB_INIT)]	= { sis_fb_init,	1, 1 }
-
-#define __HAVE_COUNTERS		5
-
-/* Buffer customization:
- */
-#define DRIVER_AGP_BUFFERS_MAP( dev )					\
-	((drm_sis_private_t *)((dev)->dev_private))->buffers
-
-extern int sis_init_context(int context);
-extern int sis_final_context(int context);
-
-#define DRIVER_CTX_CTOR sis_init_context
-#define DRIVER_CTX_DTOR sis_final_context
 
 #endif
diff -Nru a/drivers/char/drm/sis_drv.c b/drivers/char/drm/sis_drv.c
--- a/drivers/char/drm/sis_drv.c	2004-10-18 14:55:53 -07:00
+++ b/drivers/char/drm/sis_drv.c	2004-10-18 14:55:53 -07:00
@@ -31,18 +31,4 @@
 #include "sis_drm.h"
 #include "sis_drv.h"
 
-#include "drm_auth.h"
-#include "drm_agpsupport.h"
-#include "drm_bufs.h"
-#include "drm_context.h"
-#include "drm_dma.h"
-#include "drm_drawable.h"
-#include "drm_drv.h"
-#include "drm_fops.h"
-#include "drm_init.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"
+#include "drm_core.h"
diff -Nru a/drivers/char/drm/sis_drv.h b/drivers/char/drm/sis_drv.h
--- a/drivers/char/drm/sis_drv.h	2004-10-18 14:56:17 -07:00
+++ b/drivers/char/drm/sis_drv.h	2004-10-18 14:56:17 -07:00
@@ -31,8 +31,6 @@
 #include "sis_ds.h"
 
 typedef struct drm_sis_private {
-	drm_map_t *buffers;
-
 	memHeap_t *AGPHeap;
 	memHeap_t *FBHeap;
 } drm_sis_private_t;
diff -Nru a/drivers/char/drm/sis_mm.c b/drivers/char/drm/sis_mm.c
--- a/drivers/char/drm/sis_mm.c	2004-10-18 14:56:48 -07:00
+++ b/drivers/char/drm/sis_mm.c	2004-10-18 14:56:48 -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);
@@ -325,7 +326,7 @@
 	return 0;
 }
 
-int sis_init_context(int context)
+int sis_init_context(struct drm_device *dev, int context)
 {
 	int i;
 
@@ -357,7 +358,7 @@
 	return 1;
 }
 
-int sis_final_context(int context)
+int sis_final_context(struct drm_device *dev, int context)
 {
 	int i;
 
@@ -402,4 +403,11 @@
         }
 	
 	return 1;
+}
+
+void DRM(driver_register_fns)(drm_device_t *dev)
+{
+	dev->driver_features = DRIVER_USE_AGP | DRIVER_USE_MTRR;
+	dev->fn_tbl.context_ctor = sis_init_context;
+	dev->fn_tbl.context_dtor = sis_final_context;
 }
diff -Nru a/drivers/char/drm/tdfx.h b/drivers/char/drm/tdfx.h
--- a/drivers/char/drm/tdfx.h	2004-10-18 14:56:32 -07:00
+++ b/drivers/char/drm/tdfx.h	2004-10-18 14:56:32 -07:00
@@ -36,8 +36,6 @@
 
 /* General customization:
  */
-#define __HAVE_MTRR		1
-#define __HAVE_CTX_BITMAP	1
 
 #define DRIVER_AUTHOR		"VA Linux Systems Inc."
 
diff -Nru a/drivers/char/drm/tdfx_drv.c b/drivers/char/drm/tdfx_drv.c
--- a/drivers/char/drm/tdfx_drv.c	2004-10-18 14:56:32 -07:00
+++ b/drivers/char/drm/tdfx_drv.c	2004-10-18 14:56:32 -07:00
@@ -34,18 +34,10 @@
 #include "tdfx.h"
 #include "drmP.h"
 
-#include "drm_auth.h"
-#include "drm_bufs.h"
-#include "drm_context.h"
-#include "drm_dma.h"
-#include "drm_drawable.h"
-#include "drm_drv.h"
+#include "drm_core.h"
+
+void DRM(driver_register_fns)(drm_device_t *dev)
+{
+	dev->driver_features = DRIVER_USE_MTRR;
+}
 
-#include "drm_fops.h"
-#include "drm_init.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/ds1620.c b/drivers/char/ds1620.c
--- a/drivers/char/ds1620.c	2004-10-18 14:55:54 -07:00
+++ b/drivers/char/ds1620.c	2004-10-18 14:55:54 -07:00
@@ -373,8 +373,7 @@
 	th_start.hi = 1;
 	ds1620_write_state(&th_start);
 
-	set_current_state(TASK_INTERRUPTIBLE);
-	schedule_timeout(2*HZ);
+	msleep(2000);
 
 	ds1620_write_state(&th);
 
diff -Nru a/drivers/char/dsp56k.c b/drivers/char/dsp56k.c
--- a/drivers/char/dsp56k.c	2004-10-18 14:56:32 -07:00
+++ b/drivers/char/dsp56k.c	2004-10-18 14:56:32 -07:00
@@ -58,12 +58,6 @@
 #define DSP56K_TRANSMIT		(dsp56k_host_interface.isr & DSP56K_ISR_TXDE)
 #define DSP56K_RECEIVE		(dsp56k_host_interface.isr & DSP56K_ISR_RXDF)
 
-#define wait_some(n) \
-{ \
-	set_current_state(TASK_INTERRUPTIBLE); \
-	schedule_timeout(n); \
-}
-
 #define handshake(count, maxio, timeout, ENABLE, f) \
 { \
 	long i, t, m; \
@@ -71,13 +65,13 @@
 		m = min_t(unsigned long, count, maxio); \
 		for (i = 0; i < m; i++) { \
 			for (t = 0; t < timeout && !ENABLE; t++) \
-				wait_some(HZ/50); \
+				msleep(20); \
 			if(!ENABLE) \
 				return -EIO; \
 			f; \
 		} \
 		count -= m; \
-		if (m == maxio) wait_some(HZ/50); \
+		if (m == maxio) msleep(20); \
 	} \
 }
 
@@ -85,7 +79,7 @@
 { \
 	int t; \
 	for(t = 0; t < n && !DSP56K_TRANSMIT; t++) \
-		wait_some(HZ/100); \
+		msleep(10); \
 	if(!DSP56K_TRANSMIT) { \
 		return -EIO; \
 	} \
@@ -95,7 +89,7 @@
 { \
 	int t; \
 	for(t = 0; t < n && !DSP56K_RECEIVE; t++) \
-		wait_some(HZ/100); \
+		msleep(10); \
 	if(!DSP56K_RECEIVE) { \
 		return -EIO; \
 	} \
diff -Nru a/drivers/char/ec3104_keyb.c b/drivers/char/ec3104_keyb.c
--- a/drivers/char/ec3104_keyb.c	2004-10-18 14:56:29 -07:00
+++ b/drivers/char/ec3104_keyb.c	2004-10-18 14:56:29 -07:00
@@ -412,7 +412,7 @@
 	k->last_msr = 0;
 
 	for (;;) {
-		schedule_timeout(HZ/10);
+		msleep(100);
 
 		msr = ctrl_inb(EC3104_SER4_MSR);
 	
diff -Nru a/drivers/char/efirtc.c b/drivers/char/efirtc.c
--- a/drivers/char/efirtc.c	2004-10-18 14:56:48 -07:00
+++ b/drivers/char/efirtc.c	2004-10-18 14:56:48 -07:00
@@ -155,7 +155,7 @@
 	efi_time_t	eft;
 	efi_time_cap_t	cap;
 	struct rtc_time	wtime;
-	struct rtc_wkalrm *ewp;
+	struct rtc_wkalrm __user *ewp;
 	unsigned char	enabled, pending;
 
 	switch (cmd) {
@@ -189,13 +189,15 @@
 
 			convert_from_efi_time(&eft, &wtime);
 
- 			return copy_to_user((void *)arg, &wtime, sizeof (struct rtc_time)) ? - EFAULT : 0;
+ 			return copy_to_user((void __user *)arg, &wtime,
+					    sizeof (struct rtc_time)) ? - EFAULT : 0;
 
 		case RTC_SET_TIME:
 
 			if (!capable(CAP_SYS_TIME)) return -EACCES;
 
-			if (copy_from_user(&wtime, (struct rtc_time *)arg, sizeof(struct rtc_time)) )
+			if (copy_from_user(&wtime, (struct rtc_time __user *)arg,
+					   sizeof(struct rtc_time)) )
 				return -EFAULT;
 
 			convert_to_efi_time(&wtime, &eft);
@@ -212,19 +214,19 @@
 
 			if (!capable(CAP_SYS_TIME)) return -EACCES;
 
-			ewp = (struct rtc_wkalrm *)arg;
+			ewp = (struct rtc_wkalrm __user *)arg;
 
 			if (  get_user(enabled, &ewp->enabled)
 			   || copy_from_user(&wtime, &ewp->time, sizeof(struct rtc_time)) )
 				return -EFAULT;
 
 			convert_to_efi_time(&wtime, &eft);
-			
+
 			spin_lock_irqsave(&efi_rtc_lock, flags);
 			/*
 			 * XXX Fixme:
 			 * As of EFI 0.92 with the firmware I have on my
-			 * machine this call does not seem to work quite 
+			 * machine this call does not seem to work quite
 			 * right
 			 */
 			status = efi.set_wakeup_time((efi_bool_t)enabled, &eft);
@@ -243,14 +245,15 @@
 
 			if (status != EFI_SUCCESS) return -EINVAL;
 
-			ewp = (struct rtc_wkalrm *)arg;
+			ewp = (struct rtc_wkalrm __user *)arg;
 
 			if (  put_user(enabled, &ewp->enabled)
 			   || put_user(pending, &ewp->pending)) return -EFAULT;
 
 			convert_from_efi_time(&eft, &wtime);
 
-			return copy_to_user((void *)&ewp->time, &wtime, sizeof(struct rtc_time)) ? -EFAULT : 0;
+			return copy_to_user(&ewp->time, &wtime,
+					    sizeof(struct rtc_time)) ? -EFAULT : 0;
 	}
 	return -EINVAL;
 }
diff -Nru a/drivers/char/epca.c b/drivers/char/epca.c
--- a/drivers/char/epca.c	2004-10-18 14:56:33 -07:00
+++ b/drivers/char/epca.c	2004-10-18 14:56:33 -07:00
@@ -74,7 +74,6 @@
 #define DIGIINFOMAJOR       35  /* For Digi specific ioctl */ 
 
 
-#define MIN(a,b)	((a) < (b) ? (a) : (b))
 #define MAXCARDS 7
 #define epcaassert(x, msg)  if (!(x)) epca_error(__LINE__, msg)
 
@@ -551,9 +550,7 @@
 		if (tty->driver->flush_buffer)
 			tty->driver->flush_buffer(tty);
 
-		if (tty->ldisc.flush_buffer)
-			tty->ldisc.flush_buffer(tty);
-
+		tty_ldisc_flush(tty);
 		shutdown(ch);
 		tty->closing = 0;
 		ch->event = 0;
@@ -657,10 +654,7 @@
 		cli();
 		if (tty->driver->flush_buffer)
 			tty->driver->flush_buffer(tty);
-
-		if (tty->ldisc.flush_buffer)
-			tty->ldisc.flush_buffer(tty);
-
+		tty_ldisc_flush(tty);
 		shutdown(ch);
 
 		ch->tty   = NULL;
@@ -826,7 +820,7 @@
 			bytesAvailable will then take on this newly calculated value.
 		---------------------------------------------------------------------- */
 
-		bytesAvailable = MIN(dataLen, bytesAvailable);
+		bytesAvailable = min(dataLen, bytesAvailable);
 
 		/* First we read the data in from the file system into a temp buffer */
 
@@ -912,7 +906,7 @@
 			space; reduce the amount of data to fit the space.
 	---------------------------------------------------------------------- */
 
-	bytesAvailable = MIN(remain, bytesAvailable);
+	bytesAvailable = min(remain, bytesAvailable);
 
 	txwinon(ch);
 	while (bytesAvailable > 0) 
@@ -923,7 +917,7 @@
 			data copy fills to the end of card buffer.
 		------------------------------------------------------------------- */
 
-		dataLen = MIN(bytesAvailable, dataLen);
+		dataLen = min(bytesAvailable, dataLen);
 		memcpy(ch->txptr + head, buf, dataLen);
 		buf += dataLen;
 		head += dataLen;
@@ -1120,8 +1114,7 @@
 	restore_flags(flags);
 
 	wake_up_interruptible(&tty->write_wait);
-	if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) && tty->ldisc.write_wakeup)
-		(tty->ldisc.write_wakeup)(tty);
+	tty_wakeup(tty);
 
 } /* End pc_flush_buffer */
 
@@ -2262,9 +2255,7 @@
 				{ /* Begin if LOWWAIT */
 
 					ch->statusflags &= ~LOWWAIT;
-					if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
-						  tty->ldisc.write_wakeup)
-						(tty->ldisc.write_wakeup)(tty);
+					tty_wakeup(tty);
 					wake_up_interruptible(&tty->write_wait);
 
 				} /* End if LOWWAIT */
@@ -2281,9 +2272,7 @@
 				{ /* Begin if EMPTYWAIT */
 
 					ch->statusflags &= ~EMPTYWAIT;
-					if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
-						  tty->ldisc.write_wakeup)
-						(tty->ldisc.write_wakeup)(tty);
+					tty_wakeup(tty);
 
 					wake_up_interruptible(&tty->write_wait);
 
@@ -3136,6 +3125,7 @@
 			}
 			else 
 			{
+				/* ldisc lock already held in ioctl */
 				if (tty->ldisc.flush_buffer)
 					tty->ldisc.flush_buffer(tty);
 			}
@@ -3307,7 +3297,6 @@
 		}
 
 	} /* End EPCA_MAGIC */
-	MOD_DEC_USE_COUNT;
 } /* End do_softint */
 
 /* ------------------------------------------------------------
diff -Nru a/drivers/char/esp.c b/drivers/char/esp.c
--- a/drivers/char/esp.c	2004-10-18 14:55:53 -07:00
+++ b/drivers/char/esp.c	2004-10-18 14:55:53 -07:00
@@ -19,7 +19,7 @@
  *
  *  rs_set_termios fixed to look also for changes of the input
  *      flags INPCK, BRKINT, PARMRK, IGNPAR and IGNBRK.
- *                                            Bernd Anhäupl 05/17/96.
+ *                                            Bernd Anhďż˝pl 05/17/96.
  *
  * --- End of notices from serial.c ---
  *
@@ -140,7 +140,7 @@
 
 static void change_speed(struct esp_struct *info);
 static void rs_wait_until_sent(struct tty_struct *, int);
-	
+
 /*
  * The ESP card has a clock rate of 14.7456 MHz (that is, 2**ESPC_SCALE
  * times the normal 1.8432 Mhz clock of most serial boards).
@@ -150,10 +150,6 @@
 /* Standard COM flags (except for COM4, because of the 8514 problem) */
 #define STD_COM_FLAGS (ASYNC_BOOT_AUTOCONF | ASYNC_SKIP_TEST)
 
-#ifndef MIN
-#define MIN(a,b)	((a) < (b) ? (a) : (b))
-#endif
-
 /*
  * tmp_buf is used as a temporary buffer by serial_write.  We need to
  * lock it in case the memcpy_fromfs blocks while swapping in a page,
@@ -762,10 +758,7 @@
 		return;
 
 	if (test_and_clear_bit(ESP_EVENT_WRITE_WAKEUP, &info->event)) {
-		if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
-		    tty->ldisc.write_wakeup)
-			(tty->ldisc.write_wakeup)(tty);
-		wake_up_interruptible(&tty->write_wait);
+		tty_wakeup(tty);
 	}
 }
 
@@ -1370,10 +1363,7 @@
 	cli();
 	info->xmit_cnt = info->xmit_head = info->xmit_tail = 0;
 	sti();
-	wake_up_interruptible(&tty->write_wait);
-	if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
-	    tty->ldisc.write_wakeup)
-		(tty->ldisc.write_wakeup)(tty);
+	tty_wakeup(tty);
 }
 
 /*
@@ -2069,8 +2059,7 @@
 	shutdown(info);
 	if (tty->driver->flush_buffer)
 		tty->driver->flush_buffer(tty);
-	if (tty->ldisc.flush_buffer)
-		tty->ldisc.flush_buffer(tty);
+	tty_ldisc_flush(tty);
 	tty->closing = 0;
 	info->event = 0;
 	info->tty = NULL;
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	2004-10-18 14:56:27 -07:00
+++ b/drivers/char/ftape/lowlevel/ftape-calibr.c	2004-10-18 14:56:27 -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/generic_serial.c b/drivers/char/generic_serial.c
--- a/drivers/char/generic_serial.c	2004-10-18 14:56:32 -07:00
+++ b/drivers/char/generic_serial.c	2004-10-18 14:56:32 -07:00
@@ -436,9 +436,7 @@
 	restore_flags(flags);
 
 	wake_up_interruptible(&tty->write_wait);
-	if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
-	    tty->ldisc.write_wakeup)
-		(tty->ldisc.write_wakeup)(tty);
+	tty_wakeup(tty);
 	func_exit ();
 }
 
@@ -578,9 +576,7 @@
 	if (!tty) return;
 
 	if (test_and_clear_bit(RS_EVENT_WRITE_WAKEUP, &port->event)) {
-		if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
-		    tty->ldisc.write_wakeup)
-			(tty->ldisc.write_wakeup)(tty);
+		tty_wakeup(tty);
 		wake_up_interruptible(&tty->write_wait);
 	}
 	func_exit ();
@@ -694,7 +690,7 @@
 {
 	unsigned long flags;
 	struct gs_port *port;
-
+	
 	func_enter ();
 
 	if (!tty) return;
@@ -760,8 +756,8 @@
 
 	if (tty->driver->flush_buffer)
 		tty->driver->flush_buffer(tty);
-	if (tty->ldisc.flush_buffer)
-		tty->ldisc.flush_buffer(tty);
+		
+	tty_ldisc_flush(tty);
 	tty->closing = 0;
 
 	port->event = 0;
diff -Nru a/drivers/char/hpet.c b/drivers/char/hpet.c
--- a/drivers/char/hpet.c	2004-10-18 14:56:33 -07:00
+++ b/drivers/char/hpet.c	2004-10-18 14:56:33 -07:00
@@ -60,8 +60,8 @@
 
 struct hpet_dev {
 	struct hpets *hd_hpets;
-	struct hpet *hd_hpet;
-	struct hpet_timer *hd_timer;
+	struct hpet __iomem *hd_hpet;
+	struct hpet_timer __iomem *hd_timer;
 	unsigned long hd_ireqfreq;
 	unsigned long hd_irqdata;
 	wait_queue_head_t hd_waitqueue;
@@ -75,7 +75,7 @@
 
 struct hpets {
 	struct hpets *hp_next;
-	struct hpet *hp_hpet;
+	struct hpet __iomem *hp_hpet;
 	unsigned long hp_period;
 	unsigned long hp_delta;
 	unsigned int hp_ntimer;
@@ -98,14 +98,14 @@
 #endif
 
 #ifndef readq
-static unsigned long long __inline readq(void *addr)
+static unsigned long long __inline readq(void __iomem *addr)
 {
 	return readl(addr) | (((unsigned long long)readl(addr + 4)) << 32LL);
 }
 #endif
 
 #ifndef writeq
-static void __inline writeq(unsigned long long v, void *addr)
+static void __inline writeq(unsigned long long v, void __iomem *addr)
 {
 	writel(v & 0xffffffff, addr);
 	writel(v >> 32, addr + 4);
@@ -300,7 +300,7 @@
 static int hpet_release(struct inode *inode, struct file *file)
 {
 	struct hpet_dev *devp;
-	struct hpet_timer *timer;
+	struct hpet_timer __iomem *timer;
 	int irq = 0;
 
 	devp = file->private_data;
@@ -352,8 +352,8 @@
 
 static int hpet_ioctl_ieon(struct hpet_dev *devp)
 {
-	struct hpet_timer *timer;
-	struct hpet *hpet;
+	struct hpet_timer __iomem *timer;
+	struct hpet __iomem *hpet;
 	struct hpets *hpetp;
 	int irq;
 	unsigned long g, v, t, m;
@@ -435,8 +435,8 @@
 static int
 hpet_ioctl_common(struct hpet_dev *devp, int cmd, unsigned long arg, int kernel)
 {
-	struct hpet_timer *timer;
-	struct hpet *hpet;
+	struct hpet_timer __iomem *timer;
+	struct hpet __iomem *hpet;
 	struct hpets *hpetp;
 	int err;
 	unsigned long v;
@@ -547,7 +547,7 @@
 {
 	unsigned int i;
 	u64 mask;
-	struct hpet_timer *timer;
+	struct hpet_timer __iomem *timer;
 	struct hpet_dev *devp;
 	struct hpets *hpetp;
 
@@ -615,7 +615,7 @@
 int hpet_unregister(struct hpet_task *tp)
 {
 	struct hpet_dev *devp;
-	struct hpet_timer *timer;
+	struct hpet_timer __iomem *timer;
 	int err;
 
 	if ((err = hpet_tpcheck(tp)))
@@ -662,40 +662,9 @@
 
 #ifdef	CONFIG_TIME_INTERPOLATION
 
-static unsigned long hpet_offset, last_wall_hpet;
-static long hpet_nsecs_per_cycle, hpet_cycles_per_sec;
-
-static unsigned long hpet_getoffset(void)
-{
-	return hpet_offset + (read_counter(&hpets->hp_hpet->hpet_mc) -
-			      last_wall_hpet) * hpet_nsecs_per_cycle;
-}
-
-static void hpet_update(long delta)
-{
-	unsigned long mc;
-	unsigned long offset;
-
-	mc = read_counter(&hpets->hp_hpet->hpet_mc);
-	offset = hpet_offset + (mc - last_wall_hpet) * hpet_nsecs_per_cycle;
-
-	if (delta < 0 || (unsigned long)delta < offset)
-		hpet_offset = offset - delta;
-	else
-		hpet_offset = 0;
-	last_wall_hpet = mc;
-}
-
-static void hpet_reset(void)
-{
-	hpet_offset = 0;
-	last_wall_hpet = read_counter(&hpets->hp_hpet->hpet_mc);
-}
-
 static struct time_interpolator hpet_interpolator = {
-	.get_offset = hpet_getoffset,
-	.update = hpet_update,
-	.reset = hpet_reset
+	.source = TIME_SOURCE_MMIO64,
+	.shift = 10
 };
 
 #endif
@@ -745,11 +714,11 @@
 
 static unsigned long __init hpet_calibrate(struct hpets *hpetp)
 {
-	struct hpet_timer *timer = NULL;
+	struct hpet_timer __iomem *timer = NULL;
 	unsigned long t, m, count, i, flags, start;
 	struct hpet_dev *devp;
 	int j;
-	struct hpet *hpet;
+	struct hpet __iomem *hpet;
 
 	for (j = 0, devp = hpetp->hp_dev; j < hpetp->hp_ntimer; j++, devp++)
 		if ((devp->hd_flags & HPET_OPEN) == 0) {
@@ -787,8 +756,9 @@
 	u32 i, ntimer;
 	struct hpets *hpetp;
 	size_t siz;
-	struct hpet *hpet;
+	struct hpet __iomem *hpet;
 	static struct hpets *last __initdata = (struct hpets *)0;
+	unsigned long ns;
 
 	/*
 	 * hpet_alloc can be called by platform dependent code.
@@ -796,7 +766,7 @@
 	 * ACPI also reports hpet, then we catch it here.
 	 */
 	for (hpetp = hpets; hpetp; hpetp = hpetp->hp_next)
-		if (hpetp->hp_hpet == (struct hpet *)(hdp->hd_address))
+		if (hpetp->hp_hpet == hdp->hd_address)
 			return 0;
 
 	siz = sizeof(struct hpets) + ((hdp->hd_nirqs - 1) *
@@ -810,7 +780,7 @@
 	memset(hpetp, 0, siz);
 
 	hpetp->hp_which = hpet_nhpet++;
-	hpetp->hp_hpet = (struct hpet *)hdp->hd_address;
+	hpetp->hp_hpet = hdp->hd_address;
 
 	hpetp->hp_ntimer = hdp->hd_nirqs;
 
@@ -840,6 +810,18 @@
 	hpetp->hp_period = (cap & HPET_COUNTER_CLK_PERIOD_MASK) >>
 	    HPET_COUNTER_CLK_PERIOD_SHIFT;
 
+	printk(KERN_INFO "hpet%d: at MMIO 0x%p, IRQ%s",
+		hpetp->hp_which, hpet, hpetp->hp_ntimer > 1 ? "s" : "");
+	for (i = 0; i < hpetp->hp_ntimer; i++)
+		printk("%s %d", i > 0 ? "," : "", hdp->hd_irq[i]);
+	printk("\n");
+
+	ns = hpetp->hp_period;	/* femptoseconds, 10^-15 */
+	do_div(ns, 1000000);	/* convert to nanoseconds, 10^-9 */
+	printk(KERN_INFO "hpet%d: %ldns tick, %d %d-bit timers\n",
+		hpetp->hp_which, ns, hpetp->hp_ntimer,
+		cap & HPET_COUNTER_SIZE_MASK ? 64 : 32);
+
 	mcfg = readq(&hpet->hpet_config);
 	if ((mcfg & HPET_ENABLE_CNF_MASK) == 0) {
 		write_counter(0L, &hpet->hpet_mc);
@@ -850,7 +832,7 @@
 	for (i = 0, devp = hpetp->hp_dev; i < hpetp->hp_ntimer;
 	     i++, hpet_ntimer++, devp++) {
 		unsigned long v;
-		struct hpet_timer *timer;
+		struct hpet_timer __iomem *timer;
 
 		timer = &hpet->hpet_timers[devp - hpetp->hp_dev];
 		v = readq(&timer->hpet_config);
@@ -891,11 +873,10 @@
 		unsigned long size;
 
 		size = addr.max_address_range - addr.min_address_range + 1;
-		hdp->hd_address =
-		    (unsigned long)ioremap(addr.min_address_range, size);
+		hdp->hd_address = ioremap(addr.min_address_range, size);
 
 		for (hpetp = hpets; hpetp; hpetp = hpetp->hp_next)
-			if (hpetp->hp_hpet == (struct hpet *)(hdp->hd_address))
+			if (hpetp->hp_hpet == hdp->hd_address)
 				return -EBUSY;
 	} else if (res->id == ACPI_RSTYPE_EXT_IRQ) {
 		struct acpi_resource_ext_irq *irqp;
@@ -944,9 +925,8 @@
 	return 0;
 }
 
-static struct acpi_driver hpet_acpi_driver __initdata = {
+static struct acpi_driver hpet_acpi_driver = {
 	.name = "hpet",
-	.class = "",
 	.ids = "PNP0103",
 	.ops = {
 		.add = hpet_acpi_add,
@@ -971,11 +951,10 @@
 			struct hpet *hpet;
 
 			hpet = hpets->hp_hpet;
-			hpet_cycles_per_sec = hpet_time_div(hpets->hp_period);
-			hpet_interpolator.frequency = hpet_cycles_per_sec;
-			hpet_interpolator.drift = hpet_cycles_per_sec *
+			hpet_interpolator.addr = &hpets->hp_hpet->hpet_mc;
+			hpet_interpolator.frequency = hpet_time_div(hpets->hp_period);
+			hpet_interpolator.drift = hpet_interpolator.frequency *
 			    HPET_DRIFT / 1000000;
-			hpet_nsecs_per_cycle = 1000000000 / hpet_cycles_per_sec;
 			register_time_interpolator(&hpet_interpolator);
 		}
 #endif
diff -Nru a/drivers/char/hvc_console.c b/drivers/char/hvc_console.c
--- a/drivers/char/hvc_console.c	2004-10-18 14:56:50 -07:00
+++ b/drivers/char/hvc_console.c	2004-10-18 14:56:50 -07:00
@@ -1,6 +1,11 @@
 /*
  * Copyright (C) 2001 Anton Blanchard <anton@au.ibm.com>, IBM
  * Copyright (C) 2001 Paul Mackerras <paulus@au.ibm.com>, IBM
+ * Copyright (C) 2004 Benjamin Herrenschmidt <benh@kernel.crashing.org>, IBM Corp.
+ * Copyright (C) 2004 IBM Corporation
+ *
+ * Additional Author(s):
+ *  Ryan S. Arnold <rsa@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
@@ -17,38 +22,51 @@
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
  */
 
+#include <linux/console.h>
+#include <linux/cpumask.h>
 #include <linux/init.h>
+#include <linux/kbd_kern.h>
+#include <linux/kernel.h>
+#include <linux/kobject.h>
+#include <linux/kthread.h>
+#include <linux/list.h>
 #include <linux/module.h>
-#include <linux/console.h>
 #include <linux/major.h>
-#include <linux/kernel.h>
 #include <linux/sysrq.h>
 #include <linux/tty.h>
 #include <linux/tty_flip.h>
 #include <linux/sched.h>
-#include <linux/kbd_kern.h>
-#include <asm/uaccess.h>
 #include <linux/spinlock.h>
-#include <linux/cpumask.h>
-
-extern int hvc_count(int *);
-extern int hvc_get_chars(int index, char *buf, int count);
-extern int hvc_put_chars(int index, const char *buf, int count);
+#include <asm/uaccess.h>
+#include <asm/hvconsole.h>
+#include <asm/vio.h>
 
 #define HVC_MAJOR	229
 #define HVC_MINOR	0
 
-#define MAX_NR_HVC_CONSOLES	4
-
 #define TIMEOUT		((HZ + 99) / 100)
 
+/*
+ * Wait this long per iteration while trying to push buffered data to the
+ * hypervisor before allowing the tty to complete a close operation.
+ */
+#define HVC_CLOSE_WAIT (HZ/100) /* 1/10 of a second */
+
+/*
+ * The Linux TTY code does not support dynamic addition of tty derived devices
+ * so we need to know how many tty devices we might need when space is allocated
+ * for the tty device.  Since this driver supports hotplug of vty adapters we
+ * need to make sure we have enough allocated.
+ */
+#define HVC_ALLOC_TTY_ADAPTERS	8
+
 static struct tty_driver *hvc_driver;
-static int hvc_offset;
 #ifdef CONFIG_MAGIC_SYSRQ
 static int sysrq_pressed;
 #endif
 
 #define N_OUTBUF	16
+#define N_INBUF		16
 
 #define __ALIGNED__	__attribute__((__aligned__(8)))
 
@@ -60,59 +78,249 @@
 	int do_wakeup;
 	char outbuf[N_OUTBUF] __ALIGNED__;
 	int n_outbuf;
+	uint32_t vtermno;
+	int irq_requested;
+	int irq;
+	struct list_head next;
+	struct kobject kobj; /* ref count & hvc_struct lifetime */
+	struct vio_dev *vdev;
 };
 
-struct hvc_struct hvc_struct[MAX_NR_HVC_CONSOLES];
+/* dynamic list of hvc_struct instances */
+static struct list_head hvc_structs = LIST_HEAD_INIT(hvc_structs);
 
-static int hvc_open(struct tty_struct *tty, struct file * filp)
+/*
+ * Protect the list of hvc_struct instances from inserts and removals during
+ * list traversal.
+ */
+static spinlock_t hvc_structs_lock = SPIN_LOCK_UNLOCKED;
+
+/*
+ * Initial console vtermnos for console API usage prior to full console
+ * initialization.  Any vty adapter outside this range will not have usable
+ * console interfaces but can still be used as a tty device.  This has to be
+ * static because kmalloc will not work during early console init.
+ */
+static uint32_t vtermnos[MAX_NR_HVC_CONSOLES];
+
+/* Used for accounting purposes */
+static int num_vterms = 0;
+
+static struct task_struct *hvc_task;
+
+/*
+ * This value is used to associate a tty->index value to a hvc_struct based
+ * upon order of exposure via hvc_probe().
+ */
+static int hvc_count = -1;
+
+/* Picks up late kicks after list walk but before schedule() */
+static int hvc_kicked;
+
+/* Wake the sleeping khvcd */
+static void hvc_kick(void)
+{
+	hvc_kicked = 1;
+	wake_up_process(hvc_task);
+}
+
+/*
+ * NOTE: This API isn't used if the console adapter doesn't support interrupts.
+ * In this case the console is poll driven.
+ */
+static irqreturn_t hvc_handle_interrupt(int irq, void *dev_instance, struct pt_regs *regs)
+{
+	hvc_kick();
+	return IRQ_HANDLED;
+}
+
+static void hvc_unthrottle(struct tty_struct *tty)
+{
+	hvc_kick();
+}
+
+/*
+ * Do not call this function with either the hvc_strucst_lock or the hvc_struct
+ * lock held.  If successful, this function increments the kobject reference
+ * count against the target hvc_struct so it should be released when finished.
+ */
+struct hvc_struct *hvc_get_by_index(int index)
 {
-	int line = tty->index;
 	struct hvc_struct *hp;
 	unsigned long flags;
 
-	if (line < 0 || line >= MAX_NR_HVC_CONSOLES)
+	spin_lock(&hvc_structs_lock);
+
+	list_for_each_entry(hp, &hvc_structs, next) {
+		spin_lock_irqsave(&hp->lock, flags);
+		if (hp->index == index) {
+			kobject_get(&hp->kobj);
+			spin_unlock_irqrestore(&hp->lock, flags);
+			spin_unlock(&hvc_structs_lock);
+			return hp;
+		}
+		spin_unlock_irqrestore(&hp->lock, flags);
+	}
+	hp = NULL;
+
+	spin_unlock(&hvc_structs_lock);
+	return hp;
+}
+
+/*
+ * The TTY interface won't be used until after the vio layer has exposed the vty
+ * adapter to the kernel.
+ */
+static int hvc_open(struct tty_struct *tty, struct file * filp)
+{
+	struct hvc_struct *hp;
+	unsigned long flags;
+	int irq = NO_IRQ;
+	int rc = 0;
+	struct kobject *kobjp;
+
+	/* Auto increments kobject reference if found. */
+	if (!(hp = hvc_get_by_index(tty->index))) {
+		printk(KERN_WARNING "hvc_console: tty open failed, no vty associated with tty.\n");
 		return -ENODEV;
-	hp = &hvc_struct[line];
+	}
 
-	tty->driver_data = hp;
 	spin_lock_irqsave(&hp->lock, flags);
+	/* Check and then increment for fast path open. */
+	if (hp->count++ > 0) {
+		spin_unlock_irqrestore(&hp->lock, flags);
+		hvc_kick();
+		return 0;
+	} /* else count == 0 */
+
+	tty->driver_data = hp;
 	hp->tty = tty;
-	hp->count++;
+	/* Save for request_irq outside of spin_lock. */
+	irq = hp->irq;
+	if (irq != NO_IRQ)
+		hp->irq_requested = 1;
+
+	kobjp = &hp->kobj;
+
 	spin_unlock_irqrestore(&hp->lock, flags);
+	/* check error, fallback to non-irq */
+	if (irq != NO_IRQ)
+		rc = request_irq(irq, hvc_handle_interrupt, SA_INTERRUPT, "hvc_console", hp);
+
+	/*
+	 * If the request_irq() fails and we return an error.  The tty layer
+	 * will call hvc_close() after a failed open but we don't want to clean
+	 * up there so we'll clean up here and clear out the previously set
+	 * tty fields and return the kobject reference.
+	 */
+	if (rc) {
+		spin_lock_irqsave(&hp->lock, flags);
+		hp->tty = NULL;
+		hp->irq_requested = 0;
+		spin_unlock_irqrestore(&hp->lock, flags);
+		tty->driver_data = NULL;
+		kobject_put(kobjp);
+	}
+	/* Force wakeup of the polling thread */
+	hvc_kick();
 
-	return 0;
+	return rc;
 }
 
 static void hvc_close(struct tty_struct *tty, struct file * filp)
 {
-	struct hvc_struct *hp = tty->driver_data;
+	struct hvc_struct *hp;
+	struct kobject *kobjp;
+	int irq = NO_IRQ;
 	unsigned long flags;
 
 	if (tty_hung_up_p(filp))
 		return;
+
+	/*
+	 * No driver_data means that this close was issued after a failed
+	 * hvcs_open by the tty layer's release_dev() function and we can just
+	 * exit cleanly because the kobject reference wasn't made.
+	 */
+	if (!tty->driver_data)
+		return;
+
+	hp = tty->driver_data;
 	spin_lock_irqsave(&hp->lock, flags);
-	if (--hp->count == 0)
+
+	kobjp = &hp->kobj;
+	if (--hp->count == 0) {
+		if (hp->irq_requested)
+			irq = hp->irq;
+		hp->irq_requested = 0;
+
+		/* We are done with the tty pointer now. */
 		hp->tty = NULL;
-	else if (hp->count < 0)
-		printk(KERN_ERR "hvc_close %lu: oops, count is %d\n",
-		       hp - hvc_struct, hp->count);
-	spin_unlock_irqrestore(&hp->lock, flags);
+		spin_unlock_irqrestore(&hp->lock, flags);
+
+		/*
+		 * Chain calls chars_in_buffer() and returns immediately if
+		 * there is no buffered data otherwise sleeps on a wait queue
+		 * waking periodically to check chars_in_buffer().
+		 */
+		tty_wait_until_sent(tty, HVC_CLOSE_WAIT);
+
+		/*
+		 * Since the line disc doesn't block writes during tty close
+		 * operations we'll set driver_data to NULL and then make sure
+		 * to check tty->driver_data for NULL in hvc_write().
+		 */
+		tty->driver_data = NULL;
+
+		if (irq != NO_IRQ)
+			free_irq(irq, hp);
+
+	} else {
+		if (hp->count < 0)
+			printk(KERN_ERR "hvc_close %X: oops, count is %d\n",
+				hp->vtermno, hp->count);
+		spin_unlock_irqrestore(&hp->lock, flags);
+	}
+
+	kobject_put(kobjp);
 }
 
 static void hvc_hangup(struct tty_struct *tty)
 {
 	struct hvc_struct *hp = tty->driver_data;
+	unsigned long flags;
+	int irq = NO_IRQ;
+	int temp_open_count;
+	struct kobject *kobjp;
 
+	spin_lock_irqsave(&hp->lock, flags);
+	kobjp = &hp->kobj;
+	temp_open_count = hp->count;
 	hp->count = 0;
+	hp->n_outbuf = 0;
 	hp->tty = NULL;
+	if (hp->irq_requested)
+		/* Saved for use outside of spin_lock. */
+		irq = hp->irq;
+	hp->irq_requested = 0;
+	spin_unlock_irqrestore(&hp->lock, flags);
+	if (irq != NO_IRQ)
+		free_irq(irq, hp);
+	while(temp_open_count) {
+		--temp_open_count;
+		kobject_put(kobjp);
+	}
 }
 
-/* called with hp->lock held */
+/*
+ * Push buffered characters whether they were just recently buffered or waiting
+ * on a blocked hypervisor.  Call this function with hp->lock held.
+ */
 static void hvc_push(struct hvc_struct *hp)
 {
 	int n;
 
-	n = hvc_put_chars(hp->index + hvc_offset, hp->outbuf, hp->n_outbuf);
+	n = hvc_put_chars(hp->vtermno, hp->outbuf, hp->n_outbuf);
 	if (n <= 0) {
 		if (n == 0)
 			return;
@@ -127,77 +335,126 @@
 		hp->do_wakeup = 1;
 }
 
-static int hvc_write(struct tty_struct *tty, int from_user,
-		     const unsigned char *buf, int count)
+static inline int __hvc_write_user(struct hvc_struct *hp,
+				   const unsigned char *buf, int count)
 {
-	struct hvc_struct *hp = tty->driver_data;
 	char *tbuf, *p;
 	int tbsize, rsize, written = 0;
 	unsigned long flags;
 
-	if (from_user) {
-		tbsize = min(count, (int)PAGE_SIZE);
-		if (!(tbuf = kmalloc(tbsize, GFP_KERNEL)))
-			return -ENOMEM;
-
-		while ((rsize = count - written) > 0) {
-			int wsize;
-			if (rsize > tbsize)
-				rsize = tbsize;
-
-			p = tbuf;
-			rsize -= copy_from_user(p, buf, rsize);
-			if (!rsize) {
-				if (written == 0)
-					written = -EFAULT;
-				break;
-			}
-			buf += rsize;
-			written += rsize;
-
-			spin_lock_irqsave(&hp->lock, flags);
-			for (wsize = N_OUTBUF - hp->n_outbuf; rsize && wsize;
-					wsize = N_OUTBUF - hp->n_outbuf) {
-				if (wsize > rsize)
-					wsize = rsize;
-				memcpy(hp->outbuf + hp->n_outbuf, p, wsize);
-				hp->n_outbuf += wsize;
-				hvc_push(hp);
-				rsize -= wsize;
-				p += wsize;
-			}
-			spin_unlock_irqrestore(&hp->lock, flags);
-
-			if (rsize)
-				break;
+	tbsize = min(count, (int)PAGE_SIZE);
+	if (!(tbuf = kmalloc(tbsize, GFP_KERNEL)))
+		return -ENOMEM;
 
-			if (count < tbsize)
-				tbsize = count;
+	while ((rsize = count - written) > 0) {
+		int wsize;
+		if (rsize > tbsize)
+			rsize = tbsize;
+
+		p = tbuf;
+		rsize -= copy_from_user(p, buf, rsize);
+		if (!rsize) {
+			if (written == 0)
+				written = -EFAULT;
+			break;
 		}
+		buf += rsize;
 
-		kfree(tbuf);
-	} else {
 		spin_lock_irqsave(&hp->lock, flags);
-		while (count > 0 && (rsize = N_OUTBUF - hp->n_outbuf) > 0) {
-			if (rsize > count)
-				rsize = count;
-			memcpy(hp->outbuf + hp->n_outbuf, buf, rsize);
-			count -= rsize;
-			buf += rsize;
-			hp->n_outbuf += rsize;
-			written += rsize;
+
+		/* Push pending writes: make some room in buffer */
+		if (hp->n_outbuf > 0)
+			hvc_push(hp);
+
+		for (wsize = N_OUTBUF - hp->n_outbuf; rsize && wsize;
+		     wsize = N_OUTBUF - hp->n_outbuf) {
+			if (wsize > rsize)
+				wsize = rsize;
+			memcpy(hp->outbuf + hp->n_outbuf, p, wsize);
+			hp->n_outbuf += wsize;
 			hvc_push(hp);
+			rsize -= wsize;
+			p += wsize;
+			written += wsize;
 		}
 		spin_unlock_irqrestore(&hp->lock, flags);
+
+		if (rsize)
+			break;
+
+		if (count < tbsize)
+			tbsize = count;
 	}
 
+	kfree(tbuf);
+
 	return written;
 }
 
+static inline int __hvc_write_kernel(struct hvc_struct *hp,
+				   const unsigned char *buf, int count)
+{
+	unsigned long flags;
+	int rsize, written = 0;
+
+	spin_lock_irqsave(&hp->lock, flags);
+
+	/* Push pending writes */
+	if (hp->n_outbuf > 0)
+		hvc_push(hp);
+
+	while (count > 0 && (rsize = N_OUTBUF - hp->n_outbuf) > 0) {
+		if (rsize > count)
+			rsize = count;
+		memcpy(hp->outbuf + hp->n_outbuf, buf, rsize);
+		count -= rsize;
+		buf += rsize;
+		hp->n_outbuf += rsize;
+		written += rsize;
+		hvc_push(hp);
+	}
+	spin_unlock_irqrestore(&hp->lock, flags);
+
+	return written;
+}
+static int hvc_write(struct tty_struct *tty, int from_user,
+		     const unsigned char *buf, int count)
+{
+	struct hvc_struct *hp = tty->driver_data;
+	int written;
+
+	/* This write was probably executed during a tty close. */
+	if (!hp)
+		return -EPIPE;
+
+	if (from_user)
+		written = __hvc_write_user(hp, buf, count);
+	else
+		written = __hvc_write_kernel(hp, buf, count);
+
+	/*
+	 * Racy, but harmless, kick thread if there is still pending data.
+	 * There really is nothing wrong with kicking the thread, even if there
+	 * is no buffered data.
+	 */
+	if (hp->n_outbuf)
+		hvc_kick();
+
+	return written;
+}
+
+/*
+ * This is actually a contract between the driver and the tty layer outlining
+ * how much write room the driver can guarentee will be sent OR BUFFERED.  This
+ * driver MUST honor the return value.
+ */
 static int hvc_write_room(struct tty_struct *tty)
 {
 	struct hvc_struct *hp = tty->driver_data;
 
+	if (!hp)
+		return -1;
+
 	return N_OUTBUF - hp->n_outbuf;
 }
 
@@ -205,57 +462,108 @@
 {
 	struct hvc_struct *hp = tty->driver_data;
 
+	if (!hp)
+		return -1;
 	return hp->n_outbuf;
 }
 
-static void hvc_poll(int index)
+#define HVC_POLL_READ	0x00000001
+#define HVC_POLL_WRITE	0x00000002
+#define HVC_POLL_QUICK	0x00000004
+
+static int hvc_poll(struct hvc_struct *hp)
 {
-	struct hvc_struct *hp = &hvc_struct[index];
 	struct tty_struct *tty;
-	int i, n;
-	char buf[16] __ALIGNED__;
+	int i, n, poll_mask = 0;
+	char buf[N_INBUF] __ALIGNED__;
 	unsigned long flags;
+	int read_total = 0;
 
 	spin_lock_irqsave(&hp->lock, flags);
 
+	/* Push pending writes */
 	if (hp->n_outbuf > 0)
 		hvc_push(hp);
+	/* Reschedule us if still some write pending */
+	if (hp->n_outbuf > 0)
+		poll_mask |= HVC_POLL_WRITE;
 
+	/* No tty attached, just skip */
 	tty = hp->tty;
-	if (tty) {
-		for (;;) {
-			if (TTY_FLIPBUF_SIZE - tty->flip.count < sizeof(buf))
-				break;
-			n = hvc_get_chars(index + hvc_offset, buf, sizeof(buf));
-			if (n <= 0)
-				break;
-			for (i = 0; i < n; ++i) {
-#ifdef CONFIG_MAGIC_SYSRQ		/* Handle the SysRq Hack */
-				if (buf[i] == '\x0f') {	/* ^O -- should support a sequence */
-					sysrq_pressed = 1;
-					continue;
-				} else if (sysrq_pressed) {
-					handle_sysrq(buf[i], NULL, tty);
-					sysrq_pressed = 0;
-					continue;
-				}
-#endif
-				tty_insert_flip_char(tty, buf[i], 0);
+	if (tty == NULL)
+		goto bail;
+
+	/* Now check if we can get data (are we throttled ?) */
+	if (test_bit(TTY_THROTTLED, &tty->flags))
+		goto throttled;
+
+	/* If we aren't interrupt driven and aren't throttled, we always
+	 * request a reschedule
+	 */
+	if (hp->irq == NO_IRQ)
+		poll_mask |= HVC_POLL_READ;
+
+	/* Read data if any */
+	for (;;) {
+		int count = N_INBUF;
+		if (count > (TTY_FLIPBUF_SIZE - tty->flip.count))
+			count = TTY_FLIPBUF_SIZE - tty->flip.count;
+
+		/* If flip is full, just reschedule a later read */
+		if (count == 0) {
+			poll_mask |= HVC_POLL_READ;
+			break;
+		}
+
+		n = hvc_get_chars(hp->vtermno, buf, count);
+		if (n <= 0) {
+			/* Hangup the tty when disconnected from host */
+			if (n == -EPIPE) {
+				spin_unlock_irqrestore(&hp->lock, flags);
+				tty_hangup(tty);
+				spin_lock_irqsave(&hp->lock, flags);
+			}
+			break;
+		}
+		for (i = 0; i < n; ++i) {
+#ifdef CONFIG_MAGIC_SYSRQ
+			/* Handle the SysRq Hack */
+			if (buf[i] == '\x0f') {	/* ^O -- should support a sequence */
+				sysrq_pressed = 1;
+				continue;
+			} else if (sysrq_pressed) {
+				handle_sysrq(buf[i], NULL, tty);
+				sysrq_pressed = 0;
+				continue;
 			}
+#endif /* CONFIG_MAGIC_SYSRQ */
+			tty_insert_flip_char(tty, buf[i], 0);
 		}
+
 		if (tty->flip.count)
 			tty_schedule_flip(tty);
 
-		if (hp->do_wakeup) {
-			hp->do_wakeup = 0;
-			if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP))
-			    && tty->ldisc.write_wakeup)
-				(tty->ldisc.write_wakeup)(tty);
-			wake_up_interruptible(&tty->write_wait);
+		/*
+		 * Account for the total amount read in one loop, and if above
+		 * 64 bytes, we do a quick schedule loop to let the tty grok the
+		 * data and eventually throttle us.
+		 */
+		read_total += n;
+		if (read_total >= 64) {
+			poll_mask |= HVC_POLL_QUICK;
+			break;
 		}
 	}
-
+ throttled:
+	/* Wakeup write queue if necessary */
+	if (hp->do_wakeup) {
+		hp->do_wakeup = 0;
+		tty_wakeup(tty);
+	}
+ bail:
 	spin_unlock_irqrestore(&hp->lock, flags);
+
+	return poll_mask;
 }
 
 #if defined(CONFIG_XMON) && defined(CONFIG_SMP)
@@ -264,21 +572,47 @@
 static const cpumask_t cpus_in_xmon = CPU_MASK_NONE;
 #endif
 
-
+/*
+ * This kthread is either polling or interrupt driven.  This is determined by
+ * calling hvc_poll() who determines whether a console adapter support
+ * interrupts.
+ */
 int khvcd(void *unused)
 {
-	int i;
-
-	daemonize("khvcd");
+	int poll_mask;
+	struct hvc_struct *hp;
 
-	for (;;) {
+	__set_current_state(TASK_RUNNING);
+	do {
+		poll_mask = 0;
+		hvc_kicked = 0;
+		wmb();
 		if (cpus_empty(cpus_in_xmon)) {
-			for (i = 0; i < MAX_NR_HVC_CONSOLES; ++i)
-				hvc_poll(i);
+			spin_lock(&hvc_structs_lock);
+			list_for_each_entry(hp, &hvc_structs, next) {
+				/*hp = list_entry(node, struct hvc_struct, * next); */
+				poll_mask |= hvc_poll(hp);
+			}
+			spin_unlock(&hvc_structs_lock);
+		} else
+			poll_mask |= HVC_POLL_READ;
+		if (hvc_kicked)
+			continue;
+		if (poll_mask & HVC_POLL_QUICK) {
+			yield();
+			continue;
 		}
 		set_current_state(TASK_INTERRUPTIBLE);
-		schedule_timeout(TIMEOUT);
-	}
+		if (!hvc_kicked) {
+			if (poll_mask == 0)
+				schedule();
+			else
+				schedule_timeout(TIMEOUT);
+		}
+		__set_current_state(TASK_RUNNING);
+	} while (!kthread_should_stop());
+
+	return 0;
 }
 
 static struct tty_operations hvc_ops = {
@@ -286,19 +620,124 @@
 	.close = hvc_close,
 	.write = hvc_write,
 	.hangup = hvc_hangup,
+	.unthrottle = hvc_unthrottle,
 	.write_room = hvc_write_room,
 	.chars_in_buffer = hvc_chars_in_buffer,
 };
 
-int __init hvc_init(void)
+char hvc_driver_name[] = "hvc_console";
+
+static struct vio_device_id hvc_driver_table[] __devinitdata= {
+	{"serial", "hvterm1"},
+	{ 0, }
+};
+MODULE_DEVICE_TABLE(vio, hvc_driver_table);
+
+/* callback when the kboject ref count reaches zero. */
+static void destroy_hvc_struct(struct kobject *kobj)
 {
-	int num = hvc_count(&hvc_offset);
-	int i;
+	struct hvc_struct *hp = container_of(kobj, struct hvc_struct, kobj);
+	unsigned long flags;
 
-	if (num > MAX_NR_HVC_CONSOLES)
-		num = MAX_NR_HVC_CONSOLES;
+	spin_lock(&hvc_structs_lock);
 
-	hvc_driver = alloc_tty_driver(num);
+	spin_lock_irqsave(&hp->lock, flags);
+	list_del(&(hp->next));
+	spin_unlock_irqrestore(&hp->lock, flags);
+
+	spin_unlock(&hvc_structs_lock);
+
+	kfree(hp);
+}
+
+static struct kobj_type hvc_kobj_type = {
+	.release = destroy_hvc_struct,
+};
+
+static int __devinit hvc_probe(
+		struct vio_dev *dev,
+		const struct vio_device_id *id)
+{
+	struct hvc_struct *hp;
+
+	/* probed with invalid parameters. */
+	if (!dev || !id)
+		return -EPERM;
+
+	hp = kmalloc(sizeof(*hp), GFP_KERNEL);
+	if (!hp)
+		return -ENOMEM;
+
+	memset(hp, 0x00, sizeof(*hp));
+	hp->vtermno = dev->unit_address;
+	hp->vdev = dev;
+	hp->vdev->dev.driver_data = hp;
+	hp->irq = dev->irq;
+
+	kobject_init(&hp->kobj);
+	hp->kobj.ktype = &hvc_kobj_type;
+
+	hp->lock = SPIN_LOCK_UNLOCKED;
+	spin_lock(&hvc_structs_lock);
+	hp->index = ++hvc_count;
+	list_add_tail(&(hp->next), &hvc_structs);
+	spin_unlock(&hvc_structs_lock);
+
+	return 0;
+}
+
+static int __devexit hvc_remove(struct vio_dev *dev)
+{
+	struct hvc_struct *hp = dev->dev.driver_data;
+	unsigned long flags;
+	struct kobject *kobjp;
+	struct tty_struct *tty;
+
+	spin_lock_irqsave(&hp->lock, flags);
+	tty = hp->tty;
+	kobjp = &hp->kobj;
+
+	if (hp->index < MAX_NR_HVC_CONSOLES)
+		vtermnos[hp->index] = -1;
+
+	/* Don't whack hp->irq because tty_hangup() will need to free the irq. */
+
+	spin_unlock_irqrestore(&hp->lock, flags);
+
+	/*
+	 * We 'put' the instance that was grabbed when the kobject instance
+	 * was intialized using kobject_init().  Let the last holder of this
+	 * kobject cause it to be removed, which will probably be the tty_hangup
+	 * below.
+	 */
+	kobject_put(kobjp);
+
+	/*
+	 * This function call will auto chain call hvc_hangup.  The tty should
+	 * always be valid at this time unless a simultaneous tty close already
+	 * cleaned up the hvc_struct.
+	 */
+	if (tty)
+		tty_hangup(tty);
+	return 0;
+}
+
+static struct vio_driver hvc_vio_driver = {
+	.name		= hvc_driver_name,
+	.id_table	= hvc_driver_table,
+	.probe		= hvc_probe,
+	.remove		= hvc_remove,
+};
+
+/* Driver initialization.  Follow console initialization.  This is where the TTY
+ * interfaces start to become available. */
+int __init hvc_init(void)
+{
+	int rc;
+
+	/* We need more than num_vterms adapters due to hotplug additions. */
+	hvc_driver = alloc_tty_driver(HVC_ALLOC_TTY_ADAPTERS);
+	/* hvc_driver = alloc_tty_driver(num_vterms); */
 	if (!hvc_driver)
 		return -ENOMEM;
 
@@ -312,31 +751,73 @@
 	hvc_driver->init_termios = tty_std_termios;
 	hvc_driver->flags = TTY_DRIVER_REAL_RAW;
 	tty_set_operations(hvc_driver, &hvc_ops);
-	for (i = 0; i < num; i++) {
-		hvc_struct[i].lock = SPIN_LOCK_UNLOCKED;
-		hvc_struct[i].index = i;
-	}
 
 	if (tty_register_driver(hvc_driver))
 		panic("Couldn't register hvc console driver\n");
 
-	if (num > 0)
-		kernel_thread(khvcd, NULL, CLONE_KERNEL);
+	/* Always start the kthread because there can be hotplug vty adapters
+	 * added later. */
+	hvc_task = kthread_run(khvcd, NULL, "khvcd");
+	if (IS_ERR(hvc_task)) {
+		panic("Couldn't create kthread for console.\n");
+		put_tty_driver(hvc_driver);
+		return -EIO;
+	}
 
-	return 0;
+	/* Register as a vio device to receive callbacks */
+	rc = vio_register_driver(&hvc_vio_driver);
+
+	return rc;
 }
 
+/* This isn't particularily necessary due to this being a console driver but it
+ * is nice to be thorough */
 static void __exit hvc_exit(void)
 {
+	kthread_stop(hvc_task);
+
+	vio_unregister_driver(&hvc_vio_driver);
+	tty_unregister_driver(hvc_driver);
+	/* return tty_struct instances allocated in hvc_init(). */
+	put_tty_driver(hvc_driver);
+}
+
+/*
+ * Console APIs, NOT TTY.  These APIs are available immediately when
+ * hvc_console_setup() finds adapters.
+ */
+
+/*
+ * hvc_instantiate() is an early console discovery method which locates consoles
+ * prior to the vio subsystem discovering them.  Hotplugged vty adapters do NOT
+ * get an hvc_instantiate() callback since the appear after early console init.
+ */
+int hvc_instantiate(uint32_t vtermno, int index)
+{
+	if (index < 0 || index >= MAX_NR_HVC_CONSOLES)
+		return -1;
+
+	if (vtermnos[index] != -1)
+		return -1;
+
+	vtermnos[index] = vtermno;
+	return 0;
 }
 
 void hvc_console_print(struct console *co, const char *b, unsigned count)
 {
 	char c[16] __ALIGNED__;
-	unsigned i, n;
+	unsigned i = 0, n = 0;
 	int r, donecr = 0;
 
-	i = n = 0;
+	/* Console access attempt outside of acceptable console range. */
+	if (co->index >= MAX_NR_HVC_CONSOLES)
+		return;
+
+	/* This console adapter was removed so it is not useable. */
+	if (vtermnos[co->index] < 0)
+		return;
+
 	while (count > 0 || i > 0) {
 		if (count > 0 && i < sizeof(c)) {
 			if (b[n] == '\n' && !donecr) {
@@ -348,7 +829,7 @@
 				--count;
 			}
 		} else {
-			r = hvc_put_chars(co->index + hvc_offset, c, i);
+			r = hvc_put_chars(vtermnos[co->index], c, i);
 			if (r < 0) {
 				/* throw away chars on error */
 				i = 0;
@@ -369,9 +850,6 @@
 
 static int __init hvc_console_setup(struct console *co, char *options)
 {
-	if (co->index < 0 || co->index >= MAX_NR_HVC_CONSOLES
-	    || co->index >= hvc_count(&hvc_offset))
-		return -1;
 	return 0;
 }
 
@@ -384,8 +862,14 @@
 	.index		= -1,
 };
 
+/* Early console initialization.  Preceeds driver initialization. */
 static int __init hvc_console_init(void)
 {
+	int i;
+
+	for (i=0; i<MAX_NR_HVC_CONSOLES; i++)
+		vtermnos[i] = -1;
+	num_vterms = hvc_find_vtys();
 	register_console(&hvc_con_driver);
 	return 0;
 }
diff -Nru a/drivers/char/hvcs.c b/drivers/char/hvcs.c
--- a/drivers/char/hvcs.c	2004-10-18 14:56:33 -07:00
+++ b/drivers/char/hvcs.c	2004-10-18 14:56:33 -07:00
@@ -88,31 +88,47 @@
 #include <asm/vio.h>
 
 /*
- * 1.0.0 -> 1.1.0 Added kernel_thread scheduling methodology to driver to
- * replace wait_task constructs.
+ * 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
+ * list_for_each_safe() and replaced with list_for_each_entry() in
+ * hvcs_get_by_index().  The 'safe' version is un-needed now that the driver is
+ * using spinlocks.  Changed spin_lock_irqsave() to spin_lock() when locking
+ * hvcs_structs_lock and hvcs_pi_lock since these are not touched in an int
+ * handler.  Initialized hvcs_structs_lock and hvcs_pi_lock to
+ * 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.  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.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.
+ * 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.
  *
- * 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.2 -> 1.3.3 Replaced yield() in hvcs_close() with tty_wait_until_sent() to
+ * prevent possible lockup with realtime scheduling as similarily pointed out by
+ * akpm in hvc_console.  Changed resulted in the removal of hvcs_final_close()
+ * to reorder cleanup operations and prevent discarding of pending data during
+ * an hvcs_close().  Removed spinlock protection of hvcs_struct data members in
+ * hvcs_write_room() and hvcs_chars_in_buffer() because they aren't needed.
  */
-#define HVCS_DRIVER_VERSION "1.3.0"
+
+#define HVCS_DRIVER_VERSION "1.3.3"
 
 MODULE_AUTHOR("Ryan S. Arnold <rsa@us.ibm.com>");
 MODULE_DESCRIPTION("IBM hvcs (Hypervisor Virtual Console Server) Driver");
@@ -120,6 +136,12 @@
 MODULE_VERSION(HVCS_DRIVER_VERSION);
 
 /*
+ * Wait this long per iteration while trying to push buffered data to the
+ * hypervisor before allowing the tty to complete a close operation.
+ */
+#define HVCS_CLOSE_WAIT (HZ/100) /* 1/10 of a second */
+
+/*
  * Since the Linux TTY code does not currently (2-04-2004) support dynamic
  * addition of tty derived devices and we shouldn't allocate thousands of
  * tty_device pointers when the number of vty-server & vty partner connections
@@ -138,9 +160,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
 
@@ -152,9 +174,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.
@@ -194,27 +213,41 @@
 	= "IBM hvcs (Hypervisor Virtual Console Server) Driver";
 
 /* Status of partner info rescan triggered via sysfs. */
-static int hvcs_rescan_status = 0;
+static int hvcs_rescan_status;
 
 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_index_list;
+
+/*
+ * How large is the list?  This is kept for traversal since the list is
+ * dynamically created.
  */
-static int hvcs_struct_count = -1;
+static int hvcs_index_count;
 
 /*
  * Used by the khvcsd to pick up I/O operations when the kernel_thread is
  * already awake but potentially shifted to TASK_INTERRUPTIBLE state.
  */
-static int hvcs_kicked = 0;
+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;
 
 /*
@@ -223,7 +256,8 @@
  */
 static unsigned long *hvcs_pi_buff;
 
-static spinlock_t hvcs_pi_lock;
+/* 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 */
 struct hvcs_struct {
@@ -263,9 +297,9 @@
 	 */
 	struct kobject kobj; /* ref count & hvcs_struct lifetime */
 	int connected; /* is the vty-server currently connected to a vty? */
-	unsigned int p_unit_address; /* partner unit address */
-	unsigned int p_partition_ID; /* partner partition ID */
-	char p_location_code[CLC_LENGTH];
+	uint32_t p_unit_address; /* partner unit address */
+	uint32_t p_partition_ID; /* partner partition ID */
+	char p_location_code[HVCS_CLC_LENGTH + 1]; /* CLC + Null Term */
 	struct list_head next; /* list management */
 	struct vio_dev *vdev;
 };
@@ -274,7 +308,7 @@
 #define from_kobj(kobj) container_of(kobj, struct hvcs_struct, kobj)
 
 static struct list_head hvcs_structs = LIST_HEAD_INIT(hvcs_structs);
-static spinlock_t hvcs_structs_lock;
+static spinlock_t hvcs_structs_lock = SPIN_LOCK_UNLOCKED;
 
 static void hvcs_unthrottle(struct tty_struct *tty);
 static void hvcs_throttle(struct tty_struct *tty);
@@ -297,7 +331,6 @@
 
 static int hvcs_enable_device(struct hvcs_struct *hvcsd,
 		uint32_t unit_address, unsigned int irq, struct vio_dev *dev);
-static void hvcs_final_close(struct hvcs_struct *hvcsd);
 
 static void destroy_hvcs_struct(struct kobject *kobj);
 static int hvcs_open(struct tty_struct *tty, struct file *filp);
@@ -357,12 +390,11 @@
 		struct pt_regs *regs)
 {
 	struct hvcs_struct *hvcsd = dev_instance;
-	unsigned long flags;
 
-	spin_lock_irqsave(&hvcsd->lock, flags);
+	spin_lock(&hvcsd->lock);
 	vio_disable_interrupts(hvcsd->vdev);
 	hvcsd->todo_mask |= HVCS_SCHED_READ;
-	spin_unlock_irqrestore(&hvcsd->lock, flags);
+	spin_unlock(&hvcsd->lock);
 	hvcs_kick();
 
 	return IRQ_HANDLED;
@@ -371,7 +403,7 @@
 /* This function must be called with the hvcsd->lock held */
 static void hvcs_try_write(struct hvcs_struct *hvcsd)
 {
-	unsigned int unit_address = hvcsd->vdev->unit_address;
+	uint32_t unit_address = hvcsd->vdev->unit_address;
 	struct tty_struct *tty = hvcsd->tty;
 	int sent;
 
@@ -382,9 +414,9 @@
 				hvcsd->chars_in_buffer );
 		if (sent > 0) {
 			hvcsd->chars_in_buffer = 0;
-			wmb();
+			/* wmb(); */
 			hvcsd->todo_mask &= ~(HVCS_TRY_WRITE);
-			wmb();
+			/* wmb(); */
 
 			/*
 			 * We are still obligated to deliver the data to the
@@ -393,10 +425,7 @@
 			 * a non-existent tty.
 			 */
 			if (tty) {
-				if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP))
-						&& tty->ldisc.write_wakeup)
-					(tty->ldisc.write_wakeup) (tty);
-				wake_up_interruptible(&tty->write_wait);
+				tty_wakeup(tty);
 			}
 		}
 	}
@@ -404,11 +433,11 @@
 
 static int hvcs_io(struct hvcs_struct *hvcsd)
 {
-	unsigned int unit_address;
+	uint32_t unit_address;
 	struct tty_struct *tty;
 	char buf[HVCS_BUFF_LEN] __ALIGNED__;
 	unsigned long flags;
-	int got;
+	int got = 0;
 	int i;
 
 	spin_lock_irqsave(&hvcsd->lock, flags);
@@ -461,11 +490,8 @@
 
 static int khvcsd(void *unused)
 {
-	struct hvcs_struct *hvcsd = NULL;
-	struct list_head *element;
-	struct list_head *safe_temp;
+	struct hvcs_struct *hvcsd;
 	int hvcs_todo_mask;
-	unsigned long structs_flags;
 
 	__set_current_state(TASK_RUNNING);
 
@@ -474,12 +500,11 @@
 		hvcs_kicked = 0;
 		wmb();
 
-		spin_lock_irqsave(&hvcs_structs_lock, structs_flags);
-		list_for_each_safe(element, safe_temp, &hvcs_structs) {
-			hvcsd = list_entry(element, struct hvcs_struct, next);
-				hvcs_todo_mask |= hvcs_io(hvcsd);
+		spin_lock(&hvcs_structs_lock);
+		list_for_each_entry(hvcsd, &hvcs_structs, next) {
+			hvcs_todo_mask |= hvcs_io(hvcsd);
 		}
-		spin_unlock_irqrestore(&hvcs_structs_lock, structs_flags);
+		spin_unlock(&hvcs_structs_lock);
 
 		/*
 		 * If any of the hvcs adapters want to try a write or quick read
@@ -506,6 +531,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)
 {
@@ -513,6 +551,7 @@
 	struct vio_dev *vdev;
 	unsigned long flags;
 
+	spin_lock(&hvcs_structs_lock);
 	spin_lock_irqsave(&hvcsd->lock, flags);
 
 	/* the list_del poisons the pointers */
@@ -524,7 +563,7 @@
 				" partner vty@%X:%d connection.\n",
 				hvcsd->vdev->unit_address,
 				hvcsd->p_unit_address,
-				(unsigned int)hvcsd->p_partition_ID);
+				(uint32_t)hvcsd->p_partition_ID);
 	}
 	printk(KERN_INFO "HVCS: Destroyed hvcs_struct for vty-server@%X.\n",
 			hvcsd->vdev->unit_address);
@@ -534,55 +573,60 @@
 
 	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);
 
 	hvcs_remove_device_attrs(vdev);
 
 	kfree(hvcsd);
 }
 
-/* This function must be called with hvcsd->lock 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;
-
-	/* These two may be redundant if the operation was a close. */
-	if (hvcsd->tty) {
-		hvcsd->tty->driver_data = NULL;
-		hvcsd->tty = NULL;
-	}
-
-	hvcsd->open_count = 0;
-
-	memset(&hvcsd->buffer[0], 0x00, HVCS_BUFF_LEN);
-	hvcsd->chars_in_buffer = 0;
-}
-
 static struct kobj_type hvcs_kobj_type = {
 	.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;
-	unsigned long structs_flags;
+	int index;
 
 	if (!dev || !id) {
 		printk(KERN_ERR "HVCS: probed with invalid parameter.\n");
 		return -EPERM;
 	}
 
+	/* early to avoid cleanup on failure */
+	index = hvcs_get_index();
+	if (index < 0) {
+		return -EFAULT;
+	}
+
 	hvcsd = kmalloc(sizeof(*hvcsd), GFP_KERNEL);
-	if (!hvcsd) {
+	if (!hvcsd)
 		return -ENODEV;
-	}
 
 	/* hvcsd->tty is zeroed out with the memset */
 	memset(hvcsd, 0x00, sizeof(*hvcsd));
@@ -596,7 +640,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;
@@ -617,15 +663,15 @@
 	 * will get -ENODEV.
 	 */
 
-	spin_lock_irqsave(&hvcs_structs_lock, structs_flags);
+	spin_lock(&hvcs_structs_lock);
 
 	list_add_tail(&(hvcsd->next), &hvcs_structs);
 
-	spin_unlock_irqrestore(&hvcs_structs_lock, structs_flags);
+	spin_unlock(&hvcs_structs_lock);
 
 	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
@@ -688,8 +734,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],
@@ -711,20 +757,18 @@
  */
 static int hvcs_get_pi(struct hvcs_struct *hvcsd)
 {
-	/* struct hvcs_partner_info *head_pi = NULL; */
-	struct hvcs_partner_info *pi = NULL;
-	unsigned int unit_address = hvcsd->vdev->unit_address;
+	struct hvcs_partner_info *pi;
+	uint32_t unit_address = hvcsd->vdev->unit_address;
 	struct list_head head;
-	unsigned long flags;
 	int retval;
 
-	spin_lock_irqsave(&hvcs_pi_lock, flags);
+	spin_lock(&hvcs_pi_lock);
 	if (!hvcs_pi_buff) {
-		spin_unlock_irqrestore(&hvcs_pi_lock, flags);
+		spin_unlock(&hvcs_pi_lock);
 		return -EFAULT;
 	}
 	retval = hvcs_get_partner_info(unit_address, &head, hvcs_pi_buff);
-	spin_unlock_irqrestore(&hvcs_pi_lock, flags);
+	spin_unlock(&hvcs_pi_lock);
 	if (retval) {
 		printk(KERN_ERR "HVCS: Failed to fetch partner"
 			" info for vty-server@%x.\n", unit_address);
@@ -748,11 +792,10 @@
  */
 static int hvcs_rescan_devices_list(void)
 {
-	struct hvcs_struct *hvcsd = NULL;
+	struct hvcs_struct *hvcsd;
 	unsigned long flags;
-	unsigned long structs_flags;
 
-	spin_lock_irqsave(&hvcs_structs_lock, structs_flags);
+	spin_lock(&hvcs_structs_lock);
 
 	list_for_each_entry(hvcsd, &hvcs_structs, next) {
 		spin_lock_irqsave(&hvcsd->lock, flags);
@@ -760,7 +803,7 @@
 		spin_unlock_irqrestore(&hvcsd->lock, flags);
 	}
 
-	spin_unlock_irqrestore(&hvcs_structs_lock, structs_flags);
+	spin_unlock(&hvcs_structs_lock);
 
 	return 0;
 }
@@ -848,13 +891,14 @@
 		unsigned int irq, struct vio_dev *vdev)
 {
 	unsigned long flags;
+	int rc;
 
 	/*
 	 * It is possible that the vty-server was removed between the time that
 	 * the conn was registered and now.
 	 */
-	if (!request_irq(irq, &hvcs_handle_interrupt,
-				SA_INTERRUPT, "ibmhvcs", hvcsd)) {
+	if (!(rc = request_irq(irq, &hvcs_handle_interrupt,
+				SA_INTERRUPT, "ibmhvcs", hvcsd))) {
 		/*
 		 * It is possible the vty-server was removed after the irq was
 		 * requested but before we have time to enable interrupts.
@@ -874,7 +918,7 @@
 	hvcs_partner_free(hvcsd);
 	spin_unlock_irqrestore(&hvcsd->lock, flags);
 
-	return -ENODEV;
+	return rc;
 
 }
 
@@ -888,22 +932,17 @@
 struct hvcs_struct *hvcs_get_by_index(int index)
 {
 	struct hvcs_struct *hvcsd = NULL;
-	struct list_head *element;
-	struct list_head *safe_temp;
 	unsigned long flags;
-	unsigned long structs_flags;
 
-	spin_lock_irqsave(&hvcs_structs_lock, structs_flags);
+	spin_lock(&hvcs_structs_lock);
 	/* We can immediately discard OOB requests */
 	if (index >= 0 && index < HVCS_MAX_SERVER_ADAPTERS) {
-		list_for_each_safe(element, safe_temp, &hvcs_structs) {
-			hvcsd = list_entry(element, struct hvcs_struct, next);
+		list_for_each_entry(hvcsd, &hvcs_structs, next) {
 			spin_lock_irqsave(&hvcsd->lock, flags);
 			if (hvcsd->index == index) {
 				kobject_get(&hvcsd->kobj);
 				spin_unlock_irqrestore(&hvcsd->lock, flags);
-				spin_unlock_irqrestore(&hvcs_structs_lock,
-						structs_flags);
+				spin_unlock(&hvcs_structs_lock);
 				return hvcsd;
 			}
 			spin_unlock_irqrestore(&hvcsd->lock, flags);
@@ -911,7 +950,7 @@
 		hvcsd = NULL;
 	}
 
-	spin_unlock_irqrestore(&hvcs_structs_lock, structs_flags);
+	spin_unlock(&hvcs_structs_lock);
 	return hvcsd;
 }
 
@@ -921,12 +960,13 @@
  */
 static int hvcs_open(struct tty_struct *tty, struct file *filp)
 {
-	struct hvcs_struct *hvcsd = NULL;
-	int retval = 0;
+	struct hvcs_struct *hvcsd;
+	int rc, retval = 0;
 	unsigned long flags;
 	unsigned int irq;
 	struct vio_dev *vdev;
 	unsigned long unit_address;
+	struct kobject *kobjp;
 
 	if (tty->driver_data)
 		goto fast_open;
@@ -936,7 +976,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;
 	}
 
@@ -959,7 +1000,7 @@
 	 */
 	tty->low_latency = 1;
 
-	memset(&hvcsd->buffer[0], 0x3F, HVCS_BUFF_LEN);
+	memset(&hvcsd->buffer[0], 0x00, HVCS_BUFF_LEN);
 
 	/*
 	 * Save these in the spinlock for the enable operations that need them
@@ -974,12 +1015,12 @@
 
 	/*
 	 * 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 ((hvcs_enable_device(hvcsd, unit_address, irq, vdev))) {
+	if (((rc = hvcs_enable_device(hvcsd, unit_address, irq, vdev)))) {
 		kobject_put(&hvcsd->kobj);
 		printk(KERN_WARNING "HVCS: enable device failed.\n");
-		return -ENODEV;
+		return rc;
 	}
 
 	goto open_success;
@@ -1002,16 +1043,17 @@
 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;
 
 error_release:
+	kobjp = &hvcsd->kobj;
 	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;
 }
 
@@ -1020,6 +1062,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
@@ -1039,14 +1082,10 @@
 	hvcsd = tty->driver_data;
 
 	spin_lock_irqsave(&hvcsd->lock, flags);
+	kobjp = &hvcsd->kobj;
 	if (--hvcsd->open_count == 0) {
 
-		/*
-		 * This line is important because it tells hvcs_open that this
-		 * device needs to be re-configured the next time hvcs_open is
-		 * called.
-		 */
-		hvcsd->tty->driver_data = NULL;
+		vio_disable_interrupts(hvcsd->vdev);
 
 		/*
 		 * NULL this early so that the kernel_thread doesn't try to
@@ -1055,34 +1094,28 @@
 		 */
 		hvcsd->tty = NULL;
 
-		/*
-		 * Block the close until all the buffered data has been
-		 * delivered.
-		 */
-		while(hvcsd->chars_in_buffer) {
-			spin_unlock_irqrestore(&hvcsd->lock, flags);
+		irq = hvcsd->vdev->irq;
+		spin_unlock_irqrestore(&hvcsd->lock, flags);
 
-			/*
-			 * Give the kernel thread the hvcs_struct so that it can
-			 * try to deliver the remaining data but block the close
-			 * operation by spinning in this function so that other
-			 * tty operations have to wait.
-			 */
-			yield();
-			spin_lock_irqsave(&hvcsd->lock, flags);
-		}
+		tty_wait_until_sent(tty, HVCS_CLOSE_WAIT);
 
-		hvcs_final_close(hvcsd);
+		/*
+		 * This line is important because it tells hvcs_open that this
+		 * device needs to be re-configured the next time hvcs_open is
+		 * called.
+		 */
+		tty->driver_data = NULL;
 
+		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);
 }
 
@@ -1092,6 +1125,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 */
@@ -1101,15 +1135,31 @@
 	 * Don't kobject put inside the spinlock because the destruction
 	 * callback may use the spinlock and it may get called before the
 	 * spinlock has been released.  Get a pointer to the kobject and
-	 * kobject_put on that instead.
+	 * kobject_put on that after releasing the spinlock.
 	 */
 	kobjp = &hvcsd->kobj;
 
-	/* Calling this will drop any buffered data on the floor. */
-	hvcs_final_close(hvcsd);
+	vio_disable_interrupts(hvcsd->vdev);
+
+	hvcsd->todo_mask = 0;
+
+	/* I don't think the tty needs the hvcs_struct pointer after a hangup */
+	hvcsd->tty->driver_data = NULL;
+	hvcsd->tty = NULL;
+
+	hvcsd->open_count = 0;
+
+	/* This will drop any buffered data on the floor which is OK in a hangup
+	 * scenario. */
+	memset(&hvcsd->buffer[0], 0x00, HVCS_BUFF_LEN);
+	hvcsd->chars_in_buffer = 0;
+
+	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
@@ -1259,28 +1309,18 @@
 static int hvcs_write_room(struct tty_struct *tty)
 {
 	struct hvcs_struct *hvcsd = tty->driver_data;
-	unsigned long flags;
-	int retval;
 
 	if (!hvcsd || hvcsd->open_count <= 0)
 		return 0;
 
-	spin_lock_irqsave(&hvcsd->lock, flags);
-	retval = HVCS_BUFF_LEN - hvcsd->chars_in_buffer;
-	spin_unlock_irqrestore(&hvcsd->lock, flags);
-	return retval;
+	return HVCS_BUFF_LEN - hvcsd->chars_in_buffer;
 }
 
 static int hvcs_chars_in_buffer(struct tty_struct *tty)
 {
 	struct hvcs_struct *hvcsd = tty->driver_data;
-	unsigned long flags;
-	int retval;
 
-	spin_lock_irqsave(&hvcsd->lock, flags);
-	retval = hvcsd->chars_in_buffer;
-	spin_unlock_irqrestore(&hvcsd->lock, flags);
-	return retval;
+	return hvcsd->chars_in_buffer;
 }
 
 static struct tty_operations hvcs_ops = {
@@ -1294,6 +1334,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;
@@ -1312,6 +1374,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;
@@ -1342,19 +1407,25 @@
 	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;
+		return -EIO;
 	}
 
-	hvcs_structs_lock = SPIN_LOCK_UNLOCKED;
-
-	hvcs_pi_lock = SPIN_LOCK_UNLOCKED;
 	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;
 	}
@@ -1374,8 +1445,6 @@
 
 static void __exit hvcs_module_exit(void)
 {
-	unsigned long flags;
-
 	/*
 	 * This driver receives hvcs_remove callbacks for each device upon
 	 * module removal.
@@ -1387,10 +1456,10 @@
 	 */
 	kthread_stop(hvcs_task);
 
-	spin_lock_irqsave(&hvcs_pi_lock, flags);
+	spin_lock(&hvcs_pi_lock);
 	kfree(hvcs_pi_buff);
 	hvcs_pi_buff = NULL;
-	spin_unlock_irqrestore(&hvcs_pi_lock, flags);
+	spin_unlock(&hvcs_pi_lock);
 
 	hvcs_remove_driver_attrs();
 
@@ -1398,6 +1467,8 @@
 
 	tty_unregister_driver(hvcs_tty_driver);
 
+	hvcs_free_index_list();
+
 	put_tty_driver(hvcs_tty_driver);
 
 	printk(KERN_INFO "HVCS: driver module removed.\n");
@@ -1499,7 +1570,7 @@
 			" partner vty@%X:%d connection.\n",
 			hvcsd->vdev->unit_address,
 			hvcsd->p_unit_address,
-			(unsigned int)hvcsd->p_partition_ID);
+			(uint32_t)hvcsd->p_partition_ID);
 
 	spin_unlock_irqrestore(&hvcsd->lock, flags);
 	return count;
@@ -1520,11 +1591,27 @@
 static DEVICE_ATTR(vterm_state, S_IRUGO | S_IWUSR,
 		hvcs_vterm_state_show, hvcs_vterm_state_store);
 
+static ssize_t hvcs_index_show(struct device *dev, char *buf)
+{
+	struct vio_dev *viod = to_vio_dev(dev);
+	struct hvcs_struct *hvcsd = from_vio_dev(viod);
+	unsigned long flags;
+	int retval;
+
+	spin_lock_irqsave(&hvcsd->lock, flags);
+	retval = sprintf(buf, "%d\n", hvcsd->index);
+	spin_unlock_irqrestore(&hvcsd->lock, flags);
+	return retval;
+}
+
+static DEVICE_ATTR(index, S_IRUGO, hvcs_index_show, NULL);
+
 static struct attribute *hvcs_attrs[] = {
 	&dev_attr_partner_vtys.attr,
 	&dev_attr_partner_clcs.attr,
 	&dev_attr_current_vty.attr,
 	&dev_attr_vterm_state.attr,
+	&dev_attr_index.attr,
 	NULL,
 };
 
diff -Nru a/drivers/char/hvsi.c b/drivers/char/hvsi.c
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/drivers/char/hvsi.c	2004-10-18 14:57:23 -07:00
@@ -0,0 +1,1319 @@
+/*
+ * Copyright (C) 2004 Hollis Blanchard <hollisb@us.ibm.com>, IBM
+ *
+ * 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
+ */
+
+/* Host Virtual Serial Interface (HVSI) is a protocol between the hosted OS
+ * and the service processor on IBM pSeries servers. On these servers, there
+ * are no serial ports under the OS's control, and sometimes there is no other
+ * console available either. However, the service processor has two standard
+ * serial ports, so this over-complicated protocol allows the OS to control
+ * those ports by proxy.
+ *
+ * Besides data, the procotol supports the reading/writing of the serial
+ * port's DTR line, and the reading of the CD line. This is to allow the OS to
+ * control a modem attached to the service processor's serial port. Note that
+ * the OS cannot change the speed of the port through this protocol.
+ */
+
+/* TODO:
+ * test FSP reset
+ * add udbg support for xmon/kdb
+ */
+
+#undef DEBUG
+
+#include <linux/console.h>
+#include <linux/ctype.h>
+#include <linux/delay.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/module.h>
+#include <linux/major.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/spinlock.h>
+#include <linux/sysrq.h>
+#include <linux/tty.h>
+#include <linux/tty_flip.h>
+#include <asm/hvcall.h>
+#include <asm/hvconsole.h>
+#include <asm/prom.h>
+#include <asm/uaccess.h>
+#include <asm/vio.h>
+
+#define HVSI_MAJOR	229
+#define HVSI_MINOR	128
+#define MAX_NR_HVSI_CONSOLES 4
+
+#define HVSI_TIMEOUT (5*HZ)
+#define HVSI_VERSION 1
+#define HVSI_MAX_PACKET 256
+#define HVSI_MAX_READ 16
+#define HVSI_MAX_OUTGOING_DATA 12
+#define N_OUTBUF 12
+
+/*
+ * we pass data via two 8-byte registers, so we would like our char arrays
+ * properly aligned for those loads.
+ */
+#define __ALIGNED__	__attribute__((__aligned__(sizeof(long))))
+
+struct hvsi_struct {
+	struct work_struct writer;
+	wait_queue_head_t emptyq; /* woken when outbuf is emptied */
+	wait_queue_head_t stateq; /* woken when HVSI state changes */
+	spinlock_t lock;
+	int index;
+	struct tty_struct *tty;
+	unsigned int count;
+	uint8_t throttle_buf[128];
+	uint8_t outbuf[N_OUTBUF]; /* to implement write_room and chars_in_buffer */
+	/* inbuf is for packet reassembly. leave a little room for leftovers. */
+	uint8_t inbuf[HVSI_MAX_PACKET + HVSI_MAX_READ];
+	uint8_t *inbuf_end;
+	int n_throttle;
+	int n_outbuf;
+	uint32_t vtermno;
+	uint32_t virq;
+	atomic_t seqno; /* HVSI packet sequence number */
+	uint16_t mctrl;
+	uint8_t state;  /* HVSI protocol state */
+	uint8_t flags;
+#ifdef CONFIG_MAGIC_SYSRQ
+	uint8_t sysrq;
+#endif /* CONFIG_MAGIC_SYSRQ */
+};
+static struct hvsi_struct hvsi_ports[MAX_NR_HVSI_CONSOLES];
+
+static struct tty_driver *hvsi_driver;
+static int hvsi_count;
+static int (*hvsi_wait)(struct hvsi_struct *hp, int state);
+
+enum HVSI_PROTOCOL_STATE {
+	HVSI_CLOSED,
+	HVSI_WAIT_FOR_VER_RESPONSE,
+	HVSI_WAIT_FOR_VER_QUERY,
+	HVSI_OPEN,
+	HVSI_WAIT_FOR_MCTRL_RESPONSE,
+};
+#define HVSI_CONSOLE 0x1
+
+#define VS_DATA_PACKET_HEADER           0xff
+#define VS_CONTROL_PACKET_HEADER        0xfe
+#define VS_QUERY_PACKET_HEADER          0xfd
+#define VS_QUERY_RESPONSE_PACKET_HEADER 0xfc
+
+/* control verbs */
+#define VSV_SET_MODEM_CTL    1 /* to service processor only */
+#define VSV_MODEM_CTL_UPDATE 2 /* from service processor only */
+#define VSV_CLOSE_PROTOCOL   3
+
+/* query verbs */
+#define VSV_SEND_VERSION_NUMBER 1
+#define VSV_SEND_MODEM_CTL_STATUS 2
+
+/* yes, these masks are not consecutive. */
+#define HVSI_TSDTR 0x01
+#define HVSI_TSCD  0x20
+
+struct hvsi_header {
+	uint8_t  type;
+	uint8_t  len;
+	uint16_t seqno;
+} __attribute__((packed));
+
+struct hvsi_data {
+	uint8_t  type;
+	uint8_t  len;
+	uint16_t seqno;
+	uint8_t  data[HVSI_MAX_OUTGOING_DATA];
+} __attribute__((packed));
+
+struct hvsi_control {
+	uint8_t  type;
+	uint8_t  len;
+	uint16_t seqno;
+	uint16_t verb;
+	/* optional depending on verb: */
+	uint32_t word;
+	uint32_t mask;
+} __attribute__((packed));
+
+struct hvsi_query {
+	uint8_t  type;
+	uint8_t  len;
+	uint16_t seqno;
+	uint16_t verb;
+} __attribute__((packed));
+
+struct hvsi_query_response {
+	uint8_t  type;
+	uint8_t  len;
+	uint16_t seqno;
+	uint16_t verb;
+	uint16_t query_seqno;
+	union {
+		uint8_t  version;
+		uint32_t mctrl_word;
+	} u;
+} __attribute__((packed));
+
+static inline int is_open(struct hvsi_struct *hp)
+{
+	/* if we're waiting for an mctrl then we're already open */
+	return (hp->state == HVSI_OPEN)
+			|| (hp->state == HVSI_WAIT_FOR_MCTRL_RESPONSE);
+}
+
+static inline void print_state(struct hvsi_struct *hp)
+{
+#ifdef DEBUG
+	static const char *state_names[] = {
+		"HVSI_CLOSED",
+		"HVSI_WAIT_FOR_VER_RESPONSE",
+		"HVSI_WAIT_FOR_VER_QUERY",
+		"HVSI_OPEN",
+		"HVSI_WAIT_FOR_MCTRL_RESPONSE",
+	};
+	const char *name = state_names[hp->state];
+
+	if (hp->state > (sizeof(state_names)/sizeof(char*)))
+		name = "UNKNOWN";
+
+	pr_debug("hvsi%i: state = %s\n", hp->index, name);
+#endif /* DEBUG */
+}
+
+static inline void __set_state(struct hvsi_struct *hp, int state)
+{
+	hp->state = state;
+	print_state(hp);
+	wake_up_all(&hp->stateq);
+}
+
+static inline void set_state(struct hvsi_struct *hp, int state)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&hp->lock, flags);
+	__set_state(hp, state);
+	spin_unlock_irqrestore(&hp->lock, flags);
+}
+
+static inline int len_packet(const uint8_t *packet)
+{
+	return (int)((struct hvsi_header *)packet)->len;
+}
+
+static inline int is_header(const uint8_t *packet)
+{
+	struct hvsi_header *header = (struct hvsi_header *)packet;
+	return header->type >= VS_QUERY_RESPONSE_PACKET_HEADER;
+}
+
+static inline int got_packet(const struct hvsi_struct *hp, uint8_t *packet)
+{
+	if (hp->inbuf_end < packet + sizeof(struct hvsi_header))
+		return 0; /* don't even have the packet header */
+
+	if (hp->inbuf_end < (packet + len_packet(packet)))
+		return 0; /* don't have the rest of the packet */
+
+	return 1;
+}
+
+/* shift remaining bytes in packetbuf down */
+static void compact_inbuf(struct hvsi_struct *hp, uint8_t *read_to)
+{
+	int remaining = (int)(hp->inbuf_end - read_to);
+
+	pr_debug("%s: %i chars remain\n", __FUNCTION__, remaining);
+
+	if (read_to != hp->inbuf)
+		memmove(hp->inbuf, read_to, remaining);
+
+	hp->inbuf_end = hp->inbuf + remaining;
+}
+
+#ifdef DEBUG
+#define dbg_dump_packet(packet) dump_packet(packet)
+#define dbg_dump_hex(data, len) dump_hex(data, len)
+#else
+#define dbg_dump_packet(packet) do { } while (0)
+#define dbg_dump_hex(data, len) do { } while (0)
+#endif
+
+static void dump_hex(const uint8_t *data, int len)
+{
+	int i;
+
+	printk("    ");
+	for (i=0; i < len; i++)
+		printk("%.2x", data[i]);
+
+	printk("\n    ");
+	for (i=0; i < len; i++) {
+		if (isprint(data[i]))
+			printk("%c", data[i]);
+		else
+			printk(".");
+	}
+	printk("\n");
+}
+
+static void dump_packet(uint8_t *packet)
+{
+	struct hvsi_header *header = (struct hvsi_header *)packet;
+
+	printk("type 0x%x, len %i, seqno %i:\n", header->type, header->len,
+			header->seqno);
+
+	dump_hex(packet, header->len);
+}
+
+/* can't use hvc_get_chars because that strips CRs */
+static int hvsi_read(struct hvsi_struct *hp, char *buf, int count)
+{
+	unsigned long got;
+
+	if (plpar_hcall(H_GET_TERM_CHAR, hp->vtermno, 0, 0, 0, &got,
+			(unsigned long *)buf, (unsigned long *)buf+1) == H_Success)
+		return got;
+	return 0;
+}
+
+/*
+ * we can't call tty_hangup() directly here because we need to call that
+ * outside of our lock
+ */
+static struct tty_struct *hvsi_recv_control(struct hvsi_struct *hp,
+		uint8_t *packet)
+{
+	struct tty_struct *to_hangup = NULL;
+	struct hvsi_control *header = (struct hvsi_control *)packet;
+
+	switch (header->verb) {
+		case VSV_MODEM_CTL_UPDATE:
+			if ((header->word & HVSI_TSCD) == 0) {
+				/* CD went away; no more connection */
+				pr_debug("hvsi%i: CD dropped\n", hp->index);
+				hp->mctrl &= TIOCM_CD;
+				if (!(hp->tty->flags & CLOCAL))
+					to_hangup = hp->tty;
+			}
+			break;
+		case VSV_CLOSE_PROTOCOL:
+			printk(KERN_DEBUG
+				"hvsi%i: service processor closed connection!\n", hp->index);
+			__set_state(hp, HVSI_CLOSED);
+			to_hangup = hp->tty;
+			hp->tty = NULL;
+			break;
+		default:
+			printk(KERN_WARNING "hvsi%i: unknown HVSI control packet: ",
+				hp->index);
+			dump_packet(packet);
+			break;
+	}
+
+	return to_hangup;
+}
+
+static void hvsi_recv_response(struct hvsi_struct *hp, uint8_t *packet)
+{
+	struct hvsi_query_response *resp = (struct hvsi_query_response *)packet;
+
+	switch (hp->state) {
+		case HVSI_WAIT_FOR_VER_RESPONSE:
+			__set_state(hp, HVSI_WAIT_FOR_VER_QUERY);
+			break;
+		case HVSI_WAIT_FOR_MCTRL_RESPONSE:
+			hp->mctrl = 0;
+			if (resp->u.mctrl_word & HVSI_TSDTR)
+				hp->mctrl |= TIOCM_DTR;
+			if (resp->u.mctrl_word & HVSI_TSCD)
+				hp->mctrl |= TIOCM_CD;
+			__set_state(hp, HVSI_OPEN);
+			break;
+		default:
+			printk(KERN_ERR "hvsi%i: unexpected query response: ", hp->index);
+			dump_packet(packet);
+			break;
+	}
+}
+
+/* respond to service processor's version query */
+static int hvsi_version_respond(struct hvsi_struct *hp, uint16_t query_seqno)
+{
+	struct hvsi_query_response packet __ALIGNED__;
+	int wrote;
+
+	packet.type = VS_QUERY_RESPONSE_PACKET_HEADER;
+	packet.len = sizeof(struct hvsi_query_response);
+	packet.seqno = atomic_inc_return(&hp->seqno);
+	packet.verb = VSV_SEND_VERSION_NUMBER;
+	packet.u.version = HVSI_VERSION;
+	packet.query_seqno = query_seqno+1;
+
+	pr_debug("%s: sending %i bytes\n", __FUNCTION__, packet.len);
+	dbg_dump_hex((uint8_t*)&packet, packet.len);
+
+	wrote = hvc_put_chars(hp->vtermno, (char *)&packet, packet.len);
+	if (wrote != packet.len) {
+		printk(KERN_ERR "hvsi%i: couldn't send query response!\n",
+			hp->index);
+		return -EIO;
+	}
+
+	return 0;
+}
+
+static void hvsi_recv_query(struct hvsi_struct *hp, uint8_t *packet)
+{
+	struct hvsi_query *query = (struct hvsi_query *)packet;
+
+	switch (hp->state) {
+		case HVSI_WAIT_FOR_VER_QUERY:
+			__set_state(hp, HVSI_OPEN);
+			hvsi_version_respond(hp, query->seqno);
+			break;
+		default:
+			printk(KERN_ERR "hvsi%i: unexpected query: ", hp->index);
+			dump_packet(packet);
+			break;
+	}
+}
+
+static void hvsi_insert_chars(struct hvsi_struct *hp, const char *buf, int len)
+{
+	int i;
+
+	for (i=0; i < len; i++) {
+		char c = buf[i];
+#ifdef CONFIG_MAGIC_SYSRQ
+		if (c == '\0') {
+			hp->sysrq = 1;
+			continue;
+		} else if (hp->sysrq) {
+			handle_sysrq(c, NULL, hp->tty);
+			hp->sysrq = 0;
+			continue;
+		}
+#endif /* CONFIG_MAGIC_SYSRQ */
+		tty_insert_flip_char(hp->tty, c, 0);
+	}
+}
+
+/*
+ * We could get 252 bytes of data at once here. But the tty layer only
+ * throttles us at TTY_THRESHOLD_THROTTLE (128) bytes, so we could overflow
+ * it. Accordingly we won't send more than 128 bytes at a time to the flip
+ * buffer, which will give the tty buffer a chance to throttle us. Should the
+ * value of TTY_THRESHOLD_THROTTLE change in n_tty.c, this code should be
+ * revisited.
+ */
+#define TTY_THRESHOLD_THROTTLE 128
+static struct tty_struct *hvsi_recv_data(struct hvsi_struct *hp,
+		const uint8_t *packet)
+{
+	const struct hvsi_header *header = (const struct hvsi_header *)packet;
+	const uint8_t *data = packet + sizeof(struct hvsi_header);
+	int datalen = header->len - sizeof(struct hvsi_header);
+	int overflow = datalen - TTY_THRESHOLD_THROTTLE;
+
+	pr_debug("queueing %i chars '%.*s'\n", datalen, datalen, data);
+
+	if (datalen == 0)
+		return NULL;
+
+	if (overflow > 0) {
+		pr_debug("%s: got >TTY_THRESHOLD_THROTTLE bytes\n", __FUNCTION__);
+		datalen = TTY_THRESHOLD_THROTTLE;
+	}
+
+	hvsi_insert_chars(hp, data, datalen);
+
+	if (overflow > 0) {
+		/*
+		 * we still have more data to deliver, so we need to save off the
+		 * overflow and send it later
+		 */
+		pr_debug("%s: deferring overflow\n", __FUNCTION__);
+		memcpy(hp->throttle_buf, data + TTY_THRESHOLD_THROTTLE, overflow);
+		hp->n_throttle = overflow;
+	}
+
+	return hp->tty;
+}
+
+/*
+ * Returns true/false indicating data successfully read from hypervisor.
+ * Used both to get packets for tty connections and to advance the state
+ * machine during console handshaking (in which case tty = NULL and we ignore
+ * incoming data).
+ */
+static int hvsi_load_chunk(struct hvsi_struct *hp, struct tty_struct **flip,
+		struct tty_struct **hangup)
+{
+	uint8_t *packet = hp->inbuf;
+	int chunklen;
+
+	*flip = NULL;
+	*hangup = NULL;
+
+	chunklen = hvsi_read(hp, hp->inbuf_end, HVSI_MAX_READ);
+	if (chunklen == 0)
+		return 0;
+
+	pr_debug("%s: got %i bytes\n", __FUNCTION__, chunklen);
+	dbg_dump_hex(hp->inbuf_end, chunklen);
+
+	hp->inbuf_end += chunklen;
+
+	/* handle all completed packets */
+	while ((packet < hp->inbuf_end) && got_packet(hp, packet)) {
+		struct hvsi_header *header = (struct hvsi_header *)packet;
+
+		if (!is_header(packet)) {
+			printk(KERN_ERR "hvsi%i: got malformed packet\n", hp->index);
+			/* skip bytes until we find a header or run out of data */
+			while ((packet < hp->inbuf_end) && (!is_header(packet)))
+				packet++;
+			continue;
+		}
+
+		pr_debug("%s: handling %i-byte packet\n", __FUNCTION__,
+				len_packet(packet));
+		dbg_dump_packet(packet);
+
+		switch (header->type) {
+			case VS_DATA_PACKET_HEADER:
+				if (!is_open(hp))
+					break;
+				if (hp->tty == NULL)
+					break; /* no tty buffer to put data in */
+				*flip = hvsi_recv_data(hp, packet);
+				break;
+			case VS_CONTROL_PACKET_HEADER:
+				*hangup = hvsi_recv_control(hp, packet);
+				break;
+			case VS_QUERY_RESPONSE_PACKET_HEADER:
+				hvsi_recv_response(hp, packet);
+				break;
+			case VS_QUERY_PACKET_HEADER:
+				hvsi_recv_query(hp, packet);
+				break;
+			default:
+				printk(KERN_ERR "hvsi%i: unknown HVSI packet type 0x%x\n",
+						hp->index, header->type);
+				dump_packet(packet);
+				break;
+		}
+
+		packet += len_packet(packet);
+
+		if (*hangup) {
+			pr_debug("%s: hangup\n", __FUNCTION__);
+			/*
+			 * we need to send the hangup now before receiving any more data.
+			 * If we get "data, hangup, data", we can't deliver the second
+			 * data before the hangup.
+			 */
+			break;
+		}
+	}
+
+	compact_inbuf(hp, packet);
+
+	return 1;
+}
+
+static void hvsi_send_overflow(struct hvsi_struct *hp)
+{
+	pr_debug("%s: delivering %i bytes overflow\n", __FUNCTION__,
+			hp->n_throttle);
+
+	hvsi_insert_chars(hp, hp->throttle_buf, hp->n_throttle);
+	hp->n_throttle = 0;
+}
+
+/*
+ * must get all pending data because we only get an irq on empty->non-empty
+ * transition
+ */
+static irqreturn_t hvsi_interrupt(int irq, void *arg, struct pt_regs *regs)
+{
+	struct hvsi_struct *hp = (struct hvsi_struct *)arg;
+	struct tty_struct *flip;
+	struct tty_struct *hangup;
+	unsigned long flags;
+	irqreturn_t handled = IRQ_NONE;
+	int again = 1;
+
+	pr_debug("%s\n", __FUNCTION__);
+
+	while (again) {
+		spin_lock_irqsave(&hp->lock, flags);
+		again = hvsi_load_chunk(hp, &flip, &hangup);
+		handled = IRQ_HANDLED;
+		spin_unlock_irqrestore(&hp->lock, flags);
+
+		/*
+		 * we have to call tty_flip_buffer_push() and tty_hangup() outside our
+		 * spinlock. But we also have to keep going until we've read all the
+		 * available data.
+		 */
+
+		if (flip) {
+			/* there was data put in the tty flip buffer */
+			tty_flip_buffer_push(flip);
+			flip = NULL;
+		}
+
+		if (hangup) {
+			tty_hangup(hangup);
+		}
+	}
+
+	spin_lock_irqsave(&hp->lock, flags);
+	if (hp->tty && hp->n_throttle
+			&& (!test_bit(TTY_THROTTLED, &hp->tty->flags))) {
+		/* we weren't hung up and we weren't throttled, so we can deliver the
+		 * rest now */
+		flip = hp->tty;
+		hvsi_send_overflow(hp);
+	}
+	spin_unlock_irqrestore(&hp->lock, flags);
+
+	if (flip) {
+		tty_flip_buffer_push(flip);
+	}
+
+	return handled;
+}
+
+/* for boot console, before the irq handler is running */
+static int __init poll_for_state(struct hvsi_struct *hp, int state)
+{
+	unsigned long end_jiffies = jiffies + HVSI_TIMEOUT;
+
+	for (;;) {
+		hvsi_interrupt(hp->virq, (void *)hp, NULL); /* get pending data */
+
+		if (hp->state == state)
+			return 0;
+
+		mdelay(5);
+		if (time_after(jiffies, end_jiffies))
+			return -EIO;
+	}
+}
+
+/* wait for irq handler to change our state */
+static int wait_for_state(struct hvsi_struct *hp, int state)
+{
+	unsigned long end_jiffies = jiffies + HVSI_TIMEOUT;
+	unsigned long timeout;
+	int ret = 0;
+
+	DECLARE_WAITQUEUE(myself, current);
+	set_current_state(TASK_INTERRUPTIBLE);
+	add_wait_queue(&hp->stateq, &myself);
+
+	for (;;) {
+		set_current_state(TASK_INTERRUPTIBLE);
+		if (hp->state == state)
+			break;
+		timeout = end_jiffies - jiffies;
+		if (time_after(jiffies, end_jiffies)) {
+			ret = -EIO;
+			break;
+		}
+		schedule_timeout(timeout);
+	}
+	remove_wait_queue(&hp->stateq, &myself);
+	set_current_state(TASK_RUNNING);
+
+	return ret;
+}
+
+static int hvsi_query(struct hvsi_struct *hp, uint16_t verb)
+{
+	struct hvsi_query packet __ALIGNED__;
+	int wrote;
+
+	packet.type = VS_QUERY_PACKET_HEADER;
+	packet.len = sizeof(struct hvsi_query);
+	packet.seqno = atomic_inc_return(&hp->seqno);
+	packet.verb = verb;
+
+	pr_debug("%s: sending %i bytes\n", __FUNCTION__, packet.len);
+	dbg_dump_hex((uint8_t*)&packet, packet.len);
+
+	wrote = hvc_put_chars(hp->vtermno, (char *)&packet, packet.len);
+	if (wrote != packet.len) {
+		printk(KERN_ERR "hvsi%i: couldn't send query (%i)!\n", hp->index,
+			wrote);
+		return -EIO;
+	}
+
+	return 0;
+}
+
+static int hvsi_get_mctrl(struct hvsi_struct *hp)
+{
+	int ret;
+
+	set_state(hp, HVSI_WAIT_FOR_MCTRL_RESPONSE);
+	hvsi_query(hp, VSV_SEND_MODEM_CTL_STATUS);
+
+	ret = hvsi_wait(hp, HVSI_OPEN);
+	if (ret < 0) {
+		printk(KERN_ERR "hvsi%i: didn't get modem flags\n", hp->index);
+		set_state(hp, HVSI_OPEN);
+		return ret;
+	}
+
+	pr_debug("%s: mctrl 0x%x\n", __FUNCTION__, hp->mctrl);
+
+	return 0;
+}
+
+/* note that we can only set DTR */
+static int hvsi_set_mctrl(struct hvsi_struct *hp, uint16_t mctrl)
+{
+	struct hvsi_control packet __ALIGNED__;
+	int wrote;
+
+	packet.type = VS_CONTROL_PACKET_HEADER,
+	packet.seqno = atomic_inc_return(&hp->seqno);
+	packet.len = sizeof(struct hvsi_control);
+	packet.verb = VSV_SET_MODEM_CTL;
+	packet.mask = HVSI_TSDTR;
+
+	if (mctrl & TIOCM_DTR)
+		packet.word = HVSI_TSDTR;
+
+	pr_debug("%s: sending %i bytes\n", __FUNCTION__, packet.len);
+	dbg_dump_hex((uint8_t*)&packet, packet.len);
+
+	wrote = hvc_put_chars(hp->vtermno, (char *)&packet, packet.len);
+	if (wrote != packet.len) {
+		printk(KERN_ERR "hvsi%i: couldn't set DTR!\n", hp->index);
+		return -EIO;
+	}
+
+	return 0;
+}
+
+static void hvsi_drain_input(struct hvsi_struct *hp)
+{
+	uint8_t buf[HVSI_MAX_READ] __ALIGNED__;
+	unsigned long end_jiffies = jiffies + HVSI_TIMEOUT;
+
+	while (time_before(end_jiffies, jiffies))
+		if (0 == hvsi_read(hp, buf, HVSI_MAX_READ))
+			break;
+}
+
+static int hvsi_handshake(struct hvsi_struct *hp)
+{
+	int ret;
+
+	/*
+	 * We could have a CLOSE or other data waiting for us before we even try
+	 * to open; try to throw it all away so we don't get confused. (CLOSE
+	 * is the first message sent up the pipe when the FSP comes online. We
+	 * need to distinguish between "it came up a while ago and we're the first
+	 * user" and "it was just reset before it saw our handshake packet".)
+	 */
+	hvsi_drain_input(hp);
+
+	set_state(hp, HVSI_WAIT_FOR_VER_RESPONSE);
+	ret = hvsi_query(hp, VSV_SEND_VERSION_NUMBER);
+	if (ret < 0) {
+		printk(KERN_ERR "hvsi%i: couldn't send version query\n", hp->index);
+		return ret;
+	}
+
+	ret = hvsi_wait(hp, HVSI_OPEN);
+	if (ret < 0)
+		return ret;
+
+	return 0;
+}
+
+static int hvsi_put_chars(struct hvsi_struct *hp, const char *buf, int count)
+{
+	struct hvsi_data packet __ALIGNED__;
+	int ret;
+
+	BUG_ON(count > HVSI_MAX_OUTGOING_DATA);
+
+	packet.type = VS_DATA_PACKET_HEADER;
+	packet.seqno = atomic_inc_return(&hp->seqno);
+	packet.len = count + sizeof(struct hvsi_header);
+	memcpy(&packet.data, buf, count);
+
+	ret = hvc_put_chars(hp->vtermno, (char *)&packet, packet.len);
+	if (ret == packet.len) {
+		/* return the number of chars written, not the packet length */
+		return count;
+	}
+	return ret; /* return any errors */
+}
+
+static void hvsi_close_protocol(struct hvsi_struct *hp)
+{
+	struct hvsi_control packet __ALIGNED__;
+
+	packet.type = VS_CONTROL_PACKET_HEADER;
+	packet.seqno = atomic_inc_return(&hp->seqno);
+	packet.len = 6;
+	packet.verb = VSV_CLOSE_PROTOCOL;
+
+	pr_debug("%s: sending %i bytes\n", __FUNCTION__, packet.len);
+	dbg_dump_hex((uint8_t*)&packet, packet.len);
+
+	hvc_put_chars(hp->vtermno, (char *)&packet, packet.len);
+}
+
+static int hvsi_open(struct tty_struct *tty, struct file *filp)
+{
+	struct hvsi_struct *hp;
+	unsigned long flags;
+	int line = tty->index;
+	int ret;
+
+	pr_debug("%s\n", __FUNCTION__);
+
+	if (line < 0 || line >= hvsi_count)
+		return -ENODEV;
+	hp = &hvsi_ports[line];
+
+	tty->driver_data = hp;
+	tty->low_latency = 1; /* avoid throttle/tty_flip_buffer_push race */
+
+	spin_lock_irqsave(&hp->lock, flags);
+	hp->tty = tty;
+	hp->count++;
+	atomic_set(&hp->seqno, 0);
+	h_vio_signal(hp->vtermno, VIO_IRQ_ENABLE);
+	spin_unlock_irqrestore(&hp->lock, flags);
+
+	if (hp->flags & HVSI_CONSOLE)
+		return 0; /* this has already been handshaked as the console */
+
+	ret = hvsi_handshake(hp);
+	if (ret < 0) {
+		printk(KERN_ERR "%s: HVSI handshaking failed\n", tty->name);
+		return ret;
+	}
+
+	ret = hvsi_get_mctrl(hp);
+	if (ret < 0) {
+		printk(KERN_ERR "%s: couldn't get initial modem flags\n", tty->name);
+		return ret;
+	}
+
+	ret = hvsi_set_mctrl(hp, hp->mctrl | TIOCM_DTR);
+	if (ret < 0) {
+		printk(KERN_ERR "%s: couldn't set DTR\n", tty->name);
+		return ret;
+	}
+
+	return 0;
+}
+
+/* wait for hvsi_write_worker to empty hp->outbuf */
+static void hvsi_flush_output(struct hvsi_struct *hp)
+{
+	unsigned long end_jiffies = jiffies + HVSI_TIMEOUT;
+	unsigned long timeout;
+
+	DECLARE_WAITQUEUE(myself, current);
+	set_current_state(TASK_UNINTERRUPTIBLE);
+	add_wait_queue(&hp->emptyq, &myself);
+
+	for (;;) {
+		set_current_state(TASK_UNINTERRUPTIBLE);
+		if (hp->n_outbuf <= 0)
+			break;
+		timeout = end_jiffies - jiffies;
+		if (time_after(jiffies, end_jiffies))
+			break;
+		schedule_timeout(timeout);
+	}
+	remove_wait_queue(&hp->emptyq, &myself);
+	set_current_state(TASK_RUNNING);
+
+	/* 'writer' could still be pending if it didn't see n_outbuf = 0 yet */
+	cancel_delayed_work(&hp->writer);
+	flush_scheduled_work();
+
+	/*
+	 * it's also possible that our timeout expired and hvsi_write_worker
+	 * didn't manage to push outbuf. poof.
+	 */
+	hp->n_outbuf = 0;
+}
+
+static void hvsi_close(struct tty_struct *tty, struct file *filp)
+{
+	struct hvsi_struct *hp = tty->driver_data;
+	unsigned long flags;
+
+	pr_debug("%s\n", __FUNCTION__);
+
+	if (tty_hung_up_p(filp))
+		return;
+
+	spin_lock_irqsave(&hp->lock, flags);
+
+	if (--hp->count == 0) {
+		hp->tty = NULL;
+		hp->inbuf_end = hp->inbuf; /* discard remaining partial packets */
+
+		/* only close down connection if it is not the console */
+		if (!(hp->flags & HVSI_CONSOLE)) {
+			h_vio_signal(hp->vtermno, VIO_IRQ_DISABLE); /* no more irqs */
+			__set_state(hp, HVSI_CLOSED);
+			/*
+			 * any data delivered to the tty layer after this will be
+			 * discarded (except for XON/XOFF)
+			 */
+			tty->closing = 1;
+
+			spin_unlock_irqrestore(&hp->lock, flags);
+
+			/* let any existing irq handlers finish. no more will start. */
+			synchronize_irq(hp->virq);
+
+			/* hvsi_write_worker will re-schedule until outbuf is empty. */
+			hvsi_flush_output(hp);
+
+			/* tell FSP to stop sending data */
+			hvsi_close_protocol(hp);
+
+			/*
+			 * drain anything FSP is still in the middle of sending, and let
+			 * hvsi_handshake drain the rest on the next open.
+			 */
+			hvsi_drain_input(hp);
+
+			spin_lock_irqsave(&hp->lock, flags);
+		}
+	} else if (hp->count < 0)
+		printk(KERN_ERR "hvsi_close %lu: oops, count is %d\n",
+		       hp - hvsi_ports, hp->count);
+
+	spin_unlock_irqrestore(&hp->lock, flags);
+}
+
+static void hvsi_hangup(struct tty_struct *tty)
+{
+	struct hvsi_struct *hp = tty->driver_data;
+
+	pr_debug("%s\n", __FUNCTION__);
+
+	hp->count = 0;
+	hp->tty = NULL;
+}
+
+/* called with hp->lock held */
+static void hvsi_push(struct hvsi_struct *hp)
+{
+	int n;
+
+	if (hp->n_outbuf <= 0)
+		return;
+
+	n = hvsi_put_chars(hp, hp->outbuf, hp->n_outbuf);
+	if (n != 0) {
+		/*
+		 * either all data was sent or there was an error, and we throw away
+		 * data on error.
+		 */
+		hp->n_outbuf = 0;
+	}
+}
+
+/* hvsi_write_worker will keep rescheduling itself until outbuf is empty */
+static void hvsi_write_worker(void *arg)
+{
+	struct hvsi_struct *hp = (struct hvsi_struct *)arg;
+	unsigned long flags;
+#ifdef DEBUG
+	static long start_j = 0;
+
+	if (start_j == 0)
+		start_j = jiffies;
+#endif /* DEBUG */
+
+	spin_lock_irqsave(&hp->lock, flags);
+
+	hvsi_push(hp);
+	if (hp->n_outbuf > 0)
+		schedule_delayed_work(&hp->writer, 10);
+	else {
+#ifdef DEBUG
+		pr_debug("%s: outbuf emptied after %li jiffies\n", __FUNCTION__,
+				jiffies - start_j);
+		start_j = 0;
+#endif /* DEBUG */
+		wake_up_all(&hp->emptyq);
+		if (test_bit(TTY_DO_WRITE_WAKEUP, &hp->tty->flags)
+				&& hp->tty->ldisc.write_wakeup)
+			hp->tty->ldisc.write_wakeup(hp->tty);
+		wake_up_interruptible(&hp->tty->write_wait);
+	}
+
+	spin_unlock_irqrestore(&hp->lock, flags);
+}
+
+static int hvsi_write_room(struct tty_struct *tty)
+{
+	struct hvsi_struct *hp = (struct hvsi_struct *)tty->driver_data;
+
+	return N_OUTBUF - hp->n_outbuf;
+}
+
+static int hvsi_chars_in_buffer(struct tty_struct *tty)
+{
+	struct hvsi_struct *hp = (struct hvsi_struct *)tty->driver_data;
+
+	return hp->n_outbuf;
+}
+
+static int hvsi_write(struct tty_struct *tty, int from_user,
+		     const unsigned char *buf, int count)
+{
+	struct hvsi_struct *hp = tty->driver_data;
+	const char *source = buf;
+	char *kbuf = NULL;
+	unsigned long flags;
+	int total = 0;
+	int origcount = count;
+
+	if (from_user) {
+		kbuf = kmalloc(count, GFP_KERNEL);
+		if (kbuf == NULL)
+			return -ENOMEM;
+		if (copy_from_user(kbuf, buf, count)) {
+			kfree(kbuf);
+			return -EFAULT;
+		}
+		source = kbuf;
+	}
+
+	spin_lock_irqsave(&hp->lock, flags);
+
+	if (!is_open(hp)) {
+		/* we're either closing or not yet open; don't accept data */
+		pr_debug("%s: not open\n", __FUNCTION__);
+		goto out;
+	}
+
+	/*
+	 * when the hypervisor buffer (16K) fills, data will stay in hp->outbuf
+	 * and hvsi_write_worker will be scheduled. subsequent hvsi_write() calls
+	 * will see there is no room in outbuf and return.
+	 */
+	while ((count > 0) && (hvsi_write_room(hp->tty) > 0)) {
+		int chunksize = min(count, hvsi_write_room(hp->tty));
+
+		BUG_ON(hp->n_outbuf < 0);
+		memcpy(hp->outbuf + hp->n_outbuf, source, chunksize);
+		hp->n_outbuf += chunksize;
+
+		total += chunksize;
+		source += chunksize;
+		count -= chunksize;
+		hvsi_push(hp);
+	}
+
+	if (hp->n_outbuf > 0) {
+		/*
+		 * we weren't able to write it all to the hypervisor.
+		 * schedule another push attempt.
+		 */
+		schedule_delayed_work(&hp->writer, 10);
+	}
+
+out:
+	spin_unlock_irqrestore(&hp->lock, flags);
+
+	if (from_user)
+		kfree(kbuf);
+
+	if (total != origcount)
+		pr_debug("%s: wanted %i, only wrote %i\n", __FUNCTION__, origcount,
+			total);
+
+	return total;
+}
+
+/*
+ * I have never seen throttle or unthrottle called, so this little throttle
+ * buffering scheme may or may not work.
+ */
+static void hvsi_throttle(struct tty_struct *tty)
+{
+	struct hvsi_struct *hp = (struct hvsi_struct *)tty->driver_data;
+
+	pr_debug("%s\n", __FUNCTION__);
+
+	h_vio_signal(hp->vtermno, VIO_IRQ_DISABLE);
+}
+
+static void hvsi_unthrottle(struct tty_struct *tty)
+{
+	struct hvsi_struct *hp = (struct hvsi_struct *)tty->driver_data;
+	unsigned long flags;
+	int shouldflip = 0;
+
+	pr_debug("%s\n", __FUNCTION__);
+
+	spin_lock_irqsave(&hp->lock, flags);
+	if (hp->n_throttle) {
+		hvsi_send_overflow(hp);
+		shouldflip = 1;
+	}
+	spin_unlock_irqrestore(&hp->lock, flags);
+
+	if (shouldflip)
+		tty_flip_buffer_push(hp->tty);
+
+	h_vio_signal(hp->vtermno, VIO_IRQ_ENABLE);
+}
+
+static int hvsi_tiocmget(struct tty_struct *tty, struct file *file)
+{
+	struct hvsi_struct *hp = (struct hvsi_struct *)tty->driver_data;
+
+	hvsi_get_mctrl(hp);
+	return hp->mctrl;
+}
+
+static int hvsi_tiocmset(struct tty_struct *tty, struct file *file,
+		unsigned int set, unsigned int clear)
+{
+	struct hvsi_struct *hp = (struct hvsi_struct *)tty->driver_data;
+	unsigned long flags;
+	uint16_t new_mctrl;
+
+	/* we can only alter DTR */
+	clear &= TIOCM_DTR;
+	set &= TIOCM_DTR;
+
+	spin_lock_irqsave(&hp->lock, flags);
+
+	new_mctrl = (hp->mctrl & ~clear) | set;
+
+	if (hp->mctrl != new_mctrl) {
+		hvsi_set_mctrl(hp, new_mctrl);
+		hp->mctrl = new_mctrl;
+	}
+	spin_unlock_irqrestore(&hp->lock, flags);
+
+	return 0;
+}
+
+
+static struct tty_operations hvsi_ops = {
+	.open = hvsi_open,
+	.close = hvsi_close,
+	.write = hvsi_write,
+	.hangup = hvsi_hangup,
+	.write_room = hvsi_write_room,
+	.chars_in_buffer = hvsi_chars_in_buffer,
+	.throttle = hvsi_throttle,
+	.unthrottle = hvsi_unthrottle,
+	.tiocmget = hvsi_tiocmget,
+	.tiocmset = hvsi_tiocmset,
+};
+
+static int __init hvsi_init(void)
+{
+	int i;
+
+	hvsi_driver = alloc_tty_driver(hvsi_count);
+	if (!hvsi_driver)
+		return -ENOMEM;
+
+	hvsi_driver->owner = THIS_MODULE;
+	hvsi_driver->devfs_name = "hvsi/";
+	hvsi_driver->driver_name = "hvsi";
+	hvsi_driver->name = "hvsi";
+	hvsi_driver->major = HVSI_MAJOR;
+	hvsi_driver->minor_start = HVSI_MINOR;
+	hvsi_driver->type = TTY_DRIVER_TYPE_SYSTEM;
+	hvsi_driver->init_termios = tty_std_termios;
+	hvsi_driver->init_termios.c_cflag = B9600 | CS8 | CREAD | HUPCL;
+	hvsi_driver->flags = TTY_DRIVER_REAL_RAW;
+	tty_set_operations(hvsi_driver, &hvsi_ops);
+
+	for (i=0; i < hvsi_count; i++) {
+		struct hvsi_struct *hp = &hvsi_ports[i];
+		int ret = 1;
+
+		ret = request_irq(hp->virq, hvsi_interrupt, SA_INTERRUPT, "hvsi", hp);
+		if (ret)
+			printk(KERN_ERR "HVSI: couldn't reserve irq 0x%x (error %i)\n",
+				hp->virq, ret);
+	}
+	hvsi_wait = wait_for_state; /* irqs active now */
+
+	if (tty_register_driver(hvsi_driver))
+		panic("Couldn't register hvsi console driver\n");
+
+	printk(KERN_INFO "HVSI: registered %i devices\n", hvsi_count);
+
+	return 0;
+}
+device_initcall(hvsi_init);
+
+/***** console (not tty) code: *****/
+
+static void hvsi_console_print(struct console *console, const char *buf,
+		unsigned int count)
+{
+	struct hvsi_struct *hp = &hvsi_ports[console->index];
+	char c[HVSI_MAX_OUTGOING_DATA] __ALIGNED__;
+	unsigned int i = 0, n = 0;
+	int ret, donecr = 0;
+
+	mb();
+	if (!is_open(hp))
+		return;
+
+	/*
+	 * ugh, we have to translate LF -> CRLF ourselves, in place.
+	 * copied from hvc_console.c:
+	 */
+	while (count > 0 || i > 0) {
+		if (count > 0 && i < sizeof(c)) {
+			if (buf[n] == '\n' && !donecr) {
+				c[i++] = '\r';
+				donecr = 1;
+			} else {
+				c[i++] = buf[n++];
+				donecr = 0;
+				--count;
+			}
+		} else {
+			ret = hvsi_put_chars(hp, c, i);
+			if (ret < 0)
+				i = 0;
+			i -= ret;
+		}
+	}
+}
+
+static struct tty_driver *hvsi_console_device(struct console *console,
+	int *index)
+{
+	*index = console->index;
+	return hvsi_driver;
+}
+
+static int __init hvsi_console_setup(struct console *console, char *options)
+{
+	struct hvsi_struct *hp = &hvsi_ports[console->index];
+	int ret;
+
+	if (console->index < 0 || console->index >= hvsi_count)
+		return -1;
+
+	/* give the FSP a chance to change the baud rate when we re-open */
+	hvsi_close_protocol(hp);
+
+	ret = hvsi_handshake(hp);
+	if (ret < 0)
+		return ret;
+
+	ret = hvsi_get_mctrl(hp);
+	if (ret < 0)
+		return ret;
+
+	ret = hvsi_set_mctrl(hp, hp->mctrl | TIOCM_DTR);
+	if (ret < 0)
+		return ret;
+
+	hp->flags |= HVSI_CONSOLE;
+
+	return 0;
+}
+
+static struct console hvsi_con_driver = {
+	.name		= "hvsi",
+	.write		= hvsi_console_print,
+	.device		= hvsi_console_device,
+	.setup		= hvsi_console_setup,
+	.flags		= CON_PRINTBUFFER,
+	.index		= -1,
+};
+
+static int __init hvsi_console_init(void)
+{
+	struct device_node *vty;
+
+	hvsi_wait = poll_for_state; /* no irqs yet; must poll */
+
+	/* search device tree for vty nodes */
+	for (vty = of_find_compatible_node(NULL, "serial", "hvterm-protocol");
+			vty != NULL;
+			vty = of_find_compatible_node(vty, "serial", "hvterm-protocol")) {
+		struct hvsi_struct *hp;
+		uint32_t *vtermno;
+		uint32_t *irq;
+
+		vtermno = (uint32_t *)get_property(vty, "reg", NULL);
+		irq = (uint32_t *)get_property(vty, "interrupts", NULL);
+		if (!vtermno || !irq)
+			continue;
+
+		if (hvsi_count >= MAX_NR_HVSI_CONSOLES) {
+			of_node_put(vty);
+			break;
+		}
+
+		hp = &hvsi_ports[hvsi_count];
+		INIT_WORK(&hp->writer, hvsi_write_worker, hp);
+		init_waitqueue_head(&hp->emptyq);
+		init_waitqueue_head(&hp->stateq);
+		hp->lock = SPIN_LOCK_UNLOCKED;
+		hp->index = hvsi_count;
+		hp->inbuf_end = hp->inbuf;
+		hp->state = HVSI_CLOSED;
+		hp->vtermno = *vtermno;
+		hp->virq = virt_irq_create_mapping(irq[0]);
+		if (hp->virq == NO_IRQ) {
+			printk(KERN_ERR "%s: couldn't create irq mapping for 0x%x\n",
+				__FUNCTION__, hp->virq);
+			continue;
+		} else
+			hp->virq = irq_offset_up(hp->virq);
+
+		hvsi_count++;
+	}
+
+	if (hvsi_count)
+		register_console(&hvsi_con_driver);
+	return 0;
+}
+console_initcall(hvsi_console_init);
diff -Nru a/drivers/char/ip2/ip2types.h b/drivers/char/ip2/ip2types.h
--- a/drivers/char/ip2/ip2types.h	2004-10-18 14:56:49 -07:00
+++ b/drivers/char/ip2/ip2types.h	2004-10-18 14:56:49 -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-10-18 14:57:05 -07:00
+++ b/drivers/char/ip2main.c	2004-10-18 14:57:05 -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/Kconfig b/drivers/char/ipmi/Kconfig
--- a/drivers/char/ipmi/Kconfig	2004-10-18 14:56:48 -07:00
+++ b/drivers/char/ipmi/Kconfig	2004-10-18 14:56:48 -07:00
@@ -57,4 +57,11 @@
        help
          This enables the IPMI watchdog timer.
 
+config IPMI_POWEROFF
+       tristate 'IPMI Poweroff'
+       depends on IPMI_HANDLER
+       help
+         This enables a function to power off the system with IPMI if
+	 the IPMI management controller is capable of this.
+
 endmenu
diff -Nru a/drivers/char/ipmi/Makefile b/drivers/char/ipmi/Makefile
--- a/drivers/char/ipmi/Makefile	2004-10-18 14:57:03 -07:00
+++ b/drivers/char/ipmi/Makefile	2004-10-18 14:57:03 -07:00
@@ -8,6 +8,7 @@
 obj-$(CONFIG_IPMI_DEVICE_INTERFACE) += ipmi_devintf.o
 obj-$(CONFIG_IPMI_SI) += ipmi_si.o
 obj-$(CONFIG_IPMI_WATCHDOG) += ipmi_watchdog.o
+obj-$(CONFIG_IPMI_POWEROFF) += ipmi_poweroff.o
 
 ipmi_si.o:	$(ipmi_si-objs)
 	$(LD) -r -o $@ $(ipmi_si-objs)
diff -Nru a/drivers/char/ipmi/ipmi_bt_sm.c b/drivers/char/ipmi/ipmi_bt_sm.c
--- a/drivers/char/ipmi/ipmi_bt_sm.c	2004-10-18 14:56:50 -07:00
+++ b/drivers/char/ipmi/ipmi_bt_sm.c	2004-10-18 14:56:50 -07:00
@@ -31,7 +31,7 @@
 #include <linux/ipmi_msgdefs.h>		/* for completion codes */
 #include "ipmi_si_sm.h"
 
-#define IPMI_BT_VERSION "v32"
+#define IPMI_BT_VERSION "v33"
 
 static int bt_debug = 0x00;	/* Production value 0, see following flags */
 
diff -Nru a/drivers/char/ipmi/ipmi_devintf.c b/drivers/char/ipmi/ipmi_devintf.c
--- a/drivers/char/ipmi/ipmi_devintf.c	2004-10-18 14:56:50 -07:00
+++ b/drivers/char/ipmi/ipmi_devintf.c	2004-10-18 14:56:50 -07:00
@@ -45,7 +45,7 @@
 #include <asm/semaphore.h>
 #include <linux/init.h>
 
-#define IPMI_DEVINTF_VERSION "v32"
+#define IPMI_DEVINTF_VERSION "v33"
 
 struct ipmi_file_private
 {
diff -Nru a/drivers/char/ipmi/ipmi_kcs_sm.c b/drivers/char/ipmi/ipmi_kcs_sm.c
--- a/drivers/char/ipmi/ipmi_kcs_sm.c	2004-10-18 14:55:55 -07:00
+++ b/drivers/char/ipmi/ipmi_kcs_sm.c	2004-10-18 14:55:55 -07:00
@@ -42,7 +42,7 @@
 #include <linux/ipmi_msgdefs.h>		/* for completion codes */
 #include "ipmi_si_sm.h"
 
-#define IPMI_KCS_VERSION "v32"
+#define IPMI_KCS_VERSION "v33"
 
 /* Set this if you want a printout of why the state machine was hosed
    when it gets hosed. */
diff -Nru a/drivers/char/ipmi/ipmi_msghandler.c b/drivers/char/ipmi/ipmi_msghandler.c
--- a/drivers/char/ipmi/ipmi_msghandler.c	2004-10-18 14:56:32 -07:00
+++ b/drivers/char/ipmi/ipmi_msghandler.c	2004-10-18 14:56:32 -07:00
@@ -46,7 +46,8 @@
 #include <linux/init.h>
 #include <linux/proc_fs.h>
 
-#define IPMI_MSGHANDLER_VERSION "v32"
+#define PFX "IPMI message handler: "
+#define IPMI_MSGHANDLER_VERSION "v33"
 
 struct ipmi_recv_msg *ipmi_alloc_recv_msg(void);
 static int ipmi_init_msghandler(void);
@@ -895,6 +896,12 @@
 	return rv;
 }
 
+void ipmi_user_set_run_to_completion(ipmi_user_t user, int val)
+{
+	user->intf->handlers->set_run_to_completion(user->intf->send_info,
+						    val);
+}
+
 static unsigned char
 ipmb_checksum(unsigned char *data, int size)
 {
@@ -1686,8 +1693,8 @@
 			intf->curr_channel = IPMI_MAX_CHANNELS;
 			wake_up(&intf->waitq);
 
-			printk(KERN_WARNING "ipmi_msghandler: Error sending"
-			       "channel information: %d\n",
+			printk(KERN_WARNING PFX
+			       "Error sending channel information: %d\n",
 			       rv);
 		}
 	}
@@ -2351,7 +2358,7 @@
 	} else {
 		/* There's too many things in the queue, discard this
 		   message. */
-		printk(KERN_WARNING "ipmi: Event queue full, discarding an"
+		printk(KERN_WARNING PFX "Event queue full, discarding an"
 		       " incoming event\n");
 	}
 
@@ -2433,10 +2440,34 @@
 #endif
 	if (msg->rsp_size < 2) {
 		/* Message is too small to be correct. */
-		requeue = 0;
-	} else if ((msg->rsp[0] == ((IPMI_NETFN_APP_REQUEST|1) << 2))
-		   && (msg->rsp[1] == IPMI_SEND_MSG_CMD)
-		   && (msg->user_data != NULL))
+		printk(KERN_WARNING PFX "BMC returned to small a message"
+		       " for netfn %x cmd %x, got %d bytes\n",
+		       (msg->data[0] >> 2) | 1, msg->data[1], msg->rsp_size);
+
+		/* Generate an error response for the message. */
+		msg->rsp[0] = msg->data[0] | (1 << 2);
+		msg->rsp[1] = msg->data[1];
+		msg->rsp[2] = IPMI_ERR_UNSPECIFIED;
+		msg->rsp_size = 3;
+	} else if (((msg->rsp[0] >> 2) != ((msg->data[0] >> 2) | 1))/* Netfn */
+		   || (msg->rsp[1] != msg->data[1]))		  /* Command */
+	{
+		/* The response is not even marginally correct. */
+		printk(KERN_WARNING PFX "BMC returned incorrect response,"
+		       " expected netfn %x cmd %x, got netfn %x cmd %x\n",
+		       (msg->data[0] >> 2) | 1, msg->data[1],
+		       msg->rsp[0] >> 2, msg->rsp[1]);
+
+		/* Generate an error response for the message. */
+		msg->rsp[0] = msg->data[0] | (1 << 2);
+		msg->rsp[1] = msg->data[1];
+		msg->rsp[2] = IPMI_ERR_UNSPECIFIED;
+		msg->rsp_size = 3;
+	}
+
+	if ((msg->rsp[0] == ((IPMI_NETFN_APP_REQUEST|1) << 2))
+	    && (msg->rsp[1] == IPMI_SEND_MSG_CMD)
+	    && (msg->user_data != NULL))
 	{
 		/* It's a response to a response we sent.  For this we
 		   deliver a send message response to the user. */
@@ -2502,7 +2533,9 @@
 			requeue = 0;
 		}
 
-	} else if (msg->rsp[1] == IPMI_READ_EVENT_MSG_BUFFER_CMD) {
+	} else if ((msg->rsp[0] == ((IPMI_NETFN_APP_REQUEST|1) << 2))
+		   && (msg->rsp[1] == IPMI_READ_EVENT_MSG_BUFFER_CMD))
+	{
 		/* It's an asyncronous event. */
 		requeue = handle_read_event_rsp(intf, msg);
 	} else {
@@ -3114,7 +3147,7 @@
 
 	proc_ipmi_root = proc_mkdir("ipmi", NULL);
 	if (!proc_ipmi_root) {
-	    printk("Unable to create IPMI proc dir");
+	    printk(KERN_ERR PFX "Unable to create IPMI proc dir");
 	    return -ENOMEM;
 	}
 
@@ -3166,11 +3199,11 @@
 	/* Check for buffer leaks. */
 	count = atomic_read(&smi_msg_inuse_count);
 	if (count != 0)
-		printk("ipmi_msghandler: SMI message count %d at exit\n",
+		printk(KERN_WARNING PFX "SMI message count %d at exit\n",
 		       count);
 	count = atomic_read(&recv_msg_inuse_count);
 	if (count != 0)
-		printk("ipmi_msghandler: recv message count %d at exit\n",
+		printk(KERN_WARNING PFX "recv message count %d at exit\n",
 		       count);
 }
 module_exit(cleanup_ipmi);
@@ -3207,3 +3240,4 @@
 EXPORT_SYMBOL(ipmi_set_my_LUN);
 EXPORT_SYMBOL(ipmi_get_my_LUN);
 EXPORT_SYMBOL(ipmi_smi_add_proc_entry);
+EXPORT_SYMBOL(ipmi_user_set_run_to_completion);
diff -Nru a/drivers/char/ipmi/ipmi_poweroff.c b/drivers/char/ipmi/ipmi_poweroff.c
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/drivers/char/ipmi/ipmi_poweroff.c	2004-10-18 14:57:23 -07:00
@@ -0,0 +1,543 @@
+/*
+ * ipmi_poweroff.c
+ *
+ * MontaVista IPMI Poweroff extension to sys_reboot
+ *
+ * Author: MontaVista Software, Inc.
+ *         Steven Dake <sdake@mvista.com>
+ *         Corey Minyard <cminyard@mvista.com>
+ *         source@mvista.com
+ *
+ * Copyright 2002,2004 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.
+ *
+ *
+ *  THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ *  WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ *  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ *  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ *  OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ *  ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
+ *  TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
+ *  USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ *  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.
+ */
+#include <asm/semaphore.h>
+#include <linux/kdev_t.h>
+#include <linux/module.h>
+#include <linux/string.h>
+#include <linux/ipmi.h>
+#include <linux/ipmi_smi.h>
+
+#define PFX "IPMI poweroff: "
+#define IPMI_POWEROFF_VERSION	"v33"
+
+/* Where to we insert our poweroff function? */
+extern void (*pm_power_off)(void);
+
+/* Stuff from the get device id command. */
+unsigned int mfg_id;
+unsigned int prod_id;
+unsigned char capabilities;
+
+/* We use our own messages for this operation, we don't let the system
+   allocate them, since we may be in a panic situation.  The whole
+   thing is single-threaded, anyway, so multiple messages are not
+   required. */
+static void dummy_smi_free(struct ipmi_smi_msg *msg)
+{
+}
+static void dummy_recv_free(struct ipmi_recv_msg *msg)
+{
+}
+static struct ipmi_smi_msg halt_smi_msg =
+{
+	.done = dummy_smi_free
+};
+static struct ipmi_recv_msg halt_recv_msg =
+{
+	.done = dummy_recv_free
+};
+
+
+/*
+ * Code to send a message and wait for the reponse.
+ */
+
+static void receive_handler(struct ipmi_recv_msg *recv_msg, void *handler_data)
+{
+	struct semaphore *sem = recv_msg->user_msg_data;
+
+	if (sem)
+		up(sem);
+}
+
+static struct ipmi_user_hndl ipmi_poweroff_handler =
+{
+	.ipmi_recv_hndl = receive_handler
+};
+
+
+static int ipmi_request_wait_for_response(ipmi_user_t            user,
+					  struct ipmi_addr       *addr,
+					  struct kernel_ipmi_msg *send_msg)
+{
+	int              rv;
+	struct semaphore sem;
+
+	sema_init (&sem, 0);
+
+	rv = ipmi_request_supply_msgs(user, addr, 0, send_msg, &sem,
+				      &halt_smi_msg, &halt_recv_msg, 0);
+	if (rv)
+		return rv;
+
+	down (&sem);
+
+	return halt_recv_msg.msg.data[0];
+}
+
+/* We are in run-to-completion mode, no semaphore is desired. */
+static int ipmi_request_in_rc_mode(ipmi_user_t            user,
+				   struct ipmi_addr       *addr,
+				   struct kernel_ipmi_msg *send_msg)
+{
+	int              rv;
+
+	rv = ipmi_request_supply_msgs(user, addr, 0, send_msg, NULL,
+				      &halt_smi_msg, &halt_recv_msg, 0);
+	if (rv)
+		return rv;
+
+	return halt_recv_msg.msg.data[0];
+}
+
+/*
+ * ATCA Support
+ */
+
+#define IPMI_NETFN_ATCA			0x2c
+#define IPMI_ATCA_SET_POWER_CMD		0x11
+#define IPMI_ATCA_GET_ADDR_INFO_CMD	0x01
+#define IPMI_PICMG_ID			0
+
+static int ipmi_atca_detect (ipmi_user_t user)
+{
+	struct ipmi_system_interface_addr smi_addr;
+	struct kernel_ipmi_msg            send_msg;
+	int                               rv;
+	unsigned char                     data[1];
+
+        /*
+         * Configure IPMI address for local access
+         */
+        smi_addr.addr_type = IPMI_SYSTEM_INTERFACE_ADDR_TYPE;
+        smi_addr.channel = IPMI_BMC_CHANNEL;
+        smi_addr.lun = 0;
+
+	/*
+	 * Use get address info to check and see if we are ATCA
+	 */
+	send_msg.netfn = IPMI_NETFN_ATCA;
+	send_msg.cmd = IPMI_ATCA_GET_ADDR_INFO_CMD;
+	data[0] = IPMI_PICMG_ID;
+	send_msg.data = data;
+	send_msg.data_len = sizeof(data);
+	rv = ipmi_request_wait_for_response(user,
+					    (struct ipmi_addr *) &smi_addr,
+					    &send_msg);
+	return !rv;
+}
+
+static void ipmi_poweroff_atca (ipmi_user_t user)
+{
+	struct ipmi_system_interface_addr smi_addr;
+	struct kernel_ipmi_msg            send_msg;
+	int                               rv;
+	unsigned char                     data[4];
+
+        /*
+         * Configure IPMI address for local access
+         */
+        smi_addr.addr_type = IPMI_SYSTEM_INTERFACE_ADDR_TYPE;
+        smi_addr.channel = IPMI_BMC_CHANNEL;
+        smi_addr.lun = 0;
+
+	printk(KERN_INFO PFX "Powering down via ATCA power command\n");
+
+	/*
+	 * Power down
+	 */
+	send_msg.netfn = IPMI_NETFN_ATCA;
+	send_msg.cmd = IPMI_ATCA_SET_POWER_CMD;
+	data[0] = IPMI_PICMG_ID;
+	data[1] = 0; /* FRU id */
+	data[2] = 0; /* Power Level */
+	data[3] = 0; /* Don't change saved presets */
+	send_msg.data = data;
+	send_msg.data_len = sizeof (data);
+	rv = ipmi_request_in_rc_mode(user,
+				     (struct ipmi_addr *) &smi_addr,
+				     &send_msg);
+	if (rv) {
+		printk(KERN_ERR PFX "Unable to send ATCA powerdown message,"
+		       " IPMI error 0x%x\n", rv);
+		goto out;
+	}
+
+ out:
+	return;
+}
+
+/*
+ * CPI1 Support
+ */
+
+#define IPMI_NETFN_OEM_1				0xf8
+#define OEM_GRP_CMD_SET_RESET_STATE		0x84
+#define OEM_GRP_CMD_SET_POWER_STATE		0x82
+#define IPMI_NETFN_OEM_8				0xf8
+#define OEM_GRP_CMD_REQUEST_HOTSWAP_CTRL	0x80
+#define OEM_GRP_CMD_GET_SLOT_GA			0xa3
+#define IPMI_NETFN_SENSOR_EVT			0x10
+#define IPMI_CMD_GET_EVENT_RECEIVER		0x01
+
+#define IPMI_CPI1_PRODUCT_ID		0x000157
+#define IPMI_CPI1_MANUFACTURER_ID	0x0108
+
+static int ipmi_cpi1_detect (ipmi_user_t user)
+{
+	return ((mfg_id == IPMI_CPI1_MANUFACTURER_ID)
+		&& (prod_id == IPMI_CPI1_PRODUCT_ID));
+}
+
+static void ipmi_poweroff_cpi1 (ipmi_user_t user)
+{
+	struct ipmi_system_interface_addr smi_addr;
+	struct ipmi_ipmb_addr             ipmb_addr;
+	struct kernel_ipmi_msg            send_msg;
+	int                               rv;
+	unsigned char                     data[1];
+	int                               slot;
+	unsigned char                     hotswap_ipmb;
+	unsigned char                     aer_addr;
+	unsigned char                     aer_lun;
+
+        /*
+         * Configure IPMI address for local access
+         */
+        smi_addr.addr_type = IPMI_SYSTEM_INTERFACE_ADDR_TYPE;
+        smi_addr.channel = IPMI_BMC_CHANNEL;
+        smi_addr.lun = 0;
+
+	printk(KERN_INFO PFX "Powering down via CPI1 power command\n");
+
+	/*
+	 * Get IPMI ipmb address
+	 */
+	send_msg.netfn = IPMI_NETFN_OEM_8 >> 2;
+	send_msg.cmd = OEM_GRP_CMD_GET_SLOT_GA;
+	send_msg.data = NULL;
+	send_msg.data_len = 0;
+	rv = ipmi_request_in_rc_mode(user,
+				     (struct ipmi_addr *) &smi_addr,
+				     &send_msg);
+	if (rv)
+		goto out;
+	slot = halt_recv_msg.msg.data[1];
+	hotswap_ipmb = (slot > 9) ? (0xb0 + 2 * slot) : (0xae + 2 * slot);
+
+	/*
+	 * Get active event receiver
+	 */
+	send_msg.netfn = IPMI_NETFN_SENSOR_EVT >> 2;
+	send_msg.cmd = IPMI_CMD_GET_EVENT_RECEIVER;
+	send_msg.data = NULL;
+	send_msg.data_len = 0;
+	rv = ipmi_request_in_rc_mode(user,
+				     (struct ipmi_addr *) &smi_addr,
+				     &send_msg);
+	if (rv)
+		goto out;
+	aer_addr = halt_recv_msg.msg.data[1];
+	aer_lun = halt_recv_msg.msg.data[2];
+
+	/*
+	 * Setup IPMB address target instead of local target
+	 */
+	ipmb_addr.addr_type = IPMI_IPMB_ADDR_TYPE;
+	ipmb_addr.channel = 0;
+	ipmb_addr.slave_addr = aer_addr;
+	ipmb_addr.lun = aer_lun;
+
+	/*
+	 * Send request hotswap control to remove blade from dpv
+	 */
+	send_msg.netfn = IPMI_NETFN_OEM_8 >> 2;
+	send_msg.cmd = OEM_GRP_CMD_REQUEST_HOTSWAP_CTRL;
+	send_msg.data = &hotswap_ipmb;
+	send_msg.data_len = 1;
+	ipmi_request_in_rc_mode(user,
+				(struct ipmi_addr *) &ipmb_addr,
+				&send_msg);
+
+	/*
+	 * Set reset asserted
+	 */
+	send_msg.netfn = IPMI_NETFN_OEM_1 >> 2;
+	send_msg.cmd = OEM_GRP_CMD_SET_RESET_STATE;
+	send_msg.data = data;
+	data[0] = 1; /* Reset asserted state */
+	send_msg.data_len = 1;
+	rv = ipmi_request_in_rc_mode(user,
+				     (struct ipmi_addr *) &smi_addr,
+				     &send_msg);
+	if (rv)
+		goto out;
+
+	/*
+	 * Power down
+	 */
+	send_msg.netfn = IPMI_NETFN_OEM_1 >> 2;
+	send_msg.cmd = OEM_GRP_CMD_SET_POWER_STATE;
+	send_msg.data = data;
+	data[0] = 1; /* Power down state */
+	send_msg.data_len = 1;
+	rv = ipmi_request_in_rc_mode(user,
+				     (struct ipmi_addr *) &smi_addr,
+				     &send_msg);
+	if (rv)
+		goto out;
+
+ out:
+	return;
+}
+
+/*
+ * Standard chassis support
+ */
+
+#define IPMI_NETFN_CHASSIS_REQUEST	0
+#define IPMI_CHASSIS_CONTROL_CMD	0x02
+
+static int ipmi_chassis_detect (ipmi_user_t user)
+{
+	/* Chassis support, use it. */
+	return (capabilities & 0x80);
+}
+
+static void ipmi_poweroff_chassis (ipmi_user_t user)
+{
+	struct ipmi_system_interface_addr smi_addr;
+	struct kernel_ipmi_msg            send_msg;
+	int                               rv;
+	unsigned char                     data[1];
+
+        /*
+         * Configure IPMI address for local access
+         */
+        smi_addr.addr_type = IPMI_SYSTEM_INTERFACE_ADDR_TYPE;
+        smi_addr.channel = IPMI_BMC_CHANNEL;
+        smi_addr.lun = 0;
+
+	printk(KERN_INFO PFX "Powering down via IPMI chassis control command\n");
+
+	/*
+	 * Power down
+	 */
+	send_msg.netfn = IPMI_NETFN_CHASSIS_REQUEST;
+	send_msg.cmd = IPMI_CHASSIS_CONTROL_CMD;
+	data[0] = 0; /* Power down */
+	send_msg.data = data;
+	send_msg.data_len = sizeof(data);
+	rv = ipmi_request_in_rc_mode(user,
+				     (struct ipmi_addr *) &smi_addr,
+				     &send_msg);
+	if (rv) {
+		printk(KERN_ERR PFX "Unable to send chassis powerdown message,"
+		       " IPMI error 0x%x\n", rv);
+		goto out;
+	}
+
+ out:
+	return;
+}
+
+
+/* Table of possible power off functions. */
+struct poweroff_function {
+	char *platform_type;
+	int  (*detect)(ipmi_user_t user);
+	void (*poweroff_func)(ipmi_user_t user);
+};
+
+static struct poweroff_function poweroff_functions[] = {
+	{ "ATCA",    ipmi_atca_detect, ipmi_poweroff_atca },
+	{ "CPI1",    ipmi_cpi1_detect, ipmi_poweroff_cpi1 },
+	/* Chassis should generally be last, other things should override
+	   it. */
+	{ "chassis", ipmi_chassis_detect, ipmi_poweroff_chassis },
+};
+#define NUM_PO_FUNCS (sizeof(poweroff_functions) \
+		      / sizeof(struct poweroff_function))
+
+
+/* Our local state. */
+static int ready = 0;
+static ipmi_user_t ipmi_user;
+static void (*specific_poweroff_func)(ipmi_user_t user) = NULL;
+
+/* Holds the old poweroff function so we can restore it on removal. */
+static void (*old_poweroff_func)(void);
+
+
+/* Called on a powerdown request. */
+static void ipmi_poweroff_function (void)
+{
+	if (!ready)
+		return;
+
+	/* Use run-to-completion mode, since interrupts may be off. */
+	ipmi_user_set_run_to_completion(ipmi_user, 1);
+	specific_poweroff_func(ipmi_user);
+	ipmi_user_set_run_to_completion(ipmi_user, 0);
+}
+
+/* Wait for an IPMI interface to be installed, the first one installed
+   will be grabbed by this code and used to perform the powerdown. */
+static void ipmi_po_new_smi(int if_num)
+{
+	struct ipmi_system_interface_addr smi_addr;
+	struct kernel_ipmi_msg            send_msg;
+	int                               rv;
+	int                               i;
+
+	if (ready)
+		return;
+
+	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);
+		return;
+	}
+
+        /*
+         * Do a get device ide and store some results, since this is
+	 * used by several functions.
+         */
+        smi_addr.addr_type = IPMI_SYSTEM_INTERFACE_ADDR_TYPE;
+        smi_addr.channel = IPMI_BMC_CHANNEL;
+        smi_addr.lun = 0;
+
+	send_msg.netfn = IPMI_NETFN_APP_REQUEST;
+	send_msg.cmd = IPMI_GET_DEVICE_ID_CMD;
+	send_msg.data = NULL;
+	send_msg.data_len = 0;
+	rv = ipmi_request_wait_for_response(ipmi_user,
+					    (struct ipmi_addr *) &smi_addr,
+					    &send_msg);
+	if (rv) {
+		printk(KERN_ERR PFX "Unable to send IPMI get device id info,"
+		       " IPMI error 0x%x\n", rv);
+		goto out_err;
+	}
+
+	if (halt_recv_msg.msg.data_len < 12) {
+		printk(KERN_ERR PFX "(chassis) IPMI get device id info too,"
+		       " short, was %d bytes, needed %d bytes\n",
+		       halt_recv_msg.msg.data_len, 12);
+		goto out_err;
+	}
+
+	mfg_id = (halt_recv_msg.msg.data[7]
+		  | (halt_recv_msg.msg.data[8] << 8)
+		  | (halt_recv_msg.msg.data[9] << 16));
+	prod_id = (halt_recv_msg.msg.data[10]
+		   | (halt_recv_msg.msg.data[11] << 8));
+	capabilities = halt_recv_msg.msg.data[6];
+
+
+	/* Scan for a poweroff method */
+	for (i=0; i<NUM_PO_FUNCS; i++) {
+		if (poweroff_functions[i].detect(ipmi_user))
+			goto found;
+	}
+
+ out_err:
+	printk(KERN_ERR PFX "Unable to find a poweroff function that"
+	       " will work, giving up\n");
+	ipmi_destroy_user(ipmi_user);
+	return;
+
+ found:
+	printk(KERN_INFO PFX "Found a %s style poweroff function\n",
+	       poweroff_functions[i].platform_type);
+	specific_poweroff_func = poweroff_functions[i].poweroff_func;
+	old_poweroff_func = pm_power_off;
+	pm_power_off = ipmi_poweroff_function;
+	ready = 1;
+}
+
+static void ipmi_po_smi_gone(int if_num)
+{
+	/* This can never be called, because once poweroff driver is
+	   registered, the interface can't go away until the power
+	   driver is unregistered. */
+}
+
+static struct ipmi_smi_watcher smi_watcher =
+{
+	.owner    = THIS_MODULE,
+	.new_smi  = ipmi_po_new_smi,
+	.smi_gone = ipmi_po_smi_gone
+};
+
+
+/*
+ * Startup and shutdown functions.
+ */
+static int ipmi_poweroff_init (void)
+{
+	int rv;
+
+	printk ("Copyright (C) 2004 MontaVista Software -"
+		" IPMI Powerdown via sys_reboot version "
+		IPMI_POWEROFF_VERSION ".\n");
+
+	rv = ipmi_smi_watcher_register(&smi_watcher);
+	if (rv)
+		printk(KERN_ERR PFX "Unable to register SMI watcher: %d\n", rv);
+
+	return rv;
+}
+
+#ifdef MODULE
+static __exit void ipmi_poweroff_cleanup(void)
+{
+	int rv;
+
+	ipmi_smi_watcher_unregister(&smi_watcher);
+
+	if (ready) {
+		rv = ipmi_destroy_user(ipmi_user);
+		if (rv)
+			printk(KERN_ERR PFX "could not cleanup the IPMI"
+			       " user: 0x%x\n", rv);
+		pm_power_off = old_poweroff_func;
+	}
+}
+module_exit(ipmi_poweroff_cleanup);
+#endif
+
+module_init(ipmi_poweroff_init);
+MODULE_LICENSE("GPL");
diff -Nru a/drivers/char/ipmi/ipmi_si_intf.c b/drivers/char/ipmi/ipmi_si_intf.c
--- a/drivers/char/ipmi/ipmi_si_intf.c	2004-10-18 14:55:55 -07:00
+++ b/drivers/char/ipmi/ipmi_si_intf.c	2004-10-18 14:55:55 -07:00
@@ -76,7 +76,7 @@
 #include "ipmi_si_sm.h"
 #include <linux/init.h>
 
-#define IPMI_SI_VERSION "v32"
+#define IPMI_SI_VERSION "v33"
 
 /* Measure times between events in the driver. */
 #undef DEBUG_TIMING
@@ -146,6 +146,11 @@
 	/* The I/O port of an SI interface. */
 	int                 port;
 
+	/* The space between start addresses of the two ports.  For
+	   instance, if the first port is 0xca2 and the spacing is 4, then
+	   the second port is 0xca6. */
+	unsigned int        spacing;
+
 	/* zero if no irq; */
 	int                 irq;
 
@@ -452,14 +457,20 @@
 
 			/* Take off the event flag. */
 			smi_info->msg_flags &= ~EVENT_MSG_BUFFER_FULL;
+			handle_flags(smi_info);
 		} else {
 			spin_lock(&smi_info->count_lock);
 			smi_info->events++;
 			spin_unlock(&smi_info->count_lock);
 
+			/* Do this before we deliver the message
+			   because delivering the message releases the
+			   lock and something else can mess with the
+			   state. */
+			handle_flags(smi_info);
+
 			deliver_recv_msg(smi_info, msg);
 		}
-		handle_flags(smi_info);
 		break;
 	}
 
@@ -482,14 +493,20 @@
 
 			/* Take off the msg flag. */
 			smi_info->msg_flags &= ~RECEIVE_MSG_AVAIL;
+			handle_flags(smi_info);
 		} else {
 			spin_lock(&smi_info->count_lock);
 			smi_info->incoming_messages++;
 			spin_unlock(&smi_info->count_lock);
 
+			/* Do this before we deliver the message
+			   because delivering the message releases the
+			   lock and something else can mess with the
+			   state. */
+			handle_flags(smi_info);
+
 			deliver_recv_msg(smi_info, msg);
 		}
-		handle_flags(smi_info);
 		break;
 	}
 
@@ -568,6 +585,9 @@
 		smi_info->hosed_count++;
 		spin_unlock(&smi_info->count_lock);
 
+		/* Do the before return_hosed_msg, because that
+		   releases the lock. */
+		smi_info->si_state = SI_NORMAL;
 		if (smi_info->curr_msg != NULL) {
 			/* If we were handling a user message, format
                            a response to send to the upper layer to
@@ -575,7 +595,6 @@
 			return_hosed_msg(smi_info);
 		}
 		si_sm_result = smi_info->handlers->event(smi_info->si_sm, 0);
-		smi_info->si_state = SI_NORMAL;
 	}
 
 	/* We prefer handling attn over new messages. */
@@ -872,9 +891,10 @@
 
 #define DEVICE_NAME "ipmi_si"
 
-#define DEFAULT_KCS_IO_PORT 0xca2
-#define DEFAULT_SMIC_IO_PORT 0xca9
-#define DEFAULT_BT_IO_PORT   0xe4
+#define DEFAULT_KCS_IO_PORT	0xca2
+#define DEFAULT_SMIC_IO_PORT	0xca9
+#define DEFAULT_BT_IO_PORT	0xe4
+#define DEFAULT_REGSPACING	1
 
 static int           si_trydefaults = 1;
 static char          *si_type[SI_MAX_PARMS] = { NULL, NULL, NULL, NULL };
@@ -886,6 +906,12 @@
 static int num_ports = 0;
 static int           irqs[SI_MAX_PARMS] = { 0, 0, 0, 0 };
 static int num_irqs = 0;
+static int           regspacings[SI_MAX_PARMS] = { 0, 0, 0, 0 };
+static int num_regspacings = 0;
+static int           regsizes[SI_MAX_PARMS] = { 0, 0, 0, 0 };
+static int num_regsizes = 0;
+static int           regshifts[SI_MAX_PARMS] = { 0, 0, 0, 0 };
+static int num_regshifts = 0;
 
 
 module_param_named(trydefaults, si_trydefaults, bool, 0);
@@ -912,6 +938,23 @@
 		 " addresses separated by commas.  Only use if an interface"
 		 " has an interrupt.  Otherwise, set it to zero or leave"
 		 " it blank.");
+module_param_array(regspacings, int, num_regspacings, 0);
+MODULE_PARM_DESC(regspacings, "The number of bytes between the start address"
+		 " and each successive register used by the interface.  For"
+		 " instance, if the start address is 0xca2 and the spacing"
+		 " is 2, then the second address is at 0xca4.  Defaults"
+		 " to 1.");
+module_param_array(regsizes, int, num_regsizes, 0);
+MODULE_PARM_DESC(regsizes, "The size of the specific IPMI register in bytes."
+		 " This should generally be 1, 2, 4, or 8 for an 8-bit,"
+		 " 16-bit, 32-bit, or 64-bit register.  Use this if you"
+		 " the 8-bit IPMI register has to be read from a larger"
+		 " register.");
+module_param_array(regshifts, int, num_regshifts, 0);
+MODULE_PARM_DESC(regshifts, "The amount to shift the data read from the."
+		 " IPMI register, in bits.  For instance, if the data"
+		 " is read from a 32-bit word and the IPMI data is in"
+		 " bit 8-15, then the shift would be 8");
 
 #define IPMI_MEM_ADDR_SPACE 1
 #define IPMI_IO_ADDR_SPACE  2
@@ -977,7 +1020,7 @@
 {
 	unsigned int *addr = io->info;
 
-	return inb((*addr)+offset);
+	return inb((*addr)+(offset*io->regspacing));
 }
 
 static void port_outb(struct si_sm_io *io, unsigned int offset,
@@ -985,30 +1028,97 @@
 {
 	unsigned int *addr = io->info;
 
-	outb(b, (*addr)+offset);
+	outb(b, (*addr)+(offset * io->regspacing));
 }
 
-static int port_setup(struct smi_info *info)
+static unsigned char port_inw(struct si_sm_io *io, unsigned int offset)
 {
-	unsigned int *addr = info->io.info;
+	unsigned int *addr = io->info;
 
-	if (!addr || (!*addr))
-		return -ENODEV;
+	return (inw((*addr)+(offset * io->regspacing)) >> io->regshift) & 0xff;
+}
 
-	if (request_region(*addr, info->io_size, DEVICE_NAME) == NULL)
-		return -EIO;
-	return 0;
+static void port_outw(struct si_sm_io *io, unsigned int offset,
+		      unsigned char b)
+{
+	unsigned int *addr = io->info;
+
+	outw(b << io->regshift, (*addr)+(offset * io->regspacing));
+}
+
+static unsigned char port_inl(struct si_sm_io *io, unsigned int offset)
+{
+	unsigned int *addr = io->info;
+
+	return (inl((*addr)+(offset * io->regspacing)) >> io->regshift) & 0xff;
+}
+
+static void port_outl(struct si_sm_io *io, unsigned int offset,
+		      unsigned char b)
+{
+	unsigned int *addr = io->info;
+
+	outl(b << io->regshift, (*addr)+(offset * io->regspacing));
 }
 
 static void port_cleanup(struct smi_info *info)
 {
 	unsigned int *addr = info->io.info;
+	int           mapsize;
 
-	if (addr && (*addr))
-		release_region (*addr, info->io_size);
+	if (addr && (*addr)) {
+		mapsize = ((info->io_size * info->io.regspacing)
+			   - (info->io.regspacing - info->io.regsize));
+
+		release_region (*addr, mapsize);
+	}
 	kfree(info);
 }
 
+static int port_setup(struct smi_info *info)
+{
+	unsigned int *addr = info->io.info;
+	int           mapsize;
+
+	if (!addr || (!*addr))
+		return -ENODEV;
+
+	info->io_cleanup = port_cleanup;
+
+	/* Figure out the actual inb/inw/inl/etc routine to use based
+	   upon the register size. */
+	switch (info->io.regsize) {
+	case 1:
+		info->io.inputb = port_inb;
+		info->io.outputb = port_outb;
+		break;
+	case 2:
+		info->io.inputb = port_inw;
+		info->io.outputb = port_outw;
+		break;
+	case 4:
+		info->io.inputb = port_inl;
+		info->io.outputb = port_outl;
+		break;
+	default:
+		printk("ipmi_si: Invalid register size: %d\n",
+		       info->io.regsize);
+		return -EINVAL;
+	}
+
+	/* Calculate the total amount of memory to claim.  This is an
+	 * unusual looking calculation, but it avoids claiming any
+	 * more memory than it has to.  It will claim everything
+	 * between the first address to the end of the last full
+	 * register. */
+	mapsize = ((info->io_size * info->io.regspacing)
+		   - (info->io.regspacing - info->io.regsize));
+
+	if (request_region(*addr, mapsize, DEVICE_NAME) == NULL)
+		return -EIO;
+	return 0;
+}
+
 static int try_init_port(int intf_num, struct smi_info **new_info)
 {
 	struct smi_info *info;
@@ -1028,11 +1138,15 @@
 	memset(info, 0, sizeof(*info));
 
 	info->io_setup = port_setup;
-	info->io_cleanup = port_cleanup;
-	info->io.inputb = port_inb;
-	info->io.outputb = port_outb;
 	info->io.info = &(ports[intf_num]);
 	info->io.addr = NULL;
+	info->io.regspacing = regspacings[intf_num];
+	if (!info->io.regspacing)
+		info->io.regspacing = DEFAULT_REGSPACING;
+	info->io.regsize = regsizes[intf_num];
+	if (!info->io.regsize)
+		info->io.regsize = DEFAULT_REGSPACING;
+	info->io.regshift = regshifts[intf_num];
 	info->irq = 0;
 	info->irq_setup = NULL;
 	*new_info = info;
@@ -1047,44 +1161,125 @@
 
 static unsigned char mem_inb(struct si_sm_io *io, unsigned int offset)
 {
-	return readb((io->addr)+offset);
+	return readb((io->addr)+(offset * io->regspacing));
 }
 
 static void mem_outb(struct si_sm_io *io, unsigned int offset,
 		     unsigned char b)
 {
-	writeb(b, (io->addr)+offset);
+	writeb(b, (io->addr)+(offset * io->regspacing));
 }
 
-static int mem_setup(struct smi_info *info)
+static unsigned char mem_inw(struct si_sm_io *io, unsigned int offset)
 {
-	unsigned long *addr = info->io.info;
+	return (readw((io->addr)+(offset * io->regspacing)) >> io->regshift)
+		&& 0xff;
+}
 
-	if (!addr || (!*addr))
-		return -ENODEV;
+static void mem_outw(struct si_sm_io *io, unsigned int offset,
+		     unsigned char b)
+{
+	writeb(b << io->regshift, (io->addr)+(offset * io->regspacing));
+}
 
-	if (request_mem_region(*addr, info->io_size, DEVICE_NAME) == NULL)
-		return -EIO;
+static unsigned char mem_inl(struct si_sm_io *io, unsigned int offset)
+{
+	return (readl((io->addr)+(offset * io->regspacing)) >> io->regshift)
+		&& 0xff;
+}
 
-	info->io.addr = ioremap(*addr, info->io_size);
-	if (info->io.addr == NULL) {
-		release_mem_region(*addr, info->io_size);
-		return -EIO;
-	}
-	return 0;
+static void mem_outl(struct si_sm_io *io, unsigned int offset,
+		     unsigned char b)
+{
+	writel(b << io->regshift, (io->addr)+(offset * io->regspacing));
 }
 
+#ifdef readq
+static unsigned char mem_inq(struct si_sm_io *io, unsigned int offset)
+{
+	return (readq((io->addr)+(offset * io->regspacing)) >> io->regshift)
+		&& 0xff;
+}
+
+static void mem_outq(struct si_sm_io *io, unsigned int offset,
+		     unsigned char b)
+{
+	writeq(b << io->regshift, (io->addr)+(offset * io->regspacing));
+}
+#endif
+
 static void mem_cleanup(struct smi_info *info)
 {
 	unsigned long *addr = info->io.info;
+	int           mapsize;
 
 	if (info->io.addr) {
 		iounmap(info->io.addr);
-		release_mem_region(*addr, info->io_size);
+
+		mapsize = ((info->io_size * info->io.regspacing)
+			   - (info->io.regspacing - info->io.regsize));
+
+		release_mem_region(*addr, mapsize);
 	}
 	kfree(info);
 }
 
+static int mem_setup(struct smi_info *info)
+{
+	unsigned long *addr = info->io.info;
+	int           mapsize;
+
+	if (!addr || (!*addr))
+		return -ENODEV;
+
+	info->io_cleanup = mem_cleanup;
+
+	/* Figure out the actual readb/readw/readl/etc routine to use based
+	   upon the register size. */
+	switch (info->io.regsize) {
+	case 1:
+		info->io.inputb = mem_inb;
+		info->io.outputb = mem_outb;
+		break;
+	case 2:
+		info->io.inputb = mem_inw;
+		info->io.outputb = mem_outw;
+		break;
+	case 4:
+		info->io.inputb = mem_inl;
+		info->io.outputb = mem_outl;
+		break;
+#ifdef readq
+	case 8:
+		info->io.inputb = mem_inq;
+		info->io.outputb = mem_outq;
+		break;
+#endif
+	default:
+		printk("ipmi_si: Invalid register size: %d\n",
+		       info->io.regsize);
+		return -EINVAL;
+	}
+
+	/* Calculate the total amount of memory to claim.  This is an
+	 * unusual looking calculation, but it avoids claiming any
+	 * more memory than it has to.  It will claim everything
+	 * between the first address to the end of the last full
+	 * register. */
+	mapsize = ((info->io_size * info->io.regspacing)
+		   - (info->io.regspacing - info->io.regsize));
+
+	if (request_mem_region(*addr, mapsize, DEVICE_NAME) == NULL)
+		return -EIO;
+
+	info->io.addr = ioremap(*addr, mapsize);
+	if (info->io.addr == NULL) {
+		release_mem_region(*addr, mapsize);
+		return -EIO;
+	}
+	return 0;
+}
+
 static int try_init_mem(int intf_num, struct smi_info **new_info)
 {
 	struct smi_info *info;
@@ -1104,11 +1299,15 @@
 	memset(info, 0, sizeof(*info));
 
 	info->io_setup = mem_setup;
-	info->io_cleanup = mem_cleanup;
-	info->io.inputb = mem_inb;
-	info->io.outputb = mem_outb;
 	info->io.info = (void *) addrs[intf_num];
 	info->io.addr = NULL;
+	info->io.regspacing = regspacings[intf_num];
+	if (!info->io.regspacing)
+		info->io.regspacing = DEFAULT_REGSPACING;
+	info->io.regsize = regsizes[intf_num];
+	if (!info->io.regsize)
+		info->io.regsize = DEFAULT_REGSPACING;
+	info->io.regshift = regshifts[intf_num];
 	info->irq = 0;
 	info->irq_setup = NULL;
 	*new_info = info;
@@ -1132,7 +1331,7 @@
 static int acpi_failure = 0;
 
 /* For GPE-type interrupts. */
-void ipmi_acpi_gpe(void *context)
+u32 ipmi_acpi_gpe(void *context)
 {
 	struct smi_info *smi_info = context;
 	unsigned long   flags;
@@ -1156,6 +1355,8 @@
 	smi_event_handler(smi_info, 0);
  out:
 	spin_unlock_irqrestore(&(smi_info->si_lock), flags);
+
+	return ACPI_INTERRUPT_HANDLED;
 }
 
 static int acpi_gpe_irq_setup(struct smi_info *info)
@@ -1182,7 +1383,6 @@
 		printk("  Using ACPI GPE %d\n", info->irq);
 		return 0;
 	}
-
 }
 
 static void acpi_gpe_irq_cleanup(struct smi_info *info)
@@ -1310,21 +1510,22 @@
 		info->irq_setup = NULL;
 	}
 
+	regspacings[intf_num] = spmi->addr.register_bit_width / 8;
+	info->io.regspacing = spmi->addr.register_bit_width / 8;
+	regsizes[intf_num] = regspacings[intf_num];
+	info->io.regsize = regsizes[intf_num];
+	regshifts[intf_num] = spmi->addr.register_bit_offset;
+	info->io.regshift = regshifts[intf_num];
+
 	if (spmi->addr.address_space_id == ACPI_ADR_SPACE_SYSTEM_MEMORY) {
 		io_type = "memory";
 		info->io_setup = mem_setup;
-		info->io_cleanup = mem_cleanup;
 		addrs[intf_num] = spmi->addr.address;
-		info->io.inputb = mem_inb;
-		info->io.outputb = mem_outb;
 		info->io.info = &(addrs[intf_num]);
 	} else if (spmi->addr.address_space_id == ACPI_ADR_SPACE_SYSTEM_IO) {
 		io_type = "I/O";
 		info->io_setup = port_setup;
-		info->io_cleanup = port_cleanup;
 		ports[intf_num] = spmi->addr.address;
-		info->io.inputb = port_inb;
-		info->io.outputb = port_outb;
 		info->io.info = &(ports[intf_num]);
 	} else {
 		kfree(info);
@@ -1348,6 +1549,7 @@
 	u8   		addr_space;
 	unsigned long	base_addr;
 	u8   		irq;
+	u8              offset;
 }dmi_ipmi_data_t;
 
 typedef struct dmi_header
@@ -1361,6 +1563,7 @@
 {
 	u8		*data = (u8 *)dm;
 	unsigned long  	base_addr;
+	u8		reg_spacing;
 
 	ipmi_data->type = data[0x04];
 
@@ -1375,7 +1578,27 @@
 		ipmi_data->addr_space = IPMI_MEM_ADDR_SPACE;
 	}
 
-	ipmi_data->base_addr = base_addr;
+	/* The top two bits of byte 0x10 hold the register spacing. */
+	reg_spacing = (data[0x10] & 0xC0) >> 6;
+	switch(reg_spacing){
+	case 0x00: /* Byte boundaries */
+		ipmi_data->offset = 1;
+		break;
+	case 0x01: /* 32-bit boundaries */
+		ipmi_data->offset = 4;
+		break;
+	case 0x02: /* 16-bit boundaries */
+		ipmi_data->offset = 2;
+	default:
+		printk("ipmi_si: Unknown SMBIOS IPMI Base Addr"
+		       " Modifier: 0x%x\n", reg_spacing);
+		return -EIO;
+	}
+
+	/* If bit 4 of byte 0x10 is set, then the lsb for the address
+	   is odd. */
+	ipmi_data->base_addr = base_addr | ((data[0x10] & 0x10) >> 4);
+
 	ipmi_data->irq = data[0x11];
 
 	if (is_new_interface(-1, ipmi_data->addr_space,ipmi_data->base_addr))
@@ -1500,18 +1723,12 @@
 	if (ipmi_data.addr_space == 1) {
 		io_type = "memory";
 		info->io_setup = mem_setup;
-		info->io_cleanup = mem_cleanup;
 		addrs[intf_num] = ipmi_data.base_addr;
-		info->io.inputb = mem_inb;
-		info->io.outputb = mem_outb;
 		info->io.info = &(addrs[intf_num]);
 	} else if (ipmi_data.addr_space == 2) {
 		io_type = "I/O";
 		info->io_setup = port_setup;
-		info->io_cleanup = port_cleanup;
 		ports[intf_num] = ipmi_data.base_addr;
-		info->io.inputb = port_inb;
-		info->io.outputb = port_outb;
 		info->io.info = &(ports[intf_num]);
 	} else {
 		kfree(info);
@@ -1519,6 +1736,13 @@
 		return -EIO;
 	}
 
+	regspacings[intf_num] = ipmi_data.offset;
+	info->io.regspacing = regspacings[intf_num];
+	if (!info->io.regspacing)
+		info->io.regspacing = DEFAULT_REGSPACING;
+	info->io.regsize = DEFAULT_REGSPACING;
+	info->io.regshift = regshifts[intf_num];
+
 	irqs[intf_num] = ipmi_data.irq;
 
 	*new_info = info;
@@ -1596,11 +1820,13 @@
 	memset(info, 0, sizeof(*info));
 
 	info->io_setup = port_setup;
-	info->io_cleanup = port_cleanup;
 	ports[intf_num] = base_addr;
-	info->io.inputb = port_inb;
-	info->io.outputb = port_outb;
 	info->io.info = &(ports[intf_num]);
+	info->io.regspacing = regspacings[intf_num];
+	if (!info->io.regspacing)
+		info->io.regspacing = DEFAULT_REGSPACING;
+	info->io.regsize = DEFAULT_REGSPACING;
+	info->io.regshift = regshifts[intf_num];
 
 	*new_info = info;
 
@@ -1860,6 +2086,13 @@
 	new_smi->timer_stopped = 0;
 	new_smi->stop_operation = 0;
 
+	/* Start clearing the flags before we enable interrupts or the
+	   timer to avoid racing with the timer. */
+	start_clear_flags(new_smi);
+	/* IRQ is defined to be set when non-zero. */
+	if (new_smi->irq)
+		new_smi->si_state = SI_CLEARING_FLAGS_THEN_SET_IRQ;
+
 	/* The ipmi_register_smi() code does some operations to
 	   determine the channel information, so we must be ready to
 	   handle operations before it is called.  This means we have
@@ -1903,12 +2136,6 @@
 		goto out_err_stop_timer;
 	}
 
-	start_clear_flags(new_smi);
-
-	/* IRQ is defined to be set when non-zero. */
-	if (new_smi->irq)
-		new_smi->si_state = SI_CLEARING_FLAGS_THEN_SET_IRQ;
-
 	*smi = new_smi;
 
 	printk(" IPMI %s interface initialized\n", si_type[intf_num]);
@@ -2049,6 +2276,13 @@
 	   conditions removing the timer here. */
 	while (!to_clean->timer_stopped) {
 		set_current_state(TASK_UNINTERRUPTIBLE);
+		schedule_timeout(1);
+	}
+
+	/* Interrupts and timeouts are stopped, now make sure the
+	   interface is in a clean state. */
+	while ((to_clean->curr_msg) || (to_clean->si_state != SI_NORMAL)) {
+		poll(to_clean);
 		schedule_timeout(1);
 	}
 
diff -Nru a/drivers/char/ipmi/ipmi_si_sm.h b/drivers/char/ipmi/ipmi_si_sm.h
--- a/drivers/char/ipmi/ipmi_si_sm.h	2004-10-18 14:56:17 -07:00
+++ b/drivers/char/ipmi/ipmi_si_sm.h	2004-10-18 14:56:17 -07:00
@@ -52,6 +52,9 @@
            state machine shouldn't touch these. */
 	void *info;
 	void *addr;
+	int  regspacing;
+	int  regsize;
+	int  regshift;
 };
 
 /* Results of SMI events. */
diff -Nru a/drivers/char/ipmi/ipmi_smic_sm.c b/drivers/char/ipmi/ipmi_smic_sm.c
--- a/drivers/char/ipmi/ipmi_smic_sm.c	2004-10-18 14:56:29 -07:00
+++ b/drivers/char/ipmi/ipmi_smic_sm.c	2004-10-18 14:56:29 -07:00
@@ -46,7 +46,7 @@
 #include <linux/ipmi_msgdefs.h>		/* for completion codes */
 #include "ipmi_si_sm.h"
 
-#define IPMI_SMIC_VERSION "v32"
+#define IPMI_SMIC_VERSION "v33"
 
 /* smic_debug is a bit-field
  *	SMIC_DEBUG_ENABLE -	turned on for now
diff -Nru a/drivers/char/ipmi/ipmi_watchdog.c b/drivers/char/ipmi/ipmi_watchdog.c
--- a/drivers/char/ipmi/ipmi_watchdog.c	2004-10-18 14:57:04 -07:00
+++ b/drivers/char/ipmi/ipmi_watchdog.c	2004-10-18 14:57:04 -07:00
@@ -51,7 +51,9 @@
 #include <asm/apic.h>
 #endif
 
-#define IPMI_WATCHDOG_VERSION "v32"
+#define	PFX "IPMI Watchdog: "
+
+#define IPMI_WATCHDOG_VERSION "v33"
 
 /*
  * The IPMI command/response information for the watchdog timer.
@@ -160,6 +162,7 @@
 static DECLARE_WAIT_QUEUE_HEAD(read_q);
 static struct fasync_struct *fasync_q = NULL;
 static char pretimeout_since_last_heartbeat = 0;
+static char expect_close;
 
 /* If true, the driver will start running as soon as it is configured
    and ready. */
@@ -191,7 +194,7 @@
 static int ipmi_ignore_heartbeat = 0;
 
 /* Is someone using the watchdog?  Only one user is allowed. */
-static int ipmi_wdog_open = 0;
+static unsigned long ipmi_wdog_open = 0;
 
 /* If set to 1, the heartbeat command will set the state to reset and
    start the timer.  The timer doesn't normally run when the driver is
@@ -287,7 +290,7 @@
 				      recv_msg,
 				      1);
 	if (rv) {
-		printk(KERN_WARNING "IPMI Watchdog, set timeout error: %d\n",
+		printk(KERN_WARNING PFX "set timeout error: %d\n",
 		       rv);
 	}
 
@@ -464,7 +467,7 @@
 				      1);
 	if (rv) {
 		up(&heartbeat_lock);
-		printk(KERN_WARNING "IPMI Watchdog, heartbeat failure: %d\n",
+		printk(KERN_WARNING PFX "heartbeat failure: %d\n",
 		       rv);
 		return rv;
 	}
@@ -599,6 +602,21 @@
 	int rv;
 
 	if (len) {
+	    	if (!nowayout) {
+		    	size_t i;
+
+			/* In case it was set long ago */
+			expect_close = 0;
+
+    			for (i = 0; i != len; i++) {
+				char c;
+
+				if (get_user(c, buf + i))
+					return -EFAULT;
+				if (c == 'V')
+					expect_close = 42;
+			}
+		}
 		rv = ipmi_heartbeat();
 		if (rv)
 			return rv;
@@ -662,11 +680,9 @@
         switch (iminor(ino))
         {
                 case WATCHDOG_MINOR:
-                    if (ipmi_wdog_open)
+		    if(test_and_set_bit(0, &ipmi_wdog_open))
                         return -EBUSY;
 
-                    ipmi_wdog_open = 1;
-
 		    /* Don't start the timer now, let it start on the
 		       first heartbeat. */
 		    ipmi_start_timer_on_heartbeat = 1;
@@ -704,14 +720,18 @@
 {
 	if (iminor(ino)==WATCHDOG_MINOR)
 	{
-		if (!nowayout) {
+		if (expect_close == 42) {
 			ipmi_watchdog_state = WDOG_TIMEOUT_NONE;
 			ipmi_set_timeout(IPMI_SET_TIMEOUT_NO_HB);
+			clear_bit(0, &ipmi_wdog_open);
+		} else {
+			printk(KERN_CRIT PFX "Unexpected close, not stopping watchdog!\n");
+			ipmi_heartbeat();
 		}
-	        ipmi_wdog_open = 0;
 	}
 
 	ipmi_fasync (-1, filep, 0);
+	expect_close = 0;
 
 	return 0;
 }
@@ -739,7 +759,7 @@
 				  void                 *handler_data)
 {
 	if (msg->msg.data[0] != 0) {
-		printk(KERN_ERR "IPMI Watchdog response: Error %x on cmd %x\n",
+		printk(KERN_ERR PFX "response: Error %x on cmd %x\n",
 		       msg->msg.data[0],
 		       msg->msg.cmd);
 	}
@@ -784,7 +804,7 @@
 
 	rv = ipmi_create_user(ipmi_intf, &ipmi_hndlrs, NULL, &watchdog_user);
 	if (rv < 0) {
-		printk("IPMI watchdog: Unable to register with ipmi\n");
+		printk(KERN_CRIT PFX "Unable to register with ipmi\n");
 		goto out;
 	}
 
@@ -796,7 +816,7 @@
 	if (rv < 0) {
 		ipmi_destroy_user(watchdog_user);
 		watchdog_user = NULL;
-		printk("IPMI watchdog: Unable to register misc device\n");
+		printk(KERN_CRIT PFX "Unable to register misc device\n");
 	}
 
  out:
@@ -807,7 +827,7 @@
 		start_now = 0; /* Disable this function after first startup. */
 		ipmi_watchdog_state = action_val;
 		ipmi_set_timeout(IPMI_SET_TIMEOUT_FORCE_HB);
-		printk("Starting IPMI Watchdog now!\n");
+		printk(KERN_INFO PFX "Starting now!\n");
 	}
 }
 
@@ -818,7 +838,7 @@
 	/* If no one else handled the NMI, we assume it was the IPMI
            watchdog. */
 	if ((!handled) && (preop_val == WDOG_PREOP_PANIC))
-		panic("IPMI watchdog pre-timeout");
+		panic(PFX "pre-timeout");
 
 	/* On some machines, the heartbeat will give
 	   an error and not work unless we re-enable
@@ -924,7 +944,7 @@
 {
 	int rv;
 
-	printk(KERN_INFO "IPMI watchdog driver version "
+	printk(KERN_INFO PFX "driver version "
 	       IPMI_WATCHDOG_VERSION "\n");
 
 	if (strcmp(action, "reset") == 0) {
@@ -937,7 +957,7 @@
 		action_val = WDOG_TIMEOUT_POWER_DOWN;
 	} else {
 		action_val = WDOG_TIMEOUT_RESET;
-		printk("ipmi_watchdog: Unknown action '%s', defaulting to"
+		printk(KERN_INFO PFX "Unknown action '%s', defaulting to"
 		       " reset\n", action);
 	}
 
@@ -953,7 +973,7 @@
 		preaction_val = WDOG_PRETIMEOUT_MSG_INT;
 	} else {
 		preaction_val = WDOG_PRETIMEOUT_NONE;
-		printk("ipmi_watchdog: Unknown preaction '%s', defaulting to"
+		printk(KERN_INFO PFX "Unknown preaction '%s', defaulting to"
 		       " none\n", preaction);
 	}
 
@@ -965,23 +985,21 @@
 		preop_val = WDOG_PREOP_GIVE_DATA;
 	} else {
 		preop_val = WDOG_PREOP_NONE;
-		printk("ipmi_watchdog: Unknown preop '%s', defaulting to"
+		printk(KERN_INFO PFX "Unknown preop '%s', defaulting to"
 		       " none\n", preop);
 	}
 
 #ifdef HAVE_NMI_HANDLER
 	if (preaction_val == WDOG_PRETIMEOUT_NMI) {
 		if (preop_val == WDOG_PREOP_GIVE_DATA) {
-			printk(KERN_WARNING
-			       "ipmi_watchdog: Pretimeout op is to give data"
+			printk(KERN_WARNING PFX "Pretimeout op is to give data"
 			       " but NMI pretimeout is enabled, setting"
 			       " pretimeout op to none\n");
 			preop_val = WDOG_PREOP_NONE;
 		}
 #ifdef CONFIG_X86_LOCAL_APIC
 		if (nmi_watchdog == NMI_IO_APIC) {
-			printk(KERN_WARNING
-			       "ipmi_watchdog: nmi_watchdog is set to IO APIC"
+			printk(KERN_WARNING PFX "nmi_watchdog is set to IO APIC"
 			       " mode (value is %d), that is incompatible"
 			       " with using NMI in the IPMI watchdog."
 			       " Disabling IPMI nmi pretimeout.\n",
@@ -991,8 +1009,7 @@
 #endif
 		rv = request_nmi(&ipmi_nmi_handler);
 		if (rv) {
-			printk(KERN_WARNING
-			       "ipmi_watchdog: Can't register nmi handler\n");
+			printk(KERN_WARNING PFX "Can't register nmi handler\n");
 			return rv;
 		}
 #ifdef CONFIG_X86_LOCAL_APIC
@@ -1007,8 +1024,7 @@
 		if (preaction_val == WDOG_PRETIMEOUT_NMI)
 			release_nmi(&ipmi_nmi_handler);
 #endif
-		printk(KERN_WARNING
-		       "ipmi_watchdog: can't register smi watcher\n");
+		printk(KERN_WARNING PFX "can't register smi watcher\n");
 		return rv;
 	}
 
@@ -1053,8 +1069,7 @@
 	/* Disconnect from IPMI. */
 	rv = ipmi_destroy_user(watchdog_user);
 	if (rv) {
-		printk(KERN_WARNING
-		       "IPMI Watchdog, error unlinking from IPMI: %d\n",
+		printk(KERN_WARNING PFX "error unlinking from IPMI: %d\n",
 		       rv);
 	}
 	watchdog_user = NULL;
diff -Nru a/drivers/char/isicom.c b/drivers/char/isicom.c
--- a/drivers/char/isicom.c	2004-10-18 14:55:54 -07:00
+++ b/drivers/char/isicom.c	2004-10-18 14:55:54 -07:00
@@ -48,6 +48,7 @@
 #include <linux/miscdevice.h>
 #include <linux/interrupt.h>
 #include <linux/timer.h>
+#include <linux/delay.h>
 #include <linux/ioport.h>
 
 #include <asm/uaccess.h>
@@ -389,7 +390,7 @@
 		
 		tty = port->tty;
 		save_flags(flags); cli();
-		txcount = MIN(TX_SIZE, port->xmit_cnt);
+		txcount = min_t(short, TX_SIZE, port->xmit_cnt);
 		if ((txcount <= 0) || tty->stopped || tty->hw_stopped) {
 			restore_flags(flags);
 			continue;
@@ -421,7 +422,7 @@
 		residue = NO;
 		wrd = 0;			
 		while (1) {
-			cnt = MIN(txcount, (SERIAL_XMIT_SIZE - port->xmit_tail));
+			cnt = min_t(int, txcount, (SERIAL_XMIT_SIZE - port->xmit_tail));
 			if (residue == YES) {
 				residue = NO;
 				if (cnt > 0) {
@@ -484,10 +485,8 @@
 	
 	if (!tty)
 		return;
-	
-	if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
-	    tty->ldisc.write_wakeup)
-		(tty->ldisc.write_wakeup)(tty);
+
+	tty_wakeup(tty);	
 	wake_up_interruptible(&tty->write_wait);
 } 		
  		
@@ -650,7 +649,7 @@
 		}	 
 	}
 	else {				/* Data   Packet */
-		count = MIN(byte_count, (TTY_FLIPBUF_SIZE - tty->flip.count));
+		count = min_t(unsigned short, byte_count, (TTY_FLIPBUF_SIZE - tty->flip.count));
 #ifdef ISICOM_DEBUG
 		printk(KERN_DEBUG "ISICOM: Intr: Can rx %d of %d bytes.\n", 
 					count, byte_count);
@@ -1119,8 +1118,8 @@
 	isicom_shutdown_port(port);
 	if (tty->driver->flush_buffer)
 		tty->driver->flush_buffer(tty);
-	if (tty->ldisc.flush_buffer)
-		tty->ldisc.flush_buffer(tty);
+		
+	tty_ldisc_flush(tty);
 	tty->closing = 0;
 	port->tty = NULL;
 	if (port->blocked_open) {
@@ -1163,8 +1162,8 @@
 	save_flags(flags);
 	while(1) {	
 		cli();
-		cnt = MIN(count, MIN(SERIAL_XMIT_SIZE - port->xmit_cnt - 1,
-			SERIAL_XMIT_SIZE - port->xmit_head));
+		cnt = min_t(int, count, min(SERIAL_XMIT_SIZE - port->xmit_cnt - 1,
+					    SERIAL_XMIT_SIZE - port->xmit_head));
 		if (cnt <= 0) 
 			break;
 		
@@ -1180,8 +1179,8 @@
 				return -EFAULT;
 			}
 			cli();
-			cnt = MIN(cnt, MIN(SERIAL_XMIT_SIZE - port->xmit_cnt - 1,
-			SERIAL_XMIT_SIZE - port->xmit_head));
+			cnt = min_t(int, cnt, min(SERIAL_XMIT_SIZE - port->xmit_cnt - 1,
+						  SERIAL_XMIT_SIZE - port->xmit_head));
 			memcpy(port->xmit_buf + port->xmit_head, tmp_buf, cnt);
 		}	
 		else
@@ -1563,9 +1562,7 @@
 	restore_flags(flags);
 	
 	wake_up_interruptible(&tty->write_wait);
-	if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
-	    tty->ldisc.write_wakeup)
-		(tty->ldisc.write_wakeup)(tty);
+	tty_wakeup(tty);
 }
 
 
@@ -1906,8 +1903,7 @@
 void cleanup_module(void)
 {
 	re_schedule = 0;
-	set_current_state(TASK_INTERRUPTIBLE);
-	schedule_timeout(HZ);
+	msleep(1000);
 
 #ifdef ISICOM_DEBUG	
 	printk("ISICOM: isicom_tx tx_count = %ld.\n", tx_count);
diff -Nru a/drivers/char/istallion.c b/drivers/char/istallion.c
--- a/drivers/char/istallion.c	2004-10-18 14:56:33 -07:00
+++ b/drivers/char/istallion.c	2004-10-18 14:56:33 -07:00
@@ -749,17 +749,13 @@
 
 static stliport_t *stli_getport(int brdnr, int panelnr, int portnr);
 
-static inline int	stli_initbrds(void);
-static inline int	stli_initecp(stlibrd_t *brdp);
-static inline int	stli_initonb(stlibrd_t *brdp);
-static inline int	stli_findeisabrds(void);
-static inline int	stli_eisamemprobe(stlibrd_t *brdp);
-static inline int	stli_initports(stlibrd_t *brdp);
-static inline int	stli_getbrdnr(void);
+static int	stli_initecp(stlibrd_t *brdp);
+static int	stli_initonb(stlibrd_t *brdp);
+static int	stli_eisamemprobe(stlibrd_t *brdp);
+static int	stli_initports(stlibrd_t *brdp);
 
 #ifdef	CONFIG_PCI
-static inline int	stli_findpcibrds(void);
-static inline int	stli_initpcibrd(int brdtype, struct pci_dev *devp);
+static int	stli_initpcibrd(int brdtype, struct pci_dev *devp);
 #endif
 
 /*****************************************************************************/
@@ -2751,7 +2747,7 @@
  *	more chars to unload.
  */
 
-static inline void stli_read(stlibrd_t *brdp, stliport_t *portp)
+static void stli_read(stlibrd_t *brdp, stliport_t *portp)
 {
 	volatile cdkasyrq_t	*rp;
 	volatile char		*shbuf;
@@ -2819,7 +2815,7 @@
  *	difficult to deal with them here.
  */
 
-static inline void stli_dodelaycmd(stliport_t *portp, volatile cdkctrl_t *cp)
+static void stli_dodelaycmd(stliport_t *portp, volatile cdkctrl_t *cp)
 {
 	int	cmd;
 
@@ -2867,7 +2863,7 @@
  *	then port is still busy, otherwise no longer busy.
  */
 
-static inline int stli_hostcmd(stlibrd_t *brdp, stliport_t *portp)
+static int stli_hostcmd(stlibrd_t *brdp, stliport_t *portp)
 {
 	volatile cdkasy_t	*ap;
 	volatile cdkctrl_t	*cp;
@@ -3026,7 +3022,7 @@
  *	at the cdk header structure.
  */
 
-static inline void stli_brdpoll(stlibrd_t *brdp, volatile cdkhdr_t *hdrp)
+static void stli_brdpoll(stlibrd_t *brdp, volatile cdkhdr_t *hdrp)
 {
 	stliport_t	*portp;
 	unsigned char	hostbits[(STL_MAXCHANS / 8) + 1];
@@ -3299,7 +3295,7 @@
  *	we need to do here is set up the appropriate per port data structures.
  */
 
-static inline int stli_initports(stlibrd_t *brdp)
+static int stli_initports(stlibrd_t *brdp)
 {
 	stliport_t	*portp;
 	int		i, panelnr, panelport;
@@ -3911,7 +3907,7 @@
  *	board types.
  */
 
-static inline int stli_initecp(stlibrd_t *brdp)
+static int stli_initecp(stlibrd_t *brdp)
 {
 	cdkecpsig_t	sig;
 	cdkecpsig_t	*sigsp;
@@ -4072,7 +4068,7 @@
  *	This handles only these board types.
  */
 
-static inline int stli_initonb(stlibrd_t *brdp)
+static int stli_initonb(stlibrd_t *brdp)
 {
 	cdkonbsig_t	sig;
 	cdkonbsig_t	*sigsp;
@@ -4414,7 +4410,7 @@
  *	might be. This is a bit if hack, but it is the best we can do.
  */
 
-static inline int stli_eisamemprobe(stlibrd_t *brdp)
+static int stli_eisamemprobe(stlibrd_t *brdp)
 {
 	cdkecpsig_t	ecpsig, *ecpsigp;
 	cdkonbsig_t	onbsig, *onbsigp;
@@ -4506,7 +4502,7 @@
 	return(0);
 }
 
-static inline int stli_getbrdnr(void)
+static int stli_getbrdnr(void)
 {
 	int i;
 
@@ -4532,7 +4528,7 @@
  *	do is go probing around in the usual places hoping we can find it.
  */
 
-static inline int stli_findeisabrds(void)
+static int stli_findeisabrds(void)
 {
 	stlibrd_t	*brdp;
 	unsigned int	iobase, eid;
@@ -4616,7 +4612,7 @@
  *	configuration space.
  */
 
-static inline int stli_initpcibrd(int brdtype, struct pci_dev *devp)
+static int stli_initpcibrd(int brdtype, struct pci_dev *devp)
 {
 	stlibrd_t	*brdp;
 
@@ -4662,7 +4658,7 @@
  *	one as it is found.
  */
 
-static inline int stli_findpcibrds(void)
+static int stli_findpcibrds(void)
 {
 	struct pci_dev	*dev = NULL;
 	int		rc;
@@ -4711,7 +4707,7 @@
  *	can find.
  */
 
-static inline int stli_initbrds(void)
+static int stli_initbrds(void)
 {
 	stlibrd_t	*brdp, *nxtbrdp;
 	stlconf_t	*confp;
diff -Nru a/drivers/char/keyboard.c b/drivers/char/keyboard.c
--- a/drivers/char/keyboard.c	2004-10-18 14:57:19 -07:00
+++ b/drivers/char/keyboard.c	2004-10-18 14:57:19 -07:00
@@ -123,7 +123,7 @@
  */
 
 static struct input_handler kbd_handler;
-static unsigned long key_down[256/BITS_PER_LONG];	/* keyboard key bitmap */
+static unsigned long key_down[NBITS(KEY_MAX)];		/* keyboard key bitmap */
 static unsigned char shift_down[NR_SHIFT];		/* shift state counters.. */
 static int dead_key_next;
 static int npadch = -1;					/* -1 or number assembled on pad */
@@ -142,7 +142,7 @@
 /* Simple translation table for the SysRq keys */
 
 #ifdef CONFIG_MAGIC_SYSRQ
-unsigned char kbd_sysrq_xlate[128] =
+unsigned char kbd_sysrq_xlate[KEY_MAX] =
         "\000\0331234567890-=\177\t"                    /* 0x00 - 0x0f */
         "qwertyuiop[]\r\000as"                          /* 0x10 - 0x1f */
         "dfghjkl;'`\000\\zxcv"                          /* 0x20 - 0x2f */
@@ -941,6 +941,9 @@
 
 #if defined(CONFIG_X86) || defined(CONFIG_IA64) || defined(CONFIG_ALPHA) || defined(CONFIG_MIPS) || defined(CONFIG_PPC) || defined(CONFIG_SPARC32) || defined(CONFIG_SPARC64) || defined(CONFIG_PARISC) || defined(CONFIG_SUPERH)
 
+#define HW_RAW(dev) (test_bit(EV_MSC, dev->evbit) && test_bit(MSC_RAW, dev->mscbit) &&\
+			((dev)->id.bustype == BUS_I8042) && ((dev)->id.vendor == 0x0001) && ((dev)->id.product == 0x0001))
+
 static unsigned short x86_keycodes[256] =
 	{ 0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14, 15,
 	 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
@@ -1007,6 +1010,8 @@
 
 #else
 
+#define HW_RAW(dev)	0
+
 #warning "Cannot generate rawmode keyboard for your architecture yet."
 
 static int emulate_raw(struct vc_data *vc, unsigned int keycode, unsigned char up_flag)
@@ -1019,7 +1024,15 @@
 }
 #endif
 
-void kbd_keycode(unsigned int keycode, int down, struct pt_regs *regs)
+void kbd_rawcode(unsigned char data)
+{
+	struct vc_data *vc = vc_cons[fg_console].d;
+	kbd = kbd_table + fg_console;
+	if (kbd->kbdmode == VC_RAW)
+		put_queue(vc, data);
+}
+
+void kbd_keycode(unsigned int keycode, int down, int hw_raw, struct pt_regs *regs)
 {
 	struct vc_data *vc = vc_cons[fg_console].d;
 	unsigned short keysym, *key_map;
@@ -1053,7 +1066,7 @@
 		return;
 #endif /* CONFIG_MAC_EMUMOUSEBTN */
 
-	if ((raw_mode = (kbd->kbdmode == VC_RAW)))
+	if ((raw_mode = (kbd->kbdmode == VC_RAW)) && !hw_raw)
 		if (emulate_raw(vc, keycode, !down << 7))
 			if (keycode < BTN_MISC)
 				printk(KERN_WARNING "keyboard.c: can't emulate rawmode for keycode %d\n", keycode);
@@ -1119,6 +1132,9 @@
 		return;
 	}
 
+	if (keycode > NR_KEYS)
+		return;
+
 	keysym = key_map[keycode];
 	type = KTYP(keysym);
 
@@ -1148,11 +1164,12 @@
 }
 
 static void kbd_event(struct input_handle *handle, unsigned int event_type, 
-		      unsigned int keycode, int down)
+		      unsigned int event_code, int value)
 {
-	if (event_type != EV_KEY)
-		return;
-	kbd_keycode(keycode, down, handle->dev->regs);
+	if (event_type == EV_MSC && event_code == MSC_RAW && HW_RAW(handle->dev))
+		kbd_rawcode(value);
+	if (event_type == EV_KEY)
+		kbd_keycode(event_code, value, HW_RAW(handle->dev), handle->dev->regs);
 	tasklet_schedule(&keyboard_tasklet);
 	do_poke_blanked_console = 1;
 	schedule_console_callback();
diff -Nru a/drivers/char/mem.c b/drivers/char/mem.c
--- a/drivers/char/mem.c	2004-10-18 14:56:32 -07:00
+++ b/drivers/char/mem.c	2004-10-18 14:56:32 -07:00
@@ -31,9 +31,6 @@
 # include <linux/efi.h>
 #endif
 
-#ifdef CONFIG_FB
-extern void fbmem_init(void);
-#endif
 #if defined(CONFIG_S390_TAPE) && defined(CONFIG_S390_TAPE_CHAR)
 extern void tapechar_init(void);
 #endif
@@ -86,7 +83,7 @@
 	 * above the IO hole... Ah, and of course, XFree86 doesn't pass
 	 * O_SYNC when mapping us to tap IO space. Surprised ?
 	 */
-	return !page_is_ram(addr);
+	return !page_is_ram(addr >> PAGE_SHIFT);
 #else
 	/*
 	 * Accessing memory above the top the kernel knows about or through a file pointer
@@ -416,7 +413,7 @@
 
 		if (vma->vm_start > addr || (vma->vm_flags & VM_WRITE) == 0)
 			goto out_up;
-		if (vma->vm_flags & VM_SHARED)
+		if (vma->vm_flags & (VM_SHARED | VM_HUGETLB))
 			break;
 		count = vma->vm_end - addr;
 		if (count > size)
@@ -730,9 +727,6 @@
 				S_IFCHR | devlist[i].mode, devlist[i].name);
 	}
 	
-#if defined (CONFIG_FB)
-	fbmem_init();
-#endif
 	return 0;
 }
 
diff -Nru a/drivers/char/mmtimer.c b/drivers/char/mmtimer.c
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/drivers/char/mmtimer.c	2004-10-18 14:57:23 -07:00
@@ -0,0 +1,216 @@
+/*
+ * Intel Multimedia Timer device implementation for SGI SN platforms.
+ *
+ * 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-2004 Silicon Graphics, Inc.  All rights reserved.
+ *
+ * This driver exports an API that should be supportable by any HPET or IA-PC
+ * multimedia timer.  The code below is currently specific to the SGI Altix
+ * SHub RTC, however.
+ *
+ * 11/01/01 - jbarnes - initial revision
+ * 9/10/04 - Christoph Lameter - remove interrupt support for kernel inclusion
+ */
+
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/ioctl.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/errno.h>
+#include <linux/mm.h>
+#include <linux/devfs_fs_kernel.h>
+#include <linux/mmtimer.h>
+#include <linux/miscdevice.h>
+#include <asm/uaccess.h>
+#include <asm/sn/addrs.h>
+#include <asm/sn/clksupport.h>
+
+MODULE_AUTHOR("Jesse Barnes <jbarnes@sgi.com>");
+MODULE_DESCRIPTION("Multimedia timer support");
+MODULE_LICENSE("GPL");
+
+/* name of the device, usually in /dev */
+#define MMTIMER_NAME "mmtimer"
+#define MMTIMER_DESC "IA-PC Multimedia Timer"
+#define MMTIMER_VERSION "1.0"
+
+#define RTC_BITS 55 /* 55 bits for this implementation */
+
+static int mmtimer_ioctl(struct inode *inode, struct file *file,
+			 unsigned int cmd, unsigned long arg);
+static int mmtimer_mmap(struct file *file, struct vm_area_struct *vma);
+
+/*
+ * Period in femtoseconds (10^-15 s)
+ */
+static unsigned long mmtimer_femtoperiod = 0;
+
+static struct file_operations mmtimer_fops = {
+	.owner =	THIS_MODULE,
+	.mmap =		mmtimer_mmap,
+	.ioctl =	mmtimer_ioctl,
+};
+
+/**
+ * mmtimer_ioctl - ioctl interface for /dev/mmtimer
+ * @inode: inode of the device
+ * @file: file structure for the device
+ * @cmd: command to execute
+ * @arg: optional argument to command
+ *
+ * Executes the command specified by @cmd.  Returns 0 for success, < 0 for
+ * failure.
+ *
+ * Valid commands:
+ *
+ * %MMTIMER_GETOFFSET - Should return the offset (relative to the start
+ * of the page where the registers are mapped) for the counter in question.
+ *
+ * %MMTIMER_GETRES - Returns the resolution of the clock in femto (10^-15)
+ * seconds
+ *
+ * %MMTIMER_GETFREQ - Copies the frequency of the clock in Hz to the address
+ * specified by @arg
+ *
+ * %MMTIMER_GETBITS - Returns the number of bits in the clock's counter
+ *
+ * %MMTIMER_MMAPAVAIL - Returns 1 if the registers can be mmap'd into userspace
+ *
+ * %MMTIMER_GETCOUNTER - Gets the current value in the counter and places it
+ * in the address specified by @arg.
+ */
+static int mmtimer_ioctl(struct inode *inode, struct file *file,
+			 unsigned int cmd, unsigned long arg)
+{
+	int ret = 0;
+
+	switch (cmd) {
+	case MMTIMER_GETOFFSET:	/* offset of the counter */
+		/*
+		 * SN RTC registers are on their own 64k page
+		 */
+		if(PAGE_SIZE <= (1 << 16))
+			ret = (((long)RTC_COUNTER_ADDR) & (PAGE_SIZE-1)) / 8;
+		else
+			ret = -ENOSYS;
+		break;
+
+	case MMTIMER_GETRES: /* resolution of the clock in 10^-15 s */
+		if(copy_to_user((unsigned long *)arg, &mmtimer_femtoperiod,
+				sizeof(unsigned long)))
+			return -EFAULT;
+		break;
+
+	case MMTIMER_GETFREQ: /* frequency in Hz */
+		if(copy_to_user((unsigned long *)arg,
+				&sn_rtc_cycles_per_second,
+				sizeof(unsigned long)))
+			return -EFAULT;
+		ret = 0;
+		break;
+
+	case MMTIMER_GETBITS: /* number of bits in the clock */
+		ret = RTC_BITS;
+		break;
+
+	case MMTIMER_MMAPAVAIL: /* can we mmap the clock into userspace? */
+		ret = (PAGE_SIZE <= (1 << 16)) ? 1 : 0;
+		break;
+
+	case MMTIMER_GETCOUNTER:
+		if(copy_to_user((unsigned long *)arg, RTC_COUNTER_ADDR,
+				sizeof(unsigned long)))
+			return -EFAULT;
+		break;
+	default:
+		ret = -ENOSYS;
+		break;
+	}
+
+	return ret;
+}
+
+/**
+ * mmtimer_mmap - maps the clock's registers into userspace
+ * @file: file structure for the device
+ * @vma: VMA to map the registers into
+ *
+ * Calls remap_page_range() to map the clock's registers into
+ * the calling process' address space.
+ */
+static int mmtimer_mmap(struct file *file, struct vm_area_struct *vma)
+{
+	unsigned long mmtimer_addr;
+
+	if (vma->vm_end - vma->vm_start != PAGE_SIZE)
+		return -EINVAL;
+
+	if (vma->vm_flags & VM_WRITE)
+		return -EPERM;
+
+	if (PAGE_SIZE > (1 << 16))
+		return -ENOSYS;
+
+	vma->vm_flags |= (VM_IO | VM_SHM | VM_LOCKED );
+	vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
+
+	mmtimer_addr = __pa(RTC_COUNTER_ADDR);
+	mmtimer_addr &= ~(PAGE_SIZE - 1);
+	mmtimer_addr &= 0xfffffffffffffffUL;
+
+	if (remap_page_range(vma, vma->vm_start, mmtimer_addr, PAGE_SIZE,
+			     vma->vm_page_prot)) {
+		printk(KERN_ERR "remap_page_range failed in mmtimer.c\n");
+		return -EAGAIN;
+	}
+
+	return 0;
+}
+
+static struct miscdevice mmtimer_miscdev = {
+	SGI_MMTIMER,
+	MMTIMER_NAME,
+	&mmtimer_fops
+};
+
+/**
+ * mmtimer_init - device initialization routine
+ *
+ * Does initial setup for the mmtimer device.
+ */
+static int __init mmtimer_init(void)
+{
+	if (!ia64_platform_is("sn2"))
+		return -1;
+
+	/*
+	 * Sanity check the cycles/sec variable
+	 */
+	if (sn_rtc_cycles_per_second < 100000) {
+		printk(KERN_ERR "%s: unable to determine clock frequency\n",
+		       MMTIMER_NAME);
+		return -1;
+	}
+
+	mmtimer_femtoperiod = ((unsigned long)1E15 + sn_rtc_cycles_per_second /
+			       2) / sn_rtc_cycles_per_second;
+
+	strcpy(mmtimer_miscdev.devfs_name, MMTIMER_NAME);
+	if (misc_register(&mmtimer_miscdev)) {
+		printk(KERN_ERR "%s: failed to register device\n",
+		       MMTIMER_NAME);
+		return -1;
+	}
+
+	printk(KERN_INFO "%s: v%s, %ld MHz\n", MMTIMER_DESC, MMTIMER_VERSION,
+	       sn_rtc_cycles_per_second/(unsigned long)1E6);
+
+	return 0;
+}
+
+module_init(mmtimer_init);
+
diff -Nru a/drivers/char/moxa.c b/drivers/char/moxa.c
--- a/drivers/char/moxa.c	2004-10-18 14:57:04 -07:00
+++ b/drivers/char/moxa.c	2004-10-18 14:57:04 -07:00
@@ -618,8 +618,8 @@
 
 	if (tty->driver->flush_buffer)
 		tty->driver->flush_buffer(tty);
-	if (tty->ldisc.flush_buffer)
-		tty->ldisc.flush_buffer(tty);
+	tty_ldisc_flush(tty);
+			
 	tty->closing = 0;
 	ch->event = 0;
 	ch->tty = NULL;
@@ -693,9 +693,7 @@
 	if (ch == NULL)
 		return;
 	MoxaPortFlushData(ch->port, 1);
-	if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
-	    tty->ldisc.write_wakeup)
-		(tty->ldisc.write_wakeup) (tty);
+	tty_wakeup(tty);
 	wake_up_interruptible(&tty->write_wait);
 }
 
@@ -954,9 +952,7 @@
 				if (MoxaPortTxQueue(ch->port) <= WAKEUP_CHARS) {
 					if (!tp->stopped) {
 						ch->statusflags &= ~LOWWAIT;
-						if ((tp->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
-						  tp->ldisc.write_wakeup)
-							(tp->ldisc.write_wakeup) (tp);
+						tty_wakeup(tp);
 						wake_up_interruptible(&tp->write_wait);
 					}
 				}
@@ -1123,9 +1119,7 @@
 	if (ch->tty && (ch->statusflags & EMPTYWAIT)) {
 		if (MoxaPortTxQueue(ch->port) == 0) {
 			ch->statusflags &= ~EMPTYWAIT;
-			if ((ch->tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
-			    ch->tty->ldisc.write_wakeup)
-				(ch->tty->ldisc.write_wakeup) (ch->tty);
+			tty_wakeup(ch->tty);
 			wake_up_interruptible(&ch->tty->write_wait);
 			return;
 		}
diff -Nru a/drivers/char/mxser.c b/drivers/char/mxser.c
--- a/drivers/char/mxser.c	2004-10-18 14:56:48 -07:00
+++ b/drivers/char/mxser.c	2004-10-18 14:56:48 -07:00
@@ -101,10 +101,6 @@
 
 #define IRQ_T(info) ((info->flags & ASYNC_SHARE_IRQ) ? SA_SHIRQ : SA_INTERRUPT)
 
-#ifndef MIN
-#define MIN(a,b)	((a) < (b) ? (a) : (b))
-#endif
-
 /*
  *    Define the Moxa PCI vendor and device IDs.
  */
@@ -349,10 +345,10 @@
 static void mxser_stop(struct tty_struct *);
 static void mxser_start(struct tty_struct *);
 static void mxser_hangup(struct tty_struct *);
-static irqreturn_t mxser_interrupt(int, void *, struct pt_regs *);
 static inline void mxser_receive_chars(struct mxser_struct *, int *);
 static inline void mxser_transmit_chars(struct mxser_struct *);
 static inline void mxser_check_modem_status(struct mxser_struct *, int);
+static irqreturn_t mxser_interrupt(int, void *, struct pt_regs *);
 static int mxser_block_til_ready(struct tty_struct *, struct file *, struct mxser_struct *);
 static int mxser_startup(struct mxser_struct *);
 static void mxser_shutdown(struct mxser_struct *);
@@ -678,9 +674,7 @@
 	tty = info->tty;
 	if (tty) {
 		if (test_and_clear_bit(MXSER_EVENT_TXLOW, &info->event)) {
-			if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
-			    tty->ldisc.write_wakeup)
-				(tty->ldisc.write_wakeup) (tty);
+			tty_wakeup(tty);
 			wake_up_interruptible(&tty->write_wait);
 		}
 		if (test_and_clear_bit(MXSER_EVENT_HANGUP, &info->event)) {
@@ -817,8 +811,8 @@
 	mxser_shutdown(info);
 	if (tty->driver->flush_buffer)
 		tty->driver->flush_buffer(tty);
-	if (tty->ldisc.flush_buffer)
-		tty->ldisc.flush_buffer(tty);
+	tty_ldisc_flush(tty);
+
 	tty->closing = 0;
 	info->event = 0;
 	info->tty = NULL;
@@ -849,7 +843,7 @@
 	if (from_user) {
 		down(&mxvar_tmp_buf_sem);
 		while (1) {
-			c = MIN(count, MIN(SERIAL_XMIT_SIZE - info->xmit_cnt - 1,
+			c = min_t(int, count, min(SERIAL_XMIT_SIZE - info->xmit_cnt - 1,
 					   SERIAL_XMIT_SIZE - info->xmit_head));
 			if (c <= 0)
 				break;
@@ -862,7 +856,7 @@
 			}
 
 			cli();
-			c = MIN(c, MIN(SERIAL_XMIT_SIZE - info->xmit_cnt - 1,
+			c = min_t(int, c, min(SERIAL_XMIT_SIZE - info->xmit_cnt - 1,
 				       SERIAL_XMIT_SIZE - info->xmit_head));
 			memcpy(info->xmit_buf + info->xmit_head, mxvar_tmp_buf, c);
 			info->xmit_head = (info->xmit_head + c) & (SERIAL_XMIT_SIZE - 1);
@@ -877,7 +871,7 @@
 	} else {
 		while (1) {
 			cli();
-			c = MIN(count, MIN(SERIAL_XMIT_SIZE - info->xmit_cnt - 1,
+			c = min_t(int, count, min(SERIAL_XMIT_SIZE - info->xmit_cnt - 1,
 					   SERIAL_XMIT_SIZE - info->xmit_head));
 			if (c <= 0) {
 				restore_flags(flags);
@@ -976,9 +970,7 @@
 	info->xmit_cnt = info->xmit_head = info->xmit_tail = 0;
 	restore_flags(flags);
 	wake_up_interruptible(&tty->write_wait);
-	if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
-	    tty->ldisc.write_wakeup)
-		(tty->ldisc.write_wakeup) (tty);
+	tty_wakeup(tty);
 }
 
 static int mxser_ioctl(struct tty_struct *tty, struct file *file,
@@ -1307,69 +1299,6 @@
 	wake_up_interruptible(&info->open_wait);
 }
 
-/*
- * This is the serial driver's generic interrupt routine
- */
-static irqreturn_t mxser_interrupt(int irq, void *dev_id, struct pt_regs *regs)
-{
-	int status, i;
-	struct mxser_struct *info;
-	struct mxser_struct *port;
-	int max, irqbits, bits, msr;
-	int pass_counter = 0;
-	int handled = 0;
-
-	port = NULL;
-	for (i = 0; i < MXSER_BOARDS; i++) {
-		if (dev_id == &(mxvar_table[i * MXSER_PORTS_PER_BOARD])) {
-			port = dev_id;
-			break;
-		}
-	}
-
-	if (i == MXSER_BOARDS)
-		return IRQ_NONE;
-	if (port == 0)
-		return IRQ_NONE;
-	max = mxser_numports[mxsercfg[i].board_type];
-
-	while (1) {
-		irqbits = inb(port->vector) & port->vectormask;
-		if (irqbits == port->vectormask)
-			break;
-		handled = 1;
-		for (i = 0, bits = 1; i < max; i++, irqbits |= bits, bits <<= 1) {
-			if (irqbits == port->vectormask)
-				break;
-			if (bits & irqbits)
-				continue;
-			info = port + i;
-			if (!info->tty ||
-			  (inb(info->base + UART_IIR) & UART_IIR_NO_INT))
-				continue;
-			status = inb(info->base + UART_LSR) & info->read_status_mask;
-			if (status & UART_LSR_DR)
-				mxser_receive_chars(info, &status);
-			msr = inb(info->base + UART_MSR);
-			if (msr & UART_MSR_ANY_DELTA)
-				mxser_check_modem_status(info, msr);
-			if (status & UART_LSR_THRE) {
-/* 8-2-99 by William
-   if ( info->x_char || (info->xmit_cnt > 0) )
- */
-				mxser_transmit_chars(info);
-			}
-		}
-		if (pass_counter++ > MXSER_ISR_PASS_LIMIT) {
-#if 0
-			printk("MOXA Smartio/Indusrtio family driver interrupt loop break\n");
-#endif
-			break;	/* Prevent infinite loops */
-		}
-	}
-	return IRQ_RETVAL(handled);
-}
-
 static inline void mxser_receive_chars(struct mxser_struct *info,
 					 int *status)
 {
@@ -1488,6 +1417,69 @@
 			}
 		}
 	}
+}
+
+/*
+ * This is the serial driver's generic interrupt routine
+ */
+static irqreturn_t mxser_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+{
+	int status, i;
+	struct mxser_struct *info;
+	struct mxser_struct *port;
+	int max, irqbits, bits, msr;
+	int pass_counter = 0;
+	int handled = 0;
+
+	port = NULL;
+	for (i = 0; i < MXSER_BOARDS; i++) {
+		if (dev_id == &(mxvar_table[i * MXSER_PORTS_PER_BOARD])) {
+			port = dev_id;
+			break;
+		}
+	}
+
+	if (i == MXSER_BOARDS)
+		return IRQ_NONE;
+	if (port == 0)
+		return IRQ_NONE;
+	max = mxser_numports[mxsercfg[i].board_type];
+
+	while (1) {
+		irqbits = inb(port->vector) & port->vectormask;
+		if (irqbits == port->vectormask)
+			break;
+		handled = 1;
+		for (i = 0, bits = 1; i < max; i++, irqbits |= bits, bits <<= 1) {
+			if (irqbits == port->vectormask)
+				break;
+			if (bits & irqbits)
+				continue;
+			info = port + i;
+			if (!info->tty ||
+			  (inb(info->base + UART_IIR) & UART_IIR_NO_INT))
+				continue;
+			status = inb(info->base + UART_LSR) & info->read_status_mask;
+			if (status & UART_LSR_DR)
+				mxser_receive_chars(info, &status);
+			msr = inb(info->base + UART_MSR);
+			if (msr & UART_MSR_ANY_DELTA)
+				mxser_check_modem_status(info, msr);
+			if (status & UART_LSR_THRE) {
+/* 8-2-99 by William
+   if ( info->x_char || (info->xmit_cnt > 0) )
+ */
+				mxser_transmit_chars(info);
+			}
+		}
+		if (pass_counter++ > MXSER_ISR_PASS_LIMIT) {
+#if 0
+			printk("MOXA Smartio/Indusrtio family driver interrupt loop break\n");
+#endif
+			break;	/* Prevent infinite loops */
+		}
+	}
+	return IRQ_RETVAL(handled);
 }
 
 static int mxser_block_til_ready(struct tty_struct *tty, struct file *filp,
diff -Nru a/drivers/char/n_tty.c b/drivers/char/n_tty.c
--- a/drivers/char/n_tty.c	2004-10-18 14:55:54 -07:00
+++ b/drivers/char/n_tty.c	2004-10-18 14:55:54 -07:00
@@ -99,11 +99,18 @@
 	spin_unlock_irqrestore(&tty->read_lock, flags);
 }
 
-/* 
- * Check whether to call the driver.unthrottle function.
- * We test the TTY_THROTTLED bit first so that it always
- * indicates the current state.
+/**
+ *	check_unthrottle	-	allow new receive data
+ *	@tty; tty device
+ *
+ *	Check whether to call the driver.unthrottle function.
+ *	We test the TTY_THROTTLED bit first so that it always
+ *	indicates the current state. The decision about whether
+ *	it is worth allowing more input has been taken by the caller.
+ *	Can sleep, may be called under the atomic_read semaphore but
+ *	this is not guaranteed.
  */
+ 
 static void check_unthrottle(struct tty_struct * tty)
 {
 	if (tty->count &&
@@ -112,10 +119,13 @@
 		tty->driver->unthrottle(tty);
 }
 
-/*
- * Reset the read buffer counters, clear the flags, 
- * and make sure the driver is unthrottled. Called
- * from n_tty_open() and n_tty_flush_buffer().
+/**
+ *	reset_buffer_flags	-	reset buffer state
+ *	@tty: terminal to reset
+ *
+ *	Reset the read buffer counters, clear the flags, 
+ *	and make sure the driver is unthrottled. Called
+ *	from n_tty_open() and n_tty_flush_buffer().
  */
 static void reset_buffer_flags(struct tty_struct *tty)
 {
@@ -129,9 +139,19 @@
 	check_unthrottle(tty);
 }
 
-/*
- * Flush the input buffer
+/**
+ *	n_tty_flush_buffer	-	clean input queue
+ *	@tty:	terminal device
+ *
+ *	Flush the input buffer. Called when the line discipline is
+ *	being closed, when the tty layer wants the buffer flushed (eg
+ *	at hangup) or when the N_TTY line discipline internally has to
+ *	clean the pending queue (for example some signals).
+ *
+ *	FIXME: tty->ctrl_status is not spinlocked and relies on
+ *	lock_kernel() still.
  */
+ 
 void n_tty_flush_buffer(struct tty_struct * tty)
 {
 	/* clear everything and unthrottle the driver */
@@ -146,9 +166,14 @@
 	}
 }
 
-/*
- * Return number of characters buffered to be delivered to user
+/**
+ *	n_tty_chars_in_buffer	-	report available bytes
+ *	@tty: tty device
+ *
+ *	Report the number of characters buffered to be delivered to user
+ *	at this instant in time. 
  */
+ 
 ssize_t n_tty_chars_in_buffer(struct tty_struct *tty)
 {
 	unsigned long flags;
@@ -166,20 +191,47 @@
 	return n;
 }
 
+/**
+ *	is_utf8_continuation	-	utf8 multibyte check
+ *	@c: byte to check
+ *
+ *	Returns true if the utf8 character 'c' is a multibyte continuation
+ *	character. We use this to correctly compute the on screen size
+ *	of the character when printing
+ */
+ 
 static inline int is_utf8_continuation(unsigned char c)
 {
 	return (c & 0xc0) == 0x80;
 }
 
+/**
+ *	is_continuation		-	multibyte check
+ *	@c: byte to check
+ *
+ *	Returns true if the utf8 character 'c' is a multibyte continuation
+ *	character and the terminal is in unicode mode.
+ */
+ 
 static inline int is_continuation(unsigned char c, struct tty_struct *tty)
 {
 	return I_IUTF8(tty) && is_utf8_continuation(c);
 }
 
-/*
- * Perform OPOST processing.  Returns -1 when the output device is
- * full and the character must be retried.
+/**
+ *	opost			-	output post processor
+ *	@c: character (or partial unicode symbol)
+ *	@tty: terminal device
+ *
+ *	Perform OPOST processing.  Returns -1 when the output device is
+ *	full and the character must be retried. Note that Linux currently
+ *	ignores TABDLY, CRDLY, VTDLY, FFDLY and NLDLY. They simply aren't
+ *	relevant in the world today. If you ever need them, add them here.
+ *
+ *	Called from both the receive and transmit sides and can be called
+ *	re-entrantly. Relies on lock_kernel() still.
  */
+ 
 static int opost(unsigned char c, struct tty_struct *tty)
 {
 	int	space, spaces;
@@ -239,10 +291,20 @@
 	return 0;
 }
 
-/*
- * opost_block --- to speed up block console writes, among other
- * things.
+/**
+ *	opost_block		-	block postprocess
+ *	@tty: terminal device
+ *	@inbuf: user buffer
+ *	@nr: number of bytes
+ *
+ *	This path is used to speed up block console writes, among other
+ *	things when processing blocks of output data. It handles only
+ *	the simple cases normally found and helps to generate blocks of
+ *	symbols for the console driver and thus improve performance.
+ *
+ *	Called from write_chan under the tty layer write lock.
  */
+ 
 static ssize_t opost_block(struct tty_struct * tty,
 		       const unsigned char __user * inbuf, unsigned int nr)
 {
@@ -304,13 +366,27 @@
 }
 
 
-
+/**
+ *	put_char	-	write character to driver
+ *	@c: character (or part of unicode symbol)
+ *	@tty: terminal device
+ *
+ *	Queue a byte to the driver layer for output
+ */
+ 
 static inline void put_char(unsigned char c, struct tty_struct *tty)
 {
 	tty->driver->put_char(tty, c);
 }
 
-/* Must be called only when L_ECHO(tty) is true. */
+/**
+ *	echo_char	-	echo characters
+ *	@c: unicode byte to echo
+ *	@tty: terminal device
+ *
+ *	Echo user input back onto the screen. This must be called only when 
+ *	L_ECHO(tty) is true. Called from the driver receive_buf path.
+ */
 
 static void echo_char(unsigned char c, struct tty_struct *tty)
 {
@@ -331,6 +407,16 @@
 	}
 }
 
+/**
+ *	eraser		-	handle erase function
+ *	@c: character input
+ *	@tty: terminal device
+ *
+ *	Perform erase and neccessary output when an erase character is
+ *	present in the stream from the driver layer. Handles the complexities
+ *	of UTF-8 multibyte symbols.
+ */
+ 
 static void eraser(unsigned char c, struct tty_struct *tty)
 {
 	enum { ERASE, WERASE, KILL } kill_type;
@@ -463,6 +549,18 @@
 		finish_erasing(tty);
 }
 
+/**
+ *	isig		-	handle the ISIG optio
+ *	@sig: signal
+ *	@tty: terminal
+ *	@flush: force flush
+ *
+ *	Called when a signal is being sent due to terminal input. This
+ *	may caus terminal flushing to take place according to the termios
+ *	settings and character used. Called from the driver receive_buf
+ *	path so serialized.
+ */
+ 
 static inline void isig(int sig, struct tty_struct *tty, int flush)
 {
 	if (tty->pgrp > 0)
@@ -474,6 +572,16 @@
 	}
 }
 
+/**
+ *	n_tty_receive_break	-	handle break
+ *	@tty: terminal
+ *
+ *	An RS232 break event has been hit in the incoming bitstream. This
+ *	can cause a variety of events depending upon the termios settings.
+ *
+ *	Called from the receive_buf path so single threaded.
+ */
+ 
 static inline void n_tty_receive_break(struct tty_struct *tty)
 {
 	if (I_IGNBRK(tty))
@@ -490,19 +598,40 @@
 	wake_up_interruptible(&tty->read_wait);
 }
 
+/**
+ *	n_tty_receive_overrun	-	handle overrun reporting
+ *	@tty: terminal
+ *
+ *	Data arrived faster than we could process it. While the tty
+ *	driver has flagged this the bits that were missed are gone
+ *	forever.
+ *
+ *	Called from the receive_buf path so single threaded. Does not
+ *	need locking as num_overrun and overrun_time are function
+ *	private.
+ */
+ 
 static inline void n_tty_receive_overrun(struct tty_struct *tty)
 {
 	char buf[64];
 
 	tty->num_overrun++;
 	if (time_before(tty->overrun_time, jiffies - HZ)) {
-		printk("%s: %d input overrun(s)\n", tty_name(tty, buf),
+		printk(KERN_WARNING "%s: %d input overrun(s)\n", tty_name(tty, buf),
 		       tty->num_overrun);
 		tty->overrun_time = jiffies;
 		tty->num_overrun = 0;
 	}
 }
 
+/**
+ *	n_tty_receive_parity_error	-	error notifier
+ *	@tty: terminal device
+ *	@c: character
+ *
+ *	Process a parity error and queue the right data to indicate
+ *	the error case if neccessary. Locking as per n_tty_receive_buf.
+ */
 static inline void n_tty_receive_parity_error(struct tty_struct *tty,
 					      unsigned char c)
 {
@@ -520,6 +649,16 @@
 	wake_up_interruptible(&tty->read_wait);
 }
 
+/**
+ *	n_tty_receive_char	-	perform processing
+ *	@tty: terminal device
+ *	@c: character
+ *
+ *	Process an individual character of input received from the driver.
+ *	This is serialized with respect to itself by the rules for the 
+ *	driver above.
+ */
+
 static inline void n_tty_receive_char(struct tty_struct *tty, unsigned char c)
 {
 	unsigned long flags;
@@ -711,6 +850,16 @@
 	put_tty_queue(c, tty);
 }	
 
+/**
+ *	n_tty_receive_room	-	receive space
+ *	@tty: terminal
+ *
+ *	Called by the driver to find out how much data it is
+ *	permitted to feed to the line discipline without any being lost
+ *	and thus to manage flow control. Not serialized. Answers for the
+ *	"instant".
+ */
+ 
 static int n_tty_receive_room(struct tty_struct *tty)
 {
 	int	left = N_TTY_BUF_SIZE - tty->read_cnt - 1;
@@ -729,10 +878,13 @@
 	return 0;
 }
 
-/*
- * Required for the ptys, serial driver etc. since processes
- * that attach themselves to the master and rely on ASYNC
- * IO must be woken up
+/**
+ *	n_tty_write_wakeup	-	asynchronous I/O notifier
+ *	@tty: tty device
+ *
+ *	Required for the ptys, serial driver etc. since processes
+ *	that attach themselves to the master and rely on ASYNC
+ *	IO must be woken up
  */
 
 static void n_tty_write_wakeup(struct tty_struct *tty)
@@ -745,6 +897,19 @@
 	return;
 }
 
+/**
+ *	n_tty_receive_buf	-	data receive
+ *	@tty: terminal device
+ *	@cp: buffer
+ *	@fp: flag buffer
+ *	@count: characters
+ *
+ *	Called by the terminal driver when a block of characters has
+ *	been received. This function must be called from soft contexts
+ *	not from interrupt context. The driver is responsible for making
+ *	calls one at a time and in order (or using flush_to_ldisc)
+ */
+ 
 static void n_tty_receive_buf(struct tty_struct *tty, const unsigned char *cp,
 			      char *fp, int count)
 {
@@ -828,6 +993,18 @@
 	        current->sighand->action[sig-1].sa.sa_handler == SIG_IGN);
 }
 
+/**
+ *	n_tty_set_termios	-	termios data changed
+ *	@tty: terminal
+ *	@old: previous data
+ *
+ *	Called by the tty layer when the user changes termios flags so
+ *	that the line discipline can plan ahead. This function cannot sleep
+ *	and is protected from re-entry by the tty layer. The user is 
+ *	guaranteed that this function will not be re-entered or in progress
+ *	when the ldisc is closed.
+ */
+ 
 static void n_tty_set_termios(struct tty_struct *tty, struct termios * old)
 {
 	if (!tty)
@@ -843,7 +1020,6 @@
 	    I_ICRNL(tty) || I_INLCR(tty) || L_ICANON(tty) ||
 	    I_IXON(tty) || L_ISIG(tty) || L_ECHO(tty) ||
 	    I_PARMRK(tty)) {
-		local_irq_disable(); // FIXME: is this safe?
 		memset(tty->process_char_map, 0, 256/8);
 
 		if (I_IGNCR(tty) || I_ICRNL(tty))
@@ -879,7 +1055,6 @@
 			set_bit(SUSP_CHAR(tty), tty->process_char_map);
 		}
 		clear_bit(__DISABLED_CHAR, tty->process_char_map);
-		local_irq_enable(); // FIXME: is this safe?
 		tty->raw = 0;
 		tty->real_raw = 0;
 	} else {
@@ -893,6 +1068,16 @@
 	}
 }
 
+/**
+ *	n_tty_close		-	close the ldisc for this tty
+ *	@tty: device
+ *
+ *	Called from the terminal layer when this line discipline is 
+ *	being shut down, either because of a close or becsuse of a 
+ *	discipline change. The function will not be called while other
+ *	ldisc methods are in progress.
+ */
+ 
 static void n_tty_close(struct tty_struct *tty)
 {
 	n_tty_flush_buffer(tty);
@@ -902,11 +1087,22 @@
 	}
 }
 
+/**
+ *	n_tty_open		-	open an ldisc
+ *	@tty: terminal to open
+ *
+ *	Called when this line discipline is being attached to the 
+ *	terminal device. Can sleep. Called serialized so that no
+ *	other events will occur in parallel. No further open will occur
+ *	until a close.
+ */
+
 static int n_tty_open(struct tty_struct *tty)
 {
 	if (!tty)
 		return -EINVAL;
 
+	/* This one is ugly. Currently a malloc failure here can panic */
 	if (!tty->read_buf) {
 		tty->read_buf = alloc_buf();
 		if (!tty->read_buf)
@@ -932,14 +1128,23 @@
 	return 0;
 }
 
-/*
- * Helper function to speed up read_chan.  It is only called when
- * ICANON is off; it copies characters straight from the tty queue to
- * user space directly.  It can be profitably called twice; once to
- * drain the space from the tail pointer to the (physical) end of the
- * buffer, and once to drain the space from the (physical) beginning of
- * the buffer to head pointer.
+/**
+ * 	copy_from_read_buf	-	copy read data directly
+ *	@tty: terminal device
+ *	@b: user data
+ *	@nr: size of data
+ *
+ *	Helper function to speed up read_chan.  It is only called when
+ *	ICANON is off; it copies characters straight from the tty queue to
+ *	user space directly.  It can be profitably called twice; once to
+ *	drain the space from the tail pointer to the (physical) end of the
+ *	buffer, and once to drain the space from the (physical) beginning of
+ *	the buffer to head pointer.
+ *
+ *	Called under the tty->atomic_read sem and with TTY_DONT_FLIP set
+ *
  */
+ 
 static inline int copy_from_read_buf(struct tty_struct *tty,
 				      unsigned char __user **b,
 				      size_t *nr)
@@ -970,25 +1175,18 @@
 
 extern ssize_t redirected_tty_write(struct file *,const char *,size_t,loff_t *);
 
-static ssize_t read_chan(struct tty_struct *tty, struct file *file,
-			 unsigned char __user *buf, size_t nr)
+/**
+ *	job_control		-	check job control
+ *	@tty: tty
+ *	@file: file handle
+ *
+ *	Perform job control management checks on this file/tty descriptor
+ *	and if appropriate send any needed signals and return a negative 
+ *	error code if action should be taken.
+ */
+ 
+static int job_control(struct tty_struct *tty, struct file *file)
 {
-	unsigned char __user *b = buf;
-	DECLARE_WAITQUEUE(wait, current);
-	int c;
-	int minimum, time;
-	ssize_t retval = 0;
-	ssize_t size;
-	long timeout;
-	unsigned long flags;
-
-do_it_again:
-
-	if (!tty->read_buf) {
-		printk("n_tty_read_chan: called with read_buf == NULL?!?\n");
-		return -EIO;
-	}
-
 	/* Job control check -- must be done at start and after
 	   every sleep (POSIX.1 7.1.1.4). */
 	/* NOTE: not yet done after every sleep pending a thorough
@@ -1006,7 +1204,48 @@
 			return -ERESTARTSYS;
 		}
 	}
+	return 0;
+}
+ 
+
+/**
+ *	read_chan		-	read function for tty
+ *	@tty: tty device
+ *	@file: file object
+ *	@buf: userspace buffer pointer
+ *	@nr: size of I/O
+ *
+ *	Perform reads for the line discipline. We are guaranteed that the
+ *	line discipline will not be closed under us but we may get multiple
+ *	parallel readers and must handle this ourselves. We may also get
+ *	a hangup. Always called in user context, may sleep.
+ *
+ *	This code must be sure never to sleep through a hangup.
+ */
+ 
+static ssize_t read_chan(struct tty_struct *tty, struct file *file,
+			 unsigned char __user *buf, size_t nr)
+{
+	unsigned char __user *b = buf;
+	DECLARE_WAITQUEUE(wait, current);
+	int c;
+	int minimum, time;
+	ssize_t retval = 0;
+	ssize_t size;
+	long timeout;
+	unsigned long flags;
+
+do_it_again:
+
+	if (!tty->read_buf) {
+		printk("n_tty_read_chan: called with read_buf == NULL?!?\n");
+		return -EIO;
+	}
 
+	c = job_control(tty, file);
+	if(c < 0)
+		return c;
+	
 	minimum = time = 0;
 	timeout = MAX_SCHEDULE_TIMEOUT;
 	if (!tty->icanon) {
@@ -1028,6 +1267,9 @@
 		}
 	}
 
+	/*
+	 *	Internal serialization of reads.
+	 */
 	if (file->f_flags & O_NONBLOCK) {
 		if (down_trylock(&tty->atomic_read))
 			return -EAGAIN;
@@ -1177,6 +1419,21 @@
 	return retval;
 }
 
+/**
+ *	write_chan		-	write function for tty
+ *	@tty: tty device
+ *	@file: file object
+ *	@buf: userspace buffer pointer
+ *	@nr: size of I/O
+ *
+ *	Write function of the terminal device. This is serialized with
+ *	respect to other write callers but not to termios changes, reads
+ *	and other such events. We must be careful with N_TTY as the receive
+ *	code will echo characters, thus calling driver write methods.
+ *
+ *	This code must be sure never to sleep through a hangup.
+ */
+ 
 static ssize_t write_chan(struct tty_struct * tty, struct file * file,
 			  const unsigned char __user * buf, size_t nr)
 {
@@ -1246,7 +1503,25 @@
 	return (b - buf) ? b - buf : retval;
 }
 
-/* Called without the kernel lock held - fine */
+/**
+ *	normal_poll		-	poll method for N_TTY
+ *	@tty: terminal device
+ *	@file: file accessing it
+ *	@wait: poll table
+ *
+ *	Called when the line discipline is asked to poll() for data or
+ *	for special events. This code is not serialized with respect to
+ *	other events save open/close.
+ *
+ *	This code must be sure never to sleep through a hangup.
+ *	Called without the kernel lock held - fine
+ *
+ *	FIXME: if someone changes the VMIN or discipline settings for the
+ *	terminal while another process is in poll() the poll does not
+ *	recompute the new limits. Possibly set_termios should issue
+ *	a read wakeup to fix this bug.
+ */
+ 
 static unsigned int normal_poll(struct tty_struct * tty, struct file * file, poll_table *wait)
 {
 	unsigned int mask = 0;
@@ -1287,6 +1562,7 @@
 	n_tty_ioctl,		/* ioctl */
 	n_tty_set_termios,	/* set_termios */
 	normal_poll,		/* poll */
+	NULL,			/* hangup */
 	n_tty_receive_buf,	/* receive_buf */
 	n_tty_receive_room,	/* receive_room */
 	n_tty_write_wakeup	/* write_wakeup */
diff -Nru a/drivers/char/nwflash.c b/drivers/char/nwflash.c
--- a/drivers/char/nwflash.c	2004-10-18 14:57:05 -07:00
+++ b/drivers/char/nwflash.c	2004-10-18 14:57:05 -07:00
@@ -60,15 +60,6 @@
 
 extern spinlock_t gpio_lock;
 
-/*
- * the delay routine - it is often required to let the flash "breeze"...
- */
-void flash_wait(int timeout)
-{
-	current->state = TASK_INTERRUPTIBLE;
-	schedule_timeout(timeout);
-}
-
 static int get_flash_id(void)
 {
 	volatile unsigned int c1, c2;
@@ -401,7 +392,7 @@
 	/*
 	 * wait 10 ms
 	 */
-	flash_wait(HZ / 100);
+	msleep(10);
 
 	/*
 	 * wait while erasing in process (up to 10 sec)
@@ -409,7 +400,7 @@
 	timeout = jiffies + 10 * HZ;
 	c1 = 0;
 	while (!(c1 & 0x80) && time_before(jiffies, timeout)) {
-		flash_wait(HZ / 100);
+		msleep(10);
 		/*
 		 * read any address
 		 */
@@ -440,7 +431,7 @@
 	/*
 	 * just to make sure - verify if erased OK...
 	 */
-	flash_wait(HZ / 100);
+	msleep(10);
 
 	pWritePtr = (unsigned char *) ((unsigned int) (FLASH_BASE + (nBlock << 16)));
 
@@ -587,7 +578,7 @@
 				/*
 				 * wait couple ms
 				 */
-				flash_wait(HZ / 100);
+				msleep(10);
 				/*
 				 * red LED == write
 				 */
@@ -612,7 +603,7 @@
 	leds_event(led_amber_off);
 	leds_event(led_green_on);
 
-	flash_wait(HZ / 100);
+	msleep(10);
 
 	pWritePtr = (unsigned char *) ((unsigned int) (FLASH_BASE + p));
 
diff -Nru a/drivers/char/pcmcia/synclink_cs.c b/drivers/char/pcmcia/synclink_cs.c
--- a/drivers/char/pcmcia/synclink_cs.c	2004-10-18 14:56:28 -07:00
+++ b/drivers/char/pcmcia/synclink_cs.c	2004-10-18 14:56:28 -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.
@@ -41,6 +41,7 @@
 #include <linux/signal.h>
 #include <linux/sched.h>
 #include <linux/timer.h>
+#include <linux/time.h>
 #include <linux/interrupt.h>
 #include <linux/pci.h>
 #include <linux/tty.h>
@@ -68,6 +69,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 +78,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 +237,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 +259,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 +395,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);
@@ -453,8 +444,6 @@
 static int set_rxenable(MGSLPC_INFO *info, int enable);
 static int wait_events(MGSLPC_INFO *info, int __user *mask);
 
-#define jiffies_from_ms(a) ((((a) * HZ)/1000)+1)
-
 static MGSLPC_INFO *mgslpc_device_list = NULL;
 static int mgslpc_device_count = 0;
 
@@ -494,7 +483,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;
 
@@ -504,10 +493,6 @@
 static void mgslpc_change_params(MGSLPC_INFO *info);
 static void mgslpc_wait_until_sent(struct tty_struct *tty, int timeout);
 
-#ifndef MIN
-#define MIN(a,b)	((a) < (b) ? (a) : (b))
-#endif
-
 /* PCMCIA prototypes */
 
 static void mgslpc_config(dev_link_t *link);
@@ -531,6 +516,40 @@
 	return mgslpc_get_text_ptr;
 }
 
+/**
+ * line discipline callback wrappers
+ *
+ * The wrappers maintain line discipline references
+ * while calling into the line discipline.
+ *
+ * ldisc_flush_buffer - flush line discipline receive buffers
+ * ldisc_receive_buf  - pass receive data to line discipline
+ */
+
+static void ldisc_flush_buffer(struct tty_struct *tty)
+{
+	struct tty_ldisc *ld = tty_ldisc_ref(tty);
+	if (ld) {
+		if (ld->flush_buffer)
+			ld->flush_buffer(tty);
+		tty_ldisc_deref(ld);
+	}
+}
+
+static void ldisc_receive_buf(struct tty_struct *tty,
+			      const __u8 *data, char *flags, int count)
+{
+	struct tty_ldisc *ld;
+	if (!tty)
+		return;
+	ld = tty_ldisc_ref(tty);
+	if (ld) {
+		if (ld->receive_buf)
+			ld->receive_buf(tty, data, flags, count);
+		tty_ldisc_deref(ld);
+	}
+}
+
 static dev_link_t *mgslpc_attach(void)
 {
     MGSLPC_INFO *info;
@@ -984,13 +1003,7 @@
 		printk("bh_transmit() entry on %s\n", info->device_name);
 
 	if (tty) {
-		if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
-		    tty->ldisc.write_wakeup) {
-			if ( debug_level >= DEBUG_LEVEL_BH )
-				printk( "%s(%d):calling ldisc.write_wakeup on %s\n",
-					__FILE__,__LINE__,info->device_name);
-			(tty->ldisc.write_wakeup)(tty);
-		}
+		tty_wakeup(tty);
 		wake_up_interruptible(&tty->write_wait);
 	}
 }
@@ -1163,9 +1176,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
 	{
@@ -1201,7 +1214,7 @@
 		return;
 
 	while (info->tx_count && fifo_count) {
-		c = MIN(2, MIN(fifo_count, MIN(info->tx_count, TXBUFSIZE - info->tx_get)));
+		c = min(2, min_t(int, fifo_count, min(info->tx_count, TXBUFSIZE - info->tx_get)));
 		
 		if (c == 1) {
 			write_reg(info, CHA + TXFIFO, *(info->tx_buf + info->tx_get));
@@ -1271,13 +1284,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);
 
@@ -1764,8 +1777,8 @@
 	}
 
 	for (;;) {
-		c = MIN(count,
-			MIN(TXBUFSIZE - info->tx_count - 1,
+		c = min(count,
+			min(TXBUFSIZE - info->tx_count - 1,
 			    TXBUFSIZE - info->tx_put));
 		if (c <= 0)
 			break;
@@ -1875,11 +1888,9 @@
 	info->tx_count = info->tx_put = info->tx_get = 0;
 	del_timer(&info->tx_timer);	
 	spin_unlock_irqrestore(&info->lock,flags);
-	
+
 	wake_up_interruptible(&tty->write_wait);
-	if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
-	    tty->ldisc.write_wakeup)
-		(tty->ldisc.write_wakeup)(tty);
+	tty_wakeup(tty);
 }
 
 /* Send a high-priority XON/XOFF character
@@ -2588,9 +2599,8 @@
 
 	if (tty->driver->flush_buffer)
 		tty->driver->flush_buffer(tty);
-		
-	if (tty->ldisc.flush_buffer)
-		tty->ldisc.flush_buffer(tty);
+
+	ldisc_flush_buffer(tty);
 		
 	shutdown(info);
 	
@@ -2651,7 +2661,7 @@
 		char_time = 1;
 		
 	if (timeout)
-		char_time = MIN(char_time, timeout);
+		char_time = min_t(unsigned long, char_time, timeout);
 		
 	if (info->params.mode == MGSL_MODE_HDLC) {
 		while (info->tx_active) {
@@ -2876,7 +2886,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 +2941,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 +3080,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 +3096,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);
@@ -3669,7 +3674,7 @@
 		} else {
 			info->tx_active = 1;
 			tx_ready(info);
-			info->tx_timer.expires = jiffies + jiffies_from_ms(5000);
+			info->tx_timer.expires = jiffies + msecs_to_jiffies(5000);
 			add_timer(&info->tx_timer);	
 		}
 	}
@@ -4021,9 +4026,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,18 +4060,12 @@
 				++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
-			{
-				/* Call the line discipline receive callback directly. */
-				if (tty && tty->ldisc.receive_buf)
-					tty->ldisc.receive_buf(tty, buf->data, info->flag_buf, framesize);
-			}
+				ldisc_receive_buf(tty, buf->data, info->flag_buf, framesize);
 		}
 	}
 
@@ -4128,7 +4130,7 @@
 	end_time=100;
 	while(end_time-- && !info->irq_occurred) {
 		set_current_state(TASK_INTERRUPTIBLE);
-		schedule_timeout(jiffies_from_ms(10));
+		schedule_timeout(msecs_to_jiffies(10));
 	}
 	
 	info->testing_irq = FALSE;
@@ -4215,88 +4217,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 +4352,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);
 }
 
-void mgslpc_sppp_rx_done(MGSLPC_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(MGSLPC_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(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/pcxx.c b/drivers/char/pcxx.c
--- a/drivers/char/pcxx.c	2004-10-18 14:56:33 -07:00
+++ b/drivers/char/pcxx.c	2004-10-18 14:56:33 -07:00
@@ -130,7 +130,6 @@
 int pcxx_ncook=sizeof(pcxx_cook);
 int pcxx_nbios=sizeof(pcxx_bios);
 
-#define MIN(a,b)	((a) < (b) ? (a) : (b))
 #define pcxxassert(x, msg)  if(!(x)) pcxx_error(__LINE__, msg)
 
 #define FEPTIMEOUT 200000  
@@ -206,7 +205,7 @@
 {
 
 	unsigned long	flags;
-	int e1, e2;
+	int e1;
 
 	printk(KERN_NOTICE "Unloading PC/Xx version %s\n", VERSION);
 
@@ -223,12 +222,6 @@
 	restore_flags(flags);
 }
 
-/*
- * pcxe_init() is our init_module():
- */
-module_init(pcxe_init);
-module_cleanup(pcxe_cleanup);
-
 static inline struct channel *chan(register struct tty_struct *tty)
 {
 	if (tty) {
@@ -538,28 +531,11 @@
 	
 		if(tty->driver->flush_buffer)
 			tty->driver->flush_buffer(tty);
-		if(tty->ldisc.flush_buffer)
-			tty->ldisc.flush_buffer(tty);
+		tty_ldisc_flush(tty);
 		shutdown(info);
 		tty->closing = 0;
 		info->event = 0;
 		info->tty = NULL;
-#ifndef MODULE
-/* ldiscs[] is not available in a MODULE
-** worth noting that while I'm not sure what this hunk of code is supposed
-** to do, it is not present in the serial.c driver.  Hmmm.  If you know,
-** please send me a note.  brian@ilinx.com
-** Don't know either what this is supposed to do christoph@lameter.com.
-*/
-		if(tty->ldisc.num != ldiscs[N_TTY].num) {
-			if(tty->ldisc.close)
-				(tty->ldisc.close)(tty);
-			tty->ldisc = ldiscs[N_TTY];
-			tty->termios->c_line = N_TTY;
-			if(tty->ldisc.open)
-				(tty->ldisc.open)(tty);
-		}
-#endif
 		if(info->blocked_open) {
 			if(info->close_delay) {
 				current->state = TASK_INTERRUPTIBLE;
@@ -626,7 +602,7 @@
 		
 		tail &= (size - 1);
 		stlen = (head >= tail) ? (size - (head - tail) - 1) : (tail - head - 1);
-		count = MIN(stlen, count);
+		count = min(stlen, count);
 		memoff(ch);
 		restore_flags(flags);
 
@@ -658,11 +634,11 @@
 		remain = tail - head - 1;
 		stlen = remain;
 	}
-	count = MIN(remain, count);
+	count = min(remain, count);
 
 	txwinon(ch);
 	while (count > 0) {
-		stlen = MIN(count, stlen);
+		stlen = min(count, stlen);
 		memcpy(ch->txptr + head, buf, stlen);
 		buf += stlen;
 		count -= stlen;
@@ -800,9 +776,7 @@
 	memoff(ch);
 	restore_flags(flags);
 
-	wake_up_interruptible(&tty->write_wait);
-	if((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) && tty->ldisc.write_wakeup)
-		(tty->ldisc.write_wakeup)(tty);
+	tty_wakeup(tty);
 }
 
 static void pcxe_flush_chars(struct tty_struct *tty)
@@ -1013,9 +987,6 @@
 }
 #endif
 
-module_init(pcxe_init)
-module_exit(pcxe_exit)
-
 static struct tty_operations pcxe_ops = {
 	.open = pcxe_open,
 	.close = pcxe_close,
@@ -1561,6 +1532,8 @@
 	return ret;
 }
 
+module_init(pcxe_init)
+module_exit(pcxe_cleanup)
 
 static void pcxxpoll(unsigned long dummy)
 {
@@ -1675,10 +1648,7 @@
 			if (event & LOWTX_IND) {
 				if (ch->statusflags & LOWWAIT) {
 					ch->statusflags &= ~LOWWAIT;
-					if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
-						tty->ldisc.write_wakeup)
-						(tty->ldisc.write_wakeup)(tty);
-					wake_up_interruptible(&tty->write_wait);
+					tty_wakeup(tty);
 				}
 			}
 
@@ -1686,10 +1656,7 @@
 				ch->statusflags &= ~TXBUSY;
 				if (ch->statusflags & EMPTYWAIT) {
 					ch->statusflags &= ~EMPTYWAIT;
-					if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
-						tty->ldisc.write_wakeup)
-						(tty->ldisc.write_wakeup)(tty);
-					wake_up_interruptible(&tty->write_wait);
+					tty_wakeup(tty);
 				}
 			}
 		}
@@ -1995,6 +1962,7 @@
 	volatile struct board_chan *bc;
 	unsigned long flags;
 	int mflag = 0;
+	int mstat;
 
 	if(ch)
 		bc = ch->brdchan;
@@ -2069,6 +2037,7 @@
 	pcxxparam(tty,ch);
 	memoff(ch);
 	restore_flags(flags);
+	return 0;
 }
 
 
@@ -2165,8 +2134,7 @@
 				tty_wait_until_sent(tty, 0);
 			}
 			else {
-				if(tty->ldisc.flush_buffer)
-					tty->ldisc.flush_buffer(tty);
+				tty_ldisc_flush(tty);
 			}
 
 			/* Fall Thru */
diff -Nru a/drivers/char/pty.c b/drivers/char/pty.c
--- a/drivers/char/pty.c	2004-10-18 14:56:28 -07:00
+++ b/drivers/char/pty.c	2004-10-18 14:56:28 -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;
@@ -91,10 +85,7 @@
 	if (!o_tty)
 		return;
 
-	if ((o_tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
-	    o_tty->ldisc.write_wakeup)
-		(o_tty->ldisc.write_wakeup)(o_tty);
-	wake_up_interruptible(&o_tty->write_wait);
+	tty_wakeup(o_tty);
 	set_bit(TTY_THROTTLED, &tty->flags);
 }
 
@@ -107,6 +98,10 @@
  *   (2) avoid redundant copying for cases where count >> receive_room
  * N.B. Calls from user space may now return an error code instead of
  * a count.
+ *
+ * FIXME: Our pty_write method is called with our ldisc lock held but
+ * not our partners. We can't just take the other one blindly without
+ * risking deadlocks.  There is also the small matter of TTY_DONT_FLIP
  */
 static int pty_write(struct tty_struct * tty, int from_user,
 		       const unsigned char *buf, int count)
@@ -205,19 +200,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 +213,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 +269,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 +331,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 +429,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-10-18 14:55:54 -07:00
+++ b/drivers/char/random.c	2004-10-18 14:55:54 -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);
@@ -781,9 +781,9 @@
 
 /* There is one of these per entropy source */
 struct timer_rand_state {
-	__u32		last_time;
-	__s32		last_delta,last_delta2;
-	int		dont_count_entropy:1;
+	cycles_t	last_time;
+	long		last_delta,last_delta2;
+	unsigned	dont_count_entropy:1;
 };
 
 static struct timer_rand_state keyboard_timer_state;
@@ -799,37 +799,31 @@
  * The number "num" is also added to the pool - it should somehow describe
  * the type of event which just happened.  This is currently 0-255 for
  * keyboard scan codes, and 256 upwards for interrupts.
- * On the i386, this is assumed to be at most 16 bits, and the high bits
- * are used for a high-resolution timer.
  *
  */
 static void add_timer_randomness(struct timer_rand_state *state, unsigned num)
 {
-	__u32		time;
-	__s32		delta, delta2, delta3;
+	cycles_t	time;
+	long		delta, delta2, delta3;
 	int		entropy = 0;
 
+	preempt_disable();
 	/* if over the trickle threshold, use only 1 in 4096 samples */
 	if ( random_state->entropy_count > trickle_thresh &&
 	     (__get_cpu_var(trickle_count)++ & 0xfff))
-		return;
+		goto out;
 
-#if defined (__i386__) || defined (__x86_64__)
-	if (cpu_has_tsc) {
-		__u32 high;
-		rdtsc(time, high);
-		num ^= high;
+	/*
+	 * Use get_cycles() if implemented, otherwise fall back to
+	 * jiffies.
+	 */
+	time = get_cycles();
+	if (time != 0) {
+		if (sizeof(time) > 4)
+			num ^= (u32)(time >> 32);
 	} else {
 		time = jiffies;
 	}
-#elif defined (__sparc_v9__)
-	unsigned long tick = tick_ops->get_tick();
-
-	time = (unsigned int) tick;
-	num ^= (tick >> 32UL);
-#else
-	time = jiffies;
-#endif
 
 	/*
 	 * Calculate number of bits of randomness we probably added.
@@ -868,6 +862,8 @@
 		entropy = int_ln_12bits(delta);
 	}
 	batch_entropy_store(num, time, entropy);
+out:
+	preempt_enable();
 }
 
 void add_keyboard_randomness(unsigned char scancode)
@@ -1328,8 +1324,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 +1368,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 +1381,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 +1471,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,15 +1529,22 @@
 {
 	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);
+	init_std_data(urandom_state);
 #ifdef CONFIG_SYSCTL
 	sysctl_init_random(random_state);
 #endif
@@ -1674,9 +1677,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
@@ -1730,10 +1739,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:
@@ -1754,40 +1762,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;
@@ -1884,7 +1858,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,
@@ -2212,7 +2187,7 @@
 #undef K3
 
 /* This should not be decreased so low that ISNs wrap too fast. */
-#define REKEY_INTERVAL	300
+#define REKEY_INTERVAL	(300*HZ)
 /*
  * Bit layout of the tcp sequence numbers (before adding current time):
  * bit 24-31: increased after every key exchange
@@ -2238,43 +2213,55 @@
 #define HASH_MASK	( (1<<HASH_BITS)-1 )
 
 static struct keydata {
-	time_t rekey_time;
 	__u32	count;		// already shifted to the final position
 	__u32	secret[12];
 } ____cacheline_aligned ip_keydata[2];
 
-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_);
+
+static DECLARE_WORK(rekey_work, rekey_seq_generator, NULL);
+
+/*
+ * Lock avoidance:
+ * The ISN generation runs lockless - it's just a hash over random data.
+ * State changes happen every 5 minutes when the random key is replaced.
+ * Synchronization is performed by having two copies of the hash function
+ * state and rekey_seq_generator always updates the inactive copy.
+ * The copy is then activated by updating ip_cnt.
+ * The implementation breaks down if someone blocks the thread
+ * that processes SYN requests for more than 5 minutes. Should never
+ * happen, and even if that happens only a not perfectly compliant
+ * ISN is generated, nothing fatal.
+ */
+static void rekey_seq_generator(void *private_)
 {
-	struct keydata *keyptr;
-	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++;
-	}
-	spin_unlock_bh(&ip_lock);
-	return keyptr;
+	struct keydata *keyptr = &ip_keydata[1^(ip_cnt&1)];
+
+	get_random_bytes(keyptr->secret, sizeof(keyptr->secret));
+	keyptr->count = (ip_cnt&COUNT_MASK)<<HASH_BITS;
+	smp_wmb();
+	ip_cnt++;
+	schedule_delayed_work(&rekey_work, REKEY_INTERVAL);
 }
 
-static inline struct keydata *check_and_rekey(time_t time)
+static inline struct keydata *get_keyptr(void)
 {
 	struct keydata *keyptr = &ip_keydata[ip_cnt&1];
 
-	rmb();
-	if (!keyptr->rekey_time || (time - keyptr->rekey_time) > REKEY_INTERVAL) {
-		keyptr = __check_and_rekey(time);
-	}
+	smp_rmb();
 
 	return keyptr;
 }
 
+static __init int seqgen_init(void)
+{
+	rekey_seq_generator(NULL);
+	return 0;
+}
+late_initcall(seqgen_init);
+
 #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
 __u32 secure_tcpv6_sequence_number(__u32 *saddr, __u32 *daddr,
 				   __u16 sport, __u16 dport)
@@ -2282,14 +2269,12 @@
 	struct timeval 	tv;
 	__u32		seq;
 	__u32		hash[12];
-	struct keydata *keyptr;
+	struct keydata *keyptr = get_keyptr();
 
 	/* The procedure is the same as for IPv4, but addresses are longer.
 	 * Thus we must use twothirdsMD4Transform.
 	 */
 
-	do_gettimeofday(&tv);	/* We need the usecs below... */
-	keyptr = check_and_rekey(tv.tv_sec);
 
 	memcpy(hash, saddr, 16);
 	hash[4]=(sport << 16) + dport;
@@ -2297,38 +2282,22 @@
 
 	seq = twothirdsMD4Transform(daddr, hash) & HASH_MASK;
 	seq += keyptr->count;
+
+	do_gettimeofday(&tv);
 	seq += tv.tv_usec + tv.tv_sec*1000000;
 
 	return seq;
 }
 EXPORT_SYMBOL(secure_tcpv6_sequence_number);
-
-__u32 secure_ipv6_id(__u32 *daddr)
-{
-	struct keydata *keyptr;
-
-	keyptr = check_and_rekey(get_seconds());
-
-	return halfMD4Transform(daddr, keyptr->secret);
-}
-
-EXPORT_SYMBOL(secure_ipv6_id);
 #endif
 
-
 __u32 secure_tcp_sequence_number(__u32 saddr, __u32 daddr,
 				 __u16 sport, __u16 dport)
 {
 	struct timeval 	tv;
 	__u32		seq;
 	__u32	hash[4];
-	struct keydata *keyptr;
-
-	/*
-	 * Pick a random secret every REKEY_INTERVAL seconds.
-	 */
-	do_gettimeofday(&tv);	/* We need the usecs below... */
-	keyptr = check_and_rekey(tv.tv_sec);
+	struct keydata *keyptr = get_keyptr();
 
 	/*
 	 *  Pick a unique starting offset for each TCP connection endpoints
@@ -2351,6 +2320,7 @@
 	 *	That's funny, Linux has one built in!  Use it!
 	 *	(Networks are faster now - should this be increased?)
 	 */
+	do_gettimeofday(&tv);
 	seq += tv.tv_usec + tv.tv_sec*1000000;
 #if 0
 	printk("init_seq(%lx, %lx, %d, %d) = %d\n",
@@ -2369,7 +2339,7 @@
 	struct keydata *keyptr;
 	__u32 hash[4];
 
-	keyptr = check_and_rekey(get_seconds());
+	keyptr = get_keyptr();
 
 	/*
 	 *  Pick a unique starting offset for each IP destination.
diff -Nru a/drivers/char/rio/linux_compat.h b/drivers/char/rio/linux_compat.h
--- a/drivers/char/rio/linux_compat.h	2004-10-18 14:56:28 -07:00
+++ b/drivers/char/rio/linux_compat.h	2004-10-18 14:56:28 -07:00
@@ -16,7 +16,7 @@
  *      Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  */
 
-#include <asm/hardirq.h>
+#include <linux/interrupt.h>
 
 
 #define disable(oldspl) save_flags (oldspl)
diff -Nru a/drivers/char/rio/rio_linux.c b/drivers/char/rio/rio_linux.c
--- a/drivers/char/rio/rio_linux.c	2004-10-18 14:56:33 -07:00
+++ b/drivers/char/rio/rio_linux.c	2004-10-18 14:56:33 -07:00
@@ -1138,8 +1138,8 @@
       hp->Ivec = pdev->irq;
       if (((1 << hp->Ivec) & rio_irqmask) == 0)
               hp->Ivec = 0;
-      hp->CardP	= (struct DpRam *)
       hp->Caddr = ioremap(p->RIOHosts[p->RIONumHosts].PaddrP, RIO_WINDOW_LEN);
+      hp->CardP	= (struct DpRam *) hp->Caddr;
       hp->Type  = RIO_PCI;
       hp->Copy  = rio_pcicopy; 
       hp->Mode  = RIO_PCI_BOOT_FROM_RAM;
@@ -1196,8 +1196,8 @@
       if (((1 << hp->Ivec) & rio_irqmask) == 0) 
       	hp->Ivec = 0;
       hp->Ivec |= 0x8000; /* Mark as non-sharable */
-      hp->CardP	= (struct DpRam *)
       hp->Caddr = ioremap(p->RIOHosts[p->RIONumHosts].PaddrP, RIO_WINDOW_LEN);
+      hp->CardP	= (struct DpRam *) hp->Caddr;
       hp->Type  = RIO_PCI;
       hp->Copy  = rio_pcicopy;
       hp->Mode  = RIO_PCI_BOOT_FROM_RAM;
@@ -1242,8 +1242,8 @@
     hp->PaddrP = rio_probe_addrs[i];
     /* There was something about the IRQs of these cards. 'Forget what.--REW */
     hp->Ivec = 0;
-    hp->CardP = (struct DpRam *)
     hp->Caddr = ioremap(p->RIOHosts[p->RIONumHosts].PaddrP, RIO_WINDOW_LEN);
+    hp->CardP = (struct DpRam *) hp->Caddr;
     hp->Type = RIO_AT;
     hp->Copy = rio_pcicopy; /* AT card PCI???? - PVDL
                              * -- YES! this is now a normal copy. Only the 
diff -Nru a/drivers/char/riscom8.c b/drivers/char/riscom8.c
--- a/drivers/char/riscom8.c	2004-10-18 14:56:29 -07:00
+++ b/drivers/char/riscom8.c	2004-10-18 14:56:29 -07:00
@@ -75,10 +75,6 @@
 	 ASYNC_SPD_HI       | ASYNC_SPEED_VHI    | ASYNC_SESSION_LOCKOUT | \
 	 ASYNC_PGRP_LOCKOUT | ASYNC_CALLOUT_NOHUP)
 
-#ifndef MIN
-#define MIN(a,b) ((a) < (b) ? (a) : (b))
-#endif
-
 #define RS_EVENT_WRITE_WAKEUP	0
 
 static struct riscom_board * IRQ_to_board[16];
@@ -107,7 +103,7 @@
 };
 
 static struct riscom_port rc_port[RC_NBOARD * RC_NPORT];
-		
+
 /* RISCom/8 I/O ports addresses (without address translation) */
 static unsigned short rc_ioport[] =  {
 #if 1	
@@ -483,7 +479,7 @@
 				rc_out(bp, CD180_TDR, CD180_C_SBRK);
 				port->COR2 &= ~COR2_ETC;
 			}
-			count = MIN(port->break_length, 0xff);
+			count = min_t(int, port->break_length, 0xff);
 			rc_out(bp, CD180_TDR, CD180_C_ESC);
 			rc_out(bp, CD180_TDR, CD180_C_DELAY);
 			rc_out(bp, CD180_TDR, count);
@@ -1127,8 +1123,8 @@
 	rc_shutdown_port(bp, port);
 	if (tty->driver->flush_buffer)
 		tty->driver->flush_buffer(tty);
-	if (tty->ldisc.flush_buffer)
-		tty->ldisc.flush_buffer(tty);
+	tty_ldisc_flush(tty);
+
 	tty->closing = 0;
 	port->event = 0;
 	port->tty = NULL;
@@ -1165,8 +1161,8 @@
 		down(&tmp_buf_sem);
 		while (1) {
 			cli();		
-			c = MIN(count, MIN(SERIAL_XMIT_SIZE - port->xmit_cnt - 1,
-					   SERIAL_XMIT_SIZE - port->xmit_head));
+			c = min_t(int, count, min(SERIAL_XMIT_SIZE - port->xmit_cnt - 1,
+						  SERIAL_XMIT_SIZE - port->xmit_head));
 			if (c <= 0)
 				break;
 
@@ -1178,8 +1174,8 @@
 			}
 
 			cli();
-			c = MIN(c, MIN(SERIAL_XMIT_SIZE - port->xmit_cnt - 1,
-				       SERIAL_XMIT_SIZE - port->xmit_head));
+			c = min_t(int, c, min(SERIAL_XMIT_SIZE - port->xmit_cnt - 1,
+					 SERIAL_XMIT_SIZE - port->xmit_head));
 			memcpy(port->xmit_buf + port->xmit_head, tmp_buf, c);
 			port->xmit_head = (port->xmit_head + c) & (SERIAL_XMIT_SIZE-1);
 			port->xmit_cnt += c;
@@ -1193,8 +1189,8 @@
 	} else {
 		while (1) {
 			cli();		
-			c = MIN(count, MIN(SERIAL_XMIT_SIZE - port->xmit_cnt - 1,
-					   SERIAL_XMIT_SIZE - port->xmit_head));
+			c = min_t(int, count, min(SERIAL_XMIT_SIZE - port->xmit_cnt - 1,
+						  SERIAL_XMIT_SIZE - port->xmit_head));
 			if (c <= 0) {
 				restore_flags(flags);
 				break;
@@ -1301,9 +1297,7 @@
 	restore_flags(flags);
 	
 	wake_up_interruptible(&tty->write_wait);
-	if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
-	    tty->ldisc.write_wakeup)
-		(tty->ldisc.write_wakeup)(tty);
+	tty_wakeup(tty);
 }
 
 static int rc_tiocmget(struct tty_struct *tty, struct file *file)
@@ -1644,9 +1638,7 @@
 		return;
 
 	if (test_and_clear_bit(RS_EVENT_WRITE_WAKEUP, &port->event)) {
-		if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
-		    tty->ldisc.write_wakeup)
-			(tty->ldisc.write_wakeup)(tty);
+		tty_wakeup(tty);
 		wake_up_interruptible(&tty->write_wait);
 	}
 }
diff -Nru a/drivers/char/rocket.c b/drivers/char/rocket.c
--- a/drivers/char/rocket.c	2004-10-18 14:56:48 -07:00
+++ b/drivers/char/rocket.c	2004-10-18 14:56:48 -07:00
@@ -250,12 +250,16 @@
 			  CHANNEL_t * cp, unsigned int ChanStatus)
 {
 	unsigned int CharNStat;
-	int ToRecv, wRecv, space, count;
+	int ToRecv, wRecv, space = 0, count;
 	unsigned char *cbuf;
 	char *fbuf;
+	struct tty_ldisc *ld;
+
+	ld = tty_ldisc_ref(tty);
 
 	ToRecv = sGetRxCnt(cp);
-	space = tty->ldisc.receive_room(tty);
+	if (ld)
+		space = ld->receive_room(tty);
 	if (space > 2 * TTY_FLIPBUF_SIZE)
 		space = 2 * TTY_FLIPBUF_SIZE;
 	cbuf = tty->flip.char_buf;
@@ -354,7 +358,8 @@
 		count += ToRecv;
 	}
 	/*  Push the data up to the tty layer */
-	tty->ldisc.receive_buf(tty, tty->flip.char_buf, tty->flip.flag_buf, count);
+	ld->receive_buf(tty, tty->flip.char_buf, tty->flip.flag_buf, count);
+	tty_ldisc_deref(ld);
 }
 
 /*
@@ -389,7 +394,7 @@
 	while (1) {
 		if (tty->stopped || tty->hw_stopped)
 			break;
-		c = MIN(info->xmit_fifo_room, MIN(info->xmit_cnt, XMIT_BUF_SIZE - info->xmit_tail));
+		c = min(info->xmit_fifo_room, min(info->xmit_cnt, XMIT_BUF_SIZE - info->xmit_tail));
 		if (c <= 0 || info->xmit_fifo_room <= 0)
 			break;
 		sOutStrW(sGetTxRxDataIO(cp), (unsigned short *) (info->xmit_buf + info->xmit_tail), c / 2);
@@ -408,8 +413,7 @@
 		clear_bit((info->aiop * 8) + info->chan, (void *) &xmit_flags[info->board]);
 
 	if (info->xmit_cnt < WAKEUP_CHARS) {
-		if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) && tty->ldisc.write_wakeup)
-			(tty->ldisc.write_wakeup) (tty);
+		tty_wakeup(tty);
 		wake_up_interruptible(&tty->write_wait);
 #ifdef ROCKETPORT_HAVE_POLL_WAIT
 		wake_up_interruptible(&tty->poll_wait);
@@ -1022,7 +1026,7 @@
 	unsigned long flags;
 	int timeout;
 	CHANNEL_t *cp;
-
+	
 	if (rocket_paranoia_check(info, "rp_close"))
 		return;
 
@@ -1101,8 +1105,8 @@
 
 	if (TTY_DRIVER_FLUSH_BUFFER_EXISTS(tty))
 		TTY_DRIVER_FLUSH_BUFFER(tty);
-	if (tty->ldisc.flush_buffer)
-		tty->ldisc.flush_buffer(tty);
+		
+	tty_ldisc_flush(tty);
 
 	clear_bit((info->aiop * 8) + info->chan, (void *) &xmit_flags[info->board]);
 
@@ -1283,11 +1287,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;
@@ -1662,7 +1662,7 @@
 	 *  into FIFO.  Use the write queue for temp storage.
          */
 	if (!tty->stopped && !tty->hw_stopped && info->xmit_cnt == 0 && info->xmit_fifo_room > 0) {
-		c = MIN(count, info->xmit_fifo_room);
+		c = min(count, info->xmit_fifo_room);
 		b = buf;
 		if (from_user) {
 			if (copy_from_user(info->xmit_buf, buf, c)) {
@@ -1672,7 +1672,7 @@
 			if (info->tty == 0)
 				goto end;
 			b = info->xmit_buf;
-			c = MIN(c, info->xmit_fifo_room);
+			c = min(c, info->xmit_fifo_room);
 		}
 
 		/*  Push data into FIFO, 2 bytes at a time */
@@ -1700,7 +1700,7 @@
 		if (info->tty == 0)	/*   Seemingly obligatory check... */
 			goto end;
 
-		c = MIN(count, MIN(XMIT_BUF_SIZE - info->xmit_cnt - 1, XMIT_BUF_SIZE - info->xmit_head));
+		c = min(count, min(XMIT_BUF_SIZE - info->xmit_cnt - 1, XMIT_BUF_SIZE - info->xmit_head));
 		if (c <= 0)
 			break;
 
@@ -1731,8 +1731,7 @@
 	
 end:
  	if (info->xmit_cnt < WAKEUP_CHARS) {
-		if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP))  && tty->ldisc.write_wakeup)
-			(tty->ldisc.write_wakeup) (tty);
+ 		tty_wakeup(tty);
 		wake_up_interruptible(&tty->write_wait);
 #ifdef ROCKETPORT_HAVE_POLL_WAIT
 		wake_up_interruptible(&tty->poll_wait);
@@ -1806,8 +1805,7 @@
 #ifdef ROCKETPORT_HAVE_POLL_WAIT
 	wake_up_interruptible(&tty->poll_wait);
 #endif
-	if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) && tty->ldisc.write_wakeup)
-		(tty->ldisc.write_wakeup) (tty);
+	tty_wakeup(tty);
 
 	cp = &info->channel;
 	sFlushTxFIFO(cp);
diff -Nru a/drivers/char/rocket_int.h b/drivers/char/rocket_int.h
--- a/drivers/char/rocket_int.h	2004-10-18 14:56:15 -07:00
+++ b/drivers/char/rocket_int.h	2004-10-18 14:56:15 -07:00
@@ -1241,10 +1241,6 @@
 #define TTY_ROCKET_MAJOR	46
 #define CUA_ROCKET_MAJOR	47
 
-#ifndef MIN
-#define MIN(a,b)	((a) < (b) ? (a) : (b))
-#endif
-
 #ifdef PCI_VENDOR_ID_RP
 #undef PCI_VENDOR_ID_RP
 #undef PCI_DEVICE_ID_RP8OCTA
diff -Nru a/drivers/char/selection.c b/drivers/char/selection.c
--- a/drivers/char/selection.c	2004-10-18 14:57:04 -07:00
+++ b/drivers/char/selection.c	2004-10-18 14:57:04 -07:00
@@ -26,10 +26,6 @@
 #include <linux/tiocl.h>
 #include <linux/console.h>
 
-#ifndef MIN
-#define MIN(a,b)	((a) < (b) ? (a) : (b))
-#endif
-
 /* Don't take this from <ctype.h>: 011-015 on the screen aren't spaces */
 #define isspace(c)	((c) == ' ')
 
@@ -281,12 +277,15 @@
 {
 	struct vt_struct *vt = (struct vt_struct *) tty->driver_data;
 	int	pasted = 0, count;
+	struct  tty_ldisc *ld;
 	DECLARE_WAITQUEUE(wait, current);
 
 	acquire_console_sem();
 	poke_blanked_console();
 	release_console_sem();
 
+	ld = tty_ldisc_ref_wait(tty);
+	
 	add_wait_queue(&vt->paste_wait, &wait);
 	while (sel_buffer && sel_buffer_lth > pasted) {
 		set_current_state(TASK_INTERRUPTIBLE);
@@ -295,12 +294,14 @@
 			continue;
 		}
 		count = sel_buffer_lth - pasted;
-		count = MIN(count, tty->ldisc.receive_room(tty));
+		count = min(count, tty->ldisc.receive_room(tty));
 		tty->ldisc.receive_buf(tty, sel_buffer + pasted, NULL, count);
 		pasted += count;
 	}
 	remove_wait_queue(&vt->paste_wait, &wait);
 	current->state = TASK_RUNNING;
+
+	tty_ldisc_deref(ld);
 	return 0;
 }
 
diff -Nru a/drivers/char/ser_a2232.c b/drivers/char/ser_a2232.c
--- a/drivers/char/ser_a2232.c	2004-10-18 14:56:27 -07:00
+++ b/drivers/char/ser_a2232.c	2004-10-18 14:56:27 -07:00
@@ -599,10 +599,7 @@
 					
 				/* WakeUp if output buffer runs low */
 				if ((port->gs.xmit_cnt <= port->gs.wakeup_chars) && port->gs.tty) {
-					if ((port->gs.tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) && port->gs.tty->ldisc.write_wakeup){
-						(port->gs.tty->ldisc.write_wakeup)(port->gs.tty);
-					}
-					wake_up_interruptible(&port->gs.tty->write_wait);
+					tty_wakeup(port->gs.tty);
 				}
 			} // if the port is used
 		} // for every port on the board
diff -Nru a/drivers/char/serial167.c b/drivers/char/serial167.c
--- a/drivers/char/serial167.c	2004-10-18 14:56:29 -07:00
+++ b/drivers/char/serial167.c	2004-10-18 14:56:29 -07:00
@@ -83,10 +83,6 @@
 #undef  CYCLOM_16Y_HACK
 #define  CYCLOM_ENABLE_MONITORING
 
-#ifndef MIN
-#define MIN(a,b)	((a) < (b) ? (a) : (b))
-#endif
-
 #define WAKEUP_CHARS 256
 
 #define STD_COM_FLAGS (0)
@@ -760,11 +756,7 @@
 	wake_up_interruptible(&info->open_wait);
     }
     if (test_and_clear_bit(Cy_EVENT_WRITE_WAKEUP, &info->event)) {
-	if((tty->flags & (1<< TTY_DO_WRITE_WAKEUP))
-	&& tty->ldisc.write_wakeup){
-	    (tty->ldisc.write_wakeup)(tty);
-	}
-	wake_up_interruptible(&tty->write_wait);
+    	tty_wakeup(tty);
     }
 } /* do_softint */
 
@@ -1238,8 +1230,8 @@
     if (from_user) {
 	    down(&tmp_buf_sem);
 	    while (1) {
-		    c = MIN(count, MIN(SERIAL_XMIT_SIZE - info->xmit_cnt - 1,
-				       SERIAL_XMIT_SIZE - info->xmit_head));
+		    c = min_t(int, count, min(SERIAL_XMIT_SIZE - info->xmit_cnt - 1,
+					      SERIAL_XMIT_SIZE - info->xmit_head));
 		    if (c <= 0)
 			    break;
 
@@ -1251,8 +1243,8 @@
 		    }
 
 		    local_irq_save(flags);
-		    c = MIN(c, MIN(SERIAL_XMIT_SIZE - info->xmit_cnt - 1,
-				   SERIAL_XMIT_SIZE - info->xmit_head));
+		    c = min_t(int, c, min(SERIAL_XMIT_SIZE - info->xmit_cnt - 1,
+					  SERIAL_XMIT_SIZE - info->xmit_head));
 		    memcpy(info->xmit_buf + info->xmit_head, tmp_buf, c);
 		    info->xmit_head = (info->xmit_head + c) & (SERIAL_XMIT_SIZE-1);
 		    info->xmit_cnt += c;
@@ -1266,8 +1258,8 @@
     } else {
 	    while (1) {
 		    local_irq_save(flags);
-		    c = MIN(count, MIN(SERIAL_XMIT_SIZE - info->xmit_cnt - 1,
-				       SERIAL_XMIT_SIZE - info->xmit_head));
+		    c = min_t(int, count, min(SERIAL_XMIT_SIZE - info->xmit_cnt - 1,
+					      SERIAL_XMIT_SIZE - info->xmit_head));
 		    if (c <= 0) {
 			    local_irq_restore(flags);
 			    break;
@@ -1343,10 +1335,7 @@
     local_irq_save(flags);
 	info->xmit_cnt = info->xmit_head = info->xmit_tail = 0;
     local_irq_restore(flags);
-    wake_up_interruptible(&tty->write_wait);
-    if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP))
-    && tty->ldisc.write_wakeup)
-	(tty->ldisc.write_wakeup)(tty);
+    tty_wakeup(tty);
 } /* cy_flush_buffer */
 
 
@@ -1846,18 +1835,9 @@
     shutdown(info);
     if (tty->driver->flush_buffer)
 	tty->driver->flush_buffer(tty);
-    if (tty->ldisc.flush_buffer)
-	tty->ldisc.flush_buffer(tty);
+    tty_ldisc_flush(tty);
     info->event = 0;
     info->tty = 0;
-    if (tty->ldisc.num != ldiscs[N_TTY].num) {
-	if (tty->ldisc.close)
-	    (tty->ldisc.close)(tty);
-	tty->ldisc = ldiscs[N_TTY];
-	tty->termios->c_line = N_TTY;
-	if (tty->ldisc.open)
-	    (tty->ldisc.open)(tty);
-    }
     if (info->blocked_open) {
 	if (info->close_delay) {
 	    current->state = TASK_INTERRUPTIBLE;
@@ -2379,7 +2359,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/serial_tx3912.c b/drivers/char/serial_tx3912.c
--- a/drivers/char/serial_tx3912.c	2004-10-18 14:56:32 -07:00
+++ b/drivers/char/serial_tx3912.c	2004-10-18 14:56:32 -07:00
@@ -191,12 +191,9 @@
 	}
 	
         if (port->gs.xmit_cnt <= port->gs.wakeup_chars) {
-                if ((port->gs.tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
-                    port->gs.tty->ldisc.write_wakeup)
-                        (port->gs.tty->ldisc.write_wakeup)(port->gs.tty);
+        	tty_wakeup(port->gs.tty);
                 rs_dprintk (TX3912_UART_DEBUG_TRANSMIT, "Waking up.... ldisc (%d)....\n",
                             port->gs.wakeup_chars); 
-                wake_up_interruptible(&port->gs.tty->write_wait);
        	}	
 }
 
diff -Nru a/drivers/char/snsc.c b/drivers/char/snsc.c
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/drivers/char/snsc.c	2004-10-18 14:57:24 -07:00
@@ -0,0 +1,456 @@
+/*
+ * SN Platform system controller communication support
+ *
+ * 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) 2004 Silicon Graphics, Inc. All rights reserved.
+ */
+
+/*
+ * System controller communication driver
+ *
+ * This driver allows a user process to communicate with the system
+ * controller (a.k.a. "IRouter") network in an SGI SN system.
+ */
+
+#include <linux/interrupt.h>
+#include <linux/sched.h>
+#include <linux/device.h>
+#include <linux/poll.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <asm/sn/sn_sal.h>
+#include <asm/sn/nodepda.h>
+#include "snsc.h"
+
+#define SYSCTL_BASENAME	"snsc"
+
+#define SCDRV_BUFSZ	2048
+#define SCDRV_TIMEOUT	1000
+
+static irqreturn_t
+scdrv_interrupt(int irq, void *subch_data, struct pt_regs *regs)
+{
+	struct subch_data_s *sd = subch_data;
+	unsigned long flags;
+	int status;
+
+	spin_lock_irqsave(&sd->sd_rlock, flags);
+	spin_lock(&sd->sd_wlock);
+	status = ia64_sn_irtr_intr(sd->sd_nasid, sd->sd_subch);
+
+	if (status > 0) {
+		if (status & SAL_IROUTER_INTR_RECV) {
+			wake_up(&sd->sd_rq);
+		}
+		if (status & SAL_IROUTER_INTR_XMIT) {
+			ia64_sn_irtr_intr_disable
+			    (sd->sd_nasid, sd->sd_subch,
+			     SAL_IROUTER_INTR_XMIT);
+			wake_up(&sd->sd_wq);
+		}
+	}
+	spin_unlock(&sd->sd_wlock);
+	spin_unlock_irqrestore(&sd->sd_rlock, flags);
+	return IRQ_HANDLED;
+}
+
+/*
+ * scdrv_open
+ *
+ * Reserve a subchannel for system controller communication.
+ */
+
+static int
+scdrv_open(struct inode *inode, struct file *file)
+{
+	struct sysctl_data_s *scd;
+	struct subch_data_s *sd;
+	int rv;
+
+	/* look up device info for this device file */
+	scd = container_of(inode->i_cdev, struct sysctl_data_s, scd_cdev);
+
+	/* allocate memory for subchannel data */
+	sd = kmalloc(sizeof (struct subch_data_s), GFP_KERNEL);
+	if (sd == NULL) {
+		printk("%s: couldn't allocate subchannel data\n",
+		       __FUNCTION__);
+		return -ENOMEM;
+	}
+
+	/* initialize subch_data_s fields */
+	memset(sd, 0, sizeof (struct subch_data_s));
+	sd->sd_nasid = scd->scd_nasid;
+	sd->sd_subch = ia64_sn_irtr_open(scd->scd_nasid);
+
+	if (sd->sd_subch < 0) {
+		kfree(sd);
+		printk("%s: couldn't allocate subchannel\n", __FUNCTION__);
+		return -EBUSY;
+	}
+
+	spin_lock_init(&sd->sd_rlock);
+	spin_lock_init(&sd->sd_wlock);
+	init_waitqueue_head(&sd->sd_rq);
+	init_waitqueue_head(&sd->sd_wq);
+	sema_init(&sd->sd_rbs, 1);
+	sema_init(&sd->sd_wbs, 1);
+
+	file->private_data = sd;
+
+	/* hook this subchannel up to the system controller interrupt */
+	rv = request_irq(SGI_UART_VECTOR, scdrv_interrupt,
+			 SA_SHIRQ | SA_INTERRUPT,
+			 SYSCTL_BASENAME, sd);
+	if (rv) {
+		ia64_sn_irtr_close(sd->sd_nasid, sd->sd_subch);
+		kfree(sd);
+		printk("%s: irq request failed (%d)\n", __FUNCTION__, rv);
+		return -EBUSY;
+	}
+
+	return 0;
+}
+
+/*
+ * scdrv_release
+ *
+ * Release a previously-reserved subchannel.
+ */
+
+static int
+scdrv_release(struct inode *inode, struct file *file)
+{
+	struct subch_data_s *sd = (struct subch_data_s *) file->private_data;
+	int rv;
+
+	/* free the interrupt */
+	free_irq(SGI_UART_VECTOR, sd);
+
+	/* ask SAL to close the subchannel */
+	rv = ia64_sn_irtr_close(sd->sd_nasid, sd->sd_subch);
+
+	kfree(sd);
+	return rv;
+}
+
+/*
+ * scdrv_read
+ *
+ * Called to read bytes from the open IRouter pipe.
+ *
+ */
+
+static inline int
+read_status_check(struct subch_data_s *sd, int *len)
+{
+	return ia64_sn_irtr_recv(sd->sd_nasid, sd->sd_subch, sd->sd_rb, len);
+}
+
+static ssize_t
+scdrv_read(struct file *file, char __user *buf, size_t count, loff_t *f_pos)
+{
+	int status;
+	int len;
+	unsigned long flags;
+	struct subch_data_s *sd = (struct subch_data_s *) file->private_data;
+
+	/* try to get control of the read buffer */
+	if (down_trylock(&sd->sd_rbs)) {
+		/* somebody else has it now;
+		 * if we're non-blocking, then exit...
+		 */
+		if (file->f_flags & O_NONBLOCK) {
+			return -EAGAIN;
+		}
+		/* ...or if we want to block, then do so here */
+		if (down_interruptible(&sd->sd_rbs)) {
+			/* something went wrong with wait */
+			return -ERESTARTSYS;
+		}
+	}
+
+	/* anything to read? */
+	len = CHUNKSIZE;
+	spin_lock_irqsave(&sd->sd_rlock, flags);
+	status = read_status_check(sd, &len);
+
+	/* if not, and we're blocking I/O, loop */
+	while (status < 0) {
+		DECLARE_WAITQUEUE(wait, current);
+
+		if (file->f_flags & O_NONBLOCK) {
+			spin_unlock_irqrestore(&sd->sd_rlock, flags);
+			up(&sd->sd_rbs);
+			return -EAGAIN;
+		}
+
+		len = CHUNKSIZE;
+		add_wait_queue(&sd->sd_rq, &wait);
+		set_current_state(TASK_INTERRUPTIBLE);
+		spin_unlock_irqrestore(&sd->sd_rlock, flags);
+
+		schedule_timeout(SCDRV_TIMEOUT);
+
+		remove_wait_queue(&sd->sd_rq, &wait);
+		if (signal_pending(current)) {
+			/* wait was interrupted */
+			up(&sd->sd_rbs);
+			return -ERESTARTSYS;
+		}
+
+		spin_lock_irqsave(&sd->sd_rlock, flags);
+		status = read_status_check(sd, &len);
+	}
+	spin_unlock_irqrestore(&sd->sd_rlock, flags);
+
+	if (len > 0) {
+		/* we read something in the last read_status_check(); copy
+		 * it out to user space
+		 */
+		if (count < len) {
+			pr_debug("%s: only accepting %d of %d bytes\n",
+				 __FUNCTION__, (int) count, len);
+		}
+		len = min((int) count, len);
+		if (copy_to_user(buf, sd->sd_rb, len))
+			len = -EFAULT;
+	}
+
+	/* release the read buffer and wake anyone who might be
+	 * waiting for it
+	 */
+	up(&sd->sd_rbs);
+
+	/* return the number of characters read in */
+	return len;
+}
+
+/*
+ * scdrv_write
+ *
+ * Writes a chunk of an IRouter packet (or other system controller data)
+ * to the system controller.
+ *
+ */
+static inline int
+write_status_check(struct subch_data_s *sd, int count)
+{
+	return ia64_sn_irtr_send(sd->sd_nasid, sd->sd_subch, sd->sd_wb, count);
+}
+
+static ssize_t
+scdrv_write(struct file *file, const char __user *buf,
+	    size_t count, loff_t *f_pos)
+{
+	unsigned long flags;
+	int status;
+	struct subch_data_s *sd = (struct subch_data_s *) file->private_data;
+
+	/* try to get control of the write buffer */
+	if (down_trylock(&sd->sd_wbs)) {
+		/* somebody else has it now;
+		 * if we're non-blocking, then exit...
+		 */
+		if (file->f_flags & O_NONBLOCK) {
+			return -EAGAIN;
+		}
+		/* ...or if we want to block, then do so here */
+		if (down_interruptible(&sd->sd_wbs)) {
+			/* something went wrong with wait */
+			return -ERESTARTSYS;
+		}
+	}
+
+	count = min((int) count, CHUNKSIZE);
+	if (copy_from_user(sd->sd_wb, buf, count)) {
+		up(&sd->sd_wbs);
+		return -EFAULT;
+	}
+
+	/* try to send the buffer */
+	spin_lock_irqsave(&sd->sd_wlock, flags);
+	status = write_status_check(sd, count);
+
+	/* if we failed, and we want to block, then loop */
+	while (status <= 0) {
+		DECLARE_WAITQUEUE(wait, current);
+
+		if (file->f_flags & O_NONBLOCK) {
+			spin_unlock(&sd->sd_wlock);
+			up(&sd->sd_wbs);
+			return -EAGAIN;
+		}
+
+		add_wait_queue(&sd->sd_wq, &wait);
+		set_current_state(TASK_INTERRUPTIBLE);
+		spin_unlock_irqrestore(&sd->sd_wlock, flags);
+
+		schedule_timeout(SCDRV_TIMEOUT);
+
+		remove_wait_queue(&sd->sd_wq, &wait);
+		if (signal_pending(current)) {
+			/* wait was interrupted */
+			up(&sd->sd_wbs);
+			return -ERESTARTSYS;
+		}
+
+		spin_lock_irqsave(&sd->sd_wlock, flags);
+		status = write_status_check(sd, count);
+	}
+	spin_unlock_irqrestore(&sd->sd_wlock, flags);
+
+	/* release the write buffer and wake anyone who's waiting for it */
+	up(&sd->sd_wbs);
+
+	/* return the number of characters accepted (should be the complete
+	 * "chunk" as requested)
+	 */
+	if ((status >= 0) && (status < count)) {
+		pr_debug("Didn't accept the full chunk; %d of %d\n",
+			 status, (int) count);
+	}
+	return status;
+}
+
+static unsigned int
+scdrv_poll(struct file *file, struct poll_table_struct *wait)
+{
+	unsigned int mask = 0;
+	int status = 0;
+	struct subch_data_s *sd = (struct subch_data_s *) file->private_data;
+	unsigned long flags;
+
+	poll_wait(file, &sd->sd_rq, wait);
+	poll_wait(file, &sd->sd_wq, wait);
+
+	spin_lock_irqsave(&sd->sd_rlock, flags);
+	spin_lock(&sd->sd_wlock);
+	status = ia64_sn_irtr_intr(sd->sd_nasid, sd->sd_subch);
+	spin_unlock(&sd->sd_wlock);
+	spin_unlock_irqrestore(&sd->sd_rlock, flags);
+
+	if (status > 0) {
+		if (status & SAL_IROUTER_INTR_RECV) {
+			mask |= POLLIN | POLLRDNORM;
+		}
+		if (status & SAL_IROUTER_INTR_XMIT) {
+			mask |= POLLOUT | POLLWRNORM;
+		}
+	}
+
+	return mask;
+}
+
+static struct file_operations scdrv_fops = {
+	.owner =	THIS_MODULE,
+	.read =		scdrv_read,
+	.write =	scdrv_write,
+	.poll =		scdrv_poll,
+	.open =		scdrv_open,
+	.release =	scdrv_release,
+};
+
+/*
+ * scdrv_init
+ *
+ * Called at boot time to initialize the system controller communication
+ * facility.
+ */
+int __init
+scdrv_init(void)
+{
+	geoid_t geoid;
+	cmoduleid_t cmod;
+	int i;
+	char devname[32];
+	char *devnamep;
+	module_t *m;
+	struct sysctl_data_s *scd;
+	void *salbuf;
+	struct class_simple *snsc_class;
+	dev_t first_dev, dev;
+
+	if (alloc_chrdev_region(&first_dev, 0, (MAX_SLABS*nummodules),
+				SYSCTL_BASENAME) < 0) {
+		printk("%s: failed to register SN system controller device\n",
+		       __FUNCTION__);
+		return -ENODEV;
+	}
+	snsc_class = class_simple_create(THIS_MODULE, SYSCTL_BASENAME);
+
+	for (cmod = 0; cmod < nummodules; cmod++) {
+		m = sn_modules[cmod];
+		for (i = 0; i <= MAX_SLABS; i++) {
+
+			if (m->nodes[i] == -1) {
+				/* node is not alive in module */
+				continue;
+			}
+
+			geoid = m->geoid[i];
+			devnamep = devname;
+			format_module_id(devnamep, geo_module(geoid),
+					 MODULE_FORMAT_BRIEF);
+			devnamep = devname + strlen(devname);
+			sprintf(devnamep, "#%d", geo_slab(geoid));
+
+			/* allocate sysctl device data */
+			scd = kmalloc(sizeof (struct sysctl_data_s),
+				      GFP_KERNEL);
+			if (!scd) {
+				printk("%s: failed to allocate device info"
+				       "for %s/%s\n", __FUNCTION__,
+				       SYSCTL_BASENAME, devname);
+				continue;
+			}
+			memset(scd, 0, sizeof (struct sysctl_data_s));
+
+			/* initialize sysctl device data fields */
+			scd->scd_nasid = cnodeid_to_nasid(m->nodes[i]);
+			if (!(salbuf = kmalloc(SCDRV_BUFSZ, GFP_KERNEL))) {
+				printk("%s: failed to allocate driver buffer"
+				       "(%s%s)\n", __FUNCTION__,
+				       SYSCTL_BASENAME, devname);
+				kfree(scd);
+				continue;
+			}
+
+			if (ia64_sn_irtr_init(scd->scd_nasid, salbuf,
+					      SCDRV_BUFSZ) < 0) {
+				printk
+				    ("%s: failed to initialize SAL for"
+				     " system controller communication"
+				     " (%s/%s): outdated PROM?\n",
+				     __FUNCTION__, SYSCTL_BASENAME, devname);
+				kfree(scd);
+				kfree(salbuf);
+				continue;
+			}
+
+			dev = first_dev + m->nodes[i];
+			cdev_init(&scd->scd_cdev, &scdrv_fops);
+			if (cdev_add(&scd->scd_cdev, dev, 1)) {
+				printk("%s: failed to register system"
+				       " controller device (%s%s)\n",
+				       __FUNCTION__, SYSCTL_BASENAME, devname);
+				kfree(scd);
+				kfree(salbuf);
+				continue;
+			}
+
+			class_simple_device_add(snsc_class, dev, NULL,
+						"%s", devname);
+
+			ia64_sn_irtr_intr_enable(scd->scd_nasid,
+						 0 /*ignored */ ,
+						 SAL_IROUTER_INTR_RECV);
+		}
+	}
+	return 0;
+}
+
+module_init(scdrv_init);
diff -Nru a/drivers/char/snsc.h b/drivers/char/snsc.h
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/drivers/char/snsc.h	2004-10-18 14:57:23 -07:00
@@ -0,0 +1,50 @@
+/*
+ * SN Platform system controller communication support
+ *
+ * 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) 2004 Silicon Graphics, Inc. All rights reserved.
+ */
+
+/*
+ * This file contains macros and data types for communication with the
+ * system controllers in SGI SN systems.
+ */
+
+#ifndef _SN_SYSCTL_H_
+#define _SN_SYSCTL_H_
+
+#include <linux/types.h>
+#include <linux/spinlock.h>
+#include <linux/wait.h>
+#include <linux/kobject.h>
+#include <linux/fs.h>
+#include <linux/cdev.h>
+#include <asm/sn/types.h>
+#include <asm/semaphore.h>
+
+#define CHUNKSIZE 127
+
+/* This structure is used to track an open subchannel. */
+struct subch_data_s {
+	nasid_t sd_nasid;	/* node on which the subchannel was opened */
+	int sd_subch;		/* subchannel number */
+	spinlock_t sd_rlock;	/* monitor lock for rsv */
+	spinlock_t sd_wlock;	/* monitor lock for wsv */
+	wait_queue_head_t sd_rq;	/* wait queue for readers */
+	wait_queue_head_t sd_wq;	/* wait queue for writers */
+	struct semaphore sd_rbs;	/* semaphore for read buffer */
+	struct semaphore sd_wbs;	/* semaphore for write buffer */
+
+	char sd_rb[CHUNKSIZE];	/* read buffer */
+	char sd_wb[CHUNKSIZE];	/* write buffer */
+};
+
+struct sysctl_data_s {
+	struct cdev scd_cdev;	/* Character device info */
+	nasid_t scd_nasid;	/* Node on which subchannels are opened. */
+};
+
+#endif /* _SN_SYSCTL_H_ */
diff -Nru a/drivers/char/sonypi.c b/drivers/char/sonypi.c
--- a/drivers/char/sonypi.c	2004-10-18 14:56:48 -07:00
+++ b/drivers/char/sonypi.c	2004-10-18 14:56:48 -07:00
@@ -50,12 +50,13 @@
 #include <asm/io.h>
 #include <asm/system.h>
 
+static int verbose; /* = 0 */
+
 #include "sonypi.h"
 #include <linux/sonypi.h>
 
 static struct sonypi_device sonypi_device;
 static int minor = -1;
-static int verbose; /* = 0 */
 static int fnkeyinit; /* = 0 */
 static int camera; /* = 0 */
 static int compat; /* = 0 */
@@ -66,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/sonypi.h b/drivers/char/sonypi.h
--- a/drivers/char/sonypi.h	2004-10-18 14:56:33 -07:00
+++ b/drivers/char/sonypi.h	2004-10-18 14:56:33 -07:00
@@ -401,8 +401,6 @@
 #define SONYPI_ACPI_ACTIVE 0
 #endif /* CONFIG_ACPI */
 
-extern int verbose;
-
 static inline int sonypi_ec_write(u8 addr, u8 value) {
 #ifdef CONFIG_ACPI_EC
 	if (SONYPI_ACPI_ACTIVE)
diff -Nru a/drivers/char/specialix.c b/drivers/char/specialix.c
--- a/drivers/char/specialix.c	2004-10-18 14:57:03 -07:00
+++ b/drivers/char/specialix.c	2004-10-18 14:57:03 -07:00
@@ -135,10 +135,6 @@
 	 ASYNC_SPD_HI       | ASYNC_SPEED_VHI    | ASYNC_SESSION_LOCKOUT | \
 	 ASYNC_PGRP_LOCKOUT | ASYNC_CALLOUT_NOHUP)
 
-#ifndef MIN
-#define MIN(a,b) ((a) < (b) ? (a) : (b))
-#endif
-
 #undef RS_EVENT_WRITE_WAKEUP
 #define RS_EVENT_WRITE_WAKEUP	0
 
@@ -159,7 +155,7 @@
 };
 
 static struct specialix_port sx_port[SX_NBOARD * SX_NPORT];
-		
+
 
 #ifdef SPECIALIX_TIMER
 static struct timer_list missed_irq_timer;
@@ -715,7 +711,7 @@
 				sx_out(bp, CD186x_TDR, CD186x_C_SBRK);
 				port->COR2 &= ~COR2_ETC;
 			}
-			count = MIN(port->break_length, 0xff);
+			count = min_t(int, port->break_length, 0xff);
 			sx_out(bp, CD186x_TDR, CD186x_C_ESC);
 			sx_out(bp, CD186x_TDR, CD186x_C_DELAY);
 			sx_out(bp, CD186x_TDR, count);
@@ -1468,8 +1464,7 @@
 	sx_shutdown_port(bp, port);
 	if (tty->driver->flush_buffer)
 		tty->driver->flush_buffer(tty);
-	if (tty->ldisc.flush_buffer)
-		tty->ldisc.flush_buffer(tty);
+	tty_ldisc_flush(tty);
 	tty->closing = 0;
 	port->event = 0;
 	port->tty = NULL;
@@ -1506,7 +1501,7 @@
 	if (from_user) {
 		down(&tmp_buf_sem);
 		while (1) {
-			c = MIN(count, MIN(SERIAL_XMIT_SIZE - port->xmit_cnt - 1,
+			c = min_t(int, count, min(SERIAL_XMIT_SIZE - port->xmit_cnt - 1,
 					   SERIAL_XMIT_SIZE - port->xmit_head));
 			if (c <= 0)
 				break;
@@ -1519,7 +1514,7 @@
 			}
 
 			cli();
-			c = MIN(c, MIN(SERIAL_XMIT_SIZE - port->xmit_cnt - 1,
+			c = min_t(int, c, min(SERIAL_XMIT_SIZE - port->xmit_cnt - 1,
 				       SERIAL_XMIT_SIZE - port->xmit_head));
 			memcpy(port->xmit_buf + port->xmit_head, tmp_buf, c);
 			port->xmit_head = (port->xmit_head + c) & (SERIAL_XMIT_SIZE-1);
@@ -1534,7 +1529,7 @@
 	} else {
 		while (1) {
 			cli();
-			c = MIN(count, MIN(SERIAL_XMIT_SIZE - port->xmit_cnt - 1,
+			c = min_t(int, count, min(SERIAL_XMIT_SIZE - port->xmit_cnt - 1,
 					   SERIAL_XMIT_SIZE - port->xmit_head));
 			if (c <= 0) {
 				restore_flags(flags);
@@ -1646,10 +1641,8 @@
 	port->xmit_cnt = port->xmit_head = port->xmit_tail = 0;
 	restore_flags(flags);
 	
+	tty_wakeup(tty);
 	wake_up_interruptible(&tty->write_wait);
-	if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
-	    tty->ldisc.write_wakeup)
-		(tty->ldisc.write_wakeup)(tty);
 }
 
 
@@ -2052,12 +2045,8 @@
 	if(!(tty = port->tty)) 
 		return;
 
-	if (test_and_clear_bit(RS_EVENT_WRITE_WAKEUP, &port->event)) {
-		if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
-		    tty->ldisc.write_wakeup)
-			(tty->ldisc.write_wakeup)(tty);
-		wake_up_interruptible(&tty->write_wait);
-	}
+	if (test_and_clear_bit(RS_EVENT_WRITE_WAKEUP, &port->event))
+		tty_wakeup(tty);
 }
 
 static struct tty_operations sx_ops = {
diff -Nru a/drivers/char/stallion.c b/drivers/char/stallion.c
--- a/drivers/char/stallion.c	2004-10-18 14:56:49 -07:00
+++ b/drivers/char/stallion.c	2004-10-18 14:56:49 -07:00
@@ -1197,8 +1197,7 @@
 		portp->tx.tail = (char *) NULL;
 	}
 	set_bit(TTY_IO_ERROR, &tty->flags);
-	if (tty->ldisc.flush_buffer)
-		(tty->ldisc.flush_buffer)(tty);
+	tty_ldisc_flush(tty);
 
 	tty->closing = 0;
 	portp->tty = (struct tty_struct *) NULL;
@@ -1809,10 +1808,7 @@
 		return;
 
 	stl_flush(portp);
-	wake_up_interruptible(&tty->write_wait);
-	if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
-	    tty->ldisc.write_wakeup)
-		(tty->ldisc.write_wakeup)(tty);
+	tty_wakeup(tty);
 }
 
 /*****************************************************************************/
@@ -2193,10 +2189,7 @@
 
 	lock_kernel();
 	if (test_bit(ASYI_TXLOW, &portp->istate)) {
-		if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
-		    tty->ldisc.write_wakeup)
-			(tty->ldisc.write_wakeup)(tty);
-		wake_up_interruptible(&tty->write_wait);
+		tty_wakeup(tty);
 	}
 	if (test_bit(ASYI_DCDCHANGE, &portp->istate)) {
 		clear_bit(ASYI_DCDCHANGE, &portp->istate);
diff -Nru a/drivers/char/sx.c b/drivers/char/sx.c
--- a/drivers/char/sx.c	2004-10-18 14:56:29 -07:00
+++ b/drivers/char/sx.c	2004-10-18 14:56:29 -07:00
@@ -1046,12 +1046,9 @@
 	}
 
 	if ((port->gs.xmit_cnt <= port->gs.wakeup_chars) && port->gs.tty) {
-		if ((port->gs.tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
-		    port->gs.tty->ldisc.write_wakeup)
-			(port->gs.tty->ldisc.write_wakeup)(port->gs.tty);
+		tty_wakeup(port->gs.tty);
 		sx_dprintk (SX_DEBUG_TRANSMIT, "Waking up.... ldisc (%d)....\n",
 		            port->gs.wakeup_chars); 
-		wake_up_interruptible(&port->gs.tty->write_wait);
 	}
 
 	clear_bit (SX_PORT_TRANSMIT_LOCK, &port->locks);
diff -Nru a/drivers/char/synclink.c b/drivers/char/synclink.c
--- a/drivers/char/synclink.c	2004-10-18 14:56:28 -07:00
+++ b/drivers/char/synclink.c	2004-10-18 14:56:28 -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
 
 /*
@@ -863,8 +851,6 @@
 static int mgsl_wait_event(struct mgsl_struct * info, int __user *mask);
 static int mgsl_loopmode_send_done( struct mgsl_struct * info );
 
-#define jiffies_from_ms(a) ((((a) * HZ)/1000)+1)
-
 /* set non-zero on successful registration with PCI subsystem */
 static int pci_registered;
 
@@ -911,7 +897,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);
@@ -942,10 +928,6 @@
 static void mgsl_change_params(struct mgsl_struct *info);
 static void mgsl_wait_until_sent(struct tty_struct *tty, int timeout);
 
-#ifndef MIN
-#define MIN(a,b)	((a) < (b) ? (a) : (b))
-#endif
-
 /*
  * 1st function defined in .text section. Calling this function in
  * init_module() followed by a breakpoint allows a remote debugger
@@ -993,6 +975,29 @@
 	return 0;
 }
 
+/**
+ * line discipline callback wrappers
+ *
+ * The wrappers maintain line discipline references
+ * while calling into the line discipline.
+ *
+ * ldisc_receive_buf  - pass receive data to line discipline
+ */
+
+static void ldisc_receive_buf(struct tty_struct *tty,
+			      const __u8 *data, char *flags, int count)
+{
+	struct tty_ldisc *ld;
+	if (!tty)
+		return;
+	ld = tty_ldisc_ref(tty);
+	if (ld) {
+		if (ld->receive_buf)
+			ld->receive_buf(tty, data, flags, count);
+		tty_ldisc_deref(ld);
+	}
+}
+
 /* mgsl_stop()		throttle (stop) transmitter
  * 	
  * Arguments:		tty	pointer to tty info structure
@@ -1153,13 +1158,7 @@
 			__FILE__,__LINE__,info->device_name);
 
 	if (tty) {
-		if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
-		    tty->ldisc.write_wakeup) {
-			if ( debug_level >= DEBUG_LEVEL_BH )
-				printk( "%s(%d):calling ldisc.write_wakeup on %s\n",
-					__FILE__,__LINE__,info->device_name);
-			(tty->ldisc.write_wakeup)(tty);
-		}
+		tty_wakeup(tty);
 		wake_up_interruptible(&tty->write_wait);
 	}
 
@@ -1289,9 +1288,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 +1351,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)
 		{
@@ -2258,8 +2257,8 @@
 		if (from_user) {
 			down(&tmp_buf_sem);
 			while (1) {
-				c = MIN(count,
-					MIN(SERIAL_XMIT_SIZE - info->xmit_cnt - 1,
+				c = min_t(int, count,
+					min(SERIAL_XMIT_SIZE - info->xmit_cnt - 1,
 					    SERIAL_XMIT_SIZE - info->xmit_head));
 				if (c <= 0)
 					break;
@@ -2272,7 +2271,7 @@
 					break;
 				}
 				spin_lock_irqsave(&info->irq_spinlock,flags);
-				c = MIN(c, MIN(SERIAL_XMIT_SIZE - info->xmit_cnt - 1,
+				c = min_t(int, c, min(SERIAL_XMIT_SIZE - info->xmit_cnt - 1,
 					       SERIAL_XMIT_SIZE - info->xmit_head));
 				memcpy(info->xmit_buf + info->xmit_head, tmp_buf, c);
 				info->xmit_head = ((info->xmit_head + c) &
@@ -2287,8 +2286,8 @@
 		} else {
 			while (1) {
 				spin_lock_irqsave(&info->irq_spinlock,flags);
-				c = MIN(count,
-					MIN(SERIAL_XMIT_SIZE - info->xmit_cnt - 1,
+				c = min_t(int, count,
+					min(SERIAL_XMIT_SIZE - info->xmit_cnt - 1,
 					    SERIAL_XMIT_SIZE - info->xmit_head));
 				if (c <= 0) {
 					spin_unlock_irqrestore(&info->irq_spinlock,flags);
@@ -2415,11 +2414,8 @@
 	spin_unlock_irqrestore(&info->irq_spinlock,flags);
 	
 	wake_up_interruptible(&tty->write_wait);
-	if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
-	    tty->ldisc.write_wakeup)
-		(tty->ldisc.write_wakeup)(tty);
-		
-}	/* end of mgsl_flush_buffer() */
+	tty_wakeup(tty);
+}
 
 /* mgsl_send_xchar()
  *
@@ -3253,9 +3249,8 @@
 
 	if (tty->driver->flush_buffer)
 		tty->driver->flush_buffer(tty);
-		
-	if (tty->ldisc.flush_buffer)
-		tty->ldisc.flush_buffer(tty);
+
+	tty_ldisc_flush(tty);
 		
 	shutdown(info);
 	
@@ -3326,7 +3321,7 @@
 		char_time = 1;
 		
 	if (timeout)
-		char_time = MIN(char_time, timeout);
+		char_time = min_t(unsigned long, char_time, timeout);
 		
 	if ( info->params.mode == MGSL_MODE_HDLC ||
 		info->params.mode == MGSL_MODE_RAW ) {
@@ -3592,7 +3587,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--;
 	}
@@ -4187,7 +4182,7 @@
 				info->get_tx_holding_index=0;
 
 			/* restart transmit timer */
-			mod_timer(&info->tx_timer, jiffies + jiffies_from_ms(5000));
+			mod_timer(&info->tx_timer, jiffies + msecs_to_jiffies(5000));
 
 			ret = 1;
 		}
@@ -4415,12 +4410,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 +4568,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;
@@ -5819,7 +5811,7 @@
 			
 			usc_TCmd( info, TCmd_SendFrame );
 			
-			info->tx_timer.expires = jiffies + jiffies_from_ms(5000);
+			info->tx_timer.expires = jiffies + msecs_to_jiffies(5000);
 			add_timer(&info->tx_timer);	
 		}
 		info->tx_active = 1;
@@ -6750,9 +6742,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;
@@ -6779,7 +6774,7 @@
 			
 	if ( debug_level >= DEBUG_LEVEL_DATA )
 		mgsl_trace_block(info,info->rx_buffer_list[StartIndex].virt_addr,
-			MIN(framesize,DMABUFFERSIZE),0);	
+			min_t(int, framesize, DMABUFFERSIZE),0);
 		
 	if (framesize) {
 		if ( ( (info->params.crc_type & HDLC_CRC_RETURN_EX) &&
@@ -6823,18 +6818,12 @@
 						*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
-			{
-				/* Call the line discipline receive callback directly. */
-				if ( tty && tty->ldisc.receive_buf )
-				tty->ldisc.receive_buf(tty, info->intermediate_rxbuffer, info->flag_buf, framesize);
-			}
+				ldisc_receive_buf(tty, info->intermediate_rxbuffer, info->flag_buf, framesize);
 		}
 	}
 	/* Free the buffers used by this frame. */
@@ -6996,7 +6985,7 @@
 
 		if ( debug_level >= DEBUG_LEVEL_DATA )
 			mgsl_trace_block(info,info->rx_buffer_list[CurrentIndex].virt_addr,
-				MIN(framesize,DMABUFFERSIZE),0);
+				min_t(int, framesize, DMABUFFERSIZE),0);
 
 		if (framesize) {
 			/* copy dma buffer(s) to contiguous intermediate buffer */
@@ -7006,9 +6995,7 @@
 			memcpy( info->intermediate_rxbuffer, pBufEntry->virt_addr, framesize);
 			info->icount.rxok++;
 
-			/* Call the line discipline receive callback directly. */
-			if ( tty && tty->ldisc.receive_buf )
-				tty->ldisc.receive_buf(tty, info->intermediate_rxbuffer, info->flag_buf, framesize);
+			ldisc_receive_buf(tty, info->intermediate_rxbuffer, info->flag_buf, framesize);
 		}
 
 		/* Free the buffers used by this frame. */
@@ -7056,7 +7043,7 @@
 	DMABUFFERENTRY *pBufEntry;
 	
 	if ( debug_level >= DEBUG_LEVEL_DATA )
-		mgsl_trace_block(info,Buffer, MIN(BufferSize,DMABUFFERSIZE), 1);	
+		mgsl_trace_block(info,Buffer, min_t(int, BufferSize, DMABUFFERSIZE), 1);
 
 	if (info->params.flags & HDLC_FLAG_HDLC_LOOPMODE) {
 		/* set CMR:13 to start transmit when
@@ -7214,7 +7201,7 @@
 	EndTime=100;
 	while( EndTime-- && !info->irq_occurred ) {
 		set_current_state(TASK_INTERRUPTIBLE);
-		schedule_timeout(jiffies_from_ms(10));
+		schedule_timeout(msecs_to_jiffies(10));
 	}
 	
 	spin_lock_irqsave(&info->irq_spinlock,flags);
@@ -7353,7 +7340,7 @@
 	/*************************************************************/
 
 	/* Wait 100ms for interrupt. */
-	EndTime = jiffies + jiffies_from_ms(100);
+	EndTime = jiffies + msecs_to_jiffies(100);
 
 	for(;;) {
 		if (time_after(jiffies, EndTime)) {
@@ -7409,7 +7396,7 @@
 	/**********************************/
 	
 	/* Wait 100ms */
-	EndTime = jiffies + jiffies_from_ms(100);
+	EndTime = jiffies + msecs_to_jiffies(100);
 
 	for(;;) {
 		if (time_after(jiffies, EndTime)) {
@@ -7451,7 +7438,7 @@
 		/******************************/
 
 		/* Wait 100ms */
-		EndTime = jiffies + jiffies_from_ms(100);
+		EndTime = jiffies + msecs_to_jiffies(100);
 
 		/* While timer not expired wait for transmit complete */
 
@@ -7482,7 +7469,7 @@
 		/* WAIT FOR RECEIVE COMPLETE */
 
 		/* Wait 100ms */
-		EndTime = jiffies + jiffies_from_ms(100);
+		EndTime = jiffies + msecs_to_jiffies(100);
 
 		/* Wait for 16C32 to write receive status to buffer entry. */
 		status=info->rx_buffer_list[0].status;
@@ -7736,9 +7723,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 +7806,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 +7932,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++;
 
-	/* allow syncppp to do close processing */
-	sppp_close(d);
-	netif_stop_queue(d);
+	spin_lock_irqsave(&info->irq_spinlock,flags);
+	usc_stop_transmitter(info);
+	spin_unlock_irqrestore(&info->irq_spinlock,flags);
 
-	spin_lock_irqsave(&info->netlock, flags);
-	info->netcount=0;
-	spin_unlock_irqrestore(&info->netlock, flags);
-	return 0;
+	netif_wake_queue(dev);
 }
 
-void mgsl_sppp_rx_done(struct mgsl_struct *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(struct mgsl_struct *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(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-10-18 14:56:17 -07:00
+++ b/drivers/char/synclinkmp.c	2004-10-18 14:56:17 -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.29 2004/08/27 20:06:41 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
@@ -462,8 +453,6 @@
 #define CRCE	BIT2
 
 
-#define jiffies_from_ms(a) ((((a) * HZ)/1000)+1)
-
 /*
  * Global linked list of SyncLink devices
  */
@@ -498,7 +487,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.29 $";
 
 static int synclinkmp_init_one(struct pci_dev *dev,const struct pci_device_id *ent);
 static void synclinkmp_remove_one(struct pci_dev *dev);
@@ -524,10 +513,6 @@
 /* number of characters left in xmit buffer before we ask for more */
 #define WAKEUP_CHARS 256
 
-#ifndef MIN
-#define MIN(a,b) ((a) < (b) ? (a) : (b))
-#endif
-
 
 /* tty callbacks */
 
@@ -553,20 +538,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 */
@@ -668,7 +645,7 @@
 static unsigned char tx_negate_fifo_level = 32;	// tx request FIFO negation level in bytes
 
 static u32 misc_ctrl_value = 0x007e4040;
-static u32 lcr1_brdr_value = 0x0080002d;
+static u32 lcr1_brdr_value = 0x00800029;
 
 static u32 read_ahead_count = 8;
 
@@ -722,6 +699,29 @@
 	return 0;
 }
 
+/**
+ * line discipline callback wrappers
+ *
+ * The wrappers maintain line discipline references
+ * while calling into the line discipline.
+ *
+ * ldisc_receive_buf  - pass receive data to line discipline
+ */
+
+static void ldisc_receive_buf(struct tty_struct *tty,
+			      const __u8 *data, char *flags, int count)
+{
+	struct tty_ldisc *ld;
+	if (!tty)
+		return;
+	ld = tty_ldisc_ref(tty);
+	if (ld) {
+		if (ld->receive_buf)
+			ld->receive_buf(tty, data, flags, count);
+		tty_ldisc_deref(ld);
+	}
+}
+
 /* tty callbacks */
 
 /* Called when a port is opened.  Init and enable port.
@@ -800,7 +800,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--;
 	}
@@ -869,8 +869,7 @@
 	if (tty->driver->flush_buffer)
 		tty->driver->flush_buffer(tty);
 
-	if (tty->ldisc.flush_buffer)
-		tty->ldisc.flush_buffer(tty);
+	tty_ldisc_flush(tty);
 
 	shutdown(info);
 
@@ -1017,8 +1016,8 @@
 	}
 
 	for (;;) {
-		c = MIN(count,
-			MIN(info->max_frame_size - info->tx_count - 1,
+		c = min_t(int, count,
+			min(info->max_frame_size - info->tx_count - 1,
 			    info->max_frame_size - info->tx_put));
 		if (c <= 0)
 			break;
@@ -1161,7 +1160,7 @@
 		char_time = 1;
 
 	if (timeout)
-		char_time = MIN(char_time, timeout);
+		char_time = min_t(unsigned long, char_time, timeout);
 
 	if ( info->params.mode == MGSL_MODE_HDLC ) {
 		while (info->tx_active) {
@@ -1275,9 +1274,7 @@
 	spin_unlock_irqrestore(&info->lock,flags);
 
 	wake_up_interruptible(&tty->write_wait);
-	if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
-	    tty->ldisc.write_wakeup)
-		(tty->ldisc.write_wakeup)(tty);
+	tty_wakeup(tty);
 }
 
 /* throttle (stop) transmitter
@@ -1627,79 +1624,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 +1750,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.
@@ -1941,13 +2143,7 @@
 			__FILE__,__LINE__,info->device_name);
 
 	if (tty) {
-		if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
-		    tty->ldisc.write_wakeup) {
-			if ( debug_level >= DEBUG_LEVEL_BH )
-				printk( "%s(%d):%s calling ldisc.write_wakeup\n",
-					__FILE__,__LINE__,info->device_name);
-			(tty->ldisc.write_wakeup)(tty);
-		}
+		tty_wakeup(tty);
 		wake_up_interruptible(&tty->write_wait);
 	}
 }
@@ -1994,16 +2190,15 @@
 {
  	struct tty_struct *tty = info->tty;
  	struct	mgsl_icount *icount = &info->icount;
-	unsigned char status = read_reg(info, SR1);
-	unsigned char status2 = read_reg(info, SR2);
+	unsigned char status = read_reg(info, SR1) & info->ie1_value & (FLGD + IDLD + CDCD + BRKD);
+	unsigned char status2 = read_reg(info, SR2) & info->ie2_value & OVRN;
 
 	/* clear status bits */
-	if ( status & (FLGD + IDLD + CDCD + BRKD) )
-		write_reg(info, SR1, 
-				(unsigned char)(status & (FLGD + IDLD + CDCD + BRKD)));
+	if (status)
+		write_reg(info, SR1, status);
 
-	if ( status2 & OVRN )
-		write_reg(info, SR2, (unsigned char)(status2 & OVRN));
+	if (status2)
+		write_reg(info, SR2, status2);
 	
 	if ( debug_level >= DEBUG_LEVEL_ISR )
 		printk("%s(%d):%s isr_rxint status=%02X %02x\n",
@@ -2140,15 +2335,22 @@
 		printk("%s(%d):%s isr_txeom status=%02x\n",
 			__FILE__,__LINE__,info->device_name,status);
 
-	/* disable and clear MSCI interrupts */
-	info->ie1_value &= ~(IDLE + UDRN);
-	write_reg(info, IE1, info->ie1_value);
-	write_reg(info, SR1, (unsigned char)(UDRN + IDLE));
-
 	write_reg(info, TXDMA + DIR, 0x00); /* disable Tx DMA IRQs */
 	write_reg(info, TXDMA + DSR, 0xc0); /* clear IRQs and disable DMA */
 	write_reg(info, TXDMA + DCMD, SWABORT);	/* reset/init DMA channel */
 
+	if (status & UDRN) {
+		write_reg(info, CMD, TXRESET);
+		write_reg(info, CMD, TXENABLE);
+	} else
+		write_reg(info, CMD, TXBUFCLR);
+
+	/* disable and clear tx interrupts */
+	info->ie0_value &= ~TXRDYE;
+	info->ie1_value &= ~(IDLE + UDRN);
+	write_reg16(info, IE0, (unsigned short)((info->ie1_value << 8) + info->ie0_value));
+	write_reg(info, SR1, (unsigned char)(UDRN + IDLE));
+
 	if ( info->tx_active ) {
 		if (info->params.mode != MGSL_MODE_ASYNC) {
 			if (status & UDRN)
@@ -2168,9 +2370,9 @@
 			set_signals(info);
 		}
 
-#ifdef CONFIG_SYNCLINK_SYNCPPP
+#ifdef CONFIG_HDLC
 		if (info->netcount)
-			sppp_tx_done(info);
+			hdlcdev_tx_done(info);
 		else
 #endif
 		{
@@ -2189,10 +2391,10 @@
  */
 void isr_txint(SLMP_INFO * info)
 {
-	unsigned char status = read_reg(info, SR1);
+	unsigned char status = read_reg(info, SR1) & info->ie1_value & (UDRN + IDLE + CCTS);
 
 	/* clear status bits */
-	write_reg(info, SR1, (unsigned char)(status & (UDRN + IDLE + CCTS)));
+	write_reg(info, SR1, status);
 
 	if ( debug_level >= DEBUG_LEVEL_ISR )
 		printk("%s(%d):%s isr_txint status=%02x\n",
@@ -2221,6 +2423,14 @@
 		printk("%s(%d):%s isr_txrdy() tx_count=%d\n",
 			__FILE__,__LINE__,info->device_name,info->tx_count);
 
+	if (info->params.mode != MGSL_MODE_ASYNC) {
+		/* disable TXRDY IRQ, enable IDLE IRQ */
+		info->ie0_value &= ~TXRDYE;
+		info->ie1_value |= IDLE;
+		write_reg16(info, IE0, (unsigned short)((info->ie1_value << 8) + info->ie0_value));
+		return;
+	}
+
 	if (info->tty && (info->tty->stopped || info->tty->hw_stopped)) {
 		tx_stop(info);
 		return;
@@ -2275,13 +2485,6 @@
 
 void isr_txdmaok(SLMP_INFO * info)
 {
-	/* BIT7 = EOT (end of transfer, used for async mode)
-	 * BIT6 = EOM (end of message/frame, used for sync mode)
-	 *
-	 * We don't look at DMA status because only EOT is enabled
-	 * and we always clear and disable all tx DMA IRQs.
-	 */
-//	unsigned char dma_status = read_reg(info,TXDMA + DSR) & 0xc0;
 	unsigned char status_reg1 = read_reg(info, SR1);
 
 	write_reg(info, TXDMA + DIR, 0x00);	/* disable Tx DMA IRQs */
@@ -2292,19 +2495,10 @@
 		printk("%s(%d):%s isr_txdmaok(), status=%02x\n",
 			__FILE__,__LINE__,info->device_name,status_reg1);
 
-	/* If transmitter already idle, do end of frame processing,
-	 * otherwise enable interrupt for tx IDLE.
-	 */
-	if (status_reg1 & IDLE)
-		isr_txeom(info, IDLE);
-	else {
-		/* disable and clear underrun IRQ, enable IDLE interrupt */
-		info->ie1_value |= IDLE;
-		info->ie1_value &= ~UDRN;
-		write_reg(info, IE1, info->ie1_value);
-
-		write_reg(info, SR1, UDRN);
-	}
+	/* program TXRDY as FIFO empty flag, enable TXRDY IRQ */
+	write_reg16(info, TRC0, 0);
+	info->ie0_value |= TXRDYE;
+	write_reg(info, IE0, info->ie0_value);
 }
 
 void isr_txdmaerror(SLMP_INFO * info)
@@ -2358,12 +2552,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)
 		{
@@ -2577,7 +2771,7 @@
 
 	change_params(info);
 
-	info->status_timer.expires = jiffies + jiffies_from_ms(10);
+	info->status_timer.expires = jiffies + msecs_to_jiffies(10);
 	add_timer(&info->status_timer);
 
 	if (info->tty)
@@ -2988,7 +3182,7 @@
 		unsigned char oldval = info->ie1_value;
 		unsigned char newval = oldval +
 			 (mask & MgslEvent_ExitHuntMode ? FLGD:0) +
-			 (mask & MgslEvent_IdleReceived ? IDLE:0);
+			 (mask & MgslEvent_IdleReceived ? IDLD:0);
 		if ( oldval != newval ) {
 			info->ie1_value = newval;
 			write_reg(info, IE1, info->ie1_value);
@@ -3055,7 +3249,7 @@
 		spin_lock_irqsave(&info->lock,flags);
 		if (!waitqueue_active(&info->event_wait_q)) {
 			/* disable enable exit hunt mode/idle rcvd IRQs */
-			info->ie1_value &= ~(FLGD|IDLE);
+			info->ie1_value &= ~(FLGD|IDLD);
 			write_reg(info, IE1, info->ie1_value);
 		}
 		spin_unlock_irqrestore(&info->lock,flags);
@@ -3449,9 +3643,10 @@
 
 int claim_resources(SLMP_INFO *info)
 {
-	if (request_mem_region(info->phys_memory_base,0x40000,"synclinkmp") == NULL) {
+	if (request_mem_region(info->phys_memory_base,SCA_MEM_SIZE,"synclinkmp") == NULL) {
 		printk( "%s(%d):%s mem addr conflict, Addr=%08X\n",
 			__FILE__,__LINE__,info->device_name, info->phys_memory_base);
+		info->init_error = DiagStatus_AddressConflict;
 		goto errout;
 	}
 	else
@@ -3460,22 +3655,25 @@
 	if (request_mem_region(info->phys_lcr_base + info->lcr_offset,128,"synclinkmp") == NULL) {
 		printk( "%s(%d):%s lcr mem addr conflict, Addr=%08X\n",
 			__FILE__,__LINE__,info->device_name, info->phys_lcr_base);
+		info->init_error = DiagStatus_AddressConflict;
 		goto errout;
 	}
 	else
 		info->lcr_mem_requested = 1;
 
-	if (request_mem_region(info->phys_sca_base + info->sca_offset,512,"synclinkmp") == NULL) {
+	if (request_mem_region(info->phys_sca_base + info->sca_offset,SCA_BASE_SIZE,"synclinkmp") == NULL) {
 		printk( "%s(%d):%s sca mem addr conflict, Addr=%08X\n",
 			__FILE__,__LINE__,info->device_name, info->phys_sca_base);
+		info->init_error = DiagStatus_AddressConflict;
 		goto errout;
 	}
 	else
 		info->sca_base_requested = 1;
 
-	if (request_mem_region(info->phys_statctrl_base + info->statctrl_offset,16,"synclinkmp") == NULL) {
+	if (request_mem_region(info->phys_statctrl_base + info->statctrl_offset,SCA_REG_SIZE,"synclinkmp") == NULL) {
 		printk( "%s(%d):%s stat/ctrl mem addr conflict, Addr=%08X\n",
 			__FILE__,__LINE__,info->device_name, info->phys_statctrl_base);
+		info->init_error = DiagStatus_AddressConflict;
 		goto errout;
 	}
 	else
@@ -3485,33 +3683,41 @@
 	if (!info->memory_base) {
 		printk( "%s(%d):%s Cant map shared memory, MemAddr=%08X\n",
 			__FILE__,__LINE__,info->device_name, info->phys_memory_base );
+		info->init_error = DiagStatus_CantAssignPciResources;
 		goto errout;
 	}
 
-	if ( !memory_test(info) ) {
-		printk( "%s(%d):Shared Memory Test failed for device %s MemAddr=%08X\n",
-			__FILE__,__LINE__,info->device_name, info->phys_memory_base );
-		goto errout;
-	}
-
-	info->lcr_base = ioremap(info->phys_lcr_base,PAGE_SIZE) + info->lcr_offset;
+	info->lcr_base = ioremap(info->phys_lcr_base,PAGE_SIZE);
 	if (!info->lcr_base) {
 		printk( "%s(%d):%s Cant map LCR memory, MemAddr=%08X\n",
 			__FILE__,__LINE__,info->device_name, info->phys_lcr_base );
+		info->init_error = DiagStatus_CantAssignPciResources;
 		goto errout;
 	}
+	info->lcr_base += info->lcr_offset;
 
-	info->sca_base = ioremap(info->phys_sca_base,PAGE_SIZE) + info->sca_offset;
+	info->sca_base = ioremap(info->phys_sca_base,PAGE_SIZE);
 	if (!info->sca_base) {
 		printk( "%s(%d):%s Cant map SCA memory, MemAddr=%08X\n",
 			__FILE__,__LINE__,info->device_name, info->phys_sca_base );
+		info->init_error = DiagStatus_CantAssignPciResources;
 		goto errout;
 	}
+	info->sca_base += info->sca_offset;
 
-	info->statctrl_base = ioremap(info->phys_statctrl_base,PAGE_SIZE) + info->statctrl_offset;
+	info->statctrl_base = ioremap(info->phys_statctrl_base,PAGE_SIZE);
 	if (!info->statctrl_base) {
 		printk( "%s(%d):%s Cant map SCA Status/Control memory, MemAddr=%08X\n",
 			__FILE__,__LINE__,info->device_name, info->phys_statctrl_base );
+		info->init_error = DiagStatus_CantAssignPciResources;
+		goto errout;
+	}
+	info->statctrl_base += info->statctrl_offset;
+
+	if ( !memory_test(info) ) {
+		printk( "%s(%d):Shared Memory Test failed for device %s MemAddr=%08X\n",
+			__FILE__,__LINE__,info->device_name, info->phys_memory_base );
+		info->init_error = DiagStatus_MemoryError;
 		goto errout;
 	}
 
@@ -3534,7 +3740,7 @@
 	}
 
 	if ( info->shared_mem_requested ) {
-		release_mem_region(info->phys_memory_base,0x40000);
+		release_mem_region(info->phys_memory_base,SCA_MEM_SIZE);
 		info->shared_mem_requested = 0;
 	}
 	if ( info->lcr_mem_requested ) {
@@ -3542,11 +3748,11 @@
 		info->lcr_mem_requested = 0;
 	}
 	if ( info->sca_base_requested ) {
-		release_mem_region(info->phys_sca_base + info->sca_offset,512);
+		release_mem_region(info->phys_sca_base + info->sca_offset,SCA_BASE_SIZE);
 		info->sca_base_requested = 0;
 	}
 	if ( info->sca_statctrl_requested ) {
-		release_mem_region(info->phys_statctrl_base + info->statctrl_offset,16);
+		release_mem_region(info->phys_statctrl_base + info->statctrl_offset,SCA_REG_SIZE);
 		info->sca_statctrl_requested = 0;
 	}
 
@@ -3616,9 +3822,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
 }
 
@@ -3788,7 +3993,6 @@
 
 static void synclinkmp_cleanup(void)
 {
-	unsigned long flags;
 	int rc;
 	SLMP_INFO *info;
 	SLMP_INFO *tmp;
@@ -3802,34 +4006,24 @@
 		put_tty_driver(serial_driver);
 	}
 
+	/* reset devices */
 	info = synclinkmp_device_list;
 	while(info) {
-#ifdef CONFIG_SYNCLINK_SYNCPPP
-		if (info->dosyncppp)
-			sppp_delete(info);
-#endif
 		reset_port(info);
-		if ( info->port_num == 0 ) {
-			if ( info->irq_requested ) {
-				free_irq(info->irq_level, info);
-				info->irq_requested = 0;
-			}
-		}
 		info = info->next_device;
 	}
 
-	/* port 0 of each adapter originally claimed
-	 * all resources, release those now
-	 */
+	/* release devices */
 	info = synclinkmp_device_list;
 	while(info) {
+#ifdef CONFIG_HDLC
+		hdlcdev_exit(info);
+#endif
 		free_dma_bufs(info);
 		free_tmp_rx_buf(info);
 		if ( info->port_num == 0 ) {
-			spin_lock_irqsave(&info->lock,flags);
-			reset_adapter(info);
-			write_reg(info, LPR, 1);		/* set low power mode */
-			spin_unlock_irqrestore(&info->lock,flags);
+			if (info->sca_base)
+				write_reg(info, LPR, 1); /* set low power mode */
 			release_resources(info);
 		}
 		tmp = info;
@@ -4112,6 +4306,9 @@
 				}
 			}
 
+			write_reg16(info, TRC0,
+				(unsigned short)(((tx_negate_fifo_level-1)<<8) + tx_active_fifo_level));
+
 			write_reg(info, TXDMA + DSR, 0); 		/* disable DMA channel */
 			write_reg(info, TXDMA + DCMD, SWABORT);	/* reset/init DMA channel */
 	
@@ -4123,17 +4320,16 @@
 			write_reg16(info, TXDMA + EDA,
 				info->tx_buf_list_ex[info->last_tx_buf].phys_entry);
 	
-			/* clear IDLE and UDRN status bit */
-			info->ie1_value &= ~(IDLE + UDRN);
-			if (info->params.mode != MGSL_MODE_ASYNC)
-				info->ie1_value |= UDRN;     		/* HDLC, IRQ on underrun */
-			write_reg(info, IE1, info->ie1_value);	/* enable MSCI interrupts */
+			/* enable underrun IRQ */
+			info->ie1_value &= ~IDLE;
+			info->ie1_value |= UDRN;
+			write_reg(info, IE1, info->ie1_value);
 			write_reg(info, SR1, (unsigned char)(IDLE + UDRN));
 	
 			write_reg(info, TXDMA + DIR, 0x40);		/* enable Tx DMA interrupts (EOM) */
 			write_reg(info, TXDMA + DSR, 0xf2);		/* clear Tx DMA IRQs, enable Tx DMA */
 	
-			info->tx_timer.expires = jiffies + jiffies_from_ms(5000);
+			info->tx_timer.expires = jiffies + msecs_to_jiffies(5000);
 			add_timer(&info->tx_timer);
 		}
 		else {
@@ -4823,10 +5019,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
 	}
 
@@ -4836,7 +5034,7 @@
 
 	if ( debug_level >= DEBUG_LEVEL_DATA )
 		trace_block(info,info->rx_buf_list_ex[StartIndex].virt_addr,
-			MIN(framesize,SCABUFSIZE),0);
+			min_t(int, framesize,SCABUFSIZE),0);
 
 	if (framesize) {
 		if (framesize > info->max_frame_size)
@@ -4851,7 +5049,7 @@
 			info->icount.rxok++;
 
 			while(copy_count) {
-				int partial_count = MIN(copy_count,SCABUFSIZE);
+				int partial_count = min(copy_count,SCABUFSIZE);
 				memcpy( ptmp,
 					info->rx_buf_list_ex[index].virt_addr,
 					partial_count );
@@ -4862,22 +5060,13 @@
 					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
-			{
-				if ( tty && tty->ldisc.receive_buf ) {
-					/* Call the line discipline receive callback directly. */
-					tty->ldisc.receive_buf(tty,
-						info->tmp_rx_buf,
-						info->flag_buf,
-						framesize);
-				}
-			}
+				ldisc_receive_buf(tty,info->tmp_rx_buf,
+						  info->flag_buf, framesize);
 		}
 	}
 	/* Free the buffers used by this frame. */
@@ -4910,14 +5099,14 @@
 	SCADESC_EX *desc_ex;
 
 	if ( debug_level >= DEBUG_LEVEL_DATA )
-		trace_block(info,buf, MIN(count,SCABUFSIZE), 1);
+		trace_block(info,buf, min_t(int, count,SCABUFSIZE), 1);
 
 	/* Copy source buffer to one or more DMA buffers, starting with
 	 * the first transmit dma buffer.
 	 */
 	for(i=0;;)
 	{
-		copy_count = MIN(count,SCABUFSIZE);
+		copy_count = min_t(unsigned short,count,SCABUFSIZE);
 
 		desc = &info->tx_buf_list[i];
 		desc_ex = &info->tx_buf_list_ex[i];
@@ -5021,7 +5210,7 @@
 	timeout=100;
 	while( timeout-- && !info->irq_occurred ) {
 		set_current_state(TASK_INTERRUPTIBLE);
-		schedule_timeout(jiffies_from_ms(10));
+		schedule_timeout(msecs_to_jiffies(10));
 	}
 
 	spin_lock_irqsave(&info->lock,flags);
@@ -5172,7 +5361,7 @@
 	/* Set a timeout for waiting for interrupt. */
 	for ( timeout = 100; timeout; --timeout ) {
 		set_current_state(TASK_INTERRUPTIBLE);
-		schedule_timeout(jiffies_from_ms(10));
+		schedule_timeout(msecs_to_jiffies(10));
 
 		if (rx_get_frame(info)) {
 			rc = TRUE;
@@ -5384,9 +5573,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);
@@ -5428,7 +5617,7 @@
 
 	info->status_timer.data = (unsigned long)info;
 	info->status_timer.function = status_timeout;
-	info->status_timer.expires = jiffies + jiffies_from_ms(10);
+	info->status_timer.expires = jiffies + msecs_to_jiffies(10);
 	add_timer(&info->status_timer);
 }
 
diff -Nru a/drivers/char/tty_io.c b/drivers/char/tty_io.c
--- a/drivers/char/tty_io.c	2004-10-18 14:56:33 -07:00
+++ b/drivers/char/tty_io.c	2004-10-18 14:56:33 -07:00
@@ -92,6 +92,7 @@
 #include <linux/smp_lock.h>
 #include <linux/device.h>
 #include <linux/idr.h>
+#include <linux/wait.h>
 
 #include <asm/uaccess.h>
 #include <asm/system.h>
@@ -120,10 +121,14 @@
 
 EXPORT_SYMBOL(tty_std_termios);
 
+/* This list gets poked at by procfs and various bits of boot up code. This
+   could do with some rationalisation such as pulling the tty proc function
+   into this file */
+   
 LIST_HEAD(tty_drivers);			/* linked list of tty drivers */
-struct tty_ldisc ldiscs[NR_LDISCS];	/* line disc dispatch table	*/
 
-/* Semaphore to protect creating and releasing a tty */
+/* Semaphore to protect creating and releasing a tty. This is shared with
+   vt.c for deeply disgusting hack reasons */
 DECLARE_MUTEX(tty_sem);
 
 #ifdef CONFIG_UNIX98_PTYS
@@ -142,6 +147,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);
@@ -223,65 +229,323 @@
 	return 0;
 }
 
+/*
+ *	This is probably overkill for real world processors but
+ *	they are not on hot paths so a little discipline won't do 
+ *	any harm.
+ */
+ 
+static void tty_set_termios_ldisc(struct tty_struct *tty, int num)
+{
+	down(&tty->termios_sem);
+	tty->termios->c_line = num;
+	up(&tty->termios_sem);
+}
+
+/*
+ *	This guards the refcounted line discipline lists. The lock
+ *	must be taken with irqs off because there are hangup path
+ *	callers who will do ldisc lookups and cannot sleep.
+ */
+ 
+static spinlock_t tty_ldisc_lock = SPIN_LOCK_UNLOCKED;
+static DECLARE_WAIT_QUEUE_HEAD(tty_ldisc_wait);
+static struct tty_ldisc tty_ldiscs[NR_LDISCS];	/* line disc dispatch table	*/
+
 int tty_register_ldisc(int disc, struct tty_ldisc *new_ldisc)
 {
+	unsigned long flags;
+	int ret = 0;
+	
 	if (disc < N_TTY || disc >= NR_LDISCS)
 		return -EINVAL;
 	
+	spin_lock_irqsave(&tty_ldisc_lock, flags);
 	if (new_ldisc) {
-		ldiscs[disc] = *new_ldisc;
-		ldiscs[disc].flags |= LDISC_FLAG_DEFINED;
-		ldiscs[disc].num = disc;
-	} else
-		memset(&ldiscs[disc], 0, sizeof(struct tty_ldisc));
+		tty_ldiscs[disc] = *new_ldisc;
+		tty_ldiscs[disc].num = disc;
+		tty_ldiscs[disc].flags |= LDISC_FLAG_DEFINED;
+		tty_ldiscs[disc].refcount = 0;
+	} else {
+		if(tty_ldiscs[disc].refcount)
+			ret = -EBUSY;
+		else
+			tty_ldiscs[disc].flags &= ~LDISC_FLAG_DEFINED;
+	}
+	spin_unlock_irqrestore(&tty_ldisc_lock, flags);
 	
-	return 0;
+	return ret;
 }
 
 EXPORT_SYMBOL(tty_register_ldisc);
 
-/* Set the discipline of a tty line. */
+struct tty_ldisc *tty_ldisc_get(int disc)
+{
+	unsigned long flags;
+	struct tty_ldisc *ld;
+
+	if (disc < N_TTY || disc >= NR_LDISCS)
+		return NULL;
+	
+	spin_lock_irqsave(&tty_ldisc_lock, flags);
+
+	ld = &tty_ldiscs[disc];
+	/* Check the entry is defined */
+	if(ld->flags & LDISC_FLAG_DEFINED)
+	{
+		/* If the module is being unloaded we can't use it */
+		if (!try_module_get(ld->owner))
+		       	ld = NULL;
+		else /* lock it */
+			ld->refcount++;
+	}
+	else
+		ld = NULL;
+	spin_unlock_irqrestore(&tty_ldisc_lock, flags);
+	return ld;
+}
+
+EXPORT_SYMBOL_GPL(tty_ldisc_get);
+
+void tty_ldisc_put(int disc)
+{
+	struct tty_ldisc *ld;
+	unsigned long flags;
+	
+	if (disc < N_TTY || disc >= NR_LDISCS)
+		BUG();
+		
+	spin_lock_irqsave(&tty_ldisc_lock, flags);
+	ld = &tty_ldiscs[disc];
+	if(ld->refcount == 0)
+		BUG();
+	ld->refcount --;
+	module_put(ld->owner);
+	spin_unlock_irqrestore(&tty_ldisc_lock, flags);
+}
+	
+EXPORT_SYMBOL_GPL(tty_ldisc_put);
+
+void tty_ldisc_assign(struct tty_struct *tty, struct tty_ldisc *ld)
+{
+	tty->ldisc = *ld;
+	tty->ldisc.refcount = 0;
+}
+
+/**
+ *	tty_ldisc_try		-	internal helper
+ *	@tty: the tty
+ *
+ *	Make a single attempt to grab and bump the refcount on
+ *	the tty ldisc. Return 0 on failure or 1 on success. This is
+ *	used to implement both the waiting and non waiting versions
+ *	of tty_ldisc_ref
+ */
+
+static int tty_ldisc_try(struct tty_struct *tty)
+{
+	unsigned long flags;
+	struct tty_ldisc *ld;
+	int ret = 0;
+	
+	spin_lock_irqsave(&tty_ldisc_lock, flags);
+	ld = &tty->ldisc;
+	if(test_bit(TTY_LDISC, &tty->flags))
+	{
+		ld->refcount++;
+		ret = 1;
+	}
+	spin_unlock_irqrestore(&tty_ldisc_lock, flags);
+	return ret;
+}
+
+/**
+ *	tty_ldisc_ref_wait	-	wait for the tty ldisc
+ *	@tty: tty device
+ *
+ *	Dereference the line discipline for the terminal and take a 
+ *	reference to it. If the line discipline is in flux then 
+ *	wait patiently until it changes.
+ *
+ *	Note: Must not be called from an IRQ/timer context. The caller
+ *	must also be careful not to hold other locks that will deadlock
+ *	against a discipline change, such as an existing ldisc reference
+ *	(which we check for)
+ */
+ 
+struct tty_ldisc *tty_ldisc_ref_wait(struct tty_struct *tty)
+{
+	/* wait_event is a macro */
+	wait_event(tty_ldisc_wait, tty_ldisc_try(tty));
+	if(tty->ldisc.refcount == 0)
+		printk(KERN_ERR "tty_ldisc_ref_wait\n");
+	return &tty->ldisc;
+}
+
+EXPORT_SYMBOL_GPL(tty_ldisc_ref_wait);
+
+/**
+ *	tty_ldisc_ref		-	get the tty ldisc
+ *	@tty: tty device
+ *
+ *	Dereference the line discipline for the terminal and take a 
+ *	reference to it. If the line discipline is in flux then 
+ *	return NULL. Can be called from IRQ and timer functions.
+ */
+ 
+struct tty_ldisc *tty_ldisc_ref(struct tty_struct *tty)
+{
+	if(tty_ldisc_try(tty))
+		return &tty->ldisc;
+	return NULL;
+}
+
+EXPORT_SYMBOL_GPL(tty_ldisc_ref);
+
+/**
+ *	tty_ldisc_deref		-	free a tty ldisc reference
+ *	@ld: reference to free up
+ *
+ *	Undoes the effect of tty_ldisc_ref or tty_ldisc_ref_wait. May
+ *	be called in IRQ context.
+ */
+ 
+void tty_ldisc_deref(struct tty_ldisc *ld)
+{
+	unsigned long flags;
+
+	if(ld == NULL)
+		BUG();
+		
+	spin_lock_irqsave(&tty_ldisc_lock, flags);
+	if(ld->refcount == 0)
+		printk(KERN_ERR "tty_ldisc_deref: no references.\n");
+	else
+		ld->refcount--;
+	if(ld->refcount == 0)
+		wake_up(&tty_ldisc_wait);
+	spin_unlock_irqrestore(&tty_ldisc_lock, flags);
+}
+
+EXPORT_SYMBOL_GPL(tty_ldisc_deref);
+
+/**
+ *	tty_ldisc_enable	-	allow ldisc use
+ *	@tty: terminal to activate ldisc on
+ *
+ *	Set the TTY_LDISC flag when the line discipline can be called
+ *	again. Do neccessary wakeups for existing sleepers.
+ *
+ *	Note: nobody should set this bit except via this function. Clearing
+ *	directly is allowed.
+ */
+
+static void tty_ldisc_enable(struct tty_struct *tty)
+{
+	set_bit(TTY_LDISC, &tty->flags);
+	wake_up(&tty_ldisc_wait);
+}
+	
+/**
+ *	tty_set_ldisc		-	set line discipline
+ *	@tty: the terminal to set
+ *	@ldisc: the line discipline
+ *
+ *	Set the discipline of a tty line. Must be called from a process
+ *	context.
+ */
+ 
 static int tty_set_ldisc(struct tty_struct *tty, int ldisc)
 {
 	int	retval = 0;
 	struct	tty_ldisc o_ldisc;
 	char buf[64];
+	int work;
+	unsigned long flags;
+	struct tty_ldisc *ld;
 
 	if ((ldisc < N_TTY) || (ldisc >= NR_LDISCS))
 		return -EINVAL;
+
+restart:
+
+	if (tty->ldisc.num == ldisc)
+		return 0;	/* We are already in the desired discipline */
+	
+	ld = tty_ldisc_get(ldisc);
 	/* Eduardo Blanco <ejbs@cs.cs.com.uy> */
 	/* Cyrus Durgin <cider@speakeasy.org> */
-	if (!(ldiscs[ldisc].flags & LDISC_FLAG_DEFINED)) {
+	if (ld == NULL) {
 		request_module("tty-ldisc-%d", ldisc);
+		ld = tty_ldisc_get(ldisc);
 	}
-	if (!(ldiscs[ldisc].flags & LDISC_FLAG_DEFINED))
+	if (ld == NULL)
 		return -EINVAL;
 
-	if (tty->ldisc.num == ldisc)
-		return 0;	/* We are already in the desired discipline */
-
-	if (!try_module_get(ldiscs[ldisc].owner))
-	       	return -EINVAL;
-	
 	o_ldisc = tty->ldisc;
 
 	tty_wait_until_sent(tty, 0);
+
+	/*
+	 *	Make sure we don't change while someone holds a
+	 *	reference to the line discipline. The TTY_LDISC bit
+	 *	prevents anyone taking a reference once it is clear.
+	 *	We need the lock to avoid racing reference takers.
+	 */
+	 
+	spin_lock_irqsave(&tty_ldisc_lock, flags);
+	if(tty->ldisc.refcount)
+	{
+		/* Free the new ldisc we grabbed. Must drop the lock
+		   first. */
+		spin_unlock_irqrestore(&tty_ldisc_lock, flags);
+		tty_ldisc_put(ldisc);
+		/*
+		 * There are several reasons we may be busy, including
+		 * random momentary I/O traffic. We must therefore
+		 * retry. We could distinguish between blocking ops
+		 * and retries if we made tty_ldisc_wait() smarter. That
+		 * is up for discussion.
+		 */
+		if(wait_event_interruptible(tty_ldisc_wait, tty->ldisc.refcount == 0) < 0)
+			return -ERESTARTSYS;			
+		goto restart;
+	}
+	clear_bit(TTY_LDISC, &tty->flags);	
+	clear_bit(TTY_DONT_FLIP, &tty->flags);
+	spin_unlock_irqrestore(&tty_ldisc_lock, flags);
 	
+	/*
+	 *	From this point on we know nobody has an ldisc
+	 *	usage reference, nor can they obtain one until
+	 *	we say so later on.
+	 */
+	 
+	work = cancel_delayed_work(&tty->flip.work);
+	/*
+	 * Wait for ->hangup_work and ->flip.work handlers to terminate
+	 */
+	 
+	flush_scheduled_work();
 	/* Shutdown the current discipline. */
 	if (tty->ldisc.close)
 		(tty->ldisc.close)(tty);
 
 	/* Now set up the new line discipline. */
-	tty->ldisc = ldiscs[ldisc];
-	tty->termios->c_line = ldisc;
+	tty_ldisc_assign(tty, ld);
+	tty_set_termios_ldisc(tty, ldisc);
 	if (tty->ldisc.open)
 		retval = (tty->ldisc.open)(tty);
 	if (retval < 0) {
-		tty->ldisc = o_ldisc;
-		tty->termios->c_line = tty->ldisc.num;
+		tty_ldisc_put(ldisc);
+		/* There is an outstanding reference here so this is safe */
+		tty_ldisc_assign(tty, tty_ldisc_get(o_ldisc.num));
+		tty_set_termios_ldisc(tty, tty->ldisc.num);
 		if (tty->ldisc.open && (tty->ldisc.open(tty) < 0)) {
-			tty->ldisc = ldiscs[N_TTY];
-			tty->termios->c_line = N_TTY;
+			tty_ldisc_put(o_ldisc.num);
+			/* This driver is always present */
+			tty_ldisc_assign(tty, tty_ldisc_get(N_TTY));
+			tty_set_termios_ldisc(tty, N_TTY);
 			if (tty->ldisc.open) {
 				int r = tty->ldisc.open(tty);
 
@@ -291,12 +555,27 @@
 					      tty_name(tty, buf), r);
 			}
 		}
-	} else {
-		module_put(o_ldisc.owner);
 	}
+	/* At this point we hold a reference to the new ldisc and a
+	   a reference to the old ldisc. If we ended up flipping back
+	   to the existing ldisc we have two references to it */
 	
 	if (tty->ldisc.num != o_ldisc.num && tty->driver->set_ldisc)
 		tty->driver->set_ldisc(tty);
+		
+	tty_ldisc_put(o_ldisc.num);
+	
+	/*
+	 *	Allow ldisc referencing to occur as soon as the driver
+	 *	ldisc callback completes.
+	 */
+	 
+	tty_ldisc_enable(tty);
+	
+	/* Restart it in case no characters kick it off. Safe if
+	   already running */
+	if(work)
+		schedule_delayed_work(&tty->flip.work, 1);
 	return retval;
 }
 
@@ -377,6 +656,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,
@@ -399,6 +691,53 @@
 
 static spinlock_t redirect_lock = SPIN_LOCK_UNLOCKED;
 static struct file *redirect;
+
+/**
+ *	tty_wakeup	-	request more data
+ *	@tty: terminal
+ *
+ *	Internal and external helper for wakeups of tty. This function
+ *	informs the line discipline if present that the driver is ready
+ *	to receive more output data.
+ */
+ 
+void tty_wakeup(struct tty_struct *tty)
+{
+	struct tty_ldisc *ld;
+	
+	if (test_bit(TTY_DO_WRITE_WAKEUP, &tty->flags)) {
+		ld = tty_ldisc_ref(tty);
+		if(ld) {
+			if(ld->write_wakeup)
+				ld->write_wakeup(tty);
+			tty_ldisc_deref(ld);
+		}
+	}
+	wake_up_interruptible(&tty->write_wait);
+}
+
+EXPORT_SYMBOL_GPL(tty_wakeup);
+
+/**
+ *	tty_ldisc_flush	-	flush line discipline queue
+ *	@tty: tty
+ *
+ *	Flush the line discipline queue (if any) for this tty. If there
+ *	is no line discipline active this is a no-op.
+ */
+ 
+void tty_ldisc_flush(struct tty_struct *tty)
+{
+	struct tty_ldisc *ld = tty_ldisc_ref(tty);
+	if(ld) {
+		if(ld->flush_buffer)
+			ld->flush_buffer(tty);
+		tty_ldisc_deref(ld);
+	}
+}
+
+EXPORT_SYMBOL_GPL(tty_ldisc_flush);
+	
 /*
  * This can be called by the "eventd" kernel thread.  That is process synchronous,
  * but doesn't hold any locks, so we need to make sure we have the appropriate
@@ -410,7 +749,7 @@
 	struct file * cons_filp = NULL;
 	struct file *filp, *f = NULL;
 	struct task_struct *p;
-	struct pid *pid;
+	struct tty_ldisc *ld;
 	int    closecount = 0, n;
 
 	if (!tty)
@@ -428,6 +767,7 @@
 	
 	check_tty_count(tty, "do_tty_hangup");
 	file_list_lock();
+	/* This breaks for file handles being sent over AF_UNIX sockets ? */
 	list_for_each_entry(filp, &tty->tty_files, f_list) {
 		if (filp->f_op->write == redirected_tty_write)
 			cons_filp = filp;
@@ -440,21 +780,25 @@
 	file_list_unlock();
 	
 	/* FIXME! What are the locking issues here? This may me overdoing things..
-	* this question is especially important now that we've removed the irqlock. */
-	{
-		unsigned long flags;
+	 * this question is especially important now that we've removed the irqlock. */
 
-		local_irq_save(flags); // FIXME: is this safe?
-		if (tty->ldisc.flush_buffer)
-			tty->ldisc.flush_buffer(tty);
+	ld = tty_ldisc_ref(tty);
+	if(ld != NULL)	/* We may have no line discipline at this point */
+	{
+		if (ld->flush_buffer)
+			ld->flush_buffer(tty);
 		if (tty->driver->flush_buffer)
 			tty->driver->flush_buffer(tty);
 		if ((test_bit(TTY_DO_WRITE_WAKEUP, &tty->flags)) &&
-		    tty->ldisc.write_wakeup)
-			(tty->ldisc.write_wakeup)(tty);
-		local_irq_restore(flags); // FIXME: is this safe?
+		    ld->write_wakeup)
+			ld->write_wakeup(tty);
+		if (ld->hangup)
+			ld->hangup(tty);
 	}
 
+	/* FIXME: Once we trust the LDISC code better we can wait here for
+	   ldisc completion and fix the driver call race */
+	   
 	wake_up_interruptible(&tty->write_wait);
 	wake_up_interruptible(&tty->read_wait);
 
@@ -463,26 +807,21 @@
 	 * N_TTY.
 	 */
 	if (tty->driver->flags & TTY_DRIVER_RESET_TERMIOS)
+	{
+		down(&tty->termios_sem);
 		*tty->termios = tty->driver->init_termios;
-	if (tty->ldisc.num != ldiscs[N_TTY].num) {
-		if (tty->ldisc.close)
-			(tty->ldisc.close)(tty);
-		module_put(tty->ldisc.owner);
-		
-		tty->ldisc = ldiscs[N_TTY];
-		tty->termios->c_line = N_TTY;
-		if (tty->ldisc.open) {
-			int i = (tty->ldisc.open)(tty);
-			if (i < 0)
-				printk(KERN_ERR "do_tty_hangup: N_TTY open: "
-						"error %d\n", -i);
-		}
+		up(&tty->termios_sem);
 	}
 	
+	/* Defer ldisc switch */
+	/* tty_deferred_ldisc_switch(N_TTY);
+	
+	  This should get done automatically when the port closes and
+	  tty_release is called */
+	
 	read_lock(&tasklist_lock);
 	if (tty->session > 0) {
-		struct list_head *l;
-		for_each_task_pid(tty->session, PIDTYPE_SID, p, l, pid) {
+		do_each_task_pid(tty->session, PIDTYPE_SID, p) {
 			if (p->signal->tty == tty)
 				p->signal->tty = NULL;
 			if (!p->signal->leader)
@@ -491,7 +830,7 @@
 			send_group_sig_info(SIGCONT, SEND_SIG_PRIV, p);
 			if (tty->pgrp > 0)
 				p->signal->tty_old_pgrp = tty->pgrp;
-		}
+		} while_each_task_pid(tty->session, PIDTYPE_SID, p);
 	}
 	read_unlock(&tasklist_lock);
 
@@ -511,6 +850,17 @@
 				tty->driver->close(tty, cons_filp);
 	} else if (tty->driver->hangup)
 		(tty->driver->hangup)(tty);
+		
+	/* We don't want to have driver/ldisc interactions beyond
+	   the ones we did here. The driver layer expects no
+	   calls after ->hangup() from the ldisc side. However we
+	   can't yet guarantee all that */
+
+	set_bit(TTY_HUPPED, &tty->flags);
+	if (ld) {
+		tty_ldisc_enable(tty);
+		tty_ldisc_deref(ld);
+	}
 	unlock_kernel();
 	if (f)
 		fput(f);
@@ -563,8 +913,6 @@
 {
 	struct tty_struct *tty;
 	struct task_struct *p;
-	struct list_head *l;
-	struct pid *pid;
 	int tty_pgrp = -1;
 
 	lock_kernel();
@@ -593,8 +941,9 @@
 	tty->pgrp = -1;
 
 	read_lock(&tasklist_lock);
-	for_each_task_pid(current->signal->session, PIDTYPE_SID, p, l, pid)
+	do_each_task_pid(current->signal->session, PIDTYPE_SID, p) {
 		p->signal->tty = NULL;
+	} while_each_task_pid(current->signal->session, PIDTYPE_SID, p);
 	read_unlock(&tasklist_lock);
 	unlock_kernel();
 }
@@ -627,9 +976,9 @@
 	}
 	if (tty->driver->start)
 		(tty->driver->start)(tty);
-	if ((test_bit(TTY_DO_WRITE_WAKEUP, &tty->flags)) &&
-	    tty->ldisc.write_wakeup)
-		(tty->ldisc.write_wakeup)(tty);
+
+	/* If we have a running line discipline it may need kicking */
+	tty_wakeup(tty);
 	wake_up_interruptible(&tty->write_wait);
 }
 
@@ -641,6 +990,7 @@
 	int i;
 	struct tty_struct * tty;
 	struct inode *inode;
+	struct tty_ldisc *ld;
 
 	tty = (struct tty_struct *)file->private_data;
 	inode = file->f_dentry->d_inode;
@@ -649,11 +999,15 @@
 	if (!tty || (test_bit(TTY_IO_ERROR, &tty->flags)))
 		return -EIO;
 
+	/* We want to wait for the line discipline to sort out in this
+	   situation */
+	ld = tty_ldisc_ref_wait(tty);
 	lock_kernel();
-	if (tty->ldisc.read)
-		i = (tty->ldisc.read)(tty,file,buf,count);
+	if (ld->read)
+		i = (ld->read)(tty,file,buf,count);
 	else
 		i = -EIO;
+	tty_ldisc_deref(ld);
 	unlock_kernel();
 	if (i > 0)
 		inode->i_atime = CURRENT_TIME;
@@ -715,16 +1069,23 @@
 {
 	struct tty_struct * tty;
 	struct inode *inode = file->f_dentry->d_inode;
-
+	ssize_t ret;
+	struct tty_ldisc *ld;
+	
 	tty = (struct tty_struct *)file->private_data;
 	if (tty_paranoia_check(tty, inode, "tty_write"))
 		return -EIO;
 	if (!tty || !tty->driver->write || (test_bit(TTY_IO_ERROR, &tty->flags)))
 		return -EIO;
-	if (!tty->ldisc.write)
-		return -EIO;
-	return do_tty_write(tty->ldisc.write, tty, file,
+
+	ld = tty_ldisc_ref_wait(tty);		
+	if (!ld->write)
+		ret = -EIO;
+	else
+		ret = do_tty_write(ld->write, tty, file,
 			    (const unsigned char __user *)buf, count);
+	tty_ldisc_deref(ld);
+	return ret;
 }
 
 ssize_t redirected_tty_write(struct file * file, const char __user * buf, size_t count,
@@ -749,6 +1110,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);
@@ -910,6 +1282,7 @@
 	 * If we fail here just call release_mem to clean up.  No need
 	 * to decrement the use counts, as release_mem doesn't care.
 	 */
+
 	if (tty->ldisc.open) {
 		retval = (tty->ldisc.open)(tty);
 		if (retval)
@@ -922,7 +1295,9 @@
 				(tty->ldisc.close)(tty);
 			goto release_mem_out;
 		}
+		tty_ldisc_enable(o_tty);
 	}
+	tty_ldisc_enable(tty);
 	goto success;
 
 	/*
@@ -951,6 +1326,9 @@
 	tty->count++;
 	tty->driver = driver; /* N.B. why do this every time?? */
 
+	/* FIXME */
+	if(!test_bit(TTY_LDISC, &tty->flags))
+		printk(KERN_ERR "init_dev but no ldisc\n");
 success:
 	*ret_tty = tty;
 	
@@ -1054,6 +1432,7 @@
 	int	devpts_master, devpts;
 	int	idx;
 	char	buf[64];
+	unsigned long flags;
 	
 	tty = (struct tty_struct *)filp->private_data;
 	if (tty_paranoia_check(tty, filp->f_dentry->d_inode, "release_dev"))
@@ -1130,7 +1509,6 @@
 		}
 	}
 #endif
-
 	if (tty->driver->close)
 		tty->driver->close(tty, filp);
 
@@ -1235,15 +1613,15 @@
 	 */
 	if (tty_closing || o_tty_closing) {
 		struct task_struct *p;
-		struct list_head *l;
-		struct pid *pid;
 
 		read_lock(&tasklist_lock);
-		for_each_task_pid(tty->session, PIDTYPE_SID, p, l, pid)
+		do_each_task_pid(tty->session, PIDTYPE_SID, p) {
 			p->signal->tty = NULL;
+		} while_each_task_pid(tty->session, PIDTYPE_SID, p);
 		if (o_tty)
-			for_each_task_pid(o_tty->session, PIDTYPE_SID, p,l, pid)
+			do_each_task_pid(o_tty->session, PIDTYPE_SID, p) {
 				p->signal->tty = NULL;
+			} while_each_task_pid(o_tty->session, PIDTYPE_SID, p);
 		read_unlock(&tasklist_lock);
 	}
 
@@ -1254,36 +1632,58 @@
 #ifdef TTY_DEBUG_HANGUP
 	printk(KERN_DEBUG "freeing tty structure...");
 #endif
-
 	/*
 	 * Prevent flush_to_ldisc() from rescheduling the work for later.  Then
-	 * kill any delayed work.
+	 * kill any delayed work. As this is the final close it does not
+	 * race with the set_ldisc code path.
 	 */
+	clear_bit(TTY_LDISC, &tty->flags);
 	clear_bit(TTY_DONT_FLIP, &tty->flags);
 	cancel_delayed_work(&tty->flip.work);
 
 	/*
 	 * Wait for ->hangup_work and ->flip.work handlers to terminate
 	 */
+	 
 	flush_scheduled_work();
-
+	
+	/*
+	 * Wait for any short term users (we know they are just driver
+	 * side waiters as the file is closing so user count on the file
+	 * side is zero.
+	 */
+	spin_lock_irqsave(&tty_ldisc_lock, flags);
+	while(tty->ldisc.refcount)
+	{
+		spin_unlock_irqrestore(&tty_ldisc_lock, flags);
+		wait_event(tty_ldisc_wait, tty->ldisc.refcount == 0);
+		spin_lock_irqsave(&tty_ldisc_lock, flags);
+	}
+	spin_unlock_irqrestore(&tty_ldisc_lock, flags);
 	/*
 	 * Shutdown the current line discipline, and reset it to N_TTY.
 	 * N.B. why reset ldisc when we're releasing the memory??
+	 *
+	 * FIXME: this MUST get fixed for the new reflocking
 	 */
 	if (tty->ldisc.close)
 		(tty->ldisc.close)(tty);
-	module_put(tty->ldisc.owner);
+	tty_ldisc_put(tty->ldisc.num);
 	
-	tty->ldisc = ldiscs[N_TTY];
-	tty->termios->c_line = N_TTY;
+	/*
+	 *	Switch the line discipline back
+	 */
+	tty_ldisc_assign(tty, tty_ldisc_get(N_TTY));
+	tty_set_termios_ldisc(tty,N_TTY); 
 	if (o_tty) {
+		/* FIXME: could o_tty be in setldisc here ? */
+		clear_bit(TTY_LDISC, &o_tty->flags);
 		if (o_tty->ldisc.close)
 			(o_tty->ldisc.close)(o_tty);
-		module_put(o_tty->ldisc.owner);
-		o_tty->ldisc = ldiscs[N_TTY];
+		tty_ldisc_put(o_tty->ldisc.num);
+		tty_ldisc_assign(o_tty, tty_ldisc_get(N_TTY));
+		tty_set_termios_ldisc(o_tty,N_TTY); 
 	}
-
 	/*
 	 * The release_mem function takes care of the details of clearing
 	 * the slots and preserving the termios structure.
@@ -1323,6 +1723,7 @@
 	unsigned short saved_flags = filp->f_flags;
 
 	nonseekable_open(inode, filp);
+	
 retry_open:
 	noctty = filp->f_flags & O_NOCTTY;
 	index  = -1;
@@ -1358,53 +1759,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 +1792,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 +1819,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();
@@ -1479,14 +1887,18 @@
 static unsigned int tty_poll(struct file * filp, poll_table * wait)
 {
 	struct tty_struct * tty;
+	struct tty_ldisc *ld;
+	int ret = 0;
 
 	tty = (struct tty_struct *)filp->private_data;
 	if (tty_paranoia_check(tty, filp->f_dentry->d_inode, "tty_poll"))
 		return 0;
-
-	if (tty->ldisc.poll)
-		return (tty->ldisc.poll)(tty, filp, wait);
-	return 0;
+		
+	ld = tty_ldisc_ref_wait(tty);
+	if (ld->poll)
+		ret = (ld->poll)(tty, filp, wait);
+	tty_ldisc_deref(ld);
+	return ret;
 }
 
 static int tty_fasync(int fd, struct file * filp, int on)
@@ -1518,12 +1930,15 @@
 static int tiocsti(struct tty_struct *tty, char __user *p)
 {
 	char ch, mbz = 0;
-
+	struct tty_ldisc *ld;
+	
 	if ((current->signal->tty != tty) && !capable(CAP_SYS_ADMIN))
 		return -EPERM;
 	if (get_user(ch, p))
 		return -EFAULT;
-	tty->ldisc.receive_buf(tty, &ch, &mbz, 1);
+	ld = tty_ldisc_ref_wait(tty);
+	ld->receive_buf(tty, &ch, &mbz, 1);
+	tty_ldisc_deref(ld);
 	return 0;
 }
 
@@ -1606,8 +2021,6 @@
 
 static int tiocsctty(struct tty_struct *tty, int arg)
 {
-	struct list_head *l;
-	struct pid *pid;
 	task_t *p;
 
 	if (current->signal->leader &&
@@ -1630,8 +2043,9 @@
 			 */
 
 			read_lock(&tasklist_lock);
-			for_each_task_pid(tty->session, PIDTYPE_SID, p, l, pid)
+			do_each_task_pid(tty->session, PIDTYPE_SID, p) {
 				p->signal->tty = NULL;
+			} while_each_task_pid(tty->session, PIDTYPE_SID, p);
 			read_unlock(&tasklist_lock);
 		} else
 			return -EPERM;
@@ -1772,6 +2186,7 @@
 	struct tty_struct *tty, *real_tty;
 	void __user *p = (void __user *)arg;
 	int retval;
+	struct tty_ldisc *ld;
 	
 	tty = (struct tty_struct *)file->private_data;
 	if (tty_paranoia_check(tty, inode, "tty_ioctl"))
@@ -1861,6 +2276,7 @@
 		case TIOCGSID:
 			return tiocgsid(tty, real_tty, p);
 		case TIOCGETD:
+			/* FIXME: check this is ok */
 			return put_user(tty->ldisc.num, (int __user *)p);
 		case TIOCSETD:
 			return tiocsetd(tty, p);
@@ -1899,16 +2315,19 @@
 			return tty_tiocmset(tty, file, cmd, p);
 	}
 	if (tty->driver->ioctl) {
-		int retval = (tty->driver->ioctl)(tty, file, cmd, arg);
+		retval = (tty->driver->ioctl)(tty, file, cmd, arg);
 		if (retval != -ENOIOCTLCMD)
 			return retval;
 	}
-	if (tty->ldisc.ioctl) {
-		int retval = (tty->ldisc.ioctl)(tty, file, cmd, arg);
-		if (retval != -ENOIOCTLCMD)
-			return retval;
+	ld = tty_ldisc_ref_wait(tty);
+	retval = -EINVAL;
+	if (ld->ioctl) {
+		retval = ld->ioctl(tty, file, cmd, arg);
+		if (retval == -ENOIOCTLCMD)
+			retval = -EINVAL;
 	}
-	return -EINVAL;
+	tty_ldisc_deref(ld);
+	return retval;
 }
 
 
@@ -1938,21 +2357,26 @@
 #else
 	struct tty_struct *tty = arg;
 	struct task_struct *p;
-	struct list_head *l;
-	struct pid *pid;
 	int session;
 	int		i;
 	struct file	*filp;
+	struct tty_ldisc *disc;
 	
 	if (!tty)
 		return;
 	session  = tty->session;
-	if (tty->ldisc.flush_buffer)
-		tty->ldisc.flush_buffer(tty);
+	
+	/* We don't want an ldisc switch during this */
+	disc = tty_ldisc_ref(tty);
+	if (disc && disc->flush_buffer)
+		disc->flush_buffer(tty);
+	tty_ldisc_deref(disc);
+
 	if (tty->driver->flush_buffer)
 		tty->driver->flush_buffer(tty);
+	
 	read_lock(&tasklist_lock);
-	for_each_task_pid(session, PIDTYPE_SID, p, l, pid) {
+	do_each_task_pid(session, PIDTYPE_SID, p) {
 		if (p->signal->tty == tty || session > 0) {
 			printk(KERN_NOTICE "SAK: killed process %d"
 			    " (%s): p->signal->session==tty->session\n",
@@ -1979,7 +2403,7 @@
 			spin_unlock(&p->files->file_lock);
 		}
 		task_unlock(p);
-	}
+	} while_each_task_pid(session, PIDTYPE_SID, p);
 	read_unlock(&tasklist_lock);
 #endif
 }
@@ -2002,24 +2426,29 @@
 
 /*
  * This routine is called out of the software interrupt to flush data
- * from the flip buffer to the line discipline.
+ * from the flip buffer to the line discipline. 
  */
+ 
 static void flush_to_ldisc(void *private_)
 {
 	struct tty_struct *tty = (struct tty_struct *) private_;
 	unsigned char	*cp;
 	char		*fp;
 	int		count;
-	unsigned long flags;
+	unsigned long 	flags;
+	struct tty_ldisc *disc;
+
+	disc = tty_ldisc_ref(tty);
+	if (disc == NULL)	/*  !TTY_LDISC */
+		return;
 
 	if (test_bit(TTY_DONT_FLIP, &tty->flags)) {
 		/*
 		 * Do it after the next timer tick:
 		 */
 		schedule_delayed_work(&tty->flip.work, 1);
-		return;
+		goto out;
 	}
-
 	spin_lock_irqsave(&tty->read_lock, flags);
 	if (tty->flip.buf_num) {
 		cp = tty->flip.char_buf + TTY_FLIPBUF_SIZE;
@@ -2038,7 +2467,31 @@
 	tty->flip.count = 0;
 	spin_unlock_irqrestore(&tty->read_lock, flags);
 
-	tty->ldisc.receive_buf(tty, cp, fp, count);
+	disc->receive_buf(tty, cp, fp, count);
+out:
+	tty_ldisc_deref(disc);
+}
+
+/*
+ *	Call the ldisc flush directly from a driver. This function may
+ *	return an error and need retrying by the user.
+ */
+
+int tty_push_data(struct tty_struct *tty, unsigned char *cp, unsigned char *fp, int count)
+{
+	int ret = 0;
+	struct tty_ldisc *disc;
+	
+	disc = tty_ldisc_ref(tty);
+	if(test_bit(TTY_DONT_FLIP, &tty->flags))
+		ret = -EAGAIN;
+	else if(disc == NULL)
+		ret = -EIO;
+	else
+		disc->receive_buf(tty, cp, fp, count);
+	tty_ldisc_deref(disc);
+	return ret;
+	
 }
 
 /*
@@ -2060,9 +2513,20 @@
 
 static int n_baud_table = ARRAY_SIZE(baud_table);
 
+/**
+ *	tty_termios_baud_rate
+ *	@termios: termios structure
+ *
+ *	Convert termios baud rate data into a speed. This should be called
+ *	with the termios lock held if this termios is a terminal termios
+ *	structure. May change the termios data.
+ */
+ 
 int tty_termios_baud_rate(struct termios *termios)
 {
-	unsigned int cbaud = termios->c_cflag & CBAUD;
+	unsigned int cbaud;
+	
+	cbaud = termios->c_cflag & CBAUD;
 
 	if (cbaud & CBAUDEX) {
 		cbaud &= ~CBAUDEX;
@@ -2072,12 +2536,20 @@
 		else
 			cbaud += 15;
 	}
-
 	return baud_table[cbaud];
 }
 
 EXPORT_SYMBOL(tty_termios_baud_rate);
 
+/**
+ *	tty_get_baud_rate	-	get tty bit rates
+ *	@tty: tty to query
+ *
+ *	Returns the baud rate as an integer for this terminal. The
+ *	termios lock must be held by the caller and the terminal bit
+ *	flags may be updated.
+ */
+ 
 int tty_get_baud_rate(struct tty_struct *tty)
 {
 	int baud = tty_termios_baud_rate(tty->termios);
@@ -2096,6 +2568,17 @@
 
 EXPORT_SYMBOL(tty_get_baud_rate);
 
+/**
+ *	tty_flip_buffer_push	-	terminal
+ *	@tty: tty to push
+ *
+ *	Queue a push of the terminal flip buffers to the line discipline. This
+ *	function must not be called from IRQ context if tty->low_latency is set.
+ *
+ *	In the event of the queue being busy for flipping the work will be
+ *	held off and retried later.
+ */
+
 void tty_flip_buffer_push(struct tty_struct *tty)
 {
 	if (tty->low_latency)
@@ -2113,12 +2596,13 @@
 {
 	memset(tty, 0, sizeof(struct tty_struct));
 	tty->magic = TTY_MAGIC;
-	tty->ldisc = ldiscs[N_TTY];
+	tty_ldisc_assign(tty, tty_ldisc_get(N_TTY));
 	tty->pgrp = -1;
 	tty->flip.char_buf_ptr = tty->flip.char_buf;
 	tty->flip.flag_buf_ptr = tty->flip.flag_buf;
 	INIT_WORK(&tty->flip.work, flush_to_ldisc, tty);
 	init_MUTEX(&tty->flip.pty_sem);
+	init_MUTEX(&tty->termios_sem);
 	init_waitqueue_head(&tty->write_wait);
 	init_waitqueue_head(&tty->read_wait);
 	INIT_WORK(&tty->hangup_work, do_tty_hangup, tty);
@@ -2154,6 +2638,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 +2650,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 +2924,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/tty_ioctl.c b/drivers/char/tty_ioctl.c
--- a/drivers/char/tty_ioctl.c	2004-10-18 14:57:05 -07:00
+++ b/drivers/char/tty_ioctl.c	2004-10-18 14:57:05 -07:00
@@ -98,8 +98,17 @@
 {
 	int canon_change;
 	struct termios old_termios = *tty->termios;
+	struct tty_ldisc *ld;
+	
+	/*
+	 *	Perform the actual termios internal changes under lock.
+	 */
+	 
+
+	/* FIXME: we need to decide on some locking/ordering semantics
+	   for the set_termios notification eventually */
+	down(&tty->termios_sem);
 
-	local_irq_disable(); // FIXME: is this safe?
 	*tty->termios = *new_termios;
 	unset_locked_termios(tty->termios, &old_termios, tty->termios_locked);
 	canon_change = (old_termios.c_lflag ^ tty->termios->c_lflag) & ICANON;
@@ -109,12 +118,13 @@
 		tty->canon_data = 0;
 		tty->erasing = 0;
 	}
-	local_irq_enable(); // FIXME: is this safe?
+	
+	
 	if (canon_change && !L_ICANON(tty) && tty->read_cnt)
 		/* Get characters left over from canonical mode. */
 		wake_up_interruptible(&tty->read_wait);
 
-	/* see if packet mode change of state */
+	/* See if packet mode change of state. */
 
 	if (tty->link && tty->link->packet) {
 		int old_flow = ((old_termios.c_iflag & IXON) &&
@@ -132,17 +142,23 @@
 			wake_up_interruptible(&tty->link->read_wait);
 		}
 	}
-
+	   
 	if (tty->driver->set_termios)
 		(*tty->driver->set_termios)(tty, &old_termios);
 
-	if (tty->ldisc.set_termios)
-		(*tty->ldisc.set_termios)(tty, &old_termios);
+	ld = tty_ldisc_ref(tty);
+	if (ld != NULL) {
+		if (ld->set_termios)
+			(ld->set_termios)(tty, &old_termios);
+		tty_ldisc_deref(ld);
+	}
+	up(&tty->termios_sem);
 }
 
 static int set_termios(struct tty_struct * tty, void __user *arg, int opt)
 {
 	struct termios tmp_termios;
+	struct tty_ldisc *ld;
 	int retval = tty_check_change(tty);
 
 	if (retval)
@@ -159,9 +175,14 @@
 			return -EFAULT;
 	}
 
-	if ((opt & TERMIOS_FLUSH) && tty->ldisc.flush_buffer)
-		tty->ldisc.flush_buffer(tty);
-
+	ld = tty_ldisc_ref(tty);
+	
+	if (ld != NULL) {
+		if ((opt & TERMIOS_FLUSH) && ld->flush_buffer)
+			ld->flush_buffer(tty);
+		tty_ldisc_deref(ld);
+	}
+	
 	if (opt & TERMIOS_WAIT) {
 		tty_wait_until_sent(tty, 0);
 		if (signal_pending(current))
@@ -226,11 +247,14 @@
 {
 	struct sgttyb tmp;
 
+	down(&tty->termios_sem);
 	tmp.sg_ispeed = 0;
 	tmp.sg_ospeed = 0;
 	tmp.sg_erase = tty->termios->c_cc[VERASE];
 	tmp.sg_kill = tty->termios->c_cc[VKILL];
 	tmp.sg_flags = get_sgflags(tty);
+	up(&tty->termios_sem);
+	
 	return copy_to_user(sgttyb, &tmp, sizeof(tmp)) ? -EFAULT : 0;
 }
 
@@ -269,12 +293,16 @@
 	retval = tty_check_change(tty);
 	if (retval)
 		return retval;
-	termios =  *tty->termios;
+	
 	if (copy_from_user(&tmp, sgttyb, sizeof(tmp)))
 		return -EFAULT;
+
+	down(&tty->termios_sem);		
+	termios =  *tty->termios;
 	termios.c_cc[VERASE] = tmp.sg_erase;
 	termios.c_cc[VKILL] = tmp.sg_kill;
 	set_sgflags(&termios, tmp.sg_flags);
+	up(&tty->termios_sem);
 	change_termios(tty, &termios);
 	return 0;
 }
@@ -365,6 +393,7 @@
 	struct tty_struct * real_tty;
 	void __user *p = (void __user *)arg;
 	int retval;
+	struct tty_ldisc *ld;
 
 	if (tty->driver->type == TTY_DRIVER_TYPE_PTY &&
 	    tty->driver->subtype == PTY_TYPE_MASTER)
@@ -443,22 +472,26 @@
 			retval = tty_check_change(tty);
 			if (retval)
 				return retval;
+				
+			ld = tty_ldisc_ref(tty);
 			switch (arg) {
 			case TCIFLUSH:
-				if (tty->ldisc.flush_buffer)
-					tty->ldisc.flush_buffer(tty);
+				if (ld->flush_buffer)
+					ld->flush_buffer(tty);
 				break;
 			case TCIOFLUSH:
-				if (tty->ldisc.flush_buffer)
-					tty->ldisc.flush_buffer(tty);
+				if (ld->flush_buffer)
+					ld->flush_buffer(tty);
 				/* fall through */
 			case TCOFLUSH:
 				if (tty->driver->flush_buffer)
 					tty->driver->flush_buffer(tty);
 				break;
 			default:
+				tty_ldisc_deref(ld);
 				return -EINVAL;
 			}
+			tty_ldisc_deref(ld);
 			return 0;
 		case TIOCOUTQ:
 			return put_user(tty->driver->chars_in_buffer ?
@@ -504,9 +537,11 @@
 		case TIOCSSOFTCAR:
 			if (get_user(arg, (unsigned int __user *) arg))
 				return -EFAULT;
+			down(&tty->termios_sem);
 			tty->termios->c_cflag =
 				((tty->termios->c_cflag & ~CLOCAL) |
 				 (arg ? CLOCAL : 0));
+			up(&tty->termios_sem);
 			return 0;
 		default:
 			return -ENOIOCTLCMD;
diff -Nru a/drivers/char/viocons.c b/drivers/char/viocons.c
--- a/drivers/char/viocons.c	2004-10-18 14:55:46 -07:00
+++ b/drivers/char/viocons.c	2004-10-18 14:55:46 -07:00
@@ -422,10 +422,7 @@
 			pi->overflowMessage = 0;
 
 		if (pi->tty) {
-			if ((pi->tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
-			    (pi->tty->ldisc.write_wakeup))
-				(pi->tty->ldisc.write_wakeup)(pi->tty);
-			wake_up_interruptible(&pi->tty->write_wait);
+			tty_wakeup(pi->tty);
 		}
 	}
 
diff -Nru a/drivers/char/vme_scc.c b/drivers/char/vme_scc.c
--- a/drivers/char/vme_scc.c	2004-10-18 14:55:54 -07:00
+++ b/drivers/char/vme_scc.c	2004-10-18 14:55:54 -07:00
@@ -544,12 +544,8 @@
 		SCCwrite(COMMAND_REG, CR_TX_PENDING_RESET);   /* disable tx_int on next tx underrun? */
 		port->gs.flags &= ~GS_TX_INTEN;
 	}
-	if (port->gs.tty && port->gs.xmit_cnt <= port->gs.wakeup_chars) {
-		if ((port->gs.tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
-				port->gs.tty->ldisc.write_wakeup)
-			(port->gs.tty->ldisc.write_wakeup)(port->gs.tty);
-		wake_up_interruptible(&port->gs.tty->write_wait);
-	}
+	if (port->gs.tty && port->gs.xmit_cnt <= port->gs.wakeup_chars)
+		tty_wakeup(port->gs.tty);
 
 	SCCwrite_NB(COMMAND_REG, CR_HIGHEST_IUS_RESET);
 	return IRQ_HANDLED;
diff -Nru a/drivers/char/vt.c b/drivers/char/vt.c
--- a/drivers/char/vt.c	2004-10-18 14:56:50 -07:00
+++ b/drivers/char/vt.c	2004-10-18 14:56:50 -07:00
@@ -136,9 +136,6 @@
 #ifdef CONFIG_MDA_CONSOLE
 extern int mda_console_init(void);
 #endif
-#ifdef CONFIG_FRAMEBUFFER_CONSOLE
-extern int fb_console_init(void);
-#endif
 
 struct vc vc_cons [MAX_NR_CONSOLES];
 
@@ -600,6 +597,17 @@
  *	Redrawing of screen
  */
 
+static void clear_buffer_attributes(int currcons)
+{
+	unsigned short *p = (unsigned short *) origin;
+	int count = screenbuf_size/2;
+	int mask = hi_font_mask | 0xff;
+
+	for (; count > 0; count--, p++) {
+		scr_writew((scr_readw(p)&mask) | (video_erase_char&~mask), p);
+	}
+}
+
 void redraw_screen(int new_console, int is_switch)
 {
 	int redraw = 1;
@@ -637,9 +645,21 @@
 
 	if (redraw) {
 		int update;
+		int old_was_color = vc_cons[currcons].d->vc_can_do_color;
+
 		set_origin(currcons);
 		update = sw->con_switch(vc_cons[currcons].d);
 		set_palette(currcons);
+		/*
+		 * If console changed from mono<->color, the best we can do
+		 * is to clear the buffer attributes. As it currently stands,
+		 * rebuilding new attributes from the old buffer is not doable
+		 * without overly complex code.
+		 */
+		if (old_was_color != vc_cons[currcons].d->vc_can_do_color) {
+			update_attr(currcons);
+			clear_buffer_attributes(currcons);
+		}
 		if (update && vcmode != KD_GRAPHICS)
 			do_update_region(currcons, origin, screenbuf_size/2);
 	}
@@ -1865,7 +1885,7 @@
  * since console_init (and thus con_init) are called before any
  * kernel memory allocation is available.
  */
-char con_buf[PAGE_SIZE];
+char con_buf[CON_BUF_SIZE];
 DECLARE_MUTEX(con_buf_sem);
 
 /* acquires console_sem */
@@ -1958,12 +1978,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) {
@@ -2063,7 +2087,7 @@
 			continue;
 		}
 		FLUSH
-		do_con_trol(tty, currcons, c);
+		do_con_trol(tty, currcons, orig);
 	}
 	FLUSH
 	console_conditional_schedule();
@@ -2645,24 +2669,10 @@
 #ifdef CONFIG_MDA_CONSOLE
 	mda_console_init();
 #endif
-#ifdef CONFIG_FRAMEBUFFER_CONSOLE
-	fb_console_init();
-#endif	
 	return 0;
 }
 
 #ifndef VT_SINGLE_DRIVER
-
-static void clear_buffer_attributes(int currcons)
-{
-	unsigned short *p = (unsigned short *) origin;
-	int count = screenbuf_size/2;
-	int mask = hi_font_mask | 0xff;
-
-	for (; count > 0; count--, p++) {
-		scr_writew((scr_readw(p)&mask) | (video_erase_char&~mask), p);
-	}
-}
 
 /*
  *	If we support more console drivers, this function is used
diff -Nru a/drivers/char/vt_ioctl.c b/drivers/char/vt_ioctl.c
--- a/drivers/char/vt_ioctl.c	2004-10-18 14:56:48 -07:00
+++ b/drivers/char/vt_ioctl.c	2004-10-18 14:56:48 -07:00
@@ -536,8 +536,7 @@
 		  default:
 			return -EINVAL;
 		}
-		if (tty->ldisc.flush_buffer)
-			tty->ldisc.flush_buffer(tty);
+		tty_ldisc_flush(tty);
 		return 0;
 
 	case KDGKBMODE:
diff -Nru a/drivers/char/watchdog/Kconfig b/drivers/char/watchdog/Kconfig
--- a/drivers/char/watchdog/Kconfig	2004-10-18 14:56:33 -07:00
+++ b/drivers/char/watchdog/Kconfig	2004-10-18 14:56:33 -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-10-18 14:56:48 -07:00
+++ b/drivers/char/watchdog/Makefile	2004-10-18 14:56:48 -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/cpu5wdt.c b/drivers/char/watchdog/cpu5wdt.c
--- a/drivers/char/watchdog/cpu5wdt.c	2004-10-18 14:56:27 -07:00
+++ b/drivers/char/watchdog/cpu5wdt.c	2004-10-18 14:56:27 -07:00
@@ -134,7 +134,7 @@
 	if ( test_and_set_bit(0, &cpu5wdt_device.inuse) )
 		return -EBUSY;
 
-	return 0;
+	return nonseekable_open(inode, file);
 }
 
 static int cpu5wdt_release(struct inode *inode, struct file *file)
@@ -198,6 +198,7 @@
 
 static struct file_operations cpu5wdt_fops = {
 	.owner		= THIS_MODULE,
+	.llseek		= no_llseek,
 	.ioctl		= cpu5wdt_ioctl,
 	.open		= cpu5wdt_open,
 	.write		= cpu5wdt_write,
diff -Nru a/drivers/char/watchdog/ib700wdt.c b/drivers/char/watchdog/ib700wdt.c
--- a/drivers/char/watchdog/ib700wdt.c	2004-10-18 14:57:03 -07:00
+++ b/drivers/char/watchdog/ib700wdt.c	2004-10-18 14:57:03 -07:00
@@ -263,6 +263,7 @@
 
 static struct file_operations ibwdt_fops = {
 	.owner		= THIS_MODULE,
+	.llseek		= no_llseek,
 	.write		= ibwdt_write,
 	.ioctl		= ibwdt_ioctl,
 	.open		= ibwdt_open,
diff -Nru a/drivers/char/watchdog/indydog.c b/drivers/char/watchdog/indydog.c
--- a/drivers/char/watchdog/indydog.c	2004-10-18 14:57:04 -07:00
+++ b/drivers/char/watchdog/indydog.c	2004-10-18 14:57:04 -07:00
@@ -162,6 +162,7 @@
 
 static struct file_operations indydog_fops = {
 	.owner		= THIS_MODULE,
+	.llseek		= no_llseek,
 	.write		= indydog_write,
 	.ioctl		= indydog_ioctl,
 	.open		= indydog_open,
diff -Nru a/drivers/char/watchdog/ixp4xx_wdt.c b/drivers/char/watchdog/ixp4xx_wdt.c
--- a/drivers/char/watchdog/ixp4xx_wdt.c	2004-10-18 14:56:50 -07:00
+++ b/drivers/char/watchdog/ixp4xx_wdt.c	2004-10-18 14:56:50 -07:00
@@ -170,6 +170,7 @@
 static struct file_operations ixp4xx_wdt_fops =
 {
 	.owner		= THIS_MODULE,
+	.llseek		= no_llseek,
 	.write		= ixp4xx_wdt_write,
 	.ioctl		= ixp4xx_wdt_ioctl,
 	.open		= ixp4xx_wdt_open,
diff -Nru a/drivers/char/watchdog/machzwd.c b/drivers/char/watchdog/machzwd.c
--- a/drivers/char/watchdog/machzwd.c	2004-10-18 14:56:17 -07:00
+++ b/drivers/char/watchdog/machzwd.c	2004-10-18 14:56:17 -07:00
@@ -425,6 +425,7 @@
 
 static struct file_operations zf_fops = {
 	.owner          = THIS_MODULE,
+	.llseek         = no_llseek,
 	.write          = zf_write,
 	.ioctl          = zf_ioctl,
 	.open           = zf_open,
diff -Nru a/drivers/char/watchdog/mixcomwd.c b/drivers/char/watchdog/mixcomwd.c
--- a/drivers/char/watchdog/mixcomwd.c	2004-10-18 14:56:27 -07:00
+++ b/drivers/char/watchdog/mixcomwd.c	2004-10-18 14:56:27 -07:00
@@ -197,6 +197,7 @@
 static struct file_operations mixcomwd_fops=
 {
 	.owner		= THIS_MODULE,
+	.llseek		= no_llseek,
 	.write		= mixcomwd_write,
 	.ioctl		= mixcomwd_ioctl,
 	.open		= mixcomwd_open,
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-10-18 14:57:23 -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/pcwd.c b/drivers/char/watchdog/pcwd.c
--- a/drivers/char/watchdog/pcwd.c	2004-10-18 14:55:54 -07:00
+++ b/drivers/char/watchdog/pcwd.c	2004-10-18 14:55:54 -07:00
@@ -859,8 +859,7 @@
 		/* Not an 'ff' from a floating bus, so must be a card! */
 		for (i = 0; i < 4; ++i) {
 
-			set_current_state(TASK_INTERRUPTIBLE);
-			schedule_timeout(HZ / 2);
+			msleep(500);
 
 			last_port0 = port0;
 			last_port1 = port1;
diff -Nru a/drivers/char/watchdog/sa1100_wdt.c b/drivers/char/watchdog/sa1100_wdt.c
--- a/drivers/char/watchdog/sa1100_wdt.c	2004-10-18 14:56:29 -07:00
+++ b/drivers/char/watchdog/sa1100_wdt.c	2004-10-18 14:56:29 -07:00
@@ -27,6 +27,10 @@
 #include <linux/watchdog.h>
 #include <linux/init.h>
 
+#ifdef CONFIG_ARCH_PXA
+#include <asm/arch/pxa-regs.h>
+#endif
+
 #include <asm/hardware.h>
 #include <asm/bitops.h>
 #include <asm/uaccess.h>
@@ -162,6 +166,7 @@
 static struct file_operations sa1100dog_fops =
 {
 	.owner		= THIS_MODULE,
+	.llseek		= no_llseek,
 	.write		= sa1100dog_write,
 	.ioctl		= sa1100dog_ioctl,
 	.open		= sa1100dog_open,
diff -Nru a/drivers/char/watchdog/sc1200wdt.c b/drivers/char/watchdog/sc1200wdt.c
--- a/drivers/char/watchdog/sc1200wdt.c	2004-10-18 14:56:17 -07:00
+++ b/drivers/char/watchdog/sc1200wdt.c	2004-10-18 14:56:17 -07:00
@@ -301,6 +301,7 @@
 static struct file_operations sc1200wdt_fops =
 {
 	.owner		= THIS_MODULE,
+	.llseek		= no_llseek,
 	.write		= sc1200wdt_write,
 	.ioctl		= sc1200wdt_ioctl,
 	.open		= sc1200wdt_open,
diff -Nru a/drivers/char/watchdog/scx200_wdt.c b/drivers/char/watchdog/scx200_wdt.c
--- a/drivers/char/watchdog/scx200_wdt.c	2004-10-18 14:56:33 -07:00
+++ b/drivers/char/watchdog/scx200_wdt.c	2004-10-18 14:56:33 -07:00
@@ -201,6 +201,7 @@
 
 static struct file_operations scx200_wdt_fops = {
 	.owner	 = THIS_MODULE,
+	.llseek	 = no_llseek,
 	.write   = scx200_wdt_write,
 	.ioctl   = scx200_wdt_ioctl,
 	.open    = scx200_wdt_open,
diff -Nru a/drivers/char/watchdog/wdt285.c b/drivers/char/watchdog/wdt285.c
--- a/drivers/char/watchdog/wdt285.c	2004-10-18 14:56:18 -07:00
+++ b/drivers/char/watchdog/wdt285.c	2004-10-18 14:56:18 -07:00
@@ -180,6 +180,7 @@
 
 static struct file_operations watchdog_fops = {
 	.owner		= THIS_MODULE,
+	.llseek		= no_llseek,
 	.write		= watchdog_write,
 	.ioctl		= watchdog_ioctl,
 	.open		= watchdog_open,
diff -Nru a/drivers/char/watchdog/wdt977.c b/drivers/char/watchdog/wdt977.c
--- a/drivers/char/watchdog/wdt977.c	2004-10-18 14:56:49 -07:00
+++ b/drivers/char/watchdog/wdt977.c	2004-10-18 14:56:49 -07:00
@@ -392,6 +392,7 @@
 static struct file_operations wdt977_fops=
 {
 	.owner		= THIS_MODULE,
+	.llseek		= no_llseek,
 	.write		= wdt977_write,
 	.ioctl		= wdt977_ioctl,
 	.open		= wdt977_open,
diff -Nru a/drivers/char/watchdog/wdt_pci.c b/drivers/char/watchdog/wdt_pci.c
--- a/drivers/char/watchdog/wdt_pci.c	2004-10-18 14:56:33 -07:00
+++ b/drivers/char/watchdog/wdt_pci.c	2004-10-18 14:56:33 -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-10-18 14:57:03 -07:00
+++ b/drivers/cpufreq/Kconfig	2004-10-18 14:57:03 -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	2004-10-18 14:57:05 -07:00
+++ b/drivers/cpufreq/Makefile	2004-10-18 14:57:05 -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.c b/drivers/cpufreq/cpufreq.c
--- a/drivers/cpufreq/cpufreq.c	2004-10-18 14:56:17 -07:00
+++ b/drivers/cpufreq/cpufreq.c	2004-10-18 14:56:17 -07:00
@@ -100,6 +100,85 @@
 }
 
 /*********************************************************************
+ *            EXTERNALLY AFFECTING FREQUENCY CHANGES                 *
+ *********************************************************************/
+
+/**
+ * adjust_jiffies - adjust the system "loops_per_jiffy"
+ *
+ * This function alters the system "loops_per_jiffy" for the clock
+ * speed change. Note that loops_per_jiffy cannot be updated on SMP
+ * systems as each CPU might be scaled differently. So, use the arch 
+ * per-CPU loops_per_jiffy value wherever possible.
+ */
+#ifndef CONFIG_SMP
+static unsigned long l_p_j_ref;
+static unsigned int  l_p_j_ref_freq;
+
+static inline void adjust_jiffies(unsigned long val, struct cpufreq_freqs *ci)
+{
+	if (ci->flags & CPUFREQ_CONST_LOOPS)
+		return;
+
+	if (!l_p_j_ref_freq) {
+		l_p_j_ref = loops_per_jiffy;
+		l_p_j_ref_freq = ci->old;
+	}
+	if ((val == CPUFREQ_PRECHANGE  && ci->old < ci->new) ||
+	    (val == CPUFREQ_POSTCHANGE && ci->old > ci->new) ||
+	    (val == CPUFREQ_RESUMECHANGE))
+		loops_per_jiffy = cpufreq_scale(l_p_j_ref, l_p_j_ref_freq, ci->new);
+}
+#else
+static inline void adjust_jiffies(unsigned long val, struct cpufreq_freqs *ci) { return; }
+#endif
+
+
+/**
+ * cpufreq_notify_transition - call notifier chain and adjust_jiffies on frequency transition
+ *
+ * This function calls the transition notifiers and the "adjust_jiffies" function. It is called
+ * twice on all CPU frequency changes that have external effects. 
+ */
+void cpufreq_notify_transition(struct cpufreq_freqs *freqs, unsigned int state)
+{
+	BUG_ON(irqs_disabled());
+
+	freqs->flags = cpufreq_driver->flags;
+
+	down_read(&cpufreq_notifier_rwsem);
+	switch (state) {
+	case CPUFREQ_PRECHANGE:
+		/* detect if the driver reported a value as "old frequency" which
+		 * is not equal to what the cpufreq core thinks is "old frequency".
+		 */
+		if (!(cpufreq_driver->flags & CPUFREQ_CONST_LOOPS)) {
+			if ((likely(cpufreq_cpu_data[freqs->cpu])) &&
+			    (likely(cpufreq_cpu_data[freqs->cpu]->cur)) &&
+			    (unlikely(freqs->old != cpufreq_cpu_data[freqs->cpu]->cur)))
+			{
+				printk(KERN_WARNING "Warning: CPU frequency is %u, "
+				       "cpufreq assumed %u kHz.\n", freqs->old, cpufreq_cpu_data[freqs->cpu]->cur);
+				freqs->old = cpufreq_cpu_data[freqs->cpu]->cur;
+			}
+		}
+		notifier_call_chain(&cpufreq_transition_notifier_list, CPUFREQ_PRECHANGE, freqs);
+		adjust_jiffies(CPUFREQ_PRECHANGE, freqs);
+		break;
+	case CPUFREQ_POSTCHANGE:
+		adjust_jiffies(CPUFREQ_POSTCHANGE, freqs);
+		notifier_call_chain(&cpufreq_transition_notifier_list, CPUFREQ_POSTCHANGE, freqs);
+		if (likely(cpufreq_cpu_data[freqs->cpu]))
+			cpufreq_cpu_data[freqs->cpu]->cur = freqs->new;
+		break;
+	}
+	up_read(&cpufreq_notifier_rwsem);
+}
+EXPORT_SYMBOL_GPL(cpufreq_notify_transition);
+
+
+
+/*********************************************************************
  *                          SYSFS INTERFACE                          *
  *********************************************************************/
 
@@ -521,9 +600,6 @@
 {
 	struct cpufreq_freqs freqs;
 
-	if (cpufreq_driver->flags & CPUFREQ_PANIC_OUTOFSYNC)
-		panic("CPU Frequency is out of sync.");
-
 	printk(KERN_WARNING "Warning: CPU frequency out of sync: cpufreq and timing "
 	       "core thinks of %u, is %u kHz.\n", old_freq, new_freq);
 
@@ -614,11 +690,8 @@
 		if (unlikely(cur_freq != cpu_policy->cur)) {
 			struct cpufreq_freqs freqs;
 
-			if (cpufreq_driver->flags & CPUFREQ_PANIC_RESUME_OUTOFSYNC)
-				panic("CPU Frequency is out of sync.");
-
-			printk(KERN_WARNING "Warning: CPU frequency out of sync: cpufreq and timing"
-			       "core thinks of %u, is %u kHz.\n", cpu_policy->cur, cur_freq);
+			printk(KERN_WARNING "Warning: CPU frequency is %u, "
+			       "cpufreq assumed %u kHz.\n", cur_freq, cpu_policy->cur);
 
 			freqs.cpu = cpu;
 			freqs.old = cpu_policy->cur;
@@ -626,6 +699,8 @@
 
 			notifier_call_chain(&cpufreq_transition_notifier_list, CPUFREQ_RESUMECHANGE, &freqs);
 			adjust_jiffies(CPUFREQ_RESUMECHANGE, &freqs);
+
+			cpu_policy->cur = cur_freq;
 		}
 	}
 
@@ -1003,87 +1078,6 @@
 	return ret;
 }
 EXPORT_SYMBOL(cpufreq_update_policy);
-
-
-/*********************************************************************
- *            EXTERNALLY AFFECTING FREQUENCY CHANGES                 *
- *********************************************************************/
-
-/**
- * adjust_jiffies - adjust the system "loops_per_jiffy"
- *
- * This function alters the system "loops_per_jiffy" for the clock
- * speed change. Note that loops_per_jiffy cannot be updated on SMP
- * systems as each CPU might be scaled differently. So, use the arch 
- * per-CPU loops_per_jiffy value wherever possible.
- */
-#ifndef CONFIG_SMP
-static unsigned long l_p_j_ref;
-static unsigned int  l_p_j_ref_freq;
-
-static inline void adjust_jiffies(unsigned long val, struct cpufreq_freqs *ci)
-{
-	if (ci->flags & CPUFREQ_CONST_LOOPS)
-		return;
-
-	if (!l_p_j_ref_freq) {
-		l_p_j_ref = loops_per_jiffy;
-		l_p_j_ref_freq = ci->old;
-	}
-	if ((val == CPUFREQ_PRECHANGE  && ci->old < ci->new) ||
-	    (val == CPUFREQ_POSTCHANGE && ci->old > ci->new) ||
-	    (val == CPUFREQ_RESUMECHANGE))
-		loops_per_jiffy = cpufreq_scale(l_p_j_ref, l_p_j_ref_freq, ci->new);
-}
-#else
-static inline void adjust_jiffies(unsigned long val, struct cpufreq_freqs *ci) { return; }
-#endif
-
-
-/**
- * cpufreq_notify_transition - call notifier chain and adjust_jiffies on frequency transition
- *
- * This function calls the transition notifiers and the "adjust_jiffies" function. It is called
- * twice on all CPU frequency changes that have external effects. 
- */
-void cpufreq_notify_transition(struct cpufreq_freqs *freqs, unsigned int state)
-{
-	BUG_ON(irqs_disabled());
-
-	freqs->flags = cpufreq_driver->flags;
-
-	down_read(&cpufreq_notifier_rwsem);
-	switch (state) {
-	case CPUFREQ_PRECHANGE:
-		/* detect if the driver reported a value as "old frequency" which
-		 * is not equal to what the cpufreq core thinks is "old frequency".
-		 */
-		if (!(cpufreq_driver->flags & CPUFREQ_CONST_LOOPS)) {
-			if ((likely(cpufreq_cpu_data[freqs->cpu]->cur)) &&
-			    (unlikely(freqs->old != cpufreq_cpu_data[freqs->cpu]->cur)))
-			{
-				if (cpufreq_driver->flags & CPUFREQ_PANIC_OUTOFSYNC)
-					panic("CPU Frequency is out of sync.");
-
-				printk(KERN_WARNING "Warning: CPU frequency out of sync: "
-				       "cpufreq and timing core thinks of %u, is %u kHz.\n", 
-				       cpufreq_cpu_data[freqs->cpu]->cur, freqs->old);
-				freqs->old = cpufreq_cpu_data[freqs->cpu]->cur;
-			}
-		}
-		notifier_call_chain(&cpufreq_transition_notifier_list, CPUFREQ_PRECHANGE, freqs);
-		adjust_jiffies(CPUFREQ_PRECHANGE, freqs);
-		break;
-	case CPUFREQ_POSTCHANGE:
-		adjust_jiffies(CPUFREQ_POSTCHANGE, freqs);
-		notifier_call_chain(&cpufreq_transition_notifier_list, CPUFREQ_POSTCHANGE, freqs);
-		cpufreq_cpu_data[freqs->cpu]->cur = freqs->new;
-		break;
-	}
-	up_read(&cpufreq_notifier_rwsem);
-}
-EXPORT_SYMBOL_GPL(cpufreq_notify_transition);
-
 
 
 /*********************************************************************
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-10-18 14:57:24 -07:00
@@ -0,0 +1,437 @@
+/*
+ *  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))?1:((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_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(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[] = {
+	&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 total_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 */
+	total_idle_ticks = kstat_cpu(cpu).cpustat.idle +
+		kstat_cpu(cpu).cpustat.iowait;
+	idle_ticks = total_idle_ticks -
+		this_dbs_info->prev_cpu_idle_up;
+	this_dbs_info->prev_cpu_idle_up = total_idle_ticks;
+
+	/* Scale idle ticks by 100 and compare with up and down ticks */
+	idle_ticks *= 100;
+	up_idle_ticks = (100 - dbs_tuners_ins.up_threshold) *
+			sampling_rate_in_HZ(dbs_tuners_ins.sampling_rate);
+
+	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 = total_idle_ticks;
+		return;
+	}
+
+	/* Check for frequency decrease */
+	down_skip[cpu]++;
+	if (down_skip[cpu] < dbs_tuners_ins.sampling_down_factor)
+		return;
+
+	idle_ticks = total_idle_ticks -
+		this_dbs_info->prev_cpu_idle_down;
+	/* Scale idle ticks by 100 and compare with up and down ticks */
+	idle_ticks *= 100;
+	down_skip[cpu] = 0;
+	this_dbs_info->prev_cpu_idle_down = total_idle_ticks;
+
+	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);
+
+	if (idle_ticks > down_idle_ticks ) {
+		freq_down_step = (5 * this_dbs_info->cur_policy->max) / 100;
+
+		/* max freq cannot be less than 100. But who knows.... */
+		if (unlikely(freq_down_step == 0))
+			freq_down_step = 5;
+
+		__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 +
+				kstat_cpu(cpu).cpustat.iowait;
+		this_dbs_info->prev_cpu_idle_down = 
+				kstat_cpu(cpu).cpustat.idle +
+				kstat_cpu(cpu).cpustat.iowait;
+		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) {
+			unsigned int latency;
+			/* policy latency is in nS. Convert it to uS first */
+
+			latency = policy->cpuinfo.transition_latency;
+			if (latency < 1000)
+				latency = 1000;
+
+			def_sampling_rate = (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/cpufreq/cpufreq_userspace.c b/drivers/cpufreq/cpufreq_userspace.c
--- a/drivers/cpufreq/cpufreq_userspace.c	2004-10-18 14:55:55 -07:00
+++ b/drivers/cpufreq/cpufreq_userspace.c	2004-10-18 14:55:55 -07:00
@@ -82,6 +82,13 @@
 {
         struct cpufreq_freqs *freq = data;
 
+	/* Don't update cur_freq if CPU is managed and we're
+	 * waking up: else we won't remember what frequency 
+	 * we need to set the CPU to.
+	 */
+	if (cpu_is_managed[freq->cpu] && (val == CPUFREQ_RESUMECHANGE))
+		return 0;
+
 	cpu_cur_freq[freq->cpu] = freq->new;
 
         return 0;
@@ -147,6 +154,9 @@
 
 #ifdef CONFIG_CPU_FREQ_24_API
 
+#warning The /proc/sys/cpu/ and sysctl interface to cpufreq will be removed from the 2.6. kernel series soon after 2005-01-01
+
+static unsigned int warning_print = 0;
 
 /*********************** cpufreq_sysctl interface ********************/
 static int
@@ -162,6 +172,13 @@
 		return 0;
 	}
 
+	if (!warning_print) {
+		warning_print++;
+		printk(KERN_INFO "Access to /proc/sys/cpu/ is deprecated and "
+			"will be removed from (new) 2.6. kernels soon "
+			"after 2005-01-01\n");
+	}
+
 	if (write) {
 		unsigned int freq;
 
@@ -197,6 +214,13 @@
 	if (!cpu_online(cpu))
 		return -EINVAL;
 
+	if (!warning_print) {
+		warning_print++;
+		printk(KERN_INFO "Access to /proc/sys/cpu/ is deprecated and "
+			"will be removed from (new) 2.6. kernels soon "
+			"after 2005-01-01\n");
+	}
+
 	if (oldval && oldlenp) {
 		size_t oldlen;
 
@@ -521,6 +545,9 @@
 			      CPUFREQ_RELATION_H);
 		else if (policy->min > cpu_cur_freq[cpu])
 			__cpufreq_driver_target(&current_policy[cpu], policy->min, 
+			      CPUFREQ_RELATION_L);
+		else
+			__cpufreq_driver_target(&current_policy[cpu], cpu_cur_freq[cpu],
 			      CPUFREQ_RELATION_L);
 		memcpy (&current_policy[cpu], policy, sizeof(struct cpufreq_policy));
 		up(&userspace_sem);
diff -Nru a/drivers/cpufreq/proc_intf.c b/drivers/cpufreq/proc_intf.c
--- a/drivers/cpufreq/proc_intf.c	2004-10-18 14:56:13 -07:00
+++ b/drivers/cpufreq/proc_intf.c	2004-10-18 14:56:13 -07:00
@@ -12,9 +12,12 @@
 #include <linux/proc_fs.h>
 #include <asm/uaccess.h>
 
+#warning This module will be removed from the 2.6. kernel series soon after 2005-01-01
 
 #define CPUFREQ_ALL_CPUS		((NR_CPUS))
 
+static unsigned int warning_print = 0;
+
 /**
  * cpufreq_parse_policy - parse a policy string
  * @input_string: the string to parse.
@@ -110,6 +113,13 @@
 	if (off != 0)
 		goto end;
 
+	if (!warning_print) {
+		warning_print++;
+		printk(KERN_INFO "Access to /proc/cpufreq is deprecated and "
+			"will be removed from (new) 2.6. kernels soon "
+			"after 2005-01-01\n");
+	}
+
 	p += sprintf(p, "          minimum CPU frequency  -  maximum CPU frequency  -  policy\n");
 	for (i=0;i<NR_CPUS;i++) {
 		if (!cpu_online(i))
@@ -179,6 +189,13 @@
 	
 	if (copy_from_user(proc_string, buffer, count))
 		return -EFAULT;
+
+	if (!warning_print) {
+		warning_print++;
+		printk(KERN_INFO "Access to /proc/cpufreq is deprecated and "
+			"will be removed from (new) 2.6. kernels soon "
+			"after 2005-01-01\n");
+	}
 	
 	proc_string[count] = '\0';
 
diff -Nru a/drivers/fc4/soc.h b/drivers/fc4/soc.h
--- a/drivers/fc4/soc.h	2004-10-18 14:55:46 -07:00
+++ b/drivers/fc4/soc.h	2004-10-18 14:55:46 -07:00
@@ -81,29 +81,29 @@
  * That's why here are the following inline functions...
  */
  
-typedef unsigned long xram_p;
+typedef void __iomem *xram_p;
 
 /* Get 32bit number from XRAM */
-static inline u32 xram_get_32 (xram_p x)
+static inline u32 xram_get_32(xram_p x)
 {
 	return ((sbus_readw(x + 0x00UL) << 16) |
 		(sbus_readw(x + 0x02UL)));
 }
 
 /* Like the above, but when we don't care about the high 16 bits */
-static inline u32 xram_get_32low (xram_p x)
+static inline u32 xram_get_32low(xram_p x)
 {
 	return (u32) sbus_readw(x + 0x02UL);
 }
 
-static inline u16 xram_get_16 (xram_p x)
+static inline u16 xram_get_16(xram_p x)
 {
 	return sbus_readw(x);
 }
 
-static inline u8 xram_get_8 (xram_p x)
+static inline u8 xram_get_8(xram_p x)
 {
-	if (x & (xram_p)0x1) {
+	if ((unsigned long)x & 0x1UL) {
 		x = x - 1;
 		return (u8) sbus_readw(x);
 	} else {
@@ -111,7 +111,7 @@
 	}
 }
 
-static inline void xram_copy_from (void *p, xram_p x, int len)
+static inline void xram_copy_from(void *p, xram_p x, int len)
 {
 	for (len >>= 2; len > 0; len--, x += sizeof(u32)) {
 		u32 val, *p32 = p;
@@ -123,7 +123,7 @@
 	}
 }
 
-static inline void xram_copy_to (xram_p x, void *p, int len)
+static inline void xram_copy_to(xram_p x, void *p, int len)
 {
 	for (len >>= 2; len > 0; len--, x += sizeof(u32)) {
 		u32 tmp, *p32 = p;
@@ -135,7 +135,7 @@
 	}
 }
 
-static inline void xram_bzero (xram_p x, int len)
+static inline void xram_bzero(xram_p x, int len)
 {
 	for (len >>= 1; len > 0; len--, x += sizeof(u16))
 		sbus_writew(0, x);
@@ -274,7 +274,7 @@
 	soc_cq			req[2]; /* Request CQs */
 	soc_cq			rsp[2]; /* Response CQs */
 	int			soc_no;
-	unsigned long		regs;
+	void __iomem		*regs;
 	xram_p			xram;
 	fc_wwn			wwn;
 	u32			imask;	/* Our copy of regs->imask */
diff -Nru a/drivers/fc4/socal.c b/drivers/fc4/socal.c
--- a/drivers/fc4/socal.c	2004-10-18 14:56:29 -07:00
+++ b/drivers/fc4/socal.c	2004-10-18 14:56:29 -07:00
@@ -60,7 +60,7 @@
 #define for_each_socal(s) for (s = socals; s; s = s->next)
 struct socal *socals = NULL;
 
-static void socal_copy_from_xram(void *d, unsigned long xram, long size)
+static void socal_copy_from_xram(void *d, void __iomem *xram, long size)
 {
 	u32 *dp = (u32 *) d;
 	while (size) {
@@ -70,7 +70,7 @@
 	}
 }
 
-static void socal_copy_to_xram(unsigned long xram, void *s, long size)
+static void socal_copy_to_xram(void __iomem *xram, void *s, long size)
 {
 	u32 *sp = (u32 *) s;
 	while (size) {
diff -Nru a/drivers/fc4/socal.h b/drivers/fc4/socal.h
--- a/drivers/fc4/socal.h	2004-10-18 14:56:29 -07:00
+++ b/drivers/fc4/socal.h	2004-10-18 14:56:29 -07:00
@@ -295,9 +295,9 @@
 	socal_cq		req[4]; /* Request CQs */
 	socal_cq		rsp[4]; /* Response CQs */
 	int			socal_no;
-	unsigned long		regs;
-	unsigned long		xram;
-	unsigned long		eeprom;
+	void __iomem		*regs;
+	void __iomem		*xram;
+	void __iomem		*eeprom;
 	fc_wwn			wwn;
 	u32			imask;	/* Our copy of regs->imask */
 	u32			cfg;	/* Our copy of regs->cfg */
diff -Nru a/drivers/firmware/Kconfig b/drivers/firmware/Kconfig
--- a/drivers/firmware/Kconfig	2004-10-18 14:55:46 -07:00
+++ b/drivers/firmware/Kconfig	2004-10-18 14:55:46 -07:00
@@ -14,8 +14,9 @@
 	  Services real mode BIOS calls to determine which disk
 	  BIOS tries boot from.  This information is then exported via sysfs.
 
-	  This option is experimental, but believed to be safe,
-	  and most disk controller BIOS vendors do not yet implement this feature.
+	  This option is experimental and is known to fail to boot on some
+          obscure configurations. Most disk controller BIOS vendors do
+          not yet implement this feature.
 
 config EFI_VARS
 	tristate "EFI Variable Support via sysfs"
diff -Nru a/drivers/i2c/Makefile b/drivers/i2c/Makefile
--- a/drivers/i2c/Makefile	2004-10-18 14:55:54 -07:00
+++ b/drivers/i2c/Makefile	2004-10-18 14:55:54 -07:00
@@ -7,6 +7,9 @@
 obj-$(CONFIG_I2C_SENSOR)	+= i2c-sensor.o
 obj-y				+= busses/ chips/ algos/
 
+i2c-sensor-objs := i2c-sensor-detect.o i2c-sensor-vid.o
+
+
 ifeq ($(CONFIG_I2C_DEBUG_CORE),y)
 EXTRA_CFLAGS += -DDEBUG
 endif
diff -Nru a/drivers/i2c/algos/Kconfig b/drivers/i2c/algos/Kconfig
--- a/drivers/i2c/algos/Kconfig	2004-10-18 14:56:50 -07:00
+++ b/drivers/i2c/algos/Kconfig	2004-10-18 14:56:50 -07:00
@@ -27,6 +27,17 @@
 	  This support is also available as a module.  If so, the module 
 	  will be called i2c-algo-pcf.
 
+config I2C_ALGOPCA
+	tristate "I2C PCA 9564 interfaces"
+	depends on I2C
+	help
+	  This allows you to use a range of I2C adapters called PCA adapters.
+	  Say Y if you own an I2C adapter belonging to this class and then say
+	  Y to the specific driver for you adapter below.
+
+	  This support is also available as a module.  If so, the module 
+	  will be called i2c-algo-pca.
+
 config I2C_ALGOITE
 	tristate "ITE I2C Algorithm"
 	depends on MIPS_ITE8172 && I2C
diff -Nru a/drivers/i2c/algos/Makefile b/drivers/i2c/algos/Makefile
--- a/drivers/i2c/algos/Makefile	2004-10-18 14:56:48 -07:00
+++ b/drivers/i2c/algos/Makefile	2004-10-18 14:56:48 -07:00
@@ -4,6 +4,7 @@
 
 obj-$(CONFIG_I2C_ALGOBIT)	+= i2c-algo-bit.o
 obj-$(CONFIG_I2C_ALGOPCF)	+= i2c-algo-pcf.o
+obj-$(CONFIG_I2C_ALGOPCA)	+= i2c-algo-pca.o
 obj-$(CONFIG_I2C_ALGOITE)	+= i2c-algo-ite.o
 
 ifeq ($(CONFIG_I2C_DEBUG_ALGO),y)
diff -Nru a/drivers/i2c/algos/i2c-algo-bit.c b/drivers/i2c/algos/i2c-algo-bit.c
--- a/drivers/i2c/algos/i2c-algo-bit.c	2004-10-18 14:56:32 -07:00
+++ b/drivers/i2c/algos/i2c-algo-bit.c	2004-10-18 14:56:32 -07:00
@@ -565,8 +565,8 @@
 MODULE_DESCRIPTION("I2C-Bus bit-banging algorithm");
 MODULE_LICENSE("GPL");
 
-MODULE_PARM(bit_test, "i");
-MODULE_PARM(i2c_debug,"i");
+module_param(bit_test, bool, 0);
+module_param(i2c_debug, int, S_IRUGO | S_IWUSR);
 
 MODULE_PARM_DESC(bit_test, "Test the lines of the bus to see if it is stuck");
 MODULE_PARM_DESC(i2c_debug,
diff -Nru a/drivers/i2c/algos/i2c-algo-ite.c b/drivers/i2c/algos/i2c-algo-ite.c
--- a/drivers/i2c/algos/i2c-algo-ite.c	2004-10-18 14:57:03 -07:00
+++ b/drivers/i2c/algos/i2c-algo-ite.c	2004-10-18 14:57:03 -07:00
@@ -52,21 +52,15 @@
 #define	PM_IBSR		IT8172_PCI_IO_BASE + IT_PM_DSR + 0x04 
 #define GPIO_CCR	IT8172_PCI_IO_BASE + IT_GPCCR
 
-/* ----- global defines ----------------------------------------------- */
-#define DEB(x) if (i2c_debug>=1) x
 #define DEB2(x) if (i2c_debug>=2) x
 #define DEB3(x) if (i2c_debug>=3) x /* print several statistical values*/
-#define DEBPROTO(x) if (i2c_debug>=9) x;
- 	/* debug the protocol by showing transferred bits */
 #define DEF_TIMEOUT 16
 
 
-/* ----- global variables ---------------------------------------------	*/
-
 /* module parameters:
  */
-static int i2c_debug=1;
-static int iic_test=0;	/* see if the line-setting functions work	*/
+static int i2c_debug;
+static int iic_test;	/* see if the line-setting functions work	*/
 
 /* --- setting states on the bus with the right timing: ---------------	*/
 
@@ -804,8 +798,8 @@
 MODULE_DESCRIPTION("ITE iic algorithm");
 MODULE_LICENSE("GPL");
 
-MODULE_PARM(iic_test, "i");
-MODULE_PARM(i2c_debug,"i");
+module_param(iic_test, bool, 0);
+module_param(i2c_debug, int, S_IRUGO | S_IWUSR);
 
 MODULE_PARM_DESC(iic_test, "Test if the I2C bus is available");
 MODULE_PARM_DESC(i2c_debug,
diff -Nru a/drivers/i2c/algos/i2c-algo-pca.c b/drivers/i2c/algos/i2c-algo-pca.c
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/drivers/i2c/algos/i2c-algo-pca.c	2004-10-18 14:57:23 -07:00
@@ -0,0 +1,395 @@
+/*
+ *  i2c-algo-pca.c i2c driver algorithms for PCA9564 adapters                
+ *    Copyright (C) 2004 Arcom Control Systems
+ *
+ *  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.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/delay.h>
+#include <linux/slab.h>
+#include <linux/init.h>
+#include <linux/errno.h>
+#include <linux/i2c.h>
+#include <linux/i2c-algo-pca.h>
+#include "i2c-algo-pca.h"
+
+#define DRIVER "i2c-algo-pca"
+
+#define DEB1(fmt, args...) do { if (i2c_debug>=1) printk(fmt, ## args); } while(0)
+#define DEB2(fmt, args...) do { if (i2c_debug>=2) printk(fmt, ## args); } while(0)
+#define DEB3(fmt, args...) do { if (i2c_debug>=3) printk(fmt, ## args); } while(0)
+
+static int i2c_debug=0;
+
+#define pca_outw(adap, reg, val) adap->write_byte(adap, reg, val)
+#define pca_inw(adap, reg) adap->read_byte(adap, reg)
+
+#define pca_status(adap) pca_inw(adap, I2C_PCA_STA)
+#define pca_clock(adap) adap->get_clock(adap)
+#define pca_own(adap) adap->get_own(adap)
+#define pca_set_con(adap, val) pca_outw(adap, I2C_PCA_CON, val)
+#define pca_get_con(adap) pca_inw(adap, I2C_PCA_CON)
+#define pca_wait(adap) adap->wait_for_interrupt(adap)
+
+/*
+ * Generate a start condition on the i2c bus.
+ *
+ * returns after the start condition has occured
+ */
+static void pca_start(struct i2c_algo_pca_data *adap)
+{
+	int sta = pca_get_con(adap);
+	DEB2("=== START\n");
+	sta |= I2C_PCA_CON_STA;
+	sta &= ~(I2C_PCA_CON_STO|I2C_PCA_CON_SI);
+	pca_set_con(adap, sta);
+	pca_wait(adap);
+}
+
+/*
+ * Generate a repeated start condition on the i2c bus 
+ *
+ * return after the repeated start condition has occured
+ */
+static void pca_repeated_start(struct i2c_algo_pca_data *adap)
+{
+	int sta = pca_get_con(adap);
+	DEB2("=== REPEATED START\n");
+	sta |= I2C_PCA_CON_STA;
+	sta &= ~(I2C_PCA_CON_STO|I2C_PCA_CON_SI);
+	pca_set_con(adap, sta);
+	pca_wait(adap);
+}
+
+/*
+ * Generate a stop condition on the i2c bus
+ *
+ * returns after the stop condition has been generated
+ *
+ * STOPs do not generate an interrupt or set the SI flag, since the
+ * part returns the the idle state (0xf8). Hence we don't need to
+ * pca_wait here.
+ */
+static void pca_stop(struct i2c_algo_pca_data *adap)
+{
+	int sta = pca_get_con(adap);
+	DEB2("=== STOP\n");
+	sta |= I2C_PCA_CON_STO;
+	sta &= ~(I2C_PCA_CON_STA|I2C_PCA_CON_SI);
+	pca_set_con(adap, sta);
+}
+
+/*
+ * Send the slave address and R/W bit
+ *
+ * returns after the address has been sent
+ */
+static void pca_address(struct i2c_algo_pca_data *adap, 
+			struct i2c_msg *msg)
+{
+	int sta = pca_get_con(adap);
+	int addr;
+
+	addr = ( (0x7f & msg->addr) << 1 );
+	if (msg->flags & I2C_M_RD )
+		addr |= 1;
+	DEB2("=== SLAVE ADDRESS %#04x+%c=%#04x\n", 
+	     msg->addr, msg->flags & I2C_M_RD ? 'R' : 'W', addr);
+	
+	pca_outw(adap, I2C_PCA_DAT, addr);
+
+	sta &= ~(I2C_PCA_CON_STO|I2C_PCA_CON_STA|I2C_PCA_CON_SI);
+	pca_set_con(adap, sta);
+
+	pca_wait(adap);
+}
+
+/*
+ * Transmit a byte.
+ *
+ * Returns after the byte has been transmitted
+ */
+static void pca_tx_byte(struct i2c_algo_pca_data *adap, 
+			__u8 b)
+{
+	int sta = pca_get_con(adap);
+	DEB2("=== WRITE %#04x\n", b);
+	pca_outw(adap, I2C_PCA_DAT, b);
+
+	sta &= ~(I2C_PCA_CON_STO|I2C_PCA_CON_STA|I2C_PCA_CON_SI);
+	pca_set_con(adap, sta);
+
+	pca_wait(adap);
+}
+
+/*
+ * Receive a byte
+ *
+ * returns immediately.
+ */
+static void pca_rx_byte(struct i2c_algo_pca_data *adap, 
+			__u8 *b, int ack)
+{
+	*b = pca_inw(adap, I2C_PCA_DAT);
+	DEB2("=== READ %#04x %s\n", *b, ack ? "ACK" : "NACK");
+}
+
+/* 
+ * Setup ACK or NACK for next received byte and wait for it to arrive.
+ *
+ * Returns after next byte has arrived.
+ */
+static void pca_rx_ack(struct i2c_algo_pca_data *adap, 
+		       int ack)
+{
+	int sta = pca_get_con(adap);
+
+	sta &= ~(I2C_PCA_CON_STO|I2C_PCA_CON_STA|I2C_PCA_CON_SI|I2C_PCA_CON_AA);
+
+	if ( ack )
+		sta |= I2C_PCA_CON_AA;
+
+	pca_set_con(adap, sta);
+	pca_wait(adap);
+}
+
+/* 
+ * Reset the i2c bus / SIO 
+ */
+static void pca_reset(struct i2c_algo_pca_data *adap)
+{
+	/* apparently only an external reset will do it. not a lot can be done */
+	printk(KERN_ERR DRIVER ": Haven't figured out how to do a reset yet\n");
+}
+
+static int pca_xfer(struct i2c_adapter *i2c_adap,
+                    struct i2c_msg msgs[],
+                    int num)
+{
+        struct i2c_algo_pca_data *adap = i2c_adap->algo_data;
+        struct i2c_msg *msg = NULL;
+        int curmsg;
+	int numbytes = 0;
+	int state;
+
+	state = pca_status(adap);
+	if ( state != 0xF8 ) {
+		printk(KERN_ERR DRIVER ": bus is not idle. status is %#04x\n", state );
+		/* FIXME: what to do. Force stop ? */
+		return -EREMOTEIO;
+	}
+
+	DEB1("{{{ XFER %d messages\n", num);
+
+	if (i2c_debug>=2) {
+		for (curmsg = 0; curmsg < num; curmsg++) {
+			int addr, i;
+			msg = &msgs[curmsg];
+			
+			addr = (0x7f & msg->addr) ;
+		
+			if (msg->flags & I2C_M_RD )
+				printk(KERN_INFO "    [%02d] RD %d bytes from %#02x [%#02x, ...]\n", 
+				       curmsg, msg->len, addr, (addr<<1) | 1);
+			else {
+				printk(KERN_INFO "    [%02d] WR %d bytes to %#02x [%#02x%s", 
+				       curmsg, msg->len, addr, addr<<1,
+				       msg->len == 0 ? "" : ", ");
+				for(i=0; i < msg->len; i++)
+					printk("%#04x%s", msg->buf[i], i == msg->len - 1 ? "" : ", ");
+				printk("]\n");
+			}
+		}
+	}
+
+	curmsg = 0;
+	while (curmsg < num) {
+		state = pca_status(adap);
+
+		DEB3("STATE is 0x%02x\n", state);
+		msg = &msgs[curmsg];
+
+		switch (state) {
+		case 0xf8: /* On reset or stop the bus is idle */
+			pca_start(adap);
+			break;
+
+		case 0x08: /* A START condition has been transmitted */
+		case 0x10: /* A repeated start condition has been transmitted */
+			pca_address(adap, msg);
+			break;
+			
+		case 0x18: /* SLA+W has been transmitted; ACK has been received */
+		case 0x28: /* Data byte in I2CDAT has been transmitted; ACK has been received */
+			if (numbytes < msg->len) {
+				pca_tx_byte(adap, msg->buf[numbytes]);
+				numbytes++;
+				break;
+			}
+			curmsg++; numbytes = 0;
+			if (curmsg == num)
+				pca_stop(adap);
+			else
+				pca_repeated_start(adap);
+			break;
+
+		case 0x20: /* SLA+W has been transmitted; NOT ACK has been received */
+			DEB2("NOT ACK recieved after SLA+W\n");
+			pca_stop(adap);
+			return -EREMOTEIO;
+
+		case 0x40: /* SLA+R has been transmitted; ACK has been received */
+			pca_rx_ack(adap, msg->len > 1);
+			break;
+
+		case 0x50: /* Data bytes has been received; ACK has been returned */
+			if (numbytes < msg->len) {
+				pca_rx_byte(adap, &msg->buf[numbytes], 1);
+				numbytes++;
+				pca_rx_ack(adap, numbytes < msg->len - 1);
+				break;
+			} 
+			curmsg++; numbytes = 0;
+			if (curmsg == num)
+				pca_stop(adap);
+			else
+				pca_repeated_start(adap);
+			break;
+
+		case 0x48: /* SLA+R has been transmitted; NOT ACK has been received */
+			DEB2("NOT ACK received after SLA+R\n");
+			pca_stop(adap);
+			return -EREMOTEIO;
+
+		case 0x30: /* Data byte in I2CDAT has been transmitted; NOT ACK has been received */
+			DEB2("NOT ACK recieved after data byte\n");
+			return -EREMOTEIO;
+
+		case 0x38: /* Arbitration lost during SLA+W, SLA+R or data bytes */
+			DEB2("Arbitration lost\n");
+			return -EREMOTEIO;
+			
+		case 0x58: /* Data byte has been received; NOT ACK has been returned */
+			if ( numbytes == msg->len - 1 ) {
+				pca_rx_byte(adap, &msg->buf[numbytes], 0);
+				curmsg++; numbytes = 0;
+				if (curmsg == num)
+					pca_stop(adap);
+				else
+					pca_repeated_start(adap);
+			} else {
+				DEB2("NOT ACK sent after data byte received. "
+				     "Not final byte. numbytes %d. len %d\n",
+				     numbytes, msg->len);
+				pca_stop(adap);
+				return -EREMOTEIO;
+			}
+			break;
+		case 0x70: /* Bus error - SDA stuck low */
+			DEB2("BUS ERROR - SDA Stuck low\n");
+			pca_reset(adap);
+			return -EREMOTEIO;
+		case 0x90: /* Bus error - SCL stuck low */
+			DEB2("BUS ERROR - SCL Stuck low\n");
+			pca_reset(adap);
+			return -EREMOTEIO;
+		case 0x00: /* Bus error during master or slave mode due to illegal START or STOP condition */
+			DEB2("BUS ERROR - Illegal START or STOP\n");
+			pca_reset(adap);
+			return -EREMOTEIO;
+		default:
+			printk(KERN_ERR DRIVER ": unhandled SIO state 0x%02x\n", state);
+			break;
+		}
+		
+	}
+
+	DEB1(KERN_CRIT "}}} transfered %d messages. "
+	     "status is %#04x. control is %#04x\n", 
+	     num, pca_status(adap),
+	     pca_get_con(adap));
+	return curmsg;
+}
+
+static u32 pca_func(struct i2c_adapter *adap)
+{
+        return I2C_FUNC_SMBUS_EMUL;
+}
+
+static int pca_init(struct i2c_algo_pca_data *adap)
+{
+	static int freqs[] = {330,288,217,146,88,59,44,36};
+	int own, clock;
+
+	own = pca_own(adap);
+	clock = pca_clock(adap);
+	DEB1(KERN_INFO DRIVER ": own address is %#04x\n", own);
+	DEB1(KERN_INFO DRIVER ": clock freqeuncy is %dkHz\n", freqs[clock]);
+
+	pca_outw(adap, I2C_PCA_ADR, own << 1);
+
+	pca_set_con(adap, I2C_PCA_CON_ENSIO | clock);
+	udelay(500); /* 500 µs for oscilator to stabilise */
+
+	return 0;
+}
+
+static struct i2c_algorithm pca_algo = {
+	.name		= "PCA9564 algorithm",
+	.id		= I2C_ALGO_PCA,
+	.master_xfer	= pca_xfer,
+	.functionality	= pca_func,
+};
+
+/* 
+ * registering functions to load algorithms at runtime 
+ */
+int i2c_pca_add_bus(struct i2c_adapter *adap)
+{
+	struct i2c_algo_pca_data *pca_adap = adap->algo_data;
+	int rval;
+
+	/* register new adapter to i2c module... */
+
+	adap->id |= pca_algo.id;
+	adap->algo = &pca_algo;
+
+	adap->timeout = 100;		/* default values, should	*/
+	adap->retries = 3;		/* be replaced by defines	*/
+
+	rval = pca_init(pca_adap);
+
+	if (!rval)
+		i2c_add_adapter(adap);
+
+	return rval;
+}
+
+int i2c_pca_del_bus(struct i2c_adapter *adap)
+{
+	return i2c_del_adapter(adap);
+}
+
+EXPORT_SYMBOL(i2c_pca_add_bus);
+EXPORT_SYMBOL(i2c_pca_del_bus);
+
+MODULE_AUTHOR("Ian Campbell <icampbell@arcom.com>");
+MODULE_DESCRIPTION("I2C-Bus PCA9564 algorithm");
+MODULE_LICENSE("GPL");
+
+module_param(i2c_debug, int, 0);
diff -Nru a/drivers/i2c/algos/i2c-algo-pca.h b/drivers/i2c/algos/i2c-algo-pca.h
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/drivers/i2c/algos/i2c-algo-pca.h	2004-10-18 14:57:24 -07:00
@@ -0,0 +1,26 @@
+#ifndef I2C_PCA9564_H
+#define I2C_PCA9564_H 1
+
+#define I2C_PCA_STA		0x00 /* STATUS  Read Only  */
+#define I2C_PCA_TO		0x00 /* TIMEOUT Write Only */
+#define I2C_PCA_DAT		0x01 /* DATA    Read/Write */
+#define I2C_PCA_ADR		0x02 /* OWN ADR Read/Write */
+#define I2C_PCA_CON		0x03 /* CONTROL Read/Write */
+
+#define I2C_PCA_CON_AA		0x80 /* Assert Acknowledge */
+#define I2C_PCA_CON_ENSIO	0x40 /* Enable */
+#define I2C_PCA_CON_STA		0x20 /* Start */
+#define I2C_PCA_CON_STO		0x10 /* Stop */
+#define I2C_PCA_CON_SI		0x08 /* Serial Interrupt */
+#define I2C_PCA_CON_CR		0x07 /* Clock Rate (MASK) */
+
+#define I2C_PCA_CON_330kHz	0x00
+#define I2C_PCA_CON_288kHz	0x01
+#define I2C_PCA_CON_217kHz	0x02
+#define I2C_PCA_CON_146kHz	0x03
+#define I2C_PCA_CON_88kHz	0x04
+#define I2C_PCA_CON_59kHz	0x05
+#define I2C_PCA_CON_44kHz	0x06
+#define I2C_PCA_CON_36kHz	0x07
+
+#endif /* I2C_PCA9564_H */
diff -Nru a/drivers/i2c/algos/i2c-algo-pcf.c b/drivers/i2c/algos/i2c-algo-pcf.c
--- a/drivers/i2c/algos/i2c-algo-pcf.c	2004-10-18 14:56:49 -07:00
+++ b/drivers/i2c/algos/i2c-algo-pcf.c	2004-10-18 14:56:49 -07:00
@@ -38,8 +38,6 @@
 #include "i2c-algo-pcf.h"
 
 
-/* ----- global defines ----------------------------------------------- */
-#define DEB(x) if (i2c_debug>=1) x
 #define DEB2(x) if (i2c_debug>=2) x
 #define DEB3(x) if (i2c_debug>=3) x /* print several statistical values*/
 #define DEBPROTO(x) if (i2c_debug>=9) x;
@@ -48,7 +46,7 @@
 
 /* module parameters:
  */
-static int i2c_debug=0;
+static int i2c_debug;
 
 /* --- setting states on the bus with the right timing: ---------------	*/
 
@@ -101,12 +99,6 @@
 }
 
 
-static inline void pcf_sleep(unsigned long timeout)
-{
-	schedule_timeout( timeout * HZ);
-}
-
-
 static int wait_for_pin(struct i2c_algo_pcf_data *adap, int *status) {
 
 	int timeout = DEF_TIMEOUT;
@@ -472,6 +464,6 @@
 MODULE_DESCRIPTION("I2C-Bus PCF8584 algorithm");
 MODULE_LICENSE("GPL");
 
-MODULE_PARM(i2c_debug,"i");
+module_param(i2c_debug, int, S_IRUGO | S_IWUSR);
 MODULE_PARM_DESC(i2c_debug,
         "debug level - 0 off; 1 normal; 2,3 more verbose; 9 pcf-protocol");
diff -Nru a/drivers/i2c/busses/Kconfig b/drivers/i2c/busses/Kconfig
--- a/drivers/i2c/busses/Kconfig	2004-10-18 14:56:50 -07:00
+++ b/drivers/i2c/busses/Kconfig	2004-10-18 14:56:50 -07:00
@@ -164,6 +164,17 @@
 	  This support is also available as a module. If so, the module
 	  will be called i2c-ixp4xx.
 
+config I2C_IXP2000
+	tristate "IXP2000 GPIO-Based I2C Interface"
+	depends on I2C && ARCH_IXP2000
+	select I2C_ALGOBIT
+	help
+	  Say Y here if you have an Intel IXP2000(2400, 2800, 2850) based 
+	  system and are using GPIO lines for an I2C bus.
+
+	  This support is also available as a module. If so, the module
+	  will be called i2c-ixp2000.
+
 config I2C_KEYWEST
 	tristate "Powermac Keywest I2C interface"
 	depends on I2C && PPC_PMAC
@@ -174,6 +185,18 @@
 	  This support is also available as a module.  If so, the module 
 	  will be called i2c-keywest.
 
+config I2C_MPC
+	tristate "MPC107/824x/85xx/52xx"
+	depends on I2C && FSL_OCP
+	help
+	  If you say yes to this option, support will be included for the
+	  built-in I2C interface on the MPC107/Tsi107/MPC8240/MPC8245 and
+	  MPC85xx family processors. The driver may also work on 52xx
+	  family processors, though interrupts are known not to work.
+
+	  This driver can also be built as a module.  If so, the module
+	  will be called i2c-mpc.
+
 config I2C_NFORCE2
 	tristate "Nvidia Nforce2"
 	depends on I2C && PCI && EXPERIMENTAL
@@ -395,5 +418,16 @@
 
 	  This driver can also be built as a module.  If so, the module
 	  will be called i2c-voodoo3.
+
+config I2C_PCA_ISA
+	tristate "PCA9564 on an ISA bus"
+	depends on I2C
+	select I2C_ALGOPCA
+	help
+	  This driver supports ISA boards using the Philips PCA 9564
+	  Parallel bus to I2C bus controller
+	  
+	  This driver can also be built as a module.  If so, the module
+	  will be called i2c-pca-isa.
 
 endmenu
diff -Nru a/drivers/i2c/busses/Makefile b/drivers/i2c/busses/Makefile
--- a/drivers/i2c/busses/Makefile	2004-10-18 14:55:54 -07:00
+++ b/drivers/i2c/busses/Makefile	2004-10-18 14:55:54 -07:00
@@ -15,11 +15,14 @@
 obj-$(CONFIG_I2C_IOP3XX)	+= i2c-iop3xx.o
 obj-$(CONFIG_I2C_ISA)		+= i2c-isa.o
 obj-$(CONFIG_I2C_ITE)		+= i2c-ite.o
+obj-$(CONFIG_I2C_IXP2000)	+= i2c-ixp2000.o
 obj-$(CONFIG_I2C_IXP4XX)	+= i2c-ixp4xx.o
 obj-$(CONFIG_I2C_KEYWEST)	+= i2c-keywest.o
+obj-$(CONFIG_I2C_MPC)		+= i2c-mpc.o
 obj-$(CONFIG_I2C_NFORCE2)	+= i2c-nforce2.o
 obj-$(CONFIG_I2C_PARPORT)	+= i2c-parport.o
 obj-$(CONFIG_I2C_PARPORT_LIGHT)	+= i2c-parport-light.o
+obj-$(CONFIG_I2C_PCA_ISA)	+= i2c-pca-isa.o
 obj-$(CONFIG_I2C_PIIX4)		+= i2c-piix4.o
 obj-$(CONFIG_I2C_PROSAVAGE)	+= i2c-prosavage.o
 obj-$(CONFIG_I2C_RPXLITE)	+= i2c-rpx.o
diff -Nru a/drivers/i2c/busses/i2c-ali1563.c b/drivers/i2c/busses/i2c-ali1563.c
--- a/drivers/i2c/busses/i2c-ali1563.c	2004-10-18 14:56:33 -07:00
+++ b/drivers/i2c/busses/i2c-ali1563.c	2004-10-18 14:56:33 -07:00
@@ -395,7 +395,7 @@
 };
 
 static struct pci_driver ali1563_pci_driver = {
- 	.name		= "i2c-ali1563",
+ 	.name		= "ali1563_i2c",
 	.id_table	= ali1563_id_table,
  	.probe		= ali1563_probe,
 	.remove		= ali1563_remove,
diff -Nru a/drivers/i2c/busses/i2c-ali15x3.c b/drivers/i2c/busses/i2c-ali15x3.c
--- a/drivers/i2c/busses/i2c-ali15x3.c	2004-10-18 14:56:32 -07:00
+++ b/drivers/i2c/busses/i2c-ali15x3.c	2004-10-18 14:56:32 -07:00
@@ -126,8 +126,8 @@
 
 /* If force_addr is set to anything different from 0, we forcibly enable
    the device at the given address. */
-static int force_addr = 0;
-MODULE_PARM(force_addr, "i");
+static u16 force_addr = 0;
+module_param(force_addr, ushort, 0);
 MODULE_PARM_DESC(force_addr,
 		 "Initialize the base address of the i2c controller");
 
@@ -509,7 +509,7 @@
 }
 
 static struct pci_driver ali15x3_driver = {
-	.name		= "ali15x3 smbus",
+	.name		= "ali15x3_smbus",
 	.id_table	= ali15x3_ids,
 	.probe		= ali15x3_probe,
 	.remove		= __devexit_p(ali15x3_remove),
diff -Nru a/drivers/i2c/busses/i2c-amd756.c b/drivers/i2c/busses/i2c-amd756.c
--- a/drivers/i2c/busses/i2c-amd756.c	2004-10-18 14:56:50 -07:00
+++ b/drivers/i2c/busses/i2c-amd756.c	2004-10-18 14:56:50 -07:00
@@ -394,7 +394,7 @@
 }
 
 static struct pci_driver amd756_driver = {
-	.name		= "amd756 smbus",
+	.name		= "amd756_smbus",
 	.id_table	= amd756_ids,
 	.probe		= amd756_probe,
 	.remove		= __devexit_p(amd756_remove),
diff -Nru a/drivers/i2c/busses/i2c-amd8111.c b/drivers/i2c/busses/i2c-amd8111.c
--- a/drivers/i2c/busses/i2c-amd8111.c	2004-10-18 14:56:49 -07:00
+++ b/drivers/i2c/busses/i2c-amd8111.c	2004-10-18 14:56:49 -07:00
@@ -392,7 +392,7 @@
 }
 
 static struct pci_driver amd8111_driver = {
-	.name		= "amd8111 smbus 2",
+	.name		= "amd8111_smbus2",
 	.id_table	= amd8111_ids,
 	.probe		= amd8111_probe,
 	.remove		= __devexit_p(amd8111_remove),
diff -Nru a/drivers/i2c/busses/i2c-elektor.c b/drivers/i2c/busses/i2c-elektor.c
--- a/drivers/i2c/busses/i2c-elektor.c	2004-10-18 14:55:54 -07:00
+++ b/drivers/i2c/busses/i2c-elektor.c	2004-10-18 14:55:54 -07:00
@@ -269,11 +269,11 @@
 MODULE_DESCRIPTION("I2C-Bus adapter routines for PCF8584 ISA bus adapter");
 MODULE_LICENSE("GPL");
 
-MODULE_PARM(base, "i");
-MODULE_PARM(irq, "i");
-MODULE_PARM(clock, "i");
-MODULE_PARM(own, "i");
-MODULE_PARM(mmapped, "i");
+module_param(base, int, 0);
+module_param(irq, int, 0);
+module_param(clock, int, 0);
+module_param(own, int, 0);
+module_param(mmapped, int, 0);
 
 module_init(i2c_pcfisa_init);
 module_exit(i2c_pcfisa_exit);
diff -Nru a/drivers/i2c/busses/i2c-hydra.c b/drivers/i2c/busses/i2c-hydra.c
--- a/drivers/i2c/busses/i2c-hydra.c	2004-10-18 14:56:28 -07:00
+++ b/drivers/i2c/busses/i2c-hydra.c	2004-10-18 14:56:28 -07:00
@@ -158,7 +158,7 @@
 
 
 static struct pci_driver hydra_driver = {
-	.name		= "hydra smbus",
+	.name		= "hydra_smbus",
 	.id_table	= hydra_ids,
 	.probe		= hydra_probe,
 	.remove		= __devexit_p(hydra_remove),
diff -Nru a/drivers/i2c/busses/i2c-i801.c b/drivers/i2c/busses/i2c-i801.c
--- a/drivers/i2c/busses/i2c-i801.c	2004-10-18 14:56:31 -07:00
+++ b/drivers/i2c/busses/i2c-i801.c	2004-10-18 14:56:31 -07:00
@@ -98,8 +98,8 @@
 
 /* If force_addr is set to anything different from 0, we forcibly enable
    the I801 at the given address. VERY DANGEROUS! */
-static int force_addr = 0;
-MODULE_PARM(force_addr, "i");
+static u16 force_addr;
+module_param(force_addr, ushort, 0);
 MODULE_PARM_DESC(force_addr,
 		 "Forcibly enable the I801 at the given address. "
 		 "EXTREMELY DANGEROUS!");
@@ -623,7 +623,7 @@
 }
 
 static struct pci_driver i801_driver = {
-	.name		= "i801 smbus",
+	.name		= "i801_smbus",
 	.id_table	= i801_ids,
 	.probe		= i801_probe,
 	.remove		= __devexit_p(i801_remove),
diff -Nru a/drivers/i2c/busses/i2c-i810.c b/drivers/i2c/busses/i2c-i810.c
--- a/drivers/i2c/busses/i2c-i810.c	2004-10-18 14:56:13 -07:00
+++ b/drivers/i2c/busses/i2c-i810.c	2004-10-18 14:56:13 -07:00
@@ -231,7 +231,7 @@
 }
 
 static struct pci_driver i810_driver = {
-	.name		= "i810 smbus",
+	.name		= "i810_smbus",
 	.id_table	= i810_ids,
 	.probe		= i810_probe,
 	.remove		= __devexit_p(i810_remove),
diff -Nru a/drivers/i2c/busses/i2c-ibm_iic.c b/drivers/i2c/busses/i2c-ibm_iic.c
--- a/drivers/i2c/busses/i2c-ibm_iic.c	2004-10-18 14:56:48 -07:00
+++ b/drivers/i2c/busses/i2c-ibm_iic.c	2004-10-18 14:56:48 -07:00
@@ -50,12 +50,12 @@
 MODULE_DESCRIPTION("IBM IIC driver v" DRIVER_VERSION);
 MODULE_LICENSE("GPL");
 
-static int iic_force_poll = 0;
-MODULE_PARM(iic_force_poll, "i");
+static int iic_force_poll;
+module_param(iic_force_poll, bool, 0);
 MODULE_PARM_DESC(iic_force_poll, "Force polling mode");
 
-static int iic_force_fast = 0;
-MODULE_PARM(iic_force_fast, "i");
+static int iic_force_fast;
+module_param(iic_force_fast, bool, 0);
 MODULE_PARM_DESC(iic_fast_poll, "Force fast mode (400 kHz)");
 
 #define DBG_LEVEL 0
diff -Nru a/drivers/i2c/busses/i2c-ite.c b/drivers/i2c/busses/i2c-ite.c
--- a/drivers/i2c/busses/i2c-ite.c	2004-10-18 14:56:19 -07:00
+++ b/drivers/i2c/busses/i2c-ite.c	2004-10-18 14:56:19 -07:00
@@ -54,10 +54,10 @@
 #define DEFAULT_CLOCK 0x1b0e	/* default 16MHz/(27+14) = 400KHz */
 #define DEFAULT_OWN   0x55
 
-static int base  = 0;
-static int irq   = 0;
-static int clock = 0;
-static int own   = 0;
+static int base;
+static int irq;
+static int clock;
+static int own;
 
 static struct iic_ite gpi;
 static wait_queue_head_t iic_wait;
@@ -102,14 +102,6 @@
 }
 
 
-#if 0
-static void iic_ite_sleep(unsigned long timeout)
-{
-	schedule_timeout( timeout * HZ);
-}
-#endif
-
-
 /* Put this process to sleep.  We will wake up when the
  * IIC controller interrupts.
  */
@@ -254,10 +246,10 @@
 MODULE_DESCRIPTION("I2C-Bus adapter routines for ITE IIC bus adapter");
 MODULE_LICENSE("GPL");
 
-MODULE_PARM(base, "i");
-MODULE_PARM(irq, "i");
-MODULE_PARM(clock, "i");
-MODULE_PARM(own, "i");
+module_param(base, int, 0);
+module_param(irq, int, 0);
+module_param(clock, int, 0);
+module_param(own, int, 0);
 
 
 /* Called when module is loaded or when kernel is initialized.
diff -Nru a/drivers/i2c/busses/i2c-ixp2000.c b/drivers/i2c/busses/i2c-ixp2000.c
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/drivers/i2c/busses/i2c-ixp2000.c	2004-10-18 14:57:21 -07:00
@@ -0,0 +1,171 @@
+/*
+ * drivers/i2c/busses/i2c-ixp2000.c
+ *
+ * I2C adapter for IXP2000 systems using GPIOs for I2C bus
+ *
+ * Author: Deepak Saxena <dsaxena@plexity.net>
+ * Based on IXDP2400 code by: Naeem M. Afzal <naeem.m.afzal@intel.com>
+ * Made generic by: Jeff Daly <jeffrey.daly@intel.com>
+ *
+ * Copyright (c) 2003-2004 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 Jeff Daly:
+ *
+ * I2C adapter driver for Intel IXDP2xxx platforms. This should work for any
+ * IXP2000 platform if it uses the HW GPIO in the same manner.  Basically, 
+ * SDA and SCL GPIOs have external pullups.  Setting the respective GPIO to 
+ * an input will make the signal a '1' via the pullup.  Setting them to 
+ * outputs will pull them down. 
+ *
+ * The GPIOs are open drain signals and are used as configuration strap inputs
+ * during power-up so there's generally a buffer on the board that needs to be 
+ * 'enabled' to drive the GPIOs.
+ */
+
+#include <linux/config.h>
+#ifdef CONFIG_I2C_DEBUG_BUS
+#define DEBUG	1
+#endif
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/device.h>
+#include <linux/module.h>
+#include <linux/i2c.h>
+#include <linux/i2c-algo-bit.h>
+
+#include <asm/hardware.h>	/* Pick up IXP42000-specific bits */
+
+static inline int ixp2000_scl_pin(void *data)
+{
+	return ((struct ixp2000_i2c_pins*)data)->scl_pin;
+}
+
+static inline int ixp2000_sda_pin(void *data)
+{
+	return ((struct ixp2000_i2c_pins*)data)->sda_pin;
+}
+
+
+static void ixp2000_bit_setscl(void *data, int val)
+{
+	int i = 5000;
+
+	if (val) {
+		gpio_line_config(ixp2000_scl_pin(data), GPIO_IN);
+		while(!gpio_line_get(ixp2000_scl_pin(data)) && i--);
+	} else {
+		gpio_line_config(ixp2000_scl_pin(data), GPIO_OUT);
+	}
+}
+
+static void ixp2000_bit_setsda(void *data, int val)
+{
+	if (val) {
+		gpio_line_config(ixp2000_sda_pin(data), GPIO_IN);
+	} else {
+		gpio_line_config(ixp2000_sda_pin(data), GPIO_OUT);
+	}
+}
+
+static int ixp2000_bit_getscl(void *data)
+{
+	return gpio_line_get(ixp2000_scl_pin(data));
+}
+
+static int ixp2000_bit_getsda(void *data)
+{
+	return gpio_line_get(ixp2000_sda_pin(data));
+}
+
+struct ixp2000_i2c_data {
+	struct ixp2000_i2c_pins *gpio_pins;
+	struct i2c_adapter adapter;
+	struct i2c_algo_bit_data algo_data;
+};
+
+static int ixp2000_i2c_remove(struct device *dev)
+{
+	struct platform_device *plat_dev = to_platform_device(dev);
+	struct ixp2000_i2c_data *drv_data = dev_get_drvdata(&plat_dev->dev);
+
+	dev_set_drvdata(&plat_dev->dev, NULL);
+
+	i2c_bit_del_bus(&drv_data->adapter);
+
+	kfree(drv_data);
+
+	return 0;
+}
+
+static int ixp2000_i2c_probe(struct device *dev)
+{
+	int err;
+	struct platform_device *plat_dev = to_platform_device(dev);
+	struct ixp2000_i2c_pins *gpio = plat_dev->dev.platform_data;
+	struct ixp2000_i2c_data *drv_data = 
+		kmalloc(sizeof(struct ixp2000_i2c_data), GFP_KERNEL);
+
+	if (!drv_data)
+		return -ENOMEM;
+	memzero(drv_data, sizeof(*drv_data));
+	drv_data->gpio_pins = gpio;
+
+	drv_data->algo_data.data = gpio;
+	drv_data->algo_data.setsda = ixp2000_bit_setsda;
+	drv_data->algo_data.setscl = ixp2000_bit_setscl;
+	drv_data->algo_data.getsda = ixp2000_bit_getsda;
+	drv_data->algo_data.getscl = ixp2000_bit_getscl;
+	drv_data->algo_data.udelay = 6;
+	drv_data->algo_data.mdelay = 6;
+	drv_data->algo_data.timeout = 100;
+
+	drv_data->adapter.id = I2C_HW_B_IXP2000,
+	drv_data->adapter.algo_data = &drv_data->algo_data,
+
+	drv_data->adapter.dev.parent = &plat_dev->dev;
+
+	gpio_line_config(gpio->sda_pin, GPIO_IN);
+	gpio_line_config(gpio->scl_pin, GPIO_IN);
+	gpio_line_set(gpio->scl_pin, 0);
+	gpio_line_set(gpio->sda_pin, 0);
+
+	if ((err = i2c_bit_add_bus(&drv_data->adapter)) != 0) {
+		dev_err(dev, "Could not install, error %d\n", err);
+		kfree(drv_data);
+		return err;
+	} 
+
+	dev_set_drvdata(&plat_dev->dev, drv_data);
+
+	return 0;
+}
+
+static struct device_driver ixp2000_i2c_driver = {
+	.name		= "IXP2000-I2C",
+	.bus		= &platform_bus_type,
+	.probe		= ixp2000_i2c_probe,
+	.remove		= ixp2000_i2c_remove,
+};
+
+static int __init ixp2000_i2c_init(void)
+{
+	return driver_register(&ixp2000_i2c_driver);
+}
+
+static void __exit ixp2000_i2c_exit(void)
+{
+	driver_unregister(&ixp2000_i2c_driver);
+}
+
+module_init(ixp2000_i2c_init);
+module_exit(ixp2000_i2c_exit);
+
+MODULE_AUTHOR ("Deepak Saxena <dsaxena@plexity.net>");
+MODULE_DESCRIPTION("IXP2000 GPIO-based I2C bus driver");
+MODULE_LICENSE("GPL");
+
diff -Nru a/drivers/i2c/busses/i2c-keywest.c b/drivers/i2c/busses/i2c-keywest.c
--- a/drivers/i2c/busses/i2c-keywest.c	2004-10-18 14:56:48 -07:00
+++ b/drivers/i2c/busses/i2c-keywest.c	2004-10-18 14:56:48 -07:00
@@ -88,12 +88,12 @@
 };
 #endif /* DEBUG */
 
+static int probe;
+
 MODULE_AUTHOR("Benjamin Herrenschmidt <benh@kernel.crashing.org>");
 MODULE_DESCRIPTION("I2C driver for Apple's Keywest");
 MODULE_LICENSE("GPL");
-MODULE_PARM(probe, "i");
-
-static int probe = 0;
+module_param(probe, bool, 0);
 
 #ifdef POLLED_MODE
 /* Don't schedule, the g5 fan controller is too
@@ -662,8 +662,7 @@
 	spin_lock_irq(&iface->lock);
 	while (iface->state != state_idle) {
 		spin_unlock_irq(&iface->lock);
-		set_task_state(current,TASK_UNINTERRUPTIBLE);
-		schedule_timeout(HZ/10);
+		msleep(100);
 		spin_lock_irq(&iface->lock);
 	}
 #endif /* POLLED_MODE */
diff -Nru a/drivers/i2c/busses/i2c-mpc.c b/drivers/i2c/busses/i2c-mpc.c
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/drivers/i2c/busses/i2c-mpc.c	2004-10-18 14:57:23 -07:00
@@ -0,0 +1,392 @@
+/*
+ * (C) Copyright 2003-2004
+ * Humboldt Solutions Ltd, adrian@humboldt.co.uk.
+ 
+ * This is a combined i2c adapter and algorithm driver for the
+ * MPC107/Tsi107 PowerPC northbridge and processors that include
+ * the same I2C unit (8240, 8245, 85xx). 
+ *
+ * Release 0.6
+ *
+ * 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/kernel.h>
+#include <linux/module.h>
+#include <linux/sched.h>
+#include <linux/init.h>
+#include <linux/pci.h>
+#include <asm/io.h>
+#include <asm/ocp.h>
+#include <linux/i2c.h>
+#include <linux/interrupt.h>
+
+#define MPC_I2C_ADDR  0x00
+#define MPC_I2C_FDR 	0x04
+#define MPC_I2C_CR	0x08
+#define MPC_I2C_SR	0x0c
+#define MPC_I2C_DR	0x10
+#define MPC_I2C_DFSRR 0x14
+#define MPC_I2C_REGION 0x20
+
+#define CCR_MEN  0x80
+#define CCR_MIEN 0x40
+#define CCR_MSTA 0x20
+#define CCR_MTX  0x10
+#define CCR_TXAK 0x08
+#define CCR_RSTA 0x04
+
+#define CSR_MCF  0x80
+#define CSR_MAAS 0x40
+#define CSR_MBB  0x20
+#define CSR_MAL  0x10
+#define CSR_SRW  0x04
+#define CSR_MIF  0x02
+#define CSR_RXAK 0x01
+
+struct mpc_i2c {
+	char *base;
+	struct ocp_def *ocpdef;
+	u32 interrupt;
+	wait_queue_head_t queue;
+	struct i2c_adapter adap;
+};
+
+static __inline__ void writeccr(struct mpc_i2c *i2c, u32 x)
+{
+	writeb(x, i2c->base + MPC_I2C_CR);
+}
+
+static irqreturn_t mpc_i2c_isr(int irq, void *dev_id, struct pt_regs *regs)
+{
+	struct mpc_i2c *i2c = dev_id;
+	if (readb(i2c->base + MPC_I2C_SR) & CSR_MIF) {
+		/* Read again to allow register to stabilise */
+		i2c->interrupt = readb(i2c->base + MPC_I2C_SR);
+		writeb(0, i2c->base + MPC_I2C_SR);
+		wake_up_interruptible(&i2c->queue);
+	}
+	return IRQ_HANDLED;
+}
+
+static int i2c_wait(struct mpc_i2c *i2c, unsigned timeout, int writing)
+{
+	DECLARE_WAITQUEUE(wait, current);
+	unsigned long orig_jiffies = jiffies;
+	u32 x;
+	int result = 0;
+
+	if (i2c->ocpdef->irq == OCP_IRQ_NA) {
+		while (!(readb(i2c->base + MPC_I2C_SR) & CSR_MIF)) {
+			schedule();
+			if (time_after(jiffies, orig_jiffies + timeout)) {
+				pr_debug("I2C: timeout\n");
+				result = -EIO;
+				break;
+			}
+		}
+		x = readb(i2c->base + MPC_I2C_SR);
+		writeb(0, i2c->base + MPC_I2C_SR);
+	} else {
+		add_wait_queue(&i2c->queue, &wait);
+		while (!(i2c->interrupt & CSR_MIF)) {
+			set_current_state(TASK_INTERRUPTIBLE);
+			if (signal_pending(current)) {
+				pr_debug("I2C: Interrupted\n");
+				result = -EINTR;
+				break;
+			}
+			if (time_after(jiffies, orig_jiffies + timeout)) {
+				pr_debug("I2C: timeout\n");
+				result = -EIO;
+				break;
+			}
+			schedule_timeout(timeout);
+		}
+		current->state = TASK_RUNNING;
+		remove_wait_queue(&i2c->queue, &wait);
+		x = i2c->interrupt;
+		i2c->interrupt = 0;
+	}
+
+	if (result < -0)
+		return result;
+
+	if (!(x & CSR_MCF)) {
+		pr_debug("I2C: unfinished\n");
+		return -EIO;
+	}
+
+	if (x & CSR_MAL) {
+		pr_debug("I2C: MAL\n");
+		return -EIO;
+	}
+
+	if (writing && (x & CSR_RXAK)) {
+		pr_debug("I2C: No RXAK\n");
+		/* generate stop */
+		writeccr(i2c, CCR_MEN);
+		return -EIO;
+	}
+	return 0;
+}
+
+static void mpc_i2c_setclock(struct mpc_i2c *i2c)
+{
+	struct ocp_fs_i2c_data *i2c_data = i2c->ocpdef->additions;
+	/* Set clock and filters */
+	if (i2c_data && (i2c_data->flags & FS_I2C_SEPARATE_DFSRR)) {
+		writeb(0x31, i2c->base + MPC_I2C_FDR);
+		writeb(0x10, i2c->base + MPC_I2C_DFSRR);
+	} else if (i2c_data && (i2c_data->flags & FS_I2C_CLOCK_5200))
+		writeb(0x3f, i2c->base + MPC_I2C_FDR);
+	else
+		writel(0x1031, i2c->base + MPC_I2C_FDR);
+}
+
+static void mpc_i2c_start(struct mpc_i2c *i2c)
+{
+	/* Clear arbitration */
+	writeb(0, i2c->base + MPC_I2C_SR);
+	/* Start with MEN */
+	writeccr(i2c, CCR_MEN);
+}
+
+static void mpc_i2c_stop(struct mpc_i2c *i2c)
+{
+	writeccr(i2c, CCR_MEN);
+}
+
+static int mpc_write(struct mpc_i2c *i2c, int target,
+		     const u8 * data, int length, int restart)
+{
+	int i;
+	unsigned timeout = HZ;
+	u32 flags = restart ? CCR_RSTA : 0;
+
+	/* Start with MEN */
+	if (!restart)
+		writeccr(i2c, CCR_MEN);
+	/* Start as master */
+	writeccr(i2c, CCR_MIEN | CCR_MEN | CCR_MSTA | CCR_MTX | flags);
+	/* Write target byte */
+	writeb((target << 1), i2c->base + MPC_I2C_DR);
+
+	if (i2c_wait(i2c, timeout, 1) < 0)
+		return -1;
+
+	for (i = 0; i < length; i++) {
+		/* Write data byte */
+		writeb(data[i], i2c->base + MPC_I2C_DR);
+
+		if (i2c_wait(i2c, timeout, 1) < 0)
+			return -1;
+	}
+
+	return 0;
+}
+
+static int mpc_read(struct mpc_i2c *i2c, int target,
+		    u8 * data, int length, int restart)
+{
+	unsigned timeout = HZ;
+	int i;
+	u32 flags = restart ? CCR_RSTA : 0;
+
+	/* Start with MEN */
+	if (!restart)
+		writeccr(i2c, CCR_MEN);
+	/* Switch to read - restart */
+	writeccr(i2c, CCR_MIEN | CCR_MEN | CCR_MSTA | CCR_MTX | flags);
+	/* Write target address byte - this time with the read flag set */
+	writeb((target << 1) | 1, i2c->base + MPC_I2C_DR);
+
+	if (i2c_wait(i2c, timeout, 1) < 0)
+		return -1;
+
+	if (length) {
+		if (length == 1)
+			writeccr(i2c, CCR_MIEN | CCR_MEN | CCR_MSTA | CCR_TXAK);
+		else
+			writeccr(i2c, CCR_MIEN | CCR_MEN | CCR_MSTA);
+		/* Dummy read */
+		readb(i2c->base + MPC_I2C_DR);
+	}
+
+	for (i = 0; i < length; i++) {
+		if (i2c_wait(i2c, timeout, 0) < 0)
+			return -1;
+
+		/* Generate txack on next to last byte */
+		if (i == length - 2)
+			writeccr(i2c, CCR_MIEN | CCR_MEN | CCR_MSTA | CCR_TXAK);
+		/* Generate stop on last byte */
+		if (i == length - 1)
+			writeccr(i2c, CCR_MIEN | CCR_MEN | CCR_TXAK);
+		data[i] = readb(i2c->base + MPC_I2C_DR);
+	}
+
+	return length;
+}
+
+static int mpc_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], int num)
+{
+	struct i2c_msg *pmsg;
+	int i;
+	int ret = 0;
+	unsigned long orig_jiffies = jiffies;
+	struct mpc_i2c *i2c = i2c_get_adapdata(adap);
+
+	mpc_i2c_start(i2c);
+
+	/* Allow bus up to 1s to become not busy */
+	while (readb(i2c->base + MPC_I2C_SR) & CSR_MBB) {
+		if (signal_pending(current)) {
+			pr_debug("I2C: Interrupted\n");
+			return -EINTR;
+		}
+		if (time_after(jiffies, orig_jiffies + HZ)) {
+			pr_debug("I2C: timeout\n");
+			return -EIO;
+		}
+		schedule();
+	}
+
+	for (i = 0; ret >= 0 && i < num; i++) {
+		pmsg = &msgs[i];
+		pr_debug("Doing %s %d bytes to 0x%02x - %d of %d messages\n",
+			 pmsg->flags & I2C_M_RD ? "read" : "write",
+			 pmsg->len, pmsg->addr, i + 1, num);
+		if (pmsg->flags & I2C_M_RD)
+			ret =
+			    mpc_read(i2c, pmsg->addr, pmsg->buf, pmsg->len, i);
+		else
+			ret =
+			    mpc_write(i2c, pmsg->addr, pmsg->buf, pmsg->len, i);
+	}
+	mpc_i2c_stop(i2c);
+	return (ret < 0) ? ret : num;
+}
+
+static u32 mpc_functionality(struct i2c_adapter *adap)
+{
+	return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL;
+}
+
+static struct i2c_algorithm mpc_algo = {
+	.name = "MPC algorithm",
+	.id = I2C_ALGO_MPC107,
+	.master_xfer = mpc_xfer,
+	.functionality = mpc_functionality,
+};
+
+static struct i2c_adapter mpc_ops = {
+	.owner = THIS_MODULE,
+	.name = "MPC adapter",
+	.id = I2C_ALGO_MPC107 | I2C_HW_MPC107,
+	.algo = &mpc_algo,
+	.class = I2C_CLASS_HWMON,
+	.timeout = 1,
+	.retries = 1
+};
+
+static int __devinit mpc_i2c_probe(struct ocp_device *ocp)
+{
+	int result = 0;
+	struct mpc_i2c *i2c;
+
+	if (!(i2c = kmalloc(sizeof(*i2c), GFP_KERNEL))) {
+		return -ENOMEM;
+	}
+	i2c->ocpdef = ocp->def;
+	init_waitqueue_head(&i2c->queue);
+
+	if (!request_mem_region(ocp->def->paddr, MPC_I2C_REGION, "i2c-mpc")) {
+		printk(KERN_ERR "i2c-mpc - resource unavailable\n");
+		return -ENODEV;
+	}
+
+	i2c->base = ioremap(ocp->def->paddr, MPC_I2C_REGION);
+
+	if (!i2c->base) {
+		printk(KERN_ERR "i2c-mpc - failed to map controller\n");
+		result = -ENOMEM;
+		goto fail_map;
+	}
+
+	if (ocp->def->irq != OCP_IRQ_NA)
+		if ((result = request_irq(ocp->def->irq, mpc_i2c_isr,
+					  0, "i2c-mpc", i2c)) < 0) {
+			printk(KERN_ERR
+			       "i2c-mpc - failed to attach interrupt\n");
+			goto fail_irq;
+		}
+
+	i2c->adap = mpc_ops;
+	i2c_set_adapdata(&i2c->adap, i2c);
+	if ((result = i2c_add_adapter(&i2c->adap)) < 0) {
+		printk(KERN_ERR "i2c-mpc - failed to add adapter\n");
+		goto fail_add;
+	}
+
+	mpc_i2c_setclock(i2c);
+	ocp_set_drvdata(ocp, i2c);
+	return result;
+
+      fail_add:
+	if (ocp->def->irq != OCP_IRQ_NA)
+		free_irq(ocp->def->irq, 0);
+      fail_irq:
+	iounmap(i2c->base);
+      fail_map:
+	release_mem_region(ocp->def->paddr, MPC_I2C_REGION);
+	kfree(i2c);
+	return result;
+}
+static void __devexit mpc_i2c_remove(struct ocp_device *ocp)
+{
+	struct mpc_i2c *i2c = ocp_get_drvdata(ocp);
+	ocp_set_drvdata(ocp, NULL);
+	i2c_del_adapter(&i2c->adap);
+
+	if (ocp->def->irq != OCP_IRQ_NA)
+		free_irq(i2c->ocpdef->irq, i2c);
+	iounmap(i2c->base);
+	release_mem_region(i2c->ocpdef->paddr, MPC_I2C_REGION);
+	kfree(i2c);
+}
+
+static struct ocp_device_id mpc_iic_ids[] __devinitdata = {
+	{.vendor = OCP_VENDOR_FREESCALE,.function = OCP_FUNC_IIC},
+	{.vendor = OCP_VENDOR_INVALID}
+};
+
+MODULE_DEVICE_TABLE(ocp, mpc_iic_ids);
+
+static struct ocp_driver mpc_iic_driver = {
+	.name = "iic",
+	.id_table = mpc_iic_ids,
+	.probe = mpc_i2c_probe,
+	.remove = __devexit_p(mpc_i2c_remove)
+};
+
+static int __init iic_init(void)
+{
+	return ocp_register_driver(&mpc_iic_driver);
+}
+
+static void __exit iic_exit(void)
+{
+	ocp_unregister_driver(&mpc_iic_driver);
+}
+
+module_init(iic_init);
+module_exit(iic_exit);
+
+MODULE_AUTHOR("Adrian Cox <adrian@humboldt.co.uk>");
+MODULE_DESCRIPTION
+    ("I2C-Bus adapter for MPC107 bridge and MPC824x/85xx/52xx processors");
+MODULE_LICENSE("GPL");
diff -Nru a/drivers/i2c/busses/i2c-nforce2.c b/drivers/i2c/busses/i2c-nforce2.c
--- a/drivers/i2c/busses/i2c-nforce2.c	2004-10-18 14:56:15 -07:00
+++ b/drivers/i2c/busses/i2c-nforce2.c	2004-10-18 14:56:15 -07:00
@@ -244,8 +244,7 @@
 		temp = inb_p(NVIDIA_SMB_STS);
 	}
 	if (~temp & NVIDIA_SMB_STS_DONE) {
-		current->state = TASK_INTERRUPTIBLE;
-		schedule_timeout(HZ/100);
+		msleep(10);
 		temp = inb_p(NVIDIA_SMB_STS);
 	}
 
@@ -384,7 +383,7 @@
 }
 
 static struct pci_driver nforce2_driver = {
-	.name		= "nForce2 SMBus",
+	.name		= "nForce2_smbus",
 	.id_table	= nforce2_ids,
 	.probe		= nforce2_probe,
 	.remove		= __devexit_p(nforce2_remove),
diff -Nru a/drivers/i2c/busses/i2c-parport-light.c b/drivers/i2c/busses/i2c-parport-light.c
--- a/drivers/i2c/busses/i2c-parport-light.c	2004-10-18 14:56:49 -07:00
+++ b/drivers/i2c/busses/i2c-parport-light.c	2004-10-18 14:56:49 -07:00
@@ -36,8 +36,8 @@
 
 #define DEFAULT_BASE 0x378
 
-static int base;
-MODULE_PARM(base, "i");
+static u16 base;
+module_param(base, ushort, 0);
 MODULE_PARM_DESC(base, "Base I/O address");
 
 /* ----- Low-level parallel port access ----------------------------------- */
diff -Nru a/drivers/i2c/busses/i2c-parport.h b/drivers/i2c/busses/i2c-parport.h
--- a/drivers/i2c/busses/i2c-parport.h	2004-10-18 14:57:04 -07:00
+++ b/drivers/i2c/busses/i2c-parport.h	2004-10-18 14:57:04 -07:00
@@ -83,7 +83,7 @@
 };
 
 static int type;
-MODULE_PARM(type, "i");
+module_param(type, int, 0);
 MODULE_PARM_DESC(type,
 	"Type of adapter:\n"
 	" 0 = Philips adapter\n"
diff -Nru a/drivers/i2c/busses/i2c-pca-isa.c b/drivers/i2c/busses/i2c-pca-isa.c
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/drivers/i2c/busses/i2c-pca-isa.c	2004-10-18 14:57:23 -07:00
@@ -0,0 +1,184 @@
+/*
+ *  i2c-pca-isa.c driver for PCA9564 on ISA boards
+ *    Copyright (C) 2004 Arcom Control Systems
+ *
+ *  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.
+ */
+
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/ioport.h>
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/delay.h>
+#include <linux/slab.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/pci.h>
+#include <linux/wait.h>
+
+#include <linux/i2c.h>
+#include <linux/i2c-algo-pca.h>
+
+#include <asm/io.h>
+#include <asm/irq.h>
+
+#include "../algos/i2c-algo-pca.h"
+
+#define IO_SIZE 4
+
+#undef DEBUG_IO
+//#define DEBUG_IO
+
+static unsigned long base   = 0x330;
+static int irq 	  = 10;
+
+/* Data sheet recommends 59kHz for 100kHz operation due to variation
+ * in the actual clock rate */
+static int clock  = I2C_PCA_CON_59kHz;
+
+static int own    = 0x55;
+
+static wait_queue_head_t pca_wait;
+
+static int pca_isa_getown(struct i2c_algo_pca_data *adap)
+{
+	return (own);
+}
+
+static int pca_isa_getclock(struct i2c_algo_pca_data *adap)
+{
+	return (clock);
+}
+
+static void
+pca_isa_writebyte(struct i2c_algo_pca_data *adap, int reg, int val)
+{
+#ifdef DEBUG_IO
+	static char *names[] = { "T/O", "DAT", "ADR", "CON" };
+	printk("*** write %s at %#lx <= %#04x\n", names[reg], base+reg, val);
+#endif
+	outb(val, base+reg);
+}
+
+static int
+pca_isa_readbyte(struct i2c_algo_pca_data *adap, int reg)
+{
+	int res = inb(base+reg);
+#ifdef DEBUG_IO
+	{
+		static char *names[] = { "STA", "DAT", "ADR", "CON" };	
+		printk("*** read  %s => %#04x\n", names[reg], res);
+	}
+#endif
+	return res;
+}
+
+static int pca_isa_waitforinterrupt(struct i2c_algo_pca_data *adap)
+{
+	int ret = 0;
+
+	if (irq > -1) {
+		ret = wait_event_interruptible(pca_wait,
+					       pca_isa_readbyte(adap, I2C_PCA_CON) & I2C_PCA_CON_SI);
+	} else {
+		while ((pca_isa_readbyte(adap, I2C_PCA_CON) & I2C_PCA_CON_SI) == 0) 
+			udelay(100);
+	}
+	return ret;
+}
+
+static irqreturn_t pca_handler(int this_irq, void *dev_id, struct pt_regs *regs) {
+	wake_up_interruptible(&pca_wait);
+	return IRQ_HANDLED;
+}
+
+static struct i2c_algo_pca_data pca_isa_data = {
+	.get_own		= pca_isa_getown,
+	.get_clock		= pca_isa_getclock,
+	.write_byte		= pca_isa_writebyte,
+	.read_byte		= pca_isa_readbyte,
+	.wait_for_interrupt	= pca_isa_waitforinterrupt,
+};
+
+static struct i2c_adapter pca_isa_ops = {
+	.owner          = THIS_MODULE,
+	.id		= I2C_HW_A_ISA,
+	.algo_data	= &pca_isa_data,
+	.name		= "PCA9564 ISA Adapter",
+};
+
+static int __init pca_isa_init(void)
+{
+
+	init_waitqueue_head(&pca_wait);
+
+	printk(KERN_INFO "i2c-pca-isa: i/o base %#08lx. irq %d\n", base, irq);
+
+	if (!request_region(base, IO_SIZE, "i2c-pca-isa")) {
+		printk(KERN_ERR "i2c-pca-isa: I/O address %#08lx is in use.\n", base);
+		goto out;
+	}
+
+	if (irq > -1) {
+		if (request_irq(irq, pca_handler, 0, "i2c-pca-isa", &pca_isa_ops) < 0) {
+			printk(KERN_ERR "i2c-pca-isa: Request irq%d failed\n", irq);
+			goto out_region;
+		}
+	}
+
+	if (i2c_pca_add_bus(&pca_isa_ops) < 0) {
+		printk(KERN_ERR "i2c-pca-isa: Failed to add i2c bus\n");
+		goto out_irq;
+	}
+
+	return 0;
+
+ out_irq:
+	if (irq > -1)
+		free_irq(irq, &pca_isa_ops);
+ out_region:
+	release_region(base, IO_SIZE);
+ out:
+	return -ENODEV;
+}
+
+static void pca_isa_exit(void)
+{
+	i2c_pca_del_bus(&pca_isa_ops);
+
+	if (irq > 0) {
+		disable_irq(irq);
+		free_irq(irq, &pca_isa_ops);
+	}
+	release_region(base, IO_SIZE);
+}
+
+MODULE_AUTHOR("Ian Campbell <icampbell@arcom.com>");
+MODULE_DESCRIPTION("ISA base PCA9564 driver");
+MODULE_LICENSE("GPL");
+
+module_param(base, ulong, 0);
+MODULE_PARM_DESC(base, "I/O base address");
+
+module_param(irq, int, 0);
+MODULE_PARM_DESC(irq, "IRQ");
+module_param(clock, int, 0);
+MODULE_PARM_DESC(clock, "Clock rate as described in table 1 of PCA9564 datasheet");
+
+module_param(own, int, 0); /* the driver can't do slave mode, so there's no real point in this */
+
+module_init(pca_isa_init);
+module_exit(pca_isa_exit);
diff -Nru a/drivers/i2c/busses/i2c-piix4.c b/drivers/i2c/busses/i2c-piix4.c
--- a/drivers/i2c/busses/i2c-piix4.c	2004-10-18 14:56:27 -07:00
+++ b/drivers/i2c/busses/i2c-piix4.c	2004-10-18 14:56:27 -07:00
@@ -493,7 +493,7 @@
 }
 
 static struct pci_driver piix4_driver = {
-	.name		= "piix4-smbus",
+	.name		= "piix4_smbus",
 	.id_table	= piix4_ids,
 	.probe		= piix4_probe,
 	.remove		= __devexit_p(piix4_remove),
diff -Nru a/drivers/i2c/busses/i2c-prosavage.c b/drivers/i2c/busses/i2c-prosavage.c
--- a/drivers/i2c/busses/i2c-prosavage.c	2004-10-18 14:56:28 -07:00
+++ b/drivers/i2c/busses/i2c-prosavage.c	2004-10-18 14:56:28 -07:00
@@ -314,7 +314,7 @@
 };
 
 static struct pci_driver prosavage_driver = {
-	.name		=	"prosavage-smbus",
+	.name		=	"prosavage_smbus",
 	.id_table	=	prosavage_pci_tbl,
 	.probe		=	prosavage_probe,
 	.remove		=	prosavage_remove,
diff -Nru a/drivers/i2c/busses/i2c-savage4.c b/drivers/i2c/busses/i2c-savage4.c
--- a/drivers/i2c/busses/i2c-savage4.c	2004-10-18 14:56:29 -07:00
+++ b/drivers/i2c/busses/i2c-savage4.c	2004-10-18 14:56:29 -07:00
@@ -178,7 +178,7 @@
 }
 
 static struct pci_driver savage4_driver = {
-	.name		= "savage4 smbus",
+	.name		= "savage4_smbus",
 	.id_table	= savage4_ids,
 	.probe		= savage4_probe,
 	.remove		= __devexit_p(savage4_remove),
diff -Nru a/drivers/i2c/busses/i2c-sis5595.c b/drivers/i2c/busses/i2c-sis5595.c
--- a/drivers/i2c/busses/i2c-sis5595.c	2004-10-18 14:56:28 -07:00
+++ b/drivers/i2c/busses/i2c-sis5595.c	2004-10-18 14:56:28 -07:00
@@ -124,8 +124,8 @@
 
 /* If force_addr is set to anything different from 0, we forcibly enable
    the device at the given address. */
-static int force_addr = 0;
-MODULE_PARM(force_addr, "i");
+static u16 force_addr = 0;
+module_param(force_addr, ushort, 0);
 MODULE_PARM_DESC(force_addr, "Initialize the base address of the i2c controller");
 
 static unsigned short sis5595_base = 0;
@@ -393,7 +393,7 @@
 }
 
 static struct pci_driver sis5595_driver = {
-	.name		= "sis5595 smbus",
+	.name		= "sis5595_smbus",
 	.id_table	= sis5595_ids,
 	.probe		= sis5595_probe,
 	.remove		= __devexit_p(sis5595_remove),
diff -Nru a/drivers/i2c/busses/i2c-sis630.c b/drivers/i2c/busses/i2c-sis630.c
--- a/drivers/i2c/busses/i2c-sis630.c	2004-10-18 14:56:27 -07:00
+++ b/drivers/i2c/busses/i2c-sis630.c	2004-10-18 14:56:27 -07:00
@@ -94,11 +94,11 @@
 #define SIS630_BLOCK_DATA	0x05
 
 /* insmod parameters */
-static int high_clock = 0;
-static int force = 0;
-MODULE_PARM(high_clock, "i");
+static int high_clock;
+static int force;
+module_param(high_clock, bool, 0);
 MODULE_PARM_DESC(high_clock, "Set Host Master Clock to 56KHz (default 14KHz).");
-MODULE_PARM(force, "i");
+module_param(force, bool, 0);
 MODULE_PARM_DESC(force, "Forcibly enable the SIS630. DANGEROUS!");
 
 /* acpi base address */
@@ -145,7 +145,7 @@
 	dev_dbg(&adap->dev, "saved clock 0x%02x\n", *oldclock);
 
 	/* disable timeout interrupt , set Host Master Clock to 56KHz if requested */
-	if (high_clock > 0)
+	if (high_clock)
 		sis630_write(SMB_CNT, 0x20);
 	else
 		sis630_write(SMB_CNT, (*oldclock & ~0x40));
@@ -210,7 +210,7 @@
 	 * restore old Host Master Clock if high_clock is set
 	 * and oldclock was not 56KHz
 	 */
-	if (high_clock > 0 && !(oldclock & 0x20))
+	if (high_clock && !(oldclock & 0x20))
 		sis630_write(SMB_CNT,(sis630_read(SMB_CNT) & ~0x20));
 
 	dev_dbg(&adap->dev, "SMB_CNT after clock restore 0x%02x\n", sis630_read(SMB_CNT));
@@ -401,7 +401,7 @@
 	if (dummy) {
 		pci_dev_put(dummy);
 	}
-        else if (force > 0) {
+        else if (force) {
 		dev_err(&sis630_dev->dev, "WARNING: Can't detect SIS630 compatible device, but "
 			"loading because of force option enabled\n");
  	}
@@ -464,6 +464,7 @@
 
 static struct pci_device_id sis630_ids[] __devinitdata = {
 	{ PCI_DEVICE(PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_503) },
+	{ PCI_DEVICE(PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_LPC) },
 	{ 0, }
 };
 
@@ -494,7 +495,7 @@
 
 
 static struct pci_driver sis630_driver = {
-	.name		= "sis630 smbus",
+	.name		= "sis630_smbus",
 	.id_table	= sis630_ids,
 	.probe		= sis630_probe,
 	.remove		= __devexit_p(sis630_remove),
diff -Nru a/drivers/i2c/busses/i2c-sis96x.c b/drivers/i2c/busses/i2c-sis96x.c
--- a/drivers/i2c/busses/i2c-sis96x.c	2004-10-18 14:56:28 -07:00
+++ b/drivers/i2c/busses/i2c-sis96x.c	2004-10-18 14:56:28 -07:00
@@ -339,7 +339,7 @@
 }
 
 static struct pci_driver sis96x_driver = {
-	.name		= "sis96x smbus",
+	.name		= "sis96x_smbus",
 	.id_table	= sis96x_ids,
 	.probe		= sis96x_probe,
 	.remove		= __devexit_p(sis96x_remove),
diff -Nru a/drivers/i2c/busses/i2c-via.c b/drivers/i2c/busses/i2c-via.c
--- a/drivers/i2c/busses/i2c-via.c	2004-10-18 14:56:32 -07:00
+++ b/drivers/i2c/busses/i2c-via.c	2004-10-18 14:56:32 -07:00
@@ -158,7 +158,7 @@
 
 
 static struct pci_driver vt586b_driver = {
-	.name		= "vt586b smbus",
+	.name		= "vt586b_smbus",
 	.id_table	= vt586b_ids,
 	.probe		= vt586b_probe,
 	.remove		= __devexit_p(vt586b_remove),
diff -Nru a/drivers/i2c/busses/i2c-viapro.c b/drivers/i2c/busses/i2c-viapro.c
--- a/drivers/i2c/busses/i2c-viapro.c	2004-10-18 14:56:49 -07:00
+++ b/drivers/i2c/busses/i2c-viapro.c	2004-10-18 14:56:49 -07:00
@@ -92,13 +92,13 @@
 /* If force is set to anything different from 0, we forcibly enable the
    VT596. DANGEROUS! */
 static int force;
-MODULE_PARM(force, "i");
+module_param(force, bool, 0);
 MODULE_PARM_DESC(force, "Forcibly enable the SMBus. DANGEROUS!");
 
 /* If force_addr is set to anything different from 0, we forcibly enable
    the VT596 at the given address. VERY DANGEROUS! */
-static int force_addr;
-MODULE_PARM(force_addr, "i");
+static u16 force_addr;
+module_param(force_addr, ushort, 0);
 MODULE_PARM_DESC(force_addr,
 		 "Forcibly enable the SMBus at the given address. "
 		 "EXTREMELY DANGEROUS!");
@@ -455,7 +455,7 @@
 };
 
 static struct pci_driver vt596_driver = {
-	.name		= "vt596 smbus",
+	.name		= "vt596_smbus",
 	.id_table	= vt596_ids,
 	.probe		= vt596_probe,
 	.remove		= __devexit_p(vt596_remove),
diff -Nru a/drivers/i2c/busses/i2c-voodoo3.c b/drivers/i2c/busses/i2c-voodoo3.c
--- a/drivers/i2c/busses/i2c-voodoo3.c	2004-10-18 14:56:29 -07:00
+++ b/drivers/i2c/busses/i2c-voodoo3.c	2004-10-18 14:56:29 -07:00
@@ -224,7 +224,7 @@
 }
 
 static struct pci_driver voodoo3_driver = {
-	.name		= "voodoo3 smbus",
+	.name		= "voodoo3_smbus",
 	.id_table	= voodoo3_ids,
 	.probe		= voodoo3_probe,
 	.remove		= __devexit_p(voodoo3_remove),
diff -Nru a/drivers/i2c/busses/scx200_acb.c b/drivers/i2c/busses/scx200_acb.c
--- a/drivers/i2c/busses/scx200_acb.c	2004-10-18 14:56:31 -07:00
+++ b/drivers/i2c/busses/scx200_acb.c	2004-10-18 14:56:31 -07:00
@@ -32,6 +32,7 @@
 #include <linux/i2c.h>
 #include <linux/smp_lock.h>
 #include <linux/pci.h>
+#include <linux/delay.h>
 #include <asm/io.h>
 
 #include <linux/scx200.h>
@@ -44,7 +45,8 @@
 
 #define MAX_DEVICES 4
 static int base[MAX_DEVICES] = { 0x820, 0x840 };
-MODULE_PARM(base, "1-4i");
+static int num_base;
+module_param_array(base, int, num_base, 0);
 MODULE_PARM_DESC(base, "Base addresses for the ACCESS.bus controllers");
 
 #ifdef DEBUG
@@ -254,7 +256,7 @@
 			scx200_acb_machine(iface, status);
 			return;
 		}
-		schedule_timeout(HZ/100+1);
+		msleep(10);
 	}
 
 	scx200_acb_timeout(iface);
diff -Nru a/drivers/i2c/busses/scx200_i2c.c b/drivers/i2c/busses/scx200_i2c.c
--- a/drivers/i2c/busses/scx200_i2c.c	2004-10-18 14:56:29 -07:00
+++ b/drivers/i2c/busses/scx200_i2c.c	2004-10-18 14:56:29 -07:00
@@ -38,13 +38,13 @@
 MODULE_DESCRIPTION("NatSemi SCx200 I2C Driver");
 MODULE_LICENSE("GPL");
 
-MODULE_PARM(scl, "i");
-MODULE_PARM_DESC(scl, "GPIO line for SCL");
-MODULE_PARM(sda, "i");
-MODULE_PARM_DESC(sda, "GPIO line for SDA");
-
 static int scl = CONFIG_SCx200_I2C_SCL;
 static int sda = CONFIG_SCx200_I2C_SDA;
+
+module_param(scl, int, 0);
+MODULE_PARM_DESC(scl, "GPIO line for SCL");
+module_param(sda, int, 0);
+MODULE_PARM_DESC(sda, "GPIO line for SDA");
 
 static void scx200_i2c_setscl(void *data, int state)
 {
diff -Nru a/drivers/i2c/chips/Kconfig b/drivers/i2c/chips/Kconfig
--- a/drivers/i2c/chips/Kconfig	2004-10-18 14:56:32 -07:00
+++ b/drivers/i2c/chips/Kconfig	2004-10-18 14:56:32 -07:00
@@ -149,7 +149,7 @@
 
 config SENSORS_LM83
 	tristate "National Semiconductor LM83"
-	depends on I2C && EXPERIMENTAL
+	depends on I2C
 	select I2C_SENSOR
 	help
 	  If you say yes here you get support for National Semiconductor
@@ -191,6 +191,19 @@
 	  This driver can also be built as a module.  If so, the module
 	  will be called max1619.
 
+config SENSORS_SMSC47M1
+	tristate "SMSC LPC47M10x and compatibles"
+	depends on I2C && EXPERIMENTAL
+	select I2C_SENSOR
+	select I2C_ISA
+	help
+	  If you say yes here you get support for the integrated fan
+	  monitoring and control capabilities of the SMSC LPC47B27x,
+	  LPC47M10x, LPC47M13x and LPC47M14x chips.
+
+	  This driver can also be built as a module.  If so, the module
+	  will be called smsc47m1.
+
 config SENSORS_VIA686A
 	tristate "VIA686A"
 	depends on I2C && PCI && EXPERIMENTAL
@@ -285,5 +298,17 @@
 
 	  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-10-18 14:57:19 -07:00
+++ b/drivers/i2c/chips/Makefile	2004-10-18 14:57:19 -07:00
@@ -26,9 +26,12 @@
 obj-$(CONFIG_SENSORS_PCF8574)	+= pcf8574.o
 obj-$(CONFIG_SENSORS_PCF8591)	+= pcf8591.o
 obj-$(CONFIG_SENSORS_RTC8564)	+= rtc8564.o
+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/adm1021.c b/drivers/i2c/chips/adm1021.c
--- a/drivers/i2c/chips/adm1021.c	2004-10-18 14:55:54 -07:00
+++ b/drivers/i2c/chips/adm1021.c	2004-10-18 14:55:54 -07:00
@@ -418,7 +418,7 @@
 MODULE_DESCRIPTION("adm1021 driver");
 MODULE_LICENSE("GPL");
 
-MODULE_PARM(read_only, "i");
+module_param(read_only, bool, 0);
 MODULE_PARM_DESC(read_only, "Don't set any values, read only mode");
 
 module_init(sensors_adm1021_init)
diff -Nru a/drivers/i2c/chips/adm1025.c b/drivers/i2c/chips/adm1025.c
--- a/drivers/i2c/chips/adm1025.c	2004-10-18 14:55:46 -07:00
+++ b/drivers/i2c/chips/adm1025.c	2004-10-18 14:55:46 -07:00
@@ -455,7 +455,7 @@
 	struct adm1025_data *data = i2c_get_clientdata(client);
 	int i;
 
-	data->vrm = 82;
+	data->vrm = i2c_which_vrm();
 
 	/*
 	 * Set high limits
diff -Nru a/drivers/i2c/chips/asb100.c b/drivers/i2c/chips/asb100.c
--- a/drivers/i2c/chips/asb100.c	2004-10-18 14:56:32 -07:00
+++ b/drivers/i2c/chips/asb100.c	2004-10-18 14:56:32 -07:00
@@ -63,9 +63,6 @@
 static unsigned int normal_isa[] = { I2C_CLIENT_ISA_END };
 static unsigned int normal_isa_range[] = { I2C_CLIENT_ISA_END };
 
-/* default VRM to 9.0 instead of 8.2 */
-#define ASB100_DEFAULT_VRM 90
-
 /* Insmod parameters */
 SENSORS_INSMOD_1(asb100);
 I2C_CLIENT_MODULE_PARM(force_subclients, "List of subclient addresses: "
@@ -523,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)
@@ -959,7 +956,7 @@
 
 	vid = asb100_read_value(client, ASB100_REG_VID_FANDIV) & 0x0f;
 	vid |= (asb100_read_value(client, ASB100_REG_CHIPID) & 0x01) << 4;
-	data->vrm = ASB100_DEFAULT_VRM;
+	data->vrm = i2c_which_vrm();
 	vid = vid_from_reg(vid, data->vrm);
 
 	/* Start monitoring */
diff -Nru a/drivers/i2c/chips/ds1621.c b/drivers/i2c/chips/ds1621.c
--- a/drivers/i2c/chips/ds1621.c	2004-10-18 14:57:04 -07:00
+++ b/drivers/i2c/chips/ds1621.c	2004-10-18 14:57:04 -07:00
@@ -37,7 +37,7 @@
 /* Insmod parameters */
 SENSORS_INSMOD_1(ds1621);
 static int polarity = -1;
-MODULE_PARM(polarity, "i");
+module_param(polarity, int, 0);
 MODULE_PARM_DESC(polarity, "Output's polarity: 0 = active high, 1 = active low");
 
 /* Many DS1621 constants specified below */
diff -Nru a/drivers/i2c/chips/eeprom.c b/drivers/i2c/chips/eeprom.c
--- a/drivers/i2c/chips/eeprom.c	2004-10-18 14:56:28 -07:00
+++ b/drivers/i2c/chips/eeprom.c	2004-10-18 14:56:28 -07:00
@@ -45,7 +45,7 @@
 SENSORS_INSMOD_1(eeprom);
 
 static int checksum = 0;
-MODULE_PARM(checksum, "i");
+module_param(checksum, bool, 0);
 MODULE_PARM_DESC(checksum, "Only accept eeproms whose checksum is correct");
 
 
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-10-18 14:57:24 -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-10-18 14:56:49 -07:00
+++ b/drivers/i2c/chips/it87.c	2004-10-18 14:56:49 -07:00
@@ -37,6 +37,7 @@
 #include <linux/slab.h>
 #include <linux/i2c.h>
 #include <linux/i2c-sensor.h>
+#include <linux/i2c-vid.h>
 #include <asm/io.h>
 
 
@@ -47,7 +48,7 @@
 static unsigned int normal_isa_range[] = { I2C_CLIENT_ISA_END };
 
 /* Insmod parameters */
-SENSORS_INSMOD_1(it87);
+SENSORS_INSMOD_2(it87, it8712);
 
 #define	REG	0x2e	/* The register to read/write */
 #define	DEV	0x07	/* Register: Logical device select */
@@ -163,8 +164,6 @@
 					((val)+500)/1000),-128,127))
 #define TEMP_FROM_REG(val) (((val)>0x80?(val)-0x100:(val))*1000)
 
-#define VID_FROM_REG(val) ((val)==0x1f?0:(val)>=0x10?510-(val)*10:\
-				205-(val)*5)
 #define ALARMS_FROM_REG(val) (val)
 
 static int DIV_TO_REG(int val)
@@ -201,6 +200,7 @@
 	u8 sensor;		/* Register value */
 	u8 fan_div[3];		/* Register encoding, shifted right */
 	u8 vid;			/* Register encoding, combined */
+	int vrm;
 	u32 alarms;		/* Register encoding, combined */
 };
 
@@ -543,6 +543,38 @@
 }
 static DEVICE_ATTR(alarms, S_IRUGO | S_IWUSR, show_alarms, NULL);
 
+static ssize_t
+show_vrm_reg(struct device *dev, char *buf)
+{
+	struct it87_data *data = it87_update_device(dev);
+	return sprintf(buf, "%ld\n", (long) data->vrm);
+}
+static ssize_t
+store_vrm_reg(struct device *dev, const char *buf, size_t count)
+{
+	struct i2c_client *client = to_i2c_client(dev);
+	struct it87_data *data = i2c_get_clientdata(client);
+	u32 val;
+
+	val = simple_strtoul(buf, NULL, 10);
+	data->vrm = val;
+
+	return count;
+}
+static DEVICE_ATTR(vrm, S_IRUGO | S_IWUSR, show_vrm_reg, store_vrm_reg);
+#define device_create_file_vrm(client) \
+device_create_file(&client->dev, &dev_attr_vrm)
+
+static ssize_t
+show_vid_reg(struct device *dev, char *buf)
+{
+	struct it87_data *data = it87_update_device(dev);
+	return sprintf(buf, "%ld\n", (long) vid_from_reg(data->vid, data->vrm));
+}
+static DEVICE_ATTR(cpu0_vid, S_IRUGO, show_vid_reg, NULL);
+#define device_create_file_vid(client) \
+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
        available adapter
@@ -659,7 +691,11 @@
 	if (kind <= 0) {
 		i = it87_read_value(new_client, IT87_REG_CHIPID);
 		if (i == 0x90) {
+			u16 val;
 			kind = it87;
+			val = (superio_inb(DEVID) << 8) |
+			superio_inb(DEVID + 1);
+			if (val == IT8712F_DEVID) kind = it8712;
 		}
 		else {
 			if (kind == 0)
@@ -674,6 +710,8 @@
 
 	if (kind == it87) {
 		name = "it87";
+	} else if (kind == it8712) {
+		name = "it8712";
 	}
 
 	/* Fill in the remaining client fields and put it into the global list */
@@ -741,6 +779,12 @@
 	device_create_file(&new_client->dev, &dev_attr_fan3_div);
 	device_create_file(&new_client->dev, &dev_attr_alarms);
 
+	if (data->type == it8712) {
+		device_create_file_vrm(new_client);
+		device_create_file_vid(new_client);
+		data->vrm = i2c_which_vrm();
+	}
+
 	return 0;
 
 ERROR2:
@@ -910,7 +954,11 @@
 			(it87_read_value(client, IT87_REG_ALARM3) << 16);
 
 		data->sensor = it87_read_value(client, IT87_REG_TEMP_ENABLE);
-
+		/* The 8705 does not have VID capability */
+		if (data->type == it8712) {
+			data->vid = it87_read_value(client, IT87_REG_VID);
+			data->vid &= 0x1f;
+		}
 		data->last_updated = jiffies;
 		data->valid = 1;
 	}
@@ -938,9 +986,9 @@
 
 MODULE_AUTHOR("Chris Gauthron <chrisg@0-in.com>");
 MODULE_DESCRIPTION("IT8705F, IT8712F, Sis950 driver");
-MODULE_PARM(update_vbat, "i");
+module_param(update_vbat, bool, 0);
 MODULE_PARM_DESC(update_vbat, "Update vbat if set else return powerup value");
-MODULE_PARM(reset, "i");
+module_param(reset, bool, 0);
 MODULE_PARM_DESC(reset, "Reset the chip's registers, default no");
 MODULE_LICENSE("GPL");
 
diff -Nru a/drivers/i2c/chips/lm78.c b/drivers/i2c/chips/lm78.c
--- a/drivers/i2c/chips/lm78.c	2004-10-18 14:56:49 -07:00
+++ b/drivers/i2c/chips/lm78.c	2004-10-18 14:56:49 -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/lm83.c b/drivers/i2c/chips/lm83.c
--- a/drivers/i2c/chips/lm83.c	2004-10-18 14:56:29 -07:00
+++ b/drivers/i2c/chips/lm83.c	2004-10-18 14:56:29 -07:00
@@ -83,8 +83,10 @@
  * The LM83 uses signed 8-bit values.
  */
 
-#define TEMP_FROM_REG(val)	((val > 127 ? val-256 : val) * 1000)
-#define TEMP_TO_REG(val)	((val < 0 ? val+256 : val) / 1000)
+#define TEMP_FROM_REG(val)	(((val) > 127 ? (val) - 0x100 : (val)) * 1000)
+#define TEMP_TO_REG(val)	((val) <= -50000 ? -50 + 0x100 : (val) >= 127000 ? 127 : \
+				 (val) > -500 ? ((val)+500) / 1000 : \
+				 ((val)-500) / 1000 + 0x100)
 
 static const u8 LM83_REG_R_TEMP[] = {
 	LM83_REG_R_LOCAL_TEMP,
@@ -178,7 +180,7 @@
 { \
 	struct i2c_client *client = to_i2c_client(dev); \
 	struct lm83_data *data = i2c_get_clientdata(client); \
-	data->value = TEMP_TO_REG(simple_strtoul(buf, NULL, 10)); \
+	data->value = TEMP_TO_REG(simple_strtol(buf, NULL, 10)); \
 	i2c_smbus_write_byte_data(client, reg, data->value); \
 	return count; \
 }
@@ -206,8 +208,11 @@
     set_temp_high3);
 static DEVICE_ATTR(temp4_max, S_IWUSR | S_IRUGO, show_temp_high4,
     set_temp_high4);
-static DEVICE_ATTR(temp_crit, S_IWUSR | S_IRUGO, show_temp_crit,
+static DEVICE_ATTR(temp1_crit, S_IRUGO, show_temp_crit, NULL);
+static DEVICE_ATTR(temp2_crit, S_IRUGO, show_temp_crit, NULL);
+static DEVICE_ATTR(temp3_crit, S_IWUSR | S_IRUGO, show_temp_crit,
     set_temp_crit);
+static DEVICE_ATTR(temp4_crit, S_IRUGO, show_temp_crit, NULL);
 static DEVICE_ATTR(alarms, S_IRUGO, show_alarms, NULL);
 
 /*
@@ -259,6 +264,11 @@
 	 * means that the driver was loaded with the force parameter and a
 	 * given kind of chip is requested, so both the detection and the
 	 * identification steps are skipped. */
+
+	/* Default to an LM83 if forced */
+	if (kind == 0)
+		kind = lm83;
+
 	if (kind < 0) { /* detection */
 		if (((i2c_smbus_read_byte_data(new_client, LM83_REG_R_STATUS1)
 		    & 0xA8) != 0x00) ||
@@ -322,7 +332,10 @@
 	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_temp4_max);
-	device_create_file(&new_client->dev, &dev_attr_temp_crit);
+	device_create_file(&new_client->dev, &dev_attr_temp1_crit);
+	device_create_file(&new_client->dev, &dev_attr_temp2_crit);
+	device_create_file(&new_client->dev, &dev_attr_temp3_crit);
+	device_create_file(&new_client->dev, &dev_attr_temp4_crit);
 	device_create_file(&new_client->dev, &dev_attr_alarms);
 
 	return 0;
diff -Nru a/drivers/i2c/chips/lm85.c b/drivers/i2c/chips/lm85.c
--- a/drivers/i2c/chips/lm85.c	2004-10-18 14:56:28 -07:00
+++ b/drivers/i2c/chips/lm85.c	2004-10-18 14:56:28 -07:00
@@ -308,9 +308,6 @@
  * version of the driver.
  */
 
-/* Typically used with Pentium 4 systems v9.1 VRM spec */
-#define LM85_INIT_VRM  91
-
 /* Chip sampling rates
  *
  * Some sensors are not updated more frequently than once per second
@@ -468,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)
 {
@@ -832,7 +829,7 @@
 		goto ERROR1;
 
 	/* Set the VRM version */
-	data->vrm = LM85_INIT_VRM ;
+	data->vrm = i2c_which_vrm();
 
 	/* Initialize the LM85 chip */
 	lm85_init_client(new_client);
@@ -877,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/pcf8591.c b/drivers/i2c/chips/pcf8591.c
--- a/drivers/i2c/chips/pcf8591.c	2004-10-18 14:57:19 -07:00
+++ b/drivers/i2c/chips/pcf8591.c	2004-10-18 14:57:19 -07:00
@@ -36,7 +36,7 @@
 SENSORS_INSMOD_1(pcf8591);
 
 static int input_mode;
-MODULE_PARM(input_mode, "i");
+module_param(input_mode, int, 0);
 MODULE_PARM_DESC(input_mode,
 	"Analog input mode:\n"
 	" 0 = four single ended inputs\n"
diff -Nru a/drivers/i2c/chips/rtc8564.c b/drivers/i2c/chips/rtc8564.c
--- a/drivers/i2c/chips/rtc8564.c	2004-10-18 14:55:54 -07:00
+++ b/drivers/i2c/chips/rtc8564.c	2004-10-18 14:55:54 -07:00
@@ -56,8 +56,8 @@
 #define BCD_TO_BIN(val) (((val)&15) + ((val)>>4)*10)
 #define BIN_TO_BCD(val) ((((val)/10)<<4) + (val)%10)
 
-static int debug = 0;
-MODULE_PARM(debug, "i");
+static int debug;;
+module_param(debug, int, S_IRUGO | S_IWUSR);
 
 static struct i2c_driver rtc8564_driver;
 
diff -Nru a/drivers/i2c/chips/smsc47m1.c b/drivers/i2c/chips/smsc47m1.c
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/drivers/i2c/chips/smsc47m1.c	2004-10-18 14:57:23 -07:00
@@ -0,0 +1,579 @@
+/*
+    smsc47m1.c - Part of lm_sensors, Linux kernel modules
+                 for hardware monitoring
+
+    Supports the SMSC LPC47B27x, LPC47M10x, LPC47M13x and LPC47M14x
+    Super-I/O chips.
+
+    Copyright (C) 2002 Mark D. Studebaker <mdsxyz123@yahoo.com>
+    Copyright (C) 2004 Jean Delvare <khali@linux-fr.org>
+    Ported to Linux 2.6 by Gabriele Gorla <gorlik@yahoo.com>
+                        and Jean Delvare
+
+    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.
+*/
+
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/ioport.h>
+#include <linux/i2c.h>
+#include <linux/i2c-sensor.h>
+#include <linux/init.h>
+#include <asm/io.h>
+
+static unsigned short normal_i2c[] = { I2C_CLIENT_END };
+static unsigned short normal_i2c_range[] = { I2C_CLIENT_END };
+/* Address is autodetected, there is no default value */
+static unsigned int normal_isa[] = { 0x0000, I2C_CLIENT_ISA_END };
+static unsigned int normal_isa_range[] = { I2C_CLIENT_ISA_END };
+static struct i2c_force_data forces[] = {{NULL}};
+
+enum chips { any_chip, smsc47m1 };
+static struct i2c_address_data addr_data = {
+	.normal_i2c		= normal_i2c,
+	.normal_i2c_range	= normal_i2c_range,
+	.normal_isa		= normal_isa,
+	.normal_isa_range	= normal_isa_range,
+	.probe			= normal_i2c,		/* cheat */
+	.probe_range		= normal_i2c_range,	/* cheat */
+	.ignore			= normal_i2c,		/* cheat */
+	.ignore_range		= normal_i2c_range,	/* cheat */
+	.forces			= forces,
+};
+
+/* Super-I/0 registers and commands */
+
+#define	REG	0x2e	/* The register to read/write */
+#define	VAL	0x2f	/* The value to read/write */
+
+static inline void
+superio_outb(int reg, int val)
+{
+	outb(reg, REG);
+	outb(val, VAL);
+}
+
+static inline int
+superio_inb(int reg)
+{
+	outb(reg, REG);
+	return inb(VAL);
+}
+
+/* logical device for fans is 0x0A */
+#define superio_select() superio_outb(0x07, 0x0A)
+
+static inline void
+superio_enter(void)
+{
+	outb(0x55, REG);
+}
+
+static inline void
+superio_exit(void)
+{
+	outb(0xAA, REG);
+}
+
+#define SUPERIO_REG_ACT		0x30
+#define SUPERIO_REG_BASE	0x60
+#define SUPERIO_REG_DEVID	0x20
+
+/* Logical device registers */
+
+#define SMSC_EXTENT		0x80
+
+/* nr is 0 or 1 in the macros below */
+#define SMSC47M1_REG_ALARM		0x04
+#define SMSC47M1_REG_TPIN(nr)		(0x34 - (nr))
+#define SMSC47M1_REG_PPIN(nr)		(0x36 - (nr))
+#define SMSC47M1_REG_PWM(nr)		(0x56 + (nr))
+#define SMSC47M1_REG_FANDIV		0x58
+#define SMSC47M1_REG_FAN(nr)		(0x59 + (nr))
+#define SMSC47M1_REG_FAN_PRELOAD(nr)	(0x5B + (nr))
+
+#define MIN_FROM_REG(reg,div)		((reg)>=192 ? 0 : \
+					 983040/((192-(reg))*(div)))
+#define FAN_FROM_REG(reg,div,preload)	((reg)<=(preload) || (reg)==255 ? 0 : \
+					 983040/(((reg)-(preload))*(div)))
+#define DIV_FROM_REG(reg)		(1 << (reg))
+#define PWM_FROM_REG(reg)		(((reg) & 0x7E) << 1)
+#define PWM_EN_FROM_REG(reg)		((~(reg)) & 0x01)
+#define PWM_TO_REG(reg)			(((reg) >> 1) & 0x7E)
+
+struct smsc47m1_data {
+	struct i2c_client client;
+	struct semaphore lock;
+	int sysctl_id;
+
+	struct semaphore update_lock;
+	unsigned long last_updated;	/* In jiffies */
+
+	u8 fan[2];		/* Register value */
+	u8 fan_preload[2];	/* Register value */
+	u8 fan_div[2];		/* Register encoding, shifted right */
+	u8 alarms;		/* Register encoding */
+	u8 pwm[2];		/* Register value (bit 7 is enable) */
+};
+
+
+static int smsc47m1_attach_adapter(struct i2c_adapter *adapter);
+static int smsc47m1_find(int *address);
+static int smsc47m1_detect(struct i2c_adapter *adapter, int address, int kind);
+static int smsc47m1_detach_client(struct i2c_client *client);
+
+static int smsc47m1_read_value(struct i2c_client *client, u8 reg);
+static void smsc47m1_write_value(struct i2c_client *client, u8 reg, u8 value);
+
+static struct smsc47m1_data *smsc47m1_update_device(struct device *dev,
+		int init);
+
+
+static int smsc47m1_id;
+
+static struct i2c_driver smsc47m1_driver = {
+	.owner		= THIS_MODULE,
+	.name		= "smsc47m1",
+	.id		= I2C_DRIVERID_SMSC47M1,
+	.flags		= I2C_DF_NOTIFY,
+	.attach_adapter	= smsc47m1_attach_adapter,
+	.detach_client	= smsc47m1_detach_client,
+};
+
+/* nr is 0 or 1 in the callback functions below */
+
+static ssize_t get_fan(struct device *dev, char *buf, int nr)
+{
+	struct smsc47m1_data *data = smsc47m1_update_device(dev, 0);
+	/* This chip (stupidly) stops monitoring fan speed if PWM is
+	   enabled and duty cycle is 0%. This is fine if the monitoring
+	   and control concern the same fan, but troublesome if they are
+	   not (which could as well happen). */
+	int rpm = (data->pwm[nr] & 0x7F) == 0x00 ? 0 :
+		  FAN_FROM_REG(data->fan[nr],
+			       DIV_FROM_REG(data->fan_div[nr]),
+			       data->fan_preload[nr]);
+	return sprintf(buf, "%d\n", rpm);
+}
+
+static ssize_t get_fan_min(struct device *dev, char *buf, int nr)
+{
+	struct smsc47m1_data *data = smsc47m1_update_device(dev, 0);
+	int rpm = MIN_FROM_REG(data->fan_preload[nr],
+			       DIV_FROM_REG(data->fan_div[nr]));
+	return sprintf(buf, "%d\n", rpm);
+}
+
+static ssize_t get_fan_div(struct device *dev, char *buf, int nr)
+{
+	struct smsc47m1_data *data = smsc47m1_update_device(dev, 0);
+	return sprintf(buf, "%d\n", DIV_FROM_REG(data->fan_div[nr]));
+}
+
+static ssize_t get_fan_pwm(struct device *dev, char *buf, int nr)
+{
+	struct smsc47m1_data *data = smsc47m1_update_device(dev, 0);
+	return sprintf(buf, "%d\n", PWM_FROM_REG(data->pwm[nr]));
+}
+
+static ssize_t get_fan_pwm_en(struct device *dev, char *buf, int nr)
+{
+	struct smsc47m1_data *data = smsc47m1_update_device(dev, 0);
+	return sprintf(buf, "%d\n", PWM_EN_FROM_REG(data->pwm[nr]));
+}
+
+static ssize_t get_alarms(struct device *dev, char *buf)
+{
+	struct smsc47m1_data *data = smsc47m1_update_device(dev, 0);
+	return sprintf(buf, "%d\n", data->alarms);
+}
+
+static ssize_t set_fan_min(struct device *dev, const char *buf,
+		size_t count, int nr)
+{
+	struct i2c_client *client = to_i2c_client(dev);
+	struct smsc47m1_data *data = i2c_get_clientdata(client);
+
+	long rpmdiv = simple_strtol(buf, NULL, 10)
+		    * DIV_FROM_REG(data->fan_div[nr]);
+
+	if (983040 > 192 * rpmdiv || 2 * rpmdiv > 983040)
+		return -EINVAL;
+
+	data->fan_preload[nr] = 192 - ((983040 + rpmdiv / 2) / rpmdiv);
+	smsc47m1_write_value(client, SMSC47M1_REG_FAN_PRELOAD(nr),
+			     data->fan_preload[nr]);
+
+	return count;
+}
+
+/* Note: we save and restore the fan minimum here, because its value is
+   determined in part by the fan clock divider.  This follows the principle
+   of least suprise; the user doesn't expect the fan minimum to change just
+   because the divider changed. */
+static ssize_t set_fan_div(struct device *dev, const char *buf,
+		size_t count, int nr)
+{
+	struct i2c_client *client = to_i2c_client(dev);
+	struct smsc47m1_data *data = i2c_get_clientdata(client);
+
+	long new_div = simple_strtol(buf, NULL, 10), tmp;
+	u8 old_div = DIV_FROM_REG(data->fan_div[nr]);
+
+	if (new_div == old_div) /* No change */
+		return count;
+	switch (new_div) {
+	case 1: data->fan_div[nr] = 0; break;
+	case 2: data->fan_div[nr] = 1; break;
+	case 4: data->fan_div[nr] = 2; break;
+	case 8: data->fan_div[nr] = 3; break;
+	default: return -EINVAL;
+	}
+
+	tmp = smsc47m1_read_value(client, SMSC47M1_REG_FANDIV) & 0x0F;
+	tmp |= (data->fan_div[0] << 4) | (data->fan_div[1] << 6);
+	smsc47m1_write_value(client, SMSC47M1_REG_FANDIV, tmp);
+
+	/* Preserve fan min */
+	tmp = 192 - (old_div * (192 - data->fan_preload[nr])
+		     + new_div / 2) / new_div;
+	data->fan_preload[nr] = SENSORS_LIMIT(tmp, 0, 191);
+	smsc47m1_write_value(client, SMSC47M1_REG_FAN_PRELOAD(nr),
+			     data->fan_preload[nr]);
+
+	return count;
+}
+
+static ssize_t set_fan_pwm(struct device *dev, const char *buf,
+		size_t count, int nr)
+{
+	struct i2c_client *client = to_i2c_client(dev);
+	struct smsc47m1_data *data = i2c_get_clientdata(client);
+
+	long val = simple_strtol(buf, NULL, 10);
+
+	if (val < 0 || val > 255)
+		return -EINVAL;
+
+	data->pwm[nr] &= 0x81; /* Preserve additional bits */
+	data->pwm[nr] |= PWM_TO_REG(val);
+
+	smsc47m1_write_value(client, SMSC47M1_REG_PWM(nr),
+			     data->pwm[nr]);
+	return count;
+}
+
+static ssize_t set_fan_pwm_en(struct device *dev, const char *buf,
+		size_t count, int nr)
+{
+	struct i2c_client *client = to_i2c_client(dev);
+	struct smsc47m1_data *data = i2c_get_clientdata(client);
+
+	long val = simple_strtol(buf, NULL, 10);
+	
+	if (val != 0 && val != 1)
+		return -EINVAL;
+
+	data->pwm[nr] &= 0xFE; /* preserve the other bits */
+	data->pwm[nr] |= !val;
+
+	smsc47m1_write_value(client, SMSC47M1_REG_PWM(nr),
+			     data->pwm[nr]);
+
+	return count;
+}
+
+#define fan_present(offset)						\
+static ssize_t get_fan##offset (struct device *dev, char *buf)		\
+{									\
+	return get_fan(dev, buf, 0x##offset - 1);			\
+}									\
+static ssize_t get_fan##offset##_min (struct device *dev, char *buf)	\
+{									\
+	return get_fan_min(dev, buf, 0x##offset - 1);			\
+}									\
+static ssize_t set_fan##offset##_min (struct device *dev,		\
+		const char *buf, size_t count)				\
+{									\
+	return set_fan_min(dev, buf, count, 0x##offset - 1);		\
+}									\
+static ssize_t get_fan##offset##_div (struct device *dev, char *buf)	\
+{									\
+	return get_fan_div(dev, buf, 0x##offset - 1);			\
+}									\
+static ssize_t set_fan##offset##_div (struct device *dev,		\
+		const char *buf, size_t count)				\
+{									\
+	return set_fan_div(dev, buf, count, 0x##offset - 1);		\
+}									\
+static ssize_t get_fan##offset##_pwm (struct device *dev, char *buf)	\
+{									\
+	return get_fan_pwm(dev, buf, 0x##offset - 1);			\
+}									\
+static ssize_t set_fan##offset##_pwm (struct device *dev,		\
+		const char *buf, size_t count)				\
+{									\
+	return set_fan_pwm(dev, buf, count, 0x##offset - 1);		\
+}									\
+static ssize_t get_fan##offset##_pwm_en (struct device *dev, char *buf)	\
+{									\
+	return get_fan_pwm_en(dev, buf, 0x##offset - 1);		\
+}									\
+static ssize_t set_fan##offset##_pwm_en (struct device *dev,		\
+		const char *buf, size_t count)				\
+{									\
+	return set_fan_pwm_en(dev, buf, count, 0x##offset - 1);		\
+}									\
+static DEVICE_ATTR(fan##offset##_input, S_IRUGO, get_fan##offset,	\
+		NULL);							\
+static DEVICE_ATTR(fan##offset##_min, S_IRUGO | S_IWUSR,		\
+		get_fan##offset##_min, set_fan##offset##_min);		\
+static DEVICE_ATTR(fan##offset##_div, S_IRUGO | S_IWUSR,		\
+		get_fan##offset##_div, set_fan##offset##_div);		\
+static DEVICE_ATTR(fan##offset##_pwm, S_IRUGO | S_IWUSR,		\
+		get_fan##offset##_pwm, set_fan##offset##_pwm);		\
+static DEVICE_ATTR(fan##offset##_pwm_enable, S_IRUGO | S_IWUSR,		\
+		get_fan##offset##_pwm_en, set_fan##offset##_pwm_en);
+
+fan_present(1);
+fan_present(2);
+
+static DEVICE_ATTR(alarms, S_IRUGO, get_alarms, NULL);
+
+static int smsc47m1_attach_adapter(struct i2c_adapter *adapter)
+{
+	if (!(adapter->class & I2C_CLASS_HWMON))
+		return 0;
+	return i2c_detect(adapter, &addr_data, smsc47m1_detect);
+}
+
+static int smsc47m1_find(int *address)
+{
+	u8 val;
+
+	superio_enter();
+	val = superio_inb(SUPERIO_REG_DEVID);
+
+	/*
+	 * SMSC LPC47M10x/LPC47M13x (device id 0x59), LPC47M14x (device id
+	 * 0x5F) and LPC47B27x (device id 0x51) have fan control.
+	 * The LPC47M15x and LPC47M192 chips "with hardware monitoring block"
+	 * can do much more besides (device id 0x60, unsupported).
+	 */
+	if (val == 0x51)
+		printk(KERN_INFO "smsc47m1: Found SMSC47B27x\n");
+	else if (val == 0x59)
+		printk(KERN_INFO "smsc47m1: Found SMSC47M10x/SMSC47M13x\n");
+	else if (val == 0x5F)
+		printk(KERN_INFO "smsc47m1: Found SMSC47M14x\n");
+	else {
+		superio_exit();
+		return -ENODEV;
+	}
+
+	superio_select();
+	*address = (superio_inb(SUPERIO_REG_BASE) << 8)
+		 |  superio_inb(SUPERIO_REG_BASE + 1);
+	val = superio_inb(SUPERIO_REG_ACT);
+	if (*address == 0 || (val & 0x01) == 0) {
+		printk(KERN_INFO "smsc47m1: Device is disabled, will not use\n");
+		superio_exit();
+		return -ENODEV;
+	}
+
+	superio_exit();
+	return 0;
+}
+
+static int smsc47m1_detect(struct i2c_adapter *adapter, int address, int kind)
+{
+	struct i2c_client *new_client;
+	struct smsc47m1_data *data;
+	int err = 0;
+
+	if (!i2c_is_isa_adapter(adapter)) {
+		return 0;
+	}
+
+	if (!request_region(address, SMSC_EXTENT, "smsc47m1")) {
+		dev_err(&adapter->dev, "Region 0x%x already in use!\n", address);
+		return -EBUSY;
+	}
+
+	if (!(data = kmalloc(sizeof(struct smsc47m1_data), GFP_KERNEL))) {
+		err = -ENOMEM;
+		goto error_release;
+	}
+	memset(data, 0x00, sizeof(struct smsc47m1_data));
+
+	new_client = &data->client;
+	i2c_set_clientdata(new_client, data);
+	new_client->addr = address;
+	init_MUTEX(&data->lock);
+	new_client->adapter = adapter;
+	new_client->driver = &smsc47m1_driver;
+	new_client->flags = 0;
+
+	strlcpy(new_client->name, "smsc47m1", I2C_NAME_SIZE);
+
+	new_client->id = smsc47m1_id++;
+	init_MUTEX(&data->update_lock);
+
+	if ((err = i2c_attach_client(new_client)))
+		goto error_free;
+
+	/* Some values (fan min, clock dividers, pwm registers) may be
+	   needed before any update is triggered, so we better read them
+	   at least once here. We don't usually do it that way, but in
+	   this particular case, manually reading 5 registers out of 8
+	   doesn't make much sense and we're better using the existing
+	   function. */
+	smsc47m1_update_device(&new_client->dev, 1);
+
+	if ((smsc47m1_read_value(new_client, SMSC47M1_REG_TPIN(0)) & 0x05)
+	    == 0x05) {
+		device_create_file(&new_client->dev, &dev_attr_fan1_input);
+		device_create_file(&new_client->dev, &dev_attr_fan1_min);
+		device_create_file(&new_client->dev, &dev_attr_fan1_div);
+	} else
+		dev_dbg(&new_client->dev, "Fan 1 not enabled by hardware, "
+			"skipping\n");
+
+	if ((smsc47m1_read_value(new_client, SMSC47M1_REG_TPIN(1)) & 0x05)
+	    == 0x05) {
+		device_create_file(&new_client->dev, &dev_attr_fan2_input);
+		device_create_file(&new_client->dev, &dev_attr_fan2_min);
+		device_create_file(&new_client->dev, &dev_attr_fan2_div);
+	} else
+		dev_dbg(&new_client->dev, "Fan 2 not enabled by hardware, "
+			"skipping\n");
+
+	if ((smsc47m1_read_value(new_client, SMSC47M1_REG_PPIN(0)) & 0x05)
+	    == 0x04) {
+		device_create_file(&new_client->dev, &dev_attr_fan1_pwm);
+		device_create_file(&new_client->dev, &dev_attr_fan1_pwm_enable);
+	} else
+		dev_dbg(&new_client->dev, "PWM 1 not enabled by hardware, "
+			"skipping\n");
+	if ((smsc47m1_read_value(new_client, SMSC47M1_REG_PPIN(1)) & 0x05)
+	    == 0x04) {
+		device_create_file(&new_client->dev, &dev_attr_fan2_pwm);
+		device_create_file(&new_client->dev, &dev_attr_fan2_pwm_enable);
+	} else
+		dev_dbg(&new_client->dev, "PWM 2 not enabled by hardware, "
+			"skipping\n");
+
+	device_create_file(&new_client->dev, &dev_attr_alarms);
+
+	return 0;
+
+error_free:
+	kfree(new_client);
+error_release:
+	release_region(address, SMSC_EXTENT);
+	return err;
+}
+
+static int smsc47m1_detach_client(struct i2c_client *client)
+{
+	int err;
+
+	if ((err = i2c_detach_client(client))) {
+		dev_err(&client->dev, "Client deregistration failed, "
+			"client not detached.\n");
+		return err;
+	}
+
+	release_region(client->addr, SMSC_EXTENT);
+	kfree(i2c_get_clientdata(client));
+
+	return 0;
+}
+
+static int smsc47m1_read_value(struct i2c_client *client, u8 reg)
+{
+	int res;
+
+	down(&((struct smsc47m1_data *) i2c_get_clientdata(client))->lock);
+	res = inb_p(client->addr + reg);
+	up(&((struct smsc47m1_data *) i2c_get_clientdata(client))->lock);
+	return res;
+}
+
+static void smsc47m1_write_value(struct i2c_client *client, u8 reg, u8 value)
+{
+	down(&((struct smsc47m1_data *) i2c_get_clientdata(client))->lock);
+	outb_p(value, client->addr + reg);
+	up(&((struct smsc47m1_data *) i2c_get_clientdata(client))->lock);
+}
+
+static struct smsc47m1_data *smsc47m1_update_device(struct device *dev,
+		int init)
+{
+ 	struct i2c_client *client = to_i2c_client(dev);
+	struct smsc47m1_data *data = i2c_get_clientdata(client);
+
+	down(&data->update_lock);
+
+	if ((jiffies - data->last_updated > HZ + HZ / 2) ||
+	    (jiffies < data->last_updated) || init) {
+		int i;
+
+		for (i = 0; i < 2; i++) {
+			data->fan[i] = smsc47m1_read_value(client,
+				       SMSC47M1_REG_FAN(i));
+			data->fan_preload[i] = smsc47m1_read_value(client,
+					       SMSC47M1_REG_FAN_PRELOAD(i));
+			data->pwm[i] = smsc47m1_read_value(client,
+				       SMSC47M1_REG_PWM(i));
+		}
+
+		i = smsc47m1_read_value(client, SMSC47M1_REG_FANDIV);
+		data->fan_div[0] = (i >> 4) & 0x03;
+		data->fan_div[1] = i >> 6;
+
+		data->alarms = smsc47m1_read_value(client,
+			       SMSC47M1_REG_ALARM) >> 6;
+		/* Clear alarms if needed */
+		if (data->alarms)
+			smsc47m1_write_value(client, SMSC47M1_REG_ALARM, 0xC0);
+
+		data->last_updated = jiffies;
+	}
+
+	up(&data->update_lock);
+	return data;
+}
+
+static int __init sm_smsc47m1_init(void)
+{
+	if (smsc47m1_find(normal_isa)) {
+		return -ENODEV;
+	}
+
+	return i2c_add_driver(&smsc47m1_driver);
+}
+
+static void __exit sm_smsc47m1_exit(void)
+{
+	i2c_del_driver(&smsc47m1_driver);
+}
+
+MODULE_AUTHOR("Mark D. Studebaker <mdsxyz123@yahoo.com>");
+MODULE_DESCRIPTION("SMSC LPC47M1xx fan sensors driver");
+MODULE_LICENSE("GPL");
+
+module_init(sm_smsc47m1_init);
+module_exit(sm_smsc47m1_exit);
diff -Nru a/drivers/i2c/chips/via686a.c b/drivers/i2c/chips/via686a.c
--- a/drivers/i2c/chips/via686a.c	2004-10-18 14:55:55 -07:00
+++ b/drivers/i2c/chips/via686a.c	2004-10-18 14:55:55 -07:00
@@ -43,8 +43,8 @@
 
 /* If force_addr is set to anything different from 0, we forcibly enable
    the device at the given address. */
-static int force_addr = 0;
-MODULE_PARM(force_addr, "i");
+static unsigned short force_addr = 0;
+module_param(force_addr, ushort, 0);
 MODULE_PARM_DESC(force_addr,
 		 "Initialize the base address of the sensors");
 
diff -Nru a/drivers/i2c/chips/w83627hf.c b/drivers/i2c/chips/w83627hf.c
--- a/drivers/i2c/chips/w83627hf.c	2004-10-18 14:56:49 -07:00
+++ b/drivers/i2c/chips/w83627hf.c	2004-10-18 14:56:49 -07:00
@@ -46,12 +46,12 @@
 #include <asm/io.h>
 #include "lm75.h"
 
-static int force_addr;
-MODULE_PARM(force_addr, "i");
+static u16 force_addr;
+module_param(force_addr, ushort, 0);
 MODULE_PARM_DESC(force_addr,
 		 "Initialize the base address of the sensors");
-static int force_i2c = 0x1f;
-MODULE_PARM(force_i2c, "i");
+static u8 force_i2c = 0x1f;
+module_param(force_i2c, byte, 0);
 MODULE_PARM_DESC(force_i2c,
 		 "Initialize the i2c address of the sensors");
 
@@ -65,7 +65,7 @@
 SENSORS_INSMOD_4(w83627hf, w83627thf, w83697hf, w83637hf);
 
 static int init = 1;
-MODULE_PARM(init, "i");
+module_param(init, bool, 0);
 MODULE_PARM_DESC(init, "Set to zero to bypass chip initialization");
 
 /* modified from kernel/include/traps.c */
@@ -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)
@@ -1281,7 +1281,7 @@
 		data->vrm = (data->vrm_ovt & 0x01) ? 90 : 82;
 	} else {
 		/* Convert VID to voltage based on default VRM */
-		data->vrm = DEFAULT_VRM;
+		data->vrm = i2c_which_vrm();
 	}
 
 	tmp = w83627hf_read_value(client, W83781D_REG_SCFG1);
diff -Nru a/drivers/i2c/chips/w83781d.c b/drivers/i2c/chips/w83781d.c
--- a/drivers/i2c/chips/w83781d.c	2004-10-18 14:55:46 -07:00
+++ b/drivers/i2c/chips/w83781d.c	2004-10-18 14:55:46 -07:00
@@ -60,7 +60,7 @@
 		    "{bus, clientaddr, subclientaddr1, subclientaddr2}");
 
 static int init = 1;
-MODULE_PARM(init, "i");
+module_param(init, bool, 0);
 MODULE_PARM_DESC(init, "Set to zero to bypass chip initialization");
 
 /* Constants specified below */
@@ -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)
 {
@@ -815,8 +815,7 @@
 		data->sens[nr - 1] = val;
 		break;
 	default:
-		dev_err(&client->dev,
-		       "Invalid sensor type %ld; must be 1, 2, or %d\n",
+		dev_err(dev, "Invalid sensor type %ld; must be 1, 2, or %d\n",
 		       (long) val, W83781D_DEFAULT_BETA);
 		break;
 	}
@@ -1513,7 +1512,7 @@
 		w83781d_write_value(client, W83781D_REG_BEEP_INTS2, 0);
 	}
 
-	data->vrm = 82;
+	data->vrm = i2c_which_vrm();
 
 	if ((type != w83781d) && (type != as99127f)) {
 		tmp = w83781d_read_value(client, W83781D_REG_SCFG1);
@@ -1593,7 +1592,7 @@
 	if (time_after
 	    (jiffies - data->last_updated, (unsigned long) (HZ + HZ / 2))
 	    || time_before(jiffies, data->last_updated) || !data->valid) {
-		pr_debug("Starting device update\n");
+		dev_dbg(dev, "Starting device update\n");
 
 		for (i = 0; i <= 8; i++) {
 			if ((data->type == w83783s || data->type == w83697hf)
diff -Nru a/drivers/i2c/i2c-sensor-detect.c b/drivers/i2c/i2c-sensor-detect.c
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/drivers/i2c/i2c-sensor-detect.c	2004-10-18 14:56:32 -07:00
@@ -0,0 +1,169 @@
+/*
+    i2c-sensor-detect.c - Part of lm_sensors, Linux kernel modules for hardware
+            		  monitoring
+    Copyright (c) 1998 - 2001 Frodo Looijaard <frodol@dds.nl> and
+    Mark D. Studebaker <mdsxyz123@yahoo.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., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/ctype.h>
+#include <linux/sysctl.h>
+#include <linux/init.h>
+#include <linux/ioport.h>
+#include <linux/i2c.h>
+#include <linux/i2c-sensor.h>
+#include <asm/uaccess.h>
+
+
+/* Very inefficient for ISA detects, and won't work for 10-bit addresses! */
+int i2c_detect(struct i2c_adapter *adapter,
+	       struct i2c_address_data *address_data,
+	       int (*found_proc) (struct i2c_adapter *, int, int))
+{
+	int addr, i, found, j, err;
+	struct i2c_force_data *this_force;
+	int is_isa = i2c_is_isa_adapter(adapter);
+	int adapter_id =
+	    is_isa ? ANY_I2C_ISA_BUS : i2c_adapter_id(adapter);
+
+	/* Forget it if we can't probe using SMBUS_QUICK */
+	if ((!is_isa) &&
+	    !i2c_check_functionality(adapter, I2C_FUNC_SMBUS_QUICK))
+		return -1;
+
+	for (addr = 0x00; addr <= (is_isa ? 0xffff : 0x7f); addr++) {
+		if (!is_isa && i2c_check_addr(adapter, addr))
+			continue;
+
+		/* If it is in one of the force entries, we don't do any
+		   detection at all */
+		found = 0;
+		for (i = 0; !found && (this_force = address_data->forces + i, this_force->force); i++) {
+			for (j = 0; !found && (this_force->force[j] != I2C_CLIENT_END); j += 2) {
+				if ( ((adapter_id == this_force->force[j]) ||
+				      ((this_force->force[j] == ANY_I2C_BUS) && !is_isa)) &&
+				      (addr == this_force->force[j + 1]) ) {
+					dev_dbg(&adapter->dev, "found force parameter for adapter %d, addr %04x\n", adapter_id, addr);
+					if ((err = found_proc(adapter, addr, this_force->kind)))
+						return err;
+					found = 1;
+				}
+			}
+		}
+		if (found)
+			continue;
+
+		/* If this address is in one of the ignores, we can forget about it
+		   right now */
+		for (i = 0; !found && (address_data->ignore[i] != I2C_CLIENT_END); i += 2) {
+			if ( ((adapter_id == address_data->ignore[i]) ||
+			      ((address_data->ignore[i] == ANY_I2C_BUS) &&
+			       !is_isa)) &&
+			      (addr == address_data->ignore[i + 1])) {
+				dev_dbg(&adapter->dev, "found ignore parameter for adapter %d, addr %04x\n", adapter_id, addr);
+				found = 1;
+			}
+		}
+		for (i = 0; !found && (address_data->ignore_range[i] != I2C_CLIENT_END); i += 3) {
+			if ( ((adapter_id == address_data->ignore_range[i]) ||
+			      ((address_data-> ignore_range[i] == ANY_I2C_BUS) & 
+			       !is_isa)) &&
+			     (addr >= address_data->ignore_range[i + 1]) &&
+			     (addr <= address_data->ignore_range[i + 2])) {
+				dev_dbg(&adapter->dev,  "found ignore_range parameter for adapter %d, addr %04x\n", adapter_id, addr);
+				found = 1;
+			}
+		}
+		if (found)
+			continue;
+
+		/* Now, we will do a detection, but only if it is in the normal or 
+		   probe entries */
+		if (is_isa) {
+			for (i = 0; !found && (address_data->normal_isa[i] != I2C_CLIENT_ISA_END); i += 1) {
+				if (addr == address_data->normal_isa[i]) {
+					dev_dbg(&adapter->dev, "found normal isa entry for adapter %d, addr %04x\n", adapter_id, addr);
+					found = 1;
+				}
+			}
+			for (i = 0; !found && (address_data->normal_isa_range[i] != I2C_CLIENT_ISA_END); i += 3) {
+				if ((addr >= address_data->normal_isa_range[i]) &&
+				    (addr <= address_data->normal_isa_range[i + 1]) &&
+				    ((addr - address_data->normal_isa_range[i]) % address_data->normal_isa_range[i + 2] == 0)) {
+					dev_dbg(&adapter->dev, "found normal isa_range entry for adapter %d, addr %04x", adapter_id, addr);
+					found = 1;
+				}
+			}
+		} else {
+			for (i = 0; !found && (address_data->normal_i2c[i] != I2C_CLIENT_END); i += 1) {
+				if (addr == address_data->normal_i2c[i]) {
+					found = 1;
+					dev_dbg(&adapter->dev, "found normal i2c entry for adapter %d, addr %02x", adapter_id, addr);
+				}
+			}
+			for (i = 0; !found && (address_data->normal_i2c_range[i] != I2C_CLIENT_END); i += 2) {
+				if ((addr >= address_data->normal_i2c_range[i]) &&
+				    (addr <= address_data->normal_i2c_range[i + 1])) {
+					dev_dbg(&adapter->dev, "found normal i2c_range entry for adapter %d, addr %04x\n", adapter_id, addr);
+					found = 1;
+				}
+			}
+		}
+
+		for (i = 0;
+		     !found && (address_data->probe[i] != I2C_CLIENT_END);
+		     i += 2) {
+			if (((adapter_id == address_data->probe[i]) ||
+			     ((address_data->
+			       probe[i] == ANY_I2C_BUS) && !is_isa))
+			    && (addr == address_data->probe[i + 1])) {
+				dev_dbg(&adapter->dev, "found probe parameter for adapter %d, addr %04x\n", adapter_id, addr);
+				found = 1;
+			}
+		}
+		for (i = 0; !found && (address_data->probe_range[i] != I2C_CLIENT_END); i += 3) {
+			if ( ((adapter_id == address_data->probe_range[i]) ||
+			      ((address_data->probe_range[i] == ANY_I2C_BUS) && !is_isa)) &&
+			     (addr >= address_data->probe_range[i + 1]) &&
+			     (addr <= address_data->probe_range[i + 2])) {
+				found = 1;
+				dev_dbg(&adapter->dev, "found probe_range parameter for adapter %d, addr %04x\n", adapter_id, addr);
+			}
+		}
+		if (!found)
+			continue;
+
+		/* OK, so we really should examine this address. First check
+		   whether there is some client here at all! */
+		if (is_isa ||
+		    (i2c_smbus_xfer (adapter, addr, 0, 0, 0, I2C_SMBUS_QUICK, NULL) >= 0))
+			if ((err = found_proc(adapter, addr, -1)))
+				return err;
+	}
+	return 0;
+}
+
+EXPORT_SYMBOL(i2c_detect);
+
+MODULE_AUTHOR("Frodo Looijaard <frodol@dds.nl>, "
+	      "Rudolf Marek <r.marek@sh.cvut.cz>");
+
+MODULE_DESCRIPTION("i2c-sensor driver");
+MODULE_LICENSE("GPL");
diff -Nru a/drivers/i2c/i2c-sensor-vid.c b/drivers/i2c/i2c-sensor-vid.c
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/drivers/i2c/i2c-sensor-vid.c	2004-10-18 14:57:24 -07:00
@@ -0,0 +1,99 @@
+/*
+    i2c-sensor-vid.c -  Part of lm_sensors, Linux kernel modules for hardware
+        		monitoring
+
+    Copyright (c) 2004 Rudolf Marek <r.marek@sh.cvut.cz>
+
+    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.
+*/
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+
+struct vrm_model {
+	u8 vendor;
+	u8 eff_family;
+	u8 eff_model;
+	int vrm_type;
+};
+
+#define ANY 0xFF
+
+#ifdef CONFIG_X86
+
+static struct vrm_model vrm_models[] = {
+	{X86_VENDOR_AMD, 0x6, ANY, 90},		/* Athlon Duron etc */
+	{X86_VENDOR_AMD, 0xF, 0x4, 90},		/* Athlon 64 */
+	{X86_VENDOR_AMD, 0xF, 0x5, 24},		/* Opteron */
+	{X86_VENDOR_INTEL, 0x6, 0x9, 85},	/* 0.13um too */
+	{X86_VENDOR_INTEL, 0x6, 0xB, 85},	/* 0xB Tualatin */
+	{X86_VENDOR_INTEL, 0x6, ANY, 82},	/* any P6 */
+	{X86_VENDOR_INTEL, 0x7, ANY, 0},	/* Itanium */
+	{X86_VENDOR_INTEL, 0xF, 0x3, 100},	/* P4 Prescott */
+	{X86_VENDOR_INTEL, 0xF, ANY, 90},	/* P4 before Prescott */
+	{X86_VENDOR_INTEL, 0x10,ANY, 0},	/* Itanium 2 */
+	{X86_VENDOR_UNKNOWN, ANY, ANY, 0}	/* stop here */
+	};
+
+static int find_vrm(u8 eff_family, u8 eff_model, u8 vendor)
+{
+	int i = 0;
+
+	while (vrm_models[i].vendor!=X86_VENDOR_UNKNOWN) {
+		if (vrm_models[i].vendor==vendor)
+			if ((vrm_models[i].eff_family==eff_family)&& \
+			((vrm_models[i].eff_model==eff_model)|| \
+			(vrm_models[i].eff_model==ANY)))
+				return vrm_models[i].vrm_type;
+		i++;
+	}
+
+	return 0;
+}
+
+int i2c_which_vrm(void)
+{
+	struct cpuinfo_x86 *c = cpu_data;
+	u32 eax;
+	u8 eff_family, eff_model;
+	int vrm_ret;
+
+	if (c->x86 < 6) return 0;	/* any CPU with familly lower than 6
+				 	dont have VID and/or CPUID */
+	eax = cpuid_eax(1);
+	eff_family = ((eax & 0x00000F00)>>8);
+	eff_model  = ((eax & 0x000000F0)>>4);
+	if (eff_family == 0xF) {	/* use extended model & family */
+		eff_family += ((eax & 0x00F00000)>>20);
+		eff_model += ((eax & 0x000F0000)>>16)<<4;
+	}
+	vrm_ret = find_vrm(eff_family,eff_model,c->x86_vendor);
+	if (vrm_ret == 0)
+		printk(KERN_INFO "i2c-sensor.o: Unknown VRM version of your"
+		" x86 CPU\n");
+	return vrm_ret;
+}
+
+/* and now something completely different for Non-x86 world*/
+#else
+int i2c_which_vrm(void)
+{
+	printk(KERN_INFO "i2c-sensor.o: Unknown VRM version of your CPU\n");
+	return 0;
+}
+#endif
+
+EXPORT_SYMBOL(i2c_which_vrm);
diff -Nru a/drivers/i2c/i2c-sensor.c b/drivers/i2c/i2c-sensor.c
--- a/drivers/i2c/i2c-sensor.c	2004-10-18 14:56:32 -07:00
+++ /dev/null	Wed Dec 31 16:00:00 196900
@@ -1,167 +0,0 @@
-/*
-    i2c-sensor.c - Part of lm_sensors, Linux kernel modules for hardware
-                monitoring
-    Copyright (c) 1998 - 2001 Frodo Looijaard <frodol@dds.nl> and
-    Mark D. Studebaker <mdsxyz123@yahoo.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., 675 Mass Ave, Cambridge, MA 02139, USA.
-*/
-
-#include <linux/config.h>
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/slab.h>
-#include <linux/ctype.h>
-#include <linux/sysctl.h>
-#include <linux/init.h>
-#include <linux/ioport.h>
-#include <linux/i2c.h>
-#include <linux/i2c-sensor.h>
-#include <asm/uaccess.h>
-
-
-/* Very inefficient for ISA detects, and won't work for 10-bit addresses! */
-int i2c_detect(struct i2c_adapter *adapter,
-	       struct i2c_address_data *address_data,
-	       int (*found_proc) (struct i2c_adapter *, int, int))
-{
-	int addr, i, found, j, err;
-	struct i2c_force_data *this_force;
-	int is_isa = i2c_is_isa_adapter(adapter);
-	int adapter_id =
-	    is_isa ? ANY_I2C_ISA_BUS : i2c_adapter_id(adapter);
-
-	/* Forget it if we can't probe using SMBUS_QUICK */
-	if ((!is_isa) &&
-	    !i2c_check_functionality(adapter, I2C_FUNC_SMBUS_QUICK))
-		return -1;
-
-	for (addr = 0x00; addr <= (is_isa ? 0xffff : 0x7f); addr++) {
-		if (!is_isa && i2c_check_addr(adapter, addr))
-			continue;
-
-		/* If it is in one of the force entries, we don't do any
-		   detection at all */
-		found = 0;
-		for (i = 0; !found && (this_force = address_data->forces + i, this_force->force); i++) {
-			for (j = 0; !found && (this_force->force[j] != I2C_CLIENT_END); j += 2) {
-				if ( ((adapter_id == this_force->force[j]) ||
-				      ((this_force->force[j] == ANY_I2C_BUS) && !is_isa)) &&
-				      (addr == this_force->force[j + 1]) ) {
-					dev_dbg(&adapter->dev, "found force parameter for adapter %d, addr %04x\n", adapter_id, addr);
-					if ((err = found_proc(adapter, addr, this_force->kind)))
-						return err;
-					found = 1;
-				}
-			}
-		}
-		if (found)
-			continue;
-
-		/* If this address is in one of the ignores, we can forget about it
-		   right now */
-		for (i = 0; !found && (address_data->ignore[i] != I2C_CLIENT_END); i += 2) {
-			if ( ((adapter_id == address_data->ignore[i]) ||
-			      ((address_data->ignore[i] == ANY_I2C_BUS) &&
-			       !is_isa)) &&
-			      (addr == address_data->ignore[i + 1])) {
-				dev_dbg(&adapter->dev, "found ignore parameter for adapter %d, addr %04x\n", adapter_id, addr);
-				found = 1;
-			}
-		}
-		for (i = 0; !found && (address_data->ignore_range[i] != I2C_CLIENT_END); i += 3) {
-			if ( ((adapter_id == address_data->ignore_range[i]) ||
-			      ((address_data-> ignore_range[i] == ANY_I2C_BUS) & 
-			       !is_isa)) &&
-			     (addr >= address_data->ignore_range[i + 1]) &&
-			     (addr <= address_data->ignore_range[i + 2])) {
-				dev_dbg(&adapter->dev,  "found ignore_range parameter for adapter %d, addr %04x\n", adapter_id, addr);
-				found = 1;
-			}
-		}
-		if (found)
-			continue;
-
-		/* Now, we will do a detection, but only if it is in the normal or 
-		   probe entries */
-		if (is_isa) {
-			for (i = 0; !found && (address_data->normal_isa[i] != I2C_CLIENT_ISA_END); i += 1) {
-				if (addr == address_data->normal_isa[i]) {
-					dev_dbg(&adapter->dev, "found normal isa entry for adapter %d, addr %04x\n", adapter_id, addr);
-					found = 1;
-				}
-			}
-			for (i = 0; !found && (address_data->normal_isa_range[i] != I2C_CLIENT_ISA_END); i += 3) {
-				if ((addr >= address_data->normal_isa_range[i]) &&
-				    (addr <= address_data->normal_isa_range[i + 1]) &&
-				    ((addr - address_data->normal_isa_range[i]) % address_data->normal_isa_range[i + 2] == 0)) {
-					dev_dbg(&adapter->dev, "found normal isa_range entry for adapter %d, addr %04x", adapter_id, addr);
-					found = 1;
-				}
-			}
-		} else {
-			for (i = 0; !found && (address_data->normal_i2c[i] != I2C_CLIENT_END); i += 1) {
-				if (addr == address_data->normal_i2c[i]) {
-					found = 1;
-					dev_dbg(&adapter->dev, "found normal i2c entry for adapter %d, addr %02x", adapter_id, addr);
-				}
-			}
-			for (i = 0; !found && (address_data->normal_i2c_range[i] != I2C_CLIENT_END); i += 2) {
-				if ((addr >= address_data->normal_i2c_range[i]) &&
-				    (addr <= address_data->normal_i2c_range[i + 1])) {
-					dev_dbg(&adapter->dev, "found normal i2c_range entry for adapter %d, addr %04x\n", adapter_id, addr);
-					found = 1;
-				}
-			}
-		}
-
-		for (i = 0;
-		     !found && (address_data->probe[i] != I2C_CLIENT_END);
-		     i += 2) {
-			if (((adapter_id == address_data->probe[i]) ||
-			     ((address_data->
-			       probe[i] == ANY_I2C_BUS) && !is_isa))
-			    && (addr == address_data->probe[i + 1])) {
-				dev_dbg(&adapter->dev, "found probe parameter for adapter %d, addr %04x\n", adapter_id, addr);
-				found = 1;
-			}
-		}
-		for (i = 0; !found && (address_data->probe_range[i] != I2C_CLIENT_END); i += 3) {
-			if ( ((adapter_id == address_data->probe_range[i]) ||
-			      ((address_data->probe_range[i] == ANY_I2C_BUS) && !is_isa)) &&
-			     (addr >= address_data->probe_range[i + 1]) &&
-			     (addr <= address_data->probe_range[i + 2])) {
-				found = 1;
-				dev_dbg(&adapter->dev, "found probe_range parameter for adapter %d, addr %04x\n", adapter_id, addr);
-			}
-		}
-		if (!found)
-			continue;
-
-		/* OK, so we really should examine this address. First check
-		   whether there is some client here at all! */
-		if (is_isa ||
-		    (i2c_smbus_xfer (adapter, addr, 0, 0, 0, I2C_SMBUS_QUICK, NULL) >= 0))
-			if ((err = found_proc(adapter, addr, -1)))
-				return err;
-	}
-	return 0;
-}
-
-EXPORT_SYMBOL(i2c_detect);
-
-MODULE_AUTHOR("Frodo Looijaard <frodol@dds.nl>");
-MODULE_DESCRIPTION("i2c-sensor driver");
-MODULE_LICENSE("GPL");
diff -Nru a/drivers/ide/Kconfig b/drivers/ide/Kconfig
--- a/drivers/ide/Kconfig	2004-10-18 14:56:29 -07:00
+++ b/drivers/ide/Kconfig	2004-10-18 14:56:29 -07:00
@@ -457,11 +457,6 @@
 
 	  Generally say N here.
 
-config BLK_DEV_ADMA
-	bool
-	depends on PCI && BLK_DEV_IDEPCI
-	default BLK_DEV_IDEDMA_PCI
-
 config BLK_DEV_AEC62XX
 	tristate "AEC62XX chipset support"
 	help
@@ -834,6 +829,13 @@
 	help
 	  Say Y here if you want to support the Yellowstone RapIDE controller
 	  manufactured for use with Acorn computers.
+
+config BLK_DEV_IDE_BAST
+	tristate "Simtec BAST / Thorcom VR1000 IDE support"
+	depends on ARM && (ARCH_BAST || MACH_VR100)
+	help
+	  Say Y here if you want to support the onboard IDE channels on the
+	  Simtec BAST or the Thorcom VR1000
 
 config BLK_DEV_GAYLE
 	bool "Amiga Gayle IDE interface support"
diff -Nru a/drivers/ide/arm/Makefile b/drivers/ide/arm/Makefile
--- a/drivers/ide/arm/Makefile	2004-10-18 14:55:53 -07:00
+++ b/drivers/ide/arm/Makefile	2004-10-18 14:55:53 -07:00
@@ -1,5 +1,6 @@
 
 obj-$(CONFIG_BLK_DEV_IDE_ICSIDE)	+= icside.o
 obj-$(CONFIG_BLK_DEV_IDE_RAPIDE)	+= rapide.o
+obj-$(CONFIG_BLK_DEV_IDE_BAST)		+= bast-ide.o
 
 EXTRA_CFLAGS	:= -Idrivers/ide
diff -Nru a/drivers/ide/arm/bast-ide.c b/drivers/ide/arm/bast-ide.c
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/drivers/ide/arm/bast-ide.c	2004-10-18 14:57:21 -07:00
@@ -0,0 +1,71 @@
+/* linux/drivers/ide/arm/bast-ide.c
+ *
+ * Copyright (c) 2003-2004 Simtec Electronics
+ *  Ben Dooks <ben@simtec.co.uk>
+ *
+ * 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/module.h>
+#include <linux/errno.h>
+#include <linux/ide.h>
+#include <linux/init.h>
+
+#include <asm/mach-types.h>
+
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/arch/map.h>
+#include <asm/arch/bast-map.h>
+#include <asm/arch/bast-irq.h>
+
+/* list of registered interfaces */
+static ide_hwif_t *ifs[2];
+
+static int __init
+bastide_register(unsigned int base, unsigned int aux, int irq,
+		 ide_hwif_t **hwif)
+{
+	hw_regs_t hw;
+	int i;
+
+	memset(&hw, 0, sizeof(hw));
+
+	base += BAST_IDE_CS;
+	aux  += BAST_IDE_CS;
+
+	for (i = IDE_DATA_OFFSET; i <= IDE_STATUS_OFFSET; i++) {
+		hw.io_ports[i] = (unsigned long)base;
+		base += 0x20;
+	}
+
+	hw.io_ports[IDE_CONTROL_OFFSET] = aux + (6 * 0x20);
+	hw.irq = irq;
+
+	ide_register_hw(&hw, hwif);
+
+	return 0;
+}
+
+static int __init bastide_init(void)
+{
+	/* we can treat the VR1000 and the BAST the same */
+
+	if (!(machine_is_bast() || machine_is_vr1000()))
+		return 0;
+
+	printk("BAST: IDE driver, (c) 2003-2004 Simtec Electronics\n");
+
+	bastide_register(BAST_VA_IDEPRI, BAST_VA_IDEPRIAUX, IRQ_IDE0, &ifs[0]);
+	bastide_register(BAST_VA_IDESEC, BAST_VA_IDESECAUX, IRQ_IDE1, &ifs[1]);
+	return 0;
+}
+
+module_init(bastide_init);
+
+MODULE_AUTHOR("Ben Dooks <ben@simtec.co.uk>");
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("Simtec BAST / Thorcom VR1000 IDE driver");
diff -Nru a/drivers/ide/arm/icside.c b/drivers/ide/arm/icside.c
--- a/drivers/ide/arm/icside.c	2004-10-18 14:56:32 -07:00
+++ b/drivers/ide/arm/icside.c	2004-10-18 14:56:32 -07:00
@@ -215,8 +215,6 @@
 	struct scatterlist *sg = hwif->sg_table;
 	int nents;
 
-	BUG_ON(hwif->sg_dma_active);
-
 	if (rq->flags & REQ_DRIVE_TASKFILE) {
 		ide_task_t *args = rq->special;
 
@@ -401,8 +399,6 @@
 	dma_unmap_sg(state->dev, hwif->sg_table, hwif->sg_nents,
 		     hwif->sg_dma_direction);
 
-	hwif->sg_dma_active = 0;
-
 	return get_dma_residue(hwif->hw.dma) != 0;
 }
 
@@ -454,7 +450,6 @@
 	/*
 	 * We can not enable DMA on both channels.
 	 */
-	BUG_ON(hwif->sg_dma_active);
 	BUG_ON(dma_channel_active(hwif->hw.dma));
 
 	icside_build_sglist(drive, rq);
diff -Nru a/drivers/ide/ide-cd.c b/drivers/ide/ide-cd.c
--- a/drivers/ide/ide-cd.c	2004-10-18 14:56:29 -07:00
+++ b/drivers/ide/ide-cd.c	2004-10-18 14:56:29 -07:00
@@ -2719,8 +2719,10 @@
 	if (!cdrom_get_media_event(cdi, &med)) {
 		if (med.media_present)
 			return CDS_DISC_OK;
-		if (med.door_open)
+		else if (med.door_open)
 			return CDS_TRAY_OPEN;
+		else
+			return CDS_NO_DISC;
 	}
 
 	if (sense.sense_key == NOT_READY && sense.asc == 0x04 && sense.ascq == 0x04)
@@ -2732,10 +2734,12 @@
 	 * any other way to detect this...
 	 */
 	if (sense.sense_key == NOT_READY) {
-		if (sense.asc == 0x3a && sense.ascq == 1)
-			return CDS_NO_DISC;
-		else
-			return CDS_TRAY_OPEN;
+		if (sense.asc == 0x3a) {
+			if (sense.ascq == 0 || sense.ascq == 1)
+				return CDS_NO_DISC;
+			else if (sense.ascq == 2)
+				return CDS_TRAY_OPEN;
+		}
 	}
 
 	return CDS_DRIVE_NOT_READY;
diff -Nru a/drivers/ide/ide-disk.c b/drivers/ide/ide-disk.c
--- a/drivers/ide/ide-disk.c	2004-10-18 14:56:29 -07:00
+++ b/drivers/ide/ide-disk.c	2004-10-18 14:56:29 -07:00
@@ -340,12 +340,18 @@
 ide_startstop_t __ide_do_rw_disk (ide_drive_t *drive, struct request *rq, sector_t block)
 {
 	ide_hwif_t *hwif	= HWIF(drive);
+	unsigned int dma	= drive->using_dma;
 	u8 lba48		= (drive->addressing == 1) ? 1 : 0;
 	task_ioreg_t command	= WIN_NOP;
 	ata_nsector_t		nsectors;
 
 	nsectors.all		= (u16) rq->nr_sectors;
 
+	if (hwif->no_lba48_dma && lba48 && dma) {
+		if (rq->sector + rq->nr_sectors > 1ULL << 28)
+			dma = 0;
+	}
+
 	if (IDE_CONTROL_REG)
 		hwif->OUTB(drive->ctl, IDE_CONTROL_REG);
 
@@ -414,7 +420,7 @@
 	}
 
 	if (rq_data_dir(rq) == READ) {
-		if (drive->using_dma && !hwif->ide_dma_read(drive))
+		if (dma && !hwif->ide_dma_read(drive))
 			return ide_started;
 
 		command = ((drive->mult_count) ?
@@ -425,7 +431,7 @@
 	} else {
 		ide_startstop_t startstop;
 
-		if (drive->using_dma && !(HWIF(drive)->ide_dma_write(drive)))
+		if (dma && !hwif->ide_dma_write(drive))
 			return ide_started;
 
 		command = ((drive->mult_count) ?
@@ -488,31 +494,38 @@
 }
 EXPORT_SYMBOL_GPL(__ide_do_rw_disk);
 
-static u8 get_command(ide_drive_t *drive, int cmd, ide_task_t *task)
+static u8 get_command(ide_drive_t *drive, struct request *rq, ide_task_t *task)
 {
 	unsigned int lba48 = (drive->addressing == 1) ? 1 : 0;
+	unsigned int dma = drive->using_dma;
+
+	if (drive->hwif->no_lba48_dma && lba48 && dma) {
+		if (rq->sector + rq->nr_sectors > 1ULL << 28)
+			dma = 0;
+	}
 
-	if (cmd == READ) {
+	if (rq_data_dir(rq) == READ) {
 		task->command_type = IDE_DRIVE_TASK_IN;
-		if (drive->using_dma)
+		if (dma)
 			return lba48 ? WIN_READDMA_EXT : WIN_READDMA;
+		task->handler = &task_in_intr;
 		if (drive->mult_count) {
-			task->handler = &task_mulin_intr;
+			task->data_phase = TASKFILE_MULTI_IN;
 			return lba48 ? WIN_MULTREAD_EXT : WIN_MULTREAD;
 		}
-		task->handler = &task_in_intr;
+		task->data_phase = TASKFILE_IN;
 		return lba48 ? WIN_READ_EXT : WIN_READ;
 	} else {
 		task->command_type = IDE_DRIVE_TASK_RAW_WRITE;
-		if (drive->using_dma)
+		if (dma)
 			return lba48 ? WIN_WRITEDMA_EXT : WIN_WRITEDMA;
+		task->prehandler = &pre_task_out_intr;
+		task->handler = &task_out_intr;
 		if (drive->mult_count) {
-			task->prehandler = &pre_task_mulout_intr;
-			task->handler = &task_mulout_intr;
+			task->data_phase = TASKFILE_MULTI_OUT;
 			return lba48 ? WIN_MULTWRITE_EXT : WIN_MULTWRITE;
 		}
-		task->prehandler = &pre_task_out_intr;
-		task->handler = &task_out_intr;
+		task->data_phase = TASKFILE_OUT;
 		return lba48 ? WIN_WRITE_EXT : WIN_WRITE;
 	}
 }
@@ -541,9 +554,10 @@
 	args.tfRegister[IDE_HCYL_OFFSET]	= (cyl>>8);
 	args.tfRegister[IDE_SELECT_OFFSET]	= head;
 	args.tfRegister[IDE_SELECT_OFFSET]	|= drive->select.all;
-	args.tfRegister[IDE_COMMAND_OFFSET]	= get_command(drive, rq_data_dir(rq), &args);
+	args.tfRegister[IDE_COMMAND_OFFSET]	= get_command(drive, rq, &args);
 	args.rq					= (struct request *) rq;
 	rq->special				= (ide_task_t *)&args;
+	drive->hwif->data_phase = args.data_phase;
 	return do_rw_taskfile(drive, &args);
 }
 
@@ -565,9 +579,10 @@
 	args.tfRegister[IDE_HCYL_OFFSET]	= (block>>=8);
 	args.tfRegister[IDE_SELECT_OFFSET]	= ((block>>8)&0x0f);
 	args.tfRegister[IDE_SELECT_OFFSET]	|= drive->select.all;
-	args.tfRegister[IDE_COMMAND_OFFSET]	= get_command(drive, rq_data_dir(rq), &args);
+	args.tfRegister[IDE_COMMAND_OFFSET]	= get_command(drive, rq, &args);
 	args.rq					= (struct request *) rq;
 	rq->special				= (ide_task_t *)&args;
+	drive->hwif->data_phase = args.data_phase;
 	return do_rw_taskfile(drive, &args);
 }
 
@@ -595,7 +610,7 @@
 	args.tfRegister[IDE_LCYL_OFFSET]	= (block>>=8);	/* mid lba */
 	args.tfRegister[IDE_HCYL_OFFSET]	= (block>>=8);	/* hi  lba */
 	args.tfRegister[IDE_SELECT_OFFSET]	= drive->select.all;
-	args.tfRegister[IDE_COMMAND_OFFSET]	= get_command(drive, rq_data_dir(rq), &args);
+	args.tfRegister[IDE_COMMAND_OFFSET]	= get_command(drive, rq, &args);
 	args.hobRegister[IDE_SECTOR_OFFSET]	= (block>>=8);	/* low lba */
 	args.hobRegister[IDE_LCYL_OFFSET]	= (block>>=8);	/* mid lba */
 	args.hobRegister[IDE_HCYL_OFFSET]	= (block>>=8);	/* hi  lba */
@@ -603,6 +618,7 @@
 	args.hobRegister[IDE_CONTROL_OFFSET_HOB]= (drive->ctl|0x80);
 	args.rq					= (struct request *) rq;
 	rq->special				= (ide_task_t *)&args;
+	drive->hwif->data_phase = args.data_phase;
 	return do_rw_taskfile(drive, &args);
 }
 
@@ -638,7 +654,6 @@
 
 	local_irq_set(flags);
 	printk("%s: %s: status=0x%02x", drive->name, msg, stat);
-#if FANCY_STATUS_DUMPS
 	printk(" { ");
 	if (stat & BUSY_STAT)
 		printk("Busy ");
@@ -652,12 +667,10 @@
 		if (stat & ERR_STAT)	printk("Error ");
 	}
 	printk("}");
-#endif	/* FANCY_STATUS_DUMPS */
 	printk("\n");
 	if ((stat & (BUSY_STAT|ERR_STAT)) == ERR_STAT) {
 		err = hwif->INB(IDE_ERROR_REG);
 		printk("%s: %s: error=0x%02x", drive->name, msg, err);
-#if FANCY_STATUS_DUMPS
 		printk(" { ");
 		if (err & ABRT_ERR)	printk("DriveStatusError ");
 		if (err & ICRC_ERR)
@@ -700,8 +713,38 @@
 					(unsigned long long)HWGROUP(drive)->rq->sector);
 		}
 	}
-#endif	/* FANCY_STATUS_DUMPS */
 	printk("\n");
+	{
+		struct request *rq;
+		unsigned char opcode = 0;
+		int found = 0;
+
+		spin_lock(&ide_lock);
+		rq = HWGROUP(drive)->rq;
+		spin_unlock(&ide_lock);
+		if (!rq)
+			goto out;
+		if (rq->flags & (REQ_DRIVE_CMD | REQ_DRIVE_TASK)) {
+			char *args = rq->buffer;
+			if (args) {
+				opcode = args[0];
+				found = 1;
+			}
+		} else if (rq->flags & REQ_DRIVE_TASKFILE) {
+			ide_task_t *args = rq->special;
+			if (args) {
+				task_struct_t *tf = (task_struct_t *) args->tfRegister;
+				opcode = tf->command;
+				found = 1;
+			}
+		}
+		printk("ide: failed opcode was: ");
+		if (!found)
+			printk("unknown\n");
+		else
+			printk("0x%02x\n", opcode);
+	}
+out:
 	local_irq_restore(flags);
 	return err;
 }
@@ -1117,6 +1160,7 @@
 	args.tfRegister[IDE_HCYL_OFFSET]	= SMART_HCYL_PASS;
 	args.tfRegister[IDE_COMMAND_OFFSET]	= WIN_SMART;
 	args.command_type			= IDE_DRIVE_TASK_IN;
+	args.data_phase				= TASKFILE_IN;
 	args.handler				= &task_in_intr;
 	(void) smart_enable(drive);
 	return ide_raw_taskfile(drive, &args, buf);
@@ -1203,6 +1247,42 @@
 
 #endif	/* CONFIG_PROC_FS */
 
+static int idedisk_issue_flush(request_queue_t *q, struct gendisk *disk,
+			       sector_t *error_sector)
+{
+	ide_drive_t *drive = q->queuedata;
+	struct request *rq;
+	int ret;
+
+	if (!drive->wcache)
+		return 0;
+
+	rq = blk_get_request(q, WRITE, __GFP_WAIT);
+
+	memset(rq->cmd, 0, sizeof(rq->cmd));
+
+	if (ide_id_has_flush_cache_ext(drive->id) &&
+	    (drive->capacity64 >= (1UL << 28)))
+		rq->cmd[0] = WIN_FLUSH_CACHE_EXT;
+	else
+		rq->cmd[0] = WIN_FLUSH_CACHE;
+
+
+	rq->flags |= REQ_DRIVE_TASK | REQ_SOFTBARRIER;
+	rq->buffer = rq->cmd;
+
+	ret = blk_execute_rq(q, disk, rq);
+
+	/*
+	 * if we failed and caller wants error offset, get it
+	 */
+	if (ret && error_sector)
+		*error_sector = ide_get_error_location(drive, rq->cmd);
+
+	blk_put_request(rq);
+	return ret;
+}
+
 /*
  * This is tightly woven into the driver->do_special can not touch.
  * DON'T do it again until a total personality rewrite is committed.
@@ -1231,16 +1311,10 @@
 	return 0;
 }
 
-/* check if CACHE FLUSH (EXT) command is supported (bits defined in ATA-6) */
-#define ide_id_has_flush_cache(id)	((id)->cfs_enable_2 & 0x3000)
-
-/* some Maxtor disks have bit 13 defined incorrectly so check bit 10 too */
-#define ide_id_has_flush_cache_ext(id)	\
-	(((id)->cfs_enable_2 & 0x2400) == 0x2400)
-
-static int write_cache (ide_drive_t *drive, int arg)
+static int write_cache(ide_drive_t *drive, int arg)
 {
 	ide_task_t args;
+	int err;
 
 	if (!ide_id_has_flush_cache(drive->id))
 		return 1;
@@ -1251,7 +1325,10 @@
 	args.tfRegister[IDE_COMMAND_OFFSET]	= WIN_SETFEATURES;
 	args.command_type			= IDE_DRIVE_TASK_NO_DATA;
 	args.handler				= &task_no_data_intr;
-	(void) ide_raw_taskfile(drive, &args, NULL);
+
+	err = ide_raw_taskfile(drive, &args, NULL);
+	if (err)
+		return err;
 
 	drive->wcache = arg;
 	return 0;
@@ -1412,6 +1489,7 @@
 {
 	struct hd_driveid *id = drive->id;
 	unsigned long long capacity;
+	int barrier;
 
 	idedisk_add_settings(drive);
 
@@ -1443,7 +1521,7 @@
 		blk_queue_max_sectors(drive->queue, max_s);
 	}
 
-	printk("%s: max request size: %dKiB\n", drive->name, drive->queue->max_sectors / 2);
+	printk(KERN_INFO "%s: max request size: %dKiB\n", drive->name, drive->queue->max_sectors / 2);
 
 	/* Extract geometry if we did not already have one for the drive */
 	if (!drive->cyl || !drive->head || !drive->sect) {
@@ -1472,13 +1550,22 @@
 
 	/* limit drive capacity to 137GB if LBA48 cannot be used */
 	if (drive->addressing == 0 && drive->capacity64 > 1ULL << 28) {
-		printk("%s: cannot use LBA48 - full capacity "
+		printk(KERN_WARNING "%s: cannot use LBA48 - full capacity "
 		       "%llu sectors (%llu MB)\n",
 		       drive->name, (unsigned long long)drive->capacity64,
 		       sectors_to_MB(drive->capacity64));
 		drive->capacity64 = 1ULL << 28;
 	}
 
+	if (drive->hwif->no_lba48_dma && drive->addressing) {
+		if (drive->capacity64 > 1ULL << 28) {
+			printk(KERN_INFO "%s: cannot use LBA48 DMA - PIO mode will"
+					 " be used for accessing sectors > %u\n",
+					 drive->name, 1 << 28);
+		} else
+			drive->addressing = 0;
+	}
+
 	/*
 	 * if possible, give fdisk access to more of the drive,
 	 * by correcting bios_cyls:
@@ -1543,6 +1630,29 @@
 		drive->wcache = 1;
 
 	write_cache(drive, 1);
+
+	/*
+	 * We must avoid issuing commands a drive does not understand
+	 * or we may crash it. We check flush cache is supported. We also
+	 * check we have the LBA48 flush cache if the drive capacity is
+	 * too large. By this time we have trimmed the drive capacity if
+	 * LBA48 is not available so we don't need to recheck that.
+	 */
+	barrier = 0;
+	if (ide_id_has_flush_cache(id))
+		barrier = 1;
+	if (drive->addressing == 1) {
+		/* Can't issue the correct flush ? */
+		if (capacity > (1ULL << 28) && !ide_id_has_flush_cache_ext(id))
+			barrier = 0;
+	}
+
+	printk(KERN_DEBUG "%s: cache flushes %ssupported\n",
+		drive->name, barrier ? "" : "not ");
+	if (barrier) {
+		blk_queue_ordered(drive->queue, 1);
+		blk_queue_issue_flush_fn(drive->queue, idedisk_issue_flush);
+	}
 }
 
 static void ide_cacheflush_p(ide_drive_t *drive)
@@ -1723,11 +1833,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);
@@ -1735,7 +1843,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-dma.c b/drivers/ide/ide-dma.c
--- a/drivers/ide/ide-dma.c	2004-10-18 14:56:32 -07:00
+++ b/drivers/ide/ide-dma.c	2004-10-18 14:56:32 -07:00
@@ -208,9 +208,6 @@
 	struct scatterlist *sg = hwif->sg_table;
 	int nents;
 
-	if (hwif->sg_dma_active)
-		BUG();
-
 	nents = blk_rq_map_sg(drive->queue, rq, hwif->sg_table);
 		
 	if (rq_data_dir(rq) == READ)
@@ -366,7 +363,6 @@
 		     hwif->sg_table,
 		     hwif->sg_nents,
 		     hwif->sg_dma_direction);
-	hwif->sg_dma_active = 0;
 	return 0; /* revert to PIO for this request */
 }
 
@@ -390,7 +386,6 @@
 	int nents = HWIF(drive)->sg_nents;
 
 	pci_unmap_sg(dev, sg, nents, HWIF(drive)->sg_dma_direction);
-	HWIF(drive)->sg_dma_active = 0;
 }
 
 EXPORT_SYMBOL_GPL(ide_destroy_dmatable);
@@ -412,10 +407,6 @@
 	ide_hwif_t *hwif = HWIF(drive);
 
 	if ((id->capability & 1) && hwif->autodma) {
-		/* Consult the list of known "bad" drives */
-		if (__ide_dma_bad_drive(drive))
-			return __ide_dma_off(drive);
-
 		/*
 		 * Enable DMA on any drive that has
 		 * UltraDMA (mode 0/1/2/3/4/5/6) enabled
@@ -569,6 +560,10 @@
  
 int __ide_dma_on (ide_drive_t *drive)
 {
+	/* consult the list of known "bad" drives */
+	if (__ide_dma_bad_drive(drive))
+		return 1;
+
 	drive->using_dma = 1;
 	ide_toggle_bounce(drive, 1);
 
diff -Nru a/drivers/ide/ide-io.c b/drivers/ide/ide-io.c
--- a/drivers/ide/ide-io.c	2004-10-18 14:56:49 -07:00
+++ b/drivers/ide/ide-io.c	2004-10-18 14:56:49 -07:00
@@ -54,38 +54,77 @@
 #include <asm/io.h>
 #include <asm/bitops.h>
 
-/**
- *	ide_end_request		-	complete an IDE I/O
- *	@drive: IDE device for the I/O
- *	@uptodate: 
- *	@nr_sectors: number of sectors completed
- *
- *	This is our end_request wrapper function. We complete the I/O
- *	update random number input and dequeue the request, which if
- *	it was tagged may be out of order.
+static void ide_fill_flush_cmd(ide_drive_t *drive, struct request *rq)
+{
+	char *buf = rq->cmd;
+
+	/*
+	 * reuse cdb space for ata command
+	 */
+	memset(buf, 0, sizeof(rq->cmd));
+
+	rq->flags |= REQ_DRIVE_TASK | REQ_STARTED;
+	rq->buffer = buf;
+	rq->buffer[0] = WIN_FLUSH_CACHE;
+
+	if (ide_id_has_flush_cache_ext(drive->id) &&
+	    (drive->capacity64 >= (1UL << 28)))
+		rq->buffer[0] = WIN_FLUSH_CACHE_EXT;
+}
+
+/*
+ * preempt pending requests, and store this cache flush for immediate
+ * execution
  */
- 
-int ide_end_request (ide_drive_t *drive, int uptodate, int nr_sectors)
+static struct request *ide_queue_flush_cmd(ide_drive_t *drive,
+					   struct request *rq, int post)
 {
-	struct request *rq;
-	unsigned long flags;
-	int ret = 1;
+	struct request *flush_rq = &HWGROUP(drive)->wrq;
 
-	spin_lock_irqsave(&ide_lock, flags);
-	rq = HWGROUP(drive)->rq;
+	/*
+	 * write cache disabled, clear the barrier bit and treat it like
+	 * an ordinary write
+	 */
+	if (!drive->wcache) {
+		rq->flags |= REQ_BAR_PREFLUSH;
+		return rq;
+	}
 
-	BUG_ON(!(rq->flags & REQ_STARTED));
+	ide_init_drive_cmd(flush_rq);
+	ide_fill_flush_cmd(drive, flush_rq);
 
-	if (!nr_sectors)
-		nr_sectors = rq->hard_cur_sectors;
+	flush_rq->special = rq;
+	flush_rq->nr_sectors = rq->nr_sectors;
+
+	if (!post) {
+		drive->doing_barrier = 1;
+		flush_rq->flags |= REQ_BAR_PREFLUSH;
+		blkdev_dequeue_request(rq);
+	} else
+		flush_rq->flags |= REQ_BAR_POSTFLUSH;
+
+	__elv_add_request(drive->queue, flush_rq, ELEVATOR_INSERT_FRONT, 0);
+	HWGROUP(drive)->rq = NULL;
+	return flush_rq;
+}
+
+static int __ide_end_request(ide_drive_t *drive, struct request *rq,
+			     int uptodate, int nr_sectors)
+{
+	int ret = 1;
+
+	BUG_ON(!(rq->flags & REQ_STARTED));
 
 	/*
 	 * if failfast is set on a request, override number of sectors and
 	 * complete the whole request right now
 	 */
-	if (blk_noretry_request(rq) && !uptodate)
+	if (blk_noretry_request(rq) && end_io_error(uptodate))
 		nr_sectors = rq->hard_nr_sectors;
 
+	if (!blk_fs_request(rq) && end_io_error(uptodate) && !rq->errors)
+		rq->errors = -EIO;
+
 	/*
 	 * decide whether to reenable DMA -- 3 is a random magic for now,
 	 * if we DMA timeout more than 3 times, just stay in PIO
@@ -97,15 +136,56 @@
 
 	if (!end_that_request_first(rq, uptodate, nr_sectors)) {
 		add_disk_randomness(rq->rq_disk);
+
+		if (blk_rq_tagged(rq))
+			blk_queue_end_tag(drive->queue, rq);
+
 		blkdev_dequeue_request(rq);
 		HWGROUP(drive)->rq = NULL;
 		end_that_request_last(rq);
 		ret = 0;
 	}
-	spin_unlock_irqrestore(&ide_lock, flags);
 	return ret;
 }
 
+/**
+ *	ide_end_request		-	complete an IDE I/O
+ *	@drive: IDE device for the I/O
+ *	@uptodate:
+ *	@nr_sectors: number of sectors completed
+ *
+ *	This is our end_request wrapper function. We complete the I/O
+ *	update random number input and dequeue the request, which if
+ *	it was tagged may be out of order.
+ */
+
+int ide_end_request (ide_drive_t *drive, int uptodate, int nr_sectors)
+{
+	struct request *rq;
+	unsigned long flags;
+	int ret = 1;
+
+	spin_lock_irqsave(&ide_lock, flags);
+	rq = HWGROUP(drive)->rq;
+
+	if (!nr_sectors)
+		nr_sectors = rq->hard_cur_sectors;
+
+	if (!blk_barrier_rq(rq) || !drive->wcache)
+		ret = __ide_end_request(drive, rq, uptodate, nr_sectors);
+	else {
+		struct request *flush_rq = &HWGROUP(drive)->wrq;
+
+		flush_rq->nr_sectors -= nr_sectors;
+		if (!flush_rq->nr_sectors) {
+			ide_queue_flush_cmd(drive, rq, 1);
+			ret = 0;
+		}
+	}
+
+	spin_unlock_irqrestore(&ide_lock, flags);
+	return ret;
+}
 EXPORT_SYMBOL(ide_end_request);
 
 /**
@@ -137,6 +217,113 @@
 	spin_unlock_irqrestore(&ide_lock, flags);
 }
 
+/*
+ * FIXME: probably move this somewhere else, name is bad too :)
+ */
+u64 ide_get_error_location(ide_drive_t *drive, char *args)
+{
+	u32 high, low;
+	u8 hcyl, lcyl, sect;
+	u64 sector;
+
+	high = 0;
+	hcyl = args[5];
+	lcyl = args[4];
+	sect = args[3];
+
+	if (ide_id_has_flush_cache_ext(drive->id)) {
+		low = (hcyl << 16) | (lcyl << 8) | sect;
+		HWIF(drive)->OUTB(drive->ctl|0x80, IDE_CONTROL_REG);
+		high = ide_read_24(drive);
+	} else {
+		u8 cur = HWIF(drive)->INB(IDE_SELECT_REG);
+		if (cur & 0x40)
+			low = (hcyl << 16) | (lcyl << 8) | sect;
+		else {
+			low = hcyl * drive->head * drive->sect;
+			low += lcyl * drive->sect;
+			low += sect - 1;
+		}
+	}
+
+	sector = ((u64) high << 24) | low;
+	return sector;
+}
+EXPORT_SYMBOL(ide_get_error_location);
+
+static void ide_complete_barrier(ide_drive_t *drive, struct request *rq,
+				 int error)
+{
+	struct request *real_rq = rq->special;
+	int good_sectors, bad_sectors;
+	sector_t sector;
+
+	if (!error) {
+		if (blk_barrier_postflush(rq)) {
+			/*
+			 * this completes the barrier write
+			 */
+			__ide_end_request(drive, real_rq, 1, real_rq->hard_nr_sectors);
+			drive->doing_barrier = 0;
+		} else {
+			/*
+			 * just indicate that we did the pre flush
+			 */
+			real_rq->flags |= REQ_BAR_PREFLUSH;
+			elv_requeue_request(drive->queue, real_rq);
+		}
+		/*
+		 * all is fine, return
+		 */
+		return;
+	}
+
+	/*
+	 * we need to end real_rq, but it's not on the queue currently.
+	 * put it back on the queue, so we don't have to special case
+	 * anything else for completing it
+	 */
+	if (!blk_barrier_postflush(rq))
+		elv_requeue_request(drive->queue, real_rq);
+
+	/*
+	 * drive aborted flush command, assume FLUSH_CACHE_* doesn't
+	 * work and disable barrier support
+	 */
+	if (error & ABRT_ERR) {
+		printk(KERN_ERR "%s: barrier support doesn't work\n", drive->name);
+		__ide_end_request(drive, real_rq, -EOPNOTSUPP, real_rq->hard_nr_sectors);
+		blk_queue_ordered(drive->queue, 0);
+		blk_queue_issue_flush_fn(drive->queue, NULL);
+	} else {
+		/*
+		 * find out what part of the request failed
+		 */
+		good_sectors = 0;
+		if (blk_barrier_postflush(rq)) {
+			sector = ide_get_error_location(drive, rq->buffer);
+
+			if ((sector >= real_rq->hard_sector) &&
+			    (sector < real_rq->hard_sector + real_rq->hard_nr_sectors))
+				good_sectors = sector - real_rq->hard_sector;
+		} else
+			sector = real_rq->hard_sector;
+
+		bad_sectors = real_rq->hard_nr_sectors - good_sectors;
+		if (good_sectors)
+			__ide_end_request(drive, real_rq, 1, good_sectors);
+		if (bad_sectors)
+			__ide_end_request(drive, real_rq, 0, bad_sectors);
+
+		printk(KERN_ERR "%s: failed barrier write: "
+				"sector=%Lx(good=%d/bad=%d)\n",
+				drive->name, (unsigned long long)sector,
+				good_sectors, bad_sectors);
+	}
+
+	drive->doing_barrier = 0;
+}
+
 /**
  *	ide_end_drive_cmd	-	end an explicit drive command
  *	@drive: command 
@@ -197,6 +384,8 @@
 				args->hobRegister[IDE_DATA_OFFSET]	= (data >> 8) & 0xFF;
 			}
 			args->tfRegister[IDE_ERROR_OFFSET]   = err;
+			/* be sure we're looking at the low order bits */
+			hwif->OUTB(drive->ctl & ~0x80, IDE_CONTROL_REG);
 			args->tfRegister[IDE_NSECTOR_OFFSET] = hwif->INB(IDE_NSECTOR_REG);
 			args->tfRegister[IDE_SECTOR_OFFSET]  = hwif->INB(IDE_SECTOR_REG);
 			args->tfRegister[IDE_LCYL_OFFSET]    = hwif->INB(IDE_LCYL_REG);
@@ -226,6 +415,10 @@
 
 	spin_lock_irqsave(&ide_lock, flags);
 	blkdev_dequeue_request(rq);
+
+	if (blk_barrier_preflush(rq) || blk_barrier_postflush(rq))
+		ide_complete_barrier(drive, rq, err);
+
 	HWGROUP(drive)->rq = NULL;
 	end_that_request_last(rq);
 	spin_unlock_irqrestore(&ide_lock, flags);
@@ -501,7 +694,9 @@
  
 		if (!args)
 			goto done;
- 
+
+		hwif->data_phase = args->data_phase;
+
 		if (args->tf_out_flags.all != 0) 
 			return flagged_taskfile(drive, args);
 		return do_rw_taskfile(drive, args);
@@ -712,6 +907,22 @@
 repeat:	
 	best = NULL;
 	drive = hwgroup->drive;
+
+	/*
+	 * drive is doing pre-flush, ordered write, post-flush sequence. even
+	 * though that is 3 requests, it must be seen as a single transaction.
+	 * we must not preempt this drive until that is complete
+	 */
+	if (drive->doing_barrier) {
+		/*
+		 * small race where queue could get replugged during
+		 * the 3-request flush cycle, just yank the plug since
+		 * we want it to finish asap
+		 */
+		blk_remove_plug(drive->queue);
+		return drive;
+	}
+
 	do {
 		if ((!drive->sleep || time_after_eq(jiffies, drive->sleep))
 		    && !elv_queue_empty(drive->queue)) {
@@ -868,6 +1079,13 @@
 		}
 
 		/*
+		 * if rq is a barrier write, issue pre cache flush if not
+		 * already done
+		 */
+		if (blk_barrier_rq(rq) && !blk_barrier_preflush(rq))
+			rq = ide_queue_flush_cmd(drive, rq, 0);
+
+		/*
 		 * Sanity: don't accept a request that isn't a PM request
 		 * if we are currently power managed. This is very important as
 		 * blk_stop_queue() doesn't prevent the elv_next_request()
@@ -917,7 +1135,9 @@
  */
 void do_ide_request(request_queue_t *q)
 {
-	ide_do_request(q->queuedata, IDE_NO_IRQ);
+	ide_drive_t *drive = q->queuedata;
+
+	ide_do_request(HWGROUP(drive), IDE_NO_IRQ);
 }
 
 /*
@@ -1286,6 +1506,7 @@
 {
 	memset(rq, 0, sizeof(*rq));
 	rq->flags = REQ_DRIVE_CMD;
+	rq->ref_count = 1;
 }
 
 EXPORT_SYMBOL(ide_init_drive_cmd);
diff -Nru a/drivers/ide/ide-iops.c b/drivers/ide/ide-iops.c
--- a/drivers/ide/ide-iops.c	2004-10-18 14:56:28 -07:00
+++ b/drivers/ide/ide-iops.c	2004-10-18 14:56:28 -07:00
@@ -112,57 +112,57 @@
 
 static u8 ide_mm_inb (unsigned long port)
 {
-	return (u8) readb(port);
+	return (u8) readb((void __iomem *) port);
 }
 
 static u16 ide_mm_inw (unsigned long port)
 {
-	return (u16) readw(port);
+	return (u16) readw((void __iomem *) port);
 }
 
 static void ide_mm_insw (unsigned long port, void *addr, u32 count)
 {
-	__ide_mm_insw(port, addr, count);
+	__ide_mm_insw((void __iomem *) port, addr, count);
 }
 
 static u32 ide_mm_inl (unsigned long port)
 {
-	return (u32) readl(port);
+	return (u32) readl((void __iomem *) port);
 }
 
 static void ide_mm_insl (unsigned long port, void *addr, u32 count)
 {
-	__ide_mm_insl(port, addr, count);
+	__ide_mm_insl((void __iomem *) port, addr, count);
 }
 
 static void ide_mm_outb (u8 value, unsigned long port)
 {
-	writeb(value, port);
+	writeb(value, (void __iomem *) port);
 }
 
 static void ide_mm_outbsync (ide_drive_t *drive, u8 value, unsigned long port)
 {
-	writeb(value, port);	
+	writeb(value, (void __iomem *) port);
 }
 
 static void ide_mm_outw (u16 value, unsigned long port)
 {
-	writew(value, port);
+	writew(value, (void __iomem *) port);
 }
 
 static void ide_mm_outsw (unsigned long port, void *addr, u32 count)
 {
-	__ide_mm_outsw(port, addr, count);
+	__ide_mm_outsw((void __iomem *) port, addr, count);
 }
 
 static void ide_mm_outl (u32 value, unsigned long port)
 {
-	writel(value, port);
+	writel(value, (void __iomem *) port);
 }
 
 static void ide_mm_outsl (unsigned long port, void *addr, u32 count)
 {
-	__ide_mm_outsl(port, addr, count);
+	__ide_mm_outsl((void __iomem *) port, addr, count);
 }
 
 void default_hwif_mmiops (ide_hwif_t *hwif)
@@ -1096,7 +1096,6 @@
 			drive->failures = 0;
 		} else {
 			drive->failures++;
-#if FANCY_STATUS_DUMPS
 			printk("master: ");
 			switch (tmp & 0x7f) {
 				case 1: printk("passed");
@@ -1114,9 +1113,6 @@
 			if (tmp & 0x80)
 				printk("; slave: failed");
 			printk("\n");
-#else
-			printk("failed\n");
-#endif /* FANCY_STATUS_DUMPS */
 		}
 	}
 	hwgroup->poll_timeout = 0;	/* done polling */
diff -Nru a/drivers/ide/ide-lib.c b/drivers/ide/ide-lib.c
--- a/drivers/ide/ide-lib.c	2004-10-18 14:57:04 -07:00
+++ b/drivers/ide/ide-lib.c	2004-10-18 14:57:04 -07:00
@@ -465,7 +465,6 @@
 	status.all = stat;
 	local_irq_set(flags);
 	printk("%s: %s: status=0x%02x", drive->name, msg, stat);
-#if FANCY_STATUS_DUMPS
 	printk(" { ");
 	if (status.b.bsy)
 		printk("Busy ");
@@ -479,19 +478,16 @@
 		if (status.b.check)	printk("Error ");
 	}
 	printk("}");
-#endif	/* FANCY_STATUS_DUMPS */
 	printk("\n");
 	if ((status.all & (status.b.bsy|status.b.check)) == status.b.check) {
 		error.all = HWIF(drive)->INB(IDE_ERROR_REG);
 		printk("%s: %s: error=0x%02x", drive->name, msg, error.all);
-#if FANCY_STATUS_DUMPS
 		if (error.b.ili)	printk("IllegalLengthIndication ");
 		if (error.b.eom)	printk("EndOfMedia ");
 		if (error.b.abrt)	printk("Aborted Command ");
 		if (error.b.mcr)	printk("MediaChangeRequested ");
 		if (error.b.sense_key)	printk("LastFailedSense 0x%02x ",
 						error.b.sense_key);
-#endif	/* FANCY_STATUS_DUMPS */
 		printk("\n");
 	}
 	local_irq_restore(flags);
diff -Nru a/drivers/ide/ide-probe.c b/drivers/ide/ide-probe.c
--- a/drivers/ide/ide-probe.c	2004-10-18 14:56:33 -07:00
+++ b/drivers/ide/ide-probe.c	2004-10-18 14:56:33 -07:00
@@ -389,15 +389,6 @@
 				 */
 				printk("%s: IRQ probe failed (0x%lx)\n",
 					drive->name, cookie);
-#ifdef CONFIG_BLK_DEV_CMD640
-#ifdef CMD640_DUMP_REGS
-				if (hwif->chipset == ide_cmd640) {
-					printk("%s: Hmmm.. probably a driver "
-						"problem.\n", drive->name);
-					CMD640_DUMP_REGS;
-				}
-#endif /* CMD640_DUMP_REGS */
-#endif /* CONFIG_BLK_DEV_CMD640 */
 			}
 		}
 	}
@@ -635,12 +626,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 +661,6 @@
 	
 	return rc;
 }
-#endif
 
 /*
  * This routine only knows how to look for drive units 0 and 1
@@ -717,7 +706,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 +726,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 +736,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 ||
@@ -893,11 +892,15 @@
 	if (!q)
 		return 1;
 
-	q->queuedata = HWGROUP(drive);
+	q->queuedata = drive;
 	blk_queue_segment_boundary(q, 0xffff);
 
-	if (!hwif->rqsize)
-		hwif->rqsize = hwif->no_lba48 ? 256 : 65536;
+	if (!hwif->rqsize) {
+		if (hwif->no_lba48 || hwif->no_lba48_dma)
+			hwif->rqsize = 256;
+		else
+			hwif->rqsize = 65536;
+	}
 	if (hwif->rqsize < max_sectors)
 		max_sectors = hwif->rqsize;
 	blk_queue_max_sectors(q, max_sectors);
@@ -906,11 +909,11 @@
 	/* When we have an IOMMU, we may have a problem where pci_map_sg()
 	 * creates segments that don't completely match our boundary
 	 * requirements and thus need to be broken up again. Because it
-	 * doesn't align properly neither, we may actually have to break up
+	 * doesn't align properly either, we may actually have to break up
 	 * to more segments than what was we got in the first place, a max
 	 * worst case is twice as many.
 	 * This will be fixed once we teach pci_map_sg() about our boundary
-	 * requirements, hopefully soon
+	 * requirements, hopefully soon. *FIXME*
 	 */
 	if (!PCI_DMA_BUS_IS_PHYS)
 		max_sg_entries >>= 1;
diff -Nru a/drivers/ide/ide-proc.c b/drivers/ide/ide-proc.c
--- a/drivers/ide/ide-proc.c	2004-10-18 14:56:32 -07:00
+++ b/drivers/ide/ide-proc.c	2004-10-18 14:56:32 -07:00
@@ -360,27 +360,14 @@
 	int		err = 0;
 
 	len = sprintf(page, "\n");
-	
-	if (drive)
-	{
+
+	if (drive) {
 		unsigned short *val = (unsigned short *) page;
-		
-		/*
-		 *	The current code can't handle a driverless
-		 *	identify query taskfile. Now the right fix is
-		 *	to add a 'default' driver but that is a bit
-		 *	more work. 
-		 *
-		 *	FIXME: this has to be fixed for hotswap devices
-		 */
-		 
-		if(DRIVER(drive))
-			err = taskfile_lib_get_identify(drive, page);
-		else	/* This relies on the ID changes */
-			val = (unsigned short *)drive->id;
 
-		if(!err)
-		{						
+		BUG_ON(!drive->driver);
+
+		err = taskfile_lib_get_identify(drive, page);
+		if (!err) {
 			char *out = ((char *)page) + (SECTOR_WORDS * 4);
 			page = out;
 			do {
diff -Nru a/drivers/ide/ide-tape.c b/drivers/ide/ide-tape.c
--- a/drivers/ide/ide-tape.c	2004-10-18 14:56:28 -07:00
+++ b/drivers/ide/ide-tape.c	2004-10-18 14:56:28 -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-taskfile.c b/drivers/ide/ide-taskfile.c
--- a/drivers/ide/ide-taskfile.c	2004-10-18 14:55:54 -07:00
+++ b/drivers/ide/ide-taskfile.c	2004-10-18 14:55:54 -07:00
@@ -96,36 +96,13 @@
 	else
 		args.tfRegister[IDE_COMMAND_OFFSET]	= WIN_PIDENTIFY;
 	args.command_type = IDE_DRIVE_TASK_IN;
+	args.data_phase   = TASKFILE_IN;
 	args.handler	  = &task_in_intr;
 	return ide_raw_taskfile(drive, &args, buf);
 }
 
 EXPORT_SYMBOL(taskfile_lib_get_identify);
 
-#ifdef CONFIG_IDE_TASK_IOCTL_DEBUG
-void debug_taskfile (ide_drive_t *drive, ide_task_t *args)
-{
-	printk(KERN_INFO "%s: ", drive->name);
-//	printk("TF.0=x%02x ", args->tfRegister[IDE_DATA_OFFSET]);
-	printk("TF.1=x%02x ", args->tfRegister[IDE_FEATURE_OFFSET]);
-	printk("TF.2=x%02x ", args->tfRegister[IDE_NSECTOR_OFFSET]);
-	printk("TF.3=x%02x ", args->tfRegister[IDE_SECTOR_OFFSET]);
-	printk("TF.4=x%02x ", args->tfRegister[IDE_LCYL_OFFSET]);
-	printk("TF.5=x%02x ", args->tfRegister[IDE_HCYL_OFFSET]);
-	printk("TF.6=x%02x ", args->tfRegister[IDE_SELECT_OFFSET]);
-	printk("TF.7=x%02x\n", args->tfRegister[IDE_COMMAND_OFFSET]);
-	printk(KERN_INFO "%s: ", drive->name);
-//	printk("HTF.0=x%02x ", args->hobRegister[IDE_DATA_OFFSET]);
-	printk("HTF.1=x%02x ", args->hobRegister[IDE_FEATURE_OFFSET]);
-	printk("HTF.2=x%02x ", args->hobRegister[IDE_NSECTOR_OFFSET]);
-	printk("HTF.3=x%02x ", args->hobRegister[IDE_SECTOR_OFFSET]);
-	printk("HTF.4=x%02x ", args->hobRegister[IDE_LCYL_OFFSET]);
-	printk("HTF.5=x%02x ", args->hobRegister[IDE_HCYL_OFFSET]);
-	printk("HTF.6=x%02x ", args->hobRegister[IDE_SELECT_OFFSET]);
-	printk("HTF.7=x%02x\n", args->hobRegister[IDE_CONTROL_OFFSET_HOB]);
-}
-#endif /* CONFIG_IDE_TASK_IOCTL_DEBUG */
-
 ide_startstop_t do_rw_taskfile (ide_drive_t *drive, ide_task_t *task)
 {
 	ide_hwif_t *hwif	= HWIF(drive);
@@ -133,10 +110,6 @@
 	hob_struct_t *hobfile	= (hob_struct_t *) task->hobRegister;
 	u8 HIHI			= (drive->addressing == 1) ? 0xE0 : 0xEF;
 
-#ifdef CONFIG_IDE_TASK_IOCTL_DEBUG
-	void debug_taskfile(drive, task);
-#endif /* CONFIG_IDE_TASK_IOCTL_DEBUG */
-
 	/* ALL Command Block Executions SHALL clear nIEN, unless otherwise */
 	if (IDE_CONTROL_REG) {
 		/* clear nIEN */
@@ -367,12 +340,44 @@
 	return stat;
 }
 
+static inline void ide_pio_datablock(ide_drive_t *drive, struct request *rq,
+				     unsigned int write)
+{
+	switch (drive->hwif->data_phase) {
+	case TASKFILE_MULTI_IN:
+	case TASKFILE_MULTI_OUT:
+		task_multi_sectors(drive, rq, write);
+		break;
+	default:
+		task_sectors(drive, rq, 1, write);
+		break;
+	}
+}
+
 #ifdef CONFIG_IDE_TASKFILE_IO
 static ide_startstop_t task_error(ide_drive_t *drive, struct request *rq,
-				  const char *s, u8 stat, unsigned cur_bad)
+				  const char *s, u8 stat)
 {
 	if (rq->bio) {
-		int sectors = rq->hard_nr_sectors - rq->nr_sectors - cur_bad;
+		int sectors = rq->hard_nr_sectors - rq->nr_sectors;
+
+		switch (drive->hwif->data_phase) {
+		case TASKFILE_IN:
+			if (rq->nr_sectors)
+				break;
+			/* fall through */
+		case TASKFILE_OUT:
+			sectors--;
+			break;
+		case TASKFILE_MULTI_IN:
+			if (rq->nr_sectors)
+				break;
+			/* fall through */
+		case TASKFILE_MULTI_OUT:
+			sectors -= drive->mult_count;
+		default:
+			break;
+		}
 
 		if (sectors > 0)
 			drive->driver->end_request(drive, 1, sectors);
@@ -380,7 +385,7 @@
 	return drive->driver->error(drive, s, stat);
 }
 #else
-# define task_error(d, rq, s, stat, cur_bad) drive->driver->error(d, s, stat)
+# define task_error(d, rq, s, stat) drive->driver->error(d, s, stat)
 #endif
 
 static void task_end_request(ide_drive_t *drive, struct request *rq, u8 stat)
@@ -398,7 +403,7 @@
 }
 
 /*
- * Handler for command with PIO data-in phase (Read).
+ * Handler for command with PIO data-in phase (Read/Read Multiple).
  */
 ide_startstop_t task_in_intr (ide_drive_t *drive)
 {
@@ -407,19 +412,19 @@
 
 	if (!OK_STAT(stat, DATA_READY, BAD_R_STAT)) {
 		if (stat & (ERR_STAT | DRQ_STAT))
-			return task_error(drive, rq, __FUNCTION__, stat, 0);
+			return task_error(drive, rq, __FUNCTION__, stat);
 		/* No data yet, so wait for another IRQ. */
 		ide_set_handler(drive, &task_in_intr, WAIT_WORSTCASE, NULL);
 		return ide_started;
 	}
 
-	task_sectors(drive, rq, 1, IDE_PIO_IN);
+	ide_pio_datablock(drive, rq, 0);
 
 	/* If it was the last datablock check status and finish transfer. */
 	if (!rq->nr_sectors) {
 		stat = wait_drive_not_busy(drive);
 		if (!OK_STAT(stat, 0, BAD_R_STAT))
-			return task_error(drive, rq, __FUNCTION__, stat, 1);
+			return task_error(drive, rq, __FUNCTION__, stat);
 		task_end_request(drive, rq, stat);
 		return ide_stopped;
 	}
@@ -432,41 +437,7 @@
 EXPORT_SYMBOL(task_in_intr);
 
 /*
- * Handler for command with PIO data-in phase (Read Multiple).
- */
-ide_startstop_t task_mulin_intr (ide_drive_t *drive)
-{
-	struct request *rq = HWGROUP(drive)->rq;
-	u8 stat = HWIF(drive)->INB(IDE_STATUS_REG);
-
-	if (!OK_STAT(stat, DATA_READY, BAD_R_STAT)) {
-		if (stat & (ERR_STAT | DRQ_STAT))
-			return task_error(drive, rq, __FUNCTION__, stat, 0);
-		/* No data yet, so wait for another IRQ. */
-		ide_set_handler(drive, &task_mulin_intr, WAIT_WORSTCASE, NULL);
-		return ide_started;
-	}
-
-	task_multi_sectors(drive, rq, IDE_PIO_IN);
-
-	/* If it was the last datablock check status and finish transfer. */
-	if (!rq->nr_sectors) {
-		stat = wait_drive_not_busy(drive);
-		if (!OK_STAT(stat, 0, BAD_R_STAT))
-			return task_error(drive, rq, __FUNCTION__, stat, drive->mult_count);
-		task_end_request(drive, rq, stat);
-		return ide_stopped;
-	}
-
-	/* Still data left to transfer. */
-	ide_set_handler(drive, &task_mulin_intr, WAIT_WORSTCASE, NULL);
-
-	return ide_started;
-}
-EXPORT_SYMBOL(task_mulin_intr);
-
-/*
- * Handler for command with PIO data-out phase (Write).
+ * Handler for command with PIO data-out phase (Write/Write Multiple).
  */
 ide_startstop_t task_out_intr (ide_drive_t *drive)
 {
@@ -475,11 +446,11 @@
 
 	stat = HWIF(drive)->INB(IDE_STATUS_REG);
 	if (!OK_STAT(stat, DRIVE_READY, drive->bad_wstat))
-		return task_error(drive, rq, __FUNCTION__, stat, 1);
+		return task_error(drive, rq, __FUNCTION__, stat);
 
 	/* Deal with unexpected ATA data phase. */
 	if (((stat & DRQ_STAT) == 0) ^ !rq->nr_sectors)
-		return task_error(drive, rq, __FUNCTION__, stat, 1);
+		return task_error(drive, rq, __FUNCTION__, stat);
 
 	if (!rq->nr_sectors) {
 		task_end_request(drive, rq, stat);
@@ -487,7 +458,7 @@
 	}
 
 	/* Still data left to transfer. */
-	task_sectors(drive, rq, 1, IDE_PIO_OUT);
+	ide_pio_datablock(drive, rq, 1);
 	ide_set_handler(drive, &task_out_intr, WAIT_WORSTCASE, NULL);
 
 	return ide_started;
@@ -501,8 +472,10 @@
 
 	if (ide_wait_stat(&startstop, drive, DATA_READY,
 			  drive->bad_wstat, WAIT_DRQ)) {
-		printk(KERN_ERR "%s: no DRQ after issuing WRITE%s\n",
-				drive->name, drive->addressing ? "_EXT" : "");
+		printk(KERN_ERR "%s: no DRQ after issuing %sWRITE%s\n",
+				drive->name,
+				drive->hwif->data_phase ? "MULT" : "",
+				drive->addressing ? "_EXT" : "");
 		return startstop;
 	}
 
@@ -510,62 +483,12 @@
 		local_irq_disable();
 
 	ide_set_handler(drive, &task_out_intr, WAIT_WORSTCASE, NULL);
-	task_sectors(drive, rq, 1, IDE_PIO_OUT);
+	ide_pio_datablock(drive, rq, 1);
 
 	return ide_started;
 }
 EXPORT_SYMBOL(pre_task_out_intr);
 
-/*
- * Handler for command with PIO data-out phase (Write Multiple).
- */
-ide_startstop_t task_mulout_intr (ide_drive_t *drive)
-{
-	struct request *rq = HWGROUP(drive)->rq;
-	u8 stat;
-
-	stat = HWIF(drive)->INB(IDE_STATUS_REG);
-	if (!OK_STAT(stat, DRIVE_READY, drive->bad_wstat))
-		return task_error(drive, rq, __FUNCTION__, stat, drive->mult_count);
-
-	/* Deal with unexpected ATA data phase. */
-	if (((stat & DRQ_STAT) == 0) ^ !rq->nr_sectors)
-		return task_error(drive, rq, __FUNCTION__, stat, drive->mult_count);
-
-	if (!rq->nr_sectors) {
-		task_end_request(drive, rq, stat);
-		return ide_stopped;
-	}
-
-	/* Still data left to transfer. */
-	task_multi_sectors(drive, rq, IDE_PIO_OUT);
-	ide_set_handler(drive, &task_mulout_intr, WAIT_WORSTCASE, NULL);
-
-	return ide_started;
-}
-EXPORT_SYMBOL(task_mulout_intr);
-
-ide_startstop_t pre_task_mulout_intr (ide_drive_t *drive, struct request *rq)
-{
-	ide_startstop_t startstop;
-
-	if (ide_wait_stat(&startstop, drive, DATA_READY,
-			  drive->bad_wstat, WAIT_DRQ)) {
-		printk(KERN_ERR "%s: no DRQ after issuing MULTWRITE%s\n",
-				drive->name, drive->addressing ? "_EXT" : "");
-		return startstop;
-	}
-
-	if (!drive->unmask)
-		local_irq_disable();
-
-	ide_set_handler(drive, &task_mulout_intr, WAIT_WORSTCASE, NULL);
-	task_multi_sectors(drive, rq, IDE_PIO_OUT);
-
-	return ide_started;
-}
-EXPORT_SYMBOL(pre_task_mulout_intr);
-
 int ide_diag_taskfile (ide_drive_t *drive, ide_task_t *args, unsigned long data_size, u8 *buf)
 {
 	struct request rq;
@@ -688,19 +611,6 @@
 		case TASKFILE_IN_DMA:
 			err = ide_diag_taskfile(drive, &args, taskin, inbuf);
 			break;
-		case TASKFILE_IN_OUT:
-#if 0
-			args.prehandler = &pre_task_out_intr;
-			args.handler = &task_out_intr;
-			err = ide_diag_taskfile(drive, &args, taskout, outbuf);
-			args.prehandler = NULL;
-			args.handler = &task_in_intr;
-			err = ide_diag_taskfile(drive, &args, taskin, inbuf);
-			break;
-#else
-			err = -EFAULT;
-			goto abort;
-#endif
 		case TASKFILE_MULTI_OUT:
 			if (!drive->mult_count) {
 				/* (hs): give up if multcount is not set */
@@ -710,10 +620,7 @@
 				err = -EPERM;
 				goto abort;
 			}
-			args.prehandler = &pre_task_mulout_intr;
-			args.handler = &task_mulout_intr;
-			err = ide_diag_taskfile(drive, &args, taskout, outbuf);
-			break;
+			/* fall through */
 		case TASKFILE_OUT:
 			args.prehandler = &pre_task_out_intr;
 			args.handler = &task_out_intr;
@@ -728,9 +635,7 @@
 				err = -EPERM;
 				goto abort;
 			}
-			args.handler = &task_mulin_intr;
-			err = ide_diag_taskfile(drive, &args, taskin, inbuf);
-			break;
+			/* fall through */
 		case TASKFILE_IN:
 			args.handler = &task_in_intr;
 			err = ide_diag_taskfile(drive, &args, taskin, inbuf);
@@ -906,11 +811,6 @@
 #if DEBUG_TASKFILE
 	u8 status;
 #endif
-
-
-#ifdef CONFIG_IDE_TASK_IOCTL_DEBUG
-	void debug_taskfile(drive, task);
-#endif /* CONFIG_IDE_TASK_IOCTL_DEBUG */
 
 	if (task->data_phase == TASKFILE_MULTI_IN ||
 	    task->data_phase == TASKFILE_MULTI_OUT) {
diff -Nru a/drivers/ide/ide.c b/drivers/ide/ide.c
--- a/drivers/ide/ide.c	2004-10-18 14:56:27 -07:00
+++ b/drivers/ide/ide.c	2004-10-18 14:56:27 -07:00
@@ -320,13 +320,19 @@
 #endif
 }
 
-/*
- * ide_system_bus_speed() returns what we think is the system VESA/PCI
- * bus speed (in MHz).  This is used for calculating interface PIO timings.
- * The default is 40 for known PCI systems, 50 otherwise.
- * The "idebus=xx" parameter can be used to override this value.
- * The actual value to be used is computed/displayed the first time through.
+/**
+ *	ide_system_bus_speed	-	guess bus speed
+ *
+ *	ide_system_bus_speed() returns what we think is the system VESA/PCI
+ *	bus speed (in MHz). This is used for calculating interface PIO timings.
+ *	The default is 40 for known PCI systems, 50 otherwise.
+ *	The "idebus=xx" parameter can be used to override this value.
+ *	The actual value to be used is computed/displayed the first time
+ *	through. Drivers should only use this as a last resort.
+ *
+ *	Returns a guessed speed in MHz.
  */
+
 int ide_system_bus_speed (void)
 {
 	if (!system_bus_speed) {
@@ -347,10 +353,15 @@
 	return system_bus_speed;
 }
 
-/*
- * current_capacity() returns the capacity (in sectors) of a drive
- * according to its current geometry/LBA settings.
+/**
+ *	current_capacity	-	drive capacity
+ *	@drive: drive to query
+ *
+ *	Return the current capacity (in sectors) of a drive according to
+ *	its current geometry/LBA settings. Empty removables are reported
+ *	as size zero.
  */
+
 sector_t current_capacity (ide_drive_t *drive)
 {
 	if (!drive->present)
@@ -360,9 +371,17 @@
 
 EXPORT_SYMBOL(current_capacity);
 
-/*
- * Error reporting, in human readable form (luxurious, but a memory hog).
+/**
+ *	ide_dump_status		-	translate ATA error
+ *	@drive: drive the error occured on
+ *	@msg: information string
+ *	@stat: status byte
+ *
+ *	Error reporting, in human readable form (luxurious, but a memory hog).
+ *	Combines the drive name, message and status byte to provide a
+ *	user understandable explanation of the device error.
  */
+
 u8 ide_dump_status (ide_drive_t *drive, const char *msg, u8 stat)
 {
 	ide_hwif_t *hwif = HWIF(drive);
@@ -371,7 +390,6 @@
 
 	local_irq_set(flags);
 	printk(KERN_WARNING "%s: %s: status=0x%02x", drive->name, msg, stat);
-#if FANCY_STATUS_DUMPS
 	printk(" { ");
 	if (stat & BUSY_STAT) {
 		printk("Busy ");
@@ -385,12 +403,10 @@
 		if (stat & ERR_STAT)	printk("Error ");
 	}
 	printk("}");
-#endif	/* FANCY_STATUS_DUMPS */
 	printk("\n");
 	if ((stat & (BUSY_STAT|ERR_STAT)) == ERR_STAT) {
 		err = hwif->INB(IDE_ERROR_REG);
 		printk("%s: %s: error=0x%02x", drive->name, msg, err);
-#if FANCY_STATUS_DUMPS
 		if (drive->media == ide_disk) {
 			printk(" { ");
 			if (err & ABRT_ERR)	printk("DriveStatusError ");
@@ -434,9 +450,34 @@
 					printk(", sector=%llu", (unsigned long long)HWGROUP(drive)->rq->sector);
 			}
 		}
-#endif	/* FANCY_STATUS_DUMPS */
 		printk("\n");
 	}
+	{
+		struct request *rq;
+		int opcode = 0x100;
+
+		spin_lock(&ide_lock);
+		rq = NULL;
+		if (HWGROUP(drive))
+			rq = HWGROUP(drive)->rq;
+		spin_unlock(&ide_lock);
+		if (!rq)
+			goto out;
+		if (rq->flags & (REQ_DRIVE_CMD | REQ_DRIVE_TASK)) {
+			char *args = rq->buffer;
+			if (args)
+				opcode = args[0];
+		} else if (rq->flags & REQ_DRIVE_TASKFILE) {
+			ide_task_t *args = rq->special;
+			if (args) {
+				task_struct_t *tf = (task_struct_t *) args->tfRegister;
+				opcode = tf->command;
+			}
+		}
+
+		printk("ide: failed opcode was %x\n", opcode);
+	}
+out:
 	local_irq_restore(flags);
 	return err;
 }
@@ -448,11 +489,17 @@
 	return -ENXIO;
 }
 
+/*
+ *	drives_lock protects the list of drives, drivers_lock the
+ *	list of drivers.  Currently nobody takes both at once.
+ */
+
 static spinlock_t drives_lock = SPIN_LOCK_UNLOCKED;
 static spinlock_t drivers_lock = SPIN_LOCK_UNLOCKED;
 static LIST_HEAD(drivers);
 
-/* Iterator */
+/* Iterator for the driver list. */
+
 static void *m_start(struct seq_file *m, loff_t *pos)
 {
 	struct list_head *p;
@@ -463,22 +510,26 @@
 			return list_entry(p, ide_driver_t, drivers);
 	return NULL;
 }
+
 static void *m_next(struct seq_file *m, void *v, loff_t *pos)
 {
 	struct list_head *p = ((ide_driver_t *)v)->drivers.next;
 	(*pos)++;
 	return p==&drivers ? NULL : list_entry(p, ide_driver_t, drivers);
 }
+
 static void m_stop(struct seq_file *m, void *v)
 {
 	spin_unlock(&drivers_lock);
 }
+
 static int show_driver(struct seq_file *m, void *v)
 {
 	ide_driver_t *driver = v;
 	seq_printf(m, "%s version %s\n", driver->name, driver->version);
 	return 0;
 }
+
 struct seq_operations ide_drivers_op = {
 	.start	= m_start,
 	.next	= m_next,
@@ -515,6 +566,7 @@
  *	MMIO leaves it to the controller driver,
  *	PIO will migrate this way over time.
  */
+
 int ide_hwif_request_regions(ide_hwif_t *hwif)
 {
 	unsigned long addr;
@@ -564,6 +616,7 @@
  *	importantly our caller should be doing this so we need to 
  *	restructure this as a helper function for drivers.
  */
+
 void ide_hwif_release_regions(ide_hwif_t *hwif)
 {
 	u32 i = 0;
@@ -581,7 +634,15 @@
 			release_region(hwif->io_ports[i], 1);
 }
 
-/* restore hwif to a sane state */
+/**
+ *	ide_hwif_restore	-	restore hwif to template
+ *	@hwif: hwif to update
+ *	@tmp_hwif: template
+ *
+ *	Restore hwif to a previous state by copying most settngs
+ *	from the template.
+ */
+
 static void ide_hwif_restore(ide_hwif_t *hwif, ide_hwif_t *tmp_hwif)
 {
 	hwif->hwgroup			= tmp_hwif->hwgroup;
@@ -702,18 +763,13 @@
 void ide_unregister(unsigned int index)
 {
 	ide_drive_t *drive;
-	ide_hwif_t *hwif, *g, *tmp_hwif;
+	ide_hwif_t *hwif, *g;
+	static ide_hwif_t tmp_hwif; /* protected by ide_cfg_sem */
 	ide_hwgroup_t *hwgroup;
 	int irq_count = 0, unit, i;
 
 	BUG_ON(index >= MAX_HWIFS);
 
-	tmp_hwif = kmalloc(sizeof(*tmp_hwif), GFP_KERNEL|__GFP_NOFAIL);
-	if (!tmp_hwif) {
-		printk(KERN_ERR "%s: unable to allocate memory\n", __FUNCTION__);
-		return;
-	}
-
 	BUG_ON(in_interrupt());
 	BUG_ON(irqs_disabled());
 	down(&ide_cfg_sem);
@@ -860,19 +916,17 @@
 	}
 
 	/* copy original settings */
-	*tmp_hwif = *hwif;
+	tmp_hwif = *hwif;
 
 	/* restore hwif data to pristine status */
 	init_hwif_data(hwif, index);
 	init_hwif_default(hwif, index);
 
-	ide_hwif_restore(hwif, tmp_hwif);
+	ide_hwif_restore(hwif, &tmp_hwif);
 
 abort:
 	spin_unlock_irq(&ide_lock);
 	up(&ide_cfg_sem);
-
-	kfree(tmp_hwif);
 }
 
 EXPORT_SYMBOL(ide_unregister);
@@ -931,10 +985,17 @@
  */
 }
 
-/*
- * Register an IDE interface, specifying exactly the registers etc
- * Set init=1 iff calling before probes have taken place.
+/**
+ *	ide_register_hw		-	register IDE interface
+ *	@hw: hardware registers
+ *	@hwifp: pointer to returned hwif
+ *
+ *	Register an IDE interface, specifying exactly the registers etc.
+ *	Set init=1 iff calling before probes have taken place.
+ *
+ *	Returns -1 on error.
  */
+
 int ide_register_hw (hw_regs_t *hw, ide_hwif_t **hwifp)
 {
 	int index, retry = 1;
@@ -1188,6 +1249,15 @@
 	return val;
 }
 
+/**
+ *	ide_spin_wait_hwgroup	-	wait for group
+ *	@drive: drive in the group
+ *
+ *	Wait for an IDE device group to go non busy and then return
+ *	holding the ide_lock which guards the hwgroup->busy status
+ *	and right to use it.
+ */
+
 int ide_spin_wait_hwgroup (ide_drive_t *drive)
 {
 	ide_hwgroup_t *hwgroup = HWGROUP(drive);
@@ -1229,6 +1299,7 @@
  *	to the driver to change settings, and then wait on a sema for completion.
  *	The current scheme of polling is kludgy, though safe enough.
  */
+
 int ide_write_setting (ide_drive_t *drive, ide_settings_t *setting, int val)
 {
 	int i;
@@ -1322,22 +1393,14 @@
 	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;
-}
+/**
+ *	ide_add_generic_settings	-	generic ide settings
+ *	@drive: drive being configured
+ *
+ *	Add the generic parts of the system settings to the /proc files and
+ *	ioctls for this IDE device. The caller must not be holding the
+ *	ide_setting_sem.
+ */
 
 void ide_add_generic_settings (ide_drive_t *drive)
 {
@@ -1353,10 +1416,15 @@
 	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);
 }
 
+/**
+ *	system_bus_clock	-	clock guess
+ *
+ *	External version of the bus clock guess used by very old IDE drivers
+ *	for things like VLB timings. Should not be used.
+ */
+
 int system_bus_clock (void)
 {
 	return((int) ((!system_bus_speed) ? ide_system_bus_speed() : system_bus_speed ));
@@ -1391,6 +1459,22 @@
 	return 1;
 }
 
+/**
+ *	ata_attach		-	attach an ATA/ATAPI device
+ *	@drive: drive to attach
+ *
+ *	Takes a drive that is as yet not assigned to any midlayer IDE
+ *	driver (or is assigned to the default driver) and figures out
+ *	which driver would like to own it. If nobody claims the drive
+ *	then it is automatically attached to the default driver used for
+ *	unclaimed objects.
+ *
+ *	A return of zero indicates attachment to a driver, of one
+ *	attachment to the default driver.
+ *
+ *	Takes drivers_lock.
+ */
+
 int ata_attach(ide_drive_t *drive)
 {
 	struct list_head *p;
@@ -2199,6 +2283,20 @@
 
 EXPORT_SYMBOL(ide_register_subdriver);
 
+/**
+ *	ide_unregister_subdriver	-	disconnect drive from driver
+ *	@drive: drive to unplug
+ *
+ *	Disconnect a drive from the driver it was attached to and then
+ *	clean up the various proc files and other objects attached to it.
+ *
+ *	Takes ide_setting_sem, ide_lock and drives_lock.
+ *	Caller must hold none of the locks.
+ *
+ *	No locking versus subdriver unload because we are moving to the
+ *	default driver anyway. Wants double checking.
+ */
+
 int ide_unregister_subdriver (ide_drive_t *drive)
 {
 	unsigned long flags;
@@ -2234,6 +2332,17 @@
 	return 0;
 }
 
+/**
+ *	ide_register_driver	-	register IDE device driver
+ *	@driver: the IDE device driver
+ *
+ *	Register a new device driver and then scan the devices
+ *	on the IDE bus in case any should be attached to the
+ *	driver we have just registered.  If so attach them.
+ *
+ *	Takes drivers_lock and drives_lock.
+ */
+
 int ide_register_driver(ide_driver_t *driver)
 {
 	struct list_head list;
@@ -2264,6 +2373,17 @@
 }
 
 EXPORT_SYMBOL(ide_register_driver);
+
+/**
+ *	ide_unregister_driver	-	unregister IDE device driver
+ *	@driver: the IDE device driver
+ *
+ *	Called when a driver module is being unloaded. We reattach any
+ *	devices to whatever driver claims them next (typically the default
+ *	driver).
+ *
+ *	Takes drivers_lock and called functions will take ide_setting_sem.
+ */
 
 void ide_unregister_driver(ide_driver_t *driver)
 {
diff -Nru a/drivers/ide/legacy/Makefile b/drivers/ide/legacy/Makefile
--- a/drivers/ide/legacy/Makefile	2004-10-18 14:56:13 -07:00
+++ b/drivers/ide/legacy/Makefile	2004-10-18 14:56:13 -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/ide-cs.c b/drivers/ide/legacy/ide-cs.c
--- a/drivers/ide/legacy/ide-cs.c	2004-10-18 14:56:48 -07:00
+++ b/drivers/ide/legacy/ide-cs.c	2004-10-18 14:56:48 -07:00
@@ -412,12 +412,6 @@
 	/* FIXME: if this fails we need to queue the cleanup somehow
 	   -- need to investigate the required PCMCIA magic */
 	ide_unregister(info->hd);
-	/* deal with brain dead IDE resource management */
-	request_region(link->io.BasePort1, link->io.NumPorts1,
-		       info->node.dev_name);
-	if (link->io.NumPorts2)
-	    request_region(link->io.BasePort2, link->io.NumPorts2,
-			   info->node.dev_name);
     }
     info->ndev = 0;
     link->dev = NULL;
diff -Nru a/drivers/ide/legacy/pdc4030.c b/drivers/ide/legacy/pdc4030.c
--- a/drivers/ide/legacy/pdc4030.c	2004-10-18 14:56:32 -07:00
+++ b/drivers/ide/legacy/pdc4030.c	2004-10-18 14:56:32 -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	2004-10-18 14:57:04 -07:00
+++ b/drivers/ide/legacy/qd65xx.h	2004-10-18 14:57:04 -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/aec62xx.c b/drivers/ide/pci/aec62xx.c
--- a/drivers/ide/pci/aec62xx.c	2004-10-18 14:56:49 -07:00
+++ b/drivers/ide/pci/aec62xx.c	2004-10-18 14:56:49 -07:00
@@ -29,8 +29,6 @@
 static struct pci_dev *aec_devs[AEC_MAX_DEVS];
 static int n_aec_devs;
 
-#undef DEBUG_AEC_REGS
-
 static int aec62xx_get_info (char *buffer, char **addr, off_t offset, int count)
 {
 	char *p = buffer;
@@ -44,9 +42,6 @@
 		struct pci_dev *dev	= aec_devs[i];
 		unsigned long iobase = pci_resource_start(dev, 4);
 		u8 c0 = 0, c1 = 0, art	= 0;
-#ifdef DEBUG_AEC_REGS
-		u8 uart			= 0;
-#endif /* DEBUG_AEC_REGS */
 
 		c0 = inb(iobase + 0x02);
 		c1 = inb(iobase + 0x0a);
@@ -83,24 +78,6 @@
 			p += sprintf(p, "           %s(%s)\n",
 				(c1&0x40)?((art&0xc0)?"UDMA":" DMA"):" PIO",
 				(art&0x80)?"2":(art&0x40)?"1":"0");
-#ifdef DEBUG_AEC_REGS
-			(void) pci_read_config_byte(dev, 0x40, &art);
-			p += sprintf(p, "Active:         0x%02x", art);
-			(void) pci_read_config_byte(dev, 0x42, &art);
-			p += sprintf(p, "             0x%02x", art);
-			(void) pci_read_config_byte(dev, 0x44, &art);
-			p += sprintf(p, "            0x%02x", art);
-			(void) pci_read_config_byte(dev, 0x46, &art);
-			p += sprintf(p, "              0x%02x\n", art);
-			(void) pci_read_config_byte(dev, 0x41, &art);
-			p += sprintf(p, "Recovery:       0x%02x", art);
-			(void) pci_read_config_byte(dev, 0x43, &art);
-			p += sprintf(p, "             0x%02x", art);
-			(void) pci_read_config_byte(dev, 0x45, &art);
-			p += sprintf(p, "            0x%02x", art);
-			(void) pci_read_config_byte(dev, 0x47, &art);
-			p += sprintf(p, "              0x%02x\n", art);
-#endif /* DEBUG_AEC_REGS */
 		} else {
 			/*
 			 * case PCI_DEVICE_ID_ARTOP_ATP860:
@@ -146,28 +123,6 @@
 				((art&0x30)==0x30)?"2":
 				((art&0x20)==0x20)?"1":
 				((art&0x10)==0x10)?"0":"?");
-#ifdef DEBUG_AEC_REGS
-			(void) pci_read_config_byte(dev, 0x40, &art);
-			p += sprintf(p, "Active:         0x%02x", HIGH_4(art));
-			(void) pci_read_config_byte(dev, 0x41, &art);
-			p += sprintf(p, "             0x%02x", HIGH_4(art));
-			(void) pci_read_config_byte(dev, 0x42, &art);
-			p += sprintf(p, "            0x%02x", HIGH_4(art));
-			(void) pci_read_config_byte(dev, 0x43, &art);
-			p += sprintf(p, "              0x%02x\n", HIGH_4(art));
-			(void) pci_read_config_byte(dev, 0x40, &art);
-			p += sprintf(p, "Recovery:       0x%02x", LOW_4(art));
-			(void) pci_read_config_byte(dev, 0x41, &art);
-			p += sprintf(p, "             0x%02x", LOW_4(art));
-			(void) pci_read_config_byte(dev, 0x42, &art);
-			p += sprintf(p, "            0x%02x", LOW_4(art));
-			(void) pci_read_config_byte(dev, 0x43, &art);
-			p += sprintf(p, "              0x%02x\n", LOW_4(art));
-			(void) pci_read_config_byte(dev, 0x49, &uart);
-			p += sprintf(p, "reg49h = 0x%02x ", uart);
-			(void) pci_read_config_byte(dev, 0x4a, &uart);
-			p += sprintf(p, "reg4ah = 0x%02x\n", uart);
-#endif /* DEBUG_AEC_REGS */
 		}
 	}
 	/* p - buffer must be less than 4k! */
@@ -240,6 +195,7 @@
 	unsigned long flags;
 
 	local_irq_save(flags);
+	/* 0x40|(2*drive->dn): Active, 0x41|(2*drive->dn): Recovery */
 	pci_read_config_word(dev, 0x40|(2*drive->dn), &d_conf);
 	tmp0 = pci_bus_clock_list(speed, BUSCLOCK(dev));
 	SPLIT_BYTE(tmp0,tmp1,tmp2);
@@ -268,6 +224,7 @@
 	unsigned long flags;
 
 	local_irq_save(flags);
+	/* high 4-bits: Active, low 4-bits: Recovery */
 	pci_read_config_byte(dev, 0x40|drive->dn, &drive_conf);
 	drive_conf = pci_bus_clock_list(speed, BUSCLOCK(dev));
 	pci_write_config_byte(dev, 0x40|drive->dn, drive_conf);
@@ -540,7 +497,7 @@
 MODULE_DEVICE_TABLE(pci, aec62xx_pci_tbl);
 
 static struct pci_driver driver = {
-	.name		= "AEC62xx IDE",
+	.name		= "AEC62xx_IDE",
 	.id_table	= aec62xx_pci_tbl,
 	.probe		= aec62xx_init_one,
 };
diff -Nru a/drivers/ide/pci/aec62xx.h b/drivers/ide/pci/aec62xx.h
--- a/drivers/ide/pci/aec62xx.h	2004-10-18 14:56:31 -07:00
+++ b/drivers/ide/pci/aec62xx.h	2004-10-18 14:56:31 -07:00
@@ -53,13 +53,6 @@
 	{	0,		0x00,	0x00	}
 };
 
-
-#ifndef HIGH_4
-#define HIGH_4(H)		((H)=(H>>4))
-#endif
-#ifndef LOW_4
-#define LOW_4(L)		((L)=(L-((L>>4)<<4)))
-#endif
 #ifndef SPLIT_BYTE
 #define SPLIT_BYTE(B,H,L)	((H)=(B>>4), (L)=(B-((B>>4)<<4)))
 #endif
diff -Nru a/drivers/ide/pci/alim15x3.c b/drivers/ide/pci/alim15x3.c
--- a/drivers/ide/pci/alim15x3.c	2004-10-18 14:56:28 -07:00
+++ b/drivers/ide/pci/alim15x3.c	2004-10-18 14:56:28 -07:00
@@ -752,8 +752,8 @@
 	hwif->tuneproc = &ali15x3_tune_drive;
 	hwif->speedproc = &ali15x3_tune_chipset;
 
-	/* Don't use LBA48 on ALi devices before rev 0xC5 */
-	hwif->no_lba48 = (m5229_revision <= 0xC4) ? 1 : 0;
+	/* don't use LBA48 DMA on ALi devices before rev 0xC5 */
+	hwif->no_lba48_dma = (m5229_revision <= 0xC4) ? 1 : 0;
 
 	if (!hwif->dma_base) {
 		hwif->drives[0].autotune = 1;
@@ -893,7 +893,7 @@
 MODULE_DEVICE_TABLE(pci, alim15x3_pci_tbl);
 
 static struct pci_driver driver = {
-	.name		= "ALI15x3 IDE",
+	.name		= "ALI15x3_IDE",
 	.id_table	= alim15x3_pci_tbl,
 	.probe		= alim15x3_init_one,
 };
diff -Nru a/drivers/ide/pci/amd74xx.c b/drivers/ide/pci/amd74xx.c
--- a/drivers/ide/pci/amd74xx.c	2004-10-18 14:57:05 -07:00
+++ b/drivers/ide/pci/amd74xx.c	2004-10-18 14:57:05 -07:00
@@ -416,6 +416,9 @@
 {
 	int i;
 
+	if (!hwif->irq)
+		hwif->irq = hwif->channel ? 15 : 14;
+
 	hwif->autodma = 0;
 
 	hwif->tuneproc = &amd74xx_tune_drive;
@@ -520,7 +523,7 @@
 MODULE_DEVICE_TABLE(pci, amd74xx_pci_tbl);
 
 static struct pci_driver driver = {
-	.name		= "AMD IDE",
+	.name		= "AMD_IDE",
 	.id_table	= amd74xx_pci_tbl,
 	.probe		= amd74xx_probe,
 };
diff -Nru a/drivers/ide/pci/atiixp.c b/drivers/ide/pci/atiixp.c
--- a/drivers/ide/pci/atiixp.c	2004-10-18 14:56:29 -07:00
+++ b/drivers/ide/pci/atiixp.c	2004-10-18 14:56:29 -07:00
@@ -490,7 +490,7 @@
 MODULE_DEVICE_TABLE(pci, atiixp_pci_tbl);
 
 static struct pci_driver driver = {
-	.name		= "ATIIXP IDE",
+	.name		= "ATIIXP_IDE",
 	.id_table	= atiixp_pci_tbl,
 	.probe		= atiixp_init_one,
 };
diff -Nru a/drivers/ide/pci/cmd640.c b/drivers/ide/pci/cmd640.c
--- a/drivers/ide/pci/cmd640.c	2004-10-18 14:57:03 -07:00
+++ b/drivers/ide/pci/cmd640.c	2004-10-18 14:57:03 -07:00
@@ -101,6 +101,8 @@
 #undef REALLY_SLOW_IO		/* most systems can safely undef this */
 #define CMD640_PREFETCH_MASKS 1
 
+//#define CMD640_DUMP_REGS
+
 #include <linux/config.h>
 #include <linux/types.h>
 #include <linux/kernel.h>
@@ -748,7 +750,7 @@
 	put_cmd640_reg(0x5b, 0);
 
 #ifdef CMD640_DUMP_REGS
-	CMD640_DUMP_REGS;
+	cmd640_dump_regs();
 #endif
 
 	/*
@@ -870,7 +872,7 @@
 	}
 
 #ifdef CMD640_DUMP_REGS
-	CMD640_DUMP_REGS;
+	cmd640_dump_regs();
 #endif
 	return 1;
 }
diff -Nru a/drivers/ide/pci/cmd64x.c b/drivers/ide/pci/cmd64x.c
--- a/drivers/ide/pci/cmd64x.c	2004-10-18 14:57:03 -07:00
+++ b/drivers/ide/pci/cmd64x.c	2004-10-18 14:57:03 -07:00
@@ -38,8 +38,6 @@
 static struct pci_dev *cmd_devs[CMD_MAX_DEVS];
 static int n_cmd_devs;
 
-#undef DEBUG_CMD_REGS
-
 static char * print_cmd64x_get_info (char *buf, struct pci_dev *dev, int index)
 {
 	char *p = buf;
@@ -49,9 +47,6 @@
 	u8 reg72 = 0, reg73 = 0;			/* primary */
 	u8 reg7a = 0, reg7b = 0;			/* secondary */
 	u8 reg50 = 0, reg71 = 0;			/* extra */
-#ifdef DEBUG_CMD_REGS
-	u8 hi_byte = 0, lo_byte = 0;
-#endif /* DEBUG_CMD_REGS */
 
 	p += sprintf(p, "\nController: %d\n", index);
 	p += sprintf(p, "CMD%x Chipset.\n", dev->device);
@@ -127,18 +122,6 @@
 		(reg71 & MRDMODE_BLK_CH0) ? "blocked" : "enabled",
 		(reg71 & MRDMODE_BLK_CH1) ? "blocked" : "enabled");
 
-#ifdef DEBUG_CMD_REGS
-	SPLIT_BYTE(reg50, hi_byte, lo_byte);
-	p += sprintf(p, "CFR       = 0x%02x, HI = 0x%02x, "
-			"LOW = 0x%02x\n", reg50, hi_byte, lo_byte);
-	SPLIT_BYTE(reg57, hi_byte, lo_byte);
-	p += sprintf(p, "ARTTIM23  = 0x%02x, HI = 0x%02x, "
-			"LOW = 0x%02x\n", reg57, hi_byte, lo_byte);
-	SPLIT_BYTE(reg71, hi_byte, lo_byte);
-	p += sprintf(p, "MRDMODE   = 0x%02x, HI = 0x%02x, "
-			"LOW = 0x%02x\n", reg71, hi_byte, lo_byte);
-#endif /* DEBUG_CMD_REGS */
-
 	return (char *)p;
 }
 
@@ -760,7 +743,7 @@
 MODULE_DEVICE_TABLE(pci, cmd64x_pci_tbl);
 
 static struct pci_driver driver = {
-	.name		= "CMD64x IDE",
+	.name		= "CMD64x_IDE",
 	.id_table	= cmd64x_pci_tbl,
 	.probe		= cmd64x_init_one,
 };
diff -Nru a/drivers/ide/pci/cmd64x.h b/drivers/ide/pci/cmd64x.h
--- a/drivers/ide/pci/cmd64x.h	2004-10-18 14:56:29 -07:00
+++ b/drivers/ide/pci/cmd64x.h	2004-10-18 14:56:29 -07:00
@@ -15,10 +15,6 @@
 #define cmdprintk(x...)
 #endif
 
-#ifndef SPLIT_BYTE
-#define SPLIT_BYTE(B,H,L)	((H)=(B>>4), (L)=(B-((B>>4)<<4)))
-#endif
-
 /*
  * CMD64x specific registers definition.
  */
diff -Nru a/drivers/ide/pci/cs5520.c b/drivers/ide/pci/cs5520.c
--- a/drivers/ide/pci/cs5520.c	2004-10-18 14:55:54 -07:00
+++ b/drivers/ide/pci/cs5520.c	2004-10-18 14:55:54 -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;
@@ -319,7 +322,7 @@
 MODULE_DEVICE_TABLE(pci, cs5520_pci_tbl);
 
 static struct pci_driver driver = {
-	.name		= "CyrixIDE",
+	.name		= "Cyrix_IDE",
 	.id_table	= cs5520_pci_tbl,
 	.probe		= cs5520_init_one,
 };
diff -Nru a/drivers/ide/pci/cy82c693.c b/drivers/ide/pci/cy82c693.c
--- a/drivers/ide/pci/cy82c693.c	2004-10-18 14:56:16 -07:00
+++ b/drivers/ide/pci/cy82c693.c	2004-10-18 14:56:16 -07:00
@@ -444,7 +444,7 @@
 MODULE_DEVICE_TABLE(pci, cy82c693_pci_tbl);
 
 static struct pci_driver driver = {
-	.name		= "Cypress IDE",
+	.name		= "Cypress_IDE",
 	.id_table	= cy82c693_pci_tbl,
 	.probe		= cy82c693_init_one,
 };
diff -Nru a/drivers/ide/pci/generic.c b/drivers/ide/pci/generic.c
--- a/drivers/ide/pci/generic.c	2004-10-18 14:56:32 -07:00
+++ b/drivers/ide/pci/generic.c	2004-10-18 14:56:32 -07:00
@@ -138,7 +138,7 @@
 MODULE_DEVICE_TABLE(pci, generic_pci_tbl);
 
 static struct pci_driver driver = {
-	.name		= "PCI IDE",
+	.name		= "PCI_IDE",
 	.id_table	= generic_pci_tbl,
 	.probe		= generic_init_one,
 };
diff -Nru a/drivers/ide/pci/hpt34x.c b/drivers/ide/pci/hpt34x.c
--- a/drivers/ide/pci/hpt34x.c	2004-10-18 14:56:28 -07:00
+++ b/drivers/ide/pci/hpt34x.c	2004-10-18 14:56:28 -07:00
@@ -44,65 +44,6 @@
 
 #include "hpt34x.h"
 
-#if defined(DISPLAY_HPT34X_TIMINGS) && defined(CONFIG_PROC_FS)
-#include <linux/stat.h>
-#include <linux/proc_fs.h>
-
-static u8 hpt34x_proc = 0;
-
-#define HPT34X_MAX_DEVS		8
-static struct pci_dev *hpt34x_devs[HPT34X_MAX_DEVS];
-static int n_hpt34x_devs;
-
-static int hpt34x_get_info (char *buffer, char **addr, off_t offset, int count)
-{
-	char *p = buffer;
-	int i, len;
-
-	p += sprintf(p, "\n                             "
-			"HPT34X Chipset.\n");
-	for (i = 0; i < n_hpt34x_devs; i++) {
-		struct pci_dev *dev = hpt34x_devs[i];
-		unsigned long bibma = pci_resource_start(dev, 4);
-		u8  c0 = 0, c1 = 0;
-
-		/*
-		 * at that point bibma+0x2 et bibma+0xa are byte registers
-		 * to investigate:
-		 */
-		c0 = inb_p((u16)bibma + 0x02);
-		c1 = inb_p((u16)bibma + 0x0a);
-		p += sprintf(p, "\nController: %d\n", i);
-		p += sprintf(p, "--------------- Primary Channel "
-				"---------------- Secondary Channel "
-				"-------------\n");
-		p += sprintf(p, "                %sabled "
-				"                        %sabled\n",
-				(c0&0x80) ? "dis" : " en",
-				(c1&0x80) ? "dis" : " en");
-		p += sprintf(p, "--------------- drive0 --------- drive1 "
-				"-------- drive0 ---------- drive1 ------\n");
-		p += sprintf(p, "DMA enabled:    %s              %s"
-				"             %s               %s\n",
-				(c0&0x20) ? "yes" : "no ",
-				(c0&0x40) ? "yes" : "no ",
-				(c1&0x20) ? "yes" : "no ",
-				(c1&0x40) ? "yes" : "no " );
-
-		p += sprintf(p, "UDMA\n");
-		p += sprintf(p, "DMA\n");
-		p += sprintf(p, "PIO\n");
-	}
-	p += sprintf(p, "\n");
-
-	/* p - buffer must be less than 4k! */
-	len = (p - buffer) - offset;
-	*addr = buffer + offset;
-	
-	return len > count ? count : len;
-}
-#endif  /* defined(DISPLAY_HPT34X_TIMINGS) && defined(CONFIG_PROC_FS) */
-
 static u8 hpt34x_ratemask (ide_drive_t *drive)
 {
 	return 1;
@@ -277,15 +218,6 @@
 
 	local_irq_restore(flags);
 
-#if defined(DISPLAY_HPT34X_TIMINGS) && defined(CONFIG_PROC_FS)
-	hpt34x_devs[n_hpt34x_devs++] = dev;
-
-	if (!hpt34x_proc) {
-		hpt34x_proc = 1;
-		ide_pci_create_host_proc("hpt34x", hpt34x_get_info);
-	}
-#endif /* DISPLAY_HPT34X_TIMINGS && CONFIG_PROC_FS */
-
 	return dev->irq;
 }
 
@@ -339,7 +271,7 @@
 MODULE_DEVICE_TABLE(pci, hpt34x_pci_tbl);
 
 static struct pci_driver driver = {
-	.name		= "HPT34x IDE",
+	.name		= "HPT34x_IDE",
 	.id_table	= hpt34x_pci_tbl,
 	.probe		= hpt34x_init_one,
 };
diff -Nru a/drivers/ide/pci/hpt34x.h b/drivers/ide/pci/hpt34x.h
--- a/drivers/ide/pci/hpt34x.h	2004-10-18 14:55:53 -07:00
+++ b/drivers/ide/pci/hpt34x.h	2004-10-18 14:55:53 -07:00
@@ -11,8 +11,6 @@
 #define SPLIT_BYTE(B,H,L)	((H)=(B>>4), (L)=(B-((B>>4)<<4)))
 #endif
 
-#undef DISPLAY_HPT34X_TIMINGS
-
 static unsigned int init_chipset_hpt34x(struct pci_dev *, const char *);
 static void init_hwif_hpt34x(ide_hwif_t *);
 
diff -Nru a/drivers/ide/pci/hpt366.c b/drivers/ide/pci/hpt366.c
--- a/drivers/ide/pci/hpt366.c	2004-10-18 14:56:33 -07:00
+++ b/drivers/ide/pci/hpt366.c	2004-10-18 14:56:33 -07:00
@@ -777,9 +777,6 @@
 	u8 reg59h = 0, reset	= (hwif->channel) ? 0x80 : 0x40;
 	u8 regXXh = 0, state_reg= (hwif->channel) ? 0x57 : 0x53;
 
-	if (!hwif)
-		return -EINVAL;
-
 //	hwif->bus_state = state;
 
 	pci_read_config_byte(dev, 0x59, &reg59h);
@@ -813,9 +810,6 @@
 	u8 tristate = 0, resetmask = 0, bus_reg = 0;
 	u16 tri_reg;
 
-	if (!hwif)
-		return -EINVAL;
-
 	hwif->bus_state = state;
 
 	if (hwif->channel) { 
@@ -958,7 +952,7 @@
 			/* Unsupported */
 		} else if (pll == F_LOW_PCI_50) {
 			if (hpt_minimum_revision(dev,8))
-				pci_set_drvdata(dev, NULL);
+				pci_set_drvdata(dev, (void *) fifty_base_hpt370a);
 			else if (hpt_minimum_revision(dev,5))
 				pci_set_drvdata(dev, (void *) fifty_base_hpt372);
 			else if (hpt_minimum_revision(dev,4))
@@ -991,11 +985,6 @@
 	if (pci_get_drvdata(dev)) 
 		goto init_hpt37X_done;
 	
-	if (hpt_minimum_revision(dev,8))
-	{
-		printk(KERN_ERR "HPT374: Only 33MHz PCI timings are supported.\n");
-		return -EOPNOTSUPP;
-	}
 	/*
 	 * adjust PLL based upon PCI clock, enable it, and wait for
 	 * stabilization.
@@ -1403,7 +1392,7 @@
 MODULE_DEVICE_TABLE(pci, hpt366_pci_tbl);
 
 static struct pci_driver driver = {
-	.name		= "HPT366 IDE",
+	.name		= "HPT366_IDE",
 	.id_table	= hpt366_pci_tbl,
 	.probe		= hpt366_init_one,
 };
diff -Nru a/drivers/ide/pci/it8172.c b/drivers/ide/pci/it8172.c
--- a/drivers/ide/pci/it8172.c	2004-10-18 14:56:49 -07:00
+++ b/drivers/ide/pci/it8172.c	2004-10-18 14:56:49 -07:00
@@ -302,7 +302,7 @@
 MODULE_DEVICE_TABLE(pci, it8172_pci_tbl);
 
 static struct pci_driver driver = {
-	.name		= "IT8172IDE",
+	.name		= "IT8172_IDE",
 	.id_table	= it8172_pci_tbl,
 	.probe		= it8172_init_one,
 };
diff -Nru a/drivers/ide/pci/ns87415.c b/drivers/ide/pci/ns87415.c
--- a/drivers/ide/pci/ns87415.c	2004-10-18 14:56:29 -07:00
+++ b/drivers/ide/pci/ns87415.c	2004-10-18 14:56:29 -07:00
@@ -236,7 +236,7 @@
 MODULE_DEVICE_TABLE(pci, ns87415_pci_tbl);
 
 static struct pci_driver driver = {
-	.name		= "NS87415IDE",
+	.name		= "NS87415_IDE",
 	.id_table	= ns87415_pci_tbl,
 	.probe		= ns87415_init_one,
 };
diff -Nru a/drivers/ide/pci/opti621.c b/drivers/ide/pci/opti621.c
--- a/drivers/ide/pci/opti621.c	2004-10-18 14:56:28 -07:00
+++ b/drivers/ide/pci/opti621.c	2004-10-18 14:56:28 -07:00
@@ -367,7 +367,7 @@
 MODULE_DEVICE_TABLE(pci, opti621_pci_tbl);
 
 static struct pci_driver driver = {
-	.name		= "Opti621 IDE",
+	.name		= "Opti621_IDE",
 	.id_table	= opti621_pci_tbl,
 	.probe		= opti621_init_one,
 };
diff -Nru a/drivers/ide/pci/pdc202xx_new.c b/drivers/ide/pci/pdc202xx_new.c
--- a/drivers/ide/pci/pdc202xx_new.c	2004-10-18 14:56:49 -07:00
+++ b/drivers/ide/pci/pdc202xx_new.c	2004-10-18 14:56:49 -07:00
@@ -531,7 +531,7 @@
 MODULE_DEVICE_TABLE(pci, pdc202new_pci_tbl);
 
 static struct pci_driver driver = {
-	.name		= "Promise IDE",
+	.name		= "Promise_IDE",
 	.id_table	= pdc202new_pci_tbl,
 	.probe		= pdc202new_init_one,
 };
diff -Nru a/drivers/ide/pci/pdc202xx_old.c b/drivers/ide/pci/pdc202xx_old.c
--- a/drivers/ide/pci/pdc202xx_old.c	2004-10-18 14:57:04 -07:00
+++ b/drivers/ide/pci/pdc202xx_old.c	2004-10-18 14:57:04 -07:00
@@ -314,17 +314,6 @@
 		pci_write_config_byte(dev, (drive_pci)|0x02, CP|TC);
 	}
 
-#if PDC202XX_DECODE_REGISTER_INFO
-	pci_read_config_byte(dev, (drive_pci), &AP);
-	pci_read_config_byte(dev, (drive_pci)|0x01, &BP);
-	pci_read_config_byte(dev, (drive_pci)|0x02, &CP);
-	pci_read_config_byte(dev, (drive_pci)|0x03, &DP);
-
-	decode_registers(REG_A, AP);
-	decode_registers(REG_B, BP);
-	decode_registers(REG_C, CP);
-	decode_registers(REG_D, DP);
-#endif /* PDC202XX_DECODE_REGISTER_INFO */
 #if PDC202XX_DEBUG_DRIVE_INFO
 	printk(KERN_DEBUG "%s: %s drive%d 0x%08x ",
 		drive->name, ide_xfer_verbose(speed),
@@ -905,7 +894,7 @@
 MODULE_DEVICE_TABLE(pci, pdc202xx_pci_tbl);
 
 static struct pci_driver driver = {
-	.name		= "Promise Old IDE",
+	.name		= "Promise_Old_IDE",
 	.id_table	= pdc202xx_pci_tbl,
 	.probe		= pdc202xx_init_one,
 };
diff -Nru a/drivers/ide/pci/pdc202xx_old.h b/drivers/ide/pci/pdc202xx_old.h
--- a/drivers/ide/pci/pdc202xx_old.h	2004-10-18 14:55:53 -07:00
+++ b/drivers/ide/pci/pdc202xx_old.h	2004-10-18 14:55:53 -07:00
@@ -10,7 +10,6 @@
 #endif
 
 #define PDC202XX_DEBUG_DRIVE_INFO		0
-#define PDC202XX_DECODE_REGISTER_INFO		0
 
 static const char *pdc_quirk_drives[] = {
 	"QUANTUM FIREBALLlct08 08",
@@ -98,76 +97,6 @@
 #define	MC2		0x04	/* DMA"C" timing */
 #define	MC1		0x02	/* DMA"C" timing */
 #define	MC0		0x01	/* DMA"C" timing */
-
-#if PDC202XX_DECODE_REGISTER_INFO
-
-#define REG_A		0x01
-#define REG_B		0x02
-#define REG_C		0x04
-#define REG_D		0x08
-
-static void decode_registers (u8 registers, u8 value)
-{
-	u8	bit = 0, bit1 = 0, bit2 = 0;
-
-	switch(registers) {
-		case REG_A:
-			bit2 = 0;
-			printk("A Register ");
-			if (value & 0x80) printk("SYNC_IN ");
-			if (value & 0x40) printk("ERRDY_EN ");
-			if (value & 0x20) printk("IORDY_EN ");
-			if (value & 0x10) printk("PREFETCH_EN ");
-			if (value & 0x08) { printk("PA3 ");bit2 |= 0x08; }
-			if (value & 0x04) { printk("PA2 ");bit2 |= 0x04; }
-			if (value & 0x02) { printk("PA1 ");bit2 |= 0x02; }
-			if (value & 0x01) { printk("PA0 ");bit2 |= 0x01; }
-			printk("PIO(A) = %d ", bit2);
-			break;
-		case REG_B:
-			bit1 = 0;bit2 = 0;
-			printk("B Register ");
-			if (value & 0x80) { printk("MB2 ");bit1 |= 0x80; }
-			if (value & 0x40) { printk("MB1 ");bit1 |= 0x40; }
-			if (value & 0x20) { printk("MB0 ");bit1 |= 0x20; }
-			printk("DMA(B) = %d ", bit1 >> 5);
-			if (value & 0x10) printk("PIO_FORCED/PB4 ");
-			if (value & 0x08) { printk("PB3 ");bit2 |= 0x08; }
-			if (value & 0x04) { printk("PB2 ");bit2 |= 0x04; }
-			if (value & 0x02) { printk("PB1 ");bit2 |= 0x02; }
-			if (value & 0x01) { printk("PB0 ");bit2 |= 0x01; }
-			printk("PIO(B) = %d ", bit2);
-			break;
-		case REG_C:
-			bit2 = 0;
-			printk("C Register ");
-			if (value & 0x80) printk("DMARQp ");
-			if (value & 0x40) printk("IORDYp ");
-			if (value & 0x20) printk("DMAR_EN ");
-			if (value & 0x10) printk("DMAW_EN ");
-
-			if (value & 0x08) { printk("MC3 ");bit2 |= 0x08; }
-			if (value & 0x04) { printk("MC2 ");bit2 |= 0x04; }
-			if (value & 0x02) { printk("MC1 ");bit2 |= 0x02; }
-			if (value & 0x01) { printk("MC0 ");bit2 |= 0x01; }
-			printk("DMA(C) = %d ", bit2);
-			break;
-		case REG_D:
-			printk("D Register ");
-			break;
-		default:
-			return;
-	}
-	printk("\n        %s ", (registers & REG_D) ? "DP" :
-				(registers & REG_C) ? "CP" :
-				(registers & REG_B) ? "BP" :
-				(registers & REG_A) ? "AP" : "ERROR");
-	for (bit=128;bit>0;bit/=2)
-		printk("%s", (value & bit) ? "1" : "0");
-	printk("\n");
-}
-
-#endif /* PDC202XX_DECODE_REGISTER_INFO */
 
 #define DISPLAY_PDC202XX_TIMINGS
 
diff -Nru a/drivers/ide/pci/piix.c b/drivers/ide/pci/piix.c
--- a/drivers/ide/pci/piix.c	2004-10-18 14:55:54 -07:00
+++ b/drivers/ide/pci/piix.c	2004-10-18 14:55:54 -07:00
@@ -561,36 +561,31 @@
 	drive->init_speed = 0;
 
 	if ((id->capability & 1) && drive->autodma) {
+
 		/* Consult the list of known "bad" drives */
 		if (__ide_dma_bad_drive(drive))
 			goto fast_ata_pio;
-		if (id->field_valid & 4) {
-			if (id->dma_ultra & hwif->ultra_mask) {
-				/* Force if Capable UltraDMA */
-				if ((id->field_valid & 2) &&
-				    (!piix_config_drive_for_dma(drive)))
-					goto try_dma_modes;
-			}
-		} else if (id->field_valid & 2) {
-try_dma_modes:
-			if ((id->dma_mword & hwif->mwdma_mask) ||
-			    (id->dma_1word & hwif->swdma_mask)) {
-				/* Force if Capable regular DMA modes */
-				if (!piix_config_drive_for_dma(drive))
-					goto no_dma_set;
-			}
-		} else if (__ide_dma_good_drive(drive) &&
-			   (id->eide_dma_time < 150)) {
-			/* Consult the list of known "good" drives */
-			if (!piix_config_drive_for_dma(drive))
-				goto no_dma_set;
-		} else {
-			goto fast_ata_pio;
+
+		/**
+		 * Try to turn DMA on if:
+		 *  - UDMA or EIDE modes are supported or
+		 *  - drive is a known "good" drive
+		 *
+		 * Checks for best mode supported are down later by
+		 * piix_config_drive_for_dma() -> ide_dma_speed()
+		 */
+		if ((id->field_valid & (4 | 2)) ||
+		    (__ide_dma_good_drive(drive) && id->eide_dma_time < 150)) {
+			if (piix_config_drive_for_dma(drive))
+				return hwif->ide_dma_on(drive);
 		}
-		return hwif->ide_dma_on(drive);
+
+		/* For some reason DMA wasn't turned on, so try PIO. */
+		goto fast_ata_pio;
+
 	} else if ((id->capability & 8) || (id->field_valid & 2)) {
 fast_ata_pio:
-no_dma_set:
+		/* Find best PIO mode. */
 		hwif->tuneproc(drive, 255);
 		return hwif->ide_dma_off_quietly(drive);
 	}
@@ -803,7 +798,7 @@
 MODULE_DEVICE_TABLE(pci, piix_pci_tbl);
 
 static struct pci_driver driver = {
-	.name		= "PIIX IDE",
+	.name		= "PIIX_IDE",
 	.id_table	= piix_pci_tbl,
 	.probe		= piix_init_one,
 };
diff -Nru a/drivers/ide/pci/rz1000.c b/drivers/ide/pci/rz1000.c
--- a/drivers/ide/pci/rz1000.c	2004-10-18 14:56:28 -07:00
+++ b/drivers/ide/pci/rz1000.c	2004-10-18 14:56:28 -07:00
@@ -74,7 +74,7 @@
 MODULE_DEVICE_TABLE(pci, rz1000_pci_tbl);
 
 static struct pci_driver driver = {
-	.name		= "RZ1000 IDE",
+	.name		= "RZ1000_IDE",
 	.id_table	= rz1000_pci_tbl,
 	.probe		= rz1000_init_one,
 };
diff -Nru a/drivers/ide/pci/sc1200.c b/drivers/ide/pci/sc1200.c
--- a/drivers/ide/pci/sc1200.c	2004-10-18 14:56:33 -07:00
+++ b/drivers/ide/pci/sc1200.c	2004-10-18 14:56:33 -07:00
@@ -565,7 +565,7 @@
 MODULE_DEVICE_TABLE(pci, sc1200_pci_tbl);
 
 static struct pci_driver driver = {
-	.name		= "SC1200 IDE",
+	.name		= "SC1200_IDE",
 	.id_table	= sc1200_pci_tbl,
 	.probe		= sc1200_init_one,
 	.suspend	= sc1200_suspend,
diff -Nru a/drivers/ide/pci/serverworks.c b/drivers/ide/pci/serverworks.c
--- a/drivers/ide/pci/serverworks.c	2004-10-18 14:55:54 -07:00
+++ b/drivers/ide/pci/serverworks.c	2004-10-18 14:55:54 -07:00
@@ -812,7 +812,7 @@
 MODULE_DEVICE_TABLE(pci, svwks_pci_tbl);
 
 static struct pci_driver driver = {
-	.name		= "Serverworks IDE",
+	.name		= "Serverworks_IDE",
 	.id_table	= svwks_pci_tbl,
 	.probe		= svwks_init_one,
 #if 0	/* FIXME: implement */
diff -Nru a/drivers/ide/pci/sgiioc4.c b/drivers/ide/pci/sgiioc4.c
--- a/drivers/ide/pci/sgiioc4.c	2004-10-18 14:56:32 -07:00
+++ b/drivers/ide/pci/sgiioc4.c	2004-10-18 14:56:32 -07:00
@@ -570,7 +570,6 @@
 use_pio_instead:
 	pci_unmap_sg(hwif->pci_dev, hwif->sg_table, hwif->sg_nents,
 		     hwif->sg_dma_direction);
-	hwif->sg_dma_active = 0;
 
 	return 0;		/* revert to PIO for this request */
 }
@@ -702,6 +701,10 @@
 		       hwif->name, d->name);
 
 	probe_hwif_init(hwif);
+
+	/* Create /proc/ide entries */
+	create_proc_ide_interfaces(); 
+
 	return 0;
 }
 
@@ -782,7 +785,7 @@
 MODULE_DEVICE_TABLE(pci, sgiioc4_pci_tbl);
 
 static struct pci_driver driver = {
-	.name = "SGI-IOC4 IDE",
+	.name = "SGI-IOC4_IDE",
 	.id_table = sgiioc4_pci_tbl,
 	.probe = sgiioc4_init_one,
 };
diff -Nru a/drivers/ide/pci/siimage.c b/drivers/ide/pci/siimage.c
--- a/drivers/ide/pci/siimage.c	2004-10-18 14:56:28 -07:00
+++ b/drivers/ide/pci/siimage.c	2004-10-18 14:56:28 -07:00
@@ -727,8 +727,7 @@
 	unsigned long bar5	= pci_resource_start(dev, 5);
 	unsigned long barsize	= pci_resource_len(dev, 5);
 	u8 tmpbyte	= 0;
-	unsigned long addr;
-	void *ioaddr;
+	void __iomem *ioaddr;
 
 	/*
 	 *	Drop back to PIO if we can't map the mmio. Some
@@ -751,22 +750,21 @@
 	}
 
 	pci_set_master(dev);
-	pci_set_drvdata(dev, ioaddr);
-	addr = (unsigned long) ioaddr;
+	pci_set_drvdata(dev, (void *) ioaddr);
 
 	if (pdev_is_sata(dev)) {
-		writel(0, addr + 0x148);
-		writel(0, addr + 0x1C8);
+		writel(0, ioaddr + 0x148);
+		writel(0, ioaddr + 0x1C8);
 	}
 
-	writeb(0, addr + 0xB4);
-	writeb(0, addr + 0xF4);
-	tmpbyte = readb(addr + 0x4A);
+	writeb(0, ioaddr + 0xB4);
+	writeb(0, ioaddr + 0xF4);
+	tmpbyte = readb(ioaddr + 0x4A);
 
 	switch(tmpbyte & 0x30) {
 		case 0x00:
 			/* In 100 MHz clocking, try and switch to 133 */
-			writeb(tmpbyte|0x10, addr + 0x4A);
+			writeb(tmpbyte|0x10, ioaddr + 0x4A);
 			break;
 		case 0x10:
 			/* On 133Mhz clocking */
@@ -777,29 +775,29 @@
 		case 0x30:
 			/* Clocking is disabled */
 			/* 133 clock attempt to force it on */
-			writeb(tmpbyte & ~0x20, addr + 0x4A);
+			writeb(tmpbyte & ~0x20, ioaddr + 0x4A);
 			break;
 	}
 	
-	writeb(      0x72, addr + 0xA1);
-	writew(    0x328A, addr + 0xA2);
-	writel(0x62DD62DD, addr + 0xA4);
-	writel(0x43924392, addr + 0xA8);
-	writel(0x40094009, addr + 0xAC);
-	writeb(      0x72, addr + 0xE1);
-	writew(    0x328A, addr + 0xE2);
-	writel(0x62DD62DD, addr + 0xE4);
-	writel(0x43924392, addr + 0xE8);
-	writel(0x40094009, addr + 0xEC);
+	writeb(      0x72, ioaddr + 0xA1);
+	writew(    0x328A, ioaddr + 0xA2);
+	writel(0x62DD62DD, ioaddr + 0xA4);
+	writel(0x43924392, ioaddr + 0xA8);
+	writel(0x40094009, ioaddr + 0xAC);
+	writeb(      0x72, ioaddr + 0xE1);
+	writew(    0x328A, ioaddr + 0xE2);
+	writel(0x62DD62DD, ioaddr + 0xE4);
+	writel(0x43924392, ioaddr + 0xE8);
+	writel(0x40094009, ioaddr + 0xEC);
 
 	if (pdev_is_sata(dev)) {
-		writel(0xFFFF0000, addr + 0x108);
-		writel(0xFFFF0000, addr + 0x188);
-		writel(0x00680000, addr + 0x148);
-		writel(0x00680000, addr + 0x1C8);
+		writel(0xFFFF0000, ioaddr + 0x108);
+		writel(0xFFFF0000, ioaddr + 0x188);
+		writel(0x00680000, ioaddr + 0x148);
+		writel(0x00680000, ioaddr + 0x1C8);
 	}
 
-	tmpbyte = readb(addr + 0x4A);
+	tmpbyte = readb(ioaddr + 0x4A);
 
 	proc_reports_siimage(dev, (tmpbyte>>4), name);
 	return 1;
@@ -1137,7 +1135,7 @@
 MODULE_DEVICE_TABLE(pci, siimage_pci_tbl);
 
 static struct pci_driver driver = {
-	.name		= "SiI IDE",
+	.name		= "SiI_IDE",
 	.id_table	= siimage_pci_tbl,
 	.probe		= siimage_init_one,
 };
diff -Nru a/drivers/ide/pci/sis5513.c b/drivers/ide/pci/sis5513.c
--- a/drivers/ide/pci/sis5513.c	2004-10-18 14:56:31 -07:00
+++ b/drivers/ide/pci/sis5513.c	2004-10-18 14:56:31 -07:00
@@ -788,6 +788,15 @@
 			if (trueid == 0x5518) {
 				printk(KERN_INFO "SIS5513: SiS 962/963 MuTIOL IDE UDMA133 controller\n");
 				chipset_family = ATA_133;
+
+				/* Check for 5513 compability mapping
+				 * We must use this, else the port enabled code will fail,
+				 * as it expects the enablebits at 0x4a.
+				 */
+				if ((idemisc & 0x40000000) == 0) {
+					pci_write_config_dword(dev, 0x54, idemisc | 0x40000000);
+					printk(KERN_INFO "SIS5513: Switching to 5513 register mapping\n");
+				}
 			}
 	}
 
@@ -963,12 +972,13 @@
 
 static struct pci_device_id sis5513_pci_tbl[] = {
 	{ PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_5513, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+	{ PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_5518, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
 	{ 0, },
 };
 MODULE_DEVICE_TABLE(pci, sis5513_pci_tbl);
 
 static struct pci_driver driver = {
-	.name		= "SIS IDE",
+	.name		= "SIS_IDE",
 	.id_table	= sis5513_pci_tbl,
 	.probe		= sis5513_init_one,
 };
diff -Nru a/drivers/ide/pci/sl82c105.c b/drivers/ide/pci/sl82c105.c
--- a/drivers/ide/pci/sl82c105.c	2004-10-18 14:56:28 -07:00
+++ b/drivers/ide/pci/sl82c105.c	2004-10-18 14:56:28 -07:00
@@ -503,7 +503,7 @@
 MODULE_DEVICE_TABLE(pci, sl82c105_pci_tbl);
 
 static struct pci_driver driver = {
-	.name		= "W82C105 IDE",
+	.name		= "W82C105_IDE",
 	.id_table	= sl82c105_pci_tbl,
 	.probe		= sl82c105_init_one,
 };
diff -Nru a/drivers/ide/pci/slc90e66.c b/drivers/ide/pci/slc90e66.c
--- a/drivers/ide/pci/slc90e66.c	2004-10-18 14:56:49 -07:00
+++ b/drivers/ide/pci/slc90e66.c	2004-10-18 14:56:49 -07:00
@@ -387,7 +387,7 @@
 MODULE_DEVICE_TABLE(pci, slc90e66_pci_tbl);
 
 static struct pci_driver driver = {
-	.name		= "SLC90e66 IDE",
+	.name		= "SLC90e66_IDE",
 	.id_table	= slc90e66_pci_tbl,
 	.probe		= slc90e66_init_one,
 };
diff -Nru a/drivers/ide/pci/triflex.c b/drivers/ide/pci/triflex.c
--- a/drivers/ide/pci/triflex.c	2004-10-18 14:56:28 -07:00
+++ b/drivers/ide/pci/triflex.c	2004-10-18 14:56:28 -07:00
@@ -41,57 +41,6 @@
 #include <linux/ide.h>
 #include <linux/init.h>
 
-static struct pci_dev *triflex_dev;
-
-#ifdef CONFIG_PROC_FS
-static int triflex_get_info(char *buf, char **addr, off_t offset, int count)
-{
-	char *p = buf;
-	int len;
-
-	struct pci_dev *dev	= triflex_dev;
-	unsigned long bibma = pci_resource_start(dev, 4);
-	u8  c0 = 0, c1 = 0;
-	u32 pri_timing, sec_timing;
-
-	p += sprintf(p, "\n                                Compaq Triflex Chipset\n");
-	
-	pci_read_config_dword(dev, 0x70, &pri_timing);
-	pci_read_config_dword(dev, 0x74, &sec_timing);
-
-	/*
-	 * at that point bibma+0x2 et bibma+0xa are byte registers
-	 * to investigate:
-	 */
-	c0 = inb((unsigned short)bibma + 0x02);
-	c1 = inb((unsigned short)bibma + 0x0a);
-
-	p += sprintf(p, "--------------- Primary Channel "
-			"---------------- Secondary Channel "
-			"-------------\n");
-	p += sprintf(p, "                %sabled "
-			"                        %sabled\n",
-			(c0&0x80) ? "dis" : " en",
-			(c1&0x80) ? "dis" : " en");
-	p += sprintf(p, "--------------- drive0 --------- drive1 "
-			"-------- drive0 ---------- drive1 ------\n");
-	p += sprintf(p, "DMA enabled:    %s              %s "
-			"            %s               %s\n",
-			(c0&0x20) ? "yes" : "no ",
-			(c0&0x40) ? "yes" : "no ",
-			(c1&0x20) ? "yes" : "no ",
-			(c1&0x40) ? "yes" : "no " );
-
-	p += sprintf(p, "DMA\n");
-	p += sprintf(p, "PIO\n");
-
-	len = (p - buf) - offset;
-	*addr = buf + offset;
-	
-	return len > count ? count : len;
-}
-#endif
-
 static int triflex_tune_chipset(ide_drive_t *drive, u8 xferspeed)
 {
 	ide_hwif_t *hwif = HWIF(drive);
@@ -206,18 +155,8 @@
 	hwif->drives[1].autodma = hwif->autodma;
 }
 
-static unsigned int __init init_chipset_triflex(struct pci_dev *dev, 
-		const char *name) 
-{
-#ifdef CONFIG_PROC_FS
-	ide_pci_create_host_proc("triflex", triflex_get_info);
-#endif
-	return 0;	
-}
-
 static ide_pci_device_t triflex_device __devinitdata = {
 	.name		= "TRIFLEX",
-	.init_chipset	= init_chipset_triflex,
 	.init_hwif	= init_hwif_triflex,
 	.channels	= 2,
 	.autodma	= AUTODMA,
@@ -229,7 +168,6 @@
 		const struct pci_device_id *id)
 {
 	ide_setup_pci_device(dev, &triflex_device);
-	triflex_dev = dev;
 
 	return 0;
 }
@@ -242,7 +180,7 @@
 MODULE_DEVICE_TABLE(pci, triflex_pci_tbl);
 
 static struct pci_driver driver = {
-	.name		= "TRIFLEX IDE",
+	.name		= "TRIFLEX_IDE",
 	.id_table	= triflex_pci_tbl,
 	.probe		= triflex_init_one,
 };
diff -Nru a/drivers/ide/pci/trm290.c b/drivers/ide/pci/trm290.c
--- a/drivers/ide/pci/trm290.c	2004-10-18 14:56:19 -07:00
+++ b/drivers/ide/pci/trm290.c	2004-10-18 14:56:19 -07:00
@@ -408,7 +408,7 @@
 MODULE_DEVICE_TABLE(pci, trm290_pci_tbl);
 
 static struct pci_driver driver = {
-	.name		= "TRM290 IDE",
+	.name		= "TRM290_IDE",
 	.id_table	= trm290_pci_tbl,
 	.probe		= trm290_init_one,
 };
diff -Nru a/drivers/ide/pci/via82cxxx.c b/drivers/ide/pci/via82cxxx.c
--- a/drivers/ide/pci/via82cxxx.c	2004-10-18 14:55:53 -07:00
+++ b/drivers/ide/pci/via82cxxx.c	2004-10-18 14:55:53 -07:00
@@ -632,7 +632,7 @@
 MODULE_DEVICE_TABLE(pci, via_pci_tbl);
 
 static struct pci_driver driver = {
-	.name 		= "VIA IDE",
+	.name 		= "VIA_IDE",
 	.id_table 	= via_pci_tbl,
 	.probe 		= via_init_one,
 };
diff -Nru a/drivers/ide/ppc/pmac.c b/drivers/ide/ppc/pmac.c
--- a/drivers/ide/ppc/pmac.c	2004-10-18 14:55:54 -07:00
+++ b/drivers/ide/ppc/pmac.c	2004-10-18 14:55:54 -07:00
@@ -62,10 +62,10 @@
 	int				irq;
 	int				kind;
 	int				aapl_bus_id;
-	int				cable_80 : 1;
-	int				mediabay : 1;
-	int				broken_dma : 1;
-	int				broken_dma_warn : 1;
+	unsigned			cable_80 : 1;
+	unsigned			mediabay : 1;
+	unsigned			broken_dma : 1;
+	unsigned			broken_dma_warn : 1;
 	struct device_node*		node;
 	struct macio_dev		*mdev;
 	u32				timings[4];
@@ -75,7 +75,7 @@
 	 * beeing done by the generic code about the kind of dma controller
 	 * and format of the dma table. This will have to be fixed though.
 	 */
-	volatile struct dbdma_regs*	dma_regs;
+	volatile struct dbdma_regs __iomem *	dma_regs;
 	struct dbdma_cmd*		dma_table_cpu;
 	dma_addr_t			dma_table_dma;
 	struct scatterlist*		sg_table;
@@ -497,6 +497,8 @@
 		*irq = pmac_ide[ix].irq;
 }
 
+#define PMAC_IDE_REG(x) ((void __iomem *)(IDE_DATA_REG+(x)))
+
 /*
  * Apply the timings of the proper unit (master/slave) to the shared
  * timing register when selecting that unit. This version is for
@@ -511,12 +513,10 @@
 		return;
 
 	if (drive->select.b.unit & 0x01)
-		writel(pmif->timings[1],
-			(unsigned *)(IDE_DATA_REG+IDE_TIMING_CONFIG));
+		writel(pmif->timings[1], PMAC_IDE_REG(IDE_TIMING_CONFIG));
 	else
-		writel(pmif->timings[0],
-			(unsigned *)(IDE_DATA_REG+IDE_TIMING_CONFIG));
-	(void)readl((unsigned *)(IDE_DATA_REG+IDE_TIMING_CONFIG));
+		writel(pmif->timings[0], PMAC_IDE_REG(IDE_TIMING_CONFIG));
+	(void)readl(PMAC_IDE_REG(IDE_TIMING_CONFIG));
 }
 
 /*
@@ -533,17 +533,13 @@
 		return;
 
 	if (drive->select.b.unit & 0x01) {
-		writel(pmif->timings[1],
-		       (unsigned *)(IDE_DATA_REG + IDE_KAUAI_PIO_CONFIG));
-		writel(pmif->timings[3],
-		       (unsigned *)(IDE_DATA_REG + IDE_KAUAI_ULTRA_CONFIG));
+		writel(pmif->timings[1], PMAC_IDE_REG(IDE_KAUAI_PIO_CONFIG));
+		writel(pmif->timings[3], PMAC_IDE_REG(IDE_KAUAI_ULTRA_CONFIG));
 	} else {
-		writel(pmif->timings[0],
-		       (unsigned *)(IDE_DATA_REG + IDE_KAUAI_PIO_CONFIG));
-		writel(pmif->timings[2],
-		       (unsigned *)(IDE_DATA_REG + IDE_KAUAI_ULTRA_CONFIG));
+		writel(pmif->timings[0], PMAC_IDE_REG(IDE_KAUAI_PIO_CONFIG));
+		writel(pmif->timings[2], PMAC_IDE_REG(IDE_KAUAI_ULTRA_CONFIG));
 	}
-	(void)readl((unsigned *)(IDE_DATA_REG + IDE_KAUAI_PIO_CONFIG));
+	(void)readl(PMAC_IDE_REG(IDE_KAUAI_PIO_CONFIG));
 }
 
 /*
@@ -568,8 +564,8 @@
 {
 	u32 tmp;
 	
-	writeb(value, port);	
-	tmp = readl((unsigned *)(IDE_DATA_REG + IDE_TIMING_CONFIG));
+	writeb(value, (void __iomem *) port);
+	tmp = readl(PMAC_IDE_REG(IDE_TIMING_CONFIG));
 }
 
 /*
@@ -792,7 +788,7 @@
 set_timings_mdma(ide_drive_t *drive, int intf_type, u32 *timings, u32 *timings2,
 			u8 speed, int drive_cycle_time)
 {
-	int cycleTime, accessTime, recTime;
+	int cycleTime, accessTime = 0, recTime = 0;
 	unsigned accessTicks, recTicks;
 	struct mdma_timings_t* tm = NULL;
 	int i;
@@ -1281,7 +1277,8 @@
 static int __devinit
 pmac_ide_macio_attach(struct macio_dev *mdev, const struct of_match *match)
 {
-	unsigned long base, regbase;
+	void __iomem *base;
+	unsigned long regbase;
 	int irq;
 	ide_hwif_t *hwif;
 	pmac_ide_hwif_t *pmif;
@@ -1324,8 +1321,8 @@
 	} else
 		irq = macio_irq(mdev, 0);
 
-	base =  (unsigned long)ioremap(macio_resource_start(mdev, 0), 0x400);
-	regbase = base;
+	base = ioremap(macio_resource_start(mdev, 0), 0x400);
+	regbase = (unsigned long) base;
 
 	hwif->pci_dev = mdev->bus->pdev;
 	hwif->gendev.parent = &mdev->ofdev.dev;
@@ -1339,8 +1336,7 @@
 		if (macio_request_resource(mdev, 1, "ide-pmac (dma)"))
 			printk(KERN_WARNING "ide%d: can't request DMA resource !\n", i);
 		else
-			pmif->dma_regs = (volatile struct dbdma_regs*)
-				ioremap(macio_resource_start(mdev, 1), 0x1000);
+			pmif->dma_regs = ioremap(macio_resource_start(mdev, 1), 0x1000);
 	} else
 		pmif->dma_regs = NULL;
 #endif /* CONFIG_BLK_DEV_IDEDMA_PMAC */
@@ -1350,9 +1346,9 @@
 	if (rc != 0) {
 		/* The inteface is released to the common IDE layer */
 		dev_set_drvdata(&mdev->ofdev.dev, NULL);
-		iounmap((void *)base);
+		iounmap(base);
 		if (pmif->dma_regs)
-			iounmap((void *)pmif->dma_regs);
+			iounmap(pmif->dma_regs);
 		memset(pmif, 0, sizeof(*pmif));
 		macio_release_resource(mdev, 0);
 		if (pmif->dma_regs)
@@ -1401,7 +1397,7 @@
 	ide_hwif_t *hwif;
 	struct device_node *np;
 	pmac_ide_hwif_t *pmif;
-	unsigned long base;
+	void __iomem *base;
 	unsigned long rbase, rlen;
 	int i, rc;
 
@@ -1444,10 +1440,10 @@
 	rbase = pci_resource_start(pdev, 0);
 	rlen = pci_resource_len(pdev, 0);
 
-	base = (unsigned long) ioremap(rbase, rlen);
-	pmif->regbase = base + 0x2000;
+	base = ioremap(rbase, rlen);
+	pmif->regbase = (unsigned long) base + 0x2000;
 #ifdef CONFIG_BLK_DEV_IDEDMA_PMAC
-	pmif->dma_regs = (volatile struct dbdma_regs*)(base + 0x1000);
+	pmif->dma_regs = base + 0x1000;
 #endif /* CONFIG_BLK_DEV_IDEDMA_PMAC */	
 
 	/* We use the OF node irq mapping */
@@ -1462,7 +1458,7 @@
 	if (rc != 0) {
 		/* The inteface is released to the common IDE layer */
 		pci_set_drvdata(pdev, NULL);
-		iounmap((void *)base);
+		iounmap(base);
 		memset(pmif, 0, sizeof(*pmif));
 		pci_release_regions(pdev);
 	}
@@ -1578,9 +1574,6 @@
 	struct scatterlist *sg = pmif->sg_table;
 	int nents;
 
-	if (hwif->sg_dma_active)
-		BUG();
-		
 	nents = blk_rq_map_sg(drive->queue, rq, sg);
 		
 	if (rq_data_dir(rq) == READ)
@@ -1639,7 +1632,7 @@
 	int i, count = 0;
 	ide_hwif_t *hwif = HWIF(drive);
 	pmac_ide_hwif_t* pmif = (pmac_ide_hwif_t *)hwif->hwif_data;
-	volatile struct dbdma_regs *dma = pmif->dma_regs;
+	volatile struct dbdma_regs __iomem *dma = pmif->dma_regs;
 	struct scatterlist *sg;
 	int wr = (rq_data_dir(rq) == WRITE);
 
@@ -1715,7 +1708,6 @@
 		     pmif->sg_table,
 		     pmif->sg_nents,
 		     pmif->sg_dma_direction);
-	hwif->sg_dma_active = 0;
 	return 0; /* revert to PIO for this request */
 }
 
@@ -1731,7 +1723,6 @@
 	if (nents) {
 		pci_unmap_sg(dev, sg, nents, pmif->sg_dma_direction);
 		pmif->sg_nents = 0;
-		HWIF(drive)->sg_dma_active = 0;
 	}
 }
 
@@ -1912,8 +1903,8 @@
 	/* Apple adds 60ns to wrDataSetup on reads */
 	if (ata4 && (pmif->timings[unit] & TR_66_UDMA_EN)) {
 		writel(pmif->timings[unit] + (reading ? 0x00800000UL : 0),
-			(unsigned *)(IDE_DATA_REG+IDE_TIMING_CONFIG));
-		(void)readl((unsigned *)(IDE_DATA_REG + IDE_TIMING_CONFIG));
+			PMAC_IDE_REG(IDE_TIMING_CONFIG));
+		(void)readl(PMAC_IDE_REG(IDE_TIMING_CONFIG));
 	}
 
 	drive->waiting_for_dma = 1;
@@ -1992,7 +1983,7 @@
 pmac_ide_dma_begin (ide_drive_t *drive)
 {
 	pmac_ide_hwif_t* pmif = (pmac_ide_hwif_t *)HWIF(drive)->hwif_data;
-	volatile struct dbdma_regs *dma;
+	volatile struct dbdma_regs __iomem *dma;
 
 	if (pmif == NULL)
 		return 1;
@@ -2011,7 +2002,7 @@
 pmac_ide_dma_end (ide_drive_t *drive)
 {
 	pmac_ide_hwif_t* pmif = (pmac_ide_hwif_t *)HWIF(drive)->hwif_data;
-	volatile struct dbdma_regs *dma;
+	volatile struct dbdma_regs __iomem *dma;
 	u32 dstat;
 	
 	if (pmif == NULL)
@@ -2039,7 +2030,7 @@
 pmac_ide_dma_test_irq (ide_drive_t *drive)
 {
 	pmac_ide_hwif_t* pmif = (pmac_ide_hwif_t *)HWIF(drive)->hwif_data;
-	volatile struct dbdma_regs *dma;
+	volatile struct dbdma_regs __iomem *dma;
 	unsigned long status, timeout;
 
 	if (pmif == NULL)
@@ -2107,7 +2098,7 @@
 pmac_ide_dma_lostirq (ide_drive_t *drive)
 {
 	pmac_ide_hwif_t* pmif = (pmac_ide_hwif_t *)HWIF(drive)->hwif_data;
-	volatile struct dbdma_regs *dma;
+	volatile struct dbdma_regs __iomem *dma;
 	unsigned long status;
 
 	if (pmif == NULL)
diff -Nru a/drivers/ieee1394/eth1394.c b/drivers/ieee1394/eth1394.c
--- a/drivers/ieee1394/eth1394.c	2004-10-18 14:56:33 -07:00
+++ b/drivers/ieee1394/eth1394.c	2004-10-18 14:56:33 -07:00
@@ -132,7 +132,7 @@
 };
 
 /* Our ieee1394 highlevel driver */
-#define ETH1394_DRIVER_NAME "ip1394"
+#define ETH1394_DRIVER_NAME "eth1394"
 static const char driver_name[] = ETH1394_DRIVER_NAME;
 
 static kmem_cache_t *packet_task_cache;
@@ -850,7 +850,7 @@
 
 	skb->mac.raw = skb->data;
 	skb_pull (skb, ETH1394_HLEN);
-	eth = (struct eth1394hdr*)skb->mac.raw;
+	eth = eth1394_hdr(skb);
 
 	if (*eth->h_dest & 1) {
 		if (memcmp(eth->h_dest, dev->broadcast, dev->addr_len)==0)
diff -Nru a/drivers/ieee1394/eth1394.h b/drivers/ieee1394/eth1394.h
--- a/drivers/ieee1394/eth1394.h	2004-10-18 14:57:03 -07:00
+++ b/drivers/ieee1394/eth1394.h	2004-10-18 14:57:03 -07:00
@@ -81,7 +81,14 @@
 	unsigned short	h_proto;		/* packet type ID field	*/
 }  __attribute__((packed));
 
+#ifdef __KERNEL__
+#include <linux/skbuff.h>
 
+static inline struct eth1394hdr *eth1394_hdr(const struct sk_buff *skb)
+{
+	return (struct eth1394hdr *)skb->mac.raw;
+}
+#endif
 
 typedef enum {ETH1394_GASP, ETH1394_WRREQ} eth1394_tx_type;
 
diff -Nru a/drivers/ieee1394/ohci1394.h b/drivers/ieee1394/ohci1394.h
--- a/drivers/ieee1394/ohci1394.h	2004-10-18 14:55:55 -07:00
+++ b/drivers/ieee1394/ohci1394.h	2004-10-18 14:55:55 -07:00
@@ -163,7 +163,7 @@
 	} init_state;
 
         /* remapped memory spaces */
-        void *registers;
+        void __iomem *registers;
 
 	/* dma buffer for self-id packets */
         quadlet_t *selfid_buf_cpu;
diff -Nru a/drivers/input/gameport/cs461x.c b/drivers/input/gameport/cs461x.c
--- a/drivers/input/gameport/cs461x.c	2004-10-18 14:55:54 -07:00
+++ b/drivers/input/gameport/cs461x.c	2004-10-18 14:55:54 -07:00
@@ -312,7 +312,7 @@
 }
 
 static struct pci_driver cs461x_pci_driver = {
-        .name =         "CS461x Gameport",
+        .name =         "CS461x_gameport",
         .id_table =     cs461x_pci_tbl,
         .probe =        cs461x_pci_probe,
         .remove =       __devexit_p(cs461x_pci_remove),
diff -Nru a/drivers/input/gameport/emu10k1-gp.c b/drivers/input/gameport/emu10k1-gp.c
--- a/drivers/input/gameport/emu10k1-gp.c	2004-10-18 14:56:33 -07:00
+++ b/drivers/input/gameport/emu10k1-gp.c	2004-10-18 14:56:33 -07:00
@@ -50,8 +50,11 @@
 };
 
 static struct pci_device_id emu_tbl[] = {
+ 
 	{ 0x1102, 0x7002, PCI_ANY_ID, PCI_ANY_ID }, /* SB Live gameport */
 	{ 0x1102, 0x7003, PCI_ANY_ID, PCI_ANY_ID }, /* Audigy gameport */
+	{ 0x1102, 0x7004, PCI_ANY_ID, PCI_ANY_ID }, /* Dell SB Live */
+	{ 0x1102, 0x7005, PCI_ANY_ID, PCI_ANY_ID }, /* Audigy LS gameport */
 	{ 0, }
 };
 
@@ -109,7 +112,7 @@
 }
 
 static struct pci_driver emu_driver = {
-        .name =         "Emu10k1 Gameport",
+        .name =         "Emu10k1_gameport",
         .id_table =     emu_tbl,
         .probe =        emu_probe,
         .remove =       __devexit_p(emu_remove),
diff -Nru a/drivers/input/gameport/fm801-gp.c b/drivers/input/gameport/fm801-gp.c
--- a/drivers/input/gameport/fm801-gp.c	2004-10-18 14:56:33 -07:00
+++ b/drivers/input/gameport/fm801-gp.c	2004-10-18 14:56:33 -07:00
@@ -137,7 +137,7 @@
 };
 
 static struct pci_driver fm801_gp_driver = {
-	.name =		"FM801 GP",
+	.name =		"FM801_gameport",
 	.id_table =	fm801_gp_id_table,
 	.probe =	fm801_gp_probe,
 	.remove =	__devexit_p(fm801_gp_remove),
diff -Nru a/drivers/input/gameport/vortex.c b/drivers/input/gameport/vortex.c
--- a/drivers/input/gameport/vortex.c	2004-10-18 14:56:49 -07:00
+++ b/drivers/input/gameport/vortex.c	2004-10-18 14:56:49 -07:00
@@ -55,8 +55,8 @@
 struct vortex {
 	struct gameport gameport;
 	struct pci_dev *dev;
-        unsigned char *base;
-        unsigned char *io;
+        unsigned char __iomem *base;
+        unsigned char __iomem *io;
 	char phys[32];
 };
 
@@ -166,7 +166,7 @@
  { 0 }};
 
 static struct pci_driver vortex_driver = {
-	.name =		"vortex",
+	.name =		"vortex_gameport",
 	.id_table =	vortex_id_table,
 	.probe =	vortex_probe,
 	.remove =	__devexit_p(vortex_remove),
diff -Nru a/drivers/input/joydev.c b/drivers/input/joydev.c
--- a/drivers/input/joydev.c	2004-10-18 14:56:31 -07:00
+++ b/drivers/input/joydev.c	2004-10-18 14:56:31 -07:00
@@ -232,8 +232,10 @@
 		&& list->head == list->tail && (file->f_flags & O_NONBLOCK))
 			return -EAGAIN;
 
-	retval = wait_event_interruptible(list->joydev->wait, list->joydev->exist
-		&& (list->startup < joydev->nabs + joydev->nkey || list->head != list->tail));
+	retval = wait_event_interruptible(list->joydev->wait,
+		 			  !list->joydev->exist ||
+					  list->startup < joydev->nabs + joydev->nkey ||
+					  list->head != list->tail);
 
 	if (retval)
 		return retval;
diff -Nru a/drivers/input/joystick/Kconfig b/drivers/input/joystick/Kconfig
--- a/drivers/input/joystick/Kconfig	2004-10-18 14:55:53 -07:00
+++ b/drivers/input/joystick/Kconfig	2004-10-18 14:55:53 -07:00
@@ -247,9 +247,9 @@
 	  To compile this driver as a module, choose M here: the
 	  module will be called amijoy.
 
-config INPUT_JOYDUMP
+config JOYSTICK_JOYDUMP
 	tristate "Gameport data dumper"
-	depends on INPUT && INPUT_JOYSTICK
+	depends on INPUT && INPUT_JOYSTICK && GAMEPORT
 	help
 	  Say Y here if you want to dump data from your joystick into the system
 	  log for debugging purposes. Say N if you are making a production
diff -Nru a/drivers/input/joystick/gamecon.c b/drivers/input/joystick/gamecon.c
--- a/drivers/input/joystick/gamecon.c	2004-10-18 14:57:05 -07:00
+++ b/drivers/input/joystick/gamecon.c	2004-10-18 14:57:05 -07:00
@@ -1,7 +1,8 @@
 /*
- * $Id: gamecon.c,v 1.22 2002/07/01 15:42:25 vojtech Exp $
+ * NES, SNES, N64, MultiSystem, PSX gamepad driver for Linux
  *
- *  Copyright (c) 1999-2001 Vojtech Pavlik
+ *  Copyright (c) 1999-2004 	Vojtech Pavlik <vojtech@suse.cz>
+ *  Copyright (c) 2004 		Peter Nelson <rufus-kernel@hackish.org>
  *
  *  Based on the work of:
  *  	Andree Borrmann		John Dahlstrom
@@ -9,10 +10,6 @@
  */
 
 /*
- * NES, SNES, N64, MultiSystem, PSX gamepad driver for Linux
- */
-
-/*
  * 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
@@ -72,8 +69,9 @@
 #define GC_MULTI2	5
 #define GC_N64		6
 #define GC_PSX		7
+#define GC_DDR		8
 
-#define GC_MAX		7
+#define GC_MAX		8
 
 #define GC_REFRESH_TIME	HZ/100
 
@@ -91,7 +89,8 @@
 static int gc_status_bit[] = { 0x40, 0x80, 0x20, 0x10, 0x08 };
 
 static char *gc_names[] = { NULL, "SNES pad", "NES pad", "NES FourPort", "Multisystem joystick",
-				"Multisystem 2-button joystick", "N64 controller", "PSX controller" };
+				"Multisystem 2-button joystick", "N64 controller", "PSX controller"
+				"PSX DDR controller" };
 /*
  * N64 support.
  */
@@ -237,7 +236,7 @@
 #define GC_PSX_RUMBLE	7		/* Rumble in Red mode */
 
 #define GC_PSX_CLOCK	0x04		/* Pin 4 */
-#define GC_PSX_COMMAND	0x01		/* Pin 1 */
+#define GC_PSX_COMMAND	0x01		/* Pin 2 */
 #define GC_PSX_POWER	0xf8		/* Pins 5-9 */
 #define GC_PSX_SELECT	0x02		/* Pin 3 */
 
@@ -253,25 +252,29 @@
 static short gc_psx_abs[] = { ABS_X, ABS_Y, ABS_RX, ABS_RY, ABS_HAT0X, ABS_HAT0Y };
 static short gc_psx_btn[] = { BTN_TL, BTN_TR, BTN_TL2, BTN_TR2, BTN_A, BTN_B, BTN_X, BTN_Y,
 				BTN_START, BTN_SELECT, BTN_THUMBL, BTN_THUMBR };
+static short gc_psx_ddr_btn[] = { BTN_0, BTN_1, BTN_2, BTN_3 };
 
 /*
  * gc_psx_command() writes 8bit command and reads 8bit data from
  * the psx pad.
  */
 
-static int gc_psx_command(struct gc *gc, int b)
+static void gc_psx_command(struct gc *gc, int b, unsigned char data[GC_PSX_LENGTH])
 {
-	int i, cmd, data = 0;
+	int i, j, cmd, read;
+	for (i = 0; i < 5; i++)
+		data[i] = 0;
 
 	for (i = 0; i < 8; i++, b >>= 1) {
 		cmd = (b & 1) ? GC_PSX_COMMAND : 0;
 		parport_write_data(gc->pd->port, cmd | GC_PSX_POWER);
 		udelay(gc_psx_delay);
-		data |= ((parport_read_status(gc->pd->port) ^ 0x80) & gc->pads[GC_PSX]) ? (1 << i) : 0;
+		read = parport_read_status(gc->pd->port) ^ 0x80;
+		for (j = 0; j < 5; j++)
+			data[j] |= (read & gc_status_bit[j] & gc->pads[GC_PSX]) ? (1 << i) : 0;
 		parport_write_data(gc->pd->port, cmd | GC_PSX_CLOCK | GC_PSX_POWER);
 		udelay(gc_psx_delay);
 	}
-	return data;
 }
 
 /*
@@ -279,30 +282,39 @@
  * device identifier code.
  */
 
-static int gc_psx_read_packet(struct gc *gc, unsigned char *data)
+static void gc_psx_read_packet(struct gc *gc, unsigned char data[5][GC_PSX_LENGTH], unsigned char id[5])
 {
-	int i, id;
+	int i, j, max_len = 0;
 	unsigned long flags;
+	unsigned char data2[5];
 
 	parport_write_data(gc->pd->port, GC_PSX_CLOCK | GC_PSX_SELECT | GC_PSX_POWER);	/* Select pad */
-	udelay(gc_psx_delay * 2);
+	udelay(gc_psx_delay);
 	parport_write_data(gc->pd->port, GC_PSX_CLOCK | GC_PSX_POWER);			/* Deselect, begin command */
-	udelay(gc_psx_delay * 2);
+	udelay(gc_psx_delay);
 
 	local_irq_save(flags);
 
-	gc_psx_command(gc, 0x01);							/* Access pad */
-	id = gc_psx_command(gc, 0x42);							/* Get device id */
-	if (gc_psx_command(gc, 0) == 0x5a) {						/* Okay? */
-		for (i = 0; i < GC_PSX_LEN(id) * 2; i++)
-			data[i] = gc_psx_command(gc, 0);
-	} else id = 0;
+	gc_psx_command(gc, 0x01, data2);						/* Access pad */
+	gc_psx_command(gc, 0x42, id);							/* Get device ids */
+	gc_psx_command(gc, 0, data2);							/* Dump status */
+
+	for (i =0; i < 5; i++)								/* Find the longest pad */
+		if((gc_status_bit[i] & gc->pads[GC_PSX]) && (GC_PSX_LEN(id[i]) > max_len))
+			max_len = GC_PSX_LEN(id[i]);
+
+	for (i = 0; i < max_len * 2; i++) {						/* Read in all the data */
+		gc_psx_command(gc, 0, data2);
+		for (j = 0; j < 5; j++)
+			data[j][i] = data2[j];
+	}
 
 	local_irq_restore(flags);
 
 	parport_write_data(gc->pd->port, GC_PSX_CLOCK | GC_PSX_SELECT | GC_PSX_POWER);
 
-	return GC_PSX_ID(id);
+	for(i = 0; i < 5; i++)								/* Set id's to the real value */
+		id[i] = GC_PSX_ID(id[i]);
 }
 
 /*
@@ -316,6 +328,7 @@
 	struct gc *gc = (void *) private;
 	struct input_dev *dev = gc->dev;
 	unsigned char data[GC_MAX_LENGTH];
+	unsigned char data_psx[5][GC_PSX_LENGTH];
 	int i, j, s;
 
 /*
@@ -412,53 +425,72 @@
  * PSX controllers
  */
 
-	if (gc->pads[GC_PSX]) {
+	if (gc->pads[GC_PSX] || gc->pads[GC_DDR]) {
 
-		for (i = 0; i < 5; i++)
-	       		if (gc->pads[GC_PSX] & gc_status_bit[i])
-				break;
+		gc_psx_read_packet(gc, data_psx, data);
 
- 		switch (gc_psx_read_packet(gc, data)) {
+		for (i = 0; i < 5; i++) {
+	 		switch (data[i]) {
 
-			case GC_PSX_RUMBLE:
+				case GC_PSX_RUMBLE:
 
-				input_report_key(dev + i, BTN_THUMBL, ~data[0] & 0x04);
-				input_report_key(dev + i, BTN_THUMBR, ~data[0] & 0x02);
-				input_sync(dev + i);
+					input_report_key(dev + i, BTN_THUMBL, ~data_psx[i][0] & 0x04);
+					input_report_key(dev + i, BTN_THUMBR, ~data_psx[i][0] & 0x02);
 
-			case GC_PSX_NEGCON:
-			case GC_PSX_ANALOG:
+				case GC_PSX_NEGCON:
+				case GC_PSX_ANALOG:
 
-				for (j = 0; j < 4; j++)
-					input_report_abs(dev + i, gc_psx_abs[j], data[j + 2]);
+					if(gc->pads[GC_DDR] & gc_status_bit[i]) {
+						for(j = 0; j < 4; j++)
+							input_report_key(dev + i, gc_psx_ddr_btn[j], ~data_psx[i][0] & (0x10 << j));
+					} else {
+						for (j = 0; j < 4; j++)
+							input_report_abs(dev + i, gc_psx_abs[j+2], data_psx[i][j + 2]);
 
-				input_report_abs(dev + i, ABS_HAT0X, !(data[0] & 0x20) - !(data[0] & 0x80));
-				input_report_abs(dev + i, ABS_HAT0Y, !(data[0] & 0x40) - !(data[0] & 0x10));
+						input_report_abs(dev + i, ABS_X, 128 + !(data_psx[i][0] & 0x20) * 127 - !(data_psx[i][0] & 0x80) * 128);
+						input_report_abs(dev + i, ABS_Y, 128 + !(data_psx[i][0] & 0x40) * 127 - !(data_psx[i][0] & 0x10) * 128);
+					}
 
-				for (j = 0; j < 8; j++)
-					input_report_key(dev + i, gc_psx_btn[j], ~data[1] & (1 << j));
+					for (j = 0; j < 8; j++)
+						input_report_key(dev + i, gc_psx_btn[j], ~data_psx[i][1] & (1 << j));
 
-				input_report_key(dev + i, BTN_START,  ~data[0] & 0x08);
-				input_report_key(dev + i, BTN_SELECT, ~data[0] & 0x01);
+					input_report_key(dev + i, BTN_START,  ~data_psx[i][0] & 0x08);
+					input_report_key(dev + i, BTN_SELECT, ~data_psx[i][0] & 0x01);
 
-				input_sync(dev + i);
+					input_sync(dev + i);
 
-				break;
+					break;
 
-			case GC_PSX_NORMAL:
+				case GC_PSX_NORMAL:
+					if(gc->pads[GC_DDR] & gc_status_bit[i]) {
+						for(j = 0; j < 4; j++)
+							input_report_key(dev + i, gc_psx_ddr_btn[j], ~data_psx[i][0] & (0x10 << j));
+					} else {
+						input_report_abs(dev + i, ABS_X, 128 + !(data_psx[i][0] & 0x20) * 127 - !(data_psx[i][0] & 0x80) * 128);
+						input_report_abs(dev + i, ABS_Y, 128 + !(data_psx[i][0] & 0x40) * 127 - !(data_psx[i][0] & 0x10) * 128);
 
-				input_report_abs(dev + i, ABS_X, 128 + !(data[0] & 0x20) * 127 - !(data[0] & 0x80) * 128);
-				input_report_abs(dev + i, ABS_Y, 128 + !(data[0] & 0x40) * 127 - !(data[0] & 0x10) * 128);
+						/* for some reason if the extra axes are left unset they drift */
+						/* for (j = 0; j < 4; j++)
+							input_report_abs(dev + i, gc_psx_abs[j+2], 128);
+						 * This needs to be debugged properly,
+						 * maybe fuzz processing needs to be done in input_sync()
+						 *				 --vojtech
+						 */
+					}
 
-				for (j = 0; j < 8; j++)
-					input_report_key(dev + i, gc_psx_btn[j], ~data[1] & (1 << j));
+					for (j = 0; j < 8; j++)
+						input_report_key(dev + i, gc_psx_btn[j], ~data_psx[i][1] & (1 << j));
 
-				input_report_key(dev + i, BTN_START,  ~data[0] & 0x08);
-				input_report_key(dev + i, BTN_SELECT, ~data[0] & 0x01);
+					input_report_key(dev + i, BTN_START,  ~data_psx[i][0] & 0x08);
+					input_report_key(dev + i, BTN_SELECT, ~data_psx[i][0] & 0x01);
 
-				input_sync(dev + i);
+					input_sync(dev + i);
 
-				break;
+					break;
+
+				case 0: /* not a pad, ignore */
+					break;
+			}
 		}
 	}
 
@@ -490,8 +522,7 @@
 {
 	struct gc *gc;
 	struct parport *pp;
-	int i, j, psx;
-	unsigned char data[32];
+	int i, j;
 
 	if (config[0] < 0)
 		return NULL;
@@ -588,43 +619,22 @@
 				break;
 
 			case GC_PSX:
+			case GC_DDR:
+				if(config[i + 1] == GC_DDR) {
+					for (j = 0; j < 4; j++)
+						set_bit(gc_psx_ddr_btn[j], gc->dev[i].keybit);
+				} else {
+					for (j = 0; j < 6; j++) {
+						set_bit(gc_psx_abs[j], gc->dev[i].absbit);
+						gc->dev[i].absmin[gc_psx_abs[j]] = 4;
+						gc->dev[i].absmax[gc_psx_abs[j]] = 252;
+						gc->dev[i].absflat[gc_psx_abs[j]] = 2;
+					}
+				}
 
-				psx = gc_psx_read_packet(gc, data);
+				for (j = 0; j < 12; j++)
+					set_bit(gc_psx_btn[j], gc->dev[i].keybit);
 
-				switch(psx) {
-					case GC_PSX_NEGCON:
-					case GC_PSX_NORMAL:
-					case GC_PSX_ANALOG:
-					case GC_PSX_RUMBLE:
-
-						for (j = 0; j < 6; j++) {
-							psx = gc_psx_abs[j];
-							set_bit(psx, gc->dev[i].absbit);
-							if (j < 4) {
-								gc->dev[i].absmin[psx] = 4;
-								gc->dev[i].absmax[psx] = 252;
-								gc->dev[i].absflat[psx] = 2;
-							} else {
-								gc->dev[i].absmin[psx] = -1;
-								gc->dev[i].absmax[psx] = 1;
-							}
-						}
-
-						for (j = 0; j < 12; j++)
-							set_bit(gc_psx_btn[j], gc->dev[i].keybit);
-
-						break;
-
-					case 0:
-						gc->pads[GC_PSX] &= ~gc_status_bit[i];
-						printk(KERN_ERR "gamecon.c: No PSX controller found.\n");
-						break;
-
-					default:
-						gc->pads[GC_PSX] &= ~gc_status_bit[i];
-						printk(KERN_WARNING "gamecon.c: Unsupported PSX controller %#x,"
-							" please report to <vojtech@ucw.cz>.\n", psx);
-				}
 				break;
 		}
 
diff -Nru a/drivers/input/joystick/grip_mp.c b/drivers/input/joystick/grip_mp.c
--- a/drivers/input/joystick/grip_mp.c	2004-10-18 14:57:03 -07:00
+++ b/drivers/input/joystick/grip_mp.c	2004-10-18 14:57:03 -07:00
@@ -107,6 +107,8 @@
 
 static int axis_map[] = { 5, 9, 1, 5, 6, 10, 2, 6, 4, 8, 0, 4, 5, 9, 1, 5 };
 
+static void register_slot(int i, struct grip_mp *grip);
+
 /*
  * Returns whether an odd or even number of bits are on in pkt.
  */
@@ -355,7 +357,6 @@
 	u32 packet;
 	int joytype = 0;
 	int slot = 0;
-	static void register_slot(int i, struct grip_mp *grip);
 
 	/* Get a packet and check for validity */
 
diff -Nru a/drivers/input/joystick/iforce/iforce-main.c b/drivers/input/joystick/iforce/iforce-main.c
--- a/drivers/input/joystick/iforce/iforce-main.c	2004-10-18 14:56:28 -07:00
+++ b/drivers/input/joystick/iforce/iforce-main.c	2004-10-18 14:56:28 -07:00
@@ -524,7 +524,7 @@
 	usb_register(&iforce_usb_driver);
 #endif
 #ifdef CONFIG_JOYSTICK_IFORCE_232
-	serio_register_device(&iforce_serio_dev);
+	serio_register_driver(&iforce_serio_drv);
 #endif
 	return 0;
 }
@@ -535,7 +535,7 @@
 	usb_deregister(&iforce_usb_driver);
 #endif
 #ifdef CONFIG_JOYSTICK_IFORCE_232
-	serio_unregister_device(&iforce_serio_dev);
+	serio_unregister_driver(&iforce_serio_drv);
 #endif
 }
 
diff -Nru a/drivers/input/joystick/iforce/iforce-serio.c b/drivers/input/joystick/iforce/iforce-serio.c
--- a/drivers/input/joystick/iforce/iforce-serio.c	2004-10-18 14:55:54 -07:00
+++ b/drivers/input/joystick/iforce/iforce-serio.c	2004-10-18 14:55:54 -07:00
@@ -124,7 +124,7 @@
 	return IRQ_HANDLED;
 }
 
-static void iforce_serio_connect(struct serio *serio, struct serio_dev *dev)
+static void iforce_serio_connect(struct serio *serio, struct serio_driver *drv)
 {
 	struct iforce *iforce;
 	if (serio->type != (SERIO_RS232 | SERIO_IFORCE))
@@ -137,7 +137,7 @@
 	iforce->serio = serio;
 	serio->private = iforce;
 
-	if (serio_open(serio, dev)) {
+	if (serio_open(serio, drv)) {
 		kfree(iforce);
 		return;
 	}
@@ -158,9 +158,13 @@
 	kfree(iforce);
 }
 
-struct serio_dev iforce_serio_dev = {
-	.write_wakeup =	iforce_serio_write_wakeup,
-	.interrupt =	iforce_serio_irq,
-	.connect =	iforce_serio_connect,
-	.disconnect =	iforce_serio_disconnect,
+struct serio_driver iforce_serio_drv = {
+	.driver		= {
+		.name	= "iforce",
+	},
+	.description	= "RS232 I-Force joysticks and wheels driver",
+	.write_wakeup	= iforce_serio_write_wakeup,
+	.interrupt	= iforce_serio_irq,
+	.connect	= iforce_serio_connect,
+	.disconnect	= iforce_serio_disconnect,
 };
diff -Nru a/drivers/input/joystick/iforce/iforce.h b/drivers/input/joystick/iforce/iforce.h
--- a/drivers/input/joystick/iforce/iforce.h	2004-10-18 14:57:20 -07:00
+++ b/drivers/input/joystick/iforce/iforce.h	2004-10-18 14:57:20 -07:00
@@ -187,5 +187,5 @@
 int iforce_upload_condition(struct iforce*, struct ff_effect*, int is_update);
 
 /* Public variables */
-extern struct serio_dev iforce_serio_dev;
+extern struct serio_driver iforce_serio_drv;
 extern struct usb_driver iforce_usb_driver;
diff -Nru a/drivers/input/joystick/magellan.c b/drivers/input/joystick/magellan.c
--- a/drivers/input/joystick/magellan.c	2004-10-18 14:55:54 -07:00
+++ b/drivers/input/joystick/magellan.c	2004-10-18 14:55:54 -07:00
@@ -35,8 +35,10 @@
 #include <linux/serio.h>
 #include <linux/init.h>
 
+#define DRIVER_DESC	"Magellan and SpaceMouse 6dof controller driver"
+
 MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>");
-MODULE_DESCRIPTION("Magellan and SpaceMouse 6dof controller driver");
+MODULE_DESCRIPTION(DRIVER_DESC);
 MODULE_LICENSE("GPL");
 
 /*
@@ -146,7 +148,7 @@
  * it as an input device.
  */
 
-static void magellan_connect(struct serio *serio, struct serio_dev *dev)
+static void magellan_connect(struct serio *serio, struct serio_driver *drv)
 {
 	struct magellan *magellan;
 	int i, t;
@@ -184,7 +186,7 @@
 
 	serio->private = magellan;
 
-	if (serio_open(serio, dev)) {
+	if (serio_open(serio, drv)) {
 		kfree(magellan);
 		return;
 	}
@@ -199,10 +201,14 @@
  * The serio device structure.
  */
 
-static struct serio_dev magellan_dev = {
-	.interrupt =	magellan_interrupt,
-	.connect =	magellan_connect,
-	.disconnect =	magellan_disconnect,
+static struct serio_driver magellan_drv = {
+	.driver		= {
+		.name	= "magellan",
+	},
+	.description	= DRIVER_DESC,
+	.interrupt	= magellan_interrupt,
+	.connect	= magellan_connect,
+	.disconnect	= magellan_disconnect,
 };
 
 /*
@@ -211,13 +217,13 @@
 
 int __init magellan_init(void)
 {
-	serio_register_device(&magellan_dev);
+	serio_register_driver(&magellan_drv);
 	return 0;
 }
 
 void __exit magellan_exit(void)
 {
-	serio_unregister_device(&magellan_dev);
+	serio_unregister_driver(&magellan_drv);
 }
 
 module_init(magellan_init);
diff -Nru a/drivers/input/joystick/spaceball.c b/drivers/input/joystick/spaceball.c
--- a/drivers/input/joystick/spaceball.c	2004-10-18 14:55:54 -07:00
+++ b/drivers/input/joystick/spaceball.c	2004-10-18 14:55:54 -07:00
@@ -39,8 +39,10 @@
 #include <linux/input.h>
 #include <linux/serio.h>
 
+#define DRIVER_DESC	"SpaceTec SpaceBall 2003/3003/4000 FLX driver"
+
 MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>");
-MODULE_DESCRIPTION("SpaceTec SpaceBall 2003/3003/4000 FLX driver");
+MODULE_DESCRIPTION(DRIVER_DESC);
 MODULE_LICENSE("GPL");
 
 /*
@@ -201,7 +203,7 @@
  * it as an input device.
  */
 
-static void spaceball_connect(struct serio *serio, struct serio_dev *dev)
+static void spaceball_connect(struct serio *serio, struct serio_driver *drv)
 {
 	struct spaceball *spaceball;
 	int i, t, id;
@@ -254,7 +256,7 @@
 
 	serio->private = spaceball;
 
-	if (serio_open(serio, dev)) {
+	if (serio_open(serio, drv)) {
 		kfree(spaceball);
 		return;
 	}
@@ -269,10 +271,14 @@
  * The serio device structure.
  */
 
-static struct serio_dev spaceball_dev = {
-	.interrupt =	spaceball_interrupt,
-	.connect =	spaceball_connect,
-	.disconnect =	spaceball_disconnect,
+static struct serio_driver spaceball_drv = {
+	.driver		= {
+		.name	= "spaceball",
+	},
+	.description	= DRIVER_DESC,
+	.interrupt	= spaceball_interrupt,
+	.connect	= spaceball_connect,
+	.disconnect	= spaceball_disconnect,
 };
 
 /*
@@ -281,13 +287,13 @@
 
 int __init spaceball_init(void)
 {
-	serio_register_device(&spaceball_dev);
+	serio_register_driver(&spaceball_drv);
 	return 0;
 }
 
 void __exit spaceball_exit(void)
 {
-	serio_unregister_device(&spaceball_dev);
+	serio_unregister_driver(&spaceball_drv);
 }
 
 module_init(spaceball_init);
diff -Nru a/drivers/input/joystick/spaceorb.c b/drivers/input/joystick/spaceorb.c
--- a/drivers/input/joystick/spaceorb.c	2004-10-18 14:56:29 -07:00
+++ b/drivers/input/joystick/spaceorb.c	2004-10-18 14:56:29 -07:00
@@ -38,8 +38,10 @@
 #include <linux/input.h>
 #include <linux/serio.h>
 
+#define DRIVER_DESC	"SpaceTec SpaceOrb 360 and Avenger 6dof controller driver"
+
 MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>");
-MODULE_DESCRIPTION("SpaceTec SpaceOrb 360 and Avenger 6dof controller driver");
+MODULE_DESCRIPTION(DRIVER_DESC);
 MODULE_LICENSE("GPL");
 
 /*
@@ -162,7 +164,7 @@
  * it as an input device.
  */
 
-static void spaceorb_connect(struct serio *serio, struct serio_dev *dev)
+static void spaceorb_connect(struct serio *serio, struct serio_driver *drv)
 {
 	struct spaceorb *spaceorb;
 	int i, t;
@@ -201,7 +203,7 @@
 
 	serio->private = spaceorb;
 
-	if (serio_open(serio, dev)) {
+	if (serio_open(serio, drv)) {
 		kfree(spaceorb);
 		return;
 	}
@@ -213,10 +215,14 @@
  * The serio device structure.
  */
 
-static struct serio_dev spaceorb_dev = {
-	.interrupt =	spaceorb_interrupt,
-	.connect =	spaceorb_connect,
-	.disconnect =	spaceorb_disconnect,
+static struct serio_driver spaceorb_drv = {
+	.driver		= {
+		.name	= "spaceorb",
+	},
+	.description	= DRIVER_DESC,
+	.interrupt	= spaceorb_interrupt,
+	.connect	= spaceorb_connect,
+	.disconnect	= spaceorb_disconnect,
 };
 
 /*
@@ -225,13 +231,13 @@
 
 int __init spaceorb_init(void)
 {
-	serio_register_device(&spaceorb_dev);
+	serio_register_driver(&spaceorb_drv);
 	return 0;
 }
 
 void __exit spaceorb_exit(void)
 {
-	serio_unregister_device(&spaceorb_dev);
+	serio_unregister_driver(&spaceorb_drv);
 }
 
 module_init(spaceorb_init);
diff -Nru a/drivers/input/joystick/stinger.c b/drivers/input/joystick/stinger.c
--- a/drivers/input/joystick/stinger.c	2004-10-18 14:55:53 -07:00
+++ b/drivers/input/joystick/stinger.c	2004-10-18 14:55:53 -07:00
@@ -36,8 +36,10 @@
 #include <linux/serio.h>
 #include <linux/init.h>
 
+#define DRIVER_DESC	"Gravis Stinger gamepad driver"
+
 MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>");
-MODULE_DESCRIPTION("Gravis Stinger gamepad driver");
+MODULE_DESCRIPTION(DRIVER_DESC);
 MODULE_LICENSE("GPL");
 
 /*
@@ -134,7 +136,7 @@
  * it as an input device.
  */
 
-static void stinger_connect(struct serio *serio, struct serio_dev *dev)
+static void stinger_connect(struct serio *serio, struct serio_driver *drv)
 {
 	struct stinger *stinger;
 	int i;
@@ -172,7 +174,7 @@
 	stinger->dev.private = stinger;
 	serio->private = stinger;
 
-	if (serio_open(serio, dev)) {
+	if (serio_open(serio, drv)) {
 		kfree(stinger);
 		return;
 	}
@@ -187,10 +189,14 @@
  * The serio device structure.
  */
 
-static struct serio_dev stinger_dev = {
-	.interrupt =	stinger_interrupt,
-	.connect =	stinger_connect,
-	.disconnect =	stinger_disconnect,
+static struct serio_driver stinger_drv = {
+	.driver		= {
+		.name	= "stinger",
+	},
+	.description	= DRIVER_DESC,
+	.interrupt	= stinger_interrupt,
+	.connect	= stinger_connect,
+	.disconnect	= stinger_disconnect,
 };
 
 /*
@@ -199,13 +205,13 @@
 
 int __init stinger_init(void)
 {
-	serio_register_device(&stinger_dev);
+	serio_register_driver(&stinger_drv);
 	return 0;
 }
 
 void __exit stinger_exit(void)
 {
-	serio_unregister_device(&stinger_dev);
+	serio_unregister_driver(&stinger_drv);
 }
 
 module_init(stinger_init);
diff -Nru a/drivers/input/joystick/tmdc.c b/drivers/input/joystick/tmdc.c
--- a/drivers/input/joystick/tmdc.c	2004-10-18 14:56:28 -07:00
+++ b/drivers/input/joystick/tmdc.c	2004-10-18 14:56:28 -07:00
@@ -322,7 +322,7 @@
 			tmdc->dev[j].evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
 
 			for (i = 0; i < models[m].abs && i < TMDC_ABS; i++) {
-				if (tmdc->abs[i] < 0) continue;
+				if (tmdc->abs[j][i] < 0) continue;
 				set_bit(tmdc->abs[j][i], tmdc->dev[j].absbit);
 				tmdc->dev[j].absmin[tmdc->abs[j][i]] = 8;
 				tmdc->dev[j].absmax[tmdc->abs[j][i]] = 248;
diff -Nru a/drivers/input/joystick/twidjoy.c b/drivers/input/joystick/twidjoy.c
--- a/drivers/input/joystick/twidjoy.c	2004-10-18 14:55:54 -07:00
+++ b/drivers/input/joystick/twidjoy.c	2004-10-18 14:55:54 -07:00
@@ -187,7 +187,7 @@
  * it as an input device.
  */
 
-static void twidjoy_connect(struct serio *serio, struct serio_dev *dev)
+static void twidjoy_connect(struct serio *serio, struct serio_driver *drv)
 {
 	struct twidjoy_button_spec *bp;
 	struct twidjoy *twidjoy;
@@ -232,7 +232,7 @@
 	twidjoy->dev.private = twidjoy;
 	serio->private = twidjoy;
 
-	if (serio_open(serio, dev)) {
+	if (serio_open(serio, drv)) {
 		kfree(twidjoy);
 		return;
 	}
@@ -246,10 +246,14 @@
  * The serio device structure.
  */
 
-static struct serio_dev twidjoy_dev = {
-	.interrupt =	twidjoy_interrupt,
-	.connect =	twidjoy_connect,
-	.disconnect =	twidjoy_disconnect,
+static struct serio_driver twidjoy_drv = {
+	.driver		= {
+		.name	= "twidjoy",
+	},
+	.description	= DRIVER_DESC,
+	.interrupt	= twidjoy_interrupt,
+	.connect	= twidjoy_connect,
+	.disconnect	= twidjoy_disconnect,
 };
 
 /*
@@ -258,13 +262,13 @@
 
 int __init twidjoy_init(void)
 {
-	serio_register_device(&twidjoy_dev);
+	serio_register_driver(&twidjoy_drv);
 	return 0;
 }
 
 void __exit twidjoy_exit(void)
 {
-	serio_unregister_device(&twidjoy_dev);
+	serio_unregister_driver(&twidjoy_drv);
 }
 
 module_init(twidjoy_init);
diff -Nru a/drivers/input/joystick/warrior.c b/drivers/input/joystick/warrior.c
--- a/drivers/input/joystick/warrior.c	2004-10-18 14:56:48 -07:00
+++ b/drivers/input/joystick/warrior.c	2004-10-18 14:56:48 -07:00
@@ -35,8 +35,10 @@
 #include <linux/serio.h>
 #include <linux/init.h>
 
+#define DRIVER_DESC	"Logitech WingMan Warrior joystick driver"
+
 MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>");
-MODULE_DESCRIPTION("Logitech WingMan Warrior joystick driver");
+MODULE_DESCRIPTION(DRIVER_DESC);
 MODULE_LICENSE("GPL");
 
 /*
@@ -139,7 +141,7 @@
  * it as an input device.
  */
 
-static void warrior_connect(struct serio *serio, struct serio_dev *dev)
+static void warrior_connect(struct serio *serio, struct serio_driver *drv)
 {
 	struct warrior *warrior;
 	int i;
@@ -185,7 +187,7 @@
 
 	serio->private = warrior;
 
-	if (serio_open(serio, dev)) {
+	if (serio_open(serio, drv)) {
 		kfree(warrior);
 		return;
 	}
@@ -199,10 +201,14 @@
  * The serio device structure.
  */
 
-static struct serio_dev warrior_dev = {
-	.interrupt =	warrior_interrupt,
-	.connect =	warrior_connect,
-	.disconnect =	warrior_disconnect,
+static struct serio_driver warrior_drv = {
+	.driver		= {
+		.name	= "warrior",
+	},
+	.description	= DRIVER_DESC,
+	.interrupt	= warrior_interrupt,
+	.connect	= warrior_connect,
+	.disconnect	= warrior_disconnect,
 };
 
 /*
@@ -211,13 +217,13 @@
 
 int __init warrior_init(void)
 {
-	serio_register_device(&warrior_dev);
+	serio_register_driver(&warrior_drv);
 	return 0;
 }
 
 void __exit warrior_exit(void)
 {
-	serio_unregister_device(&warrior_dev);
+	serio_unregister_driver(&warrior_drv);
 }
 
 module_init(warrior_init);
diff -Nru a/drivers/input/keyboard/atkbd.c b/drivers/input/keyboard/atkbd.c
--- a/drivers/input/keyboard/atkbd.c	2004-10-18 14:56:49 -07:00
+++ b/drivers/input/keyboard/atkbd.c	2004-10-18 14:56:49 -07:00
@@ -27,8 +27,10 @@
 #include <linux/serio.h>
 #include <linux/workqueue.h>
 
+#define DRIVER_DESC	"AT and PS/2 keyboard driver"
+
 MODULE_AUTHOR("Vojtech Pavlik <vojtech@suse.cz>");
-MODULE_DESCRIPTION("AT and PS/2 keyboard driver");
+MODULE_DESCRIPTION(DRIVER_DESC);
 MODULE_LICENSE("GPL");
 
 static int atkbd_set = 2;
@@ -47,6 +49,10 @@
 module_param_named(softrepeat, atkbd_softrepeat, bool, 0);
 MODULE_PARM_DESC(softrepeat, "Use software keyboard repeat");
 
+static int atkbd_softraw = 1;
+module_param_named(softraw, atkbd_softraw, bool, 0);
+MODULE_PARM_DESC(softraw, "Use software generated rawmode");
+
 static int atkbd_scroll;
 module_param_named(scroll, atkbd_scroll, bool, 0);
 MODULE_PARM_DESC(scroll, "Enable scroll-wheel on MS Office and similar keyboards");
@@ -164,36 +170,64 @@
 	{ ATKBD_SCR_CLICK, 0x60 },
 };
 
+#define ATKBD_FLAG_ACK		0	/* Waiting for ACK/NAK */
+#define ATKBD_FLAG_CMD		1	/* Waiting for command to finish */
+#define ATKBD_FLAG_CMD1		2	/* First byte of command response */
+#define ATKBD_FLAG_ENABLED	3	/* Waining for init to finish */
+
 /*
  * The atkbd control structure
  */
 
 struct atkbd {
-	unsigned char keycode[512];
-	struct input_dev dev;
-	struct serio *serio;
 
+	/* Written only during init */
 	char name[64];
 	char phys[32];
-	unsigned short id;
+	struct serio *serio;
+	struct input_dev dev;
+
 	unsigned char set;
-	unsigned int translated:1;
-	unsigned int extra:1;
-	unsigned int write:1;
+	unsigned short id;
+	unsigned char keycode[512];
+	unsigned char translated;
+	unsigned char extra;
+	unsigned char write;
+
+	/* Protected by FLAG_ACK */
+	unsigned char nak;
 
+	/* Protected by FLAG_CMD */
 	unsigned char cmdbuf[4];
 	unsigned char cmdcnt;
-	volatile signed char ack;
-	unsigned char emul;
-	unsigned int resend:1;
-	unsigned int release:1;
-	unsigned int bat_xl:1;
-	unsigned int enabled:1;
 
+	/* Accessed only from interrupt */
+	unsigned char emul;
+	unsigned char resend;
+	unsigned char release;
+	unsigned char bat_xl;
 	unsigned int last;
 	unsigned long time;
+
+	/* Ensures that only one command is executing at a time */
+	struct semaphore cmd_sem;
+
+	/* Used to signal completion from interrupt handler */
+	wait_queue_head_t wait;
+
+	/* Flags */
+	unsigned long flags;
 };
 
+/* Work structure to schedule execution of a command */
+struct atkbd_work {
+	struct work_struct work;
+	struct atkbd *atkbd;
+	int command;
+	unsigned char param[0];
+};
+
+
 static void atkbd_report_key(struct input_dev *dev, struct pt_regs *regs, int code, int value)
 {
 	input_regs(dev, regs);
@@ -224,7 +258,7 @@
 
 #if !defined(__i386__) && !defined (__x86_64__)
 	if ((flags & (SERIO_FRAME | SERIO_PARITY)) && (~flags & SERIO_TIMEOUT) && !atkbd->resend && atkbd->write) {
-		printk("atkbd.c: frame/parity error: %02x\n", flags);
+		printk(KERN_WARNING "atkbd.c: frame/parity error: %02x\n", flags);
 		serio_write(serio, ATKBD_CMD_RESEND);
 		atkbd->resend = 1;
 		goto out;
@@ -234,24 +268,46 @@
 		atkbd->resend = 0;
 #endif
 
-	if (!atkbd->ack)
+	if (test_bit(ATKBD_FLAG_ACK, &atkbd->flags)) {
 		switch (code) {
 			case ATKBD_RET_ACK:
-				atkbd->ack = 1;
-				goto out;
+				atkbd->nak = 0;
+				if (atkbd->cmdcnt) {
+					set_bit(ATKBD_FLAG_CMD, &atkbd->flags);
+					set_bit(ATKBD_FLAG_CMD1, &atkbd->flags);
+				}
+				clear_bit(ATKBD_FLAG_ACK, &atkbd->flags);
+				wake_up_interruptible(&atkbd->wait);
+				break;
 			case ATKBD_RET_NAK:
-				atkbd->ack = -1;
-				goto out;
+				atkbd->nak = 1;
+				clear_bit(ATKBD_FLAG_ACK, &atkbd->flags);
+				wake_up_interruptible(&atkbd->wait);
+				break;
 		}
+		goto out;
+	}
+
+	if (test_bit(ATKBD_FLAG_CMD, &atkbd->flags)) {
+
+		if (atkbd->cmdcnt)
+			atkbd->cmdbuf[--atkbd->cmdcnt] = code;
 
-	if (atkbd->cmdcnt) {
-		atkbd->cmdbuf[--atkbd->cmdcnt] = code;
+		if (test_and_clear_bit(ATKBD_FLAG_CMD1, &atkbd->flags) && atkbd->cmdcnt)
+			wake_up_interruptible(&atkbd->wait);
+
+		if (!atkbd->cmdcnt) {
+			clear_bit(ATKBD_FLAG_CMD, &atkbd->flags);
+			wake_up_interruptible(&atkbd->wait);
+		}
 		goto out;
 	}
 
-	if (!atkbd->enabled)
+	if (!test_bit(ATKBD_FLAG_ENABLED, &atkbd->flags))
 		goto out;
 
+	input_event(&atkbd->dev, EV_MSC, MSC_RAW, code);
+
 	if (atkbd->translated) {
 
 		if (atkbd->emul ||
@@ -270,6 +326,7 @@
 
 	switch (code) {
 		case ATKBD_RET_BAT:
+			clear_bit(ATKBD_FLAG_ENABLED, &atkbd->flags);
 			serio_rescan(atkbd->serio);
 			goto out;
 		case ATKBD_RET_EMUL0:
@@ -300,6 +357,9 @@
 		code |= (atkbd->set != 3) ? 0x80 : 0x100;
 	}
 
+	if (atkbd->keycode[code] != ATKBD_KEY_NULL)
+		input_event(&atkbd->dev, EV_MSC, MSC_SCAN, code);
+
 	switch (atkbd->keycode[code]) {
 		case ATKBD_KEY_NULL:
 			break;
@@ -372,83 +432,147 @@
  * acknowledge. It doesn't handle resends according to the keyboard
  * protocol specs, because if these are needed, the keyboard needs
  * replacement anyway, and they only make a mess in the protocol.
+ *
+ * atkbd_sendbyte() can only be called from a process context
  */
 
 static int atkbd_sendbyte(struct atkbd *atkbd, unsigned char byte)
 {
-	int timeout = 20000; /* 200 msec */
-	atkbd->ack = 0;
-
 #ifdef ATKBD_DEBUG
 	printk(KERN_DEBUG "atkbd.c: Sent: %02x\n", byte);
 #endif
-	if (serio_write(atkbd->serio, byte))
-		return -1;
+	atkbd->nak = 1;
+	set_bit(ATKBD_FLAG_ACK, &atkbd->flags);
 
-	while (!atkbd->ack && timeout--) udelay(10);
+	if (serio_write(atkbd->serio, byte) == 0)
+		wait_event_interruptible_timeout(atkbd->wait,
+				!test_bit(ATKBD_FLAG_ACK, &atkbd->flags),
+				msecs_to_jiffies(200));
 
-	return -(atkbd->ack <= 0);
+	clear_bit(ATKBD_FLAG_ACK, &atkbd->flags);
+	return -atkbd->nak;
 }
 
 /*
  * atkbd_command() sends a command, and its parameters to the keyboard,
  * then waits for the response and puts it in the param array.
+ *
+ * atkbd_command() can only be called from a process context
  */
 
 static int atkbd_command(struct atkbd *atkbd, unsigned char *param, int command)
 {
-	int timeout = 500000; /* 500 msec */
+	int timeout;
 	int send = (command >> 12) & 0xf;
 	int receive = (command >> 8) & 0xf;
+	int rc = -1;
 	int i;
 
-	atkbd->cmdcnt = receive;
+	timeout = msecs_to_jiffies(command == ATKBD_CMD_RESET_BAT ? 4000 : 500);
 
-	if (command == ATKBD_CMD_RESET_BAT)
-		timeout = 2000000; /* 2 sec */
+	down(&atkbd->cmd_sem);
+	clear_bit(ATKBD_FLAG_CMD, &atkbd->flags);
 
 	if (receive && param)
 		for (i = 0; i < receive; i++)
 			atkbd->cmdbuf[(receive - 1) - i] = param[i];
 
+	atkbd->cmdcnt = receive;
+
 	if (command & 0xff)
 		if (atkbd_sendbyte(atkbd, command & 0xff))
-			return (atkbd->cmdcnt = 0) - 1;
+			goto out;
 
 	for (i = 0; i < send; i++)
 		if (atkbd_sendbyte(atkbd, param[i]))
-			return (atkbd->cmdcnt = 0) - 1;
-
-	while (atkbd->cmdcnt && timeout--) {
+			goto out;
 
-		if (atkbd->cmdcnt == 1 &&
-		    command == ATKBD_CMD_RESET_BAT && timeout > 100000)
-			timeout = 100000;
+	timeout = wait_event_interruptible_timeout(atkbd->wait,
+				!test_bit(ATKBD_FLAG_CMD1, &atkbd->flags), timeout);
 
-		if (atkbd->cmdcnt == 1 && command == ATKBD_CMD_GETID &&
-		    atkbd->cmdbuf[1] != 0xab && atkbd->cmdbuf[1] != 0xac) {
+	if (atkbd->cmdcnt && timeout > 0) {
+		if (command == ATKBD_CMD_RESET_BAT && jiffies_to_msecs(timeout) > 100)
+			timeout = msecs_to_jiffies(100);
+
+		if (command == ATKBD_CMD_GETID &&
+		    atkbd->cmdbuf[receive - 1] != 0xab && atkbd->cmdbuf[receive - 1] != 0xac) {
+			/*
+			 * Device behind the port is not a keyboard
+			 * so we don't need to wait for the 2nd byte
+			 * of ID response.
+			 */
+			clear_bit(ATKBD_FLAG_CMD, &atkbd->flags);
 			atkbd->cmdcnt = 0;
-			break;
 		}
 
-		udelay(1);
+		wait_event_interruptible_timeout(atkbd->wait,
+				!test_bit(ATKBD_FLAG_CMD, &atkbd->flags), timeout);
 	}
 
 	if (param)
 		for (i = 0; i < receive; i++)
 			param[i] = atkbd->cmdbuf[(receive - 1) - i];
 
-	if (command == ATKBD_CMD_RESET_BAT && atkbd->cmdcnt == 1)
-		atkbd->cmdcnt = 0;
+	if (atkbd->cmdcnt && (command != ATKBD_CMD_RESET_BAT || atkbd->cmdcnt != 1))
+		goto out;
+
+	rc = 0;
+
+out:
+	clear_bit(ATKBD_FLAG_CMD, &atkbd->flags);
+	clear_bit(ATKBD_FLAG_CMD1, &atkbd->flags);
+	up(&atkbd->cmd_sem);
+
+	return rc;
+}
+
+/*
+ * atkbd_execute_scheduled_command() sends a command, previously scheduled by
+ * atkbd_schedule_command(), to the keyboard.
+ */
+
+static void atkbd_execute_scheduled_command(void *data)
+{
+	struct atkbd_work *atkbd_work = data;
+
+	atkbd_command(atkbd_work->atkbd, atkbd_work->param, atkbd_work->command);
+
+	kfree(atkbd_work);
+}
+
+/*
+ * atkbd_schedule_command() allows to schedule delayed execution of a keyboard
+ * command and can be used to issue a command from an interrupt or softirq
+ * context.
+ */
+
+static int atkbd_schedule_command(struct atkbd *atkbd, unsigned char *param, int command)
+{
+	struct atkbd_work *atkbd_work;
+	int send = (command >> 12) & 0xf;
+	int receive = (command >> 8) & 0xf;
+
+	if (!test_bit(ATKBD_FLAG_ENABLED, &atkbd->flags))
+		return -1;
 
-	if (atkbd->cmdcnt) {
-		atkbd->cmdcnt = 0;
+	if (!(atkbd_work = kmalloc(sizeof(struct atkbd_work) + max(send, receive), GFP_ATOMIC)))
+		return -1;
+
+	memset(atkbd_work, 0, sizeof(struct atkbd_work));
+	atkbd_work->atkbd = atkbd;
+	atkbd_work->command = command;
+	memcpy(atkbd_work->param, param, send);
+	INIT_WORK(&atkbd_work->work, atkbd_execute_scheduled_command, atkbd_work);
+
+	if (!schedule_work(&atkbd_work->work)) {
+		kfree(atkbd_work);
 		return -1;
 	}
 
 	return 0;
 }
 
+
 /*
  * Event callback from the input module. Events that change the state of
  * the hardware are processed here.
@@ -475,7 +599,7 @@
 			param[0] = (test_bit(LED_SCROLLL, dev->led) ? 1 : 0)
 			         | (test_bit(LED_NUML,    dev->led) ? 2 : 0)
 			         | (test_bit(LED_CAPSL,   dev->led) ? 4 : 0);
-		        atkbd_command(atkbd, param, ATKBD_CMD_SETLEDS);
+		        atkbd_schedule_command(atkbd, param, ATKBD_CMD_SETLEDS);
 
 			if (atkbd->extra) {
 				param[0] = 0;
@@ -484,7 +608,7 @@
 					 | (test_bit(LED_SUSPEND, dev->led) ? 0x04 : 0)
 				         | (test_bit(LED_MISC,    dev->led) ? 0x10 : 0)
 				         | (test_bit(LED_MUTE,    dev->led) ? 0x20 : 0);
-				atkbd_command(atkbd, param, ATKBD_CMD_EX_SETLEDS);
+				atkbd_schedule_command(atkbd, param, ATKBD_CMD_EX_SETLEDS);
 			}
 
 			return 0;
@@ -500,7 +624,7 @@
 			dev->rep[REP_PERIOD] = period[i];
 			dev->rep[REP_DELAY] = delay[j];
 			param[0] = i | (j << 5);
-			atkbd_command(atkbd, param, ATKBD_CMD_SETREP);
+			atkbd_schedule_command(atkbd, param, ATKBD_CMD_SETREP);
 
 			return 0;
 	}
@@ -672,6 +796,11 @@
 static void atkbd_disconnect(struct serio *serio)
 {
 	struct atkbd *atkbd = serio->private;
+
+	clear_bit(ATKBD_FLAG_ENABLED, &atkbd->flags);
+	synchronize_kernel();
+	flush_scheduled_work();
+
 	input_unregister_device(&atkbd->dev);
 	serio_close(serio);
 	kfree(atkbd);
@@ -684,7 +813,7 @@
  * to the input module.
  */
 
-static void atkbd_connect(struct serio *serio, struct serio_dev *dev)
+static void atkbd_connect(struct serio *serio, struct serio_driver *drv)
 {
 	struct atkbd *atkbd;
 	int i;
@@ -693,6 +822,9 @@
 		return;
 	memset(atkbd, 0, sizeof(struct atkbd));
 
+	init_MUTEX(&atkbd->cmd_sem);
+	init_waitqueue_head(&atkbd->wait);
+
 	switch (serio->type & SERIO_TYPE) {
 
 		case SERIO_8042_XL:
@@ -709,17 +841,22 @@
 			return;
 	}
 
+	if (!atkbd->write)
+		atkbd_softrepeat = 1;
+	if (atkbd_softrepeat)
+		atkbd_softraw = 1;
+
 	if (atkbd->write) {
-		atkbd->dev.evbit[0] = BIT(EV_KEY) | BIT(EV_LED) | BIT(EV_REP);
+		atkbd->dev.evbit[0] = BIT(EV_KEY) | BIT(EV_LED) | BIT(EV_REP) | BIT(EV_MSC);
 		atkbd->dev.ledbit[0] = BIT(LED_NUML) | BIT(LED_CAPSL) | BIT(LED_SCROLLL);
-	} else  atkbd->dev.evbit[0] = BIT(EV_KEY) | BIT(EV_REP);
+	} else  atkbd->dev.evbit[0] = BIT(EV_KEY) | BIT(EV_REP) | BIT(EV_MSC);
+	atkbd->dev.mscbit[0] = atkbd_softraw ? BIT(MSC_SCAN) : BIT(MSC_RAW) | BIT(MSC_SCAN);
 
 	if (!atkbd_softrepeat) {
 		atkbd->dev.rep[REP_DELAY] = 250;
 		atkbd->dev.rep[REP_PERIOD] = 33;
-	}
+	} else atkbd_softraw = 1;
 
-	atkbd->ack = 1;
 	atkbd->serio = serio;
 
 	init_input_dev(&atkbd->dev);
@@ -732,7 +869,7 @@
 
 	serio->private = atkbd;
 
-	if (serio_open(serio, dev)) {
+	if (serio_open(serio, drv)) {
 		kfree(atkbd);
 		return;
 	}
@@ -754,8 +891,6 @@
 		atkbd->id = 0xab00;
 	}
 
-	atkbd->enabled = 1;
-
 	if (atkbd->extra) {
 		atkbd->dev.ledbit[0] |= BIT(LED_COMPOSE) | BIT(LED_SUSPEND) | BIT(LED_SLEEP) | BIT(LED_MUTE) | BIT(LED_MISC);
 		sprintf(atkbd->name, "AT Set 2 Extra keyboard");
@@ -797,6 +932,8 @@
 
 	input_register_device(&atkbd->dev);
 
+	set_bit(ATKBD_FLAG_ENABLED, &atkbd->flags);
+
 	printk(KERN_INFO "input: %s on %s\n", atkbd->name, serio->phys);
 }
 
@@ -808,10 +945,10 @@
 static int atkbd_reconnect(struct serio *serio)
 {
 	struct atkbd *atkbd = serio->private;
-	struct serio_dev *dev = serio->dev;
+	struct serio_driver *drv = serio->drv;
 	unsigned char param[1];
 
-	if (!dev) {
+	if (!drv) {
 		printk(KERN_DEBUG "atkbd: reconnect request, but serio is disconnected, ignoring...\n");
 		return -1;
 	}
@@ -832,26 +969,32 @@
 			return -1;
 	}
 
+	set_bit(ATKBD_FLAG_ENABLED, &atkbd->flags);
+
 	return 0;
 }
 
-static struct serio_dev atkbd_dev = {
-	.interrupt =	atkbd_interrupt,
-	.connect =	atkbd_connect,
-	.reconnect = 	atkbd_reconnect,
-	.disconnect =	atkbd_disconnect,
-	.cleanup =	atkbd_cleanup,
+static struct serio_driver atkbd_drv = {
+	.driver		= {
+		.name	= "atkbd",
+	},
+	.description	= DRIVER_DESC,
+	.interrupt	= atkbd_interrupt,
+	.connect	= atkbd_connect,
+	.reconnect	= atkbd_reconnect,
+	.disconnect	= atkbd_disconnect,
+	.cleanup	= atkbd_cleanup,
 };
 
 int __init atkbd_init(void)
 {
-	serio_register_device(&atkbd_dev);
+	serio_register_driver(&atkbd_drv);
 	return 0;
 }
 
 void __exit atkbd_exit(void)
 {
-	serio_unregister_device(&atkbd_dev);
+	serio_unregister_driver(&atkbd_drv);
 }
 
 module_init(atkbd_init);
diff -Nru a/drivers/input/keyboard/lkkbd.c b/drivers/input/keyboard/lkkbd.c
--- a/drivers/input/keyboard/lkkbd.c	2004-10-18 14:56:16 -07:00
+++ b/drivers/input/keyboard/lkkbd.c	2004-10-18 14:56:16 -07:00
@@ -76,8 +76,10 @@
 #include <linux/serio.h>
 #include <linux/workqueue.h>
 
+#define DRIVER_DESC	"LK keyboard driver"
+
 MODULE_AUTHOR ("Jan-Benedict Glaw <jbglaw@lug-owl.de>");
-MODULE_DESCRIPTION ("LK keyboard driver");
+MODULE_DESCRIPTION (DRIVER_DESC);
 MODULE_LICENSE ("GPL");
 
 /*
@@ -622,7 +624,7 @@
  * lkkbd_connect() probes for a LK keyboard and fills the necessary structures.
  */
 static void
-lkkbd_connect (struct serio *serio, struct serio_dev *dev)
+lkkbd_connect (struct serio *serio, struct serio_driver *drv)
 {
 	struct lkkbd *lk;
 	int i;
@@ -665,7 +667,7 @@
 
 	serio->private = lk;
 
-	if (serio_open (serio, dev)) {
+	if (serio_open (serio, drv)) {
 		kfree (lk);
 		return;
 	}
@@ -703,10 +705,14 @@
 	kfree (lk);
 }
 
-static struct serio_dev lkkbd_dev = {
-	.connect = lkkbd_connect,
-	.disconnect = lkkbd_disconnect,
-	.interrupt = lkkbd_interrupt,
+static struct serio_driver lkkbd_drv = {
+	.driver		= {
+		.name	= "lkkbd",
+	},
+	.description	= DRIVER_DESC,
+	.connect	= lkkbd_connect,
+	.disconnect	= lkkbd_disconnect,
+	.interrupt	= lkkbd_interrupt,
 };
 
 /*
@@ -715,14 +721,14 @@
 int __init
 lkkbd_init (void)
 {
-	serio_register_device (&lkkbd_dev);
+	serio_register_driver(&lkkbd_drv);
 	return 0;
 }
 
 void __exit
 lkkbd_exit (void)
 {
-	serio_unregister_device (&lkkbd_dev);
+	serio_unregister_driver(&lkkbd_drv);
 }
 
 module_init (lkkbd_init);
diff -Nru a/drivers/input/keyboard/newtonkbd.c b/drivers/input/keyboard/newtonkbd.c
--- a/drivers/input/keyboard/newtonkbd.c	2004-10-18 14:55:53 -07:00
+++ b/drivers/input/keyboard/newtonkbd.c	2004-10-18 14:55:53 -07:00
@@ -32,8 +32,10 @@
 #include <linux/init.h>
 #include <linux/serio.h>
 
+#define DRIVER_DESC	"Newton keyboard driver"
+
 MODULE_AUTHOR("Justin Cormack <j.cormack@doc.ic.ac.uk>");
-MODULE_DESCRIPTION("Newton keyboard driver");
+MODULE_DESCRIPTION(DRIVER_DESC);
 MODULE_LICENSE("GPL");
 
 #define NKBD_KEY	0x7f
@@ -82,7 +84,7 @@
 
 }
 
-void nkbd_connect(struct serio *serio, struct serio_dev *dev)
+void nkbd_connect(struct serio *serio, struct serio_driver *drv)
 {
 	struct nkbd *nkbd;
 	int i;
@@ -106,7 +108,7 @@
 	nkbd->dev.private = nkbd;
 	serio->private = nkbd;
 
-	if (serio_open(serio, dev)) {
+	if (serio_open(serio, drv)) {
 		kfree(nkbd);
 		return;
 	}
@@ -138,21 +140,25 @@
 	kfree(nkbd);
 }
 
-struct serio_dev nkbd_dev = {
-	.interrupt =	nkbd_interrupt,
-	.connect =	nkbd_connect,
-	.disconnect =	nkbd_disconnect
+struct serio_driver nkbd_drv = {
+	.driver		= {
+		.name	= "newtonkbd",
+	},
+	.description	= DRIVER_DESC,
+	.interrupt	= nkbd_interrupt,
+	.connect	= nkbd_connect,
+	.disconnect	= nkbd_disconnect,
 };
 
 int __init nkbd_init(void)
 {
-	serio_register_device(&nkbd_dev);
+	serio_register_driver(&nkbd_drv);
 	return 0;
 }
 
 void __exit nkbd_exit(void)
 {
-	serio_unregister_device(&nkbd_dev);
+	serio_unregister_driver(&nkbd_drv);
 }
 
 module_init(nkbd_init);
diff -Nru a/drivers/input/keyboard/sunkbd.c b/drivers/input/keyboard/sunkbd.c
--- a/drivers/input/keyboard/sunkbd.c	2004-10-18 14:55:53 -07:00
+++ b/drivers/input/keyboard/sunkbd.c	2004-10-18 14:55:53 -07:00
@@ -37,8 +37,10 @@
 #include <linux/serio.h>
 #include <linux/workqueue.h>
 
+#define DRIVER_DESC	"Sun keyboard driver"
+
 MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>");
-MODULE_DESCRIPTION("Sun keyboard driver");
+MODULE_DESCRIPTION(DRIVER_DESC);
 MODULE_LICENSE("GPL");
 
 static unsigned char sunkbd_keycode[128] = {
@@ -221,7 +223,7 @@
  * sunkbd_connect() probes for a Sun keyboard and fills the necessary structures.
  */
 
-static void sunkbd_connect(struct serio *serio, struct serio_dev *dev)
+static void sunkbd_connect(struct serio *serio, struct serio_driver *drv)
 {
 	struct sunkbd *sunkbd;
 	int i;
@@ -257,7 +259,7 @@
 
 	serio->private = sunkbd;
 
-	if (serio_open(serio, dev)) {
+	if (serio_open(serio, drv)) {
 		kfree(sunkbd);
 		return;
 	}
@@ -301,10 +303,14 @@
 	kfree(sunkbd);
 }
 
-static struct serio_dev sunkbd_dev = {
-	.interrupt =	sunkbd_interrupt,
-	.connect =	sunkbd_connect,
-	.disconnect =	sunkbd_disconnect
+static struct serio_driver sunkbd_drv = {
+	.driver		= {
+		.name	= "sunkbd",
+	},
+	.description	= DRIVER_DESC,
+	.interrupt	= sunkbd_interrupt,
+	.connect	= sunkbd_connect,
+	.disconnect	= sunkbd_disconnect,
 };
 
 /*
@@ -313,13 +319,13 @@
 
 int __init sunkbd_init(void)
 {
-	serio_register_device(&sunkbd_dev);
+	serio_register_driver(&sunkbd_drv);
 	return 0;
 }
 
 void __exit sunkbd_exit(void)
 {
-	serio_unregister_device(&sunkbd_dev);
+	serio_unregister_driver(&sunkbd_drv);
 }
 
 module_init(sunkbd_init);
diff -Nru a/drivers/input/keyboard/xtkbd.c b/drivers/input/keyboard/xtkbd.c
--- a/drivers/input/keyboard/xtkbd.c	2004-10-18 14:56:32 -07:00
+++ b/drivers/input/keyboard/xtkbd.c	2004-10-18 14:56:32 -07:00
@@ -34,8 +34,10 @@
 #include <linux/init.h>
 #include <linux/serio.h>
 
+#define DRIVER_DESC	"XT keyboard driver"
+
 MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>");
-MODULE_DESCRIPTION("XT keyboard driver");
+MODULE_DESCRIPTION(DRIVER_DESC);
 MODULE_LICENSE("GPL");
 
 #define XTKBD_EMUL0	0xe0
@@ -86,7 +88,7 @@
 	return IRQ_HANDLED;
 }
 
-void xtkbd_connect(struct serio *serio, struct serio_dev *dev)
+void xtkbd_connect(struct serio *serio, struct serio_driver *drv)
 {
 	struct xtkbd *xtkbd;
 	int i;
@@ -111,7 +113,7 @@
 
 	serio->private = xtkbd;
 
-	if (serio_open(serio, dev)) {
+	if (serio_open(serio, drv)) {
 		kfree(xtkbd);
 		return;
 	}
@@ -143,21 +145,25 @@
 	kfree(xtkbd);
 }
 
-struct serio_dev xtkbd_dev = {
-	.interrupt =	xtkbd_interrupt,
-	.connect =	xtkbd_connect,
-	.disconnect =	xtkbd_disconnect
+struct serio_driver xtkbd_drv = {
+	.driver		= {
+		.name	= "xtkbd",
+	},
+	.description	= DRIVER_DESC,
+	.interrupt	= xtkbd_interrupt,
+	.connect	= xtkbd_connect,
+	.disconnect	= xtkbd_disconnect,
 };
 
 int __init xtkbd_init(void)
 {
-	serio_register_device(&xtkbd_dev);
+	serio_register_driver(&xtkbd_drv);
 	return 0;
 }
 
 void __exit xtkbd_exit(void)
 {
-	serio_unregister_device(&xtkbd_dev);
+	serio_unregister_driver(&xtkbd_drv);
 }
 
 module_init(xtkbd_init);
diff -Nru a/drivers/input/misc/Kconfig b/drivers/input/misc/Kconfig
--- a/drivers/input/misc/Kconfig	2004-10-18 14:56:29 -07:00
+++ b/drivers/input/misc/Kconfig	2004-10-18 14:56:29 -07:00
@@ -14,7 +14,7 @@
 
 config INPUT_PCSPKR
 	tristate "PC Speaker support"
-	depends on (ALPHA || X86 || X86_64 || MIPS) && INPUT && INPUT_MISC
+	depends on (ALPHA || X86 || X86_64 || MIPS || PPC_PREP || PPC_CHRP || PPC_PSERIES) && INPUT && INPUT_MISC
 	help
 	  Say Y here if you want the standard PC Speaker to be used for
 	  bells and whistles.
diff -Nru a/drivers/input/misc/uinput.c b/drivers/input/misc/uinput.c
--- a/drivers/input/misc/uinput.c	2004-10-18 14:56:50 -07:00
+++ b/drivers/input/misc/uinput.c	2004-10-18 14:56:50 -07:00
@@ -279,6 +279,9 @@
 {
 	struct uinput_device *udev = file->private_data;
 
+	if (!test_bit(UIST_CREATED, &(udev->state)))
+		return 0;
+
 	poll_wait(file, &udev->waitq, wait);
 
 	if (udev->head != udev->tail)
diff -Nru a/drivers/input/mouse/Kconfig b/drivers/input/mouse/Kconfig
--- a/drivers/input/mouse/Kconfig	2004-10-18 14:56:49 -07:00
+++ b/drivers/input/mouse/Kconfig	2004-10-18 14:56:49 -07:00
@@ -30,8 +30,6 @@
 	  and a new verion of GPM at:
 		http://www.geocities.com/dt_or/gpm/gpm.html
 	  to take advantage of the advanced features of the touchpad.
-	  If you do not want install specialized drivers but want tapping
-	  working please use option psmouse.proto=imps.
 
 	  If unsure, say Y.
 
diff -Nru a/drivers/input/mouse/logips2pp.c b/drivers/input/mouse/logips2pp.c
--- a/drivers/input/mouse/logips2pp.c	2004-10-18 14:56:33 -07:00
+++ b/drivers/input/mouse/logips2pp.c	2004-10-18 14:56:33 -07:00
@@ -277,7 +277,7 @@
 				protocol = PSMOUSE_PS2TPP;
 			}
 
-		} else if (get_model_info(model) != NULL) {
+		} else if (model_info != NULL) {
 
 			param[0] = param[1] = param[2] = 0;
 			ps2pp_cmd(psmouse, param, 0x39); /* Magic knock */
diff -Nru a/drivers/input/mouse/pc110pad.c b/drivers/input/mouse/pc110pad.c
--- a/drivers/input/mouse/pc110pad.c	2004-10-18 14:56:28 -07:00
+++ b/drivers/input/mouse/pc110pad.c	2004-10-18 14:56:28 -07:00
@@ -109,9 +109,9 @@
 
 static int __init pc110pad_init(void)
 {
-	if (request_region(pc110pad_io, 4, "pc110pad"))
-	{
-		printk(KERN_ERR "pc110pad: I/O area %#x-%#x in use.\n", pc110pad_io, pc110pad_io + 4);
+	if (!request_region(pc110pad_io, 4, "pc110pad")) {
+		printk(KERN_ERR "pc110pad: I/O area %#x-%#x in use.\n",
+				pc110pad_io, pc110pad_io + 4);
 		return -EBUSY;
 	}
 
diff -Nru a/drivers/input/mouse/psmouse-base.c b/drivers/input/mouse/psmouse-base.c
--- a/drivers/input/mouse/psmouse-base.c	2004-10-18 14:56:19 -07:00
+++ b/drivers/input/mouse/psmouse-base.c	2004-10-18 14:56:19 -07:00
@@ -22,8 +22,10 @@
 #include "synaptics.h"
 #include "logips2pp.h"
 
+#define DRIVER_DESC	"PS/2 mouse driver"
+
 MODULE_AUTHOR("Vojtech Pavlik <vojtech@suse.cz>");
-MODULE_DESCRIPTION("PS/2 mouse driver");
+MODULE_DESCRIPTION(DRIVER_DESC);
 MODULE_LICENSE("GPL");
 
 static char *psmouse_proto;
@@ -142,37 +144,67 @@
 			printk(KERN_WARNING "psmouse.c: bad data from KBC -%s%s\n",
 				flags & SERIO_TIMEOUT ? " timeout" : "",
 				flags & SERIO_PARITY ? " bad parity" : "");
-		if (psmouse->acking) {
-			psmouse->ack = -1;
-			psmouse->acking = 0;
-		}
-		psmouse->pktcnt = 0;
+		psmouse->nak = 1;
+		clear_bit(PSMOUSE_FLAG_ACK, &psmouse->flags);
+		clear_bit(PSMOUSE_FLAG_CMD,  &psmouse->flags);
+		wake_up_interruptible(&psmouse->wait);
 		goto out;
 	}
 
-	if (psmouse->acking) {
+	if (test_bit(PSMOUSE_FLAG_ACK, &psmouse->flags)) {
 		switch (data) {
 			case PSMOUSE_RET_ACK:
-				psmouse->ack = 1;
+				psmouse->nak = 0;
 				break;
+
 			case PSMOUSE_RET_NAK:
-				psmouse->ack = -1;
+				psmouse->nak = 1;
 				break;
+
+			/*
+			 * Workaround for mice which don't ACK the Get ID command.
+			 * These are valid mouse IDs that we recognize.
+			 */
+			case 0x00:
+			case 0x03:
+			case 0x04:
+				if (test_bit(PSMOUSE_FLAG_WAITID, &psmouse->flags)) {
+					psmouse->nak = 0;
+					break;
+				}
+				/* Fall through */
 			default:
-				psmouse->ack = 1;	/* Workaround for mice which don't ACK the Get ID command */
-				if (psmouse->cmdcnt)
-					psmouse->cmdbuf[--psmouse->cmdcnt] = data;
-				break;
+				goto out;
 		}
-		psmouse->acking = 0;
-		goto out;
+
+		if (!psmouse->nak && psmouse->cmdcnt) {
+			set_bit(PSMOUSE_FLAG_CMD, &psmouse->flags);
+			set_bit(PSMOUSE_FLAG_CMD1, &psmouse->flags);
+		}
+		clear_bit(PSMOUSE_FLAG_ACK, &psmouse->flags);
+		wake_up_interruptible(&psmouse->wait);
+
+		if (data == PSMOUSE_RET_ACK || data == PSMOUSE_RET_NAK)
+			goto out;
 	}
 
-	if (psmouse->cmdcnt) {
-		psmouse->cmdbuf[--psmouse->cmdcnt] = data;
+	if (test_bit(PSMOUSE_FLAG_CMD, &psmouse->flags)) {
+		if (psmouse->cmdcnt)
+			psmouse->cmdbuf[--psmouse->cmdcnt] = data;
+
+		if (test_and_clear_bit(PSMOUSE_FLAG_CMD1, &psmouse->flags) && psmouse->cmdcnt)
+			wake_up_interruptible(&psmouse->wait);
+
+		if (!psmouse->cmdcnt) {
+			clear_bit(PSMOUSE_FLAG_CMD, &psmouse->flags);
+			wake_up_interruptible(&psmouse->wait);
+		}
 		goto out;
 	}
 
+	if (psmouse->state == PSMOUSE_INITIALIZING)
+		goto out;
+
 	if (psmouse->state == PSMOUSE_ACTIVATED &&
 	    psmouse->pktcnt && time_after(jiffies, psmouse->last + HZ/2)) {
 		printk(KERN_WARNING "psmouse.c: %s at %s lost synchronization, throwing %d bytes away.\n",
@@ -238,78 +270,96 @@
  * psmouse_sendbyte() sends a byte to the mouse, and waits for acknowledge.
  * It doesn't handle retransmission, though it could - because when there would
  * be need for retransmissions, the mouse has to be replaced anyway.
+ *
+ * psmouse_sendbyte() can only be called from a process context
  */
 
 static int psmouse_sendbyte(struct psmouse *psmouse, unsigned char byte)
 {
-	int timeout = 10000; /* 100 msec */
-	psmouse->ack = 0;
-	psmouse->acking = 1;
-
-	if (serio_write(psmouse->serio, byte)) {
-		psmouse->acking = 0;
-		return -1;
-	}
+	psmouse->nak = 1;
+	set_bit(PSMOUSE_FLAG_ACK, &psmouse->flags);
 
-	while (!psmouse->ack && timeout--) udelay(10);
+	if (serio_write(psmouse->serio, byte) == 0)
+		wait_event_interruptible_timeout(psmouse->wait,
+				!test_bit(PSMOUSE_FLAG_ACK, &psmouse->flags),
+				msecs_to_jiffies(200));
 
-	return -(psmouse->ack <= 0);
+	clear_bit(PSMOUSE_FLAG_ACK, &psmouse->flags);
+	return -psmouse->nak;
 }
 
 /*
  * psmouse_command() sends a command and its parameters to the mouse,
  * then waits for the response and puts it in the param array.
+ *
+ * psmouse_command() can only be called from a process context
  */
 
 int psmouse_command(struct psmouse *psmouse, unsigned char *param, int command)
 {
-	int timeout = 500000; /* 500 msec */
+	int timeout;
 	int send = (command >> 12) & 0xf;
 	int receive = (command >> 8) & 0xf;
+	int rc = -1;
 	int i;
 
-	psmouse->cmdcnt = receive;
+	timeout = msecs_to_jiffies(command == PSMOUSE_CMD_RESET_BAT ? 4000 : 500);
 
-	if (command == PSMOUSE_CMD_RESET_BAT)
-                timeout = 4000000; /* 4 sec */
+	clear_bit(PSMOUSE_FLAG_CMD, &psmouse->flags);
+	if (command == PSMOUSE_CMD_GETID)
+		set_bit(PSMOUSE_FLAG_WAITID, &psmouse->flags);
+
+	if (receive && param)
+		for (i = 0; i < receive; i++)
+			psmouse->cmdbuf[(receive - 1) - i] = param[i];
 
-	/* initialize cmdbuf with preset values from param */
-	if (receive)
-	   for (i = 0; i < receive; i++)
-		psmouse->cmdbuf[(receive - 1) - i] = param[i];
+	psmouse->cmdcnt = receive;
 
 	if (command & 0xff)
 		if (psmouse_sendbyte(psmouse, command & 0xff))
-			return (psmouse->cmdcnt = 0) - 1;
+			goto out;
 
 	for (i = 0; i < send; i++)
 		if (psmouse_sendbyte(psmouse, param[i]))
-			return (psmouse->cmdcnt = 0) - 1;
-
-	while (psmouse->cmdcnt && timeout--) {
+			goto out;
 
-		if (psmouse->cmdcnt == 1 && command == PSMOUSE_CMD_RESET_BAT &&
-				timeout > 100000) /* do not run in a endless loop */
-			timeout = 100000; /* 1 sec */
+	timeout = wait_event_interruptible_timeout(psmouse->wait,
+				!test_bit(PSMOUSE_FLAG_CMD1, &psmouse->flags), timeout);
 
-		if (psmouse->cmdcnt == 1 && command == PSMOUSE_CMD_GETID &&
-		    psmouse->cmdbuf[1] != 0xab && psmouse->cmdbuf[1] != 0xac) {
+	if (psmouse->cmdcnt && timeout > 0) {
+		if (command == PSMOUSE_CMD_RESET_BAT && jiffies_to_msecs(timeout) > 100)
+			timeout = msecs_to_jiffies(100);
+
+		if (command == PSMOUSE_CMD_GETID &&
+		    psmouse->cmdbuf[receive - 1] != 0xab && psmouse->cmdbuf[receive - 1] != 0xac) {
+			/*
+			 * Device behind the port is not a keyboard
+			 * so we don't need to wait for the 2nd byte
+			 * of ID response.
+			 */
+			clear_bit(PSMOUSE_FLAG_CMD, &psmouse->flags);
 			psmouse->cmdcnt = 0;
-			break;
 		}
 
-		udelay(1);
+		wait_event_interruptible_timeout(psmouse->wait,
+				!test_bit(PSMOUSE_FLAG_CMD, &psmouse->flags), timeout);
 	}
 
-	for (i = 0; i < receive; i++)
-		param[i] = psmouse->cmdbuf[(receive - 1) - i];
+	if (param)
+		for (i = 0; i < receive; i++)
+			param[i] = psmouse->cmdbuf[(receive - 1) - i];
 
-	if (psmouse->cmdcnt)
-		return (psmouse->cmdcnt = 0) - 1;
+	if (psmouse->cmdcnt && (command != PSMOUSE_CMD_RESET_BAT || psmouse->cmdcnt != 1))
+		goto out;
 
-	return 0;
-}
+	rc = 0;
 
+out:
+	clear_bit(PSMOUSE_FLAG_CMD, &psmouse->flags);
+	clear_bit(PSMOUSE_FLAG_CMD1, &psmouse->flags);
+	clear_bit(PSMOUSE_FLAG_WAITID, &psmouse->flags);
+	return rc;
+}
 
 /*
  * psmouse_sliced_command() sends an extended PS/2 command to the mouse
@@ -394,6 +444,8 @@
 {
 	unsigned char param[2];
 
+	intellimouse_detect(psmouse);
+
 	param[0] = 200;
 	psmouse_command(psmouse, param, PSMOUSE_CMD_SETRATE);
 	param[0] = 200;
@@ -598,6 +650,21 @@
 }
 
 /*
+ * psmouse_set_state() sets new psmouse state and resets all flags and
+ * counters while holding serio lock so fighting with interrupt handler
+ * is not a concern.
+ */
+
+static void psmouse_set_state(struct psmouse *psmouse, enum psmouse_state new_state)
+{
+	serio_pause_rx(psmouse->serio);
+	psmouse->state = new_state;
+	psmouse->pktcnt = psmouse->cmdcnt = psmouse->out_of_sync = 0;
+	psmouse->flags = 0;
+	serio_continue_rx(psmouse->serio);
+}
+
+/*
  * psmouse_activate() enables the mouse so that we get motion reports from it.
  */
 
@@ -606,9 +673,24 @@
 	if (psmouse_command(psmouse, NULL, PSMOUSE_CMD_ENABLE))
 		printk(KERN_WARNING "psmouse.c: Failed to enable mouse on %s\n", psmouse->serio->phys);
 
-	psmouse->state = PSMOUSE_ACTIVATED;
+	psmouse_set_state(psmouse, PSMOUSE_ACTIVATED);
 }
 
+
+/*
+ * psmouse_deactivate() puts the mouse into poll mode so that we don't get motion
+ * reports from it unless we explicitely request it.
+ */
+
+static void psmouse_deactivate(struct psmouse *psmouse)
+{
+	if (psmouse_command(psmouse, NULL, PSMOUSE_CMD_DISABLE))
+		printk(KERN_WARNING "psmouse.c: Failed to deactivate mouse on %s\n", psmouse->serio->phys);
+
+	psmouse_set_state(psmouse, PSMOUSE_CMD_MODE);
+}
+
+
 /*
  * psmouse_cleanup() resets the mouse into power-on state.
  */
@@ -626,22 +708,21 @@
 
 static void psmouse_disconnect(struct serio *serio)
 {
-	struct psmouse *psmouse = serio->private;
+	struct psmouse *psmouse, *parent;
 
-	psmouse->state = PSMOUSE_CMD_MODE;
+	psmouse = serio->private;
+	psmouse_set_state(psmouse, PSMOUSE_CMD_MODE);
 
-	if (psmouse->ptport) {
-		if (psmouse->ptport->deactivate)
-			psmouse->ptport->deactivate(psmouse);
-		__serio_unregister_port(&psmouse->ptport->serio); /* we have serio_sem */
-		kfree(psmouse->ptport);
-		psmouse->ptport = NULL;
+	if (serio->parent && (serio->type & SERIO_TYPE) == SERIO_PS_PSTHRU) {
+		parent = serio->parent->private;
+		if (parent->pt_deactivate)
+			parent->pt_deactivate(parent);
 	}
 
 	if (psmouse->disconnect)
 		psmouse->disconnect(psmouse);
 
-	psmouse->state = PSMOUSE_IGNORE;
+	psmouse_set_state(psmouse, PSMOUSE_IGNORE);
 
 	input_unregister_device(&psmouse->dev);
 	serio_close(serio);
@@ -652,39 +733,49 @@
  * psmouse_connect() is a callback from the serio module when
  * an unhandled serio port is found.
  */
-static void psmouse_connect(struct serio *serio, struct serio_dev *dev)
+static void psmouse_connect(struct serio *serio, struct serio_driver *drv)
 {
-	struct psmouse *psmouse;
+	struct psmouse *psmouse, *parent = NULL;
 
 	if ((serio->type & SERIO_TYPE) != SERIO_8042 &&
 	    (serio->type & SERIO_TYPE) != SERIO_PS_PSTHRU)
 		return;
 
+	/*
+	 * If this is a pass-through port deactivate parent so the device
+	 * connected to this port can be successfully identified
+	 */
+	if (serio->parent && (serio->type & SERIO_TYPE) == SERIO_PS_PSTHRU) {
+		parent = serio->parent->private;
+		psmouse_deactivate(parent);
+	}
+
 	if (!(psmouse = kmalloc(sizeof(struct psmouse), GFP_KERNEL)))
-		return;
+		goto out;
 
 	memset(psmouse, 0, sizeof(struct psmouse));
 
+	init_waitqueue_head(&psmouse->wait);
 	init_input_dev(&psmouse->dev);
 	psmouse->dev.evbit[0] = BIT(EV_KEY) | BIT(EV_REL);
 	psmouse->dev.keybit[LONG(BTN_MOUSE)] = BIT(BTN_LEFT) | BIT(BTN_MIDDLE) | BIT(BTN_RIGHT);
 	psmouse->dev.relbit[0] = BIT(REL_X) | BIT(REL_Y);
-	psmouse->state = PSMOUSE_CMD_MODE;
 	psmouse->serio = serio;
 	psmouse->dev.private = psmouse;
+	psmouse_set_state(psmouse, PSMOUSE_INITIALIZING);
 
 	serio->private = psmouse;
-	if (serio_open(serio, dev)) {
+	if (serio_open(serio, drv)) {
 		kfree(psmouse);
 		serio->private = NULL;
-		return;
+		goto out;
 	}
 
 	if (psmouse_probe(psmouse) < 0) {
 		serio_close(serio);
 		kfree(psmouse);
 		serio->private = NULL;
-		return;
+		goto out;
 	}
 
 	psmouse->type = psmouse_extensions(psmouse, psmouse_max_proto, 1);
@@ -711,63 +802,88 @@
 
 	printk(KERN_INFO "input: %s on %s\n", psmouse->devname, serio->phys);
 
+	psmouse_set_state(psmouse, PSMOUSE_CMD_MODE);
+
 	psmouse_initialize(psmouse);
 
-	if (psmouse->ptport) {
-		printk(KERN_INFO "serio: %s port at %s\n", psmouse->ptport->serio.name, psmouse->phys);
-		__serio_register_port(&psmouse->ptport->serio); /* we have serio_sem */
-		if (psmouse->ptport->activate)
-			psmouse->ptport->activate(psmouse);
+	if (parent && parent->pt_activate)
+		parent->pt_activate(parent);
+
+	if (serio->child) {
+		/*
+		 * Nothing to be done here, serio core will detect that
+		 * the driver set serio->child and will register it for us.
+		 */
+		printk(KERN_INFO "serio: %s port at %s\n", serio->child->name, psmouse->phys);
 	}
 
 	psmouse_activate(psmouse);
+
+out:
+	/* If this is a pass-through port the parent awaits to be activated */
+	if (parent)
+		psmouse_activate(parent);
 }
 
 
 static int psmouse_reconnect(struct serio *serio)
 {
 	struct psmouse *psmouse = serio->private;
-	struct serio_dev *dev = serio->dev;
+	struct psmouse *parent = NULL;
+	struct serio_driver *drv = serio->drv;
+	int rc = -1;
 
-	if (!dev || !psmouse) {
+	if (!drv || !psmouse) {
 		printk(KERN_DEBUG "psmouse: reconnect request, but serio is disconnected, ignoring...\n");
 		return -1;
 	}
 
-	psmouse->state = PSMOUSE_CMD_MODE;
-	psmouse->acking = psmouse->cmdcnt = psmouse->pktcnt = psmouse->out_of_sync = 0;
+	if (serio->parent && (serio->type & SERIO_TYPE) == SERIO_PS_PSTHRU) {
+		parent = serio->parent->private;
+		psmouse_deactivate(parent);
+	}
+
+	psmouse_set_state(psmouse, PSMOUSE_INITIALIZING);
+
 	if (psmouse->reconnect) {
 	       if (psmouse->reconnect(psmouse))
-			return -1;
+			goto out;
 	} else if (psmouse_probe(psmouse) < 0 ||
 		   psmouse->type != psmouse_extensions(psmouse, psmouse_max_proto, 0))
-		return -1;
+		goto out;
 
 	/* ok, the device type (and capabilities) match the old one,
 	 * we can continue using it, complete intialization
 	 */
+	psmouse_set_state(psmouse, PSMOUSE_CMD_MODE);
+
 	psmouse_initialize(psmouse);
 
-	if (psmouse->ptport) {
-       		if (psmouse_reconnect(&psmouse->ptport->serio)) {
-			__serio_unregister_port(&psmouse->ptport->serio);
-			__serio_register_port(&psmouse->ptport->serio);
-			if (psmouse->ptport->activate)
-				psmouse->ptport->activate(psmouse);
-		}
-	}
+	if (parent && parent->pt_activate)
+		parent->pt_activate(parent);
 
 	psmouse_activate(psmouse);
-	return 0;
+	rc = 0;
+
+out:
+	/* If this is a pass-through port the parent waits to be activated */
+	if (parent)
+		psmouse_activate(parent);
+
+	return rc;
 }
 
 
-static struct serio_dev psmouse_dev = {
-	.interrupt =	psmouse_interrupt,
-	.connect =	psmouse_connect,
-	.reconnect =	psmouse_reconnect,
-	.disconnect =	psmouse_disconnect,
-	.cleanup =	psmouse_cleanup,
+static struct serio_driver psmouse_drv = {
+	.driver		= {
+		.name	= "psmouse",
+	},
+	.description	= DRIVER_DESC,
+	.interrupt	= psmouse_interrupt,
+	.connect	= psmouse_connect,
+	.reconnect	= psmouse_reconnect,
+	.disconnect	= psmouse_disconnect,
+	.cleanup	= psmouse_cleanup,
 };
 
 static inline void psmouse_parse_proto(void)
@@ -787,13 +903,13 @@
 int __init psmouse_init(void)
 {
 	psmouse_parse_proto();
-	serio_register_device(&psmouse_dev);
+	serio_register_driver(&psmouse_drv);
 	return 0;
 }
 
 void __exit psmouse_exit(void)
 {
-	serio_unregister_device(&psmouse_dev);
+	serio_unregister_driver(&psmouse_drv);
 }
 
 module_init(psmouse_init);
diff -Nru a/drivers/input/mouse/psmouse.h b/drivers/input/mouse/psmouse.h
--- a/drivers/input/mouse/psmouse.h	2004-10-18 14:57:03 -07:00
+++ b/drivers/input/mouse/psmouse.h	2004-10-18 14:57:03 -07:00
@@ -9,6 +9,7 @@
 #define PSMOUSE_CMD_GETID	0x02f2
 #define PSMOUSE_CMD_SETRATE	0x10f3
 #define PSMOUSE_CMD_ENABLE	0x00f4
+#define PSMOUSE_CMD_DISABLE	0x00f5
 #define PSMOUSE_CMD_RESET_DIS	0x00f6
 #define PSMOUSE_CMD_RESET_BAT	0x02ff
 
@@ -17,10 +18,17 @@
 #define PSMOUSE_RET_ACK		0xfa
 #define PSMOUSE_RET_NAK		0xfe
 
-/* psmouse states */
-#define PSMOUSE_CMD_MODE	0
-#define PSMOUSE_ACTIVATED	1
-#define PSMOUSE_IGNORE		2
+#define PSMOUSE_FLAG_ACK	0	/* Waiting for ACK/NAK */
+#define PSMOUSE_FLAG_CMD	1	/* Waiting for command to finish */
+#define PSMOUSE_FLAG_CMD1	2	/* Waiting for the first byte of command response */
+#define PSMOUSE_FLAG_WAITID	3	/* Command execiting is GET ID */
+
+enum psmouse_state {
+	PSMOUSE_IGNORE,
+	PSMOUSE_INITIALIZING,
+	PSMOUSE_CMD_MODE,
+	PSMOUSE_ACTIVATED,
+};
 
 /* psmouse protocol handler return codes */
 typedef enum {
@@ -29,20 +37,10 @@
 	PSMOUSE_FULL_PACKET
 } psmouse_ret_t;
 
-struct psmouse;
-
-struct psmouse_ptport {
-	struct serio serio;
-
-	void (*activate)(struct psmouse *parent);
-	void (*deactivate)(struct psmouse *parent);
-};
-
 struct psmouse {
 	void *private;
 	struct input_dev dev;
 	struct serio *serio;
-	struct psmouse_ptport *ptport;
 	char *vendor;
 	char *name;
 	unsigned char cmdbuf[8];
@@ -53,16 +51,22 @@
 	unsigned char model;
 	unsigned long last;
 	unsigned long out_of_sync;
-	unsigned char state;
-	char acking;
-	volatile char ack;
+	enum psmouse_state state;
+	unsigned char nak;
 	char error;
 	char devname[64];
 	char phys[32];
+	unsigned long flags;
+
+	/* Used to signal completion from interrupt handler */
+	wait_queue_head_t wait;
 
-	psmouse_ret_t (*protocol_handler)(struct psmouse *psmouse, struct pt_regs *regs); 
+	psmouse_ret_t (*protocol_handler)(struct psmouse *psmouse, struct pt_regs *regs);
 	int (*reconnect)(struct psmouse *psmouse);
 	void (*disconnect)(struct psmouse *psmouse);
+
+	void (*pt_activate)(struct psmouse *psmouse);
+	void (*pt_deactivate)(struct psmouse *psmouse);
 };
 
 #define PSMOUSE_PS2		1
diff -Nru a/drivers/input/mouse/sermouse.c b/drivers/input/mouse/sermouse.c
--- a/drivers/input/mouse/sermouse.c	2004-10-18 14:56:48 -07:00
+++ b/drivers/input/mouse/sermouse.c	2004-10-18 14:56:48 -07:00
@@ -37,8 +37,10 @@
 #include <linux/serio.h>
 #include <linux/init.h>
 
+#define DRIVER_DESC	"Serial mouse driver"
+
 MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>");
-MODULE_DESCRIPTION("Serial mouse driver");
+MODULE_DESCRIPTION(DRIVER_DESC);
 MODULE_LICENSE("GPL");
 
 static char *sermouse_protocols[] = { "None", "Mouse Systems Mouse", "Sun Mouse", "Microsoft Mouse",
@@ -237,7 +239,7 @@
  * an unhandled serio port is found.
  */
 
-static void sermouse_connect(struct serio *serio, struct serio_dev *dev)
+static void sermouse_connect(struct serio *serio, struct serio_driver *drv)
 {
 	struct sermouse *sermouse;
 	unsigned char c;
@@ -279,7 +281,7 @@
 	sermouse->dev.id.product = c;
 	sermouse->dev.id.version = 0x0100;
 
-	if (serio_open(serio, dev)) {
+	if (serio_open(serio, drv)) {
 		kfree(sermouse);
 		return;
 	}
@@ -289,21 +291,25 @@
 	printk(KERN_INFO "input: %s on %s\n", sermouse_protocols[sermouse->type], serio->phys);
 }
 
-static struct serio_dev sermouse_dev = {
-	.interrupt =	sermouse_interrupt,
-	.connect =	sermouse_connect,
-	.disconnect =	sermouse_disconnect
+static struct serio_driver sermouse_drv = {
+	.driver		= {
+		.name	= "sermouse",
+	},
+	.description	= DRIVER_DESC,
+	.interrupt	= sermouse_interrupt,
+	.connect	= sermouse_connect,
+	.disconnect	= sermouse_disconnect,
 };
 
 int __init sermouse_init(void)
 {
-	serio_register_device(&sermouse_dev);
+	serio_register_driver(&sermouse_drv);
 	return 0;
 }
 
 void __exit sermouse_exit(void)
 {
-	serio_unregister_device(&sermouse_dev);
+	serio_unregister_driver(&sermouse_drv);
 }
 
 module_init(sermouse_init);
diff -Nru a/drivers/input/mouse/synaptics.c b/drivers/input/mouse/synaptics.c
--- a/drivers/input/mouse/synaptics.c	2004-10-18 14:56:28 -07:00
+++ b/drivers/input/mouse/synaptics.c	2004-10-18 14:56:28 -07:00
@@ -212,9 +212,9 @@
 /*****************************************************************************
  *	Synaptics pass-through PS/2 port support
  ****************************************************************************/
-static int synaptics_pt_write(struct serio *port, unsigned char c)
+static int synaptics_pt_write(struct serio *serio, unsigned char c)
 {
-	struct psmouse *parent = port->driver;
+	struct psmouse *parent = serio->parent->private;
 	char rate_param = SYN_PS_CLIENT_CMD; /* indicates that we want pass-through port */
 
 	if (psmouse_sliced_command(parent, c))
@@ -233,22 +233,19 @@
 {
 	struct psmouse *child = ptport->private;
 
-	if (child) {
-		if (child->state == PSMOUSE_ACTIVATED) {
-			serio_interrupt(ptport, packet[1], 0, NULL);
-			serio_interrupt(ptport, packet[4], 0, NULL);
-			serio_interrupt(ptport, packet[5], 0, NULL);
-			if (child->type >= PSMOUSE_GENPS)
-				serio_interrupt(ptport, packet[2], 0, NULL);
-		} else if (child->state != PSMOUSE_IGNORE) {
-			serio_interrupt(ptport, packet[1], 0, NULL);
-		}
-	}
+	if (child && child->state == PSMOUSE_ACTIVATED) {
+		serio_interrupt(ptport, packet[1], 0, NULL);
+		serio_interrupt(ptport, packet[4], 0, NULL);
+		serio_interrupt(ptport, packet[5], 0, NULL);
+		if (child->type >= PSMOUSE_GENPS)
+			serio_interrupt(ptport, packet[2], 0, NULL);
+	} else
+		serio_interrupt(ptport, packet[1], 0, NULL);
 }
 
 static void synaptics_pt_activate(struct psmouse *psmouse)
 {
-	struct psmouse *child = psmouse->ptport->serio.private;
+	struct psmouse *child = psmouse->serio->child->private;
 
 	/* adjust the touchpad to child's choice of protocol */
 	if (child && child->type >= PSMOUSE_GENPS) {
@@ -259,23 +256,25 @@
 
 static void synaptics_pt_create(struct psmouse *psmouse)
 {
-	struct psmouse_ptport *port;
+	struct serio *serio;
 
-	psmouse->ptport = port = kmalloc(sizeof(struct psmouse_ptport), GFP_KERNEL);
-	if (!port) {
+	serio = kmalloc(sizeof(struct serio), GFP_KERNEL);
+	if (!serio) {
 		printk(KERN_ERR "synaptics: not enough memory to allocate pass-through port\n");
 		return;
 	}
 
-	memset(port, 0, sizeof(struct psmouse_ptport));
+	memset(serio, 0, sizeof(struct serio));
+
+	serio->type = SERIO_PS_PSTHRU;
+	strlcpy(serio->name, "Synaptics pass-through", sizeof(serio->name));
+	strlcpy(serio->phys, "synaptics-pt/serio0", sizeof(serio->name));
+	serio->write = synaptics_pt_write;
+	serio->parent = psmouse->serio;
 
-	port->serio.type = SERIO_PS_PSTHRU;
-	port->serio.name = "Synaptics pass-through";
-	port->serio.phys = "synaptics-pt/serio0";
-	port->serio.write = synaptics_pt_write;
-	port->serio.driver = psmouse;
+	psmouse->pt_activate = synaptics_pt_activate;
 
-	port->activate = synaptics_pt_activate;
+	psmouse->serio->child = serio;
 }
 
 /*****************************************************************************
@@ -470,9 +469,10 @@
 		if (unlikely(priv->pkt_type == SYN_NEWABS))
 			priv->pkt_type = synaptics_detect_pkt_type(psmouse);
 
-		if (psmouse->ptport && psmouse->ptport->serio.dev && synaptics_is_pt_packet(psmouse->packet))
-			synaptics_pass_pt_packet(&psmouse->ptport->serio, psmouse->packet);
-		else
+		if (SYN_CAP_PASS_THROUGH(priv->capabilities) && synaptics_is_pt_packet(psmouse->packet)) {
+			if (psmouse->serio->child)
+				synaptics_pass_pt_packet(psmouse->serio->child, psmouse->packet);
+		} else
 			synaptics_process_packet(psmouse);
 
 		return PSMOUSE_FULL_PACKET;
diff -Nru a/drivers/input/mouse/vsxxxaa.c b/drivers/input/mouse/vsxxxaa.c
--- a/drivers/input/mouse/vsxxxaa.c	2004-10-18 14:57:18 -07:00
+++ b/drivers/input/mouse/vsxxxaa.c	2004-10-18 14:57:18 -07:00
@@ -82,8 +82,10 @@
 #include <linux/serio.h>
 #include <linux/init.h>
 
+#define DRIVER_DESC	"Serial DEC VSXXX-AA/GA mouse / DEC tablet driver"
+
 MODULE_AUTHOR ("Jan-Benedict Glaw <jbglaw@lug-owl.de>");
-MODULE_DESCRIPTION ("Serial DEC VSXXX-AA/GA mouse / DEC tablet driver");
+MODULE_DESCRIPTION (DRIVER_DESC);
 MODULE_LICENSE ("GPL");
 
 #undef VSXXXAA_DEBUG
@@ -482,7 +484,7 @@
 }
 
 static void
-vsxxxaa_connect (struct serio *serio, struct serio_dev *dev)
+vsxxxaa_connect (struct serio *serio, struct serio_driver *drv)
 {
 	struct vsxxxaa *mouse;
 
@@ -524,7 +526,7 @@
 	mouse->dev.id.bustype = BUS_RS232;
 	mouse->serio = serio;
 
-	if (serio_open (serio, dev)) {
+	if (serio_open (serio, drv)) {
 		kfree (mouse);
 		return;
 	}
@@ -540,23 +542,27 @@
 	printk (KERN_INFO "input: %s on %s\n", mouse->name, mouse->phys);
 }
 
-static struct serio_dev vsxxxaa_dev = {
-	.connect = vsxxxaa_connect,
-	.interrupt = vsxxxaa_interrupt,
-	.disconnect = vsxxxaa_disconnect,
+static struct serio_driver vsxxxaa_drv = {
+	.driver		= {
+		.name	= "vsxxxaa",
+	},
+	.description	= DRIVER_DESC,
+	.connect	= vsxxxaa_connect,
+	.interrupt	= vsxxxaa_interrupt,
+	.disconnect	= vsxxxaa_disconnect,
 };
 
 int __init
 vsxxxaa_init (void)
 {
-	serio_register_device (&vsxxxaa_dev);
+	serio_register_driver(&vsxxxaa_drv);
 	return 0;
 }
 
 void __exit
 vsxxxaa_exit (void)
 {
-	serio_unregister_device (&vsxxxaa_dev);
+	serio_unregister_driver(&vsxxxaa_drv);
 }
 
 module_init (vsxxxaa_init);
diff -Nru a/drivers/input/mousedev.c b/drivers/input/mousedev.c
--- a/drivers/input/mousedev.c	2004-10-18 14:57:03 -07:00
+++ b/drivers/input/mousedev.c	2004-10-18 14:57:03 -07:00
@@ -48,8 +48,15 @@
 module_param(yres, uint, 0);
 MODULE_PARM_DESC(yres, "Vertical screen resolution");
 
-struct mousedev_motion {
+static unsigned tap_time = 200;
+module_param(tap_time, uint, 0);
+MODULE_PARM_DESC(tap_time, "Tap time for touchpads in absolute mode (msecs)");
+
+struct mousedev_hw_data {
 	int dx, dy, dz;
+	int x, y;
+	int abs_event;
+	unsigned long buttons;
 };
 
 struct mousedev {
@@ -61,22 +68,38 @@
 	struct list_head list;
 	struct input_handle handle;
 
-	struct mousedev_motion packet;
-	unsigned long buttons;
+	struct mousedev_hw_data packet;
 	unsigned int pkt_count;
 	int old_x[4], old_y[4];
-	unsigned int touch;
+	unsigned long touch;
 };
 
+enum mousedev_emul {
+	MOUSEDEV_EMUL_PS2,
+	MOUSEDEV_EMUL_IMPS,
+	MOUSEDEV_EMUL_EXPS
+};
+
+struct mousedev_motion {
+	int dx, dy, dz;
+	unsigned long buttons;
+};
+
+#define PACKET_QUEUE_LEN	16
 struct mousedev_list {
 	struct fasync_struct *fasync;
 	struct mousedev *mousedev;
 	struct list_head node;
-	int dx, dy, dz;
-	unsigned long buttons;
+
+	struct mousedev_motion packets[PACKET_QUEUE_LEN];
+	unsigned int head, tail;
+	spinlock_t packet_lock;
+	int pos_x, pos_y;
+
 	signed char ps2[6];
 	unsigned char ready, buffer, bufsiz;
-	unsigned char mode, imexseq, impsseq;
+	unsigned char imexseq, impsseq;
+	enum mousedev_emul mode;
 };
 
 #define MOUSEDEV_SEQ_LEN	6
@@ -119,15 +142,19 @@
 		case ABS_X:
 			size = dev->absmax[ABS_X] - dev->absmin[ABS_X];
 			if (size == 0) size = xres;
-			mousedev->packet.dx = (value * xres - mousedev->old_x[0]) / size;
-			mousedev->old_x[0] = mousedev->packet.dx * size;
+			if (value > dev->absmax[ABS_X]) value = dev->absmax[ABS_X];
+			if (value < dev->absmin[ABS_X]) value = dev->absmin[ABS_X];
+			mousedev->packet.x = ((value - dev->absmin[ABS_X]) * xres) / size;
+			mousedev->packet.abs_event = 1;
 			break;
 
 		case ABS_Y:
 			size = dev->absmax[ABS_Y] - dev->absmin[ABS_Y];
 			if (size == 0) size = yres;
-			mousedev->packet.dy = (value * yres - mousedev->old_y[0]) / size;
-			mousedev->old_y[0] = mousedev->packet.dy * size;
+			if (value > dev->absmax[ABS_Y]) value = dev->absmax[ABS_Y];
+			if (value < dev->absmin[ABS_Y]) value = dev->absmin[ABS_Y];
+			mousedev->packet.y = yres - ((value - dev->absmin[ABS_Y]) * yres) / size;
+			mousedev->packet.abs_event = 1;
 			break;
 	}
 }
@@ -165,30 +192,82 @@
 	}
 
 	if (value) {
-		set_bit(index, &mousedev->buttons);
-		set_bit(index, &mousedev_mix.buttons);
+		set_bit(index, &mousedev->packet.buttons);
+		set_bit(index, &mousedev_mix.packet.buttons);
 	} else {
-		clear_bit(index, &mousedev->buttons);
-		clear_bit(index, &mousedev_mix.buttons);
+		clear_bit(index, &mousedev->packet.buttons);
+		clear_bit(index, &mousedev_mix.packet.buttons);
 	}
 }
 
-static void mousedev_notify_readers(struct mousedev *mousedev, struct mousedev_motion *packet)
+static void mousedev_notify_readers(struct mousedev *mousedev, struct mousedev_hw_data *packet)
 {
 	struct mousedev_list *list;
+	struct mousedev_motion *p;
+	unsigned long flags;
 
 	list_for_each_entry(list, &mousedev->list, node) {
-		list->dx += packet->dx;
-		list->dy += packet->dy;
-		list->dz += packet->dz;
-		list->buttons = mousedev->buttons;
+		spin_lock_irqsave(&list->packet_lock, flags);
+
+		p = &list->packets[list->head];
+		if (list->ready && p->buttons != packet->buttons) {
+			unsigned int new_head = (list->head + 1) % PACKET_QUEUE_LEN;
+			if (new_head != list->tail) {
+				p = &list->packets[list->head = new_head];
+				memset(p, 0, sizeof(struct mousedev_motion));
+			}
+		}
+
+		if (packet->abs_event) {
+			p->dx += packet->x - list->pos_x;
+			p->dy += packet->y - list->pos_y;
+			list->pos_x = packet->x;
+			list->pos_y = packet->y;
+		}
+
+		list->pos_x += packet->dx;
+		list->pos_x = list->pos_x < 0 ? 0 : (list->pos_x >= xres ? xres : list->pos_x);
+		list->pos_y += packet->dy;
+		list->pos_y = list->pos_y < 0 ? 0 : (list->pos_y >= yres ? yres : list->pos_y);
+
+		p->dx += packet->dx;
+		p->dy += packet->dy;
+		p->dz += packet->dz;
+		p->buttons = mousedev->packet.buttons;
+
 		list->ready = 1;
+
+		spin_unlock_irqrestore(&list->packet_lock, flags);
 		kill_fasync(&list->fasync, SIGIO, POLL_IN);
 	}
 
 	wake_up_interruptible(&mousedev->wait);
 }
 
+static void mousedev_touchpad_touch(struct mousedev *mousedev, int value)
+{
+	if (!value) {
+		if (mousedev->touch &&
+		    time_before(jiffies, mousedev->touch + msecs_to_jiffies(tap_time))) {
+			/*
+			 * Toggle left button to emulate tap.
+			 * We rely on the fact that mousedev_mix always has 0
+			 * motion packet so we won't mess current position.
+			 */
+			set_bit(0, &mousedev->packet.buttons);
+			set_bit(0, &mousedev_mix.packet.buttons);
+			mousedev_notify_readers(mousedev, &mousedev_mix.packet);
+			mousedev_notify_readers(&mousedev_mix, &mousedev_mix.packet);
+			clear_bit(0, &mousedev->packet.buttons);
+			clear_bit(0, &mousedev_mix.packet.buttons);
+		}
+		mousedev->touch = mousedev->pkt_count = 0;
+	}
+	else
+		if (!mousedev->touch)
+			mousedev->touch = jiffies;
+}
+
 static void mousedev_event(struct input_handle *handle, unsigned int type, unsigned int code, int value)
 {
 	struct mousedev *mousedev = handle->private;
@@ -212,12 +291,8 @@
 
 		case EV_KEY:
 			if (value != 2) {
-				if (code == BTN_TOUCH && test_bit(BTN_TOOL_FINGER, handle->dev->keybit)) {
-					/* Handle touchpad data */
-					mousedev->touch = value;
-					if (!mousedev->touch)
-						mousedev->pkt_count = 0;
-				}
+				if (code == BTN_TOUCH && test_bit(BTN_TOOL_FINGER, handle->dev->keybit))
+					mousedev_touchpad_touch(mousedev, value);
 				else
 					mousedev_key_event(mousedev, code, value);
 			}
@@ -237,7 +312,8 @@
 				mousedev_notify_readers(mousedev, &mousedev->packet);
 				mousedev_notify_readers(&mousedev_mix, &mousedev->packet);
 
-				memset(&mousedev->packet, 0, sizeof(struct mousedev_motion));
+				mousedev->packet.dx = mousedev->packet.dy = mousedev->packet.dz = 0;
+				mousedev->packet.abs_event = 0;
 			}
 			break;
 	}
@@ -322,6 +398,9 @@
 		return -ENOMEM;
 	memset(list, 0, sizeof(struct mousedev_list));
 
+	spin_lock_init(&list->packet_lock);
+	list->pos_x = xres / 2;
+	list->pos_y = yres / 2;
 	list->mousedev = mousedev_table[i];
 	list_add_tail(&list->node, &mousedev_table[i]->list);
 	file->private_data = list;
@@ -341,32 +420,56 @@
 	return 0;
 }
 
-static void mousedev_packet(struct mousedev_list *list, unsigned char off)
+static inline int mousedev_limit_delta(int delta, int limit)
 {
-	list->ps2[off] = 0x08 | ((list->dx < 0) << 4) | ((list->dy < 0) << 5) | (list->buttons & 0x07);
-	list->ps2[off + 1] = (list->dx > 127 ? 127 : (list->dx < -127 ? -127 : list->dx));
-	list->ps2[off + 2] = (list->dy > 127 ? 127 : (list->dy < -127 ? -127 : list->dy));
-	list->dx -= list->ps2[off + 1];
-	list->dy -= list->ps2[off + 2];
-	list->bufsiz = off + 3;
-
-	if (list->mode == 2) {
-		list->ps2[off + 3] = (list->dz > 7 ? 7 : (list->dz < -7 ? -7 : list->dz));
-		list->dz -= list->ps2[off + 3];
-		list->ps2[off + 3] = (list->ps2[off + 3] & 0x0f) | ((list->buttons & 0x18) << 1);
-		list->bufsiz++;
-	} else {
-		list->ps2[off] |= ((list->buttons & 0x10) >> 3) | ((list->buttons & 0x08) >> 1);
+	return delta > limit ? limit : (delta < -limit ? -limit : delta);
+}
+
+static void mousedev_packet(struct mousedev_list *list, signed char *ps2_data)
+{
+	struct mousedev_motion *p;
+	unsigned long flags;
+
+	spin_lock_irqsave(&list->packet_lock, flags);
+	p = &list->packets[list->tail];
+
+	ps2_data[0] = 0x08 | ((p->dx < 0) << 4) | ((p->dy < 0) << 5) | (p->buttons & 0x07);
+	ps2_data[1] = mousedev_limit_delta(p->dx, 127);
+	ps2_data[2] = mousedev_limit_delta(p->dy, 127);
+	p->dx -= ps2_data[1];
+	p->dy -= ps2_data[2];
+
+	switch (list->mode) {
+		case MOUSEDEV_EMUL_EXPS:
+			ps2_data[3] = mousedev_limit_delta(p->dz, 127);
+			p->dz -= ps2_data[3];
+			ps2_data[3] = (ps2_data[3] & 0x0f) | ((p->buttons & 0x18) << 1);
+			list->bufsiz = 4;
+			break;
+
+		case MOUSEDEV_EMUL_IMPS:
+			ps2_data[0] |= ((p->buttons & 0x10) >> 3) | ((p->buttons & 0x08) >> 1);
+			ps2_data[3] = mousedev_limit_delta(p->dz, 127);
+			p->dz -= ps2_data[3];
+			list->bufsiz = 4;
+			break;
+
+		case MOUSEDEV_EMUL_PS2:
+		default:
+			ps2_data[0] |= ((p->buttons & 0x10) >> 3) | ((p->buttons & 0x08) >> 1);
+			p->dz = 0;
+			list->bufsiz = 3;
+			break;
 	}
 
-	if (list->mode == 1) {
-		list->ps2[off + 3] = (list->dz > 127 ? 127 : (list->dz < -127 ? -127 : list->dz));
-		list->dz -= list->ps2[off + 3];
-		list->bufsiz++;
+	if (!p->dx && !p->dy && !p->dz) {
+		if (list->tail != list->head)
+			list->tail = (list->tail + 1) % PACKET_QUEUE_LEN;
+		if (list->tail == list->head)
+			list->ready = 0;
 	}
 
-	if (!list->dx && !list->dy && (!list->mode || !list->dz)) list->ready = 0;
-	list->buffer = list->bufsiz;
+	spin_unlock_irqrestore(&list->packet_lock, flags);
 }
 
 
@@ -384,31 +487,31 @@
 		if (c == mousedev_imex_seq[list->imexseq]) {
 			if (++list->imexseq == MOUSEDEV_SEQ_LEN) {
 				list->imexseq = 0;
-				list->mode = 2;
+				list->mode = MOUSEDEV_EMUL_EXPS;
 			}
 		} else list->imexseq = 0;
 
 		if (c == mousedev_imps_seq[list->impsseq]) {
 			if (++list->impsseq == MOUSEDEV_SEQ_LEN) {
 				list->impsseq = 0;
-				list->mode = 1;
+				list->mode = MOUSEDEV_EMUL_IMPS;
 			}
 		} else list->impsseq = 0;
 
 		list->ps2[0] = 0xfa;
-		list->bufsiz = 1;
 
 		switch (c) {
 
 			case 0xeb: /* Poll */
-				mousedev_packet(list, 1);
+				mousedev_packet(list, &list->ps2[1]);
+				list->bufsiz++; /* account for leading ACK */
 				break;
 
 			case 0xf2: /* Get ID */
 				switch (list->mode) {
-					case 0: list->ps2[1] = 0; break;
-					case 1: list->ps2[1] = 3; break;
-					case 2: list->ps2[1] = 4; break;
+					case MOUSEDEV_EMUL_PS2:  list->ps2[1] = 0; break;
+					case MOUSEDEV_EMUL_IMPS: list->ps2[1] = 3; break;
+					case MOUSEDEV_EMUL_EXPS: list->ps2[1] = 4; break;
 				}
 				list->bufsiz = 2;
 				break;
@@ -419,13 +522,15 @@
 				break;
 
 			case 0xff: /* Reset */
-				list->impsseq = 0;
-				list->imexseq = 0;
-				list->mode = 0;
-				list->ps2[1] = 0xaa;
-				list->ps2[2] = 0x00;
+				list->impsseq = list->imexseq = 0;
+				list->mode = MOUSEDEV_EMUL_PS2;
+				list->ps2[1] = 0xaa; list->ps2[2] = 0x00;
 				list->bufsiz = 3;
 				break;
+
+			default:
+				list->bufsiz = 1;
+				break;
 		}
 
 		list->buffer = list->bufsiz;
@@ -446,13 +551,19 @@
 	if (!list->ready && !list->buffer && (file->f_flags & O_NONBLOCK))
 		return -EAGAIN;
 
-	retval = wait_event_interruptible(list->mousedev->wait, list->ready || list->buffer);
+	retval = wait_event_interruptible(list->mousedev->wait,
+					  !list->mousedev->exist || list->ready || list->buffer);
 
 	if (retval)
 		return retval;
 
-	if (!list->buffer && list->ready)
-		mousedev_packet(list, 0);
+	if (!list->mousedev->exist)
+		return -ENODEV;
+
+	if (!list->buffer && list->ready) {
+		mousedev_packet(list, list->ps2);
+		list->buffer = list->bufsiz;
+	}
 
 	if (count > list->buffer)
 		count = list->buffer;
diff -Nru a/drivers/input/serio/Kconfig b/drivers/input/serio/Kconfig
--- a/drivers/input/serio/Kconfig	2004-10-18 14:56:32 -07:00
+++ b/drivers/input/serio/Kconfig	2004-10-18 14:56:32 -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 || FOOTBRIDGE_HOST)
 	---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,
@@ -130,3 +130,19 @@
 
 	  To compile this driver as a module, choose M here: the
 	  module will be called maceps2.
+
+config SERIO_RAW
+	tristate "Raw access to serio ports"
+	depends on SERIO
+	help
+	  Say Y here if you want to have raw access to serio ports, such as
+	  AUX ports on i8042 keyboard controller. Each serio port that is
+	  bound to this driver will be accessible via a char device with
+	  major 10 and dynamically allocated minor. The driver will try
+	  allocating minor 1 (that historically corresponds to /dev/psaux)
+	  first. To bind this driver to a serio port use sysfs interface:
+
+	      echo -n "serio_raw" > /sys/bus/serio/devices/serioX/driver
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called serio_raw.
diff -Nru a/drivers/input/serio/Makefile b/drivers/input/serio/Makefile
--- a/drivers/input/serio/Makefile	2004-10-18 14:55:54 -07:00
+++ b/drivers/input/serio/Makefile	2004-10-18 14:55:54 -07:00
@@ -17,3 +17,4 @@
 obj-$(CONFIG_SERIO_GSCPS2)	+= gscps2.o
 obj-$(CONFIG_SERIO_PCIPS2)	+= pcips2.o
 obj-$(CONFIG_SERIO_MACEPS2)	+= maceps2.o
+obj-$(CONFIG_SERIO_RAW)		+= serio_raw.o
diff -Nru a/drivers/input/serio/ambakmi.c b/drivers/input/serio/ambakmi.c
--- a/drivers/input/serio/ambakmi.c	2004-10-18 14:56:33 -07:00
+++ b/drivers/input/serio/ambakmi.c	2004-10-18 14:56:33 -07:00
@@ -29,7 +29,7 @@
 #define KMI_BASE	(kmi->base)
 
 struct amba_kmi_port {
-	struct serio		io;
+	struct serio		*io;
 	struct clk		*clk;
 	unsigned char		*base;
 	unsigned int		irq;
@@ -44,7 +44,7 @@
 	int handled = IRQ_NONE;
 
 	while (status & KMIIR_RXINTR) {
-		serio_interrupt(&kmi->io, readb(KMIDATA), 0, regs);
+		serio_interrupt(kmi->io, readb(KMIDATA), 0, regs);
 		status = readb(KMIIR);
 		handled = IRQ_HANDLED;
 	}
@@ -54,7 +54,7 @@
 
 static int amba_kmi_write(struct serio *io, unsigned char val)
 {
-	struct amba_kmi_port *kmi = io->driver;
+	struct amba_kmi_port *kmi = io->port_data;
 	unsigned int timeleft = 10000; /* timeout in 100ms */
 
 	while ((readb(KMISTAT) & KMISTAT_TXEMPTY) == 0 && timeleft--)
@@ -68,7 +68,7 @@
 
 static int amba_kmi_open(struct serio *io)
 {
-	struct amba_kmi_port *kmi = io->driver;
+	struct amba_kmi_port *kmi = io->port_data;
 	unsigned int divisor;
 	int ret;
 
@@ -105,7 +105,7 @@
 
 static void amba_kmi_close(struct serio *io)
 {
-	struct amba_kmi_port *kmi = io->driver;
+	struct amba_kmi_port *kmi = io->port_data;
 
 	writeb(0, KMICR);
 
@@ -117,6 +117,7 @@
 static int amba_kmi_probe(struct amba_device *dev, void *id)
 {
 	struct amba_kmi_port *kmi;
+	struct serio *io;
 	int ret;
 
 	ret = amba_request_regions(dev, NULL);
@@ -124,21 +125,25 @@
 		return ret;
 
 	kmi = kmalloc(sizeof(struct amba_kmi_port), GFP_KERNEL);
-	if (!kmi) {
+	io = kmalloc(sizeof(struct serio), GFP_KERNEL);
+	if (!kmi || !io) {
 		ret = -ENOMEM;
 		goto out;
 	}
 
 	memset(kmi, 0, sizeof(struct amba_kmi_port));
+	memset(io, 0, sizeof(struct serio));
 
-	kmi->io.type	= SERIO_8042;
-	kmi->io.write	= amba_kmi_write;
-	kmi->io.open	= amba_kmi_open;
-	kmi->io.close	= amba_kmi_close;
-	kmi->io.name	= dev->dev.bus_id;
-	kmi->io.phys	= dev->dev.bus_id;
-	kmi->io.driver	= kmi;
+	io->type	= SERIO_8042;
+	io->write	= amba_kmi_write;
+	io->open	= amba_kmi_open;
+	io->close	= amba_kmi_close;
+	strlcpy(io->name, dev->dev.bus_id, sizeof(io->name));
+	strlcpy(io->phys, dev->dev.bus_id, sizeof(io->phys));
+	io->port_data	= kmi;
+	io->dev.parent	= &dev->dev;
 
+	kmi->io 	= io;
 	kmi->base	= ioremap(dev->res.start, KMI_SIZE);
 	if (!kmi->base) {
 		ret = -ENOMEM;
@@ -154,13 +159,14 @@
 	kmi->irq = dev->irq[0];
 	amba_set_drvdata(dev, kmi);
 
-	serio_register_port(&kmi->io);
+	serio_register_port(kmi->io);
 	return 0;
 
  unmap:
 	iounmap(kmi->base);
  out:
 	kfree(kmi);
+	kfree(io);
 	amba_release_regions(dev);
 	return ret;
 }
@@ -171,7 +177,7 @@
 
 	amba_set_drvdata(dev, NULL);
 
-	serio_unregister_port(&kmi->io);
+	serio_unregister_port(kmi->io);
 	clk_put(kmi->clk);
 	iounmap(kmi->base);
 	kfree(kmi);
@@ -184,7 +190,7 @@
 	struct amba_kmi_port *kmi = amba_get_drvdata(dev);
 
 	/* kick the serio layer to rescan this port */
-	serio_rescan(&kmi->io);
+	serio_reconnect(kmi->io);
 
 	return 0;
 }
@@ -214,7 +220,7 @@
 
 static void __exit amba_kmi_exit(void)
 {
-	return amba_driver_unregister(&ambakmi_driver);
+	amba_driver_unregister(&ambakmi_driver);
 }
 
 module_init(amba_kmi_init);
diff -Nru a/drivers/input/serio/ct82c710.c b/drivers/input/serio/ct82c710.c
--- a/drivers/input/serio/ct82c710.c	2004-10-18 14:55:54 -07:00
+++ b/drivers/input/serio/ct82c710.c	2004-10-18 14:55:54 -07:00
@@ -36,6 +36,7 @@
 #include <linux/interrupt.h>
 #include <linux/serio.h>
 #include <linux/errno.h>
+#include <linux/err.h>
 
 #include <asm/io.h>
 
@@ -43,9 +44,6 @@
 MODULE_DESCRIPTION("82C710 C&T mouse port chip driver");
 MODULE_LICENSE("GPL");
 
-static char ct82c710_name[] = "C&T 82c710 mouse port";
-static char ct82c710_phys[16];
-
 /*
  * ct82c710 interface
  */
@@ -61,10 +59,22 @@
 
 #define CT82C710_IRQ          12
 
-static int ct82c710_data;
-static int ct82c710_status;
+#define CT82C710_DATA         ct82c710_iores.start
+#define CT82C710_STATUS       (ct82c710_iores.start + 1)
 
-static irqreturn_t ct82c710_interrupt(int cpl, void *dev_id, struct pt_regs * regs);
+static struct serio *ct82c710_port;
+static struct platform_device *ct82c710_device;
+static struct resource ct82c710_iores;
+
+/*
+ * Interrupt handler for the 82C710 mouse port. A character
+ * is waiting in the 82C710.
+ */
+
+static irqreturn_t ct82c710_interrupt(int cpl, void *dev_id, struct pt_regs * regs)
+{
+	return serio_interrupt(ct82c710_port, inb(CT82C710_DATA), 0, regs);
+}
 
 /*
  * Wait for device to send output char and flush any input char.
@@ -74,10 +84,10 @@
 {
 	int timeout = 60000;
 
-	while ((inb(ct82c710_status) & (CT82C710_RX_FULL | CT82C710_TX_IDLE | CT82C710_DEV_IDLE))
+	while ((inb(CT82C710_STATUS) & (CT82C710_RX_FULL | CT82C710_TX_IDLE | CT82C710_DEV_IDLE))
 		       != (CT82C710_DEV_IDLE | CT82C710_TX_IDLE) && timeout) {
 
-		if (inb_p(ct82c710_status) & CT82C710_RX_FULL) inb_p(ct82c710_data);
+		if (inb_p(CT82C710_STATUS) & CT82C710_RX_FULL) inb_p(CT82C710_DATA);
 
 		udelay(1);
 		timeout--;
@@ -91,7 +101,7 @@
 	if (ct82c170_wait())
 		printk(KERN_WARNING "ct82c710.c: Device busy in close()\n");
 
-	outb_p(inb_p(ct82c710_status) & ~(CT82C710_ENABLE | CT82C710_INTS_ON), ct82c710_status);
+	outb_p(inb_p(CT82C710_STATUS) & ~(CT82C710_ENABLE | CT82C710_INTS_ON), CT82C710_STATUS);
 
 	if (ct82c170_wait())
 		printk(KERN_WARNING "ct82c710.c: Device busy in close()\n");
@@ -106,21 +116,21 @@
 	if (request_irq(CT82C710_IRQ, ct82c710_interrupt, 0, "ct82c710", NULL))
 		return -1;
 
-	status = inb_p(ct82c710_status);
+	status = inb_p(CT82C710_STATUS);
 
 	status |= (CT82C710_ENABLE | CT82C710_RESET);
-	outb_p(status, ct82c710_status);
+	outb_p(status, CT82C710_STATUS);
 
 	status &= ~(CT82C710_RESET);
-	outb_p(status, ct82c710_status);
+	outb_p(status, CT82C710_STATUS);
 
 	status |= CT82C710_INTS_ON;
-	outb_p(status, ct82c710_status);	/* Enable interrupts */
+	outb_p(status, CT82C710_STATUS);	/* Enable interrupts */
 
 	while (ct82c170_wait()) {
 		printk(KERN_ERR "ct82c710: Device busy in open()\n");
 		status &= ~(CT82C710_ENABLE | CT82C710_INTS_ON);
-		outb_p(status, ct82c710_status);
+		outb_p(status, CT82C710_STATUS);
 		free_irq(CT82C710_IRQ, NULL);
 		return -1;
 	}
@@ -135,30 +145,10 @@
 static int ct82c710_write(struct serio *port, unsigned char c)
 {
 	if (ct82c170_wait()) return -1;
-	outb_p(c, ct82c710_data);
+	outb_p(c, CT82C710_DATA);
 	return 0;
 }
 
-static struct serio ct82c710_port =
-{
-	.type	= SERIO_8042,
-	.name	= ct82c710_name,
-	.phys	= ct82c710_phys,
-	.write	= ct82c710_write,
-	.open	= ct82c710_open,
-	.close	= ct82c710_close,
-};
-
-/*
- * Interrupt handler for the 82C710 mouse port. A character
- * is waiting in the 82C710.
- */
-
-static irqreturn_t ct82c710_interrupt(int cpl, void *dev_id, struct pt_regs * regs)
-{
-	return serio_interrupt(&ct82c710_port, inb(ct82c710_data), 0, regs);
-}
-
 /*
  * See if we can find a 82C710 device. Read mouse address.
  */
@@ -175,36 +165,60 @@
 		return -1;				/* No: no 82C710 here */
 
 	outb_p(0x0d, 0x390);				/* Write index */
-	ct82c710_data = inb_p(0x391) << 2;		/* Get mouse I/O address */
-	ct82c710_status = ct82c710_data + 1;
+	ct82c710_iores.start = inb_p(0x391) << 2;	/* Get mouse I/O address */
+	ct82c710_iores.end = ct82c710_iores.start + 1;
+	ct82c710_iores.flags = IORESOURCE_IO;
 	outb_p(0x0f, 0x390);
 	outb_p(0x0f, 0x391);				/* Close config mode */
 
 	return 0;
 }
 
+static struct serio * __init ct82c710_allocate_port(void)
+{
+	struct serio *serio;
+
+	serio = kmalloc(sizeof(struct serio), GFP_KERNEL);
+	if (serio) {
+		memset(serio, 0, sizeof(struct serio));
+		serio->type = SERIO_8042;
+		serio->open = ct82c710_open;
+		serio->close = ct82c710_close;
+		serio->write = ct82c710_write;
+		serio->dev.parent = &ct82c710_device->dev;
+		strlcpy(serio->name, "C&T 82c710 mouse port", sizeof(serio->name));
+		snprintf(serio->phys, sizeof(serio->phys), "isa%04lx/serio0", CT82C710_DATA);
+	}
+
+	return serio;
+}
+
 int __init ct82c710_init(void)
 {
 	if (ct82c710_probe())
 		return -ENODEV;
 
-	if (request_region(ct82c710_data, 2, "ct82c710"))
-		return -EBUSY;
-
-	sprintf(ct82c710_phys, "isa%04x/serio0", ct82c710_data);
+	ct82c710_device = platform_device_register_simple("ct82c710", -1, &ct82c710_iores, 1);
+	if (IS_ERR(ct82c710_device))
+		return PTR_ERR(ct82c710_device);
+
+	if (!(ct82c710_port = ct82c710_allocate_port())) {
+		platform_device_unregister(ct82c710_device);
+		return -ENOMEM;
+	}
 
-	serio_register_port(&ct82c710_port);
+	serio_register_port(ct82c710_port);
 
-	printk(KERN_INFO "serio: C&T 82c710 mouse port at %#x irq %d\n",
-		ct82c710_data, CT82C710_IRQ);
+	printk(KERN_INFO "serio: C&T 82c710 mouse port at %#lx irq %d\n",
+		CT82C710_DATA, CT82C710_IRQ);
 
 	return 0;
 }
 
 void __exit ct82c710_exit(void)
 {
-	serio_unregister_port(&ct82c710_port);
-	release_region(ct82c710_data, 2);
+	serio_unregister_port(ct82c710_port);
+	platform_device_unregister(ct82c710_device);
 }
 
 module_init(ct82c710_init);
diff -Nru a/drivers/input/serio/gscps2.c b/drivers/input/serio/gscps2.c
--- a/drivers/input/serio/gscps2.c	2004-10-18 14:57:04 -07:00
+++ b/drivers/input/serio/gscps2.c	2004-10-18 14:57:04 -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>
@@ -91,7 +91,7 @@
 struct gscps2port {
 	struct list_head node;
 	struct parisc_device *padev;
-	struct serio port;
+	struct serio *port;
 	spinlock_t lock;
 	char *addr;
 	u8 act, append; /* position in buffer[] */
@@ -100,7 +100,6 @@
 		u8 str;
 	} buffer[BUFFER_SIZE+1];
 	int id;
-	char name[32];
 };
 
 /*
@@ -272,7 +271,7 @@
 	    rxflags =	((status & GSC_STAT_TERR) ? SERIO_TIMEOUT : 0 ) |
 			((status & GSC_STAT_PERR) ? SERIO_PARITY  : 0 );
 
-	    serio_interrupt(&ps2port->port, data, rxflags, regs);
+	    serio_interrupt(ps2port->port, data, rxflags, regs);
 
 	  } /* while() */
 
@@ -288,7 +287,7 @@
 
 static int gscps2_write(struct serio *port, unsigned char data)
 {
-	struct gscps2port *ps2port = port->driver;
+	struct gscps2port *ps2port = port->port_data;
 
 	if (!gscps2_writeb_output(ps2port, data)) {
 		printk(KERN_DEBUG PFX "sending byte %#x failed.\n", data);
@@ -304,7 +303,7 @@
 
 static int gscps2_open(struct serio *port)
 {
-	struct gscps2port *ps2port = port->driver;
+	struct gscps2port *ps2port = port->port_data;
 
 	gscps2_reset(ps2port);
 
@@ -319,7 +318,7 @@
 
 static void gscps2_close(struct serio *port)
 {
-	struct gscps2port *ps2port = port->driver;
+	struct gscps2port *ps2port = port->port_data;
 	gscps2_enable(ps2port, DISABLE);
 }
 
@@ -343,7 +342,8 @@
 
 static int __init gscps2_probe(struct parisc_device *dev)
 {
-        struct gscps2port *ps2port;
+	struct gscps2port *ps2port;
+	struct serio *serio;
 	unsigned long hpa = dev->hpa;
 	int ret;
 
@@ -355,34 +355,45 @@
 		hpa += GSC_DINO_OFFSET;
 
 	ps2port = kmalloc(sizeof(struct gscps2port), GFP_KERNEL);
-	if (!ps2port)
-		return -ENOMEM;
+	serio = kmalloc(sizeof(struct serio), GFP_KERNEL);
+	if (!ps2port || !serio) {
+		ret = -ENOMEM;
+		goto fail_nomem;
+	}
 
 	dev_set_drvdata(&dev->dev, ps2port);
 
 	memset(ps2port, 0, sizeof(struct gscps2port));
+	memset(serio, 0, sizeof(struct serio));
+	ps2port->port = serio;
 	ps2port->padev = dev;
 	ps2port->addr = ioremap(hpa, GSC_STATUS + 4);
 	spin_lock_init(&ps2port->lock);
 
 	gscps2_reset(ps2port);
-	ps2port->id = readb(ps2port->addr+GSC_ID) & 0x0f;
-	snprintf(ps2port->name, sizeof(ps2port->name)-1, "%s %s",
-		gscps2_serio_port.name,
-		(ps2port->id == GSC_ID_KEYBOARD) ? "keyboard" : "mouse" );
-
-	memcpy(&ps2port->port, &gscps2_serio_port, sizeof(gscps2_serio_port));
-	ps2port->port.driver = ps2port;
-	ps2port->port.name = ps2port->name;
-	ps2port->port.phys = dev->dev.bus_id;
+	ps2port->id = readb(ps2port->addr + GSC_ID) & 0x0f;
+
+	snprintf(serio->name, sizeof(serio->name), "GSC PS/2 %s",
+		 (ps2port->id == GSC_ID_KEYBOARD) ? "keyboard" : "mouse");
+	strlcpy(serio->phys, dev->dev.bus_id, sizeof(serio->phys));
+	serio->idbus		= BUS_GSC;
+	serio->idvendor		= PCI_VENDOR_ID_HP;
+	serio->idproduct	= 0x0001;
+	serio->idversion	= 0x0010;
+	serio->type		= SERIO_8042;
+	serio->write		= gscps2_write;
+	serio->open		= gscps2_open;
+	serio->close		= gscps2_close;
+	serio->port_data	= ps2port;
+	serio->dev.parent	= &dev->dev;
 
 	list_add_tail(&ps2port->node, &ps2port_list);
 
 	ret = -EBUSY;
-	if (request_irq(dev->irq, gscps2_interrupt, SA_SHIRQ, ps2port->name, ps2port))
+	if (request_irq(dev->irq, gscps2_interrupt, SA_SHIRQ, ps2port->port->name, ps2port))
 		goto fail_miserably;
 
-	if ( (ps2port->id != GSC_ID_KEYBOARD) && (ps2port->id != GSC_ID_MOUSE) ) {
+	if (ps2port->id != GSC_ID_KEYBOARD && ps2port->id != GSC_ID_MOUSE) {
 		printk(KERN_WARNING PFX "Unsupported PS/2 port at 0x%08lx (id=%d) ignored\n",
 				hpa, ps2port->id);
 		ret = -ENODEV;
@@ -395,12 +406,12 @@
 #endif
 
 	printk(KERN_INFO "serio: %s port at 0x%p irq %d @ %s\n",
-		ps2port->name,
+		ps2port->port->name,
 		ps2port->addr,
 		ps2port->padev->irq,
-		ps2port->port.phys);
+		ps2port->port->phys);
 
-	serio_register_port(&ps2port->port);
+	serio_register_port(ps2port->port);
 
 	return 0;
 
@@ -411,7 +422,10 @@
 	list_del(&ps2port->node);
 	iounmap(ps2port->addr);
 	release_mem_region(dev->hpa, GSC_STATUS + 4);
+
+fail_nomem:
 	kfree(ps2port);
+	kfree(serio);
 	return ret;
 }
 
@@ -424,7 +438,7 @@
 {
 	struct gscps2port *ps2port = dev_get_drvdata(&dev->dev);
 
-	serio_unregister_port(&ps2port->port);
+	serio_unregister_port(ps2port->port);
 	free_irq(dev->irq, ps2port);
 	gscps2_flush(ps2port);
 	list_del(&ps2port->node);
diff -Nru a/drivers/input/serio/i8042-io.h b/drivers/input/serio/i8042-io.h
--- a/drivers/input/serio/i8042-io.h	2004-10-18 14:55:53 -07:00
+++ b/drivers/input/serio/i8042-io.h	2004-10-18 14:55:53 -07:00
@@ -65,6 +65,31 @@
 	return;
 }
 
+#if defined(__i386__)
+
+#include <linux/dmi.h>
+
+static struct dmi_system_id __initdata i8042_dmi_table[] = {
+	{
+		.ident = "Compaq Proliant 8500",
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "Compaq"),
+			DMI_MATCH(DMI_PRODUCT_NAME , "ProLiant"),
+			DMI_MATCH(DMI_PRODUCT_VERSION, "8500"),
+		},
+	},
+	{
+		.ident = "Compaq Proliant DL760",
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "Compaq"),
+			DMI_MATCH(DMI_PRODUCT_NAME , "ProLiant"),
+			DMI_MATCH(DMI_PRODUCT_VERSION, "DL760"),
+		},
+	},
+	{ }
+};
+#endif
+
 static inline int i8042_platform_init(void)
 {
 /*
@@ -79,6 +104,12 @@
 #if !defined(__i386__) && !defined(__x86_64__)
         i8042_reset = 1;
 #endif
+
+#if defined(__i386__)
+	if (dmi_check_system(i8042_dmi_table))
+		i8042_noloop = 1;
+#endif
+
 	return 0;
 }
 
diff -Nru a/drivers/input/serio/i8042-sparcio.h b/drivers/input/serio/i8042-sparcio.h
--- a/drivers/input/serio/i8042-sparcio.h	2004-10-18 14:57:04 -07:00
+++ b/drivers/input/serio/i8042-sparcio.h	2004-10-18 14:57:04 -07:00
@@ -18,7 +18,7 @@
 #define I8042_AUX_PHYS_DESC "sparcps2/serio1"
 #define I8042_MUX_PHYS_DESC "sparcps2/serio%d"
 
-static unsigned long kbd_iobase;
+static void __iomem *kbd_iobase;
 
 #define I8042_COMMAND_REG	(kbd_iobase + 0x64UL)
 #define I8042_DATA_REG		(kbd_iobase + 0x60UL)
@@ -64,7 +64,7 @@
 	if (strncmp(prop, "SUNW,JavaStation-1", len) == 0) {
 		/* Hardcoded values for MrCoffee.  */
 		i8042_kbd_irq = i8042_aux_irq = 13 | 0x20;
-		kbd_iobase = (unsigned long) ioremap(0x71300060, 8);
+		kbd_iobase = ioremap(0x71300060, 8);
 		if (!kbd_iobase)
 			return -1;
 	} else {
@@ -85,7 +85,7 @@
 			if (!strcmp(child->prom_name, OBP_PS2KBD_NAME1) ||
 			    !strcmp(child->prom_name, OBP_PS2KBD_NAME2)) {
 				i8042_kbd_irq = child->irqs[0];
-				kbd_iobase = (unsigned long)
+				kbd_iobase =
 					ioremap(child->resource[0].start, 8);
 			}
 			if (!strcmp(child->prom_name, OBP_PS2MS_NAME1) ||
@@ -109,7 +109,7 @@
 static inline void i8042_platform_exit(void)
 {
 #ifdef CONFIG_PCI
-	iounmap((void *)kbd_iobase);
+	iounmap(kbd_iobase);
 #endif
 }
 
diff -Nru a/drivers/input/serio/i8042.c b/drivers/input/serio/i8042.c
--- a/drivers/input/serio/i8042.c	2004-10-18 14:55:54 -07:00
+++ b/drivers/input/serio/i8042.c	2004-10-18 14:55:54 -07:00
@@ -1,7 +1,7 @@
 /*
  *  i8042 keyboard and mouse controller driver for Linux
  *
- *  Copyright (c) 1999-2002 Vojtech Pavlik
+ *  Copyright (c) 1999-2004 Vojtech Pavlik
  */
 
 /*
@@ -21,6 +21,7 @@
 #include <linux/sysdev.h>
 #include <linux/pm.h>
 #include <linux/serio.h>
+#include <linux/err.h>
 
 #include <asm/io.h>
 
@@ -52,6 +53,10 @@
 module_param_named(dumbkbd, i8042_dumbkbd, bool, 0);
 MODULE_PARM_DESC(dumbkbd, "Pretend that controller can only read data from keyboard");
 
+static unsigned int i8042_noloop;
+module_param_named(noloop, i8042_noloop, bool, 0);
+MODULE_PARM_DESC(dumbkbd, "Disable the AUX Loopback command while probing for the AUX port");
+
 __obsolete_setup("i8042_noaux");
 __obsolete_setup("i8042_nomux");
 __obsolete_setup("i8042_unlock");
@@ -70,19 +75,35 @@
 	unsigned char irqen;
 	unsigned char exists;
 	signed char mux;
-	unsigned char *name;
-	unsigned char *phys;
+	char name[8];
+};
+
+static struct i8042_values i8042_kbd_values = {
+	.disable	= I8042_CTR_KBDDIS,
+	.irqen 		= I8042_CTR_KBDINT,
+	.mux		= -1,
+	.name		= "KBD",
+};
+
+static struct i8042_values i8042_aux_values = {
+	.disable	= I8042_CTR_AUXDIS,
+	.irqen		= I8042_CTR_AUXINT,
+	.mux		= -1,
+	.name		= "AUX",
 };
 
-static struct serio i8042_kbd_port;
-static struct serio i8042_aux_port;
+static struct i8042_values i8042_mux_values[I8042_NUM_MUX_PORTS];
+
+static struct serio *i8042_kbd_port;
+static struct serio *i8042_aux_port;
+static struct serio *i8042_mux_port[I8042_NUM_MUX_PORTS];
 static unsigned char i8042_initial_ctr;
 static unsigned char i8042_ctr;
 static unsigned char i8042_mux_open;
 static unsigned char i8042_mux_present;
-static unsigned char i8042_sysdev_initialized;
 static struct pm_dev *i8042_pm_dev;
-struct timer_list i8042_timer;
+static struct timer_list i8042_timer;
+static struct platform_device *i8042_platform_device;
 
 /*
  * Shared IRQ's require a device pointer, but this driver doesn't support
@@ -95,6 +116,7 @@
 /*
  * The i8042_wait_read() and i8042_wait_write functions wait for the i8042 to
  * be ready for reading values from it / writing values to it.
+ * Called always with i8042_lock held.
  */
 
 static int i8042_wait_read(void)
@@ -131,6 +153,7 @@
 	spin_lock_irqsave(&i8042_lock, flags);
 
 	while ((i8042_read_status() & I8042_STR_OBF) && (i++ < I8042_BUFFER_SIZE)) {
+		udelay(50);
 		data = i8042_read_data();
 		dbg("%02x <- i8042 (flush, %s)", data,
 			i8042_read_status() & I8042_STR_AUXDATA ? "aux" : "kbd");
@@ -154,6 +177,9 @@
 	unsigned long flags;
 	int retval = 0, i = 0;
 
+	if (i8042_noloop && command == I8042_CMD_AUX_LOOP)
+		return -1;
+
 	spin_lock_irqsave(&i8042_lock, flags);
 
 	retval = i8042_wait_write();
@@ -214,7 +240,7 @@
 
 static int i8042_aux_write(struct serio *port, unsigned char c)
 {
-	struct i8042_values *values = port->driver;
+	struct i8042_values *values = port->port_data;
 	int retval;
 
 /*
@@ -242,7 +268,7 @@
 
 static int i8042_activate_port(struct serio *port)
 {
-	struct i8042_values *values = port->driver;
+	struct i8042_values *values = port->port_data;
 
 	i8042_flush();
 
@@ -270,7 +296,7 @@
 
 static int i8042_open(struct serio *port)
 {
-	struct i8042_values *values = port->driver;
+	struct i8042_values *values = port->port_data;
 
 	if (values->mux != -1)
 		if (i8042_mux_open++)
@@ -309,7 +335,7 @@
 
 static void i8042_close(struct serio *port)
 {
-	struct i8042_values *values = port->driver;
+	struct i8042_values *values = port->port_data;
 
 	if (values->mux != -1)
 		if (--i8042_mux_open)
@@ -328,52 +354,6 @@
 }
 
 /*
- * Structures for registering the devices in the serio.c module.
- */
-
-static struct i8042_values i8042_kbd_values = {
-	.irqen =	I8042_CTR_KBDINT,
-	.disable =	I8042_CTR_KBDDIS,
-	.name =		"KBD",
-	.mux =		-1,
-};
-
-static struct serio i8042_kbd_port =
-{
-	.type =		SERIO_8042_XL,
-	.write =	i8042_kbd_write,
-	.open =		i8042_open,
-	.close =	i8042_close,
-	.driver =	&i8042_kbd_values,
-	.name =		"i8042 Kbd Port",
-	.phys =		I8042_KBD_PHYS_DESC,
-};
-
-static struct i8042_values i8042_aux_values = {
-	.irqen =	I8042_CTR_AUXINT,
-	.disable =	I8042_CTR_AUXDIS,
-	.name =		"AUX",
-	.mux =		-1,
-};
-
-static struct serio i8042_aux_port =
-{
-	.type =		SERIO_8042,
-	.write =	i8042_aux_write,
-	.open =		i8042_open,
-	.close =	i8042_close,
-	.driver =	&i8042_aux_values,
-	.name =		"i8042 Aux Port",
-	.phys =		I8042_AUX_PHYS_DESC,
-};
-
-static struct i8042_values i8042_mux_values[4];
-static struct serio i8042_mux_port[4];
-static char i8042_mux_names[4][32];
-static char i8042_mux_short[4][16];
-static char i8042_mux_phys[4][32];
-
-/*
  * i8042_interrupt() is the most important function in this driver -
  * it handles the interrupts from the i8042, and sends incoming bytes
  * to the upper layers.
@@ -384,6 +364,7 @@
 	unsigned long flags;
 	unsigned char str, data = 0;
 	unsigned int dfl;
+	unsigned int aux_idx;
 	int ret;
 
 	mod_timer(&i8042_timer, jiffies + I8042_POLL_PERIOD);
@@ -400,44 +381,67 @@
 		goto out;
 	}
 
-	dfl = ((str & I8042_STR_PARITY) ? SERIO_PARITY : 0) |
-	      ((str & I8042_STR_TIMEOUT) ? SERIO_TIMEOUT : 0);
-
-	if (i8042_mux_values[0].exists && (str & I8042_STR_AUXDATA)) {
+	if (i8042_mux_present && (str & I8042_STR_AUXDATA)) {
+		static unsigned long last_transmit;
+		static unsigned char last_str;
 
+		dfl = 0;
 		if (str & I8042_STR_MUXERR) {
+			dbg("MUX error, status is %02x, data is %02x", str, data);
 			switch (data) {
+				default:
+/*
+ * When MUXERR condition is signalled the data register can only contain
+ * 0xfd, 0xfe or 0xff if implementation follows the spec. Unfortunately
+ * it is not always the case. Some KBC just get confused which port the
+ * data came from and signal error leaving the data intact. They _do not_
+ * revert to legacy mode (actually I've never seen KBC reverting to legacy
+ * mode yet, when we see one we'll add proper handling).
+ * Anyway, we will assume that the data came from the same serio last byte
+ * was transmitted (if transmission happened not too long ago).
+ */
+					if (time_before(jiffies, last_transmit + HZ/10)) {
+						str = last_str;
+						break;
+					}
+					/* fall through - report timeout */
 				case 0xfd:
-				case 0xfe: dfl = SERIO_TIMEOUT; break;
-				case 0xff: dfl = SERIO_PARITY; break;
+				case 0xfe: dfl = SERIO_TIMEOUT; data = 0xfe; break;
+				case 0xff: dfl = SERIO_PARITY;  data = 0xfe; break;
 			}
-			data = 0xfe;
-		} else dfl = 0;
+		}
+
+		aux_idx = (str >> 6) & 3;
 
 		dbg("%02x <- i8042 (interrupt, aux%d, %d%s%s)",
-			data, (str >> 6), irq,
+			data, aux_idx, irq,
 			dfl & SERIO_PARITY ? ", bad parity" : "",
 			dfl & SERIO_TIMEOUT ? ", timeout" : "");
 
-		serio_interrupt(i8042_mux_port + ((str >> 6) & 3), data, dfl, regs);
+		if (likely(i8042_mux_values[aux_idx].exists))
+			serio_interrupt(i8042_mux_port[aux_idx], data, dfl, regs);
 
+		last_str = str;
+		last_transmit = jiffies;
 		goto irq_ret;
 	}
 
+	dfl = ((str & I8042_STR_PARITY) ? SERIO_PARITY : 0) |
+	      ((str & I8042_STR_TIMEOUT) ? SERIO_TIMEOUT : 0);
+
 	dbg("%02x <- i8042 (interrupt, %s, %d%s%s)",
 		data, (str & I8042_STR_AUXDATA) ? "aux" : "kbd", irq,
 		dfl & SERIO_PARITY ? ", bad parity" : "",
 		dfl & SERIO_TIMEOUT ? ", timeout" : "");
 
-	if (i8042_aux_values.exists && (str & I8042_STR_AUXDATA)) {
-		serio_interrupt(&i8042_aux_port, data, dfl, regs);
-		goto irq_ret;
-	}
-
-	if (!i8042_kbd_values.exists)
-		goto irq_ret;
 
-	serio_interrupt(&i8042_kbd_port, data, dfl, regs);
+	if (str & I8042_STR_AUXDATA) {
+		if (likely(i8042_aux_values.exists))
+			serio_interrupt(i8042_aux_port, data, dfl, regs);
+	} else {
+		if (likely(i8042_kbd_values.exists))
+			serio_interrupt(i8042_kbd_port, data, dfl, regs);
+	}
 
 irq_ret:
 	ret = 1;
@@ -474,17 +478,8 @@
 	if (i8042_command(&param, I8042_CMD_AUX_LOOP) || param != 0xa9)
 		return -1;
 	param = 0xa4;
-	if (i8042_command(&param, I8042_CMD_AUX_LOOP) || param == 0x5b) {
-
-/*
- * Do another loop test with the 0x5a value. Doing anything else upsets
- * Profusion/ServerWorks OSB4 chipsets.
- */
-
-		param = 0x5a;
-		i8042_command(&param, I8042_CMD_AUX_LOOP);
+	if (i8042_command(&param, I8042_CMD_AUX_LOOP) || param == 0x5b)
 		return -1;
-	}
 
 	if (mux_version)
 		*mux_version = ~param;
@@ -639,8 +634,10 @@
  * registers it, and reports to the user.
  */
 
-static int __init i8042_port_register(struct i8042_values *values, struct serio *port)
+static int __init i8042_port_register(struct serio *port)
 {
+	struct i8042_values *values = port->port_data;
+
 	values->exists = 1;
 
 	i8042_ctr &= ~values->disable;
@@ -677,6 +674,7 @@
 
 static int i8042_controller_init(void)
 {
+	unsigned long flags;
 
 /*
  * Test the i8042. We need to know if it thinks it's working correctly
@@ -723,12 +721,14 @@
  * Handle keylock.
  */
 
+	spin_lock_irqsave(&i8042_lock, flags);
 	if (~i8042_read_status() & I8042_STR_KEYLOCK) {
 		if (i8042_unlock)
 			i8042_ctr |= I8042_CTR_IGNKEYLOCK;
 		 else
 			printk(KERN_WARNING "i8042.c: Warning: Keylock active.\n");
 	}
+	spin_unlock_irqrestore(&i8042_lock, flags);
 
 /*
  * If the chip is configured into nontranslated mode by the BIOS, don't
@@ -745,10 +745,8 @@
  * BIOSes.
  */
 
-	if (i8042_direct) {
+	if (i8042_direct)
 		i8042_ctr &= ~I8042_CTR_XLATE;
-		i8042_kbd_port.type = SERIO_8042;
-	}
 
 /*
  * Write CTR back.
@@ -802,14 +800,14 @@
  */
 
 	if (i8042_kbd_values.exists)
-		serio_cleanup(&i8042_kbd_port);
+		serio_cleanup(i8042_kbd_port);
 
 	if (i8042_aux_values.exists)
-		serio_cleanup(&i8042_aux_port);
+		serio_cleanup(i8042_aux_port);
 
-	for (i = 0; i < 4; i++)
+	for (i = 0; i < I8042_NUM_MUX_PORTS; i++)
 		if (i8042_mux_values[i].exists)
-			serio_cleanup(i8042_mux_port + i);
+			serio_cleanup(i8042_mux_port[i]);
 
 	i8042_controller_reset();
 }
@@ -851,15 +849,15 @@
  * Reconnect anything that was connected to the ports.
  */
 
-	if (i8042_kbd_values.exists && i8042_activate_port(&i8042_kbd_port) == 0)
-		serio_reconnect(&i8042_kbd_port);
+	if (i8042_kbd_values.exists && i8042_activate_port(i8042_kbd_port) == 0)
+		serio_reconnect(i8042_kbd_port);
 
-	if (i8042_aux_values.exists && i8042_activate_port(&i8042_aux_port) == 0)
-		serio_reconnect(&i8042_aux_port);
+	if (i8042_aux_values.exists && i8042_activate_port(i8042_aux_port) == 0)
+		serio_reconnect(i8042_aux_port);
 
-	for (i = 0; i < 4; i++)
-		if (i8042_mux_values[i].exists && i8042_activate_port(i8042_mux_port + i) == 0)
-			serio_reconnect(i8042_mux_port + i);
+	for (i = 0; i < I8042_NUM_MUX_PORTS; i++)
+		if (i8042_mux_values[i].exists && i8042_activate_port(i8042_mux_port[i]) == 0)
+			serio_reconnect(i8042_mux_port[i]);
 /*
  * Restart timer (for polling "stuck" data)
  */
@@ -882,7 +880,7 @@
         return NOTIFY_DONE;
 }
 
-static struct notifier_block i8042_notifier=
+static struct notifier_block i8042_notifier =
 {
         i8042_notify_sys,
         NULL,
@@ -892,25 +890,27 @@
 /*
  * Suspend/resume handlers for the new PM scheme (driver model)
  */
-static int i8042_suspend(struct sys_device *dev, u32 state)
+static int i8042_suspend(struct device *dev, u32 state, u32 level)
 {
-	return i8042_controller_suspend();
+	return level == SUSPEND_DISABLE ? i8042_controller_suspend() : 0;
 }
 
-static int i8042_resume(struct sys_device *dev)
+static int i8042_resume(struct device *dev, u32 level)
 {
-	return i8042_controller_resume();
+	return level == RESUME_ENABLE ? i8042_controller_resume() : 0;
 }
 
-static struct sysdev_class kbc_sysclass = {
-	set_kset_name("i8042"),
-	.suspend = i8042_suspend,
-	.resume = i8042_resume,
-};
+static void i8042_shutdown(struct device *dev)
+{
+	i8042_controller_cleanup();
+}
 
-static struct sys_device device_i8042 = {
-       .id     = 0,
-       .cls    = &kbc_sysclass,
+static struct device_driver i8042_driver = {
+	.name		= "i8042",
+	.bus		= &platform_bus_type,
+	.suspend	= i8042_suspend,
+	.resume		= i8042_resume,
+	.shutdown	= i8042_shutdown,
 };
 
 /*
@@ -929,23 +929,75 @@
 	return 0;
 }
 
-static void __init i8042_init_mux_values(struct i8042_values *values, struct serio *port, int index)
+static struct serio * __init i8042_allocate_kbd_port(void)
 {
-	memcpy(port, &i8042_aux_port, sizeof(struct serio));
-	memcpy(values, &i8042_aux_values, sizeof(struct i8042_values));
-	sprintf(i8042_mux_names[index], "i8042 Aux-%d Port", index);
-	sprintf(i8042_mux_phys[index], I8042_MUX_PHYS_DESC, index + 1);
-	sprintf(i8042_mux_short[index], "AUX%d", index);
-	port->name = i8042_mux_names[index];
-	port->phys = i8042_mux_phys[index];
-	port->driver = values;
-	values->name = i8042_mux_short[index];
-	values->mux = index;
+	struct serio *serio;
+
+	serio = kmalloc(sizeof(struct serio), GFP_KERNEL);
+	if (serio) {
+		memset(serio, 0, sizeof(struct serio));
+		serio->type		= i8042_direct ? SERIO_8042 : SERIO_8042_XL,
+		serio->write		= i8042_dumbkbd ? NULL : i8042_kbd_write,
+		serio->open		= i8042_open,
+		serio->close		= i8042_close,
+		serio->port_data	= &i8042_kbd_values,
+		serio->dev.parent	= &i8042_platform_device->dev;
+		strlcpy(serio->name, "i8042 Kbd Port", sizeof(serio->name));
+		strlcpy(serio->phys, I8042_KBD_PHYS_DESC, sizeof(serio->phys));
+	}
+
+	return serio;
+}
+
+static struct serio * __init i8042_allocate_aux_port(void)
+{
+	struct serio *serio;
+
+	serio = kmalloc(sizeof(struct serio), GFP_KERNEL);
+	if (serio) {
+		memset(serio, 0, sizeof(struct serio));
+		serio->type		= SERIO_8042;
+		serio->write		= i8042_aux_write;
+		serio->open		= i8042_open;
+		serio->close		= i8042_close;
+		serio->port_data	= &i8042_aux_values,
+		serio->dev.parent	= &i8042_platform_device->dev;
+		strlcpy(serio->name, "i8042 Aux Port", sizeof(serio->name));
+		strlcpy(serio->phys, I8042_AUX_PHYS_DESC, sizeof(serio->phys));
+	}
+
+	return serio;
+}
+
+static struct serio * __init i8042_allocate_mux_port(int index)
+{
+	struct serio *serio;
+	struct i8042_values *values = &i8042_mux_values[index];
+
+	serio = kmalloc(sizeof(struct serio), GFP_KERNEL);
+	if (serio) {
+		*values = i8042_aux_values;
+		snprintf(values->name, sizeof(values->name), "AUX%d", index);
+		values->mux = index;
+
+		memset(serio, 0, sizeof(struct serio));
+		serio->type		= SERIO_8042;
+		serio->write		= i8042_aux_write;
+		serio->open		= i8042_open;
+		serio->close		= i8042_close;
+		serio->port_data	= values;
+		serio->dev.parent	= &i8042_platform_device->dev;
+		snprintf(serio->name, sizeof(serio->name), "i8042 Aux-%d Port", index);
+		snprintf(serio->phys, sizeof(serio->phys), I8042_MUX_PHYS_DESC, index + 1);
+	}
+
+	return serio;
 }
 
 int __init i8042_init(void)
 {
 	int i;
+	int err;
 
 	dbg_init();
 
@@ -961,30 +1013,36 @@
 	if (i8042_controller_init())
 		return -ENODEV;
 
-	if (i8042_dumbkbd)
-		i8042_kbd_port.write = NULL;
+	err = driver_register(&i8042_driver);
+	if (err)
+		return err;
+
+	i8042_platform_device = platform_device_register_simple("i8042", -1, NULL, 0);
+	if (IS_ERR(i8042_platform_device)) {
+		driver_unregister(&i8042_driver);
+		return PTR_ERR(i8042_platform_device);
+	}
 
 	if (!i8042_noaux && !i8042_check_aux(&i8042_aux_values)) {
 		if (!i8042_nomux && !i8042_check_mux(&i8042_aux_values))
-			for (i = 0; i < 4; i++) {
-				i8042_init_mux_values(i8042_mux_values + i, i8042_mux_port + i, i);
-				i8042_port_register(i8042_mux_values + i, i8042_mux_port + i);
+			for (i = 0; i < I8042_NUM_MUX_PORTS; i++) {
+				i8042_mux_port[i] = i8042_allocate_mux_port(i);
+				if (i8042_mux_port[i])
+					i8042_port_register(i8042_mux_port[i]);
 			}
-		else
-			i8042_port_register(&i8042_aux_values, &i8042_aux_port);
+		else {
+			i8042_aux_port = i8042_allocate_aux_port();
+			if (i8042_aux_port)
+				i8042_port_register(i8042_aux_port);
+		}
 	}
 
-	i8042_port_register(&i8042_kbd_values, &i8042_kbd_port);
+	i8042_kbd_port = i8042_allocate_kbd_port();
+	if (i8042_kbd_port)
+		i8042_port_register(i8042_kbd_port);
 
 	mod_timer(&i8042_timer, jiffies + I8042_POLL_PERIOD);
 
-        if (sysdev_class_register(&kbc_sysclass) == 0) {
-                if (sysdev_register(&device_i8042) == 0)
-			i8042_sysdev_initialized = 1;
-		else
-			sysdev_class_unregister(&kbc_sysclass);
-        }
-
 	i8042_pm_dev = pm_register(PM_SYS_DEV, PM_SYS_UNKNOWN, i8042_pm_callback);
 
 	register_reboot_notifier(&i8042_notifier);
@@ -1001,23 +1059,22 @@
 	if (i8042_pm_dev)
 		pm_unregister(i8042_pm_dev);
 
-	if (i8042_sysdev_initialized) {
-		sysdev_unregister(&device_i8042);
-		sysdev_class_unregister(&kbc_sysclass);
-	}
-
 	i8042_controller_cleanup();
 
 	if (i8042_kbd_values.exists)
-		serio_unregister_port(&i8042_kbd_port);
+		serio_unregister_port(i8042_kbd_port);
 
 	if (i8042_aux_values.exists)
-		serio_unregister_port(&i8042_aux_port);
+		serio_unregister_port(i8042_aux_port);
 
-	for (i = 0; i < 4; i++)
+	for (i = 0; i < I8042_NUM_MUX_PORTS; i++)
 		if (i8042_mux_values[i].exists)
-			serio_unregister_port(i8042_mux_port + i);
+			serio_unregister_port(i8042_mux_port[i]);
+
 	del_timer_sync(&i8042_timer);
+
+	platform_device_unregister(i8042_platform_device);
+	driver_unregister(&i8042_driver);
 
 	i8042_platform_exit();
 }
diff -Nru a/drivers/input/serio/i8042.h b/drivers/input/serio/i8042.h
--- a/drivers/input/serio/i8042.h	2004-10-18 14:56:49 -07:00
+++ b/drivers/input/serio/i8042.h	2004-10-18 14:56:49 -07:00
@@ -104,6 +104,13 @@
 #define I8042_BUFFER_SIZE	32
 
 /*
+ * Number of AUX ports on controllers supporting active multiplexing
+ * specification
+ */
+
+#define I8042_NUM_MUX_PORTS	4
+
+/*
  * Debug.
  */
 
diff -Nru a/drivers/input/serio/maceps2.c b/drivers/input/serio/maceps2.c
--- a/drivers/input/serio/maceps2.c	2004-10-18 14:56:28 -07:00
+++ b/drivers/input/serio/maceps2.c	2004-10-18 14:56:28 -07:00
@@ -17,6 +17,7 @@
 #include <linux/device.h>
 #include <linux/slab.h>
 #include <linux/spinlock.h>
+#include <linux/err.h>
 
 #include <asm/io.h>
 #include <asm/irq.h>
@@ -46,15 +47,18 @@
 #define PS2_CONTROL_RX_CLOCK_ENABLE  BIT(4) /* pause reception if set to 0 */
 #define PS2_CONTROL_RESET            BIT(5) /* reset */
 
-
 struct maceps2_data {
 	struct mace_ps2port *port;
 	int irq;
 };
 
+static struct maceps2_data port_data[2];
+static struct serio *maceps2_port[2];
+static struct platform_device *maceps2_device;
+
 static int maceps2_write(struct serio *dev, unsigned char val)
 {
-	struct mace_ps2port *port = ((struct maceps2_data *)dev->driver)->port;
+	struct mace_ps2port *port = ((struct maceps2_data *)dev->port_data)->port;
 	unsigned int timeout = MACE_PS2_TIMEOUT;
 
 	do {
@@ -68,11 +72,10 @@
 	return -1;
 }
 
-static irqreturn_t maceps2_interrupt(int irq, void *dev_id,
-				     struct pt_regs *regs)
+static irqreturn_t maceps2_interrupt(int irq, void *dev_id, struct pt_regs *regs)
 {
 	struct serio *dev = dev_id;
-	struct mace_ps2port *port = ((struct maceps2_data *)dev->driver)->port;
+	struct mace_ps2port *port = ((struct maceps2_data *)dev->port_data)->port;
 	unsigned int byte;
 
 	if (mace_read(port->status) & PS2_STATUS_RX_FULL) {
@@ -85,7 +88,7 @@
 
 static int maceps2_open(struct serio *dev)
 {
-	struct maceps2_data *data = (struct maceps2_data *)dev->driver;
+	struct maceps2_data *data = (struct maceps2_data *)dev->port_data;
 
 	if (request_irq(data->irq, maceps2_interrupt, 0, "PS/2 port", dev)) {
 		printk(KERN_ERR "Could not allocate PS/2 IRQ\n");
@@ -106,7 +109,7 @@
 
 static void maceps2_close(struct serio *dev)
 {
-	struct maceps2_data *data = (struct maceps2_data *)dev->driver;
+	struct maceps2_data *data = (struct maceps2_data *)dev->port_data;
 
 	mace_write(PS2_CONTROL_TX_CLOCK_DISABLE | PS2_CONTROL_RESET,
 		   data->port->control);
@@ -114,46 +117,59 @@
 	free_irq(data->irq, dev);
 }
 
-static struct maceps2_data port0_data, port1_data;
 
-static struct serio maceps2_port0 =
+static struct serio * __init maceps2_allocate_port(int idx)
 {
-	.type	= SERIO_8042,
-	.open	= maceps2_open,
-	.close	= maceps2_close,
-	.write	= maceps2_write,
-	.name	= "MACE PS/2 port0",
-	.phys	= "mace/serio0",
-	.driver = &port0_data,
-};
+	struct serio *serio;
+
+	serio = kmalloc(sizeof(struct serio), GFP_KERNEL);
+	if (serio) {
+		memset(serio, 0, sizeof(struct serio));
+		serio->type		= SERIO_8042;
+		serio->write		= maceps2_write;
+		serio->open		= maceps2_open;
+		serio->close		= maceps2_close;
+		snprintf(serio->name, sizeof(serio->name), "MACE PS/2 port%d", idx);
+		snprintf(serio->phys, sizeof(serio->phys), "mace/serio%d", idx);
+		serio->port_data	= &port_data[idx];
+		serio->dev.parent	= &maceps2_device->dev;
+	}
+
+	return serio;
+}
 
-static struct serio maceps2_port1 =
-{
-	.type	= SERIO_8042,
-	.open	= maceps2_open,
-	.close	= maceps2_close,
-	.write	= maceps2_write,
-	.name	= "MACE PS/2 port1",
-	.phys	= "mace/serio1",
-	.driver = &port1_data,
-};
 
 static int __init maceps2_init(void)
 {
-	port0_data.port = &mace->perif.ps2.keyb;
-	port0_data.irq  = MACEISA_KEYB_IRQ;
-	port1_data.port = &mace->perif.ps2.mouse;
-	port1_data.irq  = MACEISA_MOUSE_IRQ;
-	serio_register_port(&maceps2_port0);
-	serio_register_port(&maceps2_port1);
+	maceps2_device = platform_device_register_simple("maceps2", -1, NULL, 0);
+	if (IS_ERR(maceps2_device))
+		return PTR_ERR(maceps2_device);
+
+	port_data[0].port = &mace->perif.ps2.keyb;
+	port_data[0].irq  = MACEISA_KEYB_IRQ;
+	port_data[1].port = &mace->perif.ps2.mouse;
+	port_data[1].irq  = MACEISA_MOUSE_IRQ;
+
+	maceps2_port[0] = maceps2_allocate_port(0);
+	maceps2_port[1] = maceps2_allocate_port(1);
+	if (!maceps2_port[0] || !maceps2_port[1]) {
+		kfree(maceps2_port[0]);
+		kfree(maceps2_port[1]);
+		platform_device_unregister(maceps2_device);
+		return -ENOMEM;
+	}
+
+	serio_register_port(maceps2_port[0]);
+	serio_register_port(maceps2_port[1]);
 
 	return 0;
 }
 
 static void __exit maceps2_exit(void)
 {
-	serio_unregister_port(&maceps2_port0);
-	serio_unregister_port(&maceps2_port1);
+	serio_unregister_port(maceps2_port[0]);
+	serio_unregister_port(maceps2_port[1]);
+	platform_device_unregister(maceps2_device);
 }
 
 module_init(maceps2_init);
diff -Nru a/drivers/input/serio/parkbd.c b/drivers/input/serio/parkbd.c
--- a/drivers/input/serio/parkbd.c	2004-10-18 14:55:54 -07:00
+++ b/drivers/input/serio/parkbd.c	2004-10-18 14:55:54 -07:00
@@ -53,9 +53,7 @@
 static unsigned long parkbd_start;
 
 static struct pardevice *parkbd_dev;
-
-static char parkbd_name[] = "PARKBD AT/XT keyboard adapter";
-static char parkbd_phys[32];
+static struct serio *parkbd_port;
 
 static int parkbd_readlines(void)
 {
@@ -86,13 +84,6 @@
 	return 0;
 }
 
-static struct serio parkbd_port =
-{
-	.write	= parkbd_write,
-	.name	= parkbd_name,
-	.phys	= parkbd_phys,
-};
-
 static void parkbd_interrupt(int irq, void *dev_id, struct pt_regs *regs)
 {
 
@@ -125,7 +116,7 @@
 		parkbd_buffer |= (parkbd_readlines() >> 1) << parkbd_counter++;
 
 		if (parkbd_counter == parkbd_mode + 10)
-			serio_interrupt(&parkbd_port, (parkbd_buffer >> (2 - parkbd_mode)) & 0xff, 0, regs);
+			serio_interrupt(parkbd_port, (parkbd_buffer >> (2 - parkbd_mode)) & 0xff, 0, regs);
 	}
 
 	parkbd_last = jiffies;
@@ -163,16 +154,39 @@
 	return 0;
 }
 
+static struct serio * __init parkbd_allocate_serio(void)
+{
+	struct serio *serio;
+
+	serio = kmalloc(sizeof(struct serio), GFP_KERNEL);
+	if (serio) {
+		memset(serio, 0, sizeof(struct serio));
+		serio->type = parkbd_mode;
+		serio->write = parkbd_write,
+		strlcpy(serio->name, "PARKBD AT/XT keyboard adapter", sizeof(serio->name));
+		snprintf(serio->phys, sizeof(serio->phys), "%s/serio0", parkbd_dev->port->name);
+	}
+
+	return serio;
+}
 
 int __init parkbd_init(void)
 {
-	if (parkbd_getport()) return -1;
-	parkbd_writelines(3);
-	parkbd_port.type = parkbd_mode;
+	int err;
 
-	sprintf(parkbd_phys, "%s/serio0", parkbd_dev->port->name);
+	err = parkbd_getport();
+	if (err)
+		return err;
+
+	parkbd_port = parkbd_allocate_serio();
+	if (!parkbd_port) {
+		parport_release(parkbd_dev);
+		return -ENOMEM;
+	}
+
+	parkbd_writelines(3);
 
-	serio_register_port(&parkbd_port);
+	serio_register_port(parkbd_port);
 
 	printk(KERN_INFO "serio: PARKBD %s adapter on %s\n",
                         parkbd_mode ? "AT" : "XT", parkbd_dev->port->name);
@@ -183,7 +197,7 @@
 void __exit parkbd_exit(void)
 {
 	parport_release(parkbd_dev);
-	serio_unregister_port(&parkbd_port);
+	serio_unregister_port(parkbd_port);
 	parport_unregister_device(parkbd_dev);
 }
 
diff -Nru a/drivers/input/serio/pcips2.c b/drivers/input/serio/pcips2.c
--- a/drivers/input/serio/pcips2.c	2004-10-18 14:56:17 -07:00
+++ b/drivers/input/serio/pcips2.c	2004-10-18 14:56:17 -07:00
@@ -38,14 +38,14 @@
 #define PS2_STAT_TXEMPTY	(1<<7)
 
 struct pcips2_data {
-	struct serio	io;
+	struct serio	*io;
 	unsigned int	base;
 	struct pci_dev	*dev;
 };
 
 static int pcips2_write(struct serio *io, unsigned char val)
 {
-	struct pcips2_data *ps2if = io->driver;
+	struct pcips2_data *ps2if = io->port_data;
 	unsigned int stat;
 
 	do {
@@ -80,7 +80,7 @@
 		if (hweight8(scancode) & 1)
 			flag ^= SERIO_PARITY;
 
-		serio_interrupt(&ps2if->io, scancode, flag, regs);
+		serio_interrupt(ps2if->io, scancode, flag, regs);
 	} while (1);
 	return IRQ_RETVAL(handled);
 }
@@ -101,7 +101,7 @@
 
 static int pcips2_open(struct serio *io)
 {
-	struct pcips2_data *ps2if = io->driver;
+	struct pcips2_data *ps2if = io->port_data;
 	int ret, val = 0;
 
 	outb(PS2_CTRL_ENABLE, ps2if->base);
@@ -119,7 +119,7 @@
 
 static void pcips2_close(struct serio *io)
 {
-	struct pcips2_data *ps2if = io->driver;
+	struct pcips2_data *ps2if = io->port_data;
 
 	outb(0, ps2if->base);
 
@@ -129,46 +129,51 @@
 static int __devinit pcips2_probe(struct pci_dev *dev, const struct pci_device_id *id)
 {
 	struct pcips2_data *ps2if;
+	struct serio *serio;
 	int ret;
 
 	ret = pci_enable_device(dev);
 	if (ret)
-		return ret;
+		goto out;
 
-	if (!request_region(pci_resource_start(dev, 0),
-			    pci_resource_len(dev, 0), "pcips2")) {
-		ret = -EBUSY;
+	ret = pci_request_regions(dev, "pcips2");
+	if (ret)
 		goto disable;
-	}
 
 	ps2if = kmalloc(sizeof(struct pcips2_data), GFP_KERNEL);
-	if (!ps2if) {
+	serio = kmalloc(sizeof(struct serio), GFP_KERNEL);
+	if (!ps2if || !serio) {
 		ret = -ENOMEM;
 		goto release;
 	}
 
 	memset(ps2if, 0, sizeof(struct pcips2_data));
+	memset(serio, 0, sizeof(struct serio));
 
-	ps2if->io.type		= SERIO_8042;
-	ps2if->io.write		= pcips2_write;
-	ps2if->io.open		= pcips2_open;
-	ps2if->io.close		= pcips2_close;
-	ps2if->io.name		= pci_name(dev);
-	ps2if->io.phys		= dev->dev.bus_id;
-	ps2if->io.driver	= ps2if;
+	serio->type		= SERIO_8042;
+	serio->write		= pcips2_write;
+	serio->open		= pcips2_open;
+	serio->close		= pcips2_close;
+	strlcpy(serio->name, pci_name(dev), sizeof(serio->name));
+	strlcpy(serio->phys, dev->dev.bus_id, sizeof(serio->phys));
+	serio->port_data	= ps2if;
+	serio->dev.parent	= &dev->dev;
+	ps2if->io		= serio;
 	ps2if->dev		= dev;
 	ps2if->base		= pci_resource_start(dev, 0);
 
 	pci_set_drvdata(dev, ps2if);
 
-	serio_register_port(&ps2if->io);
+	serio_register_port(ps2if->io);
 	return 0;
 
  release:
-	release_region(pci_resource_start(dev, 0),
-		       pci_resource_len(dev, 0));
+	kfree(ps2if);
+	kfree(serio);
+	pci_release_regions(dev);
  disable:
 	pci_disable_device(dev);
+ out:
 	return ret;
 }
 
@@ -176,11 +181,10 @@
 {
 	struct pcips2_data *ps2if = pci_get_drvdata(dev);
 
-	serio_unregister_port(&ps2if->io);
-	release_region(pci_resource_start(dev, 0),
-		       pci_resource_len(dev, 0));
+	serio_unregister_port(ps2if->io);
 	pci_set_drvdata(dev, NULL);
 	kfree(ps2if);
+	pci_release_regions(dev);
 	pci_disable_device(dev);
 }
 
diff -Nru a/drivers/input/serio/q40kbd.c b/drivers/input/serio/q40kbd.c
--- a/drivers/input/serio/q40kbd.c	2004-10-18 14:56:27 -07:00
+++ b/drivers/input/serio/q40kbd.c	2004-10-18 14:56:27 -07:00
@@ -35,6 +35,7 @@
 #include <linux/init.h>
 #include <linux/serio.h>
 #include <linux/interrupt.h>
+#include <linux/err.h>
 
 #include <asm/bitops.h>
 #include <asm/io.h>
@@ -47,43 +48,106 @@
 MODULE_DESCRIPTION("Q40 PS/2 keyboard controller driver");
 MODULE_LICENSE("GPL");
 
-static struct serio q40kbd_port =
-{
-	.type	= SERIO_8042,
-	.name	= "Q40 kbd port",
-	.phys	= "Q40",
-	.write	= NULL,
-};
+spinlock_t q40kbd_lock = SPIN_LOCK_UNLOCKED;
+static struct serio *q40kbd_port;
+static struct platform_device *q40kbd_device;
 
-static irqreturn_t q40kbd_interrupt(int irq, void *dev_id,
-				    struct pt_regs *regs)
+static irqreturn_t q40kbd_interrupt(int irq, void *dev_id, struct pt_regs *regs)
 {
+	unsigned long flags;
+
+	spin_lock_irqsave(&q40kbd_lock, flags);
+
 	if (Q40_IRQ_KEYB_MASK & master_inb(INTERRUPT_REG))
-		serio_interrupt(&q40kbd_port, master_inb(KEYCODE_REG), 0, regs);
+		serio_interrupt(q40kbd_port, master_inb(KEYCODE_REG), 0, regs);
 
 	master_outb(-1, KEYBOARD_UNLOCK_REG);
+
+	spin_unlock_irqrestore(&q40kbd_lock, flags);
+
 	return IRQ_HANDLED;
 }
 
-static int __init q40kbd_init(void)
+/*
+ * q40kbd_flush() flushes all data that may be in the keyboard buffers
+ */
+
+static void q40kbd_flush(void)
 {
-	int maxread = 100;
+ 	int maxread = 100;
+	unsigned long flags;
+
+	spin_lock_irqsave(&q40kbd_lock, flags);
+
+ 	while (maxread-- && (Q40_IRQ_KEYB_MASK & master_inb(INTERRUPT_REG)))
+ 		master_inb(KEYCODE_REG);
+
+	spin_unlock_irqrestore(&q40kbd_lock, flags);
+}
+
+/*
+ * q40kbd_open() is called when a port is open by the higher layer.
+ * It allocates the interrupt and enables in in the chip.
+ */
+
+static int q40kbd_open(struct serio *port)
+{
+	q40kbd_flush();
+
+	if (request_irq(Q40_IRQ_KEYBOARD, q40kbd_interrupt, 0, "q40kbd", NULL)) {
+		printk(KERN_ERR "q40kbd.c: Can't get irq %d.\n", Q40_IRQ_KEYBOARD);
+		return -1;
+	}
+
+ 	/* off we go */
+ 	master_outb(-1, KEYBOARD_UNLOCK_REG);
+ 	master_outb(1, KEY_IRQ_ENABLE_REG);
+
+ 	return 0;
+}
 
+static void q40kbd_close(struct serio *port)
+{
+	master_outb(0, KEY_IRQ_ENABLE_REG);
+	master_outb(-1, KEYBOARD_UNLOCK_REG);
+	free_irq(Q40_IRQ_KEYBOARD, NULL);
+
+	q40kbd_flush();
+}
+
+static struct serio * __init q40kbd_allocate_port(void)
+{
+	struct serio *serio;
+
+	serio = kmalloc(sizeof(struct serio), GFP_KERNEL);
+	if (serio) {
+		memset(serio, 0, sizeof(struct serio));
+		serio->type		= SERIO_8042;
+		serio->open		= q40kbd_open;
+		serio->close		= q40kbd_close;
+		serio->dev.parent	= &q40kbd_device->dev;
+		strlcpy(serio->name, "Q40 Kbd Port", sizeof(serio->name));
+		strlcpy(serio->phys, "Q40", sizeof(serio->phys));
+	}
+
+	return serio;
+}
+
+static int __init q40kbd_init(void)
+{
 	if (!MACH_IS_Q40)
 		return -EIO;
 
-	/* allocate the IRQ */
-	request_irq(Q40_IRQ_KEYBOARD, q40kbd_interrupt, 0, "q40kbd", NULL);
-
-	/* flush any pending input */
-	while (maxread-- && (Q40_IRQ_KEYB_MASK & master_inb(INTERRUPT_REG)))
-		master_inb(KEYCODE_REG);
-
-	/* off we go */
-	master_outb(-1,KEYBOARD_UNLOCK_REG);
-	master_outb(1,KEY_IRQ_ENABLE_REG);
+	q40kbd_device = platform_device_register_simple("q40kbd", -1, NULL, 0);
+	if (IS_ERR(q40kbd_device))
+		return PTR_ERR(q40kbd_device);
+
+	if (!(q40kbd_port = q40kbd_allocate_port())) {
+		platform_device_unregister(q40kbd_device);
+		return -ENOMEM;
+	}
 
-	serio_register_port(&q40kbd_port);
+	serio_register_port(q40kbd_port);
 	printk(KERN_INFO "serio: Q40 kbd registered\n");
 
 	return 0;
@@ -91,11 +155,8 @@
 
 static void __exit q40kbd_exit(void)
 {
-	master_outb(0,KEY_IRQ_ENABLE_REG);
-	master_outb(-1,KEYBOARD_UNLOCK_REG);
-
-	serio_unregister_port(&q40kbd_port);
-	free_irq(Q40_IRQ_KEYBOARD, NULL);
+	serio_unregister_port(q40kbd_port);
+	platform_device_unregister(q40kbd_device);
 }
 
 module_init(q40kbd_init);
diff -Nru a/drivers/input/serio/rpckbd.c b/drivers/input/serio/rpckbd.c
--- a/drivers/input/serio/rpckbd.c	2004-10-18 14:55:54 -07:00
+++ b/drivers/input/serio/rpckbd.c	2004-10-18 14:55:54 -07:00
@@ -33,6 +33,7 @@
 #include <linux/interrupt.h>
 #include <linux/init.h>
 #include <linux/serio.h>
+#include <linux/err.h>
 
 #include <asm/irq.h>
 #include <asm/hardware.h>
@@ -44,6 +45,9 @@
 MODULE_DESCRIPTION("Acorn RiscPC PS/2 keyboard controller driver");
 MODULE_LICENSE("GPL");
 
+static struct serio *rpckbd_port;
+static struct platform_device *rpckbd_device;
+
 static int rpckbd_write(struct serio *port, unsigned char val)
 {
 	while (!(iomd_readb(IOMD_KCTRL) & (1 << 7)))
@@ -101,25 +105,49 @@
 	free_irq(IRQ_KEYBOARDTX, port);
 }
 
-static struct serio rpckbd_port =
-{
-	.type	= SERIO_8042,
-	.open	= rpckbd_open,
-	.close	= rpckbd_close,
-	.write	= rpckbd_write,
-	.name	= "RiscPC PS/2 kbd port",
-	.phys	= "rpckbd/serio0",
-};
+/*
+ * Allocate and initialize serio structure for subsequent registration
+ * with serio core.
+ */
+
+static struct serio * __init rpckbd_allocate_port(void)
+{
+	struct serio *serio;
+
+	serio = kmalloc(sizeof(struct serio), GFP_KERNEL);
+	if (serio) {
+		memset(serio, 0, sizeof(struct serio));
+		serio->type		= SERIO_8042;
+		serio->write		= rpckbd_write;
+		serio->open		= rpckbd_open;
+		serio->close		= rpckbd_close;
+		serio->dev.parent	= &rpckbd_device->dev;
+		strlcpy(serio->name, "RiscPC PS/2 kbd port", sizeof(serio->name));
+		strlcpy(serio->phys, "rpckbd/serio0", sizeof(serio->phys));
+	}
+
+	return serio;
+}
 
 static int __init rpckbd_init(void)
 {
-	serio_register_port(&rpckbd_port);
+	rpckbd_device = platform_device_register_simple("rpckbd", -1, NULL, 0);
+	if (IS_ERR(rpckbd_device))
+		return PTR_ERR(rpckbd_device);
+
+	if (!(rpckbd_port = rpckbd_allocate_port())) {
+		platform_device_unregister(rpckbd_device);
+		return -ENOMEM;
+	}
+
+	serio_register_port(rpckbd_port);
 	return 0;
 }
 
 static void __exit rpckbd_exit(void)
 {
-	serio_unregister_port(&rpckbd_port);
+	serio_unregister_port(rpckbd_port);
+	platform_device_unregister(rpckbd_device);
 }
 
 module_init(rpckbd_init);
diff -Nru a/drivers/input/serio/sa1111ps2.c b/drivers/input/serio/sa1111ps2.c
--- a/drivers/input/serio/sa1111ps2.c	2004-10-18 14:56:31 -07:00
+++ b/drivers/input/serio/sa1111ps2.c	2004-10-18 14:56:31 -07:00
@@ -26,7 +26,7 @@
 #include <asm/hardware/sa1111.h>
 
 struct ps2if {
-	struct serio		io;
+	struct serio		*io;
 	struct sa1111_dev	*dev;
 	unsigned long		base;
 	unsigned int		open;
@@ -59,7 +59,7 @@
 		if (hweight8(scancode) & 1)
 			flag ^= SERIO_PARITY;
 
-		serio_interrupt(&ps2if->io, scancode, flag, regs);
+		serio_interrupt(ps2if->io, scancode, flag, regs);
 
 		status = sa1111_readl(ps2if->base + SA1111_PS2STAT);
         }
@@ -95,7 +95,7 @@
  */
 static int ps2_write(struct serio *io, unsigned char val)
 {
-	struct ps2if *ps2if = io->driver;
+	struct ps2if *ps2if = io->port_data;
 	unsigned long flags;
 	unsigned int head;
 
@@ -122,7 +122,7 @@
 
 static int ps2_open(struct serio *io)
 {
-	struct ps2if *ps2if = io->driver;
+	struct ps2if *ps2if = io->port_data;
 	int ret;
 
 	sa1111_enable_device(ps2if->dev);
@@ -154,7 +154,7 @@
 
 static void ps2_close(struct serio *io)
 {
-	struct ps2if *ps2if = io->driver;
+	struct ps2if *ps2if = io->port_data;
 
 	sa1111_writel(0, ps2if->base + SA1111_PS2CR);
 
@@ -232,22 +232,28 @@
 static int ps2_probe(struct sa1111_dev *dev)
 {
 	struct ps2if *ps2if;
+	struct serio *serio;
 	int ret;
 
 	ps2if = kmalloc(sizeof(struct ps2if), GFP_KERNEL);
-	if (!ps2if) {
-		return -ENOMEM;
+	serio = kmalloc(sizeof(struct serio), GFP_KERNEL);
+	if (!ps2if || !serio) {
+		ret = -ENOMEM;
+		goto free;
 	}
 
 	memset(ps2if, 0, sizeof(struct ps2if));
+	memset(serio, 0, sizeof(struct serio));
 
-	ps2if->io.type		= SERIO_8042;
-	ps2if->io.write		= ps2_write;
-	ps2if->io.open		= ps2_open;
-	ps2if->io.close		= ps2_close;
-	ps2if->io.name		= dev->dev.bus_id;
-	ps2if->io.phys		= dev->dev.bus_id;
-	ps2if->io.driver	= ps2if;
+	serio->type		= SERIO_8042;
+	serio->write		= ps2_write;
+	serio->open		= ps2_open;
+	serio->close		= ps2_close;
+	strlcpy(serio->name, dev->dev.bus_id, sizeof(serio->name));
+	strlcpy(serio->phys, dev->dev.bus_id, sizeof(serio->phys));
+	serio->port_data	= ps2if;
+	serio->dev.parent	= &dev->dev;
+	ps2if->io		= serio;
 	ps2if->dev		= dev;
 	sa1111_set_drvdata(dev, ps2if);
 
@@ -292,7 +298,7 @@
 	ps2_clear_input(ps2if);
 
 	sa1111_disable_device(ps2if->dev);
-	serio_register_port(&ps2if->io);
+	serio_register_port(ps2if->io);
 	return 0;
 
  out:
@@ -302,6 +308,7 @@
  free:
 	sa1111_set_drvdata(dev, NULL);
 	kfree(ps2if);
+	kfree(serio);
 	return ret;
 }
 
@@ -312,7 +319,7 @@
 {
 	struct ps2if *ps2if = sa1111_get_drvdata(dev);
 
-	serio_unregister_port(&ps2if->io);
+	serio_unregister_port(ps2if->io);
 	release_mem_region(dev->res.start,
 			   dev->res.end - dev->res.start + 1);
 	sa1111_set_drvdata(dev, NULL);
diff -Nru a/drivers/input/serio/serio.c b/drivers/input/serio/serio.c
--- a/drivers/input/serio/serio.c	2004-10-18 14:55:54 -07:00
+++ b/drivers/input/serio/serio.c	2004-10-18 14:55:54 -07:00
@@ -1,11 +1,9 @@
 /*
- * $Id: serio.c,v 1.15 2002/01/22 21:12:03 vojtech Exp $
- *
- *  Copyright (c) 1999-2001 Vojtech Pavlik
- */
-
-/*
  *  The Serio abstraction module
+ *
+ *  Copyright (c) 1999-2004 Vojtech Pavlik
+ *  Copyright (c) 2004 Dmitry Torokhov
+ *  Copyright (c) 2003 Daniele Bellucci
  */
 
 /*
@@ -26,10 +24,6 @@
  * Should you need to contact me, the author, you can do so either by
  * e-mail - mail your message to <vojtech@ucw.cz>, or by paper mail:
  * Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic
- *
- * Changes:
- * 20 Jul. 2003    Daniele Bellucci <bellucda@tiscali.it>
- *                 Minor cleanups.
  */
 
 #include <linux/stddef.h>
@@ -50,100 +44,178 @@
 EXPORT_SYMBOL(serio_interrupt);
 EXPORT_SYMBOL(serio_register_port);
 EXPORT_SYMBOL(serio_register_port_delayed);
-EXPORT_SYMBOL(__serio_register_port);
 EXPORT_SYMBOL(serio_unregister_port);
 EXPORT_SYMBOL(serio_unregister_port_delayed);
-EXPORT_SYMBOL(__serio_unregister_port);
-EXPORT_SYMBOL(serio_register_device);
-EXPORT_SYMBOL(serio_unregister_device);
+EXPORT_SYMBOL(serio_register_driver);
+EXPORT_SYMBOL(serio_unregister_driver);
 EXPORT_SYMBOL(serio_open);
 EXPORT_SYMBOL(serio_close);
 EXPORT_SYMBOL(serio_rescan);
 EXPORT_SYMBOL(serio_reconnect);
 
+static DECLARE_MUTEX(serio_sem);	/* protects serio_list and serio_diriver_list */
+static LIST_HEAD(serio_list);
+static LIST_HEAD(serio_driver_list);
+static unsigned int serio_no;
+
+struct bus_type serio_bus = {
+	.name =	"serio",
+};
+
+static void serio_find_driver(struct serio *serio);
+static void serio_create_port(struct serio *serio);
+static void serio_destroy_port(struct serio *serio);
+static void serio_connect_port(struct serio *serio, struct serio_driver *drv);
+static void serio_reconnect_port(struct serio *serio);
+static void serio_disconnect_port(struct serio *serio);
+
+static int serio_bind_driver(struct serio *serio, struct serio_driver *drv)
+{
+	get_driver(&drv->driver);
+
+	drv->connect(serio, drv);
+	if (serio->drv) {
+		down_write(&serio_bus.subsys.rwsem);
+		serio->dev.driver = &drv->driver;
+		device_bind_driver(&serio->dev);
+		up_write(&serio_bus.subsys.rwsem);
+		return 1;
+	}
+
+	put_driver(&drv->driver);
+	return 0;
+}
+
+/* serio_find_driver() must be called with serio_sem down.  */
+static void serio_find_driver(struct serio *serio)
+{
+	struct serio_driver *drv;
+
+	list_for_each_entry(drv, &serio_driver_list, node)
+		if (!drv->manual_bind)
+			if (serio_bind_driver(serio, drv))
+				break;
+}
+
+/*
+ * Serio event processing.
+ */
+
 struct serio_event {
 	int type;
 	struct serio *serio;
 	struct list_head node;
 };
 
-static DECLARE_MUTEX(serio_sem);
-static LIST_HEAD(serio_list);
-static LIST_HEAD(serio_dev_list);
+enum serio_event_type {
+	SERIO_RESCAN,
+	SERIO_RECONNECT,
+	SERIO_REGISTER_PORT,
+	SERIO_UNREGISTER_PORT,
+};
+
+static spinlock_t serio_event_lock = SPIN_LOCK_UNLOCKED;	/* protects serio_event_list */
 static LIST_HEAD(serio_event_list);
+static DECLARE_WAIT_QUEUE_HEAD(serio_wait);
+static DECLARE_COMPLETION(serio_exited);
 static int serio_pid;
 
-static void serio_find_dev(struct serio *serio)
+static void serio_queue_event(struct serio *serio, int event_type)
 {
-	struct serio_dev *dev;
+	unsigned long flags;
+	struct serio_event *event;
 
-	list_for_each_entry(dev, &serio_dev_list, node) {
-		if (serio->dev)
-			break;
-		if (dev->connect)
-			dev->connect(serio, dev);
-	}
-}
+	spin_lock_irqsave(&serio_event_lock, flags);
 
-#define SERIO_RESCAN		1
-#define SERIO_RECONNECT		2
-#define SERIO_REGISTER_PORT	3
-#define SERIO_UNREGISTER_PORT	4
+	if ((event = kmalloc(sizeof(struct serio_event), GFP_ATOMIC))) {
+		event->type = event_type;
+		event->serio = serio;
 
-static DECLARE_WAIT_QUEUE_HEAD(serio_wait);
-static DECLARE_COMPLETION(serio_exited);
+		list_add_tail(&event->node, &serio_event_list);
+		wake_up(&serio_wait);
+	}
+
+	spin_unlock_irqrestore(&serio_event_lock, flags);
+}
 
-static void serio_invalidate_pending_events(struct serio *serio)
+static struct serio_event *serio_get_event(void)
 {
 	struct serio_event *event;
+	struct list_head *node;
+	unsigned long flags;
+
+	spin_lock_irqsave(&serio_event_lock, flags);
+
+	if (list_empty(&serio_event_list)) {
+		spin_unlock_irqrestore(&serio_event_lock, flags);
+		return NULL;
+	}
+
+	node = serio_event_list.next;
+	event = container_of(node, struct serio_event, node);
+	list_del_init(node);
+
+	spin_unlock_irqrestore(&serio_event_lock, flags);
 
-	list_for_each_entry(event, &serio_event_list, node)
-		if (event->serio == serio)
-			event->serio = NULL;
+	return event;
 }
 
-void serio_handle_events(void)
+static void serio_handle_events(void)
 {
-	struct list_head *node, *next;
 	struct serio_event *event;
 
-	list_for_each_safe(node, next, &serio_event_list) {
-		event = container_of(node, struct serio_event, node);
+	while ((event = serio_get_event())) {
 
 		down(&serio_sem);
-		if (event->serio == NULL)
-			goto event_done;
 
 		switch (event->type) {
 			case SERIO_REGISTER_PORT :
-				__serio_register_port(event->serio);
+				serio_create_port(event->serio);
+				serio_connect_port(event->serio, NULL);
 				break;
 
 			case SERIO_UNREGISTER_PORT :
-				__serio_unregister_port(event->serio);
+				serio_disconnect_port(event->serio);
+				serio_destroy_port(event->serio);
 				break;
 
 			case SERIO_RECONNECT :
-				if (event->serio->dev && event->serio->dev->reconnect)
-					if (event->serio->dev->reconnect(event->serio) == 0)
-						break;
-				/* reconnect failed - fall through to rescan */
+				serio_reconnect_port(event->serio);
+				break;
 
 			case SERIO_RESCAN :
-				if (event->serio->dev && event->serio->dev->disconnect)
-					event->serio->dev->disconnect(event->serio);
-				serio_find_dev(event->serio);
+				serio_disconnect_port(event->serio);
+				serio_connect_port(event->serio, NULL);
 				break;
 			default:
 				break;
 		}
-event_done:
+
 		up(&serio_sem);
-		list_del_init(node);
 		kfree(event);
 	}
 }
 
+static void serio_remove_pending_events(struct serio *serio)
+{
+	struct list_head *node, *next;
+	struct serio_event *event;
+	unsigned long flags;
+
+	spin_lock_irqsave(&serio_event_lock, flags);
+
+	list_for_each_safe(node, next, &serio_event_list) {
+		event = container_of(node, struct serio_event, node);
+		if (event->serio == serio) {
+			list_del_init(node);
+			kfree(event);
+		}
+	}
+
+	spin_unlock_irqrestore(&serio_event_lock, flags);
+}
+
+
 static int serio_thread(void *nothing)
 {
 	lock_kernel();
@@ -163,52 +235,239 @@
 	complete_and_exit(&serio_exited, 0);
 }
 
-static void serio_queue_event(struct serio *serio, int event_type)
+
+/*
+ * Serio port operations
+ */
+
+static ssize_t serio_show_description(struct device *dev, char *buf)
 {
-	struct serio_event *event;
+	struct serio *serio = to_serio_port(dev);
+	return sprintf(buf, "%s\n", serio->name);
+}
 
-	if ((event = kmalloc(sizeof(struct serio_event), GFP_ATOMIC))) {
-		event->type = event_type;
-		event->serio = serio;
+static ssize_t serio_show_driver(struct device *dev, char *buf)
+{
+	return sprintf(buf, "%s\n", dev->driver ? dev->driver->name : "(none)");
+}
 
-		list_add_tail(&event->node, &serio_event_list);
-		wake_up(&serio_wait);
+static ssize_t serio_rebind_driver(struct device *dev, const char *buf, size_t count)
+{
+	struct serio *serio = to_serio_port(dev);
+	struct device_driver *drv;
+	int retval;
+
+	retval = down_interruptible(&serio_sem);
+	if (retval)
+		return retval;
+
+	retval = count;
+	if (!strncmp(buf, "none", count)) {
+		serio_disconnect_port(serio);
+	} else if (!strncmp(buf, "reconnect", count)) {
+		serio_reconnect_port(serio);
+	} else if (!strncmp(buf, "rescan", count)) {
+		serio_disconnect_port(serio);
+		serio_connect_port(serio, NULL);
+	} else if ((drv = driver_find(buf, &serio_bus)) != NULL) {
+		serio_disconnect_port(serio);
+		serio_connect_port(serio, to_serio_driver(drv));
+		put_driver(drv);
+	} else {
+		retval = -EINVAL;
 	}
+
+	up(&serio_sem);
+
+	return retval;
 }
 
-void serio_rescan(struct serio *serio)
+static ssize_t serio_show_bind_mode(struct device *dev, char *buf)
 {
-	serio_queue_event(serio, SERIO_RESCAN);
+	struct serio *serio = to_serio_port(dev);
+	return sprintf(buf, "%s\n", serio->manual_bind ? "manual" : "auto");
 }
 
-void serio_reconnect(struct serio *serio)
+static ssize_t serio_set_bind_mode(struct device *dev, const char *buf, size_t count)
 {
-	serio_queue_event(serio, SERIO_RECONNECT);
+	struct serio *serio = to_serio_port(dev);
+	int retval;
+
+	retval = count;
+	if (!strncmp(buf, "manual", count)) {
+		serio->manual_bind = 1;
+	} else if (!strncmp(buf, "auto", count)) {
+		serio->manual_bind = 0;
+	} else {
+		retval = -EINVAL;
+	}
+
+	return retval;
 }
 
-irqreturn_t serio_interrupt(struct serio *serio,
-		unsigned char data, unsigned int flags, struct pt_regs *regs)
+static struct device_attribute serio_device_attrs[] = {
+	__ATTR(description, S_IRUGO, serio_show_description, NULL),
+	__ATTR(driver, S_IWUSR | S_IRUGO, serio_show_driver, serio_rebind_driver),
+	__ATTR(bind_mode, S_IWUSR | S_IRUGO, serio_show_bind_mode, serio_set_bind_mode),
+	__ATTR_NULL
+};
+
+
+static void serio_release_port(struct device *dev)
 {
-	irqreturn_t ret = IRQ_NONE;
+	struct serio *serio = to_serio_port(dev);
 
-        if (serio->dev && serio->dev->interrupt) {
-                ret = serio->dev->interrupt(serio, data, flags, regs);
-	} else {
-		if (!flags) {
-			if ((serio->type == SERIO_8042 ||
-				serio->type == SERIO_8042_XL) && (data != 0xaa))
-					return ret;
-			serio_rescan(serio);
-			ret = IRQ_HANDLED;
+	kfree(serio);
+	module_put(THIS_MODULE);
+}
+
+static void serio_create_port(struct serio *serio)
+{
+	try_module_get(THIS_MODULE);
+
+	spin_lock_init(&serio->lock);
+	list_add_tail(&serio->node, &serio_list);
+	snprintf(serio->dev.bus_id, sizeof(serio->dev.bus_id), "serio%d", serio_no++);
+	serio->dev.bus = &serio_bus;
+	serio->dev.release = serio_release_port;
+	if (serio->parent)
+		serio->dev.parent = &serio->parent->dev;
+	device_register(&serio->dev);
+}
+
+/*
+ * serio_destroy_port() completes deregistration process and removes
+ * port from the system
+ */
+static void serio_destroy_port(struct serio *serio)
+{
+	struct serio_driver *drv = serio->drv;
+	unsigned long flags;
+
+	serio_remove_pending_events(serio);
+	list_del_init(&serio->node);
+
+	if (drv) {
+		drv->disconnect(serio);
+		down_write(&serio_bus.subsys.rwsem);
+		device_release_driver(&serio->dev);
+		up_write(&serio_bus.subsys.rwsem);
+		put_driver(&drv->driver);
+	}
+
+	if (serio->parent) {
+		spin_lock_irqsave(&serio->parent->lock, flags);
+		serio->parent->child = NULL;
+		spin_unlock_irqrestore(&serio->parent->lock, flags);
+	}
+
+	device_unregister(&serio->dev);
+}
+
+/*
+ * serio_connect_port() tries to bind the port and possible all its
+ * children to appropriate drivers. If driver passed in the function will not
+ * try otehr drivers when binding parent port.
+ */
+static void serio_connect_port(struct serio *serio, struct serio_driver *drv)
+{
+	WARN_ON(serio->drv);
+	WARN_ON(serio->child);
+
+	if (drv)
+		serio_bind_driver(serio, drv);
+	else if (!serio->manual_bind)
+		serio_find_driver(serio);
+
+	/* Ok, now bind children, if any */
+	while (serio->child) {
+		serio = serio->child;
+
+		WARN_ON(serio->drv);
+		WARN_ON(serio->child);
+
+		serio_create_port(serio);
+
+		if (!serio->manual_bind) {
+			/*
+			 * With children we just _prefer_ passed in driver,
+			 * but we will try other options in case preferred
+			 * is not the one
+			 */
+			if (!drv || !serio_bind_driver(serio, drv))
+				serio_find_driver(serio);
 		}
 	}
-	return ret;
+}
+
+/*
+ *
+ */
+static void serio_reconnect_port(struct serio *serio)
+{
+	do {
+		if (!serio->drv || !serio->drv->reconnect || serio->drv->reconnect(serio)) {
+			serio_disconnect_port(serio);
+			serio_connect_port(serio, NULL);
+			/* Ok, old children are now gone, we are done */
+			break;
+		}
+		serio = serio->child;
+	} while (serio);
+}
+
+/*
+ * serio_disconnect_port() unbinds a port from its driver. As a side effect
+ * all child ports are unbound and destroyed.
+ */
+static void serio_disconnect_port(struct serio *serio)
+{
+	struct serio_driver *drv = serio->drv;
+	struct serio *s;
+
+	if (serio->child) {
+		/*
+		 * Children ports should be disconnected and destroyed
+		 * first, staring with the leaf one, since we don't want
+		 * to do recursion
+		 */
+		do {
+			s = serio->child;
+		} while (s->child);
+
+		while (s != serio) {
+			s = s->parent;
+			serio_destroy_port(s->child);
+		}
+	}
+
+	/*
+	 * Ok, no children left, now disconnect this port
+	 */
+	if (drv) {
+		drv->disconnect(serio);
+		down_write(&serio_bus.subsys.rwsem);
+		device_release_driver(&serio->dev);
+		up_write(&serio_bus.subsys.rwsem);
+		put_driver(&drv->driver);
+	}
+}
+
+void serio_rescan(struct serio *serio)
+{
+	serio_queue_event(serio, SERIO_RESCAN);
+}
+
+void serio_reconnect(struct serio *serio)
+{
+	serio_queue_event(serio, SERIO_RECONNECT);
 }
 
 void serio_register_port(struct serio *serio)
 {
 	down(&serio_sem);
-	__serio_register_port(serio);
+	serio_create_port(serio);
+	serio_connect_port(serio, NULL);
 	up(&serio_sem);
 }
 
@@ -222,21 +481,11 @@
 	serio_queue_event(serio, SERIO_REGISTER_PORT);
 }
 
-/*
- * Should only be called directly if serio_sem has already been taken,
- * for example when unregistering a serio from other input device's
- * connect() function.
- */
-void __serio_register_port(struct serio *serio)
-{
-	list_add_tail(&serio->node, &serio_list);
-	serio_find_dev(serio);
-}
-
 void serio_unregister_port(struct serio *serio)
 {
 	down(&serio_sem);
-	__serio_unregister_port(serio);
+	serio_disconnect_port(serio);
+	serio_destroy_port(serio);
 	up(&serio_sem);
 }
 
@@ -250,82 +499,171 @@
 	serio_queue_event(serio, SERIO_UNREGISTER_PORT);
 }
 
+
 /*
- * Should only be called directly if serio_sem has already been taken,
- * for example when unregistering a serio from other input device's
- * disconnect() function.
+ * Serio driver operations
  */
-void __serio_unregister_port(struct serio *serio)
+
+static ssize_t serio_driver_show_description(struct device_driver *drv, char *buf)
 {
-	serio_invalidate_pending_events(serio);
-	list_del_init(&serio->node);
-	if (serio->dev && serio->dev->disconnect)
-		serio->dev->disconnect(serio);
+	struct serio_driver *driver = to_serio_driver(drv);
+	return sprintf(buf, "%s\n", driver->description ? driver->description : "(none)");
+}
+
+static ssize_t serio_driver_show_bind_mode(struct device_driver *drv, char *buf)
+{
+	struct serio_driver *serio_drv = to_serio_driver(drv);
+	return sprintf(buf, "%s\n", serio_drv->manual_bind ? "manual" : "auto");
 }
 
-void serio_register_device(struct serio_dev *dev)
+static ssize_t serio_driver_set_bind_mode(struct device_driver *drv, const char *buf, size_t count)
+{
+	struct serio_driver *serio_drv = to_serio_driver(drv);
+	int retval;
+
+	retval = count;
+	if (!strncmp(buf, "manual", count)) {
+		serio_drv->manual_bind = 1;
+	} else if (!strncmp(buf, "auto", count)) {
+		serio_drv->manual_bind = 0;
+	} else {
+		retval = -EINVAL;
+	}
+
+	return retval;
+}
+
+
+static struct driver_attribute serio_driver_attrs[] = {
+	__ATTR(description, S_IRUGO, serio_driver_show_description, NULL),
+	__ATTR(bind_mode, S_IWUSR | S_IRUGO,
+		serio_driver_show_bind_mode, serio_driver_set_bind_mode),
+	__ATTR_NULL
+};
+
+void serio_register_driver(struct serio_driver *drv)
 {
 	struct serio *serio;
+
 	down(&serio_sem);
-	list_add_tail(&dev->node, &serio_dev_list);
-	list_for_each_entry(serio, &serio_list, node)
-		if (!serio->dev && dev->connect)
-			dev->connect(serio, dev);
+
+	list_add_tail(&drv->node, &serio_driver_list);
+
+	drv->driver.bus = &serio_bus;
+	driver_register(&drv->driver);
+
+	if (drv->manual_bind)
+		goto out;
+
+start_over:
+	list_for_each_entry(serio, &serio_list, node) {
+		if (!serio->drv) {
+			serio_connect_port(serio, drv);
+			/*
+			 * if new child appeared then the list is changed,
+			 * we need to start over
+			 */
+			if (serio->child)
+				goto start_over;
+		}
+	}
+
+out:
 	up(&serio_sem);
 }
 
-void serio_unregister_device(struct serio_dev *dev)
+void serio_unregister_driver(struct serio_driver *drv)
 {
 	struct serio *serio;
 
 	down(&serio_sem);
-	list_del_init(&dev->node);
 
+	list_del_init(&drv->node);
+
+start_over:
 	list_for_each_entry(serio, &serio_list, node) {
-		if (serio->dev == dev && dev->disconnect)
-			dev->disconnect(serio);
-		serio_find_dev(serio);
+		if (serio->drv == drv) {
+			serio_disconnect_port(serio);
+			serio_connect_port(serio, NULL);
+			/* we could've deleted some ports, restart */
+			goto start_over;
+		}
 	}
+
+	driver_unregister(&drv->driver);
+
 	up(&serio_sem);
 }
 
-/* called from serio_dev->connect/disconnect methods under serio_sem */
-int serio_open(struct serio *serio, struct serio_dev *dev)
+/* called from serio_driver->connect/disconnect methods under serio_sem */
+int serio_open(struct serio *serio, struct serio_driver *drv)
 {
-	serio->dev = dev;
+	serio_pause_rx(serio);
+	serio->drv = drv;
+	serio_continue_rx(serio);
+
 	if (serio->open && serio->open(serio)) {
-		serio->dev = NULL;
+		serio_pause_rx(serio);
+		serio->drv = NULL;
+		serio_continue_rx(serio);
 		return -1;
 	}
 	return 0;
 }
 
-/* called from serio_dev->connect/disconnect methods under serio_sem */
+/* called from serio_driver->connect/disconnect methods under serio_sem */
 void serio_close(struct serio *serio)
 {
 	if (serio->close)
 		serio->close(serio);
-	serio->dev = NULL;
+
+	serio_pause_rx(serio);
+	serio->drv = NULL;
+	serio_continue_rx(serio);
 }
 
-static int __init serio_init(void)
+irqreturn_t serio_interrupt(struct serio *serio,
+		unsigned char data, unsigned int dfl, struct pt_regs *regs)
 {
-	int pid;
+	unsigned long flags;
+	irqreturn_t ret = IRQ_NONE;
+
+	spin_lock_irqsave(&serio->lock, flags);
+
+        if (likely(serio->drv)) {
+                ret = serio->drv->interrupt(serio, data, dfl, regs);
+	} else {
+		if (!dfl) {
+			if ((serio->type != SERIO_8042 &&
+			     serio->type != SERIO_8042_XL) || (data == 0xaa)) {
+				serio_rescan(serio);
+				ret = IRQ_HANDLED;
+			}
+		}
+	}
+
+	spin_unlock_irqrestore(&serio->lock, flags);
 
-	pid = kernel_thread(serio_thread, NULL, CLONE_KERNEL);
+	return ret;
+}
 
-	if (!pid) {
+static int __init serio_init(void)
+{
+	if (!(serio_pid = kernel_thread(serio_thread, NULL, CLONE_KERNEL))) {
 		printk(KERN_WARNING "serio: Failed to start kseriod\n");
 		return -1;
 	}
 
-	serio_pid = pid;
+	serio_bus.dev_attrs = serio_device_attrs;
+	serio_bus.drv_attrs = serio_driver_attrs;
+	bus_register(&serio_bus);
 
 	return 0;
 }
 
 static void __exit serio_exit(void)
 {
+	bus_unregister(&serio_bus);
 	kill_proc(serio_pid, SIGTERM, 1);
 	wait_for_completion(&serio_exited);
 }
diff -Nru a/drivers/input/serio/serio_raw.c b/drivers/input/serio/serio_raw.c
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/drivers/input/serio/serio_raw.c	2004-10-18 14:57:24 -07:00
@@ -0,0 +1,390 @@
+/*
+ * Raw serio device providing access to a raw byte stream from underlying
+ * serio port. Closely emulates behavior of pre-2.6 /dev/psaux device
+ *
+ * Copyright (c) 2004 Dmitry Torokhov
+ *
+ * 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/slab.h>
+#include <linux/poll.h>
+#include <linux/module.h>
+#include <linux/serio.h>
+#include <linux/init.h>
+#include <linux/major.h>
+#include <linux/device.h>
+#include <linux/devfs_fs_kernel.h>
+#include <linux/miscdevice.h>
+#include <linux/wait.h>
+
+#define DRIVER_DESC	"Raw serio driver"
+
+MODULE_AUTHOR("Dmitry Torokhov <dtor@mail.ru>");
+MODULE_DESCRIPTION(DRIVER_DESC);
+MODULE_LICENSE("GPL");
+
+#define SERIO_RAW_QUEUE_LEN	64
+struct serio_raw {
+	unsigned char queue[SERIO_RAW_QUEUE_LEN];
+	unsigned int tail, head;
+
+	char name[16];
+	unsigned int refcnt;
+	struct serio *serio;
+	struct miscdevice dev;
+	wait_queue_head_t wait;
+	struct list_head list;
+	struct list_head node;
+};
+
+struct serio_raw_list {
+	struct fasync_struct *fasync;
+	struct serio_raw *serio_raw;
+	struct list_head node;
+};
+
+static DECLARE_MUTEX(serio_raw_sem);
+static LIST_HEAD(serio_raw_list);
+static unsigned int serio_raw_no;
+
+/*********************************************************************
+ *             Interface with userspace (file operations)            *
+ *********************************************************************/
+
+static int serio_raw_fasync(int fd, struct file *file, int on)
+{
+	struct serio_raw_list *list = file->private_data;
+	int retval;
+
+	retval = fasync_helper(fd, file, on, &list->fasync);
+	return retval < 0 ? retval : 0;
+}
+
+static struct serio_raw *serio_raw_locate(int minor)
+{
+	struct serio_raw *serio_raw;
+
+	list_for_each_entry(serio_raw, &serio_raw_list, node) {
+		if (serio_raw->dev.minor == minor)
+			return serio_raw;
+	}
+
+	return NULL;
+}
+
+static int serio_raw_open(struct inode *inode, struct file *file)
+{
+	struct serio_raw *serio_raw;
+	struct serio_raw_list *list;
+	int retval = 0;
+
+	retval = down_interruptible(&serio_raw_sem);
+	if (retval)
+		return retval;
+
+	if (!(serio_raw = serio_raw_locate(iminor(inode)))) {
+		retval = -ENODEV;
+		goto out;
+	}
+
+	if (!serio_raw->serio) {
+		retval = -ENODEV;
+		goto out;
+	}
+
+	if (!(list = kmalloc(sizeof(struct serio_raw_list), GFP_KERNEL))) {
+		retval = -ENOMEM;
+		goto out;
+	}
+
+	memset(list, 0, sizeof(struct serio_raw_list));
+	list->serio_raw = serio_raw;
+	file->private_data = list;
+
+	serio_raw->refcnt++;
+	list_add_tail(&list->node, &serio_raw->list);
+
+out:
+	up(&serio_raw_sem);
+	return retval;
+}
+
+static int serio_raw_cleanup(struct serio_raw *serio_raw)
+{
+	if (--serio_raw->refcnt == 0) {
+		misc_deregister(&serio_raw->dev);
+		list_del_init(&serio_raw->node);
+		kfree(serio_raw);
+
+		return 1;
+	}
+
+	return 0;
+}
+
+static int serio_raw_release(struct inode *inode, struct file *file)
+{
+	struct serio_raw_list *list = file->private_data;
+	struct serio_raw *serio_raw = list->serio_raw;
+
+	down(&serio_raw_sem);
+
+	serio_raw_fasync(-1, file, 0);
+	serio_raw_cleanup(serio_raw);
+
+	up(&serio_raw_sem);
+	return 0;
+}
+
+static int serio_raw_fetch_byte(struct serio_raw *serio_raw, char *c)
+{
+	unsigned long flags;
+	int empty;
+
+	spin_lock_irqsave(&serio_raw->serio->lock, flags);
+
+	empty = serio_raw->head == serio_raw->tail;
+	if (!empty) {
+		*c = serio_raw->queue[serio_raw->tail];
+		serio_raw->tail = (serio_raw->tail + 1) % SERIO_RAW_QUEUE_LEN;
+	}
+
+	spin_unlock_irqrestore(&serio_raw->serio->lock, flags);
+
+	return !empty;
+}
+
+static ssize_t serio_raw_read(struct file *file, char __user *buffer, size_t count, loff_t *ppos)
+{
+	struct serio_raw_list *list = file->private_data;
+	struct serio_raw *serio_raw = list->serio_raw;
+	char c;
+	ssize_t retval = 0;
+
+	if (!serio_raw->serio)
+		return -ENODEV;
+
+	if (serio_raw->head == serio_raw->tail && (file->f_flags & O_NONBLOCK))
+		return -EAGAIN;
+
+	retval = wait_event_interruptible(list->serio_raw->wait,
+					  serio_raw->head != serio_raw->tail || !serio_raw->serio);
+	if (retval)
+		return retval;
+
+	if (!serio_raw->serio)
+		return -ENODEV;
+
+	while (retval < count && serio_raw_fetch_byte(serio_raw, &c)) {
+		if (put_user(c, buffer++))
+			return -EFAULT;
+		retval++;
+	}
+
+	return retval;
+}
+
+static ssize_t serio_raw_write(struct file *file, const char __user *buffer, size_t count, loff_t *ppos)
+{
+	struct serio_raw_list *list = file->private_data;
+	ssize_t written = 0;
+	int retval;
+	unsigned char c;
+
+	retval = down_interruptible(&serio_raw_sem);
+	if (retval)
+		return retval;
+
+	if (!list->serio_raw->serio) {
+		retval = -ENODEV;
+		goto out;
+	}
+
+	if (count > 32)
+		count = 32;
+
+	while (count--) {
+		if (get_user(c, buffer++)) {
+			retval = -EFAULT;
+			goto out;
+		}
+		if (serio_write(list->serio_raw->serio, c)) {
+			retval = -EIO;
+			goto out;
+		}
+		written++;
+	};
+
+out:
+	up(&serio_raw_sem);
+	return written;
+}
+
+static unsigned int serio_raw_poll(struct file *file, poll_table *wait)
+{
+	struct serio_raw_list *list = file->private_data;
+
+	poll_wait(file, &list->serio_raw->wait, wait);
+
+	if (list->serio_raw->head != list->serio_raw->tail)
+		return POLLIN | POLLRDNORM;
+
+	return 0;
+}
+
+struct file_operations serio_raw_fops = {
+	.owner =	THIS_MODULE,
+	.open =		serio_raw_open,
+	.release =	serio_raw_release,
+	.read =		serio_raw_read,
+	.write =	serio_raw_write,
+	.poll =		serio_raw_poll,
+	.fasync =	serio_raw_fasync,
+};
+
+
+/*********************************************************************
+ *                   Interface with serio port   	             *
+ *********************************************************************/
+
+static irqreturn_t serio_raw_interrupt(struct serio *serio, unsigned char data,
+					unsigned int dfl, struct pt_regs *regs)
+{
+	struct serio_raw *serio_raw = serio->private;
+	struct serio_raw_list *list;
+	unsigned int head = serio_raw->head;
+
+	/* we are holding serio->lock here so we are prootected */
+	serio_raw->queue[head] = data;
+	head = (head + 1) % SERIO_RAW_QUEUE_LEN;
+	if (likely(head != serio_raw->tail)) {
+		serio_raw->head = head;
+		list_for_each_entry(list, &serio_raw->list, node)
+			kill_fasync(&list->fasync, SIGIO, POLL_IN);
+		wake_up_interruptible(&serio_raw->wait);
+	}
+
+	return IRQ_HANDLED;
+}
+
+static void serio_raw_connect(struct serio *serio, struct serio_driver *drv)
+{
+	struct serio_raw *serio_raw;
+	int err;
+
+	if ((serio->type & SERIO_TYPE) != SERIO_8042)
+		return;
+
+	if (!(serio_raw = kmalloc(sizeof(struct serio_raw), GFP_KERNEL))) {
+		printk(KERN_ERR "serio_raw.c: can't allocate memory for a device\n");
+		return;
+	}
+
+	down(&serio_raw_sem);
+
+	memset(serio_raw, 0, sizeof(struct serio_raw));
+	snprintf(serio_raw->name, sizeof(serio_raw->name), "serio_raw%d", serio_raw_no++);
+	serio_raw->refcnt = 1;
+	serio_raw->serio = serio;
+	INIT_LIST_HEAD(&serio_raw->list);
+	init_waitqueue_head(&serio_raw->wait);
+
+	serio->private = serio_raw;
+	if (serio_open(serio, drv))
+		goto out_free;
+
+	list_add_tail(&serio_raw->node, &serio_raw_list);
+
+	serio_raw->dev.minor = PSMOUSE_MINOR;
+	serio_raw->dev.name = serio_raw->name;
+	serio_raw->dev.fops = &serio_raw_fops;
+
+	err = misc_register(&serio_raw->dev);
+	if (err) {
+		serio_raw->dev.minor = MISC_DYNAMIC_MINOR;
+		err = misc_register(&serio_raw->dev);
+	}
+
+	if (err) {
+		printk(KERN_INFO "serio_raw: failed to register raw access device for %s\n",
+			serio->phys);
+		goto out_close;
+	}
+
+	printk(KERN_INFO "serio_raw: raw access enabled on %s (%s, minor %d)\n",
+		serio->phys, serio_raw->name, serio_raw->dev.minor);
+	goto out;
+
+out_close:
+	serio_close(serio);
+	list_del_init(&serio_raw->node);
+out_free:
+	serio->private = NULL;
+	kfree(serio_raw);
+out:
+	up(&serio_raw_sem);
+}
+
+static int serio_raw_reconnect(struct serio *serio)
+{
+	struct serio_raw *serio_raw = serio->private;
+	struct serio_driver *drv = serio->drv;
+
+	if (!drv || !serio_raw) {
+		printk(KERN_DEBUG "serio_raw: reconnect request, but serio is disconnected, ignoring...\n");
+		return -1;
+	}
+
+	/*
+	 * Nothing needs to be done here, we just need this method to
+	 * keep the same device.
+	 */
+	return 0;
+}
+
+static void serio_raw_disconnect(struct serio *serio)
+{
+	struct serio_raw *serio_raw;
+
+	down(&serio_raw_sem);
+
+	serio_raw = serio->private;
+
+	serio_close(serio);
+	serio->private = NULL;
+
+	serio_raw->serio = NULL;
+	if (!serio_raw_cleanup(serio_raw))
+		wake_up_interruptible(&serio_raw->wait);
+
+	up(&serio_raw_sem);
+}
+
+static struct serio_driver serio_raw_drv = {
+	.driver		= {
+		.name	= "serio_raw",
+	},
+	.description	= DRIVER_DESC,
+	.interrupt	= serio_raw_interrupt,
+	.connect	= serio_raw_connect,
+	.reconnect	= serio_raw_reconnect,
+	.disconnect	= serio_raw_disconnect,
+	.manual_bind	= 1,
+};
+
+int __init serio_raw_init(void)
+{
+	serio_register_driver(&serio_raw_drv);
+	return 0;
+}
+
+void __exit serio_raw_exit(void)
+{
+	serio_unregister_driver(&serio_raw_drv);
+}
+
+module_init(serio_raw_init);
+module_exit(serio_raw_exit);
diff -Nru a/drivers/input/serio/serport.c b/drivers/input/serio/serport.c
--- a/drivers/input/serio/serport.c	2004-10-18 14:57:03 -07:00
+++ b/drivers/input/serio/serport.c	2004-10-18 14:57:03 -07:00
@@ -31,28 +31,25 @@
 struct serport {
 	struct tty_struct *tty;
 	wait_queue_head_t wait;
-	struct serio serio;
+	struct serio *serio;
 	unsigned long flags;
-	char phys[32];
 };
 
-char serport_name[] = "Serial port";
-
 /*
  * Callback functions from the serio code.
  */
 
 static int serport_serio_write(struct serio *serio, unsigned char data)
 {
-	struct serport *serport = serio->driver;
+	struct serport *serport = serio->port_data;
 	return -(serport->tty->driver->write(serport->tty, 0, &data, 1) != 1);
 }
 
 static void serport_serio_close(struct serio *serio)
 {
-	struct serport *serport = serio->driver;
+	struct serport *serport = serio->port_data;
 
-	serport->serio.type = 0;
+	serport->serio->type = 0;
 	wake_up_interruptible(&serport->wait);
 }
 
@@ -64,26 +61,30 @@
 static int serport_ldisc_open(struct tty_struct *tty)
 {
 	struct serport *serport;
+	struct serio *serio;
 	char name[64];
 
 	serport = kmalloc(sizeof(struct serport), GFP_KERNEL);
-	if (unlikely(!serport))
+	serio = kmalloc(sizeof(struct serio), GFP_KERNEL);
+	if (unlikely(!serport || !serio)) {
+		kfree(serport);
+		kfree(serio);
 		return -ENOMEM;
-	memset(serport, 0, sizeof(struct serport));
+	}
 
+	memset(serport, 0, sizeof(struct serport));
+	serport->serio = serio;
 	set_bit(TTY_DO_WRITE_WAKEUP, &tty->flags);
 	serport->tty = tty;
 	tty->disc_data = serport;
 
-	snprintf(serport->phys, sizeof(serport->phys), "%s/serio0", tty_name(tty, name));
-
-	serport->serio.name = serport_name;
-	serport->serio.phys = serport->phys;
-
-	serport->serio.type = SERIO_RS232;
-	serport->serio.write = serport_serio_write;
-	serport->serio.close = serport_serio_close;
-	serport->serio.driver = serport;
+	memset(serio, 0, sizeof(struct serio));
+	strlcpy(serio->name, "Serial port", sizeof(serio->name));
+	snprintf(serio->phys, sizeof(serio->phys), "%s/serio0", tty_name(tty, name));
+	serio->type = SERIO_RS232;
+	serio->write = serport_serio_write;
+	serio->close = serport_serio_close;
+	serio->port_data = serport;
 
 	init_waitqueue_head(&serport->wait);
 
@@ -114,7 +115,7 @@
 	struct serport *serport = (struct serport*) tty->disc_data;
 	int i;
 	for (i = 0; i < count; i++)
-		serio_interrupt(&serport->serio, cp[i], 0, NULL);
+		serio_interrupt(serport->serio, cp[i], 0, NULL);
 }
 
 /*
@@ -142,10 +143,10 @@
 	if (test_and_set_bit(SERPORT_BUSY, &serport->flags))
 		return -EBUSY;
 
-	serio_register_port(&serport->serio);
+	serio_register_port(serport->serio);
 	printk(KERN_INFO "serio: Serial port %s\n", tty_name(tty, name));
-	wait_event_interruptible(serport->wait, !serport->serio.type);
-	serio_unregister_port(&serport->serio);
+	wait_event_interruptible(serport->wait, !serport->serio->type);
+	serio_unregister_port(serport->serio);
 
 	clear_bit(SERPORT_BUSY, &serport->flags);
 
@@ -161,7 +162,7 @@
 	struct serport *serport = (struct serport*) tty->disc_data;
 
 	if (cmd == SPIOCSTYPE)
-		return get_user(serport->serio.type, (unsigned long __user *) arg);
+		return get_user(serport->serio->type, (unsigned long __user *) arg);
 
 	return -EINVAL;
 }
@@ -170,7 +171,7 @@
 {
 	struct serport *sp = (struct serport *) tty->disc_data;
 
-	serio_dev_write_wakeup(&sp->serio);
+	serio_drv_write_wakeup(sp->serio);
 }
 
 /*
diff -Nru a/drivers/input/touchscreen/gunze.c b/drivers/input/touchscreen/gunze.c
--- a/drivers/input/touchscreen/gunze.c	2004-10-18 14:56:28 -07:00
+++ b/drivers/input/touchscreen/gunze.c	2004-10-18 14:56:28 -07:00
@@ -36,8 +36,10 @@
 #include <linux/serio.h>
 #include <linux/init.h>
 
+#define DRIVER_DESC	"Gunze AHL-51S touchscreen driver"
+
 MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>");
-MODULE_DESCRIPTION("Gunze AHL-51S touchscreen driver");
+MODULE_DESCRIPTION(DRIVER_DESC);
 MODULE_LICENSE("GPL");
 
 /*
@@ -111,7 +113,7 @@
  * and if yes, registers it as an input device.
  */
 
-static void gunze_connect(struct serio *serio, struct serio_dev *dev)
+static void gunze_connect(struct serio *serio, struct serio_driver *drv)
 {
 	struct gunze *gunze;
 
@@ -142,7 +144,7 @@
 	gunze->dev.id.product = 0x0051;
 	gunze->dev.id.version = 0x0100;
 
-	if (serio_open(serio, dev)) {
+	if (serio_open(serio, drv)) {
 		kfree(gunze);
 		return;
 	}
@@ -156,10 +158,14 @@
  * The serio device structure.
  */
 
-static struct serio_dev gunze_dev = {
-	.interrupt =	gunze_interrupt,
-	.connect =	gunze_connect,
-	.disconnect =	gunze_disconnect,
+static struct serio_driver gunze_drv = {
+	.driver		= {
+		.name	= "gunze",
+	},
+	.description	= DRIVER_DESC,
+	.interrupt	= gunze_interrupt,
+	.connect	= gunze_connect,
+	.disconnect	= gunze_disconnect,
 };
 
 /*
@@ -168,13 +174,13 @@
 
 int __init gunze_init(void)
 {
-	serio_register_device(&gunze_dev);
+	serio_register_driver(&gunze_drv);
 	return 0;
 }
 
 void __exit gunze_exit(void)
 {
-	serio_unregister_device(&gunze_dev);
+	serio_unregister_driver(&gunze_drv);
 }
 
 module_init(gunze_init);
diff -Nru a/drivers/input/touchscreen/h3600_ts_input.c b/drivers/input/touchscreen/h3600_ts_input.c
--- a/drivers/input/touchscreen/h3600_ts_input.c	2004-10-18 14:56:50 -07:00
+++ b/drivers/input/touchscreen/h3600_ts_input.c	2004-10-18 14:56:50 -07:00
@@ -45,8 +45,10 @@
 #include <asm/arch/hardware.h>
 #include <asm/arch/irqs.h>
 
+#define DRIVER_DESC	"H3600 touchscreen driver"
+
 MODULE_AUTHOR("James Simmons <jsimmons@transvirtual.com>");
-MODULE_DESCRIPTION("H3600 touchscreen driver");
+MODULE_DESCRIPTION(DRIVER_DESC);
 MODULE_LICENSE("GPL");
 
 /*
@@ -373,7 +375,7 @@
  * new serio device. It looks whether it was registered as a H3600 touchscreen
  * and if yes, registers it as an input device.
  */
-static void h3600ts_connect(struct serio *serio, struct serio_dev *dev)
+static void h3600ts_connect(struct serio *serio, struct serio_driver *drv)
 {
 	struct h3600_dev *ts;
 
@@ -441,7 +443,7 @@
 	ts->dev.id.product = 0x0666;  /* FIXME !!! We can ask the hardware */
 	ts->dev.id.version = 0x0100;
 
-	if (serio_open(serio, dev)) {
+	if (serio_open(serio, drv)) {
         	free_irq(IRQ_GPIO_BITSY_ACTION_BUTTON, ts);
         	free_irq(IRQ_GPIO_BITSY_NPOWER_BUTTON, ts);
 		kfree(ts);
@@ -478,10 +480,14 @@
  * The serio device structure.
  */
 
-static struct serio_dev h3600ts_dev = {
-	.interrupt =	h3600ts_interrupt,
-	.connect =	h3600ts_connect,
-	.disconnect =	h3600ts_disconnect,
+static struct serio_driver h3600ts_drv = {
+	.driver		= {
+		.name	= "h3600ts",
+	},
+	.description	= DRIVER_DESC,
+	.interrupt	= h3600ts_interrupt,
+	.connect	= h3600ts_connect,
+	.disconnect	= h3600ts_disconnect,
 };
 
 /*
@@ -490,13 +496,13 @@
 
 static int __init h3600ts_init(void)
 {
-	serio_register_device(&h3600ts_dev);
+	serio_register_driver(&h3600ts_drv);
 	return 0;
 }
 
 static void __exit h3600ts_exit(void)
 {
-	serio_unregister_device(&h3600ts_dev);
+	serio_unregister_driver(&h3600ts_drv);
 }
 
 module_init(h3600ts_init);
diff -Nru a/drivers/input/tsdev.c b/drivers/input/tsdev.c
--- a/drivers/input/tsdev.c	2004-10-18 14:57:04 -07:00
+++ b/drivers/input/tsdev.c	2004-10-18 14:57:04 -07:00
@@ -3,32 +3,42 @@
  *
  *  Copyright (c) 2001 "Crazy" james Simmons 
  *
- *  Input driver to Touchscreen device driver module.
+ *  Compaq touchscreen protocol driver. The protocol emulated by this driver
+ *  is obsolete; for new programs use the tslib library which can read directly
+ *  from evdev and perform dejittering, variance filtering and calibration -
+ *  all in user space, not at kernel level. The meaning of this driver is
+ *  to allow usage of newer input drivers with old applications that use the
+ *  old /dev/h3600_ts and /dev/h3600_tsraw devices.
  *
- *  Sponsored by Transvirtual Technology
+ *  09-Apr-2004: Andrew Zabolotny <zap@homelink.ru>
+ *      Fixed to actually work, not just output random numbers.
+ *      Added support for both h3600_ts and h3600_tsraw protocol
+ *      emulation.
  */
 
 /*
  * 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 
+ * 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
- * 
+ *
  * Should you need to contact me, the author, you can do so either by
- * e-mail - mail your message to <jsimmons@transvirtual.com>.
+ * e-mail - mail your message to <jsimmons@infradead.org>.
  */
 
 #define TSDEV_MINOR_BASE 	128
 #define TSDEV_MINORS		32
+/* First 16 devices are h3600_ts compatible; second 16 are h3600_tsraw */
+#define TSDEV_MINOR_MASK	15
 #define TSDEV_BUFFER_SIZE	64
 
 #include <linux/slab.h>
@@ -52,48 +62,84 @@
 #define CONFIG_INPUT_TSDEV_SCREEN_Y	320
 #endif
 
+/* This driver emulates both protocols of the old h3600_ts and h3600_tsraw
+ * devices. The first one must output X/Y data in 'cooked' format, e.g.
+ * filtered, dejittered and calibrated. Second device just outputs raw
+ * data received from the hardware.
+ *
+ * This driver doesn't support filtering and dejittering; it supports only
+ * calibration. Filtering and dejittering must be done in the low-level
+ * driver, if needed, because it may gain additional benefits from knowing
+ * the low-level details, the nature of noise and so on.
+ *
+ * The driver precomputes a calibration matrix given the initial xres and
+ * yres values (quite innacurate for most touchscreens) that will result
+ * in a more or less expected range of output values. The driver supports
+ * the TS_SET_CAL ioctl, which will replace the calibration matrix with a
+ * new one, supposedly generated from the values taken from the raw device.
+ */
+
 MODULE_AUTHOR("James Simmons <jsimmons@transvirtual.com>");
 MODULE_DESCRIPTION("Input driver to touchscreen converter");
 MODULE_LICENSE("GPL");
 
 static int xres = CONFIG_INPUT_TSDEV_SCREEN_X;
 module_param(xres, uint, 0);
-MODULE_PARM_DESC(xres, "Horizontal screen resolution");
+MODULE_PARM_DESC(xres, "Horizontal screen resolution (can be negative for X-mirror)");
 
 static int yres = CONFIG_INPUT_TSDEV_SCREEN_Y;
 module_param(yres, uint, 0);
-MODULE_PARM_DESC(yres, "Vertical screen resolution");
+MODULE_PARM_DESC(yres, "Vertical screen resolution (can be negative for Y-mirror)");
+
+/* From Compaq's Touch Screen Specification version 0.2 (draft) */
+struct ts_event {
+	short pressure;
+	short x;
+	short y;
+	short millisecs;
+};
+
+struct ts_calibration {
+	int xscale;
+	int xtrans;
+	int yscale;
+	int ytrans;
+	int xyswap;
+};
 
 struct tsdev {
 	int exist;
 	int open;
 	int minor;
-	char name[16];
+	char name[8];
 	wait_queue_head_t wait;
 	struct list_head list;
 	struct input_handle handle;
+	int x, y, pressure;
+	struct ts_calibration cal;
 };
 
-/* From Compaq's Touch Screen Specification version 0.2 (draft) */
-typedef struct {
-	short pressure;
-	short x;
-	short y;
-	short millisecs;
-} TS_EVENT;
-
 struct tsdev_list {
 	struct fasync_struct *fasync;
 	struct list_head node;
 	struct tsdev *tsdev;
 	int head, tail;
-	int oldx, oldy, pendown;
-	TS_EVENT event[TSDEV_BUFFER_SIZE];
+	struct ts_event event[TSDEV_BUFFER_SIZE];
+	int raw;
 };
 
+/* The following ioctl codes are defined ONLY for backward compatibility.
+ * Don't use tsdev for new developement; use the tslib library instead.
+ * Touchscreen calibration is a fully userspace task.
+ */
+/* Use 'f' as magic number */
+#define IOC_H3600_TS_MAGIC  'f'
+#define TS_GET_CAL	_IOR(IOC_H3600_TS_MAGIC, 10, struct ts_calibration)
+#define TS_SET_CAL	_IOW(IOC_H3600_TS_MAGIC, 11, struct ts_calibration)
+
 static struct input_handler tsdev_handler;
 
-static struct tsdev *tsdev_table[TSDEV_MINORS];
+static struct tsdev *tsdev_table[TSDEV_MINORS/2];
 
 static int tsdev_fasync(int fd, struct file *file, int on)
 {
@@ -109,13 +155,16 @@
 	int i = iminor(inode) - TSDEV_MINOR_BASE;
 	struct tsdev_list *list;
 
-	if (i >= TSDEV_MINORS || !tsdev_table[i])
+	if (i >= TSDEV_MINORS || !tsdev_table[i & TSDEV_MINOR_MASK])
 		return -ENODEV;
 
 	if (!(list = kmalloc(sizeof(struct tsdev_list), GFP_KERNEL)))
 		return -ENOMEM;
 	memset(list, 0, sizeof(struct tsdev_list));
 
+	list->raw = (i >= TSDEV_MINORS/2) ? 1 : 0;
+
+	i &= TSDEV_MINOR_MASK;
 	list->tsdev = tsdev_table[i];
 	list_add_tail(&list->node, &tsdev_table[i]->list);
 	file->private_data = list;
@@ -161,7 +210,7 @@
 		return -EAGAIN;
 
 	retval = wait_event_interruptible(list->tsdev->wait,
-		(list->head != list->tail) && list->tsdev->exist);
+			list->head != list->tail || !list->tsdev->exist);
 
 	if (retval)
 		return retval;
@@ -169,11 +218,13 @@
 	if (!list->tsdev->exist)
 		return -ENODEV;
 
-	while (list->head != list->tail && retval + sizeof(TS_EVENT) <= count) {
-		if (copy_to_user (buffer + retval, list->event + list->tail, sizeof(TS_EVENT)))
+	while (list->head != list->tail &&
+	       retval + sizeof (struct ts_event) <= count) {
+		if (copy_to_user (buffer + retval, list->event + list->tail,
+				  sizeof (struct ts_event)))
 			return -EFAULT;
 		list->tail = (list->tail + 1) & (TSDEV_BUFFER_SIZE - 1);
-		retval += sizeof(TS_EVENT);
+		retval += sizeof (struct ts_event);
 	}
 
 	return retval;
@@ -193,22 +244,27 @@
 static int tsdev_ioctl(struct inode *inode, struct file *file,
 		       unsigned int cmd, unsigned long arg)
 {
-/*
 	struct tsdev_list *list = file->private_data;
-        struct tsdev *evdev = list->tsdev;
-        struct input_dev *dev = tsdev->handle.dev;
-        int retval;
-	
+	struct tsdev *tsdev = list->tsdev;
+	int retval = 0;
+
 	switch (cmd) {
-		case HHEHE:
-			return 0;
-		case hjff:
-			return 0;
-		default:
-			return 0;
+	case TS_GET_CAL:
+		if (copy_to_user ((void __user *)arg, &tsdev->cal,
+				  sizeof (struct ts_calibration)))
+			retval = -EFAULT;
+		break;
+	case TS_SET_CAL:
+		if (copy_from_user (&tsdev->cal, (void __user *)arg,
+				    sizeof (struct ts_calibration)))
+			retval = -EFAULT;
+		break;
+	default:
+		retval = -EINVAL;
+		break;
 	}
-*/
-	return -EINVAL;
+
+	return retval;
 }
 
 struct file_operations tsdev_fops = {
@@ -227,82 +283,85 @@
 	struct tsdev *tsdev = handle->private;
 	struct tsdev_list *list;
 	struct timeval time;
-	int size;
 
-	list_for_each_entry(list, &tsdev->list, node) {
-		switch (type) {
-		case EV_ABS:
-			switch (code) {
-			case ABS_X:
-				if (!list->pendown)
-					return;
-				size = handle->dev->absmax[ABS_X] - handle->dev->absmin[ABS_X];
-				if (size > 0)
-					list->oldx = ((value - handle->dev->absmin[ABS_X]) * xres / size);
-				else
-					list->oldx = ((value - handle->dev->absmin[ABS_X]));
-				break;
-			case ABS_Y:
-				if (!list->pendown)
-					return;
-				size = handle->dev->absmax[ABS_Y] - handle->dev->absmin[ABS_Y];
-				if (size > 0)
-					list->oldy = ((value - handle->dev->absmin[ABS_Y]) * yres / size);
-				else
-					list->oldy = ((value - handle->dev->absmin[ABS_Y]));
-				break;
-			case ABS_PRESSURE:
-				list->pendown = ((value > handle->dev-> absmin[ABS_PRESSURE])) ?
-				    value - handle->dev->absmin[ABS_PRESSURE] : 0;
-				break;
-			}
+	switch (type) {
+	case EV_ABS:
+		switch (code) {
+		case ABS_X:
+			tsdev->x = value;
+			break;
+		case ABS_Y:
+			tsdev->y = value;
 			break;
+		case ABS_PRESSURE:
+			if (value > handle->dev->absmax[ABS_PRESSURE])
+				value = handle->dev->absmax[ABS_PRESSURE];
+			value -= handle->dev->absmin[ABS_PRESSURE];
+			if (value < 0)
+				value = 0;
+			tsdev->pressure = value;
+			break;
+		}
+		break;
 
-		case EV_REL:
-			switch (code) {
-			case REL_X:
-				if (!list->pendown)
-					return;
-				list->oldx += value;
-				if (list->oldx < 0)
-					list->oldx = 0;
-				else if (list->oldx > xres)
-					list->oldx = xres;
+	case EV_REL:
+		switch (code) {
+		case REL_X:
+			tsdev->x += value;
+			if (tsdev->x < 0)
+				tsdev->x = 0;
+			else if (tsdev->x > xres)
+				tsdev->x = xres;
+			break;
+		case REL_Y:
+			tsdev->y += value;
+			if (tsdev->y < 0)
+				tsdev->y = 0;
+			else if (tsdev->y > yres)
+				tsdev->y = yres;
+			break;
+		}
+		break;
+
+	case EV_KEY:
+		if (code == BTN_TOUCH || code == BTN_MOUSE) {
+			switch (value) {
+			case 0:
+				tsdev->pressure = 0;
 				break;
-			case REL_Y:
-				if (!list->pendown)
-					return;
-				list->oldy += value;
-				if (list->oldy < 0)
-					list->oldy = 0;
-				else if (list->oldy > xres)
-					list->oldy = xres;
+			case 1:
+				if (!tsdev->pressure)
+					tsdev->pressure = 1;
 				break;
 			}
-			break;
-
-		case EV_KEY:
-			if (code == BTN_TOUCH || code == BTN_MOUSE) {
-				switch (value) {
-				case 0:
-					list->pendown = 0;
-					break;
-				case 1:
-					if (!list->pendown)
-						list->pendown = 1;
-					break;
-				case 2:
-					return;
-				}
-			} else
-				return;
-			break;
 		}
+		break;
+	}
+
+	if (type != EV_SYN || code != SYN_REPORT)
+		return;
+
+	list_for_each_entry(list, &tsdev->list, node) {
+		int x, y, tmp;
+
 		do_gettimeofday(&time);
 		list->event[list->head].millisecs = time.tv_usec / 100;
-		list->event[list->head].pressure = list->pendown;
-		list->event[list->head].x = list->oldx;
-		list->event[list->head].y = list->oldy;
+		list->event[list->head].pressure = tsdev->pressure;
+
+		x = tsdev->x;
+		y = tsdev->y;
+
+		/* Calibration */
+		if (!list->raw) {
+			x = ((x * tsdev->cal.xscale) >> 8) + tsdev->cal.xtrans;
+			y = ((y * tsdev->cal.yscale) >> 8) + tsdev->cal.ytrans;
+			if (tsdev->cal.xyswap) {
+				tmp = x; x = y; y = tmp;
+			}
+		}
+
+		list->event[list->head].x = x;
+		list->event[list->head].y = y;
 		list->head = (list->head + 1) & (TSDEV_BUFFER_SIZE - 1);
 		kill_fasync(&list->fasync, SIGIO, POLL_IN);
 	}
@@ -314,11 +373,11 @@
 					  struct input_device_id *id)
 {
 	struct tsdev *tsdev;
-	int minor;
+	int minor, delta;
 
-	for (minor = 0; minor < TSDEV_MINORS && tsdev_table[minor];
+	for (minor = 0; minor < TSDEV_MINORS/2 && tsdev_table[minor];
 	     minor++);
-	if (minor == TSDEV_MINORS) {
+	if (minor >= TSDEV_MINORS/2) {
 		printk(KERN_ERR
 		       "tsdev: You have way too many touchscreens\n");
 		return NULL;
@@ -340,10 +399,25 @@
 	tsdev->handle.handler = handler;
 	tsdev->handle.private = tsdev;
 
+	/* Precompute the rough calibration matrix */
+	delta = dev->absmax [ABS_X] - dev->absmin [ABS_X] + 1;
+	if (delta == 0)
+		delta = 1;
+	tsdev->cal.xscale = (xres << 8) / delta;
+	tsdev->cal.xtrans = - ((dev->absmin [ABS_X] * tsdev->cal.xscale) >> 8);
+
+	delta = dev->absmax [ABS_Y] - dev->absmin [ABS_Y] + 1;
+	if (delta == 0)
+		delta = 1;
+	tsdev->cal.yscale = (yres << 8) / delta;
+	tsdev->cal.ytrans = - ((dev->absmin [ABS_Y] * tsdev->cal.yscale) >> 8);
+
 	tsdev_table[minor] = tsdev;
-	
+
 	devfs_mk_cdev(MKDEV(INPUT_MAJOR, TSDEV_MINOR_BASE + minor),
 			S_IFCHR|S_IRUGO|S_IWUSR, "input/ts%d", minor);
+	devfs_mk_cdev(MKDEV(INPUT_MAJOR, TSDEV_MINOR_BASE + minor + TSDEV_MINORS/2),
+			S_IFCHR|S_IRUGO|S_IWUSR, "input/tsraw%d", minor);
 	class_simple_device_add(input_class, 
 				MKDEV(INPUT_MAJOR, TSDEV_MINOR_BASE + minor),
 				dev->dev, "ts%d", minor);
@@ -362,6 +436,7 @@
 		wake_up_interruptible(&tsdev->wait);
 	} else
 		tsdev_free(tsdev);
+	devfs_remove("input/tsraw%d", tsdev->minor);
 }
 
 static struct input_device_id tsdev_ids[] = {
@@ -378,6 +453,12 @@
 	      .keybit	= { [LONG(BTN_TOUCH)] = BIT(BTN_TOUCH) },
 	      .absbit	= { BIT(ABS_X) | BIT(ABS_Y) },
 	 },/* A tablet like device, at least touch detection, two absolute axes */
+
+	{
+	      .flags	= INPUT_DEVICE_ID_MATCH_EVBIT | INPUT_DEVICE_ID_MATCH_ABSBIT,
+	      .evbit	= { BIT(EV_ABS) },
+	      .absbit	= { BIT(ABS_X) | BIT(ABS_Y) | BIT(ABS_PRESSURE) },
+	 },/* A tablet like device with several gradations of pressure */
 
 	{},/* Terminating entry */
 };
diff -Nru a/drivers/isdn/act2000/act2000_isa.c b/drivers/isdn/act2000/act2000_isa.c
--- a/drivers/isdn/act2000/act2000_isa.c	2004-10-18 14:56:29 -07:00
+++ b/drivers/isdn/act2000/act2000_isa.c	2004-10-18 14:56:29 -07:00
@@ -434,7 +434,10 @@
                 l = (length > 1024) ? 1024 : length;
                 c = 0;
                 b = buf;
-                copy_from_user(buf, p, l);
+                if (copy_from_user(buf, p, l)) {
+                        kfree(buf);
+                        return -EFAULT;
+                }
                 while (c < l) {
                         if (act2000_isa_writeb(card, *b++)) {
                                 printk(KERN_WARNING
diff -Nru a/drivers/isdn/capi/capi.c b/drivers/isdn/capi/capi.c
--- a/drivers/isdn/capi/capi.c	2004-10-18 14:57:04 -07:00
+++ b/drivers/isdn/capi/capi.c	2004-10-18 14:57:04 -07:00
@@ -436,51 +436,62 @@
 	struct sk_buff *nskb;
 	int datalen;
 	u16 errcode, datahandle;
-
+	struct tty_ldisc *ld;
+	
 	datalen = skb->len - CAPIMSG_LEN(skb->data);
-	if (mp->tty) {
-		if (mp->tty->ldisc.receive_buf == 0) {
-			printk(KERN_ERR "capi: ldisc has no receive_buf function\n");
-			return -1;
-		}
-		if (mp->ttyinstop) {
+	if (mp->tty == NULL)
+	{
+#ifdef _DEBUG_DATAFLOW
+		printk(KERN_DEBUG "capi: currently no receiver\n");
+#endif
+		return -1;
+	}
+	
+	ld = tty_ldisc_ref(mp->tty);
+	if (ld == NULL)
+		return -1;
+	if (ld->receive_buf == NULL) {
 #if defined(_DEBUG_DATAFLOW) || defined(_DEBUG_TTYFUNCS)
-			printk(KERN_DEBUG "capi: recv tty throttled\n");
+		printk(KERN_DEBUG "capi: ldisc has no receive_buf function\n");
 #endif
-			return -1;
-		}
-		if (mp->tty->ldisc.receive_room &&
-		    mp->tty->ldisc.receive_room(mp->tty) < datalen) {
+		goto bad;
+	}
+	if (mp->ttyinstop) {
 #if defined(_DEBUG_DATAFLOW) || defined(_DEBUG_TTYFUNCS)
-			printk(KERN_DEBUG "capi: no room in tty\n");
+		printk(KERN_DEBUG "capi: recv tty throttled\n");
 #endif
-			return -1;
-		}
-		if ((nskb = gen_data_b3_resp_for(mp, skb)) == 0) {
-			printk(KERN_ERR "capi: gen_data_b3_resp failed\n");
-			return -1;
-		}
-		datahandle = CAPIMSG_U16(skb->data,CAPIMSG_BASELEN+4);
-		errcode = capi20_put_message(mp->ap, nskb);
-		if (errcode != CAPI_NOERROR) {
-			printk(KERN_ERR "capi: send DATA_B3_RESP failed=%x\n",
-					errcode);
-			kfree_skb(nskb);
-			return -1;
-		}
-		(void)skb_pull(skb, CAPIMSG_LEN(skb->data));
-#ifdef _DEBUG_DATAFLOW
-		printk(KERN_DEBUG "capi: DATA_B3_RESP %u len=%d => ldisc\n",
-					datahandle, skb->len);
+		goto bad;
+	}
+	if (ld->receive_room &&
+	    ld->receive_room(mp->tty) < datalen) {
+#if defined(_DEBUG_DATAFLOW) || defined(_DEBUG_TTYFUNCS)
+		printk(KERN_DEBUG "capi: no room in tty\n");
 #endif
-		mp->tty->ldisc.receive_buf(mp->tty, skb->data, NULL, skb->len);
-		kfree_skb(skb);
-		return 0;
-
+		goto bad;
 	}
+	if ((nskb = gen_data_b3_resp_for(mp, skb)) == 0) {
+		printk(KERN_ERR "capi: gen_data_b3_resp failed\n");
+		goto bad;
+	}
+	datahandle = CAPIMSG_U16(skb->data,CAPIMSG_BASELEN+4);
+	errcode = capi20_put_message(mp->ap, nskb);
+	if (errcode != CAPI_NOERROR) {
+		printk(KERN_ERR "capi: send DATA_B3_RESP failed=%x\n",
+				errcode);
+		kfree_skb(nskb);
+		goto bad;
+	}
+	(void)skb_pull(skb, CAPIMSG_LEN(skb->data));
 #ifdef _DEBUG_DATAFLOW
-	printk(KERN_DEBUG "capi: currently no receiver\n");
+	printk(KERN_DEBUG "capi: DATA_B3_RESP %u len=%d => ldisc\n",
+				datahandle, skb->len);
 #endif
+	ld->receive_buf(mp->tty, skb->data, NULL, skb->len);
+	kfree_skb(skb);
+	tty_ldisc_deref(ld);
+	return 0;
+bad:
+	tty_ldisc_deref(ld);
 	return -1;
 }
 
@@ -614,6 +625,7 @@
 
 
 	if (CAPIMSG_SUBCOMMAND(skb->data) == CAPI_IND) {
+		
 		datahandle = CAPIMSG_U16(skb->data, CAPIMSG_BASELEN+4+4+2);
 #ifdef _DEBUG_DATAFLOW
 		printk(KERN_DEBUG "capi_signal: DATA_B3_IND %u len=%d\n",
@@ -633,10 +645,8 @@
 #endif
 		kfree_skb(skb);
 		(void)capiminor_del_ack(mp, datahandle);
-		if (mp->tty) {
-			if (mp->tty->ldisc.write_wakeup)
-				mp->tty->ldisc.write_wakeup(mp->tty);
-		}
+		if (mp->tty)
+			tty_wakeup(mp->tty);
 		(void)handle_minor_send(mp);
 
 	} else {
diff -Nru a/drivers/isdn/capi/capidrv.c b/drivers/isdn/capi/capidrv.c
--- a/drivers/isdn/capi/capidrv.c	2004-10-18 14:56:29 -07:00
+++ b/drivers/isdn/capi/capidrv.c	2004-10-18 14:56:29 -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-10-18 14:57:03 -07:00
+++ b/drivers/isdn/hardware/avm/b1.c	2004-10-18 14:57: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-10-18 14:56:48 -07:00
+++ b/drivers/isdn/hardware/avm/b1dma.c	2004-10-18 14:56:48 -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-10-18 14:56:32 -07:00
+++ b/drivers/isdn/hardware/avm/c4.c	2004-10-18 14:56:32 -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-10-18 14:56:33 -07:00
+++ b/drivers/isdn/hardware/avm/t1isa.c	2004-10-18 14:56:33 -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-10-18 14:56:50 -07:00
+++ b/drivers/isdn/hardware/eicon/capifunc.c	2004-10-18 14:56:50 -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-10-18 14:56:49 -07:00
+++ b/drivers/isdn/hardware/eicon/capifunc.h	2004-10-18 14:56:49 -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-10-18 14:56:32 -07:00
+++ b/drivers/isdn/hardware/eicon/debug.c	2004-10-18 14:56:32 -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);
@@ -572,13 +583,22 @@
   char          *data;
   unsigned short code;
 
-  if (!format)
+  if (diva_os_in_irq()) {
+    dbg_sequence++;
     return;
+  }
+
+	if ((!format) ||
+			((TraceFilter[0] != 0) && ((TraceFilterIdent < 0) || (TraceFilterChannel < 0)))) {
+		return;
+	}
+
+
   
   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 +723,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 +740,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 +777,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 +789,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 +799,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 +813,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 +826,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 +871,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 +884,14 @@
   }
   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");
+      diva_os_free(0, pmem);
       return;
     }
     if (clients[id].hDbg) { /* slot is busy */
@@ -891,8 +912,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 +929,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 +971,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 +1010,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 +1034,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 +1052,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 +1098,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 +1171,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 +1214,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 +1364,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 +1390,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 +1438,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 +1499,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 +1551,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 +1797,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 = NULL;
+    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 +1888,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 +1928,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 +1944,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 +1976,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 = NULL;
+  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 = NULL;
+  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	2004-10-18 14:57:04 -07:00
+++ b/drivers/isdn/hardware/eicon/debug_if.h	2004-10-18 14:57:04 -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	2004-10-18 14:57:04 -07:00
+++ b/drivers/isdn/hardware/eicon/debuglib.h	2004-10-18 14:57:04 -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-10-18 14:57:04 -07:00
+++ b/drivers/isdn/hardware/eicon/diddfunc.c	2004-10-18 14:57:04 -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	2004-10-18 14:56:33 -07:00
+++ b/drivers/isdn/hardware/eicon/diva_didd.c	2004-10-18 14:56:33 -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)";
@@ -37,8 +37,6 @@
 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)
 
@@ -50,8 +48,8 @@
 static struct proc_dir_entry *proc_didd;
 struct proc_dir_entry *proc_net_eicon = NULL;
 
-EXPORT_SYMBOL_NOVERS(DIVA_DIDD_Read);
-EXPORT_SYMBOL_NOVERS(proc_net_eicon);
+EXPORT_SYMBOL(DIVA_DIDD_Read);
+EXPORT_SYMBOL(proc_net_eicon);
 
 static char *getrev(const char *revision)
 {
diff -Nru a/drivers/isdn/hardware/eicon/divamnt.c b/drivers/isdn/hardware/eicon/divamnt.c
--- a/drivers/isdn/hardware/eicon/divamnt.c	2004-10-18 14:56:32 -07:00
+++ b/drivers/isdn/hardware/eicon/divamnt.c	2004-10-18 14:56:32 -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);
+		diva_os_free(0, filep->private_data);
 		filep->private_data = NULL;
 	}
 
-	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-10-18 14:56:32 -07:00
+++ b/drivers/isdn/hardware/eicon/divasfunc.c	2004-10-18 14:56:32 -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	2004-10-18 14:56:20 -07:00
+++ b/drivers/isdn/hardware/eicon/divasync.h	2004-10-18 14:56:20 -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-10-18 14:57:04 -07:00
+++ b/drivers/isdn/hardware/eicon/idifunc.c	2004-10-18 14:57:04 -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	2004-10-18 14:56:27 -07:00
+++ b/drivers/isdn/hardware/eicon/io.c	2004-10-18 14:56:27 -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	2004-10-18 14:57:04 -07:00
+++ b/drivers/isdn/hardware/eicon/io.h	2004-10-18 14:57:04 -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-10-18 14:55:53 -07:00
+++ b/drivers/isdn/hardware/eicon/maintidi.c	2004-10-18 14:55:53 -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	2004-10-18 14:56:29 -07:00
+++ b/drivers/isdn/hardware/eicon/maintidi.h	2004-10-18 14:56: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-10-18 14:55:54 -07:00
+++ b/drivers/isdn/hardware/eicon/mntfunc.c	2004-10-18 14:55:54 -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(data, (char __user *)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 (buf, data, 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	2004-10-18 14:56:27 -07:00
+++ b/drivers/isdn/hardware/eicon/pc.h	2004-10-18 14:56:27 -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-10-18 14:56:49 -07:00
+++ b/drivers/isdn/hardware/eicon/platform.h	2004-10-18 14:56:49 -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-10-18 14:56:28 -07:00
+++ b/drivers/isdn/hisax/avm_pci.c	2004-10-18 14:56:28 -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-10-18 14:56:28 -07:00
+++ b/drivers/isdn/hisax/bkm_a4t.c	2004-10-18 14:56:28 -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-10-18 14:56:50 -07:00
+++ b/drivers/isdn/hisax/bkm_a8.c	2004-10-18 14:56:50 -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-10-18 14:57:04 -07:00
+++ b/drivers/isdn/hisax/diva.c	2004-10-18 14:57:04 -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-10-18 14:56:11 -07:00
+++ b/drivers/isdn/hisax/elsa.c	2004-10-18 14:56:11 -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-10-18 14:56:49 -07:00
+++ b/drivers/isdn/hisax/enternow_pci.c	2004-10-18 14:56:49 -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-10-18 14:56:32 -07:00
+++ b/drivers/isdn/hisax/gazel.c	2004-10-18 14:56:32 -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-10-18 14:56:29 -07:00
+++ b/drivers/isdn/hisax/hfc_pci.c	2004-10-18 14:56:29 -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-10-18 14:56:28 -07:00
+++ b/drivers/isdn/hisax/niccy.c	2004-10-18 14:56:28 -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-10-18 14:56:27 -07:00
+++ b/drivers/isdn/hisax/nj_s.c	2004-10-18 14:56:27 -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-10-18 14:56:20 -07:00
+++ b/drivers/isdn/hisax/nj_u.c	2004-10-18 14:56:20 -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-10-18 14:57:04 -07:00
+++ b/drivers/isdn/hisax/sedlbauer.c	2004-10-18 14:57:04 -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/st5481_usb.c b/drivers/isdn/hisax/st5481_usb.c
--- a/drivers/isdn/hisax/st5481_usb.c	2004-10-18 14:56:33 -07:00
+++ b/drivers/isdn/hisax/st5481_usb.c	2004-10-18 14:56:33 -07:00
@@ -143,9 +143,6 @@
 	if (ctrl_msg->dr.bRequest == USB_REQ_CLEAR_FEATURE) {
 	        /* Special case handling for pipe reset */
 		le16_to_cpus(&ctrl_msg->dr.wIndex);
-		usb_endpoint_running(adapter->usb_dev,
-				     ctrl_msg->dr.wIndex & ~USB_DIR_IN, 
-				     (ctrl_msg->dr.wIndex & USB_DIR_IN) == 0);
 
 		/* toggle is reset on clear */
 		usb_settoggle(adapter->usb_dev, 
diff -Nru a/drivers/isdn/hisax/telespci.c b/drivers/isdn/hisax/telespci.c
--- a/drivers/isdn/hisax/telespci.c	2004-10-18 14:56:48 -07:00
+++ b/drivers/isdn/hisax/telespci.c	2004-10-18 14:56:48 -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-10-18 14:57:03 -07:00
+++ b/drivers/isdn/hisax/w6692.c	2004-10-18 14:57:03 -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/i4l/isdn_net.c b/drivers/isdn/i4l/isdn_net.c
--- a/drivers/isdn/i4l/isdn_net.c	2004-10-18 14:57:05 -07:00
+++ b/drivers/isdn/i4l/isdn_net.c	2004-10-18 14:57:05 -07:00
@@ -1369,7 +1369,7 @@
 
 	skb->mac.raw = skb->data;
 	skb_pull(skb, ETH_HLEN);
-	eth = skb->mac.ethernet;
+	eth = eth_hdr(skb);
 
 	if (*eth->h_dest & 1) {
 		if (memcmp(eth->h_dest, dev->broadcast, ETH_ALEN) == 0)
diff -Nru a/drivers/isdn/i4l/isdn_tty.c b/drivers/isdn/i4l/isdn_tty.c
--- a/drivers/isdn/i4l/isdn_tty.c	2004-10-18 14:56:48 -07:00
+++ b/drivers/isdn/i4l/isdn_tty.c	2004-10-18 14:56:48 -07:00
@@ -296,10 +296,7 @@
 		info->send_outstanding++;
 		info->msr &= ~UART_MSR_CTS;
 		info->lsr &= ~UART_LSR_TEMT;
-		if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
-		    tty->ldisc.write_wakeup)
-			(tty->ldisc.write_wakeup) (tty);
-		wake_up_interruptible(&tty->write_wait);
+		tty_wakeup(tty);
 		return;
 	}
 	if (slen < 0) {
@@ -1174,10 +1171,7 @@
 						/* If DLE decoding results in zero-transmit, but
 						 * c originally was non-zero, do a wakeup.
 						 */
-						if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
-						 tty->ldisc.write_wakeup)
-							(tty->ldisc.write_wakeup) (tty);
-						wake_up_interruptible(&tty->write_wait);
+						tty_wakeup(tty);
 						info->msr |= UART_MSR_CTS;
 						info->lsr |= UART_LSR_TEMT;
 					}
@@ -1290,9 +1284,7 @@
 	isdn_tty_cleanup_xmit(info);
 	info->xmit_count = 0;
 	wake_up_interruptible(&tty->write_wait);
-	if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
-	    tty->ldisc.write_wakeup)
-		(tty->ldisc.write_wakeup) (tty);
+	tty_wakeup(tty);
 }
 
 static void
@@ -1747,10 +1739,10 @@
 	}
 	dev->modempoll--;
 	isdn_tty_shutdown(info);
+	
 	if (tty->driver->flush_buffer)
 		tty->driver->flush_buffer(tty);
-	if (tty->ldisc.flush_buffer)
-		tty->ldisc.flush_buffer(tty);
+	tty_ldisc_flush(tty);
 	info->tty = NULL;
 	info->ncarrier = 0;
 	tty->closing = 0;
@@ -2681,8 +2673,7 @@
 		if ((info->flags & ISDN_ASYNC_CLOSING) || (!info->tty)) {
 			return;
 		}
-		if (info->tty->ldisc.flush_buffer)
-			info->tty->ldisc.flush_buffer(info->tty);
+		tty_ldisc_flush(info->tty);
 		if ((info->flags & ISDN_ASYNC_CHECK_CD) &&
 		    (!((info->flags & ISDN_ASYNC_CALLOUT_ACTIVE) &&
 		       (info->flags & ISDN_ASYNC_CALLOUT_NOHUP)))) {
diff -Nru a/drivers/isdn/tpam/tpam_main.c b/drivers/isdn/tpam/tpam_main.c
--- a/drivers/isdn/tpam/tpam_main.c	2004-10-18 14:56:48 -07:00
+++ b/drivers/isdn/tpam/tpam_main.c	2004-10-18 14:56:48 -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-10-18 14:57:05 -07:00
+++ b/drivers/macintosh/adbhid.c	2004-10-18 14:57:05 -07:00
@@ -74,15 +74,135 @@
 #define ADB_KEY_POWER_OLD	0x7e
 #define ADB_KEY_POWER		0x7f
 
-unsigned char adb_to_linux_keycodes[128] = {
-	 30, 31, 32, 33, 35, 34, 44, 45, 46, 47, 86, 48, 16, 17, 18, 19,
-	 21, 20,  2,  3,  4,  5,  7,  6, 13, 10,  8, 12,  9, 11, 27, 24,
-	 22, 26, 23, 25, 28, 38, 36, 40, 37, 39, 43, 51, 53, 49, 50, 52,
-	 15, 57, 41, 14, 96,  1, 29,125, 42, 58, 56,105,106,108,103,  0,
-	  0, 83,  0, 55,  0, 78,  0, 69,  0,  0,  0, 98, 96,  0, 74,  0,
-	  0,117, 82, 79, 80, 81, 75, 76, 77, 71,  0, 72, 73,124, 89,121,
-	 63, 64, 65, 61, 66, 67,123, 87,122, 99,  0, 70,  0, 68,101, 88,
-	  0,119,110,102,104,111, 62,107, 60,109, 59, 54,100, 97,126,116
+u8 adb_to_linux_keycodes[128] = {
+	/* 0x00 */ KEY_A, 		/*  30 */
+	/* 0x01 */ KEY_S, 		/*  31 */
+	/* 0x02 */ KEY_D,		/*  32 */
+	/* 0x03 */ KEY_F,		/*  33 */
+	/* 0x04 */ KEY_H,		/*  35 */
+	/* 0x05 */ KEY_G,		/*  34 */
+	/* 0x06 */ KEY_Z,		/*  44 */
+	/* 0x07 */ KEY_X,		/*  45 */
+	/* 0x08 */ KEY_C,		/*  46 */
+	/* 0x09 */ KEY_V,		/*  47 */
+	/* 0x0a */ KEY_102ND,		/*  86 */
+	/* 0x0b */ KEY_B,		/*  48 */
+	/* 0x0c */ KEY_Q,		/*  16 */
+	/* 0x0d */ KEY_W,		/*  17 */
+	/* 0x0e */ KEY_E,		/*  18 */
+	/* 0x0f */ KEY_R,		/*  19 */
+	/* 0x10 */ KEY_Y,		/*  21 */
+	/* 0x11 */ KEY_T,		/*  20 */
+	/* 0x12 */ KEY_1,		/*   2 */
+	/* 0x13 */ KEY_2,		/*   3 */
+	/* 0x14 */ KEY_3,		/*   4 */
+	/* 0x15 */ KEY_4,		/*   5 */
+	/* 0x16 */ KEY_6,		/*   7 */
+	/* 0x17 */ KEY_5,		/*   6 */
+	/* 0x18 */ KEY_EQUAL,		/*  13 */
+	/* 0x19 */ KEY_9,		/*  10 */
+	/* 0x1a */ KEY_7,		/*   8 */
+	/* 0x1b */ KEY_MINUS,		/*  12 */
+	/* 0x1c */ KEY_8,		/*   9 */
+	/* 0x1d */ KEY_0,		/*  11 */
+	/* 0x1e */ KEY_RIGHTBRACE,	/*  27 */
+	/* 0x1f */ KEY_O,		/*  24 */
+	/* 0x20 */ KEY_U,		/*  22 */
+	/* 0x21 */ KEY_LEFTBRACE,	/*  26 */
+	/* 0x22 */ KEY_I,		/*  23 */
+	/* 0x23 */ KEY_P,		/*  25 */
+	/* 0x24 */ KEY_ENTER,		/*  28 */
+	/* 0x25 */ KEY_L,		/*  38 */
+	/* 0x26 */ KEY_J,		/*  36 */
+	/* 0x27 */ KEY_APOSTROPHE,	/*  40 */
+	/* 0x28 */ KEY_K,		/*  37 */
+	/* 0x29 */ KEY_SEMICOLON,	/*  39 */
+	/* 0x2a */ KEY_BACKSLASH,	/*  43 */
+	/* 0x2b */ KEY_COMMA,		/*  51 */
+	/* 0x2c */ KEY_SLASH,		/*  53 */
+	/* 0x2d */ KEY_N,		/*  49 */
+	/* 0x2e */ KEY_M,		/*  50 */
+	/* 0x2f */ KEY_DOT,		/*  52 */
+	/* 0x30 */ KEY_TAB,		/*  15 */
+	/* 0x31 */ KEY_SPACE,		/*  57 */
+	/* 0x32 */ KEY_GRAVE,		/*  41 */
+	/* 0x33 */ KEY_BACKSPACE,	/*  14 */
+	/* 0x34 */ KEY_KPENTER,		/*  96 */
+	/* 0x35 */ KEY_ESC,		/*   1 */
+	/* 0x36 */ KEY_LEFTCTRL,	/*  29 */
+	/* 0x37 */ KEY_LEFTMETA,	/* 125 */
+	/* 0x38 */ KEY_LEFTSHIFT,	/*  42 */
+	/* 0x39 */ KEY_CAPSLOCK,	/*  58 */
+	/* 0x3a */ KEY_LEFTALT,		/*  56 */
+	/* 0x3b */ KEY_LEFT,		/* 105 */
+	/* 0x3c */ KEY_RIGHT,		/* 106 */
+	/* 0x3d */ KEY_DOWN,		/* 108 */
+	/* 0x3e */ KEY_UP,		/* 103 */
+	/* 0x3f */ 0,
+	/* 0x40 */ 0,
+	/* 0x41 */ KEY_KPDOT,		/*  83 */
+	/* 0x42 */ 0,
+	/* 0x43 */ KEY_KPASTERISK,	/*  55 */
+	/* 0x44 */ 0,
+	/* 0x45 */ KEY_KPPLUS,		/*  78 */
+	/* 0x46 */ 0,
+	/* 0x47 */ KEY_NUMLOCK,		/*  69 */
+	/* 0x48 */ 0,
+	/* 0x49 */ 0,
+	/* 0x4a */ 0,
+	/* 0x4b */ KEY_KPSLASH,		/*  98 */
+	/* 0x4c */ KEY_KPENTER,		/*  96 */
+	/* 0x4d */ 0,
+	/* 0x4e */ KEY_KPMINUS,		/*  74 */
+	/* 0x4f */ 0,
+	/* 0x50 */ 0,
+	/* 0x51 */ KEY_KPEQUAL,		/* 117 */
+	/* 0x52 */ KEY_KP0,		/*  82 */
+	/* 0x53 */ KEY_KP1,		/*  79 */
+	/* 0x54 */ KEY_KP2,		/*  80 */
+	/* 0x55 */ KEY_KP3,		/*  81 */
+	/* 0x56 */ KEY_KP4,		/*  75 */
+	/* 0x57 */ KEY_KP5,		/*  76 */
+	/* 0x58 */ KEY_KP6,		/*  77 */
+	/* 0x59 */ KEY_KP7,		/*  71 */
+	/* 0x5a */ 0,
+	/* 0x5b */ KEY_KP8,		/*  72 */
+	/* 0x5c */ KEY_KP9,		/*  73 */
+	/* 0x5d */ KEY_YEN,		/* 124 */
+	/* 0x5e */ KEY_RO,		/*  89 */
+	/* 0x5f */ KEY_KPCOMMA,		/* 121 */
+	/* 0x60 */ KEY_F5,		/*  63 */
+	/* 0x61 */ KEY_F6,		/*  64 */
+	/* 0x62 */ KEY_F7,		/*  65 */
+	/* 0x63 */ KEY_F3,		/*  61 */
+	/* 0x64 */ KEY_F8,		/*  66 */
+	/* 0x65 */ KEY_F9,		/*  67 */
+	/* 0x66 */ KEY_HANJA,		/* 123 */
+	/* 0x67 */ KEY_F11,		/*  87 */
+	/* 0x68 */ KEY_HANGUEL,		/* 122 */
+	/* 0x69 */ KEY_SYSRQ,		/*  99 */
+	/* 0x6a */ 0,
+	/* 0x6b */ KEY_SCROLLLOCK,	/*  70 */
+	/* 0x6c */ 0,
+	/* 0x6d */ KEY_F10,		/*  68 */
+	/* 0x6e */ KEY_COMPOSE,		/* 127 */
+	/* 0x6f */ KEY_F12,		/*  88 */
+	/* 0x70 */ 0,
+	/* 0x71 */ KEY_PAUSE,		/* 119 */
+	/* 0x72 */ KEY_INSERT,		/* 110 */
+	/* 0x73 */ KEY_HOME,		/* 102 */
+	/* 0x74 */ KEY_PAGEUP,		/* 104 */
+	/* 0x75 */ KEY_DELETE,		/* 111 */
+	/* 0x76 */ KEY_F4,		/*  62 */
+	/* 0x77 */ KEY_END,		/* 107 */
+	/* 0x78 */ KEY_F2,		/*  60 */
+	/* 0x79 */ KEY_PAGEDOWN,	/* 109 */
+	/* 0x7a */ KEY_F1,		/*  59 */
+	/* 0x7b */ KEY_RIGHTSHIFT,	/*  54 */
+	/* 0x7c */ KEY_RIGHTALT,	/* 100 */
+	/* 0x7d */ KEY_RIGHTCTRL,	/*  97 */
+	/* 0x7e */ KEY_RIGHTMETA,	/* 126 */
+	/* 0x7f */ KEY_POWER,		/* 116 */
 };
 
 struct adbhid {
@@ -326,7 +446,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,
@@ -453,7 +573,7 @@
 
 static void leds_done(struct adb_request *req)
 {
-	int leds, device;
+	int leds = 0, device = 0, pending = 0;
 	unsigned long flags;
 
 	spin_lock_irqsave(&leds_lock, flags);
@@ -464,11 +584,11 @@
 		leds_pending[device] = 0;
 		pending_led_start++;
 		pending_led_start = (pending_led_start < 16) ? pending_led_start : 0;
+		pending = leds_req_pending;
 	} else
 		leds_req_pending = 0;
-
 	spin_unlock_irqrestore(&leds_lock, flags);
-	if (leds_req_pending)
+	if (pending)
 		adb_request(&led_request, leds_done, 0, 3,
 			    ADB_WRITEREG(device, KEYB_LEDREG), 0xff, ~leds);
 }
diff -Nru a/drivers/macintosh/ans-lcd.c b/drivers/macintosh/ans-lcd.c
--- a/drivers/macintosh/ans-lcd.c	2004-10-18 14:57:04 -07:00
+++ b/drivers/macintosh/ans-lcd.c	2004-10-18 14:57:04 -07:00
@@ -9,6 +9,8 @@
 #include <linux/fcntl.h>
 #include <linux/init.h>
 #include <linux/delay.h>
+#include <linux/fs.h>
+
 #include <asm/uaccess.h>
 #include <asm/sections.h>
 #include <asm/prom.h>
@@ -154,7 +156,7 @@
 	retval = misc_register(&anslcd_dev);
 	if(retval < 0){
 		printk(KERN_INFO "LCD: misc_register failed\n");
-		iounmap(anslcd_ptr);
+		iounmap((void *)anslcd_ptr);
 		return retval;
 	}
 
@@ -177,7 +179,7 @@
 anslcd_exit(void)
 {
 	misc_deregister(&anslcd_dev);
-	iounmap(anslcd_ptr);
+	iounmap((void *)anslcd_ptr);
 }
 
 module_init(anslcd_init);
diff -Nru a/drivers/macintosh/macserial.c b/drivers/macintosh/macserial.c
--- a/drivers/macintosh/macserial.c	2004-10-18 14:57:04 -07:00
+++ b/drivers/macintosh/macserial.c	2004-10-18 14:57:04 -07:00
@@ -713,12 +713,8 @@
 	if (!tty)
 		return;
 
-	if (test_and_clear_bit(RS_EVENT_WRITE_WAKEUP, &info->event)) {
-		if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
-		    tty->ldisc.write_wakeup)
-			(tty->ldisc.write_wakeup)(tty);
-		wake_up_interruptible(&tty->write_wait);
-	}
+	if (test_and_clear_bit(RS_EVENT_WRITE_WAKEUP, &info->event))
+		tty_wakeup(tty);
 }
 
 static int startup(struct mac_serial * info)
@@ -1564,10 +1560,7 @@
 	spin_lock_irqsave(&info->lock, flags);
 	info->xmit_cnt = info->xmit_head = info->xmit_tail = 0;
 	spin_unlock_irqrestore(&info->lock, flags);
-	wake_up_interruptible(&tty->write_wait);
-	if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
-	    tty->ldisc.write_wakeup)
-		(tty->ldisc.write_wakeup)(tty);
+	tty_wakeup(tty);
 }
 
 /*
@@ -1994,16 +1987,14 @@
 
 	if (tty->driver->flush_buffer)
 		tty->driver->flush_buffer(tty);
-	if (tty->ldisc.flush_buffer)
-		tty->ldisc.flush_buffer(tty);
+	tty_ldisc_flush(tty);
 	tty->closing = 0;
 	info->event = 0;
 	info->tty = 0;
 
 	if (info->blocked_open) {
 		if (info->close_delay) {
-			current->state = TASK_INTERRUPTIBLE;
-			schedule_timeout(info->close_delay);
+			msleep_interruptible(jiffies_to_msecs(info->close_delay));
 		}
 		wake_up_interruptible(&info->open_wait);
 	}
@@ -2048,8 +2039,7 @@
 	if (timeout)
 		char_time = min_t(unsigned long, char_time, timeout);
 	while ((read_zsreg(info->zs_channel, 1) & ALL_SNT) == 0) {
-		current->state = TASK_INTERRUPTIBLE;
-		schedule_timeout(char_time);
+		msleep_interruptible(jiffies_to_msecs(char_time));
 		if (signal_pending(current))
 			break;
 		if (timeout && time_after(jiffies, orig_jiffies + timeout))
diff -Nru a/drivers/macintosh/therm_adt746x.c b/drivers/macintosh/therm_adt746x.c
--- a/drivers/macintosh/therm_adt746x.c	2004-10-18 14:56:49 -07:00
+++ b/drivers/macintosh/therm_adt746x.c	2004-10-18 14:56:49 -07:00
@@ -28,6 +28,7 @@
 #include <asm/system.h>
 #include <asm/sections.h>
 #include <asm/of_device.h>
+#include <linux/kthread.h>
 
 #undef DEBUG
 
@@ -53,7 +54,7 @@
 MODULE_LICENSE("GPL");
 
 MODULE_PARM(limit_adjust,"i");
-MODULE_PARM_DESC(limit_adjust,"Adjust maximum temperatures (50°C cpu, 70°C gpu) by N °C.");
+MODULE_PARM_DESC(limit_adjust,"Adjust maximum temperatures (50 cpu, 70 gpu) by N degrees.");
 MODULE_PARM(fan_speed,"i");
 MODULE_PARM_DESC(fan_speed,"Specify fan speed (0-255) when lim < temp < lim+8 (default 128)");
 
@@ -70,9 +71,7 @@
 static int therm_bus, therm_address;
 static struct of_device * of_dev;
 static struct thermostat* thermostat;
-static pid_t monitor_thread_id;
-static int monitor_running;
-static struct completion monitor_task_compl;
+static struct task_struct *thread_therm = NULL;
 
 static int attach_one_thermostat(struct i2c_adapter *adapter, int addr, int busno);
 static void write_both_fan_speed(struct thermostat *th, int speed);
@@ -136,13 +135,12 @@
 
 	th = thermostat;
 
-	if (monitor_running) {
-		monitor_running = 0;
-		wait_for_completion(&monitor_task_compl);
+	if (thread_therm != NULL) {
+		kthread_stop(thread_therm);
 	}
 		
 	printk(KERN_INFO "adt746x: Putting max temperatures back from %d, %d, %d,"
-		" to %d, %d, %d, (°C)\n", 
+		" to %d, %d, %d\n",
 		th->limits[0], th->limits[1], th->limits[2],
 		th->initial_limits[0], th->initial_limits[1], th->initial_limits[2]);
 	
@@ -178,7 +176,8 @@
 	tmp[0] = read_reg(th, addr + 1);
 	
 	res = tmp[1] + (tmp[0] << 8);
-	return (90000*60)/res;
+	/* "a value of 0xffff means that the fan has stopped" */
+	return (res == 0xffff ? 0 : (90000*60)/res);
 }
 
 static void write_both_fan_speed(struct thermostat *th, int speed)
@@ -237,16 +236,9 @@
 #ifdef DEBUG
 	int mfan_speed;
 #endif
-	
-	lock_kernel();
-	daemonize("kfand");
-	unlock_kernel();
-	strcpy(current->comm, "thermostat");
-	monitor_running = 1;
-
-	while(monitor_running)
+	while(!kthread_should_stop())
 	{
-		msleep(2000);
+		msleep_interruptible(2000);
 
 		/* Check status */
 		/* local   : chip */
@@ -270,14 +262,14 @@
 				int var = temps[i] - lims[i];
 				if (var > 8) {
 					if (th->overriding[fan_number] == 0)
-						printk(KERN_INFO "adt746x: Limit exceeded by %d°C, overriding specified fan speed for %s.\n",
+						printk(KERN_INFO "adt746x: Limit exceeded by %d, overriding specified fan speed for %s.\n",
 							var, fan_number?"GPU":"CPU");
 					th->overriding[fan_number] = 1;
 					write_fan_speed(th, 255, fan_number);
 					started = 1;
 				} else if ((!th->overriding[fan_number] || var < 6) && var > 0) {
 					if (th->overriding[fan_number] == 1)
-						printk(KERN_INFO "adt746x: Limit exceeded by %d°C, setting speed to specified for %s.\n",
+						printk(KERN_INFO "adt746x: Limit exceeded by %d, setting speed to specified for %s.\n",
 							var, fan_number?"GPU":"CPU");					
 					th->overriding[fan_number] = 0;
 					write_fan_speed(th, fan_speed, fan_number);
@@ -308,8 +300,8 @@
 		||  temps[1] != th->cached_temp[1]
 		||  temps[2] != th->cached_temp[2]) {
 			printk(KERN_INFO "adt746x: Temperature infos:"
-					 " thermostats: %d,%d,%d °C;"
-					 " limits: %d,%d,%d °C;"
+					 " thermostats: %d,%d,%d;"
+					 " limits: %d,%d,%d;"
 					 " fan speed: %d RPM\n",
 				temps[0], temps[1], temps[2],
 				lims[0],  lims[1],  lims[2],
@@ -321,7 +313,6 @@
 #endif		
 	}
 
-	complete_and_exit(&monitor_task_compl, 0);
 	return 0;
 }
 
@@ -380,14 +371,14 @@
 	}
 	
 	printk(KERN_INFO "adt746x: Lowering max temperatures from %d, %d, %d"
-		" to %d, %d, %d (°C)\n", 
+		" to %d, %d, %d\n",
 		th->initial_limits[0], th->initial_limits[1], th->initial_limits[2], 
 		th->limits[0], th->limits[1], th->limits[2]);
 
 	thermostat = th;
 
 	if (i2c_attach_client(&th->clt)) {
-		printk("adt746x: Thermostat failed to attach client !\n");
+		printk(KERN_INFO "adt746x: Thermostat failed to attach client !\n");
 		thermostat = NULL;
 		kfree(th);
 		return -ENODEV;
@@ -403,10 +394,13 @@
 		write_both_fan_speed(th, -1);
 	}
 	
-	init_completion(&monitor_task_compl);
-	
-	monitor_thread_id = kernel_thread(monitor_task, th,
-		SIGCHLD | CLONE_KERNEL);
+	thread_therm = kthread_run(monitor_task, th, "kfand");
+
+	if (thread_therm == ERR_PTR(-ENOMEM)) {
+		printk(KERN_INFO "adt746x: Kthread creation failed\n");
+		thread_therm = NULL;
+		return -ENOMEM;
+	}
 
 	return 0;
 }
@@ -417,17 +411,21 @@
  * choice but implement a bunch of them...
  *
  */
-#define BUILD_SHOW_FUNC_DEG(name, data)				\
-static ssize_t show_##name(struct device *dev, char *buf)	\
-{								\
-	return sprintf(buf, "%d°C\n", data);			\
-}
 #define BUILD_SHOW_FUNC_INT(name, data)				\
 static ssize_t show_##name(struct device *dev, char *buf)	\
 {								\
 	return sprintf(buf, "%d\n", data);			\
 }
 
+#define BUILD_SHOW_FUNC_FAN(name, data)				\
+static ssize_t show_##name(struct device *dev, char *buf)       \
+{								\
+	return sprintf(buf, "%d (%d rpm)\n", 			\
+		thermostat->last_speed[data],			\
+		read_fan_speed(thermostat, FAN_SPEED[data])	\
+		);						\
+}
+
 #define BUILD_STORE_FUNC_DEG(name, data)			\
 static ssize_t store_##name(struct device *dev, const char *buf, size_t n) \
 {								\
@@ -448,19 +446,19 @@
 	val = simple_strtoul(buf, NULL, 10);			\
 	if (val < 0 || val > 255)				\
 		return -EINVAL;					\
-	printk(KERN_INFO "Setting fan speed to %d\n", val);	\
+	printk(KERN_INFO "Setting specified fan speed to %d\n", val);	\
 	data = val;						\
 	return n;						\
 }
 
-BUILD_SHOW_FUNC_DEG(cpu_temperature,	 (read_reg(thermostat, TEMP_REG[1])))
-BUILD_SHOW_FUNC_DEG(gpu_temperature,	 (read_reg(thermostat, TEMP_REG[2])))
-BUILD_SHOW_FUNC_DEG(cpu_limit,		 thermostat->limits[1])
-BUILD_SHOW_FUNC_DEG(gpu_limit,		 thermostat->limits[2])
+BUILD_SHOW_FUNC_INT(cpu_temperature,	 (read_reg(thermostat, TEMP_REG[1])))
+BUILD_SHOW_FUNC_INT(gpu_temperature,	 (read_reg(thermostat, TEMP_REG[2])))
+BUILD_SHOW_FUNC_INT(cpu_limit,		 thermostat->limits[1])
+BUILD_SHOW_FUNC_INT(gpu_limit,		 thermostat->limits[2])
 
 BUILD_SHOW_FUNC_INT(specified_fan_speed, fan_speed)
-BUILD_SHOW_FUNC_INT(cpu_fan_speed,	 (read_fan_speed(thermostat, FAN_SPEED[0])))
-BUILD_SHOW_FUNC_INT(gpu_fan_speed,	 (read_fan_speed(thermostat, FAN_SPEED[1])))
+BUILD_SHOW_FUNC_FAN(cpu_fan_speed,	 0)
+BUILD_SHOW_FUNC_FAN(gpu_fan_speed,	 1)
 
 BUILD_STORE_FUNC_INT(specified_fan_speed,fan_speed)
 BUILD_SHOW_FUNC_INT(limit_adjust,	 limit_adjust)
diff -Nru a/drivers/macintosh/therm_windtunnel.c b/drivers/macintosh/therm_windtunnel.c
--- a/drivers/macintosh/therm_windtunnel.c	2004-10-18 14:56:49 -07:00
+++ b/drivers/macintosh/therm_windtunnel.c	2004-10-18 14:56:49 -07:00
@@ -292,8 +292,7 @@
 	while( x.running ) {
 		up( &x.lock );
 
-		set_current_state(TASK_INTERRUPTIBLE);
-		schedule_timeout( 8*HZ );
+		msleep_interruptible(8000);
 		
 		down( &x.lock );
 		poll_temp();
diff -Nru a/drivers/macintosh/via-pmu.c b/drivers/macintosh/via-pmu.c
--- a/drivers/macintosh/via-pmu.c	2004-10-18 14:57:03 -07:00
+++ b/drivers/macintosh/via-pmu.c	2004-10-18 14:57:03 -07:00
@@ -52,7 +52,6 @@
 #include <asm/system.h>
 #include <asm/sections.h>
 #include <asm/irq.h>
-#include <asm/hardirq.h>
 #include <asm/pmac_feature.h>
 #include <asm/uaccess.h>
 #include <asm/mmu_context.h>
@@ -138,7 +137,6 @@
 static volatile int adb_int_pending;
 static volatile int disable_poll;
 static struct adb_request bright_req_1, bright_req_2;
-static unsigned long async_req_locks;
 static struct device_node *vias;
 static int pmu_kind = PMU_UNKNOWN;
 static int pmu_fully_inited = 0;
@@ -155,6 +153,7 @@
 static int option_lid_wakeup = 1;
 static int sleep_in_progress;
 static int can_sleep;
+static unsigned long async_req_locks;
 #endif /* CONFIG_PMAC_PBOOK */
 static unsigned int pmu_irq_stats[11];
 
@@ -494,12 +493,9 @@
 	/* Create /proc/pmu */
 	proc_pmu_root = proc_mkdir("pmu", NULL);
 	if (proc_pmu_root) {
-		int i;
-		proc_pmu_info = create_proc_read_entry("info", 0, proc_pmu_root,
-					proc_get_info, NULL);
-		proc_pmu_irqstats = create_proc_read_entry("interrupts", 0, proc_pmu_root,
-					proc_get_irqstats, NULL);
 #ifdef CONFIG_PMAC_PBOOK
+		int i;
+
 		for (i=0; i<pmu_battery_count; i++) {
 			char title[16];
 			sprintf(title, "battery_%d", i);
@@ -507,6 +503,11 @@
 						proc_get_batt, (void *)i);
 		}
 #endif /* CONFIG_PMAC_PBOOK */
+
+		proc_pmu_info = create_proc_read_entry("info", 0, proc_pmu_root,
+					proc_get_info, NULL);
+		proc_pmu_irqstats = create_proc_read_entry("interrupts", 0, proc_pmu_root,
+					proc_get_irqstats, NULL);
 		proc_pmu_options = create_proc_entry("options", 0600, proc_pmu_root);
 		if (proc_pmu_options) {
 			proc_pmu_options->nlink = 1;
@@ -746,6 +747,8 @@
 		pmu_power_flags &= ~PMU_PWR_AC_PRESENT;
 
 
+	capa = max = amperage = voltage = 0;
+	
 	if (req->reply[1] & 0x04) {
 		bat_flags |= PMU_BATT_PRESENT;
 		switch(req->reply[0]) {
@@ -765,8 +768,7 @@
 					req->reply_len, req->reply[0], req->reply[1], req->reply[2], req->reply[3]);
 				break;
 		}
-	} else
-		capa = max = amperage = voltage = 0;
+	}
 
 	if ((req->reply[1] & 0x01) && (amperage > 0))
 		bat_flags |= PMU_BATT_CHARGING;
@@ -1445,7 +1447,7 @@
 pmu_sr_intr(struct pt_regs *regs)
 {
 	struct adb_request *req;
-	int bite;
+	int bite = 0;
 
 	if (via[B] & TREQ) {
 		printk(KERN_ERR "PMU: spurious SR intr (%x)\n", via[B]);
diff -Nru a/drivers/md/Kconfig b/drivers/md/Kconfig
--- a/drivers/md/Kconfig	2004-10-18 14:55:55 -07:00
+++ b/drivers/md/Kconfig	2004-10-18 14:55:55 -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-10-18 14:56:32 -07:00
+++ b/drivers/md/Makefile	2004-10-18 14:56:32 -07:00
@@ -10,7 +10,7 @@
 		   raid6int1.o raid6int2.o raid6int4.o \
 		   raid6int8.o raid6int16.o raid6int32.o \
 		   raid6mmx.o raid6sse1.o raid6sse2.o
-host-progs	:= mktables
+hostprogs-y	:= mktables
 
 # Note: link order is important.  All raid personalities
 # and xor.o must come before md.o, as they each initialise 
@@ -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/dm-log.c b/drivers/md/dm-log.c
--- a/drivers/md/dm-log.c	2004-10-18 14:57:04 -07:00
+++ b/drivers/md/dm-log.c	2004-10-18 14:57:04 -07:00
@@ -140,6 +140,13 @@
 
 	int sync_search;
 
+	/* Resync flag */
+	enum sync {
+		DEFAULTSYNC,	/* Synchronize if necessary */
+		NOSYNC,		/* Devices known to be already in sync */
+		FORCESYNC,	/* Force a sync to happen */
+	} sync;
+
 	/*
 	 * Disk log fields
 	 */
@@ -205,7 +212,8 @@
 
 	header_from_disk(&log->header, log->disk_header);
 
-	if (log->header.magic != MIRROR_MAGIC) {
+	/* New log required? */
+	if (log->sync != DEFAULTSYNC || log->header.magic != MIRROR_MAGIC) {
 		log->header.magic = MIRROR_MAGIC;
 		log->header.version = MIRROR_DISK_VERSION;
 		log->header.nr_regions = 0;
@@ -273,22 +281,38 @@
 }
 
 /*----------------------------------------------------------------
- * constructor/destructor
+ * core log constructor/destructor
+ *
+ * argv contains region_size followed optionally by [no]sync
  *--------------------------------------------------------------*/
 #define BYTE_SHIFT 3
 static int core_ctr(struct dirty_log *log, struct dm_target *ti,
 		    unsigned int argc, char **argv)
 {
+	enum sync sync = DEFAULTSYNC;
+
 	struct log_c *lc;
 	sector_t region_size;
 	unsigned int region_count;
 	size_t bitset_size;
 
-	if (argc != 1) {
-		DMWARN("wrong number of arguments to log_c");
+	if (argc < 1 || argc > 2) {
+		DMWARN("wrong number of arguments to mirror log");
 		return -EINVAL;
 	}
 
+	if (argc > 1) {
+		if (!strcmp(argv[1], "sync"))
+			sync = FORCESYNC;
+		else if (!strcmp(argv[1], "nosync"))
+			sync = NOSYNC;
+		else {
+			DMWARN("unrecognised sync argument to mirror log: %s",
+			       argv[1]);
+			return -EINVAL;
+		}
+	}
+
 	if (sscanf(argv[0], SECTOR_FORMAT, &region_size) != 1) {
 		DMWARN("invalid region size string");
 		return -EINVAL;
@@ -306,6 +330,7 @@
 	lc->touched = 0;
 	lc->region_size = region_size;
 	lc->region_count = region_count;
+	lc->sync = sync;
 
 	/*
 	 * Work out how many words we need to hold the bitset.
@@ -330,8 +355,8 @@
 		kfree(lc);
 		return -ENOMEM;
 	}
-	memset(lc->sync_bits, 0, bitset_size);
-        lc->sync_count = 0;
+	memset(lc->sync_bits, (sync == NOSYNC) ? -1 : 0, bitset_size);
+	lc->sync_count = (sync == NOSYNC) ? region_count : 0;
 
 	lc->recovering_bits = vmalloc(bitset_size);
 	if (!lc->recovering_bits) {
@@ -356,6 +381,11 @@
 	kfree(lc);
 }
 
+/*----------------------------------------------------------------
+ * disk log constructor/destructor
+ *
+ * argv contains log_device region_size followed optionally by [no]sync
+ *--------------------------------------------------------------*/
 static int disk_ctr(struct dirty_log *log, struct dm_target *ti,
 		    unsigned int argc, char **argv)
 {
@@ -364,8 +394,8 @@
 	struct log_c *lc;
 	struct dm_dev *dev;
 
-	if (argc != 2) {
-		DMWARN("wrong number of arguments to log_d");
+	if (argc < 2 || argc > 3) {
+		DMWARN("wrong number of arguments to disk mirror log");
 		return -EINVAL;
 	}
 
@@ -452,10 +482,15 @@
 	if (r)
 		return r;
 
-	/* zero any new bits if the mirror has grown */
-	for (i = lc->header.nr_regions; i < lc->region_count; i++)
-		/* FIXME: amazingly inefficient */
-		log_clear_bit(lc, lc->clean_bits, i);
+	/* set or clear any new bits */
+	if (lc->sync == NOSYNC)
+		for (i = lc->header.nr_regions; i < lc->region_count; i++)
+			/* FIXME: amazingly inefficient */
+			log_set_bit(lc, lc->clean_bits, i);
+	else
+		for (i = lc->header.nr_regions; i < lc->region_count; i++)
+			/* FIXME: amazingly inefficient */
+			log_clear_bit(lc, lc->clean_bits, i);
 
 	/* copy clean across to sync */
 	memcpy(lc->sync_bits, lc->clean_bits, size);
@@ -566,6 +601,51 @@
         return lc->sync_count;
 }
 
+#define	DMEMIT_SYNC \
+	if (lc->sync != DEFAULTSYNC) \
+		DMEMIT("%ssync ", lc->sync == NOSYNC ? "no" : "")
+
+static int core_status(struct dirty_log *log, status_type_t status,
+		       char *result, unsigned int maxlen)
+{
+	int sz = 0;
+	struct log_c *lc = log->context;
+
+	switch(status) {
+	case STATUSTYPE_INFO:
+		break;
+
+	case STATUSTYPE_TABLE:
+		DMEMIT("%s %u " SECTOR_FORMAT " ", log->type->name,
+		       lc->sync == DEFAULTSYNC ? 1 : 2, lc->region_size);
+		DMEMIT_SYNC;
+	}
+
+	return sz;
+}
+
+static int disk_status(struct dirty_log *log, status_type_t status,
+		       char *result, unsigned int maxlen)
+{
+	int sz = 0;
+	char buffer[16];
+	struct log_c *lc = log->context;
+
+	switch(status) {
+	case STATUSTYPE_INFO:
+		break;
+
+	case STATUSTYPE_TABLE:
+		format_dev_t(buffer, lc->log_dev->bdev->bd_dev);
+		DMEMIT("%s %u %s " SECTOR_FORMAT " ", log->type->name,
+		       lc->sync == DEFAULTSYNC ? 2 : 3, buffer,
+		       lc->region_size);
+		DMEMIT_SYNC;
+	}
+
+	return sz;
+}
+
 static struct dirty_log_type _core_type = {
 	.name = "core",
 	.module = THIS_MODULE,
@@ -579,7 +659,8 @@
 	.clear_region = core_clear_region,
 	.get_resync_work = core_get_resync_work,
 	.complete_resync_work = core_complete_resync_work,
-        .get_sync_count = core_get_sync_count
+	.get_sync_count = core_get_sync_count,
+	.status = core_status,
 };
 
 static struct dirty_log_type _disk_type = {
@@ -597,7 +678,8 @@
 	.clear_region = core_clear_region,
 	.get_resync_work = core_get_resync_work,
 	.complete_resync_work = core_complete_resync_work,
-        .get_sync_count = core_get_sync_count
+	.get_sync_count = core_get_sync_count,
+	.status = disk_status,
 };
 
 int __init dm_dirty_log_init(void)
diff -Nru a/drivers/md/dm-log.h b/drivers/md/dm-log.h
--- a/drivers/md/dm-log.h	2004-10-18 14:56:20 -07:00
+++ b/drivers/md/dm-log.h	2004-10-18 14:56:20 -07:00
@@ -101,6 +101,12 @@
 	 * Returns the number of regions that are in sync.
          */
         region_t (*get_sync_count)(struct dirty_log *log);
+
+	/*
+	 * Support function for mirror status requests.
+	 */
+	int (*status)(struct dirty_log *log, status_type_t status_type,
+		      char *result, unsigned int maxlen);
 };
 
 int dm_register_dirty_log_type(struct dirty_log_type *type);
diff -Nru a/drivers/md/dm-raid1.c b/drivers/md/dm-raid1.c
--- a/drivers/md/dm-raid1.c	2004-10-18 14:57:05 -07:00
+++ b/drivers/md/dm-raid1.c	2004-10-18 14:57:05 -07:00
@@ -1009,8 +1009,8 @@
  * log_type #log_params <log_params>
  * #mirrors [mirror_path offset]{2,}
  *
- * For now, #log_params = 1, log_type = "core"
- *
+ * log_type is "core" or "disk"
+ * #log_params is between 1 and 3
  */
 #define DM_IO_PAGES 64
 static int mirror_ctr(struct dm_target *ti, unsigned int argc, char **argv)
@@ -1182,35 +1182,30 @@
 			 char *result, unsigned int maxlen)
 {
 	char buffer[32];
-	unsigned int m, sz = 0;
+	unsigned int m, sz;
 	struct mirror_set *ms = (struct mirror_set *) ti->private;
 
-#define EMIT(x...) sz += ((sz >= maxlen) ? \
-			  0 : scnprintf(result + sz, maxlen - sz, x))
+	sz = ms->rh.log->type->status(ms->rh.log, type, result, maxlen);
 
 	switch (type) {
 	case STATUSTYPE_INFO:
-		EMIT("%d ", ms->nr_mirrors);
-
+		DMEMIT("%d ", ms->nr_mirrors);
 		for (m = 0; m < ms->nr_mirrors; m++) {
 			format_dev_t(buffer, ms->mirror[m].dev->bdev->bd_dev);
-			EMIT("%s ", buffer);
+			DMEMIT("%s ", buffer);
 		}
 
-		EMIT(SECTOR_FORMAT "/" SECTOR_FORMAT,
-		     ms->rh.log->type->get_sync_count(ms->rh.log),
-		     ms->nr_regions);
+		DMEMIT(SECTOR_FORMAT "/" SECTOR_FORMAT,
+		       ms->rh.log->type->get_sync_count(ms->rh.log),
+		       ms->nr_regions);
 		break;
 
 	case STATUSTYPE_TABLE:
-		EMIT("%s 1 " SECTOR_FORMAT " %d ",
-		     ms->rh.log->type->name, ms->rh.region_size,
-		     ms->nr_mirrors);
-
+		DMEMIT("%d ", ms->nr_mirrors);
 		for (m = 0; m < ms->nr_mirrors; m++) {
 			format_dev_t(buffer, ms->mirror[m].dev->bdev->bd_dev);
-			EMIT("%s " SECTOR_FORMAT " ",
-			     buffer, ms->mirror[m].offset);
+			DMEMIT("%s " SECTOR_FORMAT " ",
+			       buffer, ms->mirror[m].offset);
 		}
 	}
 
diff -Nru a/drivers/md/dm-stripe.c b/drivers/md/dm-stripe.c
--- a/drivers/md/dm-stripe.c	2004-10-18 14:56:29 -07:00
+++ b/drivers/md/dm-stripe.c	2004-10-18 14:56:29 -07:00
@@ -191,20 +191,17 @@
 	unsigned int i;
 	char buffer[32];
 
-#define EMIT(x...) sz += ((sz >= maxlen) ? \
-			  0 : scnprintf(result + sz, maxlen - sz, x))
-
 	switch (type) {
 	case STATUSTYPE_INFO:
 		result[0] = '\0';
 		break;
 
 	case STATUSTYPE_TABLE:
-		EMIT("%d " SECTOR_FORMAT, sc->stripes, sc->chunk_mask + 1);
+		DMEMIT("%d " SECTOR_FORMAT, sc->stripes, sc->chunk_mask + 1);
 		for (i = 0; i < sc->stripes; i++) {
 			format_dev_t(buffer, sc->stripe[i].dev->bdev->bd_dev);
-			EMIT(" %s " SECTOR_FORMAT, buffer,
-			     sc->stripe[i].physical_start);
+			DMEMIT(" %s " SECTOR_FORMAT, buffer,
+			       sc->stripe[i].physical_start);
 		}
 		break;
 	}
diff -Nru a/drivers/md/dm-table.c b/drivers/md/dm-table.c
--- a/drivers/md/dm-table.c	2004-10-18 14:57:04 -07:00
+++ b/drivers/md/dm-table.c	2004-10-18 14:57:04 -07:00
@@ -825,7 +825,7 @@
 	 * Make sure we obey the optimistic sub devices
 	 * restrictions.
 	 */
-	q->max_sectors = t->limits.max_sectors;
+	blk_queue_max_sectors(q, t->limits.max_sectors);
 	q->max_phys_segments = t->limits.max_phys_segments;
 	q->max_hw_segments = t->limits.max_hw_segments;
 	q->hardsect_size = t->limits.hardsect_size;
@@ -900,6 +900,28 @@
 	}
 }
 
+int dm_table_flush_all(struct dm_table *t)
+{
+	struct list_head *d, *devices = dm_table_get_devices(t);
+	int ret = 0;
+
+	for (d = devices->next; d != devices; d = d->next) {
+		struct dm_dev *dd = list_entry(d, struct dm_dev, list);
+		request_queue_t *q = bdev_get_queue(dd->bdev);
+		int err;
+
+		if (!q->issue_flush_fn)
+			err = -EOPNOTSUPP;
+		else
+			err = q->issue_flush_fn(q, dd->bdev->bd_disk, NULL);
+
+		if (!ret)
+			ret = err;
+	}
+
+	return ret;
+}
+
 EXPORT_SYMBOL(dm_vcalloc);
 EXPORT_SYMBOL(dm_get_device);
 EXPORT_SYMBOL(dm_put_device);
@@ -908,3 +930,4 @@
 EXPORT_SYMBOL(dm_table_put);
 EXPORT_SYMBOL(dm_table_get);
 EXPORT_SYMBOL(dm_table_unplug_all);
+EXPORT_SYMBOL(dm_table_flush_all);
diff -Nru a/drivers/md/dm.c b/drivers/md/dm.c
--- a/drivers/md/dm.c	2004-10-18 14:56:49 -07:00
+++ b/drivers/md/dm.c	2004-10-18 14:56:49 -07:00
@@ -15,15 +15,13 @@
 #include <linux/buffer_head.h>
 #include <linux/mempool.h>
 #include <linux/slab.h>
+#include <linux/idr.h>
 
 static const char *_name = DM_NAME;
 
 static unsigned int major = 0;
 static unsigned int _major = 0;
 
-static int realloc_minor_bits(unsigned long requested_minor);
-static void free_minor_bits(void);
-
 /*
  * One of these is allocated per bio.
  */
@@ -113,19 +111,11 @@
 		return -ENOMEM;
 	}
 
-	r = realloc_minor_bits(1024);
-	if (r < 0) {
-		kmem_cache_destroy(_tio_cache);
-		kmem_cache_destroy(_io_cache);
-		return r;
-	}
-
 	_major = major;
 	r = register_blkdev(_major, _name);
 	if (r < 0) {
 		kmem_cache_destroy(_tio_cache);
 		kmem_cache_destroy(_io_cache);
-		free_minor_bits();
 		return r;
 	}
 
@@ -139,7 +129,6 @@
 {
 	kmem_cache_destroy(_tio_cache);
 	kmem_cache_destroy(_io_cache);
-	free_minor_bits();
 
 	if (unregister_blkdev(_major, _name) < 0)
 		DMERR("devfs_unregister_blkdev failed");
@@ -597,6 +586,21 @@
 	return 0;
 }
 
+static int dm_flush_all(request_queue_t *q, struct gendisk *disk,
+			sector_t *error_sector)
+{
+	struct mapped_device *md = q->queuedata;
+	struct dm_table *map = dm_get_table(md);
+	int ret = -ENXIO;
+
+	if (map) {
+		ret = dm_table_flush_all(md->map);
+		dm_table_put(map);
+	}
+
+	return ret;
+}
+
 static void dm_unplug_all(request_queue_t *q)
 {
 	struct mapped_device *md = q->queuedata;
@@ -624,59 +628,15 @@
 }
 
 /*-----------------------------------------------------------------
- * A bitset is used to keep track of allocated minor numbers.
+ * An IDR is used to keep track of allocated minor numbers.
  *---------------------------------------------------------------*/
 static DECLARE_MUTEX(_minor_lock);
-static unsigned long *_minor_bits = NULL;
-static unsigned long _max_minors = 0;
-
-#define MINORS_SIZE(minors) ((minors / BITS_PER_LONG) * sizeof(unsigned long))
-
-static int realloc_minor_bits(unsigned long requested_minor)
-{
-	unsigned long max_minors;
-	unsigned long *minor_bits, *tmp;
-
-	if (requested_minor < _max_minors)
-		return -EINVAL;
-
-	/* Round up the requested minor to the next power-of-2. */
-	max_minors = 1 << fls(requested_minor - 1);
-	if (max_minors > (1 << MINORBITS))
-		return -EINVAL;
-
-	minor_bits = kmalloc(MINORS_SIZE(max_minors), GFP_KERNEL);
-	if (!minor_bits)
-		return -ENOMEM;
-	memset(minor_bits, 0, MINORS_SIZE(max_minors));
-
-	/* Copy the existing bit-set to the new one. */
-	if (_minor_bits)
-		memcpy(minor_bits, _minor_bits, MINORS_SIZE(_max_minors));
-
-	tmp = _minor_bits;
-	_minor_bits = minor_bits;
-	_max_minors = max_minors;
-	if (tmp)
-		kfree(tmp);
-
-	return 0;
-}
-
-static void free_minor_bits(void)
-{
-	down(&_minor_lock);
-	kfree(_minor_bits);
-	_minor_bits = NULL;
-	_max_minors = 0;
-	up(&_minor_lock);
-}
+static DEFINE_IDR(_minor_idr);
 
 static void free_minor(unsigned int minor)
 {
 	down(&_minor_lock);
-	if (minor < _max_minors)
-		clear_bit(minor, _minor_bits);
+	idr_remove(&_minor_idr, minor);
 	up(&_minor_lock);
 }
 
@@ -685,24 +645,37 @@
  */
 static int specific_minor(unsigned int minor)
 {
-	int r = 0;
+	int r, m;
 
-	if (minor > (1 << MINORBITS))
+	if (minor >= (1 << MINORBITS))
 		return -EINVAL;
 
 	down(&_minor_lock);
-	if (minor >= _max_minors) {
-		r = realloc_minor_bits(minor);
-		if (r) {
-			up(&_minor_lock);
-			return r;
-		}
+
+	if (idr_find(&_minor_idr, minor)) {
+		r = -EBUSY;
+		goto out;
+	}
+
+	r = idr_pre_get(&_minor_idr, GFP_KERNEL);
+	if (!r) {
+		r = -ENOMEM;
+		goto out;
+	}
+
+	r = idr_get_new_above(&_minor_idr, specific_minor, minor, &m);
+	if (r) {
+		goto out;
 	}
 
-	if (test_and_set_bit(minor, _minor_bits))
+	if (m != minor) {
+		idr_remove(&_minor_idr, m);
 		r = -EBUSY;
-	up(&_minor_lock);
+		goto out;
+	}
 
+out:
+	up(&_minor_lock);
 	return r;
 }
 
@@ -712,21 +685,29 @@
 	unsigned int m;
 
 	down(&_minor_lock);
-	m = find_first_zero_bit(_minor_bits, _max_minors);
-	if (m >= _max_minors) {
-		r = realloc_minor_bits(_max_minors * 2);
-		if (r) {
-			up(&_minor_lock);
-			return r;
-		}
-		m = find_first_zero_bit(_minor_bits, _max_minors);
+
+	r = idr_pre_get(&_minor_idr, GFP_KERNEL);
+	if (!r) {
+		r = -ENOMEM;
+		goto out;
+	}
+
+	r = idr_get_new(&_minor_idr, next_free_minor, &m);
+	if (r) {
+		goto out;
+	}
+
+	if (m >= (1 << MINORBITS)) {
+		idr_remove(&_minor_idr, m);
+		r = -ENOSPC;
+		goto out;
 	}
 
-	set_bit(m, _minor_bits);
 	*minor = m;
-	up(&_minor_lock);
 
-	return 0;
+out:
+	up(&_minor_lock);
+	return r;
 }
 
 static struct block_device_operations dm_blk_dops;
@@ -764,6 +745,7 @@
 	md->queue->backing_dev_info.congested_data = md;
 	blk_queue_make_request(md->queue, dm_request);
 	md->queue->unplug_fn = dm_unplug_all;
+	md->queue->issue_flush_fn = dm_flush_all;
 
 	md->io_pool = mempool_create(MIN_IOS, mempool_alloc_slab,
 				     mempool_free_slab, _io_cache);
diff -Nru a/drivers/md/dm.h b/drivers/md/dm.h
--- a/drivers/md/dm.h	2004-10-18 14:56:29 -07:00
+++ b/drivers/md/dm.h	2004-10-18 14:56:29 -07:00
@@ -19,6 +19,9 @@
 #define DMERR(f, x...) printk(KERN_ERR DM_NAME ": " f "\n" , ## x)
 #define DMINFO(f, x...) printk(KERN_INFO DM_NAME ": " f "\n" , ## x)
 
+#define DMEMIT(x...) sz += ((sz >= maxlen) ? \
+			  0 : scnprintf(result + sz, maxlen - sz, x))
+
 /*
  * FIXME: I think this should be with the definition of sector_t
  * in types.h.
@@ -113,6 +116,7 @@
 void dm_table_resume_targets(struct dm_table *t);
 int dm_table_any_congested(struct dm_table *t, int bdi_bits);
 void dm_table_unplug_all(struct dm_table *t);
+int dm_table_flush_all(struct dm_table *t);
 
 /*-----------------------------------------------------------------
  * A registry of target types.
diff -Nru a/drivers/md/linear.c b/drivers/md/linear.c
--- a/drivers/md/linear.c	2004-10-18 14:56:29 -07:00
+++ b/drivers/md/linear.c	2004-10-18 14:56:29 -07:00
@@ -47,7 +47,6 @@
 		return hash->dev0;
 }
 
-
 /**
  *	linear_mergeable_bvec -- tell bio layer if a two requests can be merged
  *	@q: request queue
@@ -93,6 +92,27 @@
 	}
 }
 
+static int linear_issue_flush(request_queue_t *q, struct gendisk *disk,
+			      sector_t *error_sector)
+{
+	mddev_t *mddev = q->queuedata;
+	linear_conf_t *conf = mddev_to_conf(mddev);
+	int i, ret = 0;
+
+	for (i=0; i < mddev->raid_disks; i++) {
+		struct block_device *bdev = conf->disks[i].rdev->bdev;
+		request_queue_t *r_queue = bdev_get_queue(bdev);
+
+		if (!r_queue->issue_flush_fn) {
+			ret = -EOPNOTSUPP;
+			break;
+		}
+		ret = r_queue->issue_flush_fn(r_queue, bdev->bd_disk, error_sector);
+		if (ret)
+			break;
+	}
+	return ret;
+}
 
 static int linear_run (mddev_t *mddev)
 {
@@ -137,7 +157,7 @@
 		 */
 		if (rdev->bdev->bd_disk->queue->merge_bvec_fn &&
 		    mddev->queue->max_sectors > (PAGE_SIZE>>9))
-			mddev->queue->max_sectors = (PAGE_SIZE>>9);
+			blk_queue_max_sectors(mddev->queue, PAGE_SIZE>>9);
 
 		disk->size = rdev->size;
 		mddev->array_size += rdev->size;
@@ -200,6 +220,7 @@
 
 	blk_queue_merge_bvec(mddev->queue, linear_mergeable_bvec);
 	mddev->queue->unplug_fn = linear_unplug;
+	mddev->queue->issue_flush_fn = linear_issue_flush;
 	return 0;
 
 out:
diff -Nru a/drivers/md/md.c b/drivers/md/md.c
--- a/drivers/md/md.c	2004-10-18 14:56:27 -07:00
+++ b/drivers/md/md.c	2004-10-18 14:56:27 -07:00
@@ -154,6 +154,39 @@
 		tmp = tmp->next;})					\
 		)
 
+int md_flush_mddev(mddev_t *mddev, sector_t *error_sector)
+{
+	struct list_head *tmp;
+	mdk_rdev_t *rdev;
+	int ret = 0;
+
+	/*
+	 * this list iteration is done without any locking in md?!
+	 */
+	ITERATE_RDEV(mddev, rdev, tmp) {
+		request_queue_t *r_queue = bdev_get_queue(rdev->bdev);
+		int err;
+
+		if (!r_queue->issue_flush_fn)
+			err = -EOPNOTSUPP;
+		else
+			err = r_queue->issue_flush_fn(r_queue, rdev->bdev->bd_disk, error_sector);
+
+		if (!ret)
+			ret = err;
+	}
+
+	return ret;
+}
+
+static int md_flush_all(request_queue_t *q, struct gendisk *disk,
+			 sector_t *error_sector)
+{
+	mddev_t *mddev = q->queuedata;
+
+	return md_flush_mddev(mddev, error_sector);
+}
+
 static int md_fail_request (request_queue_t *q, struct bio *bio)
 {
 	bio_io_error(bio, bio->bi_size);
@@ -373,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;
 }
@@ -439,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
@@ -521,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;
@@ -745,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;
 }
@@ -1042,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;
 	}
@@ -1117,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);
 }
 
@@ -1312,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));
@@ -1322,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;
@@ -1615,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");
@@ -1645,6 +1714,7 @@
 	 */
 	mddev->queue->queuedata = mddev;
 	mddev->queue->make_request_fn = mddev->pers->make_request;
+	mddev->queue->issue_flush_fn = md_flush_all;
 
 	mddev->changed = 1;
 	return 0;
@@ -1881,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);
@@ -1916,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);
 	}
 
@@ -2153,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];
@@ -2197,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;
@@ -2227,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",
@@ -2489,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;
@@ -2548,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;
@@ -2690,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;
@@ -2876,7 +2895,7 @@
 	return thread;
 }
 
-void md_interrupt_thread(mdk_thread_t *thread)
+static void md_interrupt_thread(mdk_thread_t *thread)
 {
 	if (!thread->tsk) {
 		MD_BUG();
@@ -2919,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);
 }
@@ -2951,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.
@@ -3187,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;
@@ -3204,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;
 		}
@@ -3339,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:"
@@ -3697,7 +3727,6 @@
 
 static void autostart_arrays(int part)
 {
-	char b[BDEVNAME_SIZE];
 	mdk_rdev_t *rdev;
 	int i;
 
@@ -3707,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;
@@ -3762,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);
@@ -3771,6 +3797,5 @@
 EXPORT_SYMBOL(md_unregister_thread);
 EXPORT_SYMBOL(md_wakeup_thread);
 EXPORT_SYMBOL(md_print_devices);
-EXPORT_SYMBOL(md_interrupt_thread);
 EXPORT_SYMBOL(md_check_recovery);
 MODULE_LICENSE("GPL");
diff -Nru a/drivers/md/multipath.c b/drivers/md/multipath.c
--- a/drivers/md/multipath.c	2004-10-18 14:56:29 -07:00
+++ b/drivers/md/multipath.c	2004-10-18 14:56:29 -07:00
@@ -99,12 +99,12 @@
  * operation and are ready to return a success/failure code to the buffer
  * cache layer.
  */
-static void multipath_end_bh_io (struct multipath_bh *mp_bh, int uptodate)
+static void multipath_end_bh_io (struct multipath_bh *mp_bh, int err)
 {
 	struct bio *bio = mp_bh->master_bio;
 	multipath_conf_t *conf = mddev_to_conf(mp_bh->mddev);
 
-	bio_endio(bio, bio->bi_size, uptodate ? 0 : -EIO);
+	bio_endio(bio, bio->bi_size, err);
 	mempool_free(mp_bh, conf->pool);
 }
 
@@ -119,8 +119,8 @@
 		return 1;
 
 	if (uptodate)
-		multipath_end_bh_io(mp_bh, uptodate);
-	else if ((bio->bi_rw & (1 << BIO_RW_AHEAD)) == 0) {
+		multipath_end_bh_io(mp_bh, 0);
+	else if (!bio_rw_ahead(bio)) {
 		/*
 		 * oops, IO error:
 		 */
@@ -131,7 +131,7 @@
 		       (unsigned long long)bio->bi_sector);
 		multipath_reschedule_retry(mp_bh);
 	} else
-		multipath_end_bh_io(mp_bh, 0);
+		multipath_end_bh_io(mp_bh, error);
 	rdev_dec_pending(rdev, conf->mddev);
 	return 0;
 }
@@ -217,6 +217,31 @@
 	seq_printf (seq, "]");
 }
 
+static int multipath_issue_flush(request_queue_t *q, struct gendisk *disk,
+				 sector_t *error_sector)
+{
+	mddev_t *mddev = q->queuedata;
+	multipath_conf_t *conf = mddev_to_conf(mddev);
+	int i, ret = 0;
+
+	for (i=0; i<mddev->raid_disks; i++) {
+		mdk_rdev_t *rdev = conf->multipaths[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 = -EOPNOTSUPP;
+				break;
+			}
+
+			ret = r_queue->issue_flush_fn(r_queue, bdev->bd_disk, error_sector);
+			if (ret)
+				break;
+		}
+	}
+	return ret;
+}
 
 /*
  * Careful, this can execute in IRQ contexts as well!
@@ -300,7 +325,7 @@
 		 */
 			if (rdev->bdev->bd_disk->queue->merge_bvec_fn &&
 			    mddev->queue->max_sectors > (PAGE_SIZE>>9))
-				mddev->queue->max_sectors = (PAGE_SIZE>>9);
+				blk_queue_max_sectors(mddev->queue, PAGE_SIZE>>9);
 
 			conf->working_disks++;
 			rdev->raid_disk = path;
@@ -377,7 +402,7 @@
 				" error for block %llu\n",
 				bdevname(bio->bi_bdev,b),
 				(unsigned long long)bio->bi_sector);
-			multipath_end_bh_io(mp_bh, 0);
+			multipath_end_bh_io(mp_bh, -EIO);
 		} else {
 			printk(KERN_ERR "multipath: %s: redirecting sector %llu"
 				" to another IO path\n",
@@ -435,6 +460,8 @@
 
 	mddev->queue->unplug_fn = multipath_unplug;
 
+	mddev->queue->issue_flush_fn = multipath_issue_flush;
+
 	conf->working_disks = 0;
 	ITERATE_RDEV(mddev,rdev,tmp) {
 		disk_idx = rdev->raid_disk;
@@ -452,7 +479,7 @@
 		 * a merge_bvec_fn to be involved in multipath */
 		if (rdev->bdev->bd_disk->queue->merge_bvec_fn &&
 		    mddev->queue->max_sectors > (PAGE_SIZE>>9))
-			mddev->queue->max_sectors = (PAGE_SIZE>>9);
+			blk_queue_max_sectors(mddev->queue, PAGE_SIZE>>9);
 
 		if (!rdev->faulty) 
 			conf->working_disks++;
diff -Nru a/drivers/md/raid0.c b/drivers/md/raid0.c
--- a/drivers/md/raid0.c	2004-10-18 14:56:32 -07:00
+++ b/drivers/md/raid0.c	2004-10-18 14:56:32 -07:00
@@ -40,6 +40,31 @@
 	}
 }
 
+static int raid0_issue_flush(request_queue_t *q, struct gendisk *disk,
+			     sector_t *error_sector)
+{
+	mddev_t *mddev = q->queuedata;
+	raid0_conf_t *conf = mddev_to_conf(mddev);
+	mdk_rdev_t **devlist = conf->strip_zone[0].dev;
+	int i, ret = 0;
+
+	for (i=0; i<mddev->raid_disks; i++) {
+		struct block_device *bdev = devlist[i]->bdev;
+		request_queue_t *r_queue = bdev_get_queue(bdev);
+
+		if (!r_queue->issue_flush_fn) {
+			ret = -EOPNOTSUPP;
+			break;
+		}
+
+		ret =r_queue->issue_flush_fn(r_queue, bdev->bd_disk, error_sector);
+		if (ret)
+			break;
+	}
+	return ret;
+}
+
+
 static int create_strip_zones (mddev_t *mddev)
 {
 	int i, c, j;
@@ -137,7 +162,7 @@
 
 		if (rdev1->bdev->bd_disk->queue->merge_bvec_fn &&
 		    mddev->queue->max_sectors > (PAGE_SIZE>>9))
-			mddev->queue->max_sectors = (PAGE_SIZE>>9);
+			blk_queue_max_sectors(mddev->queue, PAGE_SIZE>>9);
 
 		if (!smallest || (rdev1->size <smallest->size))
 			smallest = rdev1;
@@ -218,6 +243,8 @@
 	}
 
 	mddev->queue->unplug_fn = raid0_unplug;
+
+	mddev->queue->issue_flush_fn = raid0_issue_flush;
 
 	printk("raid0: done.\n");
 	return 0;
diff -Nru a/drivers/md/raid1.c b/drivers/md/raid1.c
--- a/drivers/md/raid1.c	2004-10-18 14:56:32 -07:00
+++ b/drivers/md/raid1.c	2004-10-18 14:56:32 -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;
@@ -481,6 +451,32 @@
 	unplug_slaves(q->queuedata);
 }
 
+static int raid1_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.
@@ -545,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;
@@ -746,7 +753,7 @@
 			 */
 			if (rdev->bdev->bd_disk->queue->merge_bvec_fn &&
 			    mddev->queue->max_sectors > (PAGE_SIZE>>9))
-				mddev->queue->max_sectors = (PAGE_SIZE>>9);
+				blk_queue_max_sectors(mddev->queue, PAGE_SIZE>>9);
 
 			p->head_position = 0;
 			rdev->raid_disk = mirror;
@@ -877,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);
 	}
 
@@ -925,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),
@@ -935,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;
@@ -1117,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);
 
@@ -1168,6 +1177,7 @@
 
 	mddev->queue->unplug_fn = raid1_unplug;
 
+	mddev->queue->issue_flush_fn = raid1_issue_flush;
 
 	ITERATE_RDEV(mddev, rdev, tmp) {
 		disk_idx = rdev->raid_disk;
@@ -1186,7 +1196,7 @@
 		 */
 		if (rdev->bdev->bd_disk->queue->merge_bvec_fn &&
 		    mddev->queue->max_sectors > (PAGE_SIZE>>9))
-			mddev->queue->max_sectors = (PAGE_SIZE>>9);
+			blk_queue_max_sectors(mddev->queue, PAGE_SIZE>>9);
 
 		disk->head_position = 0;
 		if (!rdev->faulty && rdev->in_sync)
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-10-18 14:57:24 -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-10-18 14:56:17 -07:00
+++ b/drivers/md/raid5.c	2004-10-18 14:56:17 -07:00
@@ -477,8 +477,8 @@
 
 	if (!rdev->faulty) {
 		mddev->sb_dirty = 1;
-		conf->working_disks--;
 		if (rdev->in_sync) {
+			conf->working_disks--;
 			mddev->degraded++;
 			conf->failed_disks++;
 			rdev->in_sync = 0;
@@ -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",
@@ -1339,6 +1340,39 @@
 	unplug_slaves(mddev);
 }
 
+static int raid5_issue_flush(request_queue_t *q, struct gendisk *disk,
+			     sector_t *error_sector)
+{
+	mddev_t *mddev = q->queuedata;
+	raid5_conf_t *conf = mddev_to_conf(mddev);
+	int i, ret = 0;
+
+	for (i=0; i<mddev->raid_disks; i++) {
+		mdk_rdev_t *rdev = conf->disks[i].rdev;
+		if (rdev && !rdev->faulty) {
+			struct block_device *bdev = rdev->bdev;
+			request_queue_t *r_queue;
+
+			if (!bdev)
+				continue;
+
+			r_queue = bdev_get_queue(bdev);
+			if (!r_queue)
+				continue;
+
+			if (!r_queue->issue_flush_fn) {
+				ret = -EOPNOTSUPP;
+				break;
+			}
+
+			ret = r_queue->issue_flush_fn(r_queue, bdev->bd_disk, error_sector);
+			if (ret)
+				break;
+		}
+	}
+	return ret;
+}
+
 static inline void raid5_plug_device(raid5_conf_t *conf)
 {
 	spin_lock_irq(&conf->device_lock);
@@ -1545,6 +1579,7 @@
 	atomic_set(&conf->preread_active_stripes, 0);
 
 	mddev->queue->unplug_fn = raid5_unplug_device;
+	mddev->queue->issue_flush_fn = raid5_issue_flush;
 
 	PRINTK("raid5: run(%s) called.\n", mdname(mddev));
 
diff -Nru a/drivers/md/raid6main.c b/drivers/md/raid6main.c
--- a/drivers/md/raid6main.c	2004-10-18 14:55:54 -07:00
+++ b/drivers/md/raid6main.c	2004-10-18 14:55:54 -07:00
@@ -498,8 +498,8 @@
 
 	if (!rdev->faulty) {
 		mddev->sb_dirty = 1;
-		conf->working_disks--;
 		if (rdev->in_sync) {
+			conf->working_disks--;
 			mddev->degraded++;
 			conf->failed_disks++;
 			rdev->in_sync = 0;
@@ -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",
@@ -1501,6 +1502,39 @@
 	unplug_slaves(mddev);
 }
 
+static int raid6_issue_flush(request_queue_t *q, struct gendisk *disk,
+			     sector_t *error_sector)
+{
+	mddev_t *mddev = q->queuedata;
+	raid6_conf_t *conf = mddev_to_conf(mddev);
+	int i, ret = 0;
+
+	for (i=0; i<mddev->raid_disks; i++) {
+		mdk_rdev_t *rdev = conf->disks[i].rdev;
+		if (rdev && !rdev->faulty) {
+			struct block_device *bdev = rdev->bdev;
+			request_queue_t *r_queue;
+
+			if (!bdev)
+				continue;
+
+			r_queue = bdev_get_queue(bdev);
+			if (!r_queue)
+				continue;
+
+			if (!r_queue->issue_flush_fn) {
+				ret = -EOPNOTSUPP;
+				break;
+			}
+
+			ret = r_queue->issue_flush_fn(r_queue, bdev->bd_disk, error_sector);
+			if (ret)
+				break;
+		}
+	}
+	return ret;
+}
+
 static inline void raid6_plug_device(raid6_conf_t *conf)
 {
 	spin_lock_irq(&conf->device_lock);
@@ -1708,6 +1742,7 @@
 	atomic_set(&conf->preread_active_stripes, 0);
 
 	mddev->queue->unplug_fn = raid6_unplug_device;
+	mddev->queue->issue_flush_fn = raid6_issue_flush;
 
 	PRINTK("raid6: run(%s) called.\n", mdname(mddev));
 
diff -Nru a/drivers/media/common/saa7146_i2c.c b/drivers/media/common/saa7146_i2c.c
--- a/drivers/media/common/saa7146_i2c.c	2004-10-18 14:57:04 -07:00
+++ b/drivers/media/common/saa7146_i2c.c	2004-10-18 14:57:04 -07:00
@@ -1,13 +1,6 @@
 #include <linux/version.h>
 #include <media/saa7146_vv.h>
 
-/* helper function */
-static void my_wait(struct saa7146_dev *dev, long ms)
-{
-	set_current_state(TASK_INTERRUPTIBLE);
-	schedule_timeout((((ms+10)/10)*HZ)/1000);
-}
-
 u32 saa7146_i2c_func(struct i2c_adapter *adapter)
 {
 //fm	DEB_I2C(("'%s'.\n", adapter->name));
@@ -136,12 +129,12 @@
 		/* set "ABORT-OPERATION"-bit (bit 7)*/
 		saa7146_write(dev, I2C_STATUS, (dev->i2c_bitrate | MASK_07));
 		saa7146_write(dev, MC2, (MASK_00 | MASK_16));
-		my_wait(dev,SAA7146_I2C_DELAY);
+		msleep(SAA7146_I2C_DELAY);
 
 		/* clear all error-bits pending; this is needed because p.123, note 1 */
 		saa7146_write(dev, I2C_STATUS, dev->i2c_bitrate);
 		saa7146_write(dev, MC2, (MASK_00 | MASK_16));
-		my_wait(dev,SAA7146_I2C_DELAY);
+		msleep(SAA7146_I2C_DELAY);
  	}
 
 	/* check if any error is (still) present. (this can be necessary because p.123, note 1) */
@@ -155,18 +148,18 @@
 		   after serious protocol errors caused by e.g. the SAA7740 */
 		saa7146_write(dev, I2C_STATUS, (dev->i2c_bitrate | MASK_07));
 		saa7146_write(dev, MC2, (MASK_00 | MASK_16));
-		my_wait(dev,SAA7146_I2C_DELAY);
+		msleep(SAA7146_I2C_DELAY);
 
 		/* clear all error-bits pending */
 		saa7146_write(dev, I2C_STATUS, dev->i2c_bitrate);
 		saa7146_write(dev, MC2, (MASK_00 | MASK_16));
-		my_wait(dev,SAA7146_I2C_DELAY);
+		msleep(SAA7146_I2C_DELAY);
 
 		/* the data sheet says it might be necessary to clear the status
 		   twice after an abort */
 		saa7146_write(dev, I2C_STATUS, dev->i2c_bitrate);
 		saa7146_write(dev, MC2, (MASK_00 | MASK_16));
-		my_wait(dev,SAA7146_I2C_DELAY);
+		msleep(SAA7146_I2C_DELAY);
      	}
 
 	/* if any error is still present, a fatal error has occured ... */
@@ -243,7 +236,7 @@
 			if ((++trial < 20) && short_delay)
 				udelay(10);
 			else
-			my_wait(dev,1);
+			msleep(1);
 		}
 	}
 
@@ -345,7 +338,7 @@
 		}
 	        
 	        /* delay a bit before retrying */
-	        my_wait(dev, 10);
+	        msleep(10);
 		
 	} while (err != num && retries--);
 
diff -Nru a/drivers/media/dvb/b2c2/skystar2.c b/drivers/media/dvb/b2c2/skystar2.c
--- a/drivers/media/dvb/b2c2/skystar2.c	2004-10-18 14:57:20 -07:00
+++ b/drivers/media/dvb/b2c2/skystar2.c	2004-10-18 14:57:20 -07:00
@@ -2345,7 +2345,7 @@
 MODULE_DEVICE_TABLE(pci, skystar2_pci_tbl);
 
 static struct pci_driver skystar2_pci_driver = {
-	.name = "Technisat SkyStar2 driver",
+	.name = "SkyStar2",
 	.id_table = skystar2_pci_tbl,
 	.probe = skystar2_probe,
 	.remove = skystar2_remove,
diff -Nru a/drivers/media/dvb/bt8xx/bt878.c b/drivers/media/dvb/bt8xx/bt878.c
--- a/drivers/media/dvb/bt8xx/bt878.c	2004-10-18 14:56:32 -07:00
+++ b/drivers/media/dvb/bt8xx/bt878.c	2004-10-18 14:56:32 -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-10-18 14:56:28 -07:00
+++ b/drivers/media/dvb/dvb-core/dvb_ca_en50221.c	2004-10-18 14:56:28 -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];
@@ -1484,21 +1484,20 @@
 
 
 static struct file_operations dvb_ca_fops = {
-        owner: THIS_MODULE,
-        read: dvb_ca_en50221_io_read,
-        write: dvb_ca_en50221_io_write,
-        ioctl: dvb_ca_en50221_io_ioctl,
-        open: dvb_ca_en50221_io_open,
-        release: dvb_ca_en50221_io_release,
-        poll: dvb_ca_en50221_io_poll,
+        .owner = THIS_MODULE,
+        .read = dvb_ca_en50221_io_read,
+        .write = dvb_ca_en50221_io_write,
+        .ioctl = dvb_ca_en50221_io_ioctl,
+        .open = dvb_ca_en50221_io_open,
+        .release = dvb_ca_en50221_io_release,
+        .poll = dvb_ca_en50221_io_poll,
 };
 
 static struct dvb_device dvbdev_ca = {
-        priv: NULL,
-        users: 1,
-        readers: 1,
-        writers: 1,
-        fops: &dvb_ca_fops,
+        .users = 1,
+        .readers = 1,
+        .writers = 1,
+        .fops = &dvb_ca_fops,
 };
 
 
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-10-18 14:56:17 -07:00
+++ b/drivers/media/dvb/dvb-core/dvb_net.c	2004-10-18 14:56:17 -07:00
@@ -142,7 +142,7 @@
 	
 	skb->mac.raw=skb->data;
 	skb_pull(skb,dev->hard_header_len);
-	eth= skb->mac.ethernet;
+	eth = eth_hdr(skb);
 	
 	if (*eth->h_dest & 1) {
 		if(memcmp(eth->h_dest,dev->broadcast, ETH_ALEN)==0)
@@ -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/alps_tdlb7.c b/drivers/media/dvb/frontends/alps_tdlb7.c
--- a/drivers/media/dvb/frontends/alps_tdlb7.c	2004-10-18 14:57:19 -07:00
+++ b/drivers/media/dvb/frontends/alps_tdlb7.c	2004-10-18 14:57:19 -07:00
@@ -54,9 +54,6 @@
 /* starting point for firmware in file 'Sc_main.mc' */
 #define SP8870_FIRMWARE_OFFSET 0x0A
 
-
-static int errno;
-
 static struct dvb_frontend_info tdlb7_info = {
 	.name			= "Alps TDLB7",
 	.type			= FE_OFDM,
diff -Nru a/drivers/media/dvb/frontends/dst.c b/drivers/media/dvb/frontends/dst.c
--- a/drivers/media/dvb/frontends/dst.c	2004-10-18 14:56:50 -07:00
+++ b/drivers/media/dvb/frontends/dst.c	2004-10-18 14:56:50 -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/frontends/sp887x.c b/drivers/media/dvb/frontends/sp887x.c
--- a/drivers/media/dvb/frontends/sp887x.c	2004-10-18 14:56:49 -07:00
+++ b/drivers/media/dvb/frontends/sp887x.c	2004-10-18 14:56:49 -07:00
@@ -67,8 +67,6 @@
                 FE_CAN_RECOVER
 };
 
-static int errno;
-
 static
 int i2c_writebytes (struct dvb_frontend *fe, u8 addr, u8 *buf, u8 len)
 {
diff -Nru a/drivers/media/dvb/frontends/stv0299.c b/drivers/media/dvb/frontends/stv0299.c
--- a/drivers/media/dvb/frontends/stv0299.c	2004-10-18 14:57:05 -07:00
+++ b/drivers/media/dvb/frontends/stv0299.c	2004-10-18 14:57:05 -07:00
@@ -319,7 +319,7 @@
 static int pll_write (struct dvb_i2c_bus *i2c, u8 addr, u8 *data, int len)
 {
 	int ret;
-	struct i2c_msg msg = { addr: addr, .flags = 0, .buf = data, .len = len };
+	struct i2c_msg msg = { .addr = addr, .buf = data, .len = len };
 
 
 	stv0299_writereg(i2c, 0x05, 0xb5);	/*  enable i2c repeater on stv0299  */
@@ -1257,12 +1257,12 @@
         u8 stat [] = { 0 };
 	u8 tda6100_buf [] = { 0, 0 };
 	int ret;
-	struct i2c_msg msg1 [] = {{ .addr = 0x68, .flags = 0, .buf = rpt,  len: 2 },
+	struct i2c_msg msg1 [] = {{ .addr = 0x68, .buf = rpt,  .len = 2 },
 			   { .addr = 0x60, .flags = I2C_M_RD, .buf = stat, .len = 1 }};
-	struct i2c_msg msg2 [] = {{ .addr = 0x68, .flags = 0, .buf = rpt,  len: 2 },
+	struct i2c_msg msg2 [] = {{ .addr = 0x68, .buf = rpt,  .len = 2 },
 			   { .addr = 0x61, .flags = I2C_M_RD, .buf = stat, .len = 1 }};
-	struct i2c_msg msg3 [] = {{ .addr = 0x68, .flags = 0, .buf = rpt,  len: 2 },
-			   { .addr = 0x60, .flags = 0, .buf = tda6100_buf, .len = 2 }};
+	struct i2c_msg msg3 [] = {{ .addr = 0x68, .buf = rpt,  .len = 2 },
+			   { .addr = 0x60, .buf = tda6100_buf, .len = 2 }};
 
 	stv0299_writereg (i2c, 0x01, 0x15);
 	stv0299_writereg (i2c, 0x02, 0x30);
@@ -1271,7 +1271,7 @@
 
 	printk ("%s: try to attach to %s\n", __FUNCTION__, adapter->name);
 
-	if ( strcmp(adapter->name, "Technisat SkyStar2 driver") == 0 )
+	if ( strcmp(adapter->name, "SkyStar2") == 0 )
 	{
 	    printk ("%s: setup for tuner Samsung TBMU24112IMB\n", __FILE__);
 
diff -Nru a/drivers/media/dvb/frontends/tda1004x.c b/drivers/media/dvb/frontends/tda1004x.c
--- a/drivers/media/dvb/frontends/tda1004x.c	2004-10-18 14:55:53 -07:00
+++ b/drivers/media/dvb/frontends/tda1004x.c	2004-10-18 14:55:53 -07:00
@@ -188,8 +188,6 @@
 static struct fwinfo tda10046h_fwinfo[] = { {.file_size = 286720,.fw_offset = 0x3c4f9,.fw_size = 24479} };
 static int tda10046h_fwinfo_count = sizeof(tda10046h_fwinfo) / sizeof(struct fwinfo);
 
-static int errno;
-
 
 static int tda1004x_write_byte(struct dvb_i2c_bus *i2c, struct tda1004x_state *tda_state, int reg, int data)
 {
diff -Nru a/drivers/media/dvb/ttpci/Kconfig b/drivers/media/dvb/ttpci/Kconfig
--- a/drivers/media/dvb/ttpci/Kconfig	2004-10-18 14:55:55 -07:00
+++ b/drivers/media/dvb/ttpci/Kconfig	2004-10-18 14:55:55 -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/ttpci/Makefile b/drivers/media/dvb/ttpci/Makefile
--- a/drivers/media/dvb/ttpci/Makefile	2004-10-18 14:55:55 -07:00
+++ b/drivers/media/dvb/ttpci/Makefile	2004-10-18 14:55:55 -07:00
@@ -13,7 +13,7 @@
 
 EXTRA_CFLAGS = -Idrivers/media/dvb/dvb-core/
 
-host-progs	:= fdump
+hostprogs-y	:= fdump
 
 ifdef CONFIG_DVB_AV7110_FIRMWARE
 $(obj)/av7110.o: $(obj)/fdump $(obj)/av7110_firm.h 
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-10-18 14:57:03 -07:00
+++ b/drivers/media/dvb/ttusb-dec/ttusb_dec.c	2004-10-18 14:57:03 -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/radio/miropcm20-rds.c b/drivers/media/radio/miropcm20-rds.c
--- a/drivers/media/radio/miropcm20-rds.c	2004-10-18 14:55:55 -07:00
+++ b/drivers/media/radio/miropcm20-rds.c	2004-10-18 14:55:55 -07:00
@@ -14,6 +14,7 @@
 #include <linux/slab.h>
 #include <linux/fs.h>
 #include <linux/miscdevice.h>
+#include <linux/delay.h>
 #include <asm/uaccess.h>
 #include "miropcm20-rds-core.h"
 
@@ -60,8 +61,7 @@
 	char c;
 	char bits[8];
 
-	current->state=TASK_UNINTERRUPTIBLE;
-	schedule_timeout(2*HZ);
+	msleep(2000);
 	aci_rds_cmd(RDS_STATUS, &c, 1);
 	print_matrix(&c, bits);
 	if (copy_to_user(buffer, bits, 8))
diff -Nru a/drivers/media/radio/radio-aimslab.c b/drivers/media/radio/radio-aimslab.c
--- a/drivers/media/radio/radio-aimslab.c	2004-10-18 14:56:27 -07:00
+++ b/drivers/media/radio/radio-aimslab.c	2004-10-18 14:56:27 -07:00
@@ -63,12 +63,7 @@
 	if(!d)
 		udelay(n);
 	else
-	{
-		/* Yield CPU time */
-		unsigned long x=jiffies;
-		while((jiffies-x)<=d)
-			schedule();
-	}
+		msleep(jiffies_to_msecs(d));
 }
 
 static void rt_decvol(void)
diff -Nru a/drivers/media/radio/radio-cadet.c b/drivers/media/radio/radio-cadet.c
--- a/drivers/media/radio/radio-cadet.c	2004-10-18 14:56:29 -07:00
+++ b/drivers/media/radio/radio-cadet.c	2004-10-18 14:56:29 -07:00
@@ -69,8 +69,7 @@
 	outb(inb(io+1)&0x7f,io+1);  /* Reset RDS detection */
 	spin_unlock(&cadet_io_lock);
 	
-	set_current_state(TASK_UNINTERRUPTIBLE);
-	schedule_timeout(HZ/10);
+	msleep(100);
 
 	spin_lock(&cadet_io_lock);	
         outb(3,io);                 /* Select Decoder Control/Status */
@@ -243,8 +242,7 @@
 		outb(curvol,io+1);
 		spin_unlock(&cadet_io_lock);
 		
-		set_current_state(TASK_UNINTERRUPTIBLE);
-		schedule_timeout(HZ/10);
+		msleep(100);
 
 		cadet_gettune();
 		if((tunestat & 0x40) == 0) {   /* Tuned */
diff -Nru a/drivers/media/radio/radio-maestro.c b/drivers/media/radio/radio-maestro.c
--- a/drivers/media/radio/radio-maestro.c	2004-10-18 14:56:33 -07:00
+++ b/drivers/media/radio/radio-maestro.c	2004-10-18 14:56:33 -07:00
@@ -93,27 +93,6 @@
 	struct  semaphore lock;
 } radio_unit = {0, 0, 0, 0, };
 
-static void sleep_125ms(void)
-{
-	current->state = TASK_INTERRUPTIBLE;
-	schedule_timeout(HZ >> 3);
-}
-
-static void udelay2(void)
-{
-	udelay(2);
-}
-
-static void udelay4(void)
-{
-	udelay(4);
-}
-
-static void udelay16(void)
-{
-	udelay(16);
-}
-
 static __u32 radio_bits_get(struct radio_device *dev)
 {
 	register __u16 io=dev->io, l, rdata;
@@ -122,14 +101,15 @@
 	omask = inw(io + IO_MASK);
 	outw(~(STR_CLK | STR_WREN), io + IO_MASK);
 	outw(0, io);
-	udelay16();
+	udelay(16);
+
 	for (l=24;l--;) {
 		outw(STR_CLK, io);		/* HI state */
-		udelay2();
+		udelay(2);
 		if(!l) 
 			dev->tuned = inw(io) & STR_MOST ? 0 : 0xffff;
 		outw(0, io);			/* LO state */
-		udelay2();
+		udelay(2);
 		data <<= 1;			/* shift data */
 		rdata = inw(io);
 		if(!l)
@@ -138,11 +118,11 @@
 		else
 			if(rdata & STR_DATA)
 				data++;
-		udelay2();
+		udelay(2);
 	}
 	if(dev->muted)
 		outw(STR_WREN, io);
-	udelay4();
+	udelay(4);
 	outw(omask, io + IO_MASK);
 	return data & 0x3ffe;
 }
@@ -155,23 +135,23 @@
 	odir  = (inw(io + IO_DIR) & ~STR_DATA) | (STR_CLK | STR_WREN);
 	outw(odir | STR_DATA, io + IO_DIR);
 	outw(~(STR_DATA | STR_CLK | STR_WREN), io + IO_MASK);
-	udelay16();
+	udelay(16);
 	for (l=25;l;l--) {
 		bits = ((data >> 18) & STR_DATA) | STR_WREN ;
 		data <<= 1;			/* shift data */
 		outw(bits, io);			/* start strobe */
-		udelay2();
+		udelay(2);
 		outw(bits | STR_CLK, io);	/* HI level */
-		udelay2();   
+		udelay(2);
 		outw(bits, io);			/* LO level */
-		udelay4();
+		udelay(4);
 	}
 	if(!dev->muted)
 		outw(0, io);
-	udelay4();
+	udelay(4);
 	outw(omask, io + IO_MASK);
 	outw(odir, io + IO_DIR);
-	sleep_125ms();
+	msleep(125);
 }
 
 inline static int radio_function(struct inode *inode, struct file *file,
@@ -238,9 +218,9 @@
 				outw(~STR_WREN, io + IO_MASK);
 				outw((card->muted = v->flags & VIDEO_AUDIO_MUTE)
 				     ? STR_WREN : 0, io);
-				udelay4();
+				udelay(4);
 				outw(omask, io + IO_MASK);
-				sleep_125ms();
+				msleep(125);
 				return 0;
 			}
 		}
@@ -270,7 +250,7 @@
 	return ret;
 }
 
-inline static __u16 radio_install(struct pci_dev *pcidev);
+static __u16 radio_install(struct pci_dev *pcidev);
 
 MODULE_AUTHOR("Adam Tlalka, atlka@pg.gda.pl");
 MODULE_DESCRIPTION("Radio driver for the Maestro PCI sound card radio.");
@@ -315,7 +295,7 @@
 	outw(odir, io + IO_DIR);
 	outw(~(STR_WREN | STR_CLK), io + IO_MASK);
 	outw(dev->muted ? 0 : STR_WREN, io);
-	udelay16();
+	udelay(16);
 	outw(omask, io + IO_MASK);
 	ofreq = radio_bits_get(dev);
 	if((ofreq<FREQ2BITS(FREQ_LO)) || (ofreq>FREQ2BITS(FREQ_HI)))
@@ -324,7 +304,7 @@
 	return (ofreq == radio_bits_get(dev));
 }
 
-inline static __u16 radio_install(struct pci_dev *pcidev)
+static __u16 radio_install(struct pci_dev *pcidev)
 {
 	if(((pcidev->class >> 8) & 0xffff) != PCI_CLASS_MULTIMEDIA_AUDIO)
 		return 0;
diff -Nru a/drivers/media/radio/radio-maxiradio.c b/drivers/media/radio/radio-maxiradio.c
--- a/drivers/media/radio/radio-maxiradio.c	2004-10-18 14:57:04 -07:00
+++ b/drivers/media/radio/radio-maxiradio.c	2004-10-18 14:57:04 -07:00
@@ -104,13 +104,6 @@
 } radio_unit = {0, 0, 0, 0, };
 
 
-static void sleep_125ms(void)
-{
-	current->state = TASK_INTERRUPTIBLE;
-	schedule_timeout(HZ >> 3);
-}
-
-
 static void outbit(unsigned long bit, __u16 io)
 {
 	if(bit != 0)
@@ -228,7 +221,7 @@
 				return -EINVAL;
 			card->freq = *freq;
 			set_freq(card->io, FREQ2BITS(card->freq));
-			sleep_125ms();
+			msleep(125);
 			return 0;
 		}
 		case VIDIOCGAUDIO: {	
diff -Nru a/drivers/media/radio/radio-sf16fmi.c b/drivers/media/radio/radio-sf16fmi.c
--- a/drivers/media/radio/radio-sf16fmi.c	2004-10-18 14:57:03 -07:00
+++ b/drivers/media/radio/radio-sf16fmi.c	2004-10-18 14:57:03 -07:00
@@ -89,8 +89,7 @@
 
 	outbits(16, RSF16_ENCODE(freq), myport);
 	outbits(8, 0xC0, myport);
-	current->state = TASK_UNINTERRUPTIBLE;
-	schedule_timeout(HZ/7);
+	msleep(143);		/* was schedule_timeout(HZ/7) */
 	up(&lock);
 	if (dev->curvol) fmi_unmute(myport);
 	return 0;
@@ -107,8 +106,7 @@
 	val = dev->curvol ? 0x08 : 0x00;	/* unmute/mute */
 	outb(val, myport);
 	outb(val | 0x10, myport);
-	set_current_state(TASK_UNINTERRUPTIBLE);
-	schedule_timeout(HZ/7);
+	msleep(143); 		/* was schedule_timeout(HZ/7) */
 	res = (int)inb(myport+1);
 	outb(val, myport);
 	
diff -Nru a/drivers/media/radio/radio-sf16fmr2.c b/drivers/media/radio/radio-sf16fmr2.c
--- a/drivers/media/radio/radio-sf16fmr2.c	2004-10-18 14:56:29 -07:00
+++ b/drivers/media/radio/radio-sf16fmr2.c	2004-10-18 14:56:29 -07:00
@@ -55,19 +55,6 @@
 #define RSF16_MINFREQ 87*16000
 #define RSF16_MAXFREQ 108*16000
 
-/* from radio-aimslab */
-static void sleep_delay(unsigned long n)
-{
-	unsigned d=n/(1000000U/HZ);
-	if (!d)
-		udelay(n);
-	else
-	{
-		set_current_state(TASK_UNINTERRUPTIBLE);
-		schedule_timeout(d);
-	}
-}
-
 static inline void wait(int n,int port)
 {
 	for (;n;--n) inb(port);
@@ -153,7 +140,7 @@
 	fmr2_unmute(port);
 
 	/* wait 0.11 sec */
-	sleep_delay(110000LU);
+	msleep(110);
 
 	/* NOTE if mute this stop radio
 	   you must set freq on unmute */
diff -Nru a/drivers/media/video/Kconfig b/drivers/media/video/Kconfig
--- a/drivers/media/video/Kconfig	2004-10-18 14:57:03 -07:00
+++ b/drivers/media/video/Kconfig	2004-10-18 14:57:03 -07:00
@@ -155,7 +155,7 @@
 
 config VIDEO_ZORAN
 	tristate "Zoran ZR36057/36067 Video For Linux"
-	depends on VIDEO_DEV && PCI && I2C
+	depends on VIDEO_DEV && PCI && I2C_ALGOBIT
 	help
 	  Say Y for support for MJPEG capture cards based on the Zoran
 	  36057/36067 PCI controller chipset. This includes the Iomega
diff -Nru a/drivers/media/video/adv7175.c b/drivers/media/video/adv7175.c
--- a/drivers/media/video/adv7175.c	2004-10-18 14:57:03 -07:00
+++ b/drivers/media/video/adv7175.c	2004-10-18 14:57:03 -07:00
@@ -156,6 +156,22 @@
 	return ret;
 }
 
+static void
+set_subcarrier_freq (struct i2c_client *client,
+		     int                pass_through)
+{
+	/* for some reason pass_through NTSC needs
+	 * a different sub-carrier freq to remain stable. */
+	if(pass_through)
+		adv7175_write(client, 0x02, 0x00);
+	else
+		adv7175_write(client, 0x02, 0x55);
+
+	adv7175_write(client, 0x03, 0x55);
+	adv7175_write(client, 0x04, 0x55);
+	adv7175_write(client, 0x05, 0x25);
+}
+
 #ifdef ENCODER_DUMP
 static void
 dump (struct i2c_client *client)
@@ -322,6 +338,10 @@
 
 		case 0:
 			adv7175_write(client, 0x01, 0x00);
+
+			if (encoder->norm == VIDEO_MODE_NTSC)
+				set_subcarrier_freq(client, 1);
+
 			adv7175_write(client, 0x0c, TR1CAPT);	/* TR1 */
 			if (encoder->norm == VIDEO_MODE_SECAM)
 				adv7175_write(client, 0x0d, 0x49);	// Disable genlock
@@ -334,6 +354,10 @@
 
 		case 1:
 			adv7175_write(client, 0x01, 0x00);
+
+			if (encoder->norm == VIDEO_MODE_NTSC)
+				set_subcarrier_freq(client, 0);
+
 			adv7175_write(client, 0x0c, TR1PLAY);	/* TR1 */
 			adv7175_write(client, 0x0d, 0x49);
 			adv7175_write(client, 0x07, TR0MODE | TR0RST);
@@ -343,6 +367,10 @@
 
 		case 2:
 			adv7175_write(client, 0x01, 0x80);
+
+			if (encoder->norm == VIDEO_MODE_NTSC)
+				set_subcarrier_freq(client, 0);
+
 			adv7175_write(client, 0x0d, 0x49);
 			adv7175_write(client, 0x07, TR0MODE | TR0RST);
 			adv7175_write(client, 0x07, TR0MODE);
diff -Nru a/drivers/media/video/bttv-cards.c b/drivers/media/video/bttv-cards.c
--- a/drivers/media/video/bttv-cards.c	2004-10-18 14:56:29 -07:00
+++ b/drivers/media/video/bttv-cards.c	2004-10-18 14:56:29 -07:00
@@ -31,7 +31,7 @@
 #include <linux/init.h>
 #include <linux/pci.h>
 #include <linux/vmalloc.h>
-#ifdef CONFIG_FW_LOADER
+#if defined(CONFIG_FW_LOADER) || defined(CONFIG_FW_LOADER_MODULE)
 # include <linux/firmware.h>
 #endif
 
@@ -74,6 +74,9 @@
 static void picolo_tetra_muxsel(struct bttv *btv, unsigned int input);
 static void picolo_tetra_init(struct bttv *btv);
 
+static void sigmaSLC_muxsel(struct bttv *btv, unsigned int input);
+static void sigmaSQ_muxsel(struct bttv *btv, unsigned int input);
+
 static int terratec_active_radio_upgrade(struct bttv *btv);
 static int tea5757_read(struct bttv *btv);
 static int tea5757_write(struct bttv *btv, int value);
@@ -170,6 +173,7 @@
 
 	{ 0x6606107d, BTTV_WINFAST2000,   "Leadtek WinFast TV 2000" },
 	{ 0x6607107d, BTTV_WINFASTVC100,  "Leadtek WinFast VC 100" },
+	{ 0x6609107d, BTTV_WINFAST2000,   "Leadtek TV 2000 XP" },
 	{ 0x263610b4, BTTV_STB2,          "STB TV PCI FM, Gateway P/N 6000704" },
 	{ 0x264510b4, BTTV_STB2,          "STB TV PCI FM, Gateway P/N 6000704" },
  	{ 0x402010fc, BTTV_GVBCTV3PCI,    "I-O Data Co. GV-BCTV3/PCI" },
@@ -224,6 +228,7 @@
 	{ 0x1431aa00, BTTV_PV143,         "Provideo PV143B" },
 	{ 0x1432aa00, BTTV_PV143,         "Provideo PV143C" },
 	{ 0x1433aa00, BTTV_PV143,         "Provideo PV143D" },
+	{ 0x1433aa03, BTTV_PV143,         "Security Eyes" },
 
 	{ 0x1460aa00, BTTV_PV150,         "Provideo PV150A-1" },
 	{ 0x1461aa01, BTTV_PV150,         "Provideo PV150A-2" },
@@ -265,6 +270,7 @@
 	{ 0x01020304, BTTV_XGUARD,        "Grandtec Grand X-Guard" },
 	
 	{ 0x18501851, BTTV_CHRONOS_VS2,   "FlyVideo 98 (LR50)/ Chronos Video Shuttle II" },
+	{ 0xa0501851, BTTV_CHRONOS_VS2,   "FlyVideo 98 (LR50)/ Chronos Video Shuttle II" },
 	{ 0x18511851, BTTV_FLYVIDEO98EZ,  "FlyVideo 98EZ (LR51)/ CyberMail AV" },
 	{ 0x18521852, BTTV_TYPHOON_TVIEW, "FlyVideo 98FM (LR50)/ Typhoon TView TV/FM Tuner" },
 	{ 0x41a0a051, BTTV_FLYVIDEO_98FM, "Lifeview FlyVideo 98 LR50 Rev Q" },
@@ -297,7 +303,7 @@
 	
 	// DVB cards (using pci function .1 for mpeg data xfer)
 	{ 0x01010071, BTTV_NEBULA_DIGITV, "Nebula Electronics DigiTV" },
-	{ 0x07611461, BTTV_NEBULA_DIGITV, "AverMedia AverTV DVB-T" },
+	{ 0x07611461, BTTV_AVDVBT_761,    "AverMedia AverTV DVB-T" },
 	{ 0x002611bd, BTTV_TWINHAN_DST,   "Pinnacle PCTV SAT CI" },
 	{ 0x00011822, BTTV_TWINHAN_DST,   "Twinhan VisionPlus DVB-T" },
 	{ 0xfc00270f, BTTV_TWINHAN_DST,   "ChainTech digitop DST-1000 DVB-S" },
@@ -2078,6 +2084,69 @@
 #if 0 /* untested */
         .has_remote     = 1,
 #endif
+},{
+	/* ---- card 0x7c ---------------------------------- */
+	/* Matt Jesson <dvb@jesson.eclipse.co.uk> */
+	/* Based on the Nebula card data - added remote and new card number - BTTV_AVDVBT_761, see also ir-kbd-gpio.c */
+	.name           = "AverMedia AverTV DVB-T 761",
+	.video_inputs   = 1,
+	.tuner          = -1,
+	.svhs           = -1,
+	.muxsel         = { 2, 3, 1, 0},
+	.no_msp34xx     = 1,
+	.no_tda9875     = 1,
+	.no_tda7432     = 1,
+	.pll            = PLL_28,
+	.tuner_type     = -1,
+	.has_dvb        = 1,
+	.no_gpioirq     = 1,
+	.has_remote     = 1,
+},{
+	/* andre.schwarz@matrix-vision.de */
+	.name             = "MATRIX Vision Sigma-SQ",
+	.video_inputs     = 16,
+	.audio_inputs     = 0,
+	.tuner            = -1,
+	.svhs             = -1,
+	.gpiomask         = 0x0,
+	.muxsel           = { 2, 2, 2, 2, 2, 2, 2, 2,
+			      3, 3, 3, 3, 3, 3, 3, 3 },
+	.muxsel_hook      = sigmaSQ_muxsel,
+	.audiomux         = { 0 },
+	.no_msp34xx       = 1,
+	.pll              = PLL_28,
+	.tuner_type       = -1,
+},{
+	/* andre.schwarz@matrix-vision.de */
+	.name             = "MATRIX Vision Sigma-SLC",
+	.video_inputs     = 4,
+	.audio_inputs     = 0,
+	.tuner            = -1,
+	.svhs             = -1,
+	.gpiomask         = 0x0,
+	.muxsel           = { 2, 2, 2, 2 },
+	.muxsel_hook      = sigmaSLC_muxsel,
+	.audiomux         = { 0 },
+	.no_msp34xx       = 1,
+	.pll              = PLL_28,
+	.tuner_type       = -1,
+},{
+	/* BTTV_APAC_VIEWCOMP */
+	/* Attila Kondoros <attila.kondoros@chello.hu> */
+	/* bt878 TV + FM 0x00000000 subsystem ID */
+	.name           = "APAC Viewcomp 878(AMAX)",
+	.video_inputs   = 2,
+	.audio_inputs   = 1,
+	.tuner          = 0,
+	.svhs           = -1,
+	.gpiomask       = 0xFF,
+	.muxsel         = { 2, 3, 1, 1},
+	.audiomux       = { 2, 0, 0, 0, 10},
+	.needs_tvaudio  = 0,
+	.pll            = PLL_28,
+	.tuner_type     = TUNER_PHILIPS_PAL,
+	.has_remote     = 1,   /* miniremote works, see ir-kbd-gpio.c */
+	.has_radio      = 1,   /* not every card has radio */
 }};
 
 const unsigned int bttv_num_tvcards = ARRAY_SIZE(bttv_tvcards);
@@ -2405,6 +2474,19 @@
 	gpio_write(0x000000);
 }
 
+static void sigmaSQ_muxsel(struct bttv *btv, unsigned int input)
+{
+	unsigned int inmux = input % 8;
+	gpio_inout( 0xf, 0xf );
+	gpio_bits( 0xf, inmux );
+}
+
+static void sigmaSLC_muxsel(struct bttv *btv, unsigned int input)
+{
+	unsigned int inmux = input % 4;
+	gpio_inout( 3<<9, 3<<9 );
+	gpio_bits( 3<<9, inmux<<9 );
+}
 
 /* ----------------------------------------------------------------------- */
 
@@ -2859,7 +2941,7 @@
 	return 0;
 }
 
-#ifndef CONFIG_FW_LOADER
+#if !defined(CONFIG_FW_LOADER) && !defined(CONFIG_FW_LOADER_MODULE)
 /* old 2.4.x way -- via soundcore's mod_firmware_load */
    
 static char *firm_altera = "/usr/lib/video4linux/hcwamc.rbf";
@@ -4063,7 +4145,7 @@
 	  return;
 	}
 
-	rc=bttv_I2CRead(btv,(PX_I2C_PIC<<1),NULL);
+	rc=bttv_I2CRead(btv,(PX_I2C_PIC<<1),0);
 	if (!(rc & PX_CFG_PXC200F)) {
 	  printk(KERN_DEBUG "bttv%d: PXC200_muxsel: not PXC200F rc:%d \n", btv->c.nr,rc);
 	  return;
diff -Nru a/drivers/media/video/bttv-driver.c b/drivers/media/video/bttv-driver.c
--- a/drivers/media/video/bttv-driver.c	2004-10-18 14:56:49 -07:00
+++ b/drivers/media/video/bttv-driver.c	2004-10-18 14:56:49 -07:00
@@ -1051,11 +1051,6 @@
 	btwrite(whitecrush_upper, BT848_WC_UP);
 	btwrite(whitecrush_lower, BT848_WC_DOWN);
 
-	bt848_bright(btv,   btv->bright);
-	bt848_hue(btv,      btv->hue);
-	bt848_contrast(btv, btv->contrast);
-	bt848_sat(btv,      btv->saturation);
-
 	if (btv->opt_lumafilter) {
 		btwrite(0, BT848_E_CONTROL);
 		btwrite(0, BT848_O_CONTROL);
@@ -1064,6 +1059,11 @@
 		btwrite(BT848_CONTROL_LDEC, BT848_O_CONTROL);
 	}
 
+	bt848_bright(btv,   btv->bright);
+	bt848_hue(btv,      btv->hue);
+	bt848_contrast(btv, btv->contrast);
+	bt848_sat(btv,      btv->saturation);
+
         /* interrupt */
 	init_irqreg(btv);
 }
@@ -1861,6 +1861,8 @@
 
 	if (NULL == fh->ovfmt)
 		return -EINVAL;
+	if (!(fh->ovfmt->flags & FORMAT_FLAGS_PACKED))
+		return -EINVAL;
 	retval = verify_window(&bttv_tvnorms[btv->tvnorm],win,fixup);
 	if (0 != retval)
 		return retval;
@@ -2052,6 +2054,7 @@
 			f->fmt.pix.width = maxw;
 		if (f->fmt.pix.height > maxh)
 			f->fmt.pix.height = maxh;
+		f->fmt.pix.width &= ~0x03;
 		f->fmt.pix.bytesperline =
 			(f->fmt.pix.width * fmt->depth) >> 3;
 		f->fmt.pix.sizeimage =
diff -Nru a/drivers/media/video/bttv-gpio.c b/drivers/media/video/bttv-gpio.c
--- a/drivers/media/video/bttv-gpio.c	2004-10-18 14:56:49 -07:00
+++ b/drivers/media/video/bttv-gpio.c	2004-10-18 14:56:49 -07:00
@@ -106,6 +106,20 @@
 	}
 }
 
+void bttv_i2c_info(struct bttv_core *core, struct i2c_client *client, int attach)
+{
+	struct bttv_sub_driver *drv;
+	struct bttv_sub_device *dev;
+	struct list_head *item;
+
+	list_for_each(item,&core->subs) {
+		dev = list_entry(item,struct bttv_sub_device,list);
+		drv = to_bttv_sub_drv(dev->dev.driver);
+		if (drv && drv->i2c_info)
+			drv->i2c_info(dev,client,attach);
+	}
+}
+
 /* ----------------------------------------------------------------------- */
 /* external: sub-driver register/unregister                                */
 
diff -Nru a/drivers/media/video/bttv-i2c.c b/drivers/media/video/bttv-i2c.c
--- a/drivers/media/video/bttv-i2c.c	2004-10-18 14:55:54 -07:00
+++ b/drivers/media/video/bttv-i2c.c	2004-10-18 14:55:54 -07:00
@@ -40,6 +40,7 @@
 static void bttv_dec_use(struct i2c_adapter *adap);
 #endif
 static int attach_inform(struct i2c_client *client);
+static int detach_inform(struct i2c_client *client);
 
 static int i2c_debug = 0;
 static int i2c_hw = 0;
@@ -114,6 +115,7 @@
 	I2C_DEVNAME("bt848"),
 	.id                = I2C_HW_B_BT848,
 	.client_register   = attach_inform,
+	.client_unregister = detach_inform,
 };
 
 /* ----------------------------------------------------------------------- */
@@ -298,6 +300,7 @@
 	.id            = I2C_ALGO_BIT | I2C_HW_B_BT848 /* FIXME */,
 	.algo          = &bttv_algo,
 	.client_register = attach_inform,
+	.client_unregister = detach_inform,
 };
 
 /* ----------------------------------------------------------------------- */
@@ -324,11 +327,20 @@
 	if (btv->pinnacle_id != UNSET)
 		bttv_call_i2c_clients(btv,AUDC_CONFIG_PINNACLE,
 				      &btv->pinnacle_id);
+	bttv_i2c_info(&btv->c, client, 1);
 
         if (bttv_debug)
 		printk("bttv%d: i2c attach [client=%s]\n",
 		       btv->c.nr, i2c_clientname(client));
         return 0;
+}
+
+static int detach_inform(struct i2c_client *client)
+{
+        struct bttv *btv = i2c_get_adapdata(client->adapter);
+
+	bttv_i2c_info(&btv->c, client, 0);
+	return 0;
 }
 
 void bttv_call_i2c_clients(struct bttv *btv, unsigned int cmd, void *arg)
diff -Nru a/drivers/media/video/bttv-risc.c b/drivers/media/video/bttv-risc.c
--- a/drivers/media/video/bttv-risc.c	2004-10-18 14:56:31 -07:00
+++ b/drivers/media/video/bttv-risc.c	2004-10-18 14:56:31 -07:00
@@ -55,6 +55,8 @@
 	instructions += 2;
 	if ((rc = btcx_riscmem_alloc(btv->c.pci,risc,instructions*8)) < 0)
 		return rc;
+	dprintk("bttv%d: risc packed: bpl %d lines %d instr %d size %d ptr %p\n",
+		btv->c.nr, bpl, lines, instructions, risc->size, risc->cpu);
 
 	/* sync instruction */
 	rp = risc->cpu;
@@ -99,8 +101,10 @@
 			offset += todo;
 		}
 		offset += padding;
+		dprintk("bttv%d: risc packed:   line %d ptr %p\n",
+			btv->c.nr, line, rp);
 	}
-	dprintk("bttv%d: risc planar: %d sglist elems\n", btv->c.nr, (int)(sg-sglist));
+	dprintk("bttv%d: risc packed: %d sglist elems\n", btv->c.nr, (int)(sg-sglist));
 
 	/* save pointer to jmp instruction address */
 	risc->jmp = rp;
@@ -121,6 +125,7 @@
 	struct scatterlist *ysg;
 	struct scatterlist *usg;
 	struct scatterlist *vsg;
+	int topfield = (0 == yoffset);
 	int rc;
 
 	/* estimate risc mem: worst case is one write per page border +
@@ -145,11 +150,26 @@
 		    (line >= (ylines - VCR_HACK_LINES)))
 			continue;
 		switch (vshift) {
-		case 0:  chroma = 1;           break;
-		case 1:  chroma = !(line & 1); break;
-		case 2:  chroma = !(line & 3); break;
-		default: chroma = 0;
+		case 0:
+			chroma = 1;
+			break;
+		case 1:
+			if (topfield)
+				chroma = (line & 1) == 0;
+			else
+				chroma = (line & 1) == 1;
+			break;
+		case 2:
+			if (topfield)
+				chroma = (line & 3) == 0;
+			else
+				chroma = (line & 3) == 2;
+			break;
+		default:
+			chroma = 0;
+			break;
 		}
+
 		for (todo = ybpl; todo > 0; todo -= ylen) {
 			/* go to next sg entry if needed */
 			while (yoffset && yoffset >= sg_dma_len(ysg)) {
diff -Nru a/drivers/media/video/bttv.h b/drivers/media/video/bttv.h
--- a/drivers/media/video/bttv.h	2004-10-18 14:55:55 -07:00
+++ b/drivers/media/video/bttv.h	2004-10-18 14:55:55 -07:00
@@ -126,6 +126,10 @@
 #define BTTV_LMLBT4         0x76
 #define BTTV_PICOLO_TETRA_CHIP 0x79
 #define BTTV_AVDVBT_771     0x7b
+#define BTTV_AVDVBT_761     0x7c
+#define BTTV_MATRIX_VISIONSQ  0x7d
+#define BTTV_MATRIX_VISIONSLC 0x7e
+#define BTTV_APAC_VIEWCOMP  0x7f
 
 /* i2c address list */
 #define I2C_TSA5522        0xc2
@@ -298,6 +302,8 @@
 	struct device_driver   drv;
 	char                   wanted[BUS_ID_SIZE];
 	void                   (*gpio_irq)(struct bttv_sub_device *sub);
+	void                   (*i2c_info)(struct bttv_sub_device *sub,
+					   struct i2c_client *client, int attach);
 };
 #define to_bttv_sub_drv(x) container_of((x), struct bttv_sub_driver, drv)
 
diff -Nru a/drivers/media/video/bttvp.h b/drivers/media/video/bttvp.h
--- a/drivers/media/video/bttvp.h	2004-10-18 14:56:28 -07:00
+++ b/drivers/media/video/bttvp.h	2004-10-18 14:56:28 -07:00
@@ -225,6 +225,7 @@
 int bttv_sub_add_device(struct bttv_core *core, char *name);
 int bttv_sub_del_devices(struct bttv_core *core);
 void bttv_gpio_irq(struct bttv_core *core);
+void bttv_i2c_info(struct bttv_core *core, struct i2c_client *client, int attach);
 
 
 /* ---------------------------------------------------------- */
diff -Nru a/drivers/media/video/cpia.c b/drivers/media/video/cpia.c
--- a/drivers/media/video/cpia.c	2004-10-18 14:56:48 -07:00
+++ b/drivers/media/video/cpia.c	2004-10-18 14:56:48 -07:00
@@ -29,6 +29,7 @@
 #include <linux/config.h>
 
 #include <linux/module.h>
+#include <linux/moduleparam.h>
 #include <linux/init.h>
 #include <linux/fs.h>
 #include <linux/vmalloc.h>
@@ -62,6 +63,15 @@
 MODULE_SUPPORTED_DEVICE("video");
 #endif
 
+static unsigned short colorspace_conv = 0;
+module_param(colorspace_conv, ushort, 0444);
+MODULE_PARM_DESC(colorspace_conv,
+                 "\n<n> Colorspace conversion:"
+                 "\n0 = disable"
+                 "\n1 = enable"
+                 "\nDefault value is 0"
+                 "\n");
+
 #define ABOUT "V4L-Driver for Vision CPiA based cameras"
 
 #ifndef VID_HARDWARE_CPIA
@@ -1428,14 +1438,19 @@
 /* supported frame palettes and depths */
 static inline int valid_mode(u16 palette, u16 depth)
 {
-	return (palette == VIDEO_PALETTE_GREY && depth == 8) ||
-	       (palette == VIDEO_PALETTE_RGB555 && depth == 16) ||
-	       (palette == VIDEO_PALETTE_RGB565 && depth == 16) ||
-	       (palette == VIDEO_PALETTE_RGB24 && depth == 24) ||
-	       (palette == VIDEO_PALETTE_RGB32 && depth == 32) ||
-	       (palette == VIDEO_PALETTE_YUV422 && depth == 16) ||
-	       (palette == VIDEO_PALETTE_YUYV && depth == 16) ||
-	       (palette == VIDEO_PALETTE_UYVY && depth == 16);
+	if ((palette == VIDEO_PALETTE_YUV422 && depth == 16) ||
+	    (palette == VIDEO_PALETTE_YUYV && depth == 16))
+		return 1;
+
+	if (colorspace_conv)
+		return (palette == VIDEO_PALETTE_GREY && depth == 8) ||
+		       (palette == VIDEO_PALETTE_RGB555 && depth == 16) ||
+		       (palette == VIDEO_PALETTE_RGB565 && depth == 16) ||
+		       (palette == VIDEO_PALETTE_RGB24 && depth == 24) ||
+		       (palette == VIDEO_PALETTE_RGB32 && depth == 32) ||
+		       (palette == VIDEO_PALETTE_UYVY && depth == 16);
+
+	return 0;
 }
 
 static int match_videosize( int width, int height )
@@ -4040,6 +4055,13 @@
 {
 	printk(KERN_INFO "%s v%d.%d.%d\n", ABOUT,
 	       CPIA_MAJ_VER, CPIA_MIN_VER, CPIA_PATCH_VER);
+
+	printk(KERN_WARNING "Since in-kernel colorspace conversion is not "
+	       "allowed, it is disabled by default now. Users should fix the "
+	       "applications in case they don't work without conversion "
+	       "reenabled by setting the 'colorspace_conv' module "
+	       "parameter to 1");
+
 #ifdef CONFIG_PROC_FS
 	proc_cpia_create();
 #endif
diff -Nru a/drivers/media/video/dpc7146.c b/drivers/media/video/dpc7146.c
--- a/drivers/media/video/dpc7146.c	2004-10-18 14:56:29 -07:00
+++ b/drivers/media/video/dpc7146.c	2004-10-18 14:56:29 -07:00
@@ -123,6 +123,7 @@
 	/* check if all devices are present */
 	if( 0 == dpc->saa7111a ) {
 		DEB_D(("dpc_v4l2.o: dpc_attach failed for this device.\n"));	
+		i2c_del_adapter(&dpc->i2c_adapter);
 		kfree(dpc);
 		return -ENODEV;
 	}
diff -Nru a/drivers/media/video/meye.c b/drivers/media/video/meye.c
--- a/drivers/media/video/meye.c	2004-10-18 14:56:33 -07:00
+++ b/drivers/media/video/meye.c	2004-10-18 14:56:33 -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/msp3400.c b/drivers/media/video/msp3400.c
--- a/drivers/media/video/msp3400.c	2004-10-18 14:56:33 -07:00
+++ b/drivers/media/video/msp3400.c	2004-10-18 14:56:33 -07:00
@@ -1552,13 +1552,12 @@
 
 /* ----------------------------------------------------------------------- */
 
-static int msp3400_init_module(void)
+static int __init msp3400_init_module(void)
 {
-	i2c_add_driver(&driver);
-	return 0;
+	return i2c_add_driver(&driver);
 }
 
-static void msp3400_cleanup_module(void)
+static void __exit msp3400_cleanup_module(void)
 {
 	i2c_del_driver(&driver);
 }
diff -Nru a/drivers/media/video/saa7134/saa6752hs.c b/drivers/media/video/saa7134/saa6752hs.c
--- a/drivers/media/video/saa7134/saa6752hs.c	2004-10-18 14:57:04 -07:00
+++ b/drivers/media/video/saa7134/saa6752hs.c	2004-10-18 14:57:04 -07:00
@@ -387,13 +387,12 @@
         .driver     = &driver,
 };
 
-static int saa6752hs_init_module(void)
+static int __init saa6752hs_init_module(void)
 {
-	i2c_add_driver(&driver);
-	return 0;
+	return i2c_add_driver(&driver);
 }
 
-static void saa6752hs_cleanup_module(void)
+static void __exit saa6752hs_cleanup_module(void)
 {
 	i2c_del_driver(&driver);
 }
diff -Nru a/drivers/media/video/saa7134/saa7134-cards.c b/drivers/media/video/saa7134/saa7134-cards.c
--- a/drivers/media/video/saa7134/saa7134-cards.c	2004-10-18 14:56:50 -07:00
+++ b/drivers/media/video/saa7134/saa7134-cards.c	2004-10-18 14:56:50 -07:00
@@ -154,6 +154,26 @@
 			.gpio = 0x8000,
 		},
 	},
+	[SAA7134_BOARD_FLYTVPLATINUM] = {
+		/* "Arnaud Quette" <aquette@free.fr> */
+		.name           = "LifeView FlyTV Platinum",
+		.audio_clock    = 0x00200000,
+		.tuner_type     = TUNER_PHILIPS_SECAM,
+		.inputs         = {{
+			.name = name_tv,
+			.vmux = 1,
+			.amux = LINE2,
+			.tv   = 1,
+		},{
+			.name = name_comp1,
+			.vmux = 0,
+			.amux = LINE2,
+		},{
+			.name = name_svideo,
+			.vmux = 8,
+			.amux = LINE2,
+		}},
+	},
 	[SAA7134_BOARD_EMPRESS] = {
 		/* "Gert Vervoort" <gert.vervoort@philips.com> */
 		.name		= "EMPRESS",
@@ -177,7 +197,6 @@
 			.name = name_radio,
 			.amux = LINE2,
 		},
-		.i2s_rate  = 48000,
 		.has_ts    = 1,
 		.video_out = CCIR656,
 	},
@@ -243,7 +262,7 @@
 		.name		= "KNC One TV-Station RDS / Typhoon TV Tuner RDS",
 		.audio_clock	= 0x00200000,
 		.tuner_type	= TUNER_PHILIPS_FM1216ME_MK3,
-		.need_tda9887   = 1,
+		.tda9887_conf   = TDA9887_PRESENT,
 		.inputs         = {{
 			.name = name_tv,
 			.vmux = 1,
@@ -278,7 +297,7 @@
 		.name		= "KNC One TV-Station DVR",
 		.audio_clock	= 0x00200000,
 		.tuner_type	= TUNER_PHILIPS_FM1216ME_MK3,
-		.need_tda9887	= 1,
+		.tda9887_conf	= TDA9887_PRESENT,
 		.gpiomask	= 0x820000,
 		.inputs		= {{
 			.name = name_tv,
@@ -302,7 +321,6 @@
 			.amux = LINE2,
 			.gpio = 0x20000,
 		},
-		.i2s_rate	= 48000,
 		.has_ts		= 1,
 		.video_out	= CCIR656,
 	},
@@ -333,7 +351,7 @@
 		.name           = "Medion 5044",
 		.audio_clock    = 0x00187de7, // was: 0x00200000,
 		.tuner_type     = TUNER_PHILIPS_FM1216ME_MK3,
-		.need_tda9887   = 1,
+		.tda9887_conf   = TDA9887_PRESENT,
 		.inputs         = {{
 			.name = name_tv,
 			.vmux = 1,
@@ -414,7 +432,7 @@
 		//.audio_clock    = 0x00200000,
 		.audio_clock    = 0x00187de7,
 		.tuner_type     = TUNER_PHILIPS_FM1216ME_MK3,
-		.need_tda9887   = 1,
+		.tda9887_conf   = TDA9887_PRESENT,
 		.inputs = {{
 			.name   = name_tv,
 			.vmux   = 1,
@@ -440,7 +458,7 @@
 		.name           = "Typhoon TV+Radio 90031",
 		.audio_clock    = 0x00200000,
 		.tuner_type     = TUNER_PHILIPS_PAL,
-		.need_tda9887   = 1,
+		.tda9887_conf   = TDA9887_PRESENT,
 		.inputs         = {{
 			.name   = name_tv,
 			.vmux   = 1,
@@ -503,7 +521,7 @@
                 .name           = "ASUS TV-FM 7134",
                 .audio_clock    = 0x00187de7,
                 .tuner_type     = TUNER_PHILIPS_FM1216ME_MK3,
-                .need_tda9887   = 1,
+                .tda9887_conf   = TDA9887_PRESENT,
                 .inputs         = {{
                         .name = name_tv,
                         .vmux = 1,
@@ -607,7 +625,6 @@
 			.vmux = 8,
 			.amux = LINE1,
 		}},
-		.i2s_rate  = 48000,
 		.has_ts    = 1,
 		.video_out = CCIR656,
 	},
@@ -666,7 +683,7 @@
 		.name           = "AverMedia M156 / Medion 2819",
 		.audio_clock    = 0x00187de7,
 		.tuner_type     = TUNER_PHILIPS_FM1216ME_MK3,
-		.need_tda9887   = 1,
+		.tda9887_conf   = TDA9887_PRESENT,
 		.inputs         = {{
 			.name = name_tv,
 			.vmux = 1,
@@ -709,7 +726,6 @@
 			.amux = LINE2,
 			.tv   = 1,
 		}},
-		.i2s_rate  = 48000,
 		.has_ts    = 1,
 		.video_out = CCIR656,
         },
@@ -719,7 +735,7 @@
 		// probably wrong, the 7133 one is the NTSC version ...
 		// .tuner_type     = TUNER_PHILIPS_FM1236_MK3
                 .tuner_type     = TUNER_LG_NTSC_NEW_TAPC,
-                .need_tda9887   = 1,
+                .tda9887_conf   = TDA9887_PRESENT,
                 .inputs         = {{
                         .name = name_tv,
                         .vmux = 1,
@@ -743,7 +759,7 @@
                 .name           = "Pinnacle PCTV Stereo (saa7134)",
                 .audio_clock    = 0x00187de7,
                 .tuner_type     = TUNER_MT2032,
-                .need_tda9887   = 1,
+                .tda9887_conf   = TDA9887_PRESENT,
                 .inputs         = {{
                         .name = name_tv,
                         .vmux = 3,
@@ -957,7 +973,7 @@
 		.name           = "AverMedia 305",
 		.audio_clock    = 0x00187de7,
 		.tuner_type     = TUNER_PHILIPS_FM1216ME_MK3,
-		.need_tda9887   = 1,
+		.tda9887_conf   = TDA9887_PRESENT,
 		.inputs         = {{
 			.name = name_tv,
 			.vmux = 1,
@@ -989,7 +1005,7 @@
   		.name           = "UPMOST PURPLE TV",
   		.audio_clock    = 0x00187de7,
   		.tuner_type     = TUNER_PHILIPS_FM1236_MK3,
-  		.need_tda9887   = 1,
+  		.tda9887_conf   = TDA9887_PRESENT,
   		.inputs         = {{
   			.name = name_tv,
   			.vmux = 7,
@@ -1000,7 +1016,7 @@
   			.vmux = 7,
   			.amux = LINE1,
   		}},
-          },
+	},
 	[SAA7134_BOARD_ITEMS_MTV005] = {
 		/* Norman Jonas <normanjonas@arcor.de> */
 		.name           = "Items MuchTV Plus / IT-005",
@@ -1025,6 +1041,56 @@
 			.amux = LINE2,
 		},
 	},
+	[SAA7134_BOARD_CINERGY200] = {
+		.name           = "Terratec Cinergy 200 TV",
+		.audio_clock    = 0x00200000,
+		.tuner_type     = TUNER_PHILIPS_PAL,
+		.inputs         = {{
+       			.name = name_tv,
+			.vmux = 1,
+			.amux = LINE2,
+			.gpio = 0x0000,
+			.tv   = 1,
+		}},
+		.mute = {
+			 .name = name_mute,
+			 .amux = LINE2,
+		},
+	},
+	[SAA7134_BOARD_VIDEOMATE_TV_PVR] = {
+		/* Alain St-Denis <alain@topaze.homeip.net> */
+		.name           = "Compro VideoMate TV PVR/FM",
+		.audio_clock    = 0x00187de7,
+		.tuner_type     = TUNER_PHILIPS_NTSC_M,
+		.gpiomask	= 0x808c0080,
+                .inputs         = {{
+                        .name = name_svideo,
+                        .vmux = 8,
+                        .amux = LINE1,
+			.gpio = 0x00080
+                },{
+                        .name = name_comp1,
+                        .vmux = 3,
+                        .amux = LINE1,
+			.gpio = 0x00080
+                },{
+                        .name = name_tv,
+                        .vmux = 1,
+                        .amux = LINE2,
+                        .tv   = 1,
+			.gpio = 0x00080
+                }},
+		.radio = {
+			 .name = name_radio,
+			 .amux = LINE2,
+			.gpio = 0x80000
+		 },
+		.mute = {
+			.name = name_mute,
+                        .amux = LINE2,
+			.gpio = 0x40000,
+		},
+        },
 };
 const unsigned int saa7134_bcount = ARRAY_SIZE(saa7134_boards);
 
@@ -1088,6 +1154,12 @@
 		.driver_data  = SAA7134_BOARD_FLYVIDEO2000,
         },{
 		.vendor       = PCI_VENDOR_ID_PHILIPS,
+		.device       = PCI_DEVICE_ID_PHILIPS_SAA7135,
+		.subvendor    = 0x5168,
+		.subdevice    = 0x0212,
+		.driver_data  = SAA7134_BOARD_FLYTVPLATINUM,
+        },{
+		.vendor       = PCI_VENDOR_ID_PHILIPS,
 		.device       = PCI_DEVICE_ID_PHILIPS_SAA7134,
 		.subvendor    = 0x16be,
 		.subdevice    = 0x0003,
@@ -1219,6 +1291,19 @@
                 .subvendor    = 0x12ab,
                 .subdevice    = 0x0800,
  		.driver_data  = SAA7133_BOARD_UPMOST_PURPLE_TV,
+	},{
+		.vendor       = PCI_VENDOR_ID_PHILIPS,
+		.device       = PCI_DEVICE_ID_PHILIPS_SAA7130,
+		.subvendor    = 0x153B,
+		.subdevice    = 0x1152,
+		.driver_data  = SAA7134_BOARD_CINERGY200,
+
+ 	},{
+		.vendor       = PCI_VENDOR_ID_PHILIPS,
+		.device       = PCI_DEVICE_ID_PHILIPS_SAA7130,
+                .subvendor    = 0x185b,
+                .subdevice    = 0xc100,
+		.driver_data  = SAA7134_BOARD_VIDEOMATE_TV_PVR,
 		
  	},{
 		/* --- boards without eeprom + subsystem ID --- */
@@ -1297,6 +1382,7 @@
 static void board_flyvideo(struct saa7134_dev *dev)
 {
 #if 0
+	/* non-working attempt to detect the correct tuner type ... */
 	u32 value;
 	int index;
 
@@ -1307,6 +1393,10 @@
 	       fly_list[index].tuner_type);
 	dev->tuner_type = fly_list[index].tuner_type;
 #endif
+	printk("%s: there are different flyvideo cards with different tuners\n"
+	       "%s: out there, you might have to use the tuner=<nr> insmod\n"
+	       "%s: option to override the default value.\n",
+	       dev->name, dev->name, dev->name);
 }
 
 /* ----------------------------------------------------------- */
@@ -1321,8 +1411,10 @@
 	switch (dev->board) {
 	case SAA7134_BOARD_FLYVIDEO2000:
 	case SAA7134_BOARD_FLYVIDEO3000:
-		board_flyvideo(dev);
 		dev->has_remote = 1;
+		/* fall throuth */
+	case SAA7134_BOARD_FLYTVPLATINUM:
+		board_flyvideo(dev);
 		break;
 	case SAA7134_BOARD_CINERGY400:
 	case SAA7134_BOARD_CINERGY600:
@@ -1332,6 +1424,12 @@
 		break;
 	case SAA7134_BOARD_AVACSSMARTTV:
 		dev->has_remote = 1;
+		break;
+	case SAA7134_BOARD_MD5044:
+		printk("%s: seems there are two different versions of the MD5044\n"
+		       "%s: (with the same ID) out there.  If sound doesn't work for\n"
+		       "%s: you try the audio_clock_override=0x200000 insmod option.\n",
+		       dev->name,dev->name,dev->name);
 		break;
 	}
 	return 0;
diff -Nru a/drivers/media/video/saa7134/saa7134-core.c b/drivers/media/video/saa7134/saa7134-core.c
--- a/drivers/media/video/saa7134/saa7134-core.c	2004-10-18 14:56:28 -07:00
+++ b/drivers/media/video/saa7134/saa7134-core.c	2004-10-18 14:56:28 -07:00
@@ -868,7 +868,8 @@
 		must_configure_manually();
 		dev->board = SAA7134_BOARD_UNKNOWN;
 	}
-	dev->tuner_type = saa7134_boards[dev->board].tuner_type;
+	dev->tuner_type   = saa7134_boards[dev->board].tuner_type;
+	dev->tda9887_conf = saa7134_boards[dev->board].tda9887_conf;
 	if (UNSET != tuner[saa7134_devcount])
 		dev->tuner_type = tuner[saa7134_devcount];
         printk(KERN_INFO "%s: subsystem: %04x:%04x, board: %s [card=%d,%s]\n",
@@ -919,7 +920,7 @@
 	/* load i2c helpers */
 	if (TUNER_ABSENT != dev->tuner_type)
 		request_module("tuner");
-	if (saa7134_boards[dev->board].need_tda9887)
+	if (dev->tda9887_conf)
 		request_module("tda9887");
   	if (card_has_ts(dev))
 		request_module("saa6752hs");
@@ -949,7 +950,7 @@
 			       dev->name);
 			goto fail4;
 		}
-		printk(KERN_INFO "%s: registered device video%d [ts]\n",
+		printk(KERN_INFO "%s: registered device video%d [mpeg]\n",
 		       dev->name,dev->ts_dev->minor & 0x1f);
 	}
 	
diff -Nru a/drivers/media/video/saa7134/saa7134-i2c.c b/drivers/media/video/saa7134/saa7134-i2c.c
--- a/drivers/media/video/saa7134/saa7134-i2c.c	2004-10-18 14:56:13 -07:00
+++ b/drivers/media/video/saa7134/saa7134-i2c.c	2004-10-18 14:56:13 -07:00
@@ -327,8 +327,10 @@
 {
         struct saa7134_dev *dev = client->adapter->algo_data;
 	int tuner = dev->tuner_type;
+	int conf  = dev->tda9887_conf;
 
 	saa7134_i2c_call_clients(dev,TUNER_SET_TYPE,&tuner);
+	saa7134_i2c_call_clients(dev,TDA9887_SET_CONFIG,&conf);
         return 0;
 }
 
diff -Nru a/drivers/media/video/saa7134/saa7134-oss.c b/drivers/media/video/saa7134/saa7134-oss.c
--- a/drivers/media/video/saa7134/saa7134-oss.c	2004-10-18 14:56:31 -07:00
+++ b/drivers/media/video/saa7134/saa7134-oss.c	2004-10-18 14:56:31 -07:00
@@ -776,8 +776,6 @@
 	dev->oss.rate = 32000;
 	if (oss_rate)
 		dev->oss.rate = oss_rate;
-	if (saa7134_boards[dev->board].i2s_rate)
-		dev->oss.rate = saa7134_boards[dev->board].i2s_rate;
 	dev->oss.rate = (dev->oss.rate > 40000) ? 48000 : 32000;
 
 	/* mixer */
diff -Nru a/drivers/media/video/saa7134/saa7134-tvaudio.c b/drivers/media/video/saa7134/saa7134-tvaudio.c
--- a/drivers/media/video/saa7134/saa7134-tvaudio.c	2004-10-18 14:55:53 -07:00
+++ b/drivers/media/video/saa7134/saa7134-tvaudio.c	2004-10-18 14:55:53 -07:00
@@ -504,7 +504,8 @@
 		dprintk("tvaudio thread scan start [%d]\n",dev->thread.scan1);
 		dev->tvaudio  = NULL;
 		tvaudio_init(dev);
-		dev->automute = 1;
+		if (dev->ctl_automute)
+			dev->automute = 1;
 		mute_input_7134(dev);
 
 		/* give the tuner some time */
@@ -924,8 +925,9 @@
 	int (*my_thread)(void *data) = NULL;
 
 	/* enable I2S audio output */
-	if (saa7134_boards[dev->board].i2s_rate) {
-		int i2sform = (32000 == saa7134_boards[dev->board].i2s_rate) ? 0x00 : 0x01;
+	if (saa7134_boards[dev->board].has_ts) {
+		int i2sform = (48000 == dev->oss.rate)
+			? 0x01 : 0x00;
 		
 		/* enable I2S output */
 		saa_writeb(SAA7134_I2S_OUTPUT_SELECT,  0x80); 
diff -Nru a/drivers/media/video/saa7134/saa7134-video.c b/drivers/media/video/saa7134/saa7134-video.c
--- a/drivers/media/video/saa7134/saa7134-video.c	2004-10-18 14:56:14 -07:00
+++ b/drivers/media/video/saa7134/saa7134-video.c	2004-10-18 14:56:14 -07:00
@@ -272,7 +272,8 @@
 #define V4L2_CID_PRIVATE_INVERT      (V4L2_CID_PRIVATE_BASE + 0)
 #define V4L2_CID_PRIVATE_Y_ODD       (V4L2_CID_PRIVATE_BASE + 1)
 #define V4L2_CID_PRIVATE_Y_EVEN      (V4L2_CID_PRIVATE_BASE + 2)
-#define V4L2_CID_PRIVATE_LASTP1      (V4L2_CID_PRIVATE_BASE + 3)
+#define V4L2_CID_PRIVATE_AUTOMUTE    (V4L2_CID_PRIVATE_BASE + 3)
+#define V4L2_CID_PRIVATE_LASTP1      (V4L2_CID_PRIVATE_BASE + 4)
 
 static const struct v4l2_queryctrl no_ctrl = {
 	.name  = "42",
@@ -356,6 +357,13 @@
 		.maximum       = 128,
 		.default_value = 0,
 		.type          = V4L2_CTRL_TYPE_INTEGER,
+	},{
+		.id            = V4L2_CID_PRIVATE_AUTOMUTE,
+		.name          = "automute",
+		.minimum       = 0,
+		.maximum       = 1,
+		.default_value = 1,
+		.type          = V4L2_CTRL_TYPE_BOOLEAN,
 	}
 };
 static const unsigned int CTRLS = ARRAY_SIZE(video_ctrls);
@@ -433,10 +441,11 @@
 
 static void set_tvnorm(struct saa7134_dev *dev, struct saa7134_tvnorm *norm)
 {
-	int luma_control,sync_control,mux;
+	int luma_control,sync_control,mux,nosignal;
 
 	dprintk("set tv norm = %s\n",norm->name);
 	dev->tvnorm = norm;
+        nosignal = (0 == (saa_readb(SAA7134_STATUS_VIDEO1) & 0x03));
 
 	mux = card_in(dev,dev->ctl_input).vmux;
 	luma_control = norm->luma_control;
@@ -444,7 +453,7 @@
 
 	if (mux > 5)
 		luma_control |= 0x80; /* svideo */
-	if (noninterlaced)
+	if (noninterlaced || nosignal)
 		sync_control |= 0x20;
 
 	/* setup cropping */
@@ -1043,6 +1052,9 @@
 	case V4L2_CID_PRIVATE_Y_ODD:
 		c->value = dev->ctl_y_odd;
 		break;
+	case V4L2_CID_PRIVATE_AUTOMUTE:
+		c->value = dev->ctl_automute;
+		break;
 	default:
 		return -EINVAL;
 	}
@@ -1118,6 +1130,17 @@
 		dev->ctl_y_odd = c->value;
 		restart_overlay = 1;
 		break;
+	case V4L2_CID_PRIVATE_AUTOMUTE:
+		dev->ctl_automute = c->value;
+		if (dev->tda9887_conf) {
+			if (dev->ctl_automute)
+				dev->tda9887_conf |= TDA9887_AUTOMUTE;
+			else
+				dev->tda9887_conf &= ~TDA9887_AUTOMUTE;
+			saa7134_i2c_call_clients(dev, TDA9887_SET_CONFIG,
+						 &dev->tda9887_conf);
+		}
+		break;
 	default:
 		return -EINVAL;
 	}
@@ -1820,7 +1843,7 @@
 		struct v4l2_frequency *f = arg;
 
 		memset(f,0,sizeof(*f));
-		f->type = V4L2_TUNER_ANALOG_TV;
+		f->type = fh->radio ? V4L2_TUNER_RADIO : V4L2_TUNER_ANALOG_TV;
 		f->frequency = dev->ctl_freq;
 		return 0;
 	}
@@ -1830,7 +1853,9 @@
 
 		if (0 != f->tuner)
 			return -EINVAL;
-		if (V4L2_TUNER_ANALOG_TV != f->type)
+		if (0 == fh->radio && V4L2_TUNER_ANALOG_TV != f->type)
+			return -EINVAL;
+		if (1 == fh->radio && V4L2_TUNER_RADIO != f->type)
 			return -EINVAL;
 		down(&dev->lock);
 		dev->ctl_freq = f->frequency;
@@ -2244,9 +2269,12 @@
 	dev->ctl_hue        = ctrl_by_id(V4L2_CID_HUE)->default_value;
 	dev->ctl_saturation = ctrl_by_id(V4L2_CID_SATURATION)->default_value;
 	dev->ctl_volume     = ctrl_by_id(V4L2_CID_AUDIO_VOLUME)->default_value;
+	dev->ctl_mute       = ctrl_by_id(V4L2_CID_AUDIO_MUTE)->default_value;
+	dev->ctl_invert     = ctrl_by_id(V4L2_CID_PRIVATE_INVERT)->default_value;
+	dev->ctl_automute   = ctrl_by_id(V4L2_CID_PRIVATE_AUTOMUTE)->default_value;
 
-	dev->ctl_invert     = 0;
-	dev->ctl_mute       = 1;
+	if (dev->tda9887_conf && dev->ctl_automute)
+		dev->tda9887_conf |= TDA9887_AUTOMUTE;
 	dev->automute       = 0;
 
         INIT_LIST_HEAD(&dev->video_q.queue);
@@ -2300,10 +2328,14 @@
 	if (0 != norm) {
 		/* wake up tvaudio audio carrier scan thread */
 		saa7134_tvaudio_do_scan(dev);
+		if (!noninterlaced)
+			saa_clearb(SAA7134_SYNC_CTRL, 0x20);
 	} else {
 		/* no video signal -> mute audio */
-		dev->automute = 1;
+		if (dev->ctl_automute)
+			dev->automute = 1;
 		saa7134_tvaudio_setmute(dev);
+		saa_setb(SAA7134_SYNC_CTRL, 0x20);
 	}
 }
 
diff -Nru a/drivers/media/video/saa7134/saa7134.h b/drivers/media/video/saa7134/saa7134.h
--- a/drivers/media/video/saa7134/saa7134.h	2004-10-18 14:56:49 -07:00
+++ b/drivers/media/video/saa7134/saa7134.h	2004-10-18 14:56:49 -07:00
@@ -156,6 +156,9 @@
 #define SAA7134_BOARD_AVERMEDIA_305    35
 #define SAA7133_BOARD_UPMOST_PURPLE_TV 36
 #define SAA7134_BOARD_ITEMS_MTV005     37
+#define SAA7134_BOARD_CINERGY200       38
+#define SAA7134_BOARD_FLYTVPLATINUM    39
+#define SAA7134_BOARD_VIDEOMATE_TV_PVR 40
 
 #define SAA7134_INPUT_MAX 8
 
@@ -178,13 +181,12 @@
 	struct saa7134_input    mute;
 	
 	/* peripheral I/O */
-	unsigned int            i2s_rate;
 	unsigned int            has_ts;
 	enum saa7134_video_out  video_out;
 
 	/* i2c chip info */
 	unsigned int            tuner_type;
-	unsigned int            need_tda9887:1;
+	unsigned int            tda9887_conf;
 };
 
 #define card_has_radio(dev)   (NULL != saa7134_boards[dev->board].radio.name)
@@ -362,6 +364,7 @@
 	/* config info */
 	unsigned int               board;
 	unsigned int               tuner_type;
+	unsigned int               tda9887_conf;
 	unsigned int               gpio_value;
 
 	/* i2c i/o */
@@ -397,6 +400,7 @@
 	int                        ctl_mirror;
 	int                        ctl_y_odd;
 	int                        ctl_y_even;
+	int                        ctl_automute;
 
 	/* crop */
 	struct v4l2_rect           crop_bounds;
diff -Nru a/drivers/media/video/tda7432.c b/drivers/media/video/tda7432.c
--- a/drivers/media/video/tda7432.c	2004-10-18 14:56:48 -07:00
+++ b/drivers/media/video/tda7432.c	2004-10-18 14:56:48 -07:00
@@ -532,17 +532,17 @@
 	.driver     = &driver, 
 };
 
-static int tda7432_init(void)
+static int __init tda7432_init(void)
 {
 	if ( (loudness < 0) || (loudness > 15) ) {
 		printk(KERN_ERR "tda7432: loudness parameter must be between 0 and 15\n");
 		return -EINVAL;
 	}
-	i2c_add_driver(&driver);
-	return 0;
+
+	return i2c_add_driver(&driver);
 }
 
-static void tda7432_fini(void)
+static void __exit tda7432_fini(void)
 {
 	i2c_del_driver(&driver);
 }
diff -Nru a/drivers/media/video/tda9875.c b/drivers/media/video/tda9875.c
--- a/drivers/media/video/tda9875.c	2004-10-18 14:56:29 -07:00
+++ b/drivers/media/video/tda9875.c	2004-10-18 14:56:29 -07:00
@@ -403,13 +403,12 @@
         .driver    = &driver,
 };
 
-static int tda9875_init(void)
+static int __init tda9875_init(void)
 {
-	i2c_add_driver(&driver);
-	return 0;
+	return i2c_add_driver(&driver);
 }
 
-static void tda9875_fini(void)
+static void __exit tda9875_fini(void)
 {
 	i2c_del_driver(&driver);
 }
diff -Nru a/drivers/media/video/tda9887.c b/drivers/media/video/tda9887.c
--- a/drivers/media/video/tda9887.c	2004-10-18 14:55:53 -07:00
+++ b/drivers/media/video/tda9887.c	2004-10-18 14:55:53 -07:00
@@ -8,6 +8,7 @@
 #include <linux/slab.h>
 
 #include <media/audiochip.h>
+#include <media/tuner.h>
 #include <media/id.h>
 
 /* Chips:
@@ -47,6 +48,7 @@
 	struct i2c_client  client;
 	v4l2_std_id        std;
 	unsigned int       radio;
+	unsigned int       config;
 	unsigned int       pinnacle_id;
 	unsigned int       using_v4l2;
 };
@@ -397,6 +399,36 @@
 	return 0;
 }
 
+static int tda9887_set_config(struct tda9887 *t, char *buf)
+{
+	if (t->config & TDA9887_PORT1)
+		buf[1] |= cOutputPort1Inactive;
+	if (t->config & TDA9887_PORT2)
+		buf[1] |= cOutputPort2Inactive;
+	if (t->config & TDA9887_QSS)
+		buf[1] |= cQSS;
+	if (t->config & TDA9887_INTERCARRIER)
+		buf[1] &= ~cQSS;
+
+	if (t->config & TDA9887_AUTOMUTE)
+		buf[1] |= cAutoMuteFmActive;
+	if (t->config & TDA9887_DEEMPHASIS_MASK) {
+		buf[2] &= ~0x60;
+		switch (t->config & TDA9887_DEEMPHASIS_MASK) {
+		case TDA9887_DEEMPHASIS_NONE:
+			buf[2] |= cDeemphasisOFF;
+			break;
+		case TDA9887_DEEMPHASIS_50:
+			buf[2] |= cDeemphasisON | cDeemphasis50;
+			break;
+		case TDA9887_DEEMPHASIS_75:
+			buf[2] |= cDeemphasisON | cDeemphasis75;
+			break;
+		}
+	}
+	return 0;
+}
+
 /* ---------------------------------------------------------------------- */
 
 static int tda9887_set_pinnacle(struct tda9887 *t, char *buf)
@@ -499,6 +531,7 @@
 	if (UNSET != t->pinnacle_id) {
 		tda9887_set_pinnacle(t,buf);
 	}
+	tda9887_set_config(t,buf);
 	tda9887_set_insmod(t,buf);
 
 	dprintk(PREFIX "writing: b=0x%02x c=0x%02x e=0x%02x\n",
@@ -594,6 +627,14 @@
 		tda9887_configure(t);
 		break;
 	}
+	case TDA9887_SET_CONFIG:
+	{
+		int *i = arg;
+
+		t->config = *i;
+		tda9887_configure(t);
+		break;
+	}
 	/* --- v4l ioctls --- */
 	/* take care: bttv does userspace copying, we'll get a
 	   kernel pointer here... */
@@ -644,6 +685,25 @@
 			t->radio = 1;
 		}
 		tda9887_configure(t);
+		break;
+	}
+	case VIDIOC_G_TUNER:
+	{
+		static int AFC_BITS_2_kHz[] = {
+			-12500,  -37500,  -62500,  -97500,
+			-112500, -137500, -162500, -187500,
+			187500,  162500,  137500,  112500,
+			97500 ,  62500,   37500 ,  12500
+		};
+		struct v4l2_tuner* tuner = arg;
+
+		if (t->radio) {
+			__u8 reg = 0;
+			tuner->afc=0;
+			if (1 == i2c_master_recv(&t->client,&reg,1))
+				tuner->afc = AFC_BITS_2_kHz[(reg>>1)&0x0f];
+		}
+		break;
 	}
 	default:
 		/* nothing */
@@ -670,13 +730,12 @@
         .driver    = &driver,
 };
 
-static int tda9887_init_module(void)
+static int __init tda9887_init_module(void)
 {
-	i2c_add_driver(&driver);
-	return 0;
+	return i2c_add_driver(&driver);
 }
 
-static void tda9887_cleanup_module(void)
+static void __exit tda9887_cleanup_module(void)
 {
 	i2c_del_driver(&driver);
 }
diff -Nru a/drivers/media/video/tuner.c b/drivers/media/video/tuner.c
--- a/drivers/media/video/tuner.c	2004-10-18 14:56:50 -07:00
+++ b/drivers/media/video/tuner.c	2004-10-18 14:56:50 -07:00
@@ -208,7 +208,7 @@
 	{ "Temic PAL* auto + FM (4009 FN5)", TEMIC, PAL,
 	  16*141.00, 16*464.00, 0xa0,0x90,0x30,0x8e,623},
 	{ "SHARP NTSC_JP (2U5JF5540)", SHARP, NTSC, /* 940=16*58.75 NTSC@Japan */
-	  16*137.25,16*317.25,0x01,0x02,0x08,0x8e,732 }, // Corrected to NTSC=732 (was:940)
+	  16*137.25,16*317.25,0x01,0x02,0x08,0x8e,940 },
 
 	{ "Samsung PAL TCPM9091PD27", Samsung, PAL,  /* from sourceforge v3tv */
           16*169,16*464,0xA0,0x90,0x30,0x8e,623},
@@ -229,7 +229,7 @@
           16*170.00, 16*450.00, 0x01,0x02,0x08,0x8e,732},
 
 	{ "HITACHI V7-J180AT", HITACHI, NTSC,
-	  16*170.00, 16*450.00, 0x01,0x02,0x00,0x8e,940 },
+	  16*170.00, 16*450.00, 0x01,0x02,0x08,0x8e,940 },
 	{ "Philips PAL_MK (FI1216 MK)", Philips, PAL,
 	  16*140.25,16*463.25,0x01,0xc2,0xcf,0x8e,623},
 	{ "Philips 1236D ATSC/NTSC daul in",Philips,ATSC,
@@ -241,6 +241,13 @@
           16*160.00,16*442.00,0x01,0x02,0x04,0x8e,732},
 	{ "Microtune 4049 FM5",Microtune,PAL,
 	  16*141.00,16*464.00,0xa0,0x90,0x30,0x8e,623},
+	{ "Panasonic VP27s/ENGE4324D", Panasonic, NTSC,
+	  16*160.00,16*454.00,0x01,0x02,0x08,0xce,940},
+        { "LG NTSC (TAPE series)", LGINNOTEK, NTSC,
+          16*170.00, 16*450.00, 0x01,0x02,0x04,0x8e,732 },
+
+        { "Tenna TNF 8831 BGFF)", Philips, PAL,
+          16*161.25,16*463.25,0xa0,0x90,0x30,0x8e,623},
 
 };
 #define TUNERS ARRAY_SIZE(tuners)
@@ -934,6 +941,9 @@
 	case TUNER_PHILIPS_FM1236_MK3:
 		buffer[3] = 0x19;
 		break;
+	case TUNER_LG_PAL_FM:
+		buffer[3] = 0xa5;
+		break;
 	default:
 		buffer[3] = 0xa4;
 		break;
@@ -1300,13 +1310,12 @@
         .driver     = &driver,
 };
 
-static int tuner_init_module(void)
+static int __init tuner_init_module(void)
 {
-	i2c_add_driver(&driver);
-	return 0;
+	return i2c_add_driver(&driver);
 }
 
-static void tuner_cleanup_module(void)
+static void __exit tuner_cleanup_module(void)
 {
 	i2c_del_driver(&driver);
 }
diff -Nru a/drivers/media/video/tvaudio.c b/drivers/media/video/tvaudio.c
--- a/drivers/media/video/tvaudio.c	2004-10-18 14:56:28 -07:00
+++ b/drivers/media/video/tvaudio.c	2004-10-18 14:56:28 -07:00
@@ -1651,7 +1651,7 @@
         .driver     = &driver,
 };
 
-static int audiochip_init_module(void)
+static int __init audiochip_init_module(void)
 {
 	struct CHIPDESC  *desc;
 	printk(KERN_INFO "tvaudio: TV audio decoder + audio/video mux driver\n");
@@ -1659,11 +1659,11 @@
 	for (desc = chiplist; desc->name != NULL; desc++)
 		printk("%s%s", (desc == chiplist) ? "" : ",",desc->name);
 	printk("\n");
-	i2c_add_driver(&driver);
-	return 0;
+
+	return i2c_add_driver(&driver);
 }
 
-static void audiochip_cleanup_module(void)
+static void __exit audiochip_cleanup_module(void)
 {
 	i2c_del_driver(&driver);
 }
diff -Nru a/drivers/media/video/tvmixer.c b/drivers/media/video/tvmixer.c
--- a/drivers/media/video/tvmixer.c	2004-10-18 14:57:03 -07:00
+++ b/drivers/media/video/tvmixer.c	2004-10-18 14:57:03 -07:00
@@ -330,17 +330,17 @@
 
 /* ----------------------------------------------------------------------- */
 
-static int tvmixer_init_module(void)
+static int __init tvmixer_init_module(void)
 {
 	int i;
 	
 	for (i = 0; i < DEV_MAX; i++)
 		devices[i].minor = -1;
-	i2c_add_driver(&driver);
-	return 0;
+
+	return i2c_add_driver(&driver);
 }
 
-static void tvmixer_cleanup_module(void)
+static void __exit tvmixer_cleanup_module(void)
 {
 	int i;
 	
diff -Nru a/drivers/media/video/videodev.c b/drivers/media/video/videodev.c
--- a/drivers/media/video/videodev.c	2004-10-18 14:55:55 -07:00
+++ b/drivers/media/video/videodev.c	2004-10-18 14:55:55 -07:00
@@ -254,7 +254,7 @@
 	return 0;
 }
 
-extern struct file_operations video_fops;
+static struct file_operations video_fops;
 
 /**
  *	video_register_device - register video4linux devices
diff -Nru a/drivers/media/video/zoran_device.c b/drivers/media/video/zoran_device.c
--- a/drivers/media/video/zoran_device.c	2004-10-18 14:56:32 -07:00
+++ b/drivers/media/video/zoran_device.c	2004-10-18 14:56:32 -07:00
@@ -1105,8 +1105,7 @@
 			ZR36057_ISR);
 		btand(~ZR36057_JMC_Go_en, ZR36057_JMC);	// \Go_en
 
-		current->state = TASK_UNINTERRUPTIBLE;
-		schedule_timeout(HZ / 20);
+		msleep(50);
 
 		set_videobus_dir(zr, 0);
 		set_frame(zr, 1);	// /FRAME
diff -Nru a/drivers/media/video/zoran_driver.c b/drivers/media/video/zoran_driver.c
--- a/drivers/media/video/zoran_driver.c	2004-10-18 14:56:49 -07:00
+++ b/drivers/media/video/zoran_driver.c	2004-10-18 14:56:49 -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-10-18 14:57:18 -07:00
+++ b/drivers/message/fusion/Kconfig	2004-10-18 14:57:18 -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-10-18 14:56:33 -07:00
+++ b/drivers/message/fusion/Makefile	2004-10-18 14:56:33 -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	2004-10-18 14:57:04 -07: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	2004-10-18 14:56:32 -07: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-10-18 14:56:31 -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	2004-10-18 14:56:33 -07: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-10-18 14:56:19 -07:00
+++ b/drivers/message/fusion/mptbase.c	2004-10-18 14:56:19 -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-10-18 14:56:15 -07:00
+++ b/drivers/message/fusion/mptbase.h	2004-10-18 14:56:15 -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;
 
 /*
@@ -592,33 +581,38 @@
 	int			 pci_irq;	/* This irq           */
 	char			 name[MPT_NAME_LENGTH];	/* "iocN"             */
 	char			*prod_name;	/* "LSIFC9x9"         */
-	volatile SYSIF_REGS	*chip;		/* == c8817000 (mmap) */
-	volatile SYSIF_REGS	*pio_chip;	/* Programmed IO (downloadboot) */
+	SYSIF_REGS __iomem	*chip;		/* == c8817000 (mmap) */
+	SYSIF_REGS __iomem	*pio_chip;	/* Programmed IO (downloadboot) */
 	u32			 mem_phys;	/* == f4020000 (mmap) */
 	u32			 pio_mem_phys;	/* Programmed IO (downloadboot) */
 	int			 mem_size;	/* mmap memory size */
 	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-10-18 14:55:54 -07:00
+++ b/drivers/message/fusion/mptctl.c	2004-10-18 14:55:54 -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-10-18 14:56:32 -07:00
+++ b/drivers/message/fusion/mptlan.c	2004-10-18 14:56:32 -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-10-18 14:57:19 -07:00
+++ b/drivers/message/fusion/mptscsih.c	2004-10-18 14:57:19 -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;
@@ -2937,8 +2623,7 @@
 			break;
 		}
 		spin_unlock_irqrestore(&hd->ioc->FreeQlock, flags);
-		set_current_state(TASK_INTERRUPTIBLE);
-		schedule_timeout(HZ/4);
+		msleep(250);
 	} while (--loop_count);
 
 	return status;
@@ -2965,9 +2650,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 +2664,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 +2683,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 +2712,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 +2732,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 +2755,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 +2779,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 +2802,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 +2828,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 +2857,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 +2883,7 @@
 			}
 		}
 	}
-	
+
 	return;
 }
 
@@ -3212,7 +2893,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 +2921,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 +2991,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 +3029,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 +3052,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 +3086,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 +3100,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 +3108,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 +3135,6 @@
 
 		/* 2. Chain Buffer initialization
 		 */
-		mptscsih_initChainBuffers(hd, 0);
 
 		/* 3. tmPtr clear
 		 */
@@ -3583,8 +3144,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 +3155,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 +3171,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 +3192,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 +3324,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 +3346,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 +3385,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 +3438,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 +3452,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 +3461,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 +3620,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 +3697,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 +3813,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 +3834,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 +3945,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 +3981,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 +4110,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 +4163,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 +4174,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 +4184,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 +4212,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 +4384,7 @@
 	/* Set command specific information
 	 */
 	switch (cmd) {
-	case CMD_Inquiry:
+	case INQUIRY:
 		cmdLen = 6;
 		dir = MPI_SCSIIO_CONTROL_READ;
 		CDB[0] = cmd;
@@ -5205,13 +4392,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 +4406,7 @@
 		cmdTimeout = 15;
 		break;
 
-	case CMD_RequestSense:
+	case REQUEST_SENSE:
 		cmdLen = 6;
 		CDB[0] = cmd;
 		CDB[4] = io->size;
@@ -5227,7 +4414,7 @@
 		cmdTimeout = 10;
 		break;
 
-	case CMD_ReadBuffer:
+	case READ_BUFFER:
 		cmdLen = 10;
 		dir = MPI_SCSIIO_CONTROL_READ;
 		CDB[0] = cmd;
@@ -5246,7 +4433,7 @@
 		cmdTimeout = 10;
 		break;
 
-	case CMD_WriteBuffer:
+	case WRITE_BUFFER:
 		cmdLen = 10;
 		dir = MPI_SCSIIO_CONTROL_WRITE;
 		CDB[0] = cmd;
@@ -5261,21 +4448,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 +4518,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 +4626,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 +4696,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);
@@ -5597,8 +4787,7 @@
 			}
 			spin_unlock_irqrestore(&dvtaskQ_lock, flags);
 
-			set_current_state(TASK_INTERRUPTIBLE);
-			schedule_timeout(HZ/4);
+			msleep(250);
 
 			/* DV only to SCSI adapters */
 			if ((int)ioc->chip_type <= (int)FC929)
@@ -5646,8 +4835,7 @@
 					hd->ioc->spi_data.dvStatus[id] |= MPT_SCSICFG_DV_PENDING;
 					hd->ioc->spi_data.dvStatus[id] &= ~MPT_SCSICFG_NEED_DV;
 
-					set_current_state(TASK_INTERRUPTIBLE);
-					schedule_timeout(HZ/4);
+					msleep(250);
 
 					/* If hidden phys disk, block IO's to all
 					 *	raid volumes
@@ -5681,11 +4869,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 +4924,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 +5010,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 +5024,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 +5035,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 +5134,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 +5176,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 +5201,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 +5221,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 +5233,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 +5263,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 +5297,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 +5316,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 +5373,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 +5401,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 +5428,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 +5451,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 +5472,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 +5520,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 +5579,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 +5608,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 +5631,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 +5650,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 +5691,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 +5712,7 @@
 			}
 		}
 
-		iocmd.cmd = CMD_ReadBuffer;
+		iocmd.cmd = READ_BUFFER;
 		iocmd.data_dma = buf2_dma;
 		iocmd.data = pbuf2;
 		iocmd.size = sz;
@@ -6581,7 +5787,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 +5803,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 +5825,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 +5858,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 +5939,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 +5958,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 +5975,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 +6000,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 +6067,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 +6078,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-10-18 14:56:29 -07: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	2004-10-18 14:55:54 -07: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-10-18 14:56:48 -07:00
+++ b/drivers/message/i2o/Makefile	2004-10-18 14:56:48 -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-10-18 14:57:23 -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-10-18 14:57:23 -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-10-18 14:57:24 -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-10-18 14:57:23 -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-10-18 14:56:48 -07:00
+++ b/drivers/message/i2o/i2o_block.c	2004-10-18 14:56:48 -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-10-18 14:57:24 -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-10-18 14:57:03 -07:00
+++ b/drivers/message/i2o/i2o_config.c	2004-10-18 14:57:03 -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(swlen, kxfer.swlen) < 0)
 		return -EFAULT;
-	}
 
-	if(get_user(reslen, kcmd.reslen) < 0)
-	{
-		printk(KERN_INFO "i2o_config: can't copy html reslen\n");
+	if (get_user(maxfrag, kxfer.maxfrag) < 0)
 		return -EFAULT;
-	}
 
-	if(!kcmd.resbuf)		
-	{
-		printk(KERN_INFO "i2o_config: NULL html buffer\n");
+	if (get_user(curfrag, kxfer.curfrag) < 0)
 		return -EFAULT;
-	}
 
-	c = i2o_find_controller(kcmd.iop);
-	if(!c)
+	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;
 
-        return 0;
-}   
+	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_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)
+#ifdef CONFIG_COMPAT
+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 *user_msg;
+	u32 *reply = NULL;
+	u32 __user *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 __user *)(unsigned long)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;
+
+#ifndef CONFIG_COMPAT
+	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;
+#ifdef CONFIG_COMPAT
+	register_ioctl32_conversion(I2OPASSTHRU32, i2o_cfg_passthru32);
+	register_ioctl32_conversion(I2OGETIOPS, (void *)sys_ioctl);
+#endif
 	return 0;
 }
 
 static void i2o_config_exit(void)
 {
+#ifdef CONFIG_COMPAT
+	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_core.c b/drivers/message/i2o/i2o_core.c
--- a/drivers/message/i2o/i2o_core.c	2004-10-18 14:56:33 -07:00
+++ /dev/null	Wed Dec 31 16:00:00 196900
@@ -1,3978 +0,0 @@
-/*
- * Core I2O structure management 
- * 
- * (C) Copyright 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/config.h>
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/pci.h>
-
-#include <linux/i2o.h>
-
-#include <linux/errno.h>
-#include <linux/init.h>
-#include <linux/slab.h>
-#include <linux/spinlock.h>
-#include <linux/smp_lock.h>
-
-#include <linux/bitops.h>
-#include <linux/wait.h>
-#include <linux/delay.h>
-#include <linux/timer.h>
-#include <linux/interrupt.h>
-#include <linux/sched.h>
-#include <asm/semaphore.h>
-#include <linux/completion.h>
-#include <linux/workqueue.h>
-
-#include <asm/io.h>
-#include <linux/reboot.h>
-#ifdef CONFIG_MTRR
-#include <asm/mtrr.h>
-#endif // CONFIG_MTRR
-
-#include "i2o_lan.h"
-
-//#define DRIVERDEBUG
-
-#ifdef DRIVERDEBUG
-#define dprintk(s, args...) printk(s, ## args)
-#else
-#define dprintk(s, args...)
-#endif
-
-/* OSM table */
-static struct i2o_handler *i2o_handlers[MAX_I2O_MODULES];
-
-/* Controller list */
-static struct i2o_controller *i2o_controllers[MAX_I2O_CONTROLLERS];
-struct i2o_controller *i2o_controller_chain;
-int i2o_num_controllers;
-
-/* Initiator Context for Core message */
-static int core_context;
-
-/* Initialization && shutdown functions */
-void i2o_sys_init(void);
-static void i2o_sys_shutdown(void);
-static int i2o_reset_controller(struct i2o_controller *);
-static int i2o_reboot_event(struct notifier_block *, unsigned long , void *);
-static int i2o_online_controller(struct i2o_controller *);
-static int i2o_init_outbound_q(struct i2o_controller *);
-static int i2o_post_outbound_messages(struct i2o_controller *);
-
-/* Reply handler */
-static void i2o_core_reply(struct i2o_handler *, struct i2o_controller *,
-			   struct i2o_message *);
-
-/* Various helper functions */
-static int i2o_lct_get(struct i2o_controller *);
-static int i2o_lct_notify(struct i2o_controller *);
-static int i2o_hrt_get(struct i2o_controller *);
-
-static int i2o_build_sys_table(void);
-static int i2o_systab_send(struct i2o_controller *c);
-
-/* I2O core event handler */
-static int i2o_core_evt(void *);
-static int evt_pid;
-static int evt_running;
-
-/* Dynamic LCT update handler */
-static int i2o_dyn_lct(void *);
-
-void i2o_report_controller_unit(struct i2o_controller *, struct i2o_device *);
-
-static void i2o_pci_dispose(struct i2o_controller *c);
-
-/*
- * I2O System Table.  Contains information about
- * all the IOPs in the system.  Used to inform IOPs
- * about each other's existence.
- *
- * sys_tbl_ver is the CurrentChangeIndicator that is
- * used by IOPs to track changes.
- */
-static struct i2o_sys_tbl *sys_tbl;
-static int sys_tbl_ind;
-static int sys_tbl_len;
-
-/*
- * This spin lock is used to keep a device from being
- * added and deleted concurrently across CPUs or interrupts.
- * This can occur when a user creates a device and immediatelly
- * deletes it before the new_dev_notify() handler is called.
- */
-static spinlock_t i2o_dev_lock = SPIN_LOCK_UNLOCKED;
-
-/*
- * Structures and definitions for synchronous message posting.
- * See i2o_post_wait() for description.
- */ 
-struct i2o_post_wait_data
-{
-	int *status;		/* Pointer to status block on caller stack */
-	int *complete;		/* Pointer to completion flag on caller stack */
-	u32 id;			/* Unique identifier */
-	wait_queue_head_t *wq;	/* Wake up for caller (NULL for dead) */
-	struct i2o_post_wait_data *next;	/* Chain */
-	void *mem[2];		/* Memory blocks to recover on failure path */
-	dma_addr_t phys[2];	/* Physical address of blocks to recover */
-	u32 size[2];		/* Size of blocks to recover */
-};
-
-static struct i2o_post_wait_data *post_wait_queue;
-static u32 post_wait_id;	// Unique ID for each post_wait
-static spinlock_t post_wait_lock = SPIN_LOCK_UNLOCKED;
-static void i2o_post_wait_complete(struct i2o_controller *, u32, int);
-
-/* OSM descriptor handler */ 
-static struct i2o_handler i2o_core_handler =
-{
-	(void *)i2o_core_reply,
-	NULL,
-	NULL,
-	NULL,
-	"I2O core layer",
-	0,
-	I2O_CLASS_EXECUTIVE
-};
-
-/*
- * Used when queueing a reply to be handled later
- */
- 
-struct reply_info
-{
-	struct i2o_controller *iop;
-	u32 msg[MSG_FRAME_SIZE];
-};
-static struct reply_info evt_reply;
-static struct reply_info events[I2O_EVT_Q_LEN];
-static int evt_in;
-static int evt_out;
-static int evt_q_len;
-#define MODINC(x,y) ((x) = ((x) + 1) % (y))
-
-/*
- * I2O configuration spinlock. This isnt a big deal for contention
- * so we have one only
- */
-
-static DECLARE_MUTEX(i2o_configuration_lock);
-
-/* 
- * Event spinlock.  Used to keep event queue sane and from
- * handling multiple events simultaneously.
- */
-static spinlock_t i2o_evt_lock = SPIN_LOCK_UNLOCKED;
-
-/*
- * Semaphore used to synchronize event handling thread with 
- * interrupt handler.
- */
- 
-static DECLARE_MUTEX(evt_sem);
-static DECLARE_COMPLETION(evt_dead);
-static DECLARE_WAIT_QUEUE_HEAD(evt_wait);
-
-static struct notifier_block i2o_reboot_notifier =
-{
-        i2o_reboot_event,
-        NULL,
-        0
-};
-
-/*
- *	Config options
- */
-
-static int verbose;
-
-#if BITS_PER_LONG == 64
-/**
- *      i2o_context_list_add -	append an ptr to the context list and return a
- *				matching context id.
- *	@ptr: pointer to add to the context list
- *	@c: controller to which the context list belong
- *	returns context id, which could be used in the transaction context
- *	field.
- *
- *	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_context_list
- *	functiones map pointers to context fields.
- */
-u32 i2o_context_list_add(void *ptr, struct i2o_controller *c) {
-	u32 context = 1;
-	struct i2o_context_list_element **entry = &c->context_list;
-	struct i2o_context_list_element *element;
-	unsigned long flags;
-
-	spin_lock_irqsave(&c->context_list_lock, flags);
-	while(*entry && ((*entry)->flags & I2O_CONTEXT_LIST_USED)) {
-		if((*entry)->context >= context)
-			context = (*entry)->context + 1;
-		entry = &((*entry)->next);
-	}
-
-	if(!*entry) {
-		if(unlikely(!context)) {
-			spin_unlock_irqrestore(&c->context_list_lock, flags);
-			printk(KERN_EMERG "i2o_core: context list overflow\n");
-			return 0;
-		}
-
-		element = kmalloc(sizeof(struct i2o_context_list_element), GFP_KERNEL);
-		if(!element) {
-			printk(KERN_EMERG "i2o_core: could not allocate memory for context list element\n");
-			return 0;
-		}
-		element->context = context;
-		element->next = NULL;
-		*entry = element;
-	} else
-		element = *entry;
-
-	element->ptr = ptr;
-	element->flags = I2O_CONTEXT_LIST_USED;
-
-	spin_unlock_irqrestore(&c->context_list_lock, flags);
-	dprintk(KERN_DEBUG "i2o_core: add context to list %p -> %d\n", ptr, context);
-	return context;
-}
-
-/**
- *      i2o_context_list_remove - remove a ptr from the context list and return
- *				  the matching context id.
- *	@ptr: pointer to be removed from the context list
- *	@c: controller to which the context list belong
- *	returns context id, which could be used in the transaction context
- *	field.
- */
-u32 i2o_context_list_remove(void *ptr, struct i2o_controller *c) {
-	struct i2o_context_list_element **entry = &c->context_list;
-	struct i2o_context_list_element *element;
-	u32 context;
-	unsigned long flags;
-
-	spin_lock_irqsave(&c->context_list_lock, flags);
-	while(*entry && ((*entry)->ptr != ptr))
-		entry = &((*entry)->next);
-
-	if(unlikely(!*entry)) {
-		spin_unlock_irqrestore(&c->context_list_lock, flags);
-		printk(KERN_WARNING "i2o_core: could not remove nonexistent ptr %p\n", ptr);
-		return 0;
-	}
-
-	element = *entry;
-
-	context = element->context;
-	element->ptr = NULL;
-	element->flags |= I2O_CONTEXT_LIST_DELETED;
-
-	spin_unlock_irqrestore(&c->context_list_lock, flags);
-	dprintk(KERN_DEBUG "i2o_core: markt as deleted in context list %p -> %d\n", ptr, context);
-	return context;
-}
-
-/**
- *      i2o_context_list_get -	get a ptr from the context list and remove it
- *				from the list.
- *	@context: context id to which the pointer belong
- *	@c: controller to which the context list belong
- *	returns pointer to the matching context id
- */
-void *i2o_context_list_get(u32 context, struct i2o_controller *c) {
-	struct i2o_context_list_element **entry = &c->context_list;
-	struct i2o_context_list_element *element;
-	void *ptr;
-	int count = 0;
-	unsigned long flags;
-
-	spin_lock_irqsave(&c->context_list_lock, flags);
-	while(*entry && ((*entry)->context != context)) {
-		entry = &((*entry)->next);
-		count ++;
-	}
-
-	if(unlikely(!*entry)) {
-		spin_unlock_irqrestore(&c->context_list_lock, flags);
-		printk(KERN_WARNING "i2o_core: context id %d not found\n", context);
-		return NULL;
-	}
-
-	element = *entry;
-	ptr = element->ptr;
-	if(count >= I2O_CONTEXT_LIST_MIN_LENGTH) {
-		*entry = (*entry)->next;
-		kfree(element);
-	} else {
-		element->ptr = NULL;
-		element->flags &= !I2O_CONTEXT_LIST_USED;
-	}
-
-	spin_unlock_irqrestore(&c->context_list_lock, flags);
-	dprintk(KERN_DEBUG "i2o_core: get ptr from context list %d -> %p\n", context, ptr);
-	return ptr;
-}
-#endif
-
-/*
- * I2O Core reply handler
- */
-static void i2o_core_reply(struct i2o_handler *h, struct i2o_controller *c,
-		    struct i2o_message *m)
-{
-	u32 *msg=(u32 *)m;
-	u32 status;
-	u32 context = msg[2];
-
-	if (msg[0] & MSG_FAIL) // Fail bit is set
-	{
-		u32 *preserved_msg = (u32*)(c->msg_virt + msg[7]);
-
-		i2o_report_status(KERN_INFO, "i2o_core", msg);
-		i2o_dump_message(preserved_msg);
-
-		/* If the failed request needs special treatment,
-		 * it should be done here. */
-
-                /* Release the preserved msg by resubmitting it as a NOP */
-
-		preserved_msg[0] = cpu_to_le32(THREE_WORD_MSG_SIZE | SGL_OFFSET_0);
-		preserved_msg[1] = cpu_to_le32(I2O_CMD_UTIL_NOP << 24 | HOST_TID << 12 | 0);
-		preserved_msg[2] = 0;
-		i2o_post_message(c, msg[7]);
-
-		/* If reply to i2o_post_wait failed, return causes a timeout */
-
-		return;
-	}       
-
-#ifdef DRIVERDEBUG
-	i2o_report_status(KERN_INFO, "i2o_core", msg);
-#endif
-
-	if(msg[2]&0x80000000)	// Post wait message
-	{
-		if (msg[4] >> 24)
-			status = (msg[4] & 0xFFFF);
-		else
-			status = I2O_POST_WAIT_OK;
-	
-		i2o_post_wait_complete(c, context, status);
-		return;
-	}
-
-	if(m->function == I2O_CMD_UTIL_EVT_REGISTER)
-	{
-		memcpy(events[evt_in].msg, msg, (msg[0]>>16)<<2);
-		events[evt_in].iop = c;
-
-		spin_lock(&i2o_evt_lock);
-		MODINC(evt_in, I2O_EVT_Q_LEN);
-		if(evt_q_len == I2O_EVT_Q_LEN)
-			MODINC(evt_out, I2O_EVT_Q_LEN);
-		else
-			evt_q_len++;
-		spin_unlock(&i2o_evt_lock);
-
-		up(&evt_sem);
-		wake_up_interruptible(&evt_wait);
-		return;
-	}
-
-	if(m->function == I2O_CMD_LCT_NOTIFY)
-	{
-		up(&c->lct_sem);
-		return;
-	}
-
-	/*
-	 * 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;
-}
-
-/**
- *	i2o_install_handler - install a message handler
- *	@h: Handler structure
- *
- *	Install an I2O handler - these handle the asynchronous messaging
- *	from the card once it has initialised. If the table of handlers is
- *	full then -ENOSPC is returned. On a success 0 is returned and the
- *	context field is set by the function. The structure is part of the
- *	system from this time onwards. It must not be freed until it has
- *	been uninstalled
- */
- 
-int i2o_install_handler(struct i2o_handler *h)
-{
-	int i;
-	down(&i2o_configuration_lock);
-	for(i=0;i<MAX_I2O_MODULES;i++)
-	{
-		if(i2o_handlers[i]==NULL)
-		{
-			h->context = i;
-			i2o_handlers[i]=h;
-			up(&i2o_configuration_lock);
-			return 0;
-		}
-	}
-	up(&i2o_configuration_lock);
-	return -ENOSPC;
-}
-
-/**
- *	i2o_remove_handler - remove an i2o message handler
- *	@h: handler
- *
- *	Remove a message handler previously installed with i2o_install_handler.
- *	After this function returns the handler object can be freed or re-used
- */
- 
-int i2o_remove_handler(struct i2o_handler *h)
-{
-	i2o_handlers[h->context]=NULL;
-	return 0;
-}
-	
-
-/*
- *	Each I2O controller has a chain of devices on it.
- * Each device has a pointer to its LCT entry to be used
- * for fun purposes.
- */
-
-/**
- *	i2o_install_device	-	attach a device to a controller
- *	@c: controller
- *	@d: device
- * 	
- *	Add a new device to an i2o controller. This can be called from
- *	non interrupt contexts only. It adds the device and marks it as
- *	unclaimed. The device memory becomes part of the kernel and must
- *	be uninstalled before being freed or reused. Zero is returned
- *	on success.
- */
- 
-int i2o_install_device(struct i2o_controller *c, struct i2o_device *d)
-{
-	int i;
-
-	down(&i2o_configuration_lock);
-	d->controller=c;
-	d->owner=NULL;
-	d->next=c->devices;
-	d->prev=NULL;
-	if (c->devices != NULL)
-		c->devices->prev=d;
-	c->devices=d;
-	*d->dev_name = 0;
-
-	for(i = 0; i < I2O_MAX_MANAGERS; i++)
-		d->managers[i] = NULL;
-
-	up(&i2o_configuration_lock);
-	return 0;
-}
-
-/* we need this version to call out of i2o_delete_controller */
-
-int __i2o_delete_device(struct i2o_device *d)
-{
-	struct i2o_device **p;
-	int i;
-
-	p=&(d->controller->devices);
-
-	/*
-	 *	Hey we have a driver!
-	 * Check to see if the driver wants us to notify it of 
-	 * device deletion. If it doesn't we assume that it
-	 * is unsafe to delete a device with an owner and 
-	 * fail.
-	 */
-	if(d->owner)
-	{
-		if(d->owner->dev_del_notify)
-		{
-			dprintk(KERN_INFO "Device has owner, notifying\n");
-			d->owner->dev_del_notify(d->controller, d);
-			if(d->owner)
-			{
-				printk(KERN_WARNING 
-					"Driver \"%s\" did not release device!\n", d->owner->name);
-				return -EBUSY;
-			}
-		}
-		else
-			return -EBUSY;
-	}
-
-	/*
-	 * Tell any other users who are talking to this device
-	 * that it's going away.  We assume that everything works.
-	 */
-	for(i=0; i < I2O_MAX_MANAGERS; i++)
-	{
-		if(d->managers[i] && d->managers[i]->dev_del_notify)
-			d->managers[i]->dev_del_notify(d->controller, d);
-	}
-	 			
-	while(*p!=NULL)
-	{
-		if(*p==d)
-		{
-			/*
-			 *	Destroy
-			 */
-			*p=d->next;
-			kfree(d);
-			return 0;
-		}
-		p=&((*p)->next);
-	}
-	printk(KERN_ERR "i2o_delete_device: passed invalid device.\n");
-	return -EINVAL;
-}
-
-/**
- *	i2o_delete_device	-	remove an i2o device
- *	@d: device to remove
- *
- *	This function unhooks a device from a controller. The device
- *	will not be unhooked if it has an owner who does not wish to free
- *	it, or if the owner lacks a dev_del_notify function. In that case
- *	-EBUSY is returned. On success 0 is returned. Other errors cause
- *	negative errno values to be returned
- */
- 
-int i2o_delete_device(struct i2o_device *d)
-{
-	int ret;
-
-	down(&i2o_configuration_lock);
-
-	/*
-	 *	Seek, locate
-	 */
-
-	ret = __i2o_delete_device(d);
-
-	up(&i2o_configuration_lock);
-
-	return ret;
-}
-
-/**
- *	i2o_install_controller	-	attach a controller
- *	@c: controller
- * 	
- *	Add a new controller to the i2o layer. This can be called from
- *	non interrupt contexts only. It adds the controller and marks it as
- *	unused with no devices. If the tables are full or memory allocations
- *	fail then a negative errno code is returned. On success zero is
- *	returned and the controller is bound to the system. The structure
- *	must not be freed or reused until being uninstalled.
- */
- 
-int i2o_install_controller(struct i2o_controller *c)
-{
-	int i;
-	down(&i2o_configuration_lock);
-	for(i=0;i<MAX_I2O_CONTROLLERS;i++)
-	{
-		if(i2o_controllers[i]==NULL)
-		{
-			c->dlct = (i2o_lct*)pci_alloc_consistent(c->pdev, 8192, &c->dlct_phys);
-			if(c->dlct==NULL)
-			{
-				up(&i2o_configuration_lock);
-				return -ENOMEM;
-			}
-			i2o_controllers[i]=c;
-			c->devices = NULL;
-			c->next=i2o_controller_chain;
-			i2o_controller_chain=c;
-			c->unit = i;
-			c->page_frame = NULL;
-			c->hrt = NULL;
-			c->hrt_len = 0;
-			c->lct = NULL;
-			c->status_block = NULL;
-			sprintf(c->name, "i2o/iop%d", i);
-			i2o_num_controllers++;
-			init_MUTEX_LOCKED(&c->lct_sem);
-			up(&i2o_configuration_lock);
-			return 0;
-		}
-	}
-	printk(KERN_ERR "No free i2o controller slots.\n");
-	up(&i2o_configuration_lock);
-	return -EBUSY;
-}
-
-/**
- *	i2o_delete_controller	- delete a controller
- *	@c: controller
- *	
- *	Remove an i2o controller from the system. If the controller or its
- *	devices are busy then -EBUSY is returned. On a failure a negative
- *	errno code is returned. On success zero is returned.
- */
-  
-int i2o_delete_controller(struct i2o_controller *c)
-{
-	struct i2o_controller **p;
-	int users;
-	char name[16];
-	int stat;
-
-	dprintk(KERN_INFO "Deleting controller %s\n", c->name);
-
-	/*
-	 * Clear event registration as this can cause weird behavior
-	 */
-	if(c->status_block->iop_state == ADAPTER_STATE_OPERATIONAL)
-		i2o_event_register(c, core_context, 0, 0, 0);
-
-	down(&i2o_configuration_lock);
-	if((users=atomic_read(&c->users)))
-	{
-		dprintk(KERN_INFO "I2O: %d users for controller %s\n", users,
-			c->name);
-		up(&i2o_configuration_lock);
-		return -EBUSY;
-	}
-	while(c->devices)
-	{
-		if(__i2o_delete_device(c->devices)<0)
-		{
-			/* Shouldnt happen */
-			I2O_IRQ_WRITE32(c, 0xFFFFFFFF);
-			c->enabled = 0;
-			up(&i2o_configuration_lock);
-			return -EBUSY;
-		}
-	}
-
-	/*
-	 * If this is shutdown time, the thread's already been killed
-	 */
-	if(c->lct_running) {
-		stat = kill_proc(c->lct_pid, SIGKILL, 1);
-		if(!stat) {
-			int count = 10 * 100;
-			while(c->lct_running && --count) {
-				current->state = TASK_INTERRUPTIBLE;
-				schedule_timeout(1);
-			}
-		
-			if(!count)
-				printk(KERN_ERR 
-					"%s: LCT thread still running!\n", 
-					c->name);
-		}
-	}
-
-	p=&i2o_controller_chain;
-
-	while(*p)
-	{
-		if(*p==c)
-		{
- 			/* Ask the IOP to switch to RESET state */
-			i2o_reset_controller(c);
-
-			/* Release IRQ */
-			i2o_pci_dispose(c);
-
-			*p=c->next;
-			up(&i2o_configuration_lock);
-
-			if(c->page_frame)
-			{
-				pci_unmap_single(c->pdev, c->page_frame_map, MSG_POOL_SIZE, PCI_DMA_FROMDEVICE);
-				kfree(c->page_frame);
-			}
-			if(c->hrt)
-				pci_free_consistent(c->pdev, c->hrt_len, c->hrt, c->hrt_phys);
-			if(c->lct)
-				pci_free_consistent(c->pdev, c->lct->table_size << 2, c->lct, c->lct_phys);
-			if(c->status_block)
-				pci_free_consistent(c->pdev, sizeof(i2o_status_block), c->status_block, c->status_block_phys);
-			if(c->dlct)
-				pci_free_consistent(c->pdev, 8192, c->dlct, c->dlct_phys);
-
-			i2o_controllers[c->unit]=NULL;
-			memcpy(name, c->name, strlen(c->name)+1);
-			kfree(c);
-			dprintk(KERN_INFO "%s: Deleted from controller chain.\n", name);
-			
-			i2o_num_controllers--;
-			return 0;
-		}
-		p=&((*p)->next);
-	}
-	up(&i2o_configuration_lock);
-	printk(KERN_ERR "i2o_delete_controller: bad pointer!\n");
-	return -ENOENT;
-}
-
-/**
- *	i2o_unlock_controller	-	unlock a controller
- *	@c: controller to unlock
- *
- *	Take a lock on an i2o controller. This prevents it being deleted.
- *	i2o controllers are not refcounted so a deletion of an in use device
- *	will fail, not take affect on the last dereference.
- */
- 
-void i2o_unlock_controller(struct i2o_controller *c)
-{
-	atomic_dec(&c->users);
-}
-
-/**
- *	i2o_find_controller - return a locked controller
- *	@n: controller number
- *
- *	Returns a pointer to the controller object. The controller is locked
- *	on return. NULL is returned if the controller is not found.
- */
- 
-struct i2o_controller *i2o_find_controller(int n)
-{
-	struct i2o_controller *c;
-	
-	if(n<0 || n>=MAX_I2O_CONTROLLERS)
-		return NULL;
-	
-	down(&i2o_configuration_lock);
-	c=i2o_controllers[n];
-	if(c!=NULL)
-		atomic_inc(&c->users);
-	up(&i2o_configuration_lock);
-	return c;
-}
-
-/**
- *	i2o_issue_claim	- claim or release a device
- *	@cmd: command
- *	@c: controller to claim for
- *	@tid: i2o task id
- *	@type: type of claim
- *
- *	Issue I2O UTIL_CLAIM and UTIL_RELEASE messages. The message to be sent
- *	is set by cmd. The tid is the task id of the object to claim and the
- *	type is the claim type (see the i2o standard)
- *
- *	Zero is returned on success.
- */
- 
-static int i2o_issue_claim(u32 cmd, struct i2o_controller *c, int tid, u32 type)
-{
-	u32 msg[5];
-
-	msg[0] = FIVE_WORD_MSG_SIZE | SGL_OFFSET_0;
-	msg[1] = cmd << 24 | HOST_TID<<12 | tid;
-	msg[3] = 0;
-	msg[4] = type;
-	
-	return i2o_post_wait(c, msg, sizeof(msg), 60);
-}
-
-/*
- * 	i2o_claim_device - claim a device for use by an OSM
- *	@d: device to claim
- *	@h: handler for this device
- *
- *	Do the leg work to assign a device to a given OSM on Linux. The
- *	kernel updates the internal handler data for the device and then
- *	performs an I2O claim for the device, attempting to claim the
- *	device as primary. If the attempt fails a negative errno code
- *	is returned. On success zero is returned.
- */
- 
-int i2o_claim_device(struct i2o_device *d, struct i2o_handler *h)
-{
-	int ret = 0;
-
-	down(&i2o_configuration_lock);
-	if (d->owner) {
-		printk(KERN_INFO "Device claim called, but dev already owned by %s!",
-		       h->name);
-		ret = -EBUSY;
-		goto out;
-	}
-	d->owner=h;
-
-	if(i2o_issue_claim(I2O_CMD_UTIL_CLAIM ,d->controller,d->lct_data.tid, 
-			   I2O_CLAIM_PRIMARY))
-	{
-		d->owner = NULL;
-		ret = -EBUSY;
-	}
-out:
-	up(&i2o_configuration_lock);
-	return ret;
-}
-
-/**
- *	i2o_release_device - release a device that the OSM is using
- *	@d: device to claim
- *	@h: handler for this device
- *
- *	Drop a claim by an OSM on a given I2O device. The handler is cleared
- *	and 0 is returned on success.
- *
- *	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.
- */
-
-int i2o_release_device(struct i2o_device *d, struct i2o_handler *h)
-{
-	int err = 0;
-	int tries;
-
-	down(&i2o_configuration_lock);
-	if (d->owner != h) {
-		printk(KERN_INFO "Claim release called, but not owned by %s!\n",
-		       h->name);
-		up(&i2o_configuration_lock);
-		return -ENOENT;
-	}	
-
-	for(tries=0;tries<10;tries++)
-	{
-		d->owner = NULL;
-
-		/*
-		 *	If the controller takes a nonblocking approach to
-		 *	releases we have to sleep/poll for a few times.
-		 */
-		 
-		if((err=i2o_issue_claim(I2O_CMD_UTIL_RELEASE, d->controller, d->lct_data.tid, I2O_CLAIM_PRIMARY)) )
-		{
-			err = -ENXIO;
-			current->state = TASK_UNINTERRUPTIBLE;
-			schedule_timeout(HZ);
-		}
-		else
-		{
-			err=0;
-			break;
-		}
-	}
-	up(&i2o_configuration_lock);
-	return err;
-}
-
-/**
- * 	i2o_device_notify_on	-	Enable deletion notifiers
- *	@d: device for notification
- *	@h: handler to install
- *
- *	Called by OSMs to let the core know that they want to be
- *	notified if the given device is deleted from the system.
- */
-
-int i2o_device_notify_on(struct i2o_device *d, struct i2o_handler *h)
-{
-	int i;
-
-	if(d->num_managers == I2O_MAX_MANAGERS)
-		return -ENOSPC;
-
-	for(i = 0; i < I2O_MAX_MANAGERS; i++)
-	{
-		if(!d->managers[i])
-		{
-			d->managers[i] = h;
-			break;
-		}
-	}
-	
-	d->num_managers++;
-	
-	return 0;
-}
-
-/**
- * 	i2o_device_notify_off	-	Remove deletion notifiers
- *	@d: device for notification
- *	@h: handler to remove
- *
- * Called by OSMs to let the core know that they no longer
- * are interested in the fate of the given device.
- */
-int i2o_device_notify_off(struct i2o_device *d, struct i2o_handler *h)
-{
-	int i;
-
-	for(i=0; i < I2O_MAX_MANAGERS; i++)
-	{
-		if(d->managers[i] == h)
-		{
-			d->managers[i] = NULL;
-			d->num_managers--;
-			return 0;
-		}
-	}
-
-	return -ENOENT;
-}
-
-/**
- *	i2o_event_register	-	register interest in an event
- * 	@c: Controller to register interest with
- *	@tid: I2O task id
- *	@init_context: initiator context to use with this notifier
- *	@tr_context: 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. Errors in posting will be reported.
- */
- 
-int i2o_event_register(struct i2o_controller *c, u32 tid, 
-		u32 init_context, u32 tr_context, u32 evt_mask)
-{
-	u32 msg[5];	// Not performance critical, so we just 
-			// i2o_post_this it instead of building it
-			// in IOP memory
-	
-	msg[0] = FIVE_WORD_MSG_SIZE|SGL_OFFSET_0;
-	msg[1] = I2O_CMD_UTIL_EVT_REGISTER<<24 | HOST_TID<<12 | tid;
-	msg[2] = init_context;
-	msg[3] = tr_context;
-	msg[4] = evt_mask;
-
-	return i2o_post_this(c, msg, sizeof(msg));
-}
-
-/*
- * 	i2o_event_ack	-	acknowledge an event
- *	@c: controller 
- *	@msg: pointer to the UTIL_EVENT_REGISTER reply we received
- *
- *	We just take a pointer to the original UTIL_EVENT_REGISTER reply
- *	message and change the function code since that's what spec
- *	describes an EventAck message looking like.
- */
- 
-int i2o_event_ack(struct i2o_controller *c, u32 *msg)
-{
-	struct i2o_message *m = (struct i2o_message *)msg;
-
-	m->function = I2O_CMD_UTIL_EVT_ACK;
-
-	return i2o_post_wait(c, msg, m->size * 4, 2);
-}
-
-/*
- * Core event handler.  Runs as a separate thread and is woken
- * up whenever there is an Executive class event.
- */
-static int i2o_core_evt(void *reply_data)
-{
-	struct reply_info *reply = (struct reply_info *) reply_data;
-	u32 *msg = reply->msg;
-	struct i2o_controller *c = NULL;
-	unsigned long flags;
-
-	daemonize("i2oevtd");
-	allow_signal(SIGKILL);
-
-	evt_running = 1;
-
-	while(1)
-	{
-		if(down_interruptible(&evt_sem))
-		{
-			dprintk(KERN_INFO "I2O event thread dead\n");
-			printk("exiting...");
-			evt_running = 0;
-			complete_and_exit(&evt_dead, 0);
-		}
-
-		/* 
-		 * Copy the data out of the queue so that we don't have to lock
-		 * around the whole function and just around the qlen update
-		 */
-		spin_lock_irqsave(&i2o_evt_lock, flags);
-		memcpy(reply, &events[evt_out], sizeof(struct reply_info));
-		MODINC(evt_out, I2O_EVT_Q_LEN);
-		evt_q_len--;
-		spin_unlock_irqrestore(&i2o_evt_lock, flags);
-	
-		c = reply->iop;
-	 	dprintk(KERN_INFO "I2O IRTOS EVENT: iop%d, event %#10x\n", c->unit, msg[4]);
-
-		/* 
-		 * We do not attempt to delete/quiesce/etc. the controller if
-		 * some sort of error indidication occurs.  We may want to do
-		 * so in the future, but for now we just let the user deal with 
-		 * it.  One reason for this is that what to do with an error
-		 * or when to send what ćrror is not really agreed on, so
-		 * we get errors that may not be fatal but just look like they
-		 * are...so let the user deal with it.
-		 */
-		switch(msg[4])
-		{
-			case I2O_EVT_IND_EXEC_RESOURCE_LIMITS:
-				printk(KERN_ERR "%s: Out of resources\n", c->name);
-				break;
-
-			case I2O_EVT_IND_EXEC_POWER_FAIL:
-				printk(KERN_ERR "%s: Power failure\n", c->name);
-				break;
-
-			case I2O_EVT_IND_EXEC_HW_FAIL:
-			{
-				char *fail[] = 
-					{ 
-						"Unknown Error",
-						"Power Lost",
-						"Code Violation",
-						"Parity Error",
-						"Code Execution Exception",
-						"Watchdog Timer Expired" 
-					};
-
-				if(msg[5] <= 6)
-					printk(KERN_ERR "%s: Hardware Failure: %s\n", 
-						c->name, fail[msg[5]]);
-				else
-					printk(KERN_ERR "%s: Unknown Hardware Failure\n", c->name);
-
-				break;
-			}
-
-			/*
-		 	 * New device created
-		 	 * - Create a new i2o_device entry
-		 	 * - Inform all interested drivers about this device's existence
-		 	 */
-			case I2O_EVT_IND_EXEC_NEW_LCT_ENTRY:
-			{
-				struct i2o_device *d = (struct i2o_device *)
-					kmalloc(sizeof(struct i2o_device), GFP_KERNEL);
-				int i;
-
-				if (d == NULL) {
-					printk(KERN_EMERG "i2oevtd: out of memory\n");
-					break;
-				}
-				memcpy(&d->lct_data, &msg[5], sizeof(i2o_lct_entry));
-	
-				d->next = NULL;
-				d->controller = c;
-				d->flags = 0;
-	
-				i2o_report_controller_unit(c, d);
-				i2o_install_device(c,d);
-	
-				for(i = 0; i < MAX_I2O_MODULES; i++)
-				{
-					if(i2o_handlers[i] && 
-						i2o_handlers[i]->new_dev_notify &&
-						(i2o_handlers[i]->class&d->lct_data.class_id))
-						{
-						spin_lock(&i2o_dev_lock);
-						i2o_handlers[i]->new_dev_notify(c,d);
-						spin_unlock(&i2o_dev_lock);
-						}
-				}
-			
-				break;
-			}
-	
-			/*
- 		 	 * LCT entry for a device has been modified, so update it
-		 	 * internally.
-		 	 */
-			case I2O_EVT_IND_EXEC_MODIFIED_LCT:
-			{
-				struct i2o_device *d;
-				i2o_lct_entry *new_lct = (i2o_lct_entry *)&msg[5];
-
-				for(d = c->devices; d; d = d->next)
-				{
-					if(d->lct_data.tid == new_lct->tid)
-					{
-						memcpy(&d->lct_data, new_lct, sizeof(i2o_lct_entry));
-						break;
-					}
-				}
-				break;
-			}
-	
-			case I2O_EVT_IND_CONFIGURATION_FLAG:
-				printk(KERN_WARNING "%s requires user configuration\n", c->name);
-				break;
-	
-			case I2O_EVT_IND_GENERAL_WARNING:
-				printk(KERN_WARNING "%s: Warning notification received!"
-					"Check configuration for errors!\n", c->name);
-				break;
-				
-			case I2O_EVT_IND_EVT_MASK_MODIFIED:
-				/* Well I guess that was us hey .. */
-				break;
-					
-			default:
-				printk(KERN_WARNING "%s: No handler for event (0x%08x)\n", c->name, msg[4]);
-				break;
-		}
-	}
-
-	return 0;
-}
-
-/*
- * Dynamic LCT update.  This compares the LCT with the currently
- * installed devices to check for device deletions..this needed b/c there
- * is no DELETED_LCT_ENTRY EventIndicator for the Executive class so
- * we can't just have the event handler do this...annoying
- *
- * This is a hole in the spec that will hopefully be fixed someday.
- */
-static int i2o_dyn_lct(void *foo)
-{
-	struct i2o_controller *c = (struct i2o_controller *)foo;
-	struct i2o_device *d = NULL;
-	struct i2o_device *d1 = NULL;
-	int i = 0;
-	int found = 0;
-	int entries;
-	void *tmp;
-
-	daemonize("iop%d_lctd", c->unit);
-	allow_signal(SIGKILL);
-
-	c->lct_running = 1;
-
-	while(1)
-	{
-		down_interruptible(&c->lct_sem);
-		if(signal_pending(current))
-		{
-			dprintk(KERN_ERR "%s: LCT thread dead\n", c->name);
-			c->lct_running = 0;
-			return 0;
-		}
-
-		entries = c->dlct->table_size;
-		entries -= 3;
-		entries /= 9;
-
-		dprintk(KERN_INFO "%s: Dynamic LCT Update\n",c->name);
-		dprintk(KERN_INFO "%s: Dynamic LCT contains %d entries\n", c->name, entries);
-
-		if(!entries)
-		{
-			printk(KERN_INFO "%s: Empty LCT???\n", c->name);
-			continue;
-		}
-
-		/*
-		 * Loop through all the devices on the IOP looking for their
-		 * LCT data in the LCT.  We assume that TIDs are not repeated.
-		 * as that is the only way to really tell.  It's been confirmed
-		 * by the IRTOS vendor(s?) that TIDs are not reused until they 
-		 * wrap arround(4096), and I doubt a system will up long enough
-		 * to create/delete that many devices.
-		 */
-		for(d = c->devices; d; )
-		{
-			found = 0;
-			d1 = d->next;
-			
-			for(i = 0; i < entries; i++) 
-			{ 
-				if(d->lct_data.tid == c->dlct->lct_entry[i].tid) 
-				{ 
-					found = 1; 
-					break; 
-				} 
-			} 
-			if(!found) 
-			{
-				dprintk(KERN_INFO "i2o_core: Deleted device!\n"); 
-				spin_lock(&i2o_dev_lock);
-				i2o_delete_device(d); 
-				spin_unlock(&i2o_dev_lock);
-			} 
-			d = d1; 
-		}
-
-		/* 
-		 * Tell LCT to renotify us next time there is a change
-	 	 */
-		i2o_lct_notify(c);
-
-		/*
-		 * Copy new LCT into public LCT
-		 *
-		 * Possible race if someone is reading LCT while  we are copying 
-		 * over it. If this happens, we'll fix it then. but I doubt that
-		 * the LCT will get updated often enough or will get read by
-		 * a user often enough to worry.
-		 */
-		if(c->lct->table_size < c->dlct->table_size)
-		{
-			dma_addr_t phys;
-			tmp = c->lct;
-			c->lct = pci_alloc_consistent(c->pdev, c->dlct->table_size<<2, &phys);
-			if(!c->lct)
-			{
-				printk(KERN_ERR "%s: No memory for LCT!\n", c->name);
-				c->lct = tmp;
-				continue;
-			}
-			pci_free_consistent(tmp, c->lct->table_size << 2, c->lct, c->lct_phys);
-			c->lct_phys = phys;
-		}
-		memcpy(c->lct, c->dlct, c->dlct->table_size<<2);
-	}
-
-	return 0;
-}
-
-/**
- *	i2o_run_queue	-	process pending events on a controller
- *	@c: controller to process
- *
- *	This is called by the bus specific driver layer when an interrupt
- *	or poll of this card interface is desired.
- */
- 
-void i2o_run_queue(struct i2o_controller *c)
-{
-	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.
-	 */
-	if((mv=I2O_REPLY_READ32(c))==0xFFFFFFFF)
-		mv=I2O_REPLY_READ32(c);
-
-	while(mv!=0xFFFFFFFF)
-	{
-		struct i2o_handler *i;
-		/* Map the message from the page frame map to kernel virtual */
-		/* m=(struct i2o_message *)(mv - (unsigned long)c->page_frame_map + (unsigned long)c->page_frame); */
-		m=(struct i2o_message *)bus_to_virt(mv);
-		msg=(u32*)m;
-
-		/*
-	 	 *	Ensure this message is seen coherently but cachably by
-		 *	the processor 
-	 	 */
-
-		pci_dma_sync_single_for_cpu(c->pdev, c->page_frame_map, MSG_FRAME_SIZE, PCI_DMA_FROMDEVICE);
-	
-		/*
-		 *	Despatch it
-	 	 */
-
-		i=i2o_handlers[m->initiator_context&(MAX_I2O_MODULES-1)];
-		if(i && i->reply)
-			i->reply(i,c,m);
-		else
-		{
-			printk(KERN_WARNING "I2O: Spurious reply to handler %d\n", 
-				m->initiator_context&(MAX_I2O_MODULES-1));
-		}	
-	 	i2o_flush_reply(c,mv);
-		mb();
-
-		/* That 960 bug again... */	
-		if((mv=I2O_REPLY_READ32(c))==0xFFFFFFFF)
-			mv=I2O_REPLY_READ32(c);
-	}		
-}
-
-
-/**
- *	i2o_get_class_name - 	do i2o class name lookup
- *	@class: class number
- *
- *	Return a descriptive string for an i2o class
- */
- 
-const char *i2o_get_class_name(int class)
-{
-	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];
-}
-
-
-/**
- *	i2o_wait_message	-	obtain an i2o message from the IOP
- *	@c: controller
- *	@why: explanation 
- *
- *	This function waits up to 5 seconds for a message slot to be
- *	available. If no message is available it prints an error message
- *	that is expected to be what the message will be used for (eg
- *	"get_status"). 0xFFFFFFFF is returned on a failure.
- *
- *	On a success the message is returned. This is the physical page
- *	frame offset address from the read port. (See the i2o spec)
- */
- 
-u32 i2o_wait_message(struct i2o_controller *c, char *why)
-{
-	long time=jiffies;
-	u32 m;
-	while((m=I2O_POST_READ32(c))==0xFFFFFFFF)
-	{
-		if((jiffies-time)>=5*HZ)
-		{
-			dprintk(KERN_ERR "%s: Timeout waiting for message frame to send %s.\n", 
-				c->name, why);
-			return 0xFFFFFFFF;
-		}
-		schedule();
-		barrier();
-	}
-	return m;
-}
-	
-/**
- *	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;
-	int unit = d->lct_data.tid;
-
-	if(verbose==0)
-		return;
-		
-	printk(KERN_INFO "Target ID %d.\n", unit);
-	if((ret=i2o_query_scalar(c, unit, 0xF100, 3, buf, 16))>=0)
-	{
-		buf[16]=0;
-		printk(KERN_INFO "     Vendor: %s\n", buf);
-	}
-	if((ret=i2o_query_scalar(c, unit, 0xF100, 4, buf, 16))>=0)
-	{
-		buf[16]=0;
-		printk(KERN_INFO "     Device: %s\n", buf);
-	}
-	if(i2o_query_scalar(c, unit, 0xF100, 5, buf, 16)>=0)
-	{
-		buf[16]=0;
-		printk(KERN_INFO "     Description: %s\n", buf);
-	}
-	if((ret=i2o_query_scalar(c, unit, 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");
-			
-}
-
-
-/*
- *	Parse the hardware resource table. Right now we print it out
- *	and don't do a lot with it. We should collate these and then
- *	interact with the Linux resource allocation block.
- *
- *	Lets prove we can read it first eh ?
- *
- *	This is full of endianisms!
- */
- 
-static int i2o_parse_hrt(struct i2o_controller *c)
-{
-#ifdef DRIVERDEBUG
-	u32 *rows=(u32*)c->hrt;
-	u8 *p=(u8 *)c->hrt;
-	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 -1;
-	}
-		
-	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;
-	}
-#endif
-	return 0;
-}
-	
-/*
- *	The logical configuration table tells us what we can talk to
- *	on the board. Most of the stuff isn't interesting to us. 
- */
-
-static int i2o_parse_lct(struct i2o_controller *c)
-{
-	int i;
-	int max;
-	int tid;
-	struct i2o_device *d;
-	i2o_lct *lct = c->lct;
-
-	if (lct == NULL) {
-		printk(KERN_ERR "%s: LCT is empty???\n", c->name);
-		return -1;
-	}
-
-	max = lct->table_size;
-	max -= 3;
-	max /= 9;
-	
-	printk(KERN_INFO "%s: LCT has %d entries.\n", c->name, max);
-	
-	if(lct->iop_flags&(1<<0))
-		printk(KERN_WARNING "%s: Configuration dialog desired.\n", c->name);
-		
-	for(i=0;i<max;i++)
-	{
-		d = (struct i2o_device *)kmalloc(sizeof(struct i2o_device), GFP_KERNEL);
-		if(d==NULL)
-		{
-			printk(KERN_CRIT "i2o_core: Out of memory for I2O device data.\n");
-			return -ENOMEM;
-		}
-		
-		d->controller = c;
-		d->next = NULL;
-
-		memcpy(&d->lct_data, &lct->lct_entry[i], sizeof(i2o_lct_entry));
-
-		d->flags = 0;
-		tid = d->lct_data.tid;
-		
-		i2o_report_controller_unit(c, d);
-		
-		i2o_install_device(c, d);
-	}
-	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.
- */
- 
-int i2o_quiesce_controller(struct i2o_controller *c)
-{
-	u32 msg[4];
-	int ret;
-
-	i2o_status_get(c);
-
-	/* SysQuiesce discarded if IOP not in READY or OPERATIONAL state */
-
-	if ((c->status_block->iop_state != ADAPTER_STATE_READY) &&
-		(c->status_block->iop_state != ADAPTER_STATE_OPERATIONAL))
-	{
-		return 0;
-	}
-
-	msg[0] = FOUR_WORD_MSG_SIZE|SGL_OFFSET_0;
-	msg[1] = I2O_CMD_SYS_QUIESCE<<24|HOST_TID<<12|ADAPTER_TID;
-	msg[3] = 0;
-
-	/* Long timeout needed for quiesce if lots of devices */
-
-	if ((ret = i2o_post_wait(c, msg, sizeof(msg), 240)))
-		printk(KERN_INFO "%s: Unable to quiesce (status=%#x).\n",
-			c->name, -ret);
-	else
-		dprintk(KERN_INFO "%s: Quiesced.\n", c->name);
-
-	i2o_status_get(c); // Entered READY state
-	return ret;
-}
-
-/**
- *	i2o_enable_controller - move controller from ready to operational
- *	@c: controller
- *
- *	Enable IOP. This allows the IOP to resume external operations and
- *	reverses the effect of a quiesce. In the event of an error a negative
- *	errno code is returned.
- */
- 
-int i2o_enable_controller(struct i2o_controller *c)
-{
-	u32 msg[4];
-	int ret;
-
-	i2o_status_get(c);
-	
-	/* Enable only allowed on READY state */	
-	if(c->status_block->iop_state != ADAPTER_STATE_READY)
-		return -EINVAL;
-
-	msg[0]=FOUR_WORD_MSG_SIZE|SGL_OFFSET_0;
-	msg[1]=I2O_CMD_SYS_ENABLE<<24|HOST_TID<<12|ADAPTER_TID;
-
-	/* How long of a timeout do we need? */
-
-	if ((ret = i2o_post_wait(c, msg, sizeof(msg), 240)))
-		printk(KERN_ERR "%s: Could not enable (status=%#x).\n",
-			c->name, -ret);
-	else
-		dprintk(KERN_INFO "%s: Enabled.\n", c->name);
-
-	i2o_status_get(c); // entered OPERATIONAL state
-
-	return ret;
-}
-
-/**
- *	i2o_clear_controller	-	clear a controller
- *	@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.
- */
- 
-int i2o_clear_controller(struct i2o_controller *c)
-{
-	struct i2o_controller *iop;
-	u32 msg[4];
-	int ret;
-
-	/* Quiesce all IOPs first */
-
-	for (iop = i2o_controller_chain; iop; iop = iop->next)
-		i2o_quiesce_controller(iop);
-
-	msg[0]=FOUR_WORD_MSG_SIZE|SGL_OFFSET_0;
-	msg[1]=I2O_CMD_ADAPTER_CLEAR<<24|HOST_TID<<12|ADAPTER_TID;
-	msg[3]=0;
-
-	if ((ret=i2o_post_wait(c, msg, sizeof(msg), 30)))
-		printk(KERN_INFO "%s: Unable to clear (status=%#x).\n",
-			c->name, -ret);
-	else
-		dprintk(KERN_INFO "%s: Cleared.\n",c->name);
-
-	i2o_status_get(c);
-
-	/* Enable other IOPs */
-
-	for (iop = i2o_controller_chain; iop; iop = iop->next)
-		if (iop != c)
-			i2o_enable_controller(iop);
-
-	return ret;
-}
-
-
-/**
- *	i2o_reset_controller	-	reset an IOP
- *	@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_reset_controller(struct i2o_controller *c)
-{
-	struct i2o_controller *iop;
-	u32 m;
-	u8 *status;
-	dma_addr_t status_phys;
-	u32 *msg;
-	long time;
-
-	/* Quiesce all IOPs first */
-
-	for (iop = i2o_controller_chain; iop; iop = iop->next)
-	{
-		if(!iop->dpt)
-			i2o_quiesce_controller(iop);
-	}
-
-	m=i2o_wait_message(c, "AdapterReset");
-	if(m==0xFFFFFFFF)	
-		return -ETIMEDOUT;
-	msg=(u32 *)(c->msg_virt+m);
-	
-	status = pci_alloc_consistent(c->pdev, 4, &status_phys);
-	if(status == NULL) {
-		printk(KERN_ERR "IOP reset failed - no free memory.\n");
-		return -ENOMEM;
-	}
-	memset(status, 0, 4);
-	
-	msg[0]=EIGHT_WORD_MSG_SIZE|SGL_OFFSET_0;
-	msg[1]=I2O_CMD_ADAPTER_RESET<<24|HOST_TID<<12|ADAPTER_TID;
-	msg[2]=core_context;
-	msg[3]=0;
-	msg[4]=0;
-	msg[5]=0;
-	msg[6]=status_phys;
-	msg[7]=0;	/* 64bit host FIXME */
-
-	i2o_post_message(c,m);
-
-	/* Wait for a reply */
-	time=jiffies;
-	while(*status==0)
-	{
-		if((jiffies-time)>=20*HZ)
-		{
-			printk(KERN_ERR "IOP reset timeout.\n");
-			/* The controller still may respond and overwrite
-			 * status_phys, LEAK it to prevent memory corruption.
-			 */
-			return -ETIMEDOUT;
-		}
-		schedule();
-		barrier();
-	}
-
-	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.  
-		 */ 
-
-		dprintk(KERN_INFO "%s: Reset in progress, waiting for reboot...\n",
-			c->name); 
-
-		time = jiffies; 
-		m = I2O_POST_READ32(c); 
-		while(m == 0XFFFFFFFF) 
-		{ 
-			if((jiffies-time) >= 30*HZ)
-			{
-				printk(KERN_ERR "%s: Timeout waiting for IOP reset.\n", 
-						c->name); 
-				/* The controller still may respond and
-				 * overwrite status_phys, LEAK it to prevent
-				 * memory corruption.
-				 */
-				return -ETIMEDOUT; 
-			} 
-			schedule(); 
-			barrier(); 
-			m = I2O_POST_READ32(c); 
-		}
-		i2o_flush_reply(c,m);
-	}
-
-	/* If IopReset was rejected or didn't perform reset, try IopClear */
-
-	i2o_status_get(c);
-	if (status[0] == I2O_CMD_REJECTED || 
-		c->status_block->iop_state != ADAPTER_STATE_RESET)
-	{
-		printk(KERN_WARNING "%s: Reset rejected, trying to clear\n",c->name);
-		i2o_clear_controller(c);
-	}
-	else
-		dprintk(KERN_INFO "%s: Reset completed.\n", c->name);
-
-	/* Enable other IOPs */
-
-	for (iop = i2o_controller_chain; iop; iop = iop->next)
-		if (iop != c)
-			i2o_enable_controller(iop);
-
-	pci_free_consistent(c->pdev, 4, status, status_phys);
-	return 0;
-}
-
-
-/**
- * 	i2o_status_get	-	get the status block for the IOP
- *	@c: controller
- *
- *	Issue a status query on the controller. This updates the
- *	attached status_block. If the controller fails to reply or an
- *	error occurs then a negative errno code is returned. On success
- *	zero is returned and the status_blok is updated.
- */
- 
-int i2o_status_get(struct i2o_controller *c)
-{
-	long time;
-	u32 m;
-	u32 *msg;
-	u8 *status_block;
-
-	if (c->status_block == NULL) 
-	{
-		c->status_block = (i2o_status_block *)
-			pci_alloc_consistent(c->pdev, sizeof(i2o_status_block), &c->status_block_phys);
-		if (c->status_block == NULL)
-		{
-			printk(KERN_CRIT "%s: Get Status Block failed; Out of memory.\n",
-				c->name);
-			return -ENOMEM;
-		}
-	}
-
-	status_block = (u8*)c->status_block;
-	memset(c->status_block,0,sizeof(i2o_status_block));
-	
-	m=i2o_wait_message(c, "StatusGet");
-	if(m==0xFFFFFFFF)
-		return -ETIMEDOUT;	
-	msg=(u32 *)(c->msg_virt+m);
-
-	msg[0]=NINE_WORD_MSG_SIZE|SGL_OFFSET_0;
-	msg[1]=I2O_CMD_STATUS_GET<<24|HOST_TID<<12|ADAPTER_TID;
-	msg[2]=core_context;
-	msg[3]=0;
-	msg[4]=0;
-	msg[5]=0;
-	msg[6]=c->status_block_phys;
-	msg[7]=0;   /* 64bit host FIXME */
-	msg[8]=sizeof(i2o_status_block); /* always 88 bytes */
-
-	i2o_post_message(c,m);
-
-	/* Wait for a reply */
-
-	time=jiffies;
-	while(status_block[87]!=0xFF)
-	{
-		if((jiffies-time)>=5*HZ)
-		{
-			printk(KERN_ERR "%s: Get status timeout.\n",c->name);
-			return -ETIMEDOUT;
-		}
-		yield();
-		barrier();
-	}
-
-#ifdef DRIVERDEBUG
-	printk(KERN_INFO "%s: State = ", c->name);
-	switch (c->status_block->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",c->status_block->iop_state);
-}     
-#endif   
-
-	return 0;
-}
-
-/*
- * Get the Hardware Resource Table for the device.
- * The HRT contains information about possible hidden devices
- * but is mostly useless to us 
- */
-int i2o_hrt_get(struct i2o_controller *c)
-{
-	u32 msg[6];
-	int ret, size = sizeof(i2o_hrt);
-	int loops = 3;	/* we only try 3 times to get the HRT, this should be
-			   more then enough. Worst case should be 2 times.*/
-
-	/* First read just the header to figure out the real size */
-
-	do  {
-		/* first we allocate the memory for the HRT */
-		if (c->hrt == NULL) {
-			c->hrt=pci_alloc_consistent(c->pdev, size, &c->hrt_phys);
-			if (c->hrt == NULL) {
-				printk(KERN_CRIT "%s: Hrt Get failed; Out of memory.\n", c->name);
-				return -ENOMEM;
-			}
-			c->hrt_len = size;
-		}
-
-		msg[0]= SIX_WORD_MSG_SIZE| SGL_OFFSET_4;
-		msg[1]= I2O_CMD_HRT_GET<<24 | HOST_TID<<12 | ADAPTER_TID;
-		msg[3]= 0;
-		msg[4]= (0xD0000000 | c->hrt_len);	/* Simple transaction */
-		msg[5]= c->hrt_phys;		/* Dump it here */
-
-		ret = i2o_post_wait_mem(c, msg, sizeof(msg), 20, c->hrt, NULL, c->hrt_phys, 0, c->hrt_len, 0);
-		
-		if(ret == -ETIMEDOUT)
-		{
-			/* The HRT block we used is in limbo somewhere. When the iop wakes up
-			   we will recover it */
-			c->hrt = NULL;
-			c->hrt_len = 0;
-			return ret;
-		}
-		
-		if(ret<0)
-		{
-			printk(KERN_ERR "%s: Unable to get HRT (status=%#x)\n",
-				c->name, -ret);	
-			return ret;
-		}
-
-		if (c->hrt->num_entries * c->hrt->entry_len << 2 > c->hrt_len) {
-			size = c->hrt->num_entries * c->hrt->entry_len << 2;
-			pci_free_consistent(c->pdev, c->hrt_len, c->hrt, c->hrt_phys);
-			c->hrt_len = 0;
-			c->hrt = NULL;
-		}
-		loops --;
-	} while (c->hrt == NULL && loops > 0);
-
-	if(c->hrt == NULL)
-	{
-		printk(KERN_ERR "%s: Unable to get HRT after three tries, giving up\n", c->name);
-		return -1;
-	}
-
-	i2o_parse_hrt(c); // just for debugging
-
-	return 0;
-}
-
-/*
- * Send the I2O System Table to the specified IOP
- *
- * The system table contains information about all the IOPs in the
- * system.  It is build and then sent to each IOP so that IOPs can
- * establish connections between each other.
- *
- */
-static int i2o_systab_send(struct i2o_controller *iop)
-{
-	u32 msg[12];
-	dma_addr_t sys_tbl_phys;
-	int ret;
-	struct resource *root;
-	u32 *privbuf = kmalloc(16, GFP_KERNEL);
-	if(privbuf == NULL)
-		return -ENOMEM;
-	
-		
-	if(iop->status_block->current_mem_size < iop->status_block->desired_mem_size)
-	{
-		struct resource *res = &iop->mem_resource;
-		res->name = iop->pdev->bus->name;
-		res->flags = IORESOURCE_MEM;
-		res->start = 0;
-		res->end = 0;
-		printk("%s: requires private memory resources.\n", iop->name);
-		root = pci_find_parent_resource(iop->pdev, res);
-		if(root==NULL)
-			printk("Can't find parent resource!\n");
-		if(root && allocate_resource(root, res, 
-				iop->status_block->desired_mem_size,
-				iop->status_block->desired_mem_size,
-				iop->status_block->desired_mem_size,
-				1<<20,	/* Unspecified, so use 1Mb and play safe */
-				NULL,
-				NULL)>=0)
-		{
-			iop->mem_alloc = 1;
-			iop->status_block->current_mem_size = 1 + res->end - res->start;
-			iop->status_block->current_mem_base = res->start;
-			printk(KERN_INFO "%s: allocated %ld bytes of PCI memory at 0x%08lX.\n", 
-				iop->name, 1+res->end-res->start, res->start);
-		}
-	}
-	if(iop->status_block->current_io_size < iop->status_block->desired_io_size)
-	{
-		struct resource *res = &iop->io_resource;
-		res->name = iop->pdev->bus->name;
-		res->flags = IORESOURCE_IO;
-		res->start = 0;
-		res->end = 0;
-		printk("%s: requires private memory resources.\n", iop->name);
-		root = pci_find_parent_resource(iop->pdev, res);
-		if(root==NULL)
-			printk("Can't find parent resource!\n");
-		if(root &&  allocate_resource(root, res, 
-				iop->status_block->desired_io_size,
-				iop->status_block->desired_io_size,
-				iop->status_block->desired_io_size,
-				1<<20,	/* Unspecified, so use 1Mb and play safe */
-				NULL,
-				NULL)>=0)
-		{
-			iop->io_alloc = 1;
-			iop->status_block->current_io_size = 1 + res->end - res->start;
-			iop->status_block->current_mem_base = res->start;
-			printk(KERN_INFO "%s: allocated %ld bytes of PCI I/O at 0x%08lX.\n", 
-				iop->name, 1+res->end-res->start, res->start);
-		}
-	}
-	else
-	{	
-		privbuf[0] = iop->status_block->current_mem_base;
-		privbuf[1] = iop->status_block->current_mem_size;
-		privbuf[2] = iop->status_block->current_io_base;
-		privbuf[3] = iop->status_block->current_io_size;
-	}
-
-	msg[0] = I2O_MESSAGE_SIZE(12) | SGL_OFFSET_6;
-	msg[1] = I2O_CMD_SYS_TAB_SET<<24 | HOST_TID<<12 | ADAPTER_TID;
-	msg[3] = 0;
-	msg[4] = (0<<16) | ((iop->unit+2) );      /* Host 0 IOP ID (unit + 2) */
-	msg[5] = 0;                               /* Segment 0 */
-
-	/* 
- 	 * Provide three SGL-elements:
- 	 * System table (SysTab), Private memory space declaration and 
- 	 * Private i/o space declaration  
- 	 * 
- 	 * Nasty one here. We can't use pci_alloc_consistent to send the
- 	 * same table to everyone. We have to go remap it for them all
- 	 */
- 	 
- 	sys_tbl_phys = pci_map_single(iop->pdev, sys_tbl, sys_tbl_len, PCI_DMA_TODEVICE);
-	msg[6] = 0x54000000 | sys_tbl_phys;
-
-	msg[7] = sys_tbl_phys;
-	msg[8] = 0x54000000 | privbuf[1];
-	msg[9] = privbuf[0];
-	msg[10] = 0xD4000000 | privbuf[3];
-	msg[11] = privbuf[2];
-
-	ret=i2o_post_wait(iop, msg, sizeof(msg), 120);
-
-	pci_unmap_single(iop->pdev, sys_tbl_phys, sys_tbl_len, PCI_DMA_TODEVICE);
-	
-	if(ret==-ETIMEDOUT)
-	{
-		printk(KERN_ERR "%s: SysTab setup timed out.\n", iop->name);
-	}
-	else if(ret<0)
-	{
-		printk(KERN_ERR "%s: Unable to set SysTab (status=%#x).\n", 
-			iop->name, -ret);
-	}
-	else
-	{
-		dprintk(KERN_INFO "%s: SysTab set.\n", iop->name);
-	}
-	i2o_status_get(iop); // Entered READY state
-
-	kfree(privbuf);
-	return ret;	
-
- }
-
-/*
- * Initialize I2O subsystem.
- */
-void __init i2o_sys_init(void)
-{
-	struct i2o_controller *iop, *niop = NULL;
-
-	printk(KERN_INFO "Activating I2O controllers...\n");
-	printk(KERN_INFO "This may take a few minutes if there are many devices\n");
-	
-	/* In INIT state, Activate IOPs */
-	for (iop = i2o_controller_chain; iop; iop = niop) {
-		dprintk(KERN_INFO "Calling i2o_activate_controller for %s...\n", 
-			iop->name);
-		niop = iop->next;
-		if (i2o_activate_controller(iop) < 0)
-			i2o_delete_controller(iop);
-	}
-
-	/* Active IOPs in HOLD state */
-
-rebuild_sys_tab:
-	if (i2o_controller_chain == NULL)
-		return;
-
-	/*
-	 * If build_sys_table fails, we kill everything and bail
-	 * as we can't init the IOPs w/o a system table
-	 */	
-	dprintk(KERN_INFO "i2o_core: Calling i2o_build_sys_table...\n");
-	if (i2o_build_sys_table() < 0) {
-		i2o_sys_shutdown();
-		return;
-	}
-
-	/* If IOP don't get online, we need to rebuild the System table */
-	for (iop = i2o_controller_chain; iop; iop = niop) {
-		niop = iop->next;
-		dprintk(KERN_INFO "Calling i2o_online_controller for %s...\n", iop->name);
-		if (i2o_online_controller(iop) < 0) {
-			i2o_delete_controller(iop);	
-			goto rebuild_sys_tab;
-		}
-	}
-	
-	/* Active IOPs now in OPERATIONAL state */
-
-	/*
-	 * Register for status updates from all IOPs
-	 */
-	for(iop = i2o_controller_chain; iop; iop=iop->next) {
-
-		/* Create a kernel thread to deal with dynamic LCT updates */
-		iop->lct_pid = kernel_thread(i2o_dyn_lct, iop, CLONE_SIGHAND);
-	
-		/* Update change ind on DLCT */
-		iop->dlct->change_ind = iop->lct->change_ind;
-
-		/* Start dynamic LCT updates */
-		i2o_lct_notify(iop);
-
-		/* Register for all events from IRTOS */
-		i2o_event_register(iop, core_context, 0, 0, 0xFFFFFFFF);
-	}
-}
-
-/**
- *	i2o_sys_shutdown - shutdown I2O system
- *
- *	Bring down each i2o controller and then return. Each controller
- *	is taken through an orderly shutdown
- */
- 
-static void i2o_sys_shutdown(void)
-{
-	struct i2o_controller *iop, *niop;
-
-	/* Delete all IOPs from the controller chain */
-	/* that will reset all IOPs too */
-
-	for (iop = i2o_controller_chain; iop; iop = niop) {
-		niop = iop->next;
-		i2o_delete_controller(iop);
-	}
-}
-
-/**
- *	i2o_activate_controller	-	bring controller up to HOLD
- *	@iop: 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. -1 is returned on a failure, 0 on success.
- *	
- */
- 
-int i2o_activate_controller(struct i2o_controller *iop)
-{
-	/* In INIT state, Wait Inbound Q to initialize (in i2o_status_get) */
-	/* In READY state, Get status */
-
-	if (i2o_status_get(iop) < 0) {
-		printk(KERN_INFO "Unable to obtain status of %s, "
-			"attempting a reset.\n", iop->name);
-		if (i2o_reset_controller(iop) < 0)
-			return -1;
-	}
-
-	if(iop->status_block->iop_state == ADAPTER_STATE_FAULTED) {
-		printk(KERN_CRIT "%s: hardware fault\n", iop->name);
-		return -1;
-	}
-
-	if (iop->status_block->i2o_version > I2OVER15) {
-		printk(KERN_ERR "%s: Not running vrs. 1.5. of the I2O Specification.\n",
-			iop->name);
-		return -1;
-	}
-
-	if (iop->status_block->iop_state == ADAPTER_STATE_READY ||
-	    iop->status_block->iop_state == ADAPTER_STATE_OPERATIONAL ||
-	    iop->status_block->iop_state == ADAPTER_STATE_HOLD ||
-	    iop->status_block->iop_state == ADAPTER_STATE_FAILED)
-	{
-		dprintk(KERN_INFO "%s: Already running, trying to reset...\n",
-			iop->name);
-		if (i2o_reset_controller(iop) < 0)
-			return -1;
-	}
-
-	if (i2o_init_outbound_q(iop) < 0)
-		return -1;
-
-	if (i2o_post_outbound_messages(iop)) 
-		return -1;
-
-	/* In HOLD state */
-	
-	if (i2o_hrt_get(iop) < 0)
-		return -1;
-
-	return 0;
-}
-
-
-/**
- *	i2o_init_outbound_queue	- setup the outbound queue
- *	@c: controller
- *
- *	Clear and (re)initialize IOP's outbound queue. Returns 0 on
- *	success or a negative errno code on a failure.
- */
- 
-int i2o_init_outbound_q(struct i2o_controller *c)
-{
-	u8 *status;
-	dma_addr_t status_phys;
-	u32 m;
-	u32 *msg;
-	u32 time;
-
-	dprintk(KERN_INFO "%s: Initializing Outbound Queue...\n", c->name);
-	m=i2o_wait_message(c, "OutboundInit");
-	if(m==0xFFFFFFFF)
-		return -ETIMEDOUT;
-	msg=(u32 *)(c->msg_virt+m);
-
-	status = pci_alloc_consistent(c->pdev, 4, &status_phys);
-	if (status==NULL) {
-		printk(KERN_ERR "%s: Outbound Queue initialization failed - no free memory.\n",
-			c->name);
-		return -ENOMEM;
-	}
-	memset(status, 0, 4);
-
-	msg[0]= EIGHT_WORD_MSG_SIZE| TRL_OFFSET_6;
-	msg[1]= I2O_CMD_OUTBOUND_INIT<<24 | HOST_TID<<12 | ADAPTER_TID;
-	msg[2]= core_context;
-	msg[3]= 0x0106;				/* Transaction context */
-	msg[4]= 4096;				/* Host page frame size */
-	/* Frame size is in words. 256 bytes a frame for now */
-	msg[5]= MSG_FRAME_SIZE<<16|0x80;	/* Outbound msg frame size in words and Initcode */
-	msg[6]= 0xD0000004;			/* Simple SG LE, EOB */
-	msg[7]= status_phys;
-
-	i2o_post_message(c,m);
-	
-	barrier();
-	time=jiffies;
-	while(status[0] < I2O_CMD_REJECTED)
-	{
-		if((jiffies-time)>=30*HZ)
-		{
-			if(status[0]==0x00)
-				printk(KERN_ERR "%s: Ignored queue initialize request.\n",
-					c->name);
-			else  
-				printk(KERN_ERR "%s: Outbound queue initialize timeout.\n",
-					c->name);
-			pci_free_consistent(c->pdev, 4, status, status_phys);
-			return -ETIMEDOUT;
-		}  
-		yield();
-		barrier();
-	}  
-
-	if(status[0] != I2O_CMD_COMPLETED)
-	{
-		printk(KERN_ERR "%s: IOP outbound initialise failed.\n", c->name);
-		pci_free_consistent(c->pdev, 4, status, status_phys);
-		return -ETIMEDOUT;
-	}
-	pci_free_consistent(c->pdev, 4, status, status_phys);
-	return 0;
-}
-
-/**
- *	i2o_post_outbound_messages	-	fill message queue
- *	@c: controller
- *
- *	Allocate a message frame and load the messages into the IOP. The
- *	function returns zero on success or a negative errno code on
- *	failure.
- */
-
-int i2o_post_outbound_messages(struct i2o_controller *c)
-{
-	int i;
-	u32 m;
-	/* Alloc space for IOP's outbound queue message frames */
-
-	c->page_frame = kmalloc(MSG_POOL_SIZE, GFP_KERNEL);
-	if(c->page_frame==NULL) {
-		printk(KERN_ERR "%s: Outbound Q initialize failed; out of memory.\n",
-			c->name);
-		return -ENOMEM;
-	}
-
-	c->page_frame_map = pci_map_single(c->pdev, c->page_frame, MSG_POOL_SIZE, PCI_DMA_FROMDEVICE);
-
-	if(c->page_frame_map == 0)
-	{
-		kfree(c->page_frame);
-		printk(KERN_ERR "%s: Unable to map outbound queue.\n", c->name);
-		return -ENOMEM;
-	}
-
-	m = c->page_frame_map;
-
-	/* Post frames */
-
-	for(i=0; i< NMBR_MSG_FRAMES; i++) {
-		I2O_REPLY_WRITE32(c,m);
-		mb();
-		m += (MSG_FRAME_SIZE << 2);
-	}
-
-	return 0;
-}
-
-/*
- * Get the IOP's Logical Configuration Table
- */
-int i2o_lct_get(struct i2o_controller *c)
-{
-	u32 msg[8];
-	int ret, size = c->status_block->expected_lct_size;
-
-	do {
-		if (c->lct == NULL) {
-			c->lct = pci_alloc_consistent(c->pdev, size, &c->lct_phys);
-			if(c->lct == NULL) {
-				printk(KERN_CRIT "%s: Lct Get failed. Out of memory.\n",
-					c->name);
-				return -ENOMEM;
-			}
-		}
-		memset(c->lct, 0, size);
-
-		msg[0] = EIGHT_WORD_MSG_SIZE|SGL_OFFSET_6;
-		msg[1] = I2O_CMD_LCT_NOTIFY<<24 | HOST_TID<<12 | ADAPTER_TID;
-		/* msg[2] filled in i2o_post_wait */
-		msg[3] = 0;
-		msg[4] = 0xFFFFFFFF;	/* All devices */
-		msg[5] = 0x00000000;	/* Report now */
-		msg[6] = 0xD0000000|size;
-		msg[7] = c->lct_phys;
-
-		ret=i2o_post_wait_mem(c, msg, sizeof(msg), 120, c->lct, NULL, c->lct_phys, 0, size, 0);
-		
-		if(ret == -ETIMEDOUT)
-		{
-			c->lct = NULL;
-			return ret;
-		}
-		
-		if(ret<0)
-		{
-			printk(KERN_ERR "%s: LCT Get failed (status=%#x.\n", 
-				c->name, -ret);	
-			return ret;
-		}
-
-		if (c->lct->table_size << 2 > size) {
-			int new_size = c->lct->table_size << 2;
-			pci_free_consistent(c->pdev, size, c->lct, c->lct_phys);
-			size = new_size;
-			c->lct = NULL;
-		}
-	} while (c->lct == NULL);
-
-        if ((ret=i2o_parse_lct(c)) < 0)
-                return ret;
-
-	return 0;
-}
-
-/*
- * Like above, but used for async notification.  The main
- * difference is that we keep track of the CurrentChangeIndiicator
- * so that we only get updates when it actually changes.
- *
- */
-int i2o_lct_notify(struct i2o_controller *c)
-{
-	u32 msg[8];
-
-	msg[0] = EIGHT_WORD_MSG_SIZE|SGL_OFFSET_6;
-	msg[1] = I2O_CMD_LCT_NOTIFY<<24 | HOST_TID<<12 | ADAPTER_TID;
-	msg[2] = core_context;
-	msg[3] = 0xDEADBEEF;	
-	msg[4] = 0xFFFFFFFF;	/* All devices */
-	msg[5] = c->dlct->change_ind+1;	/* Next change */
-	msg[6] = 0xD0000000|8192;
-	msg[7] = c->dlct_phys;
-
-	return i2o_post_this(c, msg, sizeof(msg));
-}
-		
-/*
- *	Bring a controller online into OPERATIONAL state. 
- */
- 
-int i2o_online_controller(struct i2o_controller *iop)
-{
-	u32 v;
-	
-	if (i2o_systab_send(iop) < 0)
-		return -1;
-
-	/* In READY state */
-
-	dprintk(KERN_INFO "%s: Attempting to enable...\n", iop->name);
-	if (i2o_enable_controller(iop) < 0)
-		return -1;
-
-	/* In OPERATIONAL state  */
-
-	dprintk(KERN_INFO "%s: Attempting to get/parse lct...\n", iop->name);
-	if (i2o_lct_get(iop) < 0)
-		return -1;
-
-	/* Check battery status */
-	 
-	iop->battery = 0;
-	if(i2o_query_scalar(iop, ADAPTER_TID, 0x0000, 4, &v, 4)>=0)
-	{
-		if(v&16)
-			iop->battery = 1;
-	}
-
-	return 0;
-}
-
-/*
- * 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.
- */
-static int i2o_build_sys_table(void)
-{
-	struct i2o_controller *iop = NULL;
-	struct i2o_controller *niop = NULL;
-	int count = 0;
-
-	sys_tbl_len = sizeof(struct i2o_sys_tbl) +	// Header + IOPs
-				(i2o_num_controllers) *
-					sizeof(struct i2o_sys_tbl_entry);
-
-	if(sys_tbl)
-		kfree(sys_tbl);
-
-	sys_tbl = kmalloc(sys_tbl_len, GFP_KERNEL);
-	if(!sys_tbl) {
-		printk(KERN_CRIT "SysTab Set failed. Out of memory.\n");
-		return -ENOMEM;
-	}
-	memset((void*)sys_tbl, 0, sys_tbl_len);
-
-	sys_tbl->num_entries = i2o_num_controllers;
-	sys_tbl->version = I2OVERSION; /* TODO: Version 2.0 */
-	sys_tbl->change_ind = sys_tbl_ind++;
-
-	for(iop = i2o_controller_chain; iop; iop = niop)
-	{
-		niop = iop->next;
-
-		/* 
-		 * 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 subsyßtem...
-		 */
-		if(i2o_status_get(iop)) {
-			printk(KERN_ERR "%s: Deleting b/c could not get status while"
-				"attempting to build system table\n", iop->name);
-			i2o_delete_controller(iop);		
-			sys_tbl->num_entries--;
-			continue; // try the next one
-		}
-
-		sys_tbl->iops[count].org_id = iop->status_block->org_id;
-		sys_tbl->iops[count].iop_id = iop->unit + 2;
-		sys_tbl->iops[count].seg_num = 0;
-		sys_tbl->iops[count].i2o_version = 
-				iop->status_block->i2o_version;
-		sys_tbl->iops[count].iop_state = 
-				iop->status_block->iop_state;
-		sys_tbl->iops[count].msg_type = 
-				iop->status_block->msg_type;
-		sys_tbl->iops[count].frame_size = 
-				iop->status_block->inbound_frame_size;
-		sys_tbl->iops[count].last_changed = sys_tbl_ind - 1; // ??
-		sys_tbl->iops[count].iop_capabilities = 
-				iop->status_block->iop_capabilities;
-		sys_tbl->iops[count].inbound_low = (u32)iop->post_port;
-		sys_tbl->iops[count].inbound_high = 0;	// FIXME: 64-bit support
-
-		count++;
-	}
-
-#ifdef DRIVERDEBUG
-{
-	u32 *table;
-	table = (u32*)sys_tbl;
-	for(count = 0; count < (sys_tbl_len >>2); count++)
-		printk(KERN_INFO "sys_tbl[%d] = %0#10x\n", count, table[count]);
-}
-#endif
-
-	return 0;
-}
-
-
-/*
- *	Run time support routines
- */
- 
-/*
- *	Generic "post and forget" helpers. This is less efficient - we do
- *	a memcpy for example that isnt strictly needed, but for most uses
- *	this is simply not worth optimising
- */
-
-int i2o_post_this(struct i2o_controller *c, u32 *data, int len)
-{
-	u32 m;
-	u32 *msg;
-	unsigned long t=jiffies;
-
-	do
-	{
-		mb();
-		m = I2O_POST_READ32(c);
-	}
-	while(m==0xFFFFFFFF && (jiffies-t)<HZ);
-	
-	if(m==0xFFFFFFFF)
-	{
-		printk(KERN_ERR "%s: Timeout waiting for message frame!\n",
-		       c->name);
-		return -ETIMEDOUT;
-	}
-	msg = (u32 *)(c->msg_virt + m);
- 	memcpy_toio(msg, data, len);
-	i2o_post_message(c,m);
-	return 0;
-}
-
-/**
- * 	i2o_post_wait_mem	-	I2O query/reply with DMA buffers
- *	@c: controller
- *	@msg: message to send
- *	@len: length of message
- *	@timeout: time in seconds to wait
- *	@mem1: attached memory buffer 1
- *	@mem2: attached memory buffer 2
- *	@phys1: physical address of buffer 1
- *	@phys2: physical address of buffer 2
- *	@size1: size of buffer 1
- *	@size2: size of buffer 2
- *
- * 	This core 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 buffers attached to the request. If -ETIMEDOUT is returned then
- *	the memory buffers must not be freed. Instead the event completion will
- *	free them for you. In all other cases the buffers are your problem.
- *
- *	Pass NULL for unneeded buffers.
- */
- 
-int i2o_post_wait_mem(struct i2o_controller *c, u32 *msg, int len, int timeout, void *mem1, void *mem2, dma_addr_t phys1, dma_addr_t phys2, int size1, int size2)
-{
-	DECLARE_WAIT_QUEUE_HEAD(wq_i2o_post);
-	DECLARE_WAITQUEUE(wait, current);
-	int complete = 0;
-	int status;
-	unsigned long flags = 0;
-	struct i2o_post_wait_data *wait_data =
-		kmalloc(sizeof(struct i2o_post_wait_data), GFP_KERNEL);
-
-	if(!wait_data)
-		return -ENOMEM;
-
-	/*
-	 *	Create a new notification object
-	 */
-	wait_data->status = &status;
-	wait_data->complete = &complete;
-	wait_data->mem[0] = mem1;
-	wait_data->mem[1] = mem2;
-	wait_data->phys[0] = phys1;
-	wait_data->phys[1] = phys2;
-	wait_data->size[0] = size1;
-	wait_data->size[1] = size2;
-	
-	/* 
-	 *	Queue the event with its unique id
-	 */
-	spin_lock_irqsave(&post_wait_lock, flags);
-
-	wait_data->next = post_wait_queue;
-	post_wait_queue = wait_data;
-	wait_data->id = (++post_wait_id) & 0x7fff;
-	wait_data->wq = &wq_i2o_post;
-
-	spin_unlock_irqrestore(&post_wait_lock, flags);
-
-	/*
-	 *	Fill in the message id
-	 */
-	 
-	msg[2] = 0x80000000|(u32)core_context|((u32)wait_data->id<<16);
-	
-	/*
-	 *	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.  From the point post_this returns
-	 *	the wait_data may have been deleted.
-	 */
-
-	add_wait_queue(&wq_i2o_post, &wait);
-	set_current_state(TASK_INTERRUPTIBLE);
-	if ((status = i2o_post_this(c, msg, len))==0) {
-		schedule_timeout(HZ * timeout);
-	}  
-	else
-	{
-		remove_wait_queue(&wq_i2o_post, &wait);
-		return -EIO;
-	}
-	remove_wait_queue(&wq_i2o_post, &wait);
-
-	if(signal_pending(current))
-		status = -EINTR;
-		
-	spin_lock_irqsave(&post_wait_lock, flags);
-	barrier();	/* Be sure we see complete as it is locked */
-	if(!complete)
-	{
-		/* 
-		 *	Mark the entry dead. We cannot remove it. This is important.
-		 *	When it does terminate (which it must do if the controller hasnt
-		 *	died..) then it will otherwise scribble on stuff.
-		 *	!complete lets us safely check if the entry is still
-		 *	allocated and thus we can write into it
-		 */
-		wait_data->wq = NULL;
-		status = -ETIMEDOUT;
-	}
-	else
-	{
-		/* Debugging check - remove me soon */
-		if(status == -ETIMEDOUT)
-		{
-			printk("TIMEDOUT BUG!\n");
-			status = -EIO;
-		}
-	}
-	/* And the wait_data is not leaked either! */	 
-	spin_unlock_irqrestore(&post_wait_lock, flags);
-	return status;
-}
-
-/**
- * 	i2o_post_wait		-	I2O query/reply
- *	@c: controller
- *	@msg: message to send
- *	@len: length of message
- *	@timeout: time in seconds to wait
- *
- * 	This core API allows an OSM to post a message and then be told whether
- *	or not the system received a successful reply. 
- */
- 
-int i2o_post_wait(struct i2o_controller *c, u32 *msg, int len, int timeout)
-{
-	return i2o_post_wait_mem(c, msg, len, timeout, NULL, NULL, 0, 0, 0, 0);
-}
-
-/*
- * i2o_post_wait is completed and we want to wake up the 
- * sleeping proccess. Called by core's reply handler.
- */
-
-static void i2o_post_wait_complete(struct i2o_controller *c, u32 context, int status)
-{
-	struct i2o_post_wait_data **p1, *q;
-	unsigned long flags;
-	
-	/* 
-	 * We need to search through the post_wait 
-	 * queue 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
-	 *
-	 * Lock needed to keep anyone from moving queue pointers 
-	 * around while we're looking through them.
-	 */
-
-	spin_lock_irqsave(&post_wait_lock, flags);
-
-	for(p1 = &post_wait_queue; *p1!=NULL; p1 = &((*p1)->next)) 
-	{
-		q = (*p1);
-		if(q->id == ((context >> 16) & 0x7fff)) {
-			/*
-			 *	Delete it 
-			 */
-			 
-			*p1 = q->next;
-			
-			/*
-			 *	Live or dead ?
-			 */
-			 
-			if(q->wq)
-			{
-				/* Live entry - wakeup and set status */
-				*q->status = status;
-				*q->complete = 1;
-				wake_up(q->wq);
-			}
-			else
-			{
-				/*
-				 *	Free resources. Caller is dead
-				 */
-
-				if(q->mem[0])
-					pci_free_consistent(c->pdev, q->size[0], q->mem[0], q->phys[0]);
-				if(q->mem[1])
-					pci_free_consistent(c->pdev, q->size[1], q->mem[1], q->phys[1]);
-
-				printk(KERN_WARNING "i2o_post_wait event completed after timeout.\n");
-			}
-			kfree(q);
-			spin_unlock(&post_wait_lock);
-			return;
-		}
-	}
-	spin_unlock(&post_wait_lock);
-
-	printk(KERN_DEBUG "i2o_post_wait: Bogus reply!\n");
-}
-
-/*	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_issue_params(int cmd, struct i2o_controller *iop, int tid, 
-                void *oplist, int oplen, void *reslist, int reslen)
-{
-	u32 msg[9]; 
-	u32 *res32 = (u32*)reslist;
-	u32 *restmp = (u32*)reslist;
-	int len = 0;
-	int i = 0;
-	int wait_status;
-	u32 *opmem, *resmem;
-	dma_addr_t opmem_phys, resmem_phys;
-	
-	/* Get DMAable memory */
-	opmem = pci_alloc_consistent(iop->pdev, oplen, &opmem_phys);
-	if(opmem == NULL)
-		return -ENOMEM;
-	memcpy(opmem, oplist, oplen);
-	
-	resmem = pci_alloc_consistent(iop->pdev, reslen, &resmem_phys);
-	if(resmem == NULL)
-	{
-		pci_free_consistent(iop->pdev, oplen, opmem, opmem_phys);
-		return -ENOMEM;
-	}
-	
-	msg[0] = NINE_WORD_MSG_SIZE | SGL_OFFSET_5;
-	msg[1] = cmd << 24 | HOST_TID << 12 | tid; 
-	msg[3] = 0;
-	msg[4] = 0;
-	msg[5] = 0x54000000 | oplen;	/* OperationList */
-	msg[6] = opmem_phys;
-	msg[7] = 0xD0000000 | reslen;	/* ResultList */
-	msg[8] = resmem_phys;
-
-	wait_status = i2o_post_wait_mem(iop, msg, sizeof(msg), 10, opmem, resmem, opmem_phys, resmem_phys, oplen, reslen);
-	
-	/*
-	 *	This only looks like a memory leak - don't "fix" it.	
-	 */
-	if(wait_status == -ETIMEDOUT)
-		return wait_status;
-
-	memcpy(reslist, resmem, reslen);
-	pci_free_consistent(iop->pdev, reslen, resmem, resmem_phys);
-	pci_free_consistent(iop->pdev, oplen, opmem, opmem_phys);
-	
-	/* Query failed */
-	if(wait_status != 0)
-		return wait_status;		
-	/*
-	 * 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 scalar group value or a whole scalar group.
- */                  	
-int i2o_query_scalar(struct i2o_controller *iop, int tid, 
-                     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_issue_params(I2O_CMD_UTIL_PARAMS_GET, iop, tid, 
-		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_set_scalar(struct i2o_controller *iop, int tid, 
-		   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_issue_params(I2O_CMD_UTIL_PARAMS_SET, iop, tid, 
-				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_query_table(int oper, struct i2o_controller *iop, int tid, int group,
-		int fieldcount, void *ibuf, int ibuflen,
-		void *resblk, int reslen) 
-{
-	u16 *opblk;
-	int size;
-
-	opblk = kmalloc(10 + ibuflen, 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_issue_params(I2O_CMD_UTIL_PARAMS_GET,iop, tid, 
-				opblk, 10+ibuflen, resblk, reslen);
-
-	kfree(opblk);
-	if(size>reslen)
-		return reslen;
-	return size;
-}
-
-/*
- * 	Clear table group, i.e. delete all rows.
- */
-int i2o_clear_table(struct i2o_controller *iop, int tid, int group)
-{
-	u16 opblk[] = { 1, 0, I2O_PARAMS_TABLE_CLEAR, group };
-	u8  resblk[32]; /* min 8 bytes for result header */
-
-	return i2o_issue_params(I2O_CMD_UTIL_PARAMS_SET, iop, tid, 
-				opblk, sizeof(opblk), resblk, sizeof(resblk));
-}
-
-/*
- * 	Add a new row into a table group.
- *
- * 	if fieldcount==-1 then we add whole rows
- *		buf contains rowcount, keyvalues
- * 	else just specific fields are given, rest use defaults
- *  		buf contains fieldindexes, rowcount, keyvalues
- */	
-int i2o_row_add_table(struct i2o_controller *iop, int tid,
-		    int group, int fieldcount, void *buf, int buflen)
-{
-	u16 *opblk;
-	u8  resblk[32]; /* min 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_ROW_ADD;
-	opblk[3] = group;	
-	opblk[4] = fieldcount;
-	memcpy(opblk+5, buf, buflen);
-
-	size = i2o_issue_params(I2O_CMD_UTIL_PARAMS_SET, iop, tid, 
-				opblk, 10+buflen, resblk, sizeof(resblk));
-
-	kfree(opblk);
-	if(size>buflen)
-		return buflen;
-	return size;
-}
-
-
-/*
- * 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_lan_dsc(u16 detailed_status)
-{
-	static char *LAN_DSC[] = {	// Lan detailed status code strings
-		"SUCCESS",
-		"DEVICE_FAILURE",
-		"DESTINATION_NOT_FOUND",
-		"TRANSMIT_ERROR",
-		"TRANSMIT_ABORTED",
-		"RECEIVE_ERROR",
-		"RECEIVE_ABORTED",
-		"DMA_ERROR",
-		"BAD_PACKET_DETECTED",
-		"OUT_OF_MEMORY",
-		"BUCKET_OVERRUN",
-		"IOP_INTERNAL_ERROR",
-		"CANCELED",
-		"INVALID_TRANSACTION_CONTEXT",
-		"DEST_ADDRESS_DETECTED",
-		"DEST_ADDRESS_OMITTED",
-		"PARTIAL_PACKET_RETURNED",
-		"TEMP_SUSPENDED_STATE",	// last Lan detailed status code
-		"INVALID_REQUEST"	// general detailed status code
-	};
-
-	if (detailed_status > I2O_DSC_INVALID_REQUEST)
-		printk(" / %0#4x.\n", detailed_status);
-	else
-		printk(" / %s.\n", LAN_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);	
-	}
-}
-
-/*
- * Used for error reporting/debugging purposes
- */
-static void i2o_report_lan_cmd(u8 cmd)
-{
-	switch (cmd) {
-	case LAN_PACKET_SEND:
-		printk("LAN_PACKET_SEND, "); 
-		break;
-	case LAN_SDU_SEND:
-		printk("LAN_SDU_SEND, ");
-		break;
-	case LAN_RECEIVE_POST:
-		printk("LAN_RECEIVE_POST, ");
-		break;
-	case LAN_RESET:
-		printk("LAN_RESET, ");
-		break;
-	case LAN_SUSPEND:
-		printk("LAN_SUSPEND, ");
-		break;
-	default:
-		printk("Cmd = %0#2x, ",cmd);	
-	}	
-}
-
-/*
- * Used for error reporting/debugging purposes.
- * Report Cmd name, Request status, Detailed Status.
- */
-void i2o_report_status(const char *severity, const char *str, u32 *msg)
-{
-	u8 cmd = (msg[1]>>24)&0xFF;
-	u8 req_status = (msg[4]>>24)&0xFF;
-	u16 detailed_status = msg[4]&0xFFFF;
-	struct i2o_handler *h = i2o_handlers[msg[2] & (MAX_I2O_MODULES-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 if (h->class == I2O_CLASS_LAN && cmd >= 0x30 && cmd <= 0x3F)
-		i2o_report_lan_cmd(cmd);	// LAN 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 if (h->class == I2O_CLASS_LAN && cmd >= 0x30 && cmd <= 0x3F)
-		i2o_report_lan_dsc(detailed_status);
-	else
-		printk(" / DetailedStatus = %0#4x.\n", detailed_status); 
-}
-
-/* Used to dump a message to syslog during debugging */
-void i2o_dump_message(u32 *msg)
-{
-#ifdef DRIVERDEBUG
-	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 reboot/shutdown notification.
- *
- * - Call each OSM's reboot notifier (if one exists)
- * - Quiesce each IOP in the system
- *
- * Each IOP has to be quiesced before we can ensure that the system
- * can be properly shutdown as a transaction that has already been
- * acknowledged still needs to be placed in permanent store on the IOP.
- * The SysQuiesce causes the IOP to force all HDMs to complete their
- * transactions before returning, so only at that point is it safe
- * 
- */
-static int i2o_reboot_event(struct notifier_block *n, unsigned long code, void
-*p)
-{
-	int i = 0;
-	struct i2o_controller *c = NULL;
-
-	if(code != SYS_RESTART && code != SYS_HALT && code != SYS_POWER_OFF)
-		return NOTIFY_DONE;
-
-	printk(KERN_INFO "Shutting down I2O system.\n");
-	printk(KERN_INFO 
-		"   This could take a few minutes if there are many devices attached\n");
-
-	for(i = 0; i < MAX_I2O_MODULES; i++)
-	{
-		if(i2o_handlers[i] && i2o_handlers[i]->reboot_notify)
-			i2o_handlers[i]->reboot_notify();
-	}
-
-	for(c = i2o_controller_chain; c; c = c->next)
-	{
-		if(i2o_quiesce_controller(c))
-		{
-			printk(KERN_WARNING "i2o: Could not quiesce %s.\n"
-			       "Verify setup on next system power up.\n",
-			       c->name);
-		}
-	}
-
-	printk(KERN_INFO "I2O system down.\n");
-	return NOTIFY_DONE;
-}
-
-
-
-
-/**
- *	i2o_pci_dispose		-	Free bus specific resources
- *	@c: I2O controller
- *
- *	Disable interrupts and then free interrupt, I/O and mtrr resources 
- *	used by this controller. Called by the I2O core on unload.
- */
- 
-static void i2o_pci_dispose(struct i2o_controller *c)
-{
-	I2O_IRQ_WRITE32(c,0xFFFFFFFF);
-	if(c->irq > 0)
-		free_irq(c->irq, c);
-	iounmap(c->base_virt);
-	if(c->raptor)
-		iounmap(c->msg_virt);
-
-#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
-}
-
-/**
- *	i2o_pci_interrupt	-	Bus specific interrupt handler
- *	@irq: interrupt line
- *	@dev_id: cookie
- *
- *	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;
-	i2o_run_queue(c);
-	return IRQ_HANDLED;
-}	
-
-/**
- *	i2o_pci_install		-	Install a PCI i2o controller
- *	@dev: PCI device of the I2O controller
- *
- *	Install a PCI (or in theory AGP) i2o controller. Devices are
- *	initialized, configured and registered with the i2o core subsystem. Be
- *	very careful with ordering. There may be pending interrupts.
- *
- *	To Do: Add support for polled controllers
- */
-
-int __init i2o_pci_install(struct pci_dev *dev)
-{
-	struct i2o_controller *c=kmalloc(sizeof(struct i2o_controller),
-						GFP_KERNEL);
-	void *bar0_virt;
-	void *bar1_virt;
-	unsigned long bar0_phys = 0;
-	unsigned long bar1_phys = 0;
-	unsigned long bar0_size = 0;
-	unsigned long bar1_size = 0;
-	
-	int i;
-
-	if(c==NULL)
-	{
-		printk(KERN_ERR "i2o: Insufficient memory to add controller.\n");
-		return -ENOMEM;
-	}
-	memset(c, 0, sizeof(*c));
-
-	c->irq = -1;
-	c->dpt = 0;
-	c->raptor = 0;
-	c->short_req = 0;
-	c->pdev = dev;
-
-#if BITS_PER_LONG == 64
-	c->context_list_lock = SPIN_LOCK_UNLOCKED;
-#endif
-
-	/*
-	 *	Cards that fall apart if you hit them with large I/O
-	 *	loads...
-	 */
-	 
-	if(dev->vendor == PCI_VENDOR_ID_NCR && dev->device == 0x0630)
-	{
-		c->short_req = 1;
-		printk(KERN_INFO "I2O: Symbios FC920 workarounds activated.\n");
-	}
-
-	if(dev->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(dev->vendor == PCI_VENDOR_ID_DPT) {
-		c->dpt=1;
-		if(dev->device == 0xA511)
-			c->raptor=1;
-	}
-
-	for(i=0; i<6; i++)
-	{
-		/* Skip I/O spaces */
-		if(!(pci_resource_flags(dev, i) & IORESOURCE_IO))
-		{
-			if(!bar0_phys)
-			{
-				bar0_phys = pci_resource_start(dev, i);
-				bar0_size = pci_resource_len(dev, i);
-				if(!c->raptor)
-					break;
-			}
-			else
-			{
-				bar1_phys = pci_resource_start(dev, i);
-				bar1_size = pci_resource_len(dev, i);
-				break;
-			}
-		}
-	}
-
-	if(i==6)
-	{
-		printk(KERN_ERR "i2o: I2O controller has no memory regions defined.\n");
-		kfree(c);
-		return -EINVAL;
-	}
-
-
-	/* Map the I2O controller */
-	if(!c->raptor)
-		printk(KERN_INFO "i2o: PCI I2O controller at %08lX size=%ld\n", bar0_phys, bar0_size);
-	else
-		printk(KERN_INFO "i2o: PCI I2O controller\n    BAR0 at 0x%08lX size=%ld\n    BAR1 at 0x%08lX size=%ld\n", bar0_phys, bar0_size, bar1_phys, bar1_size);
-
-	bar0_virt = ioremap(bar0_phys, bar0_size);
-	if(bar0_virt==0)
-	{
-		printk(KERN_ERR "i2o: Unable to map controller.\n");
-		kfree(c);
-		return -EINVAL;
-	}
-
-	if(c->raptor)
-	{
-		bar1_virt = ioremap(bar1_phys, bar1_size);
-		if(bar1_virt==0)
-		{
-			printk(KERN_ERR "i2o: Unable to map controller.\n");
-			kfree(c);
-			iounmap(bar0_virt);
-			return -EINVAL;
-		}
-	} else {
-		bar1_virt = bar0_virt;
-		bar1_phys = bar0_phys;
-		bar1_size = bar0_size;
-	}
-
-	c->irq_mask = bar0_virt+0x34;
-	c->post_port = bar0_virt+0x40;
-	c->reply_port = bar0_virt+0x44;
-
-	c->base_phys = bar0_phys;
-	c->base_virt = bar0_virt;
-	c->msg_phys = bar1_phys;
-	c->msg_virt = bar1_virt;
-	
-	/* 
-	 * Enable Write Combining MTRR for IOP's memory region
-	 */
-#ifdef CONFIG_MTRR
-	c->mtrr_reg0 = mtrr_add(c->base_phys, bar0_size, MTRR_TYPE_WRCOMB, 1);
-	/*
-	 * 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.
-	 */
-	c->mtrr_reg1 = -1;
-	if(dev->vendor == PCI_VENDOR_ID_INTEL || dev->vendor == PCI_VENDOR_ID_DPT)
-	{
-		printk(KERN_INFO "I2O: MTRR workaround for Intel i960 processor\n"); 
-		c->mtrr_reg1 =	mtrr_add(c->base_phys, 65536, MTRR_TYPE_UNCACHABLE, 1);
-		if(c->mtrr_reg1< 0)
-		{
-			printk(KERN_INFO "i2o_pci: Error in setting MTRR_TYPE_UNCACHABLE\n");
-			mtrr_del(c->mtrr_reg0, c->msg_phys, bar1_size);
-			c->mtrr_reg0 = -1;
-		}
-	}
-	if(c->raptor)
-		c->mtrr_reg1 = mtrr_add(c->msg_phys, bar1_size, MTRR_TYPE_WRCOMB, 1);
-
-#endif
-
-	I2O_IRQ_WRITE32(c,0xFFFFFFFF);
-
-	i = i2o_install_controller(c);
-	
-	if(i<0)
-	{
-		printk(KERN_ERR "i2o: Unable to install controller.\n");
-		kfree(c);
-		iounmap(bar0_virt);
-		if(c->raptor)
-			iounmap(bar1_virt);
-		return i;
-	}
-
-	c->irq = dev->irq;
-	if(c->irq)
-	{
-		i=request_irq(dev->irq, i2o_pci_interrupt, SA_SHIRQ,
-			c->name, c);
-		if(i<0)
-		{
-			printk(KERN_ERR "%s: unable to allocate interrupt %d.\n",
-				c->name, dev->irq);
-			c->irq = -1;
-			i2o_delete_controller(c);
-			iounmap(bar0_virt);
-			if(c->raptor)
-				iounmap(bar1_virt);
-			return -EBUSY;
-		}
-	}
-
-	printk(KERN_INFO "%s: Installed at IRQ%d\n", c->name, dev->irq);
-	I2O_IRQ_WRITE32(c,0x0);
-	c->enabled = 1;
-	return 0;	
-}
-
-/**
- *	i2o_pci_scan	-	Scan the pci bus for controllers
- *	
- *	Scan the PCI devices on the system looking for any device which is a 
- *	memory of the Intelligent, I2O class. We attempt to set up each such device
- *	and register it with the core.
- *
- *	Returns the number of controllers registered
- *
- *	Note; Do not change this to a hot plug interface. I2O 1.5 itself
- *	does not support hot plugging.
- */
- 
-int __init i2o_pci_scan(void)
-{
-	struct pci_dev *dev = NULL;
-	int count=0;
-	
-	printk(KERN_INFO "i2o: Checking for PCI I2O controllers...\n");
-
-	while ((dev = pci_find_device(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL)
-	{
-		if((dev->class>>8)!=PCI_CLASS_INTELLIGENT_I2O &&
-		   (dev->vendor!=PCI_VENDOR_ID_DPT || dev->device!=0xA511))
-			continue;
-
-		if((dev->class>>8)==PCI_CLASS_INTELLIGENT_I2O &&
-		   (dev->class&0xFF)>1)
-		{
-			printk(KERN_INFO "i2o: I2O Controller found but does not support I2O 1.5 (skipping).\n");
-			continue;
-		}
-		if (pci_enable_device(dev))
-			continue;
-		printk(KERN_INFO "i2o: I2O controller on bus %d at %d.\n",
-			dev->bus->number, dev->devfn);
-		if(pci_set_dma_mask(dev, 0xffffffff))
-		{
-			printk(KERN_WARNING "I2O controller on bus %d at %d : No suitable DMA available\n", dev->bus->number, dev->devfn);
-		 	continue;
-		}
-		pci_set_master(dev);
-		if(i2o_pci_install(dev)==0)
-			count++;
-	}
-	if(count)
-		printk(KERN_INFO "i2o: %d I2O controller%s found and installed.\n", count,
-			count==1?"":"s");
-	return count?count:-ENODEV;
-}
-
-static int i2o_core_init(void)
-{
-	printk(KERN_INFO "I2O Core - (C) Copyright 1999 Red Hat Software\n");
-	if (i2o_install_handler(&i2o_core_handler) < 0)
-	{
-		printk(KERN_ERR "i2o_core: Unable to install core handler.\nI2O stack not loaded!");
-		return 0;
-	}
-
-	core_context = i2o_core_handler.context;
-
-	/*
-	 * Initialize event handling thread
-	 */	
-
-	init_MUTEX_LOCKED(&evt_sem);
-	evt_pid = kernel_thread(i2o_core_evt, &evt_reply, CLONE_SIGHAND);
-	if(evt_pid < 0)
-	{
-		printk(KERN_ERR "I2O: Could not create event handler kernel thread\n");
-		i2o_remove_handler(&i2o_core_handler);
-		return 0;
-	}
-	else
-		printk(KERN_INFO "I2O: Event thread created as pid %d\n", evt_pid);
-
-	i2o_pci_scan();
-	if(i2o_num_controllers)
-		i2o_sys_init();
-
-	register_reboot_notifier(&i2o_reboot_notifier);
-
-	return 0;
-}
-
-static void i2o_core_exit(void)
-{
-	int stat;
-
-	unregister_reboot_notifier(&i2o_reboot_notifier);
-
-	if(i2o_num_controllers)
-		i2o_sys_shutdown();
-
-	/*
-	 * If this is shutdown time, the thread has already been killed
-	 */
-	if(evt_running) {
-		printk("Terminating i2o threads...");
-		stat = kill_proc(evt_pid, SIGKILL, 1);
-		if(!stat) {
-			printk("waiting...\n");
-			wait_for_completion(&evt_dead);
-		}
-		printk("done.\n");
-	}
-	i2o_remove_handler(&i2o_core_handler);
-}
-
-module_init(i2o_core_init);
-module_exit(i2o_core_exit);
-
-MODULE_PARM(verbose, "i");
-MODULE_PARM_DESC(verbose, "Verbose diagnostics");
-
-MODULE_AUTHOR("Red Hat Software");
-MODULE_DESCRIPTION("I2O Core");
-MODULE_LICENSE("GPL");
-
-EXPORT_SYMBOL(i2o_controller_chain);
-EXPORT_SYMBOL(i2o_num_controllers);
-EXPORT_SYMBOL(i2o_find_controller);
-EXPORT_SYMBOL(i2o_unlock_controller);
-EXPORT_SYMBOL(i2o_status_get);
-EXPORT_SYMBOL(i2o_install_handler);
-EXPORT_SYMBOL(i2o_remove_handler);
-EXPORT_SYMBOL(i2o_install_controller);
-EXPORT_SYMBOL(i2o_delete_controller);
-EXPORT_SYMBOL(i2o_run_queue);
-EXPORT_SYMBOL(i2o_claim_device);
-EXPORT_SYMBOL(i2o_release_device);
-EXPORT_SYMBOL(i2o_device_notify_on);
-EXPORT_SYMBOL(i2o_device_notify_off);
-EXPORT_SYMBOL(i2o_post_this);
-EXPORT_SYMBOL(i2o_post_wait);
-EXPORT_SYMBOL(i2o_post_wait_mem);
-EXPORT_SYMBOL(i2o_query_scalar);
-EXPORT_SYMBOL(i2o_set_scalar);
-EXPORT_SYMBOL(i2o_query_table);
-EXPORT_SYMBOL(i2o_clear_table);
-EXPORT_SYMBOL(i2o_row_add_table);
-EXPORT_SYMBOL(i2o_issue_params);
-EXPORT_SYMBOL(i2o_event_register);
-EXPORT_SYMBOL(i2o_event_ack);
-EXPORT_SYMBOL(i2o_report_status);
-EXPORT_SYMBOL(i2o_dump_message);
-EXPORT_SYMBOL(i2o_get_class_name);
-EXPORT_SYMBOL(i2o_context_list_add);
-EXPORT_SYMBOL(i2o_context_list_get);
-EXPORT_SYMBOL(i2o_context_list_remove);
diff -Nru a/drivers/message/i2o/i2o_proc.c b/drivers/message/i2o/i2o_proc.c
--- a/drivers/message/i2o/i2o_proc.c	2004-10-18 14:56:33 -07:00
+++ b/drivers/message/i2o/i2o_proc.c	2004-10-18 14:56:33 -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-10-18 14:56:49 -07:00
+++ b/drivers/message/i2o/i2o_scsi.c	2004-10-18 14:56:49 -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-10-18 14:57:23 -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 NULL;
+};
+
+/**
+ *	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();
+	}
+
+#ifdef 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-10-18 14:57:22 -07:00
@@ -0,0 +1,528 @@
+/*
+ *	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 we know what card it is, set the size
+				 * correctly. Code is taken from dpt_i2o.c
+				 */
+				if(pdev->device == 0xa501) {
+					if(pdev->subsystem_device >= 0xc032 &&
+					   pdev->subsystem_device <= 0xc03b) {
+						if(c->base.len > 0x400000)
+							c->base.len = 0x400000;
+					} else {
+						if(c->base.len > 0x100000)
+							c->base.len = 0x100000;
+					}
+				}
+				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-10-18 14:56:33 -07:00
+++ b/drivers/misc/ibmasm/module.c	2004-10-18 14:56:33 -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/mmc/Kconfig b/drivers/mmc/Kconfig
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/drivers/mmc/Kconfig	2004-10-18 14:57:24 -07:00
@@ -0,0 +1,52 @@
+#
+# MMC subsystem configuration
+#
+
+menu "MMC/SD Card support"
+
+config MMC
+	tristate "MMC support"
+	help
+	  MMC is the "multi-media card" bus protocol.
+
+	  If you want MMC support, you should say Y here and also
+	  to the specific driver for your MMC interface.
+
+config MMC_DEBUG
+	bool "MMC debugging"
+	depends on MMC != n
+	help
+	  This is an option for use by developers; most people should
+	  say N here.  This enables MMC core and driver debugging.
+
+config MMC_BLOCK
+	tristate "MMC block device driver"
+	depends on MMC
+	default y
+	help
+	  Say Y here to enable the MMC block device driver support.
+	  This provides a block device driver, which you can use to
+	  mount the filesystem. Almost everyone wishing MMC support
+	  should say Y or M here.
+
+config MMC_ARMMMCI
+	tristate "ARM AMBA Multimedia Card Interface support"
+	depends on ARM_AMBA && MMC
+	help
+	  This selects the ARM(R) AMBA(R) PrimeCell Multimedia Card
+	  Interface (PL180 and PL181) support.  If you have an ARM(R)
+	  platform with a Multimedia Card slot, say Y or M here.
+
+	  If unsure, say N.
+
+config MMC_PXA
+	tristate "Intel PXA255 Multimedia Card Interface support"
+	depends on ARCH_PXA && MMC
+	help
+	  This selects the Intel(R) PXA(R) Multimedia card Interface.
+	  If you have a PXA(R) platform with a Multimedia Card slot,
+	  say Y or M here.
+
+	  If unsure, say N.
+
+endmenu
diff -Nru a/drivers/mmc/Makefile b/drivers/mmc/Makefile
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/drivers/mmc/Makefile	2004-10-18 14:57:23 -07:00
@@ -0,0 +1,21 @@
+#
+# Makefile for the kernel mmc device drivers.
+#
+
+#
+# Core
+#
+obj-$(CONFIG_MMC)		+= mmc_core.o
+
+#
+# Media drivers
+#
+obj-$(CONFIG_MMC_BLOCK)		+= mmc_block.o
+
+#
+# Host drivers
+#
+obj-$(CONFIG_MMC_ARMMMCI)	+= mmci.o
+obj-$(CONFIG_MMC_PXA)		+= pxamci.o
+
+mmc_core-y := mmc.o mmc_queue.o mmc_sysfs.o
diff -Nru a/drivers/mmc/mmc.c b/drivers/mmc/mmc.c
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/drivers/mmc/mmc.c	2004-10-18 14:57:23 -07:00
@@ -0,0 +1,913 @@
+/*
+ *  linux/drivers/mmc/mmc.c
+ *
+ *  Copyright (C) 2003-2004 Russell King, 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 version 2 as
+ * published by the Free Software Foundation.
+ */
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/completion.h>
+#include <linux/device.h>
+#include <linux/delay.h>
+#include <linux/pagemap.h>
+#include <linux/err.h>
+
+#include <linux/mmc/card.h>
+#include <linux/mmc/host.h>
+#include <linux/mmc/protocol.h>
+
+#include "mmc.h"
+
+#ifdef CONFIG_MMC_DEBUG
+#define DBG(x...)	printk(KERN_DEBUG x)
+#else
+#define DBG(x...)	do { } while (0)
+#endif
+
+#define CMD_RETRIES	3
+
+/*
+ * OCR Bit positions to 10s of Vdd mV.
+ */
+static const unsigned short mmc_ocr_bit_to_vdd[] = {
+	150,	155,	160,	165,	170,	180,	190,	200,
+	210,	220,	230,	240,	250,	260,	270,	280,
+	290,	300,	310,	320,	330,	340,	350,	360
+};
+
+static const unsigned int tran_exp[] = {
+	10000,		100000,		1000000,	10000000,
+	0,		0,		0,		0
+};
+
+static const unsigned char tran_mant[] = {
+	0,	10,	12,	13,	15,	20,	25,	30,
+	35,	40,	45,	50,	55,	60,	70,	80,
+};
+
+static const unsigned int tacc_exp[] = {
+	1,	10,	100,	1000,	10000,	100000,	1000000, 10000000,
+};
+
+static const unsigned int tacc_mant[] = {
+	0,	10,	12,	13,	15,	20,	25,	30,
+	35,	40,	45,	50,	55,	60,	70,	80,
+};
+
+
+/**
+ *	mmc_request_done - finish processing an MMC command
+ *	@host: MMC host which completed command
+ *	@mrq: MMC request which completed
+ *
+ *	MMC drivers should call this function when they have completed
+ *	their processing of a command.  This should be called before the
+ *	data part of the command has completed.
+ */
+void mmc_request_done(struct mmc_host *host, struct mmc_request *mrq)
+{
+	struct mmc_command *cmd = mrq->cmd;
+	int err = mrq->cmd->error;
+	DBG("MMC: req done (%02x): %d: %08x %08x %08x %08x\n", cmd->opcode,
+	    err, cmd->resp[0], cmd->resp[1], cmd->resp[2], cmd->resp[3]);
+
+	if (err && cmd->retries) {
+		cmd->retries--;
+		cmd->error = 0;
+		host->ops->request(host, mrq);
+	} else if (mrq->done) {
+		mrq->done(mrq);
+	}
+}
+
+EXPORT_SYMBOL(mmc_request_done);
+
+/**
+ *	mmc_start_request - start a command on a host
+ *	@host: MMC host to start command on
+ *	@mrq: MMC request to start
+ *
+ *	Queue a command on the specified host.  We expect the
+ *	caller to be holding the host lock with interrupts disabled.
+ */
+void
+mmc_start_request(struct mmc_host *host, struct mmc_request *mrq)
+{
+	DBG("MMC: starting cmd %02x arg %08x flags %08x\n",
+	    mrq->cmd->opcode, mrq->cmd->arg, mrq->cmd->flags);
+
+	WARN_ON(host->card_busy == NULL);
+
+	mrq->cmd->error = 0;
+	mrq->cmd->mrq = mrq;
+	if (mrq->data) {
+		mrq->cmd->data = mrq->data;
+		mrq->data->error = 0;
+		mrq->data->mrq = mrq;
+		if (mrq->stop) {
+			mrq->data->stop = mrq->stop;
+			mrq->stop->error = 0;
+			mrq->stop->mrq = mrq;
+		}
+	}
+	host->ops->request(host, mrq);
+}
+
+EXPORT_SYMBOL(mmc_start_request);
+
+static void mmc_wait_done(struct mmc_request *mrq)
+{
+	complete(mrq->done_data);
+}
+
+int mmc_wait_for_req(struct mmc_host *host, struct mmc_request *mrq)
+{
+	DECLARE_COMPLETION(complete);
+
+	mrq->done_data = &complete;
+	mrq->done = mmc_wait_done;
+
+	mmc_start_request(host, mrq);
+
+	wait_for_completion(&complete);
+
+	return 0;
+}
+
+EXPORT_SYMBOL(mmc_wait_for_req);
+
+/**
+ *	mmc_wait_for_cmd - start a command and wait for completion
+ *	@host: MMC host to start command
+ *	@cmd: MMC command to start
+ *	@retries: maximum number of retries
+ *
+ *	Start a new MMC command for a host, and wait for the command
+ *	to complete.  Return any error that occurred while the command
+ *	was executing.  Do not attempt to parse the response.
+ */
+int mmc_wait_for_cmd(struct mmc_host *host, struct mmc_command *cmd, int retries)
+{
+	struct mmc_request mrq;
+
+	BUG_ON(host->card_busy == NULL);
+
+	memset(&mrq, 0, sizeof(struct mmc_request));
+
+	memset(cmd->resp, 0, sizeof(cmd->resp));
+	cmd->retries = retries;
+
+	mrq.cmd = cmd;
+	cmd->data = NULL;
+
+	mmc_wait_for_req(host, &mrq);
+
+	return cmd->error;
+}
+
+EXPORT_SYMBOL(mmc_wait_for_cmd);
+
+
+
+/**
+ *	__mmc_claim_host - exclusively claim a host
+ *	@host: mmc host to claim
+ *	@card: mmc card to claim host for
+ *
+ *	Claim a host for a set of operations.  If a valid card
+ *	is passed and this wasn't the last card selected, select
+ *	the card before returning.
+ *
+ *	Note: you should use mmc_card_claim_host or mmc_claim_host.
+ */
+int __mmc_claim_host(struct mmc_host *host, struct mmc_card *card)
+{
+	DECLARE_WAITQUEUE(wait, current);
+	unsigned long flags;
+	int err = 0;
+
+	add_wait_queue(&host->wq, &wait);
+	spin_lock_irqsave(&host->lock, flags);
+	while (1) {
+		set_current_state(TASK_UNINTERRUPTIBLE);
+		if (host->card_busy == NULL)
+			break;
+		spin_unlock_irqrestore(&host->lock, flags);
+		schedule();
+		spin_lock_irqsave(&host->lock, flags);
+	}
+	set_current_state(TASK_RUNNING);
+	host->card_busy = card;
+	spin_unlock_irqrestore(&host->lock, flags);
+	remove_wait_queue(&host->wq, &wait);
+
+	if (card != (void *)-1 && host->card_selected != card) {
+		struct mmc_command cmd;
+
+		host->card_selected = card;
+
+		cmd.opcode = MMC_SELECT_CARD;
+		cmd.arg = card->rca << 16;
+		cmd.flags = MMC_RSP_R1;
+
+		err = mmc_wait_for_cmd(host, &cmd, CMD_RETRIES);
+	}
+
+	return err;
+}
+
+EXPORT_SYMBOL(__mmc_claim_host);
+
+/**
+ *	mmc_release_host - release a host
+ *	@host: mmc host to release
+ *
+ *	Release a MMC host, allowing others to claim the host
+ *	for their operations.
+ */
+void mmc_release_host(struct mmc_host *host)
+{
+	unsigned long flags;
+
+	BUG_ON(host->card_busy == NULL);
+
+	spin_lock_irqsave(&host->lock, flags);
+	host->card_busy = NULL;
+	spin_unlock_irqrestore(&host->lock, flags);
+
+	wake_up(&host->wq);
+}
+
+EXPORT_SYMBOL(mmc_release_host);
+
+/*
+ * Ensure that no card is selected.
+ */
+static void mmc_deselect_cards(struct mmc_host *host)
+{
+	struct mmc_command cmd;
+
+	if (host->card_selected) {
+		host->card_selected = NULL;
+
+		cmd.opcode = MMC_SELECT_CARD;
+		cmd.arg = 0;
+		cmd.flags = MMC_RSP_NONE;
+
+		mmc_wait_for_cmd(host, &cmd, 0);
+	}
+}
+
+
+static inline void mmc_delay(unsigned int ms)
+{
+	if (ms < HZ / 1000) {
+		yield();
+		mdelay(ms);
+	} else {
+		msleep_interruptible (ms);
+	}
+}
+
+/*
+ * Mask off any voltages we don't support and select
+ * the lowest voltage
+ */
+static u32 mmc_select_voltage(struct mmc_host *host, u32 ocr)
+{
+	int bit;
+
+	ocr &= host->ocr_avail;
+
+	bit = ffs(ocr);
+	if (bit) {
+		bit -= 1;
+
+		ocr = 3 << bit;
+
+		host->ios.vdd = bit;
+		host->ops->set_ios(host, &host->ios);
+	} else {
+		ocr = 0;
+	}
+
+	return ocr;
+}
+
+#define UNSTUFF_BITS(resp,start,size)					\
+	({								\
+		const u32 __mask = (1 << (size)) - 1;			\
+		const int __off = 3 - ((start) / 32);			\
+		const int __shft = (start) & 31;			\
+		u32 __res;						\
+									\
+		__res = resp[__off] >> __shft;				\
+		if ((size) + __shft >= 32)				\
+			__res |= resp[__off-1] << (32 - __shft);	\
+		__res & __mask;						\
+	})
+
+/*
+ * Given the decoded CSD structure, decode the raw CID to our CID structure.
+ */
+static void mmc_decode_cid(struct mmc_card *card)
+{
+	u32 *resp = card->raw_cid;
+
+	memset(&card->cid, 0, sizeof(struct mmc_cid));
+
+	/*
+	 * The selection of the format here is guesswork based upon
+	 * information people have sent to date.
+	 */
+	switch (card->csd.mmca_vsn) {
+	case 0: /* MMC v1.? */
+	case 1: /* MMC v1.4 */
+		card->cid.manfid	= UNSTUFF_BITS(resp, 104, 24);
+		card->cid.prod_name[0]	= UNSTUFF_BITS(resp, 96, 8);
+		card->cid.prod_name[1]	= UNSTUFF_BITS(resp, 88, 8);
+		card->cid.prod_name[2]	= UNSTUFF_BITS(resp, 80, 8);
+		card->cid.prod_name[3]	= UNSTUFF_BITS(resp, 72, 8);
+		card->cid.prod_name[4]	= UNSTUFF_BITS(resp, 64, 8);
+		card->cid.prod_name[5]	= UNSTUFF_BITS(resp, 56, 8);
+		card->cid.prod_name[6]	= UNSTUFF_BITS(resp, 48, 8);
+		card->cid.hwrev		= UNSTUFF_BITS(resp, 44, 4);
+		card->cid.fwrev		= UNSTUFF_BITS(resp, 40, 4);
+		card->cid.serial	= UNSTUFF_BITS(resp, 16, 24);
+		card->cid.month		= UNSTUFF_BITS(resp, 12, 4);
+		card->cid.year		= UNSTUFF_BITS(resp, 8, 4) + 1997;
+		break;
+
+	case 2: /* MMC v2.x ? */
+	case 3: /* MMC v3.x ? */
+		card->cid.manfid	= UNSTUFF_BITS(resp, 120, 8);
+		card->cid.oemid		= UNSTUFF_BITS(resp, 104, 16);
+		card->cid.prod_name[0]	= UNSTUFF_BITS(resp, 96, 8);
+		card->cid.prod_name[1]	= UNSTUFF_BITS(resp, 88, 8);
+		card->cid.prod_name[2]	= UNSTUFF_BITS(resp, 80, 8);
+		card->cid.prod_name[3]	= UNSTUFF_BITS(resp, 72, 8);
+		card->cid.prod_name[4]	= UNSTUFF_BITS(resp, 64, 8);
+		card->cid.prod_name[5]	= UNSTUFF_BITS(resp, 56, 8);
+		card->cid.serial	= UNSTUFF_BITS(resp, 16, 32);
+		card->cid.month		= UNSTUFF_BITS(resp, 12, 4);
+		card->cid.year		= UNSTUFF_BITS(resp, 8, 4) + 1997;
+		break;
+
+	default:
+		printk("%s: card has unknown MMCA version %d\n",
+			card->host->host_name, card->csd.mmca_vsn);
+		mmc_card_set_bad(card);
+		break;
+	}
+}
+
+/*
+ * Given a 128-bit response, decode to our card CSD structure.
+ */
+static void mmc_decode_csd(struct mmc_card *card)
+{
+	struct mmc_csd *csd = &card->csd;
+	unsigned int e, m, csd_struct;
+	u32 *resp = card->raw_csd;
+
+	/*
+	 * We only understand CSD structure v1.1 and v2.
+	 * v2 has extra information in bits 15, 11 and 10.
+	 */
+	csd_struct = UNSTUFF_BITS(resp, 126, 2);
+	if (csd_struct != 1 && csd_struct != 2) {
+		printk("%s: unrecognised CSD structure version %d\n",
+			card->host->host_name, csd_struct);
+		mmc_card_set_bad(card);
+		return;
+	}
+
+	csd->mmca_vsn	 = UNSTUFF_BITS(resp, 122, 4);
+	m = UNSTUFF_BITS(resp, 115, 4);
+	e = UNSTUFF_BITS(resp, 112, 3);
+	csd->tacc_ns	 = (tacc_exp[e] * tacc_mant[m] + 9) / 10;
+	csd->tacc_clks	 = UNSTUFF_BITS(resp, 104, 8) * 100;
+
+	m = UNSTUFF_BITS(resp, 99, 4);
+	e = UNSTUFF_BITS(resp, 96, 3);
+	csd->max_dtr	  = tran_exp[e] * tran_mant[m];
+	csd->cmdclass	  = UNSTUFF_BITS(resp, 84, 12);
+
+	e = UNSTUFF_BITS(resp, 47, 3);
+	m = UNSTUFF_BITS(resp, 62, 12);
+	csd->capacity	  = (1 + m) << (e + 2);
+
+	csd->read_blkbits = UNSTUFF_BITS(resp, 80, 4);
+}
+
+/*
+ * Locate a MMC card on this MMC host given a raw CID.
+ */
+static struct mmc_card *mmc_find_card(struct mmc_host *host, u32 *raw_cid)
+{
+	struct mmc_card *card;
+
+	list_for_each_entry(card, &host->cards, node) {
+		if (memcmp(card->raw_cid, raw_cid, sizeof(card->raw_cid)) == 0)
+			return card;
+	}
+	return NULL;
+}
+
+/*
+ * Allocate a new MMC card, and assign a unique RCA.
+ */
+static struct mmc_card *
+mmc_alloc_card(struct mmc_host *host, u32 *raw_cid, unsigned int *frca)
+{
+	struct mmc_card *card, *c;
+	unsigned int rca = *frca;
+
+	card = kmalloc(sizeof(struct mmc_card), GFP_KERNEL);
+	if (!card)
+		return ERR_PTR(-ENOMEM);
+
+	mmc_init_card(card, host);
+	memcpy(card->raw_cid, raw_cid, sizeof(card->raw_cid));
+
+ again:
+	list_for_each_entry(c, &host->cards, node)
+		if (c->rca == rca) {
+			rca++;
+			goto again;
+		}
+
+	card->rca = rca;
+
+	*frca = rca;
+
+	return card;
+}
+
+/*
+ * Tell attached cards to go to IDLE state
+ */
+static void mmc_idle_cards(struct mmc_host *host)
+{
+	struct mmc_command cmd;
+
+	cmd.opcode = MMC_GO_IDLE_STATE;
+	cmd.arg = 0;
+	cmd.flags = MMC_RSP_NONE;
+
+	mmc_wait_for_cmd(host, &cmd, 0);
+
+	mmc_delay(1);
+}
+
+/*
+ * Apply power to the MMC stack.
+ */
+static void mmc_power_up(struct mmc_host *host)
+{
+	int bit = fls(host->ocr_avail) - 1;
+
+	host->ios.vdd = bit;
+	host->ios.bus_mode = MMC_BUSMODE_OPENDRAIN;
+	host->ios.power_mode = MMC_POWER_UP;
+	host->ops->set_ios(host, &host->ios);
+
+	mmc_delay(1);
+
+	host->ios.clock = host->f_min;
+	host->ios.power_mode = MMC_POWER_ON;
+	host->ops->set_ios(host, &host->ios);
+
+	mmc_delay(2);
+}
+
+static void mmc_power_off(struct mmc_host *host)
+{
+	host->ios.clock = 0;
+	host->ios.vdd = 0;
+	host->ios.bus_mode = MMC_BUSMODE_OPENDRAIN;
+	host->ios.power_mode = MMC_POWER_OFF;
+	host->ops->set_ios(host, &host->ios);
+}
+
+static int mmc_send_op_cond(struct mmc_host *host, u32 ocr, u32 *rocr)
+{
+	struct mmc_command cmd;
+	int i, err = 0;
+
+	cmd.opcode = MMC_SEND_OP_COND;
+	cmd.arg = ocr;
+	cmd.flags = MMC_RSP_R3;
+
+	for (i = 100; i; i--) {
+		err = mmc_wait_for_cmd(host, &cmd, 0);
+		if (err != MMC_ERR_NONE)
+			break;
+
+		if (cmd.resp[0] & MMC_CARD_BUSY || ocr == 0)
+			break;
+
+		err = MMC_ERR_TIMEOUT;
+
+		mmc_delay(10);
+	}
+
+	if (rocr)
+		*rocr = cmd.resp[0];
+
+	return err;
+}
+
+/*
+ * Discover cards by requesting their CID.  If this command
+ * times out, it is not an error; there are no further cards
+ * to be discovered.  Add new cards to the list.
+ *
+ * Create a mmc_card entry for each discovered card, assigning
+ * it an RCA, and save the raw CID for decoding later.
+ */
+static void mmc_discover_cards(struct mmc_host *host)
+{
+	struct mmc_card *card;
+	unsigned int first_rca = 1, err;
+
+	while (1) {
+		struct mmc_command cmd;
+
+		cmd.opcode = MMC_ALL_SEND_CID;
+		cmd.arg = 0;
+		cmd.flags = MMC_RSP_R2;
+
+		err = mmc_wait_for_cmd(host, &cmd, CMD_RETRIES);
+		if (err == MMC_ERR_TIMEOUT) {
+			err = MMC_ERR_NONE;
+			break;
+		}
+		if (err != MMC_ERR_NONE) {
+			printk(KERN_ERR "%s: error requesting CID: %d\n",
+				host->host_name, err);
+			break;
+		}
+
+		card = mmc_find_card(host, cmd.resp);
+		if (!card) {
+			card = mmc_alloc_card(host, cmd.resp, &first_rca);
+			if (IS_ERR(card)) {
+				err = PTR_ERR(card);
+				break;
+			}
+			list_add(&card->node, &host->cards);
+		}
+
+		card->state &= ~MMC_STATE_DEAD;
+
+		cmd.opcode = MMC_SET_RELATIVE_ADDR;
+		cmd.arg = card->rca << 16;
+		cmd.flags = MMC_RSP_R1;
+
+		err = mmc_wait_for_cmd(host, &cmd, CMD_RETRIES);
+		if (err != MMC_ERR_NONE)
+			mmc_card_set_dead(card);
+	}
+}
+
+static void mmc_read_csds(struct mmc_host *host)
+{
+	struct mmc_card *card;
+
+	list_for_each_entry(card, &host->cards, node) {
+		struct mmc_command cmd;
+		int err;
+
+		if (card->state & (MMC_STATE_DEAD|MMC_STATE_PRESENT))
+			continue;
+
+		cmd.opcode = MMC_SEND_CSD;
+		cmd.arg = card->rca << 16;
+		cmd.flags = MMC_RSP_R2;
+
+		err = mmc_wait_for_cmd(host, &cmd, CMD_RETRIES);
+		if (err != MMC_ERR_NONE) {
+			mmc_card_set_dead(card);
+			continue;
+		}
+
+		memcpy(card->raw_csd, cmd.resp, sizeof(card->raw_csd));
+
+		mmc_decode_csd(card);
+		mmc_decode_cid(card);
+	}
+}
+
+static unsigned int mmc_calculate_clock(struct mmc_host *host)
+{
+	struct mmc_card *card;
+	unsigned int max_dtr = host->f_max;
+
+	list_for_each_entry(card, &host->cards, node)
+		if (!mmc_card_dead(card) && max_dtr > card->csd.max_dtr)
+			max_dtr = card->csd.max_dtr;
+
+	DBG("MMC: selected %d.%03dMHz transfer rate\n",
+	    max_dtr / 1000000, (max_dtr / 1000) % 1000);
+
+	return max_dtr;
+}
+
+/*
+ * Check whether cards we already know about are still present.
+ * We do this by requesting status, and checking whether a card
+ * responds.
+ *
+ * A request for status does not cause a state change in data
+ * transfer mode.
+ */
+static void mmc_check_cards(struct mmc_host *host)
+{
+	struct list_head *l, *n;
+
+	mmc_deselect_cards(host);
+
+	list_for_each_safe(l, n, &host->cards) {
+		struct mmc_card *card = mmc_list_to_card(l);
+		struct mmc_command cmd;
+		int err;
+
+		cmd.opcode = MMC_SEND_STATUS;
+		cmd.arg = card->rca << 16;
+		cmd.flags = MMC_RSP_R1;
+
+		err = mmc_wait_for_cmd(host, &cmd, CMD_RETRIES);
+		if (err == MMC_ERR_NONE)
+			continue;
+
+		mmc_card_set_dead(card);
+	}
+}
+
+static void mmc_setup(struct mmc_host *host)
+{
+	if (host->ios.power_mode != MMC_POWER_ON) {
+		int err;
+		u32 ocr;
+
+		mmc_power_up(host);
+		mmc_idle_cards(host);
+
+		err = mmc_send_op_cond(host, 0, &ocr);
+		if (err != MMC_ERR_NONE)
+			return;
+
+		host->ocr = mmc_select_voltage(host, ocr);
+
+		/*
+		 * Since we're changing the OCR value, we seem to
+		 * need to tell some cards to go back to the idle
+		 * state.  We wait 1ms to give cards time to
+		 * respond.
+		 */
+		if (host->ocr)
+			mmc_idle_cards(host);
+	} else {
+		host->ios.bus_mode = MMC_BUSMODE_OPENDRAIN;
+		host->ios.clock = host->f_min;
+		host->ops->set_ios(host, &host->ios);
+
+		/*
+		 * We should remember the OCR mask from the existing
+		 * cards, and detect the new cards OCR mask, combine
+		 * the two and re-select the VDD.  However, if we do
+		 * change VDD, we should do an idle, and then do a
+		 * full re-initialisation.  We would need to notify
+		 * drivers so that they can re-setup the cards as
+		 * well, while keeping their queues at bay.
+		 *
+		 * For the moment, we take the easy way out - if the
+		 * new cards don't like our currently selected VDD,
+		 * they drop off the bus.
+		 */
+	}
+
+	if (host->ocr == 0)
+		return;
+
+	/*
+	 * Send the selected OCR multiple times... until the cards
+	 * all get the idea that they should be ready for CMD2.
+	 * (My SanDisk card seems to need this.)
+	 */
+	mmc_send_op_cond(host, host->ocr, NULL);
+
+	mmc_discover_cards(host);
+
+	/*
+	 * Ok, now switch to push-pull mode.
+	 */
+	host->ios.bus_mode = MMC_BUSMODE_PUSHPULL;
+	host->ops->set_ios(host, &host->ios);
+
+	mmc_read_csds(host);
+}
+
+
+/**
+ *	mmc_detect_change - process change of state on a MMC socket
+ *	@host: host which changed state.
+ *
+ *	All we know is that card(s) have been inserted or removed
+ *	from the socket(s).  We don't know which socket or cards.
+ */
+void mmc_detect_change(struct mmc_host *host)
+{
+	schedule_work(&host->detect);
+}
+
+EXPORT_SYMBOL(mmc_detect_change);
+
+
+static void mmc_rescan(void *data)
+{
+	struct mmc_host *host = data;
+	struct list_head *l, *n;
+
+	mmc_claim_host(host);
+
+	if (host->ios.power_mode == MMC_POWER_ON)
+		mmc_check_cards(host);
+
+	mmc_setup(host);
+
+	if (!list_empty(&host->cards)) {
+		/*
+		 * (Re-)calculate the fastest clock rate which the
+		 * attached cards and the host support.
+		 */
+		host->ios.clock = mmc_calculate_clock(host);
+		host->ops->set_ios(host, &host->ios);
+	}
+
+	mmc_release_host(host);
+
+	list_for_each_safe(l, n, &host->cards) {
+		struct mmc_card *card = mmc_list_to_card(l);
+
+		/*
+		 * If this is a new and good card, register it.
+		 */
+		if (!mmc_card_present(card) && !mmc_card_dead(card)) {
+			if (mmc_register_card(card))
+				mmc_card_set_dead(card);
+			else
+				mmc_card_set_present(card);
+		}
+
+		/*
+		 * If this card is dead, destroy it.
+		 */
+		if (mmc_card_dead(card)) {
+			list_del(&card->node);
+			mmc_remove_card(card);
+		}
+	}
+
+	/*
+	 * If we discover that there are no cards on the
+	 * bus, turn off the clock and power down.
+	 */
+	if (list_empty(&host->cards))
+		mmc_power_off(host);
+}
+
+
+/**
+ *	mmc_alloc_host - initialise the per-host structure.
+ *	@extra: sizeof private data structure
+ *	@dev: pointer to host device model structure
+ *
+ *	Initialise the per-host structure.
+ */
+struct mmc_host *mmc_alloc_host(int extra, struct device *dev)
+{
+	struct mmc_host *host;
+
+	host = kmalloc(sizeof(struct mmc_host) + extra, GFP_KERNEL);
+	if (host) {
+		memset(host, 0, sizeof(struct mmc_host) + extra);
+
+		spin_lock_init(&host->lock);
+		init_waitqueue_head(&host->wq);
+		INIT_LIST_HEAD(&host->cards);
+		INIT_WORK(&host->detect, mmc_rescan, host);
+
+		host->dev = dev;
+
+		/*
+		 * By default, hosts do not support SGIO or large requests.
+		 * They have to set these according to their abilities.
+		 */
+		host->max_hw_segs = 1;
+		host->max_phys_segs = 1;
+		host->max_sectors = 1 << (PAGE_CACHE_SHIFT - 9);
+		host->max_seg_size = PAGE_CACHE_SIZE;
+	}
+
+	return host;
+}
+
+EXPORT_SYMBOL(mmc_alloc_host);
+
+/**
+ *	mmc_add_host - initialise host hardware
+ *	@host: mmc host
+ */
+int mmc_add_host(struct mmc_host *host)
+{
+	static unsigned int host_num;
+
+	snprintf(host->host_name, sizeof(host->host_name),
+		 "mmc%d", host_num++);
+
+	mmc_power_off(host);
+	mmc_detect_change(host);
+
+	return 0;
+}
+
+EXPORT_SYMBOL(mmc_add_host);
+
+/**
+ *	mmc_remove_host - remove host hardware
+ *	@host: mmc host
+ *
+ *	Unregister and remove all cards associated with this host,
+ *	and power down the MMC bus.
+ */
+void mmc_remove_host(struct mmc_host *host)
+{
+	struct list_head *l, *n;
+
+	list_for_each_safe(l, n, &host->cards) {
+		struct mmc_card *card = mmc_list_to_card(l);
+
+		mmc_remove_card(card);
+	}
+
+	mmc_power_off(host);
+}
+
+EXPORT_SYMBOL(mmc_remove_host);
+
+/**
+ *	mmc_free_host - free the host structure
+ *	@host: mmc host
+ *
+ *	Free the host once all references to it have been dropped.
+ */
+void mmc_free_host(struct mmc_host *host)
+{
+	flush_scheduled_work();
+	kfree(host);
+}
+
+EXPORT_SYMBOL(mmc_free_host);
+
+#ifdef CONFIG_PM
+
+/**
+ *	mmc_suspend_host - suspend a host
+ *	@host: mmc host
+ *	@state: suspend mode (PM_SUSPEND_xxx)
+ */
+int mmc_suspend_host(struct mmc_host *host, u32 state)
+{
+	mmc_claim_host(host);
+	mmc_deselect_cards(host);
+	mmc_power_off(host);
+	mmc_release_host(host);
+
+	return 0;
+}
+
+EXPORT_SYMBOL(mmc_suspend_host);
+
+/**
+ *	mmc_resume_host - resume a previously suspended host
+ *	@host: mmc host
+ */
+int mmc_resume_host(struct mmc_host *host)
+{
+	mmc_detect_change(host);
+
+	return 0;
+}
+
+EXPORT_SYMBOL(mmc_resume_host);
+
+#endif
+
+MODULE_LICENSE("GPL");
diff -Nru a/drivers/mmc/mmc.h b/drivers/mmc/mmc.h
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/drivers/mmc/mmc.h	2004-10-18 14:57:22 -07:00
@@ -0,0 +1,16 @@
+/*
+ *  linux/drivers/mmc/mmc.h
+ *
+ *  Copyright (C) 2003 Russell King, 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 version 2 as
+ * published by the Free Software Foundation.
+ */
+#ifndef _MMC_H
+#define _MMC_H
+/* core-internal functions */
+void mmc_init_card(struct mmc_card *card, struct mmc_host *host);
+int mmc_register_card(struct mmc_card *card);
+void mmc_remove_card(struct mmc_card *card);
+#endif
diff -Nru a/drivers/mmc/mmc_block.c b/drivers/mmc/mmc_block.c
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/drivers/mmc/mmc_block.c	2004-10-18 14:57:24 -07:00
@@ -0,0 +1,495 @@
+/*
+ * Block driver for media (i.e., flash cards)
+ *
+ * Copyright 2002 Hewlett-Packard Company
+ *
+ * Use consistent with the GNU GPL is permitted,
+ * provided that this copyright notice is
+ * preserved in its entirety in all copies and derived works.
+ *
+ * HEWLETT-PACKARD COMPANY MAKES NO WARRANTIES, EXPRESSED OR IMPLIED,
+ * AS TO THE USEFULNESS OR CORRECTNESS OF THIS CODE OR ITS
+ * FITNESS FOR ANY PARTICULAR PURPOSE.
+ *
+ * Many thanks to Alessandro Rubini and Jonathan Corbet!
+ *
+ * Author:  Andrew Christian
+ *          28 May 2002
+ */
+#include <linux/moduleparam.h>
+#include <linux/module.h>
+#include <linux/init.h>
+
+#include <linux/sched.h>
+#include <linux/kernel.h>
+#include <linux/fs.h>
+#include <linux/errno.h>
+#include <linux/hdreg.h>
+#include <linux/kdev_t.h>
+#include <linux/blkdev.h>
+#include <linux/devfs_fs_kernel.h>
+
+#include <linux/mmc/card.h>
+#include <linux/mmc/protocol.h>
+
+#include <asm/system.h>
+#include <asm/uaccess.h>
+
+#include "mmc_queue.h"
+
+/*
+ * max 8 partitions per card
+ */
+#define MMC_SHIFT	3
+
+static int major;
+
+/*
+ * There is one mmc_blk_data per slot.
+ */
+struct mmc_blk_data {
+	spinlock_t	lock;
+	struct gendisk	*disk;
+	struct mmc_queue queue;
+
+	unsigned int	usage;
+	unsigned int	block_bits;
+};
+
+static DECLARE_MUTEX(open_lock);
+
+static struct mmc_blk_data *mmc_blk_get(struct gendisk *disk)
+{
+	struct mmc_blk_data *md;
+
+	down(&open_lock);
+	md = disk->private_data;
+	if (md && md->usage == 0)
+		md = NULL;
+	if (md)
+		md->usage++;
+	up(&open_lock);
+
+	return md;
+}
+
+static void mmc_blk_put(struct mmc_blk_data *md)
+{
+	down(&open_lock);
+	md->usage--;
+	if (md->usage == 0) {
+		put_disk(md->disk);
+		mmc_cleanup_queue(&md->queue);
+		kfree(md);
+	}
+	up(&open_lock);
+}
+
+static int mmc_blk_open(struct inode *inode, struct file *filp)
+{
+	struct mmc_blk_data *md;
+	int ret = -ENXIO;
+
+	md = mmc_blk_get(inode->i_bdev->bd_disk);
+	if (md) {
+		if (md->usage == 2)
+			check_disk_change(inode->i_bdev);
+		ret = 0;
+	}
+
+	return ret;
+}
+
+static int mmc_blk_release(struct inode *inode, struct file *filp)
+{
+	struct mmc_blk_data *md = inode->i_bdev->bd_disk->private_data;
+
+	mmc_blk_put(md);
+	return 0;
+}
+
+static int
+mmc_blk_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg)
+{
+	struct block_device *bdev = inode->i_bdev;
+
+	if (cmd == HDIO_GETGEO) {
+		struct hd_geometry geo;
+
+		memset(&geo, 0, sizeof(struct hd_geometry));
+
+		geo.cylinders	= get_capacity(bdev->bd_disk) / (4 * 16);
+		geo.heads	= 4;
+		geo.sectors	= 16;
+		geo.start	= get_start_sect(bdev);
+
+		return copy_to_user((void __user *)arg, &geo, sizeof(geo))
+			? -EFAULT : 0;
+	}
+
+	return -ENOTTY;
+}
+
+static struct block_device_operations mmc_bdops = {
+	.open			= mmc_blk_open,
+	.release		= mmc_blk_release,
+	.ioctl			= mmc_blk_ioctl,
+	.owner			= THIS_MODULE,
+};
+
+struct mmc_blk_request {
+	struct mmc_request	mrq;
+	struct mmc_command	cmd;
+	struct mmc_command	stop;
+	struct mmc_data		data;
+};
+
+static int mmc_blk_prep_rq(struct mmc_queue *mq, struct request *req)
+{
+	struct mmc_blk_data *md = mq->data;
+	int stat = BLKPREP_OK;
+
+	/*
+	 * If we have no device, we haven't finished initialising.
+	 */
+	if (!md || !mq->card) {
+		printk(KERN_ERR "%s: killing request - no device/host\n",
+		       req->rq_disk->disk_name);
+		stat = BLKPREP_KILL;
+	}
+
+	return stat;
+}
+
+static int mmc_blk_issue_rq(struct mmc_queue *mq, struct request *req)
+{
+	struct mmc_blk_data *md = mq->data;
+	struct mmc_card *card = md->queue.card;
+	int ret;
+
+	if (mmc_card_claim_host(card))
+		goto cmd_err;
+
+	do {
+		struct mmc_blk_request brq;
+		struct mmc_command cmd;
+
+		memset(&brq, 0, sizeof(struct mmc_blk_request));
+		brq.mrq.cmd = &brq.cmd;
+		brq.mrq.data = &brq.data;
+
+		brq.cmd.arg = req->sector << 9;
+		brq.cmd.flags = MMC_RSP_R1;
+		brq.data.req = req;
+		brq.data.timeout_ns = card->csd.tacc_ns * 10;
+		brq.data.timeout_clks = card->csd.tacc_clks * 10;
+		brq.data.blksz_bits = md->block_bits;
+		brq.data.blocks = req->nr_sectors >> (md->block_bits - 9);
+		brq.stop.opcode = MMC_STOP_TRANSMISSION;
+		brq.stop.arg = 0;
+		brq.stop.flags = MMC_RSP_R1B;
+
+		if (rq_data_dir(req) == READ) {
+			brq.cmd.opcode = brq.data.blocks > 1 ? MMC_READ_MULTIPLE_BLOCK : MMC_READ_SINGLE_BLOCK;
+			brq.data.flags |= MMC_DATA_READ;
+		} else {
+			brq.cmd.opcode = MMC_WRITE_BLOCK;
+			brq.cmd.flags = MMC_RSP_R1B;
+			brq.data.flags |= MMC_DATA_WRITE;
+			brq.data.blocks = 1;
+		}
+		brq.mrq.stop = brq.data.blocks > 1 ? &brq.stop : NULL;
+
+		mmc_wait_for_req(card->host, &brq.mrq);
+		if (brq.cmd.error) {
+			printk(KERN_ERR "%s: error %d sending read/write command\n",
+			       req->rq_disk->disk_name, brq.cmd.error);
+			goto cmd_err;
+		}
+
+		if (brq.data.error) {
+			printk(KERN_ERR "%s: error %d transferring data\n",
+			       req->rq_disk->disk_name, brq.data.error);
+			goto cmd_err;
+		}
+
+		if (brq.stop.error) {
+			printk(KERN_ERR "%s: error %d sending stop command\n",
+			       req->rq_disk->disk_name, brq.stop.error);
+			goto cmd_err;
+		}
+
+		do {
+			int err;
+
+			cmd.opcode = MMC_SEND_STATUS;
+			cmd.arg = card->rca << 16;
+			cmd.flags = MMC_RSP_R1;
+			err = mmc_wait_for_cmd(card->host, &cmd, 5);
+			if (err) {
+				printk(KERN_ERR "%s: error %d requesting status\n",
+				       req->rq_disk->disk_name, err);
+				goto cmd_err;
+			}
+		} while (!(cmd.resp[0] & R1_READY_FOR_DATA));
+
+#if 0
+		if (cmd.resp[0] & ~0x00000900)
+			printk(KERN_ERR "%s: status = %08x\n",
+			       req->rq_disk->disk_name, cmd.resp[0]);
+		if (mmc_decode_status(cmd.resp))
+			goto cmd_err;
+#endif
+
+		/*
+		 * A block was successfully transferred.
+		 */
+		spin_lock_irq(&md->lock);
+		ret = end_that_request_chunk(req, 1, brq.data.bytes_xfered);
+		if (!ret) {
+			/*
+			 * The whole request completed successfully.
+			 */
+			add_disk_randomness(req->rq_disk);
+			blkdev_dequeue_request(req);
+			end_that_request_last(req);
+		}
+		spin_unlock_irq(&md->lock);
+	} while (ret);
+
+	mmc_card_release_host(card);
+
+	return 1;
+
+ cmd_err:
+	mmc_card_release_host(card);
+
+	/*
+	 * This is a little draconian, but until we get proper
+	 * error handling sorted out here, its the best we can
+	 * do - especially as some hosts have no idea how much
+	 * data was transferred before the error occurred.
+	 */
+	spin_lock_irq(&md->lock);
+	do {
+		ret = end_that_request_chunk(req, 0,
+				req->current_nr_sectors << 9);
+	} while (ret);
+
+	add_disk_randomness(req->rq_disk);
+	blkdev_dequeue_request(req);
+	end_that_request_last(req);
+	spin_unlock_irq(&md->lock);
+
+	return 0;
+}
+
+#define MMC_NUM_MINORS	(256 >> MMC_SHIFT)
+
+static unsigned long dev_use[MMC_NUM_MINORS/(8*sizeof(unsigned long))];
+
+static struct mmc_blk_data *mmc_blk_alloc(struct mmc_card *card)
+{
+	struct mmc_blk_data *md;
+	int devidx, ret;
+
+	devidx = find_first_zero_bit(dev_use, MMC_NUM_MINORS);
+	if (devidx >= MMC_NUM_MINORS)
+		return ERR_PTR(-ENOSPC);
+	__set_bit(devidx, dev_use);
+
+	md = kmalloc(sizeof(struct mmc_blk_data), GFP_KERNEL);
+	if (md) {
+		memset(md, 0, sizeof(struct mmc_blk_data));
+
+		md->disk = alloc_disk(1 << MMC_SHIFT);
+		if (md->disk == NULL) {
+			kfree(md);
+			md = ERR_PTR(-ENOMEM);
+			goto out;
+		}
+
+		spin_lock_init(&md->lock);
+		md->usage = 1;
+
+		ret = mmc_init_queue(&md->queue, card, &md->lock);
+		if (ret) {
+			put_disk(md->disk);
+			kfree(md);
+			md = ERR_PTR(ret);
+			goto out;
+		}
+		md->queue.prep_fn = mmc_blk_prep_rq;
+		md->queue.issue_fn = mmc_blk_issue_rq;
+		md->queue.data = md;
+
+		md->disk->major	= major;
+		md->disk->first_minor = devidx << MMC_SHIFT;
+		md->disk->fops = &mmc_bdops;
+		md->disk->private_data = md;
+		md->disk->queue = md->queue.queue;
+		md->disk->driverfs_dev = &card->dev;
+
+		sprintf(md->disk->disk_name, "mmcblk%d", devidx);
+		sprintf(md->disk->devfs_name, "mmc/blk%d", devidx);
+
+		md->block_bits = card->csd.read_blkbits;
+
+		blk_queue_hardsect_size(md->queue.queue, 1 << md->block_bits);
+		set_capacity(md->disk, card->csd.capacity);
+	}
+ out:
+	return md;
+}
+
+static int
+mmc_blk_set_blksize(struct mmc_blk_data *md, struct mmc_card *card)
+{
+	struct mmc_command cmd;
+	int err;
+
+	mmc_card_claim_host(card);
+	cmd.opcode = MMC_SET_BLOCKLEN;
+	cmd.arg = 1 << card->csd.read_blkbits;
+	cmd.flags = MMC_RSP_R1;
+	err = mmc_wait_for_cmd(card->host, &cmd, 5);
+	mmc_card_release_host(card);
+
+	if (err) {
+		printk(KERN_ERR "%s: unable to set block size to %d: %d\n",
+			md->disk->disk_name, cmd.arg, err);
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static int mmc_blk_probe(struct mmc_card *card)
+{
+	struct mmc_blk_data *md;
+	int err;
+
+	if (card->csd.cmdclass & ~0x1ff)
+		return -ENODEV;
+
+	if (card->csd.read_blkbits < 9) {
+		printk(KERN_WARNING "%s: read blocksize too small (%u)\n",
+			mmc_card_id(card), 1 << card->csd.read_blkbits);
+		return -ENODEV;
+	}
+
+	md = mmc_blk_alloc(card);
+	if (IS_ERR(md))
+		return PTR_ERR(md);
+
+	err = mmc_blk_set_blksize(md, card);
+	if (err)
+		goto out;
+
+	printk(KERN_INFO "%s: %s %s %dKiB\n",
+		md->disk->disk_name, mmc_card_id(card), mmc_card_name(card),
+		(card->csd.capacity << card->csd.read_blkbits) / 1024);
+
+	mmc_set_drvdata(card, md);
+	add_disk(md->disk);
+	return 0;
+
+ out:
+	mmc_blk_put(md);
+
+	return err;
+}
+
+static void mmc_blk_remove(struct mmc_card *card)
+{
+	struct mmc_blk_data *md = mmc_get_drvdata(card);
+
+	if (md) {
+		int devidx;
+
+		del_gendisk(md->disk);
+
+		/*
+		 * I think this is needed.
+		 */
+		md->disk->queue = NULL;
+
+		devidx = md->disk->first_minor >> MMC_SHIFT;
+		__clear_bit(devidx, dev_use);
+
+		mmc_blk_put(md);
+	}
+	mmc_set_drvdata(card, NULL);
+}
+
+#ifdef CONFIG_PM
+static int mmc_blk_suspend(struct mmc_card *card, u32 state)
+{
+	struct mmc_blk_data *md = mmc_get_drvdata(card);
+
+	if (md) {
+		mmc_queue_suspend(&md->queue);
+	}
+	return 0;
+}
+
+static int mmc_blk_resume(struct mmc_card *card)
+{
+	struct mmc_blk_data *md = mmc_get_drvdata(card);
+
+	if (md) {
+		mmc_blk_set_blksize(md, card);
+		mmc_queue_resume(&md->queue);
+	}
+	return 0;
+}
+#else
+#define	mmc_blk_suspend	NULL
+#define mmc_blk_resume	NULL
+#endif
+
+static struct mmc_driver mmc_driver = {
+	.drv		= {
+		.name	= "mmcblk",
+	},
+	.probe		= mmc_blk_probe,
+	.remove		= mmc_blk_remove,
+	.suspend	= mmc_blk_suspend,
+	.resume		= mmc_blk_resume,
+};
+
+static int __init mmc_blk_init(void)
+{
+	int res = -ENOMEM;
+
+	res = register_blkdev(major, "mmc");
+	if (res < 0) {
+		printk(KERN_WARNING "Unable to get major %d for MMC media: %d\n",
+		       major, res);
+		goto out;
+	}
+	if (major == 0)
+		major = res;
+
+	devfs_mk_dir("mmc");
+	return mmc_register_driver(&mmc_driver);
+
+ out:
+	return res;
+}
+
+static void __exit mmc_blk_exit(void)
+{
+	mmc_unregister_driver(&mmc_driver);
+	devfs_remove("mmc");
+	unregister_blkdev(major, "mmc");
+}
+
+module_init(mmc_blk_init);
+module_exit(mmc_blk_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("Multimedia Card (MMC) block device driver");
+
+module_param(major, int, 0444);
+MODULE_PARM_DESC(major, "specify the major device number for MMC block driver");
diff -Nru a/drivers/mmc/mmc_queue.c b/drivers/mmc/mmc_queue.c
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/drivers/mmc/mmc_queue.c	2004-10-18 14:57:23 -07:00
@@ -0,0 +1,222 @@
+/*
+ *  linux/drivers/mmc/mmc_queue.c
+ *
+ *  Copyright (C) 2003 Russell King, 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 version 2 as
+ * published by the Free Software Foundation.
+ *
+ */
+#include <linux/module.h>
+#include <linux/blkdev.h>
+
+#include <linux/mmc/card.h>
+#include <linux/mmc/host.h>
+#include "mmc_queue.h"
+
+#define MMC_QUEUE_EXIT		(1 << 0)
+#define MMC_QUEUE_SUSPENDED	(1 << 1)
+
+/*
+ * Prepare a MMC request.  Essentially, this means passing the
+ * preparation off to the media driver.  The media driver will
+ * create a mmc_io_request in req->special.
+ */
+static int mmc_prep_request(struct request_queue *q, struct request *req)
+{
+	struct mmc_queue *mq = q->queuedata;
+	int ret = BLKPREP_KILL;
+
+	if (req->flags & REQ_SPECIAL) {
+		/*
+		 * Special commands already have the command
+		 * blocks already setup in req->special.
+		 */
+		BUG_ON(!req->special);
+
+		ret = BLKPREP_OK;
+	} else if (req->flags & (REQ_CMD | REQ_BLOCK_PC)) {
+		/*
+		 * Block I/O requests need translating according
+		 * to the protocol.
+		 */
+		ret = mq->prep_fn(mq, req);
+	} else {
+		/*
+		 * Everything else is invalid.
+		 */
+		blk_dump_rq_flags(req, "MMC bad request");
+	}
+
+	if (ret == BLKPREP_OK)
+		req->flags |= REQ_DONTPREP;
+
+	return ret;
+}
+
+static int mmc_queue_thread(void *d)
+{
+	struct mmc_queue *mq = d;
+	struct request_queue *q = mq->queue;
+	DECLARE_WAITQUEUE(wait, current);
+
+	/*
+	 * Set iothread to ensure that we aren't put to sleep by
+	 * the process freezing.  We handle suspension ourselves.
+	 */
+	current->flags |= PF_MEMALLOC|PF_NOFREEZE;
+
+	daemonize("mmcqd");
+
+	complete(&mq->thread_complete);
+
+	down(&mq->thread_sem);
+	add_wait_queue(&mq->thread_wq, &wait);
+	do {
+		struct request *req = NULL;
+
+		spin_lock_irq(q->queue_lock);
+		set_current_state(TASK_INTERRUPTIBLE);
+		if (!blk_queue_plugged(q))
+			mq->req = req = elv_next_request(q);
+		spin_unlock(q->queue_lock);
+
+		if (!req) {
+			if (mq->flags & MMC_QUEUE_EXIT)
+				break;
+			up(&mq->thread_sem);
+			schedule();
+			down(&mq->thread_sem);
+			continue;
+		}
+		set_current_state(TASK_RUNNING);
+
+		mq->issue_fn(mq, req);
+	} while (1);
+	remove_wait_queue(&mq->thread_wq, &wait);
+	up(&mq->thread_sem);
+
+	complete_and_exit(&mq->thread_complete, 0);
+	return 0;
+}
+
+/*
+ * Generic MMC request handler.  This is called for any queue on a
+ * particular host.  When the host is not busy, we look for a request
+ * on any queue on this host, and attempt to issue it.  This may
+ * not be the queue we were asked to process.
+ */
+static void mmc_request(request_queue_t *q)
+{
+	struct mmc_queue *mq = q->queuedata;
+
+	if (!mq->req)
+		wake_up(&mq->thread_wq);
+}
+
+/**
+ * mmc_init_queue - initialise a queue structure.
+ * @mq: mmc queue
+ * @card: mmc card to attach this queue
+ * @lock: queue lock
+ *
+ * Initialise a MMC card request queue.
+ */
+int mmc_init_queue(struct mmc_queue *mq, struct mmc_card *card, spinlock_t *lock)
+{
+	struct mmc_host *host = card->host;
+	u64 limit = BLK_BOUNCE_HIGH;
+	int ret;
+
+	if (host->dev->dma_mask && *host->dev->dma_mask)
+		limit = *host->dev->dma_mask;
+
+	mq->card = card;
+	mq->queue = blk_init_queue(mmc_request, lock);
+	if (!mq->queue)
+		return -ENOMEM;
+
+	blk_queue_prep_rq(mq->queue, mmc_prep_request);
+	blk_queue_bounce_limit(mq->queue, limit);
+	blk_queue_max_sectors(mq->queue, host->max_sectors);
+	blk_queue_max_phys_segments(mq->queue, host->max_phys_segs);
+	blk_queue_max_hw_segments(mq->queue, host->max_hw_segs);
+	blk_queue_max_segment_size(mq->queue, host->max_seg_size);
+
+	mq->queue->queuedata = mq;
+	mq->req = NULL;
+
+	init_completion(&mq->thread_complete);
+	init_waitqueue_head(&mq->thread_wq);
+	init_MUTEX(&mq->thread_sem);
+
+	ret = kernel_thread(mmc_queue_thread, mq, CLONE_KERNEL);
+	if (ret < 0) {
+		blk_cleanup_queue(mq->queue);
+	} else {
+		wait_for_completion(&mq->thread_complete);
+		init_completion(&mq->thread_complete);
+		ret = 0;
+	}
+
+	return ret;
+}
+EXPORT_SYMBOL(mmc_init_queue);
+
+void mmc_cleanup_queue(struct mmc_queue *mq)
+{
+	mq->flags |= MMC_QUEUE_EXIT;
+	wake_up(&mq->thread_wq);
+	wait_for_completion(&mq->thread_complete);
+	blk_cleanup_queue(mq->queue);
+
+	mq->card = NULL;
+}
+EXPORT_SYMBOL(mmc_cleanup_queue);
+
+/**
+ * mmc_queue_suspend - suspend a MMC request queue
+ * @mq: MMC queue to suspend
+ *
+ * Stop the block request queue, and wait for our thread to
+ * complete any outstanding requests.  This ensures that we
+ * won't suspend while a request is being processed.
+ */
+void mmc_queue_suspend(struct mmc_queue *mq)
+{
+	request_queue_t *q = mq->queue;
+	unsigned long flags;
+
+	if (!(mq->flags & MMC_QUEUE_SUSPENDED)) {
+		mq->flags |= MMC_QUEUE_SUSPENDED;
+
+		spin_lock_irqsave(q->queue_lock, flags);
+		blk_stop_queue(q);
+		spin_unlock_irqrestore(q->queue_lock, flags);
+
+		down(&mq->thread_sem);
+	}
+}
+EXPORT_SYMBOL(mmc_queue_suspend);
+
+/**
+ * mmc_queue_resume - resume a previously suspended MMC request queue
+ * @mq: MMC queue to resume
+ */
+void mmc_queue_resume(struct mmc_queue *mq)
+{
+	request_queue_t *q = mq->queue;
+	unsigned long flags;
+
+	if (mq->flags & MMC_QUEUE_SUSPENDED) {
+		mq->flags &= ~MMC_QUEUE_SUSPENDED;
+
+		up(&mq->thread_sem);
+
+		spin_lock_irqsave(q->queue_lock, flags);
+		blk_start_queue(q);
+		spin_unlock_irqrestore(q->queue_lock, flags);
+	}
+}
+EXPORT_SYMBOL(mmc_queue_resume);
diff -Nru a/drivers/mmc/mmc_queue.h b/drivers/mmc/mmc_queue.h
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/drivers/mmc/mmc_queue.h	2004-10-18 14:57:21 -07:00
@@ -0,0 +1,32 @@
+#ifndef MMC_QUEUE_H
+#define MMC_QUEUE_H
+
+struct request;
+struct task_struct;
+
+struct mmc_queue {
+	struct mmc_card		*card;
+	struct completion	thread_complete;
+	wait_queue_head_t	thread_wq;
+	struct semaphore	thread_sem;
+	unsigned int		flags;
+	struct request		*req;
+	int			(*prep_fn)(struct mmc_queue *, struct request *);
+	int			(*issue_fn)(struct mmc_queue *, struct request *);
+	void			*data;
+	struct request_queue	*queue;
+};
+
+struct mmc_io_request {
+	struct request		*rq;
+	int			num;
+	struct mmc_command	selcmd;		/* mmc_queue private */
+	struct mmc_command	cmd[4];		/* max 4 commands */
+};
+
+extern int mmc_init_queue(struct mmc_queue *, struct mmc_card *, spinlock_t *);
+extern void mmc_cleanup_queue(struct mmc_queue *);
+extern void mmc_queue_suspend(struct mmc_queue *);
+extern void mmc_queue_resume(struct mmc_queue *);
+
+#endif
diff -Nru a/drivers/mmc/mmc_sysfs.c b/drivers/mmc/mmc_sysfs.c
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/drivers/mmc/mmc_sysfs.c	2004-10-18 14:57:23 -07:00
@@ -0,0 +1,241 @@
+/*
+ *  linux/drivers/mmc/mmc_sysfs.c
+ *
+ *  Copyright (C) 2003 Russell King, 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 version 2 as
+ * published by the Free Software Foundation.
+ *
+ *  MMC sysfs/driver model support.
+ */
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/device.h>
+
+#include <linux/mmc/card.h>
+#include <linux/mmc/host.h>
+
+#include "mmc.h"
+
+#define dev_to_mmc_card(d)	container_of(d, struct mmc_card, dev)
+#define to_mmc_driver(d)	container_of(d, struct mmc_driver, drv)
+
+static void mmc_release_card(struct device *dev)
+{
+	struct mmc_card *card = dev_to_mmc_card(dev);
+
+	kfree(card);
+}
+
+/*
+ * This currently matches any MMC driver to any MMC card - drivers
+ * themselves make the decision whether to drive this card in their
+ * probe method.  However, we force "bad" cards to fail.
+ */
+static int mmc_bus_match(struct device *dev, struct device_driver *drv)
+{
+	struct mmc_card *card = dev_to_mmc_card(dev);
+	return !mmc_card_bad(card);
+}
+
+static int
+mmc_bus_hotplug(struct device *dev, char **envp, int num_envp, char *buf,
+		int buf_size)
+{
+	struct mmc_card *card = dev_to_mmc_card(dev);
+	char ccc[13];
+	int i = 0;
+
+#define add_env(fmt,val)						\
+	({								\
+		int len, ret = -ENOMEM;					\
+		if (i < num_envp) {					\
+			envp[i++] = buf;				\
+			len = snprintf(buf, buf_size, fmt, val) + 1;	\
+			buf_size -= len;				\
+			buf += len;					\
+			if (buf_size >= 0)				\
+				ret = 0;				\
+		}							\
+		ret;							\
+	})
+
+	for (i = 0; i < 12; i++)
+		ccc[i] = card->csd.cmdclass & (1 << i) ? '1' : '0';
+	ccc[12] = '\0';
+
+	i = 0;
+	add_env("MMC_CCC=%s", ccc);
+	add_env("MMC_MANFID=%06x", card->cid.manfid);
+	add_env("MMC_NAME=%s", mmc_card_name(card));
+	add_env("MMC_OEMID=%04x", card->cid.oemid);
+
+	return 0;
+}
+
+static int mmc_bus_suspend(struct device *dev, u32 state)
+{
+	struct mmc_driver *drv = to_mmc_driver(dev->driver);
+	struct mmc_card *card = dev_to_mmc_card(dev);
+	int ret = 0;
+
+	if (dev->driver && drv->suspend)
+		ret = drv->suspend(card, state);
+	return ret;
+}
+
+static int mmc_bus_resume(struct device *dev)
+{
+	struct mmc_driver *drv = to_mmc_driver(dev->driver);
+	struct mmc_card *card = dev_to_mmc_card(dev);
+	int ret = 0;
+
+	if (dev->driver && drv->resume)
+		ret = drv->resume(card);
+	return ret;
+}
+
+static struct bus_type mmc_bus_type = {
+	.name		= "mmc",
+	.match		= mmc_bus_match,
+	.hotplug	= mmc_bus_hotplug,
+	.suspend	= mmc_bus_suspend,
+	.resume		= mmc_bus_resume,
+};
+
+
+static int mmc_drv_probe(struct device *dev)
+{
+	struct mmc_driver *drv = to_mmc_driver(dev->driver);
+	struct mmc_card *card = dev_to_mmc_card(dev);
+
+	return drv->probe(card);
+}
+
+static int mmc_drv_remove(struct device *dev)
+{
+	struct mmc_driver *drv = to_mmc_driver(dev->driver);
+	struct mmc_card *card = dev_to_mmc_card(dev);
+
+	drv->remove(card);
+
+	return 0;
+}
+
+
+/**
+ *	mmc_register_driver - register a media driver
+ *	@drv: MMC media driver
+ */
+int mmc_register_driver(struct mmc_driver *drv)
+{
+	drv->drv.bus = &mmc_bus_type;
+	drv->drv.probe = mmc_drv_probe;
+	drv->drv.remove = mmc_drv_remove;
+	return driver_register(&drv->drv);
+}
+
+EXPORT_SYMBOL(mmc_register_driver);
+
+/**
+ *	mmc_unregister_driver - unregister a media driver
+ *	@drv: MMC media driver
+ */
+void mmc_unregister_driver(struct mmc_driver *drv)
+{
+	drv->drv.bus = &mmc_bus_type;
+	driver_unregister(&drv->drv);
+}
+
+EXPORT_SYMBOL(mmc_unregister_driver);
+
+
+#define MMC_ATTR(name, fmt, args...)					\
+static ssize_t mmc_dev_show_##name (struct device *dev, char *buf)	\
+{									\
+	struct mmc_card *card = dev_to_mmc_card(dev);			\
+	return sprintf(buf, fmt, args);					\
+}									\
+static DEVICE_ATTR(name, S_IRUGO, mmc_dev_show_##name, NULL)
+
+MMC_ATTR(cid, "%08x%08x%08x%08x\n", card->raw_cid[0], card->raw_cid[1],
+	card->raw_cid[2], card->raw_cid[3]);
+MMC_ATTR(csd, "%08x%08x%08x%08x\n", card->raw_csd[0], card->raw_csd[1],
+	card->raw_csd[2], card->raw_csd[3]);
+MMC_ATTR(date, "%02d/%04d\n", card->cid.month, card->cid.year);
+MMC_ATTR(fwrev, "0x%x\n", card->cid.fwrev);
+MMC_ATTR(hwrev, "0x%x\n", card->cid.hwrev);
+MMC_ATTR(manfid, "0x%06x\n", card->cid.manfid);
+MMC_ATTR(name, "%s\n", card->cid.prod_name);
+MMC_ATTR(oemid, "0x%04x\n", card->cid.oemid);
+MMC_ATTR(serial, "0x%08x\n", card->cid.serial);
+
+static struct device_attribute *mmc_dev_attributes[] = {
+	&dev_attr_cid,
+	&dev_attr_csd,
+	&dev_attr_date,
+	&dev_attr_fwrev,
+	&dev_attr_hwrev,
+	&dev_attr_manfid,
+	&dev_attr_name,
+	&dev_attr_oemid,
+	&dev_attr_serial,
+};
+
+/*
+ * Internal function.  Initialise a MMC card structure.
+ */
+void mmc_init_card(struct mmc_card *card, struct mmc_host *host)
+{
+	memset(card, 0, sizeof(struct mmc_card));
+	card->host = host;
+	device_initialize(&card->dev);
+	card->dev.parent = card->host->dev;
+	card->dev.bus = &mmc_bus_type;
+	card->dev.release = mmc_release_card;
+}
+
+/*
+ * Internal function.  Register a new MMC card with the driver model.
+ */
+int mmc_register_card(struct mmc_card *card)
+{
+	int ret, i;
+
+	snprintf(card->dev.bus_id, sizeof(card->dev.bus_id),
+		 "%s:%04x", card->host->host_name, card->rca);
+
+	ret = device_add(&card->dev);
+	if (ret == 0)
+		for (i = 0; i < ARRAY_SIZE(mmc_dev_attributes); i++)
+			device_create_file(&card->dev, mmc_dev_attributes[i]);
+
+	return ret;
+}
+
+/*
+ * Internal function.  Unregister a new MMC card with the
+ * driver model, and (eventually) free it.
+ */
+void mmc_remove_card(struct mmc_card *card)
+{
+	if (mmc_card_present(card))
+		device_del(&card->dev);
+
+	put_device(&card->dev);
+}
+
+
+static int __init mmc_init(void)
+{
+	return bus_register(&mmc_bus_type);
+}
+
+static void __exit mmc_exit(void)
+{
+	bus_unregister(&mmc_bus_type);
+}
+
+module_init(mmc_init);
+module_exit(mmc_exit);
diff -Nru a/drivers/mmc/mmci.c b/drivers/mmc/mmci.c
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/drivers/mmc/mmci.c	2004-10-18 14:57:23 -07:00
@@ -0,0 +1,679 @@
+/*
+ *  linux/drivers/mmc/mmci.c - ARM PrimeCell MMCI PL180/1 driver
+ *
+ *  Copyright (C) 2003 Deep Blue Solutions, Ltd, 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 version 2 as
+ * published by the Free Software Foundation.
+ */
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/init.h>
+#include <linux/ioport.h>
+#include <linux/device.h>
+#include <linux/interrupt.h>
+#include <linux/blkdev.h>
+#include <linux/delay.h>
+#include <linux/err.h>
+#include <linux/mmc/host.h>
+#include <linux/mmc/protocol.h>
+
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/hardware/amba.h>
+#include <asm/hardware/clock.h>
+#include <asm/mach/mmc.h>
+
+#include "mmci.h"
+
+#define DRIVER_NAME "mmci-pl18x"
+
+#ifdef CONFIG_MMC_DEBUG
+#define DBG(host,fmt,args...)	\
+	pr_debug("%s: %s: " fmt, host->mmc->host_name, __func__ , args)
+#else
+#define DBG(host,fmt,args...)	do { } while (0)
+#endif
+
+static unsigned int fmax = 515633;
+
+static void
+mmci_request_end(struct mmci_host *host, struct mmc_request *mrq)
+{
+	writel(0, host->base + MMCICOMMAND);
+
+	host->mrq = NULL;
+	host->cmd = NULL;
+
+	if (mrq->data)
+		mrq->data->bytes_xfered = host->data_xfered;
+
+	/*
+	 * Need to drop the host lock here; mmc_request_done may call
+	 * back into the driver...
+	 */
+	spin_unlock(&host->lock);
+	mmc_request_done(host->mmc, mrq);
+	spin_lock(&host->lock);
+}
+
+static void mmci_stop_data(struct mmci_host *host)
+{
+	writel(0, host->base + MMCIDATACTRL);
+	writel(0, host->base + MMCIMASK1);
+	host->data = NULL;
+}
+
+static void mmci_start_data(struct mmci_host *host, struct mmc_data *data)
+{
+	unsigned int datactrl, timeout, irqmask;
+	void *base;
+
+	DBG(host, "blksz %04x blks %04x flags %08x\n",
+	    1 << data->blksz_bits, data->blocks, data->flags);
+
+	host->data = data;
+	host->size = data->blocks << data->blksz_bits;
+	host->data_xfered = 0;
+
+	mmci_init_sg(host, data);
+
+	timeout = data->timeout_clks +
+		  ((unsigned long long)data->timeout_ns * host->cclk) /
+		   1000000000ULL;
+
+	base = host->base;
+	writel(timeout, base + MMCIDATATIMER);
+	writel(host->size, base + MMCIDATALENGTH);
+
+	datactrl = MCI_DPSM_ENABLE | data->blksz_bits << 4;
+	if (data->flags & MMC_DATA_READ) {
+		datactrl |= MCI_DPSM_DIRECTION;
+		irqmask = MCI_RXFIFOHALFFULLMASK;
+	} else {
+		/*
+		 * We don't actually need to include "FIFO empty" here
+		 * since its implicit in "FIFO half empty".
+		 */
+		irqmask = MCI_TXFIFOHALFEMPTYMASK;
+	}
+
+	writel(datactrl, base + MMCIDATACTRL);
+	writel(readl(base + MMCIMASK0) & ~MCI_DATAENDMASK, base + MMCIMASK0);
+	writel(irqmask, base + MMCIMASK1);
+}
+
+static void
+mmci_start_command(struct mmci_host *host, struct mmc_command *cmd, u32 c)
+{
+	void *base = host->base;
+
+	DBG(host, "op %02x arg %08x flags %08x\n",
+	    cmd->opcode, cmd->arg, cmd->flags);
+
+	if (readl(base + MMCICOMMAND) & MCI_CPSM_ENABLE) {
+		writel(0, base + MMCICOMMAND);
+		udelay(1);
+	}
+
+	c |= cmd->opcode | MCI_CPSM_ENABLE;
+	switch (cmd->flags & MMC_RSP_MASK) {
+	case MMC_RSP_NONE:
+	default:
+		break;
+	case MMC_RSP_LONG:
+		c |= MCI_CPSM_LONGRSP;
+	case MMC_RSP_SHORT:
+		c |= MCI_CPSM_RESPONSE;
+		break;
+	}
+	if (/*interrupt*/0)
+		c |= MCI_CPSM_INTERRUPT;
+
+	host->cmd = cmd;
+
+	writel(cmd->arg, base + MMCIARGUMENT);
+	writel(c, base + MMCICOMMAND);
+}
+
+static void
+mmci_data_irq(struct mmci_host *host, struct mmc_data *data,
+	      unsigned int status)
+{
+	if (status & MCI_DATABLOCKEND) {
+		host->data_xfered += 1 << data->blksz_bits;
+	}
+	if (status & (MCI_DATACRCFAIL|MCI_DATATIMEOUT|MCI_TXUNDERRUN|MCI_RXOVERRUN)) {
+		if (status & MCI_DATACRCFAIL)
+			data->error = MMC_ERR_BADCRC;
+		else if (status & MCI_DATATIMEOUT)
+			data->error = MMC_ERR_TIMEOUT;
+		else if (status & (MCI_TXUNDERRUN|MCI_RXOVERRUN))
+			data->error = MMC_ERR_FIFO;
+		status |= MCI_DATAEND;
+	}
+	if (status & MCI_DATAEND) {
+		mmci_stop_data(host);
+
+		if (!data->stop) {
+			mmci_request_end(host, data->mrq);
+		} else {
+			mmci_start_command(host, data->stop, 0);
+		}
+	}
+}
+
+static void
+mmci_cmd_irq(struct mmci_host *host, struct mmc_command *cmd,
+	     unsigned int status)
+{
+	void *base = host->base;
+
+	host->cmd = NULL;
+
+	cmd->resp[0] = readl(base + MMCIRESPONSE0);
+	cmd->resp[1] = readl(base + MMCIRESPONSE1);
+	cmd->resp[2] = readl(base + MMCIRESPONSE2);
+	cmd->resp[3] = readl(base + MMCIRESPONSE3);
+
+	if (status & MCI_CMDTIMEOUT) {
+		cmd->error = MMC_ERR_TIMEOUT;
+	} else if (status & MCI_CMDCRCFAIL && cmd->flags & MMC_RSP_CRC) {
+		cmd->error = MMC_ERR_BADCRC;
+	}
+
+	if (!cmd->data || cmd->error != MMC_ERR_NONE) {
+		mmci_request_end(host, cmd->mrq);
+	} else if (!(cmd->data->flags & MMC_DATA_READ)) {
+		mmci_start_data(host, cmd->data);
+	}
+}
+
+static int mmci_pio_read(struct mmci_host *host, char *buffer, unsigned int remain)
+{
+	void *base = host->base;
+	char *ptr = buffer;
+	u32 status;
+
+	do {
+		int count = host->size - (readl(base + MMCIFIFOCNT) << 2);
+
+		if (count > remain)
+			count = remain;
+
+		if (count <= 0)
+			break;
+
+		readsl(base + MMCIFIFO, ptr, count >> 2);
+
+		ptr += count;
+		remain -= count;
+
+		if (remain == 0)
+			break;
+
+		status = readl(base + MMCISTATUS);
+	} while (status & MCI_RXDATAAVLBL);
+
+	return ptr - buffer;
+}
+
+static int mmci_pio_write(struct mmci_host *host, char *buffer, unsigned int remain, u32 status)
+{
+	void *base = host->base;
+	char *ptr = buffer;
+
+	do {
+		unsigned int count, maxcnt;
+
+		maxcnt = status & MCI_TXFIFOEMPTY ? MCI_FIFOSIZE : MCI_FIFOHALFSIZE;
+		count = min(remain, maxcnt);
+
+		writesl(base + MMCIFIFO, ptr, count >> 2);
+
+		ptr += count;
+		remain -= count;
+
+		if (remain == 0)
+			break;
+
+		status = readl(base + MMCISTATUS);
+	} while (status & MCI_TXFIFOHALFEMPTY);
+
+	return ptr - buffer;
+}
+
+/*
+ * PIO data transfer IRQ handler.
+ */
+static irqreturn_t mmci_pio_irq(int irq, void *dev_id, struct pt_regs *regs)
+{
+	struct mmci_host *host = dev_id;
+	void *base = host->base;
+	u32 status;
+
+	status = readl(base + MMCISTATUS);
+
+	DBG(host, "irq1 %08x\n", status);
+
+	do {
+		unsigned long flags;
+		unsigned int remain, len;
+		char *buffer;
+
+		/*
+		 * For write, we only need to test the half-empty flag
+		 * here - if the FIFO is completely empty, then by
+		 * definition it is more than half empty.
+		 *
+		 * For read, check for data available.
+		 */
+		if (!(status & (MCI_TXFIFOHALFEMPTY|MCI_RXDATAAVLBL)))
+			break;
+
+		/*
+		 * Map the current scatter buffer.
+		 */
+		buffer = mmci_kmap_atomic(host, &flags) + host->sg_off;
+		remain = host->sg_ptr->length - host->sg_off;
+
+		len = 0;
+		if (status & MCI_RXACTIVE)
+			len = mmci_pio_read(host, buffer, remain);
+		if (status & MCI_TXACTIVE)
+			len = mmci_pio_write(host, buffer, remain, status);
+
+		/*
+		 * Unmap the buffer.
+		 */
+		mmci_kunmap_atomic(host, &flags);
+
+		host->sg_off += len;
+		host->size -= len;
+		remain -= len;
+
+		if (remain)
+			break;
+
+		if (!mmci_next_sg(host))
+			break;
+
+		status = readl(base + MMCISTATUS);
+	} while (1);
+
+	/*
+	 * If we're nearing the end of the read, switch to
+	 * "any data available" mode.
+	 */
+	if (status & MCI_RXACTIVE && host->size < MCI_FIFOSIZE)
+		writel(MCI_RXDATAAVLBLMASK, base + MMCIMASK1);
+
+	/*
+	 * If we run out of data, disable the data IRQs; this
+	 * prevents a race where the FIFO becomes empty before
+	 * the chip itself has disabled the data path, and
+	 * stops us racing with our data end IRQ.
+	 */
+	if (host->size == 0) {
+		writel(0, base + MMCIMASK1);
+		writel(readl(base + MMCIMASK0) | MCI_DATAENDMASK, base + MMCIMASK0);
+	}
+
+	return IRQ_HANDLED;
+}
+
+/*
+ * Handle completion of command and data transfers.
+ */
+static irqreturn_t mmci_irq(int irq, void *dev_id, struct pt_regs *regs)
+{
+	struct mmci_host *host = dev_id;
+	u32 status;
+	int ret = 0;
+
+	spin_lock(&host->lock);
+
+	do {
+		struct mmc_command *cmd;
+		struct mmc_data *data;
+
+		status = readl(host->base + MMCISTATUS);
+		status &= readl(host->base + MMCIMASK0);
+		writel(status, host->base + MMCICLEAR);
+
+		DBG(host, "irq0 %08x\n", status);
+
+		data = host->data;
+		if (status & (MCI_DATACRCFAIL|MCI_DATATIMEOUT|MCI_TXUNDERRUN|
+			      MCI_RXOVERRUN|MCI_DATAEND|MCI_DATABLOCKEND) && data)
+			mmci_data_irq(host, data, status);
+
+		cmd = host->cmd;
+		if (status & (MCI_CMDCRCFAIL|MCI_CMDTIMEOUT|MCI_CMDSENT|MCI_CMDRESPEND) && cmd)
+			mmci_cmd_irq(host, cmd, status);
+
+		ret = 1;
+	} while (status);
+
+	spin_unlock(&host->lock);
+
+	return IRQ_RETVAL(ret);
+}
+
+static void mmci_request(struct mmc_host *mmc, struct mmc_request *mrq)
+{
+	struct mmci_host *host = mmc_priv(mmc);
+
+	WARN_ON(host->mrq != NULL);
+
+	spin_lock_irq(&host->lock);
+
+	host->mrq = mrq;
+
+	if (mrq->data && mrq->data->flags & MMC_DATA_READ)
+		mmci_start_data(host, mrq->data);
+
+	mmci_start_command(host, mrq->cmd, 0);
+
+	spin_unlock_irq(&host->lock);
+}
+
+static void mmci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
+{
+	struct mmci_host *host = mmc_priv(mmc);
+	u32 clk = 0, pwr = 0;
+
+	DBG(host, "clock %uHz busmode %u powermode %u Vdd %u\n",
+	    ios->clock, ios->bus_mode, ios->power_mode, ios->vdd);
+
+	if (ios->clock) {
+		if (ios->clock >= host->mclk) {
+			clk = MCI_CLK_BYPASS;
+			host->cclk = host->mclk;
+		} else {
+			clk = host->mclk / (2 * ios->clock) - 1;
+			if (clk > 256)
+				clk = 255;
+			host->cclk = host->mclk / (2 * (clk + 1));
+		}
+		clk |= MCI_CLK_ENABLE;
+	}
+
+	if (host->plat->translate_vdd)
+		pwr |= host->plat->translate_vdd(mmc_dev(mmc), ios->vdd);
+
+	switch (ios->power_mode) {
+	case MMC_POWER_OFF:
+		break;
+	case MMC_POWER_UP:
+		pwr |= MCI_PWR_UP;
+		break;
+	case MMC_POWER_ON:
+		pwr |= MCI_PWR_ON;
+		break;
+	}
+
+	if (ios->bus_mode == MMC_BUSMODE_OPENDRAIN)
+		pwr |= MCI_ROD;
+
+	writel(clk, host->base + MMCICLOCK);
+
+	if (host->pwr != pwr) {
+		host->pwr = pwr;
+		writel(pwr, host->base + MMCIPOWER);
+	}
+}
+
+static struct mmc_host_ops mmci_ops = {
+	.request	= mmci_request,
+	.set_ios	= mmci_set_ios,
+};
+
+static void mmci_check_status(unsigned long data)
+{
+	struct mmci_host *host = (struct mmci_host *)data;
+	unsigned int status;
+
+	status = host->plat->status(mmc_dev(host->mmc));
+	if (status ^ host->oldstat)
+		mmc_detect_change(host->mmc);
+
+	host->oldstat = status;
+	mod_timer(&host->timer, jiffies + HZ);
+}
+
+static int mmci_probe(struct amba_device *dev, void *id)
+{
+	struct mmc_platform_data *plat = dev->dev.platform_data;
+	struct mmci_host *host;
+	struct mmc_host *mmc;
+	int ret;
+
+	/* must have platform data */
+	if (!plat) {
+		ret = -EINVAL;
+		goto out;
+	}
+
+	ret = amba_request_regions(dev, DRIVER_NAME);
+	if (ret)
+		goto out;
+
+	mmc = mmc_alloc_host(sizeof(struct mmci_host), &dev->dev);
+	if (!mmc) {
+		ret = -ENOMEM;
+		goto rel_regions;
+	}
+
+	host = mmc_priv(mmc);
+	host->clk = clk_get(&dev->dev, "MCLK");
+	if (IS_ERR(host->clk)) {
+		ret = PTR_ERR(host->clk);
+		host->clk = NULL;
+		goto host_free;
+	}
+
+	ret = clk_use(host->clk);
+	if (ret)
+		goto clk_free;
+
+	ret = clk_enable(host->clk);
+	if (ret)
+		goto clk_unuse;
+
+	host->plat = plat;
+	host->mclk = clk_get_rate(host->clk);
+	host->mmc = mmc;
+	host->base = ioremap(dev->res.start, SZ_4K);
+	if (!host->base) {
+		ret = -ENOMEM;
+		goto clk_disable;
+	}
+
+	mmc->ops = &mmci_ops;
+	mmc->f_min = (host->mclk + 511) / 512;
+	mmc->f_max = min(host->mclk, fmax);
+	mmc->ocr_avail = plat->ocr_mask;
+
+	/*
+	 * We can do SGIO
+	 */
+	mmc->max_hw_segs = 16;
+	mmc->max_phys_segs = 16;
+
+	/*
+	 * Since we only have a 16-bit data length register, we must
+	 * ensure that we don't exceed 2^16-1 bytes in a single request.
+	 * Choose 64 (512-byte) sectors as the limit.
+	 */
+	mmc->max_sectors = 64;
+
+	/*
+	 * Set the maximum segment size.  Since we aren't doing DMA
+	 * (yet) we are only limited by the data length register.
+	 */
+	mmc->max_seg_size = mmc->max_sectors << 9;
+
+	spin_lock_init(&host->lock);
+
+	writel(0, host->base + MMCIMASK0);
+	writel(0, host->base + MMCIMASK1);
+	writel(0xfff, host->base + MMCICLEAR);
+
+	ret = request_irq(dev->irq[0], mmci_irq, SA_SHIRQ, DRIVER_NAME " (cmd)", host);
+	if (ret)
+		goto unmap;
+
+	ret = request_irq(dev->irq[1], mmci_pio_irq, SA_SHIRQ, DRIVER_NAME " (pio)", host);
+	if (ret)
+		goto irq0_free;
+
+	writel(MCI_IRQENABLE, host->base + MMCIMASK0);
+
+	amba_set_drvdata(dev, mmc);
+
+	mmc_add_host(mmc);
+
+	printk(KERN_INFO "%s: MMCI rev %x cfg %02x at 0x%08lx irq %d,%d\n",
+		mmc->host_name, amba_rev(dev), amba_config(dev),
+		dev->res.start, dev->irq[0], dev->irq[1]);
+
+	init_timer(&host->timer);
+	host->timer.data = (unsigned long)host;
+	host->timer.function = mmci_check_status;
+	host->timer.expires = jiffies + HZ;
+	add_timer(&host->timer);
+
+	return 0;
+
+ irq0_free:
+	free_irq(dev->irq[0], host);
+ unmap:
+	iounmap(host->base);
+ clk_disable:
+	clk_disable(host->clk);
+ clk_unuse:
+	clk_unuse(host->clk);
+ clk_free:
+	clk_put(host->clk);
+ host_free:
+	mmc_free_host(mmc);
+ rel_regions:
+	amba_release_regions(dev);
+ out:
+	return ret;
+}
+
+static int mmci_remove(struct amba_device *dev)
+{
+	struct mmc_host *mmc = amba_get_drvdata(dev);
+
+	amba_set_drvdata(dev, NULL);
+
+	if (mmc) {
+		struct mmci_host *host = mmc_priv(mmc);
+
+		del_timer_sync(&host->timer);
+
+		mmc_remove_host(mmc);
+
+		writel(0, host->base + MMCIMASK0);
+		writel(0, host->base + MMCIMASK1);
+
+		writel(0, host->base + MMCICOMMAND);
+		writel(0, host->base + MMCIDATACTRL);
+
+		free_irq(dev->irq[0], host);
+		free_irq(dev->irq[1], host);
+
+		iounmap(host->base);
+		clk_disable(host->clk);
+		clk_unuse(host->clk);
+		clk_put(host->clk);
+
+		mmc_free_host(mmc);
+
+		amba_release_regions(dev);
+	}
+
+	return 0;
+}
+
+#ifdef CONFIG_PM
+static int mmci_suspend(struct amba_device *dev, u32 state)
+{
+	struct mmc_host *mmc = amba_get_drvdata(dev);
+	int ret = 0;
+
+	if (mmc) {
+		struct mmci_host *host = mmc_priv(mmc);
+
+		ret = mmc_suspend_host(mmc, state);
+		if (ret == 0)
+			writel(0, host->base + MMCIMASK0);
+	}
+
+	return ret;
+}
+
+static int mmci_resume(struct amba_device *dev)
+{
+	struct mmc_host *mmc = amba_get_drvdata(dev);
+	int ret = 0;
+
+	if (mmc) {
+		struct mmci_host *host = mmc_priv(mmc);
+
+		writel(MCI_IRQENABLE, host->base + MMCIMASK0);
+
+		ret = mmc_resume_host(mmc);
+	}
+
+	return ret;
+}
+#else
+#define mmci_suspend	NULL
+#define mmci_resume	NULL
+#endif
+
+static struct amba_id mmci_ids[] = {
+	{
+		.id	= 0x00041180,
+		.mask	= 0x000fffff,
+	},
+	{
+		.id	= 0x00041181,
+		.mask	= 0x000fffff,
+	},
+	{ 0, 0 },
+};
+
+static struct amba_driver mmci_driver = {
+	.drv		= {
+		.name	= DRIVER_NAME,
+	},
+	.probe		= mmci_probe,
+	.remove		= mmci_remove,
+	.suspend	= mmci_suspend,
+	.resume		= mmci_resume,
+	.id_table	= mmci_ids,
+};
+
+static int __init mmci_init(void)
+{
+	return amba_driver_register(&mmci_driver);
+}
+
+static void __exit mmci_exit(void)
+{
+	amba_driver_unregister(&mmci_driver);
+}
+
+module_init(mmci_init);
+module_exit(mmci_exit);
+module_param(fmax, uint, 0444);
+
+MODULE_DESCRIPTION("ARM PrimeCell PL180/181 Multimedia Card Interface driver");
+MODULE_LICENSE("GPL");
diff -Nru a/drivers/mmc/mmci.h b/drivers/mmc/mmci.h
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/drivers/mmc/mmci.h	2004-10-18 14:57:24 -07:00
@@ -0,0 +1,183 @@
+/*
+ *  linux/drivers/mmc/mmci.h - ARM PrimeCell MMCI PL180/1 driver
+ *
+ *  Copyright (C) 2003 Deep Blue Solutions, Ltd, 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 version 2 as
+ * published by the Free Software Foundation.
+ */
+#define MMCIPOWER		0x000
+#define MCI_PWR_OFF		0x00
+#define MCI_PWR_UP		0x02
+#define MCI_PWR_ON		0x03
+#define MCI_OD			(1 << 6)
+#define MCI_ROD			(1 << 7)
+
+#define MMCICLOCK		0x004
+#define MCI_CLK_ENABLE		(1 << 8)
+#define MCI_CLK_PWRSAVE		(1 << 9)
+#define MCI_CLK_BYPASS		(1 << 10)
+
+#define MMCIARGUMENT		0x008
+#define MMCICOMMAND		0x00c
+#define MCI_CPSM_RESPONSE	(1 << 6)
+#define MCI_CPSM_LONGRSP	(1 << 7)
+#define MCI_CPSM_INTERRUPT	(1 << 8)
+#define MCI_CPSM_PENDING	(1 << 9)
+#define MCI_CPSM_ENABLE		(1 << 10)
+
+#define MMCIRESPCMD		0x010
+#define MMCIRESPONSE0		0x014
+#define MMCIRESPONSE1		0x018
+#define MMCIRESPONSE2		0x01c
+#define MMCIRESPONSE3		0x020
+#define MMCIDATATIMER		0x024
+#define MMCIDATALENGTH		0x028
+#define MMCIDATACTRL		0x02c
+#define MCI_DPSM_ENABLE		(1 << 0)
+#define MCI_DPSM_DIRECTION	(1 << 1)
+#define MCI_DPSM_MODE		(1 << 2)
+#define MCI_DPSM_DMAENABLE	(1 << 3)
+
+#define MMCIDATACNT		0x030
+#define MMCISTATUS		0x034
+#define MCI_CMDCRCFAIL		(1 << 0)
+#define MCI_DATACRCFAIL		(1 << 1)
+#define MCI_CMDTIMEOUT		(1 << 2)
+#define MCI_DATATIMEOUT		(1 << 3)
+#define MCI_TXUNDERRUN		(1 << 4)
+#define MCI_RXOVERRUN		(1 << 5)
+#define MCI_CMDRESPEND		(1 << 6)
+#define MCI_CMDSENT		(1 << 7)
+#define MCI_DATAEND		(1 << 8)
+#define MCI_DATABLOCKEND	(1 << 10)
+#define MCI_CMDACTIVE		(1 << 11)
+#define MCI_TXACTIVE		(1 << 12)
+#define MCI_RXACTIVE		(1 << 13)
+#define MCI_TXFIFOHALFEMPTY	(1 << 14)
+#define MCI_RXFIFOHALFFULL	(1 << 15)
+#define MCI_TXFIFOFULL		(1 << 16)
+#define MCI_RXFIFOFULL		(1 << 17)
+#define MCI_TXFIFOEMPTY		(1 << 18)
+#define MCI_RXFIFOEMPTY		(1 << 19)
+#define MCI_TXDATAAVLBL		(1 << 20)
+#define MCI_RXDATAAVLBL		(1 << 21)
+
+#define MMCICLEAR		0x038
+#define MCI_CMDCRCFAILCLR	(1 << 0)
+#define MCI_DATACRCFAILCLR	(1 << 1)
+#define MCI_CMDTIMEOUTCLR	(1 << 2)
+#define MCI_DATATIMEOUTCLR	(1 << 3)
+#define MCI_TXUNDERRUNCLR	(1 << 4)
+#define MCI_RXOVERRUNCLR	(1 << 5)
+#define MCI_CMDRESPENDCLR	(1 << 6)
+#define MCI_CMDSENTCLR		(1 << 7)
+#define MCI_DATAENDCLR		(1 << 8)
+#define MCI_DATABLOCKENDCLR	(1 << 10)
+
+#define MMCIMASK0		0x03c
+#define MCI_CMDCRCFAILMASK	(1 << 0)
+#define MCI_DATACRCFAILMASK	(1 << 1)
+#define MCI_CMDTIMEOUTMASK	(1 << 2)
+#define MCI_DATATIMEOUTMASK	(1 << 3)
+#define MCI_TXUNDERRUNMASK	(1 << 4)
+#define MCI_RXOVERRUNMASK	(1 << 5)
+#define MCI_CMDRESPENDMASK	(1 << 6)
+#define MCI_CMDSENTMASK		(1 << 7)
+#define MCI_DATAENDMASK		(1 << 8)
+#define MCI_DATABLOCKENDMASK	(1 << 10)
+#define MCI_CMDACTIVEMASK	(1 << 11)
+#define MCI_TXACTIVEMASK	(1 << 12)
+#define MCI_RXACTIVEMASK	(1 << 13)
+#define MCI_TXFIFOHALFEMPTYMASK	(1 << 14)
+#define MCI_RXFIFOHALFFULLMASK	(1 << 15)
+#define MCI_TXFIFOFULLMASK	(1 << 16)
+#define MCI_RXFIFOFULLMASK	(1 << 17)
+#define MCI_TXFIFOEMPTYMASK	(1 << 18)
+#define MCI_RXFIFOEMPTYMASK	(1 << 19)
+#define MCI_TXDATAAVLBLMASK	(1 << 20)
+#define MCI_RXDATAAVLBLMASK	(1 << 21)
+
+#define MMCIMASK1		0x040
+#define MMCIFIFOCNT		0x048
+#define MMCIFIFO		0x080 /* to 0x0bc */
+
+#define MCI_IRQENABLE	\
+	(MCI_CMDCRCFAILMASK|MCI_DATACRCFAILMASK|MCI_CMDTIMEOUTMASK|	\
+	MCI_DATATIMEOUTMASK|MCI_TXUNDERRUNMASK|MCI_RXOVERRUNMASK|	\
+	MCI_CMDRESPENDMASK|MCI_CMDSENTMASK|MCI_DATABLOCKENDMASK)
+
+/*
+ * The size of the FIFO in bytes.
+ */
+#define MCI_FIFOSIZE	(16*4)
+	
+#define MCI_FIFOHALFSIZE (MCI_FIFOSIZE / 2)
+
+#define NR_SG		16
+
+struct clk;
+
+struct mmci_host {
+	void			*base;
+	struct mmc_request	*mrq;
+	struct mmc_command	*cmd;
+	struct mmc_data		*data;
+	struct mmc_host		*mmc;
+	struct clk		*clk;
+
+	unsigned int		data_xfered;
+
+	spinlock_t		lock;
+
+	unsigned int		mclk;
+	unsigned int		cclk;
+	u32			pwr;
+	struct mmc_platform_data *plat;
+
+	struct timer_list	timer;
+	unsigned int		oldstat;
+
+	struct scatterlist	sg[NR_SG];
+	unsigned int		sg_len;
+
+	/* pio stuff */
+	struct scatterlist	*sg_ptr;
+	unsigned int		sg_off;
+	unsigned int		size;
+};
+
+static inline void mmci_init_sg(struct mmci_host *host, struct mmc_data *data)
+{
+	struct scatterlist *sg = host->sg;
+	struct request *req = data->req;
+
+	/*
+	 * Ideally, we want the higher levels to pass us a scatter list.
+	 */
+	host->sg_len = blk_rq_map_sg(req->q, req, sg);
+	host->sg_ptr = sg;
+	host->sg_off = 0;
+}
+
+static inline int mmci_next_sg(struct mmci_host *host)
+{
+	host->sg_ptr++;
+	host->sg_off = 0;
+	return --host->sg_len;
+}
+
+static inline char *mmci_kmap_atomic(struct mmci_host *host, unsigned long *flags)
+{
+	struct scatterlist *sg = host->sg_ptr;
+
+	local_irq_save(*flags);
+	return kmap_atomic(sg->page, KM_BIO_SRC_IRQ) + sg->offset;
+}
+
+static inline void mmci_kunmap_atomic(struct mmci_host *host, unsigned long *flags)
+{
+	kunmap_atomic(host->sg_ptr->page, KM_BIO_SRC_IRQ);
+	local_irq_restore(*flags);
+}
diff -Nru a/drivers/mmc/pxamci.c b/drivers/mmc/pxamci.c
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/drivers/mmc/pxamci.c	2004-10-18 14:57:23 -07:00
@@ -0,0 +1,604 @@
+/*
+ *  linux/drivers/mmc/pxa.c - PXA MMCI driver
+ *
+ *  Copyright (C) 2003 Russell King, 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 version 2 as
+ * published by the Free Software Foundation.
+ *
+ *  This hardware is really sick:
+ *   - No way to clear interrupts.
+ *   - Have to turn off the clock whenever we touch the device.
+ *   - Doesn't tell you how many data blocks were transferred.
+ *  Yuck!
+ *
+ *	1 and 3 byte data transfers not supported
+ *	max block length up to 1023
+ */
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/ioport.h>
+#include <linux/device.h>
+#include <linux/delay.h>
+#include <linux/interrupt.h>
+#include <linux/blkdev.h>
+#include <linux/dma-mapping.h>
+#include <linux/mmc/host.h>
+#include <linux/mmc/protocol.h>
+
+#include <asm/dma.h>
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/sizes.h>
+
+#include <asm/arch/pxa-regs.h>
+#include <asm/arch/mmc.h>
+
+#include "pxamci.h"
+
+#ifdef CONFIG_MMC_DEBUG
+#define DBG(x...)	printk(KERN_DEBUG x)
+#else
+#define DBG(x...)	do { } while (0)
+#endif
+
+struct pxamci_host {
+	struct mmc_host		*mmc;
+	spinlock_t		lock;
+	struct resource		*res;
+	void			*base;
+	int			irq;
+	int			dma;
+	unsigned int		clkrt;
+	unsigned int		cmdat;
+	unsigned int		imask;
+	unsigned int		power_mode;
+	struct pxamci_platform_data *pdata;
+
+	struct mmc_request	*mrq;
+	struct mmc_command	*cmd;
+	struct mmc_data		*data;
+
+	dma_addr_t		sg_dma;
+	struct pxa_dma_desc	*sg_cpu;
+
+	dma_addr_t		dma_buf;
+	unsigned int		dma_size;
+	unsigned int		dma_dir;
+};
+
+/*
+ * The base MMC clock rate
+ */
+#define CLOCKRATE	20000000
+
+static inline unsigned int ns_to_clocks(unsigned int ns)
+{
+	return (ns * (CLOCKRATE / 1000000) + 999) / 1000;
+}
+
+static void pxamci_stop_clock(struct pxamci_host *host)
+{
+	if (readl(host->base + MMC_STAT) & STAT_CLK_EN) {
+		unsigned long timeout = 10000;
+		unsigned int v;
+
+		writel(STOP_CLOCK, host->base + MMC_STRPCL);
+
+		do {
+			v = readl(host->base + MMC_STAT);
+			if (!(v & STAT_CLK_EN))
+				break;
+			udelay(1);
+		} while (timeout--);
+
+		if (v & STAT_CLK_EN)
+			dev_err(mmc_dev(host->mmc), "unable to stop clock\n");
+	}
+}
+
+static void pxamci_enable_irq(struct pxamci_host *host, unsigned int mask)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&host->lock, flags);
+	host->imask &= ~mask;
+	writel(host->imask, host->base + MMC_I_MASK);
+	spin_unlock_irqrestore(&host->lock, flags);
+}
+
+static void pxamci_disable_irq(struct pxamci_host *host, unsigned int mask)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&host->lock, flags);
+	host->imask |= mask;
+	writel(host->imask, host->base + MMC_I_MASK);
+	spin_unlock_irqrestore(&host->lock, flags);
+}
+
+static void pxamci_setup_data(struct pxamci_host *host, struct mmc_data *data)
+{
+	unsigned int nob = data->blocks;
+	unsigned int timeout, size;
+	dma_addr_t dma;
+	u32 dcmd;
+	int i;
+
+	host->data = data;
+
+	if (data->flags & MMC_DATA_STREAM)
+		nob = 0xffff;
+
+	writel(nob, host->base + MMC_NOB);
+	writel(1 << data->blksz_bits, host->base + MMC_BLKLEN);
+
+	timeout = ns_to_clocks(data->timeout_ns) + data->timeout_clks;
+	writel((timeout + 255) / 256, host->base + MMC_RDTO);
+
+	if (data->flags & MMC_DATA_READ) {
+		host->dma_dir = DMA_FROM_DEVICE;
+		dcmd = DCMD_INCTRGADDR | DCMD_FLOWTRG;
+		DRCMRTXMMC = 0;
+		DRCMRRXMMC = host->dma | DRCMR_MAPVLD;
+	} else {
+		host->dma_dir = DMA_TO_DEVICE;
+		dcmd = DCMD_INCSRCADDR | DCMD_FLOWSRC;
+		DRCMRRXMMC = 0;
+		DRCMRTXMMC = host->dma | DRCMR_MAPVLD;
+	}
+
+	dcmd |= DCMD_BURST32 | DCMD_WIDTH1;
+
+	host->dma_size = data->blocks << data->blksz_bits;
+	host->dma_buf = dma_map_single(mmc_dev(host->mmc), data->req->buffer,
+				       host->dma_size, host->dma_dir);
+
+	for (i = 0, size = host->dma_size, dma = host->dma_buf; size; i++) {
+		u32 len = size;
+
+		if (len > DCMD_LENGTH)
+			len = 0x1000;
+
+		if (data->flags & MMC_DATA_READ) {
+			host->sg_cpu[i].dsadr = host->res->start + MMC_RXFIFO;
+			host->sg_cpu[i].dtadr = dma;
+		} else {
+			host->sg_cpu[i].dsadr = dma;
+			host->sg_cpu[i].dtadr = host->res->start + MMC_TXFIFO;
+		}
+		host->sg_cpu[i].dcmd = dcmd | len;
+
+		dma += len;
+		size -= len;
+
+		if (size) {
+			host->sg_cpu[i].ddadr = host->sg_dma + (i + 1) *
+						 sizeof(struct pxa_dma_desc);
+		} else {
+			host->sg_cpu[i].ddadr = DDADR_STOP;
+		}
+	}
+	wmb();
+
+	DDADR(host->dma) = host->sg_dma;
+	DCSR(host->dma) = DCSR_RUN;
+}
+
+static void pxamci_start_cmd(struct pxamci_host *host, struct mmc_command *cmd, unsigned int cmdat)
+{
+	WARN_ON(host->cmd != NULL);
+	host->cmd = cmd;
+
+	if (cmd->flags & MMC_RSP_BUSY)
+		cmdat |= CMDAT_BUSY;
+
+	switch (cmd->flags & (MMC_RSP_MASK | MMC_RSP_CRC)) {
+	case MMC_RSP_SHORT | MMC_RSP_CRC:
+		cmdat |= CMDAT_RESP_SHORT;
+		break;
+	case MMC_RSP_SHORT:
+		cmdat |= CMDAT_RESP_R3;
+		break;
+	case MMC_RSP_LONG | MMC_RSP_CRC:
+		cmdat |= CMDAT_RESP_R2;
+		break;
+	default:
+		break;
+	}
+
+	writel(cmd->opcode, host->base + MMC_CMD);
+	writel(cmd->arg >> 16, host->base + MMC_ARGH);
+	writel(cmd->arg & 0xffff, host->base + MMC_ARGL);
+	writel(cmdat, host->base + MMC_CMDAT);
+	writel(host->clkrt, host->base + MMC_CLKRT);
+
+	writel(START_CLOCK, host->base + MMC_STRPCL);
+
+	pxamci_enable_irq(host, END_CMD_RES);
+}
+
+static void pxamci_finish_request(struct pxamci_host *host, struct mmc_request *mrq)
+{
+	DBG("PXAMCI: request done\n");
+	host->mrq = NULL;
+	host->cmd = NULL;
+	host->data = NULL;
+	mmc_request_done(host->mmc, mrq);
+}
+
+static int pxamci_cmd_done(struct pxamci_host *host, unsigned int stat)
+{
+	struct mmc_command *cmd = host->cmd;
+	int i;
+	u32 v;
+
+	if (!cmd)
+		return 0;
+
+	host->cmd = NULL;
+
+	/*
+	 * Did I mention this is Sick.  We always need to
+	 * discard the upper 8 bits of the first 16-bit word.
+	 */
+	v = readl(host->base + MMC_RES) & 0xffff;
+	for (i = 0; i < 4; i++) {
+		u32 w1 = readl(host->base + MMC_RES) & 0xffff;
+		u32 w2 = readl(host->base + MMC_RES) & 0xffff;
+		cmd->resp[i] = v << 24 | w1 << 8 | w2 >> 8;
+		v = w2;
+	}
+
+	if (stat & STAT_TIME_OUT_RESPONSE) {
+		cmd->error = MMC_ERR_TIMEOUT;
+	} else if (stat & STAT_RES_CRC_ERR && cmd->flags & MMC_RSP_CRC) {
+		cmd->error = MMC_ERR_BADCRC;
+	}
+
+	pxamci_disable_irq(host, END_CMD_RES);
+	if (host->data && cmd->error == MMC_ERR_NONE) {
+		pxamci_enable_irq(host, DATA_TRAN_DONE);
+	} else {
+		pxamci_finish_request(host, host->mrq);
+	}
+
+	return 1;
+}
+
+static int pxamci_data_done(struct pxamci_host *host, unsigned int stat)
+{
+	struct mmc_data *data = host->data;
+
+	if (!data)
+		return 0;
+
+	DCSR(host->dma) = 0;
+	dma_unmap_single(mmc_dev(host->mmc), host->dma_buf, host->dma_size,
+			 host->dma_dir);
+
+	if (stat & STAT_READ_TIME_OUT)
+		data->error = MMC_ERR_TIMEOUT;
+	else if (stat & (STAT_CRC_READ_ERROR|STAT_CRC_WRITE_ERROR))
+		data->error = MMC_ERR_BADCRC;
+
+	/*
+	 * There appears to be a hardware design bug here.  There seems to
+	 * be no way to find out how much data was transferred to the card.
+	 * This means that if there was an error on any block, we mark all
+	 * data blocks as being in error.
+	 */
+	if (data->error == MMC_ERR_NONE)
+		data->bytes_xfered = data->blocks << data->blksz_bits;
+	else
+		data->bytes_xfered = 0;
+
+	pxamci_disable_irq(host, DATA_TRAN_DONE);
+
+	host->data = NULL;
+	if (host->mrq->stop && data->error == MMC_ERR_NONE) {
+		pxamci_stop_clock(host);
+		pxamci_start_cmd(host, host->mrq->stop, 0);
+	} else {
+		pxamci_finish_request(host, host->mrq);
+	}
+
+	return 1;
+}
+
+static irqreturn_t pxamci_irq(int irq, void *devid, struct pt_regs *regs)
+{
+	struct pxamci_host *host = devid;
+	unsigned int ireg;
+	int handled = 0;
+
+	ireg = readl(host->base + MMC_I_REG);
+
+	DBG("PXAMCI: irq %08x\n", ireg);
+
+	if (ireg) {
+		unsigned stat = readl(host->base + MMC_STAT);
+
+		DBG("PXAMCI: stat %08x\n", stat);
+
+		if (ireg & END_CMD_RES)
+			handled |= pxamci_cmd_done(host, stat);
+		if (ireg & DATA_TRAN_DONE)
+			handled |= pxamci_data_done(host, stat);
+	}
+
+	return IRQ_RETVAL(handled);
+}
+
+static void pxamci_request(struct mmc_host *mmc, struct mmc_request *mrq)
+{
+	struct pxamci_host *host = mmc_priv(mmc);
+	unsigned int cmdat;
+
+	WARN_ON(host->mrq != NULL);
+
+	host->mrq = mrq;
+
+	pxamci_stop_clock(host);
+
+	cmdat = host->cmdat;
+	host->cmdat &= ~CMDAT_INIT;
+
+	if (mrq->data) {
+		pxamci_setup_data(host, mrq->data);
+
+		cmdat &= ~CMDAT_BUSY;
+		cmdat |= CMDAT_DATAEN | CMDAT_DMAEN;
+		if (mrq->data->flags & MMC_DATA_WRITE)
+			cmdat |= CMDAT_WRITE;
+
+		if (mrq->data->flags & MMC_DATA_STREAM)
+			cmdat |= CMDAT_STREAM;
+	}
+
+	pxamci_start_cmd(host, mrq->cmd, cmdat);
+}
+
+static void pxamci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
+{
+	struct pxamci_host *host = mmc_priv(mmc);
+
+	DBG("pxamci_set_ios: clock %u power %u vdd %u.%02u\n",
+	    ios->clock, ios->power_mode, ios->vdd / 100,
+	    ios->vdd % 100);
+
+	if (ios->clock) {
+		unsigned int clk = CLOCKRATE / ios->clock;
+		if (CLOCKRATE / clk > ios->clock)
+			clk <<= 1;
+		host->clkrt = fls(clk) - 1;
+
+		/*
+		 * we write clkrt on the next command
+		 */
+	} else if (readl(host->base + MMC_STAT) & STAT_CLK_EN) {
+		/*
+		 * Ensure that the clock is off.
+		 */
+		writel(STOP_CLOCK, host->base + MMC_STRPCL);
+	}
+
+	if (host->power_mode != ios->power_mode) {
+		host->power_mode = ios->power_mode;
+
+		if (host->pdata && host->pdata->setpower)
+			host->pdata->setpower(mmc->dev, ios->vdd);
+
+		if (ios->power_mode == MMC_POWER_ON)
+			host->cmdat |= CMDAT_INIT;
+	}
+
+	DBG("pxamci_set_ios: clkrt = %x cmdat = %x\n",
+	    host->clkrt, host->cmdat);
+}
+
+static struct mmc_host_ops pxamci_ops = {
+	.request	= pxamci_request,
+	.set_ios	= pxamci_set_ios,
+};
+
+static void pxamci_dma_irq(int dma, void *devid, struct pt_regs *regs)
+{
+	printk(KERN_ERR "DMA%d: IRQ???\n", dma);
+	DCSR(dma) = DCSR_STARTINTR|DCSR_ENDINTR|DCSR_BUSERR;
+}
+
+static irqreturn_t pxamci_detect_irq(int irq, void *devid, struct pt_regs *regs)
+{
+	mmc_detect_change(devid);
+	return IRQ_HANDLED;
+}
+
+static int pxamci_probe(struct device *dev)
+{
+	struct platform_device *pdev = to_platform_device(dev);
+	struct mmc_host *mmc;
+	struct pxamci_host *host = NULL;
+	struct resource *r;
+	int ret, irq;
+
+	r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	irq = platform_get_irq(pdev, 0);
+	if (!r || irq == NO_IRQ)
+		return -ENXIO;
+
+	r = request_mem_region(r->start, SZ_4K, "PXAMCI");
+	if (!r)
+		return -EBUSY;
+
+	mmc = mmc_alloc_host(sizeof(struct pxamci_host), dev);
+	if (!mmc) {
+		ret = -ENOMEM;
+		goto out;
+	}
+
+	mmc->ops = &pxamci_ops;
+	mmc->f_min = 312500;
+	mmc->f_max = 20000000;
+
+	host = mmc_priv(mmc);
+	host->mmc = mmc;
+	host->dma = -1;
+	host->pdata = pdev->dev.platform_data;
+	mmc->ocr_avail = host->pdata ?
+			 host->pdata->ocr_mask :
+			 MMC_VDD_32_33|MMC_VDD_33_34;
+
+	host->sg_cpu = dma_alloc_coherent(dev, PAGE_SIZE, &host->sg_dma, GFP_KERNEL);
+	if (!host->sg_cpu) {
+		ret = -ENOMEM;
+		goto out;
+	}
+
+	spin_lock_init(&host->lock);
+	host->res = r;
+	host->irq = irq;
+	host->imask = TXFIFO_WR_REQ|RXFIFO_RD_REQ|CLK_IS_OFF|STOP_CMD|
+		      END_CMD_RES|PRG_DONE|DATA_TRAN_DONE;
+
+	host->base = ioremap(r->start, SZ_4K);
+	if (!host->base) {
+		ret = -ENOMEM;
+		goto out;
+	}
+
+	/*
+	 * Ensure that the host controller is shut down, and setup
+	 * with our defaults.
+	 */
+	pxamci_stop_clock(host);
+	writel(0, host->base + MMC_SPI);
+	writel(64, host->base + MMC_RESTO);
+	writel(host->imask, host->base + MMC_I_MASK);
+
+	pxa_gpio_mode(GPIO6_MMCCLK_MD);
+	pxa_gpio_mode(GPIO8_MMCCS0_MD);
+	pxa_set_cken(CKEN12_MMC, 1);
+
+	host->dma = pxa_request_dma("PXAMCI", DMA_PRIO_LOW, pxamci_dma_irq, host);
+	if (host->dma < 0) {
+		ret = -EBUSY;
+		goto out;
+	}
+
+	ret = request_irq(host->irq, pxamci_irq, 0, "PXAMCI", host);
+	if (ret)
+		goto out;
+
+	dev_set_drvdata(dev, mmc);
+
+	if (host->pdata && host->pdata->init)
+		host->pdata->init(dev, pxamci_detect_irq, mmc);
+
+	mmc_add_host(mmc);
+
+	return 0;
+
+ out:
+	if (host) {
+		if (host->dma >= 0)
+			pxa_free_dma(host->dma);
+		if (host->base)
+			iounmap(host->base);
+		if (host->sg_cpu)
+			dma_free_coherent(dev, PAGE_SIZE, host->sg_cpu, host->sg_dma);
+	}
+	if (mmc)
+		mmc_free_host(mmc);
+	release_resource(r);
+	return ret;
+}
+
+static int pxamci_remove(struct device *dev)
+{
+	struct mmc_host *mmc = dev_get_drvdata(dev);
+
+	dev_set_drvdata(dev, NULL);
+
+	if (mmc) {
+		struct pxamci_host *host = mmc_priv(mmc);
+
+		if (host->pdata && host->pdata->exit)
+			host->pdata->exit(dev, mmc);
+
+		mmc_remove_host(mmc);
+
+		pxamci_stop_clock(host);
+		writel(TXFIFO_WR_REQ|RXFIFO_RD_REQ|CLK_IS_OFF|STOP_CMD|
+		       END_CMD_RES|PRG_DONE|DATA_TRAN_DONE,
+		       host->base + MMC_I_MASK);
+
+		pxa_set_cken(CKEN12_MMC, 0);
+
+		free_irq(host->irq, host);
+		pxa_free_dma(host->dma);
+		iounmap(host->base);
+		dma_free_coherent(dev, PAGE_SIZE, host->sg_cpu, host->sg_dma);
+
+		pxa_set_cken(CKEN12_MMC, 0);
+
+		release_resource(host->res);
+
+		mmc_free_host(mmc);
+	}
+	return 0;
+}
+
+#ifdef CONFIG_PM
+static int pxamci_suspend(struct device *dev, u32 state, u32 level)
+{
+	struct mmc_host *mmc = dev_get_drvdata(dev);
+	int ret = 0;
+
+	if (mmc && level == SUSPEND_DISABLE)
+		ret = mmc_suspend_host(mmc, state);
+
+	return ret;
+}
+
+static int pxamci_resume(struct device *dev, u32 level)
+{
+	struct mmc_host *mmc = dev_get_drvdata(dev);
+	int ret = 0;
+
+	if (mmc && level == RESUME_ENABLE)
+		ret = mmc_resume_host(mmc);
+
+	return ret;
+}
+#else
+#define pxamci_suspend	NULL
+#define pxamci_resume	NULL
+#endif
+
+static struct device_driver pxamci_driver = {
+	.name		= "pxa2xx-mci",
+	.bus		= &platform_bus_type,
+	.probe		= pxamci_probe,
+	.remove		= pxamci_remove,
+	.suspend	= pxamci_suspend,
+	.resume		= pxamci_resume,
+};
+
+static int __init pxamci_init(void)
+{
+	return driver_register(&pxamci_driver);
+}
+
+static void __exit pxamci_exit(void)
+{
+	driver_unregister(&pxamci_driver);
+}
+
+module_init(pxamci_init);
+module_exit(pxamci_exit);
+
+MODULE_DESCRIPTION("PXA Multimedia Card Interface Driver");
+MODULE_LICENSE("GPL");
diff -Nru a/drivers/mmc/pxamci.h b/drivers/mmc/pxamci.h
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/drivers/mmc/pxamci.h	2004-10-18 14:57:23 -07:00
@@ -0,0 +1,94 @@
+#undef MMC_STRPCL
+#undef MMC_STAT
+#undef MMC_CLKRT
+#undef MMC_SPI
+#undef MMC_CMDAT
+#undef MMC_RESTO
+#undef MMC_RDTO
+#undef MMC_BLKLEN
+#undef MMC_NOB
+#undef MMC_PRTBUF
+#undef MMC_I_MASK
+#undef END_CMD_RES
+#undef PRG_DONE
+#undef DATA_TRAN_DONE
+#undef MMC_I_REG
+#undef MMC_CMD
+#undef MMC_ARGH
+#undef MMC_ARGL
+#undef MMC_RES
+#undef MMC_RXFIFO
+#undef MMC_TXFIFO
+
+#define MMC_STRPCL	0x0000
+#define STOP_CLOCK		(1 << 0)
+#define START_CLOCK		(2 << 0)
+
+#define MMC_STAT	0x0004
+#define STAT_END_CMD_RES		(1 << 13)
+#define STAT_PRG_DONE			(1 << 12)
+#define STAT_DATA_TRAN_DONE		(1 << 11)
+#define STAT_CLK_EN			(1 << 8)
+#define STAT_RECV_FIFO_FULL		(1 << 7)
+#define STAT_XMIT_FIFO_EMPTY		(1 << 6)
+#define STAT_RES_CRC_ERR		(1 << 5)
+#define STAT_SPI_READ_ERROR_TOKEN	(1 << 4)
+#define STAT_CRC_READ_ERROR		(1 << 3)
+#define STAT_CRC_WRITE_ERROR		(1 << 2)
+#define STAT_TIME_OUT_RESPONSE		(1 << 1)
+#define STAT_READ_TIME_OUT		(1 << 0)
+
+#define MMC_CLKRT	0x0008		/* 3 bit */
+
+#define MMC_SPI		0x000c
+#define SPI_CS_ADDRESS		(1 << 3)
+#define SPI_CS_EN		(1 << 2)
+#define CRC_ON			(1 << 1)
+#define SPI_EN			(1 << 0)
+
+#define MMC_CMDAT	0x0010
+#define CMDAT_DMAEN		(1 << 7)
+#define CMDAT_INIT		(1 << 6)
+#define CMDAT_BUSY		(1 << 5)
+#define CMDAT_STREAM		(1 << 4)	/* 1 = stream */
+#define CMDAT_WRITE		(1 << 3)	/* 1 = write */
+#define CMDAT_DATAEN		(1 << 2)
+#define CMDAT_RESP_NONE		(0 << 0)
+#define CMDAT_RESP_SHORT	(1 << 0)
+#define CMDAT_RESP_R2		(2 << 0)
+#define CMDAT_RESP_R3		(3 << 0)
+
+#define MMC_RESTO	0x0014	/* 7 bit */
+
+#define MMC_RDTO	0x0018	/* 16 bit */
+
+#define MMC_BLKLEN	0x001c	/* 10 bit */
+
+#define MMC_NOB		0x0020	/* 16 bit */
+
+#define MMC_PRTBUF	0x0024
+#define BUF_PART_FULL		(1 << 0)
+
+#define MMC_I_MASK	0x0028
+#define TXFIFO_WR_REQ		(1 << 6)
+#define RXFIFO_RD_REQ		(1 << 5)
+#define CLK_IS_OFF		(1 << 4)
+#define STOP_CMD		(1 << 3)
+#define END_CMD_RES		(1 << 2)
+#define PRG_DONE		(1 << 1)
+#define DATA_TRAN_DONE		(1 << 0)
+
+#define MMC_I_REG	0x002c
+/* same as MMC_I_MASK */
+
+#define MMC_CMD		0x0030
+
+#define MMC_ARGH	0x0034	/* 16 bit */
+
+#define MMC_ARGL	0x0038	/* 16 bit */
+
+#define MMC_RES		0x003c	/* 16 bit */
+
+#define MMC_RXFIFO	0x0040	/* 8 bit */
+
+#define MMC_TXFIFO	0x0044	/* 8 bit */
diff -Nru a/drivers/mtd/chips/cfi_cmdset_0001.c b/drivers/mtd/chips/cfi_cmdset_0001.c
--- a/drivers/mtd/chips/cfi_cmdset_0001.c	2004-10-18 14:56:27 -07:00
+++ b/drivers/mtd/chips/cfi_cmdset_0001.c	2004-10-18 14:56:27 -07:00
@@ -603,6 +603,8 @@
 				}
 				spin_unlock(&shared->lock);
 			}
+		} else {
+			spin_unlock(&shared->lock);
 		}
 	}
 
@@ -1437,8 +1439,7 @@
 
 	spin_unlock(chip->mutex);
 	INVALIDATE_CACHED_RANGE(map, adr, len);
-	set_current_state(TASK_UNINTERRUPTIBLE);
-	schedule_timeout((chip->erase_time*HZ)/(2*1000));
+	msleep(chip->erase_time / 2);
 	spin_lock(chip->mutex);
 
 	/* FIXME. Use a timer to check this, and return immediately. */
diff -Nru a/drivers/mtd/chips/jedec_probe.c b/drivers/mtd/chips/jedec_probe.c
--- a/drivers/mtd/chips/jedec_probe.c	2004-10-18 14:57:04 -07:00
+++ b/drivers/mtd/chips/jedec_probe.c	2004-10-18 14:57:04 -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",
@@ -1209,7 +1247,7 @@
  		.DevSize	= SIZE_256KiB,
  		.CmdSet		= P_ID_SST_PAGE,
  		.NumEraseRegions= 1,
- 		regions: {ERASEINFO(0x01000,64),
+ 		.regions = {ERASEINFO(0x01000,64),
  		}
          }, {
  		.mfr_id		= MANUFACTURER_SST,
@@ -1221,7 +1259,7 @@
  		.DevSize	= SIZE_256KiB,
  		.CmdSet		= P_ID_SST_PAGE,
  		.NumEraseRegions= 1,
- 		regions: {ERASEINFO(0x01000,64),
+ 		.regions = {ERASEINFO(0x01000,64),
  		}
 	}, {
 		.mfr_id		= MANUFACTURER_SST,
@@ -1570,7 +1608,7 @@
 			ERASEINFO(0x02000, 2),
 			ERASEINFO(0x04000, 1),
 		}
-	} 
+	}
 };
 
 
diff -Nru a/drivers/mtd/maps/Kconfig b/drivers/mtd/maps/Kconfig
--- a/drivers/mtd/maps/Kconfig	2004-10-18 14:57:04 -07:00
+++ b/drivers/mtd/maps/Kconfig	2004-10-18 14:57:04 -07:00
@@ -473,6 +473,15 @@
 	  IXDP425 and Coyote. If you have an IXP4xx based board and
 	  would like to use the flash chips on it, say 'Y'.
 
+config MTD_IXP2000
+	tristate "CFI Flash device mapped on Intel IXP2000 based systems"
+	depends on ARM && MTD_CFI && MTD_COMPLEX_MAPPINGS && ARCH_IXP2000
+	help
+	  This enables MTD access to flash devices on platforms based
+	  on Intel's IXP2000 family of network processors such as the
+	  IXDP2400 and IXDP2401. If you have an IXP2000 based board and
+	  would like to use the flash chips on it, say 'Y'.
+
 config MTD_EPXA10DB
 	tristate "CFI Flash device mapped on Epxa10db"
 	depends on ARM && MTD_CFI && MTD_PARTITIONS && ARCH_CAMELOT
diff -Nru a/drivers/mtd/maps/Makefile b/drivers/mtd/maps/Makefile
--- a/drivers/mtd/maps/Makefile	2004-10-18 14:55:46 -07:00
+++ b/drivers/mtd/maps/Makefile	2004-10-18 14:55:46 -07:00
@@ -62,5 +62,6 @@
 obj-$(CONFIG_MTD_NOR_TOTO)	+= omap-toto-flash.o
 obj-$(CONFIG_MTD_MPC1211)	+= mpc1211.o
 obj-$(CONFIG_MTD_IXP4XX)	+= ixp4xx.o
+obj-$(CONFIG_MTD_IXP2000)	+= ixp2000.o
 obj-$(CONFIG_MTD_WRSBC8260)	+= wr_sbc82xx_flash.o
 obj-$(CONFIG_MTD_DMV182)	+= dmv182.o
diff -Nru a/drivers/mtd/maps/amd76xrom.c b/drivers/mtd/maps/amd76xrom.c
--- a/drivers/mtd/maps/amd76xrom.c	2004-10-18 14:56:21 -07:00
+++ b/drivers/mtd/maps/amd76xrom.c	2004-10-18 14:56:21 -07:00
@@ -26,7 +26,7 @@
 struct amd76xrom_map_info {
 	struct map_info map;
 	struct mtd_info *mtd;
-	unsigned long window_addr;
+	void __iomem * window_addr;
 	u32 window_start, window_size;
 	struct pci_dev *pdev;
 	struct resource window_rsrc;
@@ -57,7 +57,7 @@
 		del_mtd_device(info->mtd);
 		map_destroy(info->mtd);
 		info->mtd = NULL;
-		info->map.virt = 0;
+		info->map.virt = NULL;
 	}
 	if (info->rom_rsrc.parent)
 		release_resource(&info->rom_rsrc);
@@ -65,8 +65,8 @@
 		release_resource(&info->window_rsrc);
 
 	if (info->window_addr) {
-		iounmap((void *)(info->window_addr));
-		info->window_addr = 0;
+		iounmap(info->window_addr);
+		info->window_addr = NULL;
 	}
 }
 
@@ -136,8 +136,7 @@
 		printk(KERN_NOTICE MOD_NAME " window : %x at %x\n", 
 		       window->size, window->start);
 		/* For write accesses caches are useless */
-		info->window_addr =
-			(unsigned long)ioremap_nocache(window->start,
+		info->window_addr = ioremap_nocache(window->start,
 						       window->size);
 
 		if (!info->window_addr) {
@@ -163,8 +162,8 @@
 			}
 			if (info->mtd) goto found_mtd;
 		}
-		iounmap((void *)(info->window_addr));
-		info->window_addr = 0;
+		iounmap(info->window_addr);
+		info->window_addr = NULL;
 
 		/* Disable writes through the rom window */
 		pci_read_config_byte(pdev, 0x40, &byte);
diff -Nru a/drivers/mtd/maps/ceiva.c b/drivers/mtd/maps/ceiva.c
--- a/drivers/mtd/maps/ceiva.c	2004-10-18 14:56:28 -07:00
+++ b/drivers/mtd/maps/ceiva.c	2004-10-18 14:56:28 -07:00
@@ -103,7 +103,7 @@
 	unsigned long base;
 	unsigned long size;
 	int width;
-	void *vbase;
+	void __iomem *vbase;
 	struct map_info *map;
 	struct mtd_info *mtd;
 	struct resource *res;
@@ -150,7 +150,7 @@
 			break;
 		}
 
-		clps[i].map->virt = (unsigned long)clps[i].vbase;
+		clps[i].map->virt = clps[i].vbase;
 		clps[i].map->bankwidth = clps[i].width;
 		clps[i].map->size = clps[i].size;
 
diff -Nru a/drivers/mtd/maps/edb7312.c b/drivers/mtd/maps/edb7312.c
--- a/drivers/mtd/maps/edb7312.c	2004-10-18 14:57:05 -07:00
+++ b/drivers/mtd/maps/edb7312.c	2004-10-18 14:57:05 -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-10-18 14:56:17 -07:00
+++ b/drivers/mtd/maps/impa7.c	2004-10-18 14:56:17 -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/maps/ixp2000.c b/drivers/mtd/maps/ixp2000.c
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/drivers/mtd/maps/ixp2000.c	2004-10-18 14:57:24 -07:00
@@ -0,0 +1,281 @@
+/*
+ * $Id: ixp2000.c,v 1.1 2004/09/02 00:13:41 dsaxena Exp $
+ *
+ * drivers/mtd/maps/ixp2000.c
+ *
+ * Mapping for the Intel XScale IXP2000 based systems
+ *
+ * Copyright (C) 2002 Intel Corp.
+ * Copyright (C) 2003-2004 MontaVista Software, Inc.
+ *
+ * Original Author: Naeem M Afzal <naeem.m.afzal@intel.com>
+ * Maintainer: Deepak Saxena <dsaxena@plexity.net>
+ *
+ * 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/module.h>
+#include <linux/types.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/string.h>
+#include <linux/mtd/mtd.h>
+#include <linux/mtd/map.h>
+#include <linux/mtd/partitions.h>
+#include <linux/ioport.h>
+#include <linux/device.h>
+
+#include <asm/io.h>
+#include <asm/hardware.h>
+#include <asm/mach-types.h>
+#include <asm/mach/flash.h>
+
+#include <linux/reboot.h>
+
+struct ixp2000_flash_info {
+	struct		mtd_info *mtd;
+	struct		map_info map;
+	struct		mtd_partition *partitions;
+	struct		resource *res;
+	int		nr_banks;
+};
+
+static inline unsigned long flash_bank_setup(struct map_info *map, unsigned long ofs)
+{
+	unsigned long (*set_bank)(unsigned long) =
+		(unsigned long(*)(unsigned long))map->map_priv_2;
+
+	return (set_bank ? set_bank(ofs) : ofs);
+}
+
+#ifdef __ARMEB__
+/*
+ * Rev A0 and A1 of IXP2400 silicon have a broken addressing unit which
+ * causes the lower address bits to be XORed with 0x11 on 8 bit accesses
+ * and XORed with 0x10 on 16 bit accesses. See the spec update, erratta 44.
+ */
+static int errata44_workaround = 0;
+
+static inline unsigned long address_fix8_write(unsigned long addr)
+{
+	if (errata44_workaround) {
+		return (addr ^ 3);
+	}
+	return addr;
+}
+#else
+
+#define address_fix8_write(x)	(x)
+#endif
+
+static map_word ixp2000_flash_read8(struct map_info *map, unsigned long ofs)
+{
+	map_word val;
+
+	val.x[0] =  *((u8 *)(map->map_priv_1 + flash_bank_setup(map, ofs)));
+	return val;
+}
+
+/*
+ * We can't use the standard memcpy due to the broken SlowPort
+ * address translation on rev A0 and A1 silicon and the fact that
+ * we have banked flash.
+ */
+static void ixp2000_flash_copy_from(struct map_info *map, void *to,
+			      unsigned long from, ssize_t len)
+{
+	from = flash_bank_setup(map, from);
+	while(len--)
+		*(__u8 *) to++ = *(__u8 *)(map->map_priv_1 + from++);
+}
+
+static void ixp2000_flash_write8(struct map_info *map, map_word d, unsigned long ofs)
+{
+	*(__u8 *) (address_fix8_write(map->map_priv_1 +
+				      flash_bank_setup(map, ofs))) = d.x[0];
+}
+
+static void ixp2000_flash_copy_to(struct map_info *map, unsigned long to,
+			    const void *from, ssize_t len)
+{
+	to = flash_bank_setup(map, to);
+	while(len--) {
+		unsigned long tmp = address_fix8_write(map->map_priv_1 + to++);
+		*(__u8 *)(tmp) = *(__u8 *)(from++);
+	}
+}
+
+
+static int ixp2000_flash_remove(struct device *_dev)
+{
+	struct platform_device *dev = to_platform_device(_dev);
+	struct flash_platform_data *plat = dev->dev.platform_data;
+	struct ixp2000_flash_info *info = dev_get_drvdata(&dev->dev);
+
+	dev_set_drvdata(&dev->dev, NULL);
+
+	if(!info)
+		return 0;
+
+	if (info->mtd) {
+		del_mtd_partitions(info->mtd);
+		map_destroy(info->mtd);
+	}
+	if (info->map.map_priv_1)
+		iounmap((void *) info->map.map_priv_1);
+
+	if (info->partitions)
+		kfree(info->partitions);
+
+	if (info->res) {
+		release_resource(info->res);
+		kfree(info->res);
+	}
+
+	if (plat->exit)
+		plat->exit();
+
+	return 0;
+}
+
+
+static int ixp2000_flash_probe(struct device *_dev)
+{
+	static const char *probes[] = { "RedBoot", "cmdlinepart", NULL };
+	struct platform_device *dev = to_platform_device(_dev);
+	struct ixp2000_flash_data *ixp_data = dev->dev.platform_data;
+	struct flash_platform_data *plat;
+	struct ixp2000_flash_info *info;
+	unsigned long window_size;
+	int err = -1;
+
+	if (!ixp_data)
+		return -ENODEV;
+
+	plat = ixp_data->platform_data;
+	if (!plat)
+		return -ENODEV;
+
+	window_size = dev->resource->end - dev->resource->start + 1;
+	dev_info(_dev, "Probe of IXP2000 flash(%d banks x %dM)\n",
+			ixp_data->nr_banks, ((u32)window_size >> 20));
+
+	if (plat->width != 1) {
+		dev_err(_dev, "IXP2000 MTD map only supports 8-bit mode, asking for %d\n",
+				plat->width * 8);
+		return -EIO;
+	}
+
+	info = kmalloc(sizeof(struct ixp2000_flash_info), GFP_KERNEL);
+	if(!info) {
+		err = -ENOMEM;
+		goto Error;
+	}
+	memzero(info, sizeof(struct ixp2000_flash_info));
+
+	dev_set_drvdata(&dev->dev, info);
+
+	/*
+	 * Tell the MTD layer we're not 1:1 mapped so that it does
+	 * not attempt to do a direct access on us.
+	 */
+	info->map.phys = NO_XIP;
+
+	info->nr_banks = ixp_data->nr_banks;
+	info->map.size = ixp_data->nr_banks * window_size;
+	info->map.bankwidth = 1;
+
+	/*
+ 	 * map_priv_2 is used to store a ptr to to the bank_setup routine
+ 	 */
+	info->map.map_priv_2 = (u32) ixp_data->bank_setup;
+
+	info->map.name = dev->dev.bus_id;
+	info->map.read = ixp2000_flash_read8;
+	info->map.write = ixp2000_flash_write8;
+	info->map.copy_from = ixp2000_flash_copy_from;
+	info->map.copy_to = ixp2000_flash_copy_to;
+
+	info->res = request_mem_region(dev->resource->start,
+			dev->resource->end - dev->resource->start + 1,
+			dev->dev.bus_id);
+	if (!info->res) {
+		dev_err(_dev, "Could not reserve memory region\n");
+		err = -ENOMEM;
+		goto Error;
+	}
+
+	info->map.map_priv_1 =
+	    (unsigned long) ioremap(dev->resource->start,
+				    dev->resource->end - dev->resource->start + 1);
+	if (!info->map.map_priv_1) {
+		dev_err(_dev, "Failed to ioremap flash region\n");
+		err = -EIO;
+		goto Error;
+	}
+
+	/*
+	 * Setup read mode for FLASH
+	 */
+	*IXP2000_SLOWPORT_FRM = 1;
+
+#if defined(__ARMEB__)
+	/*
+	 * Enable errata 44 workaround for NPUs with broken slowport
+	 */
+
+	errata44_workaround = ixp2000_has_broken_slowport();
+	dev_info(_dev, "Errata 44 workaround %s\n",
+	       errata44_workaround ? "enabled" : "disabled");
+#endif
+
+	info->mtd = do_map_probe(plat->map_name, &info->map);
+	if (!info->mtd) {
+		dev_err(_dev, "map_probe failed\n");
+		err = -ENXIO;
+		goto Error;
+	}
+	info->mtd->owner = THIS_MODULE;
+
+	err = parse_mtd_partitions(info->mtd, probes, &info->partitions, 0);
+	if (err > 0) {
+		err = add_mtd_partitions(info->mtd, info->partitions, err);
+		if(err)
+			dev_err(_dev, "Could not parse partitions\n");
+	}
+
+	if (err)
+		goto Error;
+
+	return 0;
+
+Error:
+	ixp2000_flash_remove(_dev);
+	return err;
+}
+
+static struct device_driver ixp2000_flash_driver = {
+	.name		= "IXP2000-Flash",
+	.bus		= &platform_bus_type,
+	.probe		= &ixp2000_flash_probe,
+	.remove		= &ixp2000_flash_remove
+};
+
+static int __init ixp2000_flash_init(void)
+{
+	return driver_register(&ixp2000_flash_driver);
+}
+
+static void __exit ixp2000_flash_exit(void)
+{
+	driver_unregister(&ixp2000_flash_driver);
+}
+
+module_init(ixp2000_flash_init);
+module_exit(ixp2000_flash_exit);
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Deepak Saxena <dsaxena@plexity.net>");
+
diff -Nru a/drivers/mtd/maps/ixp4xx.c b/drivers/mtd/maps/ixp4xx.c
--- a/drivers/mtd/maps/ixp4xx.c	2004-10-18 14:55:54 -07:00
+++ b/drivers/mtd/maps/ixp4xx.c	2004-10-18 14:55:54 -07:00
@@ -1,5 +1,5 @@
 /*
- * $Id: ixp4xx.c,v 1.3 2004/07/12 22:38:29 dwmw2 Exp $
+ * $Id: ixp4xx.c,v 1.6 2004/09/17 00:25:06 gleixner Exp $
  *
  * drivers/mtd/maps/ixp4xx.c
  *
@@ -69,9 +69,22 @@
 		dest[len - 1] = BYTE0(src[i]);
 }
 
+/*
+ * Unaligned writes are ignored, causing the 8-bit
+ * probe to fail and proceed to the 16-bit probe (which succeeds).
+ */
+static void ixp4xx_probe_write16(struct map_info *map, map_word d, unsigned long adr)
+{
+	if (!(adr & 1))
+	       *(__u16 *) (map->map_priv_1 + adr) = d.x[0];
+}
+
+/*
+ * Fast write16 function without the probing check above
+ */
 static void ixp4xx_write16(struct map_info *map, map_word d, unsigned long adr)
 {
-	*(__u16 *) (map->map_priv_1 + adr) = d.x[0];
+       *(__u16 *) (map->map_priv_1 + adr) = d.x[0];
 }
 
 struct ixp4xx_flash_info {
@@ -88,6 +101,7 @@
 	struct platform_device *dev = to_platform_device(_dev);
 	struct flash_platform_data *plat = dev->dev.platform_data;
 	struct ixp4xx_flash_info *info = dev_get_drvdata(&dev->dev);
+	map_word d;
 
 	dev_set_drvdata(&dev->dev, NULL);
 
@@ -97,7 +111,8 @@
 	/*
 	 * This is required for a soft reboot to work.
 	 */
-	ixp4xx_write16(&info->map, 0xff, 0x55 * 0x2);
+	d.x[0] = 0xff;
+	ixp4xx_write16(&info->map, d, 0x55 * 0x2);
 
 	if (info->mtd) {
 		del_mtd_partitions(info->mtd);
@@ -169,7 +184,7 @@
 	info->map.bankwidth = 2;
 	info->map.name = dev->dev.bus_id;
 	info->map.read = ixp4xx_read16,
-	info->map.write = ixp4xx_write16,
+	info->map.write = ixp4xx_probe_write16,
 	info->map.copy_from = ixp4xx_copy_from,
 
 	info->res = request_mem_region(dev->resource->start, 
@@ -182,7 +197,7 @@
 	}
 
 	info->map.map_priv_1 =
-	    (unsigned long) ioremap(dev->resource->start, 
+	    (void __iomem *) ioremap(dev->resource->start,
 				    dev->resource->end - dev->resource->start + 1);
 	if (!info->map.map_priv_1) {
 		printk(KERN_ERR "IXP4XXFlash: Failed to ioremap region\n");
@@ -197,6 +212,9 @@
 		goto Error;
 	}
 	info->mtd->owner = THIS_MODULE;
+
+	/* Use the fast version */
+	info->map.write = ixp4xx_write16,
 
 	err = parse_mtd_partitions(info->mtd, probes, &info->partitions, 0);
 	if (err > 0) {
diff -Nru a/drivers/mtd/maps/lubbock-flash.c b/drivers/mtd/maps/lubbock-flash.c
--- a/drivers/mtd/maps/lubbock-flash.c	2004-10-18 14:56:48 -07:00
+++ b/drivers/mtd/maps/lubbock-flash.c	2004-10-18 14:56:48 -07:00
@@ -1,5 +1,5 @@
 /*
- * $Id: lubbock-flash.c,v 1.15 2004/07/12 21:59:44 dwmw2 Exp $
+ * $Id: lubbock-flash.c,v 1.18 2004/09/28 18:54:40 nico Exp $
  *
  * Map driver for the Lubbock developer platform.
  *
@@ -15,11 +15,13 @@
 #include <linux/types.h>
 #include <linux/kernel.h>
 #include <linux/init.h>
+#include <linux/dma-mapping.h>
 #include <linux/mtd/mtd.h>
 #include <linux/mtd/map.h>
 #include <linux/mtd/partitions.h>
 #include <asm/io.h>
 #include <asm/hardware.h>
+#include <asm/arch/pxa-regs.h>
 #include <asm/arch/lubbock.h>
 
 
@@ -82,16 +84,14 @@
 	lubbock_maps[flashboot].name = "Lubbock Boot ROM";
 
 	for (i = 0; i < 2; i++) {
-		lubbock_maps[i].virt = (unsigned long)ioremap(lubbock_maps[i].phys, WINDOW_SIZE);
+		lubbock_maps[i].virt = (void __iomem *)ioremap(lubbock_maps[i].phys, WINDOW_SIZE);
 		if (!lubbock_maps[i].virt) {
 			printk(KERN_WARNING "Failed to ioremap %s\n", lubbock_maps[i].name);
 			if (!ret)
 				ret = -ENOMEM;
 			continue;
 		}
-		lubbock_maps[i].cached = __ioremap(lubbock_maps[i].phys,
-						   WINDOW_SIZE,
-						   L_PTE_CACHEABLE, 1);
+		lubbock_maps[i].cached = ioremap_cached(lubbock_maps[i].phys, WINDOW_SIZE);
 		if (!lubbock_maps[i].cached)
 			printk(KERN_WARNING "Failed to ioremap cached %s\n", lubbock_maps[i].name);
 		simple_map_init(&lubbock_maps[i]);
diff -Nru a/drivers/mtd/maps/nettel.c b/drivers/mtd/maps/nettel.c
--- a/drivers/mtd/maps/nettel.c	2004-10-18 14:56:21 -07:00
+++ b/drivers/mtd/maps/nettel.c	2004-10-18 14:56:21 -07:00
@@ -180,7 +180,7 @@
 	if (mtd) {
 		nettel_erase.mtd = mtd;
 		nettel_erase.callback = nettel_erasecallback;
-		nettel_erase.callback = 0;
+		nettel_erase.callback = NULL;
 		nettel_erase.addr = 0;
 		nettel_erase.len = mtd->size;
 		nettel_erase.priv = (u_long) &wait_q;
diff -Nru a/drivers/mtd/maps/sa1100-flash.c b/drivers/mtd/maps/sa1100-flash.c
--- a/drivers/mtd/maps/sa1100-flash.c	2004-10-18 14:56:20 -07:00
+++ b/drivers/mtd/maps/sa1100-flash.c	2004-10-18 14:56:20 -07:00
@@ -885,7 +885,7 @@
 	unsigned long base;
 	unsigned long size;
 	int width;
-	void *vbase;
+	void __iomem *vbase;
         void (*set_vpp)(struct map_info *, int);
 	struct map_info *map;
 	struct mtd_info *mtd;
@@ -932,7 +932,7 @@
 			break;
 		}
 
-		sa[i].map->virt = (unsigned long)sa[i].vbase;
+		sa[i].map->virt = sa[i].vbase;
 		sa[i].map->phys = sa[i].base;
 		sa[i].map->set_vpp = sa[i].set_vpp;
 		sa[i].map->bankwidth = sa[i].width;
diff -Nru a/drivers/mtd/maps/tqm8xxl.c b/drivers/mtd/maps/tqm8xxl.c
--- a/drivers/mtd/maps/tqm8xxl.c	2004-10-18 14:56:17 -07:00
+++ b/drivers/mtd/maps/tqm8xxl.c	2004-10-18 14:56:17 -07:00
@@ -50,7 +50,7 @@
 static struct map_info* map_banks[FLASH_BANK_MAX];
 static struct mtd_part_def part_banks[FLASH_BANK_MAX];
 static unsigned long num_banks;
-static unsigned long start_scan_addr;
+static void __iomem *start_scan_addr;
 
 /*
  * Here are partition information for all known TQM8xxL series devices.
@@ -121,7 +121,7 @@
 	flash_size = bd->bi_flashsize;
 
 	//request maximum flash size address space
-	start_scan_addr = (unsigned long)ioremap(flash_addr, flash_size);
+	start_scan_addr = ioremap(flash_addr, flash_size);
 	if (!start_scan_addr) {
 		printk(KERN_WARNING "%s:Failed to ioremap address:0x%x\n", __FUNCTION__, flash_addr);
 		return -EIO;
@@ -231,7 +231,7 @@
 		}
 	}
 error:
-	iounmap((void *)start_scan_addr);
+	iounmap(start_scan_addr);
 	return ret;
 }
 
@@ -250,7 +250,7 @@
 	}
 
 	if (start_scan_addr) {
-		iounmap((void *)start_scan_addr);
+		iounmap(start_scan_addr);
 		start_scan_addr = 0;
 	}
 }
diff -Nru a/drivers/mtd/maps/uclinux.c b/drivers/mtd/maps/uclinux.c
--- a/drivers/mtd/maps/uclinux.c	2004-10-18 14:57:03 -07:00
+++ b/drivers/mtd/maps/uclinux.c	2004-10-18 14:57:03 -07:00
@@ -69,10 +69,9 @@
 	printk("uclinux[mtd]: RAM probe address=0x%x size=0x%x\n",
 	       	(int) mapp->map_priv_2, (int) mapp->size);
 
-	mapp->virt = (unsigned long)
-		ioremap_nocache(mapp->phys, mapp->size);
+	mapp->virt = ioremap_nocache(mapp->phys, mapp->size);
 
-	if (mapp->virt == 0) {
+	if (!mapp->virt) {
 		printk("uclinux[mtd]: ioremap_nocache() failed\n");
 		return(-EIO);
 	}
@@ -82,7 +81,7 @@
 	mtd = do_map_probe("map_ram", mapp);
 	if (!mtd) {
 		printk("uclinux[mtd]: failed to find a mapping?\n");
-		iounmap((void *) mapp->virt);
+		iounmap(mapp->virt);
 		return(-ENXIO);
 	}
 		
diff -Nru a/drivers/mtd/nftlmount.c b/drivers/mtd/nftlmount.c
--- a/drivers/mtd/nftlmount.c	2004-10-18 14:56:34 -07:00
+++ b/drivers/mtd/nftlmount.c	2004-10-18 14:56:34 -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/3c507.c b/drivers/net/3c507.c
--- a/drivers/net/3c507.c	2004-10-18 14:56:49 -07:00
+++ b/drivers/net/3c507.c	2004-10-18 14:56:49 -07:00
@@ -294,6 +294,7 @@
 static void hardware_send_packet(struct net_device *dev, void *buf, short length, short pad);
 static void init_82586_mem(struct net_device *dev);
 static struct ethtool_ops netdev_ethtool_ops;
+static void init_rx_bufs(struct net_device *);
 
 static int io = 0x300;
 static int irq;
@@ -612,7 +613,6 @@
 	}
 
 	if ((status & 0x0070) != 0x0040 && netif_running(dev)) {
-		static void init_rx_bufs(struct net_device *);
 		/* The Rx unit is not ready, it must be hung.  Restart the receiver by
 		   initializing the rx buffers, and issuing an Rx start command. */
 		if (net_debug)
diff -Nru a/drivers/net/3c527.c b/drivers/net/3c527.c
--- a/drivers/net/3c527.c	2004-10-18 14:56:32 -07:00
+++ b/drivers/net/3c527.c	2004-10-18 14:56:32 -07:00
@@ -751,18 +751,15 @@
 	
 	rx_base=lp->rx_chain;
 
-	for(i=0; i<RX_RING_LEN; i++)
-	{
+	for(i=0; i<RX_RING_LEN; i++) {
 		lp->rx_ring[i].skb=alloc_skb(1532, GFP_KERNEL);
-		skb_reserve(lp->rx_ring[i].skb, 18);  
-
-		if(lp->rx_ring[i].skb==NULL)
-		{
-			for(;i>=0;i--)
+		if (lp->rx_ring[i].skb==NULL) {
+			for (;i>=0;i--)
 				kfree_skb(lp->rx_ring[i].skb);
 			return -ENOBUFS;
 		}
-		
+		skb_reserve(lp->rx_ring[i].skb, 18);
+
 		p=isa_bus_to_virt(lp->base+rx_base);
 				
 		p->control=0;
diff -Nru a/drivers/net/3c59x.c b/drivers/net/3c59x.c
--- a/drivers/net/3c59x.c	2004-10-18 14:55:53 -07:00
+++ b/drivers/net/3c59x.c	2004-10-18 14:55:53 -07:00
@@ -695,7 +695,7 @@
 	Wn2_ResetOptions=12,
 };
 enum Window3 {			/* Window 3: MAC/config bits. */
-	Wn3_Config=0, Wn3_MAC_Ctrl=6, Wn3_Options=8,
+	Wn3_Config=0, Wn3_MaxPktSize=4, Wn3_MAC_Ctrl=6, Wn3_Options=8,
 };
 
 #define BFEXT(value, offset, bitcount)  \
@@ -723,7 +723,8 @@
 	Media_LnkBeat = 0x0800,
 };
 enum Window7 {					/* Window 7: Bus Master control. */
-	Wn7_MasterAddr = 0, Wn7_MasterLen = 6, Wn7_MasterStatus = 12,
+	Wn7_MasterAddr = 0, Wn7_VlanEtherType=4, Wn7_MasterLen = 6,
+	Wn7_MasterStatus = 12,
 };
 /* Boomerang bus master control registers. */
 enum MasterCtrl {
@@ -819,7 +820,8 @@
 		pm_state_valid:1,				/* power_state[] has sane contents */
 		open:1,
 		medialock:1,
-		must_free_region:1;				/* Flag: if zero, Cardbus owns the I/O region */
+		must_free_region:1,				/* Flag: if zero, Cardbus owns the I/O region */
+		large_frames:1;			/* accept large frames */
 	int drv_flags;
 	u16 status_enable;
 	u16 intr_enable;
@@ -900,10 +902,14 @@
 static void update_stats(long ioaddr, struct net_device *dev);
 static struct net_device_stats *vortex_get_stats(struct net_device *dev);
 static void set_rx_mode(struct net_device *dev);
+#ifdef CONFIG_PCI
 static int vortex_ioctl(struct net_device *dev, struct ifreq *rq, int cmd);
+#endif
 static void vortex_tx_timeout(struct net_device *dev);
 static void acpi_set_WOL(struct net_device *dev);
 static struct ethtool_ops vortex_ethtool_ops;
+static void set_8021q_mode(struct net_device *dev, int enable);
+
 
 /* This driver uses 'options' to pass the media type, full-duplex flag, etc. */
 /* Option count limit only -- unlimited interfaces are supported. */
@@ -1164,6 +1170,7 @@
 	dev->base_addr = ioaddr;
 	dev->irq = irq;
 	dev->mtu = mtu;
+	vp->large_frames = mtu > 1500;
 	vp->drv_flags = vci->drv_flags;
 	vp->has_nway = (vci->drv_flags & HAS_NWAY) ? 1 : 0;
 	vp->io_size = vci->io_size;
@@ -1290,6 +1297,13 @@
 		for (i = 0; i < 6; i++)
 			printk("%c%2.2x", i ? ':' : ' ', dev->dev_addr[i]);
 	}
+	/* Unfortunately an all zero eeprom passes the checksum and this
+	   gets found in the wild in failure cases. Crypto is hard 8) */
+	if (!is_valid_ether_addr(dev->dev_addr)) {
+		retval = -EINVAL;
+		printk(KERN_ERR "*** EEPROM MAC address is invalid.\n");
+		goto free_ring;	/* With every pack */
+	}
 	EL3WINDOW(2);
 	for (i = 0; i < 6; i++)
 		outb(dev->dev_addr[i], ioaddr + i);
@@ -1468,7 +1482,9 @@
 
 	dev->stop = vortex_close;
 	dev->get_stats = vortex_get_stats;
+#ifdef CONFIG_PCI
 	dev->do_ioctl = vortex_ioctl;
+#endif
 	dev->ethtool_ops = &vortex_ethtool_ops;
 	dev->set_multicast_list = set_rx_mode;
 	dev->tx_timeout = vortex_tx_timeout;
@@ -1616,7 +1632,7 @@
 
 	/* Set the full-duplex bit. */
 	outw(	((vp->info1 & 0x8000) || vp->full_duplex ? 0x20 : 0) |
-		 	(dev->mtu > 1500 ? 0x40 : 0) |
+		 	(vp->large_frames ? 0x40 : 0) |
 			((vp->full_duplex && vp->flow_ctrl && vp->partner_flow_ctrl) ? 0x100 : 0),
 			ioaddr + Wn3_MAC_Ctrl);
 
@@ -1700,6 +1716,8 @@
 	}
 	/* Set receiver mode: presumably accept b-case and phys addr only. */
 	set_rx_mode(dev);
+	/* enable 802.1q tagged frames */
+	set_8021q_mode(dev, 1);
 	outw(StatsEnable, ioaddr + EL3_CMD); /* Turn on statistics. */
 
 //	issue_and_wait(dev, SetTxStart|0x07ff);
@@ -1842,7 +1860,7 @@
 						/* Set the full-duplex bit. */
 						EL3WINDOW(3);
 						outw(	(vp->full_duplex ? 0x20 : 0) |
-								(dev->mtu > 1500 ? 0x40 : 0) |
+								(vp->large_frames ? 0x40 : 0) |
 								((vp->full_duplex && vp->flow_ctrl && vp->partner_flow_ctrl) ? 0x100 : 0),
 								ioaddr + Wn3_MAC_Ctrl);
 						if (vortex_debug > 1)
@@ -2068,6 +2086,8 @@
 			issue_and_wait(dev, RxReset|0x07);
 			/* Set the Rx filter to the current state. */
 			set_rx_mode(dev);
+			/* enable 802.1q VLAN tagged frames */
+			set_8021q_mode(dev, 1);
 			outw(RxEnable, ioaddr + EL3_CMD); /* Re-enable the receiver. */
 			outw(AckIntr | HostError, ioaddr + EL3_CMD);
 		}
@@ -2672,6 +2692,9 @@
 	outw(RxDisable, ioaddr + EL3_CMD);
 	outw(TxDisable, ioaddr + EL3_CMD);
 
+	/* Disable receiving 802.1q tagged frames */
+	set_8021q_mode(dev, 0);
+
 	if (dev->if_port == XCVR_10base2)
 		/* Turn off thinnet power.  Green! */
 		outw(StopCoax, ioaddr + EL3_CMD);
@@ -2868,6 +2891,7 @@
 	.get_drvinfo =		vortex_get_drvinfo,
 };
 
+#ifdef CONFIG_PCI
 static int vortex_do_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
 {
 	struct vortex_private *vp = netdev_priv(dev);
@@ -2925,6 +2949,7 @@
 
 	return err;
 }
+#endif
 
 
 /* Pre-Cyclone chips have no documented multicast filter, so the only
@@ -2946,6 +2971,61 @@
 
 	outw(new_mode, ioaddr + EL3_CMD);
 }
+
+#if defined(CONFIG_VLAN_8021Q) || defined(CONFIG_VLAN_8021Q_MODULE)
+/* Setup the card so that it can receive frames with an 802.1q VLAN tag.
+   Note that this must be done after each RxReset due to some backwards
+   compatibility logic in the Cyclone and Tornado ASICs */
+
+/* The Ethernet Type used for 802.1q tagged frames */
+#define VLAN_ETHER_TYPE 0x8100
+
+static void set_8021q_mode(struct net_device *dev, int enable)
+{
+	struct vortex_private *vp = (struct vortex_private *)dev->priv;
+	long ioaddr = dev->base_addr;
+	int old_window = inw(ioaddr + EL3_CMD);
+	int mac_ctrl;
+
+	if ((vp->drv_flags&IS_CYCLONE) || (vp->drv_flags&IS_TORNADO)) {
+		/* cyclone and tornado chipsets can recognize 802.1q
+		 * tagged frames and treat them correctly */
+
+		int max_pkt_size = dev->mtu+14;	/* MTU+Ethernet header */
+		if (enable)
+			max_pkt_size += 4;	/* 802.1Q VLAN tag */
+
+		EL3WINDOW(3);
+		outw(max_pkt_size, ioaddr+Wn3_MaxPktSize);
+
+		/* set VlanEtherType to let the hardware checksumming
+		   treat tagged frames correctly */
+		EL3WINDOW(7);
+		outw(VLAN_ETHER_TYPE, ioaddr+Wn7_VlanEtherType);
+	} else {
+		/* on older cards we have to enable large frames */
+
+		vp->large_frames = dev->mtu > 1500 || enable;
+
+		EL3WINDOW(3);
+		mac_ctrl = inw(ioaddr+Wn3_MAC_Ctrl);
+		if (vp->large_frames)
+			mac_ctrl |= 0x40;
+		else
+			mac_ctrl &= ~0x40;
+		outw(mac_ctrl, ioaddr+Wn3_MAC_Ctrl);
+	}
+
+	EL3WINDOW(old_window);
+}
+#else
+
+static void set_8021q_mode(struct net_device *dev, int enable)
+{
+}
+
+
+#endif
 
 /* MII transceiver control section.
    Read and write the MII registers using software-generated serial
diff -Nru a/drivers/net/8139cp.c b/drivers/net/8139cp.c
--- a/drivers/net/8139cp.c	2004-10-18 14:56:29 -07:00
+++ b/drivers/net/8139cp.c	2004-10-18 14:56:29 -07:00
@@ -1698,7 +1698,7 @@
 	}
 
 	/* Configure DMA attributes. */
-	if ((sizeof(dma_addr_t) > 32) &&
+	if ((sizeof(dma_addr_t) > 4) &&
 	    !pci_set_consistent_dma_mask(pdev, 0xffffffffffffffffULL) &&
 	    !pci_set_dma_mask(pdev, 0xffffffffffffffffULL)) {
 		pci_using_dac = 1;
diff -Nru a/drivers/net/8139too.c b/drivers/net/8139too.c
--- a/drivers/net/8139too.c	2004-10-18 14:55:46 -07:00
+++ b/drivers/net/8139too.c	2004-10-18 14:55:46 -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>");
@@ -613,7 +614,7 @@
 static int mdio_read (struct net_device *dev, int phy_id, int location);
 static void mdio_write (struct net_device *dev, int phy_id, int location,
 			int val);
-static inline void rtl8139_start_thread(struct net_device *dev);
+static void rtl8139_start_thread(struct net_device *dev);
 static void rtl8139_tx_timeout (struct net_device *dev);
 static void rtl8139_init_ring (struct net_device *dev);
 static int rtl8139_start_xmit (struct sk_buff *skb,
@@ -1643,7 +1644,7 @@
 	complete_and_exit (&tp->thr_exited, 0);
 }
 
-static inline void rtl8139_start_thread(struct net_device *dev)
+static void rtl8139_start_thread(struct net_device *dev)
 {
 	struct rtl8139_private *tp = dev->priv;
 
@@ -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/8390.c b/drivers/net/8390.c
--- a/drivers/net/8390.c	2004-10-18 14:55:55 -07:00
+++ b/drivers/net/8390.c	2004-10-18 14:55:55 -07:00
@@ -41,6 +41,8 @@
 			  module by all drivers that require it.
   Alan Cox		: Spinlocking work, added 'BUG_83C690'
   Paul Gortmaker	: Separate out Tx timeout code from Tx path.
+  Paul Gortmaker	: Remove old unused single Tx buffer code.
+  Hayato Fujiwara	: Add m32r support.
 
   Sources:
   The National Semiconductor LAN Databook, and the 3Com 3c503 databook.
@@ -218,6 +220,15 @@
 	int txsr, isr, tickssofar = jiffies - dev->trans_start;
 	unsigned long flags;
 
+#if defined(CONFIG_M32R) && defined(CONFIG_SMP)
+	unsigned long icucr;
+
+	local_irq_save(flags);
+	icucr = inl(ICUCR1);
+	icucr |= M32R_ICUCR_ISMOD11;
+	outl(icucr, ICUCR1);
+	local_irq_restore(flags);
+#endif
 	ei_local->stat.tx_errors++;
 
 	spin_lock_irqsave(&ei_local->page_lock, flags);
@@ -289,8 +300,6 @@
 
 	send_length = ETH_ZLEN < length ? length : ETH_ZLEN;
     
-#ifdef EI_PINGPONG
-
 	/*
 	 * We have two Tx slots available for use. Find the first free
 	 * slot, and then perform some sanity checks. With two Tx bufs,
@@ -309,7 +318,7 @@
 	}
 	else if (ei_local->tx2 == 0) 
 	{
-		output_page = ei_local->tx_start_page + TX_1X_PAGES;
+		output_page = ei_local->tx_start_page + TX_PAGES/2;
 		ei_local->tx2 = send_length;
 		if (ei_debug  &&  ei_local->tx1 > 0)
 			printk(KERN_DEBUG "%s: idle transmitter, tx1=%d, lasttx=%d, txing=%d.\n",
@@ -366,28 +375,6 @@
 	else
 		netif_start_queue(dev);
 
-#else	/* EI_PINGPONG */
-
-	/*
-	 * Only one Tx buffer in use. You need two Tx bufs to come close to
-	 * back-to-back transmits. Expect a 20 -> 25% performance hit on
-	 * reasonable hardware if you only use one Tx buffer.
-	 */
-
-	if (length == send_length)
-		ei_block_output(dev, length, skb->data, ei_local->tx_start_page);
-	else {
-		memset(scratch, 0, ETH_ZLEN);
-		memcpy(scratch, skb->data, skb->len);
-		ei_block_output(dev, ETH_ZLEN, scratch, ei_local->tx_start_page);
-	}
-	ei_local->txing = 1;
-	NS8390_trigger_send(dev, send_length, ei_local->tx_start_page);
-	dev->trans_start = jiffies;
-	netif_stop_queue(dev);
-
-#endif	/* EI_PINGPONG */
-
 	/* Turn 8390 interrupts back on. */
 	ei_local->irqlock = 0;
 	outb_p(ENISR_ALL, e8390_base + EN0_IMR);
@@ -590,8 +577,6 @@
     
 	outb_p(ENISR_TX, e8390_base + EN0_ISR); /* Ack intr. */
 
-#ifdef EI_PINGPONG
-
 	/*
 	 * There are two Tx buffers, see which one finished, and trigger
 	 * the send of another one if it exists.
@@ -633,13 +618,6 @@
 	}
 //	else printk(KERN_WARNING "%s: unexpected TX-done interrupt, lasttx=%d.\n",
 //			dev->name, ei_local->lasttx);
-
-#else	/* EI_PINGPONG */
-	/*
-	 *  Single Tx buffer: mark it free so another packet can be loaded.
-	 */
-	ei_local->txing = 0;
-#endif
 
 	/* Minimize Tx latency: update the statistics after we restart TXing. */
 	if (status & ENTSR_COL)
diff -Nru a/drivers/net/8390.h b/drivers/net/8390.h
--- a/drivers/net/8390.h	2004-10-18 14:56:48 -07:00
+++ b/drivers/net/8390.h	2004-10-18 14:56:48 -07:00
@@ -12,17 +12,7 @@
 #include <linux/ioport.h>
 #include <linux/skbuff.h>
 
-#define TX_2X_PAGES 12
-#define TX_1X_PAGES 6
-
-/* Should always use two Tx slots to get back-to-back transmits. */
-#define EI_PINGPONG
-
-#ifdef EI_PINGPONG
-#define TX_PAGES TX_2X_PAGES
-#else
-#define TX_PAGES TX_1X_PAGES
-#endif
+#define TX_PAGES 12	/* Two Tx slots */
 
 #define ETHER_ADDR_LEN 6
 
diff -Nru a/drivers/net/Kconfig b/drivers/net/Kconfig
--- a/drivers/net/Kconfig	2004-10-18 14:56:50 -07:00
+++ b/drivers/net/Kconfig	2004-10-18 14:56:50 -07:00
@@ -200,7 +200,7 @@
 
 config MACE
 	tristate "MACE (Power Mac ethernet) support"
-	depends on NET_ETHERNET && PPC_PMAC
+	depends on NET_ETHERNET && PPC_PMAC && PPC32
 	select CRC32
 	help
 	  Power Macintoshes and clones with Ethernet built-in on the
@@ -223,7 +223,7 @@
 
 config BMAC
 	tristate "BMAC (G3 ethernet) support"
-	depends on NET_ETHERNET && PPC_PMAC
+	depends on NET_ETHERNET && PPC_PMAC && PPC32
 	select CRC32
 	help
 	  Say Y for support of BMAC Ethernet interfaces. These are used on G3
@@ -817,7 +817,7 @@
 	tristate "SMC 91C9x/91C1xxx support"
 	select CRC32
 	select MII
-	depends on NET_ETHERNET && (ARM || REDWOOD_5 || REDWOOD_6)
+	depends on NET_ETHERNET && (ARM || REDWOOD_5 || REDWOOD_6 || M32R)
 	help
 	  This is a driver for SMC's 91x series of Ethernet chipsets,
 	  including the SMC91C94 and the SMC91C111. Say Y if you want it
@@ -1075,7 +1075,7 @@
 
 config NE2000
 	tristate "NE2000/NE1000 support"
-	depends on NET_ISA || (Q40 && m)
+	depends on NET_ISA || (Q40 && m) || M32R
 	select CRC32
 	---help---
 	  If you have a network (Ethernet) card of this type, say Y and read
@@ -1353,7 +1353,7 @@
 
 config CS89x0
 	tristate "CS89x0 support"
-	depends on NET_PCI && ISA
+	depends on NET_PCI && (ISA || ARCH_IXDP2X01)
 	---help---
 	  Support for CS89x0 chipset based Ethernet cards. If you have a
 	  network (Ethernet) card of this type, say Y and read the
@@ -1746,12 +1746,13 @@
 	tristate "VIA Velocity support"
 	depends on NET_PCI && PCI
 	select CRC32
+	select CRC_CCITT
 	select MII
 	help
 	  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)"
@@ -2043,6 +2044,23 @@
 	  To compile this driver as a module, choose M here: the module
 	  will be called r8169.  This is recommended.
 
+config R8169_NAPI
+	bool "Use Rx and Tx Polling (NAPI) (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"
 	depends on PCI
@@ -2130,6 +2148,45 @@
 
 	  To compile this driver as a module, choose M here: the module
 	  will be called tg3.  This is recommended.
+
+config GIANFAR
+	tristate "Gianfar Ethernet"
+	depends on 85xx
+	help
+	  This driver supports the Gigabit TSEC on the MPC85xx 
+	  family of chips, and the FEC on the 8540
+
+config GFAR_NAPI
+	bool "NAPI Support"
+	depends on GIANFAR
+
+config MV643XX_ETH
+	tristate "MV-643XX Ethernet support"
+	depends on MOMENCO_OCELOT_C || MOMENCO_JAGUAR_ATX
+	help
+	  This driver supports the gigabit Ethernet on the Marvell MV643XX
+	  chipset which is used in the Momenco Ocelot C and Jaguar ATX.
+
+config MV643XX_ETH_0
+	bool "MV-643XX Port 0"
+	depends on MV643XX_ETH
+	help
+	  This enables support for Port 0 of the Marvell MV643XX Gigabit
+	  Ethernet.
+
+config MV643XX_ETH_1
+	bool "MV-643XX Port 1"
+	depends on MV643XX_ETH
+	help
+	  This enables support for Port 1 of the Marvell MV643XX Gigabit
+	  Ethernet.
+
+config MV643XX_ETH_2
+	bool "MV-643XX Port 2"
+	depends on MV643XX_ETH
+	help
+	  This enables support for Port 2 of the Marvell MV643XX Gigabit
+	  Ethernet.
 
 endmenu
 
diff -Nru a/drivers/net/Makefile b/drivers/net/Makefile
--- a/drivers/net/Makefile	2004-10-18 14:56:27 -07:00
+++ b/drivers/net/Makefile	2004-10-18 14:56:27 -07:00
@@ -10,6 +10,9 @@
 obj-$(CONFIG_IBM_EMAC) += ibm_emac/
 obj-$(CONFIG_IXGB) += ixgb/
 obj-$(CONFIG_BONDING) += bonding/
+obj-$(CONFIG_GIANFAR) += gianfar_driver.o
+
+gianfar_driver-objs := gianfar.o gianfar_ethtool.o gianfar_phy.o
 
 #
 # link order important here
@@ -94,6 +97,8 @@
 obj-$(CONFIG_B44) += b44.o
 obj-$(CONFIG_FORCEDETH) += forcedeth.o
 obj-$(CONFIG_NE_H8300) += ne-h8300.o 8390.o
+
+obj-$(CONFIG_MV643XX_ETH) += mv643xx_eth.o
 
 obj-$(CONFIG_PPP) += ppp_generic.o slhc.o
 obj-$(CONFIG_PPP_ASYNC) += ppp_async.o
diff -Nru a/drivers/net/acenic.c b/drivers/net/acenic.c
--- a/drivers/net/acenic.c	2004-10-18 14:56:29 -07:00
+++ b/drivers/net/acenic.c	2004-10-18 14:56:29 -07:00
@@ -52,6 +52,7 @@
 
 #include <linux/config.h>
 #include <linux/module.h>
+#include <linux/moduleparam.h>
 #include <linux/version.h>
 #include <linux/types.h>
 #include <linux/errno.h>
@@ -425,13 +426,15 @@
 MODULE_AUTHOR("Jes Sorensen <jes@trained-monkey.org>");
 MODULE_LICENSE("GPL");
 MODULE_DESCRIPTION("AceNIC/3C985/GA620 Gigabit Ethernet driver");
-MODULE_PARM(link, "1-" __MODULE_STRING(8) "i");
-MODULE_PARM(trace, "1-" __MODULE_STRING(8) "i");
-MODULE_PARM(tx_coal_tick, "1-" __MODULE_STRING(8) "i");
-MODULE_PARM(max_tx_desc, "1-" __MODULE_STRING(8) "i");
-MODULE_PARM(rx_coal_tick, "1-" __MODULE_STRING(8) "i");
-MODULE_PARM(max_rx_desc, "1-" __MODULE_STRING(8) "i");
-MODULE_PARM(tx_ratio, "1-" __MODULE_STRING(8) "i");
+
+static int num_params;
+module_param_array(link, int, num_params, 0);
+module_param_array(trace, int, num_params, 0);
+module_param_array(tx_coal_tick, int, num_params, 0);
+module_param_array(max_tx_desc, int, num_params, 0);
+module_param_array(rx_coal_tick, int, num_params, 0);
+module_param_array(max_rx_desc, int, num_params, 0);
+module_param_array(tx_ratio, int, num_params, 0);
 MODULE_PARM_DESC(link, "AceNIC/3C985/NetGear link state");
 MODULE_PARM_DESC(trace, "AceNIC/3C985/NetGear firmware trace level");
 MODULE_PARM_DESC(tx_coal_tick, "AceNIC/3C985/GA620 max clock ticks to wait from first tx descriptor arrives");
@@ -474,6 +477,7 @@
 
 	ap = dev->priv;
 	ap->pdev = pdev;
+	ap->name = pci_name(pdev);
 
 	dev->features |= NETIF_F_SG | NETIF_F_IP_CSUM;
 #if ACENIC_DO_VLAN
@@ -516,7 +520,7 @@
 	if (!(ap->pci_command & PCI_COMMAND_MEMORY)) {
 		printk(KERN_INFO "%s: Enabling PCI Memory Mapped "
 		       "access - was not enabled by BIOS/Firmware\n",
-		       dev->name);
+		       ap->name);
 		ap->pci_command = ap->pci_command | PCI_COMMAND_MEMORY;
 		pci_write_config_word(ap->pdev, PCI_COMMAND,
 				      ap->pci_command);
@@ -539,55 +543,40 @@
 	if (!ap->regs) {
 		printk(KERN_ERR "%s:  Unable to map I/O register, "
 		       "AceNIC %i will be disabled.\n",
-		       dev->name, boards_found);
+		       ap->name, boards_found);
 		goto fail_free_netdev;
 	}
 
 	switch(pdev->vendor) {
 	case PCI_VENDOR_ID_ALTEON:
 		if (pdev->device == PCI_DEVICE_ID_FARALLON_PN9100T) {
-			strncpy(ap->name, "Farallon PN9100-T "
-				"Gigabit Ethernet", sizeof (ap->name));
 			printk(KERN_INFO "%s: Farallon PN9100-T ",
-			       dev->name);
+			       ap->name);
 		} else {
-			strncpy(ap->name, "AceNIC Gigabit Ethernet",
-				sizeof (ap->name));
 			printk(KERN_INFO "%s: Alteon AceNIC ",
-			       dev->name);
+			       ap->name);
 		}
 		break;
 	case PCI_VENDOR_ID_3COM:
-		strncpy(ap->name, "3Com 3C985 Gigabit Ethernet",
-			sizeof (ap->name));
-		printk(KERN_INFO "%s: 3Com 3C985 ", dev->name);
+		printk(KERN_INFO "%s: 3Com 3C985 ", ap->name);
 		break;
 	case PCI_VENDOR_ID_NETGEAR:
-		strncpy(ap->name, "NetGear GA620 Gigabit Ethernet",
-			sizeof (ap->name));
-		printk(KERN_INFO "%s: NetGear GA620 ", dev->name);
+		printk(KERN_INFO "%s: NetGear GA620 ", ap->name);
 		break;
 	case PCI_VENDOR_ID_DEC:
 		if (pdev->device == PCI_DEVICE_ID_FARALLON_PN9000SX) {
-			strncpy(ap->name, "Farallon PN9000-SX "
-				"Gigabit Ethernet", sizeof (ap->name));
 			printk(KERN_INFO "%s: Farallon PN9000-SX ",
-			       dev->name);
+			       ap->name);
 			break;
 		}
 	case PCI_VENDOR_ID_SGI:
-		strncpy(ap->name, "SGI AceNIC Gigabit Ethernet",
-			sizeof (ap->name));
-		printk(KERN_INFO "%s: SGI AceNIC ", dev->name);
+		printk(KERN_INFO "%s: SGI AceNIC ", ap->name);
 		break;
 	default:
- 		strncpy(ap->name, "Unknown AceNIC based Gigabit "
-			"Ethernet", sizeof (ap->name));
-		printk(KERN_INFO "%s: Unknown AceNIC ", dev->name);
+		printk(KERN_INFO "%s: Unknown AceNIC ", ap->name);
 		break;
 	}
 
-	ap->name [sizeof (ap->name) - 1] = '\0';
 	printk("Gigabit Ethernet at 0x%08lx, ", dev->base_addr);
 #ifdef __sparc__
 	printk("irq %s\n", __irq_itoa(pdev->irq));
@@ -622,6 +611,7 @@
 		printk(KERN_ERR "acenic: device registration failed\n");
 		goto fail_uninit;
 	}
+	ap->name = dev->name;
 
 	if (ap->pci_using_dac)
 		dev->features |= NETIF_F_HIGHDMA;
@@ -641,7 +631,7 @@
 static void __devexit acenic_remove_one(struct pci_dev *pdev)
 {
 	struct net_device *dev = pci_get_drvdata(pdev);
-	struct ace_private *ap = dev->priv;
+	struct ace_private *ap = netdev_priv(dev);
 	struct ace_regs *regs = ap->regs;
 	short i;
 
@@ -752,7 +742,7 @@
 
 static void ace_free_descriptors(struct net_device *dev)
 {
-	struct ace_private *ap = dev->priv;
+	struct ace_private *ap = netdev_priv(dev);
 	int size;
 
 	if (ap->rx_std_ring != NULL) {
@@ -802,7 +792,7 @@
 
 static int ace_allocate_descriptors(struct net_device *dev)
 {
-	struct ace_private *ap = dev->priv;
+	struct ace_private *ap = netdev_priv(dev);
 	int size;
 
 	size = (sizeof(struct rx_desc) *
@@ -873,7 +863,7 @@
 {
 	struct ace_private *ap;
 
-	ap = dev->priv;
+	ap = netdev_priv(dev);
 
 	ace_free_descriptors(dev);
 
@@ -921,7 +911,7 @@
 	short i;
 	unsigned char cache_size;
 
-	ap = dev->priv;
+	ap = netdev_priv(dev);
 	regs = ap->regs;
 
 	board_idx = ap->board_idx;
@@ -1387,7 +1377,7 @@
 	if (board_idx == BOARD_IDX_OVERFLOW) {
 		printk(KERN_WARNING "%s: more than %i NICs detected, "
 		       "ignoring module parameters!\n",
-		       dev->name, ACE_MAX_MOD_PARMS);
+		       ap->name, ACE_MAX_MOD_PARMS);
 	} else if (board_idx >= 0) {
 		if (tx_coal_tick[board_idx])
 			writel(tx_coal_tick[board_idx],
@@ -1426,7 +1416,7 @@
 
 		if (option & 0x01) {
 			printk(KERN_INFO "%s: Setting half duplex link\n",
-			       dev->name);
+			       ap->name);
 			tmp &= ~LNK_FULL_DUPLEX;
 		}
 		if (option & 0x02)
@@ -1439,7 +1429,7 @@
 			tmp |= LNK_1000MB;
 		if ((option & 0x70) == 0) {
 			printk(KERN_WARNING "%s: No media speed specified, "
-			       "forcing auto negotiation\n", dev->name);
+			       "forcing auto negotiation\n", ap->name);
 			tmp |= LNK_NEGOTIATE | LNK_1000MB |
 				LNK_100MB | LNK_10MB;
 		}
@@ -1447,12 +1437,12 @@
 			tmp |= LNK_NEG_FCTL;
 		else
 			printk(KERN_INFO "%s: Disabling flow control "
-			       "negotiation\n", dev->name);
+			       "negotiation\n", ap->name);
 		if (option & 0x200)
 			tmp |= LNK_RX_FLOW_CTL_Y;
 		if ((option & 0x400) && (ap->version >= 2)) {
 			printk(KERN_INFO "%s: Enabling TX flow control\n",
-			       dev->name);
+			       ap->name);
 			tmp |= LNK_TX_FLOW_CTL_Y;
 		}
 	}
@@ -1509,7 +1499,7 @@
 		cpu_relax();
 
 	if (!ap->fw_running) {
-		printk(KERN_ERR "%s: Firmware NOT running!\n", dev->name);
+		printk(KERN_ERR "%s: Firmware NOT running!\n", ap->name);
 
 		ace_dump_trace(ap);
 		writel(readl(&regs->CpuCtrl) | CPU_HALT, &regs->CpuCtrl);
@@ -1542,13 +1532,13 @@
 		ace_load_std_rx_ring(ap, RX_RING_SIZE);
 	else
 		printk(KERN_ERR "%s: Someone is busy refilling the RX ring\n",
-		       dev->name);
+		       ap->name);
 	if (ap->version >= 2) {
 		if (!test_and_set_bit(0, &ap->mini_refill_busy))
 			ace_load_mini_rx_ring(ap, RX_MINI_SIZE);
 		else
 			printk(KERN_ERR "%s: Someone is busy refilling "
-			       "the RX mini ring\n", dev->name);
+			       "the RX mini ring\n", ap->name);
 	}
 	return 0;
 
@@ -1564,7 +1554,7 @@
 	struct ace_regs *regs;
 	int board_idx;
 
-	ap = dev->priv;
+	ap = netdev_priv(dev);
 	regs = ap->regs;
 
 	board_idx = ap->board_idx;
@@ -1604,7 +1594,7 @@
 static void ace_watchdog(struct net_device *data)
 {
 	struct net_device *dev = data;
-	struct ace_private *ap = dev->priv;
+	struct ace_private *ap = netdev_priv(dev);
 	struct ace_regs *regs = ap->regs;
 
 	/*
@@ -1878,13 +1868,13 @@
 {
 	struct ace_private *ap;
 
-	ap = dev->priv;
+	ap = netdev_priv(dev);
 
 	while (evtcsm != evtprd) {
 		switch (ap->evt_ring[evtcsm].evt) {
 		case E_FW_RUNNING:
 			printk(KERN_INFO "%s: Firmware up and running\n",
-			       dev->name);
+			       ap->name);
 			ap->fw_running = 1;
 			wmb();
 			break;
@@ -1899,7 +1889,7 @@
 				u32 state = readl(&ap->regs->GigLnkState);
 				printk(KERN_WARNING "%s: Optical link UP "
 				       "(%s Duplex, Flow Control: %s%s)\n",
-				       dev->name,
+				       ap->name,
 				       state & LNK_FULL_DUPLEX ? "Full":"Half",
 				       state & LNK_TX_FLOW_CTL_Y ? "TX " : "",
 				       state & LNK_RX_FLOW_CTL_Y ? "RX" : "");
@@ -1907,15 +1897,15 @@
 			}
 			case E_C_LINK_DOWN:
 				printk(KERN_WARNING "%s: Optical link DOWN\n",
-				       dev->name);
+				       ap->name);
 				break;
 			case E_C_LINK_10_100:
 				printk(KERN_WARNING "%s: 10/100BaseT link "
-				       "UP\n", dev->name);
+				       "UP\n", ap->name);
 				break;
 			default:
 				printk(KERN_ERR "%s: Unknown optical link "
-				       "state %02x\n", dev->name, code);
+				       "state %02x\n", ap->name, code);
 			}
 			break;
 		}
@@ -1923,19 +1913,19 @@
 			switch(ap->evt_ring[evtcsm].code) {
 			case E_C_ERR_INVAL_CMD:
 				printk(KERN_ERR "%s: invalid command error\n",
-				       dev->name);
+				       ap->name);
 				break;
 			case E_C_ERR_UNIMP_CMD:
 				printk(KERN_ERR "%s: unimplemented command "
-				       "error\n", dev->name);
+				       "error\n", ap->name);
 				break;
 			case E_C_ERR_BAD_CFG:
 				printk(KERN_ERR "%s: bad config error\n",
-				       dev->name);
+				       ap->name);
 				break;
 			default:
 				printk(KERN_ERR "%s: unknown error %02x\n",
-				       dev->name, ap->evt_ring[evtcsm].code);
+				       ap->name, ap->evt_ring[evtcsm].code);
 			}
 			break;
 		case E_RESET_JUMBO_RNG:
@@ -1964,13 +1954,13 @@
 			ap->jumbo = 0;
 			ap->rx_jumbo_skbprd = 0;
 			printk(KERN_INFO "%s: Jumbo ring flushed\n",
-			       dev->name);
+			       ap->name);
 			clear_bit(0, &ap->jumbo_refill_busy);
 			break;
 		}
 		default:
 			printk(KERN_ERR "%s: Unhandled event 0x%02x\n",
-			       dev->name, ap->evt_ring[evtcsm].evt);
+			       ap->name, ap->evt_ring[evtcsm].evt);
 		}
 		evtcsm = (evtcsm + 1) % EVT_RING_ENTRIES;
 	}
@@ -1981,7 +1971,7 @@
 
 static void ace_rx_int(struct net_device *dev, u32 rxretprd, u32 rxretcsm)
 {
-	struct ace_private *ap = dev->priv;
+	struct ace_private *ap = netdev_priv(dev);
 	u32 idx;
 	int mini_count = 0, std_count = 0;
 
@@ -2108,7 +2098,7 @@
 static inline void ace_tx_int(struct net_device *dev,
 			      u32 txcsm, u32 idx)
 {
-	struct ace_private *ap = dev->priv;
+	struct ace_private *ap = netdev_priv(dev);
 
 	do {
 		struct sk_buff *skb;
@@ -2181,7 +2171,7 @@
 	u32 txcsm, rxretcsm, rxretprd;
 	u32 evtcsm, evtprd;
 
-	ap = dev->priv;
+	ap = netdev_priv(dev);
 	regs = ap->regs;
 
 	/*
@@ -2304,7 +2294,7 @@
 #if ACENIC_DO_VLAN
 static void ace_vlan_rx_register(struct net_device *dev, struct vlan_group *grp)
 {
-	struct ace_private *ap = dev->priv;
+	struct ace_private *ap = netdev_priv(dev);
 	unsigned long flags;
 
 	local_irq_save(flags);
@@ -2319,7 +2309,7 @@
 
 static void ace_vlan_rx_kill_vid(struct net_device *dev, unsigned short vid)
 {
-	struct ace_private *ap = dev->priv;
+	struct ace_private *ap = netdev_priv(dev);
 	unsigned long flags;
 
 	local_irq_save(flags);
@@ -2340,7 +2330,7 @@
 	struct ace_regs *regs;
 	struct cmd cmd;
 
-	ap = dev->priv;
+	ap = netdev_priv(dev);
 	regs = ap->regs;
 
 	if (!(ap->fw_running)) {
@@ -2407,7 +2397,7 @@
 	 */
 	netif_stop_queue(dev);
 
-	ap = dev->priv;
+	ap = netdev_priv(dev);
 	regs = ap->regs;
 
 	if (ap->promisc) {
@@ -2522,7 +2512,7 @@
 
 static int ace_start_xmit(struct sk_buff *skb, struct net_device *dev)
 {
-	struct ace_private *ap = dev->priv;
+	struct ace_private *ap = netdev_priv(dev);
 	struct ace_regs *regs = ap->regs;
 	struct tx_desc *desc;
 	u32 idx, flagsize;
@@ -2661,7 +2651,7 @@
 
 static int ace_change_mtu(struct net_device *dev, int new_mtu)
 {
-	struct ace_private *ap = dev->priv;
+	struct ace_private *ap = netdev_priv(dev);
 	struct ace_regs *regs = ap->regs;
 
 	if (new_mtu > ACE_JUMBO_MTU)
@@ -2698,7 +2688,7 @@
 
 static int ace_get_settings(struct net_device *dev, struct ethtool_cmd *ecmd)
 {
-	struct ace_private *ap = dev->priv;
+	struct ace_private *ap = netdev_priv(dev);
 	struct ace_regs *regs = ap->regs;
 	u32 link;
 
@@ -2751,7 +2741,7 @@
 
 static int ace_set_settings(struct net_device *dev, struct ethtool_cmd *ecmd)
 {
-	struct ace_private *ap = dev->priv;
+	struct ace_private *ap = netdev_priv(dev);
 	struct ace_regs *regs = ap->regs;
 	u32 link, speed;
 
@@ -2814,7 +2804,7 @@
 static void ace_get_drvinfo(struct net_device *dev, 
 			    struct ethtool_drvinfo *info)
 {
-	struct ace_private *ap = dev->priv;
+	struct ace_private *ap = netdev_priv(dev);
 
 	strlcpy(info->driver, "acenic", sizeof(info->driver));
 	snprintf(info->version, sizeof(info->version), "%i.%i.%i", 
@@ -2844,7 +2834,7 @@
 
 	da = (u8 *)dev->dev_addr;
 
-	regs = ((struct ace_private *)dev->priv)->regs;
+	regs = ((struct ace_private *)netdev_priv(dev))->regs;
 	writel(da[0] << 8 | da[1], &regs->MacAddrHi);
 	writel((da[2] << 24) | (da[3] << 16) | (da[4] << 8) | da[5],
 	       &regs->MacAddrLo);
@@ -2860,7 +2850,7 @@
 
 static void ace_set_multicast_list(struct net_device *dev)
 {
-	struct ace_private *ap = dev->priv;
+	struct ace_private *ap = netdev_priv(dev);
 	struct ace_regs *regs = ap->regs;
 	struct cmd cmd;
 
@@ -2914,7 +2904,7 @@
 
 static struct net_device_stats *ace_get_stats(struct net_device *dev)
 {
-	struct ace_private *ap = dev->priv;
+	struct ace_private *ap = netdev_priv(dev);
 	struct ace_mac_stats *mac_stats =
 		(struct ace_mac_stats *)ap->regs->Stats;
 
@@ -2997,12 +2987,12 @@
 	struct ace_private *ap;
 	struct ace_regs *regs;
 
-	ap = dev->priv;
+	ap = netdev_priv(dev);
 	regs = ap->regs;
 
 	if (!(readl(&regs->CpuCtrl) & CPU_HALTED)) {
 		printk(KERN_ERR "%s: trying to download firmware while the "
-		       "CPU is running!\n", dev->name);
+		       "CPU is running!\n", ap->name);
 		return -EFAULT;
 	}
 
@@ -3178,6 +3168,7 @@
 static int __init read_eeprom_byte(struct net_device *dev,
 				   unsigned long offset)
 {
+	struct ace_private *ap;
 	struct ace_regs *regs;
 	unsigned long flags;
 	u32 local;
@@ -3187,10 +3178,11 @@
 	if (!dev) {
 		printk(KERN_ERR "No device!\n");
 		result = -ENODEV;
-		goto eeprom_read_error;
+		goto out;
 	}
 
-	regs = ((struct ace_private *)dev->priv)->regs;
+	ap = netdev_priv(dev);
+	regs = ap->regs;
 
 	/*
 	 * Don't take interrupts on this CPU will bit banging
@@ -3203,7 +3195,7 @@
 	eeprom_prep(regs, EEPROM_WRITE_SELECT);
 	if (eeprom_check_ack(regs)) {
 		local_irq_restore(flags);
-		printk(KERN_ERR "%s: Unable to sync eeprom\n", dev->name);
+		printk(KERN_ERR "%s: Unable to sync eeprom\n", ap->name);
 		result = -EIO;
 		goto eeprom_read_error;
 	}
@@ -3212,7 +3204,7 @@
 	if (eeprom_check_ack(regs)) {
 		local_irq_restore(flags);
 		printk(KERN_ERR "%s: Unable to set address byte 0\n",
-		       dev->name);
+		       ap->name);
 		result = -EIO;
 		goto eeprom_read_error;
 	}
@@ -3221,7 +3213,7 @@
 	if (eeprom_check_ack(regs)) {
 		local_irq_restore(flags);
 		printk(KERN_ERR "%s: Unable to set address byte 1\n",
-		       dev->name);
+		       ap->name);
 		result = -EIO;
 		goto eeprom_read_error;
 	}
@@ -3231,7 +3223,7 @@
 	if (eeprom_check_ack(regs)) {
 		local_irq_restore(flags);
 		printk(KERN_ERR "%s: Unable to set READ_SELECT\n",
-		       dev->name);
+		       ap->name);
 		result = -EIO;
 		goto eeprom_read_error;
 	}
@@ -3288,7 +3280,7 @@
 
  eeprom_read_error:
 	printk(KERN_ERR "%s: Unable to read eeprom byte 0x%02lx\n",
-	       dev->name, offset);
+	       ap->name, offset);
 	goto out;
 }
 
diff -Nru a/drivers/net/acenic.h b/drivers/net/acenic.h
--- a/drivers/net/acenic.h	2004-10-18 14:56:29 -07:00
+++ b/drivers/net/acenic.h	2004-10-18 14:56:29 -07:00
@@ -693,7 +693,7 @@
 	int			board_idx;
 	u16			pci_command;
 	u8			pci_latency;
-	char			name[48];
+	const char		*name;
 #ifdef INDEX_DEBUG
 	spinlock_t		debug_lock
 				__attribute__ ((aligned (SMP_CACHE_BYTES)));
diff -Nru a/drivers/net/amd8111e.c b/drivers/net/amd8111e.c
--- a/drivers/net/amd8111e.c	2004-10-18 14:56:33 -07:00
+++ b/drivers/net/amd8111e.c	2004-10-18 14:56:33 -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/arcnet/arc-rimi.c b/drivers/net/arcnet/arc-rimi.c
--- a/drivers/net/arcnet/arc-rimi.c	2004-10-18 14:55:54 -07:00
+++ b/drivers/net/arcnet/arc-rimi.c	2004-10-18 14:55:54 -07:00
@@ -231,7 +231,7 @@
 static int arcrimi_reset(struct net_device *dev, int really_reset)
 {
 	struct arcnet_local *lp = (struct arcnet_local *) dev->priv;
-	void *ioaddr = lp->mem_start + 0x800;
+	void __iomem *ioaddr = lp->mem_start + 0x800;
 
 	BUGMSG(D_INIT, "Resetting %s (status=%02Xh)\n", dev->name, ASTATUS());
 
@@ -252,7 +252,7 @@
 static void arcrimi_setmask(struct net_device *dev, int mask)
 {
 	struct arcnet_local *lp = (struct arcnet_local *) dev->priv;
-	void *ioaddr = lp->mem_start + 0x800;
+	void __iomem *ioaddr = lp->mem_start + 0x800;
 
 	AINTMASK(mask);
 }
@@ -260,7 +260,7 @@
 static int arcrimi_status(struct net_device *dev)
 {
 	struct arcnet_local *lp = (struct arcnet_local *) dev->priv;
-	void *ioaddr = lp->mem_start + 0x800;
+	void __iomem *ioaddr = lp->mem_start + 0x800;
 
 	return ASTATUS();
 }
@@ -268,7 +268,7 @@
 static void arcrimi_command(struct net_device *dev, int cmd)
 {
 	struct arcnet_local *lp = (struct arcnet_local *) dev->priv;
-	void *ioaddr = lp->mem_start + 0x800;
+	void __iomem *ioaddr = lp->mem_start + 0x800;
 
 	ACOMMAND(cmd);
 }
@@ -277,7 +277,7 @@
 				 void *buf, int count)
 {
 	struct arcnet_local *lp = (struct arcnet_local *) dev->priv;
-	void *memaddr = lp->mem_start + 0x800 + bufnum * 512 + offset;
+	void __iomem *memaddr = lp->mem_start + 0x800 + bufnum * 512 + offset;
 	TIME("memcpy_toio", count, memcpy_toio(memaddr, buf, count));
 }
 
@@ -286,7 +286,7 @@
 				   void *buf, int count)
 {
 	struct arcnet_local *lp = (struct arcnet_local *) dev->priv;
-	void *memaddr = lp->mem_start + 0x800 + bufnum * 512 + offset;
+	void __iomem *memaddr = lp->mem_start + 0x800 + bufnum * 512 + offset;
 	TIME("memcpy_fromio", count, memcpy_fromio(buf, memaddr, count));
 }
 
diff -Nru a/drivers/net/arcnet/arcnet.c b/drivers/net/arcnet/arcnet.c
--- a/drivers/net/arcnet/arcnet.c	2004-10-18 14:56:48 -07:00
+++ b/drivers/net/arcnet/arcnet.c	2004-10-18 14:56:48 -07:00
@@ -401,7 +401,8 @@
 	lp->rfc1201.sequence = 1;
 
 	/* bring up the hardware driver */
-	lp->hw.open(dev);
+	if (lp->hw.open)
+		lp->hw.open(dev);
 
 	if (dev->dev_addr[0] == 0)
 		BUGMSG(D_NORMAL, "WARNING!  Station address 00 is reserved "
diff -Nru a/drivers/net/arcnet/com90xx.c b/drivers/net/arcnet/com90xx.c
--- a/drivers/net/arcnet/com90xx.c	2004-10-18 14:56:48 -07:00
+++ b/drivers/net/arcnet/com90xx.c	2004-10-18 14:56:48 -07:00
@@ -566,7 +566,7 @@
 				 void *buf, int count)
 {
 	struct arcnet_local *lp = (struct arcnet_local *) dev->priv;
-	void *memaddr = lp->mem_start + bufnum * 512 + offset;
+	void __iomem *memaddr = lp->mem_start + bufnum * 512 + offset;
 	TIME("memcpy_toio", count, memcpy_toio(memaddr, buf, count));
 }
 
@@ -575,7 +575,7 @@
 				   void *buf, int count)
 {
 	struct arcnet_local *lp = (struct arcnet_local *) dev->priv;
-	void *memaddr = lp->mem_start + bufnum * 512 + offset;
+	void __iomem *memaddr = lp->mem_start + bufnum * 512 + offset;
 	TIME("memcpy_fromio", count, memcpy_fromio(buf, memaddr, count));
 }
 
diff -Nru a/drivers/net/b44.c b/drivers/net/b44.c
--- a/drivers/net/b44.c	2004-10-18 14:56:29 -07:00
+++ b/drivers/net/b44.c	2004-10-18 14:56:29 -07:00
@@ -98,13 +98,24 @@
 static void b44_init_rings(struct b44 *);
 static void b44_init_hw(struct b44 *);
 
+static inline unsigned long br32(const struct b44 *bp, unsigned long reg)
+{
+	return readl(bp->regs + reg);
+}
+
+static inline void bw32(const struct b44 *bp, 
+			unsigned long reg, unsigned long val)
+{
+	writel(val, bp->regs + reg);
+}
+
 static int b44_wait_bit(struct b44 *bp, unsigned long reg,
 			u32 bit, unsigned long timeout, const int clear)
 {
 	unsigned long i;
 
 	for (i = 0; i < timeout; i++) {
-		u32 val = br32(reg);
+		u32 val = br32(bp, reg);
 
 		if (clear && !(val & bit))
 			break;
@@ -168,7 +179,7 @@
 
 static u32 ssb_get_core_rev(struct b44 *bp)
 {
-	return (br32(B44_SBIDHIGH) & SBIDHIGH_RC_MASK);
+	return (br32(bp, B44_SBIDHIGH) & SBIDHIGH_RC_MASK);
 }
 
 static u32 ssb_pci_setup(struct b44 *bp, u32 cores)
@@ -180,13 +191,13 @@
 			       ssb_get_addr(bp, SBID_REG_PCI, 0));
 	pci_rev = ssb_get_core_rev(bp);
 
-	val = br32(B44_SBINTVEC);
+	val = br32(bp, B44_SBINTVEC);
 	val |= cores;
-	bw32(B44_SBINTVEC, val);
+	bw32(bp, B44_SBINTVEC, val);
 
-	val = br32(SSB_PCI_TRANS_2);
+	val = br32(bp, SSB_PCI_TRANS_2);
 	val |= SSB_PCI_PREF | SSB_PCI_BURST;
-	bw32(SSB_PCI_TRANS_2, val);
+	bw32(bp, SSB_PCI_TRANS_2, val);
 
 	pci_write_config_dword(bp->pdev, SSB_BAR0_WIN, bar_orig);
 
@@ -195,18 +206,18 @@
 
 static void ssb_core_disable(struct b44 *bp)
 {
-	if (br32(B44_SBTMSLOW) & SBTMSLOW_RESET)
+	if (br32(bp, B44_SBTMSLOW) & SBTMSLOW_RESET)
 		return;
 
-	bw32(B44_SBTMSLOW, (SBTMSLOW_REJECT | SBTMSLOW_CLOCK));
+	bw32(bp, B44_SBTMSLOW, (SBTMSLOW_REJECT | SBTMSLOW_CLOCK));
 	b44_wait_bit(bp, B44_SBTMSLOW, SBTMSLOW_REJECT, 100000, 0);
 	b44_wait_bit(bp, B44_SBTMSHIGH, SBTMSHIGH_BUSY, 100000, 1);
-	bw32(B44_SBTMSLOW, (SBTMSLOW_FGC | SBTMSLOW_CLOCK |
+	bw32(bp, B44_SBTMSLOW, (SBTMSLOW_FGC | SBTMSLOW_CLOCK |
 			    SBTMSLOW_REJECT | SBTMSLOW_RESET));
-	br32(B44_SBTMSLOW);
+	br32(bp, B44_SBTMSLOW);
 	udelay(1);
-	bw32(B44_SBTMSLOW, (SBTMSLOW_REJECT | SBTMSLOW_RESET));
-	br32(B44_SBTMSLOW);
+	bw32(bp, B44_SBTMSLOW, (SBTMSLOW_REJECT | SBTMSLOW_RESET));
+	br32(bp, B44_SBTMSLOW);
 	udelay(1);
 }
 
@@ -215,31 +226,31 @@
 	u32 val;
 
 	ssb_core_disable(bp);
-	bw32(B44_SBTMSLOW, (SBTMSLOW_RESET | SBTMSLOW_CLOCK | SBTMSLOW_FGC));
-	br32(B44_SBTMSLOW);
+	bw32(bp, B44_SBTMSLOW, (SBTMSLOW_RESET | SBTMSLOW_CLOCK | SBTMSLOW_FGC));
+	br32(bp, B44_SBTMSLOW);
 	udelay(1);
 
 	/* Clear SERR if set, this is a hw bug workaround.  */
-	if (br32(B44_SBTMSHIGH) & SBTMSHIGH_SERR)
-		bw32(B44_SBTMSHIGH, 0);
+	if (br32(bp, B44_SBTMSHIGH) & SBTMSHIGH_SERR)
+		bw32(bp, B44_SBTMSHIGH, 0);
 
-	val = br32(B44_SBIMSTATE);
+	val = br32(bp, B44_SBIMSTATE);
 	if (val & (SBIMSTATE_IBE | SBIMSTATE_TO))
-		bw32(B44_SBIMSTATE, val & ~(SBIMSTATE_IBE | SBIMSTATE_TO));
+		bw32(bp, B44_SBIMSTATE, val & ~(SBIMSTATE_IBE | SBIMSTATE_TO));
 
-	bw32(B44_SBTMSLOW, (SBTMSLOW_CLOCK | SBTMSLOW_FGC));
-	br32(B44_SBTMSLOW);
+	bw32(bp, B44_SBTMSLOW, (SBTMSLOW_CLOCK | SBTMSLOW_FGC));
+	br32(bp, B44_SBTMSLOW);
 	udelay(1);
 
-	bw32(B44_SBTMSLOW, (SBTMSLOW_CLOCK));
-	br32(B44_SBTMSLOW);
+	bw32(bp, B44_SBTMSLOW, (SBTMSLOW_CLOCK));
+	br32(bp, B44_SBTMSLOW);
 	udelay(1);
 }
 
 static int ssb_core_unit(struct b44 *bp)
 {
 #if 0
-	u32 val = br32(B44_SBADMATCH0);
+	u32 val = br32(bp, B44_SBADMATCH0);
 	u32 base;
 
 	type = val & SBADMATCH0_TYPE_MASK;
@@ -263,7 +274,7 @@
 
 static int ssb_is_core_up(struct b44 *bp)
 {
-	return ((br32(B44_SBTMSLOW) & (SBTMSLOW_RESET | SBTMSLOW_REJECT | SBTMSLOW_CLOCK))
+	return ((br32(bp, B44_SBTMSLOW) & (SBTMSLOW_RESET | SBTMSLOW_REJECT | SBTMSLOW_CLOCK))
 		== SBTMSLOW_CLOCK);
 }
 
@@ -275,19 +286,19 @@
 	val |= ((u32) data[3]) << 16;
 	val |= ((u32) data[4]) <<  8;
 	val |= ((u32) data[5]) <<  0;
-	bw32(B44_CAM_DATA_LO, val);
+	bw32(bp, B44_CAM_DATA_LO, val);
 	val = (CAM_DATA_HI_VALID | 
 	       (((u32) data[0]) << 8) |
 	       (((u32) data[1]) << 0));
-	bw32(B44_CAM_DATA_HI, val);
-	bw32(B44_CAM_CTRL, (CAM_CTRL_WRITE |
+	bw32(bp, B44_CAM_DATA_HI, val);
+	bw32(bp, B44_CAM_CTRL, (CAM_CTRL_WRITE |
 			    (index << CAM_CTRL_INDEX_SHIFT)));
 	b44_wait_bit(bp, B44_CAM_CTRL, CAM_CTRL_BUSY, 100, 1);	
 }
 
 static inline void __b44_disable_ints(struct b44 *bp)
 {
-	bw32(B44_IMASK, 0);
+	bw32(bp, B44_IMASK, 0);
 }
 
 static void b44_disable_ints(struct b44 *bp)
@@ -295,34 +306,34 @@
 	__b44_disable_ints(bp);
 
 	/* Flush posted writes. */
-	br32(B44_IMASK);
+	br32(bp, B44_IMASK);
 }
 
 static void b44_enable_ints(struct b44 *bp)
 {
-	bw32(B44_IMASK, bp->imask);
+	bw32(bp, B44_IMASK, bp->imask);
 }
 
 static int b44_readphy(struct b44 *bp, int reg, u32 *val)
 {
 	int err;
 
-	bw32(B44_EMAC_ISTAT, EMAC_INT_MII);
-	bw32(B44_MDIO_DATA, (MDIO_DATA_SB_START |
+	bw32(bp, B44_EMAC_ISTAT, EMAC_INT_MII);
+	bw32(bp, B44_MDIO_DATA, (MDIO_DATA_SB_START |
 			     (MDIO_OP_READ << MDIO_DATA_OP_SHIFT) |
 			     (bp->phy_addr << MDIO_DATA_PMD_SHIFT) |
 			     (reg << MDIO_DATA_RA_SHIFT) |
 			     (MDIO_TA_VALID << MDIO_DATA_TA_SHIFT)));
 	err = b44_wait_bit(bp, B44_EMAC_ISTAT, EMAC_INT_MII, 100, 0);
-	*val = br32(B44_MDIO_DATA) & MDIO_DATA_DATA;
+	*val = br32(bp, B44_MDIO_DATA) & MDIO_DATA_DATA;
 
 	return err;
 }
 
 static int b44_writephy(struct b44 *bp, int reg, u32 val)
 {
-	bw32(B44_EMAC_ISTAT, EMAC_INT_MII);
-	bw32(B44_MDIO_DATA, (MDIO_DATA_SB_START |
+	bw32(bp, B44_EMAC_ISTAT, EMAC_INT_MII);
+	bw32(bp, B44_MDIO_DATA, (MDIO_DATA_SB_START |
 			     (MDIO_OP_WRITE << MDIO_DATA_OP_SHIFT) |
 			     (bp->phy_addr << MDIO_DATA_PMD_SHIFT) |
 			     (reg << MDIO_DATA_RA_SHIFT) |
@@ -382,20 +393,20 @@
 	bp->flags &= ~(B44_FLAG_TX_PAUSE | B44_FLAG_RX_PAUSE);
 	bp->flags |= pause_flags;
 
-	val = br32(B44_RXCONFIG);
+	val = br32(bp, B44_RXCONFIG);
 	if (pause_flags & B44_FLAG_RX_PAUSE)
 		val |= RXCONFIG_FLOW;
 	else
 		val &= ~RXCONFIG_FLOW;
-	bw32(B44_RXCONFIG, val);
+	bw32(bp, B44_RXCONFIG, val);
 
-	val = br32(B44_MAC_FLOW);
+	val = br32(bp, B44_MAC_FLOW);
 	if (pause_flags & B44_FLAG_TX_PAUSE)
 		val |= (MAC_FLOW_PAUSE_ENAB |
 			(0xc0 & MAC_FLOW_RX_HI_WATER));
 	else
 		val &= ~MAC_FLOW_PAUSE_ENAB;
-	bw32(B44_MAC_FLOW, val);
+	bw32(bp, B44_MAC_FLOW, val);
 }
 
 static void b44_set_flow_ctrl(struct b44 *bp, u32 local, u32 remote)
@@ -491,11 +502,11 @@
 
 	val = &bp->hw_stats.tx_good_octets;
 	for (reg = B44_TX_GOOD_O; reg <= B44_TX_PAUSE; reg += 4UL) {
-		*val++ += br32(reg);
+		*val++ += br32(bp, reg);
 	}
 	val = &bp->hw_stats.rx_good_octets;
 	for (reg = B44_RX_GOOD_O; reg <= B44_RX_NPAUSE; reg += 4UL) {
-		*val++ += br32(reg);
+		*val++ += br32(bp, reg);
 	}
 }
 
@@ -535,14 +546,14 @@
 
 		if (!netif_carrier_ok(bp->dev) &&
 		    (bmsr & BMSR_LSTATUS)) {
-			u32 val = br32(B44_TX_CTRL);
+			u32 val = br32(bp, B44_TX_CTRL);
 			u32 local_adv, remote_adv;
 
 			if (bp->flags & B44_FLAG_FULL_DUPLEX)
 				val |= TX_CTRL_DUPLEX;
 			else
 				val &= ~TX_CTRL_DUPLEX;
-			bw32(B44_TX_CTRL, val);
+			bw32(bp, B44_TX_CTRL, val);
 
 			if (!(bp->flags & B44_FLAG_FORCE_LINK) &&
 			    !b44_readphy(bp, MII_ADVERTISE, &local_adv) &&
@@ -587,7 +598,7 @@
 {
 	u32 cur, cons;
 
-	cur  = br32(B44_DMATX_STAT) & DMATX_STAT_CDMASK;
+	cur  = br32(bp, B44_DMATX_STAT) & DMATX_STAT_CDMASK;
 	cur /= sizeof(struct dma_desc);
 
 	/* XXX needs updating when NETIF_F_SG is supported */
@@ -611,7 +622,7 @@
 	    TX_BUFFS_AVAIL(bp) > B44_TX_WAKEUP_THRESH)
 		netif_wake_queue(bp->dev);
 
-	bw32(B44_GPTIMER, 0);
+	bw32(bp, B44_GPTIMER, 0);
 }
 
 /* Works like this.  This chip writes a 'struct rx_header" 30 bytes
@@ -708,7 +719,7 @@
 	u32 cons, prod;
 
 	received = 0;
-	prod  = br32(B44_DMARX_STAT) & DMARX_STAT_CDMASK;
+	prod  = br32(bp, B44_DMARX_STAT) & DMARX_STAT_CDMASK;
 	prod /= sizeof(struct dma_desc);
 	cons = bp->rx_cons;
 
@@ -787,7 +798,7 @@
 	}
 
 	bp->rx_cons = cons;
-	bw32(B44_DMARX_PTR, cons * sizeof(struct dma_desc));
+	bw32(bp, B44_DMARX_PTR, cons * sizeof(struct dma_desc));
 
 	return received;
 }
@@ -851,8 +862,8 @@
 
 	spin_lock_irqsave(&bp->lock, flags);
 
-	istat = br32(B44_ISTAT);
-	imask = br32(B44_IMASK);
+	istat = br32(bp, B44_ISTAT);
+	imask = br32(bp, B44_IMASK);
 
 	/* ??? What the fuck is the purpose of the interrupt mask
 	 * ??? register if we have to mask it out by hand anyways?
@@ -872,8 +883,8 @@
 			       dev->name);
 		}
 
-		bw32(B44_ISTAT, istat);
-		br32(B44_ISTAT);
+		bw32(bp, B44_ISTAT, istat);
+		br32(bp, B44_ISTAT);
 	}
 	spin_unlock_irqrestore(&bp->lock, flags);
 	return IRQ_RETVAL(handled);
@@ -937,11 +948,11 @@
 
 	wmb();
 
-	bw32(B44_DMATX_PTR, entry * sizeof(struct dma_desc));
+	bw32(bp, B44_DMATX_PTR, entry * sizeof(struct dma_desc));
 	if (bp->flags & B44_FLAG_BUGGY_TXPTR)
-		bw32(B44_DMATX_PTR, entry * sizeof(struct dma_desc));
+		bw32(bp, B44_DMATX_PTR, entry * sizeof(struct dma_desc));
 	if (bp->flags & B44_FLAG_REORDER_BUG)
-		br32(B44_DMATX_PTR);
+		br32(bp, B44_DMATX_PTR);
 
 	if (TX_BUFFS_AVAIL(bp) < 1)
 		netif_stop_queue(dev);
@@ -1109,27 +1120,27 @@
 {
 	unsigned long reg;
 
-	bw32(B44_MIB_CTRL, MIB_CTRL_CLR_ON_READ);
+	bw32(bp, B44_MIB_CTRL, MIB_CTRL_CLR_ON_READ);
 	for (reg = B44_TX_GOOD_O; reg <= B44_TX_PAUSE; reg += 4UL)
-		br32(reg);
+		br32(bp, reg);
 	for (reg = B44_RX_GOOD_O; reg <= B44_RX_NPAUSE; reg += 4UL)
-		br32(reg);
+		br32(bp, reg);
 }
 
 /* bp->lock is held. */
 static void b44_chip_reset(struct b44 *bp)
 {
 	if (ssb_is_core_up(bp)) {
-		bw32(B44_RCV_LAZY, 0);
-		bw32(B44_ENET_CTRL, ENET_CTRL_DISABLE);
+		bw32(bp, B44_RCV_LAZY, 0);
+		bw32(bp, B44_ENET_CTRL, ENET_CTRL_DISABLE);
 		b44_wait_bit(bp, B44_ENET_CTRL, ENET_CTRL_DISABLE, 100, 1);
-		bw32(B44_DMATX_CTRL, 0);
+		bw32(bp, B44_DMATX_CTRL, 0);
 		bp->tx_prod = bp->tx_cons = 0;
-		if (br32(B44_DMARX_STAT) & DMARX_STAT_EMASK) {
+		if (br32(bp, B44_DMARX_STAT) & DMARX_STAT_EMASK) {
 			b44_wait_bit(bp, B44_DMARX_STAT, DMARX_STAT_SIDLE,
 				     100, 0);
 		}
-		bw32(B44_DMARX_CTRL, 0);
+		bw32(bp, B44_DMARX_CTRL, 0);
 		bp->rx_prod = bp->rx_cons = 0;
 	} else {
 		ssb_pci_setup(bp, (bp->core_unit == 0 ?
@@ -1142,20 +1153,20 @@
 	b44_clear_stats(bp);
 
 	/* Make PHY accessible. */
-	bw32(B44_MDIO_CTRL, (MDIO_CTRL_PREAMBLE |
+	bw32(bp, B44_MDIO_CTRL, (MDIO_CTRL_PREAMBLE |
 			     (0x0d & MDIO_CTRL_MAXF_MASK)));
-	br32(B44_MDIO_CTRL);
+	br32(bp, B44_MDIO_CTRL);
 
-	if (!(br32(B44_DEVCTRL) & DEVCTRL_IPP)) {
-		bw32(B44_ENET_CTRL, ENET_CTRL_EPSEL);
-		br32(B44_ENET_CTRL);
+	if (!(br32(bp, B44_DEVCTRL) & DEVCTRL_IPP)) {
+		bw32(bp, B44_ENET_CTRL, ENET_CTRL_EPSEL);
+		br32(bp, B44_ENET_CTRL);
 		bp->flags &= ~B44_FLAG_INTERNAL_PHY;
 	} else {
-		u32 val = br32(B44_DEVCTRL);
+		u32 val = br32(bp, B44_DEVCTRL);
 
 		if (val & DEVCTRL_EPR) {
-			bw32(B44_DEVCTRL, (val & ~DEVCTRL_EPR));
-			br32(B44_DEVCTRL);
+			bw32(bp, B44_DEVCTRL, (val & ~DEVCTRL_EPR));
+			br32(bp, B44_DEVCTRL);
 			udelay(100);
 		}
 		bp->flags |= B44_FLAG_INTERNAL_PHY;
@@ -1172,13 +1183,13 @@
 /* bp->lock is held. */
 static void __b44_set_mac_addr(struct b44 *bp)
 {
-	bw32(B44_CAM_CTRL, 0);
+	bw32(bp, B44_CAM_CTRL, 0);
 	if (!(bp->dev->flags & IFF_PROMISC)) {
 		u32 val;
 
 		__b44_cam_write(bp, bp->dev->dev_addr, 0);
-		val = br32(B44_CAM_CTRL);
-		bw32(B44_CAM_CTRL, val | CAM_CTRL_ENABLE);
+		val = br32(bp, B44_CAM_CTRL);
+		bw32(bp, B44_CAM_CTRL, val | CAM_CTRL_ENABLE);
 	}
 }
 
@@ -1212,30 +1223,30 @@
 	b44_setup_phy(bp);
 
 	/* Enable CRC32, set proper LED modes and power on PHY */
-	bw32(B44_MAC_CTRL, MAC_CTRL_CRC32_ENAB | MAC_CTRL_PHY_LEDCTRL);
-	bw32(B44_RCV_LAZY, (1 << RCV_LAZY_FC_SHIFT));
+	bw32(bp, B44_MAC_CTRL, MAC_CTRL_CRC32_ENAB | MAC_CTRL_PHY_LEDCTRL);
+	bw32(bp, B44_RCV_LAZY, (1 << RCV_LAZY_FC_SHIFT));
 
 	/* This sets the MAC address too.  */
 	__b44_set_rx_mode(bp->dev);
 
 	/* MTU + eth header + possible VLAN tag + struct rx_header */
-	bw32(B44_RXMAXLEN, bp->dev->mtu + ETH_HLEN + 8 + RX_HEADER_LEN);
-	bw32(B44_TXMAXLEN, bp->dev->mtu + ETH_HLEN + 8 + RX_HEADER_LEN);
+	bw32(bp, B44_RXMAXLEN, bp->dev->mtu + ETH_HLEN + 8 + RX_HEADER_LEN);
+	bw32(bp, B44_TXMAXLEN, bp->dev->mtu + ETH_HLEN + 8 + RX_HEADER_LEN);
 
-	bw32(B44_TX_WMARK, 56); /* XXX magic */
-	bw32(B44_DMATX_CTRL, DMATX_CTRL_ENABLE);
-	bw32(B44_DMATX_ADDR, bp->tx_ring_dma + bp->dma_offset);
-	bw32(B44_DMARX_CTRL, (DMARX_CTRL_ENABLE |
+	bw32(bp, B44_TX_WMARK, 56); /* XXX magic */
+	bw32(bp, B44_DMATX_CTRL, DMATX_CTRL_ENABLE);
+	bw32(bp, B44_DMATX_ADDR, bp->tx_ring_dma + bp->dma_offset);
+	bw32(bp, B44_DMARX_CTRL, (DMARX_CTRL_ENABLE |
 			      (bp->rx_offset << DMARX_CTRL_ROSHIFT)));
-	bw32(B44_DMARX_ADDR, bp->rx_ring_dma + bp->dma_offset);
+	bw32(bp, B44_DMARX_ADDR, bp->rx_ring_dma + bp->dma_offset);
 
-	bw32(B44_DMARX_PTR, bp->rx_pending);
+	bw32(bp, B44_DMARX_PTR, bp->rx_pending);
 	bp->rx_prod = bp->rx_pending;	
 
-	bw32(B44_MIB_CTRL, MIB_CTRL_CLR_ON_READ);
+	bw32(bp, B44_MIB_CTRL, MIB_CTRL_CLR_ON_READ);
 
-	val = br32(B44_ENET_CTRL);
-	bw32(B44_ENET_CTRL, (val | ENET_CTRL_ENABLE));
+	val = br32(bp, B44_ENET_CTRL);
+	bw32(bp, B44_ENET_CTRL, (val | ENET_CTRL_ENABLE));
 }
 
 static int b44_open(struct net_device *dev)
@@ -1372,11 +1383,11 @@
 	int i=0;
 	unsigned char zero[6] = {0,0,0,0,0,0};
 
-	val = br32(B44_RXCONFIG);
+	val = br32(bp, B44_RXCONFIG);
 	val &= ~(RXCONFIG_PROMISC | RXCONFIG_ALLMULTI);
 	if (dev->flags & IFF_PROMISC) {
 		val |= RXCONFIG_PROMISC;
-		bw32(B44_RXCONFIG, val);
+		bw32(bp, B44_RXCONFIG, val);
 	} else {
 		__b44_set_mac_addr(bp);
 
@@ -1388,9 +1399,9 @@
 		for(;i<64;i++) {
 			__b44_cam_write(bp, zero, i);			
 		}
-		bw32(B44_RXCONFIG, val);
-        	val = br32(B44_CAM_CTRL);
-	        bw32(B44_CAM_CTRL, val | CAM_CTRL_ENABLE);
+		bw32(bp, B44_RXCONFIG, val);
+        	val = br32(bp, B44_CAM_CTRL);
+	        bw32(bp, B44_CAM_CTRL, val | CAM_CTRL_ENABLE);
 	}
 }
 
@@ -1760,7 +1771,7 @@
 
 	spin_lock_init(&bp->lock);
 
-	bp->regs = (unsigned long) ioremap(b44reg_base, b44reg_len);
+	bp->regs = ioremap(b44reg_base, b44reg_len);
 	if (bp->regs == 0UL) {
 		printk(KERN_ERR PFX "Cannot map device registers, "
 		       "aborting.\n");
@@ -1826,7 +1837,7 @@
 	return 0;
 
 err_out_iounmap:
-	iounmap((void *) bp->regs);
+	iounmap(bp->regs);
 
 err_out_free_dev:
 	free_netdev(dev);
@@ -1848,7 +1859,7 @@
 		struct b44 *bp = netdev_priv(dev);
 
 		unregister_netdev(dev);
-		iounmap((void *) bp->regs);
+		iounmap(bp->regs);
 		free_netdev(dev);
 		pci_release_regions(pdev);
 		pci_disable_device(pdev);
diff -Nru a/drivers/net/b44.h b/drivers/net/b44.h
--- a/drivers/net/b44.h	2004-10-18 14:56:33 -07:00
+++ b/drivers/net/b44.h	2004-10-18 14:56:33 -07:00
@@ -395,9 +395,6 @@
 #define SSB_PCI_MASK1		0xfc000000
 #define SSB_PCI_MASK2		0xc0000000
 
-#define br32(REG)	readl(bp->regs + (REG))
-#define bw32(REG,VAL)	writel((VAL), bp->regs + (REG))
-
 /* 4400 PHY registers */
 #define B44_MII_AUXCTRL		24	/* Auxiliary Control */
 #define  MII_AUXCTRL_DUPLEX	0x0001  /* Full Duplex */
@@ -530,7 +527,7 @@
 	struct net_device_stats	stats;
 	struct b44_hw_stats	hw_stats;
 
-	unsigned long		regs;
+	void __iomem		*regs;
 	struct pci_dev		*pdev;
 	struct net_device	*dev;
 
diff -Nru a/drivers/net/bonding/bond_alb.c b/drivers/net/bonding/bond_alb.c
--- a/drivers/net/bonding/bond_alb.c	2004-10-18 14:56:33 -07:00
+++ b/drivers/net/bonding/bond_alb.c	2004-10-18 14:56:33 -07:00
@@ -1285,7 +1285,7 @@
 	int res = 1;
 
 	skb->mac.raw = (unsigned char *)skb->data;
-	eth_data = (struct ethhdr *)skb->data;
+	eth_data = eth_hdr(skb);
 
 	/* make sure that the curr_active_slave and the slaves list do
 	 * not change during tx
diff -Nru a/drivers/net/cs89x0.c b/drivers/net/cs89x0.c
--- a/drivers/net/cs89x0.c	2004-10-18 14:56:49 -07:00
+++ b/drivers/net/cs89x0.c	2004-10-18 14:56:49 -07:00
@@ -84,6 +84,9 @@
   Oskar Schirmer    : oskar@scara.com
                     : HiCO.SH4 (superh) support added (irq#1, cs89x0_media=)
 
+  Deepak Saxena     : dsaxena@plexity.net
+                    : Intel IXDP2x01 (XScale ixp2x00 NPU) platform support
+
 */
 
 /* Always include 'config.h' first in case the user wants to turn on
@@ -97,7 +100,11 @@
  * Note that even if DMA is turned off we still support the 'dma' and  'use_dma'
  * module options so we don't break any startup scripts.
  */
+#ifndef CONFIG_ARCH_IXDP2X01
+#define ALLOW_DMA	0
+#else
 #define ALLOW_DMA	1
+#endif
 
 /*
  * Set this to zero to remove all the debug statements via
@@ -162,6 +169,10 @@
 static unsigned int netcard_portlist[] __initdata =
    { 0x0300, 0};
 static unsigned int cs8900_irq_map[] = {1,0,0,0};
+#elif defined(CONFIG_ARCH_IXDP2X01)
+#include <asm/irq.h>
+static unsigned int netcard_portlist[] __initdata = {IXDP2X01_CS8900_VIRT_BASE, 0};
+static unsigned int cs8900_irq_map[] = {IRQ_IXDP2X01_CS8900, 0, 0, 0};
 #else
 static unsigned int netcard_portlist[] __initdata =
    { 0x300, 0x320, 0x340, 0x360, 0x200, 0x220, 0x240, 0x260, 0x280, 0x2a0, 0x2c0, 0x2e0, 0};
@@ -454,11 +465,12 @@
 		        	retval = -ENODEV;
 				goto out2;
 			}
-		ioaddr &= ~3;
-		outw(PP_ChipID, ioaddr + ADD_PORT);
 	}
 printk("PP_addr=0x%x\n", inw(ioaddr + ADD_PORT));
 
+	ioaddr &= ~3;
+	outw(PP_ChipID, ioaddr + ADD_PORT);
+
 	if (inw(ioaddr + DATA_PORT) != CHIP_EISA_ID_SIG) {
 		printk(KERN_ERR "%s: incorrect signature 0x%x\n",
 			dev->name, inw(ioaddr + DATA_PORT));
@@ -665,6 +677,9 @@
 	} else {
 		i = lp->isa_config & INT_NO_MASK;
 		if (lp->chip_type == CS8900) {
+#ifdef CONFIG_ARCH_IXDP2X01
+		        i = cs8900_irq_map[0];
+#else
 			/* Translate the IRQ using the IRQ mapping table. */
 			if (i >= sizeof(cs8900_irq_map)/sizeof(cs8900_irq_map[0]))
 				printk("\ncs89x0: invalid ISA interrupt number %d\n", i);
@@ -681,6 +696,7 @@
 				if ((irq_map_buff[0] & 0xff) == PNP_IRQ_FRMT)
 					lp->irq_map = (irq_map_buff[0]>>8) | (irq_map_buff[1] << 8);
 			}
+#endif
 		}
 		if (!dev->irq)
 			dev->irq = i;
@@ -884,8 +900,10 @@
 
 void  __init reset_chip(struct net_device *dev)
 {
+#ifndef CONFIG_ARCH_IXDP2X01
 	struct net_local *lp = netdev_priv(dev);
 	int ioaddr = dev->base_addr;
+#endif
 	int reset_start_time;
 
 	writereg(dev, PP_SelfCTL, readreg(dev, PP_SelfCTL) | POWER_ON_RESET);
@@ -894,6 +912,7 @@
 	current->state = TASK_INTERRUPTIBLE;
 	schedule_timeout(30*HZ/1000);
 
+#ifndef CONFIG_ARCH_IXDP2X01
 	if (lp->chip_type != CS8900) {
 		/* Hardware problem requires PNP registers to be reconfigured after a reset */
 		outw(PP_CS8920_ISAINT, ioaddr + ADD_PORT);
@@ -904,6 +923,8 @@
 		outb((dev->mem_start >> 16) & 0xff, ioaddr + DATA_PORT);
 		outb((dev->mem_start >> 8) & 0xff,   ioaddr + DATA_PORT + 1);
 	}
+#endif	/* IXDP2x01 */
+
 	/* Wait until the chip is reset */
 	reset_start_time = jiffies;
 	while( (readreg(dev, PP_SelfST) & INIT_DONE) == 0 && jiffies - reset_start_time < 2)
@@ -1155,12 +1176,14 @@
 	else
 #endif
 	{
+#ifndef CONFIG_ARCH_IXDP2X01
 		if (((1 << dev->irq) & lp->irq_map) == 0) {
 			printk(KERN_ERR "%s: IRQ %d is not in our map of allowable IRQs, which is %x\n",
                                dev->name, dev->irq, lp->irq_map);
 			ret = -EAGAIN;
 			goto bad_out;
 		}
+#endif
 /* FIXME: Cirrus' release had this: */
 		writereg(dev, PP_BusCTL, readreg(dev, PP_BusCTL)|ENABLE_IRQ );
 /* And 2.3.47 had this: */
@@ -1575,7 +1598,9 @@
 static int
 net_close(struct net_device *dev)
 {
+#if ALLOW_DMA
 	struct net_local *lp = netdev_priv(dev);
+#endif
 
 	netif_stop_queue(dev);
 	
diff -Nru a/drivers/net/cs89x0.h b/drivers/net/cs89x0.h
--- a/drivers/net/cs89x0.h	2004-10-18 14:56:48 -07:00
+++ b/drivers/net/cs89x0.h	2004-10-18 14:56:48 -07:00
@@ -16,6 +16,13 @@
 
 #include <linux/config.h>
 
+#ifdef CONFIG_ARCH_IXDP2X01
+/* IXDP2401/IXDP2801 uses dword-aligned register addressing */
+#define CS89x0_PORT(reg) ((reg) * 2)
+#else
+#define CS89x0_PORT(reg) (reg)
+#endif
+
 #define PP_ChipID 0x0000	/* offset   0h -> Corp -ID              */
 				/* offset   2h -> Model/Product Number  */
 				/* offset   3h -> Chip Revision Number  */
@@ -324,16 +331,16 @@
 #define RAM_SIZE	0x1000       /*  The card has 4k bytes or RAM */
 #define PKT_START PP_TxFrame  /*  Start of packet RAM */
 
-#define RX_FRAME_PORT	0x0000
+#define RX_FRAME_PORT	CS89x0_PORT(0x0000)
 #define TX_FRAME_PORT RX_FRAME_PORT
-#define TX_CMD_PORT	0x0004
+#define TX_CMD_PORT	CS89x0_PORT(0x0004)
 #define TX_NOW		0x0000       /*  Tx packet after   5 bytes copied */
 #define TX_AFTER_381	0x0040       /*  Tx packet after 381 bytes copied */
 #define TX_AFTER_ALL	0x00c0       /*  Tx packet after all bytes copied */
-#define TX_LEN_PORT	0x0006
-#define ISQ_PORT	0x0008
-#define ADD_PORT	0x000A
-#define DATA_PORT	0x000C
+#define TX_LEN_PORT	CS89x0_PORT(0x0006)
+#define ISQ_PORT	CS89x0_PORT(0x0008)
+#define ADD_PORT	CS89x0_PORT(0x000A)
+#define DATA_PORT	CS89x0_PORT(0x000C)
 
 #define EEPROM_WRITE_EN		0x00F0
 #define EEPROM_WRITE_DIS	0x0000
diff -Nru a/drivers/net/defxx.c b/drivers/net/defxx.c
--- a/drivers/net/defxx.c	2004-10-18 14:55:46 -07:00
+++ b/drivers/net/defxx.c	2004-10-18 14:55:46 -07:00
@@ -1814,16 +1814,18 @@
 
 	/* Fill the bp->stats structure with driver-maintained counters */
 
-	bp->stats.rx_packets			= bp->rcv_total_frames;
-	bp->stats.tx_packets			= bp->xmt_total_frames;
-	bp->stats.rx_bytes			= bp->rcv_total_bytes;
-	bp->stats.tx_bytes			= bp->xmt_total_bytes;
-	bp->stats.rx_errors				= (u32)(bp->rcv_crc_errors + bp->rcv_frame_status_errors + bp->rcv_length_errors);
-	bp->stats.tx_errors				= bp->xmt_length_errors;
-	bp->stats.rx_dropped			= bp->rcv_discards;
-	bp->stats.tx_dropped			= bp->xmt_discards;
-	bp->stats.multicast				= bp->rcv_multicast_frames;
-	bp->stats.transmit_collision	= 0;	/* always zero (0) for FDDI */
+	bp->stats.gen.rx_packets = bp->rcv_total_frames;
+	bp->stats.gen.tx_packets = bp->xmt_total_frames;
+	bp->stats.gen.rx_bytes   = bp->rcv_total_bytes;
+	bp->stats.gen.tx_bytes   = bp->xmt_total_bytes;
+	bp->stats.gen.rx_errors  = bp->rcv_crc_errors +
+				   bp->rcv_frame_status_errors +
+				   bp->rcv_length_errors;
+	bp->stats.gen.tx_errors  = bp->xmt_length_errors;
+	bp->stats.gen.rx_dropped = bp->rcv_discards;
+	bp->stats.gen.tx_dropped = bp->xmt_discards;
+	bp->stats.gen.multicast  = bp->rcv_multicast_frames;
+	bp->stats.gen.collisions = 0;		/* always zero (0) for FDDI */
 
 	/* Get FDDI SMT MIB objects */
 
diff -Nru a/drivers/net/dl2k.h b/drivers/net/dl2k.h
--- a/drivers/net/dl2k.h	2004-10-18 14:57:03 -07:00
+++ b/drivers/net/dl2k.h	2004-10-18 14:57:03 -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/e100.c b/drivers/net/e100.c
--- a/drivers/net/e100.c	2004-10-18 14:57:04 -07:00
+++ b/drivers/net/e100.c	2004-10-18 14:57:04 -07:00
@@ -87,9 +87,8 @@
  *	cb_to_use is the next CB to use for queuing a command; cb_to_clean
  *	is the next CB to check for completion; cb_to_send is the first
  *	CB to start on in case of a previous failure to resume.  CB clean
- *	up happens in interrupt context in response to a CU interrupt, or
- *	in dev->poll in the case where NAPI is enabled.  cbs_avail keeps
- *	track of number of free CB resources available.
+ *	up happens in interrupt context in response to a CU interrupt.
+ *	cbs_avail keeps track of number of free CB resources available.
  *
  * 	Hardware padding of short packets to minimum packet size is
  * 	enabled.  82557 pads with 7Eh, while the later controllers pad
@@ -112,9 +111,8 @@
  *	replacement RFDs cannot be allocated, or the RU goes non-active,
  *	the RU must be restarted.  Frame arrival generates an interrupt,
  *	and Rx indication and re-allocation happen in the same context,
- *	therefore no locking is required.  If NAPI is enabled, this work
- *	happens in dev->poll.  A software-generated interrupt is gen-
- *	erated from the watchdog to recover from a failed allocation
+ *	therefore no locking is required.  A software-generated interrupt
+ *	is generated from the watchdog to recover from a failed allocation
  *	senario where all Rx resources have been indicated and none re-
  *	placed.
  *
@@ -126,8 +124,6 @@
  * 	supported.  Tx Scatter/Gather is not supported.  Jumbo Frames is
  * 	not supported (hardware limitation).
  *
- * 	NAPI support is enabled with CONFIG_E100_NAPI.
- *
  * 	MagicPacket(tm) WoL support is enabled/disabled via ethtool.
  *
  * 	Thanks to JC (jchapman@katalix.com) for helping with
@@ -158,7 +154,8 @@
 
 
 #define DRV_NAME		"e100"
-#define DRV_VERSION		"3.0.18"
+#define DRV_EXT			"-NAPI"
+#define DRV_VERSION		"3.0.27-k2"DRV_EXT
 #define DRV_DESCRIPTION		"Intel(R) PRO/100 Network Driver"
 #define DRV_COPYRIGHT		"Copyright(c) 1999-2004 Intel Corporation"
 #define PFX			DRV_NAME ": "
@@ -201,6 +198,8 @@
 	INTEL_8255X_ETHERNET_DEVICE(0x1053, 5),
 	INTEL_8255X_ETHERNET_DEVICE(0x1054, 5),
 	INTEL_8255X_ETHERNET_DEVICE(0x1055, 5),
+	INTEL_8255X_ETHERNET_DEVICE(0x1056, 5),
+	INTEL_8255X_ETHERNET_DEVICE(0x1057, 5),
 	INTEL_8255X_ETHERNET_DEVICE(0x1064, 6),
 	INTEL_8255X_ETHERNET_DEVICE(0x1065, 6),
 	INTEL_8255X_ETHERNET_DEVICE(0x1066, 6),
@@ -242,6 +241,7 @@
 	phy_nsc_tx   = 0x5C002000,
 	phy_82562_et = 0x033002A8,
 	phy_82562_em = 0x032002A8,
+	phy_82562_ek = 0x031002A8,
 	phy_82562_eh = 0x017002A8,
 	phy_unknown  = 0xFFFFFFFF,
 };
@@ -330,11 +330,16 @@
 };
 
 enum eeprom_offsets {
+	eeprom_cnfg_mdix  = 0x03,
 	eeprom_id         = 0x0A,
 	eeprom_config_asf = 0x0D,
 	eeprom_smbus_addr = 0x90,
 };
 
+enum eeprom_cnfg_mdix {
+	eeprom_mdix_enabled = 0x0080,
+};
+
 enum eeprom_id {
 	eeprom_id_wol = 0x0020,
 };
@@ -350,10 +355,12 @@
 };
 
 enum cb_command {
+	cb_nop    = 0x0000,
 	cb_iaaddr = 0x0001,
 	cb_config = 0x0002,
 	cb_multi  = 0x0003,
 	cb_tx     = 0x0004,
+	cb_ucode  = 0x0005,
 	cb_dump   = 0x0006,
 	cb_tx_sf  = 0x0008,
 	cb_cid    = 0x1f00,
@@ -428,12 +435,14 @@
 };
 
 /* Important: keep total struct u32-aligned */
+#define UCODE_SIZE			134
 struct cb {
 	u16 status;
 	u16 command;
 	u32 link;
 	union {
 		u8 iaaddr[ETH_ALEN];
+		u32 ucode[UCODE_SIZE];
 		struct config config;
 		struct multi multi;
 		struct {
@@ -548,6 +557,7 @@
 	u32 rx_fc_pause;
 	u32 rx_fc_unsupported;
 	u32 rx_tco_frames;
+	u32 rx_over_length_errors;
 
 	u8 rev_id;
 	u16 leds;
@@ -980,6 +990,27 @@
 		c[16], c[17], c[18], c[19], c[20], c[21], c[22], c[23]);
 }
 
+static void e100_load_ucode(struct nic *nic, struct cb *cb, struct sk_buff *skb)
+{
+	int i;
+	static const u32 ucode[UCODE_SIZE] = {
+		/* NFS packets are misinterpreted as TCO packets and
+		 * incorrectly routed to the BMC over SMBus.  This
+		 * microcode patch checks the fragmented IP bit in the
+		 * NFS/UDP header to distinguish between NFS and TCO. */
+		0x0EF70E36, 0x1FFF1FFF, 0x1FFF1FFF, 0x1FFF1FFF, 0x1FFF1FFF,
+		0x1FFF1FFF, 0x00906E41, 0x00800E3C, 0x00E00E39, 0x00000000,
+		0x00906EFD, 0x00900EFD,	0x00E00EF8,
+	};
+
+	if(nic->mac == mac_82551_F || nic->mac == mac_82551_10) {
+		for(i = 0; i < UCODE_SIZE; i++)
+			cb->u.ucode[i] = cpu_to_le32(ucode[i]);
+		cb->command = cpu_to_le16(cb_ucode);
+	} else
+		cb->command = cpu_to_le16(cb_nop);
+}
+
 static void e100_setup_iaaddr(struct nic *nic, struct cb *cb,
 	struct sk_buff *skb)
 {
@@ -1045,7 +1076,9 @@
 		mdio_write(netdev, nic->mii.phy_id, MII_NSC_CONG, cong);
 	}
 
-	if(nic->mac >= mac_82550_D102)
+	if((nic->mac >= mac_82550_D102) || ((nic->flags & ich) && 
+		(mdio_read(netdev, nic->mii.phy_id, MII_TPISTATUS) & 0x8000) && 
+		(nic->eeprom[eeprom_cnfg_mdix] & eeprom_mdix_enabled)))
 		/* enable/disable MDI/MDI-X auto-switching */
 		mdio_write(netdev, nic->mii.phy_id, MII_NCONFIG,
 			nic->mii.force_media ? 0 : NCONFIG_AUTO_SWITCH);
@@ -1069,6 +1102,8 @@
 		return err;
 	if((err = e100_exec_cmd(nic, ruc_load_base, 0)))
 		return err;
+	if((err = e100_exec_cb(nic, NULL, e100_load_ucode)))
+		return err;
 	if((err = e100_exec_cb(nic, NULL, e100_configure)))
 		return err;
 	if((err = e100_exec_cb(nic, NULL, e100_setup_iaaddr)))
@@ -1143,9 +1178,11 @@
 		ns->tx_errors += le32_to_cpu(s->tx_max_collisions) +
 			le32_to_cpu(s->tx_lost_crs);
 		ns->rx_dropped += le32_to_cpu(s->rx_resource_errors);
-		ns->rx_length_errors += le32_to_cpu(s->rx_short_frame_errors);
+		ns->rx_length_errors += le32_to_cpu(s->rx_short_frame_errors) +
+			nic->rx_over_length_errors;
 		ns->rx_crc_errors += le32_to_cpu(s->rx_crc_errors);
 		ns->rx_frame_errors += le32_to_cpu(s->rx_alignment_errors);
+		ns->rx_over_errors += le32_to_cpu(s->rx_overrun_errors);
 		ns->rx_fifo_errors += le32_to_cpu(s->rx_overrun_errors);
 		ns->rx_errors += le32_to_cpu(s->rx_crc_errors) +
 			le32_to_cpu(s->rx_alignment_errors) +
@@ -1456,18 +1493,14 @@
 		dev_kfree_skb_any(skb);
 	} else if(actual_size > nic->netdev->mtu + VLAN_ETH_HLEN) {
 		/* Don't indicate oversized frames */
-		nic->net_stats.rx_over_errors++;
+		nic->rx_over_length_errors++;
 		nic->net_stats.rx_dropped++;
 		dev_kfree_skb_any(skb);
 	} else {
 		nic->net_stats.rx_packets++;
 		nic->net_stats.rx_bytes += actual_size;
 		nic->netdev->last_rx = jiffies;
-#ifdef CONFIG_E100_NAPI
 		netif_receive_skb(skb);
-#else
-		netif_rx(skb);
-#endif
 		if(work_done)
 			(*work_done)++;
 	}
@@ -1562,20 +1595,12 @@
 	if(stat_ack & stat_ack_rnr)
 		nic->ru_running = 0;
 
-#ifdef CONFIG_E100_NAPI
 	e100_disable_irq(nic);
 	netif_rx_schedule(netdev);
-#else
-	if(stat_ack & stat_ack_rx)
-		e100_rx_clean(nic, NULL, 0);
-	if(stat_ack & stat_ack_tx)
-		e100_tx_clean(nic);
-#endif
 
 	return IRQ_HANDLED;
 }
 
-#ifdef CONFIG_E100_NAPI
 static int e100_poll(struct net_device *netdev, int *budget)
 {
 	struct nic *nic = netdev_priv(netdev);
@@ -1598,7 +1623,6 @@
 
 	return 1;
 }
-#endif
 
 #ifdef CONFIG_NET_POLL_CONTROLLER
 static void e100_netpoll(struct net_device *netdev)
@@ -1641,7 +1665,7 @@
 static int e100_asf(struct nic *nic)
 {
 	/* ASF can be enabled from eeprom */
-	return((nic->pdev->device >= 0x1050) && (nic->pdev->device <= 0x1055) &&
+	return((nic->pdev->device >= 0x1050) && (nic->pdev->device <= 0x1057) &&
 	   (nic->eeprom[eeprom_config_asf] & eeprom_asf) &&
 	   !(nic->eeprom[eeprom_config_asf] & eeprom_gcl) &&
 	   ((nic->eeprom[eeprom_smbus_addr] & 0xFF) != 0xFE));
@@ -1961,18 +1985,27 @@
 static void e100_diag_test(struct net_device *netdev,
 	struct ethtool_test *test, u64 *data)
 {
+	struct ethtool_cmd cmd;
 	struct nic *nic = netdev_priv(netdev);
-	int i;
+	int i, err;
 
 	memset(data, 0, E100_TEST_LEN * sizeof(u64));
 	data[0] = !mii_link_ok(&nic->mii);
 	data[1] = e100_eeprom_load(nic);
 	if(test->flags & ETH_TEST_FL_OFFLINE) {
+
+		/* save speed, duplex & autoneg settings */
+		err = mii_ethtool_gset(&nic->mii, &cmd);
+
 		if(netif_running(netdev))
 			e100_down(nic);
 		data[2] = e100_self_test(nic);
 		data[3] = e100_loopback_test(nic, lb_mac);
 		data[4] = e100_loopback_test(nic, lb_phy);
+
+		/* restore speed, duplex & autoneg settings */
+		err = mii_ethtool_sset(&nic->mii, &cmd);
+
 		if(netif_running(netdev))
 			e100_up(nic);
 	}
@@ -2135,10 +2168,8 @@
 	SET_ETHTOOL_OPS(netdev, &e100_ethtool_ops);
 	netdev->tx_timeout = e100_tx_timeout;
 	netdev->watchdog_timeo = E100_WATCHDOG_PERIOD;
-#ifdef CONFIG_E100_NAPI
 	netdev->poll = e100_poll;
 	netdev->weight = E100_NAPI_WEIGHT;
-#endif
 #ifdef CONFIG_NET_POLL_CONTROLLER
 	netdev->poll_controller = e100_netpoll;
 #endif
diff -Nru a/drivers/net/e1000/e1000.h b/drivers/net/e1000/e1000.h
--- a/drivers/net/e1000/e1000.h	2004-10-18 14:55:54 -07:00
+++ b/drivers/net/e1000/e1000.h	2004-10-18 14:55:54 -07:00
@@ -49,6 +49,7 @@
 #include <linux/delay.h>
 #include <linux/timer.h>
 #include <linux/slab.h>
+#include <linux/vmalloc.h>
 #include <linux/interrupt.h>
 #include <linux/string.h>
 #include <linux/pagemap.h>
@@ -63,6 +64,7 @@
 #include <linux/udp.h>
 #include <net/pkt_sched.h>
 #include <linux/list.h>
+#include <linux/rtnetlink.h>
 #include <linux/reboot.h>
 #ifdef NETIF_F_TSO
 #include <net/checksum.h>
@@ -77,6 +79,8 @@
 #define BAR_1		1
 #define BAR_5		5
 
+#define INTEL_E1000_ETHERNET_DEVICE(device_id) {\
+	PCI_DEVICE(PCI_VENDOR_ID_INTEL, device_id)}
 
 struct e1000_adapter;
 
@@ -98,11 +102,12 @@
 
 #define E1000_MAX_INTR 10
 
-/* How many descriptors for TX and RX ? */
+/* TX/RX descriptor defines */
 #define E1000_DEFAULT_TXD                  256
 #define E1000_MAX_TXD                      256
 #define E1000_MIN_TXD                       80
 #define E1000_MAX_82544_TXD               4096
+
 #define E1000_DEFAULT_RXD                  256
 #define E1000_MAX_RXD                      256
 #define E1000_MIN_RXD                       80
@@ -123,14 +128,11 @@
 #define E1000_TX_HEAD_ADDR_SHIFT 7
 #define E1000_PBA_TX_MASK 0xFFFF0000
 
-/* Flow Control High-Watermark: 5688 bytes below Rx FIFO size */
-#define E1000_FC_HIGH_DIFF 0x1638
-
-/* Flow Control Low-Watermark: 5696 bytes below Rx FIFO size */
-#define E1000_FC_LOW_DIFF 0x1640
+/* Flow Control Watermarks */
+#define E1000_FC_HIGH_DIFF 0x1638  /* High: 5688 bytes below Rx FIFO size */
+#define E1000_FC_LOW_DIFF 0x1640   /* Low:  5696 bytes below Rx FIFO size */
 
-/* Flow Control Pause Time: 858 usec */
-#define E1000_FC_PAUSE_TIME 0x0680
+#define E1000_FC_PAUSE_TIME 0x0680 /* 858 usec */
 
 /* How many Tx Descriptors do we need to call netif_wake_queue ? */
 #define E1000_TX_QUEUE_WAKE	16
@@ -153,9 +155,9 @@
 struct e1000_buffer {
 	struct sk_buff *skb;
 	uint64_t dma;
-	unsigned long length;
 	unsigned long time_stamp;
-	unsigned int next_to_watch;
+	uint16_t length;
+	uint16_t next_to_watch;
 };
 
 struct e1000_desc_ring {
@@ -202,7 +204,7 @@
 	spinlock_t stats_lock;
 	atomic_t irq_sem;
 	struct work_struct tx_timeout_task;
-    	uint8_t fc_autoneg;
+	uint8_t fc_autoneg;
 
 	struct timer_list blink_timer;
 	unsigned long led_status;
diff -Nru a/drivers/net/e1000/e1000_ethtool.c b/drivers/net/e1000/e1000_ethtool.c
--- a/drivers/net/e1000/e1000_ethtool.c	2004-10-18 14:56:29 -07:00
+++ b/drivers/net/e1000/e1000_ethtool.c	2004-10-18 14:56:29 -07:00
@@ -88,9 +88,9 @@
 	{ "rx_flow_control_xoff", E1000_STAT(stats.xoffrxc) },
 	{ "tx_flow_control_xon", E1000_STAT(stats.xontxc) },
 	{ "tx_flow_control_xoff", E1000_STAT(stats.xofftxc) },
+	{ "rx_long_byte_count", E1000_STAT(stats.gorcl) },
 	{ "rx_csum_offload_good", E1000_STAT(hw_csum_good) },
-        { "rx_csum_offload_errors", E1000_STAT(hw_csum_err) },
-	{ "rx_long_byte_count", E1000_STAT(stats.gorcl) }
+	{ "rx_csum_offload_errors", E1000_STAT(hw_csum_err) }
 };
 #define E1000_STATS_LEN	\
 	sizeof(e1000_gstrings_stats) / sizeof(struct e1000_stats)
@@ -170,7 +170,8 @@
 		ecmd->duplex = -1;
 	}
 
-	ecmd->autoneg = (hw->autoneg ? AUTONEG_ENABLE : AUTONEG_DISABLE);
+	ecmd->autoneg = ((hw->media_type == e1000_media_type_fiber) ||
+			 hw->autoneg) ? AUTONEG_ENABLE : AUTONEG_DISABLE;
 	return 0;
 }
 
@@ -192,6 +193,7 @@
 
 	if(netif_running(adapter->netdev)) {
 		e1000_down(adapter);
+		e1000_reset(adapter);
 		e1000_up(adapter);
 	} else
 		e1000_reset(adapter);
@@ -199,12 +201,13 @@
 	return 0;
 }
 
-static void 
+static void
 e1000_get_pauseparam(struct net_device *netdev,
-                    struct ethtool_pauseparam *pause)
+                     struct ethtool_pauseparam *pause)
 {
 	struct e1000_adapter *adapter = netdev->priv;
 	struct e1000_hw *hw = &adapter->hw;
+
 	pause->autoneg = 
 		(adapter->fc_autoneg ? AUTONEG_ENABLE : AUTONEG_DISABLE);
 	
@@ -218,9 +221,9 @@
 	}
 }
 
-static int 
+static int
 e1000_set_pauseparam(struct net_device *netdev,
-                    struct ethtool_pauseparam *pause)
+                     struct ethtool_pauseparam *pause)
 {
 	struct e1000_adapter *adapter = netdev->priv;
 	struct e1000_hw *hw = &adapter->hw;
@@ -271,7 +274,7 @@
 		e1000_reset(adapter);
 	return 0;
 }
-
+	
 static uint32_t
 e1000_get_tx_csum(struct net_device *netdev)
 {
@@ -337,7 +340,7 @@
 
 static void
 e1000_get_regs(struct net_device *netdev,
-                    struct ethtool_regs *regs, void *p)
+	       struct ethtool_regs *regs, void *p)
 {
 	struct e1000_adapter *adapter = netdev->priv;
 	struct e1000_hw *hw = &adapter->hw;
@@ -418,6 +421,10 @@
 	e1000_read_phy_reg(hw, PHY_1000T_STATUS, &phy_data);
 	regs_buff[24] = (uint32_t)phy_data;  /* phy local receiver status */
 	regs_buff[25] = regs_buff[24];  /* phy remote receiver status */
+	if(hw->mac_type >= e1000_82540 &&
+	   hw->media_type == e1000_media_type_copper) {
+		regs_buff[26] = E1000_READ_REG(hw, MANC);
+	}
 }
 
 static int
@@ -438,7 +445,7 @@
 	int ret_val = 0;
 	uint16_t i;
 
-	if(eeprom->len == 0) 
+	if(eeprom->len == 0)
 		return -EINVAL;
 
 	eeprom->magic = hw->vendor_id | (hw->device_id << 16);
@@ -446,9 +453,9 @@
 	first_word = eeprom->offset >> 1;
 	last_word = (eeprom->offset + eeprom->len - 1) >> 1;
 
-	eeprom_buff = kmalloc(sizeof(uint16_t) * 
+	eeprom_buff = kmalloc(sizeof(uint16_t) *
 			(last_word - first_word + 1), GFP_KERNEL);
-	if (!eeprom_buff)
+	if(!eeprom_buff)
 		return -ENOMEM;
 
 	if(hw->eeprom.type == e1000_eeprom_spi)
@@ -466,9 +473,8 @@
 	for (i = 0; i < last_word - first_word + 1; i++)
 		le16_to_cpus(&eeprom_buff[i]);
 
-
-	memcpy(bytes, (uint8_t *)eeprom_buff + (eeprom->offset%2), 
-				eeprom->len);
+	memcpy(bytes, (uint8_t *)eeprom_buff + (eeprom->offset & 1),
+			eeprom->len);
 	kfree(eeprom_buff);
 
 	return ret_val;
@@ -520,6 +526,7 @@
 		le16_to_cpus(&eeprom_buff[i]);
 
 	memcpy(ptr, bytes, eeprom->len);
+
 	for (i = 0; i < last_word - first_word + 1; i++)
 		eeprom_buff[i] = cpu_to_le16(eeprom_buff[i]);
 
@@ -575,17 +582,16 @@
 e1000_set_ringparam(struct net_device *netdev,
                     struct ethtool_ringparam *ring)
 {
-	int err;
 	struct e1000_adapter *adapter = netdev->priv;
 	e1000_mac_type mac_type = adapter->hw.mac_type;
 	struct e1000_desc_ring *txdr = &adapter->tx_ring;
 	struct e1000_desc_ring *rxdr = &adapter->rx_ring;
-	struct e1000_desc_ring tx_old, tx_new;
-	struct e1000_desc_ring rx_old, rx_new;
+	struct e1000_desc_ring tx_old, tx_new, rx_old, rx_new;
+	int err;
 
 	tx_old = adapter->tx_ring;
 	rx_old = adapter->rx_ring;
-	
+
 	if(netif_running(adapter->netdev))
 		e1000_down(adapter);
 
@@ -600,15 +606,15 @@
 	E1000_ROUNDUP(txdr->count, REQ_TX_DESCRIPTOR_MULTIPLE); 
 
 	if(netif_running(adapter->netdev)) {
-		/* try to get new resources before deleting old */
+		/* Try to get new resources before deleting old */
 		if((err = e1000_setup_rx_resources(adapter)))
 			goto err_setup_rx;
 		if((err = e1000_setup_tx_resources(adapter)))
 			goto err_setup_tx;
 
 		/* save the new, restore the old in order to free it,
-		 * then restore the new back again */	
-	
+		 * then restore the new back again */
+
 		rx_new = adapter->rx_ring;
 		tx_new = adapter->tx_ring;
 		adapter->rx_ring = rx_old;
@@ -620,6 +626,7 @@
 		if((err = e1000_up(adapter)))
 			return err;
 	}
+
 	return 0;
 err_setup_tx:
 	e1000_free_rx_resources(adapter);
@@ -766,13 +773,15 @@
 e1000_intr_test(struct e1000_adapter *adapter, uint64_t *data)
 {
 	struct net_device *netdev = adapter->netdev;
-	uint32_t icr, mask, i=0;
+ 	uint32_t icr, mask, i=0, shared_int = TRUE;
+ 	uint32_t irq = adapter->pdev->irq;
 
 	*data = 0;
 
 	/* Hook up test interrupt handler just for this test */
-	if(request_irq(adapter->pdev->irq, &e1000_test_intr, SA_SHIRQ,
-	   netdev->name, netdev)) {
+ 	if(!request_irq(irq, &e1000_test_intr, 0, netdev->name, netdev)) {
+ 		shared_int = FALSE;
+ 	} else if(request_irq(irq, &e1000_test_intr, SA_SHIRQ, netdev->name, netdev)){
 		*data = 1;
 		return -1;
 	}
@@ -802,20 +811,22 @@
 		/* Interrupt to test */
 		mask = 1 << i;
 
-		/* Disable the interrupt to be reported in
-		 * the cause register and then force the same
-		 * interrupt and see if one gets posted.  If
-		 * an interrupt was posted to the bus, the
-		 * test failed.
-		 */
-		adapter->test_icr = 0;
-		E1000_WRITE_REG(&adapter->hw, IMC, mask);
-		E1000_WRITE_REG(&adapter->hw, ICS, mask);
-		msec_delay(10);
-
-		if(adapter->test_icr & mask) {
-			*data = 3;
-			break;
+ 		if(!shared_int) {
+ 			/* Disable the interrupt to be reported in
+ 			 * the cause register and then force the same
+ 			 * interrupt and see if one gets posted.  If
+ 			 * an interrupt was posted to the bus, the
+ 			 * test failed.
+ 			 */
+ 			adapter->test_icr = 0;
+ 			E1000_WRITE_REG(&adapter->hw, IMC, mask);
+ 			E1000_WRITE_REG(&adapter->hw, ICS, mask);
+ 			msec_delay(10);
+ 
+ 			if(adapter->test_icr & mask) {
+ 				*data = 3;
+ 				break;
+ 			}
 		}
 
 		/* Enable the interrupt to be reported in
@@ -834,20 +845,22 @@
 			break;
 		}
 
-		/* Disable the other interrupts to be reported in
-		 * the cause register and then force the other
-		 * interrupts and see if any get posted.  If
-		 * an interrupt was posted to the bus, the
-		 * test failed.
-		 */
-		adapter->test_icr = 0;
-		E1000_WRITE_REG(&adapter->hw, IMC, ~mask);
-		E1000_WRITE_REG(&adapter->hw, ICS, ~mask);
-		msec_delay(10);
+ 		if(!shared_int) {
+			/* Disable the other interrupts to be reported in
+			 * the cause register and then force the other
+			 * interrupts and see if any get posted.  If
+			 * an interrupt was posted to the bus, the
+			 * test failed.
+			 */
+			adapter->test_icr = 0;
+			E1000_WRITE_REG(&adapter->hw, IMC, ~mask);
+			E1000_WRITE_REG(&adapter->hw, ICS, ~mask);
+			msec_delay(10);
 
-		if(adapter->test_icr) {
-			*data = 5;
-			break;
+			if(adapter->test_icr) {
+				*data = 5;
+				break;
+			}
 		}
 	}
 
@@ -856,7 +869,7 @@
 	msec_delay(10);
 
 	/* Unhook test interrupt handler */
-	free_irq(adapter->pdev->irq, netdev);
+	free_irq(irq, netdev);
 
 	return *data;
 }
@@ -1021,7 +1034,7 @@
 
 	return 0;
 
-      err_nomem:
+err_nomem:
 	e1000_free_desc_rings(adapter);
 	return ret_val;
 }
@@ -1312,15 +1325,15 @@
 
 	for(i = 0; i < 64; i++) {
 		e1000_create_lbtest_frame(txdr->buffer_info[i].skb, 1024);
-		pci_dma_sync_single(pdev, txdr->buffer_info[i].dma,
-				    txdr->buffer_info[i].length,
-				    PCI_DMA_TODEVICE);
+		pci_dma_sync_single_for_device(pdev, txdr->buffer_info[i].dma,
+					    txdr->buffer_info[i].length,
+					    PCI_DMA_TODEVICE);
 	}
 	E1000_WRITE_REG(&adapter->hw, TDT, i);
 
 	msec_delay(200);
 
-	pci_dma_sync_single(pdev, rxdr->buffer_info[0].dma,
+	pci_dma_sync_single_for_cpu(pdev, rxdr->buffer_info[0].dma,
 			    rxdr->buffer_info[0].length, PCI_DMA_FROMDEVICE);
 
 	return e1000_check_lbtest_frame(rxdr->buffer_info[0].skb, 1024);
@@ -1357,7 +1370,7 @@
 }
 
 static void
-e1000_diag_test(struct net_device *netdev, 
+e1000_diag_test(struct net_device *netdev,
 		   struct ethtool_test *eth_test, uint64_t *data)
 {
 	struct e1000_adapter *adapter = netdev->priv;
@@ -1368,7 +1381,7 @@
 
 		/* save speed, duplex, autoneg settings */
 		uint16_t autoneg_advertised = adapter->hw.autoneg_advertised;
-    		uint8_t forced_speed_duplex = adapter->hw.forced_speed_duplex;
+		uint8_t forced_speed_duplex = adapter->hw.forced_speed_duplex;
 		uint8_t autoneg = adapter->hw.autoneg;
 
 		/* Link test performed before hardware reset so autoneg doesn't
@@ -1396,10 +1409,11 @@
 		if(e1000_loopback_test(adapter, &data[3]))
 			eth_test->flags |= ETH_TEST_FL_FAILED;
 
-		/* restore Autoneg/speed/duplex settings */
+		/* restore speed, duplex, autoneg settings */
 		adapter->hw.autoneg_advertised = autoneg_advertised;
-    		adapter->hw.forced_speed_duplex = forced_speed_duplex;
-    		adapter->hw.autoneg = autoneg;
+		adapter->hw.forced_speed_duplex = forced_speed_duplex;
+		adapter->hw.autoneg = autoneg;
+
 		e1000_reset(adapter);
 		if(if_running)
 			e1000_up(adapter);
@@ -1427,6 +1441,7 @@
 	case E1000_DEV_ID_82543GC_FIBER:
 	case E1000_DEV_ID_82543GC_COPPER:
 	case E1000_DEV_ID_82544EI_FIBER:
+	case E1000_DEV_ID_82546EB_QUAD_COPPER:
 		wol->supported = 0;
 		wol->wolopts   = 0;
 		return;
@@ -1469,6 +1484,7 @@
 	case E1000_DEV_ID_82543GC_FIBER:
 	case E1000_DEV_ID_82543GC_COPPER:
 	case E1000_DEV_ID_82544EI_FIBER:
+	case E1000_DEV_ID_82546EB_QUAD_COPPER:
 		return wol->wolopts ? -EOPNOTSUPP : 0;
 
 	case E1000_DEV_ID_82546EB_FIBER:
@@ -1571,8 +1587,8 @@
 	e1000_update_stats(adapter);
 	for(i = 0; i < E1000_STATS_LEN; i++) {
 		char *p = (char *)adapter+e1000_gstrings_stats[i].stat_offset;	
-		data[i] = (e1000_gstrings_stats[i].sizeof_stat == sizeof(uint64_t)) 
-			? *(uint64_t *)p : *(uint32_t *)p;
+		data[i] = (e1000_gstrings_stats[i].sizeof_stat == 
+			sizeof(uint64_t)) ? *(uint64_t *)p : *(uint32_t *)p;
 	}
 }
 
diff -Nru a/drivers/net/e1000/e1000_hw.c b/drivers/net/e1000/e1000_hw.c
--- a/drivers/net/e1000/e1000_hw.c	2004-10-18 14:57:04 -07:00
+++ b/drivers/net/e1000/e1000_hw.c	2004-10-18 14:57:04 -07:00
@@ -251,6 +251,7 @@
         break;
     case E1000_DEV_ID_82541ER:
     case E1000_DEV_ID_82541GI:
+    case E1000_DEV_ID_82541GI_LF:
     case E1000_DEV_ID_82541GI_MOBILE:
         hw->mac_type = e1000_82541_rev_2;
         break;
@@ -920,7 +921,8 @@
     if(ret_val)
         return ret_val;
 
-    if(hw->mac_type == e1000_82545_rev_3) {
+    if((hw->mac_type == e1000_82545_rev_3) ||
+       (hw->mac_type == e1000_82546_rev_3)) {
         ret_val = e1000_read_phy_reg(hw, M88E1000_PHY_SPEC_CTRL, &phy_data);
         phy_data |= 0x00000008;
         ret_val = e1000_write_phy_reg(hw, M88E1000_PHY_SPEC_CTRL, phy_data);
@@ -3057,16 +3059,6 @@
         }
         break;
     default:
-        eeprom->type = e1000_eeprom_spi;
-        eeprom->opcode_bits = 8;
-        eeprom->delay_usec = 1;
-        if (eecd & E1000_EECD_ADDR_BITS) {
-            eeprom->page_size = 32;
-            eeprom->address_bits = 16;
-        } else {
-            eeprom->page_size = 8;
-            eeprom->address_bits = 8;
-        }
         break;
     }
 
@@ -3453,7 +3445,6 @@
     uint32_t i = 0;
 
     DEBUGFUNC("e1000_read_eeprom");
-
     /* A check for invalid values:  offset too large, too many words, and not
      * enough words.
      */
@@ -5224,3 +5215,4 @@
     }
     return FALSE;
 }
+
diff -Nru a/drivers/net/e1000/e1000_hw.h b/drivers/net/e1000/e1000_hw.h
--- a/drivers/net/e1000/e1000_hw.h	2004-10-18 14:56:50 -07:00
+++ b/drivers/net/e1000/e1000_hw.h	2004-10-18 14:56:50 -07:00
@@ -357,11 +357,11 @@
 #define E1000_DEV_ID_82547GI             0x1075
 #define E1000_DEV_ID_82541GI             0x1076
 #define E1000_DEV_ID_82541GI_MOBILE      0x1077
+#define E1000_DEV_ID_82541GI_LF          0x107C
 #define E1000_DEV_ID_82546GB_COPPER      0x1079
 #define E1000_DEV_ID_82546GB_FIBER       0x107A
 #define E1000_DEV_ID_82546GB_SERDES      0x107B
 #define E1000_DEV_ID_82547EI             0x1019
-
 #define NODE_ADDRESS_SIZE 6
 #define ETH_LENGTH_OF_ADDRESS 6
 
@@ -1043,7 +1043,6 @@
 
 #define E1000_EEPROM_SWDPIN0   0x0001   /* SWDPIN 0 EEPROM Value */
 #define E1000_EEPROM_LED_LOGIC 0x0020   /* Led Logic Word */
-
 /* Register Bit Masks */
 /* Device Control */
 #define E1000_CTRL_FD       0x00000001  /* Full duplex.0=half; 1=full */
diff -Nru a/drivers/net/e1000/e1000_main.c b/drivers/net/e1000/e1000_main.c
--- a/drivers/net/e1000/e1000_main.c	2004-10-18 14:56:28 -07:00
+++ b/drivers/net/e1000/e1000_main.c	2004-10-18 14:56:28 -07:00
@@ -27,73 +27,69 @@
 *******************************************************************************/
 
 #include "e1000.h"
-#include <linux/rtnetlink.h>
 
 /* Change Log
+ * 5.3.12	6/7/04
+ * - kcompat NETIF_MSG for older kernels (2.4.9) <sean.p.mcdermott@intel.com>
+ * - if_mii support and associated kcompat for older kernels
+ * - More errlogging support from Jon Mason <jonmason@us.ibm.com>
+ * - Fix TSO issues on PPC64 machines -- Jon Mason <jonmason@us.ibm.com>
  *
- * 5.2.51   5/14/04
- *   o set default configuration to 'NAPI disabled'. NAPI enabled driver
- *     causes kernel panic when the interface is shutdown while data is being
- *     transferred.
- * 5.2.47   5/04/04
- *   o fixed ethtool -t implementation
- * 5.2.45   4/29/04
- *   o fixed ethtool -e implementation
- *   o Support for ethtool ops [Stephen Hemminger (shemminger@osdl.org)]
- * 5.2.42   4/26/04
- *   o Added support for the DPRINTK macro for enhanced error logging.  Some
- *     parts of the patch were supplied by Jon Mason.
- *   o Move the register_netdevice() donw in the probe routine due to a 
- *     loading/unloading test issue.
- *   o Added a long RX byte count the the extra ethtool data members for BER
- *     testing purposes.
- * 5.2.39	3/12/04
+ * 5.3.11	6/4/04
+ * - ethtool register dump reads MANC register conditionally.
+ *
+ * 5.3.10	6/1/04
  */
 
 char e1000_driver_name[] = "e1000";
 char e1000_driver_string[] = "Intel(R) PRO/1000 Network Driver";
-char e1000_driver_version[] = "5.2.52-k4";
+#ifndef CONFIG_E1000_NAPI
+#define DRIVERNAPI
+#else
+#define DRIVERNAPI "-NAPI"
+#endif
+char e1000_driver_version[] = "5.3.19-k2"DRIVERNAPI;
 char e1000_copyright[] = "Copyright (c) 1999-2004 Intel Corporation.";
 
 /* e1000_pci_tbl - PCI Device ID Table
  *
- * Wildcard entries (PCI_ANY_ID) should come last
  * Last entry must be all 0s
  *
- * { Vendor ID, Device ID, SubVendor ID, SubDevice ID,
- *   Class, Class Mask, private data (not used) }
+ * Macro expands to...
+ *   {PCI_DEVICE(PCI_VENDOR_ID_INTEL, device_id)}
  */
 static struct pci_device_id e1000_pci_tbl[] = {
-	{0x8086, 0x1000, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
-	{0x8086, 0x1001, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
-	{0x8086, 0x1004, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
-	{0x8086, 0x1008, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
-	{0x8086, 0x1009, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
-	{0x8086, 0x100C, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
-	{0x8086, 0x100D, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
-	{0x8086, 0x100E, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
-	{0x8086, 0x100F, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
-	{0x8086, 0x1010, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
-	{0x8086, 0x1011, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
-	{0x8086, 0x1012, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
-	{0x8086, 0x1013, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
-	{0x8086, 0x1015, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
-	{0x8086, 0x1016, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
-	{0x8086, 0x1017, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
-	{0x8086, 0x1018, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
-	{0x8086, 0x1019, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
-	{0x8086, 0x101D, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
-	{0x8086, 0x101E, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
-	{0x8086, 0x1026, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
-	{0x8086, 0x1027, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
-	{0x8086, 0x1028, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
-	{0x8086, 0x1075, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
-	{0x8086, 0x1076, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
-	{0x8086, 0x1077, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
-	{0x8086, 0x1078, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
-	{0x8086, 0x1079, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
-	{0x8086, 0x107A, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
-	{0x8086, 0x107B, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+	INTEL_E1000_ETHERNET_DEVICE(0x1000),
+	INTEL_E1000_ETHERNET_DEVICE(0x1001),
+	INTEL_E1000_ETHERNET_DEVICE(0x1004),
+	INTEL_E1000_ETHERNET_DEVICE(0x1008),
+	INTEL_E1000_ETHERNET_DEVICE(0x1009),
+	INTEL_E1000_ETHERNET_DEVICE(0x100C),
+	INTEL_E1000_ETHERNET_DEVICE(0x100D),
+	INTEL_E1000_ETHERNET_DEVICE(0x100E),
+	INTEL_E1000_ETHERNET_DEVICE(0x100F),
+	INTEL_E1000_ETHERNET_DEVICE(0x1010),
+	INTEL_E1000_ETHERNET_DEVICE(0x1011),
+	INTEL_E1000_ETHERNET_DEVICE(0x1012),
+	INTEL_E1000_ETHERNET_DEVICE(0x1013),
+	INTEL_E1000_ETHERNET_DEVICE(0x1015),
+	INTEL_E1000_ETHERNET_DEVICE(0x1016),
+	INTEL_E1000_ETHERNET_DEVICE(0x1017),
+	INTEL_E1000_ETHERNET_DEVICE(0x1018),
+	INTEL_E1000_ETHERNET_DEVICE(0x1019),
+	INTEL_E1000_ETHERNET_DEVICE(0x101D),
+	INTEL_E1000_ETHERNET_DEVICE(0x101E),
+	INTEL_E1000_ETHERNET_DEVICE(0x1026),
+	INTEL_E1000_ETHERNET_DEVICE(0x1027),
+	INTEL_E1000_ETHERNET_DEVICE(0x1028),
+	INTEL_E1000_ETHERNET_DEVICE(0x1075),
+	INTEL_E1000_ETHERNET_DEVICE(0x1076),
+	INTEL_E1000_ETHERNET_DEVICE(0x1077),
+	INTEL_E1000_ETHERNET_DEVICE(0x1078),
+	INTEL_E1000_ETHERNET_DEVICE(0x1079),
+	INTEL_E1000_ETHERNET_DEVICE(0x107A),
+	INTEL_E1000_ETHERNET_DEVICE(0x107B),
+	INTEL_E1000_ETHERNET_DEVICE(0x107C),
 	/* required last entry */
 	{0,}
 };
@@ -132,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
@@ -150,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);
@@ -172,7 +168,7 @@
 
 #ifdef CONFIG_NET_POLL_CONTROLLER
 /* for netdump / net console */
-static void e1000_netpoll (struct net_device *dev);
+static void e1000_netpoll (struct net_device *netdev);
 #endif
 
 struct notifier_block e1000_notifier_reboot = {
@@ -185,7 +181,6 @@
 
 extern void e1000_check_options(struct e1000_adapter *adapter);
 
-
 static struct pci_driver e1000_driver = {
 	.name     = e1000_driver_name,
 	.id_table = e1000_pci_tbl,
@@ -202,7 +197,7 @@
 MODULE_DESCRIPTION("Intel(R) PRO/1000 Network Driver");
 MODULE_LICENSE("GPL");
 
-static int debug = 3;
+static int debug = NETIF_MSG_DRV | NETIF_MSG_PROBE;
 module_param(debug, int, 0);
 MODULE_PARM_DESC(debug, "Debug level (0=none,...,16=all)");
 
@@ -256,6 +251,14 @@
 
 	/* hardware has been reset, we need to reload some things */
 
+	/* Reset the PHY if it was previously powered down */
+	if(adapter->hw.media_type == e1000_media_type_copper) {
+		uint16_t mii_reg;
+		e1000_read_phy_reg(&adapter->hw, PHY_CTRL, &mii_reg);
+		if(mii_reg & MII_CR_POWER_DOWN)
+			e1000_phy_reset(&adapter->hw);
+	}
+
 	e1000_set_multi(netdev);
 
 	e1000_restore_vlan(adapter);
@@ -294,6 +297,15 @@
 	e1000_reset(adapter);
 	e1000_clean_tx_ring(adapter);
 	e1000_clean_rx_ring(adapter);
+
+	/* If WoL is not enabled
+	 * Power down the PHY so no link is implied when interface is down */
+	if(!adapter->wol && adapter->hw.media_type == e1000_media_type_copper) {
+		uint16_t mii_reg;
+		e1000_read_phy_reg(&adapter->hw, PHY_CTRL, &mii_reg);
+		mii_reg |= MII_CR_POWER_DOWN;
+		e1000_write_phy_reg(&adapter->hw, PHY_CTRL, mii_reg);
+	}
 }
 
 void
@@ -323,10 +335,10 @@
 	E1000_WRITE_REG(&adapter->hw, PBA, pba);
 
 	/* flow control settings */
-	adapter->hw.fc_high_water =
-		(pba << E1000_PBA_BYTES_SHIFT) - E1000_FC_HIGH_DIFF;
-	adapter->hw.fc_low_water =
-		(pba << E1000_PBA_BYTES_SHIFT) - E1000_FC_LOW_DIFF;
+	adapter->hw.fc_high_water = (pba << E1000_PBA_BYTES_SHIFT) -
+				    E1000_FC_HIGH_DIFF;
+	adapter->hw.fc_low_water = (pba << E1000_PBA_BYTES_SHIFT) -
+				   E1000_FC_LOW_DIFF;
 	adapter->hw.fc_pause_time = E1000_FC_PAUSE_TIME;
 	adapter->hw.fc_send_xon = 1;
 	adapter->hw.fc = adapter->hw.original_fc;
@@ -334,7 +346,8 @@
 	e1000_reset_hw(&adapter->hw);
 	if(adapter->hw.mac_type >= e1000_82544)
 		E1000_WRITE_REG(&adapter->hw, WUC, 0);
-	e1000_init_hw(&adapter->hw);
+	if(e1000_init_hw(&adapter->hw))
+		DPRINTK(PROBE, ERR, "Hardware Error\n");
 
 	/* Enable h/w to recognize an 802.1Q VLAN Ethernet packet */
 	E1000_WRITE_REG(&adapter->hw, VET, ETHERNET_IEEE_VLAN_TYPE);
@@ -410,8 +423,8 @@
 	adapter->msg_enable = (1 << debug) - 1;
 
 	rtnl_lock();
-	/* we need to set the name early since the DPRINTK macro needs it set */
-	if (dev_alloc_name(netdev, netdev->name) < 0) 
+	/* we need to set the name early for the DPRINTK macro */
+	if(dev_alloc_name(netdev, netdev->name) < 0)
 		goto err_free_unlock;
 
 	mmio_start = pci_resource_start(pdev, BAR_0);
@@ -476,7 +489,6 @@
 	}
 
 #ifdef NETIF_F_TSO
-#ifdef BROKEN_ON_NON_IA_ARCHS
 	/* Disbaled for now until root-cause is found for
 	 * hangs reported against non-IA archs.  TSO can be
 	 * enabled using ethtool -K eth<x> tso on */
@@ -484,11 +496,12 @@
 	   (adapter->hw.mac_type != e1000_82547))
 		netdev->features |= NETIF_F_TSO;
 #endif
-#endif
-
 	if(pci_using_dac)
 		netdev->features |= NETIF_F_HIGHDMA;
 
+ 	/* hard_start_xmit is safe against parallel locking */
+ 	netdev->features |= NETIF_F_LLTX; 
+ 
 	adapter->en_mng_pt = e1000_enable_mng_pass_thru(&adapter->hw);
 
 	/* before reading the EEPROM, reset the controller to 
@@ -506,10 +519,12 @@
 
 	/* copy the MAC address out of the EEPROM */
 
-	e1000_read_mac_addr(&adapter->hw);
+	if (e1000_read_mac_addr(&adapter->hw))
+		DPRINTK(PROBE, ERR, "EEPROM Read Error\n");
 	memcpy(netdev->dev_addr, adapter->hw.mac_addr, netdev->addr_len);
 
 	if(!is_valid_ether_addr(netdev->dev_addr)) {
+		DPRINTK(PROBE, ERR, "Invalid MAC Address\n");
 		err = -EIO;
 		goto err_eeprom;
 	}
@@ -569,10 +584,9 @@
 		adapter->wol |= E1000_WUFC_MAG;
 
 	/* reset the hardware with the new settings */
-
 	e1000_reset(adapter);
 
-	/* since we are holding the rtnl lock already, call the no-lock version */
+	/* We're already holding the rtnl lock; call the no-lock version */
 	if((err = register_netdevice(netdev)))
 		goto err_register;
 
@@ -663,7 +677,7 @@
 
 	/* identify the MAC */
 
-	if (e1000_set_mac_type(hw)) {
+	if(e1000_set_mac_type(hw)) {
 		DPRINTK(PROBE, ERR, "Unknown MAC Type\n");
 		return -EIO;
 	}
@@ -672,19 +686,19 @@
 
 	e1000_init_eeprom_params(hw);
 
-	if((hw->mac_type == e1000_82541) ||
-	   (hw->mac_type == e1000_82547) ||
-	   (hw->mac_type == e1000_82541_rev_2) ||
-	   (hw->mac_type == e1000_82547_rev_2))
+	switch(hw->mac_type) {
+	default:
+		break;
+	case e1000_82541:
+	case e1000_82547:
+	case e1000_82541_rev_2:
+	case e1000_82547_rev_2:
 		hw->phy_init_script = 1;
+		break;
+	}
 
 	e1000_set_media_type(hw);
 
-	if(hw->mac_type < e1000_82543)
-		hw->report_tx_early = 0;
-	else
-		hw->report_tx_early = 1;
-
 	hw->wait_autoneg_complete = FALSE;
 	hw->tbi_compatibility_en = TRUE;
 	hw->adaptive_ifs = TRUE;
@@ -736,7 +750,7 @@
 	if((err = e1000_up(adapter)))
 		goto err_up;
 
-	return 0;
+	return E1000_SUCCESS;
 
 err_up:
 	e1000_free_rx_resources(adapter);
@@ -788,8 +802,10 @@
 	int size;
 
 	size = sizeof(struct e1000_buffer) * txdr->count;
-	txdr->buffer_info = kmalloc(size, GFP_KERNEL);
+	txdr->buffer_info = vmalloc(size);
 	if(!txdr->buffer_info) {
+		DPRINTK(PROBE, ERR, 
+		"Unble to Allocate Memory for the Transmit descriptor ring\n");
 		return -ENOMEM;
 	}
 	memset(txdr->buffer_info, 0, size);
@@ -801,7 +817,9 @@
 
 	txdr->desc = pci_alloc_consistent(pdev, txdr->size, &txdr->dma);
 	if(!txdr->desc) {
-		kfree(txdr->buffer_info);
+		DPRINTK(PROBE, ERR, 
+		"Unble to Allocate Memory for the Transmit descriptor ring\n");
+		vfree(txdr->buffer_info);
 		return -ENOMEM;
 	}
 	memset(txdr->desc, 0, txdr->size);
@@ -878,10 +896,10 @@
 	adapter->txd_cmd = E1000_TXD_CMD_IDE | E1000_TXD_CMD_EOP |
 		E1000_TXD_CMD_IFCS;
 
-	if(adapter->hw.report_tx_early == 1)
-		adapter->txd_cmd |= E1000_TXD_CMD_RS;
-	else
+	if(adapter->hw.mac_type < e1000_82543)
 		adapter->txd_cmd |= E1000_TXD_CMD_RPS;
+	else
+		adapter->txd_cmd |= E1000_TXD_CMD_RS;
 
 	/* Cache if we're 82544 running in PCI-X because we'll
 	 * need this to apply a workaround later in the send path. */
@@ -905,8 +923,10 @@
 	int size;
 
 	size = sizeof(struct e1000_buffer) * rxdr->count;
-	rxdr->buffer_info = kmalloc(size, GFP_KERNEL);
+	rxdr->buffer_info = vmalloc(size);
 	if(!rxdr->buffer_info) {
+		DPRINTK(PROBE, ERR, 
+		"Unble to Allocate Memory for the Recieve descriptor ring\n");
 		return -ENOMEM;
 	}
 	memset(rxdr->buffer_info, 0, size);
@@ -919,7 +939,9 @@
 	rxdr->desc = pci_alloc_consistent(pdev, rxdr->size, &rxdr->dma);
 
 	if(!rxdr->desc) {
-		kfree(rxdr->buffer_info);
+		DPRINTK(PROBE, ERR, 
+		"Unble to Allocate Memory for the Recieve descriptor ring\n");
+		vfree(rxdr->buffer_info);
 		return -ENOMEM;
 	}
 	memset(rxdr->desc, 0, rxdr->size);
@@ -953,7 +975,9 @@
 	else
 		rctl &= ~E1000_RCTL_SBP;
 
+	/* Setup buffer sizes */
 	rctl &= ~(E1000_RCTL_SZ_4096);
+	rctl |= (E1000_RCTL_BSEX | E1000_RCTL_LPE);
 	switch (adapter->rx_buffer_len) {
 	case E1000_RXBUFFER_2048:
 	default:
@@ -961,13 +985,13 @@
 		rctl &= ~(E1000_RCTL_BSEX | E1000_RCTL_LPE);
 		break;
 	case E1000_RXBUFFER_4096:
-		rctl |= E1000_RCTL_SZ_4096 | E1000_RCTL_BSEX | E1000_RCTL_LPE;
+		rctl |= E1000_RCTL_SZ_4096;
 		break;
 	case E1000_RXBUFFER_8192:
-		rctl |= E1000_RCTL_SZ_8192 | E1000_RCTL_BSEX | E1000_RCTL_LPE;
+		rctl |= E1000_RCTL_SZ_8192;
 		break;
 	case E1000_RXBUFFER_16384:
-		rctl |= E1000_RCTL_SZ_16384 | E1000_RCTL_BSEX | E1000_RCTL_LPE;
+		rctl |= E1000_RCTL_SZ_16384;
 		break;
 	}
 
@@ -989,13 +1013,11 @@
 	uint32_t rctl;
 	uint32_t rxcsum;
 
-	/* make sure receives are disabled while setting up the descriptors */
-
+	/* disable receives while setting up the descriptors */
 	rctl = E1000_READ_REG(&adapter->hw, RCTL);
 	E1000_WRITE_REG(&adapter->hw, RCTL, rctl & ~E1000_RCTL_EN);
 
 	/* set the Receive Delay Timer Register */
-
 	E1000_WRITE_REG(&adapter->hw, RDTR, adapter->rx_int_delay);
 
 	if(adapter->hw.mac_type >= e1000_82540) {
@@ -1006,7 +1028,6 @@
 	}
 
 	/* Setup the Base and Length of the Rx Descriptor Ring */
-
 	E1000_WRITE_REG(&adapter->hw, RDBAL, (rdba & 0x00000000ffffffffULL));
 	E1000_WRITE_REG(&adapter->hw, RDBAH, (rdba >> 32));
 
@@ -1025,7 +1046,6 @@
 	}
 
 	/* Enable Receives */
-
 	E1000_WRITE_REG(&adapter->hw, RCTL, rctl);
 }
 
@@ -1043,7 +1063,7 @@
 
 	e1000_clean_tx_ring(adapter);
 
-	kfree(adapter->tx_ring.buffer_info);
+	vfree(adapter->tx_ring.buffer_info);
 	adapter->tx_ring.buffer_info = NULL;
 
 	pci_free_consistent(pdev, adapter->tx_ring.size,
@@ -1073,9 +1093,9 @@
 		if(buffer_info->skb) {
 
 			pci_unmap_page(pdev,
-			               buffer_info->dma,
-			               buffer_info->length,
-			               PCI_DMA_TODEVICE);
+				       buffer_info->dma,
+				       buffer_info->length,
+				       PCI_DMA_TODEVICE);
 
 			dev_kfree_skb(buffer_info->skb);
 
@@ -1112,7 +1132,7 @@
 
 	e1000_clean_rx_ring(adapter);
 
-	kfree(rx_ring->buffer_info);
+	vfree(rx_ring->buffer_info);
 	rx_ring->buffer_info = NULL;
 
 	pci_free_consistent(pdev, rx_ring->size, rx_ring->desc, rx_ring->dma);
@@ -1141,12 +1161,11 @@
 		if(buffer_info->skb) {
 
 			pci_unmap_single(pdev,
-			                 buffer_info->dma,
-			                 buffer_info->length,
-			                 PCI_DMA_FROMDEVICE);
+					 buffer_info->dma,
+					 buffer_info->length,
+					 PCI_DMA_FROMDEVICE);
 
 			dev_kfree_skb(buffer_info->skb);
-
 			buffer_info->skb = NULL;
 		}
 	}
@@ -1259,9 +1278,12 @@
 	uint32_t rctl;
 	uint32_t hash_value;
 	int i;
+	unsigned long flags;
 
 	/* Check for Promiscuous and All Multicast modes */
 
+	spin_lock_irqsave(&adapter->tx_lock, flags);
+
 	rctl = E1000_READ_REG(hw, RCTL);
 
 	if(netdev->flags & IFF_PROMISC) {
@@ -1310,9 +1332,12 @@
 
 	if(hw->mac_type == e1000_82542_rev2_0)
 		e1000_leave_82542_rst(adapter);
+
+	spin_unlock_irqrestore(&adapter->tx_lock, flags);
 }
 
-/* need to wait a few seconds after link up to get diagnostic information from the phy */
+/* Need to wait a few seconds after link up to get diagnostic information from
+ * the phy */
 
 static void
 e1000_update_phy_info(unsigned long data)
@@ -1420,7 +1445,7 @@
 	adapter->tpt_old = adapter->stats.tpt;
 	adapter->hw.collision_delta = adapter->stats.colc - adapter->colc_old;
 	adapter->colc_old = adapter->stats.colc;
-	
+
 	adapter->gorcl = adapter->stats.gorcl - adapter->gorcl_old;
 	adapter->gorcl_old = adapter->stats.gorcl;
 	adapter->gotcl = adapter->stats.gotcl - adapter->gotcl_old;
@@ -1477,8 +1502,9 @@
 #ifdef NETIF_F_TSO
 	struct e1000_context_desc *context_desc;
 	unsigned int i;
-	uint8_t ipcss, ipcso, tucss, tucso, hdr_len;
+	uint32_t cmd_length = 0;
 	uint16_t ipcse, tucse, mss;
+	uint8_t ipcss, ipcso, tucss, tucso, hdr_len;
 
 	if(skb_shinfo(skb)->tso_size) {
 		hdr_len = ((skb->h.raw - skb->data) + (skb->h.th->doff << 2));
@@ -1497,6 +1523,10 @@
 		tucso = (void *)&(skb->h.th->check) - (void *)skb->data;
 		tucse = 0;
 
+		cmd_length |= (E1000_TXD_CMD_DEXT | E1000_TXD_CMD_TSE |
+			       E1000_TXD_CMD_IP | E1000_TXD_CMD_TCP |
+			       (skb->len - (hdr_len)));
+
 		i = adapter->tx_ring.next_to_use;
 		context_desc = E1000_CONTEXT_DESC(adapter->tx_ring, i);
 
@@ -1508,10 +1538,7 @@
 		context_desc->upper_setup.tcp_fields.tucse = cpu_to_le16(tucse);
 		context_desc->tcp_seg_setup.fields.mss     = cpu_to_le16(mss);
 		context_desc->tcp_seg_setup.fields.hdr_len = hdr_len;
-		context_desc->cmd_and_length = cpu_to_le32(
-			E1000_TXD_CMD_DEXT | E1000_TXD_CMD_TSE |
-			E1000_TXD_CMD_IP | E1000_TXD_CMD_TCP |
-			(skb->len - (hdr_len)));
+		context_desc->cmd_and_length = cpu_to_le32(cmd_length);
 
 		if(++i == adapter->tx_ring.count) i = 0;
 		adapter->tx_ring.next_to_use = i;
@@ -1528,22 +1555,21 @@
 {
 	struct e1000_context_desc *context_desc;
 	unsigned int i;
-	uint8_t css, cso;
+	uint8_t css;
 
-	if(skb->ip_summed == CHECKSUM_HW) {
+	if(likely(skb->ip_summed == CHECKSUM_HW)) {
 		css = skb->h.raw - skb->data;
-		cso = (skb->h.raw + skb->csum) - skb->data;
 
 		i = adapter->tx_ring.next_to_use;
 		context_desc = E1000_CONTEXT_DESC(adapter->tx_ring, i);
 
 		context_desc->upper_setup.tcp_fields.tucss = css;
-		context_desc->upper_setup.tcp_fields.tucso = cso;
+		context_desc->upper_setup.tcp_fields.tucso = css + skb->csum;
 		context_desc->upper_setup.tcp_fields.tucse = 0;
 		context_desc->tcp_seg_setup.data = 0;
 		context_desc->cmd_and_length = cpu_to_le32(E1000_TXD_CMD_DEXT);
 
-		if(++i == adapter->tx_ring.count) i = 0;
+		if(unlikely(++i == adapter->tx_ring.count)) i = 0;
 		adapter->tx_ring.next_to_use = i;
 
 		return TRUE;
@@ -1567,7 +1593,6 @@
 	unsigned int f;
 	len -= skb->data_len;
 
-
 	i = tx_ring->next_to_use;
 
 	while(len) {
@@ -1576,14 +1601,14 @@
 #ifdef NETIF_F_TSO
 		/* Workaround for premature desc write-backs
 		 * in TSO mode.  Append 4-byte sentinel desc */
-		if(mss && !nr_frags && size == len && size > 8)
+		if(unlikely(mss && !nr_frags && size == len && size > 8))
 			size -= 4;
 #endif
 		/* Workaround for potential 82544 hang in PCI-X.  Avoid
 		 * terminating buffers within evenly-aligned dwords. */
-		if(adapter->pcix_82544 &&
+		if(unlikely(adapter->pcix_82544 &&
 		   !((unsigned long)(skb->data + offset + size - 1) & 4) &&
-		   size > 4)
+		   size > 4))
 			size -= 4;
 
 		buffer_info->length = size;
@@ -1597,7 +1622,7 @@
 		len -= size;
 		offset += size;
 		count++;
-		if(++i == tx_ring->count) i = 0;
+		if(unlikely(++i == tx_ring->count)) i = 0;
 	}
 
 	for(f = 0; f < nr_frags; f++) {
@@ -1613,15 +1638,15 @@
 #ifdef NETIF_F_TSO
 			/* Workaround for premature desc write-backs
 			 * in TSO mode.  Append 4-byte sentinel desc */
-			if(mss && f == (nr_frags-1) && size == len && size > 8)
+			if(unlikely(mss && f == (nr_frags-1) && size == len && size > 8))
 				size -= 4;
 #endif
 			/* Workaround for potential 82544 hang in PCI-X.
 			 * Avoid terminating buffers within evenly-aligned
 			 * dwords. */
-			if(adapter->pcix_82544 &&
+			if(unlikely(adapter->pcix_82544 &&
 			   !((unsigned long)(frag->page+offset+size-1) & 4) &&
-			   size > 4)
+			   size > 4))
 				size -= 4;
 
 			buffer_info->length = size;
@@ -1636,13 +1661,14 @@
 			len -= size;
 			offset += size;
 			count++;
-			if(++i == tx_ring->count) i = 0;
+			if(unlikely(++i == tx_ring->count)) i = 0;
 		}
 	}
+
 	i = (i == 0) ? tx_ring->count - 1 : i - 1;
 	tx_ring->buffer_info[i].skb = skb;
 	tx_ring->buffer_info[first].next_to_watch = i;
-	
+
 	return count;
 }
 
@@ -1655,18 +1681,18 @@
 	uint32_t txd_upper = 0, txd_lower = E1000_TXD_CMD_IFCS;
 	unsigned int i;
 
-	if(tx_flags & E1000_TX_FLAGS_TSO) {
+	if(likely(tx_flags & E1000_TX_FLAGS_TSO)) {
 		txd_lower |= E1000_TXD_CMD_DEXT | E1000_TXD_DTYP_D |
 		             E1000_TXD_CMD_TSE;
 		txd_upper |= (E1000_TXD_POPTS_IXSM | E1000_TXD_POPTS_TXSM) << 8;
 	}
 
-	if(tx_flags & E1000_TX_FLAGS_CSUM) {
+	if(likely(tx_flags & E1000_TX_FLAGS_CSUM)) {
 		txd_lower |= E1000_TXD_CMD_DEXT | E1000_TXD_DTYP_D;
 		txd_upper |= E1000_TXD_POPTS_TXSM << 8;
 	}
 
-	if(tx_flags & E1000_TX_FLAGS_VLAN) {
+	if(unlikely(tx_flags & E1000_TX_FLAGS_VLAN)) {
 		txd_lower |= E1000_TXD_CMD_VLE;
 		txd_upper |= (tx_flags & E1000_TX_FLAGS_VLAN_MASK);
 	}
@@ -1680,7 +1706,7 @@
 		tx_desc->lower.data =
 			cpu_to_le32(txd_lower | buffer_info->length);
 		tx_desc->upper.data = cpu_to_le32(txd_upper);
-		if(++i == tx_ring->count) i = 0;
+		if(unlikely(++i == tx_ring->count)) i = 0;
 	}
 
 	tx_desc->lower.data |= cpu_to_le32(adapter->txd_cmd);
@@ -1733,7 +1759,7 @@
 	return 0;
 }
 
-#define TXD_USE_COUNT(S, X) (((S) >> (X)) + 1 ) 
+#define TXD_USE_COUNT(S, X) (((S) >> (X)) + 1 )
 static int
 e1000_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
 {
@@ -1741,22 +1767,23 @@
 	unsigned int first, max_per_txd = E1000_MAX_DATA_PER_TXD;
 	unsigned int max_txd_pwr = E1000_MAX_TXD_PWR;
 	unsigned int tx_flags = 0;
-	unsigned long flags;
 	unsigned int len = skb->len;
-	int count = 0;
-	unsigned int mss = 0;
+	unsigned long flags;
 	unsigned int nr_frags = 0;
+	unsigned int mss = 0;
+	int count = 0;
 	unsigned int f;
 	nr_frags = skb_shinfo(skb)->nr_frags;
 	len -= skb->data_len;
-	if(skb->len <= 0) {
+
+	if(unlikely(skb->len <= 0)) {
 		dev_kfree_skb_any(skb);
-		return 0;
+		return NETDEV_TX_OK;
 	}
 
 #ifdef NETIF_F_TSO
 	mss = skb_shinfo(skb)->tso_size;
-	/* The controller does a simple calculation to 
+	/* The controller does a simple calculation to
 	 * make sure there is enough room in the FIFO before
 	 * initiating the DMA for each buffer.  The calc is:
 	 * 4 = ceil(buffer len/mss).  To make sure we don't
@@ -1766,62 +1793,70 @@
 		max_per_txd = min(mss << 2, max_per_txd);
 		max_txd_pwr = fls(max_per_txd) - 1;
 	}
+
 	if((mss) || (skb->ip_summed == CHECKSUM_HW))
 		count++;
-	count++;	/*for sentinel desc*/
+	count++;	/* for sentinel desc */
 #else
 	if(skb->ip_summed == CHECKSUM_HW)
 		count++;
 #endif
-
 	count += TXD_USE_COUNT(len, max_txd_pwr);
+
 	if(adapter->pcix_82544)
 		count++;
 
 	nr_frags = skb_shinfo(skb)->nr_frags;
 	for(f = 0; f < nr_frags; f++)
 		count += TXD_USE_COUNT(skb_shinfo(skb)->frags[f].size,
-		                       max_txd_pwr);
+				       max_txd_pwr);
 	if(adapter->pcix_82544)
 		count += nr_frags;
-	
-	spin_lock_irqsave(&adapter->tx_lock, flags);
-	/* need: count +  2 desc gap to keep tail from touching 
+
+ 	local_irq_save(flags); 
+ 	if (!spin_trylock(&adapter->tx_lock)) { 
+ 		/* Collision - tell upper layer to requeue */ 
+ 		local_irq_restore(flags); 
+ 		return NETDEV_TX_LOCKED; 
+ 	} 
+
+	/* need: count + 2 desc gap to keep tail from touching
 	 * head, otherwise try next time */
-	if(E1000_DESC_UNUSED(&adapter->tx_ring) < count + 2 ) {
+	if(E1000_DESC_UNUSED(&adapter->tx_ring) < count + 2) {
 		netif_stop_queue(netdev);
 		spin_unlock_irqrestore(&adapter->tx_lock, flags);
-		return 1;
+		return NETDEV_TX_BUSY;
 	}
-	spin_unlock_irqrestore(&adapter->tx_lock, flags);
 
-	if(adapter->hw.mac_type == e1000_82547) {
-		if(e1000_82547_fifo_workaround(adapter, skb)) {
+	if(unlikely(adapter->hw.mac_type == e1000_82547)) {
+		if(unlikely(e1000_82547_fifo_workaround(adapter, skb))) {
 			netif_stop_queue(netdev);
 			mod_timer(&adapter->tx_fifo_stall_timer, jiffies);
-			return 1;
+			spin_unlock_irqrestore(&adapter->tx_lock, flags);
+			return NETDEV_TX_BUSY;
 		}
 	}
 
-	if(adapter->vlgrp && vlan_tx_tag_present(skb)) {
+	if(unlikely(adapter->vlgrp && vlan_tx_tag_present(skb))) {
 		tx_flags |= E1000_TX_FLAGS_VLAN;
 		tx_flags |= (vlan_tx_tag_get(skb) << E1000_TX_FLAGS_VLAN_SHIFT);
 	}
 
 	first = adapter->tx_ring.next_to_use;
 	
-	if(e1000_tso(adapter, skb))
+	if(likely(e1000_tso(adapter, skb)))
 		tx_flags |= E1000_TX_FLAGS_TSO;
-	else if(e1000_tx_csum(adapter, skb))
+	else if(likely(e1000_tx_csum(adapter, skb)))
 		tx_flags |= E1000_TX_FLAGS_CSUM;
 
-	e1000_tx_queue(adapter, 
-		e1000_tx_map(adapter, skb, first, max_per_txd, nr_frags, mss), 
+	e1000_tx_queue(adapter,
+		e1000_tx_map(adapter, skb, first, max_per_txd, nr_frags, mss),
 		tx_flags);
 
 	netdev->trans_start = jiffies;
 
-	return 0;
+	spin_unlock_irqrestore(&adapter->tx_lock, flags);
+	return NETDEV_TX_OK;
 }
 
 /**
@@ -1843,10 +1878,8 @@
 {
 	struct e1000_adapter *adapter = netdev->priv;
 
-	netif_device_detach(netdev);
 	e1000_down(adapter);
 	e1000_up(adapter);
-	netif_device_attach(netdev);
 }
 
 /**
@@ -1905,7 +1938,6 @@
 	}
 
 	if(old_mtu != adapter->rx_buffer_len && netif_running(netdev)) {
-
 		e1000_down(adapter);
 		e1000_up(adapter);
 	}
@@ -1951,8 +1983,6 @@
 	adapter->stats.prc1023 += E1000_READ_REG(hw, PRC1023);
 	adapter->stats.prc1522 += E1000_READ_REG(hw, PRC1522);
 
-	/* the rest of the counters are only modified here */
-
 	adapter->stats.symerrs += E1000_READ_REG(hw, SYMERRS);
 	adapter->stats.mpc += E1000_READ_REG(hw, MPC);
 	adapter->stats.scc += E1000_READ_REG(hw, SCC);
@@ -2059,7 +2089,7 @@
  * @adapter: board private structure
  **/
 
-static inline void
+static void
 e1000_irq_disable(struct e1000_adapter *adapter)
 {
 	atomic_inc(&adapter->irq_sem);
@@ -2073,10 +2103,10 @@
  * @adapter: board private structure
  **/
 
-static inline void
+static void
 e1000_irq_enable(struct e1000_adapter *adapter)
 {
-	if(atomic_dec_and_test(&adapter->irq_sem)) {
+	if(likely(atomic_dec_and_test(&adapter->irq_sem))) {
 		E1000_WRITE_REG(&adapter->hw, IMS, IMS_ENABLE_MASK);
 		E1000_WRITE_FLUSH(&adapter->hw);
 	}
@@ -2095,21 +2125,21 @@
 	struct net_device *netdev = data;
 	struct e1000_adapter *adapter = netdev->priv;
 	struct e1000_hw *hw = &adapter->hw;
-	uint32_t icr = E1000_READ_REG(&adapter->hw, ICR);
+	uint32_t icr = E1000_READ_REG(hw, ICR);
 #ifndef CONFIG_E1000_NAPI
 	unsigned int i;
 #endif
 
-	if(!icr)
+	if(unlikely(!icr))
 		return IRQ_NONE;  /* Not our interrupt */
 
-	if(icr & (E1000_ICR_RXSEQ | E1000_ICR_LSC)) {
+	if(unlikely(icr & (E1000_ICR_RXSEQ | E1000_ICR_LSC))) {
 		hw->get_link_status = 1;
 		mod_timer(&adapter->watchdog_timer, jiffies);
 	}
 
 #ifdef CONFIG_E1000_NAPI
-	if(netif_rx_schedule_prep(netdev)) {
+	if(likely(netif_rx_schedule_prep(netdev))) {
 
 		/* Disable interrupts and register for poll. The flush 
 		  of the posted write is intentionally left out.
@@ -2121,8 +2151,8 @@
 	}
 #else
 	for(i = 0; i < E1000_MAX_INTR; i++)
-		if(!e1000_clean_rx_irq(adapter) &
-		   !e1000_clean_tx_irq(adapter))
+		if(unlikely(!e1000_clean_rx_irq(adapter) &
+		   !e1000_clean_tx_irq(adapter)))
 			break;
 #endif
 
@@ -2140,15 +2170,18 @@
 {
 	struct e1000_adapter *adapter = netdev->priv;
 	int work_to_do = min(*budget, netdev->quota);
+	int tx_cleaned;
 	int work_done = 0;
 	
-	e1000_clean_tx_irq(adapter);
+	tx_cleaned = e1000_clean_tx_irq(adapter);
 	e1000_clean_rx_irq(adapter, &work_done, work_to_do);
 
 	*budget -= work_done;
 	netdev->quota -= work_done;
 	
-	if(work_done < work_to_do || !netif_running(netdev)) {
+	/* if no Rx and Tx cleanup work was done, exit the polling mode */
+	if(!tx_cleaned || (work_done < work_to_do) || 
+				!netif_running(netdev)) {
 		netif_rx_complete(netdev);
 		e1000_irq_enable(adapter);
 		return 0;
@@ -2156,8 +2189,8 @@
 
 	return (work_done >= work_to_do);
 }
-#endif
 
+#endif
 /**
  * e1000_clean_tx_irq - Reclaim resources after transmit completes
  * @adapter: board private structure
@@ -2174,31 +2207,25 @@
 	unsigned int i, eop;
 	boolean_t cleaned = FALSE;
 
-
 	i = tx_ring->next_to_clean;
 	eop = tx_ring->buffer_info[i].next_to_watch;
 	eop_desc = E1000_TX_DESC(*tx_ring, eop);
 
 	while(eop_desc->upper.data & cpu_to_le32(E1000_TXD_STAT_DD)) {
-
 		for(cleaned = FALSE; !cleaned; ) {
 			tx_desc = E1000_TX_DESC(*tx_ring, i);
 			buffer_info = &tx_ring->buffer_info[i];
 
-			if(buffer_info->dma) {
-
+			if(likely(buffer_info->dma)) {
 				pci_unmap_page(pdev,
 					       buffer_info->dma,
 					       buffer_info->length,
 					       PCI_DMA_TODEVICE);
-
 				buffer_info->dma = 0;
 			}
 
 			if(buffer_info->skb) {
-
 				dev_kfree_skb_any(buffer_info->skb);
-
 				buffer_info->skb = NULL;
 			}
 
@@ -2207,7 +2234,7 @@
 			tx_desc->upper.data = 0;
 
 			cleaned = (i == eop);
-			if(++i == tx_ring->count) i = 0;
+			if(unlikely(++i == tx_ring->count)) i = 0;
 		}
 		
 		eop = tx_ring->buffer_info[i].next_to_watch;
@@ -2218,7 +2245,8 @@
 
 	spin_lock(&adapter->tx_lock);
 
-	if(cleaned && netif_queue_stopped(netdev) && netif_carrier_ok(netdev))
+	if(unlikely(cleaned && netif_queue_stopped(netdev) &&
+		    netif_carrier_ok(netdev)))
 		netif_wake_queue(netdev);
 
 	spin_unlock(&adapter->tx_lock);
@@ -2227,7 +2255,7 @@
 }
 
 /**
- * e1000_clean_rx_irq - Send received data up the network stack,
+ * e1000_clean_rx_irq - Send received data up the network stack
  * @adapter: board private structure
  **/
 
@@ -2256,14 +2284,11 @@
 
 	while(rx_desc->status & E1000_RXD_STAT_DD) {
 		buffer_info = &rx_ring->buffer_info[i];
-
 #ifdef CONFIG_E1000_NAPI
 		if(*work_done >= work_to_do)
 			break;
-
 		(*work_done)++;
 #endif
-
 		cleaned = TRUE;
 
 		pci_unmap_single(pdev,
@@ -2274,49 +2299,28 @@
 		skb = buffer_info->skb;
 		length = le16_to_cpu(rx_desc->length);
 
-		if(!(rx_desc->status & E1000_RXD_STAT_EOP)) {
-
+		if(unlikely(!(rx_desc->status & E1000_RXD_STAT_EOP))) {
 			/* All receives must fit into a single buffer */
-
-			E1000_DBG("%s: Receive packet consumed multiple buffers\n",
-				netdev->name);
-
+			E1000_DBG("%s: Receive packet consumed multiple"
+				  " buffers\n", netdev->name);
 			dev_kfree_skb_irq(skb);
-			rx_desc->status = 0;
-			buffer_info->skb = NULL;
-
-			if(++i == rx_ring->count) i = 0;
-
-			rx_desc = E1000_RX_DESC(*rx_ring, i);
-			continue;
+			goto next_desc;
 		}
 
-		if(rx_desc->errors & E1000_RXD_ERR_FRAME_ERR_MASK) {
-
+		if(unlikely(rx_desc->errors & E1000_RXD_ERR_FRAME_ERR_MASK)) {
 			last_byte = *(skb->data + length - 1);
-
 			if(TBI_ACCEPT(&adapter->hw, rx_desc->status,
 			              rx_desc->errors, length, last_byte)) {
-
 				spin_lock_irqsave(&adapter->stats_lock, flags);
-
 				e1000_tbi_adjust_stats(&adapter->hw,
 				                       &adapter->stats,
 				                       length, skb->data);
-
 				spin_unlock_irqrestore(&adapter->stats_lock,
 				                       flags);
 				length--;
 			} else {
-
 				dev_kfree_skb_irq(skb);
-				rx_desc->status = 0;
-				buffer_info->skb = NULL;
-
-				if(++i == rx_ring->count) i = 0;
-
-				rx_desc = E1000_RX_DESC(*rx_ring, i);
-				continue;
+				goto next_desc;
 			}
 		}
 
@@ -2328,17 +2332,19 @@
 
 		skb->protocol = eth_type_trans(skb, netdev);
 #ifdef CONFIG_E1000_NAPI
-		if(adapter->vlgrp && (rx_desc->status & E1000_RXD_STAT_VP)) {
+		if(unlikely(adapter->vlgrp &&
+			    (rx_desc->status & E1000_RXD_STAT_VP))) {
 			vlan_hwaccel_receive_skb(skb, adapter->vlgrp,
-				le16_to_cpu(rx_desc->special &
-					E1000_RXD_SPC_VLAN_MASK));
+						 le16_to_cpu(rx_desc->special &
+						 E1000_RXD_SPC_VLAN_MASK));
 		} else {
 			netif_receive_skb(skb);
 		}
 #else /* CONFIG_E1000_NAPI */
-		if(adapter->vlgrp && (rx_desc->status & E1000_RXD_STAT_VP)) {
+		if(unlikely(adapter->vlgrp &&
+			    (rx_desc->status & E1000_RXD_STAT_VP))) {
 			vlan_hwaccel_rx(skb, adapter->vlgrp,
-				le16_to_cpu(rx_desc->special &
+					le16_to_cpu(rx_desc->special &
 					E1000_RXD_SPC_VLAN_MASK));
 		} else {
 			netif_rx(skb);
@@ -2346,10 +2352,10 @@
 #endif /* CONFIG_E1000_NAPI */
 		netdev->last_rx = jiffies;
 
+next_desc:
 		rx_desc->status = 0;
 		buffer_info->skb = NULL;
-
-		if(++i == rx_ring->count) i = 0;
+		if(unlikely(++i == rx_ring->count)) i = 0;
 
 		rx_desc = E1000_RX_DESC(*rx_ring, i);
 	}
@@ -2381,11 +2387,9 @@
 	buffer_info = &rx_ring->buffer_info[i];
 
 	while(!buffer_info->skb) {
-		rx_desc = E1000_RX_DESC(*rx_ring, i);
 
 		skb = dev_alloc_skb(adapter->rx_buffer_len + NET_IP_ALIGN);
-
-		if(!skb) {
+		if(unlikely(!skb)) {
 			/* Better luck next round */
 			break;
 		}
@@ -2400,15 +2404,15 @@
 
 		buffer_info->skb = skb;
 		buffer_info->length = adapter->rx_buffer_len;
-		buffer_info->dma =
-			pci_map_single(pdev,
-			               skb->data,
-			               adapter->rx_buffer_len,
-			               PCI_DMA_FROMDEVICE);
+		buffer_info->dma = pci_map_single(pdev,
+						  skb->data,
+						  adapter->rx_buffer_len,
+						  PCI_DMA_FROMDEVICE);
 
+		rx_desc = E1000_RX_DESC(*rx_ring, i);
 		rx_desc->buffer_addr = cpu_to_le64(buffer_info->dma);
 
-		if((i & ~(E1000_RX_BUFFER_WRITE - 1)) == i) {
+		if(unlikely((i & ~(E1000_RX_BUFFER_WRITE - 1)) == i)) {
 			/* Force memory writes to complete before letting h/w
 			 * know there are new descriptors to fetch.  (Only
 			 * applicable for weak-ordered memory model archs,
@@ -2418,7 +2422,7 @@
 			E1000_WRITE_REG(&adapter->hw, RDT, i);
 		}
 
-		if(++i == rx_ring->count) i = 0;
+		if(unlikely(++i == rx_ring->count)) i = 0;
 		buffer_info = &rx_ring->buffer_info[i];
 	}
 
@@ -2537,22 +2541,24 @@
 			return -EFAULT;
 		mii_reg = data->val_in;
 		if (e1000_write_phy_reg(&adapter->hw, data->reg_num,
-					data->val_in))
+					mii_reg))
 			return -EIO;
 		if (adapter->hw.phy_type == e1000_phy_m88) {
 			switch (data->reg_num) {
 			case PHY_CTRL:
-				if(data->val_in & MII_CR_AUTO_NEG_EN) {
+				if(mii_reg & MII_CR_POWER_DOWN)
+					break;
+				if(mii_reg & MII_CR_AUTO_NEG_EN) {
 					adapter->hw.autoneg = 1;
 					adapter->hw.autoneg_advertised = 0x2F;
 				} else {
-					if (data->val_in & 0x40)
+					if (mii_reg & 0x40)
 						spddplx = SPEED_1000;
-					else if (data->val_in & 0x2000)
+					else if (mii_reg & 0x2000)
 						spddplx = SPEED_100;
 					else
 						spddplx = SPEED_10;
-					spddplx += (data->val_in & 0x100)
+					spddplx += (mii_reg & 0x100)
 						   ? FULL_DUPLEX :
 						   HALF_DUPLEX;
 					retval = e1000_set_spd_dplx(adapter,
@@ -2572,6 +2578,18 @@
 					return -EIO;
 				break;
 			}
+		} else {
+			switch (data->reg_num) {
+			case PHY_CTRL:
+				if(mii_reg & MII_CR_POWER_DOWN)
+					break;
+				if(netif_running(adapter->netdev)) {
+					e1000_down(adapter);
+					e1000_up(adapter);
+				} else
+					e1000_reset(adapter);
+				break;
+			}
 		}
 		break;
 	default:
@@ -2587,17 +2605,17 @@
  * @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)
 {
 	/* 82543 or newer only */
-	if((adapter->hw.mac_type < e1000_82543) ||
+	if(unlikely((adapter->hw.mac_type < e1000_82543) ||
 	/* Ignore Checksum bit is set */
 	(rx_desc->status & E1000_RXD_STAT_IXSM) ||
 	/* TCP Checksum has not been calculated */
-	(!(rx_desc->status & E1000_RXD_STAT_TCPCS))) {
+	(!(rx_desc->status & E1000_RXD_STAT_TCPCS)))) {
 		skb->ip_summed = CHECKSUM_NONE;
 		return;
 	}
@@ -2609,7 +2627,7 @@
 		skb->ip_summed = CHECKSUM_NONE;
 		adapter->hw_csum_err++;
 	} else {
-	/* TCP checksum is good */
+		/* TCP checksum is good */
 		skb->ip_summed = CHECKSUM_UNNECESSARY;
 		adapter->hw_csum_good++;
 	}
@@ -2620,7 +2638,8 @@
 {
 	struct e1000_adapter *adapter = hw->back;
 
-	pci_set_mwi(adapter->pdev);
+	int ret;
+	ret = pci_set_mwi(adapter->pdev);
 }
 
 void
@@ -2670,26 +2689,22 @@
 
 	if(grp) {
 		/* enable VLAN tag insert/strip */
-
 		ctrl = E1000_READ_REG(&adapter->hw, CTRL);
 		ctrl |= E1000_CTRL_VME;
 		E1000_WRITE_REG(&adapter->hw, CTRL, ctrl);
 
 		/* enable VLAN receive filtering */
-
 		rctl = E1000_READ_REG(&adapter->hw, RCTL);
 		rctl |= E1000_RCTL_VFE;
 		rctl &= ~E1000_RCTL_CFIEN;
 		E1000_WRITE_REG(&adapter->hw, RCTL, rctl);
 	} else {
 		/* disable VLAN tag insert/strip */
-
 		ctrl = E1000_READ_REG(&adapter->hw, CTRL);
 		ctrl &= ~E1000_CTRL_VME;
 		E1000_WRITE_REG(&adapter->hw, CTRL, ctrl);
 
 		/* disable VLAN filtering */
-
 		rctl = E1000_READ_REG(&adapter->hw, RCTL);
 		rctl &= ~E1000_RCTL_VFE;
 		E1000_WRITE_REG(&adapter->hw, RCTL, rctl);
@@ -2705,7 +2720,6 @@
 	uint32_t vfta, index;
 
 	/* add VID to filter table */
-
 	index = (vid >> 5) & 0x7F;
 	vfta = E1000_READ_REG_ARRAY(&adapter->hw, VFTA, index);
 	vfta |= (1 << (vid & 0x1F));
@@ -2725,8 +2739,7 @@
 
 	e1000_irq_enable(adapter);
 
-	/* remove VID from filter table*/
-
+	/* remove VID from filter table */
 	index = (vid >> 5) & 0x7F;
 	vfta = E1000_READ_REG_ARRAY(&adapter->hw, VFTA, index);
 	vfta &= ~(1 << (vid & 0x1F));
@@ -2772,6 +2785,8 @@
 		break;
 	case SPEED_1000 + DUPLEX_HALF: /* not supported */
 	default:
+		DPRINTK(PROBE, ERR, 
+			"Unsupported Speed/Duplexity configuration\n");
 		return -EINVAL;
 	}
 	return 0;
@@ -2865,6 +2880,8 @@
 		}
 	}
 
+	pci_disable_device(pdev);
+
 	state = (state > 0) ? 3 : 0;
 	pci_set_power_state(pdev, state);
 
@@ -2879,6 +2896,7 @@
 	struct e1000_adapter *adapter = netdev->priv;
 	uint32_t manc;
 
+	pci_enable_device(pdev);
 	pci_set_power_state(pdev, 0);
 	pci_restore_state(pdev, adapter->pci_state);
 
@@ -2910,12 +2928,12 @@
  * without having to re-enable interrupts. It's not called while
  * the interrupt routine is executing.
  */
-
-static void e1000_netpoll (struct net_device *dev)
+static void
+e1000_netpoll (struct net_device *netdev)
 {
-	struct e1000_adapter *adapter = dev->priv;
+	struct e1000_adapter *adapter = netdev->priv;
 	disable_irq(adapter->pdev->irq);
-	e1000_intr (adapter->pdev->irq, dev, NULL);
+	e1000_intr(adapter->pdev->irq, netdev, NULL);
 	enable_irq(adapter->pdev->irq);
 }
 #endif
diff -Nru a/drivers/net/e1000/e1000_param.c b/drivers/net/e1000/e1000_param.c
--- a/drivers/net/e1000/e1000_param.c	2004-10-18 14:56:48 -07:00
+++ b/drivers/net/e1000/e1000_param.c	2004-10-18 14:56:48 -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
 
@@ -235,7 +235,7 @@
 
 static int __devinit
 e1000_validate_option(int *value, struct e1000_option *opt,
-	struct e1000_adapter *adapter)
+		struct e1000_adapter *adapter)
 {
 	if(*value == OPTION_UNSET) {
 		*value = opt->def;
@@ -256,7 +256,7 @@
 	case range_option:
 		if(*value >= opt->arg.r.min && *value <= opt->arg.r.max) {
 			DPRINTK(PROBE, INFO,
-				"%s set to %i\n", opt->name, *value);
+					"%s set to %i\n", opt->name, *value);
 			return 0;
 		}
 		break;
@@ -449,8 +449,7 @@
 			DPRINTK(PROBE, INFO, "%s turned off\n", opt.name);
 			break;
 		case 1:
-			DPRINTK(PROBE, INFO,
-				"%s set to dynamic mode\n", opt.name);
+			DPRINTK(PROBE, INFO, "%s set to dynamic mode\n", opt.name);
 			break;
 		default:
 			e1000_validate_option(&adapter->itr, &opt, adapter);
@@ -493,8 +492,9 @@
 		       "parameter ignored\n");
 	}
 	if((AutoNeg[bd] != OPTION_UNSET) && (AutoNeg[bd] != 0x20)) {
-		DPRINTK(PROBE, INFO, "AutoNeg other than Full/1000 is "
-		       "not valid for fiber adapters, parameter ignored\n");
+		DPRINTK(PROBE, INFO, "AutoNeg other than 1000/Full is "
+				 "not valid for fiber adapters, "
+				 "parameter ignored\n");
 	}
 }
 
@@ -611,24 +611,24 @@
 		break;
 	case HALF_DUPLEX:
 		DPRINTK(PROBE, INFO, "Half Duplex specified without Speed\n");
-		DPRINTK(PROBE, INFO,
-			"Using Autonegotiation at Half Duplex only\n");
+		DPRINTK(PROBE, INFO, "Using Autonegotiation at "
+			"Half Duplex only\n");
 		adapter->hw.autoneg = adapter->fc_autoneg = 1;
 		adapter->hw.autoneg_advertised = ADVERTISE_10_HALF |
 		                                 ADVERTISE_100_HALF;
 		break;
 	case FULL_DUPLEX:
 		DPRINTK(PROBE, INFO, "Full Duplex specified without Speed\n");
-		DPRINTK(PROBE, INFO,
-			"Using Autonegotiation at Full Duplex only\n");
+		DPRINTK(PROBE, INFO, "Using Autonegotiation at "
+			"Full Duplex only\n");
 		adapter->hw.autoneg = adapter->fc_autoneg = 1;
 		adapter->hw.autoneg_advertised = ADVERTISE_10_FULL |
 		                                 ADVERTISE_100_FULL |
 		                                 ADVERTISE_1000_FULL;
 		break;
 	case SPEED_10:
-		DPRINTK(PROBE, INFO,
-			"10 Mbps Speed specified without Duplex\n");
+		DPRINTK(PROBE, INFO, "10 Mbps Speed specified "
+			"without Duplex\n");
 		DPRINTK(PROBE, INFO, "Using Autonegotiation at 10 Mbps only\n");
 		adapter->hw.autoneg = adapter->fc_autoneg = 1;
 		adapter->hw.autoneg_advertised = ADVERTISE_10_HALF |
@@ -647,10 +647,10 @@
 		adapter->hw.autoneg_advertised = 0;
 		break;
 	case SPEED_100:
-		DPRINTK(PROBE, INFO,
-			"100 Mbps Speed specified without Duplex\n");
-		DPRINTK(PROBE, INFO,
-			"Using Autonegotiation at 100 Mbps only\n");
+		DPRINTK(PROBE, INFO, "100 Mbps Speed specified "
+			"without Duplex\n");
+		DPRINTK(PROBE, INFO, "Using Autonegotiation at "
+			"100 Mbps only\n");
 		adapter->hw.autoneg = adapter->fc_autoneg = 1;
 		adapter->hw.autoneg_advertised = ADVERTISE_100_HALF |
 		                                 ADVERTISE_100_FULL;
@@ -668,10 +668,11 @@
 		adapter->hw.autoneg_advertised = 0;
 		break;
 	case SPEED_1000:
+		DPRINTK(PROBE, INFO, "1000 Mbps Speed specified without "
+			"Duplex\n");
 		DPRINTK(PROBE, INFO,
-			"1000 Mbps Speed specified without Duplex\n");
-		DPRINTK(PROBE, INFO,
-		       "Using Autonegotiation at 1000 Mbps Full Duplex only\n");
+			"Using Autonegotiation at 1000 Mbps "
+			"Full Duplex only\n");
 		adapter->hw.autoneg = adapter->fc_autoneg = 1;
 		adapter->hw.autoneg_advertised = ADVERTISE_1000_FULL;
 		break;
@@ -679,7 +680,8 @@
 		DPRINTK(PROBE, INFO,
 			"Half Duplex is not supported at 1000 Mbps\n");
 		DPRINTK(PROBE, INFO,
-		       "Using Autonegotiation at 1000 Mbps Full Duplex only\n");
+			"Using Autonegotiation at 1000 Mbps "
+			"Full Duplex only\n");
 		adapter->hw.autoneg = adapter->fc_autoneg = 1;
 		adapter->hw.autoneg_advertised = ADVERTISE_1000_FULL;
 		break;
@@ -696,8 +698,8 @@
 	/* Speed, AutoNeg and MDI/MDI-X must all play nice */
 	if (e1000_validate_mdi_setting(&(adapter->hw)) < 0) {
 		DPRINTK(PROBE, INFO,
-		       "Speed, AutoNeg and MDI-X specifications are "
-		       "incompatible. Setting MDI-X to a compatible value.\n");
+			"Speed, AutoNeg and MDI-X specifications are "
+			"incompatible. Setting MDI-X to a compatible value.\n");
 	}
 }
 
diff -Nru a/drivers/net/eepro100.c b/drivers/net/eepro100.c
--- a/drivers/net/eepro100.c	2004-10-18 14:56:33 -07:00
+++ b/drivers/net/eepro100.c	2004-10-18 14:56:33 -07:00
@@ -88,7 +88,6 @@
 #define PKT_BUF_SZ		1536
 
 #include <linux/config.h>
-#include <linux/version.h>
 #include <linux/module.h>
 
 #include <linux/kernel.h>
@@ -2446,22 +2445,6 @@
 	.resume		= eepro100_resume,
 #endif /* CONFIG_PM */
 };
-
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,48)
-static int pci_module_init(struct pci_driver *pdev)
-{
-	int rc;
-
-	rc = pci_register_driver(pdev);
-	if (rc <= 0) {
-		printk(KERN_INFO "%s: No cards found, driver not installed.\n",
-			   pdev->name);
-		pci_unregister_driver(pdev);
-		return -ENODEV;
-	}
-	return 0;
-}
-#endif
 
 static int __init eepro100_init_module(void)
 {
diff -Nru a/drivers/net/epic100.c b/drivers/net/epic100.c
--- a/drivers/net/epic100.c	2004-10-18 14:56:29 -07:00
+++ b/drivers/net/epic100.c	2004-10-18 14:56:29 -07:00
@@ -80,8 +80,6 @@
    These may be modified when a driver module is loaded.*/
 
 static int debug = 1;			/* 1 normal messages, 0 quiet .. 7 verbose. */
-/* Maximum events (Rx packets, etc.) to handle at each interrupt. */
-static int max_interrupt_work = 32;
 
 /* Used to pass the full-duplex flag, etc. */
 #define MAX_UNITS 8		/* More are supported, limit only on options */
@@ -99,9 +97,9 @@
    Making the Tx ring too large decreases the effectiveness of channel
    bonding and packet priority.
    There are no ill effects from too-large receive rings. */
-#define TX_RING_SIZE	16
-#define TX_QUEUE_LEN	10		/* Limit ring entries actually used.  */
-#define RX_RING_SIZE	32
+#define TX_RING_SIZE	256
+#define TX_QUEUE_LEN	240		/* Limit ring entries actually used.  */
+#define RX_RING_SIZE	256
 #define TX_TOTAL_SIZE	TX_RING_SIZE*sizeof(struct epic_tx_desc)
 #define RX_TOTAL_SIZE	RX_RING_SIZE*sizeof(struct epic_rx_desc)
 
@@ -152,12 +150,10 @@
 MODULE_LICENSE("GPL");
 
 MODULE_PARM(debug, "i");
-MODULE_PARM(max_interrupt_work, "i");
 MODULE_PARM(rx_copybreak, "i");
 MODULE_PARM(options, "1-" __MODULE_STRING(MAX_UNITS) "i");
 MODULE_PARM(full_duplex, "1-" __MODULE_STRING(MAX_UNITS) "i");
 MODULE_PARM_DESC(debug, "EPIC/100 debug level (0-5)");
-MODULE_PARM_DESC(max_interrupt_work, "EPIC/100 maximum events handled per interrupt");
 MODULE_PARM_DESC(options, "EPIC/100: Bits 0-3: media type, bit 4: full duplex");
 MODULE_PARM_DESC(rx_copybreak, "EPIC/100 copy breakpoint for copy-only-tiny-frames");
 MODULE_PARM_DESC(full_duplex, "EPIC/100 full duplex setting(s) (1)");
@@ -289,6 +285,12 @@
 	StopTxDMA=0x20, StopRxDMA=0x40, RestartTx=0x80,
 };
 
+#define EpicRemoved	0xffffffff	/* Chip failed or removed (CardBus) */
+
+#define EpicNapiEvent	(TxEmpty | TxDone | \
+			 RxDone | RxStarted | RxEarlyWarn | RxOverflow | RxFull)
+#define EpicNormalEvent	(0x0000ffff & ~EpicNapiEvent)
+
 static u16 media2miictl[16] = {
 	0, 0x0C00, 0x0C00, 0x2000,  0x0100, 0x2100, 0, 0,
 	0, 0, 0, 0,  0, 0, 0, 0 };
@@ -327,9 +329,12 @@
 
 	/* Ring pointers. */
 	spinlock_t lock;				/* Group with Tx control cache line. */
+	spinlock_t napi_lock;
+	unsigned int reschedule_in_poll;
 	unsigned int cur_tx, dirty_tx;
 
 	unsigned int cur_rx, dirty_rx;
+	u32 irq_mask;
 	unsigned int rx_buf_sz;				/* Based on MTU+slack. */
 
 	struct pci_dev *pci_dev;			/* PCI bus location. */
@@ -356,7 +361,8 @@
 static void epic_tx_timeout(struct net_device *dev);
 static void epic_init_ring(struct net_device *dev);
 static int epic_start_xmit(struct sk_buff *skb, struct net_device *dev);
-static int epic_rx(struct net_device *dev);
+static int epic_rx(struct net_device *dev, int budget);
+static int epic_poll(struct net_device *dev, int *budget);
 static irqreturn_t epic_interrupt(int irq, void *dev_instance, struct pt_regs *regs);
 static int netdev_ioctl(struct net_device *dev, struct ifreq *rq, int cmd);
 static struct ethtool_ops netdev_ethtool_ops;
@@ -375,7 +381,7 @@
 	int irq;
 	struct net_device *dev;
 	struct epic_private *ep;
-	int i, option = 0, duplex = 0;
+	int i, ret, option = 0, duplex = 0;
 	void *ring_space;
 	dma_addr_t ring_dma;
 
@@ -389,29 +395,33 @@
 	
 	card_idx++;
 	
-	i = pci_enable_device(pdev);
-	if (i)
-		return i;
+	ret = pci_enable_device(pdev);
+	if (ret)
+		goto out;
 	irq = pdev->irq;
 
 	if (pci_resource_len(pdev, 0) < pci_id_tbl[chip_idx].io_size) {
 		printk (KERN_ERR "card %d: no PCI region space\n", card_idx);
-		return -ENODEV;
+		ret = -ENODEV;
+		goto err_out_disable;
 	}
 	
 	pci_set_master(pdev);
 
+	ret = pci_request_regions(pdev, DRV_NAME);
+	if (ret < 0)
+		goto err_out_disable;
+
+	ret = -ENOMEM;
+
 	dev = alloc_etherdev(sizeof (*ep));
 	if (!dev) {
 		printk (KERN_ERR "card %d: no memory for eth device\n", card_idx);
-		return -ENOMEM;
+		goto err_out_free_res;
 	}
 	SET_MODULE_OWNER(dev);
 	SET_NETDEV_DEV(dev, &pdev->dev);
 
-	if (pci_request_regions(pdev, DRV_NAME))
-		goto err_out_free_netdev;
-
 #ifdef USE_IO_OPS
 	ioaddr = pci_resource_start (pdev, 0);
 #else
@@ -419,7 +429,7 @@
 	ioaddr = (long) ioremap (ioaddr, pci_resource_len (pdev, 1));
 	if (!ioaddr) {
 		printk (KERN_ERR DRV_NAME " %d: ioremap failed\n", card_idx);
-		goto err_out_free_res;
+		goto err_out_free_netdev;
 	}
 #endif
 
@@ -456,7 +466,9 @@
 	dev->base_addr = ioaddr;
 	dev->irq = irq;
 
-	spin_lock_init (&ep->lock);
+	spin_lock_init(&ep->lock);
+	spin_lock_init(&ep->napi_lock);
+	ep->reschedule_in_poll = 0;
 
 	/* Bring the chip out of low-power mode. */
 	outl(0x4200, ioaddr + GENCTL);
@@ -486,6 +498,9 @@
 	ep->pci_dev = pdev;
 	ep->chip_id = chip_idx;
 	ep->chip_flags = pci_id_tbl[chip_idx].drv_flags;
+	ep->irq_mask = 
+		(ep->chip_flags & TYPE2_INTR ?  PCIBusErr175 : PCIBusErr170)
+		 | CntFull | TxUnderrun | EpicNapiEvent;
 
 	/* Find the connected MII xcvrs.
 	   Doing this in open() would allow detecting external xcvrs later, but
@@ -540,10 +555,12 @@
 	dev->ethtool_ops = &netdev_ethtool_ops;
 	dev->watchdog_timeo = TX_TIMEOUT;
 	dev->tx_timeout = &epic_tx_timeout;
+	dev->poll = epic_poll;
+	dev->weight = 64;
 
-	i = register_netdev(dev);
-	if (i)
-		goto err_out_unmap_tx;
+	ret = register_netdev(dev);
+	if (ret < 0)
+		goto err_out_unmap_rx;
 
 	printk(KERN_INFO "%s: %s at %#lx, IRQ %d, ",
 		   dev->name, pci_id_tbl[chip_idx].name, ioaddr, dev->irq);
@@ -551,19 +568,24 @@
 		printk("%2.2x:", dev->dev_addr[i]);
 	printk("%2.2x.\n", dev->dev_addr[i]);
 
-	return 0;
+out:
+	return ret;
 
+err_out_unmap_rx:
+	pci_free_consistent(pdev, RX_TOTAL_SIZE, ep->rx_ring, ep->rx_ring_dma);
 err_out_unmap_tx:
 	pci_free_consistent(pdev, TX_TOTAL_SIZE, ep->tx_ring, ep->tx_ring_dma);
 err_out_iounmap:
 #ifndef USE_IO_OPS
 	iounmap(ioaddr);
-err_out_free_res:
-#endif
-	pci_release_regions(pdev);
 err_out_free_netdev:
+#endif
 	free_netdev(dev);
-	return -ENODEV;
+err_out_free_res:
+	pci_release_regions(pdev);
+err_out_disable:
+	pci_disable_device(pdev);
+	goto out;
 }
 
 /* Serial EEPROM section. */
@@ -589,6 +611,38 @@
 #define EE_READ256_CMD	(6 << 8)
 #define EE_ERASE_CMD	(7 << 6)
 
+static void epic_disable_int(struct net_device *dev, struct epic_private *ep)
+{
+	long ioaddr = dev->base_addr;
+
+	outl(0x00000000, ioaddr + INTMASK);
+}
+
+static inline void __epic_pci_commit(long ioaddr)
+{
+#ifndef USE_IO_OPS
+	inl(ioaddr + INTMASK);
+#endif
+}
+
+static inline void epic_napi_irq_off(struct net_device *dev,
+				     struct epic_private *ep)
+{
+	long ioaddr = dev->base_addr;
+
+	outl(ep->irq_mask & ~EpicNapiEvent, ioaddr + INTMASK);
+	__epic_pci_commit(ioaddr);
+}
+
+static inline void epic_napi_irq_on(struct net_device *dev,
+				    struct epic_private *ep)
+{
+	long ioaddr = dev->base_addr;
+
+	/* No need to commit possible posted write */
+	outl(ep->irq_mask | EpicNapiEvent, ioaddr + INTMASK);
+}
+
 static int __devinit read_eeprom(long ioaddr, int location)
 {
 	int i;
@@ -749,9 +803,8 @@
 
 	/* Enable interrupts by setting the interrupt mask. */
 	outl((ep->chip_flags & TYPE2_INTR ? PCIBusErr175 : PCIBusErr170)
-		 | CntFull | TxUnderrun | TxDone | TxEmpty
-		 | RxError | RxOverflow | RxFull | RxHeader | RxDone,
-		 ioaddr + INTMASK);
+		 | CntFull | TxUnderrun 
+		 | RxError | RxHeader | EpicNapiEvent, ioaddr + INTMASK);
 
 	if (debug > 1)
 		printk(KERN_DEBUG "%s: epic_open() ioaddr %lx IRQ %d status %4.4x "
@@ -792,7 +845,7 @@
 	}
 
 	/* Remove the packets on the Rx queue. */
-	epic_rx(dev);
+	epic_rx(dev, RX_RING_SIZE);
 }
 
 static void epic_restart(struct net_device *dev)
@@ -838,9 +891,9 @@
 
 	/* Enable interrupts by setting the interrupt mask. */
 	outl((ep->chip_flags & TYPE2_INTR ? PCIBusErr175 : PCIBusErr170)
-		 | CntFull | TxUnderrun | TxDone | TxEmpty
-		 | RxError | RxOverflow | RxFull | RxHeader | RxDone,
-		 ioaddr + INTMASK);
+		 | CntFull | TxUnderrun
+		 | RxError | RxHeader | EpicNapiEvent, ioaddr + INTMASK);
+
 	printk(KERN_DEBUG "%s: epic_restart() done, cmd status %4.4x, ctl %4.4x"
 		   " interrupt %4.4x.\n",
 		   dev->name, (int)inl(ioaddr + COMMAND), (int)inl(ioaddr + GENCTL),
@@ -926,7 +979,6 @@
 	int i;
 
 	ep->tx_full = 0;
-	ep->lock = (spinlock_t) SPIN_LOCK_UNLOCKED;
 	ep->dirty_tx = ep->cur_tx = 0;
 	ep->cur_rx = ep->dirty_rx = 0;
 	ep->rx_buf_sz = (dev->mtu <= 1500 ? PKT_BUF_SZ : dev->mtu + 32);
@@ -1026,6 +1078,76 @@
 	return 0;
 }
 
+static void epic_tx_error(struct net_device *dev, struct epic_private *ep,
+			  int status)
+{
+	struct net_device_stats *stats = &ep->stats;
+
+#ifndef final_version
+	/* There was an major error, log it. */
+	if (debug > 1)
+		printk(KERN_DEBUG "%s: Transmit error, Tx status %8.8x.\n",
+		       dev->name, status);
+#endif
+	stats->tx_errors++;
+	if (status & 0x1050)
+		stats->tx_aborted_errors++;
+	if (status & 0x0008)
+		stats->tx_carrier_errors++;
+	if (status & 0x0040)
+		stats->tx_window_errors++;
+	if (status & 0x0010)
+		stats->tx_fifo_errors++;
+}
+
+static void epic_tx(struct net_device *dev, struct epic_private *ep)
+{
+	unsigned int dirty_tx, cur_tx;
+
+	/*
+	 * Note: if this lock becomes a problem we can narrow the locked
+	 * region at the cost of occasionally grabbing the lock more times.
+	 */
+	cur_tx = ep->cur_tx;
+	for (dirty_tx = ep->dirty_tx; cur_tx - dirty_tx > 0; dirty_tx++) {
+		struct sk_buff *skb;
+		int entry = dirty_tx % TX_RING_SIZE;
+		int txstatus = le32_to_cpu(ep->tx_ring[entry].txstatus);
+
+		if (txstatus & DescOwn)
+			break;	/* It still hasn't been Txed */
+
+		if (likely(txstatus & 0x0001)) {
+			ep->stats.collisions += (txstatus >> 8) & 15;
+			ep->stats.tx_packets++;
+			ep->stats.tx_bytes += ep->tx_skbuff[entry]->len;
+		} else
+			epic_tx_error(dev, ep, txstatus);
+
+		/* Free the original skb. */
+		skb = ep->tx_skbuff[entry];
+		pci_unmap_single(ep->pci_dev, ep->tx_ring[entry].bufaddr, 
+				 skb->len, PCI_DMA_TODEVICE);
+		dev_kfree_skb_irq(skb);
+		ep->tx_skbuff[entry] = NULL;
+	}
+
+#ifndef final_version
+	if (cur_tx - dirty_tx > TX_RING_SIZE) {
+		printk(KERN_WARNING
+		       "%s: Out-of-sync dirty pointer, %d vs. %d, full=%d.\n",
+		       dev->name, dirty_tx, cur_tx, ep->tx_full);
+		dirty_tx += TX_RING_SIZE;
+	}
+#endif
+	ep->dirty_tx = dirty_tx;
+	if (ep->tx_full && cur_tx - dirty_tx < TX_QUEUE_LEN - 4) {
+		/* The ring is no longer full, allow new TX entries. */
+		ep->tx_full = 0;
+		netif_wake_queue(dev);
+	}
+}
+
 /* The interrupt handler does all of the Rx thread work and cleans up
    after the Tx thread. */
 static irqreturn_t epic_interrupt(int irq, void *dev_instance, struct pt_regs *regs)
@@ -1033,135 +1155,71 @@
 	struct net_device *dev = dev_instance;
 	struct epic_private *ep = dev->priv;
 	long ioaddr = dev->base_addr;
-	int status, boguscnt = max_interrupt_work;
 	unsigned int handled = 0;
+	int status;
 
-	do {
-		status = inl(ioaddr + INTSTAT);
-		/* Acknowledge all of the current interrupt sources ASAP. */
-		outl(status & 0x00007fff, ioaddr + INTSTAT);
-
-		if (debug > 4)
-			printk(KERN_DEBUG "%s: Interrupt, status=%#8.8x new "
-				   "intstat=%#8.8x.\n",
-				   dev->name, status, (int)inl(ioaddr + INTSTAT));
-
-		if ((status & IntrSummary) == 0)
-			break;
-		handled = 1;
+	status = inl(ioaddr + INTSTAT);
+	/* Acknowledge all of the current interrupt sources ASAP. */
+	outl(status & EpicNormalEvent, ioaddr + INTSTAT);
 
-		if (status & (RxDone | RxStarted | RxEarlyWarn | RxOverflow))
-			epic_rx(dev);
+	if (debug > 4) {
+		printk(KERN_DEBUG "%s: Interrupt, status=%#8.8x new "
+				   "intstat=%#8.8x.\n", dev->name, status,
+				   (int)inl(ioaddr + INTSTAT));
+	}
 
-		if (status & (TxEmpty | TxDone)) {
-			unsigned int dirty_tx, cur_tx;
+	if ((status & IntrSummary) == 0)
+		goto out;
 
-			/* Note: if this lock becomes a problem we can narrow the locked
-			   region at the cost of occasionally grabbing the lock more
-			   times. */
-			spin_lock(&ep->lock);
-			cur_tx = ep->cur_tx;
-			dirty_tx = ep->dirty_tx;
-			for (; cur_tx - dirty_tx > 0; dirty_tx++) {
-				struct sk_buff *skb;
-				int entry = dirty_tx % TX_RING_SIZE;
-				int txstatus = le32_to_cpu(ep->tx_ring[entry].txstatus);
+	handled = 1;
 
-				if (txstatus & DescOwn)
-					break;			/* It still hasn't been Txed */
+	if ((status & EpicNapiEvent) && !ep->reschedule_in_poll) {
+		spin_lock(&ep->napi_lock);
+		if (netif_rx_schedule_prep(dev)) {
+			epic_napi_irq_off(dev, ep);
+			__netif_rx_schedule(dev);
+		} else
+			ep->reschedule_in_poll++;
+		spin_unlock(&ep->napi_lock);
+	}
+	status &= ~EpicNapiEvent;
 
-				if ( ! (txstatus & 0x0001)) {
-					/* There was an major error, log it. */
-#ifndef final_version
-					if (debug > 1)
-						printk(KERN_DEBUG "%s: Transmit error, Tx status %8.8x.\n",
-							   dev->name, txstatus);
-#endif
-					ep->stats.tx_errors++;
-					if (txstatus & 0x1050) ep->stats.tx_aborted_errors++;
-					if (txstatus & 0x0008) ep->stats.tx_carrier_errors++;
-					if (txstatus & 0x0040) ep->stats.tx_window_errors++;
-					if (txstatus & 0x0010) ep->stats.tx_fifo_errors++;
-				} else {
-					ep->stats.collisions += (txstatus >> 8) & 15;
-					ep->stats.tx_packets++;
-					ep->stats.tx_bytes += ep->tx_skbuff[entry]->len;
-				}
-
-				/* Free the original skb. */
-				skb = ep->tx_skbuff[entry];
-				pci_unmap_single(ep->pci_dev, ep->tx_ring[entry].bufaddr, 
-						 skb->len, PCI_DMA_TODEVICE);
-				dev_kfree_skb_irq(skb);
-				ep->tx_skbuff[entry] = NULL;
-			}
+	/* Check uncommon events all at once. */
+	if (status & (CntFull | TxUnderrun | PCIBusErr170 | PCIBusErr175)) {
+		if (status == EpicRemoved)
+			goto out;
 
-#ifndef final_version
-			if (cur_tx - dirty_tx > TX_RING_SIZE) {
-				printk(KERN_WARNING "%s: Out-of-sync dirty pointer, %d vs. %d, full=%d.\n",
-					   dev->name, dirty_tx, cur_tx, ep->tx_full);
-				dirty_tx += TX_RING_SIZE;
-			}
-#endif
-			ep->dirty_tx = dirty_tx;
-			if (ep->tx_full
-				&& cur_tx - dirty_tx < TX_QUEUE_LEN - 4) {
-				/* The ring is no longer full, allow new TX entries. */
-				ep->tx_full = 0;
-				spin_unlock(&ep->lock);
-				netif_wake_queue(dev);
-			} else
-				spin_unlock(&ep->lock);
-		}
+		/* Always update the error counts to avoid overhead later. */
+		ep->stats.rx_missed_errors += inb(ioaddr + MPCNT);
+		ep->stats.rx_frame_errors += inb(ioaddr + ALICNT);
+		ep->stats.rx_crc_errors += inb(ioaddr + CRCCNT);
 
-		/* Check uncommon events all at once. */
-		if (status & (CntFull | TxUnderrun | RxOverflow | RxFull |
-					  PCIBusErr170 | PCIBusErr175)) {
-			if (status == 0xffffffff) /* Chip failed or removed (CardBus). */
-				break;
-			/* Always update the error counts to avoid overhead later. */
-			ep->stats.rx_missed_errors += inb(ioaddr + MPCNT);
-			ep->stats.rx_frame_errors += inb(ioaddr + ALICNT);
-			ep->stats.rx_crc_errors += inb(ioaddr + CRCCNT);
-
-			if (status & TxUnderrun) { /* Tx FIFO underflow. */
-				ep->stats.tx_fifo_errors++;
-				outl(ep->tx_threshold += 128, ioaddr + TxThresh);
-				/* Restart the transmit process. */
-				outl(RestartTx, ioaddr + COMMAND);
-			}
-			if (status & RxOverflow) {		/* Missed a Rx frame. */
-				ep->stats.rx_errors++;
-			}
-			if (status & (RxOverflow | RxFull))
-				outw(RxQueued, ioaddr + COMMAND);
-			if (status & PCIBusErr170) {
-				printk(KERN_ERR "%s: PCI Bus Error!  EPIC status %4.4x.\n",
-					   dev->name, status);
-				epic_pause(dev);
-				epic_restart(dev);
-			}
-			/* Clear all error sources. */
-			outl(status & 0x7f18, ioaddr + INTSTAT);
+		if (status & TxUnderrun) { /* Tx FIFO underflow. */
+			ep->stats.tx_fifo_errors++;
+			outl(ep->tx_threshold += 128, ioaddr + TxThresh);
+			/* Restart the transmit process. */
+			outl(RestartTx, ioaddr + COMMAND);
 		}
-		if (--boguscnt < 0) {
-			printk(KERN_ERR "%s: Too much work at interrupt, "
-				   "IntrStatus=0x%8.8x.\n",
-				   dev->name, status);
-			/* Clear all interrupt sources. */
-			outl(0x0001ffff, ioaddr + INTSTAT);
-			break;
+		if (status & PCIBusErr170) {
+			printk(KERN_ERR "%s: PCI Bus Error! status %4.4x.\n",
+					 dev->name, status);
+			epic_pause(dev);
+			epic_restart(dev);
 		}
-	} while (1);
+		/* Clear all error sources. */
+		outl(status & 0x7f18, ioaddr + INTSTAT);
+	}
 
-	if (debug > 3)
-		printk(KERN_DEBUG "%s: exiting interrupt, intr_status=%#4.4x.\n",
-			   dev->name, status);
+out:
+	if (debug > 3) {
+		printk(KERN_DEBUG "%s: exit interrupt, intr_status=%#4.4x.\n",
+				   dev->name, status);
+	}
 
 	return IRQ_RETVAL(handled);
 }
 
-static int epic_rx(struct net_device *dev)
+static int epic_rx(struct net_device *dev, int budget)
 {
 	struct epic_private *ep = dev->priv;
 	int entry = ep->cur_rx % RX_RING_SIZE;
@@ -1171,6 +1229,10 @@
 	if (debug > 4)
 		printk(KERN_DEBUG " In epic_rx(), entry %d %8.8x.\n", entry,
 			   ep->rx_ring[entry].rxstatus);
+
+	if (rx_work_limit > budget)
+		rx_work_limit = budget;
+
 	/* If we own the next entry, it's a new packet. Send it up. */
 	while ((ep->rx_ring[entry].rxstatus & cpu_to_le32(DescOwn)) == 0) {
 		int status = le32_to_cpu(ep->rx_ring[entry].rxstatus);
@@ -1226,7 +1288,7 @@
 				ep->rx_skbuff[entry] = NULL;
 			}
 			skb->protocol = eth_type_trans(skb, dev);
-			netif_rx(skb);
+			netif_receive_skb(skb);
 			dev->last_rx = jiffies;
 			ep->stats.rx_packets++;
 			ep->stats.rx_bytes += pkt_len;
@@ -1254,6 +1316,65 @@
 	return work_done;
 }
 
+static void epic_rx_err(struct net_device *dev, struct epic_private *ep)
+{
+	long ioaddr = dev->base_addr;
+	int status;
+
+	status = inl(ioaddr + INTSTAT);
+
+	if (status == EpicRemoved)
+		return;
+	if (status & RxOverflow) 	/* Missed a Rx frame. */
+		ep->stats.rx_errors++;
+	if (status & (RxOverflow | RxFull))
+		outw(RxQueued, ioaddr + COMMAND);
+}
+
+static int epic_poll(struct net_device *dev, int *budget)
+{
+	struct epic_private *ep = dev->priv;
+	int work_done, orig_budget;
+	long ioaddr = dev->base_addr;
+
+	orig_budget = (*budget > dev->quota) ? dev->quota : *budget;
+
+rx_action:
+
+	epic_tx(dev, ep);
+
+	work_done = epic_rx(dev, *budget);
+
+	epic_rx_err(dev, ep);
+
+	*budget -= work_done;
+	dev->quota -= work_done;
+
+	if (netif_running(dev) && (work_done < orig_budget)) {
+		unsigned long flags;
+		int more;
+
+		/* A bit baroque but it avoids a (space hungry) spin_unlock */
+
+		spin_lock_irqsave(&ep->napi_lock, flags);
+
+		more = ep->reschedule_in_poll;
+		if (!more) {
+			__netif_rx_complete(dev);
+			outl(EpicNapiEvent, ioaddr + INTSTAT);
+			epic_napi_irq_on(dev, ep);
+		} else
+			ep->reschedule_in_poll--;
+
+		spin_unlock_irqrestore(&ep->napi_lock, flags);
+
+		if (more)
+			goto rx_action;
+	}
+
+	return (work_done >= orig_budget);
+}
+
 static int epic_close(struct net_device *dev)
 {
 	long ioaddr = dev->base_addr;
@@ -1268,9 +1389,13 @@
 			   dev->name, (int)inl(ioaddr + INTSTAT));
 
 	del_timer_sync(&ep->timer);
-	epic_pause(dev);
+
+	epic_disable_int(dev, ep);
+
 	free_irq(dev->irq, dev);
 
+	epic_pause(dev);
+
 	/* Free all the skbuffs in the Rx queue. */
 	for (i = 0; i < RX_RING_SIZE; i++) {
 		skb = ep->rx_skbuff[i];
@@ -1491,6 +1616,7 @@
 #endif
 	pci_release_regions(pdev);
 	free_netdev(dev);
+	pci_disable_device(pdev);
 	pci_set_drvdata(pdev, NULL);
 	/* pci_power_off(pdev, -1); */
 }
diff -Nru a/drivers/net/forcedeth.c b/drivers/net/forcedeth.c
--- a/drivers/net/forcedeth.c	2004-10-18 14:55:54 -07:00
+++ b/drivers/net/forcedeth.c	2004-10-18 14:55:54 -07:00
@@ -75,6 +75,7 @@
  *			   added CK804/MCP04 device IDs, code fixes
  *			   for registers, link status and other minor fixes.
  *	0.28: 21 Jun 2004: Big cleanup, making driver mostly endian safe
+ *	0.29: 31 Aug 2004: Add backup timer for link change notification.
  *
  * Known bugs:
  * We suspect that on some hardware no TX done interrupts are generated.
@@ -86,7 +87,7 @@
  * DEV_NEED_TIMERIRQ will not harm you on sane hardware, only generating a few
  * superfluous timer interrupts from the nic.
  */
-#define FORCEDETH_VERSION		"0.28"
+#define FORCEDETH_VERSION		"0.29"
 #define DRV_NAME			"forcedeth"
 
 #include <linux/module.h>
@@ -120,10 +121,11 @@
  * Hardware access:
  */
 
-#define DEV_NEED_LASTPACKET1	0x0001
-#define DEV_IRQMASK_1		0x0002
-#define DEV_IRQMASK_2		0x0004
-#define DEV_NEED_TIMERIRQ	0x0008
+#define DEV_NEED_LASTPACKET1	0x0001	/* set LASTPACKET1 in tx flags */
+#define DEV_IRQMASK_1		0x0002  /* use NVREG_IRQMASK_WANTED_1 for irq mask */
+#define DEV_IRQMASK_2		0x0004  /* use NVREG_IRQMASK_WANTED_2 for irq mask */
+#define DEV_NEED_TIMERIRQ	0x0008  /* set the timer irq flag in the irq mask */
+#define DEV_NEED_LINKTIMER	0x0010	/* poll link settings. Relies on the timer irq */
 
 enum {
 	NvRegIrqStatus = 0x000,
@@ -367,6 +369,7 @@
 
 #define OOM_REFILL	(1+HZ/20)
 #define POLL_WAIT	(1+HZ/100)
+#define LINK_TIMEOUT	(3*HZ)
 
 #define DESC_VER_1	0x0
 #define DESC_VER_2	0x02100
@@ -446,6 +449,11 @@
 	struct timer_list oom_kick;
 	struct timer_list nic_poll;
 
+	/* media detection workaround.
+	 * Locking: Within irq hander or disable_irq+spin_lock(&np->lock);
+	 */
+	int need_linktimer;
+	unsigned long link_timeout;
 	/*
 	 * tx specific fields.
 	 */
@@ -1384,6 +1392,25 @@
 	return retval;
 }
 
+static void nv_linkchange(struct net_device *dev)
+{
+	if (nv_update_linkspeed(dev)) {
+		if (netif_carrier_ok(dev)) {
+			nv_stop_rx(dev);
+		} else {
+			netif_carrier_on(dev);
+			printk(KERN_INFO "%s: link up.\n", dev->name);
+		}
+		nv_start_rx(dev);
+	} else {
+		if (netif_carrier_ok(dev)) {
+			netif_carrier_off(dev);
+			printk(KERN_INFO "%s: link down.\n", dev->name);
+			nv_stop_rx(dev);
+		}
+	}
+}
+
 static void nv_link_irq(struct net_device *dev)
 {
 	u8 *base = get_hwbase(dev);
@@ -1391,25 +1418,10 @@
 
 	miistat = readl(base + NvRegMIIStatus);
 	writel(NVREG_MIISTAT_MASK, base + NvRegMIIStatus);
-	dprintk(KERN_DEBUG "%s: link change notification, status 0x%x.\n", dev->name, miistat);
+	dprintk(KERN_INFO "%s: link change irq, status 0x%x.\n", dev->name, miistat);
 
-	if (miistat & (NVREG_MIISTAT_LINKCHANGE)) {
-		if (nv_update_linkspeed(dev)) {
-			if (netif_carrier_ok(dev)) {
-				nv_stop_rx(dev);
-			} else {
-				netif_carrier_on(dev);
-				printk(KERN_INFO "%s: link up.\n", dev->name);
-			}
-			nv_start_rx(dev);
-		} else {
-			if (netif_carrier_ok(dev)) {
-				netif_carrier_off(dev);
-				printk(KERN_INFO "%s: link down.\n", dev->name);
-				nv_stop_rx(dev);
-			}
-		}
-	}
+	if (miistat & (NVREG_MIISTAT_LINKCHANGE))
+		nv_linkchange(dev);
 	dprintk(KERN_DEBUG "%s: link change notification done.\n", dev->name);
 }
 
@@ -1452,6 +1464,12 @@
 			nv_link_irq(dev);
 			spin_unlock(&np->lock);
 		}
+		if (np->need_linktimer && time_after(jiffies, np->link_timeout)) {
+			spin_lock(&np->lock);
+			nv_linkchange(dev);
+			spin_unlock(&np->lock);
+			np->link_timeout = jiffies + LINK_TIMEOUT;
+		}
 		if (events & (NVREG_IRQ_TX_ERR)) {
 			dprintk(KERN_DEBUG "%s: received irq with events 0x%x. Probably TX fail.\n",
 						dev->name, events);
@@ -1816,6 +1834,14 @@
 		np->irqmask = NVREG_IRQMASK_WANTED_2;
 	if (id->driver_data & DEV_NEED_TIMERIRQ)
 		np->irqmask |= NVREG_IRQ_TIMER;
+	if (id->driver_data & DEV_NEED_LINKTIMER) {
+		dprintk(KERN_INFO "%s: link timer on.\n", pci_name(pci_dev));
+		np->need_linktimer = 1;
+		np->link_timeout = jiffies + LINK_TIMEOUT;
+	} else {
+		dprintk(KERN_INFO "%s: link timer off.\n", pci_name(pci_dev));
+		np->need_linktimer = 0;
+	}
 
 	/* find a suitable phy */
 	for (i = 1; i < 32; i++) {
@@ -1909,21 +1935,21 @@
 		.device = PCI_DEVICE_ID_NVIDIA_NVENET_1,
 		.subvendor = PCI_ANY_ID,
 		.subdevice = PCI_ANY_ID,
-		.driver_data = DEV_IRQMASK_1|DEV_NEED_TIMERIRQ,
+		.driver_data = DEV_IRQMASK_1|DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER,
 	},
 	{	/* nForce2 Ethernet Controller */
 		.vendor = PCI_VENDOR_ID_NVIDIA,
 		.device = PCI_DEVICE_ID_NVIDIA_NVENET_2,
 		.subvendor = PCI_ANY_ID,
 		.subdevice = PCI_ANY_ID,
-		.driver_data = DEV_NEED_LASTPACKET1|DEV_IRQMASK_2|DEV_NEED_TIMERIRQ,
+		.driver_data = DEV_NEED_LASTPACKET1|DEV_IRQMASK_2|DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER,
 	},
 	{	/* nForce3 Ethernet Controller */
 		.vendor = PCI_VENDOR_ID_NVIDIA,
 		.device = PCI_DEVICE_ID_NVIDIA_NVENET_3,
 		.subvendor = PCI_ANY_ID,
 		.subdevice = PCI_ANY_ID,
-		.driver_data = DEV_NEED_LASTPACKET1|DEV_IRQMASK_2|DEV_NEED_TIMERIRQ,
+		.driver_data = DEV_NEED_LASTPACKET1|DEV_IRQMASK_2|DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER,
 	},
 	{	/* nForce3 Ethernet Controller */
 		.vendor = PCI_VENDOR_ID_NVIDIA,
diff -Nru a/drivers/net/gianfar.c b/drivers/net/gianfar.c
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/drivers/net/gianfar.c	2004-10-18 14:57:21 -07:00
@@ -0,0 +1,1864 @@
+/* 
+ * drivers/net/gianfar.c
+ *
+ * Gianfar Ethernet Driver
+ * Driver for FEC on MPC8540 and TSEC on MPC8540/MPC8560
+ * Based on 8260_io/fcc_enet.c
+ *
+ * Author: Andy Fleming
+ * Maintainer: Kumar Gala (kumar.gala@freescale.com)
+ *
+ * Copyright (c) 2002-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.
+ *
+ *  Gianfar:  AKA Lambda Draconis, "Dragon"
+ *  RA 11 31 24.2
+ *  Dec +69 19 52
+ *  V 3.84
+ *  B-V +1.62
+ *
+ *  Theory of operation
+ *  This driver is designed for the Triple-speed Ethernet
+ *  controllers on the Freescale 8540/8560 integrated processors,
+ *  as well as the Fast Ethernet Controller on the 8540.  
+ *  
+ *  The driver is initialized through OCP.  Structures which
+ *  define the configuration needed by the board are defined in a
+ *  board structure in arch/ppc/platforms (though I do not
+ *  discount the possibility that other architectures could one
+ *  day be supported.  One assumption the driver currently makes
+ *  is that the PHY is configured in such a way to advertise all
+ *  capabilities.  This is a sensible default, and on certain
+ *  PHYs, changing this default encounters substantial errata
+ *  issues.  Future versions may remove this requirement, but for
+ *  now, it is best for the firmware to ensure this is the case.
+ *
+ *  The Gianfar Ethernet Controller uses a ring of buffer
+ *  descriptors.  The beginning is indicated by a register
+ *  pointing to the physical address of the start of the ring. 
+ *  The end is determined by a "wrap" bit being set in the 
+ *  last descriptor of the ring.
+ *
+ *  When a packet is received, the RXF bit in the
+ *  IEVENT register is set, triggering an interrupt when the 
+ *  corresponding bit in the IMASK register is also set (if
+ *  interrupt coalescing is active, then the interrupt may not
+ *  happen immediately, but will wait until either a set number
+ *  of frames or amount of time have passed.).  In NAPI, the
+ *  interrupt handler will signal there is work to be done, and
+ *  exit.  Without NAPI, the packet(s) will be handled
+ *  immediately.  Both methods will start at the last known empty
+ *  descriptor, and process every subsequent descriptor until there 
+ *  are none left with data (NAPI will stop after a set number of
+ *  packets to give time to other tasks, but will eventually
+ *  process all the packets).  The data arrives inside a
+ *  pre-allocated skb, and so after the skb is passed up to the
+ *  stack, a new skb must be allocated, and the address field in
+ *  the buffer descriptor must be updated to indicate this new
+ *  skb.
+ *
+ *  When the kernel requests that a packet be transmitted, the
+ *  driver starts where it left off last time, and points the
+ *  descriptor at the buffer which was passed in.  The driver
+ *  then informs the DMA engine that there are packets ready to
+ *  be transmitted.  Once the controller is finished transmitting
+ *  the packet, an interrupt may be triggered (under the same
+ *  conditions as for reception, but depending on the TXF bit).
+ *  The driver then cleans up the buffer.
+ */
+
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/string.h>
+#include <linux/errno.h>
+#include <linux/slab.h>
+#include <linux/interrupt.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/skbuff.h>
+#include <linux/spinlock.h>
+#include <linux/mm.h>
+
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/uaccess.h>
+#include <linux/module.h>
+#include <linux/version.h>
+#include <linux/dma-mapping.h>
+#include <linux/crc32.h>
+
+#include "gianfar.h"
+#include "gianfar_phy.h"
+
+#define TX_TIMEOUT      (1*HZ)
+#define SKB_ALLOC_TIMEOUT 1000000
+#undef BRIEF_GFAR_ERRORS
+#undef VERBOSE_GFAR_ERRORS
+
+#ifdef CONFIG_GFAR_NAPI
+#define RECEIVE(x) netif_receive_skb(x)
+#else
+#define RECEIVE(x) netif_rx(x)
+#endif
+
+const char gfar_driver_name[] = "Gianfar Ethernet";
+const char gfar_driver_version[] = "1.1";
+
+int startup_gfar(struct net_device *dev);
+static int gfar_enet_open(struct net_device *dev);
+static int gfar_start_xmit(struct sk_buff *skb, struct net_device *dev);
+static void gfar_timeout(struct net_device *dev);
+static int gfar_close(struct net_device *dev);
+struct sk_buff *gfar_new_skb(struct net_device *dev, struct rxbd8 *bdp);
+static struct net_device_stats *gfar_get_stats(struct net_device *dev);
+static int gfar_set_mac_address(struct net_device *dev);
+static int gfar_change_mtu(struct net_device *dev, int new_mtu);
+static irqreturn_t gfar_error(int irq, void *dev_id, struct pt_regs *regs);
+static irqreturn_t gfar_transmit(int irq, void *dev_id, struct pt_regs *regs);
+irqreturn_t gfar_receive(int irq, void *dev_id, struct pt_regs *regs);
+static irqreturn_t gfar_interrupt(int irq, void *dev_id, struct pt_regs *regs);
+static irqreturn_t phy_interrupt(int irq, void *dev_id, struct pt_regs *regs);
+static void gfar_phy_change(void *data);
+static void gfar_phy_timer(unsigned long data);
+static void adjust_link(struct net_device *dev);
+static void init_registers(struct net_device *dev);
+static int init_phy(struct net_device *dev);
+static int gfar_probe(struct ocp_device *ocpdev);
+static void gfar_remove(struct ocp_device *ocpdev);
+void free_skb_resources(struct gfar_private *priv);
+static void gfar_set_multi(struct net_device *dev);
+static void gfar_set_hash_for_addr(struct net_device *dev, u8 *addr);
+#ifdef CONFIG_GFAR_NAPI
+static int gfar_poll(struct net_device *dev, int *budget);
+#endif
+static int gfar_clean_rx_ring(struct net_device *dev, int rx_work_limit);
+static int gfar_process_frame(struct net_device *dev, struct sk_buff *skb, int length);
+static void gfar_phy_startup_timer(unsigned long data);
+
+extern struct ethtool_ops gfar_ethtool_ops;
+
+MODULE_AUTHOR("Freescale Semiconductor, Inc");
+MODULE_DESCRIPTION("Gianfar Ethernet Driver");
+MODULE_LICENSE("GPL");
+
+/* Called by the ocp code to initialize device data structures
+ * required for bringing up the device
+ * returns 0 on success */
+static int gfar_probe(struct ocp_device *ocpdev)
+{
+	u32 tempval;
+	struct ocp_device *mdiodev;
+	struct net_device *dev = NULL;
+	struct gfar_private *priv = NULL;
+	struct ocp_gfar_data *einfo;
+	int idx;
+	int err = 0;
+	int dev_ethtool_ops = 0;
+
+	einfo = (struct ocp_gfar_data *) ocpdev->def->additions;
+
+	if (einfo == NULL) {
+		printk(KERN_ERR "gfar %d: Missing additional data!\n",
+		       ocpdev->def->index);
+
+		return -ENODEV;
+	}
+
+	/* get a pointer to the register memory which can
+	 * configure the PHYs.  If it's different from this set,
+	 * get the device which has those regs */
+	if ((einfo->phyregidx >= 0) && 
+			(einfo->phyregidx != ocpdev->def->index)) {
+		mdiodev = ocp_find_device(OCP_ANY_ID,
+					  OCP_FUNC_GFAR, einfo->phyregidx);
+
+		/* If the device which holds the MDIO regs isn't
+		 * up, wait for it to come up */
+		if (mdiodev == NULL)
+			return -EAGAIN;
+	} else {
+		mdiodev = ocpdev;
+	}
+
+	/* Create an ethernet device instance */
+	dev = alloc_etherdev(sizeof (*priv));
+
+	if (dev == NULL)
+		return -ENOMEM;
+
+	priv = netdev_priv(dev);
+
+	/* Set the info in the priv to the current info */
+	priv->einfo = einfo;
+
+	/* get a pointer to the register memory */
+	priv->regs = (struct gfar *)
+		ioremap(ocpdev->def->paddr, sizeof (struct gfar));
+
+	if (priv->regs == NULL) {
+		err = -ENOMEM;
+		goto regs_fail;
+	}
+
+	/* Set the PHY base address */
+	priv->phyregs = (struct gfar *)
+	    ioremap(mdiodev->def->paddr, sizeof (struct gfar));
+
+	if (priv->phyregs == NULL) {
+		err = -ENOMEM;
+		goto phy_regs_fail;
+	}
+
+	spin_lock_init(&priv->lock);
+
+	ocp_set_drvdata(ocpdev, dev);
+
+	/* Stop the DMA engine now, in case it was running before */
+	/* (The firmware could have used it, and left it running). */
+	/* To do this, we write Graceful Receive Stop and Graceful */
+	/* Transmit Stop, and then wait until the corresponding bits */
+	/* in IEVENT indicate the stops have completed. */
+	tempval = gfar_read(&priv->regs->dmactrl);
+	tempval &= ~(DMACTRL_GRS | DMACTRL_GTS);
+	gfar_write(&priv->regs->dmactrl, tempval);
+
+	tempval = gfar_read(&priv->regs->dmactrl);
+	tempval |= (DMACTRL_GRS | DMACTRL_GTS);
+	gfar_write(&priv->regs->dmactrl, tempval);
+
+	while (!(gfar_read(&priv->regs->ievent) & (IEVENT_GRSC | IEVENT_GTSC)))
+		cpu_relax();
+
+	/* Reset MAC layer */
+	gfar_write(&priv->regs->maccfg1, MACCFG1_SOFT_RESET);
+
+	tempval = (MACCFG1_TX_FLOW | MACCFG1_RX_FLOW);
+	gfar_write(&priv->regs->maccfg1, tempval);
+
+	/* Initialize MACCFG2. */
+	gfar_write(&priv->regs->maccfg2, MACCFG2_INIT_SETTINGS);
+
+	/* Initialize ECNTRL */
+	gfar_write(&priv->regs->ecntrl, ECNTRL_INIT_SETTINGS);
+
+	/* Copy the station address into the dev structure, */
+	memcpy(dev->dev_addr, einfo->mac_addr, MAC_ADDR_LEN);
+
+	/* Set the dev->base_addr to the gfar reg region */
+	dev->base_addr = (unsigned long) (priv->regs);
+
+	SET_MODULE_OWNER(dev);
+	SET_NETDEV_DEV(dev, &ocpdev->dev);
+
+	/* Fill in the dev structure */
+	dev->open = gfar_enet_open;
+	dev->hard_start_xmit = gfar_start_xmit;
+	dev->tx_timeout = gfar_timeout;
+	dev->watchdog_timeo = TX_TIMEOUT;
+#ifdef CONFIG_GFAR_NAPI
+	dev->poll = gfar_poll;
+	dev->weight = GFAR_DEV_WEIGHT;
+#endif
+	dev->stop = gfar_close;
+	dev->get_stats = gfar_get_stats;
+	dev->change_mtu = gfar_change_mtu;
+	dev->mtu = 1500;
+	dev->set_multicast_list = gfar_set_multi;
+
+	/* Index into the array of possible ethtool
+	 * ops to catch all 4 possibilities */
+	if((priv->einfo->flags & GFAR_HAS_RMON) == 0)
+		dev_ethtool_ops += 1;
+
+	if((priv->einfo->flags & GFAR_HAS_COALESCE) == 0)
+		dev_ethtool_ops += 2;
+
+	dev->ethtool_ops = gfar_op_array[dev_ethtool_ops];
+
+	priv->rx_buffer_size = DEFAULT_RX_BUFFER_SIZE;
+#ifdef CONFIG_GFAR_BUFSTASH
+	priv->rx_stash_size = STASH_LENGTH;
+#endif
+	priv->tx_ring_size = DEFAULT_TX_RING_SIZE;
+	priv->rx_ring_size = DEFAULT_RX_RING_SIZE;
+
+	priv->txcoalescing = DEFAULT_TX_COALESCE;
+	priv->txcount = DEFAULT_TXCOUNT;
+	priv->txtime = DEFAULT_TXTIME;
+	priv->rxcoalescing = DEFAULT_RX_COALESCE;
+	priv->rxcount = DEFAULT_RXCOUNT;
+	priv->rxtime = DEFAULT_RXTIME;
+
+	err = register_netdev(dev);
+
+	if (err) {
+		printk(KERN_ERR "%s: Cannot register net device, aborting.\n",
+				dev->name);
+		goto register_fail;
+	}
+
+	/* Print out the device info */
+	printk(KERN_INFO DEVICE_NAME, dev->name);
+	for (idx = 0; idx < 6; idx++)
+		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 */
+	/* devices, we only print it once */
+#ifdef CONFIG_GFAR_NAPI
+	printk(KERN_INFO "%s: Running with NAPI enabled\n", dev->name);
+#else
+	printk(KERN_INFO "%s: Running with NAPI disabled\n", dev->name);
+#endif
+	printk(KERN_INFO "%s: %d/%d RX/TX BD ring size\n",
+	       dev->name, priv->rx_ring_size, priv->tx_ring_size);
+
+	return 0;
+
+register_fail:
+	iounmap((void *) priv->phyregs);
+phy_regs_fail:
+	iounmap((void *) priv->regs);
+regs_fail:
+	free_netdev(dev);
+	return -ENOMEM;
+}
+
+static void gfar_remove(struct ocp_device *ocpdev)
+{
+	struct net_device *dev = ocp_get_drvdata(ocpdev);
+	struct gfar_private *priv = netdev_priv(dev);
+
+	ocp_set_drvdata(ocpdev, NULL);
+
+	iounmap((void *) priv->regs);
+	iounmap((void *) priv->phyregs);
+	free_netdev(dev);
+}
+
+/* Configure the PHY for dev.
+ * returns 0 if success.  -1 if failure
+ */
+static int init_phy(struct net_device *dev)
+{
+	struct gfar_private *priv = netdev_priv(dev);
+	struct phy_info *curphy;
+	unsigned int timeout = PHY_INIT_TIMEOUT;
+	struct gfar *phyregs = priv->phyregs;
+	struct gfar_mii_info *mii_info;
+	int err;
+
+	priv->oldlink = 0;
+	priv->oldspeed = 0;
+	priv->oldduplex = -1;
+
+	mii_info = kmalloc(sizeof(struct gfar_mii_info),
+			GFP_KERNEL);
+
+	if(NULL == mii_info) {
+		printk(KERN_ERR "%s: Could not allocate mii_info\n", 
+				dev->name);
+		return -ENOMEM;
+	}
+
+	mii_info->speed = SPEED_1000;
+	mii_info->duplex = DUPLEX_FULL;
+	mii_info->pause = 0;
+	mii_info->link = 1;
+
+	mii_info->advertising = (ADVERTISED_10baseT_Half |
+			ADVERTISED_10baseT_Full |
+			ADVERTISED_100baseT_Half |
+			ADVERTISED_100baseT_Full |
+			ADVERTISED_1000baseT_Full);
+	mii_info->autoneg = 1;
+
+	mii_info->mii_id = priv->einfo->phyid;
+
+	mii_info->dev = dev;
+
+	mii_info->mdio_read = &read_phy_reg;
+	mii_info->mdio_write = &write_phy_reg;
+
+	priv->mii_info = mii_info;
+
+	/* Reset the management interface */
+	gfar_write(&phyregs->miimcfg, MIIMCFG_RESET);
+
+	/* Setup the MII Mgmt clock speed */
+	gfar_write(&phyregs->miimcfg, MIIMCFG_INIT_VALUE);
+
+	/* Wait until the bus is free */
+	while ((gfar_read(&phyregs->miimind) & MIIMIND_BUSY) &&
+			timeout--)
+		cpu_relax();
+
+	if(timeout <= 0) {
+		printk(KERN_ERR "%s: The MII Bus is stuck!\n",
+				dev->name);
+		err = -1;
+		goto bus_fail;
+	}
+
+	/* get info for this PHY */
+	curphy = get_phy_info(priv->mii_info);
+
+	if (curphy == NULL) {
+		printk(KERN_ERR "%s: No PHY found\n", dev->name);
+		err = -1;
+		goto no_phy;
+	}
+
+	mii_info->phyinfo = curphy;
+
+	/* Run the commands which initialize the PHY */
+	if(curphy->init) {
+		err = curphy->init(priv->mii_info);
+
+		if (err) 
+			goto phy_init_fail;
+	}
+
+	return 0;
+
+phy_init_fail:
+no_phy:
+bus_fail:
+	kfree(mii_info);
+
+	return err;
+}
+
+static void init_registers(struct net_device *dev)
+{
+	struct gfar_private *priv = netdev_priv(dev);
+
+	/* Clear IEVENT */
+	gfar_write(&priv->regs->ievent, IEVENT_INIT_CLEAR);
+
+	/* Initialize IMASK */
+	gfar_write(&priv->regs->imask, IMASK_INIT_CLEAR);
+
+	/* Init hash registers to zero */
+	gfar_write(&priv->regs->iaddr0, 0);
+	gfar_write(&priv->regs->iaddr1, 0);
+	gfar_write(&priv->regs->iaddr2, 0);
+	gfar_write(&priv->regs->iaddr3, 0);
+	gfar_write(&priv->regs->iaddr4, 0);
+	gfar_write(&priv->regs->iaddr5, 0);
+	gfar_write(&priv->regs->iaddr6, 0);
+	gfar_write(&priv->regs->iaddr7, 0);
+
+	gfar_write(&priv->regs->gaddr0, 0);
+	gfar_write(&priv->regs->gaddr1, 0);
+	gfar_write(&priv->regs->gaddr2, 0);
+	gfar_write(&priv->regs->gaddr3, 0);
+	gfar_write(&priv->regs->gaddr4, 0);
+	gfar_write(&priv->regs->gaddr5, 0);
+	gfar_write(&priv->regs->gaddr6, 0);
+	gfar_write(&priv->regs->gaddr7, 0);
+
+	/* Zero out rctrl */
+	gfar_write(&priv->regs->rctrl, 0x00000000);
+
+	/* Zero out the rmon mib registers if it has them */
+	if (priv->einfo->flags & GFAR_HAS_RMON) {
+		memset((void *) &(priv->regs->rmon), 0,
+		       sizeof (struct rmon_mib));
+
+		/* Mask off the CAM interrupts */
+		gfar_write(&priv->regs->rmon.cam1, 0xffffffff);
+		gfar_write(&priv->regs->rmon.cam2, 0xffffffff);
+	}
+
+	/* Initialize the max receive buffer length */
+	gfar_write(&priv->regs->mrblr, priv->rx_buffer_size);
+
+#ifdef CONFIG_GFAR_BUFSTASH
+	/* If we are stashing buffers, we need to set the
+	 * extraction length to the size of the buffer */
+	gfar_write(&priv->regs->attreli, priv->rx_stash_size << 16);
+#endif
+
+	/* Initialize the Minimum Frame Length Register */
+	gfar_write(&priv->regs->minflr, MINFLR_INIT_SETTINGS);
+
+	/* Setup Attributes so that snooping is on for rx */
+	gfar_write(&priv->regs->attr, ATTR_INIT_SETTINGS);
+	gfar_write(&priv->regs->attreli, ATTRELI_INIT_SETTINGS);
+
+	/* Assign the TBI an address which won't conflict with the PHYs */
+	gfar_write(&priv->regs->tbipa, TBIPA_VALUE);
+}
+
+void stop_gfar(struct net_device *dev)
+{
+	struct gfar_private *priv = netdev_priv(dev);
+	struct gfar *regs = priv->regs;
+	unsigned long flags;
+	u32 tempval;
+
+	/* Lock it down */
+	spin_lock_irqsave(&priv->lock, flags);
+
+	/* Tell the kernel the link is down */
+	priv->mii_info->link = 0;
+	adjust_link(dev);
+
+	/* Mask all interrupts */
+	gfar_write(&regs->imask, IMASK_INIT_CLEAR);
+
+	/* Clear all interrupts */
+	gfar_write(&regs->ievent, IEVENT_INIT_CLEAR);
+
+	/* Stop the DMA, and wait for it to stop */
+	tempval = gfar_read(&priv->regs->dmactrl);
+	if ((tempval & (DMACTRL_GRS | DMACTRL_GTS))
+	    != (DMACTRL_GRS | DMACTRL_GTS)) {
+		tempval |= (DMACTRL_GRS | DMACTRL_GTS);
+		gfar_write(&priv->regs->dmactrl, tempval);
+
+		while (!(gfar_read(&priv->regs->ievent) &
+			 (IEVENT_GRSC | IEVENT_GTSC)))
+			cpu_relax();
+	}
+
+	/* Disable Rx and Tx */
+	tempval = gfar_read(&regs->maccfg1);
+	tempval &= ~(MACCFG1_RX_EN | MACCFG1_TX_EN);
+	gfar_write(&regs->maccfg1, tempval);
+
+	if (priv->einfo->flags & GFAR_HAS_PHY_INTR) {
+		/* Clear any pending interrupts */
+		mii_clear_phy_interrupt(priv->mii_info);
+
+		/* Disable PHY Interrupts */
+		mii_configure_phy_interrupt(priv->mii_info, 
+				MII_INTERRUPT_DISABLED);
+	}
+
+	spin_unlock_irqrestore(&priv->lock, flags);
+
+	/* Free the IRQs */
+	if (priv->einfo->flags & GFAR_HAS_MULTI_INTR) {
+		free_irq(priv->einfo->interruptError, dev);
+		free_irq(priv->einfo->interruptTransmit, dev);
+		free_irq(priv->einfo->interruptReceive, dev);
+	} else {
+		free_irq(priv->einfo->interruptTransmit, dev);
+	}
+
+	if (priv->einfo->flags & GFAR_HAS_PHY_INTR) {
+		free_irq(priv->einfo->interruptPHY, dev);
+	} else {
+		del_timer_sync(&priv->phy_info_timer);
+	}
+
+	free_skb_resources(priv);
+
+	dma_free_coherent(NULL,
+			sizeof(struct txbd8)*priv->tx_ring_size
+			+ sizeof(struct rxbd8)*priv->rx_ring_size,
+			priv->tx_bd_base,
+			gfar_read(&regs->tbase));
+}
+
+/* If there are any tx skbs or rx skbs still around, free them.
+ * Then free tx_skbuff and rx_skbuff */
+void free_skb_resources(struct gfar_private *priv)
+{
+	struct rxbd8 *rxbdp;
+	struct txbd8 *txbdp;
+	int i;
+
+	/* Go through all the buffer descriptors and free their data buffers */
+	txbdp = priv->tx_bd_base;
+
+	for (i = 0; i < priv->tx_ring_size; i++) {
+
+		if (priv->tx_skbuff[i]) {
+			dma_unmap_single(NULL, txbdp->bufPtr,
+					txbdp->length,
+					DMA_TO_DEVICE);
+			dev_kfree_skb_any(priv->tx_skbuff[i]);
+			priv->tx_skbuff[i] = NULL;
+		}
+	}
+
+	kfree(priv->tx_skbuff);
+
+	rxbdp = priv->rx_bd_base;
+
+	/* rx_skbuff is not guaranteed to be allocated, so only
+	 * free it and its contents if it is allocated */
+	if(priv->rx_skbuff != NULL) {
+		for (i = 0; i < priv->rx_ring_size; i++) {
+			if (priv->rx_skbuff[i]) {
+				dma_unmap_single(NULL, rxbdp->bufPtr,
+						priv->rx_buffer_size
+						+ RXBUF_ALIGNMENT,
+						DMA_FROM_DEVICE);
+
+				dev_kfree_skb_any(priv->rx_skbuff[i]);
+				priv->rx_skbuff[i] = NULL;
+			}
+
+			rxbdp->status = 0;
+			rxbdp->length = 0;
+			rxbdp->bufPtr = 0;
+
+			rxbdp++;
+		}
+
+		kfree(priv->rx_skbuff);
+	}
+}
+
+/* Bring the controller up and running */
+int startup_gfar(struct net_device *dev)
+{
+	struct txbd8 *txbdp;
+	struct rxbd8 *rxbdp;
+	dma_addr_t addr;
+	unsigned long vaddr;
+	int i;
+	struct gfar_private *priv = netdev_priv(dev);
+	struct gfar *regs = priv->regs;
+	u32 tempval;
+	int err = 0;
+
+	gfar_write(&regs->imask, IMASK_INIT_CLEAR);
+
+	/* Allocate memory for the buffer descriptors */
+	vaddr = (unsigned long) dma_alloc_coherent(NULL, 
+			sizeof (struct txbd8) * priv->tx_ring_size +
+			sizeof (struct rxbd8) * priv->rx_ring_size,
+			&addr, GFP_KERNEL);
+
+	if (vaddr == 0) {
+		printk(KERN_ERR "%s: Could not allocate buffer descriptors!\n",
+		       dev->name);
+		return -ENOMEM;
+	}
+
+	priv->tx_bd_base = (struct txbd8 *) vaddr;
+
+	/* enet DMA only understands physical addresses */
+	gfar_write(&regs->tbase, addr);
+
+	/* Start the rx descriptor ring where the tx ring leaves off */
+	addr = addr + sizeof (struct txbd8) * priv->tx_ring_size;
+	vaddr = vaddr + sizeof (struct txbd8) * priv->tx_ring_size;
+	priv->rx_bd_base = (struct rxbd8 *) vaddr;
+	gfar_write(&regs->rbase, addr);
+
+	/* Setup the skbuff rings */
+	priv->tx_skbuff =
+	    (struct sk_buff **) kmalloc(sizeof (struct sk_buff *) *
+					priv->tx_ring_size, GFP_KERNEL);
+
+	if (priv->tx_skbuff == NULL) {
+		printk(KERN_ERR "%s: Could not allocate tx_skbuff\n",
+		       dev->name);
+		err = -ENOMEM;
+		goto tx_skb_fail;
+	}
+
+	for (i = 0; i < priv->tx_ring_size; i++)
+		priv->tx_skbuff[i] = NULL;
+
+	priv->rx_skbuff =
+	    (struct sk_buff **) kmalloc(sizeof (struct sk_buff *) *
+					priv->rx_ring_size, GFP_KERNEL);
+
+	if (priv->rx_skbuff == NULL) {
+		printk(KERN_ERR "%s: Could not allocate rx_skbuff\n",
+		       dev->name);
+		err = -ENOMEM;
+		goto rx_skb_fail;
+	}
+
+	for (i = 0; i < priv->rx_ring_size; i++)
+		priv->rx_skbuff[i] = NULL;
+
+	/* Initialize some variables in our dev structure */
+	priv->dirty_tx = priv->cur_tx = priv->tx_bd_base;
+	priv->cur_rx = priv->rx_bd_base;
+	priv->skb_curtx = priv->skb_dirtytx = 0;
+	priv->skb_currx = 0;
+
+	/* Initialize Transmit Descriptor Ring */
+	txbdp = priv->tx_bd_base;
+	for (i = 0; i < priv->tx_ring_size; i++) {
+		txbdp->status = 0;
+		txbdp->length = 0;
+		txbdp->bufPtr = 0;
+		txbdp++;
+	}
+
+	/* Set the last descriptor in the ring to indicate wrap */
+	txbdp--;
+	txbdp->status |= TXBD_WRAP;
+
+	rxbdp = priv->rx_bd_base;
+	for (i = 0; i < priv->rx_ring_size; i++) {
+		struct sk_buff *skb = NULL;
+
+		rxbdp->status = 0;
+
+		skb = gfar_new_skb(dev, rxbdp);
+
+		priv->rx_skbuff[i] = skb;
+
+		rxbdp++;
+	}
+
+	/* Set the last descriptor in the ring to wrap */
+	rxbdp--;
+	rxbdp->status |= RXBD_WRAP;
+
+	/* If the device has multiple interrupts, register for
+	 * them.  Otherwise, only register for the one */
+	if (priv->einfo->flags & GFAR_HAS_MULTI_INTR) {
+		/* Install our interrupt handlers for Error, 
+		 * Transmit, and Receive */
+		if (request_irq(priv->einfo->interruptError, gfar_error,
+				0, "enet_error", dev) < 0) {
+			printk(KERN_ERR "%s: Can't get IRQ %d\n",
+			       dev->name, priv->einfo->interruptError);
+
+			err = -1;
+			goto err_irq_fail;
+		}
+
+		if (request_irq(priv->einfo->interruptTransmit, gfar_transmit,
+				0, "enet_tx", dev) < 0) {
+			printk(KERN_ERR "%s: Can't get IRQ %d\n",
+			       dev->name, priv->einfo->interruptTransmit);
+
+			err = -1;
+
+			goto tx_irq_fail;
+		}
+
+		if (request_irq(priv->einfo->interruptReceive, gfar_receive,
+				0, "enet_rx", dev) < 0) {
+			printk(KERN_ERR "%s: Can't get IRQ %d (receive0)\n",
+			       dev->name, priv->einfo->interruptReceive);
+
+			err = -1;
+			goto rx_irq_fail;
+		}
+	} else {
+		if (request_irq(priv->einfo->interruptTransmit, gfar_interrupt,
+				0, "gfar_interrupt", dev) < 0) {
+			printk(KERN_ERR "%s: Can't get IRQ %d\n",
+			       dev->name, priv->einfo->interruptError);
+
+			err = -1;
+			goto err_irq_fail;
+		}
+	}
+
+	/* Set up the PHY change work queue */
+	INIT_WORK(&priv->tq, gfar_phy_change, dev);
+
+	init_timer(&priv->phy_info_timer);
+	priv->phy_info_timer.function = &gfar_phy_startup_timer;
+	priv->phy_info_timer.data = (unsigned long) priv->mii_info;
+	mod_timer(&priv->phy_info_timer, jiffies + HZ);
+
+	/* Configure the coalescing support */
+	if (priv->txcoalescing)
+		gfar_write(&regs->txic,
+			   mk_ic_value(priv->txcount, priv->txtime));
+	else
+		gfar_write(&regs->txic, 0);
+
+	if (priv->rxcoalescing)
+		gfar_write(&regs->rxic,
+			   mk_ic_value(priv->rxcount, priv->rxtime));
+	else
+		gfar_write(&regs->rxic, 0);
+
+	init_waitqueue_head(&priv->rxcleanupq);
+
+	/* Enable Rx and Tx in MACCFG1 */
+	tempval = gfar_read(&regs->maccfg1);
+	tempval |= (MACCFG1_RX_EN | MACCFG1_TX_EN);
+	gfar_write(&regs->maccfg1, tempval);
+
+	/* Initialize DMACTRL to have WWR and WOP */
+	tempval = gfar_read(&priv->regs->dmactrl);
+	tempval |= DMACTRL_INIT_SETTINGS;
+	gfar_write(&priv->regs->dmactrl, tempval);
+
+	/* Clear THLT, so that the DMA starts polling now */
+	gfar_write(&regs->tstat, TSTAT_CLEAR_THALT);
+
+	/* Make sure we aren't stopped */
+	tempval = gfar_read(&priv->regs->dmactrl);
+	tempval &= ~(DMACTRL_GRS | DMACTRL_GTS);
+	gfar_write(&priv->regs->dmactrl, tempval);
+
+	/* Unmask the interrupts we look for */
+	gfar_write(&regs->imask, IMASK_DEFAULT);
+
+	return 0;
+
+rx_irq_fail:
+	free_irq(priv->einfo->interruptTransmit, dev);
+tx_irq_fail:
+	free_irq(priv->einfo->interruptError, dev);
+err_irq_fail:
+rx_skb_fail:
+	free_skb_resources(priv);
+tx_skb_fail:
+	dma_free_coherent(NULL,
+			sizeof(struct txbd8)*priv->tx_ring_size
+			+ sizeof(struct rxbd8)*priv->rx_ring_size,
+			priv->tx_bd_base,
+			gfar_read(&regs->tbase));
+
+	if (priv->mii_info->phyinfo->close)
+		priv->mii_info->phyinfo->close(priv->mii_info);
+
+	kfree(priv->mii_info);
+
+	return err;
+}
+
+/* Called when something needs to use the ethernet device */
+/* Returns 0 for success. */
+static int gfar_enet_open(struct net_device *dev)
+{
+	int err;
+
+	/* Initialize a bunch of registers */
+	init_registers(dev);
+
+	gfar_set_mac_address(dev);
+
+	err = init_phy(dev);
+
+	if(err)
+		return err;
+
+	err = startup_gfar(dev);
+
+	netif_start_queue(dev);
+
+	return err;
+}
+
+/* This is called by the kernel when a frame is ready for transmission. */
+/* It is pointed to by the dev->hard_start_xmit function pointer */
+static int gfar_start_xmit(struct sk_buff *skb, struct net_device *dev)
+{
+	struct gfar_private *priv = netdev_priv(dev);
+	struct txbd8 *txbdp;
+
+	/* Update transmit stats */
+	priv->stats.tx_bytes += skb->len;
+
+	/* Lock priv now */
+	spin_lock_irq(&priv->lock);
+
+	/* Point at the first free tx descriptor */
+	txbdp = priv->cur_tx;
+
+	/* Clear all but the WRAP status flags */
+	txbdp->status &= TXBD_WRAP;
+
+	/* Set buffer length and pointer */
+	txbdp->length = skb->len;
+	txbdp->bufPtr = dma_map_single(NULL, skb->data, 
+			skb->len, DMA_TO_DEVICE);
+
+	/* Save the skb pointer so we can free it later */
+	priv->tx_skbuff[priv->skb_curtx] = skb;
+
+	/* Update the current skb pointer (wrapping if this was the last) */
+	priv->skb_curtx =
+	    (priv->skb_curtx + 1) & TX_RING_MOD_MASK(priv->tx_ring_size);
+
+	/* Flag the BD as interrupt-causing */
+	txbdp->status |= TXBD_INTERRUPT;
+
+	/* Flag the BD as ready to go, last in frame, and  */
+	/* in need of CRC */
+	txbdp->status |= (TXBD_READY | TXBD_LAST | TXBD_CRC);
+
+	dev->trans_start = jiffies;
+
+	/* If this was the last BD in the ring, the next one */
+	/* is at the beginning of the ring */
+	if (txbdp->status & TXBD_WRAP)
+		txbdp = priv->tx_bd_base;
+	else
+		txbdp++;
+
+	/* If the next BD still needs to be cleaned up, then the bds
+	   are full.  We need to tell the kernel to stop sending us stuff. */
+	if (txbdp == priv->dirty_tx) {
+		netif_stop_queue(dev);
+
+		priv->stats.tx_fifo_errors++;
+	}
+
+	/* Update the current txbd to the next one */
+	priv->cur_tx = txbdp;
+
+	/* Tell the DMA to go go go */
+	gfar_write(&priv->regs->tstat, TSTAT_CLEAR_THALT);
+
+	/* Unlock priv */
+	spin_unlock_irq(&priv->lock);
+
+	return 0;
+}
+
+/* Stops the kernel queue, and halts the controller */
+static int gfar_close(struct net_device *dev)
+{
+	struct gfar_private *priv = netdev_priv(dev);
+	stop_gfar(dev);
+
+	/* Shutdown the PHY */
+	if (priv->mii_info->phyinfo->close)
+		priv->mii_info->phyinfo->close(priv->mii_info);
+
+	kfree(priv->mii_info);
+
+	netif_stop_queue(dev);
+
+	return 0;
+}
+
+/* returns a net_device_stats structure pointer */
+static struct net_device_stats * gfar_get_stats(struct net_device *dev)
+{
+	struct gfar_private *priv = netdev_priv(dev);
+
+	return &(priv->stats);
+}
+
+/* Changes the mac address if the controller is not running. */
+int gfar_set_mac_address(struct net_device *dev)
+{
+	struct gfar_private *priv = netdev_priv(dev);
+	int i;
+	char tmpbuf[MAC_ADDR_LEN];
+	u32 tempval;
+
+	/* Now copy it into the mac registers backwards, cuz */
+	/* little endian is silly */
+	for (i = 0; i < MAC_ADDR_LEN; i++)
+		tmpbuf[MAC_ADDR_LEN - 1 - i] = dev->dev_addr[i];
+
+	gfar_write(&priv->regs->macstnaddr1, *((u32 *) (tmpbuf)));
+
+	tempval = *((u32 *) (tmpbuf + 4));
+
+	gfar_write(&priv->regs->macstnaddr2, tempval);
+
+	return 0;
+}
+
+
+static int gfar_change_mtu(struct net_device *dev, int new_mtu)
+{
+	int tempsize, tempval;
+	struct gfar_private *priv = netdev_priv(dev);
+	int oldsize = priv->rx_buffer_size;
+	int frame_size = new_mtu + 18;
+
+	if ((frame_size < 64) || (frame_size > JUMBO_FRAME_SIZE)) {
+		printk(KERN_ERR "%s: Invalid MTU setting\n", dev->name);
+		return -EINVAL;
+	}
+
+	tempsize =
+	    (frame_size & ~(INCREMENTAL_BUFFER_SIZE - 1)) +
+	    INCREMENTAL_BUFFER_SIZE;
+
+	/* Only stop and start the controller if it isn't already
+	 * stopped */
+	if ((oldsize != tempsize) && (dev->flags & IFF_UP))
+		stop_gfar(dev);
+
+	priv->rx_buffer_size = tempsize;
+
+	dev->mtu = new_mtu;
+
+	gfar_write(&priv->regs->mrblr, priv->rx_buffer_size);
+	gfar_write(&priv->regs->maxfrm, priv->rx_buffer_size);
+
+	/* If the mtu is larger than the max size for standard
+	 * ethernet frames (ie, a jumbo frame), then set maccfg2
+	 * to allow huge frames, and to check the length */
+	tempval = gfar_read(&priv->regs->maccfg2);
+
+	if (priv->rx_buffer_size > DEFAULT_RX_BUFFER_SIZE)
+		tempval |= (MACCFG2_HUGEFRAME | MACCFG2_LENGTHCHECK);
+	else
+		tempval &= ~(MACCFG2_HUGEFRAME | MACCFG2_LENGTHCHECK);
+
+	gfar_write(&priv->regs->maccfg2, tempval);
+
+	if ((oldsize != tempsize) && (dev->flags & IFF_UP))
+		startup_gfar(dev);
+
+	return 0;
+}
+
+/* gfar_timeout gets called when a packet has not been
+ * transmitted after a set amount of time.
+ * For now, assume that clearing out all the structures, and
+ * starting over will fix the problem. */
+static void gfar_timeout(struct net_device *dev)
+{
+	struct gfar_private *priv = netdev_priv(dev);
+
+	priv->stats.tx_errors++;
+
+	if (dev->flags & IFF_UP) {
+		stop_gfar(dev);
+		startup_gfar(dev);
+	}
+
+	netif_schedule(dev);
+}
+
+/* Interrupt Handler for Transmit complete */
+static irqreturn_t gfar_transmit(int irq, void *dev_id, struct pt_regs *regs)
+{
+	struct net_device *dev = (struct net_device *) dev_id;
+	struct gfar_private *priv = netdev_priv(dev);
+	struct txbd8 *bdp;
+
+	/* Clear IEVENT */
+	gfar_write(&priv->regs->ievent, IEVENT_TX_MASK);
+
+	/* Lock priv */
+	spin_lock(&priv->lock);
+	bdp = priv->dirty_tx;
+	while ((bdp->status & TXBD_READY) == 0) {
+		/* If dirty_tx and cur_tx are the same, then either the */
+		/* ring is empty or full now (it could only be full in the beginning, */
+		/* obviously).  If it is empty, we are done. */
+		if ((bdp == priv->cur_tx) && (netif_queue_stopped(dev) == 0))
+			break;
+
+		priv->stats.tx_packets++;
+
+		/* Deferred means some collisions occurred during transmit, */
+		/* but we eventually sent the packet. */
+		if (bdp->status & TXBD_DEF)
+			priv->stats.collisions++;
+
+		/* Free the sk buffer associated with this TxBD */
+		dev_kfree_skb_irq(priv->tx_skbuff[priv->skb_dirtytx]);
+		priv->tx_skbuff[priv->skb_dirtytx] = NULL;
+		priv->skb_dirtytx =
+		    (priv->skb_dirtytx +
+		     1) & TX_RING_MOD_MASK(priv->tx_ring_size);
+
+		/* update bdp to point at next bd in the ring (wrapping if necessary) */
+		if (bdp->status & TXBD_WRAP)
+			bdp = priv->tx_bd_base;
+		else
+			bdp++;
+
+		/* Move dirty_tx to be the next bd */
+		priv->dirty_tx = bdp;
+
+		/* We freed a buffer, so now we can restart transmission */
+		if (netif_queue_stopped(dev))
+			netif_wake_queue(dev);
+	} /* while ((bdp->status & TXBD_READY) == 0) */
+
+	/* If we are coalescing the interrupts, reset the timer */
+	/* Otherwise, clear it */
+	if (priv->txcoalescing)
+		gfar_write(&priv->regs->txic,
+			   mk_ic_value(priv->txcount, priv->txtime));
+	else
+		gfar_write(&priv->regs->txic, 0);
+
+	spin_unlock(&priv->lock);
+
+	return IRQ_HANDLED;
+}
+
+struct sk_buff * gfar_new_skb(struct net_device *dev, struct rxbd8 *bdp)
+{
+	struct gfar_private *priv = netdev_priv(dev);
+	struct sk_buff *skb = NULL;
+	unsigned int timeout = SKB_ALLOC_TIMEOUT;
+
+	/* We have to allocate the skb, so keep trying till we succeed */
+	while ((!skb) && timeout--)
+		skb = dev_alloc_skb(priv->rx_buffer_size + RXBUF_ALIGNMENT);
+
+	if (skb == NULL)
+		return NULL;
+
+	/* We need the data buffer to be aligned properly.  We will reserve
+	 * as many bytes as needed to align the data properly
+	 */
+	skb_reserve(skb,
+		    RXBUF_ALIGNMENT -
+		    (((unsigned) skb->data) & (RXBUF_ALIGNMENT - 1)));
+
+	skb->dev = dev;
+
+	bdp->bufPtr = dma_map_single(NULL, skb->data,
+			priv->rx_buffer_size + RXBUF_ALIGNMENT, 
+			DMA_FROM_DEVICE);
+
+	bdp->length = 0;
+
+	/* Mark the buffer empty */
+	bdp->status |= (RXBD_EMPTY | RXBD_INTERRUPT);
+
+	return skb;
+}
+
+static inline void count_errors(unsigned short status, struct gfar_private *priv)
+{
+	struct net_device_stats *stats = &priv->stats;
+	struct gfar_extra_stats *estats = &priv->extra_stats;
+
+	/* If the packet was truncated, none of the other errors
+	 * matter */
+	if (status & RXBD_TRUNCATED) {
+		stats->rx_length_errors++;
+
+		estats->rx_trunc++;
+
+		return;
+	}
+	/* Count the errors, if there were any */
+	if (status & (RXBD_LARGE | RXBD_SHORT)) {
+		stats->rx_length_errors++;
+
+		if (status & RXBD_LARGE)
+			estats->rx_large++;
+		else
+			estats->rx_short++;
+	}
+	if (status & RXBD_NONOCTET) {
+		stats->rx_frame_errors++;
+		estats->rx_nonoctet++;
+	}
+	if (status & RXBD_CRCERR) {
+		estats->rx_crcerr++;
+		stats->rx_crc_errors++;
+	}
+	if (status & RXBD_OVERRUN) {
+		estats->rx_overrun++;
+		stats->rx_crc_errors++;
+	}
+}
+
+irqreturn_t gfar_receive(int irq, void *dev_id, struct pt_regs *regs)
+{
+	struct net_device *dev = (struct net_device *) dev_id;
+	struct gfar_private *priv = netdev_priv(dev);
+
+#ifdef CONFIG_GFAR_NAPI
+	u32 tempval;
+#endif
+
+	/* Clear IEVENT, so rx interrupt isn't called again
+	 * because of this interrupt */
+	gfar_write(&priv->regs->ievent, IEVENT_RX_MASK);
+
+	/* support NAPI */
+#ifdef CONFIG_GFAR_NAPI
+	if (netif_rx_schedule_prep(dev)) {
+		tempval = gfar_read(&priv->regs->imask);
+		tempval &= IMASK_RX_DISABLED;
+		gfar_write(&priv->regs->imask, tempval);
+
+		__netif_rx_schedule(dev);
+	} else {
+#ifdef VERBOSE_GFAR_ERRORS
+		printk(KERN_DEBUG "%s: receive called twice (%x)[%x]\n",
+		       dev->name, gfar_read(priv->regs->ievent),
+		       gfar_read(priv->regs->imask));
+#endif
+	}
+#else
+
+	spin_lock(&priv->lock);
+	gfar_clean_rx_ring(dev, priv->rx_ring_size);
+
+	/* If we are coalescing interrupts, update the timer */
+	/* Otherwise, clear it */
+	if (priv->rxcoalescing)
+		gfar_write(&priv->regs->rxic,
+			   mk_ic_value(priv->rxcount, priv->rxtime));
+	else
+		gfar_write(&priv->regs->rxic, 0);
+
+	/* Just in case we need to wake the ring param changer */
+	priv->rxclean = 1;
+
+	spin_unlock(&priv->lock);
+#endif
+
+	return IRQ_HANDLED;
+}
+
+
+/* gfar_process_frame() -- handle one incoming packet if skb
+ * isn't NULL.  */
+static int gfar_process_frame(struct net_device *dev, struct sk_buff *skb,
+		int length)
+{
+	struct gfar_private *priv = netdev_priv(dev);
+
+	if (skb == NULL) {
+#ifdef BRIEF_GFAR_ERRORS
+		printk(KERN_WARNING "%s: Missing skb!!.\n",
+				dev->name);
+#endif
+		priv->stats.rx_dropped++;
+		priv->extra_stats.rx_skbmissing++;
+	} else {
+		/* Prep the skb for the packet */
+		skb_put(skb, length);
+
+		/* Tell the skb what kind of packet this is */
+		skb->protocol = eth_type_trans(skb, dev);
+
+		/* Send the packet up the stack */
+		if (RECEIVE(skb) == NET_RX_DROP) {
+			priv->extra_stats.kernel_dropped++;
+		}
+	}
+
+	return 0;
+}
+
+/* gfar_clean_rx_ring() -- Processes each frame in the rx ring
+ *   until the budget/quota has been reached. Returns the number 
+ *   of frames handled
+ */
+static int gfar_clean_rx_ring(struct net_device *dev, int rx_work_limit)
+{
+	struct rxbd8 *bdp;
+	struct sk_buff *skb;
+	u16 pkt_len;
+	int howmany = 0;
+	struct gfar_private *priv = netdev_priv(dev);
+
+	/* Get the first full descriptor */
+	bdp = priv->cur_rx;
+
+	while (!((bdp->status & RXBD_EMPTY) || (--rx_work_limit < 0))) {
+		skb = priv->rx_skbuff[priv->skb_currx];
+
+		if (!(bdp->status &
+		      (RXBD_LARGE | RXBD_SHORT | RXBD_NONOCTET
+		       | RXBD_CRCERR | RXBD_OVERRUN | RXBD_TRUNCATED))) {
+			/* Increment the number of packets */
+			priv->stats.rx_packets++;
+			howmany++;
+
+			/* Remove the FCS from the packet length */
+			pkt_len = bdp->length - 4;
+
+			gfar_process_frame(dev, skb, pkt_len);
+
+			priv->stats.rx_bytes += pkt_len;
+		} else {
+			count_errors(bdp->status, priv);
+
+			if (skb)
+				dev_kfree_skb_any(skb);
+
+			priv->rx_skbuff[priv->skb_currx] = NULL;
+		}
+
+		dev->last_rx = jiffies;
+
+		/* Clear the status flags for this buffer */
+		bdp->status &= ~RXBD_STATS;
+
+		/* Add another skb for the future */
+		skb = gfar_new_skb(dev, bdp);
+		priv->rx_skbuff[priv->skb_currx] = skb;
+
+		/* Update to the next pointer */
+		if (bdp->status & RXBD_WRAP)
+			bdp = priv->rx_bd_base;
+		else
+			bdp++;
+
+		/* update to point at the next skb */
+		priv->skb_currx =
+		    (priv->skb_currx +
+		     1) & RX_RING_MOD_MASK(priv->rx_ring_size);
+
+	}
+
+	/* Update the current rxbd pointer to be the next one */
+	priv->cur_rx = bdp;
+
+	/* If no packets have arrived since the
+	 * last one we processed, clear the IEVENT RX and
+	 * BSY bits so that another interrupt won't be
+	 * generated when we set IMASK */
+	if (bdp->status & RXBD_EMPTY)
+		gfar_write(&priv->regs->ievent, IEVENT_RX_MASK);
+
+	return howmany;
+}
+
+#ifdef CONFIG_GFAR_NAPI
+static int gfar_poll(struct net_device *dev, int *budget)
+{
+	int howmany;
+	struct gfar_private *priv = netdev_priv(dev);
+	int rx_work_limit = *budget;
+
+	if (rx_work_limit > dev->quota)
+		rx_work_limit = dev->quota;
+
+	howmany = gfar_clean_rx_ring(dev, rx_work_limit);
+
+	dev->quota -= howmany;
+	rx_work_limit -= howmany;
+	*budget -= howmany;
+
+	if (rx_work_limit >= 0) {
+		netif_rx_complete(dev);
+
+		/* Clear the halt bit in RSTAT */
+		gfar_write(&priv->regs->rstat, RSTAT_CLEAR_RHALT);
+
+		gfar_write(&priv->regs->imask, IMASK_DEFAULT);
+
+		/* If we are coalescing interrupts, update the timer */
+		/* Otherwise, clear it */
+		if (priv->rxcoalescing)
+			gfar_write(&priv->regs->rxic,
+				   mk_ic_value(priv->rxcount, priv->rxtime));
+		else
+			gfar_write(&priv->regs->rxic, 0);
+
+		/* Signal to the ring size changer that it's safe to go */
+		priv->rxclean = 1;
+	}
+
+	return (rx_work_limit < 0) ? 1 : 0;
+}
+#endif
+
+/* The interrupt handler for devices with one interrupt */
+static irqreturn_t gfar_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+{
+	struct net_device *dev = dev_id;
+	struct gfar_private *priv = netdev_priv(dev);
+
+	/* Save ievent for future reference */
+	u32 events = gfar_read(&priv->regs->ievent);
+
+	/* Clear IEVENT */
+	gfar_write(&priv->regs->ievent, events);
+
+	/* Check for reception */
+	if ((events & IEVENT_RXF0) || (events & IEVENT_RXB0))
+		gfar_receive(irq, dev_id, regs);
+
+	/* Check for transmit completion */
+	if ((events & IEVENT_TXF) || (events & IEVENT_TXB))
+		gfar_transmit(irq, dev_id, regs);
+
+	/* Update error statistics */
+	if (events & IEVENT_TXE) {
+		priv->stats.tx_errors++;
+
+		if (events & IEVENT_LC)
+			priv->stats.tx_window_errors++;
+		if (events & IEVENT_CRL)
+			priv->stats.tx_aborted_errors++;
+		if (events & IEVENT_XFUN) {
+#ifdef VERBOSE_GFAR_ERRORS
+			printk(KERN_WARNING "%s: tx underrun. dropped packet\n",
+			       dev->name);
+#endif
+			priv->stats.tx_dropped++;
+			priv->extra_stats.tx_underrun++;
+
+			/* Reactivate the Tx Queues */
+			gfar_write(&priv->regs->tstat, TSTAT_CLEAR_THALT);
+		}
+	}
+	if (events & IEVENT_BSY) {
+		priv->stats.rx_errors++;
+		priv->extra_stats.rx_bsy++;
+
+		gfar_receive(irq, dev_id, regs);
+
+#ifndef CONFIG_GFAR_NAPI
+		/* Clear the halt bit in RSTAT */
+		gfar_write(&priv->regs->rstat, RSTAT_CLEAR_RHALT);
+#endif
+
+#ifdef VERBOSE_GFAR_ERRORS
+		printk(KERN_DEBUG "%s: busy error (rhalt: %x)\n", dev->name,
+		       gfar_read(priv->regs->rstat));
+#endif
+	}
+	if (events & IEVENT_BABR) {
+		priv->stats.rx_errors++;
+		priv->extra_stats.rx_babr++;
+
+#ifdef VERBOSE_GFAR_ERRORS
+		printk(KERN_DEBUG "%s: babbling error\n", dev->name);
+#endif
+	}
+	if (events & IEVENT_EBERR) {
+		priv->extra_stats.eberr++;
+#ifdef VERBOSE_GFAR_ERRORS
+		printk(KERN_DEBUG "%s: EBERR\n", dev->name);
+#endif
+	}
+	if (events & IEVENT_RXC) {
+#ifdef VERBOSE_GFAR_ERRORS
+		printk(KERN_DEBUG "%s: control frame\n", dev->name);
+#endif
+	}
+
+	if (events & IEVENT_BABT) {
+		priv->extra_stats.tx_babt++;
+#ifdef VERBOSE_GFAR_ERRORS
+		printk(KERN_DEBUG "%s: babt error\n", dev->name);
+#endif
+	}
+
+	return IRQ_HANDLED;
+}
+
+static irqreturn_t phy_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+{
+	struct net_device *dev = (struct net_device *) dev_id;
+	struct gfar_private *priv = netdev_priv(dev);
+
+	/* Clear the interrupt */
+	mii_clear_phy_interrupt(priv->mii_info);
+
+	/* Disable PHY interrupts */
+	mii_configure_phy_interrupt(priv->mii_info,
+			MII_INTERRUPT_DISABLED);
+
+	/* Schedule the phy change */
+	schedule_work(&priv->tq);
+
+	return IRQ_HANDLED;
+}
+
+/* Scheduled by the phy_interrupt/timer to handle PHY changes */
+static void gfar_phy_change(void *data)
+{
+	struct net_device *dev = (struct net_device *) data;
+	struct gfar_private *priv = netdev_priv(dev);
+	int result = 0;
+
+	/* Delay to give the PHY a chance to change the
+	 * register state */
+	msleep(1);
+
+	/* Update the link, speed, duplex */
+	result = priv->mii_info->phyinfo->read_status(priv->mii_info);
+
+	/* Adjust the known status as long as the link
+	 * isn't still coming up */
+	if((0 == result) || (priv->mii_info->link == 0))
+		adjust_link(dev);
+
+	/* Reenable interrupts, if needed */
+	if (priv->einfo->flags & GFAR_HAS_PHY_INTR)
+		mii_configure_phy_interrupt(priv->mii_info,
+				MII_INTERRUPT_ENABLED);
+}
+
+/* Called every so often on systems that don't interrupt
+ * the core for PHY changes */
+static void gfar_phy_timer(unsigned long data)
+{
+	struct net_device *dev = (struct net_device *) data;
+	struct gfar_private *priv = netdev_priv(dev);
+
+	schedule_work(&priv->tq);
+
+	mod_timer(&priv->phy_info_timer, jiffies +
+			GFAR_PHY_CHANGE_TIME * HZ);
+}
+
+/* Keep trying aneg for some time
+ * If, after GFAR_AN_TIMEOUT seconds, it has not
+ * finished, we switch to forced.
+ * Either way, once the process has completed, we either
+ * request the interrupt, or switch the timer over to 
+ * using gfar_phy_timer to check status */
+static void gfar_phy_startup_timer(unsigned long data)
+{
+	int result;
+	static int secondary = GFAR_AN_TIMEOUT;
+	struct gfar_mii_info *mii_info = (struct gfar_mii_info *)data;
+	struct gfar_private *priv = netdev_priv(mii_info->dev);
+
+	/* Configure the Auto-negotiation */
+	result = mii_info->phyinfo->config_aneg(mii_info);
+
+	/* If autonegotiation failed to start, and
+	 * we haven't timed out, reset the timer, and return */
+	if (result && secondary--) {
+		mod_timer(&priv->phy_info_timer, jiffies + HZ);
+		return;
+	} else if (result) {
+		/* Couldn't start autonegotiation.
+		 * Try switching to forced */
+		mii_info->autoneg = 0;
+		result = mii_info->phyinfo->config_aneg(mii_info);
+
+		/* Forcing failed!  Give up */
+		if(result) {
+			printk(KERN_ERR "%s: Forcing failed!\n",
+					mii_info->dev->name);
+			return;
+		}
+	}
+
+	/* Kill the timer so it can be restarted */
+	del_timer_sync(&priv->phy_info_timer);
+
+	/* Grab the PHY interrupt, if necessary/possible */
+	if (priv->einfo->flags & GFAR_HAS_PHY_INTR) {
+		if (request_irq(priv->einfo->interruptPHY, 
+					phy_interrupt,
+					SA_SHIRQ, 
+					"phy_interrupt", 
+					mii_info->dev) < 0) {
+			printk(KERN_ERR "%s: Can't get IRQ %d (PHY)\n",
+					mii_info->dev->name,
+					priv->einfo->interruptPHY);
+		} else {
+			mii_configure_phy_interrupt(priv->mii_info, 
+					MII_INTERRUPT_ENABLED);
+			return;
+		}
+	}
+
+	/* Start the timer again, this time in order to
+	 * handle a change in status */
+	init_timer(&priv->phy_info_timer);
+	priv->phy_info_timer.function = &gfar_phy_timer;
+	priv->phy_info_timer.data = (unsigned long) mii_info->dev;
+	mod_timer(&priv->phy_info_timer, jiffies +
+			GFAR_PHY_CHANGE_TIME * HZ);
+}
+
+/* Called every time the controller might need to be made
+ * aware of new link state.  The PHY code conveys this
+ * information through variables in the priv structure, and this
+ * function converts those variables into the appropriate
+ * register values, and can bring down the device if needed.
+ */
+static void adjust_link(struct net_device *dev)
+{
+	struct gfar_private *priv = netdev_priv(dev);
+	struct gfar *regs = priv->regs;
+	u32 tempval;
+	struct gfar_mii_info *mii_info = priv->mii_info;
+
+	if (mii_info->link) {
+		/* Now we make sure that we can be in full duplex mode.
+		 * If not, we operate in half-duplex mode. */
+		if (mii_info->duplex != priv->oldduplex) {
+			if (!(mii_info->duplex)) {
+				tempval = gfar_read(&regs->maccfg2);
+				tempval &= ~(MACCFG2_FULL_DUPLEX);
+				gfar_write(&regs->maccfg2, tempval);
+
+				printk(KERN_INFO "%s: Half Duplex\n",
+				       dev->name);
+			} else {
+				tempval = gfar_read(&regs->maccfg2);
+				tempval |= MACCFG2_FULL_DUPLEX;
+				gfar_write(&regs->maccfg2, tempval);
+
+				printk(KERN_INFO "%s: Full Duplex\n",
+				       dev->name);
+			}
+
+			priv->oldduplex = mii_info->duplex;
+		}
+
+		if (mii_info->speed != priv->oldspeed) {
+			switch (mii_info->speed) {
+			case 1000:
+				tempval = gfar_read(&regs->maccfg2);
+				tempval =
+				    ((tempval & ~(MACCFG2_IF)) | MACCFG2_GMII);
+				gfar_write(&regs->maccfg2, tempval);
+				break;
+			case 100:
+			case 10:
+				tempval = gfar_read(&regs->maccfg2);
+				tempval =
+				    ((tempval & ~(MACCFG2_IF)) | MACCFG2_MII);
+				gfar_write(&regs->maccfg2, tempval);
+				break;
+			default:
+				printk(KERN_WARNING
+				       "%s: Ack!  Speed (%d) is not 10/100/1000!\n",
+				       dev->name, mii_info->speed);
+				break;
+			}
+
+			printk(KERN_INFO "%s: Speed %dBT\n", dev->name,
+			       mii_info->speed);
+
+			priv->oldspeed = mii_info->speed;
+		}
+
+		if (!priv->oldlink) {
+			printk(KERN_INFO "%s: Link is up\n", dev->name);
+			priv->oldlink = 1;
+			netif_carrier_on(dev);
+			netif_schedule(dev);
+		}
+	} else {
+		if (priv->oldlink) {
+			printk(KERN_INFO "%s: Link is down\n", dev->name);
+			priv->oldlink = 0;
+			priv->oldspeed = 0;
+			priv->oldduplex = -1;
+			netif_carrier_off(dev);
+		}
+	}
+}
+
+
+/* Update the hash table based on the current list of multicast
+ * addresses we subscribe to.  Also, change the promiscuity of
+ * the device based on the flags (this function is called
+ * whenever dev->flags is changed */
+static void gfar_set_multi(struct net_device *dev)
+{
+	struct dev_mc_list *mc_ptr;
+	struct gfar_private *priv = netdev_priv(dev);
+	struct gfar *regs = priv->regs;
+	u32 tempval;
+
+	if(dev->flags & IFF_PROMISC) {
+		printk(KERN_INFO "%s: Entering promiscuous mode.\n",
+				dev->name);
+		/* Set RCTRL to PROM */
+		tempval = gfar_read(&regs->rctrl);
+		tempval |= RCTRL_PROM;
+		gfar_write(&regs->rctrl, tempval);
+	} else {
+		/* Set RCTRL to not PROM */
+		tempval = gfar_read(&regs->rctrl);
+		tempval &= ~(RCTRL_PROM);
+		gfar_write(&regs->rctrl, tempval);
+	}
+	
+	if(dev->flags & IFF_ALLMULTI) {
+		/* Set the hash to rx all multicast frames */
+		gfar_write(&regs->gaddr0, 0xffffffff);
+		gfar_write(&regs->gaddr1, 0xffffffff);
+		gfar_write(&regs->gaddr2, 0xffffffff);
+		gfar_write(&regs->gaddr3, 0xffffffff);
+		gfar_write(&regs->gaddr4, 0xffffffff);
+		gfar_write(&regs->gaddr5, 0xffffffff);
+		gfar_write(&regs->gaddr6, 0xffffffff);
+		gfar_write(&regs->gaddr7, 0xffffffff);
+	} else {
+		/* zero out the hash */
+		gfar_write(&regs->gaddr0, 0x0);
+		gfar_write(&regs->gaddr1, 0x0);
+		gfar_write(&regs->gaddr2, 0x0);
+		gfar_write(&regs->gaddr3, 0x0);
+		gfar_write(&regs->gaddr4, 0x0);
+		gfar_write(&regs->gaddr5, 0x0);
+		gfar_write(&regs->gaddr6, 0x0);
+		gfar_write(&regs->gaddr7, 0x0);
+
+		if(dev->mc_count == 0)
+			return;
+
+		/* Parse the list, and set the appropriate bits */
+		for(mc_ptr = dev->mc_list; mc_ptr; mc_ptr = mc_ptr->next) {
+			gfar_set_hash_for_addr(dev, mc_ptr->dmi_addr);
+		}
+	}
+
+	return;
+}
+
+/* Set the appropriate hash bit for the given addr */
+/* The algorithm works like so:
+ * 1) Take the Destination Address (ie the multicast address), and
+ * do a CRC on it (little endian), and reverse the bits of the
+ * result.
+ * 2) Use the 8 most significant bits as a hash into a 256-entry
+ * table.  The table is controlled through 8 32-bit registers:
+ * gaddr0-7.  gaddr0's MSB is entry 0, and gaddr7's LSB is
+ * gaddr7.  This means that the 3 most significant bits in the
+ * hash index which gaddr register to use, and the 5 other bits
+ * indicate which bit (assuming an IBM numbering scheme, which
+ * for PowerPC (tm) is usually the case) in the register holds
+ * the entry. */
+static void gfar_set_hash_for_addr(struct net_device *dev, u8 *addr)
+{
+	u32 tempval;
+	struct gfar_private *priv = netdev_priv(dev);
+	struct gfar *regs = priv->regs;
+	u32 *hash = &regs->gaddr0;
+	u32 result = ether_crc(MAC_ADDR_LEN, addr);
+	u8 whichreg = ((result >> 29) & 0x7);
+	u8 whichbit = ((result >> 24) & 0x1f);
+	u32 value = (1 << (31-whichbit));
+
+	tempval = gfar_read(&hash[whichreg]);
+	tempval |= value;
+	gfar_write(&hash[whichreg], tempval);
+
+	return;
+}
+
+/* GFAR error interrupt handler */
+static irqreturn_t gfar_error(int irq, void *dev_id, struct pt_regs *regs)
+{
+	struct net_device *dev = dev_id;
+	struct gfar_private *priv = netdev_priv(dev);
+
+	/* Save ievent for future reference */
+	u32 events = gfar_read(&priv->regs->ievent);
+
+	/* Clear IEVENT */
+	gfar_write(&priv->regs->ievent, IEVENT_ERR_MASK);
+
+	/* Hmm... */
+#if defined (BRIEF_GFAR_ERRORS) || defined (VERBOSE_GFAR_ERRORS)
+	printk(KERN_DEBUG "%s: error interrupt (ievent=0x%08x imask=0x%08x)\n",
+	       dev->name, events, gfar_read(priv->regs->imask));
+#endif
+
+	/* Update the error counters */
+	if (events & IEVENT_TXE) {
+		priv->stats.tx_errors++;
+
+		if (events & IEVENT_LC)
+			priv->stats.tx_window_errors++;
+		if (events & IEVENT_CRL)
+			priv->stats.tx_aborted_errors++;
+		if (events & IEVENT_XFUN) {
+#ifdef VERBOSE_GFAR_ERRORS
+			printk(KERN_DEBUG "%s: underrun.  packet dropped.\n",
+			       dev->name);
+#endif
+			priv->stats.tx_dropped++;
+			priv->extra_stats.tx_underrun++;
+
+			/* Reactivate the Tx Queues */
+			gfar_write(&priv->regs->tstat, TSTAT_CLEAR_THALT);
+		}
+#ifdef VERBOSE_GFAR_ERRORS
+		printk(KERN_DEBUG "%s: Transmit Error\n", dev->name);
+#endif
+	}
+	if (events & IEVENT_BSY) {
+		priv->stats.rx_errors++;
+		priv->extra_stats.rx_bsy++;
+
+		gfar_receive(irq, dev_id, regs);
+
+#ifndef CONFIG_GFAR_NAPI
+		/* Clear the halt bit in RSTAT */
+		gfar_write(&priv->regs->rstat, RSTAT_CLEAR_RHALT);
+#endif
+
+#ifdef VERBOSE_GFAR_ERRORS
+		printk(KERN_DEBUG "%s: busy error (rhalt: %x)\n", dev->name,
+		       gfar_read(priv->regs->rstat));
+#endif
+	}
+	if (events & IEVENT_BABR) {
+		priv->stats.rx_errors++;
+		priv->extra_stats.rx_babr++;
+
+#ifdef VERBOSE_GFAR_ERRORS
+		printk(KERN_DEBUG "%s: babbling error\n", dev->name);
+#endif
+	}
+	if (events & IEVENT_EBERR) {
+		priv->extra_stats.eberr++;
+#ifdef VERBOSE_GFAR_ERRORS
+		printk(KERN_DEBUG "%s: EBERR\n", dev->name);
+#endif
+	}
+	if (events & IEVENT_RXC)
+#ifdef VERBOSE_GFAR_ERRORS
+		printk(KERN_DEBUG "%s: control frame\n", dev->name);
+#endif
+
+	if (events & IEVENT_BABT) {
+		priv->extra_stats.tx_babt++;
+#ifdef VERBOSE_GFAR_ERRORS
+		printk(KERN_DEBUG "%s: babt error\n", dev->name);
+#endif
+	}
+	return IRQ_HANDLED;
+}
+
+/* Structure for a device driver */
+static struct ocp_device_id gfar_ids[] = {
+	{.vendor = OCP_ANY_ID,.function = OCP_FUNC_GFAR},
+	{.vendor = OCP_VENDOR_INVALID}
+};
+
+static struct ocp_driver gfar_driver = {
+	.name = "gianfar",
+	.id_table = gfar_ids,
+
+	.probe = gfar_probe,
+	.remove = gfar_remove,
+};
+
+static int __init gfar_init(void)
+{
+	int rc;
+
+	rc = ocp_register_driver(&gfar_driver);
+	if (rc != 0) {
+		ocp_unregister_driver(&gfar_driver);
+		return -ENODEV;
+	}
+
+	return 0;
+}
+
+static void __exit gfar_exit(void)
+{
+	ocp_unregister_driver(&gfar_driver);
+}
+
+module_init(gfar_init);
+module_exit(gfar_exit);
diff -Nru a/drivers/net/gianfar.h b/drivers/net/gianfar.h
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/drivers/net/gianfar.h	2004-10-18 14:57:24 -07:00
@@ -0,0 +1,535 @@
+/* 
+ * drivers/net/gianfar.h
+ *
+ * Gianfar Ethernet Driver
+ * Driver for FEC on MPC8540 and TSEC on MPC8540/MPC8560
+ * Based on 8260_io/fcc_enet.c
+ *
+ * Author: Andy Fleming
+ * Maintainer: Kumar Gala (kumar.gala@freescale.com)
+ *
+ * Copyright (c) 2002-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.
+ *
+ *  Still left to do:
+ *      -Add support for module parameters
+ *	-Add support for ethtool -s
+ *	-Add patch for ethtool phys id
+ */
+#ifndef __GIANFAR_H
+#define __GIANFAR_H
+
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/string.h>
+#include <linux/errno.h>
+#include <linux/slab.h>
+#include <linux/interrupt.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/skbuff.h>
+#include <linux/spinlock.h>
+#include <linux/mm.h>
+
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/uaccess.h>
+#include <linux/module.h>
+#include <linux/version.h>
+#include <linux/crc32.h>
+#include <linux/workqueue.h>
+#include <linux/ethtool.h>
+#include <linux/netdevice.h>
+#include <asm/ocp.h>
+#include "gianfar_phy.h"
+
+/* The maximum number of packets to be handled in one call of gfar_poll */
+#define GFAR_DEV_WEIGHT 64
+
+/* Number of bytes to align the rx bufs to */
+#define RXBUF_ALIGNMENT 64
+
+/* The number of bytes which composes a unit for the purpose of
+ * allocating data buffers.  ie-for any given MTU, the data buffer
+ * will be the next highest multiple of 512 bytes. */
+#define INCREMENTAL_BUFFER_SIZE 512
+
+
+#define MAC_ADDR_LEN 6
+
+#define PHY_INIT_TIMEOUT 100000
+#define GFAR_PHY_CHANGE_TIME 2
+
+#define DEVICE_NAME "%s: Gianfar Ethernet Controller Version 1.1, "
+#define DRV_NAME "gfar-enet"
+extern const char gfar_driver_name[];
+extern const char gfar_driver_version[];
+
+/* These need to be powers of 2 for this driver */
+#ifdef CONFIG_GFAR_NAPI
+#define DEFAULT_TX_RING_SIZE	256
+#define DEFAULT_RX_RING_SIZE	256
+#else
+#define DEFAULT_TX_RING_SIZE    64
+#define DEFAULT_RX_RING_SIZE    64
+#endif
+
+#define GFAR_RX_MAX_RING_SIZE   256
+#define GFAR_TX_MAX_RING_SIZE   256
+
+#define DEFAULT_RX_BUFFER_SIZE  1536
+#define TX_RING_MOD_MASK(size) (size-1)
+#define RX_RING_MOD_MASK(size) (size-1)
+#define JUMBO_BUFFER_SIZE 9728
+#define JUMBO_FRAME_SIZE 9600
+
+/* Latency of interface clock in nanoseconds */
+/* Interface clock latency , in this case, means the 
+ * time described by a value of 1 in the interrupt
+ * coalescing registers' time fields.  Since those fields
+ * refer to the time it takes for 64 clocks to pass, the
+ * latencies are as such:
+ * GBIT = 125MHz => 8ns/clock => 8*64 ns / tick
+ * 100 = 25 MHz => 40ns/clock => 40*64 ns / tick
+ * 10 = 2.5 MHz => 400ns/clock => 400*64 ns / tick
+ */
+#define GFAR_GBIT_TIME  512
+#define GFAR_100_TIME   2560
+#define GFAR_10_TIME    25600
+
+#define DEFAULT_TX_COALESCE 1
+#define DEFAULT_TXCOUNT	16
+#define DEFAULT_TXTIME	400
+
+#define DEFAULT_RX_COALESCE 1
+#define DEFAULT_RXCOUNT	16
+#define DEFAULT_RXTIME	400
+
+#define TBIPA_VALUE		0x1f
+#define MIIMCFG_INIT_VALUE	0x00000007
+#define MIIMCFG_RESET           0x80000000
+#define MIIMIND_BUSY            0x00000001
+
+/* MAC register bits */
+#define MACCFG1_SOFT_RESET	0x80000000
+#define MACCFG1_RESET_RX_MC	0x00080000
+#define MACCFG1_RESET_TX_MC	0x00040000
+#define MACCFG1_RESET_RX_FUN	0x00020000
+#define	MACCFG1_RESET_TX_FUN	0x00010000
+#define MACCFG1_LOOPBACK	0x00000100
+#define MACCFG1_RX_FLOW		0x00000020
+#define MACCFG1_TX_FLOW		0x00000010
+#define MACCFG1_SYNCD_RX_EN	0x00000008
+#define MACCFG1_RX_EN		0x00000004
+#define MACCFG1_SYNCD_TX_EN	0x00000002
+#define MACCFG1_TX_EN		0x00000001
+
+#define MACCFG2_INIT_SETTINGS	0x00007205
+#define MACCFG2_FULL_DUPLEX	0x00000001
+#define MACCFG2_IF              0x00000300
+#define MACCFG2_MII             0x00000100
+#define MACCFG2_GMII            0x00000200
+#define MACCFG2_HUGEFRAME	0x00000020
+#define MACCFG2_LENGTHCHECK	0x00000010
+
+#define ECNTRL_INIT_SETTINGS	0x00001000
+#define ECNTRL_TBI_MODE         0x00000020
+
+#define MRBLR_INIT_SETTINGS	DEFAULT_RX_BUFFER_SIZE
+
+#define MINFLR_INIT_SETTINGS	0x00000040
+
+/* Init to do tx snooping for buffers and descriptors */
+#define DMACTRL_INIT_SETTINGS   0x000000c3
+#define DMACTRL_GRS             0x00000010
+#define DMACTRL_GTS             0x00000008
+
+#define TSTAT_CLEAR_THALT       0x80000000
+
+/* Interrupt coalescing macros */
+#define IC_ICEN			0x80000000
+#define IC_ICFT_MASK		0x1fe00000
+#define IC_ICFT_SHIFT		21
+#define mk_ic_icft(x)		\
+	(((unsigned int)x << IC_ICFT_SHIFT)&IC_ICFT_MASK)
+#define IC_ICTT_MASK		0x0000ffff
+#define mk_ic_ictt(x)		(x&IC_ICTT_MASK)
+
+#define mk_ic_value(count, time) (IC_ICEN | \
+				mk_ic_icft(count) | \
+				mk_ic_ictt(time))
+
+#define RCTRL_PROM		0x00000008
+#define RSTAT_CLEAR_RHALT       0x00800000
+
+#define IEVENT_INIT_CLEAR	0xffffffff
+#define IEVENT_BABR		0x80000000
+#define IEVENT_RXC		0x40000000
+#define IEVENT_BSY		0x20000000
+#define IEVENT_EBERR		0x10000000
+#define IEVENT_MSRO		0x04000000
+#define IEVENT_GTSC		0x02000000
+#define IEVENT_BABT		0x01000000
+#define IEVENT_TXC		0x00800000
+#define IEVENT_TXE		0x00400000
+#define IEVENT_TXB		0x00200000
+#define IEVENT_TXF		0x00100000
+#define IEVENT_LC		0x00040000
+#define IEVENT_CRL		0x00020000
+#define IEVENT_XFUN		0x00010000
+#define IEVENT_RXB0		0x00008000
+#define IEVENT_GRSC		0x00000100
+#define IEVENT_RXF0		0x00000080
+#define IEVENT_RX_MASK          (IEVENT_RXB0 | IEVENT_RXF0)
+#define IEVENT_TX_MASK          (IEVENT_TXB | IEVENT_TXF)
+#define IEVENT_ERR_MASK         \
+(IEVENT_RXC | IEVENT_BSY | IEVENT_EBERR | IEVENT_MSRO | \
+ IEVENT_BABT | IEVENT_TXC | IEVENT_TXE | IEVENT_LC \
+ | IEVENT_CRL | IEVENT_XFUN)
+
+#define IMASK_INIT_CLEAR	0x00000000
+#define IMASK_BABR              0x80000000
+#define IMASK_RXC               0x40000000
+#define IMASK_BSY               0x20000000
+#define IMASK_EBERR             0x10000000
+#define IMASK_MSRO		0x04000000
+#define IMASK_GRSC              0x02000000
+#define IMASK_BABT		0x01000000
+#define IMASK_TXC               0x00800000
+#define IMASK_TXEEN		0x00400000
+#define IMASK_TXBEN		0x00200000
+#define IMASK_TXFEN             0x00100000
+#define IMASK_LC		0x00040000
+#define IMASK_CRL		0x00020000
+#define IMASK_XFUN		0x00010000
+#define IMASK_RXB0              0x00008000
+#define IMASK_GTSC              0x00000100
+#define IMASK_RXFEN0		0x00000080
+#define IMASK_RX_DISABLED ~(IMASK_RXFEN0 | IMASK_BSY)
+#define IMASK_DEFAULT  (IMASK_TXEEN | IMASK_TXFEN | IMASK_TXBEN | \
+		IMASK_RXFEN0 | IMASK_BSY | IMASK_EBERR | IMASK_BABR | \
+		IMASK_XFUN | IMASK_RXC | IMASK_BABT)
+
+
+/* Attribute fields */
+
+/* This enables rx snooping for buffers and descriptors */
+#ifdef CONFIG_GFAR_BDSTASH
+#define ATTR_BDSTASH		0x00000800
+#else
+#define ATTR_BDSTASH		0x00000000
+#endif
+
+#ifdef CONFIG_GFAR_BUFSTASH
+#define ATTR_BUFSTASH		0x00004000
+#define STASH_LENGTH		64
+#else
+#define ATTR_BUFSTASH		0x00000000
+#endif
+
+#define ATTR_SNOOPING		0x000000c0
+#define ATTR_INIT_SETTINGS      (ATTR_SNOOPING \
+		| ATTR_BDSTASH | ATTR_BUFSTASH)
+
+#define ATTRELI_INIT_SETTINGS   0x0
+
+
+/* TxBD status field bits */
+#define TXBD_READY		0x8000
+#define TXBD_PADCRC		0x4000
+#define TXBD_WRAP		0x2000
+#define TXBD_INTERRUPT		0x1000
+#define TXBD_LAST		0x0800
+#define TXBD_CRC		0x0400
+#define TXBD_DEF		0x0200
+#define TXBD_HUGEFRAME		0x0080
+#define TXBD_LATECOLLISION	0x0080
+#define TXBD_RETRYLIMIT		0x0040
+#define	TXBD_RETRYCOUNTMASK	0x003c
+#define TXBD_UNDERRUN		0x0002
+
+/* RxBD status field bits */
+#define RXBD_EMPTY		0x8000
+#define RXBD_RO1		0x4000
+#define RXBD_WRAP		0x2000
+#define RXBD_INTERRUPT		0x1000
+#define RXBD_LAST		0x0800
+#define RXBD_FIRST		0x0400
+#define RXBD_MISS		0x0100
+#define RXBD_BROADCAST		0x0080
+#define RXBD_MULTICAST		0x0040
+#define RXBD_LARGE		0x0020
+#define RXBD_NONOCTET		0x0010
+#define RXBD_SHORT		0x0008
+#define RXBD_CRCERR		0x0004
+#define RXBD_OVERRUN		0x0002
+#define RXBD_TRUNCATED		0x0001
+#define RXBD_STATS		0x01ff
+
+struct txbd8
+{
+	u16	status;	/* Status Fields */
+	u16	length;	/* Buffer length */
+	u32	bufPtr;	/* Buffer Pointer */
+};
+
+struct rxbd8
+{
+	u16	status;	/* Status Fields */
+	u16	length;	/* Buffer Length */
+	u32	bufPtr;	/* Buffer Pointer */
+};
+
+struct rmon_mib
+{
+	u32	tr64;	/* 0x.680 - Transmit and Receive 64-byte Frame Counter */
+	u32	tr127;	/* 0x.684 - Transmit and Receive 65-127 byte Frame Counter */
+	u32	tr255;	/* 0x.688 - Transmit and Receive 128-255 byte Frame Counter */
+	u32	tr511;	/* 0x.68c - Transmit and Receive 256-511 byte Frame Counter */
+	u32	tr1k;	/* 0x.690 - Transmit and Receive 512-1023 byte Frame Counter */
+	u32	trmax;	/* 0x.694 - Transmit and Receive 1024-1518 byte Frame Counter */
+	u32	trmgv;	/* 0x.698 - Transmit and Receive 1519-1522 byte Good VLAN Frame */
+	u32	rbyt;	/* 0x.69c - Receive Byte Counter */
+	u32	rpkt;	/* 0x.6a0 - Receive Packet Counter */
+	u32	rfcs;	/* 0x.6a4 - Receive FCS Error Counter */
+	u32	rmca;	/* 0x.6a8 - Receive Multicast Packet Counter */
+	u32	rbca;	/* 0x.6ac - Receive Broadcast Packet Counter */
+	u32	rxcf;	/* 0x.6b0 - Receive Control Frame Packet Counter */
+	u32	rxpf;	/* 0x.6b4 - Receive Pause Frame Packet Counter */
+	u32	rxuo;	/* 0x.6b8 - Receive Unknown OP Code Counter */
+	u32	raln;	/* 0x.6bc - Receive Alignment Error Counter */
+	u32	rflr;	/* 0x.6c0 - Receive Frame Length Error Counter */
+	u32	rcde;	/* 0x.6c4 - Receive Code Error Counter */
+	u32	rcse;	/* 0x.6c8 - Receive Carrier Sense Error Counter */
+	u32	rund;	/* 0x.6cc - Receive Undersize Packet Counter */
+	u32	rovr;	/* 0x.6d0 - Receive Oversize Packet Counter */
+	u32	rfrg;	/* 0x.6d4 - Receive Fragments Counter */
+	u32	rjbr;	/* 0x.6d8 - Receive Jabber Counter */
+	u32	rdrp;	/* 0x.6dc - Receive Drop Counter */
+	u32	tbyt;	/* 0x.6e0 - Transmit Byte Counter Counter */
+	u32	tpkt;	/* 0x.6e4 - Transmit Packet Counter */
+	u32	tmca;	/* 0x.6e8 - Transmit Multicast Packet Counter */
+	u32	tbca;	/* 0x.6ec - Transmit Broadcast Packet Counter */
+	u32	txpf;	/* 0x.6f0 - Transmit Pause Control Frame Counter */
+	u32	tdfr;	/* 0x.6f4 - Transmit Deferral Packet Counter */
+	u32	tedf;	/* 0x.6f8 - Transmit Excessive Deferral Packet Counter */
+	u32	tscl;	/* 0x.6fc - Transmit Single Collision Packet Counter */
+	u32	tmcl;	/* 0x.700 - Transmit Multiple Collision Packet Counter */
+	u32	tlcl;	/* 0x.704 - Transmit Late Collision Packet Counter */
+	u32	txcl;	/* 0x.708 - Transmit Excessive Collision Packet Counter */
+	u32	tncl;	/* 0x.70c - Transmit Total Collision Counter */
+	u8	res1[4];
+	u32	tdrp;	/* 0x.714 - Transmit Drop Frame Counter */
+	u32	tjbr;	/* 0x.718 - Transmit Jabber Frame Counter */
+	u32	tfcs;	/* 0x.71c - Transmit FCS Error Counter */
+	u32	txcf;	/* 0x.720 - Transmit Control Frame Counter */
+	u32	tovr;	/* 0x.724 - Transmit Oversize Frame Counter */
+	u32	tund;	/* 0x.728 - Transmit Undersize Frame Counter */
+	u32	tfrg;	/* 0x.72c - Transmit Fragments Frame Counter */
+	u32	car1;	/* 0x.730 - Carry Register One */
+	u32	car2;	/* 0x.734 - Carry Register Two */
+	u32	cam1;	/* 0x.738 - Carry Mask Register One */
+	u32	cam2;	/* 0x.73c - Carry Mask Register Two */
+};
+
+struct gfar_extra_stats {
+	u64 kernel_dropped;
+	u64 rx_large;
+	u64 rx_short;
+	u64 rx_nonoctet;
+	u64 rx_crcerr;
+	u64 rx_overrun;
+	u64 rx_bsy;
+	u64 rx_babr;
+	u64 rx_trunc;
+	u64 eberr;
+	u64 tx_babt;
+	u64 tx_underrun;
+	u64 rx_skbmissing;
+	u64 tx_timeout;
+};
+
+#define GFAR_RMON_LEN ((sizeof(struct rmon_mib) - 16)/sizeof(u32))
+#define GFAR_EXTRA_STATS_LEN (sizeof(struct gfar_extra_stats)/sizeof(u64))
+
+/* Number of stats in the stats structure (ignore car and cam regs)*/
+#define GFAR_STATS_LEN (GFAR_RMON_LEN + GFAR_EXTRA_STATS_LEN)
+
+#define GFAR_INFOSTR_LEN 32
+
+struct gfar_stats {
+	u64 extra[GFAR_EXTRA_STATS_LEN];
+	u64 rmon[GFAR_RMON_LEN];
+};
+
+
+struct gfar {
+	u8	res1[16];
+	u32	ievent;			/* 0x.010 - Interrupt Event Register */
+	u32	imask;			/* 0x.014 - Interrupt Mask Register */
+	u32	edis;			/* 0x.018 - Error Disabled Register */
+	u8	res2[4];
+	u32	ecntrl;			/* 0x.020 - Ethernet Control Register */
+	u32	minflr;			/* 0x.024 - Minimum Frame Length Register */
+	u32	ptv;			/* 0x.028 - Pause Time Value Register */
+	u32	dmactrl;		/* 0x.02c - DMA Control Register */
+	u32	tbipa;			/* 0x.030 - TBI PHY Address Register */
+	u8	res3[88];
+	u32	fifo_tx_thr;		/* 0x.08c - FIFO transmit threshold register */
+	u8	res4[8];
+	u32	fifo_tx_starve;		/* 0x.098 - FIFO transmit starve register */
+	u32	fifo_tx_starve_shutoff;	/* 0x.09c - FIFO transmit starve shutoff register */
+	u8	res5[96];
+	u32	tctrl;			/* 0x.100 - Transmit Control Register */
+	u32	tstat;			/* 0x.104 - Transmit Status Register */
+	u8	res6[4];
+	u32	tbdlen;			/* 0x.10c - Transmit Buffer Descriptor Data Length Register */
+	u32	txic;			/* 0x.110 - Transmit Interrupt Coalescing Configuration Register */
+	u8	res7[16];
+	u32	ctbptr;			/* 0x.124 - Current Transmit Buffer Descriptor Pointer Register */
+	u8	res8[92];
+	u32	tbptr;			/* 0x.184 - Transmit Buffer Descriptor Pointer Low Register */
+	u8	res9[124];
+	u32	tbase;			/* 0x.204 - Transmit Descriptor Base Address Register */
+	u8	res10[168];
+	u32	ostbd;			/* 0x.2b0 - Out-of-Sequence Transmit Buffer Descriptor Register */
+	u32	ostbdp;			/* 0x.2b4 - Out-of-Sequence Transmit Data Buffer Pointer Register */
+	u8	res11[72];
+	u32	rctrl;			/* 0x.300 - Receive Control Register */
+	u32	rstat;			/* 0x.304 - Receive Status Register */
+	u8	res12[4];
+	u32	rbdlen;			/* 0x.30c - RxBD Data Length Register */
+	u32	rxic;			/* 0x.310 - Receive Interrupt Coalescing Configuration Register */
+	u8	res13[16];
+	u32	crbptr;			/* 0x.324 - Current Receive Buffer Descriptor Pointer */
+	u8	res14[24];
+	u32	mrblr;			/* 0x.340 - Maximum Receive Buffer Length Register */
+	u8	res15[64];
+	u32	rbptr;			/* 0x.384 - Receive Buffer Descriptor Pointer */
+	u8	res16[124];
+	u32	rbase;			/* 0x.404 - Receive Descriptor Base Address */
+	u8	res17[248];
+	u32	maccfg1;		/* 0x.500 - MAC Configuration 1 Register */
+	u32	maccfg2;		/* 0x.504 - MAC Configuration 2 Register */
+	u32	ipgifg;			/* 0x.508 - Inter Packet Gap/Inter Frame Gap Register */
+	u32	hafdup;			/* 0x.50c - Half Duplex Register */
+	u32	maxfrm;			/* 0x.510 - Maximum Frame Length Register */
+	u8	res18[12];
+	u32	miimcfg;		/* 0x.520 - MII Management Configuration Register */
+	u32	miimcom;		/* 0x.524 - MII Management Command Register */
+	u32	miimadd;		/* 0x.528 - MII Management Address Register */
+	u32	miimcon;		/* 0x.52c - MII Management Control Register */
+	u32	miimstat;		/* 0x.530 - MII Management Status Register */
+	u32	miimind;		/* 0x.534 - MII Management Indicator Register */
+	u8	res19[4];
+	u32	ifstat;			/* 0x.53c - Interface Status Register */
+	u32	macstnaddr1;		/* 0x.540 - Station Address Part 1 Register */
+	u32	macstnaddr2;		/* 0x.544 - Station Address Part 2 Register */
+	u8	res20[312];
+	struct rmon_mib	rmon;
+	u8	res21[192];
+	u32	iaddr0;			/* 0x.800 - Indivdual address register 0 */
+	u32	iaddr1;			/* 0x.804 - Indivdual address register 1 */
+	u32	iaddr2;			/* 0x.808 - Indivdual address register 2 */
+	u32	iaddr3;			/* 0x.80c - Indivdual address register 3 */
+	u32	iaddr4;			/* 0x.810 - Indivdual address register 4 */
+	u32	iaddr5;			/* 0x.814 - Indivdual address register 5 */
+	u32	iaddr6;			/* 0x.818 - Indivdual address register 6 */
+	u32	iaddr7;			/* 0x.81c - Indivdual address register 7 */
+	u8	res22[96];
+	u32	gaddr0;			/* 0x.880 - Global address register 0 */
+	u32	gaddr1;			/* 0x.884 - Global address register 1 */
+	u32	gaddr2;			/* 0x.888 - Global address register 2 */
+	u32	gaddr3;			/* 0x.88c - Global address register 3 */
+	u32	gaddr4;			/* 0x.890 - Global address register 4 */
+	u32	gaddr5;			/* 0x.894 - Global address register 5 */
+	u32	gaddr6;			/* 0x.898 - Global address register 6 */
+	u32	gaddr7;			/* 0x.89c - Global address register 7 */
+	u8	res23[856];
+	u32	attr;			/* 0x.bf8 - Attributes Register */
+	u32	attreli;		/* 0x.bfc - Attributes Extract Length and Extract Index Register */
+	u8	res24[1024];
+
+};
+
+/* Struct stolen almost completely (and shamelessly) from the FCC enet source
+ * (Ok, that's not so true anymore, but there is a family resemblence)
+ * The GFAR buffer descriptors track the ring buffers.  The rx_bd_base
+ * and tx_bd_base always point to the currently available buffer.
+ * The dirty_tx tracks the current buffer that is being sent by the
+ * controller.  The cur_tx and dirty_tx are equal under both completely
+ * empty and completely full conditions.  The empty/ready indicator in
+ * the buffer descriptor determines the actual condition.
+ */
+struct gfar_private {
+	/* pointers to arrays of skbuffs for tx and rx */
+	struct sk_buff ** tx_skbuff;
+	struct sk_buff ** rx_skbuff;
+
+	/* indices pointing to the next free sbk in skb arrays */
+	u16 skb_curtx;
+	u16 skb_currx;
+
+	/* index of the first skb which hasn't been transmitted
+	 * yet. */
+	u16 skb_dirtytx;
+
+	/* Configuration info for the coalescing features */
+	unsigned char txcoalescing;
+	unsigned short txcount;
+	unsigned short txtime;
+	unsigned char rxcoalescing;
+	unsigned short rxcount;
+	unsigned short rxtime;
+
+	/* GFAR addresses */
+	struct rxbd8 *rx_bd_base;	/* Base addresses of Rx and Tx Buffers */
+	struct txbd8 *tx_bd_base;
+	struct rxbd8 *cur_rx;           /* Next free rx ring entry */
+	struct txbd8 *cur_tx;	        /* Next free ring entry */
+	struct txbd8 *dirty_tx;		/* The Ring entry to be freed. */
+	struct gfar *regs;	/* Pointer to the GFAR memory mapped Registers */
+	struct gfar *phyregs;
+	struct work_struct tq;
+	struct timer_list phy_info_timer;
+	struct net_device_stats stats; /* linux network statistics */
+	struct gfar_extra_stats extra_stats;
+	spinlock_t lock;
+	unsigned int rx_buffer_size;
+	unsigned int rx_stash_size;
+	unsigned int tx_ring_size;
+	unsigned int rx_ring_size;
+	wait_queue_head_t rxcleanupq;
+	unsigned int rxclean;
+
+	/* Info structure initialized by board setup code */
+	struct ocp_gfar_data *einfo;
+
+	struct gfar_mii_info *mii_info;
+	int oldspeed;
+	int oldduplex;
+	int oldlink;
+};
+
+extern inline u32 gfar_read(volatile unsigned *addr)
+{
+	u32 val;
+	val = in_be32(addr);
+	return val;
+}
+
+extern inline void gfar_write(volatile unsigned *addr, u32 val)
+{
+	out_be32(addr, val);
+}
+
+extern struct ethtool_ops *gfar_op_array[];
+
+#endif /* __GIANFAR_H */
diff -Nru a/drivers/net/gianfar_ethtool.c b/drivers/net/gianfar_ethtool.c
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/drivers/net/gianfar_ethtool.c	2004-10-18 14:57:23 -07:00
@@ -0,0 +1,525 @@
+/*
+ *  drivers/net/gianfar_ethtool.c
+ *
+ *  Gianfar Ethernet Driver
+ *  Ethtool support for Gianfar Enet
+ *  Based on e1000 ethtool support
+ *
+ *  Author: Andy Fleming
+ *  Maintainer: Kumar Gala (kumar.gala@freescale.com)
+ *
+ *  Copyright (c) 2003,2004 Freescale Semiconductor, Inc.
+ *
+ *  This software may be used and distributed according to 
+ *  the terms of the GNU Public License, Version 2, incorporated herein 
+ *  by reference.
+ */
+
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/string.h>
+#include <linux/errno.h>
+#include <linux/slab.h>
+#include <linux/interrupt.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/skbuff.h>
+#include <linux/spinlock.h>
+#include <linux/mm.h>
+
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/uaccess.h>
+#include <linux/module.h>
+#include <linux/version.h>
+#include <linux/crc32.h>
+#include <asm/types.h>
+#include <asm/uaccess.h>
+#include <linux/ethtool.h>
+
+#include "gianfar.h"
+
+#define is_power_of_2(x)        ((x) != 0 && (((x) & ((x) - 1)) == 0))
+
+extern int startup_gfar(struct net_device *dev);
+extern void stop_gfar(struct net_device *dev);
+extern void gfar_receive(int irq, void *dev_id, struct pt_regs *regs);
+
+void gfar_fill_stats(struct net_device *dev, struct ethtool_stats *dummy,
+		     u64 * buf);
+void gfar_gstrings(struct net_device *dev, u32 stringset, u8 * buf);
+int gfar_gcoalesce(struct net_device *dev, struct ethtool_coalesce *cvals);
+int gfar_scoalesce(struct net_device *dev, struct ethtool_coalesce *cvals);
+void gfar_gringparam(struct net_device *dev, struct ethtool_ringparam *rvals);
+int gfar_sringparam(struct net_device *dev, struct ethtool_ringparam *rvals);
+void gfar_gdrvinfo(struct net_device *dev, struct ethtool_drvinfo *drvinfo);
+
+static char stat_gstrings[][ETH_GSTRING_LEN] = {
+	"rx-dropped-by-kernel",
+	"rx-large-frame-errors",
+	"rx-short-frame-errors",
+	"rx-non-octet-errors",
+	"rx-crc-errors",
+	"rx-overrun-errors",
+	"rx-busy-errors",
+	"rx-babbling-errors",
+	"rx-truncated-frames",
+	"ethernet-bus-error",
+	"tx-babbling-errors",
+	"tx-underrun-errors",
+	"rx-skb-missing-errors",
+	"tx-timeout-errors",
+	"tx-rx-64-frames",
+	"tx-rx-65-127-frames",
+	"tx-rx-128-255-frames",
+	"tx-rx-256-511-frames",
+	"tx-rx-512-1023-frames",
+	"tx-rx-1024-1518-frames",
+	"tx-rx-1519-1522-good-vlan",
+	"rx-bytes",
+	"rx-packets",
+	"rx-fcs-errors",
+	"receive-multicast-packet",
+	"receive-broadcast-packet",
+	"rx-control-frame-packets",
+	"rx-pause-frame-packets",
+	"rx-unknown-op-code",
+	"rx-alignment-error",
+	"rx-frame-length-error",
+	"rx-code-error",
+	"rx-carrier-sense-error",
+	"rx-undersize-packets",
+	"rx-oversize-packets",
+	"rx-fragmented-frames",
+	"rx-jabber-frames",
+	"rx-dropped-frames",
+	"tx-byte-counter",
+	"tx-packets",
+	"tx-multicast-packets",
+	"tx-broadcast-packets",
+	"tx-pause-control-frames",
+	"tx-deferral-packets",
+	"tx-excessive-deferral-packets",
+	"tx-single-collision-packets",
+	"tx-multiple-collision-packets",
+	"tx-late-collision-packets",
+	"tx-excessive-collision-packets",
+	"tx-total-collision",
+	"reserved",
+	"tx-dropped-frames",
+	"tx-jabber-frames",
+	"tx-fcs-errors",
+	"tx-control-frames",
+	"tx-oversize-frames",
+	"tx-undersize-frames",
+	"tx-fragmented-frames",
+};
+
+/* Fill in an array of 64-bit statistics from various sources.
+ * This array will be appended to the end of the ethtool_stats
+ * structure, and returned to user space
+ */
+void gfar_fill_stats(struct net_device *dev, struct ethtool_stats *dummy, u64 * buf)
+{
+	int i;
+	struct gfar_private *priv = netdev_priv(dev);
+	u32 *rmon = (u32 *) & priv->regs->rmon;
+	u64 *extra = (u64 *) & priv->extra_stats;
+	struct gfar_stats *stats = (struct gfar_stats *) buf;
+
+	for (i = 0; i < GFAR_RMON_LEN; i++) {
+		stats->rmon[i] = (u64) (rmon[i]);
+	}
+
+	for (i = 0; i < GFAR_EXTRA_STATS_LEN; i++) {
+		stats->extra[i] = extra[i];
+	}
+}
+
+/* Returns the number of stats (and their corresponding strings) */
+int gfar_stats_count(struct net_device *dev)
+{
+	return GFAR_STATS_LEN;
+}
+
+void gfar_gstrings_normon(struct net_device *dev, u32 stringset, u8 * buf)
+{
+	memcpy(buf, stat_gstrings, GFAR_EXTRA_STATS_LEN * ETH_GSTRING_LEN);
+}
+
+void gfar_fill_stats_normon(struct net_device *dev, 
+		struct ethtool_stats *dummy, u64 * buf)
+{
+	int i;
+	struct gfar_private *priv = netdev_priv(dev);
+	u64 *extra = (u64 *) & priv->extra_stats;
+
+	for (i = 0; i < GFAR_EXTRA_STATS_LEN; i++) {
+		buf[i] = extra[i];
+	}
+}
+
+
+int gfar_stats_count_normon(struct net_device *dev)
+{
+	return GFAR_EXTRA_STATS_LEN;
+}
+/* Fills in the drvinfo structure with some basic info */
+void gfar_gdrvinfo(struct net_device *dev, struct
+	      ethtool_drvinfo *drvinfo)
+{
+	strncpy(drvinfo->driver, DRV_NAME, GFAR_INFOSTR_LEN);
+	strncpy(drvinfo->version, gfar_driver_version, GFAR_INFOSTR_LEN);
+	strncpy(drvinfo->fw_version, "N/A", GFAR_INFOSTR_LEN);
+	strncpy(drvinfo->bus_info, "N/A", GFAR_INFOSTR_LEN);
+	drvinfo->n_stats = GFAR_STATS_LEN;
+	drvinfo->testinfo_len = 0;
+	drvinfo->regdump_len = 0;
+	drvinfo->eedump_len = 0;
+}
+
+/* Return the current settings in the ethtool_cmd structure */
+int gfar_gsettings(struct net_device *dev, struct ethtool_cmd *cmd)
+{
+	struct gfar_private *priv = netdev_priv(dev);
+	uint gigabit_support = 
+		priv->einfo->flags & GFAR_HAS_GIGABIT ? SUPPORTED_1000baseT_Full : 0;
+	uint gigabit_advert = 
+		priv->einfo->flags & GFAR_HAS_GIGABIT ? ADVERTISED_1000baseT_Full: 0;
+
+	cmd->supported = (SUPPORTED_10baseT_Half
+			  | SUPPORTED_100baseT_Half
+			  | SUPPORTED_100baseT_Full
+			  | gigabit_support | SUPPORTED_Autoneg);
+
+	/* For now, we always advertise everything */
+	cmd->advertising = (ADVERTISED_10baseT_Half
+			    | ADVERTISED_100baseT_Half
+			    | ADVERTISED_100baseT_Full
+			    | gigabit_advert | ADVERTISED_Autoneg);
+
+	cmd->speed = priv->mii_info->speed;
+	cmd->duplex = priv->mii_info->duplex;
+	cmd->port = PORT_MII;
+	cmd->phy_address = priv->mii_info->mii_id;
+	cmd->transceiver = XCVR_EXTERNAL;
+	cmd->autoneg = AUTONEG_ENABLE;
+	cmd->maxtxpkt = priv->txcount;
+	cmd->maxrxpkt = priv->rxcount;
+
+	return 0;
+}
+
+/* Return the length of the register structure */
+int gfar_reglen(struct net_device *dev)
+{
+	return sizeof (struct gfar);
+}
+
+/* Return a dump of the GFAR register space */
+void gfar_get_regs(struct net_device *dev, struct ethtool_regs *regs, void *regbuf)
+{
+	int i;
+	struct gfar_private *priv = netdev_priv(dev);
+	u32 *theregs = (u32 *) priv->regs;
+	u32 *buf = (u32 *) regbuf;
+
+	for (i = 0; i < sizeof (struct gfar) / sizeof (u32); i++)
+		buf[i] = theregs[i];
+}
+
+/* Fill in a buffer with the strings which correspond to the
+ * stats */
+void gfar_gstrings(struct net_device *dev, u32 stringset, u8 * buf)
+{
+	memcpy(buf, stat_gstrings, GFAR_STATS_LEN * ETH_GSTRING_LEN);
+}
+
+/* Convert microseconds to ethernet clock ticks, which changes
+ * depending on what speed the controller is running at */
+static unsigned int gfar_usecs2ticks(struct gfar_private *priv, unsigned int usecs)
+{
+	unsigned int count;
+
+	/* The timer is different, depending on the interface speed */
+	switch (priv->mii_info->speed) {
+	case 1000:
+		count = GFAR_GBIT_TIME;
+		break;
+	case 100:
+		count = GFAR_100_TIME;
+		break;
+	case 10:
+	default:
+		count = GFAR_10_TIME;
+		break;
+	}
+
+	/* Make sure we return a number greater than 0
+	 * if usecs > 0 */
+	return ((usecs * 1000 + count - 1) / count);
+}
+
+/* Convert ethernet clock ticks to microseconds */
+static unsigned int gfar_ticks2usecs(struct gfar_private *priv, unsigned int ticks)
+{
+	unsigned int count;
+
+	/* The timer is different, depending on the interface speed */
+	switch (priv->mii_info->speed) {
+	case 1000:
+		count = GFAR_GBIT_TIME;
+		break;
+	case 100:
+		count = GFAR_100_TIME;
+		break;
+	case 10:
+	default:
+		count = GFAR_10_TIME;
+		break;
+	}
+
+	/* Make sure we return a number greater than 0 */
+	/* if ticks is > 0 */
+	return ((ticks * count) / 1000);
+}
+
+/* Get the coalescing parameters, and put them in the cvals
+ * structure.  */
+int gfar_gcoalesce(struct net_device *dev, struct ethtool_coalesce *cvals)
+{
+	struct gfar_private *priv = netdev_priv(dev);
+
+	cvals->rx_coalesce_usecs = gfar_ticks2usecs(priv, priv->rxtime);
+	cvals->rx_max_coalesced_frames = priv->rxcount;
+
+	cvals->tx_coalesce_usecs = gfar_ticks2usecs(priv, priv->txtime);
+	cvals->tx_max_coalesced_frames = priv->txcount;
+
+	cvals->use_adaptive_rx_coalesce = 0;
+	cvals->use_adaptive_tx_coalesce = 0;
+
+	cvals->pkt_rate_low = 0;
+	cvals->rx_coalesce_usecs_low = 0;
+	cvals->rx_max_coalesced_frames_low = 0;
+	cvals->tx_coalesce_usecs_low = 0;
+	cvals->tx_max_coalesced_frames_low = 0;
+
+	/* When the packet rate is below pkt_rate_high but above
+	 * pkt_rate_low (both measured in packets per second) the
+	 * normal {rx,tx}_* coalescing parameters are used.
+	 */
+
+	/* When the packet rate is (measured in packets per second)
+	 * is above pkt_rate_high, the {rx,tx}_*_high parameters are
+	 * used.
+	 */
+	cvals->pkt_rate_high = 0;
+	cvals->rx_coalesce_usecs_high = 0;
+	cvals->rx_max_coalesced_frames_high = 0;
+	cvals->tx_coalesce_usecs_high = 0;
+	cvals->tx_max_coalesced_frames_high = 0;
+
+	/* How often to do adaptive coalescing packet rate sampling,
+	 * measured in seconds.  Must not be zero.
+	 */
+	cvals->rate_sample_interval = 0;
+
+	return 0;
+}
+
+/* Change the coalescing values.
+ * Both cvals->*_usecs and cvals->*_frames have to be > 0
+ * in order for coalescing to be active
+ */
+int gfar_scoalesce(struct net_device *dev, struct ethtool_coalesce *cvals)
+{
+	struct gfar_private *priv = netdev_priv(dev);
+
+	/* Set up rx coalescing */
+	if ((cvals->rx_coalesce_usecs == 0) ||
+	    (cvals->rx_max_coalesced_frames == 0))
+		priv->rxcoalescing = 0;
+	else
+		priv->rxcoalescing = 1;
+
+	priv->rxtime = gfar_usecs2ticks(priv, cvals->rx_coalesce_usecs);
+	priv->rxcount = cvals->rx_max_coalesced_frames;
+
+	/* Set up tx coalescing */
+	if ((cvals->tx_coalesce_usecs == 0) ||
+	    (cvals->tx_max_coalesced_frames == 0))
+		priv->txcoalescing = 0;
+	else
+		priv->txcoalescing = 1;
+
+	priv->txtime = gfar_usecs2ticks(priv, cvals->tx_coalesce_usecs);
+	priv->txcount = cvals->tx_max_coalesced_frames;
+
+	if (priv->rxcoalescing)
+		gfar_write(&priv->regs->rxic,
+			   mk_ic_value(priv->rxcount, priv->rxtime));
+	else
+		gfar_write(&priv->regs->rxic, 0);
+
+	if (priv->txcoalescing)
+		gfar_write(&priv->regs->txic,
+			   mk_ic_value(priv->txcount, priv->txtime));
+	else
+		gfar_write(&priv->regs->txic, 0);
+
+	return 0;
+}
+
+/* Fills in rvals with the current ring parameters.  Currently,
+ * rx, rx_mini, and rx_jumbo rings are the same size, as mini and
+ * jumbo are ignored by the driver */
+void gfar_gringparam(struct net_device *dev, struct ethtool_ringparam *rvals)
+{
+	struct gfar_private *priv = netdev_priv(dev);
+
+	rvals->rx_max_pending = GFAR_RX_MAX_RING_SIZE;
+	rvals->rx_mini_max_pending = GFAR_RX_MAX_RING_SIZE;
+	rvals->rx_jumbo_max_pending = GFAR_RX_MAX_RING_SIZE;
+	rvals->tx_max_pending = GFAR_TX_MAX_RING_SIZE;
+
+	/* Values changeable by the user.  The valid values are
+	 * in the range 1 to the "*_max_pending" counterpart above.
+	 */
+	rvals->rx_pending = priv->rx_ring_size;
+	rvals->rx_mini_pending = priv->rx_ring_size;
+	rvals->rx_jumbo_pending = priv->rx_ring_size;
+	rvals->tx_pending = priv->tx_ring_size;
+}
+
+/* Change the current ring parameters, stopping the controller if
+ * necessary so that we don't mess things up while we're in
+ * motion.  We wait for the ring to be clean before reallocating
+ * the rings. */
+int gfar_sringparam(struct net_device *dev, struct ethtool_ringparam *rvals)
+{
+	u32 tempval;
+	struct gfar_private *priv = netdev_priv(dev);
+	int err = 0;
+
+	if (rvals->rx_pending > GFAR_RX_MAX_RING_SIZE)
+		return -EINVAL;
+
+	if (!is_power_of_2(rvals->rx_pending)) {
+		printk("%s: Ring sizes must be a power of 2\n",
+				dev->name);
+		return -EINVAL;
+	}
+
+	if (rvals->tx_pending > GFAR_TX_MAX_RING_SIZE)
+		return -EINVAL;
+
+	if (!is_power_of_2(rvals->tx_pending)) {
+		printk("%s: Ring sizes must be a power of 2\n",
+				dev->name);
+		return -EINVAL;
+	}
+
+	/* Stop the controller so we don't rx any more frames */
+	/* But first, make sure we clear the bits */
+	tempval = gfar_read(&priv->regs->dmactrl);
+	tempval &= ~(DMACTRL_GRS | DMACTRL_GTS);
+	gfar_write(&priv->regs->dmactrl, tempval);
+
+	tempval = gfar_read(&priv->regs->dmactrl);
+	tempval |= (DMACTRL_GRS | DMACTRL_GTS);
+	gfar_write(&priv->regs->dmactrl, tempval);
+
+	while (!(gfar_read(&priv->regs->ievent) & (IEVENT_GRSC | IEVENT_GTSC)))
+		cpu_relax();
+
+	/* Note that rx is not clean right now */
+	priv->rxclean = 0;
+
+	if (dev->flags & IFF_UP) {
+		/* Tell the driver to process the rest of the frames */
+		gfar_receive(0, (void *) dev, NULL);
+
+		/* Now wait for it to be done */
+		wait_event_interruptible(priv->rxcleanupq, priv->rxclean);
+
+		/* Ok, all packets have been handled.  Now we bring it down,
+		 * change the ring size, and bring it up */
+
+		stop_gfar(dev);
+	}
+
+	priv->rx_ring_size = rvals->rx_pending;
+	priv->tx_ring_size = rvals->tx_pending;
+
+	if (dev->flags & IFF_UP)
+		err = startup_gfar(dev);
+
+	return err;
+}
+
+struct ethtool_ops gfar_ethtool_ops = {
+	.get_settings = gfar_gsettings,
+	.get_drvinfo = gfar_gdrvinfo,
+	.get_regs_len = gfar_reglen,
+	.get_regs = gfar_get_regs,
+	.get_link = ethtool_op_get_link,
+	.get_coalesce = gfar_gcoalesce,
+	.set_coalesce = gfar_scoalesce,
+	.get_ringparam = gfar_gringparam,
+	.set_ringparam = gfar_sringparam,
+	.get_strings = gfar_gstrings,
+	.get_stats_count = gfar_stats_count,
+	.get_ethtool_stats = gfar_fill_stats,
+};
+
+struct ethtool_ops gfar_normon_nocoalesce_ethtool_ops = {
+	.get_settings = gfar_gsettings,
+	.get_drvinfo = gfar_gdrvinfo,
+	.get_regs_len = gfar_reglen,
+	.get_regs = gfar_get_regs,
+	.get_link = ethtool_op_get_link,
+	.get_ringparam = gfar_gringparam,
+	.set_ringparam = gfar_sringparam,
+	.get_strings = gfar_gstrings_normon,
+	.get_stats_count = gfar_stats_count_normon,
+	.get_ethtool_stats = gfar_fill_stats_normon,
+};
+
+struct ethtool_ops gfar_nocoalesce_ethtool_ops = {
+	.get_settings = gfar_gsettings,
+	.get_drvinfo = gfar_gdrvinfo,
+	.get_regs_len = gfar_reglen,
+	.get_regs = gfar_get_regs,
+	.get_link = ethtool_op_get_link,
+	.get_ringparam = gfar_gringparam,
+	.set_ringparam = gfar_sringparam,
+	.get_strings = gfar_gstrings,
+	.get_stats_count = gfar_stats_count,
+	.get_ethtool_stats = gfar_fill_stats,
+};
+
+struct ethtool_ops gfar_normon_ethtool_ops = {
+	.get_settings = gfar_gsettings,
+	.get_drvinfo = gfar_gdrvinfo,
+	.get_regs_len = gfar_reglen,
+	.get_regs = gfar_get_regs,
+	.get_link = ethtool_op_get_link,
+	.get_coalesce = gfar_gcoalesce,
+	.set_coalesce = gfar_scoalesce,
+	.get_ringparam = gfar_gringparam,
+	.set_ringparam = gfar_sringparam,
+	.get_strings = gfar_gstrings_normon,
+	.get_stats_count = gfar_stats_count_normon,
+	.get_ethtool_stats = gfar_fill_stats_normon,
+};
+
+struct ethtool_ops *gfar_op_array[] = {
+	&gfar_ethtool_ops,
+	&gfar_normon_ethtool_ops,
+	&gfar_nocoalesce_ethtool_ops,
+	&gfar_normon_nocoalesce_ethtool_ops
+};
diff -Nru a/drivers/net/gianfar_phy.c b/drivers/net/gianfar_phy.c
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/drivers/net/gianfar_phy.c	2004-10-18 14:57:23 -07:00
@@ -0,0 +1,661 @@
+/* 
+ * drivers/net/gianfar_phy.c
+ *
+ * Gianfar Ethernet Driver -- PHY handling
+ * Driver for FEC on MPC8540 and TSEC on MPC8540/MPC8560
+ * Based on 8260_io/fcc_enet.c
+ *
+ * Author: Andy Fleming
+ * Maintainer: Kumar Gala (kumar.gala@freescale.com)
+ *
+ * Copyright (c) 2002-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/kernel.h>
+#include <linux/sched.h>
+#include <linux/string.h>
+#include <linux/errno.h>
+#include <linux/slab.h>
+#include <linux/interrupt.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/skbuff.h>
+#include <linux/spinlock.h>
+#include <linux/mm.h>
+
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/uaccess.h>
+#include <linux/module.h>
+#include <linux/version.h>
+#include <linux/crc32.h>
+#include <linux/mii.h>
+
+#include "gianfar.h"
+#include "gianfar_phy.h"
+
+static void config_genmii_advert(struct gfar_mii_info *mii_info);
+static void genmii_setup_forced(struct gfar_mii_info *mii_info);
+static void genmii_restart_aneg(struct gfar_mii_info *mii_info);
+static int gbit_config_aneg(struct gfar_mii_info *mii_info);
+static int genmii_config_aneg(struct gfar_mii_info *mii_info);
+static int genmii_update_link(struct gfar_mii_info *mii_info);
+static int genmii_read_status(struct gfar_mii_info *mii_info);
+u16 phy_read(struct gfar_mii_info *mii_info, u16 regnum);
+void phy_write(struct gfar_mii_info *mii_info, u16 regnum, u16 val);
+
+/* Write value to the PHY for this device to the register at regnum, */
+/* waiting until the write is done before it returns.  All PHY */
+/* configuration has to be done through the TSEC1 MIIM regs */
+void write_phy_reg(struct net_device *dev, int mii_id, int regnum, int value)
+{
+	struct gfar_private *priv = netdev_priv(dev);
+	struct gfar *regbase = priv->phyregs;
+
+	/* Set the PHY address and the register address we want to write */
+	gfar_write(&regbase->miimadd, (mii_id << 8) | regnum);
+
+	/* Write out the value we want */
+	gfar_write(&regbase->miimcon, value);
+
+	/* Wait for the transaction to finish */
+	while (gfar_read(&regbase->miimind) & MIIMIND_BUSY)
+		cpu_relax();
+}
+
+/* Reads from register regnum in the PHY for device dev, */
+/* returning the value.  Clears miimcom first.  All PHY */
+/* configuration has to be done through the TSEC1 MIIM regs */
+int read_phy_reg(struct net_device *dev, int mii_id, int regnum)
+{
+	struct gfar_private *priv = netdev_priv(dev);
+	struct gfar *regbase = priv->phyregs;
+	u16 value;
+
+	/* Set the PHY address and the register address we want to read */
+	gfar_write(&regbase->miimadd, (mii_id << 8) | regnum);
+
+	/* Clear miimcom, and then initiate a read */
+	gfar_write(&regbase->miimcom, 0);
+	gfar_write(&regbase->miimcom, MII_READ_COMMAND);
+
+	/* Wait for the transaction to finish */
+	while (gfar_read(&regbase->miimind) & (MIIMIND_NOTVALID | MIIMIND_BUSY))
+		cpu_relax();
+
+	/* Grab the value of the register from miimstat */
+	value = gfar_read(&regbase->miimstat);
+
+	return value;
+}
+
+void mii_clear_phy_interrupt(struct gfar_mii_info *mii_info)
+{
+	if(mii_info->phyinfo->ack_interrupt)
+		mii_info->phyinfo->ack_interrupt(mii_info);
+}
+
+
+void mii_configure_phy_interrupt(struct gfar_mii_info *mii_info, u32 interrupts)
+{
+	mii_info->interrupts = interrupts;
+	if(mii_info->phyinfo->config_intr)
+		mii_info->phyinfo->config_intr(mii_info);
+}
+
+
+/* Writes MII_ADVERTISE with the appropriate values, after
+ * sanitizing advertise to make sure only supported features
+ * are advertised 
+ */
+static void config_genmii_advert(struct gfar_mii_info *mii_info)
+{
+	u32 advertise;
+	u16 adv;
+
+	/* Only allow advertising what this PHY supports */
+	mii_info->advertising &= mii_info->phyinfo->features;
+	advertise = mii_info->advertising;
+
+	/* Setup standard advertisement */
+	adv = phy_read(mii_info, MII_ADVERTISE);
+	adv &= ~(ADVERTISE_ALL | ADVERTISE_100BASE4);
+	if (advertise & ADVERTISED_10baseT_Half)
+		adv |= ADVERTISE_10HALF;
+	if (advertise & ADVERTISED_10baseT_Full)
+		adv |= ADVERTISE_10FULL;
+	if (advertise & ADVERTISED_100baseT_Half)
+		adv |= ADVERTISE_100HALF;
+	if (advertise & ADVERTISED_100baseT_Full)
+		adv |= ADVERTISE_100FULL;
+	phy_write(mii_info, MII_ADVERTISE, adv);
+}
+
+static void genmii_setup_forced(struct gfar_mii_info *mii_info)
+{
+	u16 ctrl;
+	u32 features = mii_info->phyinfo->features;
+	
+	ctrl = phy_read(mii_info, MII_BMCR);
+
+	ctrl &= ~(BMCR_FULLDPLX|BMCR_SPEED100|BMCR_SPEED1000|BMCR_ANENABLE);
+	ctrl |= BMCR_RESET;
+
+	switch(mii_info->speed) {
+		case SPEED_1000:
+			if(features & (SUPPORTED_1000baseT_Half
+						| SUPPORTED_1000baseT_Full)) {
+				ctrl |= BMCR_SPEED1000;
+				break;
+			}
+			mii_info->speed = SPEED_100;
+		case SPEED_100:
+			if (features & (SUPPORTED_100baseT_Half
+						| SUPPORTED_100baseT_Full)) {
+				ctrl |= BMCR_SPEED100;
+				break;
+			}
+			mii_info->speed = SPEED_10;
+		case SPEED_10:
+			if (features & (SUPPORTED_10baseT_Half
+						| SUPPORTED_10baseT_Full))
+				break;
+		default: /* Unsupported speed! */
+			printk(KERN_ERR "%s: Bad speed!\n", 
+					mii_info->dev->name);
+			break;
+	}
+
+	phy_write(mii_info, MII_BMCR, ctrl);
+}
+
+
+/* Enable and Restart Autonegotiation */
+static void genmii_restart_aneg(struct gfar_mii_info *mii_info)
+{
+	u16 ctl;
+
+	ctl = phy_read(mii_info, MII_BMCR);
+	ctl |= (BMCR_ANENABLE | BMCR_ANRESTART);
+	phy_write(mii_info, MII_BMCR, ctl);
+}
+
+
+static int gbit_config_aneg(struct gfar_mii_info *mii_info)
+{
+	u16 adv;
+	u32 advertise;
+
+	if(mii_info->autoneg) {
+		/* Configure the ADVERTISE register */
+		config_genmii_advert(mii_info);
+		advertise = mii_info->advertising;
+
+		adv = phy_read(mii_info, MII_1000BASETCONTROL);
+		adv &= ~(MII_1000BASETCONTROL_FULLDUPLEXCAP |
+				MII_1000BASETCONTROL_HALFDUPLEXCAP);
+		if (advertise & SUPPORTED_1000baseT_Half)
+			adv |= MII_1000BASETCONTROL_HALFDUPLEXCAP;
+		if (advertise & SUPPORTED_1000baseT_Full)
+			adv |= MII_1000BASETCONTROL_FULLDUPLEXCAP;
+		phy_write(mii_info, MII_1000BASETCONTROL, adv);
+
+		/* Start/Restart aneg */
+		genmii_restart_aneg(mii_info);
+	} else
+		genmii_setup_forced(mii_info);
+
+	return 0;
+}
+
+static int marvell_config_aneg(struct gfar_mii_info *mii_info)
+{
+	/* The Marvell PHY has an errata which requires
+	 * that certain registers get written in order
+	 * to restart autonegotiation */
+	phy_write(mii_info, MII_BMCR, BMCR_RESET);
+
+	phy_write(mii_info, 0x1d, 0x1f);
+	phy_write(mii_info, 0x1e, 0x200c);
+	phy_write(mii_info, 0x1d, 0x5);
+	phy_write(mii_info, 0x1e, 0);
+	phy_write(mii_info, 0x1e, 0x100);
+
+	gbit_config_aneg(mii_info);
+
+	return 0;
+}
+static int genmii_config_aneg(struct gfar_mii_info *mii_info)
+{
+	if (mii_info->autoneg) {
+		config_genmii_advert(mii_info);
+		genmii_restart_aneg(mii_info);
+	} else
+		genmii_setup_forced(mii_info);
+
+	return 0;
+}
+
+
+static int genmii_update_link(struct gfar_mii_info *mii_info)
+{
+	u16 status;
+
+	/* Do a fake read */
+	phy_read(mii_info, MII_BMSR);
+
+	/* Read link and autonegotiation status */
+	status = phy_read(mii_info, MII_BMSR);
+	if ((status & BMSR_LSTATUS) == 0)
+		mii_info->link = 0;
+	else
+		mii_info->link = 1;
+
+	/* If we are autonegotiating, and not done, 
+	 * return an error */
+	if (mii_info->autoneg && !(status & BMSR_ANEGCOMPLETE))
+		return -EAGAIN;
+
+	return 0;
+}
+
+static int genmii_read_status(struct gfar_mii_info *mii_info)
+{
+	u16 status;
+	int err;
+
+	/* Update the link, but return if there
+	 * was an error */
+	err = genmii_update_link(mii_info);
+	if (err)
+		return err;
+
+	if (mii_info->autoneg) {
+		status = phy_read(mii_info, MII_LPA);
+
+		if (status & (LPA_10FULL | LPA_100FULL))
+			mii_info->duplex = DUPLEX_FULL;
+		else
+			mii_info->duplex = DUPLEX_HALF;
+		if (status & (LPA_100FULL | LPA_100HALF))
+			mii_info->speed = SPEED_100;
+		else
+			mii_info->speed = SPEED_10;
+		mii_info->pause = 0;
+	}
+	/* On non-aneg, we assume what we put in BMCR is the speed,
+	 * though magic-aneg shouldn't prevent this case from occurring
+	 */
+
+	return 0;
+}
+static int marvell_read_status(struct gfar_mii_info *mii_info)
+{
+	u16 status;
+	int err;
+
+	/* Update the link, but return if there
+	 * was an error */
+	err = genmii_update_link(mii_info);
+	if (err)
+		return err;
+
+	/* If the link is up, read the speed and duplex */
+	/* If we aren't autonegotiating, assume speeds 
+	 * are as set */
+	if (mii_info->autoneg && mii_info->link) {
+		int speed;
+		status = phy_read(mii_info, MII_M1011_PHY_SPEC_STATUS);
+
+#if 0
+		/* If speed and duplex aren't resolved,
+		 * return an error.  Isn't this handled
+		 * by checking aneg?
+		 */
+		if ((status & MII_M1011_PHY_SPEC_STATUS_RESOLVED) == 0)
+			return -EAGAIN;
+#endif
+
+		/* Get the duplexity */
+		if (status & MII_M1011_PHY_SPEC_STATUS_FULLDUPLEX)
+			mii_info->duplex = DUPLEX_FULL;
+		else
+			mii_info->duplex = DUPLEX_HALF;
+
+		/* Get the speed */
+		speed = status & MII_M1011_PHY_SPEC_STATUS_SPD_MASK;
+		switch(speed) {
+			case MII_M1011_PHY_SPEC_STATUS_1000:
+				mii_info->speed = SPEED_1000;
+				break;
+			case MII_M1011_PHY_SPEC_STATUS_100:
+				mii_info->speed = SPEED_100;
+				break;
+			default:
+				mii_info->speed = SPEED_10;
+				break;
+		}
+		mii_info->pause = 0;
+	}
+
+	return 0;
+}
+
+
+static int cis820x_read_status(struct gfar_mii_info *mii_info)
+{
+	u16 status;
+	int err;
+
+	/* Update the link, but return if there
+	 * was an error */
+	err = genmii_update_link(mii_info);
+	if (err)
+		return err;
+
+	/* If the link is up, read the speed and duplex */
+	/* If we aren't autonegotiating, assume speeds 
+	 * are as set */
+	if (mii_info->autoneg && mii_info->link) {
+		int speed;
+
+		status = phy_read(mii_info, MII_CIS8201_AUX_CONSTAT);
+		if (status & MII_CIS8201_AUXCONSTAT_DUPLEX)
+			mii_info->duplex = DUPLEX_FULL;
+		else
+			mii_info->duplex = DUPLEX_HALF;
+
+		speed = status & MII_CIS8201_AUXCONSTAT_SPEED;
+
+		switch (speed) {
+		case MII_CIS8201_AUXCONSTAT_GBIT:
+			mii_info->speed = SPEED_1000;
+			break;
+		case MII_CIS8201_AUXCONSTAT_100:
+			mii_info->speed = SPEED_100;
+			break;
+		default:
+			mii_info->speed = SPEED_10;
+			break;
+		}
+	}
+
+	return 0;
+}
+
+static int marvell_ack_interrupt(struct gfar_mii_info *mii_info)
+{
+	/* Clear the interrupts by reading the reg */
+	phy_read(mii_info, MII_M1011_IEVENT);
+
+	return 0;
+}
+
+static int marvell_config_intr(struct gfar_mii_info *mii_info)
+{
+	if(mii_info->interrupts == MII_INTERRUPT_ENABLED)
+		phy_write(mii_info, MII_M1011_IMASK, MII_M1011_IMASK_INIT);
+	else
+		phy_write(mii_info, MII_M1011_IMASK, MII_M1011_IMASK_CLEAR);
+
+	return 0;
+}
+
+static int cis820x_init(struct gfar_mii_info *mii_info)
+{
+	phy_write(mii_info, MII_CIS8201_AUX_CONSTAT, 
+			MII_CIS8201_AUXCONSTAT_INIT);
+	phy_write(mii_info, MII_CIS8201_EXT_CON1,
+			MII_CIS8201_EXTCON1_INIT);
+
+	return 0;
+}
+
+static int cis820x_ack_interrupt(struct gfar_mii_info *mii_info)
+{
+	phy_read(mii_info, MII_CIS8201_ISTAT);
+
+	return 0;
+}
+
+static int cis820x_config_intr(struct gfar_mii_info *mii_info)
+{
+	if(mii_info->interrupts == MII_INTERRUPT_ENABLED)
+		phy_write(mii_info, MII_CIS8201_IMASK, MII_CIS8201_IMASK_MASK);
+	else
+		phy_write(mii_info, MII_CIS8201_IMASK, 0);
+
+	return 0;
+}
+
+#define DM9161_DELAY 10
+
+static int dm9161_read_status(struct gfar_mii_info *mii_info)
+{
+	u16 status;
+	int err;
+
+	/* Update the link, but return if there
+	 * was an error */
+	err = genmii_update_link(mii_info);
+	if (err)
+		return err;
+
+	/* If the link is up, read the speed and duplex */
+	/* If we aren't autonegotiating, assume speeds 
+	 * are as set */
+	if (mii_info->autoneg && mii_info->link) {
+		status = phy_read(mii_info, MII_DM9161_SCSR);
+		if (status & (MII_DM9161_SCSR_100F | MII_DM9161_SCSR_100H))
+			mii_info->speed = SPEED_100;
+		else
+			mii_info->speed = SPEED_10;
+
+		if (status & (MII_DM9161_SCSR_100F | MII_DM9161_SCSR_10F))
+			mii_info->duplex = DUPLEX_FULL;
+		else
+			mii_info->duplex = DUPLEX_HALF;
+	}
+
+	return 0;
+}
+
+
+static int dm9161_config_aneg(struct gfar_mii_info *mii_info)
+{
+	struct dm9161_private *priv = mii_info->priv;
+
+	if(0 == priv->resetdone)
+		return -EAGAIN;
+
+	return 0;
+}
+
+static void dm9161_timer(unsigned long data)
+{
+	struct gfar_mii_info *mii_info = (struct gfar_mii_info *)data;
+	struct dm9161_private *priv = mii_info->priv;
+	u16 status = phy_read(mii_info, MII_BMSR);
+
+	if (status & BMSR_ANEGCOMPLETE) {
+		priv->resetdone = 1;
+	} else
+		mod_timer(&priv->timer, jiffies + DM9161_DELAY * HZ);
+}
+
+static int dm9161_init(struct gfar_mii_info *mii_info)
+{
+	struct dm9161_private *priv;
+
+	/* Allocate the private data structure */
+	priv = kmalloc(sizeof(struct dm9161_private), GFP_KERNEL);
+
+	if (NULL == priv)
+		return -ENOMEM;
+
+	mii_info->priv = priv;
+
+	/* Reset is not done yet */
+	priv->resetdone = 0;
+
+	/* Isolate the PHY */
+	phy_write(mii_info, MII_BMCR, BMCR_ISOLATE);
+
+	/* Do not bypass the scrambler/descrambler */
+	phy_write(mii_info, MII_DM9161_SCR, MII_DM9161_SCR_INIT);
+
+	/* Clear 10BTCSR to default */
+	phy_write(mii_info, MII_DM9161_10BTCSR, MII_DM9161_10BTCSR_INIT);
+
+	/* Reconnect the PHY, and enable Autonegotiation */
+	phy_write(mii_info, MII_BMCR, BMCR_ANENABLE);
+
+	/* Start a timer for DM9161_DELAY seconds to wait
+	 * for the PHY to be ready */
+	init_timer(&priv->timer);
+	priv->timer.function = &dm9161_timer;
+	priv->timer.data = (unsigned long) mii_info;
+	mod_timer(&priv->timer, jiffies + DM9161_DELAY * HZ);
+
+	return 0;
+}
+
+static void dm9161_close(struct gfar_mii_info *mii_info)
+{
+	struct dm9161_private *priv = mii_info->priv;
+
+	del_timer_sync(&priv->timer);
+	kfree(priv);
+}
+
+#if 0
+static int dm9161_ack_interrupt(struct gfar_mii_info *mii_info)
+{
+	phy_read(mii_info, MII_DM9161_INTR);
+
+	return 0;
+}
+#endif
+
+/* Cicada 820x */
+static struct phy_info phy_info_cis820x = {
+	0x000fc440,
+	"Cicada Cis8204",
+	0x000fffc0,
+	.features	= MII_GBIT_FEATURES,
+	.init		= &cis820x_init,
+	.config_aneg	= &gbit_config_aneg,
+	.read_status	= &cis820x_read_status,
+	.ack_interrupt	= &cis820x_ack_interrupt,
+	.config_intr	= &cis820x_config_intr,
+};
+
+static struct phy_info phy_info_dm9161 = {
+	.phy_id		= 0x0181b880,
+	.name		= "Davicom DM9161E",
+	.phy_id_mask	= 0x0ffffff0,
+	.init		= dm9161_init,
+	.config_aneg	= dm9161_config_aneg,
+	.read_status	= dm9161_read_status,
+	.close		= dm9161_close,
+};
+
+static struct phy_info phy_info_marvell = {
+	.phy_id		= 0x01410c00,
+	.phy_id_mask	= 0xffffff00,
+	.name		= "Marvell 88E1101",
+	.features	= MII_GBIT_FEATURES,
+	.config_aneg	= &marvell_config_aneg,
+	.read_status	= &marvell_read_status,
+	.ack_interrupt	= &marvell_ack_interrupt,
+	.config_intr	= &marvell_config_intr,
+};
+
+static struct phy_info phy_info_genmii= {
+	.phy_id		= 0x00000000,
+	.phy_id_mask	= 0x00000000,
+	.name		= "Generic MII",
+	.features	= MII_BASIC_FEATURES,
+	.config_aneg	= genmii_config_aneg,
+	.read_status	= genmii_read_status,
+};
+
+static struct phy_info *phy_info[] = {
+	&phy_info_cis820x,
+	&phy_info_marvell,
+	&phy_info_dm9161,
+	&phy_info_genmii,
+	NULL
+};
+
+u16 phy_read(struct gfar_mii_info *mii_info, u16 regnum)
+{
+	u16 retval;
+	unsigned long flags;
+
+	spin_lock_irqsave(&mii_info->mdio_lock, flags);
+	retval = mii_info->mdio_read(mii_info->dev, mii_info->mii_id, regnum);
+	spin_unlock_irqrestore(&mii_info->mdio_lock, flags);
+
+	return retval;
+}
+
+void phy_write(struct gfar_mii_info *mii_info, u16 regnum, u16 val)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&mii_info->mdio_lock, flags);
+	mii_info->mdio_write(mii_info->dev, 
+			mii_info->mii_id, 
+			regnum, val);
+	spin_unlock_irqrestore(&mii_info->mdio_lock, flags);
+}
+
+/* Use the PHY ID registers to determine what type of PHY is attached
+ * to device dev.  return a struct phy_info structure describing that PHY
+ */
+struct phy_info * get_phy_info(struct gfar_mii_info *mii_info)
+{
+	u16 phy_reg;
+	u32 phy_ID;
+	int i;
+	struct phy_info *theInfo = NULL;
+	struct net_device *dev = mii_info->dev;
+
+	/* Grab the bits from PHYIR1, and put them in the upper half */
+	phy_reg = phy_read(mii_info, MII_PHYSID1);
+	phy_ID = (phy_reg & 0xffff) << 16;
+
+	/* Grab the bits from PHYIR2, and put them in the lower half */
+	phy_reg = phy_read(mii_info, MII_PHYSID2);
+	phy_ID |= (phy_reg & 0xffff);
+
+	/* loop through all the known PHY types, and find one that */
+	/* matches the ID we read from the PHY. */
+	for (i = 0; phy_info[i]; i++)
+		if (phy_info[i]->phy_id == 
+				(phy_ID & phy_info[i]->phy_id_mask)) {
+			theInfo = phy_info[i];
+			break;
+		}
+
+	/* This shouldn't happen, as we have generic PHY support */
+	if (theInfo == NULL) {
+		printk("%s: PHY id %x is not supported!\n", dev->name, phy_ID);
+		return NULL;
+	} else {
+		printk("%s: PHY is %s (%x)\n", dev->name, theInfo->name,
+		       phy_ID);
+	}
+
+	return theInfo;
+}
diff -Nru a/drivers/net/gianfar_phy.h b/drivers/net/gianfar_phy.h
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/drivers/net/gianfar_phy.h	2004-10-18 14:57:23 -07:00
@@ -0,0 +1,213 @@
+/* 
+ * drivers/net/gianfar_phy.h
+ *
+ * Gianfar Ethernet Driver -- PHY handling
+ * Driver for FEC on MPC8540 and TSEC on MPC8540/MPC8560
+ * Based on 8260_io/fcc_enet.c
+ *
+ * Author: Andy Fleming
+ * Maintainer: Kumar Gala (kumar.gala@freescale.com)
+ *
+ * Copyright (c) 2002-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.
+ *
+ */
+#ifndef __GIANFAR_PHY_H
+#define __GIANFAR_PHY_H
+
+#define MII_end ((u32)-2)
+#define MII_read ((u32)-1)
+
+#define MIIMIND_BUSY            0x00000001
+#define MIIMIND_NOTVALID        0x00000004
+
+#define GFAR_AN_TIMEOUT         2000
+
+/* 1000BT control (Marvell & BCM54xx at least) */
+#define MII_1000BASETCONTROL			0x09
+#define MII_1000BASETCONTROL_FULLDUPLEXCAP	0x0200
+#define MII_1000BASETCONTROL_HALFDUPLEXCAP	0x0100
+
+/* Cicada Extended Control Register 1 */
+#define MII_CIS8201_EXT_CON1           0x17
+#define MII_CIS8201_EXTCON1_INIT       0x0000
+
+/* Cicada Interrupt Mask Register */
+#define MII_CIS8201_IMASK		0x19
+#define MII_CIS8201_IMASK_IEN		0x8000
+#define MII_CIS8201_IMASK_SPEED	0x4000
+#define MII_CIS8201_IMASK_LINK		0x2000
+#define MII_CIS8201_IMASK_DUPLEX	0x1000
+#define MII_CIS8201_IMASK_MASK		0xf000
+
+/* Cicada Interrupt Status Register */
+#define MII_CIS8201_ISTAT		0x1a
+#define MII_CIS8201_ISTAT_STATUS	0x8000
+#define MII_CIS8201_ISTAT_SPEED	0x4000
+#define MII_CIS8201_ISTAT_LINK		0x2000
+#define MII_CIS8201_ISTAT_DUPLEX	0x1000
+
+/* Cicada Auxiliary Control/Status Register */
+#define MII_CIS8201_AUX_CONSTAT        0x1c
+#define MII_CIS8201_AUXCONSTAT_INIT    0x0004
+#define MII_CIS8201_AUXCONSTAT_DUPLEX  0x0020
+#define MII_CIS8201_AUXCONSTAT_SPEED   0x0018
+#define MII_CIS8201_AUXCONSTAT_GBIT    0x0010
+#define MII_CIS8201_AUXCONSTAT_100     0x0008
+                                                                                
+/* 88E1011 PHY Status Register */
+#define MII_M1011_PHY_SPEC_STATUS		0x11
+#define MII_M1011_PHY_SPEC_STATUS_1000		0x8000
+#define MII_M1011_PHY_SPEC_STATUS_100		0x4000
+#define MII_M1011_PHY_SPEC_STATUS_SPD_MASK	0xc000
+#define MII_M1011_PHY_SPEC_STATUS_FULLDUPLEX	0x2000
+#define MII_M1011_PHY_SPEC_STATUS_RESOLVED	0x0800
+#define MII_M1011_PHY_SPEC_STATUS_LINK		0x0400
+
+#define MII_M1011_IEVENT		0x13
+#define MII_M1011_IEVENT_CLEAR		0x0000
+
+#define MII_M1011_IMASK			0x12
+#define MII_M1011_IMASK_INIT		0x6400
+#define MII_M1011_IMASK_CLEAR		0x0000
+
+#define MII_DM9161_SCR		0x10
+#define MII_DM9161_SCR_INIT	0x0610
+
+/* DM9161 Specified Configuration and Status Register */
+#define MII_DM9161_SCSR	0x11
+#define MII_DM9161_SCSR_100F	0x8000
+#define MII_DM9161_SCSR_100H	0x4000
+#define MII_DM9161_SCSR_10F	0x2000
+#define MII_DM9161_SCSR_10H	0x1000
+
+/* DM9161 Interrupt Register */
+#define MII_DM9161_INTR	0x15
+#define MII_DM9161_INTR_PEND		0x8000
+#define MII_DM9161_INTR_DPLX_MASK	0x0800
+#define MII_DM9161_INTR_SPD_MASK	0x0400
+#define MII_DM9161_INTR_LINK_MASK	0x0200
+#define MII_DM9161_INTR_MASK		0x0100
+#define MII_DM9161_INTR_DPLX_CHANGE	0x0010
+#define MII_DM9161_INTR_SPD_CHANGE	0x0008
+#define MII_DM9161_INTR_LINK_CHANGE	0x0004
+#define MII_DM9161_INTR_INIT 		0x0000
+#define MII_DM9161_INTR_STOP	\
+(MII_DM9161_INTR_DPLX_MASK | MII_DM9161_INTR_SPD_MASK \
+ | MII_DM9161_INTR_LINK_MASK | MII_DM9161_INTR_MASK)
+
+/* DM9161 10BT Configuration/Status */
+#define MII_DM9161_10BTCSR	0x12
+#define MII_DM9161_10BTCSR_INIT	0x7800
+
+#define MII_BASIC_FEATURES	(SUPPORTED_10baseT_Half | \
+				 SUPPORTED_10baseT_Full | \
+				 SUPPORTED_100baseT_Half | \
+				 SUPPORTED_100baseT_Full | \
+				 SUPPORTED_Autoneg | \
+				 SUPPORTED_TP | \
+				 SUPPORTED_MII)
+
+#define MII_GBIT_FEATURES	(MII_BASIC_FEATURES | \
+				 SUPPORTED_1000baseT_Half | \
+				 SUPPORTED_1000baseT_Full)
+
+#define MII_READ_COMMAND       0x00000001
+
+#define MII_INTERRUPT_DISABLED 0x0
+#define MII_INTERRUPT_ENABLED 0x1
+/* Taken from mii_if_info and sungem_phy.h */
+struct gfar_mii_info {
+	/* Information about the PHY type */
+	/* And management functions */
+	struct phy_info *phyinfo;
+
+	/* forced speed & duplex (no autoneg)
+	 * partner speed & duplex & pause (autoneg)
+	 */
+	int speed;
+	int duplex;
+	int pause;
+
+	/* The most recently read link state */
+	int link;
+
+	/* Enabled Interrupts */
+	u32 interrupts;
+
+	u32 advertising;
+	int autoneg;
+	int mii_id;
+
+	/* private data pointer */
+	/* For use by PHYs to maintain extra state */
+	void *priv;
+
+	/* Provided by host chip */
+	struct net_device *dev;
+
+	/* A lock to ensure that only one thing can read/write
+	 * the MDIO bus at a time */
+	spinlock_t mdio_lock;
+
+	/* Provided by ethernet driver */
+	int (*mdio_read) (struct net_device *dev, int mii_id, int reg);
+	void (*mdio_write) (struct net_device *dev, int mii_id, int reg, int val);
+};
+
+/* struct phy_info: a structure which defines attributes for a PHY
+ *
+ * id will contain a number which represents the PHY.  During
+ * startup, the driver will poll the PHY to find out what its
+ * UID--as defined by registers 2 and 3--is.  The 32-bit result
+ * gotten from the PHY will be ANDed with phy_id_mask to
+ * discard any bits which may change based on revision numbers
+ * unimportant to functionality
+ *
+ * There are 6 commands which take a gfar_mii_info structure.
+ * Each PHY must declare config_aneg, and read_status.
+ */
+struct phy_info {
+	u32 phy_id;
+	char *name;
+	unsigned int phy_id_mask;
+	u32 features;
+
+	/* Called to initialize the PHY */
+	int (*init)(struct gfar_mii_info *mii_info);
+
+	/* Called to suspend the PHY for power */
+	int (*suspend)(struct gfar_mii_info *mii_info);
+
+	/* Reconfigures autonegotiation (or disables it) */
+	int (*config_aneg)(struct gfar_mii_info *mii_info);
+
+	/* Determines the negotiated speed and duplex */
+	int (*read_status)(struct gfar_mii_info *mii_info);
+
+	/* Clears any pending interrupts */
+	int (*ack_interrupt)(struct gfar_mii_info *mii_info);
+
+	/* Enables or disables interrupts */
+	int (*config_intr)(struct gfar_mii_info *mii_info);
+
+	/* Clears up any memory if needed */
+	void (*close)(struct gfar_mii_info *mii_info);
+};
+
+struct phy_info *get_phy_info(struct gfar_mii_info *mii_info);
+int read_phy_reg(struct net_device *dev, int mii_id, int regnum);
+void write_phy_reg(struct net_device *dev, int mii_id, int regnum, int value);
+void mii_clear_phy_interrupt(struct gfar_mii_info *mii_info);
+void mii_configure_phy_interrupt(struct gfar_mii_info *mii_info, u32 interrupts);
+
+struct dm9161_private {
+	struct timer_list timer;
+	int resetdone;
+};
+
+#endif /* GIANFAR_PHY_H */
diff -Nru a/drivers/net/gt64240eth.h b/drivers/net/gt64240eth.h
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/drivers/net/gt64240eth.h	2004-10-18 14:57:21 -07:00
@@ -0,0 +1,402 @@
+/*
+ * 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 Patton Electronics Company
+ * Copyright (C) 2002 Momentum Computer
+ *
+ * Copyright 2000 MontaVista Software Inc.
+ * Author: MontaVista Software, Inc.
+ *         	stevel@mvista.com or support@mvista.com
+ *
+ *  This program is free software; you can distribute it and/or modify it
+ *  under the terms of the GNU General Public License (Version 2) as
+ *  published by the Free Software Foundation.
+ *
+ *  This program is distributed in the hope 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.
+ *
+ * Ethernet driver definitions for the MIPS GT96100 Advanced
+ * Communication Controller.
+ * 
+ * Modified for the Marvellous GT64240 Retarded Communication Controller.
+ */
+#ifndef _GT64240ETH_H
+#define _GT64240ETH_H
+
+#include <asm/gt64240.h>
+
+#define ETHERNET_PORTS_DIFFERENCE_OFFSETS	0x400
+
+/* Translate those weanie names from Galileo/VxWorks header files: */
+
+#define GT64240_MRR                    MAIN_ROUTING_REGISTER
+#define GT64240_CIU_ARBITER_CONFIG     COMM_UNIT_ARBITER_CONFIGURATION_REGISTER
+#define GT64240_CIU_ARBITER_CONTROL    COMM_UNIT_ARBITER_CONTROL
+#define GT64240_MAIN_LOW_CAUSE         LOW_INTERRUPT_CAUSE_REGISTER
+#define GT64240_MAIN_HIGH_CAUSE        HIGH_INTERRUPT_CAUSE_REGISTER
+#define GT64240_CPU_LOW_MASK           CPU_INTERRUPT_MASK_REGISTER_LOW
+#define GT64240_CPU_HIGH_MASK          CPU_INTERRUPT_MASK_REGISTER_HIGH
+#define GT64240_CPU_SELECT_CAUSE       CPU_SELECT_CAUSE_REGISTER
+
+#define GT64240_ETH_PHY_ADDR_REG       ETHERNET_PHY_ADDRESS_REGISTER
+#define GT64240_ETH_PORT_CONFIG        ETHERNET0_PORT_CONFIGURATION_REGISTER
+#define GT64240_ETH_PORT_CONFIG_EXT    ETHERNET0_PORT_CONFIGURATION_EXTEND_REGISTER
+#define GT64240_ETH_PORT_COMMAND       ETHERNET0_PORT_COMMAND_REGISTER
+#define GT64240_ETH_PORT_STATUS        ETHERNET0_PORT_STATUS_REGISTER
+#define GT64240_ETH_IO_SIZE            ETHERNET_PORTS_DIFFERENCE_OFFSETS
+#define GT64240_ETH_SMI_REG            ETHERNET_SMI_REGISTER
+#define GT64240_ETH_MIB_COUNT_BASE     ETHERNET0_MIB_COUNTER_BASE
+#define GT64240_ETH_SDMA_CONFIG        ETHERNET0_SDMA_CONFIGURATION_REGISTER
+#define GT64240_ETH_SDMA_COMM          ETHERNET0_SDMA_COMMAND_REGISTER
+#define GT64240_ETH_INT_MASK           ETHERNET0_INTERRUPT_MASK_REGISTER
+#define GT64240_ETH_INT_CAUSE          ETHERNET0_INTERRUPT_CAUSE_REGISTER
+#define GT64240_ETH_CURR_TX_DESC_PTR0  ETHERNET0_CURRENT_TX_DESCRIPTOR_POINTER0
+#define GT64240_ETH_CURR_TX_DESC_PTR1  ETHERNET0_CURRENT_TX_DESCRIPTOR_POINTER1
+#define GT64240_ETH_1ST_RX_DESC_PTR0   ETHERNET0_FIRST_RX_DESCRIPTOR_POINTER0
+#define GT64240_ETH_CURR_RX_DESC_PTR0  ETHERNET0_CURRENT_RX_DESCRIPTOR_POINTER0
+#define GT64240_ETH_HASH_TBL_PTR       ETHERNET0_HASH_TABLE_POINTER_REGISTER
+
+/* Turn on NAPI by default */
+
+#define	GT64240_NAPI			1
+
+/* Some 64240 settings that SHOULD eventually be setup in PROM monitor: */
+/* (Board-specific to the DSL3224 Rev A board ONLY!)                    */
+#define D3224_MPP_CTRL0_SETTING		0x66669900
+#define D3224_MPP_CTRL1_SETTING		0x00000000
+#define D3224_MPP_CTRL2_SETTING		0x00887700
+#define D3224_MPP_CTRL3_SETTING		0x00000044
+#define D3224_GPP_IO_CTRL_SETTING	0x0000e800
+#define D3224_GPP_LEVEL_CTRL_SETTING	0xf001f703
+#define D3224_GPP_VALUE_SETTING		0x00000000
+
+/* Keep the ring sizes a power of two for efficiency. */
+//-#define TX_RING_SIZE 16
+#define TX_RING_SIZE	64	/* TESTING !!! */
+#define RX_RING_SIZE	32
+#define PKT_BUF_SZ	1536	/* Size of each temporary Rx buffer. */
+
+#define RX_HASH_TABLE_SIZE 16384
+#define HASH_HOP_NUMBER 12
+
+#define NUM_INTERFACES 3
+
+#define GT64240ETH_TX_TIMEOUT HZ/4
+
+#define MIPS_GT64240_BASE 0xf4000000
+#define GT64240_ETH0_BASE (MIPS_GT64240_BASE + GT64240_ETH_PORT_CONFIG)
+#define GT64240_ETH1_BASE (GT64240_ETH0_BASE + GT64240_ETH_IO_SIZE)
+#define GT64240_ETH2_BASE (GT64240_ETH1_BASE + GT64240_ETH_IO_SIZE)
+
+#if defined(CONFIG_MIPS_DSL3224)
+#define GT64240_ETHER0_IRQ 4
+#define GT64240_ETHER1_IRQ 4
+#else
+#define GT64240_ETHER0_IRQ -1
+#define GT64240_ETHER1_IRQ -1
+#endif
+
+#define REV_GT64240  0x1
+#define REV_GT64240A 0x10
+
+#define GT64240ETH_READ(gp, offset)					\
+	GT_READ((gp)->port_offset + (offset))
+
+#define GT64240ETH_WRITE(gp, offset, data)				\
+	GT_WRITE((gp)->port_offset + (offset), (data))
+
+#define GT64240ETH_SETBIT(gp, offset, bits)				\
+	GT64240ETH_WRITE((gp), (offset),				\
+	                 GT64240ETH_READ((gp), (offset)) | (bits))
+
+#define GT64240ETH_CLRBIT(gp, offset, bits)				\
+	GT64240ETH_WRITE((gp), (offset),				\
+	                 GT64240ETH_READ((gp), (offset)) & ~(bits))
+
+#define GT64240_READ(ofs)		GT_READ(ofs)
+#define GT64240_WRITE(ofs, data)	GT_WRITE((ofs), (data))
+
+/* Bit definitions of the SMI Reg */
+enum {
+	smirDataMask = 0xffff,
+	smirPhyAdMask = 0x1f << 16,
+	smirPhyAdBit = 16,
+	smirRegAdMask = 0x1f << 21,
+	smirRegAdBit = 21,
+	smirOpCode = 1 << 26,
+	smirReadValid = 1 << 27,
+	smirBusy = 1 << 28
+};
+
+/* Bit definitions of the Port Config Reg */
+enum pcr_bits {
+	pcrPM = 1 << 0,
+	pcrRBM = 1 << 1,
+	pcrPBF = 1 << 2,
+	pcrEN = 1 << 7,
+	pcrLPBKMask = 0x3 << 8,
+	pcrLPBKBit = 1 << 8,
+	pcrFC = 1 << 10,
+	pcrHS = 1 << 12,
+	pcrHM = 1 << 13,
+	pcrHDM = 1 << 14,
+	pcrHD = 1 << 15,
+	pcrISLMask = 0x7 << 28,
+	pcrISLBit = 28,
+	pcrACCS = 1 << 31
+};
+
+/* Bit definitions of the Port Config Extend Reg */
+enum pcxr_bits {
+	pcxrIGMP = 1,
+	pcxrSPAN = 2,
+	pcxrPAR = 4,
+	pcxrPRIOtxMask = 0x7 << 3,
+	pcxrPRIOtxBit = 3,
+	pcxrPRIOrxMask = 0x3 << 6,
+	pcxrPRIOrxBit = 6,
+	pcxrPRIOrxOverride = 1 << 8,
+	pcxrDPLXen = 1 << 9,
+	pcxrFCTLen = 1 << 10,
+	pcxrFLP = 1 << 11,
+	pcxrFCTL = 1 << 12,
+	pcxrMFLMask = 0x3 << 14,
+	pcxrMFLBit = 14,
+	pcxrMIBclrMode = 1 << 16,
+	pcxrSpeed = 1 << 18,
+	pcxrSpeeden = 1 << 19,
+	pcxrRMIIen = 1 << 20,
+	pcxrDSCPen = 1 << 21
+};
+
+/* Bit definitions of the Port Command Reg */
+enum pcmr_bits {
+	pcmrFJ = 1 << 15
+};
+
+
+/* Bit definitions of the Port Status Reg */
+enum psr_bits {
+	psrSpeed = 1,
+	psrDuplex = 2,
+	psrFctl = 4,
+	psrLink = 8,
+	psrPause = 1 << 4,
+	psrTxLow = 1 << 5,
+	psrTxHigh = 1 << 6,
+	psrTxInProg = 1 << 7
+};
+
+/* Bit definitions of the SDMA Config Reg */
+enum sdcr_bits {
+	sdcrRCMask = 0xf << 2,
+	sdcrRCBit = 2,
+	sdcrBLMR = 1 << 6,
+	sdcrBLMT = 1 << 7,
+	sdcrPOVR = 1 << 8,
+	sdcrRIFB = 1 << 9,
+	sdcrBSZMask = 0x3 << 12,
+	sdcrBSZBit = 12
+};
+
+/* Bit definitions of the SDMA Command Reg */
+enum sdcmr_bits {
+	sdcmrERD = 1 << 7,
+	sdcmrAR = 1 << 15,
+	sdcmrSTDH = 1 << 16,
+	sdcmrSTDL = 1 << 17,
+	sdcmrTXDH = 1 << 23,
+	sdcmrTXDL = 1 << 24,
+	sdcmrAT = 1 << 31
+};
+
+/* Bit definitions of the Interrupt Cause Reg */
+enum icr_bits {
+	icrRxBuffer = 1,
+	icrTxBufferHigh = 1 << 2,
+	icrTxBufferLow = 1 << 3,
+	icrTxEndHigh = 1 << 6,
+	icrTxEndLow = 1 << 7,
+	icrRxError = 1 << 8,
+	icrTxErrorHigh = 1 << 10,
+	icrTxErrorLow = 1 << 11,
+	icrRxOVR = 1 << 12,
+	icrTxUdr = 1 << 13,
+	icrRxBufferQ0 = 1 << 16,
+	icrRxBufferQ1 = 1 << 17,
+	icrRxBufferQ2 = 1 << 18,
+	icrRxBufferQ3 = 1 << 19,
+	icrRxErrorQ0 = 1 << 20,
+	icrRxErrorQ1 = 1 << 21,
+	icrRxErrorQ2 = 1 << 22,
+	icrRxErrorQ3 = 1 << 23,
+	icrMIIPhySTC = 1 << 28,
+	icrSMIdone = 1 << 29,
+	icrEtherIntSum = 1 << 31
+};
+
+
+/* The Rx and Tx descriptor lists. */
+#ifdef __LITTLE_ENDIAN
+typedef struct {
+	u32 cmdstat;
+	u16 reserved;		//-prk21aug01    u32 reserved:16;
+	u16 byte_cnt;		//-prk21aug01    u32 byte_cnt:16;
+	u32 buff_ptr;
+	u32 next;
+} gt64240_td_t;
+
+typedef struct {
+	u32 cmdstat;
+	u16 byte_cnt;		//-prk21aug01    u32 byte_cnt:16;
+	u16 buff_sz;		//-prk21aug01    u32 buff_sz:16;
+	u32 buff_ptr;
+	u32 next;
+} gt64240_rd_t;
+#elif defined(__BIG_ENDIAN)
+typedef struct {
+	u16 byte_cnt;		//-prk21aug01    u32 byte_cnt:16;
+	u16 reserved;		//-prk21aug01    u32 reserved:16;
+	u32 cmdstat;
+	u32 next;
+	u32 buff_ptr;
+} gt64240_td_t;
+
+typedef struct {
+	u16 buff_sz;		//-prk21aug01    u32 buff_sz:16;
+	u16 byte_cnt;		//-prk21aug01    u32 byte_cnt:16;
+	u32 cmdstat;
+	u32 next;
+	u32 buff_ptr;
+} gt64240_rd_t;
+#else
+#error Either __BIG_ENDIAN or __LITTLE_ENDIAN must be defined!
+#endif
+
+
+/* Values for the Tx command-status descriptor entry. */
+enum td_cmdstat {
+	txOwn = 1 << 31,
+	txAutoMode = 1 << 30,
+	txEI = 1 << 23,
+	txGenCRC = 1 << 22,
+	txPad = 1 << 18,
+	txFirst = 1 << 17,
+	txLast = 1 << 16,
+	txErrorSummary = 1 << 15,
+	txReTxCntMask = 0x0f << 10,
+	txReTxCntBit = 10,
+	txCollision = 1 << 9,
+	txReTxLimit = 1 << 8,
+	txUnderrun = 1 << 6,
+	txLateCollision = 1 << 5
+};
+
+
+/* Values for the Rx command-status descriptor entry. */
+enum rd_cmdstat {
+	rxOwn = 1 << 31,
+	rxAutoMode = 1 << 30,
+	rxEI = 1 << 23,
+	rxFirst = 1 << 17,
+	rxLast = 1 << 16,
+	rxErrorSummary = 1 << 15,
+	rxIGMP = 1 << 14,
+	rxHashExpired = 1 << 13,
+	rxMissedFrame = 1 << 12,
+	rxFrameType = 1 << 11,
+	rxShortFrame = 1 << 8,
+	rxMaxFrameLen = 1 << 7,
+	rxOverrun = 1 << 6,
+	rxCollision = 1 << 4,
+	rxCRCError = 1
+};
+
+/* Bit fields of a Hash Table Entry */
+enum hash_table_entry {
+	hteValid = 1,
+	hteSkip = 2,
+	hteRD = 4
+};
+
+// The MIB counters
+typedef struct {
+	u32 byteReceived;
+	u32 byteSent;
+	u32 framesReceived;
+	u32 framesSent;
+	u32 totalByteReceived;
+	u32 totalFramesReceived;
+	u32 broadcastFramesReceived;
+	u32 multicastFramesReceived;
+	u32 cRCError;
+	u32 oversizeFrames;
+	u32 fragments;
+	u32 jabber;
+	u32 collision;
+	u32 lateCollision;
+	u32 frames64;
+	u32 frames65_127;
+	u32 frames128_255;
+	u32 frames256_511;
+	u32 frames512_1023;
+	u32 frames1024_MaxSize;
+	u32 macRxError;
+	u32 droppedFrames;
+	u32 outMulticastFrames;
+	u32 outBroadcastFrames;
+	u32 undersizeFrames;
+} mib_counters_t;
+
+
+struct gt64240_private {
+	gt64240_rd_t *rx_ring;
+	gt64240_td_t *tx_ring;
+	// The Rx and Tx rings must be 16-byte aligned
+	dma_addr_t rx_ring_dma;
+	dma_addr_t tx_ring_dma;
+	char *hash_table;
+	// The Hash Table must be 8-byte aligned
+	dma_addr_t hash_table_dma;
+	int hash_mode;
+
+	// The Rx buffers must be 8-byte aligned
+	char *rx_buff;
+	dma_addr_t rx_buff_dma;
+	// Tx buffers (tx_skbuff[i]->data) with less than 8 bytes
+	// of payload must be 8-byte aligned
+	struct sk_buff *tx_skbuff[TX_RING_SIZE];
+	int rx_next_out;	/* The next free ring entry to receive */
+	int tx_next_in;		/* The next free ring entry to send */
+	int tx_next_out;	/* The last ring entry the ISR processed */
+	int tx_count;		/* current # of pkts waiting to be sent in Tx ring */
+	int intr_work_done;	/* number of Rx and Tx pkts processed in the isr */
+	int tx_full;		/* Tx ring is full */
+
+	mib_counters_t mib;
+	struct net_device_stats stats;
+
+	int io_size;
+	int port_num;		// 0 or 1
+	u32 port_offset;
+
+	int phy_addr;		// PHY address
+	u32 last_psr;		// last value of the port status register
+
+	int options;		/* User-settable misc. driver options. */
+	int drv_flags;
+	spinlock_t lock;	/* Serialise access to device */
+	struct mii_if_info mii_if;
+
+	u32 msg_enable;
+};
+
+#endif /* _GT64240ETH_H */
diff -Nru a/drivers/net/gt96100eth.c b/drivers/net/gt96100eth.c
--- a/drivers/net/gt96100eth.c	2004-10-18 14:56:49 -07:00
+++ b/drivers/net/gt96100eth.c	2004-10-18 14:56:49 -07:00
@@ -28,7 +28,6 @@
  *                gt96100_cleanup_module(), and other general code cleanups
  *                <stevel@mvista.com>.
  */
-#include <linux/config.h>
 #include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/string.h>
@@ -66,10 +65,6 @@
 static void read_mib_counters(struct gt96100_private *gp);
 static int read_MII(int phy_addr, u32 reg);
 static int write_MII(int phy_addr, u32 reg, u16 data);
-#if 0
-static void dump_tx_ring(struct net_device *dev);
-static void dump_rx_ring(struct net_device *dev);
-#endif
 static int gt96100_init_module(void);
 static void gt96100_cleanup_module(void);
 static void dump_MII(int dbg_lvl, struct net_device *dev);
@@ -84,7 +79,7 @@
 static void hard_stop(struct net_device *dev);
 static void enable_ether_irq(struct net_device *dev);
 static void disable_ether_irq(struct net_device *dev);
-static int gt96100_probe1(int port_num);
+static int gt96100_probe1(struct pci_dev *pci, int port_num);
 static void reset_tx(struct net_device *dev);
 static void reset_rx(struct net_device *dev);
 static int gt96100_check_tx_consistent(struct gt96100_private *gp);
@@ -164,13 +159,11 @@
 /*
   DMA memory allocation, derived from pci_alloc_consistent.
 */
-static void *
-dmaalloc(size_t size, dma_addr_t *dma_handle)
+static void * dmaalloc(size_t size, dma_addr_t *dma_handle)
 {
 	void *ret;
 	
-	ret = (void *)__get_free_pages(GFP_ATOMIC | GFP_DMA,
-				       get_order(size));
+	ret = (void *)__get_free_pages(GFP_ATOMIC | GFP_DMA, get_order(size));
 	
 	if (ret != NULL) {
 		dma_cache_inv((unsigned long)ret, size);
@@ -184,17 +177,13 @@
 	return ret;
 }
 
-static void
-dmafree(size_t size, void *vaddr)
+static void dmafree(size_t size, void *vaddr)
 {
 	vaddr = (void*)KSEG0ADDR(vaddr);
 	free_pages((unsigned long)vaddr, get_order(size));
 }
 
-
-
-static void
-gt96100_delay(int ms)
+static void gt96100_delay(int ms)
 {
 	if (in_interrupt())
 		return;
@@ -327,34 +316,6 @@
 	return 0;
 }
 
-#if 0
-// These routines work, just disabled to avoid compile warnings
-static void
-dump_tx_ring(struct net_device *dev)
-{
-	struct gt96100_private *gp = netdev_priv(dev);
-	int i;
-
-	dbg(0, "%s: txno/txni/cnt=%d/%d/%d\n", __FUNCTION__,
-	    gp->tx_next_out, gp->tx_next_in, gp->tx_count);
-
-	for (i=0; i<TX_RING_SIZE; i++)
-		dump_tx_desc(0, dev, i);
-}
-
-static void
-dump_rx_ring(struct net_device *dev)
-{
-	struct gt96100_private *gp = netdev_priv(dev);
-	int i;
-
-	dbg(0, "%s: rxno=%d\n", __FUNCTION__, gp->rx_next_out);
-
-	for (i=0; i<RX_RING_SIZE; i++)
-		dump_rx_desc(0, dev, i);
-}
-#endif
-
 static void
 dump_MII(int dbg_lvl, struct net_device *dev)
 {
@@ -647,23 +608,19 @@
 /*
  * Init GT96100 ethernet controller driver
  */
-int gt96100_init_module(void)
+static int gt96100_init_module(void)
 {
+	struct pci_dev *pci;
 	int i, retval=0;
-	u16 vendor_id, device_id;
 	u32 cpuConfig;
 
-#ifndef CONFIG_MIPS_GT96100ETH
-	return -ENODEV;
-#endif
-
-	// probe for GT96100 by reading PCI0 vendor/device ID register
-	pcibios_read_config_word(0, 0, PCI_VENDOR_ID, &vendor_id);
-	pcibios_read_config_word(0, 0, PCI_DEVICE_ID, &device_id);
-    
-	if (vendor_id != PCI_VENDOR_ID_MARVELL ||
-	    (device_id != PCI_DEVICE_ID_MARVELL_GT96100 &&
-	     device_id != PCI_DEVICE_ID_MARVELL_GT96100A)) {
+	/*
+	 * Stupid probe because this really isn't a PCI device
+	 */
+	if (!(pci = pci_find_device(PCI_VENDOR_ID_MARVELL,
+	                            PCI_DEVICE_ID_MARVELL_GT96100, NULL)) &&
+	    !(pci = pci_find_device(PCI_VENDOR_ID_MARVELL,
+		                    PCI_DEVICE_ID_MARVELL_GT96100A, NULL))) {
 		printk(KERN_ERR __FILE__ ": GT96100 not found!\n");
 		return -ENODEV;
 	}
@@ -675,17 +632,13 @@
 		return -ENODEV;
 	}
 
-	for (i=0; i < NUM_INTERFACES; i++) {
-		retval |= gt96100_probe1(i);
-	}
+	for (i=0; i < NUM_INTERFACES; i++)
+		retval |= gt96100_probe1(pci, i);
 
 	return retval;
 }
 
-
-
-static int __init
-gt96100_probe1(int port_num)
+static int __init gt96100_probe1(struct pci_dev *pci, int port_num)
 {
 	struct gt96100_private *gp = NULL;
 	struct gt96100_if_t *gtif = &gt96100_iflist[port_num];
@@ -696,19 +649,19 @@
 	struct net_device *dev = NULL;
     
 	if (gtif->irq < 0) {
-		printk(KERN_ERR "%s: irq unknown - probing not supported\n", __FUNCTION_);
+		printk(KERN_ERR "%s: irq unknown - probing not supported\n",
+		      __FUNCTION__);
 		return -ENODEV;
 	}
     
-	pcibios_read_config_byte(0, 0, PCI_REVISION_ID, &chip_rev);
+	pci_read_config_byte(pci, PCI_REVISION_ID, &chip_rev);
 
 	if (chip_rev >= REV_GT96100A_1) {
 		phyAD = GT96100_READ(GT96100_ETH_PHY_ADDR_REG);
 		phy_addr = (phyAD >> (5*port_num)) & 0x1f;
 	} else {
 		/*
-		 * not sure what's this about -- probably 
-		 * a gt bug
+		 * not sure what's this about -- probably a gt bug
 		 */
 		phy_addr = port_num;
 		phyAD = GT96100_READ(GT96100_ETH_PHY_ADDR_REG);
@@ -831,6 +784,7 @@
 	free_netdev (dev);
 out:
 	release_region(gtif->iobase, GT96100_ETH_IO_SIZE);
+
 	err("%s failed.  Returns %d\n", __FUNCTION__, retval);
 	return retval;
 }
@@ -1102,6 +1056,7 @@
 	}
 
 	free_irq(dev->irq, dev);
+    
 	return 0;
 }
 
@@ -1312,10 +1267,11 @@
 		    cmdstat, nextOut);
 	
 		if (cmdstat & (u32)txOwn) {
-			//dump_tx_ring(dev);
-			// DMA is not finished writing descriptor???
-			// Leave and come back later to pick-up where
-			// we left off.
+			/*
+			 * DMA is not finished writing descriptor???
+			 * Leave and come back later to pick-up where
+			 * we left off.
+			 */
 			break;
 		}
 	
@@ -1342,7 +1298,8 @@
 			gp->tx_full = 0;
 			if (gp->last_psr & psrLink) {
 				netif_wake_queue(dev);
-				dbg(2, "%s: Tx Ring was full, queue waked\n", __FUNCTION_);
+				dbg(2, "%s: Tx Ring was full, queue waked\n",
+				    __FUNCTION__);
 			}
 		}
 	
@@ -1425,12 +1382,12 @@
 		
 				if ((psr & psrLink) && !gp->tx_full &&
 				    netif_queue_stopped(dev)) {
-					dbg(0, ": Link up, waking queue.\n",
-					    __FUNCTION_);
+					dbg(0, "%s: Link up, waking queue.\n",
+					    __FUNCTION__);
 					netif_wake_queue(dev);
 				} else if (!(psr & psrLink) &&
 					   !netif_queue_stopped(dev)) {
-					dbg(0, "Link down, stopping queue.\n",
+					dbg(0, "%s: Link down, stopping queue.\n",
 					    __FUNCTION__);
 					netif_stop_queue(dev);
 				}
@@ -1569,8 +1526,8 @@
 	for (i=0; i<NUM_INTERFACES; i++) {
 		struct gt96100_if_t *gtif = &gt96100_iflist[i];
 		if (gtif->dev != NULL) {
-			struct gt96100_private *gp =
-				(struct gt96100_private *)gtif->dev->priv;
+			struct gt96100_private *gp = (struct gt96100_private *)
+				netdev_priv(gtif->dev);
 			unregister_netdev(gtif->dev);
 			dmafree(RX_HASH_TABLE_SIZE, gp->hash_table_dma);
 			dmafree(PKT_BUF_SZ*RX_RING_SIZE, gp->rx_buff);
@@ -1583,9 +1540,6 @@
 	}
 }
 
-
-#ifndef MODULE
-
 static int __init gt96100_setup(char *options)
 {
 	char *this_opt;
@@ -1609,9 +1563,6 @@
 }
 
 __setup("gt96100eth=", gt96100_setup);
-
-#endif /* !MODULE */
-
 
 module_init(gt96100_init_module);
 module_exit(gt96100_cleanup_module);
diff -Nru a/drivers/net/hamachi.c b/drivers/net/hamachi.c
--- a/drivers/net/hamachi.c	2004-10-18 14:57:05 -07:00
+++ b/drivers/net/hamachi.c	2004-10-18 14:57:05 -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/bpqether.c b/drivers/net/hamradio/bpqether.c
--- a/drivers/net/hamradio/bpqether.c	2004-10-18 14:56:29 -07:00
+++ b/drivers/net/hamradio/bpqether.c	2004-10-18 14:56:29 -07:00
@@ -193,7 +193,7 @@
 
 	bpq = (struct bpqdev *)dev->priv;
 
-	eth = (struct ethhdr *)skb->mac.raw;
+	eth = eth_hdr(skb);
 
 	if (!(bpq->acpt_addr[0] & 0x01) &&
 	    memcmp(eth->h_source, bpq->acpt_addr, ETH_ALEN))
diff -Nru a/drivers/net/hamradio/dmascc.c b/drivers/net/hamradio/dmascc.c
--- a/drivers/net/hamradio/dmascc.c	2004-10-18 14:56:29 -07:00
+++ b/drivers/net/hamradio/dmascc.c	2004-10-18 14:56:29 -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/hamradio/mkiss.c b/drivers/net/hamradio/mkiss.c
--- a/drivers/net/hamradio/mkiss.c	2004-10-18 14:57:04 -07:00
+++ b/drivers/net/hamradio/mkiss.c	2004-10-18 14:57:04 -07:00
@@ -602,8 +602,6 @@
 
 	if (tty->driver->flush_buffer)
 		tty->driver->flush_buffer(tty);
-	if (tty->ldisc.flush_buffer)
-		tty->ldisc.flush_buffer(tty);
 
 	/* Restore default settings */
 	ax->dev->type = ARPHRD_AX25;
diff -Nru a/drivers/net/hp100.c b/drivers/net/hp100.c
--- a/drivers/net/hp100.c	2004-10-18 14:56:28 -07:00
+++ b/drivers/net/hp100.c	2004-10-18 14:56:28 -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-10-18 14:56:31 -07:00
+++ b/drivers/net/ibm_emac/ibm_emac.h	2004-10-18 14:56:31 -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-10-18 14:55:54 -07:00
+++ b/drivers/net/ibm_emac/ibm_emac_core.c	2004-10-18 14:55:54 -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-10-18 14:56:17 -07:00
+++ b/drivers/net/ibm_emac/ibm_emac_core.h	2004-10-18 14:56:17 -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/ibm_emac/ibm_emac_mal.c b/drivers/net/ibm_emac/ibm_emac_mal.c
--- a/drivers/net/ibm_emac/ibm_emac_mal.c	2004-10-18 14:57:03 -07:00
+++ b/drivers/net/ibm_emac/ibm_emac_mal.c	2004-10-18 14:57:03 -07:00
@@ -55,8 +55,6 @@
 
 	write_unlock_irqrestore(&mal_list_lock, flags);
 
-	MOD_INC_USE_COUNT;
-
 	return 0;
 }
 
@@ -72,8 +70,6 @@
 	list_del_init(&commac->list);
 
 	write_unlock_irqrestore(&mal_list_lock, flags);
-
-	MOD_DEC_USE_COUNT;
 
 	return 0;
 }
diff -Nru a/drivers/net/ibmveth.c b/drivers/net/ibmveth.c
--- a/drivers/net/ibmveth.c	2004-10-18 14:55:46 -07:00
+++ b/drivers/net/ibmveth.c	2004-10-18 14:55:46 -07:00
@@ -2,8 +2,8 @@
 /*                                                                        */
 /* IBM eServer i/pSeries Virtual Ethernet Device Driver                   */
 /* Copyright (C) 2003 IBM Corp.                                           */
-/*  Dave Larson (larson1@us.ibm.com)                                      */
-/*  Santiago Leon (santil@us.ibm.com)                                     */
+/*  Originally written by Dave Larson (larson1@us.ibm.com)                */
+/*  Maintained by 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  */
@@ -104,11 +104,12 @@
 
 static const char ibmveth_driver_name[] = "ibmveth";
 static const char ibmveth_driver_string[] = "IBM i/pSeries Virtual Ethernet Driver";
-static const char ibmveth_driver_version[] = "1.0";
+#define ibmveth_driver_version "1.02"
 
-MODULE_AUTHOR("Dave Larson <larson1@us.ibm.com>");
+MODULE_AUTHOR("Santiago Leon <santil@us.ibm.com>");
 MODULE_DESCRIPTION("IBM i/pSeries Virtual Ethernet Driver");
 MODULE_LICENSE("GPL");
+MODULE_VERSION(ibmveth_driver_version);
 
 /* simple methods of getting data from the current rxq entry */
 static inline int ibmveth_rxq_pending_buffer(struct ibmveth_adapter *adapter)
@@ -213,11 +214,12 @@
 		free_index = pool->consumer_index++ % pool->size;
 		index = pool->free_map[free_index];
 	
-		ibmveth_assert(index != 0xffff);
+		ibmveth_assert(index != IBM_VETH_INVALID_MAP);
 		ibmveth_assert(pool->skbuff[index] == NULL);
 
 		dma_addr = vio_map_single(adapter->vdev, skb->data, pool->buff_size, DMA_FROM_DEVICE);
 
+		pool->free_map[free_index] = IBM_VETH_INVALID_MAP;
 		pool->dma_addr[index] = dma_addr;
 		pool->skbuff[index] = skb;
 
@@ -232,6 +234,7 @@
 		lpar_rc = h_add_logical_lan_buffer(adapter->vdev->unit_address, desc.desc);
 		    
 		if(lpar_rc != H_Success) {
+			pool->free_map[free_index] = IBM_VETH_INVALID_MAP;
 			pool->skbuff[index] = NULL;
 			pool->consumer_index--;
 			vio_unmap_single(adapter->vdev, pool->dma_addr[index], pool->buff_size, DMA_FROM_DEVICE);
@@ -239,7 +242,6 @@
 			adapter->replenish_add_buff_failure++;
 			break;
 		} else {
-			pool->free_map[free_index] = 0xffff;
 			buffers_added++;
 			adapter->replenish_add_buff_success++;
 		}
@@ -269,7 +271,6 @@
 	adapter->rx_no_buffer = *(u64*)(((char*)adapter->buffer_list_addr) + 4096 - 8);
 
 	atomic_inc(&adapter->not_replenishing);
-	ibmveth_assert(atomic_read(&adapter->not_replenishing) == 1);
 }
 
 /* kick the replenish tasklet if we need replenishing and it isn't already running */
@@ -528,7 +529,7 @@
 		ibmveth_error_printk("unable to request irq 0x%x, rc %d\n", netdev->irq, rc);
 		do {
 			rc = h_free_logical_lan(adapter->vdev->unit_address);
-		} while H_isLongBusy(rc);
+		} while (H_isLongBusy(rc) || (rc == H_Busy));
 
 		ibmveth_cleanup(adapter);
 		return rc;
@@ -560,7 +561,7 @@
 
 	do {
 		lpar_rc = h_free_logical_lan(adapter->vdev->unit_address);
-	} while H_isLongBusy(lpar_rc);
+	} while (H_isLongBusy(lpar_rc) || (lpar_rc == H_Busy));
 
 	if(lpar_rc != H_Success)
 	{
@@ -732,6 +733,8 @@
 		if(ibmveth_rxq_pending_buffer(adapter)) {
 			struct sk_buff *skb;
 
+			rmb();
+
 			if(!ibmveth_rxq_buffer_valid(adapter)) {
 				wmb(); /* suggested by larson1 */
 				adapter->rx_invalid_buffer++;
@@ -882,13 +885,16 @@
 
 	mac_addr_p = (unsigned char *) vio_get_attribute(dev, VETH_MAC_ADDR, 0);
 	if(!mac_addr_p) {
-		ibmveth_error_printk("Can't find VETH_MAC_ADDR attribute\n");
+		printk(KERN_ERR "(%s:%3.3d) ERROR: Can't find VETH_MAC_ADDR "
+				"attribute\n", __FILE__, __LINE__);
 		return 0;
 	}
 	
 	mcastFilterSize_p= (unsigned int *) vio_get_attribute(dev, VETH_MCAST_FILTER_SIZE, 0);
 	if(!mcastFilterSize_p) {
-		ibmveth_error_printk("Can't find VETH_MCAST_FILTER_SIZE attribute\n");
+		printk(KERN_ERR "(%s:%3.3d) ERROR: Can't find "
+				"VETH_MCAST_FILTER_SIZE attribute\n",
+				__FILE__, __LINE__);
 		return 0;
 	}
 	
diff -Nru a/drivers/net/ibmveth.h b/drivers/net/ibmveth.h
--- a/drivers/net/ibmveth.h	2004-10-18 14:56:33 -07:00
+++ b/drivers/net/ibmveth.h	2004-10-18 14:56:33 -07:00
@@ -77,6 +77,8 @@
 #define IbmVethPool1DftCnt  256
 #define IbmVethPool2DftCnt  256
 
+#define IBM_VETH_INVALID_MAP ((u16)0xffff)
+
 struct ibmveth_buff_pool {
     u32 size;
     u32 index;
diff -Nru a/drivers/net/ioc3-eth.c b/drivers/net/ioc3-eth.c
--- a/drivers/net/ioc3-eth.c	2004-10-18 14:55:54 -07:00
+++ b/drivers/net/ioc3-eth.c	2004-10-18 14:55:54 -07:00
@@ -506,7 +506,7 @@
 
 static void ioc3_tcpudp_checksum(struct sk_buff *skb, uint32_t hwsum, int len)
 {
-	struct ethhdr *eh = skb->mac.ethernet;
+	struct ethhdr *eh = eth_hdr(skb);
 	uint32_t csum, ehsum;
 	unsigned int proto;
 	struct iphdr *ih;
@@ -1333,7 +1333,7 @@
 		uint32_t csum, ehsum;
 		uint16_t *eh;
 
-		/* The MAC header.  skb->mac.ethernet seem the logic approach
+		/* The MAC header.  skb->mac seem the logic approach
 		   to find the MAC header - except it's a NULL pointer ...  */
 		eh = (uint16_t *) skb->data;
 
diff -Nru a/drivers/net/irda/irda-usb.c b/drivers/net/irda/irda-usb.c
--- a/drivers/net/irda/irda-usb.c	2004-10-18 14:56:32 -07:00
+++ b/drivers/net/irda/irda-usb.c	2004-10-18 14:56:32 -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/irda/irtty-sir.c b/drivers/net/irda/irtty-sir.c
--- a/drivers/net/irda/irtty-sir.c	2004-10-18 14:55:46 -07:00
+++ b/drivers/net/irda/irtty-sir.c	2004-10-18 14:55:46 -07:00
@@ -509,13 +509,6 @@
 	if (tty->driver->flush_buffer)
 		tty->driver->flush_buffer(tty);
 	
-/* from old irtty - but what is it good for?
- * we _are_ the ldisc and we _don't_ implement flush_buffer!
- *
- *	if (tty->ldisc.flush_buffer)
- *		tty->ldisc.flush_buffer(tty);
- */
-
 	/* apply mtt override */
 	sir_tty_drv.qos_mtt_bits = qos_mtt_bits;
 
diff -Nru a/drivers/net/ixgb/ixgb_main.c b/drivers/net/ixgb/ixgb_main.c
--- a/drivers/net/ixgb/ixgb_main.c	2004-10-18 14:56:17 -07:00
+++ b/drivers/net/ixgb/ixgb_main.c	2004-10-18 14:56:17 -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/lasi_82596.c b/drivers/net/lasi_82596.c
--- a/drivers/net/lasi_82596.c	2004-10-18 14:55:55 -07:00
+++ b/drivers/net/lasi_82596.c	2004-10-18 14:55:55 -07:00
@@ -1426,8 +1426,6 @@
 	free_irq(dev->irq, dev);
 	remove_rx_bufs(dev);
 
-	MOD_DEC_USE_COUNT;
-
 	return 0;
 }
 
diff -Nru a/drivers/net/loopback.c b/drivers/net/loopback.c
--- a/drivers/net/loopback.c	2004-10-18 14:56:11 -07:00
+++ b/drivers/net/loopback.c	2004-10-18 14:56:11 -07:00
@@ -49,6 +49,7 @@
 #include <linux/netdevice.h>
 #include <linux/etherdevice.h>
 #include <linux/skbuff.h>
+#include <linux/ethtool.h>
 #include <net/sock.h>
 #include <net/checksum.h>
 #include <linux/if_ether.h>	/* For the statistics structure. */
@@ -183,6 +184,17 @@
 	return stats;
 }
 
+u32 loopback_get_link(struct net_device *dev)
+{
+	return 1;
+}
+
+static struct ethtool_ops loopback_ethtool_ops = {
+	.get_link		= loopback_get_link,
+	.get_tso		= ethtool_op_get_tso,
+	.set_tso		= ethtool_op_set_tso,
+};
+
 struct net_device loopback_dev = {
 	.name	 		= "lo",
 	.mtu			= (16 * 1024) + 20 + 20 + 12,
@@ -199,6 +211,7 @@
 	.features 		= NETIF_F_SG|NETIF_F_FRAGLIST
 				  |NETIF_F_NO_CSUM|NETIF_F_HIGHDMA
 				  |NETIF_F_LLTX,
+	.ethtool_ops		= &loopback_ethtool_ops,
 };
 
 /* Setup and register the of the LOOPBACK device. */
diff -Nru a/drivers/net/mv643xx_eth.c b/drivers/net/mv643xx_eth.c
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/drivers/net/mv643xx_eth.c	2004-10-18 14:57:23 -07:00
@@ -0,0 +1,2646 @@
+/*
+ * drivers/net/mv64340_eth.c - Driver for MV64340X ethernet ports
+ * Copyright (C) 2002 Matthew Dharm <mdharm@momenco.com>
+ *
+ * Based on the 64360 driver from:
+ * Copyright (C) 2002 rabeeh@galileo.co.il
+ *
+ * Copyright (C) 2003 PMC-Sierra, Inc.,
+ *	written by Manish Lachwani (lachwani@pmc-sierra.com)
+ *
+ * Copyright (C) 2003 Ralf Baechle <ralf@linux-mips.org>
+ *
+ * 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.
+ */
+#include <linux/config.h>
+#include <linux/version.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/config.h>
+#include <linux/sched.h>
+#include <linux/ptrace.h>
+#include <linux/fcntl.h>
+#include <linux/ioport.h>
+#include <linux/interrupt.h>
+#include <linux/slab.h>
+#include <linux/string.h>
+#include <linux/errno.h>
+#include <linux/ip.h>
+#include <linux/init.h>
+#include <linux/in.h>
+#include <linux/pci.h>
+#include <linux/workqueue.h>
+#include <asm/smp.h>
+#include <linux/skbuff.h>
+#include <linux/tcp.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <net/ip.h>
+
+#include <asm/bitops.h>
+#include <asm/io.h>
+#include <asm/types.h>
+#include <asm/pgtable.h>
+#include <asm/system.h>
+#include "mv643xx_eth.h"
+
+/*
+ * The first part is the high level driver of the gigE ethernet ports. 
+ */
+
+/* Definition for configuring driver */
+#undef MV64340_RX_QUEUE_FILL_ON_TASK
+
+/* Constants */
+#define EXTRA_BYTES 32
+#define WRAP       ETH_HLEN + 2 + 4 + 16
+#define BUFFER_MTU dev->mtu + WRAP
+#define INT_CAUSE_UNMASK_ALL		0x0007ffff
+#define INT_CAUSE_UNMASK_ALL_EXT	0x0011ffff
+#ifdef MV64340_RX_FILL_ON_TASK
+#define INT_CAUSE_MASK_ALL		0x00000000
+#define INT_CAUSE_CHECK_BITS		INT_CAUSE_UNMASK_ALL
+#define INT_CAUSE_CHECK_BITS_EXT	INT_CAUSE_UNMASK_ALL_EXT
+#endif
+
+/* Static function declarations */
+static int mv64340_eth_real_open(struct net_device *);
+static int mv64340_eth_real_stop(struct net_device *);
+static int mv64340_eth_change_mtu(struct net_device *, int);
+static struct net_device_stats *mv64340_eth_get_stats(struct net_device *);
+static void eth_port_init_mac_tables(unsigned int eth_port_num);
+#ifdef MV64340_NAPI
+static int mv64340_poll(struct net_device *dev, int *budget);
+#endif
+
+unsigned char prom_mac_addr_base[6];
+unsigned long mv64340_sram_base;
+
+/*
+ * Changes MTU (maximum transfer unit) of the gigabit ethenret port
+ *
+ * Input : pointer to ethernet interface network device structure
+ *         new mtu size 
+ * Output : 0 upon success, -EINVAL upon failure
+ */
+static int mv64340_eth_change_mtu(struct net_device *dev, int new_mtu)
+{
+	struct mv64340_private *mp = netdev_priv(dev);
+	unsigned long flags;
+
+	spin_lock_irqsave(&mp->lock, flags);
+
+	if ((new_mtu > 9500) || (new_mtu < 64)) {
+		spin_unlock_irqrestore(&mp->lock, flags);
+		return -EINVAL;
+	}
+
+	dev->mtu = new_mtu;
+	/* 
+	 * Stop then re-open the interface. This will allocate RX skb's with
+	 * the new MTU.
+	 * There is a possible danger that the open will not successed, due
+	 * to memory is full, which might fail the open function.
+	 */
+	if (netif_running(dev)) {
+		if (mv64340_eth_real_stop(dev))
+			printk(KERN_ERR
+			       "%s: Fatal error on stopping device\n",
+			       dev->name);
+		if (mv64340_eth_real_open(dev))
+			printk(KERN_ERR
+			       "%s: Fatal error on opening device\n",
+			       dev->name);
+	}
+
+	spin_unlock_irqrestore(&mp->lock, flags);
+	return 0;
+}
+
+/*
+ * mv64340_eth_rx_task
+ *								       
+ * Fills / refills RX queue on a certain gigabit ethernet port
+ *
+ * Input : pointer to ethernet interface network device structure
+ * Output : N/A
+ */
+static void mv64340_eth_rx_task(void *data)
+{
+	struct net_device *dev = (struct net_device *) data;
+	struct mv64340_private *mp = netdev_priv(dev);
+	struct pkt_info pkt_info;
+	struct sk_buff *skb;
+
+	if (test_and_set_bit(0, &mp->rx_task_busy))
+		panic("%s: Error in test_set_bit / clear_bit", dev->name);
+
+	while (mp->rx_ring_skbs < (mp->rx_ring_size - 5)) {
+		/* The +8 for buffer allignment and another 32 byte extra */
+
+		skb = dev_alloc_skb(BUFFER_MTU + 8 + EXTRA_BYTES);
+		if (!skb)
+			/* Better luck next time */
+			break;
+		mp->rx_ring_skbs++;
+		pkt_info.cmd_sts = ETH_RX_ENABLE_INTERRUPT;
+		pkt_info.byte_cnt = dev->mtu + ETH_HLEN + 4 + 2 + EXTRA_BYTES;
+		/* Allign buffer to 8 bytes */
+		if (pkt_info.byte_cnt & ~0x7) {
+			pkt_info.byte_cnt &= ~0x7;
+			pkt_info.byte_cnt += 8;
+		}
+		pkt_info.buf_ptr =
+		    pci_map_single(0, skb->data,
+				   dev->mtu + ETH_HLEN + 4 + 2 + EXTRA_BYTES,
+				   PCI_DMA_FROMDEVICE);
+		pkt_info.return_info = skb;
+		if (eth_rx_return_buff(mp, &pkt_info) != ETH_OK) {
+			printk(KERN_ERR
+			       "%s: Error allocating RX Ring\n", dev->name);
+			break;
+		}
+		skb_reserve(skb, 2);
+	}
+	clear_bit(0, &mp->rx_task_busy);
+	/*
+	 * If RX ring is empty of SKB, set a timer to try allocating
+	 * again in a later time .
+	 */
+	if ((mp->rx_ring_skbs == 0) && (mp->rx_timer_flag == 0)) {
+		printk(KERN_INFO "%s: Rx ring is empty\n", dev->name);
+		/* After 100mSec */
+		mp->timeout.expires = jiffies + (HZ / 10);
+		add_timer(&mp->timeout);
+		mp->rx_timer_flag = 1;
+	}
+#if MV64340_RX_QUEUE_FILL_ON_TASK
+	else {
+		/* Return interrupts */
+		MV_WRITE(MV64340_ETH_INTERRUPT_MASK_REG(mp->port_num),
+			 INT_CAUSE_UNMASK_ALL);
+	}
+#endif
+}
+
+/*
+ * mv64340_eth_rx_task_timer_wrapper
+ *								       
+ * Timer routine to wake up RX queue filling task. This function is
+ * used only in case the RX queue is empty, and all alloc_skb has
+ * failed (due to out of memory event).
+ *
+ * Input : pointer to ethernet interface network device structure
+ * Output : N/A
+ */
+static void mv64340_eth_rx_task_timer_wrapper(unsigned long data)
+{
+	struct net_device *dev = (struct net_device *) data;
+	struct mv64340_private *mp = netdev_priv(dev);
+
+	mp->rx_timer_flag = 0;
+	mv64340_eth_rx_task((void *) data);
+}
+
+
+/*
+ * mv64340_eth_update_mac_address
+ *								       
+ * Update the MAC address of the port in the address table
+ *
+ * Input : pointer to ethernet interface network device structure
+ * Output : N/A
+ */
+static void mv64340_eth_update_mac_address(struct net_device *dev)
+{
+	struct mv64340_private *mp = netdev_priv(dev);
+	unsigned int port_num = mp->port_num;
+
+	eth_port_init_mac_tables(port_num);
+	memcpy(mp->port_mac_addr, dev->dev_addr, 6);
+	eth_port_uc_addr_set(port_num, mp->port_mac_addr);
+}
+
+/*
+ * mv64340_eth_set_rx_mode
+ *								       
+ * Change from promiscuos to regular rx mode
+ *
+ * Input : pointer to ethernet interface network device structure
+ * Output : N/A
+ */
+static void mv64340_eth_set_rx_mode(struct net_device *dev)
+{
+	struct mv64340_private *mp = netdev_priv(dev);
+
+	if (dev->flags & IFF_PROMISC) {
+		ethernet_set_config_reg
+		    (mp->port_num,
+		     ethernet_get_config_reg(mp->port_num) |
+		     ETH_UNICAST_PROMISCUOUS_MODE);
+	} else {
+		ethernet_set_config_reg
+		    (mp->port_num,
+		     ethernet_get_config_reg(mp->port_num) &
+		     ~(unsigned int) ETH_UNICAST_PROMISCUOUS_MODE);
+	}
+}
+
+
+/*
+ * mv64340_eth_set_mac_address
+ *								       
+ * Change the interface's mac address.
+ * No special hardware thing should be done because interface is always
+ * put in promiscuous mode.
+ *
+ * Input : pointer to ethernet interface network device structure and
+ *         a pointer to the designated entry to be added to the cache.
+ * Output : zero upon success, negative upon failure
+ */
+static int mv64340_eth_set_mac_address(struct net_device *dev, void *addr)
+{
+	int i;
+
+	for (i = 0; i < 6; i++)
+		/* +2 is for the offset of the HW addr type */
+		dev->dev_addr[i] = ((unsigned char *) addr)[i + 2];
+	mv64340_eth_update_mac_address(dev);
+	return 0;
+}
+
+/*
+ * mv64340_eth_tx_timeout
+ *								       
+ * Called upon a timeout on transmitting a packet
+ *
+ * Input : pointer to ethernet interface network device structure.
+ * Output : N/A
+ */
+static void mv64340_eth_tx_timeout(struct net_device *dev)
+{
+	struct mv64340_private *mp = netdev_priv(dev);
+
+	printk(KERN_INFO "%s: TX timeout  ", dev->name);
+
+	/* Do the reset outside of interrupt context */
+	schedule_work(&mp->tx_timeout_task);
+}
+
+/*
+ * mv64340_eth_tx_timeout_task
+ *
+ * Actual routine to reset the adapter when a timeout on Tx has occurred
+ */
+static void mv64340_eth_tx_timeout_task(struct net_device *dev)
+{
+        struct mv64340_private *mp = netdev_priv(dev);
+
+        netif_device_detach(dev);
+        eth_port_reset(mp->port_num);
+        eth_port_start(mp);
+        netif_device_attach(dev);
+}
+
+/*
+ * mv64340_eth_free_tx_queue
+ *
+ * Input : dev - a pointer to the required interface
+ *
+ * Output : 0 if was able to release skb , nonzero otherwise
+ */
+static int mv64340_eth_free_tx_queue(struct net_device *dev,
+			      unsigned int eth_int_cause_ext)
+{
+	struct mv64340_private *mp = netdev_priv(dev);
+	struct net_device_stats *stats = &mp->stats;
+	struct pkt_info pkt_info;
+	int released = 1;
+
+	if (!(eth_int_cause_ext & (BIT0 | BIT8)))
+		return released;
+
+	spin_lock(&mp->lock);
+
+	/* Check only queue 0 */
+	while (eth_tx_return_desc(mp, &pkt_info) == ETH_OK) {
+		if (pkt_info.cmd_sts & BIT0) {
+			printk("%s: Error in TX\n", dev->name);
+			stats->tx_errors++;
+		}
+
+		/* 
+		 * If return_info is different than 0, release the skb.
+		 * The case where return_info is not 0 is only in case
+		 * when transmitted a scatter/gather packet, where only
+		 * last skb releases the whole chain.
+		 */
+		if (pkt_info.return_info) {
+			dev_kfree_skb_irq((struct sk_buff *)
+					  pkt_info.return_info);
+			released = 0;
+			if (skb_shinfo(pkt_info.return_info)->nr_frags)
+				pci_unmap_page(NULL, pkt_info.buf_ptr,
+					pkt_info.byte_cnt, PCI_DMA_TODEVICE);
+
+			if (mp->tx_ring_skbs != 1)
+				mp->tx_ring_skbs--;
+		} else 
+			pci_unmap_page(NULL, pkt_info.buf_ptr,
+					pkt_info.byte_cnt, PCI_DMA_TODEVICE);
+
+		/* 
+		 * Decrement the number of outstanding skbs counter on
+		 * the TX queue.
+		 */
+		if (mp->tx_ring_skbs == 0)
+			panic("ERROR - TX outstanding SKBs counter is corrupted");
+
+	}
+
+	spin_unlock(&mp->lock);
+
+	return released;
+}
+
+/*
+ * mv64340_eth_receive
+ *
+ * This function is forward packets that are received from the port's
+ * queues toward kernel core or FastRoute them to another interface.
+ *
+ * Input : dev - a pointer to the required interface
+ *         max - maximum number to receive (0 means unlimted)
+ *
+ * Output : number of served packets
+ */
+#ifdef MV64340_NAPI
+static int mv64340_eth_receive_queue(struct net_device *dev, unsigned int max,
+								int budget)
+#else
+static int mv64340_eth_receive_queue(struct net_device *dev, unsigned int max)
+#endif
+{
+	struct mv64340_private *mp = netdev_priv(dev);
+	struct net_device_stats *stats = &mp->stats;
+	unsigned int received_packets = 0;
+	struct sk_buff *skb;
+	struct pkt_info pkt_info;
+
+#ifdef MV64340_NAPI
+	while (eth_port_receive(mp, &pkt_info) == ETH_OK && budget > 0) {
+#else
+	while ((--max) && eth_port_receive(mp, &pkt_info) == ETH_OK) {
+#endif
+		mp->rx_ring_skbs--;
+		received_packets++;
+#ifdef MV64340_NAPI
+		budget--;
+#endif
+		/* Update statistics. Note byte count includes 4 byte CRC count */
+		stats->rx_packets++;
+		stats->rx_bytes += pkt_info.byte_cnt;
+		skb = (struct sk_buff *) pkt_info.return_info;
+		/*
+		 * In case received a packet without first / last bits on OR
+		 * the error summary bit is on, the packets needs to be dropeed.
+		 */
+		if (((pkt_info.cmd_sts
+		      & (ETH_RX_FIRST_DESC | ETH_RX_LAST_DESC)) !=
+		     (ETH_RX_FIRST_DESC | ETH_RX_LAST_DESC))
+		    || (pkt_info.cmd_sts & ETH_ERROR_SUMMARY)) {
+			stats->rx_dropped++;
+			if ((pkt_info.cmd_sts & (ETH_RX_FIRST_DESC |
+						 ETH_RX_LAST_DESC)) !=
+			    (ETH_RX_FIRST_DESC | ETH_RX_LAST_DESC)) {
+				if (net_ratelimit())
+					printk(KERN_ERR
+					       "%s: Received packet spread on multiple"
+					       " descriptors\n",
+					       dev->name);
+			}
+			if (pkt_info.cmd_sts & ETH_ERROR_SUMMARY)
+				stats->rx_errors++;
+
+			dev_kfree_skb_irq(skb);
+		} else {
+			/*
+			 * The -4 is for the CRC in the trailer of the
+			 * received packet
+			 */
+			skb_put(skb, pkt_info.byte_cnt - 4);
+			skb->dev = dev;
+
+			if (pkt_info.cmd_sts & ETH_LAYER_4_CHECKSUM_OK) {
+				skb->ip_summed = CHECKSUM_UNNECESSARY;
+				skb->csum = htons((pkt_info.cmd_sts
+							& 0x0007fff8) >> 3);
+			}
+			skb->protocol = eth_type_trans(skb, dev);
+#ifdef MV64340_NAPI
+			netif_receive_skb(skb);
+#else
+			netif_rx(skb);
+#endif
+		}
+	}
+
+	return received_packets;
+}
+
+/*
+ * mv64340_eth_int_handler
+ *
+ * Main interrupt handler for the gigbit ethernet ports
+ *
+ * Input : irq - irq number (not used)
+ *         dev_id - a pointer to the required interface's data structure
+ *         regs   - not used
+ * Output : N/A
+ */
+
+static irqreturn_t mv64340_eth_int_handler(int irq, void *dev_id,
+	struct pt_regs *regs)
+{
+	struct net_device *dev = (struct net_device *) dev_id;
+	struct mv64340_private *mp = netdev_priv(dev);
+	u32 eth_int_cause, eth_int_cause_ext = 0;
+	unsigned int port_num = mp->port_num;
+
+	/* Read interrupt cause registers */
+	eth_int_cause = MV_READ(MV64340_ETH_INTERRUPT_CAUSE_REG(port_num)) &
+			INT_CAUSE_UNMASK_ALL;
+
+	if (eth_int_cause & BIT1)
+		eth_int_cause_ext =
+		MV_READ(MV64340_ETH_INTERRUPT_CAUSE_EXTEND_REG(port_num)) &
+		INT_CAUSE_UNMASK_ALL_EXT;
+
+#ifdef MV64340_NAPI
+	if (!(eth_int_cause & 0x0007fffd)) {
+	/* Dont ack the Rx interrupt */
+#endif
+		/*
+	 	 * Clear specific ethernet port intrerrupt registers by
+		 * acknowleding relevant bits.
+		 */
+		MV_WRITE(MV64340_ETH_INTERRUPT_CAUSE_REG(port_num),
+			 ~eth_int_cause);
+		if (eth_int_cause_ext != 0x0)
+			MV_WRITE(MV64340_ETH_INTERRUPT_CAUSE_EXTEND_REG(port_num),
+				 ~eth_int_cause_ext);
+
+		/* UDP change : We may need this */
+		if ((eth_int_cause_ext & 0x0000ffff) &&
+		    (mv64340_eth_free_tx_queue(dev, eth_int_cause_ext) == 0) &&
+		    (MV64340_TX_QUEUE_SIZE > mp->tx_ring_skbs + 1))
+                                         netif_wake_queue(dev);
+#ifdef MV64340_NAPI
+	} else {
+		if (netif_rx_schedule_prep(dev)) {
+			/* Mask all the interrupts */
+			MV_WRITE(MV64340_ETH_INTERRUPT_MASK_REG(port_num),0);
+			MV_WRITE(MV64340_ETH_INTERRUPT_EXTEND_MASK_REG(port_num), 0);
+			__netif_rx_schedule(dev);
+		}
+#else
+		{
+		if (eth_int_cause & (BIT2 | BIT11))
+			mv64340_eth_receive_queue(dev, 0);
+
+		/*
+		 * After forwarded received packets to upper layer,  add a task
+		 * in an interrupts enabled context that refills the RX ring
+		 * with skb's.
+		 */
+#if MV64340_RX_QUEUE_FILL_ON_TASK
+		/* Unmask all interrupts on ethernet port */
+		MV_WRITE(MV64340_ETH_INTERRUPT_MASK_REG(port_num),
+		         INT_CAUSE_MASK_ALL);
+		queue_task(&mp->rx_task, &tq_immediate);
+		mark_bh(IMMEDIATE_BH);
+#else
+		mp->rx_task.func(dev);
+#endif
+#endif
+	}
+	/* PHY status changed */
+	if (eth_int_cause_ext & (BIT16 | BIT20)) {
+		unsigned int phy_reg_data;
+
+		/* Check Link status on ethernet port */
+		eth_port_read_smi_reg(port_num, 1, &phy_reg_data);
+		if (!(phy_reg_data & 0x20)) {
+			netif_stop_queue(dev);
+		} else {
+			netif_wake_queue(dev);
+
+			/*
+			 * Start all TX queues on ethernet port. This is good in
+			 * case of previous packets where not transmitted, due
+			 * to link down and this command re-enables all TX
+			 * queues.
+			 * Note that it is possible to get a TX resource error
+			 * interrupt after issuing this, since not all TX queues
+			 * are enabled, or has anything to send.
+			 */
+			MV_WRITE(MV64340_ETH_TRANSMIT_QUEUE_COMMAND_REG(port_num), 1);
+		}
+	}
+
+	/*
+	 * If no real interrupt occured, exit.
+	 * This can happen when using gigE interrupt coalescing mechanism.
+	 */
+	if ((eth_int_cause == 0x0) && (eth_int_cause_ext == 0x0))
+		return IRQ_NONE;
+
+	return IRQ_HANDLED;
+}
+
+#ifdef MV64340_COAL
+
+/*
+ * eth_port_set_rx_coal - Sets coalescing interrupt mechanism on RX path
+ *
+ * DESCRIPTION:
+ *	This routine sets the RX coalescing interrupt mechanism parameter.
+ *	This parameter is a timeout counter, that counts in 64 t_clk
+ *	chunks ; that when timeout event occurs a maskable interrupt
+ *	occurs.
+ *	The parameter is calculated using the tClk of the MV-643xx chip
+ *	, and the required delay of the interrupt in usec.
+ *
+ * INPUT:
+ *	unsigned int eth_port_num      Ethernet port number
+ *	unsigned int t_clk        t_clk of the MV-643xx chip in HZ units
+ *	unsigned int delay       Delay in usec
+ *
+ * OUTPUT:
+ *	Interrupt coalescing mechanism value is set in MV-643xx chip.
+ *
+ * RETURN:
+ *	The interrupt coalescing value set in the gigE port.
+ *
+ */
+static unsigned int eth_port_set_rx_coal(unsigned int eth_port_num,
+	unsigned int t_clk, unsigned int delay)
+{
+	unsigned int coal = ((t_clk / 1000000) * delay) / 64;
+
+	/* Set RX Coalescing mechanism */
+	MV_WRITE(MV64340_ETH_SDMA_CONFIG_REG(eth_port_num),
+		 ((coal & 0x3fff) << 8) |
+		 (MV_READ(MV64340_ETH_SDMA_CONFIG_REG(eth_port_num))
+		  & 0xffc000ff));
+
+	return coal;
+}
+#endif
+
+/*
+ * eth_port_set_tx_coal - Sets coalescing interrupt mechanism on TX path
+ *
+ * DESCRIPTION:
+ *	This routine sets the TX coalescing interrupt mechanism parameter.
+ *	This parameter is a timeout counter, that counts in 64 t_clk
+ *	chunks ; that when timeout event occurs a maskable interrupt
+ *	occurs.
+ *	The parameter is calculated using the t_cLK frequency of the 
+ *	MV-643xx chip and the required delay in the interrupt in uSec
+ *
+ * INPUT:
+ *	unsigned int eth_port_num      Ethernet port number
+ *	unsigned int t_clk        t_clk of the MV-643xx chip in HZ units
+ *	unsigned int delay       Delay in uSeconds
+ *
+ * OUTPUT:
+ *	Interrupt coalescing mechanism value is set in MV-643xx chip.
+ *
+ * RETURN:
+ *	The interrupt coalescing value set in the gigE port.
+ *
+ */
+static unsigned int eth_port_set_tx_coal(unsigned int eth_port_num,
+	unsigned int t_clk, unsigned int delay)
+{
+	unsigned int coal;
+	coal = ((t_clk / 1000000) * delay) / 64;
+	/* Set TX Coalescing mechanism */
+	MV_WRITE(MV64340_ETH_TX_FIFO_URGENT_THRESHOLD_REG(eth_port_num),
+		 coal << 4);
+	return coal;
+}
+
+/*
+ * mv64340_eth_open
+ *
+ * This function is called when openning the network device. The function
+ * should initialize all the hardware, initialize cyclic Rx/Tx
+ * descriptors chain and buffers and allocate an IRQ to the network
+ * device.
+ *
+ * Input : a pointer to the network device structure
+ *
+ * Output : zero of success , nonzero if fails.
+ */
+
+static int mv64340_eth_open(struct net_device *dev)
+{
+	struct mv64340_private *mp = netdev_priv(dev);
+	unsigned int port_num = mp->port_num;
+	int err = err;
+
+	spin_lock_irq(&mp->lock);
+
+	err = request_irq(dev->irq, mv64340_eth_int_handler,
+	                  SA_INTERRUPT | SA_SAMPLE_RANDOM, dev->name, dev);
+
+	if (err) {
+		printk(KERN_ERR "Can not assign IRQ number to MV64340_eth%d\n",
+		       port_num);
+		err = -EAGAIN;
+		goto out;
+	}
+
+	if (mv64340_eth_real_open(dev)) {
+		printk("%s: Error opening interface\n", dev->name);
+		err = -EBUSY;
+		goto out_free;
+	}
+
+	spin_unlock_irq(&mp->lock);
+
+	return 0;
+
+out_free:
+	free_irq(dev->irq, dev);
+
+out:
+	spin_unlock_irq(&mp->lock);
+
+	return err;
+}
+
+/*
+ * ether_init_rx_desc_ring - Curve a Rx chain desc list and buffer in memory.
+ *
+ * DESCRIPTION:
+ *       This function prepares a Rx chained list of descriptors and packet 
+ *       buffers in a form of a ring. The routine must be called after port 
+ *       initialization routine and before port start routine. 
+ *       The Ethernet SDMA engine uses CPU bus addresses to access the various 
+ *       devices in the system (i.e. DRAM). This function uses the ethernet 
+ *       struct 'virtual to physical' routine (set by the user) to set the ring 
+ *       with physical addresses.
+ *
+ * INPUT:
+ *	struct mv64340_private   *mp   Ethernet Port Control srtuct. 
+ *      int 			rx_desc_num       Number of Rx descriptors
+ *      int 			rx_buff_size      Size of Rx buffer
+ *      unsigned int    rx_desc_base_addr  Rx descriptors memory area base addr.
+ *      unsigned int    rx_buff_base_addr  Rx buffer memory area base addr.
+ *
+ * OUTPUT:
+ *      The routine updates the Ethernet port control struct with information 
+ *      regarding the Rx descriptors and buffers.
+ *
+ * RETURN:
+ *      false if the given descriptors memory area is not aligned according to
+ *      Ethernet SDMA specifications.
+ *      true otherwise.
+ */
+static int ether_init_rx_desc_ring(struct mv64340_private * mp,
+	unsigned long rx_buff_base_addr)
+{
+	unsigned long buffer_addr = rx_buff_base_addr;
+	volatile struct eth_rx_desc *p_rx_desc;
+	int rx_desc_num = mp->rx_ring_size;
+	unsigned long rx_desc_base_addr = (unsigned long) mp->p_rx_desc_area;
+	int rx_buff_size = 1536;	/* Dummy, will be replaced later */
+	int i;
+
+	p_rx_desc = (struct eth_rx_desc *) rx_desc_base_addr;
+
+	/* Rx desc Must be 4LW aligned (i.e. Descriptor_Address[3:0]=0000). */
+	if (rx_buff_base_addr & 0xf)
+		return 0;
+
+	/* Rx buffers are limited to 64K bytes and Minimum size is 8 bytes  */
+	if ((rx_buff_size < 8) || (rx_buff_size > RX_BUFFER_MAX_SIZE))
+		return 0;
+
+	/* Rx buffers must be 64-bit aligned.       */
+	if ((rx_buff_base_addr + rx_buff_size) & 0x7)
+		return 0;
+
+	/* initialize the Rx descriptors ring */
+	for (i = 0; i < rx_desc_num; i++) {
+		p_rx_desc[i].buf_size = rx_buff_size;
+		p_rx_desc[i].byte_cnt = 0x0000;
+		p_rx_desc[i].cmd_sts =
+			ETH_BUFFER_OWNED_BY_DMA | ETH_RX_ENABLE_INTERRUPT;
+		p_rx_desc[i].next_desc_ptr = mp->rx_desc_dma +
+			((i + 1) % rx_desc_num) * sizeof(struct eth_rx_desc);
+		p_rx_desc[i].buf_ptr = buffer_addr;
+
+		mp->rx_skb[i] = NULL;
+		buffer_addr += rx_buff_size;
+	}
+
+	/* Save Rx desc pointer to driver struct. */
+	mp->rx_curr_desc_q = 0;
+	mp->rx_used_desc_q = 0;
+
+	mp->rx_desc_area_size = rx_desc_num * sizeof(struct eth_rx_desc);
+
+	mp->port_rx_queue_command |= 1;
+
+	return 1;
+}
+
+/*
+ * ether_init_tx_desc_ring - Curve a Tx chain desc list and buffer in memory.
+ *
+ * DESCRIPTION:
+ *       This function prepares a Tx chained list of descriptors and packet 
+ *       buffers in a form of a ring. The routine must be called after port 
+ *       initialization routine and before port start routine. 
+ *       The Ethernet SDMA engine uses CPU bus addresses to access the various 
+ *       devices in the system (i.e. DRAM). This function uses the ethernet 
+ *       struct 'virtual to physical' routine (set by the user) to set the ring 
+ *       with physical addresses.
+ *
+ * INPUT:
+ *	struct mv64340_private   *mp   Ethernet Port Control srtuct. 
+ *      int 		tx_desc_num        Number of Tx descriptors
+ *      int 		tx_buff_size	   Size of Tx buffer
+ *      unsigned int    tx_desc_base_addr  Tx descriptors memory area base addr.
+ *
+ * OUTPUT:
+ *      The routine updates the Ethernet port control struct with information 
+ *      regarding the Tx descriptors and buffers.
+ *
+ * RETURN:
+ *      false if the given descriptors memory area is not aligned according to
+ *      Ethernet SDMA specifications.
+ *      true otherwise.
+ */
+static int ether_init_tx_desc_ring(struct mv64340_private *mp)
+{
+	unsigned long tx_desc_base_addr = (unsigned long) mp->p_tx_desc_area;
+	int tx_desc_num = mp->tx_ring_size;
+	struct eth_tx_desc *p_tx_desc;
+	int i;
+
+	/* Tx desc Must be 4LW aligned (i.e. Descriptor_Address[3:0]=0000). */
+	if (tx_desc_base_addr & 0xf)
+		return 0;
+
+	/* save the first desc pointer to link with the last descriptor */
+	p_tx_desc = (struct eth_tx_desc *) tx_desc_base_addr;
+
+	/* Initialize the Tx descriptors ring */
+	for (i = 0; i < tx_desc_num; i++) {
+		p_tx_desc[i].byte_cnt	= 0x0000;
+		p_tx_desc[i].l4i_chk	= 0x0000;
+		p_tx_desc[i].cmd_sts	= 0x00000000;
+		p_tx_desc[i].next_desc_ptr = mp->tx_desc_dma +
+			((i + 1) % tx_desc_num) * sizeof(struct eth_tx_desc);
+		p_tx_desc[i].buf_ptr	= 0x00000000;
+		mp->tx_skb[i]		= NULL;
+	}
+
+	/* Set Tx desc pointer in driver struct. */
+	mp->tx_curr_desc_q = 0;
+	mp->tx_used_desc_q = 0;
+#ifdef MV64340_CHECKSUM_OFFLOAD_TX
+        mp->tx_first_desc_q = 0;
+#endif
+	/* Init Tx ring base and size parameters */
+	mp->tx_desc_area_size	= tx_desc_num * sizeof(struct eth_tx_desc);
+
+	/* Add the queue to the list of Tx queues of this port */
+	mp->port_tx_queue_command |= 1;
+
+	return 1;
+}
+
+/* Helper function for mv64340_eth_open */
+static int mv64340_eth_real_open(struct net_device *dev)
+{
+	struct mv64340_private *mp = netdev_priv(dev);
+	unsigned int port_num = mp->port_num;
+	u32 phy_reg_data;
+	unsigned int size;
+
+	/* Stop RX Queues */
+	MV_WRITE(MV64340_ETH_RECEIVE_QUEUE_COMMAND_REG(port_num),
+		 0x0000ff00);
+
+	/* Clear the ethernet port interrupts */
+	MV_WRITE(MV64340_ETH_INTERRUPT_CAUSE_REG(port_num), 0);
+	MV_WRITE(MV64340_ETH_INTERRUPT_CAUSE_EXTEND_REG(port_num), 0);
+
+	/* Unmask RX buffer and TX end interrupt */
+	MV_WRITE(MV64340_ETH_INTERRUPT_MASK_REG(port_num),
+		 INT_CAUSE_UNMASK_ALL);
+
+	/* Unmask phy and link status changes interrupts */
+	MV_WRITE(MV64340_ETH_INTERRUPT_EXTEND_MASK_REG(port_num),
+		 INT_CAUSE_UNMASK_ALL_EXT);
+
+	/* Set the MAC Address */
+	memcpy(mp->port_mac_addr, dev->dev_addr, 6);
+
+	eth_port_init(mp);
+
+	INIT_WORK(&mp->rx_task, (void (*)(void *)) mv64340_eth_rx_task, dev);
+
+	memset(&mp->timeout, 0, sizeof(struct timer_list));
+	mp->timeout.function = mv64340_eth_rx_task_timer_wrapper;
+	mp->timeout.data = (unsigned long) dev;
+
+	mp->rx_task_busy = 0;
+	mp->rx_timer_flag = 0;
+
+	/* Allocate TX ring */
+	mp->tx_ring_skbs = 0;
+	mp->tx_ring_size = MV64340_TX_QUEUE_SIZE;
+	size = mp->tx_ring_size * sizeof(struct eth_tx_desc);
+	mp->tx_desc_area_size = size;
+
+	/* Assumes allocated ring is 16 bytes alligned */
+	mp->p_tx_desc_area = pci_alloc_consistent(NULL, size, &mp->tx_desc_dma);
+	if (!mp->p_tx_desc_area) {
+		printk(KERN_ERR "%s: Cannot allocate Tx Ring (size %d bytes)\n",
+		       dev->name, size);
+		return -ENOMEM;
+	}
+	memset((void *) mp->p_tx_desc_area, 0, mp->tx_desc_area_size);
+
+	/* Dummy will be replaced upon real tx */
+	ether_init_tx_desc_ring(mp);
+
+	/* Allocate RX ring */
+	/* Meantime RX Ring are fixed - but must be configurable by user */
+	mp->rx_ring_size = MV64340_RX_QUEUE_SIZE;
+	mp->rx_ring_skbs = 0;
+	size = mp->rx_ring_size * sizeof(struct eth_rx_desc);
+	mp->rx_desc_area_size = size;
+
+	/* Assumes allocated ring is 16 bytes aligned */
+
+	mp->p_rx_desc_area = pci_alloc_consistent(NULL, size, &mp->rx_desc_dma);
+
+	if (!mp->p_rx_desc_area) {
+		printk(KERN_ERR "%s: Cannot allocate Rx ring (size %d bytes)\n",
+		       dev->name, size);
+		printk(KERN_ERR "%s: Freeing previously allocated TX queues...",
+		       dev->name);
+		pci_free_consistent(0, mp->tx_desc_area_size,
+				    (void *) mp->p_tx_desc_area,
+				    mp->tx_desc_dma);
+		return -ENOMEM;
+	}
+	memset(mp->p_rx_desc_area, 0, size);
+
+	if (!(ether_init_rx_desc_ring(mp, 0)))
+		panic("%s: Error initializing RX Ring", dev->name);
+
+	mv64340_eth_rx_task(dev);	/* Fill RX ring with skb's */
+
+	eth_port_start(mp);
+
+	/* Interrupt Coalescing */
+
+#ifdef MV64340_COAL
+	mp->rx_int_coal =
+		eth_port_set_rx_coal(port_num, 133000000, MV64340_RX_COAL);
+#endif
+
+	mp->tx_int_coal =
+		eth_port_set_tx_coal (port_num, 133000000, MV64340_TX_COAL);  
+
+	/* Increase the Rx side buffer size */
+
+	MV_WRITE (MV64340_ETH_PORT_SERIAL_CONTROL_REG(port_num), (0x5 << 17) |
+			(MV_READ(MV64340_ETH_PORT_SERIAL_CONTROL_REG(port_num))
+					& 0xfff1ffff));
+
+	/* Check Link status on phy */
+	eth_port_read_smi_reg(port_num, 1, &phy_reg_data);
+	if (!(phy_reg_data & 0x20))
+		netif_stop_queue(dev);
+	else
+		netif_start_queue(dev);
+
+	return 0;
+}
+
+static void mv64340_eth_free_tx_rings(struct net_device *dev)
+{
+	struct mv64340_private *mp = netdev_priv(dev);
+	unsigned int port_num = mp->port_num;
+	unsigned int curr;
+
+	/* Stop Tx Queues */
+	MV_WRITE(MV64340_ETH_TRANSMIT_QUEUE_COMMAND_REG(port_num),
+		 0x0000ff00);
+
+	/* Free TX rings */
+	/* Free outstanding skb's on TX rings */
+	for (curr = 0;
+	     (mp->tx_ring_skbs) && (curr < MV64340_TX_QUEUE_SIZE);
+	     curr++) {
+		if (mp->tx_skb[curr]) {
+			dev_kfree_skb(mp->tx_skb[curr]);
+			mp->tx_ring_skbs--;
+		}
+	}
+	if (mp->tx_ring_skbs != 0)
+		printk("%s: Error on Tx descriptor free - could not free %d"
+		     " descriptors\n", dev->name,
+		     mp->tx_ring_skbs);
+	pci_free_consistent(0, mp->tx_desc_area_size,
+			    (void *) mp->p_tx_desc_area, mp->tx_desc_dma);
+}
+
+static void mv64340_eth_free_rx_rings(struct net_device *dev)
+{
+	struct mv64340_private *mp = netdev_priv(dev);
+	unsigned int port_num = mp->port_num;
+	int curr;
+
+	/* Stop RX Queues */
+	MV_WRITE(MV64340_ETH_RECEIVE_QUEUE_COMMAND_REG(port_num),
+		 0x0000ff00);
+
+	/* Free RX rings */
+	/* Free preallocated skb's on RX rings */
+	for (curr = 0;
+		mp->rx_ring_skbs && (curr < MV64340_RX_QUEUE_SIZE);
+		curr++) {
+		if (mp->rx_skb[curr]) {
+			dev_kfree_skb(mp->rx_skb[curr]);
+			mp->rx_ring_skbs--;
+		}
+	}
+
+	if (mp->rx_ring_skbs != 0)
+		printk(KERN_ERR
+		       "%s: Error in freeing Rx Ring. %d skb's still"
+		       " stuck in RX Ring - ignoring them\n", dev->name,
+		       mp->rx_ring_skbs);
+	pci_free_consistent(0, mp->rx_desc_area_size,
+			    (void *) mp->p_rx_desc_area,
+			    mp->rx_desc_dma);
+}
+
+/*
+ * mv64340_eth_stop
+ *
+ * This function is used when closing the network device. 
+ * It updates the hardware, 
+ * release all memory that holds buffers and descriptors and release the IRQ.
+ * Input : a pointer to the device structure
+ * Output : zero if success , nonzero if fails
+ */
+
+/* Helper function for mv64340_eth_stop */
+
+static int mv64340_eth_real_stop(struct net_device *dev)
+{
+	struct mv64340_private *mp = netdev_priv(dev);
+	unsigned int port_num = mp->port_num;
+
+	netif_stop_queue(dev);
+
+	mv64340_eth_free_tx_rings(dev);
+	mv64340_eth_free_rx_rings(dev);
+
+	eth_port_reset(mp->port_num);
+
+	/* Disable ethernet port interrupts */
+	MV_WRITE(MV64340_ETH_INTERRUPT_CAUSE_REG(port_num), 0);
+	MV_WRITE(MV64340_ETH_INTERRUPT_CAUSE_EXTEND_REG(port_num), 0);
+
+	/* Mask RX buffer and TX end interrupt */
+	MV_WRITE(MV64340_ETH_INTERRUPT_MASK_REG(port_num), 0);
+
+	/* Mask phy and link status changes interrupts */
+	MV_WRITE(MV64340_ETH_INTERRUPT_EXTEND_MASK_REG(port_num), 0);
+
+	return 0;
+}
+
+static int mv64340_eth_stop(struct net_device *dev)
+{
+	struct mv64340_private *mp = netdev_priv(dev);
+
+	spin_lock_irq(&mp->lock);
+
+	mv64340_eth_real_stop(dev);
+
+	free_irq(dev->irq, dev);
+	spin_unlock_irq(&mp->lock);
+
+	return 0;
+}
+
+#ifdef MV64340_NAPI
+static void mv64340_tx(struct net_device *dev)
+{
+	struct mv64340_private *mp = netdev_priv(dev);
+        struct pkt_info pkt_info;
+
+	while (eth_tx_return_desc(mp, &pkt_info) == ETH_OK) {
+		if (pkt_info.return_info) {
+			dev_kfree_skb_irq((struct sk_buff *)
+                                                  pkt_info.return_info);
+			if (skb_shinfo(pkt_info.return_info)->nr_frags) 
+                                 pci_unmap_page(NULL, pkt_info.buf_ptr,
+                                             pkt_info.byte_cnt,
+                                             PCI_DMA_TODEVICE);
+
+                         if (mp->tx_ring_skbs != 1)
+                                  mp->tx_ring_skbs--;
+                } else 
+                       pci_unmap_page(NULL, pkt_info.buf_ptr, pkt_info.byte_cnt,
+                                      PCI_DMA_TODEVICE);
+	}
+
+	if (netif_queue_stopped(dev) &&
+            MV64340_TX_QUEUE_SIZE > mp->tx_ring_skbs + 1)
+                       netif_wake_queue(dev);
+}
+
+/*
+ * mv64340_poll
+ *
+ * This function is used in case of NAPI
+ */
+static int mv64340_poll(struct net_device *dev, int *budget)
+{
+	struct mv64340_private *mp = netdev_priv(dev);
+	int	done = 1, orig_budget, work_done;
+	unsigned int port_num = mp->port_num;
+	unsigned long flags;
+
+#ifdef MV64340_TX_FAST_REFILL
+	if (++mp->tx_clean_threshold > 5) {
+		spin_lock_irqsave(&mp->lock, flags);
+		mv64340_tx(dev);
+		mp->tx_clean_threshold = 0;
+		spin_unlock_irqrestore(&mp->lock, flags);
+	}
+#endif
+
+	if ((u32)(MV_READ(MV64340_ETH_RX_CURRENT_QUEUE_DESC_PTR_0(port_num)))                                      != (u32)mp->rx_used_desc_q) {
+		orig_budget = *budget;
+		if (orig_budget > dev->quota)
+			orig_budget = dev->quota;
+		work_done = mv64340_eth_receive_queue(dev, 0, orig_budget);
+		mp->rx_task.func(dev);
+		*budget -= work_done;
+		dev->quota -= work_done;
+		if (work_done >= orig_budget)
+			done = 0;
+	}
+
+	if (done) {
+		spin_lock_irqsave(&mp->lock, flags);
+		__netif_rx_complete(dev);
+		MV_WRITE(MV64340_ETH_INTERRUPT_CAUSE_REG(port_num),0);
+                MV_WRITE(MV64340_ETH_INTERRUPT_CAUSE_EXTEND_REG(port_num),0);
+		MV_WRITE(MV64340_ETH_INTERRUPT_MASK_REG(port_num), 
+						INT_CAUSE_UNMASK_ALL);
+		MV_WRITE(MV64340_ETH_INTERRUPT_EXTEND_MASK_REG(port_num),
+				                 INT_CAUSE_UNMASK_ALL_EXT);
+		spin_unlock_irqrestore(&mp->lock, flags);
+	}
+
+	return done ? 0 : 1;
+}
+#endif
+
+/*
+ * mv64340_eth_start_xmit
+ *
+ * This function is queues a packet in the Tx descriptor for 
+ * required port.
+ *
+ * Input : skb - a pointer to socket buffer
+ *         dev - a pointer to the required port
+ *
+ * Output : zero upon success
+ */
+static int mv64340_eth_start_xmit(struct sk_buff *skb, struct net_device *dev)
+{
+	struct mv64340_private *mp = netdev_priv(dev);
+	struct net_device_stats *stats = &mp->stats;
+	ETH_FUNC_RET_STATUS status;
+	unsigned long flags;
+	struct pkt_info pkt_info;
+
+	if (netif_queue_stopped(dev)) {
+		printk(KERN_ERR
+		       "%s: Tried sending packet when interface is stopped\n",
+		       dev->name);
+		return 1;
+	}
+
+	/* This is a hard error, log it. */
+	if ((MV64340_TX_QUEUE_SIZE - mp->tx_ring_skbs) <=
+	    (skb_shinfo(skb)->nr_frags + 1)) {
+		netif_stop_queue(dev);
+		printk(KERN_ERR
+		       "%s: Bug in mv64340_eth - Trying to transmit when"
+		       " queue full !\n", dev->name);
+		return 1;
+	}
+
+	/* Paranoid check - this shouldn't happen */
+	if (skb == NULL) {
+		stats->tx_dropped++;
+		return 1;
+	}
+
+	spin_lock_irqsave(&mp->lock, flags);
+
+	/* Update packet info data structure -- DMA owned, first last */
+#ifdef MV64340_CHECKSUM_OFFLOAD_TX
+	if (!skb_shinfo(skb)->nr_frags || (skb_shinfo(skb)->nr_frags > 3)) {
+#endif
+		pkt_info.cmd_sts = ETH_TX_ENABLE_INTERRUPT |
+	    	                   ETH_TX_FIRST_DESC | ETH_TX_LAST_DESC;
+
+		pkt_info.byte_cnt = skb->len;
+		pkt_info.buf_ptr = pci_map_single(0, skb->data, skb->len,
+		                                  PCI_DMA_TODEVICE);
+
+
+		pkt_info.return_info = skb;
+		status = eth_port_send(mp, &pkt_info);
+		if ((status == ETH_ERROR) || (status == ETH_QUEUE_FULL))
+			printk(KERN_ERR "%s: Error on transmitting packet\n",
+				       dev->name);
+		mp->tx_ring_skbs++;
+#ifdef MV64340_CHECKSUM_OFFLOAD_TX
+	} else {
+		unsigned int    frag;
+		u32		ipheader;
+
+                /* first frag which is skb header */
+                pkt_info.byte_cnt = skb_headlen(skb);
+                pkt_info.buf_ptr = pci_map_single(0, skb->data,
+                                        skb_headlen(skb), PCI_DMA_TODEVICE);
+                pkt_info.return_info = 0;
+                ipheader = skb->nh.iph->ihl << 11;
+                pkt_info.cmd_sts = ETH_TX_FIRST_DESC | 
+					ETH_GEN_TCP_UDP_CHECKSUM |
+					ETH_GEN_IP_V_4_CHECKSUM |
+                                        ipheader;
+		/* CPU already calculated pseudo header checksum. So, use it */
+                pkt_info.l4i_chk = skb->h.th->check;
+                status = eth_port_send(mp, &pkt_info);
+		if (status != ETH_OK) {
+	                if ((status == ETH_ERROR))
+        	                printk(KERN_ERR "%s: Error on transmitting packet\n", dev->name);
+	                if (status == ETH_QUEUE_FULL)
+        	                printk("Error on Queue Full \n");
+                	if (status == ETH_QUEUE_LAST_RESOURCE)
+                        	printk("Tx resource error \n");
+		}
+
+                /* Check for the remaining frags */
+                for (frag = 0; frag < skb_shinfo(skb)->nr_frags; frag++) {
+                        skb_frag_t *this_frag = &skb_shinfo(skb)->frags[frag];
+                        pkt_info.l4i_chk = 0x0000;
+                        pkt_info.cmd_sts = 0x00000000;
+
+                        /* Last Frag enables interrupt and frees the skb */
+                        if (frag == (skb_shinfo(skb)->nr_frags - 1)) {
+                                pkt_info.cmd_sts |= ETH_TX_ENABLE_INTERRUPT |
+                                                        ETH_TX_LAST_DESC;
+                                pkt_info.return_info = skb;
+                                mp->tx_ring_skbs++;
+                        }
+                        else {
+                                pkt_info.return_info = 0;
+                        }
+                        pkt_info.byte_cnt = this_frag->size;
+                        if (this_frag->size < 8)
+                                printk("%d : \n", skb_shinfo(skb)->nr_frags);
+
+                        pkt_info.buf_ptr = pci_map_page(NULL, this_frag->page,
+                                        this_frag->page_offset,
+                                        this_frag->size, PCI_DMA_TODEVICE);
+
+                        status = eth_port_send(mp, &pkt_info);
+
+			if (status != ETH_OK) {
+	                        if ((status == ETH_ERROR))
+        	                        printk(KERN_ERR "%s: Error on transmitting packet\n", dev->name);
+
+       		                 if (status == ETH_QUEUE_LAST_RESOURCE)
+                	                printk("Tx resource error \n");
+
+                        	if (status == ETH_QUEUE_FULL)
+                                	printk("Queue is full \n");
+			}
+                }
+        }
+#endif
+
+	/* Check if TX queue can handle another skb. If not, then
+	 * signal higher layers to stop requesting TX
+	 */
+	if (MV64340_TX_QUEUE_SIZE <= (mp->tx_ring_skbs + 1))
+		/* 
+		 * Stop getting skb's from upper layers.
+		 * Getting skb's from upper layers will be enabled again after
+		 * packets are released.
+		 */
+		netif_stop_queue(dev);
+
+	/* Update statistics and start of transmittion time */
+	stats->tx_bytes += skb->len;
+	stats->tx_packets++;
+	dev->trans_start = jiffies;
+
+	spin_unlock_irqrestore(&mp->lock, flags);
+
+	return 0;		/* success */
+}
+
+/*
+ * mv64340_eth_get_stats
+ *
+ * Returns a pointer to the interface statistics.
+ *
+ * Input : dev - a pointer to the required interface
+ *
+ * Output : a pointer to the interface's statistics
+ */
+
+static struct net_device_stats *mv64340_eth_get_stats(struct net_device *dev)
+{
+	struct mv64340_private *mp = netdev_priv(dev);
+
+	return &mp->stats;
+}
+
+/*/
+ * mv64340_eth_init
+ *								       
+ * First function called after registering the network device. 
+ * It's purpose is to initialize the device as an ethernet device, 
+ * fill the structure that was given in registration with pointers
+ * to functions, and setting the MAC address of the interface
+ *
+ * Input : number of port to initialize
+ * Output : -ENONMEM if failed , 0 if success
+ */
+static struct net_device *mv64340_eth_init(int port_num)
+{
+	struct mv64340_private *mp;
+	struct net_device *dev;
+	int err;
+
+	dev = alloc_etherdev(sizeof(struct mv64340_private));
+	if (!dev)
+		return NULL;
+
+	mp = netdev_priv(dev);
+
+	dev->irq = ETH_PORT0_IRQ_NUM + port_num;
+
+	dev->open = mv64340_eth_open;
+	dev->stop = mv64340_eth_stop;
+	dev->hard_start_xmit = mv64340_eth_start_xmit;
+	dev->get_stats = mv64340_eth_get_stats;
+	dev->set_mac_address = mv64340_eth_set_mac_address;
+	dev->set_multicast_list = mv64340_eth_set_rx_mode;
+
+	/* No need to Tx Timeout */
+	dev->tx_timeout = mv64340_eth_tx_timeout;
+#ifdef MV64340_NAPI
+        dev->poll = mv64340_poll;
+        dev->weight = 64;
+#endif
+
+	dev->watchdog_timeo = 2 * HZ;
+	dev->tx_queue_len = MV64340_TX_QUEUE_SIZE;
+	dev->base_addr = 0;
+	dev->change_mtu = mv64340_eth_change_mtu;
+
+#ifdef MV64340_CHECKSUM_OFFLOAD_TX
+#ifdef MAX_SKB_FRAGS
+#ifndef CONFIG_JAGUAR_DMALOW
+        /*
+         * Zero copy can only work if we use Discovery II memory. Else, we will
+         * have to map the buffers to ISA memory which is only 16 MB
+         */
+        dev->features = NETIF_F_SG | NETIF_F_IP_CSUM | NETIF_F_HW_CSUM;
+#endif
+#endif
+#endif
+
+	mp->port_num = port_num;
+
+	/* Configure the timeout task */
+        INIT_WORK(&mp->tx_timeout_task,
+                  (void (*)(void *))mv64340_eth_tx_timeout_task, dev);
+
+	spin_lock_init(&mp->lock);
+
+	/* set MAC addresses */
+	memcpy(dev->dev_addr, prom_mac_addr_base, 6);
+	dev->dev_addr[5] += port_num;
+
+	err = register_netdev(dev);
+	if (err)
+		goto out_free_dev;
+
+	printk(KERN_NOTICE "%s: port %d with MAC address %02x:%02x:%02x:%02x:%02x:%02x\n",
+		dev->name, port_num,
+		dev->dev_addr[0], dev->dev_addr[1], dev->dev_addr[2],
+		dev->dev_addr[3], dev->dev_addr[4], dev->dev_addr[5]);
+
+	if (dev->features & NETIF_F_SG)
+		printk("Scatter Gather Enabled  ");
+
+	if (dev->features & NETIF_F_IP_CSUM)
+		printk("TX TCP/IP Checksumming Supported  \n");
+
+	printk("RX TCP/UDP Checksum Offload ON, \n");
+	printk("TX and RX Interrupt Coalescing ON \n");
+
+#ifdef MV64340_NAPI
+	printk("RX NAPI Enabled \n");
+#endif
+
+	return dev;
+
+out_free_dev:
+	free_netdev(dev);
+
+	return NULL;
+}
+
+static void mv64340_eth_remove(struct net_device *dev)
+{
+	struct mv64340_private *mp = netdev_priv(dev);
+
+	unregister_netdev(dev);
+	flush_scheduled_work();
+	free_netdev(dev);
+}
+
+static struct net_device *mv64340_dev0;
+static struct net_device *mv64340_dev1;
+static struct net_device *mv64340_dev2;
+
+/*
+ * mv64340_init_module
+ *
+ * Registers the network drivers into the Linux kernel
+ *
+ * Input : N/A
+ *
+ * Output : N/A
+ */
+static int __init mv64340_init_module(void)
+{
+	printk(KERN_NOTICE "MV-643xx 10/100/1000 Ethernet Driver\n");
+
+#ifdef CONFIG_MV643XX_ETH_0
+	mv64340_dev0 = mv64340_eth_init(0);
+	if (!mv64340_dev0) {
+		printk(KERN_ERR
+		       "Error registering MV-64360 ethernet port 0\n");
+	}
+#endif
+#ifdef CONFIG_MV643XX_ETH_1
+	mv64340_dev1 = mv64340_eth_init(1);
+	if (!mv64340_dev1) {
+		printk(KERN_ERR
+		       "Error registering MV-64360 ethernet port 1\n");
+	}
+#endif
+#ifdef CONFIG_MV643XX_ETH_2
+	mv64340_dev2 = mv64340_eth_init(2);
+	if (!mv64340_dev2) {
+		printk(KERN_ERR
+		       "Error registering MV-64360 ethernet port 2\n");
+	}
+#endif
+	return 0;
+}
+
+/*
+ * mv64340_cleanup_module
+ *
+ * Registers the network drivers into the Linux kernel
+ *
+ * Input : N/A
+ *
+ * Output : N/A
+ */
+static void __exit mv64340_cleanup_module(void)
+{
+	if (mv64340_dev2)
+		mv64340_eth_remove(mv64340_dev2);
+	if (mv64340_dev1)
+		mv64340_eth_remove(mv64340_dev1);
+	if (mv64340_dev0)
+		mv64340_eth_remove(mv64340_dev0);
+}
+
+module_init(mv64340_init_module);
+module_exit(mv64340_cleanup_module);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Rabeeh Khoury, Assaf Hoffman, Matthew Dharm and Manish Lachwani");
+MODULE_DESCRIPTION("Ethernet driver for Marvell MV64340");
+
+/*
+ *  The second part is the low level driver of the gigE ethernet ports.
+ */
+
+/*
+ * Marvell's Gigabit Ethernet controller low level driver
+ *
+ * DESCRIPTION:
+ *       This file introduce low level API to Marvell's Gigabit Ethernet
+ *		controller. This Gigabit Ethernet Controller driver API controls
+ *		1) Operations (i.e. port init, start, reset etc').
+ *		2) Data flow (i.e. port send, receive etc').
+ *		Each Gigabit Ethernet port is controlled via
+ *              struct mv64340_private.
+ *		This struct includes user configuration information as well as
+ *		driver internal data needed for its operations.
+ *
+ *		Supported Features:  
+ *		- This low level driver is OS independent. Allocating memory for
+ *		  the descriptor rings and buffers are not within the scope of
+ *		  this driver.
+ *		- The user is free from Rx/Tx queue managing.
+ *		- This low level driver introduce functionality API that enable
+ *		  the to operate Marvell's Gigabit Ethernet Controller in a
+ *		  convenient way.
+ *		- Simple Gigabit Ethernet port operation API.
+ *		- Simple Gigabit Ethernet port data flow API.
+ *		- Data flow and operation API support per queue functionality.
+ *		- Support cached descriptors for better performance.
+ *		- Enable access to all four DRAM banks and internal SRAM memory
+ *		  spaces.
+ *		- PHY access and control API.
+ *		- Port control register configuration API.
+ *		- Full control over Unicast and Multicast MAC configurations.
+ *								   
+ *		Operation flow:
+ *
+ *		Initialization phase
+ *		This phase complete the initialization of the the mv64340_private
+ *		struct. 
+ *		User information regarding port configuration has to be set
+ *		prior to calling the port initialization routine.
+ *
+ *		In this phase any port Tx/Rx activity is halted, MIB counters
+ *		are cleared, PHY address is set according to user parameter and
+ *		access to DRAM and internal SRAM memory spaces.
+ *
+ *		Driver ring initialization
+ *		Allocating memory for the descriptor rings and buffers is not 
+ *		within the scope of this driver. Thus, the user is required to
+ *		allocate memory for the descriptors ring and buffers. Those
+ *		memory parameters are used by the Rx and Tx ring initialization
+ *		routines in order to curve the descriptor linked list in a form
+ *		of a ring.
+ *		Note: Pay special attention to alignment issues when using
+ *		cached descriptors/buffers. In this phase the driver store
+ *		information in the mv64340_private struct regarding each queue
+ *		ring.
+ *
+ *		Driver start 
+ *		This phase prepares the Ethernet port for Rx and Tx activity.
+ *		It uses the information stored in the mv64340_private struct to 
+ *		initialize the various port registers.
+ *
+ *		Data flow:
+ *		All packet references to/from the driver are done using
+ *              struct pkt_info.
+ *		This struct is a unified struct used with Rx and Tx operations. 
+ *		This way the user is not required to be familiar with neither
+ *		Tx nor Rx descriptors structures.
+ *		The driver's descriptors rings are management by indexes.
+ *		Those indexes controls the ring resources and used to indicate
+ *		a SW resource error:
+ *		'current' 
+ *		This index points to the current available resource for use. For 
+ *		example in Rx process this index will point to the descriptor  
+ *		that will be passed to the user upon calling the receive routine.
+ *		In Tx process, this index will point to the descriptor
+ *		that will be assigned with the user packet info and transmitted.
+ *		'used'    
+ *		This index points to the descriptor that need to restore its 
+ *		resources. For example in Rx process, using the Rx buffer return
+ *		API will attach the buffer returned in packet info to the
+ *		descriptor pointed by 'used'. In Tx process, using the Tx
+ *		descriptor return will merely return the user packet info with
+ *		the command status of  the transmitted buffer pointed by the
+ *		'used' index. Nevertheless, it is essential to use this routine
+ *		to update the 'used' index.
+ *		'first'
+ *		This index supports Tx Scatter-Gather. It points to the first 
+ *		descriptor of a packet assembled of multiple buffers. For example
+ *		when in middle of Such packet we have a Tx resource error the 
+ *		'curr' index get the value of 'first' to indicate that the ring 
+ *		returned to its state before trying to transmit this packet.
+ *
+ *		Receive operation:
+ *		The eth_port_receive API set the packet information struct,
+ *		passed by the caller, with received information from the 
+ *		'current' SDMA descriptor. 
+ *		It is the user responsibility to return this resource back
+ *		to the Rx descriptor ring to enable the reuse of this source.
+ *		Return Rx resource is done using the eth_rx_return_buff API.
+ *
+ *		Transmit operation:
+ *		The eth_port_send API supports Scatter-Gather which enables to
+ *		send a packet spanned over multiple buffers. This means that
+ *		for each packet info structure given by the user and put into
+ *		the Tx descriptors ring, will be transmitted only if the 'LAST'
+ *		bit will be set in the packet info command status field. This
+ *		API also consider restriction regarding buffer alignments and
+ *		sizes.
+ *		The user must return a Tx resource after ensuring the buffer
+ *		has been transmitted to enable the Tx ring indexes to update.
+ *
+ *		BOARD LAYOUT
+ *		This device is on-board.  No jumper diagram is necessary.
+ *
+ *		EXTERNAL INTERFACE
+ *
+ *       Prior to calling the initialization routine eth_port_init() the user
+ *	 must set the following fields under mv64340_private struct:
+ *       port_num             User Ethernet port number.
+ *       port_mac_addr[6]	    User defined port MAC address.
+ *       port_config          User port configuration value.
+ *       port_config_extend    User port config extend value.
+ *       port_sdma_config      User port SDMA config value.
+ *       port_serial_control   User port serial control value.
+ *
+ *       This driver introduce a set of default values:
+ *       PORT_CONFIG_VALUE           Default port configuration value
+ *       PORT_CONFIG_EXTEND_VALUE    Default port extend configuration value
+ *       PORT_SDMA_CONFIG_VALUE      Default sdma control value
+ *       PORT_SERIAL_CONTROL_VALUE   Default port serial control value
+ *
+ *		This driver data flow is done using the struct pkt_info which
+ *              is a unified struct for Rx and Tx operations:
+ *
+ *		byte_cnt	Tx/Rx descriptor buffer byte count.
+ *		l4i_chk		CPU provided TCP Checksum. For Tx operation
+ *                              only.
+ *		cmd_sts		Tx/Rx descriptor command status.
+ *		buf_ptr		Tx/Rx descriptor buffer pointer.
+ *		return_info	Tx/Rx user resource return information.
+ */
+
+/* defines */
+/* SDMA command macros */
+#define ETH_ENABLE_TX_QUEUE(eth_port) \
+	MV_WRITE(MV64340_ETH_TRANSMIT_QUEUE_COMMAND_REG(eth_port), 1)
+
+#define ETH_DISABLE_TX_QUEUE(eth_port) \
+	MV_WRITE(MV64340_ETH_TRANSMIT_QUEUE_COMMAND_REG(eth_port),	\
+	         (1 << 8))
+
+#define ETH_ENABLE_RX_QUEUE(rx_queue, eth_port) \
+	MV_WRITE(MV64340_ETH_RECEIVE_QUEUE_COMMAND_REG(eth_port),	\
+	         (1 << rx_queue))
+
+#define ETH_DISABLE_RX_QUEUE(rx_queue, eth_port) \
+	MV_WRITE(MV64340_ETH_RECEIVE_QUEUE_COMMAND_REG(eth_port),	\
+	         (1 << (8 + rx_queue)))
+
+#define LINK_UP_TIMEOUT		100000
+#define PHY_BUSY_TIMEOUT	10000000
+
+/* locals */
+
+/* PHY routines */
+static int ethernet_phy_get(unsigned int eth_port_num);
+
+/* Ethernet Port routines */
+static int eth_port_uc_addr(unsigned int eth_port_num, unsigned char uc_nibble,
+	int option);
+
+/*
+ * eth_port_init - Initialize the Ethernet port driver
+ *
+ * DESCRIPTION:
+ *       This function prepares the ethernet port to start its activity:
+ *       1) Completes the ethernet port driver struct initialization toward port
+ *           start routine.
+ *       2) Resets the device to a quiescent state in case of warm reboot.
+ *       3) Enable SDMA access to all four DRAM banks as well as internal SRAM.
+ *       4) Clean MAC tables. The reset status of those tables is unknown.
+ *       5) Set PHY address. 
+ *       Note: Call this routine prior to eth_port_start routine and after
+ *       setting user values in the user fields of Ethernet port control
+ *       struct.
+ *
+ * INPUT:
+ *       struct mv64340_private *mp   Ethernet port control struct
+ *
+ * OUTPUT:
+ *       See description.
+ *
+ * RETURN:
+ *       None.
+ */
+static void eth_port_init(struct mv64340_private * mp)
+{
+	mp->port_config = PORT_CONFIG_VALUE;
+	mp->port_config_extend = PORT_CONFIG_EXTEND_VALUE;
+#if defined(__BIG_ENDIAN)
+	mp->port_sdma_config = PORT_SDMA_CONFIG_VALUE;
+#elif defined(__LITTLE_ENDIAN)
+	mp->port_sdma_config = PORT_SDMA_CONFIG_VALUE |
+		ETH_BLM_RX_NO_SWAP | ETH_BLM_TX_NO_SWAP;
+#else
+#error One of __LITTLE_ENDIAN or __BIG_ENDIAN must be defined!
+#endif
+	mp->port_serial_control = PORT_SERIAL_CONTROL_VALUE;
+
+	mp->port_rx_queue_command = 0;
+	mp->port_tx_queue_command = 0;
+
+	mp->rx_resource_err = 0;
+	mp->tx_resource_err = 0;
+
+	eth_port_reset(mp->port_num);
+
+	eth_port_init_mac_tables(mp->port_num);
+
+	ethernet_phy_reset(mp->port_num);
+}
+
+/*
+ * eth_port_start - Start the Ethernet port activity.
+ *
+ * DESCRIPTION:
+ *       This routine prepares the Ethernet port for Rx and Tx activity:
+ *       1. Initialize Tx and Rx Current Descriptor Pointer for each queue that
+ *          has been initialized a descriptor's ring (using
+ *          ether_init_tx_desc_ring for Tx and ether_init_rx_desc_ring for Rx)
+ *       2. Initialize and enable the Ethernet configuration port by writing to
+ *          the port's configuration and command registers.
+ *       3. Initialize and enable the SDMA by writing to the SDMA's 
+ *          configuration and command registers.  After completing these steps,
+ *          the ethernet port SDMA can starts to perform Rx and Tx activities.
+ *
+ *       Note: Each Rx and Tx queue descriptor's list must be initialized prior
+ *       to calling this function (use ether_init_tx_desc_ring for Tx queues
+ *       and ether_init_rx_desc_ring for Rx queues).
+ *
+ * INPUT:
+ *       struct mv64340_private 	*mp   Ethernet port control struct
+ *
+ * OUTPUT:
+ *       Ethernet port is ready to receive and transmit.
+ *
+ * RETURN:
+ *       false if the port PHY is not up.
+ *       true otherwise.
+ */
+static int eth_port_start(struct mv64340_private *mp)
+{
+	unsigned int eth_port_num = mp->port_num;
+	int tx_curr_desc, rx_curr_desc;
+	unsigned int phy_reg_data;
+
+	/* Assignment of Tx CTRP of given queue */
+	tx_curr_desc = mp->tx_curr_desc_q;
+	MV_WRITE(MV64340_ETH_TX_CURRENT_QUEUE_DESC_PTR_0(eth_port_num),
+	         (struct eth_tx_desc *) mp->tx_desc_dma + tx_curr_desc);
+
+	/* Assignment of Rx CRDP of given queue */
+	rx_curr_desc = mp->rx_curr_desc_q;
+	MV_WRITE(MV64340_ETH_RX_CURRENT_QUEUE_DESC_PTR_0(eth_port_num),
+		 (struct eth_rx_desc *) mp->rx_desc_dma + rx_curr_desc);
+
+	/* Add the assigned Ethernet address to the port's address table */
+	eth_port_uc_addr_set(mp->port_num, mp->port_mac_addr);
+
+	/* Assign port configuration and command. */
+	MV_WRITE(MV64340_ETH_PORT_CONFIG_REG(eth_port_num),
+		 mp->port_config);
+
+	MV_WRITE(MV64340_ETH_PORT_CONFIG_EXTEND_REG(eth_port_num),
+		 mp->port_config_extend);
+
+	MV_WRITE(MV64340_ETH_PORT_SERIAL_CONTROL_REG(eth_port_num),
+		 mp->port_serial_control);
+
+	MV_SET_REG_BITS(MV64340_ETH_PORT_SERIAL_CONTROL_REG(eth_port_num),
+			ETH_SERIAL_PORT_ENABLE);
+
+	/* Assign port SDMA configuration */
+	MV_WRITE(MV64340_ETH_SDMA_CONFIG_REG(eth_port_num),
+		 mp->port_sdma_config);
+
+	/* Enable port Rx. */
+	MV_WRITE(MV64340_ETH_RECEIVE_QUEUE_COMMAND_REG(eth_port_num),
+		 mp->port_rx_queue_command);
+
+	/* Check if link is up */
+	eth_port_read_smi_reg(eth_port_num, 1, &phy_reg_data);
+
+	if (!(phy_reg_data & 0x20))
+		return 0;
+
+	return 1;
+}
+
+/*
+ * eth_port_uc_addr_set - This function Set the port Unicast address.
+ *
+ * DESCRIPTION:
+ *		This function Set the port Ethernet MAC address.
+ *
+ * INPUT:
+ *	unsigned int eth_port_num     Port number.
+ *	char *        p_addr		Address to be set 
+ *
+ * OUTPUT:
+ *	Set MAC address low and high registers. also calls eth_port_uc_addr() 
+ *       To set the unicast table with the proper information.
+ *
+ * RETURN:
+ *	N/A.
+ *
+ */
+static void eth_port_uc_addr_set(unsigned int eth_port_num,
+				 unsigned char *p_addr)
+{
+	unsigned int mac_h;
+	unsigned int mac_l;
+
+	mac_l = (p_addr[4] << 8) | (p_addr[5]);
+	mac_h = (p_addr[0] << 24) | (p_addr[1] << 16) |
+	    (p_addr[2] << 8) | (p_addr[3] << 0);
+
+	MV_WRITE(MV64340_ETH_MAC_ADDR_LOW(eth_port_num), mac_l);
+	MV_WRITE(MV64340_ETH_MAC_ADDR_HIGH(eth_port_num), mac_h);
+
+	/* Accept frames of this address */
+	eth_port_uc_addr(eth_port_num, p_addr[5], ACCEPT_MAC_ADDR);
+
+	return;
+}
+
+/*
+ * eth_port_uc_addr - This function Set the port unicast address table
+ *
+ * DESCRIPTION:
+ *	This function locates the proper entry in the Unicast table for the 
+ *	specified MAC nibble and sets its properties according to function 
+ *	parameters.
+ *
+ * INPUT:
+ *	unsigned int 	eth_port_num      Port number.
+ *	unsigned char uc_nibble		Unicast MAC Address last nibble. 
+ *	int 			option      0 = Add, 1 = remove address.
+ *
+ * OUTPUT:
+ *	This function add/removes MAC addresses from the port unicast address
+ *	table. 
+ *
+ * RETURN:
+ *	true is output succeeded.
+ *	false if option parameter is invalid.
+ *
+ */
+static int eth_port_uc_addr(unsigned int eth_port_num,
+	unsigned char uc_nibble, int option)
+{
+	unsigned int unicast_reg;
+	unsigned int tbl_offset;
+	unsigned int reg_offset;
+
+	/* Locate the Unicast table entry */
+	uc_nibble = (0xf & uc_nibble);
+	tbl_offset = (uc_nibble / 4) * 4;	/* Register offset from unicast table base */
+	reg_offset = uc_nibble % 4;	/* Entry offset within the above register */
+
+	switch (option) {
+	case REJECT_MAC_ADDR:
+		/* Clear accepts frame bit at specified unicast DA table entry */
+		unicast_reg = MV_READ((MV64340_ETH_DA_FILTER_UNICAST_TABLE_BASE
+				  (eth_port_num) + tbl_offset));
+
+		unicast_reg &= (0x0E << (8 * reg_offset));
+
+		MV_WRITE(
+			 (MV64340_ETH_DA_FILTER_UNICAST_TABLE_BASE
+			  (eth_port_num) + tbl_offset), unicast_reg);
+		break;
+
+	case ACCEPT_MAC_ADDR:
+		/* Set accepts frame bit at unicast DA filter table entry */
+		unicast_reg =
+		    MV_READ(
+				 (MV64340_ETH_DA_FILTER_UNICAST_TABLE_BASE
+				  (eth_port_num) + tbl_offset));
+
+		unicast_reg |= (0x01 << (8 * reg_offset));
+
+		MV_WRITE(
+			 (MV64340_ETH_DA_FILTER_UNICAST_TABLE_BASE
+			  (eth_port_num) + tbl_offset), unicast_reg);
+
+		break;
+
+	default:
+		return 0;
+	}
+
+	return 1;
+}
+
+/*
+ * eth_port_init_mac_tables - Clear all entrance in the UC, SMC and OMC tables
+ *
+ * DESCRIPTION:
+ *       Go through all the DA filter tables (Unicast, Special Multicast &
+ *       Other Multicast) and set each entry to 0.
+ *
+ * INPUT:
+ *	unsigned int    eth_port_num   Ethernet Port number.
+ *
+ * OUTPUT:
+ *       Multicast and Unicast packets are rejected.
+ *
+ * RETURN:
+ *       None.
+ */
+static void eth_port_init_mac_tables(unsigned int eth_port_num)
+{
+	int table_index;
+
+	/* Clear DA filter unicast table (Ex_dFUT) */
+	for (table_index = 0; table_index <= 0xC; table_index += 4)
+		MV_WRITE(
+			 (MV64340_ETH_DA_FILTER_UNICAST_TABLE_BASE
+			  (eth_port_num) + table_index), 0);
+
+	for (table_index = 0; table_index <= 0xFC; table_index += 4) {
+		/* Clear DA filter special multicast table (Ex_dFSMT) */
+		MV_WRITE(
+			 (MV64340_ETH_DA_FILTER_SPECIAL_MULTICAST_TABLE_BASE
+			  (eth_port_num) + table_index), 0);
+		/* Clear DA filter other multicast table (Ex_dFOMT) */
+		MV_WRITE((MV64340_ETH_DA_FILTER_OTHER_MULTICAST_TABLE_BASE
+			  (eth_port_num) + table_index), 0);
+	}
+}
+
+/*
+ * eth_clear_mib_counters - Clear all MIB counters
+ *
+ * DESCRIPTION:
+ *       This function clears all MIB counters of a specific ethernet port.
+ *       A read from the MIB counter will reset the counter.
+ *
+ * INPUT:
+ *	unsigned int    eth_port_num   Ethernet Port number.
+ *
+ * OUTPUT:
+ *       After reading all MIB counters, the counters resets.
+ *
+ * RETURN:
+ *       MIB counter value.
+ *
+ */
+static void eth_clear_mib_counters(unsigned int eth_port_num)
+{
+	int i;
+
+	/* Perform dummy reads from MIB counters */
+	for (i = ETH_MIB_GOOD_OCTETS_RECEIVED_LOW; i < ETH_MIB_LATE_COLLISION; i += 4)
+		MV_READ(MV64340_ETH_MIB_COUNTERS_BASE(eth_port_num) + i);
+}
+
+
+/*
+ * ethernet_phy_get - Get the ethernet port PHY address.
+ *
+ * DESCRIPTION:
+ *       This routine returns the given ethernet port PHY address.
+ *
+ * INPUT:
+ *		unsigned int   eth_port_num   Ethernet Port number.
+ *
+ * OUTPUT:
+ *       None.
+ *
+ * RETURN:
+ *       PHY address.
+ *
+ */
+static int ethernet_phy_get(unsigned int eth_port_num)
+{
+	unsigned int reg_data;
+
+	reg_data = MV_READ(MV64340_ETH_PHY_ADDR_REG);
+
+	return ((reg_data >> (5 * eth_port_num)) & 0x1f);
+}
+
+/*
+ * ethernet_phy_reset - Reset Ethernet port PHY.
+ *
+ * DESCRIPTION:
+ *       This routine utilize the SMI interface to reset the ethernet port PHY.
+ *       The routine waits until the link is up again or link up is timeout.
+ *
+ * INPUT:
+ *	unsigned int   eth_port_num   Ethernet Port number.
+ *
+ * OUTPUT:
+ *       The ethernet port PHY renew its link.
+ *
+ * RETURN:
+ *       None.
+ *
+ */
+static int ethernet_phy_reset(unsigned int eth_port_num)
+{
+	unsigned int time_out = 50;
+	unsigned int phy_reg_data;
+
+	/* Reset the PHY */
+	eth_port_read_smi_reg(eth_port_num, 0, &phy_reg_data);
+	phy_reg_data |= 0x8000;	/* Set bit 15 to reset the PHY */
+	eth_port_write_smi_reg(eth_port_num, 0, phy_reg_data);
+
+	/* Poll on the PHY LINK */
+	do {
+		eth_port_read_smi_reg(eth_port_num, 1, &phy_reg_data);
+
+		if (time_out-- == 0)
+			return 0;
+	} while (!(phy_reg_data & 0x20));
+
+	return 1;
+}
+
+/*
+ * eth_port_reset - Reset Ethernet port
+ *
+ * DESCRIPTION:
+ * 	This routine resets the chip by aborting any SDMA engine activity and
+ *      clearing the MIB counters. The Receiver and the Transmit unit are in 
+ *      idle state after this command is performed and the port is disabled.
+ *
+ * INPUT:
+ *	unsigned int   eth_port_num   Ethernet Port number.
+ *
+ * OUTPUT:
+ *       Channel activity is halted.
+ *
+ * RETURN:
+ *       None.
+ *
+ */
+static void eth_port_reset(unsigned int eth_port_num)
+{
+	unsigned int reg_data;
+
+	/* Stop Tx port activity. Check port Tx activity. */
+	reg_data =
+	    MV_READ(MV64340_ETH_TRANSMIT_QUEUE_COMMAND_REG(eth_port_num));
+
+	if (reg_data & 0xFF) {
+		/* Issue stop command for active channels only */
+		MV_WRITE(MV64340_ETH_TRANSMIT_QUEUE_COMMAND_REG
+			 (eth_port_num), (reg_data << 8));
+
+		/* Wait for all Tx activity to terminate. */
+		do {
+			/* Check port cause register that all Tx queues are stopped */
+			reg_data =
+			    MV_READ
+			    (MV64340_ETH_TRANSMIT_QUEUE_COMMAND_REG
+			     (eth_port_num));
+		}
+		while (reg_data & 0xFF);
+	}
+
+	/* Stop Rx port activity. Check port Rx activity. */
+	reg_data =
+	    MV_READ(MV64340_ETH_RECEIVE_QUEUE_COMMAND_REG
+			 (eth_port_num));
+
+	if (reg_data & 0xFF) {
+		/* Issue stop command for active channels only */
+		MV_WRITE(MV64340_ETH_RECEIVE_QUEUE_COMMAND_REG
+			 (eth_port_num), (reg_data << 8));
+
+		/* Wait for all Rx activity to terminate. */
+		do {
+			/* Check port cause register that all Rx queues are stopped */
+			reg_data =
+			    MV_READ
+			    (MV64340_ETH_RECEIVE_QUEUE_COMMAND_REG
+			     (eth_port_num));
+		}
+		while (reg_data & 0xFF);
+	}
+
+
+	/* Clear all MIB counters */
+	eth_clear_mib_counters(eth_port_num);
+
+	/* Reset the Enable bit in the Configuration Register */
+	reg_data =
+	    MV_READ(MV64340_ETH_PORT_SERIAL_CONTROL_REG (eth_port_num));
+	reg_data &= ~ETH_SERIAL_PORT_ENABLE;
+	MV_WRITE(MV64340_ETH_PORT_SERIAL_CONTROL_REG(eth_port_num), reg_data);
+
+	return;
+}
+
+/*
+ * ethernet_set_config_reg - Set specified bits in configuration register.
+ *
+ * DESCRIPTION:
+ *       This function sets specified bits in the given ethernet 
+ *       configuration register. 
+ *
+ * INPUT:
+ *	unsigned int   eth_port_num   Ethernet Port number.
+ *      unsigned int    value   32 bit value.
+ *
+ * OUTPUT:
+ *      The set bits in the value parameter are set in the configuration 
+ *      register.
+ *
+ * RETURN:
+ *      None.
+ *
+ */
+static void ethernet_set_config_reg(unsigned int eth_port_num,
+				    unsigned int value)
+{
+	unsigned int eth_config_reg;
+
+	eth_config_reg =
+	    MV_READ(MV64340_ETH_PORT_CONFIG_REG(eth_port_num));
+	eth_config_reg |= value;
+	MV_WRITE(MV64340_ETH_PORT_CONFIG_REG(eth_port_num),
+		 eth_config_reg);
+}
+
+/*
+ * ethernet_get_config_reg - Get the port configuration register
+ *
+ * DESCRIPTION:
+ *       This function returns the configuration register value of the given 
+ *       ethernet port.
+ *
+ * INPUT:
+ *	unsigned int   eth_port_num   Ethernet Port number.
+ *
+ * OUTPUT:
+ *       None.
+ *
+ * RETURN:
+ *       Port configuration register value.
+ */
+static unsigned int ethernet_get_config_reg(unsigned int eth_port_num)
+{
+	unsigned int eth_config_reg;
+
+	eth_config_reg = MV_READ(MV64340_ETH_PORT_CONFIG_EXTEND_REG
+				      (eth_port_num));
+	return eth_config_reg;
+}
+
+
+/*
+ * eth_port_read_smi_reg - Read PHY registers
+ *
+ * DESCRIPTION:
+ *       This routine utilize the SMI interface to interact with the PHY in 
+ *       order to perform PHY register read.
+ *
+ * INPUT:
+ *	unsigned int   eth_port_num   Ethernet Port number.
+ *       unsigned int   phy_reg   PHY register address offset.
+ *       unsigned int   *value   Register value buffer.
+ *
+ * OUTPUT:
+ *       Write the value of a specified PHY register into given buffer.
+ *
+ * RETURN:
+ *       false if the PHY is busy or read data is not in valid state.
+ *       true otherwise.
+ *
+ */
+static int eth_port_read_smi_reg(unsigned int eth_port_num,
+	unsigned int phy_reg, unsigned int *value)
+{
+	int phy_addr = ethernet_phy_get(eth_port_num);
+	unsigned int time_out = PHY_BUSY_TIMEOUT;
+	unsigned int reg_value;
+
+	/* first check that it is not busy */
+	do {
+		reg_value = MV_READ(MV64340_ETH_SMI_REG);
+		if (time_out-- == 0)
+			return 0;
+	} while (reg_value & ETH_SMI_BUSY);
+
+	/* not busy */
+
+	MV_WRITE(MV64340_ETH_SMI_REG,
+		 (phy_addr << 16) | (phy_reg << 21) | ETH_SMI_OPCODE_READ);
+
+	time_out = PHY_BUSY_TIMEOUT;	/* initialize the time out var again */
+
+	do {
+		reg_value = MV_READ(MV64340_ETH_SMI_REG);
+		if (time_out-- == 0)
+			return 0;
+	} while (reg_value & ETH_SMI_READ_VALID);
+
+	/* Wait for the data to update in the SMI register */
+	for (time_out = 0; time_out < PHY_BUSY_TIMEOUT; time_out++);
+
+	reg_value = MV_READ(MV64340_ETH_SMI_REG);
+
+	*value = reg_value & 0xffff;
+
+	return 1;
+}
+
+/*
+ * eth_port_write_smi_reg - Write to PHY registers
+ *
+ * DESCRIPTION:
+ *       This routine utilize the SMI interface to interact with the PHY in 
+ *       order to perform writes to PHY registers.
+ *
+ * INPUT:
+ *	unsigned int   eth_port_num   Ethernet Port number.
+ *      unsigned int   phy_reg   PHY register address offset.
+ *      unsigned int    value   Register value.
+ *
+ * OUTPUT:
+ *      Write the given value to the specified PHY register.
+ *
+ * RETURN:
+ *      false if the PHY is busy.
+ *      true otherwise.
+ *
+ */
+static int eth_port_write_smi_reg(unsigned int eth_port_num,
+	unsigned int phy_reg, unsigned int value)
+{
+	unsigned int time_out = PHY_BUSY_TIMEOUT;
+	unsigned int reg_value;
+	int phy_addr;
+
+	phy_addr = ethernet_phy_get(eth_port_num);
+
+	/* first check that it is not busy */
+	do {
+		reg_value = MV_READ(MV64340_ETH_SMI_REG);
+		if (time_out-- == 0)
+			return 0;
+	} while (reg_value & ETH_SMI_BUSY);
+
+	/* not busy */
+	MV_WRITE(MV64340_ETH_SMI_REG, (phy_addr << 16) | (phy_reg << 21) |
+		 ETH_SMI_OPCODE_WRITE | (value & 0xffff));
+
+	return 1;
+}
+
+/*
+ * eth_port_send - Send an Ethernet packet
+ *
+ * DESCRIPTION:
+ *	This routine send a given packet described by p_pktinfo parameter. It 
+ *      supports transmitting of a packet spaned over multiple buffers. The 
+ *      routine updates 'curr' and 'first' indexes according to the packet 
+ *      segment passed to the routine. In case the packet segment is first, 
+ *      the 'first' index is update. In any case, the 'curr' index is updated. 
+ *      If the routine get into Tx resource error it assigns 'curr' index as 
+ *      'first'. This way the function can abort Tx process of multiple 
+ *      descriptors per packet.
+ *
+ * INPUT:
+ *	struct mv64340_private   *mp   Ethernet Port Control srtuct. 
+ *	struct pkt_info        *p_pkt_info       User packet buffer.
+ *
+ * OUTPUT:
+ *	Tx ring 'curr' and 'first' indexes are updated. 
+ *
+ * RETURN:
+ *      ETH_QUEUE_FULL in case of Tx resource error.
+ *	ETH_ERROR in case the routine can not access Tx desc ring.
+ *	ETH_QUEUE_LAST_RESOURCE if the routine uses the last Tx resource.
+ *      ETH_OK otherwise.
+ *
+ */
+#ifdef  MV64340_CHECKSUM_OFFLOAD_TX
+/*
+ * Modified to include the first descriptor pointer in case of SG
+ */
+static ETH_FUNC_RET_STATUS eth_port_send(struct mv64340_private * mp,
+                                         struct pkt_info * p_pkt_info)
+{
+	int tx_desc_curr, tx_desc_used, tx_first_desc, tx_next_desc;
+	volatile struct eth_tx_desc *current_descriptor;
+	volatile struct eth_tx_desc *first_descriptor;
+	u32 command_status, first_chip_ptr;
+
+	/* Do not process Tx ring in case of Tx ring resource error */
+	if (mp->tx_resource_err)
+		return ETH_QUEUE_FULL;
+
+	/* Get the Tx Desc ring indexes */
+	tx_desc_curr = mp->tx_curr_desc_q;
+	tx_desc_used = mp->tx_used_desc_q;
+
+	current_descriptor = &mp->p_tx_desc_area[tx_desc_curr];
+	if (current_descriptor == NULL)
+		return ETH_ERROR;
+
+	tx_next_desc = (tx_desc_curr + 1) % MV64340_TX_QUEUE_SIZE;
+	command_status = p_pkt_info->cmd_sts | ETH_ZERO_PADDING | ETH_GEN_CRC;
+
+	if (command_status & ETH_TX_FIRST_DESC) {
+		tx_first_desc = tx_desc_curr;
+		mp->tx_first_desc_q = tx_first_desc;
+
+                /* fill first descriptor */
+                first_descriptor = &mp->p_tx_desc_area[tx_desc_curr];
+                first_descriptor->l4i_chk = p_pkt_info->l4i_chk;
+                first_descriptor->cmd_sts = command_status;
+                first_descriptor->byte_cnt = p_pkt_info->byte_cnt;
+                first_descriptor->buf_ptr = p_pkt_info->buf_ptr;
+                first_descriptor->next_desc_ptr = mp->tx_desc_dma +
+			tx_next_desc * sizeof(struct eth_tx_desc);
+		wmb();
+        } else {
+                tx_first_desc = mp->tx_first_desc_q;
+                first_descriptor = &mp->p_tx_desc_area[tx_first_desc];
+                if (first_descriptor == NULL) {
+                        printk("First desc is NULL !!\n");
+                        return ETH_ERROR;
+                }
+                if (command_status & ETH_TX_LAST_DESC)
+                        current_descriptor->next_desc_ptr = 0x00000000;
+                else {
+                        command_status |= ETH_BUFFER_OWNED_BY_DMA;
+                        current_descriptor->next_desc_ptr = mp->tx_desc_dma +
+				tx_next_desc * sizeof(struct eth_tx_desc);
+                }
+        }
+
+        if (p_pkt_info->byte_cnt < 8) {
+                printk(" < 8 problem \n");
+                return ETH_ERROR;
+        }
+
+        current_descriptor->buf_ptr = p_pkt_info->buf_ptr;
+        current_descriptor->byte_cnt = p_pkt_info->byte_cnt;
+        current_descriptor->l4i_chk = p_pkt_info->l4i_chk;
+        current_descriptor->cmd_sts = command_status;
+
+        mp->tx_skb[tx_desc_curr] = (struct sk_buff*) p_pkt_info->return_info;
+
+        wmb();
+
+        /* Set last desc with DMA ownership and interrupt enable. */
+        if (command_status & ETH_TX_LAST_DESC) {
+                current_descriptor->cmd_sts = command_status |
+                                        ETH_TX_ENABLE_INTERRUPT |
+                                        ETH_BUFFER_OWNED_BY_DMA;
+
+		if (!(command_status & ETH_TX_FIRST_DESC))
+			first_descriptor->cmd_sts |= ETH_BUFFER_OWNED_BY_DMA;
+		wmb();
+
+		first_chip_ptr = MV_READ(MV64340_ETH_CURRENT_SERVED_TX_DESC_PTR(mp->port_num));
+
+		/* Apply send command */
+		if (first_chip_ptr == 0x00000000)
+			MV_WRITE(MV64340_ETH_TX_CURRENT_QUEUE_DESC_PTR_0(mp->port_num), (struct eth_tx_desc *) mp->tx_desc_dma + tx_first_desc);
+
+                ETH_ENABLE_TX_QUEUE(mp->port_num);
+
+		/*
+		 * Finish Tx packet. Update first desc in case of Tx resource
+		 * error */
+                tx_first_desc = tx_next_desc;
+                mp->tx_first_desc_q = tx_first_desc;
+	} else {
+		if (! (command_status & ETH_TX_FIRST_DESC) ) {
+			current_descriptor->cmd_sts = command_status;
+			wmb();
+		}
+	}
+
+        /* Check for ring index overlap in the Tx desc ring */
+        if (tx_next_desc == tx_desc_used) {
+                mp->tx_resource_err = 1;
+                mp->tx_curr_desc_q = tx_first_desc;
+
+                return ETH_QUEUE_LAST_RESOURCE;
+	}
+
+        mp->tx_curr_desc_q = tx_next_desc;
+        wmb();
+
+        return ETH_OK;
+}
+#else
+static ETH_FUNC_RET_STATUS eth_port_send(struct mv64340_private * mp,
+					 struct pkt_info * p_pkt_info)
+{
+	int tx_desc_curr;
+	int tx_desc_used;
+	volatile struct eth_tx_desc* current_descriptor;
+	unsigned int command_status;
+
+	/* Do not process Tx ring in case of Tx ring resource error */
+	if (mp->tx_resource_err)
+		return ETH_QUEUE_FULL;
+
+	/* Get the Tx Desc ring indexes */
+	tx_desc_curr = mp->tx_curr_desc_q;
+	tx_desc_used = mp->tx_used_desc_q;
+	current_descriptor = &mp->p_tx_desc_area[tx_desc_curr];
+
+	if (current_descriptor == NULL)
+		return ETH_ERROR;
+
+	command_status = p_pkt_info->cmd_sts | ETH_ZERO_PADDING | ETH_GEN_CRC;
+
+/* XXX Is this for real ?!?!? */
+	/* Buffers with a payload smaller than 8 bytes must be aligned to a
+	 * 64-bit boundary. We use the memory allocated for Tx descriptor.
+	 * This memory is located in TX_BUF_OFFSET_IN_DESC offset within the
+	 * Tx descriptor. */
+	if (p_pkt_info->byte_cnt <= 8) {
+		printk(KERN_ERR
+		       "You have failed in the < 8 bytes errata - fixme\n");
+		return ETH_ERROR;
+	}
+	current_descriptor->buf_ptr = p_pkt_info->buf_ptr;
+	current_descriptor->byte_cnt = p_pkt_info->byte_cnt;
+	mp->tx_skb[tx_desc_curr] = (struct sk_buff *) p_pkt_info->return_info;
+
+	mb();
+
+	/* Set last desc with DMA ownership and interrupt enable. */
+	current_descriptor->cmd_sts = command_status |
+			ETH_BUFFER_OWNED_BY_DMA | ETH_TX_ENABLE_INTERRUPT;
+
+	/* Apply send command */
+	ETH_ENABLE_TX_QUEUE(mp->port_num);
+
+	/* Finish Tx packet. Update first desc in case of Tx resource error */
+	tx_desc_curr = (tx_desc_curr + 1) % MV64340_TX_QUEUE_SIZE;
+
+	/* Update the current descriptor */
+ 	mp->tx_curr_desc_q = tx_desc_curr;
+
+	/* Check for ring index overlap in the Tx desc ring */
+	if (tx_desc_curr == tx_desc_used) {
+		mp->tx_resource_err = 1;
+		return ETH_QUEUE_LAST_RESOURCE;
+	}
+
+	return ETH_OK;
+}
+#endif
+
+/*
+ * eth_tx_return_desc - Free all used Tx descriptors
+ *
+ * DESCRIPTION:
+ *	This routine returns the transmitted packet information to the caller.
+ *      It uses the 'first' index to support Tx desc return in case a transmit 
+ *      of a packet spanned over multiple buffer still in process.
+ *      In case the Tx queue was in "resource error" condition, where there are 
+ *      no available Tx resources, the function resets the resource error flag.
+ *
+ * INPUT:
+ *	struct mv64340_private   *mp   Ethernet Port Control srtuct. 
+ *	struct pkt_info        *p_pkt_info       User packet buffer.
+ *
+ * OUTPUT:
+ *	Tx ring 'first' and 'used' indexes are updated. 
+ *
+ * RETURN:
+ *	ETH_ERROR in case the routine can not access Tx desc ring.
+ *      ETH_RETRY in case there is transmission in process.
+ *	ETH_END_OF_JOB if the routine has nothing to release.
+ *      ETH_OK otherwise.
+ *
+ */
+static ETH_FUNC_RET_STATUS eth_tx_return_desc(struct mv64340_private * mp,
+					      struct pkt_info * p_pkt_info)
+{
+	int tx_desc_used, tx_desc_curr;
+#ifdef MV64340_CHECKSUM_OFFLOAD_TX
+        int tx_first_desc;
+#endif
+	volatile struct eth_tx_desc *p_tx_desc_used;
+	unsigned int command_status;
+
+	/* Get the Tx Desc ring indexes */
+	tx_desc_curr = mp->tx_curr_desc_q;
+	tx_desc_used = mp->tx_used_desc_q;
+#ifdef MV64340_CHECKSUM_OFFLOAD_TX
+        tx_first_desc = mp->tx_first_desc_q;
+#endif
+	p_tx_desc_used = &mp->p_tx_desc_area[tx_desc_used];
+
+	/* XXX Sanity check */
+	if (p_tx_desc_used == NULL)
+		return ETH_ERROR;
+
+	command_status = p_tx_desc_used->cmd_sts;
+
+	/* Still transmitting... */
+#ifndef MV64340_CHECKSUM_OFFLOAD_TX
+	if (command_status & (ETH_BUFFER_OWNED_BY_DMA))
+		return ETH_RETRY;
+#endif
+	/* Stop release. About to overlap the current available Tx descriptor */
+#ifdef MV64340_CHECKSUM_OFFLOAD_TX
+	if (tx_desc_used == tx_first_desc && !mp->tx_resource_err)
+		return ETH_END_OF_JOB;
+#else
+	if (tx_desc_used == tx_desc_curr && !mp->tx_resource_err)
+		return ETH_END_OF_JOB;
+#endif
+
+	/* Pass the packet information to the caller */
+	p_pkt_info->cmd_sts = command_status;
+	p_pkt_info->return_info = mp->tx_skb[tx_desc_used];
+	mp->tx_skb[tx_desc_used] = NULL;
+
+	/* Update the next descriptor to release. */
+	mp->tx_used_desc_q = (tx_desc_used + 1) % MV64340_TX_QUEUE_SIZE;
+
+	/* Any Tx return cancels the Tx resource error status */
+	mp->tx_resource_err = 0;
+
+	return ETH_OK;
+}
+
+/*
+ * eth_port_receive - Get received information from Rx ring.
+ *
+ * DESCRIPTION:
+ * 	This routine returns the received data to the caller. There is no 
+ *	data copying during routine operation. All information is returned 
+ *	using pointer to packet information struct passed from the caller. 
+ *      If the routine exhausts	Rx ring resources then the resource error flag 
+ *      is set.  
+ *
+ * INPUT:
+ *	struct mv64340_private   *mp   Ethernet Port Control srtuct. 
+ *	struct pkt_info        *p_pkt_info       User packet buffer.
+ *
+ * OUTPUT:
+ *	Rx ring current and used indexes are updated. 
+ *
+ * RETURN:
+ *	ETH_ERROR in case the routine can not access Rx desc ring.
+ *	ETH_QUEUE_FULL if Rx ring resources are exhausted.
+ *	ETH_END_OF_JOB if there is no received data.
+ *      ETH_OK otherwise.
+ */
+static ETH_FUNC_RET_STATUS eth_port_receive(struct mv64340_private * mp,
+					    struct pkt_info * p_pkt_info)
+{
+	int rx_next_curr_desc, rx_curr_desc, rx_used_desc;
+	volatile struct eth_rx_desc * p_rx_desc;
+	unsigned int command_status;
+
+	/* Do not process Rx ring in case of Rx ring resource error */
+	if (mp->rx_resource_err)
+		return ETH_QUEUE_FULL;
+
+	/* Get the Rx Desc ring 'curr and 'used' indexes */
+	rx_curr_desc = mp->rx_curr_desc_q;
+	rx_used_desc = mp->rx_used_desc_q;
+
+	p_rx_desc = &mp->p_rx_desc_area[rx_curr_desc];
+
+	/* The following parameters are used to save readings from memory */
+	command_status = p_rx_desc->cmd_sts;
+
+	/* Nothing to receive... */
+	if (command_status & (ETH_BUFFER_OWNED_BY_DMA))
+		return ETH_END_OF_JOB;
+
+	p_pkt_info->byte_cnt = (p_rx_desc->byte_cnt) - RX_BUF_OFFSET;
+	p_pkt_info->cmd_sts = command_status;
+	p_pkt_info->buf_ptr = (p_rx_desc->buf_ptr) + RX_BUF_OFFSET;
+	p_pkt_info->return_info = mp->rx_skb[rx_curr_desc];
+	p_pkt_info->l4i_chk = p_rx_desc->buf_size;
+
+	/* Clean the return info field to indicate that the packet has been */
+	/* moved to the upper layers                                        */
+	mp->rx_skb[rx_curr_desc] = NULL;
+
+	/* Update current index in data structure */
+	rx_next_curr_desc = (rx_curr_desc + 1) % MV64340_RX_QUEUE_SIZE;
+	mp->rx_curr_desc_q = rx_next_curr_desc;
+
+	/* Rx descriptors exhausted. Set the Rx ring resource error flag */
+	if (rx_next_curr_desc == rx_used_desc)
+		mp->rx_resource_err = 1;
+
+	mb();
+	return ETH_OK;
+}
+
+/*
+ * eth_rx_return_buff - Returns a Rx buffer back to the Rx ring.
+ *
+ * DESCRIPTION:
+ *	This routine returns a Rx buffer back to the Rx ring. It retrieves the 
+ *      next 'used' descriptor and attached the returned buffer to it.
+ *      In case the Rx ring was in "resource error" condition, where there are 
+ *      no available Rx resources, the function resets the resource error flag.
+ *
+ * INPUT:
+ *	struct mv64340_private *mp   Ethernet Port Control srtuct. 
+ *      struct pkt_info        *p_pkt_info   Information on the returned buffer.
+ *
+ * OUTPUT:
+ *	New available Rx resource in Rx descriptor ring.
+ *
+ * RETURN:
+ *	ETH_ERROR in case the routine can not access Rx desc ring.
+ *      ETH_OK otherwise.
+ */
+static ETH_FUNC_RET_STATUS eth_rx_return_buff(struct mv64340_private * mp,
+	struct pkt_info * p_pkt_info)
+{
+	int used_rx_desc;	/* Where to return Rx resource */
+	volatile struct eth_rx_desc* p_used_rx_desc;
+
+	/* Get 'used' Rx descriptor */
+	used_rx_desc = mp->rx_used_desc_q;
+	p_used_rx_desc = &mp->p_rx_desc_area[used_rx_desc];
+
+	p_used_rx_desc->buf_ptr = p_pkt_info->buf_ptr;
+	p_used_rx_desc->buf_size = p_pkt_info->byte_cnt;
+	mp->rx_skb[used_rx_desc] = p_pkt_info->return_info;
+
+	/* Flush the write pipe */
+	mb();
+
+	/* Return the descriptor to DMA ownership */
+	p_used_rx_desc->cmd_sts =
+		ETH_BUFFER_OWNED_BY_DMA | ETH_RX_ENABLE_INTERRUPT;
+
+	/* Flush descriptor and CPU pipe */
+	mb();
+
+	/* Move the used descriptor pointer to the next descriptor */
+	mp->rx_used_desc_q = (used_rx_desc + 1) % MV64340_RX_QUEUE_SIZE;
+
+	/* Any Rx return cancels the Rx resource error status */
+	mp->rx_resource_err = 0;
+
+	return ETH_OK;
+}
diff -Nru a/drivers/net/mv643xx_eth.h b/drivers/net/mv643xx_eth.h
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/drivers/net/mv643xx_eth.h	2004-10-18 14:57:23 -07:00
@@ -0,0 +1,601 @@
+#ifndef __MV64340_ETH_H__
+#define __MV64340_ETH_H__
+
+#include <linux/version.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/spinlock.h>
+#include <linux/workqueue.h>
+
+#include <linux/mv643xx.h>
+
+#define	BIT0	0x00000001
+#define	BIT1	0x00000002
+#define	BIT2	0x00000004
+#define	BIT3	0x00000008
+#define	BIT4	0x00000010
+#define	BIT5	0x00000020
+#define	BIT6	0x00000040
+#define	BIT7	0x00000080
+#define	BIT8	0x00000100
+#define	BIT9	0x00000200
+#define	BIT10	0x00000400
+#define	BIT11	0x00000800
+#define	BIT12	0x00001000
+#define	BIT13	0x00002000
+#define	BIT14	0x00004000
+#define	BIT15	0x00008000
+#define	BIT16	0x00010000
+#define	BIT17	0x00020000
+#define	BIT18	0x00040000
+#define	BIT19	0x00080000
+#define	BIT20	0x00100000
+#define	BIT21	0x00200000
+#define	BIT22	0x00400000
+#define	BIT23	0x00800000
+#define	BIT24	0x01000000
+#define	BIT25	0x02000000
+#define	BIT26	0x04000000
+#define	BIT27	0x08000000
+#define	BIT28	0x10000000
+#define	BIT29	0x20000000
+#define	BIT30	0x40000000
+#define	BIT31	0x80000000
+
+/*
+ *  The first part is the high level driver of the gigE ethernet ports.
+ */
+
+#define ETH_PORT0_IRQ_NUM 48			/* main high register, bit0 */
+#define ETH_PORT1_IRQ_NUM ETH_PORT0_IRQ_NUM+1	/* main high register, bit1 */
+#define ETH_PORT2_IRQ_NUM ETH_PORT0_IRQ_NUM+2	/* main high register, bit1 */
+
+/* Checksum offload for Tx works */
+#define  MV64340_CHECKSUM_OFFLOAD_TX
+#define	 MV64340_NAPI
+#define	 MV64340_TX_FAST_REFILL
+#undef	 MV64340_COAL
+
+/* 
+ * Number of RX / TX descriptors on RX / TX rings.
+ * Note that allocating RX descriptors is done by allocating the RX
+ * ring AND a preallocated RX buffers (skb's) for each descriptor.
+ * The TX descriptors only allocates the TX descriptors ring,
+ * with no pre allocated TX buffers (skb's are allocated by higher layers.
+ */
+
+/* Default TX ring size is 1000 descriptors */
+#define MV64340_TX_QUEUE_SIZE 1000
+
+/* Default RX ring size is 400 descriptors */
+#define MV64340_RX_QUEUE_SIZE 400
+
+#define MV64340_TX_COAL 100
+#ifdef MV64340_COAL
+#define MV64340_RX_COAL 100
+#endif
+
+
+/*
+ * The second part is the low level driver of the gigE ethernet ports.   *
+ */
+
+
+/*
+ * Header File for : MV-643xx network interface header 
+ *
+ * DESCRIPTION:
+ *       This header file contains macros typedefs and function declaration for
+ *       the Marvell Gig Bit Ethernet Controller. 
+ *
+ * DEPENDENCIES:
+ *       None.
+ *
+ */
+
+/* Default port configuration value */
+#define PORT_CONFIG_VALUE                       \
+             ETH_UNICAST_NORMAL_MODE		|   \
+             ETH_DEFAULT_RX_QUEUE_0		|   \
+             ETH_DEFAULT_RX_ARP_QUEUE_0		|   \
+             ETH_RECEIVE_BC_IF_NOT_IP_OR_ARP	|   \
+             ETH_RECEIVE_BC_IF_IP		|   \
+             ETH_RECEIVE_BC_IF_ARP 		|   \
+             ETH_CAPTURE_TCP_FRAMES_DIS		|   \
+             ETH_CAPTURE_UDP_FRAMES_DIS		|   \
+             ETH_DEFAULT_RX_TCP_QUEUE_0		|   \
+             ETH_DEFAULT_RX_UDP_QUEUE_0		|   \
+             ETH_DEFAULT_RX_BPDU_QUEUE_0
+
+/* Default port extend configuration value */
+#define PORT_CONFIG_EXTEND_VALUE		\
+             ETH_SPAN_BPDU_PACKETS_AS_NORMAL	|   \
+             ETH_PARTITION_DISABLE
+
+
+/* Default sdma control value */
+#define PORT_SDMA_CONFIG_VALUE			\
+			 ETH_RX_BURST_SIZE_16_64BIT 	|	\
+			 GT_ETH_IPG_INT_RX(0) 		|	\
+			 ETH_TX_BURST_SIZE_16_64BIT;
+
+#define GT_ETH_IPG_INT_RX(value)                \
+            ((value & 0x3fff) << 8)
+
+/* Default port serial control value */
+#define PORT_SERIAL_CONTROL_VALUE		\
+			ETH_FORCE_LINK_PASS 			|	\
+			ETH_ENABLE_AUTO_NEG_FOR_DUPLX		|	\
+			ETH_DISABLE_AUTO_NEG_FOR_FLOW_CTRL 	|	\
+			ETH_ADV_SYMMETRIC_FLOW_CTRL 		|	\
+			ETH_FORCE_FC_MODE_NO_PAUSE_DIS_TX 	|	\
+			ETH_FORCE_BP_MODE_NO_JAM 		|	\
+			BIT9 					|	\
+			ETH_DO_NOT_FORCE_LINK_FAIL 		|	\
+			ETH_RETRANSMIT_16_ATTEMPTS 		|	\
+			ETH_ENABLE_AUTO_NEG_SPEED_GMII	 	|	\
+			ETH_DTE_ADV_0 				|	\
+			ETH_DISABLE_AUTO_NEG_BYPASS		|	\
+			ETH_AUTO_NEG_NO_CHANGE 			|	\
+			ETH_MAX_RX_PACKET_9700BYTE 		|	\
+			ETH_CLR_EXT_LOOPBACK 			|	\
+			ETH_SET_FULL_DUPLEX_MODE 		|	\
+			ETH_ENABLE_FLOW_CTRL_TX_RX_IN_FULL_DUPLEX
+
+#define RX_BUFFER_MAX_SIZE  0x4000000
+#define TX_BUFFER_MAX_SIZE  0x4000000
+
+/* MAC accepet/reject macros */
+#define ACCEPT_MAC_ADDR	    0
+#define REJECT_MAC_ADDR	    1
+
+/* Buffer offset from buffer pointer */
+#define RX_BUF_OFFSET				0x2
+
+/* Gigabit Ethernet Unit Global Registers */
+
+/* MIB Counters register definitions */
+#define ETH_MIB_GOOD_OCTETS_RECEIVED_LOW   0x0
+#define ETH_MIB_GOOD_OCTETS_RECEIVED_HIGH  0x4
+#define ETH_MIB_BAD_OCTETS_RECEIVED        0x8
+#define ETH_MIB_INTERNAL_MAC_TRANSMIT_ERR  0xc
+#define ETH_MIB_GOOD_FRAMES_RECEIVED       0x10
+#define ETH_MIB_BAD_FRAMES_RECEIVED        0x14
+#define ETH_MIB_BROADCAST_FRAMES_RECEIVED  0x18
+#define ETH_MIB_MULTICAST_FRAMES_RECEIVED  0x1c
+#define ETH_MIB_FRAMES_64_OCTETS           0x20
+#define ETH_MIB_FRAMES_65_TO_127_OCTETS    0x24
+#define ETH_MIB_FRAMES_128_TO_255_OCTETS   0x28
+#define ETH_MIB_FRAMES_256_TO_511_OCTETS   0x2c
+#define ETH_MIB_FRAMES_512_TO_1023_OCTETS  0x30
+#define ETH_MIB_FRAMES_1024_TO_MAX_OCTETS  0x34
+#define ETH_MIB_GOOD_OCTETS_SENT_LOW       0x38
+#define ETH_MIB_GOOD_OCTETS_SENT_HIGH      0x3c
+#define ETH_MIB_GOOD_FRAMES_SENT           0x40
+#define ETH_MIB_EXCESSIVE_COLLISION        0x44
+#define ETH_MIB_MULTICAST_FRAMES_SENT      0x48
+#define ETH_MIB_BROADCAST_FRAMES_SENT      0x4c
+#define ETH_MIB_UNREC_MAC_CONTROL_RECEIVED 0x50
+#define ETH_MIB_FC_SENT                    0x54
+#define ETH_MIB_GOOD_FC_RECEIVED           0x58
+#define ETH_MIB_BAD_FC_RECEIVED            0x5c
+#define ETH_MIB_UNDERSIZE_RECEIVED         0x60
+#define ETH_MIB_FRAGMENTS_RECEIVED         0x64
+#define ETH_MIB_OVERSIZE_RECEIVED          0x68
+#define ETH_MIB_JABBER_RECEIVED            0x6c
+#define ETH_MIB_MAC_RECEIVE_ERROR          0x70
+#define ETH_MIB_BAD_CRC_EVENT              0x74
+#define ETH_MIB_COLLISION                  0x78
+#define ETH_MIB_LATE_COLLISION             0x7c
+
+/* Port serial status reg (PSR) */
+#define ETH_INTERFACE_GMII_MII                          0
+#define ETH_INTERFACE_PCM                               BIT0
+#define ETH_LINK_IS_DOWN                                0
+#define ETH_LINK_IS_UP                                  BIT1
+#define ETH_PORT_AT_HALF_DUPLEX                         0
+#define ETH_PORT_AT_FULL_DUPLEX                         BIT2
+#define ETH_RX_FLOW_CTRL_DISABLED                       0
+#define ETH_RX_FLOW_CTRL_ENBALED                        BIT3
+#define ETH_GMII_SPEED_100_10                           0
+#define ETH_GMII_SPEED_1000                             BIT4
+#define ETH_MII_SPEED_10                                0
+#define ETH_MII_SPEED_100                               BIT5
+#define ETH_NO_TX                                       0
+#define ETH_TX_IN_PROGRESS                              BIT7
+#define ETH_BYPASS_NO_ACTIVE                            0
+#define ETH_BYPASS_ACTIVE                               BIT8
+#define ETH_PORT_NOT_AT_PARTITION_STATE                 0
+#define ETH_PORT_AT_PARTITION_STATE                     BIT9
+#define ETH_PORT_TX_FIFO_NOT_EMPTY                      0
+#define ETH_PORT_TX_FIFO_EMPTY                          BIT10
+
+
+/* These macros describes the Port configuration reg (Px_cR) bits */
+#define ETH_UNICAST_NORMAL_MODE                         0
+#define ETH_UNICAST_PROMISCUOUS_MODE                    BIT0
+#define ETH_DEFAULT_RX_QUEUE_0                          0
+#define ETH_DEFAULT_RX_QUEUE_1                          BIT1
+#define ETH_DEFAULT_RX_QUEUE_2                          BIT2
+#define ETH_DEFAULT_RX_QUEUE_3                          (BIT2 | BIT1)
+#define ETH_DEFAULT_RX_QUEUE_4                          BIT3
+#define ETH_DEFAULT_RX_QUEUE_5                          (BIT3 | BIT1)
+#define ETH_DEFAULT_RX_QUEUE_6                          (BIT3 | BIT2)
+#define ETH_DEFAULT_RX_QUEUE_7                          (BIT3 | BIT2 | BIT1)
+#define ETH_DEFAULT_RX_ARP_QUEUE_0                      0
+#define ETH_DEFAULT_RX_ARP_QUEUE_1                      BIT4
+#define ETH_DEFAULT_RX_ARP_QUEUE_2                      BIT5
+#define ETH_DEFAULT_RX_ARP_QUEUE_3                      (BIT5 | BIT4)
+#define ETH_DEFAULT_RX_ARP_QUEUE_4                      BIT6
+#define ETH_DEFAULT_RX_ARP_QUEUE_5                      (BIT6 | BIT4)
+#define ETH_DEFAULT_RX_ARP_QUEUE_6                      (BIT6 | BIT5)
+#define ETH_DEFAULT_RX_ARP_QUEUE_7                      (BIT6 | BIT5 | BIT4)
+#define ETH_RECEIVE_BC_IF_NOT_IP_OR_ARP                 0
+#define ETH_REJECT_BC_IF_NOT_IP_OR_ARP                  BIT7
+#define ETH_RECEIVE_BC_IF_IP                            0
+#define ETH_REJECT_BC_IF_IP                             BIT8
+#define ETH_RECEIVE_BC_IF_ARP                           0
+#define ETH_REJECT_BC_IF_ARP                            BIT9
+#define ETH_TX_AM_NO_UPDATE_ERROR_SUMMARY               BIT12
+#define ETH_CAPTURE_TCP_FRAMES_DIS                      0
+#define ETH_CAPTURE_TCP_FRAMES_EN                       BIT14
+#define ETH_CAPTURE_UDP_FRAMES_DIS                      0
+#define ETH_CAPTURE_UDP_FRAMES_EN                       BIT15
+#define ETH_DEFAULT_RX_TCP_QUEUE_0                      0
+#define ETH_DEFAULT_RX_TCP_QUEUE_1                      BIT16
+#define ETH_DEFAULT_RX_TCP_QUEUE_2                      BIT17
+#define ETH_DEFAULT_RX_TCP_QUEUE_3                      (BIT17 | BIT16)
+#define ETH_DEFAULT_RX_TCP_QUEUE_4                      BIT18
+#define ETH_DEFAULT_RX_TCP_QUEUE_5                      (BIT18 | BIT16)
+#define ETH_DEFAULT_RX_TCP_QUEUE_6                      (BIT18 | BIT17)
+#define ETH_DEFAULT_RX_TCP_QUEUE_7                      (BIT18 | BIT17 | BIT16)
+#define ETH_DEFAULT_RX_UDP_QUEUE_0                      0
+#define ETH_DEFAULT_RX_UDP_QUEUE_1                      BIT19
+#define ETH_DEFAULT_RX_UDP_QUEUE_2                      BIT20
+#define ETH_DEFAULT_RX_UDP_QUEUE_3                      (BIT20 | BIT19)
+#define ETH_DEFAULT_RX_UDP_QUEUE_4                      (BIT21
+#define ETH_DEFAULT_RX_UDP_QUEUE_5                      (BIT21 | BIT19)
+#define ETH_DEFAULT_RX_UDP_QUEUE_6                      (BIT21 | BIT20)
+#define ETH_DEFAULT_RX_UDP_QUEUE_7                      (BIT21 | BIT20 | BIT19)
+#define ETH_DEFAULT_RX_BPDU_QUEUE_0                      0
+#define ETH_DEFAULT_RX_BPDU_QUEUE_1                     BIT22
+#define ETH_DEFAULT_RX_BPDU_QUEUE_2                     BIT23
+#define ETH_DEFAULT_RX_BPDU_QUEUE_3                     (BIT23 | BIT22)
+#define ETH_DEFAULT_RX_BPDU_QUEUE_4                     BIT24
+#define ETH_DEFAULT_RX_BPDU_QUEUE_5                     (BIT24 | BIT22)
+#define ETH_DEFAULT_RX_BPDU_QUEUE_6                     (BIT24 | BIT23)
+#define ETH_DEFAULT_RX_BPDU_QUEUE_7                     (BIT24 | BIT23 | BIT22)
+
+
+/* These macros describes the Port configuration extend reg (Px_cXR) bits*/
+#define ETH_CLASSIFY_EN                                 BIT0
+#define ETH_SPAN_BPDU_PACKETS_AS_NORMAL                 0
+#define ETH_SPAN_BPDU_PACKETS_TO_RX_QUEUE_7             BIT1
+#define ETH_PARTITION_DISABLE                           0
+#define ETH_PARTITION_ENABLE                            BIT2
+
+
+/* Tx/Rx queue command reg (RQCR/TQCR)*/
+#define ETH_QUEUE_0_ENABLE                              BIT0
+#define ETH_QUEUE_1_ENABLE                              BIT1
+#define ETH_QUEUE_2_ENABLE                              BIT2
+#define ETH_QUEUE_3_ENABLE                              BIT3
+#define ETH_QUEUE_4_ENABLE                              BIT4
+#define ETH_QUEUE_5_ENABLE                              BIT5
+#define ETH_QUEUE_6_ENABLE                              BIT6
+#define ETH_QUEUE_7_ENABLE                              BIT7
+#define ETH_QUEUE_0_DISABLE                             BIT8
+#define ETH_QUEUE_1_DISABLE                             BIT9
+#define ETH_QUEUE_2_DISABLE                             BIT10
+#define ETH_QUEUE_3_DISABLE                             BIT11
+#define ETH_QUEUE_4_DISABLE                             BIT12
+#define ETH_QUEUE_5_DISABLE                             BIT13
+#define ETH_QUEUE_6_DISABLE                             BIT14
+#define ETH_QUEUE_7_DISABLE                             BIT15
+
+
+/* These macros describes the Port Sdma configuration reg (SDCR) bits */
+#define ETH_RIFB                                        BIT0
+#define ETH_RX_BURST_SIZE_1_64BIT                       0
+#define ETH_RX_BURST_SIZE_2_64BIT                       BIT1
+#define ETH_RX_BURST_SIZE_4_64BIT                       BIT2
+#define ETH_RX_BURST_SIZE_8_64BIT                       (BIT2 | BIT1)
+#define ETH_RX_BURST_SIZE_16_64BIT                      BIT3
+#define ETH_BLM_RX_NO_SWAP                              BIT4
+#define ETH_BLM_RX_BYTE_SWAP                            0
+#define ETH_BLM_TX_NO_SWAP                              BIT5
+#define ETH_BLM_TX_BYTE_SWAP                            0
+#define ETH_DESCRIPTORS_BYTE_SWAP                       BIT6
+#define ETH_DESCRIPTORS_NO_SWAP                         0
+#define ETH_TX_BURST_SIZE_1_64BIT                       0
+#define ETH_TX_BURST_SIZE_2_64BIT                       BIT22
+#define ETH_TX_BURST_SIZE_4_64BIT                       BIT23
+#define ETH_TX_BURST_SIZE_8_64BIT                       (BIT23 | BIT22)
+#define ETH_TX_BURST_SIZE_16_64BIT                      BIT24
+
+
+
+/* These macros describes the Port serial control reg (PSCR) bits */
+#define ETH_SERIAL_PORT_DISABLE                         0
+#define ETH_SERIAL_PORT_ENABLE                          BIT0
+#define ETH_FORCE_LINK_PASS                             BIT1
+#define ETH_DO_NOT_FORCE_LINK_PASS                      0
+#define ETH_ENABLE_AUTO_NEG_FOR_DUPLX                   0
+#define ETH_DISABLE_AUTO_NEG_FOR_DUPLX                  BIT2
+#define ETH_ENABLE_AUTO_NEG_FOR_FLOW_CTRL               0
+#define ETH_DISABLE_AUTO_NEG_FOR_FLOW_CTRL              BIT3
+#define ETH_ADV_NO_FLOW_CTRL                            0
+#define ETH_ADV_SYMMETRIC_FLOW_CTRL                     BIT4
+#define ETH_FORCE_FC_MODE_NO_PAUSE_DIS_TX               0
+#define ETH_FORCE_FC_MODE_TX_PAUSE_DIS                  BIT5
+#define ETH_FORCE_BP_MODE_NO_JAM                        0
+#define ETH_FORCE_BP_MODE_JAM_TX                        BIT7
+#define ETH_FORCE_BP_MODE_JAM_TX_ON_RX_ERR              BIT8
+#define ETH_FORCE_LINK_FAIL                             0
+#define ETH_DO_NOT_FORCE_LINK_FAIL                      BIT10
+#define ETH_RETRANSMIT_16_ATTEMPTS                      0
+#define ETH_RETRANSMIT_FOREVER                          BIT11
+#define ETH_DISABLE_AUTO_NEG_SPEED_GMII                 BIT13
+#define ETH_ENABLE_AUTO_NEG_SPEED_GMII                  0
+#define ETH_DTE_ADV_0                                   0
+#define ETH_DTE_ADV_1                                   BIT14
+#define ETH_DISABLE_AUTO_NEG_BYPASS                     0
+#define ETH_ENABLE_AUTO_NEG_BYPASS                      BIT15
+#define ETH_AUTO_NEG_NO_CHANGE                          0
+#define ETH_RESTART_AUTO_NEG                            BIT16
+#define ETH_MAX_RX_PACKET_1518BYTE                      0
+#define ETH_MAX_RX_PACKET_1522BYTE                      BIT17
+#define ETH_MAX_RX_PACKET_1552BYTE                      BIT18
+#define ETH_MAX_RX_PACKET_9022BYTE                      (BIT18 | BIT17)
+#define ETH_MAX_RX_PACKET_9192BYTE                      BIT19
+#define ETH_MAX_RX_PACKET_9700BYTE                      (BIT19 | BIT17)
+#define ETH_SET_EXT_LOOPBACK                            BIT20
+#define ETH_CLR_EXT_LOOPBACK                            0
+#define ETH_SET_FULL_DUPLEX_MODE                        BIT21
+#define ETH_SET_HALF_DUPLEX_MODE                        0
+#define ETH_ENABLE_FLOW_CTRL_TX_RX_IN_FULL_DUPLEX       BIT22
+#define ETH_DISABLE_FLOW_CTRL_TX_RX_IN_FULL_DUPLEX      0
+#define ETH_SET_GMII_SPEED_TO_10_100                    0
+#define ETH_SET_GMII_SPEED_TO_1000                      BIT23
+#define ETH_SET_MII_SPEED_TO_10                         0
+#define ETH_SET_MII_SPEED_TO_100                        BIT24
+
+
+/* SMI reg */
+#define ETH_SMI_BUSY        	BIT28	/* 0 - Write, 1 - Read          */
+#define ETH_SMI_READ_VALID  	BIT27	/* 0 - Write, 1 - Read          */
+#define ETH_SMI_OPCODE_WRITE	0	/* Completion of Read operation */
+#define ETH_SMI_OPCODE_READ 	BIT26	/* Operation is in progress             */
+
+/* SDMA command status fields macros */
+
+/* Tx & Rx descriptors status */
+#define ETH_ERROR_SUMMARY                   (BIT0)
+
+/* Tx & Rx descriptors command */
+#define ETH_BUFFER_OWNED_BY_DMA             (BIT31)
+
+/* Tx descriptors status */
+#define ETH_LC_ERROR                        (0	  )
+#define ETH_UR_ERROR                        (BIT1 )
+#define ETH_RL_ERROR                        (BIT2 )
+#define ETH_LLC_SNAP_FORMAT                 (BIT9 )
+
+/* Rx descriptors status */
+#define ETH_CRC_ERROR                       (0	  )
+#define ETH_OVERRUN_ERROR                   (BIT1 )
+#define ETH_MAX_FRAME_LENGTH_ERROR          (BIT2 )
+#define ETH_RESOURCE_ERROR                  ((BIT2 | BIT1))
+#define ETH_VLAN_TAGGED                     (BIT19)
+#define ETH_BPDU_FRAME                      (BIT20)
+#define ETH_TCP_FRAME_OVER_IP_V_4           (0    )
+#define ETH_UDP_FRAME_OVER_IP_V_4           (BIT21)
+#define ETH_OTHER_FRAME_TYPE                (BIT22)
+#define ETH_LAYER_2_IS_ETH_V_2              (BIT23)
+#define ETH_FRAME_TYPE_IP_V_4               (BIT24)
+#define ETH_FRAME_HEADER_OK                 (BIT25)
+#define ETH_RX_LAST_DESC                    (BIT26)
+#define ETH_RX_FIRST_DESC                   (BIT27)
+#define ETH_UNKNOWN_DESTINATION_ADDR        (BIT28)
+#define ETH_RX_ENABLE_INTERRUPT             (BIT29)
+#define ETH_LAYER_4_CHECKSUM_OK             (BIT30)
+
+/* Rx descriptors byte count */
+#define ETH_FRAME_FRAGMENTED                (BIT2)
+
+/* Tx descriptors command */
+#define ETH_LAYER_4_CHECKSUM_FIRST_DESC		(BIT10)
+#define ETH_FRAME_SET_TO_VLAN               (BIT15)
+#define ETH_TCP_FRAME                       (0	  )
+#define ETH_UDP_FRAME                       (BIT16)
+#define ETH_GEN_TCP_UDP_CHECKSUM            (BIT17)
+#define ETH_GEN_IP_V_4_CHECKSUM             (BIT18)
+#define ETH_ZERO_PADDING                    (BIT19)
+#define ETH_TX_LAST_DESC                    (BIT20)
+#define ETH_TX_FIRST_DESC                   (BIT21)
+#define ETH_GEN_CRC                         (BIT22)
+#define ETH_TX_ENABLE_INTERRUPT             (BIT23)
+#define ETH_AUTO_MODE                       (BIT30)
+
+/* typedefs */
+
+typedef enum _eth_func_ret_status {
+	ETH_OK,			/* Returned as expected.                    */
+	ETH_ERROR,		/* Fundamental error.                       */
+	ETH_RETRY,		/* Could not process request. Try later.    */
+	ETH_END_OF_JOB,		/* Ring has nothing to process.             */
+	ETH_QUEUE_FULL,		/* Ring resource error.                     */
+	ETH_QUEUE_LAST_RESOURCE	/* Ring resources about to exhaust.         */
+} ETH_FUNC_RET_STATUS;
+
+typedef enum _eth_target {
+	ETH_TARGET_DRAM,
+	ETH_TARGET_DEVICE,
+	ETH_TARGET_CBS,
+	ETH_TARGET_PCI0,
+	ETH_TARGET_PCI1
+} ETH_TARGET;
+
+/* These are for big-endian machines.  Little endian needs different
+ * definitions.
+ */
+#if defined(__BIG_ENDIAN)
+struct eth_rx_desc {
+	u16	byte_cnt;	/* Descriptor buffer byte count     */
+	u16	buf_size;	/* Buffer size                      */
+	u32	cmd_sts;	/* Descriptor command status        */
+	u32	next_desc_ptr;	/* Next descriptor pointer          */
+	u32	buf_ptr;	/* Descriptor buffer pointer        */
+};
+
+struct eth_tx_desc {
+	u16	byte_cnt;	/* buffer byte count */
+	u16	l4i_chk;	/* CPU provided TCP checksum */
+	u32	cmd_sts;	/* Command/status field */
+	u32	next_desc_ptr;	/* Pointer to next descriptor */
+	u32	buf_ptr;	/* pointer to buffer for this descriptor */
+};
+
+#elif defined(__LITTLE_ENDIAN)
+struct eth_rx_desc {
+	u32	cmd_sts;	/* Descriptor command status        */
+	u16	buf_size;	/* Buffer size                      */
+	u16	byte_cnt;	/* Descriptor buffer byte count     */
+	u32	buf_ptr;	/* Descriptor buffer pointer        */
+	u32	next_desc_ptr;	/* Next descriptor pointer          */
+};
+
+struct eth_tx_desc {
+	u32	cmd_sts;	/* Command/status field */
+	u16	l4i_chk;	/* CPU provided TCP checksum */
+	u16	byte_cnt;	/* buffer byte count */
+	u32	buf_ptr;	/* pointer to buffer for this descriptor */
+	u32	next_desc_ptr;	/* Pointer to next descriptor */
+};
+#else
+#error One of __BIG_ENDIAN or __LITTLE_ENDIAN must be defined
+#endif
+
+/* Unified struct for Rx and Tx operations. The user is not required to */
+/* be familier with neither Tx nor Rx descriptors.                       */
+struct pkt_info {
+	unsigned short	byte_cnt;	/* Descriptor buffer byte count     */
+	unsigned short	l4i_chk;	/* Tx CPU provided TCP Checksum     */
+	unsigned int	cmd_sts;	/* Descriptor command status        */
+	dma_addr_t	buf_ptr;	/* Descriptor buffer pointer        */
+	struct sk_buff	* return_info;	/* User resource return information */
+};
+
+
+/* Ethernet port specific infomation */
+
+struct mv64340_private {
+	int	port_num;		/* User Ethernet port number */
+	u8	port_mac_addr[6];	/* User defined port MAC address. */
+	u32	port_config;		/* User port configuration value */
+	u32	port_config_extend;	/* User port config extend value */
+	u32	port_sdma_config;	/* User port SDMA config value */
+	u32	port_serial_control;	/* User port serial control value */
+	u32	port_tx_queue_command;	/* Port active Tx queues summary */
+	u32	port_rx_queue_command;	/* Port active Rx queues summary */
+
+	int	rx_resource_err;	/* Rx ring resource error flag */
+	int	tx_resource_err;	/* Tx ring resource error flag */
+
+	/* Tx/Rx rings managment indexes fields. For driver use */
+
+	/* Next available and first returning Rx resource */
+	int rx_curr_desc_q, rx_used_desc_q;
+
+	/* Next available and first returning Tx resource */
+	int tx_curr_desc_q, tx_used_desc_q;
+#ifdef MV64340_CHECKSUM_OFFLOAD_TX
+        int tx_first_desc_q;
+#endif
+
+#ifdef MV64340_TX_FAST_REFILL
+	u32	tx_clean_threshold;
+#endif
+
+	volatile struct eth_rx_desc	* p_rx_desc_area;
+	dma_addr_t			rx_desc_dma;
+	unsigned int			rx_desc_area_size;
+	struct sk_buff			* rx_skb[MV64340_RX_QUEUE_SIZE];
+
+	volatile struct eth_tx_desc	* p_tx_desc_area;
+	dma_addr_t			tx_desc_dma;
+	unsigned int			tx_desc_area_size;
+	struct sk_buff			* tx_skb[MV64340_TX_QUEUE_SIZE];
+
+	struct work_struct		tx_timeout_task;
+
+	/*
+	 * Former struct mv64340_eth_priv members start here
+	 */
+	struct net_device_stats stats;
+	spinlock_t lock;
+	/* Size of Tx Ring per queue */
+	unsigned int tx_ring_size;
+	/* Ammont of SKBs outstanding on Tx queue */
+	unsigned int tx_ring_skbs;
+	/* Size of Rx Ring per queue */
+	unsigned int rx_ring_size;
+	/* Ammount of SKBs allocated to Rx Ring per queue */
+	unsigned int rx_ring_skbs;
+
+	/*
+	 * rx_task used to fill RX ring out of bottom half context 
+	 */
+	struct work_struct rx_task;
+
+	/* 
+	 * Used in case RX Ring is empty, which can be caused when 
+	 * system does not have resources (skb's) 
+	 */
+	struct timer_list timeout;
+	long rx_task_busy __attribute__ ((aligned(SMP_CACHE_BYTES)));
+	unsigned rx_timer_flag;
+
+	u32 rx_int_coal;
+	u32 tx_int_coal;
+};
+
+/* ethernet.h API list */
+
+/* Port operation control routines */
+static void eth_port_init(struct mv64340_private *mp);
+static void eth_port_reset(unsigned int eth_port_num);
+static int eth_port_start(struct mv64340_private *mp);
+
+static void ethernet_set_config_reg(unsigned int eth_port_num,
+				    unsigned int value);
+static unsigned int ethernet_get_config_reg(unsigned int eth_port_num);
+
+/* Port MAC address routines */
+static void eth_port_uc_addr_set(unsigned int eth_port_num,
+				 unsigned char *p_addr);
+
+/* PHY and MIB routines */
+static int ethernet_phy_reset(unsigned int eth_port_num);
+
+static int eth_port_write_smi_reg(unsigned int eth_port_num,
+				   unsigned int phy_reg,
+				   unsigned int value);
+
+static int eth_port_read_smi_reg(unsigned int eth_port_num,
+				  unsigned int phy_reg,
+				  unsigned int *value);
+
+static void eth_clear_mib_counters(unsigned int eth_port_num);
+
+/* Port data flow control routines */
+static ETH_FUNC_RET_STATUS eth_port_send(struct mv64340_private *mp,
+					 struct pkt_info * p_pkt_info);
+static ETH_FUNC_RET_STATUS eth_tx_return_desc(struct mv64340_private *mp,
+					      struct pkt_info * p_pkt_info);
+static ETH_FUNC_RET_STATUS eth_port_receive(struct mv64340_private *mp,
+					    struct pkt_info * p_pkt_info);
+static ETH_FUNC_RET_STATUS eth_rx_return_buff(struct mv64340_private *mp,
+					      struct pkt_info * p_pkt_info);
+
+#endif  /* __MV64340_ETH_H__ */
diff -Nru a/drivers/net/myri_sbus.c b/drivers/net/myri_sbus.c
--- a/drivers/net/myri_sbus.c	2004-10-18 14:55:54 -07:00
+++ b/drivers/net/myri_sbus.c	2004-10-18 14:55:54 -07:00
@@ -85,7 +85,7 @@
 static struct myri_eth *root_myri_dev;
 #endif
 
-static void myri_reset_off(unsigned long lp, unsigned long cregs)
+static void myri_reset_off(void __iomem *lp, void __iomem *cregs)
 {
 	/* Clear IRQ mask. */
 	sbus_writel(0, lp + LANAI_EIMASK);
@@ -94,7 +94,7 @@
 	sbus_writel(CONTROL_ROFF, cregs + MYRICTRL_CTRL);
 }
 
-static void myri_reset_on(unsigned long cregs)
+static void myri_reset_on(void __iomem *cregs)
 {
 	/* Enable RESET function. */
 	sbus_writel(CONTROL_RON, cregs + MYRICTRL_CTRL);
@@ -103,14 +103,14 @@
 	sbus_writel(CONTROL_DIRQ, cregs + MYRICTRL_CTRL);
 }
 
-static void myri_disable_irq(unsigned long lp, unsigned long cregs)
+static void myri_disable_irq(void __iomem *lp, void __iomem *cregs)
 {
 	sbus_writel(CONTROL_DIRQ, cregs + MYRICTRL_CTRL);
 	sbus_writel(0, lp + LANAI_EIMASK);
 	sbus_writel(ISTAT_HOST, lp + LANAI_ISTAT);
 }
 
-static void myri_enable_irq(unsigned long lp, unsigned long cregs)
+static void myri_enable_irq(void __iomem *lp, void __iomem *cregs)
 {
 	sbus_writel(CONTROL_EIRQ, cregs + MYRICTRL_CTRL);
 	sbus_writel(ISTAT_HOST, lp + LANAI_EIMASK);
@@ -119,7 +119,7 @@
 static inline void bang_the_chip(struct myri_eth *mp)
 {
 	struct myri_shmem *shmem	= mp->shmem;
-	unsigned long cregs		= mp->cregs;
+	void __iomem *cregs		= mp->cregs;
 
 	sbus_writel(1, &shmem->send);
 	sbus_writel(CONTROL_WON, cregs + MYRICTRL_CTRL);
@@ -128,7 +128,7 @@
 static int myri_do_handshake(struct myri_eth *mp)
 {
 	struct myri_shmem *shmem	= mp->shmem;
-	unsigned long cregs = mp->cregs;
+	void __iomem *cregs = mp->cregs;
 	struct myri_channel *chan	= &shmem->channel;
 	int tick 			= 0;
 
@@ -176,27 +176,27 @@
 static int myri_load_lanai(struct myri_eth *mp)
 {
 	struct net_device	*dev = mp->dev;
-	struct myri_shmem	*shmem = mp->shmem;
-	unsigned char		*rptr;
+	struct myri_shmem __iomem *shmem = mp->shmem;
+	void __iomem		*rptr;
 	int 			i;
 
 	myri_disable_irq(mp->lregs, mp->cregs);
 	myri_reset_on(mp->cregs);
 
-	rptr = (unsigned char *) mp->lanai;
+	rptr = mp->lanai;
 	for (i = 0; i < mp->eeprom.ramsz; i++)
-		sbus_writeb(0, &rptr[i]);
+		sbus_writeb(0, rptr + i);
 
 	if (mp->eeprom.cpuvers >= CPUVERS_3_0)
 		sbus_writel(mp->eeprom.cval, mp->lregs + LANAI_CVAL);
 
 	/* Load executable code. */
 	for (i = 0; i < sizeof(lanai4_code); i++)
-		sbus_writeb(lanai4_code[i], &rptr[(lanai4_code_off * 2) + i]);
+		sbus_writeb(lanai4_code[i], rptr + (lanai4_code_off * 2) + i);
 
 	/* Load data segment. */
 	for (i = 0; i < sizeof(lanai4_data); i++)
-		sbus_writeb(lanai4_data[i], &rptr[(lanai4_data_off * 2) + i]);
+		sbus_writeb(lanai4_data[i], rptr + (lanai4_data_off * 2) + i);
 
 	/* Set device address. */
 	sbus_writeb(0, &shmem->addr[0]);
@@ -237,15 +237,15 @@
 
 static void myri_clean_rings(struct myri_eth *mp)
 {
-	struct sendq *sq = mp->sq;
-	struct recvq *rq = mp->rq;
+	struct sendq __iomem *sq = mp->sq;
+	struct recvq __iomem *rq = mp->rq;
 	int i;
 
 	sbus_writel(0, &rq->tail);
 	sbus_writel(0, &rq->head);
 	for (i = 0; i < (RX_RING_SIZE+1); i++) {
 		if (mp->rx_skbs[i] != NULL) {
-			struct myri_rxd *rxd = &rq->myri_rxd[i];
+			struct myri_rxd __iomem *rxd = &rq->myri_rxd[i];
 			u32 dma_addr;
 
 			dma_addr = sbus_readl(&rxd->myri_scatters[0].addr);
@@ -261,7 +261,7 @@
 	for (i = 0; i < TX_RING_SIZE; i++) {
 		if (mp->tx_skbs[i] != NULL) {
 			struct sk_buff *skb = mp->tx_skbs[i];
-			struct myri_txd *txd = &sq->myri_txd[i];
+			struct myri_txd __iomem *txd = &sq->myri_txd[i];
 			u32 dma_addr;
 
 			dma_addr = sbus_readl(&txd->myri_gathers[0].addr);
@@ -274,8 +274,8 @@
 
 static void myri_init_rings(struct myri_eth *mp, int from_irq)
 {
-	struct recvq *rq = mp->rq;
-	struct myri_rxd *rxd = &rq->myri_rxd[0];
+	struct recvq __iomem *rq = mp->rq;
+	struct myri_rxd __iomem *rxd = &rq->myri_rxd[0];
 	struct net_device *dev = mp->dev;
 	int gfp_flags = GFP_KERNEL;
 	int i;
@@ -343,7 +343,7 @@
 
 static void myri_tx(struct myri_eth *mp, struct net_device *dev)
 {
-	struct sendq *sq	= mp->sq;
+	struct sendq __iomem *sq= mp->sq;
 	int entry		= mp->tx_old;
 	int limit		= sbus_readl(&sq->head);
 
@@ -376,7 +376,7 @@
 	
 	skb->mac.raw = (((unsigned char *)skb->data) + MYRI_PAD_LEN);
 	skb_pull(skb, dev->hard_header_len);
-	eth = skb->mac.ethernet;
+	eth = eth_hdr(skb);
 	
 #ifdef DEBUG_HEADER
 	DHDR(("myri_type_trans: "));
@@ -411,8 +411,8 @@
 
 static void myri_rx(struct myri_eth *mp, struct net_device *dev)
 {
-	struct recvq *rq	= mp->rq;
-	struct recvq *rqa	= mp->rqack;
+	struct recvq __iomem *rq = mp->rq;
+	struct recvq __iomem *rqa = mp->rqack;
 	int entry		= sbus_readl(&rqa->head);
 	int limit		= sbus_readl(&rqa->tail);
 	int drops;
@@ -423,11 +423,11 @@
 	drops = 0;
 	DRX(("\n"));
 	while (entry != limit) {
-		struct myri_rxd *rxdack = &rqa->myri_rxd[entry];
+		struct myri_rxd __iomem *rxdack = &rqa->myri_rxd[entry];
 		u32 csum		= sbus_readl(&rxdack->csum);
 		int len			= sbus_readl(&rxdack->myri_scatters[0].len);
 		int index		= sbus_readl(&rxdack->ctx);
-		struct myri_rxd *rxd	= &rq->myri_rxd[rq->tail];
+		struct myri_rxd __iomem *rxd	= &rq->myri_rxd[rq->tail];
 		struct sk_buff *skb	= mp->rx_skbs[index];
 
 		/* Ack it. */
@@ -545,7 +545,7 @@
 {
 	struct net_device *dev		= (struct net_device *) dev_id;
 	struct myri_eth *mp		= (struct myri_eth *) dev->priv;
-	unsigned long lregs		= mp->lregs;
+	void __iomem *lregs		= mp->lregs;
 	struct myri_channel *chan	= &mp->shmem->channel;
 	unsigned long flags;
 	u32 status;
@@ -610,8 +610,8 @@
 static int myri_start_xmit(struct sk_buff *skb, struct net_device *dev)
 {
 	struct myri_eth *mp = (struct myri_eth *) dev->priv;
-	struct sendq *sq = mp->sq;
-	struct myri_txd *txd;
+	struct sendq __iomem *sq = mp->sq;
+	struct myri_txd __iomem *txd;
 	unsigned long flags;
 	unsigned int head, tail;
 	int len, entry;
@@ -998,22 +998,20 @@
 			printk("MyriCOM: Cannot map MyriCOM registers.\n");
 			goto err;
 		}
-		mp->lanai = (unsigned short *) (mp->regs + (256 * 1024));
-		mp->lanai3 = (unsigned int *) mp->lanai;
-		mp->lregs = (unsigned long) &mp->lanai[0x10000];
+		mp->lanai = mp->regs + (256 * 1024);
+		mp->lregs = mp->lanai + (0x10000 * 2);
 	} else {
 		DET(("Mapping regs for cpuvers >= CPUVERS_4_0\n"));
 		mp->cregs = sbus_ioremap(&sdev->resource[0], 0,
 					 PAGE_SIZE, "MyriCOM Control Regs");
 		mp->lregs = sbus_ioremap(&sdev->resource[0], (256 * 1024),
 					 PAGE_SIZE, "MyriCOM LANAI Regs");
-		mp->lanai = (unsigned short *)
+		mp->lanai =
 			sbus_ioremap(&sdev->resource[0], (512 * 1024),
 				     mp->eeprom.ramsz, "MyriCOM SRAM");
-		mp->lanai3 = (unsigned int *) mp->lanai;
 	}
-	DET(("Registers mapped: cregs[%lx] lregs[%lx] lanai[%p] lanai3[%p]\n",
-	     mp->cregs, mp->lregs, mp->lanai, mp->lanai3));
+	DET(("Registers mapped: cregs[%p] lregs[%p] lanai[%p]\n",
+	     mp->cregs, mp->lregs, mp->lanai));
 
 	if (mp->eeprom.cpuvers >= CPUVERS_4_0)
 		mp->shmem_base = 0xf000;
@@ -1022,7 +1020,8 @@
 
 	DET(("Shared memory base is %04x, ", mp->shmem_base));
 
-	mp->shmem = (struct myri_shmem *) &mp->lanai[mp->shmem_base];
+	mp->shmem = (struct myri_shmem __iomem *)
+		(mp->lanai + (mp->shmem_base * 2));
 	DET(("shmem mapped at %p\n", mp->shmem));
 
 	mp->rqack	= &mp->shmem->channel.recvqa;
diff -Nru a/drivers/net/myri_sbus.h b/drivers/net/myri_sbus.h
--- a/drivers/net/myri_sbus.h	2004-10-18 14:56:49 -07:00
+++ b/drivers/net/myri_sbus.h	2004-10-18 14:56:49 -07:00
@@ -270,22 +270,21 @@
 	 * to obtain good cache hit rates.
 	 */
 	spinlock_t			irq_lock;
-	struct myri_shmem		*shmem;		/* Shared data structures.    */
-	unsigned long			cregs;		/* Control register space.    */
-	struct recvq			*rqack;		/* Where we ack rx's.         */
-	struct recvq			*rq;		/* Where we put buffers.      */
-	struct sendq			*sq;		/* Where we stuff tx's.       */
+	struct myri_shmem __iomem	*shmem;		/* Shared data structures.    */
+	void __iomem			*cregs;		/* Control register space.    */
+	struct recvq __iomem		*rqack;		/* Where we ack rx's.         */
+	struct recvq __iomem		*rq;		/* Where we put buffers.      */
+	struct sendq __iomem		*sq;		/* Where we stuff tx's.       */
 	struct net_device		*dev;		/* Linux/NET dev struct.      */
 	int				tx_old;		/* To speed up tx cleaning.   */
-	unsigned long			lregs;		/* Quick ptr to LANAI regs.   */
+	void __iomem			*lregs;		/* Quick ptr to LANAI regs.   */
 	struct sk_buff	       *rx_skbs[RX_RING_SIZE+1];/* RX skb's                   */
 	struct sk_buff	       *tx_skbs[TX_RING_SIZE];  /* TX skb's                   */
 	struct net_device_stats		enet_stats;	/* Interface stats.           */
 
 	/* These are less frequently accessed. */
-	unsigned long			regs;          /* MyriCOM register space.    */
-	unsigned short			*lanai;		/* View 2 of register space.  */
-	unsigned int			*lanai3;	/* View 3 of register space.  */
+	void __iomem			*regs;          /* MyriCOM register space.    */
+	void __iomem			*lanai;		/* View 2 of register space.  */
 	unsigned int			myri_bursts;	/* SBUS bursts.               */
 	struct myri_eeprom		eeprom;		/* Local copy of EEPROM.      */
 	unsigned int			reg_size;	/* Size of register space.    */
diff -Nru a/drivers/net/natsemi.c b/drivers/net/natsemi.c
--- a/drivers/net/natsemi.c	2004-10-18 14:55:54 -07:00
+++ b/drivers/net/natsemi.c	2004-10-18 14:55:54 -07:00
@@ -719,7 +719,7 @@
 };
 
 static void move_int_phy(struct net_device *dev, int addr);
-static int eeprom_read(long ioaddr, int location);
+static int eeprom_read(void __iomem *ioaddr, int location);
 static int mdio_read(struct net_device *dev, int reg);
 static void mdio_write(struct net_device *dev, int reg, u16 data);
 static void init_phy_fixup(struct net_device *dev);
@@ -750,6 +750,9 @@
 static void netdev_rx(struct net_device *dev);
 static void netdev_tx_done(struct net_device *dev);
 static int natsemi_change_mtu(struct net_device *dev, int new_mtu);
+#ifdef CONFIG_NET_POLL_CONTROLLER
+static void natsemi_poll_controller(struct net_device *dev);
+#endif
 static void __set_rx_mode(struct net_device *dev);
 static void set_rx_mode(struct net_device *dev);
 static void __get_stats(struct net_device *dev);
@@ -766,9 +769,15 @@
 static int netdev_get_regs(struct net_device *dev, u8 *buf);
 static int netdev_get_eeprom(struct net_device *dev, u8 *buf);
 
+static inline void __iomem *ns_ioaddr(struct net_device *dev)
+{
+	return (void __iomem *) dev->base_addr;
+}
+
 static void move_int_phy(struct net_device *dev, int addr)
 {
 	struct netdev_private *np = netdev_priv(dev);
+	void __iomem *ioaddr = ns_ioaddr(dev);
 	int target = 31;
 
 	/* 
@@ -785,8 +794,8 @@
 		target--;
 	if (target == np->phy_addr_external)
 		target--;
-	writew(target, dev->base_addr + PhyCtrl);
-	readw(dev->base_addr + PhyCtrl);
+	writew(target, ioaddr + PhyCtrl);
+	readw(ioaddr + PhyCtrl);
 	udelay(1);
 }
 
@@ -797,7 +806,8 @@
 	struct netdev_private *np;
 	int i, option, irq, chip_idx = ent->driver_data;
 	static int find_cnt = -1;
-	unsigned long ioaddr, iosize;
+	unsigned long iostart, iosize;
+	void __iomem *ioaddr;
 	const int pcibar = 1; /* PCI base address register */
 	int prev_eedata;
 	u32 tmp;
@@ -824,7 +834,7 @@
 	}
 
 	find_cnt++;
-	ioaddr = pci_resource_start(pdev, pcibar);
+	iostart = pci_resource_start(pdev, pcibar);
 	iosize = pci_resource_len(pdev, pcibar);
 	irq = pdev->irq;
 
@@ -841,7 +851,7 @@
 	if (i)
 		goto err_pci_request_regions;
 
-	ioaddr = (unsigned long) ioremap (ioaddr, iosize);
+	ioaddr = ioremap(iostart, iosize);
 	if (!ioaddr) {
 		i = -ENOMEM;
 		goto err_ioremap;
@@ -856,7 +866,7 @@
 		prev_eedata = eedata;
 	}
 
-	dev->base_addr = ioaddr;
+	dev->base_addr = (unsigned long __force) ioaddr;
 	dev->irq = irq;
 
 	np = netdev_priv(dev);
@@ -876,7 +886,7 @@
 	 * The address would be used to access a phy over the mii bus, but
 	 * the internal phy is accessed through mapped registers.
 	 */
-	if (readl(dev->base_addr + ChipConfig) & CfgExtPhy)
+	if (readl(ioaddr + ChipConfig) & CfgExtPhy)
 		dev->if_port = PORT_MII;
 	else
 		dev->if_port = PORT_TP;
@@ -920,6 +930,9 @@
 	dev->do_ioctl = &netdev_ioctl;
 	dev->tx_timeout = &tx_timeout;
 	dev->watchdog_timeo = TX_TIMEOUT;
+#ifdef CONFIG_NET_POLL_CONTROLLER
+	dev->poll_controller = &natsemi_poll_controller;
+#endif
 
 	if (mtu)
 		dev->mtu = mtu;
@@ -965,7 +978,7 @@
 
 	if (netif_msg_drv(np)) {
 		printk(KERN_INFO "natsemi %s: %s at %#08lx (%s), ",
-			dev->name, natsemi_pci_info[chip_idx].name, ioaddr,
+			dev->name, natsemi_pci_info[chip_idx].name, iostart,
 			pci_name(np->pci_dev));
 		for (i = 0; i < ETH_ALEN-1; i++)
 				printk("%02x:", dev->dev_addr[i]);
@@ -978,7 +991,7 @@
 	return 0;
 
  err_register_netdev:
-	iounmap ((void *) dev->base_addr);
+	iounmap(ioaddr);
 
  err_ioremap:
 	pci_release_regions(pdev);
@@ -1010,12 +1023,13 @@
 	EE_WriteCmd=(5 << 6), EE_ReadCmd=(6 << 6), EE_EraseCmd=(7 << 6),
 };
 
-static int eeprom_read(long addr, int location)
+static int eeprom_read(void __iomem *addr, int location)
 {
 	int i;
 	int retval = 0;
-	long ee_addr = addr + EECtrl;
+	void __iomem *ee_addr = addr + EECtrl;
 	int read_cmd = location | EE_ReadCmd;
+
 	writel(EE_Write0, ee_addr);
 
 	/* Shift the read command bits out. */
@@ -1052,33 +1066,35 @@
 /* clock transitions >= 20ns (25MHz)
  * One readl should be good to PCI @ 100MHz
  */
-#define mii_delay(dev)  readl(dev->base_addr + EECtrl)
+#define mii_delay(ioaddr)  readl(ioaddr + EECtrl)
 
 static int mii_getbit (struct net_device *dev)
 {
 	int data;
+	void __iomem *ioaddr = ns_ioaddr(dev);
 
-	writel(MII_ShiftClk, dev->base_addr + EECtrl);
-	data = readl(dev->base_addr + EECtrl);
-	writel(0, dev->base_addr + EECtrl);
-	mii_delay(dev);
+	writel(MII_ShiftClk, ioaddr + EECtrl);
+	data = readl(ioaddr + EECtrl);
+	writel(0, ioaddr + EECtrl);
+	mii_delay(ioaddr);
 	return (data & MII_Data)? 1 : 0;
 }
 
 static void mii_send_bits (struct net_device *dev, u32 data, int len)
 {
 	u32 i;
+	void __iomem *ioaddr = ns_ioaddr(dev);
 
 	for (i = (1 << (len-1)); i; i >>= 1)
 	{
 		u32 mdio_val = MII_Write | ((data & i)? MII_Data : 0);
-		writel(mdio_val, dev->base_addr + EECtrl);
-		mii_delay(dev);
-		writel(mdio_val | MII_ShiftClk, dev->base_addr + EECtrl);
-		mii_delay(dev);
+		writel(mdio_val, ioaddr + EECtrl);
+		mii_delay(ioaddr);
+		writel(mdio_val | MII_ShiftClk, ioaddr + EECtrl);
+		mii_delay(ioaddr);
 	}
-	writel(0, dev->base_addr + EECtrl);
-	mii_delay(dev);
+	writel(0, ioaddr + EECtrl);
+	mii_delay(ioaddr);
 }
 
 static int miiport_read(struct net_device *dev, int phy_id, int reg)
@@ -1123,13 +1139,14 @@
 static int mdio_read(struct net_device *dev, int reg)
 {
 	struct netdev_private *np = netdev_priv(dev);
+	void __iomem *ioaddr = ns_ioaddr(dev);
 
 	/* The 83815 series has two ports:
 	 * - an internal transceiver
 	 * - an external mii bus
 	 */
 	if (dev->if_port == PORT_TP)
-		return readw(dev->base_addr+BasicControl+(reg<<2));
+		return readw(ioaddr+BasicControl+(reg<<2));
 	else
 		return miiport_read(dev, np->phy_addr_external, reg);
 }
@@ -1137,10 +1154,11 @@
 static void mdio_write(struct net_device *dev, int reg, u16 data)
 {
 	struct netdev_private *np = netdev_priv(dev);
+	void __iomem *ioaddr = ns_ioaddr(dev);
 
 	/* The 83815 series has an internal transceiver; handle separately */
 	if (dev->if_port == PORT_TP)
-		writew(data, dev->base_addr+BasicControl+(reg<<2));
+		writew(data, ioaddr+BasicControl+(reg<<2));
 	else
 		miiport_write(dev, np->phy_addr_external, reg, data);
 }
@@ -1148,7 +1166,7 @@
 static void init_phy_fixup(struct net_device *dev)
 {
 	struct netdev_private *np = netdev_priv(dev);
-	long ioaddr = dev->base_addr;
+	void __iomem *ioaddr = ns_ioaddr(dev);
 	int i;
 	u32 cfg;
 	u16 tmp;
@@ -1180,7 +1198,7 @@
 		 */
 	}
 	mdio_write(dev, MII_BMCR, tmp);
-	readl(dev->base_addr + ChipConfig);
+	readl(ioaddr + ChipConfig);
 	udelay(1);
 
 	/* find out what phy this is */
@@ -1202,7 +1220,7 @@
 	default:
 		break;
 	}
-	cfg = readl(dev->base_addr + ChipConfig);
+	cfg = readl(ioaddr + ChipConfig);
 	if (cfg & CfgExtPhy)
 		return;
 
@@ -1260,9 +1278,10 @@
 static int switch_port_external(struct net_device *dev)
 {
 	struct netdev_private *np = netdev_priv(dev);
+	void __iomem *ioaddr = ns_ioaddr(dev);
 	u32 cfg;
 
-	cfg = readl(dev->base_addr + ChipConfig);
+	cfg = readl(ioaddr + ChipConfig);
 	if (cfg & CfgExtPhy)
 		return 0;
 
@@ -1272,8 +1291,8 @@
 	}
 
 	/* 1) switch back to external phy */
-	writel(cfg | (CfgExtPhy | CfgPhyDis), dev->base_addr + ChipConfig);
-	readl(dev->base_addr + ChipConfig);
+	writel(cfg | (CfgExtPhy | CfgPhyDis), ioaddr + ChipConfig);
+	readl(ioaddr + ChipConfig);
 	udelay(1);
 
 	/* 2) reset the external phy: */
@@ -1292,11 +1311,12 @@
 static int switch_port_internal(struct net_device *dev)
 {
 	struct netdev_private *np = netdev_priv(dev);
+	void __iomem *ioaddr = ns_ioaddr(dev);
 	int i;
 	u32 cfg;
 	u16 bmcr;
 
-	cfg = readl(dev->base_addr + ChipConfig);
+	cfg = readl(ioaddr + ChipConfig);
 	if (!(cfg &CfgExtPhy))
 		return 0;
 
@@ -1306,17 +1326,17 @@
 	}
 	/* 1) switch back to internal phy: */
 	cfg = cfg & ~(CfgExtPhy | CfgPhyDis);
-	writel(cfg, dev->base_addr + ChipConfig);
-	readl(dev->base_addr + ChipConfig);
+	writel(cfg, ioaddr + ChipConfig);
+	readl(ioaddr + ChipConfig);
 	udelay(1);
 	
 	/* 2) reset the internal phy: */
-	bmcr = readw(dev->base_addr+BasicControl+(MII_BMCR<<2));
-	writel(bmcr | BMCR_RESET, dev->base_addr+BasicControl+(MII_BMCR<<2));
-	readl(dev->base_addr + ChipConfig);
+	bmcr = readw(ioaddr+BasicControl+(MII_BMCR<<2));
+	writel(bmcr | BMCR_RESET, ioaddr+BasicControl+(MII_BMCR<<2));
+	readl(ioaddr + ChipConfig);
 	udelay(10);
 	for (i=0;i<NATSEMI_HW_TIMEOUT;i++) {
-		bmcr = readw(dev->base_addr+BasicControl+(MII_BMCR<<2));
+		bmcr = readw(ioaddr+BasicControl+(MII_BMCR<<2));
 		if (!(bmcr & BMCR_RESET))
 			break;
 		udelay(10);
@@ -1392,6 +1412,7 @@
 	u16 pmatch[3];
 	u16 sopass[3];
 	struct netdev_private *np = netdev_priv(dev);
+	void __iomem *ioaddr = ns_ioaddr(dev);
 
 	/*
 	 * Resetting the chip causes some registers to be lost.
@@ -1402,26 +1423,26 @@
 	 */
 
 	/* CFG */
-	cfg = readl(dev->base_addr + ChipConfig) & CFG_RESET_SAVE;
+	cfg = readl(ioaddr + ChipConfig) & CFG_RESET_SAVE;
 	/* WCSR */
-	wcsr = readl(dev->base_addr + WOLCmd) & WCSR_RESET_SAVE;
+	wcsr = readl(ioaddr + WOLCmd) & WCSR_RESET_SAVE;
 	/* RFCR */
-	rfcr = readl(dev->base_addr + RxFilterAddr) & RFCR_RESET_SAVE;
+	rfcr = readl(ioaddr + RxFilterAddr) & RFCR_RESET_SAVE;
 	/* PMATCH */
 	for (i = 0; i < 3; i++) {
-		writel(i*2, dev->base_addr + RxFilterAddr);
-		pmatch[i] = readw(dev->base_addr + RxFilterData);
+		writel(i*2, ioaddr + RxFilterAddr);
+		pmatch[i] = readw(ioaddr + RxFilterData);
 	}
 	/* SOPAS */
 	for (i = 0; i < 3; i++) {
-		writel(0xa+(i*2), dev->base_addr + RxFilterAddr);
-		sopass[i] = readw(dev->base_addr + RxFilterData);
+		writel(0xa+(i*2), ioaddr + RxFilterAddr);
+		sopass[i] = readw(ioaddr + RxFilterData);
 	}
 
 	/* now whack the chip */
-	writel(ChipReset, dev->base_addr + ChipCmd);
+	writel(ChipReset, ioaddr + ChipCmd);
 	for (i=0;i<NATSEMI_HW_TIMEOUT;i++) {
-		if (!(readl(dev->base_addr + ChipCmd) & ChipReset))
+		if (!(readl(ioaddr + ChipCmd) & ChipReset))
 			break;
 		udelay(5);
 	}
@@ -1434,40 +1455,41 @@
 	}
 
 	/* restore CFG */
-	cfg |= readl(dev->base_addr + ChipConfig) & ~CFG_RESET_SAVE;
+	cfg |= readl(ioaddr + ChipConfig) & ~CFG_RESET_SAVE;
 	/* turn on external phy if it was selected */
 	if (dev->if_port == PORT_TP)
 		cfg &= ~(CfgExtPhy | CfgPhyDis);
 	else
 		cfg |= (CfgExtPhy | CfgPhyDis);
-	writel(cfg, dev->base_addr + ChipConfig);
+	writel(cfg, ioaddr + ChipConfig);
 	/* restore WCSR */
-	wcsr |= readl(dev->base_addr + WOLCmd) & ~WCSR_RESET_SAVE;
-	writel(wcsr, dev->base_addr + WOLCmd);
+	wcsr |= readl(ioaddr + WOLCmd) & ~WCSR_RESET_SAVE;
+	writel(wcsr, ioaddr + WOLCmd);
 	/* read RFCR */
-	rfcr |= readl(dev->base_addr + RxFilterAddr) & ~RFCR_RESET_SAVE;
+	rfcr |= readl(ioaddr + RxFilterAddr) & ~RFCR_RESET_SAVE;
 	/* restore PMATCH */
 	for (i = 0; i < 3; i++) {
-		writel(i*2, dev->base_addr + RxFilterAddr);
-		writew(pmatch[i], dev->base_addr + RxFilterData);
+		writel(i*2, ioaddr + RxFilterAddr);
+		writew(pmatch[i], ioaddr + RxFilterData);
 	}
 	for (i = 0; i < 3; i++) {
-		writel(0xa+(i*2), dev->base_addr + RxFilterAddr);
-		writew(sopass[i], dev->base_addr + RxFilterData);
+		writel(0xa+(i*2), ioaddr + RxFilterAddr);
+		writew(sopass[i], ioaddr + RxFilterData);
 	}
 	/* restore RFCR */
-	writel(rfcr, dev->base_addr + RxFilterAddr);
+	writel(rfcr, ioaddr + RxFilterAddr);
 }
 
 static void natsemi_reload_eeprom(struct net_device *dev)
 {
 	struct netdev_private *np = netdev_priv(dev);
+	void __iomem *ioaddr = ns_ioaddr(dev);
 	int i;
 
-	writel(EepromReload, dev->base_addr + PCIBusCfg);
+	writel(EepromReload, ioaddr + PCIBusCfg);
 	for (i=0;i<NATSEMI_HW_TIMEOUT;i++) {
 		udelay(50);
-		if (!(readl(dev->base_addr + PCIBusCfg) & EepromReload))
+		if (!(readl(ioaddr + PCIBusCfg) & EepromReload))
 			break;
 	}
 	if (i==NATSEMI_HW_TIMEOUT) {
@@ -1481,7 +1503,7 @@
 
 static void natsemi_stop_rxtx(struct net_device *dev)
 {
-	long ioaddr = dev->base_addr;
+	void __iomem * ioaddr = ns_ioaddr(dev);
 	struct netdev_private *np = netdev_priv(dev);
 	int i;
 
@@ -1503,7 +1525,7 @@
 static int netdev_open(struct net_device *dev)
 {
 	struct netdev_private *np = netdev_priv(dev);
-	long ioaddr = dev->base_addr;
+	void __iomem * ioaddr = ns_ioaddr(dev);
 	int i;
 
 	/* Reset the chip, just in case. */
@@ -1552,6 +1574,7 @@
 static void do_cable_magic(struct net_device *dev)
 {
 	struct netdev_private *np = netdev_priv(dev);
+	void __iomem *ioaddr = ns_ioaddr(dev);
 
 	if (dev->if_port != PORT_TP)
 		return;
@@ -1565,15 +1588,15 @@
 	 * activity LED while idle.  This process is based on instructions
 	 * from engineers at National.
 	 */
-	if (readl(dev->base_addr + ChipConfig) & CfgSpeed100) {
+	if (readl(ioaddr + ChipConfig) & CfgSpeed100) {
 		u16 data;
 
-		writew(1, dev->base_addr + PGSEL);
+		writew(1, ioaddr + PGSEL);
 		/*
 		 * coefficient visibility should already be enabled via
 		 * DSPCFG | 0x1000
 		 */
-		data = readw(dev->base_addr + TSTDAT) & 0xff;
+		data = readw(ioaddr + TSTDAT) & 0xff;
 		/*
 		 * the value must be negative, and within certain values
 		 * (these values all come from National)
@@ -1582,13 +1605,13 @@
 			struct netdev_private *np = netdev_priv(dev);
 
 			/* the bug has been triggered - fix the coefficient */
-			writew(TSTDAT_FIXED, dev->base_addr + TSTDAT);
+			writew(TSTDAT_FIXED, ioaddr + TSTDAT);
 			/* lock the value */
-			data = readw(dev->base_addr + DSPCFG);
+			data = readw(ioaddr + DSPCFG);
 			np->dspcfg = data | DSPCFG_LOCK;
-			writew(np->dspcfg, dev->base_addr + DSPCFG);
+			writew(np->dspcfg, ioaddr + DSPCFG);
 		}
-		writew(0, dev->base_addr + PGSEL);
+		writew(0, ioaddr + PGSEL);
 	}
 }
 
@@ -1596,6 +1619,7 @@
 {
 	u16 data;
 	struct netdev_private *np = netdev_priv(dev);
+	void __iomem * ioaddr = ns_ioaddr(dev);
 
 	if (dev->if_port != PORT_TP)
 		return;
@@ -1603,18 +1627,18 @@
 	if (np->srr >= SRR_DP83816_A5)
 		return;
 
-	writew(1, dev->base_addr + PGSEL);
+	writew(1, ioaddr + PGSEL);
 	/* make sure the lock bit is clear */
-	data = readw(dev->base_addr + DSPCFG);
+	data = readw(ioaddr + DSPCFG);
 	np->dspcfg = data & ~DSPCFG_LOCK;
-	writew(np->dspcfg, dev->base_addr + DSPCFG);
-	writew(0, dev->base_addr + PGSEL);
+	writew(np->dspcfg, ioaddr + DSPCFG);
+	writew(0, ioaddr + PGSEL);
 }
 
 static void check_link(struct net_device *dev)
 {
 	struct netdev_private *np = netdev_priv(dev);
-	long ioaddr = dev->base_addr;
+	void __iomem * ioaddr = ns_ioaddr(dev);
 	int duplex;
 	u16 bmsr;
        
@@ -1675,7 +1699,7 @@
 static void init_registers(struct net_device *dev)
 {
 	struct netdev_private *np = netdev_priv(dev);
-	long ioaddr = dev->base_addr;
+	void __iomem * ioaddr = ns_ioaddr(dev);
 
 	init_phy_fixup(dev);
 
@@ -1754,6 +1778,7 @@
 {
 	struct net_device *dev = (struct net_device *)data;
 	struct netdev_private *np = netdev_priv(dev);
+	void __iomem * ioaddr = ns_ioaddr(dev);
 	int next_tick = 5*HZ;
 
 	if (netif_msg_timer(np)) {
@@ -1765,7 +1790,6 @@
 	}
 
 	if (dev->if_port == PORT_TP) {
-		long ioaddr = dev->base_addr;
 		u16 dspcfg;
 
 		spin_lock_irq(&np->lock);
@@ -1808,7 +1832,7 @@
 		refill_rx(dev);
 		enable_irq(dev->irq);
 		if (!np->oom) {
-			writel(RxOn, dev->base_addr + ChipCmd);
+			writel(RxOn, ioaddr + ChipCmd);
 		} else {
 			next_tick = 1;
 		}
@@ -1842,7 +1866,7 @@
 static void tx_timeout(struct net_device *dev)
 {
 	struct netdev_private *np = netdev_priv(dev);
-	long ioaddr = dev->base_addr;
+	void __iomem * ioaddr = ns_ioaddr(dev);
 
 	disable_irq(dev->irq);
 	spin_lock_irq(&np->lock);
@@ -2042,6 +2066,7 @@
 static int start_tx(struct sk_buff *skb, struct net_device *dev)
 {
 	struct netdev_private *np = netdev_priv(dev);
+	void __iomem * ioaddr = ns_ioaddr(dev);
 	unsigned entry;
 
 	/* Note: Ordering is important here, set the field with the
@@ -2070,7 +2095,7 @@
 				netif_stop_queue(dev);
 		}
 		/* Wake the potentially-idle transmit channel. */
-		writel(TxOn, dev->base_addr + ChipCmd);
+		writel(TxOn, ioaddr + ChipCmd);
 	} else {
 		dev_kfree_skb_irq(skb);
 		np->stats.tx_dropped++;
@@ -2135,7 +2160,7 @@
 {
 	struct net_device *dev = dev_instance;
 	struct netdev_private *np = netdev_priv(dev);
-	long ioaddr = dev->base_addr;
+	void __iomem * ioaddr = ns_ioaddr(dev);
 	int boguscnt = max_interrupt_work;
 	unsigned int handled = 0;
 
@@ -2197,6 +2222,7 @@
 	int boguscnt = np->dirty_rx + RX_RING_SIZE - np->cur_rx;
 	s32 desc_status = le32_to_cpu(np->rx_head_desc->cmd_status);
 	unsigned int buflen = np->rx_buf_sz;
+	void __iomem * ioaddr = ns_ioaddr(dev);
 
 	/* If the driver owns the next entry it's a new packet. Send it up. */
 	while (desc_status < 0) { /* e.g. & DescOwn */
@@ -2278,13 +2304,13 @@
 	if (np->oom)
 		mod_timer(&np->timer, jiffies + 1);
 	else
-		writel(RxOn, dev->base_addr + ChipCmd);
+		writel(RxOn, ioaddr + ChipCmd);
 }
 
 static void netdev_error(struct net_device *dev, int intr_status)
 {
 	struct netdev_private *np = netdev_priv(dev);
-	long ioaddr = dev->base_addr;
+	void __iomem * ioaddr = ns_ioaddr(dev);
 
 	spin_lock(&np->lock);
 	if (intr_status & LinkChange) {
@@ -2343,7 +2369,7 @@
 
 static void __get_stats(struct net_device *dev)
 {
-	long ioaddr = dev->base_addr;
+	void __iomem * ioaddr = ns_ioaddr(dev);
 	struct netdev_private *np = netdev_priv(dev);
 
 	/* The chip only need report frame silently dropped. */
@@ -2364,10 +2390,19 @@
 	return &np->stats;
 }
 
+#ifdef CONFIG_NET_POLL_CONTROLLER
+static void natsemi_poll_controller(struct net_device *dev)
+{
+	disable_irq(dev->irq);
+	intr_handler(dev->irq, dev, NULL);
+	enable_irq(dev->irq);
+}
+#endif
+
 #define HASH_TABLE	0x200
 static void __set_rx_mode(struct net_device *dev)
 {
-	long ioaddr = dev->base_addr;
+	void __iomem * ioaddr = ns_ioaddr(dev);
 	struct netdev_private *np = netdev_priv(dev);
 	u8 mc_filter[64]; /* Multicast hash filter */
 	u32 rx_mode;
@@ -2413,7 +2448,7 @@
 	/* synchronized against open : rtnl_lock() held by caller */
 	if (netif_running(dev)) {
 		struct netdev_private *np = netdev_priv(dev);
-		long ioaddr = dev->base_addr;
+		void __iomem * ioaddr = ns_ioaddr(dev);
 
 		disable_irq(dev->irq);
 		spin_lock(&np->lock);
@@ -2616,7 +2651,8 @@
 static int netdev_set_wol(struct net_device *dev, u32 newval)
 {
 	struct netdev_private *np = netdev_priv(dev);
-	u32 data = readl(dev->base_addr + WOLCmd) & ~WakeOptsSummary;
+	void __iomem * ioaddr = ns_ioaddr(dev);
+	u32 data = readl(ioaddr + WOLCmd) & ~WakeOptsSummary;
 
 	/* translate to bitmasks this chip understands */
 	if (newval & WAKE_PHY)
@@ -2637,7 +2673,7 @@
 		}
 	}
 
-	writel(data, dev->base_addr + WOLCmd);
+	writel(data, ioaddr + WOLCmd);
 
 	return 0;
 }
@@ -2645,7 +2681,8 @@
 static int netdev_get_wol(struct net_device *dev, u32 *supported, u32 *cur)
 {
 	struct netdev_private *np = netdev_priv(dev);
-	u32 regval = readl(dev->base_addr + WOLCmd);
+	void __iomem * ioaddr = ns_ioaddr(dev);
+	u32 regval = readl(ioaddr + WOLCmd);
 
 	*supported = (WAKE_PHY | WAKE_UCAST | WAKE_MCAST | WAKE_BCAST
 			| WAKE_ARP | WAKE_MAGIC);
@@ -2680,6 +2717,7 @@
 static int netdev_set_sopass(struct net_device *dev, u8 *newval)
 {
 	struct netdev_private *np = netdev_priv(dev);
+	void __iomem * ioaddr = ns_ioaddr(dev);
 	u16 *sval = (u16 *)newval;
 	u32 addr;
 
@@ -2688,22 +2726,22 @@
 	}
 
 	/* enable writing to these registers by disabling the RX filter */
-	addr = readl(dev->base_addr + RxFilterAddr) & ~RFCRAddressMask;
+	addr = readl(ioaddr + RxFilterAddr) & ~RFCRAddressMask;
 	addr &= ~RxFilterEnable;
-	writel(addr, dev->base_addr + RxFilterAddr);
+	writel(addr, ioaddr + RxFilterAddr);
 
 	/* write the three words to (undocumented) RFCR vals 0xa, 0xc, 0xe */
-	writel(addr | 0xa, dev->base_addr + RxFilterAddr);
-	writew(sval[0], dev->base_addr + RxFilterData);
+	writel(addr | 0xa, ioaddr + RxFilterAddr);
+	writew(sval[0], ioaddr + RxFilterData);
 
-	writel(addr | 0xc, dev->base_addr + RxFilterAddr);
-	writew(sval[1], dev->base_addr + RxFilterData);
+	writel(addr | 0xc, ioaddr + RxFilterAddr);
+	writew(sval[1], ioaddr + RxFilterData);
 
-	writel(addr | 0xe, dev->base_addr + RxFilterAddr);
-	writew(sval[2], dev->base_addr + RxFilterData);
+	writel(addr | 0xe, ioaddr + RxFilterAddr);
+	writew(sval[2], ioaddr + RxFilterData);
 
 	/* re-enable the RX filter */
-	writel(addr | RxFilterEnable, dev->base_addr + RxFilterAddr);
+	writel(addr | RxFilterEnable, ioaddr + RxFilterAddr);
 
 	return 0;
 }
@@ -2711,6 +2749,7 @@
 static int netdev_get_sopass(struct net_device *dev, u8 *data)
 {
 	struct netdev_private *np = netdev_priv(dev);
+	void __iomem * ioaddr = ns_ioaddr(dev);
 	u16 *sval = (u16 *)data;
 	u32 addr;
 
@@ -2720,18 +2759,18 @@
 	}
 
 	/* read the three words from (undocumented) RFCR vals 0xa, 0xc, 0xe */
-	addr = readl(dev->base_addr + RxFilterAddr) & ~RFCRAddressMask;
+	addr = readl(ioaddr + RxFilterAddr) & ~RFCRAddressMask;
 
-	writel(addr | 0xa, dev->base_addr + RxFilterAddr);
-	sval[0] = readw(dev->base_addr + RxFilterData);
+	writel(addr | 0xa, ioaddr + RxFilterAddr);
+	sval[0] = readw(ioaddr + RxFilterData);
 
-	writel(addr | 0xc, dev->base_addr + RxFilterAddr);
-	sval[1] = readw(dev->base_addr + RxFilterData);
+	writel(addr | 0xc, ioaddr + RxFilterAddr);
+	sval[1] = readw(ioaddr + RxFilterData);
 
-	writel(addr | 0xe, dev->base_addr + RxFilterAddr);
-	sval[2] = readw(dev->base_addr + RxFilterData);
+	writel(addr | 0xe, ioaddr + RxFilterAddr);
+	sval[2] = readw(ioaddr + RxFilterData);
 
-	writel(addr, dev->base_addr + RxFilterAddr);
+	writel(addr, ioaddr + RxFilterAddr);
 
 	return 0;
 }
@@ -2894,10 +2933,11 @@
 	int j;
 	u32 rfcr;
 	u32 *rbuf = (u32 *)buf;
+	void __iomem * ioaddr = ns_ioaddr(dev);
 
 	/* read non-mii page 0 of registers */
 	for (i = 0; i < NATSEMI_PG0_NREGS/2; i++) {
-		rbuf[i] = readl(dev->base_addr + i*4);
+		rbuf[i] = readl(ioaddr + i*4);
 	}
 
 	/* read current mii registers */
@@ -2905,20 +2945,20 @@
 		rbuf[i] = mdio_read(dev, i & 0x1f);
 
 	/* read only the 'magic' registers from page 1 */
-	writew(1, dev->base_addr + PGSEL);
-	rbuf[i++] = readw(dev->base_addr + PMDCSR);
-	rbuf[i++] = readw(dev->base_addr + TSTDAT);
-	rbuf[i++] = readw(dev->base_addr + DSPCFG);
-	rbuf[i++] = readw(dev->base_addr + SDCFG);
-	writew(0, dev->base_addr + PGSEL);
+	writew(1, ioaddr + PGSEL);
+	rbuf[i++] = readw(ioaddr + PMDCSR);
+	rbuf[i++] = readw(ioaddr + TSTDAT);
+	rbuf[i++] = readw(ioaddr + DSPCFG);
+	rbuf[i++] = readw(ioaddr + SDCFG);
+	writew(0, ioaddr + PGSEL);
 
 	/* read RFCR indexed registers */
-	rfcr = readl(dev->base_addr + RxFilterAddr);
+	rfcr = readl(ioaddr + RxFilterAddr);
 	for (j = 0; j < NATSEMI_RFDR_NREGS; j++) {
-		writel(j*2, dev->base_addr + RxFilterAddr);
-		rbuf[i++] = readw(dev->base_addr + RxFilterData);
+		writel(j*2, ioaddr + RxFilterAddr);
+		rbuf[i++] = readw(ioaddr + RxFilterData);
 	}
-	writel(rfcr, dev->base_addr + RxFilterAddr);
+	writel(rfcr, ioaddr + RxFilterAddr);
 
 	/* the interrupt status is clear-on-read - see if we missed any */
 	if (rbuf[4] & rbuf[5]) {
@@ -2943,10 +2983,11 @@
 {
 	int i;
 	u16 *ebuf = (u16 *)buf;
+	void __iomem * ioaddr = ns_ioaddr(dev);
 
 	/* eeprom_read reads 16 bits, and indexes by 16 bits */
 	for (i = 0; i < NATSEMI_EEPROM_SIZE/2; i++) {
-		ebuf[i] = eeprom_read(dev->base_addr, i);
+		ebuf[i] = eeprom_read(ioaddr, i);
 		/* The EEPROM itself stores data bit-swapped, but eeprom_read
 		 * reads it back "sanely". So we swap it back here in order to
 		 * present it to userland as it is stored. */
@@ -3016,7 +3057,7 @@
 
 static void enable_wol_mode(struct net_device *dev, int enable_intr)
 {
-	long ioaddr = dev->base_addr;
+	void __iomem * ioaddr = ns_ioaddr(dev);
 	struct netdev_private *np = netdev_priv(dev);
 
 	if (netif_msg_wol(np))
@@ -3049,7 +3090,7 @@
 
 static int netdev_close(struct net_device *dev)
 {
-	long ioaddr = dev->base_addr;
+	void __iomem * ioaddr = ns_ioaddr(dev);
 	struct netdev_private *np = netdev_priv(dev);
 
 	if (netif_msg_ifdown(np))
@@ -3126,10 +3167,11 @@
 static void __devexit natsemi_remove1 (struct pci_dev *pdev)
 {
 	struct net_device *dev = pci_get_drvdata(pdev);
+	void __iomem * ioaddr = ns_ioaddr(dev);
 
 	unregister_netdev (dev);
 	pci_release_regions (pdev);
-	iounmap ((char *) dev->base_addr);
+	iounmap(ioaddr);
 	free_netdev (dev);
 	pci_set_drvdata(pdev, NULL);
 }
@@ -3163,7 +3205,7 @@
 {
 	struct net_device *dev = pci_get_drvdata (pdev);
 	struct netdev_private *np = netdev_priv(dev);
-	long ioaddr = dev->base_addr;
+	void __iomem * ioaddr = ns_ioaddr(dev);
 
 	rtnl_lock();
 	if (netif_running (dev)) {
diff -Nru a/drivers/net/ne.c b/drivers/net/ne.c
--- a/drivers/net/ne.c	2004-10-18 14:56:29 -07:00
+++ b/drivers/net/ne.c	2004-10-18 14:56:29 -07:00
@@ -29,6 +29,7 @@
     last in cleanup_modue()
     Richard Guenther    : Added support for ISAPnP cards
     Paul Gortmaker	: Discontinued PCI support - use ne2k-pci.c instead.
+    Hayato Fujiwara	: Add m32r support.
 
 */
 
@@ -128,6 +129,14 @@
 #define NESM_START_PG	0x40	/* First page of TX buffer */
 #define NESM_STOP_PG	0x80	/* Last page +1 of RX ring */
 
+#ifdef CONFIG_PLAT_MAPPI
+#  define DCR_VAL 0x4b
+#elif CONFIG_PLAT_OAKS32R
+#  define DCR_VAL 0x48
+#else
+#  define DCR_VAL 0x49
+#endif
+
 static int ne_probe1(struct net_device *dev, int ioaddr);
 static int ne_probe_isapnp(struct net_device *dev);
 
@@ -387,7 +396,7 @@
 		for (i = 0; i < 16; i++)
 			SA_prom[i] = SA_prom[i+i];
 		/* We must set the 8390 for word mode. */
-		outb_p(0x49, ioaddr + EN0_DCFG);
+		outb_p(DCR_VAL, ioaddr + EN0_DCFG);
 		start_page = NESM_START_PG;
 		stop_page = NESM_STOP_PG;
 	} else {
@@ -395,7 +404,12 @@
 		stop_page = NE1SM_STOP_PG;
 	}
 
+#if  defined(CONFIG_PLAT_MAPPI) || defined(CONFIG_PLAT_OAKS32R)
+	neX000 = ((SA_prom[14] == 0x57  &&  SA_prom[15] == 0x57)
+		|| (SA_prom[14] == 0x42 && SA_prom[15] == 0x42));
+#else
 	neX000 = (SA_prom[14] == 0x57  &&  SA_prom[15] == 0x57);
+#endif
 	ctron =  (SA_prom[0] == 0x00 && SA_prom[1] == 0x00 && SA_prom[2] == 0x1d);
 	copam =  (SA_prom[14] == 0x49 && SA_prom[15] == 0x00);
 
@@ -476,10 +490,20 @@
 
 	dev->base_addr = ioaddr;
 
+#ifdef CONFIG_PLAT_MAPPI
+	outb_p(E8390_NODMA + E8390_PAGE1 + E8390_STOP,
+		ioaddr + E8390_CMD); /* 0x61 */
+	for (i = 0 ; i < ETHER_ADDR_LEN ; i++) {
+		dev->dev_addr[i] = SA_prom[i]
+			= inb_p(ioaddr + EN1_PHYS_SHIFT(i));
+		printk(" %2.2x", SA_prom[i]);
+	}
+#else
 	for(i = 0; i < ETHER_ADDR_LEN; i++) {
 		printk(" %2.2x", SA_prom[i]);
 		dev->dev_addr[i] = SA_prom[i];
 	}
+#endif
 
 	printk("\n%s: %s found at %#x, using IRQ %d.\n",
 		dev->name, name, ioaddr, dev->irq);
@@ -487,7 +511,11 @@
 	ei_status.name = name;
 	ei_status.tx_start_page = start_page;
 	ei_status.stop_page = stop_page;
+#ifdef CONFIG_PLAT_OAKS32R
+	ei_status.word16 = 0;
+#else
 	ei_status.word16 = (wordlength == 2);
+#endif
 
 	ei_status.rx_start_page = start_page + TX_PAGES;
 #ifdef PACKETBUF_MEMSIZE
diff -Nru a/drivers/net/plip.c b/drivers/net/plip.c
--- a/drivers/net/plip.c	2004-10-18 14:57:04 -07:00
+++ b/drivers/net/plip.c	2004-10-18 14:57:04 -07:00
@@ -547,7 +547,7 @@
 	
 	skb->mac.raw=skb->data;
 	skb_pull(skb,dev->hard_header_len);
-	eth= skb->mac.ethernet;
+	eth = eth_hdr(skb);
 	
 	if(*eth->h_dest&1)
 	{
diff -Nru a/drivers/net/ppp_async.c b/drivers/net/ppp_async.c
--- a/drivers/net/ppp_async.c	2004-10-18 14:56:49 -07:00
+++ b/drivers/net/ppp_async.c	2004-10-18 14:56:49 -07:00
@@ -122,6 +122,9 @@
  * frees the memory that ppp_asynctty_receive is using.  The best
  * way to fix this is to use a rwlock in the tty struct, but for now
  * we use a single global rwlock for all ttys in ppp line discipline.
+ *
+ * FIXME: this is no longer true. The _close path for the ldisc is 
+ * now guaranteed to be sane. 
  */
 static rwlock_t disc_data_lock = RW_LOCK_UNLOCKED;
 
@@ -144,7 +147,8 @@
 }
 
 /*
- * Called when a tty is put into PPP line discipline.
+ * Called when a tty is put into PPP line discipline. Called in process
+ * context.
  */
 static int
 ppp_asynctty_open(struct tty_struct *tty)
@@ -255,6 +259,11 @@
 	return -EAGAIN;
 }
 
+/*
+ * Called in process context only. May be re-entered by multiple
+ * ioctl calling threads.
+ */
+ 
 static int
 ppp_asynctty_ioctl(struct tty_struct *tty, struct file *file,
 		   unsigned int cmd, unsigned long arg)
@@ -716,7 +725,8 @@
 
 /*
  * Flush output from our internal buffers.
- * Called for the TCFLSH ioctl.
+ * Called for the TCFLSH ioctl. Can be entered in parallel
+ * but this is covered by the xmit_lock.
  */
 static void
 ppp_async_flush_output(struct asyncppp *ap)
@@ -816,7 +826,9 @@
 		skb_trim(skb, 0);
 }
 
-/* called when the tty driver has data for us. */
+/* Called when the tty driver has data for us. Runs parallel with the
+   other ldisc functions but will not be re-entered */
+
 static void
 ppp_async_input(struct asyncppp *ap, const unsigned char *buf,
 		char *flags, int count)
diff -Nru a/drivers/net/ppp_generic.c b/drivers/net/ppp_generic.c
--- a/drivers/net/ppp_generic.c	2004-10-18 14:57:04 -07:00
+++ b/drivers/net/ppp_generic.c	2004-10-18 14:57:04 -07:00
@@ -1595,6 +1595,7 @@
 			skb->dev = ppp->dev;
 			skb->protocol = htons(npindex_to_ethertype[npi]);
 			skb->mac.raw = skb->data;
+			skb->input_dev = ppp->dev;
 			netif_rx(skb);
 			ppp->dev->last_rx = jiffies;
 		}
diff -Nru a/drivers/net/ppp_synctty.c b/drivers/net/ppp_synctty.c
--- a/drivers/net/ppp_synctty.c	2004-10-18 14:56:29 -07:00
+++ b/drivers/net/ppp_synctty.c	2004-10-18 14:56:29 -07:00
@@ -175,6 +175,8 @@
  * frees the memory that ppp_synctty_receive is using.  The best
  * way to fix this is to use a rwlock in the tty struct, but for now
  * we use a single global rwlock for all ttys in ppp line discipline.
+ *
+ * FIXME: Fixed in tty_io nowdays.
  */
 static rwlock_t disc_data_lock = RW_LOCK_UNLOCKED;
 
diff -Nru a/drivers/net/pppoe.c b/drivers/net/pppoe.c
--- a/drivers/net/pppoe.c	2004-10-18 14:56:33 -07:00
+++ b/drivers/net/pppoe.c	2004-10-18 14:56:33 -07:00
@@ -391,7 +391,7 @@
 
 	ph = (struct pppoe_hdr *) skb->nh.raw;
 
-	po = get_item((unsigned long) ph->sid, skb->mac.ethernet->h_source);
+	po = get_item((unsigned long) ph->sid, eth_hdr(skb)->h_source);
 	if (!po) 
 		goto drop;
 
@@ -440,7 +440,7 @@
 	if (ph->code != PADT_CODE)
 		goto abort;
 
-	po = get_item((unsigned long) ph->sid, skb->mac.ethernet->h_source);
+	po = get_item((unsigned long) ph->sid, eth_hdr(skb)->h_source);
 	if (po) {
 		struct sock *sk = po->sk;
 
diff -Nru a/drivers/net/r8169.c b/drivers/net/r8169.c
--- a/drivers/net/r8169.c	2004-10-18 14:56:32 -07:00
+++ b/drivers/net/r8169.c	2004-10-18 14:56:32 -07:00
@@ -7,7 +7,7 @@
  Feb  4 2002	- created initially by ShuChen <shuchen@realtek.com.tw>.
  May 20 2002	- Add link status force-mode and TBI mode support.
 =========================================================================
-  1. The media can be forced in 5 modes.
+  1. [DEPRECATED: use ethtool instead] The media can be forced in 5 modes.
 	 Command: 'insmod r8169 media = SET_MEDIA'
 	 Ex:	  'insmod r8169 media = 0x04' will force PHY to operate in 100Mpbs Half-duplex.
 	
@@ -41,6 +41,7 @@
 #include <linux/etherdevice.h>
 #include <linux/delay.h>
 #include <linux/ethtool.h>
+#include <linux/mii.h>
 #include <linux/crc32.h>
 #include <linux/init.h>
 #include <linux/dma-mapping.h>
@@ -64,6 +65,14 @@
 #define dprintk(fmt, args...)	do {} while (0)
 #endif /* RTL8169_DEBUG */
 
+#ifdef CONFIG_R8169_NAPI
+#define rtl8169_rx_skb			netif_receive_skb
+#define rtl8169_rx_quota(count, quota)	min(count, quota)
+#else
+#define rtl8169_rx_skb			netif_rx
+#define rtl8169_rx_quota(count, quota)	count
+#endif
+
 /* media options */
 #define MAX_UNITS 8
 static int media[MAX_UNITS] = { -1, -1, -1, -1, -1, -1, -1, -1 };
@@ -90,15 +99,16 @@
 #define RxPacketMaxSize	0x0800	/* Maximum size supported is 16K-1 */
 #define InterFrameGap	0x03	/* 3 means InterFrameGap = the shortest one */
 
+#define R8169_NAPI_WEIGHT	64
 #define NUM_TX_DESC	64	/* Number of Tx descriptor registers */
-#define NUM_RX_DESC	64	/* Number of Rx descriptor registers */
+#define NUM_RX_DESC	256	/* Number of Rx descriptor registers */
 #define RX_BUF_SIZE	1536	/* Rx Buffer size */
 #define R8169_TX_RING_BYTES	(NUM_TX_DESC * sizeof(struct TxDesc))
 #define R8169_RX_RING_BYTES	(NUM_RX_DESC * sizeof(struct RxDesc))
 
 #define RTL_MIN_IO_SIZE 0x80
 #define RTL8169_TX_TIMEOUT	(6*HZ)
-#define RTL8169_PHY_TIMEOUT	(HZ) 
+#define RTL8169_PHY_TIMEOUT	(10*HZ)
 
 /* write/read MMIO register */
 #define RTL_W8(reg, val8)	writeb ((val8), ioaddr + (reg))
@@ -146,6 +156,7 @@
 MODULE_DEVICE_TABLE(pci, rtl8169_pci_tbl);
 
 static int rx_copybreak = 200;
+static int use_dac;
 
 enum RTL8169_registers {
 	MAC0 = 0,		/* Ethernet hardware address. */
@@ -194,7 +205,7 @@
 	SWInt = 0x0100,
 	TxDescUnavail = 0x80,
 	RxFIFOOver = 0x40,
-	RxUnderrun = 0x20,
+	LinkChg = 0x20,
 	RxOverflow = 0x10,
 	TxErr = 0x08,
 	TxOK = 0x04,
@@ -233,6 +244,14 @@
 	TxInterFrameGapShift = 24,
 	TxDMAShift = 8,	/* DMA burst value (0-7) is shift this many bits */
 
+	/* TBICSR p.28 */
+	TBIReset	= 0x80000000,
+	TBILoopback	= 0x40000000,
+	TBINwEnable	= 0x20000000,
+	TBINwRestart	= 0x10000000,
+	TBILinkOk	= 0x02000000,
+	TBINwComplete	= 0x01000000,
+
 	/* CPlusCmd p.31 */
 	RxVlan		= (1 << 6),
 	RxChkSum	= (1 << 5),
@@ -306,10 +325,10 @@
 };
 
 struct rtl8169_private {
-	void *mmio_addr;	/* memory map physical address */
+	void *mmio_addr;		/* memory map physical address */
 	struct pci_dev *pci_dev;	/* Index of PCI device  */
 	struct net_device_stats stats;	/* statistics of net device */
-	spinlock_t lock;	/* spin lock flag */
+	spinlock_t lock;		/* spin lock flag */
 	int chipset;
 	int mac_version;
 	int phy_version;
@@ -317,21 +336,31 @@
 	u32 cur_tx; /* Index into the Tx descriptor buffer of next Rx pkt. */
 	u32 dirty_rx;
 	u32 dirty_tx;
-	struct TxDesc *TxDescArray;	/* Index of 256-alignment Tx Descriptor buffer */
-	struct RxDesc *RxDescArray;	/* Index of 256-alignment Rx Descriptor buffer */
+	struct TxDesc *TxDescArray;	/* 256-aligned Tx descriptor ring */
+	struct RxDesc *RxDescArray;	/* 256-aligned Rx descriptor ring */
 	dma_addr_t TxPhyAddr;
 	dma_addr_t RxPhyAddr;
 	struct sk_buff *Rx_skbuff[NUM_RX_DESC];	/* Rx data buffers */
-	struct sk_buff *Tx_skbuff[NUM_TX_DESC];	/* Index of Transmit data buffer */
+	struct sk_buff *Tx_skbuff[NUM_TX_DESC];	/* Tx data buffers */
 	struct timer_list timer;
-	unsigned long phy_link_down_cnt;
 	u16 cp_cmd;
+	u16 intr_mask;
+	int phy_auto_nego_reg;
+	int phy_1000_ctrl_reg;
+
+	int (*set_speed)(struct net_device *, u8 autoneg, u16 speed, u8 duplex);
+	void (*get_settings)(struct net_device *, struct ethtool_cmd *);
+	void (*phy_reset_enable)(void *);
+	unsigned int (*phy_reset_pending)(void *);
+	unsigned int (*link_ok)(void *);
 };
 
 MODULE_AUTHOR("Realtek");
 MODULE_DESCRIPTION("RealTek RTL-8169 Gigabit Ethernet driver");
 MODULE_PARM(media, "1-" __MODULE_STRING(MAX_UNITS) "i");
 MODULE_PARM(rx_copybreak, "i");
+MODULE_PARM(use_dac, "i");
+MODULE_PARM_DESC(use_dac, "Enable PCI DAC. Unsafe on 32 bit PCI slot.");
 MODULE_LICENSE("GPL");
 
 static int rtl8169_open(struct net_device *dev);
@@ -344,9 +373,14 @@
 static void rtl8169_set_rx_mode(struct net_device *dev);
 static void rtl8169_tx_timeout(struct net_device *dev);
 static struct net_device_stats *rtl8169_get_stats(struct net_device *netdev);
+#ifdef CONFIG_R8169_NAPI
+static int rtl8169_poll(struct net_device *dev, int *budget);
+#endif
 
 static const u16 rtl8169_intr_mask =
-    RxUnderrun | RxOverflow | RxFIFOOver | TxErr | TxOK | RxErr | RxOK;
+	SYSErr | LinkChg | RxOverflow | RxFIFOOver | TxErr | TxOK | RxErr | RxOK;
+static const u16 rtl8169_napi_event =
+	RxOK | RxOverflow | RxFIFOOver | TxOK | TxErr;
 static const unsigned int rtl8169_rx_config =
     (RX_FIFO_THRESH << RxCfgFIFOShift) | (RX_DMA_BURST << RxCfgDMAShift);
 
@@ -364,11 +398,9 @@
 
 	for (i = 2000; i > 0; i--) {
 		// Check if the RTL8169 has completed writing to the specified MII register
-		if (!(RTL_R32(PHYAR) & 0x80000000)) {
+		if (!(RTL_R32(PHYAR) & 0x80000000)) 
 			break;
-		} else {
-			udelay(100);
-		}
+		udelay(100);
 	}
 }
 
@@ -390,18 +422,264 @@
 	return value;
 }
 
+static unsigned int rtl8169_tbi_reset_pending(void *ioaddr)
+{
+	return RTL_R32(TBICSR) & TBIReset;
+}
+
+static unsigned int rtl8169_xmii_reset_pending(void *ioaddr)
+{
+	return mdio_read(ioaddr, 0) & 0x8000;
+}
+
+static unsigned int rtl8169_tbi_link_ok(void *ioaddr)
+{
+	return RTL_R32(TBICSR) & TBILinkOk;
+}
+
+static unsigned int rtl8169_xmii_link_ok(void *ioaddr)
+{
+	return RTL_R8(PHYstatus) & LinkStatus;
+}
+
+static void rtl8169_tbi_reset_enable(void *ioaddr)
+{
+	RTL_W32(TBICSR, RTL_R32(TBICSR) | TBIReset);
+}
+
+static void rtl8169_xmii_reset_enable(void *ioaddr)
+{
+	unsigned int val;
+
+	val = (mdio_read(ioaddr, PHY_CTRL_REG) | 0x8000) & 0xffff;
+	mdio_write(ioaddr, PHY_CTRL_REG, val);
+}
+
+static void rtl8169_check_link_status(struct net_device *dev,
+				      struct rtl8169_private *tp, void *ioaddr)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&tp->lock, flags);
+	if (tp->link_ok(ioaddr)) {
+		netif_carrier_on(dev);
+		printk(KERN_INFO PFX "%s: link up\n", dev->name);
+	} else
+		netif_carrier_off(dev);
+	spin_unlock_irqrestore(&tp->lock, flags);
+}
+
+static void rtl8169_link_option(int idx, u8 *autoneg, u16 *speed, u8 *duplex)
+{
+	struct {
+		u16 speed;
+		u8 duplex;
+		u8 autoneg;
+		u8 media;
+	} link_settings[] = {
+		{ SPEED_10,	DUPLEX_HALF, AUTONEG_DISABLE,	_10_Half },
+		{ SPEED_10,	DUPLEX_FULL, AUTONEG_DISABLE,	_10_Full },
+		{ SPEED_100,	DUPLEX_HALF, AUTONEG_DISABLE,	_100_Half },
+		{ SPEED_100,	DUPLEX_FULL, AUTONEG_DISABLE,	_100_Full },
+		{ SPEED_1000,	DUPLEX_FULL, AUTONEG_DISABLE,	_1000_Full },
+		/* Make TBI happy */
+		{ SPEED_1000,	DUPLEX_FULL, AUTONEG_ENABLE,	0xff }
+	}, *p;
+	unsigned char option;
+	
+	option = ((idx < MAX_UNITS) && (idx >= 0)) ? media[idx] : 0xff;
+
+	if ((option != 0xff) && !idx)
+		printk(KERN_WARNING PFX "media option is deprecated.\n");
+
+	for (p = link_settings; p->media != 0xff; p++) {
+		if (p->media == option)
+			break;
+	}
+	*autoneg = p->autoneg;
+	*speed = p->speed;
+	*duplex = p->duplex;
+}
+
 static void rtl8169_get_drvinfo(struct net_device *dev,
 				struct ethtool_drvinfo *info)
 {
-	struct rtl8169_private *tp = dev->priv;
+	struct rtl8169_private *tp = netdev_priv(dev);
 
 	strcpy(info->driver, RTL8169_DRIVER_NAME);
 	strcpy(info->version, RTL8169_VERSION );
 	strcpy(info->bus_info, pci_name(tp->pci_dev));
 }
 
+static int rtl8169_set_speed_tbi(struct net_device *dev,
+				 u8 autoneg, u16 speed, u8 duplex)
+{
+	struct rtl8169_private *tp = netdev_priv(dev);
+	void *ioaddr = tp->mmio_addr;
+	int ret = 0;
+	u32 reg;
+
+	reg = RTL_R32(TBICSR);
+	if ((autoneg == AUTONEG_DISABLE) && (speed == SPEED_1000) &&
+	    (duplex == DUPLEX_FULL)) {
+		RTL_W32(TBICSR, reg & ~(TBINwEnable | TBINwRestart));
+	} else if (autoneg == AUTONEG_ENABLE)
+		RTL_W32(TBICSR, reg | TBINwEnable | TBINwRestart);
+	else {
+		printk(KERN_WARNING PFX
+		       "%s: incorrect speed setting refused in TBI mode\n",
+		       dev->name);
+		ret = -EOPNOTSUPP;
+	}
+
+	return ret;
+}
+
+static int rtl8169_set_speed_xmii(struct net_device *dev,
+				  u8 autoneg, u16 speed, u8 duplex)
+{
+	struct rtl8169_private *tp = netdev_priv(dev);
+	void *ioaddr = tp->mmio_addr;
+	int auto_nego, giga_ctrl;
+
+	auto_nego = mdio_read(ioaddr, PHY_AUTO_NEGO_REG);
+	auto_nego &= ~(PHY_Cap_10_Half | PHY_Cap_10_Full |
+		       PHY_Cap_100_Half | PHY_Cap_100_Full);
+	giga_ctrl = mdio_read(ioaddr, PHY_1000_CTRL_REG);
+	giga_ctrl &= ~(PHY_Cap_1000_Full | PHY_Cap_Null);
+
+	if (autoneg == AUTONEG_ENABLE) {
+		auto_nego |= (PHY_Cap_10_Half | PHY_Cap_10_Full |
+			      PHY_Cap_100_Half | PHY_Cap_100_Full);
+		giga_ctrl |= PHY_Cap_1000_Full;
+	} else {
+		if (speed == SPEED_10)
+			auto_nego |= PHY_Cap_10_Half | PHY_Cap_10_Full;
+		else if (speed == SPEED_100)
+			auto_nego |= PHY_Cap_100_Half | PHY_Cap_100_Full;
+		else if (speed == SPEED_1000)
+			giga_ctrl |= PHY_Cap_1000_Full;
+
+		if (duplex == DUPLEX_HALF)
+			auto_nego &= ~(PHY_Cap_10_Full | PHY_Cap_100_Full);
+	}
+
+	tp->phy_auto_nego_reg = auto_nego;
+	tp->phy_1000_ctrl_reg = giga_ctrl;
+
+	mdio_write(ioaddr, PHY_AUTO_NEGO_REG, auto_nego);
+	mdio_write(ioaddr, PHY_1000_CTRL_REG, giga_ctrl);
+	mdio_write(ioaddr, PHY_CTRL_REG, PHY_Enable_Auto_Nego |
+					 PHY_Restart_Auto_Nego);
+	return 0;
+}
+
+static int rtl8169_set_speed(struct net_device *dev,
+			     u8 autoneg, u16 speed, u8 duplex)
+{
+	struct rtl8169_private *tp = netdev_priv(dev);
+	int ret;
+
+	ret = tp->set_speed(dev, autoneg, speed, duplex);
+
+	if (netif_running(dev) && (tp->phy_1000_ctrl_reg & PHY_Cap_1000_Full))
+		mod_timer(&tp->timer, jiffies + RTL8169_PHY_TIMEOUT);
+
+	return ret;
+}
+
+static int rtl8169_set_settings(struct net_device *dev, struct ethtool_cmd *cmd)
+{
+	struct rtl8169_private *tp = netdev_priv(dev);
+	unsigned long flags;
+	int ret;
+
+	spin_lock_irqsave(&tp->lock, flags);
+	ret = rtl8169_set_speed(dev, cmd->autoneg, cmd->speed, cmd->duplex);
+	spin_unlock_irqrestore(&tp->lock, flags);
+	
+	return ret;
+}
+
+static void rtl8169_gset_tbi(struct net_device *dev, struct ethtool_cmd *cmd)
+{
+	struct rtl8169_private *tp = netdev_priv(dev);
+	void *ioaddr = tp->mmio_addr;
+	u32 status;
+
+	cmd->supported =
+		SUPPORTED_1000baseT_Full | SUPPORTED_Autoneg | SUPPORTED_FIBRE;
+	cmd->port = PORT_FIBRE;
+	cmd->transceiver = XCVR_INTERNAL;
+
+	status = RTL_R32(TBICSR);
+	cmd->advertising = (status & TBINwEnable) ?  ADVERTISED_Autoneg : 0;
+	cmd->autoneg = !!(status & TBINwEnable);
+
+	cmd->speed = SPEED_1000;
+	cmd->duplex = DUPLEX_FULL; /* Always set */
+}
+
+static void rtl8169_gset_xmii(struct net_device *dev, struct ethtool_cmd *cmd)
+{
+	struct rtl8169_private *tp = netdev_priv(dev);
+	void *ioaddr = tp->mmio_addr;
+	u8 status;
+
+	cmd->supported = SUPPORTED_10baseT_Half |
+			 SUPPORTED_10baseT_Full |
+			 SUPPORTED_100baseT_Half |
+			 SUPPORTED_100baseT_Full |
+			 SUPPORTED_1000baseT_Full |
+			 SUPPORTED_Autoneg |
+		         SUPPORTED_TP;
+
+	cmd->autoneg = 1;
+	cmd->advertising = ADVERTISED_TP | ADVERTISED_Autoneg;
+
+	if (tp->phy_auto_nego_reg & PHY_Cap_10_Half)
+		cmd->advertising |= ADVERTISED_10baseT_Half;
+	if (tp->phy_auto_nego_reg & PHY_Cap_10_Full)
+		cmd->advertising |= ADVERTISED_10baseT_Full;
+	if (tp->phy_auto_nego_reg & PHY_Cap_100_Half)
+		cmd->advertising |= ADVERTISED_100baseT_Half;
+	if (tp->phy_auto_nego_reg & PHY_Cap_100_Full)
+		cmd->advertising |= ADVERTISED_100baseT_Full;
+	if (tp->phy_1000_ctrl_reg & PHY_Cap_1000_Full)
+		cmd->advertising |= ADVERTISED_1000baseT_Full;
+
+	status = RTL_R8(PHYstatus);
+
+	if (status & _1000bpsF)
+		cmd->speed = SPEED_1000;
+	else if (status & _100bps)
+		cmd->speed = SPEED_100;
+	else if (status & _10bps)
+		cmd->speed = SPEED_10;
+
+	cmd->duplex = ((status & _1000bpsF) || (status & FullDup)) ?
+		      DUPLEX_FULL : DUPLEX_HALF;
+}
+
+static int rtl8169_get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
+{
+	struct rtl8169_private *tp = netdev_priv(dev);
+	unsigned long flags;
+
+	spin_lock_irqsave(&tp->lock, flags);
+
+	tp->get_settings(dev, cmd);
+
+	spin_unlock_irqrestore(&tp->lock, flags);
+	return 0;
+}
+
+
 static struct ethtool_ops rtl8169_ethtool_ops = {
 	.get_drvinfo		= rtl8169_get_drvinfo,
+	.get_link		= ethtool_op_get_link,
+	.get_settings		= rtl8169_get_settings,
+	.set_settings		= rtl8169_set_settings,
 };
 
 static void rtl8169_write_gmii_reg_bit(void *ioaddr, int reg, int bitnum,
@@ -500,7 +778,7 @@
 
 static void rtl8169_hw_phy_config(struct net_device *dev)
 {
-	struct rtl8169_private *tp = dev->priv;
+	struct rtl8169_private *tp = netdev_priv(dev);
 	void *ioaddr = tp->mmio_addr;
 	struct {
 		u16 regs[5]; /* Beware of bit-sign propagation */
@@ -566,61 +844,47 @@
 	mdio_write(ioaddr, 31, 0x0000); //w 31 2 0 0
 }
 
-static void rtl8169_hw_phy_reset(struct net_device *dev)
-{
-	struct rtl8169_private *tp = dev->priv;
-	void *ioaddr = tp->mmio_addr;
-	int i, val;
-
-	printk(KERN_WARNING PFX "%s: Reset RTL8169s PHY\n", dev->name);
-
-	val = (mdio_read(ioaddr, 0) | 0x8000) & 0xffff;
-	mdio_write(ioaddr, 0, val);
-
-	for (i = 50; i >= 0; i--) {
-		if (!(mdio_read(ioaddr, 0) & 0x8000))
-			break;
-		udelay(100); /* Gross */
-	}
-
-	if (i < 0) {
-		printk(KERN_WARNING PFX "%s: no PHY Reset ack. Giving up.\n",
-		       dev->name);
-	}
-}
-
 static void rtl8169_phy_timer(unsigned long __opaque)
 {
 	struct net_device *dev = (struct net_device *)__opaque;
-	struct rtl8169_private *tp = dev->priv;
+	struct rtl8169_private *tp = netdev_priv(dev);
 	struct timer_list *timer = &tp->timer;
 	void *ioaddr = tp->mmio_addr;
+	unsigned long timeout = RTL8169_PHY_TIMEOUT;
 
 	assert(tp->mac_version > RTL_GIGA_MAC_VER_B);
 	assert(tp->phy_version < RTL_GIGA_PHY_VER_G);
 
-	if (RTL_R8(PHYstatus) & LinkStatus)
-		tp->phy_link_down_cnt = 0;
-	else {
-		tp->phy_link_down_cnt++;
-		if (tp->phy_link_down_cnt >= 12) {
-			int reg;
-
-			// If link on 1000, perform phy reset.
-			reg = mdio_read(ioaddr, PHY_1000_CTRL_REG);
-			if (reg & PHY_Cap_1000_Full) 
-				rtl8169_hw_phy_reset(dev);
+	if (!(tp->phy_1000_ctrl_reg & PHY_Cap_1000_Full))
+		return;
 
-			tp->phy_link_down_cnt = 0;
-		}
+	spin_lock_irq(&tp->lock);
+
+	if (tp->phy_reset_pending(ioaddr)) {
+		/* 
+		 * A busy loop could burn quite a few cycles on nowadays CPU.
+		 * Let's delay the execution of the timer for a few ticks.
+		 */
+		timeout = HZ/10;
+		goto out_mod_timer;
 	}
 
-	mod_timer(timer, jiffies + RTL8169_PHY_TIMEOUT);
+	if (tp->link_ok(ioaddr))
+		goto out_unlock;
+
+	printk(KERN_WARNING PFX "%s: PHY reset until link up\n", dev->name);
+
+	tp->phy_reset_enable(ioaddr);
+
+out_mod_timer:
+	mod_timer(timer, jiffies + timeout);
+out_unlock:
+	spin_unlock_irq(&tp->lock);
 }
 
 static inline void rtl8169_delete_timer(struct net_device *dev)
 {
-	struct rtl8169_private *tp = dev->priv;
+	struct rtl8169_private *tp = netdev_priv(dev);
 	struct timer_list *timer = &tp->timer;
 
 	if ((tp->mac_version <= RTL_GIGA_MAC_VER_B) ||
@@ -628,21 +892,17 @@
 		return;
 
 	del_timer_sync(timer);
-
-	tp->phy_link_down_cnt = 0;
 }
 
 static inline void rtl8169_request_timer(struct net_device *dev)
 {
-	struct rtl8169_private *tp = dev->priv;
+	struct rtl8169_private *tp = netdev_priv(dev);
 	struct timer_list *timer = &tp->timer;
 
 	if ((tp->mac_version <= RTL_GIGA_MAC_VER_B) ||
 	    (tp->phy_version >= RTL_GIGA_PHY_VER_G))
 		return;
 
-	tp->phy_link_down_cnt = 0;
-
 	init_timer(timer);
 	timer->expires = jiffies + RTL8169_PHY_TIMEOUT;
 	timer->data = (unsigned long)(dev);
@@ -681,7 +941,7 @@
 	// enable device (incl. PCI PM wakeup and hotplug setup)
 	rc = pci_enable_device(pdev);
 	if (rc) {
-		printk(KERN_ERR PFX "%s: unable to enable device\n", pdev->slot_name);
+		printk(KERN_ERR PFX "%s: enable failure\n", pdev->slot_name);
 		goto err_out;
 	}
 
@@ -693,7 +953,8 @@
 		pci_read_config_word(pdev, pm_cap + PCI_PM_CTRL, &pwr_command);
 		acpi_idle_state = pwr_command & PCI_PM_CTRL_STATE_MASK;
 	} else {
-		printk(KERN_ERR PFX "Cannot find PowerManagement capability, aborting.\n");
+		printk(KERN_ERR PFX
+		       "Cannot find PowerManagement capability, aborting.\n");
 		goto err_out_free_res;
 	}
 
@@ -718,14 +979,15 @@
 
 	rc = pci_request_regions(pdev, MODULENAME);
 	if (rc) {
-		printk(KERN_ERR PFX "%s: Could not request regions.\n", pdev->slot_name);
+		printk(KERN_ERR PFX "%s: could not request regions.\n",
+		       pdev->slot_name);
 		goto err_out_disable;
 	}
 
 	tp->cp_cmd = PCIMulRW | RxChkSum;
 
-	if ((sizeof(dma_addr_t) > 32) &&
-	    !pci_set_dma_mask(pdev, DMA_64BIT_MASK))
+	if ((sizeof(dma_addr_t) > 4) &&
+	    !pci_set_dma_mask(pdev, DMA_64BIT_MASK) && use_dac)
 		tp->cp_cmd |= PCIDAC;
 	else {
 		rc = pci_set_dma_mask(pdev, DMA_32BIT_MASK);
@@ -800,8 +1062,9 @@
 	void *ioaddr = NULL;
 	static int board_idx = -1;
 	static int printed_version = 0;
+	u8 autoneg, duplex;
+	u16 speed;
 	int i, rc;
-	int option = -1, Cap10_100 = 0, Cap1000 = 0;
 
 	assert(pdev != NULL);
 	assert(ent != NULL);
@@ -822,6 +1085,22 @@
 	assert(dev != NULL);
 	assert(tp != NULL);
 
+	if (RTL_R8(PHYstatus) & TBI_Enable) {
+		tp->set_speed = rtl8169_set_speed_tbi;
+		tp->get_settings = rtl8169_gset_tbi;
+		tp->phy_reset_enable = rtl8169_tbi_reset_enable;
+		tp->phy_reset_pending = rtl8169_tbi_reset_pending;
+		tp->link_ok = rtl8169_tbi_link_ok;
+
+		tp->phy_1000_ctrl_reg = PHY_Cap_1000_Full; /* Implied by TBI */
+	} else {
+		tp->set_speed = rtl8169_set_speed_xmii;
+		tp->get_settings = rtl8169_gset_xmii;
+		tp->phy_reset_enable = rtl8169_xmii_reset_enable;
+		tp->phy_reset_pending = rtl8169_xmii_reset_pending;
+		tp->link_ok = rtl8169_xmii_link_ok;
+	}
+
 	// Get MAC address.  FIXME: read EEPROM
 	for (i = 0; i < MAC_ADDR_LEN; i++)
 		dev->dev_addr[i] = RTL_R8(MAC0 + i);
@@ -836,9 +1115,12 @@
 	dev->watchdog_timeo = RTL8169_TX_TIMEOUT;
 	dev->irq = pdev->irq;
 	dev->base_addr = (unsigned long) ioaddr;
-//      dev->do_ioctl           = mii_ioctl;
-
-	tp = dev->priv;		// private data //
+#ifdef CONFIG_R8169_NAPI
+	dev->poll = rtl8169_poll;
+	dev->weight = R8169_NAPI_WEIGHT;
+	printk(KERN_INFO PFX "NAPI enabled\n");
+#endif
+	tp->intr_mask = 0xffff;
 	tp->pci_dev = pdev;
 	tp->mmio_addr = ioaddr;
 
@@ -885,95 +1167,12 @@
 		mdio_write(ioaddr, 0x0b, 0x0000); //w 0x0b 15 0 0
 	}
 
-	// if TBI is not endbled
-	if (!(RTL_R8(PHYstatus) & TBI_Enable)) {
-		int val = mdio_read(ioaddr, PHY_AUTO_NEGO_REG);
-
-		option = (board_idx >= MAX_UNITS) ? 0 : media[board_idx];
-		// Force RTL8169 in 10/100/1000 Full/Half mode.
-		if (option > 0) {
-			printk(KERN_INFO "%s: Force-mode Enabled.\n",
-			       dev->name);
-			Cap10_100 = 0, Cap1000 = 0;
-			switch (option) {
-			case _10_Half:
-				Cap10_100 = PHY_Cap_10_Half_Or_Less;
-				Cap1000 = PHY_Cap_Null;
-				break;
-			case _10_Full:
-				Cap10_100 = PHY_Cap_10_Full_Or_Less;
-				Cap1000 = PHY_Cap_Null;
-				break;
-			case _100_Half:
-				Cap10_100 = PHY_Cap_100_Half_Or_Less;
-				Cap1000 = PHY_Cap_Null;
-				break;
-			case _100_Full:
-				Cap10_100 = PHY_Cap_100_Full_Or_Less;
-				Cap1000 = PHY_Cap_Null;
-				break;
-			case _1000_Full:
-				Cap10_100 = PHY_Cap_100_Full_Or_Less;
-				Cap1000 = PHY_Cap_1000_Full;
-				break;
-			default:
-				break;
-			}
-			mdio_write(ioaddr, PHY_AUTO_NEGO_REG, Cap10_100 | (val & 0x1F));	//leave PHY_AUTO_NEGO_REG bit4:0 unchanged
-			mdio_write(ioaddr, PHY_1000_CTRL_REG, Cap1000);
-		} else {
-			printk(KERN_INFO "%s: Auto-negotiation Enabled.\n",
-			       dev->name);
-
-			// enable 10/100 Full/Half Mode, leave PHY_AUTO_NEGO_REG bit4:0 unchanged
-			mdio_write(ioaddr, PHY_AUTO_NEGO_REG,
-				   PHY_Cap_100_Full_Or_Less | (val & 0x1f));
-
-			// enable 1000 Full Mode
-			mdio_write(ioaddr, PHY_1000_CTRL_REG,
-				   PHY_Cap_1000_Full);
+	rtl8169_link_option(board_idx, &autoneg, &speed, &duplex);
 
-		}
-
-		// Enable auto-negotiation and restart auto-nigotiation
-		mdio_write(ioaddr, PHY_CTRL_REG,
-			   PHY_Enable_Auto_Nego | PHY_Restart_Auto_Nego);
-		udelay(100);
-
-		// wait for auto-negotiation process
-		for (i = 10000; i > 0; i--) {
-			//check if auto-negotiation complete
-			if (mdio_read(ioaddr, PHY_STAT_REG) &
-			    PHY_Auto_Neco_Comp) {
-				udelay(100);
-				option = RTL_R8(PHYstatus);
-				if (option & _1000bpsF) {
-					printk(KERN_INFO
-					       "%s: 1000Mbps Full-duplex operation.\n",
-					       dev->name);
-				} else {
-					printk(KERN_INFO
-					       "%s: %sMbps %s-duplex operation.\n",
-					       dev->name,
-					       (option & _100bps) ? "100" :
-					       "10",
-					       (option & FullDup) ? "Full" :
-					       "Half");
-				}
-				break;
-			} else {
-				udelay(100);
-			}
-		}		// end for-loop to wait for auto-negotiation process
-
-	} else {
-		udelay(100);
-		printk(KERN_INFO
-		       "%s: 1000Mbps Full-duplex operation, TBI Link %s!\n",
-		       dev->name,
-		       (RTL_R32(TBICSR) & TBILinkOK) ? "OK" : "Failed");
-
-	}
+	rtl8169_set_speed(dev, autoneg, speed, duplex);
+	
+	if (RTL_R8(PHYstatus) & TBI_Enable)
+		printk(KERN_INFO PFX "%s: TBI auto-negotiating\n", dev->name);
 
 	return 0;
 }
@@ -982,7 +1181,7 @@
 rtl8169_remove_one(struct pci_dev *pdev)
 {
 	struct net_device *dev = pci_get_drvdata(pdev);
-	struct rtl8169_private *tp = dev->priv;
+	struct rtl8169_private *tp = netdev_priv(dev);
 
 	assert(dev != NULL);
 	assert(tp != NULL);
@@ -1001,7 +1200,7 @@
 static int rtl8169_suspend(struct pci_dev *pdev, u32 state)
 {
 	struct net_device *dev = pci_get_drvdata(pdev);
-	struct rtl8169_private *tp = dev->priv;
+	struct rtl8169_private *tp = netdev_priv(dev);
 	void *ioaddr = tp->mmio_addr;
 	unsigned long flags;
 
@@ -1042,7 +1241,7 @@
 static int
 rtl8169_open(struct net_device *dev)
 {
-	struct rtl8169_private *tp = dev->priv;
+	struct rtl8169_private *tp = netdev_priv(dev);
 	struct pci_dev *pdev = tp->pci_dev;
 	int retval;
 
@@ -1074,6 +1273,8 @@
 	rtl8169_hw_start(dev);
 
 	rtl8169_request_timer(dev);
+
+	rtl8169_check_link_status(dev, tp, tp->mmio_addr);
 out:
 	return retval;
 
@@ -1091,7 +1292,7 @@
 static void
 rtl8169_hw_start(struct net_device *dev)
 {
-	struct rtl8169_private *tp = dev->priv;
+	struct rtl8169_private *tp = netdev_priv(dev);
 	void *ioaddr = tp->mmio_addr;
 	u32 i;
 
@@ -1102,8 +1303,7 @@
 	for (i = 1000; i > 0; i--) {
 		if ((RTL_R8(ChipCmd) & CmdReset) == 0)
 			break;
-		else
-			udelay(10);
+		udelay(10);
 	}
 
 	RTL_W8(Cfg9346, Cfg9346_Unlock);
@@ -1114,8 +1314,8 @@
 	RTL_W16(RxMaxSize, RxPacketMaxSize);
 
 	// Set Rx Config register
-	i = rtl8169_rx_config | (RTL_R32(RxConfig) & rtl_chip_info[tp->chipset].
-				 RxConfigMask);
+	i = rtl8169_rx_config |
+		(RTL_R32(RxConfig) & rtl_chip_info[tp->chipset].RxConfigMask);
 	RTL_W32(RxConfig, i);
 
 	/* Set DMA burst size and Interframe Gap Time */
@@ -1126,7 +1326,8 @@
 	RTL_W16(CPlusCmd, tp->cp_cmd);
 
 	if (tp->mac_version == RTL_GIGA_MAC_VER_D) {
-		dprintk(KERN_INFO PFX "Set MAC Reg C+CR Offset 0xE0: bit-3 and bit-14 MUST be 1\n");
+		dprintk(KERN_INFO PFX "Set MAC Reg C+CR Offset 0xE0. "
+			"Bit-3 and bit-14 MUST be 1\n");
 		tp->cp_cmd |= (1 << 14) | PCIMulRW;
 		RTL_W16(CPlusCmd, tp->cp_cmd);
 	}
@@ -1151,7 +1352,6 @@
 	RTL_W16(IntrMask, rtl8169_intr_mask);
 
 	netif_start_queue(dev);
-
 }
 
 static inline void rtl8169_make_unusable_by_asic(struct RxDesc *desc)
@@ -1248,7 +1448,7 @@
 
 static int rtl8169_init_ring(struct net_device *dev)
 {
-	struct rtl8169_private *tp = dev->priv;
+	struct rtl8169_private *tp = netdev_priv(dev);
 
 	tp->cur_rx = tp->dirty_rx = 0;
 	tp->cur_tx = tp->dirty_tx = 0;
@@ -1302,10 +1502,11 @@
 static void
 rtl8169_tx_timeout(struct net_device *dev)
 {
-	struct rtl8169_private *tp = dev->priv;
+	struct rtl8169_private *tp = netdev_priv(dev);
 	void *ioaddr = tp->mmio_addr;
 	u8 tmp8;
 
+	printk(KERN_INFO "%s: TX Timeout\n", dev->name);
 	/* disable Tx, if not already */
 	tmp8 = RTL_R8(ChipCmd);
 	if (tmp8 & CmdTxEnb)
@@ -1328,9 +1529,9 @@
 static int
 rtl8169_start_xmit(struct sk_buff *skb, struct net_device *dev)
 {
-	struct rtl8169_private *tp = dev->priv;
+	struct rtl8169_private *tp = netdev_priv(dev);
 	void *ioaddr = tp->mmio_addr;
-	int entry = tp->cur_tx % NUM_TX_DESC;
+	unsigned int entry = tp->cur_tx % NUM_TX_DESC;
 	u32 len = skb->len;
 
 	if (unlikely(skb->len < ETH_ZLEN)) {
@@ -1340,10 +1541,9 @@
 		len = ETH_ZLEN;
 	}
 	
-	spin_lock_irq(&tp->lock);
-
 	if (!(le32_to_cpu(tp->TxDescArray[entry].status) & OWNbit)) {
 		dma_addr_t mapping;
+		u32 status;
 
 		mapping = pci_map_single(tp->pci_dev, skb->data, len,
 					 PCI_DMA_TODEVICE);
@@ -1351,24 +1551,30 @@
 		tp->Tx_skbuff[entry] = skb;
 		tp->TxDescArray[entry].addr = cpu_to_le64(mapping);
 
-		tp->TxDescArray[entry].status = cpu_to_le32(OWNbit | FSbit |
-			LSbit | len | (EORbit * !((entry + 1) % NUM_TX_DESC)));
+		/* anti gcc 2.95.3 bugware */
+		status = OWNbit | FSbit | LSbit | len |
+			 (EORbit * !((entry + 1) % NUM_TX_DESC));
+		tp->TxDescArray[entry].status = cpu_to_le32(status);
 			
 		RTL_W8(TxPoll, 0x40);	//set polling bit
 
 		dev->trans_start = jiffies;
 
 		tp->cur_tx++;
+		smp_wmb();
 	} else
 		goto err_drop;
 
-
 	if ((tp->cur_tx - NUM_TX_DESC) == tp->dirty_tx) {
+		u32 dirty = tp->dirty_tx;
+	
 		netif_stop_queue(dev);
+		smp_rmb();
+		if (dirty != tp->dirty_tx)
+			netif_wake_queue(dev);
 	}
-out:
-	spin_unlock_irq(&tp->lock);
 
+out:
 	return 0;
 
 err_drop:
@@ -1382,17 +1588,18 @@
 rtl8169_tx_interrupt(struct net_device *dev, struct rtl8169_private *tp,
 		     void *ioaddr)
 {
-	unsigned long dirty_tx, tx_left;
+	unsigned int dirty_tx, tx_left;
 
 	assert(dev != NULL);
 	assert(tp != NULL);
 	assert(ioaddr != NULL);
 
 	dirty_tx = tp->dirty_tx;
+	smp_rmb();
 	tx_left = tp->cur_tx - dirty_tx;
 
 	while (tx_left > 0) {
-		int entry = dirty_tx % NUM_TX_DESC;
+		unsigned int entry = dirty_tx % NUM_TX_DESC;
 		struct sk_buff *skb = tp->Tx_skbuff[entry];
 		u32 status;
 
@@ -1415,6 +1622,7 @@
 
 	if (tp->dirty_tx != dirty_tx) {
 		tp->dirty_tx = dirty_tx;
+		smp_wmb();
 		if (netif_queue_stopped(dev))
 			netif_wake_queue(dev);
 	}
@@ -1442,11 +1650,11 @@
 	return ret;
 }
 
-static void
+static int
 rtl8169_rx_interrupt(struct net_device *dev, struct rtl8169_private *tp,
 		     void *ioaddr)
 {
-	unsigned long cur_rx, rx_left;
+	unsigned int cur_rx, rx_left, count;
 	int delta;
 
 	assert(dev != NULL);
@@ -1455,9 +1663,10 @@
 
 	cur_rx = tp->cur_rx;
 	rx_left = NUM_RX_DESC + tp->dirty_rx - cur_rx;
+	rx_left = rtl8169_rx_quota(rx_left, (u32) dev->quota);
 
 	while (rx_left > 0) {
-		int entry = cur_rx % NUM_RX_DESC;
+		unsigned int entry = cur_rx % NUM_RX_DESC;
 		u32 status;
 
 		rmb();
@@ -1494,7 +1703,7 @@
 
 			skb_put(skb, pkt_size);
 			skb->protocol = eth_type_trans(skb, dev);
-			netif_rx(skb);
+			rtl8169_rx_skb(skb);
 
 			dev->last_rx = jiffies;
 			tp->stats.rx_bytes += pkt_size;
@@ -1505,13 +1714,15 @@
 		rx_left--;
 	}
 
+	count = cur_rx - tp->cur_rx;
 	tp->cur_rx = cur_rx;
 
 	delta = rtl8169_rx_fill(tp, dev, tp->dirty_rx, tp->cur_rx);
-	if (delta > 0)
-		tp->dirty_rx += delta;
-	else if (delta < 0)
+	if (delta < 0) {
 		printk(KERN_INFO "%s: no Rx buffer allocated\n", dev->name);
+		delta = 0;
+	}
+	tp->dirty_rx += delta;
 
 	/*
 	 * FIXME: until there is periodic timer to try and refill the ring,
@@ -1522,6 +1733,8 @@
 	 */
 	if (tp->dirty_rx + NUM_RX_DESC == tp->cur_rx)
 		printk(KERN_EMERG "%s: Rx buffers exhausted\n", dev->name);
+
+	return count;
 }
 
 /* The interrupt handler does all of the Rx thread work and cleans up after the Tx thread. */
@@ -1529,7 +1742,7 @@
 rtl8169_interrupt(int irq, void *dev_instance, struct pt_regs *regs)
 {
 	struct net_device *dev = (struct net_device *) dev_instance;
-	struct rtl8169_private *tp = dev->priv;
+	struct rtl8169_private *tp = netdev_priv(dev);
 	int boguscnt = max_interrupt_work;
 	void *ioaddr = tp->mmio_addr;
 	int status = 0;
@@ -1543,26 +1756,46 @@
 			break;
 
 		handled = 1;
-/*
-		if (status & RxUnderrun)
-			link_changed = RTL_R16 (CSCR) & CSCR_LinkChangeBit;
-*/
+
+		status &= tp->intr_mask;
 		RTL_W16(IntrStatus,
 			(status & RxFIFOOver) ? (status | RxOverflow) : status);
 
 		if (!(status & rtl8169_intr_mask))
 			break;
 
+		if (unlikely(status & SYSErr)) {
+			printk(KERN_ERR PFX "%s: PCI error (status: 0x%04x)."
+			       " Device disabled.\n", dev->name, status);
+			RTL_W8(ChipCmd, 0x00);
+			RTL_W16(IntrMask, 0x0000);
+			RTL_R16(IntrMask);
+			break;
+		}
+
+		if (status & LinkChg)
+			rtl8169_check_link_status(dev, tp, ioaddr);
+
+#ifdef CONFIG_R8169_NAPI
+		RTL_W16(IntrMask, rtl8169_intr_mask & ~rtl8169_napi_event);
+		tp->intr_mask = ~rtl8169_napi_event;
+
+		if (likely(netif_rx_schedule_prep(dev)))
+			__netif_rx_schedule(dev);
+		else {
+			printk(KERN_INFO "%s: interrupt %x taken in poll\n",
+			       dev->name, status);	
+		}
+		break;
+#else
 		// Rx interrupt 
-		if (status & (RxOK | RxUnderrun | RxOverflow | RxFIFOOver)) {
+		if (status & (RxOK | RxOverflow | RxFIFOOver)) {
 			rtl8169_rx_interrupt(dev, tp, ioaddr);
 		}
 		// Tx interrupt
-		if (status & (TxOK | TxErr)) {
-			spin_lock(&tp->lock);
+		if (status & (TxOK | TxErr))
 			rtl8169_tx_interrupt(dev, tp, ioaddr);
-			spin_unlock(&tp->lock);
-		}
+#endif
 
 		boguscnt--;
 	} while (boguscnt > 0);
@@ -1576,10 +1809,40 @@
 	return IRQ_RETVAL(handled);
 }
 
+#ifdef CONFIG_R8169_NAPI
+static int rtl8169_poll(struct net_device *dev, int *budget)
+{
+	unsigned int work_done, work_to_do = min(*budget, dev->quota);
+	struct rtl8169_private *tp = netdev_priv(dev);
+	void *ioaddr = tp->mmio_addr;
+
+	work_done = rtl8169_rx_interrupt(dev, tp, ioaddr);
+	rtl8169_tx_interrupt(dev, tp, ioaddr);
+
+	*budget -= work_done;
+	dev->quota -= work_done;
+
+	if ((work_done < work_to_do) || !netif_running(dev)) {
+		netif_rx_complete(dev);
+		tp->intr_mask = 0xffff;
+		/*
+		 * 20040426: the barrier is not strictly required but the
+		 * behavior of the irq handler could be less predictable
+		 * without it. Btw, the lack of flush for the posted pci
+		 * write is safe - FR
+		 */
+		smp_wmb();
+		RTL_W16(IntrMask, rtl8169_intr_mask);
+	}
+
+	return (work_done >= work_to_do);
+}
+#endif
+
 static int
 rtl8169_close(struct net_device *dev)
 {
-	struct rtl8169_private *tp = dev->priv;
+	struct rtl8169_private *tp = netdev_priv(dev);
 	struct pci_dev *pdev = tp->pci_dev;
 	void *ioaddr = tp->mmio_addr;
 
@@ -1621,7 +1884,7 @@
 static void
 rtl8169_set_rx_mode(struct net_device *dev)
 {
-	struct rtl8169_private *tp = dev->priv;
+	struct rtl8169_private *tp = netdev_priv(dev);
 	void *ioaddr = tp->mmio_addr;
 	unsigned long flags;
 	u32 mc_filter[2];	/* Multicast hash filter */
@@ -1655,10 +1918,8 @@
 
 	spin_lock_irqsave(&tp->lock, flags);
 
-	tmp =
-	    rtl8169_rx_config | rx_mode | (RTL_R32(RxConfig) &
-					   rtl_chip_info[tp->chipset].
-					   RxConfigMask);
+	tmp = rtl8169_rx_config | rx_mode |
+	      (RTL_R32(RxConfig) & rtl_chip_info[tp->chipset].RxConfigMask);
 
 	RTL_W32(RxConfig, tmp);
 	RTL_W32(MAR0 + 0, mc_filter[0]);
@@ -1675,7 +1936,7 @@
  */
 static struct net_device_stats *rtl8169_get_stats(struct net_device *dev)
 {
-	struct rtl8169_private *tp = dev->priv;
+	struct rtl8169_private *tp = netdev_priv(dev);
 	void *ioaddr = tp->mmio_addr;
 	unsigned long flags;
 
diff -Nru a/drivers/net/rrunner.c b/drivers/net/rrunner.c
--- a/drivers/net/rrunner.c	2004-10-18 14:56:20 -07:00
+++ b/drivers/net/rrunner.c	2004-10-18 14:56:20 -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/s2io.c b/drivers/net/s2io.c
--- a/drivers/net/s2io.c	2004-10-18 14:56:33 -07:00
+++ b/drivers/net/s2io.c	2004-10-18 14:56:33 -07:00
@@ -235,10 +235,10 @@
 MODULE_DEVICE_TABLE(pci, s2io_tbl);
 
 static struct pci_driver s2io_driver = {
-      name:"S2IO",
-      id_table:s2io_tbl,
-      probe:s2io_init_nic,
-      remove:__devexit_p(s2io_rem_nic),
+      .name = "S2IO",
+      .id_table = s2io_tbl,
+      .probe = s2io_init_nic,
+      .remove = __devexit_p(s2io_rem_nic),
 };
 
 /*  
diff -Nru a/drivers/net/sis900.c b/drivers/net/sis900.c
--- a/drivers/net/sis900.c	2004-10-18 14:56:29 -07:00
+++ b/drivers/net/sis900.c	2004-10-18 14:56:29 -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/h/skdrv2nd.h b/drivers/net/sk98lin/h/skdrv2nd.h
--- a/drivers/net/sk98lin/h/skdrv2nd.h	2004-10-18 14:57:04 -07:00
+++ b/drivers/net/sk98lin/h/skdrv2nd.h	2004-10-18 14:57:04 -07:00
@@ -53,60 +53,6 @@
 #include "h/skrlmt.h"
 #include "h/skgedrv.h"
 
-#define SK_PCI_ISCOMPLIANT(result, pdev) {     \
-    result = SK_FALSE; /* default */     \
-    /* 3Com (0x10b7) */     \
-    if (pdev->vendor == 0x10b7) {     \
-        /* Gigabit Ethernet Adapter (0x1700) */     \
-        if ((pdev->device == 0x1700) || \
-            (pdev->device == 0x80eb)) { \
-            result = SK_TRUE;     \
-        }     \
-    /* SysKonnect (0x1148) */     \
-    } else if (pdev->vendor == 0x1148) {     \
-        /* SK-98xx Gigabit Ethernet Server Adapter (0x4300) */     \
-        /* SK-98xx V2.0 Gigabit Ethernet Adapter (0x4320) */     \
-        if ((pdev->device == 0x4300) || \
-            (pdev->device == 0x4320)) { \
-            result = SK_TRUE;     \
-        }     \
-    /* D-Link (0x1186) */     \
-    } else if (pdev->vendor == 0x1186) {     \
-        /* Gigabit Ethernet Adapter (0x4c00) */     \
-        if ((pdev->device == 0x4c00)) { \
-            result = SK_TRUE;     \
-        }     \
-    /* Marvell (0x11ab) */     \
-    } else if (pdev->vendor == 0x11ab) {     \
-        /* Gigabit Ethernet Adapter (0x4320) */     \
-        /* Gigabit Ethernet Adapter (0x4360) */     \
-        /* Gigabit Ethernet Adapter (0x4361) */     \
-        /* Belkin (0x5005) */     \
-        if ((pdev->device == 0x4320) || \
-            (pdev->device == 0x4360) || \
-            (pdev->device == 0x4361) || \
-            (pdev->device == 0x5005)) { \
-            result = SK_TRUE;     \
-        }     \
-    /* CNet (0x1371) */     \
-    } else if (pdev->vendor == 0x1371) {     \
-        /* GigaCard Network Adapter (0x434e) */     \
-        if ((pdev->device == 0x434e)) { \
-            result = SK_TRUE;     \
-        }     \
-    /* Linksys (0x1737) */     \
-    } else if (pdev->vendor == 0x1737) {     \
-        /* Gigabit Network Adapter (0x1032) */     \
-        /* Gigabit Network Adapter (0x1064) */     \
-        if ((pdev->device == 0x1032) || \
-            (pdev->device == 0x1064)) { \
-            result = SK_TRUE;     \
-        }     \
-    } else {     \
-        result = SK_FALSE;     \
-    }     \
-}
-
 
 extern SK_MBUF		*SkDrvAllocRlmtMbuf(SK_AC*, SK_IOC, unsigned);
 extern void		SkDrvFreeRlmtMbuf(SK_AC*, SK_IOC, SK_MBUF*);
diff -Nru a/drivers/net/sk98lin/skaddr.c b/drivers/net/sk98lin/skaddr.c
--- a/drivers/net/sk98lin/skaddr.c	2004-10-18 14:56:33 -07:00
+++ b/drivers/net/sk98lin/skaddr.c	2004-10-18 14:56:33 -07:00
@@ -892,7 +892,7 @@
 SK_IOC	IoC,		/* I/O context */
 SK_U32	PortNumber)	/* Port Number */
 {
-	int ReturnCode;
+	int ReturnCode = 0;
 #if (!defined(SK_SLIM) || defined(DEBUG))
 	if (PortNumber >= (SK_U32) pAC->GIni.GIMacsFound) {
 		return (SK_ADDR_ILLEGAL_PORT);
@@ -1424,7 +1424,7 @@
 SK_U32	PortNumber,		/* port whose promiscuous mode changes */
 int		NewPromMode)	/* new promiscuous mode */
 {
-	int ReturnCode;
+	int ReturnCode = 0;
 #if (!defined(SK_SLIM) || defined(DEBUG))
 	if (PortNumber >= (SK_U32) pAC->GIni.GIMacsFound) {
 		return (SK_ADDR_ILLEGAL_PORT);
diff -Nru a/drivers/net/sk98lin/skge.c b/drivers/net/sk98lin/skge.c
--- a/drivers/net/sk98lin/skge.c	2004-10-18 14:56:11 -07:00
+++ b/drivers/net/sk98lin/skge.c	2004-10-18 14:56:11 -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"
@@ -239,7 +236,7 @@
 
 #ifdef CONFIG_PROC_FS
 static const char 	SK_Root_Dir_entry[] = "sk98lin";
-static struct		proc_dir_entry *pSkRootDir = NULL;
+static struct		proc_dir_entry *pSkRootDir;
 extern struct	file_operations sk_proc_fops;
 #endif
 
@@ -255,303 +252,13 @@
 #endif
 
 /* global variables *********************************************************/
-static const char *BootString = BOOT_STRING;
 struct SK_NET_DEVICE *SkGeRootDev = NULL;
-static int probed __initdata = 0;
 static SK_BOOL DoPrintInterfaceChange = SK_TRUE;
 
 /* local variables **********************************************************/
 static uintptr_t TxQueueAddr[SK_MAX_MACS][2] = {{0x680, 0x600},{0x780, 0x700}};
 static uintptr_t RxQueueAddr[SK_MAX_MACS] = {0x400, 0x480};
 
-
-#ifdef CONFIG_PROC_FS
-static struct proc_dir_entry	*pSkRootDir;
-#endif
-
-
-
-/*****************************************************************************
- *
- * 	skge_probe - find all SK-98xx adapters
- *
- * Description:
- *	This function scans the PCI bus for SK-98xx adapters. Resources for
- *	each adapter are allocated and the adapter is brought into Init 1
- *	state.
- *
- * Returns:
- *	0, if everything is ok
- *	!=0, on error
- */
-static int __init skge_probe (void)
-{
-	int			boards_found = 0;
-	int			vendor_flag = SK_FALSE;
-	SK_AC			*pAC;
-	DEV_NET			*pNet = NULL;
-	struct pci_dev	*pdev = NULL;
-	struct SK_NET_DEVICE *dev = NULL;
-	SK_BOOL DeviceFound = SK_FALSE;
-	SK_BOOL BootStringCount = SK_FALSE;
-	int			retval;
-#ifdef CONFIG_PROC_FS
-	struct proc_dir_entry	*pProcFile;
-#endif
-
-	if (probed)
-		return -ENODEV;
-	probed++;
-
-
-	while((pdev = pci_find_class(PCI_CLASS_NETWORK_ETHERNET << 8, pdev))) {
-
-                if (pci_enable_device(pdev)) {
-                        continue;
-                }
-		dev = NULL;
-		pNet = NULL;
-
-		/* Don't handle Yukon2 cards at the moment */
-		/* 12-feb-2004 ---- mlindner@syskonnect.de */
-		if (pdev->vendor == 0x11ab) {
-			if ( (pdev->device == 0x4360) || (pdev->device == 0x4361) )
-				continue;
-		}
-
-		SK_PCI_ISCOMPLIANT(vendor_flag, pdev);
-		if (!vendor_flag)
-			continue;
-
-		/* Configure DMA attributes. */
-		if (pci_set_dma_mask(pdev, (u64) 0xffffffffffffffffULL) &&
-			pci_set_dma_mask(pdev, (u64) 0xffffffff))
-			continue;
-
-
-		if ((dev = alloc_etherdev(sizeof(DEV_NET))) == NULL) {
-			printk(KERN_ERR "Unable to allocate etherdev "
-			       "structure!\n");
-			break;
-		}
-
-		pNet = dev->priv;
-		pNet->pAC = kmalloc(sizeof(SK_AC), GFP_KERNEL);
-		if (pNet->pAC == NULL){
-			free_netdev(dev);
-			printk(KERN_ERR "Unable to allocate adapter "
-			       "structure!\n");
-			break;
-		}
-
-		/* Print message */
-		if (!BootStringCount) {
-			/* set display flag to TRUE so that */
-			/* we only display this string ONCE */
-			BootStringCount = SK_TRUE;
-			printk("%s\n", BootString);
-		}
-
-		memset(pNet->pAC, 0, sizeof(SK_AC));
-		pAC = pNet->pAC;
-		pAC->PciDev = pdev;
-		pAC->PciDevId = pdev->device;
-		pAC->dev[0] = dev;
-		pAC->dev[1] = dev;
-		sprintf(pAC->Name, "SysKonnect SK-98xx");
-		pAC->CheckQueue = SK_FALSE;
-
-		pNet->Mtu = 1500;
-		pNet->Up = 0;
-		dev->irq = pdev->irq;
-		retval = SkGeInitPCI(pAC);
-		if (retval) {
-			printk("SKGE: PCI setup failed: %i\n", retval);
-			free_netdev(dev);
-			continue;
-		}
-
-		SET_MODULE_OWNER(dev);
-		dev->open =		&SkGeOpen;
-		dev->stop =		&SkGeClose;
-		dev->hard_start_xmit =	&SkGeXmit;
-		dev->get_stats =	&SkGeStats;
-		dev->last_stats =	&SkGeStats;
-		dev->set_multicast_list = &SkGeSetRxMode;
-		dev->set_mac_address =	&SkGeSetMacAddr;
-		dev->do_ioctl =		&SkGeIoctl;
-		dev->change_mtu =	&SkGeChangeMtu;
-		dev->flags &= 		~IFF_RUNNING;
-		SET_NETDEV_DEV(dev, &pdev->dev);
-
-#ifdef SK_ZEROCOPY
-#ifdef USE_SK_TX_CHECKSUM
-
-		if (pAC->ChipsetType) {
-			/* Use only if yukon hardware */
-			/* SK and ZEROCOPY - fly baby... */
-			dev->features |= NETIF_F_SG | NETIF_F_IP_CSUM;
-		}
-#endif
-#endif
-
-		pAC->Index = boards_found;
-
-		if (SkGeBoardInit(dev, pAC)) {
-			free_netdev(dev);
-			continue;
-		}
-
-		/* Register net device */
-		if (register_netdev(dev)) {
-			printk(KERN_ERR "SKGE: Could not register device.\n");
-			FreeResources(dev);
-			free_netdev(dev);
-			continue;
-		}
-
-		/* Print adapter specific string from vpd */
-		ProductStr(pAC);
-		printk("%s: %s\n", dev->name, pAC->DeviceStr);
-
-		/* Print configuration settings */
-		printk("      PrefPort:%c  RlmtMode:%s\n",
-			'A' + pAC->Rlmt.Net[0].Port[pAC->Rlmt.Net[0].PrefPort]->PortNumber,
-			(pAC->RlmtMode==0)  ? "Check Link State" :
-			((pAC->RlmtMode==1) ? "Check Link State" :
-			((pAC->RlmtMode==3) ? "Check Local Port" :
-			((pAC->RlmtMode==7) ? "Check Segmentation" :
-			((pAC->RlmtMode==17) ? "Dual Check Link State" :"Error")))));
-
-		SkGeYellowLED(pAC, pAC->IoBase, 1);
-
-
-		memcpy((caddr_t) &dev->dev_addr,
-			(caddr_t) &pAC->Addr.Net[0].CurrentMacAddress, 6);
-
-		/* First adapter... Create proc and print message */
-#ifdef CONFIG_PROC_FS
-		if (!DeviceFound) {
-			DeviceFound = SK_TRUE;
-			SK_MEMCPY(&SK_Root_Dir_entry, BootString,
-				sizeof(SK_Root_Dir_entry) - 1);
-
-			/*Create proc (directory)*/
-			if(!pSkRootDir) {
-				pSkRootDir = proc_mkdir(SK_Root_Dir_entry, proc_net);
-				if (!pSkRootDir) {
-					printk(KERN_WARNING "%s: Unable to create /proc/net/%s",
-						dev->name, SK_Root_Dir_entry);
-				} else {
-					pSkRootDir->owner = THIS_MODULE;
-				}
-			}
-		}
-
-		/* Create proc file */
-		if (pSkRootDir && 
-			(pProcFile = create_proc_entry(dev->name, S_IRUGO,
-				pSkRootDir))) {
-			pProcFile->proc_fops = &sk_proc_fops;
-			pProcFile->data      = dev;
-		}
-
-#endif
-
-		pNet->PortNr = 0;
-		pNet->NetNr  = 0;
-
-		boards_found++;
-
-		/* More then one port found */
-		if ((pAC->GIni.GIMacsFound == 2 ) && (pAC->RlmtNets == 2)) {
-			if ((dev = alloc_etherdev(sizeof(DEV_NET))) == 0) {
-				printk(KERN_ERR "Unable to allocate etherdev "
-					"structure!\n");
-				break;
-			}
-
-			pAC->dev[1]   = dev;
-			pNet          = dev->priv;
-			pNet->PortNr  = 1;
-			pNet->NetNr   = 1;
-			pNet->pAC     = pAC;
-			pNet->Mtu     = 1500;
-			pNet->Up      = 0;
-
-			dev->open               = &SkGeOpen;
-			dev->stop               = &SkGeClose;
-			dev->hard_start_xmit    = &SkGeXmit;
-			dev->get_stats          = &SkGeStats;
-			dev->last_stats         = &SkGeStats;
-			dev->set_multicast_list = &SkGeSetRxMode;
-			dev->set_mac_address    = &SkGeSetMacAddr;
-			dev->do_ioctl           = &SkGeIoctl;
-			dev->change_mtu         = &SkGeChangeMtu;
-			dev->flags             &= ~IFF_RUNNING;
-
-#ifdef SK_ZEROCOPY
-#ifdef USE_SK_TX_CHECKSUM
-			if (pAC->ChipsetType) {
-				/* SG and ZEROCOPY - fly baby... */
-				dev->features |= NETIF_F_SG | NETIF_F_IP_CSUM;
-			}
-#endif
-#endif
-
-			if (register_netdev(dev)) {
-				printk(KERN_ERR "SKGE: Could not register device.\n");
-				free_netdev(dev);
-				pAC->dev[1] = pAC->dev[0];
-			} else {
-#ifdef CONFIG_PROC_FS
-				if (pSkRootDir 
-				    && (pProcFile = create_proc_entry(dev->name, 
-								S_IRUGO, pSkRootDir))) {
-					pProcFile->proc_fops = &sk_proc_fops;
-					pProcFile->data      = dev;
-				}
-#endif
-
-			memcpy((caddr_t) &dev->dev_addr,
-			(caddr_t) &pAC->Addr.Net[1].CurrentMacAddress, 6);
-	
-			printk("%s: %s\n", dev->name, pAC->DeviceStr);
-			printk("      PrefPort:B  RlmtMode:Dual Check Link State\n");
-			}
-		}
-
-		/* Save the hardware revision */
-		pAC->HWRevision = (((pAC->GIni.GIPciHwRev >> 4) & 0x0F)*10) +
-			(pAC->GIni.GIPciHwRev & 0x0F);
-
-		/* Set driver globals */
-		pAC->Pnmi.pDriverFileName    = DRIVER_FILE_NAME;
-		pAC->Pnmi.pDriverReleaseDate = DRIVER_REL_DATE;
-
-		SK_MEMSET(&(pAC->PnmiBackup), 0, sizeof(SK_PNMI_STRUCT_DATA));
-		SK_MEMCPY(&(pAC->PnmiBackup), &(pAC->PnmiStruct), 
-				sizeof(SK_PNMI_STRUCT_DATA));
-
-		/*
-		 * This is bollocks, but we need to tell the net-init
-		 * code that it shall go for the next device.
-		 */
-#ifndef MODULE
-		dev->base_addr = 0;
-#endif
-	}
-
-	/*
-	 * If we're at this point we're going through skge_probe() for
-	 * the first time.  Return success (0) if we've initialized 1
-	 * or more boards. Otherwise, return failure (-ENODEV).
-	 */
-
-	return boards_found;
-} /* skge_probe */
-
-
 /*****************************************************************************
  *
  * 	SkGeInitPCI - Init the PCI resources
@@ -666,9 +373,6 @@
 MODULE_PARM(ConType,	"1-" __MODULE_STRING(SK_MAX_CARD_PARAM) "s");
 MODULE_PARM(PrefPort,   "1-" __MODULE_STRING(SK_MAX_CARD_PARAM) "s");
 MODULE_PARM(RlmtMode,   "1-" __MODULE_STRING(SK_MAX_CARD_PARAM) "s");
-/* not used, just there because every driver should have them: */
-MODULE_PARM(options,    "1-" __MODULE_STRING(SK_MAX_CARD_PARAM) "i");
-MODULE_PARM(debug,      "i");
 /* used for interrupt moderation */
 MODULE_PARM(IntsPerSec,     "1-" __MODULE_STRING(SK_MAX_CARD_PARAM) "i");
 MODULE_PARM(Moderation,     "1-" __MODULE_STRING(SK_MAX_CARD_PARAM) "s");
@@ -755,123 +459,12 @@
 static char *RlmtMode[SK_MAX_CARD_PARAM] = {"", };
 #endif
 
-static int debug = 0; /* not used */
-static int options[SK_MAX_CARD_PARAM] = {0, }; /* not used */
-
 static int   IntsPerSec[SK_MAX_CARD_PARAM];
 static char *Moderation[SK_MAX_CARD_PARAM];
 static char *ModerationMask[SK_MAX_CARD_PARAM];
 static char *AutoSizing[SK_MAX_CARD_PARAM];
 static char *Stats[SK_MAX_CARD_PARAM];
 
-
-/*****************************************************************************
- *
- * 	skge_init_module - module initialization function
- *
- * Description:
- *	Very simple, only call skge_probe and return approriate result.
- *
- * Returns:
- *	0, if everything is ok
- *	!=0, on error
- */
-static int __init skge_init_module(void)
-{
-	int cards;
-	SkGeRootDev = NULL;
-	
-	/* just to avoid warnings ... */
-	debug = 0;
-	options[0] = 0;
-
-	cards = skge_probe();
-	if (cards == 0) {
-		printk("sk98lin: No adapter found.\n");
-	}
-	return cards ? 0 : -ENODEV;
-} /* skge_init_module */
-
-
-/*****************************************************************************
- *
- * 	skge_cleanup_module - module unload function
- *
- * Description:
- *	Disable adapter if it is still running, free resources,
- *	free device struct.
- *
- * Returns: N/A
- */
-static void __exit skge_cleanup_module(void)
-{
-DEV_NET		*pNet;
-SK_AC		*pAC;
-struct SK_NET_DEVICE *next;
-unsigned long Flags;
-SK_EVPARA EvPara;
-
-	while (SkGeRootDev) {
-		pNet = (DEV_NET*) SkGeRootDev->priv;
-		pAC = pNet->pAC;
-		next = pAC->Next;
-
-		netif_stop_queue(SkGeRootDev);
-		SkGeYellowLED(pAC, pAC->IoBase, 0);
-
-		if(pAC->BoardLevel == SK_INIT_RUN) {
-			/* board is still alive */
-			spin_lock_irqsave(&pAC->SlowPathLock, Flags);
-			EvPara.Para32[0] = 0;
-			EvPara.Para32[1] = -1;
-			SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_STOP, EvPara);
-			EvPara.Para32[0] = 1;
-			EvPara.Para32[1] = -1;
-			SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_STOP, EvPara);
-			SkEventDispatcher(pAC, pAC->IoBase);
-			/* disable interrupts */
-			SK_OUT32(pAC->IoBase, B0_IMSK, 0);
-			SkGeDeInit(pAC, pAC->IoBase);
-			spin_unlock_irqrestore(&pAC->SlowPathLock, Flags);
-			pAC->BoardLevel = SK_INIT_DATA;
-			/* We do NOT check here, if IRQ was pending, of course*/
-		}
-
-		if(pAC->BoardLevel == SK_INIT_IO) {
-			/* board is still alive */
-			SkGeDeInit(pAC, pAC->IoBase);
-			pAC->BoardLevel = SK_INIT_DATA;
-		}
-
-		if ((pAC->GIni.GIMacsFound == 2) && pAC->RlmtNets == 2){
-			unregister_netdev(pAC->dev[1]);
-			free_netdev(pAC->dev[1]);
-		}
-
-		FreeResources(SkGeRootDev);
-
-		SkGeRootDev->get_stats = NULL;
-		/*
-		 * otherwise unregister_netdev calls get_stats with
-		 * invalid IO ...  :-(
-		 */
-		unregister_netdev(SkGeRootDev);
-		free_netdev(SkGeRootDev);
-		kfree(pAC);
-		SkGeRootDev = next;
-	}
-
-#ifdef CONFIG_PROC_FS
-	/* clear proc-dir */
-	remove_proc_entry(pSkRootDir->name, proc_net);
-#endif
-
-} /* skge_cleanup_module */
-
-module_init(skge_init_module);
-module_exit(skge_cleanup_module);
-
-
 /*****************************************************************************
  *
  * 	SkGeBoardInit - do level 0 and 1 initialization
@@ -3094,8 +2687,7 @@
 	SkEventDispatcher(pAC, pAC->IoBase);
 
 	for (i=0; i<pAC->GIni.GIMacsFound; i++) {
-		spin_lock_irqsave(
-			&pAC->TxPort[i][TX_PRIO_LOW].TxDesRingLock, Flags);
+		spin_lock(&pAC->TxPort[i][TX_PRIO_LOW].TxDesRingLock);
 		netif_stop_queue(pAC->dev[i]);
 
 	}
@@ -4774,12 +4366,10 @@
 		spin_lock_irqsave(
 			&pAC->TxPort[FromPort][TX_PRIO_LOW].TxDesRingLock,
 			Flags);
-		spin_lock_irqsave(
-			&pAC->TxPort[ToPort][TX_PRIO_LOW].TxDesRingLock, Flags);
+		spin_lock(&pAC->TxPort[ToPort][TX_PRIO_LOW].TxDesRingLock);
 		SkGeStopPort(pAC, IoC, FromPort, SK_STOP_ALL, SK_SOFT_RST);
 		SkGeStopPort(pAC, IoC, ToPort, SK_STOP_ALL, SK_SOFT_RST);
-		spin_unlock_irqrestore(
-			&pAC->TxPort[ToPort][TX_PRIO_LOW].TxDesRingLock, Flags);
+		spin_unlock(&pAC->TxPort[ToPort][TX_PRIO_LOW].TxDesRingLock);
 		spin_unlock_irqrestore(
 			&pAC->TxPort[FromPort][TX_PRIO_LOW].TxDesRingLock,
 			Flags);
@@ -4792,8 +4382,7 @@
 		spin_lock_irqsave(
 			&pAC->TxPort[FromPort][TX_PRIO_LOW].TxDesRingLock,
 			Flags);
-		spin_lock_irqsave(
-			&pAC->TxPort[ToPort][TX_PRIO_LOW].TxDesRingLock, Flags);
+		spin_lock(&pAC->TxPort[ToPort][TX_PRIO_LOW].TxDesRingLock);
 		pAC->ActivePort = ToPort;
 #if 0
 		SetQueueSizes(pAC);
@@ -4808,8 +4397,7 @@
 			pAC,
 			pAC->ActivePort,
 			DualNet)) {
-			spin_unlock_irqrestore(
-				&pAC->TxPort[ToPort][TX_PRIO_LOW].TxDesRingLock, Flags);
+			spin_unlock(&pAC->TxPort[ToPort][TX_PRIO_LOW].TxDesRingLock);
 			spin_unlock_irqrestore(
 				&pAC->TxPort[FromPort][TX_PRIO_LOW].TxDesRingLock,
 				Flags);
@@ -4835,8 +4423,7 @@
 		SkGePollTxD(pAC, IoC, ToPort, SK_TRUE);
 		ClearAndStartRx(pAC, FromPort);
 		ClearAndStartRx(pAC, ToPort);
-		spin_unlock_irqrestore(
-			&pAC->TxPort[ToPort][TX_PRIO_LOW].TxDesRingLock, Flags);
+		spin_unlock(&pAC->TxPort[ToPort][TX_PRIO_LOW].TxDesRingLock);
 		spin_unlock_irqrestore(
 			&pAC->TxPort[FromPort][TX_PRIO_LOW].TxDesRingLock,
 			Flags);
@@ -5311,8 +4898,317 @@
 
 #endif
 
-/*******************************************************************************
- *
- * End of file
- *
- ******************************************************************************/
+static int __devinit skge_probe_one(struct pci_dev *pdev,
+		const struct pci_device_id *ent)
+{
+	SK_AC			*pAC;
+	DEV_NET			*pNet = NULL;
+	struct net_device	*dev = NULL;
+#ifdef CONFIG_PROC_FS
+	struct proc_dir_entry	*pProcFile;
+#endif
+	static int boards_found = 0;
+	int error = -ENODEV;
+
+	if (pci_enable_device(pdev))
+		goto out;
+ 
+	/* Configure DMA attributes. */
+	if (pci_set_dma_mask(pdev, (u64) 0xffffffffffffffffULL) &&
+	    pci_set_dma_mask(pdev, (u64) 0xffffffff))
+		goto out_disable_device;
+
+
+	if ((dev = alloc_etherdev(sizeof(DEV_NET))) == NULL) {
+		printk(KERN_ERR "Unable to allocate etherdev "
+		       "structure!\n");
+		goto out_disable_device;
+	}
+
+	pNet = dev->priv;
+	pNet->pAC = kmalloc(sizeof(SK_AC), GFP_KERNEL);
+	if (!pNet->pAC) {
+		printk(KERN_ERR "Unable to allocate adapter "
+		       "structure!\n");
+		goto out_free_netdev;
+	}
+
+	memset(pNet->pAC, 0, sizeof(SK_AC));
+	pAC = pNet->pAC;
+	pAC->PciDev = pdev;
+	pAC->PciDevId = pdev->device;
+	pAC->dev[0] = dev;
+	pAC->dev[1] = dev;
+	sprintf(pAC->Name, "SysKonnect SK-98xx");
+	pAC->CheckQueue = SK_FALSE;
+
+	pNet->Mtu = 1500;
+	pNet->Up = 0;
+	dev->irq = pdev->irq;
+	error = SkGeInitPCI(pAC);
+	if (error) {
+		printk("SKGE: PCI setup failed: %i\n", error);
+		goto out_free_netdev;
+	}
+
+	SET_MODULE_OWNER(dev);
+	dev->open =		&SkGeOpen;
+	dev->stop =		&SkGeClose;
+	dev->hard_start_xmit =	&SkGeXmit;
+	dev->get_stats =	&SkGeStats;
+	dev->set_multicast_list = &SkGeSetRxMode;
+	dev->set_mac_address =	&SkGeSetMacAddr;
+	dev->do_ioctl =		&SkGeIoctl;
+	dev->change_mtu =	&SkGeChangeMtu;
+	dev->flags &= 		~IFF_RUNNING;
+	SET_NETDEV_DEV(dev, &pdev->dev);
+
+#ifdef SK_ZEROCOPY
+#ifdef USE_SK_TX_CHECKSUM
+	if (pAC->ChipsetType) {
+		/* Use only if yukon hardware */
+		/* SK and ZEROCOPY - fly baby... */
+		dev->features |= NETIF_F_SG | NETIF_F_IP_CSUM;
+	}
+#endif
+#endif
+
+	pAC->Index = boards_found++;
+
+	if (SkGeBoardInit(dev, pAC))
+		goto out_free_netdev;
+
+	/* Register net device */
+	if (register_netdev(dev)) {
+		printk(KERN_ERR "SKGE: Could not register device.\n");
+		goto out_free_resources;
+	}
+
+	/* Print adapter specific string from vpd */
+	ProductStr(pAC);
+	printk("%s: %s\n", dev->name, pAC->DeviceStr);
+
+	/* Print configuration settings */
+	printk("      PrefPort:%c  RlmtMode:%s\n",
+		'A' + pAC->Rlmt.Net[0].Port[pAC->Rlmt.Net[0].PrefPort]->PortNumber,
+		(pAC->RlmtMode==0)  ? "Check Link State" :
+		((pAC->RlmtMode==1) ? "Check Link State" :
+		((pAC->RlmtMode==3) ? "Check Local Port" :
+		((pAC->RlmtMode==7) ? "Check Segmentation" :
+		((pAC->RlmtMode==17) ? "Dual Check Link State" :"Error")))));
+
+	SkGeYellowLED(pAC, pAC->IoBase, 1);
+
+
+	memcpy(&dev->dev_addr, &pAC->Addr.Net[0].CurrentMacAddress, 6);
+
+#ifdef CONFIG_PROC_FS
+	pProcFile = create_proc_entry(dev->name, S_IRUGO, pSkRootDir);
+	if (pProcFile) {
+		pProcFile->proc_fops = &sk_proc_fops;
+		pProcFile->data = dev;
+		pProcFile->owner = THIS_MODULE;
+	}
+#endif
+
+	pNet->PortNr = 0;
+	pNet->NetNr  = 0;
+
+	boards_found++;
+
+	/* More then one port found */
+	if ((pAC->GIni.GIMacsFound == 2 ) && (pAC->RlmtNets == 2)) {
+		if ((dev = alloc_etherdev(sizeof(DEV_NET))) == 0) {
+			printk(KERN_ERR "Unable to allocate etherdev "
+				"structure!\n");
+			goto out;
+		}
+
+		pAC->dev[1]   = dev;
+		pNet          = dev->priv;
+		pNet->PortNr  = 1;
+		pNet->NetNr   = 1;
+		pNet->pAC     = pAC;
+		pNet->Mtu     = 1500;
+		pNet->Up      = 0;
+
+		dev->open               = &SkGeOpen;
+		dev->stop               = &SkGeClose;
+		dev->hard_start_xmit    = &SkGeXmit;
+		dev->get_stats          = &SkGeStats;
+		dev->set_multicast_list = &SkGeSetRxMode;
+		dev->set_mac_address    = &SkGeSetMacAddr;
+		dev->do_ioctl           = &SkGeIoctl;
+		dev->change_mtu         = &SkGeChangeMtu;
+		dev->flags             &= ~IFF_RUNNING;
+
+#ifdef SK_ZEROCOPY
+#ifdef USE_SK_TX_CHECKSUM
+		if (pAC->ChipsetType) {
+			/* SG and ZEROCOPY - fly baby... */
+			dev->features |= NETIF_F_SG | NETIF_F_IP_CSUM;
+		}
+#endif
+#endif
+
+		if (register_netdev(dev)) {
+			printk(KERN_ERR "SKGE: Could not register device.\n");
+			free_netdev(dev);
+			pAC->dev[1] = pAC->dev[0];
+		} else {
+#ifdef CONFIG_PROC_FS
+			pProcFile = create_proc_entry(dev->name, S_IRUGO,
+					pSkRootDir);
+			if (pProcFile) {
+				pProcFile->proc_fops = &sk_proc_fops;
+				pProcFile->data = dev;
+				pProcFile->owner = THIS_MODULE;
+			}
+#endif
+
+			memcpy(&dev->dev_addr,
+					&pAC->Addr.Net[1].CurrentMacAddress, 6);
+	
+			printk("%s: %s\n", dev->name, pAC->DeviceStr);
+			printk("      PrefPort:B  RlmtMode:Dual Check Link State\n");
+		}
+	}
+
+	/* Save the hardware revision */
+	pAC->HWRevision = (((pAC->GIni.GIPciHwRev >> 4) & 0x0F)*10) +
+		(pAC->GIni.GIPciHwRev & 0x0F);
+
+	/* Set driver globals */
+	pAC->Pnmi.pDriverFileName    = DRIVER_FILE_NAME;
+	pAC->Pnmi.pDriverReleaseDate = DRIVER_REL_DATE;
+
+	memset(&pAC->PnmiBackup, 0, sizeof(SK_PNMI_STRUCT_DATA));
+	memcpy(&pAC->PnmiBackup, &pAC->PnmiStruct, sizeof(SK_PNMI_STRUCT_DATA));
+
+	pci_set_drvdata(pdev, dev);
+	return 0;
+
+ out_free_resources:
+	FreeResources(dev);
+ out_free_netdev:
+	free_netdev(dev);
+ out_disable_device:
+	pci_disable_device(pdev);
+ out:
+	return error;
+}
+
+static void __devexit skge_remove_one(struct pci_dev *pdev)
+{
+	struct net_device *dev = pci_get_drvdata(pdev);
+	DEV_NET *pNet = (DEV_NET *) dev->priv;
+	SK_AC *pAC = pNet->pAC;
+	int have_second_mac = 0;
+
+	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) {
+		remove_proc_entry(pAC->dev[1]->name, pSkRootDir);
+		unregister_netdev(pAC->dev[1]);
+	}
+
+	SkGeYellowLED(pAC, pAC->IoBase, 0);
+
+	if (pAC->BoardLevel == SK_INIT_RUN) {
+		SK_EVPARA EvPara;
+		unsigned long Flags;
+
+		/* board is still alive */
+		spin_lock_irqsave(&pAC->SlowPathLock, Flags);
+		EvPara.Para32[0] = 0;
+		EvPara.Para32[1] = -1;
+		SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_STOP, EvPara);
+		EvPara.Para32[0] = 1;
+		EvPara.Para32[1] = -1;
+		SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_STOP, EvPara);
+		SkEventDispatcher(pAC, pAC->IoBase);
+		/* disable interrupts */
+		SK_OUT32(pAC->IoBase, B0_IMSK, 0);
+		SkGeDeInit(pAC, pAC->IoBase);
+		spin_unlock_irqrestore(&pAC->SlowPathLock, Flags);
+		pAC->BoardLevel = SK_INIT_DATA;
+		/* We do NOT check here, if IRQ was pending, of course*/
+	}
+
+	if (pAC->BoardLevel == SK_INIT_IO) {
+		/* board is still alive */
+		SkGeDeInit(pAC, pAC->IoBase);
+		pAC->BoardLevel = SK_INIT_DATA;
+	}
+
+	FreeResources(dev);
+	free_netdev(dev);
+	if (have_second_mac)
+		free_netdev(pAC->dev[1]);
+	kfree(pAC);
+}
+
+static struct pci_device_id skge_pci_tbl[] = {
+	{ PCI_VENDOR_ID_3COM, 0x1700, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
+	{ PCI_VENDOR_ID_3COM, 0x80eb, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
+	{ PCI_VENDOR_ID_SYSKONNECT, 0x4300, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
+	{ PCI_VENDOR_ID_SYSKONNECT, 0x4320, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
+	{ PCI_VENDOR_ID_DLINK, 0x4c00, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
+	{ PCI_VENDOR_ID_MARVELL, 0x4320, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
+#if 0	/* don't handle Yukon2 cards at the moment -- mlindner@syskonnect.de */
+	{ PCI_VENDOR_ID_MARVELL, 0x4360, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
+	{ PCI_VENDOR_ID_MARVELL, 0x4361, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
+#endif
+	{ PCI_VENDOR_ID_MARVELL, 0x5005, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
+	{ PCI_VENDOR_ID_CNET, 0x434e, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
+	{ PCI_VENDOR_ID_LINKSYS, 0x1032, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
+	{ PCI_VENDOR_ID_LINKSYS, 0x1064, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
+	{ 0, }
+};
+
+static struct pci_driver skge_driver = {
+	.name		= "skge",
+	.id_table	= skge_pci_tbl,
+	.probe		= skge_probe_one,
+	.remove		= __devexit_p(skge_remove_one),
+};
+
+static int __init skge_init(void)
+{
+	int error;
+
+#ifdef CONFIG_PROC_FS
+	memcpy(&SK_Root_Dir_entry, BOOT_STRING, sizeof(SK_Root_Dir_entry) - 1);
+
+	pSkRootDir = proc_mkdir(SK_Root_Dir_entry, proc_net);
+	if (!pSkRootDir) {
+		printk(KERN_WARNING "Unable to create /proc/net/%s",
+				SK_Root_Dir_entry);
+		return -ENOMEM;
+	}
+	pSkRootDir->owner = THIS_MODULE;
+#endif
+
+	error = pci_module_init(&skge_driver);
+	if (error) {
+#ifdef CONFIG_PROC_FS
+		remove_proc_entry(pSkRootDir->name, proc_net);
+#endif
+	}
+
+	return error;
+}
+
+static void __exit skge_exit(void)
+{
+	 pci_unregister_driver(&skge_driver);
+#ifdef CONFIG_PROC_FS
+	remove_proc_entry(pSkRootDir->name, proc_net);
+#endif
+}
+
+module_init(skge_init);
+module_exit(skge_exit);
diff -Nru a/drivers/net/skfp/skfddi.c b/drivers/net/skfp/skfddi.c
--- a/drivers/net/skfp/skfddi.c	2004-10-18 14:55:54 -07:00
+++ b/drivers/net/skfp/skfddi.c	2004-10-18 14:55:54 -07:00
@@ -1095,7 +1095,7 @@
 	 */
 
 	if (!(skb->len >= FDDI_K_LLC_ZLEN && skb->len <= FDDI_K_LLC_LEN)) {
-		bp->MacStat.tx_errors++;	/* bump error counter */
+		bp->MacStat.gen.tx_errors++;	/* bump error counter */
 		// dequeue packets from xmt queue and send them
 		netif_start_queue(dev);
 		dev_kfree_skb(skb);
@@ -1546,8 +1546,8 @@
 			 skb->len, PCI_DMA_TODEVICE);
 	txd->txd_os.dma_addr = 0;
 
-	smc->os.MacStat.tx_packets++;	// Count transmitted packets.
-	smc->os.MacStat.tx_bytes+=skb->len;	// Count bytes
+	smc->os.MacStat.gen.tx_packets++;	// Count transmitted packets.
+	smc->os.MacStat.gen.tx_bytes+=skb->len;	// Count bytes
 
 	// free the skb
 	dev_kfree_skb_irq(skb);
@@ -1629,7 +1629,7 @@
 	skb = rxd->rxd_os.skb;
 	if (!skb) {
 		PRINTK(KERN_INFO "No skb in rxd\n");
-		smc->os.MacStat.rx_errors++;
+		smc->os.MacStat.gen.rx_errors++;
 		goto RequeueRxd;
 	}
 	virt = skb->data;
@@ -1682,13 +1682,14 @@
 	}
 
 	// Count statistics.
-	smc->os.MacStat.rx_packets++;	// Count indicated receive packets.
-	smc->os.MacStat.rx_bytes+=len;	// Count bytes
+	smc->os.MacStat.gen.rx_packets++;	// Count indicated receive
+						// packets.
+	smc->os.MacStat.gen.rx_bytes+=len;	// Count bytes.
 
 	// virt points to header again
 	if (virt[1] & 0x01) {	// Check group (multicast) bit.
 
-		smc->os.MacStat.multicast++;
+		smc->os.MacStat.gen.multicast++;
 	}
 
 	// deliver frame to system
@@ -1706,7 +1707,8 @@
       RequeueRxd:
 	PRINTK(KERN_INFO "Rx: re-queue RXD.\n");
 	mac_drv_requeue_rxd(smc, rxd, frag_count);
-	smc->os.MacStat.rx_errors++;	// Count receive packets not indicated.
+	smc->os.MacStat.gen.rx_errors++;	// Count receive packets
+						// not indicated.
 
 }				// mac_drv_rx_complete
 
@@ -2081,7 +2083,7 @@
 		break;
 	case 1:
 		PRINTK(KERN_INFO "Receive fifo overflow.\n");
-		smc->os.MacStat.rx_errors++;
+		smc->os.MacStat.gen.rx_errors++;
 		break;
 	default:
 		PRINTK(KERN_INFO "Unknown status (%d).\n", stat);
diff -Nru a/drivers/net/slip.c b/drivers/net/slip.c
--- a/drivers/net/slip.c	2004-10-18 14:57:05 -07:00
+++ b/drivers/net/slip.c	2004-10-18 14:57:05 -07:00
@@ -672,7 +672,9 @@
  * Handle the 'receiver data ready' interrupt.
  * This function is called by the 'tty_io' module in the kernel when
  * a block of SLIP data has been received, which can now be decapsulated
- * and sent on to some IP layer for further processing.
+ * and sent on to some IP layer for further processing. This will not
+ * be re-entered while running but other ldisc functions may be called
+ * in parallel
  */
  
 static void slip_receive_buf(struct tty_struct *tty, const unsigned char *cp, char *fp, int count)
@@ -841,9 +843,11 @@
  * SLIP line discipline is called for.  Because we are
  * sure the tty line exists, we only have to link it to
  * a free SLIP channel...
+ *
+ * Called in process context serialized from other ldisc calls.
  */
-static int
-slip_open(struct tty_struct *tty)
+
+static int slip_open(struct tty_struct *tty)
 {
 	struct slip *sl;
 	int err;
@@ -876,11 +880,11 @@
 	tty->disc_data = sl;
 	sl->line = tty_devnum(tty);
 	sl->pid = current->pid;
+	
+	/* FIXME: already done before we were called - seems this can go */
 	if (tty->driver->flush_buffer)
 		tty->driver->flush_buffer(tty);
-	if (tty->ldisc.flush_buffer)
-		tty->ldisc.flush_buffer(tty);
-
+		
 	if (!test_bit(SLF_INUSE, &sl->flags)) {
 		/* Perform the low-level SLIP initialization. */
 		if ((err = sl_alloc_bufs(sl, SL_MTU)) != 0)
@@ -923,6 +927,9 @@
 }
 
 /*
+
+  FIXME: 1,2 are fixed 3 was never true anyway.
+  
    Let me to blame a bit.
    1. TTY module calls this funstion on soft interrupt.
    2. TTY module calls this function WITH MASKED INTERRUPTS!
@@ -941,9 +948,8 @@
 
 /*
  * Close down a SLIP channel.
- * This means flushing out any pending queues, and then restoring the
- * TTY line discipline to what it was before it got hooked to SLIP
- * (which usually is TTY again).
+ * This means flushing out any pending queues, and then returning. This
+ * call is serialized against other ldisc functions.
  */
 static void
 slip_close(struct tty_struct *tty)
diff -Nru a/drivers/net/smc9194.c b/drivers/net/smc9194.c
--- a/drivers/net/smc9194.c	2004-10-18 14:56:49 -07:00
+++ b/drivers/net/smc9194.c	2004-10-18 14:56:49 -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-10-18 14:57:04 -07:00
+++ b/drivers/net/smc91x.c	2004-10-18 14:57:04 -07:00
@@ -55,6 +55,9 @@
  *                                  smc_phy_configure
  *                                - clean up (and fix stack overrun) in PHY
  *                                  MII read/write functions
+ *   09/15/04  Hayato Fujiwara    - Add m32r support.
+ *                                - Modify for SMP kernel; Change spin-locked
+ *                                  regions.
  */
 static const char version[] =
 	"smc91x.c: v1.0, mar 07 2003 by Nicolas Pitre <nico@cam.org>\n";
@@ -256,24 +259,18 @@
 
 /* this enables an interrupt in the interrupt mask register */
 #define SMC_ENABLE_INT(x) do {						\
-	unsigned long flags;						\
 	unsigned char mask;						\
-	spin_lock_irqsave(&lp->lock, flags);				\
 	mask = SMC_GET_INT_MASK();					\
 	mask |= (x);							\
 	SMC_SET_INT_MASK(mask);						\
-	spin_unlock_irqrestore(&lp->lock, flags);			\
 } while (0)
 
 /* this disables an interrupt from the interrupt mask register */
 #define SMC_DISABLE_INT(x) do {						\
-	unsigned long flags;						\
 	unsigned char mask;						\
-	spin_lock_irqsave(&lp->lock, flags);				\
 	mask = SMC_GET_INT_MASK();					\
 	mask &= ~(x);							\
 	SMC_SET_INT_MASK(mask);						\
-	spin_unlock_irqrestore(&lp->lock, flags);			\
 } while (0)
 
 /*
@@ -580,9 +577,12 @@
 	struct smc_local *lp = netdev_priv(dev);
 	unsigned long ioaddr = dev->base_addr;
 	unsigned int numPages, poll_count, status, saved_bank;
+	unsigned long flags;
 
 	DBG(3, "%s: %s\n", dev->name, __FUNCTION__);
 
+	spin_lock_irqsave(&lp->lock, flags);
+
 	BUG_ON(lp->saved_skb != NULL);
 	lp->saved_skb = skb;
 
@@ -604,6 +604,7 @@
 		lp->stats.tx_errors++;
 		lp->stats.tx_dropped++;
 		dev_kfree_skb(skb);
+		spin_unlock_irqrestore(&lp->lock, flags);
 		return 0;
 	}
 
@@ -652,6 +653,7 @@
 	}
 
 	SMC_SELECT_BANK(saved_bank);
+	spin_unlock_irqrestore(&lp->lock, flags);
 	return 0;
 }
 
@@ -1166,6 +1168,8 @@
 
 	DBG(3, "%s: %s\n", dev->name, __FUNCTION__);
 
+	spin_lock(&lp->lock);
+
 	saved_bank = SMC_CURRENT_BANK();
 	SMC_SELECT_BANK(2);
 	saved_pointer = SMC_GET_PTR();
@@ -1189,8 +1193,6 @@
 		if (!status)
 			break;
 
-		spin_lock(&lp->lock);
-
 		if (status & IM_RCV_INT) {
 			DBG(3, "%s: RX irq\n", dev->name);
 			smc_rcv(dev);
@@ -1239,7 +1241,6 @@
 			PRINTK("%s: UNSUPPORTED: ERCV INTERRUPT \n", dev->name);
 		}
 
-		spin_unlock(&lp->lock);
 	} while (--timeout);
 
 	/* restore register states */
@@ -1249,6 +1250,7 @@
 
 	DBG(3, "%s: Interrupt done (%d loops)\n", dev->name, 8-timeout);
 
+	spin_unlock(&lp->lock);
 	/*
 	 * We return IRQ_HANDLED unconditionally here even if there was
 	 * nothing to do.  There is a possibility that a packet might
@@ -1264,7 +1266,9 @@
 static void smc_timeout(struct net_device *dev)
 {
 	struct smc_local *lp = netdev_priv(dev);
+	unsigned long flags;
 
+	spin_lock_irqsave(&lp->lock, flags);
 	DBG(2, "%s: %s\n", dev->name, __FUNCTION__);
 
 	smc_reset(dev);
@@ -1298,6 +1302,9 @@
 	}
 	/* We can accept TX packets again */
 	dev->trans_start = jiffies;
+
+	spin_unlock_irqrestore(&lp->lock, flags);
+
 	netif_wake_queue(dev);
 }
 
@@ -1438,7 +1445,7 @@
 	 * address using ifconfig eth0 hw ether xx:xx:xx:xx:xx:xx
 	 */
 	if (!is_valid_ether_addr(dev->dev_addr)) {
-		DBG(2, (KERN_DEBUG "smc_open: no valid ethernet hw addr\n"));
+		DBG(2, "smc_open: no valid ethernet hw addr\n");
 		return -EINVAL;
 	}
 
@@ -1878,7 +1885,9 @@
       	if (retval)
       		goto err_out;
 
+#if !defined(__m32r__)
 	set_irq_type(dev->irq, IRQT_RISING);
+#endif
 #ifdef SMC_USE_PXA_DMA
 	{
 		int dma = pxa_request_dma(dev->name, DMA_PRIO_LOW,
@@ -2154,10 +2163,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-10-18 14:56:49 -07:00
+++ b/drivers/net/smc91x.h	2004-10-18 14:56:49 -07:00
@@ -160,6 +160,19 @@
 #define SMC_insw(a, r, p, l)	insw((a) + (r), p, l)
 #define SMC_outsw(a, r, p, l)	outsw((a) + (r), p, l)
 
+#elif   defined(CONFIG_M32R)
+
+#define SMC_CAN_USE_8BIT	0
+#define SMC_CAN_USE_16BIT	1
+#define SMC_CAN_USE_32BIT	0
+
+#define SMC_inb(a, r)		inb((a) + (r) - 0xa0000000)
+#define SMC_inw(a, r)		inw((a) + (r) - 0xa0000000)
+#define SMC_outb(v, a, r)	outb(v, (a) + (r) - 0xa0000000)
+#define SMC_outw(v, a, r)	outw(v, (a) + (r) - 0xa0000000)
+#define SMC_insw(a, r, p, l)	insw((a) + (r) - 0xa0000000, p, l)
+#define SMC_outsw(a, r, p, l)	outsw((a) + (r) - 0xa0000000, p, l)
+
 #else
 
 #define SMC_CAN_USE_8BIT	1
@@ -809,9 +822,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 +837,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 +845,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/sunbmac.c b/drivers/net/sunbmac.c
--- a/drivers/net/sunbmac.c	2004-10-18 14:56:32 -07:00
+++ b/drivers/net/sunbmac.c	2004-10-18 14:56:32 -07:00
@@ -68,7 +68,7 @@
 
 #define QEC_RESET_TRIES 200
 
-static int qec_global_reset(unsigned long gregs)
+static int qec_global_reset(void __iomem *gregs)
 {
 	int tries = QEC_RESET_TRIES;
 
@@ -88,7 +88,7 @@
 
 static void qec_init(struct bigmac *bp)
 {
-	unsigned long gregs = bp->gregs;
+	void __iomem *gregs = bp->gregs;
 	struct sbus_dev *qec_sdev = bp->qec_sdev;
 	u8 bsizes = bp->bigmac_bursts;
 	u32 regval;
@@ -117,7 +117,7 @@
 #define TX_RESET_TRIES     32
 #define RX_RESET_TRIES     32
 
-static void bigmac_tx_reset(unsigned long bregs)
+static void bigmac_tx_reset(void __iomem *bregs)
 {
 	int tries = TX_RESET_TRIES;
 
@@ -137,7 +137,7 @@
 	}
 }
 
-static void bigmac_rx_reset(unsigned long bregs)
+static void bigmac_rx_reset(void __iomem *bregs)
 {
 	int tries = RX_RESET_TRIES;
 
@@ -159,7 +159,7 @@
 	bigmac_rx_reset(bp->bregs);
 }
 
-static void bigmac_get_counters(struct bigmac *bp, unsigned long bregs)
+static void bigmac_get_counters(struct bigmac *bp, void __iomem *bregs)
 {
 	struct net_device_stats *stats = &bp->enet_stats;
 
@@ -244,7 +244,7 @@
 #define MGMT_CLKON  (MGMT_PAL_INT_MDIO|MGMT_PAL_EXT_MDIO|MGMT_PAL_OENAB|MGMT_PAL_DCLOCK)
 #define MGMT_CLKOFF (MGMT_PAL_INT_MDIO|MGMT_PAL_EXT_MDIO|MGMT_PAL_OENAB)
 
-static void idle_transceiver(unsigned long tregs)
+static void idle_transceiver(void __iomem *tregs)
 {
 	int i = 20;
 
@@ -256,7 +256,7 @@
 	}
 }
 
-static void write_tcvr_bit(struct bigmac *bp, unsigned long tregs, int bit)
+static void write_tcvr_bit(struct bigmac *bp, void __iomem *tregs, int bit)
 {
 	if (bp->tcvr_type == internal) {
 		bit = (bit & 1) << 3;
@@ -279,7 +279,7 @@
 	}
 }
 
-static int read_tcvr_bit(struct bigmac *bp, unsigned long tregs)
+static int read_tcvr_bit(struct bigmac *bp, void __iomem *tregs)
 {
 	int retval = 0;
 
@@ -302,7 +302,7 @@
 	return retval;
 }
 
-static int read_tcvr_bit2(struct bigmac *bp, unsigned long tregs)
+static int read_tcvr_bit2(struct bigmac *bp, void __iomem *tregs)
 {
 	int retval = 0;
 
@@ -325,7 +325,7 @@
 }
 
 static void put_tcvr_byte(struct bigmac *bp,
-			  unsigned long tregs,
+			  void __iomem *tregs,
 			  unsigned int byte)
 {
 	int shift = 4;
@@ -336,7 +336,7 @@
 	} while (shift >= 0);
 }
 
-static void bigmac_tcvr_write(struct bigmac *bp, unsigned long tregs,
+static void bigmac_tcvr_write(struct bigmac *bp, void __iomem *tregs,
 			      int reg, unsigned short val)
 {
 	int shift;
@@ -376,7 +376,7 @@
 }
 
 static unsigned short bigmac_tcvr_read(struct bigmac *bp,
-				       unsigned long tregs,
+				       void __iomem *tregs,
 				       int reg)
 {
 	unsigned short retval = 0;
@@ -444,7 +444,7 @@
 
 static void bigmac_tcvr_init(struct bigmac *bp)
 {
-	unsigned long tregs = bp->tregs;
+	void __iomem *tregs = bp->tregs;
 	u32 mpal;
 
 	idle_transceiver(tregs);
@@ -482,7 +482,7 @@
 
 static int bigmac_init(struct bigmac *, int);
 
-static int try_next_permutation(struct bigmac *bp, unsigned long tregs)
+static int try_next_permutation(struct bigmac *bp, void __iomem *tregs)
 {
 	if (bp->sw_bmcr & BMCR_SPEED100) {
 		int timeout;
@@ -518,7 +518,7 @@
 static void bigmac_timer(unsigned long data)
 {
 	struct bigmac *bp = (struct bigmac *) data;
-	unsigned long tregs = bp->tregs;
+	void __iomem *tregs = bp->tregs;
 	int restart_timer = 0;
 
 	bp->timer_ticks++;
@@ -573,7 +573,7 @@
  */
 static void bigmac_begin_auto_negotiation(struct bigmac *bp)
 {
-	unsigned long tregs = bp->tregs;
+	void __iomem *tregs = bp->tregs;
 	int timeout;
 
 	/* Grab new software copies of PHY registers. */
@@ -612,9 +612,9 @@
 
 static int bigmac_init(struct bigmac *bp, int from_irq)
 {
-	unsigned long gregs        = bp->gregs;
-	unsigned long cregs        = bp->creg;
-	unsigned long bregs        = bp->bregs;
+	void __iomem *gregs        = bp->gregs;
+	void __iomem *cregs        = bp->creg;
+	void __iomem *bregs        = bp->bregs;
 	unsigned char *e = &bp->dev->dev_addr[0];
 
 	/* Latch current counters into statistics. */
@@ -987,7 +987,7 @@
 static void bigmac_set_multicast(struct net_device *dev)
 {
 	struct bigmac *bp = (struct bigmac *) dev->priv;
-	unsigned long bregs = bp->bregs;
+	void __iomem *bregs = bp->bregs;
 	struct dev_mc_list *dmi = dev->mc_list;
 	char *addrs;
 	int i;
diff -Nru a/drivers/net/sunbmac.h b/drivers/net/sunbmac.h
--- a/drivers/net/sunbmac.h	2004-10-18 14:55:54 -07:00
+++ b/drivers/net/sunbmac.h	2004-10-18 14:55:54 -07:00
@@ -303,10 +303,10 @@
 };
 
 struct bigmac {
-	unsigned long	gregs;	/* QEC Global Registers               */
-	unsigned long	creg;	/* QEC BigMAC Channel Registers       */
-	unsigned long	bregs;	/* BigMAC Registers                   */
-	unsigned long	tregs;	/* BigMAC Transceiver                 */
+	void __iomem	*gregs;	/* QEC Global Registers               */
+	void __iomem	*creg;	/* QEC BigMAC Channel Registers       */
+	void __iomem	*bregs;	/* BigMAC Registers                   */
+	void __iomem	*tregs;	/* BigMAC Transceiver                 */
 	struct bmac_init_block	*bmac_block;	/* RX and TX descriptors */
 	__u32			 bblock_dvma;	/* RX and TX descriptors */
 
diff -Nru a/drivers/net/sundance.c b/drivers/net/sundance.c
--- a/drivers/net/sundance.c	2004-10-18 14:56:33 -07:00
+++ b/drivers/net/sundance.c	2004-10-18 14:56:33 -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/sungem.c b/drivers/net/sungem.c
--- a/drivers/net/sungem.c	2004-10-18 14:57:04 -07:00
+++ b/drivers/net/sungem.c	2004-10-18 14:57:04 -07:00
@@ -5,6 +5,9 @@
  * 
  * Support for Apple GMAC and assorted PHYs by
  * Benjamin Herrenscmidt (benh@kernel.crashing.org)
+ *
+ * NAPI and NETPOLL support
+ * (C) 2004 by Eric Lemoine (eric.lemoine@gmail.com)
  * 
  * TODO: 
  *  - Get rid of all those nasty mdelay's and replace them
@@ -181,6 +184,18 @@
 	__phy_write(gp, gp->mii_phy_addr, reg, val);
 }
 
+static inline void gem_enable_ints(struct gem *gp)
+{
+	/* Enable all interrupts but TXDONE */
+	writel(GREG_STAT_TXDONE, gp->regs + GREG_IMASK);
+}
+
+static inline void gem_disable_ints(struct gem *gp)
+{
+	/* Disable all interrupts, including TXDONE */
+	writel(GREG_STAT_NAPI | GREG_STAT_TXDONE, gp->regs + GREG_IMASK);
+}
+
 static void gem_handle_mif_event(struct gem *gp, u32 reg_val, u32 changed_bits)
 {
 	if (netif_msg_intr(gp))
@@ -678,12 +693,12 @@
 	}
 }
 
-static void gem_rx(struct gem *gp)
+static int gem_rx(struct gem *gp, int work_to_do)
 {
-	int entry, drops;
+	int entry, drops, work_done = 0;
 	u32 done;
 
-	if (netif_msg_intr(gp))
+	if (netif_msg_rx_status(gp))
 		printk(KERN_DEBUG "%s: rx interrupt, done: %d, rx_new: %d\n",
 			gp->dev->name, readl(gp->regs + RXDMA_DONE), gp->rx_new);
 
@@ -700,6 +715,9 @@
 		if ((status & RXDCTRL_OWN) != 0)
 			break;
 
+		if (work_done >= RX_RING_SIZE || work_done >= work_to_do)
+			break;
+
 		/* When writing back RX descriptor, GEM writes status
 		 * then buffer address, possibly in seperate transactions.
 		 * If we don't wait for the chip to write both, we could
@@ -713,6 +731,9 @@
 				break;
 		}
 
+		/* We can now account for the work we're about to do */
+		work_done++;
+
 		skb = gp->rx_skbs[entry];
 
 		len = (status & RXDCTRL_BUFSZ) >> 16;
@@ -775,7 +796,8 @@
 		skb->csum = ntohs((status & RXDCTRL_TCPCSUM) ^ 0xffff);
 		skb->ip_summed = CHECKSUM_HW;
 		skb->protocol = eth_type_trans(skb, gp->dev);
-		netif_rx(skb);
+
+		netif_receive_skb(skb);
 
 		gp->net_stats.rx_packets++;
 		gp->net_stats.rx_bytes += len;
@@ -792,35 +814,103 @@
 	if (drops)
 		printk(KERN_INFO "%s: Memory squeeze, deferring packet.\n",
 		       gp->dev->name);
+
+	return work_done;
+}
+
+static int gem_poll(struct net_device *dev, int *budget)
+{
+	struct gem *gp = dev->priv;
+	unsigned long flags;
+
+	spin_lock_irqsave(&gp->lock, flags);
+
+	do {
+		int work_to_do, work_done;
+
+		/* Handle anomalies */
+		if (gp->status & GREG_STAT_ABNORMAL) {
+			if (gem_abnormal_irq(dev, gp, gp->status))
+				break;
+		}
+
+		/* Run TX completion thread */
+		spin_lock(&gp->tx_lock);
+		gem_tx(dev, gp, gp->status);
+		spin_unlock(&gp->tx_lock);
+
+		spin_unlock_irqrestore(&gp->lock, flags);
+
+		/* Run RX thread. We don't use any locking here, 
+		 * code willing to do bad things - like cleaning the 
+		 * rx ring - must call netif_poll_disable(), which
+		 * schedule_timeout()'s if polling is already disabled.
+		 */
+		work_to_do = min(*budget, dev->quota);
+
+		work_done = gem_rx(gp, work_to_do);
+
+		*budget -= work_done;
+		dev->quota -= work_done;
+
+		if (work_done >= work_to_do)
+			return 1;
+
+		spin_lock_irqsave(&gp->lock, flags);
+		
+		gp->status = readl(gp->regs + GREG_STAT);
+	} while (gp->status & GREG_STAT_NAPI);
+
+	__netif_rx_complete(dev);
+	gem_enable_ints(gp);
+
+	spin_unlock_irqrestore(&gp->lock, flags);
+	return 0;
 }
 
 static irqreturn_t gem_interrupt(int irq, void *dev_id, struct pt_regs *regs)
 {
 	struct net_device *dev = dev_id;
 	struct gem *gp = dev->priv;
-	u32 gem_status = readl(gp->regs + GREG_STAT);
+	unsigned long flags;
 
 	/* Swallow interrupts when shutting the chip down */
-	if (gp->hw_running == 0)
-		goto out;
-
-	spin_lock(&gp->lock);
+	if (!gp->hw_running)
+		return IRQ_HANDLED;
 
-	if (gem_status & GREG_STAT_ABNORMAL) {
-		if (gem_abnormal_irq(dev, gp, gem_status))
-			goto out;
-	}
-	if (gem_status & (GREG_STAT_TXALL | GREG_STAT_TXINTME))
-		gem_tx(dev, gp, gem_status);
-	if (gem_status & GREG_STAT_RXDONE)
-		gem_rx(gp);
+	spin_lock_irqsave(&gp->lock, flags);
+	
+	if (netif_rx_schedule_prep(dev)) {
+		u32 gem_status = readl(gp->regs + GREG_STAT);
 
-out:
-	spin_unlock(&gp->lock);
+		if (gem_status == 0) {
+			spin_unlock_irqrestore(&gp->lock, flags);
+			return IRQ_NONE;
+		}
+		gp->status = gem_status;
+		gem_disable_ints(gp);
+		__netif_rx_schedule(dev);
+	}
 
+	spin_unlock_irqrestore(&gp->lock, flags);
+  
+	/* If polling was disabled at the time we received that
+	 * interrupt, we may return IRQ_HANDLED here while we 
+	 * should return IRQ_NONE. No big deal...
+	 */
 	return IRQ_HANDLED;
 }
 
+#ifdef CONFIG_NET_POLL_CONTROLLER
+static void gem_poll_controller(struct net_device *dev)
+{
+	/* gem_interrupt is safe to reentrance so no need
+	 * to disable_irq here.
+	 */
+	gem_interrupt(dev->irq, dev, NULL);
+}
+#endif
+
 static void gem_tx_timeout(struct net_device *dev)
 {
 	struct gem *gp = dev->priv;
@@ -842,10 +932,12 @@
 	       readl(gp->regs + MAC_RXCFG));
 
 	spin_lock_irq(&gp->lock);
+	spin_lock(&gp->tx_lock);
 
 	gp->reset_task_pending = 2;
 	schedule_work(&gp->reset_task);
 
+	spin_unlock(&gp->tx_lock);
 	spin_unlock_irq(&gp->lock);
 }
 
@@ -863,6 +955,7 @@
 	struct gem *gp = dev->priv;
 	int entry;
 	u64 ctrl;
+	unsigned long flags;
 
 	ctrl = 0;
 	if (skb->ip_summed == CHECKSUM_HW) {
@@ -876,15 +969,20 @@
 			(csum_stuff_off << 21));
 	}
 
-	spin_lock_irq(&gp->lock);
+	local_irq_save(flags);
+	if (!spin_trylock(&gp->tx_lock)) {
+		/* Tell upper layer to requeue */
+		local_irq_restore(flags);
+		return NETDEV_TX_LOCKED;
+	}
 
 	/* This is a hard error, log it. */
 	if (TX_BUFFS_AVAIL(gp) <= (skb_shinfo(skb)->nr_frags + 1)) {
 		netif_stop_queue(dev);
-		spin_unlock_irq(&gp->lock);
+		spin_unlock_irqrestore(&gp->tx_lock, flags);
 		printk(KERN_ERR PFX "%s: BUG! Tx Ring full when queue awake!\n",
 		       dev->name);
-		return 1;
+		return NETDEV_TX_BUSY;
 	}
 
 	entry = gp->tx_new;
@@ -968,11 +1066,11 @@
 		       dev->name, entry, skb->len);
 	mb();
 	writel(gp->tx_new, gp->regs + TXDMA_KICK);
-	spin_unlock_irq(&gp->lock);
+	spin_unlock_irqrestore(&gp->tx_lock, flags);
 
 	dev->trans_start = jiffies;
 
-	return 0;
+	return NETDEV_TX_OK;
 }
 
 /* Jumbo-grams don't seem to work :-( */
@@ -999,9 +1097,11 @@
 	}
 
 	spin_lock_irq(&gp->lock);
+	spin_lock(&gp->tx_lock);
 	dev->mtu = new_mtu;
 	gp->reset_task_pending = 1;
 	schedule_work(&gp->reset_task);
+	spin_unlock(&gp->tx_lock);
 	spin_unlock_irq(&gp->lock);
 
 	flush_scheduled_work();
@@ -1011,7 +1111,7 @@
 
 #define STOP_TRIES 32
 
-/* Must be invoked under gp->lock. */
+/* Must be invoked under gp->lock and gp->tx_lock. */
 static void gem_stop(struct gem *gp)
 {
 	int limit;
@@ -1037,7 +1137,7 @@
 		printk(KERN_ERR "%s: SW reset is ghetto.\n", gp->dev->name);
 }
 
-/* Must be invoked under gp->lock. */
+/* Must be invoked under gp->lock and gp->tx_lock. */
 static void gem_start_dma(struct gem *gp)
 {
 	unsigned long val;
@@ -1062,7 +1162,7 @@
 }
 
 
-/* Must be invoked under gp->lock. */
+/* Must be invoked under gp->lock and gp->tx_lock. */
 // XXX dbl check what that function should do when called on PCS PHY
 static void gem_begin_auto_negotiation(struct gem *gp, struct ethtool_cmd *ep)
 {
@@ -1149,7 +1249,7 @@
 /* A link-up condition has occurred, initialize and enable the
  * rest of the chip.
  *
- * Must be invoked under gp->lock.
+ * Must be invoked under gp->lock and gp->tx_lock.
  */
 static int gem_set_link_modes(struct gem *gp)
 {
@@ -1256,7 +1356,7 @@
 	return 0;
 }
 
-/* Must be invoked under gp->lock. */
+/* Must be invoked under gp->lock and gp->tx_lock. */
 static int gem_mdio_link_not_up(struct gem *gp)
 {
 	switch (gp->lstate) {
@@ -1312,19 +1412,13 @@
 {
 	struct gem *gp = (struct gem *) data;
 
-	/* The link went down, we reset the ring, but keep
-	 * DMA stopped. Todo: Use this function for reset
-	 * on error as well.
-	 */
-
+	netif_poll_disable(gp->dev);
 	spin_lock_irq(&gp->lock);
+	spin_lock(&gp->tx_lock);
 
 	if (gp->hw_running && gp->opened) {
-		/* Make sure we don't get interrupts or tx packets */
 		netif_stop_queue(gp->dev);
 
-		writel(0xffffffff, gp->regs + GREG_IMASK);
-
 		/* Reset the chip & rings */
 		gem_stop(gp);
 		gem_init_rings(gp);
@@ -1336,7 +1430,9 @@
 	}
 	gp->reset_task_pending = 0;
 
+	spin_unlock(&gp->tx_lock);
 	spin_unlock_irq(&gp->lock);
+	netif_poll_enable(gp->dev);
 }
 
 static void gem_link_timer(unsigned long data)
@@ -1348,6 +1444,7 @@
 		return;
 
 	spin_lock_irq(&gp->lock);
+	spin_lock(&gp->tx_lock);
 
 	/* If the link of task is still pending, we just
 	 * reschedule the link timer
@@ -1417,10 +1514,11 @@
 restart:
 	mod_timer(&gp->link_timer, jiffies + ((12 * HZ) / 10));
 out_unlock:
+	spin_unlock(&gp->tx_lock);
 	spin_unlock_irq(&gp->lock);
 }
 
-/* Must be invoked under gp->lock. */
+/* Must be invoked under gp->lock and gp->tx_lock. */
 static void gem_clean_rings(struct gem *gp)
 {
 	struct gem_init_block *gb = gp->init_block;
@@ -1471,7 +1569,7 @@
 	}
 }
 
-/* Must be invoked under gp->lock. */
+/* Must be invoked under gp->lock and gp->tx_lock. */
 static void gem_init_rings(struct gem *gp)
 {
 	struct gem_init_block *gb = gp->init_block;
@@ -1521,7 +1619,7 @@
 	wmb();
 }
 
-/* Must be invoked under gp->lock. */
+/* Must be invoked under gp->lock and gp->tx_lock. */
 static void gem_init_phy(struct gem *gp)
 {
 	u32 mifcfg;
@@ -1659,7 +1757,7 @@
 	}
 }
 
-/* Must be invoked under gp->lock. */
+/* Must be invoked under gp->lock and gp->tx_lock. */
 static void gem_init_dma(struct gem *gp)
 {
 	u64 desc_dma = (u64) gp->gblock_dvma;
@@ -1697,7 +1795,7 @@
 		       gp->regs + RXDMA_BLANK);
 }
 
-/* Must be invoked under gp->lock. */
+/* Must be invoked under gp->lock and gp->tx_lock. */
 static u32
 gem_setup_multicast(struct gem *gp)
 {
@@ -1740,7 +1838,7 @@
 	return rxcfg;
 }
 
-/* Must be invoked under gp->lock. */
+/* Must be invoked under gp->lock and gp->tx_lock. */
 static void gem_init_mac(struct gem *gp)
 {
 	unsigned char *e = &gp->dev->dev_addr[0];
@@ -1818,7 +1916,7 @@
 	writel(0xffffffff, gp->regs + MAC_MCMASK);
 }
 
-/* Must be invoked under gp->lock. */
+/* Must be invoked under gp->lock and gp->tx_lock. */
 static void gem_init_pause_thresholds(struct gem *gp)
 {
        	u32 cfg;
@@ -1954,7 +2052,7 @@
 	return 0;
 }
 
-/* Must be invoked under gp->lock. */
+/* Must be invoked under gp->lock and gp->tx_lock. */
 static void gem_init_hw(struct gem *gp, int restart_link)
 {
 	/* On Apple's gmac, I initialize the PHY only after
@@ -2052,9 +2150,11 @@
 
 	if (!gp->wake_on_lan) {
 		spin_lock_irqsave(&gp->lock, flags);
+		spin_lock(&gp->tx_lock);
 		gem_stop(gp);
 		writel(MAC_TXRST_CMD, gp->regs + MAC_TXRST);
 		writel(MAC_RXRST_CMD, gp->regs + MAC_RXRST);
+		spin_unlock(&gp->tx_lock);
 		spin_unlock_irqrestore(&gp->lock, flags);
 	}
 
@@ -2102,8 +2202,10 @@
 		unsigned long flags;
 
 		spin_lock_irqsave(&gp->lock, flags);
+		spin_lock(&gp->tx_lock);
 		gem_stop(gp);
-		spin_unlock_irqrestore(&gp->lock, flags);	
+		spin_unlock(&gp->tx_lock);
+		spin_unlock_irqrestore(&gp->lock, flags);
 	}
 }
 
@@ -2163,7 +2265,9 @@
 
 		/* Reset the chip */
 		spin_lock_irq(&gp->lock);
+		spin_lock(&gp->tx_lock);
 		gem_stop(gp);
+		spin_unlock(&gp->tx_lock);
 		spin_unlock_irq(&gp->lock);
 
 		gp->hw_running = 1;
@@ -2177,6 +2281,7 @@
 		printk(KERN_ERR "%s: failed to request irq !\n", gp->dev->name);
 
 		spin_lock_irq(&gp->lock);
+		spin_lock(&gp->tx_lock);
 #ifdef CONFIG_PPC_PMAC
 		if (!hw_was_up && gp->pdev->vendor == PCI_VENDOR_ID_APPLE)
 			gem_apple_powerdown(gp);
@@ -2185,12 +2290,14 @@
 		gp->pm_timer.expires = jiffies + 10*HZ;
 		add_timer(&gp->pm_timer);
 		up(&gp->pm_sem);
+		spin_unlock(&gp->tx_lock);
 		spin_unlock_irq(&gp->lock);
 
 		return -EAGAIN;
 	}
 
        	spin_lock_irq(&gp->lock);
+	spin_lock(&gp->tx_lock);
 
 	/* Allocate & setup ring buffers */
 	gem_init_rings(gp);
@@ -2200,6 +2307,7 @@
 
 	gp->opened = 1;
 
+	spin_unlock(&gp->tx_lock);
 	spin_unlock_irq(&gp->lock);
 
 	up(&gp->pm_sem);
@@ -2214,11 +2322,16 @@
 	/* Make sure we don't get distracted by suspend/resume */
 	down(&gp->pm_sem);
 
+	/* Note: we don't need to call netif_poll_disable() here because
+	 * our caller (dev_close) already did it for us
+	 */
+
 	/* Stop traffic, mark us closed */
 	spin_lock_irq(&gp->lock);
+	spin_lock(&gp->tx_lock);
 
 	gp->opened = 0;	
-	writel(0xffffffff, gp->regs + GREG_IMASK);
+
 	netif_stop_queue(dev);
 
 	/* Stop chip */
@@ -2230,6 +2343,7 @@
 	/* Bye, the pm timer will finish the job */
 	free_irq(gp->pdev->irq, (void *) dev);
 
+	spin_unlock(&gp->tx_lock);
 	spin_unlock_irq(&gp->lock);
 
 	/* Fire the PM timer that will shut us down in about 10 seconds */
@@ -2247,6 +2361,8 @@
 	struct net_device *dev = pci_get_drvdata(pdev);
 	struct gem *gp = dev->priv;
 
+	netif_poll_disable(dev);
+
 	/* We hold the PM semaphore during entire driver
 	 * sleep time
 	 */
@@ -2258,18 +2374,18 @@
 	/* If the driver is opened, we stop the DMA */
 	if (gp->opened) {
 		spin_lock_irq(&gp->lock);
+		spin_lock(&gp->tx_lock);
 
 		/* Stop traffic, mark us closed */
 		netif_device_detach(dev);
 
-		writel(0xffffffff, gp->regs + GREG_IMASK);
-
 		/* Stop chip */
 		gem_stop(gp);
 
 		/* Get rid of ring buffers */
 		gem_clean_rings(gp);
 
+		spin_unlock(&gp->tx_lock);
 		spin_unlock_irq(&gp->lock);
 
 		if (gp->pdev->vendor == PCI_VENDOR_ID_APPLE)
@@ -2303,12 +2419,14 @@
 		}
 #endif /* CONFIG_PPC_PMAC */
 		spin_lock_irq(&gp->lock);
+		spin_lock(&gp->tx_lock);
 
 		gem_stop(gp);
 		gp->hw_running = 1;
 		gem_init_rings(gp);
 		gem_init_hw(gp, 1);
 
+		spin_unlock(&gp->tx_lock);
 		spin_unlock_irq(&gp->lock);
 
 		netif_device_attach(dev);
@@ -2317,6 +2435,8 @@
 	}
 	up(&gp->pm_sem);
 
+	netif_poll_enable(dev);
+	
 	return 0;
 }
 #endif /* CONFIG_PM */
@@ -2327,6 +2447,7 @@
 	struct net_device_stats *stats = &gp->net_stats;
 
 	spin_lock_irq(&gp->lock);
+	spin_lock(&gp->tx_lock);
 
 	if (gp->hw_running) {
 		stats->rx_crc_errors += readl(gp->regs + MAC_FCSERR);
@@ -2346,6 +2467,7 @@
 		writel(0, gp->regs + MAC_LCOLL);
 	}
 
+	spin_unlock(&gp->tx_lock);
 	spin_unlock_irq(&gp->lock);
 
 	return &gp->net_stats;
@@ -2361,6 +2483,7 @@
 		return;
 		
 	spin_lock_irq(&gp->lock);
+	spin_lock(&gp->tx_lock);
 
 	netif_stop_queue(dev);
 
@@ -2385,6 +2508,7 @@
 
 	netif_wake_queue(dev);
 
+	spin_unlock(&gp->tx_lock);
 	spin_unlock_irq(&gp->lock);
 }
 
@@ -2416,6 +2540,7 @@
 
 		/* Return current PHY settings */
 		spin_lock_irq(&gp->lock);
+		spin_lock(&gp->tx_lock);
 		cmd->autoneg = gp->want_autoneg;
 		cmd->speed = gp->phy_mii.speed;
 		cmd->duplex = gp->phy_mii.duplex;			
@@ -2427,6 +2552,7 @@
 		 */
 		if (cmd->advertising == 0)
 			cmd->advertising = cmd->supported;
+		spin_unlock(&gp->tx_lock);
 		spin_unlock_irq(&gp->lock);
 	} else { // XXX PCS ?
 		cmd->supported =
@@ -2466,7 +2592,9 @@
 	      
 	/* Apply settings and restart link process. */
 	spin_lock_irq(&gp->lock);
+	spin_lock(&gp->tx_lock);
 	gem_begin_auto_negotiation(gp, cmd);
+	spin_unlock(&gp->tx_lock);
 	spin_unlock_irq(&gp->lock);
 
 	return 0;
@@ -2481,7 +2609,9 @@
 
 	/* Restart link process. */
 	spin_lock_irq(&gp->lock);
+	spin_lock(&gp->tx_lock);
 	gem_begin_auto_negotiation(gp, NULL);
+	spin_unlock(&gp->tx_lock);
 	spin_unlock_irq(&gp->lock);
 
 	return 0;
@@ -2581,7 +2711,7 @@
 static void get_gem_mac_nonobp(struct pci_dev *pdev, unsigned char *dev_addr)
 {
 	u32 rom_reg_orig;
-	void *p;
+	void __iomem *p;
 
 	if (pdev->resource[PCI_ROM_RESOURCE].parent == NULL) {
 		if (pci_assign_resource(pdev, PCI_ROM_RESOURCE) < 0)
@@ -2733,6 +2863,7 @@
 	gp->msg_enable = DEFAULT_MSG;
 
 	spin_lock_init(&gp->lock);
+	spin_lock_init(&gp->tx_lock);
 	init_MUTEX(&gp->pm_sem);
 
 	init_timer(&gp->link_timer);
@@ -2750,7 +2881,7 @@
 	gp->timer_ticks = 0;
 	netif_carrier_off(dev);
 
-	gp->regs = (unsigned long) ioremap(gemreg_base, gemreg_len);
+	gp->regs = ioremap(gemreg_base, gemreg_len);
 	if (gp->regs == 0UL) {
 		printk(KERN_ERR PFX "Cannot map device registers, "
 		       "aborting.\n");
@@ -2768,7 +2899,9 @@
 		gem_apple_powerup(gp);
 #endif
 	spin_lock_irq(&gp->lock);
+	spin_lock(&gp->tx_lock);
 	gem_stop(gp);
+	spin_unlock(&gp->tx_lock);
 	spin_unlock_irq(&gp->lock);
 
 	/* Fill up the mii_phy structure (even if we won't use it) */
@@ -2806,12 +2939,17 @@
 	dev->get_stats = gem_get_stats;
 	dev->set_multicast_list = gem_set_multicast;
 	dev->do_ioctl = gem_ioctl;
+	dev->poll = gem_poll;
+	dev->weight = 64;
 	dev->ethtool_ops = &gem_ethtool_ops;
 	dev->tx_timeout = gem_tx_timeout;
 	dev->watchdog_timeo = 5 * HZ;
 	dev->change_mtu = gem_change_mtu;
 	dev->irq = pdev->irq;
 	dev->dma = 0;
+#ifdef CONFIG_NET_POLL_CONTROLLER
+	dev->poll_controller = gem_poll_controller;
+#endif
 
 	if (register_netdev(dev)) {
 		printk(KERN_ERR PFX "Cannot register net device, "
@@ -2829,9 +2967,11 @@
 
 	/* Detect & init PHY, start autoneg */
 	spin_lock_irq(&gp->lock);
+	spin_lock(&gp->tx_lock);
 	gp->hw_running = 1;
 	gem_init_phy(gp);
 	gem_begin_auto_negotiation(gp, NULL);
+	spin_unlock(&gp->tx_lock);
 	spin_unlock_irq(&gp->lock);
 
 	if (gp->phy_type == phy_mii_mdio0 ||
@@ -2842,7 +2982,7 @@
 	pci_set_drvdata(pdev, dev);
 
 	/* GEM can do it all... */
-	dev->features |= NETIF_F_SG | NETIF_F_HW_CSUM;
+	dev->features |= NETIF_F_SG | NETIF_F_HW_CSUM | NETIF_F_LLTX;
 	if (pci_using_dac)
 		dev->features |= NETIF_F_HIGHDMA;
 
@@ -2867,7 +3007,7 @@
 		gem_shutdown(gp);
 	up(&gp->pm_sem);
 
-	iounmap((void *) gp->regs);
+	iounmap(gp->regs);
 
 err_out_free_res:
 	pci_release_regions(pdev);
@@ -2901,7 +3041,7 @@
 				    sizeof(struct gem_init_block),
 				    gp->init_block,
 				    gp->gblock_dvma);
-		iounmap((void *) gp->regs);
+		iounmap(gp->regs);
 		pci_release_regions(pdev);
 		free_netdev(dev);
 
diff -Nru a/drivers/net/sungem.h b/drivers/net/sungem.h
--- a/drivers/net/sungem.h	2004-10-18 14:56:32 -07:00
+++ b/drivers/net/sungem.h	2004-10-18 14:56:32 -07:00
@@ -60,6 +60,9 @@
 				 GREG_STAT_PCS | GREG_STAT_TXMAC | GREG_STAT_RXMAC | \
 				 GREG_STAT_MAC | GREG_STAT_MIF | GREG_STAT_PCIERR)
 
+#define GREG_STAT_NAPI		(GREG_STAT_TXALL  | GREG_STAT_TXINTME | \
+				 GREG_STAT_RXDONE | GREG_STAT_ABNORMAL)
+
 /* The layout of GREG_IMASK and GREG_IACK is identical to GREG_STAT.
  * Bits set in GREG_IMASK will prevent that interrupt type from being
  * signalled to the cpu.  GREG_IACK can be used to clear specific top-level
@@ -950,7 +953,8 @@
 
 struct gem {
 	spinlock_t lock;
-	unsigned long regs;
+	spinlock_t tx_lock;
+	void __iomem *regs;
 	int rx_new, rx_old;
 	int tx_new, tx_old;
 
@@ -969,6 +973,7 @@
 	struct sk_buff *tx_skbs[RX_RING_SIZE];
 
 	u32			msg_enable;
+	u32			status;
 
 	struct net_device_stats net_stats;
 
diff -Nru a/drivers/net/sunhme.c b/drivers/net/sunhme.c
--- a/drivers/net/sunhme.c	2004-10-18 14:56:28 -07:00
+++ b/drivers/net/sunhme.c	2004-10-18 14:56:28 -07:00
@@ -203,12 +203,12 @@
  */
 
 #if defined(CONFIG_SBUS) && defined(CONFIG_PCI)
-static void sbus_hme_write32(unsigned long reg, u32 val)
+static void sbus_hme_write32(void __iomem *reg, u32 val)
 {
 	sbus_writel(val, reg);
 }
 
-static u32 sbus_hme_read32(unsigned long reg)
+static u32 sbus_hme_read32(void __iomem *reg)
 {
 	return sbus_readl(reg);
 }
@@ -232,12 +232,12 @@
 	return *p;
 }
 
-static void pci_hme_write32(unsigned long reg, u32 val)
+static void pci_hme_write32(void __iomem *reg, u32 val)
 {
 	writel(val, reg);
 }
 
-static u32 pci_hme_read32(unsigned long reg)
+static u32 pci_hme_read32(void __iomem *reg)
 {
 	return readl(reg);
 }
@@ -354,7 +354,7 @@
 
 
 /* Oh yes, the MIF BitBang is mighty fun to program.  BitBucket is more like it. */
-static void BB_PUT_BIT(struct happy_meal *hp, unsigned long tregs, int bit)
+static void BB_PUT_BIT(struct happy_meal *hp, void __iomem *tregs, int bit)
 {
 	hme_write32(hp, tregs + TCVR_BBDATA, bit);
 	hme_write32(hp, tregs + TCVR_BBCLOCK, 0);
@@ -362,7 +362,7 @@
 }
 
 #if 0
-static u32 BB_GET_BIT(struct happy_meal *hp, unsigned long tregs, int internal)
+static u32 BB_GET_BIT(struct happy_meal *hp, void __iomem *tregs, int internal)
 {
 	u32 ret;
 
@@ -378,7 +378,7 @@
 }
 #endif
 
-static u32 BB_GET_BIT2(struct happy_meal *hp, unsigned long tregs, int internal)
+static u32 BB_GET_BIT2(struct happy_meal *hp, void __iomem *tregs, int internal)
 {
 	u32 retval;
 
@@ -397,7 +397,7 @@
 #define TCVR_FAILURE      0x80000000     /* Impossible MIF read value */
 
 static int happy_meal_bb_read(struct happy_meal *hp,
-			      unsigned long tregs, int reg)
+			      void __iomem *tregs, int reg)
 {
 	u32 tmp;
 	int retval = 0;
@@ -443,7 +443,7 @@
 }
 
 static void happy_meal_bb_write(struct happy_meal *hp,
-				unsigned long tregs, int reg,
+				void __iomem *tregs, int reg,
 				unsigned short value)
 {
 	u32 tmp;
@@ -488,7 +488,7 @@
 #define TCVR_READ_TRIES   16
 
 static int happy_meal_tcvr_read(struct happy_meal *hp,
-				unsigned long tregs, int reg)
+				void __iomem *tregs, int reg)
 {
 	int tries = TCVR_READ_TRIES;
 	int retval;
@@ -520,7 +520,7 @@
 #define TCVR_WRITE_TRIES  16
 
 static void happy_meal_tcvr_write(struct happy_meal *hp,
-				  unsigned long tregs, int reg,
+				  void __iomem *tregs, int reg,
 				  unsigned short value)
 {
 	int tries = TCVR_WRITE_TRIES;
@@ -579,7 +579,7 @@
  * service routine, and the chip is reset, or the link is ifconfig'd down
  * and then back up, this entire process repeats itself all over again.
  */
-static int try_next_permutation(struct happy_meal *hp, unsigned long tregs)
+static int try_next_permutation(struct happy_meal *hp, void __iomem *tregs)
 {
 	hp->sw_bmcr = happy_meal_tcvr_read(hp, tregs, MII_BMCR);
 
@@ -603,7 +603,7 @@
 	return -1;
 }
 
-static void display_link_mode(struct happy_meal *hp, unsigned long tregs)
+static void display_link_mode(struct happy_meal *hp, void __iomem *tregs)
 {
 	printk(KERN_INFO "%s: Link is up using ", hp->dev->name);
 	if (hp->tcvr_type == external)
@@ -625,7 +625,7 @@
 	}
 }
 
-static void display_forced_link_mode(struct happy_meal *hp, unsigned long tregs)
+static void display_forced_link_mode(struct happy_meal *hp, void __iomem *tregs)
 {
 	printk(KERN_INFO "%s: Link has been forced up using ", hp->dev->name);
 	if (hp->tcvr_type == external)
@@ -644,7 +644,7 @@
 		printk("Half Duplex.\n");
 }
 
-static int set_happy_link_modes(struct happy_meal *hp, unsigned long tregs)
+static int set_happy_link_modes(struct happy_meal *hp, void __iomem *tregs)
 {
 	int full;
 
@@ -708,7 +708,7 @@
 
 static int is_lucent_phy(struct happy_meal *hp)
 {
-	unsigned long tregs = hp->tcvregs;
+	void __iomem *tregs = hp->tcvregs;
 	unsigned short mr2, mr3;
 	int ret = 0;
 
@@ -724,7 +724,7 @@
 static void happy_meal_timer(unsigned long data)
 {
 	struct happy_meal *hp = (struct happy_meal *) data;
-	unsigned long tregs = hp->tcvregs;
+	void __iomem *tregs = hp->tcvregs;
 	int restart_timer = 0;
 
 	spin_lock_irq(&hp->happy_lock);
@@ -905,7 +905,7 @@
 #define RX_RESET_TRIES     32
 
 /* hp->happy_lock must be held */
-static void happy_meal_tx_reset(struct happy_meal *hp, unsigned long bregs)
+static void happy_meal_tx_reset(struct happy_meal *hp, void __iomem *bregs)
 {
 	int tries = TX_RESET_TRIES;
 
@@ -925,7 +925,7 @@
 }
 
 /* hp->happy_lock must be held */
-static void happy_meal_rx_reset(struct happy_meal *hp, unsigned long bregs)
+static void happy_meal_rx_reset(struct happy_meal *hp, void __iomem *bregs)
 {
 	int tries = RX_RESET_TRIES;
 
@@ -947,7 +947,7 @@
 #define STOP_TRIES         16
 
 /* hp->happy_lock must be held */
-static void happy_meal_stop(struct happy_meal *hp, unsigned long gregs)
+static void happy_meal_stop(struct happy_meal *hp, void __iomem *gregs)
 {
 	int tries = STOP_TRIES;
 
@@ -967,7 +967,7 @@
 }
 
 /* hp->happy_lock must be held */
-static void happy_meal_get_counters(struct happy_meal *hp, unsigned long bregs)
+static void happy_meal_get_counters(struct happy_meal *hp, void __iomem *bregs)
 {
 	struct net_device_stats *stats = &hp->net_stats;
 
@@ -990,7 +990,7 @@
 }
 
 /* hp->happy_lock must be held */
-static void happy_meal_poll_stop(struct happy_meal *hp, unsigned long tregs)
+static void happy_meal_poll_stop(struct happy_meal *hp, void __iomem *tregs)
 {
 	ASD(("happy_meal_poll_stop: "));
 
@@ -1025,7 +1025,7 @@
 #define TCVR_UNISOLATE_TRIES   32 /* Dis-isolation can take longer. */
 
 /* hp->happy_lock must be held */
-static int happy_meal_tcvr_reset(struct happy_meal *hp, unsigned long tregs)
+static int happy_meal_tcvr_reset(struct happy_meal *hp, void __iomem *tregs)
 {
 	u32 tconfig;
 	int result, tries = TCVR_RESET_TRIES;
@@ -1123,7 +1123,7 @@
  *
  * hp->happy_lock must be held
  */
-static void happy_meal_transceiver_check(struct happy_meal *hp, unsigned long tregs)
+static void happy_meal_transceiver_check(struct happy_meal *hp, void __iomem *tregs)
 {
 	unsigned long tconfig = hme_read32(hp, tregs + TCVR_CFG);
 
@@ -1318,7 +1318,7 @@
 
 /* hp->happy_lock must be held */
 static void happy_meal_begin_auto_negotiation(struct happy_meal *hp,
-					      unsigned long tregs,
+					      void __iomem *tregs,
 					      struct ethtool_cmd *ep)
 {
 	int timeout;
@@ -1443,11 +1443,11 @@
 /* hp->happy_lock must be held */
 static int happy_meal_init(struct happy_meal *hp)
 {
-	unsigned long gregs        = hp->gregs;
-	unsigned long etxregs      = hp->etxregs;
-	unsigned long erxregs      = hp->erxregs;
-	unsigned long bregs        = hp->bigmacregs;
-	unsigned long tregs        = hp->tcvregs;
+	void __iomem *gregs        = hp->gregs;
+	void __iomem *etxregs      = hp->etxregs;
+	void __iomem *erxregs      = hp->erxregs;
+	void __iomem *bregs        = hp->bigmacregs;
+	void __iomem *tregs        = hp->tcvregs;
 	u32 regtmp, rxcfg;
 	unsigned char *e = &hp->dev->dev_addr[0];
 
@@ -1736,9 +1736,9 @@
 /* hp->happy_lock must be held */
 static void happy_meal_set_initial_advertisement(struct happy_meal *hp)
 {
-	unsigned long tregs	= hp->tcvregs;
-	unsigned long bregs	= hp->bigmacregs;
-	unsigned long gregs	= hp->gregs;
+	void __iomem *tregs	= hp->tcvregs;
+	void __iomem *bregs	= hp->bigmacregs;
+	void __iomem *gregs	= hp->gregs;
 
 	happy_meal_stop(hp, gregs);
 	hme_write32(hp, tregs + TCVR_IMASK, 0xffff);
@@ -1910,7 +1910,7 @@
 /* hp->happy_lock must be held */
 static void happy_meal_mif_interrupt(struct happy_meal *hp)
 {
-	unsigned long tregs = hp->tcvregs;
+	void __iomem *tregs = hp->tcvregs;
 
 	printk(KERN_INFO "%s: Link status change.\n", hp->dev->name);
 	hp->sw_bmcr = happy_meal_tcvr_read(hp, tregs, MII_BMCR);
@@ -2390,7 +2390,7 @@
 static void happy_meal_set_multicast(struct net_device *dev)
 {
 	struct happy_meal *hp = dev->priv;
-	unsigned long bregs = hp->bigmacregs;
+	void __iomem *bregs = hp->bigmacregs;
 	struct dev_mc_list *dmi = dev->mc_list;
 	char *addrs;
 	int i;
@@ -3025,7 +3025,8 @@
 #endif
 	struct happy_meal *hp;
 	struct net_device *dev;
-	unsigned long hpreg_base;
+	void __iomem *hpreg_base;
+	unsigned long hpreg_res;
 	int i, qfe_slot = -1;
 	char prom_name[64];
 	int err;
@@ -3084,7 +3085,7 @@
 		qp->happy_meals[qfe_slot] = dev;
 	}		
 
-	hpreg_base = pci_resource_start(pdev, 0);
+	hpreg_res = pci_resource_start(pdev, 0);
 	err = -ENODEV;
 	if ((pci_resource_flags(pdev, 0) & IORESOURCE_IO) != 0) {
 		printk(KERN_ERR "happymeal(PCI): Cannot find proper PCI device base address.\n");
@@ -3096,7 +3097,7 @@
 		goto err_out_clear_quattro;
 	}
 
-	if ((hpreg_base = (unsigned long) ioremap(hpreg_base, 0x8000)) == 0) {
+	if ((hpreg_base = ioremap(hpreg_res, 0x8000)) == 0) {
 		printk(KERN_ERR "happymeal(PCI): Unable to remap card memory.\n");
 		goto err_out_free_res;
 	}
diff -Nru a/drivers/net/sunhme.h b/drivers/net/sunhme.h
--- a/drivers/net/sunhme.h	2004-10-18 14:56:29 -07:00
+++ b/drivers/net/sunhme.h	2004-10-18 14:56:29 -07:00
@@ -397,7 +397,7 @@
 
 /* Happy happy, joy joy! */
 struct happy_meal {
-	unsigned long	gregs;			/* Happy meal global registers       */
+	void __iomem	*gregs;			/* Happy meal global registers       */
 	struct hmeal_init_block  *happy_block;	/* RX and TX descriptors (CPU addr)  */
 
 #if defined(CONFIG_SBUS) && defined(CONFIG_PCI)
@@ -423,14 +423,14 @@
 	struct net_device_stats	  net_stats;      /* Statistical counters              */
 
 #if defined(CONFIG_SBUS) && defined(CONFIG_PCI)
-	u32 (*read32)(unsigned long);
-	void (*write32)(unsigned long, u32);
+	u32 (*read32)(void __iomem *);
+	void (*write32)(void __iomem *, u32);
 #endif
 
-	unsigned long	etxregs;        /* External transmitter regs         */
-	unsigned long	erxregs;        /* External receiver regs            */
-	unsigned long	bigmacregs;     /* BIGMAC core regs		     */
-	unsigned long	tcvregs;        /* MIF transceiver regs              */
+	void __iomem	*etxregs;        /* External transmitter regs        */
+	void __iomem	*erxregs;        /* External receiver regs           */
+	void __iomem	*bigmacregs;     /* BIGMAC core regs		     */
+	void __iomem	*tcvregs;        /* MIF transceiver regs             */
 
 	dma_addr_t                hblock_dvma;    /* DVMA visible address happy block  */
 	unsigned int              happy_flags;    /* Driver state flags                */
diff -Nru a/drivers/net/sunlance.c b/drivers/net/sunlance.c
--- a/drivers/net/sunlance.c	2004-10-18 14:56:27 -07:00
+++ b/drivers/net/sunlance.c	2004-10-18 14:56:27 -07:00
@@ -230,9 +230,9 @@
 ((__u32)(((unsigned long)(&(((struct lance_init_block *)0)->rt[elem][0])))))
 
 struct lance_private {
-	unsigned long	lregs;		/* Lance RAP/RDP regs.		*/
-	unsigned long	dregs;		/* DMA controller regs.		*/
-	volatile struct lance_init_block *init_block;
+	void __iomem	*lregs;		/* Lance RAP/RDP regs.		*/
+	void __iomem	*dregs;		/* DMA controller regs.		*/
+	struct lance_init_block *init_block;
     
 	spinlock_t	lock;
 
@@ -270,7 +270,7 @@
 #define LANCE_REG_SIZE	0x04UL
 
 #define STOP_LANCE(__lp) \
-do {	unsigned long __base = (__lp)->lregs; \
+do {	void __iomem *__base = (__lp)->lregs; \
 	sbus_writew(LE_CSR0,	__base + RAP); \
 	sbus_writew(LE_C0_STOP,	__base + RDP); \
 } while (0)
@@ -314,7 +314,7 @@
 static void lance_init_ring_dvma(struct net_device *dev)
 {
 	struct lance_private *lp = netdev_priv(dev);
-	volatile struct lance_init_block *ib = lp->init_block;
+	struct lance_init_block *ib = lp->init_block;
 	dma_addr_t aib = lp->init_block_dvma;
 	__u32 leptr;
 	int i;
@@ -371,7 +371,7 @@
 static void lance_init_ring_pio(struct net_device *dev)
 {
 	struct lance_private *lp = netdev_priv(dev);
-	volatile struct lance_init_block *ib = lp->init_block;
+	struct lance_init_block *ib = lp->init_block;
 	u32 leptr;
 	int i;
     
@@ -501,8 +501,8 @@
 static void lance_rx_dvma(struct net_device *dev)
 {
 	struct lance_private *lp = netdev_priv(dev);
-	volatile struct lance_init_block *ib = lp->init_block;
-	volatile struct lance_rx_desc *rd;
+	struct lance_init_block *ib = lp->init_block;
+	struct lance_rx_desc *rd;
 	u8 bits;
 	int len, entry = lp->rx_new;
 	struct sk_buff *skb;
@@ -564,14 +564,14 @@
 static void lance_tx_dvma(struct net_device *dev)
 {
 	struct lance_private *lp = netdev_priv(dev);
-	volatile struct lance_init_block *ib = lp->init_block;
+	struct lance_init_block *ib = lp->init_block;
 	int i, j;
 
 	spin_lock(&lp->lock);
 
 	j = lp->tx_old;
 	for (i = j; i != lp->tx_new; i = j) {
-		volatile struct lance_tx_desc *td = &ib->btx_ring [i];
+		struct lance_tx_desc *td = &ib->btx_ring [i];
 		u8 bits = td->tmd1_bits;
 
 		/* If we hit a packet not owned by us, stop */
@@ -641,12 +641,12 @@
 	spin_unlock(&lp->lock);
 }
 
-static void lance_piocopy_to_skb(struct sk_buff *skb, volatile void *piobuf, int len)
+static void lance_piocopy_to_skb(struct sk_buff *skb, void __iomem *piobuf, int len)
 {
 	u16 *p16 = (u16 *) skb->data;
 	u32 *p32;
 	u8 *p8;
-	unsigned long pbuf = (unsigned long) piobuf;
+	void __iomem *pbuf = piobuf;
 
 	/* We know here that both src and dest are on a 16bit boundary. */
 	*p16++ = sbus_readw(pbuf);
@@ -674,8 +674,8 @@
 static void lance_rx_pio(struct net_device *dev)
 {
 	struct lance_private *lp = netdev_priv(dev);
-	volatile struct lance_init_block *ib = lp->init_block;
-	volatile struct lance_rx_desc *rd;
+	struct lance_init_block *ib = lp->init_block;
+	struct lance_rx_desc *rd;
 	unsigned char bits;
 	int len, entry;
 	struct sk_buff *skb;
@@ -736,14 +736,14 @@
 static void lance_tx_pio(struct net_device *dev)
 {
 	struct lance_private *lp = netdev_priv(dev);
-	volatile struct lance_init_block *ib = lp->init_block;
+	struct lance_init_block *ib = lp->init_block;
 	int i, j;
 
 	spin_lock(&lp->lock);
 
 	j = lp->tx_old;
 	for (i = j; i != lp->tx_new; i = j) {
-		volatile struct lance_tx_desc *td = &ib->btx_ring [i];
+		struct lance_tx_desc *td = &ib->btx_ring [i];
 		u8 bits = sbus_readb(&td->tmd1_bits);
 
 		/* If we hit a packet not owned by us, stop */
@@ -880,7 +880,7 @@
 static void build_fake_packet(struct lance_private *lp)
 {
 	struct net_device *dev = lp->dev;
-	volatile struct lance_init_block *ib = lp->init_block;
+	struct lance_init_block *ib = lp->init_block;
 	u16 *packet;
 	struct ethhdr *eth;
 	int i, entry;
@@ -916,7 +916,7 @@
 static int lance_open(struct net_device *dev)
 {
 	struct lance_private *lp = netdev_priv(dev);
-	volatile struct lance_init_block *ib = lp->init_block;
+	struct lance_init_block *ib = lp->init_block;
 	int status = 0;
 
 	last_dev = dev;
@@ -1006,9 +1006,9 @@
 	return status;
 }
 
-static void lance_piocopy_from_skb(volatile void *dest, unsigned char *src, int len)
+static void lance_piocopy_from_skb(void __iomem *dest, unsigned char *src, int len)
 {
-	unsigned long piobuf = (unsigned long) dest;
+	void __iomem *piobuf = dest;
 	u32 *p32;
 	u16 *p16;
 	u8 *p8;
@@ -1064,11 +1064,11 @@
 		sbus_writeb(src[0], piobuf);
 }
 
-static void lance_piozero(volatile void *dest, int len)
+static void lance_piozero(void __iomem *dest, int len)
 {
-	unsigned long piobuf = (unsigned long) dest;
+	void __iomem *piobuf = dest;
 
-	if (piobuf & 1) {
+	if ((unsigned long)piobuf & 1) {
 		sbus_writeb(0, piobuf);
 		piobuf += 1;
 		len -= 1;
@@ -1079,7 +1079,7 @@
 		sbus_writeb(0, piobuf);
 		return;
 	}
-	if (piobuf & 2) {
+	if ((unsigned long)piobuf & 2) {
 		sbus_writew(0, piobuf);
 		piobuf += 2;
 		len -= 2;
@@ -1113,7 +1113,7 @@
 static int lance_start_xmit(struct sk_buff *skb, struct net_device *dev)
 {
 	struct lance_private *lp = netdev_priv(dev);
-	volatile struct lance_init_block *ib = lp->init_block;
+	struct lance_init_block *ib = lp->init_block;
 	int entry, skblen, len;
 
 	skblen = skb->len;
@@ -1174,8 +1174,8 @@
 static void lance_load_multicast(struct net_device *dev)
 {
 	struct lance_private *lp = netdev_priv(dev);
-	volatile struct lance_init_block *ib = lp->init_block;
-	volatile u16 *mcast_table = (u16 *) &ib->filter;
+	struct lance_init_block *ib = lp->init_block;
+	u16 *mcast_table = (u16 *) &ib->filter;
 	struct dev_mc_list *dmi = dev->mc_list;
 	char *addrs;
 	int i;
@@ -1224,7 +1224,7 @@
 static void lance_set_multicast(struct net_device *dev)
 {
 	struct lance_private *lp = netdev_priv(dev);
-	volatile struct lance_init_block *ib = lp->init_block;
+	struct lance_init_block *ib = lp->init_block;
 	u16 mode;
 
 	if (!netif_running(dev))
@@ -1277,12 +1277,12 @@
 		sbus_iounmap(lp->lregs, LANCE_REG_SIZE);
 	if (lp->init_block != NULL) {
 		if (lp->pio_buffer) {
-			sbus_iounmap((unsigned long)lp->init_block,
+			sbus_iounmap(lp->init_block,
 				     sizeof(struct lance_init_block));
 		} else {
 			sbus_free_consistent(lp->sdev,
 					     sizeof(struct lance_init_block),
-					     (void *)lp->init_block,
+					     lp->init_block,
 					     lp->init_block_dvma);
 		}
 	}
@@ -1349,7 +1349,7 @@
 
 	lp->sdev = sdev;
 	if (lebuffer) {
-		lp->init_block = (volatile struct lance_init_block *)
+		lp->init_block =
 			sbus_ioremap(&lebuffer->resource[0], 0,
 				     sizeof(struct lance_init_block), "lebuffer");
 		if (lp->init_block == NULL) {
@@ -1362,7 +1362,7 @@
 		lp->rx = lance_rx_pio;
 		lp->tx = lance_tx_pio;
 	} else {
-		lp->init_block = (volatile struct lance_init_block *)
+		lp->init_block =
 			sbus_alloc_consistent(sdev, sizeof(struct lance_init_block),
 					      &lp->init_block_dvma);
 		if (lp->init_block == NULL ||
diff -Nru a/drivers/net/sunqe.c b/drivers/net/sunqe.c
--- a/drivers/net/sunqe.c	2004-10-18 14:56:28 -07:00
+++ b/drivers/net/sunqe.c	2004-10-18 14:56:28 -07:00
@@ -49,7 +49,7 @@
 
 #define QEC_RESET_TRIES 200
 
-static inline int qec_global_reset(unsigned long gregs)
+static inline int qec_global_reset(void __iomem *gregs)
 {
 	int tries = QEC_RESET_TRIES;
 
@@ -73,8 +73,8 @@
 
 static inline int qe_stop(struct sunqe *qep)
 {
-	unsigned long cregs = qep->qcregs;
-	unsigned long mregs = qep->mregs;
+	void __iomem *cregs = qep->qcregs;
+	void __iomem *mregs = qep->mregs;
 	int tries;
 
 	/* Reset the MACE, then the QEC channel. */
@@ -130,9 +130,9 @@
 static int qe_init(struct sunqe *qep, int from_irq)
 {
 	struct sunqec *qecp = qep->parent;
-	unsigned long cregs = qep->qcregs;
-	unsigned long mregs = qep->mregs;
-	unsigned long gregs = qecp->gregs;
+	void __iomem *cregs = qep->qcregs;
+	void __iomem *mregs = qep->mregs;
+	void __iomem *gregs = qecp->gregs;
 	unsigned char *e = &qep->dev->dev_addr[0];
 	u32 tmp;
 	int i;
@@ -699,7 +699,7 @@
 static u32 qe_get_link(struct net_device *dev)
 {
 	struct sunqe *qep = dev->priv;
-	unsigned long mregs = qep->mregs;
+	void __iomem *mregs = qep->mregs;
 	u8 phyconfig;
 
 	spin_lock_irq(&qep->lock);
diff -Nru a/drivers/net/sunqe.h b/drivers/net/sunqe.h
--- a/drivers/net/sunqe.h	2004-10-18 14:55:46 -07:00
+++ b/drivers/net/sunqe.h	2004-10-18 14:55:46 -07:00
@@ -311,7 +311,7 @@
 struct sunqe;
 
 struct sunqec {
-	unsigned long		gregs;		/* QEC Global Registers         */
+	void __iomem		*gregs;		/* QEC Global Registers         */
 	struct sunqe		*qes[4];	/* Each child MACE              */
 	unsigned int            qec_bursts;	/* Support burst sizes          */
 	struct sbus_dev		*qec_sdev;	/* QEC's SBUS device            */
@@ -331,8 +331,8 @@
 ((__u32)((unsigned long)(&(((struct sunqe_buffers *)0)->mem[elem][0]))))
 
 struct sunqe {
-	unsigned long			qcregs;		/* QEC per-channel Registers   */
-	unsigned long			mregs;		/* Per-channel MACE Registers  */
+	void __iomem			*qcregs;		/* QEC per-channel Registers   */
+	void __iomem			*mregs;		/* Per-channel MACE Registers  */
 	struct qe_init_block      	*qe_block;	/* RX and TX descriptors       */
 	__u32                      	qblock_dvma;	/* RX and TX descriptors       */
 	spinlock_t			lock;		/* Protects txfull state       */
diff -Nru a/drivers/net/tg3.c b/drivers/net/tg3.c
--- a/drivers/net/tg3.c	2004-10-18 14:56:32 -07:00
+++ b/drivers/net/tg3.c	2004-10-18 14:56:32 -07:00
@@ -4,6 +4,9 @@
  * Copyright (C) 2001, 2002, 2003, 2004 David S. Miller (davem@redhat.com)
  * Copyright (C) 2001, 2002, 2003 Jeff Garzik (jgarzik@pobox.com)
  * Copyright (C) 2004 Sun Microsystems Inc.
+ *
+ * Firmware is:
+ * 	Copyright (C) 2000-2003 Broadcom Corporation.
  */
 
 #include <linux/config.h>
@@ -57,8 +60,8 @@
 
 #define DRV_MODULE_NAME		"tg3"
 #define PFX DRV_MODULE_NAME	": "
-#define DRV_MODULE_VERSION	"3.8"
-#define DRV_MODULE_RELDATE	"July 14, 2004"
+#define DRV_MODULE_VERSION	"3.10"
+#define DRV_MODULE_RELDATE	"September 14, 2004"
 
 #define TG3_DEF_MAC_MODE	0
 #define TG3_DEF_RX_MODE		0
@@ -328,7 +331,7 @@
 		pci_write_config_dword(tp->pdev, TG3PCI_REG_DATA, val);
 		spin_unlock_irqrestore(&tp->indirect_lock, flags);
 	} else {
-		unsigned long dest = tp->regs + off;
+		void __iomem *dest = tp->regs + off;
 		writel(val, dest);
 		readl(dest);    /* always flush PCI write */
 	}
@@ -336,7 +339,7 @@
 
 static inline void _tw32_rx_mbox(struct tg3 *tp, u32 off, u32 val)
 {
-	unsigned long mbox = tp->regs + off;
+	void __iomem *mbox = tp->regs + off;
 	writel(val, mbox);
 	if (tp->tg3_flags & TG3_FLAG_MBOX_WRITE_REORDER)
 		readl(mbox);
@@ -344,7 +347,7 @@
 
 static inline void _tw32_tx_mbox(struct tg3 *tp, u32 off, u32 val)
 {
-	unsigned long mbox = tp->regs + off;
+	void __iomem *mbox = tp->regs + off;
 	writel(val, mbox);
 	if (tp->tg3_flags & TG3_FLAG_TXD_MBOX_HWBUG)
 		writel(val, mbox);
@@ -442,9 +445,14 @@
 		       0x1f);
 	tp->pci_clock_ctrl = clock_ctrl;
 
-	if (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5705 &&
-	    GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5750 &&
-	    (orig_clock_ctrl & CLOCK_CTRL_44MHZ_CORE) != 0) {
+	if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5705 ||
+	    GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5750) {
+		if (orig_clock_ctrl & CLOCK_CTRL_625_CORE) {
+			tw32_f(TG3PCI_CLOCK_CTRL,
+			       clock_ctrl | CLOCK_CTRL_625_CORE);
+			udelay(40);
+		}
+	} else if ((orig_clock_ctrl & CLOCK_CTRL_44MHZ_CORE) != 0) {
 		tw32_f(TG3PCI_CLOCK_CTRL,
 		     clock_ctrl |
 		     (CLOCK_CTRL_44MHZ_CORE | CLOCK_CTRL_ALTCLK));
@@ -980,7 +988,7 @@
 		tp->link_config.orig_autoneg = tp->link_config.autoneg;
 	}
 
-	if (tp->phy_id != PHY_ID_SERDES) {
+	if (!(tp->tg3_flags2 & TG3_FLG2_PHY_SERDES)) {
 		tp->link_config.speed = SPEED_10;
 		tp->link_config.duplex = DUPLEX_HALF;
 		tp->link_config.autoneg = AUTONEG_ENABLE;
@@ -992,7 +1000,7 @@
 	if (tp->tg3_flags & TG3_FLAG_WOL_ENABLE) {
 		u32 mac_mode;
 
-		if (tp->phy_id != PHY_ID_SERDES) {
+		if (!(tp->tg3_flags2 & TG3_FLG2_PHY_SERDES)) {
 			tg3_writephy(tp, MII_TG3_AUX_CTRL, 0x5a);
 			udelay(40);
 
@@ -1114,29 +1122,33 @@
 	u32 old_rx_mode = tp->rx_mode;
 	u32 old_tx_mode = tp->tx_mode;
 
-	if (local_adv & ADVERTISE_PAUSE_CAP) {
-		if (local_adv & ADVERTISE_PAUSE_ASYM) {
-			if (remote_adv & LPA_PAUSE_CAP)
-				new_tg3_flags |=
-					(TG3_FLAG_RX_PAUSE |
-					 TG3_FLAG_TX_PAUSE);
-			else if (remote_adv & LPA_PAUSE_ASYM)
-				new_tg3_flags |=
-					(TG3_FLAG_RX_PAUSE);
-		} else {
-			if (remote_adv & LPA_PAUSE_CAP)
-				new_tg3_flags |=
-					(TG3_FLAG_RX_PAUSE |
-					 TG3_FLAG_TX_PAUSE);
+	if (tp->tg3_flags & TG3_FLAG_PAUSE_AUTONEG) {
+		if (local_adv & ADVERTISE_PAUSE_CAP) {
+			if (local_adv & ADVERTISE_PAUSE_ASYM) {
+				if (remote_adv & LPA_PAUSE_CAP)
+					new_tg3_flags |=
+						(TG3_FLAG_RX_PAUSE |
+					 	TG3_FLAG_TX_PAUSE);
+				else if (remote_adv & LPA_PAUSE_ASYM)
+					new_tg3_flags |=
+						(TG3_FLAG_RX_PAUSE);
+			} else {
+				if (remote_adv & LPA_PAUSE_CAP)
+					new_tg3_flags |=
+						(TG3_FLAG_RX_PAUSE |
+					 	TG3_FLAG_TX_PAUSE);
+			}
+		} else if (local_adv & ADVERTISE_PAUSE_ASYM) {
+			if ((remote_adv & LPA_PAUSE_CAP) &&
+		    	(remote_adv & LPA_PAUSE_ASYM))
+				new_tg3_flags |= TG3_FLAG_TX_PAUSE;
 		}
-	} else if (local_adv & ADVERTISE_PAUSE_ASYM) {
-		if ((remote_adv & LPA_PAUSE_CAP) &&
-		    (remote_adv & LPA_PAUSE_ASYM))
-			new_tg3_flags |= TG3_FLAG_TX_PAUSE;
-	}
 
-	tp->tg3_flags &= ~(TG3_FLAG_RX_PAUSE | TG3_FLAG_TX_PAUSE);
-	tp->tg3_flags |= new_tg3_flags;
+		tp->tg3_flags &= ~(TG3_FLAG_RX_PAUSE | TG3_FLAG_TX_PAUSE);
+		tp->tg3_flags |= new_tg3_flags;
+	} else {
+		new_tg3_flags = tp->tg3_flags;
+	}
 
 	if (new_tg3_flags & TG3_FLAG_RX_PAUSE)
 		tp->rx_mode |= RX_MODE_FLOW_CTRL_ENABLE;
@@ -1487,6 +1499,18 @@
 	current_speed = SPEED_INVALID;
 	current_duplex = DUPLEX_INVALID;
 
+	if (tp->tg3_flags2 & TG3_FLG2_CAPACITIVE_COUPLING) {
+		u32 val;
+
+		tg3_writephy(tp, MII_TG3_AUX_CTRL, 0x4007);
+		tg3_readphy(tp, MII_TG3_AUX_CTRL, &val);
+		if (!(val & (1 << 10))) {
+			val |= (1 << 10);
+			tg3_writephy(tp, MII_TG3_AUX_CTRL, val);
+			goto relink;
+		}
+	}
+
 	bmsr = 0;
 	for (i = 0; i < 100; i++) {
 		tg3_readphy(tp, MII_BMSR, &bmsr);
@@ -1566,7 +1590,7 @@
 			tg3_setup_flow_control(tp, local_adv, remote_adv);
 		}
 	}
-
+relink:
 	if (current_link_up == 0) {
 		u32 tmp;
 
@@ -1616,7 +1640,7 @@
 	tw32_f(MAC_MODE, tp->mac_mode);
 	udelay(40);
 
-	if (tp->tg3_flags & (TG3_FLAG_USE_LINKCHG_REG | TG3_FLAG_POLL_SERDES)) {
+	if (tp->tg3_flags & TG3_FLAG_USE_LINKCHG_REG) {
 		/* Polled via timer. */
 		tw32_f(MAC_EVENT, 0);
 	} else {
@@ -1965,62 +1989,264 @@
 static int fiber_autoneg(struct tg3 *tp, u32 *flags)
 {
 	int res = 0;
+	struct tg3_fiber_aneginfo aninfo;
+	int status = ANEG_FAILED;
+	unsigned int tick;
+	u32 tmp;
 
-	if (tp->tg3_flags2 & TG3_FLG2_HW_AUTONEG) {
-		u32 dig_status;
+	tw32_f(MAC_TX_AUTO_NEG, 0);
 
-		dig_status = tr32(SG_DIG_STATUS);
-		*flags = 0;
-		if (dig_status & SG_DIG_PARTNER_ASYM_PAUSE)
-			*flags |= MR_LP_ADV_ASYM_PAUSE;
-		if (dig_status & SG_DIG_PARTNER_PAUSE_CAPABLE)
-			*flags |= MR_LP_ADV_SYM_PAUSE;
-
-		if ((dig_status & SG_DIG_AUTONEG_COMPLETE) &&
-		    !(dig_status & (SG_DIG_AUTONEG_ERROR |
-				    SG_DIG_PARTNER_FAULT_MASK)))
-			res = 1;
-	} else {
-		struct tg3_fiber_aneginfo aninfo;
-		int status = ANEG_FAILED;
-		unsigned int tick;
-		u32 tmp;
+	tmp = tp->mac_mode & ~MAC_MODE_PORT_MODE_MASK;
+	tw32_f(MAC_MODE, tmp | MAC_MODE_PORT_MODE_GMII);
+	udelay(40);
 
-		tw32_f(MAC_TX_AUTO_NEG, 0);
+	tw32_f(MAC_MODE, tp->mac_mode | MAC_MODE_SEND_CONFIGS);
+	udelay(40);
 
-		tmp = tp->mac_mode & ~MAC_MODE_PORT_MODE_MASK;
-		tw32_f(MAC_MODE, tmp | MAC_MODE_PORT_MODE_GMII);
-		udelay(40);
+	memset(&aninfo, 0, sizeof(aninfo));
+	aninfo.flags |= MR_AN_ENABLE;
+	aninfo.state = ANEG_STATE_UNKNOWN;
+	aninfo.cur_time = 0;
+	tick = 0;
+	while (++tick < 195000) {
+		status = tg3_fiber_aneg_smachine(tp, &aninfo);
+		if (status == ANEG_DONE || status == ANEG_FAILED)
+			break;
 
-		tw32_f(MAC_MODE, tp->mac_mode | MAC_MODE_SEND_CONFIGS);
-		udelay(40);
+		udelay(1);
+	}
 
-		memset(&aninfo, 0, sizeof(aninfo));
-		aninfo.flags |= MR_AN_ENABLE;
-		aninfo.state = ANEG_STATE_UNKNOWN;
-		aninfo.cur_time = 0;
-		tick = 0;
-		while (++tick < 195000) {
-			status = tg3_fiber_aneg_smachine(tp, &aninfo);
-			if (status == ANEG_DONE || status == ANEG_FAILED)
-				break;
+	tp->mac_mode &= ~MAC_MODE_SEND_CONFIGS;
+	tw32_f(MAC_MODE, tp->mac_mode);
+	udelay(40);
 
-			udelay(1);
+	*flags = aninfo.flags;
+
+	if (status == ANEG_DONE &&
+	    (aninfo.flags & (MR_AN_COMPLETE | MR_LINK_OK |
+			     MR_LP_ADV_FULL_DUPLEX)))
+		res = 1;
+
+	return res;
+}
+
+static void tg3_init_bcm8002(struct tg3 *tp)
+{
+	u32 mac_status = tr32(MAC_STATUS);
+	int i;
+
+	/* Reset when initting first time or we have a link. */
+	if ((tp->tg3_flags & TG3_FLAG_INIT_COMPLETE) &&
+	    !(mac_status & MAC_STATUS_PCS_SYNCED))
+		return;
+
+	/* Set PLL lock range. */
+	tg3_writephy(tp, 0x16, 0x8007);
+
+	/* SW reset */
+	tg3_writephy(tp, MII_BMCR, BMCR_RESET);
+
+	/* Wait for reset to complete. */
+	/* XXX schedule_timeout() ... */
+	for (i = 0; i < 500; i++)
+		udelay(10);
+
+	/* Config mode; select PMA/Ch 1 regs. */
+	tg3_writephy(tp, 0x10, 0x8411);
+
+	/* Enable auto-lock and comdet, select txclk for tx. */
+	tg3_writephy(tp, 0x11, 0x0a10);
+
+	tg3_writephy(tp, 0x18, 0x00a0);
+	tg3_writephy(tp, 0x16, 0x41ff);
+
+	/* Assert and deassert POR. */
+	tg3_writephy(tp, 0x13, 0x0400);
+	udelay(40);
+	tg3_writephy(tp, 0x13, 0x0000);
+
+	tg3_writephy(tp, 0x11, 0x0a50);
+	udelay(40);
+	tg3_writephy(tp, 0x11, 0x0a10);
+
+	/* Wait for signal to stabilize */
+	/* XXX schedule_timeout() ... */
+	for (i = 0; i < 15000; i++)
+		udelay(10);
+
+	/* Deselect the channel register so we can read the PHYID
+	 * later.
+	 */
+	tg3_writephy(tp, 0x10, 0x8011);
+}
+
+static int tg3_setup_fiber_hw_autoneg(struct tg3 *tp, u32 mac_status)
+{
+	u32 sg_dig_ctrl, sg_dig_status;
+	u32 serdes_cfg, expected_sg_dig_ctrl;
+	int workaround, port_a;
+	int current_link_up;
+
+	serdes_cfg = 0;
+	expected_sg_dig_ctrl = 0;
+	workaround = 0;
+	port_a = 1;
+	current_link_up = 0;
+
+	if (tp->pci_chip_rev_id != CHIPREV_ID_5704_A0 &&
+	    tp->pci_chip_rev_id != CHIPREV_ID_5704_A1) {
+		workaround = 1;
+		if (tr32(TG3PCI_DUAL_MAC_CTRL) & DUAL_MAC_CTRL_ID)
+			port_a = 0;
+
+		serdes_cfg = tr32(MAC_SERDES_CFG) &
+			((1 << 23) | (1 << 22) | (1 << 21) | (1 << 20));
+	}
+
+	sg_dig_ctrl = tr32(SG_DIG_CTRL);
+
+	if (tp->link_config.autoneg != AUTONEG_ENABLE) {
+		if (sg_dig_ctrl & (1 << 31)) {
+			if (workaround) {
+				u32 val = serdes_cfg;
+
+				if (port_a)
+					val |= 0xc010880;
+				else
+					val |= 0x4010880;
+				tw32_f(MAC_SERDES_CFG, val);
+			}
+			tw32_f(SG_DIG_CTRL, 0x01388400);
 		}
+		if (mac_status & MAC_STATUS_PCS_SYNCED) {
+			tg3_setup_flow_control(tp, 0, 0);
+			current_link_up = 1;
+		}
+		goto out;
+	}
 
-		tp->mac_mode &= ~MAC_MODE_SEND_CONFIGS;
-		tw32_f(MAC_MODE, tp->mac_mode);
-		udelay(40);
+	/* Want auto-negotiation.  */
+	expected_sg_dig_ctrl = 0x81388400;
+
+	/* Pause capability */
+	expected_sg_dig_ctrl |= (1 << 11);
+
+	/* Asymettric pause */
+	expected_sg_dig_ctrl |= (1 << 12);
+
+	if (sg_dig_ctrl != expected_sg_dig_ctrl) {
+		if (workaround)
+			tw32_f(MAC_SERDES_CFG, serdes_cfg | 0xc011880);
+		tw32_f(SG_DIG_CTRL, expected_sg_dig_ctrl | (1 << 30));
+		udelay(5);
+		tw32_f(SG_DIG_CTRL, expected_sg_dig_ctrl);
+
+		tp->tg3_flags2 |= TG3_FLG2_PHY_JUST_INITTED;
+	} else if (mac_status & (MAC_STATUS_PCS_SYNCED |
+				 MAC_STATUS_SIGNAL_DET)) {
+		sg_dig_status = tr32(SG_DIG_STATUS);
+
+		if ((sg_dig_status & (1 << 1)) &&
+		    (mac_status & MAC_STATUS_PCS_SYNCED)) {
+			u32 local_adv, remote_adv;
+
+			local_adv = ADVERTISE_PAUSE_CAP;
+			remote_adv = 0;
+			if (sg_dig_status & (1 << 19))
+				remote_adv |= LPA_PAUSE_CAP;
+			if (sg_dig_status & (1 << 20))
+				remote_adv |= LPA_PAUSE_ASYM;
+
+			tg3_setup_flow_control(tp, local_adv, remote_adv);
+			current_link_up = 1;
+			tp->tg3_flags2 &= ~TG3_FLG2_PHY_JUST_INITTED;
+		} else if (!(sg_dig_status & (1 << 1))) {
+			if (tp->tg3_flags2 & TG3_FLG2_PHY_JUST_INITTED)
+				tp->tg3_flags2 &= ~TG3_FLG2_PHY_JUST_INITTED;
+			else {
+				if (workaround) {
+					u32 val = serdes_cfg;
+
+					if (port_a)
+						val |= 0xc010880;
+					else
+						val |= 0x4010880;
 
-		*flags = aninfo.flags;
+					tw32_f(MAC_SERDES_CFG, val);
+				}
 
-		if (status == ANEG_DONE &&
-		    (aninfo.flags & (MR_AN_COMPLETE | MR_LINK_OK |
-				     MR_LP_ADV_FULL_DUPLEX)))
-			res = 1;
+				tw32_f(SG_DIG_CTRL, 0x01388400);
+				udelay(40);
+
+				mac_status = tr32(MAC_STATUS);
+				if (mac_status & MAC_STATUS_PCS_SYNCED) {
+					tg3_setup_flow_control(tp, 0, 0);
+					current_link_up = 1;
+				}
+			}
+		}
 	}
 
-	return res;
+out:
+	return current_link_up;
+}
+
+static int tg3_setup_fiber_by_hand(struct tg3 *tp, u32 mac_status)
+{
+	int current_link_up = 0;
+
+ 	if (!(mac_status & MAC_STATUS_PCS_SYNCED)) {
+		tp->tg3_flags &= ~TG3_FLAG_GOT_SERDES_FLOWCTL;
+		goto out;
+	}
+
+	if (tp->link_config.autoneg == AUTONEG_ENABLE) {
+		u32 flags;
+		int i;
+  
+		if (fiber_autoneg(tp, &flags)) {
+			u32 local_adv, remote_adv;
+
+			local_adv = ADVERTISE_PAUSE_CAP;
+			remote_adv = 0;
+			if (flags & MR_LP_ADV_SYM_PAUSE)
+				remote_adv |= LPA_PAUSE_CAP;
+			if (flags & MR_LP_ADV_ASYM_PAUSE)
+				remote_adv |= LPA_PAUSE_ASYM;
+
+			tg3_setup_flow_control(tp, local_adv, remote_adv);
+
+			tp->tg3_flags |= TG3_FLAG_GOT_SERDES_FLOWCTL;
+			current_link_up = 1;
+		}
+		for (i = 0; i < 30; i++) {
+			udelay(20);
+			tw32_f(MAC_STATUS,
+			       (MAC_STATUS_SYNC_CHANGED |
+				MAC_STATUS_CFG_CHANGED));
+			udelay(40);
+			if ((tr32(MAC_STATUS) &
+			     (MAC_STATUS_SYNC_CHANGED |
+			      MAC_STATUS_CFG_CHANGED)) == 0)
+				break;
+		}
+
+		mac_status = tr32(MAC_STATUS);
+		if (current_link_up == 0 &&
+		    (mac_status & MAC_STATUS_PCS_SYNCED) &&
+		    !(mac_status & MAC_STATUS_RCVD_CFG))
+			current_link_up = 1;
+	} else {
+		/* Forcing 1000FD link up. */
+		current_link_up = 1;
+		tp->tg3_flags |= TG3_FLAG_GOT_SERDES_FLOWCTL;
+
+		tw32_f(MAC_MODE, (tp->mac_mode | MAC_MODE_SEND_CONFIGS));
+		udelay(40);
+	}
+
+out:
+	return current_link_up;
 }
 
 static int tg3_setup_fiber_phy(struct tg3 *tp, int force_reset)
@@ -2028,6 +2254,7 @@
 	u32 orig_pause_cfg;
 	u16 orig_active_speed;
 	u8 orig_active_duplex;
+	u32 mac_status;
 	int current_link_up;
 	int i;
 
@@ -2037,118 +2264,43 @@
 	orig_active_speed = tp->link_config.active_speed;
 	orig_active_duplex = tp->link_config.active_duplex;
 
-	tp->mac_mode &= ~(MAC_MODE_PORT_MODE_MASK | MAC_MODE_HALF_DUPLEX);
-	tp->mac_mode |= MAC_MODE_PORT_MODE_TBI;
-	tw32_f(MAC_MODE, tp->mac_mode);
-	udelay(40);
-
-	if (tp->tg3_flags2 & TG3_FLG2_HW_AUTONEG) {
-		/* Allow time for the hardware to auto-negotiate (195ms) */
-		unsigned int tick = 0;
-
-		while (++tick < 195000) { 
-			if (tr32(SG_DIG_STATUS) & SG_DIG_AUTONEG_COMPLETE)
-				break;
-			udelay(1);
+	if (!(tp->tg3_flags2 & TG3_FLG2_HW_AUTONEG) &&
+	    netif_carrier_ok(tp->dev) &&
+	    (tp->tg3_flags & TG3_FLAG_INIT_COMPLETE)) {
+		mac_status = tr32(MAC_STATUS);
+		mac_status &= (MAC_STATUS_PCS_SYNCED |
+			       MAC_STATUS_SIGNAL_DET |
+			       MAC_STATUS_CFG_CHANGED |
+			       MAC_STATUS_RCVD_CFG);
+		if (mac_status == (MAC_STATUS_PCS_SYNCED |
+				   MAC_STATUS_SIGNAL_DET)) {
+			tw32_f(MAC_STATUS, (MAC_STATUS_SYNC_CHANGED |
+					    MAC_STATUS_CFG_CHANGED));
+			return 0;
 		}
-		if (tick >= 195000)
-			printk(KERN_INFO PFX "%s: HW autoneg failed !\n",
-			    tp->dev->name);
 	}
 
-	/* Reset when initting first time or we have a link. */
-	if (!(tp->tg3_flags & TG3_FLAG_INIT_COMPLETE) ||
-	    (tr32(MAC_STATUS) & MAC_STATUS_PCS_SYNCED)) {
-		/* Set PLL lock range. */
-		tg3_writephy(tp, 0x16, 0x8007);
-
-		/* SW reset */
-		tg3_writephy(tp, MII_BMCR, BMCR_RESET);
-
-		/* Wait for reset to complete. */
-		/* XXX schedule_timeout() ... */
-		for (i = 0; i < 500; i++)
-			udelay(10);
-
-		/* Config mode; select PMA/Ch 1 regs. */
-		tg3_writephy(tp, 0x10, 0x8411);
-
-		/* Enable auto-lock and comdet, select txclk for tx. */
-		tg3_writephy(tp, 0x11, 0x0a10);
-
-		tg3_writephy(tp, 0x18, 0x00a0);
-		tg3_writephy(tp, 0x16, 0x41ff);
-
-		/* Assert and deassert POR. */
-		tg3_writephy(tp, 0x13, 0x0400);
-		udelay(40);
-		tg3_writephy(tp, 0x13, 0x0000);
-
-		tg3_writephy(tp, 0x11, 0x0a50);
-		udelay(40);
-		tg3_writephy(tp, 0x11, 0x0a10);
+	tw32_f(MAC_TX_AUTO_NEG, 0);
 
-		/* Wait for signal to stabilize */
-		/* XXX schedule_timeout() ... */
-		for (i = 0; i < 15000; i++)
-			udelay(10);
+	tp->mac_mode &= ~(MAC_MODE_PORT_MODE_MASK | MAC_MODE_HALF_DUPLEX);
+	tp->mac_mode |= MAC_MODE_PORT_MODE_TBI;
+	tw32_f(MAC_MODE, tp->mac_mode);
+	udelay(40);
 
-		/* Deselect the channel register so we can read the PHYID
-		 * later.
-		 */
-		tg3_writephy(tp, 0x10, 0x8011);
-	}
+	if (tp->phy_id == PHY_ID_BCM8002)
+		tg3_init_bcm8002(tp);
 
-	/* Enable link change interrupt unless serdes polling.  */
-	if (!(tp->tg3_flags & TG3_FLAG_POLL_SERDES))
-		tw32_f(MAC_EVENT, MAC_EVENT_LNKSTATE_CHANGED);
-	else
-		tw32_f(MAC_EVENT, 0);
+	/* Enable link change event even when serdes polling.  */
+	tw32_f(MAC_EVENT, MAC_EVENT_LNKSTATE_CHANGED);
 	udelay(40);
 
 	current_link_up = 0;
- 	if (tr32(MAC_STATUS) & MAC_STATUS_PCS_SYNCED) {
-		if (tp->link_config.autoneg == AUTONEG_ENABLE) {
-			u32 flags;
-  
-			if (fiber_autoneg(tp, &flags)) {
-				u32 local_adv, remote_adv;
-
-				local_adv = ADVERTISE_PAUSE_CAP;
-				remote_adv = 0;
-				if (flags & MR_LP_ADV_SYM_PAUSE)
-  					remote_adv |= LPA_PAUSE_CAP;
-				if (flags & MR_LP_ADV_ASYM_PAUSE)
-					remote_adv |= LPA_PAUSE_ASYM;
+	mac_status = tr32(MAC_STATUS);
 
-				tg3_setup_flow_control(tp, local_adv, remote_adv);
-
-				tp->tg3_flags |=
-					TG3_FLAG_GOT_SERDES_FLOWCTL;
-				current_link_up = 1;
-			}
-			for (i = 0; i < 60; i++) {
-				udelay(20);
-				tw32_f(MAC_STATUS,
-				     (MAC_STATUS_SYNC_CHANGED |
-				      MAC_STATUS_CFG_CHANGED));
-				udelay(40);
-				if ((tr32(MAC_STATUS) &
-				     (MAC_STATUS_SYNC_CHANGED |
-				      MAC_STATUS_CFG_CHANGED)) == 0)
-					break;
-			}
-			if (current_link_up == 0 &&
-			    (tr32(MAC_STATUS) & MAC_STATUS_PCS_SYNCED)) {
-				current_link_up = 1;
-			}
-		} else {
-			/* Forcing 1000FD link up. */
-			current_link_up = 1;
-			tp->tg3_flags |= TG3_FLAG_GOT_SERDES_FLOWCTL;
-		}
-	} else
-		tp->tg3_flags &= ~TG3_FLAG_GOT_SERDES_FLOWCTL;
+	if (tp->tg3_flags2 & TG3_FLG2_HW_AUTONEG)
+		current_link_up = tg3_setup_fiber_hw_autoneg(tp, mac_status);
+	else
+		current_link_up = tg3_setup_fiber_by_hand(tp, mac_status);
 
 	tp->mac_mode &= ~MAC_MODE_LINK_POLARITY;
 	tw32_f(MAC_MODE, tp->mac_mode);
@@ -2159,19 +2311,24 @@
 		 (tp->hw_status->status & ~SD_STATUS_LINK_CHG));
 
 	for (i = 0; i < 100; i++) {
-		udelay(20);
-		tw32_f(MAC_STATUS,
-		     (MAC_STATUS_SYNC_CHANGED |
-		      MAC_STATUS_CFG_CHANGED));
-		udelay(40);
-		if ((tr32(MAC_STATUS) &
-		     (MAC_STATUS_SYNC_CHANGED |
-		      MAC_STATUS_CFG_CHANGED)) == 0)
+		tw32_f(MAC_STATUS, (MAC_STATUS_SYNC_CHANGED |
+				    MAC_STATUS_CFG_CHANGED));
+		udelay(5);
+		if ((tr32(MAC_STATUS) & (MAC_STATUS_SYNC_CHANGED |
+					 MAC_STATUS_CFG_CHANGED)) == 0)
 			break;
 	}
 
-	if ((tr32(MAC_STATUS) & MAC_STATUS_PCS_SYNCED) == 0)
+	mac_status = tr32(MAC_STATUS);
+	if ((mac_status & MAC_STATUS_PCS_SYNCED) == 0) {
 		current_link_up = 0;
+		if (tp->link_config.autoneg == AUTONEG_ENABLE) {
+			tw32_f(MAC_MODE, (tp->mac_mode |
+					  MAC_MODE_SEND_CONFIGS));
+			udelay(1);
+			tw32_f(MAC_MODE, tp->mac_mode);
+		}
+	}
 
 	if (current_link_up == 1) {
 		tp->link_config.active_speed = SPEED_1000;
@@ -2203,15 +2360,6 @@
 			tg3_link_report(tp);
 	}
 
-	if ((tr32(MAC_STATUS) & MAC_STATUS_PCS_SYNCED) == 0) {
-		tw32_f(MAC_MODE, tp->mac_mode | MAC_MODE_LINK_POLARITY);
-		udelay(40);
-		if (tp->tg3_flags & TG3_FLAG_INIT_COMPLETE) {
-			tw32_f(MAC_MODE, tp->mac_mode);
-			udelay(40);
-		}
-	}
-
 	return 0;
 }
 
@@ -2219,7 +2367,7 @@
 {
 	int err;
 
-	if (tp->phy_id == PHY_ID_SERDES) {
+	if (tp->tg3_flags2 & TG3_FLG2_PHY_SERDES) {
 		err = tg3_setup_fiber_phy(tp, force_reset);
 	} else {
 		err = tg3_setup_copper_phy(tp, force_reset);
@@ -2738,11 +2886,11 @@
 	tg3_halt(tp);
 	tg3_init_hw(tp);
 
+	tg3_netif_start(tp);
+
 	spin_unlock(&tp->tx_lock);
 	spin_unlock_irq(&tp->lock);
 
-	tg3_netif_start(tp);
-
 	if (restart_timer)
 		mod_timer(&tp->timer, jiffies + 1);
 }
@@ -2812,6 +2960,7 @@
 			dma_addr_t mapping, int len, u32 flags,
 			u32 mss_and_is_end)
 {
+	struct tg3_tx_buffer_desc *txd = &tp->tx_ring[entry];
 	int is_end = (mss_and_is_end & 0x1);
 	u32 mss = (mss_and_is_end >> 1);
 	u32 vlan_tag = 0;
@@ -2823,35 +2972,11 @@
 		flags &= 0xffff;
 	}
 	vlan_tag |= (mss << TXD_MSS_SHIFT);
-	if (tp->tg3_flags & TG3_FLAG_HOST_TXDS) {
-		struct tg3_tx_buffer_desc *txd = &tp->tx_ring[entry];
-
-		txd->addr_hi = ((u64) mapping >> 32);
-		txd->addr_lo = ((u64) mapping & 0xffffffff);
-		txd->len_flags = (len << TXD_LEN_SHIFT) | flags;
-		txd->vlan_tag = vlan_tag << TXD_VLAN_TAG_SHIFT;
-	} else {
-		struct tx_ring_info *txr = &tp->tx_buffers[entry];
-		unsigned long txd;
-
-		txd = (tp->regs +
-		       NIC_SRAM_WIN_BASE +
-		       NIC_SRAM_TX_BUFFER_DESC);
-		txd += (entry * TXD_SIZE);
 
-		/* Save some PIOs */
-		if (sizeof(dma_addr_t) != sizeof(u32))
-			writel(((u64) mapping >> 32),
-			       txd + TXD_ADDR + TG3_64BIT_REG_HIGH);
-
-		writel(((u64) mapping & 0xffffffff),
-		       txd + TXD_ADDR + TG3_64BIT_REG_LOW);
-		writel(len << TXD_LEN_SHIFT | flags, txd + TXD_LEN_FLAGS);
-		if (txr->prev_vlan_tag != vlan_tag) {
-			writel(vlan_tag << TXD_VLAN_TAG_SHIFT, txd + TXD_VLAN_TAG);
-			txr->prev_vlan_tag = vlan_tag;
-		}
-	}
+	txd->addr_hi = ((u64) mapping >> 32);
+	txd->addr_lo = ((u64) mapping & 0xffffffff);
+	txd->len_flags = (len << TXD_LEN_SHIFT) | flags;
+	txd->vlan_tag = vlan_tag << TXD_VLAN_TAG_SHIFT;
 }
 
 static inline int tg3_4g_overflow_test(dma_addr_t mapping, int len)
@@ -2892,7 +3017,11 @@
 	 * So we really do need to disable interrupts when taking
 	 * tx_lock here.
 	 */
-	spin_lock_irqsave(&tp->tx_lock, flags);
+	local_irq_save(flags);
+	if (!spin_trylock(&tp->tx_lock)) { 
+		local_irq_restore(flags);
+		return NETDEV_TX_LOCKED; 
+	} 
 
 	/* This is a hard error, log it. */
 	if (unlikely(TX_BUFFS_AVAIL(tp) <= (skb_shinfo(skb)->nr_frags + 1))) {
@@ -2900,7 +3029,7 @@
 		spin_unlock_irqrestore(&tp->tx_lock, flags);
 		printk(KERN_ERR PFX "%s: BUG! Tx Ring full when queue awake!\n",
 		       dev->name);
-		return 1;
+		return NETDEV_TX_BUSY;
 	}
 
 	entry = tp->tx_prod;
@@ -3040,19 +3169,7 @@
 	}
 
 	/* Packets are ready, update Tx producer idx local and on card. */
-	if (tp->tg3_flags & TG3_FLAG_HOST_TXDS) {
-		tw32_tx_mbox((MAILBOX_SNDHOST_PROD_IDX_0 +
-			      TG3_64BIT_REG_LOW), entry);
-	} else {
-		/* First, make sure tg3 sees last descriptor fully
-		 * in SRAM.
-		 */
-		if (tp->tg3_flags & TG3_FLAG_MBOX_WRITE_REORDER)
-			tr32(MAILBOX_SNDNIC_PROD_IDX_0 + TG3_64BIT_REG_LOW);
-
-		tw32_tx_mbox((MAILBOX_SNDNIC_PROD_IDX_0 +
-			      TG3_64BIT_REG_LOW), entry);
-	}
+	tw32_tx_mbox((MAILBOX_SNDHOST_PROD_IDX_0 + TG3_64BIT_REG_LOW), entry);
 
 	tp->tx_prod = entry;
 	if (TX_BUFFS_AVAIL(tp) <= (MAX_SKB_FRAGS + 1))
@@ -3063,7 +3180,7 @@
 
 	dev->trans_start = jiffies;
 
-	return 0;
+	return NETDEV_TX_OK;
 }
 
 static inline void tg3_set_mtu(struct net_device *dev, struct tg3 *tp,
@@ -3102,9 +3219,10 @@
 
 	tg3_init_hw(tp);
 
+	tg3_netif_start(tp);
+
 	spin_unlock(&tp->tx_lock);
 	spin_unlock_irq(&tp->lock);
-	tg3_netif_start(tp);
 
 	return 0;
 }
@@ -3190,7 +3308,6 @@
  */
 static void tg3_init_rings(struct tg3 *tp)
 {
-	unsigned long start, end;
 	u32 i;
 
 	/* Free up all the SKBs. */
@@ -3200,21 +3317,7 @@
 	memset(tp->rx_std, 0, TG3_RX_RING_BYTES);
 	memset(tp->rx_jumbo, 0, TG3_RX_JUMBO_RING_BYTES);
 	memset(tp->rx_rcb, 0, TG3_RX_RCB_RING_BYTES(tp));
-
-	if (tp->tg3_flags & TG3_FLAG_HOST_TXDS) {
-		memset(tp->tx_ring, 0, TG3_TX_RING_BYTES);
-	} else {
-		start = (tp->regs +
-			 NIC_SRAM_WIN_BASE +
-			 NIC_SRAM_TX_BUFFER_DESC);
-		end = start + TG3_TX_RING_BYTES;
-		while (start < end) {
-			writel(0, start);
-			start += 4;
-		}
-		for (i = 0; i < TG3_TX_RING_SIZE; i++)
-			tp->tx_buffers[i].prev_vlan_tag = 0;
-	}
+	memset(tp->tx_ring, 0, TG3_TX_RING_BYTES);
 
 	/* Initialize invariants of the rings, we only set this
 	 * stuff once.  This works because the card does not
@@ -3345,15 +3448,10 @@
 	if (!tp->rx_rcb)
 		goto err_out;
 
-	if (tp->tg3_flags & TG3_FLAG_HOST_TXDS) {
-		tp->tx_ring = pci_alloc_consistent(tp->pdev, TG3_TX_RING_BYTES,
-						   &tp->tx_desc_mapping);
-		if (!tp->tx_ring)
-			goto err_out;
-	} else {
-		tp->tx_ring = NULL;
-		tp->tx_desc_mapping = 0;
-	}
+	tp->tx_ring = pci_alloc_consistent(tp->pdev, TG3_TX_RING_BYTES,
+					   &tp->tx_desc_mapping);
+	if (!tp->tx_ring)
+		goto err_out;
 
 	tp->hw_status = pci_alloc_consistent(tp->pdev,
 					     TG3_HW_STATUS_SIZE,
@@ -3595,6 +3693,8 @@
 	}
 }
 
+static void tg3_stop_fw(struct tg3 *);
+
 /* tp->lock is held. */
 static int tg3_chip_reset(struct tg3 *tp)
 {
@@ -3602,7 +3702,7 @@
 	u32 flags_save;
 	int i;
 
-	if (!(tp->tg3_flags2 & TG3_FLG2_SUN_5704))
+	if (!(tp->tg3_flags2 & TG3_FLG2_SUN_570X))
 		tg3_nvram_lock(tp);
 
 	/*
@@ -3697,6 +3797,11 @@
 
 	tw32(MEMARB_MODE, MEMARB_MODE_ENABLE);
 
+	if (tp->pci_chip_rev_id == CHIPREV_ID_5750_A3) {
+		tg3_stop_fw(tp);
+		tw32(0x5000, 0x400);
+	}
+
 	tw32(GRC_MODE, tp->grc_mode);
 
 	if (tp->pci_chip_rev_id == CHIPREV_ID_5705_A0) {
@@ -3713,7 +3818,7 @@
 		tw32(TG3PCI_CLOCK_CTRL, tp->pci_clock_ctrl);
 	}
 
-	if (tp->phy_id == PHY_ID_SERDES) {
+	if (tp->tg3_flags2 & TG3_FLG2_PHY_SERDES) {
 		tp->mac_mode = MAC_MODE_PORT_MODE_TBI;
 		tw32_f(MAC_MODE, tp->mac_mode);
 	} else
@@ -3728,7 +3833,7 @@
 		udelay(10);
 	}
 	if (i >= 100000 &&
-	    !(tp->tg3_flags2 & TG3_FLG2_SUN_5704)) {
+	    !(tp->tg3_flags2 & TG3_FLG2_SUN_570X)) {
 		printk(KERN_ERR PFX "tg3_reset_hw timed out for %s, "
 		       "firmware will not restart magic=%08x\n",
 		       tp->dev->name, val);
@@ -4810,10 +4915,7 @@
 			  GRC_MODE_4X_NIC_SEND_RINGS |
 			  GRC_MODE_NO_TX_PHDR_CSUM |
 			  GRC_MODE_NO_RX_PHDR_CSUM);
-	if (tp->tg3_flags & TG3_FLAG_HOST_TXDS)
-		tp->grc_mode |= GRC_MODE_HOST_SENDBDS;
-	else
-		tp->grc_mode |= GRC_MODE_4X_NIC_SEND_RINGS;
+	tp->grc_mode |= GRC_MODE_HOST_SENDBDS;
 	if (tp->tg3_flags & TG3_FLAG_NO_TX_PSEUDO_CSUM)
 		tp->grc_mode |= GRC_MODE_NO_TX_PHDR_CSUM;
 	if (tp->tg3_flags & TG3_FLAG_NO_RX_PSEUDO_CSUM)
@@ -4966,18 +5068,11 @@
 	tw32_mailbox(MAILBOX_SNDHOST_PROD_IDX_0 + TG3_64BIT_REG_LOW, 0);
 	tw32_tx_mbox(MAILBOX_SNDNIC_PROD_IDX_0 + TG3_64BIT_REG_LOW, 0);
 
-	if (tp->tg3_flags & TG3_FLAG_HOST_TXDS) {
-		tg3_set_bdinfo(tp, NIC_SRAM_SEND_RCB,
-			       tp->tx_desc_mapping,
-			       (TG3_TX_RING_SIZE <<
-				BDINFO_FLAGS_MAXLEN_SHIFT),
-			       NIC_SRAM_TX_BUFFER_DESC);
-	} else {
-		tg3_set_bdinfo(tp, NIC_SRAM_SEND_RCB,
-			       0,
-			       BDINFO_FLAGS_DISABLED,
-			       NIC_SRAM_TX_BUFFER_DESC);
-	}
+	tg3_set_bdinfo(tp, NIC_SRAM_SEND_RCB,
+		       tp->tx_desc_mapping,
+		       (TG3_TX_RING_SIZE <<
+			BDINFO_FLAGS_MAXLEN_SHIFT),
+		       NIC_SRAM_TX_BUFFER_DESC);
 
 	/* There is only one receive return ring on 5705/5750, no need
 	 * to explicitly disable the others.
@@ -5243,14 +5338,14 @@
 	tw32(MAC_LED_CTRL, tp->led_ctrl);
 
 	tw32(MAC_MI_STAT, MAC_MI_STAT_LNKSTAT_ATTN_ENAB);
-	if (tp->phy_id == PHY_ID_SERDES) {
+	if (tp->tg3_flags2 & TG3_FLG2_PHY_SERDES) {
 		tw32_f(MAC_RX_MODE, RX_MODE_RESET);
 		udelay(10);
 	}
 	tw32_f(MAC_RX_MODE, tp->rx_mode);
 	udelay(10);
 
-	if (tp->phy_id == PHY_ID_SERDES) {
+	if (tp->tg3_flags2 & TG3_FLG2_PHY_SERDES) {
 		if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5704) {
 			/* Set drive transmission level to 1.2V  */
 			val = tr32(MAC_SERDES_CFG);
@@ -5268,22 +5363,8 @@
 	tw32_f(MAC_LOW_WMARK_MAX_RX_FRAME, 2);
 
 	if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5704 &&
-	    tp->phy_id == PHY_ID_SERDES) {
-		/* Enable hardware link auto-negotiation */
-		u32 digctrl, txctrl;
-
-		digctrl = SG_DIG_USING_HW_AUTONEG | SG_DIG_CRC16_CLEAR_N |
-		    SG_DIG_LOCAL_DUPLEX_STATUS | SG_DIG_LOCAL_LINK_STATUS |
-		    (2 << SG_DIG_SPEED_STATUS_SHIFT) | SG_DIG_FIBER_MODE |
-		    SG_DIG_GBIC_ENABLE;
-
-		txctrl = tr32(MAC_SERDES_CFG);
-		tw32_f(MAC_SERDES_CFG, txctrl | MAC_SERDES_CFG_EDGE_SELECT);
-		tw32_f(SG_DIG_CTRL, digctrl | SG_DIG_SOFT_RESET);
-		tr32(SG_DIG_CTRL);
-		udelay(5);
-		tw32_f(SG_DIG_CTRL, digctrl);
-
+	    (tp->tg3_flags2 & TG3_FLG2_PHY_SERDES)) {
+		/* Use hardware link auto-negotiation */
 		tp->tg3_flags2 |= TG3_FLG2_HW_AUTONEG;
 	}
 
@@ -5291,7 +5372,7 @@
 	if (err)
 		return err;
 
-	if (tp->phy_id != PHY_ID_SERDES) {
+	if (!(tp->tg3_flags2 & TG3_FLG2_PHY_SERDES)) {
 		u32 tmp;
 
 		/* Clear CRC stats. */
@@ -5483,7 +5564,8 @@
 				need_setup = 1;
 			}
 			if (! netif_carrier_ok(tp->dev) &&
-			    (mac_stat & MAC_STATUS_PCS_SYNCED)) {
+			    (mac_stat & (MAC_STATUS_PCS_SYNCED |
+					 MAC_STATUS_SIGNAL_DET))) {
 				need_setup = 1;
 			}
 			if (need_setup) {
@@ -5536,8 +5618,8 @@
 	spin_unlock(&tp->tx_lock);
 	spin_unlock_irq(&tp->lock);
 
-	/* If you move this call, make sure TG3_FLAG_HOST_TXDS in
-	 * tp->tg3_flags is accurate at that new place.
+	/* The placement of this call is tied
+	 * to the setup and use of Host TX descriptors.
 	 */
 	err = tg3_alloc_consistent(tp);
 	if (err)
@@ -5879,7 +5961,7 @@
 {
 	struct tg3_hw_stats *hw_stats = tp->hw_stats;
 
-	if (tp->phy_id != PHY_ID_SERDES &&
+	if (!(tp->tg3_flags2 & TG3_FLG2_PHY_SERDES) &&
 	    (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5700 ||
 	     GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5701)) {
 		unsigned long flags;
@@ -6152,7 +6234,9 @@
 	struct tg3 *tp = netdev_priv(dev);
 
 	spin_lock_irq(&tp->lock);
+	spin_lock(&tp->tx_lock);
 	__tg3_set_rx_mode(dev);
+	spin_unlock(&tp->tx_lock);
 	spin_unlock_irq(&tp->lock);
 }
 
@@ -6310,7 +6394,7 @@
 		cmd->supported |= (SUPPORTED_1000baseT_Half |
 				   SUPPORTED_1000baseT_Full);
 
-	if (tp->phy_id != PHY_ID_SERDES)
+	if (!(tp->tg3_flags2 & TG3_FLG2_PHY_SERDES))
 		cmd->supported |= (SUPPORTED_100baseT_Half |
 				  SUPPORTED_100baseT_Full |
 				  SUPPORTED_10baseT_Half |
@@ -6339,7 +6423,7 @@
 	    tp->link_config.phy_is_low_power)
 		return -EAGAIN;
 
-	if (tp->phy_id == PHY_ID_SERDES) {
+	if (tp->tg3_flags2 & TG3_FLG2_PHY_SERDES) {
 		/* These are the only valid advertisement bits allowed.  */
 		if (cmd->autoneg == AUTONEG_ENABLE &&
 		    (cmd->advertising & ~(ADVERTISED_1000baseT_Half |
@@ -6397,7 +6481,7 @@
 	if (wol->wolopts & ~WAKE_MAGIC)
 		return -EINVAL;
 	if ((wol->wolopts & WAKE_MAGIC) &&
-	    tp->phy_id == PHY_ID_SERDES &&
+	    tp->tg3_flags2 & TG3_FLG2_PHY_SERDES &&
 	    !(tp->tg3_flags & TG3_FLAG_SERDES_WOL_CAP))
 		return -EINVAL;
   
@@ -6493,10 +6577,9 @@
 
 	tg3_halt(tp);
 	tg3_init_hw(tp);
-	netif_wake_queue(tp->dev);
+	tg3_netif_start(tp);
 	spin_unlock(&tp->tx_lock);
 	spin_unlock_irq(&tp->lock);
-	tg3_netif_start(tp);
   
 	return 0;
 }
@@ -6506,8 +6589,8 @@
 	struct tg3 *tp = netdev_priv(dev);
   
 	epause->autoneg = (tp->tg3_flags & TG3_FLAG_PAUSE_AUTONEG) != 0;
-	epause->rx_pause = (tp->tg3_flags & TG3_FLAG_PAUSE_RX) != 0;
-	epause->tx_pause = (tp->tg3_flags & TG3_FLAG_PAUSE_TX) != 0;
+	epause->rx_pause = (tp->tg3_flags & TG3_FLAG_RX_PAUSE) != 0;
+	epause->tx_pause = (tp->tg3_flags & TG3_FLAG_TX_PAUSE) != 0;
 }
   
 static int tg3_set_pauseparam(struct net_device *dev, struct ethtool_pauseparam *epause)
@@ -6522,18 +6605,18 @@
 	else
 		tp->tg3_flags &= ~TG3_FLAG_PAUSE_AUTONEG;
 	if (epause->rx_pause)
-		tp->tg3_flags |= TG3_FLAG_PAUSE_RX;
+		tp->tg3_flags |= TG3_FLAG_RX_PAUSE;
 	else
-		tp->tg3_flags &= ~TG3_FLAG_PAUSE_RX;
+		tp->tg3_flags &= ~TG3_FLAG_RX_PAUSE;
 	if (epause->tx_pause)
-		tp->tg3_flags |= TG3_FLAG_PAUSE_TX;
+		tp->tg3_flags |= TG3_FLAG_TX_PAUSE;
 	else
-		tp->tg3_flags &= ~TG3_FLAG_PAUSE_TX;
+		tp->tg3_flags &= ~TG3_FLAG_TX_PAUSE;
 	tg3_halt(tp);
 	tg3_init_hw(tp);
+	tg3_netif_start(tp);
 	spin_unlock(&tp->tx_lock);
 	spin_unlock_irq(&tp->lock);
-	tg3_netif_start(tp);
   
 	return 0;
 }
@@ -6620,7 +6703,7 @@
 	case SIOCGMIIREG: {
 		u32 mii_regval;
 
-		if (tp->phy_id == PHY_ID_SERDES)
+		if (tp->tg3_flags2 & TG3_FLG2_PHY_SERDES)
 			break;			/* We have no PHY */
 
 		spin_lock_irq(&tp->lock);
@@ -6633,7 +6716,7 @@
 	}
 
 	case SIOCSMIIREG:
-		if (tp->phy_id == PHY_ID_SERDES)
+		if (tp->tg3_flags2 & TG3_FLG2_PHY_SERDES)
 			break;			/* We have no PHY */
 
 		if (!capable(CAP_NET_ADMIN))
@@ -6720,7 +6803,7 @@
 {
 	int j;
 
-	if (tp->tg3_flags2 & TG3_FLG2_SUN_5704)
+	if (tp->tg3_flags2 & TG3_FLG2_SUN_570X)
 		return;
 
 	tw32_f(GRC_EEPROM_ADDR,
@@ -6807,8 +6890,8 @@
 {
 	int i;
 
-	if (tp->tg3_flags2 & TG3_FLG2_SUN_5704) {
-		printk(KERN_ERR PFX "Attempt to do nvram_read on Sun 5704\n");
+	if (tp->tg3_flags2 & TG3_FLG2_SUN_570X) {
+		printk(KERN_ERR PFX "Attempt to do nvram_read on Sun 570X\n");
 		return -EINVAL;
 	}
 
@@ -6870,10 +6953,10 @@
 	{ PCI_VENDOR_ID_BROADCOM, 0x1644, PHY_ID_BCM5401 }, /* BCM95700A6 */
 	{ PCI_VENDOR_ID_BROADCOM, 0x0001, PHY_ID_BCM5701 }, /* BCM95701A5 */
 	{ PCI_VENDOR_ID_BROADCOM, 0x0002, PHY_ID_BCM8002 }, /* BCM95700T6 */
-	{ PCI_VENDOR_ID_BROADCOM, 0x0003, PHY_ID_SERDES  }, /* BCM95700A9 */
+	{ PCI_VENDOR_ID_BROADCOM, 0x0003, 0 },		    /* BCM95700A9 */
 	{ PCI_VENDOR_ID_BROADCOM, 0x0005, PHY_ID_BCM5701 }, /* BCM95701T1 */
 	{ PCI_VENDOR_ID_BROADCOM, 0x0006, PHY_ID_BCM5701 }, /* BCM95701T8 */
-	{ PCI_VENDOR_ID_BROADCOM, 0x0007, PHY_ID_SERDES  }, /* BCM95701A7 */
+	{ PCI_VENDOR_ID_BROADCOM, 0x0007, 0 },		    /* BCM95701A7 */
 	{ PCI_VENDOR_ID_BROADCOM, 0x0008, PHY_ID_BCM5701 }, /* BCM95701A10 */
 	{ PCI_VENDOR_ID_BROADCOM, 0x8008, PHY_ID_BCM5701 }, /* BCM95701A12 */
 	{ PCI_VENDOR_ID_BROADCOM, 0x0009, PHY_ID_BCM5703 }, /* BCM95703Ax1 */
@@ -6882,7 +6965,7 @@
 	/* 3com boards. */
 	{ PCI_VENDOR_ID_3COM, 0x1000, PHY_ID_BCM5401 }, /* 3C996T */
 	{ PCI_VENDOR_ID_3COM, 0x1006, PHY_ID_BCM5701 }, /* 3C996BT */
-	{ PCI_VENDOR_ID_3COM, 0x1004, PHY_ID_SERDES  }, /* 3C996SX */
+	{ PCI_VENDOR_ID_3COM, 0x1004, 0 },		/* 3C996SX */
 	{ PCI_VENDOR_ID_3COM, 0x1007, PHY_ID_BCM5701 }, /* 3C1000T */
 	{ PCI_VENDOR_ID_3COM, 0x1008, PHY_ID_BCM5701 }, /* 3C940BR01 */
 
@@ -6895,37 +6978,43 @@
 	/* Compaq boards. */
 	{ PCI_VENDOR_ID_COMPAQ, 0x007c, PHY_ID_BCM5701 }, /* BANSHEE */
 	{ PCI_VENDOR_ID_COMPAQ, 0x009a, PHY_ID_BCM5701 }, /* BANSHEE_2 */
-	{ PCI_VENDOR_ID_COMPAQ, 0x007d, PHY_ID_SERDES  }, /* CHANGELING */
+	{ PCI_VENDOR_ID_COMPAQ, 0x007d, 0 },		  /* CHANGELING */
 	{ PCI_VENDOR_ID_COMPAQ, 0x0085, PHY_ID_BCM5701 }, /* NC7780 */
 	{ PCI_VENDOR_ID_COMPAQ, 0x0099, PHY_ID_BCM5701 }, /* NC7780_2 */
 
 	/* IBM boards. */
-	{ PCI_VENDOR_ID_IBM, 0x0281, PHY_ID_SERDES } /* IBM??? */
+	{ PCI_VENDOR_ID_IBM, 0x0281, 0 } /* IBM??? */
 };
 
-static int __devinit tg3_phy_probe(struct tg3 *tp)
+static inline struct subsys_tbl_ent *lookup_by_subsys(struct tg3 *tp)
 {
-	u32 eeprom_phy_id, hw_phy_id_1, hw_phy_id_2;
-	u32 hw_phy_id, hw_phy_id_masked;
-	u32 val;
-	int i, eeprom_signature_found, err;
+	int i;
 
-	tp->phy_id = PHY_ID_INVALID;
 	for (i = 0; i < ARRAY_SIZE(subsys_id_to_phy_id); i++) {
 		if ((subsys_id_to_phy_id[i].subsys_vendor ==
 		     tp->pdev->subsystem_vendor) &&
 		    (subsys_id_to_phy_id[i].subsys_devid ==
-		     tp->pdev->subsystem_device)) {
-			tp->phy_id = subsys_id_to_phy_id[i].phy_id;
-			break;
-		}
+		     tp->pdev->subsystem_device))
+			return &subsys_id_to_phy_id[i];
 	}
+	return NULL;
+}
 
+static int __devinit tg3_phy_probe(struct tg3 *tp)
+{
+	u32 eeprom_phy_id, hw_phy_id_1, hw_phy_id_2;
+	u32 hw_phy_id, hw_phy_id_masked;
+	u32 val;
+	int eeprom_signature_found, eeprom_phy_serdes, err;
+
+	tp->phy_id = PHY_ID_INVALID;
 	eeprom_phy_id = PHY_ID_INVALID;
+	eeprom_phy_serdes = 0;
 	eeprom_signature_found = 0;
 	tg3_read_mem(tp, NIC_SRAM_DATA_SIG, &val);
 	if (val == NIC_SRAM_DATA_SIG_MAGIC) {
 		u32 nic_cfg, led_cfg;
+		u32 nic_phy_id, cfg2;
 
 		tg3_read_mem(tp, NIC_SRAM_DATA_CFG, &nic_cfg);
 		tp->nic_sram_data_cfg = nic_cfg;
@@ -6933,21 +7022,19 @@
 		eeprom_signature_found = 1;
 
 		if ((nic_cfg & NIC_SRAM_DATA_CFG_PHY_TYPE_MASK) ==
-		    NIC_SRAM_DATA_CFG_PHY_TYPE_FIBER) {
-			eeprom_phy_id = PHY_ID_SERDES;
-		} else {
-			u32 nic_phy_id;
+		    NIC_SRAM_DATA_CFG_PHY_TYPE_FIBER)
+			eeprom_phy_serdes = 1;
 
-			tg3_read_mem(tp, NIC_SRAM_DATA_PHY_ID, &nic_phy_id);
-			if (nic_phy_id != 0) {
-				u32 id1 = nic_phy_id & NIC_SRAM_DATA_PHY_ID1_MASK;
-				u32 id2 = nic_phy_id & NIC_SRAM_DATA_PHY_ID2_MASK;
-
-				eeprom_phy_id  = (id1 >> 16) << 10;
-				eeprom_phy_id |= (id2 & 0xfc00) << 16;
-				eeprom_phy_id |= (id2 & 0x03ff) <<  0;
-			}
-		}
+		tg3_read_mem(tp, NIC_SRAM_DATA_PHY_ID, &nic_phy_id);
+		if (nic_phy_id != 0) {
+			u32 id1 = nic_phy_id & NIC_SRAM_DATA_PHY_ID1_MASK;
+			u32 id2 = nic_phy_id & NIC_SRAM_DATA_PHY_ID2_MASK;
+
+			eeprom_phy_id  = (id1 >> 16) << 10;
+			eeprom_phy_id |= (id2 & 0xfc00) << 16;
+			eeprom_phy_id |= (id2 & 0x03ff) <<  0;
+		} else
+			eeprom_phy_id = 0;
 
 		if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5750) {
 			tg3_read_mem(tp, NIC_SRAM_DATA_CFG_2, &led_cfg);
@@ -7009,6 +7096,10 @@
 		}
 		if (nic_cfg & NIC_SRAM_DATA_CFG_FIBER_WOL)
 			tp->tg3_flags |= TG3_FLAG_SERDES_WOL_CAP;
+
+		tg3_read_mem(tp, NIC_SRAM_DATA_PHY_ID, &cfg2);
+		if (cfg2 & (1 << 17))
+			tp->tg3_flags2 |= TG3_FLG2_CAPACITIVE_COUPLING;
 	}
 
 	/* Reading the PHY ID register can conflict with ASF
@@ -7035,20 +7126,31 @@
 
 	if (!err && KNOWN_PHY_ID(hw_phy_id_masked)) {
 		tp->phy_id = hw_phy_id;
+		if (hw_phy_id_masked == PHY_ID_BCM8002)
+			tp->tg3_flags2 |= TG3_FLG2_PHY_SERDES;
 	} else {
-		/* phy_id currently holds the value found in the
-		 * subsys_id_to_phy_id[] table or PHY_ID_INVALID
-		 * if a match was not found there.
-		 */
-		if (tp->phy_id == PHY_ID_INVALID) {
-			if (!eeprom_signature_found ||
-			    !KNOWN_PHY_ID(eeprom_phy_id & PHY_ID_MASK))
-				return -ENODEV;
+		if (eeprom_signature_found) {
 			tp->phy_id = eeprom_phy_id;
+			if (eeprom_phy_serdes)
+				tp->tg3_flags2 |= TG3_FLG2_PHY_SERDES;
+		} else {
+			struct subsys_tbl_ent *p;
+
+			/* No eeprom signature?  Try the hardcoded
+			 * subsys device table.
+			 */
+			p = lookup_by_subsys(tp);
+			if (!p)
+				return -ENODEV;
+
+			tp->phy_id = p->phy_id;
+			if (!tp->phy_id ||
+			    tp->phy_id == PHY_ID_BCM8002)
+				tp->tg3_flags2 |= TG3_FLG2_PHY_SERDES;
 		}
 	}
 
-	if (tp->phy_id != PHY_ID_SERDES &&
+	if (!(tp->tg3_flags2 & TG3_FLG2_PHY_SERDES) &&
 	    !(tp->tg3_flags & TG3_FLAG_ENABLE_ASF)) {
 		u32 bmsr, adv_reg, tg3_ctrl;
 
@@ -7105,7 +7207,7 @@
 	if (!eeprom_signature_found)
 		tp->led_ctrl = LED_CTRL_MODE_PHY_1;
 
-	if (tp->phy_id == PHY_ID_SERDES)
+	if (tp->tg3_flags2 & TG3_FLG2_PHY_SERDES)
 		tp->link_config.advertising =
 			(ADVERTISED_1000baseT_Half |
 			 ADVERTISED_1000baseT_Full |
@@ -7124,11 +7226,11 @@
 	unsigned char vpd_data[256];
 	int i;
 
-	if (tp->tg3_flags2 & TG3_FLG2_SUN_5704) {
+	if (tp->tg3_flags2 & TG3_FLG2_SUN_570X) {
 		/* Sun decided not to put the necessary bits in the
 		 * NVRAM of their onboard tg3 parts :(
 		 */
-		strcpy(tp->board_part_number, "Sun 5704");
+		strcpy(tp->board_part_number, "Sun 570X");
 		return;
 	}
 
@@ -7189,27 +7291,21 @@
 }
 
 #ifdef CONFIG_SPARC64
-static int __devinit tg3_is_sun_5704(struct tg3 *tp)
+static int __devinit tg3_is_sun_570X(struct tg3 *tp)
 {
 	struct pci_dev *pdev = tp->pdev;
 	struct pcidev_cookie *pcp = pdev->sysdata;
 
 	if (pcp != NULL) {
 		int node = pcp->prom_node;
-		u32 venid, devid;
+		u32 venid;
 		int err;
 
 		err = prom_getproperty(node, "subsystem-vendor-id",
 				       (char *) &venid, sizeof(venid));
 		if (err == 0 || err == -1)
 			return 0;
-		err = prom_getproperty(node, "subsystem-id",
-				       (char *) &devid, sizeof(devid));
-		if (err == 0 || err == -1)
-			return 0;
-
-		if (venid == PCI_VENDOR_ID_SUN &&
-		    devid == PCI_DEVICE_ID_TIGON3_5704)
+		if (venid == PCI_VENDOR_ID_SUN)
 			return 1;
 	}
 	return 0;
@@ -7226,8 +7322,8 @@
 	int err;
 
 #ifdef CONFIG_SPARC64
-	if (tg3_is_sun_5704(tp))
-		tp->tg3_flags2 |= TG3_FLG2_SUN_5704;
+	if (tg3_is_sun_570X(tp))
+		tp->tg3_flags2 |= TG3_FLG2_SUN_570X;
 #endif
 
 	/* If we have an AMD 762 or Intel ICH/ICH0/ICH2 chipset, write
@@ -7453,7 +7549,7 @@
 		    chiprevid == CHIPREV_ID_5701_B0 ||
 		    chiprevid == CHIPREV_ID_5701_B2 ||
 		    chiprevid == CHIPREV_ID_5701_B5) {
-			unsigned long sram_base;
+			void __iomem *sram_base;
 
 			/* Write some dummy words into the SRAM status block
 			 * area, see if it reads back correctly.  If the return
@@ -7472,32 +7568,17 @@
 	udelay(50);
 	tg3_nvram_init(tp);
 
-	/* Always use host TXDs, it performs better in particular
-	 * with multi-frag packets.  The tests below are kept here
-	 * as documentation should we change this decision again
-	 * in the future.
-	 */
-	tp->tg3_flags |= TG3_FLAG_HOST_TXDS;
-
-#if 0
-	/* Determine if TX descriptors will reside in
-	 * main memory or in the chip SRAM.
-	 */
-	if ((tp->tg3_flags & TG3_FLAG_PCIX_TARGET_HWBUG) != 0 ||
-	    GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5705 ||
-	    GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5750)
-		tp->tg3_flags |= TG3_FLAG_HOST_TXDS;
-#endif
-
 	grc_misc_cfg = tr32(GRC_MISC_CFG);
 	grc_misc_cfg &= GRC_MISC_CFG_BOARD_ID_MASK;
 
+	/* Broadcom's driver says that CIOBE multisplit has a bug */
+#if 0
 	if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5704 &&
 	    grc_misc_cfg == GRC_MISC_CFG_BOARD_ID_5704CIOBE) {
 		tp->tg3_flags |= TG3_FLAG_SPLIT_MODE;
 		tp->split_mode_max_reqs = SPLIT_MODE_5704_MAX_REQ;
 	}
-
+#endif
 	if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5705 &&
 	    (grc_misc_cfg == GRC_MISC_CFG_BOARD_ID_5788 ||
 	     grc_misc_cfg == GRC_MISC_CFG_BOARD_ID_5788M))
@@ -7524,7 +7605,7 @@
 
 	tg3_read_partno(tp);
 
-	if (tp->phy_id == PHY_ID_SERDES) {
+	if (tp->tg3_flags2 & TG3_FLG2_PHY_SERDES) {
 		tp->tg3_flags &= ~TG3_FLAG_USE_MI_INTERRUPT;
 	} else {
 		if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5700)
@@ -7547,13 +7628,13 @@
 	 * upon subsystem IDs.
 	 */
 	if (tp->pdev->subsystem_vendor == PCI_VENDOR_ID_DELL &&
-	    tp->phy_id != PHY_ID_SERDES) {
+	    !(tp->tg3_flags2 & TG3_FLG2_PHY_SERDES)) {
 		tp->tg3_flags |= (TG3_FLAG_USE_MI_INTERRUPT |
 				  TG3_FLAG_USE_LINKCHG_REG);
 	}
 
 	/* For all SERDES we poll the MAC status register. */
-	if (tp->phy_id == PHY_ID_SERDES)
+	if (tp->tg3_flags2 & TG3_FLG2_PHY_SERDES)
 		tp->tg3_flags |= TG3_FLAG_POLL_SERDES;
 	else
 		tp->tg3_flags &= ~TG3_FLAG_POLL_SERDES;
@@ -7624,7 +7705,7 @@
 
 	mac_offset = 0x7c;
 	if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5704 &&
-	    !(tp->tg3_flags & TG3_FLG2_SUN_5704)) {
+	    !(tp->tg3_flags & TG3_FLG2_SUN_570X)) {
 		if (tr32(TG3PCI_DUAL_MAC_CTRL) & DUAL_MAC_CTRL_ID)
 			mac_offset = 0xcc;
 		if (tg3_nvram_lock(tp))
@@ -7646,7 +7727,7 @@
 		dev->dev_addr[5] = (lo >>  0) & 0xff;
 	}
 	/* Next, try NVRAM. */
-	else if (!(tp->tg3_flags & TG3_FLG2_SUN_5704) &&
+	else if (!(tp->tg3_flags & TG3_FLG2_SUN_570X) &&
 		 !tg3_nvram_read(tp, mac_offset + 0, &hi) &&
 		 !tg3_nvram_read(tp, mac_offset + 4, &lo)) {
 		dev->dev_addr[0] = ((hi >> 16) & 0xff);
@@ -7988,8 +8069,8 @@
 	case PHY_ID_BCM5704:	return "5704";
 	case PHY_ID_BCM5705:	return "5705";
 	case PHY_ID_BCM5750:	return "5750";
-	case PHY_ID_BCM8002:	return "8002";
-	case PHY_ID_SERDES:	return "serdes";
+	case PHY_ID_BCM8002:	return "8002/serdes";
+	case 0:			return "serdes";
 	default:		return "unknown";
 	};
 }
@@ -8096,6 +8177,7 @@
 
 	if (pci_using_dac)
 		dev->features |= NETIF_F_HIGHDMA;
+	dev->features |= NETIF_F_LLTX;
 #if TG3_VLAN_TAG_USED
 	dev->features |= NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX;
 	dev->vlan_rx_register = tg3_vlan_rx_register;
@@ -8141,7 +8223,7 @@
 	spin_lock_init(&tp->indirect_lock);
 	INIT_WORK(&tp->reset_task, tg3_reset_task, tp);
 
-	tp->regs = (unsigned long) ioremap(tg3reg_base, tg3reg_len);
+	tp->regs = ioremap(tg3reg_base, tg3reg_len);
 	if (tp->regs == 0UL) {
 		printk(KERN_ERR PFX "Cannot map device registers, "
 		       "aborting.\n");
@@ -8257,6 +8339,9 @@
 	if (tp->tg3_flags2 & TG3_FLG2_IS_5788)
 		dev->features &= ~NETIF_F_HIGHDMA;
 
+	/* flow control autonegotiation is default behavior */
+	tp->tg3_flags |= TG3_FLAG_PAUSE_AUTONEG;
+
 	err = register_netdev(dev);
 	if (err) {
 		printk(KERN_ERR PFX "Cannot register net device, "
@@ -8288,11 +8373,10 @@
 		printk("%2.2x%c", dev->dev_addr[i],
 		       i == 5 ? '\n' : ':');
 
-	printk(KERN_INFO "%s: HostTXDS[%d] RXcsums[%d] LinkChgREG[%d] "
+	printk(KERN_INFO "%s: RXcsums[%d] LinkChgREG[%d] "
 	       "MIirq[%d] ASF[%d] Split[%d] WireSpeed[%d] "
 	       "TSOcap[%d] \n",
 	       dev->name,
-	       (tp->tg3_flags & TG3_FLAG_HOST_TXDS) != 0,
 	       (tp->tg3_flags & TG3_FLAG_RX_CHECKSUMS) != 0,
 	       (tp->tg3_flags & TG3_FLAG_USE_LINKCHG_REG) != 0,
 	       (tp->tg3_flags & TG3_FLAG_USE_MI_INTERRUPT) != 0,
@@ -8304,7 +8388,7 @@
 	return 0;
 
 err_out_iounmap:
-	iounmap((void *) tp->regs);
+	iounmap(tp->regs);
 
 err_out_free_dev:
 	free_netdev(dev);
@@ -8326,7 +8410,7 @@
 		struct tg3 *tp = netdev_priv(dev);
 
 		unregister_netdev(dev);
-		iounmap((void *)tp->regs);
+		iounmap(tp->regs);
 		free_netdev(dev);
 		pci_release_regions(pdev);
 		pci_disable_device(pdev);
@@ -8371,11 +8455,11 @@
 		tp->timer.expires = jiffies + tp->timer_offset;
 		add_timer(&tp->timer);
 
-		spin_unlock(&tp->tx_lock);
-		spin_unlock_irq(&tp->lock);
-
 		netif_device_attach(dev);
 		tg3_netif_start(tp);
+
+		spin_unlock(&tp->tx_lock);
+		spin_unlock_irq(&tp->lock);
 	}
 
 	return err;
@@ -8408,10 +8492,10 @@
 
 	tg3_enable_ints(tp);
 
+	tg3_netif_start(tp);
+
 	spin_unlock(&tp->tx_lock);
 	spin_unlock_irq(&tp->lock);
-
-	tg3_netif_start(tp);
 
 	return 0;
 }
diff -Nru a/drivers/net/tg3.h b/drivers/net/tg3.h
--- a/drivers/net/tg3.h	2004-10-18 14:56:17 -07:00
+++ b/drivers/net/tg3.h	2004-10-18 14:56:17 -07:00
@@ -124,6 +124,7 @@
 #define  CHIPREV_ID_5705_A3		 0x3003
 #define  CHIPREV_ID_5750_A0		 0x4000
 #define  CHIPREV_ID_5750_A1		 0x4001
+#define  CHIPREV_ID_5750_A3		 0x4003
 #define  GET_ASIC_REV(CHIP_REV_ID)	((CHIP_REV_ID) >> 12)
 #define   ASIC_REV_5700			 0x07
 #define   ASIC_REV_5701			 0x00
@@ -1548,7 +1549,7 @@
  * exist only in the cards on-chip SRAM.  All 16 send bds are under
  * the same mode, they may not be configured individually.
  *
- * The mode we use is controlled by TG3_FLAG_HOST_TXDS in tp->tg3_flags.
+ * This driver always uses host memory TX descriptors.
  *
  * To use host memory TX descriptors:
  *	1) Set GRC_MODE_HOST_SENDBDS in GRC_MODE register.
@@ -1988,7 +1989,7 @@
 	spinlock_t			lock;
 	spinlock_t			indirect_lock;
 
-	unsigned long			regs;
+	void __iomem			*regs;
 	struct net_device		*dev;
 	struct pci_dev			*pdev;
 
@@ -2004,7 +2005,6 @@
 
 	spinlock_t			tx_lock;
 
-	/* TX descs are only used if TG3_FLAG_HOST_TXDS is set. */
 	struct tg3_tx_buffer_desc	*tx_ring;
 	struct tx_ring_info		*tx_buffers;
 	dma_addr_t			tx_desc_mapping;
@@ -2040,7 +2040,6 @@
 
 	u32				rx_offset;
 	u32				tg3_flags;
-#define TG3_FLAG_HOST_TXDS		0x00000001
 #define TG3_FLAG_TXD_MBOX_HWBUG		0x00000002
 #define TG3_FLAG_RX_CHECKSUMS		0x00000004
 #define TG3_FLAG_USE_LINKCHG_REG	0x00000008
@@ -2070,15 +2069,13 @@
 #define TG3_FLAG_JUMBO_ENABLE		0x00800000
 #define TG3_FLAG_10_100_ONLY		0x01000000
 #define TG3_FLAG_PAUSE_AUTONEG		0x02000000
-#define TG3_FLAG_PAUSE_RX		0x04000000
-#define TG3_FLAG_PAUSE_TX		0x08000000
 #define TG3_FLAG_BROKEN_CHECKSUMS	0x10000000
 #define TG3_FLAG_GOT_SERDES_FLOWCTL	0x20000000
 #define TG3_FLAG_SPLIT_MODE		0x40000000
 #define TG3_FLAG_INIT_COMPLETE		0x80000000
 	u32				tg3_flags2;
 #define TG3_FLG2_RESTART_TIMER		0x00000001
-#define TG3_FLG2_SUN_5704		0x00000002
+#define TG3_FLG2_SUN_570X		0x00000002
 #define TG3_FLG2_NO_ETH_WIRE_SPEED	0x00000004
 #define TG3_FLG2_IS_5788		0x00000008
 #define TG3_FLG2_MAX_RXPEND_64		0x00000010
@@ -2089,6 +2086,9 @@
 #define TG3_FLG2_PCI_EXPRESS		0x00000200
 #define TG3_FLG2_ASF_NEW_HANDSHAKE	0x00000400
 #define TG3_FLG2_HW_AUTONEG		0x00000800
+#define TG3_FLG2_PHY_JUST_INITTED	0x00001000
+#define TG3_FLG2_PHY_SERDES		0x00002000
+#define TG3_FLG2_CAPACITIVE_COUPLING	0x00004000
 
 	u32				split_mode_max_reqs;
 #define SPLIT_MODE_5704_MAX_REQ		3
@@ -2136,7 +2136,6 @@
 #define PHY_ID_BCM5705			0x600081a0
 #define PHY_ID_BCM5750			0x60008180
 #define PHY_ID_BCM8002			0x60010140
-#define PHY_ID_SERDES			0xfeedbee0
 #define PHY_ID_INVALID			0xffffffff
 #define PHY_ID_REV_MASK			0x0000000f
 #define PHY_REV_BCM5401_B0		0x1
@@ -2159,7 +2158,7 @@
 	 (X) == PHY_ID_BCM5411 || (X) == PHY_ID_BCM5701 || \
 	 (X) == PHY_ID_BCM5703 || (X) == PHY_ID_BCM5704 || \
 	 (X) == PHY_ID_BCM5705 || (X) == PHY_ID_BCM5750 || \
-	 (X) == PHY_ID_BCM8002 || (X) == PHY_ID_SERDES)
+	 (X) == PHY_ID_BCM8002)
 
 	struct tg3_hw_stats		*hw_stats;
 	dma_addr_t			stats_mapping;
diff -Nru a/drivers/net/tokenring/Kconfig b/drivers/net/tokenring/Kconfig
--- a/drivers/net/tokenring/Kconfig	2004-10-18 14:56:27 -07:00
+++ b/drivers/net/tokenring/Kconfig	2004-10-18 14:56:27 -07:00
@@ -84,7 +84,8 @@
 
 config TMS380TR
 	tristate "Generic TMS380 Token Ring ISA/PCI adapter support"
-	depends on TR && (PCI || ISA)
+	depends on TR && (PCI || ISA) && HOTPLUG
+	select FW_LOADER
 	---help---
 	  This driver provides generic support for token ring adapters
 	  based on the Texas Instruments TMS380 series chipsets.  This
diff -Nru a/drivers/net/tokenring/ibmtr.c b/drivers/net/tokenring/ibmtr.c
--- a/drivers/net/tokenring/ibmtr.c	2004-10-18 14:56:33 -07:00
+++ b/drivers/net/tokenring/ibmtr.c	2004-10-18 14:56:33 -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/tokenring/olympic.c b/drivers/net/tokenring/olympic.c
--- a/drivers/net/tokenring/olympic.c	2004-10-18 14:56:49 -07:00
+++ b/drivers/net/tokenring/olympic.c	2004-10-18 14:56:49 -07:00
@@ -221,6 +221,8 @@
 
 	olympic_priv = dev->priv ;
 	
+	spin_lock_init(&olympic_priv->olympic_lock) ; 
+
 	init_waitqueue_head(&olympic_priv->srb_wait);
 	init_waitqueue_head(&olympic_priv->trb_wait);
 #if OLYMPIC_DEBUG  
@@ -291,7 +293,7 @@
 static int __devinit olympic_init(struct net_device *dev)
 {
     	struct olympic_private *olympic_priv;
-	u8 *olympic_mmio, *init_srb,*adapter_addr;
+	u8 __iomem *olympic_mmio, *init_srb,*adapter_addr;
 	unsigned long t; 
 	unsigned int uaa_addr;
 
@@ -311,7 +313,6 @@
 		}
 	}
 
-	spin_lock_init(&olympic_priv->olympic_lock) ; 
 
 	/* Needed for cardbus */
 	if(!(readl(olympic_mmio+BCTL) & BCTL_MODE_INDICATOR)) {
@@ -435,13 +436,15 @@
 static int olympic_open(struct net_device *dev) 
 {
 	struct olympic_private *olympic_priv=(struct olympic_private *)dev->priv;
-	u8 *olympic_mmio=olympic_priv->olympic_mmio,*init_srb;
+	u8 __iomem *olympic_mmio=olympic_priv->olympic_mmio,*init_srb;
 	unsigned long flags, t;
 	char open_error[255] ; 
 	int i, open_finished = 1 ;
 
 	DECLARE_WAITQUEUE(wait,current) ; 
 
+	olympic_init(dev);
+
 	if(request_irq(dev->irq, &olympic_interrupt, SA_SHIRQ , "olympic", dev)) {
 		return -EAGAIN;
 	}
@@ -706,10 +709,10 @@
 #endif
 
 	if (olympic_priv->olympic_network_monitor) { 
-		u8 *oat ; 
-		u8 *opt ; 
-		oat = (u8 *)(olympic_priv->olympic_lap + olympic_priv->olympic_addr_table_addr) ; 
-		opt = (u8 *)(olympic_priv->olympic_lap + olympic_priv->olympic_parms_addr) ; 
+		u8 __iomem *oat ; 
+		u8 __iomem *opt ; 
+		oat = (olympic_priv->olympic_lap + olympic_priv->olympic_addr_table_addr) ; 
+		opt = (olympic_priv->olympic_lap + olympic_priv->olympic_parms_addr) ; 
 
 		printk("%s: Node Address: %02x:%02x:%02x:%02x:%02x:%02x\n",dev->name, 
 			readb(oat+offsetof(struct olympic_adapter_addr_table,node_addr)), 
@@ -755,7 +758,7 @@
 static void olympic_rx(struct net_device *dev)
 {
 	struct olympic_private *olympic_priv=(struct olympic_private *)dev->priv;
-	u8 *olympic_mmio=olympic_priv->olympic_mmio;
+	u8 __iomem *olympic_mmio=olympic_priv->olympic_mmio;
 	struct olympic_rx_status *rx_status;
 	struct olympic_rx_desc *rx_desc ; 
 	int rx_ring_last_received,length, buffer_cnt, cpy_length, frag_len;
@@ -898,7 +901,10 @@
 	int i;
 			
 	for(i=0;i<OLYMPIC_RX_RING_SIZE;i++) {
-		dev_kfree_skb_irq(olympic_priv->rx_ring_skb[olympic_priv->rx_status_last_received]);
+		if (olympic_priv->rx_ring_skb[olympic_priv->rx_status_last_received] != NULL) {
+			dev_kfree_skb_irq(olympic_priv->rx_ring_skb[olympic_priv->rx_status_last_received]);
+			olympic_priv->rx_ring_skb[olympic_priv->rx_status_last_received] = NULL;
+		}
 		if (olympic_priv->olympic_rx_ring[olympic_priv->rx_status_last_received].buffer != 0xdeadbeef) {
 			pci_unmap_single(olympic_priv->pdev, 
 			le32_to_cpu(olympic_priv->olympic_rx_ring[olympic_priv->rx_status_last_received].buffer),
@@ -925,9 +931,9 @@
 {
 	struct net_device *dev= (struct net_device *)dev_id;
 	struct olympic_private *olympic_priv=(struct olympic_private *)dev->priv;
-	u8 *olympic_mmio=olympic_priv->olympic_mmio;
+	u8 __iomem *olympic_mmio=olympic_priv->olympic_mmio;
 	u32 sisr;
-	u8 *adapter_check_area ; 
+	u8 __iomem *adapter_check_area ; 
 	
 	/* 
 	 *  Read sisr but don't reset it yet. 
@@ -944,9 +950,6 @@
 	/* Hotswap gives us this on removal */
 	if (sisr == 0xffffffff) { 
 		printk(KERN_WARNING "%s: Hotswap adapter removal.\n",dev->name) ; 
-		olympic_freemem(dev) ; 
-		free_irq(dev->irq, dev) ;
-		dev->stop = NULL ;  
 		spin_unlock(&olympic_priv->olympic_lock) ; 
 		return IRQ_NONE;
 	} 
@@ -961,9 +964,7 @@
 			printk(KERN_ERR "The adapter must be reset to clear this condition.\n") ; 
 			printk(KERN_ERR "Please report this error to the driver maintainer and/\n") ; 
 			printk(KERN_ERR "or the linux-tr mailing list.\n") ; 
-			olympic_freemem(dev) ; 
-			free_irq(dev->irq, dev) ;
-			dev->stop = NULL ;  
+			wake_up_interruptible(&olympic_priv->srb_wait);
 			spin_unlock(&olympic_priv->olympic_lock) ; 
 			return IRQ_HANDLED;
 		} /* SISR_ERR */
@@ -1006,9 +1007,6 @@
 			writel(readl(olympic_mmio+LAPWWC),olympic_mmio+LAPA);
 			adapter_check_area = olympic_priv->olympic_lap + ((readl(olympic_mmio+LAPWWC)) & (~0xf800)) ;
 			printk(KERN_WARNING "%s: Bytes %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n",dev->name, readb(adapter_check_area+0), readb(adapter_check_area+1), readb(adapter_check_area+2), readb(adapter_check_area+3), readb(adapter_check_area+4), readb(adapter_check_area+5), readb(adapter_check_area+6), readb(adapter_check_area+7)) ; 
-			olympic_freemem(dev) ;
-			free_irq(dev->irq, dev) ;
-			dev->stop = NULL ;  
 			spin_unlock(&olympic_priv->olympic_lock) ; 
 			return IRQ_HANDLED; 
 		} /* SISR_ADAPTER_CHECK */
@@ -1049,7 +1047,7 @@
 static int olympic_xmit(struct sk_buff *skb, struct net_device *dev) 
 {
 	struct olympic_private *olympic_priv=(struct olympic_private *)dev->priv;
-	u8 *olympic_mmio=olympic_priv->olympic_mmio;
+	u8 __iomem *olympic_mmio=olympic_priv->olympic_mmio;
 	unsigned long flags ; 
 
 	spin_lock_irqsave(&olympic_priv->olympic_lock, flags);
@@ -1080,7 +1078,7 @@
 static int olympic_close(struct net_device *dev) 
 {
 	struct olympic_private *olympic_priv=(struct olympic_private *)dev->priv;
-    	u8 *olympic_mmio=olympic_priv->olympic_mmio,*srb;
+	u8 __iomem *olympic_mmio=olympic_priv->olympic_mmio,*srb;
 	unsigned long t,flags;
 
 	DECLARE_WAITQUEUE(wait,current) ; 
@@ -1094,34 +1092,32 @@
 	writeb(0,srb+1);
 	writeb(OLYMPIC_CLEAR_RET_CODE,srb+2);
 
+	add_wait_queue(&olympic_priv->srb_wait,&wait) ;
+	set_current_state(TASK_INTERRUPTIBLE) ; 
+
 	spin_lock_irqsave(&olympic_priv->olympic_lock,flags);
 	olympic_priv->srb_queued=1;
 
 	writel(LISR_SRB_CMD,olympic_mmio+LISR_SUM);
 	spin_unlock_irqrestore(&olympic_priv->olympic_lock,flags);
-	
-	t = jiffies ; 
-
-	add_wait_queue(&olympic_priv->srb_wait,&wait) ;
-	set_current_state(TASK_INTERRUPTIBLE) ; 
 
 	while(olympic_priv->srb_queued) {
-		schedule() ; 
+
+		t = schedule_timeout(60*HZ); 
+
         	if(signal_pending(current))	{            
 			printk(KERN_WARNING "%s: SRB timed out.\n",dev->name);
             		printk(KERN_WARNING "SISR=%x MISR=%x\n",readl(olympic_mmio+SISR),readl(olympic_mmio+LISR));
             		olympic_priv->srb_queued=0;
             		break;
         	}
-		if ((jiffies-t) > 60*HZ) { 
+
+		if (t == 0) { 
 			printk(KERN_WARNING "%s: SRB timed out. May not be fatal. \n",dev->name) ; 
-			olympic_priv->srb_queued=0;
-			break ; 
 		} 
-		set_current_state(TASK_INTERRUPTIBLE) ; 
+		olympic_priv->srb_queued=0;
     	}
 	remove_wait_queue(&olympic_priv->srb_wait,&wait) ; 
-	set_current_state(TASK_RUNNING) ; 
 
 	olympic_priv->rx_status_last_received++;
 	olympic_priv->rx_status_last_received&=OLYMPIC_RX_RING_SIZE-1;
@@ -1152,9 +1148,9 @@
 static void olympic_set_rx_mode(struct net_device *dev) 
 {
 	struct olympic_private *olympic_priv = (struct olympic_private *) dev->priv ; 
-   	u8 *olympic_mmio = olympic_priv->olympic_mmio ; 
+   	u8 __iomem *olympic_mmio = olympic_priv->olympic_mmio ; 
 	u8 options = 0; 
-	u8 *srb;
+	u8 __iomem *srb;
 	struct dev_mc_list *dmi ; 
 	unsigned char dev_mc_address[4] ; 
 	int i ; 
@@ -1220,8 +1216,8 @@
 static void olympic_srb_bh(struct net_device *dev) 
 { 
 	struct olympic_private *olympic_priv = (struct olympic_private *) dev->priv ; 
-   	u8 *olympic_mmio = olympic_priv->olympic_mmio ; 
-	u8 *srb;
+   	u8 __iomem *olympic_mmio = olympic_priv->olympic_mmio ; 
+	u8 __iomem *srb;
 
 	writel(olympic_priv->srb,olympic_mmio+LAPA);
 	srb=olympic_priv->olympic_lap + (olympic_priv->srb & (~0xf800));
@@ -1394,22 +1390,22 @@
 static void olympic_arb_cmd(struct net_device *dev)
 {
 	struct olympic_private *olympic_priv = (struct olympic_private *) dev->priv;
-    	u8 *olympic_mmio=olympic_priv->olympic_mmio;
-	u8 *arb_block, *asb_block, *srb  ; 
+	u8 __iomem *olympic_mmio=olympic_priv->olympic_mmio;
+	u8 __iomem *arb_block, *asb_block, *srb  ; 
 	u8 header_len ; 
 	u16 frame_len, buffer_len ;
 	struct sk_buff *mac_frame ;  
-	u8 *buf_ptr ;
-	u8 *frame_data ;  
+	u8 __iomem *buf_ptr ;
+	u8 __iomem *frame_data ;  
 	u16 buff_off ; 
 	u16 lan_status = 0, lan_status_diff  ; /* Initialize to stop compiler warning */
 	u8 fdx_prot_error ; 
 	u16 next_ptr;
 	int i ; 
 
-	arb_block = (u8 *)(olympic_priv->olympic_lap + olympic_priv->arb) ; 
-	asb_block = (u8 *)(olympic_priv->olympic_lap + olympic_priv->asb) ; 
-	srb = (u8 *)(olympic_priv->olympic_lap + olympic_priv->srb) ; 
+	arb_block = (olympic_priv->olympic_lap + olympic_priv->arb) ; 
+	asb_block = (olympic_priv->olympic_lap + olympic_priv->asb) ; 
+	srb = (olympic_priv->olympic_lap + olympic_priv->srb) ; 
 	
 	if (readb(arb_block+0) == ARB_RECEIVE_DATA) { /* Receive.data, MAC frames */
 
@@ -1513,29 +1509,6 @@
 			writel(readl(olympic_mmio+BCTL)&~(3<<13),olympic_mmio+BCTL);
 			netif_stop_queue(dev);
 			olympic_priv->srb = readw(olympic_priv->olympic_lap + LAPWWO) ; 
-			for(i=0;i<OLYMPIC_RX_RING_SIZE;i++) {
-				dev_kfree_skb_irq(olympic_priv->rx_ring_skb[olympic_priv->rx_status_last_received]);
-				if (olympic_priv->olympic_rx_ring[olympic_priv->rx_status_last_received].buffer != 0xdeadbeef) {
-					pci_unmap_single(olympic_priv->pdev, 
-						le32_to_cpu(olympic_priv->olympic_rx_ring[olympic_priv->rx_status_last_received].buffer),
-						olympic_priv->pkt_buf_sz, PCI_DMA_FROMDEVICE);
-				}
-				olympic_priv->rx_status_last_received++;
-				olympic_priv->rx_status_last_received&=OLYMPIC_RX_RING_SIZE-1;
-			}
-			/* unmap rings */
-			pci_unmap_single(olympic_priv->pdev, olympic_priv->rx_status_ring_dma_addr, 
-				sizeof(struct olympic_rx_status) * OLYMPIC_RX_RING_SIZE, PCI_DMA_FROMDEVICE);
-			pci_unmap_single(olympic_priv->pdev, olympic_priv->rx_ring_dma_addr,
-				sizeof(struct olympic_rx_desc) * OLYMPIC_RX_RING_SIZE, PCI_DMA_TODEVICE);
-
-			pci_unmap_single(olympic_priv->pdev, olympic_priv->tx_status_ring_dma_addr, 
-				sizeof(struct olympic_tx_status) * OLYMPIC_TX_RING_SIZE, PCI_DMA_FROMDEVICE);
-			pci_unmap_single(olympic_priv->pdev, olympic_priv->tx_ring_dma_addr, 
-				sizeof(struct olympic_tx_desc) * OLYMPIC_TX_RING_SIZE, PCI_DMA_TODEVICE);
-
-			free_irq(dev->irq,dev);
-			dev->stop=NULL;
 			printk(KERN_WARNING "%s: Adapter has been closed \n", dev->name) ; 
 		} /* If serious error */
 		
@@ -1604,10 +1577,10 @@
 static void olympic_asb_bh(struct net_device *dev) 
 {
 	struct olympic_private *olympic_priv = (struct olympic_private *) dev->priv ; 
-	u8 *arb_block, *asb_block ; 
+	u8 __iomem *arb_block, *asb_block ; 
 
-	arb_block = (u8 *)(olympic_priv->olympic_lap + olympic_priv->arb) ; 
-	asb_block = (u8 *)(olympic_priv->olympic_lap + olympic_priv->asb) ; 
+	arb_block = (olympic_priv->olympic_lap + olympic_priv->arb) ; 
+	asb_block = (olympic_priv->olympic_lap + olympic_priv->asb) ; 
 
 	if (olympic_priv->asb_queued == 1) {   /* Dropped through the first time */
 
@@ -1666,8 +1639,8 @@
 {
 	struct net_device *dev = (struct net_device *)data ; 
 	struct olympic_private *olympic_priv=(struct olympic_private *)dev->priv;
-	u8 *oat = (u8 *)(olympic_priv->olympic_lap + olympic_priv->olympic_addr_table_addr) ; 
-	u8 *opt = (u8 *)(olympic_priv->olympic_lap + olympic_priv->olympic_parms_addr) ; 
+	u8 __iomem *oat = (olympic_priv->olympic_lap + olympic_priv->olympic_addr_table_addr) ; 
+	u8 __iomem *opt = (olympic_priv->olympic_lap + olympic_priv->olympic_parms_addr) ; 
 	int size = 0 ; 
 	int len=0;
 	off_t begin=0;
diff -Nru a/drivers/net/tokenring/olympic.h b/drivers/net/tokenring/olympic.h
--- a/drivers/net/tokenring/olympic.h	2004-10-18 14:57:04 -07:00
+++ b/drivers/net/tokenring/olympic.h	2004-10-18 14:57:04 -07:00
@@ -251,8 +251,8 @@
 	u16 arb;      /* be16 */
 	u16 asb;      /* be16 */
 
-	u8 *olympic_mmio;
-	u8 *olympic_lap;
+	u8 __iomem *olympic_mmio;
+	u8 __iomem *olympic_lap;
 	struct pci_dev *pdev ; 
 	char *olympic_card_name ; 
 
diff -Nru a/drivers/net/tulip/Kconfig b/drivers/net/tulip/Kconfig
--- a/drivers/net/tulip/Kconfig	2004-10-18 14:56:49 -07:00
+++ b/drivers/net/tulip/Kconfig	2004-10-18 14:56:49 -07:00
@@ -40,9 +40,7 @@
 	  (smc9332dst), you can also try the driver for "Generic DECchip"
 	  cards, above.  However, most people with a network card of this type
 	  will say Y here.) Do read the Ethernet-HOWTO, available from
-	  <http://www.tldp.org/docs.html#howto>.  More specific
-	  information is contained in 
-	  <file:Documentation/networking/tulip.txt>.
+	  <http://www.tldp.org/docs.html#howto>.
 
 	  To compile this driver as a module, choose M here and read
 	  <file:Documentation/networking/net-modules.txt>.  The module will
diff -Nru a/drivers/net/tulip/de4x5.c b/drivers/net/tulip/de4x5.c
--- a/drivers/net/tulip/de4x5.c	2004-10-18 14:55:54 -07:00
+++ b/drivers/net/tulip/de4x5.c	2004-10-18 14:55:54 -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-10-18 14:57:03 -07:00
+++ b/drivers/net/tulip/dmfe.c	2004-10-18 14:57:03 -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/typhoon.c b/drivers/net/typhoon.c
--- a/drivers/net/typhoon.c	2004-10-18 14:56:33 -07:00
+++ b/drivers/net/typhoon.c	2004-10-18 14:56:33 -07:00
@@ -248,11 +248,11 @@
 	/* Tx cache line section */
 	struct transmit_ring 	txLoRing	____cacheline_aligned;	
 	struct pci_dev *	tx_pdev;
-	unsigned long		tx_ioaddr;
+	void __iomem		*tx_ioaddr;
 	u32			txlo_dma_addr;
 
 	/* Irq/Rx cache line section */
-	unsigned long		ioaddr		____cacheline_aligned;
+	void __iomem		*ioaddr		____cacheline_aligned;
 	struct typhoon_indexes *indexes;
 	u8			awaiting_resp;
 	u8			duplex;
@@ -373,7 +373,7 @@
 }
 
 static int
-typhoon_reset(unsigned long ioaddr, int wait_type)
+typhoon_reset(void __iomem *ioaddr, int wait_type)
 {
 	int i, err = 0;
 	int timeout;
@@ -428,7 +428,7 @@
 }
 
 static int
-typhoon_wait_status(unsigned long ioaddr, u32 wait_value)
+typhoon_wait_status(void __iomem *ioaddr, u32 wait_value)
 {
 	int i, err = 0;
 
@@ -1240,7 +1240,7 @@
 }
 
 static int
-typhoon_wait_interrupt(unsigned long ioaddr)
+typhoon_wait_interrupt(void __iomem *ioaddr)
 {
 	int i, err = 0;
 
@@ -1348,7 +1348,7 @@
 static int
 typhoon_download_firmware(struct typhoon *tp)
 {
-	unsigned long ioaddr = tp->ioaddr;
+	void __iomem *ioaddr = tp->ioaddr;
 	struct pci_dev *pdev = tp->pdev;
 	struct typhoon_file_header *fHdr;
 	struct typhoon_section_header *sHdr;
@@ -1497,7 +1497,7 @@
 static int
 typhoon_boot_3XP(struct typhoon *tp, u32 initial_status)
 {
-	unsigned long ioaddr = tp->ioaddr;
+	void __iomem *ioaddr = tp->ioaddr;
 
 	if(typhoon_wait_status(ioaddr, initial_status) < 0) {
 		printk(KERN_ERR "%s: boot ready timeout\n", tp->name);
@@ -1812,7 +1812,8 @@
 typhoon_interrupt(int irq, void *dev_instance, struct pt_regs *rgs)
 {
 	struct net_device *dev = (struct net_device *) dev_instance;
-	unsigned long ioaddr = dev->base_addr;
+	struct typhoon *tp = dev->priv;
+	void __iomem *ioaddr = tp->ioaddr;
 	u32 intr_status;
 
 	intr_status = readl(ioaddr + TYPHOON_REG_INTR_STATUS);
@@ -1852,7 +1853,7 @@
 typhoon_sleep(struct typhoon *tp, int state, u16 events)
 {
 	struct pci_dev *pdev = tp->pdev;
-	unsigned long ioaddr = tp->ioaddr;
+	void __iomem *ioaddr = tp->ioaddr;
 	struct cmd_desc xp_cmd;
 	int err;
 
@@ -1890,7 +1891,7 @@
 typhoon_wakeup(struct typhoon *tp, int wait_type)
 {
 	struct pci_dev *pdev = tp->pdev;
-	unsigned long ioaddr = tp->ioaddr;
+	void __iomem *ioaddr = tp->ioaddr;
 
 	pci_set_power_state(pdev, 0);
 	pci_restore_state(pdev, tp->pci_state);
@@ -1911,7 +1912,7 @@
 typhoon_start_runtime(struct typhoon *tp)
 {
 	struct net_device *dev = tp->dev;
-	unsigned long ioaddr = tp->ioaddr;
+	void __iomem *ioaddr = tp->ioaddr;
 	struct cmd_desc xp_cmd;
 	int err;
 
@@ -2006,7 +2007,7 @@
 {
 	struct typhoon_indexes *indexes = tp->indexes;
 	struct transmit_ring *txLo = &tp->txLoRing;
-	unsigned long ioaddr = tp->ioaddr;
+	void __iomem *ioaddr = tp->ioaddr;
 	struct cmd_desc xp_cmd;
 	int i;
 
@@ -2070,7 +2071,7 @@
 {
 	struct typhoon *tp = (struct typhoon *) dev->priv;
 
-	if(typhoon_reset(dev->base_addr, WaitNoSleep) < 0) {
+	if(typhoon_reset(tp->ioaddr, WaitNoSleep) < 0) {
 		printk(KERN_WARNING "%s: could not reset in tx timeout\n",
 					dev->name);
 		goto truely_dead;
@@ -2091,7 +2092,7 @@
 
 truely_dead:
 	/* Reset the hardware, and turn off carrier to avoid more timeouts */
-	typhoon_reset(dev->base_addr, NoWait);
+	typhoon_reset(tp->ioaddr, NoWait);
 	netif_carrier_off(dev);
 }
 
@@ -2126,7 +2127,7 @@
 	if(typhoon_boot_3XP(tp, TYPHOON_STATUS_WAITING_FOR_HOST) < 0) {
 		printk(KERN_ERR "%s: unable to reboot into sleep img\n",
 				dev->name);
-		typhoon_reset(dev->base_addr, NoWait);
+		typhoon_reset(tp->ioaddr, NoWait);
 		goto out;
 	}
 
@@ -2192,7 +2193,7 @@
 	return 0;
 
 reset:
-	typhoon_reset(dev->base_addr, NoWait);
+	typhoon_reset(tp->ioaddr, NoWait);
 	return -EBUSY;
 }
 
@@ -2276,6 +2277,7 @@
 	struct typhoon *tp;
 	int card_id = (int) ent->driver_data;
 	unsigned long ioaddr;
+	void __iomem *ioaddr_mapped;
 	void *shared;
 	dma_addr_t shared_dma;
 	struct cmd_desc xp_cmd;
@@ -2345,14 +2347,13 @@
 	/* map our MMIO region
 	 */
 	ioaddr = pci_resource_start(pdev, 1);
-	ioaddr = (unsigned long) ioremap(ioaddr, 128);
-	if(!ioaddr) {
+	ioaddr_mapped = ioremap(ioaddr, 128);
+	if (!ioaddr_mapped) {
 		printk(ERR_PFX "%s: cannot remap MMIO, aborting\n",
 		       pci_name(pdev));
 		err = -EIO;
 		goto error_out_regions;
 	}
-	dev->base_addr = ioaddr;
 
 	/* allocate pci dma space for rx and tx descriptor rings
 	 */
@@ -2371,8 +2372,8 @@
 	tp->shared_dma = shared_dma;
 	tp->pdev = pdev;
 	tp->tx_pdev = pdev;
-	tp->ioaddr = dev->base_addr;
-	tp->tx_ioaddr = dev->base_addr;
+	tp->ioaddr = ioaddr_mapped;
+	tp->tx_ioaddr = ioaddr_mapped;
 	tp->dev = dev;
 
 	/* need to be able to restore PCI state after a suspend */
@@ -2385,7 +2386,7 @@
 	 * 4) Get the hardware address.
 	 * 5) Put the card to sleep.
 	 */
-	if(typhoon_reset(ioaddr, WaitSleep) < 0) {
+	if (typhoon_reset(ioaddr_mapped, WaitSleep) < 0) {
 		printk(ERR_PFX "%s: could not reset 3XP\n", pci_name(pdev));
 		err = -EIO;
 		goto error_out_dma;
@@ -2518,13 +2519,13 @@
 	return 0;
 
 error_out_reset:
-	typhoon_reset(ioaddr, NoWait);
+	typhoon_reset(ioaddr_mapped, NoWait);
 
 error_out_dma:
 	pci_free_consistent(pdev, sizeof(struct typhoon_shared),
 			    shared, shared_dma);
 error_out_remap:
-	iounmap((void *) ioaddr);
+	iounmap(ioaddr_mapped);
 error_out_regions:
 	pci_release_regions(pdev);
 error_out_dev:
@@ -2542,8 +2543,8 @@
 	unregister_netdev(dev);
 	pci_set_power_state(pdev, 0);
 	pci_restore_state(pdev, tp->pci_state);
-	typhoon_reset(dev->base_addr, NoWait);
-	iounmap((char *) (dev->base_addr));
+	typhoon_reset(tp->ioaddr, NoWait);
+	iounmap(tp->ioaddr);
 	pci_free_consistent(pdev, sizeof(struct typhoon_shared),
 			    tp->shared, tp->shared_dma);
 	pci_release_regions(pdev);
diff -Nru a/drivers/net/via-rhine.c b/drivers/net/via-rhine.c
--- a/drivers/net/via-rhine.c	2004-10-18 14:57:04 -07:00
+++ b/drivers/net/via-rhine.c	2004-10-18 14:57:04 -07:00
@@ -125,11 +125,16 @@
 	LK1.1.19 (Roger Luethi)
 	- Increase Tx threshold for unspecified errors
 
+	LK1.2.0-2.6 (Roger Luethi)
+	- Massive clean-up
+	- Rewrite PHY, media handling (remove options, full_duplex, backoff)
+	- Fix Tx engine race for good
+
 */
 
 #define DRV_NAME	"via-rhine"
-#define DRV_VERSION	"1.1.20-2.6"
-#define DRV_RELDATE	"May-23-2004"
+#define DRV_VERSION	"1.2.0-2.6"
+#define DRV_RELDATE	"June-10-2004"
 
 
 /* A few user-configurable values.
@@ -142,22 +147,10 @@
    Setting to > 1518 effectively disables this feature. */
 static int rx_copybreak;
 
-/* Select a backoff algorithm (Ethernet capture effect) */
-static int backoff;
-
-/* Used to pass the media type, etc.
-   Both 'options[]' and 'full_duplex[]' should exist for driver
-   interoperability.
-   The media type is usually passed in 'options[]'.
-   The default is autonegotiation for speed and duplex.
-     This should rarely be overridden.
-   Use option values 0x10/0x20 for 10Mbps, 0x100,0x200 for 100Mbps.
-   Use option values 0x10 and 0x100 for forcing half duplex fixed speed.
-   Use option values 0x20 and 0x200 for forcing full duplex operation.
-*/
-#define MAX_UNITS	8	/* More are supported, limit only on options */
-static int options[MAX_UNITS] = {-1, -1, -1, -1, -1, -1, -1, -1};
-static int full_duplex[MAX_UNITS] = {-1, -1, -1, -1, -1, -1, -1, -1};
+/*
+ * In case you are looking for 'options[]' or 'full_duplex[]', they
+ * are gone. Use ethtool(8) instead.
+ */
 
 /* Maximum number of multicast addresses to filter (vs. rx-all-multicast).
    The Rhine has a 64 element 8390-like hash table. */
@@ -210,9 +203,6 @@
 static char version[] __devinitdata =
 KERN_INFO DRV_NAME ".c:v1.10-LK" DRV_VERSION " " DRV_RELDATE " Written by Donald Becker\n";
 
-static char shortname[] = DRV_NAME;
-
-
 /* This driver was written to use PCI memory space. Some early versions
    of the Rhine may only work correctly with I/O space accesses. */
 #ifdef CONFIG_VIA_RHINE_MMIO
@@ -239,15 +229,9 @@
 MODULE_PARM(max_interrupt_work, "i");
 MODULE_PARM(debug, "i");
 MODULE_PARM(rx_copybreak, "i");
-MODULE_PARM(backoff, "i");
-MODULE_PARM(options, "1-" __MODULE_STRING(MAX_UNITS) "i");
-MODULE_PARM(full_duplex, "1-" __MODULE_STRING(MAX_UNITS) "i");
 MODULE_PARM_DESC(max_interrupt_work, "VIA Rhine maximum events handled per interrupt");
 MODULE_PARM_DESC(debug, "VIA Rhine debug level (0-7)");
 MODULE_PARM_DESC(rx_copybreak, "VIA Rhine copy breakpoint for copy-only-tiny-frames");
-MODULE_PARM_DESC(backoff, "VIA Rhine: Bits 0-3: backoff algorithm");
-MODULE_PARM_DESC(options, "VIA Rhine: Bits 0-3: media type, bit 17: full duplex");
-MODULE_PARM_DESC(full_duplex, "VIA Rhine full duplex setting(s) (1)");
 
 /*
 		Theory of Operation
@@ -350,24 +334,24 @@
 
 enum rhine_revs {
 	VT86C100A	= 0x00,
+	VTunknown0	= 0x20,
 	VT6102		= 0x40,
 	VT8231		= 0x50,	/* Integrated MAC */
 	VT8233		= 0x60,	/* Integrated MAC */
 	VT8235		= 0x74,	/* Integrated MAC */
 	VT8237		= 0x78,	/* Integrated MAC */
-	VTunknown0	= 0x7C,
+	VTunknown1	= 0x7C,
 	VT6105		= 0x80,
 	VT6105_B0	= 0x83,
 	VT6105L		= 0x8A,
 	VT6107		= 0x8C,
-	VTunknown1	= 0x8E,
-	VT6105M		= 0x90,
+	VTunknown2	= 0x8E,
+	VT6105M		= 0x90,	/* Management adapter */
 };
 
 enum rhine_quirks {
 	rqWOL		= 0x0001,	/* Wake-On-LAN support */
 	rqForceReset	= 0x0002,
-	rqDavicomPhy	= 0x0020,
 	rq6patterns	= 0x0040,	/* 6 instead of 4 patterns for WOL */
 	rqStatusWBRace	= 0x0080,	/* Tx Status Writeback Error possible */
 	rqRhineI	= 0x0100,	/* See comment below */
@@ -395,6 +379,7 @@
 /* Offsets to the device registers. */
 enum register_offsets {
 	StationAddr=0x00, RxConfig=0x06, TxConfig=0x07, ChipCmd=0x08,
+	ChipCmd1=0x09,
 	IntrStatus=0x0C, IntrEnable=0x0E,
 	MulticastFilter0=0x10, MulticastFilter1=0x14,
 	RxRingPtr=0x18, TxRingPtr=0x1C, GFIFOTest=0x54,
@@ -403,8 +388,8 @@
 	ConfigA=0x78, ConfigB=0x79, ConfigC=0x7A, ConfigD=0x7B,
 	RxMissed=0x7C, RxCRCErrs=0x7E, MiscCmd=0x81,
 	StickyHW=0x83, IntrStatus2=0x84,
-	WOLcrSet=0xA0, WOLcrClr=0xA4, WOLcrClr1=0xA6,
-	WOLcgClr=0xA7,
+	WOLcrSet=0xA0, PwcfgSet=0xA1, WOLcgSet=0xA3, WOLcrClr=0xA4,
+	WOLcrClr1=0xA6, WOLcgClr=0xA7,
 	PwrcsrSet=0xA8, PwrcsrSet1=0xA9, PwrcsrClr=0xAC, PwrcsrClr1=0xAD,
 };
 
@@ -436,6 +421,15 @@
 	IntrTxErrSummary=0x082218,
 };
 
+/* Bits in WOLcrSet/WOLcrClr and PwrcsrSet/PwrcsrClr */
+enum wol_bits {
+	WOLucast	= 0x10,
+	WOLmagic	= 0x20,
+	WOLbmcast	= 0x30,
+	WOLlnkon	= 0x40,
+	WOLlnkoff	= 0x80,
+};
+
 /* The Rx and Tx buffer descriptors. */
 struct rx_desc {
 	s32 rx_status;
@@ -464,13 +458,12 @@
 
 /* Bits in ChipCmd. */
 enum chip_cmd_bits {
-	CmdInit=0x0001, CmdStart=0x0002, CmdStop=0x0004, CmdRxOn=0x0008,
-	CmdTxOn=0x0010, CmdTxDemand=0x0020, CmdRxDemand=0x0040,
-	CmdEarlyRx=0x0100, CmdEarlyTx=0x0200, CmdFDuplex=0x0400,
-	CmdNoTxPoll=0x0800, CmdReset=0x8000,
+	CmdInit=0x01, CmdStart=0x02, CmdStop=0x04, CmdRxOn=0x08,
+	CmdTxOn=0x10, Cmd1TxDemand=0x20, CmdRxDemand=0x40,
+	Cmd1EarlyRx=0x01, Cmd1EarlyTx=0x02, Cmd1FDuplex=0x04,
+	Cmd1NoTxPoll=0x08, Cmd1Reset=0x80,
 };
 
-#define MAX_MII_CNT	4
 struct rhine_private {
 	/* Descriptor rings */
 	struct rx_desc *rx_ring;
@@ -492,8 +485,8 @@
 	dma_addr_t tx_bufs_dma;
 
 	struct pci_dev *pdev;
+	long pioaddr;
 	struct net_device_stats stats;
-	struct timer_list timer;	/* Media monitoring timer. */
 	spinlock_t lock;
 
 	/* Frequently used values: keep some adjacent for cache effect. */
@@ -502,23 +495,16 @@
 	unsigned int cur_rx, dirty_rx;	/* Producer/consumer ring indices */
 	unsigned int cur_tx, dirty_tx;
 	unsigned int rx_buf_sz;		/* Based on MTU+slack. */
-	u16 chip_cmd;			/* Current setting for ChipCmd */
+	u8 wolopts;
 
-	/* These values are keep track of the transceiver/media in use. */
 	u8 tx_thresh, rx_thresh;
 
-	/* MII transceiver section. */
-	unsigned char phys[MAX_MII_CNT];	/* MII device addresses. */
-	unsigned int mii_cnt;		/* number of MIIs found, but only the first one is used */
-	u16 mii_status;			/* last read MII status */
 	struct mii_if_info mii_if;
 };
 
 static int  mdio_read(struct net_device *dev, int phy_id, int location);
 static void mdio_write(struct net_device *dev, int phy_id, int location, int value);
 static int  rhine_open(struct net_device *dev);
-static void rhine_check_duplex(struct net_device *dev);
-static void rhine_timer(unsigned long data);
 static void rhine_tx_timeout(struct net_device *dev);
 static int  rhine_start_tx(struct sk_buff *skb, struct net_device *dev);
 static irqreturn_t rhine_interrupt(int irq, void *dev_instance, struct pt_regs *regs);
@@ -530,6 +516,16 @@
 static int netdev_ioctl(struct net_device *dev, struct ifreq *rq, int cmd);
 static struct ethtool_ops netdev_ethtool_ops;
 static int  rhine_close(struct net_device *dev);
+static void rhine_shutdown (struct device *gdev);
+
+#define RHINE_WAIT_FOR(condition) do {					\
+	int i=1024;							\
+	while (!(condition) && --i)					\
+		;							\
+	if (debug > 1 && i < 512)					\
+		printk(KERN_INFO "%s: %4d cycles used @ %s:%d\n",	\
+				DRV_NAME, 1024-i, __func__, __LINE__);	\
+} while(0)
 
 static inline u32 get_intr_status(struct net_device *dev)
 {
@@ -546,12 +542,13 @@
 
 /*
  * Get power related registers into sane state.
- * Returns content of power-event (WOL) registers.
+ * Notify user about past WOL event.
  */
 static void rhine_power_init(struct net_device *dev)
 {
 	long ioaddr = dev->base_addr;
 	struct rhine_private *rp = netdev_priv(dev);
+	u16 wolstat;
 
 	if (rp->quirks & rqWOL) {
 		/* Make sure chip is in power state D0 */
@@ -566,63 +563,109 @@
 		if (rp->quirks & rq6patterns)
 			writeb(0x03, ioaddr + WOLcrClr1);
 
+		/* Save power-event status bits */
+		wolstat = readb(ioaddr + PwrcsrSet);
+		if (rp->quirks & rq6patterns)
+			wolstat |= (readb(ioaddr + PwrcsrSet1) & 0x03) << 8;
+
 		/* Clear power-event status bits */
 		writeb(0xFF, ioaddr + PwrcsrClr);
 		if (rp->quirks & rq6patterns)
 			writeb(0x03, ioaddr + PwrcsrClr1);
+
+		if (wolstat) {
+			char *reason;
+			switch (wolstat) {
+			case WOLmagic:
+				reason = "Magic packet";
+				break;
+			case WOLlnkon:
+				reason = "Link went up";
+				break;
+			case WOLlnkoff:
+				reason = "Link went down";
+				break;
+			case WOLucast:
+				reason = "Unicast packet";
+				break;
+			case WOLbmcast:
+				reason = "Multicast/broadcast packet";
+				break;
+			default:
+				reason = "Unknown";
+			}
+			printk(KERN_INFO "%s: Woke system up. Reason: %s.\n",
+			       DRV_NAME, reason);
+		}
 	}
 }
 
-static void wait_for_reset(struct net_device *dev, u32 quirks, char *name)
+static void rhine_chip_reset(struct net_device *dev)
 {
 	long ioaddr = dev->base_addr;
-	int boguscnt = 20;
+	struct rhine_private *rp = netdev_priv(dev);
 
+	writeb(Cmd1Reset, ioaddr + ChipCmd1);
 	IOSYNC;
 
-	if (readw(ioaddr + ChipCmd) & CmdReset) {
+	if (readb(ioaddr + ChipCmd1) & Cmd1Reset) {
 		printk(KERN_INFO "%s: Reset not complete yet. "
-			"Trying harder.\n", name);
+			"Trying harder.\n", DRV_NAME);
 
-		/* Rhine-II needs to be forced sometimes */
-		if (quirks & rqForceReset)
+		/* Force reset */
+		if (rp->quirks & rqForceReset)
 			writeb(0x40, ioaddr + MiscCmd);
 
-		/* VT86C100A may need long delay after reset (dlink) */
-		/* Seen on Rhine-II as well (rl) */
-		while ((readw(ioaddr + ChipCmd) & CmdReset) && --boguscnt)
-			udelay(5);
-
+		/* Reset can take somewhat longer (rare) */
+		RHINE_WAIT_FOR(!(readb(ioaddr + ChipCmd1) & Cmd1Reset));
 	}
 
 	if (debug > 1)
-		printk(KERN_INFO "%s: Reset %s.\n", name,
-			boguscnt ? "succeeded" : "failed");
+		printk(KERN_INFO "%s: Reset %s.\n", dev->name,
+			(readb(ioaddr + ChipCmd1) & Cmd1Reset) ?
+			"failed" : "succeeded");
 }
 
 #ifdef USE_MMIO
-static void __devinit enable_mmio(long ioaddr, u32 quirks)
+static void __devinit enable_mmio(long pioaddr, u32 quirks)
 {
 	int n;
 	if (quirks & rqRhineI) {
 		/* More recent docs say that this bit is reserved ... */
-		n = inb(ioaddr + ConfigA) | 0x20;
-		outb(n, ioaddr + ConfigA);
+		n = inb(pioaddr + ConfigA) | 0x20;
+		outb(n, pioaddr + ConfigA);
 	} else {
-		n = inb(ioaddr + ConfigD) | 0x80;
-		outb(n, ioaddr + ConfigD);
+		n = inb(pioaddr + ConfigD) | 0x80;
+		outb(n, pioaddr + ConfigD);
 	}
 }
 #endif
 
-static void __devinit reload_eeprom(long ioaddr)
+/*
+ * Loads bytes 0x00-0x05, 0x6E-0x6F, 0x78-0x7B from EEPROM
+ * (plus 0x6C for Rhine-I/II)
+ */
+static void __devinit rhine_reload_eeprom(long pioaddr, struct net_device *dev)
 {
-	int i;
-	outb(0x20, ioaddr + MACRegEEcsr);
-	/* Typically 2 cycles to reload. */
-	for (i = 0; i < 150; i++)
-		if (! (inb(ioaddr + MACRegEEcsr) & 0x20))
-			break;
+	long ioaddr = dev->base_addr;
+	struct rhine_private *rp = netdev_priv(dev);
+
+	outb(0x20, pioaddr + MACRegEEcsr);
+	RHINE_WAIT_FOR(!(inb(pioaddr + MACRegEEcsr) & 0x20));
+
+#ifdef USE_MMIO
+	/*
+	 * Reloading from EEPROM overwrites ConfigA-D, so we must re-enable
+	 * MMIO. If reloading EEPROM was done first this could be avoided, but
+	 * it is not known if that still works with the "win98-reboot" problem.
+	 */
+	enable_mmio(pioaddr, rp->quirks);
+#endif
+
+	/* Turn off EEPROM-controlled wake-up (magic packet) */
+	if (rp->quirks & rqWOL)
+		writeb(readb(ioaddr + ConfigA) & 0xFE, ioaddr + ConfigA);
+
 }
 
 #ifdef CONFIG_NET_POLL_CONTROLLER
@@ -634,22 +677,33 @@
 }
 #endif
 
+static void rhine_hw_init(struct net_device *dev, long pioaddr)
+{
+	struct rhine_private *rp = netdev_priv(dev);
+
+	/* Reset the chip to erase previous misconfiguration. */
+	rhine_chip_reset(dev);
+
+	/* Rhine-I needs extra time to recuperate before EEPROM reload */
+	if (rp->quirks & rqRhineI)
+		msleep(5);
+
+	/* Reload EEPROM controlled bytes cleared by soft reset */
+	rhine_reload_eeprom(pioaddr, dev);
+}
+
 static int __devinit rhine_init_one(struct pci_dev *pdev,
 				    const struct pci_device_id *ent)
 {
 	struct net_device *dev;
 	struct rhine_private *rp;
-	int i, option, rc;
+	int i, rc;
 	u8 pci_rev;
 	u32 quirks;
-	static int card_idx = -1;
-	long ioaddr;
+	long pioaddr;
 	long memaddr;
-	int io_size;
-	int phy, phy_idx = 0;
-#ifdef USE_MMIO
-	long ioaddr0;
-#endif
+	long ioaddr;
+	int io_size, phy_id;
 	const char *name;
 
 /* when built into the kernel, we only print version if device is found */
@@ -659,26 +713,30 @@
 		printk(version);
 #endif
 
-	card_idx++;
-	option = card_idx < MAX_UNITS ? options[card_idx] : 0;
 	pci_read_config_byte(pdev, PCI_REVISION_ID, &pci_rev);
 
 	io_size = 256;
-	if (pci_rev < VT6102) {
-		quirks = rqRhineI | rqDavicomPhy;
+	phy_id = 0;
+	quirks = 0;
+	name = "Rhine";
+	if (pci_rev < VTunknown0) {
+		quirks = rqRhineI;
 		io_size = 128;
-		name = "VT86C100A Rhine";
 	}
-	else {
+	else if (pci_rev >= VT6102) {
 		quirks = rqWOL | rqForceReset;
 		if (pci_rev < VT6105) {
 			name = "Rhine II";
 			quirks |= rqStatusWBRace;	/* Rhine-II exclusive */
 		}
 		else {
-			name = "Rhine III";
+			phy_id = 1;	/* Integrated PHY, phy_id fixed to 1 */
 			if (pci_rev >= VT6105_B0)
 				quirks |= rq6patterns;
+			if (pci_rev < VT6105M)
+				name = "Rhine III";
+			else
+				name = "Rhine III (Management Adapter)";
 		}
 	}
 
@@ -702,28 +760,31 @@
 		goto err_out;
 	}
 
-	ioaddr = pci_resource_start(pdev, 0);
+	pioaddr = pci_resource_start(pdev, 0);
 	memaddr = pci_resource_start(pdev, 1);
 
 	pci_set_master(pdev);
 
-	dev = alloc_etherdev(sizeof(*rp));
-	if (dev == NULL) {
+	dev = alloc_etherdev(sizeof(struct rhine_private));
+	if (!dev) {
 		rc = -ENOMEM;
-		printk(KERN_ERR "init_ethernet failed for card #%d\n",
-		       card_idx);
+		printk(KERN_ERR "alloc_etherdev failed\n");
 		goto err_out;
 	}
 	SET_MODULE_OWNER(dev);
 	SET_NETDEV_DEV(dev, &pdev->dev);
 
-	rc = pci_request_regions(pdev, shortname);
+	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;
 
 #ifdef USE_MMIO
-	ioaddr0 = ioaddr;
-	enable_mmio(ioaddr0, quirks);
+	enable_mmio(pioaddr, quirks);
 
 	ioaddr = (long) ioremap(memaddr, io_size);
 	if (!ioaddr) {
@@ -737,7 +798,7 @@
 	i = 0;
 	while (mmio_verify_registers[i]) {
 		int reg = mmio_verify_registers[i++];
-		unsigned char a = inb(ioaddr0+reg);
+		unsigned char a = inb(pioaddr+reg);
 		unsigned char b = readb(ioaddr+reg);
 		if (a != b) {
 			rc = -EIO;
@@ -746,65 +807,38 @@
 			goto err_out_unmap;
 		}
 	}
+#else
+	ioaddr = pioaddr;
 #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);
-
-	/* Reset the chip to erase previous misconfiguration. */
-	writew(CmdReset, ioaddr + ChipCmd);
-
-	wait_for_reset(dev, quirks, shortname);
-
-	/* Reload the station address from the EEPROM. */
-#ifdef USE_MMIO
-	reload_eeprom(ioaddr0);
-	/* Reloading from eeprom overwrites cfgA-D, so we must re-enable MMIO.
-	   If reload_eeprom() was done first this could be avoided, but it is
-	   not known if that still works with the "win98-reboot" problem. */
-	enable_mmio(ioaddr0, quirks);
-#else
-	reload_eeprom(ioaddr);
-#endif
+	rhine_hw_init(dev, pioaddr);
 
 	for (i = 0; i < 6; i++)
 		dev->dev_addr[i] = readb(ioaddr + StationAddr + i);
 
 	if (!is_valid_ether_addr(dev->dev_addr)) {
 		rc = -EIO;
-		printk(KERN_ERR "Invalid MAC address for card #%d\n", card_idx);
+		printk(KERN_ERR "Invalid MAC address\n");
 		goto err_out_unmap;
 	}
 
-	if (quirks & rqWOL) {
-		/*
-		 * for 3065D, EEPROM reloaded will cause bit 0 in MAC_REG_CFGA
-		 * turned on. it makes MAC receive magic packet
-		 * automatically. So, we turn it off. (D-Link)
-		 */
-		writeb(readb(ioaddr + ConfigA) & 0xFE, ioaddr + ConfigA);
-	}
-
-	/* Select backoff algorithm */
-	if (backoff)
-		writeb(readb(ioaddr + ConfigD) & (0xF0 | backoff),
-		       ioaddr + ConfigD);
+	/* For Rhine-I/II, phy_id is loaded from EEPROM */
+	if (!phy_id)
+		phy_id = readb(ioaddr + 0x6C);
 
 	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;
 	rp->mii_if.phy_id_mask = 0x1f;
 	rp->mii_if.reg_num_mask = 0x1f;
 
-	if (dev->mem_start)
-		option = dev->mem_start;
-
 	/* The chip-specific entries in the device structure. */
 	dev->open = rhine_open;
 	dev->hard_start_xmit = rhine_start_tx;
@@ -826,20 +860,6 @@
 	if (rc)
 		goto err_out_unmap;
 
-	/* The lower four bits are the media type. */
-	if (option > 0) {
-		if (option & 0x220)
-			rp->mii_if.full_duplex = 1;
-	}
-	if (card_idx < MAX_UNITS && full_duplex[card_idx] > 0)
-		rp->mii_if.full_duplex = 1;
-
-	if (rp->mii_if.full_duplex) {
-		printk(KERN_INFO "%s: Set to forced full duplex, "
-		       "autonegotiation disabled.\n", dev->name);
-		rp->mii_if.force_media = 1;
-	}
-
 	printk(KERN_INFO "%s: VIA %s at 0x%lx, ",
 	       dev->name, name,
 #ifdef USE_MMIO
@@ -855,17 +875,18 @@
 
 	pci_set_drvdata(pdev, dev);
 
-	rp->phys[0] = 1;		/* Standard for this chip. */
-	for (phy = 1; phy < 32 && phy_idx < MAX_MII_CNT; phy++) {
-		int mii_status = mdio_read(dev, phy, 1);
+	{
+		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->phys[phy_idx++] = phy;
-			rp->mii_if.advertising = mdio_read(dev, phy, 4);
+			rp->mii_if.advertising = mdio_read(dev, phy_id, 4);
 			printk(KERN_INFO "%s: MII PHY found at address "
 			       "%d, status 0x%4.4x advertising %4.4x "
-			       "Link %4.4x.\n", dev->name, phy,
+			       "Link %4.4x.\n", dev->name, phy_id,
 			       mii_status, rp->mii_if.advertising,
-			       mdio_read(dev, phy, 5));
+			       mdio_read(dev, phy_id, 5));
 
 			/* set IFF_RUNNING */
 			if (mii_status & BMSR_LSTATUS)
@@ -873,27 +894,9 @@
 			else
 				netif_carrier_off(dev);
 
-			break;
-		}
-	}
-	rp->mii_cnt = phy_idx;
-	rp->mii_if.phy_id = rp->phys[0];
-
-	/* Allow forcing the media type. */
-	if (option > 0) {
-		if (option & 0x220)
-			rp->mii_if.full_duplex = 1;
-		if (option & 0x330) {
-			printk(KERN_INFO " Forcing %dMbs %s-duplex "
-				"operation.\n",
-			       (option & 0x300 ? 100 : 10),
-			       (option & 0x220 ? "full" : "half"));
-			if (rp->mii_cnt)
-				mdio_write(dev, rp->phys[0], MII_BMCR,
-					   ((option & 0x300) ? 0x2000 : 0) | /* 100mbps? */
-					   ((option & 0x220) ? 0x0100 : 0)); /* Full duplex? */
 		}
 	}
+	rp->mii_if.phy_id = phy_id;
 
 	return 0;
 
@@ -1065,6 +1068,21 @@
 	}
 }
 
+static void rhine_check_media(struct net_device *dev, unsigned int init_media)
+{
+	struct rhine_private *rp = netdev_priv(dev);
+	long ioaddr = dev->base_addr;
+
+	mii_check_media(&rp->mii_if, debug, init_media);
+
+	if (rp->mii_if.full_duplex)
+	    writeb(readb(ioaddr + ChipCmd1) | Cmd1FDuplex,
+		   ioaddr + ChipCmd1);
+	else
+	    writeb(readb(ioaddr + ChipCmd1) & ~Cmd1FDuplex,
+		   ioaddr + ChipCmd1);
+}
+
 static void init_registers(struct net_device *dev)
 {
 	struct rhine_private *rp = netdev_priv(dev);
@@ -1080,7 +1098,6 @@
 	writeb(0x20, ioaddr + TxConfig);
 	rp->tx_thresh = 0x20;
 	rp->rx_thresh = 0x60;		/* Written in rhine_set_rx_mode(). */
-	rp->mii_if.full_duplex = 0;
 
 	writel(rp->rx_ring_dma, ioaddr + RxRingPtr);
 	writel(rp->tx_ring_dma, ioaddr + TxRingPtr);
@@ -1094,17 +1111,44 @@
 	       IntrPCIErr | IntrStatsMax | IntrLinkChange,
 	       ioaddr + IntrEnable);
 
-	rp->chip_cmd = CmdStart|CmdTxOn|CmdRxOn|CmdNoTxPoll;
-	if (rp->mii_if.force_media)
-		rp->chip_cmd |= CmdFDuplex;
-	writew(rp->chip_cmd, ioaddr + ChipCmd);
-
-	rhine_check_duplex(dev);
-
-	/* The LED outputs of various MII xcvrs should be configured. */
-	/* For NS or Mison phys, turn on bit 1 in register 0x17 */
-	mdio_write(dev, rp->phys[0], 0x17, mdio_read(dev, rp->phys[0], 0x17) |
-		   0x0001);
+	writew(CmdStart | CmdTxOn | CmdRxOn | (Cmd1NoTxPoll << 8),
+	       ioaddr + ChipCmd);
+	rhine_check_media(dev, 1);
+}
+
+/* Enable MII link status auto-polling (required for IntrLinkChange) */
+static void rhine_enable_linkmon(long ioaddr)
+{
+	writeb(0, ioaddr + MIICmd);
+	writeb(MII_BMSR, ioaddr + MIIRegAddr);
+	writeb(0x80, ioaddr + MIICmd);
+
+	RHINE_WAIT_FOR((readb(ioaddr + MIIRegAddr) & 0x20));
+
+	writeb(MII_BMSR | 0x40, ioaddr + MIIRegAddr);
+}
+
+/* Disable MII link status auto-polling (required for MDIO access) */
+static void rhine_disable_linkmon(long ioaddr, u32 quirks)
+{
+	writeb(0, ioaddr + MIICmd);
+
+	if (quirks & rqRhineI) {
+		writeb(0x01, ioaddr + MIIRegAddr);	// MII_BMSR
+
+		/* Can be called from ISR. Evil. */
+		mdelay(1);
+
+		/* 0x80 must be set immediately before turning it off */
+		writeb(0x80, ioaddr + MIICmd);
+
+		RHINE_WAIT_FOR(readb(ioaddr + MIIRegAddr) & 0x20);
+
+		/* Heh. Now clear 0x80 again. */
+		writeb(0, ioaddr + MIICmd);
+	}
+	else
+		RHINE_WAIT_FOR(readb(ioaddr + MIIRegAddr) & 0x80);
 }
 
 /* Read and write over the MII Management Data I/O (MDIO) interface. */
@@ -1112,156 +1156,72 @@
 static int mdio_read(struct net_device *dev, int phy_id, int regnum)
 {
 	long ioaddr = dev->base_addr;
-	int boguscnt = 1024;
+	struct rhine_private *rp = netdev_priv(dev);
+	int result;
+
+	rhine_disable_linkmon(ioaddr, rp->quirks);
 
-	/* Wait for a previous command to complete. */
-	while ((readb(ioaddr + MIICmd) & 0x60) && --boguscnt > 0)
-		;
-	writeb(0x00, ioaddr + MIICmd);
+	/* rhine_disable_linkmon already cleared MIICmd */
 	writeb(phy_id, ioaddr + MIIPhyAddr);
 	writeb(regnum, ioaddr + MIIRegAddr);
 	writeb(0x40, ioaddr + MIICmd);		/* Trigger read */
-	boguscnt = 1024;
-	while ((readb(ioaddr + MIICmd) & 0x40) && --boguscnt > 0)
-		;
-	return readw(ioaddr + MIIData);
+	RHINE_WAIT_FOR(!(readb(ioaddr + MIICmd) & 0x40));
+	result = readw(ioaddr + MIIData);
+
+	rhine_enable_linkmon(ioaddr);
+	return result;
 }
 
 static void mdio_write(struct net_device *dev, int phy_id, int regnum, int value)
 {
 	struct rhine_private *rp = netdev_priv(dev);
 	long ioaddr = dev->base_addr;
-	int boguscnt = 1024;
 
-	if (phy_id == rp->phys[0]) {
-		switch (regnum) {
-		case MII_BMCR:		/* Is user forcing speed/duplex? */
-			if (value & 0x9000)	/* Autonegotiation. */
-				rp->mii_if.force_media = 0;
-			else
-				rp->mii_if.full_duplex = (value & 0x0100) ? 1 : 0;
-			break;
-		case MII_ADVERTISE:
-			rp->mii_if.advertising = value;
-			break;
-		}
-	}
+	rhine_disable_linkmon(ioaddr, rp->quirks);
 
-	/* Wait for a previous command to complete. */
-	while ((readb(ioaddr + MIICmd) & 0x60) && --boguscnt > 0)
-		;
-	writeb(0x00, ioaddr + MIICmd);
+	/* rhine_disable_linkmon already cleared MIICmd */
 	writeb(phy_id, ioaddr + MIIPhyAddr);
 	writeb(regnum, ioaddr + MIIRegAddr);
 	writew(value, ioaddr + MIIData);
-	writeb(0x20, ioaddr + MIICmd);		/* Trigger write. */
-}
+	writeb(0x20, ioaddr + MIICmd);		/* Trigger write */
+	RHINE_WAIT_FOR(!(readb(ioaddr + MIICmd) & 0x20));
 
+	rhine_enable_linkmon(ioaddr);
+}
 
 static int rhine_open(struct net_device *dev)
 {
 	struct rhine_private *rp = netdev_priv(dev);
 	long ioaddr = dev->base_addr;
-	int i;
-
-	/* Reset the chip. */
-	writew(CmdReset, ioaddr + ChipCmd);
+	int rc;
 
-	i = request_irq(rp->pdev->irq, &rhine_interrupt, SA_SHIRQ, dev->name,
+	rc = request_irq(rp->pdev->irq, &rhine_interrupt, SA_SHIRQ, dev->name,
 			dev);
-	if (i)
-		return i;
+	if (rc)
+		return rc;
 
 	if (debug > 1)
 		printk(KERN_DEBUG "%s: rhine_open() irq %d.\n",
 		       dev->name, rp->pdev->irq);
 
-	i = alloc_ring(dev);
-	if (i)
-		return i;
+	rc = alloc_ring(dev);
+	if (rc)
+		return rc;
 	alloc_rbufs(dev);
 	alloc_tbufs(dev);
-	wait_for_reset(dev, rp->quirks, dev->name);
+	rhine_chip_reset(dev);
 	init_registers(dev);
 	if (debug > 2)
 		printk(KERN_DEBUG "%s: Done rhine_open(), status %4.4x "
 		       "MII status: %4.4x.\n",
 		       dev->name, readw(ioaddr + ChipCmd),
-		       mdio_read(dev, rp->phys[0], MII_BMSR));
+		       mdio_read(dev, rp->mii_if.phy_id, MII_BMSR));
 
 	netif_start_queue(dev);
 
-	/* Set the timer to check for link beat. */
-	init_timer(&rp->timer);
-	rp->timer.expires = jiffies + 2 * HZ/100;
-	rp->timer.data = (unsigned long)dev;
-	rp->timer.function = &rhine_timer;		/* timer handler */
-	add_timer(&rp->timer);
-
 	return 0;
 }
 
-static void rhine_check_duplex(struct net_device *dev)
-{
-	struct rhine_private *rp = netdev_priv(dev);
-	long ioaddr = dev->base_addr;
-	int mii_lpa = mdio_read(dev, rp->phys[0], MII_LPA);
-	int negotiated = mii_lpa & rp->mii_if.advertising;
-	int duplex;
-
-	if (rp->mii_if.force_media || mii_lpa == 0xffff)
-		return;
-	duplex = (negotiated & 0x0100) || (negotiated & 0x01C0) == 0x0040;
-	if (rp->mii_if.full_duplex != duplex) {
-		rp->mii_if.full_duplex = duplex;
-		if (debug)
-			printk(KERN_INFO "%s: Setting %s-duplex based on "
-			       "MII #%d link partner capability of %4.4x.\n",
-			       dev->name, duplex ? "full" : "half",
-			       rp->phys[0], mii_lpa);
-		if (duplex)
-			rp->chip_cmd |= CmdFDuplex;
-		else
-			rp->chip_cmd &= ~CmdFDuplex;
-		writew(rp->chip_cmd, ioaddr + ChipCmd);
-	}
-}
-
-
-static void rhine_timer(unsigned long data)
-{
-	struct net_device *dev = (struct net_device *)data;
-	struct rhine_private *rp = netdev_priv(dev);
-	long ioaddr = dev->base_addr;
-	int next_tick = 10*HZ;
-	int mii_status;
-
-	if (debug > 3) {
-		printk(KERN_DEBUG "%s: VIA Rhine monitor tick, status %4.4x.\n",
-		       dev->name, readw(ioaddr + IntrStatus));
-	}
-
-	spin_lock_irq (&rp->lock);
-
-	rhine_check_duplex(dev);
-
-	/* make IFF_RUNNING follow the MII status bit "Link established" */
-	mii_status = mdio_read(dev, rp->phys[0], MII_BMSR);
-	if ((mii_status & BMSR_LSTATUS) != (rp->mii_status & BMSR_LSTATUS)) {
-		if (mii_status & BMSR_LSTATUS)
-			netif_carrier_on(dev);
-		else
-			netif_carrier_off(dev);
-	}
-	rp->mii_status = mii_status;
-
-	spin_unlock_irq(&rp->lock);
-
-	rp->timer.expires = jiffies + next_tick;
-	add_timer(&rp->timer);
-}
-
-
 static void rhine_tx_timeout(struct net_device *dev)
 {
 	struct rhine_private *rp = netdev_priv(dev);
@@ -1270,16 +1230,13 @@
 	printk(KERN_WARNING "%s: Transmit timed out, status %4.4x, PHY status "
 	       "%4.4x, resetting...\n",
 	       dev->name, readw(ioaddr + IntrStatus),
-	       mdio_read(dev, rp->phys[0], MII_BMSR));
+	       mdio_read(dev, rp->mii_if.phy_id, MII_BMSR));
 
 	/* protect against concurrent rx interrupts */
 	disable_irq(rp->pdev->irq);
 
 	spin_lock(&rp->lock);
 
-	/* Reset the chip. */
-	writew(CmdReset, ioaddr + ChipCmd);
-
 	/* clear all descriptors */
 	free_tbufs(dev);
 	free_rbufs(dev);
@@ -1287,7 +1244,7 @@
 	alloc_rbufs(dev);
 
 	/* Reinitialize the hardware. */
-	wait_for_reset(dev, rp->quirks, dev->name);
+	rhine_chip_reset(dev);
 	init_registers(dev);
 
 	spin_unlock(&rp->lock);
@@ -1301,8 +1258,8 @@
 static int rhine_start_tx(struct sk_buff *skb, struct net_device *dev)
 {
 	struct rhine_private *rp = netdev_priv(dev);
+	long ioaddr = dev->base_addr;
 	unsigned entry;
-	u32 intr_status;
 
 	/* Caution: the write order is important here, set the field
 	   with the "ownership" bits last. */
@@ -1353,14 +1310,9 @@
 
 	/* Non-x86 Todo: explicitly flush cache lines here. */
 
-	/*
-	 * Wake the potentially-idle transmit channel unless errors are
-	 * pending (the ISR must sort them out first).
-	 */
-	intr_status = get_intr_status(dev);
-	if ((intr_status & IntrTxErrSummary) == 0) {
-		writew(CmdTxDemand | rp->chip_cmd, dev->base_addr + ChipCmd);
-	}
+	/* Wake the potentially-idle transmit channel */
+	writeb(readb(ioaddr + ChipCmd1) | Cmd1TxDemand,
+	       ioaddr + ChipCmd1);
 	IOSYNC;
 
 	if (rp->cur_tx == rp->dirty_tx + TX_QUEUE_LEN)
@@ -1408,11 +1360,10 @@
 
 		if (intr_status & (IntrTxErrSummary | IntrTxDone)) {
 			if (intr_status & IntrTxErrSummary) {
-				int cnt = 20;
 				/* Avoid scavenging before Tx engine turned off */
-				while ((readw(ioaddr+ChipCmd) & CmdTxOn) && --cnt)
-					udelay(5);
-				if (debug > 2 && !cnt)
+				RHINE_WAIT_FOR(!(readb(ioaddr+ChipCmd) & CmdTxOn));
+				if (debug > 2 &&
+				    readb(ioaddr+ChipCmd) & CmdTxOn)
 					printk(KERN_WARNING "%s: "
 					       "rhine_interrupt() Tx engine"
 					       "still on.\n", dev->name);
@@ -1572,10 +1523,6 @@
 							    rp->rx_buf_sz,
 							    PCI_DMA_FROMDEVICE);
 
-				/* *_IP_COPYSUM isn't defined anywhere and
-				   eth_copy_and_sum is memcpy for all archs so
-				   this is kind of pointless right now
-				   ... or? */
 				eth_copy_and_sum(skb,
 						 rp->rx_skbuff[entry]->tail,
 						 pkt_len, 0);
@@ -1627,10 +1574,6 @@
 		}
 		rp->rx_ring[entry].rx_status = cpu_to_le32(DescOwn);
 	}
-
-	/* Pre-emptively restart Rx engine. */
-	writew(readw(dev->base_addr + ChipCmd) | CmdRxOn | CmdRxDemand,
-	       dev->base_addr + ChipCmd);
 }
 
 /*
@@ -1664,7 +1607,10 @@
 		writel(rp->tx_ring_dma + entry * sizeof(struct tx_desc),
 		       ioaddr + TxRingPtr);
 
-		writew(CmdTxDemand | rp->chip_cmd, ioaddr + ChipCmd);
+		writeb(readb(ioaddr + ChipCmd) | CmdTxOn,
+		       ioaddr + ChipCmd);
+		writeb(readb(ioaddr + ChipCmd1) | Cmd1TxDemand,
+		       ioaddr + ChipCmd1);
 		IOSYNC;
 	}
 	else {
@@ -1684,20 +1630,8 @@
 
 	spin_lock(&rp->lock);
 
-	if (intr_status & (IntrLinkChange)) {
-		if (readb(ioaddr + MIIStatus) & 0x02) {
-			/* Link failed, restart autonegotiation. */
-			if (rp->quirks & rqRhineI)
-				mdio_write(dev, rp->phys[0], MII_BMCR, 0x3300);
-		} else
-			rhine_check_duplex(dev);
-		if (debug)
-			printk(KERN_ERR "%s: MII status changed: "
-			       "Autonegotiation advertising %4.4x partner "
-			       "%4.4x.\n", dev->name,
-			       mdio_read(dev, rp->phys[0], MII_ADVERTISE),
-			       mdio_read(dev, rp->phys[0], MII_LPA));
-	}
+	if (intr_status & IntrLinkChange)
+		rhine_check_media(dev, 0);
 	if (intr_status & IntrStatsMax) {
 		rp->stats.rx_crc_errors += readw(ioaddr + RxCRCErrs);
 		rp->stats.rx_missed_errors += readw(ioaddr + RxMissed);
@@ -1790,7 +1724,7 @@
 		     i++, mclist = mclist->next) {
 			int bit_nr = ether_crc(ETH_ALEN, mclist->dmi_addr) >> 26;
 
-			mc_filter[bit_nr >> 5] |= cpu_to_le32(1 << (bit_nr & 31));
+			mc_filter[bit_nr >> 5] |= 1 << (bit_nr & 31);
 		}
 		writel(mc_filter[0], ioaddr + MulticastFilter0);
 		writel(mc_filter[1], ioaddr + MulticastFilter1);
@@ -1856,6 +1790,39 @@
 	debug = value;
 }
 
+static void rhine_get_wol(struct net_device *dev, struct ethtool_wolinfo *wol)
+{
+	struct rhine_private *rp = netdev_priv(dev);
+
+	if (!(rp->quirks & rqWOL))
+		return;
+
+	spin_lock_irq(&rp->lock);
+	wol->supported = WAKE_PHY | WAKE_MAGIC |
+			 WAKE_UCAST | WAKE_MCAST | WAKE_BCAST;	/* Untested */
+	wol->wolopts = rp->wolopts;
+	spin_unlock_irq(&rp->lock);
+}
+
+static int rhine_set_wol(struct net_device *dev, struct ethtool_wolinfo *wol)
+{
+	struct rhine_private *rp = netdev_priv(dev);
+	u32 support = WAKE_PHY | WAKE_MAGIC |
+		      WAKE_UCAST | WAKE_MCAST | WAKE_BCAST;	/* Untested */
+
+	if (!(rp->quirks & rqWOL))
+		return -EINVAL;
+
+	if (wol->wolopts & ~support)
+		return -EINVAL;
+
+	spin_lock_irq(&rp->lock);
+	rp->wolopts = wol->wolopts;
+	spin_unlock_irq(&rp->lock);
+
+	return 0;
+}
+
 static struct ethtool_ops netdev_ethtool_ops = {
 	.get_drvinfo		= netdev_get_drvinfo,
 	.get_settings		= netdev_get_settings,
@@ -1864,6 +1831,8 @@
 	.get_link		= netdev_get_link,
 	.get_msglevel		= netdev_get_msglevel,
 	.set_msglevel		= netdev_set_msglevel,
+	.get_wol		= rhine_get_wol,
+	.set_wol		= rhine_set_wol,
 	.get_sg			= ethtool_op_get_sg,
 	.get_tx_csum		= ethtool_op_get_tx_csum,
 };
@@ -1888,8 +1857,6 @@
 	long ioaddr = dev->base_addr;
 	struct rhine_private *rp = netdev_priv(dev);
 
-	del_timer_sync(&rp->timer);
-
 	spin_lock_irq(&rp->lock);
 
 	netif_stop_queue(dev);
@@ -1936,12 +1903,110 @@
 	pci_set_drvdata(pdev, NULL);
 }
 
+static void rhine_shutdown (struct device *gendev)
+{
+	struct pci_dev *pdev = to_pci_dev(gendev);
+	struct net_device *dev = pci_get_drvdata(pdev);
+	struct rhine_private *rp = netdev_priv(dev);
+
+	long ioaddr = dev->base_addr;
+
+	rhine_power_init(dev);
+
+	/* Make sure we use pattern 0, 1 and not 4, 5 */
+	if (rp->quirks & rq6patterns)
+		writeb(0x04, ioaddr + 0xA7);
+
+	if (rp->wolopts & WAKE_MAGIC)
+		writeb(WOLmagic, ioaddr + WOLcrSet);
+
+	if (rp->wolopts & (WAKE_BCAST|WAKE_MCAST))
+		writeb(WOLbmcast, ioaddr + WOLcgSet);
+
+	if (rp->wolopts & WAKE_PHY)
+		writeb(WOLlnkon | WOLlnkoff, ioaddr + WOLcrSet);
+
+	if (rp->wolopts & WAKE_UCAST)
+		writeb(WOLucast, ioaddr + WOLcrSet);
+
+	/* Enable legacy WOL (for old motherboards) */
+	writeb(0x01, ioaddr + PwcfgSet);
+	writeb(readb(ioaddr + StickyHW) | 0x04, ioaddr + StickyHW);
+
+	/* Hit power state D3 (sleep) */
+	writeb(readb(ioaddr + StickyHW) | 0x03, ioaddr + StickyHW);
+
+	/* TODO: Check use of pci_enable_wake() */
+
+}
+
+#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		= "via-rhine",
+	.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-10-18 14:56:49 -07:00
+++ b/drivers/net/via-velocity.c	2004-10-18 14:56:49 -07:00
@@ -78,6 +78,8 @@
 #include <linux/ip.h>
 #include <linux/tcp.h>
 #include <linux/udp.h>
+#include <linux/crc-ccitt.h>
+#include <linux/crc32.h>
 
 #include "via-velocity.h"
 
@@ -226,7 +228,10 @@
 
 VELOCITY_PARAM(int_works, "Number of packets per interrupt services");
 
-static int velocity_found1(struct pci_dev *pdev, const struct pci_device_id *ent);
+static int rx_copybreak = 200;
+MODULE_PARM(rx_copybreak, "i");
+MODULE_PARM_DESC(rx_copybreak, "Copy breakpoint for copy-only-tiny-frames");
+
 static void velocity_init_info(struct pci_dev *pdev, struct velocity_info *vptr, struct velocity_info_tbl *info);
 static int velocity_get_pci_info(struct velocity_info *, struct pci_dev *pdev);
 static void velocity_print_info(struct velocity_info *vptr);
@@ -238,10 +243,8 @@
 static struct net_device_stats *velocity_get_stats(struct net_device *dev);
 static int velocity_ioctl(struct net_device *dev, struct ifreq *rq, int cmd);
 static int velocity_close(struct net_device *dev);
-static int velocity_rx_srv(struct velocity_info *vptr, int status);
 static int velocity_receive_frame(struct velocity_info *, int idx);
 static int velocity_alloc_rx_buf(struct velocity_info *, int idx);
-static void velocity_init_registers(struct velocity_info *vptr, enum velocity_init_type type);
 static void velocity_free_rd_ring(struct velocity_info *vptr);
 static void velocity_free_tx_buf(struct velocity_info *vptr, struct velocity_td_info *);
 static int velocity_soft_reset(struct velocity_info *vptr);
@@ -254,25 +257,40 @@
 static void enable_mii_autopoll(struct mac_regs * regs);
 static int velocity_mii_read(struct mac_regs *, u8 byIdx, u16 * pdata);
 static int velocity_mii_write(struct mac_regs *, u8 byMiiAddr, u16 data);
-static int velocity_set_wol(struct velocity_info *vptr);
-static void velocity_save_context(struct velocity_info *vptr, struct velocity_context *context);
-static void velocity_restore_context(struct velocity_info *vptr, struct velocity_context *context);
 static u32 mii_check_media_mode(struct mac_regs * regs);
 static u32 check_connection_type(struct mac_regs * regs);
-static void velocity_init_cam_filter(struct velocity_info *vptr);
 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);
 
 static int velocity_netdev_event(struct notifier_block *nb, unsigned long notification, void *ptr);
 
 static struct notifier_block velocity_inetaddr_notifier = {
-      notifier_call:velocity_netdev_event,
+      .notifier_call	= velocity_netdev_event,
 };
 
-#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
@@ -289,8 +307,9 @@
  */
 
 static struct pci_device_id velocity_id_table[] __devinitdata = {
-	{0x1106, 0x3119, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (unsigned long) &chip_info_table[0]},
-	{0,}
+	{PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_612X,
+	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, (unsigned long) chip_info_table},
+	{0, }
 };
 
 MODULE_DEVICE_TABLE(pci, velocity_id_table);
@@ -326,12 +345,22 @@
 	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);
 	pci_disable_device(pdev);
 	pci_set_drvdata(pdev, NULL);
 	free_netdev(dev);
+
+	velocity_nics--;
 }
 
 /**
@@ -435,7 +464,7 @@
 {
 	struct mac_regs * regs = vptr->mac_regs;
 
-	/* T urn on MCFG_PQEN, turn off MCFG_RTGOPT */
+	/* Turn on MCFG_PQEN, turn off MCFG_RTGOPT */
 	WORD_REG_BITS_SET(MCFG_PQEN, MCFG_RTGOPT, &regs->MCFG);
 	WORD_REG_BITS_ON(MCFG_VIDFR, &regs->MCFG);
 
@@ -477,13 +506,13 @@
 	struct mac_regs * regs = vptr->mac_regs;
 	int i;
 
-	vptr->rd_used = vptr->rd_curr = 0;
+	vptr->rd_dirty = vptr->rd_filled = vptr->rd_curr = 0;
 
 	/*
 	 *	Init state, all RD entries belong to the NIC
 	 */
 	for (i = 0; i < vptr->options.numrx; ++i)
-		vptr->rd_ring[i].rdesc0.owner = cpu_to_le32(OWNED_BY_NIC);
+		vptr->rd_ring[i].rdesc0.owner = OWNED_BY_NIC;
 
 	writew(vptr->options.numrx, &regs->RBRDU);
 	writel(vptr->rd_pool_dma, &regs->RDBaseLo);
@@ -558,11 +587,16 @@
 
 		writeb(WOLCFG_SAM | WOLCFG_SAB, &regs->WOLCFGSet);
 		/*
-		 *	Bback off algorithm use original IEEE standard
+		 *	Back off algorithm use original IEEE standard
 		 */
 		BYTE_REG_BITS_SET(CFGB_OFSET, (CFGB_CRANDOM | CFGB_CAP | CFGB_MBA | CFGB_BAKOPT), &regs->CFGB);
 
 		/*
+		 *	Init CAM filter
+		 */
+		velocity_init_cam_filter(vptr);
+
+		/*
 		 *	Set packet filter: Receive directed and broadcast address
 		 */
 		velocity_set_multi(vptr->dev);
@@ -586,8 +620,6 @@
 			mac_tx_queue_run(regs, i);
 		}
 
-		velocity_init_cam_filter(vptr);
-
 		init_flow_control_register(vptr);
 
 		writel(CR0_STOP, &regs->CR0Clr);
@@ -595,7 +627,6 @@
 
 		mii_status = velocity_get_opt_media_mode(vptr);
 		netif_stop_queue(vptr->dev);
-		mac_clear_isr(regs);
 
 		mii_init(vptr, mii_status);
 
@@ -662,7 +693,7 @@
 	struct mac_regs * regs;
 	int ret = -ENOMEM;
 
-	if (velocity_nics++ >= MAX_UNITS) {
+	if (velocity_nics >= MAX_UNITS) {
 		printk(KERN_NOTICE VELOCITY_NAME ": already found %d NICs.\n", 
 				velocity_nics);
 		return -ENODEV;
@@ -694,7 +725,6 @@
 
 	vptr->dev = dev;
 
-	dev->priv = vptr;
 	dev->irq = pdev->irq;
 
 	ret = pci_enable_device(pdev);
@@ -729,7 +759,7 @@
 		dev->dev_addr[i] = readb(&regs->PAR[i]);
 
 
-	velocity_get_options(&vptr->options, velocity_nics - 1, dev->name);
+	velocity_get_options(&vptr->options, velocity_nics, dev->name);
 
 	/* 
 	 *	Mask out the options cannot be set to the chip
@@ -775,6 +805,16 @@
 	/* and leave the chip powered down */
 	
 	pci_set_power_state(pdev, 3);
+#ifdef CONFIG_PM
+	{
+		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
+	velocity_nics++;
 out:
 	return ret;
 
@@ -827,9 +867,8 @@
 	vptr->io_size = info->io_size;
 	vptr->num_txq = info->txqueue;
 	vptr->multicast_limit = MCAM_SIZE;
-
 	spin_lock_init(&vptr->lock);
-	spin_lock_init(&vptr->xmit_lock);
+	INIT_LIST_HEAD(&vptr->list);
 }
 
 /**
@@ -966,6 +1005,60 @@
 	pci_free_consistent(vptr->pdev, size, vptr->tx_bufs, vptr->tx_bufs_dma);
 }
 
+static inline void velocity_give_many_rx_descs(struct velocity_info *vptr)
+{
+	struct mac_regs *regs = vptr->mac_regs;
+	int avail, dirty, unusable;
+
+	/*
+	 * RD number must be equal to 4X per hardware spec
+	 * (programming guide rev 1.20, p.13)
+	 */
+	if (vptr->rd_filled < 4)
+		return;
+
+	wmb();
+
+	unusable = vptr->rd_filled & 0x0003;
+	dirty = vptr->rd_dirty - unusable;
+	for (avail = vptr->rd_filled & 0xfffc; avail; avail--) {
+		dirty = (dirty > 0) ? dirty - 1 : vptr->options.numrx - 1;
+		vptr->rd_ring[dirty].rdesc0.owner = OWNED_BY_NIC;
+	}
+
+	writew(vptr->rd_filled & 0xfffc, &regs->RBRDU);
+	vptr->rd_filled = unusable;
+}
+
+static int velocity_rx_refill(struct velocity_info *vptr)
+{
+	int dirty = vptr->rd_dirty, done = 0, ret = 0;
+
+	do {
+		struct rx_desc *rd = vptr->rd_ring + dirty;
+
+		/* Fine for an all zero Rx desc at init time as well */
+		if (rd->rdesc0.owner == OWNED_BY_NIC)
+			break;
+
+		if (!vptr->rd_info[dirty].skb) {
+			ret = velocity_alloc_rx_buf(vptr, dirty);
+			if (ret < 0)
+				break;
+		}
+		done++;
+		dirty = (dirty < vptr->options.numrx - 1) ? dirty + 1 : 0;	
+	} while (dirty != vptr->rd_curr);
+
+	if (done) {
+		vptr->rd_dirty = dirty;
+		vptr->rd_filled += done;
+		velocity_give_many_rx_descs(vptr);
+	}
+
+	return ret;
+}
+
 /**
  *	velocity_init_rd_ring	-	set up receive ring
  *	@vptr: velocity to configure
@@ -976,9 +1069,7 @@
 
 static int velocity_init_rd_ring(struct velocity_info *vptr)
 {
-	int i, ret = -ENOMEM;
-	struct rx_desc *rd;
-	struct velocity_rd_info *rd_info;
+	int ret = -ENOMEM;
 	unsigned int rsize = sizeof(struct velocity_rd_info) * 
 					vptr->options.numrx;
 
@@ -987,28 +1078,20 @@
 		goto out;
 	memset(vptr->rd_info, 0, rsize);
 
-	/* Init the RD ring entries */
-	for (i = 0; i < vptr->options.numrx; i++) {
-		rd = &(vptr->rd_ring[i]);
-		rd_info = &(vptr->rd_info[i]);
+	vptr->rd_filled = vptr->rd_dirty = vptr->rd_curr = 0;
 
-		ret = velocity_alloc_rx_buf(vptr, i);
-		if (ret < 0) {
-			VELOCITY_PRT(MSG_LEVEL_ERR, KERN_ERR
-				"%s: failed to allocate RX buffer.\n", 
-				vptr->dev->name);
-			velocity_free_rd_ring(vptr);
-			goto out;
-		}
-		rd->rdesc0.owner = OWNED_BY_NIC;
+	ret = velocity_rx_refill(vptr);
+	if (ret < 0) {
+		VELOCITY_PRT(MSG_LEVEL_ERR, KERN_ERR
+			"%s: failed to allocate RX buffer.\n", vptr->dev->name);
+		velocity_free_rd_ring(vptr);
 	}
-	vptr->rd_used = vptr->rd_curr = 0;
 out:
 	return ret;
 }
 
 /**
- *	velocity_free_rd_ring	-	set up receive ring
+ *	velocity_free_rd_ring	-	free receive ring
  *	@vptr: velocity to clean up
  *
  *	Free the receive buffers for each ring slot and any
@@ -1025,7 +1108,7 @@
 	for (i = 0; i < vptr->options.numrx; i++) {
 		struct velocity_rd_info *rd_info = &(vptr->rd_info[i]);
 
-		if (!rd_info->skb_dma)
+		if (!rd_info->skb)
 			continue;
 		pci_unmap_single(vptr->pdev, rd_info->skb_dma, vptr->rx_buf_sz,
 				 PCI_DMA_FROMDEVICE);
@@ -1073,8 +1156,10 @@
 		for (i = 0; i < vptr->options.numtx; i++, curr += sizeof(struct tx_desc)) {
 			td = &(vptr->td_rings[j][i]);
 			td_info = &(vptr->td_infos[j][i]);
-			td_info->buf = vptr->tx_bufs + (i + j) * PKT_BUF_SZ;
-			td_info->buf_dma = vptr->tx_bufs_dma + (i + j) * PKT_BUF_SZ;
+			td_info->buf = vptr->tx_bufs +
+				(j * vptr->options.numtx + i) * PKT_BUF_SZ;
+			td_info->buf_dma = vptr->tx_bufs_dma +
+				(j * vptr->options.numtx + i) * PKT_BUF_SZ;
 		}
 		vptr->td_tail[j] = vptr->td_curr[j] = vptr->td_used[j] = 0;
 	}
@@ -1146,40 +1231,27 @@
  
 static int velocity_rx_srv(struct velocity_info *vptr, int status)
 {
-	struct rx_desc *rd;
 	struct net_device_stats *stats = &vptr->stats;
-	struct mac_regs * regs = vptr->mac_regs;
 	int rd_curr = vptr->rd_curr;
 	int works = 0;
 
-	while (1) {
-
-		rd = &(vptr->rd_ring[rd_curr]);
+	do {
+		struct rx_desc *rd = vptr->rd_ring + rd_curr;
 
-		if ((vptr->rd_info[rd_curr]).skb == NULL) {
-			if (velocity_alloc_rx_buf(vptr, rd_curr) < 0)
-				break;
-		}
-
-		if (works++ > 15)
+		if (!vptr->rd_info[rd_curr].skb)
 			break;
 
 		if (rd->rdesc0.owner == OWNED_BY_NIC)
 			break;
 
+		rmb();
+
 		/*
 		 *	Don't drop CE or RL error frame although RXOK is off
-		 *	FIXME: need to handle copybreak
 		 */
 		if ((rd->rdesc0.RSR & RSR_RXOK) || (!(rd->rdesc0.RSR & RSR_RXOK) && (rd->rdesc0.RSR & (RSR_CE | RSR_RL)))) {
-			if (velocity_receive_frame(vptr, rd_curr) == 0) {
-				if (velocity_alloc_rx_buf(vptr, rd_curr) < 0) {
-					VELOCITY_PRT(MSG_LEVEL_ERR, KERN_ERR "%s: can not allocate rx buf\n", vptr->dev->name);
-					break;
-				}
-			} else {
+			if (velocity_receive_frame(vptr, rd_curr) < 0)
 				stats->rx_dropped++;
-			}
 		} else {
 			if (rd->rdesc0.RSR & RSR_CRC)
 				stats->rx_crc_errors++;
@@ -1191,26 +1263,20 @@
 
 		rd->inten = 1;
 
-		if (++vptr->rd_used >= 4) {
-			int i, rd_prev = rd_curr;
-			for (i = 0; i < 4; i++) {
-				if (--rd_prev < 0)
-					rd_prev = vptr->options.numrx - 1;
-
-				rd = &(vptr->rd_ring[rd_prev]);
-				rd->rdesc0.owner = OWNED_BY_NIC;
-			}
-			writew(4, &(regs->RBRDU));
-			vptr->rd_used -= 4;
-		}
-
 		vptr->dev->last_rx = jiffies;
 
 		rd_curr++;
 		if (rd_curr >= vptr->options.numrx)
 			rd_curr = 0;
-	}
+	} while (++works <= 15);
+
 	vptr->rd_curr = rd_curr;
+
+	if (works > 0 && velocity_rx_refill(vptr) < 0) {
+		VELOCITY_PRT(MSG_LEVEL_ERR, KERN_ERR
+			"%s: rx buf allocation failure\n", vptr->dev->name);
+	}
+
 	VAR_USED(stats);
 	return works;
 }
@@ -1242,6 +1308,65 @@
 }
 
 /**
+ *	velocity_rx_copy	-	in place Rx copy for small packets
+ *	@rx_skb: network layer packet buffer candidate
+ *	@pkt_size: received data size
+ *	@rd: receive packet descriptor
+ *	@dev: network device
+ *
+ *	Replace the current skb that is scheduled for Rx processing by a
+ *	shorter, immediatly allocated skb, if the received packet is small
+ *	enough. This function returns a negative value if the received
+ *	packet is too big or if memory is exhausted.
+ */
+static inline int velocity_rx_copy(struct sk_buff **rx_skb, int pkt_size,
+				   struct velocity_info *vptr)
+{
+	int ret = -1;
+
+	if (pkt_size < rx_copybreak) {
+		struct sk_buff *new_skb;
+
+		new_skb = dev_alloc_skb(pkt_size + 2);
+		if (new_skb) {
+			new_skb->dev = vptr->dev;
+			new_skb->ip_summed = rx_skb[0]->ip_summed;
+
+			if (vptr->flags & VELOCITY_FLAGS_IP_ALIGN)
+				skb_reserve(new_skb, 2);
+
+			memcpy(new_skb->data, rx_skb[0]->tail, pkt_size);
+			*rx_skb = new_skb;
+			ret = 0;
+		}
+		
+	}
+	return ret;
+}
+
+/**
+ *	velocity_iph_realign	-	IP header alignment
+ *	@vptr: velocity we are handling
+ *	@skb: network layer packet buffer
+ *	@pkt_size: received data size
+ *
+ *	Align IP header on a 2 bytes boundary. This behavior can be
+ *	configured by the user.
+ */
+static inline void velocity_iph_realign(struct velocity_info *vptr,
+					struct sk_buff *skb, int pkt_size)
+{
+	/* FIXME - memmove ? */
+	if (vptr->flags & VELOCITY_FLAGS_IP_ALIGN) {
+		int i;
+
+		for (i = pkt_size; i >= 0; i--)
+			*(skb->data + i + 2) = *(skb->data + i);
+		skb_reserve(skb, 2);
+	}
+}
+
+/**
  *	velocity_receive_frame	-	received packet processor
  *	@vptr: velocity we are handling
  *	@idx: ring index
@@ -1252,9 +1377,11 @@
  
 static int velocity_receive_frame(struct velocity_info *vptr, int idx)
 {
+	void (*pci_action)(struct pci_dev *, dma_addr_t, size_t, int);
 	struct net_device_stats *stats = &vptr->stats;
 	struct velocity_rd_info *rd_info = &(vptr->rd_info[idx]);
 	struct rx_desc *rd = &(vptr->rd_ring[idx]);
+	int pkt_len = rd->rdesc0.len;
 	struct sk_buff *skb;
 
 	if (rd->rdesc0.RSR & (RSR_STP | RSR_EDP)) {
@@ -1269,22 +1396,8 @@
 	skb = rd_info->skb;
 	skb->dev = vptr->dev;
 
-	pci_unmap_single(vptr->pdev, rd_info->skb_dma, vptr->rx_buf_sz, 
-							PCI_DMA_FROMDEVICE);
-	rd_info->skb_dma = (dma_addr_t) NULL;
-	rd_info->skb = NULL;
-
-	/* FIXME - memmove ? */
-	if (vptr->flags & VELOCITY_FLAGS_IP_ALIGN) {
-		int i;
-		for (i = rd->rdesc0.len + 4; i >= 0; i--)
-			*(skb->data + i + 2) = *(skb->data + i);
-		skb->data += 2;
-		skb->tail += 2;
-	}
-
-	skb_put(skb, (rd->rdesc0.len - 4));
-	skb->protocol = eth_type_trans(skb, skb->dev);
+	pci_dma_sync_single_for_cpu(vptr->pdev, rd_info->skb_dma,
+				    vptr->rx_buf_sz, PCI_DMA_FROMDEVICE);
 
 	/*
 	 *	Drop frame not meeting IEEE 802.3
@@ -1297,13 +1410,23 @@
 		}
 	}
 
+	pci_action = pci_dma_sync_single_for_device;
+
 	velocity_rx_csum(rd, skb);
-	
-	/*
-	 *	FIXME: need rx_copybreak handling
-	 */
 
-	stats->rx_bytes += skb->len;
+	if (velocity_rx_copy(&skb, pkt_len, vptr) < 0) {
+		velocity_iph_realign(vptr, skb, pkt_len);
+		pci_action = pci_unmap_single;
+		rd_info->skb = NULL;
+	}
+
+	pci_action(vptr->pdev, rd_info->skb_dma, vptr->rx_buf_sz,
+		   PCI_DMA_FROMDEVICE);
+
+	skb_put(skb, pkt_len - 4);
+	skb->protocol = eth_type_trans(skb, skb->dev);	
+
+	stats->rx_bytes += pkt_len;
 	netif_rx(skb);
 
 	return 0;
@@ -1963,32 +2086,6 @@
 
 
 /**
- *	ether_crc	-	ethernet CRC function
- *
- *	Compute an ethernet CRC hash of the data block provided. This
- *	is not performance optimised but is not needed in performance
- *	critical code paths.
- *
- *	FIXME: could we use shared code here ?
- */
- 
-static inline u32 ether_crc(int length, unsigned char *data)
-{
-	static unsigned const ethernet_polynomial = 0x04c11db7U;
-	
-	int crc = -1;
-
-	while (--length >= 0) {
-		unsigned char current_octet = *data++;
-		int bit;
-		for (bit = 0; bit < 8; bit++, current_octet >>= 1) {
-			crc = (crc << 1) ^ ((crc < 0) ^ (current_octet & 1) ? ethernet_polynomial : 0);
-		}
-	}
-	return crc;
-}
-
-/**
  *	velocity_set_multi	-	filter list change callback
  *	@dev: network device
  *
@@ -2123,13 +2220,13 @@
  */
  
 static struct pci_driver velocity_driver = {
-      name:VELOCITY_NAME,
-      id_table:velocity_id_table,
-      probe:velocity_found1,
-      remove:velocity_remove1,
+      .name	= VELOCITY_NAME,
+      .id_table	= velocity_id_table,
+      .probe	= velocity_found1,
+      .remove	= __devexit_p(velocity_remove1),
 #ifdef CONFIG_PM
-      suspend:velocity_suspend,
-      resume:velocity_resume,
+      .suspend	= velocity_suspend,
+      .resume	= velocity_resume,
 #endif
 };
 
@@ -2145,11 +2242,11 @@
 static int __init velocity_init_module(void)
 {
 	int ret;
-	ret = pci_module_init(&velocity_driver);
 
-#ifdef CONFIG_PM
-	register_inetaddr_notifier(&velocity_inetaddr_notifier);
-#endif
+	velocity_register_notifier();
+	ret = pci_module_init(&velocity_driver);
+	if (ret < 0)
+		velocity_unregister_notifier();
 	return ret;
 }
 
@@ -2164,9 +2261,7 @@
  
 static void __exit velocity_cleanup_module(void)
 {
-#ifdef CONFIG_PM
-	unregister_inetaddr_notifier(&velocity_inetaddr_notifier);
-#endif
+	velocity_unregister_notifier();
 	pci_unregister_driver(&velocity_driver);
 }
 
@@ -2992,172 +3087,6 @@
 
 }
 
-static int velocity_suspend(struct pci_dev *pdev, u32 state)
-{
-	struct velocity_info *vptr = pci_get_drvdata(pdev);
-	unsigned long flags;
-	
-	if(!netif_running(vptr->dev))
-		return 0;
-		
-	netif_device_detach(vptr->dev);
-	
-	spin_lock_irqsave(&vptr->lock, flags);
-	pci_save_state(pdev, vptr->pci_state);
-#ifdef ETHTOOL_GWOL
-	if (vptr->flags & VELOCITY_FLAGS_WOL_ENABLED) {
-		velocity_get_ip(vptr);
-		velocity_save_context(vptr, &vptr->context);
-		velocity_shutdown(vptr);
-		velocity_set_wol(vptr);
-		pci_enable_wake(pdev, 3, 1);
-		pci_set_power_state(pdev, 3);
-	} else {
-		velocity_save_context(vptr, &vptr->context);
-		velocity_shutdown(vptr);
-		pci_disable_device(pdev);
-		pci_set_power_state(pdev, state);
-	}
-#else
-	pci_set_power_state(pdev, state);
-#endif
-	spin_unlock_irqrestore(&vptr->lock, flags);
-	return 0;
-}
-
-static int velocity_resume(struct pci_dev *pdev)
-{
-	struct velocity_info *vptr = pci_get_drvdata(pdev);
-	unsigned long flags;
-	int i;
-	
-	if(!netif_running(vptr->dev))
-		return 0;
-		
-	pci_set_power_state(pdev, 0);
-	pci_enable_wake(pdev, 0, 0);
-	pci_restore_state(pdev, vptr->pci_state);
-
-	mac_wol_reset(vptr->mac_regs);
-
-	spin_lock_irqsave(&vptr->lock, flags);
-	velocity_restore_context(vptr, &vptr->context);
-	velocity_init_registers(vptr, VELOCITY_INIT_WOL);
-	mac_disable_int(vptr->mac_regs);
-
-	velocity_tx_srv(vptr, 0);
-
-	for (i = 0; i < vptr->num_txq; i++) {
-		if (vptr->td_used[i]) {
-			mac_tx_queue_wake(vptr->mac_regs, i);
-		}
-	}
-
-	mac_enable_int(vptr->mac_regs);
-	spin_unlock_irqrestore(&vptr->lock, flags);
-	netif_device_attach(vptr->dev);
-
-	return 0;
-}
-
-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);
-	}
-	return NOTIFY_DONE;
-}
-#endif
-
-/*
- * Purpose: Functions to set WOL.
- */
-
-const static unsigned short crc16_tab[256] = {
-	0x0000, 0x1189, 0x2312, 0x329b, 0x4624, 0x57ad, 0x6536, 0x74bf,
-	0x8c48, 0x9dc1, 0xaf5a, 0xbed3, 0xca6c, 0xdbe5, 0xe97e, 0xf8f7,
-	0x1081, 0x0108, 0x3393, 0x221a, 0x56a5, 0x472c, 0x75b7, 0x643e,
-	0x9cc9, 0x8d40, 0xbfdb, 0xae52, 0xdaed, 0xcb64, 0xf9ff, 0xe876,
-	0x2102, 0x308b, 0x0210, 0x1399, 0x6726, 0x76af, 0x4434, 0x55bd,
-	0xad4a, 0xbcc3, 0x8e58, 0x9fd1, 0xeb6e, 0xfae7, 0xc87c, 0xd9f5,
-	0x3183, 0x200a, 0x1291, 0x0318, 0x77a7, 0x662e, 0x54b5, 0x453c,
-	0xbdcb, 0xac42, 0x9ed9, 0x8f50, 0xfbef, 0xea66, 0xd8fd, 0xc974,
-	0x4204, 0x538d, 0x6116, 0x709f, 0x0420, 0x15a9, 0x2732, 0x36bb,
-	0xce4c, 0xdfc5, 0xed5e, 0xfcd7, 0x8868, 0x99e1, 0xab7a, 0xbaf3,
-	0x5285, 0x430c, 0x7197, 0x601e, 0x14a1, 0x0528, 0x37b3, 0x263a,
-	0xdecd, 0xcf44, 0xfddf, 0xec56, 0x98e9, 0x8960, 0xbbfb, 0xaa72,
-	0x6306, 0x728f, 0x4014, 0x519d, 0x2522, 0x34ab, 0x0630, 0x17b9,
-	0xef4e, 0xfec7, 0xcc5c, 0xddd5, 0xa96a, 0xb8e3, 0x8a78, 0x9bf1,
-	0x7387, 0x620e, 0x5095, 0x411c, 0x35a3, 0x242a, 0x16b1, 0x0738,
-	0xffcf, 0xee46, 0xdcdd, 0xcd54, 0xb9eb, 0xa862, 0x9af9, 0x8b70,
-	0x8408, 0x9581, 0xa71a, 0xb693, 0xc22c, 0xd3a5, 0xe13e, 0xf0b7,
-	0x0840, 0x19c9, 0x2b52, 0x3adb, 0x4e64, 0x5fed, 0x6d76, 0x7cff,
-	0x9489, 0x8500, 0xb79b, 0xa612, 0xd2ad, 0xc324, 0xf1bf, 0xe036,
-	0x18c1, 0x0948, 0x3bd3, 0x2a5a, 0x5ee5, 0x4f6c, 0x7df7, 0x6c7e,
-	0xa50a, 0xb483, 0x8618, 0x9791, 0xe32e, 0xf2a7, 0xc03c, 0xd1b5,
-	0x2942, 0x38cb, 0x0a50, 0x1bd9, 0x6f66, 0x7eef, 0x4c74, 0x5dfd,
-	0xb58b, 0xa402, 0x9699, 0x8710, 0xf3af, 0xe226, 0xd0bd, 0xc134,
-	0x39c3, 0x284a, 0x1ad1, 0x0b58, 0x7fe7, 0x6e6e, 0x5cf5, 0x4d7c,
-	0xc60c, 0xd785, 0xe51e, 0xf497, 0x8028, 0x91a1, 0xa33a, 0xb2b3,
-	0x4a44, 0x5bcd, 0x6956, 0x78df, 0x0c60, 0x1de9, 0x2f72, 0x3efb,
-	0xd68d, 0xc704, 0xf59f, 0xe416, 0x90a9, 0x8120, 0xb3bb, 0xa232,
-	0x5ac5, 0x4b4c, 0x79d7, 0x685e, 0x1ce1, 0x0d68, 0x3ff3, 0x2e7a,
-	0xe70e, 0xf687, 0xc41c, 0xd595, 0xa12a, 0xb0a3, 0x8238, 0x93b1,
-	0x6b46, 0x7acf, 0x4854, 0x59dd, 0x2d62, 0x3ceb, 0x0e70, 0x1ff9,
-	0xf78f, 0xe606, 0xd49d, 0xc514, 0xb1ab, 0xa022, 0x92b9, 0x8330,
-	0x7bc7, 0x6a4e, 0x58d5, 0x495c, 0x3de3, 0x2c6a, 0x1ef1, 0x0f78
-};
-
-
-static u32 mask_pattern[2][4] = {
-	{0x00203000, 0x000003C0, 0x00000000, 0x0000000},	/* ARP		*/
-	{0xfffff000, 0xffffffff, 0xffffffff, 0x000ffff}		/* Magic Packet */ 
-};
-
-/**
- *	ether_crc16	-	compute ethernet CRC
- *	@len: buffer length
- *	@cp: buffer
- *	@crc16: initial CRC
- *
- *	Compute a CRC value for a block of data. 
- *	FIXME: can we use generic functions ?
- */
- 
-static u16 ether_crc16(int len, u8 * cp, u16 crc16)
-{
-	while (len--)
-		crc16 = (crc16 >> 8) ^ crc16_tab[(crc16 ^ *cp++) & 0xff];
-	return (crc16);
-}
-
-/**
- *	bit_reverse		-	16bit reverse
- *	@data: 16bit data t reverse
- *
- *	Reverse the order of a 16bit value and return the reversed bits
- */
- 
-static u16 bit_reverse(u16 data)
-{
-	u32 new = 0x00000000;
-	int ii;
-
-
-	for (ii = 0; ii < 16; ii++) {
-		new |= ((u32) (data & 1) << (31 - ii));
-		data >>= 1;
-	}
-
-	return (u16) (new >> 16);
-}
-
 /**
  *	wol_calc_crc		-	WOL CRC
  *	@pattern: data pattern
@@ -3166,7 +3095,7 @@
  *	Compute the wake on lan crc hashes for the packet header
  *	we are interested in.
  */
- 
+
 u16 wol_calc_crc(int size, u8 * pattern, u8 *mask_pattern)
 {
 	u16 crc = 0xFFFF;
@@ -3186,12 +3115,12 @@
 				continue;
 			}
 			mask >>= 1;
-			crc = ether_crc16(1, &(pattern[i * 8 + j]), crc);
+			crc = crc_ccitt(crc, &(pattern[i * 8 + j]), 1);
 		}
 	}
 	/*	Finally, invert the result once to get the correct data */
 	crc = ~crc;
-	return bit_reverse(crc);
+	return bitreverse(crc) >> 16;
 }
 
 /**
@@ -3203,13 +3132,18 @@
  *
  *	FIXME: check static buffer is safe here
  */
- 
+
 static int velocity_set_wol(struct velocity_info *vptr)
 {
 	struct mac_regs * regs = vptr->mac_regs;
 	static u8 buf[256];
 	int i;
 
+	static u32 mask_pattern[2][4] = {
+		{0x00203000, 0x000003C0, 0x00000000, 0x0000000}, /* ARP */
+		{0xfffff000, 0xffffffff, 0xffffffff, 0x000ffff}	 /* Magic Packet */
+	};
+
 	writew(0xFFFF, &regs->WOLCRClr);
 	writeb(WOLCFG_SAB | WOLCFG_SAM, &regs->WOLCFGSet);
 	writew(WOLCR_MAGIC_EN, &regs->WOLCRSet);
@@ -3236,7 +3170,8 @@
 
 		memcpy(arp->ar_tip, vptr->ip_addr, 4);
 
-		crc = wol_calc_crc((sizeof(struct arp_packet) + 7) / 8, buf, (u8 *) & mask_pattern[0][0]);
+		crc = wol_calc_crc((sizeof(struct arp_packet) + 7) / 8, buf,
+				(u8 *) & mask_pattern[0][0]);
 
 		writew(crc, &regs->PatternCRC[0]);
 		writew(WOLCR_ARP_EN, &regs->WOLCRSet);
@@ -3275,3 +3210,92 @@
 	return 0;
 }
 
+static int velocity_suspend(struct pci_dev *pdev, u32 state)
+{
+	struct velocity_info *vptr = pci_get_drvdata(pdev);
+	unsigned long flags;
+
+	if(!netif_running(vptr->dev))
+		return 0;
+
+	netif_device_detach(vptr->dev);
+
+	spin_lock_irqsave(&vptr->lock, flags);
+	pci_save_state(pdev, vptr->pci_state);
+#ifdef ETHTOOL_GWOL
+	if (vptr->flags & VELOCITY_FLAGS_WOL_ENABLED) {
+		velocity_get_ip(vptr);
+		velocity_save_context(vptr, &vptr->context);
+		velocity_shutdown(vptr);
+		velocity_set_wol(vptr);
+		pci_enable_wake(pdev, 3, 1);
+		pci_set_power_state(pdev, 3);
+	} else {
+		velocity_save_context(vptr, &vptr->context);
+		velocity_shutdown(vptr);
+		pci_disable_device(pdev);
+		pci_set_power_state(pdev, state);
+	}
+#else
+	pci_set_power_state(pdev, state);
+#endif
+	spin_unlock_irqrestore(&vptr->lock, flags);
+	return 0;
+}
+
+static int velocity_resume(struct pci_dev *pdev)
+{
+	struct velocity_info *vptr = pci_get_drvdata(pdev);
+	unsigned long flags;
+	int i;
+
+	if(!netif_running(vptr->dev))
+		return 0;
+
+	pci_set_power_state(pdev, 0);
+	pci_enable_wake(pdev, 0, 0);
+	pci_restore_state(pdev, vptr->pci_state);
+
+	mac_wol_reset(vptr->mac_regs);
+
+	spin_lock_irqsave(&vptr->lock, flags);
+	velocity_restore_context(vptr, &vptr->context);
+	velocity_init_registers(vptr, VELOCITY_INIT_WOL);
+	mac_disable_int(vptr->mac_regs);
+
+	velocity_tx_srv(vptr, 0);
+
+	for (i = 0; i < vptr->num_txq; i++) {
+		if (vptr->td_used[i]) {
+			mac_tx_queue_wake(vptr->mac_regs, i);
+		}
+	}
+
+	mac_enable_int(vptr->mac_regs);
+	spin_unlock_irqrestore(&vptr->lock, flags);
+	netif_device_attach(vptr->dev);
+
+	return 0;
+}
+
+static int velocity_netdev_event(struct notifier_block *nb, unsigned long notification, void *ptr)
+{
+	struct in_ifaddr *ifa = (struct in_ifaddr *) ptr;
+
+	if (ifa) {
+		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;
+}
+#endif
diff -Nru a/drivers/net/via-velocity.h b/drivers/net/via-velocity.h
--- a/drivers/net/via-velocity.h	2004-10-18 14:57:04 -07:00
+++ b/drivers/net/via-velocity.h	2004-10-18 14:57:04 -07:00
@@ -37,7 +37,6 @@
 #define OPTION_DEFAULT      { [0 ... MAX_UNITS-1] = -1}
 
 #define REV_ID_VT6110       (0)
-#define DEVICE_ID           (0x3119)
 
 #define BYTE_REG_BITS_ON(x,p)       do { writeb(readb((p))|(x),(p));} while (0)
 #define WORD_REG_BITS_ON(x,p)       do { writew(readw((p))|(x),(p));} while (0)
@@ -1320,7 +1319,7 @@
 	/* disable CAMEN */
 	writeb(0, &regs->CAMADDR);
 
-	/* Select CAM mask */
+	/* Select mar */
 	BYTE_REG_BITS_SET(CAMCR_PS_MAR, CAMCR_PS1 | CAMCR_PS0, &regs->CAMCR);
 }
 
@@ -1361,7 +1360,7 @@
 
 	writeb(0, &regs->CAMADDR);
 
-	/* Select CAM mask */
+	/* Select mar */
 	BYTE_REG_BITS_SET(CAMCR_PS_MAR, CAMCR_PS1 | CAMCR_PS0, &regs->CAMCR);
 }
 
@@ -1402,7 +1401,7 @@
 
 	writeb(0, &regs->CAMADDR);
 
-	/* Select CAM mask */
+	/* Select mar */
 	BYTE_REG_BITS_SET(CAMCR_PS_MAR, CAMCR_PS1 | CAMCR_PS0, &regs->CAMCR);
 }
 
@@ -1734,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
 
@@ -1772,7 +1770,8 @@
 	struct velocity_td_info *td_infos[TX_QUEUE_NO];
 
 	int rd_curr;
-	int rd_used;
+	int rd_dirty;
+	u32 rd_filled;
 	struct rx_desc *rd_ring;
 	struct velocity_rd_info *rd_info;	/* It's an array */
 
@@ -1793,7 +1792,6 @@
 	u8 mCAMmask[(MCAM_SIZE / 8)];
 
 	spinlock_t lock;
-	spinlock_t xmit_lock;
 
 	int wol_opts;
 	u8 wol_passwd[6];
diff -Nru a/drivers/net/wan/cycx_x25.c b/drivers/net/wan/cycx_x25.c
--- a/drivers/net/wan/cycx_x25.c	2004-10-18 14:56:17 -07:00
+++ b/drivers/net/wan/cycx_x25.c	2004-10-18 14:56:17 -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/dscc4.c b/drivers/net/wan/dscc4.c
--- a/drivers/net/wan/dscc4.c	2004-10-18 14:57:19 -07:00
+++ b/drivers/net/wan/dscc4.c	2004-10-18 14:57:19 -07:00
@@ -351,8 +351,8 @@
 #endif
 
 /* Functions prototypes */
-static inline void dscc4_rx_irq(struct dscc4_pci_priv *, struct dscc4_dev_priv *);
-static inline void dscc4_tx_irq(struct dscc4_pci_priv *, struct dscc4_dev_priv *);
+static void dscc4_rx_irq(struct dscc4_pci_priv *, struct dscc4_dev_priv *);
+static void dscc4_tx_irq(struct dscc4_pci_priv *, struct dscc4_dev_priv *);
 static int dscc4_found1(struct pci_dev *, unsigned long ioaddr);
 static int dscc4_init_one(struct pci_dev *, const struct pci_device_id *ent);
 static int dscc4_open(struct net_device *);
@@ -366,7 +366,6 @@
 static irqreturn_t dscc4_irq(int irq, void *dev_id, struct pt_regs *ptregs);
 static int dscc4_hdlc_attach(struct net_device *, unsigned short, unsigned short);
 static int dscc4_set_iface(struct dscc4_dev_priv *, struct net_device *);
-static inline int dscc4_set_quartz(struct dscc4_dev_priv *, int);
 #ifdef DSCC4_POLLING
 static int dscc4_tx_poll(struct dscc4_dev_priv *, struct net_device *);
 #endif
@@ -866,6 +865,18 @@
 	//scc_writel(0x00250008 & ~RxActivate, dpriv, dev, CCR2);
 }
 
+static inline int dscc4_set_quartz(struct dscc4_dev_priv *dpriv, int hz)
+{
+	int ret = 0;
+
+	if ((hz < 0) || (hz > DSCC4_HZ_MAX))
+		ret = -EOPNOTSUPP;
+	else
+		dpriv->pci_priv->xtal_hz = hz;
+
+	return ret;
+}
+
 static int dscc4_found1(struct pci_dev *pdev, unsigned long ioaddr)
 {
 	struct dscc4_pci_priv *ppriv;
@@ -1340,18 +1351,6 @@
 	return ret;
 }
 
-static inline int dscc4_set_quartz(struct dscc4_dev_priv *dpriv, int hz)
-{
-	int ret = 0;
-
-	if ((hz < 0) || (hz > DSCC4_HZ_MAX))
-		ret = -EOPNOTSUPP;
-	else
-		dpriv->pci_priv->xtal_hz = hz;
-
-	return ret;
-}
-
 static int dscc4_match(struct thingie *p, int value)
 {
 	int i;
@@ -1531,7 +1530,7 @@
 	return IRQ_RETVAL(handled);
 }
 
-static inline void dscc4_tx_irq(struct dscc4_pci_priv *ppriv,
+static void dscc4_tx_irq(struct dscc4_pci_priv *ppriv,
 				struct dscc4_dev_priv *dpriv)
 {
 	struct net_device *dev = dscc4_to_dev(dpriv);
@@ -1700,7 +1699,7 @@
 	goto try;
 }
 
-static inline void dscc4_rx_irq(struct dscc4_pci_priv *priv,
+static void dscc4_rx_irq(struct dscc4_pci_priv *priv,
 				    struct dscc4_dev_priv *dpriv)
 {
 	struct net_device *dev = dscc4_to_dev(dpriv);
diff -Nru a/drivers/net/wan/hd6457x.c b/drivers/net/wan/hd6457x.c
--- a/drivers/net/wan/hd6457x.c	2004-10-18 14:56:17 -07:00
+++ b/drivers/net/wan/hd6457x.c	2004-10-18 14:56:17 -07:00
@@ -463,8 +463,8 @@
 			brv >>= 1; /* brv = 2^9 = 512 max in specs */
 
 			/* Baud Rate = CLOCK_BASE / TMC / 2^BR */
-			tmc = CLOCK_BASE / (brv * port->settings.clock_rate);
-		}while(br > 1 && tmc <= 128);
+			tmc = CLOCK_BASE / brv / port->settings.clock_rate;
+		}while (br > 1 && tmc <= 128);
 
 		if (tmc < 1) {
 			tmc = 1;
@@ -473,7 +473,7 @@
 		} else if (tmc > 255)
 			tmc = 256; /* tmc=0 means 256 - low baud rates */
 
-		port->settings.clock_rate = CLOCK_BASE / (brv * tmc);
+		port->settings.clock_rate = CLOCK_BASE / brv / tmc;
 	} else {
 		br = 9; /* Minimum clock rate */
 		tmc = 256;	/* 8bit = 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	2004-10-18 14:56:28 -07:00
+++ b/drivers/net/wan/lmc/lmc_debug.c	2004-10-18 14:56:28 -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/net/wan/pc300.h b/drivers/net/wan/pc300.h
--- a/drivers/net/wan/pc300.h	2004-10-18 14:56:27 -07:00
+++ b/drivers/net/wan/pc300.h	2004-10-18 14:56:27 -07:00
@@ -164,9 +164,9 @@
  * (required to support Alpha systems) *
  ***************************************/
 #ifdef __KERNEL__
-#define cpc_writeb(port,val)	{writeb((ucchar)(val),(ulong)(port)); mb();}
-#define cpc_writew(port,val)	{writew((ushort)(val),(ulong)(port)); mb();}
-#define cpc_writel(port,val)	{writel((uclong)(val),(ulong)(port)); mb();}
+#define cpc_writeb(port,val)	{writeb((ucchar)(val),(port)); mb();}
+#define cpc_writew(port,val)	{writew((ushort)(val),(port)); mb();}
+#define cpc_writel(port,val)	{writel((uclong)(val),(port)); mb();}
 
 #define cpc_readb(port)		readb(port)
 #define cpc_readw(port)		readw(port)
@@ -358,17 +358,17 @@
 	uclong iophys;		/* PLX registers I/O base */
 	uclong iosize;		/* PLX registers I/O size */
 	uclong plxphys;		/* PLX registers MMIO base (physical) */
-	uclong plxbase;		/* PLX registers MMIO base (virtual) */
+	void __iomem * plxbase;	/* PLX registers MMIO base (virtual) */
 	uclong plxsize;		/* PLX registers MMIO size */
 	uclong scaphys;		/* SCA registers MMIO base (physical) */
-	uclong scabase;		/* SCA registers MMIO base (virtual) */
+	void __iomem * scabase;	/* SCA registers MMIO base (virtual) */
 	uclong scasize;		/* SCA registers MMIO size */
 	uclong ramphys;		/* On-board RAM MMIO base (physical) */
-	uclong rambase;		/* On-board RAM MMIO base (virtual) */
+	void __iomem * rambase;	/* On-board RAM MMIO base (virtual) */
 	uclong alloc_ramsize;	/* RAM MMIO size allocated by the PCI bridge */
 	uclong ramsize;		/* On-board RAM MMIO size */
 	uclong falcphys;	/* FALC registers MMIO base (physical) */
-	uclong falcbase;	/* FALC registers MMIO base (virtual) */
+	void __iomem * falcbase;/* FALC registers MMIO base (virtual) */
 	uclong falcsize;	/* FALC registers MMIO size */
 } pc300hw_t;
 
diff -Nru a/drivers/net/wan/pc300_drv.c b/drivers/net/wan/pc300_drv.c
--- a/drivers/net/wan/pc300_drv.c	2004-10-18 14:57:04 -07:00
+++ b/drivers/net/wan/pc300_drv.c	2004-10-18 14:57:04 -07:00
@@ -307,7 +307,7 @@
 {
 	int i;
 	int ch_factor = ch * N_DMA_TX_BUF;
-	volatile pcsca_bd_t *ptdescr = (pcsca_bd_t *) (card->hw.rambase
+	volatile pcsca_bd_t __iomem *ptdescr = (card->hw.rambase
 			               + DMA_TX_BD_BASE + ch_factor * sizeof(pcsca_bd_t));
 
 	for (i = 0; i < N_DMA_TX_BUF; i++, ptdescr++) {
@@ -322,7 +322,7 @@
 {
 	int i;
 	int ch_factor = ch * N_DMA_TX_BUF;
-	volatile pcsca_bd_t *ptdescr = (pcsca_bd_t *) (card->hw.rambase
+	volatile pcsca_bd_t __iomem *ptdescr = (card->hw.rambase
 			       + DMA_TX_BD_BASE + ch_factor * sizeof(pcsca_bd_t));
 
 	for (i = 0; i < N_DMA_TX_BUF; i++, ptdescr++) {
@@ -337,7 +337,7 @@
 {
 	int i;
 	int ch_factor = ch * N_DMA_RX_BUF;
-	volatile pcsca_bd_t *ptdescr = (pcsca_bd_t *) (card->hw.rambase
+	volatile pcsca_bd_t __iomem *ptdescr = (card->hw.rambase
 				       + DMA_RX_BD_BASE + ch_factor * sizeof(pcsca_bd_t));
 
 	for (i = 0; i < N_DMA_RX_BUF; i++, ptdescr++) {
@@ -352,7 +352,7 @@
 {
 	int i;
 	int ch_factor = ch * N_DMA_RX_BUF;
-	volatile pcsca_bd_t *ptdescr = (pcsca_bd_t *) (card->hw.rambase
+	volatile pcsca_bd_t __iomem *ptdescr = (card->hw.rambase
 				       + DMA_RX_BD_BASE + ch_factor * sizeof(pcsca_bd_t));
 
 	for (i = 0; i < N_DMA_RX_BUF; i++, ptdescr++) {
@@ -365,7 +365,7 @@
 
 static void tx_dma_buf_check(pc300_t * card, int ch)
 {
-	volatile pcsca_bd_t *ptdescr;
+	volatile pcsca_bd_t __iomem *ptdescr;
 	int i;
 	ucshort first_bd = card->chan[ch].tx_first_bd;
 	ucshort next_bd = card->chan[ch].tx_next_bd;
@@ -374,10 +374,10 @@
 	       first_bd, TX_BD_ADDR(ch, first_bd),
 	       next_bd, TX_BD_ADDR(ch, next_bd));
 	for (i = first_bd,
-	     ptdescr = (pcsca_bd_t *) (card->hw.rambase + TX_BD_ADDR(ch, first_bd));
+	     ptdescr = (card->hw.rambase + TX_BD_ADDR(ch, first_bd));
 	     i != ((next_bd + 1) & (N_DMA_TX_BUF - 1));
 	     i = (i + 1) & (N_DMA_TX_BUF - 1), 
-		 ptdescr = (pcsca_bd_t *) (card->hw.rambase + TX_BD_ADDR(ch, i))) {
+		 ptdescr = (card->hw.rambase + TX_BD_ADDR(ch, i))) {
 		printk("\n CH%d TX%d: next=0x%lx, ptbuf=0x%lx, ST=0x%x, len=%d",
 		       ch, i, (uclong) cpc_readl(&ptdescr->next),
 		       (uclong) cpc_readl(&ptdescr->ptbuf),
@@ -390,7 +390,7 @@
 /* Show all TX buffer descriptors */
 static void tx1_dma_buf_check(pc300_t * card, int ch)
 {
-	volatile pcsca_bd_t *ptdescr;
+	volatile pcsca_bd_t __iomem *ptdescr;
 	int i;
 	ucshort first_bd = card->chan[ch].tx_first_bd;
 	ucshort next_bd = card->chan[ch].tx_next_bd;
@@ -404,7 +404,7 @@
 	       (uclong) cpc_readl(scabase + DTX_REG(CDAL, ch)),
 	       (uclong) cpc_readl(scabase + DTX_REG(EDAL, ch)));
 	for (i = 0; i < N_DMA_TX_BUF; i++) {
-		ptdescr = (pcsca_bd_t *) (card->hw.rambase + TX_BD_ADDR(ch, i));
+		ptdescr = (card->hw.rambase + TX_BD_ADDR(ch, i));
 		printk("\n CH%d TX%d: next=0x%lx, ptbuf=0x%lx, ST=0x%x, len=%d",
 		       ch, i, (uclong) cpc_readl(&ptdescr->next),
 		       (uclong) cpc_readl(&ptdescr->ptbuf),
@@ -416,7 +416,7 @@
 			 
 static void rx_dma_buf_check(pc300_t * card, int ch)
 {
-	volatile pcsca_bd_t *ptdescr;
+	volatile pcsca_bd_t __iomem *ptdescr;
 	int i;
 	ucshort first_bd = card->chan[ch].rx_first_bd;
 	ucshort last_bd = card->chan[ch].rx_last_bd;
@@ -424,7 +424,7 @@
 
 	ch_factor = ch * N_DMA_RX_BUF;
 	printk("#CH%d: f_bd = %d, l_bd = %d\n", ch, first_bd, last_bd);
-	for (i = 0, ptdescr = (pcsca_bd_t *) (card->hw.rambase +
+	for (i = 0, ptdescr = (card->hw.rambase +
 					      DMA_RX_BD_BASE + ch_factor * sizeof(pcsca_bd_t));
 	     i < N_DMA_RX_BUF; i++, ptdescr++) {
 		if (cpc_readb(&ptdescr->status) & DST_OSB)
@@ -439,12 +439,12 @@
 
 int dma_get_rx_frame_size(pc300_t * card, int ch)
 {
-	volatile pcsca_bd_t *ptdescr;
+	volatile pcsca_bd_t __iomem *ptdescr;
 	ucshort first_bd = card->chan[ch].rx_first_bd;
 	int rcvd = 0;
 	volatile ucchar status;
 
-	ptdescr = (pcsca_bd_t *)(card->hw.rambase + RX_BD_ADDR(ch, first_bd));
+	ptdescr = (card->hw.rambase + RX_BD_ADDR(ch, first_bd));
 	while ((status = cpc_readb(&ptdescr->status)) & DST_OSB) {
 		rcvd += cpc_readw(&ptdescr->len);
 		first_bd = (first_bd + 1) & (N_DMA_RX_BUF - 1);
@@ -453,7 +453,7 @@
 			* (dma_buf_read will clean the buffer descriptors in this case). */
 			return (rcvd);
 		}
-		ptdescr = (pcsca_bd_t *)(card->hw.rambase + cpc_readl(&ptdescr->next));
+		ptdescr = (card->hw.rambase + cpc_readl(&ptdescr->next));
 	}
 	return (-1);
 }
@@ -465,7 +465,7 @@
 int dma_buf_write(pc300_t * card, int ch, ucchar * ptdata, int len)
 {
 	int i, nchar;
-	volatile pcsca_bd_t *ptdescr;
+	volatile pcsca_bd_t __iomem *ptdescr;
 	int tosend = len;
 	ucchar nbuf = ((len - 1) / BD_DEF_LEN) + 1;
 
@@ -474,11 +474,11 @@
 	}
 
 	for (i = 0; i < nbuf; i++) {
-		ptdescr = (pcsca_bd_t *) (card->hw.rambase +
+		ptdescr = (card->hw.rambase +
 					  TX_BD_ADDR(ch, card->chan[ch].tx_next_bd));
 		nchar = cpc_min(BD_DEF_LEN, tosend);
 		if (cpc_readb(&ptdescr->status) & DST_OSB) {
-			memcpy_toio((void *)(card->hw.rambase + cpc_readl(&ptdescr->ptbuf)),
+			memcpy_toio((card->hw.rambase + cpc_readl(&ptdescr->ptbuf)),
 				    &ptdata[len - tosend], nchar);
 			cpc_writew(&ptdescr->len, nchar);
 			card->chan[ch].nfree_tx_bd--;
@@ -507,11 +507,11 @@
 {
 	int nchar;
 	pc300ch_t *chan = (pc300ch_t *) & card->chan[ch];
-	volatile pcsca_bd_t *ptdescr;
+	volatile pcsca_bd_t __iomem *ptdescr;
 	int rcvd = 0;
 	volatile ucchar status;
 
-	ptdescr = (pcsca_bd_t *) (card->hw.rambase +
+	ptdescr = (card->hw.rambase +
 				  RX_BD_ADDR(ch, chan->rx_first_bd));
 	while ((status = cpc_readb(&ptdescr->status)) & DST_OSB) {
 		nchar = cpc_readw(&ptdescr->len);
@@ -527,7 +527,7 @@
 				chan->rx_first_bd = (chan->rx_first_bd+1) & (N_DMA_RX_BUF-1);
 				if (status & DST_EOM)
 					break;
-				ptdescr = (pcsca_bd_t *) (card->hw.rambase +
+				ptdescr = (card->hw.rambase +
 							  cpc_readl(&ptdescr->next));
 				status = cpc_readb(&ptdescr->status);
 			}
@@ -536,7 +536,7 @@
 		if (nchar != 0) {
 			if (skb) {
 				memcpy_fromio(skb_put(skb, nchar),
-				 (void *)(card->hw.rambase+cpc_readl(&ptdescr->ptbuf)),nchar);
+				 (card->hw.rambase+cpc_readl(&ptdescr->ptbuf)),nchar);
 			}
 			rcvd += nchar;
 		}
@@ -547,7 +547,7 @@
 		if (status & DST_EOM)
 			break;
 
-		ptdescr = (pcsca_bd_t *) (card->hw.rambase + cpc_readl(&ptdescr->next));
+		ptdescr = (card->hw.rambase + cpc_readl(&ptdescr->next));
 	}
 
 	if (rcvd != 0) {
@@ -562,7 +562,7 @@
 
 void tx_dma_stop(pc300_t * card, int ch)
 {
-	uclong scabase = card->hw.scabase;
+	void __iomem *scabase = card->hw.scabase;
 	ucchar drr_ena_bit = 1 << (5 + 2 * ch);
 	ucchar drr_rst_bit = 1 << (1 + 2 * ch);
 
@@ -573,7 +573,7 @@
 
 void rx_dma_stop(pc300_t * card, int ch)
 {
-	uclong scabase = card->hw.scabase;
+	void __iomem *scabase = card->hw.scabase;
 	ucchar drr_ena_bit = 1 << (4 + 2 * ch);
 	ucchar drr_rst_bit = 1 << (2 * ch);
 
@@ -584,7 +584,7 @@
 
 void rx_dma_start(pc300_t * card, int ch)
 {
-	uclong scabase = card->hw.scabase;
+	void __iomem *scabase = card->hw.scabase;
 	pc300ch_t *chan = (pc300ch_t *) & card->chan[ch];
 	
 	/* Start DMA */
@@ -609,7 +609,7 @@
 /*************************/
 void falc_issue_cmd(pc300_t * card, int ch, ucchar cmd)
 {
-	uclong falcbase = card->hw.falcbase;
+	void __iomem *falcbase = card->hw.falcbase;
 	unsigned long i = 0;
 
 	while (cpc_readb(falcbase + F_REG(SIS, ch)) & SIS_CEC) {
@@ -627,7 +627,7 @@
 	pc300ch_t *chan = (pc300ch_t *) & card->chan[ch];
 	pc300chconf_t *conf = (pc300chconf_t *) & chan->conf;
 	falc_t *pfalc = (falc_t *) & chan->falc;
-	uclong falcbase = card->hw.falcbase;
+	void __iomem *falcbase = card->hw.falcbase;
 
 	/* Interrupt pins are open-drain */
 	cpc_writeb(falcbase + F_REG(IPC, ch),
@@ -674,7 +674,7 @@
 
 void falc_open_timeslot(pc300_t * card, int ch, int timeslot)
 {
-	uclong falcbase = card->hw.falcbase;
+	void __iomem *falcbase = card->hw.falcbase;
 	ucchar tshf = card->chan[ch].falc.offset;
 
 	cpc_writeb(falcbase + F_REG((ICB1 + (timeslot - tshf) / 8), ch),
@@ -690,7 +690,7 @@
 
 void falc_close_timeslot(pc300_t * card, int ch, int timeslot)
 {
-	uclong falcbase = card->hw.falcbase;
+	void __iomem *falcbase = card->hw.falcbase;
 	ucchar tshf = card->chan[ch].falc.offset;
 
 	cpc_writeb(falcbase + F_REG((ICB1 + (timeslot - tshf) / 8), ch),
@@ -708,7 +708,7 @@
 {
 	pc300ch_t *chan = (pc300ch_t *) & card->chan[ch];
 	pc300chconf_t *conf = (pc300chconf_t *) & chan->conf;
-	uclong falcbase = card->hw.falcbase;
+	void __iomem *falcbase = card->hw.falcbase;
 
 	cpc_writeb(falcbase + F_REG(ICB1, ch), 0xff);
 	cpc_writeb(falcbase + F_REG(TTR1, ch), 0);
@@ -730,7 +730,7 @@
 {
 	pc300ch_t *chan = (pc300ch_t *) & card->chan[ch];
 	pc300chconf_t *conf = (pc300chconf_t *) & chan->conf;
-	uclong falcbase = card->hw.falcbase;
+	void __iomem *falcbase = card->hw.falcbase;
 
 	cpc_writeb(falcbase + F_REG(ICB1, ch), 0);
 	if (conf->fr_mode == PC300_FR_UNFRAMED) {
@@ -811,7 +811,7 @@
 	pc300ch_t *chan = (pc300ch_t *) & card->chan[ch];
 	pc300chconf_t *conf = (pc300chconf_t *) & chan->conf;
 	falc_t *pfalc = (falc_t *) & chan->falc;
-	uclong falcbase = card->hw.falcbase;
+	void __iomem *falcbase = card->hw.falcbase;
 	ucchar dja = (ch ? (LIM2_DJA2 | LIM2_DJA1) : 0);
 
 	/* Switch to T1 mode (PCM 24) */
@@ -980,7 +980,7 @@
 	pc300ch_t *chan = (pc300ch_t *) & card->chan[ch];
 	pc300chconf_t *conf = (pc300chconf_t *) & chan->conf;
 	falc_t *pfalc = (falc_t *) & chan->falc;
-	uclong falcbase = card->hw.falcbase;
+	void __iomem *falcbase = card->hw.falcbase;
 	ucchar dja = (ch ? (LIM2_DJA2 | LIM2_DJA1) : 0);
 
 	/* Switch to E1 mode (PCM 30) */
@@ -1157,7 +1157,7 @@
 
 void falc_init_hdlc(pc300_t * card, int ch)
 {
-	uclong falcbase = card->hw.falcbase;
+	void __iomem *falcbase = card->hw.falcbase;
 	pc300ch_t *chan = (pc300ch_t *) & card->chan[ch];
 	pc300chconf_t *conf = (pc300chconf_t *) & chan->conf;
 
@@ -1186,7 +1186,7 @@
 	pc300ch_t *chan = (pc300ch_t *) & card->chan[ch];
 	pc300chconf_t *conf = (pc300chconf_t *) & chan->conf;
 	falc_t *pfalc = (falc_t *) & chan->falc;
-	uclong falcbase = card->hw.falcbase;
+	void __iomem *falcbase = card->hw.falcbase;
 	ucchar dummy;
 	unsigned long flags;
 
@@ -1246,7 +1246,7 @@
 	pc300ch_t *chan = (pc300ch_t *) & card->chan[ch];
 	pc300chconf_t *conf = (pc300chconf_t *) & chan->conf;
 	falc_t *pfalc = (falc_t *) & chan->falc;
-	uclong falcbase = card->hw.falcbase;
+	void __iomem *falcbase = card->hw.falcbase;
 
 	/* Verify LOS */
 	if (frs0 & FRS0_LOS) {
@@ -1402,7 +1402,7 @@
 	pc300ch_t *chan = (pc300ch_t *) & card->chan[ch];
 	pc300chconf_t *conf = (pc300chconf_t *) & chan->conf;
 	falc_t *pfalc = (falc_t *) & chan->falc;
-	uclong falcbase = card->hw.falcbase;
+	void __iomem *falcbase = card->hw.falcbase;
 	ucshort counter;
 
 	counter = cpc_readb(falcbase + F_REG(FECL, ch));
@@ -1455,7 +1455,7 @@
 	pc300ch_t *chan = (pc300ch_t *) & card->chan[ch];
 	pc300chconf_t *conf = (pc300chconf_t *) & chan->conf;
 	falc_t *pfalc = (falc_t *) & chan->falc;
-	uclong falcbase = card->hw.falcbase;
+	void __iomem *falcbase = card->hw.falcbase;
 
 	if (loop_on) {
 		// EVENT_FALC_ABNORMAL
@@ -1499,7 +1499,7 @@
 {
 	pc300ch_t *chan = (pc300ch_t *) & card->chan[ch];
 	falc_t *pfalc = (falc_t *) & chan->falc;
-	uclong falcbase = card->hw.falcbase;
+	void __iomem *falcbase = card->hw.falcbase;
 
 	if (loop_on) {
 		cpc_writeb(falcbase + F_REG(LIM0, ch),
@@ -1527,7 +1527,7 @@
 	pc300ch_t *chan = (pc300ch_t *) & card->chan[ch];
 	pc300chconf_t *conf = (pc300chconf_t *) & chan->conf;
 	falc_t *pfalc = (falc_t *) & chan->falc;
-	uclong falcbase = card->hw.falcbase;
+	void __iomem *falcbase = card->hw.falcbase;
 
 	if (loop_on) {
 		// EVENT_FALC_ABNORMAL
@@ -1580,7 +1580,7 @@
 {
 	pc300ch_t *chan = (pc300ch_t *) & card->chan[ch];
 	pc300chconf_t *conf = (pc300chconf_t *) & chan->conf;
-	uclong falcbase = card->hw.falcbase;
+	void __iomem *falcbase = card->hw.falcbase;
 
 	if (conf->media == IF_IFACE_T1) {
 		cpc_writeb(falcbase + F_REG(FMR5, ch),
@@ -1601,7 +1601,7 @@
 {
 	pc300ch_t *chan = (pc300ch_t *) & card->chan[ch];
 	pc300chconf_t *conf = (pc300chconf_t *) & chan->conf;
-	uclong falcbase = card->hw.falcbase;
+	void __iomem *falcbase = card->hw.falcbase;
 
 	if (conf->media == IF_IFACE_T1) {
 		cpc_writeb(falcbase + F_REG(FMR5, ch),
@@ -1624,7 +1624,7 @@
 	pc300ch_t *chan = (pc300ch_t *) & card->chan[ch];
 	pc300chconf_t *conf = (pc300chconf_t *) & chan->conf;
 	falc_t *pfalc = (falc_t *) & chan->falc;
-	uclong falcbase = card->hw.falcbase;
+	void __iomem *falcbase = card->hw.falcbase;
 
 	if (conf->media == IF_IFACE_T1) {
 		cpc_writeb(falcbase + F_REG(FMR5, ch),
@@ -1657,7 +1657,7 @@
 	pc300ch_t *chan = (pc300ch_t *) & card->chan[ch];
 	pc300chconf_t *conf = (pc300chconf_t *) & chan->conf;
 	falc_t *pfalc = (falc_t *) & chan->falc;
-	uclong falcbase = card->hw.falcbase;
+	void __iomem *falcbase = card->hw.falcbase;
 
 	if (conf->media == IF_IFACE_T1) {
 		cpc_writeb(falcbase + F_REG(FMR5, ch),
@@ -1687,7 +1687,7 @@
 	pc300ch_t *chan = (pc300ch_t *) & card->chan[ch];
 	pc300chconf_t *conf = (pc300chconf_t *) & chan->conf;
 	falc_t *pfalc = (falc_t *) & chan->falc;
-	uclong falcbase = card->hw.falcbase;
+	void __iomem *falcbase = card->hw.falcbase;
 
 	if (activate) {
 		pfalc->prbs = 1;
@@ -1973,11 +1973,11 @@
 	pc300ch_t *chan = (pc300ch_t *)dev->chan; 
 	pc300_t *card = (pc300_t *)chan->card; 
 	int ch = chan->channel; 
-	volatile pcsca_bd_t * ptdescr; 
+	volatile pcsca_bd_t __iomem * ptdescr; 
 	struct net_device_stats *stats = hdlc_stats(dev->dev);
 
     /* Clean up descriptors from previous transmission */
-	ptdescr = (pcsca_bd_t *)(card->hw.rambase +
+	ptdescr = (card->hw.rambase +
 						TX_BD_ADDR(ch,chan->tx_first_bd));
 	while ((cpc_readl(card->hw.scabase + DTX_REG(CDAL,ch)) != 
 							TX_BD_ADDR(ch,chan->tx_first_bd)) && 
@@ -1988,8 +1988,7 @@
 		cpc_writew(&ptdescr->len, 0);
 		chan->nfree_tx_bd++;
 		chan->tx_first_bd = (chan->tx_first_bd + 1) & (N_DMA_TX_BUF - 1);
-		ptdescr = (pcsca_bd_t *)(card->hw.rambase +
-						TX_BD_ADDR(ch,chan->tx_first_bd));
+		ptdescr = (card->hw.rambase + TX_BD_ADDR(ch,chan->tx_first_bd));
     }
 
 #ifdef CONFIG_PC300_MLPPP
@@ -2006,7 +2005,7 @@
 
 static void sca_intr(pc300_t * card)
 {
-	uclong scabase = card->hw.scabase;
+	void __iomem *scabase = card->hw.scabase;
 	volatile uclong status;
 	int ch;
 	int intr_count = 0;
@@ -2187,7 +2186,7 @@
 {
 	pc300ch_t *chan = (pc300ch_t *) & card->chan[ch];
 	falc_t *pfalc = (falc_t *) & chan->falc;
-	uclong falcbase = card->hw.falcbase;
+	void __iomem *falcbase = card->hw.falcbase;
 
 	if (((cpc_readb(falcbase + F_REG(LCR1, ch)) & LCR1_XPRBS) == 0) &&
 	    !pfalc->loop_gen) {
@@ -2212,7 +2211,7 @@
 {
 	pc300ch_t *chan = (pc300ch_t *) & card->chan[ch];
 	falc_t *pfalc = (falc_t *) & chan->falc;
-	uclong falcbase = card->hw.falcbase;
+	void __iomem *falcbase = card->hw.falcbase;
 
 	if (((cpc_readb(falcbase + F_REG(LCR1, ch)) & LCR1_XPRBS) == 0) &&
 	    !pfalc->loop_gen) {
@@ -2237,7 +2236,7 @@
 {
 	pc300ch_t *chan = (pc300ch_t *) & card->chan[ch];
 	falc_t *pfalc = (falc_t *) & chan->falc;
-	uclong falcbase = card->hw.falcbase;
+	void __iomem *falcbase = card->hw.falcbase;
 	ucchar isr0, isr3, gis;
 	ucchar dummy;
 
@@ -2284,7 +2283,7 @@
 {
 	pc300ch_t *chan = (pc300ch_t *) & card->chan[ch];
 	falc_t *pfalc = (falc_t *) & chan->falc;
-	uclong falcbase = card->hw.falcbase;
+	void __iomem *falcbase = card->hw.falcbase;
 	ucchar isr1, isr2, isr3, gis, rsp;
 	ucchar dummy;
 
@@ -2408,7 +2407,7 @@
 void cpc_sca_status(pc300_t * card, int ch)
 {
 	ucchar ilar;
-	uclong scabase = card->hw.scabase;
+	void __iomem *scabase = card->hw.scabase;
 	uclong flags;
 
 	tx_dma_buf_check(card, ch);
@@ -2544,7 +2543,7 @@
 	int ch = chan->channel;
 	void __user *arg = ifr->ifr_data;
 	struct if_settings *settings = &ifr->ifr_settings;
-	uclong scabase = card->hw.scabase;
+	void __iomem *scabase = card->hw.scabase;
 
 	if (!capable(CAP_NET_ADMIN))
 		return -EPERM;
@@ -2863,8 +2862,8 @@
 	pc300ch_t *chan = (pc300ch_t *) d->chan;
 	pc300chconf_t *conf = (pc300chconf_t *) & chan->conf;
 	pc300_t *card = (pc300_t *) chan->card;
-	uclong scabase = card->hw.scabase;
-	uclong plxbase = card->hw.plxbase;
+	void __iomem *scabase = card->hw.scabase;
+	void __iomem *plxbase = card->hw.plxbase;
 	int ch = chan->channel;
 	uclong clkrate = chan->conf.phys_settings.clock_rate;
 	uclong clktype = chan->conf.phys_settings.clock_type;
@@ -3010,7 +3009,7 @@
 {
 	pc300ch_t *chan = (pc300ch_t *) d->chan;
 	pc300_t *card = (pc300_t *) chan->card;
-	uclong scabase = card->hw.scabase;
+	void __iomem *scabase = card->hw.scabase;
 	int ch = chan->channel;
 
 	cpc_writeb(scabase + DSR_RX(ch), 0);
@@ -3041,7 +3040,7 @@
 {
 	pc300ch_t *chan = (pc300ch_t *) d->chan;
 	pc300_t *card = (pc300_t *) chan->card;
-	uclong scabase = card->hw.scabase;
+	void __iomem *scabase = card->hw.scabase;
 	int ch = chan->channel;
 
 	cpc_writeb(scabase + DSR_TX(ch), 0);
@@ -3105,7 +3104,7 @@
 	pc300ch_t *chan = (pc300ch_t *) d->chan;
 	pc300_t *card = (pc300_t *) chan->card;
 	int ch = chan->channel;
-	uclong scabase = card->hw.scabase;
+	void __iomem *scabase = card->hw.scabase;
 
 	ch_config(d);
 
@@ -3211,7 +3210,7 @@
 {
 	uclong i;
 	ucchar data;
-	uclong rambase = card->hw.rambase;
+	void __iomem *rambase = card->hw.rambase;
 
 	card->hw.ramsize = PC300_RAMSIZE;
 	/* Let's find out how much RAM is present on this board */
@@ -3227,7 +3226,7 @@
 
 static void plx_init(pc300_t * card)
 {
-	struct RUNTIME_9050 *plx_ctl = (struct RUNTIME_9050 *) card->hw.plxbase;
+	struct RUNTIME_9050 __iomem *plx_ctl = card->hw.plxbase;
 
 	/* Reset PLX */
 	cpc_writel(&plx_ctl->init_ctrl,
@@ -3532,10 +3531,9 @@
 	if ((err = pci_enable_device(pdev)) != 0)
 		goto err_release_sca;
 
-	card->hw.plxbase = (uclong) ioremap(card->hw.plxphys, card->hw.plxsize);
-	card->hw.rambase = (uclong) ioremap(card->hw.ramphys,
-					    card->hw.alloc_ramsize);
-	card->hw.scabase = (uclong) ioremap(card->hw.scaphys, card->hw.scasize);
+	card->hw.plxbase = ioremap(card->hw.plxphys, card->hw.plxsize);
+	card->hw.rambase = ioremap(card->hw.ramphys, card->hw.alloc_ramsize);
+	card->hw.scabase = ioremap(card->hw.scaphys, card->hw.scasize);
 	switch (device_id) {
 		case PCI_DEVICE_ID_PC300_TE_1:
 		case PCI_DEVICE_ID_PC300_TE_2:
@@ -3543,14 +3541,13 @@
 		case PCI_DEVICE_ID_PC300_TE_M_2:
 			request_mem_region(card->hw.falcphys, card->hw.falcsize,
 					   "FALC Registers");
-			card->hw.falcbase = (uclong) ioremap(card->hw.falcphys,
-							     card->hw.falcsize);
+			card->hw.falcbase = ioremap(card->hw.falcphys, card->hw.falcsize);
 			break;
 
 		case PCI_DEVICE_ID_PC300_RX_1:
 		case PCI_DEVICE_ID_PC300_RX_2:
 		default:
-			card->hw.falcbase = 0;
+			card->hw.falcbase = NULL;
 			break;
 	}
 
@@ -3616,11 +3613,11 @@
 	return 0;
 
 err_io_unmap:
-	iounmap((void *) card->hw.plxbase);
-	iounmap((void *) card->hw.scabase);
-	iounmap((void *) card->hw.rambase);
+	iounmap(card->hw.plxbase);
+	iounmap(card->hw.scabase);
+	iounmap(card->hw.rambase);
 	if (card->hw.type == PC300_TE) {
-		iounmap((void *) card->hw.falcbase);
+		iounmap(card->hw.falcbase);
 		release_mem_region(card->hw.falcphys, card->hw.falcsize);
 	}
 err_release_sca:
@@ -3649,15 +3646,15 @@
 		for (i = 0; i < card->hw.nchan; i++) {
 			unregister_hdlc_device(card->chan[i].d.dev);
 		}
-		iounmap((void *) card->hw.plxbase);
-		iounmap((void *) card->hw.scabase);
-		iounmap((void *) card->hw.rambase);
+		iounmap(card->hw.plxbase);
+		iounmap(card->hw.scabase);
+		iounmap(card->hw.rambase);
 		release_mem_region(card->hw.plxphys, card->hw.plxsize);
 		release_mem_region(card->hw.ramphys, card->hw.alloc_ramsize);
 		release_mem_region(card->hw.scaphys, card->hw.scasize);
 		release_region(card->hw.iophys, card->hw.iosize);
 		if (card->hw.type == PC300_TE) {
-			iounmap((void *) card->hw.falcbase);
+			iounmap(card->hw.falcbase);
 			release_mem_region(card->hw.falcphys, card->hw.falcsize);
 		}
 		for (i = 0; i < card->hw.nchan; i++)
diff -Nru a/drivers/net/wan/pc300_tty.c b/drivers/net/wan/pc300_tty.c
--- a/drivers/net/wan/pc300_tty.c	2004-10-18 14:56:29 -07:00
+++ b/drivers/net/wan/pc300_tty.c	2004-10-18 14:56:29 -07:00
@@ -192,13 +192,14 @@
  */
 void cpc_tty_init(pc300dev_t *pc300dev)
 {
-	int port, aux;
+	unsigned long port;
+	int aux;
 	st_cpc_tty_area * cpc_tty;
 
 	/* hdlcX - X=interface number */
 	port = pc300dev->dev->name[4] - '0';
 	if (port >= CPC_TTY_NPORTS) {
-		printk("%s-tty: invalid interface selected (0-%i): %i", 
+		printk("%s-tty: invalid interface selected (0-%i): %li",
 			pc300dev->dev->name,
 			CPC_TTY_NPORTS-1,port);
 		return;
@@ -634,14 +635,8 @@
 	}
 
 	CPC_TTY_DBG("%s: call wake_up_interruptible\n",cpc_tty->name);
-	
-	wake_up_interruptible(&tty->write_wait); 
-
-	if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) && tty->ldisc.write_wakeup){
-		CPC_TTY_DBG("%s: call line disc. wake up\n",cpc_tty->name);
-		tty->ldisc.write_wakeup(tty); 
-	} 
 
+	tty_wakeup(tty);	
 	return; 
 } 
 
@@ -688,25 +683,32 @@
  */
 static void cpc_tty_rx_work(void * data)
 {
-	int port, i, j;
+	unsigned long port;
+	int i, j;
 	st_cpc_tty_area *cpc_tty; 
 	volatile st_cpc_rx_buf * buf;
 	char flags=0,flg_rx=1; 
+	struct tty_ldisc *ld;
 
 	if (cpc_tty_cnt == 0) return;
 
+	
 	for (i=0; (i < 4) && flg_rx ; i++) {
 		flg_rx = 0;
-		port = (int) data;
+		port = (unsigned long)data;
 		for (j=0; j < CPC_TTY_NPORTS; j++) {
 			cpc_tty = &cpc_tty_area[port];
 		
 			if ((buf=cpc_tty->buf_rx.first) != 0) {
-															
-				if (cpc_tty->tty && (cpc_tty->tty->ldisc.receive_buf)) { 
-					CPC_TTY_DBG("%s: call line disc. receive_buf\n",cpc_tty->name);
-					cpc_tty->tty->ldisc.receive_buf(cpc_tty->tty, (char *)(buf->data), 
-					&flags, buf->size);
+				if(cpc_tty->tty) {
+					ld = tty_ldisc_ref(cpc_tty->tty);
+					if(ld) {
+						if (ld->receive_buf) {
+							CPC_TTY_DBG("%s: call line disc. receive_buf\n",cpc_tty->name);
+							ld->receive_buf(cpc_tty->tty, (char *)(buf->data), &flags, buf->size);
+						}
+						tty_ldisc_deref(ld);
+					}
 				}	
 				cpc_tty->buf_rx.first = cpc_tty->buf_rx.first->next;
 				kfree((unsigned char *)buf);
@@ -760,7 +762,7 @@
 	int rx_len, rx_aux; 
 	volatile unsigned char status; 
 	unsigned short first_bd = pc300chan->rx_first_bd;
-	st_cpc_rx_buf	*new;
+	st_cpc_rx_buf	*new=NULL;
 	unsigned char dsr_rx;
 
 	if (pc300dev->cpc_tty == NULL) { 
@@ -789,6 +791,10 @@
 				cpc_writel(card->hw.scabase + DRX_REG(EDAL, ch), 
 						RX_BD_ADDR(ch, pc300chan->rx_last_bd)); 
 			}
+			if (new) {
+				kfree(new);
+				new = NULL;
+			}
 			return; 
 		}
 		
@@ -834,7 +840,8 @@
 						cpc_tty->name);
 				cpc_tty_rx_disc_frame(pc300chan);
 				rx_len = 0;
-				kfree((unsigned char *)new);
+				kfree(new);
+				new = NULL;
 				break; /* read next frame - while(1) */
 			}
 
@@ -843,7 +850,8 @@
 				cpc_tty_rx_disc_frame(pc300chan);
 				stats->rx_dropped++; 
 				rx_len = 0; 
-				kfree((unsigned char *)new);
+				kfree(new);
+				new = NULL;
 				break; /* read next frame - while(1) */
 			}
 
@@ -910,13 +918,7 @@
 		CPC_TTY_DBG("%s: the interface is not opened\n",cpc_tty->name);
 		return; 
 	}
-
-	if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) && tty->ldisc.write_wakeup){
-		CPC_TTY_DBG("%s:call line disc. wakeup\n",cpc_tty->name);
-		tty->ldisc.write_wakeup (tty); 
-	}
-
-	wake_up_interruptible(&tty->write_wait); 
+	tty_wakeup(tty);
 }
 
 /*
diff -Nru a/drivers/net/wan/sdla_chdlc.c b/drivers/net/wan/sdla_chdlc.c
--- a/drivers/net/wan/sdla_chdlc.c	2004-10-18 14:56:31 -07:00
+++ b/drivers/net/wan/sdla_chdlc.c	2004-10-18 14:56:31 -07:00
@@ -3628,11 +3628,7 @@
 	if ((tty=card->tty)==NULL)
 		return;
 	
-	if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
-	    tty->ldisc.write_wakeup){
-		(tty->ldisc.write_wakeup)(tty);
-	}
-	wake_up_interruptible(&tty->write_wait);
+	tty_wakeup(tty);
 #if defined(SERIAL_HAVE_POLL_WAIT)
 	wake_up_interruptible(&tty->poll_wait);
 #endif	
@@ -3857,6 +3853,7 @@
 	char fp=0;
 	struct tty_struct *tty;
 	int i;
+	struct tty_ldisc *ld;
 	
 	if (!card->tty_open){
 		dbg_printk(KERN_INFO "%s: TTY not open during receive\n",
@@ -3944,8 +3941,11 @@
 			len -= offset;
 		}
 		sdla_peek(&card->hw, addr, card->tty_rx+offset, len);
-		if (tty->ldisc.receive_buf){
-			tty->ldisc.receive_buf(tty,card->tty_rx,&fp,olen);
+		ld = tty_ldisc_ref(tty);
+		if (ld) {
+			if (ld->receive_buf)
+				ld->receive_buf(tty,card->tty_rx,&fp,olen);
+			tty_ldisc_deref(ld);
 		}else{
 			if (net_ratelimit()){
 				printk(KERN_INFO 
@@ -4252,14 +4252,10 @@
 	if (!tty)
 		return;
 	
-	wake_up_interruptible(&tty->write_wait);
 #if defined(SERIAL_HAVE_POLL_WAIT)
 	wake_up_interruptible(&tty->poll_wait);
 #endif
-	if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
-	    tty->ldisc.write_wakeup)
-		(tty->ldisc.write_wakeup)(tty);
-
+	tty_wakeup(tty);
 	return;
 }
 
diff -Nru a/drivers/net/wan/sdla_fr.c b/drivers/net/wan/sdla_fr.c
--- a/drivers/net/wan/sdla_fr.c	2004-10-18 14:57:04 -07:00
+++ b/drivers/net/wan/sdla_fr.c	2004-10-18 14:57:04 -07:00
@@ -3678,7 +3678,7 @@
                                 break;
                         }
 
-			(void *)ptr_trc_el = card->u.f.curr_trc_el;
+			ptr_trc_el = (void *)card->u.f.curr_trc_el;
 
                         buffer_length = 0;
 			fr_udp_pkt->data[0x00] = 0x00;
@@ -3729,7 +3729,7 @@
                                
 				ptr_trc_el ++;
 				if((void *)ptr_trc_el > card->u.f.trc_el_last)
-					(void*)ptr_trc_el = card->u.f.trc_el_base;
+					ptr_trc_el = (void*)card->u.f.trc_el_base;
 
 				buffer_length += sizeof(fpipemon_trc_hdr_t);
                                	if(fpipemon_trc->fpipemon_trc_hdr.data_passed) {
diff -Nru a/drivers/net/wan/sdladrv.c b/drivers/net/wan/sdladrv.c
--- a/drivers/net/wan/sdladrv.c	2004-10-18 14:56:20 -07:00
+++ b/drivers/net/wan/sdladrv.c	2004-10-18 14:56:20 -07:00
@@ -937,7 +937,7 @@
                         peek_by_4 ((unsigned long)hw->dpmbase + curpos, buf,
 				curlen);
                         addr       += curlen;
-                        (char*)buf += curlen;
+                        buf         = (char*)buf + curlen;
                         len        -= curlen;
                 }
 
@@ -1019,7 +1019,7 @@
                         poke_by_4 ((unsigned long)hw->dpmbase + curpos, buf,
 				curlen);
 	                addr       += curlen;
-                        (char*)buf += curlen;
+                        buf         = (char*)buf + curlen;
                         len        -= curlen;
                 }
 
@@ -2001,7 +2001,7 @@
 	(void *)hw->dpmbase = ioremap((unsigned long)S514_mem_base_addr,
 		(unsigned long)MAX_SIZEOF_S514_MEMORY);
     	/* map the physical control register memory to virtual memory */
-	(void *)hw->vector = ioremap(
+	hw->vector = (unsigned long)ioremap(
 		(unsigned long)(S514_mem_base_addr + S514_CTRL_REG_BYTE),
 		(unsigned long)16);
      
diff -Nru a/drivers/net/wan/sdlamain.c b/drivers/net/wan/sdlamain.c
--- a/drivers/net/wan/sdlamain.c	2004-10-18 14:56:49 -07:00
+++ b/drivers/net/wan/sdlamain.c	2004-10-18 14:56:49 -07:00
@@ -976,7 +976,7 @@
 
                         dump.length     -= len;
                         dump.offset     += len;
-                        (char*)dump.ptr += len;
+                        dump.ptr         = (char*)dump.ptr + len;
                 }
 		
                 sdla_mapmem(&card->hw, oldvec);/* restore DPM window position */
diff -Nru a/drivers/net/wan/syncppp.c b/drivers/net/wan/syncppp.c
--- a/drivers/net/wan/syncppp.c	2004-10-18 14:56:27 -07:00
+++ b/drivers/net/wan/syncppp.c	2004-10-18 14:56:27 -07:00
@@ -50,6 +50,7 @@
 #include <linux/random.h>
 #include <linux/pkt_sched.h>
 #include <linux/spinlock.h>
+#include <linux/rcupdate.h>
 
 #include <net/syncppp.h>
 
@@ -767,9 +768,9 @@
 		struct in_ifaddr *ifa;
 		u32 addr = 0, mask = ~0; /* FIXME: is the mask correct? */
 #ifdef CONFIG_INET
-		if ((in_dev=in_dev_get(dev)) != NULL)
+		rcu_read_lock();
+		if ((in_dev = __in_dev_get(dev)) != NULL)
 		{
-			read_lock(&in_dev->lock);
 			for (ifa=in_dev->ifa_list; ifa != NULL;
 				ifa=ifa->ifa_next) {
 				if (strcmp(dev->name, ifa->ifa_label) == 0) 
@@ -779,9 +780,8 @@
 					break;
 				}
 			}
-			read_unlock(&in_dev->lock);
-			in_dev_put(in_dev);
 		}
+		rcu_read_unlock();
 #endif		
 		/* I hope both addr and mask are in the net order */
 		sppp_cisco_send (sp, CISCO_ADDR_REPLY, addr, mask);
diff -Nru a/drivers/net/wireless/airo.c b/drivers/net/wireless/airo.c
--- a/drivers/net/wireless/airo.c	2004-10-18 14:55:55 -07:00
+++ b/drivers/net/wireless/airo.c	2004-10-18 14:55:55 -07:00
@@ -25,6 +25,7 @@
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/proc_fs.h>
+#include <linux/smp_lock.h>
 
 #include <linux/sched.h>
 #include <linux/ptrace.h>
@@ -1815,7 +1816,8 @@
 	if (!test_bit (FLAG_COMMIT, &ai->flags))
 		return SUCCESS;
 
-	clear_bit (FLAG_COMMIT | FLAG_RESET, &ai->flags);
+	clear_bit (FLAG_COMMIT, &ai->flags);
+	clear_bit (FLAG_RESET, &ai->flags);
 	checkThrottle(ai);
 	cfgr = ai->config;
 
@@ -1979,9 +1981,6 @@
 	ai->txfids[0].tx_desc.eoc = 1;
 	ai->txfids[0].tx_desc.len =len+sizeof(WifiHdr);
 
-	memcpy((char *)ai->txfids[0].card_ram_off,
-		(char *)&ai->txfids[0].tx_desc, sizeof(TxFid));
-
 /*
  * Magic, the cards firmware needs a length count (2 bytes) in the host buffer
  * right after  TXFID_HDR.The TXFID_HDR contains the status short so payloadlen
@@ -2011,6 +2010,7 @@
 			return ERROR;
 
 		*payloadLen = cpu_to_le16(len-sizeof(etherHead)+sizeof(pMic));
+		ai->txfids[0].tx_desc.len += sizeof(pMic);
 		/* copy data into airo dma buffer */
 		memcpy (sendbuf, buffer, sizeof(etherHead));
 		buffer += sizeof(etherHead);
@@ -2029,6 +2029,9 @@
 		memcpy(sendbuf, buffer, len);
 	}
 
+	memcpy((char *)ai->txfids[0].card_ram_off,
+		(char *)&ai->txfids[0].tx_desc, sizeof(TxFid));
+
 	OUT4500(ai, EVACK, 8);
 
 	dev_kfree_skb_any(skb);
@@ -2183,6 +2186,12 @@
 	struct airo_info *priv = dev->priv;
 	u32 *fids = priv->fids;
 
+	if (test_bit(FLAG_MPI, &priv->flags)) {
+		/* Not implemented yet for MPI350 */
+		netif_stop_queue(dev);
+		return -ENETDOWN;
+	}
+
 	if ( skb == NULL ) {
 		printk( KERN_ERR "airo:  skb == NULL!!!\n" );
 		return 0;
@@ -2248,12 +2257,14 @@
 {
 	struct airo_info *local =  dev->priv;
 
-	/* Get stats out of the card if available */
-	if (down_trylock(&local->sem) != 0) {
-		set_bit(JOB_STATS, &local->flags);
-		wake_up_interruptible(&local->thr_wait);
-	} else
-		airo_read_stats(local);
+	if (!test_bit(JOB_STATS, &local->flags)) {
+		/* Get stats out of the card if available */
+		if (down_trylock(&local->sem) != 0) {
+			set_bit(JOB_STATS, &local->flags);
+			wake_up_interruptible(&local->thr_wait);
+		} else
+			airo_read_stats(local);
+	}
 
 	return &local->stats;
 }
@@ -2339,6 +2350,9 @@
 void stop_airo_card( struct net_device *dev, int freeres )
 {
 	struct airo_info *ai = dev->priv;
+
+	set_bit(FLAG_RADIO_DOWN, &ai->flags);
+	disable_MAC(ai, 1);
 	disable_interrupts(ai);
 	free_irq( dev->irq, dev );
 	takedown_proc_entry( dev, ai );
@@ -3405,13 +3419,8 @@
 }
 
 static void enable_interrupts( struct airo_info *ai ) {
-	/* Reset the status register */
-	u16 status = IN4500( ai, EVSTAT );
-	OUT4500( ai, EVACK, status );
 	/* Enable the interrupts */
 	OUT4500( ai, EVINTEN, STATUS_INTS );
-	/* Note there is a race condition between the last two lines that
-	   I don't know how to get rid of right now... */
 }
 
 static void disable_interrupts( struct airo_info *ai ) {
@@ -3459,7 +3468,7 @@
 		memcpy(buffer + ETH_ALEN * 2,
 			ai->rxfids[0].virtual_host_addr + ETH_ALEN * 2 + off,
 			len - ETH_ALEN * 2 - off);
-		if (decapsulate (ai, &micbuf, (etherHead*)buffer, len - off)) {
+		if (decapsulate (ai, &micbuf, (etherHead*)buffer, len - off - ETH_ALEN * 2)) {
 badmic:
 			dev_kfree_skb_irq (skb);
 			goto badrx;
@@ -3669,18 +3678,6 @@
 		status = readCapabilityRid(ai, &cap_rid, lock);
 		if ( status != SUCCESS ) return ERROR;
 
-		/*
-		 * This driver supports MPI350 firmwares up to, and
-		 * including 5.30.17
-		 */
-		if (test_bit(FLAG_MPI, &ai->flags) &&
-		    strncmp (cap_rid.prodVer, "5.00.", 5) &&
-		    strncmp (cap_rid.prodVer, "5b00.", 5) &&
-		    strncmp (cap_rid.prodVer, "5.02.", 5) &&
-		    strncmp (cap_rid.prodVer, "5.20.", 5) &&
-		    strncmp (cap_rid.prodVer, "5.30.", 5))
-			printk(KERN_ERR "airo: Firmware version %s is not supported. Use it at your own risk!\n", cap_rid.prodVer);
-
 		status = PC4500_readrid(ai,RID_RSSI,&rssi_rid,sizeof(rssi_rid),lock);
 		if ( status == SUCCESS ) {
 			if (ai->rssi || (ai->rssi = kmalloc(512, GFP_KERNEL)) != NULL)
@@ -3715,9 +3712,9 @@
 
 		/* Check to see if there are any insmod configured
 		   rates to add */
-		if ( rates ) {
+		if ( rates[0] ) {
 			int i = 0;
-			if ( rates[0] ) memset(ai->config.rates,0,sizeof(ai->config.rates));
+			memset(ai->config.rates,0,sizeof(ai->config.rates));
 			for( i = 0; i < 8 && rates[i]; i++ ) {
 				ai->config.rates[i] = rates[i];
 			}
@@ -3784,7 +3781,6 @@
 static u16 issuecommand(struct airo_info *ai, Cmd *pCmd, Resp *pRsp) {
         // Im really paranoid about letting it run forever!
 	int max_tries = 600000;
-	u16 cmd;
 
 	if (IN4500(ai, EVSTAT) & EV_CMD)
 		OUT4500(ai, EVACK, EV_CMD);
@@ -3793,26 +3789,23 @@
 	OUT4500(ai, PARAM1, pCmd->parm1);
 	OUT4500(ai, PARAM2, pCmd->parm2);
 	OUT4500(ai, COMMAND, pCmd->cmd);
-	while ( max_tries-- && (IN4500(ai, EVSTAT) & EV_CMD) == 0 &&
-		(cmd = IN4500(ai, COMMAND)) != 0 )
-			if (cmd == pCmd->cmd)
-				// PC4500 didn't notice command, try again
-				OUT4500(ai, COMMAND, pCmd->cmd);
-	if ( max_tries == -1 ) {
-		printk( KERN_ERR
-			"airo: Max tries exceeded when issueing command\n" );
-                return ERROR;
-	}
 
 	while (max_tries-- && (IN4500(ai, EVSTAT) & EV_CMD) == 0) {
+		if ((IN4500(ai, COMMAND)) == pCmd->cmd)
+			// PC4500 didn't notice command, try again
+			OUT4500(ai, COMMAND, pCmd->cmd);
 		if (!in_atomic() && (max_tries & 255) == 0)
 			schedule();
 	}
+
 	if ( max_tries == -1 ) {
 		printk( KERN_ERR
-			"airo: Max tries exceeded waiting for command\n" );
-                return ERROR;
+			"airo: Max tries exceeded when issueing command\n" );
+		if (IN4500(ai, COMMAND) & COMMAND_BUSY)
+			OUT4500(ai, EVACK, EV_CLEARCOMMANDBUSY);
+		return ERROR;
 	}
+
 	// command completed
 	pRsp->status = IN4500(ai, STATUS);
 	pRsp->rsp0 = IN4500(ai, RESP0);
@@ -4508,8 +4501,6 @@
 		len = priv->readlen - pos;
 	if (copy_to_user(buffer, priv->rbuffer + pos, len))
 		return -EFAULT;
-	if (pos + len > priv->writelen)
-		priv->writelen = pos + len;
 	*offset = pos + len;
 	return len;
 }
@@ -5520,7 +5511,6 @@
 		mpi_init_descriptors(ai);
 		setup_card(ai, dev->dev_addr, 0);
 		clear_bit(FLAG_RADIO_OFF, &ai->flags);
-		clear_bit(FLAG_RADIO_DOWN, &ai->flags);
 		clear_bit(FLAG_PENDING_XMIT, &ai->flags);
 	} else {
 		OUT4500(ai, EVACK, EV_AWAKEN);
@@ -5605,6 +5595,30 @@
  * would not work at all... - Jean II
  */
 
+static int airo_get_quality (StatusRid *status_rid, CapabilityRid *cap_rid)
+{
+	int quality = 0;
+
+	if ((status_rid->mode & 0x3f) == 0x3f && (cap_rid->hardCap & 8)) {
+		if (memcmp(cap_rid->prodName, "350", 3))
+			if (status_rid->signalQuality > 0x20)
+				quality = 0;
+			else
+				quality = 0x20 - status_rid->signalQuality;
+		else
+			if (status_rid->signalQuality > 0xb0)
+				quality = 0;
+			else if (status_rid->signalQuality < 0x10)
+				quality = 0xa0;
+			else
+				quality = 0xb0 - status_rid->signalQuality;
+	}
+	return quality;
+}
+
+#define airo_get_max_quality(cap_rid) (memcmp((cap_rid)->prodName, "350", 3) ? 0x20 : 0xa0)
+#define airo_get_avg_quality(cap_rid) (memcmp((cap_rid)->prodName, "350", 3) ? 0x10 : 0x50);
+
 /*------------------------------------------------------------------*/
 /*
  * Wireless Handler : get protocol name
@@ -6292,7 +6306,8 @@
 	readCapabilityRid(local, &cap_rid, 1);
 
 	if (vwrq->disabled) {
-		set_bit (FLAG_RADIO_OFF | FLAG_COMMIT, &local->flags);
+		set_bit (FLAG_RADIO_OFF, &local->flags);
+		set_bit (FLAG_COMMIT, &local->flags);
 		return -EINPROGRESS;		/* Call commit handler */
 	}
 	if (vwrq->flags != IW_TXPOW_MWATT) {
@@ -6431,7 +6446,7 @@
 	range->num_frequency = k;
 
 	/* Hum... Should put the right values there */
-	range->max_qual.qual = 10;
+	range->max_qual.qual = airo_get_max_quality(&cap_rid);
 	range->max_qual.level = 0x100 - 120;	/* -120 dBm */
 	range->max_qual.noise = 0;
 	range->sensitivity = 65535;
@@ -6498,7 +6513,7 @@
 	/* Experimental measurements - boundary 11/5.5 Mb/s */
 	/* Note : with or without the (local->rssi), results
 	 * are somewhat different. - Jean II */
-	range->avg_qual.qual = 6;
+	range->avg_qual.qual = airo_get_avg_quality(&cap_rid);
 	if (local->rssi)
 		range->avg_qual.level = 186;	/* -70 dBm */
 	else
@@ -7112,6 +7127,7 @@
 {
 	StatusRid status_rid;
 	StatsRid stats_rid;
+	CapabilityRid cap_rid;
 	u32 *vals = stats_rid.vals;
 
 	/* Get stats out of the card */
@@ -7120,6 +7136,7 @@
 		up(&local->sem);
 		return;
 	}
+	readCapabilityRid(local, &cap_rid, 0);
 	readStatusRid(local, &status_rid, 0);
 	readStatsRid(local, &stats_rid, RID_STATS, 0);
 	up(&local->sem);
@@ -7128,7 +7145,7 @@
 	local->wstats.status = status_rid.mode;
 
 	/* Signal quality and co. But where is the noise level ??? */
-	local->wstats.qual.qual = status_rid.signalQuality;
+	local->wstats.qual.qual = airo_get_quality(&status_rid, &cap_rid);
 	if (local->rssi)
 		local->wstats.qual.level = 0x100 - local->rssi[status_rid.sigQuality].rssidBm;
 	else
@@ -7155,12 +7172,14 @@
 {
 	struct airo_info *local =  dev->priv;
 
-	/* Get stats out of the card if available */
-	if (down_trylock(&local->sem) != 0) {
-		set_bit(JOB_WSTATS, &local->flags);
-		wake_up_interruptible(&local->thr_wait);
-	} else
-		airo_read_wireless_stats(local);
+	if (!test_bit(JOB_WSTATS, &local->flags)) {
+		/* Get stats out of the card if available */
+		if (down_trylock(&local->sem) != 0) {
+			set_bit(JOB_WSTATS, &local->flags);
+			wake_up_interruptible(&local->thr_wait);
+		} else
+			airo_read_wireless_stats(local);
+	}
 
 	return &local->wstats;
 }
@@ -7187,9 +7206,11 @@
 	{
 	case AIROGCAP:      ridcode = RID_CAPABILITIES; break;
 	case AIROGCFG:      ridcode = RID_CONFIG;
-		disable_MAC (ai, 1);
-		writeConfigRid (ai, 1);
-		enable_MAC (ai, &rsp, 1);
+		if (test_bit(FLAG_COMMIT, &ai->flags)) {
+			disable_MAC (ai, 1);
+			writeConfigRid (ai, 1);
+			enable_MAC (ai, &rsp, 1);
+		}
 		break;
 	case AIROGSLIST:    ridcode = RID_SSID;         break;
 	case AIROGVLIST:    ridcode = RID_APLIST;       break;
@@ -7269,6 +7290,7 @@
 	case AIROPCAP:      ridcode = RID_CAPABILITIES; break;
 	case AIROPAPLIST:   ridcode = RID_APLIST;       break;
 	case AIROPCFG: ai->config.len = 0;
+			    clear_bit(FLAG_COMMIT, &ai->flags);
 			    ridcode = RID_CONFIG;       break;
 	case AIROPWEPKEYNV: ridcode = RID_WEP_PERM;     break;
 	case AIROPLEAPUSR:  ridcode = RID_LEAPUSERNAME; break;
diff -Nru a/drivers/net/wireless/airport.c b/drivers/net/wireless/airport.c
--- a/drivers/net/wireless/airport.c	2004-10-18 14:57:04 -07:00
+++ b/drivers/net/wireless/airport.c	2004-10-18 14:57:04 -07:00
@@ -1,4 +1,4 @@
-/* airport.c 0.13e
+/* airport.c
  *
  * A driver for "Hermes" chipset based Apple Airport wireless
  * card.
@@ -11,6 +11,9 @@
  *  0.06 : fix possible hang on powerup, add sleep support
  */
 
+#define DRIVER_NAME "airport"
+#define PFX DRIVER_NAME ": "
+
 #include <linux/config.h>
 
 #include <linux/module.h>
@@ -25,6 +28,7 @@
 #include <linux/if_arp.h>
 #include <linux/etherdevice.h>
 #include <linux/wireless.h>
+#include <linux/delay.h>
 
 #include <asm/io.h>
 #include <asm/system.h>
@@ -50,7 +54,7 @@
 airport_suspend(struct macio_dev *mdev, u32 state)
 {
 	struct net_device *dev = dev_get_drvdata(&mdev->ofdev.dev);
-	struct orinoco_private *priv = dev->priv;
+	struct orinoco_private *priv = netdev_priv(dev);
 	unsigned long flags;
 	int err;
 
@@ -84,15 +88,14 @@
 airport_resume(struct macio_dev *mdev)
 {
 	struct net_device *dev = dev_get_drvdata(&mdev->ofdev.dev);
-	struct orinoco_private *priv = dev->priv;
+	struct orinoco_private *priv = netdev_priv(dev);
 	unsigned long flags;
 	int err;
 
 	printk(KERN_DEBUG "%s: Airport waking up\n", dev->name);
 
 	pmac_call_feature(PMAC_FTR_AIRPORT_ENABLE, macio_get_of_node(mdev), 0, 1);
-	set_current_state(TASK_UNINTERRUPTIBLE);
-	schedule_timeout(HZ/5);
+	msleep(200);
 
 	enable_irq(dev->irq);
 
@@ -126,7 +129,7 @@
 airport_detach(struct macio_dev *mdev)
 {
 	struct net_device *dev = dev_get_drvdata(&mdev->ofdev.dev);
-	struct orinoco_private *priv = dev->priv;
+	struct orinoco_private *priv = netdev_priv(dev);
 	struct airport *card = priv->card;
 
 	if (card->ndev_registered)
@@ -144,8 +147,7 @@
 	macio_release_resource(mdev, 0);
 
 	pmac_call_feature(PMAC_FTR_AIRPORT_ENABLE, macio_get_of_node(mdev), 0, 0);
-	set_current_state(TASK_UNINTERRUPTIBLE);
-	schedule_timeout(HZ);
+	ssleep(1);
 
 	macio_set_drvdata(mdev, NULL);
 	free_netdev(dev);
@@ -171,14 +173,12 @@
 	disable_irq(dev->irq);
 
 	pmac_call_feature(PMAC_FTR_AIRPORT_ENABLE, macio_get_of_node(card->mdev), 0, 0);
-	set_current_state(TASK_UNINTERRUPTIBLE);
-	schedule_timeout(HZ);
+	ssleep(1);
 	pmac_call_feature(PMAC_FTR_AIRPORT_ENABLE, macio_get_of_node(card->mdev), 0, 1);
-	set_current_state(TASK_UNINTERRUPTIBLE);
-	schedule_timeout(HZ);
+	ssleep(1);
 
 	enable_irq(dev->irq);
-	schedule_timeout(HZ);
+	ssleep(1);
 #endif
 
 	return 0;
@@ -194,24 +194,24 @@
 	hermes_t *hw;
 
 	if (macio_resource_count(mdev) < 1 || macio_irq_count(mdev) < 1) {
-		printk(KERN_ERR "airport: wrong interrupt/addresses in OF tree\n");
+		printk(KERN_ERR PFX "wrong interrupt/addresses in OF tree\n");
 		return -ENODEV;
 	}
 
 	/* Allocate space for private device-specific data */
 	dev = alloc_orinocodev(sizeof(*card), airport_hard_reset);
 	if (! dev) {
-		printk(KERN_ERR "airport: can't allocate device datas\n");
+		printk(KERN_ERR PFX "can't allocate device datas\n");
 		return -ENODEV;
 	}
-	priv = dev->priv;
+	priv = netdev_priv(dev);
 	card = priv->card;
 
 	hw = &priv->hw;
 	card->mdev = mdev;
 
 	if (macio_request_resource(mdev, 0, "airport")) {
-		printk(KERN_ERR "airport: can't request IO resource !\n");
+		printk(KERN_ERR PFX "can't request IO resource !\n");
 		free_netdev(dev);
 		return -EBUSY;
 	}
@@ -224,11 +224,11 @@
 	/* Setup interrupts & base address */
 	dev->irq = macio_irq(mdev, 0);
 	phys_addr = macio_resource_start(mdev, 0);  /* Physical address */
-	printk(KERN_DEBUG "Airport at physical address %lx\n", phys_addr);
+	printk(KERN_DEBUG PFX "Airport at physical address %lx\n", phys_addr);
 	dev->base_addr = phys_addr;
 	card->vaddr = ioremap(phys_addr, AIRPORT_IO_LEN);
 	if (!card->vaddr) {
-		printk("airport: ioremap() failed\n");
+		printk(PFX "ioremap() failed\n");
 		goto failed;
 	}
 
@@ -237,24 +237,23 @@
 		
 	/* Power up card */
 	pmac_call_feature(PMAC_FTR_AIRPORT_ENABLE, macio_get_of_node(mdev), 0, 1);
-	set_current_state(TASK_UNINTERRUPTIBLE);
-	schedule_timeout(HZ);
+	ssleep(1);
 
 	/* Reset it before we get the interrupt */
 	hermes_init(hw);
 
 	if (request_irq(dev->irq, orinoco_interrupt, 0, "Airport", dev)) {
-		printk(KERN_ERR "airport: Couldn't get IRQ %d\n", dev->irq);
+		printk(KERN_ERR PFX "Couldn't get IRQ %d\n", dev->irq);
 		goto failed;
 	}
 	card->irq_requested = 1;
 
 	/* Tell the stack we exist */
 	if (register_netdev(dev) != 0) {
-		printk(KERN_ERR "airport: register_netdev() failed\n");
+		printk(KERN_ERR PFX "register_netdev() failed\n");
 		goto failed;
 	}
-	printk(KERN_DEBUG "airport: card registered for interface %s\n", dev->name);
+	printk(KERN_DEBUG PFX "card registered for interface %s\n", dev->name);
 	card->ndev_registered = 1;
 	return 0;
  failed:
@@ -263,7 +262,8 @@
 }				/* airport_attach */
 
 
-static char version[] __initdata = "airport.c 0.13e (Benjamin Herrenschmidt <benh@kernel.crashing.org>)";
+static char version[] __initdata = DRIVER_NAME " " DRIVER_VERSION
+	" (Benjamin Herrenschmidt <benh@kernel.crashing.org>)";
 MODULE_AUTHOR("Benjamin Herrenschmidt <benh@kernel.crashing.org>");
 MODULE_DESCRIPTION("Driver for the Apple Airport wireless card.");
 MODULE_LICENSE("Dual MPL/GPL");
@@ -280,7 +280,7 @@
 
 static struct macio_driver airport_driver = 
 {
-	.name 		= "airport",
+	.name 		= DRIVER_NAME,
 	.match_table	= airport_match,
 	.probe		= airport_attach,
 	.remove		= airport_detach,
diff -Nru a/drivers/net/wireless/atmel.c b/drivers/net/wireless/atmel.c
--- a/drivers/net/wireless/atmel.c	2004-10-18 14:56:27 -07:00
+++ b/drivers/net/wireless/atmel.c	2004-10-18 14:56:27 -07:00
@@ -2430,12 +2430,13 @@
 			rc = -ENOMEM;
 			break;
 		}
-		
+
 		if (copy_from_user(new_firmware, com.data, com.len)) {
+			kfree(new_firmware);
 			rc = -EFAULT;
 			break;
 		}
-		
+
 		if (priv->firmware)
 			kfree(priv->firmware);
 		
diff -Nru a/drivers/net/wireless/hermes.c b/drivers/net/wireless/hermes.c
--- a/drivers/net/wireless/hermes.c	2004-10-18 14:56:17 -07:00
+++ b/drivers/net/wireless/hermes.c	2004-10-18 14:56:17 -07:00
@@ -13,8 +13,8 @@
  * (wvlan_hcf.c) library, and the NetBSD wireless driver (in no
  * particular order).
  *
- * Copyright (C) 2000, David Gibson, Linuxcare Australia <hermes@gibson.dropbear.id.au>
- * Copyright (C) 2001, David Gibson, IBM <hermes@gibson.dropbear.id.au>
+ * Copyright (C) 2000, David Gibson, Linuxcare Australia.
+ * (C) Copyright David Gibson, IBM Corp. 2001-2003.
  * 
  * The contents of this file are subject to the Mozilla Public License
  * Version 1.1 (the "License"); you may not use this file except in
@@ -53,10 +53,9 @@
 #include "hermes.h"
 
 MODULE_DESCRIPTION("Low-level driver helper for Lucent Hermes chipset and Prism II HFA384x wireless MAC controller");
-MODULE_AUTHOR("David Gibson <hermes@gibson.dropbear.id.au>");
-#ifdef MODULE_LICENSE
+MODULE_AUTHOR("Pavel Roskin <proski@gnu.org>"
+	" & David Gibson <hermes@gibson.dropbear.id.au>");
 MODULE_LICENSE("Dual MPL/GPL");
-#endif
 
 /* These are maximum timeouts. Most often, card wil react much faster */
 #define CMD_BUSY_TIMEOUT (100) /* In iterations of ~1us */
@@ -226,7 +225,7 @@
  *
  * Callable from any context, but locking is your problem. */
 int hermes_docmd_wait(hermes_t *hw, u16 cmd, u16 parm0,
-		      hermes_response_t *resp)
+		      struct hermes_response *resp)
 {
 	int err;
 	int k;
@@ -391,7 +390,6 @@
 	if (reg & HERMES_OFFSET_ERR) {
 		return -EIO;
 	}
-
 
 	return 0;
 }
diff -Nru a/drivers/net/wireless/hermes.h b/drivers/net/wireless/hermes.h
--- a/drivers/net/wireless/hermes.h	2004-10-18 14:55:54 -07:00
+++ b/drivers/net/wireless/hermes.h	2004-10-18 14:55:54 -07:00
@@ -12,7 +12,8 @@
  * project, the Linux wvlan_cs driver, Lucent's HCF-Light
  * (wvlan_hcf.c) library, and the NetBSD wireless driver.
  *
- * Copyright (C) 2000, David Gibson, Linuxcare Australia <hermes@gibson.dropbear.id.au>
+ * Copyright (C) 2000, David Gibson, Linuxcare Australia.
+ * (C) Copyright David Gibson, IBM Corp. 2001-2003.
  *
  * Portions taken from hfa384x.h, Copyright (C) 1999 AbsoluteValue Systems, Inc. All Rights Reserved.
  *
@@ -124,29 +125,52 @@
 /*
  * Command codes
  */
-/*--- Controller Commands --------------------------*/
+/*--- Controller Commands ----------------------------*/
 #define		HERMES_CMD_INIT			(0x0000)
 #define		HERMES_CMD_ENABLE		(0x0001)
 #define		HERMES_CMD_DISABLE		(0x0002)
 #define		HERMES_CMD_DIAG			(0x0003)
 
-/*--- Buffer Mgmt Commands --------------------------*/
+/*--- Buffer Mgmt Commands ---------------------------*/
 #define		HERMES_CMD_ALLOC		(0x000A)
 #define		HERMES_CMD_TX			(0x000B)
-#define		HERMES_CMD_CLRPRST		(0x0012)
 
-/*--- Regulate Commands --------------------------*/
+/*--- Regulate Commands ------------------------------*/
 #define		HERMES_CMD_NOTIFY		(0x0010)
 #define		HERMES_CMD_INQUIRE		(0x0011)
 
-/*--- Configure Commands --------------------------*/
+/*--- Configure Commands -----------------------------*/
 #define		HERMES_CMD_ACCESS		(0x0021)
 #define		HERMES_CMD_DOWNLD		(0x0022)
 
+/*--- Serial I/O Commands ----------------------------*/
+#define		HERMES_CMD_READMIF		(0x0030)
+#define		HERMES_CMD_WRITEMIF		(0x0031)
+
 /*--- Debugging Commands -----------------------------*/
-#define 	HERMES_CMD_MONITOR		(0x0038)
-#define		HERMES_MONITOR_ENABLE		(0x000b)
-#define		HERMES_MONITOR_DISABLE		(0x000f)
+#define 	HERMES_CMD_TEST			(0x0038)
+
+
+/* Test command arguments */
+#define		HERMES_TEST_SET_CHANNEL		0x0800
+#define		HERMES_TEST_MONITOR		0x0b00
+#define		HERMES_TEST_STOP		0x0f00
+
+/* Authentication algorithms */
+#define		HERMES_AUTH_OPEN		1
+#define		HERMES_AUTH_SHARED_KEY		2
+
+/* WEP settings */
+#define		HERMES_WEP_PRIVACY_INVOKED	0x0001
+#define		HERMES_WEP_EXCL_UNENCRYPTED	0x0002
+#define		HERMES_WEP_HOST_ENCRYPT		0x0010
+#define		HERMES_WEP_HOST_DECRYPT		0x0080
+
+/* Symbol hostscan options */
+#define		HERMES_HOSTSCAN_SYMBOL_5SEC	0x0001
+#define		HERMES_HOSTSCAN_SYMBOL_ONCE	0x0002
+#define		HERMES_HOSTSCAN_SYMBOL_PASSIVE	0x0040
+#define		HERMES_HOSTSCAN_SYMBOL_BCAST	0x0080
 
 /*
  * Frame structures and constants
@@ -157,16 +181,6 @@
 #define HERMES_802_3_OFFSET		(14+32)
 #define HERMES_802_2_OFFSET		(14+32+14)
 
-struct hermes_rx_descriptor {
-	u16 status;
-	u32 time;
-	u8 silence;
-	u8 signal;
-	u8 rate;
-	u8 rxflow;
-	u32 reserved;
-} __attribute__ ((packed));
-
 #define HERMES_RXSTAT_ERR		(0x0003)
 #define	HERMES_RXSTAT_BADCRC		(0x0001)
 #define	HERMES_RXSTAT_UNDECRYPTABLE	(0x0002)
@@ -201,7 +215,11 @@
 
 #define HERMES_INQ_TALLIES		(0xF100)
 #define HERMES_INQ_SCAN			(0xF101)
+#define HERMES_INQ_CHANNELINFO		(0xF102)
+#define HERMES_INQ_HOSTSCAN		(0xF103)
+#define HERMES_INQ_HOSTSCAN_SYMBOL	(0xF104)
 #define HERMES_INQ_LINKSTATUS		(0xF200)
+#define HERMES_INQ_SEC_STAT_AGERE	(0xF202)
 
 struct hermes_tallies_frame {
 	u16 TxUnicastFrames;
@@ -233,23 +251,58 @@
 /* Grabbed from wlan-ng - Thanks Mark... - Jean II
  * This is the result of a scan inquiry command */
 /* Structure describing info about an Access Point */
-struct hermes_scan_apinfo {
+struct prism2_scan_apinfo {
 	u16 channel;		/* Channel where the AP sits */
 	u16 noise;		/* Noise level */
 	u16 level;		/* Signal level */
 	u8 bssid[ETH_ALEN];	/* MAC address of the Access Point */
-	u16 beacon_interv;	/* Beacon interval ? */
-	u16 capabilities;	/* Capabilities ? */
+	u16 beacon_interv;	/* Beacon interval */
+	u16 capabilities;	/* Capabilities */
+	u16 essid_len;		/* ESSID length */
 	u8 essid[32];		/* ESSID of the network */
 	u8 rates[10];		/* Bit rate supported */
-	u16 proberesp_rate;	/* ???? */
+	u16 proberesp_rate;	/* Data rate of the response frame */
+	u16 atim;		/* ATIM window time, Kus (hostscan only) */
 } __attribute__ ((packed));
-/* Container */
-struct hermes_scan_frame {
-	u16 rsvd;                   /* ??? */
-	u16 scanreason;             /* ??? */
-	struct hermes_scan_apinfo aps[35];        /* Scan result */
+
+/* Same stuff for the Lucent/Agere card.
+ * Thanks to h1kari <h1kari AT dachb0den.com> - Jean II */
+struct agere_scan_apinfo {
+	u16 channel;		/* Channel where the AP sits */
+	u16 noise;		/* Noise level */
+	u16 level;		/* Signal level */
+	u8 bssid[ETH_ALEN];	/* MAC address of the Access Point */
+	u16 beacon_interv;	/* Beacon interval */
+	u16 capabilities;	/* Capabilities */
+	/* bits: 0-ess, 1-ibss, 4-privacy [wep] */
+	u16 essid_len;		/* ESSID length */
+	u8 essid[32];		/* ESSID of the network */
+} __attribute__ ((packed));
+
+/* Moustafa: Scan structure for Symbol cards */
+struct symbol_scan_apinfo {
+	u8 channel;		/* Channel where the AP sits */
+	u8 unknown1;		/* 8 in 2.9x and 3.9x f/w, 0 otherwise */
+	u16 noise;		/* Noise level */
+	u16 level;		/* Signal level */
+	u8 bssid[ETH_ALEN];	/* MAC address of the Access Point */
+	u16 beacon_interv;	/* Beacon interval */
+	u16 capabilities;	/* Capabilities */
+	/* bits: 0-ess, 1-ibss, 4-privacy [wep] */
+	u16 essid_len;		/* ESSID length */
+	u8 essid[32];		/* ESSID of the network */
+    	u16 rates[5];		/* Bit rate supported */
+	u16 basic_rates;	/* Basic rates bitmask */
+	u8 unknown2[6];		/* Always FF:FF:FF:FF:00:00 */
+	u8 unknown3[8];		/* Always 0, appeared in f/w 3.91-68 */
 } __attribute__ ((packed));
+
+union hermes_scan_info {
+	struct agere_scan_apinfo	a;
+	struct prism2_scan_apinfo	p;
+	struct symbol_scan_apinfo	s;
+};
+
 #define HERMES_LINKSTATUS_NOT_CONNECTED   (0x0000)  
 #define HERMES_LINKSTATUS_CONNECTED       (0x0001)
 #define HERMES_LINKSTATUS_DISCONNECTED    (0x0002)
@@ -262,6 +315,20 @@
 	u16 linkstatus;         /* Link status */
 } __attribute__ ((packed));
 
+struct hermes_response {
+	u16 status, resp0, resp1, resp2;
+};
+
+/* "ID" structure - used for ESSID and station nickname */
+struct hermes_idstring {
+	u16 len;
+	u16 val[16];
+} __attribute__ ((packed));
+
+struct hermes_multicast {
+	u8 addr[HERMES_MAX_MULTICAST][ETH_ALEN];
+} __attribute__ ((packed));
+
 // #define HERMES_DEBUG_BUFFER 1
 #define HERMES_DEBUG_BUFSIZE 4096
 struct hermes_debug_entry {
@@ -294,10 +361,6 @@
 #endif
 } hermes_t;
 
-typedef struct hermes_response {
-	u16 status, resp0, resp1, resp2;
-} hermes_response_t;
-
 /* Register access convenience macros */
 #define hermes_read_reg(hw, off) ((hw)->io_space ? \
 	inw((hw)->iobase + ( (off) << (hw)->reg_spacing )) : \
@@ -312,9 +375,11 @@
 #define hermes_write_regn(hw, name, val) hermes_write_reg((hw), HERMES_##name, (val))
 
 /* Function prototypes */
-void hermes_struct_init(hermes_t *hw, ulong address, int io_space, int reg_spacing);
+void hermes_struct_init(hermes_t *hw, ulong address, int io_space,
+			int reg_spacing);
 int hermes_init(hermes_t *hw);
-int hermes_docmd_wait(hermes_t *hw, u16 cmd, u16 parm0, hermes_response_t *resp);
+int hermes_docmd_wait(hermes_t *hw, u16 cmd, u16 parm0,
+		      struct hermes_response *resp);
 int hermes_allocate(hermes_t *hw, u16 size, u16 *fid);
 
 int hermes_bap_pread(hermes_t *hw, int bap, void *buf, unsigned len,
diff -Nru a/drivers/net/wireless/hermes_rid.h b/drivers/net/wireless/hermes_rid.h
--- a/drivers/net/wireless/hermes_rid.h	2004-10-18 14:56:29 -07:00
+++ b/drivers/net/wireless/hermes_rid.h	2004-10-18 14:56:29 -07:00
@@ -4,21 +4,21 @@
 /*
  * Configuration RIDs
  */
-#define HERMES_RID_CNFPORTTYPE			0xFC00	/* used */
-#define HERMES_RID_CNFOWNMACADDR		0xFC01	/* used */
-#define HERMES_RID_CNFDESIREDSSID		0xFC02	/* used */
-#define HERMES_RID_CNFOWNCHANNEL		0xFC03	/* used */
-#define HERMES_RID_CNFOWNSSID			0xFC04	/* used */
+#define HERMES_RID_CNFPORTTYPE			0xFC00
+#define HERMES_RID_CNFOWNMACADDR		0xFC01
+#define HERMES_RID_CNFDESIREDSSID		0xFC02
+#define HERMES_RID_CNFOWNCHANNEL		0xFC03
+#define HERMES_RID_CNFOWNSSID			0xFC04
 #define HERMES_RID_CNFOWNATIMWINDOW		0xFC05
-#define HERMES_RID_CNFSYSTEMSCALE		0xFC06	/* used */
+#define HERMES_RID_CNFSYSTEMSCALE		0xFC06
 #define HERMES_RID_CNFMAXDATALEN		0xFC07
 #define HERMES_RID_CNFWDSADDRESS		0xFC08
-#define HERMES_RID_CNFPMENABLED			0xFC09	/* used */
+#define HERMES_RID_CNFPMENABLED			0xFC09
 #define HERMES_RID_CNFPMEPS			0xFC0A
-#define HERMES_RID_CNFMULTICASTRECEIVE		0xFC0B	/* used */
-#define HERMES_RID_CNFMAXSLEEPDURATION		0xFC0C	/* used */
-#define HERMES_RID_CNFPMHOLDOVERDURATION	0xFC0D	/* used */
-#define HERMES_RID_CNFOWNNAME			0xFC0E	/* used */
+#define HERMES_RID_CNFMULTICASTRECEIVE		0xFC0B
+#define HERMES_RID_CNFMAXSLEEPDURATION		0xFC0C
+#define HERMES_RID_CNFPMHOLDOVERDURATION	0xFC0D
+#define HERMES_RID_CNFOWNNAME			0xFC0E
 #define HERMES_RID_CNFOWNDTIMPERIOD		0xFC10
 #define HERMES_RID_CNFWDSADDRESS1		0xFC11
 #define HERMES_RID_CNFWDSADDRESS2		0xFC12
@@ -27,17 +27,18 @@
 #define HERMES_RID_CNFWDSADDRESS5		0xFC15
 #define HERMES_RID_CNFWDSADDRESS6		0xFC16
 #define HERMES_RID_CNFMULTICASTPMBUFFERING	0xFC17
-#define HERMES_RID_CNFWEPENABLED_AGERE		0xFC20	/* used */
+#define HERMES_RID_CNFWEPENABLED_AGERE		0xFC20
+#define HERMES_RID_CNFAUTHENTICATION_AGERE	0xFC21
 #define HERMES_RID_CNFMANDATORYBSSID_SYMBOL	0xFC21
-#define HERMES_RID_CNFWEPDEFAULTKEYID		0xFC23	/* used */
-#define HERMES_RID_CNFDEFAULTKEY0		0xFC24	/* used */
-#define HERMES_RID_CNFDEFAULTKEY1		0xFC25	/* used */
-#define HERMES_RID_CNFMWOROBUST_AGERE		0xFC25	/* used */
-#define HERMES_RID_CNFDEFAULTKEY2		0xFC26	/* used */
-#define HERMES_RID_CNFDEFAULTKEY3		0xFC27	/* used */
-#define HERMES_RID_CNFWEPFLAGS_INTERSIL		0xFC28	/* used */
+#define HERMES_RID_CNFWEPDEFAULTKEYID		0xFC23
+#define HERMES_RID_CNFDEFAULTKEY0		0xFC24
+#define HERMES_RID_CNFDEFAULTKEY1		0xFC25
+#define HERMES_RID_CNFMWOROBUST_AGERE		0xFC25
+#define HERMES_RID_CNFDEFAULTKEY2		0xFC26
+#define HERMES_RID_CNFDEFAULTKEY3		0xFC27
+#define HERMES_RID_CNFWEPFLAGS_INTERSIL		0xFC28
 #define HERMES_RID_CNFWEPKEYMAPPINGTABLE	0xFC29
-#define HERMES_RID_CNFAUTHENTICATION		0xFC2A	/* used */
+#define HERMES_RID_CNFAUTHENTICATION		0xFC2A
 #define HERMES_RID_CNFMAXASSOCSTA		0xFC2B
 #define	HERMES_RID_CNFKEYLENGTH_SYMBOL		0xFC2B
 #define HERMES_RID_CNFTXCONTROL			0xFC2C
@@ -53,14 +54,14 @@
 #define HERMES_RID_CNFTIMCTRL			0xFC40
 #define HERMES_RID_CNFTHIRTY2TALLY		0xFC42
 #define HERMES_RID_CNFENHSECURITY		0xFC43
-#define HERMES_RID_CNFGROUPADDRESSES		0xFC80	/* used */
-#define HERMES_RID_CNFCREATEIBSS		0xFC81	/* used */
-#define HERMES_RID_CNFFRAGMENTATIONTHRESHOLD	0xFC82	/* used */
-#define HERMES_RID_CNFRTSTHRESHOLD		0xFC83	/* used */
-#define HERMES_RID_CNFTXRATECONTROL		0xFC84	/* used */
-#define HERMES_RID_CNFPROMISCUOUSMODE		0xFC85	/* used */
+#define HERMES_RID_CNFGROUPADDRESSES		0xFC80
+#define HERMES_RID_CNFCREATEIBSS		0xFC81
+#define HERMES_RID_CNFFRAGMENTATIONTHRESHOLD	0xFC82
+#define HERMES_RID_CNFRTSTHRESHOLD		0xFC83
+#define HERMES_RID_CNFTXRATECONTROL		0xFC84
+#define HERMES_RID_CNFPROMISCUOUSMODE		0xFC85
 #define HERMES_RID_CNFBASICRATES_SYMBOL		0xFC8A
-#define HERMES_RID_CNFPREAMBLE_SYMBOL		0xFC8C	/* used */
+#define HERMES_RID_CNFPREAMBLE_SYMBOL		0xFC8C
 #define HERMES_RID_CNFFRAGMENTATIONTHRESHOLD0	0xFC90
 #define HERMES_RID_CNFFRAGMENTATIONTHRESHOLD1	0xFC91
 #define HERMES_RID_CNFFRAGMENTATIONTHRESHOLD2	0xFC92
@@ -75,18 +76,21 @@
 #define HERMES_RID_CNFRTSTHRESHOLD4		0xFC9B
 #define HERMES_RID_CNFRTSTHRESHOLD5		0xFC9C
 #define HERMES_RID_CNFRTSTHRESHOLD6		0xFC9D
+#define HERMES_RID_CNFHOSTSCAN_SYMBOL		0xFCAB
 #define HERMES_RID_CNFSHORTPREAMBLE		0xFCB0
-#define HERMES_RID_CNFWEPKEYS_AGERE		0xFCB0	/* used */
+#define HERMES_RID_CNFWEPKEYS_AGERE		0xFCB0
 #define HERMES_RID_CNFEXCLUDELONGPREAMBLE	0xFCB1
-#define HERMES_RID_CNFTXKEY_AGERE		0xFCB1	/* used */
+#define HERMES_RID_CNFTXKEY_AGERE		0xFCB1
 #define HERMES_RID_CNFAUTHENTICATIONRSPTO	0xFCB2
+#define HERMES_RID_CNFSCANSSID_AGERE		0xFCB2
 #define HERMES_RID_CNFBASICRATES		0xFCB3
 #define HERMES_RID_CNFSUPPORTEDRATES		0xFCB4
-#define HERMES_RID_CNFTICKTIME			0xFCE0	/* used */
+#define HERMES_RID_CNFTICKTIME			0xFCE0
 #define HERMES_RID_CNFSCANREQUEST		0xFCE1
 #define HERMES_RID_CNFJOINREQUEST		0xFCE2
 #define HERMES_RID_CNFAUTHENTICATESTATION	0xFCE3
 #define HERMES_RID_CNFCHANNELINFOREQUEST	0xFCE4
+#define HERMES_RID_CNFHOSTSCAN			0xFCE5
 
 /*
  * Information RIDs
@@ -100,30 +104,31 @@
 #define HERMES_RID_NICID			0xFD0B
 #define HERMES_RID_MFISUPRANGE			0xFD0C
 #define HERMES_RID_CFISUPRANGE			0xFD0D
-#define HERMES_RID_CHANNELLIST			0xFD10	/* used */
+#define HERMES_RID_CHANNELLIST			0xFD10
 #define HERMES_RID_REGULATORYDOMAINS		0xFD11
 #define HERMES_RID_TEMPTYPE			0xFD12
 #define HERMES_RID_CIS				0xFD13
-#define HERMES_RID_STAID			0xFD20	/* used */
+#define HERMES_RID_STAID			0xFD20
 #define HERMES_RID_STASUPRANGE			0xFD21
 #define HERMES_RID_MFIACTRANGES			0xFD22
 #define HERMES_RID_CFIACTRANGES2		0xFD23
-#define HERMES_RID_SECONDARYVERSION_SYMBOL	0xFD24	/* used */
+#define HERMES_RID_SECONDARYVERSION_SYMBOL	0xFD24
 #define HERMES_RID_PORTSTATUS			0xFD40
-#define HERMES_RID_CURRENTSSID			0xFD41	/* used */
-#define HERMES_RID_CURRENTBSSID			0xFD42	/* used */
-#define HERMES_RID_COMMSQUALITY			0xFD43	/* used */
-#define HERMES_RID_CURRENTTXRATE		0xFD44	/* used */
+#define HERMES_RID_CURRENTSSID			0xFD41
+#define HERMES_RID_CURRENTBSSID			0xFD42
+#define HERMES_RID_COMMSQUALITY			0xFD43
+#define HERMES_RID_CURRENTTXRATE		0xFD44
 #define HERMES_RID_CURRENTBEACONINTERVAL	0xFD45
 #define HERMES_RID_CURRENTSCALETHRESHOLDS	0xFD46
 #define HERMES_RID_PROTOCOLRSPTIME		0xFD47
-#define HERMES_RID_SHORTRETRYLIMIT		0xFD48	/* used */
-#define HERMES_RID_LONGRETRYLIMIT		0xFD49	/* used */
-#define HERMES_RID_MAXTRANSMITLIFETIME		0xFD4A	/* used */
+#define HERMES_RID_SHORTRETRYLIMIT		0xFD48
+#define HERMES_RID_LONGRETRYLIMIT		0xFD49
+#define HERMES_RID_MAXTRANSMITLIFETIME		0xFD4A
 #define HERMES_RID_MAXRECEIVELIFETIME		0xFD4B
 #define HERMES_RID_CFPOLLABLE			0xFD4C
 #define HERMES_RID_AUTHENTICATIONALGORITHMS	0xFD4D
 #define HERMES_RID_PRIVACYOPTIONIMPLEMENTED	0xFD4F
+#define HERMES_RID_DBMCOMMSQUALITY_INTERSIL	0xFD51
 #define HERMES_RID_CURRENTTXRATE1		0xFD80
 #define HERMES_RID_CURRENTTXRATE2		0xFD81
 #define HERMES_RID_CURRENTTXRATE3		0xFD82
@@ -133,21 +138,11 @@
 #define HERMES_RID_OWNMACADDR			0xFD86
 #define HERMES_RID_SCANRESULTSTABLE		0xFD88
 #define HERMES_RID_PHYTYPE			0xFDC0
-#define HERMES_RID_CURRENTCHANNEL		0xFDC1	/* used */
+#define HERMES_RID_CURRENTCHANNEL		0xFDC1
 #define HERMES_RID_CURRENTPOWERSTATE		0xFDC2
 #define HERMES_RID_CCAMODE			0xFDC3
-#define HERMES_RID_SUPPORTEDDATARATES		0xFDC6	/* used */
+#define HERMES_RID_SUPPORTEDDATARATES		0xFDC6
 #define HERMES_RID_BUILDSEQ			0xFFFE
 #define HERMES_RID_FWID				0xFFFF
-
-/* "ID" structure - used for ESSID and station nickname */
-struct hermes_idstring {
-	u16 len;
-	u16 val[16];
-} __attribute__ ((packed));
-
-typedef struct hermes_multicast {
-	u8 addr[HERMES_MAX_MULTICAST][ETH_ALEN];
-} __attribute__ ((packed)) hermes_multicast_t;
 
 #endif
diff -Nru a/drivers/net/wireless/ieee802_11.h b/drivers/net/wireless/ieee802_11.h
--- a/drivers/net/wireless/ieee802_11.h	2004-10-18 14:56:32 -07:00
+++ b/drivers/net/wireless/ieee802_11.h	2004-10-18 14:56:32 -07:00
@@ -76,4 +76,3 @@
 #define IEEE802_11_SCTL_SEQ		0xFFF0
 
 #endif /* _IEEE802_11_H */
-
diff -Nru a/drivers/net/wireless/orinoco.c b/drivers/net/wireless/orinoco.c
--- a/drivers/net/wireless/orinoco.c	2004-10-18 14:57:05 -07:00
+++ b/drivers/net/wireless/orinoco.c	2004-10-18 14:57:05 -07:00
@@ -1,17 +1,23 @@
-/* orinoco.c 0.13e	- (formerly known as dldwd_cs.c and orinoco_cs.c)
+/* orinoco.c - (formerly known as dldwd_cs.c and orinoco_cs.c)
  *
  * A driver for Hermes or Prism 2 chipset based PCMCIA wireless
  * adaptors, with Lucent/Agere, Intersil or Symbol firmware.
  *
- * Copyright (C) 2000 David Gibson, Linuxcare Australia <hermes@gibson.dropbear.id.au>
+ * Current maintainers (as of 29 September 2003) are:
+ * 	Pavel Roskin <proski AT gnu.org>
+ * and	David Gibson <hermes AT gibson.dropbear.id.au>
+ *
+ * (C) Copyright David Gibson, IBM Corporation 2001-2003.
+ * Copyright (C) 2000 David Gibson, Linuxcare Australia.
  *	With some help from :
- * Copyright (C) 2001 Jean Tourrilhes, HP Labs <jt@hpl.hp.com>
- * Copyright (C) 2001 Benjamin Herrenschmidt <benh@kernel.crashing.org>
+ * Copyright (C) 2001 Jean Tourrilhes, HP Labs
+ * Copyright (C) 2001 Benjamin Herrenschmidt
  *
  * Based on dummy_cs.c 1.27 2000/06/12 21:27:25
  *
- * Portions based on wvlan_cs.c 1.0.6, Copyright Andreas Neuhaus <andy@fasta.fh-dortmund.de>
- *      http://www.fasta.fh-dortmund.de/users/andy/wvlan/
+ * Portions based on wvlan_cs.c 1.0.6, Copyright Andreas Neuhaus <andy
+ * AT fasta.fh-dortmund.de>
+ *      http://www.stud.fh-dortmund.de/~andy/wvlan/
  *
  * The contents of this file are subject to the Mozilla Public License
  * Version 1.1 (the "License"); you may not use this file except in
@@ -24,7 +30,7 @@
  * limitations under the License.
  *
  * The initial developer of the original code is David A. Hinds
- * <dahinds@users.sourceforge.net>.  Portions created by David
+ * <dahinds AT users.sourceforge.net>.  Portions created by David
  * A. Hinds are Copyright (C) 1999 David A. Hinds.  All Rights
  * Reserved.
  *
@@ -58,7 +64,7 @@
  *	o Add PM timeout (holdover duration)
  *	o Enable "iwconfig eth0 key off" and friends (toggle flags)
  *	o Enable "iwconfig eth0 power unicast/all" (toggle flags)
- *	o Try with an intel card. It report firmware 1.01, behave like
+ *	o Try with an Intel card. It report firmware 1.01, behave like
  *	  an antiquated firmware, however on windows it says 2.00. Yuck !
  *	o Workaround firmware bug in allocate buffer (Intel 1.01)
  *	o Finish external renaming to orinoco...
@@ -68,8 +74,8 @@
  *	o Update to Wireless 11 -> add retry limit/lifetime support
  *	o Tested with a D-Link DWL 650 card, fill in firmware support
  *	o Warning on Vcc mismatch (D-Link 3.3v card in Lucent 5v only slot)
- *	o Fixed the Prims2 WEP bugs that I introduced in v0.03 :-(
- *	  It work on D-Link *only* after a tcpdump. Weird...
+ *	o Fixed the Prism2 WEP bugs that I introduced in v0.03 :-(
+ *	  It works on D-Link *only* after a tcpdump. Weird...
  *	  And still doesn't work on Intel card. Grrrr...
  *	o Update the mode after a setport3
  *	o Add preamble setting for Symbol cards (not yet enabled)
@@ -82,7 +88,7 @@
  *	o Clean up RID definitions in hermes.h, other cleanups
  *
  * v0.04b -> v0.04c - 24/4/2001 - Jean II
- *	o Tim Hurley <timster@seiki.bliztech.com> reported a D-Link card
+ *	o Tim Hurley <timster AT seiki.bliztech.com> reported a D-Link card
  *	  with vendor 02 and firmware 0.08. Added in the capabilities...
  *	o Tested Lucent firmware 7.28, everything works...
  *
@@ -105,15 +111,15 @@
  *	o Remove deferred power enabling code
  *
  * v0.05c -> v0.05d - 5/5/2001 - Jean II
- *	o Workaround to SNAP decapsulate frame from LinkSys AP
- *	  original patch from : Dong Liu <dliu@research.bell-labs.com>
+ *	o Workaround to SNAP decapsulate frame from Linksys AP
+ *	  original patch from : Dong Liu <dliu AT research.bell-labs.com>
  *	  (note : the memcmp bug was mine - fixed)
  *	o Remove set_retry stuff, no firmware support it (bloat--).
  *
  * v0.05d -> v0.06 - 25/5/2001 - Jean II
- *		Original patch from "Hong Lin" <alin@redhat.com>,
- *		"Ian Kinner" <ikinner@redhat.com>
- *		and "David Smith" <dsmith@redhat.com>
+ *		Original patch from "Hong Lin" <alin AT redhat.com>,
+ *		"Ian Kinner" <ikinner AT redhat.com>
+ *		and "David Smith" <dsmith AT redhat.com>
  *	o Init of priv->tx_rate_ctrl in firmware specific section.
  *	o Prism2/Symbol rate, upto should be 0xF and not 0x15. Doh !
  *	o Spectrum card always need cor_reset (for every reset)
@@ -134,15 +140,15 @@
  *
  * v0.06c -> v0.06d - 6/7/2001 - David Gibson
  *      o Change a bunch of KERN_INFO messages to KERN_DEBUG, as per Linus'
- *        wishes to reduce the number of unecessary messages.
+ *        wishes to reduce the number of unnecessary messages.
  *	o Removed bogus message on CRC error.
- *	o Merged fixeds for v0.08 Prism 2 firmware from William Waghorn
- *	  <willwaghorn@yahoo.co.uk>
+ *	o Merged fixes for v0.08 Prism 2 firmware from William Waghorn
+ *	  <willwaghorn AT yahoo.co.uk>
  *	o Slight cleanup/re-arrangement of firmware detection code.
  *
  * v0.06d -> v0.06e - 1/8/2001 - David Gibson
  *	o Removed some redundant global initializers (orinoco_cs.c).
- *	o Added some module metadataa
+ *	o Added some module metadata
  *
  * v0.06e -> v0.06f - 14/8/2001 - David Gibson
  *	o Wording fix to license
@@ -159,7 +165,7 @@
  * v0.07 -> v0.07a - 1/10/3001 - Jean II
  *	o Add code to read Symbol firmware revision, inspired by latest code
  *	  in Spectrum24 by Lee John Keyser-Allen - Thanks Lee !
- *	o Thanks to Jared Valentine <hidden@xmission.com> for "providing" me
+ *	o Thanks to Jared Valentine <hidden AT xmission.com> for "providing" me
  *	  a 3Com card with a recent firmware, fill out Symbol firmware
  *	  capabilities of latest rev (2.20), as well as older Symbol cards.
  *	o Disable Power Management in newer Symbol firmware, the API 
@@ -172,7 +178,7 @@
  *	o Turned has_big_wep on for Intersil cards.  That's not true for all of
  *	  them but we should at least let the capable ones try.
  *	o Wait for BUSY to clear at the beginning of hermes_bap_seek().  I
- *	  realised that my assumption that the driver's serialization
+ *	  realized that my assumption that the driver's serialization
  *	  would prevent the BAP being busy on entry was possibly false, because
  *	  things other than seeks may make the BAP busy.
  *	o Use "alternate" (oui 00:00:00) encapsulation by default.
@@ -181,12 +187,12 @@
  *	o Don't try to make __initdata const (the version string).  This can't
  *	  work because of the way the __initdata sectioning works.
  *	o Added MODULE_LICENSE tags.
- *	o Support for PLX (transparent PCMCIA->PCI brdge) cards.
- *	o Changed to using the new type-facist min/max.
+ *	o Support for PLX (transparent PCMCIA->PCI bridge) cards.
+ *	o Changed to using the new type-fascist min/max.
  *
  * v0.08 -> v0.08a - 9/10/2001 - David Gibson
  *	o Inserted some missing acknowledgements/info into the Changelog.
- *	o Fixed some bugs in the normalisation of signel level reporting.
+ *	o Fixed some bugs in the normalization of signal level reporting.
  *	o Fixed bad bug in WEP key handling on Intersil and Symbol firmware,
  *	  which led to an instant crash on big-endian machines.
  *
@@ -342,7 +348,7 @@
  *	o Bugfix in orinoco_stop() - it used to fail if hw_unavailable
  *	  was set, which was usually true on PCMCIA hot removes.
  * 	o Track LINKSTATUS messages, silently drop Tx packets before
- * 	  we are connected (avoids cofusing the firmware), and only
+ * 	  we are connected (avoids confusing the firmware), and only
  * 	  give LINKSTATUS printk()s if the status has changed.
  *
  * v0.13b -> v0.13c - 11 Mar 2003 - David Gibson
@@ -397,7 +403,8 @@
  *	o Disconnect wireless extensions from fundamental configuration.
  *	o (maybe) Software WEP support (patch from Stano Meduna).
  *	o (maybe) Use multiple Tx buffers - driver handling queue
- *	  rather than firmware. */
+ *	  rather than firmware.
+ */
 
 /* Locking and synchronization:
  *
@@ -414,7 +421,10 @@
  * flag after taking the lock, and if it is set, give up on whatever
  * they are doing and drop the lock again.  The orinoco_lock()
  * function handles this (it unlocks and returns -EBUSY if
- * hw_unavailable is non-zero). */
+ * hw_unavailable is non-zero).
+ */
+
+#define DRIVER_NAME "orinoco"
 
 #include <linux/config.h>
 
@@ -444,11 +454,9 @@
 /* Module information                                               */
 /********************************************************************/
 
-MODULE_AUTHOR("David Gibson <hermes@gibson.dropbear.id.au>");
+MODULE_AUTHOR("Pavel Roskin <proski@gnu.org> & David Gibson <hermes@gibson.dropbear.id.au>");
 MODULE_DESCRIPTION("Driver for Lucent Orinoco, Prism II based and similar wireless cards");
-#ifdef MODULE_LICENSE
 MODULE_LICENSE("Dual MPL/GPL");
-#endif
 
 /* Level of debugging. Used in the macros in orinoco.h */
 #ifdef ORINOCO_DEBUG
@@ -464,11 +472,6 @@
 /* Compile time configuration and compatibility stuff               */
 /********************************************************************/
 
-/* Wireless extensions backwards compatibility */
-#ifndef SIOCIWFIRSTPRIV
-#define SIOCIWFIRSTPRIV		SIOCDEVPRIVATE
-#endif /* SIOCIWFIRSTPRIV */
-
 /* We do this this way to avoid ifdefs in the actual code */
 #ifdef WIRELESS_SPY
 #define SPY_NUMBER(priv)	(priv->spy_number)
@@ -497,25 +500,29 @@
 
 #define DUMMY_FID		0xFFFF
 
-#define RUP_EVEN(a) (((a) + 1) & (~1))
-
 /*#define MAX_MULTICAST(priv)	(priv->firmware_type == FIRMWARE_TYPE_AGERE ? \
   HERMES_MAX_MULTICAST : 0)*/
 #define MAX_MULTICAST(priv)	(HERMES_MAX_MULTICAST)
 
+#define ORINOCO_INTEN	 	(HERMES_EV_RX | HERMES_EV_ALLOC \
+				 | HERMES_EV_TX | HERMES_EV_TXEXC \
+				 | HERMES_EV_WTERR | HERMES_EV_INFO \
+				 | HERMES_EV_INFDROP )
+
 /********************************************************************/
 /* Data tables                                                      */
 /********************************************************************/
 
 /* The frequency of each channel in MHz */
-const long channel_frequency[] = {
+static const long channel_frequency[] = {
 	2412, 2417, 2422, 2427, 2432, 2437, 2442,
 	2447, 2452, 2457, 2462, 2467, 2472, 2484
 };
-#define NUM_CHANNELS ( sizeof(channel_frequency) / sizeof(channel_frequency[0]) )
+#define NUM_CHANNELS ARRAY_SIZE(channel_frequency)
 
-/* This tables gives the actual meanings of the bitrate IDs returned by the firmware. */
-struct {
+/* This tables gives the actual meanings of the bitrate IDs returned
+ * by the firmware. */
+static struct {
 	int bitrate; /* in 100s of kilobits */
 	int automatic;
 	u16 agere_txratectrl;
@@ -530,7 +537,7 @@
 	{55,  1,  7,  7},
 	{110, 0,  5,  8},
 };
-#define BITRATE_TABLE_SIZE (sizeof(bitrate_table) / sizeof(bitrate_table[0]))
+#define BITRATE_TABLE_SIZE ARRAY_SIZE(bitrate_table)
 
 /********************************************************************/
 /* Data types                                                       */
@@ -555,46 +562,758 @@
 
 #define ENCAPS_OVERHEAD		(sizeof(encaps_hdr) + 2)
 
+struct hermes_rx_descriptor {
+	u16 status;
+	u32 time;
+	u8 silence;
+	u8 signal;
+	u8 rate;
+	u8 rxflow;
+	u32 reserved;
+} __attribute__ ((packed));
+
 /********************************************************************/
 /* Function prototypes                                              */
 /********************************************************************/
 
+static int orinoco_ioctl(struct net_device *dev, struct ifreq *rq, int cmd);
+static int __orinoco_program_rids(struct net_device *dev);
+static void __orinoco_set_multicast_list(struct net_device *dev);
+static int orinoco_debug_dump_recs(struct net_device *dev);
+
+/********************************************************************/
+/* Internal helper functions                                        */
+/********************************************************************/
+
+static inline void set_port_type(struct orinoco_private *priv)
+{
+	switch (priv->iw_mode) {
+	case IW_MODE_INFRA:
+		priv->port_type = 1;
+		priv->createibss = 0;
+		break;
+	case IW_MODE_ADHOC:
+		if (priv->prefer_port3) {
+			priv->port_type = 3;
+			priv->createibss = 0;
+		} else {
+			priv->port_type = priv->ibss_port;
+			priv->createibss = 1;
+		}
+		break;
+	default:
+		printk(KERN_ERR "%s: Invalid priv->iw_mode in set_port_type()\n",
+		       priv->ndev->name);
+	}
+}
+
+/********************************************************************/
+/* Device methods                                                   */
+/********************************************************************/
+
+static int orinoco_open(struct net_device *dev)
+{
+	struct orinoco_private *priv = netdev_priv(dev);
+	unsigned long flags;
+	int err;
+
+	err = orinoco_lock(priv, &flags);
+	if (err)
+		return err;
+
+	err = __orinoco_up(dev);
+
+	if (! err)
+		priv->open = 1;
+
+	orinoco_unlock(priv, &flags);
+
+	return err;
+}
+
+int orinoco_stop(struct net_device *dev)
+{
+	struct orinoco_private *priv = netdev_priv(dev);
+	int err = 0;
+
+	/* We mustn't use orinoco_lock() here, because we need to be
+	   able to close the interface even if hw_unavailable is set
+	   (e.g. as we're released after a PC Card removal) */
+	spin_lock_irq(&priv->lock);
+
+	priv->open = 0;
+
+	err = __orinoco_down(dev);
+
+	spin_unlock_irq(&priv->lock);
+
+	return err;
+}
+
+static struct net_device_stats *orinoco_get_stats(struct net_device *dev)
+{
+	struct orinoco_private *priv = netdev_priv(dev);
+	
+	return &priv->stats;
+}
+
+static struct iw_statistics *orinoco_get_wireless_stats(struct net_device *dev)
+{
+	struct orinoco_private *priv = netdev_priv(dev);
+	hermes_t *hw = &priv->hw;
+	struct iw_statistics *wstats = &priv->wstats;
+	int err = 0;
+	unsigned long flags;
+
+	if (! netif_device_present(dev)) {
+		printk(KERN_WARNING "%s: get_wireless_stats() called while device not present\n",
+		       dev->name);
+		return NULL; /* FIXME: Can we do better than this? */
+	}
+
+	err = orinoco_lock(priv, &flags);
+	if (err)
+		return NULL; /* FIXME: Erg, we've been signalled, how
+			      * do we propagate this back up? */
+
+	if (priv->iw_mode == IW_MODE_ADHOC) {
+		memset(&wstats->qual, 0, sizeof(wstats->qual));
+		/* If a spy address is defined, we report stats of the
+		 * first spy address - Jean II */
+		if (SPY_NUMBER(priv)) {
+			wstats->qual.qual = priv->spy_stat[0].qual;
+			wstats->qual.level = priv->spy_stat[0].level;
+			wstats->qual.noise = priv->spy_stat[0].noise;
+			wstats->qual.updated = priv->spy_stat[0].updated;
+		}
+	} else {
+		struct {
+			u16 qual, signal, noise;
+		} __attribute__ ((packed)) cq;
+
+		err = HERMES_READ_RECORD(hw, USER_BAP,
+					 HERMES_RID_COMMSQUALITY, &cq);
+		
+		wstats->qual.qual = (int)le16_to_cpu(cq.qual);
+		wstats->qual.level = (int)le16_to_cpu(cq.signal) - 0x95;
+		wstats->qual.noise = (int)le16_to_cpu(cq.noise) - 0x95;
+		wstats->qual.updated = 7;
+	}
+
+	/* We can't really wait for the tallies inquiry command to
+	 * complete, so we just use the previous results and trigger
+	 * a new tallies inquiry command for next time - Jean II */
+	/* FIXME: We're in user context (I think?), so we should just
+           wait for the tallies to come through */
+	err = hermes_inquire(hw, HERMES_INQ_TALLIES);
+               
+	orinoco_unlock(priv, &flags);
+
+	if (err)
+		return NULL;
+		
+	return wstats;
+}
+
+static void orinoco_set_multicast_list(struct net_device *dev)
+{
+	struct orinoco_private *priv = netdev_priv(dev);
+	unsigned long flags;
+
+	if (orinoco_lock(priv, &flags) != 0) {
+		printk(KERN_DEBUG "%s: orinoco_set_multicast_list() "
+		       "called when hw_unavailable\n", dev->name);
+		return;
+	}
+
+	__orinoco_set_multicast_list(dev);
+	orinoco_unlock(priv, &flags);
+}
+
+static int orinoco_change_mtu(struct net_device *dev, int new_mtu)
+{
+	struct orinoco_private *priv = netdev_priv(dev);
+
+	if ( (new_mtu < ORINOCO_MIN_MTU) || (new_mtu > ORINOCO_MAX_MTU) )
+		return -EINVAL;
+
+	if ( (new_mtu + ENCAPS_OVERHEAD + IEEE802_11_HLEN) >
+	     (priv->nicbuf_size - ETH_HLEN) )
+		return -EINVAL;
+
+	dev->mtu = new_mtu;
+
+	return 0;
+}
+
+/********************************************************************/
+/* Tx path                                                          */
+/********************************************************************/
+
+static int orinoco_xmit(struct sk_buff *skb, struct net_device *dev)
+{
+	struct orinoco_private *priv = netdev_priv(dev);
+	struct net_device_stats *stats = &priv->stats;
+	hermes_t *hw = &priv->hw;
+	int err = 0;
+	u16 txfid = priv->txfid;
+	char *p;
+	struct ethhdr *eh;
+	int len, data_len, data_off;
+	struct hermes_tx_descriptor desc;
+	unsigned long flags;
+
+	TRACE_ENTER(dev->name);
+
+	if (! netif_running(dev)) {
+		printk(KERN_ERR "%s: Tx on stopped device!\n",
+		       dev->name);
+		TRACE_EXIT(dev->name);
+		return 1;
+	}
+	
+	if (netif_queue_stopped(dev)) {
+		printk(KERN_DEBUG "%s: Tx while transmitter busy!\n", 
+		       dev->name);
+		TRACE_EXIT(dev->name);
+		return 1;
+	}
+	
+	if (orinoco_lock(priv, &flags) != 0) {
+		printk(KERN_ERR "%s: orinoco_xmit() called while hw_unavailable\n",
+		       dev->name);
+		TRACE_EXIT(dev->name);
+		return 1;
+	}
+
+	if (! priv->connected) {
+		/* Oops, the firmware hasn't established a connection,
+                   silently drop the packet (this seems to be the
+                   safest approach). */
+		stats->tx_errors++;
+		orinoco_unlock(priv, &flags);
+		dev_kfree_skb(skb);
+		TRACE_EXIT(dev->name);
+		return 0;
+	}
+
+	/* Length of the packet body */
+	/* FIXME: what if the skb is smaller than this? */
+	len = max_t(int,skb->len - ETH_HLEN, ETH_ZLEN - ETH_HLEN);
+
+	eh = (struct ethhdr *)skb->data;
+
+	memset(&desc, 0, sizeof(desc));
+ 	desc.tx_control = cpu_to_le16(HERMES_TXCTRL_TX_OK | HERMES_TXCTRL_TX_EX);
+	err = hermes_bap_pwrite(hw, USER_BAP, &desc, sizeof(desc), txfid, 0);
+	if (err) {
+		printk(KERN_ERR "%s: Error %d writing Tx descriptor to BAP\n",
+		       dev->name, err);
+		stats->tx_errors++;
+		goto fail;
+	}
+
+	/* Clear the 802.11 header and data length fields - some
+	 * firmwares (e.g. Lucent/Agere 8.xx) appear to get confused
+	 * if this isn't done. */
+	hermes_clear_words(hw, HERMES_DATA0,
+			   HERMES_802_3_OFFSET - HERMES_802_11_OFFSET);
+
+	/* Encapsulate Ethernet-II frames */
+	if (ntohs(eh->h_proto) > ETH_DATA_LEN) { /* Ethernet-II frame */
+		struct header_struct hdr;
+		data_len = len;
+		data_off = HERMES_802_3_OFFSET + sizeof(hdr);
+		p = skb->data + ETH_HLEN;
+
+		/* 802.3 header */
+		memcpy(hdr.dest, eh->h_dest, ETH_ALEN);
+		memcpy(hdr.src, eh->h_source, ETH_ALEN);
+		hdr.len = htons(data_len + ENCAPS_OVERHEAD);
+		
+		/* 802.2 header */
+		memcpy(&hdr.dsap, &encaps_hdr, sizeof(encaps_hdr));
+			
+		hdr.ethertype = eh->h_proto;
+		err  = hermes_bap_pwrite(hw, USER_BAP, &hdr, sizeof(hdr),
+					 txfid, HERMES_802_3_OFFSET);
+		if (err) {
+			printk(KERN_ERR "%s: Error %d writing packet header to BAP\n",
+			       dev->name, err);
+			stats->tx_errors++;
+			goto fail;
+		}
+	} else { /* IEEE 802.3 frame */
+		data_len = len + ETH_HLEN;
+		data_off = HERMES_802_3_OFFSET;
+		p = skb->data;
+	}
+
+	/* Round up for odd length packets */
+	err = hermes_bap_pwrite(hw, USER_BAP, p, ALIGN(data_len, 2),
+				txfid, data_off);
+	if (err) {
+		printk(KERN_ERR "%s: Error %d writing packet to BAP\n",
+		       dev->name, err);
+		stats->tx_errors++;
+		goto fail;
+	}
+
+	/* Finally, we actually initiate the send */
+	netif_stop_queue(dev);
+
+	err = hermes_docmd_wait(hw, HERMES_CMD_TX | HERMES_CMD_RECL,
+				txfid, NULL);
+	if (err) {
+		netif_start_queue(dev);
+		printk(KERN_ERR "%s: Error %d transmitting packet\n",
+		       dev->name, err);
+		stats->tx_errors++;
+		goto fail;
+	}
+
+	dev->trans_start = jiffies;
+	stats->tx_bytes += data_off + data_len;
+
+	orinoco_unlock(priv, &flags);
+
+	dev_kfree_skb(skb);
+
+	TRACE_EXIT(dev->name);
+
+	return 0;
+ fail:
+	TRACE_EXIT(dev->name);
+
+	orinoco_unlock(priv, &flags);
+	return err;
+}
+
+static void __orinoco_ev_alloc(struct net_device *dev, hermes_t *hw)
+{
+	struct orinoco_private *priv = netdev_priv(dev);
+	u16 fid = hermes_read_regn(hw, ALLOCFID);
+
+	if (fid != priv->txfid) {
+		if (fid != DUMMY_FID)
+			printk(KERN_WARNING "%s: Allocate event on unexpected fid (%04X)\n",
+			       dev->name, fid);
+		return;
+	} else {
+		netif_wake_queue(dev);
+	}
+
+	hermes_write_regn(hw, ALLOCFID, DUMMY_FID);
+}
+
+static void __orinoco_ev_tx(struct net_device *dev, hermes_t *hw)
+{
+	struct orinoco_private *priv = netdev_priv(dev);
+	struct net_device_stats *stats = &priv->stats;
+
+	stats->tx_packets++;
+
+	hermes_write_regn(hw, TXCOMPLFID, DUMMY_FID);
+}
+
+static void __orinoco_ev_txexc(struct net_device *dev, hermes_t *hw)
+{
+	struct orinoco_private *priv = netdev_priv(dev);
+	struct net_device_stats *stats = &priv->stats;
+	u16 fid = hermes_read_regn(hw, TXCOMPLFID);
+	struct hermes_tx_descriptor desc;
+	int err = 0;
+
+	if (fid == DUMMY_FID)
+		return; /* Nothing's really happened */
+
+	err = hermes_bap_pread(hw, IRQ_BAP, &desc, sizeof(desc), fid, 0);
+	if (err) {
+		printk(KERN_WARNING "%s: Unable to read descriptor on Tx error "
+		       "(FID=%04X error %d)\n",
+		       dev->name, fid, err);
+	} else {
+		DEBUG(1, "%s: Tx error, status %d\n",
+		      dev->name, le16_to_cpu(desc.status));
+	}
+	
+	stats->tx_errors++;
+
+	hermes_write_regn(hw, TXCOMPLFID, DUMMY_FID);
+}
+
+static void orinoco_tx_timeout(struct net_device *dev)
+{
+	struct orinoco_private *priv = netdev_priv(dev);
+	struct net_device_stats *stats = &priv->stats;
+	struct hermes *hw = &priv->hw;
+
+	printk(KERN_WARNING "%s: Tx timeout! "
+	       "ALLOCFID=%04x, TXCOMPLFID=%04x, EVSTAT=%04x\n",
+	       dev->name, hermes_read_regn(hw, ALLOCFID),
+	       hermes_read_regn(hw, TXCOMPLFID), hermes_read_regn(hw, EVSTAT));
+
+	stats->tx_errors++;
+
+	schedule_work(&priv->reset_work);
+}
+
+/********************************************************************/
+/* Rx path (data frames)                                            */
+/********************************************************************/
+
+/* Does the frame have a SNAP header indicating it should be
+ * de-encapsulated to Ethernet-II? */
+static inline int is_ethersnap(struct header_struct *hdr)
+{
+	/* We de-encapsulate all packets which, a) have SNAP headers
+	 * (i.e. SSAP=DSAP=0xaa and CTRL=0x3 in the 802.2 LLC header
+	 * and where b) the OUI of the SNAP header is 00:00:00 or
+	 * 00:00:f8 - we need both because different APs appear to use
+	 * different OUIs for some reason */
+	return (memcmp(&hdr->dsap, &encaps_hdr, 5) == 0)
+		&& ( (hdr->oui[2] == 0x00) || (hdr->oui[2] == 0xf8) );
+}
+
+static inline void orinoco_spy_gather(struct net_device *dev, u_char *mac,
+				      int level, int noise)
+{
+	struct orinoco_private *priv = netdev_priv(dev);
+	int i;
+
+	/* Gather wireless spy statistics: for each packet, compare the
+	 * source address with out list, and if match, get the stats... */
+	for (i = 0; i < priv->spy_number; i++)
+		if (!memcmp(mac, priv->spy_address[i], ETH_ALEN)) {
+			priv->spy_stat[i].level = level - 0x95;
+			priv->spy_stat[i].noise = noise - 0x95;
+			priv->spy_stat[i].qual = (level > noise) ? (level - noise) : 0;
+			priv->spy_stat[i].updated = 7;
+		}
+}
+
 static void orinoco_stat_gather(struct net_device *dev,
 				struct sk_buff *skb,
-				struct hermes_rx_descriptor *desc);
+				struct hermes_rx_descriptor *desc)
+{
+	struct orinoco_private *priv = netdev_priv(dev);
 
-static struct net_device_stats *orinoco_get_stats(struct net_device *dev);
-static struct iw_statistics *orinoco_get_wireless_stats(struct net_device *dev);
+	/* Using spy support with lots of Rx packets, like in an
+	 * infrastructure (AP), will really slow down everything, because
+	 * the MAC address must be compared to each entry of the spy list.
+	 * If the user really asks for it (set some address in the
+	 * spy list), we do it, but he will pay the price.
+	 * Note that to get here, you need both WIRELESS_SPY
+	 * compiled in AND some addresses in the list !!!
+	 */
+	/* Note : gcc will optimise the whole section away if
+	 * WIRELESS_SPY is not defined... - Jean II */
+	if (SPY_NUMBER(priv)) {
+		orinoco_spy_gather(dev, skb->mac.raw + ETH_ALEN,
+				   desc->signal, desc->silence);
+	}
+}
 
-/* Hardware control routines */
+static void __orinoco_ev_rx(struct net_device *dev, hermes_t *hw)
+{
+	struct orinoco_private *priv = netdev_priv(dev);
+	struct net_device_stats *stats = &priv->stats;
+	struct iw_statistics *wstats = &priv->wstats;
+	struct sk_buff *skb = NULL;
+	u16 rxfid, status;
+	int length, data_len, data_off;
+	char *p;
+	struct hermes_rx_descriptor desc;
+	struct header_struct hdr;
+	struct ethhdr *eh;
+	int err;
 
-static int __orinoco_program_rids(struct net_device *dev);
+	rxfid = hermes_read_regn(hw, RXFID);
 
-static int __orinoco_hw_set_bitrate(struct orinoco_private *priv);
-static int __orinoco_hw_setup_wep(struct orinoco_private *priv);
-static int orinoco_hw_get_bssid(struct orinoco_private *priv, char buf[ETH_ALEN]);
-static int orinoco_hw_get_essid(struct orinoco_private *priv, int *active,
-				char buf[IW_ESSID_MAX_SIZE+1]);
-static long orinoco_hw_get_freq(struct orinoco_private *priv);
-static int orinoco_hw_get_bitratelist(struct orinoco_private *priv, int *numrates,
-				      s32 *rates, int max);
-static void __orinoco_set_multicast_list(struct net_device *dev);
+	err = hermes_bap_pread(hw, IRQ_BAP, &desc, sizeof(desc),
+			       rxfid, 0);
+	if (err) {
+		printk(KERN_ERR "%s: error %d reading Rx descriptor. "
+		       "Frame dropped.\n", dev->name, err);
+		stats->rx_errors++;
+		goto drop;
+	}
 
-/* Interrupt handling routines */
-static void __orinoco_ev_tick(struct net_device *dev, hermes_t *hw);
-static void __orinoco_ev_wterr(struct net_device *dev, hermes_t *hw);
-static void __orinoco_ev_infdrop(struct net_device *dev, hermes_t *hw);
-static void __orinoco_ev_info(struct net_device *dev, hermes_t *hw);
-static void __orinoco_ev_rx(struct net_device *dev, hermes_t *hw);
-static void __orinoco_ev_txexc(struct net_device *dev, hermes_t *hw);
-static void __orinoco_ev_tx(struct net_device *dev, hermes_t *hw);
-static void __orinoco_ev_alloc(struct net_device *dev, hermes_t *hw);
+	status = le16_to_cpu(desc.status);
 
-/* ioctl() routines */
-static int orinoco_debug_dump_recs(struct net_device *dev);
+	if (status & HERMES_RXSTAT_ERR) {
+		if (status & HERMES_RXSTAT_UNDECRYPTABLE) {
+			wstats->discard.code++;
+			DEBUG(1, "%s: Undecryptable frame on Rx. Frame dropped.\n",
+			       dev->name);
+		} else {
+			stats->rx_crc_errors++;
+			DEBUG(1, "%s: Bad CRC on Rx. Frame dropped.\n", dev->name);
+		}
+		stats->rx_errors++;
+		goto drop;
+	}
+
+	/* For now we ignore the 802.11 header completely, assuming
+           that the card's firmware has handled anything vital */
+
+	err = hermes_bap_pread(hw, IRQ_BAP, &hdr, sizeof(hdr),
+			       rxfid, HERMES_802_3_OFFSET);
+	if (err) {
+		printk(KERN_ERR "%s: error %d reading frame header. "
+		       "Frame dropped.\n", dev->name, err);
+		stats->rx_errors++;
+		goto drop;
+	}
+
+	length = ntohs(hdr.len);
+	
+	/* Sanity checks */
+	if (length < 3) { /* No for even an 802.2 LLC header */
+		/* At least on Symbol firmware with PCF we get quite a
+                   lot of these legitimately - Poll frames with no
+                   data. */
+		stats->rx_dropped++;
+		goto drop;
+	}
+	if (length > IEEE802_11_DATA_LEN) {
+		printk(KERN_WARNING "%s: Oversized frame received (%d bytes)\n",
+		       dev->name, length);
+		stats->rx_length_errors++;
+		stats->rx_errors++;
+		goto drop;
+	}
+
+	/* We need space for the packet data itself, plus an ethernet
+	   header, plus 2 bytes so we can align the IP header on a
+	   32bit boundary, plus 1 byte so we can read in odd length
+	   packets from the card, which has an IO granularity of 16
+	   bits */  
+	skb = dev_alloc_skb(length+ETH_HLEN+2+1);
+	if (!skb) {
+		printk(KERN_WARNING "%s: Can't allocate skb for Rx\n",
+		       dev->name);
+		goto drop;
+	}
+
+	skb_reserve(skb, 2); /* This way the IP header is aligned */
+
+	/* Handle decapsulation
+	 * In most cases, the firmware tell us about SNAP frames.
+	 * For some reason, the SNAP frames sent by LinkSys APs
+	 * are not properly recognised by most firmwares.
+	 * So, check ourselves */
+	if (((status & HERMES_RXSTAT_MSGTYPE) == HERMES_RXSTAT_1042) ||
+	    ((status & HERMES_RXSTAT_MSGTYPE) == HERMES_RXSTAT_TUNNEL) ||
+	    is_ethersnap(&hdr)) {
+		/* These indicate a SNAP within 802.2 LLC within
+		   802.11 frame which we'll need to de-encapsulate to
+		   the original EthernetII frame. */
+
+		if (length < ENCAPS_OVERHEAD) { /* No room for full LLC+SNAP */
+			stats->rx_length_errors++;
+			goto drop;
+		}
+
+		/* Remove SNAP header, reconstruct EthernetII frame */
+		data_len = length - ENCAPS_OVERHEAD;
+		data_off = HERMES_802_3_OFFSET + sizeof(hdr);
+
+		eh = (struct ethhdr *)skb_put(skb, ETH_HLEN);
+
+		memcpy(eh, &hdr, 2 * ETH_ALEN);
+		eh->h_proto = hdr.ethertype;
+	} else {
+		/* All other cases indicate a genuine 802.3 frame.  No
+		   decapsulation needed.  We just throw the whole
+		   thing in, and hope the protocol layer can deal with
+		   it as 802.3 */
+		data_len = length;
+		data_off = HERMES_802_3_OFFSET;
+		/* FIXME: we re-read from the card data we already read here */
+	}
+
+	p = skb_put(skb, data_len);
+	err = hermes_bap_pread(hw, IRQ_BAP, p, ALIGN(data_len, 2),
+			       rxfid, data_off);
+	if (err) {
+		printk(KERN_ERR "%s: error %d reading frame. "
+		       "Frame dropped.\n", dev->name, err);
+		stats->rx_errors++;
+		goto drop;
+	}
+
+	dev->last_rx = jiffies;
+	skb->dev = dev;
+	skb->protocol = eth_type_trans(skb, dev);
+	skb->ip_summed = CHECKSUM_NONE;
+	
+	/* Process the wireless stats if needed */
+	orinoco_stat_gather(dev, skb, &desc);
+
+	/* Pass the packet to the networking stack */
+	netif_rx(skb);
+	stats->rx_packets++;
+	stats->rx_bytes += length;
+
+	return;
+
+ drop:	
+	stats->rx_dropped++;
+
+	if (skb)
+		dev_kfree_skb_irq(skb);
+	return;
+}
 
 /********************************************************************/
-/* Function prototypes                                              */
+/* Rx path (info frames)                                            */
+/********************************************************************/
+
+static void print_linkstatus(struct net_device *dev, u16 status)
+{
+	char * s;
+
+	if (suppress_linkstatus)
+		return;
+
+	switch (status) {
+	case HERMES_LINKSTATUS_NOT_CONNECTED:
+		s = "Not Connected";
+		break;
+	case HERMES_LINKSTATUS_CONNECTED:
+		s = "Connected";
+		break;
+	case HERMES_LINKSTATUS_DISCONNECTED:
+		s = "Disconnected";
+		break;
+	case HERMES_LINKSTATUS_AP_CHANGE:
+		s = "AP Changed";
+		break;
+	case HERMES_LINKSTATUS_AP_OUT_OF_RANGE:
+		s = "AP Out of Range";
+		break;
+	case HERMES_LINKSTATUS_AP_IN_RANGE:
+		s = "AP In Range";
+		break;
+	case HERMES_LINKSTATUS_ASSOC_FAILED:
+		s = "Association Failed";
+		break;
+	default:
+		s = "UNKNOWN";
+	}
+	
+	printk(KERN_INFO "%s: New link status: %s (%04x)\n",
+	       dev->name, s, status);
+}
+
+static void __orinoco_ev_info(struct net_device *dev, hermes_t *hw)
+{
+	struct orinoco_private *priv = netdev_priv(dev);
+	u16 infofid;
+	struct {
+		u16 len;
+		u16 type;
+	} __attribute__ ((packed)) info;
+	int len, type;
+	int err;
+
+	/* This is an answer to an INQUIRE command that we did earlier,
+	 * or an information "event" generated by the card
+	 * The controller return to us a pseudo frame containing
+	 * the information in question - Jean II */
+	infofid = hermes_read_regn(hw, INFOFID);
+
+	/* Read the info frame header - don't try too hard */
+	err = hermes_bap_pread(hw, IRQ_BAP, &info, sizeof(info),
+			       infofid, 0);
+	if (err) {
+		printk(KERN_ERR "%s: error %d reading info frame. "
+		       "Frame dropped.\n", dev->name, err);
+		return;
+	}
+	
+	len = HERMES_RECLEN_TO_BYTES(le16_to_cpu(info.len));
+	type = le16_to_cpu(info.type);
+
+	switch (type) {
+	case HERMES_INQ_TALLIES: {
+		struct hermes_tallies_frame tallies;
+		struct iw_statistics *wstats = &priv->wstats;
+		
+		if (len > sizeof(tallies)) {
+			printk(KERN_WARNING "%s: Tallies frame too long (%d bytes)\n",
+			       dev->name, len);
+			len = sizeof(tallies);
+		}
+		
+		/* Read directly the data (no seek) */
+		hermes_read_words(hw, HERMES_DATA1, (void *) &tallies,
+				  len / 2); /* FIXME: blech! */
+		
+		/* Increment our various counters */
+		/* wstats->discard.nwid - no wrong BSSID stuff */
+		wstats->discard.code +=
+			le16_to_cpu(tallies.RxWEPUndecryptable);
+		if (len == sizeof(tallies))  
+			wstats->discard.code +=
+				le16_to_cpu(tallies.RxDiscards_WEPICVError) +
+				le16_to_cpu(tallies.RxDiscards_WEPExcluded);
+		wstats->discard.misc +=
+			le16_to_cpu(tallies.TxDiscardsWrongSA);
+		wstats->discard.fragment +=
+			le16_to_cpu(tallies.RxMsgInBadMsgFragments);
+		wstats->discard.retries +=
+			le16_to_cpu(tallies.TxRetryLimitExceeded);
+		/* wstats->miss.beacon - no match */
+	}
+	break;
+	case HERMES_INQ_LINKSTATUS: {
+		struct hermes_linkstatus linkstatus;
+		u16 newstatus;
+
+		if (len != sizeof(linkstatus)) {
+			printk(KERN_WARNING "%s: Unexpected size for linkstatus frame (%d bytes)\n",
+			       dev->name, len);
+			break;
+		}
+
+		hermes_read_words(hw, HERMES_DATA1, (void *) &linkstatus,
+				  len / 2);
+		newstatus = le16_to_cpu(linkstatus.linkstatus);
+
+		if ( (newstatus == HERMES_LINKSTATUS_CONNECTED)
+		     || (newstatus == HERMES_LINKSTATUS_AP_CHANGE)
+		     || (newstatus == HERMES_LINKSTATUS_AP_IN_RANGE) )
+			priv->connected = 1;
+		else if ( (newstatus == HERMES_LINKSTATUS_NOT_CONNECTED)
+			  || (newstatus == HERMES_LINKSTATUS_DISCONNECTED)
+			  || (newstatus == HERMES_LINKSTATUS_AP_OUT_OF_RANGE)
+			  || (newstatus == HERMES_LINKSTATUS_ASSOC_FAILED) )
+			priv->connected = 0;
+
+		if (newstatus != priv->last_linkstatus)
+			print_linkstatus(dev, newstatus);
+
+		priv->last_linkstatus = newstatus;
+	}
+	break;
+	default:
+		printk(KERN_DEBUG "%s: Unknown information frame received "
+		       "(type %04x).\n", dev->name, type);
+		/* We don't actually do anything about it */
+		break;
+	}
+}
+
+static void __orinoco_ev_infdrop(struct net_device *dev, hermes_t *hw)
+{
+	if (net_ratelimit())
+		printk(KERN_WARNING "%s: Information frame lost.\n", dev->name);
+}
+
+/********************************************************************/
+/* Internal hardware control routines                               */
 /********************************************************************/
 
 int __orinoco_up(struct net_device *dev)
@@ -683,43 +1402,139 @@
 	return err;
 }
 
-static int orinoco_open(struct net_device *dev)
+static int __orinoco_hw_set_bitrate(struct orinoco_private *priv)
 {
-	struct orinoco_private *priv = netdev_priv(dev);
-	unsigned long flags;
-	int err;
-
-	err = orinoco_lock(priv, &flags);
-	if (err)
-		return err;
-
-	err = __orinoco_up(dev);
+	hermes_t *hw = &priv->hw;
+	int err = 0;
 
-	if (! err)
-		priv->open = 1;
+	if (priv->bitratemode >= BITRATE_TABLE_SIZE) {
+		printk(KERN_ERR "%s: BUG: Invalid bitrate mode %d\n",
+		       priv->ndev->name, priv->bitratemode);
+		return -EINVAL;
+	}
 
-	orinoco_unlock(priv, &flags);
+	switch (priv->firmware_type) {
+	case FIRMWARE_TYPE_AGERE:
+		err = hermes_write_wordrec(hw, USER_BAP,
+					   HERMES_RID_CNFTXRATECONTROL,
+					   bitrate_table[priv->bitratemode].agere_txratectrl);
+		break;
+	case FIRMWARE_TYPE_INTERSIL:
+	case FIRMWARE_TYPE_SYMBOL:
+		err = hermes_write_wordrec(hw, USER_BAP,
+					   HERMES_RID_CNFTXRATECONTROL,
+					   bitrate_table[priv->bitratemode].intersil_txratectrl);
+		break;
+	default:
+		BUG();
+	}
 
 	return err;
 }
 
-int orinoco_stop(struct net_device *dev)
+static int __orinoco_hw_setup_wep(struct orinoco_private *priv)
 {
-	struct orinoco_private *priv = netdev_priv(dev);
+	hermes_t *hw = &priv->hw;
 	int err = 0;
+	int	master_wep_flag;
+	int	auth_flag;
 
-	/* We mustn't use orinoco_lock() here, because we need to be
-	   able to close the interface even if hw_unavailable is set
-	   (e.g. as we're released after a PC Card removal) */
-	spin_lock_irq(&priv->lock);
+	switch (priv->firmware_type) {
+	case FIRMWARE_TYPE_AGERE: /* Agere style WEP */
+		if (priv->wep_on) {
+			err = hermes_write_wordrec(hw, USER_BAP,
+						   HERMES_RID_CNFTXKEY_AGERE,
+						   priv->tx_key);
+			if (err)
+				return err;
+			
+			err = HERMES_WRITE_RECORD(hw, USER_BAP,
+						  HERMES_RID_CNFWEPKEYS_AGERE,
+						  &priv->keys);
+			if (err)
+				return err;
+		}
+		err = hermes_write_wordrec(hw, USER_BAP,
+					   HERMES_RID_CNFWEPENABLED_AGERE,
+					   priv->wep_on);
+		if (err)
+			return err;
+		break;
 
-	priv->open = 0;
+	case FIRMWARE_TYPE_INTERSIL: /* Intersil style WEP */
+	case FIRMWARE_TYPE_SYMBOL: /* Symbol style WEP */
+		master_wep_flag = 0;		/* Off */
+		if (priv->wep_on) {
+			int keylen;
+			int i;
 
-	err = __orinoco_down(dev);
+			/* Fudge around firmware weirdness */
+			keylen = le16_to_cpu(priv->keys[priv->tx_key].len);
+			
+			/* Write all 4 keys */
+			for(i = 0; i < ORINOCO_MAX_KEYS; i++) {
+/*  				int keylen = le16_to_cpu(priv->keys[i].len); */
+				
+				if (keylen > LARGE_KEY_SIZE) {
+					printk(KERN_ERR "%s: BUG: Key %d has oversize length %d.\n",
+					       priv->ndev->name, i, keylen);
+					return -E2BIG;
+				}
 
-	spin_unlock_irq(&priv->lock);
+				err = hermes_write_ltv(hw, USER_BAP,
+						       HERMES_RID_CNFDEFAULTKEY0 + i,
+						       HERMES_BYTES_TO_RECLEN(keylen),
+						       priv->keys[i].data);
+				if (err)
+					return err;
+			}
 
-	return err;
+			/* Write the index of the key used in transmission */
+			err = hermes_write_wordrec(hw, USER_BAP,
+						   HERMES_RID_CNFWEPDEFAULTKEYID,
+						   priv->tx_key);
+			if (err)
+				return err;
+			
+			if (priv->wep_restrict) {
+				auth_flag = 2;
+				master_wep_flag = 3;
+			} else {
+				/* Authentication is where Intersil and Symbol
+				 * firmware differ... */
+				auth_flag = 1;
+				if (priv->firmware_type == FIRMWARE_TYPE_SYMBOL)
+					master_wep_flag = 3; /* Symbol */ 
+				else 
+					master_wep_flag = 1; /* Intersil */
+			}
+
+
+			err = hermes_write_wordrec(hw, USER_BAP,
+						   HERMES_RID_CNFAUTHENTICATION,
+						   auth_flag);
+			if (err)
+				return err;
+		}
+
+		/* Master WEP setting : on/off */
+		err = hermes_write_wordrec(hw, USER_BAP,
+					   HERMES_RID_CNFWEPFLAGS_INTERSIL,
+					   master_wep_flag);
+		if (err)
+			return err;	
+
+		break;
+
+	default:
+		if (priv->wep_on) {
+			printk(KERN_ERR "%s: WEP enabled, although not supported!\n",
+			       priv->ndev->name);
+			return -EINVAL;
+		}
+	}
+
+	return 0;
 }
 
 static int __orinoco_program_rids(struct net_device *dev)
@@ -733,14 +1548,17 @@
 	err = hermes_write_ltv(hw, USER_BAP, HERMES_RID_CNFOWNMACADDR,
 			       HERMES_BYTES_TO_RECLEN(ETH_ALEN), dev->dev_addr);
 	if (err) {
-		printk(KERN_ERR "%s: Error %d setting MAC address\n", dev->name, err);
+		printk(KERN_ERR "%s: Error %d setting MAC address\n",
+		       dev->name, err);
 		return err;
 	}
 
 	/* Set up the link mode */
-	err = hermes_write_wordrec(hw, USER_BAP, HERMES_RID_CNFPORTTYPE, priv->port_type);
+	err = hermes_write_wordrec(hw, USER_BAP, HERMES_RID_CNFPORTTYPE,
+				   priv->port_type);
 	if (err) {
-		printk(KERN_ERR "%s: Error %d setting port type\n", dev->name, err);
+		printk(KERN_ERR "%s: Error %d setting port type\n",
+		       dev->name, err);
 		return err;
 	}
 	/* Set the channel/frequency */
@@ -749,14 +1567,17 @@
 		if (priv->createibss)
 			priv->channel = 10;
 	}
-	err = hermes_write_wordrec(hw, USER_BAP, HERMES_RID_CNFOWNCHANNEL, priv->channel);
+	err = hermes_write_wordrec(hw, USER_BAP, HERMES_RID_CNFOWNCHANNEL,
+				   priv->channel);
 	if (err) {
-		printk(KERN_ERR "%s: Error %d setting channel\n", dev->name, err);
+		printk(KERN_ERR "%s: Error %d setting channel\n",
+		       dev->name, err);
 		return err;
 	}
 
 	if (priv->has_ibss) {
-		err = hermes_write_wordrec(hw, USER_BAP, HERMES_RID_CNFCREATEIBSS,
+		err = hermes_write_wordrec(hw, USER_BAP,
+					   HERMES_RID_CNFCREATEIBSS,
 					   priv->createibss);
 		if (err) {
 			printk(KERN_ERR "%s: Error %d setting CREATEIBSS\n", dev->name, err);
@@ -765,8 +1586,8 @@
 
 		if ((strlen(priv->desired_essid) == 0) && (priv->createibss)
 		   && (!priv->has_ibss_any)) {
-			printk(KERN_WARNING "%s: This firmware requires an \
-ESSID in IBSS-Ad-Hoc mode.\n", dev->name);
+			printk(KERN_WARNING "%s: This firmware requires an "
+			       "ESSID in IBSS-Ad-Hoc mode.\n", dev->name);
 			/* With wvlan_cs, in this case, we would crash.
 			 * hopefully, this driver will behave better...
 			 * Jean II */
@@ -781,14 +1602,16 @@
 			       HERMES_BYTES_TO_RECLEN(strlen(priv->desired_essid)+2),
 			       &idbuf);
 	if (err) {
-		printk(KERN_ERR "%s: Error %d setting OWNSSID\n", dev->name, err);
+		printk(KERN_ERR "%s: Error %d setting OWNSSID\n",
+		       dev->name, err);
 		return err;
 	}
 	err = hermes_write_ltv(hw, USER_BAP, HERMES_RID_CNFDESIREDSSID,
 			       HERMES_BYTES_TO_RECLEN(strlen(priv->desired_essid)+2),
 			       &idbuf);
 	if (err) {
-		printk(KERN_ERR "%s: Error %d setting DESIREDSSID\n", dev->name, err);
+		printk(KERN_ERR "%s: Error %d setting DESIREDSSID\n",
+		       dev->name, err);
 		return err;
 	}
 
@@ -799,26 +1622,31 @@
 			       HERMES_BYTES_TO_RECLEN(strlen(priv->nick)+2),
 			       &idbuf);
 	if (err) {
-		printk(KERN_ERR "%s: Error %d setting nickname\n", dev->name, err);
+		printk(KERN_ERR "%s: Error %d setting nickname\n",
+		       dev->name, err);
 		return err;
 	}
 
 	/* Set AP density */
 	if (priv->has_sensitivity) {
-		err = hermes_write_wordrec(hw, USER_BAP, HERMES_RID_CNFSYSTEMSCALE,
+		err = hermes_write_wordrec(hw, USER_BAP,
+					   HERMES_RID_CNFSYSTEMSCALE,
 					   priv->ap_density);
 		if (err) {
 			printk(KERN_WARNING "%s: Error %d setting SYSTEMSCALE.  "
-			       "Disabling sensitivity control\n", dev->name, err);
+			       "Disabling sensitivity control\n",
+			       dev->name, err);
 
 			priv->has_sensitivity = 0;
 		}
 	}
 
 	/* Set RTS threshold */
-	err = hermes_write_wordrec(hw, USER_BAP, HERMES_RID_CNFRTSTHRESHOLD, priv->rts_thresh);
+	err = hermes_write_wordrec(hw, USER_BAP, HERMES_RID_CNFRTSTHRESHOLD,
+				   priv->rts_thresh);
 	if (err) {
-		printk(KERN_ERR "%s: Error %d setting RTS threshold\n", dev->name, err);
+		printk(KERN_ERR "%s: Error %d setting RTS threshold\n",
+		       dev->name, err);
 		return err;
 	}
 
@@ -832,20 +1660,23 @@
 					   HERMES_RID_CNFFRAGMENTATIONTHRESHOLD,
 					   priv->frag_thresh);
 	if (err) {
-		printk(KERN_ERR "%s: Error %d setting framentation\n", dev->name, err);
+		printk(KERN_ERR "%s: Error %d setting fragmentation\n",
+		       dev->name, err);
 		return err;
 	}
 
 	/* Set bitrate */
 	err = __orinoco_hw_set_bitrate(priv);
 	if (err) {
-		printk(KERN_ERR "%s: Error %d setting bitrate\n", dev->name, err);
+		printk(KERN_ERR "%s: Error %d setting bitrate\n",
+		       dev->name, err);
 		return err;
 	}
 
 	/* Set power management */
 	if (priv->has_pm) {
-		err = hermes_write_wordrec(hw, USER_BAP, HERMES_RID_CNFPMENABLED,
+		err = hermes_write_wordrec(hw, USER_BAP,
+					   HERMES_RID_CNFPMENABLED,
 					   priv->pm_on);
 		if (err) {
 			printk(KERN_ERR "%s: Error %d setting up PM\n",
@@ -909,7 +1740,73 @@
 	return 0;
 }
 
-/* xyzzy */
+/* FIXME: return int? */
+static void
+__orinoco_set_multicast_list(struct net_device *dev)
+{
+	struct orinoco_private *priv = netdev_priv(dev);
+	hermes_t *hw = &priv->hw;
+	int err = 0;
+	int promisc, mc_count;
+
+	/* The Hermes doesn't seem to have an allmulti mode, so we go
+	 * into promiscuous mode and let the upper levels deal. */
+	if ( (dev->flags & IFF_PROMISC) || (dev->flags & IFF_ALLMULTI) ||
+	     (dev->mc_count > MAX_MULTICAST(priv)) ) {
+		promisc = 1;
+		mc_count = 0;
+	} else {
+		promisc = 0;
+		mc_count = dev->mc_count;
+	}
+
+	if (promisc != priv->promiscuous) {
+		err = hermes_write_wordrec(hw, USER_BAP,
+					   HERMES_RID_CNFPROMISCUOUSMODE,
+					   promisc);
+		if (err) {
+			printk(KERN_ERR "%s: Error %d setting PROMISCUOUSMODE to 1.\n",
+			       dev->name, err);
+		} else 
+			priv->promiscuous = promisc;
+	}
+
+	if (! promisc && (mc_count || priv->mc_count) ) {
+		struct dev_mc_list *p = dev->mc_list;
+		struct hermes_multicast mclist;
+		int i;
+
+		for (i = 0; i < mc_count; i++) {
+			/* paranoia: is list shorter than mc_count? */
+			BUG_ON(! p);
+			/* paranoia: bad address size in list? */
+			BUG_ON(p->dmi_addrlen != ETH_ALEN);
+			
+			memcpy(mclist.addr[i], p->dmi_addr, ETH_ALEN);
+			p = p->next;
+		}
+		
+		if (p)
+			printk(KERN_WARNING "Multicast list is longer than mc_count\n");
+
+		err = hermes_write_ltv(hw, USER_BAP, HERMES_RID_CNFGROUPADDRESSES,
+				       HERMES_BYTES_TO_RECLEN(priv->mc_count * ETH_ALEN),
+				       &mclist);
+		if (err)
+			printk(KERN_ERR "%s: Error %d setting multicast list.\n",
+			       dev->name, err);
+		else
+			priv->mc_count = mc_count;
+	}
+
+	/* Since we can set the promiscuous flag when it wasn't asked
+	   for, make sure the net_device knows about it. */
+	if (priv->promiscuous)
+		dev->flags |= IFF_PROMISC;
+	else
+		dev->flags &= ~IFF_PROMISC;
+}
+
 static int orinoco_reconfigure(struct net_device *dev)
 {
 	struct orinoco_private *priv = netdev_priv(dev);
@@ -974,7 +1871,7 @@
 	if (err)
 		/* When the hardware becomes available again, whatever
 		 * detects that is responsible for re-initializing
-		 * it. So no need for anything further*/
+		 * it. So no need for anything further */
 		return;
 
 	netif_stop_queue(dev);
@@ -993,8 +1890,8 @@
 	if (priv->hard_reset)
 		err = (*priv->hard_reset)(priv);
 	if (err) {
-		printk(KERN_ERR "%s: orinoco_reset: Error %d performing hard reset\n",
-		       dev->name, err);
+		printk(KERN_ERR "%s: orinoco_reset: Error %d "
+		       "performing  hard reset\n", dev->name, err);
 		/* FIXME: shutdown of some sort */
 		return;
 	}
@@ -1027,409 +1924,22 @@
 }
 
 /********************************************************************/
-/* Internal helper functions                                        */
+/* Interrupt handler                                                */
 /********************************************************************/
 
-static inline void
-set_port_type(struct orinoco_private *priv)
-{
-	switch (priv->iw_mode) {
-	case IW_MODE_INFRA:
-		priv->port_type = 1;
-		priv->createibss = 0;
-		break;
-	case IW_MODE_ADHOC:
-		if (priv->prefer_port3) {
-			priv->port_type = 3;
-			priv->createibss = 0;
-		} else {
-			priv->port_type = priv->ibss_port;
-			priv->createibss = 1;
-		}
-		break;
-	default:
-		printk(KERN_ERR "%s: Invalid priv->iw_mode in set_port_type()\n",
-		       priv->ndev->name);
-	}
-}
-
-/* Does the frame have a SNAP header indicating it should be
- * de-encapsulated to Ethernet-II? */
-static inline int
-is_ethersnap(struct header_struct *hdr)
-{
-	/* We de-encapsulate all packets which, a) have SNAP headers
-	 * (i.e. SSAP=DSAP=0xaa and CTRL=0x3 in the 802.2 LLC header
-	 * and where b) the OUI of the SNAP header is 00:00:00 or
-	 * 00:00:f8 - we need both because different APs appear to use
-	 * different OUIs for some reason */
-	return (memcmp(&hdr->dsap, &encaps_hdr, 5) == 0)
-		&& ( (hdr->oui[2] == 0x00) || (hdr->oui[2] == 0xf8) );
-}
-
-static void
-orinoco_set_multicast_list(struct net_device *dev)
-{
-	struct orinoco_private *priv = netdev_priv(dev);
-	unsigned long flags;
-
-	if (orinoco_lock(priv, &flags) != 0) {
-		printk(KERN_DEBUG "%s: orinoco_set_multicast_list() "
-		       "called when hw_unavailable\n", dev->name);
-		return;
-	}
-
-	__orinoco_set_multicast_list(dev);
-	orinoco_unlock(priv, &flags);
-}
-
-/********************************************************************/
-/* Hardware control functions                                       */
-/********************************************************************/
-
-
-static int __orinoco_hw_set_bitrate(struct orinoco_private *priv)
-{
-	hermes_t *hw = &priv->hw;
-	int err = 0;
-
-	if (priv->bitratemode >= BITRATE_TABLE_SIZE) {
-		printk(KERN_ERR "%s: BUG: Invalid bitrate mode %d\n",
-		       priv->ndev->name, priv->bitratemode);
-		return -EINVAL;
-	}
-
-	switch (priv->firmware_type) {
-	case FIRMWARE_TYPE_AGERE:
-		err = hermes_write_wordrec(hw, USER_BAP,
-					   HERMES_RID_CNFTXRATECONTROL,
-					   bitrate_table[priv->bitratemode].agere_txratectrl);
-		break;
-	case FIRMWARE_TYPE_INTERSIL:
-	case FIRMWARE_TYPE_SYMBOL:
-		err = hermes_write_wordrec(hw, USER_BAP,
-					   HERMES_RID_CNFTXRATECONTROL,
-					   bitrate_table[priv->bitratemode].intersil_txratectrl);
-		break;
-	default:
-		BUG();
-	}
-
-	return err;
-}
-
-
-static int __orinoco_hw_setup_wep(struct orinoco_private *priv)
-{
-	hermes_t *hw = &priv->hw;
-	int err = 0;
-	int	master_wep_flag;
-	int	auth_flag;
-
-	switch (priv->firmware_type) {
-	case FIRMWARE_TYPE_AGERE: /* Agere style WEP */
-		if (priv->wep_on) {
-			err = hermes_write_wordrec(hw, USER_BAP,
-						   HERMES_RID_CNFTXKEY_AGERE,
-						   priv->tx_key);
-			if (err)
-				return err;
-			
-			err = HERMES_WRITE_RECORD(hw, USER_BAP,
-						  HERMES_RID_CNFWEPKEYS_AGERE,
-						  &priv->keys);
-			if (err)
-				return err;
-		}
-		err = hermes_write_wordrec(hw, USER_BAP,
-					   HERMES_RID_CNFWEPENABLED_AGERE,
-					   priv->wep_on);
-		if (err)
-			return err;
-		break;
-
-	case FIRMWARE_TYPE_INTERSIL: /* Intersil style WEP */
-	case FIRMWARE_TYPE_SYMBOL: /* Symbol style WEP */
-		master_wep_flag = 0;		/* Off */
-		if (priv->wep_on) {
-			int keylen;
-			int i;
-
-			/* Fudge around firmware weirdness */
-			keylen = le16_to_cpu(priv->keys[priv->tx_key].len);
-			
-			/* Write all 4 keys */
-			for(i = 0; i < ORINOCO_MAX_KEYS; i++) {
-/*  				int keylen = le16_to_cpu(priv->keys[i].len); */
-				
-				if (keylen > LARGE_KEY_SIZE) {
-					printk(KERN_ERR "%s: BUG: Key %d has oversize length %d.\n",
-					       priv->ndev->name, i, keylen);
-					return -E2BIG;
-				}
-
-				err = hermes_write_ltv(hw, USER_BAP,
-						       HERMES_RID_CNFDEFAULTKEY0 + i,
-						       HERMES_BYTES_TO_RECLEN(keylen),
-						       priv->keys[i].data);
-				if (err)
-					return err;
-			}
-
-			/* Write the index of the key used in transmission */
-			err = hermes_write_wordrec(hw, USER_BAP, HERMES_RID_CNFWEPDEFAULTKEYID,
-						   priv->tx_key);
-			if (err)
-				return err;
-			
-			if (priv->wep_restrict) {
-				auth_flag = 2;
-				master_wep_flag = 3;
-			} else {
-				/* Authentication is where Intersil and Symbol
-				 * firmware differ... */
-				auth_flag = 1;
-				if (priv->firmware_type == FIRMWARE_TYPE_SYMBOL)
-					master_wep_flag = 3; /* Symbol */ 
-				else 
-					master_wep_flag = 1; /* Intersil */
-			}
-
-
-			err = hermes_write_wordrec(hw, USER_BAP,
-						   HERMES_RID_CNFAUTHENTICATION, auth_flag);
-			if (err)
-				return err;
-		}
-		
-		/* Master WEP setting : on/off */
-		err = hermes_write_wordrec(hw, USER_BAP,
-					   HERMES_RID_CNFWEPFLAGS_INTERSIL,
-					   master_wep_flag);
-		if (err)
-			return err;	
-
-		break;
-
-	default:
-		if (priv->wep_on) {
-			printk(KERN_ERR "%s: WEP enabled, although not supported!\n",
-			       priv->ndev->name);
-			return -EINVAL;
-		}
-	}
-
-	return 0;
-}
-
-static int orinoco_hw_get_bssid(struct orinoco_private *priv,
-				char buf[ETH_ALEN])
-{
-	hermes_t *hw = &priv->hw;
-	int err = 0;
-	unsigned long flags;
-
-	err = orinoco_lock(priv, &flags);
-	if (err)
-		return err;
-
-	err = hermes_read_ltv(hw, USER_BAP, HERMES_RID_CURRENTBSSID,
-			      ETH_ALEN, NULL, buf);
-
-	orinoco_unlock(priv, &flags);
-
-	return err;
-}
-
-static int orinoco_hw_get_essid(struct orinoco_private *priv, int *active,
-				char buf[IW_ESSID_MAX_SIZE+1])
-{
-	hermes_t *hw = &priv->hw;
-	int err = 0;
-	struct hermes_idstring essidbuf;
-	char *p = (char *)(&essidbuf.val);
-	int len;
-	unsigned long flags;
-
-	err = orinoco_lock(priv, &flags);
-	if (err)
-		return err;
-
-	if (strlen(priv->desired_essid) > 0) {
-		/* We read the desired SSID from the hardware rather
-		   than from priv->desired_essid, just in case the
-		   firmware is allowed to change it on us. I'm not
-		   sure about this */
-		/* My guess is that the OWNSSID should always be whatever
-		 * we set to the card, whereas CURRENT_SSID is the one that
-		 * may change... - Jean II */
-		u16 rid;
-
-		*active = 1;
-
-		rid = (priv->port_type == 3) ? HERMES_RID_CNFOWNSSID :
-			HERMES_RID_CNFDESIREDSSID;
-		
-		err = hermes_read_ltv(hw, USER_BAP, rid, sizeof(essidbuf),
-				      NULL, &essidbuf);
-		if (err)
-			goto fail_unlock;
-	} else {
-		*active = 0;
-
-		err = hermes_read_ltv(hw, USER_BAP, HERMES_RID_CURRENTSSID,
-				      sizeof(essidbuf), NULL, &essidbuf);
-		if (err)
-			goto fail_unlock;
-	}
-
-	len = le16_to_cpu(essidbuf.len);
-
-	memset(buf, 0, IW_ESSID_MAX_SIZE+1);
-	memcpy(buf, p, len);
-	buf[len] = '\0';
-
- fail_unlock:
-	orinoco_unlock(priv, &flags);
-
-	return err;       
-}
-
-static long orinoco_hw_get_freq(struct orinoco_private *priv)
-{
-	
-	hermes_t *hw = &priv->hw;
-	int err = 0;
-	u16 channel;
-	long freq = 0;
-	unsigned long flags;
-
-	err = orinoco_lock(priv, &flags);
-	if (err)
-		return err;
-	
-	err = hermes_read_wordrec(hw, USER_BAP, HERMES_RID_CURRENTCHANNEL, &channel);
-	if (err)
-		goto out;
-
-	/* Intersil firmware 1.3.5 returns 0 when the interface is down */
-	if (channel == 0) {
-		err = -EBUSY;
-		goto out;
-	}
-
-	if ( (channel < 1) || (channel > NUM_CHANNELS) ) {
-		printk(KERN_WARNING "%s: Channel out of range (%d)!\n",
-		       priv->ndev->name, channel);
-		err = -EBUSY;
-		goto out;
-
-	}
-	freq = channel_frequency[channel-1] * 100000;
-
- out:
-	orinoco_unlock(priv, &flags);
-
-	if (err > 0)
-		err = -EBUSY;
-	return err ? err : freq;
-}
-
-static int orinoco_hw_get_bitratelist(struct orinoco_private *priv,
-				      int *numrates, s32 *rates, int max)
+static void __orinoco_ev_tick(struct net_device *dev, hermes_t *hw)
 {
-	hermes_t *hw = &priv->hw;
-	struct hermes_idstring list;
-	unsigned char *p = (unsigned char *)&list.val;
-	int err = 0;
-	int num;
-	int i;
-	unsigned long flags;
-
-	err = orinoco_lock(priv, &flags);
-	if (err)
-		return err;
-
-	err = hermes_read_ltv(hw, USER_BAP, HERMES_RID_SUPPORTEDDATARATES,
-			      sizeof(list), NULL, &list);
-	orinoco_unlock(priv, &flags);
-
-	if (err)
-		return err;
-	
-	num = le16_to_cpu(list.len);
-	*numrates = num;
-	num = min(num, max);
-
-	for (i = 0; i < num; i++) {
-		rates[i] = (p[i] & 0x7f) * 500000; /* convert to bps */
-	}
-
-	return 0;
+	printk(KERN_DEBUG "%s: TICK\n", dev->name);
 }
 
-#if 0
-static void show_rx_frame(struct orinoco_rxframe_hdr *frame)
+static void __orinoco_ev_wterr(struct net_device *dev, hermes_t *hw)
 {
-	printk(KERN_DEBUG "RX descriptor:\n");
-	printk(KERN_DEBUG "  status      = 0x%04x\n", frame->desc.status);
-	printk(KERN_DEBUG "  time        = 0x%08x\n", frame->desc.time);
-	printk(KERN_DEBUG "  silence     = 0x%02x\n", frame->desc.silence);
-	printk(KERN_DEBUG "  signal      = 0x%02x\n", frame->desc.signal);
-	printk(KERN_DEBUG "  rate        = 0x%02x\n", frame->desc.rate);
-	printk(KERN_DEBUG "  rxflow      = 0x%02x\n", frame->desc.rxflow);
-	printk(KERN_DEBUG "  reserved    = 0x%08x\n", frame->desc.reserved);
-
-	printk(KERN_DEBUG "IEEE 802.11 header:\n");
-	printk(KERN_DEBUG "  frame_ctl   = 0x%04x\n",
-	       frame->p80211.frame_ctl);
-	printk(KERN_DEBUG "  duration_id = 0x%04x\n",
-	       frame->p80211.duration_id);
-	printk(KERN_DEBUG "  addr1       = %02x:%02x:%02x:%02x:%02x:%02x\n",
-	       frame->p80211.addr1[0], frame->p80211.addr1[1],
-	       frame->p80211.addr1[2], frame->p80211.addr1[3],
-	       frame->p80211.addr1[4], frame->p80211.addr1[5]);
-	printk(KERN_DEBUG "  addr2       = %02x:%02x:%02x:%02x:%02x:%02x\n",
-	       frame->p80211.addr2[0], frame->p80211.addr2[1],
-	       frame->p80211.addr2[2], frame->p80211.addr2[3],
-	       frame->p80211.addr2[4], frame->p80211.addr2[5]);
-	printk(KERN_DEBUG "  addr3       = %02x:%02x:%02x:%02x:%02x:%02x\n",
-	       frame->p80211.addr3[0], frame->p80211.addr3[1],
-	       frame->p80211.addr3[2], frame->p80211.addr3[3],
-	       frame->p80211.addr3[4], frame->p80211.addr3[5]);
-	printk(KERN_DEBUG "  seq_ctl     = 0x%04x\n",
-	       frame->p80211.seq_ctl);
-	printk(KERN_DEBUG "  addr4       = %02x:%02x:%02x:%02x:%02x:%02x\n",
-	       frame->p80211.addr4[0], frame->p80211.addr4[1],
-	       frame->p80211.addr4[2], frame->p80211.addr4[3],
-	       frame->p80211.addr4[4], frame->p80211.addr4[5]);
-	printk(KERN_DEBUG "  data_len    = 0x%04x\n",
-	       frame->p80211.data_len);
-
-	printk(KERN_DEBUG "IEEE 802.3 header:\n");
-	printk(KERN_DEBUG "  dest        = %02x:%02x:%02x:%02x:%02x:%02x\n",
-	       frame->p8023.h_dest[0], frame->p8023.h_dest[1],
-	       frame->p8023.h_dest[2], frame->p8023.h_dest[3],
-	       frame->p8023.h_dest[4], frame->p8023.h_dest[5]);
-	printk(KERN_DEBUG "  src         = %02x:%02x:%02x:%02x:%02x:%02x\n",
-	       frame->p8023.h_source[0], frame->p8023.h_source[1],
-	       frame->p8023.h_source[2], frame->p8023.h_source[3],
-	       frame->p8023.h_source[4], frame->p8023.h_source[5]);
-	printk(KERN_DEBUG "  len         = 0x%04x\n", frame->p8023.h_proto);
-
-	printk(KERN_DEBUG "IEEE 802.2 LLC/SNAP header:\n");
-	printk(KERN_DEBUG "  DSAP        = 0x%02x\n", frame->p8022.dsap);
-	printk(KERN_DEBUG "  SSAP        = 0x%02x\n", frame->p8022.ssap);
-	printk(KERN_DEBUG "  ctrl        = 0x%02x\n", frame->p8022.ctrl);
-	printk(KERN_DEBUG "  OUI         = %02x:%02x:%02x\n",
-	       frame->p8022.oui[0], frame->p8022.oui[1], frame->p8022.oui[2]);
-	printk(KERN_DEBUG "  ethertype  = 0x%04x\n", frame->ethertype);
+	/* This seems to happen a fair bit under load, but ignoring it
+	   seems to work fine...*/
+	printk(KERN_DEBUG "%s: MAC controller error (WTERR). Ignoring.\n",
+	       dev->name);
 }
-#endif /* 0 */
 
-/*
- * Interrupt handler
- */
 irqreturn_t orinoco_interrupt(int irq, void *dev_id, struct pt_regs *regs)
 {
 	struct net_device *dev = (struct net_device *)dev_id;
@@ -1440,7 +1950,8 @@
 	/* These are used to detect a runaway interrupt situation */
 	/* If we get more than MAX_IRQLOOPS_PER_JIFFY iterations in a jiffy,
 	 * we panic and shut down the hardware */
-	static int last_irq_jiffy = 0; /* jiffies value the last time we were called */
+	static int last_irq_jiffy = 0; /* jiffies value the last time
+					* we were called */
 	static int loops_this_jiffy = 0;
 	unsigned long flags;
 
@@ -1504,368 +2015,9 @@
 	return IRQ_HANDLED;
 }
 
-static void __orinoco_ev_tick(struct net_device *dev, hermes_t *hw)
-{
-	printk(KERN_DEBUG "%s: TICK\n", dev->name);
-}
-
-static void __orinoco_ev_wterr(struct net_device *dev, hermes_t *hw)
-{
-	/* This seems to happen a fair bit under load, but ignoring it
-	   seems to work fine...*/
-	printk(KERN_DEBUG "%s: MAC controller error (WTERR). Ignoring.\n",
-	       dev->name);
-}
-
-static void __orinoco_ev_infdrop(struct net_device *dev, hermes_t *hw)
-{
-	if (net_ratelimit())
-		printk(KERN_WARNING "%s: Information frame lost.\n", dev->name);
-}
-
-static void print_linkstatus(struct net_device *dev, u16 status)
-{
-	char * s;
-
-	if (suppress_linkstatus)
-		return;
-
-	switch (status) {
-	case HERMES_LINKSTATUS_NOT_CONNECTED:
-		s = "Not Connected";
-		break;
-	case HERMES_LINKSTATUS_CONNECTED:
-		s = "Connected";
-		break;
-	case HERMES_LINKSTATUS_DISCONNECTED:
-		s = "Disconnected";
-		break;
-	case HERMES_LINKSTATUS_AP_CHANGE:
-		s = "AP Changed";
-		break;
-	case HERMES_LINKSTATUS_AP_OUT_OF_RANGE:
-		s = "AP Out of Range";
-		break;
-	case HERMES_LINKSTATUS_AP_IN_RANGE:
-		s = "AP In Range";
-		break;
-	case HERMES_LINKSTATUS_ASSOC_FAILED:
-		s = "Association Failed";
-		break;
-	default:
-		s = "UNKNOWN";
-	}
-	
-	printk(KERN_INFO "%s: New link status: %s (%04x)\n",
-	       dev->name, s, status);
-}
-
-static void __orinoco_ev_info(struct net_device *dev, hermes_t *hw)
-{
-	struct orinoco_private *priv = netdev_priv(dev);
-	u16 infofid;
-	struct {
-		u16 len;
-		u16 type;
-	} __attribute__ ((packed)) info;
-	int len, type;
-	int err;
-
-	/* This is an answer to an INQUIRE command that we did earlier,
-	 * or an information "event" generated by the card
-	 * The controller return to us a pseudo frame containing
-	 * the information in question - Jean II */
-	infofid = hermes_read_regn(hw, INFOFID);
-
-	/* Read the info frame header - don't try too hard */
-	err = hermes_bap_pread(hw, IRQ_BAP, &info, sizeof(info),
-			       infofid, 0);
-	if (err) {
-		printk(KERN_ERR "%s: error %d reading info frame. "
-		       "Frame dropped.\n", dev->name, err);
-		return;
-	}
-	
-	len = HERMES_RECLEN_TO_BYTES(le16_to_cpu(info.len));
-	type = le16_to_cpu(info.type);
-
-	switch (type) {
-	case HERMES_INQ_TALLIES: {
-		struct hermes_tallies_frame tallies;
-		struct iw_statistics *wstats = &priv->wstats;
-		
-		if (len > sizeof(tallies)) {
-			printk(KERN_WARNING "%s: Tallies frame too long (%d bytes)\n",
-			       dev->name, len);
-			len = sizeof(tallies);
-		}
-		
-		/* Read directly the data (no seek) */
-		hermes_read_words(hw, HERMES_DATA1, (void *) &tallies,
-				  len / 2); /* FIXME: blech! */
-		
-		/* Increment our various counters */
-		/* wstats->discard.nwid - no wrong BSSID stuff */
-		wstats->discard.code +=
-			le16_to_cpu(tallies.RxWEPUndecryptable);
-		if (len == sizeof(tallies))  
-			wstats->discard.code +=
-				le16_to_cpu(tallies.RxDiscards_WEPICVError) +
-				le16_to_cpu(tallies.RxDiscards_WEPExcluded);
-		wstats->discard.misc +=
-			le16_to_cpu(tallies.TxDiscardsWrongSA);
-#if WIRELESS_EXT > 11
-		wstats->discard.fragment +=
-			le16_to_cpu(tallies.RxMsgInBadMsgFragments);
-		wstats->discard.retries +=
-			le16_to_cpu(tallies.TxRetryLimitExceeded);
-		/* wstats->miss.beacon - no match */
-#endif /* WIRELESS_EXT > 11 */
-	}
-	break;
-	case HERMES_INQ_LINKSTATUS: {
-		struct hermes_linkstatus linkstatus;
-		u16 newstatus;
-		
-		if (len != sizeof(linkstatus)) {
-			printk(KERN_WARNING "%s: Unexpected size for linkstatus frame (%d bytes)\n",
-			       dev->name, len);
-			break;
-		}
-
-		hermes_read_words(hw, HERMES_DATA1, (void *) &linkstatus,
-				  len / 2);
-		newstatus = le16_to_cpu(linkstatus.linkstatus);
-
-		if ( (newstatus == HERMES_LINKSTATUS_CONNECTED)
-		     || (newstatus == HERMES_LINKSTATUS_AP_CHANGE)
-		     || (newstatus == HERMES_LINKSTATUS_AP_IN_RANGE) )
-			priv->connected = 1;
-		else if ( (newstatus == HERMES_LINKSTATUS_NOT_CONNECTED)
-			  || (newstatus == HERMES_LINKSTATUS_DISCONNECTED)
-			  || (newstatus == HERMES_LINKSTATUS_AP_OUT_OF_RANGE)
-			  || (newstatus == HERMES_LINKSTATUS_ASSOC_FAILED) )
-			priv->connected = 0;
-
-		if (newstatus != priv->last_linkstatus)
-			print_linkstatus(dev, newstatus);
-
-		priv->last_linkstatus = newstatus;
-	}
-	break;
-	default:
-		printk(KERN_DEBUG "%s: Unknown information frame received (type %04x).\n",
-		      dev->name, type);
-		/* We don't actually do anything about it */
-		break;
-	}
-}
-
-static void __orinoco_ev_rx(struct net_device *dev, hermes_t *hw)
-{
-	struct orinoco_private *priv = netdev_priv(dev);
-	struct net_device_stats *stats = &priv->stats;
-	struct iw_statistics *wstats = &priv->wstats;
-	struct sk_buff *skb = NULL;
-	u16 rxfid, status;
-	int length, data_len, data_off;
-	char *p;
-	struct hermes_rx_descriptor desc;
-	struct header_struct hdr;
-	struct ethhdr *eh;
-	int err;
-
-	rxfid = hermes_read_regn(hw, RXFID);
-
-	err = hermes_bap_pread(hw, IRQ_BAP, &desc, sizeof(desc),
-			       rxfid, 0);
-	if (err) {
-		printk(KERN_ERR "%s: error %d reading Rx descriptor. "
-		       "Frame dropped.\n", dev->name, err);
-		stats->rx_errors++;
-		goto drop;
-	}
-
-	status = le16_to_cpu(desc.status);
-	
-	if (status & HERMES_RXSTAT_ERR) {
-		if (status & HERMES_RXSTAT_UNDECRYPTABLE) {
-			wstats->discard.code++;
-			DEBUG(1, "%s: Undecryptable frame on Rx. Frame dropped.\n",
-			       dev->name);
-		} else {
-			stats->rx_crc_errors++;
-			DEBUG(1, "%s: Bad CRC on Rx. Frame dropped.\n", dev->name);
-		}
-		stats->rx_errors++;
-		goto drop;
-	}
-
-	/* For now we ignore the 802.11 header completely, assuming
-           that the card's firmware has handled anything vital */
-
-	err = hermes_bap_pread(hw, IRQ_BAP, &hdr, sizeof(hdr),
-			       rxfid, HERMES_802_3_OFFSET);
-	if (err) {
-		printk(KERN_ERR "%s: error %d reading frame header. "
-		       "Frame dropped.\n", dev->name, err);
-		stats->rx_errors++;
-		goto drop;
-	}
-
-	length = ntohs(hdr.len);
-	
-	/* Sanity checks */
-	if (length < 3) { /* No for even an 802.2 LLC header */
-		/* At least on Symbol firmware with PCF we get quite a
-                   lot of these legitimately - Poll frames with no
-                   data. */
-		stats->rx_dropped++;
-		goto drop;
-	}
-	if (length > IEEE802_11_DATA_LEN) {
-		printk(KERN_WARNING "%s: Oversized frame received (%d bytes)\n",
-		       dev->name, length);
-		stats->rx_length_errors++;
-		stats->rx_errors++;
-		goto drop;
-	}
-
-	/* We need space for the packet data itself, plus an ethernet
-	   header, plus 2 bytes so we can align the IP header on a
-	   32bit boundary, plus 1 byte so we can read in odd length
-	   packets from the card, which has an IO granularity of 16
-	   bits */  
-	skb = dev_alloc_skb(length+ETH_HLEN+2+1);
-	if (!skb) {
-		printk(KERN_WARNING "%s: Can't allocate skb for Rx\n",
-		       dev->name);
-		goto drop;
-	}
-
-	skb_reserve(skb, 2); /* This way the IP header is aligned */
-
-	/* Handle decapsulation
-	 * In most cases, the firmware tell us about SNAP frames.
-	 * For some reason, the SNAP frames sent by LinkSys APs
-	 * are not properly recognised by most firmwares.
-	 * So, check ourselves */
-	if(((status & HERMES_RXSTAT_MSGTYPE) == HERMES_RXSTAT_1042) ||
-	   ((status & HERMES_RXSTAT_MSGTYPE) == HERMES_RXSTAT_TUNNEL) ||
-	   is_ethersnap(&hdr)) {
-		/* These indicate a SNAP within 802.2 LLC within
-		   802.11 frame which we'll need to de-encapsulate to
-		   the original EthernetII frame. */
-
-		if (length < ENCAPS_OVERHEAD) { /* No room for full LLC+SNAP */
-			stats->rx_length_errors++;
-			goto drop;
-		}
-
-		/* Remove SNAP header, reconstruct EthernetII frame */
-		data_len = length - ENCAPS_OVERHEAD;
-		data_off = HERMES_802_3_OFFSET + sizeof(hdr);
-
-		eh = (struct ethhdr *)skb_put(skb, ETH_HLEN);
-
-		memcpy(eh, &hdr, 2 * ETH_ALEN);
-		eh->h_proto = hdr.ethertype;
-	} else {
-		/* All other cases indicate a genuine 802.3 frame.  No
-		   decapsulation needed.  We just throw the whole
-		   thing in, and hope the protocol layer can deal with
-		   it as 802.3 */
-		data_len = length;
-		data_off = HERMES_802_3_OFFSET;
-		/* FIXME: we re-read from the card data we already read here */
-	}
-
-	p = skb_put(skb, data_len);
-	err = hermes_bap_pread(hw, IRQ_BAP, p, RUP_EVEN(data_len),
-			       rxfid, data_off);
-	if (err) {
-		printk(KERN_ERR "%s: error %d reading frame. "
-		       "Frame dropped.\n", dev->name, err);
-		stats->rx_errors++;
-		goto drop;
-	}
-
-	dev->last_rx = jiffies;
-	skb->dev = dev;
-	skb->protocol = eth_type_trans(skb, dev);
-	skb->ip_summed = CHECKSUM_NONE;
-	
-	/* Process the wireless stats if needed */
-	orinoco_stat_gather(dev, skb, &desc);
-
-	/* Pass the packet to the networking stack */
-	netif_rx(skb);
-	stats->rx_packets++;
-	stats->rx_bytes += length;
-
-	return;
-
- drop:	
-	stats->rx_dropped++;
-
-	if (skb)
-		dev_kfree_skb_irq(skb);
-	return;
-}
-
-static void __orinoco_ev_txexc(struct net_device *dev, hermes_t *hw)
-{
-	struct orinoco_private *priv = netdev_priv(dev);
-	struct net_device_stats *stats = &priv->stats;
-	u16 fid = hermes_read_regn(hw, TXCOMPLFID);
-	struct hermes_tx_descriptor desc;
-	int err = 0;
-
-	if (fid == DUMMY_FID)
-		return; /* Nothing's really happened */
-
-	err = hermes_bap_pread(hw, IRQ_BAP, &desc, sizeof(desc), fid, 0);
-	if (err) {
-		printk(KERN_WARNING "%s: Unable to read descriptor on Tx error "
-		       "(FID=%04X error %d)\n",
-		       dev->name, fid, err);
-	} else {
-		DEBUG(1, "%s: Tx error, status %d\n",
-		      dev->name, le16_to_cpu(desc.status));
-	}
-	
-	stats->tx_errors++;
-
-	hermes_write_regn(hw, TXCOMPLFID, DUMMY_FID);
-}
-
-static void __orinoco_ev_tx(struct net_device *dev, hermes_t *hw)
-{
-	struct orinoco_private *priv = netdev_priv(dev);
-	struct net_device_stats *stats = &priv->stats;
-
-	stats->tx_packets++;
-
-	hermes_write_regn(hw, TXCOMPLFID, DUMMY_FID);
-}
-
-static void __orinoco_ev_alloc(struct net_device *dev, hermes_t *hw)
-{
-	struct orinoco_private *priv = netdev_priv(dev);
-
-	u16 fid = hermes_read_regn(hw, ALLOCFID);
-
-	if (fid != priv->txfid) {
-		if (fid != DUMMY_FID)
-			printk(KERN_WARNING "%s: Allocate event on unexpected fid (%04X)\n",
-			       dev->name, fid);
-		return;
-	} else {
-		netif_wake_queue(dev);
-	}
-
-	hermes_write_regn(hw, ALLOCFID, DUMMY_FID);
-}
+/********************************************************************/
+/* Initialization                                                   */
+/********************************************************************/
 
 struct sta_id {
 	u16 id, variant, major, minor;
@@ -1901,11 +2053,11 @@
 		       dev->name, err);
 		memset(&sta_id, 0, sizeof(sta_id));
 	}
+
 	le16_to_cpus(&sta_id.id);
 	le16_to_cpus(&sta_id.variant);
 	le16_to_cpus(&sta_id.major);
 	le16_to_cpus(&sta_id.minor);
-
 	printk(KERN_DEBUG "%s: Station identity %04x:%04x:%04x:%04x\n",
 	       dev->name, sta_id.id, sta_id.variant,
 	       sta_id.major, sta_id.minor);
@@ -2018,12 +2170,7 @@
 	}
 }
 
-/*
- * struct net_device methods
- */
-
-static int
-orinoco_init(struct net_device *dev)
+static int orinoco_init(struct net_device *dev)
 {
 	struct orinoco_private *priv = netdev_priv(dev);
 	hermes_t *hw = &priv->hw;
@@ -2112,7 +2259,8 @@
 	err = hermes_read_wordrec(hw, USER_BAP, HERMES_RID_CNFRTSTHRESHOLD,
 				  &priv->rts_thresh);
 	if (err) {
-		printk(KERN_ERR "%s: failed to read RTS threshold!\n", dev->name);
+		printk(KERN_ERR "%s: failed to read RTS threshold!\n",
+		       dev->name);
 		goto out;
 	}
 
@@ -2125,7 +2273,8 @@
 		err = hermes_read_wordrec(hw, USER_BAP, HERMES_RID_CNFFRAGMENTATIONTHRESHOLD,
 					  &priv->frag_thresh);
 	if (err) {
-		printk(KERN_ERR "%s: failed to read fragmentation settings!\n", dev->name);
+		printk(KERN_ERR "%s: failed to read fragmentation settings!\n",
+		       dev->name);
 		goto out;
 	}
 
@@ -2153,7 +2302,8 @@
 
 	/* Preamble setup */
 	if (priv->has_preamble) {
-		err = hermes_read_wordrec(hw, USER_BAP, HERMES_RID_CNFPREAMBLE_SYMBOL,
+		err = hermes_read_wordrec(hw, USER_BAP,
+					  HERMES_RID_CNFPREAMBLE_SYMBOL,
 					  &priv->preamble);
 		if (err)
 			goto out;
@@ -2202,357 +2352,204 @@
 	return err;
 }
 
-struct net_device_stats *
-orinoco_get_stats(struct net_device *dev)
+struct net_device *alloc_orinocodev(int sizeof_card,
+				    int (*hard_reset)(struct orinoco_private *))
 {
-	struct orinoco_private *priv = netdev_priv(dev);
-	
-	return &priv->stats;
-}
+	struct net_device *dev;
+	struct orinoco_private *priv;
 
-struct iw_statistics *
-orinoco_get_wireless_stats(struct net_device *dev)
-{
-	struct orinoco_private *priv = netdev_priv(dev);
-	hermes_t *hw = &priv->hw;
-	struct iw_statistics *wstats = &priv->wstats;
-	int err = 0;
-	unsigned long flags;
+	dev = alloc_etherdev(sizeof(struct orinoco_private) + sizeof_card);
+	if (! dev)
+		return NULL;
+	priv = netdev_priv(dev);
+	priv->ndev = dev;
+	if (sizeof_card)
+		priv->card = (void *)((unsigned long)netdev_priv(dev)
+				      + sizeof(struct orinoco_private));
+	else
+		priv->card = NULL;
 
-	if (! netif_device_present(dev)) {
-		printk(KERN_WARNING "%s: get_wireless_stats() called while device not present\n",
-		       dev->name);
-		return NULL; /* FIXME: Can we do better than this? */
-	}
+	/* Setup / override net_device fields */
+	dev->init = orinoco_init;
+	dev->hard_start_xmit = orinoco_xmit;
+	dev->tx_timeout = orinoco_tx_timeout;
+	dev->watchdog_timeo = HZ; /* 1 second timeout */
+	dev->get_stats = orinoco_get_stats;
+	dev->get_wireless_stats = orinoco_get_wireless_stats;
+	dev->do_ioctl = orinoco_ioctl;
+	dev->change_mtu = orinoco_change_mtu;
+	dev->set_multicast_list = orinoco_set_multicast_list;
+	/* we use the default eth_mac_addr for setting the MAC addr */
 
-	err = orinoco_lock(priv, &flags);
-	if (err)
-		return NULL; /* FIXME: Erg, we've been signalled, how
-			      * do we propagate this back up? */
+	/* Set up default callbacks */
+	dev->open = orinoco_open;
+	dev->stop = orinoco_stop;
+	priv->hard_reset = hard_reset;
 
-	if (priv->iw_mode == IW_MODE_ADHOC) {
-		memset(&wstats->qual, 0, sizeof(wstats->qual));
-		/* If a spy address is defined, we report stats of the
-		 * first spy address - Jean II */
-		if (SPY_NUMBER(priv)) {
-			wstats->qual.qual = priv->spy_stat[0].qual;
-			wstats->qual.level = priv->spy_stat[0].level;
-			wstats->qual.noise = priv->spy_stat[0].noise;
-			wstats->qual.updated = priv->spy_stat[0].updated;
-		}
-	} else {
-		struct {
-			u16 qual, signal, noise;
-		} __attribute__ ((packed)) cq;
+	spin_lock_init(&priv->lock);
+	priv->open = 0;
+	priv->hw_unavailable = 1; /* orinoco_init() must clear this
+				   * before anything else touches the
+				   * hardware */
+	INIT_WORK(&priv->reset_work, (void (*)(void *))orinoco_reset, dev);
 
-		err = HERMES_READ_RECORD(hw, USER_BAP,
-					 HERMES_RID_COMMSQUALITY, &cq);
-		
-		wstats->qual.qual = (int)le16_to_cpu(cq.qual);
-		wstats->qual.level = (int)le16_to_cpu(cq.signal) - 0x95;
-		wstats->qual.noise = (int)le16_to_cpu(cq.noise) - 0x95;
-		wstats->qual.updated = 7;
-	}
+	priv->last_linkstatus = 0xffff;
+	priv->connected = 0;
 
-	/* We can't really wait for the tallies inquiry command to
-	 * complete, so we just use the previous results and trigger
-	 * a new tallies inquiry command for next time - Jean II */
-	/* FIXME: We're in user context (I think?), so we should just
-           wait for the tallies to come through */
-	err = hermes_inquire(hw, HERMES_INQ_TALLIES);
-               
-	orinoco_unlock(priv, &flags);
+	return dev;
 
-	if (err)
-		return NULL;
-		
-	return wstats;
 }
 
-static inline void orinoco_spy_gather(struct net_device *dev, u_char *mac,
-				    int level, int noise)
-{
-	struct orinoco_private *priv = netdev_priv(dev);
-	int i;
-
-	/* Gather wireless spy statistics: for each packet, compare the
-	 * source address with out list, and if match, get the stats... */
-	for (i = 0; i < priv->spy_number; i++)
-		if (!memcmp(mac, priv->spy_address[i], ETH_ALEN)) {
-			priv->spy_stat[i].level = level - 0x95;
-			priv->spy_stat[i].noise = noise - 0x95;
-			priv->spy_stat[i].qual = (level > noise) ? (level - noise) : 0;
-			priv->spy_stat[i].updated = 7;
-		}
-}
-
-void
-orinoco_stat_gather(struct net_device *dev,
-		    struct sk_buff *skb,
-		    struct hermes_rx_descriptor *desc)
-{
-	struct orinoco_private *priv = netdev_priv(dev);
-
-	/* Using spy support with lots of Rx packets, like in an
-	 * infrastructure (AP), will really slow down everything, because
-	 * the MAC address must be compared to each entry of the spy list.
-	 * If the user really asks for it (set some address in the
-	 * spy list), we do it, but he will pay the price.
-	 * Note that to get here, you need both WIRELESS_SPY
-	 * compiled in AND some addresses in the list !!!
-	 */
-	/* Note : gcc will optimise the whole section away if
-	 * WIRELESS_SPY is not defined... - Jean II */
-	if (SPY_NUMBER(priv)) {
-		orinoco_spy_gather(dev, skb->mac.raw + ETH_ALEN,
-				   desc->signal, desc->silence);
-	}
-}
+/********************************************************************/
+/* Wireless extensions                                              */
+/********************************************************************/
 
-static int
-orinoco_xmit(struct sk_buff *skb, struct net_device *dev)
+static int orinoco_hw_get_bssid(struct orinoco_private *priv,
+				char buf[ETH_ALEN])
 {
-	struct orinoco_private *priv = netdev_priv(dev);
-	struct net_device_stats *stats = &priv->stats;
 	hermes_t *hw = &priv->hw;
 	int err = 0;
-	u16 txfid = priv->txfid;
-	char *p;
-	struct ethhdr *eh;
-	int len, data_len, data_off;
-	struct hermes_tx_descriptor desc;
 	unsigned long flags;
 
-	TRACE_ENTER(dev->name);
+	err = orinoco_lock(priv, &flags);
+	if (err)
+		return err;
 
-	if (! netif_running(dev)) {
-		printk(KERN_ERR "%s: Tx on stopped device!\n",
-		       dev->name);
-		TRACE_EXIT(dev->name);
-		return 1;
-	}
-	
-	if (netif_queue_stopped(dev)) {
-		printk(KERN_DEBUG "%s: Tx while transmitter busy!\n", 
-		       dev->name);
-		TRACE_EXIT(dev->name);
-		return 1;
-	}
-	
-	if (orinoco_lock(priv, &flags) != 0) {
-		printk(KERN_ERR "%s: orinoco_xmit() called while hw_unavailable\n",
-		       dev->name);
-		TRACE_EXIT(dev->name);
-/*  		BUG(); */
-		return 1;
-	}
+	err = hermes_read_ltv(hw, USER_BAP, HERMES_RID_CURRENTBSSID,
+			      ETH_ALEN, NULL, buf);
 
-	if (! priv->connected) {
-		/* Oops, the firmware hasn't established a connection,
-                   silently drop the packet (this seems to be the
-                   safest approach). */
-		stats->tx_errors++;
-		orinoco_unlock(priv, &flags);
-		dev_kfree_skb(skb);
-		TRACE_EXIT(dev->name);
-		return 0;
-	}
+	orinoco_unlock(priv, &flags);
 
-	/* Length of the packet body */
-	/* FIXME: what if the skb is smaller than this? */
-	len = max_t(int,skb->len - ETH_HLEN, ETH_ZLEN - ETH_HLEN);
+	return err;
+}
 
-	eh = (struct ethhdr *)skb->data;
+static int orinoco_hw_get_essid(struct orinoco_private *priv, int *active,
+				char buf[IW_ESSID_MAX_SIZE+1])
+{
+	hermes_t *hw = &priv->hw;
+	int err = 0;
+	struct hermes_idstring essidbuf;
+	char *p = (char *)(&essidbuf.val);
+	int len;
+	unsigned long flags;
 
-	memset(&desc, 0, sizeof(desc));
- 	desc.tx_control = cpu_to_le16(HERMES_TXCTRL_TX_OK | HERMES_TXCTRL_TX_EX);
-	err = hermes_bap_pwrite(hw, USER_BAP, &desc, sizeof(desc), txfid, 0);
-	if (err) {
-		printk(KERN_ERR "%s: Error %d writing Tx descriptor to BAP\n",
-		       dev->name, err);
-		stats->tx_errors++;
-		goto fail;
-	}
+	err = orinoco_lock(priv, &flags);
+	if (err)
+		return err;
 
-	/* Clear the 802.11 header and data length fields - some
-	 * firmwares (e.g. Lucent/Agere 8.xx) appear to get confused
-	 * if this isn't done. */
-	hermes_clear_words(hw, HERMES_DATA0,
-			   HERMES_802_3_OFFSET - HERMES_802_11_OFFSET);
+	if (strlen(priv->desired_essid) > 0) {
+		/* We read the desired SSID from the hardware rather
+		   than from priv->desired_essid, just in case the
+		   firmware is allowed to change it on us. I'm not
+		   sure about this */
+		/* My guess is that the OWNSSID should always be whatever
+		 * we set to the card, whereas CURRENT_SSID is the one that
+		 * may change... - Jean II */
+		u16 rid;
 
-	/* Encapsulate Ethernet-II frames */
-	if (ntohs(eh->h_proto) > 1500) { /* Ethernet-II frame */
-		struct header_struct hdr;
-		data_len = len;
-		data_off = HERMES_802_3_OFFSET + sizeof(hdr);
-		p = skb->data + ETH_HLEN;
+		*active = 1;
 
-		/* 802.3 header */
-		memcpy(hdr.dest, eh->h_dest, ETH_ALEN);
-		memcpy(hdr.src, eh->h_source, ETH_ALEN);
-		hdr.len = htons(data_len + ENCAPS_OVERHEAD);
+		rid = (priv->port_type == 3) ? HERMES_RID_CNFOWNSSID :
+			HERMES_RID_CNFDESIREDSSID;
 		
-		/* 802.2 header */
-		memcpy(&hdr.dsap, &encaps_hdr, sizeof(encaps_hdr));
-			
-		hdr.ethertype = eh->h_proto;
-		err  = hermes_bap_pwrite(hw, USER_BAP, &hdr, sizeof(hdr),
-					 txfid, HERMES_802_3_OFFSET);
-		if (err) {
-			printk(KERN_ERR "%s: Error %d writing packet header to BAP\n",
-			       dev->name, err);
-			stats->tx_errors++;
-			goto fail;
-		}
-	} else { /* IEEE 802.3 frame */
-		data_len = len + ETH_HLEN;
-		data_off = HERMES_802_3_OFFSET;
-		p = skb->data;
-	}
+		err = hermes_read_ltv(hw, USER_BAP, rid, sizeof(essidbuf),
+				      NULL, &essidbuf);
+		if (err)
+			goto fail_unlock;
+	} else {
+		*active = 0;
 
-	/* Round up for odd length packets */
-	err = hermes_bap_pwrite(hw, USER_BAP, p, RUP_EVEN(data_len), txfid, data_off);
-	if (err) {
-		printk(KERN_ERR "%s: Error %d writing packet to BAP\n",
-		       dev->name, err);
-		stats->tx_errors++;
-		goto fail;
+		err = hermes_read_ltv(hw, USER_BAP, HERMES_RID_CURRENTSSID,
+				      sizeof(essidbuf), NULL, &essidbuf);
+		if (err)
+			goto fail_unlock;
 	}
 
-	/* Finally, we actually initiate the send */
-	netif_stop_queue(dev);
-
-	err = hermes_docmd_wait(hw, HERMES_CMD_TX | HERMES_CMD_RECL, txfid, NULL);
-	if (err) {
-		netif_start_queue(dev);
-		printk(KERN_ERR "%s: Error %d transmitting packet\n", dev->name, err);
-		stats->tx_errors++;
-		goto fail;
-	}
+	len = le16_to_cpu(essidbuf.len);
 
-	dev->trans_start = jiffies;
-	stats->tx_bytes += data_off + data_len;
+	memset(buf, 0, IW_ESSID_MAX_SIZE+1);
+	memcpy(buf, p, len);
+	buf[len] = '\0';
 
+ fail_unlock:
 	orinoco_unlock(priv, &flags);
 
-	dev_kfree_skb(skb);
-
-	TRACE_EXIT(dev->name);
-
-	return 0;
- fail:
-	TRACE_EXIT(dev->name);
-
-	orinoco_unlock(priv, &flags);
-	return err;
+	return err;       
 }
 
-static void
-orinoco_tx_timeout(struct net_device *dev)
+static long orinoco_hw_get_freq(struct orinoco_private *priv)
 {
-	struct orinoco_private *priv = netdev_priv(dev);
-	struct net_device_stats *stats = &priv->stats;
-	struct hermes *hw = &priv->hw;
-
-	printk(KERN_WARNING "%s: Tx timeout! "
-	       "ALLOCFID=%04x, TXCOMPLFID=%04x, EVSTAT=%04x\n",
-	       dev->name, hermes_read_regn(hw, ALLOCFID),
-	       hermes_read_regn(hw, TXCOMPLFID), hermes_read_regn(hw, EVSTAT));
-
-	stats->tx_errors++;
+	
+	hermes_t *hw = &priv->hw;
+	int err = 0;
+	u16 channel;
+	long freq = 0;
+	unsigned long flags;
 
-	schedule_work(&priv->reset_work);
-}
+	err = orinoco_lock(priv, &flags);
+	if (err)
+		return err;
+	
+	err = hermes_read_wordrec(hw, USER_BAP, HERMES_RID_CURRENTCHANNEL, &channel);
+	if (err)
+		goto out;
 
-static int
-orinoco_change_mtu(struct net_device *dev, int new_mtu)
-{
-	struct orinoco_private *priv = netdev_priv(dev);
+	/* Intersil firmware 1.3.5 returns 0 when the interface is down */
+	if (channel == 0) {
+		err = -EBUSY;
+		goto out;
+	}
 
-	if ( (new_mtu < ORINOCO_MIN_MTU) || (new_mtu > ORINOCO_MAX_MTU) )
-		return -EINVAL;
+	if ( (channel < 1) || (channel > NUM_CHANNELS) ) {
+		printk(KERN_WARNING "%s: Channel out of range (%d)!\n",
+		       priv->ndev->name, channel);
+		err = -EBUSY;
+		goto out;
 
-	if ( (new_mtu + ENCAPS_OVERHEAD + IEEE802_11_HLEN) >
-	     (priv->nicbuf_size - ETH_HLEN) )
-		return -EINVAL;
+	}
+	freq = channel_frequency[channel-1] * 100000;
 
-	dev->mtu = new_mtu;
+ out:
+	orinoco_unlock(priv, &flags);
 
-	return 0;
+	if (err > 0)
+		err = -EBUSY;
+	return err ? err : freq;
 }
 
-/* FIXME: return int? */
-static void
-__orinoco_set_multicast_list(struct net_device *dev)
+static int orinoco_hw_get_bitratelist(struct orinoco_private *priv,
+				      int *numrates, s32 *rates, int max)
 {
-	struct orinoco_private *priv = netdev_priv(dev);
 	hermes_t *hw = &priv->hw;
+	struct hermes_idstring list;
+	unsigned char *p = (unsigned char *)&list.val;
 	int err = 0;
-	int promisc, mc_count;
-
-	/* The Hermes doesn't seem to have an allmulti mode, so we go
-	 * into promiscuous mode and let the upper levels deal. */
-	if ( (dev->flags & IFF_PROMISC) || (dev->flags & IFF_ALLMULTI) ||
-	     (dev->mc_count > MAX_MULTICAST(priv)) ) {
-		promisc = 1;
-		mc_count = 0;
-	} else {
-		promisc = 0;
-		mc_count = dev->mc_count;
-	}
+	int num;
+	int i;
+	unsigned long flags;
 
-	if (promisc != priv->promiscuous) {
-		err = hermes_write_wordrec(hw, USER_BAP,
-					   HERMES_RID_CNFPROMISCUOUSMODE,
-					   promisc);
-		if (err) {
-			printk(KERN_ERR "%s: Error %d setting PROMISCUOUSMODE to 1.\n",
-			       dev->name, err);
-		} else 
-			priv->promiscuous = promisc;
-	}
+	err = orinoco_lock(priv, &flags);
+	if (err)
+		return err;
 
-	if (! promisc && (mc_count || priv->mc_count) ) {
-		struct dev_mc_list *p = dev->mc_list;
-		hermes_multicast_t mclist;
-		int i;
+	err = hermes_read_ltv(hw, USER_BAP, HERMES_RID_SUPPORTEDDATARATES,
+			      sizeof(list), NULL, &list);
+	orinoco_unlock(priv, &flags);
 
-		for (i = 0; i < mc_count; i++) {
-			/* Paranoia: */
-			if (! p)
-				BUG(); /* Multicast list shorter than mc_count */
-			if (p->dmi_addrlen != ETH_ALEN)
-				BUG(); /* Bad address size in multicast list */
-			
-			memcpy(mclist.addr[i], p->dmi_addr, ETH_ALEN);
-			p = p->next;
-		}
-		
-		if (p)
-			printk(KERN_WARNING "Multicast list is longer than mc_count\n");
+	if (err)
+		return err;
+	
+	num = le16_to_cpu(list.len);
+	*numrates = num;
+	num = min(num, max);
 
-		err = hermes_write_ltv(hw, USER_BAP, HERMES_RID_CNFGROUPADDRESSES,
-				       HERMES_BYTES_TO_RECLEN(priv->mc_count * ETH_ALEN),
-				       &mclist);
-		if (err)
-			printk(KERN_ERR "%s: Error %d setting multicast list.\n",
-			       dev->name, err);
-		else
-			priv->mc_count = mc_count;
+	for (i = 0; i < num; i++) {
+		rates[i] = (p[i] & 0x7f) * 500000; /* convert to bps */
 	}
 
-	/* Since we can set the promiscuous flag when it wasn't asked
-	   for, make sure the net_device knows about it. */
-	if (priv->promiscuous)
-		dev->flags |= IFF_PROMISC;
-	else
-		dev->flags &= ~IFF_PROMISC;
+	return 0;
 }
 
-/********************************************************************/
-/* Wireless extensions support                                      */
-/********************************************************************/
-
 static int orinoco_ioctl_getiwrange(struct net_device *dev, struct iw_point *rrq)
 {
 	struct orinoco_private *priv = netdev_priv(dev);
@@ -2582,10 +2579,8 @@
 
 	/* Much of this shamelessly taken from wvlan_cs.c. No idea
 	 * what it all means -dgibson */
-#if WIRELESS_EXT > 10
 	range.we_version_compiled = WIRELESS_EXT;
 	range.we_version_source = 11;
-#endif /* WIRELESS_EXT > 10 */
 
 	range.min_nwid = range.max_nwid = 0; /* We don't use nwids */
 
@@ -2612,22 +2607,17 @@
 		range.max_qual.qual = 0;
 		range.max_qual.level = 0;
 		range.max_qual.noise = 0;
-#if WIRELESS_EXT > 11
 		range.avg_qual.qual = 0;
 		range.avg_qual.level = 0;
 		range.avg_qual.noise = 0;
-#endif /* WIRELESS_EXT > 11 */
-
 	} else {
 		range.max_qual.qual = 0x8b - 0x2f;
 		range.max_qual.level = 0x2f - 0x95 - 1;
 		range.max_qual.noise = 0x2f - 0x95 - 1;
-#if WIRELESS_EXT > 11
 		/* Need to get better values */
 		range.avg_qual.qual = 0x24;
 		range.avg_qual.level = 0xC2;
 		range.avg_qual.noise = 0x9E;
-#endif /* WIRELESS_EXT > 11 */
 	}
 
 	err = orinoco_hw_get_bitratelist(priv, &numrates,
@@ -2680,7 +2670,6 @@
 	range.txpower[0] = 15; /* 15dBm */
 	range.txpower_capa = IW_TXPOW_DBM;
 
-#if WIRELESS_EXT > 10
 	range.retry_capa = IW_RETRY_LIMIT | IW_RETRY_LIFETIME;
 	range.retry_flags = IW_RETRY_LIMIT;
 	range.r_time_flags = IW_RETRY_LIFETIME;
@@ -2688,7 +2677,6 @@
 	range.max_retry = 65535;	/* ??? */
 	range.min_r_time = 0;
 	range.max_r_time = 65535 * 1000;	/* ??? */
-#endif /* WIRELESS_EXT > 10 */
 
 	if (copy_to_user(rrq->pointer, &range, sizeof(range)))
 		return -EFAULT;
@@ -2737,7 +2725,8 @@
 		
 		if ((index < 0) || (index >= ORINOCO_MAX_KEYS))
 			index = priv->tx_key;
-		
+
+		/* Adjust key length to a supported value */
 		if (erq->length > SMALL_KEY_SIZE) {
 			xlen = LARGE_KEY_SIZE;
 		} else if (erq->length > 0) {
@@ -2779,14 +2768,14 @@
 
 	if (erq->pointer) {
 		priv->keys[index].len = cpu_to_le16(xlen);
-		memset(priv->keys[index].data, 0, sizeof(priv->keys[index].data));
+		memset(priv->keys[index].data, 0,
+		       sizeof(priv->keys[index].data));
 		memcpy(priv->keys[index].data, keybuf, erq->length);
 	}
 	priv->tx_key = setindex;
 	priv->wep_on = enable;
 	priv->wep_restrict = restricted;
 
-	
  out:
 	orinoco_unlock(priv, &flags);
 
@@ -3012,7 +3001,8 @@
 	err = orinoco_lock(priv, &flags);
 	if (err)
 		return err;
-	err = hermes_read_wordrec(hw, USER_BAP, HERMES_RID_CNFSYSTEMSCALE, &val);
+	err = hermes_read_wordrec(hw, USER_BAP,
+				  HERMES_RID_CNFSYSTEMSCALE, &val);
 	orinoco_unlock(priv, &flags);
 
 	if (err)
@@ -3201,8 +3191,7 @@
 
 	ratemode = priv->bitratemode;
 
-	if ( (ratemode < 0) || (ratemode >= BITRATE_TABLE_SIZE) )
-		BUG();
+	BUG_ON((ratemode < 0) || (ratemode >= BITRATE_TABLE_SIZE));
 
 	rrq->value = bitrate_table[ratemode].bitrate * 100000;
 	rrq->fixed = ! bitrate_table[ratemode].automatic;
@@ -3354,7 +3343,6 @@
 	return err;
 }
 
-#if WIRELESS_EXT > 10
 static int orinoco_ioctl_getretry(struct net_device *dev, struct iw_param *rrq)
 {
 	struct orinoco_private *priv = netdev_priv(dev);
@@ -3406,7 +3394,6 @@
 
 	return err;
 }
-#endif /* WIRELESS_EXT > 10 */
 
 static int orinoco_ioctl_setibssport(struct net_device *dev, struct iwreq *wrq)
 {
@@ -3500,7 +3487,6 @@
 
 	*val = priv->prefer_port3;
 	orinoco_unlock(priv, &flags);
-
 	return 0;
 }
 
@@ -3790,7 +3776,6 @@
 		wrq->u.txpower.flags = IW_TXPOW_DBM;
 		break;
 
-#if WIRELESS_EXT > 10
 	case SIOCSIWRETRY:
 		err = -EOPNOTSUPP;
 		break;
@@ -3798,7 +3783,6 @@
 	case SIOCGIWRETRY:
 		err = orinoco_ioctl_getretry(dev, &wrq->u.retry);
 		break;
-#endif /* WIRELESS_EXT > 10 */
 
 	case SIOCSIWSPY:
 		err = orinoco_ioctl_setspy(dev, &wrq->u.data);
@@ -4124,51 +4108,68 @@
 	return 0;
 }
 
-struct net_device *alloc_orinocodev(int sizeof_card, int (*hard_reset)(struct orinoco_private *))
-{
-	struct net_device *dev;
-	struct orinoco_private *priv;
-
-	dev = alloc_etherdev(sizeof(struct orinoco_private) + sizeof_card);
-	if (!dev)
-		return NULL;
-	priv = netdev_priv(dev);
-	priv->ndev = dev;
-	if (sizeof_card)
-		priv->card = (void *)((unsigned long)dev->priv + sizeof(struct orinoco_private));
-	else
-		priv->card = NULL;
-
-	/* Setup / override net_device fields */
-	dev->init = orinoco_init;
-	dev->hard_start_xmit = orinoco_xmit;
-	dev->tx_timeout = orinoco_tx_timeout;
-	dev->watchdog_timeo = HZ; /* 1 second timeout */
-	dev->get_stats = orinoco_get_stats;
-	dev->get_wireless_stats = orinoco_get_wireless_stats;
-	dev->do_ioctl = orinoco_ioctl;
-	dev->change_mtu = orinoco_change_mtu;
-	dev->set_multicast_list = orinoco_set_multicast_list;
-	/* we use the default eth_mac_addr for setting the MAC addr */
-
-	/* Set up default callbacks */
-	dev->open = orinoco_open;
-	dev->stop = orinoco_stop;
-	priv->hard_reset = hard_reset;
+/********************************************************************/
+/* Debugging                                                        */
+/********************************************************************/
 
-	spin_lock_init(&priv->lock);
-	priv->open = 0;
-	priv->hw_unavailable = 1; /* orinoco_init() must clear this
-				   * before anything else touches the
-				   * hardware */
-	INIT_WORK(&priv->reset_work, (void (*)(void *))orinoco_reset, dev);
+#if 0
+static void show_rx_frame(struct orinoco_rxframe_hdr *frame)
+{
+	printk(KERN_DEBUG "RX descriptor:\n");
+	printk(KERN_DEBUG "  status      = 0x%04x\n", frame->desc.status);
+	printk(KERN_DEBUG "  time        = 0x%08x\n", frame->desc.time);
+	printk(KERN_DEBUG "  silence     = 0x%02x\n", frame->desc.silence);
+	printk(KERN_DEBUG "  signal      = 0x%02x\n", frame->desc.signal);
+	printk(KERN_DEBUG "  rate        = 0x%02x\n", frame->desc.rate);
+	printk(KERN_DEBUG "  rxflow      = 0x%02x\n", frame->desc.rxflow);
+	printk(KERN_DEBUG "  reserved    = 0x%08x\n", frame->desc.reserved);
 
-	priv->last_linkstatus = 0xffff;
-	priv->connected = 0;
+	printk(KERN_DEBUG "IEEE 802.11 header:\n");
+	printk(KERN_DEBUG "  frame_ctl   = 0x%04x\n",
+	       frame->p80211.frame_ctl);
+	printk(KERN_DEBUG "  duration_id = 0x%04x\n",
+	       frame->p80211.duration_id);
+	printk(KERN_DEBUG "  addr1       = %02x:%02x:%02x:%02x:%02x:%02x\n",
+	       frame->p80211.addr1[0], frame->p80211.addr1[1],
+	       frame->p80211.addr1[2], frame->p80211.addr1[3],
+	       frame->p80211.addr1[4], frame->p80211.addr1[5]);
+	printk(KERN_DEBUG "  addr2       = %02x:%02x:%02x:%02x:%02x:%02x\n",
+	       frame->p80211.addr2[0], frame->p80211.addr2[1],
+	       frame->p80211.addr2[2], frame->p80211.addr2[3],
+	       frame->p80211.addr2[4], frame->p80211.addr2[5]);
+	printk(KERN_DEBUG "  addr3       = %02x:%02x:%02x:%02x:%02x:%02x\n",
+	       frame->p80211.addr3[0], frame->p80211.addr3[1],
+	       frame->p80211.addr3[2], frame->p80211.addr3[3],
+	       frame->p80211.addr3[4], frame->p80211.addr3[5]);
+	printk(KERN_DEBUG "  seq_ctl     = 0x%04x\n",
+	       frame->p80211.seq_ctl);
+	printk(KERN_DEBUG "  addr4       = %02x:%02x:%02x:%02x:%02x:%02x\n",
+	       frame->p80211.addr4[0], frame->p80211.addr4[1],
+	       frame->p80211.addr4[2], frame->p80211.addr4[3],
+	       frame->p80211.addr4[4], frame->p80211.addr4[5]);
+	printk(KERN_DEBUG "  data_len    = 0x%04x\n",
+	       frame->p80211.data_len);
 
-	return dev;
+	printk(KERN_DEBUG "IEEE 802.3 header:\n");
+	printk(KERN_DEBUG "  dest        = %02x:%02x:%02x:%02x:%02x:%02x\n",
+	       frame->p8023.h_dest[0], frame->p8023.h_dest[1],
+	       frame->p8023.h_dest[2], frame->p8023.h_dest[3],
+	       frame->p8023.h_dest[4], frame->p8023.h_dest[5]);
+	printk(KERN_DEBUG "  src         = %02x:%02x:%02x:%02x:%02x:%02x\n",
+	       frame->p8023.h_source[0], frame->p8023.h_source[1],
+	       frame->p8023.h_source[2], frame->p8023.h_source[3],
+	       frame->p8023.h_source[4], frame->p8023.h_source[5]);
+	printk(KERN_DEBUG "  len         = 0x%04x\n", frame->p8023.h_proto);
 
+	printk(KERN_DEBUG "IEEE 802.2 LLC/SNAP header:\n");
+	printk(KERN_DEBUG "  DSAP        = 0x%02x\n", frame->p8022.dsap);
+	printk(KERN_DEBUG "  SSAP        = 0x%02x\n", frame->p8022.ssap);
+	printk(KERN_DEBUG "  ctrl        = 0x%02x\n", frame->p8022.ctrl);
+	printk(KERN_DEBUG "  OUI         = %02x:%02x:%02x\n",
+	       frame->p8022.oui[0], frame->p8022.oui[1], frame->p8022.oui[2]);
+	printk(KERN_DEBUG "  ethertype  = 0x%04x\n", frame->ethertype);
 }
+#endif /* 0 */
 
 /********************************************************************/
 /* Module initialization                                            */
@@ -4185,7 +4186,9 @@
 
 /* Can't be declared "const" or the whole __initdata section will
  * become const */
-static char version[] __initdata = "orinoco.c 0.13e (David Gibson <hermes@gibson.dropbear.id.au> and others)";
+static char version[] __initdata = DRIVER_NAME " " DRIVER_VERSION
+	" (David Gibson <hermes@gibson.dropbear.id.au>, "
+	"Pavel Roskin <proski@gnu.org>, et al)";
 
 static int __init init_orinoco(void)
 {
diff -Nru a/drivers/net/wireless/orinoco.h b/drivers/net/wireless/orinoco.h
--- a/drivers/net/wireless/orinoco.h	2004-10-18 14:56:27 -07:00
+++ b/drivers/net/wireless/orinoco.h	2004-10-18 14:56:27 -07:00
@@ -7,39 +7,19 @@
 #ifndef _ORINOCO_H
 #define _ORINOCO_H
 
+#define DRIVER_VERSION "0.13e"
+
 #include <linux/types.h>
 #include <linux/spinlock.h>
 #include <linux/netdevice.h>
 #include <linux/wireless.h>
 #include <linux/version.h>
-#include "hermes.h"
-
-/* Workqueue / task queue backwards compatibility stuff */
-
-#if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,41)
-#include <linux/workqueue.h>
-#else
-#include <linux/tqueue.h>
-#define work_struct tq_struct
-#define INIT_WORK INIT_TQUEUE
-#define schedule_work schedule_task
-#endif
-
-/* Interrupt handler backwards compatibility stuff */
-#ifndef IRQ_NONE
 
-#define IRQ_NONE
-#define IRQ_HANDLED
-typedef void irqreturn_t;
-
-#endif
+#include "hermes.h"
 
 /* To enable debug messages */
 //#define ORINOCO_DEBUG		3
 
-#if (! defined (WIRELESS_EXT)) || (WIRELESS_EXT < 10)
-#error "orinoco driver requires Wireless extensions v10 or later."
-#endif /* (! defined (WIRELESS_EXT)) || (WIRELESS_EXT < 10) */
 #define WIRELESS_SPY		// enable iwspy support
 
 #define ORINOCO_MAX_KEY_SIZE	14
@@ -50,11 +30,6 @@
 	char data[ORINOCO_MAX_KEY_SIZE];
 } __attribute__ ((packed));
 
-#define ORINOCO_INTEN	 	( HERMES_EV_RX | HERMES_EV_ALLOC | HERMES_EV_TX | \
-				HERMES_EV_TXEXC | HERMES_EV_WTERR | HERMES_EV_INFO | \
-				HERMES_EV_INFDROP )
-
-
 struct orinoco_private {
 	void *card;	/* Pointer to card dependent structure */
 	int (*hard_reset)(struct orinoco_private *);
@@ -78,7 +53,6 @@
 	hermes_t hw;
 	u16 txfid;
 
-
 	/* Capabilities of the hardware/firmware */
 	int firmware_type;
 #define FIRMWARE_TYPE_AGERE 1
@@ -127,6 +101,10 @@
 
 #define TRACE_ENTER(devname) DEBUG(2, "%s: -> %s()\n", devname, __FUNCTION__);
 #define TRACE_EXIT(devname)  DEBUG(2, "%s: <- %s()\n", devname, __FUNCTION__);
+
+/********************************************************************/
+/* Exported prototypes                                              */
+/********************************************************************/
 
 extern struct net_device *alloc_orinocodev(int sizeof_card,
 					   int (*hard_reset)(struct orinoco_private *));
diff -Nru a/drivers/net/wireless/orinoco_cs.c b/drivers/net/wireless/orinoco_cs.c
--- a/drivers/net/wireless/orinoco_cs.c	2004-10-18 14:57:03 -07:00
+++ b/drivers/net/wireless/orinoco_cs.c	2004-10-18 14:57:03 -07:00
@@ -1,4 +1,4 @@
-/* orinoco_cs.c 0.13e	- (formerly known as dldwd_cs.c)
+/* orinoco_cs.c (formerly known as dldwd_cs.c)
  *
  * A driver for "Hermes" chipset based PCMCIA wireless adaptors, such
  * as the Lucent WavelanIEEE/Orinoco cards and their OEM (Cabletron/
@@ -10,6 +10,9 @@
  * Copyright notice & release notes in file orinoco.c
  */
 
+#define DRIVER_NAME "orinoco_cs"
+#define PFX DRIVER_NAME ": "
+
 #include <linux/config.h>
 #ifdef  __IN_PCMCIA_PACKAGE__
 #include <pcmcia/k_compat.h>
@@ -47,9 +50,7 @@
 
 MODULE_AUTHOR("David Gibson <hermes@gibson.dropbear.id.au>");
 MODULE_DESCRIPTION("Driver for PCMCIA Lucent Orinoco, Prism II based and similar wireless cards");
-#ifdef MODULE_LICENSE
 MODULE_LICENSE("Dual MPL/GPL");
-#endif
 
 /* Module parameters */
 
@@ -76,7 +77,7 @@
  * device driver with appropriate cards, through the card
  * configuration database.
  */
-static dev_info_t dev_info = "orinoco_cs";
+static dev_info_t dev_info = DRIVER_NAME;
 
 /********************************************************************/
 /* Data structures						    */
@@ -144,15 +145,6 @@
 /* PCMCIA stuff     						    */
 /********************************************************************/
 
-/* In 2.5 (as of 2.5.69 at least) there is a cs_error exported which
- * does this, but it's not in 2.4 so we do our own for now. */
-static void
-orinoco_cs_error(client_handle_t handle, int func, int ret)
-{
-	error_info_t err = { func, ret };
-	pcmcia_report_error(handle, &err);
-}
-
 /*
  * This creates an "instance" of the driver, allocating local data
  * structures for one device.  The device is registered with Card
@@ -174,7 +166,7 @@
 	dev = alloc_orinocodev(sizeof(*card), orinoco_cs_hard_reset);
 	if (! dev)
 		return NULL;
-	priv = dev->priv;
+	priv = netdev_priv(dev);
 	card = priv->card;
 
 	/* Link both structures together */
@@ -216,7 +208,7 @@
 
 	ret = pcmcia_register_client(&link->handle, &client_reg);
 	if (ret != CS_SUCCESS) {
-		orinoco_cs_error(link->handle, RegisterClient, ret);
+		cs_error(link->handle, RegisterClient, ret);
 		orinoco_cs_detach(link);
 		return NULL;
 	}
@@ -230,8 +222,7 @@
  * are freed.  Otherwise, the structures will be freed when the device
  * is released.
  */
-static void
-orinoco_cs_detach(dev_link_t * link)
+static void orinoco_cs_detach(dev_link_t *link)
 {
 	dev_link_t **linkp;
 	struct net_device *dev = link->priv;
@@ -240,10 +231,8 @@
 	for (linkp = &dev_list; *linkp; linkp = &(*linkp)->next)
 		if (*linkp == link)
 			break;
-	if (*linkp == NULL) {
-		BUG();
-		return;
-	}
+
+	BUG_ON(*linkp == NULL);
 
 	if (link->state & DEV_CONFIG)
 		orinoco_cs_release(link);
@@ -254,9 +243,9 @@
 
 	/* Unlink device structure, and free it */
 	*linkp = link->next;
-	DEBUG(0, "orinoco_cs: detach: link=%p link->dev=%p\n", link, link->dev);
+	DEBUG(0, PFX "detach: link=%p link->dev=%p\n", link, link->dev);
 	if (link->dev) {
-		DEBUG(0, "orinoco_cs: About to unregister net device %p\n",
+		DEBUG(0, PFX "About to unregister net device %p\n",
 		      dev);
 		unregister_netdev(dev);
 	}
@@ -269,15 +258,16 @@
  * device available to the system.
  */
 
-#define CS_CHECK(fn, ret) \
-do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0)
+#define CS_CHECK(fn, ret) do { \
+		last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; \
+	} while (0)
 
 static void
 orinoco_cs_config(dev_link_t *link)
 {
 	struct net_device *dev = link->priv;
 	client_handle_t handle = link->handle;
-	struct orinoco_private *priv = dev->priv;
+	struct orinoco_private *priv = netdev_priv(dev);
 	struct orinoco_pccard *card = priv->card;
 	hermes_t *hw = &priv->hw;
 	int last_fn, last_ret;
@@ -308,7 +298,8 @@
 	link->state |= DEV_CONFIG;
 
 	/* Look up the current Vcc */
-	CS_CHECK(GetConfigurationInfo, pcmcia_get_configuration_info(handle, &conf));
+	CS_CHECK(GetConfigurationInfo,
+		 pcmcia_get_configuration_info(handle, &conf));
 	link->conf.Vcc = conf.Vcc;
 
 	/*
@@ -412,8 +403,9 @@
 			pcmcia_release_io(link->handle, &link->io);
 		last_ret = pcmcia_get_next_tuple(handle, &tuple);
 		if (last_ret  == CS_NO_MORE_ITEMS) {
-			printk(KERN_ERR "GetNextTuple().  No matching CIS configuration, "
-			       "maybe you need the ignore_cis_vcc=1 parameter.\n");
+			printk(KERN_ERR PFX "GetNextTuple(): No matching "
+			       "CIS configuration, maybe you need the "
+			       "ignore_cis_vcc=1 parameter.\n");
 			goto cs_failed;
 		}
 	}
@@ -451,7 +443,8 @@
 	 * the I/O windows and the interrupt mapping, and putting the
 	 * card and host interface into "Memory and IO" mode.
 	 */
-	CS_CHECK(RequestConfiguration, pcmcia_request_configuration(link->handle, &link->conf));
+	CS_CHECK(RequestConfiguration,
+		 pcmcia_request_configuration(link->handle, &link->conf));
 
 	/* Ok, we have the configuration, prepare to register the netdev */
 	dev->base_addr = link->io.BasePort1;
@@ -463,7 +456,7 @@
 	dev->name[0] = '\0';
 	/* Tell the stack we exist */
 	if (register_netdev(dev) != 0) {
-		printk(KERN_ERR "orinoco_cs: register_netdev() failed\n");
+		printk(KERN_ERR PFX "register_netdev() failed\n");
 		goto failed;
 	}
 
@@ -495,7 +488,7 @@
 	return;
 
  cs_failed:
-	orinoco_cs_error(link->handle, last_fn, last_ret);
+	cs_error(link->handle, last_fn, last_ret);
 
  failed:
 	orinoco_cs_release(link);
@@ -510,7 +503,7 @@
 orinoco_cs_release(dev_link_t *link)
 {
 	struct net_device *dev = link->priv;
-	struct orinoco_private *priv = dev->priv;
+	struct orinoco_private *priv = netdev_priv(dev);
 	unsigned long flags;
 
 	/* We're committed to taking the device away now, so mark the
@@ -538,7 +531,7 @@
 {
 	dev_link_t *link = args->client_data;
 	struct net_device *dev = link->priv;
-	struct orinoco_private *priv = dev->priv;
+	struct orinoco_private *priv = netdev_priv(dev);
 	struct orinoco_pccard *card = priv->card;
 	int err = 0;
 	unsigned long flags;
@@ -635,12 +628,14 @@
 
 /* Can't be declared "const" or the whole __initdata section will
  * become const */
-static char version[] __initdata = "orinoco_cs.c 0.13e (David Gibson <hermes@gibson.dropbear.id.au> and others)";
+static char version[] __initdata = DRIVER_NAME " " DRIVER_VERSION
+	" (David Gibson <hermes@gibson.dropbear.id.au>, "
+	"Pavel Roskin <proski@gnu.org>, et al)";
 
 static struct pcmcia_driver orinoco_driver = {
 	.owner		= THIS_MODULE,
 	.drv		= {
-		.name	= "orinoco_cs",
+		.name	= DRIVER_NAME,
 	},
 	.attach		= orinoco_cs_attach,
 	.detach		= orinoco_cs_detach,
@@ -660,7 +655,7 @@
 	pcmcia_unregister_driver(&orinoco_driver);
 
 	if (dev_list)
-		DEBUG(0, "orinoco_cs: Removing leftover devices.\n");
+		DEBUG(0, PFX "Removing leftover devices.\n");
 	while (dev_list != NULL) {
 		if (dev_list->state & DEV_CONFIG)
 			orinoco_cs_release(dev_list);
@@ -670,4 +665,3 @@
 
 module_init(init_orinoco_cs);
 module_exit(exit_orinoco_cs);
-
diff -Nru a/drivers/net/wireless/orinoco_pci.c b/drivers/net/wireless/orinoco_pci.c
--- a/drivers/net/wireless/orinoco_pci.c	2004-10-18 14:56:48 -07:00
+++ b/drivers/net/wireless/orinoco_pci.c	2004-10-18 14:56:48 -07:00
@@ -1,19 +1,23 @@
-/* orinoco_pci.c 0.13e
+/* orinoco_pci.c
  * 
  * Driver for Prism II devices that have a direct PCI interface
  * (i.e., not in a Pcmcia or PLX bridge)
  *
  * Specifically here we're talking about the Linksys WMP11
  *
+ * Current maintainers (as of 29 September 2003) are:
+ * 	Pavel Roskin <proski AT gnu.org>
+ * and	David Gibson <hermes AT gibson.dropbear.id.au>
+ *
  * Some of this code is borrowed from orinoco_plx.c
- *	Copyright (C) 2001 Daniel Barlow <dan@telent.net>
+ *	Copyright (C) 2001 Daniel Barlow <dan AT telent.net>
  * Some of this code is "inspired" by linux-wlan-ng-0.1.10, but nothing
  * has been copied from it. linux-wlan-ng-0.1.10 is originally :
  *	Copyright (C) 1999 AbsoluteValue Systems, Inc.  All Rights Reserved.
  * This file originally written by:
- *	Copyright (C) 2001 Jean Tourrilhes <jt@hpl.hp.com>
+ *	Copyright (C) 2001 Jean Tourrilhes <jt AT hpl.hp.com>
  * And is now maintained by:
- *	Copyright (C) 2002 David Gibson, IBM Corporation <herme@gibson.dropbear.id.au>
+ *	(C) Copyright David Gibson, IBM Corp. 2002-2003.
  *
  * The contents of this file are subject to the Mozilla Public License
  * Version 1.1 (the "License"); you may not use this file except in
@@ -85,6 +89,9 @@
  * Jean II
  */
 
+#define DRIVER_NAME "orinoco_pci"
+#define PFX DRIVER_NAME ": "
+
 #include <linux/config.h>
 
 #include <linux/module.h>
@@ -99,7 +106,6 @@
 #include <linux/netdevice.h>
 #include <linux/if_arp.h>
 #include <linux/etherdevice.h>
-#include <linux/wireless.h>
 #include <linux/list.h>
 #include <linux/pci.h>
 #include <linux/fcntl.h>
@@ -174,7 +180,7 @@
 	}
 	/* Did we timeout ? */
 	if(time_after_eq(jiffies, timeout)) {
-		printk(KERN_ERR "orinoco_pci: Busy timeout\n");
+		printk(KERN_ERR PFX "Busy timeout\n");
 		return -ETIMEDOUT;
 	}
 	printk(KERN_NOTICE "pci_cor : reg = 0x%X - %lX - %lX\n", reg, timeout, jiffies);
@@ -206,22 +212,21 @@
 	if (! pci_iorange)
 		goto fail;
 
-	/* Usual setup of structures */
+	/* Allocate network device */
 	dev = alloc_orinocodev(0, NULL);
 	if (! dev) {
 		err = -ENOMEM;
 		goto fail;
 	}
-	priv = dev->priv;
 
+	priv = netdev_priv(dev);
 	dev->base_addr = (unsigned long) pci_ioaddr;
 	dev->mem_start = pci_iorange;
 	dev->mem_end = pci_iorange + pci_iolen - 1;
-
 	SET_MODULE_OWNER(dev);
 	SET_NETDEV_DEV(dev, &pdev->dev);
 
-	printk(KERN_DEBUG
+	printk(KERN_DEBUG PFX
 	       "Detected Orinoco/Prism2 PCI device at %s, mem:0x%lX to 0x%lX -> 0x%p, irq:%d\n",
 	       pci_name(pdev), dev->mem_start, dev->mem_end, pci_ioaddr, pdev->irq);
 
@@ -232,12 +237,13 @@
 	err = request_irq(pdev->irq, orinoco_interrupt, SA_SHIRQ,
 			  dev->name, dev);
 	if (err) {
-		printk(KERN_ERR "orinoco_pci: Error allocating IRQ %d.\n",
+		printk(KERN_ERR PFX "Error allocating IRQ %d.\n",
 		       pdev->irq);
 		err = -EBUSY;
 		goto fail;
 	}
 	dev->irq = pdev->irq;
+
 	/* Perform a COR reset to start the card */
 	if(orinoco_pci_cor_reset(priv) != 0) {
 		printk(KERN_ERR "%s: Failed to start the card\n", dev->name);
@@ -255,7 +261,8 @@
 		goto fail;
 	}
 
-        return 0;               /* succeeded */
+	return 0;
+
  fail:
 	if (dev) {
 		if (dev->irq)
@@ -275,11 +282,11 @@
 static void __devexit orinoco_pci_remove_one(struct pci_dev *pdev)
 {
 	struct net_device *dev = pci_get_drvdata(pdev);
-	struct orinoco_private *priv = dev->priv;
+	struct orinoco_private *priv = netdev_priv(dev);
 
 	unregister_netdev(dev);
 
-        if (dev->irq)
+	if (dev->irq)
 		free_irq(dev->irq, dev);
 
 	if (priv->hw.iobase)
@@ -294,7 +301,7 @@
 static int orinoco_pci_suspend(struct pci_dev *pdev, u32 state)
 {
 	struct net_device *dev = pci_get_drvdata(pdev);
-	struct orinoco_private *priv = dev->priv;
+	struct orinoco_private *priv = netdev_priv(dev);
 	unsigned long flags;
 	int err;
 	
@@ -325,7 +332,7 @@
 static int orinoco_pci_resume(struct pci_dev *pdev)
 {
 	struct net_device *dev = pci_get_drvdata(pdev);
-	struct orinoco_private *priv = dev->priv;
+	struct orinoco_private *priv = netdev_priv(dev);
 	unsigned long flags;
 	int err;
 
@@ -357,7 +364,9 @@
 }
 
 static struct pci_device_id orinoco_pci_pci_id_table[] = {
+	/* Intersil Prism 3 */
 	{0x1260, 0x3872, PCI_ANY_ID, PCI_ANY_ID,},
+	/* Intersil Prism 2.5 */
 	{0x1260, 0x3873, PCI_ANY_ID, PCI_ANY_ID,},
 	{0,},
 };
@@ -365,7 +374,7 @@
 MODULE_DEVICE_TABLE(pci, orinoco_pci_pci_id_table);
 
 static struct pci_driver orinoco_pci_driver = {
-	.name		= "orinoco_pci",
+	.name		= DRIVER_NAME,
 	.id_table	= orinoco_pci_pci_id_table,
 	.probe		= orinoco_pci_init_one,
 	.remove		= __devexit_p(orinoco_pci_remove_one),
@@ -373,8 +382,11 @@
 	.resume		= orinoco_pci_resume,
 };
 
-static char version[] __initdata = "orinoco_pci.c 0.13e (David Gibson <hermes@gibson.dropbear.id.au> & Jean Tourrilhes <jt@hpl.hp.com>)";
-MODULE_AUTHOR("David Gibson <hermes@gibson.dropbear.id.au>");
+static char version[] __initdata = DRIVER_NAME " " DRIVER_VERSION
+	" (Pavel Roskin <proski@gnu.org>,"
+	" David Gibson <hermes@gibson.dropbear.id.au> &"
+	" Jean Tourrilhes <jt@hpl.hp.com>)";
+MODULE_AUTHOR("Pavel Roskin <proski@gnu.org> & David Gibson <hermes@gibson.dropbear.id.au>");
 MODULE_DESCRIPTION("Driver for wireless LAN cards using direct PCI interface");
 MODULE_LICENSE("Dual MPL/GPL");
 
@@ -384,7 +396,7 @@
 	return pci_module_init(&orinoco_pci_driver);
 }
 
-void __exit orinoco_pci_exit(void)
+static void __exit orinoco_pci_exit(void)
 {
 	pci_unregister_driver(&orinoco_pci_driver);
 }
diff -Nru a/drivers/net/wireless/orinoco_plx.c b/drivers/net/wireless/orinoco_plx.c
--- a/drivers/net/wireless/orinoco_plx.c	2004-10-18 14:57:04 -07:00
+++ b/drivers/net/wireless/orinoco_plx.c	2004-10-18 14:57:04 -07:00
@@ -1,9 +1,14 @@
-/* orinoco_plx.c 0.13e
- * 
+/* orinoco_plx.c
+ *
  * Driver for Prism II devices which would usually be driven by orinoco_cs,
- * but are connected to the PCI bus by a PLX9052. 
+ * but are connected to the PCI bus by a PLX9052.
+ *
+ * Current maintainers (as of 29 September 2003) are:
+ * 	Pavel Roskin <proski AT gnu.org>
+ * and	David Gibson <hermes AT gibson.dropbear.id.au>
  *
- * Copyright (C) 2001 Daniel Barlow <dan@telent.net>
+ * (C) Copyright David Gibson, IBM Corp. 2001-2003.
+ * Copyright (C) 2001 Daniel Barlow
  *
  * The contents of this file are subject to the Mozilla Public License
  * Version 1.1 (the "License"); you may not use this file except in
@@ -33,77 +38,83 @@
  * drop me mail with the id and "it works"/"it doesn't work".
  *
  * Note: if everything gets detected fine but it doesn't actually send
- * or receive packets, your first port of call should probably be to   
+ * or receive packets, your first port of call should probably be to
  * try newer firmware in the card.  Especially if you're doing Ad-Hoc
- * modes
+ * modes.
  *
  * The actual driving is done by orinoco.c, this is just resource
  * allocation stuff.  The explanation below is courtesy of Ryan Niemi
  * on the linux-wlan-ng list at
  * http://archives.neohapsis.com/archives/dev/linux-wlan/2001-q1/0026.html
+ *
+ * The PLX9052-based cards (WL11000 and several others) are a
+ * different beast than the usual PCMCIA-based PRISM2 configuration
+ * expected by wlan-ng.  Here's the general details on how the WL11000
+ * PCI adapter works:
+ *
+ * - Two PCI I/O address spaces, one 0x80 long which contains the
+ * PLX9052 registers, and one that's 0x40 long mapped to the PCMCIA
+ * slot I/O address space.
+ *
+ * - One PCI memory address space, mapped to the PCMCIA memory space
+ * (containing the CIS).
+ *
+ * After identifying the I/O and memory space, you can read through
+ * the memory space to confirm the CIS's device ID or manufacturer ID
+ * to make sure it's the expected card.  qKeep in mind that the PCMCIA
+ * spec specifies the CIS as the lower 8 bits of each word read from
+ * the CIS, so to read the bytes of the CIS, read every other byte
+ * (0,2,4,...). Passing that test, you need to enable the I/O address
+ * space on the PCMCIA card via the PCMCIA COR register. This is the
+ * first byte following the CIS. In my case (which may not have any
+ * relation to what's on the PRISM2 cards), COR was at offset 0x800
+ * within the PCI memory space. Write 0x41 to the COR register to
+ * enable I/O mode and to select level triggered interrupts. To
+ * confirm you actually succeeded, read the COR register back and make
+ * sure it actually got set to 0x41, incase you have an unexpected
+ * card inserted.
+ *
+ * Following that, you can treat the second PCI I/O address space (the
+ * one that's not 0x80 in length) as the PCMCIA I/O space.
+ *
+ * Note that in the Eumitcom's source for their drivers, they register
+ * the interrupt as edge triggered when registering it with the
+ * Windows kernel. I don't recall how to register edge triggered on
+ * Linux (if it can be done at all). But in some experimentation, I
+ * don't see much operational difference between using either
+ * interrupt mode. Don't mess with the interrupt mode in the COR
+ * register though, as the PLX9052 wants level triggers with the way
+ * the serial EEPROM configures it on the WL11000.
+ *
+ * There's some other little quirks related to timing that I bumped
+ * into, but I don't recall right now. Also, there's two variants of
+ * the WL11000 I've seen, revision A1 and T2. These seem to differ
+ * slightly in the timings configured in the wait-state generator in
+ * the PLX9052. There have also been some comments from Eumitcom that
+ * cards shouldn't be hot swapped, apparently due to risk of cooking
+ * the PLX9052. I'm unsure why they believe this, as I can't see
+ * anything in the design that would really cause a problem, except
+ * for crashing drivers not written to expect it. And having developed
+ * drivers for the WL11000, I'd say it's quite tricky to write code
+ * that will successfully deal with a hot unplug. Very odd things
+ * happen on the I/O side of things. But anyway, be warned. Despite
+ * that, I've hot-swapped a number of times during debugging and
+ * driver development for various reasons (stuck WAIT# line after the
+ * radio card's firmware locks up).
+ *
+ * Hope this is enough info for someone to add PLX9052 support to the
+ * wlan-ng card. In the case of the WL11000, the PCI ID's are
+ * 0x1639/0x0200, with matching subsystem ID's. Other PLX9052-based
+ * manufacturers other than Eumitcom (or on cards other than the
+ * WL11000) may have different PCI ID's.
+ *
+ * If anyone needs any more specific info, let me know. I haven't had
+ * time to implement support myself yet, and with the way things are
+ * going, might not have time for a while..
+ */
 
-The PLX9052-based cards (WL11000 and several others) are a different
-beast than the usual PCMCIA-based PRISM2 configuration expected by
-wlan-ng. Here's the general details on how the WL11000 PCI adapter
-works:
-
- - Two PCI I/O address spaces, one 0x80 long which contains the PLX9052
-   registers, and one that's 0x40 long mapped to the PCMCIA slot I/O
-   address space.
-
- - One PCI memory address space, mapped to the PCMCIA memory space
-   (containing the CIS).
-
-After identifying the I/O and memory space, you can read through the
-memory space to confirm the CIS's device ID or manufacturer ID to make
-sure it's the expected card. Keep in mind that the PCMCIA spec specifies
-the CIS as the lower 8 bits of each word read from the CIS, so to read the
-bytes of the CIS, read every other byte (0,2,4,...). Passing that test,
-you need to enable the I/O address space on the PCMCIA card via the PCMCIA
-COR register. This is the first byte following the CIS. In my case
-(which may not have any relation to what's on the PRISM2 cards), COR was
-at offset 0x800 within the PCI memory space. Write 0x41 to the COR
-register to enable I/O mode and to select level triggered interrupts. To
-confirm you actually succeeded, read the COR register back and make sure
-it actually got set to 0x41, incase you have an unexpected card inserted.
-
-Following that, you can treat the second PCI I/O address space (the one
-that's not 0x80 in length) as the PCMCIA I/O space.
-
-Note that in the Eumitcom's source for their drivers, they register the
-interrupt as edge triggered when registering it with the Windows kernel. I
-don't recall how to register edge triggered on Linux (if it can be done at
-all). But in some experimentation, I don't see much operational
-difference between using either interrupt mode. Don't mess with the
-interrupt mode in the COR register though, as the PLX9052 wants level
-triggers with the way the serial EEPROM configures it on the WL11000.
-
-There's some other little quirks related to timing that I bumped into, but
-I don't recall right now. Also, there's two variants of the WL11000 I've
-seen, revision A1 and T2. These seem to differ slightly in the timings
-configured in the wait-state generator in the PLX9052. There have also
-been some comments from Eumitcom that cards shouldn't be hot swapped,
-apparently due to risk of cooking the PLX9052. I'm unsure why they
-believe this, as I can't see anything in the design that would really
-cause a problem, except for crashing drivers not written to expect it. And
-having developed drivers for the WL11000, I'd say it's quite tricky to
-write code that will successfully deal with a hot unplug. Very odd things
-happen on the I/O side of things. But anyway, be warned. Despite that,
-I've hot-swapped a number of times during debugging and driver development
-for various reasons (stuck WAIT# line after the radio card's firmware
-locks up).
-
-Hope this is enough info for someone to add PLX9052 support to the wlan-ng
-card. In the case of the WL11000, the PCI ID's are 0x1639/0x0200, with
-matching subsystem ID's. Other PLX9052-based manufacturers other than
-Eumitcom (or on cards other than the WL11000) may have different PCI ID's.
-
-If anyone needs any more specific info, let me know. I haven't had time
-to implement support myself yet, and with the way things are going, might
-not have time for a while..
-
----end of mail---
-*/
+#define DRIVER_NAME "orinoco_plx"
+#define PFX DRIVER_NAME ": "
 
 #include <linux/config.h>
 
@@ -122,7 +133,6 @@
 #include <linux/netdevice.h>
 #include <linux/if_arp.h>
 #include <linux/etherdevice.h>
-#include <linux/wireless.h>
 #include <linux/list.h>
 #include <linux/pci.h>
 #include <linux/fcntl.h>
@@ -132,13 +142,11 @@
 #include "hermes.h"
 #include "orinoco.h"
 
-static char dev_info[] = "orinoco_plx";
-
-#define COR_OFFSET    (0x3e0 / 2)	/* COR attribute offset of Prism2 PC card */
-#define COR_VALUE     (COR_LEVEL_REQ | COR_FUNC_ENA) /* Enable PC card with interrupt in level trigger */
+#define COR_OFFSET	(0x3e0/2) /* COR attribute offset of Prism2 PC card */
+#define COR_VALUE	(COR_LEVEL_REQ | COR_FUNC_ENA) /* Enable PC card with interrupt in level trigger */
 
-#define PLX_INTCSR       0x4c /* Interrupt Control and Status Register */
-#define PLX_INTCSR_INTEN (1<<6) /* Interrupt Enable bit */
+#define PLX_INTCSR		0x4c /* Interrupt Control & Status Register */
+#define PLX_INTCSR_INTEN	(1<<6) /* Interrupt Enable bit */
 
 static const u16 cis_magic[] = {
 	0x0001, 0x0003, 0x0000, 0x0000, 0x00ff, 0x0017, 0x0004, 0x0067
@@ -215,7 +223,7 @@
 	/* and 3 to the PCMCIA slot I/O address space */
 	pccard_ioaddr = pci_resource_start(pdev, 3);
 	pccard_iolen = pci_resource_len(pdev, 3);
-	if (! request_region(pccard_ioaddr, pccard_iolen, dev_info)) {
+	if (! request_region(pccard_ioaddr, pccard_iolen, DRIVER_NAME)) {
 		printk(KERN_ERR "orinoco_plx: I/O resource 0x%lx @ 0x%lx busy\n",
 		       pccard_iolen, pccard_ioaddr);
 		pccard_ioaddr = 0;
@@ -223,28 +231,30 @@
 		goto fail;
 	}
 
+	/* Allocate network device */
 	dev = alloc_orinocodev(0, NULL);
 	if (! dev) {
 		err = -ENOMEM;
 		goto fail;
 	}
 
-	priv = dev->priv;
+	priv = netdev_priv(dev);
 	dev->base_addr = pccard_ioaddr;
 	SET_MODULE_OWNER(dev);
 	SET_NETDEV_DEV(dev, &pdev->dev);
 
-	printk(KERN_DEBUG
-	       "Detected Orinoco/Prism2 PLX device at %s irq:%d, io addr:0x%lx\n",
-	       pci_name(pdev), pdev->irq, pccard_ioaddr);
+	printk(KERN_DEBUG PFX "Detected Orinoco/Prism2 PLX device "
+	       "at %s irq:%d, io addr:0x%lx\n", pci_name(pdev), pdev->irq,
+	       pccard_ioaddr);
 
-	hermes_struct_init(&(priv->hw), dev->base_addr,
-			HERMES_IO, HERMES_16BIT_REGSPACING);
+	hermes_struct_init(&(priv->hw), dev->base_addr, HERMES_IO,
+			   HERMES_16BIT_REGSPACING);
 	pci_set_drvdata(pdev, dev);
 
-	err = request_irq(pdev->irq, orinoco_interrupt, SA_SHIRQ, dev->name, dev);
+	err = request_irq(pdev->irq, orinoco_interrupt, SA_SHIRQ,
+			  dev->name, dev);
 	if (err) {
-		printk(KERN_ERR "orinoco_plx: Error allocating IRQ %d.\n", pdev->irq);
+		printk(KERN_ERR PFX "Error allocating IRQ %d.\n", pdev->irq);
 		err = -EBUSY;
 		goto fail;
 	}
@@ -254,10 +264,10 @@
 	if (err)
 		goto fail;
 
-	return 0;		/* succeeded */
+	return 0;
 
- fail:	
-	printk(KERN_DEBUG "orinoco_plx: init_one(), FAIL!\n");
+ fail:
+	printk(KERN_DEBUG PFX "init_one(), FAIL!\n");
 
 	if (dev) {
 		if (dev->irq)
@@ -281,8 +291,7 @@
 {
 	struct net_device *dev = pci_get_drvdata(pdev);
 
-	if (! dev)
-		BUG();
+	BUG_ON(! dev);
 
 	unregister_netdev(dev);
 		
@@ -305,33 +314,34 @@
 	{0x15e8, 0x0130, PCI_ANY_ID, PCI_ANY_ID,},	/* Correga  - does this work? */
 	{0x1638, 0x1100, PCI_ANY_ID, PCI_ANY_ID,},	/* SMC EZConnect SMC2602W,
 							   Eumitcom PCI WL11000,
-							   Addtron AWA-100*/
+							   Addtron AWA-100 */
 	{0x16ab, 0x1100, PCI_ANY_ID, PCI_ANY_ID,},	/* Global Sun Tech GL24110P */
 	{0x16ab, 0x1101, PCI_ANY_ID, PCI_ANY_ID,},	/* Reported working, but unknown */
 	{0x16ab, 0x1102, PCI_ANY_ID, PCI_ANY_ID,},	/* Linksys WDT11 */
 	{0x16ec, 0x3685, PCI_ANY_ID, PCI_ANY_ID,},	/* USR 2415 */
 	{0xec80, 0xec00, PCI_ANY_ID, PCI_ANY_ID,},	/* Belkin F5D6000 tested by
-							   Brendan W. McAdams <rit@jacked-in.org> */
+							   Brendan W. McAdams <rit AT jacked-in.org> */
 	{0x10b7, 0x7770, PCI_ANY_ID, PCI_ANY_ID,},	/* 3Com AirConnect PCI tested by
-							   Damien Persohn <damien@persohn.net> */
+							   Damien Persohn <damien AT persohn.net> */
 	{0,},
 };
 
 MODULE_DEVICE_TABLE(pci, orinoco_plx_pci_id_table);
 
 static struct pci_driver orinoco_plx_driver = {
-	.name		= "orinoco_plx",
+	.name		= DRIVER_NAME,
 	.id_table	= orinoco_plx_pci_id_table,
 	.probe		= orinoco_plx_init_one,
 	.remove		= __devexit_p(orinoco_plx_remove_one),
 };
 
-static char version[] __initdata = "orinoco_plx.c 0.13e (Daniel Barlow <dan@telent.net>, David Gibson <hermes@gibson.dropbear.id.au>)";
+static char version[] __initdata = DRIVER_NAME " " DRIVER_VERSION
+	" (Pavel Roskin <proski@gnu.org>,"
+	" David Gibson <hermes@gibson.dropbear.id.au>,"
+	" Daniel Barlow <dan@telent.net>)";
 MODULE_AUTHOR("Daniel Barlow <dan@telent.net>");
 MODULE_DESCRIPTION("Driver for wireless LAN cards using the PLX9052 PCI bridge");
-#ifdef MODULE_LICENSE
 MODULE_LICENSE("Dual MPL/GPL");
-#endif
 
 static int __init orinoco_plx_init(void)
 {
@@ -339,7 +349,7 @@
 	return pci_module_init(&orinoco_plx_driver);
 }
 
-void __exit orinoco_plx_exit(void)
+static void __exit orinoco_plx_exit(void)
 {
 	pci_unregister_driver(&orinoco_plx_driver);
 	current->state = TASK_UNINTERRUPTIBLE;
diff -Nru a/drivers/net/wireless/orinoco_tmd.c b/drivers/net/wireless/orinoco_tmd.c
--- a/drivers/net/wireless/orinoco_tmd.c	2004-10-18 14:55:55 -07:00
+++ b/drivers/net/wireless/orinoco_tmd.c	2004-10-18 14:55:55 -07:00
@@ -1,10 +1,10 @@
-/* orinoco_tmd.c 0.01
+/* orinoco_tmd.c
  * 
  * Driver for Prism II devices which would usually be driven by orinoco_cs,
  * but are connected to the PCI bus by a TMD7160. 
  *
- * Copyright (C) 2003 Joerg Dorchain <joerg@dorchain.net>
- * based heavily upon orinoco_plx.c Copyright (C) 2001 Daniel Barlow <dan@telent.net>
+ * Copyright (C) 2003 Joerg Dorchain <joerg AT dorchain.net>
+ * based heavily upon orinoco_plx.c Copyright (C) 2001 Daniel Barlow
  *
  * The contents of this file are subject to the Mozilla Public License
  * Version 1.1 (the "License"); you may not use this file except in
@@ -49,6 +49,9 @@
  * Pheecom sells cards with the TMD chip as "ASIC version"
  */
 
+#define DRIVER_NAME "orinoco_tmd"
+#define PFX DRIVER_NAME ": "
+
 #include <linux/config.h>
 
 #include <linux/module.h>
@@ -66,7 +69,6 @@
 #include <linux/netdevice.h>
 #include <linux/if_arp.h>
 #include <linux/etherdevice.h>
-#include <linux/wireless.h>
 #include <linux/list.h>
 #include <linux/pci.h>
 #include <linux/fcntl.h>
@@ -76,10 +78,7 @@
 #include "hermes.h"
 #include "orinoco.h"
 
-static char dev_info[] = "orinoco_tmd";
-
-#define COR_VALUE     (COR_LEVEL_REQ | COR_FUNC_ENA | COR_FUNC_ENA) /* Enable PC card with level triggered irqs and irq requests */
-
+#define COR_VALUE	(COR_LEVEL_REQ | COR_FUNC_ENA) /* Enable PC card with interrupt in level trigger */
 
 static int orinoco_tmd_init_one(struct pci_dev *pdev,
 				const struct pci_device_id *ent)
@@ -95,11 +94,11 @@
 	if (err)
 		return -EIO;
 
-	printk(KERN_DEBUG "TMD setup\n");
+	printk(KERN_DEBUG PFX "TMD setup\n");
 	pccard_ioaddr = pci_resource_start(pdev, 2);
 	pccard_iolen = pci_resource_len(pdev, 2);
-	if (! request_region(pccard_ioaddr, pccard_iolen, dev_info)) {
-		printk(KERN_ERR "orinoco_tmd: I/O resource at 0x%lx len 0x%lx busy\n",
+	if (! request_region(pccard_ioaddr, pccard_iolen, DRIVER_NAME)) {
+		printk(KERN_ERR PFX "I/O resource at 0x%lx len 0x%lx busy\n",
 			pccard_ioaddr, pccard_iolen);
 		pccard_ioaddr = 0;
 		err = -EBUSY;
@@ -110,34 +109,35 @@
 	mdelay(1);
 	reg = inb(addr);
 	if (reg != COR_VALUE) {
-		printk(KERN_ERR "orinoco_tmd: Error setting TMD COR values %x should be %x\n", reg, COR_VALUE);
+		printk(KERN_ERR PFX "Error setting TMD COR values %x should be %x\n", reg, COR_VALUE);
 		err = -EIO;
 		goto fail;
 	}
 
+	/* Allocate network device */
 	dev = alloc_orinocodev(0, NULL);
 	if (! dev) {
 		err = -ENOMEM;
 		goto fail;
 	}
 
-	priv = dev->priv;
+	priv = netdev_priv(dev);
 	dev->base_addr = pccard_ioaddr;
 	SET_MODULE_OWNER(dev);
 	SET_NETDEV_DEV(dev, &pdev->dev);
 
-	printk(KERN_DEBUG
-	       "Detected Orinoco/Prism2 TMD device at %s irq:%d, io addr:0x%lx\n",
-	       pci_name(pdev), pdev->irq, pccard_ioaddr);
+	printk(KERN_DEBUG PFX "Detected Orinoco/Prism2 TMD device "
+	       "at %s irq:%d, io addr:0x%lx\n", pci_name(pdev), pdev->irq,
+	       pccard_ioaddr);
 
 	hermes_struct_init(&(priv->hw), dev->base_addr,
 			HERMES_IO, HERMES_16BIT_REGSPACING);
 	pci_set_drvdata(pdev, dev);
 
-	err = request_irq(pdev->irq, orinoco_interrupt, SA_SHIRQ, dev->name,
-			  dev);
+	err = request_irq(pdev->irq, orinoco_interrupt, SA_SHIRQ,
+			  dev->name, dev);
 	if (err) {
-		printk(KERN_ERR "orinoco_tmd: Error allocating IRQ %d.\n",
+		printk(KERN_ERR PFX "Error allocating IRQ %d.\n",
 		       pdev->irq);
 		err = -EBUSY;
 		goto fail;
@@ -148,10 +148,10 @@
 	if (err)
 		goto fail;
 
-	return 0;		/* succeeded */
+	return 0;
 
- fail:	
-	printk(KERN_DEBUG "orinoco_tmd: init_one(), FAIL!\n");
+ fail:
+	printk(KERN_DEBUG PFX "init_one(), FAIL!\n");
 
 	if (dev) {
 		if (dev->irq)
@@ -172,8 +172,7 @@
 {
 	struct net_device *dev = pci_get_drvdata(pdev);
 
-	if (! dev)
-		BUG();
+	BUG_ON(! dev);
 
 	unregister_netdev(dev);
 		
@@ -198,18 +197,17 @@
 MODULE_DEVICE_TABLE(pci, orinoco_tmd_pci_id_table);
 
 static struct pci_driver orinoco_tmd_driver = {
-	.name		= "orinoco_tmd",
+	.name		= DRIVER_NAME,
 	.id_table	= orinoco_tmd_pci_id_table,
 	.probe		= orinoco_tmd_init_one,
 	.remove		= __devexit_p(orinoco_tmd_remove_one),
 };
 
-static char version[] __initdata = "orinoco_tmd.c 0.01 (Joerg Dorchain <joerg@dorchain.net>)";
+static char version[] __initdata = DRIVER_NAME " " DRIVER_VERSION
+	" (Joerg Dorchain <joerg@dorchain.net>)";
 MODULE_AUTHOR("Joerg Dorchain <joerg@dorchain.net>");
 MODULE_DESCRIPTION("Driver for wireless LAN cards using the TMD7160 PCI bridge");
-#ifdef MODULE_LICENSE
 MODULE_LICENSE("Dual MPL/GPL");
-#endif
 
 static int __init orinoco_tmd_init(void)
 {
@@ -217,7 +215,7 @@
 	return pci_module_init(&orinoco_tmd_driver);
 }
 
-void __exit orinoco_tmd_exit(void)
+static void __exit orinoco_tmd_exit(void)
 {
 	pci_unregister_driver(&orinoco_tmd_driver);
 	current->state = TASK_UNINTERRUPTIBLE;
diff -Nru a/drivers/net/wireless/prism54/isl_38xx.c b/drivers/net/wireless/prism54/isl_38xx.c
--- a/drivers/net/wireless/prism54/isl_38xx.c	2004-10-18 14:56:31 -07:00
+++ b/drivers/net/wireless/prism54/isl_38xx.c	2004-10-18 14:56:31 -07:00
@@ -44,7 +44,7 @@
  *  register located at offset %ISL38XX_INT_IDENT_REG.
  */
 void
-isl38xx_disable_interrupts(void *device)
+isl38xx_disable_interrupts(void __iomem *device)
 {
 	isl38xx_w32_flush(device, 0x00000000, ISL38XX_INT_EN_REG);
 	udelay(ISL38XX_WRITEIO_DELAY);
@@ -52,7 +52,7 @@
 
 void
 isl38xx_handle_sleep_request(isl38xx_control_block *control_block,
-			     int *powerstate, void *device_base)
+			     int *powerstate, void __iomem *device_base)
 {
 	/* device requests to go into sleep mode
 	 * check whether the transmit queues for data and management are empty */
@@ -88,7 +88,7 @@
 
 void
 isl38xx_handle_wakeup(isl38xx_control_block *control_block,
-		      int *powerstate, void *device_base)
+		      int *powerstate, void __iomem *device_base)
 {
 	/* device is in active state, update the powerstate flag */
 	*powerstate = ISL38XX_PSM_ACTIVE_STATE;
@@ -110,7 +110,7 @@
 }
 
 void
-isl38xx_trigger_device(int asleep, void *device_base)
+isl38xx_trigger_device(int asleep, void __iomem *device_base)
 {
 	struct timeval current_time;
 	u32 reg, counter = 0;
@@ -190,7 +190,7 @@
 }
 
 void
-isl38xx_interface_reset(void *device_base, dma_addr_t host_address)
+isl38xx_interface_reset(void __iomem *device_base, dma_addr_t host_address)
 {
 	u32 reg;
 
@@ -219,7 +219,7 @@
 }
 
 void
-isl38xx_enable_common_interrupts(void *device_base) {
+isl38xx_enable_common_interrupts(void __iomem *device_base) {
 	u32 reg;
 	reg = ( ISL38XX_INT_IDENT_UPDATE | 
 			ISL38XX_INT_IDENT_SLEEP | ISL38XX_INT_IDENT_WAKEUP);
diff -Nru a/drivers/net/wireless/prism54/isl_38xx.h b/drivers/net/wireless/prism54/isl_38xx.h
--- a/drivers/net/wireless/prism54/isl_38xx.h	2004-10-18 14:57:19 -07:00
+++ b/drivers/net/wireless/prism54/isl_38xx.h	2004-10-18 14:57:19 -07:00
@@ -75,7 +75,7 @@
  *  from the %ISL38XX_PCI_POSTING_FLUSH offset.
  */
 static inline void
-isl38xx_w32_flush(void *base, u32 val, unsigned long offset)
+isl38xx_w32_flush(void __iomem *base, u32 val, unsigned long offset)
 {
 	writel(val, base + offset);
 	(void) readl(base + ISL38XX_PCI_POSTING_FLUSH);
@@ -157,13 +157,13 @@
 /* determine number of entries currently in queue */
 int isl38xx_in_queue(isl38xx_control_block *cb, int queue);
 
-void isl38xx_disable_interrupts(void *);
-void isl38xx_enable_common_interrupts(void *);
+void isl38xx_disable_interrupts(void __iomem *);
+void isl38xx_enable_common_interrupts(void __iomem *);
 
 void isl38xx_handle_sleep_request(isl38xx_control_block *, int *,
-				  void *);
-void isl38xx_handle_wakeup(isl38xx_control_block *, int *, void *);
-void isl38xx_trigger_device(int, void *);
-void isl38xx_interface_reset(void *, dma_addr_t);
+				  void __iomem *);
+void isl38xx_handle_wakeup(isl38xx_control_block *, int *, void __iomem *);
+void isl38xx_trigger_device(int, void __iomem *);
+void isl38xx_interface_reset(void __iomem *, dma_addr_t);
 
 #endif				/* _ISL_38XX_H */
diff -Nru a/drivers/net/wireless/prism54/isl_ioctl.c b/drivers/net/wireless/prism54/isl_ioctl.c
--- a/drivers/net/wireless/prism54/isl_ioctl.c	2004-10-18 14:56:28 -07:00
+++ b/drivers/net/wireless/prism54/isl_ioctl.c	2004-10-18 14:56:28 -07:00
@@ -334,9 +334,10 @@
 	int rvalue;
 
 	rvalue = mgt_get_request(priv, DOT11_OID_CHANNEL, 0, NULL, &r);
-
+	fwrq->i = r.u;
+	rvalue |= mgt_get_request(priv, DOT11_OID_FREQUENCY, 0, NULL, &r);
 	fwrq->m = r.u;
-	fwrq->e = 0;
+	fwrq->e = 3;
 
 	return rvalue;
 }
diff -Nru a/drivers/net/wireless/prism54/islpci_dev.c b/drivers/net/wireless/prism54/islpci_dev.c
--- a/drivers/net/wireless/prism54/islpci_dev.c	2004-10-18 14:55:54 -07:00
+++ b/drivers/net/wireless/prism54/islpci_dev.c	2004-10-18 14:55:54 -07:00
@@ -58,7 +58,7 @@
 isl_upload_firmware(islpci_private *priv)
 {
 	u32 reg, rc;
-	void *device_base = priv->device_base;
+	void __iomem *device_base = priv->device_base;
 
 	/* clear the RAMBoot and the Reset bit */
 	reg = readl(device_base + ISL38XX_CTRL_STAT_REG);
@@ -113,7 +113,7 @@
 			    (fw_len >
 			     ISL38XX_MEMORY_WINDOW_SIZE) ?
 			    ISL38XX_MEMORY_WINDOW_SIZE : fw_len;
-			u32 *dev_fw_ptr = device_base + ISL38XX_DIRECT_MEM_WIN;
+			u32 __iomem *dev_fw_ptr = device_base + ISL38XX_DIRECT_MEM_WIN;
 
 			/* set the cards base address for writting the data */
 			isl38xx_w32_flush(device_base, reg,
@@ -183,7 +183,7 @@
 	u32 reg;
 	islpci_private *priv = config;
 	struct net_device *ndev = priv->ndev;
-	void *device = priv->device_base;
+	void __iomem *device = priv->device_base;
 	int powerstate = ISL38XX_PSM_POWERSAVE_STATE;
 
 	/* lock the interrupt handler */
@@ -405,7 +405,7 @@
 static int
 prism54_bring_down(islpci_private *priv)
 {
-	void *device_base = priv->device_base;
+	void __iomem *device_base = priv->device_base;
 	u32 reg;
 	/* we are going to shutdown the device */
 	islpci_set_state(priv, PRV_STATE_PREBOOT);
diff -Nru a/drivers/net/wireless/prism54/islpci_dev.h b/drivers/net/wireless/prism54/islpci_dev.h
--- a/drivers/net/wireless/prism54/islpci_dev.h	2004-10-18 14:56:28 -07:00
+++ b/drivers/net/wireless/prism54/islpci_dev.h	2004-10-18 14:56:28 -07:00
@@ -109,7 +109,7 @@
 	u32 pci_state[16];	/* used for suspend/resume */
 	char firmware[33];
 
-	void *device_base;	/* ioremapped device base address */
+	void __iomem *device_base;	/* ioremapped device base address */
 
 	/* consistent DMA region */
 	void *driver_mem_address;	/* base DMA address */
diff -Nru a/drivers/net/wireless/ray_cs.c b/drivers/net/wireless/ray_cs.c
--- a/drivers/net/wireless/ray_cs.c	2004-10-18 14:56:28 -07:00
+++ b/drivers/net/wireless/ray_cs.c	2004-10-18 14:56:28 -07:00
@@ -54,7 +54,6 @@
 #include <pcmcia/ds.h>
 #include <pcmcia/mem_op.h>
 
-#ifdef CONFIG_NET_PCMCIA_RADIO
 #include <linux/wireless.h>
 
 #include <asm/io.h>
@@ -68,7 +67,6 @@
 typedef struct iw_statistics	iw_stats;
 typedef struct iw_quality	iw_qual;
 typedef u_char	mac_addr[ETH_ALEN];	/* Hardware address */
-#endif	/* CONFIG_NET_PCMCIA_RADIO */
 
 #include "rayctl.h"
 #include "ray_cs.h"
@@ -112,9 +110,9 @@
 static int ray_dev_start_xmit(struct sk_buff *skb, struct net_device *dev);
 static void set_multicast_list(struct net_device *dev);
 static void ray_update_multi_list(struct net_device *dev, int all);
-static int translate_frame(ray_dev_t *local, struct tx_msg *ptx,
+static int translate_frame(ray_dev_t *local, struct tx_msg __iomem *ptx,
                 unsigned char *data, int len);
-static void ray_build_header(ray_dev_t *local, struct tx_msg *ptx, UCHAR msg_type,
+static void ray_build_header(ray_dev_t *local, struct tx_msg __iomem *ptx, UCHAR msg_type,
                 unsigned char *data);
 static void untranslate(ray_dev_t *local, struct sk_buff *skb, int len);
 #if WIRELESS_EXT > 7	/* If wireless extension exist in the kernel */
@@ -140,14 +138,14 @@
 /* Prototypes for interrpt time functions **********************************/
 static irqreturn_t ray_interrupt (int reg, void *dev_id, struct pt_regs *regs);
 static void clear_interrupt(ray_dev_t *local);
-static void rx_deauthenticate(ray_dev_t *local, struct rcs *prcs, 
+static void rx_deauthenticate(ray_dev_t *local, struct rcs __iomem *prcs, 
                        unsigned int pkt_addr, int rx_len);
 static int copy_from_rx_buff(ray_dev_t *local, UCHAR *dest, int pkt_addr, int len);
-static void ray_rx(struct net_device *dev, ray_dev_t *local, struct rcs *prcs);
-static void release_frag_chain(ray_dev_t *local, struct rcs *prcs);
-static void rx_authenticate(ray_dev_t *local, struct rcs *prcs,
+static void ray_rx(struct net_device *dev, ray_dev_t *local, struct rcs __iomem *prcs);
+static void release_frag_chain(ray_dev_t *local, struct rcs __iomem *prcs);
+static void rx_authenticate(ray_dev_t *local, struct rcs __iomem *prcs,
                      unsigned int pkt_addr, int rx_len);
-static void rx_data(struct net_device *dev, struct rcs *prcs, unsigned int pkt_addr, 
+static void rx_data(struct net_device *dev, struct rcs __iomem *prcs, unsigned int pkt_addr, 
              int rx_len);
 static void associate(ray_dev_t *local);
 
@@ -540,7 +538,7 @@
     CS_CHECK(RequestWindow, pcmcia_request_window(&link->handle, &req, &link->win));
     mem.CardOffset = 0x0000; mem.Page = 0;
     CS_CHECK(MapMemPage, pcmcia_map_mem_page(link->win, &mem));
-    local->sram = (UCHAR *)(ioremap(req.Base,req.Size));
+    local->sram = ioremap(req.Base,req.Size);
 
 /*** Set up 16k window for shared memory (receive buffer) ***************/
     req.Attributes = WIN_DATA_WIDTH_8 | WIN_MEMORY_TYPE_CM | WIN_ENABLE | WIN_USE_WAIT;
@@ -550,7 +548,7 @@
     CS_CHECK(RequestWindow, pcmcia_request_window(&link->handle, &req, &local->rmem_handle));
     mem.CardOffset = 0x8000; mem.Page = 0;
     CS_CHECK(MapMemPage, pcmcia_map_mem_page(local->rmem_handle, &mem));
-    local->rmem = (UCHAR *)(ioremap(req.Base,req.Size));
+    local->rmem = ioremap(req.Base,req.Size);
 
 /*** Set up window for attribute memory ***********************************/
     req.Attributes = WIN_DATA_WIDTH_8 | WIN_MEMORY_TYPE_AM | WIN_ENABLE | WIN_USE_WAIT;
@@ -560,7 +558,7 @@
     CS_CHECK(RequestWindow, pcmcia_request_window(&link->handle, &req, &local->amem_handle));
     mem.CardOffset = 0x0000; mem.Page = 0;
     CS_CHECK(MapMemPage, pcmcia_map_mem_page(local->amem_handle, &mem));
-    local->amem = (UCHAR *)(ioremap(req.Base,req.Size));
+    local->amem = ioremap(req.Base,req.Size);
 
     DEBUG(3,"ray_config sram=%p\n",local->sram);
     DEBUG(3,"ray_config rmem=%p\n",local->rmem);
@@ -593,12 +591,30 @@
 
     ray_release(link);
 } /* ray_config */
+
+static inline struct ccs __iomem *ccs_base(ray_dev_t *dev)
+{
+	return dev->sram + CCS_BASE;
+}
+
+static inline struct rcs __iomem *rcs_base(ray_dev_t *dev)
+{
+	/*
+	 * This looks nonsensical, since there is a separate
+	 * RCS_BASE. But the difference between a "struct rcs"
+	 * and a "struct ccs" ends up being in the _index_ off
+	 * the base, so the base pointer is the same for both
+	 * ccs/rcs.
+	 */
+	return dev->sram + CCS_BASE;
+}
+
 /*===========================================================================*/
 static int ray_init(struct net_device *dev)
 {
     int i;
     UCHAR *p;
-    struct ccs *pccs;
+    struct ccs __iomem *pccs;
     ray_dev_t *local = (ray_dev_t *)dev->priv;
     dev_link_t *link = local->finder;
     DEBUG(1, "ray_init(0x%p)\n", dev);
@@ -632,7 +648,7 @@
         local->tib_length = local->startup_res.tib_length;
     DEBUG(2,"ray_init tib_length = 0x%02x\n", local->tib_length);
     /* Initialize CCS's to buffer free state */
-    pccs = (struct ccs *)(local->sram + CCS_BASE);
+    pccs = ccs_base(local);
     for (i=0;  i<NUMBER_OF_CCS;  i++) {
         writeb(CCS_BUFFER_FREE, &(pccs++)->buffer_status);
     }
@@ -661,7 +677,7 @@
 {
     int ccsindex;
     ray_dev_t *local = (ray_dev_t *)dev->priv;
-    struct ccs *pccs;
+    struct ccs __iomem *pccs;
     dev_link_t *link = local->finder;
 
     DEBUG(1,"dl_startup_params entered\n");
@@ -682,7 +698,7 @@
     /* Fill in the CCS fields for the ECF */
     if ((ccsindex = get_free_ccs(local)) < 0) return -1;
     local->dl_param_ccs = ccsindex;
-    pccs = ((struct ccs *)(local->sram + CCS_BASE)) + ccsindex;
+    pccs = ccs_base(local) + ccsindex;
     writeb(CCS_DOWNLOAD_STARTUP_PARAMS, &pccs->cmd);
     DEBUG(2,"dl_startup_params start ccsindex = %d\n", local->dl_param_ccs);
     /* Interrupt the firmware to process the command */
@@ -767,7 +783,7 @@
 static void verify_dl_startup(u_long data)
 {
     ray_dev_t *local = (ray_dev_t *)data;
-    struct ccs *pccs = ((struct ccs *)(local->sram + CCS_BASE)) + local->dl_param_ccs;
+    struct ccs __iomem *pccs = ccs_base(local) + local->dl_param_ccs;
     UCHAR status;
     dev_link_t *link = local->finder;
 
@@ -807,7 +823,7 @@
 static void start_net(u_long data)
 {
     ray_dev_t *local = (ray_dev_t *)data;
-    struct ccs *pccs;
+    struct ccs __iomem *pccs;
     int ccsindex;
     dev_link_t *link = local->finder;
     if (!(link->state & DEV_PRESENT)) {
@@ -816,7 +832,7 @@
     }
     /* Fill in the CCS fields for the ECF */
     if ((ccsindex = get_free_ccs(local)) < 0) return;
-    pccs = ((struct ccs *)(local->sram + CCS_BASE)) + ccsindex;
+    pccs = ccs_base(local) + ccsindex;
     writeb(CCS_START_NETWORK, &pccs->cmd);
     writeb(0, &pccs->var.start_network.update_param);
     /* Interrupt the firmware to process the command */
@@ -834,7 +850,7 @@
 {
     ray_dev_t *local = (ray_dev_t *)data;
 
-    struct ccs *pccs;
+    struct ccs __iomem *pccs;
     int ccsindex;
     dev_link_t *link = local->finder;
     
@@ -844,7 +860,7 @@
     }
     /* Fill in the CCS fields for the ECF */
     if ((ccsindex = get_free_ccs(local)) < 0) return;
-    pccs = ((struct ccs *)(local->sram + CCS_BASE)) + ccsindex;
+    pccs = ccs_base(local) + ccsindex;
     writeb(CCS_JOIN_NETWORK, &pccs->cmd);
     writeb(0, &pccs->var.join_network.update_param);
     writeb(0, &pccs->var.join_network.net_initiated);
@@ -1049,10 +1065,10 @@
                 UCHAR msg_type)
 {
     ray_dev_t *local = (ray_dev_t *)dev->priv;
-    struct ccs *pccs;
+    struct ccs __iomem *pccs;
     int ccsindex;
     int offset;
-    struct tx_msg *ptx; /* Address of xmit buffer in PC space */
+    struct tx_msg __iomem *ptx; /* Address of xmit buffer in PC space */
     short int addr;     /* Address of xmit buffer in card space */
     
     DEBUG(3,"ray_hw_xmit(data=%p, len=%d, dev=%p)\n",data,len,dev);
@@ -1079,7 +1095,7 @@
         local->stats.tx_packets++;
     }
 
-    ptx = (struct tx_msg *)(local->sram + addr);
+    ptx = local->sram + addr;
 
     ray_build_header(local, ptx, msg_type, data);
     if (translate) {
@@ -1092,7 +1108,7 @@
     }
 
     /* fill in the CCS */
-    pccs = ((struct ccs *)(local->sram + CCS_BASE)) + ccsindex;
+    pccs = ccs_base(local) + ccsindex;
     len += TX_HEADER_LENGTH + offset;
     writeb(CCS_TX_REQUEST, &pccs->cmd);
     writeb(addr >> 8, &pccs->var.tx_request.tx_data_ptr[0]);
@@ -1119,21 +1135,21 @@
     return XMIT_OK;
 } /* end ray_hw_xmit */
 /*===========================================================================*/
-static int translate_frame(ray_dev_t *local, struct tx_msg *ptx, unsigned char *data,
+static int translate_frame(ray_dev_t *local, struct tx_msg __iomem *ptx, unsigned char *data,
                     int len)
 {
     unsigned short int proto = ((struct ethhdr *)data)->h_proto;
     if (ntohs(proto) >= 1536) { /* DIX II ethernet frame */
         DEBUG(3,"ray_cs translate_frame DIX II\n");
         /* Copy LLC header to card buffer */
-        memcpy_toio((UCHAR *)&ptx->var, eth2_llc, sizeof(eth2_llc));
-        memcpy_toio( ((UCHAR *)&ptx->var) + sizeof(eth2_llc), (UCHAR *)&proto, 2);
+        memcpy_toio(&ptx->var, eth2_llc, sizeof(eth2_llc));
+        memcpy_toio( ((void __iomem *)&ptx->var) + sizeof(eth2_llc), (UCHAR *)&proto, 2);
         if ((proto == 0xf380) || (proto == 0x3781)) {
             /* This is the selective translation table, only 2 entries */
-            writeb(0xf8, (UCHAR *) &((struct snaphdr_t *)ptx->var)->org[3]);
+            writeb(0xf8, &((struct snaphdr_t __iomem *)ptx->var)->org[3]);
         }
         /* Copy body of ethernet packet without ethernet header */
-        memcpy_toio((UCHAR *)&ptx->var + sizeof(struct snaphdr_t), \
+        memcpy_toio((void __iomem *)&ptx->var + sizeof(struct snaphdr_t), \
                     data + ETH_HLEN,  len - ETH_HLEN);
         return (int) sizeof(struct snaphdr_t) - ETH_HLEN;
     }
@@ -1141,16 +1157,16 @@
         DEBUG(3,"ray_cs translate_frame 802\n");
         if (proto == 0xffff) { /* evil netware IPX 802.3 without LLC */
         DEBUG(3,"ray_cs translate_frame evil IPX\n");
-            memcpy_toio((UCHAR *)&ptx->var, data + ETH_HLEN,  len - ETH_HLEN);
+            memcpy_toio(&ptx->var, data + ETH_HLEN,  len - ETH_HLEN);
             return 0 - ETH_HLEN;
         }
-        memcpy_toio((UCHAR *)&ptx->var, data + ETH_HLEN,  len - ETH_HLEN);
+        memcpy_toio(&ptx->var, data + ETH_HLEN,  len - ETH_HLEN);
         return 0 - ETH_HLEN;
     }
     /* TBD do other frame types */
 } /* end translate_frame */
 /*===========================================================================*/
-static void ray_build_header(ray_dev_t *local, struct tx_msg *ptx, UCHAR msg_type,
+static void ray_build_header(ray_dev_t *local, struct tx_msg __iomem *ptx, UCHAR msg_type,
                 unsigned char *data)
 {
     writeb(PROTOCOL_VER | msg_type, &ptx->mac.frame_ctl_1);
@@ -1633,7 +1649,7 @@
 {
   ray_dev_t *	local = (ray_dev_t *) dev->priv;
   dev_link_t *link = local->finder;
-  struct status *p = (struct status *)(local->sram + STATUS_BASE);
+  struct status __iomem *p = local->sram + STATUS_BASE;
 
   if(local == (ray_dev_t *) NULL)
     return (iw_stats *) NULL;
@@ -1755,7 +1771,7 @@
 static int get_free_tx_ccs(ray_dev_t *local)
 {
     int i;
-    struct ccs *pccs = (struct ccs *)(local->sram + CCS_BASE);
+    struct ccs __iomem *pccs = ccs_base(local);
     dev_link_t *link = local->finder;
 
     if (!(link->state & DEV_PRESENT)) {
@@ -1786,7 +1802,7 @@
 static int get_free_ccs(ray_dev_t *local)
 {
     int i;
-    struct ccs *pccs = (struct ccs *)(local->sram + CCS_BASE);
+    struct ccs __iomem *pccs = ccs_base(local);
     dev_link_t *link = local->finder;
 
     if (!(link->state & DEV_PRESENT)) {
@@ -1863,7 +1879,7 @@
 {
     ray_dev_t *local = (ray_dev_t *)dev->priv;
     dev_link_t *link = local->finder;
-    struct status *p = (struct status *)(local->sram + STATUS_BASE);
+    struct status __iomem *p = local->sram + STATUS_BASE;
     if (!(link->state & DEV_PRESENT)) {
         DEBUG(2,"ray_cs net_device_stats - device not present\n");
         return &local->stats;
@@ -1895,7 +1911,7 @@
     dev_link_t *link = local->finder;
     int ccsindex;
     int i;
-    struct ccs *pccs;
+    struct ccs __iomem *pccs;
 
     if (!(link->state & DEV_PRESENT)) {
         DEBUG(2,"ray_update_parm - device not present\n");
@@ -1907,7 +1923,7 @@
         DEBUG(0,"ray_update_parm - No free ccs\n");
         return;
     }
-    pccs = ((struct ccs *)(local->sram + CCS_BASE)) + ccsindex;
+    pccs = ccs_base(local) + ccsindex;
     writeb(CCS_UPDATE_PARAMS, &pccs->cmd);
     writeb(objid, &pccs->var.update_param.object_id);
     writeb(1, &pccs->var.update_param.number_objects);
@@ -1926,11 +1942,11 @@
 {
     struct dev_mc_list *dmi, **dmip;
     int ccsindex;
-    struct ccs *pccs;
+    struct ccs __iomem *pccs;
     int i = 0;
     ray_dev_t *local = (ray_dev_t *)dev->priv;
     dev_link_t *link = local->finder;
-    UCHAR *p = local->sram + HOST_TO_ECF_BASE;
+    void __iomem *p = local->sram + HOST_TO_ECF_BASE;
 
     if (!(link->state & DEV_PRESENT)) {
         DEBUG(2,"ray_update_multi_list - device not present\n");
@@ -1943,7 +1959,7 @@
         DEBUG(1,"ray_update_multi - No free ccs\n");
         return;
     }
-    pccs = ((struct ccs *)(local->sram + CCS_BASE)) + ccsindex;
+    pccs = ccs_base(local) + ccsindex;
     writeb(CCS_UPDATE_MULTICAST_LIST, &pccs->cmd);
 
     if (all) {
@@ -2011,8 +2027,8 @@
     struct net_device *dev = (struct net_device *)dev_id;
     dev_link_t *link;
     ray_dev_t *local;
-    struct ccs *pccs;
-    struct rcs *prcs;
+    struct ccs __iomem *pccs;
+    struct rcs __iomem *prcs;
     UCHAR rcsindex;
     UCHAR tmp;
     UCHAR cmd;
@@ -2029,7 +2045,7 @@
         DEBUG(2,"ray_cs interrupt from device not present or suspended.\n");
         return IRQ_NONE;
     }
-    rcsindex = readb(&((struct scb *)(local->sram))->rcs_index);
+    rcsindex = readb(&((struct scb __iomem *)(local->sram))->rcs_index);
 
     if (rcsindex >= (NUMBER_OF_CCS + NUMBER_OF_RCS))
     {
@@ -2039,7 +2055,7 @@
     }
     if (rcsindex < NUMBER_OF_CCS) /* If it's a returned CCS */
     {
-        pccs = ((struct ccs *) (local->sram + CCS_BASE)) + rcsindex;
+        pccs = ccs_base(local) + rcsindex;
         cmd = readb(&pccs->cmd);
         status = readb(&pccs->buffer_status);
         switch (cmd)
@@ -2153,7 +2169,7 @@
     }
     else /* It's an RCS */
     {
-        prcs = ((struct rcs *)(local->sram + CCS_BASE)) + rcsindex;
+        prcs = rcs_base(local) + rcsindex;
     
         switch (readb(&prcs->interrupt_id))
         {
@@ -2194,11 +2210,11 @@
     return IRQ_HANDLED;
 } /* ray_interrupt */
 /*===========================================================================*/
-static void ray_rx(struct net_device *dev, ray_dev_t *local, struct rcs *prcs)
+static void ray_rx(struct net_device *dev, ray_dev_t *local, struct rcs __iomem *prcs)
 {
     int rx_len;
     unsigned int pkt_addr;
-    UCHAR *pmsg;
+    void __iomem *pmsg;
     DEBUG(4,"ray_rx process rx packet\n");
 
     /* Calculate address of packet within Rx buffer */
@@ -2248,11 +2264,11 @@
 
 } /* end ray_rx */
 /*===========================================================================*/
-static void rx_data(struct net_device *dev, struct rcs *prcs, unsigned int pkt_addr, 
+static void rx_data(struct net_device *dev, struct rcs __iomem *prcs, unsigned int pkt_addr, 
              int rx_len)
 {
     struct sk_buff *skb = NULL;
-    struct rcs *prcslink = prcs;
+    struct rcs __iomem *prcslink = prcs;
     ray_dev_t *local = dev->priv;
     UCHAR *rx_ptr;
     int total_len;
@@ -2294,7 +2310,7 @@
                 +   readb(&prcslink->var.rx_packet.rx_data_length[1]);
             if (readb(&prcslink->var.rx_packet.next_frag_rcs_index) == 0xFF
                 || tmp < 0) break;
-            prcslink = ((struct rcs *)(local->sram + CCS_BASE))
+            prcslink = rcs_base(local)
                 + readb(&prcslink->link_field);
         } while (1);
 
@@ -2355,7 +2371,7 @@
         prcslink = prcs;
         DEBUG(1,"ray_cs rx_data in fragment loop\n");
         do {
-            prcslink = ((struct rcs *)(local->sram + CCS_BASE))
+            prcslink = rcs_base(local)
                 + readb(&prcslink->var.rx_packet.next_frag_rcs_index);
             rx_len = (( readb(&prcslink->var.rx_packet.rx_data_length[0]) << 8)
                       + readb(&prcslink->var.rx_packet.rx_data_length[1]))
@@ -2529,9 +2545,9 @@
     return length;
 }
 /*===========================================================================*/
-static void release_frag_chain(ray_dev_t *local, struct rcs* prcs)
+static void release_frag_chain(ray_dev_t *local, struct rcs __iomem * prcs)
 {
-    struct rcs *prcslink = prcs;
+    struct rcs __iomem *prcslink = prcs;
     int tmp = 17;
     unsigned rcsindex = readb(&prcs->var.rx_packet.next_frag_rcs_index);
 
@@ -2541,7 +2557,7 @@
             DEBUG(1,"ray_cs interrupt bad rcsindex = 0x%x\n",rcsindex);
             break;      
         }   
-        prcslink = ((struct rcs *)(local->sram + CCS_BASE)) + rcsindex;
+        prcslink = rcs_base(local) + rcsindex;
         rcsindex = readb(&prcslink->var.rx_packet.next_frag_rcs_index);
     }
     writeb(CCS_BUFFER_FREE, &prcslink->buffer_status);
@@ -2569,7 +2585,7 @@
     local->authentication_state = AWAITING_RESPONSE;
 } /* end authenticate */
 /*===========================================================================*/
-static void rx_authenticate(ray_dev_t *local, struct rcs *prcs,
+static void rx_authenticate(ray_dev_t *local, struct rcs __iomem *prcs,
                      unsigned int pkt_addr, int rx_len)
 {
     UCHAR buff[256];
@@ -2614,7 +2630,7 @@
 /*===========================================================================*/
 static void associate(ray_dev_t *local)
 {
-    struct ccs *pccs;
+    struct ccs __iomem *pccs;
     dev_link_t *link = local->finder;
     struct net_device *dev = link->priv;
     int ccsindex;
@@ -2630,7 +2646,7 @@
         return;
     }
     DEBUG(1,"ray_cs Starting association with access point\n");
-    pccs = ((struct ccs *)(local->sram + CCS_BASE)) + ccsindex;
+    pccs = ccs_base(local) + ccsindex;
     /* fill in the CCS */
     writeb(CCS_START_ASSOCIATION, &pccs->cmd);
     /* Interrupt the firmware to process the command */
@@ -2650,7 +2666,7 @@
 
 } /* end associate */
 /*===========================================================================*/
-static void rx_deauthenticate(ray_dev_t *local, struct rcs *prcs, 
+static void rx_deauthenticate(ray_dev_t *local, struct rcs __iomem *prcs, 
                        unsigned int pkt_addr, int rx_len)
 {
 /*  UCHAR buff[256];
@@ -2798,8 +2814,8 @@
 static int build_auth_frame(ray_dev_t *local, UCHAR *dest, int auth_type)
 {
     int addr;
-    struct ccs *pccs;
-    struct tx_msg *ptx;
+    struct ccs __iomem *pccs;
+    struct tx_msg __iomem *ptx;
     int ccsindex;
 
     /* If no tx buffers available, return */
@@ -2809,7 +2825,7 @@
         return -1;
     }
 
-    pccs = ((struct ccs *)(local->sram + CCS_BASE)) + ccsindex;
+    pccs = ccs_base(local) + ccsindex;
 
     /* Address in card space */
     addr = TX_BUF_BASE + (ccsindex << 11);
@@ -2821,7 +2837,7 @@
     writeb(TX_AUTHENTICATE_LENGTH_LSB,pccs->var.tx_request.tx_data_length + 1);
     writeb(0, &pccs->var.tx_request.pow_sav_mode);
 
-    ptx = (struct tx_msg *)(local->sram + addr);
+    ptx = local->sram + addr;
     /* fill in the mac header */
     writeb(PROTOCOL_VER | AUTHENTIC_TYPE, &ptx->mac.frame_ctl_1);
     writeb(0, &ptx->mac.frame_ctl_2);
@@ -2931,15 +2947,6 @@
 {
     DEBUG(0, "ray_cs: cleanup_module\n");
 
-
-#ifdef CONFIG_PROC_FS
-    remove_proc_entry("ray_cs", proc_root_driver);
-#endif
-
-    pcmcia_unregister_driver(&ray_driver);
-    while (dev_list != NULL)
-        ray_detach(dev_list);
-
 #ifdef CONFIG_PROC_FS
     remove_proc_entry("driver/ray_cs/ray_cs", NULL);
     remove_proc_entry("driver/ray_cs/essid", NULL);
@@ -2947,6 +2954,10 @@
     remove_proc_entry("driver/ray_cs/translate", NULL);
     remove_proc_entry("driver/ray_cs", NULL);
 #endif
+
+    pcmcia_unregister_driver(&ray_driver);
+    while (dev_list != NULL)
+        ray_detach(dev_list);
 } /* exit_ray_cs */
 
 module_init(init_ray_cs);
diff -Nru a/drivers/net/wireless/ray_cs.h b/drivers/net/wireless/ray_cs.h
--- a/drivers/net/wireless/ray_cs.h	2004-10-18 14:56:50 -07:00
+++ b/drivers/net/wireless/ray_cs.h	2004-10-18 14:56:50 -07:00
@@ -28,9 +28,9 @@
     dev_node_t  node;
     window_handle_t amem_handle;   /* handle to window for attribute memory  */
     window_handle_t rmem_handle;   /* handle to window for rx buffer on card */
-    UCHAR *sram;                   /* pointer to beginning of shared RAM     */
-    UCHAR *amem;                   /* pointer to attribute mem window        */
-    UCHAR *rmem;                   /* pointer to receive buffer window       */
+    void __iomem *sram;            /* pointer to beginning of shared RAM     */
+    void __iomem *amem;            /* pointer to attribute mem window        */
+    void __iomem *rmem;            /* pointer to receive buffer window       */
     dev_link_t *finder;            /* pointer back to dev_link_t for card    */
     struct timer_list timer;
     long tx_ccs_lock;
diff -Nru a/drivers/net/wireless/strip.c b/drivers/net/wireless/strip.c
--- a/drivers/net/wireless/strip.c	2004-10-18 14:56:48 -07:00
+++ b/drivers/net/wireless/strip.c	2004-10-18 14:56:48 -07:00
@@ -106,6 +106,7 @@
 #include <linux/seq_file.h>
 #include <linux/serial.h>
 #include <linux/serialP.h>
+#include <linux/rcupdate.h>
 #include <net/arp.h>
 
 #include <linux/ip.h>
@@ -1348,14 +1349,17 @@
 	 */
 	if (haddr.c[0] == 0xFF) {
 		u32 brd = 0;
-		struct in_device *in_dev = in_dev_get(strip_info->dev);
-		if (in_dev == NULL)
+		struct in_device *in_dev;
+
+		rcu_read_lock();
+		in_dev = __in_dev_get(strip_info->dev);
+		if (in_dev == NULL) {
+			rcu_read_unlock();
 			return NULL;
-		read_lock(&in_dev->lock);
+		}
 		if (in_dev->ifa_list)
 			brd = in_dev->ifa_list->ifa_broadcast;
-		read_unlock(&in_dev->lock);
-		in_dev_put(in_dev);
+		rcu_read_unlock();
 
 		/* arp_query returns 1 if it succeeds in looking up the address, 0 if it fails */
 		if (!arp_query(haddr.c, brd, strip_info->dev)) {
@@ -1500,17 +1504,18 @@
 	}
 
 	if (1) {
-		struct in_device *in_dev = in_dev_get(strip_info->dev);
+		struct in_device *in_dev;
+
 		brd = addr = 0;
+		rcu_read_lock();
+		in_dev = __in_dev_get(strip_info->dev);
 		if (in_dev) {
-			read_lock(&in_dev->lock);
 			if (in_dev->ifa_list) {
 				brd = in_dev->ifa_list->ifa_broadcast;
 				addr = in_dev->ifa_list->ifa_local;
 			}
-			read_unlock(&in_dev->lock);
-			in_dev_put(in_dev);
 		}
+		rcu_read_unlock();
 	}
 
 
@@ -2661,8 +2666,6 @@
 	tty->disc_data = strip_info;
 	if (tty->driver->flush_buffer)
 		tty->driver->flush_buffer(tty);
-	if (tty->ldisc.flush_buffer)
-		tty->ldisc.flush_buffer(tty);
 
 	/*
 	 * Restore default settings
diff -Nru a/drivers/net/wireless/wavelan.c b/drivers/net/wireless/wavelan.c
--- a/drivers/net/wireless/wavelan.c	2004-10-18 14:57:03 -07:00
+++ b/drivers/net/wireless/wavelan.c	2004-10-18 14:57:03 -07:00
@@ -3822,17 +3822,18 @@
 	if ((hasr & HASR_MMC_INTR) && (lp->hacr & HACR_MMC_INT_ENABLE)) {
 		u8 dce_status;
 
-#ifdef DEBUG_INTERRUPT_ERROR
-		printk(KERN_INFO
-		       "%s: wavelan_interrupt(): unexpected mmc interrupt: status 0x%04x.\n",
-		       dev->name, dce_status);
-#endif
 		/*
 		 * Interrupt from the modem management controller.
 		 * This will clear it -- ignored for now.
 		 */
 		mmc_read(ioaddr, mmroff(0, mmr_dce_status), &dce_status,
 			 sizeof(dce_status));
+
+#ifdef DEBUG_INTERRUPT_ERROR
+		printk(KERN_INFO
+		       "%s: wavelan_interrupt(): unexpected mmc interrupt: status 0x%04x.\n",
+		       dev->name, dce_status);
+#endif
 	}
 
 	/* Check if not controller interrupt */
diff -Nru a/drivers/oprofile/buffer_sync.c b/drivers/oprofile/buffer_sync.c
--- a/drivers/oprofile/buffer_sync.c	2004-10-18 14:56:27 -07:00
+++ b/drivers/oprofile/buffer_sync.c	2004-10-18 14:56:27 -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_work();
+	/* 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_work();
 
-	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();
 }
 
  
@@ -337,40 +339,25 @@
 	}
 }
  
- 
+
 static void release_mm(struct mm_struct * mm)
 {
-	if (mm)
-		up_read(&mm->mmap_sem);
+	if (!mm)
+		return;
+	up_read(&mm->mmap_sem);
+	mmput(mm);
 }
 
 
-/* Take the task's mmap_sem to protect ourselves from
- * races when we do lookup_dcookie().
- */
 static struct mm_struct * take_tasks_mm(struct task_struct * task)
 {
-	struct mm_struct * mm;
-       
-	/* Subtle. We don't need to keep a reference to this task's mm,
-	 * because, for the mm to be freed on another CPU, that would have
-	 * to go through the task exit notifier, which ends up sleeping
-	 * on the buffer_sem we hold, so we end up with mutual exclusion
-	 * anyway.
-	 */
-	task_lock(task);
-	mm = task->mm;
-	task_unlock(task);
- 
-	if (mm) {
-		/* needed to walk the task's VMAs */
+	struct mm_struct * mm = get_task_mm(task);
+	if (mm)
 		down_read(&mm->mmap_sem);
-	}
- 
 	return mm;
 }
- 
- 
+
+
 static inline int is_ctx_switch(unsigned long val)
 {
 	return val == ~0UL;
@@ -417,24 +404,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 +505,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	2004-10-18 14:55:54 -07:00
+++ b/drivers/oprofile/buffer_sync.h	2004-10-18 14:55:54 -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-10-18 14:55:54 -07:00
+++ b/drivers/oprofile/cpu_buffer.c	2004-10-18 14:55:54 -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,23 @@
 #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 *);
+
+#define DEFAULT_TIMER_EXPIRE (HZ / 10)
+int work_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)) 
-			continue;
- 
-		vfree(b->buffer);
+	for_each_online_cpu(i) {
+		if (cpu_buffer[i].buffer)
+			vfree(cpu_buffer[i].buffer);
 	}
 }
  
@@ -47,12 +49,9 @@
  
 	unsigned long buffer_size = fs_cpu_buffer_size;
  
-	for (i=0; i < NR_CPUS; ++i) {
+	for_each_online_cpu(i) {
 		struct oprofile_cpu_buffer * b = &cpu_buffer[i];
  
-		if (!cpu_possible(i)) 
-			continue;
- 
 		b->buffer = vmalloc(sizeof(struct op_sample) * buffer_size);
 		if (!b->buffer)
 			goto fail;
@@ -64,9 +63,11 @@
 		b->head_pos = 0;
 		b->sample_received = 0;
 		b->sample_lost_overflow = 0;
-		b->sample_lost_task_exit = 0;
+		b->cpu = i;
+		INIT_WORK(&b->work, wq_sync_buffer, b);
 	}
 	return 0;
+
 fail:
 	__free_cpu_buffers(i);
 	return -ENOMEM;
@@ -79,6 +80,40 @@
 }
 
 
+void start_cpu_work(void)
+{
+	int i;
+
+	work_enabled = 1;
+
+	for_each_online_cpu(i) {
+		struct oprofile_cpu_buffer * b = &cpu_buffer[i];
+
+		/*
+		 * Spread the work by 1 jiffy per cpu so they dont all
+		 * fire at once.
+		 */
+		schedule_delayed_work_on(i, &b->work, DEFAULT_TIMER_EXPIRE + i);
+	}
+}
+
+
+void end_cpu_work(void)
+{
+	int i;
+
+	work_enabled = 0;
+
+	for_each_online_cpu(i) {
+		struct oprofile_cpu_buffer * b = &cpu_buffer[i];
+
+		cancel_delayed_work(&b->work);
+	}
+
+	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 +180,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 +200,26 @@
 	 */
 	cpu_buf->last_is_kernel = -1;
 	cpu_buf->last_task = NULL;
+}
+
+
+/*
+ * This serves to avoid cpu buffer overflow, and makes sure
+ * the task mortuary progresses
+ *
+ * By using schedule_delayed_work_on and then schedule_delayed_work
+ * we guarantee this will stay on the correct 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 work if we're shutting down */
+	if (work_enabled)
+		schedule_delayed_work(&b->work, DEFAULT_TIMER_EXPIRE);
 }
diff -Nru a/drivers/oprofile/cpu_buffer.h b/drivers/oprofile/cpu_buffer.h
--- a/drivers/oprofile/cpu_buffer.h	2004-10-18 14:57:04 -07:00
+++ b/drivers/oprofile/cpu_buffer.h	2004-10-18 14:57:04 -07:00
@@ -12,15 +12,17 @@
 
 #include <linux/types.h>
 #include <linux/spinlock.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_work(void);
+void end_cpu_work(void);
+
 /* CPU buffer is composed of such entries (which are
  * also used for context switch notes)
  */
@@ -38,11 +40,12 @@
 	struct op_sample * buffer;
 	unsigned long sample_received;
 	unsigned long sample_lost_overflow;
-	unsigned long sample_lost_task_exit;
+	int cpu;
+	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-10-18 14:56:48 -07:00
+++ b/drivers/oprofile/oprofile_stats.c	2004-10-18 14:56:48 -07:00
@@ -22,14 +22,10 @@
 	struct oprofile_cpu_buffer * cpu_buf; 
 	int i;
  
-	for (i = 0; i < NR_CPUS; ++i) {
-		if (!cpu_possible(i))
-			continue;
-
+	for_each_cpu(i) {
 		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);
@@ -50,10 +46,7 @@
 	if (!dir)
 		return;
 
-	for (i = 0; i < NR_CPUS; ++i) {
-		if (!cpu_possible(i))
-			continue;
-
+	for_each_cpu(i) {
 		cpu_buf = &cpu_buffer[i]; 
 		snprintf(buf, 10, "cpu%d", i);
 		cpudir = oprofilefs_mkdir(sb, dir, buf);
@@ -66,8 +59,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/oprofile/timer_int.c b/drivers/oprofile/timer_int.c
--- a/drivers/oprofile/timer_int.c	2004-10-18 14:56:28 -07:00
+++ b/drivers/oprofile/timer_int.c	2004-10-18 14:56:28 -07:00
@@ -19,7 +19,7 @@
 {
 	struct pt_regs * regs = (struct pt_regs *)data;
 	int cpu = smp_processor_id();
-	unsigned long eip = instruction_pointer(regs);
+	unsigned long eip = profile_pc(regs);
  
 	oprofile_add_sample(eip, !user_mode(regs), 0, cpu);
 	return 0;
diff -Nru a/drivers/parisc/lasi.c b/drivers/parisc/lasi.c
--- a/drivers/parisc/lasi.c	2004-10-18 14:56:48 -07:00
+++ b/drivers/parisc/lasi.c	2004-10-18 14:56:48 -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-10-18 14:56:34 -07:00
+++ b/drivers/parisc/superio.c	2004-10-18 14:56:34 -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>
  *
@@ -484,6 +484,7 @@
 	pci_read_config_byte(pdev, PCI_CLASS_PROG, &prog);
 	printk("PCI: Enabled native mode for NS87415 (pif=0x%x)\n", prog);
 }
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_NS, PCI_DEVICE_ID_NS_87415, superio_fixup_pci);
 
 /* Because of a defect in Super I/O, all reads of the PCI DMA status 
  * registers, IDE status register and the IDE select register need to be 
diff -Nru a/drivers/parport/parport_pc.c b/drivers/parport/parport_pc.c
--- a/drivers/parport/parport_pc.c	2004-10-18 14:57:04 -07:00
+++ b/drivers/parport/parport_pc.c	2004-10-18 14:57:04 -07:00
@@ -1194,7 +1194,7 @@
 
 #ifdef CONFIG_PARPORT_PC_SUPERIO
 /* Super-IO chipset detection, Winbond, SMSC */
-static void __devinit show_parconfig_smsc37c669(int io, int key)
+static int __devinit show_parconfig_smsc37c669(int io, int key)
 {
 	int cr1,cr4,cra,cr23,cr26,cr27,i=0;
 	static const char *modes[]={ "SPP and Bidirectional (PS/2)",	
@@ -1261,17 +1261,26 @@
 					superios[i].io = 0x278;
 					superios[i].irq = 5;
 			}
+			if (io != superios[i].io) {
+				/* how many bytes? */
+				if (!request_region(superios[i].io, 3, "smsc parport")) {
+					superios[i].io = 0;
+					return 0;
+				}
+			}
 			d=(cr26 &0x0f);
 			if((d==1) || (d==3)) 
 				superios[i].dma= d;
 			else
 				superios[i].dma= PARPORT_DMA_NONE;
+			return 1;
 		}
  	}
+	return 0;
 }
 
 
-static void __devinit show_parconfig_winbond(int io, int key)
+static int __devinit show_parconfig_winbond(int io, int key)
 {
 	int cr30,cr60,cr61,cr70,cr74,crf0,i=0;
 	static const char *modes[] = {
@@ -1327,14 +1336,23 @@
 			printk(KERN_INFO "Super-IO: too many chips!\n");
 		else {
 			superios[i].io = (cr60<<8)|cr61;
+			if (io != superios[i].io) {
+				/* how many bytes? */
+				if (!request_region(superios[i].io, 3, "winbond parport")) {
+					superios[i].io = 0;
+					return 0;
+				}
+			}
 			superios[i].irq = cr70&0x0f;
 			superios[i].dma = (((cr74 & 0x07) > 3) ?
 					   PARPORT_DMA_NONE : (cr74 & 0x07));
+			return 1;
 		}
 	}
+	return 0;
 }
 
-static void __devinit decode_winbond(int efer, int key, int devid, int devrev, int oldid)
+static int __devinit decode_winbond(int efer, int key, int devid, int devrev, int oldid)
 {
 	const char *type = "unknown";
 	int id,progif=2;
@@ -1342,7 +1360,7 @@
 	if (devid == devrev)
 		/* simple heuristics, we happened to read some
                    non-winbond register */
-		return;
+		return 0;
 
 	id=(devid<<8) | devrev;
 
@@ -1367,19 +1385,20 @@
 		       efer, key, devid, devrev, oldid, type);
 
 	if (progif == 2)
-		show_parconfig_winbond(efer,key);
+		return show_parconfig_winbond(efer,key);
+	return 0;
 }
 
-static void __devinit decode_smsc(int efer, int key, int devid, int devrev)
+static int __devinit decode_smsc(int efer, int key, int devid, int devrev)
 {
         const char *type = "unknown";
-	void (*func)(int io, int key);
+	int (*func)(int io, int key);
         int id;
 
         if (devid == devrev)
 		/* simple heuristics, we happened to read some
                    non-smsc register */
-		return;
+		return 0;
 
 	func=NULL;
         id=(devid<<8) | devrev;
@@ -1395,7 +1414,8 @@
 		       efer, key, devid, devrev, type);
 
 	if (func)
-		func(efer,key);
+		return func(efer,key);
+	return 0;
 }
 
 
@@ -1403,6 +1423,9 @@
 {
 	int devid,devrev,oldid,x_devid,x_devrev,x_oldid;
 
+	if (!request_region(io, 3, __FUNCTION__))
+		return;
+
 	/* First probe without key */
 	outb(0x20,io);
 	x_devid=inb(io+1);
@@ -1423,15 +1446,21 @@
 	outb(0xaa,io);    /* Magic Seal */
 
 	if ((x_devid == devid) && (x_devrev == devrev) && (x_oldid == oldid))
-		return; /* protection against false positives */
+		goto out; /* protection against false positives */
 
-	decode_winbond(io,key,devid,devrev,oldid);
+	if (decode_winbond(io,key,devid,devrev,oldid));
+		return;
+out:
+	release_region(io, 3);
 }
 
 static void __devinit winbond_check2(int io,int key)
 {
         int devid,devrev,oldid,x_devid,x_devrev,x_oldid;
 
+	if (!request_region(io, 3, __FUNCTION__))
+		return;
+
 	/* First probe without the key */
 	outb(0x20,io+2);
 	x_devid=inb(io+2);
@@ -1451,15 +1480,21 @@
         outb(0xaa,io);    /* Magic Seal */
 
 	if ((x_devid == devid) && (x_devrev == devrev) && (x_oldid == oldid))
-		return; /* protection against false positives */
+		goto out; /* protection against false positives */
 
-        decode_winbond(io,key,devid,devrev,oldid);
+        if (decode_winbond(io,key,devid,devrev,oldid))
+		return;
+out:
+	release_region(io, 3);
 }
 
 static void __devinit smsc_check(int io, int key)
 {
         int id,rev,oldid,oldrev,x_id,x_rev,x_oldid,x_oldrev;
 
+	if (!request_region(io, 3, __FUNCTION__))
+		return;
+
 	/* First probe without the key */
 	outb(0x0d,io);
 	x_oldid=inb(io+1);
@@ -1485,9 +1520,12 @@
 
 	if ((x_id == id) && (x_oldrev == oldrev) &&
 	    (x_oldid == oldid) && (x_rev == rev))
-		return; /* protection against false positives */
+		goto out; /* protection against false positives */
 
-        decode_smsc(io,key,oldid,oldrev);
+        if (decode_smsc(io,key,oldid,oldrev))
+		return;
+out:
+	release_region(io, 3);
 }
 
 
@@ -2636,6 +2674,10 @@
 	netmos_9805,
 	netmos_9815,
 	netmos_9855,
+	netmos_9735,
+	netmos_9835,
+	netmos_9755,
+	netmos_9715
 };
 
 
@@ -2709,6 +2751,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 +2832,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/Makefile b/drivers/pci/Makefile
--- a/drivers/pci/Makefile	2004-10-18 14:57:03 -07:00
+++ b/drivers/pci/Makefile	2004-10-18 14:57:03 -07:00
@@ -35,7 +35,7 @@
 obj-y += syscall.o
 endif
 
-host-progs := gen-devlist
+hostprogs-y := gen-devlist
 
 # Dependencies on generated files need to be listed explicitly
 $(obj)/names.o: $(obj)/devlist.h $(obj)/classlist.h
diff -Nru a/drivers/pci/hotplug/Kconfig b/drivers/pci/hotplug/Kconfig
--- a/drivers/pci/hotplug/Kconfig	2004-10-18 14:57:20 -07:00
+++ b/drivers/pci/hotplug/Kconfig	2004-10-18 14:57:20 -07:00
@@ -88,6 +88,18 @@
 
 	  When in doubt, say N.
 
+config HOTPLUG_PCI_ACPI_IBM
+	tristate "ACPI PCI Hotplug driver IBM extensions"
+	depends on HOTPLUG_PCI_ACPI
+	help
+	  Say Y here if you have an IBM system that supports PCI Hotplug using
+	  ACPI.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called acpiphp_ibm.
+
+	  When in doubt, say N.
+
 config HOTPLUG_PCI_CPCI
 	bool "CompactPCI Hotplug driver"
 	depends on HOTPLUG_PCI
diff -Nru a/drivers/pci/hotplug/Makefile b/drivers/pci/hotplug/Makefile
--- a/drivers/pci/hotplug/Makefile	2004-10-18 14:56:48 -07:00
+++ b/drivers/pci/hotplug/Makefile	2004-10-18 14:56:48 -07:00
@@ -7,6 +7,7 @@
 obj-$(CONFIG_HOTPLUG_PCI_COMPAQ)	+= cpqphp.o
 obj-$(CONFIG_HOTPLUG_PCI_IBM)		+= ibmphp.o
 obj-$(CONFIG_HOTPLUG_PCI_ACPI)		+= acpiphp.o
+obj-$(CONFIG_HOTPLUG_PCI_ACPI_IBM)	+= acpiphp_ibm.o
 obj-$(CONFIG_HOTPLUG_PCI_CPCI_ZT5550)	+= cpcihp_zt5550.o
 obj-$(CONFIG_HOTPLUG_PCI_CPCI_GENERIC)	+= cpcihp_generic.o
 obj-$(CONFIG_HOTPLUG_PCI_PCIE)		+= pciehp.o
diff -Nru a/drivers/pci/hotplug/acpiphp.h b/drivers/pci/hotplug/acpiphp.h
--- a/drivers/pci/hotplug/acpiphp.h	2004-10-18 14:57:04 -07:00
+++ b/drivers/pci/hotplug/acpiphp.h	2004-10-18 14:57:04 -07:00
@@ -171,6 +171,18 @@
 	struct pci_resource *bus_head;
 };
 
+/**
+ * struct acpiphp_attention_info - device specific attention registration
+ *
+ * ACPI has no generic method of setting/getting attention status
+ * this allows for device specific driver registration
+ */
+struct acpiphp_attention_info
+{
+	int (*set_attn)(struct hotplug_slot *slot, u8 status);
+	int (*get_attn)(struct hotplug_slot *slot, u8 *status);
+	struct module *owner;
+};
 
 /* PCI bus bridge HID */
 #define ACPI_PCI_HOST_HID		"PNP0A03"
@@ -211,6 +223,10 @@
 #define FUNC_HAS_PS3		(0x00000080)
 
 /* function prototypes */
+
+/* acpiphp_core.c */
+extern int acpiphp_register_attention(struct acpiphp_attention_info*info);
+extern int acpiphp_unregister_attention(struct acpiphp_attention_info *info);
 
 /* acpiphp_glue.c */
 extern int acpiphp_glue_init (void);
diff -Nru a/drivers/pci/hotplug/acpiphp_core.c b/drivers/pci/hotplug/acpiphp_core.c
--- a/drivers/pci/hotplug/acpiphp_core.c	2004-10-18 14:56:33 -07:00
+++ b/drivers/pci/hotplug/acpiphp_core.c	2004-10-18 14:56:33 -07:00
@@ -51,6 +51,7 @@
 
 /* local variables */
 static int num_slots;
+static struct acpiphp_attention_info *attention_info;
 
 #define DRIVER_VERSION	"0.4"
 #define DRIVER_AUTHOR	"Greg Kroah-Hartman <gregkh@us.ibm.com>, Takayoshi Kochi <t-kochi@bq.jp.nec.com>"
@@ -60,12 +61,17 @@
 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);
+EXPORT_SYMBOL_GPL(acpiphp_unregister_attention);
 
 static int enable_slot		(struct hotplug_slot *slot);
 static int disable_slot		(struct hotplug_slot *slot);
 static int set_attention_status (struct hotplug_slot *slot, u8 value);
 static int get_power_status	(struct hotplug_slot *slot, u8 *value);
+static int get_attention_status (struct hotplug_slot *slot, u8 *value);
 static int get_address		(struct hotplug_slot *slot, u32 *value);
 static int get_latch_status	(struct hotplug_slot *slot, u8 *value);
 static int get_adapter_status	(struct hotplug_slot *slot, u8 *value);
@@ -76,11 +82,54 @@
 	.disable_slot		= disable_slot,
 	.set_attention_status	= set_attention_status,
 	.get_power_status	= get_power_status,
+	.get_attention_status	= get_attention_status,
 	.get_latch_status	= get_latch_status,
 	.get_adapter_status	= get_adapter_status,
 	.get_address		= get_address,
 };
 
+
+/**
+ * acpiphp_register_attention - set attention LED callback
+ * @info: must be completely filled with LED callbacks
+ *
+ * Description: this is used to register a hardware specific ACPI
+ * driver that manipulates the attention LED.  All the fields in
+ * info must be set.
+ **/
+int acpiphp_register_attention(struct acpiphp_attention_info *info)
+{
+	int retval = -EINVAL;
+
+	if (info && info->owner && info->set_attn &&
+			info->get_attn && !attention_info) {
+		retval = 0;
+		attention_info = info;
+	}
+	return retval;
+}
+
+
+/**
+ * acpiphp_unregister_attention - unset attention LED callback
+ * @info: must match the pointer used to register
+ *
+ * Description: this is used to un-register a hardware specific acpi
+ * driver that manipulates the attention LED.  The pointer to the 
+ * info struct must be the same as the one used to set it.
+ **/
+int acpiphp_unregister_attention(struct acpiphp_attention_info *info)
+{
+	int retval = -EINVAL;
+
+	if (info && attention_info == info) {
+		attention_info = NULL;
+		retval = 0;
+	}
+	return retval;
+}
+
+
 /**
  * enable_slot - power on and enable a slot
  * @hotplug_slot: slot to enable
@@ -117,33 +166,29 @@
 }
 
 
-/**
- * set_attention_status - set attention LED
- *
- * TBD:
- * ACPI doesn't have known method to manipulate
- * attention status LED.
- *
- */
-static int set_attention_status(struct hotplug_slot *hotplug_slot, u8 status)
-{
-	dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name);
-
-	switch (status) {
-		case 0:
-			/* FIXME turn light off */
-			hotplug_slot->info->attention_status = 0;
-			break;
-
-		case 1:
-		default:
-			/* FIXME turn light on */
-			hotplug_slot->info->attention_status = 1;
-			break;
-	}
-
-	return 0;
-}
+ /**
+  * set_attention_status - set attention LED
+ * @hotplug_slot: slot to set attention LED on
+ * @status: value to set attention LED to (0 or 1)
+ *
+ * attention status LED, so we use a callback that
+ * was registered with us.  This allows hardware specific
+ * ACPI implementations to blink the light for us.
+ **/
+ static int set_attention_status(struct hotplug_slot *hotplug_slot, u8 status)
+ {
+	int retval = -ENODEV;
+
+ 	dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name);
+ 
+	if (attention_info && try_module_get(attention_info->owner)) {
+		retval = attention_info->set_attn(hotplug_slot, status);
+		module_put(attention_info->owner);
+	} else
+		attention_info = NULL;
+	return retval;
+ }
+ 
 
 /**
  * get_power_status - get power status of a slot
@@ -165,6 +210,32 @@
 	return 0;
 }
 
+
+ /**
+ * get_attention_status - get attention LED status
+ * @hotplug_slot: slot to get status from
+ * @value: returns with value of attention LED
+ *
+ * ACPI doesn't have known method to determine the state
+ * of the attention status LED, so we use a callback that
+ * was registered with us.  This allows hardware specific
+ * ACPI implementations to determine its state
+ **/
+static int get_attention_status(struct hotplug_slot *hotplug_slot, u8 *value)
+{
+	int retval = -EINVAL;
+
+	dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name);
+
+	if (attention_info && try_module_get(attention_info->owner)) {
+		retval = attention_info->get_attn(hotplug_slot, value);
+		module_put(attention_info->owner);
+	} else
+		attention_info = NULL;
+	return retval;
+}
+
+
 /**
  * get_latch_status - get latch status of a slot
  * @hotplug_slot: slot to get status
@@ -307,7 +378,7 @@
 
 		slot->acpi_slot = get_slot_from_id(i);
 		slot->hotplug_slot->info->power_status = acpiphp_get_power_status(slot->acpi_slot);
-		slot->hotplug_slot->info->attention_status = acpiphp_get_attention_status(slot->acpi_slot);
+		slot->hotplug_slot->info->attention_status = 0;
 		slot->hotplug_slot->info->latch_status = acpiphp_get_latch_status(slot->acpi_slot);
 		slot->hotplug_slot->info->adapter_status = acpiphp_get_adapter_status(slot->acpi_slot);
 		slot->hotplug_slot->info->max_bus_speed = PCI_SPEED_UNKNOWN;
diff -Nru a/drivers/pci/hotplug/acpiphp_glue.c b/drivers/pci/hotplug/acpiphp_glue.c
--- a/drivers/pci/hotplug/acpiphp_glue.c	2004-10-18 14:56:28 -07:00
+++ b/drivers/pci/hotplug/acpiphp_glue.c	2004-10-18 14:56:28 -07:00
@@ -1302,20 +1302,6 @@
 
 
 /*
- * attention LED ON: 1
- *		OFF: 0
- *
- * TBD
- * no direct attention led status information via ACPI
- *
- */
-u8 acpiphp_get_attention_status(struct acpiphp_slot *slot)
-{
-	return 0;
-}
-
-
-/*
  * latch closed:  1
  * latch   open:  0
  */
diff -Nru a/drivers/pci/hotplug/acpiphp_ibm.c b/drivers/pci/hotplug/acpiphp_ibm.c
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/drivers/pci/hotplug/acpiphp_ibm.c	2004-10-18 14:57:24 -07:00
@@ -0,0 +1,474 @@
+/*
+ * ACPI PCI Hot Plug IBM Extension
+ *
+ * Copyright (C) 2004 Vernon Mauery <vernux@us.ibm.com>
+ * Copyright (C) 2004 IBM Corp.
+ *
+ * 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, GOOD TITLE or
+ * NON INFRINGEMENT.  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.
+ *
+ * Send feedback to <vernux@us.ibm.com>
+ *
+ */
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <acpi/acpi_bus.h>
+#include <linux/sysfs.h>
+#include <linux/kobject.h>
+#include <asm/uaccess.h>
+#include <linux/moduleparam.h>
+
+#include "acpiphp.h"
+#include "pci_hotplug.h"
+
+#define DRIVER_VERSION	"1.0.1"
+#define DRIVER_AUTHOR	"Irene Zubarev <zubarev@us.ibm.com>, Vernon Mauery <vernux@us.ibm.com>"
+#define DRIVER_DESC	"ACPI Hot Plug PCI Controller Driver IBM extension"
+
+static int debug;
+
+MODULE_AUTHOR(DRIVER_AUTHOR);
+MODULE_DESCRIPTION(DRIVER_DESC);
+MODULE_LICENSE("GPL");
+MODULE_VERSION(DRIVER_VERSION);
+module_param(debug, bool, 644);
+MODULE_PARM_DESC(debug, " Debugging mode enabled or not");
+#define MY_NAME "acpiphp_ibm"
+
+#undef dbg
+#define dbg(format, arg...)				\
+do {							\
+	if (debug)					\
+		printk(KERN_DEBUG "%s: " format,	\
+				MY_NAME , ## arg);	\
+} while (0)
+
+#define FOUND_APCI 0x61504349
+/* these are the names for the IBM ACPI pseudo-device */
+#define IBM_HARDWARE_ID1 "IBM37D0"
+#define IBM_HARDWARE_ID2 "IBM37D4"
+
+/* union apci_descriptor - allows access to the
+ * various device descriptors that are embedded in the
+ * aPCI table
+ */
+union apci_descriptor {
+	struct {
+		char sig[4];
+		u8   len;
+	} header;
+	struct {
+		u8  type;
+		u8  len;
+		u16 slot_id;
+		u8  bus_id;
+		u8  dev_num;
+		u8  slot_num;
+		u8  slot_attr[2];
+		u8  attn;
+		u8  status[2];
+		u8  sun;
+	} slot;
+	struct {
+		u8 type;
+		u8 len;
+	} generic;
+};
+
+/* struct notification - keeps info about the device
+ * that cause the ACPI notification event
+ */
+struct notification {
+	struct acpi_device *device;
+	u8                  event;
+};
+
+static int ibm_set_attention_status(struct hotplug_slot *slot, u8 status);
+static int ibm_get_attention_status(struct hotplug_slot *slot, u8 *status);
+static void ibm_handle_events(acpi_handle handle, u32 event, void *context);
+static int ibm_get_table_from_acpi(char **bufp);
+static ssize_t ibm_read_apci_table(struct kobject *kobj,
+		char *buffer, loff_t pos, size_t size);
+static acpi_status __init ibm_find_acpi_device(acpi_handle handle,
+		u32 lvl, void *context, void **rv);
+static int __init ibm_acpiphp_init(void);
+static void __exit ibm_acpiphp_exit(void);
+
+static acpi_handle ibm_acpi_handle;
+static struct notification ibm_note;
+static struct bin_attribute ibm_apci_table_attr = {
+	    .attr = {
+		    .name = "apci_table",
+		    .owner = THIS_MODULE,
+		    .mode = S_IRUGO,
+	    },
+	    .read = ibm_read_apci_table,
+	    .write = NULL,
+};
+static struct acpiphp_attention_info ibm_attention_info = 
+{
+	.set_attn = ibm_set_attention_status,
+	.get_attn = ibm_get_attention_status,
+	.owner = THIS_MODULE,
+};
+
+
+/**
+ * ibm_set_attention_status - callback method to set the attention LED
+ * @slot: the hotplug_slot to work with
+ * @status: what to set the LED to (0 or 1)
+ *
+ * Description: this method is registered with the acpiphp module as a
+ * callback to do the device specific task of setting the LED status
+ **/
+static int ibm_set_attention_status(struct hotplug_slot *slot, u8 status)
+{
+	int retval = 0;
+	union acpi_object args[2]; 
+	struct acpi_object_list params = { .pointer = args, .count = 2 };
+	acpi_status stat; 
+	unsigned long rc = 0;
+	struct acpiphp_slot *acpi_slot;
+
+	acpi_slot = ((struct slot *)(slot->private))->acpi_slot;
+
+	dbg("%s: set slot %d attention status to %d\n", __FUNCTION__,
+			acpi_slot->sun, (status ? 1 : 0));
+
+	args[0].type = ACPI_TYPE_INTEGER;
+	args[0].integer.value = acpi_slot->sun;
+	args[1].type = ACPI_TYPE_INTEGER;
+	args[1].integer.value = (status) ? 1 : 0;
+
+	stat = acpi_evaluate_integer(ibm_acpi_handle, "APLS", &params, &rc);
+	if (ACPI_FAILURE(stat)) {
+		retval = -ENODEV;
+		err("APLS evaluation failed:  0x%08x\n", stat);
+	} else if (!rc) {
+		retval = -ERANGE;
+		err("APLS method failed:  0x%08lx\n", rc);
+	}
+	return retval;
+}
+
+/**
+ * ibm_get_attention_status - callback method to get attention LED status
+ * @slot: the hotplug_slot to work with
+ * @status: returns what the LED is set to (0 or 1)
+ *
+ * Description: this method is registered with the acpiphp module as a
+ * callback to do the device specific task of getting the LED status
+ * 
+ * Because there is no direct method of getting the LED status directly
+ * from an ACPI call, we read the aPCI table and parse out our
+ * slot descriptor to read the status from that.
+ **/
+static int ibm_get_attention_status(struct hotplug_slot *slot, u8 *status)
+{
+	int retval = -EINVAL, ind = 0, size;
+	char *table = NULL;
+	struct acpiphp_slot *acpi_slot;
+	union apci_descriptor *des;
+
+	acpi_slot = ((struct slot *)(slot->private))->acpi_slot;
+
+	size = ibm_get_table_from_acpi(&table);
+	if (size <= 0 || !table)
+		goto get_attn_done;
+	// read the header
+	des = (union apci_descriptor *)&table[ind];
+	if (memcmp(des->header.sig, "aPCI", 4) != 0)
+		goto get_attn_done;
+	des = (union apci_descriptor *)&table[ind += des->header.len];
+	while (ind < size && (des->generic.type != 0x82 ||
+			des->slot.slot_id != acpi_slot->sun))
+		des = (union apci_descriptor *)&table[ind += des->generic.len];
+	if (ind < size && des->slot.slot_id == acpi_slot->sun) {
+		retval = 0;
+		if (des->slot.attn & 0xa0 || des->slot.status[1] & 0x08)
+			*status = 1;
+		else
+			*status = 0;
+	}
+
+	dbg("%s: get slot %d attention status is %d retval=%x\n",
+			__FUNCTION__, acpi_slot->sun, *status, retval);
+
+get_attn_done:
+	kfree(table);
+	return retval;
+}
+
+/**
+ * ibm_handle_events - listens for ACPI events for the IBM37D0 device
+ * @handle: an ACPI handle to the device that caused the event
+ * @event: the event info (device specific)
+ * @context: passed context (our notification struct)
+ *
+ * Description: this method is registered as a callback with the ACPI
+ * subsystem it is called when this device has an event to notify the OS of
+ *
+ * The events actually come from the device as two events that get
+ * synthesized into one event with data by this function.  The event
+ * ID comes first and then the slot number that caused it.  We report
+ * this as one event to the OS.
+ *
+ * From section 5.6.2.2 of the ACPI 2.0 spec, I understand that the OSPM will
+ * only re-enable the interrupt that causes this event AFTER this method
+ * has returned, thereby enforcing serial access for the notification struct.
+ **/
+static void ibm_handle_events(acpi_handle handle, u32 event, void *context)
+{
+	u8 detail = event & 0x0f;
+	u8 subevent = event & 0xf0;
+	struct notification *note = context;
+
+	dbg("%s: Received notification %02x\n", __FUNCTION__, event);
+
+	if (subevent == 0x80) {
+		dbg("%s: generationg bus event\n", __FUNCTION__);
+		acpi_bus_generate_event(note->device, note->event, detail);
+	} else
+		note->event = event;
+}
+
+/**
+ * ibm_get_table_from_acpi - reads the APLS buffer from ACPI
+ * @bufp: address to pointer to allocate for the table
+ *
+ * Description: this method reads the APLS buffer in from ACPI and
+ * stores the "stripped" table into a single buffer
+ * it allocates and passes the address back in bufp
+ *
+ * If NULL is passed in as buffer, this method only calculates
+ * the size of the table and returns that without filling
+ * in the buffer
+ *
+ * returns < 0 on error or the size of the table on success
+ **/
+static int ibm_get_table_from_acpi(char **bufp)
+{
+	union acpi_object *package;
+	struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
+	acpi_status status;
+	char *lbuf = NULL;
+	int i, size = -EIO;
+
+	status = acpi_evaluate_object(ibm_acpi_handle, "APCI", NULL, &buffer);
+	if (ACPI_FAILURE(status)) {
+		err("%s:  APCI evaluation failed\n", __FUNCTION__);
+		return -ENODEV;
+	}
+
+	package = (union acpi_object *) buffer.pointer;
+	if(!(package) ||
+			(package->type != ACPI_TYPE_PACKAGE) ||
+			!(package->package.elements)) {
+		err("%s:  Invalid APCI object\n", __FUNCTION__);
+		goto read_table_done;
+	}
+
+	for(size = 0, i = 0; i < package->package.count; i++) {
+		if (package->package.elements[i].type != ACPI_TYPE_BUFFER) {
+			err("%s:  Invalid APCI element %d\n", __FUNCTION__, i);
+			goto read_table_done;
+		}
+		size += package->package.elements[i].buffer.length;
+	}
+
+	if (bufp == NULL)
+		goto read_table_done;
+
+	lbuf = kmalloc(size, GFP_KERNEL);
+	dbg("%s: element count: %i, ASL table size: %i, &table = 0x%p\n",
+			__FUNCTION__, package->package.count, size, lbuf);
+
+	if (lbuf) {
+		*bufp = lbuf;
+		memset(lbuf, 0, size);
+	} else {
+		size = -ENOMEM;
+		goto read_table_done;
+	}
+
+	size = 0;
+	for (i=0; i<package->package.count; i++) {
+		memcpy(&lbuf[size],
+				package->package.elements[i].buffer.pointer,
+				package->package.elements[i].buffer.length);
+		size += package->package.elements[i].buffer.length;
+	}
+
+read_table_done:
+	kfree(buffer.pointer);
+	return size;
+}
+
+/**
+ * ibm_read_apci_table - callback for the sysfs apci_table file
+ * @kobj: the kobject this binary attribute is a part of
+ * @buffer: the kernel space buffer to fill
+ * @pos: the offset into the file
+ * @size: the number of bytes requested
+ *
+ * Description: gets registered with sysfs as the reader callback
+ * to be executed when /sys/bus/pci/slots/apci_table gets read
+ *
+ * Since we don't get notified on open and close for this file,
+ * things get really tricky here...
+ * our solution is to only allow reading the table in all at once
+ **/
+static ssize_t ibm_read_apci_table(struct kobject *kobj,
+		char *buffer, loff_t pos, size_t size)
+{
+	int bytes_read = -EINVAL;
+	char *table = NULL;
+	
+	dbg("%s: pos = %d, size = %zd\n", __FUNCTION__, (int)pos, size);
+
+	if (pos == 0) {
+		bytes_read = ibm_get_table_from_acpi(&table);
+		if (bytes_read > 0 && bytes_read <= size)
+			memcpy(buffer, table, bytes_read);
+		kfree(table);
+	}
+	return bytes_read;
+}
+
+/**
+ * ibm_find_acpi_device - callback to find our ACPI device
+ * @handle: the ACPI handle of the device we are inspecting
+ * @lvl: depth into the namespace tree
+ * @context: a pointer to our handle to fill when we find the device
+ * @rv: a return value to fill if desired
+ *
+ * Description: used as a callback when calling acpi_walk_namespace
+ * to find our device.  When this method returns non-zero
+ * acpi_walk_namespace quits its search and returns our value
+ **/
+static acpi_status __init ibm_find_acpi_device(acpi_handle handle,
+		u32 lvl, void *context, void **rv)
+{
+	acpi_handle *phandle = (acpi_handle *)context;
+	acpi_status status; 
+	struct acpi_device_info info; 
+	struct acpi_buffer info_buffer = {
+		.length = sizeof(struct acpi_device_info),
+		.pointer = &info,
+	};
+
+	status = acpi_get_object_info(handle, &info_buffer);
+	if (ACPI_FAILURE(status)) {
+		err("%s:  Failed to get device information", __FUNCTION__);
+		return 0;
+	}
+	info.hardware_id.value[sizeof(info.hardware_id.value) - 1] = '\0';
+
+	if(info.current_status && (info.valid & ACPI_VALID_HID) &&
+			(!strcmp(info.hardware_id.value, IBM_HARDWARE_ID1) ||
+			!strcmp(info.hardware_id.value, IBM_HARDWARE_ID2))) {
+		dbg("found hardware: %s, handle: %p\n", info.hardware_id.value,
+				handle);
+		*phandle = handle;
+		/* returning non-zero causes the search to stop
+		 * and returns this value to the caller of 
+		 * acpi_walk_namespace, but it also causes some warnings
+		 * in the acpi debug code to print...
+		 */
+		return FOUND_APCI;
+	}
+	return 0;
+}
+
+static int __init ibm_acpiphp_init(void)
+{
+	int retval = 0;
+	acpi_status status;
+	struct acpi_device *device;
+	struct kobject *sysdir = &pci_hotplug_slots_subsys.kset.kobj;
+
+	dbg("%s\n", __FUNCTION__);
+
+	if (acpi_walk_namespace(ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT,
+			ACPI_UINT32_MAX, ibm_find_acpi_device,
+			&ibm_acpi_handle, NULL) != FOUND_APCI) {
+		err("%s: acpi_walk_namespace failed\n", __FUNCTION__);
+		retval = -ENODEV;
+		goto init_return;
+	}
+	dbg("%s: found IBM aPCI device\n", __FUNCTION__);
+	if (acpi_bus_get_device(ibm_acpi_handle, &device)) {
+		err("%s: acpi_bus_get_device failed\n", __FUNCTION__);
+		retval = -ENODEV;
+		goto init_return;
+	}
+	if (acpiphp_register_attention(&ibm_attention_info)) {
+		retval = -ENODEV;
+		goto init_return;
+	}
+
+	ibm_note.device = device;
+	status = acpi_install_notify_handler(
+			ibm_acpi_handle,
+			ACPI_DEVICE_NOTIFY,
+			ibm_handle_events,
+			&ibm_note);
+	if (ACPI_FAILURE(status)) {
+		err("%s:  Failed to register notification handler\n",
+				__FUNCTION__);
+		retval = -EBUSY;
+		goto init_cleanup;
+	}
+
+	ibm_apci_table_attr.size = ibm_get_table_from_acpi(NULL);
+	retval = sysfs_create_bin_file(sysdir, &ibm_apci_table_attr);
+
+	return retval;
+
+init_cleanup:
+	acpiphp_unregister_attention(&ibm_attention_info);
+init_return:
+	return retval;
+}
+
+static void __exit ibm_acpiphp_exit(void)
+{
+	acpi_status status;
+	struct kobject *sysdir = &pci_hotplug_slots_subsys.kset.kobj;
+
+	dbg("%s\n", __FUNCTION__);
+
+	if (acpiphp_unregister_attention(&ibm_attention_info))
+		err("%s: attention info deregistration failed", __FUNCTION__);
+
+	   status = acpi_remove_notify_handler(
+			   ibm_acpi_handle,
+			   ACPI_DEVICE_NOTIFY,
+			   ibm_handle_events);
+	   if (ACPI_FAILURE(status))
+		   err("%s:  Notification handler removal failed\n",
+				   __FUNCTION__);
+	// remove the /sys entries
+	if (sysfs_remove_bin_file(sysdir, &ibm_apci_table_attr))
+		err("%s: removal of sysfs file apci_table failed\n",
+				__FUNCTION__);
+}
+
+module_init(ibm_acpiphp_init);
+module_exit(ibm_acpiphp_exit);
diff -Nru a/drivers/pci/hotplug/cpci_hotplug_core.c b/drivers/pci/hotplug/cpci_hotplug_core.c
--- a/drivers/pci/hotplug/cpci_hotplug_core.c	2004-10-18 14:56:29 -07:00
+++ b/drivers/pci/hotplug/cpci_hotplug_core.c	2004-10-18 14:56:29 -07:00
@@ -33,6 +33,7 @@
 #include <linux/init.h>
 #include <linux/interrupt.h>
 #include <linux/smp_lock.h>
+#include <linux/delay.h>
 #include "pci_hotplug.h"
 #include "cpci_hotplug.h"
 
@@ -513,11 +514,10 @@
 			break;
 		while(controller->ops->query_enum()) {
 			rc = check_slots();
-			if(rc > 0) {
+			if (rc > 0)
 				/* Give userspace a chance to handle extraction */
-				set_current_state(TASK_INTERRUPTIBLE);
-				schedule_timeout(HZ / 2);
-			} else if(rc < 0) {
+				msleep(500);
+			else if (rc < 0) {
 				dbg("%s - error checking slots", __FUNCTION__);
 				thread_finished = 1;
 				break;
@@ -568,11 +568,10 @@
 
 		while(controller->ops->query_enum()) {
 			rc = check_slots();
-			if(rc > 0) {
+			if(rc > 0)
 				/* Give userspace a chance to handle extraction */
-				set_current_state(TASK_INTERRUPTIBLE);
-				schedule_timeout(HZ / 2);
-			} else if(rc < 0) {
+				msleep(500);
+			else if (rc < 0) {
 				dbg("%s - error checking slots", __FUNCTION__);
 				thread_finished = 1;
 				break;
@@ -595,8 +594,7 @@
 			}
 		}
 
-		set_current_state(TASK_INTERRUPTIBLE);
-		schedule_timeout(HZ / 10);
+		msleep(100);
 	}
 	dbg("poll thread signals exit");
 	up(&thread_exit);
diff -Nru a/drivers/pci/hotplug/cpcihp_zt5550.c b/drivers/pci/hotplug/cpcihp_zt5550.c
--- a/drivers/pci/hotplug/cpcihp_zt5550.c	2004-10-18 14:56:33 -07:00
+++ b/drivers/pci/hotplug/cpcihp_zt5550.c	2004-10-18 14:56:33 -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-10-18 14:55:46 -07:00
+++ b/drivers/pci/hotplug/cpqphp_core.c	2004-10-18 14:55:46 -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/ibmphp.h b/drivers/pci/hotplug/ibmphp.h
--- a/drivers/pci/hotplug/ibmphp.h	2004-10-18 14:55:55 -07:00
+++ b/drivers/pci/hotplug/ibmphp.h	2004-10-18 14:55:55 -07:00
@@ -759,11 +759,5 @@
 extern int ibmphp_unconfigure_card (struct slot **, int);
 extern struct hotplug_slot_ops ibmphp_hotplug_slot_ops;
 
-static inline void long_delay (int delay)
-{
-	set_current_state (TASK_INTERRUPTIBLE);
-	schedule_timeout (delay);
-}
-
 #endif				//__IBMPHP_H
 
diff -Nru a/drivers/pci/hotplug/ibmphp_core.c b/drivers/pci/hotplug/ibmphp_core.c
--- a/drivers/pci/hotplug/ibmphp_core.c	2004-10-18 14:57:05 -07:00
+++ b/drivers/pci/hotplug/ibmphp_core.c	2004-10-18 14:57:05 -07:00
@@ -190,7 +190,7 @@
 		err ("command not completed successfully in power_on\n");
 		return -EIO;
 	}
-	long_delay (3 * HZ); /* For ServeRAID cards, and some 66 PCI */
+	msleep(3000);	/* For ServeRAID cards, and some 66 PCI */
 	return 0;
 }
 
@@ -913,7 +913,7 @@
 	}
 	/* This is for x440, once Brandon fixes the firmware, 
 	will not need this delay */
-	long_delay (1 * HZ);
+	msleep(1000);
 	debug ("%s -Exit\n", __FUNCTION__);
 	return 0;
 }
diff -Nru a/drivers/pci/hotplug/ibmphp_hpc.c b/drivers/pci/hotplug/ibmphp_hpc.c
--- a/drivers/pci/hotplug/ibmphp_hpc.c	2004-10-18 14:56:27 -07:00
+++ b/drivers/pci/hotplug/ibmphp_hpc.c	2004-10-18 14:56:27 -07:00
@@ -29,6 +29,7 @@
 
 #include <linux/wait.h>
 #include <linux/time.h>
+#include <linux/delay.h>
 #include <linux/module.h>
 #include <linux/pci.h>
 #include <linux/smp_lock.h>
@@ -205,7 +206,7 @@
 	// READ - step 4 : wait until start operation bit clears
 	i = CMD_COMPLETE_TOUT_SEC;
 	while (i) {
-		long_delay (1 * HZ / 100);
+		msleep(10);
 		wpg_addr = WPGBbar + WPG_I2CMCNTL_OFFSET;
 		wpg_data = readl (wpg_addr);
 		data = swab32 (wpg_data);
@@ -221,7 +222,7 @@
 	// READ - step 5 : read I2C status register
 	i = CMD_COMPLETE_TOUT_SEC;
 	while (i) {
-		long_delay (1 * HZ / 100);
+		msleep(10);
 		wpg_addr = WPGBbar + WPG_I2CSTAT_OFFSET;
 		wpg_data = readl (wpg_addr);
 		data = swab32 (wpg_data);
@@ -316,7 +317,7 @@
 	// WRITE - step 4 : wait until start operation bit clears
 	i = CMD_COMPLETE_TOUT_SEC;
 	while (i) {
-		long_delay (1 * HZ / 100);
+		msleep(10);
 		wpg_addr = WPGBbar + WPG_I2CMCNTL_OFFSET;
 		wpg_data = readl (wpg_addr);
 		data = swab32 (wpg_data);
@@ -333,7 +334,7 @@
 	// WRITE - step 5 : read I2C status register
 	i = CMD_COMPLETE_TOUT_SEC;
 	while (i) {
-		long_delay (1 * HZ / 100);
+		msleep(10);
 		wpg_addr = WPGBbar + WPG_I2CSTAT_OFFSET;
 		wpg_data = readl (wpg_addr);
 		data = swab32 (wpg_data);
@@ -748,7 +749,7 @@
 					done = TRUE;
 			}
 			if (!done) {
-				long_delay (1 * HZ);
+				msleep(1000);
 				if (timeout < 1) {
 					done = TRUE;
 					err ("%s - Error command complete timeout\n", __FUNCTION__);
@@ -891,7 +892,7 @@
 		case POLL_SLEEP:
 			/* don't sleep with a lock on the hardware */
 			up (&semOperations);
-			long_delay (POLL_INTERVAL_SEC * HZ);
+			msleep(POLL_INTERVAL_SEC * 1000);
 
 			if (ibmphp_shutdown) 
 				break;
@@ -908,8 +909,7 @@
 		/* give up the harware semaphore */
 		up (&semOperations);
 		/* sleep for a short time just for good measure */
-		set_current_state (TASK_INTERRUPTIBLE);
-		schedule_timeout (HZ/10);
+		msleep(100);
 	}
 	up (&sem_exit);
 	debug ("%s - Exit\n", __FUNCTION__);
@@ -974,7 +974,7 @@
 			if (SLOT_PWRGD (pslot->status)) {
 				// power goes on and off after closing latch
 				// check again to make sure power is still ON
-				long_delay (1 * HZ);
+				msleep(1000);
 				rc = ibmphp_hpc_readslot (pslot, READ_SLOTSTATUS, &status);
 				if (SLOT_PWRGD (status))
 					update = TRUE;
@@ -1147,7 +1147,7 @@
 		if (CTLR_WORKING (*pstatus) == HPC_CTLR_WORKING_NO)
 			done = TRUE;
 		if (!done) {
-			long_delay (1 * HZ);
+			msleep(1000);
 			if (timeout < 1) {
 				done = TRUE;
 				err ("HPCreadslot - Error ctlr timeout\n");
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-10-18 14:56:49 -07:00
+++ b/drivers/pci/hotplug/pci_hotplug_core.c	2004-10-18 14:56:49 -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-10-18 14:55:53 -07:00
+++ b/drivers/pci/hotplug/pciehp_core.c	2004-10-18 14:55:53 -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/pciehp_hpc.c b/drivers/pci/hotplug/pciehp_hpc.c
--- a/drivers/pci/hotplug/pciehp_hpc.c	2004-10-18 14:56:33 -07:00
+++ b/drivers/pci/hotplug/pciehp_hpc.c	2004-10-18 14:56:33 -07:00
@@ -1017,7 +1017,7 @@
 	return IRQ_HANDLED;
 }
 
-static int hpc_get_max_lnk_speed (struct slot *slot, enum pcie_link_speed *value)
+static int hpc_get_max_lnk_speed (struct slot *slot, enum pci_bus_speed *value)
 {
 	struct php_ctlr_state_s *php_ctlr = slot->ctrl->hpc_ctlr_handle;
 	enum pcie_link_speed lnk_speed;
@@ -1120,7 +1120,7 @@
 	return retval;
 }
 
-static int hpc_get_cur_lnk_speed (struct slot *slot, enum pcie_link_speed *value)
+static int hpc_get_cur_lnk_speed (struct slot *slot, enum pci_bus_speed *value)
 {
 	struct php_ctlr_state_s *php_ctlr = slot->ctrl->hpc_ctlr_handle;
 	enum pcie_link_speed lnk_speed = PCI_SPEED_UNKNOWN;
diff -Nru a/drivers/pci/hotplug/pcihp_skeleton.c b/drivers/pci/hotplug/pcihp_skeleton.c
--- a/drivers/pci/hotplug/pcihp_skeleton.c	2004-10-18 14:56:32 -07:00
+++ b/drivers/pci/hotplug/pcihp_skeleton.c	2004-10-18 14:56:32 -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/rpaphp_core.c b/drivers/pci/hotplug/rpaphp_core.c
--- a/drivers/pci/hotplug/rpaphp_core.c	2004-10-18 14:57:04 -07:00
+++ b/drivers/pci/hotplug/rpaphp_core.c	2004-10-18 14:57:04 -07:00
@@ -54,8 +54,6 @@
 MODULE_DESCRIPTION(DRIVER_DESC);
 MODULE_LICENSE("GPL");
 
-void eeh_register_disable_func(int (*)(struct pci_dev *));
-
 module_param(debug, bool, 0644);
 
 static int enable_slot(struct hotplug_slot *slot);
@@ -407,18 +405,12 @@
 {
 	info(DRIVER_DESC " version: " DRIVER_VERSION "\n");
 
-	/* let EEH know they can use hotplug */
-	eeh_register_disable_func(&rpaphp_disable_slot);
-
 	/* read all the PRA info from the system */
 	return init_rpa();
 }
 
 static void __exit rpaphp_exit(void)
 {
-	/* let EEH know we are going away */
-	eeh_register_disable_func(NULL);
-
 	cleanup_slots();
 }
 
@@ -457,7 +449,7 @@
 
 static int disable_slot(struct hotplug_slot *hotplug_slot)
 {
-	int retval;
+	int retval = -EINVAL;
 	struct slot *slot = (struct slot *)hotplug_slot->private;
 
 	dbg("%s - Entry: slot[%s]\n", __FUNCTION__, slot->name);
diff -Nru a/drivers/pci/hotplug/rpaphp_pci.c b/drivers/pci/hotplug/rpaphp_pci.c
--- a/drivers/pci/hotplug/rpaphp_pci.c	2004-10-18 14:55:46 -07:00
+++ b/drivers/pci/hotplug/rpaphp_pci.c	2004-10-18 14:55:46 -07:00
@@ -186,7 +186,7 @@
 rpaphp_pci_config_slot(struct device_node *dn, struct pci_bus *bus)
 {
 	struct device_node *eads_first_child = dn->child;
-	struct pci_dev *dev;
+	struct pci_dev *dev = NULL;
 	int num;
 	
 	dbg("Enter %s: dn=%s bus=%s\n", __FUNCTION__, dn->full_name, bus->name);
@@ -341,7 +341,6 @@
 	return rc;
 }
 
-
 static void rpaphp_eeh_remove_bus_device(struct pci_dev *dev)
 {
 	eeh_remove_device(dev);
@@ -363,7 +362,7 @@
 int rpaphp_unconfig_pci_adapter(struct slot *slot)
 {
 	int retval = 0;
-	struct list_head *ln;
+	struct list_head *ln, *tmp;
 
 	dbg("Entry %s: slot[%s]\n", __FUNCTION__, slot->name);
 	if (list_empty(&slot->dev.pci_funcs)) {
@@ -374,7 +373,7 @@
 		goto exit;
 	}
 	/* remove the devices from the pci core */
-	list_for_each (ln, &slot->dev.pci_funcs) {
+	list_for_each_safe (ln, tmp, &slot->dev.pci_funcs) {
 		struct rpaphp_pci_func *func;
 	
 		func = list_entry(ln, struct rpaphp_pci_func, sibling);
@@ -430,10 +429,26 @@
 				__FUNCTION__, slot->name);
 			goto exit_rc;
 		}
-		if (init_slot_pci_funcs(slot)) {
-			err("%s: init_slot_pci_funcs failed\n", __FUNCTION__);
+
+		if (slot->hotplug_slot->info->adapter_status == NOT_CONFIGURED) {
+			dbg("%s CONFIGURING pci adapter in slot[%s]\n",  
+				__FUNCTION__, slot->name);
+			if (rpaphp_config_pci_adapter(slot)) {
+				err("%s: CONFIG pci adapter failed\n", __FUNCTION__);
+				goto exit_rc;		
+			}
+		} else if (slot->hotplug_slot->info->adapter_status == CONFIGURED) {
+			if (init_slot_pci_funcs(slot)) {
+				err("%s: init_slot_pci_funcs failed\n", __FUNCTION__);
+				goto exit_rc;
+			}
+
+		} else {
+			err("%s: slot[%s]'s adapter_status is NOT_VALID.\n",
+				__FUNCTION__, slot->name);
 			goto exit_rc;
 		}
+		
 		print_slot_pci_funcs(slot);
 		if (!list_empty(&slot->dev.pci_funcs)) {
 			slot->state = CONFIGURED;
diff -Nru a/drivers/pci/hotplug/rpaphp_slot.c b/drivers/pci/hotplug/rpaphp_slot.c
--- a/drivers/pci/hotplug/rpaphp_slot.c	2004-10-18 14:56:32 -07:00
+++ b/drivers/pci/hotplug/rpaphp_slot.c	2004-10-18 14:56:32 -07:00
@@ -244,7 +244,7 @@
 
 int rpaphp_get_power_status(struct slot *slot, u8 * value)
 {
-	int rc = 0;
+	int rc = 0, level;
 	
 	if (slot->type == EMBEDDED) {
 		dbg("%s set to POWER_ON for EMBEDDED slot %s\n",
@@ -252,10 +252,14 @@
 		*value = POWER_ON;
 	}
 	else {
-		rc = rtas_get_power_level(slot->power_domain, (int *) value);
-		if (rc)
+		rc = rtas_get_power_level(slot->power_domain, &level);
+		if (!rc) {
+			dbg("%s the power level of slot %s(pwd-domain:0x%x) is %d\n",
+				__FUNCTION__, slot->name, slot->power_domain, level);
+			*value = level;
+		} else
 			err("failed to get power-level for slot(%s), rc=0x%x\n",
-		    		slot->location, rc);
+				slot->location, rc);
 	}
 
 	return rc;
diff -Nru a/drivers/pci/hotplug/shpchp_core.c b/drivers/pci/hotplug/shpchp_core.c
--- a/drivers/pci/hotplug/shpchp_core.c	2004-10-18 14:55:53 -07:00
+++ b/drivers/pci/hotplug/shpchp_core.c	2004-10-18 14:55:53 -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/hotplug/shpchp_ctrl.c b/drivers/pci/hotplug/shpchp_ctrl.c
--- a/drivers/pci/hotplug/shpchp_ctrl.c	2004-10-18 14:57:04 -07:00
+++ b/drivers/pci/hotplug/shpchp_ctrl.c	2004-10-18 14:57:04 -07:00
@@ -2163,11 +2163,13 @@
 	u32 rc = 0;
 	int ret = 0;
 	unsigned int devfn;
-	struct pci_bus *pci_bus = p_slot->ctrl->pci_dev->subordinate;
+	struct pci_bus *pci_bus;
 	struct pci_func *func;
 
 	if (!p_slot->ctrl)
 		return 1;
+
+	pci_bus = p_slot->ctrl->pci_dev->subordinate;
 
 	/* Check to see if (latch closed, card present, power on) */
 	down(&p_slot->ctrl->crit_sect);
diff -Nru a/drivers/pci/hotplug/shpchp_hpc.c b/drivers/pci/hotplug/shpchp_hpc.c
--- a/drivers/pci/hotplug/shpchp_hpc.c	2004-10-18 14:56:27 -07:00
+++ b/drivers/pci/hotplug/shpchp_hpc.c	2004-10-18 14:56:27 -07:00
@@ -35,6 +35,7 @@
 #include <linux/vmalloc.h>
 #include <linux/interrupt.h>
 #include <linux/spinlock.h>
+#include <linux/delay.h>
 #include <linux/pci.h>
 #include <asm/system.h>
 #include "shpchp.h"
@@ -300,8 +301,7 @@
 		if (!(cmd_status & 0x1))
 			break;
 		/*  Check every 0.1 sec for a total of 1 sec*/
-		set_current_state(TASK_INTERRUPTIBLE);
-		schedule_timeout(HZ/10);
+		msleep(100);
 	}
 
 	cmd_status = readw(php_ctlr->creg + CMD_STATUS);
diff -Nru a/drivers/pci/pci-driver.c b/drivers/pci/pci-driver.c
--- a/drivers/pci/pci-driver.c	2004-10-18 14:56:48 -07:00
+++ b/drivers/pci/pci-driver.c	2004-10-18 14:56:48 -07:00
@@ -299,10 +299,23 @@
 {
 	struct pci_dev * pci_dev = to_pci_dev(dev);
 	struct pci_driver * drv = pci_dev->driver;
+	u32 dev_state;
 	int i = 0;
 
+	/* Translate PM_SUSPEND_xx states to PCI device states */
+	static u32 state_conversion[] = {
+		[PM_SUSPEND_ON] = 0,
+		[PM_SUSPEND_STANDBY] = 1,
+		[PM_SUSPEND_MEM] = 3,
+		[PM_SUSPEND_DISK] = 3,
+	};
+
+	if (state >= sizeof(state_conversion) / sizeof(state_conversion[1]))
+		return -EINVAL;
+
+	dev_state = state_conversion[state];
 	if (drv && drv->suspend)
-		i = drv->suspend(pci_dev,state);
+		i = drv->suspend(pci_dev, dev_state);
 		
 	pci_save_state(pci_dev, pci_dev->saved_config_space);
 	return i;
@@ -390,10 +403,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.c b/drivers/pci/pci.c
--- a/drivers/pci/pci.c	2004-10-18 14:56:27 -07:00
+++ b/drivers/pci/pci.c	2004-10-18 14:56:27 -07:00
@@ -291,10 +291,7 @@
 	/* Mandatory power management transition delays */
 	/* see PCI PM 1.1 5.6.1 table 18 */
 	if(state == 3 || dev->current_state == 3)
-	{
-		set_current_state(TASK_UNINTERRUPTIBLE);
-		schedule_timeout(HZ/100);
-	}
+		msleep(10);
 	else if(state == 2 || dev->current_state == 2)
 		udelay(200);
 	dev->current_state = state;
@@ -748,7 +745,7 @@
 	struct pci_dev *dev = NULL;
 
 	while ((dev = pci_find_device(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL) {
-		pci_fixup_device(PCI_FIXUP_FINAL, dev);
+		pci_fixup_device(pci_fixup_final, dev);
 	}
 	return 0;
 }
diff -Nru a/drivers/pci/pci.ids b/drivers/pci/pci.ids
--- a/drivers/pci/pci.ids	2004-10-18 14:56:32 -07:00
+++ b/drivers/pci/pci.ids	2004-10-18 14:56:32 -07:00
@@ -7,7 +7,7 @@
 #	so if you have anything to contribute, please visit the home page or
 #	send a diff -u against the most recent pci.ids to pci-ids@ucw.cz.
 #
-#	Daily snapshot on Thu 2004-04-15 10:00:04
+#	Daily snapshot on Mon 2004-07-12 10:00:27
 #
 
 # Vendors, devices and subsystems. Please keep sorted.
@@ -150,37 +150,58 @@
 		0e11 4082  Smart Array 532
 		0e11 4083  Smart Array 5312
 	b1a4  NC7131 Gigabit Server Adapter
+	b203  Integrated Lights Out Controller
+	b204  Integrated Lights Out  Processor
 	f130  NetFlex-3/P ThunderLAN 1.0
 	f150  NetFlex-3/P ThunderLAN 2.3
 0e55  HaSoTec GmbH
 # Formerly NCR
 1000  LSI Logic / Symbios Logic
 	0001  53c810
-		1000 1000  8100S
+		1000 1000  LSI53C810AE PCI to SCSI I/O Processor
 	0002  53c820
 	0003  53c825
+		1000 1000  LSI53C825AE PCI to SCSI I/O Processor (Ultra Wide)
 	0004  53c815
 	0005  53c810AP
 	0006  53c860
+		1000 1000  LSI53C860E PCI to Ultra SCSI I/O Processor
 	000a  53c1510
-	000b  53c896
+		1000 1000  LSI53C1510 PCI to Dual Channel Wide Ultra2 SCSI Controller (Nonintelligent mode)
+	000b  53C896/897
+		1000 1000  LSI53C896/7 PCI to Dual Channel Ultra2 SCSI Multifunction Controller
+		1000 1010  LSI22910 PCI to Dual Channel Ultra2 SCSI host adapter
+		1000 1020  LSI21002 PCI to Dual Channel Ultra2 SCSI host adapter
+# multifunction PCI card: Dual U2W SCSI, dual 10/100TX, graphics
+		13e9 1000  6221L-4U
 	000c  53c895
+		1000 1010  LSI8951U PCI to Ultra2 SCSI host adapter
+		1000 1020  LSI8952U PCI to Ultra2 SCSI host adapter
+		1de1 3906  DC-390U2B SCSI adapter
 		1de1 3907  DC-390U2W
 	000d  53c885
 	000f  53c875
 		0e11 7004  Embedded Ultra Wide SCSI Controller
+		1000 1000  LSI53C876/E PCI to Dual Channel SCSI Controller
+		1000 1010  LSI22801 PCI to Dual Channel Ultra SCSI host adapter
+		1000 1020  LSI22802 PCI to Dual Channel Ultra SCSI host adapter
 		1092 8760  FirePort 40 Dual SCSI Controller
-		1de1 3904  DC390F Ultra Wide SCSI Controller
+		1de1 3904  DC390F/U Ultra Wide SCSI Adapter
 		4c53 1000  CC7/CR7/CP7/VC7/VP7/VR7 mainboard
 		4c53 1050  CT7 mainboard
-	0010  53c895
+	0010  53C1510
 		0e11 4040  Integrated Array Controller
 		0e11 4048  Integrated Array Controller
+		1000 1000  53C1510 PCI to Dual Channel Wide Ultra2 SCSI Controller (Intelligent mode)
 	0012  53c895a
+		1000 1000  LSI53C895A PCI to Ultra2 SCSI Controller
 	0013  53c875a
+		1000 1000  LSI53C875A PCI to Ultra SCSI Controller
 	0020  53c1010 Ultra3 SCSI Adapter
+		1000 1000  LSI53C1010-33 PCI to Dual Channel Ultra160 SCSI Controller
 		1de1 1020  DC-390U3W
 	0021  53c1010 66MHz  Ultra3 SCSI Adapter
+		1000 1000  LSI53C1000/1000R/1010R/1010-66 PCI to Ultra160 SCSI Controller
 		124b 1070  PMC-USCSI3
 		4c53 1080  CT8 mainboard
 		4c53 1300  P017 mezzanine (32-bit PMC)
@@ -191,6 +212,7 @@
 		1028 1010  LSI U320 SCSI Controller
 	0031  53c1030ZC PCI-X Fusion-MPT Dual Ultra320 SCSI
 	0032  53c1035 PCI-X Fusion-MPT Dual Ultra320 SCSI
+		1000 1000  LSI53C1020/1030 PCI-X to Ultra320 SCSI Controller
 	0033  1030ZC_53c1035 PCI-X Fusion-MPT Dual Ultra320 SCSI
 	0040  53c1035 PCI-X Fusion-MPT Dual Ultra320 SCSI
 		1000 0033  MegaRAID SCSI 320-2XR
@@ -203,8 +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  PowerEgde 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
+		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
@@ -228,13 +264,16 @@
 	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
 		1028 0518  MegaRAID 518 DELL PERC 4/DC RAID Controller
 		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
@@ -350,6 +389,8 @@
 		1002 8008  Rage XL
 		1028 00ce  PowerEdge 1400
 		1028 00d1  PowerEdge 2550
+		8086 3411  SDS2 Mainboard
+		8086 3427  S875WP1-E mainboard
 	4753  Rage XC
 		1002 4753  Rage XC
 	4754  3D Rage I/II 215GT [Mach64 GT]
@@ -435,10 +476,12 @@
 	4e44  Radeon R300 ND [Radeon 9700 Pro]
 	4e45  Radeon R300 NE [Radeon 9500 Pro]
 		1002 0002  Radeon R300 NE [Radeon 9500 Pro]
+		1681 0002  Hercules 3D Prophet 9500 PRO [Radeon 9500 Pro]
 # New PCI ID provided by ATI developer relations (correction to above)
 	4e46  RV350 NF [Radeon 9600]
 	4e47  Radeon R300 NG [FireGL X1]
-	4e48  Radeon R350 [Radeon 9800]
+# (added pro)
+	4e48  Radeon R350 [Radeon 9800 Pro]
 # New PCI ID provided by ATI developer relations
 	4e49  Radeon R350 [Radeon 9800]
 	4e4a  RV350 NJ [Radeon 9800 XT]
@@ -451,10 +494,12 @@
 	4e64  Radeon R300 [Radeon 9700 Pro] (Secondary)
 	4e65  Radeon R300 [Radeon 9500 Pro] (Secondary)
 		1002 0003  Radeon R300 NE [Radeon 9500 Pro]
+		1681 0003  Hercules 3D Prophet 9500 PRO [Radeon 9500 Pro] (Secondary)
 # New PCI ID provided by ATI developer relations (correction to above)
 	4e66  RV350 NF [Radeon 9600] (Secondary)
 	4e67  Radeon R300 [FireGL X1] (Secondary)
-	4e68  Radeon R350 [Radeon 9800] (Secondary)
+# (added pro)
+	4e68  Radeon R350 [Radeon 9800 Pro] (Secondary)
 # New PCI ID provided by ATI developer relations
 	4e69  Radeon R350 [Radeon 9800] (Secondary)
 	4e6a  RV350 NJ [Radeon 9800 XT] (Secondary)
@@ -535,6 +580,7 @@
 		148c 2024  RV200 QW [Radeon 7500LE Dual Display]
 		148c 2025  RV200 QW [Radeon 7500 Evil Master Multi Display Edition]
 		148c 2036  RV200 QW [Radeon 7500 PCI Dual Display]
+		174b 7146  RV200 QW [Radeon 7500 LE]
 		174b 7147  RV200 QW [Sapphire Radeon 7500LE]
 		174b 7161  Radeon RV200 QW [Radeon 7500 LE]
 		17af 0202  RV200 QW [Excalibur Radeon 7500LE]
@@ -624,6 +670,7 @@
 	5d44  RV280 [Radeon 9200 SE] (Secondary)
 	700f  PCI Bridge [IGP 320M]
 	7010  PCI Bridge [IGP 340M]
+	7c37  RV350 AQ [Radeon 9600 SE]
 	cab0  AGP Bridge [IGP 320M]
 	cab2  RS200/RS200M AGP Bridge [IGP 340M]
 1003  ULSI Systems
@@ -865,6 +912,8 @@
 		1014 002e  ServeRAID-3x
 		1014 022e  ServeRAID-4H
 	0031  2 Port Serial Adapter
+# AS400 iSeries PCI sync serial card
+		1014 0031  2721 WAN IOA - 2 Port Sync Serial Adapter
 	0036  Miami
 	003a  CPU to PCI Bridge
 	003c  GXT250P/GXT255P Graphics Adapter
@@ -924,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
@@ -946,7 +996,9 @@
 	0266  PCI-X Dual Channel SCSI
 	0268  Gigabit Ethernet-SX Adapter (PCI-X)
 	0269  10/100/1000 Base-TX Ethernet Adapter (PCI-X)
-	0302  XA-32 chipset [Summit]
+	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
 1016  ICL Personal Systems
@@ -1059,20 +1111,27 @@
 	7454  AMD-8151 System Controller
 	7455  AMD-8151 AGP Bridge
 	7460  AMD-8111 PCI
+		161f 3017  HDAMB
 	7461  AMD-8111 USB
 	7462  AMD-8111 Ethernet
 	7464  AMD-8111 USB
+		161f 3017  HDAMB
 	7468  AMD-8111 LPC
+		161f 3017  HDAMB
 	7469  AMD-8111 IDE
+		161f 3017  HDAMB
 	746a  AMD-8111 SMBus 2.0
 	746b  AMD-8111 ACPI
+		161f 3017  HDAMB
 	746d  AMD-8111 AC97 Audio
+		161f 3017  HDAMB
 	746e  AMD-8111 MC97 Modem
 	756b  AMD-8111 ACPI
 1023  Trident Microsystems
 	0194  82C194
 	2000  4DWave DX
 	2001  4DWave NX
+		122d 1400  Trident PCI288-Q3DII (NX)
 	2100  CyberBlade XP4m32
 	8400  CyberBlade/i7
 		1023 8400  CyberBlade i7 AGP
@@ -1083,7 +1142,7 @@
 		0e11 b16e  CyberBlade i1 AGP
 		1023 8520  CyberBlade i1 AGP
 	8620  CyberBlade/i1
-		1014 0502  ThinkPad T30
+		1014 0502  ThinkPad R30/T30
 	8820  CyberBlade XPAi1
 	9320  TGUI 9320
 	9350  GUI Accelerator
@@ -1179,34 +1238,32 @@
 	5453  M5453 PCI AC-Link Controller Modem Device
 	7101  M7101 PCI PMU Power Management Controller
 		10b9 7101  M7101 PCI PMU Power Management Controller
-1028  Dell Computer Corporation
+1028  Dell
 	0001  PowerEdge Expandable RAID Controller 2/Si
-		1028 0001  PowerEdge Expandable RAID Controller 2/Si
-	0002  PowerEdge Expandable RAID Controller 3
-		1028 0002  PowerEdge Expandable RAID Controller 3/Di
-		1028 00d1  PowerEdge Expandable RAID Controller 3/Di
-		1028 00d9  PowerEdge Expandable RAID Controller 3/Di
+		1028 0001  PowerEdge 2400
+	0002  PowerEdge Expandable RAID Controller 3/Di
+		1028 0002  PowerEdge 4400
 	0003  PowerEdge Expandable RAID Controller 3/Si
-		1028 0003  PowerEdge Expandable RAID Controller 3/Si
-	0004  PowerEdge Expandable RAID Controller 3/Si
-		1028 00d0  PowerEdge Expandable RAID Controller 3/Si
+		1028 0003  PowerEdge 2450
 	0006  PowerEdge Expandable RAID Controller 3/Di
-	0007  Remote Access Controller:DRAC III
-	0008  Remote Access Controller
-	0009  BMC/SMIC device not present
-	000a  PowerEdge Expandable RAID Controller 3
-		1028 0106  PowerEdge Expandable RAID Controller 3/Di
-		1028 011b  PowerEdge Expandable RAID Controller 3/Di
-		1028 0121  PowerEdge Expandable RAID Controller 3/Di
-	000c  Remote Access Controller:ERA or ERA/O
-	000d  BMC/SMIC device
-	000e  PowerEdge Expandable RAID controller 4
-		1028 0123  PowerEdge Expandable RAID Controller 4/Di
-	000f  PowerEdge Expandable RAID controller 4
-		1028 013b  MegaRAID DELL PERC 4/Di RAID On Motherboard
-		1028 014a  PowerEdge Expandable RAID Controller 4/Di
-		1028 014c  MegaRAID DELL PERC 4/Di RAID On Motherboard
-		1028 014d  MegaRAID DELL PERC 4/Di RAID On Motherboard
+	0007  Remote Access Card III
+	0008  Remote Access Card III
+	0009  Remote Access Card III: BMC/SMIC device not present
+	000a  PowerEdge Expandable RAID Controller 3/Di
+	000c  Embedded Remote Access or ERA/O
+	000d  Embedded Remote Access: BMC/SMIC device
+	000e  PowerEdge Expandable RAID controller 4/Di
+	000f  PowerEdge Expandable RAID controller 4/Di
+	0010  Remote Access Card 4
+	0011  Remote Access Card 4 Daughter Card
+	0012  Remote Access Card 4 Daughter Card Virtual UART
+	0013  PowerEdge Expandable RAID controller 4
+		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
 	0000  HYDRA
@@ -1518,6 +1575,7 @@
 		1039 5513  SiS5513 EIDE Controller (A,B step)
 		1043 8035  CUSI-FX motherboard
 	5517  5517
+	5518  5518 [IDE]
 	5571  5571
 	5581  5581 Pentium Chipset
 	5582  5582
@@ -1542,6 +1600,7 @@
 		1092 4920  SpeedStar A70
 		1569 6326  SiS6326 GUI Accelerator
 	6330  661FX/M661FX/M661MX/741/M741/760/M760 PCI/AGP
+		1039 6330  [M]661FX/M661MX/[M]741/[M]760 PCI/AGP VGA Display Adapter
 	7001  USB 1.0 Controller
 		1039 7000  Onboard USB Controller
 	7002  USB 2.0 Controller
@@ -1604,7 +1663,7 @@
 		103c 1049  Tosca Console
 		103c 104a  Tosca Secondary
 		103c 104b  Maestro SP2
-		103c 1223  Halfdome Console
+		103c 1223  Superdome Console
 		103c 1226  Keystone SP2
 		103c 1227  Powerbar SP2
 		103c 1282  Everest SP2
@@ -1642,7 +1701,7 @@
 	4057  v8200 GeForce 3
 	8043  v8240 PAL 128M [P4T] Motherboard
 	807b  v9280/TD [Geforce4 TI4200 8X With TV-Out and DVI]
-1044  Distributed Processing Technology
+1044  Adaptec (formerly DPT)
 	1012  Domino RAID Engine
 	a400  SmartCache/Raid I-IV Controller
 	a500  PCI Bridge
@@ -1683,6 +1742,7 @@
 		1044 c065  3010S Ultra3 Four Channel
 		1044 c066  3010S Fibre Channel
 	a511  SmartRAID V Controller
+		1044 c032  ASR-2005S I2O Zero Channel
 1045  OPTi Inc.
 	a0f8  82C750 [Vendetta] USB Controller
 	c101  92C264
@@ -1786,6 +1846,7 @@
 		1028 00e6  PCI4451 IEEE-1394 Controller (Dell Inspiron 8100)
 	8029  PCI4510 IEEE-1394 Controller
 		1071 8160  MIM2900
+	802e  PCI7x20 1394a-2000 OHCI Two-Port PHY/Link-Layer Controller
 	8400  ACX 100 22Mbps Wireless Interface
 		00fc 16ec  U.S. Robotics 22 Mbps Wireless PC Card (model 2210)
 		00fd 16ec  U.S. Robotics 22Mbps Wireless PCI Adapter (model 2216)
@@ -1894,6 +1955,8 @@
 	0003  MPC8240 [Kahlua]
 	0004  MPC107
 	0006  MPC8245 [Unity]
+	0008  MPC8540
+	0009  MPC8560
 	0100  MC145575 [HFC-PCI]
 	0431  KTI829c 100VG
 	1801  DSP56301 Digital Signal Processor
@@ -1939,44 +2002,49 @@
 1058  Electronics & Telecommunications RSH
 1059  Teknor Industrial Computers Inc
 105a  Promise Technology, Inc.
-	0d30  20265
+# more correct description from promise linux sources
+	0d30  PDC20265 (FastTrak100 Lite/Ultra100)
 		105a 4d33  Ultra100
 	0d38  20263
 		105a 4d39  Fasttrak66
 	1275  20275
 	3318  PDC20318 (SATA150 TX4)
-	3319  PDC20319 (SATA150 TX4)
-	3373  PDC20378 (SATA150 TX)
+	3319  PDC20319 (FastTrak S150 TX4)
+		8086 3427  S875WP1-E mainboard
+	3371  PDC20371 (FastTrak S150 TX2plus)
+	3373  PDC20378 (FastTrak 378/SATA 378)
+		1043 80f5  PC-DL Deluxe motherboard
 		1462 702e  K8T NEO FIS2R motherboard
 	3375  PDC20375 (SATA150 TX2plus)
-	3376  PDC20376
+	3376  PDC20376 (FastTrak 376)
 		1043 809e  A7V8X motherboard
-	4d30  20267
+	4d30  PDC20267 (FastTrak100/Ultra100)
 		105a 4d33  Ultra100
-		105a 4d39  Fasttrak100
+		105a 4d39  FastTrak100
 	4d33  20246
 		105a 4d33  20246 IDE Controller
-	4d38  20262
+	4d38  PDC20262 (FastTrak66/Ultra66)
 		105a 4d30  Ultra Device on SuperTrak
 		105a 4d33  Ultra66
-		105a 4d39  Fasttrak66
-	4d68  20268
+		105a 4d39  FastTrak66
+	4d68  PDC20268 (Ultra100 TX2)
 		105a 4d68  Ultra100TX2
 	4d69  20269
 		105a 4d68  Ultra133TX2
-	5275  PDC20276 IDE
+	5275  PDC20276 (MBFastTrak133 Lite)
 		105a 0275  SuperTrak SX6000 IDE
 		105a 1275  MBFastTrak133 Lite (tm) Controller (RAID mode)
 		1458 b001  MBUltra 133
 	5300  DC5300
-	6268  20268R
-	6269  PDC20271
+	6268  PDC20270 (FastTrak100 LP/TX2/TX4)
+		105a 4d68  FastTrak100 TX2
+	6269  PDC20271 (FastTrak TX2000)
 		105a 6269  FastTrak TX2/TX2000
-	6621  PDC20621 [SX4000] 4 Channel IDE RAID Controller
+	6621  PDC20621 (FastTrak S150 SX4/FastTrak SX4000 lite)
 	6622  PDC20621 [SATA150 SX4] 4 Channel IDE RAID Controller
-	6626  PDC20618 Ultra 618
-	6629  PDC20619 FastTrak TX4000 RAID
-	7275  PDC20277
+	6626  PDC20618 (Ultra 618)
+	6629  PDC20619 (FastTrak TX4000)
+	7275  PDC20277 (SBFastTrak133 Lite)
 105b  Foxconn International, Inc.
 105c  Wipro Infotech Limited
 105d  Number 9 Computer Company
@@ -2070,6 +2138,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
@@ -2199,6 +2269,7 @@
 107c  LG Electronics [Lucky Goldstar Co. Ltd]
 107d  LeadTek Research Inc.
 	0000  P86C850
+	2134  WinFast 3D S320 II
 107e  Interphase Corporation
 	0001  5515 ATM Adapter [Flipper]
 	0002  100 VG AnyLan Controller
@@ -2348,10 +2419,10 @@
 	0673  USB0673
 	0680  PCI0680 Ultra ATA-133 Host Controller
 		1095 3680  Winic W-680 (Silicon Image 680 based)
-	3112  Silicon Image Serial ATARaid Controller [ CMD/Sil 3112/3112A ]
+	3112  SiI 3112 [SATALink/SATARaid] Serial ATA Controller
 		1095 6112  Asus A7N8X
-	3114  Silicon Image SiI 3114 SATARaid
-	3512  Silicon Image Serial ATARaid Controller [ CMD/Sil 3512 ]
+	3114  SiI 3114 [SATALink/SATARaid] Serial ATA Controller
+	3512  SiI 3512 [SATALink/SATARaid] Serial ATA Controller
 1096  Alacron
 1097  Appian Technology
 1098  Quantum Designs (H.K.) Ltd
@@ -2742,6 +2813,7 @@
 		10b7 7000  10/100 Mini PCI Ethernet Adapter
 		10f1 2466  Tiger MPX S2466 (3C920 Integrated Fast Ethernet Controller)
 	9201  3C920B-EMB Integrated Fast Ethernet Controller [Tornado]
+		1043 80ab  A7N8X Deluxe onboard 3C920B-EMB Integrated Fast Ethernet Controller
 	9202  3Com 3C920B-EMB-WNM Integrated Fast Ethernet Controller
 	9210  3C920B-EMB-WNM Integrated Fast Ethernet Controller
 	9300  3CSOHO100B-TX 910-A01 [tulip]
@@ -2837,6 +2909,7 @@
 	5219  M5219
 	5225  M5225
 	5229  M5229 IDE
+		1014 050f  ThinkPad R30
 		1043 8053  A7A266 Motherboard IDE
 	5235  M5225
 	5237  USB 1.1 Controller
@@ -2859,8 +2932,8 @@
 	545a  SmartLink SmartPCI563 56K Modem
 	5471  M5471 Memory Stick Controller
 	5473  M5473 SD-MMC Controller
-	7101  M7101 PMU
-		10b9 7101  ALI M7101 Power Management Controller
+	7101  M7101 Power Management Controller [PMU]
+		1014 0510  ThinkPad R30
 10ba  Mitsubishi Electric Corp.
 	0301  AccelGraphics AccelECLIPSE
 	0304  AccelGALAXY A2100 [OEM Evans & Sutherland]
@@ -3001,6 +3074,7 @@
 		1043 0205  PCI-V3800
 		1043 4000  AGP-V3800PRO
 		1048 0c21  Synergy II
+		107d 2134  WinFast 3D S320 II + TV-Out
 		1092 4804  Viper V770
 		1092 4a00  Viper V770
 		1092 4a02  Viper V770 Ultra
@@ -3041,11 +3115,13 @@
 		1554 1041  Pixelview RIVA TNT2 M64
 	002e  NV6 [Vanta]
 	002f  NV6 [Vanta]
+	0041  NV40 OS1RT00B30
 	0060  nForce2 ISA Bridge
 		1043 80ad  A7N8X Mainboard
 	0064  nForce2 SMBus (MCP)
 	0065  nForce2 IDE
 	0066  nForce2 Ethernet Controller
+		1043 80a7  A7N8X Mainboard onboard nForce2 Ethernet
 	0067  nForce2 USB Controller
 		1043 0c11  A7N8X Mainboard
 	0068  nForce2 USB Controller
@@ -3292,6 +3368,7 @@
 		1071 8160  MIM2000
 		10bd 0320  EP-320X-R
 		10ec 8139  RT8139
+		1113 ec01  FNC-0107TX
 		1186 1300  DFE-538TX
 		1186 1320  SN5200
 		1186 8139  DRN-32TX
@@ -3342,7 +3419,7 @@
 10f9  PC Direct
 10fa  Truevision
 	000c  TARGA 1000
-10fb  Thesys Gesellschaft fĂĽr Mikroelektronik mbH
+10fb  Thesys Gesellschaft für Mikroelektronik mbH
 	186f  TH 6255
 10fc  I-O Data Device, Inc.
 # What's in the cardbus end of a Sony ACR-A01 card, comes with newer Vaio CD-RW drives
@@ -3358,6 +3435,7 @@
 	9400  INI-940
 	9401  INI-950
 	9500  360P
+	9502  Initio INI-9100UW Ultra Wide SCSI Controller INIC-950P chip
 1102  Creative Labs
 	0002  SB Live! EMU10k1
 		1102 0020  CT4850 SBLive! Value
@@ -3507,13 +3585,16 @@
 		0e11 0097  SoundMax Digital Integrated Audio
 		0e11 b194  Soundmax integrated digital audio
 		1019 0985  P6VXA Motherboard
+		1043 1106  A7V133/A7V133-C Mainboard
 		1106 4511  Onboard Audio on EP7KXA
 		1458 7600  Onboard Audio
 		1462 3091  MS-6309 Onboard Audio
+		1462 3300  MS-6330 Onboard Audio
 		15dd 7609  Onboard Audio
 	3059  VT8233/A/8235/8237 AC97 Audio Controller
 		1019 0a81  L7VTA v1.0 Motherboard (KT400-8235)
 		1043 8095  A7V8X Motherboard (Realtek ALC650 codec)
+		1043 80a1  A7V8X-X Motherboard
 		1043 80b0  A7V600 motherboard (ADI AD1980 codec [SoundMAX])
 		1106 3059  L7VMM2 Motherboard
 		1297 c160  FX41 motherboard (Realtek ALC650 codec)
@@ -3526,6 +3607,7 @@
 		1186 1401  DFE-530TX rev B
 		13b9 1421  LD-10/100AL PCI Fast Ethernet Adapter (rev.B)
 	3068  Intel 537 [AC97 Modem]
+		1462 309e  MS-6309 Saturn Motherboard
 	3074  VT8233 PCI to ISA Bridge
 		1043 8052  VT8233A
 	3091  VT8633 [Apollo Pro266]
@@ -3906,7 +3988,15 @@
 		1133 1c0b  Diva Server V-PRI/T1-24 Cornet NQ 3
 		1133 1c0c  Diva Server V-PRI/E1-30 Cornet NQ 3
 	e01e  Diva Server 2PRI
+		1133 1e00  Diva Server V-2PRI/E1-60
+		1133 1e01  Diva Server V-2PRI/T1-48
+		1133 1e02  Diva Server 2PRI/E1-60
+		1133 1e03  Diva Server 2PRI/T1-48
 	e020  Diva Server 4PRI
+		1133 2000  Diva Server V-4PRI/E1-120
+		1133 2001  Diva Server V-4PRI/T1-96
+		1133 2002  Diva Server 4PRI/E1-120
+		1133 2003  Diva Server 4PRI/T1-96
 	e024  Diva Server Analog-4P
 	e028  Diva Server Analog-8P
 1134  Mercury Computer Systems
@@ -4145,6 +4235,7 @@
 1165  Imagraph Corporation
 	0001  Motion TPEG Recorder/Player with audio
 1166  ServerWorks
+	0000  CMIC-LE
 	0005  CNB20-LE Host Bridge
 	0006  CNB20HE Host Bridge
 	0007  CNB20-LE Host Bridge
@@ -4152,13 +4243,13 @@
 	0009  CNB20LE Host Bridge
 	0010  CIOB30
 	0011  CMIC-HE
-	0012  CMIC-LE
+	0012  CMIC-WS Host Bridge (GC-LE chipset)
 	0013  CNB20-HE Host Bridge
-	0014  CNB20-HE Host Bridge
+	0014  CMIC-LE Host Bridge (GC-LE chipset)
 	0015  CMIC-GC Host Bridge
 	0016  CMIC-GC Host Bridge
 	0017  GCNB-LE Host Bridge
-	0101  CIOB-X2
+	0101  CIOB-X2 PCI-X I/O Bridge
 	0110  CIOB-E I/O Bridge with Gigabit Ethernet
 	0200  OSB4 South Bridge
 	0201  CSB5 South Bridge
@@ -4255,6 +4346,7 @@
 		1186 1300  DFE-538TX 10/100 Ethernet Adapter
 		1186 1301  DFE-530TX+ 10/100 Ethernet Adapter
 	1340  DFE-690TXD CardBus PC Card
+	1541  DFE-680TXD CardBus PC Card
 	1561  DRP-32TXD Cardbus PC Card
 	3300  DWL-510 2.4GHz Wireless PCI Adapter
 	3b05  DWL-G650+ CardBus PC Card
@@ -4337,9 +4429,10 @@
 11a9  InnoSys Inc.
 	4240  AMCC S933Q Intelligent Serial Card
 11aa  Actel
-# (formerly Galileo technologies)
-11ab  Marvell
+# Formerly Galileo Technology, Inc.
+11ab  Marvell Technology Group Ltd.
 	0146  GT-64010/64010A System Controller
+	1fa6  Marvell W8300 802.11 Adapter
 	4320  Yukon Gigabit Ethernet 10/100/1000Base-T Adapter
 	4611  GT-64115 System Controller
 	4620  GT-64120/64120A/64121A System Controller
@@ -4677,6 +4770,7 @@
 	6933  OZ6933 Cardbus Controller
 		1025 1016  Travelmate 612 TX
 	6972  OZ6912 Cardbus Controller
+		1014 020c  ThinkPad R30
 		1179 0001  Magnia Z310
 	7110  OZ711Mx MultiMediaBay Accelerator
 	7112  OZ711EC1/M1 SmartCardBus MultiMediaBay Controller
@@ -4762,6 +4856,7 @@
 122c  Sican GmbH
 122d  Aztech System Ltd
 	1206  368DSP
+	1400  Trident PCI288-Q3DII (NX)
 	50dc  3328 Audio
 		122d 0001  3328 Audio
 	80da  3328 Audio
@@ -4905,11 +5000,15 @@
 	3873  Prism 2.5 Wavelan chipset
 		1186 3501  DWL-520 Wireless PCI Adapter
 		1186 3700  DWL-520 Wireless PCI Adapter, Rev E1
+		1385 4105  MA311 802.11b wireless adapter
 		1668 0414  HWP01170-01 802.11b PCI Wireless Adapter
 		16a5 1601  AIR.mate PC-400 PCI Wireless LAN Adapter
 		1737 3874  WMP11 Wireless 802.11b PCI Adapter
 		8086 2513  Wireless 802.11b MiniPCI Adapter
+	3886  ISL3886 [Prism Javelin/Prism Xbow]
 	3890  Intersil ISL3890 [Prism GT/Prism Duette]
+		10b8 a835  SMC2835W V2 Wireless Cardbus Adapter
+		16a5 1605  ALLNET ALL0271 Wireless PCI Adapter
 		17cf 0014  Ovislink WL-5400PCM, Prism GT
 	8130  HMP8130 NTSC/PAL Video Decoder
 	8131  HMP8131 NTSC/PAL Video Decoder
@@ -5155,7 +5254,7 @@
 	9132  Ethernet 100/10 MBit
 1283  Integrated Technology Express, Inc.
 	673a  IT8330G
-	8212  IT/ITE8212 Dual channel ATA RAID
+	8212  IT/ITE8212 Dual channel ATA RAID controller
 	8330  IT8330G
 	8872  IT8874F PCI Dual Serial Port Controller
 	8888  IT8888F PCI to ISA Bridge with SMB
@@ -5466,7 +5565,8 @@
 	0985  NC100 Network Everywhere Fast Ethernet 10/100
 	1985  21x4x DEC-Tulip compatible 10/100 Ethernet
 	2850  HSP MicroModem 56
-	8201  [ADMtek] SP906B_V2 Wireless LAN adapter
+	8201  ADMtek ADM8211 802.11b Wireless Interface
+		10b8 2635  SMC2635W 802.11b (11Mbps) wireless lan pcmcia (cardbus) card
 		1317 8201  SMC2635W 802.11b (11mbps) wireless lan pcmcia (cardbus) card
 	9511  21x4x DEC-Tulip compatible 10/100 Ethernet
 1318  Packet Engines Inc.
@@ -5535,7 +5635,6 @@
 132d  Integrated Silicon Solution, Inc.
 1330  MMC Networks
 1331  Radisys Corp.
-	0030  ENP-2611
 	8200  82600 Host Bridge
 	8201  82600 IDE
 	8202  82600 USB
@@ -5659,9 +5758,11 @@
 1385  Netgear
 	4100  802.11b Wireless Adapter (MA301)
 	4105  MA311 802.11b wireless adapter
+	4a00  WAG311 802.11abg Wireless Adapter
 	620a  GA620 Gigabit Ethernet
 	622a  GA622
 	630a  GA630 Gigabit Ethernet
+	f004  FA310TX
 1386  Video Domain Technologies
 1387  Systran Corp
 1388  Hitachi Information Technology Co Ltd
@@ -5720,6 +5821,7 @@
 13a6  Videonics Inc
 13a7  Teles AG
 13a8  Exar Corp.
+	0154  XR17C154 Quad UART
 	0158  XR17C158 Octal UART
 13a9  Siemens Medical Systems, Ultrasound Group
 13aa  Broadband Networks Inc
@@ -5752,6 +5854,7 @@
 13c1  3ware Inc
 	1000  3ware ATA-RAID
 	1001  3ware 7000-series ATA-RAID
+		13c1 1001  3ware Inc 3ware 7xxx/8xxx-series PATA/SATA-RAID
 	1002  3ware ATA-RAID
 13c2  Technotrend Systemtechnik GmbH
 13c3  Janz Computer AG
@@ -5884,10 +5987,11 @@
 140f  Salient Systems Corp
 1410  Midas lab Inc
 1411  Ikos Systems Inc
-1412  IC Ensemble Inc
-	1712  ICE1712 [Envy24]
+# formerly IC Ensemble Inc.
+1412  VIA Technologies Inc.
+	1712  ICE1712 [Envy24] PCI Multi-Channel I/O Controller
 		1412 d638  M-Audio Delta 410
-	1724  ICE1724 [Envy24HT]
+	1724  VT1720/24 [Envy24PT/HT] PCI Multi-Channel Audio Controller
 1413  Addonics
 1414  Microsoft Corporation
 1415  Oxford Semiconductor Ltd
@@ -5990,6 +6094,7 @@
 1460  DYNARC INC
 1461  Avermedia Technologies Inc
 1462  Micro-Star International Co., Ltd.
+	6825  PCI Card wireless 11g [PC54G]
 	8725  NVIDIA NV25 [GeForce4 Ti 4600] VGA Adapter
 # MSI G4Ti4800, 128MB DDR SDRAM, TV-Out, DVI-I
 	9000  NVIDIA NV28 [GeForce4 Ti 4800] VGA Adapter
@@ -6150,8 +6255,9 @@
 14d6  Accusys Inc
 14d7  Hirakawa Hewtech Corp
 14d8  HOPF Elektronik GmBH
-14d9  Alpha Processor Inc
-	0010  AP1011 HyperTransport-PCI Bridge [Sturgeon]
+# Formerly SiPackets, Inc., formerly API NetWorks, Inc., formerly Alpha Processor, Inc.
+14d9  Alliance Semiconductor Corporation
+	0010  AP1011/SP1011 HyperTransport-PCI Bridge [Sturgeon]
 14da  National Aerospace Laboratories
 14db  AFAVLAB Technology Inc
 	2120  TK9902
@@ -6175,6 +6281,14 @@
 14e2  INFOLIBRIA
 14e3  AMTELCO
 14e4  Broadcom Corporation
+	0800  Sentry5 Chipcommon I/O Controller
+	0804  Sentry5 PCI Bridge
+	0805  Sentry5 MIPS32 CPU
+	0806  Sentry5 Ethernet Controller
+	080b  Sentry5 Crypto Accelerator
+	080f  Sentry5 DDR/SDR RAM Controller
+	0811  Sentry5 External Interface Core
+	0816  BCM3302 Sentry5 MIPS32 CPU
 	1644  NetXtreme BCM5700 Gigabit Ethernet
 		1014 0277  Broadcom Vigil B5700 1000Base-T
 		1028 00d1  Broadcom BCM5700
@@ -6241,21 +6355,14 @@
 	164d  NetXtreme BCM5702FE Gigabit Ethernet
 	1653  NetXtreme BCM5705 Gigabit Ethernet
 	1654  NetXtreme BCM5705_2 Gigabit Ethernet
-	1658  NetXtreme BCM5720 Gigabit Ethernet
-	1659  NetXtreme BCM5721 Gigabit Ethernet
+	1659  NetXtreme BCM5721 Gigabit Ethernet PCI Express
 	165d  NetXtreme BCM5705M Gigabit Ethernet
 	165e  NetXtreme BCM5705M_2 Gigabit Ethernet
-	166e  NetXtreme BCM5705F Gigabit Ethernet
-	1676  NetXtreme BCM5750 Gigabit Ethernet
-	1677  NetXtreme BCM5751 Gigabit Ethernet
-	167c  NetXtreme BCM5750M Gigabit Ethernet
-	167d  NetXtreme BCM5751M Gigabit Ethernet
-	167e  NetXtreme BCM5751F Gigabit Ethernet
+	1677  NetXtreme BCM5751 Gigabit Ethernet PCI Express
 	1696  NetXtreme BCM5782 Gigabit Ethernet
 		103c 12bc  HP d530 CMT (DG746A)
 		14e4 000d  NetXtreme BCM5782 1000Base-T
 	169c  NetXtreme BCM5788 Gigabit Ethernet
-	169d  NetXtreme BCM5789 Gigabit Ethernet
 	16a6  NetXtreme BCM5702X Gigabit Ethernet
 		0e11 00bb  NC7760 Gigabit Server Adapter (PCI-X, 10/100/1000-T)
 		1028 0126  BCM5702 1000Base-T
@@ -6279,13 +6386,17 @@
 		103c 12ca  HP Combo FC/GigE-T [A9784A]
 		14e4 0009  NetXtreme BCM5703 1000Base-T
 		14e4 000a  NetXtreme BCM5703 1000Base-SX
-	170d  NetXtreme BCM5901 Gigabit Ethernet
-	170e  NetXtreme BCM5901_2 Gigabit Ethernet
+	170c  BCM4401-B0 100Base-TX
+	170d  NetXtreme BCM5901 100Base-TX
+	170e  NetXtreme BCM5901 100Base-TX
+	3352  BCM3352
+	3360  BCM3360
 	4210  BCM4210 iLine10 HomePNA 2.0
 	4211  BCM4211 iLine10 HomePNA 2.0 + V.90 56k modem
 	4212  BCM4212 v.90 56k modem
 	4301  BCM4301 802.11b
-	4320  BCM94306 802.11g
+	4307  BCM4307 802.11b Wireless LAN Controller
+	4320  BCM4306 802.11b/g Wireless LAN Controller
 		1028 0001  TrueMobile 1300 WLAN Mini-PCI Card
 		1737 4320  WPC54G
 	4324  BCM4309 802.11a/b/g
@@ -6293,12 +6404,47 @@
 	4401  BCM4401 100Base-T
 		1043 80a8  A7V8X motherboard
 	4402  BCM4402 Integrated 10/100BaseT
+	4403  BCM4402 V.90 56k Modem
 	4410  BCM4413 iLine32 HomePNA 2.0
 	4411  BCM4413 V.90 56k modem
 	4412  BCM4413 10/100BaseT
+	4430  BCM44xx CardBus iLine32 HomePNA 2.0
+	4432  BCM44xx CardBus 10/100BaseT
+	4610  BCM4610 Sentry5 PCI to SB Bridge
+	4611  BCM4610 Sentry5 iLine32 HomePNA 1.0
+	4612  BCM4610 Sentry5 V.90 56k Modem
+	4613  BCM4610 Sentry5 Ethernet Controller
+	4614  BCM4610 Sentry5 External Interface
+	4615  BCM4610 Sentry5 USB Controller
+	4704  BCM4704 PCI to SB Bridge
+	4708  BCM4708 Sentry5 PCI to SB Bridge
+	4710  BCM4710 Sentry5 PCI to SB Bridge
+	4711  BCM47xx Sentry5 iLine32 HomePNA 2.0
+	4712  Sentry5 UART
+	4713  Sentry5 Ethernet Controller
+	4714  BCM47xx Sentry5 External Interface
+	4715  Sentry5 USB Controller
+	4716  BCM47xx Sentry5 USB Host Controller
+	4717  BCM47xx Sentry5 USB Device Controller
+	4718  Sentry5 Crypto Accelerator
+	5365  BCM5365P Sentry5 Host Bridge
+	5600  BCM5600 StrataSwitch 24+2 Ethernet Switch Controller
+	5605  BCM5605 StrataSwitch 24+2 Ethernet Switch Controller
+	5615  BCM5615 StrataSwitch 24+2 Ethernet Switch Controller
+	5625  BCM5625 StrataSwitch 24+2 Ethernet Switch Controller
+	5645  BCM5645 StrataSwitch 24+2 Ethernet Switch Controller
+	5670  BCM5670 8-Port 10GE Ethernet Switch Fabric
+	5680  BCM5680 G-Switch 8 Port Gigabit Ethernet Switch Controller
 	5690  BCM5690 12-port Multi-Layer Gigabit Ethernet Switch
+	5691  BCM5691 GE/10GE 8+2 Gigabit Ethernet Switch Controller
 	5820  BCM5820 Crypto Accelerator
 	5821  BCM5821 Crypto Accelerator
+	5822  BCM5822 Crypto Accelerator
+	5823  BCM5823 Crypto Accelerator
+	5824  BCM5824 Crypto Accelerator
+	5840  BCM5840 Crypto Accelerator
+	5841  BCM5841 Crypto Accelerator
+	5850  BCM5850 Crypto Accelerator
 14e5  Pixelfusion Ltd
 14e6  SHINING Technology Inc
 14e7  3CX
@@ -6823,11 +6969,16 @@
 1619  FarSite Communications Ltd
 	0400  FarSync T2P (2 port X.21/V.35/V.24)
 	0440  FarSync T4P (4 port X.21/V.35/V.24)
+# www.rioworks.com
+161f  Rioworks
 1626  TDK Semiconductor Corp.
 	8410  RTL81xx Fast Ethernet
 1629  Kongsberg Spacetec AS
 	1003  Format synchronizer v3.0
 	2002  Fast Universal Data Output
+# This seems to occur on their 802.11b Wireless card WMP-11
+1637  Linksys
+	3874  Linksys 802.11b WMP11 PCI Wireless card
 1638  Standard Microsystems Corp [SMC]
 	1100  SMC2602W EZConnect/Addtron AWA-100/Eumitcom WL11000
 163c  Smart Link Ltd.
@@ -6862,6 +7013,7 @@
 		168c 0013  WG511T Wireless CardBus Adapter
 		168c 1025  DWL-G650B2 Wireless CardBus Adapter
 	1014  AR5212 802.11abg NIC
+16a5  Tekram Technology Co.,Ltd.
 16ab  Global Sun Technology Inc
 	1100  GL24110P
 	1101  PLX9052 PCMCIA-to-PCI Wireless LAN
@@ -6874,9 +7026,13 @@
 16cd  Densitron Technologies
 # www.pikatechnologies.com
 16df  PIKA Technologies Inc.
+16e3  European Space Agency
+	1e0f  LEON2FT Processor
 16ec  U.S. Robotics
 	00ff  USR997900 10/100 Mbps PCI Network Card
 	3685  Wireless Access PCI Adapter Model 022415
+16f4  Vweb Corp
+	8000  VW2010
 16f6  VideoTele.com, Inc.
 # www.internetmachines.com
 1702  Internet Machines Corporation (IMC)
@@ -6884,8 +7040,12 @@
 170b  NetOctave
 	0100  NSP2000-SSL crypto accelerator
 170c  YottaYotta Inc.
+# Seems to be a 2nd ID for Vitesse Semiconductor
+1725  Vitesse Semiconductor
+	7174  VSC7174 PCI/PCI-X Serial ATA Host Bus Controller
 172a  Accelerated Encryption
 1737  Linksys
+	0013  WMP54G Wireless Pci Card
 	1032  Gigabit Network Adapter
 		1737 0015  EG1032 v2 Instant Gigabit Network Adapter
 	1064  Gigabit Network Adapter
@@ -6914,10 +7074,12 @@
 	0004  CAMAC Controller
 	0005  PROFIBUS
 	0006  AMCC HOTlink
+1797  JumpTec h, GMBH
 1799  Belkin
 	6001  Wireless PCI Card - F5D6001
 	6020  Wireless PCMCIA Card - F5D6020
 	6060  Wireless PDA Card - F5D6060
+	7000  Wireless PCI Card - F5D7000
 17af  Hightech Information System Ltd.
 17b3  Hawking Technologies
 	ab08  PN672TX 10/100 Ethernet
@@ -6929,6 +7091,9 @@
 	2280  USB 2.0
 # S2io ships 10Gb PCI-X Ethernet adapters www.s2io.com
 17d5  S2io Inc.
+# Supplying full name for a currently green entry
+17fe  Linksys, A Division of Cisco Systems
+	2220  [AirConn] INPROCOMM IPN 2220 WLAN Adapter (rev 01)
 1813  Ambient Technologies Inc
 	4000  HaM controllerless modem
 		16be 0001  V9x HAM Data Fax Modem
@@ -6937,6 +7102,8 @@
 1814  RaLink
 	0101  Wireless PCI Adpator RT2400 / RT2460
 	0201  Ralink RT2500 802.11 Cardbus Reference Card
+1820  InfiniCon Systems Inc.
+1822  Twinhan Technology Co. Ltd
 1830  Credence Systems Corporation
 1851  Microtune, Inc.
 1852  Anritsu Corp.
@@ -6952,6 +7119,8 @@
 # found e.g. on KNC DVB-S card
 1894  KNC One
 18a1  Astute Networks Inc.
+18bc  Info-Tek Corp.
+18c9  ARVOO Engineering BV
 18ca  XGI - Xabre Graphics Inc
 	0040  Volari V8
 18e6  MPL AG
@@ -7018,6 +7187,7 @@
 	0008  GLINT Gamma G1
 	0009  Permedia II 2D+3D
 		1040 0011  AccelStar II
+		13e9 1000  6221L-4U
 		3d3d 0100  AccelStar II 3D Accelerator
 		3d3d 0111  Permedia 3:16
 		3d3d 0114  Santa Ana
@@ -7269,10 +7439,11 @@
 5555  Genroco, Inc
 	0003  TURBOstor HFP-832 [HiPPI NIC]
 5654  VoiceTronix Pty Ltd
+	3132  OpenSwitch12
 5700  Netpower
 5851  Exacq Technologies
 6356  UltraStor
-6374  c't Magazin fĂĽr Computertechnik
+6374  c't Magazin für Computertechnik
 	6773  GPPCI
 6409  Logitec Corp.
 6666  Decision Computer International Co.
@@ -7292,6 +7463,8 @@
 		0008 1000  WorldMark 4300 INCA ASIC
 	0039  21145 Fast Ethernet
 	0122  82437FX
+	0309  80303 I/O Processor PCI-to-PCI Bridge
+	030d  80312 I/O Companion Chip PCI-to-PCI Bridge
 	0326  PCI Bridge Hub I/OxAPIC Interrupt Controller A
 	0327  PCI Bridge Hub I/OxAPIC Interrupt Controller B
 	0329  PCI Bridge Hub A
@@ -7315,13 +7488,38 @@
 	0340  41210 [Lanai] Serial to Parallel PCI Bridge
 # B-segment bridge
 	0341  41210 [Lanai] Serial to Parallel PCI Bridge
-	0482  82375EB
-	0483  82424ZX [Saturn]
-	0484  82378IB [SIO ISA Bridge]
-	0486  82430ZX [Aries]
-	04a3  82434LX [Mercury/Neptune]
+	0482  82375EB/SB PCI to EISA Bridge
+	0483  82424TX/ZX [Saturn] CPU to PCI bridge
+	0484  82378ZB/IB, 82379AB (SIO, SIO.A) PCI to ISA Bridge
+	0486  82425EX/ZX [Aries] PCIset with ISA bridge
+	04a3  82434LX/NX [Mercury/Neptune] Processor to PCI bridge
 	04d0  82437FX [Triton FX]
+	0500  E8870 Processor bus control
+	0501  E8870 Memory controller
+# and registers common to both SPs
+	0502  E8870 Scalability Port 0
+# and global performance monitoring
+	0503  E8870 Scalability Port 1
+	0510  E8870IO Hub Interface Port 0 registers (8-bit compatibility port)
+	0511  E8870IO Hub Interface Port 1 registers
+	0512  E8870IO Hub Interface Port 2 registers
+	0513  E8870IO Hub Interface Port 3 registers
+	0514  E8870IO Hub Interface Port 4 registers
+	0515  E8870IO General SIOH registers
+	0516  E8870IO RAS registers
+	0530  E8870SP Scalability Port 0 registers
+	0531  E8870SP Scalability Port 1 registers
+	0532  E8870SP Scalability Port 2 registers
+	0533  E8870SP Scalability Port 3 registers
+	0534  E8870SP Scalability Port 4 registers
+	0535  E8870SP Scalability Port 5 registers
+# (bi-interleave 0) and global registers that are neither per-port nor per-interleave
+	0536  E8870SP Interleave registers 0 and 1
+# (bi-interleave 1)
+	0537  E8870SP Interleave registers 2 and 3
 	0600  RAID Controller
+		8086 01c1  ICP Vortex GDT8546RZ
+		8086 01f7  SCRU32
 	0960  80960RP [i960 RP Microprocessor/Bridge]
 	0962  80960RM [i960RM Bridge]
 	0964  80960RP [i960 RP Microprocessor/Bridge]
@@ -7406,6 +7604,7 @@
 	1019  82547EI Gigabit Ethernet Controller (LOM)
 		1458 1019  GA-8IPE1000 Pro2 motherboard (865PE)
 		8086 1019  PRO/1000 CT Desktop Connection
+		8086 3427  S875WP1-E mainboard
 	101d  82546EB Gigabit Ethernet Controller
 		8086 1000  PRO/1000 MT Quad Port Server Adapter
 	101e  82540EP Gigabit Ethernet Controller (Mobile)
@@ -7453,13 +7652,16 @@
 		16be 1040  V.9X DSP Data Fax Modem
 	1043  PRO/Wireless LAN 2100 3B Mini PCI Adapter
 		8086 2527  MIM2000/Centrino
-	1048  Intel(R) PRO/10GbE LR Server Adapter
+	1048  PRO/10GbE LR Server Adapter
 		8086 a01f  PRO/10GbE LR Server Adapter
 		8086 a11f  PRO/10GbE LR Server Adapter
 	1050  82562EZ 10/100 Ethernet Controller
 		1462 728c  865PE Neo2 (MS-6728)
+		1462 758c  MS-6758 (875P Neo)
+		8086 3427  S875WP1-E mainboard
 	1051  82801EB/ER (ICH5/ICH5R) integrated LAN Controller
 	1059  82551QM Ethernet Controller
+	1065  82801FB/FBM/FR/FW/FRW (ICH6 Family) LAN Controller
 # Updated controller name from 82547EI to 82547GI
 	1075  82547GI Gigabit Ethernet Controller
 		8086 0075  PRO/1000 CT Network Connection
@@ -7516,8 +7718,8 @@
 		4c53 1050  CT7 mainboard
 		4c53 1051  CE7 mainboard
 		4c53 1070  PC6 mainboard
-	1221  82092AA_0
-	1222  82092AA_1
+	1221  82092AA PCI to PCMCIA Bridge
+	1222  82092AA IDE Controller
 	1223  SAA7116
 	1225  82452KX/GX [Orion]
 	1226  82596 PRO/10 PCI
@@ -7587,6 +7789,7 @@
 		1259 2560  AT-2560 100
 		1259 2561  AT-2560 100 FX Ethernet Adapter
 		1266 0001  NE10/100 Adapter
+		13e9 1000  6221L-4U
 		144d 2501  SEM-2000 MiniPCI LAN Adapter
 		144d 2502  SEM-2100IL MiniPCI LAN Adapter
 		1668 1100  EtherExpress PRO/100B (TX) (MiniPCI Ethernet+Modem)
@@ -7675,6 +7878,7 @@
 		8086 3010  EtherExpress PRO/100 S Network Connection
 		8086 3011  EtherExpress PRO/100 S Network Connection
 		8086 3012  EtherExpress PRO/100 Network Connection
+		8086 3411  SDS2 Mainboard
 	122d  430FX - 82437FX TSC [Triton I]
 	122e  82371FB PIIX ISA [Triton I]
 	1230  82371FB PIIX IDE [Triton I]
@@ -7682,13 +7886,15 @@
 	1234  430MX - 82371MX Mobile PCI I/O IDE Xcelerator (MPIIX)
 	1235  430MX - 82437MX Mob. System Ctrlr (MTSC) & 82438MX Data Path (MTDP)
 	1237  440FX - 82441FX PMC [Natoma]
-	1239  82371FB
-	123b  82380PB
-	123c  82380AB
+	1239  82371FB PIIX IDE Interface
+	123b  82380PB PCI to PCI Docking Bridge
+	123c  82380AB (MISA) Mobile PCI-to-ISA Bridge
 	123d  683053 Programmable Interrupt Device
+# in" hidden" mode
+	123e  82466GX (IHPC) Integrated Hot-Plug Controller
 	123f  82466GX Integrated Hot-Plug Controller (IHPC)
-	1240  752 AGP
-	124b  82380FB
+	1240  82752 (752) AGP Graphics Accelerator
+	124b  82380FB (MPCI2) Mobile Docking Controller
 	1250  430HX - 82439HX TXC [Triton II]
 	1360  82806AA PCI64 Hub PCI Bridge
 	1361  82806AA PCI64 Hub Controller (HRes)
@@ -7782,7 +7988,7 @@
 	2446  Intel 537 [82801BA/BAM AC'97 Modem]
 		1025 1016  Travelmate 612 TX
 		104d 80df  Vaio PCG-FX403
-	2448  82801BAM/CAM PCI Bridge
+	2448  82801 PCI Bridge
 	2449  82801BA/BAM/CA/CAM Ethernet Controller
 		0e11 0012  EtherExpress PRO/100 VM
 		0e11 0091  EtherExpress PRO/100 VE
@@ -7824,7 +8030,7 @@
 		8086 4532  D815EEA2 mainboard
 		8086 4557  D815EGEW Mainboard
 	244c  82801BAM ISA Bridge (LPC)
-	244e  82801BA/CA/DB/EB/ER Hub interface to PCI Bridge
+	244e  82801 PCI Bridge
 		1014 0267  NetVista A30p
 	2450  82801E ISA Bridge (LPC)
 	2452  82801E USB
@@ -7879,45 +8085,45 @@
 	248b  82801CA Ultra ATA Storage Controller
 		15d9 3480  P4DP6
 	248c  82801CAM ISA Bridge (LPC)
-	24c0  82801DB (ICH4) LPC Bridge
+	24c0  82801DB/DBL (ICH4/ICH4-L) LPC Bridge
 		1014 0267  NetVista A30p
 		1462 5800  845PE Max (MS-6580)
-	24c2  82801DB (ICH4) USB UHCI #1
+	24c2  82801DB/DBL/DBM (ICH4/ICH4-L/ICH4-M) USB UHCI Controller #1
 		1014 0267  NetVista A30p
 		1071 8160  MIM2000
 		1462 5800  845PE Max (MS-6580)
-	24c3  82801DB/DBM (ICH4) SMBus Controller
+	24c3  82801DB/DBL/DBM (ICH4/ICH4-L/ICH4-M) SMBus Controller
 		1014 0267  NetVista A30p
 		1071 8160  MIM2000
 		1458 24c2  GA-8PE667 Ultra
 		1462 5800  845PE Max (MS-6580)
 		4c53 1090  Cx9 / Vx9 mainboard
-	24c4  82801DB (ICH4) USB UHCI #2
+	24c4  82801DB/DBL/DBM (ICH4/ICH4-L/ICH4-M) USB UHCI Controller #2
 		1014 0267  NetVista A30p
 		1071 8160  MIM2000
 		1462 5800  845PE Max (MS-6580)
 		4c53 1090  Cx9 / Vx9 mainboard
-	24c5  82801DB (ICH4) AC'97 Audio Controller
+	24c5  82801DB/DBL/DBM (ICH4/ICH4-L/ICH4-M) AC'97 Audio Controller
 		0e11 00b8  Analog Devices Inc. codec [SoundMAX]
 		1014 0267  NetVista A30p
 		1071 8160  MIM2000
 		1458 a002  GA-8PE667 Ultra
 		1462 5800  845PE Max (MS-6580)
-	24c6  82801DB (ICH4) AC'97 Modem Controller
+	24c6  82801DB/DBL/DBM (ICH4/ICH4-L/ICH4-M) AC'97 Modem Controller
 		1071 8160  MIM2000
-	24c7  82801DB (ICH4) USB UHCI #3
+	24c7  82801DB/DBL/DBM (ICH4/ICH4-L/ICH4-M) USB UHCI Controller #3
 		1014 0267  NetVista A30p
 		1071 8160  MIM2000
 		1462 5800  845PE Max (MS-6580)
 	24ca  82801DBM (ICH4) Ultra ATA Storage Controller
 		1071 8160  MIM2000
-	24cb  82801DB (ICH4) Ultra ATA 100 Storage Controller
+	24cb  82801DB/DBL (ICH4/ICH4-L) UltraATA-100 IDE Controller
 		1014 0267  NetVista A30p
 		1458 24c2  GA-8PE667 Ultra
 		1462 5800  845PE Max (MS-6580)
 		4c53 1090  Cx9 / Vx9 mainboard
 	24cc  82801DBM LPC Interface Controller
-	24cd  82801DB (ICH4) USB2 EHCI Controller
+	24cd  82801DB/DBM (ICH4/ICH4-M) USB 2.0 EHCI Controller
 		1014 0267  NetVista A30p
 		1071 8160  MIM2000
 		1462 3981  845PE Max (MS-6580)
@@ -7927,19 +8133,23 @@
 		103c 12bc  d530 CMT (DG746A)
 		1458 24d1  GA-8IPE1000 Pro2 motherboard (865PE)
 		1462 7280  865PE Neo2 (MS-6728)
+		8086 3427  S875WP1-E mainboard
 	24d2  82801EB/ER (ICH5/ICH5R) USB UHCI #1
 		103c 12bc  d530 CMT (DG746A)
 		1043 80a6  P4P800 Mainboard
 		1462 7280  865PE Neo2 (MS-6728)
+		8086 3427  S875WP1-E mainboard
 	24d3  82801EB/ER (ICH5/ICH5R) SMBus Controller
 		1043 80a6  P4P800 Mainboard
 		1458 24d2  GA-8IPE1000 Pro2 motherboard (865PE)
 		1462 7280  865PE Neo2 (MS-6728)
+		8086 3427  S875WP1-E mainboard
 	24d4  82801EB/ER (ICH5/ICH5R) USB UHCI #2
 		103c 12bc  d530 CMT (DG746A)
 		1043 80a6  P4P800 Mainboard
 		1458 24d2  GA-8IPE1000 Pro2 motherboard (865PE)
 		1462 7280  865PE Neo2 (MS-6728)
+		8086 3427  S875WP1-E mainboard
 	24d5  82801EB/ER (ICH5/ICH5R) AC'97 Audio Controller
 		103c 12bc  Analog Devices codec [SoundMAX Integrated Digital Audio]
 		1043 80f3  P4P800 Mainboard
@@ -7950,22 +8160,26 @@
 		1043 80a6  P4P800 Mainboard
 		1458 24d2  GA-8IPE1000 Pro2 motherboard (865PE)
 		1462 7280  865PE Neo2 (MS-6728)
+		8086 3427  S875WP1-E mainboard
 	24db  82801EB/ER (ICH5/ICH5R) Ultra ATA 100 Storage Controller
 		103c 12bc  d530 CMT (DG746A)
 		1043 80a6  P4P800 Mainboard
 		1458 24d2  GA-8IPE1000 Pro2 motherboard (865PE)
 		1462 7280  865PE Neo2 (MS-6728)
 		1462 7580  MSI 875P
+		8086 3427  S875WP1-E mainboard
 	24dc  82801EB LPC Interface Controller
 	24dd  82801EB/ER (ICH5/ICH5R) USB2 EHCI Controller
 		103c 12bc  d530 CMT (DG746A)
 		1043 80a6  P4P800 Mainboard
 		1458 5006  GA-8IPE1000 Pro2 motherboard (865PE)
 		1462 7280  865PE Neo2 (MS-6728)
+		8086 3427  S875WP1-E mainboard
 	24de  82801EB/ER (ICH5/ICH5R) USB UHCI #4
 		1043 80a6  P4P800 Mainboard
 		1458 24d2  GA-8IPE1000 Pro2 motherboard (865PE)
 		1462 7280  865PE Neo2 (MS-6728)
+		8086 3427  S875WP1-E mainboard
 	24df  82801EB (ICH5R) SATA (cc=RAID)
 	2500  82820 820 (Camino) Chipset Host Bridge (MCH)
 		1028 0095  Precision Workstation 220 Chipset
@@ -7984,23 +8198,23 @@
 	2534  82860 860 (Wombat) Chipset PCI Bridge
 	2540  E7500 Memory Controller Hub
 		15d9 3480  P4DP6
-	2541  E7000 Series Host RASUM Controller
+	2541  E7500/E7501 Host RASUM Controller
 		15d9 3480  P4DP6
 		4c53 1090  Cx9 / Vx9 mainboard
-	2543  E7000 Series Hub Interface B PCI-to-PCI Bridge
-	2544  E7000 Series Hub Interface B RASUM Controller
+	2543  E7500/E7501 Hub Interface B PCI-to-PCI Bridge
+	2544  E7500/E7501 Hub Interface B RASUM Controller
 		4c53 1090  Cx9 / Vx9 mainboard
-	2545  E7000 Series Hub Interface C PCI-to-PCI Bridge
-	2546  E7000 Series Hub Interface C RASUM Controller
-	2547  E7000 Series Hub Interface D PCI-to-PCI Bridge
-	2548  E7000 Series Hub Interface D RASUM Controller
+	2545  E7500/E7501 Hub Interface C PCI-to-PCI Bridge
+	2546  E7500/E7501 Hub Interface C RASUM Controller
+	2547  E7500/E7501 Hub Interface D PCI-to-PCI Bridge
+	2548  E7500/E7501 Hub Interface D RASUM Controller
 	254c  E7501 Memory Controller Hub
 		4c53 1090  Cx9 / Vx9 mainboard
 	2550  E7505 Memory Controller Hub
-	2551  E7000 Series RAS Controller
-	2552  E7000 Series Processor to AGP Controller
-	2553  E7000 Series Hub Interface B PCI-to-PCI Bridge
-	2554  E7000 Series Hub Interface B PCI-to-PCI Bridge RAS Controller
+	2551  E7505/E7205 Series RAS Controller
+	2552  E7505/E7205 PCI-to-AGP Bridge
+	2553  E7505 Hub Interface B PCI-to-PCI Bridge
+	2554  E7505 Hub Interface B PCI-to-PCI Bridge RAS Controller
 	255d  E7205 Memory Controller Hub
 	2560  82845G/GL[Brookdale-G]/GE/PE DRAM Controller/Host-Hub Interface
 		1458 2560  GA-8PE667 Ultra
@@ -8022,14 +8236,17 @@
 	2579  82875P Processor to AGP Controller
 	257b  82875P Processor to PCI to CSA Bridge
 	257e  82875P Processor to I/O Memory Interface
-	2580  Memory Controller Hub
-	2581  Memory Controller Hub PCI Express Port
-	2582  Graphics Controller
-	2584  Workstation Memory Controller Hub
-	2585  Workstation Memory Controller Hub PCI Express Port
+	2580  915G/P/GV Processor to I/O Controller
+	2581  915G/P/GV PCI Express Root Port
+	2582  82915G Express Chipset Family Graphics Controller
+	2584  925X Memory Controller Hub
+	2585  925X PCI Express Root Port
 	2588  Server Memory Controller Hub
 	2589  Server Memory Controller Hub PCI Express Port
 	258a  Graphics Controller
+	2590  Mobile Memory Controller Hub
+	2591  Mobile Memory Controller Hub PCI Express Port
+	2592  Mobile Graphics Controller
 	25a1  6300ESB LPC Interface Controller
 	25a2  6300ESB PATA Storage Controller
 	25a3  6300ESB SATA Storage Controller
@@ -8043,26 +8260,63 @@
 	25ad  6300ESB USB2 Enhanced Host Controller
 	25ae  6300ESB 64-bit PCI-X Bridge
 	25b0  6300ESB SATA RAID Controller
-	2640  I/O Controller Hub LPC
-	2641  I/O Controller Hub LPC
-	2642  I/O Controller Hub LPC
-	2651  I/O Controller Hub SATA cc=ide
-	2652  I/O Controller Hub SATA cc=raid
-	2658  I/O Controller Hub USB
-	2659  I/O Controller Hub USB
-	265a  I/O Controller Hub USB
-	265b  I/O Controller Hub USB
-	265c  I/O Controller Hub USB2
-	2660  I/O Controller Hub PCI Express Port 0
-	2662  I/O Controller Hub PCI Express Port 1
-	2664  I/O Controller Hub PCI Express Port 2
-	2666  I/O Controller Hub PCI Express Port 3
-	2668  I/O Controller Hub Audio
-	266a  I/O Controller Hub SMBus
-	266d  I/O Controller Hub Modem
-	266e  I/O Controller Hub Audio
-	266f  I/O Controller Hub PATA
-	2782  Graphics Controller
+	2600  Server Hub Interface
+	2601  Server Hub PCI Express x4 Port D
+	2602  Server Hub PCI Express x4 Port C0
+	2603  Server Hub PCI Express x4 Port C1
+	2604  Server Hub PCI Express x4 Port B0
+	2605  Server Hub PCI Express x4 Port B1
+	2606  Server Hub PCI Express x4 Port A0
+	2607  Server Hub PCI Express x4 Port A1
+	2608  Server Hub PCI Express x8 Port C
+	2609  Server Hub PCI Express x8 Port B
+	260a  Server Hub PCI Express x8 Port A
+	260c  Server Hub IMI Registers
+	2610  Server Hub System Bus, Boot, and Interrupt Registers
+	2611  Server Hub Address Mapping Registers
+	2612  Server Hub RAS Registers
+	2613  Server Hub Performance Monitoring Registers
+	2614  Server Hub Performance Monitoring Registers
+	2615  Server Hub Performance Monitoring Registers
+	2617  Server Hub Debug Registers
+	2618  Server Hub Debug Registers
+	2619  Server Hub Debug Registers
+	261a  Server Hub Debug Registers
+	261b  Server Hub Debug Registers
+	261c  Server Hub Debug Registers
+	261d  Server Hub Debug Registers
+	261e  Server Hub Debug Registers
+	2620  External Memory Bridge
+	2621  External Memory Bridge Control Registers
+	2622  External Memory Bridge Memory Interleaving Registers
+	2623  External Memory Bridge DDR Initialization and Calibration
+	2624  External Memory Bridge Reserved Registers
+	2625  External Memory Bridge Reserved Registers
+	2626  External Memory Bridge Reserved Registers
+	2627  External Memory Bridge Reserved Registers
+	2640  82801FB/FR (ICH6/ICH6R) LPC Interface Bridge
+	2641  82801FBM (ICH6M) LPC Interface Bridge
+	2642  82801FW/FRW (ICH6W/ICH6RW) LPC Interface Bridge
+	2651  82801FB/FW (ICH6/ICH6W) SATA Controller
+	2652  82801FR/FRW (ICH6R/ICH6RW) SATA Controller
+	2653  82801FBM (ICH6M) SATA Controller
+	2658  82801FB/FBM/FR/FW/FRW (ICH6 Family) USB UHCI #1
+	2659  82801FB/FBM/FR/FW/FRW (ICH6 Family) USB UHCI #2
+	265a  82801FB/FBM/FR/FW/FRW (ICH6 Family) USB UHCI #3
+	265b  82801FB/FBM/FR/FW/FRW (ICH6 Family) USB UHCI #4
+	265c  82801FB/FBM/FR/FW/FRW (ICH6 Family) USB2 EHCI Controller
+	2660  82801FB/FBM/FR/FW/FRW (ICH6 Family) PCI Express Port 1
+	2662  82801FB/FBM/FR/FW/FRW (ICH6 Family) PCI Express Port 2
+	2664  82801FB/FBM/FR/FW/FRW (ICH6 Family) PCI Express Port 3
+	2666  82801FB/FBM/FR/FW/FRW (ICH6 Family) PCI Express Port 4
+	2668  82801FB/FBM/FR/FW/FRW (ICH6 Family) High Definition Audio Controller
+	266a  82801FB/FBM/FR/FW/FRW (ICH6 Family) SMBus Controller
+	266c  82801FB/FBM/FR/FW/FRW (ICH6 Family) LAN Controller
+	266d  82801FB/FBM/FR/FW/FRW (ICH6 Family) AC'97 Modem Controller
+	266e  82801FB/FBM/FR/FW/FRW (ICH6 Family) AC'97 Audio Controller
+	266f  82801FB/FBM/FR/FW/FRW (ICH6 Family) IDE Controller
+	2782  82915G Express Chipset Family Graphics Controller
+	2792  Mobile Graphics Controller
 	3092  Integrated RAID
 	3200  GD31244 PCI-X SATA HBA
 	3340  82855PM Processor to I/O Controller
@@ -8092,7 +8346,7 @@
 	359a  Memory Controller Hub PCI Express Port C1
 	359b  Memory Controller Hub Extended Configuration Registers
 	359e  Workstation Memory Controller Hub
-	4220  Intel(R) PRO/Wireless 2200BG
+	4220  PRO/Wireless 2200BG
 	5200  EtherExpress PRO/100 Intelligent Server
 	5201  EtherExpress PRO/100 Intelligent Server
 		8086 0001  EtherExpress PRO/100 Server Ethernet Adapter
@@ -8155,7 +8409,7 @@
 	7601  82372FB PIIX5 IDE
 	7602  82372FB PIIX5 USB
 	7603  82372FB PIIX5 SMBus
-	7800  i740
+	7800  82740 (i740) AGP Graphics Accelerator
 		003d 0008  Starfighter AGP
 		003d 000b  Starfighter AGP
 		1092 0100  Stealth II G460
@@ -8175,7 +8429,9 @@
 	84e6  460GX - 82466GX Wide and fast PCI eXpander Bridge (WXB)
 	84ea  460GX - 84460GX AGP Bridge (GXB function 1)
 	8500  IXP4xx Family  Network Processor (IXP420, 421, 422, 425 and IXC1100)
-	9000  Intel IXP2000 Familly Network Processor
+	9000  Intel IXP2000 Family Network Processor
+	9001  Intel IXP2400 Network Processor
+	9004  Intel IXP2800 Network Processor
 	9621  Integrated RAID
 	9622  Integrated RAID
 	9641  Integrated RAID
@@ -8184,10 +8440,12 @@
 # observed, and documented in Intel revision note; new mask of 1011:0026
 	b154  21154 PCI-to-PCI Bridge
 	b555  21555 Non transparent PCI-to-PCI Bridge
+		1331 0030  Radisys ENP-2611
 		4c53 1050  CT7 mainboard
 		4c53 1051  CE7 mainboard
 		e4bf 1000  CC8-1-BLUES
 	ffff  450NX/GX [Orion] - 82453KX/GX Memory controller [BUG]
+8401  TRENDware International Inc.
 8800  Trigem Computer Inc.
 	2008  Video assistent component
 8866  T-Square Design Inc.
@@ -8352,15 +8610,18 @@
 	00c1  AIC-7899B U160/m
 	00c3  AIC-7899D U160/m
 	00c5  RAID subsystem HBA
-		1028 00c5  PowerEdge 2550
+		1028 00c5  PowerEdge 2400,2500,2550,4400
 	00cf  AIC-7899P U160/m
 		1028 00ce  PowerEdge 1400
 		1028 00d1  PowerEdge 2550
 		10f1 2462  Thunder K7 S2462
 		15d9 9005  Onboard SCSI Host Adapter
+		8086 3411  SDS2 Mainboard
 	0250  ServeRAID Controller
 		1014 0279  ServeRAID-xx
 		1014 028c  ServeRAID-xx
+# from kernel sources
+	0279  ServeRAID 6M
 	0283  AAC-RAID
 		9005 0283  Catapult
 	0284  AAC-RAID
@@ -8429,7 +8690,7 @@
 		1000 0012  1P2S
 	9845  PCI 9845 Multi-I/O Controller
 		1000 0006  0P6S (6 port 16550a serial card)
-	9855  PCI 9855 Multi-I/O Controller 4 Serial 1 Parallel
+	9855  PCI 9855 Multi-I/O Controller
 		1000 0014  1P4S
 9902  Stargen Inc.
 	0001  SG2010 PCI over Starfabric Bridge
@@ -8444,6 +8705,7 @@
 a727  3Com Corporation
 aa42  Scitex Digital Video
 ac1e  Digital Receiver Technology Inc
+aecb  Adrienne Electronics Corporation
 b1b3  Shiva Europe Limited
 # Pinnacle should be 11bd, but they got it wrong several times --mj
 bd11  Pinnacle Systems, Inc. (Wrong ID)
@@ -8464,9 +8726,9 @@
 dead  Indigita Corporation
 e000  Winbond
 	e000  W89C940
-# see : http://www.schoenfeld.de/inside/Inside_CWMK3.txt
-e159  Individual Computers - Jens Schoenfeld
-	0001  Intel 537
+# see also : http://www.schoenfeld.de/inside/Inside_CWMK3.txt maybe a misuse of TJN id or it use the TJN 3XX chip for other applic
+e159  Tiger Jet Network Inc.
+	0001  Tiger3XX Modem/ISDN interface
 		0059 0001  128k ISDN-S/T Adapter
 		0059 0003  128k ISDN-U Adapter
 	0002  Tiger100APC ISDN chipset
diff -Nru a/drivers/pci/probe.c b/drivers/pci/probe.c
--- a/drivers/pci/probe.c	2004-10-18 14:56:48 -07:00
+++ b/drivers/pci/probe.c	2004-10-18 14:56:48 -07:00
@@ -373,7 +373,10 @@
 		child->bridge_ctl = bctl;
 
 		cmax = pci_scan_child_bus(child);
-		if (cmax > max) max = cmax;
+		if (cmax > max)
+			max = cmax;
+		if (child->subordinate > max)
+			max = child->subordinate;
 	} else {
 		/*
 		 * We need to assign a number to this bus which we always
@@ -571,6 +574,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...
@@ -640,7 +648,7 @@
 		return NULL;
 	
 	/* Fix up broken headers */
-	pci_fixup_device(PCI_FIXUP_HEADER, dev);
+	pci_fixup_device(pci_fixup_header, dev);
 
 	/*
 	 * Add the device to our list of discovered devices
@@ -772,6 +780,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/quirks.c b/drivers/pci/quirks.c
--- a/drivers/pci/quirks.c	2004-10-18 14:55:54 -07:00
+++ b/drivers/pci/quirks.c	2004-10-18 14:55:54 -07:00
@@ -1,10 +1,10 @@
 /*
- * $Id: quirks.c,v 1.5 1998/05/02 19:24:14 mj Exp $
- *
  *  This file contains work-arounds for many known PCI hardware
  *  bugs.  Devices present only on certain architectures (host
  *  bridges et cetera) should be handled in arch-specific code.
  *
+ *  Note: any quirks for hotpluggable devices must _NOT_ be declared __init.
+ *
  *  Copyright (c) 1999 Martin Mares <mj@ucw.cz>
  *
  *  The bridge optimization stuff has been removed. If you really
@@ -39,6 +39,7 @@
 		}
 	}
 }
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL,	PCI_DEVICE_ID_INTEL_82441,	quirk_passive_release );
 
 /*  The VIA VP2/VP3/MVP3 seem to have some 'features'. There may be a workaround
     but VIA don't answer queries. If you happen to have good contacts at VIA
@@ -46,8 +47,6 @@
     
     This appears to be BIOS not version dependent. So presumably there is a 
     chipset level fix */
-    
-
 int isa_dma_bridge_buggy;		/* Exported */
     
 static void __devinit quirk_isa_dma_hangs(struct pci_dev *dev)
@@ -57,34 +56,47 @@
 		printk(KERN_INFO "Activating ISA DMA hang workarounds.\n");
 	}
 }
+	/*
+	 * Its not totally clear which chipsets are the problematic ones
+	 * We know 82C586 and 82C596 variants are affected.
+	 */
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_VIA,	PCI_DEVICE_ID_VIA_82C586_0,	quirk_isa_dma_hangs );
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_VIA,	PCI_DEVICE_ID_VIA_82C596,	quirk_isa_dma_hangs );
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL,    PCI_DEVICE_ID_INTEL_82371SB_0,  quirk_isa_dma_hangs );
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_AL,	PCI_DEVICE_ID_AL_M1533, 	quirk_isa_dma_hangs );
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_NEC,	PCI_DEVICE_ID_NEC_CBUS_1,	quirk_isa_dma_hangs );
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_NEC,	PCI_DEVICE_ID_NEC_CBUS_2,	quirk_isa_dma_hangs );
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_NEC,	PCI_DEVICE_ID_NEC_CBUS_3,	quirk_isa_dma_hangs );
 
 int pci_pci_problems;
 
 /*
  *	Chipsets where PCI->PCI transfers vanish or hang
  */
-
 static void __devinit quirk_nopcipci(struct pci_dev *dev)
 {
-	if((pci_pci_problems&PCIPCI_FAIL)==0)
-	{
+	if ((pci_pci_problems & PCIPCI_FAIL)==0) {
 		printk(KERN_INFO "Disabling direct PCI/PCI transfers.\n");
-		pci_pci_problems|=PCIPCI_FAIL;
+		pci_pci_problems |= PCIPCI_FAIL;
 	}
 }
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_SI,	PCI_DEVICE_ID_SI_5597,		quirk_nopcipci );
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_SI,	PCI_DEVICE_ID_SI_496,		quirk_nopcipci );
 
 /*
  *	Triton requires workarounds to be used by the drivers
  */
- 
 static void __devinit quirk_triton(struct pci_dev *dev)
 {
-	if((pci_pci_problems&PCIPCI_TRITON)==0)
-	{
+	if ((pci_pci_problems&PCIPCI_TRITON)==0) {
 		printk(KERN_INFO "Limiting direct PCI/PCI transfers.\n");
-		pci_pci_problems|=PCIPCI_TRITON;
+		pci_pci_problems |= PCIPCI_TRITON;
 	}
 }
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 	PCI_DEVICE_ID_INTEL_82437, 	quirk_triton ); 
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 	PCI_DEVICE_ID_INTEL_82437VX, 	quirk_triton ); 
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 	PCI_DEVICE_ID_INTEL_82439, 	quirk_triton ); 
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 	PCI_DEVICE_ID_INTEL_82439TX, 	quirk_triton ); 
 
 /*
  *	VIA Apollo KT133 needs PCI latency patch
@@ -104,19 +116,16 @@
 	/* Ok we have a potential problem chipset here. Now see if we have
 	   a buggy southbridge */
 	   
-	p=pci_find_device(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C686, NULL);
-	if(p!=NULL)
-	{
+	p = pci_find_device(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C686, NULL);
+	if (p!=NULL) {
 		pci_read_config_byte(p, PCI_CLASS_REVISION, &rev);
 		/* 0x40 - 0x4f == 686B, 0x10 - 0x2f == 686A; thanks Dan Hollis */
 		/* Check for buggy part revisions */
 		if (rev < 0x40 || rev > 0x42) 
 			return;
-	}
-	else
-	{
+	} else {
 		p = pci_find_device(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8231, NULL);
-		if(p==NULL)	/* No problem parts */
+		if (p==NULL)	/* No problem parts */
 			return;
 		pci_read_config_byte(p, PCI_CLASS_REVISION, &rev);
 		/* Check for buggy part revisions */
@@ -145,27 +154,30 @@
 	pci_write_config_byte(dev, 0x76, busarb);
 	printk(KERN_INFO "Applying VIA southbridge workaround.\n");
 }
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_VIA,	PCI_DEVICE_ID_VIA_8363_0,	quirk_vialatency );
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_VIA,	PCI_DEVICE_ID_VIA_8371_1,	quirk_vialatency );
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_VIA,	PCI_DEVICE_ID_VIA_8361,		quirk_vialatency );
 
 /*
  *	VIA Apollo VP3 needs ETBF on BT848/878
  */
- 
 static void __devinit quirk_viaetbf(struct pci_dev *dev)
 {
-	if((pci_pci_problems&PCIPCI_VIAETBF)==0)
-	{
+	if ((pci_pci_problems&PCIPCI_VIAETBF)==0) {
 		printk(KERN_INFO "Limiting direct PCI/PCI transfers.\n");
-		pci_pci_problems|=PCIPCI_VIAETBF;
+		pci_pci_problems |= PCIPCI_VIAETBF;
 	}
 }
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_VIA,	PCI_DEVICE_ID_VIA_82C597_0,	quirk_viaetbf );
+
 static void __devinit quirk_vsfx(struct pci_dev *dev)
 {
-	if((pci_pci_problems&PCIPCI_VSFX)==0)
-	{
+	if ((pci_pci_problems&PCIPCI_VSFX)==0) {
 		printk(KERN_INFO "Limiting direct PCI/PCI transfers.\n");
-		pci_pci_problems|=PCIPCI_VSFX;
+		pci_pci_problems |= PCIPCI_VSFX;
 	}
 }
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_VIA,	PCI_DEVICE_ID_VIA_82C576,	quirk_vsfx );
 
 /*
  *	Ali Magik requires workarounds to be used by the drivers
@@ -173,36 +185,38 @@
  *	workaround applied too
  *	[Info kindly provided by ALi]
  */	
- 
 static void __init quirk_alimagik(struct pci_dev *dev)
 {
-	if((pci_pci_problems&PCIPCI_ALIMAGIK)==0)
-	{
+	if ((pci_pci_problems&PCIPCI_ALIMAGIK)==0) {
 		printk(KERN_INFO "Limiting direct PCI/PCI transfers.\n");
-		pci_pci_problems|=PCIPCI_ALIMAGIK|PCIPCI_TRITON;
+		pci_pci_problems |= PCIPCI_ALIMAGIK|PCIPCI_TRITON;
 	}
 }
-
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_AL, 	PCI_DEVICE_ID_AL_M1647, 	quirk_alimagik );
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_AL, 	PCI_DEVICE_ID_AL_M1651, 	quirk_alimagik );
 
 /*
  *	Natoma has some interesting boundary conditions with Zoran stuff
  *	at least
  */
- 
 static void __devinit quirk_natoma(struct pci_dev *dev)
 {
-	if((pci_pci_problems&PCIPCI_NATOMA)==0)
-	{
+	if ((pci_pci_problems&PCIPCI_NATOMA)==0) {
 		printk(KERN_INFO "Limiting direct PCI/PCI transfers.\n");
-		pci_pci_problems|=PCIPCI_NATOMA;
+		pci_pci_problems |= PCIPCI_NATOMA;
 	}
 }
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 	PCI_DEVICE_ID_INTEL_82441, 	quirk_natoma ); 
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 	PCI_DEVICE_ID_INTEL_82443LX_0, 	quirk_natoma ); 
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 	PCI_DEVICE_ID_INTEL_82443LX_1, 	quirk_natoma ); 
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 	PCI_DEVICE_ID_INTEL_82443BX_0, 	quirk_natoma ); 
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 	PCI_DEVICE_ID_INTEL_82443BX_1, 	quirk_natoma ); 
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 	PCI_DEVICE_ID_INTEL_82443BX_2, 	quirk_natoma );
 
 /*
  *  S3 868 and 968 chips report region size equal to 32M, but they decode 64M.
  *  If it's needed, re-allocate the region.
  */
-
 static void __devinit quirk_s3_64M(struct pci_dev *dev)
 {
 	struct resource *r = &dev->resource[0];
@@ -212,6 +226,8 @@
 		r->end = 0x3ffffff;
 	}
 }
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_S3,	PCI_DEVICE_ID_S3_868,		quirk_s3_64M );
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_S3,	PCI_DEVICE_ID_S3_968,		quirk_s3_64M );
 
 static void __devinit quirk_io_region(struct pci_dev *dev, unsigned region, unsigned size, int nr)
 {
@@ -231,7 +247,6 @@
  *	ATI Northbridge setups MCE the processor if you even
  *	read somewhere between 0x3b0->0x3bb or read 0x3d3
  */
- 
 static void __devinit quirk_ati_exploding_mce(struct pci_dev *dev)
 {
 	printk(KERN_INFO "ATI Northbridge, reserving I/O ports 0x3b0 to 0x3bb.\n");
@@ -239,6 +254,7 @@
 	request_region(0x3b0, 0x0C, "RadeonIGP");
 	request_region(0x3d3, 0x01, "RadeonIGP");
 }
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_ATI,	PCI_DEVICE_ID_ATI_RS100,   quirk_ati_exploding_mce );
 
 /*
  * Let's make the southbridge information explicit instead
@@ -260,6 +276,7 @@
 	pci_read_config_word(dev, 0xE2, &region);
 	quirk_io_region(dev, region, 32, PCI_BRIDGE_RESOURCES+1);
 }
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_AL,	PCI_DEVICE_ID_AL_M7101,		quirk_ali7101_acpi );
 
 /*
  * PIIX4 ACPI: Two IO regions pointed to by longwords at
@@ -275,6 +292,7 @@
 	pci_read_config_dword(dev, 0x90, &region);
 	quirk_io_region(dev, region, 32, PCI_BRIDGE_RESOURCES+1);
 }
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL,	PCI_DEVICE_ID_INTEL_82371AB_3,	quirk_piix4_acpi );
 
 /*
  * ICH4, ICH4-M, ICH5, ICH5-M ACPI: Three IO regions pointed to by longwords at
@@ -291,6 +309,15 @@
 	pci_read_config_dword(dev, 0x58, &region);
 	quirk_io_region(dev, region, 64, PCI_BRIDGE_RESOURCES+1);
 }
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL,    PCI_DEVICE_ID_INTEL_82801AA_0,		quirk_ich4_lpc_acpi );
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL,    PCI_DEVICE_ID_INTEL_82801AB_0,		quirk_ich4_lpc_acpi );
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL,    PCI_DEVICE_ID_INTEL_82801BA_0,		quirk_ich4_lpc_acpi );
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL,    PCI_DEVICE_ID_INTEL_82801BA_10,	quirk_ich4_lpc_acpi );
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL,    PCI_DEVICE_ID_INTEL_82801CA_0,		quirk_ich4_lpc_acpi );
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL,    PCI_DEVICE_ID_INTEL_82801CA_12,	quirk_ich4_lpc_acpi );
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL,    PCI_DEVICE_ID_INTEL_82801DB_0,		quirk_ich4_lpc_acpi );
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL,    PCI_DEVICE_ID_INTEL_82801DB_12,	quirk_ich4_lpc_acpi );
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL,    PCI_DEVICE_ID_INTEL_82801EB_0,		quirk_ich4_lpc_acpi );
 
 /*
  * VIA ACPI: One IO region pointed to by longword at
@@ -308,6 +335,7 @@
 		quirk_io_region(dev, region, 256, PCI_BRIDGE_RESOURCES);
 	}
 }
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_VIA,	PCI_DEVICE_ID_VIA_82C586_3,	quirk_vt82c586_acpi );
 
 /*
  * VIA VT82C686 ACPI: Three IO region pointed to by (long)words at
@@ -330,6 +358,7 @@
 	smb &= PCI_BASE_ADDRESS_IO_MASK;
 	quirk_io_region(dev, smb, 16, PCI_BRIDGE_RESOURCES + 2);
 }
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_VIA,	PCI_DEVICE_ID_VIA_82C686_4,	quirk_vt82c686_acpi );
 
 
 #ifdef CONFIG_X86_IO_APIC 
@@ -358,6 +387,7 @@
 	/* Offset 0x58: External APIC IRQ output control */
 	pci_write_config_byte (dev, 0x58, tmp);
 }
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_VIA,	PCI_DEVICE_ID_VIA_82C686,	quirk_via_ioapic );
 
 /*
  * The AMD io apic can hang the box when an apic irq is masked.
@@ -368,30 +398,29 @@
  * noapic specified. For the moment we assume its the errata. We may be wrong
  * of course. However the advice is demonstrably good even if so..
  */
- 
 static void __devinit quirk_amd_ioapic(struct pci_dev *dev)
 {
 	u8 rev;
 
 	pci_read_config_byte(dev, PCI_REVISION_ID, &rev);
-	if(rev >= 0x02)
-	{
+	if (rev >= 0x02) {
 		printk(KERN_WARNING "I/O APIC: AMD Errata #22 may be present. In the event of instability try\n");
 		printk(KERN_WARNING "        : booting with the \"noapic\" option.\n");
 	}
 }
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_AMD,	PCI_DEVICE_ID_AMD_VIPER_7410,	quirk_amd_ioapic );
 
 static void __init quirk_ioapic_rmw(struct pci_dev *dev)
 {
 	if (dev->devfn == 0 && dev->bus->number == 0)
 		sis_apic_bug = 1;
 }
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_SI,	PCI_ANY_ID,			quirk_ioapic_rmw );
 
 #define AMD8131_revA0        0x01
 #define AMD8131_revB0        0x11
 #define AMD8131_MISC         0x40
 #define AMD8131_NIOAMODE_BIT 0
-
 static void __init quirk_amd_8131_ioapic(struct pci_dev *dev) 
 { 
         unsigned char revid, tmp;
@@ -407,6 +436,7 @@
                 pci_write_config_byte( dev, AMD8131_MISC, tmp);
         }
 } 
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_8131_APIC,         quirk_amd_8131_ioapic ); 
 
 #endif /* CONFIG_X86_IO_APIC */
 
@@ -444,6 +474,8 @@
 	if (irq && (irq != 2))
 		d->irq = irq;
 }
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_VIA,	PCI_DEVICE_ID_VIA_82C586_3,	quirk_via_acpi );
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_VIA,	PCI_DEVICE_ID_VIA_82C686_4,	quirk_via_acpi );
 
 static void __devinit quirk_via_irqpic(struct pci_dev *dev)
 {
@@ -459,6 +491,9 @@
 		pci_write_config_byte(dev, PCI_INTERRUPT_LINE, new_irq);
 	}
 }
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_VIA,	PCI_DEVICE_ID_VIA_82C586_2,	quirk_via_irqpic );
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_VIA,	PCI_DEVICE_ID_VIA_82C686_5,	quirk_via_irqpic );
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_VIA,	PCI_DEVICE_ID_VIA_82C686_6,	quirk_via_irqpic );
 
 
 /*
@@ -480,6 +515,8 @@
 	legsup &= 0x50ef;
 	pci_write_config_word(dev, 0xc0, legsup);
 }
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL,	PCI_DEVICE_ID_INTEL_82371SB_2,	quirk_piix3_usb );
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL,	PCI_DEVICE_ID_INTEL_82371AB_2,	quirk_piix3_usb );
 
 /*
  * VIA VT82C598 has its device ID settable and many BIOSes
@@ -492,6 +529,7 @@
 	pci_write_config_byte(dev, 0xfc, 0);
 	pci_read_config_word(dev, PCI_DEVICE_ID, &dev->device);
 }
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_VIA,	PCI_DEVICE_ID_VIA_82C597_0,	quirk_vt82c598_id );
 
 /*
  * CardBus controllers have a legacy base address that enables them
@@ -505,6 +543,7 @@
 		return;
 	pci_write_config_dword(dev, PCI_CB_LEGACY_MODE_BASE, 0);
 }
+DECLARE_PCI_FIXUP_FINAL(PCI_ANY_ID,		PCI_ANY_ID,			quirk_cardbus_legacy );
 
 /*
  * Following the PCI ordering rules is optional on the AMD762. I'm not
@@ -513,13 +552,11 @@
  * To be fair to AMD, it follows the spec by default, its BIOS people
  * who turn it off!
  */
- 
 static void __devinit quirk_amd_ordering(struct pci_dev *dev)
 {
 	u32 pcic;
 	pci_read_config_dword(dev, 0x4C, &pcic);
-	if((pcic&6)!=6)
-	{
+	if ((pcic&6)!=6) {
 		pcic |= 6;
 		printk(KERN_WARNING "BIOS failed to enable PCI standards compliance, fixing this error.\n");
 		pci_write_config_dword(dev, 0x4C, pcic);
@@ -528,6 +565,7 @@
 		pci_write_config_dword(dev, 0x84, pcic);
 	}
 }
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_AMD,	PCI_DEVICE_ID_AMD_FE_GATE_700C, quirk_amd_ordering );
 
 /*
  *	DreamWorks provided workaround for Dunord I-3000 problem
@@ -536,18 +574,26 @@
  *	assigned to it. We force a larger allocation to ensure that
  *	nothing gets put too close to it.
  */
-
 static void __devinit quirk_dunord ( struct pci_dev * dev )
 {
-	struct resource * r = & dev -> resource [ 1 ];
-	r -> start = 0;
-	r -> end = 0xffffff;
+	struct resource *r = &dev->resource [1];
+	r->start = 0;
+	r->end = 0xffffff;
 }
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_DUNORD,	PCI_DEVICE_ID_DUNORD_I3000,	quirk_dunord );
 
+/*
+ * i82380FB mobile docking controller: its PCI-to-PCI bridge
+ * is subtractive decoding (transparent), and does indicate this
+ * in the ProgIf. Unfortunately, the ProgIf value is wrong - 0x80
+ * instead of 0x01.
+ */
 static void __devinit quirk_transparent_bridge(struct pci_dev *dev)
 {
 	dev->transparent = 1;
 }
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL,	PCI_DEVICE_ID_INTEL_82380FB,	quirk_transparent_bridge );
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_TOSHIBA,	0x605,	quirk_transparent_bridge );
 
 /*
  * Common misconfiguration of the MediaGX/Geode PCI master that will
@@ -555,7 +601,6 @@
  * datasheets found at http://www.national.com/ds/GX for info on what
  * these bits do.  <christer@weinigel.se>
  */
- 
 static void __init quirk_mediagx_master(struct pci_dev *dev)
 {
 	u8 reg;
@@ -566,6 +611,7 @@
                 pci_write_config_byte(dev, 0x41, reg);
 	}
 }
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_CYRIX,	PCI_DEVICE_ID_CYRIX_PCI_MASTER, quirk_mediagx_master );
 
 /*
  * As per PCI spec, ignore base address registers 0-3 of the IDE controllers
@@ -584,7 +630,6 @@
  * we do now ? We don't want is pci_enable_device to come along
  * and assign new resources. Both approaches work for that.
  */ 
-
 static void __devinit quirk_ide_bases(struct pci_dev *dev)
 {
        struct resource *res;
@@ -616,34 +661,33 @@
        printk(KERN_INFO "PCI: Ignoring BAR%d-%d of IDE controller %s\n",
               first_bar, last_bar, pci_name(dev));
 }
+DECLARE_PCI_FIXUP_HEADER(PCI_ANY_ID,             PCI_ANY_ID,                     quirk_ide_bases );
 
 /*
  *	Ensure C0 rev restreaming is off. This is normally done by
  *	the BIOS but in the odd case it is not the results are corruption
  *	hence the presence of a Linux check
  */
- 
 static void __init quirk_disable_pxb(struct pci_dev *pdev)
 {
 	u16 config;
 	u8 rev;
 	
 	pci_read_config_byte(pdev, PCI_REVISION_ID, &rev);
-	if(rev != 0x04)		/* Only C0 requires this */
+	if (rev != 0x04)		/* Only C0 requires this */
 		return;
 	pci_read_config_word(pdev, 0x40, &config);
-	if(config & (1<<6))
-	{
+	if (config & (1<<6)) {
 		config &= ~(1<<6);
 		pci_write_config_word(pdev, 0x40, config);
 		printk(KERN_INFO "PCI: C0 revision 450NX. Disabling PCI restreaming.\n");
 	}
 }
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL,	PCI_DEVICE_ID_INTEL_82454NX,	quirk_disable_pxb );
 
 /*
  *	VIA northbridges care about PCI_INTERRUPT_LINE
  */
- 
 int interrupt_line_quirk;
 
 static void __devinit quirk_via_bridge(struct pci_dev *pdev)
@@ -651,6 +695,7 @@
 	if(pdev->devfn == 0)
 		interrupt_line_quirk = 1;
 }
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_VIA,	PCI_ANY_ID,                     quirk_via_bridge );
 
 /*
  *	Serverworks CSB5 IDE does not fully support native mode
@@ -667,15 +712,16 @@
 		quirk_ide_bases(pdev);
 	}
 }
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_SERVERWORKS, PCI_DEVICE_ID_SERVERWORKS_CSB5IDE, quirk_svwks_csb5ide );
 
 /* This was originally an Alpha specific thing, but it really fits here.
  * The i82375 PCI/EISA bridge appears as non-classified. Fix that.
  */
-
 static void __init quirk_eisa_bridge(struct pci_dev *dev)
 {
 	dev->class = PCI_CLASS_BRIDGE_EISA << 8;
 }
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL,	PCI_DEVICE_ID_INTEL_82375,	quirk_eisa_bridge );
 
 /*
  * On ASUS P4B boards, the SMBus PCI Device within the ICH2/4 southbridge
@@ -689,7 +735,6 @@
  * becomes necessary to do this tweak in two steps -- I've chosen the Host
  * bridge as trigger.
  */
-
 static int __initdata asus_hides_smbus = 0;
 
 static void __init asus_hides_smbus_hostbridge(struct pci_dev *dev)
@@ -699,6 +744,7 @@
 			switch(dev->subsystem_device) {
 			case 0x8070: /* P4B */
 			case 0x8088: /* P4B533 */
+			case 0x1626: /* L3C notebook */
 				asus_hides_smbus = 1;
 			}
 		if (dev->device == PCI_DEVICE_ID_INTEL_82845G_HB)
@@ -730,8 +776,20 @@
 			case 0x0890: /* HP Compaq nc6000 */
 				asus_hides_smbus = 1;
 			}
+		if (dev->device == PCI_DEVICE_ID_INTEL_82865_HB)
+			switch (dev->subsystem_device) {
+			case 0x12bc: /* HP D330L */
+				asus_hides_smbus = 1;
+			}
 	}
 }
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL,	PCI_DEVICE_ID_INTEL_82845_HB,	asus_hides_smbus_hostbridge );
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL,	PCI_DEVICE_ID_INTEL_82845G_HB,	asus_hides_smbus_hostbridge );
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL,	PCI_DEVICE_ID_INTEL_82850_HB,	asus_hides_smbus_hostbridge );
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL,	PCI_DEVICE_ID_INTEL_82865_HB,	asus_hides_smbus_hostbridge );
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL,	PCI_DEVICE_ID_INTEL_7205_0,	asus_hides_smbus_hostbridge );
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL,	PCI_DEVICE_ID_INTEL_82855PM_HB,	asus_hides_smbus_hostbridge );
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL,	PCI_DEVICE_ID_INTEL_82855GM_HB,	asus_hides_smbus_hostbridge );
 
 static void __init asus_hides_smbus_lpc(struct pci_dev *dev)
 {
@@ -744,12 +802,17 @@
 	if (val & 0x8) {
 		pci_write_config_word(dev, 0xF2, val & (~0x8));
 		pci_read_config_word(dev, 0xF2, &val);
-		if(val & 0x8)
+		if (val & 0x8)
 			printk(KERN_INFO "PCI: i801 SMBus device continues to play 'hide and seek'! 0x%x\n", val);
 		else
 			printk(KERN_INFO "PCI: Enabled i801 SMBus device\n");
 	}
 }
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL,	PCI_DEVICE_ID_INTEL_82801DB_0,	asus_hides_smbus_lpc );
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL,	PCI_DEVICE_ID_INTEL_82801BA_0,	asus_hides_smbus_lpc );
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL,	PCI_DEVICE_ID_INTEL_82801CA_12,	asus_hides_smbus_lpc );
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL,	PCI_DEVICE_ID_INTEL_82801DB_12,	asus_hides_smbus_lpc );
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL,	PCI_DEVICE_ID_INTEL_82801EB_0,	asus_hides_smbus_lpc );
 
 /*
  * SiS 96x south bridge: BIOS typically hides SMBus device...
@@ -803,6 +866,19 @@
 {
 	sis_96x_compatible = 1;
 }
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_SI,	PCI_DEVICE_ID_SI_645,		quirk_sis_96x_compatible );
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_SI,	PCI_DEVICE_ID_SI_646,		quirk_sis_96x_compatible );
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_SI,	PCI_DEVICE_ID_SI_648,		quirk_sis_96x_compatible );
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_SI,	PCI_DEVICE_ID_SI_650,		quirk_sis_96x_compatible );
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_SI,	PCI_DEVICE_ID_SI_651,		quirk_sis_96x_compatible );
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_SI,	PCI_DEVICE_ID_SI_735,		quirk_sis_96x_compatible );
+
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_SI,	PCI_DEVICE_ID_SI_503,		quirk_sis_503 );
+
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_SI,	PCI_DEVICE_ID_SI_961,		quirk_sis_96x_smbus );
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_SI,	PCI_DEVICE_ID_SI_962,		quirk_sis_96x_smbus );
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_SI,	PCI_DEVICE_ID_SI_963,		quirk_sis_96x_smbus );
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_SI,	PCI_DEVICE_ID_SI_LPC,		quirk_sis_96x_smbus );
 
 #ifdef CONFIG_X86_IO_APIC
 static void __init quirk_alder_ioapic(struct pci_dev *pdev)
@@ -815,16 +891,17 @@
 	/* the first BAR is the location of the IO APIC...we must
 	 * not touch this (and it's already covered by the fixmap), so
 	 * forcibly insert it into the resource tree */
-	if(pci_resource_start(pdev, 0) && pci_resource_len(pdev, 0))
+	if (pci_resource_start(pdev, 0) && pci_resource_len(pdev, 0))
 		insert_resource(&iomem_resource, &pdev->resource[0]);
 
 	/* The next five BARs all seem to be rubbish, so just clean
 	 * them out */
-	for(i=1; i < 6; i++) {
+	for (i=1; i < 6; i++) {
 		memset(&pdev->resource[i], 0, sizeof(pdev->resource[i]));
 	}
 
 }
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL,	PCI_DEVICE_ID_INTEL_EESSC,	quirk_alder_ioapic );
 #endif
 
 #ifdef CONFIG_SCSI_SATA
@@ -898,6 +975,7 @@
 	else
 		request_region(0x170, 8, "libata");	/* port 1 */
 }
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL,    PCI_ANY_ID,	  quirk_intel_ide_combined );
 #endif /* CONFIG_SCSI_SATA */
 
 int pciehp_msi_quirk;
@@ -906,163 +984,45 @@
 {
 	pciehp_msi_quirk = 1;
 }
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL,    PCI_DEVICE_ID_INTEL_SMCH,	quirk_pciehp_msi );
 
-/*
- *  The main table of quirks.
- *
- *  Note: any hooks for hotpluggable devices in this table must _NOT_
- *        be declared __init.
- */
-
-static struct pci_fixup pci_fixups[] __devinitdata = {
-	{ PCI_FIXUP_HEADER,	PCI_VENDOR_ID_DUNORD,	PCI_DEVICE_ID_DUNORD_I3000,	quirk_dunord },
-	{ PCI_FIXUP_FINAL,	PCI_VENDOR_ID_INTEL,	PCI_DEVICE_ID_INTEL_82441,	quirk_passive_release },
-	{ PCI_FIXUP_FINAL,	PCI_VENDOR_ID_INTEL,	PCI_DEVICE_ID_INTEL_82441,	quirk_passive_release },
-	/*
-	 * Its not totally clear which chipsets are the problematic ones
-	 * We know 82C586 and 82C596 variants are affected.
-	 */
-	{ PCI_FIXUP_FINAL,	PCI_VENDOR_ID_VIA,	PCI_DEVICE_ID_VIA_82C586_0,	quirk_isa_dma_hangs },
-	{ PCI_FIXUP_FINAL,	PCI_VENDOR_ID_VIA,	PCI_DEVICE_ID_VIA_82C596,	quirk_isa_dma_hangs },
-	{ PCI_FIXUP_FINAL,      PCI_VENDOR_ID_INTEL,    PCI_DEVICE_ID_INTEL_82371SB_0,  quirk_isa_dma_hangs },
-	{ PCI_FIXUP_FINAL,	PCI_VENDOR_ID_AL,	PCI_DEVICE_ID_AL_M1533, 	quirk_isa_dma_hangs },
-	{ PCI_FIXUP_FINAL,	PCI_VENDOR_ID_INTEL,	PCI_DEVICE_ID_INTEL_82454NX,	quirk_disable_pxb },
-	{ PCI_FIXUP_FINAL,	PCI_VENDOR_ID_NEC,	PCI_DEVICE_ID_NEC_CBUS_1,	quirk_isa_dma_hangs },
-	{ PCI_FIXUP_FINAL,	PCI_VENDOR_ID_NEC,	PCI_DEVICE_ID_NEC_CBUS_2,	quirk_isa_dma_hangs },
-	{ PCI_FIXUP_FINAL,	PCI_VENDOR_ID_NEC,	PCI_DEVICE_ID_NEC_CBUS_3,	quirk_isa_dma_hangs },
-	{ PCI_FIXUP_HEADER,	PCI_VENDOR_ID_S3,	PCI_DEVICE_ID_S3_868,		quirk_s3_64M },
-	{ PCI_FIXUP_HEADER,	PCI_VENDOR_ID_S3,	PCI_DEVICE_ID_S3_968,		quirk_s3_64M },
-	{ PCI_FIXUP_FINAL,	PCI_VENDOR_ID_INTEL, 	PCI_DEVICE_ID_INTEL_82437, 	quirk_triton }, 
-	{ PCI_FIXUP_FINAL,	PCI_VENDOR_ID_INTEL, 	PCI_DEVICE_ID_INTEL_82437VX, 	quirk_triton }, 
-	{ PCI_FIXUP_FINAL,	PCI_VENDOR_ID_INTEL, 	PCI_DEVICE_ID_INTEL_82439, 	quirk_triton }, 
-	{ PCI_FIXUP_FINAL,	PCI_VENDOR_ID_INTEL, 	PCI_DEVICE_ID_INTEL_82439TX, 	quirk_triton }, 
-	{ PCI_FIXUP_FINAL,	PCI_VENDOR_ID_INTEL, 	PCI_DEVICE_ID_INTEL_82441, 	quirk_natoma }, 
-	{ PCI_FIXUP_FINAL,	PCI_VENDOR_ID_INTEL, 	PCI_DEVICE_ID_INTEL_82443LX_0, 	quirk_natoma }, 
-	{ PCI_FIXUP_FINAL,	PCI_VENDOR_ID_INTEL, 	PCI_DEVICE_ID_INTEL_82443LX_1, 	quirk_natoma }, 
-	{ PCI_FIXUP_FINAL,	PCI_VENDOR_ID_INTEL, 	PCI_DEVICE_ID_INTEL_82443BX_0, 	quirk_natoma }, 
-	{ PCI_FIXUP_FINAL,	PCI_VENDOR_ID_INTEL, 	PCI_DEVICE_ID_INTEL_82443BX_1, 	quirk_natoma }, 
-	{ PCI_FIXUP_FINAL,	PCI_VENDOR_ID_INTEL, 	PCI_DEVICE_ID_INTEL_82443BX_2, 	quirk_natoma },
-	{ PCI_FIXUP_FINAL,	PCI_VENDOR_ID_SI,	PCI_DEVICE_ID_SI_5597,		quirk_nopcipci },
-	{ PCI_FIXUP_FINAL,	PCI_VENDOR_ID_SI,	PCI_DEVICE_ID_SI_496,		quirk_nopcipci },
-	{ PCI_FIXUP_HEADER,	PCI_VENDOR_ID_SI,	PCI_DEVICE_ID_SI_503,		quirk_sis_503 },
-	{ PCI_FIXUP_HEADER,	PCI_VENDOR_ID_SI,	PCI_DEVICE_ID_SI_LPC,		quirk_sis_96x_smbus },
-	{ PCI_FIXUP_HEADER,	PCI_VENDOR_ID_SI,	PCI_DEVICE_ID_SI_645,		quirk_sis_96x_compatible },
-	{ PCI_FIXUP_HEADER,	PCI_VENDOR_ID_SI,	PCI_DEVICE_ID_SI_646,		quirk_sis_96x_compatible },
-	{ PCI_FIXUP_HEADER,	PCI_VENDOR_ID_SI,	PCI_DEVICE_ID_SI_648,		quirk_sis_96x_compatible },
-	{ PCI_FIXUP_HEADER,	PCI_VENDOR_ID_SI,	PCI_DEVICE_ID_SI_650,		quirk_sis_96x_compatible },
-	{ PCI_FIXUP_HEADER,	PCI_VENDOR_ID_SI,	PCI_DEVICE_ID_SI_651,		quirk_sis_96x_compatible },
-	{ PCI_FIXUP_HEADER,	PCI_VENDOR_ID_SI,	PCI_DEVICE_ID_SI_735,		quirk_sis_96x_compatible },
-	{ PCI_FIXUP_HEADER,	PCI_VENDOR_ID_SI,	PCI_DEVICE_ID_SI_961,		quirk_sis_96x_smbus },
-	{ PCI_FIXUP_HEADER,	PCI_VENDOR_ID_SI,	PCI_DEVICE_ID_SI_962,		quirk_sis_96x_smbus },
-	{ PCI_FIXUP_HEADER,	PCI_VENDOR_ID_SI,	PCI_DEVICE_ID_SI_963,		quirk_sis_96x_smbus },
-	{ PCI_FIXUP_FINAL,	PCI_VENDOR_ID_AL, 	PCI_DEVICE_ID_AL_M1647, 	quirk_alimagik },
-	{ PCI_FIXUP_FINAL,	PCI_VENDOR_ID_AL, 	PCI_DEVICE_ID_AL_M1651, 	quirk_alimagik },
-	{ PCI_FIXUP_FINAL,	PCI_VENDOR_ID_VIA,	PCI_DEVICE_ID_VIA_8363_0,	quirk_vialatency },
-	{ PCI_FIXUP_FINAL,	PCI_VENDOR_ID_VIA,	PCI_DEVICE_ID_VIA_8371_1,	quirk_vialatency },
-	{ PCI_FIXUP_FINAL,	PCI_VENDOR_ID_VIA,	PCI_DEVICE_ID_VIA_8361,	quirk_vialatency },
-	{ PCI_FIXUP_FINAL,	PCI_VENDOR_ID_VIA,	PCI_DEVICE_ID_VIA_82C576,	quirk_vsfx },
-	{ PCI_FIXUP_FINAL,	PCI_VENDOR_ID_VIA,	PCI_DEVICE_ID_VIA_82C597_0,	quirk_viaetbf },
-	{ PCI_FIXUP_HEADER,	PCI_VENDOR_ID_VIA,	PCI_DEVICE_ID_VIA_82C597_0,	quirk_vt82c598_id },
-	{ PCI_FIXUP_HEADER,	PCI_VENDOR_ID_VIA,	PCI_DEVICE_ID_VIA_82C586_3,	quirk_vt82c586_acpi },
-	{ PCI_FIXUP_HEADER,	PCI_VENDOR_ID_VIA,	PCI_DEVICE_ID_VIA_82C686_4,	quirk_vt82c686_acpi },
-	{ PCI_FIXUP_HEADER,	PCI_VENDOR_ID_INTEL,	PCI_DEVICE_ID_INTEL_82371AB_3,	quirk_piix4_acpi },
-
-	/* Intel LPC interface bridges all have 128 bytes of magic ACPI/TCO regs and 64 bytes of GPIO */
-	{ PCI_FIXUP_HEADER,     PCI_VENDOR_ID_INTEL,    PCI_DEVICE_ID_INTEL_82801AA_0,	quirk_ich4_lpc_acpi },
-	{ PCI_FIXUP_HEADER,     PCI_VENDOR_ID_INTEL,    PCI_DEVICE_ID_INTEL_82801AB_0,	quirk_ich4_lpc_acpi },
-	{ PCI_FIXUP_HEADER,     PCI_VENDOR_ID_INTEL,    PCI_DEVICE_ID_INTEL_82801BA_0,	quirk_ich4_lpc_acpi },
-	{ PCI_FIXUP_HEADER,     PCI_VENDOR_ID_INTEL,    PCI_DEVICE_ID_INTEL_82801BA_10,	quirk_ich4_lpc_acpi },
-	{ PCI_FIXUP_HEADER,     PCI_VENDOR_ID_INTEL,    PCI_DEVICE_ID_INTEL_82801CA_0,	quirk_ich4_lpc_acpi },
-	{ PCI_FIXUP_HEADER,     PCI_VENDOR_ID_INTEL,    PCI_DEVICE_ID_INTEL_82801CA_12,	quirk_ich4_lpc_acpi },
-	{ PCI_FIXUP_HEADER,     PCI_VENDOR_ID_INTEL,    PCI_DEVICE_ID_INTEL_82801DB_0,	quirk_ich4_lpc_acpi },
-	{ PCI_FIXUP_HEADER,	PCI_VENDOR_ID_INTEL,	PCI_DEVICE_ID_INTEL_82801DB_12,	quirk_ich4_lpc_acpi },
-	{ PCI_FIXUP_HEADER,     PCI_VENDOR_ID_INTEL,    PCI_DEVICE_ID_INTEL_82801EB_0,	quirk_ich4_lpc_acpi },
-
-	{ PCI_FIXUP_HEADER,	PCI_VENDOR_ID_AL,	PCI_DEVICE_ID_AL_M7101,		quirk_ali7101_acpi },
- 	{ PCI_FIXUP_HEADER,	PCI_VENDOR_ID_INTEL,	PCI_DEVICE_ID_INTEL_82371SB_2,	quirk_piix3_usb },
-	{ PCI_FIXUP_HEADER,	PCI_VENDOR_ID_INTEL,	PCI_DEVICE_ID_INTEL_82371AB_2,	quirk_piix3_usb },
-	{ PCI_FIXUP_HEADER,     PCI_ANY_ID,             PCI_ANY_ID,                     quirk_ide_bases },
-	{ PCI_FIXUP_HEADER,     PCI_VENDOR_ID_VIA,	PCI_ANY_ID,                     quirk_via_bridge },
-	{ PCI_FIXUP_FINAL,	PCI_ANY_ID,		PCI_ANY_ID,			quirk_cardbus_legacy },
-
-#ifdef CONFIG_X86_IO_APIC 
-	{ PCI_FIXUP_FINAL,	PCI_VENDOR_ID_VIA,	PCI_DEVICE_ID_VIA_82C686,	quirk_via_ioapic },
-	{ PCI_FIXUP_FINAL, 	PCI_VENDOR_ID_AMD,	PCI_DEVICE_ID_AMD_VIPER_7410,	quirk_amd_ioapic },
-	{ PCI_FIXUP_FINAL,	PCI_VENDOR_ID_SI,	PCI_ANY_ID,			quirk_ioapic_rmw },
-        { PCI_FIXUP_FINAL,      PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_8131_APIC,
-          quirk_amd_8131_ioapic }, 
-	{ PCI_FIXUP_HEADER,	PCI_VENDOR_ID_INTEL,	PCI_DEVICE_ID_INTEL_EESSC,	quirk_alder_ioapic },
-#endif
-	{ PCI_FIXUP_HEADER,	PCI_VENDOR_ID_VIA,	PCI_DEVICE_ID_VIA_82C586_3,	quirk_via_acpi },
-	{ PCI_FIXUP_HEADER,	PCI_VENDOR_ID_VIA,	PCI_DEVICE_ID_VIA_82C686_4,	quirk_via_acpi },
-	{ PCI_FIXUP_FINAL,	PCI_VENDOR_ID_VIA,	PCI_DEVICE_ID_VIA_82C586_2,	quirk_via_irqpic },
-	{ PCI_FIXUP_FINAL,	PCI_VENDOR_ID_VIA,	PCI_DEVICE_ID_VIA_82C686_5,	quirk_via_irqpic },
-	{ PCI_FIXUP_FINAL,	PCI_VENDOR_ID_VIA,	PCI_DEVICE_ID_VIA_82C686_6,	quirk_via_irqpic },
-
-	{ PCI_FIXUP_FINAL,	PCI_VENDOR_ID_AMD,	PCI_DEVICE_ID_AMD_FE_GATE_700C, quirk_amd_ordering },
-	{ PCI_FIXUP_FINAL,	PCI_VENDOR_ID_ATI,	PCI_DEVICE_ID_ATI_RS100,   quirk_ati_exploding_mce },
-	/*
-	 * i82380FB mobile docking controller: its PCI-to-PCI bridge
-	 * is subtractive decoding (transparent), and does indicate this
-	 * in the ProgIf. Unfortunately, the ProgIf value is wrong - 0x80
-	 * instead of 0x01.
-	 */
-	{ PCI_FIXUP_HEADER,	PCI_VENDOR_ID_INTEL,	PCI_DEVICE_ID_INTEL_82380FB,	quirk_transparent_bridge },
-	{ PCI_FIXUP_HEADER,	PCI_VENDOR_ID_TOSHIBA,	0x605,	quirk_transparent_bridge },
-
-	{ PCI_FIXUP_FINAL,	PCI_VENDOR_ID_CYRIX,	PCI_DEVICE_ID_CYRIX_PCI_MASTER, quirk_mediagx_master },
-
-	{ PCI_FIXUP_HEADER,	PCI_VENDOR_ID_SERVERWORKS, PCI_DEVICE_ID_SERVERWORKS_CSB5IDE, quirk_svwks_csb5ide },
-
-	{ PCI_FIXUP_HEADER,	PCI_VENDOR_ID_INTEL,	PCI_DEVICE_ID_INTEL_82375,	quirk_eisa_bridge },
-
-	/*
-	 * on Asus P4B boards, the i801SMBus device is disabled at startup.
-	 * this also goes for boards in HP Compaq nc6000 and nc8000 notebooks.
-	 */
-	{ PCI_FIXUP_HEADER,	PCI_VENDOR_ID_INTEL,	PCI_DEVICE_ID_INTEL_82845_HB,	asus_hides_smbus_hostbridge },
-	{ PCI_FIXUP_HEADER,	PCI_VENDOR_ID_INTEL,	PCI_DEVICE_ID_INTEL_82845G_HB,	asus_hides_smbus_hostbridge },
-	{ PCI_FIXUP_HEADER,	PCI_VENDOR_ID_INTEL,	PCI_DEVICE_ID_INTEL_82850_HB,	asus_hides_smbus_hostbridge },
-	{ PCI_FIXUP_HEADER,	PCI_VENDOR_ID_INTEL,	PCI_DEVICE_ID_INTEL_7205_0,	asus_hides_smbus_hostbridge },
-	{ PCI_FIXUP_HEADER,	PCI_VENDOR_ID_INTEL,	PCI_DEVICE_ID_INTEL_82855PM_HB,	asus_hides_smbus_hostbridge },
-	{ PCI_FIXUP_HEADER,	PCI_VENDOR_ID_INTEL,	PCI_DEVICE_ID_INTEL_82855GM_HB,	asus_hides_smbus_hostbridge },
-	{ PCI_FIXUP_HEADER,	PCI_VENDOR_ID_INTEL,	PCI_DEVICE_ID_INTEL_82801DB_0,	asus_hides_smbus_lpc },
-	{ PCI_FIXUP_HEADER,	PCI_VENDOR_ID_INTEL,	PCI_DEVICE_ID_INTEL_82801BA_0,	asus_hides_smbus_lpc },
-	{ PCI_FIXUP_HEADER,	PCI_VENDOR_ID_INTEL,	PCI_DEVICE_ID_INTEL_82801DB_12,	asus_hides_smbus_lpc },
-
-#ifdef CONFIG_SCSI_SATA
-	/* Fixup BIOSes that configure Parallel ATA (PATA / IDE) and
-	 * Serial ATA (SATA) into the same PCI ID.
-	 */
-	{ PCI_FIXUP_FINAL,      PCI_VENDOR_ID_INTEL,    PCI_ANY_ID,
-	  quirk_intel_ide_combined },
-#endif /* CONFIG_SCSI_SATA */
-
-	{ PCI_FIXUP_FINAL,      PCI_VENDOR_ID_INTEL,    PCI_DEVICE_ID_INTEL_SMCH,	quirk_pciehp_msi },
-
-	{ 0 }
-};
 
-
-static void pci_do_fixups(struct pci_dev *dev, int pass, struct pci_fixup *f)
+static void pci_do_fixups(struct pci_dev *dev, struct pci_fixup *f, struct pci_fixup *end)
 {
-	while (f->pass) {
-		if (f->pass == pass &&
- 		    (f->vendor == dev->vendor || f->vendor == (u16) PCI_ANY_ID) &&
+	while (f < end) {
+		if ((f->vendor == dev->vendor || f->vendor == (u16) PCI_ANY_ID) &&
  		    (f->device == dev->device || f->device == (u16) PCI_ANY_ID)) {
-#ifdef DEBUG
-			printk(KERN_INFO "PCI: Calling quirk %p for %s\n", f->hook, pci_name(dev));
-#endif
+			pr_debug(KERN_INFO "PCI: Calling quirk %p for %s\n", f->hook, pci_name(dev));
 			f->hook(dev);
 		}
 		f++;
 	}
 }
 
-void pci_fixup_device(int pass, struct pci_dev *dev)
-{
-	pci_do_fixups(dev, pass, pcibios_fixups);
-	pci_do_fixups(dev, pass, pci_fixups);
+extern struct pci_fixup __start_pci_fixups_header[];
+extern struct pci_fixup __end_pci_fixups_header[];
+extern struct pci_fixup __start_pci_fixups_final[];
+extern struct pci_fixup __end_pci_fixups_final[];
+
+void pci_fixup_device(enum pci_fixup_pass pass, struct pci_dev *dev)
+{
+	struct pci_fixup *start, *end;
+
+	switch(pass) {
+	case pci_fixup_header:
+		start = __start_pci_fixups_header;
+		end = __end_pci_fixups_header;
+		break;
+
+	case pci_fixup_final:
+		start = __start_pci_fixups_final;
+		end = __end_pci_fixups_final;
+		break;
+	default:
+		/* stupid compiler warning, you would think with an enum... */
+		return;
+	}
+	pci_do_fixups(dev, start, end);
 }
 
 EXPORT_SYMBOL(pciehp_msi_quirk);
diff -Nru a/drivers/pci/remove.c b/drivers/pci/remove.c
--- a/drivers/pci/remove.c	2004-10-18 14:56:17 -07:00
+++ b/drivers/pci/remove.c	2004-10-18 14:56:17 -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/pci/setup-bus.c b/drivers/pci/setup-bus.c
--- a/drivers/pci/setup-bus.c	2004-10-18 14:57:04 -07:00
+++ b/drivers/pci/setup-bus.c	2004-10-18 14:57:04 -07:00
@@ -537,10 +537,11 @@
 
 	/* Depth first, calculate sizes and alignments of all
 	   subordinate buses. */
-	for(ln=pci_root_buses.next; ln != &pci_root_buses; ln=ln->next)
+	list_for_each(ln, &pci_root_buses) {
 		pci_bus_size_bridges(pci_bus_b(ln));
+	}
 	/* Depth last, allocate resources and update the hardware. */
-	for(ln=pci_root_buses.next; ln != &pci_root_buses; ln=ln->next) {
+	list_for_each(ln, &pci_root_buses) {
 		pci_bus_assign_resources(pci_bus_b(ln));
 		pci_enable_bridges(pci_bus_b(ln));
 	}
diff -Nru a/drivers/pcmcia/au1000_generic.c b/drivers/pcmcia/au1000_generic.c
--- a/drivers/pcmcia/au1000_generic.c	2004-10-18 14:56:33 -07:00
+++ b/drivers/pcmcia/au1000_generic.c	2004-10-18 14:56:33 -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/cardbus.c b/drivers/pcmcia/cardbus.c
--- a/drivers/pcmcia/cardbus.c	2004-10-18 14:56:27 -07:00
+++ b/drivers/pcmcia/cardbus.c	2004-10-18 14:56:27 -07:00
@@ -85,7 +85,7 @@
     
 =====================================================================*/
 
-static u_int xlate_rom_addr(u_char * b, u_int addr)
+static u_int xlate_rom_addr(void __iomem *b, u_int addr)
 {
 	u_int img = 0, ofs = 0, sz;
 	u_short data;
diff -Nru a/drivers/pcmcia/cistpl.c b/drivers/pcmcia/cistpl.c
--- a/drivers/pcmcia/cistpl.c	2004-10-18 14:56:28 -07:00
+++ b/drivers/pcmcia/cistpl.c	2004-10-18 14:56:28 -07:00
@@ -103,7 +103,7 @@
  * If flags & MAP_ATTRIB, map the attribute space, otherwise
  * map the memory space.
  */
-static unsigned char *
+static void __iomem *
 set_cis_map(struct pcmcia_socket *s, unsigned int card_offset, unsigned int flags)
 {
     pccard_mem_map *mem = &s->cis_mem;
@@ -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;
 }
@@ -143,7 +141,8 @@
 int read_cis_mem(struct pcmcia_socket *s, int attr, u_int addr,
 		 u_int len, void *ptr)
 {
-    u_char *sys, *end, *buf = ptr;
+    void __iomem *sys, *end;
+    unsigned char *buf = ptr;
     
     cs_dbg(s, 3, "read_cis_mem(%d, %#x, %u)\n", attr, addr, len);
 
@@ -206,7 +205,8 @@
 void write_cis_mem(struct pcmcia_socket *s, int attr, u_int addr,
 		   u_int len, void *ptr)
 {
-    u_char *sys, *end, *buf = ptr;
+    void __iomem *sys, *end;
+    unsigned char *buf = ptr;
     
     cs_dbg(s, 3, "write_cis_mem(%d, %#x, %u)\n", attr, addr, len);
 
diff -Nru a/drivers/pcmcia/cs.c b/drivers/pcmcia/cs.c
--- a/drivers/pcmcia/cs.c	2004-10-18 14:56:27 -07:00
+++ b/drivers/pcmcia/cs.c	2004-10-18 14:56:27 -07:00
@@ -427,8 +427,6 @@
     return ret;
 } /* send_event */
 
-#define cs_to_timeout(cs) (((cs) * HZ + 99) / 100)
-
 static void socket_remove_drivers(struct pcmcia_socket *skt)
 {
 	client_t *client;
@@ -448,8 +446,7 @@
 
 	socket_remove_drivers(skt);
 	skt->state &= SOCKET_INUSE|SOCKET_PRESENT;
-	set_current_state(TASK_UNINTERRUPTIBLE);
-	schedule_timeout(cs_to_timeout(shutdown_delay));
+	msleep(shutdown_delay * 10);
 	skt->state &= SOCKET_INUSE;
 	shutdown_socket(skt);
 }
@@ -467,8 +464,7 @@
 	skt->socket.flags &= ~SS_RESET;
 	skt->ops->set_socket(skt, &skt->socket);
 
-	set_current_state(TASK_UNINTERRUPTIBLE);
-	schedule_timeout(cs_to_timeout(unreset_delay));
+	msleep(unreset_delay * 10);
 	for (i = 0; i < unreset_limit; i++) {
 		skt->ops->get_status(skt, &status);
 
@@ -478,8 +474,7 @@
 		if (status & SS_READY)
 			return CS_SUCCESS;
 
-		set_current_state(TASK_UNINTERRUPTIBLE);
-		schedule_timeout(cs_to_timeout(unreset_check));
+		msleep(unreset_check * 10);
 	}
 
 	cs_err(skt, "time out after reset.\n");
@@ -496,8 +491,7 @@
 	if (!(status & SS_DETECT))
 		return CS_NO_CARD;
 
-	set_current_state(TASK_UNINTERRUPTIBLE);
-	schedule_timeout(cs_to_timeout(initial_delay));
+	msleep(initial_delay * 10);
 
 	for (i = 0; i < 100; i++) {
 		skt->ops->get_status(skt, &status);
@@ -507,8 +501,7 @@
 		if (!(status & SS_PENDING))
 			break;
 
-		set_current_state(TASK_UNINTERRUPTIBLE);
-		schedule_timeout(cs_to_timeout(10));
+		msleep(100);
 	}
 
 	if (status & SS_PENDING) {
@@ -541,8 +534,7 @@
 	/*
 	 * Wait "vcc_settle" for the supply to stabilise.
 	 */
-	set_current_state(TASK_UNINTERRUPTIBLE);
-	schedule_timeout(cs_to_timeout(vcc_settle));
+	msleep(vcc_settle * 10);
 
 	skt->ops->get_status(skt, &status);
 	if (!(status & SS_POWERON)) {
@@ -659,10 +651,8 @@
 	if (!(skt->state & SOCKET_SUSPEND)) {
 		int status;
 
-		if (!(skt->state & SOCKET_PRESENT)) {
-			set_current_state(TASK_UNINTERRUPTIBLE);
-			schedule_timeout(cs_to_timeout(2));
-		}
+		if (!(skt->state & SOCKET_PRESENT))
+			msleep(20);
 
 		skt->ops->get_status(skt, &status);
 		if ((skt->state & SOCKET_PRESENT) &&
@@ -1886,11 +1876,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 +1897,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/ds.c b/drivers/pcmcia/ds.c
--- a/drivers/pcmcia/ds.c	2004-10-18 14:56:49 -07:00
+++ b/drivers/pcmcia/ds.c	2004-10-18 14:56:49 -07:00
@@ -50,6 +50,7 @@
 #include <linux/poll.h>
 #include <linux/pci.h>
 #include <linux/list.h>
+#include <linux/delay.h>
 #include <linux/workqueue.h>
 
 #include <asm/atomic.h>
@@ -133,7 +134,7 @@
 
 static int major_dev = -1;
 
-extern struct proc_dir_entry *proc_pccard;
+static struct proc_dir_entry *proc_pccard;
 
 /*====================================================================*/
 
@@ -1080,8 +1081,7 @@
 	 * Ugly. But we want to wait for the socket threads to have started up.
 	 * We really should let the drivers themselves drive some of this..
 	 */
-	current->state = TASK_INTERRUPTIBLE;
-	schedule_timeout(HZ/4);
+	msleep(250);
 
 	init_waitqueue_head(&s->queue);
 	init_waitqueue_head(&s->request);
diff -Nru a/drivers/pcmcia/hd64465_ss.c b/drivers/pcmcia/hd64465_ss.c
--- a/drivers/pcmcia/hd64465_ss.c	2004-10-18 14:56:33 -07:00
+++ b/drivers/pcmcia/hd64465_ss.c	2004-10-18 14:56:33 -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-10-18 14:57:05 -07:00
+++ b/drivers/pcmcia/i82092.c	2004-10-18 14:57:05 -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-10-18 14:57:03 -07:00
+++ b/drivers/pcmcia/i82365.c	2004-10-18 14:57:03 -07:00
@@ -513,8 +513,7 @@
     if (request_irq(irq, i365_count_irq, 0, "scan", i365_count_irq) != 0)
 	return 1;
     irq_hits = 0; irq_sock = sock;
-    __set_current_state(TASK_UNINTERRUPTIBLE);
-    schedule_timeout(HZ/100);
+    msleep(10);
     if (irq_hits) {
 	free_irq(irq, i365_count_irq);
 	debug(2, "    spurious hit!\n");
@@ -1159,13 +1158,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 +1172,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 +1186,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 +1308,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-10-18 14:56:50 -07:00
+++ b/drivers/pcmcia/pd6729.c	2004-10-18 14:56:50 -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/pxa2xx_base.c b/drivers/pcmcia/pxa2xx_base.c
--- a/drivers/pcmcia/pxa2xx_base.c	2004-10-18 14:57:18 -07:00
+++ b/drivers/pcmcia/pxa2xx_base.c	2004-10-18 14:57:18 -07:00
@@ -28,6 +28,7 @@
 #include <asm/io.h>
 #include <asm/irq.h>
 #include <asm/system.h>
+#include <asm/arch/pxa-regs.h>
 
 #include <pcmcia/cs_types.h>
 #include <pcmcia/ss.h>
@@ -177,39 +178,6 @@
 	ops = (struct pcmcia_low_level *)dev->platform_data;
 	first = ops->first;
 	nr = ops->nr;
-
-	/* Setup GPIOs for PCMCIA/CF alternate function mode.
-	 *
-	 * It would be nice if set_GPIO_mode included support
-	 * for driving GPIO outputs to default high/low state
-	 * before programming GPIOs as outputs. Setting GPIO
-	 * outputs to default high/low state via GPSR/GPCR
-	 * before defining them as outputs should reduce
-	 * the possibility of glitching outputs during GPIO
-	 * setup. This of course assumes external terminators
-	 * are present to hold GPIOs in a defined state.
-	 *
-	 * In the meantime, setup default state of GPIO
-	 * outputs before we enable them as outputs.
-	 */
-
-	GPSR(GPIO48_nPOE) = GPIO_bit(GPIO48_nPOE) |
-		GPIO_bit(GPIO49_nPWE) |
-		GPIO_bit(GPIO50_nPIOR) |
-		GPIO_bit(GPIO51_nPIOW) |
-		GPIO_bit(GPIO52_nPCE_1) |
-		GPIO_bit(GPIO53_nPCE_2);
-
-	pxa_gpio_mode(GPIO48_nPOE_MD);
-	pxa_gpio_mode(GPIO49_nPWE_MD);
-	pxa_gpio_mode(GPIO50_nPIOR_MD);
-	pxa_gpio_mode(GPIO51_nPIOW_MD);
-	pxa_gpio_mode(GPIO52_nPCE_1_MD);
-	pxa_gpio_mode(GPIO53_nPCE_2_MD);
-	pxa_gpio_mode(GPIO54_pSKTSEL_MD); /* REVISIT: s/b dependent on num sockets */
-	pxa_gpio_mode(GPIO55_nPREG_MD);
-	pxa_gpio_mode(GPIO56_nPWAIT_MD);
-	pxa_gpio_mode(GPIO57_nIOIS16_MD);
 
 	/* Provide our PXA2xx specific timing routines. */
 	ops->set_timing  = pxa2xx_pcmcia_set_timing;
diff -Nru a/drivers/pcmcia/pxa2xx_lubbock.c b/drivers/pcmcia/pxa2xx_lubbock.c
--- a/drivers/pcmcia/pxa2xx_lubbock.c	2004-10-18 14:56:50 -07:00
+++ b/drivers/pcmcia/pxa2xx_lubbock.c	2004-10-18 14:56:50 -07:00
@@ -25,11 +25,41 @@
 #include <asm/hardware.h>
 #include <asm/hardware/sa1111.h>
 #include <asm/mach-types.h>
+#include <asm/arch/pxa-regs.h>
 #include <asm/arch/lubbock.h>
 
 #include "sa1111_generic.h"
 
 static int
+lubbock_pcmcia_hw_init(struct soc_pcmcia_socket *skt)
+{
+	/*
+	 * Setup default state of GPIO outputs
+	 * before we enable them as outputs.
+	 */
+	GPSR(GPIO48_nPOE) =
+		GPIO_bit(GPIO48_nPOE) |
+		GPIO_bit(GPIO49_nPWE) |
+		GPIO_bit(GPIO50_nPIOR) |
+		GPIO_bit(GPIO51_nPIOW) |
+		GPIO_bit(GPIO52_nPCE_1) |
+		GPIO_bit(GPIO53_nPCE_2);
+
+	pxa_gpio_mode(GPIO48_nPOE_MD);
+	pxa_gpio_mode(GPIO49_nPWE_MD);
+	pxa_gpio_mode(GPIO50_nPIOR_MD);
+	pxa_gpio_mode(GPIO51_nPIOW_MD);
+	pxa_gpio_mode(GPIO52_nPCE_1_MD);
+	pxa_gpio_mode(GPIO53_nPCE_2_MD);
+	pxa_gpio_mode(GPIO54_pSKTSEL_MD);
+	pxa_gpio_mode(GPIO55_nPREG_MD);
+	pxa_gpio_mode(GPIO56_nPWAIT_MD);
+	pxa_gpio_mode(GPIO57_nIOIS16_MD);
+
+	return sa1111_pcmcia_hw_init(skt);
+}
+
+static int
 lubbock_pcmcia_configure_socket(struct soc_pcmcia_socket *skt,
 				const socket_state_t *state)
 {
@@ -201,7 +231,7 @@
 
 static struct pcmcia_low_level lubbock_pcmcia_ops = {
 	.owner			= THIS_MODULE,
-	.hw_init		= sa1111_pcmcia_hw_init,
+	.hw_init		= lubbock_pcmcia_hw_init,
 	.hw_shutdown		= sa1111_pcmcia_hw_shutdown,
 	.socket_state		= sa1111_pcmcia_socket_state,
 	.configure_socket	= lubbock_pcmcia_configure_socket,
diff -Nru a/drivers/pcmcia/pxa2xx_mainstone.c b/drivers/pcmcia/pxa2xx_mainstone.c
--- a/drivers/pcmcia/pxa2xx_mainstone.c	2004-10-18 14:56:32 -07:00
+++ b/drivers/pcmcia/pxa2xx_mainstone.c	2004-10-18 14:56:32 -07:00
@@ -24,6 +24,7 @@
 #include <asm/hardware.h>
 #include <asm/irq.h>
 
+#include <asm/arch/pxa-regs.h>
 #include <asm/arch/mainstone.h>
 
 #include "soc_common.h"
@@ -38,6 +39,29 @@
 
 static int mst_pcmcia_hw_init(struct soc_pcmcia_socket *skt)
 {
+	/*
+	 * Setup default state of GPIO outputs
+	 * before we enable them as outputs.
+	 */
+	GPSR(GPIO48_nPOE) =
+		GPIO_bit(GPIO48_nPOE) |
+		GPIO_bit(GPIO49_nPWE) |
+		GPIO_bit(GPIO50_nPIOR) |
+		GPIO_bit(GPIO51_nPIOW) |
+		GPIO_bit(GPIO85_nPCE_1) |
+		GPIO_bit(GPIO54_nPCE_2);
+
+	pxa_gpio_mode(GPIO48_nPOE_MD);
+	pxa_gpio_mode(GPIO49_nPWE_MD);
+	pxa_gpio_mode(GPIO50_nPIOR_MD);
+	pxa_gpio_mode(GPIO51_nPIOW_MD);
+	pxa_gpio_mode(GPIO85_nPCE_1_MD);
+	pxa_gpio_mode(GPIO54_nPCE_2_MD);
+	pxa_gpio_mode(GPIO79_pSKTSEL_MD);
+	pxa_gpio_mode(GPIO55_nPREG_MD);
+	pxa_gpio_mode(GPIO56_nPWAIT_MD);
+	pxa_gpio_mode(GPIO57_nIOIS16_MD);
+
 	skt->irq = (skt->nr == 0) ? MAINSTONE_S0_IRQ : MAINSTONE_S1_IRQ;
 	return soc_pcmcia_request_irqs(skt, irqs, ARRAY_SIZE(irqs));
 }
diff -Nru a/drivers/pcmcia/rsrc_mgr.c b/drivers/pcmcia/rsrc_mgr.c
--- a/drivers/pcmcia/rsrc_mgr.c	2004-10-18 14:56:33 -07:00
+++ b/drivers/pcmcia/rsrc_mgr.c	2004-10-18 14:56:33 -07:00
@@ -88,6 +88,9 @@
 };
 
 static DECLARE_MUTEX(rsrc_sem);
+static unsigned int rsrc_mem_probe;
+#define MEM_PROBE_LOW	(1 << 0)
+#define MEM_PROBE_HIGH	(1 << 1)
 
 #ifdef CONFIG_PCMCIA_PROBE
 
@@ -301,8 +304,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 +313,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;
@@ -325,15 +324,13 @@
 {
 	pccard_mem_map map;
 	int i, a = 0, b = -1, d;
-	void *virt;
+	void __iomem *virt;
 
 	virt = ioremap(res->start, s->map_size);
 	if (virt) {
 		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);
@@ -457,24 +454,21 @@
     return do_mem_probe(m->base, m->num, s);
 }
 
-static void validate_mem(struct pcmcia_socket *s)
+static void validate_mem(struct pcmcia_socket *s, unsigned int probe_mask)
 {
     resource_map_t *m, mm;
     static u_char order[] = { 0xd0, 0xe0, 0xc0, 0xf0 };
-    static int hi = 0, lo = 0;
     u_long b, i, ok = 0;
-    int force_low = !(s->features & SS_CAP_PAGE_REGS);
 
-    down(&rsrc_sem);
     /* We do up to four passes through the list */
-    if (!force_low) {
-	if (hi++ || (inv_probe(mem_db.next, s) > 0))
-	    goto out;
+    if (probe_mask & MEM_PROBE_HIGH) {
+	if (inv_probe(mem_db.next, s) > 0)
+	    return;
 	printk(KERN_NOTICE "cs: warning: no high memory space "
 	       "available!\n");
     }
-    if (lo++)
-	goto out;
+    if ((probe_mask & MEM_PROBE_LOW) == 0)
+	return;
     for (m = mem_db.next; m != &mem_db; m = mm.next) {
 	mm = *m;
 	/* Only probe < 1 MB */
@@ -494,38 +488,51 @@
 	    }
 	}
     }
- out:
-    up(&rsrc_sem);
 }
 
 #else /* CONFIG_PCMCIA_PROBE */
 
-static void validate_mem(struct pcmcia_socket *s)
+static void validate_mem(struct pcmcia_socket *s, unsigned int probe_mask)
 {
-    resource_map_t *m, mm;
-    static int done = 0;
+	resource_map_t *m, mm;
     
-    if (done++ == 0) {
-	down(&rsrc_sem);
 	for (m = mem_db.next; m != &mem_db; m = mm.next) {
-	    mm = *m;
-	    if (do_mem_probe(mm.base, mm.num, s))
-		break;
+		mm = *m;
+		if (do_mem_probe(mm.base, mm.num, s))
+			break;
 	}
-	up(&rsrc_sem);
-    }
 }
 
 #endif /* CONFIG_PCMCIA_PROBE */
 
+/*
+ * Locking note: this is the only place where we take
+ * both rsrc_sem and skt_sem.
+ */
 void pcmcia_validate_mem(struct pcmcia_socket *s)
 {
-	down(&s->skt_sem);
+	if (probe_mem) {
+		unsigned int probe_mask;
+
+		down(&rsrc_sem);
+
+		probe_mask = MEM_PROBE_LOW;
+		if (s->features & SS_CAP_PAGE_REGS)
+			probe_mask = MEM_PROBE_HIGH;
 
-	if (probe_mem && s->state & SOCKET_PRESENT)
-		validate_mem(s);
+		if (probe_mask & ~rsrc_mem_probe) {
+			rsrc_mem_probe |= probe_mask;
 
-	up(&s->skt_sem);
+			down(&s->skt_sem);
+
+			if (s->state & SOCKET_PRESENT)
+				validate_mem(s, probe_mask);
+
+			up(&s->skt_sem);
+		}
+
+		up(&rsrc_sem);
+	}
 }
 
 EXPORT_SYMBOL(pcmcia_validate_mem);
diff -Nru a/drivers/pcmcia/sa1100_h3600.c b/drivers/pcmcia/sa1100_h3600.c
--- a/drivers/pcmcia/sa1100_h3600.c	2004-10-18 14:56:48 -07:00
+++ b/drivers/pcmcia/sa1100_h3600.c	2004-10-18 14:56:48 -07:00
@@ -10,6 +10,7 @@
 #include <linux/device.h>
 #include <linux/interrupt.h>
 #include <linux/init.h>
+#include <linux/delay.h>
 
 #include <asm/hardware.h>
 #include <asm/irq.h>
@@ -96,8 +97,7 @@
 	set_h3600_egpio(IPAQ_EGPIO_OPT_ON);
 	clr_h3600_egpio(IPAQ_EGPIO_OPT_RESET);
 
-	set_current_state(TASK_UNINTERRUPTIBLE);
-	schedule_timeout(10*HZ / 1000);
+	msleep(10);
 
 	soc_pcmcia_enable_irqs(skt, irqs, ARRAY_SIZE(irqs));
 }
diff -Nru a/drivers/pcmcia/soc_common.c b/drivers/pcmcia/soc_common.c
--- a/drivers/pcmcia/soc_common.c	2004-10-18 14:56:17 -07:00
+++ b/drivers/pcmcia/soc_common.c	2004-10-18 14:56:17 -07:00
@@ -49,6 +49,11 @@
 
 #include "soc_common.h"
 
+/* FIXME: platform dependent resource declaration has to move out of this file */
+#ifdef CONFIG_ARCH_PXA
+#include <asm/arch/pxa-regs.h>
+#endif
+
 #ifdef DEBUG
 
 static int pc_debug;
@@ -448,9 +453,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 +665,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 +683,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 +781,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-10-18 14:56:32 -07:00
+++ b/drivers/pcmcia/tcic.c	2004-10-18 14:56:32 -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-10-18 14:56:33 -07:00
+++ b/drivers/pcmcia/yenta_socket.c	2004-10-18 14:56:33 -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++) {
@@ -1088,6 +1091,7 @@
 	CB_ID(PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_4410, TI12XX),
 	CB_ID(PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_4450, TI12XX),
 	CB_ID(PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_4451, TI12XX),
+	CB_ID(PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_4520, TI12XX),
 
 	CB_ID(PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_1250, TI1250),
 	CB_ID(PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_1410, TI1250),
diff -Nru a/drivers/pcmcia/yenta_socket.h b/drivers/pcmcia/yenta_socket.h
--- a/drivers/pcmcia/yenta_socket.h	2004-10-18 14:56:28 -07:00
+++ b/drivers/pcmcia/yenta_socket.h	2004-10-18 14:56:28 -07:00
@@ -107,7 +107,7 @@
 struct yenta_socket {
 	struct pci_dev *dev;
 	int cb_irq, io_irq;
-	void *base;
+	void __iomem *base;
 	struct timer_list poll_timer;
 
 	struct pcmcia_socket socket;
diff -Nru a/drivers/pnp/interface.c b/drivers/pnp/interface.c
--- a/drivers/pnp/interface.c	2004-10-18 14:56:11 -07:00
+++ b/drivers/pnp/interface.c	2004-10-18 14:56:11 -07:00
@@ -240,12 +240,14 @@
 {
 	struct pnp_dev *dev = to_pnp_dev(dmdev);
 	int i, ret;
-	pnp_info_buffer_t *buffer = (pnp_info_buffer_t *)
-				pnp_alloc(sizeof(pnp_info_buffer_t));
-	if (!buffer)
-		return -ENOMEM;
+	pnp_info_buffer_t *buffer;
+
 	if (!dev)
 		return -EINVAL;
+
+	buffer = (pnp_info_buffer_t *) pnp_alloc(sizeof(pnp_info_buffer_t));
+	if (!buffer)
+		return -ENOMEM;
 	buffer->len = PAGE_SIZE;
 	buffer->buffer = buf;
 	buffer->curr = buffer->buffer;
diff -Nru a/drivers/pnp/isapnp/core.c b/drivers/pnp/isapnp/core.c
--- a/drivers/pnp/isapnp/core.c	2004-10-18 14:56:32 -07:00
+++ b/drivers/pnp/isapnp/core.c	2004-10-18 14:56:32 -07:00
@@ -655,8 +655,10 @@
 	if ((dev = isapnp_parse_device(card, size, number++)) == NULL)
 		return 1;
 	option = pnp_register_independent_option(dev);
-	if (!option)
+	if (!option) {
+		kfree(dev);
 		return 1;
+	}
 	pnp_add_card_device(card,dev);
 
 	while (1) {
diff -Nru a/drivers/pnp/pnpbios/bioscalls.c b/drivers/pnp/pnpbios/bioscalls.c
--- a/drivers/pnp/pnpbios/bioscalls.c	2004-10-18 14:56:48 -07:00
+++ b/drivers/pnp/pnpbios/bioscalls.c	2004-10-18 14:56:48 -07:00
@@ -69,14 +69,14 @@
 
 #define Q_SET_SEL(cpu, selname, address, size) \
 do { \
-set_base(cpu_gdt_table[cpu][(selname) >> 3], __va((u32)(address))); \
-set_limit(cpu_gdt_table[cpu][(selname) >> 3], size); \
+set_base(per_cpu(cpu_gdt_table,cpu)[(selname) >> 3], __va((u32)(address))); \
+set_limit(per_cpu(cpu_gdt_table,cpu)[(selname) >> 3], size); \
 } while(0)
 
 #define Q2_SET_SEL(cpu, selname, address, size) \
 do { \
-set_base(cpu_gdt_table[cpu][(selname) >> 3], (u32)(address)); \
-set_limit(cpu_gdt_table[cpu][(selname) >> 3], size); \
+set_base(per_cpu(cpu_gdt_table,cpu)[(selname) >> 3], (u32)(address)); \
+set_limit(per_cpu(cpu_gdt_table,cpu)[(selname) >> 3], size); \
 } while(0)
 
 static struct desc_struct bad_bios_desc = { 0, 0x00409200 };
@@ -115,8 +115,8 @@
 		return PNP_FUNCTION_NOT_SUPPORTED;
 
 	cpu = get_cpu();
-	save_desc_40 = cpu_gdt_table[cpu][0x40 / 8];
-	cpu_gdt_table[cpu][0x40 / 8] = bad_bios_desc;
+	save_desc_40 = per_cpu(cpu_gdt_table,cpu)[0x40 / 8];
+	per_cpu(cpu_gdt_table,cpu)[0x40 / 8] = bad_bios_desc;
 
 	/* On some boxes IRQ's during PnP BIOS calls are deadly.  */
 	spin_lock_irqsave(&pnp_bios_lock, flags);
@@ -158,7 +158,7 @@
 	);
 	spin_unlock_irqrestore(&pnp_bios_lock, flags);
 
-	cpu_gdt_table[cpu][0x40 / 8] = save_desc_40;
+	per_cpu(cpu_gdt_table,cpu)[0x40 / 8] = save_desc_40;
 	put_cpu();
 
 	/* If we get here and this is set then the PnP BIOS faulted on us. */
diff -Nru a/drivers/pnp/pnpbios/core.c b/drivers/pnp/pnpbios/core.c
--- a/drivers/pnp/pnpbios/core.c	2004-10-18 14:55:54 -07:00
+++ b/drivers/pnp/pnpbios/core.c	2004-10-18 14:55:54 -07:00
@@ -252,8 +252,10 @@
 	node = pnpbios_kmalloc(node_info.max_node_size, GFP_KERNEL);
 	if (!node)
 		return -1;
-	if (pnp_bios_get_dev_node(&nodenum, (char )PNPMODE_DYNAMIC, node))
+	if (pnp_bios_get_dev_node(&nodenum, (char )PNPMODE_DYNAMIC, node)) {
+		kfree(node);
 		return -ENODEV;
+	}
 	if(pnpbios_write_resources_to_node(res, node)<0) {
 		kfree(node);
 		return -1;
diff -Nru a/drivers/pnp/pnpbios/proc.c b/drivers/pnp/pnpbios/proc.c
--- a/drivers/pnp/pnpbios/proc.c	2004-10-18 14:57:04 -07:00
+++ b/drivers/pnp/pnpbios/proc.c	2004-10-18 14:57:04 -07:00
@@ -90,8 +90,10 @@
 	tmpbuf = pnpbios_kmalloc(escd.escd_size, GFP_KERNEL);
 	if (!tmpbuf) return -ENOMEM;
 
-	if (pnp_bios_read_escd(tmpbuf, escd.nv_storage_base))
+	if (pnp_bios_read_escd(tmpbuf, escd.nv_storage_base)) {
+		kfree(tmpbuf);
 		return -EIO;
+	}
 
 	escd_size = (unsigned char)(tmpbuf[0]) + (unsigned char)(tmpbuf[1])*256;
 
@@ -168,8 +170,10 @@
 
 	node = pnpbios_kmalloc(node_info.max_node_size, GFP_KERNEL);
 	if (!node) return -ENOMEM;
-	if (pnp_bios_get_dev_node(&nodenum, boot, node))
+	if (pnp_bios_get_dev_node(&nodenum, boot, node)) {
+		kfree(node);
 		return -EIO;
+	}
 	len = node->size - sizeof(struct pnp_bios_node);
 	memcpy(buf, node->data, len);
 	kfree(node);
diff -Nru a/drivers/pnp/pnpbios/rsparser.c b/drivers/pnp/pnpbios/rsparser.c
--- a/drivers/pnp/pnpbios/rsparser.c	2004-10-18 14:56:28 -07:00
+++ b/drivers/pnp/pnpbios/rsparser.c	2004-10-18 14:56:28 -07:00
@@ -346,12 +346,12 @@
 {
 	unsigned int len, tag;
 	int priority = 0;
-	struct pnp_option *option;
+	struct pnp_option *option, *option_independent;
 
 	if (!p)
 		return NULL;
 
-	option = pnp_register_independent_option(dev);
+	option_independent = option = pnp_register_independent_option(dev);
 	if (!option)
 		return NULL;
 
@@ -428,9 +428,14 @@
 		case SMALL_TAG_ENDDEP:
 			if (len != 0)
 				goto len_err;
+			if (option_independent == option)
+				printk(KERN_WARNING "PnPBIOS: Missing SMALL_TAG_STARTDEP tag\n");
+			option = option_independent;
 			break;
 
 		case SMALL_TAG_END:
+			if (option_independent != option)
+				printk(KERN_WARNING "PnPBIOS: Missing SMALL_TAG_ENDDEP tag\n");
 			p = p + 2;
         		return (unsigned char *)p;
 			break;
diff -Nru a/drivers/pnp/system.c b/drivers/pnp/system.c
--- a/drivers/pnp/system.c	2004-10-18 14:57:18 -07:00
+++ b/drivers/pnp/system.c	2004-10-18 14:57:18 -07:00
@@ -104,4 +104,8 @@
 	return pnp_register_driver(&system_pnp_driver);
 }
 
-subsys_initcall(pnp_system_init);
+/**
+ * Reserve motherboard resources after PCI claim BARs,
+ * but before PCI assign resources for uninitialized PCI devices
+ */
+fs_initcall(pnp_system_init);
diff -Nru a/drivers/s390/block/dasd_diag.c b/drivers/s390/block/dasd_diag.c
--- a/drivers/s390/block/dasd_diag.c	2004-10-18 14:55:54 -07:00
+++ b/drivers/s390/block/dasd_diag.c	2004-10-18 14:55:54 -07:00
@@ -6,7 +6,7 @@
  * Bugreports.to..: <Linux390@de.ibm.com>
  * (C) IBM Corporation, IBM Deutschland Entwicklung GmbH, 1999,2000
  *
- * $Revision: 1.37 $
+ * $Revision: 1.38 $
  */
 
 #include <linux/config.h>
@@ -304,8 +304,11 @@
 			    (device->bp_block >> 10),
 			    (device->blocks << device->s2b_shift) >> 1);
 		rc = 0;
-	} else
+	} else {
+		DEV_MESSAGE(KERN_WARNING, device, "%s",
+			    "volume has incompatible disk layout");
 		rc = -EMEDIUMTYPE;
+	}
 	free_page((long) label);
 	return rc;
 }
diff -Nru a/drivers/s390/block/dasd_eckd.c b/drivers/s390/block/dasd_eckd.c
--- a/drivers/s390/block/dasd_eckd.c	2004-10-18 14:55:53 -07:00
+++ b/drivers/s390/block/dasd_eckd.c	2004-10-18 14:55:53 -07:00
@@ -7,7 +7,7 @@
  * Bugreports.to..: <Linux390@de.ibm.com>
  * (C) IBM Corporation, IBM Deutschland Entwicklung GmbH, 1999,2000
  *
- * $Revision: 1.57 $
+ * $Revision: 1.61 $
  */
 
 #include <linux/config.h>
@@ -68,6 +68,10 @@
 	{ CCW_DEVICE_DEVTYPE (0x3990, 0, 0x3380, 0), driver_info: 0x4},
 	{ CCW_DEVICE_DEVTYPE (0x2105, 0, 0x3380, 0), driver_info: 0x5},
 	{ CCW_DEVICE_DEVTYPE (0x9343, 0, 0x9345, 0), driver_info: 0x6},
+	{ CCW_DEVICE_DEVTYPE (0x2107, 0, 0x3390, 0), driver_info: 0x7},
+	{ CCW_DEVICE_DEVTYPE (0x2107, 0, 0x3380, 0), driver_info: 0x8},
+	{ CCW_DEVICE_DEVTYPE (0x1750, 0, 0x3390, 0), driver_info: 0x9},
+	{ CCW_DEVICE_DEVTYPE (0x1750, 0, 0x3380, 0), driver_info: 0xa},
 	{ /* end of list */ },
 };
 
@@ -274,9 +278,11 @@
 
 	data->attributes.mode = 0x3;	/* ECKD */
 
-	if (private->rdc_data.cu_type == 0x2105
+	if ((private->rdc_data.cu_type == 0x2105 ||
+	     private->rdc_data.cu_type == 0x2107 ||
+	     private->rdc_data.cu_type == 0x1750)
 	    && !(private->uses_cdl && trk < 2))
-		data->ga_extended |= 0x40;
+		data->ga_extended |= 0x40; /* Regular Data Format Mode */
 
 	geo.cyl = private->rdc_data.no_cyl;
 	geo.head = private->rdc_data.trk_per_cyl;
@@ -499,11 +505,13 @@
 			"sizes of configuration data mismatch"
 			"%d (read) vs %ld (expected)",
 			conf_len, sizeof (struct dasd_eckd_confdata));
+
+		kfree(conf_data); /* allocated by read_conf_data() */
 		return 0;	/* no errror */
 	}
 	memcpy(&private->conf_data, conf_data,
 	       sizeof (struct dasd_eckd_confdata));
-
+	kfree(conf_data); /* allocated by read_conf_data() */
 	return 0;
 }
 
@@ -903,6 +911,8 @@
 	switch (cdev->id.cu_type) {
 	case 0x3990:
 	case 0x2105:
+	case 0x2107:
+	case 0x1750:
 		return dasd_3990_erp_examine(cqr, irb);
 	case 0x9343:
 		return dasd_9343_erp_examine(cqr, irb);
@@ -923,6 +933,8 @@
 	switch (cdev->id.cu_type) {
 	case 0x3990:
 	case 0x2105:
+	case 0x2107:
+	case 0x1750:
 		return dasd_3990_erp_action;
 	case 0x9343:
 		/* Return dasd_9343_erp_action; */
diff -Nru a/drivers/s390/block/dcssblk.c b/drivers/s390/block/dcssblk.c
--- a/drivers/s390/block/dcssblk.c	2004-10-18 14:56:18 -07:00
+++ b/drivers/s390/block/dcssblk.c	2004-10-18 14:56:18 -07:00
@@ -5,6 +5,7 @@
  */
 
 #include <linux/module.h>
+#include <linux/moduleparam.h>
 #include <linux/ctype.h>
 #include <linux/errno.h>
 #include <linux/init.h>
@@ -19,6 +20,7 @@
 //#define DCSSBLK_DEBUG		/* Debug messages on/off */
 #define DCSSBLK_NAME "dcssblk"
 #define DCSSBLK_MINORS_PER_DISK 1
+#define DCSSBLK_PARM_LEN 400
 
 #ifdef DCSSBLK_DEBUG
 #define PRINT_DEBUG(x...) printk(KERN_DEBUG DCSSBLK_NAME " debug: " x)
@@ -34,6 +36,8 @@
 static int dcssblk_release(struct inode *inode, struct file *filp);
 static int dcssblk_make_request(struct request_queue *q, struct bio *bio);
 
+static char dcssblk_segments[DCSSBLK_PARM_LEN] = "\0";
+
 static int dcssblk_major;
 static struct block_device_operations dcssblk_devops = {
 	.owner   = THIS_MODULE,
@@ -641,6 +645,47 @@
 	return 0;
 }
 
+static void
+dcssblk_check_params(void)
+{
+	int rc, i, j, k;
+	char buf[9];
+	struct dcssblk_dev_info *dev_info;
+
+	for (i = 0; (i < DCSSBLK_PARM_LEN) && (dcssblk_segments[i] != '\0');
+	     i++) {
+		for (j = i; (dcssblk_segments[j] != ',')  &&
+			    (dcssblk_segments[j] != '\0') &&
+			    (dcssblk_segments[j] != '(')  &&
+			    (j - i) < 8; j++)
+		{
+			buf[j-i] = dcssblk_segments[j];
+		}
+		buf[j-i] = '\0';
+		rc = dcssblk_add_store(dcssblk_root_dev, buf, j-i);
+		if ((rc >= 0) && (dcssblk_segments[j] == '(')) {
+			for (k = 0; buf[k] != '\0'; k++)
+				buf[k] = toupper(buf[k]);
+			if (!strncmp(&dcssblk_segments[j], "(local)", 7)) {
+				down_read(&dcssblk_devices_sem);
+				dev_info = dcssblk_get_device_by_name(buf);
+				up_read(&dcssblk_devices_sem);
+				if (dev_info)
+					dcssblk_shared_store(&dev_info->dev,
+							     "0\n", 2);
+			}
+		}
+		while ((dcssblk_segments[j] != ',') &&
+		       (dcssblk_segments[j] != '\0'))
+		{
+			j++;
+		}
+		if (dcssblk_segments[j] == '\0')
+			break;
+		i = j;
+	}
+}
+
 /*
  * The init/exit functions.
  */
@@ -689,11 +734,22 @@
 	}
 	dcssblk_major = rc;
 	init_rwsem(&dcssblk_devices_sem);
+
+	dcssblk_check_params();
+
 	PRINT_DEBUG("...finished!\n");
 	return 0;
 }
 
 module_init(dcssblk_init);
 module_exit(dcssblk_exit);
+
+module_param_string(segments, dcssblk_segments, DCSSBLK_PARM_LEN, 0444);
+MODULE_PARM_DESC(segments, "Name of DCSS segment(s) to be loaded, "
+		 "comma-separated list, each name max. 8 chars.\n"
+		 "Adding \"(local)\" to segment name equals echoing 0 to "
+		 "/sys/devices/dcssblk/<segment name>/shared after loading "
+		 "the segment - \n"
+		 "e.g. segments=\"mydcss1,mydcss2,mydcss3(local)\"");
 
 MODULE_LICENSE("GPL");
diff -Nru a/drivers/s390/char/con3215.c b/drivers/s390/char/con3215.c
--- a/drivers/s390/char/con3215.c	2004-10-18 14:56:48 -07:00
+++ b/drivers/s390/char/con3215.c	2004-10-18 14:56:48 -07:00
@@ -366,10 +366,7 @@
 	tty = raw->tty;
 	if (tty != NULL &&
 	    RAW3215_BUFFER_SIZE - raw->count >= RAW3215_MIN_SPACE) {
-		if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
-		    tty->ldisc.write_wakeup)
-			(tty->ldisc.write_wakeup)(tty);
-		wake_up_interruptible(&tty->write_wait);
+	    	tty_wakeup(tty);
 	}
 }
 
@@ -1055,10 +1052,7 @@
 
 	raw = (struct raw3215_info *) tty->driver_data;
 	raw3215_flush_buffer(raw);
-	wake_up_interruptible(&tty->write_wait);
-	if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
-	    tty->ldisc.write_wakeup)
-		(tty->ldisc.write_wakeup)(tty);
+	tty_wakeup(tty);
 }
 
 /*
diff -Nru a/drivers/s390/char/sclp.c b/drivers/s390/char/sclp.c
--- a/drivers/s390/char/sclp.c	2004-10-18 14:56:33 -07:00
+++ b/drivers/s390/char/sclp.c	2004-10-18 14:56:33 -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/char/sclp_tty.c b/drivers/s390/char/sclp_tty.c
--- a/drivers/s390/char/sclp_tty.c	2004-10-18 14:57:19 -07:00
+++ b/drivers/s390/char/sclp_tty.c	2004-10-18 14:57:19 -07:00
@@ -277,10 +277,7 @@
 	wake_up(&sclp_tty_waitq);
 	/* check if the tty needs a wake up call */
 	if (sclp_tty != NULL) {
-		if ((sclp_tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
-		    sclp_tty->ldisc.write_wakeup)
-			(sclp_tty->ldisc.write_wakeup)(sclp_tty);
-		wake_up_interruptible(&sclp_tty->write_wait);
+		tty_wakeup(sclp_tty);
 	}
 }
 
diff -Nru a/drivers/s390/char/sclp_vt220.c b/drivers/s390/char/sclp_vt220.c
--- a/drivers/s390/char/sclp_vt220.c	2004-10-18 14:56:28 -07:00
+++ b/drivers/s390/char/sclp_vt220.c	2004-10-18 14:56:28 -07:00
@@ -139,10 +139,7 @@
 	wake_up(&sclp_vt220_waitq);
 	/* Check if the tty needs a wake up call */
 	if (sclp_vt220_tty != NULL) {
-		if ((sclp_vt220_tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
-		    (sclp_vt220_tty->ldisc.write_wakeup != NULL))
-			(sclp_vt220_tty->ldisc.write_wakeup)(sclp_vt220_tty);
-		wake_up_interruptible(&sclp_vt220_tty->write_wait);
+		tty_wakeup(sclp_vt220_tty);
 	}
 }
 
diff -Nru a/drivers/s390/cio/blacklist.c b/drivers/s390/cio/blacklist.c
--- a/drivers/s390/cio/blacklist.c	2004-10-18 14:56:28 -07:00
+++ b/drivers/s390/cio/blacklist.c	2004-10-18 14:56:28 -07:00
@@ -1,7 +1,7 @@
 /*
  *  drivers/s390/cio/blacklist.c
  *   S/390 common I/O routines -- blacklisting of specific devices
- *   $Revision: 1.31 $
+ *   $Revision: 1.33 $
  *
  *    Copyright (C) 1999-2002 IBM Deutschland Entwicklung GmbH,
  *			      IBM Corporation
@@ -229,7 +229,7 @@
 	unsigned int irq;
 
 	CIO_TRACE_EVENT (0, "redoval");
-	for (irq = 0; irq <= __MAX_SUBCHANNELS; irq++) {
+	for (irq = 0; irq < __MAX_SUBCHANNELS; irq++) {
 		int ret;
 		struct subchannel *sch;
 
diff -Nru a/drivers/s390/cio/ccwgroup.c b/drivers/s390/cio/ccwgroup.c
--- a/drivers/s390/cio/ccwgroup.c	2004-10-18 14:56:32 -07:00
+++ b/drivers/s390/cio/ccwgroup.c	2004-10-18 14:56:32 -07:00
@@ -1,7 +1,7 @@
 /*
  *  drivers/s390/cio/ccwgroup.c
  *  bus driver for ccwgroup
- *   $Revision: 1.28 $
+ *   $Revision: 1.29 $
  *
  *    Copyright (C) 2002 IBM Deutschland Entwicklung GmbH,
  *                       IBM Corporation
@@ -191,14 +191,12 @@
 		gdev->cdev[i]->dev.driver_data = gdev;
 	del_drvdata = 1;
 
-	*gdev = (struct ccwgroup_device) {
-		.creator_id = creator_id,
-		.count = argc,
-		.dev = {
-			.bus = &ccwgroup_bus_type,
-			.parent = root,
-			.release = ccwgroup_release,
-		},
+	gdev->creator_id = creator_id;
+	gdev->count = argc;
+	gdev->dev = (struct device ) {
+		.bus = &ccwgroup_bus_type,
+		.parent = root,
+		.release = ccwgroup_release,
 	};
 
 	snprintf (gdev->dev.bus_id, BUS_ID_SIZE, "%s",
diff -Nru a/drivers/s390/cio/cio.c b/drivers/s390/cio/cio.c
--- a/drivers/s390/cio/cio.c	2004-10-18 14:57:04 -07:00
+++ b/drivers/s390/cio/cio.c	2004-10-18 14:57:04 -07:00
@@ -1,7 +1,7 @@
 /*
  *  drivers/s390/cio/cio.c
  *   S/390 common I/O routines -- low level i/o calls
- *   $Revision: 1.123 $
+ *   $Revision: 1.128 $
  *
  *    Copyright (C) 1999-2002 IBM Deutschland Entwicklung GmbH,
  *			      IBM Corporation
@@ -17,8 +17,8 @@
 #include <linux/slab.h>
 #include <linux/device.h>
 #include <linux/kernel_stat.h>
+#include <linux/interrupt.h>
 
-#include <asm/hardirq.h>
 #include <asm/cio.h>
 #include <asm/delay.h>
 #include <asm/irq.h>
@@ -141,6 +141,7 @@
 	sch = (struct subchannel *)(unsigned long)tpi_info->intparm;
 	if (!sch)
 		return 1;
+	local_bh_disable();
 	irq_enter ();
 	spin_lock(&sch->lock);
 	memcpy (&sch->schib.scsw, &irb->scsw, sizeof (struct scsw));
@@ -148,6 +149,7 @@
 		sch->driver->irq(&sch->dev);
 	spin_unlock(&sch->lock);
 	irq_exit ();
+	__local_bh_enable();
 	return 1;
 }
 
@@ -409,10 +411,10 @@
 	if (ccode)
 		return -ENODEV;
 
-	sch->schib.pmcw.ena = 1;
-	sch->schib.pmcw.isc = isc;
-	sch->schib.pmcw.intparm = (__u32)(unsigned long)sch;
 	for (retry = 5, ret = 0; retry > 0; retry--) {
+		sch->schib.pmcw.ena = 1;
+		sch->schib.pmcw.isc = isc;
+		sch->schib.pmcw.intparm = (__u32)(unsigned long)sch;
 		ret = cio_modify(sch);
 		if (ret == -ENODEV)
 			break;
@@ -463,9 +465,8 @@
 		 */
 		return -EBUSY;
 
-
-	sch->schib.pmcw.ena = 0;
 	for (retry = 5, ret = 0; retry > 0; retry--) {
+		sch->schib.pmcw.ena = 0;
 		ret = cio_modify(sch);
 		if (ret == -ENODEV)
 			break;
diff -Nru a/drivers/s390/cio/cmf.c b/drivers/s390/cio/cmf.c
--- a/drivers/s390/cio/cmf.c	2004-10-18 14:55:46 -07:00
+++ b/drivers/s390/cio/cmf.c	2004-10-18 14:55:46 -07:00
@@ -1,5 +1,5 @@
 /*
- * linux/drivers/s390/cio/cmf.c ($Revision: 1.15 $)
+ * linux/drivers/s390/cio/cmf.c ($Revision: 1.16 $)
  *
  * Linux on zSeries Channel Measurement Facility support
  *
@@ -526,29 +526,26 @@
 	time = get_clock() - cdev->private->cmb_start_time;
 	spin_unlock_irqrestore(cdev->ccwlock, flags);
 
-	*data = (struct cmbdata) {
-		/* we only know values before device_busy_time */
-		.size = offsetof(struct cmbdata, device_busy_time),
-
-		/* conver to nanoseconds */
-		.elapsed_time = (time * 1000) >> 12,
-
-		/* copy data to new structure */
-		.ssch_rsch_count		= cmb.ssch_rsch_count,
-		.sample_count			= cmb.sample_count,
-
-		/* time fields are converted to nanoseconds while copying */
-		.device_connect_time
-			= time_to_nsec(cmb.device_connect_time),
-		.function_pending_time
-			= time_to_nsec(cmb.function_pending_time),
-		.device_disconnect_time
-			= time_to_nsec(cmb.device_disconnect_time),
-		.control_unit_queuing_time
-		 	= time_to_nsec(cmb.control_unit_queuing_time),
-		.device_active_only_time
-			= time_to_nsec(cmb.device_active_only_time),
-	};
+	memset(data, sizeof(struct cmbdata), 0);
+
+	/* we only know values before device_busy_time */
+	data->size = offsetof(struct cmbdata, device_busy_time);
+
+	/* convert to nanoseconds */
+	data->elapsed_time = (time * 1000) >> 12;
+
+	/* copy data to new structure */
+	data->ssch_rsch_count = cmb.ssch_rsch_count;
+	data->sample_count = cmb.sample_count;
+
+	/* time fields are converted to nanoseconds while copying */
+	data->device_connect_time = time_to_nsec(cmb.device_connect_time);
+	data->function_pending_time = time_to_nsec(cmb.function_pending_time);
+	data->device_disconnect_time = time_to_nsec(cmb.device_disconnect_time);
+	data->control_unit_queuing_time
+		= time_to_nsec(cmb.control_unit_queuing_time);
+	data->device_active_only_time
+		= time_to_nsec(cmb.device_active_only_time);
 
 	return 0;
 }
@@ -739,33 +736,29 @@
 	time = get_clock() - cdev->private->cmb_start_time;
 	spin_unlock_irqrestore(cdev->ccwlock, flags);
 
-	*data = (struct cmbdata) {
-		/* we only know values before device_busy_time */
-		.size = offsetof(struct cmbdata, device_busy_time),
-
-		/* conver to nanoseconds */
-		.elapsed_time = (time * 1000) >> 12,
-
-		/* copy data to new structure */
-		.ssch_rsch_count		= cmb.ssch_rsch_count,
-		.sample_count			= cmb.sample_count,
-
-		/* time fields are converted to nanoseconds while copying */
-		.device_connect_time
-			= time_to_nsec(cmb.device_connect_time),
-		.function_pending_time
-			= time_to_nsec(cmb.function_pending_time),
-		.device_disconnect_time
-			= time_to_nsec(cmb.device_disconnect_time),
-		.control_unit_queuing_time
-		 	= time_to_nsec(cmb.control_unit_queuing_time),
-		.device_active_only_time
-			= time_to_nsec(cmb.device_active_only_time),
-		.device_busy_time
-			= time_to_nsec(cmb.device_busy_time),
-		.initial_command_response_time
-			= time_to_nsec(cmb.initial_command_response_time),
-	};
+	memset (data, sizeof(struct cmbdata), 0);
+
+	/* we only know values before device_busy_time */
+	data->size = offsetof(struct cmbdata, device_busy_time);
+
+	/* conver to nanoseconds */
+	data->elapsed_time = (time * 1000) >> 12;
+
+	/* copy data to new structure */
+	data->ssch_rsch_count = cmb.ssch_rsch_count;
+	data->sample_count = cmb.sample_count;
+
+	/* time fields are converted to nanoseconds while copying */
+	data->device_connect_time = time_to_nsec(cmb.device_connect_time);
+	data->function_pending_time = time_to_nsec(cmb.function_pending_time);
+	data->device_disconnect_time = time_to_nsec(cmb.device_disconnect_time);
+	data->control_unit_queuing_time
+		= time_to_nsec(cmb.control_unit_queuing_time);
+	data->device_active_only_time
+		= time_to_nsec(cmb.device_active_only_time);
+	data->device_busy_time = time_to_nsec(cmb.device_busy_time);
+	data->initial_command_response_time
+		= time_to_nsec(cmb.initial_command_response_time);
 
 	return 0;
 }
diff -Nru a/drivers/s390/cio/css.c b/drivers/s390/cio/css.c
--- a/drivers/s390/cio/css.c	2004-10-18 14:57:19 -07:00
+++ b/drivers/s390/cio/css.c	2004-10-18 14:57:19 -07:00
@@ -1,7 +1,7 @@
 /*
  *  drivers/s390/cio/css.c
  *  driver for channel subsystem
- *   $Revision: 1.80 $
+ *   $Revision: 1.82 $
  *
  *    Copyright (C) 2002 IBM Deutschland Entwicklung GmbH,
  *			 IBM Corporation
@@ -278,7 +278,7 @@
 {
 	int irq, ret;
 
-	for (irq = 0; irq <= __MAX_SUBCHANNELS; irq++) {
+	for (irq = 0; irq < __MAX_SUBCHANNELS; irq++) {
 		ret = css_evaluate_subchannel(irq, 1);
 		/* No more memory. It doesn't make sense to continue. No
 		 * panic because this can happen in midflight and just
@@ -521,6 +521,7 @@
 	new_slow_sch = kmalloc(sizeof(struct slow_subchannel), GFP_ATOMIC);
 	if (!new_slow_sch)
 		return -ENOMEM;
+	memset(new_slow_sch, sizeof(struct slow_subchannel), 0);
 	new_slow_sch->schid = schid;
 	spin_lock_irqsave(&slow_subchannel_lock, flags);
 	list_add_tail(&new_slow_sch->slow_list, &slow_subchannels_head);
diff -Nru a/drivers/s390/cio/device.c b/drivers/s390/cio/device.c
--- a/drivers/s390/cio/device.c	2004-10-18 14:56:49 -07:00
+++ b/drivers/s390/cio/device.c	2004-10-18 14:56:49 -07:00
@@ -1,7 +1,7 @@
 /*
  *  drivers/s390/cio/device.c
  *  bus driver for ccw devices
- *   $Revision: 1.120 $
+ *   $Revision: 1.124 $
  *
  *    Copyright (C) 2002 IBM Deutschland Entwicklung GmbH,
  *			 IBM Corporation
@@ -540,6 +540,8 @@
 	return cdev;
 }
 
+extern int css_get_ssd_info(struct subchannel *sch);
+
 void
 ccw_device_do_unreg_rereg(void *data)
 {
@@ -581,6 +583,8 @@
 				device_unregister(&other_sch->dev);
 			}
 		}
+		/* Update ssd info here. */
+		css_get_ssd_info(sch);
 		cdev->private->devno = sch->schib.pmcw.dev;
 	} else
 		need_rename = 0;
@@ -633,7 +637,8 @@
 		sch->dev.driver_data = 0;
 		kfree (cdev->private);
 		kfree (cdev);
-		goto out;
+		put_device(&sch->dev);
+		return;
 	}
 
 	ret = subchannel_add_files(cdev->dev.parent);
@@ -707,18 +712,19 @@
 io_subchannel_recog(struct ccw_device *cdev, struct subchannel *sch)
 {
 	int rc;
+	struct ccw_device_private *priv;
 
 	sch->dev.driver_data = cdev;
 	sch->driver = &io_subchannel_driver;
 	cdev->ccwlock = &sch->lock;
-	*cdev->private = (struct ccw_device_private) {
-		.devno	= sch->schib.pmcw.dev,
-		.irq	= sch->irq,
-		.state	= DEV_STATE_NOT_OPER,
-		.cmb_list = LIST_HEAD_INIT(cdev->private->cmb_list),
-	};
-	init_waitqueue_head(&cdev->private->wait_q);
-	init_timer(&cdev->private->timer);
+	/* Init private data. */
+	priv = cdev->private;
+	priv->devno = sch->schib.pmcw.dev;
+	priv->irq = sch->irq;
+	priv->state = DEV_STATE_NOT_OPER;
+	INIT_LIST_HEAD(&priv->cmb_list);
+	init_waitqueue_head(&priv->wait_q);
+	init_timer(&priv->timer);
 
 	/* Set an initial name for the device. */
 	snprintf (cdev->dev.bus_id, BUS_ID_SIZE, "0.0.%04x",
diff -Nru a/drivers/s390/cio/device_fsm.c b/drivers/s390/cio/device_fsm.c
--- a/drivers/s390/cio/device_fsm.c	2004-10-18 14:56:32 -07:00
+++ b/drivers/s390/cio/device_fsm.c	2004-10-18 14:56:32 -07:00
@@ -995,6 +995,7 @@
 	if ((sch->lpm & (sch->lpm - 1)) != 0)
 		sch->schib.pmcw.mp = 1;
 	sch->schib.pmcw.intparm = (__u32)(unsigned long)sch;
+	/* We should also udate ssd info, but this has to wait. */
 	ccw_device_start_id(cdev, 0);
 	spin_unlock_irqrestore(&sch->lock, flags);
 }
diff -Nru a/drivers/s390/cio/device_id.c b/drivers/s390/cio/device_id.c
--- a/drivers/s390/cio/device_id.c	2004-10-18 14:55:46 -07:00
+++ b/drivers/s390/cio/device_id.c	2004-10-18 14:55:46 -07:00
@@ -303,10 +303,10 @@
 
 	sch = to_subchannel(cdev->dev.parent);
 	irb = (struct irb *) __LC_IRB;
-	/* Retry sense id for cc=1. */
+	/* Retry sense id, if needed. */
 	if (irb->scsw.stctl ==
 	    (SCSW_STCTL_STATUS_PEND | SCSW_STCTL_ALERT_STATUS)) {
-		if (irb->scsw.cc == 1) {
+		if ((irb->scsw.cc == 1) || !irb->scsw.actl) {
 			ret = __ccw_device_sense_id_start(cdev);
 			if (ret && ret != -EBUSY)
 				ccw_device_sense_id_done(cdev, ret);
diff -Nru a/drivers/s390/cio/qdio.c b/drivers/s390/cio/qdio.c
--- a/drivers/s390/cio/qdio.c	2004-10-18 14:56:33 -07:00
+++ b/drivers/s390/cio/qdio.c	2004-10-18 14:56:33 -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/ctctty.c b/drivers/s390/net/ctctty.c
--- a/drivers/s390/net/ctctty.c	2004-10-18 14:56:32 -07:00
+++ b/drivers/s390/net/ctctty.c	2004-10-18 14:56:32 -07:00
@@ -307,10 +307,7 @@
 
 		info->flags &= ~CTC_ASYNC_TX_LINESTAT;
 		if (tty) {
-			if (wake && (tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
-			    tty->ldisc.write_wakeup)
-				(tty->ldisc.write_wakeup)(tty);
-			wake_up_interruptible(&tty->write_wait);
+			tty_wakeup(tty);
 		}
 	}
 	return (skb_queue_empty(&info->tx_queue) ? 0 : 1);
@@ -589,9 +586,7 @@
 	info->lsr |= UART_LSR_TEMT;
 	spin_unlock_irqrestore(&ctc_tty_lock, flags);
 	wake_up_interruptible(&tty->write_wait);
-	if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
-	    tty->ldisc.write_wakeup)
-		(tty->ldisc.write_wakeup) (tty);
+	tty_wakeup(tty);
 ex:
 	DBF_TEXT_(trace, 2, "ex: %s ", __FUNCTION__);
 	return;
@@ -1066,8 +1061,7 @@
 		skb_queue_purge(&info->tx_queue);
 		info->lsr |= UART_LSR_TEMT;
 	}
-	if (tty->ldisc.flush_buffer)
-		tty->ldisc.flush_buffer(tty);
+	tty_ldisc_flush(tty);
 	info->tty = 0;
 	tty->closing = 0;
 	if (info->blocked_open) {
diff -Nru a/drivers/s390/net/lcs.c b/drivers/s390/net/lcs.c
--- a/drivers/s390/net/lcs.c	2004-10-18 14:55:55 -07:00
+++ b/drivers/s390/net/lcs.c	2004-10-18 14:55:55 -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.92 $	 $Date: 2004/09/03 08:06:11 $
  *
  * 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.92 $"
 
 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,53 @@
 	/* 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 lcs_ipm_list *ipm;
+	unsigned long flags;
+
+	/* Free multicast list. */
+	LCS_DBF_TEXT(3, setup, "clmclist");
+	spin_lock_irqsave(&card->ipm_lock, flags);
+	while (!list_empty(&card->ipm_list)){
+		ipm = list_entry(card->ipm_list.next,
+				 struct lcs_ipm_list, list);
+		list_del(&ipm->list);
+		if (ipm->ipm_state != LCS_IPM_STATE_SET_REQUIRED){
+			spin_unlock_irqrestore(&card->ipm_lock, flags);
+			lcs_send_delipm(card, ipm);
+			spin_lock_irqsave(&card->ipm_lock, flags);
+		}
+		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 +770,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 +822,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 +842,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;
 }
 
 /**
@@ -940,33 +1115,56 @@
 static void
 lcs_fix_multicast_list(struct lcs_card *card)
 {
-	struct list_head *l, *n;
-	struct lcs_ipm_list *ipm;
+	struct list_head failed_list;
+	struct lcs_ipm_list *ipm, *tmp;
+	unsigned long flags;
+	int rc;
 
 	LCS_DBF_TEXT(4,trace, "fixipm");
-	spin_lock(&card->ipm_lock);
-	list_for_each_safe(l, n, &card->ipm_list) {
-		ipm = list_entry(l, struct lcs_ipm_list, list);
+	INIT_LIST_HEAD(&failed_list);
+	spin_lock_irqsave(&card->ipm_lock, flags);
+list_modified:
+	list_for_each_entry_safe(ipm, tmp, &card->ipm_list, list){
 		switch (ipm->ipm_state) {
 		case LCS_IPM_STATE_SET_REQUIRED:
-			if (lcs_send_setipm(card, ipm))
+			/* del from ipm_list so noone else can tamper with
+			 * this entry */
+			list_del_init(&ipm->list);
+			spin_unlock_irqrestore(&card->ipm_lock, flags);
+			rc = lcs_send_setipm(card, ipm);
+			spin_lock_irqsave(&card->ipm_lock, flags);
+			if (rc) {
 				PRINT_INFO("Adding multicast address failed."
 					   "Table possibly full!\n");
-			else
+				/* store ipm in failed list -> will be added
+				 * to ipm_list again, so a retry will be done
+				 * during the next call of this function */
+				list_add_tail(&ipm->list, &failed_list);
+			} else {
 				ipm->ipm_state = LCS_IPM_STATE_ON_CARD;
-			break;
+				/* re-insert into ipm_list */
+				list_add_tail(&ipm->list, &card->ipm_list);
+			}
+			goto list_modified;
 		case LCS_IPM_STATE_DEL_REQUIRED:
-			lcs_send_delipm(card, ipm);
 			list_del(&ipm->list);
+			spin_unlock_irqrestore(&card->ipm_lock, flags);
+			lcs_send_delipm(card, ipm);
+			spin_lock_irqsave(&card->ipm_lock, flags);
 			kfree(ipm);
-			break;
+			goto list_modified;
 		case LCS_IPM_STATE_ON_CARD:
 			break;
 		}
 	}
+	/* re-insert all entries from the failed_list into ipm_list */
+	list_for_each_entry(ipm, &failed_list, list) {
+		list_del_init(&ipm->list);
+		list_add_tail(&ipm->list, &card->ipm_list);
+	}
+	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 +1183,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->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 +1257,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);
-	read_unlock(&in4_dev->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 +1301,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 +1668,7 @@
 	return -EIO;
 }
 
+
 /**
  * LCS Stop card
  */
@@ -1440,6 +1682,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 +1702,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 +1717,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 +1732,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 +1761,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 +1777,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 +1793,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 +1804,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 +1826,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 +2211,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 +2242,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-10-18 14:56:48 -07:00
+++ b/drivers/s390/net/lcs.h	2004-10-18 14:56:48 -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-10-18 14:56:29 -07:00
+++ b/drivers/s390/net/qeth_main.c	2004-10-18 14:56:31 -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.145 $)
  *
  * 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.145 $	 $Date: 2004/10/08 15:08:40 $
  *
  * 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
@@ -73,12 +73,13 @@
 #include <linux/reboot.h>
 #include <asm/qeth.h>
 #include <linux/mii.h>
+#include <linux/rcupdate.h>
 
 #include "qeth.h"
 #include "qeth_mpc.h"
 #include "qeth_fs.h"
 
-#define VERSION_QETH_C "$Revision: 1.130 $"
+#define VERSION_QETH_C "$Revision: 1.145 $"
 static const char *version = "qeth S/390 OSA-Express driver";
 
 /**
@@ -2147,7 +2148,7 @@
 
 	skb->mac.raw = skb->data;
 	skb_pull(skb, ETH_ALEN * 2 + sizeof (short));
-	eth = skb->mac.ethernet;
+	eth = eth_hdr(skb);
 
 	if (*eth->h_dest & 1) {
 		if (memcmp(eth->h_dest, dev->broadcast, ETH_ALEN) == 0)
@@ -3834,6 +3835,7 @@
 				/* return EBUSY because we sent old packet, not
 				 * the current one */
 				rc = -EBUSY;
+				atomic_set(&queue->state, QETH_OUT_Q_UNLOCKED);
 				goto out;
 			}
 		}
@@ -4372,12 +4374,13 @@
 	/* skip 4 bytes (data_len struct member) to get req_len */
 	if (copy_from_user(&req_len, udata + sizeof(int), sizeof(int)))
 		return -EFAULT;
-	ureq = kmalloc(req_len, GFP_KERNEL);
+	ureq = kmalloc(req_len+sizeof(struct qeth_snmp_ureq_hdr), GFP_KERNEL);
 	if (!ureq) {
 		QETH_DBF_TEXT(trace, 2, "snmpnome");
 		return -ENOMEM;
 	}
-	if (copy_from_user(ureq, udata, req_len)){
+	if (copy_from_user(ureq, udata,
+			req_len+sizeof(struct qeth_snmp_ureq_hdr))){
 		kfree(ureq);
 		return -EFAULT;
 	}
@@ -4546,7 +4549,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){
@@ -4733,9 +4737,10 @@
 	QETH_DBF_TEXT(trace, 4, "frvaddr4");
 	if (!card->vlangrp)
 		return;
-	in_dev = in_dev_get(card->vlangrp->vlan_devices[vid]);
+	rcu_read_lock();
+	in_dev = __in_dev_get(card->vlangrp->vlan_devices[vid]);
 	if (!in_dev)
-		return;
+		goto out;
 	for (ifa = in_dev->ifa_list; ifa; ifa = ifa->ifa_next){
 		addr = qeth_get_addr_buffer(QETH_PROT_IPV4);
 		if (addr){
@@ -4746,7 +4751,8 @@
 				kfree(addr);
 		}
 	}
-	in_dev_put(in_dev);
+out:
+	rcu_read_unlock();
 }
 
 static void
@@ -4918,9 +4924,9 @@
 		in_dev = in_dev_get(vg->vlan_devices[i]);
 		if (!in_dev)
 			continue;
-		read_lock(&in_dev->lock);
+		read_lock(&in_dev->mc_list_lock);
 		qeth_add_mc(card,in_dev);
-		read_unlock(&in_dev->lock);
+		read_unlock(&in_dev->mc_list_lock);
 		in_dev_put(in_dev);
 	}
 #endif
@@ -4935,10 +4941,10 @@
 	in4_dev = in_dev_get(card->dev);
 	if (in4_dev == NULL)
 		return;
-	read_lock(&in4_dev->lock);
+	read_lock(&in4_dev->mc_list_lock);
 	qeth_add_mc(card, in4_dev);
 	qeth_add_vlan_mc(card);
-	read_unlock(&in4_dev->lock);
+	read_unlock(&in4_dev->mc_list_lock);
 	in_dev_put(in4_dev);
 }
 
@@ -5739,7 +5745,7 @@
 	QETH_DBF_TEXT(trace,3,"ipaipfrg");
 
 	if (!qeth_is_supported(card, IPA_IP_FRAGMENTATION)) {
-		PRINT_INFO("IP fragmentation not supported on %s\n",
+		PRINT_INFO("Hardware IP fragmentation not supported on %s\n",
 			   card->info.if_name);
 		return  -EOPNOTSUPP;
 	}
@@ -5747,11 +5753,11 @@
 	rc = qeth_send_simple_setassparms(card, IPA_IP_FRAGMENTATION,
 					  IPA_CMD_ASS_START, 0);
 	if (rc) {
-		PRINT_WARN("Could not start IP fragmentation "
+		PRINT_WARN("Could not start Hardware IP fragmentation "
 			   "assist on %s: 0x%x\n",
 			   card->info.if_name, rc);
 	} else
-		PRINT_INFO("IP fragmentation enabled \n");
+		PRINT_INFO("Hardware IP fragmentation enabled \n");
 	return rc;
 }
 
@@ -6706,19 +6712,26 @@
 qeth_arp_constructor(struct neighbour *neigh)
 {
 	struct net_device *dev = neigh->dev;
-	struct in_device *in_dev = in_dev_get(dev);
+	struct in_device *in_dev;
+	struct neigh_parms *parms;
 
-	if (in_dev == NULL)
-		return -EINVAL;
 	if (!qeth_verify_dev(dev)) {
-		in_dev_put(in_dev);
 		return qeth_old_arp_constructor(neigh);
 	}
 
+	rcu_read_lock();
+	in_dev = rcu_dereference(__in_dev_get(dev));
+	if (in_dev == NULL) {
+		rcu_read_unlock();
+		return -EINVAL;
+	}
+
+	parms = in_dev->arp_parms;
+	__neigh_parms_put(neigh->parms);
+	neigh->parms = neigh_parms_clone(parms);
+	rcu_read_unlock();
+
 	neigh->type = inet_addr_type(*(u32 *) neigh->primary_key);
-	if (in_dev->arp_parms)
-		neigh->parms = in_dev->arp_parms;
-	in_dev_put(in_dev);
 	neigh->nud_state = NUD_NOARP;
 	neigh->ops = arp_direct_ops;
 	neigh->output = neigh->ops->queue_xmit;
diff -Nru a/drivers/s390/s390mach.h b/drivers/s390/s390mach.h
--- a/drivers/s390/s390mach.h	2004-10-18 14:56:33 -07:00
+++ b/drivers/s390/s390mach.h	2004-10-18 14:56:33 -07:00
@@ -63,10 +63,6 @@
 #define CRW_ERC_PERRI    0x07 /* perm. error, facility init */
 #define CRW_ERC_PMOD     0x08 /* installed parameters modified */
 
-#define MCHCHK_STATUS_TO_PROCESS    0x00000001
-#define MCHCHK_STATUS_IN_PROGRESS   0x00000002
-#define MCHCHK_STATUS_WAITING       0x00000004
-
 extern __inline__ int stcrw(struct crw *pcrw )
 {
         int ccode;
diff -Nru a/drivers/s390/scsi/zfcp_aux.c b/drivers/s390/scsi/zfcp_aux.c
--- a/drivers/s390/scsi/zfcp_aux.c	2004-10-18 14:57:05 -07:00
+++ b/drivers/s390/scsi/zfcp_aux.c	2004-10-18 14:57:05 -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.129 $"
 
 #include "zfcp_ext.h"
 
@@ -47,11 +47,11 @@
 /* miscellaneous */
 
 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 void zfcp_sg_list_free(struct zfcp_sg_list *);
+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, "
+		 "FC ERP QDIO CIO Config FSF SCSI Other, "
 		 "levels: 0=none 1=normal 2=devel 3=trace");
 
 #ifdef ZFCP_PRINT_FLAGS
@@ -257,24 +257,20 @@
 static void __init
 zfcp_init_device_configure(void)
 {
-	int found = 0;
 	struct zfcp_adapter *adapter;
 	struct zfcp_port *port;
 	struct zfcp_unit *unit;
 
 	down(&zfcp_data.config_sema);
 	read_lock_irq(&zfcp_data.config_lock);
-	list_for_each_entry(adapter, &zfcp_data.adapter_list_head, list)
-		if (strcmp(zfcp_data.init_busid,
-			   zfcp_get_busid_by_adapter(adapter)) == 0) {
-			zfcp_adapter_get(adapter);
-			found = 1;
-			break;
-		}
+	adapter = zfcp_get_adapter_by_busid(zfcp_data.init_busid);
+	if (adapter)
+		zfcp_adapter_get(adapter);
 	read_unlock_irq(&zfcp_data.config_lock);
-	if (!found)
+
+	if (adapter == NULL)
 		goto out_adapter;
-	port = zfcp_port_enqueue(adapter, zfcp_data.init_wwpn, 0);
+	port = zfcp_port_enqueue(adapter, zfcp_data.init_wwpn, 0, 0);
 	if (!port)
 		goto out_port;
 	unit = zfcp_unit_enqueue(port, zfcp_data.init_fcp_lun);
@@ -377,12 +373,13 @@
  *              -ENOMEM     - Insufficient memory
  *              -EFAULT     - User space memory I/O operation fault
  *              -EPERM      - Cannot create or queue FSF request or create SBALs
+ *              -ERESTARTSYS- Received signal (is mapped to EAGAIN by VFS)
  */
 static int
 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 +400,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;
@@ -467,22 +464,17 @@
 		(sense_data.devno >> 16) & 0xFF,
 		(sense_data.devno & 0xFFFF));
 
-	retval = -ENXIO;
 	read_lock_irq(&zfcp_data.config_lock);
-	list_for_each_entry(adapter, &zfcp_data.adapter_list_head, list) {
-		if (strncmp(bus_id, zfcp_get_busid_by_adapter(adapter),
-		    BUS_ID_SIZE) == 0) {
-			zfcp_adapter_get(adapter);
-			retval = 0;
-			break;
-		}
-	}
+	adapter = zfcp_get_adapter_by_busid(bus_id);
+	if (adapter)
+		zfcp_adapter_get(adapter);
 	read_unlock_irq(&zfcp_data.config_lock);
 
 	kfree(bus_id);
 
-	if (retval != 0) {
+	if (adapter == NULL) {
 		ZFCP_LOG_INFO("invalid adapter\n");
+		retval = -ENXIO;
 		goto out;
 	}
 
@@ -520,6 +512,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,
@@ -559,13 +557,16 @@
 }
 
 
-/*
- * function:    zfcp_sg_list_alloc
- *
- * purpose:     Create a scatter-gather list of the specified size
+/**
+ * zfcp_sg_list_alloc - create a scatter-gather list of the specified size
+ * @sg_list: structure describing a scatter gather list
+ * @size: size of scatter-gather list
+ * Return: 0 on success, else -ENOMEM
  *
- * returns:     0       - Scatter gather list is created
- *              -ENOMEM - Insufficient memory (*list_ptr is then set to NULL)
+ * In sg_list->sg a pointer to the created scatter-gather list is returned,
+ * or NULL if we run out of memory. sg_list->count specifies the number of
+ * elements of the scatter-gather list. The maximum size of a single element
+ * in the scatter-gather list is PAGE_SIZE.
  */
 static inline int
 zfcp_sg_list_alloc(struct zfcp_sg_list *sg_list, size_t size)
@@ -573,6 +574,9 @@
 	struct scatterlist *sg;
 	unsigned int i;
 	int retval = 0;
+	void *address;
+
+	BUG_ON(sg_list == NULL);
 
 	sg_list->count = size >> PAGE_SHIFT;
 	if (size & ~PAGE_MASK)
@@ -588,7 +592,8 @@
 	for (i = 0, sg = sg_list->sg; i < sg_list->count; i++, sg++) {
 		sg->length = min(size, PAGE_SIZE);
 		sg->offset = 0;
-		sg->page = alloc_pages(GFP_KERNEL, 0);
+		address = (void *) get_zeroed_page(GFP_KERNEL);
+		zfcp_address_to_sg(address, sg);
 		if (sg->page == NULL) {
 			sg_list->count = i;
 			zfcp_sg_list_free(sg_list);
@@ -603,41 +608,61 @@
 }
 
 
-/*
- * function:    zfcp_sg_list_free
- *
- * purpose:     Destroy a scatter-gather list and release memory
+/**
+ * zfcp_sg_list_free - free memory of a scatter-gather list
+ * @sg_list: structure describing a scatter-gather list
  *
- * returns:     Always 0
+ * Memory for each element in the scatter-gather list is freed.
+ * Finally sg_list->sg is freed itself and sg_list->count is reset.
  */
-static inline int
+static inline void
 zfcp_sg_list_free(struct zfcp_sg_list *sg_list)
 {
 	struct scatterlist *sg;
 	unsigned int i;
-	int retval = 0;
 
 	BUG_ON(sg_list == NULL);
 
 	for (i = 0, sg = sg_list->sg; i < sg_list->count; i++, sg++)
 		__free_pages(sg->page, 0);
 
+	sg_list->count = 0;
 	kfree(sg_list->sg);
+}
 
-	return retval;
+/**
+ * zfcp_sg_size - determine size of a scatter-gather list
+ * @sg: array of (struct scatterlist)
+ * @sg_count: elements in array
+ * Return: size of entire scatter-gather list
+ */
+size_t
+zfcp_sg_size(struct scatterlist *sg, unsigned int sg_count)
+{
+	unsigned int i;
+	struct scatterlist *p;
+	size_t size;
+
+	size = 0;
+	for (i = 0, p = sg; i < sg_count; i++, p++) {
+		BUG_ON(p == NULL);
+		size += p->length;
+	}
+
+	return size;
 }
 
 
-/*
- * function:    zfcp_sg_list_copy_from_user
- *
- * purpose:     Copy data from user space memory to the scatter-gather list
- *
- * returns:     0       - The data has been copied from user
- *              -EFAULT - Memory I/O operation fault
+/**
+ * zfcp_sg_list_copy_from_user -copy data from user space to scatter-gather list
+ * @sg_list: structure describing a scatter-gather list
+ * @user_buffer: pointer to buffer in user space
+ * @size: number of bytes to be copied
+ * Return: 0 on success, -EFAULT if copy_from_user fails.
  */
 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;
@@ -645,10 +670,14 @@
 	void *zfcp_buffer;
 	int retval = 0;
 
+	BUG_ON(sg_list == NULL);
+
+	if (zfcp_sg_size(sg_list->sg, sg_list->count) < size)
+		return -EFAULT;
+
 	for (sg = sg_list->sg; size > 0; sg++) {
 		length = min((unsigned int)size, sg->length);
-		zfcp_buffer = (void*)
-			((page_to_pfn(sg->page) << PAGE_SHIFT) + sg->offset);
+		zfcp_buffer = zfcp_sg_to_address(sg);
 		if (copy_from_user(zfcp_buffer, user_buffer, length)) {
 			retval = -EFAULT;
 			goto out;
@@ -662,16 +691,16 @@
 }
 
 
-/*
- * function:    zfcp_sg_list_copy_to_user
- *
- * purpose:     Copy data from the scatter-gather list to user space memory
- *
- * returns:     0       - The data has been copied to user
- *              -EFAULT - Memory I/O operation fault
+/**
+ * zfcp_sg_list_copy_to_user - copy data from scatter-gather list to user space
+ * @user_buffer: pointer to buffer in user space
+ * @sg_list: structure describing a scatter-gather list
+ * @size: number of bytes to be copied
+ * Return: 0 on success, -EFAULT if copy_to_user fails
  */
 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;
@@ -679,10 +708,14 @@
 	void *zfcp_buffer;
 	int retval = 0;
 
+	BUG_ON(sg_list == NULL);
+
+	if (zfcp_sg_size(sg_list->sg, sg_list->count) < size)
+		return -EFAULT;
+
 	for (sg = sg_list->sg; size > 0; sg++) {
-		length = min((unsigned int)size, sg->length);
-		zfcp_buffer = (void*)
-			((page_to_pfn(sg->page) << PAGE_SHIFT) + sg->offset);
+		length = min((unsigned int) size, sg->length);
+		zfcp_buffer = zfcp_sg_to_address(sg);
 		if (copy_to_user(user_buffer, zfcp_buffer, length)) {
 			retval = -EFAULT;
 			goto out;
@@ -705,13 +738,12 @@
 #define ZFCP_LOG_AREA			ZFCP_LOG_AREA_CONFIG
 
 /**
- * zfcp_get_unit_by_lun - find unit in unit list of port by fcp lun
+ * zfcp_get_unit_by_lun - find unit in unit list of port by FCP LUN
  * @port: pointer to port to search for unit
- * @fcp_lun: lun to search for
- * Traverses list of all units of a port and returns pointer to a unit
- * if lun of a unit matches.
+ * @fcp_lun: FCP LUN to search for
+ * Traverse list of all units of a port and return pointer to a unit
+ * with the given FCP LUN.
  */
-
 struct zfcp_unit *
 zfcp_get_unit_by_lun(struct zfcp_port *port, fcp_lun_t fcp_lun)
 {
@@ -730,13 +762,12 @@
 }
 
 /**
- * zfcp_get_port_by_wwpn - find unit in unit list of port by fcp lun
+ * zfcp_get_port_by_wwpn - find port in port list of adapter by wwpn
  * @adapter: pointer to adapter to search for port
  * @wwpn: wwpn to search for
- * Traverses list of all ports of an adapter and returns a pointer to a port
- * if wwpn of a port matches.
+ * Traverse list of all ports of an adapter and return pointer to a port
+ * with the given wwpn.
  */
-
 struct zfcp_port *
 zfcp_get_port_by_wwpn(struct zfcp_adapter *adapter, wwn_t wwpn)
 {
@@ -745,6 +776,30 @@
 
 	list_for_each_entry(port, &adapter->port_list_head, list) {
 		if ((port->wwpn == wwpn) &&
+		    !(atomic_read(&port->status) &
+		      (ZFCP_STATUS_PORT_NO_WWPN | ZFCP_STATUS_COMMON_REMOVE))) {
+			found = 1;
+			break;
+		}
+	}
+	return found ? port : NULL;
+}
+
+/**
+ * zfcp_get_port_by_did - find port in port list of adapter by d_id
+ * @adapter: pointer to adapter to search for port
+ * @d_id: d_id to search for
+ * Traverse list of all ports of an adapter and return pointer to a port
+ * with the given d_id.
+ */
+struct zfcp_port *
+zfcp_get_port_by_did(struct zfcp_adapter *adapter, u32 d_id)
+{
+	struct zfcp_port *port;
+	int found = 0;
+
+	list_for_each_entry(port, &adapter->port_list_head, list) {
+		if ((port->d_id == d_id) &&
 		    !atomic_test_mask(ZFCP_STATUS_COMMON_REMOVE, &port->status))
 		{
 			found = 1;
@@ -754,14 +809,38 @@
 	return found ? port : NULL;
 }
 
-/*
- * Enqueues a logical unit at the end of the unit list associated with the 
- * specified port. Also sets up some unit internal structures.
+/**
+ * zfcp_get_adapter_by_busid - find adpater in adapter list by bus_id
+ * @bus_id: bus_id to search for
+ * Traverse list of all adapters and return pointer to an adapter
+ * with the given bus_id.
+ */
+struct zfcp_adapter *
+zfcp_get_adapter_by_busid(char *bus_id)
+{
+	struct zfcp_adapter *adapter;
+	int found = 0;
+
+	list_for_each_entry(adapter, &zfcp_data.adapter_list_head, list) {
+		if ((strncmp(bus_id, zfcp_get_busid_by_adapter(adapter),
+			     BUS_ID_SIZE) == 0) &&
+		    !atomic_test_mask(ZFCP_STATUS_COMMON_REMOVE,
+				      &adapter->status)){
+			found = 1;
+			break;
+		}
+	}
+	return found ? adapter : NULL;
+}
+
+/**
+ * zfcp_unit_enqueue - enqueue unit to unit list of a port.
+ * @port: pointer to port where unit is added
+ * @fcp_lun: FCP LUN of unit to be enqueued
+ * Return: pointer to enqueued unit on success, NULL on error
+ * Locks: config_sema must be held to serialize changes to the unit list
  *
- * returns:	pointer to unit with a usecount of 1 if a new unit was
- *              successfully enqueued
- *              NULL otherwise
- * locks:	config_sema must be held to serialise changes to the unit list
+ * Sets up some unit internal structures and creates sysfs entry.
  */
 struct zfcp_unit *
 zfcp_unit_enqueue(struct zfcp_port *port, fcp_lun_t fcp_lun)
@@ -1022,6 +1101,12 @@
 	debug_unregister(adapter->in_els_dbf);
 }
 
+void
+zfcp_dummy_release(struct device *dev)
+{
+	return;
+}
+
 /*
  * Enqueues an adapter at the end of the adapter list in the driver data.
  * All adapter internal structures are set up.
@@ -1113,6 +1198,14 @@
 	if (zfcp_sysfs_adapter_create_files(&ccw_device->dev))
 		goto sysfs_failed;
 
+	adapter->generic_services.parent = &adapter->ccw_device->dev;
+	adapter->generic_services.release = zfcp_dummy_release;
+	snprintf(adapter->generic_services.bus_id, BUS_ID_SIZE,
+		 "generic_services");
+
+	if (device_register(&adapter->generic_services))
+		goto generic_services_failed;
+
 	/* put allocated adapter at list tail */
 	write_lock_irq(&zfcp_data.config_lock);
 	atomic_clear_mask(ZFCP_STATUS_COMMON_REMOVE, &adapter->status);
@@ -1123,6 +1216,8 @@
 
 	goto out;
 
+ generic_services_failed:
+	zfcp_sysfs_adapter_remove_files(&adapter->ccw_device->dev);
  sysfs_failed:
 	dev_set_drvdata(&ccw_device->dev, NULL);
  failed_low_mem_buffers:
@@ -1153,6 +1248,7 @@
 	int retval = 0;
 	unsigned long flags;
 
+	device_unregister(&adapter->generic_services);
 	zfcp_sysfs_adapter_remove_files(&adapter->ccw_device->dev);
 	dev_set_drvdata(&adapter->ccw_device->dev, NULL);
 	/* sanity check: no pending FSF requests */
@@ -1195,15 +1291,22 @@
 	return;
 }
 
-/*
- * Enqueues a remote port to the port list. All port internal structures
- * are set up and the sysfs entry is also generated.
+/**
+ * zfcp_port_enqueue - enqueue port to port list of adapter
+ * @adapter: adapter where remote port is added
+ * @wwpn: WWPN of the remote port to be enqueued
+ * @status: initial status for the port
+ * @d_id: destination id of the remote port to be enqueued
+ * Return: pointer to enqueued port on success, NULL on error
+ * Locks: config_sema must be held to serialize changes to the port list
  *
- * returns:     pointer to port or NULL
- * locks:       config_sema must be held to serialise changes to the port list
+ * All port internal structures are set up and the sysfs entry is generated.
+ * d_id is used to enqueue ports with a well known address like the Directory
+ * Service for nameserver lookup.
  */
 struct zfcp_port *
-zfcp_port_enqueue(struct zfcp_adapter *adapter, wwn_t wwpn, u32 status)
+zfcp_port_enqueue(struct zfcp_adapter *adapter, wwn_t wwpn, u32 status,
+		  u32 d_id)
 {
 	struct zfcp_port *port, *tmp_port;
 	int check_wwpn;
@@ -1243,12 +1346,39 @@
 	atomic_set_mask(status, &port->status);
 
 	/* setup for sysfs registration */
-	if (status & ZFCP_STATUS_PORT_NAMESERVER)
-		snprintf(port->sysfs_device.bus_id, BUS_ID_SIZE, "nameserver");
-	else
+	if (status & ZFCP_STATUS_PORT_WKA) {
+		switch (d_id) {
+		case ZFCP_DID_DIRECTORY_SERVICE:
+			snprintf(port->sysfs_device.bus_id, BUS_ID_SIZE,
+				 "directory");
+			break;
+		case ZFCP_DID_MANAGEMENT_SERVICE:
+			snprintf(port->sysfs_device.bus_id, BUS_ID_SIZE,
+				 "management");
+			break;
+		case ZFCP_DID_KEY_DISTRIBUTION_SERVICE:
+			snprintf(port->sysfs_device.bus_id, BUS_ID_SIZE,
+				 "key_distribution");
+			break;
+		case ZFCP_DID_ALIAS_SERVICE:
+			snprintf(port->sysfs_device.bus_id, BUS_ID_SIZE,
+				 "alias");
+			break;
+		case ZFCP_DID_TIME_SERVICE:
+			snprintf(port->sysfs_device.bus_id, BUS_ID_SIZE,
+				 "time");
+			break;
+		default:
+			kfree(port);
+			return NULL;
+		}
+		port->d_id = d_id;
+		port->sysfs_device.parent = &adapter->generic_services;
+	} else {
 		snprintf(port->sysfs_device.bus_id,
 			 BUS_ID_SIZE, "0x%016llx", wwpn);
 	port->sysfs_device.parent = &adapter->ccw_device->dev;
+	}
 	port->sysfs_device.release = zfcp_sysfs_port_release;
 	dev_set_drvdata(&port->sysfs_device, port);
 
@@ -1287,9 +1417,12 @@
 		list_add_tail(&port->list, &adapter->port_list_head);
 	atomic_clear_mask(ZFCP_STATUS_COMMON_REMOVE, &port->status);
 	atomic_set_mask(ZFCP_STATUS_COMMON_RUNNING, &port->status);
+	if (d_id == ZFCP_DID_DIRECTORY_SERVICE)
+		if (!adapter->nameserver_port)
+			adapter->nameserver_port = port;
+	adapter->ports++;
 	write_unlock_irq(&zfcp_data.config_lock);
 
-	adapter->ports++;
 	zfcp_adapter_get(adapter);
 
 	return port;
@@ -1301,8 +1434,8 @@
 	zfcp_port_wait(port);
 	write_lock_irq(&zfcp_data.config_lock);
 	list_del(&port->list);
-	write_unlock_irq(&zfcp_data.config_lock);
 	port->adapter->ports--;
+	write_unlock_irq(&zfcp_data.config_lock);
 	zfcp_adapter_put(port->adapter);
 	zfcp_sysfs_port_remove_files(&port->sysfs_device,
 				     atomic_read(&port->status));
@@ -1315,17 +1448,14 @@
 {
 	struct zfcp_port *port;
 
-	/* generate port structure */
-	port = zfcp_port_enqueue(adapter, 0, ZFCP_STATUS_PORT_NAMESERVER);
+	port = zfcp_port_enqueue(adapter, 0, ZFCP_STATUS_PORT_WKA,
+				 ZFCP_DID_DIRECTORY_SERVICE);
 	if (!port) {
 		ZFCP_LOG_INFO("error: enqueue of nameserver port for "
 			      "adapter %s failed\n",
 			      zfcp_get_busid_by_adapter(adapter));
 		return -ENXIO;
 	}
-	/* set special D_ID */
-	port->d_id = ZFCP_DID_NAMESERVER;
-	adapter->nameserver_port = port;
 	zfcp_port_put(port);
 
 	return 0;
@@ -1389,7 +1519,7 @@
 		read_lock_irqsave(&zfcp_data.config_lock, flags);
 		list_for_each_entry(port, &adapter->port_list_head, list) {
 			if (atomic_test_mask
-			    (ZFCP_STATUS_PORT_NAMESERVER, &port->status))
+			    (ZFCP_STATUS_PORT_WKA, &port->status))
 				continue;
 			/* Do we know this port? If not skip it. */
 			if (!atomic_test_mask
@@ -1646,15 +1776,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 ((ct->status != 0) || 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;
@@ -1665,7 +1787,7 @@
 				"lookup does not match expected wwpn 0x%016Lx "
 				"for adapter %s\n", ct_iu_req->wwpn, port->wwpn,
 				zfcp_get_busid_by_port(port));
-		goto failed;
+		goto mismatch;
 	}
 
 	/* looks like a valid d_id */
@@ -1675,19 +1797,185 @@
 		       zfcp_get_busid_by_port(port), port->wwpn, port->d_id);
 	goto out;
 
-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));
+ mismatch:
 	ZFCP_LOG_DEBUG("CT IUs do not match:\n");
 	ZFCP_HEX_DUMP(ZFCP_LOG_LEVEL_DEBUG, (char *) ct_iu_req,
 		      sizeof(struct ct_iu_gid_pn_req));
 	ZFCP_HEX_DUMP(ZFCP_LOG_LEVEL_DEBUG, (char *) ct_iu_resp,
 		      sizeof(struct ct_iu_gid_pn_resp));
 
+ 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));
  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-10-18 14:56:32 -07:00
+++ b/drivers/s390/scsi/zfcp_def.h	2004-10-18 14:56:32 -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.91 $"
 
 /*************************** INCLUDES *****************************************/
 
@@ -43,6 +43,7 @@
 #include <linux/major.h>
 #include <linux/blkdev.h>
 #include <linux/delay.h>
+#include <linux/timer.h>
 #include <scsi/scsi.h>
 #include <scsi/scsi_tcq.h>
 #include <scsi/scsi_cmnd.h>
@@ -72,12 +73,22 @@
 /* zfcp version number, it consists of major, minor, and patch-level number */
 #define ZFCP_VERSION		"4.1.3"
 
+/**
+ * zfcp_sg_to_address - determine kernel address from struct scatterlist
+ * @list: struct scatterlist
+ * Return: kernel address
+ */
 static inline void *
 zfcp_sg_to_address(struct scatterlist *list)
 {
 	return (void *) (page_address(list->page) + list->offset);
 }
 
+/**
+ * zfcp_address_to_sg - set up struct scatterlist from kernel address
+ * @address: kernel address
+ * @list: struct scatterlist
+ */
 static inline void
 zfcp_address_to_sg(void *address, struct scatterlist *list)
 {
@@ -146,6 +157,9 @@
 #define ZFCP_EXCHANGE_CONFIG_DATA_RETRIES	6
 #define ZFCP_EXCHANGE_CONFIG_DATA_SLEEP		50
 
+/* timeout value for "default timer" for fsf requests */
+#define ZFCP_FSF_REQUEST_TIMEOUT (60*HZ);
+
 /*************** FIBRE CHANNEL PROTOCOL SPECIFIC DEFINES ********************/
 
 typedef unsigned long long wwn_t;
@@ -158,7 +172,6 @@
 
 /* timeout for name-server lookup (in seconds) */
 #define ZFCP_NS_GID_PN_TIMEOUT		10
-#define ZFCP_NS_GA_NXT_TIMEOUT		120
 
 /* largest SCSI command we can process */
 /* FCP-2 (FCP_CMND IU) allows up to (255-3+16) */
@@ -276,33 +289,17 @@
 #define R_A_TOV				10 /* seconds */
 #define ZFCP_ELS_TIMEOUT		(2 * R_A_TOV)
 
-#define ZFCP_LS_RJT			0x01
-#define ZFCP_LS_ACC			0x02
 #define ZFCP_LS_RTV			0x0E
 #define ZFCP_LS_RLS			0x0F
 #define ZFCP_LS_PDISC			0x50
 #define ZFCP_LS_ADISC			0x52
-#define ZFCP_LS_RSCN			0x61
-#define ZFCP_LS_RNID			0x78
-#define ZFCP_LS_RLIR			0x7A
 #define ZFCP_LS_RTV_E_D_TOV_FLAG	0x04000000
 
-/* LS_ACC Reason Codes */
-#define ZFCP_LS_RJT_INVALID_COMMAND_CODE	0x01
-#define ZFCP_LS_RJT_LOGICAL_ERROR		0x03
-#define ZFCP_LS_RJT_LOGICAL_BUSY		0x05
-#define ZFCP_LS_RJT_PROTOCOL_ERROR		0x07
-#define ZFCP_LS_RJT_UNABLE_TO_PERFORM		0x09
-#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 {
@@ -383,45 +380,10 @@
 	fc_id_t		nport_id;
 } __attribute__ ((packed));
 
-struct zfcp_ls_rnid {
-	u8		code;
-	u8		field[3];
-	u8		node_id_format;
-	u8		reserved[3];
-} __attribute__((packed));
-
-/* common identification data */
-struct zfcp_ls_rnid_common_id {
-	u64		n_port_name;
-	u64		node_name;
-} __attribute__((packed));
-
-/* general topology specific identification data */
-struct zfcp_ls_rnid_general_topology_id {
-	u8		vendor_unique[16];
-	u32		associated_type;
-	u32		physical_port_number;
-	u32		nr_attached_nodes;
-	u8		node_management;
-	u8		ip_version;
-	u16		port_number;
-	u8		ip_address[16];
-	u8		reserved[2];
-	u16		vendor_specific;
-} __attribute__((packed));
-
-struct zfcp_ls_rnid_acc {
-	u8		code;
-	u8		field[3];
-	u8		node_id_format;
-	u8		common_id_length;
-	u8		reserved;
-	u8		specific_id_length;
-	struct zfcp_ls_rnid_common_id
-			common_id;
-	struct zfcp_ls_rnid_general_topology_id
-			specific_id;
-} __attribute__((packed));
+struct zfcp_rc_entry {
+	u8 code;
+	const char *description;
+};
 
 /*
  * FC-GS-2 stuff
@@ -431,9 +393,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
@@ -530,23 +492,29 @@
 	       __LINE__ , ##args);
 
 #define ZFCP_LOG(level, fmt, args...) \
+do { \
 	if (ZFCP_LOG_CHECK(level)) \
-		_ZFCP_LOG(fmt , ##args)
+		_ZFCP_LOG(fmt, ##args); \
+} while (0)
 	
 #if ZFCP_LOG_LEVEL_LIMIT < ZFCP_LOG_LEVEL_NORMAL
 # define ZFCP_LOG_NORMAL(fmt, args...)
 #else
 # define ZFCP_LOG_NORMAL(fmt, args...) \
+do { \
 	if (ZFCP_LOG_CHECK(ZFCP_LOG_LEVEL_NORMAL)) \
-		printk(KERN_ERR ZFCP_NAME": " fmt , ##args);
+		printk(KERN_ERR ZFCP_NAME": " fmt, ##args); \
+} while (0)
 #endif
 
 #if ZFCP_LOG_LEVEL_LIMIT < ZFCP_LOG_LEVEL_INFO
 # define ZFCP_LOG_INFO(fmt, args...)
 #else
 # define ZFCP_LOG_INFO(fmt, args...) \
+do { \
 	if (ZFCP_LOG_CHECK(ZFCP_LOG_LEVEL_INFO)) \
-		printk(KERN_ERR ZFCP_NAME": " fmt , ##args);
+		printk(KERN_ERR ZFCP_NAME": " fmt, ##args); \
+} while (0)
 #endif
 
 #if ZFCP_LOG_LEVEL_LIMIT < ZFCP_LOG_LEVEL_DEBUG
@@ -568,8 +536,10 @@
 #else
 extern u32 flags_dump;
 # define ZFCP_LOG_FLAGS(level, fmt, args...) \
+do { \
 	if (level <= flags_dump) \
-		_ZFCP_LOG(fmt , ##args)
+		_ZFCP_LOG(fmt, ##args); \
+} while (0)
 #endif
 
 /*************** ADAPTER/PORT/UNIT AND FSF_REQ STATUS FLAGS ******************/
@@ -606,7 +576,12 @@
 		 ZFCP_STATUS_ADAPTER_REGISTERED)
 
 
-#define ZFCP_DID_NAMESERVER			0xFFFFFC
+/* FC-PH/FC-GS well-known address identifiers for generic services */
+#define ZFCP_DID_MANAGEMENT_SERVICE		0xFFFFFA
+#define ZFCP_DID_TIME_SERVICE			0xFFFFFB
+#define ZFCP_DID_DIRECTORY_SERVICE		0xFFFFFC
+#define ZFCP_DID_ALIAS_SERVICE			0xFFFFF8
+#define ZFCP_DID_KEY_DISTRIBUTION_SERVICE	0xFFFFF7
 
 /* remote port status */
 #define ZFCP_STATUS_PORT_PHYS_OPEN		0x00000001
@@ -616,7 +591,8 @@
 #define ZFCP_STATUS_PORT_NO_SCSI_ID		0x00000010
 #define ZFCP_STATUS_PORT_INVALID_WWPN		0x00000020
 
-#define ZFCP_STATUS_PORT_NAMESERVER \
+/* for ports with well known addresses */
+#define ZFCP_STATUS_PORT_WKA \
 		(ZFCP_STATUS_PORT_NO_WWPN | \
 		 ZFCP_STATUS_PORT_NO_SCSI_ID)
 
@@ -789,43 +765,29 @@
 	wwn_t wwpn;
 } __attribute__ ((packed));
 
-/* nameserver request CT_IU -- for requests where
- * a port identifier is required */
-struct ct_iu_ga_nxt_req {
-	struct ct_hdr header;
-	fc_id_t d_id;
-} __attribute__ ((packed));
-
 /* FS_ACC IU and data unit for GID_PN nameserver request */
 struct ct_iu_gid_pn_resp {
 	struct ct_hdr header;
 	fc_id_t d_id;
 } __attribute__ ((packed));
 
-/* FS_ACC IU and data unit for GA_NXT nameserver request */
-struct ct_iu_ga_nxt_resp {
-	struct ct_hdr header;
-        u8 port_type;
-        u8 port_id[3];
-        u64 port_wwn;
-        u8 port_symbolic_name_length;
-        u8 port_symbolic_name[255];
-        u64 node_wwn;
-        u8 node_symbolic_name_length;
-        u8 node_symbolic_name[255];
-        u64 initial_process_associator;
-        u8 node_ip[16];
-        u32 cos;
-        u8 fc4_types[32];
-        u8 port_ip[16];
-        u64 fabric_wwn;
-        u8 reserved;
-        u8 hard_address[3];
-} __attribute__ ((packed));
-
 typedef void (*zfcp_send_ct_handler_t)(unsigned long);
 
-/* used to pass parameters to zfcp_send_ct() */
+/**
+ * struct zfcp_send_ct - used to pass parameters to function zfcp_fsf_send_ct
+ * @port: port where the request is sent to
+ * @req: scatter-gather list for request
+ * @resp: scatter-gather list for response
+ * @req_count: number of elements in request scatter-gather list
+ * @resp_count: number of elements in response scatter-gather list
+ * @handler: handler function (called for response to the request)
+ * @handler_data: data passed to handler function
+ * @pool: pointer to memory pool for ct request structure
+ * @timeout: FSF timeout for this request
+ * @timer: timer (e.g. for request initiated by erp)
+ * @completion: completion for synchronization purposes
+ * @status: used to pass error status to calling function
+ */
 struct zfcp_send_ct {
 	struct zfcp_port *port;
 	struct scatterlist *req;
@@ -834,7 +796,7 @@
 	unsigned int resp_count;
 	zfcp_send_ct_handler_t handler;
 	unsigned long handler_data;
-	mempool_t *pool;		/* mempool for ct not for fsf_req */
+	mempool_t *pool;
 	int timeout;
 	struct timer_list *timer;
 	struct completion *completion;
@@ -851,10 +813,22 @@
         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 */
+/**
+ * struct zfcp_send_els - used to pass parameters to function zfcp_fsf_send_els
+ * @port: port where the request is sent to
+ * @req: scatter-gather list for request
+ * @resp: scatter-gather list for response
+ * @req_count: number of elements in request scatter-gather list
+ * @resp_count: number of elements in response scatter-gather list
+ * @handler: handler function (called for response to the request)
+ * @handler_data: data passed to handler function
+ * @timer: timer (e.g. for request initiated by erp)
+ * @completion: completion for synchronization purposes
+ * @ls_code: hex code of ELS command
+ * @status: used to pass error status to calling function
+ */
 struct zfcp_send_els {
 	struct zfcp_port *port;
 	struct scatterlist *req;
@@ -863,6 +837,7 @@
 	unsigned int resp_count;
 	zfcp_send_els_handler_t handler;
 	unsigned long handler_data;
+	struct timer_list *timer;
 	struct completion *completion;
 	int ls_code;
 	int status;
@@ -892,6 +867,7 @@
 	struct zfcp_send_ct *send_ct;
 	struct zfcp_send_els *send_els;
 	struct zfcp_status_read 	  status_read;
+	struct fsf_qtcb_bottom_port *port_data;
 };
 
 struct zfcp_qdio_queue {
@@ -979,6 +955,7 @@
 	rwlock_t                cmd_dbf_lock;
 	struct zfcp_adapter_mempool	pool;      /* Adapter memory pools */
 	struct qdio_initialize  qdio_init_data;    /* for qdio_establish */
+	struct device           generic_services;  /* directory for WKA ports */
 };
 
 /*
@@ -1080,6 +1057,11 @@
 	fcp_lun_t               init_fcp_lun;
 };
 
+/**
+ * struct zfcp_sg_list - struct describing a scatter-gather list
+ * @sg: pointer to array of (struct scatterlist)
+ * @count: number of elements in scatter-gather list
+ */
 struct zfcp_sg_list {
 	struct scatterlist *sg;
 	unsigned int count;
diff -Nru a/drivers/s390/scsi/zfcp_erp.c b/drivers/s390/scsi/zfcp_erp.c
--- a/drivers/s390/scsi/zfcp_erp.c	2004-10-18 14:56:17 -07:00
+++ b/drivers/s390/scsi/zfcp_erp.c	2004-10-18 14:56:17 -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.65 $"
 
 #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);
@@ -126,6 +126,25 @@
 static void zfcp_erp_timeout_handler(unsigned long);
 static inline void zfcp_erp_timeout_init(struct zfcp_erp_action *);
 
+/**
+ * zfcp_fsf_request_timeout_handler - called if a request timed out
+ * @data: pointer to adapter for handler function
+ *
+ * This function needs to be called if requests (ELS, Generic Service,
+ * or SCSI commands) exceed a certain time limit. The assumption is
+ * that after the time limit the adapter get stuck. So we trigger a reopen of
+ * the adapter. This should not be used for error recovery, SCSI abort
+ * commands and SCSI requests from SCSI mid-layer.
+ */
+void
+zfcp_fsf_request_timeout_handler(unsigned long data)
+{
+	struct zfcp_adapter *adapter;
+
+	adapter = (struct zfcp_adapter *) data;
+
+	zfcp_erp_adapter_reopen(adapter, 0);
+}
 
 /*
  * function:	zfcp_fsf_scsi_er_timeout_handler
@@ -324,6 +343,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 +432,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) {
-
-		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;
+	switch (req_code) {
 
-		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;
-		break;
-
-	case ZFCP_LS_ACC:
-		switch (req_code) {
-
-		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_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_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_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_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);
 }
 
 
@@ -735,14 +669,15 @@
 	return retval;
 }
 
-/*
- * function:	
- *
- * purpose:	Wrappper for zfcp_erp_port_reopen_internal
- *              used to ensure the correct locking
- *
- * returns:	0	- initiated action succesfully
- *		<0	- failed to initiate action
+/**
+ * zfcp_erp_port_reopen - initiate reopen of a remote port
+ * @port: port to be reopened
+ * @clear_mask: specifies flags in port status to be cleared
+ * Return: 0 on success, < 0 on error
+ *
+ * This is a wrappper function for zfcp_erp_port_reopen_internal. It ensures
+ * correct locking. An error recovery task is initiated to do the reopen.
+ * To wait for the completion of the reopen zfcp_erp_wait should be used.
  */
 int
 zfcp_erp_port_reopen(struct zfcp_port *port, int clear_mask)
@@ -802,14 +737,15 @@
 	return retval;
 }
 
-/*
- * function:	
- *
- * purpose:	Wrappper for zfcp_erp_unit_reopen_internal
- *              used to ensure the correct locking
- *
- * returns:	0	- initiated action succesfully
- *		<0	- failed to initiate action
+/**
+ * zfcp_erp_unit_reopen - initiate reopen of a unit
+ * @unit: unit to be reopened
+ * @clear_mask: specifies flags in unit status to be cleared
+ * Return: 0 on success, < 0 on error
+ *
+ * This is a wrappper for zfcp_erp_unit_reopen_internal. It ensures correct
+ * locking. An error recovery task is initiated to do the reopen.
+ * To wait for the completion of the reopen zfcp_erp_wait should be used.
  */
 int
 zfcp_erp_unit_reopen(struct zfcp_unit *unit, int clear_mask)
@@ -1987,12 +1923,10 @@
 	return retval;
 }
 
-/*
- * function:	
- *
- * purpose:	
- *
- * returns:
+/**
+ * zfcp_erp_wait - wait for completion of error recovery on an adapter
+ * @adapter: adapter for which to wait for completion of its error recovery
+ * Return: 0
  */
 int
 zfcp_erp_wait(struct zfcp_adapter *adapter)
@@ -2130,7 +2064,7 @@
 	struct zfcp_port *port;
 
 	list_for_each_entry(port, &adapter->port_list_head, list)
-		if (!atomic_test_mask(ZFCP_STATUS_PORT_NAMESERVER, &port->status))
+		if (!atomic_test_mask(ZFCP_STATUS_PORT_WKA, &port->status))
 			zfcp_erp_port_reopen_internal(port, clear_mask);
 
 	return retval;
@@ -2725,7 +2659,7 @@
 {
 	int retval;
 
-	if (atomic_test_mask(ZFCP_STATUS_PORT_NAMESERVER,
+	if (atomic_test_mask(ZFCP_STATUS_PORT_WKA,
 			     &erp_action->port->status))
 		retval = zfcp_erp_port_strategy_open_nameserver(erp_action);
 	else
@@ -2863,10 +2797,10 @@
 
 	case ZFCP_ERP_STEP_PORT_OPENING:
 		if (atomic_test_mask(ZFCP_STATUS_COMMON_OPEN, &port->status)) {
-			ZFCP_LOG_DEBUG("nameserver port is open\n");
+			ZFCP_LOG_DEBUG("WKA port is open\n");
 			retval = ZFCP_ERP_SUCCEEDED;
 		} else {
-			ZFCP_LOG_DEBUG("open failed for nameserver port\n");
+			ZFCP_LOG_DEBUG("open failed for WKA port\n");
 			retval = ZFCP_ERP_FAILED;
 		}
 		/* this is needed anyway (dont care for retval of wakeup) */
diff -Nru a/drivers/s390/scsi/zfcp_ext.h b/drivers/s390/scsi/zfcp_ext.h
--- a/drivers/s390/scsi/zfcp_ext.h	2004-10-18 14:56:20 -07:00
+++ b/drivers/s390/scsi/zfcp_ext.h	2004-10-18 14:56:20 -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.57 $"
 
 #include "zfcp_def.h"
 
@@ -50,15 +50,16 @@
 extern void zfcp_sysfs_unit_release(struct device *);
 
 /**************************** CONFIGURATION  *********************************/
-extern struct zfcp_unit *zfcp_get_unit_by_lun(struct zfcp_port *,
-					      fcp_lun_t fcp_lun);
-extern struct zfcp_port *zfcp_get_port_by_wwpn(struct zfcp_adapter *,
-					       wwn_t wwpn);
+extern struct zfcp_unit *zfcp_get_unit_by_lun(struct zfcp_port *, fcp_lun_t);
+extern struct zfcp_port *zfcp_get_port_by_wwpn(struct zfcp_adapter *, wwn_t);
+extern struct zfcp_port *zfcp_get_port_by_did(struct zfcp_adapter *, u32);
+struct zfcp_adapter *zfcp_get_adapter_by_busid(char *);
 extern struct zfcp_adapter *zfcp_adapter_enqueue(struct ccw_device *);
 extern int    zfcp_adapter_debug_register(struct zfcp_adapter *);
 extern void   zfcp_adapter_dequeue(struct zfcp_adapter *);
 extern void   zfcp_adapter_debug_unregister(struct zfcp_adapter *);
-extern struct zfcp_port *zfcp_port_enqueue(struct zfcp_adapter *, wwn_t, u32);
+extern struct zfcp_port *zfcp_port_enqueue(struct zfcp_adapter *, wwn_t,
+					   u32, u32);
 extern void   zfcp_port_dequeue(struct zfcp_port *);
 extern struct zfcp_unit *zfcp_unit_enqueue(struct zfcp_port *, fcp_lun_t);
 extern void   zfcp_unit_dequeue(struct zfcp_unit *);
@@ -94,8 +95,11 @@
 extern int  zfcp_fsf_close_unit(struct zfcp_erp_action *);
 
 extern int  zfcp_fsf_exchange_config_data(struct zfcp_erp_action *);
+extern int  zfcp_fsf_exchange_port_data(struct zfcp_adapter *,
+					struct fsf_qtcb_bottom_port *);
 extern int  zfcp_fsf_control_file(struct zfcp_adapter *, struct zfcp_fsf_req **,
 				  u32, u32, struct zfcp_sg_list *);
+extern void zfcp_fsf_request_timeout_handler(unsigned long);
 extern void zfcp_fsf_scsi_er_timeout_handler(unsigned long);
 extern int  zfcp_fsf_req_dismiss_all(struct zfcp_adapter *);
 extern int  zfcp_fsf_status_read(struct zfcp_adapter *, int);
@@ -108,7 +112,7 @@
 extern int  zfcp_fsf_send_fcp_command_task(struct zfcp_adapter *,
 					   struct zfcp_unit *,
 					   struct scsi_cmnd *,
-					   int);
+					   struct timer_list*, int);
 extern int  zfcp_fsf_req_complete(struct zfcp_fsf_req *);
 extern void zfcp_fsf_incoming_els(struct zfcp_fsf_req *);
 extern void zfcp_fsf_req_cleanup(struct zfcp_fsf_req *);
@@ -117,9 +121,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 *);
@@ -132,10 +138,10 @@
 extern void zfcp_fsf_start_scsi_er_timer(struct zfcp_adapter *);
 extern fcp_dl_t zfcp_get_fcp_dl(struct fcp_cmnd_iu *);
 
-extern int zfcp_scsi_command_async(struct zfcp_adapter *,struct zfcp_unit *unit,
-				   struct scsi_cmnd *scsi_cmnd);
-extern int zfcp_scsi_command_sync(struct zfcp_unit *unit,
-				  struct scsi_cmnd *scsi_cmnd);
+extern int zfcp_scsi_command_async(struct zfcp_adapter *,struct zfcp_unit *,
+				   struct scsi_cmnd *, struct timer_list *);
+extern int zfcp_scsi_command_sync(struct zfcp_unit *, struct scsi_cmnd *,
+				  struct timer_list *);
 extern struct scsi_transport_template *zfcp_transport_template;
 extern struct fc_function_template zfcp_transport_functions;
 
diff -Nru a/drivers/s390/scsi/zfcp_fsf.c b/drivers/s390/scsi/zfcp_fsf.c
--- a/drivers/s390/scsi/zfcp_fsf.c	2004-10-18 14:56:48 -07:00
+++ b/drivers/s390/scsi/zfcp_fsf.c	2004-10-18 14:56:48 -07:00
@@ -29,11 +29,12 @@
  */
 
 /* 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.65 $"
 
 #include "zfcp_ext.h"
 
 static int zfcp_fsf_exchange_config_data_handler(struct zfcp_fsf_req *);
+static void zfcp_fsf_exchange_port_data_handler(struct zfcp_fsf_req *);
 static int zfcp_fsf_open_port_handler(struct zfcp_fsf_req *);
 static int zfcp_fsf_close_port_handler(struct zfcp_fsf_req *);
 static int zfcp_fsf_close_physical_port_handler(struct zfcp_fsf_req *);
@@ -48,7 +49,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 +80,9 @@
 };
 
 static const char zfcp_act_subtable_type[5][8] = {
-	{"unknown"}, {"OS"}, {"WWPN"}, {"DID"}, {"LUN"}
+	"unknown", "OS", "WWPN", "DID", "LUN"
 };
 
-
 /****************************************************************/
 /*************** FSF related Functions  *************************/
 /****************************************************************/
@@ -684,13 +684,11 @@
 		break;
 	case FSF_SQ_ULP_PROGRAMMING_ERROR:
 		ZFCP_LOG_FLAGS(0, "FSF_SQ_ULP_PROGRAMMING_ERROR\n");
-		ZFCP_LOG_NORMAL("bug: An illegal amount of data was attempted "
-				"to be sent to the adapter %s "
-				"Stopping all operations on this adapter. ",
+		ZFCP_LOG_NORMAL("error: not enough SBALs for data transfer "
+				"(adapter %s)\n",
 				zfcp_get_busid_by_adapter(fsf_req->adapter));
 		debug_text_exception(fsf_req->adapter->erp_dbf, 0,
 				     "fsf_sq_ulp_err");
-		zfcp_erp_adapter_shutdown(fsf_req->adapter, 0);
 		fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR;
 		break;
 	case FSF_SQ_INVOKE_LINK_TEST_PROCEDURE:
@@ -785,6 +783,11 @@
 		zfcp_fsf_exchange_config_data_handler(fsf_req);
 		break;
 
+	case FSF_QTCB_EXCHANGE_PORT_DATA :
+		ZFCP_LOG_FLAGS(2, "FSF_QTCB_EXCHANGE_PORT_DATA\n");
+		zfcp_fsf_exchange_port_data_handler(fsf_req);
+		break;
+
 	case FSF_QTCB_SEND_ELS :
 		ZFCP_LOG_FLAGS(2, "FSF_QTCB_SEND_ELS\n");
 		zfcp_fsf_send_els_handler(fsf_req);
@@ -1624,26 +1627,6 @@
 		fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR;
 		break;
 
-	case FSF_REQUEST_BUF_NOT_VALID :
-		ZFCP_LOG_FLAGS(2, "FSF_REQUEST_BUF_NOT_VALID\n");
-		ZFCP_LOG_NORMAL("error: The port 0x%016Lx on adapter %s has "
-				"rejected a generic services command "
-				"due to invalid request buffer.\n",
-				port->wwpn, zfcp_get_busid_by_port(port));
-		debug_text_event(adapter->erp_dbf, 1, "fsf_s_reqiv");
-		fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR;
-		break;
-
-	case FSF_RESPONSE_BUF_NOT_VALID :
-		ZFCP_LOG_FLAGS(2, "FSF_RESPONSE_BUF_NOT_VALID\n");
-		ZFCP_LOG_NORMAL("error: The port 0x%016Lx on adapter %s has "
-				"rejected a generic services command "
-				"due to invalid response buffer.\n",
-				port->wwpn, zfcp_get_busid_by_port(port));
-		debug_text_event(adapter->erp_dbf, 1, "fsf_s_resiv");
-		fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR;
-		break;
-
         case FSF_PORT_BOXED :
 		ZFCP_LOG_FLAGS(2, "FSF_PORT_BOXED\n");
 		ZFCP_LOG_INFO("The remote port 0x%016Lx on adapter %s "
@@ -1665,9 +1648,10 @@
 	}
 
 skip_fsfstatus:
-	if (send_ct->handler != NULL) {
+	send_ct->status = retval;
+
+	if (send_ct->handler != NULL)
 		send_ct->handler(send_ct->handler_data);
-        }
 
 	return retval;
 }
@@ -1769,7 +1753,7 @@
 	sbale = zfcp_qdio_sbale_req(fsf_req, fsf_req->sbal_curr, 0);
 
 	/* start QDIO request for this FSF request */
-	ret = zfcp_fsf_req_send(fsf_req, NULL);
+	ret = zfcp_fsf_req_send(fsf_req, els->timer);
 	if (ret) {
 		ZFCP_LOG_DEBUG("error: initiation of ELS request failed "
 			       "(adapter %s, port 0x%016Lx)\n",
@@ -1863,6 +1847,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");
@@ -1921,15 +1909,6 @@
 			bottom->resp_buf_length);
 		break;
 
-	case FSF_UNKNOWN_COMMAND:
-		ZFCP_LOG_FLAGS(2, "FSF_UNKNOWN_COMMAND\n");
-		ZFCP_LOG_INFO(
-			"FSF command 0x%x is not supported by FCP adapter "
-			"(adapter: %s)\n", fsf_req->fsf_command,
-			zfcp_get_busid_by_port(port));
-		fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR;
-		break;
-
 	case FSF_ACCESS_DENIED:
 		ZFCP_LOG_FLAGS(2, "FSF_ACCESS_DENIED\n");
 		ZFCP_LOG_NORMAL("Access denied, cannot send ELS "
@@ -1971,8 +1950,6 @@
 	if (send_els->handler != 0)
 		send_els->handler(send_els->handler_data);
 
-	kfree(send_els);
-
 	return retval;
 }
 
@@ -2219,6 +2196,111 @@
 	return 0;
 }
 
+/**
+ * zfcp_fsf_exchange_port_data - request information about local port
+ * @adapter: for which port data is requested
+ * @data: response to exchange port data request
+ */
+int
+zfcp_fsf_exchange_port_data(struct zfcp_adapter *adapter,
+			    struct fsf_qtcb_bottom_port *data)
+{
+	volatile struct qdio_buffer_element *sbale;
+	int retval = 0;
+	unsigned long lock_flags;
+        struct zfcp_fsf_req *fsf_req;
+	struct timer_list *timer;
+
+        if(!(adapter->supported_features & FSF_FEATURE_HBAAPI_MANAGEMENT)){
+		ZFCP_LOG_INFO("error: exchange port data "
+                              "command not supported by adapter %s\n",
+			      zfcp_get_busid_by_adapter(adapter));
+                return -EOPNOTSUPP;
+        }
+
+	timer = kmalloc(sizeof(struct timer_list), GFP_KERNEL);
+	if (!timer)
+		return -ENOMEM;
+
+	/* setup new FSF request */
+	retval = zfcp_fsf_req_create(adapter, FSF_QTCB_EXCHANGE_PORT_DATA,
+                                     0, 0, &lock_flags, &fsf_req);
+	if (retval < 0) {
+		ZFCP_LOG_INFO("error: Out of resources. Could not create an "
+                              "exchange port data request for"
+                              "the adapter %s.\n",
+			      zfcp_get_busid_by_adapter(adapter));
+		write_unlock_irqrestore(&adapter->request_queue.queue_lock,
+					lock_flags);
+		goto out;
+	}
+
+	sbale = zfcp_qdio_sbale_req(fsf_req, fsf_req->sbal_curr, 0);
+        sbale[0].flags |= SBAL_FLAGS0_TYPE_READ;
+        sbale[1].flags |= SBAL_FLAGS_LAST_ENTRY;
+
+        fsf_req->data.port_data = data;
+
+	init_timer(timer);
+	timer->function = zfcp_fsf_request_timeout_handler;
+	timer->data = (unsigned long) adapter;
+	timer->expires = ZFCP_FSF_REQUEST_TIMEOUT;
+
+	retval = zfcp_fsf_req_send(fsf_req, timer);
+	if (retval) {
+		ZFCP_LOG_INFO("error: Could not send an exchange port data "
+                              "command on the adapter %s\n",
+			      zfcp_get_busid_by_adapter(adapter));
+		zfcp_fsf_req_free(fsf_req);
+		write_unlock_irqrestore(&adapter->request_queue.queue_lock,
+					lock_flags);
+		goto out;
+	}
+
+	ZFCP_LOG_DEBUG("Exchange Port Data request initiated (adapter %s)\n",
+		       zfcp_get_busid_by_adapter(adapter));
+
+	write_unlock_irqrestore(&adapter->request_queue.queue_lock,
+				lock_flags);
+
+	wait_event(fsf_req->completion_wq,
+		   fsf_req->status & ZFCP_STATUS_FSFREQ_COMPLETED);
+	del_timer_sync(timer);
+	zfcp_fsf_req_cleanup(fsf_req);
+ out:
+	kfree(timer);
+	return retval;
+}
+
+
+/**
+ * zfcp_fsf_exchange_port_data_handler - handler for exchange_port_data request
+ * @fsf_req: pointer to struct zfcp_fsf_req
+ */
+static void
+zfcp_fsf_exchange_port_data_handler(struct zfcp_fsf_req *fsf_req)
+{
+	struct fsf_qtcb_bottom_port *bottom;
+	struct fsf_qtcb_bottom_port *data = fsf_req->data.port_data;
+
+	if (fsf_req->status & ZFCP_STATUS_FSFREQ_ERROR)
+		return;
+
+	switch (fsf_req->qtcb->header.fsf_status) {
+        case FSF_GOOD :
+                ZFCP_LOG_FLAGS(2,"FSF_GOOD\n");
+                bottom = &fsf_req->qtcb->bottom.port;
+                memcpy(data, bottom, sizeof(*data));
+                break;
+
+        default:
+		debug_text_event(fsf_req->adapter->erp_dbf, 0, "xchg-port-ng");
+                debug_event(fsf_req->adapter->erp_dbf, 0,
+			    &fsf_req->qtcb->header.fsf_status, sizeof(u32));
+	}
+}
+
+
 /*
  * function:    zfcp_fsf_open_port
  *
@@ -3319,19 +3401,19 @@
 	return retval;
 }
 
-/*
- * function:    zfcp_fsf_send_fcp_command_task
- *
- * purpose:
- *
- * returns:
- *
- * note: we do not employ linked commands (not supported by HBA anyway)
+/**
+ * zfcp_fsf_send_fcp_command_task - initiate an FCP command (for a SCSI command)
+ * @adapter: adapter where scsi command is issued
+ * @unit: unit where command is sent to
+ * @scsi_cmnd: scsi command to be sent
+ * @timer: timer to be started when request is initiated
+ * @req_flags: flags for fsf_request
  */
 int
 zfcp_fsf_send_fcp_command_task(struct zfcp_adapter *adapter,
 			       struct zfcp_unit *unit,
-			       struct scsi_cmnd * scsi_cmnd, int req_flags)
+			       struct scsi_cmnd * scsi_cmnd,
+			       struct timer_list *timer, int req_flags)
 {
 	struct zfcp_fsf_req *fsf_req = NULL;
 	struct fcp_cmnd_iu *fcp_cmnd_iu;
@@ -3486,7 +3568,7 @@
 	 * start QDIO request for this FSF request
 	 *  covered by an SBALE)
 	 */
-	retval = zfcp_fsf_req_send(fsf_req, NULL);
+	retval = zfcp_fsf_req_send(fsf_req, timer);
 	if (unlikely(retval < 0)) {
 		ZFCP_LOG_INFO("error: Could not send FCP command request "
 			      "on adapter %s, port 0x%016Lx, unit 0x%016Lx\n",
@@ -3788,44 +3870,6 @@
 		fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR;
 		break;
 
-		/* FIXME: this should be obsolete, isn' it? */
-	case FSF_INBOUND_DATA_LENGTH_NOT_VALID:
-		ZFCP_LOG_FLAGS(0, "FSF_INBOUND_DATA_LENGTH_NOT_VALID\n");
-		ZFCP_LOG_NORMAL("bug: An invalid inbound data length field "
-				"was found in a command for unit 0x%016Lx "
-				"on port 0x%016Lx on adapter %s.\n",
-				unit->fcp_lun,
-				unit->port->wwpn, zfcp_get_busid_by_unit(unit));
-		/* stop operation for this adapter */
-		debug_text_event(fsf_req->adapter->erp_dbf, 0,
-				 "fsf_s_in_dl_nv");
-		zfcp_erp_adapter_shutdown(unit->port->adapter, 0);
-		zfcp_cmd_dbf_event_fsf("idleninv",
-				       fsf_req,
-				       &header->fsf_status_qual,
-				       sizeof (union fsf_status_qual));
-		fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR;
-		break;
-
-		/* FIXME: this should be obsolete, isn' it? */
-	case FSF_OUTBOUND_DATA_LENGTH_NOT_VALID:
-		ZFCP_LOG_FLAGS(0, "FSF_OUTBOUND_DATA_LENGTH_NOT_VALID\n");
-		ZFCP_LOG_NORMAL("bug: An invalid outbound data length field "
-				"was found in a command unit 0x%016Lx on port "
-				"0x%016Lx on adapter %s\n",
-				unit->fcp_lun,
-				unit->port->wwpn,
-				zfcp_get_busid_by_unit(unit));
-		/* stop operation for this adapter */
-		debug_text_event(fsf_req->adapter->erp_dbf, 0,
-				 "fsf_s_out_dl_nv");
-		zfcp_erp_adapter_shutdown(unit->port->adapter, 0);
-		zfcp_cmd_dbf_event_fsf("odleninv", fsf_req,
-				       &header->fsf_status_qual,
-				       sizeof (union fsf_status_qual));
-		fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR;
-		break;
-
 	case FSF_CMND_LENGTH_NOT_VALID:
 		ZFCP_LOG_FLAGS(0, "FSF_CMND_LENGTH_NOT_VALID\n");
 		ZFCP_LOG_NORMAL
@@ -4157,87 +4201,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);
@@ -4585,16 +4548,6 @@
 		retval = -EIO;
 		break;
 
-	case FSF_UNKNOWN_COMMAND:
-		ZFCP_LOG_FLAGS(2, "FSF_UNKNOWN_COMMAND\n");
-		ZFCP_LOG_NORMAL(
-			"FSF command 0x%x is not supported by the adapter %s\n",
-			fsf_req->fsf_command,
-			zfcp_get_busid_by_adapter(adapter));
-		fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR;
-		retval = -EINVAL;
-		break;
-
 	case FSF_UNKNOWN_OP_SUBTYPE:
 		ZFCP_LOG_FLAGS(2, "FSF_UNKNOWN_OP_SUBTYPE\n");
 		ZFCP_LOG_NORMAL(
@@ -4682,8 +4635,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))
@@ -4712,30 +4665,25 @@
  * zfcp_fsf_req_sbal_get - try to get one SBAL in the request queue
  * @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
+ * @lock_flags: lock_flags if queue_lock is taken
+ * 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-10-18 14:56:50 -07:00
+++ b/drivers/s390/scsi/zfcp_fsf.h	2004-10-18 14:56:50 -07:00
@@ -84,19 +84,12 @@
 #define FSF_SERVICE_CLASS_NOT_SUPPORTED		0x00000006
 #define FSF_FCPLUN_NOT_VALID			0x00000009
 #define FSF_ACCESS_DENIED			0x00000010
-#define FSF_ACCESS_TYPE_NOT_VALID		0x00000011
 #define FSF_LUN_SHARING_VIOLATION               0x00000012
-#define FSF_COMMAND_ABORTED_ULP			0x00000020
-#define FSF_COMMAND_ABORTED_ADAPTER		0x00000021
 #define FSF_FCP_COMMAND_DOES_NOT_EXIST		0x00000022
 #define FSF_DIRECTION_INDICATOR_NOT_VALID	0x00000030
-#define FSF_INBOUND_DATA_LENGTH_NOT_VALID	0x00000031 /* FIX: obsolete? */
-#define FSF_OUTBOUND_DATA_LENGTH_NOT_VALID	0x00000032 /* FIX: obsolete? */
 #define FSF_CMND_LENGTH_NOT_VALID		0x00000033
 #define FSF_MAXIMUM_NUMBER_OF_PORTS_EXCEEDED	0x00000040
 #define FSF_MAXIMUM_NUMBER_OF_LUNS_EXCEEDED	0x00000041
-#define FSF_REQUEST_BUF_NOT_VALID		0x00000042
-#define FSF_RESPONSE_BUF_NOT_VALID		0x00000043
 #define FSF_ELS_COMMAND_REJECTED		0x00000050
 #define FSF_GENERIC_COMMAND_REJECTED		0x00000051
 #define FSF_OPERATION_PARTIALLY_SUCCESSFUL	0x00000052
@@ -227,6 +220,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-10-18 14:57:20 -07:00
+++ b/drivers/s390/scsi/zfcp_scsi.c	2004-10-18 14:57:20 -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.68 $"
 
 #include "zfcp_ext.h"
 
@@ -247,15 +247,16 @@
 /**
  * zfcp_scsi_command_async - worker for zfcp_scsi_queuecommand and
  *	zfcp_scsi_command_sync
- * @adapter: adapter for where scsi command is issued
+ * @adapter: adapter where scsi command is issued
  * @unit: unit to which scsi command is sent
  * @scpnt: scsi command to be sent
+ * @timer: timer to be started if request is successfully initiated
  *
  * Note: In scsi_done function must be set in scpnt.
  */
 int
 zfcp_scsi_command_async(struct zfcp_adapter *adapter, struct zfcp_unit *unit,
-			struct scsi_cmnd *scpnt)
+			struct scsi_cmnd *scpnt, struct timer_list *timer)
 {
 	int tmp;
 	int retval;
@@ -291,7 +292,7 @@
 		goto out;
 	}
 
-	tmp = zfcp_fsf_send_fcp_command_task(adapter, unit, scpnt,
+	tmp = zfcp_fsf_send_fcp_command_task(adapter, unit, scpnt, timer,
 					     ZFCP_REQ_AUTO_CLEANUP);
 
 	if (unlikely(tmp < 0)) {
@@ -313,18 +314,28 @@
 
 /**
  * zfcp_scsi_command_sync - send a SCSI command and wait for completion
- * returns 0, errors are indicated by scsi_cmnd->result
+ * @unit: unit where command is sent to
+ * @scpnt: scsi command to be sent
+ * @timer: timer to be started if request is successfully initiated
+ * Return: 0
+ *
+ * Errors are indicated in scpnt->result
  */
 int
-zfcp_scsi_command_sync(struct zfcp_unit *unit, struct scsi_cmnd *scpnt)
+zfcp_scsi_command_sync(struct zfcp_unit *unit, struct scsi_cmnd *scpnt,
+		       struct timer_list *timer)
 {
+	int ret;
 	DECLARE_COMPLETION(wait);
 
 	scpnt->SCp.ptr = (void *) &wait;  /* silent re-use */
-	scpnt->done = zfcp_scsi_command_sync_handler;
-        zfcp_scsi_command_async(unit->port->adapter, unit, scpnt);
+	scpnt->scsi_done = zfcp_scsi_command_sync_handler;
+	ret = zfcp_scsi_command_async(unit->port->adapter, unit, scpnt, timer);
+	if ((ret == 0) && (scpnt->result == 0))
 	wait_for_completion(&wait);
 
+	scpnt->SCp.ptr = NULL;
+
 	return 0;
 }
 
@@ -355,7 +366,7 @@
 	adapter = (struct zfcp_adapter *) scpnt->device->host->hostdata[0];
 	unit = (struct zfcp_unit *) scpnt->device->hostdata;
 
-	return zfcp_scsi_command_async(adapter, unit, scpnt);
+	return zfcp_scsi_command_async(adapter, unit, scpnt, NULL);
 }
 
 /*
@@ -430,7 +441,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-10-18 14:55:54 -07:00
+++ b/drivers/s390/scsi/zfcp_sysfs_adapter.c	2004-10-18 14:55:54 -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.37 $"
 
 #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
@@ -127,7 +106,7 @@
 	if ((endp + 1) < (buf + count))
 		goto out;
 
-	port = zfcp_port_enqueue(adapter, wwpn, 0);
+	port = zfcp_port_enqueue(adapter, wwpn, 0, 0);
 	if (!port)
 		goto out;
 
@@ -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-10-18 14:56:50 -07:00
+++ b/drivers/s390/scsi/zfcp_sysfs_driver.c	2004-10-18 14:56:50 -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-10-18 14:57:04 -07:00
+++ b/drivers/s390/scsi/zfcp_sysfs_port.c	2004-10-18 14:57:04 -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.44 $"
 
 #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;
 }
 
 /**
@@ -233,29 +235,6 @@
 		   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
  * sysfs attributes that are common for all kind of fc ports.
  */
@@ -300,7 +279,7 @@
 
 	retval = sysfs_create_group(&dev->kobj, &zfcp_port_common_attr_group);
 
-	if ((flags & ZFCP_STATUS_PORT_NAMESERVER) || retval)
+	if ((flags & ZFCP_STATUS_PORT_WKA) || retval)
 		return retval;
 
 	retval = sysfs_create_group(&dev->kobj, &zfcp_port_no_ns_attr_group);
@@ -320,7 +299,7 @@
 zfcp_sysfs_port_remove_files(struct device *dev, u32 flags)
 {
 	sysfs_remove_group(&dev->kobj, &zfcp_port_common_attr_group);
-	if (!(flags & ZFCP_STATUS_PORT_NAMESERVER))
+	if (!(flags & ZFCP_STATUS_PORT_WKA))
 		sysfs_remove_group(&dev->kobj, &zfcp_port_no_ns_attr_group);
 }
 
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-10-18 14:57:19 -07:00
+++ b/drivers/s390/scsi/zfcp_sysfs_unit.c	2004-10-18 14:57:19 -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/sbus/char/aurora.c b/drivers/sbus/char/aurora.c
--- a/drivers/sbus/char/aurora.c	2004-10-18 14:56:13 -07:00
+++ b/drivers/sbus/char/aurora.c	2004-10-18 14:56:13 -07:00
@@ -1531,8 +1531,7 @@
 	aurora_shutdown_port(bp, port);
 	if (tty->driver->flush_buffer)
 		tty->driver->flush_buffer(tty);
-	if (tty->ldisc.flush_buffer)
-		tty->ldisc.flush_buffer(tty);
+	tty_ldisc_flush(tty);
 	tty->closing = 0;
 	port->event = 0;
 	port->tty = 0;
@@ -1743,10 +1742,7 @@
 	port->xmit_cnt = port->xmit_head = port->xmit_tail = 0;
 	restore_flags(flags);
 	
-	wake_up_interruptible(&tty->write_wait);
-	if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
-	    tty->ldisc.write_wakeup)
-		(tty->ldisc.write_wakeup)(tty);
+	tty_wakeup(tty);
 #ifdef AURORA_DEBUG
 	printk("aurora_flush_buffer: end\n");
 #endif
@@ -2223,10 +2219,7 @@
 		return;
 
 	if (test_and_clear_bit(RS_EVENT_WRITE_WAKEUP, &port->event)) {
-		if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
-		    tty->ldisc.write_wakeup)
-			(tty->ldisc.write_wakeup)(tty);
-		wake_up_interruptible(&tty->write_wait);
+		tty_wakeup(tty);
 	}
 #ifdef AURORA_DEBUG
 	printk("do_softint: end\n");
diff -Nru a/drivers/sbus/char/bbc_envctrl.c b/drivers/sbus/char/bbc_envctrl.c
--- a/drivers/sbus/char/bbc_envctrl.c	2004-10-18 14:57:20 -07:00
+++ b/drivers/sbus/char/bbc_envctrl.c	2004-10-18 14:57:20 -07:00
@@ -452,7 +452,7 @@
 	}
 }
 
-#define POLL_INTERVAL	(5 * HZ)
+#define POLL_INTERVAL	(5 * 1000)
 static unsigned long last_warning_jiffies;
 static struct task_struct *kenvctrld_task;
 
@@ -468,8 +468,7 @@
 		struct bbc_cpu_temperature *tp;
 		struct bbc_fan_control *fp;
 
-		current->state = TASK_INTERRUPTIBLE;
-		schedule_timeout(POLL_INTERVAL);
+		msleep_interruptible(POLL_INTERVAL);
 		if (signal_pending(current))
 			break;
 
diff -Nru a/drivers/sbus/char/bbc_i2c.c b/drivers/sbus/char/bbc_i2c.c
--- a/drivers/sbus/char/bbc_i2c.c	2004-10-18 14:56:49 -07:00
+++ b/drivers/sbus/char/bbc_i2c.c	2004-10-18 14:56:49 -07:00
@@ -189,13 +189,13 @@
 	while (limit-- > 0) {
 		u8 val;
 
-		current->state = TASK_INTERRUPTIBLE;
+		set_current_state(TASK_INTERRUPTIBLE);
 		*status = val = readb(bp->i2c_control_regs + 0);
 		if ((val & I2C_PCF_PIN) == 0) {
 			ret = 0;
 			break;
 		}
-		schedule_timeout(HZ/4);
+		msleep_interruptible(250);
 	}
 	remove_wait_queue(&bp->wq, &wait);
 	bp->waiting = 0;
diff -Nru a/drivers/sbus/char/cpwatchdog.c b/drivers/sbus/char/cpwatchdog.c
--- a/drivers/sbus/char/cpwatchdog.c	2004-10-18 14:57:03 -07:00
+++ b/drivers/sbus/char/cpwatchdog.c	2004-10-18 14:57:03 -07:00
@@ -118,40 +118,26 @@
  * UNKNOWN, MAGICAL MYSTERY REGISTER
  *
  */
-struct wd_timer_regblk {
-	volatile __u16	dcntr;		/* down counter		- hw	*/
-	volatile __u16	dcntr_pad;
-	volatile __u16	limit;		/* limit register	- hw	*/
-	volatile __u16	limit_pad;
-	volatile __u8	status;		/* status register	- b		*/
-	volatile __u8	status_pad;
-	volatile __u16	status_pad2;
-	volatile __u32	pad32;		/* yet more padding			*/
-};
-
-struct wd_pld_regblk {
-	volatile __u8	intr_mask;	/* interrupt mask	- b		*/
-	volatile __u8	intr_mask_pad;
-	volatile __u16	intr_mask_pad2;
-	volatile __u8	status;		/* device status	- b		*/
-	volatile __u8	status_pad;
-	volatile __u16	status_pad2;
-};
+#define WD_TIMER_REGSZ	16
+#define WD0_OFF		0
+#define WD1_OFF		(WD_TIMER_REGSZ * 1)
+#define WD2_OFF		(WD_TIMER_REGSZ * 2)
+#define PLD_OFF		(WD_TIMER_REGSZ * 3)
+
+#define WD_DCNTR	0x00
+#define WD_LIMIT	0x04
+#define WD_STATUS	0x08
 
-struct wd_regblk {
-	volatile struct wd_timer_regblk		wd0_regs;
-	volatile struct wd_timer_regblk		wd1_regs;
-	volatile struct wd_timer_regblk		wd2_regs;
-	volatile struct wd_pld_regblk		pld_regs;
-};
+#define PLD_IMASK	(PLD_OFF + 0x00)
+#define PLD_STATUS	(PLD_OFF + 0x04)
 
 /* Individual timer structure 
  */
 struct wd_timer {
 	__u16			timeout;
 	__u8			intr_mask;
-	unsigned char	runstatus;
-	volatile struct wd_timer_regblk* regs;
+	unsigned char		runstatus;
+	void __iomem		*regs;
 };
 
 /* Device structure
@@ -165,7 +151,7 @@
 	unsigned short	opt_timeout;
 	unsigned char	initialized;
 	struct wd_timer	watchdog[WD_NUMDEVS];
-	volatile struct	wd_regblk* regs;
+	void __iomem	*regs;
 };
 
 static struct wd_device wd_dev = { 
@@ -495,12 +481,12 @@
 				i,
 				wd_getstatus(&wd_dev.watchdog[i]));
 	}
-	printk("\tintr_mask  at 0x%lx: 0x%x\n", 
-		(unsigned long)(&wd_dev.regs->pld_regs.intr_mask), 
-		readb(&wd_dev.regs->pld_regs.intr_mask));
-	printk("\tpld_status at 0x%lx: 0x%x\n", 
-		(unsigned long)(&wd_dev.regs->pld_regs.status), 
-		readb(&wd_dev.regs->pld_regs.status));
+	printk("\tintr_mask  at %p: 0x%x\n", 
+		wd_dev.regs + PLD_IMASK,
+		readb(wd_dev.regs + PLD_IMASK));
+	printk("\tpld_status at %p: 0x%x\n", 
+		wd_dev.regs + PLD_STATUS, 
+		readb(wd_dev.regs + PLD_STATUS));
 }
 #endif
 
@@ -513,7 +499,7 @@
  */
 static void wd_toggleintr(struct wd_timer* pTimer, int enable)
 {
-	unsigned char curregs = wd_readb(&wd_dev.regs->pld_regs.intr_mask);
+	unsigned char curregs = wd_readb(wd_dev.regs + PLD_IMASK);
 	unsigned char setregs = 
 		(NULL == pTimer) ? 
 			(WD0_INTR_MASK | WD1_INTR_MASK | WD2_INTR_MASK) : 
@@ -523,7 +509,7 @@
 		(curregs &= ~setregs):
 		(curregs |=  setregs);
 
-	wd_writeb(curregs, &wd_dev.regs->pld_regs.intr_mask);
+	wd_writeb(curregs, wd_dev.regs + PLD_IMASK);
 	return;
 }
 
@@ -534,8 +520,8 @@
  */
 static void wd_pingtimer(struct wd_timer* pTimer)
 {
-	if(wd_readb(&pTimer->regs->status) & WD_S_RUNNING) {
-		wd_readw(&pTimer->regs->dcntr);
+	if (wd_readb(pTimer->regs + WD_STATUS) & WD_S_RUNNING) {
+		wd_readw(pTimer->regs + WD_DCNTR);
 	}
 }
 
@@ -547,7 +533,7 @@
  */
 static void wd_stoptimer(struct wd_timer* pTimer)
 {
-	if(wd_readb(&pTimer->regs->status) & WD_S_RUNNING) {
+	if(wd_readb(pTimer->regs + WD_STATUS) & WD_S_RUNNING) {
 		wd_toggleintr(pTimer, WD_INTR_OFF);
 
 		if(wd_dev.isbaddoggie) {
@@ -574,7 +560,7 @@
 	}
 	pTimer->runstatus &= ~WD_STAT_SVCD;
 
-	wd_writew(pTimer->timeout, &pTimer->regs->limit);
+	wd_writew(pTimer->timeout, pTimer->regs + WD_LIMIT);
 	wd_toggleintr(pTimer, WD_INTR_ON);
 }
 
@@ -584,7 +570,7 @@
 static void wd_resetbrokentimer(struct wd_timer* pTimer)
 {
 	wd_toggleintr(pTimer, WD_INTR_ON);
-	wd_writew(WD_BLIMIT, &pTimer->regs->limit);
+	wd_writew(WD_BLIMIT, pTimer->regs + WD_LIMIT);
 }
 
 /* Timer device initialization helper.
@@ -593,7 +579,7 @@
 static int wd_inittimer(int whichdog)
 {
 	struct miscdevice 				*whichmisc;
-	volatile struct wd_timer_regblk	*whichregs;
+	void __iomem *whichregs;
 	char 							whichident[8];
 	int								whichmask;
 	__u16							whichlimit;
@@ -603,7 +589,7 @@
 		case WD0_ID:
 			whichmisc = &wd0_miscdev;
 			strcpy(whichident, "RIC");
-			whichregs = &wd_dev.regs->wd0_regs;
+			whichregs = wd_dev.regs + WD0_OFF;
 			whichmask = WD0_INTR_MASK;
 			whichlimit= (0 == wd0_timeout) 	? 
 						(wd_dev.opt_timeout): 
@@ -612,7 +598,7 @@
 		case WD1_ID:
 			whichmisc = &wd1_miscdev;
 			strcpy(whichident, "XIR");
-			whichregs = &wd_dev.regs->wd1_regs;
+			whichregs = wd_dev.regs + WD1_OFF;
 			whichmask = WD1_INTR_MASK;
 			whichlimit= (0 == wd1_timeout) 	? 
 						(wd_dev.opt_timeout): 
@@ -621,7 +607,7 @@
 		case WD2_ID:
 			whichmisc = &wd2_miscdev;
 			strcpy(whichident, "POR");
-			whichregs = &wd_dev.regs->wd2_regs;
+			whichregs = wd_dev.regs + WD2_OFF;
 			whichmask = WD2_INTR_MASK;
 			whichlimit= (0 == wd2_timeout) 	? 
 						(wd_dev.opt_timeout): 
@@ -686,8 +672,8 @@
 
 static int wd_getstatus(struct wd_timer* pTimer)
 {
-	unsigned char stat = wd_readb(&pTimer->regs->status);
-	unsigned char intr = wd_readb(&wd_dev.regs->pld_regs.intr_mask);
+	unsigned char stat = wd_readb(pTimer->regs + WD_STATUS);
+	unsigned char intr = wd_readb(wd_dev.regs + PLD_IMASK);
 	unsigned char ret  = WD_STOPPED;
 
 	/* determine STOPPED */
@@ -805,7 +791,7 @@
 	 * also now eventually trip. 
 	 */
 	for(id = WD0_ID; id < WD_NUMDEVS; ++id) {
-		if(WD_S_RUNNING == wd_readb(&wd_dev.watchdog[id].regs->status)) {
+		if(WD_S_RUNNING == wd_readb(wd_dev.watchdog[id].regs + WD_STATUS)) {
 			if(wd_dev.opt_enable) {
 				printk(KERN_WARNING "%s%i: timer not stopped at release\n",
 					WD_OBPNAME, id);
@@ -818,7 +804,7 @@
 							"%s%i: defect workaround disabled at release, "\
 							"timer expires in ~%01i sec\n",
 							WD_OBPNAME, id, 
-							wd_readw(&wd_dev.watchdog[id].regs->limit) / 10);
+							wd_readw(wd_dev.watchdog[id].regs + WD_LIMIT) / 10);
 				}
 			}
 		}
diff -Nru a/drivers/sbus/char/display7seg.c b/drivers/sbus/char/display7seg.c
--- a/drivers/sbus/char/display7seg.c	2004-10-18 14:56:49 -07:00
+++ b/drivers/sbus/char/display7seg.c	2004-10-18 14:56:49 -07:00
@@ -70,7 +70,7 @@
  * FLIP		- Inverts display for upside-down mounted board
  * bits 0-4	- 7-segment display contents
  */
-volatile u8* d7s_regs = NULL;
+static void __iomem* d7s_regs;
 
 static inline void d7s_free(void)
 {
diff -Nru a/drivers/sbus/char/envctrl.c b/drivers/sbus/char/envctrl.c
--- a/drivers/sbus/char/envctrl.c	2004-10-18 14:56:13 -07:00
+++ b/drivers/sbus/char/envctrl.c	2004-10-18 14:56:13 -07:00
@@ -130,10 +130,8 @@
  */
 #define ENVCTRL_CPCI_IGNORED_NODE		0x70
 
-struct pcf8584_reg {
-	 unsigned char data;
-	 unsigned char csr;
-};
+#define PCF8584_DATA	0x00
+#define PCF8584_CSR	0x01
 
 /* Each child device can be monitored by up to PCF8584_MAX_CHANNELS.
  * Property of a port or channel as defined by the firmware.
@@ -175,7 +173,7 @@
 	char mon_type[PCF8584_MAX_CHANNELS];
 };
 
-volatile static struct pcf8584_reg *i2c = NULL;
+static void __iomem *i2c;
 static struct i2c_child_t i2c_childlist[ENVCTRL_MAX_CPU*2];
 static unsigned char chnls_mask[] = { 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80 };
 static unsigned int warning_temperature = 0;
@@ -185,22 +183,6 @@
 /* Forward declarations. */
 static struct i2c_child_t *envctrl_get_i2c_child(unsigned char);
 
-/* Function description: Read a byte from an i2c controller register.
- * Return: A byte from the passed in address.
- */
-static inline unsigned char envctrl_readb(volatile unsigned char *p)
-{
-	return readb(p);
-}
-
-/* Function description: Write a byte to an i2c controller register.
- * Return: Nothing.
- */
-static inline void envctrl_writeb(unsigned char val, volatile unsigned char *p)
-{
-	writeb(val, p);
-}
-
 /* Function Description: Test the PIN bit (Pending Interrupt Not) 
  * 			 to test when serial transmission is completed .
  * Return : None.
@@ -210,7 +192,7 @@
 	int limit = 1000000;
 
 	while (--limit > 0) {
-		if (!(envctrl_readb(&i2c->csr) & STATUS_PIN)) 
+		if (!(readb(i2c + PCF8584_CSR) & STATUS_PIN)) 
 			break;
 		udelay(1);
 	} 
@@ -228,7 +210,7 @@
 
 	while (--limit > 0) {
 		/* Busy bit 0 means busy. */
-		if (envctrl_readb(&i2c->csr) & STATUS_BB)
+		if (readb(i2c + PCF8584_CSR) & STATUS_BB)
 			break;
 		udelay(1);
 	} 
@@ -245,20 +227,20 @@
 	envctrl_i2c_test_bb();
 
 	/* Load address. */
-	envctrl_writeb(addr + 1, &i2c->data);
+	writeb(addr + 1, i2c + PCF8584_DATA);
 
 	envctrl_i2c_test_bb();
 
-	envctrl_writeb(OBD_SEND_START, &i2c->csr);
+	writeb(OBD_SEND_START, i2c + PCF8584_CSR);
 
 	/* Wait for PIN. */
 	envtrl_i2c_test_pin();
 
 	/* CSR 0 means acknowledged. */
-	if (!(envctrl_readb(&i2c->csr) & STATUS_LRB)) {
-		return envctrl_readb(&i2c->data);
+	if (!(readb(i2c + PCF8584_CSR) & STATUS_LRB)) {
+		return readb(i2c + PCF8584_DATA);
 	} else {
-		envctrl_writeb(OBD_SEND_STOP, &i2c->csr);
+		writeb(OBD_SEND_STOP, i2c + PCF8584_CSR);
 		return 0;
 	}
 }
@@ -269,10 +251,10 @@
 static void envctrl_i2c_write_addr(unsigned char addr)
 {
 	envctrl_i2c_test_bb();
-	envctrl_writeb(addr, &i2c->data);
+	writeb(addr, i2c + PCF8584_DATA);
 
 	/* Generate Start condition. */
-	envctrl_writeb(OBD_SEND_START, &i2c->csr);
+	writeb(OBD_SEND_START, i2c + PCF8584_CSR);
 }
 
 /* Function Description: Read 1 byte of data from addr 
@@ -282,8 +264,8 @@
 static unsigned char envctrl_i2c_read_data(void)
 {
 	envtrl_i2c_test_pin();
-	envctrl_writeb(CONTROL_ES0, &i2c->csr);  /* Send neg ack. */
-	return envctrl_readb(&i2c->data);
+	writeb(CONTROL_ES0, i2c + PCF8584_CSR);  /* Send neg ack. */
+	return readb(i2c + PCF8584_DATA);
 }
 
 /* Function Description: Instruct the device which port to read data from.  
@@ -292,7 +274,7 @@
 static void envctrl_i2c_write_data(unsigned char port)
 {
 	envtrl_i2c_test_pin();
-	envctrl_writeb(port, &i2c->data);
+	writeb(port, i2c + PCF8584_DATA);
 }
 
 /* Function Description: Generate Stop condition after last byte is sent.
@@ -301,7 +283,7 @@
 static void envctrl_i2c_stop(void)
 {
 	envtrl_i2c_test_pin();
-	envctrl_writeb(OBD_SEND_STOP, &i2c->csr);
+	writeb(OBD_SEND_STOP, i2c + PCF8584_CSR);
 }
 
 /* Function Description: Read adc device.
@@ -323,7 +305,7 @@
 	envctrl_i2c_read_data();
 	envctrl_i2c_stop();
 
-	return envctrl_readb(&i2c->data);
+	return readb(i2c + PCF8584_DATA);
 }
 
 /* Function Description: Read gpio device.
@@ -1084,8 +1066,7 @@
 	for_each_ebus(ebus) {
 		for_each_ebusdev(edev, ebus) {
 			if (!strcmp(edev->prom_name, "i2c")) {
-				i2c = ioremap(	edev->resource[0].start, 
-								sizeof(struct pcf8584_reg));
+				i2c = ioremap(edev->resource[0].start, 0x2);
 				for_each_edevchild(edev, edev_child) {
 					if (!strcmp("gpio", edev_child->prom_name)) {
 						i2c_childlist[i].i2ctype = I2C_GPIO;
@@ -1108,15 +1089,15 @@
 	}
 
 	/* Set device address. */
-	envctrl_writeb(CONTROL_PIN, &i2c->csr);
-	envctrl_writeb(PCF8584_ADDRESS, &i2c->data);
+	writeb(CONTROL_PIN, i2c + PCF8584_CSR);
+	writeb(PCF8584_ADDRESS, i2c + PCF8584_DATA);
 
 	/* Set system clock and SCL frequencies. */ 
-	envctrl_writeb(CONTROL_PIN | CONTROL_ES1, &i2c->csr);
-	envctrl_writeb(CLK_4_43 | BUS_CLK_90, &i2c->data);
+	writeb(CONTROL_PIN | CONTROL_ES1, i2c + PCF8584_CSR);
+	writeb(CLK_4_43 | BUS_CLK_90, i2c + PCF8584_DATA);
 
 	/* Enable serial interface. */
-	envctrl_writeb(CONTROL_PIN | CONTROL_ES0 | CONTROL_ACK, &i2c->csr);
+	writeb(CONTROL_PIN | CONTROL_ES0 | CONTROL_ACK, i2c + PCF8584_CSR);
 	udelay(200);
 
 	/* Register the device as a minor miscellaneous device. */
diff -Nru a/drivers/sbus/char/flash.c b/drivers/sbus/char/flash.c
--- a/drivers/sbus/char/flash.c	2004-10-18 14:56:32 -07:00
+++ b/drivers/sbus/char/flash.c	2004-10-18 14:56:32 -07:00
@@ -22,6 +22,7 @@
 #include <asm/io.h>
 #include <asm/sbus.h>
 #include <asm/ebus.h>
+#include <asm/upa.h>
 
 static spinlock_t flash_lock = SPIN_LOCK_UNLOCKED;
 static struct {
@@ -115,7 +116,7 @@
 		count = flash.read_size - p;
 
 	for (i = 0; i < count; i++) {
-		u8 data = readb(flash.read_base + p + i);
+		u8 data = upa_readb(flash.read_base + p + i);
 		if (put_user(data, buf))
 			return -EFAULT;
 		buf++;
diff -Nru a/drivers/sbus/dvma.c b/drivers/sbus/dvma.c
--- a/drivers/sbus/dvma.c	2004-10-18 14:57:03 -07:00
+++ b/drivers/sbus/dvma.c	2004-10-18 14:57:03 -07:00
@@ -17,14 +17,6 @@
 
 struct sbus_dma *dma_chain;
 
-/* Print out the current values in the DMA control registers */
-extern __inline__ void dump_dma_regs(unsigned long dregs)
-{
-	printk("DMA CONTROL<%08x> ADDR<%08x> CNT<%08x> TEST<%08x>\n",
-	       sbus_readl(dregs + DMA_CSR), sbus_readl(dregs + DMA_ADDR),
-	       sbus_readl(dregs + DMA_COUNT), sbus_readl(dregs + DMA_TEST));
-}
-
 void __init init_one_dvma(struct sbus_dma *dma, int num_dma)
 {
 	printk("dma%d: ", num_dma);
@@ -64,9 +56,6 @@
 		break;
 	}
 	printk("\n");
-#if 0 /* Clutters up the screen */
-	dump_dma_regs(dma->regs);
-#endif
 }
 
 /* Probe this SBus DMA module(s) */
diff -Nru a/drivers/scsi/3w-xxxx.c b/drivers/scsi/3w-xxxx.c
--- a/drivers/scsi/3w-xxxx.c	2004-10-18 14:57:04 -07:00
+++ b/drivers/scsi/3w-xxxx.c	2004-10-18 14:57:04 -07:00
@@ -551,7 +551,7 @@
 	/* Now post the command packet */
 	if ((status_reg_value & TW_STATUS_COMMAND_QUEUE_FULL) == 0) {
 		dprintk(KERN_WARNING "3w-xxxx: tw_aen_read_queue(): Post succeeded.\n");
-		tw_dev->srb[request_id] = 0; /* Flag internal command */
+		tw_dev->srb[request_id] = NULL; /* Flag internal command */
 		tw_dev->state[request_id] = TW_S_POSTED;
 		outl(command_que_value, command_que_addr);
 	} else {
@@ -718,7 +718,7 @@
 			tw_state_request_start(tw_dev, &request_id);
 
 			/* Flag internal command */
-			tw_dev->srb[request_id] = 0;
+			tw_dev->srb[request_id] = NULL;
 
 			/* Flag chrdev ioctl */
 			tw_dev->chrdev_request_id = request_id;
@@ -2692,7 +2692,7 @@
 	/* Fake like we just shut down, so notify the card that
 	 * we "shut down cleanly".
 	 */
-	tw_halt(0, 0, 0);  // parameters aren't actually used
+	tw_halt(NULL, 0, NULL);  // parameters aren't actually used
 
 	/* Free up the IO region */
 	release_region((tw_dev->tw_pci_dev->resource[0].start), TW_IO_ADDRESS_RANGE);
diff -Nru a/drivers/scsi/BusLogic.c b/drivers/scsi/BusLogic.c
--- a/drivers/scsi/BusLogic.c	2004-10-18 14:57:04 -07:00
+++ b/drivers/scsi/BusLogic.c	2004-10-18 14:57:04 -07:00
@@ -142,11 +142,8 @@
 
 static void BusLogic_AnnounceDriver(struct BusLogic_HostAdapter *HostAdapter)
 {
-  BusLogic_Announce("***** BusLogic SCSI Driver Version "
-		    BusLogic_DriverVersion " of "
-		    BusLogic_DriverDate " *****\n", HostAdapter);
-  BusLogic_Announce("Copyright 1995-1998 by Leonard N. Zubkoff "
-		    "<lnz@dandelion.com>\n", HostAdapter);
+	BusLogic_Announce("***** BusLogic SCSI Driver Version " BusLogic_DriverVersion " of " BusLogic_DriverDate " *****\n", HostAdapter);
+	BusLogic_Announce("Copyright 1995-1998 by Leonard N. Zubkoff " "<lnz@dandelion.com>\n", HostAdapter);
 }
 
 
@@ -157,9 +154,8 @@
 
 static const char *BusLogic_DriverInfo(struct Scsi_Host *Host)
 {
-  struct BusLogic_HostAdapter *HostAdapter =
-    (struct BusLogic_HostAdapter *) Host->hostdata;
-  return HostAdapter->FullModelName;
+	struct BusLogic_HostAdapter *HostAdapter = (struct BusLogic_HostAdapter *) Host->hostdata;
+	return HostAdapter->FullModelName;
 }
 
 
@@ -170,17 +166,14 @@
 
 static void __init BusLogic_RegisterHostAdapter(struct BusLogic_HostAdapter *HostAdapter)
 {
-  HostAdapter->Next = NULL;
-  if (BusLogic_FirstRegisteredHostAdapter == NULL)
-    {
-      BusLogic_FirstRegisteredHostAdapter = HostAdapter;
-      BusLogic_LastRegisteredHostAdapter = HostAdapter;
-    }
-  else
-    {
-      BusLogic_LastRegisteredHostAdapter->Next = HostAdapter;
-      BusLogic_LastRegisteredHostAdapter = HostAdapter;
-    }
+	HostAdapter->Next = NULL;
+	if (BusLogic_FirstRegisteredHostAdapter == NULL) {
+		BusLogic_FirstRegisteredHostAdapter = HostAdapter;
+		BusLogic_LastRegisteredHostAdapter = HostAdapter;
+	} else {
+		BusLogic_LastRegisteredHostAdapter->Next = HostAdapter;
+		BusLogic_LastRegisteredHostAdapter = HostAdapter;
+	}
 }
 
 
@@ -191,24 +184,18 @@
 
 static void BusLogic_UnregisterHostAdapter(struct BusLogic_HostAdapter *HostAdapter)
 {
-  if (HostAdapter == BusLogic_FirstRegisteredHostAdapter)
-    {
-      BusLogic_FirstRegisteredHostAdapter =
-	BusLogic_FirstRegisteredHostAdapter->Next;
-      if (HostAdapter == BusLogic_LastRegisteredHostAdapter)
-	BusLogic_LastRegisteredHostAdapter = NULL;
-    }
-  else
-    {
-      struct BusLogic_HostAdapter *PreviousHostAdapter =
-	BusLogic_FirstRegisteredHostAdapter;
-      while (PreviousHostAdapter != NULL &&
-	     PreviousHostAdapter->Next != HostAdapter)
-	PreviousHostAdapter = PreviousHostAdapter->Next;
-      if (PreviousHostAdapter != NULL)
-	PreviousHostAdapter->Next = HostAdapter->Next;
-    }
-  HostAdapter->Next = NULL;
+	if (HostAdapter == BusLogic_FirstRegisteredHostAdapter) {
+		BusLogic_FirstRegisteredHostAdapter = BusLogic_FirstRegisteredHostAdapter->Next;
+		if (HostAdapter == BusLogic_LastRegisteredHostAdapter)
+			BusLogic_LastRegisteredHostAdapter = NULL;
+	} else {
+		struct BusLogic_HostAdapter *PreviousHostAdapter = BusLogic_FirstRegisteredHostAdapter;
+		while (PreviousHostAdapter != NULL && PreviousHostAdapter->Next != HostAdapter)
+			PreviousHostAdapter = PreviousHostAdapter->Next;
+		if (PreviousHostAdapter != NULL)
+			PreviousHostAdapter->Next = HostAdapter->Next;
+	}
+	HostAdapter->Next = NULL;
 }
 
 
@@ -218,33 +205,29 @@
   created CCBs are added to Host Adapter's free list.
 */
 
-static void BusLogic_InitializeCCBs(struct BusLogic_HostAdapter *HostAdapter,
-				    void *BlockPointer, int BlockSize,
-				    dma_addr_t BlockPointerHandle)
-{
-  struct BusLogic_CCB *CCB = (struct BusLogic_CCB *) BlockPointer;
-  unsigned int offset = 0;
-  memset(BlockPointer, 0, BlockSize);
-  CCB->AllocationGroupHead = BlockPointerHandle;
-  CCB->AllocationGroupSize = BlockSize;
-  while ((BlockSize -= sizeof(struct BusLogic_CCB)) >= 0)
-    {
-      CCB->Status = BusLogic_CCB_Free;
-      CCB->HostAdapter = HostAdapter;
-      CCB->DMA_Handle = (u32)BlockPointerHandle + offset;
-      if (BusLogic_FlashPointHostAdapterP(HostAdapter))
-	{
-	  CCB->CallbackFunction = BusLogic_QueueCompletedCCB;
-	  CCB->BaseAddress = HostAdapter->FlashPointInfo.BaseAddress;
-	}
-      CCB->Next = HostAdapter->Free_CCBs;
-      CCB->NextAll = HostAdapter->All_CCBs;
-      HostAdapter->Free_CCBs = CCB;
-      HostAdapter->All_CCBs = CCB;
-      HostAdapter->AllocatedCCBs++;
-      CCB++;
-      offset += sizeof(struct BusLogic_CCB);
-    }
+static void BusLogic_InitializeCCBs(struct BusLogic_HostAdapter *HostAdapter, void *BlockPointer, int BlockSize, dma_addr_t BlockPointerHandle)
+{
+	struct BusLogic_CCB *CCB = (struct BusLogic_CCB *) BlockPointer;
+	unsigned int offset = 0;
+	memset(BlockPointer, 0, BlockSize);
+	CCB->AllocationGroupHead = BlockPointerHandle;
+	CCB->AllocationGroupSize = BlockSize;
+	while ((BlockSize -= sizeof(struct BusLogic_CCB)) >= 0) {
+		CCB->Status = BusLogic_CCB_Free;
+		CCB->HostAdapter = HostAdapter;
+		CCB->DMA_Handle = (u32) BlockPointerHandle + offset;
+		if (BusLogic_FlashPointHostAdapterP(HostAdapter)) {
+			CCB->CallbackFunction = BusLogic_QueueCompletedCCB;
+			CCB->BaseAddress = HostAdapter->FlashPointInfo.BaseAddress;
+		}
+		CCB->Next = HostAdapter->Free_CCBs;
+		CCB->NextAll = HostAdapter->All_CCBs;
+		HostAdapter->Free_CCBs = CCB;
+		HostAdapter->All_CCBs = CCB;
+		HostAdapter->AllocatedCCBs++;
+		CCB++;
+		offset += sizeof(struct BusLogic_CCB);
+	}
 }
 
 
@@ -254,23 +237,18 @@
 
 static boolean __init BusLogic_CreateInitialCCBs(struct BusLogic_HostAdapter *HostAdapter)
 {
-  int BlockSize = BusLogic_CCB_AllocationGroupSize * sizeof(struct BusLogic_CCB);
-  void *BlockPointer;
-  dma_addr_t BlockPointerHandle;
-  while (HostAdapter->AllocatedCCBs < HostAdapter->InitialCCBs)
-    {
-      BlockPointer = pci_alloc_consistent(HostAdapter->PCI_Device, BlockSize,
-					  &BlockPointerHandle);
-      if (BlockPointer == NULL)
-	{
-	  BusLogic_Error("UNABLE TO ALLOCATE CCB GROUP - DETACHING\n",
-			 HostAdapter);
-	  return false;
-	}
-      BusLogic_InitializeCCBs(HostAdapter, BlockPointer, BlockSize,
-			      BlockPointerHandle);
-    }
-  return true;
+	int BlockSize = BusLogic_CCB_AllocationGroupSize * sizeof(struct BusLogic_CCB);
+	void *BlockPointer;
+	dma_addr_t BlockPointerHandle;
+	while (HostAdapter->AllocatedCCBs < HostAdapter->InitialCCBs) {
+		BlockPointer = pci_alloc_consistent(HostAdapter->PCI_Device, BlockSize, &BlockPointerHandle);
+		if (BlockPointer == NULL) {
+			BusLogic_Error("UNABLE TO ALLOCATE CCB GROUP - DETACHING\n", HostAdapter);
+			return false;
+		}
+		BusLogic_InitializeCCBs(HostAdapter, BlockPointer, BlockSize, BlockPointerHandle);
+	}
+	return true;
 }
 
 
@@ -280,25 +258,19 @@
 
 static void BusLogic_DestroyCCBs(struct BusLogic_HostAdapter *HostAdapter)
 {
-  struct BusLogic_CCB *NextCCB = HostAdapter->All_CCBs, *CCB, *Last_CCB = NULL;
-  HostAdapter->All_CCBs = NULL;
-  HostAdapter->Free_CCBs = NULL;
-  while ((CCB = NextCCB) != NULL)
-    {
-      NextCCB = CCB->NextAll;
-      if (CCB->AllocationGroupHead)
-	{
-	  if (Last_CCB)
-	    pci_free_consistent(HostAdapter->PCI_Device,
-				Last_CCB->AllocationGroupSize, Last_CCB,
-			 	Last_CCB->AllocationGroupHead);
-	  Last_CCB = CCB;
-	}
-    }
-  if (Last_CCB)
-    pci_free_consistent(HostAdapter->PCI_Device,
-			Last_CCB->AllocationGroupSize, Last_CCB,
-		 	Last_CCB->AllocationGroupHead);
+	struct BusLogic_CCB *NextCCB = HostAdapter->All_CCBs, *CCB, *Last_CCB = NULL;
+	HostAdapter->All_CCBs = NULL;
+	HostAdapter->Free_CCBs = NULL;
+	while ((CCB = NextCCB) != NULL) {
+		NextCCB = CCB->NextAll;
+		if (CCB->AllocationGroupHead) {
+			if (Last_CCB)
+				pci_free_consistent(HostAdapter->PCI_Device, Last_CCB->AllocationGroupSize, Last_CCB, Last_CCB->AllocationGroupHead);
+			Last_CCB = CCB;
+		}
+	}
+	if (Last_CCB)
+		pci_free_consistent(HostAdapter->PCI_Device, Last_CCB->AllocationGroupSize, Last_CCB, Last_CCB->AllocationGroupHead);
 }
 
 
@@ -309,40 +281,30 @@
   multiple host adapters share the same IRQ Channel.
 */
 
-static void BusLogic_CreateAdditionalCCBs(struct BusLogic_HostAdapter *HostAdapter,
-					  int AdditionalCCBs,
-					  boolean SuccessMessageP)
-{
-  int BlockSize = BusLogic_CCB_AllocationGroupSize * sizeof(struct BusLogic_CCB);
-  int PreviouslyAllocated = HostAdapter->AllocatedCCBs;
-  void *BlockPointer;
-  dma_addr_t BlockPointerHandle;
-  if (AdditionalCCBs <= 0) return;
-  while (HostAdapter->AllocatedCCBs - PreviouslyAllocated < AdditionalCCBs)
-    {
-      BlockPointer = pci_alloc_consistent(HostAdapter->PCI_Device, BlockSize,
-					  &BlockPointerHandle);
-      if (BlockPointer == NULL) break;
-      BusLogic_InitializeCCBs(HostAdapter, BlockPointer, BlockSize,
-			      BlockPointerHandle);
-    }
-  if (HostAdapter->AllocatedCCBs > PreviouslyAllocated)
-    {
-      if (SuccessMessageP)
-	BusLogic_Notice("Allocated %d additional CCBs (total now %d)\n",
-			HostAdapter,
-			HostAdapter->AllocatedCCBs - PreviouslyAllocated,
-			HostAdapter->AllocatedCCBs);
-      return;
-    }
-  BusLogic_Notice("Failed to allocate additional CCBs\n", HostAdapter);
-  if (HostAdapter->DriverQueueDepth >
-      HostAdapter->AllocatedCCBs - HostAdapter->TargetDeviceCount)
-    {
-      HostAdapter->DriverQueueDepth =
-	HostAdapter->AllocatedCCBs - HostAdapter->TargetDeviceCount;
-      HostAdapter->SCSI_Host->can_queue = HostAdapter->DriverQueueDepth;
-    }
+static void BusLogic_CreateAdditionalCCBs(struct BusLogic_HostAdapter *HostAdapter, int AdditionalCCBs, boolean SuccessMessageP)
+{
+	int BlockSize = BusLogic_CCB_AllocationGroupSize * sizeof(struct BusLogic_CCB);
+	int PreviouslyAllocated = HostAdapter->AllocatedCCBs;
+	void *BlockPointer;
+	dma_addr_t BlockPointerHandle;
+	if (AdditionalCCBs <= 0)
+		return;
+	while (HostAdapter->AllocatedCCBs - PreviouslyAllocated < AdditionalCCBs) {
+		BlockPointer = pci_alloc_consistent(HostAdapter->PCI_Device, BlockSize, &BlockPointerHandle);
+		if (BlockPointer == NULL)
+			break;
+		BusLogic_InitializeCCBs(HostAdapter, BlockPointer, BlockSize, BlockPointerHandle);
+	}
+	if (HostAdapter->AllocatedCCBs > PreviouslyAllocated) {
+		if (SuccessMessageP)
+			BusLogic_Notice("Allocated %d additional CCBs (total now %d)\n", HostAdapter, HostAdapter->AllocatedCCBs - PreviouslyAllocated, HostAdapter->AllocatedCCBs);
+		return;
+	}
+	BusLogic_Notice("Failed to allocate additional CCBs\n", HostAdapter);
+	if (HostAdapter->DriverQueueDepth > HostAdapter->AllocatedCCBs - HostAdapter->TargetDeviceCount) {
+		HostAdapter->DriverQueueDepth = HostAdapter->AllocatedCCBs - HostAdapter->TargetDeviceCount;
+		HostAdapter->SCSI_Host->can_queue = HostAdapter->DriverQueueDepth;
+	}
 }
 
 /*
@@ -352,31 +314,27 @@
 */
 
 static struct BusLogic_CCB *BusLogic_AllocateCCB(struct BusLogic_HostAdapter
-					    *HostAdapter)
+						 *HostAdapter)
 {
-  static unsigned long SerialNumber = 0;
-  struct BusLogic_CCB *CCB;
-  CCB = HostAdapter->Free_CCBs;
-  if (CCB != NULL)
-    {
-      CCB->SerialNumber = ++SerialNumber;
-      HostAdapter->Free_CCBs = CCB->Next;
-      CCB->Next = NULL;
-      if (HostAdapter->Free_CCBs == NULL)
-	BusLogic_CreateAdditionalCCBs(HostAdapter,
-				      HostAdapter->IncrementalCCBs,
-				      true);
-      return CCB;
-    }
-  BusLogic_CreateAdditionalCCBs(HostAdapter,
-				HostAdapter->IncrementalCCBs,
-				true);
-  CCB = HostAdapter->Free_CCBs;
-  if (CCB == NULL) return NULL;
-  CCB->SerialNumber = ++SerialNumber;
-  HostAdapter->Free_CCBs = CCB->Next;
-  CCB->Next = NULL;
-  return CCB;
+	static unsigned long SerialNumber = 0;
+	struct BusLogic_CCB *CCB;
+	CCB = HostAdapter->Free_CCBs;
+	if (CCB != NULL) {
+		CCB->SerialNumber = ++SerialNumber;
+		HostAdapter->Free_CCBs = CCB->Next;
+		CCB->Next = NULL;
+		if (HostAdapter->Free_CCBs == NULL)
+			BusLogic_CreateAdditionalCCBs(HostAdapter, HostAdapter->IncrementalCCBs, true);
+		return CCB;
+	}
+	BusLogic_CreateAdditionalCCBs(HostAdapter, HostAdapter->IncrementalCCBs, true);
+	CCB = HostAdapter->Free_CCBs;
+	if (CCB == NULL)
+		return NULL;
+	CCB->SerialNumber = ++SerialNumber;
+	HostAdapter->Free_CCBs = CCB->Next;
+	CCB->Next = NULL;
+	return CCB;
 }
 
 
@@ -388,26 +346,17 @@
 
 static void BusLogic_DeallocateCCB(struct BusLogic_CCB *CCB)
 {
-  struct BusLogic_HostAdapter *HostAdapter = CCB->HostAdapter;
-  if (CCB->Command->use_sg != 0)
-    {
-      pci_unmap_sg(HostAdapter->PCI_Device,
-		   (struct scatterlist *)CCB->Command->request_buffer,
-		   CCB->Command->use_sg,
-		   scsi_to_pci_dma_dir(CCB->Command->sc_data_direction));
-    }
-  else if (CCB->Command->request_bufflen != 0)
-    {
-      pci_unmap_single(HostAdapter->PCI_Device, CCB->DataPointer,
-		       CCB->DataLength,
-		       scsi_to_pci_dma_dir(CCB->Command->sc_data_direction));
-    }
-  pci_unmap_single(HostAdapter->PCI_Device, CCB->SenseDataPointer,
-		   CCB->SenseDataLength, PCI_DMA_FROMDEVICE);
-  CCB->Command = NULL;
-  CCB->Status = BusLogic_CCB_Free;
-  CCB->Next = HostAdapter->Free_CCBs;
-  HostAdapter->Free_CCBs = CCB;
+	struct BusLogic_HostAdapter *HostAdapter = CCB->HostAdapter;
+	if (CCB->Command->use_sg != 0) {
+		pci_unmap_sg(HostAdapter->PCI_Device, (struct scatterlist *) CCB->Command->request_buffer, CCB->Command->use_sg, scsi_to_pci_dma_dir(CCB->Command->sc_data_direction));
+	} else if (CCB->Command->request_bufflen != 0) {
+		pci_unmap_single(HostAdapter->PCI_Device, CCB->DataPointer, CCB->DataLength, scsi_to_pci_dma_dir(CCB->Command->sc_data_direction));
+	}
+	pci_unmap_single(HostAdapter->PCI_Device, CCB->SenseDataPointer, CCB->SenseDataLength, PCI_DMA_FROMDEVICE);
+	CCB->Command = NULL;
+	CCB->Status = BusLogic_CCB_Free;
+	CCB->Next = HostAdapter->Free_CCBs;
+	HostAdapter->Free_CCBs = CCB;
 }
 
 
@@ -429,228 +378,205 @@
   waiting for the Host Adapter Ready bit to be set in the Status Register.
 */
 
-static int BusLogic_Command(struct BusLogic_HostAdapter *HostAdapter,
-			    enum BusLogic_OperationCode OperationCode,
-			    void *ParameterData,
-			    int ParameterLength,
-			    void *ReplyData,
-			    int ReplyLength)
-{
-  unsigned char *ParameterPointer = (unsigned char *) ParameterData;
-  unsigned char *ReplyPointer = (unsigned char *) ReplyData;
-  union BusLogic_StatusRegister StatusRegister;
-  union BusLogic_InterruptRegister InterruptRegister;
-  unsigned long ProcessorFlags = 0;
-  int ReplyBytes = 0, Result;
-  long TimeoutCounter;
-  /*
-    Clear out the Reply Data if provided.
-  */
-  if (ReplyLength > 0)
-    memset(ReplyData, 0, ReplyLength);
-  /*
-    If the IRQ Channel has not yet been acquired, then interrupts must be
-    disabled while issuing host adapter commands since a Command Complete
-    interrupt could occur if the IRQ Channel was previously enabled by another
-    BusLogic Host Adapter or another driver sharing the same IRQ Channel.
-  */
-  if (!HostAdapter->IRQ_ChannelAcquired)
-    {
-      local_irq_save(ProcessorFlags);
-      local_irq_disable();
-    }
-  /*
-    Wait for the Host Adapter Ready bit to be set and the Command/Parameter
-    Register Busy bit to be reset in the Status Register.
-  */
-  TimeoutCounter = 10000;
-  while (--TimeoutCounter >= 0)
-    {
-      StatusRegister.All = BusLogic_ReadStatusRegister(HostAdapter);
-      if (StatusRegister.sr.HostAdapterReady &&
-	  !StatusRegister.sr.CommandParameterRegisterBusy)
-	break;
-      udelay(100);
-    }
-  if (TimeoutCounter < 0)
-    {
-      BusLogic_CommandFailureReason = "Timeout waiting for Host Adapter Ready";
-      Result = -2;
-      goto Done;
-    }
-  /*
-    Write the OperationCode to the Command/Parameter Register.
-  */
-  HostAdapter->HostAdapterCommandCompleted = false;
-  BusLogic_WriteCommandParameterRegister(HostAdapter, OperationCode);
-  /*
-    Write any additional Parameter Bytes.
-  */
-  TimeoutCounter = 10000;
-  while (ParameterLength > 0 && --TimeoutCounter >= 0)
-    {
-      /*
-	Wait 100 microseconds to give the Host Adapter enough time to determine
-	whether the last value written to the Command/Parameter Register was
-	valid or not.  If the Command Complete bit is set in the Interrupt
-	Register, then the Command Invalid bit in the Status Register will be
-	reset if the Operation Code or Parameter was valid and the command
-	has completed, or set if the Operation Code or Parameter was invalid.
-	If the Data In Register Ready bit is set in the Status Register, then
-	the Operation Code was valid, and data is waiting to be read back
-	from the Host Adapter.  Otherwise, wait for the Command/Parameter
-	Register Busy bit in the Status Register to be reset.
-      */
-      udelay(100);
-      InterruptRegister.All = BusLogic_ReadInterruptRegister(HostAdapter);
-      StatusRegister.All = BusLogic_ReadStatusRegister(HostAdapter);
-      if (InterruptRegister.ir.CommandComplete) break;
-      if (HostAdapter->HostAdapterCommandCompleted) break;
-      if (StatusRegister.sr.DataInRegisterReady) break;
-      if (StatusRegister.sr.CommandParameterRegisterBusy) continue;
-      BusLogic_WriteCommandParameterRegister(HostAdapter, *ParameterPointer++);
-      ParameterLength--;
-    }
-  if (TimeoutCounter < 0)
-    {
-      BusLogic_CommandFailureReason =
-	"Timeout waiting for Parameter Acceptance";
-      Result = -2;
-      goto Done;
-    }
-  /*
-    The Modify I/O Address command does not cause a Command Complete Interrupt.
-  */
-  if (OperationCode == BusLogic_ModifyIOAddress)
-    {
-      StatusRegister.All = BusLogic_ReadStatusRegister(HostAdapter);
-      if (StatusRegister.sr.CommandInvalid)
-	{
-	  BusLogic_CommandFailureReason = "Modify I/O Address Invalid";
-	  Result = -1;
-	  goto Done;
-	}
-      if (BusLogic_GlobalOptions.TraceConfiguration)
-	BusLogic_Notice("BusLogic_Command(%02X) Status = %02X: "
-			"(Modify I/O Address)\n", HostAdapter,
-			OperationCode, StatusRegister.All);
-      Result = 0;
-      goto Done;
-    }
-  /*
-    Select an appropriate timeout value for awaiting command completion.
-  */
-  switch (OperationCode)
-    {
-    case BusLogic_InquireInstalledDevicesID0to7:
-    case BusLogic_InquireInstalledDevicesID8to15:
-    case BusLogic_InquireTargetDevices:
-      /* Approximately 60 seconds. */
-      TimeoutCounter = 60*10000;
-      break;
-    default:
-      /* Approximately 1 second. */
-      TimeoutCounter = 10000;
-      break;
-    }
-  /*
-    Receive any Reply Bytes, waiting for either the Command Complete bit to
-    be set in the Interrupt Register, or for the Interrupt Handler to set the
-    Host Adapter Command Completed bit in the Host Adapter structure.
-  */
-  while (--TimeoutCounter >= 0)
-    {
-      InterruptRegister.All = BusLogic_ReadInterruptRegister(HostAdapter);
-      StatusRegister.All = BusLogic_ReadStatusRegister(HostAdapter);
-      if (InterruptRegister.ir.CommandComplete) break;
-      if (HostAdapter->HostAdapterCommandCompleted) break;
-      if (StatusRegister.sr.DataInRegisterReady)
-	{
-	  if (++ReplyBytes <= ReplyLength)
-	    *ReplyPointer++ = BusLogic_ReadDataInRegister(HostAdapter);
-	  else BusLogic_ReadDataInRegister(HostAdapter);
-	}
-      if (OperationCode == BusLogic_FetchHostAdapterLocalRAM &&
-	  StatusRegister.sr.HostAdapterReady) break;
-      udelay(100);
-    }
-  if (TimeoutCounter < 0)
-    {
-      BusLogic_CommandFailureReason = "Timeout waiting for Command Complete";
-      Result = -2;
-      goto Done;
-    }
-  /*
-    Clear any pending Command Complete Interrupt.
-  */
-  BusLogic_InterruptReset(HostAdapter);
-  /*
-    Provide tracing information if requested.
-  */
-  if (BusLogic_GlobalOptions.TraceConfiguration)
-    {
-      int i;
-      BusLogic_Notice("BusLogic_Command(%02X) Status = %02X: %2d ==> %2d:",
-		      HostAdapter, OperationCode,
-		      StatusRegister.All, ReplyLength, ReplyBytes);
-      if (ReplyLength > ReplyBytes) ReplyLength = ReplyBytes;
-      for (i = 0; i < ReplyLength; i++)
-	BusLogic_Notice(" %02X", HostAdapter,
-			((unsigned char *) ReplyData)[i]);
-      BusLogic_Notice("\n", HostAdapter);
-    }
-  /*
-    Process Command Invalid conditions.
-  */
-  if (StatusRegister.sr.CommandInvalid)
-    {
-      /*
-	Some early BusLogic Host Adapters may not recover properly from
-	a Command Invalid condition, so if this appears to be the case,
-	a Soft Reset is issued to the Host Adapter.  Potentially invalid
-	commands are never attempted after Mailbox Initialization is
-	performed, so there should be no Host Adapter state lost by a
-	Soft Reset in response to a Command Invalid condition.
-      */
-      udelay(1000);
-      StatusRegister.All = BusLogic_ReadStatusRegister(HostAdapter);
-      if (StatusRegister.sr.CommandInvalid ||
-	  StatusRegister.sr.Reserved ||
-	  StatusRegister.sr.DataInRegisterReady ||
-	  StatusRegister.sr.CommandParameterRegisterBusy ||
-	  !StatusRegister.sr.HostAdapterReady ||
-	  !StatusRegister.sr.InitializationRequired ||
-	  StatusRegister.sr.DiagnosticActive ||
-	  StatusRegister.sr.DiagnosticFailure)
-	{
-	  BusLogic_SoftReset(HostAdapter);
-	  udelay(1000);
-	}
-      BusLogic_CommandFailureReason = "Command Invalid";
-      Result = -1;
-      goto Done;
-    }
-  /*
-    Handle Excess Parameters Supplied conditions.
-  */
-  if (ParameterLength > 0)
-    {
-      BusLogic_CommandFailureReason = "Excess Parameters Supplied";
-      Result = -1;
-      goto Done;
-    }
-  /*
-    Indicate the command completed successfully.
-  */
-  BusLogic_CommandFailureReason = NULL;
-  Result = ReplyBytes;
-  /*
-    Restore the interrupt status if necessary and return.
-  */
-Done:
-  if (!HostAdapter->IRQ_ChannelAcquired)
-    local_irq_restore(ProcessorFlags);
-  return Result;
+static int BusLogic_Command(struct BusLogic_HostAdapter *HostAdapter, enum BusLogic_OperationCode OperationCode, void *ParameterData, int ParameterLength, void *ReplyData, int ReplyLength)
+{
+	unsigned char *ParameterPointer = (unsigned char *) ParameterData;
+	unsigned char *ReplyPointer = (unsigned char *) ReplyData;
+	union BusLogic_StatusRegister StatusRegister;
+	union BusLogic_InterruptRegister InterruptRegister;
+	unsigned long ProcessorFlags = 0;
+	int ReplyBytes = 0, Result;
+	long TimeoutCounter;
+	/*
+	   Clear out the Reply Data if provided.
+	 */
+	if (ReplyLength > 0)
+		memset(ReplyData, 0, ReplyLength);
+	/*
+	   If the IRQ Channel has not yet been acquired, then interrupts must be
+	   disabled while issuing host adapter commands since a Command Complete
+	   interrupt could occur if the IRQ Channel was previously enabled by another
+	   BusLogic Host Adapter or another driver sharing the same IRQ Channel.
+	 */
+	if (!HostAdapter->IRQ_ChannelAcquired) {
+		local_irq_save(ProcessorFlags);
+		local_irq_disable();
+	}
+	/*
+	   Wait for the Host Adapter Ready bit to be set and the Command/Parameter
+	   Register Busy bit to be reset in the Status Register.
+	 */
+	TimeoutCounter = 10000;
+	while (--TimeoutCounter >= 0) {
+		StatusRegister.All = BusLogic_ReadStatusRegister(HostAdapter);
+		if (StatusRegister.sr.HostAdapterReady && !StatusRegister.sr.CommandParameterRegisterBusy)
+			break;
+		udelay(100);
+	}
+	if (TimeoutCounter < 0) {
+		BusLogic_CommandFailureReason = "Timeout waiting for Host Adapter Ready";
+		Result = -2;
+		goto Done;
+	}
+	/*
+	   Write the OperationCode to the Command/Parameter Register.
+	 */
+	HostAdapter->HostAdapterCommandCompleted = false;
+	BusLogic_WriteCommandParameterRegister(HostAdapter, OperationCode);
+	/*
+	   Write any additional Parameter Bytes.
+	 */
+	TimeoutCounter = 10000;
+	while (ParameterLength > 0 && --TimeoutCounter >= 0) {
+		/*
+		   Wait 100 microseconds to give the Host Adapter enough time to determine
+		   whether the last value written to the Command/Parameter Register was
+		   valid or not.  If the Command Complete bit is set in the Interrupt
+		   Register, then the Command Invalid bit in the Status Register will be
+		   reset if the Operation Code or Parameter was valid and the command
+		   has completed, or set if the Operation Code or Parameter was invalid.
+		   If the Data In Register Ready bit is set in the Status Register, then
+		   the Operation Code was valid, and data is waiting to be read back
+		   from the Host Adapter.  Otherwise, wait for the Command/Parameter
+		   Register Busy bit in the Status Register to be reset.
+		 */
+		udelay(100);
+		InterruptRegister.All = BusLogic_ReadInterruptRegister(HostAdapter);
+		StatusRegister.All = BusLogic_ReadStatusRegister(HostAdapter);
+		if (InterruptRegister.ir.CommandComplete)
+			break;
+		if (HostAdapter->HostAdapterCommandCompleted)
+			break;
+		if (StatusRegister.sr.DataInRegisterReady)
+			break;
+		if (StatusRegister.sr.CommandParameterRegisterBusy)
+			continue;
+		BusLogic_WriteCommandParameterRegister(HostAdapter, *ParameterPointer++);
+		ParameterLength--;
+	}
+	if (TimeoutCounter < 0) {
+		BusLogic_CommandFailureReason = "Timeout waiting for Parameter Acceptance";
+		Result = -2;
+		goto Done;
+	}
+	/*
+	   The Modify I/O Address command does not cause a Command Complete Interrupt.
+	 */
+	if (OperationCode == BusLogic_ModifyIOAddress) {
+		StatusRegister.All = BusLogic_ReadStatusRegister(HostAdapter);
+		if (StatusRegister.sr.CommandInvalid) {
+			BusLogic_CommandFailureReason = "Modify I/O Address Invalid";
+			Result = -1;
+			goto Done;
+		}
+		if (BusLogic_GlobalOptions.TraceConfiguration)
+			BusLogic_Notice("BusLogic_Command(%02X) Status = %02X: " "(Modify I/O Address)\n", HostAdapter, OperationCode, StatusRegister.All);
+		Result = 0;
+		goto Done;
+	}
+	/*
+	   Select an appropriate timeout value for awaiting command completion.
+	 */
+	switch (OperationCode) {
+	case BusLogic_InquireInstalledDevicesID0to7:
+	case BusLogic_InquireInstalledDevicesID8to15:
+	case BusLogic_InquireTargetDevices:
+		/* Approximately 60 seconds. */
+		TimeoutCounter = 60 * 10000;
+		break;
+	default:
+		/* Approximately 1 second. */
+		TimeoutCounter = 10000;
+		break;
+	}
+	/*
+	   Receive any Reply Bytes, waiting for either the Command Complete bit to
+	   be set in the Interrupt Register, or for the Interrupt Handler to set the
+	   Host Adapter Command Completed bit in the Host Adapter structure.
+	 */
+	while (--TimeoutCounter >= 0) {
+		InterruptRegister.All = BusLogic_ReadInterruptRegister(HostAdapter);
+		StatusRegister.All = BusLogic_ReadStatusRegister(HostAdapter);
+		if (InterruptRegister.ir.CommandComplete)
+			break;
+		if (HostAdapter->HostAdapterCommandCompleted)
+			break;
+		if (StatusRegister.sr.DataInRegisterReady) {
+			if (++ReplyBytes <= ReplyLength)
+				*ReplyPointer++ = BusLogic_ReadDataInRegister(HostAdapter);
+			else
+				BusLogic_ReadDataInRegister(HostAdapter);
+		}
+		if (OperationCode == BusLogic_FetchHostAdapterLocalRAM && StatusRegister.sr.HostAdapterReady)
+			break;
+		udelay(100);
+	}
+	if (TimeoutCounter < 0) {
+		BusLogic_CommandFailureReason = "Timeout waiting for Command Complete";
+		Result = -2;
+		goto Done;
+	}
+	/*
+	   Clear any pending Command Complete Interrupt.
+	 */
+	BusLogic_InterruptReset(HostAdapter);
+	/*
+	   Provide tracing information if requested.
+	 */
+	if (BusLogic_GlobalOptions.TraceConfiguration) {
+		int i;
+		BusLogic_Notice("BusLogic_Command(%02X) Status = %02X: %2d ==> %2d:", HostAdapter, OperationCode, StatusRegister.All, ReplyLength, ReplyBytes);
+		if (ReplyLength > ReplyBytes)
+			ReplyLength = ReplyBytes;
+		for (i = 0; i < ReplyLength; i++)
+			BusLogic_Notice(" %02X", HostAdapter, ((unsigned char *) ReplyData)[i]);
+		BusLogic_Notice("\n", HostAdapter);
+	}
+	/*
+	   Process Command Invalid conditions.
+	 */
+	if (StatusRegister.sr.CommandInvalid) {
+		/*
+		   Some early BusLogic Host Adapters may not recover properly from
+		   a Command Invalid condition, so if this appears to be the case,
+		   a Soft Reset is issued to the Host Adapter.  Potentially invalid
+		   commands are never attempted after Mailbox Initialization is
+		   performed, so there should be no Host Adapter state lost by a
+		   Soft Reset in response to a Command Invalid condition.
+		 */
+		udelay(1000);
+		StatusRegister.All = BusLogic_ReadStatusRegister(HostAdapter);
+		if (StatusRegister.sr.CommandInvalid ||
+		    StatusRegister.sr.Reserved ||
+		    StatusRegister.sr.DataInRegisterReady ||
+		    StatusRegister.sr.CommandParameterRegisterBusy || !StatusRegister.sr.HostAdapterReady || !StatusRegister.sr.InitializationRequired || StatusRegister.sr.DiagnosticActive || StatusRegister.sr.DiagnosticFailure) {
+			BusLogic_SoftReset(HostAdapter);
+			udelay(1000);
+		}
+		BusLogic_CommandFailureReason = "Command Invalid";
+		Result = -1;
+		goto Done;
+	}
+	/*
+	   Handle Excess Parameters Supplied conditions.
+	 */
+	if (ParameterLength > 0) {
+		BusLogic_CommandFailureReason = "Excess Parameters Supplied";
+		Result = -1;
+		goto Done;
+	}
+	/*
+	   Indicate the command completed successfully.
+	 */
+	BusLogic_CommandFailureReason = NULL;
+	Result = ReplyBytes;
+	/*
+	   Restore the interrupt status if necessary and return.
+	 */
+      Done:
+	if (!HostAdapter->IRQ_ChannelAcquired)
+		local_irq_restore(ProcessorFlags);
+	return Result;
 }
 
 
@@ -662,13 +588,14 @@
 
 static void __init BusLogic_AppendProbeAddressISA(unsigned long IO_Address)
 {
-  struct BusLogic_ProbeInfo *ProbeInfo;
-  if (BusLogic_ProbeInfoCount >= BusLogic_MaxHostAdapters) return;
-  ProbeInfo = &BusLogic_ProbeInfoList[BusLogic_ProbeInfoCount++];
-  ProbeInfo->HostAdapterType = BusLogic_MultiMaster;
-  ProbeInfo->HostAdapterBusType = BusLogic_ISA_Bus;
-  ProbeInfo->IO_Address = IO_Address;
-  ProbeInfo->PCI_Device = NULL;
+	struct BusLogic_ProbeInfo *ProbeInfo;
+	if (BusLogic_ProbeInfoCount >= BusLogic_MaxHostAdapters)
+		return;
+	ProbeInfo = &BusLogic_ProbeInfoList[BusLogic_ProbeInfoCount++];
+	ProbeInfo->HostAdapterType = BusLogic_MultiMaster;
+	ProbeInfo->HostAdapterBusType = BusLogic_ISA_Bus;
+	ProbeInfo->IO_Address = IO_Address;
+	ProbeInfo->PCI_Device = NULL;
 }
 
 
@@ -681,38 +608,27 @@
 static void __init BusLogic_InitializeProbeInfoListISA(struct BusLogic_HostAdapter
 						       *PrototypeHostAdapter)
 {
-  /*
-    If BusLogic Driver Options specifications requested that ISA Bus Probes
-    be inhibited, do not proceed further.
-  */
-  if (BusLogic_ProbeOptions.NoProbeISA) return;
-  /*
-    Append the list of standard BusLogic MultiMaster ISA I/O Addresses.
-  */
-  if (BusLogic_ProbeOptions.LimitedProbeISA
-      ? BusLogic_ProbeOptions.Probe330
-      : check_region(0x330, BusLogic_MultiMasterAddressCount) == 0)
-    BusLogic_AppendProbeAddressISA(0x330);
-  if (BusLogic_ProbeOptions.LimitedProbeISA
-      ? BusLogic_ProbeOptions.Probe334
-      : check_region(0x334, BusLogic_MultiMasterAddressCount) == 0)
-    BusLogic_AppendProbeAddressISA(0x334);
-  if (BusLogic_ProbeOptions.LimitedProbeISA
-      ? BusLogic_ProbeOptions.Probe230
-      : check_region(0x230, BusLogic_MultiMasterAddressCount) == 0)
-    BusLogic_AppendProbeAddressISA(0x230);
-  if (BusLogic_ProbeOptions.LimitedProbeISA
-      ? BusLogic_ProbeOptions.Probe234
-      : check_region(0x234, BusLogic_MultiMasterAddressCount) == 0)
-    BusLogic_AppendProbeAddressISA(0x234);
-  if (BusLogic_ProbeOptions.LimitedProbeISA
-      ? BusLogic_ProbeOptions.Probe130
-      : check_region(0x130, BusLogic_MultiMasterAddressCount) == 0)
-    BusLogic_AppendProbeAddressISA(0x130);
-  if (BusLogic_ProbeOptions.LimitedProbeISA
-      ? BusLogic_ProbeOptions.Probe134
-      : check_region(0x134, BusLogic_MultiMasterAddressCount) == 0)
-    BusLogic_AppendProbeAddressISA(0x134);
+	/*
+	   If BusLogic Driver Options specifications requested that ISA Bus Probes
+	   be inhibited, do not proceed further.
+	 */
+	if (BusLogic_ProbeOptions.NoProbeISA)
+		return;
+	/*
+	   Append the list of standard BusLogic MultiMaster ISA I/O Addresses.
+	 */
+	if (BusLogic_ProbeOptions.LimitedProbeISA ? BusLogic_ProbeOptions.Probe330 : check_region(0x330, BusLogic_MultiMasterAddressCount) == 0)
+		BusLogic_AppendProbeAddressISA(0x330);
+	if (BusLogic_ProbeOptions.LimitedProbeISA ? BusLogic_ProbeOptions.Probe334 : check_region(0x334, BusLogic_MultiMasterAddressCount) == 0)
+		BusLogic_AppendProbeAddressISA(0x334);
+	if (BusLogic_ProbeOptions.LimitedProbeISA ? BusLogic_ProbeOptions.Probe230 : check_region(0x230, BusLogic_MultiMasterAddressCount) == 0)
+		BusLogic_AppendProbeAddressISA(0x230);
+	if (BusLogic_ProbeOptions.LimitedProbeISA ? BusLogic_ProbeOptions.Probe234 : check_region(0x234, BusLogic_MultiMasterAddressCount) == 0)
+		BusLogic_AppendProbeAddressISA(0x234);
+	if (BusLogic_ProbeOptions.LimitedProbeISA ? BusLogic_ProbeOptions.Probe130 : check_region(0x130, BusLogic_MultiMasterAddressCount) == 0)
+		BusLogic_AppendProbeAddressISA(0x130);
+	if (BusLogic_ProbeOptions.LimitedProbeISA ? BusLogic_ProbeOptions.Probe134 : check_region(0x134, BusLogic_MultiMasterAddressCount) == 0)
+		BusLogic_AppendProbeAddressISA(0x134);
 }
 
 
@@ -724,30 +640,24 @@
   of increasing PCI Bus and Device Number.
 */
 
-static void __init BusLogic_SortProbeInfo(struct BusLogic_ProbeInfo *ProbeInfoList,
-					  int ProbeInfoCount)
+static void __init BusLogic_SortProbeInfo(struct BusLogic_ProbeInfo *ProbeInfoList, int ProbeInfoCount)
 {
-  int LastInterchange = ProbeInfoCount-1, Bound, j;
-  while (LastInterchange > 0)
-    {
-      Bound = LastInterchange;
-      LastInterchange = 0;
-      for (j = 0; j < Bound; j++)
-	{
-	  struct BusLogic_ProbeInfo *ProbeInfo1 = &ProbeInfoList[j];
-	  struct BusLogic_ProbeInfo *ProbeInfo2 = &ProbeInfoList[j+1];
-	  if (ProbeInfo1->Bus > ProbeInfo2->Bus ||
-	      (ProbeInfo1->Bus == ProbeInfo2->Bus &&
-	       (ProbeInfo1->Device > ProbeInfo2->Device)))
-	    {
-	      struct BusLogic_ProbeInfo TempProbeInfo;
-	      memcpy(&TempProbeInfo, ProbeInfo1, sizeof(struct BusLogic_ProbeInfo));
-	      memcpy(ProbeInfo1, ProbeInfo2, sizeof(struct BusLogic_ProbeInfo));
-	      memcpy(ProbeInfo2, &TempProbeInfo, sizeof(struct BusLogic_ProbeInfo));
-	      LastInterchange = j;
-	    }
+	int LastInterchange = ProbeInfoCount - 1, Bound, j;
+	while (LastInterchange > 0) {
+		Bound = LastInterchange;
+		LastInterchange = 0;
+		for (j = 0; j < Bound; j++) {
+			struct BusLogic_ProbeInfo *ProbeInfo1 = &ProbeInfoList[j];
+			struct BusLogic_ProbeInfo *ProbeInfo2 = &ProbeInfoList[j + 1];
+			if (ProbeInfo1->Bus > ProbeInfo2->Bus || (ProbeInfo1->Bus == ProbeInfo2->Bus && (ProbeInfo1->Device > ProbeInfo2->Device))) {
+				struct BusLogic_ProbeInfo TempProbeInfo;
+				memcpy(&TempProbeInfo, ProbeInfo1, sizeof(struct BusLogic_ProbeInfo));
+				memcpy(ProbeInfo1, ProbeInfo2, sizeof(struct BusLogic_ProbeInfo));
+				memcpy(ProbeInfo2, &TempProbeInfo, sizeof(struct BusLogic_ProbeInfo));
+				LastInterchange = j;
+			}
+		}
 	}
-    }
 }
 
 
@@ -762,292 +672,226 @@
 static int __init BusLogic_InitializeMultiMasterProbeInfo(struct BusLogic_HostAdapter
 							  *PrototypeHostAdapter)
 {
-  struct BusLogic_ProbeInfo *PrimaryProbeInfo =
-    &BusLogic_ProbeInfoList[BusLogic_ProbeInfoCount];
-  int NonPrimaryPCIMultiMasterIndex = BusLogic_ProbeInfoCount + 1;
-  int NonPrimaryPCIMultiMasterCount = 0, PCIMultiMasterCount = 0;
-  boolean ForceBusDeviceScanningOrder = false;
-  boolean ForceBusDeviceScanningOrderChecked = false;
-  boolean StandardAddressSeen[6];
-  struct pci_dev *PCI_Device = NULL;
-  int i;
-  if (BusLogic_ProbeInfoCount >= BusLogic_MaxHostAdapters) return 0;
-  BusLogic_ProbeInfoCount++;
-  for (i = 0; i < 6; i++)
-    StandardAddressSeen[i] = false;
-  /*
-    Iterate over the MultiMaster PCI Host Adapters.  For each enumerated host
-    adapter, determine whether its ISA Compatible I/O Port is enabled and if
-    so, whether it is assigned the Primary I/O Address.  A host adapter that is
-    assigned the Primary I/O Address will always be the preferred boot device.
-    The MultiMaster BIOS will first recognize a host adapter at the Primary I/O
-    Address, then any other PCI host adapters, and finally any host adapters
-    located at the remaining standard ISA I/O Addresses.  When a PCI host
-    adapter is found with its ISA Compatible I/O Port enabled, a command is
-    issued to disable the ISA Compatible I/O Port, and it is noted that the
-    particular standard ISA I/O Address need not be probed.
-  */
-  PrimaryProbeInfo->IO_Address = 0;
-  while ((PCI_Device = pci_find_device(PCI_VENDOR_ID_BUSLOGIC,
-				       PCI_DEVICE_ID_BUSLOGIC_MULTIMASTER,
-				       PCI_Device)) != NULL)
-    {
-      struct BusLogic_HostAdapter *HostAdapter = PrototypeHostAdapter;
-      struct BusLogic_PCIHostAdapterInformation PCIHostAdapterInformation;
-      enum BusLogic_ISACompatibleIOPort ModifyIOAddressRequest;
-      unsigned char Bus;
-      unsigned char Device;
-      unsigned int IRQ_Channel;
-      unsigned long BaseAddress0;
-      unsigned long BaseAddress1;
-      unsigned long IO_Address;
-      unsigned long PCI_Address;
-
-      if (pci_enable_device(PCI_Device))
-      	continue;
-
-      if (pci_set_dma_mask(PCI_Device, (u64)0xffffffff))
-	continue;
-      
-      Bus = PCI_Device->bus->number;
-      Device = PCI_Device->devfn >> 3;
-      IRQ_Channel = PCI_Device->irq;
-      IO_Address  = BaseAddress0 = pci_resource_start(PCI_Device, 0);
-      PCI_Address = BaseAddress1 = pci_resource_start(PCI_Device, 1);
-
-      if (pci_resource_flags(PCI_Device, 0) & IORESOURCE_MEM)
-	{
-	  BusLogic_Error("BusLogic: Base Address0 0x%X not I/O for "
-			 "MultiMaster Host Adapter\n", NULL, BaseAddress0);
-	  BusLogic_Error("at PCI Bus %d Device %d I/O Address 0x%X\n",
-			 NULL, Bus, Device, IO_Address);
-	  continue;
-	}
-      if (pci_resource_flags(PCI_Device,1) & IORESOURCE_IO)
-	{
-	  BusLogic_Error("BusLogic: Base Address1 0x%X not Memory for "
-			 "MultiMaster Host Adapter\n", NULL, BaseAddress1);
-	  BusLogic_Error("at PCI Bus %d Device %d PCI Address 0x%X\n",
-			 NULL, Bus, Device, PCI_Address);
-	  continue;
-	}
-      if (IRQ_Channel == 0)
-	{
-	  BusLogic_Error("BusLogic: IRQ Channel %d invalid for "
-			 "MultiMaster Host Adapter\n", NULL, IRQ_Channel);
-	  BusLogic_Error("at PCI Bus %d Device %d I/O Address 0x%X\n",
-			 NULL, Bus, Device, IO_Address);
-	  continue;
-	}
-      if (BusLogic_GlobalOptions.TraceProbe)
-	{
-	  BusLogic_Notice("BusLogic: PCI MultiMaster Host Adapter "
-			  "detected at\n", NULL);
-	  BusLogic_Notice("BusLogic: PCI Bus %d Device %d I/O Address "
-			  "0x%X PCI Address 0x%X\n", NULL,
-			  Bus, Device, IO_Address, PCI_Address);
-	}
-      /*
-	Issue the Inquire PCI Host Adapter Information command to determine
-	the ISA Compatible I/O Port.  If the ISA Compatible I/O Port is
-	known and enabled, note that the particular Standard ISA I/O
-	Address should not be probed.
-      */
-      HostAdapter->IO_Address = IO_Address;
-      BusLogic_InterruptReset(HostAdapter);
-      if (BusLogic_Command(HostAdapter,
-			   BusLogic_InquirePCIHostAdapterInformation,
-			   NULL, 0, &PCIHostAdapterInformation,
-			   sizeof(PCIHostAdapterInformation))
-	  == sizeof(PCIHostAdapterInformation))
-	{
-	  if (PCIHostAdapterInformation.ISACompatibleIOPort < 6)
-	    StandardAddressSeen[PCIHostAdapterInformation
-				.ISACompatibleIOPort] = true;
-	}
-      else PCIHostAdapterInformation.ISACompatibleIOPort =
-	     BusLogic_IO_Disable;
-      /*
-       * Issue the Modify I/O Address command to disable the ISA Compatible
-       * I/O Port.  On PCI Host Adapters, the Modify I/O Address command
-       * allows modification of the ISA compatible I/O Address that the Host
-       * Adapter responds to; it does not affect the PCI compliant I/O Address
-       * assigned at system initialization.
-       */
-      ModifyIOAddressRequest = BusLogic_IO_Disable;
-      BusLogic_Command(HostAdapter, BusLogic_ModifyIOAddress,
-		       &ModifyIOAddressRequest,
-		       sizeof(ModifyIOAddressRequest), NULL, 0);
-      /*
-	For the first MultiMaster Host Adapter enumerated, issue the Fetch
-	Host Adapter Local RAM command to read byte 45 of the AutoSCSI area,
-	for the setting of the "Use Bus And Device # For PCI Scanning Seq."
-	option.  Issue the Inquire Board ID command since this option is
-	only valid for the BT-948/958/958D.
-      */
-      if (!ForceBusDeviceScanningOrderChecked)
-	{
-	  struct BusLogic_FetchHostAdapterLocalRAMRequest
-	    FetchHostAdapterLocalRAMRequest;
-	  struct BusLogic_AutoSCSIByte45 AutoSCSIByte45;
-	  struct BusLogic_BoardID BoardID;
-	  FetchHostAdapterLocalRAMRequest.ByteOffset =
-	    BusLogic_AutoSCSI_BaseOffset + 45;
-	  FetchHostAdapterLocalRAMRequest.ByteCount =
-	    sizeof(AutoSCSIByte45);
-	  BusLogic_Command(HostAdapter,
-			   BusLogic_FetchHostAdapterLocalRAM,
-			   &FetchHostAdapterLocalRAMRequest,
-			   sizeof(FetchHostAdapterLocalRAMRequest),
-			   &AutoSCSIByte45, sizeof(AutoSCSIByte45));
-	  BusLogic_Command(HostAdapter, BusLogic_InquireBoardID,
-			   NULL, 0, &BoardID, sizeof(BoardID));
-	  if (BoardID.FirmwareVersion1stDigit == '5')
-	    ForceBusDeviceScanningOrder =
-	      AutoSCSIByte45.ForceBusDeviceScanningOrder;
-	  ForceBusDeviceScanningOrderChecked = true;
-	}
-      /*
-	Determine whether this MultiMaster Host Adapter has its ISA
-	Compatible I/O Port enabled and is assigned the Primary I/O Address.
-	If it does, then it is the Primary MultiMaster Host Adapter and must
-	be recognized first.  If it does not, then it is added to the list
-	for probing after any Primary MultiMaster Host Adapter is probed.
-      */
-      if (PCIHostAdapterInformation.ISACompatibleIOPort == BusLogic_IO_330)
-	{
-	  PrimaryProbeInfo->HostAdapterType = BusLogic_MultiMaster;
-	  PrimaryProbeInfo->HostAdapterBusType = BusLogic_PCI_Bus;
-	  PrimaryProbeInfo->IO_Address = IO_Address;
-	  PrimaryProbeInfo->PCI_Address = PCI_Address;
-	  PrimaryProbeInfo->Bus = Bus;
-	  PrimaryProbeInfo->Device = Device;
-	  PrimaryProbeInfo->IRQ_Channel = IRQ_Channel;
-	  PrimaryProbeInfo->PCI_Device = PCI_Device;
-	  PCIMultiMasterCount++;
-	}
-      else if (BusLogic_ProbeInfoCount < BusLogic_MaxHostAdapters)
-	{
-	  struct BusLogic_ProbeInfo *ProbeInfo =
-	    &BusLogic_ProbeInfoList[BusLogic_ProbeInfoCount++];
-	  ProbeInfo->HostAdapterType = BusLogic_MultiMaster;
-	  ProbeInfo->HostAdapterBusType = BusLogic_PCI_Bus;
-	  ProbeInfo->IO_Address = IO_Address;
-	  ProbeInfo->PCI_Address = PCI_Address;
-	  ProbeInfo->Bus = Bus;
-	  ProbeInfo->Device = Device;
-	  ProbeInfo->IRQ_Channel = IRQ_Channel;
-	  ProbeInfo->PCI_Device = PCI_Device;
-	  NonPrimaryPCIMultiMasterCount++;
-	  PCIMultiMasterCount++;
-	}
-      else BusLogic_Warning("BusLogic: Too many Host Adapters "
-			    "detected\n", NULL);
-    }
-  /*
-    If the AutoSCSI "Use Bus And Device # For PCI Scanning Seq." option is ON
-    for the first enumerated MultiMaster Host Adapter, and if that host adapter
-    is a BT-948/958/958D, then the MultiMaster BIOS will recognize MultiMaster
-    Host Adapters in the order of increasing PCI Bus and Device Number.  In
-    that case, sort the probe information into the same order the BIOS uses.
-    If this option is OFF, then the MultiMaster BIOS will recognize MultiMaster
-    Host Adapters in the order they are enumerated by the PCI BIOS, and hence
-    no sorting is necessary.
-  */
-  if (ForceBusDeviceScanningOrder)
-    BusLogic_SortProbeInfo(&BusLogic_ProbeInfoList[
-			      NonPrimaryPCIMultiMasterIndex],
-			   NonPrimaryPCIMultiMasterCount);
-  /*
-    If no PCI MultiMaster Host Adapter is assigned the Primary I/O Address,
-    then the Primary I/O Address must be probed explicitly before any PCI
-    host adapters are probed.
-  */
-  if (!BusLogic_ProbeOptions.NoProbeISA)
-    if (PrimaryProbeInfo->IO_Address == 0 &&
-	(BusLogic_ProbeOptions.LimitedProbeISA
-	 ? BusLogic_ProbeOptions.Probe330
-	 : check_region(0x330, BusLogic_MultiMasterAddressCount) == 0))
-      {
-	PrimaryProbeInfo->HostAdapterType = BusLogic_MultiMaster;
-	PrimaryProbeInfo->HostAdapterBusType = BusLogic_ISA_Bus;
-	PrimaryProbeInfo->IO_Address = 0x330;
-      }
-  /*
-    Append the list of standard BusLogic MultiMaster ISA I/O Addresses,
-    omitting the Primary I/O Address which has already been handled.
-  */
-  if (!BusLogic_ProbeOptions.NoProbeISA)
-    {
-      if (!StandardAddressSeen[1] &&
-	  (BusLogic_ProbeOptions.LimitedProbeISA
-	   ? BusLogic_ProbeOptions.Probe334
-	   : check_region(0x334, BusLogic_MultiMasterAddressCount) == 0))
-	BusLogic_AppendProbeAddressISA(0x334);
-      if (!StandardAddressSeen[2] &&
-	  (BusLogic_ProbeOptions.LimitedProbeISA
-	   ? BusLogic_ProbeOptions.Probe230
-	   : check_region(0x230, BusLogic_MultiMasterAddressCount) == 0))
-	BusLogic_AppendProbeAddressISA(0x230);
-      if (!StandardAddressSeen[3] &&
-	  (BusLogic_ProbeOptions.LimitedProbeISA
-	   ? BusLogic_ProbeOptions.Probe234
-	   : check_region(0x234, BusLogic_MultiMasterAddressCount) == 0))
-	BusLogic_AppendProbeAddressISA(0x234);
-      if (!StandardAddressSeen[4] &&
-	  (BusLogic_ProbeOptions.LimitedProbeISA
-	   ? BusLogic_ProbeOptions.Probe130
-	   : check_region(0x130, BusLogic_MultiMasterAddressCount) == 0))
-	BusLogic_AppendProbeAddressISA(0x130);
-      if (!StandardAddressSeen[5] &&
-	  (BusLogic_ProbeOptions.LimitedProbeISA
-	   ? BusLogic_ProbeOptions.Probe134
-	   : check_region(0x134, BusLogic_MultiMasterAddressCount) == 0))
-	BusLogic_AppendProbeAddressISA(0x134);
-    }
-  /*
-    Iterate over the older non-compliant MultiMaster PCI Host Adapters,
-    noting the PCI bus location and assigned IRQ Channel.
-  */
-  PCI_Device = NULL;
-  while ((PCI_Device = pci_find_device(PCI_VENDOR_ID_BUSLOGIC,
-				       PCI_DEVICE_ID_BUSLOGIC_MULTIMASTER_NC,
-				       PCI_Device)) != NULL)
-    {
-      unsigned char Bus;
-      unsigned char Device;
-      unsigned int IRQ_Channel;
-      unsigned long IO_Address;
-
-      if (pci_enable_device(PCI_Device))
-	continue;
-
-      if (pci_set_dma_mask(PCI_Device, (u64)0xffffffff))
-	continue;
-
-      Bus = PCI_Device->bus->number;
-      Device = PCI_Device->devfn >> 3;
-      IRQ_Channel = PCI_Device->irq;
-      IO_Address = pci_resource_start(PCI_Device, 0);
-
-      if (IO_Address == 0 || IRQ_Channel == 0) continue;
-      for (i = 0; i < BusLogic_ProbeInfoCount; i++)
-	{
-	  struct BusLogic_ProbeInfo *ProbeInfo = &BusLogic_ProbeInfoList[i];
-	  if (ProbeInfo->IO_Address == IO_Address &&
-	      ProbeInfo->HostAdapterType == BusLogic_MultiMaster)
-	    {
-	      ProbeInfo->HostAdapterBusType = BusLogic_PCI_Bus;
-	      ProbeInfo->PCI_Address = 0;
-	      ProbeInfo->Bus = Bus;
-	      ProbeInfo->Device = Device;
-	      ProbeInfo->IRQ_Channel = IRQ_Channel;
-	      ProbeInfo->PCI_Device = PCI_Device;
-	      break;
-	    }
+	struct BusLogic_ProbeInfo *PrimaryProbeInfo = &BusLogic_ProbeInfoList[BusLogic_ProbeInfoCount];
+	int NonPrimaryPCIMultiMasterIndex = BusLogic_ProbeInfoCount + 1;
+	int NonPrimaryPCIMultiMasterCount = 0, PCIMultiMasterCount = 0;
+	boolean ForceBusDeviceScanningOrder = false;
+	boolean ForceBusDeviceScanningOrderChecked = false;
+	boolean StandardAddressSeen[6];
+	struct pci_dev *PCI_Device = NULL;
+	int i;
+	if (BusLogic_ProbeInfoCount >= BusLogic_MaxHostAdapters)
+		return 0;
+	BusLogic_ProbeInfoCount++;
+	for (i = 0; i < 6; i++)
+		StandardAddressSeen[i] = false;
+	/*
+	   Iterate over the MultiMaster PCI Host Adapters.  For each enumerated host
+	   adapter, determine whether its ISA Compatible I/O Port is enabled and if
+	   so, whether it is assigned the Primary I/O Address.  A host adapter that is
+	   assigned the Primary I/O Address will always be the preferred boot device.
+	   The MultiMaster BIOS will first recognize a host adapter at the Primary I/O
+	   Address, then any other PCI host adapters, and finally any host adapters
+	   located at the remaining standard ISA I/O Addresses.  When a PCI host
+	   adapter is found with its ISA Compatible I/O Port enabled, a command is
+	   issued to disable the ISA Compatible I/O Port, and it is noted that the
+	   particular standard ISA I/O Address need not be probed.
+	 */
+	PrimaryProbeInfo->IO_Address = 0;
+	while ((PCI_Device = pci_find_device(PCI_VENDOR_ID_BUSLOGIC, PCI_DEVICE_ID_BUSLOGIC_MULTIMASTER, PCI_Device)) != NULL) {
+		struct BusLogic_HostAdapter *HostAdapter = PrototypeHostAdapter;
+		struct BusLogic_PCIHostAdapterInformation PCIHostAdapterInformation;
+		enum BusLogic_ISACompatibleIOPort ModifyIOAddressRequest;
+		unsigned char Bus;
+		unsigned char Device;
+		unsigned int IRQ_Channel;
+		unsigned long BaseAddress0;
+		unsigned long BaseAddress1;
+		unsigned long IO_Address;
+		unsigned long PCI_Address;
+
+		if (pci_enable_device(PCI_Device))
+			continue;
+
+		if (pci_set_dma_mask(PCI_Device, (u64) 0xffffffff))
+			continue;
+
+		Bus = PCI_Device->bus->number;
+		Device = PCI_Device->devfn >> 3;
+		IRQ_Channel = PCI_Device->irq;
+		IO_Address = BaseAddress0 = pci_resource_start(PCI_Device, 0);
+		PCI_Address = BaseAddress1 = pci_resource_start(PCI_Device, 1);
+
+		if (pci_resource_flags(PCI_Device, 0) & IORESOURCE_MEM) {
+			BusLogic_Error("BusLogic: Base Address0 0x%X not I/O for " "MultiMaster Host Adapter\n", NULL, BaseAddress0);
+			BusLogic_Error("at PCI Bus %d Device %d I/O Address 0x%X\n", NULL, Bus, Device, IO_Address);
+			continue;
+		}
+		if (pci_resource_flags(PCI_Device, 1) & IORESOURCE_IO) {
+			BusLogic_Error("BusLogic: Base Address1 0x%X not Memory for " "MultiMaster Host Adapter\n", NULL, BaseAddress1);
+			BusLogic_Error("at PCI Bus %d Device %d PCI Address 0x%X\n", NULL, Bus, Device, PCI_Address);
+			continue;
+		}
+		if (IRQ_Channel == 0) {
+			BusLogic_Error("BusLogic: IRQ Channel %d invalid for " "MultiMaster Host Adapter\n", NULL, IRQ_Channel);
+			BusLogic_Error("at PCI Bus %d Device %d I/O Address 0x%X\n", NULL, Bus, Device, IO_Address);
+			continue;
+		}
+		if (BusLogic_GlobalOptions.TraceProbe) {
+			BusLogic_Notice("BusLogic: PCI MultiMaster Host Adapter " "detected at\n", NULL);
+			BusLogic_Notice("BusLogic: PCI Bus %d Device %d I/O Address " "0x%X PCI Address 0x%X\n", NULL, Bus, Device, IO_Address, PCI_Address);
+		}
+		/*
+		   Issue the Inquire PCI Host Adapter Information command to determine
+		   the ISA Compatible I/O Port.  If the ISA Compatible I/O Port is
+		   known and enabled, note that the particular Standard ISA I/O
+		   Address should not be probed.
+		 */
+		HostAdapter->IO_Address = IO_Address;
+		BusLogic_InterruptReset(HostAdapter);
+		if (BusLogic_Command(HostAdapter, BusLogic_InquirePCIHostAdapterInformation, NULL, 0, &PCIHostAdapterInformation, sizeof(PCIHostAdapterInformation))
+		    == sizeof(PCIHostAdapterInformation)) {
+			if (PCIHostAdapterInformation.ISACompatibleIOPort < 6)
+				StandardAddressSeen[PCIHostAdapterInformation.ISACompatibleIOPort] = true;
+		} else
+			PCIHostAdapterInformation.ISACompatibleIOPort = BusLogic_IO_Disable;
+		/*
+		 * Issue the Modify I/O Address command to disable the ISA Compatible
+		 * I/O Port.  On PCI Host Adapters, the Modify I/O Address command
+		 * allows modification of the ISA compatible I/O Address that the Host
+		 * Adapter responds to; it does not affect the PCI compliant I/O Address
+		 * assigned at system initialization.
+		 */
+		ModifyIOAddressRequest = BusLogic_IO_Disable;
+		BusLogic_Command(HostAdapter, BusLogic_ModifyIOAddress, &ModifyIOAddressRequest, sizeof(ModifyIOAddressRequest), NULL, 0);
+		/*
+		   For the first MultiMaster Host Adapter enumerated, issue the Fetch
+		   Host Adapter Local RAM command to read byte 45 of the AutoSCSI area,
+		   for the setting of the "Use Bus And Device # For PCI Scanning Seq."
+		   option.  Issue the Inquire Board ID command since this option is
+		   only valid for the BT-948/958/958D.
+		 */
+		if (!ForceBusDeviceScanningOrderChecked) {
+			struct BusLogic_FetchHostAdapterLocalRAMRequest FetchHostAdapterLocalRAMRequest;
+			struct BusLogic_AutoSCSIByte45 AutoSCSIByte45;
+			struct BusLogic_BoardID BoardID;
+			FetchHostAdapterLocalRAMRequest.ByteOffset = BusLogic_AutoSCSI_BaseOffset + 45;
+			FetchHostAdapterLocalRAMRequest.ByteCount = sizeof(AutoSCSIByte45);
+			BusLogic_Command(HostAdapter, BusLogic_FetchHostAdapterLocalRAM, &FetchHostAdapterLocalRAMRequest, sizeof(FetchHostAdapterLocalRAMRequest), &AutoSCSIByte45, sizeof(AutoSCSIByte45));
+			BusLogic_Command(HostAdapter, BusLogic_InquireBoardID, NULL, 0, &BoardID, sizeof(BoardID));
+			if (BoardID.FirmwareVersion1stDigit == '5')
+				ForceBusDeviceScanningOrder = AutoSCSIByte45.ForceBusDeviceScanningOrder;
+			ForceBusDeviceScanningOrderChecked = true;
+		}
+		/*
+		   Determine whether this MultiMaster Host Adapter has its ISA
+		   Compatible I/O Port enabled and is assigned the Primary I/O Address.
+		   If it does, then it is the Primary MultiMaster Host Adapter and must
+		   be recognized first.  If it does not, then it is added to the list
+		   for probing after any Primary MultiMaster Host Adapter is probed.
+		 */
+		if (PCIHostAdapterInformation.ISACompatibleIOPort == BusLogic_IO_330) {
+			PrimaryProbeInfo->HostAdapterType = BusLogic_MultiMaster;
+			PrimaryProbeInfo->HostAdapterBusType = BusLogic_PCI_Bus;
+			PrimaryProbeInfo->IO_Address = IO_Address;
+			PrimaryProbeInfo->PCI_Address = PCI_Address;
+			PrimaryProbeInfo->Bus = Bus;
+			PrimaryProbeInfo->Device = Device;
+			PrimaryProbeInfo->IRQ_Channel = IRQ_Channel;
+			PrimaryProbeInfo->PCI_Device = PCI_Device;
+			PCIMultiMasterCount++;
+		} else if (BusLogic_ProbeInfoCount < BusLogic_MaxHostAdapters) {
+			struct BusLogic_ProbeInfo *ProbeInfo = &BusLogic_ProbeInfoList[BusLogic_ProbeInfoCount++];
+			ProbeInfo->HostAdapterType = BusLogic_MultiMaster;
+			ProbeInfo->HostAdapterBusType = BusLogic_PCI_Bus;
+			ProbeInfo->IO_Address = IO_Address;
+			ProbeInfo->PCI_Address = PCI_Address;
+			ProbeInfo->Bus = Bus;
+			ProbeInfo->Device = Device;
+			ProbeInfo->IRQ_Channel = IRQ_Channel;
+			ProbeInfo->PCI_Device = PCI_Device;
+			NonPrimaryPCIMultiMasterCount++;
+			PCIMultiMasterCount++;
+		} else
+			BusLogic_Warning("BusLogic: Too many Host Adapters " "detected\n", NULL);
 	}
-    }
-  return PCIMultiMasterCount;
+	/*
+	   If the AutoSCSI "Use Bus And Device # For PCI Scanning Seq." option is ON
+	   for the first enumerated MultiMaster Host Adapter, and if that host adapter
+	   is a BT-948/958/958D, then the MultiMaster BIOS will recognize MultiMaster
+	   Host Adapters in the order of increasing PCI Bus and Device Number.  In
+	   that case, sort the probe information into the same order the BIOS uses.
+	   If this option is OFF, then the MultiMaster BIOS will recognize MultiMaster
+	   Host Adapters in the order they are enumerated by the PCI BIOS, and hence
+	   no sorting is necessary.
+	 */
+	if (ForceBusDeviceScanningOrder)
+		BusLogic_SortProbeInfo(&BusLogic_ProbeInfoList[NonPrimaryPCIMultiMasterIndex], NonPrimaryPCIMultiMasterCount);
+	/*
+	   If no PCI MultiMaster Host Adapter is assigned the Primary I/O Address,
+	   then the Primary I/O Address must be probed explicitly before any PCI
+	   host adapters are probed.
+	 */
+	if (!BusLogic_ProbeOptions.NoProbeISA)
+		if (PrimaryProbeInfo->IO_Address == 0 && (BusLogic_ProbeOptions.LimitedProbeISA ? BusLogic_ProbeOptions.Probe330 : check_region(0x330, BusLogic_MultiMasterAddressCount) == 0)) {
+			PrimaryProbeInfo->HostAdapterType = BusLogic_MultiMaster;
+			PrimaryProbeInfo->HostAdapterBusType = BusLogic_ISA_Bus;
+			PrimaryProbeInfo->IO_Address = 0x330;
+		}
+	/*
+	   Append the list of standard BusLogic MultiMaster ISA I/O Addresses,
+	   omitting the Primary I/O Address which has already been handled.
+	 */
+	if (!BusLogic_ProbeOptions.NoProbeISA) {
+		if (!StandardAddressSeen[1] && (BusLogic_ProbeOptions.LimitedProbeISA ? BusLogic_ProbeOptions.Probe334 : check_region(0x334, BusLogic_MultiMasterAddressCount) == 0))
+			BusLogic_AppendProbeAddressISA(0x334);
+		if (!StandardAddressSeen[2] && (BusLogic_ProbeOptions.LimitedProbeISA ? BusLogic_ProbeOptions.Probe230 : check_region(0x230, BusLogic_MultiMasterAddressCount) == 0))
+			BusLogic_AppendProbeAddressISA(0x230);
+		if (!StandardAddressSeen[3] && (BusLogic_ProbeOptions.LimitedProbeISA ? BusLogic_ProbeOptions.Probe234 : check_region(0x234, BusLogic_MultiMasterAddressCount) == 0))
+			BusLogic_AppendProbeAddressISA(0x234);
+		if (!StandardAddressSeen[4] && (BusLogic_ProbeOptions.LimitedProbeISA ? BusLogic_ProbeOptions.Probe130 : check_region(0x130, BusLogic_MultiMasterAddressCount) == 0))
+			BusLogic_AppendProbeAddressISA(0x130);
+		if (!StandardAddressSeen[5] && (BusLogic_ProbeOptions.LimitedProbeISA ? BusLogic_ProbeOptions.Probe134 : check_region(0x134, BusLogic_MultiMasterAddressCount) == 0))
+			BusLogic_AppendProbeAddressISA(0x134);
+	}
+	/*
+	   Iterate over the older non-compliant MultiMaster PCI Host Adapters,
+	   noting the PCI bus location and assigned IRQ Channel.
+	 */
+	PCI_Device = NULL;
+	while ((PCI_Device = pci_find_device(PCI_VENDOR_ID_BUSLOGIC, PCI_DEVICE_ID_BUSLOGIC_MULTIMASTER_NC, PCI_Device)) != NULL) {
+		unsigned char Bus;
+		unsigned char Device;
+		unsigned int IRQ_Channel;
+		unsigned long IO_Address;
+
+		if (pci_enable_device(PCI_Device))
+			continue;
+
+		if (pci_set_dma_mask(PCI_Device, (u64) 0xffffffff))
+			continue;
+
+		Bus = PCI_Device->bus->number;
+		Device = PCI_Device->devfn >> 3;
+		IRQ_Channel = PCI_Device->irq;
+		IO_Address = pci_resource_start(PCI_Device, 0);
+
+		if (IO_Address == 0 || IRQ_Channel == 0)
+			continue;
+		for (i = 0; i < BusLogic_ProbeInfoCount; i++) {
+			struct BusLogic_ProbeInfo *ProbeInfo = &BusLogic_ProbeInfoList[i];
+			if (ProbeInfo->IO_Address == IO_Address && ProbeInfo->HostAdapterType == BusLogic_MultiMaster) {
+				ProbeInfo->HostAdapterBusType = BusLogic_PCI_Bus;
+				ProbeInfo->PCI_Address = 0;
+				ProbeInfo->Bus = Bus;
+				ProbeInfo->Device = Device;
+				ProbeInfo->IRQ_Channel = IRQ_Channel;
+				ProbeInfo->PCI_Device = PCI_Device;
+				break;
+			}
+		}
+	}
+	return PCIMultiMasterCount;
 }
 
 
@@ -1061,100 +905,77 @@
 static int __init BusLogic_InitializeFlashPointProbeInfo(struct BusLogic_HostAdapter
 							 *PrototypeHostAdapter)
 {
-  int FlashPointIndex = BusLogic_ProbeInfoCount, FlashPointCount = 0;
-  struct pci_dev *PCI_Device = NULL;
-  /*
-    Interrogate PCI Configuration Space for any FlashPoint Host Adapters.
-  */
-  while ((PCI_Device = pci_find_device(PCI_VENDOR_ID_BUSLOGIC,
-				       PCI_DEVICE_ID_BUSLOGIC_FLASHPOINT,
-				       PCI_Device)) != NULL)
-    {
-      unsigned char Bus;
-      unsigned char Device;
-      unsigned int IRQ_Channel;
-      unsigned long BaseAddress0;
-      unsigned long BaseAddress1;
-      unsigned long IO_Address;
-      unsigned long PCI_Address;
-
-      if (pci_enable_device(PCI_Device))
-	continue;
-
-      if (pci_set_dma_mask(PCI_Device, (u64)0xffffffff))
-	continue;
-
-      Bus = PCI_Device->bus->number;
-      Device = PCI_Device->devfn >> 3;
-      IRQ_Channel = PCI_Device->irq;
-      IO_Address = BaseAddress0 = pci_resource_start(PCI_Device, 0);
-      PCI_Address = BaseAddress1 = pci_resource_start(PCI_Device, 1);
+	int FlashPointIndex = BusLogic_ProbeInfoCount, FlashPointCount = 0;
+	struct pci_dev *PCI_Device = NULL;
+	/*
+	   Interrogate PCI Configuration Space for any FlashPoint Host Adapters.
+	 */
+	while ((PCI_Device = pci_find_device(PCI_VENDOR_ID_BUSLOGIC, PCI_DEVICE_ID_BUSLOGIC_FLASHPOINT, PCI_Device)) != NULL) {
+		unsigned char Bus;
+		unsigned char Device;
+		unsigned int IRQ_Channel;
+		unsigned long BaseAddress0;
+		unsigned long BaseAddress1;
+		unsigned long IO_Address;
+		unsigned long PCI_Address;
+
+		if (pci_enable_device(PCI_Device))
+			continue;
+
+		if (pci_set_dma_mask(PCI_Device, (u64) 0xffffffff))
+			continue;
+
+		Bus = PCI_Device->bus->number;
+		Device = PCI_Device->devfn >> 3;
+		IRQ_Channel = PCI_Device->irq;
+		IO_Address = BaseAddress0 = pci_resource_start(PCI_Device, 0);
+		PCI_Address = BaseAddress1 = pci_resource_start(PCI_Device, 1);
 #ifndef CONFIG_SCSI_OMIT_FLASHPOINT
-      if (pci_resource_flags(PCI_Device, 0) & IORESOURCE_MEM)
-	{
-	  BusLogic_Error("BusLogic: Base Address0 0x%X not I/O for "
-			 "FlashPoint Host Adapter\n", NULL, BaseAddress0);
-	  BusLogic_Error("at PCI Bus %d Device %d I/O Address 0x%X\n",
-			 NULL, Bus, Device, IO_Address);
-	  continue;
-	}
-      if (pci_resource_flags(PCI_Device, 1) & IORESOURCE_IO)
-	{
-	  BusLogic_Error("BusLogic: Base Address1 0x%X not Memory for "
-			 "FlashPoint Host Adapter\n", NULL, BaseAddress1);
-	  BusLogic_Error("at PCI Bus %d Device %d PCI Address 0x%X\n",
-			 NULL, Bus, Device, PCI_Address);
-	  continue;
-	}
-      if (IRQ_Channel == 0)
-	{
-	  BusLogic_Error("BusLogic: IRQ Channel %d invalid for "
-			 "FlashPoint Host Adapter\n", NULL, IRQ_Channel);
-	  BusLogic_Error("at PCI Bus %d Device %d I/O Address 0x%X\n",
-			 NULL, Bus, Device, IO_Address);
-	  continue;
-	}
-      if (BusLogic_GlobalOptions.TraceProbe)
-	{
-	  BusLogic_Notice("BusLogic: FlashPoint Host Adapter "
-			  "detected at\n", NULL);
-	  BusLogic_Notice("BusLogic: PCI Bus %d Device %d I/O Address "
-			  "0x%X PCI Address 0x%X\n", NULL,
-			  Bus, Device, IO_Address, PCI_Address);
-	}
-      if (BusLogic_ProbeInfoCount < BusLogic_MaxHostAdapters)
-	{
-	  struct BusLogic_ProbeInfo *ProbeInfo =
-	    &BusLogic_ProbeInfoList[BusLogic_ProbeInfoCount++];
-	  ProbeInfo->HostAdapterType = BusLogic_FlashPoint;
-	  ProbeInfo->HostAdapterBusType = BusLogic_PCI_Bus;
-	  ProbeInfo->IO_Address = IO_Address;
-	  ProbeInfo->PCI_Address = PCI_Address;
-	  ProbeInfo->Bus = Bus;
-	  ProbeInfo->Device = Device;
-	  ProbeInfo->IRQ_Channel = IRQ_Channel;
-	  ProbeInfo->PCI_Device = PCI_Device;
-	  FlashPointCount++;
-	}
-      else BusLogic_Warning("BusLogic: Too many Host Adapters "
-			    "detected\n", NULL);
+		if (pci_resource_flags(PCI_Device, 0) & IORESOURCE_MEM) {
+			BusLogic_Error("BusLogic: Base Address0 0x%X not I/O for " "FlashPoint Host Adapter\n", NULL, BaseAddress0);
+			BusLogic_Error("at PCI Bus %d Device %d I/O Address 0x%X\n", NULL, Bus, Device, IO_Address);
+			continue;
+		}
+		if (pci_resource_flags(PCI_Device, 1) & IORESOURCE_IO) {
+			BusLogic_Error("BusLogic: Base Address1 0x%X not Memory for " "FlashPoint Host Adapter\n", NULL, BaseAddress1);
+			BusLogic_Error("at PCI Bus %d Device %d PCI Address 0x%X\n", NULL, Bus, Device, PCI_Address);
+			continue;
+		}
+		if (IRQ_Channel == 0) {
+			BusLogic_Error("BusLogic: IRQ Channel %d invalid for " "FlashPoint Host Adapter\n", NULL, IRQ_Channel);
+			BusLogic_Error("at PCI Bus %d Device %d I/O Address 0x%X\n", NULL, Bus, Device, IO_Address);
+			continue;
+		}
+		if (BusLogic_GlobalOptions.TraceProbe) {
+			BusLogic_Notice("BusLogic: FlashPoint Host Adapter " "detected at\n", NULL);
+			BusLogic_Notice("BusLogic: PCI Bus %d Device %d I/O Address " "0x%X PCI Address 0x%X\n", NULL, Bus, Device, IO_Address, PCI_Address);
+		}
+		if (BusLogic_ProbeInfoCount < BusLogic_MaxHostAdapters) {
+			struct BusLogic_ProbeInfo *ProbeInfo = &BusLogic_ProbeInfoList[BusLogic_ProbeInfoCount++];
+			ProbeInfo->HostAdapterType = BusLogic_FlashPoint;
+			ProbeInfo->HostAdapterBusType = BusLogic_PCI_Bus;
+			ProbeInfo->IO_Address = IO_Address;
+			ProbeInfo->PCI_Address = PCI_Address;
+			ProbeInfo->Bus = Bus;
+			ProbeInfo->Device = Device;
+			ProbeInfo->IRQ_Channel = IRQ_Channel;
+			ProbeInfo->PCI_Device = PCI_Device;
+			FlashPointCount++;
+		} else
+			BusLogic_Warning("BusLogic: Too many Host Adapters " "detected\n", NULL);
 #else
-      BusLogic_Error("BusLogic: FlashPoint Host Adapter detected at "
-		     "PCI Bus %d Device %d\n", NULL, Bus, Device);
-      BusLogic_Error("BusLogic: I/O Address 0x%X PCI Address 0x%X, irq %d, "
-		     "but FlashPoint\n", NULL, IO_Address, PCI_Address, IRQ_Channel);
-      BusLogic_Error("BusLogic: support was omitted in this kernel "
-		     "configuration.\n", NULL);
+		BusLogic_Error("BusLogic: FlashPoint Host Adapter detected at " "PCI Bus %d Device %d\n", NULL, Bus, Device);
+		BusLogic_Error("BusLogic: I/O Address 0x%X PCI Address 0x%X, irq %d, " "but FlashPoint\n", NULL, IO_Address, PCI_Address, IRQ_Channel);
+		BusLogic_Error("BusLogic: support was omitted in this kernel " "configuration.\n", NULL);
 #endif
-    }
-  /*
-    The FlashPoint BIOS will scan for FlashPoint Host Adapters in the order of
-    increasing PCI Bus and Device Number, so sort the probe information into
-    the same order the BIOS uses.
-  */
-  BusLogic_SortProbeInfo(&BusLogic_ProbeInfoList[FlashPointIndex],
-			 FlashPointCount);
-  return FlashPointCount;
+	}
+	/*
+	   The FlashPoint BIOS will scan for FlashPoint Host Adapters in the order of
+	   increasing PCI Bus and Device Number, so sort the probe information into
+	   the same order the BIOS uses.
+	 */
+	BusLogic_SortProbeInfo(&BusLogic_ProbeInfoList[FlashPointIndex], FlashPointCount);
+	return FlashPointCount;
 }
 
 
@@ -1174,106 +995,70 @@
 static void __init BusLogic_InitializeProbeInfoList(struct BusLogic_HostAdapter
 						    *PrototypeHostAdapter)
 {
-  /*
-    If a PCI BIOS is present, interrogate it for MultiMaster and FlashPoint
-    Host Adapters; otherwise, default to the standard ISA MultiMaster probe.
-  */
-  if (!BusLogic_ProbeOptions.NoProbePCI)
-    {
-      if (BusLogic_ProbeOptions.MultiMasterFirst)
-	{
-	  BusLogic_InitializeMultiMasterProbeInfo(PrototypeHostAdapter);
-	  BusLogic_InitializeFlashPointProbeInfo(PrototypeHostAdapter);
-	}
-      else if (BusLogic_ProbeOptions.FlashPointFirst)
-	{
-	  BusLogic_InitializeFlashPointProbeInfo(PrototypeHostAdapter);
-	  BusLogic_InitializeMultiMasterProbeInfo(PrototypeHostAdapter);
-	}
-      else
-	{
-	  int FlashPointCount =
-	    BusLogic_InitializeFlashPointProbeInfo(PrototypeHostAdapter);
-	  int PCIMultiMasterCount =
-	    BusLogic_InitializeMultiMasterProbeInfo(PrototypeHostAdapter);
-	  if (FlashPointCount > 0 && PCIMultiMasterCount > 0)
-	    {
-	      struct BusLogic_ProbeInfo *ProbeInfo =
-		&BusLogic_ProbeInfoList[FlashPointCount];
-	      struct BusLogic_HostAdapter *HostAdapter = PrototypeHostAdapter;
-	      struct BusLogic_FetchHostAdapterLocalRAMRequest
-		FetchHostAdapterLocalRAMRequest;
-	      struct BusLogic_BIOSDriveMapByte Drive0MapByte;
-	      while (ProbeInfo->HostAdapterBusType != BusLogic_PCI_Bus)
-		ProbeInfo++;
-	      HostAdapter->IO_Address = ProbeInfo->IO_Address;
-	      FetchHostAdapterLocalRAMRequest.ByteOffset =
-		BusLogic_BIOS_BaseOffset + BusLogic_BIOS_DriveMapOffset + 0;
-	      FetchHostAdapterLocalRAMRequest.ByteCount =
-		sizeof(Drive0MapByte);
-	      BusLogic_Command(HostAdapter,
-			       BusLogic_FetchHostAdapterLocalRAM,
-			       &FetchHostAdapterLocalRAMRequest,
-			       sizeof(FetchHostAdapterLocalRAMRequest),
-			       &Drive0MapByte, sizeof(Drive0MapByte));
-	      /*
-		If the Map Byte for BIOS Drive 0 indicates that BIOS Drive 0
-		is controlled by this PCI MultiMaster Host Adapter, then
-		reverse the probe order so that MultiMaster Host Adapters are
-		probed before FlashPoint Host Adapters.
-	      */
-	      if (Drive0MapByte.DiskGeometry !=
-		  BusLogic_BIOS_Disk_Not_Installed)
-		{
-		  struct BusLogic_ProbeInfo
-		    SavedProbeInfo[BusLogic_MaxHostAdapters];
-		  int MultiMasterCount =
-		    BusLogic_ProbeInfoCount - FlashPointCount;
-		  memcpy(SavedProbeInfo,
-			 BusLogic_ProbeInfoList,
-			 BusLogic_ProbeInfoCount
-			 * sizeof(struct BusLogic_ProbeInfo));
-		  memcpy(&BusLogic_ProbeInfoList[0],
-			 &SavedProbeInfo[FlashPointCount],
-			 MultiMasterCount * sizeof(struct BusLogic_ProbeInfo));
-		  memcpy(&BusLogic_ProbeInfoList[MultiMasterCount],
-			 &SavedProbeInfo[0],
-			 FlashPointCount * sizeof(struct BusLogic_ProbeInfo));
+	/*
+	   If a PCI BIOS is present, interrogate it for MultiMaster and FlashPoint
+	   Host Adapters; otherwise, default to the standard ISA MultiMaster probe.
+	 */
+	if (!BusLogic_ProbeOptions.NoProbePCI) {
+		if (BusLogic_ProbeOptions.MultiMasterFirst) {
+			BusLogic_InitializeMultiMasterProbeInfo(PrototypeHostAdapter);
+			BusLogic_InitializeFlashPointProbeInfo(PrototypeHostAdapter);
+		} else if (BusLogic_ProbeOptions.FlashPointFirst) {
+			BusLogic_InitializeFlashPointProbeInfo(PrototypeHostAdapter);
+			BusLogic_InitializeMultiMasterProbeInfo(PrototypeHostAdapter);
+		} else {
+			int FlashPointCount = BusLogic_InitializeFlashPointProbeInfo(PrototypeHostAdapter);
+			int PCIMultiMasterCount = BusLogic_InitializeMultiMasterProbeInfo(PrototypeHostAdapter);
+			if (FlashPointCount > 0 && PCIMultiMasterCount > 0) {
+				struct BusLogic_ProbeInfo *ProbeInfo = &BusLogic_ProbeInfoList[FlashPointCount];
+				struct BusLogic_HostAdapter *HostAdapter = PrototypeHostAdapter;
+				struct BusLogic_FetchHostAdapterLocalRAMRequest FetchHostAdapterLocalRAMRequest;
+				struct BusLogic_BIOSDriveMapByte Drive0MapByte;
+				while (ProbeInfo->HostAdapterBusType != BusLogic_PCI_Bus)
+					ProbeInfo++;
+				HostAdapter->IO_Address = ProbeInfo->IO_Address;
+				FetchHostAdapterLocalRAMRequest.ByteOffset = BusLogic_BIOS_BaseOffset + BusLogic_BIOS_DriveMapOffset + 0;
+				FetchHostAdapterLocalRAMRequest.ByteCount = sizeof(Drive0MapByte);
+				BusLogic_Command(HostAdapter, BusLogic_FetchHostAdapterLocalRAM, &FetchHostAdapterLocalRAMRequest, sizeof(FetchHostAdapterLocalRAMRequest), &Drive0MapByte, sizeof(Drive0MapByte));
+				/*
+				   If the Map Byte for BIOS Drive 0 indicates that BIOS Drive 0
+				   is controlled by this PCI MultiMaster Host Adapter, then
+				   reverse the probe order so that MultiMaster Host Adapters are
+				   probed before FlashPoint Host Adapters.
+				 */
+				if (Drive0MapByte.DiskGeometry != BusLogic_BIOS_Disk_Not_Installed) {
+					struct BusLogic_ProbeInfo SavedProbeInfo[BusLogic_MaxHostAdapters];
+					int MultiMasterCount = BusLogic_ProbeInfoCount - FlashPointCount;
+					memcpy(SavedProbeInfo, BusLogic_ProbeInfoList, BusLogic_ProbeInfoCount * sizeof(struct BusLogic_ProbeInfo));
+					memcpy(&BusLogic_ProbeInfoList[0], &SavedProbeInfo[FlashPointCount], MultiMasterCount * sizeof(struct BusLogic_ProbeInfo));
+					memcpy(&BusLogic_ProbeInfoList[MultiMasterCount], &SavedProbeInfo[0], FlashPointCount * sizeof(struct BusLogic_ProbeInfo));
+				}
+			}
 		}
-	    }
-	}
-    }
-  else BusLogic_InitializeProbeInfoListISA(PrototypeHostAdapter);
+	} else
+		BusLogic_InitializeProbeInfoListISA(PrototypeHostAdapter);
 }
 
 
-#endif  /* CONFIG_PCI */
+#endif				/* CONFIG_PCI */
 
 
 /*
   BusLogic_Failure prints a standardized error message, and then returns false.
 */
 
-static boolean BusLogic_Failure(struct BusLogic_HostAdapter *HostAdapter,
-				char *ErrorMessage)
+static boolean BusLogic_Failure(struct BusLogic_HostAdapter *HostAdapter, char *ErrorMessage)
 {
-  BusLogic_AnnounceDriver(HostAdapter);
-  if (HostAdapter->HostAdapterBusType == BusLogic_PCI_Bus)
-    {
-      BusLogic_Error("While configuring BusLogic PCI Host Adapter at\n",
-		     HostAdapter);
-      BusLogic_Error("Bus %d Device %d I/O Address 0x%X PCI Address 0x%X:\n",
-		     HostAdapter, HostAdapter->Bus, HostAdapter->Device,
-		     HostAdapter->IO_Address, HostAdapter->PCI_Address);
-    }
-  else BusLogic_Error("While configuring BusLogic Host Adapter at "
-		      "I/O Address 0x%X:\n", HostAdapter,
-		      HostAdapter->IO_Address);
-  BusLogic_Error("%s FAILED - DETACHING\n", HostAdapter, ErrorMessage);
-  if (BusLogic_CommandFailureReason != NULL)
-    BusLogic_Error("ADDITIONAL FAILURE INFO - %s\n", HostAdapter,
-		   BusLogic_CommandFailureReason);
-  return false;
+	BusLogic_AnnounceDriver(HostAdapter);
+	if (HostAdapter->HostAdapterBusType == BusLogic_PCI_Bus) {
+		BusLogic_Error("While configuring BusLogic PCI Host Adapter at\n", HostAdapter);
+		BusLogic_Error("Bus %d Device %d I/O Address 0x%X PCI Address 0x%X:\n", HostAdapter, HostAdapter->Bus, HostAdapter->Device, HostAdapter->IO_Address, HostAdapter->PCI_Address);
+	} else
+		BusLogic_Error("While configuring BusLogic Host Adapter at " "I/O Address 0x%X:\n", HostAdapter, HostAdapter->IO_Address);
+	BusLogic_Error("%s FAILED - DETACHING\n", HostAdapter, ErrorMessage);
+	if (BusLogic_CommandFailureReason != NULL)
+		BusLogic_Error("ADDITIONAL FAILURE INFO - %s\n", HostAdapter, BusLogic_CommandFailureReason);
+	return false;
 }
 
 
@@ -1283,81 +1068,64 @@
 
 static boolean __init BusLogic_ProbeHostAdapter(struct BusLogic_HostAdapter *HostAdapter)
 {
-  union BusLogic_StatusRegister StatusRegister;
-  union BusLogic_InterruptRegister InterruptRegister;
-  union BusLogic_GeometryRegister GeometryRegister;
-  /*
-    FlashPoint Host Adapters are Probed by the FlashPoint SCCB Manager.
-  */
-  if (BusLogic_FlashPointHostAdapterP(HostAdapter))
-    {
-      struct FlashPoint_Info *FlashPointInfo = &HostAdapter->FlashPointInfo;
-      FlashPointInfo->BaseAddress =
-	(u32) HostAdapter->IO_Address;
-      FlashPointInfo->IRQ_Channel = HostAdapter->IRQ_Channel;
-      FlashPointInfo->Present = false;
-      if (!(FlashPoint_ProbeHostAdapter(FlashPointInfo) == 0 &&
-	    FlashPointInfo->Present))
-	{
-	  BusLogic_Error("BusLogic: FlashPoint Host Adapter detected at "
-			 "PCI Bus %d Device %d\n", HostAdapter,
-			 HostAdapter->Bus, HostAdapter->Device);
-	  BusLogic_Error("BusLogic: I/O Address 0x%X PCI Address 0x%X, "
-			 "but FlashPoint\n", HostAdapter,
-			 HostAdapter->IO_Address, HostAdapter->PCI_Address);
-	  BusLogic_Error("BusLogic: Probe Function failed to validate it.\n",
-			 HostAdapter);
-	  return false;
-	}
-      if (BusLogic_GlobalOptions.TraceProbe)
-	BusLogic_Notice("BusLogic_Probe(0x%X): FlashPoint Found\n",
-			HostAdapter, HostAdapter->IO_Address);
-      /*
-	Indicate the Host Adapter Probe completed successfully.
-      */
-      return true;
-    }
-  /*
-    Read the Status, Interrupt, and Geometry Registers to test if there are I/O
-    ports that respond, and to check the values to determine if they are from a
-    BusLogic Host Adapter.  A nonexistent I/O port will return 0xFF, in which
-    case there is definitely no BusLogic Host Adapter at this base I/O Address.
-    The test here is a subset of that used by the BusLogic Host Adapter BIOS.
-  */
-  StatusRegister.All = BusLogic_ReadStatusRegister(HostAdapter);
-  InterruptRegister.All = BusLogic_ReadInterruptRegister(HostAdapter);
-  GeometryRegister.All = BusLogic_ReadGeometryRegister(HostAdapter);
-  if (BusLogic_GlobalOptions.TraceProbe)
-    BusLogic_Notice("BusLogic_Probe(0x%X): Status 0x%02X, Interrupt 0x%02X, "
-		    "Geometry 0x%02X\n", HostAdapter,
-		    HostAdapter->IO_Address, StatusRegister.All,
-		    InterruptRegister.All, GeometryRegister.All);
-  if (StatusRegister.All == 0 ||
-      StatusRegister.sr.DiagnosticActive ||
-      StatusRegister.sr.CommandParameterRegisterBusy ||
-      StatusRegister.sr.Reserved ||
-      StatusRegister.sr.CommandInvalid ||
-      InterruptRegister.ir.Reserved != 0)
-    return false;
-  /*
-    Check the undocumented Geometry Register to test if there is an I/O port
-    that responded.  Adaptec Host Adapters do not implement the Geometry
-    Register, so this test helps serve to avoid incorrectly recognizing an
-    Adaptec 1542A or 1542B as a BusLogic.  Unfortunately, the Adaptec 1542C
-    series does respond to the Geometry Register I/O port, but it will be
-    rejected later when the Inquire Extended Setup Information command is
-    issued in BusLogic_CheckHostAdapter.  The AMI FastDisk Host Adapter is a
-    BusLogic clone that implements the same interface as earlier BusLogic
-    Host Adapters, including the undocumented commands, and is therefore
-    supported by this driver.  However, the AMI FastDisk always returns 0x00
-    upon reading the Geometry Register, so the extended translation option
-    should always be left disabled on the AMI FastDisk.
-  */
-  if (GeometryRegister.All == 0xFF) return false;
-  /*
-    Indicate the Host Adapter Probe completed successfully.
-  */
-  return true;
+	union BusLogic_StatusRegister StatusRegister;
+	union BusLogic_InterruptRegister InterruptRegister;
+	union BusLogic_GeometryRegister GeometryRegister;
+	/*
+	   FlashPoint Host Adapters are Probed by the FlashPoint SCCB Manager.
+	 */
+	if (BusLogic_FlashPointHostAdapterP(HostAdapter)) {
+		struct FlashPoint_Info *FlashPointInfo = &HostAdapter->FlashPointInfo;
+		FlashPointInfo->BaseAddress = (u32) HostAdapter->IO_Address;
+		FlashPointInfo->IRQ_Channel = HostAdapter->IRQ_Channel;
+		FlashPointInfo->Present = false;
+		if (!(FlashPoint_ProbeHostAdapter(FlashPointInfo) == 0 && FlashPointInfo->Present)) {
+			BusLogic_Error("BusLogic: FlashPoint Host Adapter detected at " "PCI Bus %d Device %d\n", HostAdapter, HostAdapter->Bus, HostAdapter->Device);
+			BusLogic_Error("BusLogic: I/O Address 0x%X PCI Address 0x%X, " "but FlashPoint\n", HostAdapter, HostAdapter->IO_Address, HostAdapter->PCI_Address);
+			BusLogic_Error("BusLogic: Probe Function failed to validate it.\n", HostAdapter);
+			return false;
+		}
+		if (BusLogic_GlobalOptions.TraceProbe)
+			BusLogic_Notice("BusLogic_Probe(0x%X): FlashPoint Found\n", HostAdapter, HostAdapter->IO_Address);
+		/*
+		   Indicate the Host Adapter Probe completed successfully.
+		 */
+		return true;
+	}
+	/*
+	   Read the Status, Interrupt, and Geometry Registers to test if there are I/O
+	   ports that respond, and to check the values to determine if they are from a
+	   BusLogic Host Adapter.  A nonexistent I/O port will return 0xFF, in which
+	   case there is definitely no BusLogic Host Adapter at this base I/O Address.
+	   The test here is a subset of that used by the BusLogic Host Adapter BIOS.
+	 */
+	StatusRegister.All = BusLogic_ReadStatusRegister(HostAdapter);
+	InterruptRegister.All = BusLogic_ReadInterruptRegister(HostAdapter);
+	GeometryRegister.All = BusLogic_ReadGeometryRegister(HostAdapter);
+	if (BusLogic_GlobalOptions.TraceProbe)
+		BusLogic_Notice("BusLogic_Probe(0x%X): Status 0x%02X, Interrupt 0x%02X, " "Geometry 0x%02X\n", HostAdapter, HostAdapter->IO_Address, StatusRegister.All, InterruptRegister.All, GeometryRegister.All);
+	if (StatusRegister.All == 0 || StatusRegister.sr.DiagnosticActive || StatusRegister.sr.CommandParameterRegisterBusy || StatusRegister.sr.Reserved || StatusRegister.sr.CommandInvalid || InterruptRegister.ir.Reserved != 0)
+		return false;
+	/*
+	   Check the undocumented Geometry Register to test if there is an I/O port
+	   that responded.  Adaptec Host Adapters do not implement the Geometry
+	   Register, so this test helps serve to avoid incorrectly recognizing an
+	   Adaptec 1542A or 1542B as a BusLogic.  Unfortunately, the Adaptec 1542C
+	   series does respond to the Geometry Register I/O port, but it will be
+	   rejected later when the Inquire Extended Setup Information command is
+	   issued in BusLogic_CheckHostAdapter.  The AMI FastDisk Host Adapter is a
+	   BusLogic clone that implements the same interface as earlier BusLogic
+	   Host Adapters, including the undocumented commands, and is therefore
+	   supported by this driver.  However, the AMI FastDisk always returns 0x00
+	   upon reading the Geometry Register, so the extended translation option
+	   should always be left disabled on the AMI FastDisk.
+	 */
+	if (GeometryRegister.All == 0xFF)
+		return false;
+	/*
+	   Indicate the Host Adapter Probe completed successfully.
+	 */
+	return true;
 }
 
 
@@ -1370,113 +1138,101 @@
 */
 
 static boolean BusLogic_HardwareResetHostAdapter(struct BusLogic_HostAdapter
-						   *HostAdapter,
-						 boolean HardReset)
+						 *HostAdapter, boolean HardReset)
 {
-  union BusLogic_StatusRegister StatusRegister;
-  int TimeoutCounter;
-  /*
-    FlashPoint Host Adapters are Hard Reset by the FlashPoint SCCB Manager.
-  */
-  if (BusLogic_FlashPointHostAdapterP(HostAdapter))
-    {
-      struct FlashPoint_Info *FlashPointInfo = &HostAdapter->FlashPointInfo;
-      FlashPointInfo->HostSoftReset = !HardReset;
-      FlashPointInfo->ReportDataUnderrun = true;
-      HostAdapter->CardHandle =
-	FlashPoint_HardwareResetHostAdapter(FlashPointInfo);
-      if (HostAdapter->CardHandle == FlashPoint_BadCardHandle) return false;
-      /*
-	Indicate the Host Adapter Hard Reset completed successfully.
-      */
-      return true;
-    }
-  /*
-    Issue a Hard Reset or Soft Reset Command to the Host Adapter.  The Host
-    Adapter should respond by setting Diagnostic Active in the Status Register.
-  */
-  if (HardReset)
-    BusLogic_HardReset(HostAdapter);
-  else BusLogic_SoftReset(HostAdapter);
-  /*
-    Wait until Diagnostic Active is set in the Status Register.
-  */
-  TimeoutCounter = 5*10000;
-  while (--TimeoutCounter >= 0)
-    {
-      StatusRegister.All = BusLogic_ReadStatusRegister(HostAdapter);
-      if (StatusRegister.sr.DiagnosticActive) break;
-      udelay(100);
-    }
-  if (BusLogic_GlobalOptions.TraceHardwareReset)
-    BusLogic_Notice("BusLogic_HardwareReset(0x%X): Diagnostic Active, "
-		    "Status 0x%02X\n", HostAdapter,
-		    HostAdapter->IO_Address, StatusRegister.All);
-  if (TimeoutCounter < 0) return false;
-  /*
-    Wait 100 microseconds to allow completion of any initial diagnostic
-    activity which might leave the contents of the Status Register
-    unpredictable.
-  */
-  udelay(100);
-  /*
-    Wait until Diagnostic Active is reset in the Status Register.
-  */
-  TimeoutCounter = 10*10000;
-  while (--TimeoutCounter >= 0)
-    {
-      StatusRegister.All = BusLogic_ReadStatusRegister(HostAdapter);
-      if (!StatusRegister.sr.DiagnosticActive) break;
-      udelay(100);
-    }
-  if (BusLogic_GlobalOptions.TraceHardwareReset)
-    BusLogic_Notice("BusLogic_HardwareReset(0x%X): Diagnostic Completed, "
-		    "Status 0x%02X\n", HostAdapter,
-		    HostAdapter->IO_Address, StatusRegister.All);
-  if (TimeoutCounter < 0) return false;
-  /*
-    Wait until at least one of the Diagnostic Failure, Host Adapter Ready,
-    or Data In Register Ready bits is set in the Status Register.
-  */
-  TimeoutCounter = 10000;
-  while (--TimeoutCounter >= 0)
-    {
-      StatusRegister.All = BusLogic_ReadStatusRegister(HostAdapter);
-      if (StatusRegister.sr.DiagnosticFailure ||
-	  StatusRegister.sr.HostAdapterReady ||
-	  StatusRegister.sr.DataInRegisterReady)
-	break;
-      udelay(100);
-    }
-  if (BusLogic_GlobalOptions.TraceHardwareReset)
-    BusLogic_Notice("BusLogic_HardwareReset(0x%X): Host Adapter Ready, "
-		    "Status 0x%02X\n", HostAdapter,
-		    HostAdapter->IO_Address, StatusRegister.All);
-  if (TimeoutCounter < 0) return false;
-  /*
-    If Diagnostic Failure is set or Host Adapter Ready is reset, then an
-    error occurred during the Host Adapter diagnostics.  If Data In Register
-    Ready is set, then there is an Error Code available.
-  */
-  if (StatusRegister.sr.DiagnosticFailure ||
-      !StatusRegister.sr.HostAdapterReady)
-    {
-      BusLogic_CommandFailureReason = NULL;
-      BusLogic_Failure(HostAdapter, "HARD RESET DIAGNOSTICS");
-      BusLogic_Error("HOST ADAPTER STATUS REGISTER = %02X\n",
-		     HostAdapter, StatusRegister.All);
-      if (StatusRegister.sr.DataInRegisterReady)
-	{
-	  unsigned char ErrorCode = BusLogic_ReadDataInRegister(HostAdapter);
-	  BusLogic_Error("HOST ADAPTER ERROR CODE = %d\n",
-			 HostAdapter, ErrorCode);
-	}
-      return false;
-    }
-  /*
-    Indicate the Host Adapter Hard Reset completed successfully.
-  */
-  return true;
+	union BusLogic_StatusRegister StatusRegister;
+	int TimeoutCounter;
+	/*
+	   FlashPoint Host Adapters are Hard Reset by the FlashPoint SCCB Manager.
+	 */
+	if (BusLogic_FlashPointHostAdapterP(HostAdapter)) {
+		struct FlashPoint_Info *FlashPointInfo = &HostAdapter->FlashPointInfo;
+		FlashPointInfo->HostSoftReset = !HardReset;
+		FlashPointInfo->ReportDataUnderrun = true;
+		HostAdapter->CardHandle = FlashPoint_HardwareResetHostAdapter(FlashPointInfo);
+		if (HostAdapter->CardHandle == FlashPoint_BadCardHandle)
+			return false;
+		/*
+		   Indicate the Host Adapter Hard Reset completed successfully.
+		 */
+		return true;
+	}
+	/*
+	   Issue a Hard Reset or Soft Reset Command to the Host Adapter.  The Host
+	   Adapter should respond by setting Diagnostic Active in the Status Register.
+	 */
+	if (HardReset)
+		BusLogic_HardReset(HostAdapter);
+	else
+		BusLogic_SoftReset(HostAdapter);
+	/*
+	   Wait until Diagnostic Active is set in the Status Register.
+	 */
+	TimeoutCounter = 5 * 10000;
+	while (--TimeoutCounter >= 0) {
+		StatusRegister.All = BusLogic_ReadStatusRegister(HostAdapter);
+		if (StatusRegister.sr.DiagnosticActive)
+			break;
+		udelay(100);
+	}
+	if (BusLogic_GlobalOptions.TraceHardwareReset)
+		BusLogic_Notice("BusLogic_HardwareReset(0x%X): Diagnostic Active, " "Status 0x%02X\n", HostAdapter, HostAdapter->IO_Address, StatusRegister.All);
+	if (TimeoutCounter < 0)
+		return false;
+	/*
+	   Wait 100 microseconds to allow completion of any initial diagnostic
+	   activity which might leave the contents of the Status Register
+	   unpredictable.
+	 */
+	udelay(100);
+	/*
+	   Wait until Diagnostic Active is reset in the Status Register.
+	 */
+	TimeoutCounter = 10 * 10000;
+	while (--TimeoutCounter >= 0) {
+		StatusRegister.All = BusLogic_ReadStatusRegister(HostAdapter);
+		if (!StatusRegister.sr.DiagnosticActive)
+			break;
+		udelay(100);
+	}
+	if (BusLogic_GlobalOptions.TraceHardwareReset)
+		BusLogic_Notice("BusLogic_HardwareReset(0x%X): Diagnostic Completed, " "Status 0x%02X\n", HostAdapter, HostAdapter->IO_Address, StatusRegister.All);
+	if (TimeoutCounter < 0)
+		return false;
+	/*
+	   Wait until at least one of the Diagnostic Failure, Host Adapter Ready,
+	   or Data In Register Ready bits is set in the Status Register.
+	 */
+	TimeoutCounter = 10000;
+	while (--TimeoutCounter >= 0) {
+		StatusRegister.All = BusLogic_ReadStatusRegister(HostAdapter);
+		if (StatusRegister.sr.DiagnosticFailure || StatusRegister.sr.HostAdapterReady || StatusRegister.sr.DataInRegisterReady)
+			break;
+		udelay(100);
+	}
+	if (BusLogic_GlobalOptions.TraceHardwareReset)
+		BusLogic_Notice("BusLogic_HardwareReset(0x%X): Host Adapter Ready, " "Status 0x%02X\n", HostAdapter, HostAdapter->IO_Address, StatusRegister.All);
+	if (TimeoutCounter < 0)
+		return false;
+	/*
+	   If Diagnostic Failure is set or Host Adapter Ready is reset, then an
+	   error occurred during the Host Adapter diagnostics.  If Data In Register
+	   Ready is set, then there is an Error Code available.
+	 */
+	if (StatusRegister.sr.DiagnosticFailure || !StatusRegister.sr.HostAdapterReady) {
+		BusLogic_CommandFailureReason = NULL;
+		BusLogic_Failure(HostAdapter, "HARD RESET DIAGNOSTICS");
+		BusLogic_Error("HOST ADAPTER STATUS REGISTER = %02X\n", HostAdapter, StatusRegister.All);
+		if (StatusRegister.sr.DataInRegisterReady) {
+			unsigned char ErrorCode = BusLogic_ReadDataInRegister(HostAdapter);
+			BusLogic_Error("HOST ADAPTER ERROR CODE = %d\n", HostAdapter, ErrorCode);
+		}
+		return false;
+	}
+	/*
+	   Indicate the Host Adapter Hard Reset completed successfully.
+	 */
+	return true;
 }
 
 
@@ -1487,35 +1243,30 @@
 
 static boolean __init BusLogic_CheckHostAdapter(struct BusLogic_HostAdapter *HostAdapter)
 {
-  struct BusLogic_ExtendedSetupInformation ExtendedSetupInformation;
-  unsigned char RequestedReplyLength;
-  boolean Result = true;
-  /*
-    FlashPoint Host Adapters do not require this protection.
-  */
-  if (BusLogic_FlashPointHostAdapterP(HostAdapter)) return true;
-  /*
-    Issue the Inquire Extended Setup Information command.  Only genuine
-    BusLogic Host Adapters and true clones support this command.  Adaptec 1542C
-    series Host Adapters that respond to the Geometry Register I/O port will
-    fail this command.
-  */
-  RequestedReplyLength = sizeof(ExtendedSetupInformation);
-  if (BusLogic_Command(HostAdapter,
-		       BusLogic_InquireExtendedSetupInformation,
-		       &RequestedReplyLength,
-		       sizeof(RequestedReplyLength),
-		       &ExtendedSetupInformation,
-		       sizeof(ExtendedSetupInformation))
-      != sizeof(ExtendedSetupInformation))
-    Result = false;
-  /*
-    Provide tracing information if requested and return.
-  */
-  if (BusLogic_GlobalOptions.TraceProbe)
-    BusLogic_Notice("BusLogic_Check(0x%X): MultiMaster %s\n", HostAdapter,
-		    HostAdapter->IO_Address, (Result ? "Found" : "Not Found"));
-  return Result;
+	struct BusLogic_ExtendedSetupInformation ExtendedSetupInformation;
+	unsigned char RequestedReplyLength;
+	boolean Result = true;
+	/*
+	   FlashPoint Host Adapters do not require this protection.
+	 */
+	if (BusLogic_FlashPointHostAdapterP(HostAdapter))
+		return true;
+	/*
+	   Issue the Inquire Extended Setup Information command.  Only genuine
+	   BusLogic Host Adapters and true clones support this command.  Adaptec 1542C
+	   series Host Adapters that respond to the Geometry Register I/O port will
+	   fail this command.
+	 */
+	RequestedReplyLength = sizeof(ExtendedSetupInformation);
+	if (BusLogic_Command(HostAdapter, BusLogic_InquireExtendedSetupInformation, &RequestedReplyLength, sizeof(RequestedReplyLength), &ExtendedSetupInformation, sizeof(ExtendedSetupInformation))
+	    != sizeof(ExtendedSetupInformation))
+		Result = false;
+	/*
+	   Provide tracing information if requested and return.
+	 */
+	if (BusLogic_GlobalOptions.TraceProbe)
+		BusLogic_Notice("BusLogic_Check(0x%X): MultiMaster %s\n", HostAdapter, HostAdapter->IO_Address, (Result ? "Found" : "Not Found"));
+	return Result;
 }
 
 
@@ -1527,513 +1278,442 @@
 static boolean __init BusLogic_ReadHostAdapterConfiguration(struct BusLogic_HostAdapter
 							    *HostAdapter)
 {
-  struct BusLogic_BoardID BoardID;
-  struct BusLogic_Configuration Configuration;
-  struct BusLogic_SetupInformation SetupInformation;
-  struct BusLogic_ExtendedSetupInformation ExtendedSetupInformation;
-  unsigned char HostAdapterModelNumber[5];
-  unsigned char FirmwareVersion3rdDigit;
-  unsigned char FirmwareVersionLetter;
-  struct BusLogic_PCIHostAdapterInformation PCIHostAdapterInformation;
-  struct BusLogic_FetchHostAdapterLocalRAMRequest FetchHostAdapterLocalRAMRequest;
-  struct BusLogic_AutoSCSIData AutoSCSIData;
-  union BusLogic_GeometryRegister GeometryRegister;
-  unsigned char RequestedReplyLength;
-  unsigned char *TargetPointer, Character;
-  int TargetID, i;
-  /*
-    Configuration Information for FlashPoint Host Adapters is provided in the
-    FlashPoint_Info structure by the FlashPoint SCCB Manager's Probe Function.
-    Initialize fields in the Host Adapter structure from the FlashPoint_Info
-    structure.
-  */
-  if (BusLogic_FlashPointHostAdapterP(HostAdapter))
-    {
-      struct FlashPoint_Info *FlashPointInfo = &HostAdapter->FlashPointInfo;
-      TargetPointer = HostAdapter->ModelName;
-      *TargetPointer++ = 'B';
-      *TargetPointer++ = 'T';
-      *TargetPointer++ = '-';
-      for (i = 0; i < sizeof(FlashPointInfo->ModelNumber); i++)
-	*TargetPointer++ = FlashPointInfo->ModelNumber[i];
-      *TargetPointer++ = '\0';
-      strcpy(HostAdapter->FirmwareVersion, FlashPoint_FirmwareVersion);
-      HostAdapter->SCSI_ID = FlashPointInfo->SCSI_ID;
-      HostAdapter->ExtendedTranslationEnabled =
-	FlashPointInfo->ExtendedTranslationEnabled;
-      HostAdapter->ParityCheckingEnabled =
-	FlashPointInfo->ParityCheckingEnabled;
-      HostAdapter->BusResetEnabled = !FlashPointInfo->HostSoftReset;
-      HostAdapter->LevelSensitiveInterrupt = true;
-      HostAdapter->HostWideSCSI = FlashPointInfo->HostWideSCSI;
-      HostAdapter->HostDifferentialSCSI = false;
-      HostAdapter->HostSupportsSCAM = true;
-      HostAdapter->HostUltraSCSI = true;
-      HostAdapter->ExtendedLUNSupport = true;
-      HostAdapter->TerminationInfoValid = true;
-      HostAdapter->LowByteTerminated = FlashPointInfo->LowByteTerminated;
-      HostAdapter->HighByteTerminated = FlashPointInfo->HighByteTerminated;
-      HostAdapter->SCAM_Enabled = FlashPointInfo->SCAM_Enabled;
-      HostAdapter->SCAM_Level2 = FlashPointInfo->SCAM_Level2;
-      HostAdapter->DriverScatterGatherLimit = BusLogic_ScatterGatherLimit;
-      HostAdapter->MaxTargetDevices = (HostAdapter->HostWideSCSI ? 16 : 8);
-      HostAdapter->MaxLogicalUnits = 32;
-      HostAdapter->InitialCCBs = 4 * BusLogic_CCB_AllocationGroupSize;
-      HostAdapter->IncrementalCCBs = BusLogic_CCB_AllocationGroupSize;
-      HostAdapter->DriverQueueDepth = 255;
-      HostAdapter->HostAdapterQueueDepth = HostAdapter->DriverQueueDepth;
-      HostAdapter->SynchronousPermitted = FlashPointInfo->SynchronousPermitted;
-      HostAdapter->FastPermitted = FlashPointInfo->FastPermitted;
-      HostAdapter->UltraPermitted = FlashPointInfo->UltraPermitted;
-      HostAdapter->WidePermitted = FlashPointInfo->WidePermitted;
-      HostAdapter->DisconnectPermitted = FlashPointInfo->DisconnectPermitted;
-      HostAdapter->TaggedQueuingPermitted = 0xFFFF;
-      goto Common;
-    }
-  /*
-    Issue the Inquire Board ID command.
-  */
-  if (BusLogic_Command(HostAdapter, BusLogic_InquireBoardID, NULL, 0,
-		       &BoardID, sizeof(BoardID)) != sizeof(BoardID))
-    return BusLogic_Failure(HostAdapter, "INQUIRE BOARD ID");
-  /*
-    Issue the Inquire Configuration command.
-  */
-  if (BusLogic_Command(HostAdapter, BusLogic_InquireConfiguration, NULL, 0,
-		       &Configuration, sizeof(Configuration))
-      != sizeof(Configuration))
-    return BusLogic_Failure(HostAdapter, "INQUIRE CONFIGURATION");
-  /*
-    Issue the Inquire Setup Information command.
-  */
-  RequestedReplyLength = sizeof(SetupInformation);
-  if (BusLogic_Command(HostAdapter, BusLogic_InquireSetupInformation,
-		       &RequestedReplyLength, sizeof(RequestedReplyLength),
-		       &SetupInformation, sizeof(SetupInformation))
-      != sizeof(SetupInformation))
-    return BusLogic_Failure(HostAdapter, "INQUIRE SETUP INFORMATION");
-  /*
-    Issue the Inquire Extended Setup Information command.
-  */
-  RequestedReplyLength = sizeof(ExtendedSetupInformation);
-  if (BusLogic_Command(HostAdapter, BusLogic_InquireExtendedSetupInformation,
-		       &RequestedReplyLength, sizeof(RequestedReplyLength),
-		       &ExtendedSetupInformation,
-		       sizeof(ExtendedSetupInformation))
-      != sizeof(ExtendedSetupInformation))
-    return BusLogic_Failure(HostAdapter, "INQUIRE EXTENDED SETUP INFORMATION");
-  /*
-    Issue the Inquire Firmware Version 3rd Digit command.
-  */
-  FirmwareVersion3rdDigit = '\0';
-  if (BoardID.FirmwareVersion1stDigit > '0')
-    if (BusLogic_Command(HostAdapter, BusLogic_InquireFirmwareVersion3rdDigit,
-			 NULL, 0, &FirmwareVersion3rdDigit,
-			 sizeof(FirmwareVersion3rdDigit))
-	!= sizeof(FirmwareVersion3rdDigit))
-      return BusLogic_Failure(HostAdapter, "INQUIRE FIRMWARE 3RD DIGIT");
-  /*
-    Issue the Inquire Host Adapter Model Number command.
-  */
-  if (ExtendedSetupInformation.BusType == 'A' &&
-      BoardID.FirmwareVersion1stDigit == '2')
-    /* BusLogic BT-542B ISA 2.xx */
-    strcpy(HostAdapterModelNumber, "542B");
-  else if (ExtendedSetupInformation.BusType == 'E' &&
-	   BoardID.FirmwareVersion1stDigit == '2' &&
-	   (BoardID.FirmwareVersion2ndDigit <= '1' ||
-	    (BoardID.FirmwareVersion2ndDigit == '2' &&
-	     FirmwareVersion3rdDigit == '0')))
-    /* BusLogic BT-742A EISA 2.1x or 2.20 */
-    strcpy(HostAdapterModelNumber, "742A");
-  else if (ExtendedSetupInformation.BusType == 'E' &&
-	   BoardID.FirmwareVersion1stDigit == '0')
-    /* AMI FastDisk EISA Series 441 0.x */
-    strcpy(HostAdapterModelNumber, "747A");
-  else
-    {
-      RequestedReplyLength = sizeof(HostAdapterModelNumber);
-      if (BusLogic_Command(HostAdapter, BusLogic_InquireHostAdapterModelNumber,
-			   &RequestedReplyLength, sizeof(RequestedReplyLength),
-			   &HostAdapterModelNumber,
-			   sizeof(HostAdapterModelNumber))
-	  != sizeof(HostAdapterModelNumber))
-	return BusLogic_Failure(HostAdapter,
-				"INQUIRE HOST ADAPTER MODEL NUMBER");
-    }
-  /*
-    BusLogic MultiMaster Host Adapters can be identified by their model number
-    and the major version number of their firmware as follows:
-
-    5.xx	BusLogic "W" Series Host Adapters:
-		  BT-948/958/958D
-    4.xx	BusLogic "C" Series Host Adapters:
-		  BT-946C/956C/956CD/747C/757C/757CD/445C/545C/540CF
-    3.xx	BusLogic "S" Series Host Adapters:
-		  BT-747S/747D/757S/757D/445S/545S/542D
-		  BT-542B/742A (revision H)
-    2.xx	BusLogic "A" Series Host Adapters:
-		  BT-542B/742A (revision G and below)
-    0.xx	AMI FastDisk VLB/EISA BusLogic Clone Host Adapter
-  */
-  /*
-    Save the Model Name and Host Adapter Name in the Host Adapter structure.
-  */
-  TargetPointer = HostAdapter->ModelName;
-  *TargetPointer++ = 'B';
-  *TargetPointer++ = 'T';
-  *TargetPointer++ = '-';
-  for (i = 0; i < sizeof(HostAdapterModelNumber); i++)
-    {
-      Character = HostAdapterModelNumber[i];
-      if (Character == ' ' || Character == '\0') break;
-      *TargetPointer++ = Character;
-    }
-  *TargetPointer++ = '\0';
-  /*
-    Save the Firmware Version in the Host Adapter structure.
-  */
-  TargetPointer = HostAdapter->FirmwareVersion;
-  *TargetPointer++ = BoardID.FirmwareVersion1stDigit;
-  *TargetPointer++ = '.';
-  *TargetPointer++ = BoardID.FirmwareVersion2ndDigit;
-  if (FirmwareVersion3rdDigit != ' ' && FirmwareVersion3rdDigit != '\0')
-    *TargetPointer++ = FirmwareVersion3rdDigit;
-  *TargetPointer = '\0';
-  /*
-    Issue the Inquire Firmware Version Letter command.
-  */
-  if (strcmp(HostAdapter->FirmwareVersion, "3.3") >= 0)
-    {
-      if (BusLogic_Command(HostAdapter, BusLogic_InquireFirmwareVersionLetter,
-			   NULL, 0, &FirmwareVersionLetter,
-			   sizeof(FirmwareVersionLetter))
-	  != sizeof(FirmwareVersionLetter))
-	return BusLogic_Failure(HostAdapter,
-				"INQUIRE FIRMWARE VERSION LETTER");
-      if (FirmwareVersionLetter != ' ' && FirmwareVersionLetter != '\0')
-	*TargetPointer++ = FirmwareVersionLetter;
-      *TargetPointer = '\0';
-    }
-  /*
-    Save the Host Adapter SCSI ID in the Host Adapter structure.
-  */
-  HostAdapter->SCSI_ID = Configuration.HostAdapterID;
-  /*
-    Determine the Bus Type and save it in the Host Adapter structure, determine
-    and save the IRQ Channel if necessary, and determine and save the DMA
-    Channel for ISA Host Adapters.
-  */
-  HostAdapter->HostAdapterBusType =
-    BusLogic_HostAdapterBusTypes[HostAdapter->ModelName[3] - '4'];
-  if (HostAdapter->IRQ_Channel == 0)
-    {
-      if (Configuration.IRQ_Channel9)
-	HostAdapter->IRQ_Channel = 9;
-      else if (Configuration.IRQ_Channel10)
-	HostAdapter->IRQ_Channel = 10;
-      else if (Configuration.IRQ_Channel11)
-	HostAdapter->IRQ_Channel = 11;
-      else if (Configuration.IRQ_Channel12)
-	HostAdapter->IRQ_Channel = 12;
-      else if (Configuration.IRQ_Channel14)
-	HostAdapter->IRQ_Channel = 14;
-      else if (Configuration.IRQ_Channel15)
-	HostAdapter->IRQ_Channel = 15;
-    }
-  if (HostAdapter->HostAdapterBusType == BusLogic_ISA_Bus)
-    {
-      if (Configuration.DMA_Channel5)
-	HostAdapter->DMA_Channel = 5;
-      else if (Configuration.DMA_Channel6)
-	HostAdapter->DMA_Channel = 6;
-      else if (Configuration.DMA_Channel7)
-	HostAdapter->DMA_Channel = 7;
-    }
-  /*
-    Determine whether Extended Translation is enabled and save it in
-    the Host Adapter structure.
-  */
-  GeometryRegister.All = BusLogic_ReadGeometryRegister(HostAdapter);
-  HostAdapter->ExtendedTranslationEnabled =
-    GeometryRegister.gr.ExtendedTranslationEnabled;
-  /*
-    Save the Scatter Gather Limits, Level Sensitive Interrupt flag, Wide
-    SCSI flag, Differential SCSI flag, SCAM Supported flag, and
-    Ultra SCSI flag in the Host Adapter structure.
-  */
-  HostAdapter->HostAdapterScatterGatherLimit =
-    ExtendedSetupInformation.ScatterGatherLimit;
-  HostAdapter->DriverScatterGatherLimit =
-    HostAdapter->HostAdapterScatterGatherLimit;
-  if (HostAdapter->HostAdapterScatterGatherLimit > BusLogic_ScatterGatherLimit)
-    HostAdapter->DriverScatterGatherLimit = BusLogic_ScatterGatherLimit;
-  if (ExtendedSetupInformation.Misc.LevelSensitiveInterrupt)
-    HostAdapter->LevelSensitiveInterrupt = true;
-  HostAdapter->HostWideSCSI = ExtendedSetupInformation.HostWideSCSI;
-  HostAdapter->HostDifferentialSCSI =
-    ExtendedSetupInformation.HostDifferentialSCSI;
-  HostAdapter->HostSupportsSCAM = ExtendedSetupInformation.HostSupportsSCAM;
-  HostAdapter->HostUltraSCSI = ExtendedSetupInformation.HostUltraSCSI;
-  /*
-    Determine whether Extended LUN Format CCBs are supported and save the
-    information in the Host Adapter structure.
-  */
-  if (HostAdapter->FirmwareVersion[0] == '5' ||
-      (HostAdapter->FirmwareVersion[0] == '4' && HostAdapter->HostWideSCSI))
-    HostAdapter->ExtendedLUNSupport = true;
-  /*
-    Issue the Inquire PCI Host Adapter Information command to read the
-    Termination Information from "W" series MultiMaster Host Adapters.
-  */
-  if (HostAdapter->FirmwareVersion[0] == '5')
-    {
-      if (BusLogic_Command(HostAdapter,
-			   BusLogic_InquirePCIHostAdapterInformation,
-			   NULL, 0, &PCIHostAdapterInformation,
-			   sizeof(PCIHostAdapterInformation))
-	  != sizeof(PCIHostAdapterInformation))
-	return BusLogic_Failure(HostAdapter,
-				"INQUIRE PCI HOST ADAPTER INFORMATION");
-      /*
-	Save the Termination Information in the Host Adapter structure.
-      */
-      if (PCIHostAdapterInformation.GenericInfoValid)
-	{
-	  HostAdapter->TerminationInfoValid = true;
-	  HostAdapter->LowByteTerminated =
-	    PCIHostAdapterInformation.LowByteTerminated;
-	  HostAdapter->HighByteTerminated =
-	    PCIHostAdapterInformation.HighByteTerminated;
-	}
-    }
-  /*
-    Issue the Fetch Host Adapter Local RAM command to read the AutoSCSI data
-    from "W" and "C" series MultiMaster Host Adapters.
-  */
-  if (HostAdapter->FirmwareVersion[0] >= '4')
-    {
-      FetchHostAdapterLocalRAMRequest.ByteOffset =
-	BusLogic_AutoSCSI_BaseOffset;
-      FetchHostAdapterLocalRAMRequest.ByteCount = sizeof(AutoSCSIData);
-      if (BusLogic_Command(HostAdapter,
-			   BusLogic_FetchHostAdapterLocalRAM,
-			   &FetchHostAdapterLocalRAMRequest,
-			   sizeof(FetchHostAdapterLocalRAMRequest),
-			   &AutoSCSIData, sizeof(AutoSCSIData))
-	  != sizeof(AutoSCSIData))
-	return BusLogic_Failure(HostAdapter, "FETCH HOST ADAPTER LOCAL RAM");
-      /*
-	Save the Parity Checking Enabled, Bus Reset Enabled, and Termination
-	Information in the Host Adapter structure.
-      */
-      HostAdapter->ParityCheckingEnabled = AutoSCSIData.ParityCheckingEnabled;
-      HostAdapter->BusResetEnabled = AutoSCSIData.BusResetEnabled;
-      if (HostAdapter->FirmwareVersion[0] == '4')
-	{
-	  HostAdapter->TerminationInfoValid = true;
-	  HostAdapter->LowByteTerminated = AutoSCSIData.LowByteTerminated;
-	  HostAdapter->HighByteTerminated = AutoSCSIData.HighByteTerminated;
-	}
-      /*
-	Save the Wide Permitted, Fast Permitted, Synchronous Permitted,
-	Disconnect Permitted, Ultra Permitted, and SCAM Information in the
-	Host Adapter structure.
-      */
-      HostAdapter->WidePermitted = AutoSCSIData.WidePermitted;
-      HostAdapter->FastPermitted = AutoSCSIData.FastPermitted;
-      HostAdapter->SynchronousPermitted =
-	AutoSCSIData.SynchronousPermitted;
-      HostAdapter->DisconnectPermitted =
-	AutoSCSIData.DisconnectPermitted;
-      if (HostAdapter->HostUltraSCSI)
-	HostAdapter->UltraPermitted = AutoSCSIData.UltraPermitted;
-      if (HostAdapter->HostSupportsSCAM)
-	{
-	  HostAdapter->SCAM_Enabled = AutoSCSIData.SCAM_Enabled;
-	  HostAdapter->SCAM_Level2 = AutoSCSIData.SCAM_Level2;
-	}
-    }
-  /*
-    Initialize fields in the Host Adapter structure for "S" and "A" series
-    MultiMaster Host Adapters.
-  */
-  if (HostAdapter->FirmwareVersion[0] < '4')
-    {
-      if (SetupInformation.SynchronousInitiationEnabled)
-	{
-	  HostAdapter->SynchronousPermitted = 0xFF;
-	  if (HostAdapter->HostAdapterBusType == BusLogic_EISA_Bus)
-	    {
-	      if (ExtendedSetupInformation.Misc.FastOnEISA)
-		HostAdapter->FastPermitted = 0xFF;
-	      if (strcmp(HostAdapter->ModelName, "BT-757") == 0)
-		HostAdapter->WidePermitted = 0xFF;
-	    }
-	}
-      HostAdapter->DisconnectPermitted = 0xFF;
-      HostAdapter->ParityCheckingEnabled =
-	SetupInformation.ParityCheckingEnabled;
-      HostAdapter->BusResetEnabled = true;
-    }
-  /*
-    Determine the maximum number of Target IDs and Logical Units supported by
-    this driver for Wide and Narrow Host Adapters.
-  */
-  HostAdapter->MaxTargetDevices = (HostAdapter->HostWideSCSI ? 16 : 8);
-  HostAdapter->MaxLogicalUnits = (HostAdapter->ExtendedLUNSupport ? 32 : 8);
-  /*
-    Select appropriate values for the Mailbox Count, Driver Queue Depth,
-    Initial CCBs, and Incremental CCBs variables based on whether or not Strict
-    Round Robin Mode is supported.  If Strict Round Robin Mode is supported,
-    then there is no performance degradation in using the maximum possible
-    number of Outgoing and Incoming Mailboxes and allowing the Tagged and
-    Untagged Queue Depths to determine the actual utilization.  If Strict Round
-    Robin Mode is not supported, then the Host Adapter must scan all the
-    Outgoing Mailboxes whenever an Outgoing Mailbox entry is made, which can
-    cause a substantial performance penalty.  The host adapters actually have
-    room to store the following number of CCBs internally; that is, they can
-    internally queue and manage this many active commands on the SCSI bus
-    simultaneously.  Performance measurements demonstrate that the Driver Queue
-    Depth should be set to the Mailbox Count, rather than the Host Adapter
-    Queue Depth (internal CCB capacity), as it is more efficient to have the
-    queued commands waiting in Outgoing Mailboxes if necessary than to block
-    the process in the higher levels of the SCSI Subsystem.
-
-	192	  BT-948/958/958D
-	100	  BT-946C/956C/956CD/747C/757C/757CD/445C
-	 50	  BT-545C/540CF
-	 30	  BT-747S/747D/757S/757D/445S/545S/542D/542B/742A
-  */
-  if (HostAdapter->FirmwareVersion[0] == '5')
-    HostAdapter->HostAdapterQueueDepth = 192;
-  else if (HostAdapter->FirmwareVersion[0] == '4')
-    HostAdapter->HostAdapterQueueDepth =
-      (HostAdapter->HostAdapterBusType != BusLogic_ISA_Bus ? 100 : 50);
-  else HostAdapter->HostAdapterQueueDepth = 30;
-  if (strcmp(HostAdapter->FirmwareVersion, "3.31") >= 0)
-    {
-      HostAdapter->StrictRoundRobinModeSupport = true;
-      HostAdapter->MailboxCount = BusLogic_MaxMailboxes;
-    }
-  else
-    {
-      HostAdapter->StrictRoundRobinModeSupport = false;
-      HostAdapter->MailboxCount = 32;
-    }
-  HostAdapter->DriverQueueDepth = HostAdapter->MailboxCount;
-  HostAdapter->InitialCCBs = 4 * BusLogic_CCB_AllocationGroupSize;
-  HostAdapter->IncrementalCCBs = BusLogic_CCB_AllocationGroupSize;
-  /*
-    Tagged Queuing support is available and operates properly on all "W" series
-    MultiMaster Host Adapters, on "C" series MultiMaster Host Adapters with
-    firmware version 4.22 and above, and on "S" series MultiMaster Host
-    Adapters with firmware version 3.35 and above.
-  */
-  HostAdapter->TaggedQueuingPermitted = 0;
-  switch (HostAdapter->FirmwareVersion[0])
-    {
-    case '5':
-      HostAdapter->TaggedQueuingPermitted = 0xFFFF;
-      break;
-    case '4':
-      if (strcmp(HostAdapter->FirmwareVersion, "4.22") >= 0)
-	HostAdapter->TaggedQueuingPermitted = 0xFFFF;
-      break;
-    case '3':
-      if (strcmp(HostAdapter->FirmwareVersion, "3.35") >= 0)
-	HostAdapter->TaggedQueuingPermitted = 0xFFFF;
-      break;
-    }
-  /*
-    Determine the Host Adapter BIOS Address if the BIOS is enabled and
-    save it in the Host Adapter structure.  The BIOS is disabled if the
-    BIOS_Address is 0.
-  */
-  HostAdapter->BIOS_Address = ExtendedSetupInformation.BIOS_Address << 12;
-  /*
-    ISA Host Adapters require Bounce Buffers if there is more than 16MB memory.
-  */
-  if (HostAdapter->HostAdapterBusType == BusLogic_ISA_Bus &&
-      (void *) high_memory > (void *) MAX_DMA_ADDRESS)
-    HostAdapter->BounceBuffersRequired = true;
-  /*
-    BusLogic BT-445S Host Adapters prior to board revision E have a hardware
-    bug whereby when the BIOS is enabled, transfers to/from the same address
-    range the BIOS occupies modulo 16MB are handled incorrectly.  Only properly
-    functioning BT-445S Host Adapters have firmware version 3.37, so require
-    that ISA Bounce Buffers be used for the buggy BT-445S models if there is
-    more than 16MB memory.
-  */
-  if (HostAdapter->BIOS_Address > 0 &&
-      strcmp(HostAdapter->ModelName, "BT-445S") == 0 &&
-      strcmp(HostAdapter->FirmwareVersion, "3.37") < 0 &&
-      (void *) high_memory > (void *) MAX_DMA_ADDRESS)
-    HostAdapter->BounceBuffersRequired = true;
-  /*
-    Initialize parameters common to MultiMaster and FlashPoint Host Adapters.
-  */
-Common:
-  /*
-    Initialize the Host Adapter Full Model Name from the Model Name.
-  */
-  strcpy(HostAdapter->FullModelName, "BusLogic ");
-  strcat(HostAdapter->FullModelName, HostAdapter->ModelName);
-  /*
-    Select an appropriate value for the Tagged Queue Depth either from a
-    BusLogic Driver Options specification, or based on whether this Host
-    Adapter requires that ISA Bounce Buffers be used.  The Tagged Queue Depth
-    is left at 0 for automatic determination in BusLogic_SelectQueueDepths.
-    Initialize the Untagged Queue Depth.
-  */
-  for (TargetID = 0; TargetID < BusLogic_MaxTargetDevices; TargetID++)
-    {
-      unsigned char QueueDepth = 0;
-      if (HostAdapter->DriverOptions != NULL &&
-	  HostAdapter->DriverOptions->QueueDepth[TargetID] > 0)
-	QueueDepth = HostAdapter->DriverOptions->QueueDepth[TargetID];
-      else if (HostAdapter->BounceBuffersRequired)
-	QueueDepth = BusLogic_TaggedQueueDepthBB;
-      HostAdapter->QueueDepth[TargetID] = QueueDepth;
-    }
-  if (HostAdapter->BounceBuffersRequired)
-    HostAdapter->UntaggedQueueDepth = BusLogic_UntaggedQueueDepthBB;
-  else HostAdapter->UntaggedQueueDepth = BusLogic_UntaggedQueueDepth;
-  if (HostAdapter->DriverOptions != NULL)
-    HostAdapter->CommonQueueDepth =
-      HostAdapter->DriverOptions->CommonQueueDepth;
-  if (HostAdapter->CommonQueueDepth > 0 &&
-      HostAdapter->CommonQueueDepth < HostAdapter->UntaggedQueueDepth)
-    HostAdapter->UntaggedQueueDepth = HostAdapter->CommonQueueDepth;
-  /*
-    Tagged Queuing is only allowed if Disconnect/Reconnect is permitted.
-    Therefore, mask the Tagged Queuing Permitted Default bits with the
-    Disconnect/Reconnect Permitted bits.
-  */
-  HostAdapter->TaggedQueuingPermitted &= HostAdapter->DisconnectPermitted;
-  /*
-    Combine the default Tagged Queuing Permitted bits with any BusLogic Driver
-    Options Tagged Queuing specification.
-  */
-  if (HostAdapter->DriverOptions != NULL)
-    HostAdapter->TaggedQueuingPermitted =
-      (HostAdapter->DriverOptions->TaggedQueuingPermitted &
-       HostAdapter->DriverOptions->TaggedQueuingPermittedMask) |
-      (HostAdapter->TaggedQueuingPermitted &
-       ~HostAdapter->DriverOptions->TaggedQueuingPermittedMask);
-
-  /*
-    Select an appropriate value for Bus Settle Time either from a BusLogic
-    Driver Options specification, or from BusLogic_DefaultBusSettleTime.
-  */
-  if (HostAdapter->DriverOptions != NULL &&
-      HostAdapter->DriverOptions->BusSettleTime > 0)
-    HostAdapter->BusSettleTime = HostAdapter->DriverOptions->BusSettleTime;
-  else HostAdapter->BusSettleTime = BusLogic_DefaultBusSettleTime;
-  /*
-    Indicate reading the Host Adapter Configuration completed successfully.
-  */
-  return true;
+	struct BusLogic_BoardID BoardID;
+	struct BusLogic_Configuration Configuration;
+	struct BusLogic_SetupInformation SetupInformation;
+	struct BusLogic_ExtendedSetupInformation ExtendedSetupInformation;
+	unsigned char HostAdapterModelNumber[5];
+	unsigned char FirmwareVersion3rdDigit;
+	unsigned char FirmwareVersionLetter;
+	struct BusLogic_PCIHostAdapterInformation PCIHostAdapterInformation;
+	struct BusLogic_FetchHostAdapterLocalRAMRequest FetchHostAdapterLocalRAMRequest;
+	struct BusLogic_AutoSCSIData AutoSCSIData;
+	union BusLogic_GeometryRegister GeometryRegister;
+	unsigned char RequestedReplyLength;
+	unsigned char *TargetPointer, Character;
+	int TargetID, i;
+	/*
+	   Configuration Information for FlashPoint Host Adapters is provided in the
+	   FlashPoint_Info structure by the FlashPoint SCCB Manager's Probe Function.
+	   Initialize fields in the Host Adapter structure from the FlashPoint_Info
+	   structure.
+	 */
+	if (BusLogic_FlashPointHostAdapterP(HostAdapter)) {
+		struct FlashPoint_Info *FlashPointInfo = &HostAdapter->FlashPointInfo;
+		TargetPointer = HostAdapter->ModelName;
+		*TargetPointer++ = 'B';
+		*TargetPointer++ = 'T';
+		*TargetPointer++ = '-';
+		for (i = 0; i < sizeof(FlashPointInfo->ModelNumber); i++)
+			*TargetPointer++ = FlashPointInfo->ModelNumber[i];
+		*TargetPointer++ = '\0';
+		strcpy(HostAdapter->FirmwareVersion, FlashPoint_FirmwareVersion);
+		HostAdapter->SCSI_ID = FlashPointInfo->SCSI_ID;
+		HostAdapter->ExtendedTranslationEnabled = FlashPointInfo->ExtendedTranslationEnabled;
+		HostAdapter->ParityCheckingEnabled = FlashPointInfo->ParityCheckingEnabled;
+		HostAdapter->BusResetEnabled = !FlashPointInfo->HostSoftReset;
+		HostAdapter->LevelSensitiveInterrupt = true;
+		HostAdapter->HostWideSCSI = FlashPointInfo->HostWideSCSI;
+		HostAdapter->HostDifferentialSCSI = false;
+		HostAdapter->HostSupportsSCAM = true;
+		HostAdapter->HostUltraSCSI = true;
+		HostAdapter->ExtendedLUNSupport = true;
+		HostAdapter->TerminationInfoValid = true;
+		HostAdapter->LowByteTerminated = FlashPointInfo->LowByteTerminated;
+		HostAdapter->HighByteTerminated = FlashPointInfo->HighByteTerminated;
+		HostAdapter->SCAM_Enabled = FlashPointInfo->SCAM_Enabled;
+		HostAdapter->SCAM_Level2 = FlashPointInfo->SCAM_Level2;
+		HostAdapter->DriverScatterGatherLimit = BusLogic_ScatterGatherLimit;
+		HostAdapter->MaxTargetDevices = (HostAdapter->HostWideSCSI ? 16 : 8);
+		HostAdapter->MaxLogicalUnits = 32;
+		HostAdapter->InitialCCBs = 4 * BusLogic_CCB_AllocationGroupSize;
+		HostAdapter->IncrementalCCBs = BusLogic_CCB_AllocationGroupSize;
+		HostAdapter->DriverQueueDepth = 255;
+		HostAdapter->HostAdapterQueueDepth = HostAdapter->DriverQueueDepth;
+		HostAdapter->SynchronousPermitted = FlashPointInfo->SynchronousPermitted;
+		HostAdapter->FastPermitted = FlashPointInfo->FastPermitted;
+		HostAdapter->UltraPermitted = FlashPointInfo->UltraPermitted;
+		HostAdapter->WidePermitted = FlashPointInfo->WidePermitted;
+		HostAdapter->DisconnectPermitted = FlashPointInfo->DisconnectPermitted;
+		HostAdapter->TaggedQueuingPermitted = 0xFFFF;
+		goto Common;
+	}
+	/*
+	   Issue the Inquire Board ID command.
+	 */
+	if (BusLogic_Command(HostAdapter, BusLogic_InquireBoardID, NULL, 0, &BoardID, sizeof(BoardID)) != sizeof(BoardID))
+		return BusLogic_Failure(HostAdapter, "INQUIRE BOARD ID");
+	/*
+	   Issue the Inquire Configuration command.
+	 */
+	if (BusLogic_Command(HostAdapter, BusLogic_InquireConfiguration, NULL, 0, &Configuration, sizeof(Configuration))
+	    != sizeof(Configuration))
+		return BusLogic_Failure(HostAdapter, "INQUIRE CONFIGURATION");
+	/*
+	   Issue the Inquire Setup Information command.
+	 */
+	RequestedReplyLength = sizeof(SetupInformation);
+	if (BusLogic_Command(HostAdapter, BusLogic_InquireSetupInformation, &RequestedReplyLength, sizeof(RequestedReplyLength), &SetupInformation, sizeof(SetupInformation))
+	    != sizeof(SetupInformation))
+		return BusLogic_Failure(HostAdapter, "INQUIRE SETUP INFORMATION");
+	/*
+	   Issue the Inquire Extended Setup Information command.
+	 */
+	RequestedReplyLength = sizeof(ExtendedSetupInformation);
+	if (BusLogic_Command(HostAdapter, BusLogic_InquireExtendedSetupInformation, &RequestedReplyLength, sizeof(RequestedReplyLength), &ExtendedSetupInformation, sizeof(ExtendedSetupInformation))
+	    != sizeof(ExtendedSetupInformation))
+		return BusLogic_Failure(HostAdapter, "INQUIRE EXTENDED SETUP INFORMATION");
+	/*
+	   Issue the Inquire Firmware Version 3rd Digit command.
+	 */
+	FirmwareVersion3rdDigit = '\0';
+	if (BoardID.FirmwareVersion1stDigit > '0')
+		if (BusLogic_Command(HostAdapter, BusLogic_InquireFirmwareVersion3rdDigit, NULL, 0, &FirmwareVersion3rdDigit, sizeof(FirmwareVersion3rdDigit))
+		    != sizeof(FirmwareVersion3rdDigit))
+			return BusLogic_Failure(HostAdapter, "INQUIRE FIRMWARE 3RD DIGIT");
+	/*
+	   Issue the Inquire Host Adapter Model Number command.
+	 */
+	if (ExtendedSetupInformation.BusType == 'A' && BoardID.FirmwareVersion1stDigit == '2')
+		/* BusLogic BT-542B ISA 2.xx */
+		strcpy(HostAdapterModelNumber, "542B");
+	else if (ExtendedSetupInformation.BusType == 'E' && BoardID.FirmwareVersion1stDigit == '2' && (BoardID.FirmwareVersion2ndDigit <= '1' || (BoardID.FirmwareVersion2ndDigit == '2' && FirmwareVersion3rdDigit == '0')))
+		/* BusLogic BT-742A EISA 2.1x or 2.20 */
+		strcpy(HostAdapterModelNumber, "742A");
+	else if (ExtendedSetupInformation.BusType == 'E' && BoardID.FirmwareVersion1stDigit == '0')
+		/* AMI FastDisk EISA Series 441 0.x */
+		strcpy(HostAdapterModelNumber, "747A");
+	else {
+		RequestedReplyLength = sizeof(HostAdapterModelNumber);
+		if (BusLogic_Command(HostAdapter, BusLogic_InquireHostAdapterModelNumber, &RequestedReplyLength, sizeof(RequestedReplyLength), &HostAdapterModelNumber, sizeof(HostAdapterModelNumber))
+		    != sizeof(HostAdapterModelNumber))
+			return BusLogic_Failure(HostAdapter, "INQUIRE HOST ADAPTER MODEL NUMBER");
+	}
+	/*
+	   BusLogic MultiMaster Host Adapters can be identified by their model number
+	   and the major version number of their firmware as follows:
+
+	   5.xx       BusLogic "W" Series Host Adapters:
+	   BT-948/958/958D
+	   4.xx       BusLogic "C" Series Host Adapters:
+	   BT-946C/956C/956CD/747C/757C/757CD/445C/545C/540CF
+	   3.xx       BusLogic "S" Series Host Adapters:
+	   BT-747S/747D/757S/757D/445S/545S/542D
+	   BT-542B/742A (revision H)
+	   2.xx       BusLogic "A" Series Host Adapters:
+	   BT-542B/742A (revision G and below)
+	   0.xx       AMI FastDisk VLB/EISA BusLogic Clone Host Adapter
+	 */
+	/*
+	   Save the Model Name and Host Adapter Name in the Host Adapter structure.
+	 */
+	TargetPointer = HostAdapter->ModelName;
+	*TargetPointer++ = 'B';
+	*TargetPointer++ = 'T';
+	*TargetPointer++ = '-';
+	for (i = 0; i < sizeof(HostAdapterModelNumber); i++) {
+		Character = HostAdapterModelNumber[i];
+		if (Character == ' ' || Character == '\0')
+			break;
+		*TargetPointer++ = Character;
+	}
+	*TargetPointer++ = '\0';
+	/*
+	   Save the Firmware Version in the Host Adapter structure.
+	 */
+	TargetPointer = HostAdapter->FirmwareVersion;
+	*TargetPointer++ = BoardID.FirmwareVersion1stDigit;
+	*TargetPointer++ = '.';
+	*TargetPointer++ = BoardID.FirmwareVersion2ndDigit;
+	if (FirmwareVersion3rdDigit != ' ' && FirmwareVersion3rdDigit != '\0')
+		*TargetPointer++ = FirmwareVersion3rdDigit;
+	*TargetPointer = '\0';
+	/*
+	   Issue the Inquire Firmware Version Letter command.
+	 */
+	if (strcmp(HostAdapter->FirmwareVersion, "3.3") >= 0) {
+		if (BusLogic_Command(HostAdapter, BusLogic_InquireFirmwareVersionLetter, NULL, 0, &FirmwareVersionLetter, sizeof(FirmwareVersionLetter))
+		    != sizeof(FirmwareVersionLetter))
+			return BusLogic_Failure(HostAdapter, "INQUIRE FIRMWARE VERSION LETTER");
+		if (FirmwareVersionLetter != ' ' && FirmwareVersionLetter != '\0')
+			*TargetPointer++ = FirmwareVersionLetter;
+		*TargetPointer = '\0';
+	}
+	/*
+	   Save the Host Adapter SCSI ID in the Host Adapter structure.
+	 */
+	HostAdapter->SCSI_ID = Configuration.HostAdapterID;
+	/*
+	   Determine the Bus Type and save it in the Host Adapter structure, determine
+	   and save the IRQ Channel if necessary, and determine and save the DMA
+	   Channel for ISA Host Adapters.
+	 */
+	HostAdapter->HostAdapterBusType = BusLogic_HostAdapterBusTypes[HostAdapter->ModelName[3] - '4'];
+	if (HostAdapter->IRQ_Channel == 0) {
+		if (Configuration.IRQ_Channel9)
+			HostAdapter->IRQ_Channel = 9;
+		else if (Configuration.IRQ_Channel10)
+			HostAdapter->IRQ_Channel = 10;
+		else if (Configuration.IRQ_Channel11)
+			HostAdapter->IRQ_Channel = 11;
+		else if (Configuration.IRQ_Channel12)
+			HostAdapter->IRQ_Channel = 12;
+		else if (Configuration.IRQ_Channel14)
+			HostAdapter->IRQ_Channel = 14;
+		else if (Configuration.IRQ_Channel15)
+			HostAdapter->IRQ_Channel = 15;
+	}
+	if (HostAdapter->HostAdapterBusType == BusLogic_ISA_Bus) {
+		if (Configuration.DMA_Channel5)
+			HostAdapter->DMA_Channel = 5;
+		else if (Configuration.DMA_Channel6)
+			HostAdapter->DMA_Channel = 6;
+		else if (Configuration.DMA_Channel7)
+			HostAdapter->DMA_Channel = 7;
+	}
+	/*
+	   Determine whether Extended Translation is enabled and save it in
+	   the Host Adapter structure.
+	 */
+	GeometryRegister.All = BusLogic_ReadGeometryRegister(HostAdapter);
+	HostAdapter->ExtendedTranslationEnabled = GeometryRegister.gr.ExtendedTranslationEnabled;
+	/*
+	   Save the Scatter Gather Limits, Level Sensitive Interrupt flag, Wide
+	   SCSI flag, Differential SCSI flag, SCAM Supported flag, and
+	   Ultra SCSI flag in the Host Adapter structure.
+	 */
+	HostAdapter->HostAdapterScatterGatherLimit = ExtendedSetupInformation.ScatterGatherLimit;
+	HostAdapter->DriverScatterGatherLimit = HostAdapter->HostAdapterScatterGatherLimit;
+	if (HostAdapter->HostAdapterScatterGatherLimit > BusLogic_ScatterGatherLimit)
+		HostAdapter->DriverScatterGatherLimit = BusLogic_ScatterGatherLimit;
+	if (ExtendedSetupInformation.Misc.LevelSensitiveInterrupt)
+		HostAdapter->LevelSensitiveInterrupt = true;
+	HostAdapter->HostWideSCSI = ExtendedSetupInformation.HostWideSCSI;
+	HostAdapter->HostDifferentialSCSI = ExtendedSetupInformation.HostDifferentialSCSI;
+	HostAdapter->HostSupportsSCAM = ExtendedSetupInformation.HostSupportsSCAM;
+	HostAdapter->HostUltraSCSI = ExtendedSetupInformation.HostUltraSCSI;
+	/*
+	   Determine whether Extended LUN Format CCBs are supported and save the
+	   information in the Host Adapter structure.
+	 */
+	if (HostAdapter->FirmwareVersion[0] == '5' || (HostAdapter->FirmwareVersion[0] == '4' && HostAdapter->HostWideSCSI))
+		HostAdapter->ExtendedLUNSupport = true;
+	/*
+	   Issue the Inquire PCI Host Adapter Information command to read the
+	   Termination Information from "W" series MultiMaster Host Adapters.
+	 */
+	if (HostAdapter->FirmwareVersion[0] == '5') {
+		if (BusLogic_Command(HostAdapter, BusLogic_InquirePCIHostAdapterInformation, NULL, 0, &PCIHostAdapterInformation, sizeof(PCIHostAdapterInformation))
+		    != sizeof(PCIHostAdapterInformation))
+			return BusLogic_Failure(HostAdapter, "INQUIRE PCI HOST ADAPTER INFORMATION");
+		/*
+		   Save the Termination Information in the Host Adapter structure.
+		 */
+		if (PCIHostAdapterInformation.GenericInfoValid) {
+			HostAdapter->TerminationInfoValid = true;
+			HostAdapter->LowByteTerminated = PCIHostAdapterInformation.LowByteTerminated;
+			HostAdapter->HighByteTerminated = PCIHostAdapterInformation.HighByteTerminated;
+		}
+	}
+	/*
+	   Issue the Fetch Host Adapter Local RAM command to read the AutoSCSI data
+	   from "W" and "C" series MultiMaster Host Adapters.
+	 */
+	if (HostAdapter->FirmwareVersion[0] >= '4') {
+		FetchHostAdapterLocalRAMRequest.ByteOffset = BusLogic_AutoSCSI_BaseOffset;
+		FetchHostAdapterLocalRAMRequest.ByteCount = sizeof(AutoSCSIData);
+		if (BusLogic_Command(HostAdapter, BusLogic_FetchHostAdapterLocalRAM, &FetchHostAdapterLocalRAMRequest, sizeof(FetchHostAdapterLocalRAMRequest), &AutoSCSIData, sizeof(AutoSCSIData))
+		    != sizeof(AutoSCSIData))
+			return BusLogic_Failure(HostAdapter, "FETCH HOST ADAPTER LOCAL RAM");
+		/*
+		   Save the Parity Checking Enabled, Bus Reset Enabled, and Termination
+		   Information in the Host Adapter structure.
+		 */
+		HostAdapter->ParityCheckingEnabled = AutoSCSIData.ParityCheckingEnabled;
+		HostAdapter->BusResetEnabled = AutoSCSIData.BusResetEnabled;
+		if (HostAdapter->FirmwareVersion[0] == '4') {
+			HostAdapter->TerminationInfoValid = true;
+			HostAdapter->LowByteTerminated = AutoSCSIData.LowByteTerminated;
+			HostAdapter->HighByteTerminated = AutoSCSIData.HighByteTerminated;
+		}
+		/*
+		   Save the Wide Permitted, Fast Permitted, Synchronous Permitted,
+		   Disconnect Permitted, Ultra Permitted, and SCAM Information in the
+		   Host Adapter structure.
+		 */
+		HostAdapter->WidePermitted = AutoSCSIData.WidePermitted;
+		HostAdapter->FastPermitted = AutoSCSIData.FastPermitted;
+		HostAdapter->SynchronousPermitted = AutoSCSIData.SynchronousPermitted;
+		HostAdapter->DisconnectPermitted = AutoSCSIData.DisconnectPermitted;
+		if (HostAdapter->HostUltraSCSI)
+			HostAdapter->UltraPermitted = AutoSCSIData.UltraPermitted;
+		if (HostAdapter->HostSupportsSCAM) {
+			HostAdapter->SCAM_Enabled = AutoSCSIData.SCAM_Enabled;
+			HostAdapter->SCAM_Level2 = AutoSCSIData.SCAM_Level2;
+		}
+	}
+	/*
+	   Initialize fields in the Host Adapter structure for "S" and "A" series
+	   MultiMaster Host Adapters.
+	 */
+	if (HostAdapter->FirmwareVersion[0] < '4') {
+		if (SetupInformation.SynchronousInitiationEnabled) {
+			HostAdapter->SynchronousPermitted = 0xFF;
+			if (HostAdapter->HostAdapterBusType == BusLogic_EISA_Bus) {
+				if (ExtendedSetupInformation.Misc.FastOnEISA)
+					HostAdapter->FastPermitted = 0xFF;
+				if (strcmp(HostAdapter->ModelName, "BT-757") == 0)
+					HostAdapter->WidePermitted = 0xFF;
+			}
+		}
+		HostAdapter->DisconnectPermitted = 0xFF;
+		HostAdapter->ParityCheckingEnabled = SetupInformation.ParityCheckingEnabled;
+		HostAdapter->BusResetEnabled = true;
+	}
+	/*
+	   Determine the maximum number of Target IDs and Logical Units supported by
+	   this driver for Wide and Narrow Host Adapters.
+	 */
+	HostAdapter->MaxTargetDevices = (HostAdapter->HostWideSCSI ? 16 : 8);
+	HostAdapter->MaxLogicalUnits = (HostAdapter->ExtendedLUNSupport ? 32 : 8);
+	/*
+	   Select appropriate values for the Mailbox Count, Driver Queue Depth,
+	   Initial CCBs, and Incremental CCBs variables based on whether or not Strict
+	   Round Robin Mode is supported.  If Strict Round Robin Mode is supported,
+	   then there is no performance degradation in using the maximum possible
+	   number of Outgoing and Incoming Mailboxes and allowing the Tagged and
+	   Untagged Queue Depths to determine the actual utilization.  If Strict Round
+	   Robin Mode is not supported, then the Host Adapter must scan all the
+	   Outgoing Mailboxes whenever an Outgoing Mailbox entry is made, which can
+	   cause a substantial performance penalty.  The host adapters actually have
+	   room to store the following number of CCBs internally; that is, they can
+	   internally queue and manage this many active commands on the SCSI bus
+	   simultaneously.  Performance measurements demonstrate that the Driver Queue
+	   Depth should be set to the Mailbox Count, rather than the Host Adapter
+	   Queue Depth (internal CCB capacity), as it is more efficient to have the
+	   queued commands waiting in Outgoing Mailboxes if necessary than to block
+	   the process in the higher levels of the SCSI Subsystem.
+
+	   192          BT-948/958/958D
+	   100          BT-946C/956C/956CD/747C/757C/757CD/445C
+	   50   BT-545C/540CF
+	   30   BT-747S/747D/757S/757D/445S/545S/542D/542B/742A
+	 */
+	if (HostAdapter->FirmwareVersion[0] == '5')
+		HostAdapter->HostAdapterQueueDepth = 192;
+	else if (HostAdapter->FirmwareVersion[0] == '4')
+		HostAdapter->HostAdapterQueueDepth = (HostAdapter->HostAdapterBusType != BusLogic_ISA_Bus ? 100 : 50);
+	else
+		HostAdapter->HostAdapterQueueDepth = 30;
+	if (strcmp(HostAdapter->FirmwareVersion, "3.31") >= 0) {
+		HostAdapter->StrictRoundRobinModeSupport = true;
+		HostAdapter->MailboxCount = BusLogic_MaxMailboxes;
+	} else {
+		HostAdapter->StrictRoundRobinModeSupport = false;
+		HostAdapter->MailboxCount = 32;
+	}
+	HostAdapter->DriverQueueDepth = HostAdapter->MailboxCount;
+	HostAdapter->InitialCCBs = 4 * BusLogic_CCB_AllocationGroupSize;
+	HostAdapter->IncrementalCCBs = BusLogic_CCB_AllocationGroupSize;
+	/*
+	   Tagged Queuing support is available and operates properly on all "W" series
+	   MultiMaster Host Adapters, on "C" series MultiMaster Host Adapters with
+	   firmware version 4.22 and above, and on "S" series MultiMaster Host
+	   Adapters with firmware version 3.35 and above.
+	 */
+	HostAdapter->TaggedQueuingPermitted = 0;
+	switch (HostAdapter->FirmwareVersion[0]) {
+	case '5':
+		HostAdapter->TaggedQueuingPermitted = 0xFFFF;
+		break;
+	case '4':
+		if (strcmp(HostAdapter->FirmwareVersion, "4.22") >= 0)
+			HostAdapter->TaggedQueuingPermitted = 0xFFFF;
+		break;
+	case '3':
+		if (strcmp(HostAdapter->FirmwareVersion, "3.35") >= 0)
+			HostAdapter->TaggedQueuingPermitted = 0xFFFF;
+		break;
+	}
+	/*
+	   Determine the Host Adapter BIOS Address if the BIOS is enabled and
+	   save it in the Host Adapter structure.  The BIOS is disabled if the
+	   BIOS_Address is 0.
+	 */
+	HostAdapter->BIOS_Address = ExtendedSetupInformation.BIOS_Address << 12;
+	/*
+	   ISA Host Adapters require Bounce Buffers if there is more than 16MB memory.
+	 */
+	if (HostAdapter->HostAdapterBusType == BusLogic_ISA_Bus && (void *) high_memory > (void *) MAX_DMA_ADDRESS)
+		HostAdapter->BounceBuffersRequired = true;
+	/*
+	   BusLogic BT-445S Host Adapters prior to board revision E have a hardware
+	   bug whereby when the BIOS is enabled, transfers to/from the same address
+	   range the BIOS occupies modulo 16MB are handled incorrectly.  Only properly
+	   functioning BT-445S Host Adapters have firmware version 3.37, so require
+	   that ISA Bounce Buffers be used for the buggy BT-445S models if there is
+	   more than 16MB memory.
+	 */
+	if (HostAdapter->BIOS_Address > 0 && strcmp(HostAdapter->ModelName, "BT-445S") == 0 && strcmp(HostAdapter->FirmwareVersion, "3.37") < 0 && (void *) high_memory > (void *) MAX_DMA_ADDRESS)
+		HostAdapter->BounceBuffersRequired = true;
+	/*
+	   Initialize parameters common to MultiMaster and FlashPoint Host Adapters.
+	 */
+      Common:
+	/*
+	   Initialize the Host Adapter Full Model Name from the Model Name.
+	 */
+	strcpy(HostAdapter->FullModelName, "BusLogic ");
+	strcat(HostAdapter->FullModelName, HostAdapter->ModelName);
+	/*
+	   Select an appropriate value for the Tagged Queue Depth either from a
+	   BusLogic Driver Options specification, or based on whether this Host
+	   Adapter requires that ISA Bounce Buffers be used.  The Tagged Queue Depth
+	   is left at 0 for automatic determination in BusLogic_SelectQueueDepths.
+	   Initialize the Untagged Queue Depth.
+	 */
+	for (TargetID = 0; TargetID < BusLogic_MaxTargetDevices; TargetID++) {
+		unsigned char QueueDepth = 0;
+		if (HostAdapter->DriverOptions != NULL && HostAdapter->DriverOptions->QueueDepth[TargetID] > 0)
+			QueueDepth = HostAdapter->DriverOptions->QueueDepth[TargetID];
+		else if (HostAdapter->BounceBuffersRequired)
+			QueueDepth = BusLogic_TaggedQueueDepthBB;
+		HostAdapter->QueueDepth[TargetID] = QueueDepth;
+	}
+	if (HostAdapter->BounceBuffersRequired)
+		HostAdapter->UntaggedQueueDepth = BusLogic_UntaggedQueueDepthBB;
+	else
+		HostAdapter->UntaggedQueueDepth = BusLogic_UntaggedQueueDepth;
+	if (HostAdapter->DriverOptions != NULL)
+		HostAdapter->CommonQueueDepth = HostAdapter->DriverOptions->CommonQueueDepth;
+	if (HostAdapter->CommonQueueDepth > 0 && HostAdapter->CommonQueueDepth < HostAdapter->UntaggedQueueDepth)
+		HostAdapter->UntaggedQueueDepth = HostAdapter->CommonQueueDepth;
+	/*
+	   Tagged Queuing is only allowed if Disconnect/Reconnect is permitted.
+	   Therefore, mask the Tagged Queuing Permitted Default bits with the
+	   Disconnect/Reconnect Permitted bits.
+	 */
+	HostAdapter->TaggedQueuingPermitted &= HostAdapter->DisconnectPermitted;
+	/*
+	   Combine the default Tagged Queuing Permitted bits with any BusLogic Driver
+	   Options Tagged Queuing specification.
+	 */
+	if (HostAdapter->DriverOptions != NULL)
+		HostAdapter->TaggedQueuingPermitted =
+		    (HostAdapter->DriverOptions->TaggedQueuingPermitted & HostAdapter->DriverOptions->TaggedQueuingPermittedMask) | (HostAdapter->TaggedQueuingPermitted & ~HostAdapter->DriverOptions->TaggedQueuingPermittedMask);
+
+	/*
+	   Select an appropriate value for Bus Settle Time either from a BusLogic
+	   Driver Options specification, or from BusLogic_DefaultBusSettleTime.
+	 */
+	if (HostAdapter->DriverOptions != NULL && HostAdapter->DriverOptions->BusSettleTime > 0)
+		HostAdapter->BusSettleTime = HostAdapter->DriverOptions->BusSettleTime;
+	else
+		HostAdapter->BusSettleTime = BusLogic_DefaultBusSettleTime;
+	/*
+	   Indicate reading the Host Adapter Configuration completed successfully.
+	 */
+	return true;
 }
 
 
@@ -2045,210 +1725,144 @@
 static boolean __init BusLogic_ReportHostAdapterConfiguration(struct BusLogic_HostAdapter
 							      *HostAdapter)
 {
-  unsigned short AllTargetsMask = (1 << HostAdapter->MaxTargetDevices) - 1;
-  unsigned short SynchronousPermitted, FastPermitted;
-  unsigned short UltraPermitted, WidePermitted;
-  unsigned short DisconnectPermitted, TaggedQueuingPermitted;
-  boolean CommonSynchronousNegotiation, CommonTaggedQueueDepth;
-  char SynchronousString[BusLogic_MaxTargetDevices+1];
-  char WideString[BusLogic_MaxTargetDevices+1];
-  char DisconnectString[BusLogic_MaxTargetDevices+1];
-  char TaggedQueuingString[BusLogic_MaxTargetDevices+1];
-  char *SynchronousMessage = SynchronousString;
-  char *WideMessage = WideString;
-  char *DisconnectMessage = DisconnectString;
-  char *TaggedQueuingMessage = TaggedQueuingString;
-  int TargetID;
-  BusLogic_Info("Configuring BusLogic Model %s %s%s%s%s SCSI Host Adapter\n",
-		HostAdapter, HostAdapter->ModelName,
-		BusLogic_HostAdapterBusNames[HostAdapter->HostAdapterBusType],
-		(HostAdapter->HostWideSCSI ? " Wide" : ""),
-		(HostAdapter->HostDifferentialSCSI ? " Differential" : ""),
-		(HostAdapter->HostUltraSCSI ? " Ultra" : ""));
-  BusLogic_Info("  Firmware Version: %s, I/O Address: 0x%X, "
-		"IRQ Channel: %d/%s\n", HostAdapter,
-		HostAdapter->FirmwareVersion,
-		HostAdapter->IO_Address, HostAdapter->IRQ_Channel,
-		(HostAdapter->LevelSensitiveInterrupt ? "Level" : "Edge"));
-  if (HostAdapter->HostAdapterBusType != BusLogic_PCI_Bus)
-    {
-      BusLogic_Info("  DMA Channel: ", HostAdapter);
-      if (HostAdapter->DMA_Channel > 0)
-	BusLogic_Info("%d, ", HostAdapter, HostAdapter->DMA_Channel);
-      else BusLogic_Info("None, ", HostAdapter);
-      if (HostAdapter->BIOS_Address > 0)
-	BusLogic_Info("BIOS Address: 0x%X, ", HostAdapter,
-		      HostAdapter->BIOS_Address);
-      else BusLogic_Info("BIOS Address: None, ", HostAdapter);
-    }
-  else
-    {
-      BusLogic_Info("  PCI Bus: %d, Device: %d, Address: ",
-		    HostAdapter, HostAdapter->Bus, HostAdapter->Device);
-      if (HostAdapter->PCI_Address > 0)
-	BusLogic_Info("0x%X, ", HostAdapter, HostAdapter->PCI_Address);
-      else BusLogic_Info("Unassigned, ", HostAdapter);
-    }
-  BusLogic_Info("Host Adapter SCSI ID: %d\n", HostAdapter,
-		HostAdapter->SCSI_ID);
-  BusLogic_Info("  Parity Checking: %s, Extended Translation: %s\n",
-		HostAdapter,
-		(HostAdapter->ParityCheckingEnabled
-		 ? "Enabled" : "Disabled"),
-		(HostAdapter->ExtendedTranslationEnabled
-		 ? "Enabled" : "Disabled"));
-  AllTargetsMask &= ~(1 << HostAdapter->SCSI_ID);
-  SynchronousPermitted = HostAdapter->SynchronousPermitted & AllTargetsMask;
-  FastPermitted = HostAdapter->FastPermitted & AllTargetsMask;
-  UltraPermitted = HostAdapter->UltraPermitted & AllTargetsMask;
-  if ((BusLogic_MultiMasterHostAdapterP(HostAdapter) &&
-       (HostAdapter->FirmwareVersion[0] >= '4' ||
-	HostAdapter->HostAdapterBusType == BusLogic_EISA_Bus)) ||
-      BusLogic_FlashPointHostAdapterP(HostAdapter))
-    {
-      CommonSynchronousNegotiation = false;
-      if (SynchronousPermitted == 0)
-	{
-	  SynchronousMessage = "Disabled";
-	  CommonSynchronousNegotiation = true;
-	}
-      else if (SynchronousPermitted == AllTargetsMask)
-	{
-	  if (FastPermitted == 0)
-	    {
-	      SynchronousMessage = "Slow";
-	      CommonSynchronousNegotiation = true;
-	    }
-	  else if (FastPermitted == AllTargetsMask)
-	    {
-	      if (UltraPermitted == 0)
-		{
-		  SynchronousMessage = "Fast";
-		  CommonSynchronousNegotiation = true;
-		}
-	      else if (UltraPermitted == AllTargetsMask)
-		{
-		  SynchronousMessage = "Ultra";
-		  CommonSynchronousNegotiation = true;
-		}
-	    }
-	}
-      if (!CommonSynchronousNegotiation)
-	{
-	  for (TargetID = 0;
-	       TargetID < HostAdapter->MaxTargetDevices;
-	       TargetID++)
-	    SynchronousString[TargetID] =
-	      ((!(SynchronousPermitted & (1 << TargetID))) ? 'N' :
-	       (!(FastPermitted & (1 << TargetID)) ? 'S' :
-		(!(UltraPermitted & (1 << TargetID)) ? 'F' : 'U')));
-	  SynchronousString[HostAdapter->SCSI_ID] = '#';
-	  SynchronousString[HostAdapter->MaxTargetDevices] = '\0';
-	}
-    }
-  else SynchronousMessage =
-	 (SynchronousPermitted == 0 ? "Disabled" : "Enabled");
-  WidePermitted = HostAdapter->WidePermitted & AllTargetsMask;
-  if (WidePermitted == 0)
-    WideMessage = "Disabled";
-  else if (WidePermitted == AllTargetsMask)
-    WideMessage = "Enabled";
-  else
-    {
-      for (TargetID = 0; TargetID < HostAdapter->MaxTargetDevices; TargetID++)
-	 WideString[TargetID] =
-	   ((WidePermitted & (1 << TargetID)) ? 'Y' : 'N');
-      WideString[HostAdapter->SCSI_ID] = '#';
-      WideString[HostAdapter->MaxTargetDevices] = '\0';
-    }
-  DisconnectPermitted = HostAdapter->DisconnectPermitted & AllTargetsMask;
-  if (DisconnectPermitted == 0)
-    DisconnectMessage = "Disabled";
-  else if (DisconnectPermitted == AllTargetsMask)
-    DisconnectMessage = "Enabled";
-  else
-    {
-      for (TargetID = 0; TargetID < HostAdapter->MaxTargetDevices; TargetID++)
-	DisconnectString[TargetID] =
-	  ((DisconnectPermitted & (1 << TargetID)) ? 'Y' : 'N');
-      DisconnectString[HostAdapter->SCSI_ID] = '#';
-      DisconnectString[HostAdapter->MaxTargetDevices] = '\0';
-    }
-  TaggedQueuingPermitted =
-    HostAdapter->TaggedQueuingPermitted & AllTargetsMask;
-  if (TaggedQueuingPermitted == 0)
-    TaggedQueuingMessage = "Disabled";
-  else if (TaggedQueuingPermitted == AllTargetsMask)
-    TaggedQueuingMessage = "Enabled";
-  else
-    {
-      for (TargetID = 0; TargetID < HostAdapter->MaxTargetDevices; TargetID++)
-	TaggedQueuingString[TargetID] =
-	  ((TaggedQueuingPermitted & (1 << TargetID)) ? 'Y' : 'N');
-      TaggedQueuingString[HostAdapter->SCSI_ID] = '#';
-      TaggedQueuingString[HostAdapter->MaxTargetDevices] = '\0';
-    }
-  BusLogic_Info("  Synchronous Negotiation: %s, Wide Negotiation: %s\n",
-		HostAdapter, SynchronousMessage, WideMessage);
-  BusLogic_Info("  Disconnect/Reconnect: %s, Tagged Queuing: %s\n",
-		HostAdapter, DisconnectMessage, TaggedQueuingMessage);
-  if (BusLogic_MultiMasterHostAdapterP(HostAdapter))
-    {
-      BusLogic_Info("  Scatter/Gather Limit: %d of %d segments, "
-		    "Mailboxes: %d\n", HostAdapter,
-		    HostAdapter->DriverScatterGatherLimit,
-		    HostAdapter->HostAdapterScatterGatherLimit,
-		    HostAdapter->MailboxCount);
-      BusLogic_Info("  Driver Queue Depth: %d, "
-		    "Host Adapter Queue Depth: %d\n",
-		    HostAdapter, HostAdapter->DriverQueueDepth,
-		    HostAdapter->HostAdapterQueueDepth);
-    }
-  else BusLogic_Info("  Driver Queue Depth: %d, "
-		     "Scatter/Gather Limit: %d segments\n",
-		     HostAdapter, HostAdapter->DriverQueueDepth,
-		     HostAdapter->DriverScatterGatherLimit);
-  BusLogic_Info("  Tagged Queue Depth: ", HostAdapter);
-  CommonTaggedQueueDepth = true;
-  for (TargetID = 1; TargetID < HostAdapter->MaxTargetDevices; TargetID++)
-    if (HostAdapter->QueueDepth[TargetID] != HostAdapter->QueueDepth[0])
-      {
-	CommonTaggedQueueDepth = false;
-	break;
-      }
-  if (CommonTaggedQueueDepth)
-    {
-      if (HostAdapter->QueueDepth[0] > 0)
-	BusLogic_Info("%d", HostAdapter, HostAdapter->QueueDepth[0]);
-      else BusLogic_Info("Automatic", HostAdapter);
-    }
-  else BusLogic_Info("Individual", HostAdapter);
-  BusLogic_Info(", Untagged Queue Depth: %d\n", HostAdapter,
-		HostAdapter->UntaggedQueueDepth);
-  if (HostAdapter->TerminationInfoValid)
-    {
-      if (HostAdapter->HostWideSCSI)
-	BusLogic_Info("  SCSI Bus Termination: %s", HostAdapter,
-		      (HostAdapter->LowByteTerminated
-		       ? (HostAdapter->HighByteTerminated
-			  ? "Both Enabled" : "Low Enabled")
-		       : (HostAdapter->HighByteTerminated
-			  ? "High Enabled" : "Both Disabled")));
-      else BusLogic_Info("  SCSI Bus Termination: %s", HostAdapter,
-			 (HostAdapter->LowByteTerminated ?
-			  "Enabled" : "Disabled"));
-      if (HostAdapter->HostSupportsSCAM)
-	BusLogic_Info(", SCAM: %s", HostAdapter,
-		      (HostAdapter->SCAM_Enabled
-		       ? (HostAdapter->SCAM_Level2
-			  ? "Enabled, Level 2" : "Enabled, Level 1")
-		       : "Disabled"));
-      BusLogic_Info("\n", HostAdapter);
-    }
-  /*
-    Indicate reporting the Host Adapter configuration completed successfully.
-  */
-  return true;
+	unsigned short AllTargetsMask = (1 << HostAdapter->MaxTargetDevices) - 1;
+	unsigned short SynchronousPermitted, FastPermitted;
+	unsigned short UltraPermitted, WidePermitted;
+	unsigned short DisconnectPermitted, TaggedQueuingPermitted;
+	boolean CommonSynchronousNegotiation, CommonTaggedQueueDepth;
+	char SynchronousString[BusLogic_MaxTargetDevices + 1];
+	char WideString[BusLogic_MaxTargetDevices + 1];
+	char DisconnectString[BusLogic_MaxTargetDevices + 1];
+	char TaggedQueuingString[BusLogic_MaxTargetDevices + 1];
+	char *SynchronousMessage = SynchronousString;
+	char *WideMessage = WideString;
+	char *DisconnectMessage = DisconnectString;
+	char *TaggedQueuingMessage = TaggedQueuingString;
+	int TargetID;
+	BusLogic_Info("Configuring BusLogic Model %s %s%s%s%s SCSI Host Adapter\n",
+		      HostAdapter, HostAdapter->ModelName,
+		      BusLogic_HostAdapterBusNames[HostAdapter->HostAdapterBusType], (HostAdapter->HostWideSCSI ? " Wide" : ""), (HostAdapter->HostDifferentialSCSI ? " Differential" : ""), (HostAdapter->HostUltraSCSI ? " Ultra" : ""));
+	BusLogic_Info("  Firmware Version: %s, I/O Address: 0x%X, " "IRQ Channel: %d/%s\n", HostAdapter, HostAdapter->FirmwareVersion, HostAdapter->IO_Address, HostAdapter->IRQ_Channel, (HostAdapter->LevelSensitiveInterrupt ? "Level" : "Edge"));
+	if (HostAdapter->HostAdapterBusType != BusLogic_PCI_Bus) {
+		BusLogic_Info("  DMA Channel: ", HostAdapter);
+		if (HostAdapter->DMA_Channel > 0)
+			BusLogic_Info("%d, ", HostAdapter, HostAdapter->DMA_Channel);
+		else
+			BusLogic_Info("None, ", HostAdapter);
+		if (HostAdapter->BIOS_Address > 0)
+			BusLogic_Info("BIOS Address: 0x%X, ", HostAdapter, HostAdapter->BIOS_Address);
+		else
+			BusLogic_Info("BIOS Address: None, ", HostAdapter);
+	} else {
+		BusLogic_Info("  PCI Bus: %d, Device: %d, Address: ", HostAdapter, HostAdapter->Bus, HostAdapter->Device);
+		if (HostAdapter->PCI_Address > 0)
+			BusLogic_Info("0x%X, ", HostAdapter, HostAdapter->PCI_Address);
+		else
+			BusLogic_Info("Unassigned, ", HostAdapter);
+	}
+	BusLogic_Info("Host Adapter SCSI ID: %d\n", HostAdapter, HostAdapter->SCSI_ID);
+	BusLogic_Info("  Parity Checking: %s, Extended Translation: %s\n", HostAdapter, (HostAdapter->ParityCheckingEnabled ? "Enabled" : "Disabled"), (HostAdapter->ExtendedTranslationEnabled ? "Enabled" : "Disabled"));
+	AllTargetsMask &= ~(1 << HostAdapter->SCSI_ID);
+	SynchronousPermitted = HostAdapter->SynchronousPermitted & AllTargetsMask;
+	FastPermitted = HostAdapter->FastPermitted & AllTargetsMask;
+	UltraPermitted = HostAdapter->UltraPermitted & AllTargetsMask;
+	if ((BusLogic_MultiMasterHostAdapterP(HostAdapter) && (HostAdapter->FirmwareVersion[0] >= '4' || HostAdapter->HostAdapterBusType == BusLogic_EISA_Bus)) || BusLogic_FlashPointHostAdapterP(HostAdapter)) {
+		CommonSynchronousNegotiation = false;
+		if (SynchronousPermitted == 0) {
+			SynchronousMessage = "Disabled";
+			CommonSynchronousNegotiation = true;
+		} else if (SynchronousPermitted == AllTargetsMask) {
+			if (FastPermitted == 0) {
+				SynchronousMessage = "Slow";
+				CommonSynchronousNegotiation = true;
+			} else if (FastPermitted == AllTargetsMask) {
+				if (UltraPermitted == 0) {
+					SynchronousMessage = "Fast";
+					CommonSynchronousNegotiation = true;
+				} else if (UltraPermitted == AllTargetsMask) {
+					SynchronousMessage = "Ultra";
+					CommonSynchronousNegotiation = true;
+				}
+			}
+		}
+		if (!CommonSynchronousNegotiation) {
+			for (TargetID = 0; TargetID < HostAdapter->MaxTargetDevices; TargetID++)
+				SynchronousString[TargetID] = ((!(SynchronousPermitted & (1 << TargetID))) ? 'N' : (!(FastPermitted & (1 << TargetID)) ? 'S' : (!(UltraPermitted & (1 << TargetID)) ? 'F' : 'U')));
+			SynchronousString[HostAdapter->SCSI_ID] = '#';
+			SynchronousString[HostAdapter->MaxTargetDevices] = '\0';
+		}
+	} else
+		SynchronousMessage = (SynchronousPermitted == 0 ? "Disabled" : "Enabled");
+	WidePermitted = HostAdapter->WidePermitted & AllTargetsMask;
+	if (WidePermitted == 0)
+		WideMessage = "Disabled";
+	else if (WidePermitted == AllTargetsMask)
+		WideMessage = "Enabled";
+	else {
+		for (TargetID = 0; TargetID < HostAdapter->MaxTargetDevices; TargetID++)
+			WideString[TargetID] = ((WidePermitted & (1 << TargetID)) ? 'Y' : 'N');
+		WideString[HostAdapter->SCSI_ID] = '#';
+		WideString[HostAdapter->MaxTargetDevices] = '\0';
+	}
+	DisconnectPermitted = HostAdapter->DisconnectPermitted & AllTargetsMask;
+	if (DisconnectPermitted == 0)
+		DisconnectMessage = "Disabled";
+	else if (DisconnectPermitted == AllTargetsMask)
+		DisconnectMessage = "Enabled";
+	else {
+		for (TargetID = 0; TargetID < HostAdapter->MaxTargetDevices; TargetID++)
+			DisconnectString[TargetID] = ((DisconnectPermitted & (1 << TargetID)) ? 'Y' : 'N');
+		DisconnectString[HostAdapter->SCSI_ID] = '#';
+		DisconnectString[HostAdapter->MaxTargetDevices] = '\0';
+	}
+	TaggedQueuingPermitted = HostAdapter->TaggedQueuingPermitted & AllTargetsMask;
+	if (TaggedQueuingPermitted == 0)
+		TaggedQueuingMessage = "Disabled";
+	else if (TaggedQueuingPermitted == AllTargetsMask)
+		TaggedQueuingMessage = "Enabled";
+	else {
+		for (TargetID = 0; TargetID < HostAdapter->MaxTargetDevices; TargetID++)
+			TaggedQueuingString[TargetID] = ((TaggedQueuingPermitted & (1 << TargetID)) ? 'Y' : 'N');
+		TaggedQueuingString[HostAdapter->SCSI_ID] = '#';
+		TaggedQueuingString[HostAdapter->MaxTargetDevices] = '\0';
+	}
+	BusLogic_Info("  Synchronous Negotiation: %s, Wide Negotiation: %s\n", HostAdapter, SynchronousMessage, WideMessage);
+	BusLogic_Info("  Disconnect/Reconnect: %s, Tagged Queuing: %s\n", HostAdapter, DisconnectMessage, TaggedQueuingMessage);
+	if (BusLogic_MultiMasterHostAdapterP(HostAdapter)) {
+		BusLogic_Info("  Scatter/Gather Limit: %d of %d segments, " "Mailboxes: %d\n", HostAdapter, HostAdapter->DriverScatterGatherLimit, HostAdapter->HostAdapterScatterGatherLimit, HostAdapter->MailboxCount);
+		BusLogic_Info("  Driver Queue Depth: %d, " "Host Adapter Queue Depth: %d\n", HostAdapter, HostAdapter->DriverQueueDepth, HostAdapter->HostAdapterQueueDepth);
+	} else
+		BusLogic_Info("  Driver Queue Depth: %d, " "Scatter/Gather Limit: %d segments\n", HostAdapter, HostAdapter->DriverQueueDepth, HostAdapter->DriverScatterGatherLimit);
+	BusLogic_Info("  Tagged Queue Depth: ", HostAdapter);
+	CommonTaggedQueueDepth = true;
+	for (TargetID = 1; TargetID < HostAdapter->MaxTargetDevices; TargetID++)
+		if (HostAdapter->QueueDepth[TargetID] != HostAdapter->QueueDepth[0]) {
+			CommonTaggedQueueDepth = false;
+			break;
+		}
+	if (CommonTaggedQueueDepth) {
+		if (HostAdapter->QueueDepth[0] > 0)
+			BusLogic_Info("%d", HostAdapter, HostAdapter->QueueDepth[0]);
+		else
+			BusLogic_Info("Automatic", HostAdapter);
+	} else
+		BusLogic_Info("Individual", HostAdapter);
+	BusLogic_Info(", Untagged Queue Depth: %d\n", HostAdapter, HostAdapter->UntaggedQueueDepth);
+	if (HostAdapter->TerminationInfoValid) {
+		if (HostAdapter->HostWideSCSI)
+			BusLogic_Info("  SCSI Bus Termination: %s", HostAdapter, (HostAdapter->LowByteTerminated ? (HostAdapter->HighByteTerminated ? "Both Enabled" : "Low Enabled")
+										  : (HostAdapter->HighByteTerminated ? "High Enabled" : "Both Disabled")));
+		else
+			BusLogic_Info("  SCSI Bus Termination: %s", HostAdapter, (HostAdapter->LowByteTerminated ? "Enabled" : "Disabled"));
+		if (HostAdapter->HostSupportsSCAM)
+			BusLogic_Info(", SCAM: %s", HostAdapter, (HostAdapter->SCAM_Enabled ? (HostAdapter->SCAM_Level2 ? "Enabled, Level 2" : "Enabled, Level 1")
+								  : "Disabled"));
+		BusLogic_Info("\n", HostAdapter);
+	}
+	/*
+	   Indicate reporting the Host Adapter configuration completed successfully.
+	 */
+	return true;
 }
 
 
@@ -2259,43 +1873,34 @@
 
 static boolean __init BusLogic_AcquireResources(struct BusLogic_HostAdapter *HostAdapter)
 {
-  if (HostAdapter->IRQ_Channel == 0)
-    {
-      BusLogic_Error("NO LEGAL INTERRUPT CHANNEL ASSIGNED - DETACHING\n",
-		     HostAdapter);
-      return false;
-    }
-  /*
-    Acquire shared access to the IRQ Channel.
-  */
-  if (request_irq(HostAdapter->IRQ_Channel, BusLogic_InterruptHandler,
-		  SA_SHIRQ, HostAdapter->FullModelName, HostAdapter) < 0)
-    {
-      BusLogic_Error("UNABLE TO ACQUIRE IRQ CHANNEL %d - DETACHING\n",
-		     HostAdapter, HostAdapter->IRQ_Channel);
-      return false;
-    }
-  HostAdapter->IRQ_ChannelAcquired = true;
-  /*
-    Acquire exclusive access to the DMA Channel.
-  */
-  if (HostAdapter->DMA_Channel > 0)
-    {
-      if (request_dma(HostAdapter->DMA_Channel,
-		      HostAdapter->FullModelName) < 0)
-	{
-	  BusLogic_Error("UNABLE TO ACQUIRE DMA CHANNEL %d - DETACHING\n",
-			 HostAdapter, HostAdapter->DMA_Channel);
-	  return false;
-	}
-      set_dma_mode(HostAdapter->DMA_Channel, DMA_MODE_CASCADE);
-      enable_dma(HostAdapter->DMA_Channel);
-      HostAdapter->DMA_ChannelAcquired = true;
-    }
-  /*
-    Indicate the System Resource Acquisition completed successfully,
-  */
-  return true;
+	if (HostAdapter->IRQ_Channel == 0) {
+		BusLogic_Error("NO LEGAL INTERRUPT CHANNEL ASSIGNED - DETACHING\n", HostAdapter);
+		return false;
+	}
+	/*
+	   Acquire shared access to the IRQ Channel.
+	 */
+	if (request_irq(HostAdapter->IRQ_Channel, BusLogic_InterruptHandler, SA_SHIRQ, HostAdapter->FullModelName, HostAdapter) < 0) {
+		BusLogic_Error("UNABLE TO ACQUIRE IRQ CHANNEL %d - DETACHING\n", HostAdapter, HostAdapter->IRQ_Channel);
+		return false;
+	}
+	HostAdapter->IRQ_ChannelAcquired = true;
+	/*
+	   Acquire exclusive access to the DMA Channel.
+	 */
+	if (HostAdapter->DMA_Channel > 0) {
+		if (request_dma(HostAdapter->DMA_Channel, HostAdapter->FullModelName) < 0) {
+			BusLogic_Error("UNABLE TO ACQUIRE DMA CHANNEL %d - DETACHING\n", HostAdapter, HostAdapter->DMA_Channel);
+			return false;
+		}
+		set_dma_mode(HostAdapter->DMA_Channel, DMA_MODE_CASCADE);
+		enable_dma(HostAdapter->DMA_Channel);
+		HostAdapter->DMA_ChannelAcquired = true;
+	}
+	/*
+	   Indicate the System Resource Acquisition completed successfully,
+	 */
+	return true;
 }
 
 
@@ -2306,26 +1911,24 @@
 
 static void BusLogic_ReleaseResources(struct BusLogic_HostAdapter *HostAdapter)
 {
-  /*
-    Release shared access to the IRQ Channel.
-  */
-  if (HostAdapter->IRQ_ChannelAcquired)
-    free_irq(HostAdapter->IRQ_Channel, HostAdapter);
-  /*
-    Release exclusive access to the DMA Channel.
-  */
-  if (HostAdapter->DMA_ChannelAcquired)
-    free_dma(HostAdapter->DMA_Channel);
-  /*
-    Release any allocated memory structs not released elsewhere
-  */
-  if (HostAdapter->MailboxSpace)
-    pci_free_consistent(HostAdapter->PCI_Device, HostAdapter->MailboxSize,
-			HostAdapter->MailboxSpace,
-			HostAdapter->MailboxSpaceHandle);
-  HostAdapter->MailboxSpace = NULL;
-  HostAdapter->MailboxSpaceHandle = 0;
-  HostAdapter->MailboxSize = 0;
+	/*
+	   Release shared access to the IRQ Channel.
+	 */
+	if (HostAdapter->IRQ_ChannelAcquired)
+		free_irq(HostAdapter->IRQ_Channel, HostAdapter);
+	/*
+	   Release exclusive access to the DMA Channel.
+	 */
+	if (HostAdapter->DMA_ChannelAcquired)
+		free_dma(HostAdapter->DMA_Channel);
+	/*
+	   Release any allocated memory structs not released elsewhere
+	 */
+	if (HostAdapter->MailboxSpace)
+		pci_free_consistent(HostAdapter->PCI_Device, HostAdapter->MailboxSize, HostAdapter->MailboxSpace, HostAdapter->MailboxSpaceHandle);
+	HostAdapter->MailboxSpace = NULL;
+	HostAdapter->MailboxSpaceHandle = 0;
+	HostAdapter->MailboxSize = 0;
 }
 
 
@@ -2338,114 +1941,94 @@
 static boolean BusLogic_InitializeHostAdapter(struct BusLogic_HostAdapter
 					      *HostAdapter)
 {
-  struct BusLogic_ExtendedMailboxRequest ExtendedMailboxRequest;
-  enum BusLogic_RoundRobinModeRequest RoundRobinModeRequest;
-  enum BusLogic_SetCCBFormatRequest SetCCBFormatRequest;
-  int TargetID;
-  /*
-    Initialize the pointers to the first and last CCBs that are queued for
-    completion processing.
-  */
-  HostAdapter->FirstCompletedCCB = NULL;
-  HostAdapter->LastCompletedCCB = NULL;
-  /*
-    Initialize the Bus Device Reset Pending CCB, Tagged Queuing Active,
-    Command Successful Flag, Active Commands, and Commands Since Reset
-    for each Target Device.
-  */
-  for (TargetID = 0; TargetID < HostAdapter->MaxTargetDevices; TargetID++)
-    {
-      HostAdapter->BusDeviceResetPendingCCB[TargetID] = NULL;
-      HostAdapter->TargetFlags[TargetID].TaggedQueuingActive = false;
-      HostAdapter->TargetFlags[TargetID].CommandSuccessfulFlag = false;
-      HostAdapter->ActiveCommands[TargetID] = 0;
-      HostAdapter->CommandsSinceReset[TargetID] = 0;
-    }
-  /*
-    FlashPoint Host Adapters do not use Outgoing and Incoming Mailboxes.
-  */
-  if (BusLogic_FlashPointHostAdapterP(HostAdapter)) goto Done;
-  /*
-    Initialize the Outgoing and Incoming Mailbox pointers.
-  */
-  HostAdapter->MailboxSize = HostAdapter->MailboxCount *
-    (sizeof(struct BusLogic_OutgoingMailbox) + sizeof(struct BusLogic_IncomingMailbox));
-  HostAdapter->MailboxSpace = pci_alloc_consistent(HostAdapter->PCI_Device,
-    HostAdapter->MailboxSize, &HostAdapter->MailboxSpaceHandle);
-  if (HostAdapter->MailboxSpace == NULL)
-    return BusLogic_Failure(HostAdapter, "MAILBOX ALLOCATION");
-  HostAdapter->FirstOutgoingMailbox =
-    (struct BusLogic_OutgoingMailbox *) HostAdapter->MailboxSpace;
-  HostAdapter->LastOutgoingMailbox =
-    HostAdapter->FirstOutgoingMailbox + HostAdapter->MailboxCount - 1;
-  HostAdapter->NextOutgoingMailbox = HostAdapter->FirstOutgoingMailbox;
-  HostAdapter->FirstIncomingMailbox =
-    (struct BusLogic_IncomingMailbox *) (HostAdapter->LastOutgoingMailbox + 1);
-  HostAdapter->LastIncomingMailbox =
-    HostAdapter->FirstIncomingMailbox + HostAdapter->MailboxCount - 1;
-  HostAdapter->NextIncomingMailbox = HostAdapter->FirstIncomingMailbox;
-
-  /*
-    Initialize the Outgoing and Incoming Mailbox structures.
-  */
-  memset(HostAdapter->FirstOutgoingMailbox, 0,
-	 HostAdapter->MailboxCount * sizeof(struct BusLogic_OutgoingMailbox));
-  memset(HostAdapter->FirstIncomingMailbox, 0,
-	 HostAdapter->MailboxCount * sizeof(struct BusLogic_IncomingMailbox));
-  /*
-    Initialize the Host Adapter's Pointer to the Outgoing/Incoming Mailboxes.
-  */
-  ExtendedMailboxRequest.MailboxCount = HostAdapter->MailboxCount;
-  ExtendedMailboxRequest.BaseMailboxAddress =
-    (u32) HostAdapter->MailboxSpaceHandle;
-  if (BusLogic_Command(HostAdapter, BusLogic_InitializeExtendedMailbox,
-		       &ExtendedMailboxRequest,
-		       sizeof(ExtendedMailboxRequest), NULL, 0) < 0)
-    return BusLogic_Failure(HostAdapter, "MAILBOX INITIALIZATION");
-  /*
-    Enable Strict Round Robin Mode if supported by the Host Adapter.  In
-    Strict Round Robin Mode, the Host Adapter only looks at the next Outgoing
-    Mailbox for each new command, rather than scanning through all the
-    Outgoing Mailboxes to find any that have new commands in them.  Strict
-    Round Robin Mode is significantly more efficient.
-  */
-  if (HostAdapter->StrictRoundRobinModeSupport)
-    {
-      RoundRobinModeRequest = BusLogic_StrictRoundRobinMode;
-      if (BusLogic_Command(HostAdapter, BusLogic_EnableStrictRoundRobinMode,
-			   &RoundRobinModeRequest,
-			   sizeof(RoundRobinModeRequest), NULL, 0) < 0)
-	return BusLogic_Failure(HostAdapter, "ENABLE STRICT ROUND ROBIN MODE");
-    }
-  /*
-    For Host Adapters that support Extended LUN Format CCBs, issue the Set CCB
-    Format command to allow 32 Logical Units per Target Device.
-  */
-  if (HostAdapter->ExtendedLUNSupport)
-    {
-      SetCCBFormatRequest = BusLogic_ExtendedLUNFormatCCB;
-      if (BusLogic_Command(HostAdapter, BusLogic_SetCCBFormat,
-			   &SetCCBFormatRequest, sizeof(SetCCBFormatRequest),
-			   NULL, 0) < 0)
-	return BusLogic_Failure(HostAdapter, "SET CCB FORMAT");
-    }
-  /*
-    Announce Successful Initialization.
-  */
-Done:
-  if (!HostAdapter->HostAdapterInitialized)
-    {
-      BusLogic_Info("*** %s Initialized Successfully ***\n",
-		    HostAdapter, HostAdapter->FullModelName);
-      BusLogic_Info("\n", HostAdapter);
-    }
-  else BusLogic_Warning("*** %s Initialized Successfully ***\n",
-			HostAdapter, HostAdapter->FullModelName);
-  HostAdapter->HostAdapterInitialized = true;
-  /*
-    Indicate the Host Adapter Initialization completed successfully.
-  */
-  return true;
+	struct BusLogic_ExtendedMailboxRequest ExtendedMailboxRequest;
+	enum BusLogic_RoundRobinModeRequest RoundRobinModeRequest;
+	enum BusLogic_SetCCBFormatRequest SetCCBFormatRequest;
+	int TargetID;
+	/*
+	   Initialize the pointers to the first and last CCBs that are queued for
+	   completion processing.
+	 */
+	HostAdapter->FirstCompletedCCB = NULL;
+	HostAdapter->LastCompletedCCB = NULL;
+	/*
+	   Initialize the Bus Device Reset Pending CCB, Tagged Queuing Active,
+	   Command Successful Flag, Active Commands, and Commands Since Reset
+	   for each Target Device.
+	 */
+	for (TargetID = 0; TargetID < HostAdapter->MaxTargetDevices; TargetID++) {
+		HostAdapter->BusDeviceResetPendingCCB[TargetID] = NULL;
+		HostAdapter->TargetFlags[TargetID].TaggedQueuingActive = false;
+		HostAdapter->TargetFlags[TargetID].CommandSuccessfulFlag = false;
+		HostAdapter->ActiveCommands[TargetID] = 0;
+		HostAdapter->CommandsSinceReset[TargetID] = 0;
+	}
+	/*
+	   FlashPoint Host Adapters do not use Outgoing and Incoming Mailboxes.
+	 */
+	if (BusLogic_FlashPointHostAdapterP(HostAdapter))
+		goto Done;
+	/*
+	   Initialize the Outgoing and Incoming Mailbox pointers.
+	 */
+	HostAdapter->MailboxSize = HostAdapter->MailboxCount * (sizeof(struct BusLogic_OutgoingMailbox) + sizeof(struct BusLogic_IncomingMailbox));
+	HostAdapter->MailboxSpace = pci_alloc_consistent(HostAdapter->PCI_Device, HostAdapter->MailboxSize, &HostAdapter->MailboxSpaceHandle);
+	if (HostAdapter->MailboxSpace == NULL)
+		return BusLogic_Failure(HostAdapter, "MAILBOX ALLOCATION");
+	HostAdapter->FirstOutgoingMailbox = (struct BusLogic_OutgoingMailbox *) HostAdapter->MailboxSpace;
+	HostAdapter->LastOutgoingMailbox = HostAdapter->FirstOutgoingMailbox + HostAdapter->MailboxCount - 1;
+	HostAdapter->NextOutgoingMailbox = HostAdapter->FirstOutgoingMailbox;
+	HostAdapter->FirstIncomingMailbox = (struct BusLogic_IncomingMailbox *) (HostAdapter->LastOutgoingMailbox + 1);
+	HostAdapter->LastIncomingMailbox = HostAdapter->FirstIncomingMailbox + HostAdapter->MailboxCount - 1;
+	HostAdapter->NextIncomingMailbox = HostAdapter->FirstIncomingMailbox;
+
+	/*
+	   Initialize the Outgoing and Incoming Mailbox structures.
+	 */
+	memset(HostAdapter->FirstOutgoingMailbox, 0, HostAdapter->MailboxCount * sizeof(struct BusLogic_OutgoingMailbox));
+	memset(HostAdapter->FirstIncomingMailbox, 0, HostAdapter->MailboxCount * sizeof(struct BusLogic_IncomingMailbox));
+	/*
+	   Initialize the Host Adapter's Pointer to the Outgoing/Incoming Mailboxes.
+	 */
+	ExtendedMailboxRequest.MailboxCount = HostAdapter->MailboxCount;
+	ExtendedMailboxRequest.BaseMailboxAddress = (u32) HostAdapter->MailboxSpaceHandle;
+	if (BusLogic_Command(HostAdapter, BusLogic_InitializeExtendedMailbox, &ExtendedMailboxRequest, sizeof(ExtendedMailboxRequest), NULL, 0) < 0)
+		return BusLogic_Failure(HostAdapter, "MAILBOX INITIALIZATION");
+	/*
+	   Enable Strict Round Robin Mode if supported by the Host Adapter.  In
+	   Strict Round Robin Mode, the Host Adapter only looks at the next Outgoing
+	   Mailbox for each new command, rather than scanning through all the
+	   Outgoing Mailboxes to find any that have new commands in them.  Strict
+	   Round Robin Mode is significantly more efficient.
+	 */
+	if (HostAdapter->StrictRoundRobinModeSupport) {
+		RoundRobinModeRequest = BusLogic_StrictRoundRobinMode;
+		if (BusLogic_Command(HostAdapter, BusLogic_EnableStrictRoundRobinMode, &RoundRobinModeRequest, sizeof(RoundRobinModeRequest), NULL, 0) < 0)
+			return BusLogic_Failure(HostAdapter, "ENABLE STRICT ROUND ROBIN MODE");
+	}
+	/*
+	   For Host Adapters that support Extended LUN Format CCBs, issue the Set CCB
+	   Format command to allow 32 Logical Units per Target Device.
+	 */
+	if (HostAdapter->ExtendedLUNSupport) {
+		SetCCBFormatRequest = BusLogic_ExtendedLUNFormatCCB;
+		if (BusLogic_Command(HostAdapter, BusLogic_SetCCBFormat, &SetCCBFormatRequest, sizeof(SetCCBFormatRequest), NULL, 0) < 0)
+			return BusLogic_Failure(HostAdapter, "SET CCB FORMAT");
+	}
+	/*
+	   Announce Successful Initialization.
+	 */
+      Done:
+	if (!HostAdapter->HostAdapterInitialized) {
+		BusLogic_Info("*** %s Initialized Successfully ***\n", HostAdapter, HostAdapter->FullModelName);
+		BusLogic_Info("\n", HostAdapter);
+	} else
+		BusLogic_Warning("*** %s Initialized Successfully ***\n", HostAdapter, HostAdapter->FullModelName);
+	HostAdapter->HostAdapterInitialized = true;
+	/*
+	   Indicate the Host Adapter Initialization completed successfully.
+	 */
+	return true;
 }
 
 
@@ -2457,127 +2040,106 @@
 static boolean __init BusLogic_TargetDeviceInquiry(struct BusLogic_HostAdapter
 						   *HostAdapter)
 {
-  u16 InstalledDevices;
-  u8 InstalledDevicesID0to7[8];
-  struct BusLogic_SetupInformation SetupInformation;
-  u8 SynchronousPeriod[BusLogic_MaxTargetDevices];
-  unsigned char RequestedReplyLength;
-  int TargetID;
-  /*
-    Wait a few seconds between the Host Adapter Hard Reset which initiates
-    a SCSI Bus Reset and issuing any SCSI Commands.  Some SCSI devices get
-    confused if they receive SCSI Commands too soon after a SCSI Bus Reset.
-  */
-  BusLogic_Delay(HostAdapter->BusSettleTime);
-  /*
-    FlashPoint Host Adapters do not provide for Target Device Inquiry.
-  */
-  if (BusLogic_FlashPointHostAdapterP(HostAdapter)) return true;
-  /*
-    Inhibit the Target Device Inquiry if requested.
-  */
-  if (HostAdapter->DriverOptions != NULL &&
-      HostAdapter->DriverOptions->LocalOptions.InhibitTargetInquiry)
-    return true;
-  /*
-    Issue the Inquire Target Devices command for host adapters with firmware
-    version 4.25 or later, or the Inquire Installed Devices ID 0 to 7 command
-    for older host adapters.  This is necessary to force Synchronous Transfer
-    Negotiation so that the Inquire Setup Information and Inquire Synchronous
-    Period commands will return valid data.  The Inquire Target Devices command
-    is preferable to Inquire Installed Devices ID 0 to 7 since it only probes
-    Logical Unit 0 of each Target Device.
-  */
-  if (strcmp(HostAdapter->FirmwareVersion, "4.25") >= 0)
-    {
-
-      /*
-       * Issue a Inquire Target Devices command.  Inquire Target Devices only
-       * tests Logical Unit 0 of each Target Device unlike the Inquire Installed
-       * Devices commands which test Logical Units 0 - 7.  Two bytes are
-       * returned, where byte 0 bit 0 set indicates that Target Device 0 exists,
-       * and so on.
-       */
-
-      if (BusLogic_Command(HostAdapter, BusLogic_InquireTargetDevices, NULL, 0,
-			   &InstalledDevices, sizeof(InstalledDevices))
-	  != sizeof(InstalledDevices))
-	return BusLogic_Failure(HostAdapter, "INQUIRE TARGET DEVICES");
-      for (TargetID = 0; TargetID < HostAdapter->MaxTargetDevices; TargetID++)
-	HostAdapter->TargetFlags[TargetID].TargetExists =
-	  (InstalledDevices & (1 << TargetID) ? true : false);
-    }
-  else
-    {
-
-      /*
-       * Issue an Inquire Installed Devices command.  For each Target Device,
-       * a byte is returned where bit 0 set indicates that Logical Unit 0
-       * exists, bit 1 set indicates that Logical Unit 1 exists, and so on.
-       */
-
-      if (BusLogic_Command(HostAdapter, BusLogic_InquireInstalledDevicesID0to7,
-			   NULL, 0, &InstalledDevicesID0to7,
-			   sizeof(InstalledDevicesID0to7))
-	  != sizeof(InstalledDevicesID0to7))
-	return BusLogic_Failure(HostAdapter,
-				"INQUIRE INSTALLED DEVICES ID 0 TO 7");
-      for (TargetID = 0; TargetID < 8; TargetID++)
-	HostAdapter->TargetFlags[TargetID].TargetExists =
-	  (InstalledDevicesID0to7[TargetID] != 0 ? true : false);
-    }
-  /*
-    Issue the Inquire Setup Information command.
-  */
-  RequestedReplyLength = sizeof(SetupInformation);
-  if (BusLogic_Command(HostAdapter, BusLogic_InquireSetupInformation,
-		       &RequestedReplyLength, sizeof(RequestedReplyLength),
-		       &SetupInformation, sizeof(SetupInformation))
-      != sizeof(SetupInformation))
-    return BusLogic_Failure(HostAdapter, "INQUIRE SETUP INFORMATION");
-  for (TargetID = 0; TargetID < HostAdapter->MaxTargetDevices; TargetID++)
-      HostAdapter->SynchronousOffset[TargetID] =
-	(TargetID < 8
-	 ? SetupInformation.SynchronousValuesID0to7[TargetID].Offset
-	 : SetupInformation.SynchronousValuesID8to15[TargetID-8].Offset);
-  if (strcmp(HostAdapter->FirmwareVersion, "5.06L") >= 0)
-    for (TargetID = 0; TargetID < HostAdapter->MaxTargetDevices; TargetID++)
-      HostAdapter->TargetFlags[TargetID].WideTransfersActive =
-	(TargetID < 8
-	 ? (SetupInformation.WideTransfersActiveID0to7 & (1 << TargetID)
-	    ? true : false)
-	 : (SetupInformation.WideTransfersActiveID8to15 & (1 << (TargetID-8))
-	    ? true : false));
-  /*
-    Issue the Inquire Synchronous Period command.
-  */
-  if (HostAdapter->FirmwareVersion[0] >= '3')
-    {
-
-      /* Issue a Inquire Synchronous Period command.  For each Target Device,
-       * a byte is returned which represents the Synchronous Transfer Period
-       * in units of 10 nanoseconds.
-       */
-
-      RequestedReplyLength = sizeof(SynchronousPeriod);
-      if (BusLogic_Command(HostAdapter, BusLogic_InquireSynchronousPeriod,
-			   &RequestedReplyLength, sizeof(RequestedReplyLength),
-			   &SynchronousPeriod, sizeof(SynchronousPeriod))
-	  != sizeof(SynchronousPeriod))
-	return BusLogic_Failure(HostAdapter, "INQUIRE SYNCHRONOUS PERIOD");
-      for (TargetID = 0; TargetID < HostAdapter->MaxTargetDevices; TargetID++)
-	HostAdapter->SynchronousPeriod[TargetID] = SynchronousPeriod[TargetID];
-    }
-  else
-    for (TargetID = 0; TargetID < HostAdapter->MaxTargetDevices; TargetID++)
-      if (SetupInformation.SynchronousValuesID0to7[TargetID].Offset > 0)
-	HostAdapter->SynchronousPeriod[TargetID] =
-	  20 + 5 * SetupInformation.SynchronousValuesID0to7[TargetID]
-				   .TransferPeriod;
-  /*
-    Indicate the Target Device Inquiry completed successfully.
-  */
-  return true;
+	u16 InstalledDevices;
+	u8 InstalledDevicesID0to7[8];
+	struct BusLogic_SetupInformation SetupInformation;
+	u8 SynchronousPeriod[BusLogic_MaxTargetDevices];
+	unsigned char RequestedReplyLength;
+	int TargetID;
+	/*
+	   Wait a few seconds between the Host Adapter Hard Reset which initiates
+	   a SCSI Bus Reset and issuing any SCSI Commands.  Some SCSI devices get
+	   confused if they receive SCSI Commands too soon after a SCSI Bus Reset.
+	 */
+	BusLogic_Delay(HostAdapter->BusSettleTime);
+	/*
+	   FlashPoint Host Adapters do not provide for Target Device Inquiry.
+	 */
+	if (BusLogic_FlashPointHostAdapterP(HostAdapter))
+		return true;
+	/*
+	   Inhibit the Target Device Inquiry if requested.
+	 */
+	if (HostAdapter->DriverOptions != NULL && HostAdapter->DriverOptions->LocalOptions.InhibitTargetInquiry)
+		return true;
+	/*
+	   Issue the Inquire Target Devices command for host adapters with firmware
+	   version 4.25 or later, or the Inquire Installed Devices ID 0 to 7 command
+	   for older host adapters.  This is necessary to force Synchronous Transfer
+	   Negotiation so that the Inquire Setup Information and Inquire Synchronous
+	   Period commands will return valid data.  The Inquire Target Devices command
+	   is preferable to Inquire Installed Devices ID 0 to 7 since it only probes
+	   Logical Unit 0 of each Target Device.
+	 */
+	if (strcmp(HostAdapter->FirmwareVersion, "4.25") >= 0) {
+
+		/*
+		 * Issue a Inquire Target Devices command.  Inquire Target Devices only
+		 * tests Logical Unit 0 of each Target Device unlike the Inquire Installed
+		 * Devices commands which test Logical Units 0 - 7.  Two bytes are
+		 * returned, where byte 0 bit 0 set indicates that Target Device 0 exists,
+		 * and so on.
+		 */
+
+		if (BusLogic_Command(HostAdapter, BusLogic_InquireTargetDevices, NULL, 0, &InstalledDevices, sizeof(InstalledDevices))
+		    != sizeof(InstalledDevices))
+			return BusLogic_Failure(HostAdapter, "INQUIRE TARGET DEVICES");
+		for (TargetID = 0; TargetID < HostAdapter->MaxTargetDevices; TargetID++)
+			HostAdapter->TargetFlags[TargetID].TargetExists = (InstalledDevices & (1 << TargetID) ? true : false);
+	} else {
+
+		/*
+		 * Issue an Inquire Installed Devices command.  For each Target Device,
+		 * a byte is returned where bit 0 set indicates that Logical Unit 0
+		 * exists, bit 1 set indicates that Logical Unit 1 exists, and so on.
+		 */
+
+		if (BusLogic_Command(HostAdapter, BusLogic_InquireInstalledDevicesID0to7, NULL, 0, &InstalledDevicesID0to7, sizeof(InstalledDevicesID0to7))
+		    != sizeof(InstalledDevicesID0to7))
+			return BusLogic_Failure(HostAdapter, "INQUIRE INSTALLED DEVICES ID 0 TO 7");
+		for (TargetID = 0; TargetID < 8; TargetID++)
+			HostAdapter->TargetFlags[TargetID].TargetExists = (InstalledDevicesID0to7[TargetID] != 0 ? true : false);
+	}
+	/*
+	   Issue the Inquire Setup Information command.
+	 */
+	RequestedReplyLength = sizeof(SetupInformation);
+	if (BusLogic_Command(HostAdapter, BusLogic_InquireSetupInformation, &RequestedReplyLength, sizeof(RequestedReplyLength), &SetupInformation, sizeof(SetupInformation))
+	    != sizeof(SetupInformation))
+		return BusLogic_Failure(HostAdapter, "INQUIRE SETUP INFORMATION");
+	for (TargetID = 0; TargetID < HostAdapter->MaxTargetDevices; TargetID++)
+		HostAdapter->SynchronousOffset[TargetID] = (TargetID < 8 ? SetupInformation.SynchronousValuesID0to7[TargetID].Offset : SetupInformation.SynchronousValuesID8to15[TargetID - 8].Offset);
+	if (strcmp(HostAdapter->FirmwareVersion, "5.06L") >= 0)
+		for (TargetID = 0; TargetID < HostAdapter->MaxTargetDevices; TargetID++)
+			HostAdapter->TargetFlags[TargetID].WideTransfersActive = (TargetID < 8 ? (SetupInformation.WideTransfersActiveID0to7 & (1 << TargetID)
+												  ? true : false)
+										  : (SetupInformation.WideTransfersActiveID8to15 & (1 << (TargetID - 8))
+										     ? true : false));
+	/*
+	   Issue the Inquire Synchronous Period command.
+	 */
+	if (HostAdapter->FirmwareVersion[0] >= '3') {
+
+		/* Issue a Inquire Synchronous Period command.  For each Target Device,
+		 * a byte is returned which represents the Synchronous Transfer Period
+		 * in units of 10 nanoseconds.
+		 */
+
+		RequestedReplyLength = sizeof(SynchronousPeriod);
+		if (BusLogic_Command(HostAdapter, BusLogic_InquireSynchronousPeriod, &RequestedReplyLength, sizeof(RequestedReplyLength), &SynchronousPeriod, sizeof(SynchronousPeriod))
+		    != sizeof(SynchronousPeriod))
+			return BusLogic_Failure(HostAdapter, "INQUIRE SYNCHRONOUS PERIOD");
+		for (TargetID = 0; TargetID < HostAdapter->MaxTargetDevices; TargetID++)
+			HostAdapter->SynchronousPeriod[TargetID] = SynchronousPeriod[TargetID];
+	} else
+		for (TargetID = 0; TargetID < HostAdapter->MaxTargetDevices; TargetID++)
+			if (SetupInformation.SynchronousValuesID0to7[TargetID].Offset > 0)
+				HostAdapter->SynchronousPeriod[TargetID] = 20 + 5 * SetupInformation.SynchronousValuesID0to7[TargetID]
+				    .TransferPeriod;
+	/*
+	   Indicate the Target Device Inquiry completed successfully.
+	 */
+	return true;
 }
 
 /*
@@ -2590,18 +2152,17 @@
 */
 
 static void __init BusLogic_InitializeHostStructure(struct BusLogic_HostAdapter
-						    *HostAdapter,
-						    struct Scsi_Host *Host)
+						    *HostAdapter, struct Scsi_Host *Host)
 {
-  Host->max_id = HostAdapter->MaxTargetDevices;
-  Host->max_lun = HostAdapter->MaxLogicalUnits;
-  Host->max_channel = 0;
-  Host->unique_id = HostAdapter->IO_Address;
-  Host->this_id = HostAdapter->SCSI_ID;
-  Host->can_queue = HostAdapter->DriverQueueDepth;
-  Host->sg_tablesize = HostAdapter->DriverScatterGatherLimit;
-  Host->unchecked_isa_dma = HostAdapter->BounceBuffersRequired;
-  Host->cmd_per_lun = HostAdapter->UntaggedQueueDepth;
+	Host->max_id = HostAdapter->MaxTargetDevices;
+	Host->max_lun = HostAdapter->MaxLogicalUnits;
+	Host->max_channel = 0;
+	Host->unique_id = HostAdapter->IO_Address;
+	Host->this_id = HostAdapter->SCSI_ID;
+	Host->can_queue = HostAdapter->DriverQueueDepth;
+	Host->sg_tablesize = HostAdapter->DriverScatterGatherLimit;
+	Host->unchecked_isa_dma = HostAdapter->BounceBuffersRequired;
+	Host->cmd_per_lun = HostAdapter->UntaggedQueueDepth;
 }
 
 /*
@@ -2614,38 +2175,29 @@
 */
 static int BusLogic_SlaveConfigure(struct scsi_device *Device)
 {
-  struct BusLogic_HostAdapter *HostAdapter =
-    (struct BusLogic_HostAdapter *) Device->host->hostdata;
-  int TargetID = Device->id;
-  int QueueDepth = HostAdapter->QueueDepth[TargetID];
-
-  if (HostAdapter->TargetFlags[TargetID].TaggedQueuingSupported &&
-      (HostAdapter->TaggedQueuingPermitted & (1 << TargetID)))
-    {
-      if (QueueDepth == 0)
-	QueueDepth = BusLogic_MaxAutomaticTaggedQueueDepth;
-      HostAdapter->QueueDepth[TargetID] = QueueDepth;
-      scsi_adjust_queue_depth(Device, MSG_SIMPLE_TAG, QueueDepth);
-    }
-  else
-    {
-      HostAdapter->TaggedQueuingPermitted &= ~(1 << TargetID);
-      QueueDepth = HostAdapter->UntaggedQueueDepth;
-      HostAdapter->QueueDepth[TargetID] = QueueDepth;
-      scsi_adjust_queue_depth(Device, 0, QueueDepth);
-    }
-  QueueDepth = 0;
-  for (TargetID = 0; TargetID < HostAdapter->MaxTargetDevices; TargetID++)
-    if (HostAdapter->TargetFlags[TargetID].TargetExists)
-      {
-	QueueDepth += HostAdapter->QueueDepth[TargetID];
-      }
-  if (QueueDepth > HostAdapter->AllocatedCCBs)
-    BusLogic_CreateAdditionalCCBs(HostAdapter,
-				  QueueDepth
-				  - HostAdapter->AllocatedCCBs,
-				  false);
-  return 0;
+	struct BusLogic_HostAdapter *HostAdapter = (struct BusLogic_HostAdapter *) Device->host->hostdata;
+	int TargetID = Device->id;
+	int QueueDepth = HostAdapter->QueueDepth[TargetID];
+
+	if (HostAdapter->TargetFlags[TargetID].TaggedQueuingSupported && (HostAdapter->TaggedQueuingPermitted & (1 << TargetID))) {
+		if (QueueDepth == 0)
+			QueueDepth = BusLogic_MaxAutomaticTaggedQueueDepth;
+		HostAdapter->QueueDepth[TargetID] = QueueDepth;
+		scsi_adjust_queue_depth(Device, MSG_SIMPLE_TAG, QueueDepth);
+	} else {
+		HostAdapter->TaggedQueuingPermitted &= ~(1 << TargetID);
+		QueueDepth = HostAdapter->UntaggedQueueDepth;
+		HostAdapter->QueueDepth[TargetID] = QueueDepth;
+		scsi_adjust_queue_depth(Device, 0, QueueDepth);
+	}
+	QueueDepth = 0;
+	for (TargetID = 0; TargetID < HostAdapter->MaxTargetDevices; TargetID++)
+		if (HostAdapter->TargetFlags[TargetID].TargetExists) {
+			QueueDepth += HostAdapter->QueueDepth[TargetID];
+		}
+	if (QueueDepth > HostAdapter->AllocatedCCBs)
+		BusLogic_CreateAdditionalCCBs(HostAdapter, QueueDepth - HostAdapter->AllocatedCCBs, false);
+	return 0;
 }
 
 /*
@@ -2658,162 +2210,145 @@
 
 static int __init BusLogic_DetectHostAdapter(struct scsi_host_template *HostTemplate)
 {
-  int BusLogicHostAdapterCount = 0, DriverOptionsIndex = 0, ProbeIndex;
-  struct BusLogic_HostAdapter *PrototypeHostAdapter;
-  if (BusLogic_ProbeOptions.NoProbe) return 0;
-  BusLogic_ProbeInfoList = (struct BusLogic_ProbeInfo *)
-    kmalloc(BusLogic_MaxHostAdapters * sizeof(struct BusLogic_ProbeInfo),
-	    GFP_ATOMIC);
-  if (BusLogic_ProbeInfoList == NULL)
-    {
-      BusLogic_Error("BusLogic: Unable to allocate Probe Info List\n", NULL);
-      return 0;
-    }
-  memset(BusLogic_ProbeInfoList, 0,
-	 BusLogic_MaxHostAdapters * sizeof(struct BusLogic_ProbeInfo));
-  PrototypeHostAdapter = (struct BusLogic_HostAdapter *)
-    kmalloc(sizeof(struct BusLogic_HostAdapter), GFP_ATOMIC);
-  if (PrototypeHostAdapter == NULL)
-    {
-      kfree(BusLogic_ProbeInfoList);
-      BusLogic_Error("BusLogic: Unable to allocate Prototype "
-		     "Host Adapter\n", NULL);
-      return 0;
-    }
-  memset(PrototypeHostAdapter, 0, sizeof(struct BusLogic_HostAdapter));
+	int BusLogicHostAdapterCount = 0, DriverOptionsIndex = 0, ProbeIndex;
+	struct BusLogic_HostAdapter *PrototypeHostAdapter;
+	if (BusLogic_ProbeOptions.NoProbe)
+		return 0;
+	BusLogic_ProbeInfoList = (struct BusLogic_ProbeInfo *)
+	    kmalloc(BusLogic_MaxHostAdapters * sizeof(struct BusLogic_ProbeInfo), GFP_ATOMIC);
+	if (BusLogic_ProbeInfoList == NULL) {
+		BusLogic_Error("BusLogic: Unable to allocate Probe Info List\n", NULL);
+		return 0;
+	}
+	memset(BusLogic_ProbeInfoList, 0, BusLogic_MaxHostAdapters * sizeof(struct BusLogic_ProbeInfo));
+	PrototypeHostAdapter = (struct BusLogic_HostAdapter *)
+	    kmalloc(sizeof(struct BusLogic_HostAdapter), GFP_ATOMIC);
+	if (PrototypeHostAdapter == NULL) {
+		kfree(BusLogic_ProbeInfoList);
+		BusLogic_Error("BusLogic: Unable to allocate Prototype " "Host Adapter\n", NULL);
+		return 0;
+	}
+	memset(PrototypeHostAdapter, 0, sizeof(struct BusLogic_HostAdapter));
 #ifdef MODULE
-  if (BusLogic != NULL)
-    BusLogic_Setup(BusLogic);
+	if (BusLogic != NULL)
+		BusLogic_Setup(BusLogic);
 #endif
-  BusLogic_InitializeProbeInfoList(PrototypeHostAdapter);
-  for (ProbeIndex = 0; ProbeIndex < BusLogic_ProbeInfoCount; ProbeIndex++)
-    {
-      struct BusLogic_ProbeInfo *ProbeInfo = &BusLogic_ProbeInfoList[ProbeIndex];
-      struct BusLogic_HostAdapter *HostAdapter = PrototypeHostAdapter;
-      struct Scsi_Host *Host;
-      if (ProbeInfo->IO_Address == 0) continue;
-      memset(HostAdapter, 0, sizeof(struct BusLogic_HostAdapter));
-      HostAdapter->HostAdapterType = ProbeInfo->HostAdapterType;
-      HostAdapter->HostAdapterBusType = ProbeInfo->HostAdapterBusType;
-      HostAdapter->IO_Address = ProbeInfo->IO_Address;
-      HostAdapter->PCI_Address = ProbeInfo->PCI_Address;
-      HostAdapter->Bus = ProbeInfo->Bus;
-      HostAdapter->Device = ProbeInfo->Device;
-      HostAdapter->IRQ_Channel = ProbeInfo->IRQ_Channel;
-      HostAdapter->AddressCount =
-	BusLogic_HostAdapterAddressCount[HostAdapter->HostAdapterType];
-      /*
-	Probe the Host Adapter.  If unsuccessful, abort further initialization.
-      */
-      if (!BusLogic_ProbeHostAdapter(HostAdapter)) continue;
-      /*
-	Hard Reset the Host Adapter.  If unsuccessful, abort further
-	initialization.
-      */
-      if (!BusLogic_HardwareResetHostAdapter(HostAdapter, true)) continue;
-      /*
-	Check the Host Adapter.  If unsuccessful, abort further initialization.
-      */
-      if (!BusLogic_CheckHostAdapter(HostAdapter)) continue;
-      /*
-	Initialize the Driver Options field if provided.
-      */
-      if (DriverOptionsIndex < BusLogic_DriverOptionsCount)
-	HostAdapter->DriverOptions =
-	  &BusLogic_DriverOptions[DriverOptionsIndex++];
-      /*
-	Announce the Driver Version and Date, Author's Name, Copyright Notice,
-	and Electronic Mail Address.
-      */
-      BusLogic_AnnounceDriver(HostAdapter);
-      /*
-	Register usage of the I/O Address range.  From this point onward, any
-	failure will be assumed to be due to a problem with the Host Adapter,
-	rather than due to having mistakenly identified this port as belonging
-	to a BusLogic Host Adapter.  The I/O Address range will not be
-	released, thereby preventing it from being incorrectly identified as
-	any other type of Host Adapter.
-      */
-      if (!request_region(HostAdapter->IO_Address, HostAdapter->AddressCount,
-		     "BusLogic")) continue;
-      /*
-	Register the SCSI Host structure.
-      */
-
-      Host = scsi_host_alloc(HostTemplate, sizeof(struct BusLogic_HostAdapter));
-      if(Host==NULL)
-      {
-      	release_region(HostAdapter->IO_Address, HostAdapter->AddressCount);
-      	continue;
-      }
-      HostAdapter = (struct BusLogic_HostAdapter *) Host->hostdata;
-      memcpy(HostAdapter, PrototypeHostAdapter, sizeof(struct BusLogic_HostAdapter));
-      HostAdapter->SCSI_Host = Host;
-      HostAdapter->HostNumber = Host->host_no;
-      /*
-	Add Host Adapter to the end of the list of registered BusLogic
-	Host Adapters.
-      */
-      BusLogic_RegisterHostAdapter(HostAdapter);
-      /*
-	Read the Host Adapter Configuration, Configure the Host Adapter,
-	Acquire the System Resources necessary to use the Host Adapter, then
-	Create the Initial CCBs, Initialize the Host Adapter, and finally
-	perform Target Device Inquiry.
-      */
-      if (BusLogic_ReadHostAdapterConfiguration(HostAdapter) &&
-	  BusLogic_ReportHostAdapterConfiguration(HostAdapter) &&
-	  BusLogic_AcquireResources(HostAdapter) &&
-	  BusLogic_CreateInitialCCBs(HostAdapter) &&
-	  BusLogic_InitializeHostAdapter(HostAdapter) &&
-	  BusLogic_TargetDeviceInquiry(HostAdapter))
-	{
-	  /*
-	    Initialization has been completed successfully.  Release and
-	    re-register usage of the I/O Address range so that the Model
-	    Name of the Host Adapter will appear, and initialize the SCSI
-	    Host structure.
-	  */
-	  release_region(HostAdapter->IO_Address,
-			 HostAdapter->AddressCount);
-	  if(!request_region(HostAdapter->IO_Address,
-			     HostAdapter->AddressCount,
-			     HostAdapter->FullModelName)) {
-		  printk(KERN_WARNING "BusLogic: Release and re-register of "
-			 "port 0x%04lx failed \n",
-			 (unsigned long)HostAdapter->IO_Address);
-		  BusLogic_DestroyCCBs(HostAdapter);
-		  BusLogic_ReleaseResources(HostAdapter);
-		  BusLogic_UnregisterHostAdapter(HostAdapter);
-		  scsi_host_put(Host);
-	  }
-	  else {
-		  BusLogic_InitializeHostStructure(HostAdapter, Host);
-	          scsi_add_host(Host, NULL);
-	          scsi_scan_host(Host);
-		  BusLogicHostAdapterCount++;
-	  }
-	}
-      else
-	{
-	  /*
-	    An error occurred during Host Adapter Configuration Querying, Host
-	    Adapter Configuration, Resource Acquisition, CCB Creation, Host
-	    Adapter Initialization, or Target Device Inquiry, so remove Host
-	    Adapter from the list of registered BusLogic Host Adapters, destroy
-	    the CCBs, Release the System Resources, and Unregister the SCSI
-	    Host.
-	  */
-	  BusLogic_DestroyCCBs(HostAdapter);
-	  BusLogic_ReleaseResources(HostAdapter);
-	  BusLogic_UnregisterHostAdapter(HostAdapter);
-	  scsi_host_put(Host);
-	}
-    }
-  kfree(PrototypeHostAdapter);
-  kfree(BusLogic_ProbeInfoList);
-  BusLogic_ProbeInfoList = NULL;
-  return BusLogicHostAdapterCount;
+	BusLogic_InitializeProbeInfoList(PrototypeHostAdapter);
+	for (ProbeIndex = 0; ProbeIndex < BusLogic_ProbeInfoCount; ProbeIndex++) {
+		struct BusLogic_ProbeInfo *ProbeInfo = &BusLogic_ProbeInfoList[ProbeIndex];
+		struct BusLogic_HostAdapter *HostAdapter = PrototypeHostAdapter;
+		struct Scsi_Host *Host;
+		if (ProbeInfo->IO_Address == 0)
+			continue;
+		memset(HostAdapter, 0, sizeof(struct BusLogic_HostAdapter));
+		HostAdapter->HostAdapterType = ProbeInfo->HostAdapterType;
+		HostAdapter->HostAdapterBusType = ProbeInfo->HostAdapterBusType;
+		HostAdapter->IO_Address = ProbeInfo->IO_Address;
+		HostAdapter->PCI_Address = ProbeInfo->PCI_Address;
+		HostAdapter->Bus = ProbeInfo->Bus;
+		HostAdapter->Device = ProbeInfo->Device;
+		HostAdapter->IRQ_Channel = ProbeInfo->IRQ_Channel;
+		HostAdapter->AddressCount = BusLogic_HostAdapterAddressCount[HostAdapter->HostAdapterType];
+		/*
+		   Probe the Host Adapter.  If unsuccessful, abort further initialization.
+		 */
+		if (!BusLogic_ProbeHostAdapter(HostAdapter))
+			continue;
+		/*
+		   Hard Reset the Host Adapter.  If unsuccessful, abort further
+		   initialization.
+		 */
+		if (!BusLogic_HardwareResetHostAdapter(HostAdapter, true))
+			continue;
+		/*
+		   Check the Host Adapter.  If unsuccessful, abort further initialization.
+		 */
+		if (!BusLogic_CheckHostAdapter(HostAdapter))
+			continue;
+		/*
+		   Initialize the Driver Options field if provided.
+		 */
+		if (DriverOptionsIndex < BusLogic_DriverOptionsCount)
+			HostAdapter->DriverOptions = &BusLogic_DriverOptions[DriverOptionsIndex++];
+		/*
+		   Announce the Driver Version and Date, Author's Name, Copyright Notice,
+		   and Electronic Mail Address.
+		 */
+		BusLogic_AnnounceDriver(HostAdapter);
+		/*
+		   Register usage of the I/O Address range.  From this point onward, any
+		   failure will be assumed to be due to a problem with the Host Adapter,
+		   rather than due to having mistakenly identified this port as belonging
+		   to a BusLogic Host Adapter.  The I/O Address range will not be
+		   released, thereby preventing it from being incorrectly identified as
+		   any other type of Host Adapter.
+		 */
+		if (!request_region(HostAdapter->IO_Address, HostAdapter->AddressCount, "BusLogic"))
+			continue;
+		/*
+		   Register the SCSI Host structure.
+		 */
+
+		Host = scsi_host_alloc(HostTemplate, sizeof(struct BusLogic_HostAdapter));
+		if (Host == NULL) {
+			release_region(HostAdapter->IO_Address, HostAdapter->AddressCount);
+			continue;
+		}
+		HostAdapter = (struct BusLogic_HostAdapter *) Host->hostdata;
+		memcpy(HostAdapter, PrototypeHostAdapter, sizeof(struct BusLogic_HostAdapter));
+		HostAdapter->SCSI_Host = Host;
+		HostAdapter->HostNumber = Host->host_no;
+		/*
+		   Add Host Adapter to the end of the list of registered BusLogic
+		   Host Adapters.
+		 */
+		BusLogic_RegisterHostAdapter(HostAdapter);
+		/*
+		   Read the Host Adapter Configuration, Configure the Host Adapter,
+		   Acquire the System Resources necessary to use the Host Adapter, then
+		   Create the Initial CCBs, Initialize the Host Adapter, and finally
+		   perform Target Device Inquiry.
+		 */
+		if (BusLogic_ReadHostAdapterConfiguration(HostAdapter) &&
+		    BusLogic_ReportHostAdapterConfiguration(HostAdapter) && BusLogic_AcquireResources(HostAdapter) && BusLogic_CreateInitialCCBs(HostAdapter) && BusLogic_InitializeHostAdapter(HostAdapter) && BusLogic_TargetDeviceInquiry(HostAdapter)) {
+			/*
+			   Initialization has been completed successfully.  Release and
+			   re-register usage of the I/O Address range so that the Model
+			   Name of the Host Adapter will appear, and initialize the SCSI
+			   Host structure.
+			 */
+			release_region(HostAdapter->IO_Address, HostAdapter->AddressCount);
+			if (!request_region(HostAdapter->IO_Address, HostAdapter->AddressCount, HostAdapter->FullModelName)) {
+				printk(KERN_WARNING "BusLogic: Release and re-register of " "port 0x%04lx failed \n", (unsigned long) HostAdapter->IO_Address);
+				BusLogic_DestroyCCBs(HostAdapter);
+				BusLogic_ReleaseResources(HostAdapter);
+				BusLogic_UnregisterHostAdapter(HostAdapter);
+				scsi_host_put(Host);
+			} else {
+				BusLogic_InitializeHostStructure(HostAdapter, Host);
+				scsi_add_host(Host, NULL);
+				scsi_scan_host(Host);
+				BusLogicHostAdapterCount++;
+			}
+		} else {
+			/*
+			   An error occurred during Host Adapter Configuration Querying, Host
+			   Adapter Configuration, Resource Acquisition, CCB Creation, Host
+			   Adapter Initialization, or Target Device Inquiry, so remove Host
+			   Adapter from the list of registered BusLogic Host Adapters, destroy
+			   the CCBs, Release the System Resources, and Unregister the SCSI
+			   Host.
+			 */
+			BusLogic_DestroyCCBs(HostAdapter);
+			BusLogic_ReleaseResources(HostAdapter);
+			BusLogic_UnregisterHostAdapter(HostAdapter);
+			scsi_host_put(Host);
+		}
+	}
+	kfree(PrototypeHostAdapter);
+	kfree(BusLogic_ProbeInfoList);
+	BusLogic_ProbeInfoList = NULL;
+	return BusLogicHostAdapterCount;
 }
 
 
@@ -2825,29 +2360,28 @@
 
 static int __exit BusLogic_ReleaseHostAdapter(struct Scsi_Host *Host)
 {
-  struct BusLogic_HostAdapter *HostAdapter =
-    (struct BusLogic_HostAdapter *) Host->hostdata;
-  /*
-    FlashPoint Host Adapters must first be released by the FlashPoint
-    SCCB Manager.
-  */
-  if (BusLogic_FlashPointHostAdapterP(HostAdapter))
-    FlashPoint_ReleaseHostAdapter(HostAdapter->CardHandle);
-  /*
-    Destroy the CCBs and release any system resources acquired to
-    support Host Adapter.
-  */
-  BusLogic_DestroyCCBs(HostAdapter);
-  BusLogic_ReleaseResources(HostAdapter);
-  /*
-    Release usage of the I/O Address range.
-  */
-  release_region(HostAdapter->IO_Address, HostAdapter->AddressCount);
-  /*
-    Remove Host Adapter from the list of registered BusLogic Host Adapters.
-  */
-  BusLogic_UnregisterHostAdapter(HostAdapter);
-  return 0;
+	struct BusLogic_HostAdapter *HostAdapter = (struct BusLogic_HostAdapter *) Host->hostdata;
+	/*
+	   FlashPoint Host Adapters must first be released by the FlashPoint
+	   SCCB Manager.
+	 */
+	if (BusLogic_FlashPointHostAdapterP(HostAdapter))
+		FlashPoint_ReleaseHostAdapter(HostAdapter->CardHandle);
+	/*
+	   Destroy the CCBs and release any system resources acquired to
+	   support Host Adapter.
+	 */
+	BusLogic_DestroyCCBs(HostAdapter);
+	BusLogic_ReleaseResources(HostAdapter);
+	/*
+	   Release usage of the I/O Address range.
+	 */
+	release_region(HostAdapter->IO_Address, HostAdapter->AddressCount);
+	/*
+	   Remove Host Adapter from the list of registered BusLogic Host Adapters.
+	 */
+	BusLogic_UnregisterHostAdapter(HostAdapter);
+	return 0;
 }
 
 
@@ -2857,20 +2391,17 @@
 
 static void BusLogic_QueueCompletedCCB(struct BusLogic_CCB *CCB)
 {
-  struct BusLogic_HostAdapter *HostAdapter = CCB->HostAdapter;
-  CCB->Status = BusLogic_CCB_Completed;
-  CCB->Next = NULL;
-  if (HostAdapter->FirstCompletedCCB == NULL)
-    {
-      HostAdapter->FirstCompletedCCB = CCB;
-      HostAdapter->LastCompletedCCB = CCB;
-    }
-  else
-    {
-      HostAdapter->LastCompletedCCB->Next = CCB;
-      HostAdapter->LastCompletedCCB = CCB;
-    }
-  HostAdapter->ActiveCommands[CCB->TargetID]--;
+	struct BusLogic_HostAdapter *HostAdapter = CCB->HostAdapter;
+	CCB->Status = BusLogic_CCB_Completed;
+	CCB->Next = NULL;
+	if (HostAdapter->FirstCompletedCCB == NULL) {
+		HostAdapter->FirstCompletedCCB = CCB;
+		HostAdapter->LastCompletedCCB = CCB;
+	} else {
+		HostAdapter->LastCompletedCCB->Next = CCB;
+		HostAdapter->LastCompletedCCB = CCB;
+	}
+	HostAdapter->ActiveCommands[CCB->TargetID]--;
 }
 
 
@@ -2879,57 +2410,50 @@
   the Host Adapter Status and Target Device Status.
 */
 
-static int BusLogic_ComputeResultCode(struct BusLogic_HostAdapter *HostAdapter,
-				      enum BusLogic_HostAdapterStatus
-					HostAdapterStatus,
-				      enum BusLogic_TargetDeviceStatus
-					TargetDeviceStatus)
-{
-  int HostStatus;
-  switch (HostAdapterStatus)
-    {
-    case BusLogic_CommandCompletedNormally:
-    case BusLogic_LinkedCommandCompleted:
-    case BusLogic_LinkedCommandCompletedWithFlag:
-      HostStatus = DID_OK;
-      break;
-    case BusLogic_SCSISelectionTimeout:
-      HostStatus = DID_TIME_OUT;
-      break;
-    case BusLogic_InvalidOutgoingMailboxActionCode:
-    case BusLogic_InvalidCommandOperationCode:
-    case BusLogic_InvalidCommandParameter:
-      BusLogic_Warning("BusLogic Driver Protocol Error 0x%02X\n",
-		       HostAdapter, HostAdapterStatus);
-    case BusLogic_DataUnderRun:
-    case BusLogic_DataOverRun:
-    case BusLogic_UnexpectedBusFree:
-    case BusLogic_LinkedCCBhasInvalidLUN:
-    case BusLogic_AutoRequestSenseFailed:
-    case BusLogic_TaggedQueuingMessageRejected:
-    case BusLogic_UnsupportedMessageReceived:
-    case BusLogic_HostAdapterHardwareFailed:
-    case BusLogic_TargetDeviceReconnectedImproperly:
-    case BusLogic_AbortQueueGenerated:
-    case BusLogic_HostAdapterSoftwareError:
-    case BusLogic_HostAdapterHardwareTimeoutError:
-    case BusLogic_SCSIParityErrorDetected:
-      HostStatus = DID_ERROR;
-      break;
-    case BusLogic_InvalidBusPhaseRequested:
-    case BusLogic_TargetFailedResponseToATN:
-    case BusLogic_HostAdapterAssertedRST:
-    case BusLogic_OtherDeviceAssertedRST:
-    case BusLogic_HostAdapterAssertedBusDeviceReset:
-      HostStatus = DID_RESET;
-      break;
-    default:
-      BusLogic_Warning("Unknown Host Adapter Status 0x%02X\n",
-		       HostAdapter, HostAdapterStatus);
-      HostStatus = DID_ERROR;
-      break;
-    }
-  return (HostStatus << 16) | TargetDeviceStatus;
+static int BusLogic_ComputeResultCode(struct BusLogic_HostAdapter *HostAdapter, enum BusLogic_HostAdapterStatus HostAdapterStatus, enum BusLogic_TargetDeviceStatus TargetDeviceStatus)
+{
+	int HostStatus;
+	switch (HostAdapterStatus) {
+	case BusLogic_CommandCompletedNormally:
+	case BusLogic_LinkedCommandCompleted:
+	case BusLogic_LinkedCommandCompletedWithFlag:
+		HostStatus = DID_OK;
+		break;
+	case BusLogic_SCSISelectionTimeout:
+		HostStatus = DID_TIME_OUT;
+		break;
+	case BusLogic_InvalidOutgoingMailboxActionCode:
+	case BusLogic_InvalidCommandOperationCode:
+	case BusLogic_InvalidCommandParameter:
+		BusLogic_Warning("BusLogic Driver Protocol Error 0x%02X\n", HostAdapter, HostAdapterStatus);
+	case BusLogic_DataUnderRun:
+	case BusLogic_DataOverRun:
+	case BusLogic_UnexpectedBusFree:
+	case BusLogic_LinkedCCBhasInvalidLUN:
+	case BusLogic_AutoRequestSenseFailed:
+	case BusLogic_TaggedQueuingMessageRejected:
+	case BusLogic_UnsupportedMessageReceived:
+	case BusLogic_HostAdapterHardwareFailed:
+	case BusLogic_TargetDeviceReconnectedImproperly:
+	case BusLogic_AbortQueueGenerated:
+	case BusLogic_HostAdapterSoftwareError:
+	case BusLogic_HostAdapterHardwareTimeoutError:
+	case BusLogic_SCSIParityErrorDetected:
+		HostStatus = DID_ERROR;
+		break;
+	case BusLogic_InvalidBusPhaseRequested:
+	case BusLogic_TargetFailedResponseToATN:
+	case BusLogic_HostAdapterAssertedRST:
+	case BusLogic_OtherDeviceAssertedRST:
+	case BusLogic_HostAdapterAssertedBusDeviceReset:
+		HostStatus = DID_RESET;
+		break;
+	default:
+		BusLogic_Warning("Unknown Host Adapter Status 0x%02X\n", HostAdapter, HostAdapterStatus);
+		HostStatus = DID_ERROR;
+		break;
+	}
+	return (HostStatus << 16) | TargetDeviceStatus;
 }
 
 
@@ -2940,62 +2464,51 @@
 
 static void BusLogic_ScanIncomingMailboxes(struct BusLogic_HostAdapter *HostAdapter)
 {
-  /*
-    Scan through the Incoming Mailboxes in Strict Round Robin fashion, saving
-    any completed CCBs for further processing.  It is essential that for each
-    CCB and SCSI Command issued, command completion processing is performed
-    exactly once.  Therefore, only Incoming Mailboxes with completion code
-    Command Completed Without Error, Command Completed With Error, or Command
-    Aborted At Host Request are saved for completion processing.  When an
-    Incoming Mailbox has a completion code of Aborted Command Not Found, the
-    CCB had already completed or been aborted before the current Abort request
-    was processed, and so completion processing has already occurred and no
-    further action should be taken.
-  */
-  struct BusLogic_IncomingMailbox *NextIncomingMailbox =
-    HostAdapter->NextIncomingMailbox;
-  enum BusLogic_CompletionCode CompletionCode;
-  while ((CompletionCode = NextIncomingMailbox->CompletionCode) !=
-	 BusLogic_IncomingMailboxFree)
-    {
-      /*
-        We are only allowed to do this because we limit our architectures we
-        run on to machines where bus_to_virt() actually works.  There *needs*
-        to be a dma_addr_to_virt() in the new PCI DMA mapping interface to
-        replace bus_to_virt() or else this code is going to become very
-        innefficient.
-      */
-      struct BusLogic_CCB *CCB = (struct BusLogic_CCB *)
-	Bus_to_Virtual(NextIncomingMailbox->CCB);
-      if (CompletionCode != BusLogic_AbortedCommandNotFound)
-	{
-	  if (CCB->Status == BusLogic_CCB_Active ||
-	      CCB->Status == BusLogic_CCB_Reset)
-	    {
-	      /*
-		Save the Completion Code for this CCB and queue the CCB
-		for completion processing.
-	      */
-	      CCB->CompletionCode = CompletionCode;
-	      BusLogic_QueueCompletedCCB(CCB);
-	    }
-	  else
-	    {
-	      /*
-		If a CCB ever appears in an Incoming Mailbox and is not marked
-		as status Active or Reset, then there is most likely a bug in
-		the Host Adapter firmware.
-	      */
-	      BusLogic_Warning("Illegal CCB #%ld status %d in "
-			       "Incoming Mailbox\n", HostAdapter,
-			       CCB->SerialNumber, CCB->Status);
-	    }
-	}
-      NextIncomingMailbox->CompletionCode = BusLogic_IncomingMailboxFree;
-      if (++NextIncomingMailbox > HostAdapter->LastIncomingMailbox)
-	NextIncomingMailbox = HostAdapter->FirstIncomingMailbox;
-    }
-  HostAdapter->NextIncomingMailbox = NextIncomingMailbox;
+	/*
+	   Scan through the Incoming Mailboxes in Strict Round Robin fashion, saving
+	   any completed CCBs for further processing.  It is essential that for each
+	   CCB and SCSI Command issued, command completion processing is performed
+	   exactly once.  Therefore, only Incoming Mailboxes with completion code
+	   Command Completed Without Error, Command Completed With Error, or Command
+	   Aborted At Host Request are saved for completion processing.  When an
+	   Incoming Mailbox has a completion code of Aborted Command Not Found, the
+	   CCB had already completed or been aborted before the current Abort request
+	   was processed, and so completion processing has already occurred and no
+	   further action should be taken.
+	 */
+	struct BusLogic_IncomingMailbox *NextIncomingMailbox = HostAdapter->NextIncomingMailbox;
+	enum BusLogic_CompletionCode CompletionCode;
+	while ((CompletionCode = NextIncomingMailbox->CompletionCode) != BusLogic_IncomingMailboxFree) {
+		/*
+		   We are only allowed to do this because we limit our architectures we
+		   run on to machines where bus_to_virt() actually works.  There *needs*
+		   to be a dma_addr_to_virt() in the new PCI DMA mapping interface to
+		   replace bus_to_virt() or else this code is going to become very
+		   innefficient.
+		 */
+		struct BusLogic_CCB *CCB = (struct BusLogic_CCB *) Bus_to_Virtual(NextIncomingMailbox->CCB);
+		if (CompletionCode != BusLogic_AbortedCommandNotFound) {
+			if (CCB->Status == BusLogic_CCB_Active || CCB->Status == BusLogic_CCB_Reset) {
+				/*
+				   Save the Completion Code for this CCB and queue the CCB
+				   for completion processing.
+				 */
+				CCB->CompletionCode = CompletionCode;
+				BusLogic_QueueCompletedCCB(CCB);
+			} else {
+				/*
+				   If a CCB ever appears in an Incoming Mailbox and is not marked
+				   as status Active or Reset, then there is most likely a bug in
+				   the Host Adapter firmware.
+				 */
+				BusLogic_Warning("Illegal CCB #%ld status %d in " "Incoming Mailbox\n", HostAdapter, CCB->SerialNumber, CCB->Status);
+			}
+		}
+		NextIncomingMailbox->CompletionCode = BusLogic_IncomingMailboxFree;
+		if (++NextIncomingMailbox > HostAdapter->LastIncomingMailbox)
+			NextIncomingMailbox = HostAdapter->FirstIncomingMailbox;
+	}
+	HostAdapter->NextIncomingMailbox = NextIncomingMailbox;
 }
 
 
@@ -3008,153 +2521,126 @@
 
 static void BusLogic_ProcessCompletedCCBs(struct BusLogic_HostAdapter *HostAdapter)
 {
-  if (HostAdapter->ProcessCompletedCCBsActive) return;
-  HostAdapter->ProcessCompletedCCBsActive = true;
-  while (HostAdapter->FirstCompletedCCB != NULL)
-    {
-      struct BusLogic_CCB *CCB = HostAdapter->FirstCompletedCCB;
-      struct scsi_cmnd *Command = CCB->Command;
-      HostAdapter->FirstCompletedCCB = CCB->Next;
-      if (HostAdapter->FirstCompletedCCB == NULL)
-	HostAdapter->LastCompletedCCB = NULL;
-      /*
-	Process the Completed CCB.
-      */
-      if (CCB->Opcode == BusLogic_BusDeviceReset)
-	{
-	  int TargetID = CCB->TargetID;
-	  BusLogic_Warning("Bus Device Reset CCB #%ld to Target "
-			   "%d Completed\n", HostAdapter,
-			   CCB->SerialNumber, TargetID);
-	  BusLogic_IncrementErrorCounter(
-	    &HostAdapter->TargetStatistics[TargetID].BusDeviceResetsCompleted);
-	  HostAdapter->TargetFlags[TargetID].TaggedQueuingActive = false;
-	  HostAdapter->CommandsSinceReset[TargetID] = 0;
-	  HostAdapter->LastResetCompleted[TargetID] = jiffies;
-	  /*
-	    Place CCB back on the Host Adapter's free list.
-	  */
-	  BusLogic_DeallocateCCB(CCB);
-#if 0	/* this needs to be redone different for new EH */
-	  /*
-	    Bus Device Reset CCBs have the Command field non-NULL only when a
-	    Bus Device Reset was requested for a Command that did not have a
-	    currently active CCB in the Host Adapter (i.e., a Synchronous
-	    Bus Device Reset), and hence would not have its Completion Routine
-	    called otherwise.
-	  */
-	  while (Command != NULL)
-	    {
-	      struct scsi_cmnd *NextCommand = Command->reset_chain;
-	      Command->reset_chain = NULL;
-	      Command->result = DID_RESET << 16;
-	      Command->scsi_done(Command);
-	      Command = NextCommand;
-	    }
+	if (HostAdapter->ProcessCompletedCCBsActive)
+		return;
+	HostAdapter->ProcessCompletedCCBsActive = true;
+	while (HostAdapter->FirstCompletedCCB != NULL) {
+		struct BusLogic_CCB *CCB = HostAdapter->FirstCompletedCCB;
+		struct scsi_cmnd *Command = CCB->Command;
+		HostAdapter->FirstCompletedCCB = CCB->Next;
+		if (HostAdapter->FirstCompletedCCB == NULL)
+			HostAdapter->LastCompletedCCB = NULL;
+		/*
+		   Process the Completed CCB.
+		 */
+		if (CCB->Opcode == BusLogic_BusDeviceReset) {
+			int TargetID = CCB->TargetID;
+			BusLogic_Warning("Bus Device Reset CCB #%ld to Target " "%d Completed\n", HostAdapter, CCB->SerialNumber, TargetID);
+			BusLogic_IncrementErrorCounter(&HostAdapter->TargetStatistics[TargetID].BusDeviceResetsCompleted);
+			HostAdapter->TargetFlags[TargetID].TaggedQueuingActive = false;
+			HostAdapter->CommandsSinceReset[TargetID] = 0;
+			HostAdapter->LastResetCompleted[TargetID] = jiffies;
+			/*
+			   Place CCB back on the Host Adapter's free list.
+			 */
+			BusLogic_DeallocateCCB(CCB);
+#if 0				/* this needs to be redone different for new EH */
+			/*
+			   Bus Device Reset CCBs have the Command field non-NULL only when a
+			   Bus Device Reset was requested for a Command that did not have a
+			   currently active CCB in the Host Adapter (i.e., a Synchronous
+			   Bus Device Reset), and hence would not have its Completion Routine
+			   called otherwise.
+			 */
+			while (Command != NULL) {
+				struct scsi_cmnd *NextCommand = Command->reset_chain;
+				Command->reset_chain = NULL;
+				Command->result = DID_RESET << 16;
+				Command->scsi_done(Command);
+				Command = NextCommand;
+			}
 #endif
-	  /*
-	    Iterate over the CCBs for this Host Adapter performing completion
-	    processing for any CCBs marked as Reset for this Target.
-	  */
-	  for (CCB = HostAdapter->All_CCBs; CCB != NULL; CCB = CCB->NextAll)
-	    if (CCB->Status == BusLogic_CCB_Reset && CCB->TargetID == TargetID)
-	      {
-		Command = CCB->Command;
-		BusLogic_DeallocateCCB(CCB);
-		HostAdapter->ActiveCommands[TargetID]--;
-		Command->result = DID_RESET << 16;
-		Command->scsi_done(Command);
-	      }
-	  HostAdapter->BusDeviceResetPendingCCB[TargetID] = NULL;
-	}
-      else
-	{
-	  /*
-	    Translate the Completion Code, Host Adapter Status, and Target
-	    Device Status into a SCSI Subsystem Result Code.
-	  */
-	  switch (CCB->CompletionCode)
-	    {
-	    case BusLogic_IncomingMailboxFree:
-	    case BusLogic_AbortedCommandNotFound:
-	    case BusLogic_InvalidCCB:
-	      BusLogic_Warning("CCB #%ld to Target %d Impossible State\n",
-			       HostAdapter, CCB->SerialNumber, CCB->TargetID);
-	      break;
-	    case BusLogic_CommandCompletedWithoutError:
-	      HostAdapter->TargetStatistics[CCB->TargetID]
-			   .CommandsCompleted++;
-	      HostAdapter->TargetFlags[CCB->TargetID]
-			   .CommandSuccessfulFlag = true;
-	      Command->result = DID_OK << 16;
-	      break;
-	    case BusLogic_CommandAbortedAtHostRequest:
-	      BusLogic_Warning("CCB #%ld to Target %d Aborted\n",
-			       HostAdapter, CCB->SerialNumber, CCB->TargetID);
-	      BusLogic_IncrementErrorCounter(
-		&HostAdapter->TargetStatistics[CCB->TargetID]
-			      .CommandAbortsCompleted);
-	      Command->result = DID_ABORT << 16;
-	      break;
-	    case BusLogic_CommandCompletedWithError:
-	      Command->result =
-		BusLogic_ComputeResultCode(HostAdapter,
-					   CCB->HostAdapterStatus,
-					   CCB->TargetDeviceStatus);
-	      if (CCB->HostAdapterStatus != BusLogic_SCSISelectionTimeout)
-		{
-		  HostAdapter->TargetStatistics[CCB->TargetID]
-			       .CommandsCompleted++;
-		  if (BusLogic_GlobalOptions.TraceErrors)
-		    {
-		      int i;
-		      BusLogic_Notice("CCB #%ld Target %d: Result %X Host "
-				      "Adapter Status %02X "
-				      "Target Status %02X\n",
-				      HostAdapter, CCB->SerialNumber,
-				      CCB->TargetID, Command->result,
-				      CCB->HostAdapterStatus,
-				      CCB->TargetDeviceStatus);
-		      BusLogic_Notice("CDB   ", HostAdapter);
-		      for (i = 0; i < CCB->CDB_Length; i++)
-			BusLogic_Notice(" %02X", HostAdapter, CCB->CDB[i]);
-		      BusLogic_Notice("\n", HostAdapter);
-		      BusLogic_Notice("Sense ", HostAdapter);
-		      for (i = 0; i < CCB->SenseDataLength; i++)
-			BusLogic_Notice(" %02X", HostAdapter,
-					Command->sense_buffer[i]);
-		      BusLogic_Notice("\n", HostAdapter);
-		    }
-		}
-	      break;
-	    }
-	  /*
-	    When an INQUIRY command completes normally, save the
-	    CmdQue (Tagged Queuing Supported) and WBus16 (16 Bit
-	    Wide Data Transfers Supported) bits.
-	  */
-	  if (CCB->CDB[0] == INQUIRY && CCB->CDB[1] == 0 &&
-	      CCB->HostAdapterStatus == BusLogic_CommandCompletedNormally)
-	    {
-	      struct BusLogic_TargetFlags *TargetFlags =
-		&HostAdapter->TargetFlags[CCB->TargetID];
-	      struct SCSI_Inquiry *InquiryResult =
-		(struct SCSI_Inquiry *) Command->request_buffer;
-	      TargetFlags->TargetExists = true;
-	      TargetFlags->TaggedQueuingSupported = InquiryResult->CmdQue;
-	      TargetFlags->WideTransfersSupported = InquiryResult->WBus16;
-	    }
-	  /*
-	    Place CCB back on the Host Adapter's free list.
-	  */
-	  BusLogic_DeallocateCCB(CCB);
-	  /*
-	    Call the SCSI Command Completion Routine.
-	  */
-	  Command->scsi_done(Command);
+			/*
+			   Iterate over the CCBs for this Host Adapter performing completion
+			   processing for any CCBs marked as Reset for this Target.
+			 */
+			for (CCB = HostAdapter->All_CCBs; CCB != NULL; CCB = CCB->NextAll)
+				if (CCB->Status == BusLogic_CCB_Reset && CCB->TargetID == TargetID) {
+					Command = CCB->Command;
+					BusLogic_DeallocateCCB(CCB);
+					HostAdapter->ActiveCommands[TargetID]--;
+					Command->result = DID_RESET << 16;
+					Command->scsi_done(Command);
+				}
+			HostAdapter->BusDeviceResetPendingCCB[TargetID] = NULL;
+		} else {
+			/*
+			   Translate the Completion Code, Host Adapter Status, and Target
+			   Device Status into a SCSI Subsystem Result Code.
+			 */
+			switch (CCB->CompletionCode) {
+			case BusLogic_IncomingMailboxFree:
+			case BusLogic_AbortedCommandNotFound:
+			case BusLogic_InvalidCCB:
+				BusLogic_Warning("CCB #%ld to Target %d Impossible State\n", HostAdapter, CCB->SerialNumber, CCB->TargetID);
+				break;
+			case BusLogic_CommandCompletedWithoutError:
+				HostAdapter->TargetStatistics[CCB->TargetID]
+				    .CommandsCompleted++;
+				HostAdapter->TargetFlags[CCB->TargetID]
+				    .CommandSuccessfulFlag = true;
+				Command->result = DID_OK << 16;
+				break;
+			case BusLogic_CommandAbortedAtHostRequest:
+				BusLogic_Warning("CCB #%ld to Target %d Aborted\n", HostAdapter, CCB->SerialNumber, CCB->TargetID);
+				BusLogic_IncrementErrorCounter(&HostAdapter->TargetStatistics[CCB->TargetID]
+							       .CommandAbortsCompleted);
+				Command->result = DID_ABORT << 16;
+				break;
+			case BusLogic_CommandCompletedWithError:
+				Command->result = BusLogic_ComputeResultCode(HostAdapter, CCB->HostAdapterStatus, CCB->TargetDeviceStatus);
+				if (CCB->HostAdapterStatus != BusLogic_SCSISelectionTimeout) {
+					HostAdapter->TargetStatistics[CCB->TargetID]
+					    .CommandsCompleted++;
+					if (BusLogic_GlobalOptions.TraceErrors) {
+						int i;
+						BusLogic_Notice("CCB #%ld Target %d: Result %X Host "
+								"Adapter Status %02X " "Target Status %02X\n", HostAdapter, CCB->SerialNumber, CCB->TargetID, Command->result, CCB->HostAdapterStatus, CCB->TargetDeviceStatus);
+						BusLogic_Notice("CDB   ", HostAdapter);
+						for (i = 0; i < CCB->CDB_Length; i++)
+							BusLogic_Notice(" %02X", HostAdapter, CCB->CDB[i]);
+						BusLogic_Notice("\n", HostAdapter);
+						BusLogic_Notice("Sense ", HostAdapter);
+						for (i = 0; i < CCB->SenseDataLength; i++)
+							BusLogic_Notice(" %02X", HostAdapter, Command->sense_buffer[i]);
+						BusLogic_Notice("\n", HostAdapter);
+					}
+				}
+				break;
+			}
+			/*
+			   When an INQUIRY command completes normally, save the
+			   CmdQue (Tagged Queuing Supported) and WBus16 (16 Bit
+			   Wide Data Transfers Supported) bits.
+			 */
+			if (CCB->CDB[0] == INQUIRY && CCB->CDB[1] == 0 && CCB->HostAdapterStatus == BusLogic_CommandCompletedNormally) {
+				struct BusLogic_TargetFlags *TargetFlags = &HostAdapter->TargetFlags[CCB->TargetID];
+				struct SCSI_Inquiry *InquiryResult = (struct SCSI_Inquiry *) Command->request_buffer;
+				TargetFlags->TargetExists = true;
+				TargetFlags->TaggedQueuingSupported = InquiryResult->CmdQue;
+				TargetFlags->WideTransfersSupported = InquiryResult->WBus16;
+			}
+			/*
+			   Place CCB back on the Host Adapter's free list.
+			 */
+			BusLogic_DeallocateCCB(CCB);
+			/*
+			   Call the SCSI Command Completion Routine.
+			 */
+			Command->scsi_done(Command);
+		}
 	}
-    }
-  HostAdapter->ProcessCompletedCCBsActive = false;
+	HostAdapter->ProcessCompletedCCBsActive = false;
 }
 
 
@@ -3163,97 +2649,83 @@
   Adapters.
 */
 
-static irqreturn_t BusLogic_InterruptHandler(int IRQ_Channel,
-				      void *DeviceIdentifier,
-				      struct pt_regs *InterruptRegisters)
-{
-  struct BusLogic_HostAdapter *HostAdapter =
-    (struct BusLogic_HostAdapter *) DeviceIdentifier;
-  unsigned long ProcessorFlags;
-  /*
-    Acquire exclusive access to Host Adapter.
-  */
-  BusLogic_AcquireHostAdapterLockIH(HostAdapter, &ProcessorFlags);
-  /*
-    Handle Interrupts appropriately for each Host Adapter type.
-  */
-  if (BusLogic_MultiMasterHostAdapterP(HostAdapter))
-    {
-      union BusLogic_InterruptRegister InterruptRegister;
-      /*
-	Read the Host Adapter Interrupt Register.
-      */
-      InterruptRegister.All = BusLogic_ReadInterruptRegister(HostAdapter);
-      if (InterruptRegister.ir.InterruptValid)
-	{
-	  /*
-	    Acknowledge the interrupt and reset the Host Adapter
-	    Interrupt Register.
-	  */
-	  BusLogic_InterruptReset(HostAdapter);
-	  /*
-	    Process valid External SCSI Bus Reset and Incoming Mailbox
-	    Loaded Interrupts.  Command Complete Interrupts are noted,
-	    and Outgoing Mailbox Available Interrupts are ignored, as
-	    they are never enabled.
-	  */
-	  if (InterruptRegister.ir.ExternalBusReset)
-	    HostAdapter->HostAdapterExternalReset = true;
-	  else if (InterruptRegister.ir.IncomingMailboxLoaded)
-	    BusLogic_ScanIncomingMailboxes(HostAdapter);
-	  else if (InterruptRegister.ir.CommandComplete)
-	    HostAdapter->HostAdapterCommandCompleted = true;
-	}
-    }
-  else
-    {
-      /*
-	Check if there is a pending interrupt for this Host Adapter.
-      */
-      if (FlashPoint_InterruptPending(HostAdapter->CardHandle))
-	switch (FlashPoint_HandleInterrupt(HostAdapter->CardHandle))
-	  {
-	  case FlashPoint_NormalInterrupt:
-	    break;
-	  case FlashPoint_ExternalBusReset:
-	    HostAdapter->HostAdapterExternalReset = true;
-	    break;
-	  case FlashPoint_InternalError:
-	    BusLogic_Warning("Internal FlashPoint Error detected"
-			     " - Resetting Host Adapter\n", HostAdapter);
-	    HostAdapter->HostAdapterInternalError = true;
-	    break;
-	  }
-    }
-  /*
-    Process any completed CCBs.
-  */
-  if (HostAdapter->FirstCompletedCCB != NULL)
-    BusLogic_ProcessCompletedCCBs(HostAdapter);
-  /*
-    Reset the Host Adapter if requested.
-  */
-  if (HostAdapter->HostAdapterExternalReset)
-    {
-      BusLogic_Warning("Resetting %s due to External SCSI Bus Reset\n",
-		       HostAdapter, HostAdapter->FullModelName);
-      BusLogic_IncrementErrorCounter(&HostAdapter->ExternalHostAdapterResets);
-      BusLogic_ResetHostAdapter(HostAdapter, false);
-      HostAdapter->HostAdapterExternalReset = false;
-    }
-  else if (HostAdapter->HostAdapterInternalError)
-    {
-      BusLogic_Warning("Resetting %s due to Host Adapter Internal Error\n",
-		       HostAdapter, HostAdapter->FullModelName);
-      BusLogic_IncrementErrorCounter(&HostAdapter->HostAdapterInternalErrors);
-      BusLogic_ResetHostAdapter(HostAdapter, true);
-      HostAdapter->HostAdapterInternalError = false;
-    }
-  /*
-    Release exclusive access to Host Adapter.
-  */
-  BusLogic_ReleaseHostAdapterLockIH(HostAdapter, &ProcessorFlags);
-  return IRQ_HANDLED;
+static irqreturn_t BusLogic_InterruptHandler(int IRQ_Channel, void *DeviceIdentifier, struct pt_regs *InterruptRegisters)
+{
+	struct BusLogic_HostAdapter *HostAdapter = (struct BusLogic_HostAdapter *) DeviceIdentifier;
+	unsigned long ProcessorFlags;
+	/*
+	   Acquire exclusive access to Host Adapter.
+	 */
+	BusLogic_AcquireHostAdapterLockIH(HostAdapter, &ProcessorFlags);
+	/*
+	   Handle Interrupts appropriately for each Host Adapter type.
+	 */
+	if (BusLogic_MultiMasterHostAdapterP(HostAdapter)) {
+		union BusLogic_InterruptRegister InterruptRegister;
+		/*
+		   Read the Host Adapter Interrupt Register.
+		 */
+		InterruptRegister.All = BusLogic_ReadInterruptRegister(HostAdapter);
+		if (InterruptRegister.ir.InterruptValid) {
+			/*
+			   Acknowledge the interrupt and reset the Host Adapter
+			   Interrupt Register.
+			 */
+			BusLogic_InterruptReset(HostAdapter);
+			/*
+			   Process valid External SCSI Bus Reset and Incoming Mailbox
+			   Loaded Interrupts.  Command Complete Interrupts are noted,
+			   and Outgoing Mailbox Available Interrupts are ignored, as
+			   they are never enabled.
+			 */
+			if (InterruptRegister.ir.ExternalBusReset)
+				HostAdapter->HostAdapterExternalReset = true;
+			else if (InterruptRegister.ir.IncomingMailboxLoaded)
+				BusLogic_ScanIncomingMailboxes(HostAdapter);
+			else if (InterruptRegister.ir.CommandComplete)
+				HostAdapter->HostAdapterCommandCompleted = true;
+		}
+	} else {
+		/*
+		   Check if there is a pending interrupt for this Host Adapter.
+		 */
+		if (FlashPoint_InterruptPending(HostAdapter->CardHandle))
+			switch (FlashPoint_HandleInterrupt(HostAdapter->CardHandle)) {
+			case FlashPoint_NormalInterrupt:
+				break;
+			case FlashPoint_ExternalBusReset:
+				HostAdapter->HostAdapterExternalReset = true;
+				break;
+			case FlashPoint_InternalError:
+				BusLogic_Warning("Internal FlashPoint Error detected" " - Resetting Host Adapter\n", HostAdapter);
+				HostAdapter->HostAdapterInternalError = true;
+				break;
+			}
+	}
+	/*
+	   Process any completed CCBs.
+	 */
+	if (HostAdapter->FirstCompletedCCB != NULL)
+		BusLogic_ProcessCompletedCCBs(HostAdapter);
+	/*
+	   Reset the Host Adapter if requested.
+	 */
+	if (HostAdapter->HostAdapterExternalReset) {
+		BusLogic_Warning("Resetting %s due to External SCSI Bus Reset\n", HostAdapter, HostAdapter->FullModelName);
+		BusLogic_IncrementErrorCounter(&HostAdapter->ExternalHostAdapterResets);
+		BusLogic_ResetHostAdapter(HostAdapter, false);
+		HostAdapter->HostAdapterExternalReset = false;
+	} else if (HostAdapter->HostAdapterInternalError) {
+		BusLogic_Warning("Resetting %s due to Host Adapter Internal Error\n", HostAdapter, HostAdapter->FullModelName);
+		BusLogic_IncrementErrorCounter(&HostAdapter->HostAdapterInternalErrors);
+		BusLogic_ResetHostAdapter(HostAdapter, true);
+		HostAdapter->HostAdapterInternalError = false;
+	}
+	/*
+	   Release exclusive access to Host Adapter.
+	 */
+	BusLogic_ReleaseHostAdapterLockIH(HostAdapter, &ProcessorFlags);
+	return IRQ_HANDLED;
 }
 
 
@@ -3264,43 +2736,38 @@
 */
 
 static boolean BusLogic_WriteOutgoingMailbox(struct BusLogic_HostAdapter
-					       *HostAdapter,
-					     enum BusLogic_ActionCode ActionCode,
-					     struct BusLogic_CCB *CCB)
-{
-  struct BusLogic_OutgoingMailbox *NextOutgoingMailbox;
-  NextOutgoingMailbox = HostAdapter->NextOutgoingMailbox;
-  if (NextOutgoingMailbox->ActionCode == BusLogic_OutgoingMailboxFree)
-    {
-      CCB->Status = BusLogic_CCB_Active;
-      /*
-	The CCB field must be written before the Action Code field since
-	the Host Adapter is operating asynchronously and the locking code
-	does not protect against simultaneous access by the Host Adapter.
-      */
-      NextOutgoingMailbox->CCB = CCB->DMA_Handle;
-      NextOutgoingMailbox->ActionCode = ActionCode;
-      BusLogic_StartMailboxCommand(HostAdapter);
-      if (++NextOutgoingMailbox > HostAdapter->LastOutgoingMailbox)
-	NextOutgoingMailbox = HostAdapter->FirstOutgoingMailbox;
-      HostAdapter->NextOutgoingMailbox = NextOutgoingMailbox;
-      if (ActionCode == BusLogic_MailboxStartCommand)
-	{
-	  HostAdapter->ActiveCommands[CCB->TargetID]++;
-	  if (CCB->Opcode != BusLogic_BusDeviceReset)
-	    HostAdapter->TargetStatistics[CCB->TargetID].CommandsAttempted++;
-	}
-      return true;
-    }
-  return false;
+					     *HostAdapter, enum BusLogic_ActionCode ActionCode, struct BusLogic_CCB *CCB)
+{
+	struct BusLogic_OutgoingMailbox *NextOutgoingMailbox;
+	NextOutgoingMailbox = HostAdapter->NextOutgoingMailbox;
+	if (NextOutgoingMailbox->ActionCode == BusLogic_OutgoingMailboxFree) {
+		CCB->Status = BusLogic_CCB_Active;
+		/*
+		   The CCB field must be written before the Action Code field since
+		   the Host Adapter is operating asynchronously and the locking code
+		   does not protect against simultaneous access by the Host Adapter.
+		 */
+		NextOutgoingMailbox->CCB = CCB->DMA_Handle;
+		NextOutgoingMailbox->ActionCode = ActionCode;
+		BusLogic_StartMailboxCommand(HostAdapter);
+		if (++NextOutgoingMailbox > HostAdapter->LastOutgoingMailbox)
+			NextOutgoingMailbox = HostAdapter->FirstOutgoingMailbox;
+		HostAdapter->NextOutgoingMailbox = NextOutgoingMailbox;
+		if (ActionCode == BusLogic_MailboxStartCommand) {
+			HostAdapter->ActiveCommands[CCB->TargetID]++;
+			if (CCB->Opcode != BusLogic_BusDeviceReset)
+				HostAdapter->TargetStatistics[CCB->TargetID].CommandsAttempted++;
+		}
+		return true;
+	}
+	return false;
 }
 
 /* Error Handling (EH) support */
 
-static int BusLogic_host_reset(Scsi_Cmnd *SCpnt)
+static int BusLogic_host_reset(Scsi_Cmnd * SCpnt)
 {
-	struct BusLogic_HostAdapter *HostAdapter =
-		(struct BusLogic_HostAdapter *) SCpnt->device->host->hostdata;
+	struct BusLogic_HostAdapter *HostAdapter = (struct BusLogic_HostAdapter *) SCpnt->device->host->hostdata;
 
 	unsigned int id = SCpnt->device->id;
 	struct BusLogic_TargetStatistics *stats = &HostAdapter->TargetStatistics[id];
@@ -3314,237 +2781,190 @@
   Outgoing Mailbox for execution by the associated Host Adapter.
 */
 
-static int BusLogic_QueueCommand(struct scsi_cmnd *Command,
-				 void (*CompletionRoutine)(struct scsi_cmnd *))
+static int BusLogic_QueueCommand(struct scsi_cmnd *Command, void (*CompletionRoutine) (struct scsi_cmnd *))
 {
-  struct BusLogic_HostAdapter *HostAdapter =
-    (struct BusLogic_HostAdapter *) Command->device->host->hostdata;
-  struct BusLogic_TargetFlags *TargetFlags =
-    &HostAdapter->TargetFlags[Command->device->id];
-  struct BusLogic_TargetStatistics *TargetStatistics =
-    HostAdapter->TargetStatistics;
-  unsigned char *CDB = Command->cmnd;
-  int CDB_Length = Command->cmd_len;
-  int TargetID = Command->device->id;
-  int LogicalUnit = Command->device->lun;
-  void *BufferPointer = Command->request_buffer;
-  int BufferLength = Command->request_bufflen;
-  int SegmentCount = Command->use_sg;
-  struct BusLogic_CCB *CCB;
-  /*
-    SCSI REQUEST_SENSE commands will be executed automatically by the Host
-    Adapter for any errors, so they should not be executed explicitly unless
-    the Sense Data is zero indicating that no error occurred.
-  */
-  if (CDB[0] == REQUEST_SENSE && Command->sense_buffer[0] != 0)
-    {
-      Command->result = DID_OK << 16;
-      CompletionRoutine(Command);
-      return 0;
-    }
-  /*
-    Allocate a CCB from the Host Adapter's free list.  In the unlikely event
-    that there are none available and memory allocation fails, wait 1 second
-    and try again.  If that fails, the Host Adapter is probably hung so signal
-    an error as a Host Adapter Hard Reset should be initiated soon.
-  */
-  CCB = BusLogic_AllocateCCB(HostAdapter);
-  if (CCB == NULL)
-    {
-      BusLogic_ReleaseHostAdapterLock(HostAdapter);
-      BusLogic_Delay(1);
-      BusLogic_AcquireHostAdapterLock(HostAdapter);
-      CCB = BusLogic_AllocateCCB(HostAdapter);
-      if (CCB == NULL)
-	{
-	  Command->result = DID_ERROR << 16;
-	  CompletionRoutine(Command);
-	  return 0;
-	}
-    }
-  /*
-    Initialize the fields in the BusLogic Command Control Block (CCB).
-  */
-  if (SegmentCount == 0 && BufferLength != 0)
-    {
-      CCB->Opcode = BusLogic_InitiatorCCB;
-      CCB->DataLength = BufferLength;
-      CCB->DataPointer =
-	pci_map_single(HostAdapter->PCI_Device, BufferPointer, BufferLength,
-		       scsi_to_pci_dma_dir(Command->sc_data_direction));
-    }
-  else if (SegmentCount != 0)
-    {
-      struct scatterlist *ScatterList = (struct scatterlist *) BufferPointer;
-      int Segment, Count;
-
-      Count = pci_map_sg(HostAdapter->PCI_Device, ScatterList, SegmentCount,
-			 scsi_to_pci_dma_dir(Command->sc_data_direction));
-      CCB->Opcode = BusLogic_InitiatorCCB_ScatterGather;
-      CCB->DataLength = Count * sizeof(struct BusLogic_ScatterGatherSegment);
-      if (BusLogic_MultiMasterHostAdapterP(HostAdapter))
-	CCB->DataPointer = (unsigned int)CCB->DMA_Handle +
-			    ((unsigned long)&CCB->ScatterGatherList - 
-			     (unsigned long)CCB);
-      else CCB->DataPointer = Virtual_to_32Bit_Virtual(CCB->ScatterGatherList);
-      for (Segment = 0; Segment < Count; Segment++)
-	{
-	  CCB->ScatterGatherList[Segment].SegmentByteCount =
-	    sg_dma_len(ScatterList+Segment);
-	  CCB->ScatterGatherList[Segment].SegmentDataPointer =
-	    sg_dma_address(ScatterList+Segment);
-	}
-    }
-  else
-    {
-      CCB->Opcode = BusLogic_InitiatorCCB;
-      CCB->DataLength = BufferLength;
-      CCB->DataPointer = 0;
-    }
-  switch (CDB[0])
-    {
-    case READ_6:
-    case READ_10:
-      CCB->DataDirection = BusLogic_DataInLengthChecked;
-      TargetStatistics[TargetID].ReadCommands++;
-      BusLogic_IncrementByteCounter(
-	&TargetStatistics[TargetID].TotalBytesRead, BufferLength);
-      BusLogic_IncrementSizeBucket(
-	TargetStatistics[TargetID].ReadCommandSizeBuckets, BufferLength);
-      break;
-    case WRITE_6:
-    case WRITE_10:
-      CCB->DataDirection = BusLogic_DataOutLengthChecked;
-      TargetStatistics[TargetID].WriteCommands++;
-      BusLogic_IncrementByteCounter(
-	&TargetStatistics[TargetID].TotalBytesWritten, BufferLength);
-      BusLogic_IncrementSizeBucket(
-	TargetStatistics[TargetID].WriteCommandSizeBuckets, BufferLength);
-      break;
-    default:
-      CCB->DataDirection = BusLogic_UncheckedDataTransfer;
-      break;
-    }
-  CCB->CDB_Length = CDB_Length;
-  CCB->HostAdapterStatus = 0;
-  CCB->TargetDeviceStatus = 0;
-  CCB->TargetID = TargetID;
-  CCB->LogicalUnit = LogicalUnit;
-  CCB->TagEnable = false;
-  CCB->LegacyTagEnable = false;
-  /*
-    BusLogic recommends that after a Reset the first couple of commands that
-    are sent to a Target Device be sent in a non Tagged Queue fashion so that
-    the Host Adapter and Target Device can establish Synchronous and Wide
-    Transfer before Queue Tag messages can interfere with the Synchronous and
-    Wide Negotiation messages.  By waiting to enable Tagged Queuing until after
-    the first BusLogic_MaxTaggedQueueDepth commands have been queued, it is
-    assured that after a Reset any pending commands are requeued before Tagged
-    Queuing is enabled and that the Tagged Queuing message will not occur while
-    the partition table is being printed.  In addition, some devices do not
-    properly handle the transition from non-tagged to tagged commands, so it is
-    necessary to wait until there are no pending commands for a target device
-    before queuing tagged commands.
-  */
-  if (HostAdapter->CommandsSinceReset[TargetID]++ >=
-	BusLogic_MaxTaggedQueueDepth &&
-      !TargetFlags->TaggedQueuingActive &&
-      HostAdapter->ActiveCommands[TargetID] == 0 &&
-      TargetFlags->TaggedQueuingSupported &&
-      (HostAdapter->TaggedQueuingPermitted & (1 << TargetID)))
-    {
-      TargetFlags->TaggedQueuingActive = true;
-      BusLogic_Notice("Tagged Queuing now active for Target %d\n",
-		      HostAdapter, TargetID);
-    }
-  if (TargetFlags->TaggedQueuingActive)
-    {
-      enum BusLogic_QueueTag QueueTag = BusLogic_SimpleQueueTag;
-      /*
-	When using Tagged Queuing with Simple Queue Tags, it appears that disk
-	drive controllers do not guarantee that a queued command will not
-	remain in a disconnected state indefinitely if commands that read or
-	write nearer the head position continue to arrive without interruption.
-	Therefore, for each Target Device this driver keeps track of the last
-	time either the queue was empty or an Ordered Queue Tag was issued.  If
-	more than 4 seconds (one fifth of the 20 second disk timeout) have
-	elapsed since this last sequence point, this command will be issued
-	with an Ordered Queue Tag rather than a Simple Queue Tag, which forces
-	the Target Device to complete all previously queued commands before
-	this command may be executed.
-      */
-      if (HostAdapter->ActiveCommands[TargetID] == 0)
-	HostAdapter->LastSequencePoint[TargetID] = jiffies;
-      else if (jiffies - HostAdapter->LastSequencePoint[TargetID] > 4*HZ)
-	{
-	  HostAdapter->LastSequencePoint[TargetID] = jiffies;
-	  QueueTag = BusLogic_OrderedQueueTag;
-	}
-      if (HostAdapter->ExtendedLUNSupport)
-	{
-	  CCB->TagEnable = true;
-	  CCB->QueueTag = QueueTag;
-	}
-      else
-	{
-	  CCB->LegacyTagEnable = true;
-	  CCB->LegacyQueueTag = QueueTag;
-	}
-    }
-  memcpy(CCB->CDB, CDB, CDB_Length);
-  CCB->SenseDataLength = sizeof(Command->sense_buffer);
-  CCB->SenseDataPointer = pci_map_single(HostAdapter->PCI_Device,
-					 Command->sense_buffer,
-					 CCB->SenseDataLength,
-					 PCI_DMA_FROMDEVICE);
-  CCB->Command = Command;
-  Command->scsi_done = CompletionRoutine;
-  if (BusLogic_MultiMasterHostAdapterP(HostAdapter))
-    {
-      /*
-	Place the CCB in an Outgoing Mailbox.  The higher levels of the SCSI
-	Subsystem should not attempt to queue more commands than can be placed
-	in Outgoing Mailboxes, so there should always be one free.  In the
-	unlikely event that there are none available, wait 1 second and try
-	again.  If that fails, the Host Adapter is probably hung so signal an
-	error as a Host Adapter Hard Reset should be initiated soon.
-      */
-      if (!BusLogic_WriteOutgoingMailbox(
-	     HostAdapter, BusLogic_MailboxStartCommand, CCB))
-	{
-	  BusLogic_ReleaseHostAdapterLock(HostAdapter);
-	  BusLogic_Warning("Unable to write Outgoing Mailbox - "
-			   "Pausing for 1 second\n", HostAdapter);
-	  BusLogic_Delay(1);
-	  BusLogic_AcquireHostAdapterLock(HostAdapter);
-	  if (!BusLogic_WriteOutgoingMailbox(
-		 HostAdapter, BusLogic_MailboxStartCommand, CCB))
-	    {
-	      BusLogic_Warning("Still unable to write Outgoing Mailbox - "
-			       "Host Adapter Dead?\n", HostAdapter);
-	      BusLogic_DeallocateCCB(CCB);
-	      Command->result = DID_ERROR << 16;
-	      Command->scsi_done(Command);
-	    }
-	}
-    }
-  else
-    {
-      /*
-	Call the FlashPoint SCCB Manager to start execution of the CCB.
-      */
-      CCB->Status = BusLogic_CCB_Active;
-      HostAdapter->ActiveCommands[TargetID]++;
-      TargetStatistics[TargetID].CommandsAttempted++;
-      FlashPoint_StartCCB(HostAdapter->CardHandle, CCB);
-      /*
-	The Command may have already completed and BusLogic_QueueCompletedCCB
-	been called, or it may still be pending.
-      */
-      if (CCB->Status == BusLogic_CCB_Completed)
-	BusLogic_ProcessCompletedCCBs(HostAdapter);
-    }
-  return 0;
+	struct BusLogic_HostAdapter *HostAdapter = (struct BusLogic_HostAdapter *) Command->device->host->hostdata;
+	struct BusLogic_TargetFlags *TargetFlags = &HostAdapter->TargetFlags[Command->device->id];
+	struct BusLogic_TargetStatistics *TargetStatistics = HostAdapter->TargetStatistics;
+	unsigned char *CDB = Command->cmnd;
+	int CDB_Length = Command->cmd_len;
+	int TargetID = Command->device->id;
+	int LogicalUnit = Command->device->lun;
+	void *BufferPointer = Command->request_buffer;
+	int BufferLength = Command->request_bufflen;
+	int SegmentCount = Command->use_sg;
+	struct BusLogic_CCB *CCB;
+	/*
+	   SCSI REQUEST_SENSE commands will be executed automatically by the Host
+	   Adapter for any errors, so they should not be executed explicitly unless
+	   the Sense Data is zero indicating that no error occurred.
+	 */
+	if (CDB[0] == REQUEST_SENSE && Command->sense_buffer[0] != 0) {
+		Command->result = DID_OK << 16;
+		CompletionRoutine(Command);
+		return 0;
+	}
+	/*
+	   Allocate a CCB from the Host Adapter's free list.  In the unlikely event
+	   that there are none available and memory allocation fails, wait 1 second
+	   and try again.  If that fails, the Host Adapter is probably hung so signal
+	   an error as a Host Adapter Hard Reset should be initiated soon.
+	 */
+	CCB = BusLogic_AllocateCCB(HostAdapter);
+	if (CCB == NULL) {
+		BusLogic_ReleaseHostAdapterLock(HostAdapter);
+		BusLogic_Delay(1);
+		BusLogic_AcquireHostAdapterLock(HostAdapter);
+		CCB = BusLogic_AllocateCCB(HostAdapter);
+		if (CCB == NULL) {
+			Command->result = DID_ERROR << 16;
+			CompletionRoutine(Command);
+			return 0;
+		}
+	}
+	/*
+	   Initialize the fields in the BusLogic Command Control Block (CCB).
+	 */
+	if (SegmentCount == 0 && BufferLength != 0) {
+		CCB->Opcode = BusLogic_InitiatorCCB;
+		CCB->DataLength = BufferLength;
+		CCB->DataPointer = pci_map_single(HostAdapter->PCI_Device, BufferPointer, BufferLength, scsi_to_pci_dma_dir(Command->sc_data_direction));
+	} else if (SegmentCount != 0) {
+		struct scatterlist *ScatterList = (struct scatterlist *) BufferPointer;
+		int Segment, Count;
+
+		Count = pci_map_sg(HostAdapter->PCI_Device, ScatterList, SegmentCount, scsi_to_pci_dma_dir(Command->sc_data_direction));
+		CCB->Opcode = BusLogic_InitiatorCCB_ScatterGather;
+		CCB->DataLength = Count * sizeof(struct BusLogic_ScatterGatherSegment);
+		if (BusLogic_MultiMasterHostAdapterP(HostAdapter))
+			CCB->DataPointer = (unsigned int) CCB->DMA_Handle + ((unsigned long) &CCB->ScatterGatherList - (unsigned long) CCB);
+		else
+			CCB->DataPointer = Virtual_to_32Bit_Virtual(CCB->ScatterGatherList);
+		for (Segment = 0; Segment < Count; Segment++) {
+			CCB->ScatterGatherList[Segment].SegmentByteCount = sg_dma_len(ScatterList + Segment);
+			CCB->ScatterGatherList[Segment].SegmentDataPointer = sg_dma_address(ScatterList + Segment);
+		}
+	} else {
+		CCB->Opcode = BusLogic_InitiatorCCB;
+		CCB->DataLength = BufferLength;
+		CCB->DataPointer = 0;
+	}
+	switch (CDB[0]) {
+	case READ_6:
+	case READ_10:
+		CCB->DataDirection = BusLogic_DataInLengthChecked;
+		TargetStatistics[TargetID].ReadCommands++;
+		BusLogic_IncrementByteCounter(&TargetStatistics[TargetID].TotalBytesRead, BufferLength);
+		BusLogic_IncrementSizeBucket(TargetStatistics[TargetID].ReadCommandSizeBuckets, BufferLength);
+		break;
+	case WRITE_6:
+	case WRITE_10:
+		CCB->DataDirection = BusLogic_DataOutLengthChecked;
+		TargetStatistics[TargetID].WriteCommands++;
+		BusLogic_IncrementByteCounter(&TargetStatistics[TargetID].TotalBytesWritten, BufferLength);
+		BusLogic_IncrementSizeBucket(TargetStatistics[TargetID].WriteCommandSizeBuckets, BufferLength);
+		break;
+	default:
+		CCB->DataDirection = BusLogic_UncheckedDataTransfer;
+		break;
+	}
+	CCB->CDB_Length = CDB_Length;
+	CCB->HostAdapterStatus = 0;
+	CCB->TargetDeviceStatus = 0;
+	CCB->TargetID = TargetID;
+	CCB->LogicalUnit = LogicalUnit;
+	CCB->TagEnable = false;
+	CCB->LegacyTagEnable = false;
+	/*
+	   BusLogic recommends that after a Reset the first couple of commands that
+	   are sent to a Target Device be sent in a non Tagged Queue fashion so that
+	   the Host Adapter and Target Device can establish Synchronous and Wide
+	   Transfer before Queue Tag messages can interfere with the Synchronous and
+	   Wide Negotiation messages.  By waiting to enable Tagged Queuing until after
+	   the first BusLogic_MaxTaggedQueueDepth commands have been queued, it is
+	   assured that after a Reset any pending commands are requeued before Tagged
+	   Queuing is enabled and that the Tagged Queuing message will not occur while
+	   the partition table is being printed.  In addition, some devices do not
+	   properly handle the transition from non-tagged to tagged commands, so it is
+	   necessary to wait until there are no pending commands for a target device
+	   before queuing tagged commands.
+	 */
+	if (HostAdapter->CommandsSinceReset[TargetID]++ >=
+	    BusLogic_MaxTaggedQueueDepth && !TargetFlags->TaggedQueuingActive && HostAdapter->ActiveCommands[TargetID] == 0 && TargetFlags->TaggedQueuingSupported && (HostAdapter->TaggedQueuingPermitted & (1 << TargetID))) {
+		TargetFlags->TaggedQueuingActive = true;
+		BusLogic_Notice("Tagged Queuing now active for Target %d\n", HostAdapter, TargetID);
+	}
+	if (TargetFlags->TaggedQueuingActive) {
+		enum BusLogic_QueueTag QueueTag = BusLogic_SimpleQueueTag;
+		/*
+		   When using Tagged Queuing with Simple Queue Tags, it appears that disk
+		   drive controllers do not guarantee that a queued command will not
+		   remain in a disconnected state indefinitely if commands that read or
+		   write nearer the head position continue to arrive without interruption.
+		   Therefore, for each Target Device this driver keeps track of the last
+		   time either the queue was empty or an Ordered Queue Tag was issued.  If
+		   more than 4 seconds (one fifth of the 20 second disk timeout) have
+		   elapsed since this last sequence point, this command will be issued
+		   with an Ordered Queue Tag rather than a Simple Queue Tag, which forces
+		   the Target Device to complete all previously queued commands before
+		   this command may be executed.
+		 */
+		if (HostAdapter->ActiveCommands[TargetID] == 0)
+			HostAdapter->LastSequencePoint[TargetID] = jiffies;
+		else if (jiffies - HostAdapter->LastSequencePoint[TargetID] > 4 * HZ) {
+			HostAdapter->LastSequencePoint[TargetID] = jiffies;
+			QueueTag = BusLogic_OrderedQueueTag;
+		}
+		if (HostAdapter->ExtendedLUNSupport) {
+			CCB->TagEnable = true;
+			CCB->QueueTag = QueueTag;
+		} else {
+			CCB->LegacyTagEnable = true;
+			CCB->LegacyQueueTag = QueueTag;
+		}
+	}
+	memcpy(CCB->CDB, CDB, CDB_Length);
+	CCB->SenseDataLength = sizeof(Command->sense_buffer);
+	CCB->SenseDataPointer = pci_map_single(HostAdapter->PCI_Device, Command->sense_buffer, CCB->SenseDataLength, PCI_DMA_FROMDEVICE);
+	CCB->Command = Command;
+	Command->scsi_done = CompletionRoutine;
+	if (BusLogic_MultiMasterHostAdapterP(HostAdapter)) {
+		/*
+		   Place the CCB in an Outgoing Mailbox.  The higher levels of the SCSI
+		   Subsystem should not attempt to queue more commands than can be placed
+		   in Outgoing Mailboxes, so there should always be one free.  In the
+		   unlikely event that there are none available, wait 1 second and try
+		   again.  If that fails, the Host Adapter is probably hung so signal an
+		   error as a Host Adapter Hard Reset should be initiated soon.
+		 */
+		if (!BusLogic_WriteOutgoingMailbox(HostAdapter, BusLogic_MailboxStartCommand, CCB)) {
+			BusLogic_ReleaseHostAdapterLock(HostAdapter);
+			BusLogic_Warning("Unable to write Outgoing Mailbox - " "Pausing for 1 second\n", HostAdapter);
+			BusLogic_Delay(1);
+			BusLogic_AcquireHostAdapterLock(HostAdapter);
+			if (!BusLogic_WriteOutgoingMailbox(HostAdapter, BusLogic_MailboxStartCommand, CCB)) {
+				BusLogic_Warning("Still unable to write Outgoing Mailbox - " "Host Adapter Dead?\n", HostAdapter);
+				BusLogic_DeallocateCCB(CCB);
+				Command->result = DID_ERROR << 16;
+				Command->scsi_done(Command);
+			}
+		}
+	} else {
+		/*
+		   Call the FlashPoint SCCB Manager to start execution of the CCB.
+		 */
+		CCB->Status = BusLogic_CCB_Active;
+		HostAdapter->ActiveCommands[TargetID]++;
+		TargetStatistics[TargetID].CommandsAttempted++;
+		FlashPoint_StartCCB(HostAdapter->CardHandle, CCB);
+		/*
+		   The Command may have already completed and BusLogic_QueueCompletedCCB
+		   been called, or it may still be pending.
+		 */
+		if (CCB->Status == BusLogic_CCB_Completed)
+			BusLogic_ProcessCompletedCCBs(HostAdapter);
+	}
+	return 0;
 }
 
 
@@ -3554,105 +2974,75 @@
 
 static int BusLogic_AbortCommand(struct scsi_cmnd *Command)
 {
-  struct BusLogic_HostAdapter *HostAdapter =
-    (struct BusLogic_HostAdapter *) Command->device->host->hostdata;
+	struct BusLogic_HostAdapter *HostAdapter = (struct BusLogic_HostAdapter *) Command->device->host->hostdata;
 
-  int TargetID = Command->device->id;
-  struct BusLogic_CCB *CCB;
-  BusLogic_IncrementErrorCounter(
-    &HostAdapter->TargetStatistics[TargetID].CommandAbortsRequested);
-  /*
-    If this Command has already completed, then no Abort is necessary.
-  */
-  if (Command->serial_number != Command->serial_number_at_timeout)
-    {
-      BusLogic_Warning("Unable to Abort Command to Target %d - "
-		       "Already Completed\n", HostAdapter, TargetID);
-      return SUCCESS;
-    }
-  /*
-    Attempt to find an Active CCB for this Command.  If no Active CCB for this
-    Command is found, then no Abort is necessary.
-  */
-  for (CCB = HostAdapter->All_CCBs; CCB != NULL; CCB = CCB->NextAll)
-    if (CCB->Command == Command) break;
-  if (CCB == NULL)
-    {
-      BusLogic_Warning("Unable to Abort Command to Target %d - "
-		       "No CCB Found\n", HostAdapter, TargetID);
-      return SUCCESS;
-    }
-  else if (CCB->Status == BusLogic_CCB_Completed)
-    {
-      BusLogic_Warning("Unable to Abort Command to Target %d - "
-		       "CCB Completed\n", HostAdapter, TargetID);
-      return SUCCESS;
-    }
-  else if (CCB->Status == BusLogic_CCB_Reset)
-    {
-      BusLogic_Warning("Unable to Abort Command to Target %d - "
-		       "CCB Reset\n", HostAdapter, TargetID);
-      return SUCCESS;
-    }
-  if (BusLogic_MultiMasterHostAdapterP(HostAdapter))
-    {
-      /*
-	Attempt to Abort this CCB.  MultiMaster Firmware versions prior to 5.xx
-	do not generate Abort Tag messages, but only generate the non-tagged
-	Abort message.  Since non-tagged commands are not sent by the Host
-	Adapter until the queue of outstanding tagged commands has completed,
-	and the Abort message is treated as a non-tagged command, it is
-	effectively impossible to abort commands when Tagged Queuing is active.
-	Firmware version 5.xx does generate Abort Tag messages, so it is
-	possible to abort commands when Tagged Queuing is active.
-      */
-      if (HostAdapter->TargetFlags[TargetID].TaggedQueuingActive &&
-	  HostAdapter->FirmwareVersion[0] < '5')
-	{
-	  BusLogic_Warning("Unable to Abort CCB #%ld to Target %d - "
-			   "Abort Tag Not Supported\n",
-			   HostAdapter, CCB->SerialNumber, TargetID);
-	  return FAILURE;
-	}
-      else if (BusLogic_WriteOutgoingMailbox(
-		 HostAdapter, BusLogic_MailboxAbortCommand, CCB))
-	{
-	  BusLogic_Warning("Aborting CCB #%ld to Target %d\n",
-			   HostAdapter, CCB->SerialNumber, TargetID);
-	  BusLogic_IncrementErrorCounter(
-	    &HostAdapter->TargetStatistics[TargetID].CommandAbortsAttempted);
-	  return SUCCESS;
-	}
-      else
-	{
-	  BusLogic_Warning("Unable to Abort CCB #%ld to Target %d - "
-			   "No Outgoing Mailboxes\n",
-			    HostAdapter, CCB->SerialNumber, TargetID);
-	  return FAILURE;
-	}
-    }
-  else
-    {
-      /*
-	Call the FlashPoint SCCB Manager to abort execution of the CCB.
-      */
-      BusLogic_Warning("Aborting CCB #%ld to Target %d\n",
-		       HostAdapter, CCB->SerialNumber, TargetID);
-      BusLogic_IncrementErrorCounter(
-	&HostAdapter->TargetStatistics[TargetID].CommandAbortsAttempted);
-      FlashPoint_AbortCCB(HostAdapter->CardHandle, CCB);
-      /*
-	The Abort may have already been completed and
-	BusLogic_QueueCompletedCCB been called, or it
-	may still be pending.
-      */
-      if (CCB->Status == BusLogic_CCB_Completed)
-	{
-	  BusLogic_ProcessCompletedCCBs(HostAdapter);
-	}
-      return SUCCESS;
-    }
-  return SUCCESS;
+	int TargetID = Command->device->id;
+	struct BusLogic_CCB *CCB;
+	BusLogic_IncrementErrorCounter(&HostAdapter->TargetStatistics[TargetID].CommandAbortsRequested);
+	/*
+	   If this Command has already completed, then no Abort is necessary.
+	 */
+	if (Command->serial_number != Command->serial_number_at_timeout) {
+		BusLogic_Warning("Unable to Abort Command to Target %d - " "Already Completed\n", HostAdapter, TargetID);
+		return SUCCESS;
+	}
+	/*
+	   Attempt to find an Active CCB for this Command.  If no Active CCB for this
+	   Command is found, then no Abort is necessary.
+	 */
+	for (CCB = HostAdapter->All_CCBs; CCB != NULL; CCB = CCB->NextAll)
+		if (CCB->Command == Command)
+			break;
+	if (CCB == NULL) {
+		BusLogic_Warning("Unable to Abort Command to Target %d - " "No CCB Found\n", HostAdapter, TargetID);
+		return SUCCESS;
+	} else if (CCB->Status == BusLogic_CCB_Completed) {
+		BusLogic_Warning("Unable to Abort Command to Target %d - " "CCB Completed\n", HostAdapter, TargetID);
+		return SUCCESS;
+	} else if (CCB->Status == BusLogic_CCB_Reset) {
+		BusLogic_Warning("Unable to Abort Command to Target %d - " "CCB Reset\n", HostAdapter, TargetID);
+		return SUCCESS;
+	}
+	if (BusLogic_MultiMasterHostAdapterP(HostAdapter)) {
+		/*
+		   Attempt to Abort this CCB.  MultiMaster Firmware versions prior to 5.xx
+		   do not generate Abort Tag messages, but only generate the non-tagged
+		   Abort message.  Since non-tagged commands are not sent by the Host
+		   Adapter until the queue of outstanding tagged commands has completed,
+		   and the Abort message is treated as a non-tagged command, it is
+		   effectively impossible to abort commands when Tagged Queuing is active.
+		   Firmware version 5.xx does generate Abort Tag messages, so it is
+		   possible to abort commands when Tagged Queuing is active.
+		 */
+		if (HostAdapter->TargetFlags[TargetID].TaggedQueuingActive && HostAdapter->FirmwareVersion[0] < '5') {
+			BusLogic_Warning("Unable to Abort CCB #%ld to Target %d - " "Abort Tag Not Supported\n", HostAdapter, CCB->SerialNumber, TargetID);
+			return FAILURE;
+		} else if (BusLogic_WriteOutgoingMailbox(HostAdapter, BusLogic_MailboxAbortCommand, CCB)) {
+			BusLogic_Warning("Aborting CCB #%ld to Target %d\n", HostAdapter, CCB->SerialNumber, TargetID);
+			BusLogic_IncrementErrorCounter(&HostAdapter->TargetStatistics[TargetID].CommandAbortsAttempted);
+			return SUCCESS;
+		} else {
+			BusLogic_Warning("Unable to Abort CCB #%ld to Target %d - " "No Outgoing Mailboxes\n", HostAdapter, CCB->SerialNumber, TargetID);
+			return FAILURE;
+		}
+	} else {
+		/*
+		   Call the FlashPoint SCCB Manager to abort execution of the CCB.
+		 */
+		BusLogic_Warning("Aborting CCB #%ld to Target %d\n", HostAdapter, CCB->SerialNumber, TargetID);
+		BusLogic_IncrementErrorCounter(&HostAdapter->TargetStatistics[TargetID].CommandAbortsAttempted);
+		FlashPoint_AbortCCB(HostAdapter->CardHandle, CCB);
+		/*
+		   The Abort may have already been completed and
+		   BusLogic_QueueCompletedCCB been called, or it
+		   may still be pending.
+		 */
+		if (CCB->Status == BusLogic_CCB_Completed) {
+			BusLogic_ProcessCompletedCCBs(HostAdapter);
+		}
+		return SUCCESS;
+	}
+	return SUCCESS;
 }
 
 /*
@@ -3660,8 +3050,7 @@
   currently executing SCSI Commands as having been Reset.
 */
 
-static int BusLogic_ResetHostAdapter(struct BusLogic_HostAdapter *HostAdapter,
-				     boolean HardReset)
+static int BusLogic_ResetHostAdapter(struct BusLogic_HostAdapter *HostAdapter, boolean HardReset)
 {
 	struct BusLogic_CCB *CCB;
 	int TargetID;
@@ -3670,10 +3059,8 @@
 	 * Attempt to Reset and Reinitialize the Host Adapter.
 	 */
 
-	if (!(BusLogic_HardwareResetHostAdapter(HostAdapter, HardReset) &&
-		BusLogic_InitializeHostAdapter(HostAdapter))) {
-		BusLogic_Error("Resetting %s Failed\n", HostAdapter,
-			       HostAdapter->FullModelName);
+	if (!(BusLogic_HardwareResetHostAdapter(HostAdapter, HardReset) && BusLogic_InitializeHostAdapter(HostAdapter))) {
+		BusLogic_Error("Resetting %s Failed\n", HostAdapter, HostAdapter->FullModelName);
 		return FAILURE;
 	}
 
@@ -3721,98 +3108,70 @@
   the BIOS, and a warning may be displayed.
 */
 
-static int BusLogic_BIOSDiskParameters(struct scsi_device *sdev, struct block_device *Device,
-				       sector_t capacity, int *Parameters)
+static int BusLogic_BIOSDiskParameters(struct scsi_device *sdev, struct block_device *Device, sector_t capacity, int *Parameters)
 {
-  struct BusLogic_HostAdapter *HostAdapter = (struct BusLogic_HostAdapter *) sdev->host->hostdata;
-  struct BIOS_DiskParameters *DiskParameters = (struct BIOS_DiskParameters *) Parameters;
-  unsigned char *buf;
-  if (HostAdapter->ExtendedTranslationEnabled &&
-      capacity >= 2*1024*1024 /* 1 GB in 512 byte sectors */)
-    {
-      if (capacity >= 4*1024*1024 /* 2 GB in 512 byte sectors */)
-	{
-	  DiskParameters->Heads = 255;
-	  DiskParameters->Sectors = 63;
-	}
-      else
-	{
-	  DiskParameters->Heads = 128;
-	  DiskParameters->Sectors = 32;
-	}
-    }
-  else
-    {
-      DiskParameters->Heads = 64;
-      DiskParameters->Sectors = 32;
-    }
-  DiskParameters->Cylinders =
-    (unsigned long)capacity / (DiskParameters->Heads * DiskParameters->Sectors);
-  buf = scsi_bios_ptable(Device);
-  if (buf == NULL) return 0;
-  /*
-    If the boot sector partition table flag is valid, search for a partition
-    table entry whose end_head matches one of the standard BusLogic geometry
-    translations (64/32, 128/32, or 255/63).
-  */
-  if (*(unsigned short *) (buf+64) == 0xAA55)
-    {
-      struct partition *FirstPartitionEntry = (struct partition *) buf;
-      struct partition *PartitionEntry = FirstPartitionEntry;
-      int SavedCylinders = DiskParameters->Cylinders, PartitionNumber;
-      unsigned char PartitionEntryEndHead=0, PartitionEntryEndSector=0;
-      for (PartitionNumber = 0; PartitionNumber < 4; PartitionNumber++)
-	{
-	  PartitionEntryEndHead = PartitionEntry->end_head;
-	  PartitionEntryEndSector = PartitionEntry->end_sector & 0x3F;
-	  if (PartitionEntryEndHead == 64-1)
-	    {
-	      DiskParameters->Heads = 64;
-	      DiskParameters->Sectors = 32;
-	      break;
-	    }
-	  else if (PartitionEntryEndHead == 128-1)
-	    {
-	      DiskParameters->Heads = 128;
-	      DiskParameters->Sectors = 32;
-	      break;
-	    }
-	  else if (PartitionEntryEndHead == 255-1)
-	    {
-	      DiskParameters->Heads = 255;
-	      DiskParameters->Sectors = 63;
-	      break;
-	    }
-	  PartitionEntry++;
-	}
-      if (PartitionNumber == 4)
-	{
-	  PartitionEntryEndHead = FirstPartitionEntry->end_head;
-	  PartitionEntryEndSector = FirstPartitionEntry->end_sector & 0x3F;
-	}
-      DiskParameters->Cylinders =
-	(unsigned long)capacity / (DiskParameters->Heads * DiskParameters->Sectors);
-      if (PartitionNumber < 4 &&
-	  PartitionEntryEndSector == DiskParameters->Sectors)
-	{
-	  if (DiskParameters->Cylinders != SavedCylinders)
-	    BusLogic_Warning("Adopting Geometry %d/%d from Partition Table\n",
-			     HostAdapter,
-			     DiskParameters->Heads, DiskParameters->Sectors);
-	}
-      else if (PartitionEntryEndHead > 0 || PartitionEntryEndSector > 0)
-	{
-	  BusLogic_Warning("Warning: Partition Table appears to "
-			   "have Geometry %d/%d which is\n", HostAdapter,
-			   PartitionEntryEndHead + 1,
-			   PartitionEntryEndSector);
-	  BusLogic_Warning("not compatible with current BusLogic "
-			   "Host Adapter Geometry %d/%d\n", HostAdapter,
-			   DiskParameters->Heads, DiskParameters->Sectors);
-	}
-    }
-  kfree(buf);
-  return 0;
+	struct BusLogic_HostAdapter *HostAdapter = (struct BusLogic_HostAdapter *) sdev->host->hostdata;
+	struct BIOS_DiskParameters *DiskParameters = (struct BIOS_DiskParameters *) Parameters;
+	unsigned char *buf;
+	if (HostAdapter->ExtendedTranslationEnabled && capacity >= 2 * 1024 * 1024 /* 1 GB in 512 byte sectors */ ) {
+		if (capacity >= 4 * 1024 * 1024 /* 2 GB in 512 byte sectors */ ) {
+			DiskParameters->Heads = 255;
+			DiskParameters->Sectors = 63;
+		} else {
+			DiskParameters->Heads = 128;
+			DiskParameters->Sectors = 32;
+		}
+	} else {
+		DiskParameters->Heads = 64;
+		DiskParameters->Sectors = 32;
+	}
+	DiskParameters->Cylinders = (unsigned long) capacity / (DiskParameters->Heads * DiskParameters->Sectors);
+	buf = scsi_bios_ptable(Device);
+	if (buf == NULL)
+		return 0;
+	/*
+	   If the boot sector partition table flag is valid, search for a partition
+	   table entry whose end_head matches one of the standard BusLogic geometry
+	   translations (64/32, 128/32, or 255/63).
+	 */
+	if (*(unsigned short *) (buf + 64) == 0xAA55) {
+		struct partition *FirstPartitionEntry = (struct partition *) buf;
+		struct partition *PartitionEntry = FirstPartitionEntry;
+		int SavedCylinders = DiskParameters->Cylinders, PartitionNumber;
+		unsigned char PartitionEntryEndHead = 0, PartitionEntryEndSector = 0;
+		for (PartitionNumber = 0; PartitionNumber < 4; PartitionNumber++) {
+			PartitionEntryEndHead = PartitionEntry->end_head;
+			PartitionEntryEndSector = PartitionEntry->end_sector & 0x3F;
+			if (PartitionEntryEndHead == 64 - 1) {
+				DiskParameters->Heads = 64;
+				DiskParameters->Sectors = 32;
+				break;
+			} else if (PartitionEntryEndHead == 128 - 1) {
+				DiskParameters->Heads = 128;
+				DiskParameters->Sectors = 32;
+				break;
+			} else if (PartitionEntryEndHead == 255 - 1) {
+				DiskParameters->Heads = 255;
+				DiskParameters->Sectors = 63;
+				break;
+			}
+			PartitionEntry++;
+		}
+		if (PartitionNumber == 4) {
+			PartitionEntryEndHead = FirstPartitionEntry->end_head;
+			PartitionEntryEndSector = FirstPartitionEntry->end_sector & 0x3F;
+		}
+		DiskParameters->Cylinders = (unsigned long) capacity / (DiskParameters->Heads * DiskParameters->Sectors);
+		if (PartitionNumber < 4 && PartitionEntryEndSector == DiskParameters->Sectors) {
+			if (DiskParameters->Cylinders != SavedCylinders)
+				BusLogic_Warning("Adopting Geometry %d/%d from Partition Table\n", HostAdapter, DiskParameters->Heads, DiskParameters->Sectors);
+		} else if (PartitionEntryEndHead > 0 || PartitionEntryEndSector > 0) {
+			BusLogic_Warning("Warning: Partition Table appears to " "have Geometry %d/%d which is\n", HostAdapter, PartitionEntryEndHead + 1, PartitionEntryEndSector);
+			BusLogic_Warning("not compatible with current BusLogic " "Host Adapter Geometry %d/%d\n", HostAdapter, DiskParameters->Heads, DiskParameters->Sectors);
+		}
+	}
+	kfree(buf);
+	return 0;
 }
 
 
@@ -3820,178 +3179,124 @@
   BugLogic_ProcDirectoryInfo implements /proc/scsi/BusLogic/<N>.
 */
 
-static int BusLogic_ProcDirectoryInfo(struct Scsi_Host *shost, char *ProcBuffer,
-				      char **StartPointer, off_t Offset,
-				      int BytesAvailable, int WriteFlag)
-{
-  struct BusLogic_HostAdapter *HostAdapter;
-  struct BusLogic_TargetStatistics *TargetStatistics;
-  int TargetID, Length;
-  char *Buffer;
-  for (HostAdapter = BusLogic_FirstRegisteredHostAdapter;
-       HostAdapter != NULL;
-       HostAdapter = HostAdapter->Next)
-    if (HostAdapter->HostNumber == shost->host_no) break;
-  if (HostAdapter == NULL)
-    {
-      BusLogic_Error("Cannot find Host Adapter for SCSI Host %d\n",
-		     NULL, shost->host_no);
-      return 0;
-    }
-  TargetStatistics = HostAdapter->TargetStatistics;
-  if (WriteFlag)
-    {
-      HostAdapter->ExternalHostAdapterResets = 0;
-      HostAdapter->HostAdapterInternalErrors = 0;
-      memset(TargetStatistics, 0,
-	     BusLogic_MaxTargetDevices * sizeof(struct BusLogic_TargetStatistics));
-      return 0;
-    }
-  Buffer = HostAdapter->MessageBuffer;
-  Length = HostAdapter->MessageBufferLength;
-  Length += sprintf(&Buffer[Length], "\n\
+static int BusLogic_ProcDirectoryInfo(struct Scsi_Host *shost, char *ProcBuffer, char **StartPointer, off_t Offset, int BytesAvailable, int WriteFlag)
+{
+	struct BusLogic_HostAdapter *HostAdapter;
+	struct BusLogic_TargetStatistics *TargetStatistics;
+	int TargetID, Length;
+	char *Buffer;
+	for (HostAdapter = BusLogic_FirstRegisteredHostAdapter; HostAdapter != NULL; HostAdapter = HostAdapter->Next)
+		if (HostAdapter->HostNumber == shost->host_no)
+			break;
+	if (HostAdapter == NULL) {
+		BusLogic_Error("Cannot find Host Adapter for SCSI Host %d\n", NULL, shost->host_no);
+		return 0;
+	}
+	TargetStatistics = HostAdapter->TargetStatistics;
+	if (WriteFlag) {
+		HostAdapter->ExternalHostAdapterResets = 0;
+		HostAdapter->HostAdapterInternalErrors = 0;
+		memset(TargetStatistics, 0, BusLogic_MaxTargetDevices * sizeof(struct BusLogic_TargetStatistics));
+		return 0;
+	}
+	Buffer = HostAdapter->MessageBuffer;
+	Length = HostAdapter->MessageBufferLength;
+	Length += sprintf(&Buffer[Length], "\n\
 Current Driver Queue Depth:	%d\n\
-Currently Allocated CCBs:	%d\n",
-		    HostAdapter->DriverQueueDepth,
-		    HostAdapter->AllocatedCCBs);
-  Length += sprintf(&Buffer[Length], "\n\n\
+Currently Allocated CCBs:	%d\n", HostAdapter->DriverQueueDepth, HostAdapter->AllocatedCCBs);
+	Length += sprintf(&Buffer[Length], "\n\n\
 			   DATA TRANSFER STATISTICS\n\
 \n\
 Target	Tagged Queuing	Queue Depth  Active  Attempted	Completed\n\
 ======	==============	===========  ======  =========	=========\n");
-  for (TargetID = 0; TargetID < HostAdapter->MaxTargetDevices; TargetID++)
-    {
-      struct BusLogic_TargetFlags *TargetFlags = &HostAdapter->TargetFlags[TargetID];
-      if (!TargetFlags->TargetExists) continue;
-      Length +=
-	sprintf(&Buffer[Length], "  %2d	%s", TargetID,
-		(TargetFlags->TaggedQueuingSupported
-		 ? (TargetFlags->TaggedQueuingActive
-		    ? "    Active"
-		    : (HostAdapter->TaggedQueuingPermitted & (1 << TargetID)
-		       ? "  Permitted" : "   Disabled"))
-		 : "Not Supported"));
-      Length += sprintf(&Buffer[Length],
-			"	    %3d       %3u    %9u	%9u\n",
-			HostAdapter->QueueDepth[TargetID],
-			HostAdapter->ActiveCommands[TargetID],
-			TargetStatistics[TargetID].CommandsAttempted,
-			TargetStatistics[TargetID].CommandsCompleted);
-    }
-  Length += sprintf(&Buffer[Length], "\n\
+	for (TargetID = 0; TargetID < HostAdapter->MaxTargetDevices; TargetID++) {
+		struct BusLogic_TargetFlags *TargetFlags = &HostAdapter->TargetFlags[TargetID];
+		if (!TargetFlags->TargetExists)
+			continue;
+		Length += sprintf(&Buffer[Length], "  %2d	%s", TargetID, (TargetFlags->TaggedQueuingSupported ? (TargetFlags->TaggedQueuingActive ? "    Active" : (HostAdapter->TaggedQueuingPermitted & (1 << TargetID)
+																				    ? "  Permitted" : "   Disabled"))
+									  : "Not Supported"));
+		Length += sprintf(&Buffer[Length],
+				  "	    %3d       %3u    %9u	%9u\n", HostAdapter->QueueDepth[TargetID], HostAdapter->ActiveCommands[TargetID], TargetStatistics[TargetID].CommandsAttempted, TargetStatistics[TargetID].CommandsCompleted);
+	}
+	Length += sprintf(&Buffer[Length], "\n\
 Target  Read Commands  Write Commands   Total Bytes Read    Total Bytes Written\n\
 ======  =============  ==============  ===================  ===================\n");
-  for (TargetID = 0; TargetID < HostAdapter->MaxTargetDevices; TargetID++)
-    {
-      struct BusLogic_TargetFlags *TargetFlags = &HostAdapter->TargetFlags[TargetID];
-      if (!TargetFlags->TargetExists) continue;
-      Length +=
-	sprintf(&Buffer[Length], "  %2d	  %9u	 %9u", TargetID,
-		TargetStatistics[TargetID].ReadCommands,
-		TargetStatistics[TargetID].WriteCommands);
-      if (TargetStatistics[TargetID].TotalBytesRead.Billions > 0)
-	Length +=
-	  sprintf(&Buffer[Length], "     %9u%09u",
-		  TargetStatistics[TargetID].TotalBytesRead.Billions,
-		  TargetStatistics[TargetID].TotalBytesRead.Units);
-      else
-	Length +=
-	  sprintf(&Buffer[Length], "		%9u",
-		  TargetStatistics[TargetID].TotalBytesRead.Units);
-      if (TargetStatistics[TargetID].TotalBytesWritten.Billions > 0)
-	Length +=
-	  sprintf(&Buffer[Length], "   %9u%09u\n",
-		  TargetStatistics[TargetID].TotalBytesWritten.Billions,
-		  TargetStatistics[TargetID].TotalBytesWritten.Units);
-      else
-	Length +=
-	  sprintf(&Buffer[Length], "	     %9u\n",
-		  TargetStatistics[TargetID].TotalBytesWritten.Units);
-    }
-  Length += sprintf(&Buffer[Length], "\n\
+	for (TargetID = 0; TargetID < HostAdapter->MaxTargetDevices; TargetID++) {
+		struct BusLogic_TargetFlags *TargetFlags = &HostAdapter->TargetFlags[TargetID];
+		if (!TargetFlags->TargetExists)
+			continue;
+		Length += sprintf(&Buffer[Length], "  %2d	  %9u	 %9u", TargetID, TargetStatistics[TargetID].ReadCommands, TargetStatistics[TargetID].WriteCommands);
+		if (TargetStatistics[TargetID].TotalBytesRead.Billions > 0)
+			Length += sprintf(&Buffer[Length], "     %9u%09u", TargetStatistics[TargetID].TotalBytesRead.Billions, TargetStatistics[TargetID].TotalBytesRead.Units);
+		else
+			Length += sprintf(&Buffer[Length], "		%9u", TargetStatistics[TargetID].TotalBytesRead.Units);
+		if (TargetStatistics[TargetID].TotalBytesWritten.Billions > 0)
+			Length += sprintf(&Buffer[Length], "   %9u%09u\n", TargetStatistics[TargetID].TotalBytesWritten.Billions, TargetStatistics[TargetID].TotalBytesWritten.Units);
+		else
+			Length += sprintf(&Buffer[Length], "	     %9u\n", TargetStatistics[TargetID].TotalBytesWritten.Units);
+	}
+	Length += sprintf(&Buffer[Length], "\n\
 Target  Command    0-1KB      1-2KB      2-4KB      4-8KB     8-16KB\n\
 ======  =======  =========  =========  =========  =========  =========\n");
-  for (TargetID = 0; TargetID < HostAdapter->MaxTargetDevices; TargetID++)
-    {
-      struct BusLogic_TargetFlags *TargetFlags = &HostAdapter->TargetFlags[TargetID];
-      if (!TargetFlags->TargetExists) continue;
-      Length +=
-	sprintf(&Buffer[Length],
-		"  %2d	 Read	 %9u  %9u  %9u  %9u  %9u\n", TargetID,
-		TargetStatistics[TargetID].ReadCommandSizeBuckets[0],
-		TargetStatistics[TargetID].ReadCommandSizeBuckets[1],
-		TargetStatistics[TargetID].ReadCommandSizeBuckets[2],
-		TargetStatistics[TargetID].ReadCommandSizeBuckets[3],
-		TargetStatistics[TargetID].ReadCommandSizeBuckets[4]);
-      Length +=
-	sprintf(&Buffer[Length],
-		"  %2d	 Write	 %9u  %9u  %9u  %9u  %9u\n", TargetID,
-		TargetStatistics[TargetID].WriteCommandSizeBuckets[0],
-		TargetStatistics[TargetID].WriteCommandSizeBuckets[1],
-		TargetStatistics[TargetID].WriteCommandSizeBuckets[2],
-		TargetStatistics[TargetID].WriteCommandSizeBuckets[3],
-		TargetStatistics[TargetID].WriteCommandSizeBuckets[4]);
-    }
-  Length += sprintf(&Buffer[Length], "\n\
+	for (TargetID = 0; TargetID < HostAdapter->MaxTargetDevices; TargetID++) {
+		struct BusLogic_TargetFlags *TargetFlags = &HostAdapter->TargetFlags[TargetID];
+		if (!TargetFlags->TargetExists)
+			continue;
+		Length +=
+		    sprintf(&Buffer[Length],
+			    "  %2d	 Read	 %9u  %9u  %9u  %9u  %9u\n", TargetID,
+			    TargetStatistics[TargetID].ReadCommandSizeBuckets[0],
+			    TargetStatistics[TargetID].ReadCommandSizeBuckets[1], TargetStatistics[TargetID].ReadCommandSizeBuckets[2], TargetStatistics[TargetID].ReadCommandSizeBuckets[3], TargetStatistics[TargetID].ReadCommandSizeBuckets[4]);
+		Length +=
+		    sprintf(&Buffer[Length],
+			    "  %2d	 Write	 %9u  %9u  %9u  %9u  %9u\n", TargetID,
+			    TargetStatistics[TargetID].WriteCommandSizeBuckets[0],
+			    TargetStatistics[TargetID].WriteCommandSizeBuckets[1], TargetStatistics[TargetID].WriteCommandSizeBuckets[2], TargetStatistics[TargetID].WriteCommandSizeBuckets[3], TargetStatistics[TargetID].WriteCommandSizeBuckets[4]);
+	}
+	Length += sprintf(&Buffer[Length], "\n\
 Target  Command   16-32KB    32-64KB   64-128KB   128-256KB   256KB+\n\
 ======  =======  =========  =========  =========  =========  =========\n");
-  for (TargetID = 0; TargetID < HostAdapter->MaxTargetDevices; TargetID++)
-    {
-      struct BusLogic_TargetFlags *TargetFlags = &HostAdapter->TargetFlags[TargetID];
-      if (!TargetFlags->TargetExists) continue;
-      Length +=
-	sprintf(&Buffer[Length],
-		"  %2d	 Read	 %9u  %9u  %9u  %9u  %9u\n", TargetID,
-		TargetStatistics[TargetID].ReadCommandSizeBuckets[5],
-		TargetStatistics[TargetID].ReadCommandSizeBuckets[6],
-		TargetStatistics[TargetID].ReadCommandSizeBuckets[7],
-		TargetStatistics[TargetID].ReadCommandSizeBuckets[8],
-		TargetStatistics[TargetID].ReadCommandSizeBuckets[9]);
-      Length +=
-	sprintf(&Buffer[Length],
-		"  %2d	 Write	 %9u  %9u  %9u  %9u  %9u\n", TargetID,
-		TargetStatistics[TargetID].WriteCommandSizeBuckets[5],
-		TargetStatistics[TargetID].WriteCommandSizeBuckets[6],
-		TargetStatistics[TargetID].WriteCommandSizeBuckets[7],
-		TargetStatistics[TargetID].WriteCommandSizeBuckets[8],
-		TargetStatistics[TargetID].WriteCommandSizeBuckets[9]);
-    }
-  Length += sprintf(&Buffer[Length], "\n\n\
+	for (TargetID = 0; TargetID < HostAdapter->MaxTargetDevices; TargetID++) {
+		struct BusLogic_TargetFlags *TargetFlags = &HostAdapter->TargetFlags[TargetID];
+		if (!TargetFlags->TargetExists)
+			continue;
+		Length +=
+		    sprintf(&Buffer[Length],
+			    "  %2d	 Read	 %9u  %9u  %9u  %9u  %9u\n", TargetID,
+			    TargetStatistics[TargetID].ReadCommandSizeBuckets[5],
+			    TargetStatistics[TargetID].ReadCommandSizeBuckets[6], TargetStatistics[TargetID].ReadCommandSizeBuckets[7], TargetStatistics[TargetID].ReadCommandSizeBuckets[8], TargetStatistics[TargetID].ReadCommandSizeBuckets[9]);
+		Length +=
+		    sprintf(&Buffer[Length],
+			    "  %2d	 Write	 %9u  %9u  %9u  %9u  %9u\n", TargetID,
+			    TargetStatistics[TargetID].WriteCommandSizeBuckets[5],
+			    TargetStatistics[TargetID].WriteCommandSizeBuckets[6], TargetStatistics[TargetID].WriteCommandSizeBuckets[7], TargetStatistics[TargetID].WriteCommandSizeBuckets[8], TargetStatistics[TargetID].WriteCommandSizeBuckets[9]);
+	}
+	Length += sprintf(&Buffer[Length], "\n\n\
 			   ERROR RECOVERY STATISTICS\n\
 \n\
 	  Command Aborts      Bus Device Resets	  Host Adapter Resets\n\
 Target	Requested Completed  Requested Completed  Requested Completed\n\
   ID	\\\\\\\\ Attempted ////  \\\\\\\\ Attempted ////  \\\\\\\\ Attempted ////\n\
 ======	 ===== ===== =====    ===== ===== =====	   ===== ===== =====\n");
-  for (TargetID = 0; TargetID < HostAdapter->MaxTargetDevices; TargetID++)
-    {
-      struct BusLogic_TargetFlags *TargetFlags = &HostAdapter->TargetFlags[TargetID];
-      if (!TargetFlags->TargetExists) continue;
-      Length +=
-	sprintf(&Buffer[Length], "\
-  %2d	 %5d %5d %5d    %5d %5d %5d	   %5d %5d %5d\n", TargetID,
-		TargetStatistics[TargetID].CommandAbortsRequested,
-		TargetStatistics[TargetID].CommandAbortsAttempted,
-		TargetStatistics[TargetID].CommandAbortsCompleted,
-		TargetStatistics[TargetID].BusDeviceResetsRequested,
-		TargetStatistics[TargetID].BusDeviceResetsAttempted,
-		TargetStatistics[TargetID].BusDeviceResetsCompleted,
-		TargetStatistics[TargetID].HostAdapterResetsRequested,
-		TargetStatistics[TargetID].HostAdapterResetsAttempted,
-		TargetStatistics[TargetID].HostAdapterResetsCompleted);
-    }
-  Length += sprintf(&Buffer[Length], "\nExternal Host Adapter Resets: %d\n",
-		    HostAdapter->ExternalHostAdapterResets);
-  Length += sprintf(&Buffer[Length], "Host Adapter Internal Errors: %d\n",
-		    HostAdapter->HostAdapterInternalErrors);
-  if (Length >= BusLogic_MessageBufferSize)
-    BusLogic_Error("Message Buffer length %d exceeds size %d\n",
-		   HostAdapter, Length, BusLogic_MessageBufferSize);
-  if ((Length -= Offset) <= 0) return 0;
-  if (Length >= BytesAvailable) Length = BytesAvailable;
-  memcpy(ProcBuffer, HostAdapter->MessageBuffer + Offset, Length);
-  *StartPointer = ProcBuffer;
-  return Length;
+	for (TargetID = 0; TargetID < HostAdapter->MaxTargetDevices; TargetID++) {
+		struct BusLogic_TargetFlags *TargetFlags = &HostAdapter->TargetFlags[TargetID];
+		if (!TargetFlags->TargetExists)
+			continue;
+		Length += sprintf(&Buffer[Length], "\
+  %2d	 %5d %5d %5d    %5d %5d %5d	   %5d %5d %5d\n", TargetID, TargetStatistics[TargetID].CommandAbortsRequested, TargetStatistics[TargetID].CommandAbortsAttempted, TargetStatistics[TargetID].CommandAbortsCompleted, TargetStatistics[TargetID].BusDeviceResetsRequested, TargetStatistics[TargetID].BusDeviceResetsAttempted, TargetStatistics[TargetID].BusDeviceResetsCompleted, TargetStatistics[TargetID].HostAdapterResetsRequested, TargetStatistics[TargetID].HostAdapterResetsAttempted, TargetStatistics[TargetID].HostAdapterResetsCompleted);
+	}
+	Length += sprintf(&Buffer[Length], "\nExternal Host Adapter Resets: %d\n", HostAdapter->ExternalHostAdapterResets);
+	Length += sprintf(&Buffer[Length], "Host Adapter Internal Errors: %d\n", HostAdapter->HostAdapterInternalErrors);
+	if (Length >= BusLogic_MessageBufferSize)
+		BusLogic_Error("Message Buffer length %d exceeds size %d\n", HostAdapter, Length, BusLogic_MessageBufferSize);
+	if ((Length -= Offset) <= 0)
+		return 0;
+	if (Length >= BytesAvailable)
+		Length = BytesAvailable;
+	memcpy(ProcBuffer, HostAdapter->MessageBuffer + Offset, Length);
+	*StartPointer = ProcBuffer;
+	return Length;
 }
 
 
@@ -3999,52 +3304,39 @@
   BusLogic_Message prints Driver Messages.
 */
 
-static void BusLogic_Message(enum BusLogic_MessageLevel MessageLevel,
-			     char *Format,
-			     struct BusLogic_HostAdapter *HostAdapter,
-			     ...)
-{
-  static char Buffer[BusLogic_LineBufferSize];
-  static boolean BeginningOfLine = true;
-  va_list Arguments;
-  int Length = 0;
-  va_start(Arguments, HostAdapter);
-  Length = vsprintf(Buffer, Format, Arguments);
-  va_end(Arguments);
-  if (MessageLevel == BusLogic_AnnounceLevel)
-    {
-      static int AnnouncementLines = 0;
-      strcpy(&HostAdapter->MessageBuffer[HostAdapter->MessageBufferLength],
-	     Buffer);
-      HostAdapter->MessageBufferLength += Length;
-      if (++AnnouncementLines <= 2)
-	printk("%sscsi: %s", BusLogic_MessageLevelMap[MessageLevel], Buffer);
-    }
-  else if (MessageLevel == BusLogic_InfoLevel)
-    {
-      strcpy(&HostAdapter->MessageBuffer[HostAdapter->MessageBufferLength],
-	     Buffer);
-      HostAdapter->MessageBufferLength += Length;
-      if (BeginningOfLine)
-	{
-	  if (Buffer[0] != '\n' || Length > 1)
-	    printk("%sscsi%d: %s", BusLogic_MessageLevelMap[MessageLevel],
-		   HostAdapter->HostNumber, Buffer);
-	}
-      else printk("%s", Buffer);
-    }
-  else
-    {
-      if (BeginningOfLine)
-	{
-	  if (HostAdapter != NULL && HostAdapter->HostAdapterInitialized)
-	    printk("%sscsi%d: %s", BusLogic_MessageLevelMap[MessageLevel],
-		   HostAdapter->HostNumber, Buffer);
-	  else printk("%s%s", BusLogic_MessageLevelMap[MessageLevel], Buffer);
-	}
-      else printk("%s", Buffer);
-    }
-  BeginningOfLine = (Buffer[Length-1] == '\n');
+static void BusLogic_Message(enum BusLogic_MessageLevel MessageLevel, char *Format, struct BusLogic_HostAdapter *HostAdapter, ...)
+{
+	static char Buffer[BusLogic_LineBufferSize];
+	static boolean BeginningOfLine = true;
+	va_list Arguments;
+	int Length = 0;
+	va_start(Arguments, HostAdapter);
+	Length = vsprintf(Buffer, Format, Arguments);
+	va_end(Arguments);
+	if (MessageLevel == BusLogic_AnnounceLevel) {
+		static int AnnouncementLines = 0;
+		strcpy(&HostAdapter->MessageBuffer[HostAdapter->MessageBufferLength], Buffer);
+		HostAdapter->MessageBufferLength += Length;
+		if (++AnnouncementLines <= 2)
+			printk("%sscsi: %s", BusLogic_MessageLevelMap[MessageLevel], Buffer);
+	} else if (MessageLevel == BusLogic_InfoLevel) {
+		strcpy(&HostAdapter->MessageBuffer[HostAdapter->MessageBufferLength], Buffer);
+		HostAdapter->MessageBufferLength += Length;
+		if (BeginningOfLine) {
+			if (Buffer[0] != '\n' || Length > 1)
+				printk("%sscsi%d: %s", BusLogic_MessageLevelMap[MessageLevel], HostAdapter->HostNumber, Buffer);
+		} else
+			printk("%s", Buffer);
+	} else {
+		if (BeginningOfLine) {
+			if (HostAdapter != NULL && HostAdapter->HostAdapterInitialized)
+				printk("%sscsi%d: %s", BusLogic_MessageLevelMap[MessageLevel], HostAdapter->HostNumber, Buffer);
+			else
+				printk("%s%s", BusLogic_MessageLevelMap[MessageLevel], Buffer);
+		} else
+			printk("%s", Buffer);
+	}
+	BeginningOfLine = (Buffer[Length - 1] == '\n');
 }
 
 
@@ -4055,19 +3347,19 @@
 
 static boolean __init BusLogic_ParseKeyword(char **StringPointer, char *Keyword)
 {
-  char *Pointer = *StringPointer;
-  while (*Keyword != '\0')
-    {
-      char StringChar = *Pointer++;
-      char KeywordChar = *Keyword++;
-      if (StringChar >= 'A' && StringChar <= 'Z')
-	StringChar += 'a' - 'Z';
-      if (KeywordChar >= 'A' && KeywordChar <= 'Z')
-	KeywordChar += 'a' - 'Z';
-      if (StringChar != KeywordChar) return false;
-    }
-  *StringPointer = Pointer;
-  return true;
+	char *Pointer = *StringPointer;
+	while (*Keyword != '\0') {
+		char StringChar = *Pointer++;
+		char KeywordChar = *Keyword++;
+		if (StringChar >= 'A' && StringChar <= 'Z')
+			StringChar += 'a' - 'Z';
+		if (KeywordChar >= 'A' && KeywordChar <= 'Z')
+			KeywordChar += 'a' - 'Z';
+		if (StringChar != KeywordChar)
+			return false;
+	}
+	*StringPointer = Pointer;
+	return true;
 }
 
 
@@ -4090,225 +3382,165 @@
 
 static int __init BusLogic_ParseDriverOptions(char *OptionsString)
 {
-  while (true)
-    {
-      struct BusLogic_DriverOptions *DriverOptions =
-	&BusLogic_DriverOptions[BusLogic_DriverOptionsCount++];
-      int TargetID;
-      memset(DriverOptions, 0, sizeof(struct BusLogic_DriverOptions));
-      while (*OptionsString != '\0' && *OptionsString != ';')
-	{
-	  /* Probing Options. */
-	  if (BusLogic_ParseKeyword(&OptionsString, "IO:"))
-	    {
-	      unsigned long IO_Address =
-		simple_strtoul(OptionsString, &OptionsString, 0);
-	      BusLogic_ProbeOptions.LimitedProbeISA = true;
-	      switch (IO_Address)
-		{
-		case 0x330:
-		  BusLogic_ProbeOptions.Probe330 = true;
-		  break;
-		case 0x334:
-		  BusLogic_ProbeOptions.Probe334 = true;
-		  break;
-		case 0x230:
-		  BusLogic_ProbeOptions.Probe230 = true;
-		  break;
-		case 0x234:
-		  BusLogic_ProbeOptions.Probe234 = true;
-		  break;
-		case 0x130:
-		  BusLogic_ProbeOptions.Probe130 = true;
-		  break;
-		case 0x134:
-		  BusLogic_ProbeOptions.Probe134 = true;
-		  break;
-		default:
-		  BusLogic_Error("BusLogic: Invalid Driver Options "
-				 "(invalid I/O Address 0x%X)\n",
-				 NULL, IO_Address);
-		  return 0;
-		}
-	    }
-	  else if (BusLogic_ParseKeyword(&OptionsString, "NoProbeISA"))
-	    BusLogic_ProbeOptions.NoProbeISA = true;
-	  else if (BusLogic_ParseKeyword(&OptionsString, "NoProbePCI"))
-	    BusLogic_ProbeOptions.NoProbePCI = true;
-	  else if (BusLogic_ParseKeyword(&OptionsString, "NoProbe"))
-	    BusLogic_ProbeOptions.NoProbe = true;
-	  else if (BusLogic_ParseKeyword(&OptionsString, "NoSortPCI"))
-	    BusLogic_ProbeOptions.NoSortPCI = true;
-	  else if (BusLogic_ParseKeyword(&OptionsString, "MultiMasterFirst"))
-	    BusLogic_ProbeOptions.MultiMasterFirst = true;
-	  else if (BusLogic_ParseKeyword(&OptionsString, "FlashPointFirst"))
-	    BusLogic_ProbeOptions.FlashPointFirst = true;
-	  /* Tagged Queuing Options. */
-	  else if (BusLogic_ParseKeyword(&OptionsString, "QueueDepth:[") ||
-		   BusLogic_ParseKeyword(&OptionsString, "QD:["))
-	    {
-	      for (TargetID = 0;
-		   TargetID < BusLogic_MaxTargetDevices;
-		   TargetID++)
-		{
-		  unsigned short QueueDepth =
-		    simple_strtoul(OptionsString, &OptionsString, 0);
-		  if (QueueDepth > BusLogic_MaxTaggedQueueDepth)
-		    {
-		      BusLogic_Error("BusLogic: Invalid Driver Options "
-				     "(invalid Queue Depth %d)\n",
-				     NULL, QueueDepth);
-		      return 0;
-		    }
-		  DriverOptions->QueueDepth[TargetID] = QueueDepth;
-		  if (*OptionsString == ',')
-		    OptionsString++;
-		  else if (*OptionsString == ']')
-		    break;
-		  else
-		    {
-		      BusLogic_Error("BusLogic: Invalid Driver Options "
-				     "(',' or ']' expected at '%s')\n",
-				     NULL, OptionsString);
-		      return 0;
-		    }
-		}
-	      if (*OptionsString != ']')
-		{
-		  BusLogic_Error("BusLogic: Invalid Driver Options "
-				 "(']' expected at '%s')\n",
-				 NULL, OptionsString);
-		  return 0;
-		}
-	      else OptionsString++;
-	    }
-	  else if (BusLogic_ParseKeyword(&OptionsString, "QueueDepth:") ||
-		   BusLogic_ParseKeyword(&OptionsString, "QD:"))
-	    {
-	      unsigned short QueueDepth =
-		simple_strtoul(OptionsString, &OptionsString, 0);
-	      if (QueueDepth == 0 || QueueDepth > BusLogic_MaxTaggedQueueDepth)
-		{
-		  BusLogic_Error("BusLogic: Invalid Driver Options "
-				 "(invalid Queue Depth %d)\n",
-				 NULL, QueueDepth);
-		  return 0;
-		}
-	      DriverOptions->CommonQueueDepth = QueueDepth;
-	      for (TargetID = 0;
-		   TargetID < BusLogic_MaxTargetDevices;
-		   TargetID++)
-		DriverOptions->QueueDepth[TargetID] = QueueDepth;
-	    }
-	  else if (BusLogic_ParseKeyword(&OptionsString, "TaggedQueuing:") ||
-		   BusLogic_ParseKeyword(&OptionsString, "TQ:"))
-	    {
-	      if (BusLogic_ParseKeyword(&OptionsString, "Default"))
-		{
-		  DriverOptions->TaggedQueuingPermitted = 0x0000;
-		  DriverOptions->TaggedQueuingPermittedMask = 0x0000;
-		}
-	      else if (BusLogic_ParseKeyword(&OptionsString, "Enable"))
-		{
-		  DriverOptions->TaggedQueuingPermitted = 0xFFFF;
-		  DriverOptions->TaggedQueuingPermittedMask = 0xFFFF;
-		}
-	      else if (BusLogic_ParseKeyword(&OptionsString, "Disable"))
-		{
-		  DriverOptions->TaggedQueuingPermitted = 0x0000;
-		  DriverOptions->TaggedQueuingPermittedMask = 0xFFFF;
-		}
-	      else
-		{
-		  unsigned short TargetBit;
-		  for (TargetID = 0, TargetBit = 1;
-		       TargetID < BusLogic_MaxTargetDevices;
-		       TargetID++, TargetBit <<= 1)
-		    switch (*OptionsString++)
-		      {
-		      case 'Y':
-			DriverOptions->TaggedQueuingPermitted |= TargetBit;
-			DriverOptions->TaggedQueuingPermittedMask |= TargetBit;
-			break;
-		      case 'N':
-			DriverOptions->TaggedQueuingPermitted &= ~TargetBit;
-			DriverOptions->TaggedQueuingPermittedMask |= TargetBit;
-			break;
-		      case 'X':
-			break;
-		      default:
-			OptionsString--;
-			TargetID = BusLogic_MaxTargetDevices;
-			break;
-		      }
+	while (true) {
+		struct BusLogic_DriverOptions *DriverOptions = &BusLogic_DriverOptions[BusLogic_DriverOptionsCount++];
+		int TargetID;
+		memset(DriverOptions, 0, sizeof(struct BusLogic_DriverOptions));
+		while (*OptionsString != '\0' && *OptionsString != ';') {
+			/* Probing Options. */
+			if (BusLogic_ParseKeyword(&OptionsString, "IO:")) {
+				unsigned long IO_Address = simple_strtoul(OptionsString, &OptionsString, 0);
+				BusLogic_ProbeOptions.LimitedProbeISA = true;
+				switch (IO_Address) {
+				case 0x330:
+					BusLogic_ProbeOptions.Probe330 = true;
+					break;
+				case 0x334:
+					BusLogic_ProbeOptions.Probe334 = true;
+					break;
+				case 0x230:
+					BusLogic_ProbeOptions.Probe230 = true;
+					break;
+				case 0x234:
+					BusLogic_ProbeOptions.Probe234 = true;
+					break;
+				case 0x130:
+					BusLogic_ProbeOptions.Probe130 = true;
+					break;
+				case 0x134:
+					BusLogic_ProbeOptions.Probe134 = true;
+					break;
+				default:
+					BusLogic_Error("BusLogic: Invalid Driver Options " "(invalid I/O Address 0x%X)\n", NULL, IO_Address);
+					return 0;
+				}
+			} else if (BusLogic_ParseKeyword(&OptionsString, "NoProbeISA"))
+				BusLogic_ProbeOptions.NoProbeISA = true;
+			else if (BusLogic_ParseKeyword(&OptionsString, "NoProbePCI"))
+				BusLogic_ProbeOptions.NoProbePCI = true;
+			else if (BusLogic_ParseKeyword(&OptionsString, "NoProbe"))
+				BusLogic_ProbeOptions.NoProbe = true;
+			else if (BusLogic_ParseKeyword(&OptionsString, "NoSortPCI"))
+				BusLogic_ProbeOptions.NoSortPCI = true;
+			else if (BusLogic_ParseKeyword(&OptionsString, "MultiMasterFirst"))
+				BusLogic_ProbeOptions.MultiMasterFirst = true;
+			else if (BusLogic_ParseKeyword(&OptionsString, "FlashPointFirst"))
+				BusLogic_ProbeOptions.FlashPointFirst = true;
+			/* Tagged Queuing Options. */
+			else if (BusLogic_ParseKeyword(&OptionsString, "QueueDepth:[") || BusLogic_ParseKeyword(&OptionsString, "QD:[")) {
+				for (TargetID = 0; TargetID < BusLogic_MaxTargetDevices; TargetID++) {
+					unsigned short QueueDepth = simple_strtoul(OptionsString, &OptionsString, 0);
+					if (QueueDepth > BusLogic_MaxTaggedQueueDepth) {
+						BusLogic_Error("BusLogic: Invalid Driver Options " "(invalid Queue Depth %d)\n", NULL, QueueDepth);
+						return 0;
+					}
+					DriverOptions->QueueDepth[TargetID] = QueueDepth;
+					if (*OptionsString == ',')
+						OptionsString++;
+					else if (*OptionsString == ']')
+						break;
+					else {
+						BusLogic_Error("BusLogic: Invalid Driver Options " "(',' or ']' expected at '%s')\n", NULL, OptionsString);
+						return 0;
+					}
+				}
+				if (*OptionsString != ']') {
+					BusLogic_Error("BusLogic: Invalid Driver Options " "(']' expected at '%s')\n", NULL, OptionsString);
+					return 0;
+				} else
+					OptionsString++;
+			} else if (BusLogic_ParseKeyword(&OptionsString, "QueueDepth:") || BusLogic_ParseKeyword(&OptionsString, "QD:")) {
+				unsigned short QueueDepth = simple_strtoul(OptionsString, &OptionsString, 0);
+				if (QueueDepth == 0 || QueueDepth > BusLogic_MaxTaggedQueueDepth) {
+					BusLogic_Error("BusLogic: Invalid Driver Options " "(invalid Queue Depth %d)\n", NULL, QueueDepth);
+					return 0;
+				}
+				DriverOptions->CommonQueueDepth = QueueDepth;
+				for (TargetID = 0; TargetID < BusLogic_MaxTargetDevices; TargetID++)
+					DriverOptions->QueueDepth[TargetID] = QueueDepth;
+			} else if (BusLogic_ParseKeyword(&OptionsString, "TaggedQueuing:") || BusLogic_ParseKeyword(&OptionsString, "TQ:")) {
+				if (BusLogic_ParseKeyword(&OptionsString, "Default")) {
+					DriverOptions->TaggedQueuingPermitted = 0x0000;
+					DriverOptions->TaggedQueuingPermittedMask = 0x0000;
+				} else if (BusLogic_ParseKeyword(&OptionsString, "Enable")) {
+					DriverOptions->TaggedQueuingPermitted = 0xFFFF;
+					DriverOptions->TaggedQueuingPermittedMask = 0xFFFF;
+				} else if (BusLogic_ParseKeyword(&OptionsString, "Disable")) {
+					DriverOptions->TaggedQueuingPermitted = 0x0000;
+					DriverOptions->TaggedQueuingPermittedMask = 0xFFFF;
+				} else {
+					unsigned short TargetBit;
+					for (TargetID = 0, TargetBit = 1; TargetID < BusLogic_MaxTargetDevices; TargetID++, TargetBit <<= 1)
+						switch (*OptionsString++) {
+						case 'Y':
+							DriverOptions->TaggedQueuingPermitted |= TargetBit;
+							DriverOptions->TaggedQueuingPermittedMask |= TargetBit;
+							break;
+						case 'N':
+							DriverOptions->TaggedQueuingPermitted &= ~TargetBit;
+							DriverOptions->TaggedQueuingPermittedMask |= TargetBit;
+							break;
+						case 'X':
+							break;
+						default:
+							OptionsString--;
+							TargetID = BusLogic_MaxTargetDevices;
+							break;
+						}
+				}
+			}
+			/* Miscellaneous Options. */
+			else if (BusLogic_ParseKeyword(&OptionsString, "BusSettleTime:") || BusLogic_ParseKeyword(&OptionsString, "BST:")) {
+				unsigned short BusSettleTime = simple_strtoul(OptionsString, &OptionsString, 0);
+				if (BusSettleTime > 5 * 60) {
+					BusLogic_Error("BusLogic: Invalid Driver Options " "(invalid Bus Settle Time %d)\n", NULL, BusSettleTime);
+					return 0;
+				}
+				DriverOptions->BusSettleTime = BusSettleTime;
+			} else if (BusLogic_ParseKeyword(&OptionsString, "InhibitTargetInquiry"))
+				DriverOptions->LocalOptions.InhibitTargetInquiry = true;
+			/* Debugging Options. */
+			else if (BusLogic_ParseKeyword(&OptionsString, "TraceProbe"))
+				BusLogic_GlobalOptions.TraceProbe = true;
+			else if (BusLogic_ParseKeyword(&OptionsString, "TraceHardwareReset"))
+				BusLogic_GlobalOptions.TraceHardwareReset = true;
+			else if (BusLogic_ParseKeyword(&OptionsString, "TraceConfiguration"))
+				BusLogic_GlobalOptions.TraceConfiguration = true;
+			else if (BusLogic_ParseKeyword(&OptionsString, "TraceErrors"))
+				BusLogic_GlobalOptions.TraceErrors = true;
+			else if (BusLogic_ParseKeyword(&OptionsString, "Debug")) {
+				BusLogic_GlobalOptions.TraceProbe = true;
+				BusLogic_GlobalOptions.TraceHardwareReset = true;
+				BusLogic_GlobalOptions.TraceConfiguration = true;
+				BusLogic_GlobalOptions.TraceErrors = true;
+			}
+			if (*OptionsString == ',')
+				OptionsString++;
+			else if (*OptionsString != ';' && *OptionsString != '\0') {
+				BusLogic_Error("BusLogic: Unexpected Driver Option '%s' " "ignored\n", NULL, OptionsString);
+				*OptionsString = '\0';
+			}
+		}
+		if (!(BusLogic_DriverOptionsCount == 0 || BusLogic_ProbeInfoCount == 0 || BusLogic_DriverOptionsCount == BusLogic_ProbeInfoCount)) {
+			BusLogic_Error("BusLogic: Invalid Driver Options " "(all or no I/O Addresses must be specified)\n", NULL);
+			return 0;
 		}
-	    }
-	  /* Miscellaneous Options. */
-	  else if (BusLogic_ParseKeyword(&OptionsString, "BusSettleTime:") ||
-		   BusLogic_ParseKeyword(&OptionsString, "BST:"))
-	    {
-	      unsigned short BusSettleTime =
-		simple_strtoul(OptionsString, &OptionsString, 0);
-	      if (BusSettleTime > 5 * 60)
-		{
-		  BusLogic_Error("BusLogic: Invalid Driver Options "
-				 "(invalid Bus Settle Time %d)\n",
-				 NULL, BusSettleTime);
-		  return 0;
-		}
-	      DriverOptions->BusSettleTime = BusSettleTime;
-	    }
-	  else if (BusLogic_ParseKeyword(&OptionsString,
-					 "InhibitTargetInquiry"))
-	    DriverOptions->LocalOptions.InhibitTargetInquiry = true;
-	  /* Debugging Options. */
-	  else if (BusLogic_ParseKeyword(&OptionsString, "TraceProbe"))
-	      BusLogic_GlobalOptions.TraceProbe = true;
-	  else if (BusLogic_ParseKeyword(&OptionsString, "TraceHardwareReset"))
-	      BusLogic_GlobalOptions.TraceHardwareReset = true;
-	  else if (BusLogic_ParseKeyword(&OptionsString, "TraceConfiguration"))
-	      BusLogic_GlobalOptions.TraceConfiguration = true;
-	  else if (BusLogic_ParseKeyword(&OptionsString, "TraceErrors"))
-	      BusLogic_GlobalOptions.TraceErrors = true;
-	  else if (BusLogic_ParseKeyword(&OptionsString, "Debug"))
-	    {
-	      BusLogic_GlobalOptions.TraceProbe = true;
-	      BusLogic_GlobalOptions.TraceHardwareReset = true;
-	      BusLogic_GlobalOptions.TraceConfiguration = true;
-	      BusLogic_GlobalOptions.TraceErrors = true;
-	    }
-	  if (*OptionsString == ',')
-	    OptionsString++;
-	  else if (*OptionsString != ';' && *OptionsString != '\0')
-	    {
-	      BusLogic_Error("BusLogic: Unexpected Driver Option '%s' "
-			     "ignored\n", NULL, OptionsString);
-	      *OptionsString = '\0';
-	    }
-	}
-      if (!(BusLogic_DriverOptionsCount == 0 ||
-	    BusLogic_ProbeInfoCount == 0 ||
-	    BusLogic_DriverOptionsCount == BusLogic_ProbeInfoCount))
-	{
-	  BusLogic_Error("BusLogic: Invalid Driver Options "
-			 "(all or no I/O Addresses must be specified)\n", NULL);
-	  return 0;
-	}
-      /*
-	Tagged Queuing is disabled when the Queue Depth is 1 since queuing
-	multiple commands is not possible.
-      */
-      for (TargetID = 0; TargetID < BusLogic_MaxTargetDevices; TargetID++)
-	if (DriverOptions->QueueDepth[TargetID] == 1)
-	  {
-	    unsigned short TargetBit = 1 << TargetID;
-	    DriverOptions->TaggedQueuingPermitted &= ~TargetBit;
-	    DriverOptions->TaggedQueuingPermittedMask |= TargetBit;
-	  }
-      if (*OptionsString == ';') OptionsString++;
-      if (*OptionsString == '\0') return 0;
-    }
-    return 1;
+		/*
+		   Tagged Queuing is disabled when the Queue Depth is 1 since queuing
+		   multiple commands is not possible.
+		 */
+		for (TargetID = 0; TargetID < BusLogic_MaxTargetDevices; TargetID++)
+			if (DriverOptions->QueueDepth[TargetID] == 1) {
+				unsigned short TargetBit = 1 << TargetID;
+				DriverOptions->TaggedQueuingPermitted &= ~TargetBit;
+				DriverOptions->TaggedQueuingPermittedMask |= TargetBit;
+			}
+		if (*OptionsString == ';')
+			OptionsString++;
+		if (*OptionsString == '\0')
+			return 0;
+	}
+	return 1;
 }
 
 /*
@@ -4316,21 +3548,21 @@
 */
 
 static struct scsi_host_template driver_template = {
-	.module			= THIS_MODULE,
-	.proc_name		= "BusLogic",
-	.proc_info		= BusLogic_ProcDirectoryInfo,
-	.name			= "BusLogic",
-	.info			= BusLogic_DriverInfo,
-	.queuecommand		= BusLogic_QueueCommand,
-	.slave_configure	= BusLogic_SlaveConfigure,
-	.bios_param		= BusLogic_BIOSDiskParameters,
-	.eh_host_reset_handler	= BusLogic_host_reset,
+	.module = THIS_MODULE,
+	.proc_name = "BusLogic",
+	.proc_info = BusLogic_ProcDirectoryInfo,
+	.name = "BusLogic",
+	.info = BusLogic_DriverInfo,
+	.queuecommand = BusLogic_QueueCommand,
+	.slave_configure = BusLogic_SlaveConfigure,
+	.bios_param = BusLogic_BIOSDiskParameters,
+	.eh_host_reset_handler = BusLogic_host_reset,
 #if 0
-	.eh_abort_handler	= BusLogic_AbortCommand,
+	.eh_abort_handler = BusLogic_AbortCommand,
 #endif
-	.unchecked_isa_dma	= 1,
-	.max_sectors		= 128,
-	.use_clustering		= ENABLE_CLUSTERING,
+	.unchecked_isa_dma = 1,
+	.max_sectors = 128,
+	.use_clustering = ENABLE_CLUSTERING,
 };
 
 /*
@@ -4341,11 +3573,10 @@
 {
 	int ints[3];
 
-	(void)get_options(str, ARRAY_SIZE(ints), ints);
+	(void) get_options(str, ARRAY_SIZE(ints), ints);
 
 	if (ints[0] != 0) {
-		BusLogic_Error("BusLogic: Obsolete Command Line Entry "
-				"Format Ignored\n", NULL);
+		BusLogic_Error("BusLogic: Obsolete Command Line Entry " "Format Ignored\n", NULL);
 		return 0;
 	}
 	if (str == NULL || *str == '\0')
@@ -4357,13 +3588,14 @@
  * Initialization function
  */
 
-static int __init BusLogic_init(void) {
+static int __init BusLogic_init(void)
+{
 
 #ifdef MODULE
 	if (BusLogic)
 		BusLogic_Setup(BusLogic);
 #endif
-	 
+
 	return BusLogic_DetectHostAdapter(&driver_template) ? 0 : -ENODEV;
 }
 
@@ -4374,14 +3606,12 @@
 static void __exit BusLogic_exit(void)
 {
 	struct BusLogic_HostAdapter *HostAdapter;
-	for (HostAdapter = BusLogic_FirstRegisteredHostAdapter;
-		HostAdapter != NULL; HostAdapter = HostAdapter->Next) {
+	for (HostAdapter = BusLogic_FirstRegisteredHostAdapter; HostAdapter != NULL; HostAdapter = HostAdapter->Next) {
 		struct Scsi_Host *host = HostAdapter->SCSI_Host;
 		scsi_remove_host(host);
 
 	}
-	for (HostAdapter = BusLogic_FirstRegisteredHostAdapter;
-		HostAdapter != NULL; HostAdapter = HostAdapter->Next) {
+	for (HostAdapter = BusLogic_FirstRegisteredHostAdapter; HostAdapter != NULL; HostAdapter = HostAdapter->Next) {
 		struct Scsi_Host *host = HostAdapter->SCSI_Host;
 		BusLogic_ReleaseHostAdapter(host);
 	}
diff -Nru a/drivers/scsi/BusLogic.h b/drivers/scsi/BusLogic.h
--- a/drivers/scsi/BusLogic.h	2004-10-18 14:56:29 -07:00
+++ b/drivers/scsi/BusLogic.h	2004-10-18 14:56:29 -07:00
@@ -128,17 +128,15 @@
   Define the Driver Message Levels.
 */
 
-enum BusLogic_MessageLevel
-{
-  BusLogic_AnnounceLevel =			0,
-  BusLogic_InfoLevel =				1,
-  BusLogic_NoticeLevel =			2,
-  BusLogic_WarningLevel =			3,
-  BusLogic_ErrorLevel =				4
+enum BusLogic_MessageLevel {
+	BusLogic_AnnounceLevel = 0,
+	BusLogic_InfoLevel = 1,
+	BusLogic_NoticeLevel = 2,
+	BusLogic_WarningLevel = 3,
+	BusLogic_ErrorLevel = 4
 };
 
-static char *BusLogic_MessageLevelMap[] =
-    { KERN_NOTICE, KERN_NOTICE, KERN_NOTICE, KERN_WARNING, KERN_ERR };
+static char *BusLogic_MessageLevelMap[] = { KERN_NOTICE, KERN_NOTICE, KERN_NOTICE, KERN_WARNING, KERN_ERR };
 
 
 /*
@@ -166,17 +164,15 @@
   of I/O Addresses required by each type.
 */
 
-enum BusLogic_HostAdapterType
-{
-  BusLogic_MultiMaster =			1,
-  BusLogic_FlashPoint =				2
+enum BusLogic_HostAdapterType {
+	BusLogic_MultiMaster = 1,
+	BusLogic_FlashPoint = 2
 } PACKED;
 
 #define BusLogic_MultiMasterAddressCount	4
 #define BusLogic_FlashPointAddressCount		256
 
-static int BusLogic_HostAdapterAddressCount[3] =
-    { 0, BusLogic_MultiMasterAddressCount, BusLogic_FlashPointAddressCount };
+static int BusLogic_HostAdapterAddressCount[3] = { 0, BusLogic_MultiMasterAddressCount, BusLogic_FlashPointAddressCount };
 
 
 /*
@@ -206,39 +202,35 @@
   Define the possible Host Adapter Bus Types.
 */
 
-enum BusLogic_HostAdapterBusType
-{
-  BusLogic_Unknown_Bus =			0,
-  BusLogic_ISA_Bus =				1,
-  BusLogic_EISA_Bus =				2,
-  BusLogic_PCI_Bus =				3,
-  BusLogic_VESA_Bus =				4,
-  BusLogic_MCA_Bus =				5
+enum BusLogic_HostAdapterBusType {
+	BusLogic_Unknown_Bus = 0,
+	BusLogic_ISA_Bus = 1,
+	BusLogic_EISA_Bus = 2,
+	BusLogic_PCI_Bus = 3,
+	BusLogic_VESA_Bus = 4,
+	BusLogic_MCA_Bus = 5
 } PACKED;
 
-static char *BusLogic_HostAdapterBusNames[] =
-    { "Unknown", "ISA", "EISA", "PCI", "VESA", "MCA" };
+static char *BusLogic_HostAdapterBusNames[] = { "Unknown", "ISA", "EISA", "PCI", "VESA", "MCA" };
 
-static enum BusLogic_HostAdapterBusType BusLogic_HostAdapterBusTypes[] =
-{
-  BusLogic_VESA_Bus,				/* BT-4xx */
-  BusLogic_ISA_Bus,				/* BT-5xx */
-  BusLogic_MCA_Bus,				/* BT-6xx */
-  BusLogic_EISA_Bus,				/* BT-7xx */
-  BusLogic_Unknown_Bus,				/* BT-8xx */
-  BusLogic_PCI_Bus				/* BT-9xx */
+static enum BusLogic_HostAdapterBusType BusLogic_HostAdapterBusTypes[] = {
+	BusLogic_VESA_Bus,	/* BT-4xx */
+	BusLogic_ISA_Bus,	/* BT-5xx */
+	BusLogic_MCA_Bus,	/* BT-6xx */
+	BusLogic_EISA_Bus,	/* BT-7xx */
+	BusLogic_Unknown_Bus,	/* BT-8xx */
+	BusLogic_PCI_Bus	/* BT-9xx */
 };
 
 /*
   Define the possible Host Adapter BIOS Disk Geometry Translations.
 */
 
-enum BusLogic_BIOS_DiskGeometryTranslation
-{
-  BusLogic_BIOS_Disk_Not_Installed =		0,
-  BusLogic_BIOS_Disk_Installed_64x32 =		1,
-  BusLogic_BIOS_Disk_Installed_128x32 =		2,
-  BusLogic_BIOS_Disk_Installed_255x63 =		3
+enum BusLogic_BIOS_DiskGeometryTranslation {
+	BusLogic_BIOS_Disk_Not_Installed = 0,
+	BusLogic_BIOS_Disk_Installed_64x32 = 1,
+	BusLogic_BIOS_Disk_Installed_128x32 = 2,
+	BusLogic_BIOS_Disk_Installed_255x63 = 3
 } PACKED;
 
 
@@ -247,18 +239,17 @@
 */
 
 typedef enum {
-  false,
-  true
+	false,
+	true
 } PACKED boolean;
 
 /*
   Define a 10^18 Statistics Byte Counter data type.
 */
 
-struct BusLogic_ByteCounter
-{
-  unsigned int Units;
-  unsigned int Billions;
+struct BusLogic_ByteCounter {
+	unsigned int Units;
+	unsigned int Billions;
 };
 
 
@@ -266,58 +257,54 @@
   Define the structure for I/O Address and Bus Probing Information.
 */
 
-struct BusLogic_ProbeInfo
-{
-  enum BusLogic_HostAdapterType HostAdapterType;
-  enum BusLogic_HostAdapterBusType HostAdapterBusType;
-  unsigned long IO_Address;
-  unsigned long PCI_Address;
-  struct pci_dev *PCI_Device;
-  unsigned char Bus;
-  unsigned char Device;
-  unsigned char IRQ_Channel;
+struct BusLogic_ProbeInfo {
+	enum BusLogic_HostAdapterType HostAdapterType;
+	enum BusLogic_HostAdapterBusType HostAdapterBusType;
+	unsigned long IO_Address;
+	unsigned long PCI_Address;
+	struct pci_dev *PCI_Device;
+	unsigned char Bus;
+	unsigned char Device;
+	unsigned char IRQ_Channel;
 };
 
 /*
   Define the Probe Options.
 */
 
-struct BusLogic_ProbeOptions
-{
-  boolean NoProbe:1;					/* Bit 0 */
-  boolean NoProbeISA:1;					/* Bit 1 */
-  boolean NoProbePCI:1;					/* Bit 2 */
-  boolean NoSortPCI:1;					/* Bit 3 */
-  boolean MultiMasterFirst:1;				/* Bit 4 */
-  boolean FlashPointFirst:1;				/* Bit 5 */
-  boolean LimitedProbeISA:1;				/* Bit 6 */
-  boolean Probe330:1;					/* Bit 7 */
-  boolean Probe334:1;					/* Bit 8 */
-  boolean Probe230:1;					/* Bit 9 */
-  boolean Probe234:1;					/* Bit 10 */
-  boolean Probe130:1;					/* Bit 11 */
-  boolean Probe134:1;					/* Bit 12 */
+struct BusLogic_ProbeOptions {
+	boolean NoProbe:1;	/* Bit 0 */
+	boolean NoProbeISA:1;	/* Bit 1 */
+	boolean NoProbePCI:1;	/* Bit 2 */
+	boolean NoSortPCI:1;	/* Bit 3 */
+	boolean MultiMasterFirst:1;	/* Bit 4 */
+	boolean FlashPointFirst:1;	/* Bit 5 */
+	boolean LimitedProbeISA:1;	/* Bit 6 */
+	boolean Probe330:1;	/* Bit 7 */
+	boolean Probe334:1;	/* Bit 8 */
+	boolean Probe230:1;	/* Bit 9 */
+	boolean Probe234:1;	/* Bit 10 */
+	boolean Probe130:1;	/* Bit 11 */
+	boolean Probe134:1;	/* Bit 12 */
 };
 
 /*
   Define the Global Options.
 */
 
-struct BusLogic_GlobalOptions
-{
-  boolean TraceProbe:1;					/* Bit 0 */
-  boolean TraceHardwareReset:1;				/* Bit 1 */
-  boolean TraceConfiguration:1;				/* Bit 2 */
-  boolean TraceErrors:1;				/* Bit 3 */
+struct BusLogic_GlobalOptions {
+	boolean TraceProbe:1;	/* Bit 0 */
+	boolean TraceHardwareReset:1;	/* Bit 1 */
+	boolean TraceConfiguration:1;	/* Bit 2 */
+	boolean TraceErrors:1;	/* Bit 3 */
 };
 
 /*
   Define the Local Options.
 */
 
-struct BusLogic_LocalOptions
-{
-  boolean InhibitTargetInquiry:1;			/* Bit 0 */
+struct BusLogic_LocalOptions {
+	boolean InhibitTargetInquiry:1;	/* Bit 0 */
 };
 
 /*
@@ -335,198 +322,188 @@
   Define the structure of the write-only Control Register.
 */
 
-union BusLogic_ControlRegister
-{
-  unsigned char All;
-  struct {
-    unsigned char :4;					/* Bits 0-3 */
-    boolean SCSIBusReset:1;				/* Bit 4 */
-    boolean InterruptReset:1;				/* Bit 5 */
-    boolean SoftReset:1;				/* Bit 6 */
-    boolean HardReset:1;				/* Bit 7 */
-  } cr;
+union BusLogic_ControlRegister {
+	unsigned char All;
+	struct {
+		unsigned char:4;	/* Bits 0-3 */
+		boolean SCSIBusReset:1;	/* Bit 4 */
+		boolean InterruptReset:1;	/* Bit 5 */
+		boolean SoftReset:1;	/* Bit 6 */
+		boolean HardReset:1;	/* Bit 7 */
+	} cr;
 };
 
 /*
   Define the structure of the read-only Status Register.
 */
 
-union BusLogic_StatusRegister
-{
-  unsigned char All;
-  struct {
-    boolean CommandInvalid:1;				/* Bit 0 */
-    boolean Reserved:1;					/* Bit 1 */
-    boolean DataInRegisterReady:1;			/* Bit 2 */
-    boolean CommandParameterRegisterBusy:1;		/* Bit 3 */
-    boolean HostAdapterReady:1;				/* Bit 4 */
-    boolean InitializationRequired:1;			/* Bit 5 */
-    boolean DiagnosticFailure:1;			/* Bit 6 */
-    boolean DiagnosticActive:1;				/* Bit 7 */
-  } sr;
+union BusLogic_StatusRegister {
+	unsigned char All;
+	struct {
+		boolean CommandInvalid:1;	/* Bit 0 */
+		boolean Reserved:1;	/* Bit 1 */
+		boolean DataInRegisterReady:1;	/* Bit 2 */
+		boolean CommandParameterRegisterBusy:1;	/* Bit 3 */
+		boolean HostAdapterReady:1;	/* Bit 4 */
+		boolean InitializationRequired:1;	/* Bit 5 */
+		boolean DiagnosticFailure:1;	/* Bit 6 */
+		boolean DiagnosticActive:1;	/* Bit 7 */
+	} sr;
 };
 
 /*
   Define the structure of the read-only Interrupt Register.
 */
 
-union BusLogic_InterruptRegister
-{
-  unsigned char All;
-  struct {
-    boolean IncomingMailboxLoaded:1;			/* Bit 0 */
-    boolean OutgoingMailboxAvailable:1;			/* Bit 1 */
-    boolean CommandComplete:1;				/* Bit 2 */
-    boolean ExternalBusReset:1;				/* Bit 3 */
-    unsigned char Reserved:3;				/* Bits 4-6 */
-    boolean InterruptValid:1;				/* Bit 7 */
-  } ir;
+union BusLogic_InterruptRegister {
+	unsigned char All;
+	struct {
+		boolean IncomingMailboxLoaded:1;	/* Bit 0 */
+		boolean OutgoingMailboxAvailable:1;	/* Bit 1 */
+		boolean CommandComplete:1;	/* Bit 2 */
+		boolean ExternalBusReset:1;	/* Bit 3 */
+		unsigned char Reserved:3;	/* Bits 4-6 */
+		boolean InterruptValid:1;	/* Bit 7 */
+	} ir;
 };
 
 /*
   Define the structure of the read-only Geometry Register.
 */
 
-union BusLogic_GeometryRegister
-{
-  unsigned char All;
-  struct {
-    enum BusLogic_BIOS_DiskGeometryTranslation Drive0Geometry:2;/* Bits 0-1 */
-    enum BusLogic_BIOS_DiskGeometryTranslation Drive1Geometry:2;/* Bits 2-3 */
-    unsigned char :3;						/* Bits 4-6 */
-    boolean ExtendedTranslationEnabled:1;			/* Bit 7 */
-  } gr;
+union BusLogic_GeometryRegister {
+	unsigned char All;
+	struct {
+		enum BusLogic_BIOS_DiskGeometryTranslation Drive0Geometry:2;	/* Bits 0-1 */
+		enum BusLogic_BIOS_DiskGeometryTranslation Drive1Geometry:2;	/* Bits 2-3 */
+		unsigned char:3;	/* Bits 4-6 */
+		boolean ExtendedTranslationEnabled:1;	/* Bit 7 */
+	} gr;
 };
 
 /*
   Define the BusLogic SCSI Host Adapter Command Register Operation Codes.
 */
 
-enum BusLogic_OperationCode
-{
-  BusLogic_TestCommandCompleteInterrupt =		0x00,
-  BusLogic_InitializeMailbox =				0x01,
-  BusLogic_ExecuteMailboxCommand =			0x02,
-  BusLogic_ExecuteBIOSCommand =				0x03,
-  BusLogic_InquireBoardID =				0x04,
-  BusLogic_EnableOutgoingMailboxAvailableInt =		0x05,
-  BusLogic_SetSCSISelectionTimeout =			0x06,
-  BusLogic_SetPreemptTimeOnBus =			0x07,
-  BusLogic_SetTimeOffBus =				0x08,
-  BusLogic_SetBusTransferRate =				0x09,
-  BusLogic_InquireInstalledDevicesID0to7 =		0x0A,
-  BusLogic_InquireConfiguration =			0x0B,
-  BusLogic_EnableTargetMode =				0x0C,
-  BusLogic_InquireSetupInformation =			0x0D,
-  BusLogic_WriteAdapterLocalRAM =			0x1A,
-  BusLogic_ReadAdapterLocalRAM =			0x1B,
-  BusLogic_WriteBusMasterChipFIFO =			0x1C,
-  BusLogic_ReadBusMasterChipFIFO =			0x1D,
-  BusLogic_EchoCommandData =				0x1F,
-  BusLogic_HostAdapterDiagnostic =			0x20,
-  BusLogic_SetAdapterOptions =				0x21,
-  BusLogic_InquireInstalledDevicesID8to15 =		0x23,
-  BusLogic_InquireTargetDevices =			0x24,
-  BusLogic_DisableHostAdapterInterrupt =		0x25,
-  BusLogic_InitializeExtendedMailbox =			0x81,
-  BusLogic_ExecuteSCSICommand =				0x83,
-  BusLogic_InquireFirmwareVersion3rdDigit =		0x84,
-  BusLogic_InquireFirmwareVersionLetter =		0x85,
-  BusLogic_InquirePCIHostAdapterInformation =		0x86,
-  BusLogic_InquireHostAdapterModelNumber =		0x8B,
-  BusLogic_InquireSynchronousPeriod =			0x8C,
-  BusLogic_InquireExtendedSetupInformation =		0x8D,
-  BusLogic_EnableStrictRoundRobinMode =			0x8F,
-  BusLogic_StoreHostAdapterLocalRAM =			0x90,
-  BusLogic_FetchHostAdapterLocalRAM =			0x91,
-  BusLogic_StoreLocalDataInEEPROM =			0x92,
-  BusLogic_UploadAutoSCSICode =				0x94,
-  BusLogic_ModifyIOAddress =				0x95,
-  BusLogic_SetCCBFormat =				0x96,
-  BusLogic_WriteInquiryBuffer =				0x9A,
-  BusLogic_ReadInquiryBuffer =				0x9B,
-  BusLogic_FlashROMUploadDownload =			0xA7,
-  BusLogic_ReadSCAMData =				0xA8,
-  BusLogic_WriteSCAMData =				0xA9
+enum BusLogic_OperationCode {
+	BusLogic_TestCommandCompleteInterrupt = 0x00,
+	BusLogic_InitializeMailbox = 0x01,
+	BusLogic_ExecuteMailboxCommand = 0x02,
+	BusLogic_ExecuteBIOSCommand = 0x03,
+	BusLogic_InquireBoardID = 0x04,
+	BusLogic_EnableOutgoingMailboxAvailableInt = 0x05,
+	BusLogic_SetSCSISelectionTimeout = 0x06,
+	BusLogic_SetPreemptTimeOnBus = 0x07,
+	BusLogic_SetTimeOffBus = 0x08,
+	BusLogic_SetBusTransferRate = 0x09,
+	BusLogic_InquireInstalledDevicesID0to7 = 0x0A,
+	BusLogic_InquireConfiguration = 0x0B,
+	BusLogic_EnableTargetMode = 0x0C,
+	BusLogic_InquireSetupInformation = 0x0D,
+	BusLogic_WriteAdapterLocalRAM = 0x1A,
+	BusLogic_ReadAdapterLocalRAM = 0x1B,
+	BusLogic_WriteBusMasterChipFIFO = 0x1C,
+	BusLogic_ReadBusMasterChipFIFO = 0x1D,
+	BusLogic_EchoCommandData = 0x1F,
+	BusLogic_HostAdapterDiagnostic = 0x20,
+	BusLogic_SetAdapterOptions = 0x21,
+	BusLogic_InquireInstalledDevicesID8to15 = 0x23,
+	BusLogic_InquireTargetDevices = 0x24,
+	BusLogic_DisableHostAdapterInterrupt = 0x25,
+	BusLogic_InitializeExtendedMailbox = 0x81,
+	BusLogic_ExecuteSCSICommand = 0x83,
+	BusLogic_InquireFirmwareVersion3rdDigit = 0x84,
+	BusLogic_InquireFirmwareVersionLetter = 0x85,
+	BusLogic_InquirePCIHostAdapterInformation = 0x86,
+	BusLogic_InquireHostAdapterModelNumber = 0x8B,
+	BusLogic_InquireSynchronousPeriod = 0x8C,
+	BusLogic_InquireExtendedSetupInformation = 0x8D,
+	BusLogic_EnableStrictRoundRobinMode = 0x8F,
+	BusLogic_StoreHostAdapterLocalRAM = 0x90,
+	BusLogic_FetchHostAdapterLocalRAM = 0x91,
+	BusLogic_StoreLocalDataInEEPROM = 0x92,
+	BusLogic_UploadAutoSCSICode = 0x94,
+	BusLogic_ModifyIOAddress = 0x95,
+	BusLogic_SetCCBFormat = 0x96,
+	BusLogic_WriteInquiryBuffer = 0x9A,
+	BusLogic_ReadInquiryBuffer = 0x9B,
+	BusLogic_FlashROMUploadDownload = 0xA7,
+	BusLogic_ReadSCAMData = 0xA8,
+	BusLogic_WriteSCAMData = 0xA9
 };
 
 /*
   Define the Inquire Board ID reply structure.
 */
 
-struct BusLogic_BoardID
-{
-  unsigned char BoardType;				/* Byte 0 */
-  unsigned char CustomFeatures;				/* Byte 1 */
-  unsigned char FirmwareVersion1stDigit;		/* Byte 2 */
-  unsigned char FirmwareVersion2ndDigit;		/* Byte 3 */
+struct BusLogic_BoardID {
+	unsigned char BoardType;	/* Byte 0 */
+	unsigned char CustomFeatures;	/* Byte 1 */
+	unsigned char FirmwareVersion1stDigit;	/* Byte 2 */
+	unsigned char FirmwareVersion2ndDigit;	/* Byte 3 */
 };
 
 /*
   Define the Inquire Configuration reply structure.
 */
 
-struct BusLogic_Configuration
-{
-  unsigned char :5;					/* Byte 0 Bits 0-4 */
-  boolean DMA_Channel5:1;				/* Byte 0 Bit 5 */
-  boolean DMA_Channel6:1;				/* Byte 0 Bit 6 */
-  boolean DMA_Channel7:1;				/* Byte 0 Bit 7 */
-  boolean IRQ_Channel9:1;				/* Byte 1 Bit 0 */
-  boolean IRQ_Channel10:1;				/* Byte 1 Bit 1 */
-  boolean IRQ_Channel11:1;				/* Byte 1 Bit 2 */
-  boolean IRQ_Channel12:1;				/* Byte 1 Bit 3 */
-  unsigned char :1;					/* Byte 1 Bit 4 */
-  boolean IRQ_Channel14:1;				/* Byte 1 Bit 5 */
-  boolean IRQ_Channel15:1;				/* Byte 1 Bit 6 */
-  unsigned char :1;					/* Byte 1 Bit 7 */
-  unsigned char HostAdapterID:4;			/* Byte 2 Bits 0-3 */
-  unsigned char :4;					/* Byte 2 Bits 4-7 */
+struct BusLogic_Configuration {
+	unsigned char:5;	/* Byte 0 Bits 0-4 */
+	boolean DMA_Channel5:1;	/* Byte 0 Bit 5 */
+	boolean DMA_Channel6:1;	/* Byte 0 Bit 6 */
+	boolean DMA_Channel7:1;	/* Byte 0 Bit 7 */
+	boolean IRQ_Channel9:1;	/* Byte 1 Bit 0 */
+	boolean IRQ_Channel10:1;	/* Byte 1 Bit 1 */
+	boolean IRQ_Channel11:1;	/* Byte 1 Bit 2 */
+	boolean IRQ_Channel12:1;	/* Byte 1 Bit 3 */
+	unsigned char:1;	/* Byte 1 Bit 4 */
+	boolean IRQ_Channel14:1;	/* Byte 1 Bit 5 */
+	boolean IRQ_Channel15:1;	/* Byte 1 Bit 6 */
+	unsigned char:1;	/* Byte 1 Bit 7 */
+	unsigned char HostAdapterID:4;	/* Byte 2 Bits 0-3 */
+	unsigned char:4;	/* Byte 2 Bits 4-7 */
 };
 
 /*
   Define the Inquire Setup Information reply structure.
 */
 
-struct BusLogic_SynchronousValue
-{
-  unsigned char Offset:4;				/* Bits 0-3 */
-  unsigned char TransferPeriod:3;			/* Bits 4-6 */
-  boolean Synchronous:1;				/* Bit 7 */
-};
-
-struct BusLogic_SetupInformation
-{
-  boolean SynchronousInitiationEnabled:1;		/* Byte 0 Bit 0 */
-  boolean ParityCheckingEnabled:1;			/* Byte 0 Bit 1 */
-  unsigned char :6;					/* Byte 0 Bits 2-7 */
-  unsigned char BusTransferRate;			/* Byte 1 */
-  unsigned char PreemptTimeOnBus;			/* Byte 2 */
-  unsigned char TimeOffBus;				/* Byte 3 */
-  unsigned char MailboxCount;				/* Byte 4 */
-  unsigned char MailboxAddress[3];			/* Bytes 5-7 */
-  struct BusLogic_SynchronousValue SynchronousValuesID0to7[8];/* Bytes 8-15 */
-  unsigned char DisconnectPermittedID0to7;		/* Byte 16 */
-  unsigned char Signature;				/* Byte 17 */
-  unsigned char CharacterD;				/* Byte 18 */
-  unsigned char HostBusType;				/* Byte 19 */
-  unsigned char WideTransfersPermittedID0to7;		/* Byte 20 */
-  unsigned char WideTransfersActiveID0to7;		/* Byte 21 */
-  struct BusLogic_SynchronousValue SynchronousValuesID8to15[8]; /* Bytes 22-29 */
-  unsigned char DisconnectPermittedID8to15;		/* Byte 30 */
-  unsigned char :8;					/* Byte 31 */
-  unsigned char WideTransfersPermittedID8to15;		/* Byte 32 */
-  unsigned char WideTransfersActiveID8to15;		/* Byte 33 */
+struct BusLogic_SynchronousValue {
+	unsigned char Offset:4;	/* Bits 0-3 */
+	unsigned char TransferPeriod:3;	/* Bits 4-6 */
+	boolean Synchronous:1;	/* Bit 7 */
+};
+
+struct BusLogic_SetupInformation {
+	boolean SynchronousInitiationEnabled:1;	/* Byte 0 Bit 0 */
+	boolean ParityCheckingEnabled:1;	/* Byte 0 Bit 1 */
+	unsigned char:6;	/* Byte 0 Bits 2-7 */
+	unsigned char BusTransferRate;	/* Byte 1 */
+	unsigned char PreemptTimeOnBus;	/* Byte 2 */
+	unsigned char TimeOffBus;	/* Byte 3 */
+	unsigned char MailboxCount;	/* Byte 4 */
+	unsigned char MailboxAddress[3];	/* Bytes 5-7 */
+	struct BusLogic_SynchronousValue SynchronousValuesID0to7[8];	/* Bytes 8-15 */
+	unsigned char DisconnectPermittedID0to7;	/* Byte 16 */
+	unsigned char Signature;	/* Byte 17 */
+	unsigned char CharacterD;	/* Byte 18 */
+	unsigned char HostBusType;	/* Byte 19 */
+	unsigned char WideTransfersPermittedID0to7;	/* Byte 20 */
+	unsigned char WideTransfersActiveID0to7;	/* Byte 21 */
+	struct BusLogic_SynchronousValue SynchronousValuesID8to15[8];	/* Bytes 22-29 */
+	unsigned char DisconnectPermittedID8to15;	/* Byte 30 */
+	unsigned char:8;	/* Byte 31 */
+	unsigned char WideTransfersPermittedID8to15;	/* Byte 32 */
+	unsigned char WideTransfersActiveID8to15;	/* Byte 33 */
 };
 
 /*
   Define the Initialize Extended Mailbox request structure.
 */
 
-struct BusLogic_ExtendedMailboxRequest
-{
-  unsigned char MailboxCount;				/* Byte 0 */
-  u32 BaseMailboxAddress;				/* Bytes 1-4 */
+struct BusLogic_ExtendedMailboxRequest {
+	unsigned char MailboxCount;	/* Byte 0 */
+	u32 BaseMailboxAddress;	/* Bytes 1-4 */
 } PACKED;
 
 
@@ -536,67 +513,63 @@
   the Modify I/O Address command.
 */
 
-enum BusLogic_ISACompatibleIOPort
-{
-  BusLogic_IO_330 =				0,
-  BusLogic_IO_334 =				1,
-  BusLogic_IO_230 =				2,
-  BusLogic_IO_234 =				3,
-  BusLogic_IO_130 =				4,
-  BusLogic_IO_134 =				5,
-  BusLogic_IO_Disable =				6,
-  BusLogic_IO_Disable2 =			7
+enum BusLogic_ISACompatibleIOPort {
+	BusLogic_IO_330 = 0,
+	BusLogic_IO_334 = 1,
+	BusLogic_IO_230 = 2,
+	BusLogic_IO_234 = 3,
+	BusLogic_IO_130 = 4,
+	BusLogic_IO_134 = 5,
+	BusLogic_IO_Disable = 6,
+	BusLogic_IO_Disable2 = 7
 } PACKED;
 
-struct BusLogic_PCIHostAdapterInformation
-{
-  enum BusLogic_ISACompatibleIOPort ISACompatibleIOPort;/* Byte 0 */
-  unsigned char PCIAssignedIRQChannel;			/* Byte 1 */
-  boolean LowByteTerminated:1;				/* Byte 2 Bit 0 */
-  boolean HighByteTerminated:1;				/* Byte 2 Bit 1 */
-  unsigned char :2;					/* Byte 2 Bits 2-3 */
-  boolean JP1:1;					/* Byte 2 Bit 4 */
-  boolean JP2:1;					/* Byte 2 Bit 5 */
-  boolean JP3:1;					/* Byte 2 Bit 6 */
-  boolean GenericInfoValid:1;				/* Byte 2 Bit 7 */
-  unsigned char :8;					/* Byte 3 */
+struct BusLogic_PCIHostAdapterInformation {
+	enum BusLogic_ISACompatibleIOPort ISACompatibleIOPort;	/* Byte 0 */
+	unsigned char PCIAssignedIRQChannel;	/* Byte 1 */
+	boolean LowByteTerminated:1;	/* Byte 2 Bit 0 */
+	boolean HighByteTerminated:1;	/* Byte 2 Bit 1 */
+	unsigned char:2;	/* Byte 2 Bits 2-3 */
+	boolean JP1:1;		/* Byte 2 Bit 4 */
+	boolean JP2:1;		/* Byte 2 Bit 5 */
+	boolean JP3:1;		/* Byte 2 Bit 6 */
+	boolean GenericInfoValid:1;	/* Byte 2 Bit 7 */
+	unsigned char:8;	/* Byte 3 */
 };
 
 /*
   Define the Inquire Extended Setup Information reply structure.
 */
 
-struct BusLogic_ExtendedSetupInformation
-{
-  unsigned char BusType;				/* Byte 0 */
-  unsigned char BIOS_Address;				/* Byte 1 */
-  unsigned short ScatterGatherLimit;			/* Bytes 2-3 */
-  unsigned char MailboxCount;				/* Byte 4 */
-  u32 BaseMailboxAddress;				/* Bytes 5-8 */
-  struct {
-           unsigned char :2;				/* Byte 9 Bits 0-1 */
-	   boolean FastOnEISA:1;			/* Byte 9 Bit 2 */
-	   unsigned char :3;				/* Byte 9 Bits 3-5 */
-	   boolean LevelSensitiveInterrupt:1;		/* Byte 9 Bit 6 */
-	   unsigned char :1;				/* Byte 9 Bit 7 */
-  } Misc;
-  unsigned char FirmwareRevision[3];			/* Bytes 10-12 */
-  boolean HostWideSCSI:1;				/* Byte 13 Bit 0 */
-  boolean HostDifferentialSCSI:1;			/* Byte 13 Bit 1 */
-  boolean HostSupportsSCAM:1;				/* Byte 13 Bit 2 */
-  boolean HostUltraSCSI:1;				/* Byte 13 Bit 3 */
-  boolean HostSmartTermination:1;			/* Byte 13 Bit 4 */
-  unsigned char :3;					/* Byte 13 Bits 5-7 */
+struct BusLogic_ExtendedSetupInformation {
+	unsigned char BusType;	/* Byte 0 */
+	unsigned char BIOS_Address;	/* Byte 1 */
+	unsigned short ScatterGatherLimit;	/* Bytes 2-3 */
+	unsigned char MailboxCount;	/* Byte 4 */
+	u32 BaseMailboxAddress;	/* Bytes 5-8 */
+	struct {
+		unsigned char:2;	/* Byte 9 Bits 0-1 */
+		boolean FastOnEISA:1;	/* Byte 9 Bit 2 */
+		unsigned char:3;	/* Byte 9 Bits 3-5 */
+		boolean LevelSensitiveInterrupt:1;	/* Byte 9 Bit 6 */
+		unsigned char:1;	/* Byte 9 Bit 7 */
+	} Misc;
+	unsigned char FirmwareRevision[3];	/* Bytes 10-12 */
+	boolean HostWideSCSI:1;	/* Byte 13 Bit 0 */
+	boolean HostDifferentialSCSI:1;	/* Byte 13 Bit 1 */
+	boolean HostSupportsSCAM:1;	/* Byte 13 Bit 2 */
+	boolean HostUltraSCSI:1;	/* Byte 13 Bit 3 */
+	boolean HostSmartTermination:1;	/* Byte 13 Bit 4 */
+	unsigned char:3;	/* Byte 13 Bits 5-7 */
 } PACKED;
 
 /*
   Define the Enable Strict Round Robin Mode request type.
 */
 
-enum BusLogic_RoundRobinModeRequest
-{
-  BusLogic_AggressiveRoundRobinMode =		0,
-  BusLogic_StrictRoundRobinMode =		1
+enum BusLogic_RoundRobinModeRequest {
+	BusLogic_AggressiveRoundRobinMode = 0,
+	BusLogic_StrictRoundRobinMode = 1
 } PACKED;
 
 
@@ -607,96 +580,93 @@
 #define BusLogic_BIOS_BaseOffset		0
 #define BusLogic_AutoSCSI_BaseOffset		64
 
-struct BusLogic_FetchHostAdapterLocalRAMRequest
-{
-  unsigned char ByteOffset;				/* Byte 0 */
-  unsigned char ByteCount;				/* Byte 1 */
+struct BusLogic_FetchHostAdapterLocalRAMRequest {
+	unsigned char ByteOffset;	/* Byte 0 */
+	unsigned char ByteCount;	/* Byte 1 */
 };
 
 /*
   Define the Host Adapter Local RAM AutoSCSI structure.
 */
 
-struct BusLogic_AutoSCSIData
-{
-  unsigned char InternalFactorySignature[2];		/* Bytes 0-1 */
-  unsigned char InformationByteCount;			/* Byte 2 */
-  unsigned char HostAdapterType[6];			/* Bytes 3-8 */
-  unsigned char :8;					/* Byte 9 */
-  boolean FloppyEnabled:1;				/* Byte 10 Bit 0 */
-  boolean FloppySecondary:1;				/* Byte 10 Bit 1 */
-  boolean LevelSensitiveInterrupt:1;			/* Byte 10 Bit 2 */
-  unsigned char :2;					/* Byte 10 Bits 3-4 */
-  unsigned char SystemRAMAreaForBIOS:3;			/* Byte 10 Bits 5-7 */
-  unsigned char DMA_Channel:7;				/* Byte 11 Bits 0-6 */
-  boolean DMA_AutoConfiguration:1;			/* Byte 11 Bit 7 */
-  unsigned char IRQ_Channel:7;				/* Byte 12 Bits 0-6 */
-  boolean IRQ_AutoConfiguration:1;			/* Byte 12 Bit 7 */
-  unsigned char DMA_TransferRate;			/* Byte 13 */
-  unsigned char SCSI_ID;				/* Byte 14 */
-  boolean LowByteTerminated:1;				/* Byte 15 Bit 0 */
-  boolean ParityCheckingEnabled:1;			/* Byte 15 Bit 1 */
-  boolean HighByteTerminated:1;				/* Byte 15 Bit 2 */
-  boolean NoisyCablingEnvironment:1;			/* Byte 15 Bit 3 */
-  boolean FastSynchronousNegotiation:1;			/* Byte 15 Bit 4 */
-  boolean BusResetEnabled:1;				/* Byte 15 Bit 5 */
-  boolean :1;						/* Byte 15 Bit 6 */
-  boolean ActiveNegationEnabled:1;			/* Byte 15 Bit 7 */
-  unsigned char BusOnDelay;				/* Byte 16 */
-  unsigned char BusOffDelay;				/* Byte 17 */
-  boolean HostAdapterBIOSEnabled:1;			/* Byte 18 Bit 0 */
-  boolean BIOSRedirectionOfINT19Enabled:1;		/* Byte 18 Bit 1 */
-  boolean ExtendedTranslationEnabled:1;			/* Byte 18 Bit 2 */
-  boolean MapRemovableAsFixedEnabled:1;			/* Byte 18 Bit 3 */
-  boolean :1;						/* Byte 18 Bit 4 */
-  boolean BIOSSupportsMoreThan2DrivesEnabled:1;		/* Byte 18 Bit 5 */
-  boolean BIOSInterruptModeEnabled:1;			/* Byte 18 Bit 6 */
-  boolean FlopticalSupportEnabled:1;			/* Byte 19 Bit 7 */
-  unsigned short DeviceEnabled;				/* Bytes 19-20 */
-  unsigned short WidePermitted;				/* Bytes 21-22 */
-  unsigned short FastPermitted;				/* Bytes 23-24 */
-  unsigned short SynchronousPermitted;			/* Bytes 25-26 */
-  unsigned short DisconnectPermitted;			/* Bytes 27-28 */
-  unsigned short SendStartUnitCommand;			/* Bytes 29-30 */
-  unsigned short IgnoreInBIOSScan;			/* Bytes 31-32 */
-  unsigned char PCIInterruptPin:2;			/* Byte 33 Bits 0-1 */
-  unsigned char HostAdapterIOPortAddress:2;		/* Byte 33 Bits 2-3 */
-  boolean StrictRoundRobinModeEnabled:1;		/* Byte 33 Bit 4 */
-  boolean VESABusSpeedGreaterThan33MHz:1;		/* Byte 33 Bit 5 */
-  boolean VESABurstWriteEnabled:1;			/* Byte 33 Bit 6 */
-  boolean VESABurstReadEnabled:1;			/* Byte 33 Bit 7 */
-  unsigned short UltraPermitted;			/* Bytes 34-35 */
-  unsigned int :32;					/* Bytes 36-39 */
-  unsigned char :8;					/* Byte 40 */
-  unsigned char AutoSCSIMaximumLUN;			/* Byte 41 */
-  boolean :1;						/* Byte 42 Bit 0 */
-  boolean SCAM_Dominant:1;				/* Byte 42 Bit 1 */
-  boolean SCAM_Enabled:1;				/* Byte 42 Bit 2 */
-  boolean SCAM_Level2:1;				/* Byte 42 Bit 3 */
-  unsigned char :4;					/* Byte 42 Bits 4-7 */
-  boolean INT13ExtensionEnabled:1;			/* Byte 43 Bit 0 */
-  boolean :1;						/* Byte 43 Bit 1 */
-  boolean CDROMBootEnabled:1;				/* Byte 43 Bit 2 */
-  unsigned char :5;					/* Byte 43 Bits 3-7 */
-  unsigned char BootTargetID:4;				/* Byte 44 Bits 0-3 */
-  unsigned char BootChannel:4;				/* Byte 44 Bits 4-7 */
-  unsigned char ForceBusDeviceScanningOrder:1;		/* Byte 45 Bit 0 */
-  unsigned char :7;					/* Byte 45 Bits 1-7 */
-  unsigned short NonTaggedToAlternateLUNPermitted;	/* Bytes 46-47 */
-  unsigned short RenegotiateSyncAfterCheckCondition;	/* Bytes 48-49 */
-  unsigned char Reserved[10];				/* Bytes 50-59 */
-  unsigned char ManufacturingDiagnostic[2];		/* Bytes 60-61 */
-  unsigned short Checksum;				/* Bytes 62-63 */
+struct BusLogic_AutoSCSIData {
+	unsigned char InternalFactorySignature[2];	/* Bytes 0-1 */
+	unsigned char InformationByteCount;	/* Byte 2 */
+	unsigned char HostAdapterType[6];	/* Bytes 3-8 */
+	unsigned char:8;	/* Byte 9 */
+	boolean FloppyEnabled:1;	/* Byte 10 Bit 0 */
+	boolean FloppySecondary:1;	/* Byte 10 Bit 1 */
+	boolean LevelSensitiveInterrupt:1;	/* Byte 10 Bit 2 */
+	unsigned char:2;	/* Byte 10 Bits 3-4 */
+	unsigned char SystemRAMAreaForBIOS:3;	/* Byte 10 Bits 5-7 */
+	unsigned char DMA_Channel:7;	/* Byte 11 Bits 0-6 */
+	boolean DMA_AutoConfiguration:1;	/* Byte 11 Bit 7 */
+	unsigned char IRQ_Channel:7;	/* Byte 12 Bits 0-6 */
+	boolean IRQ_AutoConfiguration:1;	/* Byte 12 Bit 7 */
+	unsigned char DMA_TransferRate;	/* Byte 13 */
+	unsigned char SCSI_ID;	/* Byte 14 */
+	boolean LowByteTerminated:1;	/* Byte 15 Bit 0 */
+	boolean ParityCheckingEnabled:1;	/* Byte 15 Bit 1 */
+	boolean HighByteTerminated:1;	/* Byte 15 Bit 2 */
+	boolean NoisyCablingEnvironment:1;	/* Byte 15 Bit 3 */
+	boolean FastSynchronousNegotiation:1;	/* Byte 15 Bit 4 */
+	boolean BusResetEnabled:1;	/* Byte 15 Bit 5 */
+	 boolean:1;		/* Byte 15 Bit 6 */
+	boolean ActiveNegationEnabled:1;	/* Byte 15 Bit 7 */
+	unsigned char BusOnDelay;	/* Byte 16 */
+	unsigned char BusOffDelay;	/* Byte 17 */
+	boolean HostAdapterBIOSEnabled:1;	/* Byte 18 Bit 0 */
+	boolean BIOSRedirectionOfINT19Enabled:1;	/* Byte 18 Bit 1 */
+	boolean ExtendedTranslationEnabled:1;	/* Byte 18 Bit 2 */
+	boolean MapRemovableAsFixedEnabled:1;	/* Byte 18 Bit 3 */
+	 boolean:1;		/* Byte 18 Bit 4 */
+	boolean BIOSSupportsMoreThan2DrivesEnabled:1;	/* Byte 18 Bit 5 */
+	boolean BIOSInterruptModeEnabled:1;	/* Byte 18 Bit 6 */
+	boolean FlopticalSupportEnabled:1;	/* Byte 19 Bit 7 */
+	unsigned short DeviceEnabled;	/* Bytes 19-20 */
+	unsigned short WidePermitted;	/* Bytes 21-22 */
+	unsigned short FastPermitted;	/* Bytes 23-24 */
+	unsigned short SynchronousPermitted;	/* Bytes 25-26 */
+	unsigned short DisconnectPermitted;	/* Bytes 27-28 */
+	unsigned short SendStartUnitCommand;	/* Bytes 29-30 */
+	unsigned short IgnoreInBIOSScan;	/* Bytes 31-32 */
+	unsigned char PCIInterruptPin:2;	/* Byte 33 Bits 0-1 */
+	unsigned char HostAdapterIOPortAddress:2;	/* Byte 33 Bits 2-3 */
+	boolean StrictRoundRobinModeEnabled:1;	/* Byte 33 Bit 4 */
+	boolean VESABusSpeedGreaterThan33MHz:1;	/* Byte 33 Bit 5 */
+	boolean VESABurstWriteEnabled:1;	/* Byte 33 Bit 6 */
+	boolean VESABurstReadEnabled:1;	/* Byte 33 Bit 7 */
+	unsigned short UltraPermitted;	/* Bytes 34-35 */
+	unsigned int:32;	/* Bytes 36-39 */
+	unsigned char:8;	/* Byte 40 */
+	unsigned char AutoSCSIMaximumLUN;	/* Byte 41 */
+	 boolean:1;		/* Byte 42 Bit 0 */
+	boolean SCAM_Dominant:1;	/* Byte 42 Bit 1 */
+	boolean SCAM_Enabled:1;	/* Byte 42 Bit 2 */
+	boolean SCAM_Level2:1;	/* Byte 42 Bit 3 */
+	unsigned char:4;	/* Byte 42 Bits 4-7 */
+	boolean INT13ExtensionEnabled:1;	/* Byte 43 Bit 0 */
+	 boolean:1;		/* Byte 43 Bit 1 */
+	boolean CDROMBootEnabled:1;	/* Byte 43 Bit 2 */
+	unsigned char:5;	/* Byte 43 Bits 3-7 */
+	unsigned char BootTargetID:4;	/* Byte 44 Bits 0-3 */
+	unsigned char BootChannel:4;	/* Byte 44 Bits 4-7 */
+	unsigned char ForceBusDeviceScanningOrder:1;	/* Byte 45 Bit 0 */
+	unsigned char:7;	/* Byte 45 Bits 1-7 */
+	unsigned short NonTaggedToAlternateLUNPermitted;	/* Bytes 46-47 */
+	unsigned short RenegotiateSyncAfterCheckCondition;	/* Bytes 48-49 */
+	unsigned char Reserved[10];	/* Bytes 50-59 */
+	unsigned char ManufacturingDiagnostic[2];	/* Bytes 60-61 */
+	unsigned short Checksum;	/* Bytes 62-63 */
 } PACKED;
 
 /*
   Define the Host Adapter Local RAM Auto SCSI Byte 45 structure.
 */
 
-struct BusLogic_AutoSCSIByte45
-{
-  unsigned char ForceBusDeviceScanningOrder:1;		/* Bit 0 */
-  unsigned char :7;					/* Bits 1-7 */
+struct BusLogic_AutoSCSIByte45 {
+	unsigned char ForceBusDeviceScanningOrder:1;	/* Bit 0 */
+	unsigned char:7;	/* Bits 1-7 */
 };
 
 /*
@@ -705,12 +675,11 @@
 
 #define BusLogic_BIOS_DriveMapOffset		17
 
-struct BusLogic_BIOSDriveMapByte
-{
-  unsigned char TargetIDBit3:1;				/* Bit 0 */
-  unsigned char :2;					/* Bits 1-2 */
-  enum BusLogic_BIOS_DiskGeometryTranslation DiskGeometry:2; /* Bits 3-4 */
-  unsigned char TargetID:3;				/* Bits 5-7 */
+struct BusLogic_BIOSDriveMapByte {
+	unsigned char TargetIDBit3:1;	/* Bit 0 */
+	unsigned char:2;	/* Bits 1-2 */
+	enum BusLogic_BIOS_DiskGeometryTranslation DiskGeometry:2;	/* Bits 3-4 */
+	unsigned char TargetID:3;	/* Bits 5-7 */
 };
 
 /*
@@ -718,21 +687,19 @@
   necessary to support more than 8 Logical Units per Target Device.
 */
 
-enum BusLogic_SetCCBFormatRequest
-{
-  BusLogic_LegacyLUNFormatCCB =			0,
-  BusLogic_ExtendedLUNFormatCCB =		1
+enum BusLogic_SetCCBFormatRequest {
+	BusLogic_LegacyLUNFormatCCB = 0,
+	BusLogic_ExtendedLUNFormatCCB = 1
 } PACKED;
 
 /*
   Define the Outgoing Mailbox Action Codes.
 */
 
-enum BusLogic_ActionCode
-{
-  BusLogic_OutgoingMailboxFree =		0x00,
-  BusLogic_MailboxStartCommand =		0x01,
-  BusLogic_MailboxAbortCommand =		0x02
+enum BusLogic_ActionCode {
+	BusLogic_OutgoingMailboxFree = 0x00,
+	BusLogic_MailboxStartCommand = 0x01,
+	BusLogic_MailboxAbortCommand = 0x02
 } PACKED;
 
 
@@ -742,28 +709,26 @@
   completion codes are stored in the CCB; it only uses codes 1, 2, 4, and 5.
 */
 
-enum BusLogic_CompletionCode
-{
-  BusLogic_IncomingMailboxFree =		0x00,
-  BusLogic_CommandCompletedWithoutError =	0x01,
-  BusLogic_CommandAbortedAtHostRequest =	0x02,
-  BusLogic_AbortedCommandNotFound =		0x03,
-  BusLogic_CommandCompletedWithError =		0x04,
-  BusLogic_InvalidCCB =				0x05
+enum BusLogic_CompletionCode {
+	BusLogic_IncomingMailboxFree = 0x00,
+	BusLogic_CommandCompletedWithoutError = 0x01,
+	BusLogic_CommandAbortedAtHostRequest = 0x02,
+	BusLogic_AbortedCommandNotFound = 0x03,
+	BusLogic_CommandCompletedWithError = 0x04,
+	BusLogic_InvalidCCB = 0x05
 } PACKED;
 
 /*
   Define the Command Control Block (CCB) Opcodes.
 */
 
-enum BusLogic_CCB_Opcode
-{
-  BusLogic_InitiatorCCB =			0x00,
-  BusLogic_TargetCCB =				0x01,
-  BusLogic_InitiatorCCB_ScatterGather =		0x02,
-  BusLogic_InitiatorCCB_ResidualDataLength =	0x03,
-  BusLogic_InitiatorCCB_ScatterGatherResidual =	0x04,
-  BusLogic_BusDeviceReset =			0x81
+enum BusLogic_CCB_Opcode {
+	BusLogic_InitiatorCCB = 0x00,
+	BusLogic_TargetCCB = 0x01,
+	BusLogic_InitiatorCCB_ScatterGather = 0x02,
+	BusLogic_InitiatorCCB_ResidualDataLength = 0x03,
+	BusLogic_InitiatorCCB_ScatterGatherResidual = 0x04,
+	BusLogic_BusDeviceReset = 0x81
 } PACKED;
 
 
@@ -771,12 +736,11 @@
   Define the CCB Data Direction Codes.
 */
 
-enum BusLogic_DataDirection
-{
-  BusLogic_UncheckedDataTransfer =		0,
-  BusLogic_DataInLengthChecked =		1,
-  BusLogic_DataOutLengthChecked =		2,
-  BusLogic_NoDataTransfer =			3
+enum BusLogic_DataDirection {
+	BusLogic_UncheckedDataTransfer = 0,
+	BusLogic_DataInLengthChecked = 1,
+	BusLogic_DataOutLengthChecked = 2,
+	BusLogic_NoDataTransfer = 3
 };
 
 
@@ -785,33 +749,32 @@
   return status code 0x0C; it uses 0x12 for both overruns and underruns.
 */
 
-enum BusLogic_HostAdapterStatus
-{
-  BusLogic_CommandCompletedNormally =		0x00,
-  BusLogic_LinkedCommandCompleted =		0x0A,
-  BusLogic_LinkedCommandCompletedWithFlag =	0x0B,
-  BusLogic_DataUnderRun =			0x0C,
-  BusLogic_SCSISelectionTimeout =		0x11,
-  BusLogic_DataOverRun =			0x12,
-  BusLogic_UnexpectedBusFree =			0x13,
-  BusLogic_InvalidBusPhaseRequested =		0x14,
-  BusLogic_InvalidOutgoingMailboxActionCode =	0x15,
-  BusLogic_InvalidCommandOperationCode =	0x16,
-  BusLogic_LinkedCCBhasInvalidLUN =		0x17,
-  BusLogic_InvalidCommandParameter =		0x1A,
-  BusLogic_AutoRequestSenseFailed =		0x1B,
-  BusLogic_TaggedQueuingMessageRejected =	0x1C,
-  BusLogic_UnsupportedMessageReceived =		0x1D,
-  BusLogic_HostAdapterHardwareFailed =		0x20,
-  BusLogic_TargetFailedResponseToATN =		0x21,
-  BusLogic_HostAdapterAssertedRST =		0x22,
-  BusLogic_OtherDeviceAssertedRST =		0x23,
-  BusLogic_TargetDeviceReconnectedImproperly =	0x24,
-  BusLogic_HostAdapterAssertedBusDeviceReset =	0x25,
-  BusLogic_AbortQueueGenerated =		0x26,
-  BusLogic_HostAdapterSoftwareError =		0x27,
-  BusLogic_HostAdapterHardwareTimeoutError =	0x30,
-  BusLogic_SCSIParityErrorDetected =		0x34
+enum BusLogic_HostAdapterStatus {
+	BusLogic_CommandCompletedNormally = 0x00,
+	BusLogic_LinkedCommandCompleted = 0x0A,
+	BusLogic_LinkedCommandCompletedWithFlag = 0x0B,
+	BusLogic_DataUnderRun = 0x0C,
+	BusLogic_SCSISelectionTimeout = 0x11,
+	BusLogic_DataOverRun = 0x12,
+	BusLogic_UnexpectedBusFree = 0x13,
+	BusLogic_InvalidBusPhaseRequested = 0x14,
+	BusLogic_InvalidOutgoingMailboxActionCode = 0x15,
+	BusLogic_InvalidCommandOperationCode = 0x16,
+	BusLogic_LinkedCCBhasInvalidLUN = 0x17,
+	BusLogic_InvalidCommandParameter = 0x1A,
+	BusLogic_AutoRequestSenseFailed = 0x1B,
+	BusLogic_TaggedQueuingMessageRejected = 0x1C,
+	BusLogic_UnsupportedMessageReceived = 0x1D,
+	BusLogic_HostAdapterHardwareFailed = 0x20,
+	BusLogic_TargetFailedResponseToATN = 0x21,
+	BusLogic_HostAdapterAssertedRST = 0x22,
+	BusLogic_OtherDeviceAssertedRST = 0x23,
+	BusLogic_TargetDeviceReconnectedImproperly = 0x24,
+	BusLogic_HostAdapterAssertedBusDeviceReset = 0x25,
+	BusLogic_AbortQueueGenerated = 0x26,
+	BusLogic_HostAdapterSoftwareError = 0x27,
+	BusLogic_HostAdapterHardwareTimeoutError = 0x30,
+	BusLogic_SCSIParityErrorDetected = 0x34
 } PACKED;
 
 
@@ -819,23 +782,21 @@
   Define the SCSI Target Device Status Codes.
 */
 
-enum BusLogic_TargetDeviceStatus
-{
-  BusLogic_OperationGood =			0x00,
-  BusLogic_CheckCondition =			0x02,
-  BusLogic_DeviceBusy =				0x08
+enum BusLogic_TargetDeviceStatus {
+	BusLogic_OperationGood = 0x00,
+	BusLogic_CheckCondition = 0x02,
+	BusLogic_DeviceBusy = 0x08
 } PACKED;
 
 /*
   Define the Queue Tag Codes.
 */
 
-enum BusLogic_QueueTag
-{
-  BusLogic_SimpleQueueTag =			0,
-  BusLogic_HeadOfQueueTag =			1,
-  BusLogic_OrderedQueueTag =			2,
-  BusLogic_ReservedQT =				3
+enum BusLogic_QueueTag {
+	BusLogic_SimpleQueueTag = 0,
+	BusLogic_HeadOfQueueTag = 1,
+	BusLogic_OrderedQueueTag = 2,
+	BusLogic_ReservedQT = 3
 };
 
 /*
@@ -852,22 +813,20 @@
   Firmware Interface and the FlashPoint SCCB Manager.
 */
 
-struct BusLogic_ScatterGatherSegment
-{
-  u32 SegmentByteCount;					/* Bytes 0-3 */
-  u32 SegmentDataPointer;				/* Bytes 4-7 */
+struct BusLogic_ScatterGatherSegment {
+	u32 SegmentByteCount;	/* Bytes 0-3 */
+	u32 SegmentDataPointer;	/* Bytes 4-7 */
 };
 
 /*
   Define the Driver CCB Status Codes.
 */
 
-enum BusLogic_CCB_Status
-{
-  BusLogic_CCB_Free =				0,
-  BusLogic_CCB_Active =				1,
-  BusLogic_CCB_Completed =			2,
-  BusLogic_CCB_Reset =				3
+enum BusLogic_CCB_Status {
+	BusLogic_CCB_Free = 0,
+	BusLogic_CCB_Active = 1,
+	BusLogic_CCB_Completed = 2,
+	BusLogic_CCB_Reset = 3
 } PACKED;
 
 
@@ -890,82 +849,79 @@
   32 Logical Units per Target Device.
 */
 
-struct BusLogic_CCB
-{
-  /*
-    MultiMaster Firmware and FlashPoint SCCB Manager Common Portion.
-  */
-  enum BusLogic_CCB_Opcode Opcode;			/* Byte 0 */
-  unsigned char :3;					/* Byte 1 Bits 0-2 */
-  enum BusLogic_DataDirection DataDirection:2;		/* Byte 1 Bits 3-4 */
-  boolean TagEnable:1;					/* Byte 1 Bit 5 */
-  enum BusLogic_QueueTag QueueTag:2;			/* Byte 1 Bits 6-7 */
-  unsigned char CDB_Length;				/* Byte 2 */
-  unsigned char SenseDataLength;			/* Byte 3 */
-  u32 DataLength;					/* Bytes 4-7 */
-  u32 DataPointer;					/* Bytes 8-11 */
-  unsigned char :8;					/* Byte 12 */
-  unsigned char :8;					/* Byte 13 */
-  enum BusLogic_HostAdapterStatus HostAdapterStatus;	/* Byte 14 */
-  enum BusLogic_TargetDeviceStatus TargetDeviceStatus;	/* Byte 15 */
-  unsigned char TargetID;				/* Byte 16 */
-  unsigned char LogicalUnit:5;				/* Byte 17 Bits 0-4 */
-  boolean LegacyTagEnable:1;				/* Byte 17 Bit 5 */
-  enum BusLogic_QueueTag LegacyQueueTag:2;		/* Byte 17 Bits 6-7 */
-  SCSI_CDB_T CDB;					/* Bytes 18-29 */
-  unsigned char :8;					/* Byte 30 */
-  unsigned char :8;					/* Byte 31 */
-  unsigned int :32;					/* Bytes 32-35 */
-  u32 SenseDataPointer;					/* Bytes 36-39 */
-  /*
-    FlashPoint SCCB Manager Defined Portion.
-  */
-  void (*CallbackFunction)(struct BusLogic_CCB *);	/* Bytes 40-43 */
-  u32 BaseAddress;					/* Bytes 44-47 */
-  enum BusLogic_CompletionCode CompletionCode;		/* Byte 48 */
+struct BusLogic_CCB {
+	/*
+	   MultiMaster Firmware and FlashPoint SCCB Manager Common Portion.
+	 */
+	enum BusLogic_CCB_Opcode Opcode;	/* Byte 0 */
+	unsigned char:3;	/* Byte 1 Bits 0-2 */
+	enum BusLogic_DataDirection DataDirection:2;	/* Byte 1 Bits 3-4 */
+	boolean TagEnable:1;	/* Byte 1 Bit 5 */
+	enum BusLogic_QueueTag QueueTag:2;	/* Byte 1 Bits 6-7 */
+	unsigned char CDB_Length;	/* Byte 2 */
+	unsigned char SenseDataLength;	/* Byte 3 */
+	u32 DataLength;		/* Bytes 4-7 */
+	u32 DataPointer;	/* Bytes 8-11 */
+	unsigned char:8;	/* Byte 12 */
+	unsigned char:8;	/* Byte 13 */
+	enum BusLogic_HostAdapterStatus HostAdapterStatus;	/* Byte 14 */
+	enum BusLogic_TargetDeviceStatus TargetDeviceStatus;	/* Byte 15 */
+	unsigned char TargetID;	/* Byte 16 */
+	unsigned char LogicalUnit:5;	/* Byte 17 Bits 0-4 */
+	boolean LegacyTagEnable:1;	/* Byte 17 Bit 5 */
+	enum BusLogic_QueueTag LegacyQueueTag:2;	/* Byte 17 Bits 6-7 */
+	SCSI_CDB_T CDB;		/* Bytes 18-29 */
+	unsigned char:8;	/* Byte 30 */
+	unsigned char:8;	/* Byte 31 */
+	unsigned int:32;	/* Bytes 32-35 */
+	u32 SenseDataPointer;	/* Bytes 36-39 */
+	/*
+	   FlashPoint SCCB Manager Defined Portion.
+	 */
+	void (*CallbackFunction) (struct BusLogic_CCB *);	/* Bytes 40-43 */
+	u32 BaseAddress;	/* Bytes 44-47 */
+	enum BusLogic_CompletionCode CompletionCode;	/* Byte 48 */
 #ifndef CONFIG_SCSI_OMIT_FLASHPOINT
-  unsigned char :8;					/* Byte 49 */
-  unsigned short OS_Flags;				/* Bytes 50-51 */
-  unsigned char Private[48];				/* Bytes 52-99 */
+	unsigned char:8;	/* Byte 49 */
+	unsigned short OS_Flags;	/* Bytes 50-51 */
+	unsigned char Private[48];	/* Bytes 52-99 */
 #endif
-  /*
-    BusLogic Linux Driver Defined Portion.
-  */
-  dma_addr_t AllocationGroupHead;
-  unsigned int AllocationGroupSize;
-  u32 DMA_Handle;
-  enum BusLogic_CCB_Status Status;
-  unsigned long SerialNumber;
-  struct scsi_cmnd *Command;
-  struct BusLogic_HostAdapter *HostAdapter;
-  struct BusLogic_CCB *Next;
-  struct BusLogic_CCB *NextAll;
-  struct BusLogic_ScatterGatherSegment
-    ScatterGatherList[BusLogic_ScatterGatherLimit];
+	/*
+	   BusLogic Linux Driver Defined Portion.
+	 */
+	dma_addr_t AllocationGroupHead;
+	unsigned int AllocationGroupSize;
+	u32 DMA_Handle;
+	enum BusLogic_CCB_Status Status;
+	unsigned long SerialNumber;
+	struct scsi_cmnd *Command;
+	struct BusLogic_HostAdapter *HostAdapter;
+	struct BusLogic_CCB *Next;
+	struct BusLogic_CCB *NextAll;
+	struct BusLogic_ScatterGatherSegment
+	 ScatterGatherList[BusLogic_ScatterGatherLimit];
 };
 
 /*
   Define the 32 Bit Mode Outgoing Mailbox structure.
 */
 
-struct BusLogic_OutgoingMailbox
-{
-  u32 CCB;						/* Bytes 0-3 */
-  unsigned int :24;					/* Bytes 4-6 */
-  enum BusLogic_ActionCode ActionCode;			/* Byte 7 */
+struct BusLogic_OutgoingMailbox {
+	u32 CCB;		/* Bytes 0-3 */
+	unsigned int:24;	/* Bytes 4-6 */
+	enum BusLogic_ActionCode ActionCode;	/* Byte 7 */
 };
 
 /*
   Define the 32 Bit Mode Incoming Mailbox structure.
 */
 
-struct BusLogic_IncomingMailbox
-{
-  u32 CCB;						/* Bytes 0-3 */
-  enum BusLogic_HostAdapterStatus HostAdapterStatus;	/* Byte 4 */
-  enum BusLogic_TargetDeviceStatus TargetDeviceStatus;	/* Byte 5 */
-  unsigned char :8;					/* Byte 6 */
-  enum BusLogic_CompletionCode CompletionCode;		/* Byte 7 */
+struct BusLogic_IncomingMailbox {
+	u32 CCB;		/* Bytes 0-3 */
+	enum BusLogic_HostAdapterStatus HostAdapterStatus;	/* Byte 4 */
+	enum BusLogic_TargetDeviceStatus TargetDeviceStatus;	/* Byte 5 */
+	unsigned char:8;	/* Byte 6 */
+	enum BusLogic_CompletionCode CompletionCode;	/* Byte 7 */
 };
 
 
@@ -973,29 +929,27 @@
   Define the BusLogic Driver Options structure.
 */
 
-struct BusLogic_DriverOptions
-{
-  unsigned short TaggedQueuingPermitted;
-  unsigned short TaggedQueuingPermittedMask;
-  unsigned short BusSettleTime;
-  struct BusLogic_LocalOptions LocalOptions;
-  unsigned char CommonQueueDepth;
-  unsigned char QueueDepth[BusLogic_MaxTargetDevices];
+struct BusLogic_DriverOptions {
+	unsigned short TaggedQueuingPermitted;
+	unsigned short TaggedQueuingPermittedMask;
+	unsigned short BusSettleTime;
+	struct BusLogic_LocalOptions LocalOptions;
+	unsigned char CommonQueueDepth;
+	unsigned char QueueDepth[BusLogic_MaxTargetDevices];
 };
 
 /*
   Define the Host Adapter Target Flags structure.
 */
 
-struct BusLogic_TargetFlags
-{
-  boolean TargetExists:1;
-  boolean TaggedQueuingSupported:1;
-  boolean WideTransfersSupported:1;
-  boolean TaggedQueuingActive:1;
-  boolean WideTransfersActive:1;
-  boolean CommandSuccessfulFlag:1;
-  boolean TargetInfoReported:1;
+struct BusLogic_TargetFlags {
+	boolean TargetExists:1;
+	boolean TaggedQueuingSupported:1;
+	boolean WideTransfersSupported:1;
+	boolean TaggedQueuingActive:1;
+	boolean WideTransfersActive:1;
+	boolean CommandSuccessfulFlag:1;
+	boolean TargetInfoReported:1;
 };
 
 /*
@@ -1006,25 +960,24 @@
 
 typedef unsigned int BusLogic_CommandSizeBuckets_T[BusLogic_SizeBuckets];
 
-struct BusLogic_TargetStatistics
-{
-  unsigned int CommandsAttempted;
-  unsigned int CommandsCompleted;
-  unsigned int ReadCommands;
-  unsigned int WriteCommands;
-  struct BusLogic_ByteCounter TotalBytesRead;
-  struct BusLogic_ByteCounter TotalBytesWritten;
-  BusLogic_CommandSizeBuckets_T ReadCommandSizeBuckets;
-  BusLogic_CommandSizeBuckets_T WriteCommandSizeBuckets;
-  unsigned short CommandAbortsRequested;
-  unsigned short CommandAbortsAttempted;
-  unsigned short CommandAbortsCompleted;
-  unsigned short BusDeviceResetsRequested;
-  unsigned short BusDeviceResetsAttempted;
-  unsigned short BusDeviceResetsCompleted;
-  unsigned short HostAdapterResetsRequested;
-  unsigned short HostAdapterResetsAttempted;
-  unsigned short HostAdapterResetsCompleted;
+struct BusLogic_TargetStatistics {
+	unsigned int CommandsAttempted;
+	unsigned int CommandsCompleted;
+	unsigned int ReadCommands;
+	unsigned int WriteCommands;
+	struct BusLogic_ByteCounter TotalBytesRead;
+	struct BusLogic_ByteCounter TotalBytesWritten;
+	BusLogic_CommandSizeBuckets_T ReadCommandSizeBuckets;
+	BusLogic_CommandSizeBuckets_T WriteCommandSizeBuckets;
+	unsigned short CommandAbortsRequested;
+	unsigned short CommandAbortsAttempted;
+	unsigned short CommandAbortsCompleted;
+	unsigned short BusDeviceResetsRequested;
+	unsigned short BusDeviceResetsAttempted;
+	unsigned short BusDeviceResetsCompleted;
+	unsigned short HostAdapterResetsRequested;
+	unsigned short HostAdapterResetsAttempted;
+	unsigned short HostAdapterResetsCompleted;
 };
 
 /*
@@ -1041,183 +994,179 @@
   by the FlashPoint SCCB Manager.
 */
 
-struct FlashPoint_Info
-{
-  u32 BaseAddress;					/* Bytes 0-3 */
-  boolean Present;					/* Byte 4 */
-  unsigned char IRQ_Channel;				/* Byte 5 */
-  unsigned char SCSI_ID;				/* Byte 6 */
-  unsigned char SCSI_LUN;				/* Byte 7 */
-  unsigned short FirmwareRevision;			/* Bytes 8-9 */
-  unsigned short SynchronousPermitted;			/* Bytes 10-11 */
-  unsigned short FastPermitted;				/* Bytes 12-13 */
-  unsigned short UltraPermitted;			/* Bytes 14-15 */
-  unsigned short DisconnectPermitted;			/* Bytes 16-17 */
-  unsigned short WidePermitted;				/* Bytes 18-19 */
-  boolean ParityCheckingEnabled:1;			/* Byte 20 Bit 0 */
-  boolean HostWideSCSI:1;				/* Byte 20 Bit 1 */
-  boolean HostSoftReset:1;				/* Byte 20 Bit 2 */
-  boolean ExtendedTranslationEnabled:1;			/* Byte 20 Bit 3 */
-  boolean LowByteTerminated:1;				/* Byte 20 Bit 4 */
-  boolean HighByteTerminated:1;				/* Byte 20 Bit 5 */
-  boolean ReportDataUnderrun:1;				/* Byte 20 Bit 6 */
-  boolean SCAM_Enabled:1;				/* Byte 20 Bit 7 */
-  boolean SCAM_Level2:1;				/* Byte 21 Bit 0 */
-  unsigned char :7;					/* Byte 21 Bits 1-7 */
-  unsigned char Family;					/* Byte 22 */
-  unsigned char BusType;				/* Byte 23 */
-  unsigned char ModelNumber[3];				/* Bytes 24-26 */
-  unsigned char RelativeCardNumber;			/* Byte 27 */
-  unsigned char Reserved[4];				/* Bytes 28-31 */
-  unsigned int OS_Reserved;				/* Bytes 32-35 */
-  unsigned char TranslationInfo[4];			/* Bytes 36-39 */
-  unsigned int Reserved2[5];				/* Bytes 40-59 */
-  unsigned int SecondaryRange;				/* Bytes 60-63 */
+struct FlashPoint_Info {
+	u32 BaseAddress;	/* Bytes 0-3 */
+	boolean Present;	/* Byte 4 */
+	unsigned char IRQ_Channel;	/* Byte 5 */
+	unsigned char SCSI_ID;	/* Byte 6 */
+	unsigned char SCSI_LUN;	/* Byte 7 */
+	unsigned short FirmwareRevision;	/* Bytes 8-9 */
+	unsigned short SynchronousPermitted;	/* Bytes 10-11 */
+	unsigned short FastPermitted;	/* Bytes 12-13 */
+	unsigned short UltraPermitted;	/* Bytes 14-15 */
+	unsigned short DisconnectPermitted;	/* Bytes 16-17 */
+	unsigned short WidePermitted;	/* Bytes 18-19 */
+	boolean ParityCheckingEnabled:1;	/* Byte 20 Bit 0 */
+	boolean HostWideSCSI:1;	/* Byte 20 Bit 1 */
+	boolean HostSoftReset:1;	/* Byte 20 Bit 2 */
+	boolean ExtendedTranslationEnabled:1;	/* Byte 20 Bit 3 */
+	boolean LowByteTerminated:1;	/* Byte 20 Bit 4 */
+	boolean HighByteTerminated:1;	/* Byte 20 Bit 5 */
+	boolean ReportDataUnderrun:1;	/* Byte 20 Bit 6 */
+	boolean SCAM_Enabled:1;	/* Byte 20 Bit 7 */
+	boolean SCAM_Level2:1;	/* Byte 21 Bit 0 */
+	unsigned char:7;	/* Byte 21 Bits 1-7 */
+	unsigned char Family;	/* Byte 22 */
+	unsigned char BusType;	/* Byte 23 */
+	unsigned char ModelNumber[3];	/* Bytes 24-26 */
+	unsigned char RelativeCardNumber;	/* Byte 27 */
+	unsigned char Reserved[4];	/* Bytes 28-31 */
+	unsigned int OS_Reserved;	/* Bytes 32-35 */
+	unsigned char TranslationInfo[4];	/* Bytes 36-39 */
+	unsigned int Reserved2[5];	/* Bytes 40-59 */
+	unsigned int SecondaryRange;	/* Bytes 60-63 */
 };
 
 /*
   Define the BusLogic Driver Host Adapter structure.
 */
 
-struct BusLogic_HostAdapter
-{
-  struct Scsi_Host *SCSI_Host;
-  struct pci_dev *PCI_Device;
-  enum BusLogic_HostAdapterType HostAdapterType;
-  enum BusLogic_HostAdapterBusType HostAdapterBusType;
-  unsigned long IO_Address;
-  unsigned long PCI_Address;
-  unsigned short AddressCount;
-  unsigned char HostNumber;
-  unsigned char ModelName[9];
-  unsigned char FirmwareVersion[6];
-  unsigned char FullModelName[18];
-  unsigned char Bus;
-  unsigned char Device;
-  unsigned char IRQ_Channel;
-  unsigned char DMA_Channel;
-  unsigned char SCSI_ID;
-  boolean IRQ_ChannelAcquired:1;
-  boolean DMA_ChannelAcquired:1;
-  boolean ExtendedTranslationEnabled:1;
-  boolean ParityCheckingEnabled:1;
-  boolean BusResetEnabled:1;
-  boolean LevelSensitiveInterrupt:1;
-  boolean HostWideSCSI:1;
-  boolean HostDifferentialSCSI:1;
-  boolean HostSupportsSCAM:1;
-  boolean HostUltraSCSI:1;
-  boolean ExtendedLUNSupport:1;
-  boolean TerminationInfoValid:1;
-  boolean LowByteTerminated:1;
-  boolean HighByteTerminated:1;
-  boolean BounceBuffersRequired:1;
-  boolean StrictRoundRobinModeSupport:1;
-  boolean SCAM_Enabled:1;
-  boolean SCAM_Level2:1;
-  boolean HostAdapterInitialized:1;
-  boolean HostAdapterExternalReset:1;
-  boolean HostAdapterInternalError:1;
-  boolean ProcessCompletedCCBsActive;
-  volatile boolean HostAdapterCommandCompleted;
-  unsigned short HostAdapterScatterGatherLimit;
-  unsigned short DriverScatterGatherLimit;
-  unsigned short MaxTargetDevices;
-  unsigned short MaxLogicalUnits;
-  unsigned short MailboxCount;
-  unsigned short InitialCCBs;
-  unsigned short IncrementalCCBs;
-  unsigned short AllocatedCCBs;
-  unsigned short DriverQueueDepth;
-  unsigned short HostAdapterQueueDepth;
-  unsigned short UntaggedQueueDepth;
-  unsigned short CommonQueueDepth;
-  unsigned short BusSettleTime;
-  unsigned short SynchronousPermitted;
-  unsigned short FastPermitted;
-  unsigned short UltraPermitted;
-  unsigned short WidePermitted;
-  unsigned short DisconnectPermitted;
-  unsigned short TaggedQueuingPermitted;
-  unsigned short ExternalHostAdapterResets;
-  unsigned short HostAdapterInternalErrors;
-  unsigned short TargetDeviceCount;
-  unsigned short MessageBufferLength;
-  u32 BIOS_Address;
-  struct BusLogic_DriverOptions *DriverOptions;
-  struct FlashPoint_Info FlashPointInfo;
-  FlashPoint_CardHandle_T CardHandle;
-  struct BusLogic_HostAdapter *Next;
-  struct BusLogic_CCB *All_CCBs;
-  struct BusLogic_CCB *Free_CCBs;
-  struct BusLogic_CCB *FirstCompletedCCB;
-  struct BusLogic_CCB *LastCompletedCCB;
-  struct BusLogic_CCB *BusDeviceResetPendingCCB[BusLogic_MaxTargetDevices];
-  struct BusLogic_TargetFlags TargetFlags[BusLogic_MaxTargetDevices];
-  unsigned char QueueDepth[BusLogic_MaxTargetDevices];
-  unsigned char SynchronousPeriod[BusLogic_MaxTargetDevices];
-  unsigned char SynchronousOffset[BusLogic_MaxTargetDevices];
-  unsigned char ActiveCommands[BusLogic_MaxTargetDevices];
-  unsigned int CommandsSinceReset[BusLogic_MaxTargetDevices];
-  unsigned long LastSequencePoint[BusLogic_MaxTargetDevices];
-  unsigned long LastResetAttempted[BusLogic_MaxTargetDevices];
-  unsigned long LastResetCompleted[BusLogic_MaxTargetDevices];
-  struct BusLogic_OutgoingMailbox *FirstOutgoingMailbox;
-  struct BusLogic_OutgoingMailbox *LastOutgoingMailbox;
-  struct BusLogic_OutgoingMailbox *NextOutgoingMailbox;
-  struct BusLogic_IncomingMailbox *FirstIncomingMailbox;
-  struct BusLogic_IncomingMailbox *LastIncomingMailbox;
-  struct BusLogic_IncomingMailbox *NextIncomingMailbox;
-  struct BusLogic_TargetStatistics TargetStatistics[BusLogic_MaxTargetDevices];
-  unsigned char *MailboxSpace;
-  dma_addr_t MailboxSpaceHandle;
-  unsigned int MailboxSize;
-  unsigned long CCB_Offset;
-  char MessageBuffer[BusLogic_MessageBufferSize];
+struct BusLogic_HostAdapter {
+	struct Scsi_Host *SCSI_Host;
+	struct pci_dev *PCI_Device;
+	enum BusLogic_HostAdapterType HostAdapterType;
+	enum BusLogic_HostAdapterBusType HostAdapterBusType;
+	unsigned long IO_Address;
+	unsigned long PCI_Address;
+	unsigned short AddressCount;
+	unsigned char HostNumber;
+	unsigned char ModelName[9];
+	unsigned char FirmwareVersion[6];
+	unsigned char FullModelName[18];
+	unsigned char Bus;
+	unsigned char Device;
+	unsigned char IRQ_Channel;
+	unsigned char DMA_Channel;
+	unsigned char SCSI_ID;
+	boolean IRQ_ChannelAcquired:1;
+	boolean DMA_ChannelAcquired:1;
+	boolean ExtendedTranslationEnabled:1;
+	boolean ParityCheckingEnabled:1;
+	boolean BusResetEnabled:1;
+	boolean LevelSensitiveInterrupt:1;
+	boolean HostWideSCSI:1;
+	boolean HostDifferentialSCSI:1;
+	boolean HostSupportsSCAM:1;
+	boolean HostUltraSCSI:1;
+	boolean ExtendedLUNSupport:1;
+	boolean TerminationInfoValid:1;
+	boolean LowByteTerminated:1;
+	boolean HighByteTerminated:1;
+	boolean BounceBuffersRequired:1;
+	boolean StrictRoundRobinModeSupport:1;
+	boolean SCAM_Enabled:1;
+	boolean SCAM_Level2:1;
+	boolean HostAdapterInitialized:1;
+	boolean HostAdapterExternalReset:1;
+	boolean HostAdapterInternalError:1;
+	boolean ProcessCompletedCCBsActive;
+	volatile boolean HostAdapterCommandCompleted;
+	unsigned short HostAdapterScatterGatherLimit;
+	unsigned short DriverScatterGatherLimit;
+	unsigned short MaxTargetDevices;
+	unsigned short MaxLogicalUnits;
+	unsigned short MailboxCount;
+	unsigned short InitialCCBs;
+	unsigned short IncrementalCCBs;
+	unsigned short AllocatedCCBs;
+	unsigned short DriverQueueDepth;
+	unsigned short HostAdapterQueueDepth;
+	unsigned short UntaggedQueueDepth;
+	unsigned short CommonQueueDepth;
+	unsigned short BusSettleTime;
+	unsigned short SynchronousPermitted;
+	unsigned short FastPermitted;
+	unsigned short UltraPermitted;
+	unsigned short WidePermitted;
+	unsigned short DisconnectPermitted;
+	unsigned short TaggedQueuingPermitted;
+	unsigned short ExternalHostAdapterResets;
+	unsigned short HostAdapterInternalErrors;
+	unsigned short TargetDeviceCount;
+	unsigned short MessageBufferLength;
+	u32 BIOS_Address;
+	struct BusLogic_DriverOptions *DriverOptions;
+	struct FlashPoint_Info FlashPointInfo;
+	FlashPoint_CardHandle_T CardHandle;
+	struct BusLogic_HostAdapter *Next;
+	struct BusLogic_CCB *All_CCBs;
+	struct BusLogic_CCB *Free_CCBs;
+	struct BusLogic_CCB *FirstCompletedCCB;
+	struct BusLogic_CCB *LastCompletedCCB;
+	struct BusLogic_CCB *BusDeviceResetPendingCCB[BusLogic_MaxTargetDevices];
+	struct BusLogic_TargetFlags TargetFlags[BusLogic_MaxTargetDevices];
+	unsigned char QueueDepth[BusLogic_MaxTargetDevices];
+	unsigned char SynchronousPeriod[BusLogic_MaxTargetDevices];
+	unsigned char SynchronousOffset[BusLogic_MaxTargetDevices];
+	unsigned char ActiveCommands[BusLogic_MaxTargetDevices];
+	unsigned int CommandsSinceReset[BusLogic_MaxTargetDevices];
+	unsigned long LastSequencePoint[BusLogic_MaxTargetDevices];
+	unsigned long LastResetAttempted[BusLogic_MaxTargetDevices];
+	unsigned long LastResetCompleted[BusLogic_MaxTargetDevices];
+	struct BusLogic_OutgoingMailbox *FirstOutgoingMailbox;
+	struct BusLogic_OutgoingMailbox *LastOutgoingMailbox;
+	struct BusLogic_OutgoingMailbox *NextOutgoingMailbox;
+	struct BusLogic_IncomingMailbox *FirstIncomingMailbox;
+	struct BusLogic_IncomingMailbox *LastIncomingMailbox;
+	struct BusLogic_IncomingMailbox *NextIncomingMailbox;
+	struct BusLogic_TargetStatistics TargetStatistics[BusLogic_MaxTargetDevices];
+	unsigned char *MailboxSpace;
+	dma_addr_t MailboxSpaceHandle;
+	unsigned int MailboxSize;
+	unsigned long CCB_Offset;
+	char MessageBuffer[BusLogic_MessageBufferSize];
 };
 
 /*
   Define a structure for the BIOS Disk Parameters.
 */
 
-struct BIOS_DiskParameters
-{
-  int Heads;
-  int Sectors;
-  int Cylinders;
+struct BIOS_DiskParameters {
+	int Heads;
+	int Sectors;
+	int Cylinders;
 };
 
 /*
   Define a structure for the SCSI Inquiry command results.
 */
 
-struct SCSI_Inquiry
-{
-  unsigned char PeripheralDeviceType:5;			/* Byte 0 Bits 0-4 */
-  unsigned char PeripheralQualifier:3;			/* Byte 0 Bits 5-7 */
-  unsigned char DeviceTypeModifier:7;			/* Byte 1 Bits 0-6 */
-  boolean RMB:1;					/* Byte 1 Bit 7 */
-  unsigned char ANSI_ApprovedVersion:3;			/* Byte 2 Bits 0-2 */
-  unsigned char ECMA_Version:3;				/* Byte 2 Bits 3-5 */
-  unsigned char ISO_Version:2;				/* Byte 2 Bits 6-7 */
-  unsigned char ResponseDataFormat:4;			/* Byte 3 Bits 0-3 */
-  unsigned char :2;					/* Byte 3 Bits 4-5 */
-  boolean TrmIOP:1;					/* Byte 3 Bit 6 */
-  boolean AENC:1;					/* Byte 3 Bit 7 */
-  unsigned char AdditionalLength;			/* Byte 4 */
-  unsigned char :8;					/* Byte 5 */
-  unsigned char :8;					/* Byte 6 */
-  boolean SftRe:1;					/* Byte 7 Bit 0 */
-  boolean CmdQue:1;					/* Byte 7 Bit 1 */
-  boolean :1;						/* Byte 7 Bit 2 */
-  boolean Linked:1;					/* Byte 7 Bit 3 */
-  boolean Sync:1;					/* Byte 7 Bit 4 */
-  boolean WBus16:1;					/* Byte 7 Bit 5 */
-  boolean WBus32:1;					/* Byte 7 Bit 6 */
-  boolean RelAdr:1;					/* Byte 7 Bit 7 */
-  unsigned char VendorIdentification[8];		/* Bytes 8-15 */
-  unsigned char ProductIdentification[16];		/* Bytes 16-31 */
-  unsigned char ProductRevisionLevel[4];		/* Bytes 32-35 */
+struct SCSI_Inquiry {
+	unsigned char PeripheralDeviceType:5;	/* Byte 0 Bits 0-4 */
+	unsigned char PeripheralQualifier:3;	/* Byte 0 Bits 5-7 */
+	unsigned char DeviceTypeModifier:7;	/* Byte 1 Bits 0-6 */
+	boolean RMB:1;		/* Byte 1 Bit 7 */
+	unsigned char ANSI_ApprovedVersion:3;	/* Byte 2 Bits 0-2 */
+	unsigned char ECMA_Version:3;	/* Byte 2 Bits 3-5 */
+	unsigned char ISO_Version:2;	/* Byte 2 Bits 6-7 */
+	unsigned char ResponseDataFormat:4;	/* Byte 3 Bits 0-3 */
+	unsigned char:2;	/* Byte 3 Bits 4-5 */
+	boolean TrmIOP:1;	/* Byte 3 Bit 6 */
+	boolean AENC:1;		/* Byte 3 Bit 7 */
+	unsigned char AdditionalLength;	/* Byte 4 */
+	unsigned char:8;	/* Byte 5 */
+	unsigned char:8;	/* Byte 6 */
+	boolean SftRe:1;	/* Byte 7 Bit 0 */
+	boolean CmdQue:1;	/* Byte 7 Bit 1 */
+	 boolean:1;		/* Byte 7 Bit 2 */
+	boolean Linked:1;	/* Byte 7 Bit 3 */
+	boolean Sync:1;		/* Byte 7 Bit 4 */
+	boolean WBus16:1;	/* Byte 7 Bit 5 */
+	boolean WBus32:1;	/* Byte 7 Bit 6 */
+	boolean RelAdr:1;	/* Byte 7 Bit 7 */
+	unsigned char VendorIdentification[8];	/* Bytes 8-15 */
+	unsigned char ProductIdentification[16];	/* Bytes 16-31 */
+	unsigned char ProductRevisionLevel[4];	/* Bytes 32-35 */
 };
 
 /*
@@ -1226,7 +1175,7 @@
 
 static inline void BusLogic_AcquireHostAdapterLock(struct BusLogic_HostAdapter *HostAdapter)
 {
-  spin_lock_irq(HostAdapter->SCSI_Host->host_lock);
+	spin_lock_irq(HostAdapter->SCSI_Host->host_lock);
 }
 
 /*
@@ -1235,7 +1184,7 @@
 
 static inline void BusLogic_ReleaseHostAdapterLock(struct BusLogic_HostAdapter *HostAdapter)
 {
-  spin_unlock_irq(HostAdapter->SCSI_Host->host_lock);
+	spin_unlock_irq(HostAdapter->SCSI_Host->host_lock);
 }
 
 
@@ -1244,10 +1193,9 @@
   but is only called from the interrupt handler.
 */
 
-static inline void BusLogic_AcquireHostAdapterLockIH(struct BusLogic_HostAdapter *HostAdapter,
-						     unsigned long *ProcessorFlags)
+static inline void BusLogic_AcquireHostAdapterLockIH(struct BusLogic_HostAdapter *HostAdapter, unsigned long *ProcessorFlags)
 {
-  spin_lock_irqsave(HostAdapter->SCSI_Host->host_lock, *ProcessorFlags);
+	spin_lock_irqsave(HostAdapter->SCSI_Host->host_lock, *ProcessorFlags);
 }
 
 
@@ -1256,10 +1204,9 @@
   but is only called from the interrupt handler.
 */
 
-static inline void BusLogic_ReleaseHostAdapterLockIH(struct BusLogic_HostAdapter *HostAdapter,
-						     unsigned long *ProcessorFlags)
+static inline void BusLogic_ReleaseHostAdapterLockIH(struct BusLogic_HostAdapter *HostAdapter, unsigned long *ProcessorFlags)
 {
-  spin_unlock_irqrestore(HostAdapter->SCSI_Host->host_lock, *ProcessorFlags);
+	spin_unlock_irqrestore(HostAdapter->SCSI_Host->host_lock, *ProcessorFlags);
 }
 
 
@@ -1270,65 +1217,60 @@
 
 static inline void BusLogic_SCSIBusReset(struct BusLogic_HostAdapter *HostAdapter)
 {
-  union BusLogic_ControlRegister ControlRegister;
-  ControlRegister.All = 0;
-  ControlRegister.cr.SCSIBusReset = true;
-  outb(ControlRegister.All,
-       HostAdapter->IO_Address + BusLogic_ControlRegisterOffset);
+	union BusLogic_ControlRegister ControlRegister;
+	ControlRegister.All = 0;
+	ControlRegister.cr.SCSIBusReset = true;
+	outb(ControlRegister.All, HostAdapter->IO_Address + BusLogic_ControlRegisterOffset);
 }
 
 static inline void BusLogic_InterruptReset(struct BusLogic_HostAdapter *HostAdapter)
 {
-  union BusLogic_ControlRegister ControlRegister;
-  ControlRegister.All = 0;
-  ControlRegister.cr.InterruptReset = true;
-  outb(ControlRegister.All,
-       HostAdapter->IO_Address + BusLogic_ControlRegisterOffset);
+	union BusLogic_ControlRegister ControlRegister;
+	ControlRegister.All = 0;
+	ControlRegister.cr.InterruptReset = true;
+	outb(ControlRegister.All, HostAdapter->IO_Address + BusLogic_ControlRegisterOffset);
 }
 
 static inline void BusLogic_SoftReset(struct BusLogic_HostAdapter *HostAdapter)
 {
-  union BusLogic_ControlRegister ControlRegister;
-  ControlRegister.All = 0;
-  ControlRegister.cr.SoftReset = true;
-  outb(ControlRegister.All,
-       HostAdapter->IO_Address + BusLogic_ControlRegisterOffset);
+	union BusLogic_ControlRegister ControlRegister;
+	ControlRegister.All = 0;
+	ControlRegister.cr.SoftReset = true;
+	outb(ControlRegister.All, HostAdapter->IO_Address + BusLogic_ControlRegisterOffset);
 }
 
 static inline void BusLogic_HardReset(struct BusLogic_HostAdapter *HostAdapter)
 {
-  union BusLogic_ControlRegister ControlRegister;
-  ControlRegister.All = 0;
-  ControlRegister.cr.HardReset = true;
-  outb(ControlRegister.All,
-       HostAdapter->IO_Address + BusLogic_ControlRegisterOffset);
+	union BusLogic_ControlRegister ControlRegister;
+	ControlRegister.All = 0;
+	ControlRegister.cr.HardReset = true;
+	outb(ControlRegister.All, HostAdapter->IO_Address + BusLogic_ControlRegisterOffset);
 }
 
 static inline unsigned char BusLogic_ReadStatusRegister(struct BusLogic_HostAdapter *HostAdapter)
 {
-  return inb(HostAdapter->IO_Address + BusLogic_StatusRegisterOffset);
+	return inb(HostAdapter->IO_Address + BusLogic_StatusRegisterOffset);
 }
 
 static inline void BusLogic_WriteCommandParameterRegister(struct BusLogic_HostAdapter
-							  *HostAdapter,
-							  unsigned char Value)
+							  *HostAdapter, unsigned char Value)
 {
-  outb(Value, HostAdapter->IO_Address + BusLogic_CommandParameterRegisterOffset);
+	outb(Value, HostAdapter->IO_Address + BusLogic_CommandParameterRegisterOffset);
 }
 
 static inline unsigned char BusLogic_ReadDataInRegister(struct BusLogic_HostAdapter *HostAdapter)
 {
-  return inb(HostAdapter->IO_Address + BusLogic_DataInRegisterOffset);
+	return inb(HostAdapter->IO_Address + BusLogic_DataInRegisterOffset);
 }
 
 static inline unsigned char BusLogic_ReadInterruptRegister(struct BusLogic_HostAdapter *HostAdapter)
 {
-  return inb(HostAdapter->IO_Address + BusLogic_InterruptRegisterOffset);
+	return inb(HostAdapter->IO_Address + BusLogic_InterruptRegisterOffset);
 }
 
 static inline unsigned char BusLogic_ReadGeometryRegister(struct BusLogic_HostAdapter *HostAdapter)
 {
-  return inb(HostAdapter->IO_Address + BusLogic_GeometryRegisterOffset);
+	return inb(HostAdapter->IO_Address + BusLogic_GeometryRegisterOffset);
 }
 
 /*
@@ -1339,7 +1281,7 @@
 
 static inline void BusLogic_StartMailboxCommand(struct BusLogic_HostAdapter *HostAdapter)
 {
-  BusLogic_WriteCommandParameterRegister(HostAdapter, BusLogic_ExecuteMailboxCommand);
+	BusLogic_WriteCommandParameterRegister(HostAdapter, BusLogic_ExecuteMailboxCommand);
 }
 
 /*
@@ -1348,7 +1290,7 @@
 
 static inline void BusLogic_Delay(int Seconds)
 {
-  mdelay(1000 * Seconds);
+	mdelay(1000 * Seconds);
 }
 
 /*
@@ -1358,12 +1300,12 @@
 
 static inline u32 Virtual_to_Bus(void *VirtualAddress)
 {
-  return (u32) virt_to_bus(VirtualAddress);
+	return (u32) virt_to_bus(VirtualAddress);
 }
 
 static inline void *Bus_to_Virtual(u32 BusAddress)
 {
-  return (void *) bus_to_virt(BusAddress);
+	return (void *) bus_to_virt(BusAddress);
 }
 
 /*
@@ -1374,7 +1316,7 @@
 
 static inline u32 Virtual_to_32Bit_Virtual(void *VirtualAddress)
 {
-  return (u32) (unsigned long) VirtualAddress;
+	return (u32) (unsigned long) VirtualAddress;
 }
 
 /*
@@ -1384,7 +1326,8 @@
 
 static inline void BusLogic_IncrementErrorCounter(unsigned short *ErrorCounter)
 {
-  if (*ErrorCounter < 65535) (*ErrorCounter)++;
+	if (*ErrorCounter < 65535)
+		(*ErrorCounter)++;
 }
 
 /*
@@ -1392,40 +1335,35 @@
 */
 
 static inline void BusLogic_IncrementByteCounter(struct BusLogic_ByteCounter
-						 *ByteCounter,
-						 unsigned int Amount)
+						 *ByteCounter, unsigned int Amount)
 {
-  ByteCounter->Units += Amount;
-  if (ByteCounter->Units > 999999999)
-    {
-      ByteCounter->Units -= 1000000000;
-      ByteCounter->Billions++;
-    }
+	ByteCounter->Units += Amount;
+	if (ByteCounter->Units > 999999999) {
+		ByteCounter->Units -= 1000000000;
+		ByteCounter->Billions++;
+	}
 }
 
 /*
   BusLogic_IncrementSizeBucket increments the Bucket for Amount.
 */
 
-static inline void BusLogic_IncrementSizeBucket(BusLogic_CommandSizeBuckets_T
-						CommandSizeBuckets,
-						unsigned int Amount)
-{
-  int Index = 0;
-  if (Amount < 8*1024)
-    {
-      if (Amount < 2*1024)
-	Index = (Amount < 1*1024 ? 0 : 1);
-      else Index = (Amount < 4*1024 ? 2 : 3);
-    }
-  else if (Amount < 128*1024)
-    {
-      if (Amount < 32*1024)
-	Index = (Amount < 16*1024 ? 4 : 5);
-      else Index = (Amount < 64*1024 ? 6 : 7);
-    }
-  else Index = (Amount < 256*1024 ? 8 : 9);
-  CommandSizeBuckets[Index]++;
+static inline void BusLogic_IncrementSizeBucket(BusLogic_CommandSizeBuckets_T CommandSizeBuckets, unsigned int Amount)
+{
+	int Index = 0;
+	if (Amount < 8 * 1024) {
+		if (Amount < 2 * 1024)
+			Index = (Amount < 1 * 1024 ? 0 : 1);
+		else
+			Index = (Amount < 4 * 1024 ? 2 : 3);
+	} else if (Amount < 128 * 1024) {
+		if (Amount < 32 * 1024)
+			Index = (Amount < 16 * 1024 ? 4 : 5);
+		else
+			Index = (Amount < 64 * 1024 ? 6 : 7);
+	} else
+		Index = (Amount < 256 * 1024 ? 8 : 9);
+	CommandSizeBuckets[Index]++;
 }
 
 /*
@@ -1450,20 +1388,14 @@
 static const char *BusLogic_DriverInfo(struct Scsi_Host *);
 static int BusLogic_DetectHostAdapter(struct scsi_host_template *);
 static int BusLogic_ReleaseHostAdapter(struct Scsi_Host *);
-static int BusLogic_QueueCommand(struct scsi_cmnd *,
-				 void (*CompletionRoutine)(struct scsi_cmnd *));
-static int BusLogic_BIOSDiskParameters(struct scsi_device *,
-				       struct block_device *,
-				       sector_t, int *);
-static int BusLogic_ProcDirectoryInfo(struct Scsi_Host *, char *,
-				      char **, off_t, int, int);
+static int BusLogic_QueueCommand(struct scsi_cmnd *, void (*CompletionRoutine) (struct scsi_cmnd *));
+static int BusLogic_BIOSDiskParameters(struct scsi_device *, struct block_device *, sector_t, int *);
+static int BusLogic_ProcDirectoryInfo(struct Scsi_Host *, char *, char **, off_t, int, int);
 static int BusLogic_SlaveConfigure(struct scsi_device *);
 static void BusLogic_QueueCompletedCCB(struct BusLogic_CCB *);
 static irqreturn_t BusLogic_InterruptHandler(int, void *, struct pt_regs *);
-static int BusLogic_ResetHostAdapter(struct BusLogic_HostAdapter *,
-				     boolean HardReset);
-static void BusLogic_Message(enum BusLogic_MessageLevel, char *,
-			     struct BusLogic_HostAdapter *, ...);
+static int BusLogic_ResetHostAdapter(struct BusLogic_HostAdapter *, boolean HardReset);
+static void BusLogic_Message(enum BusLogic_MessageLevel, char *, struct BusLogic_HostAdapter *, ...);
 static int __init BusLogic_Setup(char *);
 
-#endif /* _BUSLOGIC_H */
+#endif				/* _BUSLOGIC_H */
diff -Nru a/drivers/scsi/Kconfig b/drivers/scsi/Kconfig
--- a/drivers/scsi/Kconfig	2004-10-18 14:57:03 -07:00
+++ b/drivers/scsi/Kconfig	2004-10-18 14:57:03 -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-10-18 14:56:49 -07:00
+++ b/drivers/scsi/Makefile	2004-10-18 14:56:49 -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-10-18 14:56:20 -07:00
+++ b/drivers/scsi/NCR5380.c	2004-10-18 14:56:20 -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	2004-10-18 14:56:32 -07:00
+++ b/drivers/scsi/NCR5380.h	2004-10-18 14:56:32 -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/NCR53C9x.c b/drivers/scsi/NCR53C9x.c
--- a/drivers/scsi/NCR53C9x.c	2004-10-18 14:56:19 -07:00
+++ b/drivers/scsi/NCR53C9x.c	2004-10-18 14:56:19 -07:00
@@ -94,7 +94,7 @@
 };
 
 /* The master ring of all esp hosts we are managing in this driver. */
-struct NCR_ESP *espchain = 0;
+struct NCR_ESP *espchain;
 int nesps = 0, esps_in_use = 0, esps_running = 0;
 
 irqreturn_t esp_intr(int irq, void *dev_id, struct pt_regs *pregs);
@@ -555,7 +555,7 @@
 	} else {
 		espchain = esp;
 	}
-	esp->next = 0;
+	esp->next = NULL;
 
 	return esp;
 }
@@ -565,7 +565,7 @@
 	struct NCR_ESP *elink;
 
 	if(espchain == esp) {
-		espchain = 0;
+		espchain = NULL;
 	} else {
 		for(elink = espchain; elink && (elink->next != esp); elink = elink->next);
 		if(elink) 
@@ -708,9 +708,9 @@
 	}				
 
 	/* Initialize the command queues */
-	esp->current_SC = 0;
-	esp->disconnected_SC = 0;
-	esp->issue_SC = 0;
+	esp->current_SC = NULL;
+	esp->disconnected_SC = NULL;
+	esp->issue_SC = NULL;
 
 	/* Clear the state machines. */
 	esp->targets_present = 0;
@@ -1728,7 +1728,7 @@
 		ESPLOG(("esp%d: Weird, being reselected but disconnected "
 			"command queue is empty.\n", esp->esp_id));
 	esp->snip = 0;
-	esp->current_SC = 0;
+	esp->current_SC = NULL;
 	sp->SCp.phase = not_issued;
 	append_SC(&esp->issue_SC, sp);
 }
@@ -3393,7 +3393,7 @@
 }
 
 static espfunc_t isvc_vector[] = {
-	0,
+	NULL,
 	esp_do_phase_determine,
 	esp_do_resetbus,
 	esp_finish_reset,
diff -Nru a/drivers/scsi/NCR53c406a.c b/drivers/scsi/NCR53c406a.c
--- a/drivers/scsi/NCR53c406a.c	2004-10-18 14:56:31 -07:00
+++ b/drivers/scsi/NCR53c406a.c	2004-10-18 14:56:31 -07:00
@@ -606,22 +606,24 @@
 }
 
 /* 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;
 	}
+	get_options(str, 4, ints);
 	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 +633,7 @@
 		}
 	if (!port_base) {
 		printk("NCR53c406a: Invalid PORTBASE 0x%x specified\n", ints[1]);
-		return;
+		return 0;
 	}
 
 	if (ints[0] > 1) {
@@ -654,6 +656,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-10-18 14:55:55 -07:00
+++ b/drivers/scsi/NCR_Q720.c	2004-10-18 14:55:55 -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-10-18 14:55:54 -07:00
+++ b/drivers/scsi/aacraid/README	2004-10-18 14:55:54 -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-10-18 14:56:29 -07:00
+++ b/drivers/scsi/aacraid/aachba.c	2004-10-18 14:56:29 -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-10-18 14:56:19 -07:00
+++ b/drivers/scsi/aacraid/aacraid.h	2004-10-18 14:56:19 -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-10-18 14:56:28 -07:00
+++ b/drivers/scsi/aacraid/commctrl.c	2004-10-18 14:56:28 -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-10-18 14:56:48 -07:00
+++ b/drivers/scsi/aacraid/commsup.c	2004-10-18 14:56:48 -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-10-18 14:56:28 -07:00
+++ b/drivers/scsi/aacraid/linit.c	2004-10-18 14:56:28 -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-10-18 14:56:27 -07:00
+++ b/drivers/scsi/advansys.c	2004-10-18 14:56:27 -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-10-18 14:57:04 -07:00
+++ b/drivers/scsi/advansys.h	2004-10-18 14:57:04 -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-10-18 14:56:32 -07:00
+++ b/drivers/scsi/aha1542.c	2004-10-18 14:56:32 -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	2004-10-18 14:56:48 -07:00
+++ b/drivers/scsi/aha1542.h	2004-10-18 14:56:48 -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-10-18 14:56:29 -07:00
+++ b/drivers/scsi/aic7xxx/Kconfig.aic79xx	2004-10-18 14:56:29 -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-10-18 14:56:28 -07:00
+++ b/drivers/scsi/aic7xxx/Kconfig.aic7xxx	2004-10-18 14:56:28 -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-10-18 14:56:32 -07:00
+++ b/drivers/scsi/aic7xxx/aic79xx_osm.c	2004-10-18 14:56:32 -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 *,
@@ -513,9 +511,6 @@
 			    struct scsi_cmnd *cmd,
 			    struct ahd_devinfo *devinfo,
 			    struct ahd_linux_target *targ);
-static __inline int
-	   ahd_linux_dv_fallback(struct ahd_softc *ahd,
-				 struct ahd_devinfo *devinfo);
 static int ahd_linux_fallback(struct ahd_softc *ahd,
 			      struct ahd_devinfo *devinfo);
 static __inline int ahd_linux_dv_fallback(struct ahd_softc *ahd,
@@ -2915,6 +2910,19 @@
 	ahd_unlock(ahd, &s);
 }
 
+static __inline int
+ahd_linux_dv_fallback(struct ahd_softc *ahd, struct ahd_devinfo *devinfo)
+{
+	u_long s;
+	int retval;
+
+	ahd_lock(ahd, &s);
+	retval = ahd_linux_fallback(ahd, devinfo);
+	ahd_unlock(ahd, &s);
+
+	return (retval);
+}
+
 static void
 ahd_linux_dv_transition(struct ahd_softc *ahd, struct scsi_cmnd *cmd,
 			struct ahd_devinfo *devinfo,
@@ -3163,7 +3171,7 @@
 				break;
 			}
 			if (status & SSQ_DELAY)
-				scsi_sleep(1 * HZ);
+				ssleep(1);
 
 			break;
 		case SS_START:
@@ -3323,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
@@ -3367,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) {
@@ -3549,19 +3557,6 @@
 	cmd->cmd_len = 6;
 	cmd->cmnd[0] = START_STOP_UNIT;
 	cmd->cmnd[4] = le | SSS_START;
-}
-
-static __inline int
-ahd_linux_dv_fallback(struct ahd_softc *ahd, struct ahd_devinfo *devinfo)
-{
-	u_long s;
-	int retval;
-
-	ahd_lock(ahd, &s);
-	retval = ahd_linux_fallback(ahd, devinfo);
-	ahd_unlock(ahd, &s);
-
-	return (retval);
 }
 
 static int
diff -Nru a/drivers/scsi/aic7xxx/aic79xx_pci.c b/drivers/scsi/aic7xxx/aic79xx_pci.c
--- a/drivers/scsi/aic7xxx/aic79xx_pci.c	2004-10-18 14:56:29 -07:00
+++ b/drivers/scsi/aic7xxx/aic79xx_pci.c	2004-10-18 14:56:29 -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-10-18 14:55:54 -07:00
+++ b/drivers/scsi/aic7xxx/aic7xxx_osm.c	2004-10-18 14:55:54 -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	2004-10-18 14:55:54 -07:00
+++ b/drivers/scsi/aic7xxx/aic7xxx_pci.c	2004-10-18 14:55:54 -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-10-18 14:56:50 -07:00
+++ b/drivers/scsi/aic7xxx/aicasm/Makefile	2004-10-18 14:56:50 -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-10-18 14:57:20 -07:00
+++ b/drivers/scsi/aic7xxx_old.c	2004-10-18 14:57:20 -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-10-18 14:55:54 -07:00
+++ b/drivers/scsi/arm/cumana_1.c	2004-10-18 14:55:54 -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-10-18 14:57:04 -07:00
+++ b/drivers/scsi/arm/ecoscsi.c	2004-10-18 14:57:04 -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-10-18 14:57:04 -07:00
+++ b/drivers/scsi/arm/eesox.c	2004-10-18 14:57:04 -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-10-18 14:56:28 -07:00
+++ b/drivers/scsi/arm/fas216.c	2004-10-18 14:56:28 -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-10-18 14:55:46 -07:00
+++ b/drivers/scsi/arm/oak.c	2004-10-18 14:55:46 -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/ata_piix.c b/drivers/scsi/ata_piix.c
--- a/drivers/scsi/ata_piix.c	2004-10-18 14:56:31 -07:00
+++ b/drivers/scsi/ata_piix.c	2004-10-18 14:56:31 -07:00
@@ -39,6 +39,7 @@
 	ICH5_PMR		= 0x90, /* port mapping register */
 	ICH5_PCS		= 0x92,	/* port control and status */
 
+	PIIX_FLAG_AHCI		= (1 << 28), /* AHCI possible */
 	PIIX_FLAG_CHECKINTR	= (1 << 29), /* make sure PCI INTx enabled */
 	PIIX_FLAG_COMBINED	= (1 << 30), /* combined mode possible */
 
@@ -58,6 +59,7 @@
 	ich5_sata		= 1,
 	piix4_pata		= 2,
 	ich6_sata		= 3,
+	ich6_sata_rm		= 4,
 };
 
 static int piix_init_one (struct pci_dev *pdev,
@@ -65,10 +67,8 @@
 
 static void piix_pata_phy_reset(struct ata_port *ap);
 static void piix_sata_phy_reset(struct ata_port *ap);
-static void piix_set_piomode (struct ata_port *ap, struct ata_device *adev,
-			      unsigned int pio);
-static void piix_set_udmamode (struct ata_port *ap, struct ata_device *adev,
-			       unsigned int udma);
+static void piix_set_piomode (struct ata_port *ap, struct ata_device *adev);
+static void piix_set_dmamode (struct ata_port *ap, struct ata_device *adev);
 
 static unsigned int in_module_init = 1;
 
@@ -87,13 +87,9 @@
 	{ 0x8086, 0x24df, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich5_sata },
 	{ 0x8086, 0x25a3, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich5_sata },
 	{ 0x8086, 0x25b0, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich5_sata },
-
-	/* ICH6 operates in two modes, "looks-like-ICH5" mode,
-	 * and enhanced mode, with queueing and other fancy stuff.
-	 * This is distinguished by PCI class code.
-	 */
 	{ 0x8086, 0x2651, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich6_sata },
-	{ 0x8086, 0x2652, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich6_sata },
+	{ 0x8086, 0x2652, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich6_sata_rm },
+	{ 0x8086, 0x2653, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich6_sata_rm },
 
 	{ }	/* terminate list */
 };
@@ -108,6 +104,7 @@
 static Scsi_Host_Template piix_sht = {
 	.module			= THIS_MODULE,
 	.name			= DRV_NAME,
+	.ioctl			= ata_scsi_ioctl,
 	.queuecommand		= ata_scsi_queuecmd,
 	.eh_strategy_handler	= ata_scsi_error,
 	.can_queue		= ATA_DEF_QUEUE,
@@ -126,17 +123,18 @@
 static struct ata_port_operations piix_pata_ops = {
 	.port_disable		= ata_port_disable,
 	.set_piomode		= piix_set_piomode,
-	.set_udmamode		= piix_set_udmamode,
+	.set_dmamode		= piix_set_dmamode,
 
-	.tf_load		= ata_tf_load_pio,
-	.tf_read		= ata_tf_read_pio,
-	.check_status		= ata_check_status_pio,
-	.exec_command		= ata_exec_command_pio,
+	.tf_load		= ata_tf_load,
+	.tf_read		= ata_tf_read,
+	.check_status		= ata_check_status,
+	.exec_command		= ata_exec_command,
+	.dev_select		= ata_std_dev_select,
 
 	.phy_reset		= piix_pata_phy_reset,
 
-	.bmdma_setup		= ata_bmdma_setup_pio,
-	.bmdma_start		= ata_bmdma_start_pio,
+	.bmdma_setup		= ata_bmdma_setup,
+	.bmdma_start		= ata_bmdma_start,
 	.qc_prep		= ata_qc_prep,
 	.qc_issue		= ata_qc_issue_prot,
 
@@ -151,18 +149,17 @@
 
 static struct ata_port_operations piix_sata_ops = {
 	.port_disable		= ata_port_disable,
-	.set_piomode		= piix_set_piomode,
-	.set_udmamode		= piix_set_udmamode,
 
-	.tf_load		= ata_tf_load_pio,
-	.tf_read		= ata_tf_read_pio,
-	.check_status		= ata_check_status_pio,
-	.exec_command		= ata_exec_command_pio,
+	.tf_load		= ata_tf_load,
+	.tf_read		= ata_tf_read,
+	.check_status		= ata_check_status,
+	.exec_command		= ata_exec_command,
+	.dev_select		= ata_std_dev_select,
 
 	.phy_reset		= piix_sata_phy_reset,
 
-	.bmdma_setup		= ata_bmdma_setup_pio,
-	.bmdma_start		= ata_bmdma_start_pio,
+	.bmdma_setup		= ata_bmdma_setup,
+	.bmdma_start		= ata_bmdma_start,
 	.qc_prep		= ata_qc_prep,
 	.qc_issue		= ata_qc_issue_prot,
 
@@ -181,7 +178,12 @@
 		.sht		= &piix_sht,
 		.host_flags	= ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST |
 				  PIIX_FLAG_CHECKINTR,
-		.pio_mask	= 0x03,	/* pio3-4 */
+		.pio_mask	= 0x1f,	/* pio0-4 */
+#if 0
+		.mwdma_mask	= 0x06, /* mwdma1-2 */
+#else
+		.mwdma_mask	= 0x00, /* mwdma broken */
+#endif
 		.udma_mask	= ATA_UDMA_MASK_40C, /* FIXME: cbl det */
 		.port_ops	= &piix_pata_ops,
 	},
@@ -191,8 +193,9 @@
 		.sht		= &piix_sht,
 		.host_flags	= ATA_FLAG_SATA | ATA_FLAG_SRST |
 				  PIIX_FLAG_COMBINED | PIIX_FLAG_CHECKINTR,
-		.pio_mask	= 0x03,	/* pio3-4 */
-		.udma_mask	= 0x7f,	/* udma0-6 ; FIXME */
+		.pio_mask	= 0x1f,	/* pio0-4 */
+		.mwdma_mask	= 0x07, /* mwdma0-2 */
+		.udma_mask	= 0x7f,	/* udma0-6 */
 		.port_ops	= &piix_sata_ops,
 	},
 
@@ -200,7 +203,12 @@
 	{
 		.sht		= &piix_sht,
 		.host_flags	= ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST,
-		.pio_mask	= 0x03, /* pio3-4 */
+		.pio_mask	= 0x1f,	/* pio0-4 */
+#if 0
+		.mwdma_mask	= 0x06, /* mwdma1-2 */
+#else
+		.mwdma_mask	= 0x00, /* mwdma broken */
+#endif
 		.udma_mask	= ATA_UDMA_MASK_40C, /* FIXME: cbl det */
 		.port_ops	= &piix_pata_ops,
 	},
@@ -211,8 +219,21 @@
 		.host_flags	= ATA_FLAG_SATA | ATA_FLAG_SRST |
 				  PIIX_FLAG_COMBINED | PIIX_FLAG_CHECKINTR |
 				  ATA_FLAG_SLAVE_POSS,
-		.pio_mask	= 0x03,	/* pio3-4 */
-		.udma_mask	= 0x7f,	/* udma0-6 ; FIXME */
+		.pio_mask	= 0x1f,	/* pio0-4 */
+		.mwdma_mask	= 0x07, /* mwdma0-2 */
+		.udma_mask	= 0x7f,	/* udma0-6 */
+		.port_ops	= &piix_sata_ops,
+	},
+
+	/* ich6_sata_rm */
+	{
+		.sht		= &piix_sht,
+		.host_flags	= ATA_FLAG_SATA | ATA_FLAG_SRST |
+				  PIIX_FLAG_COMBINED | PIIX_FLAG_CHECKINTR |
+				  ATA_FLAG_SLAVE_POSS | PIIX_FLAG_AHCI,
+		.pio_mask	= 0x1f,	/* pio0-4 */
+		.mwdma_mask	= 0x07, /* mwdma0-2 */
+		.udma_mask	= 0x7f,	/* udma0-6 */
 		.port_ops	= &piix_sata_ops,
 	},
 };
@@ -368,11 +389,11 @@
  *	None (inherited from caller).
  */
 
-static void piix_set_piomode (struct ata_port *ap, struct ata_device *adev,
-			      unsigned int pio)
+static void piix_set_piomode (struct ata_port *ap, struct ata_device *adev)
 {
+	unsigned int pio	= adev->pio_mode - XFER_PIO_0;
 	struct pci_dev *dev	= ap->host_set->pdev;
-	unsigned int is_slave	= (adev->flags & ATA_DFLAG_MASTER) ? 0 : 1;
+	unsigned int is_slave	= (adev->devno != 0);
 	unsigned int master_port= ap->port_no ? 0x42 : 0x40;
 	unsigned int slave_port	= 0x44;
 	u16 master_data;
@@ -409,7 +430,7 @@
 }
 
 /**
- *	piix_set_udmamode - Initialize host controller PATA PIO timings
+ *	piix_set_dmamode - Initialize host controller PATA PIO timings
  *	@ap: Port whose timings we are configuring
  *	@adev: um
  *	@udma: udma mode, 0 - 6
@@ -420,9 +441,9 @@
  *	None (inherited from caller).
  */
 
-static void piix_set_udmamode (struct ata_port *ap, struct ata_device *adev,
-			      unsigned int udma)
+static void piix_set_dmamode (struct ata_port *ap, struct ata_device *adev)
 {
+	unsigned int udma	= adev->dma_mode; /* FIXME: MWDMA too */
 	struct pci_dev *dev	= ap->host_set->pdev;
 	u8 maslave		= ap->port_no ? 0x42 : 0x40;
 	u8 speed		= udma;
@@ -452,25 +473,38 @@
 		case XFER_UDMA_3:
 		case XFER_UDMA_1:	u_speed = 1 << (drive_dn * 4); break;
 		case XFER_UDMA_0:	u_speed = 0 << (drive_dn * 4); break;
+		case XFER_MW_DMA_2:
+		case XFER_MW_DMA_1:	break;
 		default:
 			BUG();
 			return;
 	}
 
-	if (!(reg48 & u_flag))
-		pci_write_config_byte(dev, 0x48, reg48 | u_flag);
-	if (speed == XFER_UDMA_5) {
-		pci_write_config_byte(dev, 0x55, (u8) reg55|w_flag);
+	if (speed >= XFER_UDMA_0) {
+		if (!(reg48 & u_flag))
+			pci_write_config_byte(dev, 0x48, reg48 | u_flag);
+		if (speed == XFER_UDMA_5) {
+			pci_write_config_byte(dev, 0x55, (u8) reg55|w_flag);
+		} else {
+			pci_write_config_byte(dev, 0x55, (u8) reg55 & ~w_flag);
+		}
+		if ((reg4a & a_speed) != u_speed)
+			pci_write_config_word(dev, 0x4a, (reg4a & ~a_speed) | u_speed);
+		if (speed > XFER_UDMA_2) {
+			if (!(reg54 & v_flag))
+				pci_write_config_byte(dev, 0x54, reg54 | v_flag);
+		} else
+			pci_write_config_byte(dev, 0x54, reg54 & ~v_flag);
 	} else {
-		pci_write_config_byte(dev, 0x55, (u8) reg55 & ~w_flag);
+		if (reg48 & u_flag)
+			pci_write_config_byte(dev, 0x48, reg48 & ~u_flag);
+		if (reg4a & a_speed)
+			pci_write_config_word(dev, 0x4a, reg4a & ~a_speed);
+		if (reg54 & v_flag)
+			pci_write_config_byte(dev, 0x54, reg54 & ~v_flag);
+		if (reg55 & w_flag)
+			pci_write_config_byte(dev, 0x55, (u8) reg55 & ~w_flag);
 	}
-	if ((reg4a & a_speed) != u_speed)
-		pci_write_config_word(dev, 0x4a, (reg4a & ~a_speed) | u_speed);
-	if (speed > XFER_UDMA_2) {
-		if (!(reg54 & v_flag))
-			pci_write_config_byte(dev, 0x54, reg54 | v_flag);
-	} else
-		pci_write_config_byte(dev, 0x54, reg54 & ~v_flag);
 }
 
 /* move to PCI layer, integrate w/ MSI stuff */
@@ -485,6 +519,42 @@
 	}
 }
 
+#define AHCI_PCI_BAR 5
+#define AHCI_GLOBAL_CTL 0x04
+#define AHCI_ENABLE (1 << 31)
+static int piix_disable_ahci(struct pci_dev *pdev)
+{
+	void *mmio;
+	unsigned long addr;
+	u32 tmp;
+	int rc = 0;
+
+	/* BUG: pci_enable_device has not yet been called.  This
+	 * works because this device is usually set up by BIOS.
+	 */
+
+	addr = pci_resource_start(pdev, AHCI_PCI_BAR);
+	if (!addr || !pci_resource_len(pdev, AHCI_PCI_BAR))
+		return 0;
+	
+	mmio = ioremap(addr, 64);
+	if (!mmio)
+		return -ENOMEM;
+	
+	tmp = readl(mmio + AHCI_GLOBAL_CTL);
+	if (tmp & AHCI_ENABLE) {
+		tmp &= ~AHCI_ENABLE;
+		writel(tmp, mmio + AHCI_GLOBAL_CTL);
+
+		tmp = readl(mmio + AHCI_GLOBAL_CTL);
+		if (tmp & AHCI_ENABLE)
+			rc = -EIO;
+	}
+	
+	iounmap(mmio);
+	return rc;
+}
+
 /**
  *	piix_init_one - Register PIIX ATA PCI device with kernel services
  *	@pdev: PCI device to register
@@ -516,6 +586,12 @@
 
 	port_info[0] = &piix_port_info[ent->driver_data];
 	port_info[1] = NULL;
+
+	if (port_info[0]->host_flags & PIIX_FLAG_AHCI) {
+		int rc = piix_disable_ahci(pdev);
+		if (rc)
+			return rc;
+	}
 
 	if (port_info[0]->host_flags & PIIX_FLAG_COMBINED) {
 		u8 tmp;
diff -Nru a/drivers/scsi/atp870u.c b/drivers/scsi/atp870u.c
--- a/drivers/scsi/atp870u.c	2004-10-18 14:56:28 -07:00
+++ b/drivers/scsi/atp870u.c	2004-10-18 14:56:28 -07:00
@@ -363,7 +363,7 @@
 			/*
 			 *      Clear it off the queue
 			 */
-			dev->id[target_id].curr_req = 0;
+			dev->id[target_id].curr_req = NULL;
 			dev->working--;
 			spin_unlock_irqrestore(dev->host->host_lock, flags);
 			/*
@@ -2263,10 +2263,10 @@
 	dev->in_snd = 0;
 	dev->in_int = 0;
 	for (k = 0; k < qcnt; k++) {
-		dev->querequ[k] = 0;
+		dev->querequ[k] = NULL;
 	}
 	for (k = 0; k < 16; k++) {
-		dev->id[k].curr_req = 0;
+		dev->id[k].curr_req = NULL;
 		dev->sp[k] = 0x04;
 	}
 	return 0;
diff -Nru a/drivers/scsi/cpqfcTScontrol.c b/drivers/scsi/cpqfcTScontrol.c
--- a/drivers/scsi/cpqfcTScontrol.c	2004-10-18 14:55:54 -07:00
+++ b/drivers/scsi/cpqfcTScontrol.c	2004-10-18 14:55:54 -07:00
@@ -116,7 +116,6 @@
   cpqfcHBAdata->fcLQ = pci_alloc_consistent(cpqfcHBAdata->PciDev,
 				 sizeof( FC_LINK_QUE), &cpqfcHBAdata->fcLQ_dma_handle);
   /* printk("@ %p (%u elements)\n", cpqfcHBAdata->fcLQ, FC_LINKQ_DEPTH); */
-  memset( cpqfcHBAdata->fcLQ, 0, sizeof( FC_LINK_QUE));
 
   if( cpqfcHBAdata->fcLQ == NULL ) // fatal error!!
   {
diff -Nru a/drivers/scsi/cpqfcTSinit.c b/drivers/scsi/cpqfcTSinit.c
--- a/drivers/scsi/cpqfcTSinit.c	2004-10-18 14:55:54 -07:00
+++ b/drivers/scsi/cpqfcTSinit.c	2004-10-18 14:55:54 -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-10-18 14:56:17 -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-10-18 14:55:55 -07:00
+++ b/drivers/scsi/dc395x.c	2004-10-18 14:55:55 -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);
 
@@ -989,7 +989,7 @@
 	srb->sg_count = 0;
 	srb->total_xfer_length = 0;
 	srb->sg_bus_addr = 0;
-	srb->virt_addr = 0;
+	srb->virt_addr = NULL;
 	srb->sg_index = 0;
 	srb->adapter_status = 0;
 	srb->target_status = 0;
@@ -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.
@@ -1999,7 +2016,7 @@
 	}
 
 	dprintkl(KERN_ERR, "sg_update_list: sg_to_virt failed\n");
-	srb->virt_addr = 0;
+	srb->virt_addr = NULL;
 }
 
 
@@ -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)
@@ -2603,18 +2615,6 @@
 }
 
 
-/* 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;
-}
-
-
 static struct ScsiReqBlk *msgin_qtag(struct AdapterCtlBlk *acb,
 		struct DeviceCtlBlk *dcb, u8 tag)
 {
@@ -3656,7 +3656,7 @@
 	} else {
 		acb->acb_flag |= RESET_DETECT;
 		reset_dev_param(acb);
-		doing_srb_done(acb, DID_RESET, 0, 1);
+		doing_srb_done(acb, DID_RESET, NULL, 1);
 		/*DC395x_RecoverSRB( acb ); */
 		acb->active_dcb = NULL;
 		acb->acb_flag = 0;
diff -Nru a/drivers/scsi/dmx3191d.c b/drivers/scsi/dmx3191d.c
--- a/drivers/scsi/dmx3191d.c	2004-10-18 14:56:33 -07:00
+++ b/drivers/scsi/dmx3191d.c	2004-10-18 14:56:33 -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-10-18 14:56:48 -07:00
+++ b/drivers/scsi/dtc.c	2004-10-18 14:56:48 -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-10-18 14:56:33 -07:00
+++ b/drivers/scsi/eata_pio.c	2004-10-18 14:56:33 -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/esp.h b/drivers/scsi/esp.h
--- a/drivers/scsi/esp.h	2004-10-18 14:55:54 -07:00
+++ b/drivers/scsi/esp.h	2004-10-18 14:55:54 -07:00
@@ -77,8 +77,8 @@
 
 /* We get one of these for each ESP probed. */
 struct esp {
-	unsigned long		eregs;		/* ESP controller registers */
-	unsigned long		dregs;		/* DMA controller registers */
+	void __iomem		*eregs;		/* ESP controller registers */
+	void __iomem		*dregs;		/* DMA controller registers */
 	struct sbus_dma		*dma;		/* DMA controller sw state */
 	struct Scsi_Host	*ehost;		/* Backpointer to SCSI Host */
 	struct sbus_dev		*sdev;		/* Pointer to SBus entry */
diff -Nru a/drivers/scsi/fd_mcs.c b/drivers/scsi/fd_mcs.c
--- a/drivers/scsi/fd_mcs.c	2004-10-18 14:56:28 -07:00
+++ b/drivers/scsi/fd_mcs.c	2004-10-18 14:56:28 -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,20 @@
 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];
 
+	get_options(str, 3, ints);
 	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 +396,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-10-18 14:56:48 -07:00
+++ b/drivers/scsi/fdomain.c	2004-10-18 14:56:48 -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-10-18 14:56:17 -07:00
+++ b/drivers/scsi/g_NCR5380.c	2004-10-18 14:56:17 -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-10-18 14:56:33 -07:00
+++ b/drivers/scsi/gdth.c	2004-10-18 14:56:33 -07:00
@@ -571,12 +571,12 @@
 
 #define BUS_L2P(a,b)    ((b)>(a)->virt_bus ? (b-1):(b))
 
-#define gdth_readb(addr)        readb((ulong)(addr))
-#define gdth_readw(addr)        readw((ulong)(addr))
-#define gdth_readl(addr)        (ulong32)readl((ulong)(addr))
-#define gdth_writeb(b,addr)     writeb((b),(ulong)(addr))
-#define gdth_writew(b,addr)     writew((b),(ulong)(addr))
-#define gdth_writel(b,addr)     writel((ulong32)(b),(ulong)(addr))
+#define gdth_readb(addr)        readb(addr)
+#define gdth_readw(addr)        readw(addr)
+#define gdth_readl(addr)        readl(addr)
+#define gdth_writeb(b,addr)     writeb((b),(addr))
+#define gdth_writew(b,addr)     writew((b),(addr))
+#define gdth_writel(b,addr)     writel((b),(addr))
 
 static unchar   gdth_drq_tab[4] = {5,6,7,7};            /* DRQ table */
 static unchar   gdth_irq_tab[6] = {0,10,11,12,14,0};    /* IRQ table */
@@ -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>
@@ -778,7 +775,7 @@
 
 GDTH_INITFUNC(static int, gdth_search_isa(ulong32 bios_adr))
 {
-    void *addr;
+    void __iomem *addr;
     ulong32 id;
 
     TRACE(("gdth_search_isa() bios adr. %x\n",bios_adr));
@@ -1053,7 +1050,7 @@
        
 GDTH_INITFUNC(static int, gdth_init_isa(ulong32 bios_adr,gdth_ha_str *ha))
 {
-    register gdt2_dpram_str *dp2_ptr;
+    register gdt2_dpram_str __iomem *dp2_ptr;
     int i;
     unchar irq_drq,prot_ver;
     ulong32 retries;
@@ -1065,10 +1062,10 @@
         printk("GDT-ISA: Initialization error (DPMEM remap error)\n");
         return 0;
     }
-    dp2_ptr = (gdt2_dpram_str *)ha->brd;
+    dp2_ptr = ha->brd;
     gdth_writeb(1, &dp2_ptr->io.memlock); /* switch off write protection */
     /* reset interface area */
-    memset_io((char *)&dp2_ptr->u,0,sizeof(dp2_ptr->u));
+    memset_io(&dp2_ptr->u, 0, sizeof(dp2_ptr->u));
     if (gdth_readl(&dp2_ptr->u) != 0) {
         printk("GDT-ISA: Initialization error (DPMEM write error)\n");
         iounmap(ha->brd);
@@ -1153,9 +1150,9 @@
 
 GDTH_INITFUNC(static int, gdth_init_pci(gdth_pci_str *pcistr,gdth_ha_str *ha))
 {
-    register gdt6_dpram_str *dp6_ptr;
-    register gdt6c_dpram_str *dp6c_ptr;
-    register gdt6m_dpram_str *dp6m_ptr;
+    register gdt6_dpram_str __iomem *dp6_ptr;
+    register gdt6c_dpram_str __iomem *dp6c_ptr;
+    register gdt6m_dpram_str __iomem *dp6m_ptr;
     ulong32 retries;
     unchar prot_ver;
     ushort command;
@@ -1183,7 +1180,7 @@
             return 0;
         }
         /* check and reset interface area */
-        dp6_ptr = (gdt6_dpram_str *)ha->brd;
+        dp6_ptr = ha->brd;
         gdth_writel(DPMEM_MAGIC, &dp6_ptr->u);
         if (gdth_readl(&dp6_ptr->u) != DPMEM_MAGIC) {
             printk("GDT-PCI: Cannot access DPMEM at 0x%lx (shadowed?)\n", 
@@ -1208,7 +1205,7 @@
                     printk("GDT-PCI: Initialization error (DPMEM remap error)\n");
                     return 0;
                 }
-                dp6_ptr = (gdt6_dpram_str *)ha->brd;
+                dp6_ptr = ha->brd;
                 gdth_writel(DPMEM_MAGIC, &dp6_ptr->u);
                 if (gdth_readl(&dp6_ptr->u) == DPMEM_MAGIC) {
                     printk("GDT-PCI: Use free address at 0x%x\n", i);
@@ -1222,7 +1219,7 @@
                 return 0;
             }
         }
-        memset_io((char *)&dp6_ptr->u,0,sizeof(dp6_ptr->u));
+        memset_io(&dp6_ptr->u, 0, sizeof(dp6_ptr->u));
         if (gdth_readl(&dp6_ptr->u) != 0) {
             printk("GDT-PCI: Initialization error (DPMEM write error)\n");
             iounmap(ha->brd);
@@ -1293,7 +1290,7 @@
             return 0;
         }
         /* check and reset interface area */
-        dp6c_ptr = (gdt6c_dpram_str *)ha->brd;
+        dp6c_ptr = ha->brd;
         gdth_writel(DPMEM_MAGIC, &dp6c_ptr->u);
         if (gdth_readl(&dp6c_ptr->u) != DPMEM_MAGIC) {
             printk("GDT-PCI: Cannot access DPMEM at 0x%lx (shadowed?)\n", 
@@ -1318,7 +1315,7 @@
                     printk("GDT-PCI: Initialization error (DPMEM remap error)\n");
                     return 0;
                 }
-                dp6c_ptr = (gdt6c_dpram_str *)ha->brd;
+                dp6c_ptr = ha->brd;
                 gdth_writel(DPMEM_MAGIC, &dp6c_ptr->u);
                 if (gdth_readl(&dp6c_ptr->u) == DPMEM_MAGIC) {
                     printk("GDT-PCI: Use free address at 0x%x\n", i);
@@ -1332,7 +1329,7 @@
                 return 0;
             }
         }
-        memset_io((char *)&dp6c_ptr->u,0,sizeof(dp6c_ptr->u));
+        memset_io(&dp6c_ptr->u, 0, sizeof(dp6c_ptr->u));
         if (gdth_readl(&dp6c_ptr->u) != 0) {
             printk("GDT-PCI: Initialization error (DPMEM write error)\n");
             iounmap(ha->brd);
@@ -1428,13 +1425,14 @@
                                pcistr->pdev->rom_address);
 #endif
         
+        dp6m_ptr = ha->brd;
+
         /* Ensure that it is safe to access the non HW portions of DPMEM.
          * Aditional check needed for Xscale based RAID controllers */
-        while( ((int)gdth_readb(&((gdt6m_dpram_str *)ha->brd)->i960r.sema0_reg) ) & 3 )
+        while( ((int)gdth_readb(&dp6m_ptr->i960r.sema0_reg) ) & 3 )
             gdth_delay(1);
         
         /* check and reset interface area */
-        dp6m_ptr = (gdt6m_dpram_str *)ha->brd;
         gdth_writel(DPMEM_MAGIC, &dp6m_ptr->u);
         if (gdth_readl(&dp6m_ptr->u) != DPMEM_MAGIC) {
             printk("GDT-PCI: Cannot access DPMEM at 0x%lx (shadowed?)\n", 
@@ -1459,7 +1457,7 @@
                     printk("GDT-PCI: Initialization error (DPMEM remap error)\n");
                     return 0;
                 }
-                dp6m_ptr = (gdt6m_dpram_str *)ha->brd;
+                dp6m_ptr = ha->brd;
                 gdth_writel(DPMEM_MAGIC, &dp6m_ptr->u);
                 if (gdth_readl(&dp6m_ptr->u) == DPMEM_MAGIC) {
                     printk("GDT-PCI: Use free address at 0x%x\n", i);
@@ -1473,7 +1471,7 @@
                 return 0;
             }
         }
-        memset_io((char *)&dp6m_ptr->u,0,sizeof(dp6m_ptr->u));
+        memset_io(&dp6m_ptr->u, 0, sizeof(dp6m_ptr->u));
         
         /* disable board interrupts, deinit services */
         gdth_writeb(gdth_readb(&dp6m_ptr->i960r.edoor_en_reg) | 4,
@@ -1556,9 +1554,9 @@
 {
     gdth_ha_str *ha;
     ulong flags;
-    gdt2_dpram_str *dp2_ptr;
-    gdt6_dpram_str *dp6_ptr;
-    gdt6m_dpram_str *dp6m_ptr;
+    gdt2_dpram_str __iomem *dp2_ptr;
+    gdt6_dpram_str __iomem *dp6_ptr;
+    gdt6m_dpram_str __iomem *dp6m_ptr;
 
     TRACE(("gdth_enable_int() hanum %d\n",hanum));
     ha = HADATA(gdth_ctr_tab[hanum]);
@@ -1569,12 +1567,12 @@
         outb(0xff, ha->bmic + EDENABREG);
         outb(0x01, ha->bmic + EINTENABREG);
     } else if (ha->type == GDT_ISA) {
-        dp2_ptr = (gdt2_dpram_str *)ha->brd;
+        dp2_ptr = ha->brd;
         gdth_writeb(1, &dp2_ptr->io.irqdel);
         gdth_writeb(0, &dp2_ptr->u.ic.Cmd_Index);
         gdth_writeb(1, &dp2_ptr->io.irqen);
     } else if (ha->type == GDT_PCI) {
-        dp6_ptr = (gdt6_dpram_str *)ha->brd;
+        dp6_ptr = ha->brd;
         gdth_writeb(1, &dp6_ptr->io.irqdel);
         gdth_writeb(0, &dp6_ptr->u.ic.Cmd_Index);
         gdth_writeb(1, &dp6_ptr->io.irqen);
@@ -1582,7 +1580,7 @@
         outb(0xff, PTR2USHORT(&ha->plx->edoor_reg));
         outb(0x03, PTR2USHORT(&ha->plx->control1));
     } else if (ha->type == GDT_PCIMPR) {
-        dp6m_ptr = (gdt6m_dpram_str *)ha->brd;
+        dp6m_ptr = ha->brd;
         gdth_writeb(0xff, &dp6m_ptr->i960r.edoor_reg);
         gdth_writeb(gdth_readb(&dp6m_ptr->i960r.edoor_en_reg) & ~4,
                     &dp6m_ptr->i960r.edoor_en_reg);
@@ -1608,15 +1606,15 @@
             *pIStatus = inb((ushort)ha->bmic + EDOORREG);
         else if (ha->type == GDT_ISA)
             *pIStatus =
-                gdth_readb(&((gdt2_dpram_str *)ha->brd)->u.ic.Cmd_Index);
+                gdth_readb(&((gdt2_dpram_str __iomem *)ha->brd)->u.ic.Cmd_Index);
         else if (ha->type == GDT_PCI)
             *pIStatus =
-                gdth_readb(&((gdt6_dpram_str *)ha->brd)->u.ic.Cmd_Index);
+                gdth_readb(&((gdt6_dpram_str __iomem *)ha->brd)->u.ic.Cmd_Index);
         else if (ha->type == GDT_PCINEW) 
             *pIStatus = inb(PTR2USHORT(&ha->plx->edoor_reg));
         else if (ha->type == GDT_PCIMPR)
             *pIStatus =
-                gdth_readb(&((gdt6m_dpram_str *)ha->brd)->i960r.edoor_reg);
+                gdth_readb(&((gdt6m_dpram_str __iomem *)ha->brd)->i960r.edoor_reg);
    
         if (*pIStatus)                                  
             return i;                           /* board found */
@@ -1636,14 +1634,14 @@
     if (ha->type == GDT_EISA)
         gdtsema0 = (int)inb(ha->bmic + SEMA0REG);
     else if (ha->type == GDT_ISA)
-        gdtsema0 = (int)gdth_readb(&((gdt2_dpram_str *)ha->brd)->u.ic.Sema0);
+        gdtsema0 = (int)gdth_readb(&((gdt2_dpram_str __iomem *)ha->brd)->u.ic.Sema0);
     else if (ha->type == GDT_PCI)
-        gdtsema0 = (int)gdth_readb(&((gdt6_dpram_str *)ha->brd)->u.ic.Sema0);
+        gdtsema0 = (int)gdth_readb(&((gdt6_dpram_str __iomem *)ha->brd)->u.ic.Sema0);
     else if (ha->type == GDT_PCINEW) 
         gdtsema0 = (int)inb(PTR2USHORT(&ha->plx->sema0_reg));
     else if (ha->type == GDT_PCIMPR)
         gdtsema0 = 
-            (int)gdth_readb(&((gdt6m_dpram_str *)ha->brd)->i960r.sema0_reg);
+            (int)gdth_readb(&((gdt6m_dpram_str __iomem *)ha->brd)->i960r.sema0_reg);
 
     return (gdtsema0 & 1);
 }
@@ -1679,13 +1677,13 @@
     if (ha->type == GDT_EISA) {
         outb(1, ha->bmic + SEMA0REG);
     } else if (ha->type == GDT_ISA) {
-        gdth_writeb(1, &((gdt2_dpram_str *)ha->brd)->u.ic.Sema0);
+        gdth_writeb(1, &((gdt2_dpram_str __iomem *)ha->brd)->u.ic.Sema0);
     } else if (ha->type == GDT_PCI) {
-        gdth_writeb(1, &((gdt6_dpram_str *)ha->brd)->u.ic.Sema0);
+        gdth_writeb(1, &((gdt6_dpram_str __iomem *)ha->brd)->u.ic.Sema0);
     } else if (ha->type == GDT_PCINEW) { 
         outb(1, PTR2USHORT(&ha->plx->sema0_reg));
     } else if (ha->type == GDT_PCIMPR) {
-        gdth_writeb(1, &((gdt6m_dpram_str *)ha->brd)->i960r.sema0_reg);
+        gdth_writeb(1, &((gdt6m_dpram_str __iomem *)ha->brd)->i960r.sema0_reg);
     }
 }
 
@@ -1694,10 +1692,10 @@
 {
     register gdth_ha_str *ha;
     register gdth_cmd_str *cmd_ptr;
-    register gdt6m_dpram_str *dp6m_ptr;
-    register gdt6c_dpram_str *dp6c_ptr;
-    gdt6_dpram_str *dp6_ptr;
-    gdt2_dpram_str *dp2_ptr;
+    register gdt6m_dpram_str __iomem *dp6m_ptr;
+    register gdt6c_dpram_str __iomem *dp6c_ptr;
+    gdt6_dpram_str __iomem *dp6_ptr;
+    gdt2_dpram_str __iomem *dp2_ptr;
     ushort cp_count,dp_offset,cmd_no;
     
     TRACE(("gdth_copy_command() hanum %d\n",hanum));
@@ -1720,28 +1718,28 @@
     
     /* set offset and service, copy command to DPMEM */
     if (ha->type == GDT_ISA) {
-        dp2_ptr = (gdt2_dpram_str *)ha->brd;
+        dp2_ptr = ha->brd;
         gdth_writew(dp_offset + DPMEM_COMMAND_OFFSET, 
                     &dp2_ptr->u.ic.comm_queue[cmd_no].offset);
         gdth_writew((ushort)cmd_ptr->Service, 
                     &dp2_ptr->u.ic.comm_queue[cmd_no].serv_id);
         memcpy_toio(&dp2_ptr->u.ic.gdt_dpr_cmd[dp_offset],cmd_ptr,cp_count);
     } else if (ha->type == GDT_PCI) {
-        dp6_ptr = (gdt6_dpram_str *)ha->brd;
+        dp6_ptr = ha->brd;
         gdth_writew(dp_offset + DPMEM_COMMAND_OFFSET, 
                     &dp6_ptr->u.ic.comm_queue[cmd_no].offset);
         gdth_writew((ushort)cmd_ptr->Service, 
                     &dp6_ptr->u.ic.comm_queue[cmd_no].serv_id);
         memcpy_toio(&dp6_ptr->u.ic.gdt_dpr_cmd[dp_offset],cmd_ptr,cp_count);
     } else if (ha->type == GDT_PCINEW) {
-        dp6c_ptr = (gdt6c_dpram_str *)ha->brd;
+        dp6c_ptr = ha->brd;
         gdth_writew(dp_offset + DPMEM_COMMAND_OFFSET, 
                     &dp6c_ptr->u.ic.comm_queue[cmd_no].offset);
         gdth_writew((ushort)cmd_ptr->Service, 
                     &dp6c_ptr->u.ic.comm_queue[cmd_no].serv_id);
         memcpy_toio(&dp6c_ptr->u.ic.gdt_dpr_cmd[dp_offset],cmd_ptr,cp_count);
     } else if (ha->type == GDT_PCIMPR) {
-        dp6m_ptr = (gdt6m_dpram_str *)ha->brd;
+        dp6m_ptr = ha->brd;
         gdth_writew(dp_offset + DPMEM_COMMAND_OFFSET, 
                     &dp6m_ptr->u.ic.comm_queue[cmd_no].offset);
         gdth_writew((ushort)cmd_ptr->Service, 
@@ -1780,13 +1778,13 @@
             outl(ha->ccb_phys, ha->bmic + MAILBOXREG);
         outb(ha->pccb->Service, ha->bmic + LDOORREG);
     } else if (ha->type == GDT_ISA) {
-        gdth_writeb(0, &((gdt2_dpram_str *)ha->brd)->io.event);
+        gdth_writeb(0, &((gdt2_dpram_str __iomem *)ha->brd)->io.event);
     } else if (ha->type == GDT_PCI) {
-        gdth_writeb(0, &((gdt6_dpram_str *)ha->brd)->io.event);
+        gdth_writeb(0, &((gdt6_dpram_str __iomem *)ha->brd)->io.event);
     } else if (ha->type == GDT_PCINEW) { 
         outb(1, PTR2USHORT(&ha->plx->ldoor_reg));
     } else if (ha->type == GDT_PCIMPR) {
-        gdth_writeb(1, &((gdt6m_dpram_str *)ha->brd)->i960r.ldoor_reg);
+        gdth_writeb(1, &((gdt6m_dpram_str __iomem *)ha->brd)->i960r.ldoor_reg);
     }
 }
 
@@ -3419,7 +3417,7 @@
     /* no GDTH_LOCK_HA() ! */
     TRACE2(("gdth_store_event() source %d idx %d\n", source, idx));
     if (source == 0)                        /* no source -> no event */
-        return 0;
+        return NULL;
 
     if (ebuffer[elastidx].event_source == source &&
         ebuffer[elastidx].event_idx == idx &&
@@ -3538,9 +3536,9 @@
 #endif
 {
     register gdth_ha_str *ha;
-    gdt6m_dpram_str *dp6m_ptr = NULL;
-    gdt6_dpram_str *dp6_ptr;
-    gdt2_dpram_str *dp2_ptr;
+    gdt6m_dpram_str __iomem *dp6m_ptr = NULL;
+    gdt6_dpram_str __iomem *dp6_ptr;
+    gdt2_dpram_str __iomem *dp2_ptr;
     Scsi_Cmnd *scp;
     int hanum, rval, i;
     unchar IStatus;
@@ -3619,7 +3617,7 @@
             outb(0xff, ha->bmic + EDOORREG);    /* acknowledge interrupt */
             outb(0x00, ha->bmic + SEMA1REG);    /* reset status semaphore */
         } else if (ha->type == GDT_ISA) {
-            dp2_ptr = (gdt2_dpram_str *)ha->brd;
+            dp2_ptr = ha->brd;
             if (IStatus & 0x80) {                       /* error flag */
                 IStatus &= ~0x80;
                 ha->status = gdth_readw(&dp2_ptr->u.ic.Status);
@@ -3634,7 +3632,7 @@
             gdth_writeb(0, &dp2_ptr->u.ic.Cmd_Index);/* reset command index */
             gdth_writeb(0, &dp2_ptr->io.Sema1);     /* reset status semaphore */
         } else if (ha->type == GDT_PCI) {
-            dp6_ptr = (gdt6_dpram_str *)ha->brd;
+            dp6_ptr = ha->brd;
             if (IStatus & 0x80) {                       /* error flag */
                 IStatus &= ~0x80;
                 ha->status = gdth_readw(&dp6_ptr->u.ic.Status);
@@ -3662,7 +3660,7 @@
             outb(0xff, PTR2USHORT(&ha->plx->edoor_reg)); 
             outb(0x00, PTR2USHORT(&ha->plx->sema1_reg)); 
         } else if (ha->type == GDT_PCIMPR) {
-            dp6m_ptr = (gdt6m_dpram_str *)ha->brd;
+            dp6m_ptr = ha->brd;
             if (IStatus & 0x80) {                       /* error flag */
                 IStatus &= ~0x80;
 #ifdef INT_COAL
@@ -3692,10 +3690,10 @@
                 if (ha->service != SCREENSERVICE &&
                     (ha->fw_vers & 0xff) >= 0x1a) {
                     ha->dvr.severity = gdth_readb
-                        (&((gdt6m_dpram_str *)ha->brd)->i960r.severity);
+                        (&((gdt6m_dpram_str __iomem *)ha->brd)->i960r.severity);
                     for (i = 0; i < 256; ++i) {
                         ha->dvr.event_string[i] = gdth_readb
-                            (&((gdt6m_dpram_str *)ha->brd)->i960r.evt_str[i]);
+                            (&((gdt6m_dpram_str __iomem *)ha->brd)->i960r.evt_str[i]);
                         if (ha->dvr.event_string[i] == 0)
                             break;
                     }
diff -Nru a/drivers/scsi/gdth.h b/drivers/scsi/gdth.h
--- a/drivers/scsi/gdth.h	2004-10-18 14:56:28 -07:00
+++ b/drivers/scsi/gdth.h	2004-10-18 14:56:28 -07:00
@@ -868,7 +868,7 @@
     ushort              raw_feat;               /* feat. raw service (s/g,..)*/
     ushort              screen_feat;            /* feat. raw service (s/g,..)*/
     ushort              bmic;                   /* BMIC address (EISA) */
-    void                *brd;                   /* DPRAM address */
+    void __iomem        *brd;                   /* DPRAM address */
     ulong32             brd_phys;               /* slot number/BIOS address */
     gdt6c_plx_regs      *plx;                   /* PLX regs (new PCI contr.) */
     gdth_cmd_str        *pccb;                  /* address command structure */
diff -Nru a/drivers/scsi/hosts.c b/drivers/scsi/hosts.c
--- a/drivers/scsi/hosts.c	2004-10-18 14:55:54 -07:00
+++ b/drivers/scsi/hosts.c	2004-10-18 14:55:54 -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-10-18 14:57:23 -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-10-18 14:57:22 -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-10-18 14:57:23 -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-10-18 14:57:23 -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-10-18 14:57:23 -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-10-18 14:57:24 -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-10-18 14:57:23 -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-10-18 14:57:04 -07:00
+++ b/drivers/scsi/imm.c	2004-10-18 14:57:04 -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-10-18 14:57:19 -07:00
+++ b/drivers/scsi/ipr.c	2004-10-18 14:57:19 -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,14 @@
 
 	if (ioa_cfg->sdt_state == GET_DUMP) {
 		dump = ioa_cfg->dump;
-		if (!dump || !kobject_get(&dump->kobj)) {
+		if (!dump) {
 			spin_unlock_irqrestore(ioa_cfg->host->host_lock, lock_flags);
 			return;
 		}
+		kref_get(&dump->kref);
 		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 +2040,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,15 +2424,15 @@
 	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) {
 		spin_unlock_irqrestore(ioa_cfg->host->host_lock, lock_flags);
 		return 0;
 	}
-
+	kref_get(&dump->kref);
 	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 +2482,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 +2507,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 +2554,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 +2690,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 +2697,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 +2713,6 @@
 	}
 
 	spin_unlock_irqrestore(ioa_cfg->host->host_lock, lock_flags);
-	scsi_adjust_queue_depth(sdev, tagged, qdepth);
 	return len;
 }
 
@@ -2785,7 +2782,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 +2847,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 +3078,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 +3099,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 +3729,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 +3865,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 +5429,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 +5452,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 +5502,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 +5523,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 +5548,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 +5559,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 +5688,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 +5697,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 +5708,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 +5721,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 +5732,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 +5763,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 +5784,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 +6002,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_SNIPE,
+		PCI_VENDOR_ID_IBM, IPR_SUBS_DEV_ID_570F,
+		0, 0, (kernel_ulong_t)&ipr_chip_cfg[1] },
 	{ }
 };
 MODULE_DEVICE_TABLE(pci, ipr_pci_table);
@@ -6009,16 +6029,14 @@
  * ipr_init - Module entry point
  *
  * Return value:
- * 	0 on success / non-zero on failure
+ * 	0 on success / negative value on failure
  **/
 static int __init ipr_init(void)
 {
 	ipr_info("IBM Power RAID SCSI Device Driver version: %s %s\n",
 		 IPR_DRIVER_VERSION, IPR_DRIVER_DATE);
 
-	pci_register_driver(&ipr_driver);
-
-	return 0;
+	return pci_module_init(&ipr_driver);
 }
 
 /**
diff -Nru a/drivers/scsi/ipr.h b/drivers/scsi/ipr.h
--- a/drivers/scsi/ipr.h	2004-10-18 14:56:18 -07:00
+++ b/drivers/scsi/ipr.h	2004-10-18 14:56:18 -07:00
@@ -1,7 +1,7 @@
 /*
  * ipr.h -- 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
  *
@@ -19,6 +19,8 @@
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  *
+ * Alan Cox <alan@redhat.com> - Removed several careless u32/dma_addr_t errors
+ *				that broke 64bit platforms.
  */
 
 #ifndef _IPR_H
@@ -27,6 +29,7 @@
 #include <linux/types.h>
 #include <linux/completion.h>
 #include <linux/list.h>
+#include <linux/kref.h>
 #include <scsi/scsi.h>
 #include <scsi/scsi_cmnd.h>
 #ifdef CONFIG_KDB
@@ -36,8 +39,8 @@
 /*
  * Literals
  */
-#define IPR_DRIVER_VERSION "2.0.10"
-#define IPR_DRIVER_DATE "(June 7, 2004)"
+#define IPR_DRIVER_VERSION "2.0.11"
+#define IPR_DRIVER_DATE "(August 3, 2004)"
 
 /*
  * IPR_DBG_TRACE: Setting this to 1 will turn on some general function tracing
@@ -72,6 +75,8 @@
 #define IPR_SUBS_DEV_ID_5703	0x0278
 #define IPR_SUBS_DEV_ID_572E  0x02D3
 #define IPR_SUBS_DEV_ID_573D  0x02D4
+#define IPR_SUBS_DEV_ID_570F	0x02BD
+#define IPR_SUBS_DEV_ID_571B	0x02BE
 
 #define IPR_NAME				"ipr"
 
@@ -148,7 +153,6 @@
 #define	IPR_BUS_RESET					0x10
 #define IPR_ID_HOST_RR_Q				0xC4
 #define IPR_QUERY_IOA_CONFIG				0xC5
-#define IPR_ABORT_TASK					0xC7
 #define IPR_CANCEL_ALL_REQUESTS			0xCE
 #define IPR_HOST_CONTROLLED_ASYNC			0xCF
 #define	IPR_HCAM_CDB_OP_CODE_CONFIG_CHANGE	0x01
@@ -667,7 +671,7 @@
 
 struct ipr_hostrcb {
 	struct ipr_hcam hcam;
-	u32 hostrcb_dma;
+	dma_addr_t hostrcb_dma;
 	struct list_head queue;
 };
 
@@ -850,7 +854,7 @@
 	char cfg_table_start[8];
 #define IPR_CFG_TBL_START		"cfg"
 	struct ipr_config_table *cfg_table;
-	u32 cfg_table_dma;
+	dma_addr_t cfg_table_dma;
 
 	char resource_table_label[8];
 #define IPR_RES_TABLE_LABEL		"res_tbl"
@@ -861,12 +865,12 @@
 	char ipr_hcam_label[8];
 #define IPR_HCAM_LABEL			"hcams"
 	struct ipr_hostrcb *hostrcb[IPR_NUM_HCAMS];
-	u32 hostrcb_dma[IPR_NUM_HCAMS];
+	dma_addr_t hostrcb_dma[IPR_NUM_HCAMS];
 	struct list_head hostrcb_free_q;
 	struct list_head hostrcb_pending_q;
 
 	u32 *host_rrq;
-	u32 host_rrq_dma;
+	dma_addr_t host_rrq_dma;
 #define IPR_HRRQ_REQ_RESP_HANDLE_MASK	0xfffffffc
 #define IPR_HRRQ_RESP_BIT_SET			0x00000002
 #define IPR_HRRQ_TOGGLE_BIT				0x00000001
@@ -905,7 +909,7 @@
 	enum ipr_sdt_state sdt_state;
 
 	struct ipr_misc_cbs *vpd_cbs;
-	u32 vpd_cbs_dma;
+	dma_addr_t vpd_cbs_dma;
 
 	struct pci_pool *ipr_cmd_pool;
 
@@ -1029,7 +1033,7 @@
 }__attribute__((packed, aligned (4)));
 
 struct ipr_dump {
-	struct kobject kobj;
+	struct kref kref;
 	struct ipr_ioa_cfg *ioa_cfg;
 	struct ipr_driver_dump driver_dump;
 	struct ipr_ioa_dump ioa_dump;
diff -Nru a/drivers/scsi/ips.c b/drivers/scsi/ips.c
--- a/drivers/scsi/ips.c	2004-10-18 14:55:53 -07:00
+++ b/drivers/scsi/ips.c	2004-10-18 14:55:53 -07:00
@@ -215,7 +215,7 @@
 #endif
 #else
 #define IPS_SG_ADDRESS(sg)      (page_address((sg)->page) ? \
-                                     page_address((sg)->page)+(sg)->offset : 0)
+                                   page_address((sg)->page)+(sg)->offset : NULL)
 #define IPS_LOCK_SAVE(lock,flags) do{spin_lock(lock);(void)flags;}while(0)
 #define IPS_UNLOCK_RESTORE(lock,flags) do{spin_unlock(lock);(void)flags;}while(0)
 #endif
@@ -474,21 +474,17 @@
 static uint32_t ips_statupd_copperhead_memio(ips_ha_t *);
 static uint32_t ips_statupd_morpheus(ips_ha_t *);
 static ips_scb_t *ips_getscb(ips_ha_t *);
-static inline void ips_putq_scb_head(ips_scb_queue_t *, ips_scb_t *);
-static inline void ips_putq_scb_tail(ips_scb_queue_t *, ips_scb_t *);
-static inline void ips_putq_wait_head(ips_wait_queue_t *, Scsi_Cmnd *);
-static inline void ips_putq_wait_tail(ips_wait_queue_t *, Scsi_Cmnd *);
-static inline void ips_putq_copp_head(ips_copp_queue_t *,
+static void ips_putq_scb_head(ips_scb_queue_t *, ips_scb_t *);
+static void ips_putq_wait_tail(ips_wait_queue_t *, Scsi_Cmnd *);
+static void ips_putq_copp_tail(ips_copp_queue_t *,
 				      ips_copp_wait_item_t *);
-static inline void ips_putq_copp_tail(ips_copp_queue_t *,
-				      ips_copp_wait_item_t *);
-static inline ips_scb_t *ips_removeq_scb_head(ips_scb_queue_t *);
-static inline ips_scb_t *ips_removeq_scb(ips_scb_queue_t *, ips_scb_t *);
-static inline Scsi_Cmnd *ips_removeq_wait_head(ips_wait_queue_t *);
-static inline Scsi_Cmnd *ips_removeq_wait(ips_wait_queue_t *, Scsi_Cmnd *);
-static inline ips_copp_wait_item_t *ips_removeq_copp(ips_copp_queue_t *,
+static ips_scb_t *ips_removeq_scb_head(ips_scb_queue_t *);
+static ips_scb_t *ips_removeq_scb(ips_scb_queue_t *, ips_scb_t *);
+static Scsi_Cmnd *ips_removeq_wait_head(ips_wait_queue_t *);
+static Scsi_Cmnd *ips_removeq_wait(ips_wait_queue_t *, Scsi_Cmnd *);
+static ips_copp_wait_item_t *ips_removeq_copp(ips_copp_queue_t *,
 						     ips_copp_wait_item_t *);
-static inline ips_copp_wait_item_t *ips_removeq_copp_head(ips_copp_queue_t *);
+static ips_copp_wait_item_t *ips_removeq_copp_head(ips_copp_queue_t *);
 
 static int ips_is_passthru(Scsi_Cmnd *);
 static int ips_make_passthru(ips_ha_t *, Scsi_Cmnd *, ips_scb_t *, int);
@@ -1885,7 +1881,7 @@
 /*   Fill in a single scb sg_list element from an address                   */
 /*   return a -1 if a breakup occurred                                      */
 /****************************************************************************/
-static inline int
+static int
 ips_fill_scb_sg_single(ips_ha_t * ha, dma_addr_t busaddr,
 		       ips_scb_t * scb, int indx, unsigned int e_len)
 {
@@ -2950,7 +2946,7 @@
 /* ASSUMED to be called from within the HA lock                             */
 /*                                                                          */
 /****************************************************************************/
-static inline void
+static void
 ips_putq_scb_head(ips_scb_queue_t * queue, ips_scb_t * item)
 {
 	METHOD_TRACE("ips_putq_scb_head", 1);
@@ -2969,38 +2965,6 @@
 
 /****************************************************************************/
 /*                                                                          */
-/* Routine Name: ips_putq_scb_tail                                          */
-/*                                                                          */
-/* Routine Description:                                                     */
-/*                                                                          */
-/*   Add an item to the tail of the queue                                   */
-/*                                                                          */
-/* ASSUMED to be called from within the HA lock                             */
-/*                                                                          */
-/****************************************************************************/
-static inline void
-ips_putq_scb_tail(ips_scb_queue_t * queue, ips_scb_t * item)
-{
-	METHOD_TRACE("ips_putq_scb_tail", 1);
-
-	if (!item)
-		return;
-
-	item->q_next = NULL;
-
-	if (queue->tail)
-		queue->tail->q_next = item;
-
-	queue->tail = item;
-
-	if (!queue->head)
-		queue->head = item;
-
-	queue->count++;
-}
-
-/****************************************************************************/
-/*                                                                          */
 /* Routine Name: ips_removeq_scb_head                                       */
 /*                                                                          */
 /* Routine Description:                                                     */
@@ -3010,7 +2974,7 @@
 /* ASSUMED to be called from within the HA lock                             */
 /*                                                                          */
 /****************************************************************************/
-static inline ips_scb_t *
+static ips_scb_t *
 ips_removeq_scb_head(ips_scb_queue_t * queue)
 {
 	ips_scb_t *item;
@@ -3045,7 +3009,7 @@
 /* ASSUMED to be called from within the HA lock                             */
 /*                                                                          */
 /****************************************************************************/
-static inline ips_scb_t *
+static ips_scb_t *
 ips_removeq_scb(ips_scb_queue_t * queue, ips_scb_t * item)
 {
 	ips_scb_t *p;
@@ -3082,34 +3046,6 @@
 
 /****************************************************************************/
 /*                                                                          */
-/* Routine Name: ips_putq_wait_head                                         */
-/*                                                                          */
-/* Routine Description:                                                     */
-/*                                                                          */
-/*   Add an item to the head of the queue                                   */
-/*                                                                          */
-/* ASSUMED to be called from within the HA lock                             */
-/*                                                                          */
-/****************************************************************************/
-static inline void
-ips_putq_wait_head(ips_wait_queue_t * queue, Scsi_Cmnd * item)
-{
-	METHOD_TRACE("ips_putq_wait_head", 1);
-
-	if (!item)
-		return;
-
-	item->host_scribble = (char *) queue->head;
-	queue->head = item;
-
-	if (!queue->tail)
-		queue->tail = item;
-
-	queue->count++;
-}
-
-/****************************************************************************/
-/*                                                                          */
 /* Routine Name: ips_putq_wait_tail                                         */
 /*                                                                          */
 /* Routine Description:                                                     */
@@ -3119,7 +3055,7 @@
 /* ASSUMED to be called from within the HA lock                             */
 /*                                                                          */
 /****************************************************************************/
-static inline void
+static void
 ips_putq_wait_tail(ips_wait_queue_t * queue, Scsi_Cmnd * item)
 {
 	METHOD_TRACE("ips_putq_wait_tail", 1);
@@ -3151,7 +3087,7 @@
 /* ASSUMED to be called from within the HA lock                             */
 /*                                                                          */
 /****************************************************************************/
-static inline Scsi_Cmnd *
+static Scsi_Cmnd *
 ips_removeq_wait_head(ips_wait_queue_t * queue)
 {
 	Scsi_Cmnd *item;
@@ -3186,7 +3122,7 @@
 /* ASSUMED to be called from within the HA lock                             */
 /*                                                                          */
 /****************************************************************************/
-static inline Scsi_Cmnd *
+static Scsi_Cmnd *
 ips_removeq_wait(ips_wait_queue_t * queue, Scsi_Cmnd * item)
 {
 	Scsi_Cmnd *p;
@@ -3223,34 +3159,6 @@
 
 /****************************************************************************/
 /*                                                                          */
-/* Routine Name: ips_putq_copp_head                                         */
-/*                                                                          */
-/* Routine Description:                                                     */
-/*                                                                          */
-/*   Add an item to the head of the queue                                   */
-/*                                                                          */
-/* ASSUMED to be called from within the HA lock                             */
-/*                                                                          */
-/****************************************************************************/
-static inline void
-ips_putq_copp_head(ips_copp_queue_t * queue, ips_copp_wait_item_t * item)
-{
-	METHOD_TRACE("ips_putq_copp_head", 1);
-
-	if (!item)
-		return;
-
-	item->next = queue->head;
-	queue->head = item;
-
-	if (!queue->tail)
-		queue->tail = item;
-
-	queue->count++;
-}
-
-/****************************************************************************/
-/*                                                                          */
 /* Routine Name: ips_putq_copp_tail                                         */
 /*                                                                          */
 /* Routine Description:                                                     */
@@ -3260,7 +3168,7 @@
 /* ASSUMED to be called from within the HA lock                             */
 /*                                                                          */
 /****************************************************************************/
-static inline void
+static void
 ips_putq_copp_tail(ips_copp_queue_t * queue, ips_copp_wait_item_t * item)
 {
 	METHOD_TRACE("ips_putq_copp_tail", 1);
@@ -3292,7 +3200,7 @@
 /* ASSUMED to be called from within the HA lock                             */
 /*                                                                          */
 /****************************************************************************/
-static inline ips_copp_wait_item_t *
+static ips_copp_wait_item_t *
 ips_removeq_copp_head(ips_copp_queue_t * queue)
 {
 	ips_copp_wait_item_t *item;
@@ -3327,7 +3235,7 @@
 /* ASSUMED to be called from within the HA lock                             */
 /*                                                                          */
 /****************************************************************************/
-static inline ips_copp_wait_item_t *
+static ips_copp_wait_item_t *
 ips_removeq_copp(ips_copp_queue_t * queue, ips_copp_wait_item_t * item)
 {
 	ips_copp_wait_item_t *p;
@@ -6946,8 +6854,8 @@
 {
 	ha->active = 0;
 	ips_free(ha);
-	ips_ha[index] = 0;
-	ips_sh[index] = 0;
+	ips_ha[index] = NULL;
+	ips_sh[index] = NULL;
 	return -1;
 }
 
diff -Nru a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c
--- a/drivers/scsi/libata-core.c	2004-10-18 14:55:53 -07:00
+++ b/drivers/scsi/libata-core.c	2004-10-18 14:55:53 -07:00
@@ -43,18 +43,21 @@
 #include <linux/libata.h>
 #include <asm/io.h>
 #include <asm/semaphore.h>
+#include <asm/byteorder.h>
 
 #include "libata.h"
 
 static unsigned int ata_busy_sleep (struct ata_port *ap,
 				    unsigned long tmout_pat,
 			    	    unsigned long tmout);
-static void __ata_dev_select (struct ata_port *ap, unsigned int device);
-static void ata_host_set_pio(struct ata_port *ap);
-static void ata_host_set_udma(struct ata_port *ap);
-static void ata_dev_set_pio(struct ata_port *ap, unsigned int device);
-static void ata_dev_set_udma(struct ata_port *ap, unsigned int device);
 static void ata_set_mode(struct ata_port *ap);
+static void ata_dev_set_xfermode(struct ata_port *ap, struct ata_device *dev);
+static unsigned int ata_get_mode_mask(struct ata_port *ap, int shift);
+static int fgb(u32 bitmap);
+static int ata_choose_xfer_mode(struct ata_port *ap,
+				u8 *xfer_mode_out,
+				unsigned int *xfer_shift_out);
+static int ata_qc_complete_noop(struct ata_queued_cmd *qc, u8 drv_stat);
 
 static unsigned int ata_unique_id = 1;
 static struct workqueue_struct *ata_wq;
@@ -64,17 +67,17 @@
 MODULE_LICENSE("GPL");
 
 /**
- *	ata_tf_load_pio - send taskfile registers to host controller
+ *	ata_tf_load - send taskfile registers to host controller
  *	@ap: Port to which output is sent
  *	@tf: ATA taskfile register set
  *
- *	Outputs ATA taskfile to standard ATA host controller using PIO.
+ *	Outputs ATA taskfile to standard ATA host controller.
  *
  *	LOCKING:
  *	Inherited from caller.
  */
 
-void ata_tf_load_pio(struct ata_port *ap, struct ata_taskfile *tf)
+static void ata_tf_load_pio(struct ata_port *ap, struct ata_taskfile *tf)
 {
 	struct ata_ioports *ioaddr = &ap->ioaddr;
 	unsigned int is_addr = tf->flags & ATA_TFLAG_ISADDR;
@@ -132,23 +135,23 @@
  *	Inherited from caller.
  */
 
-void ata_tf_load_mmio(struct ata_port *ap, struct ata_taskfile *tf)
+static void ata_tf_load_mmio(struct ata_port *ap, struct ata_taskfile *tf)
 {
 	struct ata_ioports *ioaddr = &ap->ioaddr;
 	unsigned int is_addr = tf->flags & ATA_TFLAG_ISADDR;
 
 	if (tf->ctl != ap->last_ctl) {
-		writeb(tf->ctl, ap->ioaddr.ctl_addr);
+		writeb(tf->ctl, (void __iomem *) ap->ioaddr.ctl_addr);
 		ap->last_ctl = tf->ctl;
 		ata_wait_idle(ap);
 	}
 
 	if (is_addr && (tf->flags & ATA_TFLAG_LBA48)) {
-		writeb(tf->hob_feature, (void *) ioaddr->feature_addr);
-		writeb(tf->hob_nsect, (void *) ioaddr->nsect_addr);
-		writeb(tf->hob_lbal, (void *) ioaddr->lbal_addr);
-		writeb(tf->hob_lbam, (void *) ioaddr->lbam_addr);
-		writeb(tf->hob_lbah, (void *) ioaddr->lbah_addr);
+		writeb(tf->hob_feature, (void __iomem *) ioaddr->feature_addr);
+		writeb(tf->hob_nsect, (void __iomem *) ioaddr->nsect_addr);
+		writeb(tf->hob_lbal, (void __iomem *) ioaddr->lbal_addr);
+		writeb(tf->hob_lbam, (void __iomem *) ioaddr->lbam_addr);
+		writeb(tf->hob_lbah, (void __iomem *) ioaddr->lbah_addr);
 		VPRINTK("hob: feat 0x%X nsect 0x%X, lba 0x%X 0x%X 0x%X\n",
 			tf->hob_feature,
 			tf->hob_nsect,
@@ -158,11 +161,11 @@
 	}
 
 	if (is_addr) {
-		writeb(tf->feature, (void *) ioaddr->feature_addr);
-		writeb(tf->nsect, (void *) ioaddr->nsect_addr);
-		writeb(tf->lbal, (void *) ioaddr->lbal_addr);
-		writeb(tf->lbam, (void *) ioaddr->lbam_addr);
-		writeb(tf->lbah, (void *) ioaddr->lbah_addr);
+		writeb(tf->feature, (void __iomem *) ioaddr->feature_addr);
+		writeb(tf->nsect, (void __iomem *) ioaddr->nsect_addr);
+		writeb(tf->lbal, (void __iomem *) ioaddr->lbal_addr);
+		writeb(tf->lbam, (void __iomem *) ioaddr->lbam_addr);
+		writeb(tf->lbah, (void __iomem *) ioaddr->lbah_addr);
 		VPRINTK("feat 0x%X nsect 0x%X lba 0x%X 0x%X 0x%X\n",
 			tf->feature,
 			tf->nsect,
@@ -172,26 +175,34 @@
 	}
 
 	if (tf->flags & ATA_TFLAG_DEVICE) {
-		writeb(tf->device, (void *) ioaddr->device_addr);
+		writeb(tf->device, (void __iomem *) ioaddr->device_addr);
 		VPRINTK("device 0x%X\n", tf->device);
 	}
 
 	ata_wait_idle(ap);
 }
 
+void ata_tf_load(struct ata_port *ap, struct ata_taskfile *tf)
+{
+	if (ap->flags & ATA_FLAG_MMIO)
+		ata_tf_load_mmio(ap, tf);
+	else
+		ata_tf_load_pio(ap, tf);
+}
+
 /**
- *	ata_exec_command_pio - issue ATA command to host controller
+ *	ata_exec_command - issue ATA command to host controller
  *	@ap: port to which command is being issued
  *	@tf: ATA taskfile register set
  *
- *	Issues PIO write to ATA command register, with proper
+ *	Issues PIO/MMIO write to ATA command register, with proper
  *	synchronization with interrupt handler / other threads.
  *
  *	LOCKING:
  *	spin_lock_irqsave(host_set lock)
  */
 
-void ata_exec_command_pio(struct ata_port *ap, struct ata_taskfile *tf)
+static void ata_exec_command_pio(struct ata_port *ap, struct ata_taskfile *tf)
 {
 	DPRINTK("ata%u: cmd 0x%X\n", ap->id, tf->command);
 
@@ -212,20 +223,28 @@
  *	spin_lock_irqsave(host_set lock)
  */
 
-void ata_exec_command_mmio(struct ata_port *ap, struct ata_taskfile *tf)
+static void ata_exec_command_mmio(struct ata_port *ap, struct ata_taskfile *tf)
 {
 	DPRINTK("ata%u: cmd 0x%X\n", ap->id, tf->command);
 
-       	writeb(tf->command, (void *) ap->ioaddr.command_addr);
+       	writeb(tf->command, (void __iomem *) ap->ioaddr.command_addr);
 	ata_pause(ap);
 }
 
+void ata_exec_command(struct ata_port *ap, struct ata_taskfile *tf)
+{
+	if (ap->flags & ATA_FLAG_MMIO)
+		ata_exec_command_mmio(ap, tf);
+	else
+		ata_exec_command_pio(ap, tf);
+}
+
 /**
  *	ata_exec - issue ATA command to host controller
  *	@ap: port to which command is being issued
  *	@tf: ATA taskfile register set
  *
- *	Issues PIO write to ATA command register, with proper
+ *	Issues PIO/MMIO write to ATA command register, with proper
  *	synchronization with interrupt handler / other threads.
  *
  *	LOCKING:
@@ -248,7 +267,7 @@
  *	@tf: ATA taskfile register set
  *
  *	Issues ATA taskfile register set to ATA host controller,
- *	via PIO, with proper synchronization with interrupt handler and
+ *	with proper synchronization with interrupt handler and
  *	other threads.
  *
  *	LOCKING:
@@ -268,7 +287,7 @@
  *	@tf: ATA taskfile register set
  *
  *	Issues ATA taskfile register set to ATA host controller,
- *	via PIO, with proper synchronization with interrupt handler and
+ *	with proper synchronization with interrupt handler and
  *	other threads.
  *
  *	LOCKING:
@@ -282,18 +301,18 @@
 }
 
 /**
- *	ata_tf_read_pio - input device's ATA taskfile shadow registers
+ *	ata_tf_read - input device's ATA taskfile shadow registers
  *	@ap: Port from which input is read
  *	@tf: ATA taskfile register set for storing input
  *
  *	Reads ATA taskfile registers for currently-selected device
- *	into @tf via PIO.
+ *	into @tf.
  *
  *	LOCKING:
  *	Inherited from caller.
  */
 
-void ata_tf_read_pio(struct ata_port *ap, struct ata_taskfile *tf)
+static void ata_tf_read_pio(struct ata_port *ap, struct ata_taskfile *tf)
 {
 	struct ata_ioports *ioaddr = &ap->ioaddr;
 
@@ -325,38 +344,46 @@
  *	Inherited from caller.
  */
 
-void ata_tf_read_mmio(struct ata_port *ap, struct ata_taskfile *tf)
+static void ata_tf_read_mmio(struct ata_port *ap, struct ata_taskfile *tf)
 {
 	struct ata_ioports *ioaddr = &ap->ioaddr;
 
-	tf->nsect = readb((void *)ioaddr->nsect_addr);
-	tf->lbal = readb((void *)ioaddr->lbal_addr);
-	tf->lbam = readb((void *)ioaddr->lbam_addr);
-	tf->lbah = readb((void *)ioaddr->lbah_addr);
-	tf->device = readb((void *)ioaddr->device_addr);
+	tf->nsect = readb((void __iomem *)ioaddr->nsect_addr);
+	tf->lbal = readb((void __iomem *)ioaddr->lbal_addr);
+	tf->lbam = readb((void __iomem *)ioaddr->lbam_addr);
+	tf->lbah = readb((void __iomem *)ioaddr->lbah_addr);
+	tf->device = readb((void __iomem *)ioaddr->device_addr);
 
 	if (tf->flags & ATA_TFLAG_LBA48) {
-		writeb(tf->ctl | ATA_HOB, ap->ioaddr.ctl_addr);
-		tf->hob_feature = readb((void *)ioaddr->error_addr);
-		tf->hob_nsect = readb((void *)ioaddr->nsect_addr);
-		tf->hob_lbal = readb((void *)ioaddr->lbal_addr);
-		tf->hob_lbam = readb((void *)ioaddr->lbam_addr);
-		tf->hob_lbah = readb((void *)ioaddr->lbah_addr);
+		writeb(tf->ctl | ATA_HOB, (void __iomem *) ap->ioaddr.ctl_addr);
+		tf->hob_feature = readb((void __iomem *)ioaddr->error_addr);
+		tf->hob_nsect = readb((void __iomem *)ioaddr->nsect_addr);
+		tf->hob_lbal = readb((void __iomem *)ioaddr->lbal_addr);
+		tf->hob_lbam = readb((void __iomem *)ioaddr->lbam_addr);
+		tf->hob_lbah = readb((void __iomem *)ioaddr->lbah_addr);
 	}
 }
 
+void ata_tf_read(struct ata_port *ap, struct ata_taskfile *tf)
+{
+	if (ap->flags & ATA_FLAG_MMIO)
+		ata_tf_read_mmio(ap, tf);
+	else
+		ata_tf_read_pio(ap, tf);
+}
+
 /**
- *	ata_check_status_pio - Read device status reg & clear interrupt
+ *	ata_check_status - Read device status reg & clear interrupt
  *	@ap: port where the device is
  *
  *	Reads ATA taskfile status register for currently-selected device
- *	via PIO and return it's value. This also clears pending interrupts
+ *	and return it's value. This also clears pending interrupts
  *      from this device
  *
  *	LOCKING:
  *	Inherited from caller.
  */
-u8 ata_check_status_pio(struct ata_port *ap)
+static u8 ata_check_status_pio(struct ata_port *ap)
 {
 	return inb(ap->ioaddr.status_addr);
 }
@@ -372,9 +399,16 @@
  *	LOCKING:
  *	Inherited from caller.
  */
-u8 ata_check_status_mmio(struct ata_port *ap)
+static u8 ata_check_status_mmio(struct ata_port *ap)
+{
+       	return readb((void __iomem *) ap->ioaddr.status_addr);
+}
+
+u8 ata_check_status(struct ata_port *ap)
 {
-       	return readb((void *) ap->ioaddr.status_addr);
+	if (ap->flags & ATA_FLAG_MMIO)
+		return ata_check_status_mmio(ap);
+	return ata_check_status_pio(ap);
 }
 
 /**
@@ -524,7 +558,7 @@
 	dev->write_cmd = (cmd >> 8) & 0xff;
 }
 
-static const char * udma_str[] = {
+static const char * xfer_mode_str[] = {
 	"UDMA/16",
 	"UDMA/25",
 	"UDMA/33",
@@ -533,6 +567,14 @@
 	"UDMA/100",
 	"UDMA/133",
 	"UDMA7",
+	"MWDMA0",
+	"MWDMA1",
+	"MWDMA2",
+	"PIO0",
+	"PIO1",
+	"PIO2",
+	"PIO3",
+	"PIO4",
 };
 
 /**
@@ -550,16 +592,24 @@
  *	@udma_mask, or the constant C string "<n/a>".
  */
 
-static const char *ata_udma_string(unsigned int udma_mask)
+static const char *ata_mode_string(unsigned int mask)
 {
 	int i;
 
-	for (i = 7; i >= 0; i--) {
-		if (udma_mask & (1 << i))
-			return udma_str[i];
-	}
+	for (i = 7; i >= 0; i--)
+		if (mask & (1 << i))
+			goto out;
+	for (i = ATA_SHIFT_MWDMA + 2; i >= ATA_SHIFT_MWDMA; i--)
+		if (mask & (1 << i))
+			goto out;
+	for (i = ATA_SHIFT_PIO + 4; i >= ATA_SHIFT_PIO; i--)
+		if (mask & (1 << i))
+			goto out;
 
 	return "<n/a>";
+
+out:
+	return xfer_mode_str[i];
 }
 
 /**
@@ -586,7 +636,7 @@
 	struct ata_ioports *ioaddr = &ap->ioaddr;
 	u8 nsect, lbal;
 
-	__ata_dev_select(ap, device);
+	ap->ops->dev_select(ap, device);
 
 	outb(0x55, ioaddr->nsect_addr);
 	outb(0xaa, ioaddr->lbal_addr);
@@ -630,19 +680,19 @@
 	struct ata_ioports *ioaddr = &ap->ioaddr;
 	u8 nsect, lbal;
 
-	__ata_dev_select(ap, device);
+	ap->ops->dev_select(ap, device);
 
-	writeb(0x55, (void *) ioaddr->nsect_addr);
-	writeb(0xaa, (void *) ioaddr->lbal_addr);
+	writeb(0x55, (void __iomem *) ioaddr->nsect_addr);
+	writeb(0xaa, (void __iomem *) ioaddr->lbal_addr);
 
-	writeb(0xaa, (void *) ioaddr->nsect_addr);
-	writeb(0x55, (void *) ioaddr->lbal_addr);
+	writeb(0xaa, (void __iomem *) ioaddr->nsect_addr);
+	writeb(0x55, (void __iomem *) ioaddr->lbal_addr);
 
-	writeb(0x55, (void *) ioaddr->nsect_addr);
-	writeb(0xaa, (void *) ioaddr->lbal_addr);
+	writeb(0x55, (void __iomem *) ioaddr->nsect_addr);
+	writeb(0xaa, (void __iomem *) ioaddr->lbal_addr);
 
-	nsect = readb((void *) ioaddr->nsect_addr);
-	lbal = readb((void *) ioaddr->lbal_addr);
+	nsect = readb((void __iomem *) ioaddr->nsect_addr);
+	lbal = readb((void __iomem *) ioaddr->lbal_addr);
 
 	if ((nsect == 0x55) && (lbal == 0xaa))
 		return 1;	/* we found a device */
@@ -651,7 +701,7 @@
 }
 
 /**
- *	ata_dev_devchk - PATA device presence detection
+ *	ata_devchk - PATA device presence detection
  *	@ap: ATA channel to examine
  *	@device: Device to examine (starting at zero)
  *
@@ -663,7 +713,7 @@
  *	caller.
  */
 
-static unsigned int ata_dev_devchk(struct ata_port *ap,
+static unsigned int ata_devchk(struct ata_port *ap,
 				    unsigned int device)
 {
 	if (ap->flags & ATA_FLAG_MMIO)
@@ -687,7 +737,7 @@
  *	the event of failure.
  */
 
-static unsigned int ata_dev_classify(struct ata_taskfile *tf)
+unsigned int ata_dev_classify(struct ata_taskfile *tf)
 {
 	/* Apple's open source Darwin code hints that some devices only
 	 * put a proper signature into the LBA mid/high registers,
@@ -735,7 +785,7 @@
 	unsigned int class;
 	u8 err;
 
-	__ata_dev_select(ap, device);
+	ap->ops->dev_select(ap, device);
 
 	memset(&tf, 0, sizeof(tf));
 
@@ -798,8 +848,12 @@
 	}
 }
 
+void ata_noop_dev_select (struct ata_port *ap, unsigned int device)
+{
+}
+
 /**
- *	__ata_dev_select - Select device 0/1 on ATA bus
+ *	ata_std_dev_select - Select device 0/1 on ATA bus
  *	@ap: ATA channel to manipulate
  *	@device: ATA device (numbered from zero) to select
  *
@@ -811,7 +865,7 @@
  *	caller.
  */
 
-static void __ata_dev_select (struct ata_port *ap, unsigned int device)
+void ata_std_dev_select (struct ata_port *ap, unsigned int device)
 {
 	u8 tmp;
 
@@ -821,7 +875,7 @@
 		tmp = ATA_DEVICE_OBS | ATA_DEV1;
 
 	if (ap->flags & ATA_FLAG_MMIO) {
-		writeb(tmp, (void *) ap->ioaddr.device_addr);
+		writeb(tmp, (void __iomem *) ap->ioaddr.device_addr);
 	} else {
 		outb(tmp, ap->ioaddr.device_addr);
 	}
@@ -839,7 +893,7 @@
  *	make either device 0, or device 1, active on the
  *	ATA channel.
  *
- *	This is a high-level version of __ata_dev_select(),
+ *	This is a high-level version of ata_std_dev_select(),
  *	which additionally provides the services of inserting
  *	the proper pauses and status polling, where needed.
  *
@@ -856,7 +910,7 @@
 	if (wait)
 		ata_wait_idle(ap);
 
-	__ata_dev_select(ap, device);
+	ap->ops->dev_select(ap, device);
 
 	if (wait) {
 		if (can_sleep && ap->device[device].class == ATA_DEV_ATAPI)
@@ -930,10 +984,14 @@
 {
 	struct ata_device *dev = &ap->device[device];
 	unsigned int i;
-	u16 tmp, udma_modes;
+	u16 tmp;
+	unsigned long xfer_modes;
 	u8 status;
-	struct ata_taskfile tf;
 	unsigned int using_edd;
+	DECLARE_COMPLETION(wait);
+	struct ata_queued_cmd *qc;
+	unsigned long flags;
+	int rc;
 
 	if (!ata_dev_present(dev)) {
 		DPRINTK("ENTER/EXIT (host %u, dev %u) -- nodev\n",
@@ -953,27 +1011,34 @@
 
 	ata_dev_select(ap, device, 1, 1); /* select device 0/1 */
 
-retry:
-	ata_tf_init(ap, &tf, device);
-	tf.ctl |= ATA_NIEN;
-	tf.protocol = ATA_PROT_PIO;
+	qc = ata_qc_new_init(ap, dev);
+	BUG_ON(qc == NULL);
 
+	ata_sg_init_one(qc, dev->id, sizeof(dev->id));
+	qc->pci_dma_dir = PCI_DMA_FROMDEVICE;
+	qc->tf.protocol = ATA_PROT_PIO;
+	qc->nsect = 1;
+
+retry:
 	if (dev->class == ATA_DEV_ATA) {
-		tf.command = ATA_CMD_ID_ATA;
+		qc->tf.command = ATA_CMD_ID_ATA;
 		DPRINTK("do ATA identify\n");
 	} else {
-		tf.command = ATA_CMD_ID_ATAPI;
+		qc->tf.command = ATA_CMD_ID_ATAPI;
 		DPRINTK("do ATAPI identify\n");
 	}
 
-	ata_tf_to_host(ap, &tf);
+	qc->waiting = &wait;
+	qc->complete_fn = ata_qc_complete_noop;
 
-	/* crazy ATAPI devices... */
-	if (dev->class == ATA_DEV_ATAPI)
-		msleep(150);
+	spin_lock_irqsave(&ap->host_set->lock, flags);
+	rc = ata_qc_issue(qc);
+	spin_unlock_irqrestore(&ap->host_set->lock, flags);
 
-	if (ata_busy_sleep(ap, ATA_TMOUT_BOOT_QUICK, ATA_TMOUT_BOOT))
+	if (rc)
 		goto err_out;
+	else
+		wait_for_completion(&wait);
 
 	status = ata_chk_status(ap);
 	if (status & ATA_ERR) {
@@ -988,44 +1053,21 @@
 		 * ATA software reset (SRST, the default) does not appear
 		 * to have this problem.
 		 */
-		if ((using_edd) && (tf.command == ATA_CMD_ID_ATA)) {
+		if ((using_edd) && (qc->tf.command == ATA_CMD_ID_ATA)) {
 			u8 err = ata_chk_err(ap);
 			if (err & ATA_ABORTED) {
 				dev->class = ATA_DEV_ATAPI;
+				qc->cursg = 0;
+				qc->cursg_ofs = 0;
+				qc->cursect = 0;
+				qc->nsect = 1;
 				goto retry;
 			}
 		}
 		goto err_out;
 	}
 
-	/* make sure we have BSY=0, DRQ=1 */
-	if ((status & ATA_DRQ) == 0) {
-		printk(KERN_WARNING "ata%u: dev %u (ATA%s?) not returning id page (0x%x)\n",
-		       ap->id, device,
-		       dev->class == ATA_DEV_ATA ? "" : "PI",
-		       status);
-		goto err_out;
-	}
-
-	/* read IDENTIFY [X] DEVICE page */
-	if (ap->flags & ATA_FLAG_MMIO) {
-		for (i = 0; i < ATA_ID_WORDS; i++)
-			dev->id[i] = readw((void *)ap->ioaddr.data_addr);
-	} else
-		for (i = 0; i < ATA_ID_WORDS; i++)
-			dev->id[i] = inw(ap->ioaddr.data_addr);
-
-	/* wait for host_idle */
-	status = ata_wait_idle(ap);
-	if (status & (ATA_BUSY | ATA_DRQ)) {
-		printk(KERN_WARNING "ata%u: dev %u (ATA%s?) error after id page (0x%x)\n",
-		       ap->id, device,
-		       dev->class == ATA_DEV_ATA ? "" : "PI",
-		       status);
-		goto err_out;
-	}
-
-	ata_irq_on(ap);	/* re-enable interrupts */
+	swap_buf_le16(dev->id, ATA_ID_WORDS);
 
 	/* print device capabilities */
 	printk(KERN_DEBUG "ata%u: dev %u cfg "
@@ -1045,12 +1087,13 @@
 		goto err_out_nosup;
 	}
 
-	/* we require UDMA support */
-	udma_modes =
-	tmp = dev->id[ATA_ID_UDMA_MODES];
-	if ((tmp & 0xff) == 0) {
-		printk(KERN_DEBUG "ata%u: no udma\n", ap->id);
-		goto err_out_nosup;
+	/* quick-n-dirty find max transfer mode; for printk only */
+	xfer_modes = dev->id[ATA_ID_UDMA_MODES];
+	if (!xfer_modes)
+		xfer_modes = (dev->id[ATA_ID_MWDMA_MODES]) << ATA_SHIFT_MWDMA;
+	if (!xfer_modes) {
+		xfer_modes = (dev->id[ATA_ID_PIO_MODES]) << (ATA_SHIFT_PIO + 3);
+		xfer_modes |= (0x7 << ATA_SHIFT_PIO);
 	}
 
 	ata_dump_id(dev);
@@ -1083,7 +1126,7 @@
 		/* print device info to dmesg */
 		printk(KERN_INFO "ata%u: dev %u ATA, max %s, %Lu sectors:%s\n",
 		       ap->id, device,
-		       ata_udma_string(udma_modes),
+		       ata_mode_string(xfer_modes),
 		       (unsigned long long)dev->n_sectors,
 		       dev->flags & ATA_DFLAG_LBA48 ? " lba48" : "");
 	}
@@ -1093,15 +1136,18 @@
 		if (ata_id_is_ata(dev))		/* sanity check */
 			goto err_out_nosup;
 
-		/* see if 16-byte commands supported */
-		tmp = dev->id[0] & 0x3;
-		if (tmp == 1)
-			ap->host->max_cmd_len = 16;
+		rc = atapi_cdb_len(dev->id);
+		if ((rc < 12) || (rc > ATAPI_CDB_LEN)) {
+			printk(KERN_WARNING "ata%u: unsupported CDB len\n", ap->id);
+			goto err_out_nosup;
+		}
+		ap->cdb_len = (unsigned int) rc;
+		ap->host->max_cmd_len = (unsigned char) ap->cdb_len;
 
 		/* print device info to dmesg */
 		printk(KERN_INFO "ata%u: dev %u ATAPI, max %s\n",
 		       ap->id, device,
-		       ata_udma_string(udma_modes));
+		       ata_mode_string(xfer_modes));
 	}
 
 	DPRINTK("EXIT, drv_stat = 0x%x\n", ata_chk_status(ap));
@@ -1171,13 +1217,13 @@
 }
 
 /**
- *	sata_phy_reset -
+ *	__sata_phy_reset -
  *	@ap:
  *
  *	LOCKING:
  *
  */
-void sata_phy_reset(struct ata_port *ap)
+void __sata_phy_reset(struct ata_port *ap)
 {
 	u32 sstatus;
 	unsigned long timeout = jiffies + (HZ * 5);
@@ -1215,6 +1261,21 @@
 		return;
 	}
 
+	ap->cbl = ATA_CBL_SATA;
+}
+
+/**
+ *	__sata_phy_reset -
+ *	@ap:
+ *
+ *	LOCKING:
+ *
+ */
+void sata_phy_reset(struct ata_port *ap)
+{
+	__sata_phy_reset(ap);
+	if (ap->flags & ATA_FLAG_PORT_DISABLED)
+		return;
 	ata_bus_reset(ap);
 }
 
@@ -1232,6 +1293,101 @@
 	ap->flags |= ATA_FLAG_PORT_DISABLED;
 }
 
+static struct {
+	unsigned int shift;
+	u8 base;
+} xfer_mode_classes[] = {
+	{ ATA_SHIFT_UDMA,	XFER_UDMA_0 },
+	{ ATA_SHIFT_MWDMA,	XFER_MW_DMA_0 },
+	{ ATA_SHIFT_PIO,	XFER_PIO_0 },
+};
+
+static inline u8 base_from_shift(unsigned int shift)
+{
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(xfer_mode_classes); i++)
+		if (xfer_mode_classes[i].shift == shift)
+			return xfer_mode_classes[i].base;
+
+	return 0xff;
+}
+
+static void ata_dev_set_mode(struct ata_port *ap, struct ata_device *dev)
+{
+	int ofs, idx;
+	u8 base;
+
+	if (!ata_dev_present(dev) || (ap->flags & ATA_FLAG_PORT_DISABLED))
+		return;
+
+	if (dev->xfer_shift == ATA_SHIFT_PIO)
+		dev->flags |= ATA_DFLAG_PIO;
+
+	ata_dev_set_xfermode(ap, dev);
+
+	base = base_from_shift(dev->xfer_shift);
+	ofs = dev->xfer_mode - base;
+	idx = ofs + dev->xfer_shift;
+	WARN_ON(idx >= ARRAY_SIZE(xfer_mode_str));
+
+	DPRINTK("idx=%d xfer_shift=%u, xfer_mode=0x%x, base=0x%x, offset=%d\n",
+		idx, dev->xfer_shift, (int)dev->xfer_mode, (int)base, ofs);
+
+	printk(KERN_INFO "ata%u: dev %u configured for %s\n",
+		ap->id, dev->devno, xfer_mode_str[idx]);
+}
+
+static int ata_host_set_pio(struct ata_port *ap)
+{
+	unsigned int mask;
+	int x, i;
+	u8 base, xfer_mode;
+
+	mask = ata_get_mode_mask(ap, ATA_SHIFT_PIO);
+	x = fgb(mask);
+	if (x < 0) {
+		printk(KERN_WARNING "ata%u: no PIO support\n", ap->id);
+		return -1;
+	}
+
+	base = base_from_shift(ATA_SHIFT_PIO);
+	xfer_mode = base + x;
+
+	DPRINTK("base 0x%x xfer_mode 0x%x mask 0x%x x %d\n",
+		(int)base, (int)xfer_mode, mask, x);
+
+	for (i = 0; i < ATA_MAX_DEVICES; i++) {
+		struct ata_device *dev = &ap->device[i];
+		if (ata_dev_present(dev)) {
+			dev->pio_mode = xfer_mode;
+			dev->xfer_mode = xfer_mode;
+			dev->xfer_shift = ATA_SHIFT_PIO;
+			if (ap->ops->set_piomode)
+				ap->ops->set_piomode(ap, dev);
+		}
+	}
+
+	return 0;
+}
+
+static void ata_host_set_dma(struct ata_port *ap, u8 xfer_mode,
+			    unsigned int xfer_shift)
+{
+	int i;
+
+	for (i = 0; i < ATA_MAX_DEVICES; i++) {
+		struct ata_device *dev = &ap->device[i];
+		if (ata_dev_present(dev)) {
+			dev->dma_mode = xfer_mode;
+			dev->xfer_mode = xfer_mode;
+			dev->xfer_shift = xfer_shift;
+			if (ap->ops->set_dmamode)
+				ap->ops->set_dmamode(ap, dev);
+		}
+	}
+}
+
 /**
  *	ata_set_mode - Program timings and issue SET FEATURES - XFER
  *	@ap: port on which timings will be programmed
@@ -1241,29 +1397,28 @@
  */
 static void ata_set_mode(struct ata_port *ap)
 {
-	unsigned int force_pio, i;
-
-	ata_host_set_pio(ap);
-	if (ap->flags & ATA_FLAG_PORT_DISABLED)
-		return;
+	unsigned int i, xfer_shift;
+	u8 xfer_mode;
+	int rc;
 
-	ata_host_set_udma(ap);
-	if (ap->flags & ATA_FLAG_PORT_DISABLED)
-		return;
+	/* step 1: always set host PIO timings */
+	rc = ata_host_set_pio(ap);
+	if (rc)
+		goto err_out;
 
-#ifdef ATA_FORCE_PIO
-	force_pio = 1;
-#else
-	force_pio = 0;
-#endif
+	/* step 2: choose the best data xfer mode */
+	xfer_mode = xfer_shift = 0;
+	rc = ata_choose_xfer_mode(ap, &xfer_mode, &xfer_shift);
+	if (rc)
+		goto err_out;
 
-	if (force_pio) {
-		ata_dev_set_pio(ap, 0);
-		ata_dev_set_pio(ap, 1);
-	} else {
-		ata_dev_set_udma(ap, 0);
-		ata_dev_set_udma(ap, 1);
-	}
+	/* step 3: if that xfer mode isn't PIO, set host DMA timings */
+	if (xfer_shift != ATA_SHIFT_PIO)
+		ata_host_set_dma(ap, xfer_mode, xfer_shift);
+
+	/* step 4: update devices' xfer mode */
+	ata_dev_set_mode(ap, &ap->device[0]);
+	ata_dev_set_mode(ap, &ap->device[1]);
 
 	if (ap->flags & ATA_FLAG_PORT_DISABLED)
 		return;
@@ -1275,6 +1430,11 @@
 		struct ata_device *dev = &ap->device[i];
 		ata_dev_set_protocol(dev);
 	}
+
+	return;
+
+err_out:
+	ata_port_disable(ap);
 }
 
 /**
@@ -1328,23 +1488,23 @@
 	unsigned int dev1 = devmask & (1 << 1);
 	unsigned long timeout;
 
-	/* if device 0 was found in ata_dev_devchk, wait for its
+	/* if device 0 was found in ata_devchk, wait for its
 	 * BSY bit to clear
 	 */
 	if (dev0)
 		ata_busy_sleep(ap, ATA_TMOUT_BOOT_QUICK, ATA_TMOUT_BOOT);
 
-	/* if device 1 was found in ata_dev_devchk, wait for
+	/* if device 1 was found in ata_devchk, wait for
 	 * register access, then wait for BSY to clear
 	 */
 	timeout = jiffies + ATA_TMOUT_BOOT;
 	while (dev1) {
 		u8 nsect, lbal;
 
-		__ata_dev_select(ap, 1);
+		ap->ops->dev_select(ap, 1);
 		if (ap->flags & ATA_FLAG_MMIO) {
-			nsect = readb((void *) ioaddr->nsect_addr);
-			lbal = readb((void *) ioaddr->lbal_addr);
+			nsect = readb((void __iomem *) ioaddr->nsect_addr);
+			lbal = readb((void __iomem *) ioaddr->lbal_addr);
 		} else {
 			nsect = inb(ioaddr->nsect_addr);
 			lbal = inb(ioaddr->lbal_addr);
@@ -1361,11 +1521,11 @@
 		ata_busy_sleep(ap, ATA_TMOUT_BOOT_QUICK, ATA_TMOUT_BOOT);
 
 	/* is all this really necessary? */
-	__ata_dev_select(ap, 0);
+	ap->ops->dev_select(ap, 0);
 	if (dev1)
-		__ata_dev_select(ap, 1);
+		ap->ops->dev_select(ap, 1);
 	if (dev0)
-		__ata_dev_select(ap, 0);
+		ap->ops->dev_select(ap, 0);
 }
 
 /**
@@ -1408,11 +1568,11 @@
 
 	/* software reset.  causes dev0 to be selected */
 	if (ap->flags & ATA_FLAG_MMIO) {
-		writeb(ap->ctl, ioaddr->ctl_addr);
+		writeb(ap->ctl, (void __iomem *) ioaddr->ctl_addr);
 		udelay(20);	/* FIXME: flush */
-		writeb(ap->ctl | ATA_SRST, ioaddr->ctl_addr);
+		writeb(ap->ctl | ATA_SRST, (void __iomem *) ioaddr->ctl_addr);
 		udelay(20);	/* FIXME: flush */
-		writeb(ap->ctl, ioaddr->ctl_addr);
+		writeb(ap->ctl, (void __iomem *) ioaddr->ctl_addr);
 	} else {
 		outb(ap->ctl, ioaddr->ctl_addr);
 		udelay(10);
@@ -1469,9 +1629,9 @@
 	if (ap->flags & ATA_FLAG_SATA_RESET)
 		dev0 = 1;
 	else {
-		dev0 = ata_dev_devchk(ap, 0);
+		dev0 = ata_devchk(ap, 0);
 		if (slave_possible)
-			dev1 = ata_dev_devchk(ap, 1);
+			dev1 = ata_devchk(ap, 1);
 	}
 
 	if (dev0)
@@ -1480,7 +1640,7 @@
 		devmask |= (1 << 1);
 
 	/* select device 0 again */
-	__ata_dev_select(ap, 0);
+	ap->ops->dev_select(ap, 0);
 
 	/* issue bus reset */
 	if (ap->flags & ATA_FLAG_SRST)
@@ -1488,7 +1648,7 @@
 	else if ((ap->flags & ATA_FLAG_SATA_RESET) == 0) {
 		/* set up device control */
 		if (ap->flags & ATA_FLAG_MMIO)
-			writeb(ap->ctl, ioaddr->ctl_addr);
+			writeb(ap->ctl, (void __iomem *) ioaddr->ctl_addr);
 		else
 			outb(ap->ctl, ioaddr->ctl_addr);
 		rc = ata_bus_edd(ap);
@@ -1509,9 +1669,9 @@
 
 	/* is double-select really necessary? */
 	if (ap->device[1].class != ATA_DEV_NONE)
-		__ata_dev_select(ap, 1);
+		ap->ops->dev_select(ap, 1);
 	if (ap->device[0].class != ATA_DEV_NONE)
-		__ata_dev_select(ap, 0);
+		ap->ops->dev_select(ap, 0);
 
 	/* if no devices were detected, disable this port */
 	if ((ap->device[0].class == ATA_DEV_NONE) &&
@@ -1521,7 +1681,7 @@
 	if (ap->flags & (ATA_FLAG_SATA_RESET | ATA_FLAG_SRST)) {
 		/* set up device control for ATA_FLAG_SATA_RESET */
 		if (ap->flags & ATA_FLAG_MMIO)
-			writeb(ap->ctl, ioaddr->ctl_addr);
+			writeb(ap->ctl, (void __iomem *) ioaddr->ctl_addr);
 		else
 			outb(ap->ctl, ioaddr->ctl_addr);
 	}
@@ -1536,116 +1696,102 @@
 	DPRINTK("EXIT\n");
 }
 
-/**
- *	ata_host_set_pio -
- *	@ap:
- *
- *	LOCKING:
- */
-
-static void ata_host_set_pio(struct ata_port *ap)
+static unsigned int ata_get_mode_mask(struct ata_port *ap, int shift)
 {
 	struct ata_device *master, *slave;
-	unsigned int pio, i;
-	u16 mask;
+	unsigned int mask;
 
 	master = &ap->device[0];
 	slave = &ap->device[1];
 
 	assert (ata_dev_present(master) || ata_dev_present(slave));
 
-	mask = ap->pio_mask;
-	if (ata_dev_present(master))
-		mask &= (master->id[ATA_ID_PIO_MODES] & 0x03);
-	if (ata_dev_present(slave))
-		mask &= (slave->id[ATA_ID_PIO_MODES] & 0x03);
-
-	/* require pio mode 3 or 4 support for host and all devices */
-	if (mask == 0) {
-		printk(KERN_WARNING "ata%u: no PIO3/4 support, ignoring\n",
-		       ap->id);
-		goto err_out;
+	if (shift == ATA_SHIFT_UDMA) {
+		mask = ap->udma_mask;
+		if (ata_dev_present(master))
+			mask &= (master->id[ATA_ID_UDMA_MODES] & 0xff);
+		if (ata_dev_present(slave))
+			mask &= (slave->id[ATA_ID_UDMA_MODES] & 0xff);
+	}
+	else if (shift == ATA_SHIFT_MWDMA) {
+		mask = ap->mwdma_mask;
+		if (ata_dev_present(master))
+			mask &= (master->id[ATA_ID_MWDMA_MODES] & 0x07);
+		if (ata_dev_present(slave))
+			mask &= (slave->id[ATA_ID_MWDMA_MODES] & 0x07);
+	}
+	else if (shift == ATA_SHIFT_PIO) {
+		mask = ap->pio_mask;
+		if (ata_dev_present(master)) {
+			/* spec doesn't return explicit support for
+			 * PIO0-2, so we fake it
+			 */
+			u16 tmp_mode = master->id[ATA_ID_PIO_MODES] & 0x03;
+			tmp_mode <<= 3;
+			tmp_mode |= 0x7;
+			mask &= tmp_mode;
+		}
+		if (ata_dev_present(slave)) {
+			/* spec doesn't return explicit support for
+			 * PIO0-2, so we fake it
+			 */
+			u16 tmp_mode = slave->id[ATA_ID_PIO_MODES] & 0x03;
+			tmp_mode <<= 3;
+			tmp_mode |= 0x7;
+			mask &= tmp_mode;
+		}
+	}
+	else {
+		mask = 0xffffffff; /* shut up compiler warning */
+		BUG();
 	}
 
-	pio = (mask & ATA_ID_PIO4) ? 4 : 3;
-	for (i = 0; i < ATA_MAX_DEVICES; i++)
-		if (ata_dev_present(&ap->device[i])) {
-			ap->device[i].pio_mode = (pio == 3) ?
-				XFER_PIO_3 : XFER_PIO_4;
-			if (ap->ops->set_piomode)
-				ap->ops->set_piomode(ap, &ap->device[i], pio);
-		}
+	return mask;
+}
 
-	return;
+/* find greatest bit */
+static int fgb(u32 bitmap)
+{
+	unsigned int i;
+	int x = -1;
 
-err_out:
-	ap->ops->port_disable(ap);
+	for (i = 0; i < 32; i++)
+		if (bitmap & (1 << i))
+			x = i;
+
+	return x;
 }
 
 /**
- *	ata_host_set_udma -
+ *	ata_choose_xfer_mode -
  *	@ap:
  *
  *	LOCKING:
+ *
+ *	RETURNS:
+ *	Zero on success, negative on error.
  */
 
-static void ata_host_set_udma(struct ata_port *ap)
-{
-	struct ata_device *master, *slave;
-	u16 mask;
-	unsigned int i, j;
-	int udma_mode = -1;
-
-	master = &ap->device[0];
-	slave = &ap->device[1];
-
-	assert (ata_dev_present(master) || ata_dev_present(slave));
-	assert ((ap->flags & ATA_FLAG_PORT_DISABLED) == 0);
-
-	DPRINTK("udma masks: host 0x%X, master 0x%X, slave 0x%X\n",
-		ap->udma_mask,
-		(!ata_dev_present(master)) ? 0xff :
-			(master->id[ATA_ID_UDMA_MODES] & 0xff),
-		(!ata_dev_present(slave)) ? 0xff :
-			(slave->id[ATA_ID_UDMA_MODES] & 0xff));
-
-	mask = ap->udma_mask;
-	if (ata_dev_present(master))
-		mask &= (master->id[ATA_ID_UDMA_MODES] & 0xff);
-	if (ata_dev_present(slave))
-		mask &= (slave->id[ATA_ID_UDMA_MODES] & 0xff);
-
-	i = XFER_UDMA_7;
-	while (i >= XFER_UDMA_0) {
-		j = i - XFER_UDMA_0;
-		DPRINTK("mask 0x%X i 0x%X j %u\n", mask, i, j);
-		if (mask & (1 << j)) {
-			udma_mode = i;
-			break;
+static int ata_choose_xfer_mode(struct ata_port *ap,
+				u8 *xfer_mode_out,
+				unsigned int *xfer_shift_out)
+{
+	unsigned int mask, shift;
+	int x, i;
+
+	for (i = 0; i < ARRAY_SIZE(xfer_mode_classes); i++) {
+		shift = xfer_mode_classes[i].shift;
+		mask = ata_get_mode_mask(ap, shift);
+
+		x = fgb(mask);
+		if (x >= 0) {
+			*xfer_mode_out = xfer_mode_classes[i].base + x;
+			*xfer_shift_out = shift;
+			return 0;
 		}
-
-		i--;
-	}
-
-	/* require udma for host and all attached devices */
-	if (udma_mode < 0) {
-		printk(KERN_WARNING "ata%u: no UltraDMA support, ignoring\n",
-		       ap->id);
-		goto err_out;
 	}
 
-	for (i = 0; i < ATA_MAX_DEVICES; i++)
-		if (ata_dev_present(&ap->device[i])) {
-			ap->device[i].udma_mode = udma_mode;
-			if (ap->ops->set_udmamode)
-				ap->ops->set_udmamode(ap, &ap->device[i],
-						      udma_mode);
-		}
-
-	return;
-
-err_out:
-	ap->ops->port_disable(ap);
+	return -1;
 }
 
 /**
@@ -1658,89 +1804,39 @@
 
 static void ata_dev_set_xfermode(struct ata_port *ap, struct ata_device *dev)
 {
-	struct ata_taskfile tf;
+	DECLARE_COMPLETION(wait);
+	struct ata_queued_cmd *qc;
+	int rc;
+	unsigned long flags;
 
 	/* set up set-features taskfile */
 	DPRINTK("set features - xfer mode\n");
-	ata_tf_init(ap, &tf, dev->devno);
-	tf.ctl |= ATA_NIEN;
-	tf.command = ATA_CMD_SET_FEATURES;
-	tf.feature = SETFEATURES_XFER;
-	tf.flags |= ATA_TFLAG_ISADDR | ATA_TFLAG_DEVICE;
-	tf.protocol = ATA_PROT_NODATA;
-	if (dev->flags & ATA_DFLAG_PIO)
-		tf.nsect = dev->pio_mode;
-	else
-		tf.nsect = dev->udma_mode;
 
-	/* do bus reset */
-	ata_tf_to_host(ap, &tf);
+	qc = ata_qc_new_init(ap, dev);
+	BUG_ON(qc == NULL);
 
-	/* crazy ATAPI devices... */
-	if (dev->class == ATA_DEV_ATAPI)
-		msleep(150);
+	qc->tf.command = ATA_CMD_SET_FEATURES;
+	qc->tf.feature = SETFEATURES_XFER;
+	qc->tf.flags |= ATA_TFLAG_ISADDR | ATA_TFLAG_DEVICE;
+	qc->tf.protocol = ATA_PROT_NODATA;
+	qc->tf.nsect = dev->xfer_mode;
 
-	ata_busy_sleep(ap, ATA_TMOUT_BOOT_QUICK, ATA_TMOUT_BOOT);
+	qc->waiting = &wait;
+	qc->complete_fn = ata_qc_complete_noop;
 
-	ata_irq_on(ap);	/* re-enable interrupts */
+	spin_lock_irqsave(&ap->host_set->lock, flags);
+	rc = ata_qc_issue(qc);
+	spin_unlock_irqrestore(&ap->host_set->lock, flags);
 
-	ata_wait_idle(ap);
+	if (rc)
+		ata_port_disable(ap);
+	else
+		wait_for_completion(&wait);
 
 	DPRINTK("EXIT\n");
 }
 
 /**
- *	ata_dev_set_udma - Set ATA device's transfer mode to Ultra DMA
- *	@ap: Port associated with device @dev
- *	@device: Device whose mode will be set
- *
- *	LOCKING:
- */
-
-static void ata_dev_set_udma(struct ata_port *ap, unsigned int device)
-{
-	struct ata_device *dev = &ap->device[device];
-
-	if (!ata_dev_present(dev) || (ap->flags & ATA_FLAG_PORT_DISABLED))
-		return;
-
-	ata_dev_set_xfermode(ap, dev);
-
-	assert((dev->udma_mode >= XFER_UDMA_0) &&
-	       (dev->udma_mode <= XFER_UDMA_7));
-	printk(KERN_INFO "ata%u: dev %u configured for %s\n",
-	       ap->id, device,
-	       udma_str[dev->udma_mode - XFER_UDMA_0]);
-}
-
-/**
- *	ata_dev_set_pio - Set ATA device's transfer mode to PIO
- *	@ap: Port associated with device @dev
- *	@device: Device whose mode will be set
- *
- *	LOCKING:
- */
-
-static void ata_dev_set_pio(struct ata_port *ap, unsigned int device)
-{
-	struct ata_device *dev = &ap->device[device];
-
-	if (!ata_dev_present(dev) || (ap->flags & ATA_FLAG_PORT_DISABLED))
-		return;
-
-	/* force PIO mode */
-	dev->flags |= ATA_DFLAG_PIO;
-
-	ata_dev_set_xfermode(ap, dev);
-
-	assert((dev->pio_mode >= XFER_PIO_3) &&
-	       (dev->pio_mode <= XFER_PIO_4));
-	printk(KERN_INFO "ata%u: dev %u configured for PIO%c\n",
-	       ap->id, device,
-	       dev->pio_mode == 3 ? '3' : '4');
-}
-
-/**
  *	ata_sg_clean -
  *	@qc:
  *
@@ -1789,7 +1885,7 @@
 
 	idx = 0;
 	for (nelem = qc->n_elem; nelem; nelem--,sg++) {
-		u32 addr, boundary;
+		u32 addr, offset;
 		u32 sg_len, len;
 
 		/* determine if physical DMA addr spans 64K boundary.
@@ -1800,10 +1896,10 @@
 		sg_len = sg_dma_len(sg);
 
 		while (sg_len) {
-			boundary = (addr & ~0xffff) + (0xffff + 1);
+			offset = addr & 0xffff;
 			len = sg_len;
-			if ((addr + sg_len) > boundary)
-				len = boundary - addr;
+			if ((offset + sg_len) > 0x10000)
+				len = 0x10000 - offset;
 
 			ap->prd[idx].addr = cpu_to_le32(addr);
 			ap->prd[idx].flags_len = cpu_to_le32(len & 0xffff);
@@ -2003,7 +2099,7 @@
 	}
 
 	drv_stat = ata_wait_idle(ap);
-	if (drv_stat & (ATA_BUSY | ATA_DRQ)) {
+	if (!ata_ok(drv_stat)) {
 		ap->pio_task_state = PIO_ST_ERR;
 		return;
 	}
@@ -2018,6 +2114,126 @@
 	ata_qc_complete(qc, drv_stat);
 }
 
+void swap_buf_le16(u16 *buf, unsigned int buf_words)
+{
+#ifdef __BIG_ENDIAN
+	unsigned int i;
+
+	for (i = 0; i < buf_words; i++)
+		buf[i] = le16_to_cpu(buf[i]);
+#endif /* __BIG_ENDIAN */
+}
+
+static void ata_mmio_data_xfer(struct ata_port *ap, unsigned char *buf,
+			       unsigned int buflen, int write_data)
+{
+	unsigned int i;
+	unsigned int words = buflen >> 1;
+	u16 *buf16 = (u16 *) buf;
+	void __iomem *mmio = (void __iomem *)ap->ioaddr.data_addr;
+
+	if (write_data) {
+		for (i = 0; i < words; i++)
+			writew(le16_to_cpu(buf16[i]), mmio);
+	} else {
+		for (i = 0; i < words; i++)
+			buf16[i] = cpu_to_le16(readw(mmio));
+	}
+}
+
+static void ata_pio_data_xfer(struct ata_port *ap, unsigned char *buf,
+			      unsigned int buflen, int write_data)
+{
+	unsigned int dwords = buflen >> 1;
+
+	if (write_data)
+		outsw(ap->ioaddr.data_addr, buf, dwords);
+	else
+		insw(ap->ioaddr.data_addr, buf, dwords);
+}
+
+static void ata_data_xfer(struct ata_port *ap, unsigned char *buf,
+			  unsigned int buflen, int do_write)
+{
+	if (ap->flags & ATA_FLAG_MMIO)
+		ata_mmio_data_xfer(ap, buf, buflen, do_write);
+	else
+		ata_pio_data_xfer(ap, buf, buflen, do_write);
+}
+
+static void ata_pio_sector(struct ata_queued_cmd *qc)
+{
+	int do_write = (qc->tf.flags & ATA_TFLAG_WRITE);
+	struct scatterlist *sg = qc->sg;
+	struct ata_port *ap = qc->ap;
+	struct page *page;
+	unsigned char *buf;
+
+	if (qc->cursect == (qc->nsect - 1))
+		ap->pio_task_state = PIO_ST_LAST;
+
+	page = sg[qc->cursg].page;
+	buf = kmap(page) +
+	      sg[qc->cursg].offset + (qc->cursg_ofs * ATA_SECT_SIZE);
+
+	qc->cursect++;
+	qc->cursg_ofs++;
+
+	if ((qc->cursg_ofs * ATA_SECT_SIZE) == sg_dma_len(&sg[qc->cursg])) {
+		qc->cursg++;
+		qc->cursg_ofs = 0;
+	}
+
+	DPRINTK("data %s\n", qc->tf.flags & ATA_TFLAG_WRITE ? "write" : "read");
+
+	/* do the actual data transfer */
+	do_write = (qc->tf.flags & ATA_TFLAG_WRITE);
+	ata_data_xfer(ap, buf, ATA_SECT_SIZE, do_write);
+
+	kunmap(page);
+}
+
+static void atapi_pio_sector(struct ata_queued_cmd *qc)
+{
+	struct ata_port *ap = qc->ap;
+	struct ata_device *dev = qc->dev;
+	unsigned int i, ireason, bc_lo, bc_hi, bytes;
+	int i_write, do_write = (qc->tf.flags & ATA_TFLAG_WRITE) ? 1 : 0;
+
+	ap->ops->tf_read(ap, &qc->tf);
+	ireason = qc->tf.nsect;
+	bc_lo = qc->tf.lbam;
+	bc_hi = qc->tf.lbah;
+	bytes = (bc_hi << 8) | bc_lo;
+
+	/* shall be cleared to zero, indicating xfer of data */
+	if (ireason & (1 << 0))
+		goto err_out;
+
+	/* make sure transfer direction matches expected */
+	i_write = ((ireason & (1 << 1)) == 0) ? 1 : 0;
+	if (do_write != i_write)
+		goto err_out;
+
+	/* make sure byte count is multiple of sector size; not
+	* required by standard (warning! warning!), but IDE driver
+	* does this to simplify things a bit.  We are lazy, and
+	* follow suit.
+	*/
+	if (bytes & (ATA_SECT_SIZE - 1))
+		goto err_out;
+
+	for (i = 0; i < (bytes >> 9); i++)
+		ata_pio_sector(qc);
+
+	return;
+
+err_out:
+	printk(KERN_INFO "ata%u: dev %u: ATAPI check failed\n",
+	      ap->id, dev->devno);
+	ap->pio_task_state = PIO_ST_ERR;
+}
+
 /**
  *	ata_pio_sector -
  *	@ap:
@@ -2025,12 +2241,9 @@
  *	LOCKING:
  */
 
-static void ata_pio_sector(struct ata_port *ap)
+static void ata_pio_block(struct ata_port *ap)
 {
 	struct ata_queued_cmd *qc;
-	struct scatterlist *sg;
-	struct page *page;
-	unsigned char *buf;
 	u8 status;
 
 	/*
@@ -2061,36 +2274,29 @@
 	qc = ata_qc_from_tag(ap, ap->active_tag);
 	assert(qc != NULL);
 
-	sg = qc->sg;
-
-	if (qc->cursect == (qc->nsect - 1))
-		ap->pio_task_state = PIO_ST_LAST;
+	if (is_atapi_taskfile(&qc->tf))
+		atapi_pio_sector(qc);
+	else
+		ata_pio_sector(qc);
+}
 
-	page = sg[qc->cursg].page;
-	buf = kmap(page) +
-	      sg[qc->cursg].offset + (qc->cursg_ofs * ATA_SECT_SIZE);
+static void ata_pio_error(struct ata_port *ap)
+{
+	struct ata_queued_cmd *qc;
+	u8 drv_stat;
 
-	qc->cursect++;
-	qc->cursg_ofs++;
+	qc = ata_qc_from_tag(ap, ap->active_tag);
+	assert(qc != NULL);
 
-	if (qc->flags & ATA_QCFLAG_SG)
-		if ((qc->cursg_ofs * ATA_SECT_SIZE) == sg_dma_len(&sg[qc->cursg])) {
-			qc->cursg++;
-			qc->cursg_ofs = 0;
-		}
+	drv_stat = ata_chk_status(ap);
+	printk(KERN_WARNING "ata%u: PIO error, drv_stat 0x%x\n",
+	       ap->id, drv_stat);
 
-	DPRINTK("data %s, drv_stat 0x%X\n",
-		qc->tf.flags & ATA_TFLAG_WRITE ? "write" : "read",
-		status);
+	ap->pio_task_state = PIO_ST_IDLE;
 
-	/* do the actual data transfer */
-	/* FIXME: mmio-ize */
-	if (qc->tf.flags & ATA_TFLAG_WRITE)
-		outsl(ap->ioaddr.data_addr, buf, ATA_SECT_DWORDS);
-	else
-		insl(ap->ioaddr.data_addr, buf, ATA_SECT_DWORDS);
+	ata_irq_on(ap);
 
-	kunmap(page);
+	ata_qc_complete(qc, drv_stat | ATA_ERR);
 }
 
 static void ata_pio_task(void *_data)
@@ -2100,7 +2306,7 @@
 
 	switch (ap->pio_task_state) {
 	case PIO_ST:
-		ata_pio_sector(ap);
+		ata_pio_block(ap);
 		break;
 
 	case PIO_ST_LAST:
@@ -2113,15 +2319,8 @@
 		break;
 
 	case PIO_ST_TMOUT:
-		printk(KERN_ERR "ata%d: FIXME: PIO_ST_TMOUT\n", /* FIXME */
-		       ap->id);
-		timeout = 11 * HZ;
-		break;
-
 	case PIO_ST_ERR:
-		printk(KERN_ERR "ata%d: FIXME: PIO_ST_ERR\n", /* FIXME */
-		       ap->id);
-		timeout = 11 * HZ;
+		ata_pio_error(ap);
 		break;
 	}
 
@@ -2180,7 +2379,6 @@
 
 		/* fall through */
 
-	case ATA_PROT_NODATA:
 	default:
 		ata_altstatus(ap);
 		drv_stat = ata_chk_status(ap);
@@ -2287,8 +2485,6 @@
 
 		ata_tf_init(ap, &qc->tf, dev->devno);
 
-		if (likely((dev->flags & ATA_DFLAG_PIO) == 0))
-			qc->flags |= ATA_QCFLAG_DMA;
 		if (dev->flags & ATA_DFLAG_LBA48)
 			qc->tf.flags |= ATA_TFLAG_LBA48;
 	}
@@ -2296,6 +2492,11 @@
 	return qc;
 }
 
+static int ata_qc_complete_noop(struct ata_queued_cmd *qc, u8 drv_stat)
+{
+	return 0;
+}
+
 /**
  *	ata_qc_complete - Complete an active ATA command
  *	@qc: Command to complete
@@ -2335,11 +2536,16 @@
 		do_clear = 1;
 	}
 
-	if (qc->waiting)
-		complete(qc->waiting);
+	if (qc->waiting) {
+		struct completion *waiting = qc->waiting;
+		qc->waiting = NULL;
+		complete(waiting);
+	}
 
 	if (likely(do_clear))
 		clear_bit(tag, &ap->qactive);
+
+	VPRINTK("EXIT\n");
 }
 
 /**
@@ -2422,6 +2628,12 @@
 		break;
 
 	case ATA_PROT_ATAPI:
+		ata_qc_set_polling(qc);
+		ata_tf_to_host_nolock(ap, &qc->tf);
+		queue_work(ata_wq, &ap->packet_task);
+		break;
+
+	case ATA_PROT_ATAPI_NODATA:
 		ata_tf_to_host_nolock(ap, &qc->tf);
 		queue_work(ata_wq, &ap->packet_task);
 		break;
@@ -2441,19 +2653,19 @@
 }
 
 /**
- *	ata_bmdma_setup_mmio - Set up PCI IDE BMDMA transaction (MMIO)
+ *	ata_bmdma_setup - Set up PCI IDE BMDMA transaction
  *	@qc: Info associated with this ATA transaction.
  *
  *	LOCKING:
  *	spin_lock_irqsave(host_set lock)
  */
 
-void ata_bmdma_setup_mmio (struct ata_queued_cmd *qc)
+static void ata_bmdma_setup_mmio (struct ata_queued_cmd *qc)
 {
 	struct ata_port *ap = qc->ap;
 	unsigned int rw = (qc->tf.flags & ATA_TFLAG_WRITE);
 	u8 dmactl;
-	void *mmio = (void *) ap->ioaddr.bmdma_addr;
+	void __iomem *mmio = (void __iomem *) ap->ioaddr.bmdma_addr;
 
 	/* load PRD table addr. */
 	mb();	/* make sure PRD table writes are visible to controller */
@@ -2471,17 +2683,17 @@
 }
 
 /**
- *	ata_bmdma_start_mmio - Start a PCI IDE BMDMA transaction (MMIO)
+ *	ata_bmdma_start - Start a PCI IDE BMDMA transaction
  *	@qc: Info associated with this ATA transaction.
  *
  *	LOCKING:
  *	spin_lock_irqsave(host_set lock)
  */
 
-void ata_bmdma_start_mmio (struct ata_queued_cmd *qc)
+static void ata_bmdma_start_mmio (struct ata_queued_cmd *qc)
 {
 	struct ata_port *ap = qc->ap;
-	void *mmio = (void *) ap->ioaddr.bmdma_addr;
+	void __iomem *mmio = (void __iomem *) ap->ioaddr.bmdma_addr;
 	u8 dmactl;
 
 	/* start host DMA transaction */
@@ -2509,7 +2721,7 @@
  *	spin_lock_irqsave(host_set lock)
  */
 
-void ata_bmdma_setup_pio (struct ata_queued_cmd *qc)
+static void ata_bmdma_setup_pio (struct ata_queued_cmd *qc)
 {
 	struct ata_port *ap = qc->ap;
 	unsigned int rw = (qc->tf.flags & ATA_TFLAG_WRITE);
@@ -2537,7 +2749,7 @@
  *	spin_lock_irqsave(host_set lock)
  */
 
-void ata_bmdma_start_pio (struct ata_queued_cmd *qc)
+static void ata_bmdma_start_pio (struct ata_queued_cmd *qc)
 {
 	struct ata_port *ap = qc->ap;
 	u8 dmactl;
@@ -2548,6 +2760,22 @@
 	     ap->ioaddr.bmdma_addr + ATA_DMA_CMD);
 }
 
+void ata_bmdma_start(struct ata_queued_cmd *qc)
+{
+	if (qc->ap->flags & ATA_FLAG_MMIO)
+		ata_bmdma_start_mmio(qc);
+	else
+		ata_bmdma_start_pio(qc);
+}
+
+void ata_bmdma_setup(struct ata_queued_cmd *qc)
+{
+	if (qc->ap->flags & ATA_FLAG_MMIO)
+		ata_bmdma_setup_mmio(qc);
+	else
+		ata_bmdma_setup_pio(qc);
+}
+
 void ata_bmdma_irq_clear(struct ata_port *ap)
 {
 	ata_bmdma_ack_irq(ap);
@@ -2581,7 +2809,7 @@
 	case ATA_PROT_ATAPI:
 		/* check status of DMA engine */
 		host_stat = ata_bmdma_status(ap);
-		VPRINTK("BUS_DMA (host_stat 0x%X)\n", host_stat);
+		VPRINTK("ata%u: host_stat 0x%X\n", ap->id, host_stat);
 
 		/* if it's not our irq... */
 		if (!(host_stat & ATA_DMA_INTR))
@@ -2592,6 +2820,7 @@
 
 		/* fall through */
 
+	case ATA_PROT_ATAPI_NODATA:
 	case ATA_PROT_NODATA:
 		/* check altstatus */
 		status = ata_altstatus(ap);
@@ -2602,7 +2831,8 @@
 		status = ata_chk_status(ap);
 		if (unlikely(status & ATA_BUSY))
 			goto idle_irq;
-		DPRINTK("BUS_NODATA (dev_stat 0x%X)\n", status);
+		DPRINTK("ata%u: protocol %d (dev_stat 0x%X)\n",
+			ap->id, qc->tf.protocol, status);
 
 		/* ack bmdma irq events */
 		ata_bmdma_ack_irq(ap);
@@ -2701,21 +2931,20 @@
 
 	/* make sure DRQ is set */
 	status = ata_chk_status(ap);
-	if ((status & ATA_DRQ) == 0)
+	if ((status & (ATA_BUSY | ATA_DRQ)) != ATA_DRQ)
 		goto err_out;
 
 	/* send SCSI cdb */
-	/* FIXME: mmio-ize */
 	DPRINTK("send cdb\n");
-	outsl(ap->ioaddr.data_addr,
-	      qc->scsicmd->cmnd, ap->host->max_cmd_len / 4);
+	assert(ap->cdb_len >= 12);
+	ata_data_xfer(ap, qc->cdb, ap->cdb_len, 1);
 
 	/* if we are DMA'ing, irq handler takes over from here */
 	if (qc->tf.protocol == ATA_PROT_ATAPI_DMA)
 		ap->ops->bmdma_start(qc);	    /* initiate bmdma */
 
 	/* non-data commands are also handled via irq */
-	else if (qc->scsicmd->sc_data_direction == SCSI_DATA_NONE) {
+	else if (qc->tf.protocol == ATA_PROT_ATAPI_NODATA) {
 		/* do nothing */
 	}
 
@@ -2804,11 +3033,11 @@
 	ap->host_set = host_set;
 	ap->port_no = port_no;
 	ap->pio_mask = ent->pio_mask;
+	ap->mwdma_mask = ent->mwdma_mask;
 	ap->udma_mask = ent->udma_mask;
 	ap->flags |= ent->host_flags;
 	ap->ops = ent->port_ops;
 	ap->cbl = ATA_CBL_NONE;
-	ap->device[0].flags = ATA_DFLAG_MASTER;
 	ap->active_tag = ATA_TAG_POISON;
 	ap->last_ctl = 0xFF;
 
@@ -2901,19 +3130,23 @@
 	/* register each port bound to this device */
 	for (i = 0; i < ent->n_ports; i++) {
 		struct ata_port *ap;
+		unsigned long xfer_mode_mask;
 
 		ap = ata_host_add(ent, host_set, i);
 		if (!ap)
 			goto err_out;
 
 		host_set->ports[i] = ap;
+		xfer_mode_mask =(ap->udma_mask << ATA_SHIFT_UDMA) |
+				(ap->mwdma_mask << ATA_SHIFT_MWDMA) |
+				(ap->pio_mask << ATA_SHIFT_PIO);
 
 		/* print per-port info to dmesg */
 		printk(KERN_INFO "ata%u: %cATA max %s cmd 0x%lX ctl 0x%lX "
 				 "bmdma 0x%lX irq %lu\n",
 			ap->id,
 			ap->flags & ATA_FLAG_SATA ? 'S' : 'P',
-			ata_udma_string(ent->udma_mask),
+			ata_mode_string(xfer_mode_mask),
 	       		ap->ioaddr.cmd_addr,
 	       		ap->ioaddr.ctl_addr,
 	       		ap->ioaddr.bmdma_addr,
@@ -3035,6 +3268,95 @@
 	ioaddr->command_addr = ioaddr->cmd_addr + ATA_REG_CMD;
 }
 
+static struct ata_probe_ent *
+ata_probe_ent_alloc(int n, struct pci_dev *pdev, struct ata_port_info **port)
+{
+	struct ata_probe_ent *probe_ent;
+	int i;
+
+	probe_ent = kmalloc(sizeof(*probe_ent) * n, GFP_KERNEL);
+	if (!probe_ent) {
+		printk(KERN_ERR DRV_NAME "(%s): out of memory\n",
+		       pci_name(pdev));
+		return NULL;
+	}
+
+	memset(probe_ent, 0, sizeof(*probe_ent) * n);
+
+	for (i = 0; i < n; i++) {
+		INIT_LIST_HEAD(&probe_ent[i].node);
+		probe_ent[i].pdev = pdev;
+
+		probe_ent[i].sht = port[i]->sht;
+		probe_ent[i].host_flags = port[i]->host_flags;
+		probe_ent[i].pio_mask = port[i]->pio_mask;
+		probe_ent[i].mwdma_mask = port[i]->mwdma_mask;
+		probe_ent[i].udma_mask = port[i]->udma_mask;
+		probe_ent[i].port_ops = port[i]->port_ops;
+
+	}
+
+	return probe_ent;
+}
+
+struct ata_probe_ent *
+ata_pci_init_native_mode(struct pci_dev *pdev, struct ata_port_info **port)
+{
+	struct ata_probe_ent *probe_ent = ata_probe_ent_alloc(1, pdev, port);
+	if (!probe_ent)
+		return NULL;
+
+	probe_ent->n_ports = 2;
+	probe_ent->irq = pdev->irq;
+	probe_ent->irq_flags = SA_SHIRQ;
+
+	probe_ent->port[0].cmd_addr = pci_resource_start(pdev, 0);
+	probe_ent->port[0].altstatus_addr =
+	probe_ent->port[0].ctl_addr =
+		pci_resource_start(pdev, 1) | ATA_PCI_CTL_OFS;
+	probe_ent->port[0].bmdma_addr = pci_resource_start(pdev, 4);
+
+	probe_ent->port[1].cmd_addr = pci_resource_start(pdev, 2);
+	probe_ent->port[1].altstatus_addr =
+	probe_ent->port[1].ctl_addr =
+		pci_resource_start(pdev, 3) | ATA_PCI_CTL_OFS;
+	probe_ent->port[1].bmdma_addr = pci_resource_start(pdev, 4) + 8;
+
+	ata_std_ports(&probe_ent->port[0]);
+	ata_std_ports(&probe_ent->port[1]);
+
+	return probe_ent;
+}
+
+struct ata_probe_ent *
+ata_pci_init_legacy_mode(struct pci_dev *pdev, struct ata_port_info **port)
+{
+	struct ata_probe_ent *probe_ent = ata_probe_ent_alloc(2, pdev, port);
+	if (!probe_ent)
+		return NULL;
+
+	probe_ent[0].n_ports = 1;
+	probe_ent[0].irq = 14;
+
+	probe_ent[1].n_ports = 1;
+	probe_ent[1].irq = 15;
+
+	probe_ent[0].port[0].cmd_addr = 0x1f0;
+	probe_ent[0].port[0].altstatus_addr =
+	probe_ent[0].port[0].ctl_addr = 0x3f6;
+	probe_ent[0].port[0].bmdma_addr = pci_resource_start(pdev, 4);
+
+	probe_ent[1].port[0].cmd_addr = 0x170;
+	probe_ent[1].port[0].altstatus_addr =
+	probe_ent[1].port[0].ctl_addr = 0x376;
+	probe_ent[1].port[0].bmdma_addr = pci_resource_start(pdev, 4)+8;
+
+	ata_std_ports(&probe_ent[0].port[0]);
+	ata_std_ports(&probe_ent[1].port[0]);
+
+	return probe_ent;
+}
+
 /**
  *	ata_pci_init_one - Initialize/register PCI IDE host controller
  *	@pdev: Controller to be initialized
@@ -3052,20 +3374,20 @@
 		      unsigned int n_ports)
 {
 	struct ata_probe_ent *probe_ent, *probe_ent2 = NULL;
-	struct ata_port_info *port0, *port1;
+	struct ata_port_info *port[2];
 	u8 tmp8, mask;
 	unsigned int legacy_mode = 0;
 	int rc;
 
 	DPRINTK("ENTER\n");
 
-	port0 = port_info[0];
+	port[0] = port_info[0];
 	if (n_ports > 1)
-		port1 = port_info[1];
+		port[1] = port_info[1];
 	else
-		port1 = port0;
+		port[1] = port[0];
 
-	if ((port0->host_flags & ATA_FLAG_NO_LEGACY) == 0) {
+	if ((port[0]->host_flags & ATA_FLAG_NO_LEGACY) == 0) {
 		/* TODO: support transitioning to native mode? */
 		pci_read_config_byte(pdev, PCI_CLASS_PROG, &tmp8);
 		mask = (1 << 2) | (1 << 0);
@@ -3126,75 +3448,17 @@
 	if (rc)
 		goto err_out_regions;
 
-	probe_ent = kmalloc(sizeof(*probe_ent), GFP_KERNEL);
+	if (legacy_mode) {
+		probe_ent = ata_pci_init_legacy_mode(pdev, port);
+		if (probe_ent)
+			probe_ent2 = &probe_ent[1];
+	} else
+		probe_ent = ata_pci_init_native_mode(pdev, port);
 	if (!probe_ent) {
 		rc = -ENOMEM;
 		goto err_out_regions;
 	}
 
-	memset(probe_ent, 0, sizeof(*probe_ent));
-	probe_ent->pdev = pdev;
-	INIT_LIST_HEAD(&probe_ent->node);
-
-	if (legacy_mode) {
-		probe_ent2 = kmalloc(sizeof(*probe_ent), GFP_KERNEL);
-		if (!probe_ent2) {
-			rc = -ENOMEM;
-			goto err_out_free_ent;
-		}
-
-		memset(probe_ent2, 0, sizeof(*probe_ent));
-		probe_ent2->pdev = pdev;
-		INIT_LIST_HEAD(&probe_ent2->node);
-	}
-
-	probe_ent->port[0].bmdma_addr = pci_resource_start(pdev, 4);
-	probe_ent->sht = port0->sht;
-	probe_ent->host_flags = port0->host_flags;
-	probe_ent->pio_mask = port0->pio_mask;
-	probe_ent->udma_mask = port0->udma_mask;
-	probe_ent->port_ops = port0->port_ops;
-
-	if (legacy_mode) {
-		probe_ent->port[0].cmd_addr = 0x1f0;
-		probe_ent->port[0].altstatus_addr =
-		probe_ent->port[0].ctl_addr = 0x3f6;
-		probe_ent->n_ports = 1;
-		probe_ent->irq = 14;
-		ata_std_ports(&probe_ent->port[0]);
-
-		probe_ent2->port[0].cmd_addr = 0x170;
-		probe_ent2->port[0].altstatus_addr =
-		probe_ent2->port[0].ctl_addr = 0x376;
-		probe_ent2->port[0].bmdma_addr = pci_resource_start(pdev, 4)+8;
-		probe_ent2->n_ports = 1;
-		probe_ent2->irq = 15;
-		ata_std_ports(&probe_ent2->port[0]);
-
-		probe_ent2->sht = port1->sht;
-		probe_ent2->host_flags = port1->host_flags;
-		probe_ent2->pio_mask = port1->pio_mask;
-		probe_ent2->udma_mask = port1->udma_mask;
-		probe_ent2->port_ops = port1->port_ops;
-	} else {
-		probe_ent->port[0].cmd_addr = pci_resource_start(pdev, 0);
-		ata_std_ports(&probe_ent->port[0]);
-		probe_ent->port[0].altstatus_addr =
-		probe_ent->port[0].ctl_addr =
-			pci_resource_start(pdev, 1) | ATA_PCI_CTL_OFS;
-
-		probe_ent->port[1].cmd_addr = pci_resource_start(pdev, 2);
-		ata_std_ports(&probe_ent->port[1]);
-		probe_ent->port[1].altstatus_addr =
-		probe_ent->port[1].ctl_addr =
-			pci_resource_start(pdev, 3) | ATA_PCI_CTL_OFS;
-		probe_ent->port[1].bmdma_addr = pci_resource_start(pdev, 4) + 8;
-
-		probe_ent->n_ports = 2;
-		probe_ent->irq = pdev->irq;
-		probe_ent->irq_flags = SA_SHIRQ;
-	}
-
 	pci_set_master(pdev);
 
 	/* FIXME: check ata_device_add return */
@@ -3203,17 +3467,13 @@
 			ata_device_add(probe_ent);
 		if (legacy_mode & (1 << 1))
 			ata_device_add(probe_ent2);
-		kfree(probe_ent2);
 	} else {
 		ata_device_add(probe_ent);
-		assert(probe_ent2 == NULL);
 	}
 	kfree(probe_ent);
 
 	return 0;
 
-err_out_free_ent:
-	kfree(probe_ent);
 err_out_regions:
 	if (legacy_mode & (1 << 0))
 		release_region(0x1f0, 8);
@@ -3363,34 +3623,35 @@
 EXPORT_SYMBOL_GPL(ata_qc_complete);
 EXPORT_SYMBOL_GPL(ata_qc_issue_prot);
 EXPORT_SYMBOL_GPL(ata_eng_timeout);
-EXPORT_SYMBOL_GPL(ata_tf_load_pio);
-EXPORT_SYMBOL_GPL(ata_tf_load_mmio);
-EXPORT_SYMBOL_GPL(ata_tf_read_pio);
-EXPORT_SYMBOL_GPL(ata_tf_read_mmio);
+EXPORT_SYMBOL_GPL(ata_tf_load);
+EXPORT_SYMBOL_GPL(ata_tf_read);
+EXPORT_SYMBOL_GPL(ata_noop_dev_select);
+EXPORT_SYMBOL_GPL(ata_std_dev_select);
 EXPORT_SYMBOL_GPL(ata_tf_to_fis);
 EXPORT_SYMBOL_GPL(ata_tf_from_fis);
-EXPORT_SYMBOL_GPL(ata_check_status_pio);
-EXPORT_SYMBOL_GPL(ata_check_status_mmio);
-EXPORT_SYMBOL_GPL(ata_exec_command_pio);
-EXPORT_SYMBOL_GPL(ata_exec_command_mmio);
+EXPORT_SYMBOL_GPL(ata_pci_init_legacy_mode);
+EXPORT_SYMBOL_GPL(ata_pci_init_native_mode);
+EXPORT_SYMBOL_GPL(ata_check_status);
+EXPORT_SYMBOL_GPL(ata_exec_command);
 EXPORT_SYMBOL_GPL(ata_port_start);
 EXPORT_SYMBOL_GPL(ata_port_stop);
 EXPORT_SYMBOL_GPL(ata_interrupt);
 EXPORT_SYMBOL_GPL(ata_qc_prep);
-EXPORT_SYMBOL_GPL(ata_bmdma_setup_pio);
-EXPORT_SYMBOL_GPL(ata_bmdma_start_pio);
-EXPORT_SYMBOL_GPL(ata_bmdma_setup_mmio);
-EXPORT_SYMBOL_GPL(ata_bmdma_start_mmio);
+EXPORT_SYMBOL_GPL(ata_bmdma_setup);
+EXPORT_SYMBOL_GPL(ata_bmdma_start);
 EXPORT_SYMBOL_GPL(ata_bmdma_irq_clear);
 EXPORT_SYMBOL_GPL(ata_port_probe);
 EXPORT_SYMBOL_GPL(sata_phy_reset);
+EXPORT_SYMBOL_GPL(__sata_phy_reset);
 EXPORT_SYMBOL_GPL(ata_bus_reset);
 EXPORT_SYMBOL_GPL(ata_port_disable);
 EXPORT_SYMBOL_GPL(ata_pci_init_one);
 EXPORT_SYMBOL_GPL(ata_pci_remove_one);
+EXPORT_SYMBOL_GPL(ata_scsi_ioctl);
 EXPORT_SYMBOL_GPL(ata_scsi_queuecmd);
 EXPORT_SYMBOL_GPL(ata_scsi_error);
 EXPORT_SYMBOL_GPL(ata_scsi_slave_config);
 EXPORT_SYMBOL_GPL(ata_scsi_release);
 EXPORT_SYMBOL_GPL(ata_host_intr);
+EXPORT_SYMBOL_GPL(ata_dev_classify);
 EXPORT_SYMBOL_GPL(ata_dev_id_string);
diff -Nru a/drivers/scsi/libata-scsi.c b/drivers/scsi/libata-scsi.c
--- a/drivers/scsi/libata-scsi.c	2004-10-18 14:56:28 -07:00
+++ b/drivers/scsi/libata-scsi.c	2004-10-18 14:56:28 -07:00
@@ -29,6 +29,7 @@
 #include "scsi.h"
 #include <scsi/scsi_host.h>
 #include <linux/libata.h>
+#include <asm/uaccess.h>
 
 #include "libata.h"
 
@@ -36,6 +37,8 @@
 static void ata_scsi_simulate(struct ata_port *ap, struct ata_device *dev,
 			      struct scsi_cmnd *cmd,
 			      void (*done)(struct scsi_cmnd *));
+static struct ata_device *
+ata_scsi_find_dev(struct ata_port *ap, struct scsi_device *scsidev);
 
 
 /**
@@ -67,6 +70,43 @@
 	return 0;
 }
 
+int ata_scsi_ioctl(struct scsi_device *scsidev, int cmd, void __user *arg)
+{
+	struct ata_port *ap;
+	struct ata_device *dev;
+	int val = -EINVAL, rc = -EINVAL;
+
+	ap = (struct ata_port *) &scsidev->host->hostdata[0];
+	if (!ap)
+		goto out;
+
+	dev = ata_scsi_find_dev(ap, scsidev);
+	if (!dev) {
+		rc = -ENODEV;
+		goto out;
+	}
+
+	switch (cmd) {
+	case ATA_IOC_GET_IO32:
+		val = 0;
+		if (copy_to_user(arg, &val, 1))
+			return -EFAULT;
+		return 0;
+
+	case ATA_IOC_SET_IO32:
+		val = (unsigned long) arg;
+		if (val != 0)
+			return -EINVAL;
+		return 0;
+
+	default:
+		rc = -EOPNOTSUPP;
+		break;
+	}
+
+out:
+	return rc;
+}
 
 /**
  *	ata_scsi_qc_new - acquire new ata_queued_cmd reference
@@ -120,34 +160,158 @@
  *	ata_to_sense_error - convert ATA error to SCSI error
  *	@qc: Command that we are erroring out
  *
- *	Converts an ATA error into a SCSI error.
- *
- *	Right now, this routine is laughably primitive.  We
- *	don't even examine what ATA told us, we just look at
- *	the command data direction, and return a fatal SCSI
- *	sense error based on that.
+ *	Converts an ATA error into a SCSI error. While we are at it
+ *	we decode and dump the ATA error for the user so that they
+ *	have some idea what really happened at the non make-believe
+ *	layer.
  *
  *	LOCKING:
  *	spin_lock_irqsave(host_set lock)
  */
 
-void ata_to_sense_error(struct ata_queued_cmd *qc)
+void ata_to_sense_error(struct ata_queued_cmd *qc, u8 drv_stat)
 {
 	struct scsi_cmnd *cmd = qc->scsicmd;
+	u8 err = 0;
+	unsigned char *sb = cmd->sense_buffer;
+	/* Based on the 3ware driver translation table */
+	static unsigned char sense_table[][4] = {
+		/* BBD|ECC|ID|MAR */
+		{0xd1, 		ABORTED_COMMAND, 0x00, 0x00}, 	// Device busy                  Aborted command
+		/* BBD|ECC|ID */
+		{0xd0,  	ABORTED_COMMAND, 0x00, 0x00}, 	// Device busy                  Aborted command
+		/* ECC|MC|MARK */
+		{0x61, 		HARDWARE_ERROR, 0x00, 0x00}, 	// Device fault                 Hardware error
+		/* ICRC|ABRT */		/* NB: ICRC & !ABRT is BBD */
+		{0x84, 		ABORTED_COMMAND, 0x47, 0x00}, 	// Data CRC error               SCSI parity error
+		/* MC|ID|ABRT|TRK0|MARK */
+		{0x37, 		NOT_READY, 0x04, 0x00}, 	// Unit offline                 Not ready
+		/* MCR|MARK */
+		{0x09, 		NOT_READY, 0x04, 0x00}, 	// Unrecovered disk error       Not ready
+		/*  Bad address mark */
+		{0x01, 		MEDIUM_ERROR, 0x13, 0x00}, 	// Address mark not found       Address mark not found for data field
+		/* TRK0 */
+		{0x02, 		HARDWARE_ERROR, 0x00, 0x00}, 	// Track 0 not found		  Hardware error
+		/* Abort & !ICRC */
+		{0x04, 		ABORTED_COMMAND, 0x00, 0x00}, 	// Aborted command              Aborted command
+		/* Media change request */
+		{0x08, 		NOT_READY, 0x04, 0x00}, 	// Media change request	  FIXME: faking offline
+		/* SRV */
+		{0x10, 		ABORTED_COMMAND, 0x14, 0x00}, 	// ID not found                 Recorded entity not found
+		/* Media change */
+		{0x08,  	NOT_READY, 0x04, 0x00}, 	// Media change		  FIXME: faking offline
+		/* ECC */
+		{0x40, 		MEDIUM_ERROR, 0x11, 0x04}, 	// Uncorrectable ECC error      Unrecovered read error
+		/* BBD - block marked bad */
+		{0x80, 		MEDIUM_ERROR, 0x11, 0x04}, 	// Block marked bad		  Medium error, unrecovered read error
+		{0xFF, 0xFF, 0xFF, 0xFF}, // END mark 
+	};
+	static unsigned char stat_table[][4] = {
+		/* Must be first because BUSY means no other bits valid */
+		{0x80, 		ABORTED_COMMAND, 0x47, 0x00},	// Busy, fake parity for now
+		{0x20, 		HARDWARE_ERROR,  0x00, 0x00}, 	// Device fault
+		{0x08, 		ABORTED_COMMAND, 0x47, 0x00},	// Timed out in xfer, fake parity for now
+		{0x04, 		RECOVERED_ERROR, 0x11, 0x00},	// Recovered ECC error	  Medium error, recovered
+		{0xFF, 0xFF, 0xFF, 0xFF}, // END mark 
+	};
+	int i = 0;
 
 	cmd->result = SAM_STAT_CHECK_CONDITION;
-
-	cmd->sense_buffer[0] = 0x70;
-	cmd->sense_buffer[2] = MEDIUM_ERROR;
-	cmd->sense_buffer[7] = 14 - 8;	/* addnl. sense len. FIXME: correct? */
-
+	
+	/*
+	 *	Is this an error we can process/parse
+	 */
+	 
+	if(drv_stat & ATA_ERR)
+		/* Read the err bits */
+		err = ata_chk_err(qc->ap);
+
+	/* Display the ATA level error info */
+	
+	printk(KERN_WARNING "ata%u: status=0x%02x { ", qc->ap->id, drv_stat);
+	if(drv_stat & 0x80)
+	{
+		printk("Busy ");
+		err = 0;	/* Data is not valid in this case */
+	}
+	else {
+		if(drv_stat & 0x40)	printk("DriveReady ");
+		if(drv_stat & 0x20)	printk("DeviceFault ");
+		if(drv_stat & 0x10)	printk("SeekComplete ");
+		if(drv_stat & 0x08)	printk("DataRequest ");
+		if(drv_stat & 0x04)	printk("CorrectedError ");
+		if(drv_stat & 0x02)	printk("Index ");
+		if(drv_stat & 0x01)	printk("Error ");
+	}
+	printk("}\n");
+	
+	if(err)
+	{
+		printk(KERN_WARNING "ata%u: error=0x%02x { ", qc->ap->id, err);
+		if(err & 0x04)		printk("DriveStatusError ");
+		if(err & 0x80)
+		{
+			if(err & 0x04)
+				printk("BadCRC ");
+			else
+				printk("Sector ");
+		}
+		if(err & 0x40)		printk("UncorrectableError ");
+		if(err & 0x10)		printk("SectorIdNotFound ");
+		if(err & 0x02)		printk("TrackZeroNotFound ");
+		if(err & 0x01)		printk("AddrMarkNotFound ");
+		printk("}\n");
+		
+		/* Should we dump sector info here too ?? */
+	}
+		
+	
+	/* Look for err */
+	while(sense_table[i][0] != 0xFF)
+	{
+		/* Look for best matches first */
+		if((sense_table[i][0] & err) == sense_table[i][0])
+		{
+			sb[0] = 0x70;
+			sb[2] = sense_table[i][1];
+			sb[7] = 0x0a;
+			sb[12] = sense_table[i][2];
+			sb[13] = sense_table[i][3];
+			return;
+		}
+		i++;
+	}
+	/* No immediate match */
+	if(err)
+		printk(KERN_DEBUG "ata%u: no sense translation for 0x%02x\n", qc->ap->id, err);
+	
+	/* Fall back to interpreting status bits */
+	while(stat_table[i][0] != 0xFF)
+	{
+		if(stat_table[i][0] & drv_stat)
+		{
+			sb[0] = 0x70;
+			sb[2] = stat_table[i][1];
+			sb[7] = 0x0a;
+			sb[12] = stat_table[i][2];
+			sb[13] = stat_table[i][3];
+			return;
+		}
+		i++;
+	}
+	/* No error ?? */
+	printk(KERN_ERR "ata%u: called with no error (%02X)!\n", qc->ap->id, drv_stat);
 	/* additional-sense-code[-qualifier] */
+	
+	sb[0] = 0x70;
+	sb[2] = MEDIUM_ERROR;
+	sb[7] = 0x0A;
 	if (cmd->sc_data_direction == SCSI_DATA_READ) {
-		cmd->sense_buffer[12] = 0x11; /* "unrecovered read error" */
-		cmd->sense_buffer[13] = 0x04;
+		sb[12] = 0x11; /* "unrecovered read error" */
+		sb[13] = 0x04;
 	} else {
-		cmd->sense_buffer[12] = 0x0C; /* "write error -             */
-		cmd->sense_buffer[13] = 0x02; /*  auto-reallocation failed" */
+		sb[12] = 0x0C; /* "write error -             */
+		sb[13] = 0x02; /*  auto-reallocation failed" */
 	}
 }
 
@@ -214,11 +378,135 @@
 	ap = (struct ata_port *) &host->hostdata[0];
 	ap->ops->eng_timeout(ap);
 
+	/* TODO: this is per-command; when queueing is supported
+	 * this code will either change or move to a more
+	 * appropriate place
+	 */
+	host->host_failed--;
+
 	DPRINTK("EXIT\n");
 	return 0;
 }
 
 /**
+ *	ata_scsi_flush_xlat - Translate SCSI SYNCHRONIZE CACHE command
+ *	@qc: Storage for translated ATA taskfile
+ *	@scsicmd: SCSI command to translate (ignored)
+ *
+ *	Sets up an ATA taskfile to issue FLUSH CACHE or
+ *	FLUSH CACHE EXT.
+ *
+ *	LOCKING:
+ *	spin_lock_irqsave(host_set lock)
+ *
+ *	RETURNS:
+ *	Zero on success, non-zero on error.
+ */
+
+static unsigned int ata_scsi_flush_xlat(struct ata_queued_cmd *qc, u8 *scsicmd)
+{
+	struct ata_taskfile *tf = &qc->tf;
+
+	tf->flags |= ATA_TFLAG_DEVICE;
+	tf->protocol = ATA_PROT_NODATA;
+
+	if ((tf->flags & ATA_TFLAG_LBA48) &&
+	    (ata_id_has_flush_ext(qc->dev)))
+		tf->command = ATA_CMD_FLUSH_EXT;
+	else
+		tf->command = ATA_CMD_FLUSH;
+
+	return 0;
+}
+
+/**
+ *	ata_scsi_verify_xlat - Translate SCSI VERIFY command into an ATA one
+ *	@qc: Storage for translated ATA taskfile
+ *	@scsicmd: SCSI command to translate
+ *
+ *	Converts SCSI VERIFY command to an ATA READ VERIFY command.
+ *
+ *	LOCKING:
+ *	spin_lock_irqsave(host_set lock)
+ *
+ *	RETURNS:
+ *	Zero on success, non-zero on error.
+ */
+
+static unsigned int ata_scsi_verify_xlat(struct ata_queued_cmd *qc, u8 *scsicmd)
+{
+	struct ata_taskfile *tf = &qc->tf;
+	unsigned int lba48 = tf->flags & ATA_TFLAG_LBA48;
+	u64 dev_sectors = qc->dev->n_sectors;
+	u64 sect = 0;
+	u32 n_sect = 0;
+
+	tf->flags |= ATA_TFLAG_ISADDR | ATA_TFLAG_DEVICE;
+	tf->protocol = ATA_PROT_NODATA;
+	tf->device |= ATA_LBA;
+
+	if (scsicmd[0] == VERIFY) {
+		sect |= ((u64)scsicmd[2]) << 24;
+		sect |= ((u64)scsicmd[3]) << 16;
+		sect |= ((u64)scsicmd[4]) << 8;
+		sect |= ((u64)scsicmd[5]);
+
+		n_sect |= ((u32)scsicmd[7]) << 8;
+		n_sect |= ((u32)scsicmd[8]);
+	}
+
+	else if (scsicmd[0] == VERIFY_16) {
+		sect |= ((u64)scsicmd[2]) << 56;
+		sect |= ((u64)scsicmd[3]) << 48;
+		sect |= ((u64)scsicmd[4]) << 40;
+		sect |= ((u64)scsicmd[5]) << 32;
+		sect |= ((u64)scsicmd[6]) << 24;
+		sect |= ((u64)scsicmd[7]) << 16;
+		sect |= ((u64)scsicmd[8]) << 8;
+		sect |= ((u64)scsicmd[9]);
+
+		n_sect |= ((u32)scsicmd[10]) << 24;
+		n_sect |= ((u32)scsicmd[11]) << 16;
+		n_sect |= ((u32)scsicmd[12]) << 8;
+		n_sect |= ((u32)scsicmd[13]);
+	}
+
+	else
+		return 1;
+
+	if (!n_sect)
+		return 1;
+	if (sect >= dev_sectors)
+		return 1;
+	if ((sect + n_sect) > dev_sectors)
+		return 1;
+	if (lba48) {
+		if (n_sect > (64 * 1024))
+			return 1;
+	} else {
+		if (n_sect > 256)
+			return 1;
+	}
+
+	if (lba48) {
+		tf->hob_nsect = (n_sect >> 8) & 0xff;
+
+		tf->hob_lbah = (sect >> 40) & 0xff;
+		tf->hob_lbam = (sect >> 32) & 0xff;
+		tf->hob_lbal = (sect >> 24) & 0xff;
+	} else
+		tf->device |= (sect >> 24) & 0xf;
+
+	tf->nsect = n_sect & 0xff;
+
+	tf->hob_lbah = (sect >> 16) & 0xff;
+	tf->hob_lbam = (sect >> 8) & 0xff;
+	tf->hob_lbal = sect & 0xff;
+
+	return 0;
+}
+
+/**
  *	ata_scsi_rw_xlat - Translate SCSI r/w command into an ATA one
  *	@qc: Storage for translated ATA taskfile
  *	@scsicmd: SCSI command to translate
@@ -244,10 +532,6 @@
 	unsigned int lba48 = tf->flags & ATA_TFLAG_LBA48;
 
 	tf->flags |= ATA_TFLAG_ISADDR | ATA_TFLAG_DEVICE;
-	tf->hob_nsect = 0;
-	tf->hob_lbal = 0;
-	tf->hob_lbam = 0;
-	tf->hob_lbah = 0;
 	tf->protocol = qc->dev->xfer_protocol;
 	tf->device |= ATA_LBA;
 
@@ -339,14 +623,10 @@
 {
 	struct scsi_cmnd *cmd = qc->scsicmd;
 
-	if (unlikely(drv_stat & (ATA_ERR | ATA_BUSY | ATA_DRQ))) {
-		if (is_atapi_taskfile(&qc->tf))
-			cmd->result = SAM_STAT_CHECK_CONDITION;
-		else
-			ata_to_sense_error(qc);
-	} else {
+	if (unlikely(drv_stat & (ATA_ERR | ATA_BUSY | ATA_DRQ)))
+		ata_to_sense_error(qc, drv_stat);
+	else
 		cmd->result = SAM_STAT_GOOD;
-	}
 
 	qc->scsidone(cmd);
 
@@ -534,7 +814,7 @@
 		0,
 		0x5,	/* claim SPC-3 version compatibility */
 		2,
-		96 - 4
+		95 - 4
 	};
 
 	/* set scsi removeable (RMB) bit per ata bit */
@@ -545,7 +825,7 @@
 
 	memcpy(rbuf, hdr, sizeof(hdr));
 
-	if (buflen > 36) {
+	if (buflen > 35) {
 		memcpy(&rbuf[8], "ATA     ", 8);
 		ata_dev_id_string(dev, &rbuf[16], ATA_ID_PROD_OFS, 16);
 		ata_dev_id_string(dev, &rbuf[32], ATA_ID_FW_REV_OFS, 4);
@@ -964,6 +1244,31 @@
 	done(cmd);
 }
 
+static int atapi_qc_complete(struct ata_queued_cmd *qc, u8 drv_stat)
+{
+	struct scsi_cmnd *cmd = qc->scsicmd;
+
+	if (unlikely(drv_stat & (ATA_ERR | ATA_BUSY | ATA_DRQ)))
+		cmd->result = SAM_STAT_CHECK_CONDITION;
+	else {
+		u8 *scsicmd = cmd->cmnd;
+
+		if (scsicmd[0] == INQUIRY) {
+			u8 *buf = NULL;
+			unsigned int buflen;
+
+			buflen = ata_scsi_rbuf_get(cmd, &buf);
+			buf[2] = 0x5;
+			buf[3] = (buf[3] & 0xf0) | 2;
+			ata_scsi_rbuf_put(cmd);
+		}
+		cmd->result = SAM_STAT_GOOD;
+	}
+
+	qc->scsidone(cmd);
+
+	return 0;
+}
 /**
  *	atapi_xlat - Initialize PACKET taskfile
  *	@qc: command structure to be initialized
@@ -979,6 +1284,13 @@
 static unsigned int atapi_xlat(struct ata_queued_cmd *qc, u8 *scsicmd)
 {
 	struct scsi_cmnd *cmd = qc->scsicmd;
+	struct ata_device *dev = qc->dev;
+	int using_pio = (dev->flags & ATA_DFLAG_PIO);
+	int nodata = (cmd->sc_data_direction == SCSI_DATA_NONE);
+
+	memcpy(&qc->cdb, scsicmd, qc->ap->cdb_len);
+
+	qc->complete_fn = atapi_qc_complete;
 
 	qc->tf.flags |= ATA_TFLAG_ISADDR | ATA_TFLAG_DEVICE;
 	if (cmd->sc_data_direction == SCSI_DATA_WRITE) {
@@ -988,19 +1300,18 @@
 
 	qc->tf.command = ATA_CMD_PACKET;
 
-	/* no data - interrupt-driven */
-	if (cmd->sc_data_direction == SCSI_DATA_NONE)
-		qc->tf.protocol = ATA_PROT_ATAPI;
-
-	/* PIO data xfer - polling */
-	else if ((qc->flags & ATA_QCFLAG_DMA) == 0) {
-		ata_qc_set_polling(qc);
-		qc->tf.protocol = ATA_PROT_ATAPI;
+	/* no data, or PIO data xfer */
+	if (using_pio || nodata) {
+		if (nodata)
+			qc->tf.protocol = ATA_PROT_ATAPI_NODATA;
+		else
+			qc->tf.protocol = ATA_PROT_ATAPI;
 		qc->tf.lbam = (8 * 1024) & 0xff;
 		qc->tf.lbah = (8 * 1024) >> 8;
+	}
 
-	/* DMA data xfer - interrupt-driven */
-	} else {
+	/* DMA data xfer */
+	else {
 		qc->tf.protocol = ATA_PROT_ATAPI_DMA;
 		qc->tf.feature |= ATAPI_PKT_DMA;
 
@@ -1031,19 +1342,19 @@
  *	Associated ATA device, or %NULL if not found.
  */
 
-static inline struct ata_device *
-ata_scsi_find_dev(struct ata_port *ap, struct scsi_cmnd *cmd)
+static struct ata_device *
+ata_scsi_find_dev(struct ata_port *ap, struct scsi_device *scsidev)
 {
 	struct ata_device *dev;
 
 	/* skip commands not addressed to targets we simulate */
-	if (likely(cmd->device->id < ATA_MAX_DEVICES))
-		dev = &ap->device[cmd->device->id];
+	if (likely(scsidev->id < ATA_MAX_DEVICES))
+		dev = &ap->device[scsidev->id];
 	else
 		return NULL;
 
-	if (unlikely((cmd->device->channel != 0) ||
-		     (cmd->device->lun != 0)))
+	if (unlikely((scsidev->channel != 0) ||
+		     (scsidev->lun != 0)))
 		return NULL;
 
 	if (unlikely(!ata_dev_present(dev)))
@@ -1059,6 +1370,7 @@
 
 /**
  *	ata_get_xlat_func - check if SCSI to ATA translation is possible
+ *	@dev: ATA device
  *	@cmd: SCSI command opcode to consider
  *
  *	Look up the SCSI command given, and determine whether the
@@ -1068,7 +1380,7 @@
  *	Pointer to translation function if possible, %NULL if not.
  */
 
-static inline ata_xlat_func_t ata_get_xlat_func(u8 cmd)
+static inline ata_xlat_func_t ata_get_xlat_func(struct ata_device *dev, u8 cmd)
 {
 	switch (cmd) {
 	case READ_6:
@@ -1079,6 +1391,15 @@
 	case WRITE_10:
 	case WRITE_16:
 		return ata_scsi_rw_xlat;
+
+	case SYNCHRONIZE_CACHE:
+		if (ata_try_flush_cache(dev))
+			return ata_scsi_flush_xlat;
+		break;
+
+	case VERIFY:
+	case VERIFY_16:
+		return ata_scsi_verify_xlat;
 	}
 
 	return NULL;
@@ -1096,11 +1417,12 @@
 				     struct scsi_cmnd *cmd)
 {
 #ifdef ATA_DEBUG
+	struct scsi_device *scsidev = cmd->device;
 	u8 *scsicmd = cmd->cmnd;
 
 	DPRINTK("CDB (%u:%d,%d,%d) %02x %02x %02x %02x %02x %02x %02x %02x %02x\n",
 		ap->id,
-		cmd->device->channel, cmd->device->id, cmd->device->lun,
+		scsidev->channel, scsidev->id, scsidev->lun,
 		scsicmd[0], scsicmd[1], scsicmd[2], scsicmd[3],
 		scsicmd[4], scsicmd[5], scsicmd[6], scsicmd[7],
 		scsicmd[8]);
@@ -1130,12 +1452,13 @@
 {
 	struct ata_port *ap;
 	struct ata_device *dev;
+	struct scsi_device *scsidev = cmd->device;
 
-	ap = (struct ata_port *) &cmd->device->host->hostdata[0];
+	ap = (struct ata_port *) &scsidev->host->hostdata[0];
 
 	ata_scsi_dump_cdb(ap, cmd);
 
-	dev = ata_scsi_find_dev(ap, cmd);
+	dev = ata_scsi_find_dev(ap, scsidev);
 	if (unlikely(!dev)) {
 		cmd->result = (DID_BAD_TARGET << 16);
 		done(cmd);
@@ -1143,7 +1466,8 @@
 	}
 
 	if (dev->class == ATA_DEV_ATA) {
-		ata_xlat_func_t xlat_func = ata_get_xlat_func(cmd->cmnd[0]);
+		ata_xlat_func_t xlat_func = ata_get_xlat_func(dev,
+							      cmd->cmnd[0]);
 
 		if (xlat_func)
 			ata_scsi_translate(ap, dev, cmd, done, xlat_func);
@@ -1184,7 +1508,7 @@
 
 	switch(scsicmd[0]) {
 		/* no-op's, complete with success */
-		case SYNCHRONIZE_CACHE:		/* FIXME: temporary */
+		case SYNCHRONIZE_CACHE:
 		case REZERO_UNIT:
 		case SEEK_6:
 		case SEEK_10:
diff -Nru a/drivers/scsi/libata.h b/drivers/scsi/libata.h
--- a/drivers/scsi/libata.h	2004-10-18 14:56:17 -07:00
+++ b/drivers/scsi/libata.h	2004-10-18 14:56:17 -07:00
@@ -42,10 +42,11 @@
 extern void ata_dev_select(struct ata_port *ap, unsigned int device,
                            unsigned int wait, unsigned int can_sleep);
 extern void ata_tf_to_host_nolock(struct ata_port *ap, struct ata_taskfile *tf);
+extern void swap_buf_le16(u16 *buf, unsigned int buf_words);
 
 
 /* libata-scsi.c */
-extern void ata_to_sense_error(struct ata_queued_cmd *qc);
+extern void ata_to_sense_error(struct ata_queued_cmd *qc, u8 drv_stat);
 extern int ata_scsi_error(struct Scsi_Host *host);
 extern unsigned int ata_scsiop_inq_std(struct ata_scsi_args *args, u8 *rbuf,
 			       unsigned int buflen);
diff -Nru a/drivers/scsi/mac_scsi.c b/drivers/scsi/mac_scsi.c
--- a/drivers/scsi/mac_scsi.c	2004-10-18 14:55:54 -07:00
+++ b/drivers/scsi/mac_scsi.c	2004-10-18 14:55:54 -07:00
@@ -326,6 +326,7 @@
 {
 	if (shpnt->irq != SCSI_IRQ_NONE)
 		free_irq (shpnt->irq, NCR5380_intr);
+	NCR5380_exit(shpnt);
 
 	return 0;
 }
diff -Nru a/drivers/scsi/mca_53c9x.c b/drivers/scsi/mca_53c9x.c
--- a/drivers/scsi/mca_53c9x.c	2004-10-18 14:56:27 -07:00
+++ b/drivers/scsi/mca_53c9x.c	2004-10-18 14:56:27 -07:00
@@ -238,15 +238,15 @@
 
 			/* Optional functions */
 
-			esp->dma_barrier = 0;
-			esp->dma_drain = 0;
-			esp->dma_invalidate = 0;
-			esp->dma_irq_entry = 0;
-			esp->dma_irq_exit = 0;
+			esp->dma_barrier = NULL;
+			esp->dma_drain = NULL;
+			esp->dma_invalidate = NULL;
+			esp->dma_irq_entry = NULL;
+			esp->dma_irq_exit = NULL;
 			esp->dma_led_on = dma_led_on;
 			esp->dma_led_off = dma_led_off;
-			esp->dma_poll = 0;
-			esp->dma_reset = 0;
+			esp->dma_poll = NULL;
+			esp->dma_reset = NULL;
 
 			/* Set the command buffer */
 
diff -Nru a/drivers/scsi/megaraid/Kconfig.megaraid b/drivers/scsi/megaraid/Kconfig.megaraid
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/drivers/scsi/megaraid/Kconfig.megaraid	2004-10-18 14:57:21 -07:00
@@ -0,0 +1,77 @@
+config MEGARAID_NEWGEN
+	bool "LSI Logic New Generation RAID Device Drivers"
+	depends on PCI && SCSI
+	help
+	LSI Logic RAID Device Drivers
+
+config MEGARAID_MM
+	tristate "LSI Logic Management Module (New Driver)"
+	depends on PCI && SCSI && MEGARAID_NEWGEN
+	help
+	Management Module provides ioctl, sysfs support for LSI Logic
+	RAID controllers.
+	To compile this driver as a module, choose M here: the
+	module will be called megaraid_mm
+
+
+config MEGARAID_MAILBOX
+	tristate "LSI Logic MegaRAID Driver (New Driver)"
+	depends on PCI && SCSI && MEGARAID_MM
+	help
+	List of supported controllers
+
+	OEM	Product Name		VID :DID :SVID:SSID
+	---	------------		---- ---- ---- ----
+	Dell PERC3/QC			101E:1960:1028:0471
+	Dell PERC3/DC			101E:1960:1028:0493
+	Dell PERC3/SC			101E:1960:1028:0475
+	Dell PERC3/Di			1028:000E:1028:0123
+	Dell PERC4/SC			1000:1960:1028:0520
+	Dell PERC4/DC			1000:1960:1028:0518
+	Dell PERC4/QC			1000:0407:1028:0531
+	Dell PERC4/Di			1028:000F:1028:014A
+	Dell PERC 4e/Si			1028:0013:1028:016c
+	Dell PERC 4e/Di			1028:0013:1028:016d
+	Dell PERC 4e/Di			1028:0013:1028:016e
+	Dell PERC 4e/Di			1028:0013:1028:016f
+	Dell PERC 4e/Di			1028:0013:1028:0170
+	Dell PERC 4e/DC			1000:0408:1028:0002
+	Dell PERC 4e/SC			1000:0408:1028:0001
+	LSI MegaRAID SCSI 320-0		1000:1960:1000:A520
+	LSI MegaRAID SCSI 320-1		1000:1960:1000:0520
+	LSI MegaRAID SCSI 320-2		1000:1960:1000:0518
+	LSI MegaRAID SCSI 320-0X	1000:0407:1000:0530
+	LSI MegaRAID SCSI 320-2X	1000:0407:1000:0532
+	LSI MegaRAID SCSI 320-4X	1000:0407:1000:0531
+	LSI MegaRAID SCSI 320-1E	1000:0408:1000:0001
+	LSI MegaRAID SCSI 320-2E	1000:0408:1000:0002
+	LSI MegaRAID SATA 150-4		1000:1960:1000:4523
+	LSI MegaRAID SATA 150-6		1000:1960:1000:0523
+	LSI MegaRAID SATA 300-4X	1000:0409:1000:3004
+	LSI MegaRAID SATA 300-8X	1000:0409:1000:3008
+	INTEL RAID Controller SRCU42X	1000:0407:8086:0532
+	INTEL RAID Controller SRCS16	1000:1960:8086:0523
+	INTEL RAID Controller SRCU42E	1000:0408:8086:0002
+	INTEL RAID Controller SRCZCRX	1000:0407:8086:0530
+	INTEL RAID Controller SRCS28X	1000:0409:8086:3008
+	INTEL RAID Controller SROMBU42E	1000:0408:8086:3431
+	INTEL RAID Controller SROMBU42E	1000:0408:8086:3499
+	INTEL RAID Controller SRCU51L	1000:1960:8086:0520
+	FSC MegaRAID PCI Express ROMB	1000:0408:1734:1065
+	ACER MegaRAID ROMB-2E		1000:0408:1025:004D
+
+	To compile this driver as a module, choose M here: the
+	module will be called megaraid_mbox
+
+if MEGARAID_NEWGEN=n
+config MEGARAID_LEGACY
+	tristate "LSI Logic Legacy MegaRAID Driver"
+	depends on PCI && SCSI
+	help
+	This driver supports the LSI MegaRAID 418, 428, 438, 466, 762, 490
+	and 467 SCSI host adapters. This driver also support the all U320
+	RAID controllers
+
+	To compile this driver as a module, choose M here: the
+	module will be called megaraid
+endif
diff -Nru a/drivers/scsi/megaraid/Makefile b/drivers/scsi/megaraid/Makefile
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/drivers/scsi/megaraid/Makefile	2004-10-18 14:57:24 -07:00
@@ -0,0 +1,2 @@
+obj-$(CONFIG_MEGARAID_MM)	+= megaraid_mm.o
+obj-$(CONFIG_MEGARAID_MAILBOX)	+= megaraid_mbox.o
diff -Nru a/drivers/scsi/megaraid/mbox_defs.h b/drivers/scsi/megaraid/mbox_defs.h
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/drivers/scsi/megaraid/mbox_defs.h	2004-10-18 14:57:24 -07:00
@@ -0,0 +1,790 @@
+/*
+ *
+ *			Linux MegaRAID Unified device driver
+ *
+ * Copyright (c) 2003-2004  LSI Logic 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.
+ *
+ * FILE		: mbox_defs.h
+ *
+ */
+#ifndef _MRAID_MBOX_DEFS_H_
+#define _MRAID_MBOX_DEFS_H_
+
+#include <linux/types.h>
+
+/*
+ * Commands and states for mailbox based controllers
+ */
+
+#define MBOXCMD_LREAD		0x01
+#define MBOXCMD_LWRITE		0x02
+#define MBOXCMD_PASSTHRU	0x03
+#define MBOXCMD_ADPEXTINQ	0x04
+#define MBOXCMD_ADAPTERINQ	0x05
+#define MBOXCMD_LREAD64		0xA7
+#define MBOXCMD_LWRITE64	0xA8
+#define MBOXCMD_PASSTHRU64	0xC3
+#define MBOXCMD_EXTPTHRU	0xE3
+
+#define MAIN_MISC_OPCODE	0xA4
+#define GET_MAX_SG_SUPPORT	0x01
+#define SUPPORT_EXT_CDB		0x16
+
+#define FC_NEW_CONFIG		0xA1
+#define NC_SUBOP_PRODUCT_INFO	0x0E
+#define NC_SUBOP_ENQUIRY3	0x0F
+#define ENQ3_GET_SOLICITED_FULL	0x02
+#define OP_DCMD_READ_CONFIG	0x04
+#define NEW_READ_CONFIG_8LD	0x67
+#define READ_CONFIG_8LD		0x07
+#define FLUSH_ADAPTER		0x0A
+#define FLUSH_SYSTEM		0xFE
+
+/*
+ * Command for random deletion of logical drives
+ */
+#define	FC_DEL_LOGDRV		0xA4
+#define	OP_SUP_DEL_LOGDRV	0x2A
+#define OP_GET_LDID_MAP		0x18
+#define OP_DEL_LOGDRV		0x1C
+
+/*
+ * BIOS commands
+ */
+#define IS_BIOS_ENABLED		0x62
+#define GET_BIOS		0x01
+#define CHNL_CLASS		0xA9
+#define GET_CHNL_CLASS		0x00
+#define SET_CHNL_CLASS		0x01
+#define CH_RAID			0x01
+#define CH_SCSI			0x00
+#define BIOS_PVT_DATA		0x40
+#define GET_BIOS_PVT_DATA	0x00
+
+
+/*
+ * Commands to support clustering
+ */
+#define GET_TARGET_ID		0x7D
+#define CLUSTER_OP		0x70
+#define GET_CLUSTER_MODE	0x02
+#define CLUSTER_CMD		0x6E
+#define RESERVE_LD		0x01
+#define RELEASE_LD		0x02
+#define RESET_RESERVATIONS	0x03
+#define RESERVATION_STATUS	0x04
+#define RESERVE_PD		0x05
+#define RELEASE_PD		0x06
+
+
+/*
+ * Module battery status
+ */
+#define BATTERY_MODULE_MISSING		0x01
+#define BATTERY_LOW_VOLTAGE		0x02
+#define BATTERY_TEMP_HIGH		0x04
+#define BATTERY_PACK_MISSING		0x08
+#define BATTERY_CHARGE_MASK		0x30
+#define BATTERY_CHARGE_DONE		0x00
+#define BATTERY_CHARGE_INPROG		0x10
+#define BATTERY_CHARGE_FAIL		0x20
+#define BATTERY_CYCLES_EXCEEDED		0x40
+
+/*
+ * Physical drive states.
+ */
+#define PDRV_UNCNF	0
+#define PDRV_ONLINE	3
+#define PDRV_FAILED	4
+#define PDRV_RBLD	5
+#define PDRV_HOTSPARE	6
+
+
+/*
+ * Raid logical drive states.
+ */
+#define RDRV_OFFLINE	0
+#define RDRV_DEGRADED	1
+#define RDRV_OPTIMAL	2
+#define RDRV_DELETED	3
+
+/*
+ * Read, write and cache policies
+ */
+#define NO_READ_AHEAD		0
+#define READ_AHEAD		1
+#define ADAP_READ_AHEAD		2
+#define WRMODE_WRITE_THRU	0
+#define WRMODE_WRITE_BACK	1
+#define CACHED_IO		0
+#define DIRECT_IO		1
+
+#define MAX_LOGICAL_DRIVES_8LD		8
+#define MAX_LOGICAL_DRIVES_40LD		40
+#define FC_MAX_PHYSICAL_DEVICES		256
+#define MAX_MBOX_CHANNELS		5
+#define MAX_MBOX_TARGET			15
+#define MBOX_MAX_PHYSICAL_DRIVES	MAX_MBOX_CHANNELS*MAX_MBOX_TARGET
+#define MAX_ROW_SIZE_40LD		32
+#define MAX_ROW_SIZE_8LD		8
+#define SPAN_DEPTH_8_SPANS		8
+#define SPAN_DEPTH_4_SPANS		4
+#define MAX_REQ_SENSE_LEN		0x20
+
+
+
+/**
+ * struct mbox_t - Driver and f/w handshake structure.
+ * @cmd		: firmware command
+ * @cmdid	: command id
+ * @numsectors	: number of sectors to be transferred
+ * @lba		: Logical Block Address on LD
+ * @xferaddr	: DMA address for data transfer
+ * @logdrv	: logical drive number
+ * @numsge	: number of scatter gather elements in sg list
+ * @resvd	: reserved
+ * @busy	: f/w busy, must wait to issue more commands.
+ * @numstatus	: number of commands completed.
+ * @status	: status of the commands completed
+ * @completed	: array of completed command ids.
+ * @poll	: poll and ack sequence
+ * @ack		: poll and ack sequence
+ *
+ * The central handshake structure between the driver and the firmware. This
+ * structure must be allocated by the driver and aligned at 8-byte boundary.
+ */
+#define MBOX_MAX_FIRMWARE_STATUS	46
+typedef struct {
+	uint8_t		cmd;
+	uint8_t		cmdid;
+	uint16_t	numsectors;
+	uint32_t	lba;
+	uint32_t	xferaddr;
+	uint8_t		logdrv;
+	uint8_t		numsge;
+	uint8_t		resvd;
+	uint8_t		busy;
+	uint8_t		numstatus;
+	uint8_t		status;
+	uint8_t		completed[MBOX_MAX_FIRMWARE_STATUS];
+	uint8_t		poll;
+	uint8_t		ack;
+} __attribute__ ((packed)) mbox_t;
+
+
+/**
+ * mbox64_t - 64-bit extension for the mailbox
+ * @segment_lo	: the low 32-bits of the address of the scatter-gather list
+ * @segment_hi	: the upper 32-bits of the address of the scatter-gather list
+ * @mbox	: 32-bit mailbox, whose xferadder field must be set to
+ *		0xFFFFFFFF
+ *
+ * This is the extension of the 32-bit mailbox to be able to perform DMA
+ * beyond 4GB address range.
+ */
+typedef struct {
+	uint32_t	xferaddr_lo;
+	uint32_t	xferaddr_hi;
+	mbox_t		mbox32;
+} __attribute__ ((packed)) mbox64_t;
+
+/*
+ * mailbox structure used for internal commands
+ */
+typedef struct {
+	u8	cmd;
+	u8	cmdid;
+	u8	opcode;
+	u8	subopcode;
+	u32	lba;
+	u32	xferaddr;
+	u8	logdrv;
+	u8	rsvd[3];
+	u8	numstatus;
+	u8	status;
+} __attribute__ ((packed)) int_mbox_t;
+
+/**
+ * mraid_passthru_t - passthru structure to issue commands to physical devices
+ * @timeout		: command timeout, 0=6sec, 1=60sec, 2=10min, 3=3hr
+ * @ars			: set if ARS required after check condition
+ * @islogical		: set if command meant for logical devices
+ * @logdrv		: logical drive number if command for LD
+ * @channel		: Channel on which physical device is located
+ * @target		: SCSI target of the device
+ * @queuetag		: unused
+ * @queueaction		: unused
+ * @cdb			: SCSI CDB
+ * @cdblen		: length of the CDB
+ * @reqsenselen		: amount of request sense data to be returned
+ * @reqsensearea	: Sense information buffer
+ * @numsge		: number of scatter-gather elements in the sg list
+ * @scsistatus		: SCSI status of the command completed.
+ * @dataxferaddr	: DMA data transfer address
+ * @dataxferlen		: amount of the data to be transferred.
+ */
+typedef struct {
+	uint8_t		timeout		:3;
+	uint8_t		ars		:1;
+	uint8_t		reserved	:3;
+	uint8_t		islogical	:1;
+	uint8_t		logdrv;
+	uint8_t		channel;
+	uint8_t		target;
+	uint8_t		queuetag;
+	uint8_t		queueaction;
+	uint8_t		cdb[10];
+	uint8_t		cdblen;
+	uint8_t		reqsenselen;
+	uint8_t		reqsensearea[MAX_REQ_SENSE_LEN];
+	uint8_t		numsge;
+	uint8_t		scsistatus;
+	uint32_t	dataxferaddr;
+	uint32_t	dataxferlen;
+} __attribute__ ((packed)) mraid_passthru_t;
+
+typedef struct {
+
+	uint32_t		dataxferaddr_lo;
+	uint32_t		dataxferaddr_hi;
+	mraid_passthru_t	pthru32;
+
+} __attribute__ ((packed)) mega_passthru64_t;
+
+/**
+ * mraid_epassthru_t - passthru structure to issue commands to physical devices
+ * @timeout		: command timeout, 0=6sec, 1=60sec, 2=10min, 3=3hr
+ * @ars			: set if ARS required after check condition
+ * @rsvd1		: reserved field
+ * @cd_rom		: (?)
+ * @rsvd2		: reserved field
+ * @islogical		: set if command meant for logical devices
+ * @logdrv		: logical drive number if command for LD
+ * @channel		: Channel on which physical device is located
+ * @target		: SCSI target of the device
+ * @queuetag		: unused
+ * @queueaction		: unused
+ * @cdblen		: length of the CDB
+ * @rsvd3		: reserved field
+ * @cdb			: SCSI CDB
+ * @numsge		: number of scatter-gather elements in the sg list
+ * @status		: SCSI status of the command completed.
+ * @reqsenselen		: amount of request sense data to be returned
+ * @reqsensearea	: Sense information buffer
+ * @rsvd4		: reserved field
+ * @dataxferaddr	: DMA data transfer address
+ * @dataxferlen		: amount of the data to be transferred.
+ */
+typedef struct {
+	uint8_t		timeout		:3;
+	uint8_t		ars		:1;
+	uint8_t		rsvd1		:1;
+	uint8_t		cd_rom		:1;
+	uint8_t		rsvd2		:1;
+	uint8_t		islogical	:1;
+	uint8_t		logdrv;
+	uint8_t		channel;
+	uint8_t		target;
+	uint8_t		queuetag;
+	uint8_t		queueaction;
+	uint8_t		cdblen;
+	uint8_t		rsvd3;
+	uint8_t		cdb[16];
+	uint8_t		numsge;
+	uint8_t		status;
+	uint8_t		reqsenselen;
+	uint8_t		reqsensearea[MAX_REQ_SENSE_LEN];
+	uint8_t		rsvd4;
+	uint32_t	dataxferaddr;
+	uint32_t	dataxferlen;
+} __attribute__ ((packed)) mraid_epassthru_t;
+
+
+/**
+ * mraid_pinfo_t - product info, static information about the controller
+ * @data_size		: current size in bytes (not including resvd)
+ * @config_signature	: Current value is 0x00282008
+ * @fw_version		: Firmware version
+ * @bios_version	: version of the BIOS
+ * @product_name	: Name given to the controller
+ * @max_commands	: Maximum concurrent commands supported
+ * @nchannels		: Number of SCSI Channels detected
+ * @fc_loop_present	: Number of Fibre Loops detected
+ * @mem_type		: EDO, FPM, SDRAM etc
+ * @signature		:
+ * @dram_size		: In terms of MB
+ * @subsysid		: device PCI subsystem ID
+ * @subsysvid		: device PCI subsystem vendor ID
+ * @notify_counters	:
+ * @pad1k		: 135 + 889 resvd = 1024 total size
+ *
+ * This structures holds the information about the controller which is not
+ * expected to change dynamically.
+ *
+ * The current value of config signature is 0x00282008:
+ * 0x28 = MAX_LOGICAL_DRIVES,
+ * 0x20 = Number of stripes and
+ * 0x08 = Number of spans
+ */
+typedef struct {
+	uint32_t	data_size;
+	uint32_t	config_signature;
+	uint8_t		fw_version[16];
+	uint8_t		bios_version[16];
+	uint8_t		product_name[80];
+	uint8_t		max_commands;
+	uint8_t		nchannels;
+	uint8_t		fc_loop_present;
+	uint8_t		mem_type;
+	uint32_t	signature;
+	uint16_t	dram_size;
+	uint16_t	subsysid;
+	uint16_t	subsysvid;
+	uint8_t		notify_counters;
+	uint8_t		pad1k[889];
+} __attribute__ ((packed)) mraid_pinfo_t;
+
+
+/**
+ * mraid_notify_t - the notification structure
+ * @global_counter		: Any change increments this counter
+ * @param_counter		: Indicates any params changed
+ * @param_id			: Param modified - defined below
+ * @param_val			: New val of last param modified
+ * @write_config_counter	: write config occurred
+ * @write_config_rsvd		:
+ * @ldrv_op_counter		: Indicates ldrv op started/completed
+ * @ldrv_opid			: ldrv num
+ * @ldrv_opcmd			: ldrv operation - defined below
+ * @ldrv_opstatus		: status of the operation
+ * @ldrv_state_counter		: Indicates change of ldrv state
+ * @ldrv_state_id		: ldrv num
+ * @ldrv_state_new		: New state
+ * @ldrv_state_old		: old state
+ * @pdrv_state_counter		: Indicates change of ldrv state
+ * @pdrv_state_id		: pdrv id
+ * @pdrv_state_new		: New state
+ * @pdrv_state_old		: old state
+ * @pdrv_fmt_counter		: Indicates pdrv format started/over
+ * @pdrv_fmt_id			: pdrv id
+ * @pdrv_fmt_val		: format started/over
+ * @pdrv_fmt_rsvd		:
+ * @targ_xfer_counter		: Indicates SCSI-2 Xfer rate change
+ * @targ_xfer_id		: pdrv Id
+ * @targ_xfer_val		: new Xfer params of last pdrv
+ * @targ_xfer_rsvd		:
+ * @fcloop_id_chg_counter	: Indicates loopid changed
+ * @fcloopid_pdrvid		: pdrv id
+ * @fcloop_id0			: loopid on fc loop 0
+ * @fcloop_id1			: loopid on fc loop 1
+ * @fcloop_state_counter	: Indicates loop state changed
+ * @fcloop_state0		: state of fc loop 0
+ * @fcloop_state1		: state of fc loop 1
+ * @fcloop_state_rsvd		:
+ */
+typedef struct {
+	uint32_t	global_counter;
+	uint8_t		param_counter;
+	uint8_t		param_id;
+	uint16_t	param_val;
+	uint8_t		write_config_counter;
+	uint8_t		write_config_rsvd[3];
+	uint8_t		ldrv_op_counter;
+	uint8_t		ldrv_opid;
+	uint8_t		ldrv_opcmd;
+	uint8_t		ldrv_opstatus;
+	uint8_t		ldrv_state_counter;
+	uint8_t		ldrv_state_id;
+	uint8_t		ldrv_state_new;
+	uint8_t		ldrv_state_old;
+	uint8_t		pdrv_state_counter;
+	uint8_t		pdrv_state_id;
+	uint8_t		pdrv_state_new;
+	uint8_t		pdrv_state_old;
+	uint8_t		pdrv_fmt_counter;
+	uint8_t		pdrv_fmt_id;
+	uint8_t		pdrv_fmt_val;
+	uint8_t		pdrv_fmt_rsvd;
+	uint8_t		targ_xfer_counter;
+	uint8_t		targ_xfer_id;
+	uint8_t		targ_xfer_val;
+	uint8_t		targ_xfer_rsvd;
+	uint8_t		fcloop_id_chg_counter;
+	uint8_t		fcloopid_pdrvid;
+	uint8_t		fcloop_id0;
+	uint8_t		fcloop_id1;
+	uint8_t		fcloop_state_counter;
+	uint8_t		fcloop_state0;
+	uint8_t		fcloop_state1;
+	uint8_t		fcloop_state_rsvd;
+} __attribute__ ((packed)) mraid_notify_t;
+
+
+/**
+ * mraid_inquiry3_t - enquiry for device information
+ *
+ * @data_size		: current size in bytes (not including resvd)
+ * @notify		:
+ * @notify_rsvd		:
+ * @rebuild_rate	: rebuild rate (0% - 100%)
+ * @cache_flush_int	: cache flush interval in seconds
+ * @sense_alert		:
+ * @drive_insert_count	: drive insertion count
+ * @battery_status	:
+ * @num_ldrv		: no. of Log Drives configured
+ * @recon_state		: state of reconstruct
+ * @ldrv_op_status	: logdrv Status
+ * @ldrv_size		: size of each log drv
+ * @ldrv_prop		:
+ * @ldrv_state		: state of log drives
+ * @pdrv_state		: state of phys drvs.
+ * @pdrv_format		:
+ * @targ_xfer		: phys device transfer rate
+ * @pad1k		: 761 + 263reserved = 1024 bytes total size
+ */
+#define MAX_NOTIFY_SIZE		0x80
+#define CUR_NOTIFY_SIZE		sizeof(mraid_notify_t)
+
+typedef struct {
+	uint32_t	data_size;
+
+	mraid_notify_t	notify;
+
+	uint8_t		notify_rsvd[MAX_NOTIFY_SIZE - CUR_NOTIFY_SIZE];
+
+	uint8_t		rebuild_rate;
+	uint8_t		cache_flush_int;
+	uint8_t		sense_alert;
+	uint8_t		drive_insert_count;
+
+	uint8_t		battery_status;
+	uint8_t		num_ldrv;
+	uint8_t		recon_state[MAX_LOGICAL_DRIVES_40LD / 8];
+	uint16_t	ldrv_op_status[MAX_LOGICAL_DRIVES_40LD / 8];
+
+	uint32_t	ldrv_size[MAX_LOGICAL_DRIVES_40LD];
+	uint8_t		ldrv_prop[MAX_LOGICAL_DRIVES_40LD];
+	uint8_t		ldrv_state[MAX_LOGICAL_DRIVES_40LD];
+	uint8_t		pdrv_state[FC_MAX_PHYSICAL_DEVICES];
+	uint16_t	pdrv_format[FC_MAX_PHYSICAL_DEVICES / 16];
+
+	uint8_t		targ_xfer[80];
+	uint8_t		pad1k[263];
+} __attribute__ ((packed)) mraid_inquiry3_t;
+
+
+/**
+ * mraid_adapinfo_t - information about the adapter
+ * @max_commands		: max concurrent commands supported
+ * @rebuild_rate		: rebuild rate - 0% thru 100%
+ * @max_targ_per_chan		: max targ per channel
+ * @nchannels			: number of channels on HBA
+ * @fw_version			: firmware version
+ * @age_of_flash		: number of times FW has been flashed
+ * @chip_set_value		: contents of 0xC0000832
+ * @dram_size			: in MB
+ * @cache_flush_interval	: in seconds
+ * @bios_version		:
+ * @board_type			:
+ * @sense_alert			:
+ * @write_config_count		: increase with every configuration change
+ * @drive_inserted_count	: increase with every drive inserted
+ * @inserted_drive		: channel:Id of inserted drive
+ * @battery_status		: bit 0: battery module missing
+ *				bit 1: VBAD
+ *				bit 2: temprature high
+ *				bit 3: battery pack missing
+ *				bit 4,5:
+ *					00 - charge complete
+ *					01 - fast charge in progress
+ *					10 - fast charge fail
+ *					11 - undefined
+ *				bit 6: counter > 1000
+ *				bit 7: Undefined
+ * @dec_fault_bus_info		:
+ */
+typedef struct {
+	uint8_t		max_commands;
+	uint8_t		rebuild_rate;
+	uint8_t		max_targ_per_chan;
+	uint8_t		nchannels;
+	uint8_t		fw_version[4];
+	uint16_t	age_of_flash;
+	uint8_t		chip_set_value;
+	uint8_t		dram_size;
+	uint8_t		cache_flush_interval;
+	uint8_t		bios_version[4];
+	uint8_t		board_type;
+	uint8_t		sense_alert;
+	uint8_t		write_config_count;
+	uint8_t		battery_status;
+	uint8_t		dec_fault_bus_info;
+} __attribute__ ((packed)) mraid_adapinfo_t;
+
+
+/**
+ * mraid_ldrv_info_t - information about the logical drives
+ * @nldrv	: Number of logical drives configured
+ * @rsvd	:
+ * @size	: size of each logical drive
+ * @prop	:
+ * @state	: state of each logical drive
+ */
+typedef struct {
+	uint8_t		nldrv;
+	uint8_t		rsvd[3];
+	uint32_t	size[MAX_LOGICAL_DRIVES_8LD];
+	uint8_t		prop[MAX_LOGICAL_DRIVES_8LD];
+	uint8_t		state[MAX_LOGICAL_DRIVES_8LD];
+} __attribute__ ((packed)) mraid_ldrv_info_t;
+
+
+/**
+ * mraid_pdrv_info_t - information about the physical drives
+ * @pdrv_state	: state of each physical drive
+ */
+typedef struct {
+	uint8_t		pdrv_state[MBOX_MAX_PHYSICAL_DRIVES];
+	uint8_t		rsvd;
+} __attribute__ ((packed)) mraid_pdrv_info_t;
+
+
+/**
+ * mraid_inquiry_t - RAID inquiry, mailbox command 0x05
+ * @mraid_adapinfo_t	: adapter information
+ * @mraid_ldrv_info_t	: logical drives information
+ * @mraid_pdrv_info_t	: physical drives information
+ */
+typedef struct {
+	mraid_adapinfo_t	adapter_info;
+	mraid_ldrv_info_t	logdrv_info;
+	mraid_pdrv_info_t	pdrv_info;
+} __attribute__ ((packed)) mraid_inquiry_t;
+
+
+/**
+ * mraid_extinq_t - RAID extended inquiry, mailbox command 0x04
+ *
+ * @raid_inq		: raid inquiry
+ * @phys_drv_format	:
+ * @stack_attn		:
+ * @modem_status	:
+ * @rsvd		:
+ */
+typedef struct {
+	mraid_inquiry_t	raid_inq;
+	uint16_t	phys_drv_format[MAX_MBOX_CHANNELS];
+	uint8_t		stack_attn;
+	uint8_t		modem_status;
+	uint8_t		rsvd[2];
+} __attribute__ ((packed)) mraid_extinq_t;
+
+
+/**
+ * adap_device_t - device information
+ * @channel	: channel fpor the device
+ * @target	: target ID of the device
+ */
+typedef struct {
+	uint8_t		channel;
+	uint8_t		target;
+}__attribute__ ((packed)) adap_device_t;
+
+
+/**
+ * adap_span_40ld_t - 40LD span
+ * @start_blk	: starting block
+ * @num_blks	: number of blocks
+ */
+typedef struct {
+	uint32_t	start_blk;
+	uint32_t	num_blks;
+	adap_device_t	device[MAX_ROW_SIZE_40LD];
+}__attribute__ ((packed)) adap_span_40ld_t;
+
+
+/**
+ * adap_span_8ld_t - 8LD span
+ * @start_blk	: starting block
+ * @num_blks	: number of blocks
+ */
+typedef struct {
+	uint32_t	start_blk;
+	uint32_t	num_blks;
+	adap_device_t	device[MAX_ROW_SIZE_8LD];
+}__attribute__ ((packed)) adap_span_8ld_t;
+
+
+/**
+ * logdrv_param_t - logical drives parameters
+ *
+ * @span_depth	: total number of spans
+ * @level	: RAID level
+ * @read_ahead	: read ahead, no read ahead, adaptive read ahead
+ * @stripe_sz	: encoded stripe size
+ * @status	: status of the logical drive
+ * @write_mode	: write mode, write_through/write_back
+ * @direct_io	: direct io or through cache
+ * @row_size	: number of stripes in a row
+ */
+typedef struct {
+	uint8_t		span_depth;
+	uint8_t		level;
+	uint8_t		read_ahead;
+	uint8_t		stripe_sz;
+	uint8_t		status;
+	uint8_t		write_mode;
+	uint8_t		direct_io;
+	uint8_t		row_size;
+} __attribute__ ((packed)) logdrv_param_t;
+
+
+/**
+ * logdrv_40ld_t - logical drive definition for 40LD controllers
+ * @lparam	: logical drives parameters
+ * @span	: span
+ */
+typedef struct {
+	logdrv_param_t		lparam;
+	adap_span_40ld_t	span[SPAN_DEPTH_8_SPANS];
+}__attribute__ ((packed)) logdrv_40ld_t;
+
+
+/**
+ * logdrv_8ld_span8_t - logical drive definition for 8LD controllers
+ * @lparam	: logical drives parameters
+ * @span	: span
+ *
+ * 8-LD logical drive with upto 8 spans
+ */
+typedef struct {
+	logdrv_param_t	lparam;
+	adap_span_8ld_t	span[SPAN_DEPTH_8_SPANS];
+}__attribute__ ((packed)) logdrv_8ld_span8_t;
+
+
+/**
+ * logdrv_8ld_span4_t - logical drive definition for 8LD controllers
+ * @lparam	: logical drives parameters
+ * @span	: span
+ *
+ * 8-LD logical drive with upto 4 spans
+ */
+typedef struct {
+	logdrv_param_t	lparam;
+	adap_span_8ld_t	span[SPAN_DEPTH_4_SPANS];
+}__attribute__ ((packed)) logdrv_8ld_span4_t;
+
+
+/**
+ * phys_drive_t - physical device information
+ * @type	: Type of the device
+ * @cur_status	: current status of the device
+ * @tag_depth	: Level of tagging
+ * @sync_neg	: sync negotiation - ENABLE or DISBALE
+ * @size	: configurable size in terms of 512 byte
+ */
+typedef struct {
+	uint8_t		type;
+	uint8_t		cur_status;
+	uint8_t		tag_depth;
+	uint8_t		sync_neg;
+	uint32_t	size;
+}__attribute__ ((packed)) phys_drive_t;
+
+
+/**
+ * disk_array_40ld_t - disk array for 40LD controllers
+ * @numldrv	: number of logical drives
+ * @resvd	:
+ * @ldrv	: logical drives information
+ * @pdrv	: physical drives information
+ */
+typedef struct {
+	uint8_t		numldrv;
+	uint8_t		resvd[3];
+	logdrv_40ld_t	ldrv[MAX_LOGICAL_DRIVES_40LD];
+	phys_drive_t	pdrv[MBOX_MAX_PHYSICAL_DRIVES];
+}__attribute__ ((packed)) disk_array_40ld_t;
+
+
+/**
+ * disk_array_8ld_span8_t - disk array for 8LD controllers
+ * @numldrv	: number of logical drives
+ * @resvd	:
+ * @ldrv	: logical drives information
+ * @pdrv	: physical drives information
+ *
+ * Disk array for 8LD logical drives with upto 8 spans
+ */
+typedef struct {
+	uint8_t			numldrv;
+	uint8_t			resvd[3];
+	logdrv_8ld_span8_t	ldrv[MAX_LOGICAL_DRIVES_8LD];
+	phys_drive_t		pdrv[MBOX_MAX_PHYSICAL_DRIVES];
+}__attribute__ ((packed)) disk_array_8ld_span8_t;
+
+
+/**
+ * disk_array_8ld_span4_t - disk array for 8LD controllers
+ * @numldrv	: number of logical drives
+ * @resvd	:
+ * @ldrv	: logical drives information
+ * @pdrv	: physical drives information
+ *
+ * Disk array for 8LD logical drives with upto 4 spans
+ */
+typedef struct {
+	uint8_t			numldrv;
+	uint8_t			resvd[3];
+	logdrv_8ld_span4_t	ldrv[MAX_LOGICAL_DRIVES_8LD];
+	phys_drive_t		pdrv[MBOX_MAX_PHYSICAL_DRIVES];
+}__attribute__ ((packed)) disk_array_8ld_span4_t;
+
+
+/**
+ * private_bios_data - bios private data for boot devices
+ * @geometry	: bits 0-3 - BIOS geometry, 0x0001 - 1GB, 0x0010 - 2GB,
+ *		0x1000 - 8GB, Others values are invalid
+ * @unused	: bits 4-7 are unused
+ * @boot_drv	: logical drive set as boot drive, 0..7 - for 8LD cards,
+ * 		0..39 - for 40LD cards
+ * @cksum	: 0-(sum of first 13 bytes of this structure)
+ */
+struct private_bios_data {
+	uint8_t		geometry	:4;
+	uint8_t		unused		:4;
+	uint8_t		boot_drv;
+	uint8_t		rsvd[12];
+	uint16_t	cksum;
+} __attribute__ ((packed));
+
+
+/**
+ * mbox_sgl64 - 64-bit scatter list for mailbox based controllers
+ * @address	: address of the buffer
+ * @length	: data transfer length
+ */
+typedef struct {
+	uint64_t	address;
+	uint32_t	length;
+} __attribute__ ((packed)) mbox_sgl64;
+
+/**
+ * mbox_sgl32 - 32-bit scatter list for mailbox based controllers
+ * @address	: address of the buffer
+ * @length	: data transfer length
+ */
+typedef struct {
+	uint32_t	address;
+	uint32_t	length;
+} __attribute__ ((packed)) mbox_sgl32;
+
+#endif		// _MRAID_MBOX_DEFS_H_
+
+/* vim: set ts=8 sw=8 tw=78: */
diff -Nru a/drivers/scsi/megaraid/mega_common.h b/drivers/scsi/megaraid/mega_common.h
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/drivers/scsi/megaraid/mega_common.h	2004-10-18 14:57:23 -07:00
@@ -0,0 +1,283 @@
+/*
+ *
+ *			Linux MegaRAID device driver
+ *
+ * Copyright (c) 2003-2004  LSI Logic 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.
+ *
+ * FILE		: mega_common.h
+ *
+ * Libaray of common routine used by all low-level megaraid drivers
+ */
+
+#ifndef _MEGA_COMMON_H_
+#define _MEGA_COMMON_H_
+
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/pci.h>
+#include <linux/spinlock.h>
+#include <linux/interrupt.h>
+#include <linux/delay.h>
+#include <linux/blkdev.h>
+#include <linux/list.h>
+#include <linux/version.h>
+#include <linux/moduleparam.h>
+#include <asm/semaphore.h>
+#include <scsi/scsi.h>
+#include <scsi/scsi_cmnd.h>
+#include <scsi/scsi_device.h>
+#include <scsi/scsi_host.h>
+
+
+#define LSI_MAX_CHANNELS		16
+#define LSI_MAX_LOGICAL_DRIVES_64LD	(64+1)
+
+
+/**
+ * scb_t - scsi command control block
+ * @param ccb		: command control block for individual driver
+ * @param list		: list of control blocks
+ * @param gp		: general purpose field for LLDs
+ * @param sno		: all SCBs have a serial number
+ * @param scp		: associated scsi command
+ * @param state		: current state of scb
+ * @param dma_dir	: direction of data transfer
+ * @param dma_type	: transfer with sg list, buffer, or no data transfer
+ * @param dev_channel	: actual channel on the device
+ * @param dev_target	: actual target on the device
+ * @param status	: completion status
+ *
+ * This is our central data structure to issue commands the each driver.
+ * Driver specific data structures are maintained in the ccb field.
+ * scb provides a field 'gp', which can be used by LLD for its own purposes
+ *
+ * dev_channel and dev_target must be initialized with the actual channel and
+ * target on the controller.
+ */
+typedef struct {
+	caddr_t			ccb;
+	struct list_head	list;
+	unsigned long		gp;
+	unsigned int		sno;
+	struct scsi_cmnd	*scp;
+	uint32_t		state;
+	uint32_t		dma_direction;
+	uint32_t		dma_type;
+	uint16_t		dev_channel;
+	uint16_t		dev_target;
+	uint32_t		status;
+} scb_t;
+
+/*
+ * SCB states as it transitions from one state to another
+ */
+#define SCB_FREE	0x0000	/* on the free list */
+#define SCB_ACTIVE	0x0001	/* off the free list */
+#define SCB_PENDQ	0x0002	/* on the pending queue */
+#define SCB_ISSUED	0x0004	/* issued - owner f/w */
+#define SCB_ABORT	0x0008	/* Got an abort for this one */
+#define SCB_RESET	0x0010	/* Got a reset for this one */
+
+/*
+ * DMA types for scb
+ */
+#define MRAID_DMA_NONE	0x0000	/* no data transfer for this command */
+#define MRAID_DMA_WSG	0x0001	/* data transfer using a sg list */
+#define MRAID_DMA_WBUF	0x0002	/* data transfer using a contiguous buffer */
+
+
+/**
+ * struct adapter_t - driver's initialization structure
+ * @param dpc_h			: tasklet handle
+ * @param pdev			: pci configuration pointer for kernel
+ * @param host			: pointer to host structure of mid-layer
+ * @param host_lock		: pointer to appropriate lock
+ * @param lock			: synchronization lock for mid-layer and driver
+ * @param quiescent		: driver is quiescent for now.
+ * @param outstanding_cmds	: number of commands pending in the driver
+ * @param kscb_list		: pointer to the bulk of SCBs pointers for IO
+ * @param kscb_pool		: pool of free scbs for IO
+ * @param kscb_pool_lock	: lock for pool of free scbs
+ * @param pend_list		: pending commands list
+ * @param pend_list_lock	: exlusion lock for pending commands list
+ * @param completed_list	: list of completed commands
+ * @param completed_list_lock	: exclusion lock for list of completed commands
+ * @param sglen			: max sg elements supported
+ * @param device_ids		: to convert kernel device addr to our devices.
+ * @param raid_device		: raid adapter specific pointer
+ * @param max_channel		: maximum channel number supported - inclusive
+ * @param max_target		: max target supported - inclusive
+ * @param max_lun		: max lun supported - inclusive
+ * @param unique_id		: unique identifier for each adapter
+ * @param irq			: IRQ for this adapter
+ * @param ito			: internal timeout value, (-1) means no timeout
+ * @param ibuf			: buffer to issue internal commands
+ * @param ibuf_dma_h		: dma handle for the above buffer
+ * @param uscb_list		: SCB pointers for user cmds, common mgmt module
+ * @param uscb_pool		: pool of SCBs for user commands
+ * @param uscb_pool_lock	: exclusion lock for these SCBs
+ * @param max_cmds		: max outstanding commands
+ * @param fw_version		: firmware version
+ * @param bios_version		: bios version
+ * @param max_cdb_sz		: biggest CDB size supported.
+ * @param ha			: is high availability present - clustering
+ * @param init_id		: initiator ID, the default value should be 7
+ * @param max_sectors		: max sectors per request
+ * @param cmd_per_lun		: max outstanding commands per LUN
+ * @param being_detached	: set when unloading, no more mgmt calls
+ *
+ *
+ * mraid_setup_device_map() can be called anytime after the device map is
+ * available and MRAID_GET_DEVICE_MAP() can be called whenever the mapping is
+ * required, usually from LLD's queue entry point. The formar API sets up the
+ * MRAID_IS_LOGICAL(adapter_t *, struct scsi_cmnd *) to find out if the
+ * device in question is a logical drive.
+ *
+ * quiescent flag should be set by the driver if it is not accepting more
+ * commands
+ *
+ * NOTE: The fields of this structures are placed to minimize cache misses
+ */
+
+// amount of space required to store the bios and firmware version strings
+#define VERSION_SIZE	16
+
+typedef struct {
+	struct tasklet_struct	dpc_h;
+	struct pci_dev		*pdev;
+	struct Scsi_Host	*host;
+	spinlock_t		*host_lock;
+	spinlock_t		lock;
+	uint8_t			quiescent;
+	int			outstanding_cmds;
+	scb_t			*kscb_list;
+	struct list_head	kscb_pool;
+	spinlock_t		kscb_pool_lock;
+	struct list_head	pend_list;
+	spinlock_t		pend_list_lock;
+	struct list_head	completed_list;
+	spinlock_t		completed_list_lock;
+	uint16_t		sglen;
+	int			device_ids[LSI_MAX_CHANNELS]
+					[LSI_MAX_LOGICAL_DRIVES_64LD];
+	caddr_t			raid_device;
+	uint8_t			max_channel;
+	uint16_t		max_target;
+	uint8_t			max_lun;
+
+	uint32_t		unique_id;
+	uint8_t			irq;
+	uint8_t			ito;
+	caddr_t			ibuf;
+	dma_addr_t		ibuf_dma_h;
+	scb_t			*uscb_list;
+	struct list_head	uscb_pool;
+	spinlock_t		uscb_pool_lock;
+	int			max_cmds;
+	uint8_t			fw_version[VERSION_SIZE];
+	uint8_t			bios_version[VERSION_SIZE];
+	uint8_t			max_cdb_sz;
+	uint8_t			ha;
+	uint16_t		init_id;
+	uint16_t		max_sectors;
+	uint16_t		cmd_per_lun;
+	atomic_t		being_detached;
+} adapter_t;
+
+#define SCSI_FREE_LIST_LOCK(adapter)	(&adapter->kscb_pool_lock)
+#define USER_FREE_LIST_LOCK(adapter)	(&adapter->uscb_pool_lock)
+#define PENDING_LIST_LOCK(adapter)	(&adapter->pend_list_lock)
+#define COMPLETED_LIST_LOCK(adapter)	(&adapter->completed_list_lock)
+
+
+// conversion from scsi command
+#define SCP2HOST(scp)			(scp)->device->host	// to host
+#define SCP2HOSTDATA(scp)		SCP2HOST(scp)->hostdata	// to soft state
+#define SCP2CHANNEL(scp)		(scp)->device->channel	// to channel
+#define SCP2TARGET(scp)			(scp)->device->id	// to target
+#define SCP2LUN(scp)			(scp)->device->lun	// to LUN
+
+// generic macro to convert scsi command and host to controller's soft state
+#define SCSIHOST2ADAP(host)	(((caddr_t *)(host->hostdata))[0])
+#define SCP2ADAPTER(scp)	(adapter_t *)SCSIHOST2ADAP(SCP2HOST(scp))
+
+
+/**
+ * MRAID_GET_DEVICE_MAP - device ids
+ * @param adp		- Adapter's soft state
+ * @param scp		- mid-layer scsi command pointer
+ * @param p_chan	- physical channel on the controller
+ * @param target	- target id of the device or logical drive number
+ * @param islogical	- set if the command is for the logical drive
+ *
+ * Macro to retrieve information about device class, logical or physical and
+ * the corresponding physical channel and target or logical drive number
+ **/
+#define MRAID_IS_LOGICAL(adp, scp)	\
+	(SCP2CHANNEL(scp) == (adp)->max_channel) ? 1 : 0
+
+#define MRAID_GET_DEVICE_MAP(adp, scp, p_chan, target, islogical)	\
+	/*								\
+	 * Is the request coming for the virtual channel		\
+	 */								\
+	islogical = MRAID_IS_LOGICAL(adp, scp);				\
+									\
+	/*								\
+	 * Get an index into our table of drive ids mapping		\
+	 */								\
+	if (islogical) {						\
+		p_chan = 0xFF;						\
+		target =						\
+		(adp)->device_ids[(adp)->max_channel][SCP2TARGET(scp)];	\
+	}								\
+	else {								\
+		p_chan = ((adp)->device_ids[SCP2CHANNEL(scp)]		\
+					[SCP2TARGET(scp)] >> 8) & 0xFF;	\
+		target = ((adp)->device_ids[SCP2CHANNEL(scp)]		\
+					[SCP2TARGET(scp)] & 0xFF);	\
+	}
+
+/*
+ * ### Helper routines ###
+ */
+#define LSI_DBGLVL mraid_debug_level	// each LLD must define a global
+ 					// mraid_debug_level
+
+#ifdef DEBUG
+#if defined (_ASSERT_PANIC)
+#define ASSERT_ACTION	panic
+#else
+#define ASSERT_ACTION	printk
+#endif
+
+#define ASSERT(expression)						\
+	if (!(expression)) {						\
+	ASSERT_ACTION("assertion failed:(%s), file: %s, line: %d:%s\n",	\
+			#expression, __FILE__, __LINE__, __FUNCTION__);	\
+	}
+#else
+#define ASSERT(expression)
+#endif
+
+/*
+ * struct mraid_pci_blk - structure holds DMA memory block info
+ * @param vaddr		: virtual address to a memory block
+ * @param dma_addr	: DMA handle to a memory block
+ *
+ * This structure is filled up for the caller. It is the responsibilty of the
+ * caller to allocate this array big enough to store addresses for all
+ * requested elements
+ */
+struct mraid_pci_blk {
+	caddr_t		vaddr;
+	dma_addr_t	dma_addr;
+};
+
+#endif // _MEGA_COMMON_H_
+
+// vim: set ts=8 sw=8 tw=78:
diff -Nru a/drivers/scsi/megaraid/megaraid_ioctl.h b/drivers/scsi/megaraid/megaraid_ioctl.h
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/drivers/scsi/megaraid/megaraid_ioctl.h	2004-10-18 14:57:23 -07:00
@@ -0,0 +1,291 @@
+/*
+ *
+ *			Linux MegaRAID device driver
+ *
+ * Copyright (c) 2003-2004  LSI Logic 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.
+ *
+ * FILE		: megaraid_ioctl.h
+ *
+ * Definitions to interface with user level applications
+ */
+
+#ifndef _MEGARAID_IOCTL_H_
+#define _MEGARAID_IOCTL_H_
+
+#include <linux/types.h>
+#include <asm/semaphore.h>
+
+#include "mbox_defs.h"
+
+/**
+ * con_log() - console log routine
+ * @param level		: indicates the severity of the message.
+ * @fparam mt		: format string
+ *
+ * con_log displays the error messages on the console based on the current
+ * debug level. Also it attaches the appropriate kernel severity level with
+ * the message.
+ *
+ *
+ * consolge messages debug levels
+ */
+#define	CL_ANN		0	/* print unconditionally, announcements */
+#define CL_DLEVEL1	1	/* debug level 1, informative */
+#define CL_DLEVEL2	2	/* debug level 2, verbose */
+#define CL_DLEVEL3	3	/* debug level 3, very verbose */
+
+#define	con_log(level, fmt) if (LSI_DBGLVL >= level) printk fmt;
+
+/*
+ * Definitions & Declarations needed to use common management module
+ */
+
+#define MEGAIOC_MAGIC		'm'
+#define MEGAIOCCMD		_IOWR(MEGAIOC_MAGIC, 0, mimd_t)
+
+#define MEGAIOC_QNADAP		'm'	/* Query # of adapters		*/
+#define MEGAIOC_QDRVRVER	'e'	/* Query driver version		*/
+#define MEGAIOC_QADAPINFO   	'g'	/* Query adapter information	*/
+
+#define USCSICMD		0x80
+#define UIOC_RD			0x00001
+#define UIOC_WR			0x00002
+
+#define MBOX_CMD		0x00000
+#define GET_DRIVER_VER		0x10000
+#define GET_N_ADAP		0x20000
+#define GET_ADAP_INFO		0x30000
+#define GET_CAP			0x40000
+#define GET_STATS		0x50000
+#define GET_IOCTL_VERSION	0x01
+
+#define EXT_IOCTL_SIGN_SZ	16
+#define EXT_IOCTL_SIGN		"$$_EXTD_IOCTL_$$"
+
+#define	MBOX_LEGACY		0x00		/* ioctl has legacy mbox*/
+#define MBOX_HPE		0x01		/* ioctl has hpe mbox	*/
+
+#define	APPTYPE_MIMD		0x00		/* old existing apps	*/
+#define APPTYPE_UIOC		0x01		/* new apps using uioc	*/
+
+#define IOCTL_ISSUE		0x00000001	/* Issue ioctl		*/
+#define IOCTL_ABORT		0x00000002	/* Abort previous ioctl	*/
+
+#define DRVRTYPE_MBOX		0x00000001	/* regular mbox driver	*/
+#define DRVRTYPE_HPE		0x00000002	/* new hpe driver	*/
+
+#define MKADAP(adapno)	(MEGAIOC_MAGIC << 8 | (adapno) )
+#define GETADAP(mkadap)	((mkadap) ^ MEGAIOC_MAGIC << 8)
+
+#define MAX_DMA_POOLS		5		/* 4k, 8k, 16k, 32k, 64k*/
+
+
+/**
+ * struct uioc_t - the common ioctl packet structure
+ *
+ * @signature	: Must be "$$_EXTD_IOCTL_$$"
+ * @mb_type	: Type of the mail box (MB_LEGACY or MB_HPE)
+ * @app_type	: Type of the issuing application (existing or new)
+ * @opcode	: Opcode of the command
+ * @adapno	: Adapter number
+ * @cmdbuf	: Pointer to buffer - can point to mbox or plain data buffer
+ * @xferlen	: xferlen for DCMD and non mailbox commands
+ * @data_dir	: Direction of the data transfer
+ * @status	: Status from the driver
+ * @reserved	: reserved bytes for future expansion
+ *
+ * @user_data	: user data transfer address is saved in this
+ * @user_data_len: length of the data buffer sent by user app
+ * @user_pthru	: user passthru address is saves in this (null if DCMD)
+ * @pthru32	: kernel address passthru (allocated per kioc)
+ * @pthru32_h	: physicall address of @pthru32
+ * @list	: for kioc free pool list maintenance
+ * @done	: call back routine for llds to call when kioc is completed
+ * @buf_vaddr	: dma pool buffer attached to kioc for data transfer
+ * @buf_paddr	: physical address of the dma pool buffer
+ * @pool_index	: index of the dma pool that @buf_vaddr is taken from
+ * @free_buf	: indicates if buffer needs to be freed after kioc completes
+ *
+ * Note		: All LSI drivers understand only this packet. Any other
+ *		: format sent by applications would be converted to this.
+ */
+typedef struct uioc {
+
+/* User Apps: */
+
+	uint8_t			signature[EXT_IOCTL_SIGN_SZ];
+	uint16_t		mb_type;
+	uint16_t		app_type;
+	uint32_t		opcode;
+	uint32_t		adapno;
+	uint64_t		cmdbuf;
+	uint32_t		xferlen;
+	uint32_t		data_dir;
+	int32_t			status;
+	uint8_t			reserved[128];
+
+/* Driver Data: */
+	void __user *		user_data;
+	uint32_t		user_data_len;
+	mraid_passthru_t	__user *user_pthru;
+
+	mraid_passthru_t	*pthru32;
+	dma_addr_t		pthru32_h;
+
+	struct list_head	list;
+	void			(*done)(struct uioc*);
+
+	caddr_t			buf_vaddr;
+	dma_addr_t		buf_paddr;
+	uint8_t			pool_index;
+	uint8_t			free_buf;
+
+} __attribute__ ((aligned(1024),packed)) uioc_t;
+
+
+/**
+ * struct mraid_hba_info - information about the controller
+ *
+ * @param pci_vendor_id		: PCI vendor id
+ * @param pci_device_id		: PCI device id
+ * @param subsystem_vendor_id	: PCI subsystem vendor id
+ * @param subsystem_device_id	: PCI subsystem device id
+ * @param baseport		: base port of hba memory
+ * @param pci_bus		: PCI bus
+ * @param pci_dev_fn		: PCI device/function values
+ * @param irq			: interrupt vector for the device
+ *
+ * Extended information of 256 bytes about the controller. Align on the single
+ * byte boundary so that 32-bit applications can be run on 64-bit platform
+ * drivers withoug re-compilation.
+ * NOTE: reduce the number of reserved bytes whenever new field are added, so
+ * that total size of the structure remains 256 bytes.
+ */
+typedef struct mraid_hba_info {
+
+	uint16_t	pci_vendor_id;
+	uint16_t	pci_device_id;
+	uint16_t	subsys_vendor_id;
+	uint16_t	subsys_device_id;
+
+	uint64_t	baseport;
+	uint8_t		pci_bus;
+	uint8_t		pci_dev_fn;
+	uint8_t		pci_slot;
+	uint8_t		irq;
+
+	uint32_t	unique_id;
+	uint32_t	host_no;
+
+	uint8_t		num_ldrv;
+} __attribute__ ((aligned(256), packed)) mraid_hba_info_t;
+
+
+/**
+ * mcontroller	: adapter info structure for old mimd_t apps
+ *
+ * @base	: base address
+ * @irq		: irq number
+ * @numldrv	: number of logical drives
+ * @pcibus	: pci bus
+ * @pcidev	: pci device
+ * @pcifun	: pci function
+ * @pciid	: pci id
+ * @pcivendor	: vendor id
+ * @pcislot	: slot number
+ * @uid		: unique id
+ */
+typedef struct mcontroller {
+
+	uint64_t	base;
+	uint8_t		irq;
+	uint8_t		numldrv;
+	uint8_t		pcibus;
+	uint16_t	pcidev;
+	uint8_t		pcifun;
+	uint16_t	pciid;
+	uint16_t	pcivendor;
+	uint8_t		pcislot;
+	uint32_t	uid;
+
+} __attribute__ ((packed)) mcontroller_t;
+
+
+/**
+ * mm_dmapool_t	: Represents one dma pool with just one buffer
+ *
+ * @vaddr	: Virtual address
+ * @paddr	: DMA physicall address
+ * @bufsize	: In KB - 4 = 4k, 8 = 8k etc.
+ * @handle	: Handle to the dma pool
+ * @lock	: lock to synchronize access to the pool
+ * @in_use	: If pool already in use, attach new block
+ */
+typedef struct mm_dmapool {
+	caddr_t		vaddr;
+	dma_addr_t	paddr;
+	uint32_t	buf_size;
+	struct dma_pool	*handle;
+	spinlock_t	lock;
+	uint8_t		in_use;
+} mm_dmapool_t;
+
+
+/**
+ * mraid_mmadp_t: Structure that drivers pass during (un)registration
+ *
+ * @unique_id		: Any unique id (usually PCI bus+dev+fn)
+ * @drvr_type		: megaraid or hpe (DRVRTYPE_MBOX or DRVRTYPE_HPE)
+ * @drv_data		: Driver specific; not touched by the common module
+ * @timeout		: timeout for issued kiocs
+ * @max_kioc		: Maximum ioctl packets acceptable by the lld
+ * @pdev		: pci dev; used for allocating dma'ble memory
+ * @issue_uioc		: Driver supplied routine to issue uioc_t commands
+ *			: issue_uioc(drvr_data, kioc, ISSUE/ABORT, uioc_done)
+ * @list		: attach with the global list of adapters
+ * @kioc_list		: block of mem for @max_kioc number of kiocs
+ * @kioc_pool		: pool of free kiocs
+ * @kioc_pool_lock	: protection for free pool
+ * @kioc_semaphore	: so as not to exceed @max_kioc parallel ioctls
+ * @mbox_list		: block of mem for @max_kioc number of mboxes
+ * @pthru_dma_pool	: DMA pool to allocate passthru packets
+ * @dma_pool_list	: array of dma pools
+ */
+
+typedef struct mraid_mmadp {
+
+/* Filled by driver */
+
+	uint32_t		unique_id;
+	uint32_t		drvr_type;
+	unsigned long		drvr_data;
+	uint8_t			timeout;
+	uint8_t			max_kioc;
+
+	struct pci_dev		*pdev;
+
+	int(*issue_uioc)(unsigned long, uioc_t *, uint32_t);
+
+/* Maintained by common module */
+
+	struct list_head	list;
+	uioc_t			*kioc_list;
+	struct list_head	kioc_pool;
+	spinlock_t		kioc_pool_lock;
+	struct semaphore	kioc_semaphore;
+
+	mbox64_t		*mbox_list;
+	struct dma_pool		*pthru_dma_pool;
+	mm_dmapool_t		dma_pool_list[MAX_DMA_POOLS];
+
+} mraid_mmadp_t;
+
+int mraid_mm_register_adp(mraid_mmadp_t *);
+int mraid_mm_unregister_adp(uint32_t);
+
+#endif /* _MEGARAID_IOCTL_H_ */
diff -Nru a/drivers/scsi/megaraid/megaraid_mbox.c b/drivers/scsi/megaraid/megaraid_mbox.c
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/drivers/scsi/megaraid/megaraid_mbox.c	2004-10-18 14:57:23 -07:00
@@ -0,0 +1,3891 @@
+/*
+ *
+ *			Linux MegaRAID device driver
+ *
+ * Copyright (c) 2003-2004  LSI Logic 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.
+ *
+ * FILE		: megaraid_mbox.c
+ * Version	: v2.20.4 (September 27 2004)
+ *
+ * Authors:
+ * 	Atul Mukker		<Atul.Mukker@lsil.com>
+ * 	Sreenivas Bagalkote	<Sreenivas.Bagalkote@lsil.com>
+ * 	Manoj Jose		<Manoj.Jose@lsil.com>
+ *
+ * List of supported controllers
+ *
+ * OEM	Product Name			VID	DID	SSVID	SSID
+ * ---	------------			---	---	----	----
+ * Dell PERC3/QC			101E	1960	1028	0471
+ * Dell PERC3/DC			101E	1960	1028	0493
+ * Dell PERC3/SC			101E	1960	1028	0475
+ * Dell PERC3/Di			1028	1960	1028	0123
+ * Dell PERC4/SC			1000	1960	1028	0520
+ * Dell PERC4/DC			1000	1960	1028	0518
+ * Dell PERC4/QC			1000	0407	1028	0531
+ * Dell PERC4/Di			1028	000F	1028	014A
+ * Dell PERC 4e/Si			1028	0013	1028	016c
+ * Dell PERC 4e/Di			1028	0013	1028	016d
+ * Dell PERC 4e/Di			1028	0013	1028	016e
+ * Dell PERC 4e/Di			1028	0013	1028	016f
+ * Dell PERC 4e/Di			1028	0013	1028	0170
+ * Dell PERC 4e/DC			1000	0408	1028	0002
+ * Dell PERC 4e/SC			1000	0408	1028	0001
+ *
+ *
+ * LSI MegaRAID SCSI 320-0		1000	1960	1000	A520
+ * LSI MegaRAID SCSI 320-1		1000	1960	1000	0520
+ * LSI MegaRAID SCSI 320-2		1000	1960	1000	0518
+ * LSI MegaRAID SCSI 320-0X		1000	0407	1000	0530
+ * LSI MegaRAID SCSI 320-2X		1000	0407	1000	0532
+ * LSI MegaRAID SCSI 320-4X		1000	0407	1000	0531
+ * LSI MegaRAID SCSI 320-1E		1000	0408	1000	0001
+ * LSI MegaRAID SCSI 320-2E		1000	0408	1000	0002
+ * LSI MegaRAID SATA 150-4		1000	1960	1000	4523
+ * LSI MegaRAID SATA 150-6		1000	1960	1000	0523
+ * LSI MegaRAID SATA 300-4X		1000	0409	1000	3004
+ * LSI MegaRAID SATA 300-8X		1000	0409	1000	3008
+ *
+ * INTEL RAID Controller SRCU42X	1000	0407	8086	0532
+ * INTEL RAID Controller SRCS16		1000	1960	8086	0523
+ * INTEL RAID Controller SRCU42E	1000	0408	8086	0002
+ * INTEL RAID Controller SRCZCRX	1000	0407	8086	0530
+ * INTEL RAID Controller SRCS28X	1000	0409	8086	3008
+ * INTEL RAID Controller SROMBU42E	1000	0408	8086	3431
+ * INTEL RAID Controller SROMBU42E	1000	0408	8086	3499
+ * INTEL RAID Controller SRCU51L	1000	1960	8086	0520
+ *
+ *
+ * FSC	MegaRAID PCI Express ROMB	1000	0408	1734	1065
+ *
+ *
+ * ACER	MegaRAID ROMB-2E		1000	0408	1025	004D
+ *
+ *
+ * For history of changes, see Documentation/ChangeLog.megaraid
+ */
+
+#include "megaraid_mbox.h"
+
+static int megaraid_init(void);
+static void megaraid_exit(void);
+
+static int megaraid_probe_one(struct pci_dev*, const struct pci_device_id *);
+static void megaraid_detach_one(struct pci_dev *);
+static void megaraid_mbox_shutdown(struct device *);
+
+static int megaraid_io_attach(adapter_t *);
+static void megaraid_io_detach(adapter_t *);
+
+static int megaraid_init_mbox(adapter_t *);
+static void megaraid_fini_mbox(adapter_t *);
+
+static int megaraid_alloc_cmd_packets(adapter_t *);
+static void megaraid_free_cmd_packets(adapter_t *);
+
+static int megaraid_mbox_setup_dma_pools(adapter_t *);
+static void megaraid_mbox_teardown_dma_pools(adapter_t *);
+
+static int megaraid_abort_handler(struct scsi_cmnd *);
+static int megaraid_reset_handler(struct scsi_cmnd *);
+
+static int mbox_post_sync_cmd(adapter_t *, uint8_t []);
+static int mbox_post_sync_cmd_fast(adapter_t *, uint8_t []);
+static int megaraid_busywait_mbox(mraid_device_t *);
+static int megaraid_mbox_product_info(adapter_t *);
+static int megaraid_mbox_extended_cdb(adapter_t *);
+static int megaraid_mbox_support_ha(adapter_t *, uint16_t *);
+static int megaraid_mbox_support_random_del(adapter_t *);
+static int megaraid_mbox_get_max_sg(adapter_t *);
+static void megaraid_mbox_enum_raid_scsi(adapter_t *);
+static void megaraid_mbox_flush_cache(adapter_t *);
+
+static void megaraid_mbox_display_scb(adapter_t *, scb_t *);
+static void megaraid_mbox_setup_device_map(adapter_t *);
+
+static int megaraid_queue_command(struct scsi_cmnd *,
+		void (*)(struct scsi_cmnd *));
+static scb_t *megaraid_mbox_build_cmd(adapter_t *, struct scsi_cmnd *, int *);
+static void megaraid_mbox_runpendq(adapter_t *, scb_t *);
+static void megaraid_mbox_prepare_pthru(adapter_t *, scb_t *,
+		struct scsi_cmnd *);
+static void megaraid_mbox_prepare_epthru(adapter_t *, scb_t *,
+		struct scsi_cmnd *);
+
+static irqreturn_t megaraid_isr(int, void *, struct pt_regs *);
+
+static void megaraid_mbox_dpc(unsigned long);
+
+static int megaraid_cmm_register(adapter_t *);
+static int megaraid_cmm_unregister(adapter_t *);
+static int megaraid_mbox_mm_handler(unsigned long, uioc_t *, uint32_t);
+static int megaraid_mbox_mm_command(adapter_t *, uioc_t *);
+static void megaraid_mbox_mm_done(adapter_t *, scb_t *);
+static int gather_hbainfo(adapter_t *, mraid_hba_info_t *);
+static int wait_till_fw_empty(adapter_t *);
+
+
+
+MODULE_AUTHOR("LSI Logic Corporation");
+MODULE_DESCRIPTION("LSI Logic MegaRAID Mailbox Driver");
+MODULE_LICENSE("GPL");
+MODULE_VERSION(MEGARAID_VERSION);
+
+/*
+ * ### modules parameters for driver ###
+ */
+
+/**
+ * Set to enable driver to expose unconfigured disk to kernel
+ */
+static int megaraid_expose_unconf_disks = 0;
+module_param_named(unconf_disks, megaraid_expose_unconf_disks, int, 0);
+MODULE_PARM_DESC(unconf_disks,
+	"Set to expose unconfigured disks to kernel (default=0)");
+
+/**
+ * driver wait time if the adapter's mailbox is busy
+ */
+static unsigned int max_mbox_busy_wait = MBOX_BUSY_WAIT;
+module_param_named(busy_wait, max_mbox_busy_wait, int, 0);
+MODULE_PARM_DESC(busy_wait,
+	"Max wait for mailbox in microseconds if busy (default=10)");
+
+/**
+ * number of sectors per IO command
+ */
+static unsigned int megaraid_max_sectors = MBOX_MAX_SECTORS;
+module_param_named(max_sectors, megaraid_max_sectors, int, 0);
+MODULE_PARM_DESC(max_sectors,
+	"Maximum number of sectors per IO command (default=128)");
+
+/**
+ * number of commands per logical unit
+ */
+static unsigned int megaraid_cmd_per_lun = MBOX_DEF_CMD_PER_LUN;
+module_param_named(cmd_per_lun, megaraid_cmd_per_lun, int, 0);
+MODULE_PARM_DESC(cmd_per_lun,
+	"Maximum number of commands per logical unit (default=64)");
+
+
+/**
+ * Fast driver load option, skip scanning for physical devices during load.
+ * This would result in non-disk devices being skipped during driver load
+ * time. These can be later added though, using /proc/scsi/scsi
+ */
+static unsigned int megaraid_fast_load = 0;
+module_param_named(fast_load, megaraid_fast_load, int, 0);
+MODULE_PARM_DESC(fast_load,
+	"Faster loading of the driver, skips physical devices! (default=0)");
+
+
+/**
+ * mraid_debug level - threshold for amount of information to be displayed by
+ * the driver. This level can be changed through modules parameters, ioctl or
+ * sysfs/proc interface. By default, print the announcement messages only.
+ */
+int mraid_debug_level = CL_ANN;
+module_param_named(debug_level, mraid_debug_level, int, 0);
+MODULE_PARM_DESC(debug_level, "Debug level for driver (default=0)");
+
+/*
+ * ### global data ###
+ */
+static uint8_t megaraid_mbox_version[8] =
+	{ 0x02, 0x20, 0x04, 0x00, 9, 27, 20, 4 };
+
+
+/*
+ * PCI table for all supported controllers.
+ */
+static struct pci_device_id pci_id_table_g[] =  {
+	{
+		PCI_VENDOR_ID_DELL,
+		PCI_DEVICE_ID_PERC4_DI_DISCOVERY,
+		PCI_VENDOR_ID_DELL,
+		PCI_SUBSYS_ID_PERC4_DI_DISCOVERY,
+	},
+	{
+		PCI_VENDOR_ID_LSI_LOGIC,
+		PCI_DEVICE_ID_PERC4_SC,
+		PCI_VENDOR_ID_DELL,
+		PCI_SUBSYS_ID_PERC4_SC,
+	},
+	{
+		PCI_VENDOR_ID_LSI_LOGIC,
+		PCI_DEVICE_ID_PERC4_DC,
+		PCI_VENDOR_ID_DELL,
+		PCI_SUBSYS_ID_PERC4_DC,
+	},
+	{
+		PCI_VENDOR_ID_LSI_LOGIC,
+		PCI_DEVICE_ID_PERC4_QC,
+		PCI_VENDOR_ID_DELL,
+		PCI_SUBSYS_ID_PERC4_QC,
+	},
+	{
+		PCI_VENDOR_ID_DELL,
+		PCI_DEVICE_ID_PERC4_DI_EVERGLADES,
+		PCI_VENDOR_ID_DELL,
+		PCI_SUBSYS_ID_PERC4_DI_EVERGLADES,
+	},
+	{
+		PCI_VENDOR_ID_DELL,
+		PCI_DEVICE_ID_PERC4E_SI_BIGBEND,
+		PCI_VENDOR_ID_DELL,
+		PCI_SUBSYS_ID_PERC4E_SI_BIGBEND,
+	},
+	{
+		PCI_VENDOR_ID_DELL,
+		PCI_DEVICE_ID_PERC4E_DI_KOBUK,
+		PCI_VENDOR_ID_DELL,
+		PCI_SUBSYS_ID_PERC4E_DI_KOBUK,
+	},
+	{
+		PCI_VENDOR_ID_DELL,
+		PCI_DEVICE_ID_PERC4E_DI_CORVETTE,
+		PCI_VENDOR_ID_DELL,
+		PCI_SUBSYS_ID_PERC4E_DI_CORVETTE,
+	},
+	{
+		PCI_VENDOR_ID_DELL,
+		PCI_DEVICE_ID_PERC4E_DI_EXPEDITION,
+		PCI_VENDOR_ID_DELL,
+		PCI_SUBSYS_ID_PERC4E_DI_EXPEDITION,
+	},
+	{
+		PCI_VENDOR_ID_DELL,
+		PCI_DEVICE_ID_PERC4E_DI_GUADALUPE,
+		PCI_VENDOR_ID_DELL,
+		PCI_SUBSYS_ID_PERC4E_DI_GUADALUPE,
+	},
+	{
+		PCI_VENDOR_ID_LSI_LOGIC,
+		PCI_DEVICE_ID_PERC4E_DC_320_2E,
+		PCI_VENDOR_ID_DELL,
+		PCI_SUBSYS_ID_PERC4E_DC_320_2E,
+	},
+	{
+		PCI_VENDOR_ID_LSI_LOGIC,
+		PCI_DEVICE_ID_PERC4E_SC_320_1E,
+		PCI_VENDOR_ID_DELL,
+		PCI_SUBSYS_ID_PERC4E_SC_320_1E,
+	},
+	{
+		PCI_VENDOR_ID_AMI,
+		PCI_DEVICE_ID_AMI_MEGARAID3,
+		PCI_VENDOR_ID_DELL,
+		PCI_SUBSYS_ID_PERC3_QC,
+	},
+	{
+		PCI_VENDOR_ID_AMI,
+		PCI_DEVICE_ID_AMI_MEGARAID3,
+		PCI_VENDOR_ID_DELL,
+		PCI_SUBSYS_ID_PERC3_DC,
+	},
+	{
+		PCI_VENDOR_ID_AMI,
+		PCI_DEVICE_ID_AMI_MEGARAID3,
+		PCI_VENDOR_ID_DELL,
+		PCI_SUBSYS_ID_PERC3_SC,
+	},
+	{
+		PCI_VENDOR_ID_LSI_LOGIC,
+		PCI_DEVICE_ID_MEGARAID_SCSI_320_0,
+		PCI_VENDOR_ID_LSI_LOGIC,
+		PCI_SUBSYS_ID_MEGARAID_SCSI_320_0,
+	},
+	{
+		PCI_VENDOR_ID_LSI_LOGIC,
+		PCI_DEVICE_ID_MEGARAID_SCSI_320_1,
+		PCI_VENDOR_ID_LSI_LOGIC,
+		PCI_SUBSYS_ID_MEGARAID_SCSI_320_1,
+	},
+	{
+		PCI_VENDOR_ID_LSI_LOGIC,
+		PCI_DEVICE_ID_MEGARAID_SCSI_320_2,
+		PCI_VENDOR_ID_LSI_LOGIC,
+		PCI_SUBSYS_ID_MEGARAID_SCSI_320_2,
+	},
+	{
+		PCI_VENDOR_ID_LSI_LOGIC,
+		PCI_DEVICE_ID_MEGARAID_SCSI_320_0x,
+		PCI_VENDOR_ID_LSI_LOGIC,
+		PCI_SUBSYS_ID_MEGARAID_SCSI_320_0x,
+	},
+	{
+		PCI_VENDOR_ID_LSI_LOGIC,
+		PCI_DEVICE_ID_MEGARAID_SCSI_320_2x,
+		PCI_VENDOR_ID_LSI_LOGIC,
+		PCI_SUBSYS_ID_MEGARAID_SCSI_320_2x,
+	},
+	{
+		PCI_VENDOR_ID_LSI_LOGIC,
+		PCI_DEVICE_ID_MEGARAID_SCSI_320_4x,
+		PCI_VENDOR_ID_LSI_LOGIC,
+		PCI_SUBSYS_ID_MEGARAID_SCSI_320_4x,
+	},
+	{
+		PCI_VENDOR_ID_LSI_LOGIC,
+		PCI_DEVICE_ID_MEGARAID_SCSI_320_1E,
+		PCI_VENDOR_ID_LSI_LOGIC,
+		PCI_SUBSYS_ID_MEGARAID_SCSI_320_1E,
+	},
+	{
+		PCI_VENDOR_ID_LSI_LOGIC,
+		PCI_DEVICE_ID_MEGARAID_SCSI_320_2E,
+		PCI_VENDOR_ID_LSI_LOGIC,
+		PCI_SUBSYS_ID_MEGARAID_SCSI_320_2E,
+	},
+	{
+		PCI_VENDOR_ID_LSI_LOGIC,
+		PCI_DEVICE_ID_MEGARAID_I4_133_RAID,
+		PCI_VENDOR_ID_LSI_LOGIC,
+		PCI_SUBSYS_ID_MEGARAID_I4_133_RAID,
+	},
+	{
+		PCI_VENDOR_ID_LSI_LOGIC,
+		PCI_DEVICE_ID_MEGARAID_SATA_150_4,
+		PCI_VENDOR_ID_LSI_LOGIC,
+		PCI_SUBSYS_ID_MEGARAID_SATA_150_4,
+	},
+	{
+		PCI_VENDOR_ID_LSI_LOGIC,
+		PCI_DEVICE_ID_MEGARAID_SATA_150_6,
+		PCI_VENDOR_ID_LSI_LOGIC,
+		PCI_SUBSYS_ID_MEGARAID_SATA_150_6,
+	},
+	{
+		PCI_VENDOR_ID_LSI_LOGIC,
+		PCI_DEVICE_ID_MEGARAID_SATA_300_4x,
+		PCI_VENDOR_ID_LSI_LOGIC,
+		PCI_SUBSYS_ID_MEGARAID_SATA_300_4x,
+	},
+	{
+		PCI_VENDOR_ID_LSI_LOGIC,
+		PCI_DEVICE_ID_MEGARAID_SATA_300_8x,
+		PCI_VENDOR_ID_LSI_LOGIC,
+		PCI_SUBSYS_ID_MEGARAID_SATA_300_8x,
+	},
+	{
+		PCI_VENDOR_ID_LSI_LOGIC,
+		PCI_DEVICE_ID_INTEL_RAID_SRCU42X,
+		PCI_VENDOR_ID_INTEL,
+		PCI_SUBSYS_ID_INTEL_RAID_SRCU42X,
+	},
+	{
+		PCI_VENDOR_ID_LSI_LOGIC,
+		PCI_DEVICE_ID_INTEL_RAID_SRCS16,
+		PCI_VENDOR_ID_INTEL,
+		PCI_SUBSYS_ID_INTEL_RAID_SRCS16,
+	},
+	{
+		PCI_VENDOR_ID_LSI_LOGIC,
+		PCI_DEVICE_ID_INTEL_RAID_SRCU42E,
+		PCI_VENDOR_ID_INTEL,
+		PCI_SUBSYS_ID_INTEL_RAID_SRCU42E,
+	},
+	{
+		PCI_VENDOR_ID_LSI_LOGIC,
+		PCI_DEVICE_ID_INTEL_RAID_SRCZCRX,
+		PCI_VENDOR_ID_INTEL,
+		PCI_SUBSYS_ID_INTEL_RAID_SRCZCRX,
+	},
+	{
+		PCI_VENDOR_ID_LSI_LOGIC,
+		PCI_DEVICE_ID_INTEL_RAID_SRCS28X,
+		PCI_VENDOR_ID_INTEL,
+		PCI_SUBSYS_ID_INTEL_RAID_SRCS28X,
+	},
+	{
+		PCI_VENDOR_ID_LSI_LOGIC,
+		PCI_DEVICE_ID_INTEL_RAID_SROMBU42E_ALIEF,
+		PCI_VENDOR_ID_INTEL,
+		PCI_SUBSYS_ID_INTEL_RAID_SROMBU42E_ALIEF,
+	},
+	{
+		PCI_VENDOR_ID_LSI_LOGIC,
+		PCI_DEVICE_ID_INTEL_RAID_SROMBU42E_HARWICH,
+		PCI_VENDOR_ID_INTEL,
+		PCI_SUBSYS_ID_INTEL_RAID_SROMBU42E_HARWICH,
+	},
+	{
+		PCI_VENDOR_ID_LSI_LOGIC,
+		PCI_DEVICE_ID_INTEL_RAID_SRCU41L_LAKE_SHETEK,
+		PCI_VENDOR_ID_INTEL,
+		PCI_SUBSYS_ID_INTEL_RAID_SRCU41L_LAKE_SHETEK,
+	},
+	{
+		PCI_VENDOR_ID_LSI_LOGIC,
+		PCI_DEVICE_ID_FSC_MEGARAID_PCI_EXPRESS_ROMB,
+		PCI_SUBSYS_ID_FSC,
+		PCI_SUBSYS_ID_FSC_MEGARAID_PCI_EXPRESS_ROMB,
+	},
+	{
+		PCI_VENDOR_ID_LSI_LOGIC,
+		PCI_DEVICE_ID_MEGARAID_ACER_ROMB_2E,
+		PCI_VENDOR_ID_AI,
+		PCI_SUBSYS_ID_MEGARAID_ACER_ROMB_2E,
+	},
+	{0}	/* Terminating entry */
+};
+MODULE_DEVICE_TABLE(pci, pci_id_table_g);
+
+
+static struct pci_driver megaraid_pci_driver_g = {
+	.name		= "megaraid",
+	.id_table	= pci_id_table_g,
+	.probe		= megaraid_probe_one,
+	.remove		= __devexit_p(megaraid_detach_one),
+	.driver		= {
+		.shutdown	= megaraid_mbox_shutdown,
+	}
+};
+
+
+/*
+ * Scsi host template for megaraid unified driver
+ */
+static struct scsi_host_template megaraid_template_g = {
+	.module				= THIS_MODULE,
+	.name				= "LSI Logic MegaRAID driver",
+	.proc_name			= "megaraid",
+	.queuecommand			= megaraid_queue_command,
+	.eh_abort_handler		= megaraid_abort_handler,
+	.eh_device_reset_handler	= megaraid_reset_handler,
+	.eh_bus_reset_handler		= megaraid_reset_handler,
+	.eh_host_reset_handler		= megaraid_reset_handler,
+	.use_clustering			= ENABLE_CLUSTERING,
+};
+
+
+/**
+ * megaraid_init - module load hook
+ *
+ * We register ourselves as hotplug enabled module and let PCI subsystem
+ * discover our adaters
+ **/
+static int __init
+megaraid_init(void)
+{
+	int	rval;
+
+	// Announce the driver version
+	con_log(CL_ANN, (KERN_INFO "megaraid: %s %s\n", MEGARAID_VERSION,
+		MEGARAID_EXT_VERSION));
+
+	// check validity of module parameters
+	if (megaraid_cmd_per_lun > MBOX_MAX_SCSI_CMDS) {
+
+		con_log(CL_ANN, (KERN_WARNING
+			"megaraid mailbox: max commands per lun reset to %d\n",
+			MBOX_MAX_SCSI_CMDS));
+
+		megaraid_cmd_per_lun = MBOX_MAX_SCSI_CMDS;
+	}
+
+
+	// register as a PCI hot-plug driver module
+	if ((rval = pci_module_init(&megaraid_pci_driver_g))) {
+		con_log(CL_ANN, (KERN_WARNING
+			"megaraid: could not register hotplug support.\n"));
+	}
+
+	return rval;
+}
+
+
+/**
+ * megaraid_exit - driver unload entry point
+ *
+ * We simply unwrap the megaraid_init routine here
+ */
+static void __exit
+megaraid_exit(void)
+{
+	con_log(CL_DLEVEL1, (KERN_NOTICE "megaraid: unloading framework\n"));
+
+	// unregister as PCI hotplug driver
+	pci_unregister_driver(&megaraid_pci_driver_g);
+
+	return;
+}
+
+
+/**
+ * megaraid_probe_one - PCI hotplug entry point
+ * @param pdev	: handle to this controller's PCI configuration space
+ * @param id	: pci device id of the class of controllers
+ *
+ * This routine should be called whenever a new adapter is detected by the
+ * PCI hotplug susbsytem.
+ **/
+static int __devinit
+megaraid_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
+{
+	adapter_t	*adapter;
+
+
+	// detected a new controller
+	con_log(CL_ANN, (KERN_INFO
+		"megaraid: probe new device %#4.04x:%#4.04x:%#4.04x:%#4.04x: ",
+		pdev->vendor, pdev->device, pdev->subsystem_vendor,
+		pdev->subsystem_device));
+
+	con_log(CL_ANN, ("bus %d:slot %d:func %d\n", pdev->bus->number,
+		PCI_SLOT(pdev->devfn), PCI_FUNC(pdev->devfn)));
+
+	if (pci_enable_device(pdev)) {
+		con_log(CL_ANN, (KERN_WARNING
+				"megaraid: pci_enable_device failed\n"));
+
+		return -ENODEV;
+	}
+
+	// Enable bus-mastering on this controller
+	pci_set_master(pdev);
+
+	// Allocate the per driver initialization structure
+	adapter = kmalloc(sizeof(adapter_t), GFP_KERNEL);
+
+	if (adapter == NULL) {
+		con_log(CL_ANN, (KERN_WARNING
+		"megaraid: out of memory, %s %d.\n", __FUNCTION__, __LINE__));
+
+		goto out_probe_one;
+	}
+	memset(adapter, 0, sizeof(adapter_t));
+
+
+	// set up PCI related soft state and other pre-known parameters
+	adapter->unique_id	= pdev->bus->number << 8 | pdev->devfn;
+	adapter->irq		= pdev->irq;
+	adapter->pdev		= pdev;
+
+	atomic_set(&adapter->being_detached, 0);
+
+	// Setup the default DMA mask. This would be changed later on
+	// depending on hardware capabilities
+	if (pci_set_dma_mask(adapter->pdev, 0xFFFFFFFF) != 0) {
+
+		con_log(CL_ANN, (KERN_WARNING
+			"megaraid: pci_set_dma_mask failed:%d\n", __LINE__));
+
+		goto out_free_adapter;
+	}
+
+
+	// Initialize the synchronization lock for kernel and LLD
+	spin_lock_init(&adapter->lock);
+	adapter->host_lock = &adapter->lock;
+
+
+	// Initialize the command queues: the list of free SCBs and the list
+	// of pending SCBs.
+	INIT_LIST_HEAD(&adapter->kscb_pool);
+	spin_lock_init(SCSI_FREE_LIST_LOCK(adapter));
+
+	INIT_LIST_HEAD(&adapter->pend_list);
+	spin_lock_init(PENDING_LIST_LOCK(adapter));
+
+	INIT_LIST_HEAD(&adapter->completed_list);
+	spin_lock_init(COMPLETED_LIST_LOCK(adapter));
+
+
+	// Start the mailbox based controller
+	if (megaraid_init_mbox(adapter) != 0) {
+		con_log(CL_ANN, (KERN_WARNING
+			"megaraid: maibox adapter did not initialize\n"));
+
+		goto out_free_adapter;
+	}
+
+	// Register with LSI Common Management Module
+	if (megaraid_cmm_register(adapter) != 0) {
+
+		con_log(CL_ANN, (KERN_WARNING
+		"megaraid: could not register with management module\n"));
+
+		goto out_fini_mbox;
+	}
+
+	// setup adapter handle in PCI soft state
+	pci_set_drvdata(pdev, adapter);
+
+	// attach with scsi mid-layer
+	if (megaraid_io_attach(adapter) != 0) {
+
+		con_log(CL_ANN, (KERN_WARNING "megaraid: io attach failed\n"));
+
+		goto out_cmm_unreg;
+	}
+
+	return 0;
+
+out_cmm_unreg:
+	pci_set_drvdata(pdev, NULL);
+	megaraid_cmm_unregister(adapter);
+out_fini_mbox:
+	megaraid_fini_mbox(adapter);
+out_free_adapter:
+	kfree(adapter);
+out_probe_one:
+	pci_disable_device(pdev);
+
+	return -ENODEV;
+}
+
+
+/**
+ * megaraid_detach_one - release the framework resources and call LLD release
+ * routine
+ * @param pdev	: handle for our PCI cofiguration space
+ *
+ * This routine is called during driver unload. We free all the allocated
+ * resources and call the corresponding LLD so that it can also release all
+ * its resources.
+ *
+ * This routine is also called from the PCI hotplug system
+ **/
+static void
+megaraid_detach_one(struct pci_dev *pdev)
+{
+	adapter_t		*adapter;
+	struct Scsi_Host	*host;
+
+
+	// Start a rollback on this adapter
+	adapter = pci_get_drvdata(pdev);
+
+	if (!adapter) {
+		con_log(CL_ANN, (KERN_CRIT
+		"megaraid: Invalid detach on %#4.04x:%#4.04x:%#4.04x:%#4.04x\n",
+			pdev->vendor, pdev->device, pdev->subsystem_vendor,
+			pdev->subsystem_device));
+
+		return;
+	}
+	else {
+		con_log(CL_ANN, (KERN_NOTICE
+		"megaraid: detaching device %#4.04x:%#4.04x:%#4.04x:%#4.04x\n",
+			pdev->vendor, pdev->device, pdev->subsystem_vendor,
+			pdev->subsystem_device));
+	}
+
+
+	host = adapter->host;
+
+	// do not allow any more requests from the management module for this
+	// adapter.
+	// FIXME: How do we account for the request which might still be
+	// pending with us?
+	atomic_set(&adapter->being_detached, 1);
+
+	// detach from the IO sub-system
+	megaraid_io_detach(adapter);
+
+	// reset the device state in the PCI structure. We check this
+	// condition when we enter here. If the device state is NULL,
+	// that would mean the device has already been removed
+	pci_set_drvdata(pdev, NULL);
+
+	// Unregister from common management module
+	//
+	// FIXME: this must return success or failure for conditions if there
+	// is a command pending with LLD or not.
+	megaraid_cmm_unregister(adapter);
+
+	// finalize the mailbox based controller and release all resources
+	megaraid_fini_mbox(adapter);
+
+	kfree(adapter);
+
+	scsi_host_put(host);
+
+	pci_disable_device(pdev);
+
+	return;
+}
+
+
+/**
+ * megaraid_mbox_shutdown - PCI shutdown for megaraid HBA
+ * @param device	: generice driver model device
+ *
+ * Shutdown notification, perform flush cache
+ */
+static void
+megaraid_mbox_shutdown(struct device *device)
+{
+	adapter_t		*adapter = pci_get_drvdata(to_pci_dev(device));
+	static int		counter;
+
+	if (!adapter) {
+		con_log(CL_ANN, (KERN_WARNING
+			"megaraid: null device in shutdown\n"));
+		return;
+	}
+
+	// flush caches now
+	con_log(CL_ANN, (KERN_INFO "megaraid: flushing adapter %d...",
+		counter++));
+
+	megaraid_mbox_flush_cache(adapter);
+
+	con_log(CL_ANN, ("done\n"));
+}
+
+
+/**
+ * megaraid_io_attach - attach a device with the IO subsystem
+ * @param adapter	: controller's soft state
+ *
+ * Attach this device with the IO subsystem
+ **/
+static int
+megaraid_io_attach(adapter_t *adapter)
+{
+	struct Scsi_Host	*host;
+
+	// Initialize SCSI Host structure
+	host = scsi_host_alloc(&megaraid_template_g, 8);
+	if (!host) {
+		con_log(CL_ANN, (KERN_WARNING
+			"megaraid mbox: scsi_register failed\n"));
+
+		return -1;
+	}
+
+	SCSIHOST2ADAP(host)	= (caddr_t)adapter;
+	adapter->host		= host;
+
+	// export the parameters required by the mid-layer
+	scsi_assign_lock(host, adapter->host_lock);
+	scsi_set_device(host, &adapter->pdev->dev);
+
+	host->irq		= adapter->irq;
+	host->unique_id		= adapter->unique_id;
+	host->can_queue		= adapter->max_cmds;
+	host->this_id		= adapter->init_id;
+	host->sg_tablesize	= adapter->sglen;
+	host->max_sectors	= adapter->max_sectors;
+	host->cmd_per_lun	= adapter->cmd_per_lun;
+	host->max_channel	= adapter->max_channel;
+	host->max_id		= adapter->max_target;
+	host->max_lun		= adapter->max_lun;
+
+
+	// notify mid-layer about the new controller
+	if (scsi_add_host(host, &adapter->pdev->dev)) {
+
+		con_log(CL_ANN, (KERN_WARNING
+			"megaraid mbox: scsi_add_host failed\n"));
+
+		scsi_host_put(host);
+
+		return -1;
+	}
+
+	scsi_scan_host(host);
+
+	return 0;
+}
+
+
+/**
+ * megaraid_io_detach - detach a device from the IO subsystem
+ * @param adapter	: controller's soft state
+ *
+ * Detach this device from the IO subsystem
+ **/
+static void
+megaraid_io_detach(adapter_t *adapter)
+{
+	struct Scsi_Host	*host;
+
+	con_log(CL_DLEVEL1, (KERN_INFO "megaraid: io detach\n"));
+
+	host = adapter->host;
+
+	scsi_remove_host(host);
+
+	return;
+}
+
+
+/*
+ * START: Mailbox Low Level Driver
+ *
+ * This is section specific to the single mailbox based controllers
+ */
+
+/**
+ * megaraid_init_mbox - initialize controller
+ * @param adapter	- our soft state
+ *
+ * . Allocate 16-byte aligned mailbox memory for firmware handshake
+ * . Allocate controller's memory resources
+ * . Find out all initialization data
+ * . Allocate memory required for all the commands
+ * . Use internal library of FW routines, build up complete soft state
+ */
+static int __init
+megaraid_init_mbox(adapter_t *adapter)
+{
+	struct pci_dev		*pdev;
+	mraid_device_t		*raid_dev;
+	int			i;
+
+
+	adapter->ito	= MBOX_TIMEOUT;
+	pdev		= adapter->pdev;
+
+	/*
+	 * Allocate and initialize the init data structure for mailbox
+	 * controllers
+	 */
+	raid_dev = kmalloc(sizeof(mraid_device_t), GFP_KERNEL);
+	if (raid_dev == NULL) return -1;
+
+	memset(raid_dev, 0, sizeof(mraid_device_t));
+
+	/*
+	 * Attach the adapter soft state to raid device soft state
+	 */
+	adapter->raid_device	= (caddr_t)raid_dev;
+	raid_dev->fast_load	= megaraid_fast_load;
+
+
+	// our baseport
+	raid_dev->baseport = pci_resource_start(pdev, 0);
+
+	if (pci_request_regions(pdev, "MegaRAID: LSI Logic Corporation") != 0) {
+
+		con_log(CL_ANN, (KERN_WARNING
+				"megaraid: mem region busy\n"));
+
+		goto out_free_raid_dev;
+	}
+
+	raid_dev->baseaddr = (unsigned long)
+			ioremap_nocache(raid_dev->baseport, 128);
+
+	if (!raid_dev->baseaddr) {
+
+		con_log(CL_ANN, (KERN_WARNING
+			"megaraid: could not map hba memory\n") );
+
+		goto out_release_regions;
+	}
+
+	//
+	// Setup the rest of the soft state using the library of FW routines
+	//
+
+	// request IRQ and register the interrupt service routine
+	if (request_irq(adapter->irq, megaraid_isr, SA_SHIRQ, "megaraid",
+		adapter)) {
+
+		con_log(CL_ANN, (KERN_WARNING
+			"megaraid: Couldn't register IRQ %d!\n", adapter->irq));
+
+		goto out_iounmap;
+	}
+
+
+	// initialize the mutual exclusion lock for the mailbox
+	spin_lock_init(&raid_dev->mailbox_lock);
+
+	// allocate memory required for commands
+	if (megaraid_alloc_cmd_packets(adapter) != 0) {
+		goto out_free_irq;
+	}
+
+	// Product info
+	if (megaraid_mbox_product_info(adapter) != 0) {
+		goto out_alloc_cmds;
+	}
+
+	// Do we support extended CDBs
+	adapter->max_cdb_sz = 10;
+	if (megaraid_mbox_extended_cdb(adapter) == 0) {
+		adapter->max_cdb_sz = 16;
+	}
+
+	/*
+	 * Do we support cluster environment, if we do, what is the initiator
+	 * id.
+	 * NOTE: In a non-cluster aware firmware environment, the LLD should
+	 * return 7 as initiator id.
+	 */
+	adapter->ha		= 0;
+	adapter->init_id	= -1;
+	if (megaraid_mbox_support_ha(adapter, &adapter->init_id) == 0) {
+		adapter->ha = 1;
+	}
+
+	/*
+	 * Prepare the device ids array to have the mapping between the kernel
+	 * device address and megaraid device address.
+	 * We export the physical devices on their actual addresses. The
+	 * logical drives are exported on a virtual SCSI channel
+	 */
+	megaraid_mbox_setup_device_map(adapter);
+
+	// If the firmware supports random deletion, update the device id map
+	if (megaraid_mbox_support_random_del(adapter)) {
+
+		// Change the logical drives numbers in device_ids array one
+		// slot in device_ids is reserved for target id, that's why
+		// "<=" below
+		for (i = 0; i <= MAX_LOGICAL_DRIVES_40LD; i++) {
+			adapter->device_ids[adapter->max_channel][i] += 0x80;
+		}
+		adapter->device_ids[adapter->max_channel][adapter->init_id] =
+			0xFF;
+	}
+
+	/*
+	 * find out the maximum number of scatter-gather elements supported by
+	 * this firmware
+	 */
+	adapter->sglen = megaraid_mbox_get_max_sg(adapter);
+
+	// enumerate RAID and SCSI channels so that all devices on SCSI
+	// channels can later be exported, including disk devices
+	megaraid_mbox_enum_raid_scsi(adapter);
+
+	/*
+	 * Other parameters required by upper layer
+	 *
+	 * maximum number of sectors per IO command
+	 */
+	adapter->max_sectors = megaraid_max_sectors;
+
+	/*
+	 * number of queued commands per LUN.
+	 */
+	adapter->cmd_per_lun = megaraid_cmd_per_lun;
+
+	// Set the DMA mask to 64-bit. All supported controllers as capable of
+	// DMA in this range
+	if (pci_set_dma_mask(adapter->pdev, 0xFFFFFFFFFFFFFFFFULL) != 0) {
+
+		con_log(CL_ANN, (KERN_WARNING
+			"megaraid: could not set DMA mask for 64-bit.\n"));
+
+		goto out_alloc_cmds;
+	}
+
+	// setup tasklet for DPC
+	tasklet_init(&adapter->dpc_h, megaraid_mbox_dpc,
+			(unsigned long)adapter);
+
+	con_log(CL_DLEVEL1, (KERN_INFO
+		"megaraid mbox hba successfully initialized\n"));
+
+	return 0;
+
+out_alloc_cmds:
+	megaraid_free_cmd_packets(adapter);
+out_free_irq:
+	free_irq(adapter->irq, adapter);
+out_iounmap:
+	iounmap((caddr_t)raid_dev->baseaddr);
+out_release_regions:
+	pci_release_regions(pdev);
+out_free_raid_dev:
+	kfree(raid_dev);
+
+	return -1;
+}
+
+
+/**
+ * megaraid_fini_mbox - undo controller initialization
+ * @param adapter	: our soft state
+ */
+static void
+megaraid_fini_mbox(adapter_t *adapter)
+{
+	mraid_device_t *raid_dev = ADAP2RAIDDEV(adapter);
+
+	// flush all caches
+	megaraid_mbox_flush_cache(adapter);
+
+	tasklet_kill(&adapter->dpc_h);
+
+	megaraid_free_cmd_packets(adapter);
+
+	free_irq(adapter->irq, adapter);
+
+	iounmap((caddr_t)raid_dev->baseaddr);
+
+	pci_release_regions(adapter->pdev);
+
+	kfree(raid_dev);
+
+	return;
+}
+
+
+/**
+ * megaraid_alloc_cmd_packets - allocate shared mailbox
+ * @param adapter	: soft state of the raid controller
+ *
+ * Allocate and align the shared mailbox. This maibox is used to issue
+ * all the commands. For IO based controllers, the mailbox is also regsitered
+ * with the FW. Allocate memory for all commands as well.
+ * This is our big allocator
+ */
+static int
+megaraid_alloc_cmd_packets(adapter_t *adapter)
+{
+	mraid_device_t		*raid_dev = ADAP2RAIDDEV(adapter);
+	struct pci_dev		*pdev;
+	unsigned long		align;
+	scb_t			*scb;
+	mbox_ccb_t		*ccb;
+	struct mraid_pci_blk	*epthru_pci_blk;
+	struct mraid_pci_blk	*sg_pci_blk;
+	struct mraid_pci_blk	*mbox_pci_blk;
+	int			i;
+
+	pdev = adapter->pdev;
+
+	/*
+	 * Setup the mailbox
+	 * Allocate the common 16-byte aligned memory for the handshake
+	 * mailbox.
+	 */
+	raid_dev->una_mbox64 = pci_alloc_consistent(adapter->pdev,
+			sizeof(mbox64_t), &raid_dev->una_mbox64_dma);
+
+	if (!raid_dev->una_mbox64) {
+		con_log(CL_ANN, (KERN_WARNING
+			"megaraid: out of memory, %s %d\n", __FUNCTION__,
+			__LINE__));
+		return -1;
+	}
+	memset(raid_dev->una_mbox64, 0, sizeof(mbox64_t));
+
+	/*
+	 * Align the mailbox at 16-byte boundary
+	 */
+	raid_dev->mbox	= &raid_dev->una_mbox64->mbox32;
+
+	raid_dev->mbox	= (mbox_t *)((((unsigned long)raid_dev->mbox) + 15) &
+				(~0UL ^ 0xFUL));
+
+	raid_dev->mbox64 = (mbox64_t *)(((unsigned long)raid_dev->mbox) - 8);
+
+	align = ((void *)raid_dev->mbox -
+			((void *)&raid_dev->una_mbox64->mbox32));
+
+	raid_dev->mbox_dma = (unsigned long)raid_dev->una_mbox64_dma + 8 +
+			align;
+
+	// Allocate memory for commands issued internally
+	adapter->ibuf = pci_alloc_consistent(pdev, MBOX_IBUF_SIZE,
+				&adapter->ibuf_dma_h);
+	if (!adapter->ibuf) {
+
+		con_log(CL_ANN, (KERN_WARNING
+			"megaraid: out of memory, %s %d\n", __FUNCTION__,
+			__LINE__));
+
+		goto out_free_common_mbox;
+	}
+	memset(adapter->ibuf, 0, MBOX_IBUF_SIZE);
+
+	// Allocate memory for our SCSI Command Blocks and their associated
+	// memory
+
+	/*
+	 * Allocate memory for the base list of scb. Later allocate memory for
+	 * CCBs and embedded components of each CCB and point the pointers in
+	 * scb to the allocated components
+	 * NOTE: The code to allocate SCB will be duplicated in all the LLD
+	 * since the calling routine does not yet know the number of available
+	 * commands.
+	 */
+	adapter->kscb_list = kmalloc(sizeof(scb_t) * MBOX_MAX_SCSI_CMDS,
+			GFP_KERNEL);
+
+	if (adapter->kscb_list == NULL) {
+		con_log(CL_ANN, (KERN_WARNING
+			"megaraid: out of memory, %s %d\n", __FUNCTION__,
+			__LINE__));
+		goto out_free_ibuf;
+	}
+	memset(adapter->kscb_list, 0, sizeof(scb_t) * MBOX_MAX_SCSI_CMDS);
+
+	// memory allocation for our command packets
+	if (megaraid_mbox_setup_dma_pools(adapter) != 0) {
+		con_log(CL_ANN, (KERN_WARNING
+			"megaraid: out of memory, %s %d\n", __FUNCTION__,
+			__LINE__));
+		goto out_free_scb_list;
+	}
+
+	// Adjust the scb pointers and link in the free pool
+	epthru_pci_blk	= raid_dev->epthru_pool;
+	sg_pci_blk	= raid_dev->sg_pool;
+	mbox_pci_blk	= raid_dev->mbox_pool;
+
+	for (i = 0; i < MBOX_MAX_SCSI_CMDS; i++) {
+		scb			= adapter->kscb_list + i;
+		ccb			= raid_dev->ccb_list + i;
+
+		ccb->mbox	= (mbox_t *)(mbox_pci_blk[i].vaddr + 16);
+		ccb->raw_mbox	= (uint8_t *)ccb->mbox;
+		ccb->mbox64	= (mbox64_t *)(mbox_pci_blk[i].vaddr + 8);
+		ccb->mbox_dma_h	= (unsigned long)mbox_pci_blk[i].dma_addr + 16;
+
+		// make sure the mailbox is aligned properly
+		if (ccb->mbox_dma_h & 0x0F) {
+			con_log(CL_ANN, (KERN_CRIT
+				"megaraid mbox: not aligned on 16-bytes\n"));
+
+			goto out_teardown_dma_pools;
+		}
+
+		ccb->epthru		= (mraid_epassthru_t *)
+						epthru_pci_blk[i].vaddr;
+		ccb->epthru_dma_h	= epthru_pci_blk[i].dma_addr;
+		ccb->pthru		= (mraid_passthru_t *)ccb->epthru;
+		ccb->pthru_dma_h	= ccb->epthru_dma_h;
+
+
+		ccb->sgl64		= (mbox_sgl64 *)sg_pci_blk[i].vaddr;
+		ccb->sgl_dma_h		= sg_pci_blk[i].dma_addr;
+		ccb->sgl32		= (mbox_sgl32 *)ccb->sgl64;
+
+		scb->ccb		= (caddr_t)ccb;
+		scb->gp			= 0;
+
+		scb->sno		= i;	// command index
+
+		scb->scp		= NULL;
+		scb->state		= SCB_FREE;
+		scb->dma_direction	= PCI_DMA_NONE;
+		scb->dma_type		= MRAID_DMA_NONE;
+		scb->dev_channel	= -1;
+		scb->dev_target		= -1;
+
+		// put scb in the free pool
+		list_add_tail(&scb->list, &adapter->kscb_pool);
+	}
+
+	return 0;
+
+out_teardown_dma_pools:
+	megaraid_mbox_teardown_dma_pools(adapter);
+out_free_scb_list:
+	kfree(adapter->kscb_list);
+out_free_ibuf:
+	pci_free_consistent(pdev, MBOX_IBUF_SIZE, (void *)adapter->ibuf,
+		adapter->ibuf_dma_h);
+out_free_common_mbox:
+	pci_free_consistent(adapter->pdev, sizeof(mbox64_t),
+		(caddr_t)raid_dev->una_mbox64, raid_dev->una_mbox64_dma);
+
+	return -1;
+}
+
+
+/**
+ * megaraid_free_cmd_packets - free memory
+ * @param adapter	: soft state of the raid controller
+ *
+ * Release memory resources allocated for commands
+ */
+static void
+megaraid_free_cmd_packets(adapter_t *adapter)
+{
+	mraid_device_t *raid_dev = ADAP2RAIDDEV(adapter);
+
+	megaraid_mbox_teardown_dma_pools(adapter);
+
+	kfree(adapter->kscb_list);
+
+	pci_free_consistent(adapter->pdev, MBOX_IBUF_SIZE,
+		(void *)adapter->ibuf, adapter->ibuf_dma_h);
+
+	pci_free_consistent(adapter->pdev, sizeof(mbox64_t),
+		(caddr_t)raid_dev->una_mbox64, raid_dev->una_mbox64_dma);
+	return;
+}
+
+
+/**
+ * megaraid_mbox_setup_dma_pools - setup dma pool for command packets
+ * @param adapter	: HBA soft state
+ *
+ * setup the dma pools for mailbox, passthru and extended passthru structures,
+ * and scatter-gather lists
+ */
+static int
+megaraid_mbox_setup_dma_pools(adapter_t *adapter)
+{
+	mraid_device_t		*raid_dev = ADAP2RAIDDEV(adapter);
+	struct mraid_pci_blk	*epthru_pci_blk;
+	struct mraid_pci_blk	*sg_pci_blk;
+	struct mraid_pci_blk	*mbox_pci_blk;
+	int			i;
+
+
+
+	// Allocate memory for 16-bytes aligned mailboxes
+	raid_dev->mbox_pool_handle = pci_pool_create("megaraid mbox pool",
+						adapter->pdev,
+						sizeof(mbox64_t) + 16,
+						16, 0);
+
+	if (raid_dev->mbox_pool_handle == NULL) {
+		goto fail_setup_dma_pool;
+	}
+
+	mbox_pci_blk = raid_dev->mbox_pool;
+	for (i = 0; i < MBOX_MAX_SCSI_CMDS; i++) {
+		mbox_pci_blk[i].vaddr = pci_pool_alloc(
+						raid_dev->mbox_pool_handle,
+						GFP_KERNEL,
+						&mbox_pci_blk[i].dma_addr);
+		if (!mbox_pci_blk[i].vaddr) {
+			goto fail_setup_dma_pool;
+		}
+	}
+
+	/*
+	 * Allocate memory for each embedded passthru strucuture pointer
+	 * Request for a 128 bytes aligned structure for each passthru command
+	 * structure
+	 * Since passthru and extended passthru commands are exclusive, they
+	 * share common memory pool. Passthru structures piggyback on memory
+	 * allocted to extended passthru since passthru is smaller of the two
+	 */
+	raid_dev->epthru_pool_handle = pci_pool_create("megaraid mbox pthru",
+			adapter->pdev, sizeof(mraid_epassthru_t), 128, 0);
+
+	if (raid_dev->epthru_pool_handle == NULL) {
+		goto fail_setup_dma_pool;
+	}
+
+	epthru_pci_blk = raid_dev->epthru_pool;
+	for (i = 0; i < MBOX_MAX_SCSI_CMDS; i++) {
+		epthru_pci_blk[i].vaddr = pci_pool_alloc(
+						raid_dev->epthru_pool_handle,
+						GFP_KERNEL,
+						&epthru_pci_blk[i].dma_addr);
+		if (!epthru_pci_blk[i].vaddr) {
+			goto fail_setup_dma_pool;
+		}
+	}
+
+
+	// Allocate memory for each scatter-gather list. Request for 512 bytes
+	// alignment for each sg list
+	raid_dev->sg_pool_handle = pci_pool_create("megaraid mbox sg",
+					adapter->pdev,
+					sizeof(mbox_sgl64) * MBOX_MAX_SG_SIZE,
+					512, 0);
+
+	if (raid_dev->sg_pool_handle == NULL) {
+		goto fail_setup_dma_pool;
+	}
+
+	sg_pci_blk = raid_dev->sg_pool;
+	for (i = 0; i < MBOX_MAX_SCSI_CMDS; i++) {
+		sg_pci_blk[i].vaddr = pci_pool_alloc(
+						raid_dev->sg_pool_handle,
+						GFP_KERNEL,
+						&sg_pci_blk[i].dma_addr);
+		if (!sg_pci_blk[i].vaddr) {
+			goto fail_setup_dma_pool;
+		}
+	}
+
+	return 0;
+
+fail_setup_dma_pool:
+	megaraid_mbox_teardown_dma_pools(adapter);
+	return -1;
+}
+
+
+/**
+ * megaraid_mbox_teardown_dma_pools - teardown dma pools for command packets
+ * @param adapter	: HBA soft state
+ *
+ * teardown the dma pool for mailbox, passthru and extended passthru
+ * structures, and scatter-gather lists
+ */
+static void
+megaraid_mbox_teardown_dma_pools(adapter_t *adapter)
+{
+	mraid_device_t		*raid_dev = ADAP2RAIDDEV(adapter);
+	struct mraid_pci_blk	*epthru_pci_blk;
+	struct mraid_pci_blk	*sg_pci_blk;
+	struct mraid_pci_blk	*mbox_pci_blk;
+	int			i;
+
+
+	sg_pci_blk = raid_dev->sg_pool;
+	for (i = 0; i < MBOX_MAX_SCSI_CMDS && sg_pci_blk[i].vaddr; i++) {
+		pci_pool_free(raid_dev->sg_pool_handle, sg_pci_blk[i].vaddr,
+			sg_pci_blk[i].dma_addr);
+	}
+	if (raid_dev->sg_pool_handle)
+		pci_pool_destroy(raid_dev->sg_pool_handle);
+
+
+	epthru_pci_blk = raid_dev->epthru_pool;
+	for (i = 0; i < MBOX_MAX_SCSI_CMDS && epthru_pci_blk[i].vaddr; i++) {
+		pci_pool_free(raid_dev->epthru_pool_handle,
+			epthru_pci_blk[i].vaddr, epthru_pci_blk[i].dma_addr);
+	}
+	if (raid_dev->epthru_pool_handle)
+		pci_pool_destroy(raid_dev->epthru_pool_handle);
+
+
+	mbox_pci_blk = raid_dev->mbox_pool;
+	for (i = 0; i < MBOX_MAX_SCSI_CMDS && mbox_pci_blk[i].vaddr; i++) {
+		pci_pool_free(raid_dev->mbox_pool_handle,
+			mbox_pci_blk[i].vaddr, mbox_pci_blk[i].dma_addr);
+	}
+	if (raid_dev->mbox_pool_handle)
+		pci_pool_destroy(raid_dev->mbox_pool_handle);
+
+	return;
+}
+
+
+/**
+ * megaraid_alloc_scb - detach and return a scb from the free list
+ * @adapter	: controller's soft state
+ *
+ * return the scb from the head of the free list. NULL if there are none
+ * available
+ **/
+static inline scb_t *
+megaraid_alloc_scb(adapter_t *adapter, struct scsi_cmnd *scp)
+{
+	struct list_head	*head = &adapter->kscb_pool;
+	scb_t			*scb = NULL;
+	unsigned long		flags;
+
+	// detach scb from free pool
+	spin_lock_irqsave(SCSI_FREE_LIST_LOCK(adapter), flags);
+
+	if (list_empty(head)) {
+		spin_unlock_irqrestore(SCSI_FREE_LIST_LOCK(adapter), flags);
+		return NULL;
+	}
+
+	scb = list_entry(head->next, scb_t, list);
+	list_del_init(&scb->list);
+
+	spin_unlock_irqrestore(SCSI_FREE_LIST_LOCK(adapter), flags);
+
+	scb->state	= SCB_ACTIVE;
+	scb->scp	= scp;
+	scb->dma_type	= MRAID_DMA_NONE;
+
+	return scb;
+}
+
+
+/**
+ * megaraid_dealloc_scb - return the scb to the free pool
+ * @adapter	: controller's soft state
+ * @scb		: scb to be freed
+ *
+ * return the scb back to the free list of scbs. The caller must 'flush' the
+ * SCB before calling us. E.g., performing pci_unamp and/or pci_sync etc.
+ * NOTE NOTE: Make sure the scb is not on any list before calling this
+ * routine.
+ **/
+static inline void
+megaraid_dealloc_scb(adapter_t *adapter, scb_t *scb)
+{
+	unsigned long		flags;
+
+	// put scb in the free pool
+	scb->state	= SCB_FREE;
+	scb->scp	= NULL;
+	spin_lock_irqsave(SCSI_FREE_LIST_LOCK(adapter), flags);
+
+	list_add(&scb->list, &adapter->kscb_pool);
+
+	spin_unlock_irqrestore(SCSI_FREE_LIST_LOCK(adapter), flags);
+
+	return;
+}
+
+
+/**
+ * megaraid_mbox_mksgl - make the scatter-gather list
+ * @adapter	- controller's soft state
+ * @scb		- scsi control block
+ *
+ * prepare the scatter-gather list
+ */
+static inline int
+megaraid_mbox_mksgl(adapter_t *adapter, scb_t *scb)
+{
+	struct scatterlist	*sgl;
+	mbox_ccb_t		*ccb;
+	struct page		*page;
+	unsigned long		offset;
+	struct scsi_cmnd	*scp;
+	int			sgcnt;
+	int			i;
+
+
+	scp	= scb->scp;
+	ccb	= (mbox_ccb_t *)scb->ccb;
+
+	// no mapping required if no data to be transferred
+	if (!scp->request_buffer || !scp->request_bufflen)
+		return 0;
+
+	if (!scp->use_sg) {	/* scatter-gather list not used */
+
+		page = virt_to_page(scp->request_buffer);
+
+		offset = ((unsigned long)scp->request_buffer & ~PAGE_MASK);
+
+		ccb->buf_dma_h = pci_map_page(adapter->pdev, page, offset,
+						  scp->request_bufflen,
+						  scb->dma_direction);
+		scb->dma_type = MRAID_DMA_WBUF;
+
+		/*
+		 * We need to handle special 64-bit commands that need a
+		 * minimum of 1 SG
+		 */
+		sgcnt = 1;
+		ccb->sgl64[0].address	= ccb->buf_dma_h;
+		ccb->sgl64[0].length	= scp->request_bufflen;
+
+		return sgcnt;
+	}
+
+	sgl = (struct scatterlist *)scp->request_buffer;
+
+	// The number of sg elements returned must not exceed our limit
+	sgcnt = pci_map_sg(adapter->pdev, sgl, scp->use_sg,
+			scb->dma_direction);
+
+	if (sgcnt > adapter->sglen) {
+		con_log(CL_ANN, (KERN_CRIT
+			"megaraid critical: too many sg elements:%d\n",
+			sgcnt));
+		BUG();
+	}
+
+	scb->dma_type = MRAID_DMA_WSG;
+
+	for (i = 0; i < sgcnt; i++, sgl++) {
+		ccb->sgl64[i].address	= sg_dma_address(sgl);
+		ccb->sgl64[i].length	= sg_dma_len(sgl);
+	}
+
+	// Return count of SG nodes
+	return sgcnt;
+}
+
+
+/**
+ * mbox_post_cmd - issue a mailbox command
+ * @adapter	- controller's soft state
+ * @scb		- command to be issued
+ *
+ * post the command to the controller if mailbox is availble.
+ */
+static inline int
+mbox_post_cmd(adapter_t *adapter, scb_t *scb)
+{
+	mraid_device_t	*raid_dev = ADAP2RAIDDEV(adapter);
+	mbox64_t	*mbox64;
+	mbox_t		*mbox;
+	mbox_ccb_t	*ccb;
+	unsigned long	flags;
+	unsigned int	i = 0;
+
+
+	ccb	= (mbox_ccb_t *)scb->ccb;
+	mbox	= raid_dev->mbox;
+	mbox64	= raid_dev->mbox64;
+
+	/*
+	 * Check for busy mailbox. If it is, return failure - the caller
+	 * should retry later.
+	 */
+	spin_lock_irqsave(MAILBOX_LOCK(raid_dev), flags);
+
+	if (unlikely(mbox->busy)) {
+		do {
+			udelay(1);
+			i++;
+			rmb();
+		} while(mbox->busy && (i < max_mbox_busy_wait));
+
+		if (mbox->busy) {
+
+			spin_unlock_irqrestore(MAILBOX_LOCK(raid_dev), flags);
+
+			return -1;
+		}
+	}
+
+
+	// Copy this command's mailbox data into "adapter's" mailbox
+	memcpy((caddr_t)mbox64, (caddr_t)ccb->mbox64, 22);
+	mbox->cmdid = scb->sno;
+
+	adapter->outstanding_cmds++;
+
+	if (scb->dma_direction == PCI_DMA_TODEVICE) {
+		if (!scb->scp->use_sg) {	// sg list not used
+			pci_dma_sync_single(adapter->pdev, ccb->buf_dma_h,
+					scb->scp->request_bufflen,
+					PCI_DMA_TODEVICE);
+		}
+		else {
+			pci_dma_sync_sg(adapter->pdev, scb->scp->request_buffer,
+				scb->scp->use_sg, PCI_DMA_TODEVICE);
+		}
+	}
+
+	mbox->busy	= 1;	// Set busy
+	mbox->poll	= 0;
+	mbox->ack	= 0;
+	wmb();
+
+	WRINDOOR(raid_dev, raid_dev->mbox_dma | 0x1);
+
+	spin_unlock_irqrestore(MAILBOX_LOCK(raid_dev), flags);
+
+	return 0;
+}
+
+
+/**
+ * megaraid_queue_command - generic queue entry point for all LLDs
+ * @scp		: pointer to the scsi command to be executed
+ * @done	: callback routine to be called after the cmd has be completed
+ *
+ * Queue entry point for mailbox based controllers.
+ */
+static int
+megaraid_queue_command(struct scsi_cmnd *scp, void (* done)(struct scsi_cmnd *))
+{
+	adapter_t	*adapter;
+	scb_t		*scb;
+	int		if_busy;
+
+	adapter		= SCP2ADAPTER(scp);
+	scp->scsi_done	= done;
+	scp->result	= 0;
+
+	ASSERT(spin_is_locked(adapter->host_lock));
+
+	spin_unlock(adapter->host_lock);
+
+	/*
+	 * Allocate and build a SCB request
+	 * if_busy flag will be set if megaraid_mbox_build_cmd() command could
+	 * not allocate scb. We will return non-zero status in that case.
+	 * NOTE: scb can be null even though certain commands completed
+	 * successfully, e.g., MODE_SENSE and TEST_UNIT_READY, it would
+	 * return 0 in that case, and we would do the callback right away.
+	 */
+	if_busy	= 0;
+	scb	= megaraid_mbox_build_cmd(adapter, scp, &if_busy);
+
+	if (scb) {
+		megaraid_mbox_runpendq(adapter, scb);
+	}
+
+	spin_lock(adapter->host_lock);
+
+	if (!scb) {	// command already completed
+		done(scp);
+	}
+
+	return if_busy;
+}
+
+
+/**
+ * megaraid_mbox_build_cmd - transform the mid-layer scsi command to megaraid
+ * firmware lingua
+ * @adapter	- controller's soft state
+ * @scp		- mid-layer scsi command pointer
+ * @busy	- set if request could not be completed because of lack of
+ *		resources
+ *
+ * convert the command issued by mid-layer to format understood by megaraid
+ * firmware. We also complete certain command without sending them to firmware
+ */
+static scb_t *
+megaraid_mbox_build_cmd(adapter_t *adapter, struct scsi_cmnd *scp, int *busy)
+{
+	mraid_device_t		*rdev = ADAP2RAIDDEV(adapter);
+	int			channel;
+	int			target;
+	int			islogical;
+	mbox_ccb_t		*ccb;
+	mraid_passthru_t	*pthru;
+	mbox64_t		*mbox64;
+	mbox_t			*mbox;
+	scb_t			*scb;
+	char			skip[] = "skipping";
+	char			scan[] = "scanning";
+	char			*ss;
+
+
+	/*
+	 * Get the appropriate device map for the device this command is
+	 * intended for
+	 */
+	MRAID_GET_DEVICE_MAP(adapter, scp, channel, target, islogical);
+
+	/*
+	 * Logical drive commands
+	 */
+	if (islogical) {
+		switch (scp->cmnd[0]) {
+		case TEST_UNIT_READY:
+			/*
+			 * Do we support clustering and is the support enabled
+			 * If no, return success always
+			 */
+			if (!adapter->ha) {
+				scp->result = (DID_OK << 16);
+				return NULL;
+			}
+
+			if (!(scb = megaraid_alloc_scb(adapter, scp))) {
+				scp->result = (DID_ERROR << 16);
+				*busy = 1;
+				return NULL;
+			}
+
+			scb->dma_direction	= scp->sc_data_direction;
+			scb->dev_channel	= 0xFF;
+			scb->dev_target		= target;
+			ccb			= (mbox_ccb_t *)scb->ccb;
+
+			/*
+			 * The command id will be provided by the command
+			 * issuance routine
+			 */
+			ccb->raw_mbox[0]	= CLUSTER_CMD;
+			ccb->raw_mbox[2]	= RESERVATION_STATUS;
+			ccb->raw_mbox[3]	= target;
+
+			return scb;
+
+		case MODE_SENSE:
+			if (scp->use_sg) {
+				struct scatterlist	*sgl;
+				caddr_t			vaddr;
+
+				sgl = (struct scatterlist *)scp->request_buffer;
+				if (sgl->page) {
+					vaddr = (caddr_t)
+						(page_address((&sgl[0])->page)
+						+ (&sgl[0])->offset);
+
+					memset(vaddr, 0, scp->cmnd[4]);
+				}
+				else {
+					con_log(CL_ANN, (KERN_WARNING
+					"megaraid mailbox: invalid sg:%d\n",
+					__LINE__));
+				}
+			}
+			else {
+				memset(scp->request_buffer, 0, scp->cmnd[4]);
+			}
+			scp->result = (DID_OK << 16);
+			return NULL;
+
+		case INQUIRY:
+			/*
+			 * Display the channel scan for logical drives
+			 * Do not display scan for a channel if already done.
+			 */
+			if (!(rdev->last_disp & (1L << SCP2CHANNEL(scp)))) {
+
+				con_log(CL_ANN, (KERN_INFO
+					"scsi[%d]: scanning scsi channel %d",
+					adapter->host->host_no,
+					SCP2CHANNEL(scp)));
+
+				con_log(CL_ANN, (
+					" [virtual] for logical drives\n"));
+
+				rdev->last_disp |= (1L << SCP2CHANNEL(scp));
+			}
+
+			/* Fall through */
+
+		case READ_CAPACITY:
+			/*
+			 * Do not allow LUN > 0 for logical drives and
+			 * requests for more than 40 logical drives
+			 */
+			if (SCP2LUN(scp)) {
+				scp->result = (DID_BAD_TARGET << 16);
+				return NULL;
+			}
+			if ((target % 0x80) >= MAX_LOGICAL_DRIVES_40LD) {
+				scp->result = (DID_BAD_TARGET << 16);
+				return NULL;
+			}
+
+
+			/* Allocate a SCB and initialize passthru */
+			if (!(scb = megaraid_alloc_scb(adapter, scp))) {
+				scp->result = (DID_ERROR << 16);
+				*busy = 1;
+				return NULL;
+			}
+
+			ccb			= (mbox_ccb_t *)scb->ccb;
+			scb->dev_channel	= 0xFF;
+			scb->dev_target		= target;
+			pthru			= ccb->pthru;
+			mbox			= ccb->mbox;
+			mbox64			= ccb->mbox64;
+
+			pthru->timeout		= 0;
+			pthru->ars		= 1;
+			pthru->reqsenselen	= 14;
+			pthru->islogical	= 1;
+			pthru->logdrv		= target;
+			pthru->cdblen		= scp->cmd_len;
+			memcpy(pthru->cdb, scp->cmnd, scp->cmd_len);
+
+			mbox->cmd		= MBOXCMD_PASSTHRU64;
+			scb->dma_direction	= scp->sc_data_direction;
+
+			pthru->dataxferlen	= scp->request_bufflen;
+			pthru->dataxferaddr	= ccb->sgl_dma_h;
+			pthru->numsge		= megaraid_mbox_mksgl(adapter,
+							scb);
+
+			mbox->xferaddr		= 0xFFFFFFFF;
+			mbox64->xferaddr_lo	= (uint32_t )ccb->pthru_dma_h;
+			mbox64->xferaddr_hi	= 0;
+
+			return scb;
+
+		case READ_6:
+		case WRITE_6:
+		case READ_10:
+		case WRITE_10:
+		case READ_12:
+		case WRITE_12:
+
+			/*
+			 * Allocate a SCB and initialize mailbox
+			 */
+			if (!(scb = megaraid_alloc_scb(adapter, scp))) {
+				scp->result = (DID_ERROR << 16);
+				*busy = 1;
+				return NULL;
+			}
+			ccb			= (mbox_ccb_t *)scb->ccb;
+			scb->dev_channel	= 0xFF;
+			scb->dev_target		= target;
+			mbox			= ccb->mbox;
+			mbox64			= ccb->mbox64;
+			mbox->logdrv		= target;
+
+			/*
+			 * A little HACK: 2nd bit is zero for all scsi read
+			 * commands and is set for all scsi write commands
+			 */
+			mbox->cmd = (scp->cmnd[0] & 0x02) ?  MBOXCMD_LWRITE64:
+					MBOXCMD_LREAD64 ;
+
+			/*
+			 * 6-byte READ(0x08) or WRITE(0x0A) cdb
+			 */
+			if (scp->cmd_len == 6) {
+				mbox->numsectors = (uint32_t)scp->cmnd[4];
+				mbox->lba =
+					((uint32_t)scp->cmnd[1] << 16)	|
+					((uint32_t)scp->cmnd[2] << 8)	|
+					(uint32_t)scp->cmnd[3];
+
+				mbox->lba &= 0x1FFFFF;
+			}
+
+			/*
+			 * 10-byte READ(0x28) or WRITE(0x2A) cdb
+			 */
+			else if (scp->cmd_len == 10) {
+				mbox->numsectors =
+					(uint32_t)scp->cmnd[8] |
+					((uint32_t)scp->cmnd[7] << 8);
+				mbox->lba =
+					((uint32_t)scp->cmnd[2] << 24) |
+					((uint32_t)scp->cmnd[3] << 16) |
+					((uint32_t)scp->cmnd[4] << 8) |
+					(uint32_t)scp->cmnd[5];
+			}
+
+			/*
+			 * 12-byte READ(0xA8) or WRITE(0xAA) cdb
+			 */
+			else if (scp->cmd_len == 12) {
+				mbox->lba =
+					((uint32_t)scp->cmnd[2] << 24) |
+					((uint32_t)scp->cmnd[3] << 16) |
+					((uint32_t)scp->cmnd[4] << 8) |
+					(uint32_t)scp->cmnd[5];
+
+				mbox->numsectors =
+					((uint32_t)scp->cmnd[6] << 24) |
+					((uint32_t)scp->cmnd[7] << 16) |
+					((uint32_t)scp->cmnd[8] << 8) |
+					(uint32_t)scp->cmnd[9];
+			}
+			else {
+				con_log(CL_ANN, (KERN_WARNING
+					"megaraid: unsupported CDB length\n"));
+
+				megaraid_dealloc_scb(adapter, scb);
+
+				scp->result = (DID_ERROR << 16);
+				return NULL;
+			}
+
+			scb->dma_direction = scp->sc_data_direction;
+
+			// Calculate Scatter-Gather info
+			mbox64->xferaddr_lo	= (uint32_t )ccb->sgl_dma_h;
+			mbox->numsge		= megaraid_mbox_mksgl(adapter,
+							scb);
+			mbox->xferaddr		= 0xFFFFFFFF;
+			mbox64->xferaddr_hi	= 0;
+
+			return scb;
+
+		case RESERVE:
+		case RELEASE:
+			/*
+			 * Do we support clustering and is the support enabled
+			 */
+			if (!adapter->ha) {
+				scp->result = (DID_BAD_TARGET << 16);
+				return NULL;
+			}
+
+			/*
+			 * Allocate a SCB and initialize mailbox
+			 */
+			if (!(scb = megaraid_alloc_scb(adapter, scp))) {
+				scp->result = (DID_ERROR << 16);
+				*busy = 1;
+				return NULL;
+			}
+
+			ccb			= (mbox_ccb_t *)scb->ccb;
+			scb->dev_channel	= 0xFF;
+			scb->dev_target		= target;
+			ccb->raw_mbox[0]	= CLUSTER_CMD;
+			ccb->raw_mbox[2]	=  (scp->cmnd[0] == RESERVE) ?
+						RESERVE_LD : RELEASE_LD;
+
+			ccb->raw_mbox[3]	= target;
+			scb->dma_direction	= scp->sc_data_direction;
+
+			return scb;
+
+		default:
+			scp->result = (DID_BAD_TARGET << 16);
+			return NULL;
+		}
+	}
+	else { // Passthru device commands
+
+		// Do not allow access to target id > 15 or LUN > 7
+		if (target > 15 || SCP2LUN(scp) > 7) {
+			scp->result = (DID_BAD_TARGET << 16);
+			return NULL;
+		}
+
+		// if fast load option was set and scan for last device is
+		// over, reset the fast_load flag so that during a possible
+		// next scan, devices can be made available
+		if (rdev->fast_load && (target == 15) &&
+			(SCP2CHANNEL(scp) == adapter->max_channel -1)) {
+
+			con_log(CL_ANN, (KERN_INFO
+			"megaraid[%d]: physical device scan re-enabled\n",
+				adapter->host->host_no));
+			rdev->fast_load = 0;
+		}
+
+		/*
+		 * Display the channel scan for physical devices
+		 */
+		if (!(rdev->last_disp & (1L << SCP2CHANNEL(scp)))) {
+
+			ss = rdev->fast_load ? skip : scan;
+
+			con_log(CL_ANN, (KERN_INFO
+				"scsi[%d]: %s scsi channel %d [Phy %d]",
+				adapter->host->host_no, ss, SCP2CHANNEL(scp),
+				channel));
+
+			con_log(CL_ANN, (
+				" for non-raid devices\n"));
+
+			rdev->last_disp |= (1L << SCP2CHANNEL(scp));
+		}
+
+		// disable channel sweep if fast load option given
+		if (rdev->fast_load) {
+			scp->result = (DID_BAD_TARGET << 16);
+			return NULL;
+		}
+
+		// Allocate a SCB and initialize passthru
+		if (!(scb = megaraid_alloc_scb(adapter, scp))) {
+			scp->result = (DID_ERROR << 16);
+			*busy = 1;
+			return NULL;
+		}
+
+		ccb			= (mbox_ccb_t *)scb->ccb;
+		scb->dev_channel	= channel;
+		scb->dev_target		= target;
+		scb->dma_direction	= scp->sc_data_direction;
+		mbox			= ccb->mbox;
+		mbox64			= ccb->mbox64;
+
+		// Does this firmware support extended CDBs
+		if (adapter->max_cdb_sz == 16) {
+			mbox->cmd		= MBOXCMD_EXTPTHRU;
+
+			megaraid_mbox_prepare_epthru(adapter, scb, scp);
+
+			mbox64->xferaddr_lo	= (uint32_t)ccb->epthru_dma_h;
+			mbox64->xferaddr_hi	= 0;
+			mbox->xferaddr		= 0xFFFFFFFF;
+		}
+		else {
+			mbox->cmd = MBOXCMD_PASSTHRU64;
+
+			megaraid_mbox_prepare_pthru(adapter, scb, scp);
+
+			mbox64->xferaddr_lo	= (uint32_t)ccb->pthru_dma_h;
+			mbox64->xferaddr_hi	= 0;
+			mbox->xferaddr		= 0xFFFFFFFF;
+		}
+		return scb;
+	}
+
+	// NOT REACHED
+}
+
+
+/**
+ * megaraid_mbox_runpendq - execute commands queued in the pending queue
+ * @adapter	: controller's soft state
+ * @scb		: SCB to be queued in the pending list
+ *
+ * scan the pending list for commands which are not yet issued and try to
+ * post to the controller. The SCB can be a null pointer, which would indicate
+ * no SCB to be queue, just try to execute the ones in the pending list.
+ *
+ * NOTE: We do not actually traverse the pending list. The SCBs are plucked
+ * out from the head of the pending list. If it is successfully issued, the
+ * next SCB is at the head now.
+ */
+static void
+megaraid_mbox_runpendq(adapter_t *adapter, scb_t *scb_q)
+{
+	scb_t			*scb;
+	unsigned long		flags;
+
+	spin_lock_irqsave(PENDING_LIST_LOCK(adapter), flags);
+
+	if (scb_q) {
+		scb_q->state = SCB_PENDQ;
+		list_add_tail(&scb_q->list, &adapter->pend_list);
+	}
+
+	// if the adapter in not in quiescent mode, post the commands to FW
+	if (adapter->quiescent) {
+		spin_unlock_irqrestore(PENDING_LIST_LOCK(adapter), flags);
+		return;
+	}
+
+	while (!list_empty(&adapter->pend_list)) {
+
+		ASSERT(spin_is_locked(PENDING_LIST_LOCK(adapter)));
+
+		scb = list_entry(adapter->pend_list.next, scb_t, list);
+
+		// remove the scb from the pending list and try to
+		// issue. If we are unable to issue it, put back in
+		// the pending list and return
+
+		list_del_init(&scb->list);
+
+		spin_unlock_irqrestore(PENDING_LIST_LOCK(adapter), flags);
+
+		// if mailbox was busy, return SCB back to pending
+		// list. Make sure to add at the head, since that's
+		// where it would have been removed from
+
+		scb->state = SCB_ISSUED;
+
+		if (mbox_post_cmd(adapter, scb) != 0) {
+
+			spin_lock_irqsave(PENDING_LIST_LOCK(adapter), flags);
+
+			scb->state = SCB_PENDQ;
+
+			list_add(&scb->list, &adapter->pend_list);
+
+			spin_unlock_irqrestore(PENDING_LIST_LOCK(adapter),
+				flags);
+
+			return;
+		}
+
+		spin_lock_irqsave(PENDING_LIST_LOCK(adapter), flags);
+	}
+
+	spin_unlock_irqrestore(PENDING_LIST_LOCK(adapter), flags);
+
+
+	return;
+}
+
+
+/**
+ * megaraid_mbox_prepare_pthru - prepare a command for physical devices
+ * @adapter	- pointer to controller's soft state
+ * @scb		- scsi control block
+ * @scp		- scsi command from the mid-layer
+ *
+ * prepare a command for the scsi physical devices
+ */
+static void
+megaraid_mbox_prepare_pthru(adapter_t *adapter, scb_t *scb,
+		struct scsi_cmnd *scp)
+{
+	mbox_ccb_t		*ccb;
+	mraid_passthru_t	*pthru;
+	uint8_t			channel;
+	uint8_t			target;
+
+	ccb	= (mbox_ccb_t *)scb->ccb;
+	pthru	= ccb->pthru;
+	channel	= scb->dev_channel;
+	target	= scb->dev_target;
+
+	pthru->timeout		= 1;	// 0=6sec, 1=60sec, 2=10min, 3=3hrs
+	pthru->ars		= 1;
+	pthru->islogical	= 0;
+	pthru->channel		= 0;
+	pthru->target		= (channel << 4) | target;
+	pthru->logdrv		= SCP2LUN(scp);
+	pthru->reqsenselen	= 14;
+	pthru->cdblen		= scp->cmd_len;
+
+	memcpy(pthru->cdb, scp->cmnd, scp->cmd_len);
+
+	if (scp->request_bufflen) {
+		pthru->dataxferlen	= scp->request_bufflen;
+		pthru->dataxferaddr	= ccb->sgl_dma_h;
+		pthru->numsge		= megaraid_mbox_mksgl(adapter, scb);
+	}
+	else {
+		pthru->dataxferaddr	= 0;
+		pthru->dataxferlen	= 0;
+		pthru->numsge		= 0;
+	}
+	return;
+}
+
+
+/**
+ * megaraid_mbox_prepare_epthru - prepare a command for physical devices
+ * @adapter	- pointer to controller's soft state
+ * @scb		- scsi control block
+ * @scp		- scsi command from the mid-layer
+ *
+ * prepare a command for the scsi physical devices. This rountine prepares
+ * commands for devices which can take extended CDBs (>10 bytes)
+ */
+static void
+megaraid_mbox_prepare_epthru(adapter_t *adapter, scb_t *scb,
+		struct scsi_cmnd *scp)
+{
+	mbox_ccb_t		*ccb;
+	mraid_epassthru_t	*epthru;
+	uint8_t			channel;
+	uint8_t			target;
+
+	ccb	= (mbox_ccb_t *)scb->ccb;
+	epthru	= ccb->epthru;
+	channel	= scb->dev_channel;
+	target	= scb->dev_target;
+
+	epthru->timeout		= 1;	// 0=6sec, 1=60sec, 2=10min, 3=3hrs
+	epthru->ars		= 1;
+	epthru->islogical	= 0;
+	epthru->channel		= 0;
+	epthru->target		= (channel << 4) | target;
+	epthru->logdrv		= SCP2LUN(scp);
+	epthru->reqsenselen	= 14;
+	epthru->cdblen		= scp->cmd_len;
+
+	memcpy(epthru->cdb, scp->cmnd, scp->cmd_len);
+
+	if (scp->request_bufflen) {
+		epthru->dataxferlen	= scp->request_bufflen;
+		epthru->dataxferaddr	= ccb->sgl_dma_h;
+		epthru->numsge		= megaraid_mbox_mksgl(adapter, scb);
+	}
+	else {
+		epthru->dataxferaddr	= 0;
+		epthru->dataxferlen	= 0;
+		epthru->numsge		= 0;
+	}
+	return;
+}
+
+
+/**
+ * megaraid_ack_sequence - interrupt ack sequence for memory mapped HBAs
+ * @adapter	- controller's soft state
+ *
+ * Interrupt ackrowledgement sequence for memory mapped HBAs. Find out the
+ * completed command and put them on the completed list for later processing.
+ *
+ * Returns:	1 if the interrupt is valid, 0 otherwise
+ */
+static inline int
+megaraid_ack_sequence(adapter_t *adapter)
+{
+	mraid_device_t		*raid_dev = ADAP2RAIDDEV(adapter);
+	mbox_t			*mbox;
+	scb_t			*scb;
+	uint8_t			nstatus;
+	uint8_t			completed[MBOX_MAX_FIRMWARE_STATUS];
+	struct list_head	clist;
+	int			handled;
+	uint32_t		dword;
+	unsigned long		flags;
+	int			i, j;
+
+
+	mbox	= raid_dev->mbox;
+
+	// move the SCBs from the firmware completed array to our local list
+	INIT_LIST_HEAD(&clist);
+
+	// loop till F/W has more commands for us to complete
+	handled = 0;
+	spin_lock_irqsave(MAILBOX_LOCK(raid_dev), flags);
+	do {
+		/*
+		 * Check if a valid interrupt is pending. If found, force the
+		 * interrupt line low.
+		 */
+		dword = RDOUTDOOR(raid_dev);
+		if (dword != 0x10001234) break;
+
+		handled = 1;
+
+		WROUTDOOR(raid_dev, 0x10001234);
+
+		nstatus = 0;
+		// wait for valid numstatus to post
+		for (i = 0; i < 0xFFFFF; i++) {
+			if (mbox->numstatus != 0xFF) {
+				nstatus = mbox->numstatus;
+				break;
+			}
+			rmb();
+		}
+		mbox->numstatus = 0xFF;
+
+		adapter->outstanding_cmds -= nstatus;
+
+		for (i = 0; i < nstatus; i++) {
+
+			// wait for valid command index to post
+			for (j = 0; j < 0xFFFFF; j++) {
+				if (mbox->completed[i] != 0xFF) break;
+				rmb();
+			}
+			completed[i]		= mbox->completed[i];
+			mbox->completed[i]	= 0xFF;
+
+			if (completed[i] == 0xFF) {
+				con_log(CL_ANN, (KERN_CRIT
+				"megaraid: command posting timed out\n"));
+
+				BUG();
+				continue;
+			}
+
+			// Get SCB associated with this command id
+			if (completed[i] >= MBOX_MAX_SCSI_CMDS) {
+				// a cmm command
+				scb = adapter->uscb_list + (completed[i] -
+						MBOX_MAX_SCSI_CMDS);
+			}
+			else {
+				// an os command
+				scb = adapter->kscb_list + completed[i];
+			}
+
+			scb->status = mbox->status;
+			list_add_tail(&scb->list, &clist);
+		}
+
+		// Acknowledge interrupt
+		WRINDOOR(raid_dev, 0x02);
+
+	} while(1);
+
+	spin_unlock_irqrestore(MAILBOX_LOCK(raid_dev), flags);
+
+
+	// put the completed commands in the completed list. DPC would
+	// complete these commands later
+	spin_lock_irqsave(COMPLETED_LIST_LOCK(adapter), flags);
+
+	list_splice(&clist, &adapter->completed_list);
+
+	spin_unlock_irqrestore(COMPLETED_LIST_LOCK(adapter), flags);
+
+
+	// schedule the DPC if there is some work for it
+	if (handled)
+		tasklet_schedule(&adapter->dpc_h);
+
+	return handled;
+}
+
+
+/**
+ * megaraid_isr - isr for memory based mailbox based controllers
+ * @irq		- irq
+ * @devp	- pointer to our soft state
+ * @regs	- unused
+ *
+ * Interrupt service routine for memory-mapped mailbox controllers.
+ */
+static irqreturn_t
+megaraid_isr(int irq, void *devp, struct pt_regs *regs)
+{
+	adapter_t	*adapter = devp;
+	int		handled;
+
+	handled = megaraid_ack_sequence(adapter);
+
+	/* Loop through any pending requests */
+	if (!adapter->quiescent) {
+		megaraid_mbox_runpendq(adapter, NULL);
+	}
+
+	return IRQ_RETVAL(handled);
+}
+
+
+/**
+ * megaraid_mbox_sync_scb - sync kernel buffers
+ * @adapter	: controller's soft state
+ * @scb		: pointer to the resource packet
+ *
+ * DMA sync if required.
+ */
+static inline void
+megaraid_mbox_sync_scb(adapter_t *adapter, scb_t *scb)
+{
+	mbox_ccb_t	*ccb;
+
+	ccb	= (mbox_ccb_t *)scb->ccb;
+
+	switch (scb->dma_type) {
+
+	case MRAID_DMA_WBUF:
+		if (scb->dma_direction == PCI_DMA_FROMDEVICE) {
+			pci_dma_sync_single(adapter->pdev,
+					ccb->buf_dma_h,
+					scb->scp->request_bufflen,
+					PCI_DMA_FROMDEVICE);
+		}
+
+		pci_unmap_page(adapter->pdev, ccb->buf_dma_h,
+			scb->scp->request_bufflen, scb->dma_direction);
+
+		break;
+
+	case MRAID_DMA_WSG:
+		if (scb->dma_direction == PCI_DMA_FROMDEVICE) {
+			pci_dma_sync_sg(adapter->pdev,
+					scb->scp->request_buffer,
+					scb->scp->use_sg, PCI_DMA_FROMDEVICE);
+		}
+
+		pci_unmap_sg(adapter->pdev, scb->scp->request_buffer,
+			scb->scp->use_sg, scb->dma_direction);
+
+		break;
+
+	default:
+		break;
+	}
+
+	return;
+}
+
+
+/**
+ * megaraid_mbox_dpc - the tasklet to complete the commands from completed list
+ * @devp	: pointer to HBA soft state
+ *
+ * Pick up the commands from the completed list and send back to the owners.
+ * This is a reentrant function and does not assume any locks are held while
+ * it is being called.
+ */
+static void
+megaraid_mbox_dpc(unsigned long devp)
+{
+	adapter_t		*adapter = (adapter_t *)devp;
+	mraid_device_t		*raid_dev;
+	struct list_head	clist;
+	struct scatterlist	*sgl;
+	scb_t			*scb;
+	scb_t			*tmp;
+	struct scsi_cmnd	*scp;
+	mraid_passthru_t	*pthru;
+	mraid_epassthru_t	*epthru;
+	mbox_ccb_t		*ccb;
+	int			islogical;
+	int			pdev_index;
+	int			pdev_state;
+	mbox_t			*mbox;
+	unsigned long		flags;
+	uint8_t			c;
+	int			status;
+
+
+	if (!adapter) return;
+
+	raid_dev = ADAP2RAIDDEV(adapter);
+
+	// move the SCBs from the completed list to our local list
+	INIT_LIST_HEAD(&clist);
+
+	spin_lock_irqsave(COMPLETED_LIST_LOCK(adapter), flags);
+
+	list_splice_init(&adapter->completed_list, &clist);
+
+	spin_unlock_irqrestore(COMPLETED_LIST_LOCK(adapter), flags);
+
+
+	list_for_each_entry_safe(scb, tmp, &clist, list) {
+
+		status		= scb->status;
+		scp		= scb->scp;
+		ccb		= (mbox_ccb_t *)scb->ccb;
+		pthru		= ccb->pthru;
+		epthru		= ccb->epthru;
+		mbox		= ccb->mbox;
+
+		// Make sure f/w has completed a valid command
+		if (scb->state != SCB_ISSUED) {
+			con_log(CL_ANN, (KERN_CRIT
+			"megaraid critical err: invalid command %d:%d:%p\n",
+				scb->sno, scb->state, scp));
+			BUG();
+			continue;	// Must never happen!
+		}
+
+		// check for the management command and complete it right away
+		if (scb->sno >= MBOX_MAX_SCSI_CMDS) {
+			scb->state	= SCB_FREE;
+			scb->status	= status;
+
+			// remove from local clist
+			list_del_init(&scb->list);
+
+			megaraid_mbox_mm_done(adapter, scb);
+
+			continue;
+		}
+
+		// Was an abort issued for this command earlier
+		if (scb->state & SCB_ABORT) {
+			con_log(CL_ANN, (KERN_NOTICE
+			"megaraid: aborted cmd %lx[%x] completed\n",
+				scp->serial_number, scb->sno));
+		}
+
+		/*
+		 * If the inquiry came of a disk drive which is not part of
+		 * any RAID array, expose it to the kernel. For this to be
+		 * enabled, user must set the "megaraid_expose_unconf_disks"
+		 * flag to 1 by specifying it on module parameter list.
+		 * This would enable data migration off drives from other
+		 * configurations.
+		 */
+		islogical = MRAID_IS_LOGICAL(adapter, scp);
+		if (scp->cmnd[0] == INQUIRY && status == 0 && islogical == 0
+				&& IS_RAID_CH(raid_dev, scb->dev_channel)) {
+
+			if (scp->use_sg) {
+				sgl = (struct scatterlist *)
+					scp->request_buffer;
+
+				if (sgl->page) {
+					c = *(unsigned char *)
+					(page_address((&sgl[0])->page) +
+						(&sgl[0])->offset);
+				}
+				else {
+					con_log(CL_ANN, (KERN_WARNING
+					"megaraid mailbox: invalid sg:%d\n",
+					__LINE__));
+					c = 0;
+				}
+			}
+			else {
+				c = *(uint8_t *)scp->request_buffer;
+			}
+
+			if ((c & 0x1F ) == TYPE_DISK) {
+				pdev_index = (scb->dev_channel * 16) +
+					scb->dev_target;
+				pdev_state =
+					raid_dev->pdrv_state[pdev_index] & 0x0F;
+
+				if (pdev_state == PDRV_ONLINE		||
+					pdev_state == PDRV_FAILED	||
+					pdev_state == PDRV_RBLD		||
+					pdev_state == PDRV_HOTSPARE	||
+					megaraid_expose_unconf_disks == 0) {
+
+					status = 0xF0;
+				}
+			}
+		}
+
+		// Convert MegaRAID status to Linux error code
+		switch (status) {
+
+		case 0x00:
+
+			scp->result = (DID_OK << 16);
+			break;
+
+		case 0x02:
+
+			/* set sense_buffer and result fields */
+			if (mbox->cmd == MBOXCMD_PASSTHRU ||
+				mbox->cmd == MBOXCMD_PASSTHRU64) {
+
+				memcpy(scp->sense_buffer, pthru->reqsensearea,
+						14);
+
+				scp->result = DRIVER_SENSE << 24 |
+					DID_OK << 16 | CHECK_CONDITION << 1;
+			}
+			else {
+				if (mbox->cmd == MBOXCMD_EXTPTHRU) {
+
+					memcpy(scp->sense_buffer,
+						epthru->reqsensearea, 14);
+
+					scp->result = DRIVER_SENSE << 24 |
+						DID_OK << 16 |
+						CHECK_CONDITION << 1;
+				} else {
+					scp->sense_buffer[0] = 0x70;
+					scp->sense_buffer[2] = ABORTED_COMMAND;
+					scp->result = CHECK_CONDITION << 1;
+				}
+			}
+			break;
+
+		case 0x08:
+
+			scp->result = DID_BUS_BUSY << 16 | status;
+			break;
+
+		default:
+
+			/*
+			 * If TEST_UNIT_READY fails, we know RESERVATION_STATUS
+			 * failed
+			 */
+			if (scp->cmnd[0] == TEST_UNIT_READY) {
+				scp->result = DID_ERROR << 16 |
+					RESERVATION_CONFLICT << 1;
+			}
+			else
+			/*
+			 * Error code returned is 1 if Reserve or Release
+			 * failed or the input parameter is invalid
+			 */
+			if (status == 1 && (scp->cmnd[0] == RESERVE ||
+					 scp->cmnd[0] == RELEASE)) {
+
+				scp->result = DID_ERROR << 16 |
+					RESERVATION_CONFLICT << 1;
+			}
+			else {
+				scp->result = DID_BAD_TARGET << 16 | status;
+			}
+		}
+
+		// print a debug message for all failed commands
+		if (status) {
+			megaraid_mbox_display_scb(adapter, scb);
+		}
+
+		// Free our internal resources and call the mid-layer callback
+		// routine
+		megaraid_mbox_sync_scb(adapter, scb);
+
+		// remove from local clist
+		list_del_init(&scb->list);
+
+		// put back in free list
+		megaraid_dealloc_scb(adapter, scb);
+
+		// send the scsi packet back to kernel
+		spin_lock(adapter->host_lock);
+		scp->scsi_done(scp);
+		spin_unlock(adapter->host_lock);
+	}
+
+	return;
+}
+
+
+/**
+ * megaraid_abort_handler - abort the scsi command
+ * @scp		: command to be aborted
+ *
+ * Abort a previous SCSI request. Only commands on the pending list can be
+ * aborted. All the commands issued to the F/W must complete.
+ **/
+static int
+megaraid_abort_handler(struct scsi_cmnd *scp)
+{
+	adapter_t		*adapter;
+	mraid_device_t		*raid_dev;
+	scb_t			*scb;
+	scb_t			*tmp;
+	int			found;
+	unsigned long		flags;
+	int			i;
+
+
+	adapter		= SCP2ADAPTER(scp);
+	raid_dev	= ADAP2RAIDDEV(adapter);
+
+	ASSERT(spin_is_locked(adapter->host_lock));
+
+	con_log(CL_ANN, (KERN_WARNING
+		"megaraid: aborting-%ld cmd=%x <c=%d t=%d l=%d>\n",
+		scp->serial_number, scp->cmnd[0], SCP2CHANNEL(scp),
+		SCP2TARGET(scp), SCP2LUN(scp)));
+
+	// If FW has stopped responding, simply return failure
+	if (raid_dev->hw_error) {
+		con_log(CL_ANN, (KERN_NOTICE
+			"megaraid: hw error, not aborting\n"));
+		return FAILED;
+	}
+
+	// There might a race here, where the command was completed by the
+	// firmware and now it is on the completed list. Before we could
+	// complete the command to the kernel in dpc, the abort came.
+	// Find out if this is the case to avoid the race.
+	scb = NULL;
+	spin_lock_irqsave(COMPLETED_LIST_LOCK(adapter), flags);
+	list_for_each_entry_safe(scb, tmp, &adapter->completed_list, list) {
+
+		if (scb->scp == scp) {	// Found command
+
+			list_del_init(&scb->list);	// from completed list
+
+			con_log(CL_ANN, (KERN_WARNING
+			"megaraid: %ld:%d[%d:%d], abort from completed list\n",
+				scp->serial_number, scb->sno,
+				scb->dev_channel, scb->dev_target));
+
+			scp->result = (DID_ABORT << 16);
+			scp->scsi_done(scp);
+
+			megaraid_dealloc_scb(adapter, scb);
+
+			spin_unlock_irqrestore(COMPLETED_LIST_LOCK(adapter),
+				flags);
+
+			return SUCCESS;
+		}
+	}
+	spin_unlock_irqrestore(COMPLETED_LIST_LOCK(adapter), flags);
+
+
+	// Find out if this command is still on the pending list. If it is and
+	// was never issued, abort and return success. If the command is owned
+	// by the firmware, we must wait for it to complete by the FW.
+	spin_lock_irqsave(PENDING_LIST_LOCK(adapter), flags);
+	list_for_each_entry_safe(scb, tmp, &adapter->pend_list, list) {
+
+		if (scb->scp == scp) {	// Found command
+
+			list_del_init(&scb->list);	// from pending list
+
+			ASSERT(!(scb->state & SCB_ISSUED));
+
+			con_log(CL_ANN, (KERN_WARNING
+				"megaraid abort: %ld[%d:%d], driver owner\n",
+				scp->serial_number, scb->dev_channel,
+				scb->dev_target));
+
+			scp->result = (DID_ABORT << 16);
+			scp->scsi_done(scp);
+
+			megaraid_dealloc_scb(adapter, scb);
+
+			spin_unlock_irqrestore(PENDING_LIST_LOCK(adapter),
+				flags);
+
+			return SUCCESS;
+		}
+	}
+	spin_unlock_irqrestore(PENDING_LIST_LOCK(adapter), flags);
+
+
+	// Check do we even own this command, in which case this would be
+	// owned by the firmware. The only way to locate the FW scb is to
+	// traverse through the list of all SCB, since driver does not
+	// maintain these SCBs on any list
+	found = 0;
+	for (i = 0; i < MBOX_MAX_SCSI_CMDS; i++) {
+		scb = adapter->kscb_list + i;
+
+		if (scb->scp == scp) {
+
+			found = 1;
+
+			if (!(scb->state & SCB_ISSUED)) {
+				con_log(CL_ANN, (KERN_WARNING
+				"megaraid abort: %ld%d[%d:%d], invalid state\n",
+				scp->serial_number, scb->sno, scb->dev_channel,
+				scb->dev_target));
+				BUG();
+			}
+			else {
+				con_log(CL_ANN, (KERN_WARNING
+				"megaraid abort: %ld:%d[%d:%d], fw owner\n",
+				scp->serial_number, scb->sno, scb->dev_channel,
+				scb->dev_target));
+			}
+		}
+	}
+
+	if (!found) {
+		con_log(CL_ANN, (KERN_WARNING
+			"megaraid abort: scsi cmd:%ld, do now own\n",
+			scp->serial_number));
+
+		// FIXME: Should there be a callback for this command?
+		return SUCCESS;
+	}
+
+	// We cannot actually abort a command owned by firmware, return
+	// failure and wait for reset. In host reset handler, we will find out
+	// if the HBA is still live
+	return FAILED;
+}
+
+
+/**
+ * megaraid_reset_handler - device reset hadler for mailbox based driver
+ * @scp		: reference command
+ *
+ * Reset handler for the mailbox based controller. First try to find out if
+ * the FW is still live, in which case the outstanding commands counter mut go
+ * down to 0. If that happens, also issue the reservation reset command to
+ * relinquish (possible) reservations on the logical drives connected to this
+ * host
+ **/
+static int
+megaraid_reset_handler(struct scsi_cmnd *scp)
+{
+	adapter_t	*adapter;
+	scb_t		*scb;
+	scb_t		*tmp;
+	mraid_device_t	*raid_dev;
+	unsigned long	flags;
+	uint8_t		raw_mbox[sizeof(mbox_t)];
+	int		rval;
+	int		recovery_window;
+	int		recovering;
+	int		i;
+
+	adapter		= SCP2ADAPTER(scp);
+	raid_dev	= ADAP2RAIDDEV(adapter);
+
+	ASSERT(spin_is_locked(adapter->host_lock));
+
+	con_log(CL_ANN, (KERN_WARNING "megaraid: reseting the host...\n"));
+
+	// return failure if adapter is not responding
+	if (raid_dev->hw_error) {
+		con_log(CL_ANN, (KERN_NOTICE
+			"megaraid: hw error, cannot reset\n"));
+		return FAILED;
+	}
+
+
+	// Under exceptional conditions, FW can take up to 3 minutes to
+	// complete command processing. Wait for additional 2 minutes for the
+	// pending commands counter to go down to 0. If it doesn't, let the
+	// controller be marked offline
+	// Also, reset all the commands currently owned by the driver
+	spin_lock_irqsave(PENDING_LIST_LOCK(adapter), flags);
+	list_for_each_entry_safe(scb, tmp, &adapter->pend_list, list) {
+
+		list_del_init(&scb->list);	// from pending list
+
+		con_log(CL_ANN, (KERN_WARNING
+			"megaraid: %ld:%d[%d:%d], reset from pending list\n",
+				scp->serial_number, scb->sno,
+				scb->dev_channel, scb->dev_target));
+
+		scp->result = (DID_RESET << 16);
+		scp->scsi_done(scp);
+
+		megaraid_dealloc_scb(adapter, scb);
+	}
+	spin_unlock_irqrestore(PENDING_LIST_LOCK(adapter), flags);
+
+	if (adapter->outstanding_cmds) {
+		con_log(CL_ANN, (KERN_NOTICE
+			"megaraid: %d outstanding commands. Max wait %d sec\n",
+			adapter->outstanding_cmds, MBOX_RESET_WAIT));
+	}
+
+	spin_unlock(adapter->host_lock);
+
+	recovery_window = MBOX_RESET_WAIT + MBOX_RESET_EXT_WAIT;
+
+	recovering = adapter->outstanding_cmds;
+
+	for (i = 0; i < recovery_window && adapter->outstanding_cmds; i++) {
+
+		megaraid_ack_sequence(adapter);
+
+		// print a message once every 5 seconds only
+		if (!(i % 5)) {
+			con_log(CL_ANN, (
+			"megaraid mbox: Wait for %d commands to complete:%d\n",
+				adapter->outstanding_cmds,
+				MBOX_RESET_WAIT - i));
+		}
+
+		// bailout if no recovery happended in reset time
+		if ((i == MBOX_RESET_WAIT) &&
+			(recovering == adapter->outstanding_cmds)) {
+			break;
+		}
+
+		msleep(1000);
+	}
+
+	spin_lock(adapter->host_lock);
+
+	// If still outstanding commands, bail out
+	if (adapter->outstanding_cmds) {
+		con_log(CL_ANN, (KERN_WARNING
+			"megaraid mbox: critical hardware error!\n"));
+
+		raid_dev->hw_error = 1;
+
+		return FAILED;
+	}
+	else {
+		con_log(CL_ANN, (KERN_NOTICE
+		"megaraid mbox: reset sequence completed sucessfully\n"));
+	}
+
+
+	// If the controller supports clustering, reset reservations
+	if (!adapter->ha) return SUCCESS;
+
+	// clear reservations if any
+	raw_mbox[0] = CLUSTER_CMD;
+	raw_mbox[2] = RESET_RESERVATIONS;
+
+	rval = SUCCESS;
+	if (mbox_post_sync_cmd_fast(adapter, raw_mbox) == 0) {
+		con_log(CL_ANN,
+			(KERN_INFO "megaraid: reservation reset\n"));
+	}
+	else {
+		rval = FAILED;
+		con_log(CL_ANN, (KERN_WARNING
+				"megaraid: reservation reset failed\n"));
+	}
+
+	return rval;
+}
+
+
+/*
+ * START: internal commands library
+ *
+ * This section of the driver has the common routine used by the driver and
+ * also has all the FW routines
+ */
+
+/**
+ * mbox_post_sync_cmd() - blocking command to the mailbox based controllers
+ * @adapter	- controller's soft state
+ * @raw_mbox	- the mailbox
+ *
+ * Issue a scb in synchronous and non-interrupt mode for mailbox based
+ * controllers
+ */
+static int
+mbox_post_sync_cmd(adapter_t *adapter, uint8_t raw_mbox[])
+{
+	mraid_device_t	*raid_dev = ADAP2RAIDDEV(adapter);
+	mbox64_t	*mbox64;
+	mbox_t		*mbox;
+	uint8_t		status;
+	int		i;
+
+
+	mbox64	= raid_dev->mbox64;
+	mbox	= raid_dev->mbox;
+
+	/*
+	 * Wait until mailbox is free
+	 */
+	if (megaraid_busywait_mbox(raid_dev) != 0)
+		goto blocked_mailbox;
+
+	/*
+	 * Copy mailbox data into host structure
+	 */
+	memcpy((caddr_t)mbox, (caddr_t)raw_mbox, 16);
+	mbox->cmdid		= 0xFE;
+	mbox->busy		= 1;
+	mbox->poll		= 0;
+	mbox->ack		= 0;
+	mbox->numstatus		= 0xFF;
+	mbox->status		= 0xFF;
+
+	wmb();
+	WRINDOOR(raid_dev, raid_dev->mbox_dma | 0x1);
+
+	// wait for maximum 1 second for status to post. If the status is not
+	// available within 1 second, assume FW is initializing and wait
+	// for an extended amount of time
+	if (mbox->numstatus == 0xFF) {	// status not yet available
+		udelay(25);;
+
+		for (i = 0; mbox->numstatus == 0xFF && i < 1000; i++) {
+			rmb();
+			msleep(1);
+		}
+
+
+		if (i == 1000) {
+			con_log(CL_ANN, (KERN_NOTICE
+				"megaraid mailbox: wait for FW to boot      "));
+
+			for (i = 0; (mbox->numstatus == 0xFF) &&
+					(i < MBOX_RESET_WAIT); i++) {
+				rmb();
+				con_log(CL_ANN, ("\b\b\b\b\b[%03d]",
+							MBOX_RESET_WAIT - i));
+				msleep(1000);
+			}
+
+			if (i == MBOX_RESET_WAIT) {
+
+				con_log(CL_ANN, (
+				"\nmegaraid mailbox: status not available\n"));
+
+				return -1;
+			}
+			con_log(CL_ANN, ("\b\b\b\b\b[ok] \n"));
+		}
+	}
+
+	// wait for maximum 1 second for poll semaphore
+	if (mbox->poll != 0x77) {
+		udelay(25);
+
+		for (i = 0; (mbox->poll != 0x77) && (i < 1000); i++) {
+			rmb();
+			msleep(1);
+		}
+
+		if (i == 1000) {
+			con_log(CL_ANN, (KERN_WARNING
+			"megaraid mailbox: could not get poll semaphore\n"));
+			return -1;
+		}
+	}
+
+	WRINDOOR(raid_dev, raid_dev->mbox_dma | 0x2);
+	wmb();
+
+	// wait for maximum 1 second for acknowledgement
+	if (RDINDOOR(raid_dev) & 0x2) {
+		udelay(25);
+
+		for (i = 0; (RDINDOOR(raid_dev) & 0x2) && (i < 1000); i++) {
+			rmb();
+			msleep(1);
+		}
+
+		if (i == 1000) {
+			con_log(CL_ANN, (KERN_WARNING
+				"megaraid mailbox: could not acknowledge\n"));
+			return -1;
+		}
+	}
+	mbox->poll	= 0;
+	mbox->ack	= 0x77;
+
+	status = mbox->status;
+
+	// invalidate the completed command id array. After command
+	// completion, firmware would write the valid id.
+	mbox->numstatus	= 0xFF;
+	mbox->status	= 0xFF;
+	for (i = 0; i < MBOX_MAX_FIRMWARE_STATUS; i++) {
+		mbox->completed[i] = 0xFF;
+	}
+
+	return status;
+
+blocked_mailbox:
+
+	con_log(CL_ANN, (KERN_WARNING "megaraid: blocked mailbox\n") );
+	return -1;
+}
+
+
+/**
+ * mbox_post_sync_cmd_fast - blocking command to the mailbox based controllers
+ * @adapter	- controller's soft state
+ * @raw_mbox	- the mailbox
+ *
+ * Issue a scb in synchronous and non-interrupt mode for mailbox based
+ * controllers. This is a faster version of the synchronous command and
+ * therefore can be called in interrupt-context as well
+ */
+static int
+mbox_post_sync_cmd_fast(adapter_t *adapter, uint8_t raw_mbox[])
+{
+	mraid_device_t	*raid_dev = ADAP2RAIDDEV(adapter);
+	mbox_t		*mbox;
+	long		i;
+
+
+	mbox	= raid_dev->mbox;
+
+	// return immediately if the mailbox is busy
+	if (mbox->busy) return -1;
+
+	// Copy mailbox data into host structure
+	memcpy((caddr_t)mbox, (caddr_t)raw_mbox, 14);
+	mbox->cmdid		= 0xFE;
+	mbox->busy		= 1;
+	mbox->poll		= 0;
+	mbox->ack		= 0;
+	mbox->numstatus		= 0xFF;
+	mbox->status		= 0xFF;
+
+	wmb();
+	WRINDOOR(raid_dev, raid_dev->mbox_dma | 0x1);
+
+	for (i = 0; i < 0xFFFFF; i++) {
+		if (mbox->numstatus != 0xFF) break;
+	}
+
+	if (i == 0xFFFFF) {
+		// We may need to re-calibrate the counter
+		con_log(CL_ANN, (KERN_CRIT
+			"megaraid: fast sync command timed out\n"));
+	}
+
+	WRINDOOR(raid_dev, raid_dev->mbox_dma | 0x2);
+	wmb();
+
+	return mbox->status;
+}
+
+
+/**
+ * megaraid_busywait_mbox() - Wait until the controller's mailbox is available
+ * @raid_dev	- RAID device (HBA) soft state
+ *
+ * wait until the controller's mailbox is available to accept more commands.
+ * wait for at most 1 second
+ */
+static int
+megaraid_busywait_mbox(mraid_device_t *raid_dev)
+{
+	mbox_t	*mbox = raid_dev->mbox;
+	int	i = 0;
+
+	if (mbox->busy) {
+		udelay(25);
+		for (i = 0; mbox->busy && i < 1000; i++)
+			msleep(1);
+	}
+
+	if (i < 1000) return 0;
+	else return -1;
+}
+
+
+/**
+ * megaraid_mbox_product_info - some static information about the controller
+ * @adapter	- our soft state
+ *
+ * issue commands to the controller to grab some parameters required by our
+ * caller.
+ */
+static int
+megaraid_mbox_product_info(adapter_t *adapter)
+{
+	mraid_device_t		*raid_dev = ADAP2RAIDDEV(adapter);
+	mbox_t			*mbox;
+	uint8_t			raw_mbox[sizeof(mbox_t)];
+	mraid_pinfo_t		*pinfo;
+	dma_addr_t		pinfo_dma_h;
+	mraid_inquiry3_t	*mraid_inq3;
+	int			i;
+
+
+	memset((caddr_t)raw_mbox, 0, sizeof(raw_mbox));
+	mbox = (mbox_t *)raw_mbox;
+
+	/*
+	 * Issue an ENQUIRY3 command to find out certain adapter parameters,
+	 * e.g., max channels, max commands etc.
+	 */
+	pinfo = pci_alloc_consistent(adapter->pdev, sizeof(mraid_pinfo_t),
+			&pinfo_dma_h);
+
+	if (pinfo == NULL) {
+		con_log(CL_ANN, (KERN_WARNING
+			"megaraid: out of memory, %s %d\n", __FUNCTION__,
+			__LINE__));
+
+		return -1;
+	}
+	memset(pinfo, 0, sizeof(mraid_pinfo_t));
+
+	mbox->xferaddr = (uint32_t)adapter->ibuf_dma_h;
+	memset((void *)adapter->ibuf, 0, MBOX_IBUF_SIZE);
+
+	raw_mbox[0] = FC_NEW_CONFIG;
+	raw_mbox[2] = NC_SUBOP_ENQUIRY3;
+	raw_mbox[3] = ENQ3_GET_SOLICITED_FULL;
+
+	// Issue the command
+	if (mbox_post_sync_cmd(adapter, raw_mbox) != 0) {
+
+		con_log(CL_ANN, (KERN_WARNING "megaraid: Inquiry3 failed\n"));
+
+		pci_free_consistent(adapter->pdev, sizeof(mraid_pinfo_t),
+			pinfo, pinfo_dma_h);
+
+		return -1;
+	}
+
+	/*
+	 * Collect information about state of each physical drive
+	 * attached to the controller. We will expose all the disks
+	 * which are not part of RAID
+	 */
+	mraid_inq3 = (mraid_inquiry3_t *)adapter->ibuf;
+	for (i = 0; i < MBOX_MAX_PHYSICAL_DRIVES; i++) {
+		raid_dev->pdrv_state[i] = mraid_inq3->pdrv_state[i];
+	}
+
+	/*
+	 * Get product info for information like number of channels,
+	 * maximum commands supported.
+	 */
+	memset((caddr_t)raw_mbox, 0, sizeof(raw_mbox));
+	mbox->xferaddr = (uint32_t)pinfo_dma_h;
+
+	raw_mbox[0] = FC_NEW_CONFIG;
+	raw_mbox[2] = NC_SUBOP_PRODUCT_INFO;
+
+	if (mbox_post_sync_cmd(adapter, raw_mbox) != 0) {
+
+		con_log(CL_ANN, (KERN_WARNING
+			"megaraid: product info failed\n"));
+
+		pci_free_consistent(adapter->pdev, sizeof(mraid_pinfo_t),
+			pinfo, pinfo_dma_h);
+
+		return -1;
+	}
+
+	/*
+	 * Setup some parameters for host, as required by our caller
+	 */
+	adapter->max_channel = pinfo->nchannels;
+
+	/*
+	 * we will export all the logical drives on a single channel.
+	 * Add 1 since inquires do not come for inititor ID
+	 */
+	adapter->max_target	= MAX_LOGICAL_DRIVES_40LD + 1;
+	adapter->max_lun	= 8;	// up to 8 LUNs for non-disk devices
+
+	/*
+	 * These are the maximum outstanding commands for the scsi-layer
+	 */
+	adapter->max_cmds	= MBOX_MAX_SCSI_CMDS;
+
+	memset(adapter->fw_version, 0, VERSION_SIZE);
+	memset(adapter->bios_version, 0, VERSION_SIZE);
+
+	memcpy(adapter->fw_version, pinfo->fw_version, 4);
+	adapter->fw_version[4] = 0;
+
+	memcpy(adapter->bios_version, pinfo->bios_version, 4);
+	adapter->bios_version[4] = 0;
+
+	con_log(CL_ANN, (KERN_NOTICE
+		"megaraid: fw version:[%s] bios version:[%s]\n",
+		adapter->fw_version, adapter->bios_version));
+
+	pci_free_consistent(adapter->pdev, sizeof(mraid_pinfo_t), pinfo,
+			pinfo_dma_h);
+
+	return 0;
+}
+
+
+
+/**
+ * megaraid_mbox_extended_cdb - check for support for extended CDBs
+ * @adapter	- soft state for the controller
+ *
+ * this routine check whether the controller in question supports extended
+ * ( > 10 bytes ) CDBs
+ */
+static int
+megaraid_mbox_extended_cdb(adapter_t *adapter)
+{
+	mbox_t		*mbox;
+	uint8_t		raw_mbox[sizeof(mbox_t)];
+	int		rval;
+
+	mbox = (mbox_t *)raw_mbox;
+
+	memset((caddr_t)raw_mbox, 0, sizeof(raw_mbox));
+	mbox->xferaddr	= (uint32_t)adapter->ibuf_dma_h;
+
+	memset((void *)adapter->ibuf, 0, MBOX_IBUF_SIZE);
+
+	raw_mbox[0] = MAIN_MISC_OPCODE;
+	raw_mbox[2] = SUPPORT_EXT_CDB;
+
+	/*
+	 * Issue the command
+	 */
+	rval = 0;
+	if (mbox_post_sync_cmd(adapter, raw_mbox) != 0) {
+		rval = -1;
+	}
+
+	return rval;
+}
+
+
+/**
+ * megaraid_mbox_support_ha - Do we support clustering
+ * @adapter	- soft state for the controller
+ * @init_id	- ID of the initiator
+ *
+ * Determine if the firmware supports clustering and the ID of the initiator.
+ */
+static int
+megaraid_mbox_support_ha(adapter_t *adapter, uint16_t *init_id)
+{
+	mbox_t		*mbox;
+	uint8_t		raw_mbox[sizeof(mbox_t)];
+	int		rval;
+
+
+	mbox = (mbox_t *)raw_mbox;
+
+	memset((caddr_t)raw_mbox, 0, sizeof(raw_mbox));
+
+	mbox->xferaddr = (uint32_t)adapter->ibuf_dma_h;
+
+	memset((void *)adapter->ibuf, 0, MBOX_IBUF_SIZE);
+
+	raw_mbox[0] = GET_TARGET_ID;
+
+	// Issue the command
+	*init_id = 7;
+	rval =  -1;
+	if (mbox_post_sync_cmd(adapter, raw_mbox) == 0) {
+
+		*init_id = *(uint8_t *)adapter->ibuf;
+
+		con_log(CL_ANN, (KERN_INFO
+			"megaraid: cluster firmware, initiator ID: %d\n",
+			*init_id));
+
+		rval =  0;
+	}
+
+	return rval;
+}
+
+
+/**
+ * megaraid_mbox_support_random_del - Do we support random deletion
+ * @adapter	- soft state for the controller
+ *
+ * Determine if the firmware supports random deletion
+ * Return:	1 is operation supported, 0 otherwise
+ */
+static int
+megaraid_mbox_support_random_del(adapter_t *adapter)
+{
+	mbox_t		*mbox;
+	uint8_t		raw_mbox[sizeof(mbox_t)];
+	int		rval;
+
+
+	mbox = (mbox_t *)raw_mbox;
+
+	memset((caddr_t)raw_mbox, 0, sizeof(mbox_t));
+
+	raw_mbox[0] = FC_DEL_LOGDRV;
+	raw_mbox[0] = OP_SUP_DEL_LOGDRV;
+
+	// Issue the command
+	rval = 0;
+	if (mbox_post_sync_cmd(adapter, raw_mbox) == 0) {
+
+		con_log(CL_DLEVEL1, ("megaraid: supports random deletion\n"));
+
+		rval =  1;
+	}
+
+	return rval;
+}
+
+
+/**
+ * megaraid_mbox_get_max_sg - maximum sg elements supported by the firmware
+ * @adapter	- soft state for the controller
+ *
+ * Find out the maximum number of scatter-gather elements supported by the
+ * firmware
+ */
+static int
+megaraid_mbox_get_max_sg(adapter_t *adapter)
+{
+	mbox_t		*mbox;
+	uint8_t		raw_mbox[sizeof(mbox_t)];
+	int		nsg;
+
+
+	mbox = (mbox_t *)raw_mbox;
+
+	memset((caddr_t)raw_mbox, 0, sizeof(mbox_t));
+
+	mbox->xferaddr = (uint32_t)adapter->ibuf_dma_h;
+
+	memset((void *)adapter->ibuf, 0, MBOX_IBUF_SIZE);
+
+	raw_mbox[0] = MAIN_MISC_OPCODE;
+	raw_mbox[2] = GET_MAX_SG_SUPPORT;
+
+	// Issue the command
+	if (mbox_post_sync_cmd(adapter, raw_mbox) == 0) {
+		nsg =  *(uint8_t *)adapter->ibuf;
+	}
+	else {
+		nsg =  MBOX_DEFAULT_SG_SIZE;
+	}
+
+	if (nsg > MBOX_MAX_SG_SIZE) nsg = MBOX_MAX_SG_SIZE;
+
+	return nsg;
+}
+
+
+/**
+ * megaraid_mbox_enum_raid_scsi - enumerate the RAID and SCSI channels
+ * @adapter	- soft state for the controller
+ *
+ * Enumerate the RAID and SCSI channels for ROMB platoforms so that channels
+ * can be exported as regular SCSI channels
+ */
+static void
+megaraid_mbox_enum_raid_scsi(adapter_t *adapter)
+{
+	mraid_device_t	*raid_dev = ADAP2RAIDDEV(adapter);
+	mbox_t		*mbox;
+	uint8_t		raw_mbox[sizeof(mbox_t)];
+
+
+	mbox = (mbox_t *)raw_mbox;
+
+	memset((caddr_t)raw_mbox, 0, sizeof(mbox_t));
+
+	mbox->xferaddr = (uint32_t)adapter->ibuf_dma_h;
+
+	memset((void *)adapter->ibuf, 0, MBOX_IBUF_SIZE);
+
+	raw_mbox[0] = CHNL_CLASS;
+	raw_mbox[2] = GET_CHNL_CLASS;
+
+	// Issue the command. If the command fails, all channels are RAID
+	// channels
+	raid_dev->channel_class = 0xFF;
+	if (mbox_post_sync_cmd(adapter, raw_mbox) == 0) {
+		raid_dev->channel_class =  *(uint8_t *)adapter->ibuf;
+	}
+
+	return;
+}
+
+
+/**
+ * megaraid_mbox_flush_cache - flush adapter and disks cache
+ * @param adapter	: soft state for the controller
+ *
+ * Flush adapter cache followed by disks cache
+ */
+static void
+megaraid_mbox_flush_cache(adapter_t *adapter)
+{
+	mbox_t	*mbox;
+	uint8_t	raw_mbox[sizeof(mbox_t)];
+
+
+	mbox = (mbox_t *)raw_mbox;
+
+	memset((caddr_t)raw_mbox, 0, sizeof(mbox_t));
+
+	raw_mbox[0] = FLUSH_ADAPTER;
+
+	if (mbox_post_sync_cmd(adapter, raw_mbox) != 0) {
+		con_log(CL_ANN, ("megaraid: flush adapter failed\n"));
+	}
+
+	raw_mbox[0] = FLUSH_SYSTEM;
+
+	if (mbox_post_sync_cmd(adapter, raw_mbox) != 0) {
+		con_log(CL_ANN, ("megaraid: flush disks cache failed\n"));
+	}
+
+	return;
+}
+
+
+/**
+ * megaraid_mbox_display_scb - display SCB information, mostly debug purposes
+ * @param adapter	: controllers' soft state
+ * @param scb		: SCB to be displayed
+ * @param level	: debug level for console print
+ *
+ * Diplay information about the given SCB iff the current debug level is
+ * verbose
+ */
+static void
+megaraid_mbox_display_scb(adapter_t *adapter, scb_t *scb)
+{
+	mbox_ccb_t		*ccb;
+	struct scsi_cmnd	*scp;
+	mbox_t			*mbox;
+	int			level;
+	int			i;
+
+
+	ccb	= (mbox_ccb_t *)scb->ccb;
+	scp	= scb->scp;
+	mbox	= ccb->mbox;
+
+	level = CL_DLEVEL3;
+
+	con_log(level, (KERN_NOTICE
+		"megaraid mailbox: status:%#x cmd:%#x id:%#x ", scb->status,
+		mbox->cmd, scb->sno));
+
+	con_log(level, ("sec:%#x lba:%#x addr:%#x ld:%d sg:%d\n",
+		mbox->numsectors, mbox->lba, mbox->xferaddr, mbox->logdrv,
+		mbox->numsge));
+
+	if (!scp) return;
+
+	con_log(level, (KERN_NOTICE "scsi cmnd: "));
+
+	for (i = 0; i < scp->cmd_len; i++) {
+		con_log(level, ("%#2.02x ", scp->cmnd[i]));
+	}
+
+	con_log(level, ("\n"));
+
+	return;
+}
+
+
+/**
+ * megaraid_mbox_setup_device_map - manage device ids
+ * @adapter	: Driver's soft state
+ *
+ * Manange the device ids to have an appropraite mapping between the kernel
+ * scsi addresses and megaraid scsi and logical drive addresses. We export
+ * scsi devices on their actual addresses, whereas the logical drives are
+ * exported on a virtual scsi channel.
+ **/
+static void
+megaraid_mbox_setup_device_map(adapter_t *adapter)
+{
+	uint8_t		c;
+	uint8_t		t;
+
+	/*
+	 * First fill the values on the logical drive channel
+	 */
+	for (t = 0; t < LSI_MAX_LOGICAL_DRIVES_64LD; t++)
+		adapter->device_ids[adapter->max_channel][t] =
+			(t < adapter->init_id) ?  t : t - 1;
+
+	adapter->device_ids[adapter->max_channel][adapter->init_id] = 0xFF;
+
+	/*
+	 * Fill the values on the physical devices channels
+	 */
+	for (c = 0; c < adapter->max_channel; c++)
+		for (t = 0; t < LSI_MAX_LOGICAL_DRIVES_64LD; t++)
+			adapter->device_ids[c][t] = (c << 8) | t;
+}
+
+
+/*
+ * END: internal commands library
+ */
+
+/*
+ * START: Interface for the common management module
+ *
+ * This is the module, which interfaces with the common mangement module to
+ * provide support for ioctl and sysfs
+ */
+
+/**
+ * megaraid_cmm_register - register with the mangement module
+ * @param adapter	: HBA soft state
+ *
+ * Register with the management module, which allows applications to issue
+ * ioctl calls to the drivers. This interface is used by the management module
+ * to setup sysfs support as well.
+ */
+static int
+megaraid_cmm_register(adapter_t *adapter)
+{
+	mraid_device_t	*raid_dev = ADAP2RAIDDEV(adapter);
+	mraid_mmadp_t	adp;
+	scb_t		*scb;
+	mbox_ccb_t	*ccb;
+	int		rval;
+	int		i;
+
+	// Allocate memory for the base list of scb for management module.
+	adapter->uscb_list = kmalloc(sizeof(scb_t) * MBOX_MAX_USER_CMDS,
+			GFP_KERNEL);
+
+	if (adapter->uscb_list == NULL) {
+		con_log(CL_ANN, (KERN_WARNING
+			"megaraid: out of memory, %s %d\n", __FUNCTION__,
+			__LINE__));
+		return -1;
+	}
+	memset(adapter->uscb_list, 0, sizeof(scb_t) * MBOX_MAX_USER_CMDS);
+
+
+	// Initialize the synchronization parameters for resources for
+	// commands for management module
+	INIT_LIST_HEAD(&adapter->uscb_pool);
+
+	spin_lock_init(USER_FREE_LIST_LOCK(adapter));
+
+
+
+	// link all the packets. Note, CCB for commands, coming from the
+	// commom management module, mailbox physical address are already
+	// setup by it. We just need placeholder for that in our local command
+	// control blocks
+	for (i = 0; i < MBOX_MAX_USER_CMDS; i++) {
+
+		scb			= adapter->uscb_list + i;
+		ccb			= raid_dev->uccb_list + i;
+
+		scb->ccb		= (caddr_t)ccb;
+		ccb->mbox64		= raid_dev->umbox64 + i;
+		ccb->mbox		= &ccb->mbox64->mbox32;
+		ccb->raw_mbox		= (uint8_t *)ccb->mbox;
+
+		scb->gp			= 0;
+
+		// COMMAND ID 0 - (MBOX_MAX_SCSI_CMDS-1) ARE RESERVED FOR
+		// COMMANDS COMING FROM IO SUBSYSTEM (MID-LAYER)
+		scb->sno		= i + MBOX_MAX_SCSI_CMDS;
+
+		scb->scp		= NULL;
+		scb->state		= SCB_FREE;
+		scb->dma_direction	= PCI_DMA_NONE;
+		scb->dma_type		= MRAID_DMA_NONE;
+		scb->dev_channel	= -1;
+		scb->dev_target		= -1;
+
+		// put scb in the free pool
+		list_add_tail(&scb->list, &adapter->uscb_pool);
+	}
+
+	adp.unique_id		= adapter->unique_id;
+	adp.drvr_type		= DRVRTYPE_MBOX;
+	adp.drvr_data		= (unsigned long)adapter;
+	adp.pdev		= adapter->pdev;
+	adp.issue_uioc		= megaraid_mbox_mm_handler;
+	adp.timeout		= 30;
+	adp.max_kioc		= MBOX_MAX_USER_CMDS;
+
+	if ((rval = mraid_mm_register_adp(&adp)) != 0) {
+
+		con_log(CL_ANN, (KERN_WARNING
+			"megaraid mbox: did not register with CMM\n"));
+
+		kfree(adapter->uscb_list);
+	}
+
+	return rval;
+}
+
+
+/**
+ * megaraid_cmm_unregister - un-register with the mangement module
+ * @param adapter	: HBA soft state
+ *
+ * Un-register with the management module.
+ * FIXME: mgmt module must return failure for unregister if it has pending
+ * commands in LLD
+ */
+static int
+megaraid_cmm_unregister(adapter_t *adapter)
+{
+	kfree(adapter->uscb_list);
+	mraid_mm_unregister_adp(adapter->unique_id);
+	return 0;
+}
+
+
+/**
+ * megaraid_mbox_mm_handler - interface for CMM to issue commands to LLD
+ * @param drvr_data	: LLD specific data
+ * @param kioc		: CMM interface packet
+ * @param action	: command action
+ *
+ * This routine is invoked whenever the Common Mangement Module (CMM) has a
+ * command for us. The 'action' parameter specifies if this is a new command
+ * or otherwise.
+ */
+static int
+megaraid_mbox_mm_handler(unsigned long drvr_data, uioc_t *kioc, uint32_t action)
+{
+	adapter_t *adapter;
+
+	if (action != IOCTL_ISSUE) {
+		con_log(CL_ANN, (KERN_WARNING
+			"megaraid: unsupported management action:%#2x\n",
+			action));
+		return (-ENOTSUPP);
+	}
+
+	adapter = (adapter_t *)drvr_data;
+
+	// make sure this adapter is not being detached right now.
+	if (atomic_read(&adapter->being_detached)) {
+		con_log(CL_ANN, (KERN_WARNING
+			"megaraid: reject management request, detaching\n"));
+		return (-ENODEV);
+	}
+
+	switch (kioc->opcode) {
+
+	case GET_ADAP_INFO:
+
+		kioc->status =  gather_hbainfo(adapter, (mraid_hba_info_t *)
+					(unsigned long)kioc->buf_vaddr);
+
+		kioc->done(kioc);
+
+		return kioc->status;
+
+	case MBOX_CMD:
+
+		return megaraid_mbox_mm_command(adapter, kioc);
+
+	default:
+		kioc->status = (-EINVAL);
+		kioc->done(kioc);
+		return (-EINVAL);
+	}
+
+	return 0;	// not reached
+}
+
+/**
+ * megaraid_mbox_mm_command - issues commands routed through CMM
+ * @param adapter	: HBA soft state
+ * @param kioc		: management command packet
+ *
+ * Issues commands, which are routed through the management module.
+ */
+static int
+megaraid_mbox_mm_command(adapter_t *adapter, uioc_t *kioc)
+{
+	struct list_head	*head = &adapter->uscb_pool;
+	mbox64_t		*mbox64;
+	uint8_t			*raw_mbox;
+	scb_t			*scb;
+	mbox_ccb_t		*ccb;
+	unsigned long		flags;
+
+	// detach one scb from free pool
+	spin_lock_irqsave(USER_FREE_LIST_LOCK(adapter), flags);
+
+	if (list_empty(head)) {	// should never happen because of CMM
+
+		con_log(CL_ANN, (KERN_WARNING
+			"megaraid mbox: bug in cmm handler, lost resources\n"));
+
+		spin_unlock_irqrestore(USER_FREE_LIST_LOCK(adapter), flags);
+
+		return (-EINVAL);
+	}
+
+	scb = list_entry(head->next, scb_t, list);
+	list_del_init(&scb->list);
+
+	spin_unlock_irqrestore(USER_FREE_LIST_LOCK(adapter), flags);
+
+	scb->state	= SCB_ACTIVE;
+	scb->dma_type	= MRAID_DMA_NONE;
+
+	ccb		= (mbox_ccb_t *)scb->ccb;
+	mbox64		= (mbox64_t *)(unsigned long)kioc->cmdbuf;
+	raw_mbox	= (uint8_t *)&mbox64->mbox32;
+
+	memcpy(ccb->mbox64, mbox64, sizeof(mbox64_t));
+
+	scb->gp		= (unsigned long)kioc;
+
+	/*
+	 * If it is a logdrv random delete operation, we have to wait till
+	 * there are no outstanding cmds at the fw and then issue it directly
+	 */
+	if (raw_mbox[0] == FC_DEL_LOGDRV && raw_mbox[2] == OP_DEL_LOGDRV) {
+
+		if (wait_till_fw_empty(adapter)) {
+			con_log(CL_ANN, (KERN_NOTICE
+				"megaraid mbox: LD delete, timed out\n"));
+
+			kioc->status = -ETIME;
+
+			scb->status = -1;
+
+			megaraid_mbox_mm_done(adapter, scb);
+
+			return (-ETIME);
+		}
+
+		INIT_LIST_HEAD(&scb->list);
+
+		scb->state = SCB_ISSUED;
+		if (mbox_post_cmd(adapter, scb) != 0) {
+
+			con_log(CL_ANN, (KERN_NOTICE
+				"megaraid mbox: LD delete, mailbox busy\n"));
+
+			kioc->status = -EBUSY;
+
+			scb->status = -1;
+
+			megaraid_mbox_mm_done(adapter, scb);
+
+			return (-EBUSY);
+		}
+
+		return 0;
+	}
+
+	// put the command on the pending list and execute
+	megaraid_mbox_runpendq(adapter, scb);
+
+	return 0;
+}
+
+
+static int
+wait_till_fw_empty(adapter_t *adapter)
+{
+	unsigned long	flags = 0;
+	int		i;
+
+
+	/*
+	 * Set the quiescent flag to stop issuing cmds to FW.
+	 */
+	spin_lock_irqsave(adapter->host_lock, flags);
+	adapter->quiescent++;
+	spin_unlock_irqrestore(adapter->host_lock, flags);
+
+	/*
+	 * Wait till there are no more cmds outstanding at FW. Try for at most
+	 * 60 seconds
+	 */
+	for (i = 0; i < 60 && adapter->outstanding_cmds; i++) {
+		con_log(CL_DLEVEL1, (KERN_INFO
+			"megaraid: FW has %d pending commands\n",
+			adapter->outstanding_cmds));
+
+		msleep(1000);
+	}
+
+	return adapter->outstanding_cmds;
+}
+
+
+/**
+ * megaraid_mbox_mm_done - callback for CMM commands
+ * @adapter	: HBA soft state
+ * @scb		: completed command
+ *
+ * Callback routine for internal commands originated from the management
+ * module.
+ */
+static void
+megaraid_mbox_mm_done(adapter_t *adapter, scb_t *scb)
+{
+	uioc_t			*kioc;
+	mbox64_t		*mbox64;
+	uint8_t			*raw_mbox;
+	unsigned long		flags;
+
+	kioc			= (uioc_t *)scb->gp;
+	kioc->status		= 0;
+	mbox64			= (mbox64_t *)(unsigned long)kioc->cmdbuf;
+	mbox64->mbox32.status	= scb->status;
+	raw_mbox		= (uint8_t *)&mbox64->mbox32;
+
+
+	// put scb in the free pool
+	scb->state	= SCB_FREE;
+	scb->scp	= NULL;
+
+	spin_lock_irqsave(USER_FREE_LIST_LOCK(adapter), flags);
+
+	list_add(&scb->list, &adapter->uscb_pool);
+
+	spin_unlock_irqrestore(USER_FREE_LIST_LOCK(adapter), flags);
+
+	// if a delete logical drive operation succeeded, restart the
+	// controller
+	if (raw_mbox[0] == FC_DEL_LOGDRV && raw_mbox[2] == OP_DEL_LOGDRV) {
+
+		adapter->quiescent--;
+
+		megaraid_mbox_runpendq(adapter, NULL);
+	}
+
+	kioc->done(kioc);
+
+	return;
+}
+
+
+/**
+ * gather_hbainfo - HBA characteristics for the applications
+ * @param adapter	: HBA soft state
+ * @param hinfo		: pointer to the caller's host info strucuture
+ */
+static int
+gather_hbainfo(adapter_t *adapter, mraid_hba_info_t *hinfo)
+{
+	uint8_t	dmajor;
+
+	dmajor			= megaraid_mbox_version[0];
+
+	hinfo->pci_vendor_id	= adapter->pdev->vendor;
+	hinfo->pci_device_id	= adapter->pdev->device;
+	hinfo->subsys_vendor_id	= adapter->pdev->subsystem_vendor;
+	hinfo->subsys_device_id	= adapter->pdev->subsystem_device;
+
+	hinfo->pci_bus		= adapter->pdev->bus->number;
+	hinfo->pci_dev_fn	= adapter->pdev->devfn;
+	hinfo->pci_slot		= PCI_SLOT(adapter->pdev->devfn);
+	hinfo->irq		= adapter->host->irq;
+	hinfo->baseport		= ADAP2RAIDDEV(adapter)->baseport;
+
+	hinfo->unique_id	= (hinfo->pci_bus << 8) | adapter->pdev->devfn;
+	hinfo->host_no		= adapter->host->host_no;
+
+	return 0;
+}
+
+/*
+ * END: Interface for the common management module
+ */
+
+
+/*
+ * END: Mailbox Low Level Driver
+ */
+module_init(megaraid_init);
+module_exit(megaraid_exit);
+
+/* vim: set ts=8 sw=8 tw=78 ai si: */
diff -Nru a/drivers/scsi/megaraid/megaraid_mbox.h b/drivers/scsi/megaraid/megaraid_mbox.h
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/drivers/scsi/megaraid/megaraid_mbox.h	2004-10-18 14:57:23 -07:00
@@ -0,0 +1,268 @@
+/*
+ *
+ *			Linux MegaRAID device driver
+ *
+ * Copyright (c) 2003-2004  LSI Logic 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.
+ *
+ * FILE		: megaraid_mbox.h
+ */
+
+#ifndef _MEGARAID_H_
+#define _MEGARAID_H_
+
+
+#include "mega_common.h"
+#include "mbox_defs.h"
+#include "megaraid_ioctl.h"
+
+
+#define MEGARAID_VERSION	"2.20.4.0"
+#define MEGARAID_EXT_VERSION	"(Release Date: Mon Sep 27 22:15:07 EDT 2004)"
+
+
+/*
+ * Define some PCI values here until they are put in the kernel
+ */
+#define PCI_DEVICE_ID_PERC4_DI_DISCOVERY		0x000E
+#define PCI_SUBSYS_ID_PERC4_DI_DISCOVERY		0x0123
+
+#define PCI_DEVICE_ID_PERC4_SC				0x1960
+#define PCI_SUBSYS_ID_PERC4_SC				0x0520
+
+#define PCI_DEVICE_ID_PERC4_DC				0x1960
+#define PCI_SUBSYS_ID_PERC4_DC				0x0518
+
+#define PCI_DEVICE_ID_PERC4_QC				0x0407
+#define PCI_SUBSYS_ID_PERC4_QC				0x0531
+
+#define PCI_DEVICE_ID_PERC4_DI_EVERGLADES		0x000F
+#define PCI_SUBSYS_ID_PERC4_DI_EVERGLADES		0x014A
+
+#define PCI_DEVICE_ID_PERC4E_SI_BIGBEND			0x0013
+#define PCI_SUBSYS_ID_PERC4E_SI_BIGBEND			0x016c
+
+#define PCI_DEVICE_ID_PERC4E_DI_KOBUK			0x0013
+#define PCI_SUBSYS_ID_PERC4E_DI_KOBUK			0x016d
+
+#define PCI_DEVICE_ID_PERC4E_DI_CORVETTE		0x0013
+#define PCI_SUBSYS_ID_PERC4E_DI_CORVETTE		0x016e
+
+#define PCI_DEVICE_ID_PERC4E_DI_EXPEDITION		0x0013
+#define PCI_SUBSYS_ID_PERC4E_DI_EXPEDITION		0x016f
+
+#define PCI_DEVICE_ID_PERC4E_DI_GUADALUPE		0x0013
+#define PCI_SUBSYS_ID_PERC4E_DI_GUADALUPE		0x0170
+
+#define PCI_DEVICE_ID_PERC4E_DC_320_2E			0x0408
+#define PCI_SUBSYS_ID_PERC4E_DC_320_2E			0x0002
+
+#define PCI_DEVICE_ID_PERC4E_SC_320_1E			0x0408
+#define PCI_SUBSYS_ID_PERC4E_SC_320_1E			0x0001
+
+#define PCI_DEVICE_ID_MEGARAID_SCSI_320_0		0x1960
+#define PCI_SUBSYS_ID_MEGARAID_SCSI_320_0		0xA520
+
+#define PCI_DEVICE_ID_MEGARAID_SCSI_320_1		0x1960
+#define PCI_SUBSYS_ID_MEGARAID_SCSI_320_1		0x0520
+
+#define PCI_DEVICE_ID_MEGARAID_SCSI_320_2		0x1960
+#define PCI_SUBSYS_ID_MEGARAID_SCSI_320_2		0x0518
+
+#define PCI_DEVICE_ID_MEGARAID_SCSI_320_0x		0x0407
+#define PCI_SUBSYS_ID_MEGARAID_SCSI_320_0x		0x0530
+
+#define PCI_DEVICE_ID_MEGARAID_SCSI_320_2x		0x0407
+#define PCI_SUBSYS_ID_MEGARAID_SCSI_320_2x		0x0532
+
+#define PCI_DEVICE_ID_MEGARAID_SCSI_320_4x		0x0407
+#define PCI_SUBSYS_ID_MEGARAID_SCSI_320_4x		0x0531
+
+#define PCI_DEVICE_ID_MEGARAID_SCSI_320_1E		0x0408
+#define PCI_SUBSYS_ID_MEGARAID_SCSI_320_1E		0x0001
+
+#define PCI_DEVICE_ID_MEGARAID_SCSI_320_2E		0x0408
+#define PCI_SUBSYS_ID_MEGARAID_SCSI_320_2E		0x0002
+
+#define PCI_DEVICE_ID_MEGARAID_I4_133_RAID		0x1960
+#define PCI_SUBSYS_ID_MEGARAID_I4_133_RAID		0x0522
+
+#define PCI_DEVICE_ID_MEGARAID_SATA_150_4		0x1960
+#define PCI_SUBSYS_ID_MEGARAID_SATA_150_4		0x4523
+
+#define PCI_DEVICE_ID_MEGARAID_SATA_150_6		0x1960
+#define PCI_SUBSYS_ID_MEGARAID_SATA_150_6		0x0523
+
+#define PCI_DEVICE_ID_MEGARAID_SATA_300_4x		0x0409
+#define PCI_SUBSYS_ID_MEGARAID_SATA_300_4x		0x3004
+
+#define PCI_DEVICE_ID_MEGARAID_SATA_300_8x		0x0409
+#define PCI_SUBSYS_ID_MEGARAID_SATA_300_8x		0x3008
+
+#define PCI_DEVICE_ID_INTEL_RAID_SRCU42X		0x0407
+#define PCI_SUBSYS_ID_INTEL_RAID_SRCU42X		0x0532
+
+#define PCI_DEVICE_ID_INTEL_RAID_SRCS16			0x1960
+#define PCI_SUBSYS_ID_INTEL_RAID_SRCS16			0x0523
+
+#define PCI_DEVICE_ID_INTEL_RAID_SRCU42E		0x0408
+#define PCI_SUBSYS_ID_INTEL_RAID_SRCU42E		0x0002
+
+#define PCI_DEVICE_ID_INTEL_RAID_SRCZCRX		0x0407
+#define PCI_SUBSYS_ID_INTEL_RAID_SRCZCRX		0x0530
+
+#define PCI_DEVICE_ID_INTEL_RAID_SRCS28X		0x0409
+#define PCI_SUBSYS_ID_INTEL_RAID_SRCS28X		0x3008
+
+#define PCI_DEVICE_ID_INTEL_RAID_SROMBU42E_ALIEF	0x0408
+#define PCI_SUBSYS_ID_INTEL_RAID_SROMBU42E_ALIEF	0x3431
+
+#define PCI_DEVICE_ID_INTEL_RAID_SROMBU42E_HARWICH	0x0408
+#define PCI_SUBSYS_ID_INTEL_RAID_SROMBU42E_HARWICH	0x3499
+
+#define PCI_DEVICE_ID_INTEL_RAID_SRCU41L_LAKE_SHETEK	0x1960
+#define PCI_SUBSYS_ID_INTEL_RAID_SRCU41L_LAKE_SHETEK	0x0520
+
+#define PCI_DEVICE_ID_FSC_MEGARAID_PCI_EXPRESS_ROMB	0x0408
+#define PCI_SUBSYS_ID_FSC_MEGARAID_PCI_EXPRESS_ROMB	0x1065
+
+#define PCI_DEVICE_ID_MEGARAID_ACER_ROMB_2E		0x0408
+#define PCI_SUBSYS_ID_MEGARAID_ACER_ROMB_2E		0x004D
+
+#define PCI_SUBSYS_ID_PERC3_QC				0x0471
+#define PCI_SUBSYS_ID_PERC3_DC				0x0493
+#define PCI_SUBSYS_ID_PERC3_SC				0x0475
+
+#ifndef PCI_SUBSYS_ID_FSC
+#define PCI_SUBSYS_ID_FSC				0x1734
+#endif
+
+#define MBOX_MAX_SCSI_CMDS	128	// number of cmds reserved for kernel
+#define MBOX_MAX_USER_CMDS	32	// number of cmds for applications
+#define MBOX_DEF_CMD_PER_LUN	64	// default commands per lun
+#define MBOX_DEFAULT_SG_SIZE	26	// default sg size supported by all fw
+#define MBOX_MAX_SG_SIZE	32	// maximum scatter-gather list size
+#define MBOX_MAX_SECTORS	128	// maximum sectors per IO
+#define MBOX_TIMEOUT		30	// timeout value for internal cmds
+#define MBOX_BUSY_WAIT		10	// max usec to wait for busy mailbox
+#define MBOX_RESET_WAIT		180	// wait these many seconds in reset
+#define MBOX_RESET_EXT_WAIT	120	// extended wait reset
+
+/*
+ * maximum transfer that can happen through the firmware commands issued
+ * internnaly from the driver.
+ */
+#define MBOX_IBUF_SIZE		4096
+
+
+/**
+ * mbox_ccb_t - command control block specific to mailbox based controllers
+ * @raw_mbox		: raw mailbox pointer
+ * @mbox		: mailbox
+ * @mbox64		: extended mailbox
+ * @mbox_dma_h		: maibox dma address
+ * @sgl64		: 64-bit scatter-gather list
+ * @sgl32		: 32-bit scatter-gather list
+ * @sgl_dma_h		: dma handle for the scatter-gather list
+ * @pthru		: passthru structure
+ * @pthru_dma_h		: dma handle for the passthru structure
+ * @epthru		: extended passthru structure
+ * @epthru_dma_h	: dma handle for extended passthru structure
+ * @buf_dma_h		: dma handle for buffers w/o sg list
+ *
+ * command control block specific to the mailbox based controllers
+ */
+typedef struct {
+	uint8_t			*raw_mbox;
+	mbox_t			*mbox;
+	mbox64_t		*mbox64;
+	dma_addr_t		mbox_dma_h;
+	mbox_sgl64		*sgl64;
+	mbox_sgl32		*sgl32;
+	dma_addr_t		sgl_dma_h;
+	mraid_passthru_t	*pthru;
+	dma_addr_t		pthru_dma_h;
+	mraid_epassthru_t	*epthru;
+	dma_addr_t		epthru_dma_h;
+	dma_addr_t		buf_dma_h;
+} mbox_ccb_t;
+
+
+/**
+ * mraid_device_t - adapter soft state structure for mailbox controllers
+ * @param una_mbox64		: 64-bit mbox - unaligned
+ * @param una_mbox64_dma	: mbox dma addr - unaligned
+ * @param mbox			: 32-bit mbox - aligned
+ * @param mbox64		: 64-bit mbox - aligned
+ * @param mbox_dma		: mbox dma addr - aligned
+ * @param mailbox_lock		: exclusion lock for the mailbox
+ * @param baseport		: base port of hba memory
+ * @param baseaddr		: mapped addr of hba memory
+ * @param mbox_pool		: pool of mailboxes
+ * @param mbox_pool_handle	: handle for the mailbox pool memory
+ * @param epthru_pool		: a pool for extended passthru commands
+ * @param epthru_pool_handle	: handle to the pool above
+ * @param sg_pool		: pool of scatter-gather lists for this driver
+ * @param sg_pool_handle	: handle to the pool above
+ * @param ccb_list		: list of our command control blocks
+ * @param uccb_list		: list of cmd control blocks for mgmt module
+ * @param umbox64		: array of mailbox for user commands (cmm)
+ * @param pdrv_state		: array for state of each physical drive.
+ * @param last_disp		: flag used to show device scanning
+ * @param hw_error		: set if FW not responding
+ * @param fast_load		: If set, skip physical device scanning
+ * @channel_class		: channel class, RAID or SCSI
+ *
+ * Initialization structure for mailbox controllers: memory based and IO based
+ * All the fields in this structure are LLD specific and may be discovered at
+ * init() or start() time.
+ *
+ * NOTE: The fields of this structures are placed to minimize cache misses
+ */
+typedef struct {
+	mbox64_t			*una_mbox64;
+	dma_addr_t			una_mbox64_dma;
+	mbox_t				*mbox;
+	mbox64_t			*mbox64;
+	dma_addr_t			mbox_dma;
+	spinlock_t			mailbox_lock;
+	unsigned long			baseport;
+	unsigned long			baseaddr;
+	struct mraid_pci_blk		mbox_pool[MBOX_MAX_SCSI_CMDS];
+	struct dma_pool			*mbox_pool_handle;
+	struct mraid_pci_blk		epthru_pool[MBOX_MAX_SCSI_CMDS];
+	struct dma_pool			*epthru_pool_handle;
+	struct mraid_pci_blk		sg_pool[MBOX_MAX_SCSI_CMDS];
+	struct dma_pool			*sg_pool_handle;
+	mbox_ccb_t			ccb_list[MBOX_MAX_SCSI_CMDS];
+	mbox_ccb_t			uccb_list[MBOX_MAX_USER_CMDS];
+	mbox64_t			umbox64[MBOX_MAX_USER_CMDS];
+
+	uint8_t				pdrv_state[MBOX_MAX_PHYSICAL_DRIVES];
+	uint32_t			last_disp;
+	int				hw_error;
+	int				fast_load;
+	uint8_t				channel_class;
+} mraid_device_t;
+
+// route to raid device from adapter
+#define ADAP2RAIDDEV(adp)	((mraid_device_t *)((adp)->raid_device))
+
+#define MAILBOX_LOCK(rdev)	(&(rdev)->mailbox_lock)
+
+// Find out if this channel is a RAID or SCSI
+#define IS_RAID_CH(rdev, ch)	(((rdev)->channel_class >> (ch)) & 0x01)
+
+
+#define RDINDOOR(rdev)		readl((rdev)->baseaddr + 0x20)
+#define RDOUTDOOR(rdev)		readl((rdev)->baseaddr + 0x2C)
+#define WRINDOOR(rdev, value)	writel(value, (rdev)->baseaddr + 0x20)
+#define WROUTDOOR(rdev, value)	writel(value, (rdev)->baseaddr + 0x2C)
+
+#endif // _MEGARAID_H_
+
+// vim: set ts=8 sw=8 tw=78:
diff -Nru a/drivers/scsi/megaraid/megaraid_mm.c b/drivers/scsi/megaraid/megaraid_mm.c
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/drivers/scsi/megaraid/megaraid_mm.c	2004-10-18 14:57:23 -07:00
@@ -0,0 +1,1160 @@
+/*
+ *
+ *			Linux MegaRAID device driver
+ *
+ * Copyright (c) 2003-2004  LSI Logic 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.
+ *
+ * FILE		: megaraid_mm.c
+ * Version	: v2.20.2.0 (August 19 2004)
+ *
+ * Common management module
+ */
+
+#include "megaraid_mm.h"
+
+
+// Entry points for char node driver
+static int mraid_mm_open(struct inode *, struct file *);
+static int mraid_mm_ioctl(struct inode *, struct file *, uint, unsigned long);
+
+
+// routines to convert to and from the old the format
+static int mimd_to_kioc(mimd_t __user *, mraid_mmadp_t *, uioc_t *);
+static int kioc_to_mimd(uioc_t *, mimd_t __user *);
+
+
+// Helper functions
+static int handle_drvrcmd(void __user *, uint8_t, int *);
+static int lld_ioctl(mraid_mmadp_t *, uioc_t *);
+static void ioctl_done(uioc_t *);
+static void lld_timedout(unsigned long);
+static void hinfo_to_cinfo(mraid_hba_info_t *, mcontroller_t *);
+static mraid_mmadp_t *mraid_mm_get_adapter(mimd_t __user *, int *);
+static uioc_t *mraid_mm_alloc_kioc(mraid_mmadp_t *);
+static void mraid_mm_dealloc_kioc(mraid_mmadp_t *, uioc_t *);
+static int mraid_mm_attach_buf(mraid_mmadp_t *, uioc_t *, int);
+static int mraid_mm_setup_dma_pools(mraid_mmadp_t *);
+static void mraid_mm_free_adp_resources(mraid_mmadp_t *);
+static void mraid_mm_teardown_dma_pools(mraid_mmadp_t *);
+
+#ifdef CONFIG_COMPAT
+static int mraid_mm_compat_ioctl(unsigned int, unsigned int, unsigned long,
+		struct file *);
+#endif
+
+MODULE_AUTHOR("LSI Logic Corporation");
+MODULE_DESCRIPTION("LSI Logic Management Module");
+MODULE_LICENSE("GPL");
+MODULE_VERSION(LSI_COMMON_MOD_VERSION);
+
+static int dbglevel = CL_ANN;
+module_param_named(dlevel, dbglevel, int, 0);
+MODULE_PARM_DESC(dlevel, "Debug level (default=0)");
+
+EXPORT_SYMBOL(mraid_mm_register_adp);
+EXPORT_SYMBOL(mraid_mm_unregister_adp);
+
+static int majorno;
+static uint32_t drvr_ver	= 0x02200100;
+
+static int adapters_count_g;
+static struct list_head adapters_list_g;
+
+wait_queue_head_t wait_q;
+
+static struct file_operations lsi_fops = {
+	.open	= mraid_mm_open,
+	.ioctl	= mraid_mm_ioctl,
+	.owner	= THIS_MODULE,
+};
+
+/**
+ * mraid_mm_open - open routine for char node interface
+ * @inod	: unused
+ * @filep	: unused
+ *
+ * allow ioctl operations by apps only if they superuser privilege
+ */
+static int
+mraid_mm_open(struct inode *inode, struct file *filep)
+{
+	/*
+	 * Only allow superuser to access private ioctl interface
+	 */
+	if (!capable(CAP_SYS_ADMIN)) return (-EACCES);
+
+	return 0;
+}
+
+/**
+ * mraid_mm_ioctl - module entry-point for ioctls
+ * @inode	: inode (ignored)
+ * @filep	: file operations pointer (ignored)
+ * @cmd		: ioctl command
+ * @arg		: user ioctl packet
+ */
+static int
+mraid_mm_ioctl(struct inode *inode, struct file *filep, unsigned int cmd,
+							unsigned long arg)
+{
+	uioc_t		*kioc;
+	char		signature[EXT_IOCTL_SIGN_SZ]	= {0};
+	int		rval;
+	mraid_mmadp_t	*adp;
+	uint8_t		old_ioctl;
+	int		drvrcmd_rval;
+	void __user *argp = (void __user *)arg;
+
+	/*
+	 * Make sure only USCSICMD are issued through this interface.
+	 * MIMD application would still fire different command.
+	 */
+
+	if ((_IOC_TYPE(cmd) != MEGAIOC_MAGIC) && (cmd != USCSICMD)) {
+		return (-EINVAL);
+	}
+
+	/*
+	 * Look for signature to see if this is the new or old ioctl format.
+	 */
+	if (copy_from_user(signature, argp, EXT_IOCTL_SIGN_SZ)) {
+		con_log(CL_ANN, (KERN_WARNING
+			"megaraid cmm: copy from usr addr failed\n"));
+		return (-EFAULT);
+	}
+
+	if (memcmp(signature, EXT_IOCTL_SIGN, EXT_IOCTL_SIGN_SZ) == 0)
+		old_ioctl = 0;
+	else
+		old_ioctl = 1;
+
+	/*
+	 * At present, we don't support the new ioctl packet
+	 */
+	if (!old_ioctl )
+		return (-EINVAL);
+
+	/*
+	 * If it is a driver ioctl (as opposed to fw ioctls), then we can
+	 * handle the command locally. rval > 0 means it is not a drvr cmd
+	 */
+	rval = handle_drvrcmd(argp, old_ioctl, &drvrcmd_rval);
+
+	if (rval < 0)
+		return rval;
+	else if (rval == 0)
+		return drvrcmd_rval;
+
+	rval = 0;
+	if ((adp = mraid_mm_get_adapter(argp, &rval)) == NULL) {
+		return rval;
+	}
+
+	/*
+	 * The following call will block till a kioc is available
+	 */
+	kioc = mraid_mm_alloc_kioc(adp);
+
+	/*
+	 * User sent the old mimd_t ioctl packet. Convert it to uioc_t.
+	 */
+	if ((rval = mimd_to_kioc(argp, adp, kioc))) {
+		mraid_mm_dealloc_kioc(adp, kioc);
+		return rval;
+	}
+
+	kioc->done = ioctl_done;
+
+	/*
+	 * Issue the IOCTL to the low level driver
+	 */
+	if ((rval = lld_ioctl(adp, kioc))) {
+		mraid_mm_dealloc_kioc(adp, kioc);
+		return rval;
+	}
+
+	/*
+	 * Convert the kioc back to user space
+	 */
+	rval = kioc_to_mimd(kioc, argp);
+
+	/*
+	 * Return the kioc to free pool
+	 */
+	mraid_mm_dealloc_kioc(adp, kioc);
+
+	return rval;
+}
+
+
+/**
+ * mraid_mm_get_adapter - Returns corresponding adapters for the mimd packet
+ * @umimd	: User space mimd_t ioctl packet
+ * @adapter	: pointer to the adapter (OUT)
+ */
+static mraid_mmadp_t *
+mraid_mm_get_adapter(mimd_t __user *umimd, int *rval)
+{
+	mraid_mmadp_t	*adapter;
+	mimd_t		mimd;
+	uint32_t	adapno;
+	int		iterator;
+
+
+	if (copy_from_user(&mimd, umimd, sizeof(mimd_t))) {
+		*rval = -EFAULT;
+		return NULL;
+	}
+
+	adapno = GETADAP(mimd.ui.fcs.adapno);
+
+	if (adapno >= adapters_count_g) {
+		*rval = -ENODEV;
+		return NULL;
+	}
+
+	adapter = NULL;
+	iterator = 0;
+
+	list_for_each_entry(adapter, &adapters_list_g, list) {
+		if (iterator++ == adapno) break;
+	}
+
+	if (!adapter) {
+		*rval = -ENODEV;
+		return NULL;
+	}
+
+	return adapter;
+}
+
+/*
+ * handle_drvrcmd - This routine checks if the opcode is a driver
+ * 			  cmd and if it is, handles it.
+ * @arg		: packet sent by the user app
+ * @old_ioctl	: mimd if 1; uioc otherwise
+ */
+static int
+handle_drvrcmd(void __user *arg, uint8_t old_ioctl, int *rval)
+{
+	mimd_t		__user *umimd;
+	mimd_t		kmimd;
+	uint8_t		opcode;
+	uint8_t		subopcode;
+
+	if (old_ioctl)
+		goto old_packet;
+	else
+		goto new_packet;
+
+new_packet:
+	return (-ENOTSUPP);
+
+old_packet:
+	*rval = 0;
+	umimd = arg;
+
+	if (copy_from_user(&kmimd, umimd, sizeof(mimd_t)))
+		return (-EFAULT);
+
+	opcode		= kmimd.ui.fcs.opcode;
+	subopcode	= kmimd.ui.fcs.subopcode;
+
+	/*
+	 * If the opcode is 0x82 and the subopcode is either GET_DRVRVER or
+	 * GET_NUMADP, then we can handle. Otherwise we should return 1 to
+	 * indicate that we cannot handle this.
+	 */
+	if (opcode != 0x82)
+		return 1;
+
+	switch (subopcode) {
+
+	case MEGAIOC_QDRVRVER:
+
+		if (copy_to_user(kmimd.data, &drvr_ver, sizeof(uint32_t)))
+			return (-EFAULT);
+
+		return 0;
+
+	case MEGAIOC_QNADAP:
+
+		*rval = adapters_count_g;
+
+		if (copy_to_user(kmimd.data, &adapters_count_g,
+				sizeof(uint32_t)))
+			return (-EFAULT);
+
+		return 0;
+
+	default:
+		/* cannot handle */
+		return 1;
+	}
+
+	return 0;
+}
+
+
+/**
+ * mimd_to_kioc	- Converter from old to new ioctl format
+ *
+ * @umimd	: user space old MIMD IOCTL
+ * @kioc	: kernel space new format IOCTL
+ *
+ * Routine to convert MIMD interface IOCTL to new interface IOCTL packet. The
+ * new packet is in kernel space so that driver can perform operations on it
+ * freely.
+ */
+
+static int
+mimd_to_kioc(mimd_t __user *umimd, mraid_mmadp_t *adp, uioc_t *kioc)
+{
+	mbox64_t		*mbox64;
+	mbox_t			*mbox;
+	mraid_passthru_t	*pthru32;
+	uint32_t		adapno;
+	uint8_t			opcode;
+	uint8_t			subopcode;
+	mimd_t			mimd;
+
+	if (copy_from_user(&mimd, umimd, sizeof(mimd_t)))
+		return (-EFAULT);
+
+	/*
+	 * Applications are not allowed to send extd pthru
+	 */
+	if ((mimd.mbox[0] == MBOXCMD_PASSTHRU64) ||
+			(mimd.mbox[0] == MBOXCMD_EXTPTHRU))
+		return (-EINVAL);
+
+	opcode		= mimd.ui.fcs.opcode;
+	subopcode	= mimd.ui.fcs.subopcode;
+	adapno		= GETADAP(mimd.ui.fcs.adapno);
+
+	if (adapno >= adapters_count_g)
+		return (-ENODEV);
+
+	kioc->adapno	= adapno;
+	kioc->mb_type	= MBOX_LEGACY;
+	kioc->app_type	= APPTYPE_MIMD;
+
+	switch (opcode) {
+
+	case 0x82:
+
+		if (subopcode == MEGAIOC_QADAPINFO) {
+
+			kioc->opcode	= GET_ADAP_INFO;
+			kioc->data_dir	= UIOC_RD;
+			kioc->xferlen	= sizeof(mraid_hba_info_t);
+
+			if (mraid_mm_attach_buf(adp, kioc, kioc->xferlen))
+				return (-ENOMEM);
+		}
+		else {
+			con_log(CL_ANN, (KERN_WARNING
+					"megaraid cmm: Invalid subop\n"));
+			return (-EINVAL);
+		}
+
+		break;
+
+	case 0x81:
+
+		kioc->opcode		= MBOX_CMD;
+		kioc->xferlen		= mimd.ui.fcs.length;
+		kioc->user_data_len	= kioc->xferlen;
+		kioc->user_data		= mimd.ui.fcs.buffer;
+
+		if (mraid_mm_attach_buf(adp, kioc, kioc->xferlen))
+			return (-ENOMEM);
+
+		if (mimd.outlen) kioc->data_dir  = UIOC_RD;
+		if (mimd.inlen) kioc->data_dir |= UIOC_WR;
+
+		break;
+
+	case 0x80:
+
+		kioc->opcode		= MBOX_CMD;
+		kioc->xferlen		= (mimd.outlen > mimd.inlen) ?
+						mimd.outlen : mimd.inlen;
+		kioc->user_data_len	= kioc->xferlen;
+		kioc->user_data		= mimd.data;
+
+		if (mraid_mm_attach_buf(adp, kioc, kioc->xferlen))
+			return (-ENOMEM);
+
+		if (mimd.outlen) kioc->data_dir  = UIOC_RD;
+		if (mimd.inlen) kioc->data_dir |= UIOC_WR;
+
+		break;
+
+	default:
+		return (-EINVAL);
+	}
+
+	/*
+	 * If driver command, nothing else to do
+	 */
+	if (opcode == 0x82)
+		return 0;
+
+	/*
+	 * This is a mailbox cmd; copy the mailbox from mimd
+	 */
+	mbox64	= (mbox64_t *)((unsigned long)kioc->cmdbuf);
+	mbox	= &mbox64->mbox32;
+	memcpy(mbox, mimd.mbox, 14);
+
+	if (mbox->cmd != MBOXCMD_PASSTHRU) {	// regular DCMD
+
+		mbox->xferaddr	= (uint32_t)kioc->buf_paddr;
+
+		if (kioc->data_dir & UIOC_WR) {
+			if (copy_from_user(kioc->buf_vaddr, kioc->user_data,
+							kioc->xferlen)) {
+				return (-EFAULT);
+			}
+		}
+
+		return 0;
+	}
+
+	/*
+	 * This is a regular 32-bit pthru cmd; mbox points to pthru struct.
+	 * Just like in above case, the beginning for memblk is treated as
+	 * a mailbox. The passthru will begin at next 1K boundary. And the
+	 * data will start 1K after that.
+	 */
+	pthru32			= kioc->pthru32;
+	kioc->user_pthru	= &umimd->pthru;
+	mbox->xferaddr		= (uint32_t)kioc->pthru32_h;
+
+	if (copy_from_user(pthru32, kioc->user_pthru,
+			sizeof(mraid_passthru_t))) {
+		return (-EFAULT);
+	}
+
+	pthru32->dataxferaddr	= kioc->buf_paddr;
+	if (kioc->data_dir & UIOC_WR) {
+		if (copy_from_user(kioc->buf_vaddr, kioc->user_data,
+						pthru32->dataxferlen)) {
+			return (-EFAULT);
+		}
+	}
+
+	return 0;
+}
+
+/**
+ * mraid_mm_attch_buf - Attach a free dma buffer for required size
+ *
+ * @adp		: Adapter softstate
+ * @kioc	: kioc that the buffer needs to be attached to
+ * @xferlen	: required length for buffer
+ *
+ * First we search for a pool with smallest buffer that is >= @xferlen. If
+ * that pool has no free buffer, we will try for the next bigger size. If none
+ * is available, we will try to allocate the smallest buffer that is >=
+ * @xferlen and attach it the pool.
+ */
+static int
+mraid_mm_attach_buf(mraid_mmadp_t *adp, uioc_t *kioc, int xferlen)
+{
+	mm_dmapool_t	*pool;
+	int		right_pool = -1;
+	unsigned long	flags;
+	int		i;
+
+	kioc->pool_index	= -1;
+	kioc->buf_vaddr		= NULL;
+	kioc->buf_paddr		= 0;
+	kioc->free_buf		= 0;
+
+	/*
+	 * We need xferlen amount of memory. See if we can get it from our
+	 * dma pools. If we don't get exact size, we will try bigger buffer
+	 */
+
+	for (i = 0; i < MAX_DMA_POOLS; i++) {
+
+		pool = &adp->dma_pool_list[i];
+
+		if (xferlen > pool->buf_size)
+			continue;
+
+		if (right_pool == -1)
+			right_pool = i;
+
+		spin_lock_irqsave(&pool->lock, flags);
+
+		if (!pool->in_use) {
+
+			pool->in_use		= 1;
+			kioc->pool_index	= i;
+			kioc->buf_vaddr		= pool->vaddr;
+			kioc->buf_paddr		= pool->paddr;
+
+			spin_unlock_irqrestore(&pool->lock, flags);
+			return 0;
+		}
+		else {
+			spin_unlock_irqrestore(&pool->lock, flags);
+			continue;
+		}
+	}
+
+	/*
+	 * If xferlen doesn't match any of our pools, return error
+	 */
+	if (right_pool == -1)
+		return -EINVAL;
+
+	/*
+	 * We did not get any buffer from the preallocated pool. Let us try
+	 * to allocate one new buffer. NOTE: This is a blocking call.
+	 */
+	pool = &adp->dma_pool_list[right_pool];
+
+	spin_lock_irqsave(&pool->lock, flags);
+
+	kioc->pool_index	= right_pool;
+	kioc->free_buf		= 1;
+	kioc->buf_vaddr 	= pci_pool_alloc(pool->handle, GFP_KERNEL,
+							&kioc->buf_paddr);
+	spin_unlock_irqrestore(&pool->lock, flags);
+
+	if (!kioc->buf_vaddr)
+		return -ENOMEM;
+
+	return 0;
+}
+
+/**
+ * mraid_mm_alloc_kioc - Returns a uioc_t from free list
+ * @adp	: Adapter softstate for this module
+ *
+ * The kioc_semaphore is initialized with number of kioc nodes in the
+ * free kioc pool. If the kioc pool is empty, this function blocks till
+ * a kioc becomes free.
+ */
+static uioc_t *
+mraid_mm_alloc_kioc(mraid_mmadp_t *adp)
+{
+	uioc_t			*kioc;
+	struct list_head*	head;
+	unsigned long		flags;
+
+	down(&adp->kioc_semaphore);
+
+	spin_lock_irqsave(&adp->kioc_pool_lock, flags);
+
+	head = &adp->kioc_pool;
+
+	if (list_empty(head)) {
+		up(&adp->kioc_semaphore);
+		spin_unlock_irqrestore(&adp->kioc_pool_lock, flags);
+
+		con_log(CL_ANN, ("megaraid cmm: kioc list empty!\n"));
+		return NULL;
+	}
+
+	kioc = list_entry(head->next, uioc_t, list);
+	list_del_init(&kioc->list);
+
+	spin_unlock_irqrestore(&adp->kioc_pool_lock, flags);
+
+	memset((caddr_t)(unsigned long)kioc->cmdbuf, 0, sizeof(mbox64_t));
+	memset((caddr_t) kioc->pthru32, 0, sizeof(mraid_passthru_t));
+
+	kioc->buf_vaddr		= NULL;
+	kioc->buf_paddr		= 0;
+	kioc->pool_index	=-1;
+	kioc->free_buf		= 0;
+	kioc->user_data		= NULL;
+	kioc->user_data_len	= 0;
+	kioc->user_pthru	= NULL;
+
+	return kioc;
+}
+
+/**
+ * mraid_mm_dealloc_kioc - Return kioc to free pool
+ *
+ * @adp		: Adapter softstate
+ * @kioc	: uioc_t node to be returned to free pool
+ */
+static void
+mraid_mm_dealloc_kioc(mraid_mmadp_t *adp, uioc_t *kioc)
+{
+	mm_dmapool_t	*pool;
+	unsigned long	flags;
+
+	pool = &adp->dma_pool_list[kioc->pool_index];
+
+	/* This routine may be called in non-isr context also */
+	spin_lock_irqsave(&pool->lock, flags);
+
+	/*
+	 * While attaching the dma buffer, if we didn't get the required
+	 * buffer from the pool, we would have allocated it at the run time
+	 * and set the free_buf flag. We must free that buffer. Otherwise,
+	 * just mark that the buffer is not in use
+	 */
+	if (kioc->free_buf == 1)
+		pci_pool_free(pool->handle, kioc->buf_vaddr, kioc->buf_paddr);
+	else
+		pool->in_use = 0;
+
+	spin_unlock_irqrestore(&pool->lock, flags);
+
+	/* Return the kioc to the free pool */
+	spin_lock_irqsave(&adp->kioc_pool_lock, flags);
+	list_add(&kioc->list, &adp->kioc_pool);
+	spin_unlock_irqrestore(&adp->kioc_pool_lock, flags);
+
+	/* increment the free kioc count */
+	up(&adp->kioc_semaphore);
+
+	return;
+}
+
+/**
+ * lld_ioctl - Routine to issue ioctl to low level drvr
+ *
+ * @adp		: The adapter handle
+ * @kioc	: The ioctl packet with kernel addresses
+ */
+static int
+lld_ioctl(mraid_mmadp_t *adp, uioc_t *kioc)
+{
+	int			rval;
+	struct timer_list	timer;
+	struct timer_list	*tp = NULL;
+
+	kioc->status	= -ENODATA;
+	rval		= adp->issue_uioc(adp->drvr_data, kioc, IOCTL_ISSUE);
+
+	if (rval) return rval;
+
+	/*
+	 * Start the timer
+	 */
+	if (adp->timeout > 0) {
+		tp		= &timer;
+		init_timer(tp);
+
+		tp->function	= lld_timedout;
+		tp->data	= (unsigned long)kioc;
+		tp->expires	= jiffies + adp->timeout * HZ;
+
+		add_timer(tp);
+	}
+
+	/*
+	 * Wait till the low level driver completes the ioctl. After this
+	 * call, the ioctl either completed successfully or timedout.
+	 */
+	wait_event(wait_q, (kioc->status != -ENODATA));
+	if (tp) {
+		del_timer_sync(tp);
+	}
+
+	return kioc->status;
+}
+
+
+/**
+ * ioctl_done - callback from the low level driver
+ *
+ * @kioc	: completed ioctl packet
+ */
+static void
+ioctl_done(uioc_t *kioc)
+{
+	/*
+	 * When the kioc returns from driver, make sure it still doesn't
+	 * have ENODATA in status. Otherwise, driver will hang on wait_event
+	 * forever
+	 */
+	if (kioc->status == -ENODATA) {
+		con_log(CL_ANN, (KERN_WARNING
+			"megaraid cmm: lld didn't change status!\n"));
+
+		kioc->status = -EINVAL;
+	}
+
+	wake_up(&wait_q);
+}
+
+
+/*
+ * lld_timedout	: callback from the expired timer
+ *
+ * @ptr		: ioctl packet that timed out
+ */
+static void
+lld_timedout(unsigned long ptr)
+{
+	uioc_t *kioc	= (uioc_t *)ptr;
+
+	kioc->status 	= -ETIME;
+
+	con_log(CL_ANN, (KERN_WARNING "megaraid cmm: ioctl timed out\n"));
+
+	wake_up(&wait_q);
+}
+
+
+/**
+ * kioc_to_mimd	: Converter from new back to old format
+ *
+ * @kioc	: Kernel space IOCTL packet (successfully issued)
+ * @mimd	: User space MIMD packet
+ */
+static int
+kioc_to_mimd(uioc_t *kioc, mimd_t __user *mimd)
+{
+	mimd_t			kmimd;
+	uint8_t			opcode;
+	uint8_t			subopcode;
+
+	mbox64_t		*mbox64;
+	mraid_passthru_t	__user *upthru32;
+	mraid_passthru_t	*kpthru32;
+	mcontroller_t		cinfo;
+	mraid_hba_info_t	*hinfo;
+
+
+	if (copy_from_user(&kmimd, mimd, sizeof(mimd_t)))
+		return (-EFAULT);
+
+	opcode		= kmimd.ui.fcs.opcode;
+	subopcode	= kmimd.ui.fcs.subopcode;
+
+	if (opcode == 0x82) {
+		switch (subopcode) {
+
+		case MEGAIOC_QADAPINFO:
+
+			hinfo = (mraid_hba_info_t *)(unsigned long)
+					kioc->buf_vaddr;
+
+			hinfo_to_cinfo(hinfo, &cinfo);
+
+			if (copy_to_user(kmimd.data, &cinfo, sizeof(cinfo)))
+				return (-EFAULT);
+
+			return 0;
+
+		default:
+			return (-EINVAL);
+		}
+
+		return 0;
+	}
+
+	mbox64 = (mbox64_t *)(unsigned long)kioc->cmdbuf;
+
+	if (kioc->user_pthru) {
+
+		upthru32 = kioc->user_pthru;
+		kpthru32 = kioc->pthru32;
+
+		if (copy_to_user(&upthru32->scsistatus,
+					&kpthru32->scsistatus,
+					sizeof(uint8_t))) {
+			return (-EFAULT);
+		}
+	}
+
+	if (kioc->user_data) {
+		if (copy_to_user(kioc->user_data, kioc->buf_vaddr,
+					kioc->user_data_len)) {
+			return (-EFAULT);
+		}
+	}
+
+	if (copy_to_user(&mimd->mbox[17],
+			&mbox64->mbox32.status, sizeof(uint8_t))) {
+		return (-EFAULT);
+	}
+
+	return 0;
+}
+
+
+/**
+ * hinfo_to_cinfo - Convert new format hba info into old format
+ *
+ * @hinfo	: New format, more comprehensive adapter info
+ * @cinfo	: Old format adapter info to support mimd_t apps
+ */
+static void
+hinfo_to_cinfo(mraid_hba_info_t *hinfo, mcontroller_t *cinfo)
+{
+	if (!hinfo || !cinfo)
+		return;
+
+	cinfo->base		= hinfo->baseport;
+	cinfo->irq		= hinfo->irq;
+	cinfo->numldrv		= hinfo->num_ldrv;
+	cinfo->pcibus		= hinfo->pci_bus;
+	cinfo->pcidev		= hinfo->pci_slot;
+	cinfo->pcifun		= PCI_FUNC(hinfo->pci_dev_fn);
+	cinfo->pciid		= hinfo->pci_device_id;
+	cinfo->pcivendor	= hinfo->pci_vendor_id;
+	cinfo->pcislot		= hinfo->pci_slot;
+	cinfo->uid		= hinfo->unique_id;
+}
+
+
+/*
+ * mraid_mm_register_adp - Registration routine for low level drvrs
+ *
+ * @adp	: Adapter objejct
+ */
+int
+mraid_mm_register_adp(mraid_mmadp_t *lld_adp)
+{
+	mraid_mmadp_t	*adapter;
+	mbox64_t	*mbox_list;
+	uioc_t		*kioc;
+	uint32_t	rval;
+	int		i;
+
+
+	if (lld_adp->drvr_type != DRVRTYPE_MBOX)
+		return (-EINVAL);
+
+	adapter = kmalloc(sizeof(mraid_mmadp_t), GFP_KERNEL);
+
+	if (!adapter) {
+		rval = -ENOMEM;
+		goto memalloc_error;
+	}
+
+	memset(adapter, 0, sizeof(mraid_mmadp_t));
+
+	adapter->unique_id	= lld_adp->unique_id;
+	adapter->drvr_type	= lld_adp->drvr_type;
+	adapter->drvr_data	= lld_adp->drvr_data;
+	adapter->pdev		= lld_adp->pdev;
+	adapter->issue_uioc	= lld_adp->issue_uioc;
+	adapter->timeout	= lld_adp->timeout;
+	adapter->max_kioc	= lld_adp->max_kioc;
+
+	/*
+	 * Allocate single blocks of memory for all required kiocs,
+	 * mailboxes and passthru structures.
+	 */
+	adapter->kioc_list	= kmalloc(sizeof(uioc_t) * lld_adp->max_kioc,
+						GFP_KERNEL);
+	adapter->mbox_list	= kmalloc(sizeof(mbox64_t) * lld_adp->max_kioc,
+						GFP_KERNEL);
+	adapter->pthru_dma_pool = pci_pool_create("megaraid mm pthru pool",
+						adapter->pdev,
+						sizeof(mraid_passthru_t),
+						16, 0);
+
+	if (!adapter->kioc_list || !adapter->mbox_list ||
+			!adapter->pthru_dma_pool) {
+
+		con_log(CL_ANN, (KERN_WARNING
+			"megaraid cmm: out of memory, %s %d\n", __FUNCTION__,
+			__LINE__));
+
+		rval = (-ENOMEM);
+
+		goto memalloc_error;
+	}
+
+	/*
+	 * Slice kioc_list and make a kioc_pool with the individiual kiocs
+	 */
+	INIT_LIST_HEAD(&adapter->kioc_pool);
+	spin_lock_init(&adapter->kioc_pool_lock);
+	sema_init(&adapter->kioc_semaphore, lld_adp->max_kioc);
+
+	mbox_list	= (mbox64_t *)adapter->mbox_list;
+
+	for (i = 0; i < lld_adp->max_kioc; i++) {
+
+		kioc		= adapter->kioc_list + i;
+		kioc->cmdbuf	= (uint64_t)(unsigned long)(mbox_list + i);
+		kioc->pthru32	= pci_pool_alloc(adapter->pthru_dma_pool,
+						GFP_KERNEL, &kioc->pthru32_h);
+
+		if (!kioc->pthru32) {
+
+			con_log(CL_ANN, (KERN_WARNING
+				"megaraid cmm: out of memory, %s %d\n",
+					__FUNCTION__, __LINE__));
+
+			rval = (-ENOMEM);
+
+			goto pthru_dma_pool_error;
+		}
+
+		list_add_tail(&kioc->list, &adapter->kioc_pool);
+	}
+
+	// Setup the dma pools for data buffers
+	if ((rval = mraid_mm_setup_dma_pools(adapter)) != 0) {
+		goto dma_pool_error;
+	}
+
+	list_add_tail(&adapter->list, &adapters_list_g);
+
+	adapters_count_g++;
+
+	return 0;
+
+dma_pool_error:
+	/* Do nothing */
+
+pthru_dma_pool_error:
+
+	for (i = 0; i < lld_adp->max_kioc; i++) {
+		kioc = adapter->kioc_list + i;
+		if (kioc->pthru32) {
+			pci_pool_free(adapter->pthru_dma_pool, kioc->pthru32,
+				kioc->pthru32_h);
+		}
+	}
+
+memalloc_error:
+
+	if (adapter->kioc_list)
+		kfree(adapter->kioc_list);
+
+	if (adapter->mbox_list)
+		kfree(adapter->mbox_list);
+
+	if (adapter->pthru_dma_pool)
+		pci_pool_destroy(adapter->pthru_dma_pool);
+
+	if (adapter)
+		kfree(adapter);
+
+	return rval;
+}
+
+/**
+ * mraid_mm_setup_dma_pools - Set up dma buffer pools per adapter
+ *
+ * @adp	: Adapter softstate
+ *
+ * We maintain a pool of dma buffers per each adapter. Each pool has one
+ * buffer. E.g, we may have 5 dma pools - one each for 4k, 8k ... 64k buffers.
+ * We have just one 4k buffer in 4k pool, one 8k buffer in 8k pool etc. We
+ * dont' want to waste too much memory by allocating more buffers per each
+ * pool.
+ */
+static int
+mraid_mm_setup_dma_pools(mraid_mmadp_t *adp)
+{
+	mm_dmapool_t	*pool;
+	int		bufsize;
+	int		i;
+
+	/*
+	 * Create MAX_DMA_POOLS number of pools
+	 */
+	bufsize = MRAID_MM_INIT_BUFF_SIZE;
+
+	for (i = 0; i < MAX_DMA_POOLS; i++){
+
+		pool = &adp->dma_pool_list[i];
+
+		pool->buf_size = bufsize;
+		spin_lock_init(&pool->lock);
+
+		pool->handle = pci_pool_create("megaraid mm data buffer",
+						adp->pdev, bufsize, 16, 0);
+
+		if (!pool->handle) {
+			goto dma_pool_setup_error;
+		}
+
+		pool->vaddr = pci_pool_alloc(pool->handle, GFP_KERNEL,
+							&pool->paddr);
+
+		if (!pool->vaddr)
+			goto dma_pool_setup_error;
+
+		bufsize = bufsize * 2;
+	}
+
+	return 0;
+
+dma_pool_setup_error:
+
+	mraid_mm_teardown_dma_pools(adp);
+	return (-ENOMEM);
+}
+
+
+/*
+ * mraid_mm_unregister_adp - Unregister routine for low level drivers
+ *				  Assume no outstanding ioctls to llds.
+ *
+ * @unique_id	: UID of the adpater
+ */
+int
+mraid_mm_unregister_adp(uint32_t unique_id)
+{
+	mraid_mmadp_t	*adapter;
+	mraid_mmadp_t	*tmp;
+
+	list_for_each_entry_safe(adapter, tmp, &adapters_list_g, list) {
+
+
+		if (adapter->unique_id == unique_id) {
+
+			adapters_count_g--;
+
+			list_del_init(&adapter->list);
+
+			mraid_mm_free_adp_resources(adapter);
+
+			kfree(adapter);
+
+			con_log(CL_ANN, (
+				"megaraid cmm: Unregistered one adapter:%#x\n",
+				unique_id));
+
+			return 0;
+		}
+	}
+
+	return (-ENODEV);
+}
+
+/**
+ * mraid_mm_free_adp_resources - Free adapter softstate
+ *
+ * @adp	: Adapter softstate
+ */
+static void
+mraid_mm_free_adp_resources(mraid_mmadp_t *adp)
+{
+	uioc_t	*kioc;
+	int	i;
+
+	mraid_mm_teardown_dma_pools(adp);
+
+	for (i = 0; i < adp->max_kioc; i++) {
+
+		kioc = adp->kioc_list + i;
+
+		pci_pool_free(adp->pthru_dma_pool, kioc->pthru32,
+				kioc->pthru32_h);
+	}
+
+	kfree(adp->kioc_list);
+
+	kfree(adp->mbox_list);
+
+	pci_pool_destroy(adp->pthru_dma_pool);
+
+
+	return;
+}
+
+
+/**
+ * mraid_mm_teardown_dma_pools - Free all per adapter dma buffers
+ *
+ * @adp	: Adapter softstate
+ */
+static void
+mraid_mm_teardown_dma_pools(mraid_mmadp_t *adp)
+{
+	int		i;
+	mm_dmapool_t	*pool;
+
+	for (i = 0; i < MAX_DMA_POOLS; i++) {
+
+		pool = &adp->dma_pool_list[i];
+
+		if (pool->handle) {
+
+			if (pool->vaddr)
+				pci_pool_free(pool->handle, pool->vaddr,
+							pool->paddr);
+
+			pci_pool_destroy(pool->handle);
+			pool->handle = NULL;
+		}
+	}
+
+	return;
+}
+
+/**
+ * mraid_mm_init	: Module entry point
+ */
+static int __init
+mraid_mm_init(void)
+{
+	// Announce the driver version
+	con_log(CL_ANN, (KERN_INFO "megaraid cmm: %s %s\n",
+		LSI_COMMON_MOD_VERSION, LSI_COMMON_MOD_EXT_VERSION));
+
+	majorno = register_chrdev(0, "megadev", &lsi_fops);
+
+	if (majorno < 0) {
+		con_log(CL_ANN, ("megaraid cmm: cannot get major\n"));
+		return majorno;
+	}
+
+	init_waitqueue_head(&wait_q);
+
+	INIT_LIST_HEAD(&adapters_list_g);
+
+#ifdef CONFIG_COMPAT
+	register_ioctl32_conversion(MEGAIOCCMD, mraid_mm_compat_ioctl);
+#endif
+
+	return 0;
+}
+
+
+/**
+ * mraid_mm_compat_ioctl	: 32bit to 64bit ioctl conversion routine
+ */
+#ifdef CONFIG_COMPAT
+static int
+mraid_mm_compat_ioctl(unsigned int fd, unsigned int cmd,
+			unsigned long arg, struct file *filep)
+{
+	struct inode *inode = filep->f_dentry->d_inode;
+
+	return mraid_mm_ioctl(inode, filep, cmd, arg);
+}
+#endif
+
+/**
+ * mraid_mm_exit	: Module exit point
+ */
+static void __exit
+mraid_mm_exit(void)
+{
+	con_log(CL_DLEVEL1 , ("exiting common mod\n"));
+
+	unregister_chrdev(majorno, "megadev");
+	unregister_ioctl32_conversion(MEGAIOCCMD);
+}
+
+module_init(mraid_mm_init);
+module_exit(mraid_mm_exit);
+
+/* vi: set ts=8 sw=8 tw=78: */
diff -Nru a/drivers/scsi/megaraid/megaraid_mm.h b/drivers/scsi/megaraid/megaraid_mm.h
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/drivers/scsi/megaraid/megaraid_mm.h	2004-10-18 14:57:21 -07:00
@@ -0,0 +1,102 @@
+/*
+ *
+ *			Linux MegaRAID device driver
+ *
+ * Copyright (c) 2003-2004  LSI Logic 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.
+ *
+ * FILE		: megaraid_mm.h
+ */
+
+#ifndef MEGARAID_MM_H
+#define MEGARAID_MM_H
+
+#include <linux/spinlock.h>
+#include <linux/fs.h>
+#include <asm/uaccess.h>
+#include <linux/version.h>
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/pci.h>
+#include <linux/list.h>
+#include <linux/ioctl32.h>
+
+#include "mbox_defs.h"
+#include "megaraid_ioctl.h"
+
+
+#define LSI_COMMON_MOD_VERSION	"2.20.2.0"
+#define LSI_COMMON_MOD_EXT_VERSION	\
+		"(Release Date: Thu Aug 19 09:58:33 EDT 2004)"
+
+
+#define LSI_DBGLVL			dbglevel
+
+// The smallest dma pool
+#define MRAID_MM_INIT_BUFF_SIZE		4096
+
+/**
+ * mimd_t	: Old style ioctl packet structure (deprecated)
+ *
+ * @inlen	:
+ * @outlen	:
+ * @fca		:
+ * @opcode	:
+ * @subopcode	:
+ * @adapno	:
+ * @buffer	:
+ * @pad		:
+ * @length	:
+ * @mbox	:
+ * @pthru	:
+ * @data	:
+ * @pad		:
+ *
+ * Note		: This structure is DEPRECATED. New applications must use
+ *		: uioc_t structure instead. All new hba drivers use the new
+ *		: format. If we get this mimd packet, we will convert it into
+ *		: new uioc_t format and send it to the hba drivers.
+ */
+
+typedef struct mimd {
+
+	uint32_t inlen;
+	uint32_t outlen;
+
+	union {
+		uint8_t fca[16];
+		struct {
+			uint8_t opcode;
+			uint8_t subopcode;
+			uint16_t adapno;
+#if BITS_PER_LONG == 32
+			uint8_t __user *buffer;
+			uint8_t pad[4];
+#endif
+#if BITS_PER_LONG == 64
+			uint8_t __user *buffer;
+#endif
+			uint32_t length;
+		} __attribute__ ((packed)) fcs;
+	} __attribute__ ((packed)) ui;
+
+	uint8_t mbox[18];		/* 16 bytes + 2 status bytes */
+	mraid_passthru_t pthru;
+
+#if BITS_PER_LONG == 32
+	char __user *data;		/* buffer <= 4096 for 0x80 commands */
+	char pad[4];
+#endif
+#if BITS_PER_LONG == 64
+	char __user *data;
+#endif
+
+} __attribute__ ((packed))mimd_t;
+
+#endif // MEGARAID_MM_H
+
+// vi: set ts=8 sw=8 tw=78:
diff -Nru a/drivers/scsi/megaraid.c b/drivers/scsi/megaraid.c
--- a/drivers/scsi/megaraid.c	2004-10-18 14:55:53 -07:00
+++ b/drivers/scsi/megaraid.c	2004-10-18 14:55:53 -07:00
@@ -25,11 +25,8 @@
  *					518, 520, 531, 532
  *
  * This driver is supported by LSI Logic, with assistance from Red Hat, Dell,
- * and others. Please send updates to the public mailing list
- * linux-megaraid-devel@dell.com, and subscribe to and read archives of this
- * list at http://lists.us.dell.com/.
- *
- * For history of changes, see ChangeLog.megaraid.
+ * and others. Please send updates to the mailing list
+ * linux-scsi@vger.kernel.org .
  *
  */
 
@@ -53,9 +50,12 @@
 
 #include "megaraid.h"
 
+#define MEGARAID_MODULE_VERSION "2.00.3"
+
 MODULE_AUTHOR ("LSI Logic Corporation");
 MODULE_DESCRIPTION ("LSI Logic MegaRAID driver");
 MODULE_LICENSE ("GPL");
+MODULE_VERSION(MEGARAID_MODULE_VERSION);
 
 static unsigned int max_cmd_per_lun = DEF_CMD_PER_LUN;
 MODULE_PARM(max_cmd_per_lun, "i");
diff -Nru a/drivers/scsi/nsp32.c b/drivers/scsi/nsp32.c
--- a/drivers/scsi/nsp32.c	2004-10-18 14:56:28 -07:00
+++ b/drivers/scsi/nsp32.c	2004-10-18 14:56:28 -07:00
@@ -267,8 +267,8 @@
 static        int  nsp32_prom_read     (nsp32_hw_data *, int);
 static        int  nsp32_prom_read_bit (nsp32_hw_data *);
 static        void nsp32_prom_write_bit(nsp32_hw_data *, int);
-static inline void nsp32_prom_set      (nsp32_hw_data *, int, int);
-static inline int  nsp32_prom_get      (nsp32_hw_data *, int);
+static        void nsp32_prom_set      (nsp32_hw_data *, int, int);
+static        int  nsp32_prom_get      (nsp32_hw_data *, int);
 
 /* debug/warning/info message */
 static void nsp32_message (const char *, int, char *, char *, ...);
@@ -3342,7 +3342,7 @@
 	return val;
 }
 
-static inline void nsp32_prom_set(nsp32_hw_data *data, int bit, int val)
+static void nsp32_prom_set(nsp32_hw_data *data, int bit, int val)
 {
 	int base = data->BaseAddress;
 	int tmp;
@@ -3360,7 +3360,7 @@
 	udelay(10);
 }
 
-static inline int nsp32_prom_get(nsp32_hw_data *data, int bit)
+static int nsp32_prom_get(nsp32_hw_data *data, int bit)
 {
 	int base = data->BaseAddress;
 	int tmp, ret;
diff -Nru a/drivers/scsi/pas16.c b/drivers/scsi/pas16.c
--- a/drivers/scsi/pas16.c	2004-10-18 14:55:54 -07:00
+++ b/drivers/scsi/pas16.c	2004-10-18 14:55:54 -07:00
@@ -605,6 +605,7 @@
 {
 	if (shost->irq)
 		free_irq(shost->irq, NULL);
+	NCR5380_exit(shost);
 	if (shost->dma_channel != 0xff)
 		free_dma(shost->dma_channel);
 	if (shost->io_port && shost->n_io_port)
diff -Nru a/drivers/scsi/pcmcia/nsp_cs.c b/drivers/scsi/pcmcia/nsp_cs.c
--- a/drivers/scsi/pcmcia/nsp_cs.c	2004-10-18 14:57:04 -07:00
+++ b/drivers/scsi/pcmcia/nsp_cs.c	2004-10-18 14:57:04 -07:00
@@ -1528,7 +1528,7 @@
 	thislength = pos - (buffer + offset);
 
 	if(thislength < 0) {
-		*start = 0;
+		*start = NULL;
                 return 0;
         }
 
diff -Nru a/drivers/scsi/qla1280.c b/drivers/scsi/qla1280.c
--- a/drivers/scsi/qla1280.c	2004-10-18 14:57:05 -07:00
+++ b/drivers/scsi/qla1280.c	2004-10-18 14:57:05 -07:00
@@ -4,7 +4,7 @@
 * QLogic  QLA1280 (Ultra2)  and  QLA12160 (Ultra3) SCSI driver
 * Copyright (C) 2000 Qlogic Corporation (www.qlogic.com)
 * Copyright (C) 2001-2004 Jes Sorensen, Wild Open Source Inc.
-* Copyright (C) 2003 Christoph Hellwig
+* Copyright (C) 2003-2004 Christoph Hellwig
 *
 * 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
@@ -17,9 +17,12 @@
 * General Public License for more details.
 *
 ******************************************************************************/
-#define QLA1280_VERSION      "3.24.3"
+#define QLA1280_VERSION      "3.24.4"
 /*****************************************************************************
     Revision History:
+    Rev  3.24.4 June 7, 2004 Christoph Hellwig
+	- restructure firmware loading, cleanup initialization code
+	- prepare support for ISP1020/1040 chips
     Rev  3.24.3 January 19, 2004, Jes Sorensen
 	- Handle PCI DMA mask settings correctly
 	- Correct order of error handling in probe_one, free_irq should not
@@ -485,6 +488,14 @@
 #define ia64_platform_is(foo)		(!strcmp(x, platform_name))
 #endif
 
+
+#define IS_ISP1040(ha) (ha->pdev->device == PCI_DEVICE_ID_QLOGIC_ISP1020)
+#define IS_ISP1x40(ha) (ha->pdev->device == PCI_DEVICE_ID_QLOGIC_ISP1020 || \
+			ha->pdev->device == PCI_DEVICE_ID_QLOGIC_ISP1240)
+#define IS_ISP1x160(ha)        (ha->pdev->device == PCI_DEVICE_ID_QLOGIC_ISP10160 || \
+				ha->pdev->device == PCI_DEVICE_ID_QLOGIC_ISP12160)
+
+
 static int qla1280_probe_one(struct pci_dev *, const struct pci_device_id *);
 static void qla1280_remove_one(struct pci_dev *);
 
@@ -501,9 +512,7 @@
 /*
  *  QLogic ISP1280 Hardware Support Function Prototypes.
  */
-static int qla1280_isp_firmware(struct scsi_qla_host *);
-static int qla1280_chip_diag(struct scsi_qla_host *);
-static int qla1280_setup_chip(struct scsi_qla_host *);
+static int qla1280_load_firmware(struct scsi_qla_host *);
 static int qla1280_init_rings(struct scsi_qla_host *);
 static int qla1280_nvram_config(struct scsi_qla_host *);
 static int qla1280_mailbox_command(struct scsi_qla_host *,
@@ -1384,16 +1393,10 @@
 	uint8_t mr;
 	uint16_t mb[MAILBOX_REGISTER_COUNT];
 	struct nvram *nv;
-	int is1x160, status;
+	int status;
 
 	nv = &ha->nvram;
 
-	if (ha->pdev->device == PCI_DEVICE_ID_QLOGIC_ISP12160 ||
-	    ha->pdev->device == PCI_DEVICE_ID_QLOGIC_ISP10160)
-		is1x160 = 1;
-	else
-		is1x160 = 0;
-
 	mr = BIT_3 | BIT_2 | BIT_1 | BIT_0;
 
 	/* Set Target Parameters. */
@@ -1403,17 +1406,16 @@
 
 	mb[2] = (nv->bus[bus].target[target].parameter.c << 8);
 
-	if (is1x160)
-		mb[3] =	nv->bus[bus].target[target].flags.flags1x160.sync_offset << 8;
-	else
-		mb[3] =	nv->bus[bus].target[target].flags.flags1x80.sync_offset << 8;
-	mb[3] |= nv->bus[bus].target[target].sync_period;
-
-	if (is1x160) {
+	if (IS_ISP1x160(ha)) {
 		mb[2] |= nv->bus[bus].target[target].ppr_1x160.flags.enable_ppr << 5;
-		mb[6] =	nv->bus[bus].target[target].ppr_1x160.flags.ppr_options << 8;
-		mb[6] |= nv->bus[bus].target[target].ppr_1x160.flags.ppr_bus_width;
+		mb[3] =	(nv->bus[bus].target[target].flags.flags1x160.sync_offset << 8) |
+			 nv->bus[bus].target[target].sync_period;
+		mb[6] =	(nv->bus[bus].target[target].ppr_1x160.flags.ppr_options << 8) |
+			 nv->bus[bus].target[target].ppr_1x160.flags.ppr_bus_width;
 		mr |= BIT_6;
+	} else {
+		mb[3] =	(nv->bus[bus].target[target].flags.flags1x80.sync_offset << 8) |
+			 nv->bus[bus].target[target].sync_period;
 	}
 
 	status = qla1280_mailbox_command(ha, mr, &mb[0]);
@@ -1476,8 +1478,7 @@
 	    (driver_setup.wide_mask &&
 	     (~driver_setup.wide_mask & (1 << target))))
 		nv->bus[bus].target[target].parameter.f.enable_wide = 0;
-	if (ha->pdev->device == PCI_DEVICE_ID_QLOGIC_ISP12160 ||
-	    ha->pdev->device == PCI_DEVICE_ID_QLOGIC_ISP10160) {
+	if (IS_ISP1x160(ha)) {
 		if (driver_setup.no_ppr ||
 		    (driver_setup.ppr_mask &&
 		     (~driver_setup.ppr_mask & (1 << target))))
@@ -1802,17 +1803,8 @@
 	 */
 	spin_lock_irqsave(HOST_LOCK, flags);
 #endif
-	/* If firmware needs to be loaded */
-	if (qla1280_isp_firmware(ha)) {
-		if (!(status = qla1280_chip_diag(ha))) {
-			status = qla1280_setup_chip(ha);
-		}
-	} else {
-		printk(KERN_ERR "scsi(%li): isp_firmware() failed!\n",
-		       ha->host_no);
-		status = 1;
-	}
 
+	status = qla1280_load_firmware(ha);
 	if (status) {
 		printk(KERN_ERR "scsi(%li): initialize: pci probe failed!\n",
 		       ha->host_no);
@@ -1823,36 +1815,24 @@
 	dprintk(1, "scsi(%ld): Configure NVRAM parameters\n", ha->host_no);
 	qla1280_nvram_config(ha);
 
-	if (!ha->flags.disable_host_adapter && !qla1280_init_rings(ha)) {
-		/* Issue SCSI reset. */
-		/* dg 03/13 if we can't reset twice then bus is dead */
-		for (bus = 0; bus < ha->ports; bus++) {
-			if (!ha->bus_settings[bus].disable_scsi_reset){
-				if (qla1280_bus_reset(ha, bus)) {
-					if (qla1280_bus_reset(ha, bus)) {
-						ha->bus_settings[bus].scsi_bus_dead = 1;
-					}
-				}
-			}
-		}
+	if (ha->flags.disable_host_adapter) {
+		status = 1;
+		goto out;
+	}
 
-		/*
-		 * qla1280_bus_reset() will take care of issueing markers,
-		 * no need to do that here as well!
-		 */
-#if 0
-		/* Issue marker command. */
-		ha->flags.reset_marker = 0;
-		for (bus = 0; bus < ha->ports; bus++) {
-			ha->bus_settings[bus].reset_marker = 0;
-			qla1280_marker(ha, bus, 0, 0, MK_SYNC_ALL);
-		}
-#endif
+	status = qla1280_init_rings(ha);
+	if (status)
+		goto out;
 
-		ha->flags.online = 1;
-	} else
-		status = 1;
+	/* Issue SCSI reset, if we can't reset twice then bus is dead */
+	for (bus = 0; bus < ha->ports; bus++) {
+		if (!ha->bus_settings[bus].disable_scsi_reset &&
+		    qla1280_bus_reset(ha, bus) &&
+		    qla1280_bus_reset(ha, bus))
+			ha->bus_settings[bus].scsi_bus_dead = 1;
+	}
 
+	ha->flags.online = 1;
  out:
 #if LINUX_VERSION_CODE >= 0x020500
 	spin_unlock_irqrestore(HOST_LOCK, flags);
@@ -1945,13 +1925,13 @@
 	int status = 0;
 	int cnt;
 	uint16_t data;
-
 	dprintk(3, "qla1280_chip_diag: testing device at 0x%p \n", &reg->id_l);
 
 	dprintk(1, "scsi(%ld): Verifying chip\n", ha->host_no);
 
 	/* Soft reset chip and wait for it to finish. */
 	WRT_REG_WORD(&reg->ictrl, ISP_RESET);
+
 	/*
 	 * We can't do a traditional PCI write flush here by reading
 	 * back the register. The card will not respond once the reset
@@ -1969,145 +1949,138 @@
 		data = RD_REG_WORD(&reg->ictrl);
 	}
 
-	if (cnt) {
-		/* Reset register cleared by chip reset. */
-		dprintk(3, "qla1280_chip_diag: reset register cleared by "
-			"chip reset\n");
+	if (!cnt)
+		goto fail;
 
-		WRT_REG_WORD(&reg->cfg_1, 0);
+	/* Reset register cleared by chip reset. */
+	dprintk(3, "qla1280_chip_diag: reset register cleared by chip reset\n");
 
-		/* Reset RISC and disable BIOS which
-		   allows RISC to execute out of RAM. */
-#if 0
-		WRT_REG_WORD(&reg->host_cmd, HC_RESET_RISC);
-		RD_REG_WORD(&reg->id_l);	/* Flush PCI write */
-		WRT_REG_WORD(&reg->host_cmd, HC_RELEASE_RISC);
-		RD_REG_WORD(&reg->id_l);	/* Flush PCI write */
-		WRT_REG_WORD(&reg->host_cmd, HC_DISABLE_BIOS);
-#else
-		WRT_REG_WORD(&reg->host_cmd, HC_RESET_RISC |
-			     HC_RELEASE_RISC | HC_DISABLE_BIOS);
-#endif
-		RD_REG_WORD(&reg->id_l);	/* Flush PCI write */
-		data = qla1280_debounce_register(&reg->mailbox0);
-		/*
-		 * I *LOVE* this code!
-		 */
-		for (cnt = 1000000; cnt && data == MBS_BUSY; cnt--) {
-			udelay(5);
-			data = RD_REG_WORD(&reg->mailbox0);
-		}
+	WRT_REG_WORD(&reg->cfg_1, 0);
 
-		if (cnt) {
-			/* Check product ID of chip */
-			dprintk(3, "qla1280_chip_diag: Checking product "
-				"ID of chip\n");
-
-			if (RD_REG_WORD(&reg->mailbox1) != PROD_ID_1 ||
-			    (RD_REG_WORD(&reg->mailbox2) != PROD_ID_2 &&
-			     RD_REG_WORD(&reg->mailbox2) != PROD_ID_2a) ||
-			    RD_REG_WORD(&reg->mailbox3) != PROD_ID_3 ||
-			    RD_REG_WORD(&reg->mailbox4) != PROD_ID_4) {
-				printk(KERN_INFO "qla1280: Wrong product ID = "
-				       "0x%x,0x%x,0x%x,0x%x\n",
-				       RD_REG_WORD(&reg->mailbox1),
-				       RD_REG_WORD(&reg->mailbox2),
-				       RD_REG_WORD(&reg->mailbox3),
-				       RD_REG_WORD(&reg->mailbox4));
-				status = 1;
-			} else {
-				/*
-				 * Enable ints early!!!
-				 */
-				qla1280_enable_intrs(ha);
-
-				dprintk(1, "qla1280_chip_diag: Checking "
-					"mailboxes of chip\n");
-				/* Wrap Incoming Mailboxes Test. */
-				mb[0] = MBC_MAILBOX_REGISTER_TEST;
-				mb[1] = 0xAAAA;
-				mb[2] = 0x5555;
-				mb[3] = 0xAA55;
-				mb[4] = 0x55AA;
-				mb[5] = 0xA5A5;
-				mb[6] = 0x5A5A;
-				mb[7] = 0x2525;
-				if (!(status = qla1280_mailbox_command(ha,
-								       0xff,
-								       &mb
-								       [0]))) {
-					if (mb[1] != 0xAAAA ||
-					    mb[2] != 0x5555 ||
-					    mb[3] != 0xAA55 ||
-					    mb[4] != 0x55AA ||
-					    mb[5] != 0xA5A5 ||
-					    mb[6] != 0x5A5A ||
-					    mb[7] != 0x2525) {
-						status = 1;
-						printk(KERN_INFO "qla1280: "
-						       "Failed mbox check\n");
-					}
-				}
-			}
-		} else
-			status = 1;
-	} else
-		status = 1;
+	/* Reset RISC and disable BIOS which
+	   allows RISC to execute out of RAM. */
+	WRT_REG_WORD(&reg->host_cmd, HC_RESET_RISC |
+		     HC_RELEASE_RISC | HC_DISABLE_BIOS);
+
+	RD_REG_WORD(&reg->id_l);	/* Flush PCI write */
+	data = qla1280_debounce_register(&reg->mailbox0);
+
+	/*
+	 * I *LOVE* this code!
+	 */
+	for (cnt = 1000000; cnt && data == MBS_BUSY; cnt--) {
+		udelay(5);
+		data = RD_REG_WORD(&reg->mailbox0);
+	}
+
+	if (!cnt)
+		goto fail;
+
+	/* Check product ID of chip */
+	dprintk(3, "qla1280_chip_diag: Checking product ID of chip\n");
+
+	if (RD_REG_WORD(&reg->mailbox1) != PROD_ID_1 ||
+	    (RD_REG_WORD(&reg->mailbox2) != PROD_ID_2 &&
+	     RD_REG_WORD(&reg->mailbox2) != PROD_ID_2a) ||
+	    RD_REG_WORD(&reg->mailbox3) != PROD_ID_3 ||
+	    RD_REG_WORD(&reg->mailbox4) != PROD_ID_4) {
+		printk(KERN_INFO "qla1280: Wrong product ID = "
+		       "0x%x,0x%x,0x%x,0x%x\n",
+		       RD_REG_WORD(&reg->mailbox1),
+		       RD_REG_WORD(&reg->mailbox2),
+		       RD_REG_WORD(&reg->mailbox3),
+		       RD_REG_WORD(&reg->mailbox4));
+		goto fail;
+	}
 
+	/*
+	 * Enable ints early!!!
+	 */
+	qla1280_enable_intrs(ha);
+
+	dprintk(1, "qla1280_chip_diag: Checking mailboxes of chip\n");
+	/* Wrap Incoming Mailboxes Test. */
+	mb[0] = MBC_MAILBOX_REGISTER_TEST;
+	mb[1] = 0xAAAA;
+	mb[2] = 0x5555;
+	mb[3] = 0xAA55;
+	mb[4] = 0x55AA;
+	mb[5] = 0xA5A5;
+	mb[6] = 0x5A5A;
+	mb[7] = 0x2525;
+
+	status = qla1280_mailbox_command(ha, 0xff, mb);
 	if (status)
-		dprintk(2, "qla1280_chip_diag: **** FAILED ****\n");
-	else
-		dprintk(3, "qla1280_chip_diag: exiting normally\n");
+		goto fail;
 
+	if (mb[1] != 0xAAAA || mb[2] != 0x5555 || mb[3] != 0xAA55 ||
+	    mb[4] != 0x55AA || mb[5] != 0xA5A5 || mb[6] != 0x5A5A ||
+	    mb[7] != 0x2525) {
+		printk(KERN_INFO "qla1280: Failed mbox check\n");
+		goto fail;
+	}
+
+	dprintk(3, "qla1280_chip_diag: exiting normally\n");
+	return 0;
+ fail:
+	dprintk(2, "qla1280_chip_diag: **** FAILED ****\n");
 	return status;
 }
 
-/*
- * Setup chip
- *      Load and start RISC firmware.
- *
- * Input:
- *      ha = adapter block pointer.
- *
- * Returns:
- *      0 = success.
- */
-#define DUMP_IT_BACK 0		/* for debug of RISC loading */
 static int
-qla1280_setup_chip(struct scsi_qla_host *ha)
+qla1280_load_firmware_pio(struct scsi_qla_host *ha)
 {
-	int status = 0;
-	uint16_t risc_address;
-	uint16_t *risc_code_address;
-	int risc_code_size;
-	uint16_t mb[MAILBOX_REGISTER_COUNT];
-	uint16_t cnt;
-	int num, i;
-#if DUMP_IT_BACK
-	uint8_t *sp;
-	uint8_t *tbuf;
-	dma_addr_t p_tbuf;
-#endif
+	uint16_t risc_address, *risc_code_address, risc_code_size;
+	uint16_t mb[MAILBOX_REGISTER_COUNT], i;
+	int err;
 
-	ENTER("qla1280_setup_chip");
+	/* Load RISC code. */
+	risc_address = *ql1280_board_tbl[ha->devnum].fwstart;
+	risc_code_address = ql1280_board_tbl[ha->devnum].fwcode;
+	risc_code_size = *ql1280_board_tbl[ha->devnum].fwlen;
 
-	dprintk(1, "scsi(%ld): Setup chip\n", ha->host_no);
+	for (i = 0; i < risc_code_size; i++) {
+		mb[0] = MBC_WRITE_RAM_WORD;
+		mb[1] = risc_address + i;
+		mb[2] = risc_code_address[i];
+
+		err = qla1280_mailbox_command(ha, BIT_0 | BIT_1 | BIT_2, mb);
+		if (err) {
+			printk(KERN_ERR "scsi(%li): Failed to load firmware\n",
+					ha->host_no);
+			return err;
+		}
+	}
 
+	return 0;
+}
+
+#define DUMP_IT_BACK 0		/* for debug of RISC loading */
+static int
+qla1280_load_firmware_dma(struct scsi_qla_host *ha)
+{
+	uint16_t risc_address, *risc_code_address, risc_code_size;
+	uint16_t mb[MAILBOX_REGISTER_COUNT], cnt;
+	int err = 0, num, i;
 #if DUMP_IT_BACK
-	/* get consistent memory allocated for setup_chip */
+	uint8_t *sp, *tbuf;
+	dma_addr_t p_tbuf;
+
 	tbuf = pci_alloc_consistent(ha->pdev, 8000, &p_tbuf);
+	if (!tbuf)
+		return -ENOMEM;
 #endif
 
 	/* Load RISC code. */
 	risc_address = *ql1280_board_tbl[ha->devnum].fwstart;
 	risc_code_address = ql1280_board_tbl[ha->devnum].fwcode;
-	risc_code_size = (int) *ql1280_board_tbl[ha->devnum].fwlen;
+	risc_code_size = *ql1280_board_tbl[ha->devnum].fwlen;
 
-	dprintk(1, "qla1280_setup_chip: DMA RISC code (%i) words\n",
-		risc_code_size);
+	dprintk(1, "%s: DMA RISC code (%i) words\n",
+			__FUNCTION__, risc_code_size);
 
 	num = 0;
-	while (risc_code_size > 0 && !status) {
+	while (risc_code_size > 0) {
 		int warn __attribute__((unused)) = 0;
 
 		cnt = 2000 >> 1;
@@ -2129,15 +2102,16 @@
 		mb[2] = (ha->request_dma >> 16) & 0xffff;
 		mb[7] = pci_dma_hi32(ha->request_dma) & 0xffff;
 		mb[6] = pci_dma_hi32(ha->request_dma) >> 16;
-		dprintk(2, "qla1280_setup_chip: op=%d  0x%p = 0x%4x,0x%4x,"
-			"0x%4x,0x%4x\n", mb[0], (void *)(long)ha->request_dma,
-			mb[6], mb[7], mb[2], mb[3]);
-		if ((status = qla1280_mailbox_command(ha, BIT_4 | BIT_3 |
-						      BIT_2 | BIT_1 | BIT_0,
-						      &mb[0]))) {
+		dprintk(2, "%s: op=%d  0x%p = 0x%4x,0x%4x,0x%4x,0x%4x\n",
+				__FUNCTION__, mb[0],
+				(void *)(long)ha->request_dma,
+				mb[6], mb[7], mb[2], mb[3]);
+		err = qla1280_mailbox_command(ha, BIT_4 | BIT_3 | BIT_2 |
+				BIT_1 | BIT_0, mb);
+		if (err) {
 			printk(KERN_ERR "scsi(%li): Failed to load partial "
 			       "segment of f\n", ha->host_no);
-			break;
+			goto out;
 		}
 
 #if DUMP_IT_BACK
@@ -2149,22 +2123,22 @@
 		mb[7] = pci_dma_hi32(p_tbuf) & 0xffff;
 		mb[6] = pci_dma_hi32(p_tbuf) >> 16;
 
-		if ((status = qla1280_mailbox_command(ha,
-						      BIT_4 | BIT_3 | BIT_2 |
-						      BIT_1 | BIT_0,
-						      &mb[0]))) {
+		err = qla1280_mailbox_command(ha, BIT_4 | BIT_3 | BIT_2 |
+				BIT_1 | BIT_0, mb);
+		if (err) {
 			printk(KERN_ERR
 			       "Failed to dump partial segment of f/w\n");
-			break;
+			goto out;
 		}
 		sp = (uint8_t *)ha->request_ring;
 		for (i = 0; i < (cnt << 1); i++) {
 			if (tbuf[i] != sp[i] && warn++ < 10) {
-				printk(KERN_ERR "qla1280_setup_chip: FW "
-				       "compare error @ byte(0x%x) loop#=%x\n",
-				       i, num);
-				printk(KERN_ERR "setup_chip: FWbyte=%x  "
-				       "FWfromChip=%x\n", sp[i], tbuf[i]);
+				printk(KERN_ERR "%s: FW compare error @ "
+						"byte(0x%x) loop#=%x\n",
+						__FUNCTION__, i, num);
+				printk(KERN_ERR "%s: FWbyte=%x  "
+						"FWfromChip=%x\n",
+						__FUNCTION__, sp[i], tbuf[i]);
 				/*break; */
 			}
 		}
@@ -2175,37 +2149,69 @@
 		num++;
 	}
 
-	/* Verify checksum of loaded RISC code. */
-	if (!status) {
-		dprintk(1, "qla1280_setup_chip: Verifying checksum of "
-			"loaded RISC code.\n");
-		mb[0] = MBC_VERIFY_CHECKSUM;
-		/* mb[1] = ql12_risc_code_addr01; */
-		mb[1] = *ql1280_board_tbl[ha->devnum].fwstart;
-
-		if (!(status =
-		      qla1280_mailbox_command(ha, BIT_1 | BIT_0, &mb[0]))) {
-			/* Start firmware execution. */
-			dprintk(1,
-				"qla1280_setup_chip: start firmware running.\n");
-			mb[0] = MBC_EXECUTE_FIRMWARE;
-			mb[1] = *ql1280_board_tbl[ha->devnum].fwstart;
-			qla1280_mailbox_command(ha, BIT_1 | BIT_0, &mb[0]);
-		} else
-			printk(KERN_ERR "scsi(%li): qla1280_setup_chip: "
-			       "Failed checksum\n", ha->host_no);
-	}
-
+ out:
 #if DUMP_IT_BACK
-	/* free consistent memory allocated for setup_chip */
 	pci_free_consistent(ha->pdev, 8000, tbuf, p_tbuf);
 #endif
+	return err;
+}
 
-	if (status)
-		dprintk(2, "qla1280_setup_chip: **** FAILED ****\n");
+static int
+qla1280_start_firmware(struct scsi_qla_host *ha)
+{
+	uint16_t mb[MAILBOX_REGISTER_COUNT];
+	int err;
 
-	LEAVE("qla1280_setup_chip");
-	return status;
+	dprintk(1, "%s: Verifying checksum of loaded RISC code.\n",
+			__FUNCTION__);
+
+	/* Verify checksum of loaded RISC code. */
+	mb[0] = MBC_VERIFY_CHECKSUM;
+	/* mb[1] = ql12_risc_code_addr01; */
+	mb[1] = *ql1280_board_tbl[ha->devnum].fwstart;
+	err = qla1280_mailbox_command(ha, BIT_1 | BIT_0, mb);
+	if (err) {
+		printk(KERN_ERR "scsi(%li): Failed checksum\n", ha->host_no);
+		return err;
+	}
+
+	/* Start firmware execution. */
+	dprintk(1, "%s: start firmware running.\n", __FUNCTION__);
+	mb[0] = MBC_EXECUTE_FIRMWARE;
+	mb[1] = *ql1280_board_tbl[ha->devnum].fwstart;
+	err = qla1280_mailbox_command(ha, BIT_1 | BIT_0, &mb[0]);
+	if (err) {
+		printk(KERN_ERR "scsi(%li): Failed to start firmware\n",
+				ha->host_no);
+	}
+
+	return err;
+}
+
+static int
+qla1280_load_firmware(struct scsi_qla_host *ha)
+{
+	int err = -ENODEV;
+
+	/* If firmware needs to be loaded */
+	if (!qla1280_isp_firmware(ha)) {
+		printk(KERN_ERR "scsi(%li): isp_firmware() failed!\n",
+				ha->host_no);
+		goto out;
+	}
+
+	err = qla1280_chip_diag(ha);
+	if (err)
+		goto out;
+	if (IS_ISP1040(ha))
+		err = qla1280_load_firmware_pio(ha);
+	else
+		err = qla1280_load_firmware_dma(ha);
+	if (err)
+		goto out;
+	err = qla1280_start_firmware(ha);
+ out:
+	return err;
 }
 
 /*
@@ -2271,123 +2277,9 @@
 	return status;
 }
 
-/*
- * NVRAM configuration.
- *
- * Input:
- *      ha                = adapter block pointer.
- *      ha->request_ring  = request ring virtual address
- *
- * Output:
- *      host adapters parameters in host adapter block
- *
- * Returns:
- *      0 = success.
- */
-static int
-qla1280_nvram_config(struct scsi_qla_host *ha)
+static void
+qla1280_print_settings(struct nvram *nv)
 {
-	struct device_reg *reg = ha->iobase;
-	struct nvram *nv;
-	int is1x160, status = 0;
-	int bus, target, lun;
-	uint16_t mb[MAILBOX_REGISTER_COUNT];
-	uint16_t mask;
-
-	ENTER("qla1280_nvram_config");
-
-	if (ha->pdev->device == PCI_DEVICE_ID_QLOGIC_ISP12160 ||
-	    ha->pdev->device == PCI_DEVICE_ID_QLOGIC_ISP10160)
-		is1x160 = 1;
-	else
-		is1x160 = 0;
-
-	nv = &ha->nvram;
-	if (!ha->nvram_valid) {
-		dprintk(1, "Using defaults for NVRAM: \n");
-		memset(nv, 0, sizeof(struct nvram));
-
-		/* nv->cntr_flags_1.disable_loading_risc_code = 1; */
-		nv->firmware_feature.f.enable_fast_posting = 1;
-		nv->firmware_feature.f.disable_synchronous_backoff = 1;
-
-		nv->termination.f.scsi_bus_0_control = 3;
-		nv->termination.f.scsi_bus_1_control = 3;
-		nv->termination.f.auto_term_support = 1;
-
-		/*
-		 * Set default FIFO magic - What appropriate values
-		 * would be here is unknown. This is what I have found
-		 * testing with 12160s.
-		 * Now, I would love the magic decoder ring for this one,
-		 * the header file provided by QLogic seems to be bogus
-		 * or incomplete at best.
-		 */
-		nv->isp_config.c = 0x44;
-
-		if (is1x160)
-			nv->isp_parameter = 0x01;
-
-		for (bus = 0; bus < MAX_BUSES; bus++) {
-			nv->bus[bus].config_1.initiator_id = 7;
-			nv->bus[bus].bus_reset_delay = 5;
-			/* 8 = 5.0 clocks */
-			nv->bus[bus].config_2.async_data_setup_time = 8;
-			nv->bus[bus].config_2.req_ack_active_negation = 1;
-			nv->bus[bus].config_2.data_line_active_negation = 1;
-			nv->bus[bus].selection_timeout = 250;
-			nv->bus[bus].max_queue_depth = 256;
-
-			for (target = 0; target < MAX_TARGETS; target++) {
-				nv->bus[bus].target[target].parameter.f.
-					renegotiate_on_error = 1;
-				nv->bus[bus].target[target].parameter.f.
-					auto_request_sense = 1;
-				nv->bus[bus].target[target].parameter.f.
-					tag_queuing = 1;
-				nv->bus[bus].target[target].parameter.f.
-					enable_sync = 1;
-#if 1	/* Some SCSI Processors do not seem to like this */
-				nv->bus[bus].target[target].parameter.f.
-					enable_wide = 1;
-#endif
-				nv->bus[bus].target[target].parameter.f.
-					parity_checking = 1;
-				nv->bus[bus].target[target].parameter.f.
-					disconnect_allowed = 1;
-				nv->bus[bus].target[target].execution_throttle=
-					nv->bus[bus].max_queue_depth - 1;
-				if (is1x160) {
-					nv->bus[bus].target[target].flags.
-						flags1x160.device_enable = 1;
-					nv->bus[bus].target[target].flags.
-						flags1x160.sync_offset = 0x0e;
-					nv->bus[bus].target[target].
-						sync_period = 9;
-					nv->bus[bus].target[target].
-						ppr_1x160.flags.enable_ppr = 1;
-					nv->bus[bus].target[target].ppr_1x160.
-						flags.ppr_options = 2;
-					nv->bus[bus].target[target].ppr_1x160.
-						flags.ppr_bus_width = 1;
-				} else {
-					nv->bus[bus].target[target].flags.
-						flags1x80.device_enable = 1;
-					nv->bus[bus].target[target].flags.
-						flags1x80.sync_offset = 0x8;
-					nv->bus[bus].target[target].
-						sync_period = 10;
-				}
-			}
-		}
-	} else {
-		/* Always force AUTO sense for LINUX SCSI */
-		for (bus = 0; bus < MAX_BUSES; bus++)
-			for (target = 0; target < MAX_TARGETS; target++) {
-				nv->bus[bus].target[target].parameter.f.
-					auto_request_sense = 1;
-			}
-	}
 	dprintk(1, "qla1280 : initiator scsi id bus[0]=%d\n",
 		nv->bus[0].config_1.initiator_id);
 	dprintk(1, "qla1280 : initiator scsi id bus[1]=%d\n",
@@ -2433,36 +2325,264 @@
 		nv->bus[0].max_queue_depth);
 	dprintk(1, "qla1280 : max queue depth[1]=%d\n",
 		nv->bus[1].max_queue_depth);
+}
+
+static void
+qla1280_set_target_defaults(struct scsi_qla_host *ha, int bus, int target)
+{
+	struct nvram *nv = &ha->nvram;
+
+	nv->bus[bus].target[target].parameter.f.renegotiate_on_error = 1;
+	nv->bus[bus].target[target].parameter.f.auto_request_sense = 1;
+	nv->bus[bus].target[target].parameter.f.tag_queuing = 1;
+	nv->bus[bus].target[target].parameter.f.enable_sync = 1;
+#if 1	/* Some SCSI Processors do not seem to like this */
+	nv->bus[bus].target[target].parameter.f.enable_wide = 1;
+#endif
+	if (!IS_ISP1040(ha))
+		nv->bus[bus].target[target].parameter.f.parity_checking = 1;
+
+	nv->bus[bus].target[target].parameter.f.disconnect_allowed = 1;
+	nv->bus[bus].target[target].execution_throttle =
+		nv->bus[bus].max_queue_depth - 1;
+
+	if (IS_ISP1x160(ha)) {
+		nv->bus[bus].target[target].flags.flags1x160.device_enable = 1;
+		nv->bus[bus].target[target].flags.flags1x160.sync_offset = 0x0e;
+		nv->bus[bus].target[target].sync_period = 9;
+		nv->bus[bus].target[target].ppr_1x160.flags.enable_ppr = 1;
+		nv->bus[bus].target[target].ppr_1x160.flags.ppr_options = 2;
+		nv->bus[bus].target[target].ppr_1x160.flags.ppr_bus_width = 1;
+	} else {
+		nv->bus[bus].target[target].flags.flags1x80.device_enable = 1;
+		nv->bus[bus].target[target].flags.flags1x80.sync_offset = 12;
+		nv->bus[bus].target[target].sync_period = 10;
+	}
+}
+
+static void
+qla1280_set_defaults(struct scsi_qla_host *ha)
+{
+	struct nvram *nv = &ha->nvram;
+	int bus, target;
+
+	dprintk(1, "Using defaults for NVRAM: \n");
+	memset(nv, 0, sizeof(struct nvram));
+
+	/* nv->cntr_flags_1.disable_loading_risc_code = 1; */
+	nv->firmware_feature.f.enable_fast_posting = 1;
+	nv->firmware_feature.f.disable_synchronous_backoff = 1;
+	nv->termination.f.scsi_bus_0_control = 3;
+	nv->termination.f.scsi_bus_1_control = 3;
+	nv->termination.f.auto_term_support = 1;
+
+	/*
+	 * Set default FIFO magic - What appropriate values would be here
+	 * is unknown. This is what I have found testing with 12160s.
+	 *
+	 * Now, I would love the magic decoder ring for this one, the
+	 * header file provided by QLogic seems to be bogus or incomplete
+	 * at best.
+	 */
+	nv->isp_config.c = ISP_CFG1_BENAB|ISP_CFG1_F128;
+	if (IS_ISP1x160(ha))
+		nv->isp_parameter = 0x01; /* fast memory enable */
+
+	for (bus = 0; bus < MAX_BUSES; bus++) {
+		nv->bus[bus].config_1.initiator_id = 7;
+		nv->bus[bus].config_2.req_ack_active_negation = 1;
+		nv->bus[bus].config_2.data_line_active_negation = 1;
+		nv->bus[bus].selection_timeout = 250;
+		nv->bus[bus].max_queue_depth = 256;
+
+		if (IS_ISP1040(ha)) {
+			nv->bus[bus].bus_reset_delay = 3;
+			nv->bus[bus].config_2.async_data_setup_time = 6;
+			nv->bus[bus].retry_delay = 1;
+		} else {
+			nv->bus[bus].bus_reset_delay = 5;
+			nv->bus[bus].config_2.async_data_setup_time = 8;
+		}
+
+		for (target = 0; target < MAX_TARGETS; target++)
+			qla1280_set_target_defaults(ha, bus, target);
+	}
+}
+
+static int
+qla1280_config_target(struct scsi_qla_host *ha, int bus, int target)
+{
+	struct nvram *nv = &ha->nvram;
+	uint16_t mb[MAILBOX_REGISTER_COUNT];
+	int status, lun;
+
+	/* Set Target Parameters. */
+	mb[0] = MBC_SET_TARGET_PARAMETERS;
+	mb[1] = (uint16_t) (bus ? target | BIT_7 : target);
+	mb[1] <<= 8;
+
+	/*
+	 * Do not enable wide, sync, and ppr for the initial
+	 * INQUIRY run. We enable this later if we determine
+	 * the target actually supports it.
+	 */
+	nv->bus[bus].target[target].parameter.f.
+		auto_request_sense = 1;
+	nv->bus[bus].target[target].parameter.f.
+		stop_queue_on_check = 0;
+
+	if (IS_ISP1x160(ha))
+		nv->bus[bus].target[target].ppr_1x160.
+			flags.enable_ppr = 0;
+
+	/*
+	 * No sync, wide, etc. while probing
+	 */
+	mb[2] = (nv->bus[bus].target[target].parameter.c << 8) &
+		~(TP_SYNC /*| TP_WIDE | TP_PPR*/);
+
+	if (IS_ISP1x160(ha))
+		mb[3] =	nv->bus[bus].target[target].flags.flags1x160.sync_offset << 8;
+	else
+		mb[3] =	nv->bus[bus].target[target].flags.flags1x80.sync_offset << 8;
+	mb[3] |= nv->bus[bus].target[target].sync_period;
+
+	status = qla1280_mailbox_command(ha, BIT_3 | BIT_2 | BIT_1 | BIT_0, &mb[0]);
+
+	/* Save Tag queuing enable flag. */
+	mb[0] = BIT_0 << target;
+	if (nv->bus[bus].target[target].parameter.f.tag_queuing)
+		ha->bus_settings[bus].qtag_enables |= mb[0];
+
+	/* Save Device enable flag. */
+	if (IS_ISP1x160(ha)) {
+		if (nv->bus[bus].target[target].flags.flags1x160.device_enable)
+			ha->bus_settings[bus].device_enables |= mb[0];
+		ha->bus_settings[bus].lun_disables |= 0;
+	} else {
+		if (nv->bus[bus].target[target].flags.flags1x80.device_enable)
+			ha->bus_settings[bus].device_enables |= mb[0];
+		/* Save LUN disable flag. */
+		if (nv->bus[bus].target[target].flags.flags1x80.lun_disable)
+			ha->bus_settings[bus].lun_disables |= mb[0];
+	}
+
+	/* Set Device Queue Parameters. */
+	for (lun = 0; lun < MAX_LUNS; lun++) {
+		mb[0] = MBC_SET_DEVICE_QUEUE;
+		mb[1] = (uint16_t)(bus ? target | BIT_7 : target);
+		mb[1] = mb[1] << 8 | lun;
+		mb[2] = nv->bus[bus].max_queue_depth;
+		mb[3] = nv->bus[bus].target[target].execution_throttle;
+		status |= qla1280_mailbox_command(ha, 0x0f, &mb[0]);
+	}
+
+	return status;
+}
+
+static int
+qla1280_config_bus(struct scsi_qla_host *ha, int bus)
+{
+	struct nvram *nv = &ha->nvram;
+	uint16_t mb[MAILBOX_REGISTER_COUNT];
+	int target, status;
+
+	/* SCSI Reset Disable. */
+	ha->bus_settings[bus].disable_scsi_reset =
+		nv->bus[bus].config_1.scsi_reset_disable;
+
+	/* Initiator ID. */
+	ha->bus_settings[bus].id = nv->bus[bus].config_1.initiator_id;
+	mb[0] = MBC_SET_INITIATOR_ID;
+	mb[1] = bus ? ha->bus_settings[bus].id | BIT_7 :
+		ha->bus_settings[bus].id;
+	status = qla1280_mailbox_command(ha, BIT_1 | BIT_0, &mb[0]);
+
+	/* Reset Delay. */
+	ha->bus_settings[bus].bus_reset_delay =
+		nv->bus[bus].bus_reset_delay;
+
+	/* Command queue depth per device. */
+	ha->bus_settings[bus].hiwat = nv->bus[bus].max_queue_depth - 1;
+
+	/* Set target parameters. */
+	for (target = 0; target < MAX_TARGETS; target++)
+		status |= qla1280_config_target(ha, bus, target);
+
+	return status;
+}
+
+static int
+qla1280_nvram_config(struct scsi_qla_host *ha)
+{
+	struct device_reg *reg = ha->iobase;
+	struct nvram *nv = &ha->nvram;
+	int bus, target, status = 0;
+	uint16_t mb[MAILBOX_REGISTER_COUNT];
+	uint16_t mask;
+
+	ENTER("qla1280_nvram_config");
+
+	if (ha->nvram_valid) {
+		/* Always force AUTO sense for LINUX SCSI */
+		for (bus = 0; bus < MAX_BUSES; bus++)
+			for (target = 0; target < MAX_TARGETS; target++) {
+				nv->bus[bus].target[target].parameter.f.
+					auto_request_sense = 1;
+			}
+	} else {
+		qla1280_set_defaults(ha);
+	}
+
+	qla1280_print_settings(nv);
 
 	/* Disable RISC load of firmware. */
 	ha->flags.disable_risc_code_load =
 		nv->cntr_flags_1.disable_loading_risc_code;
 
-	/* Set ISP hardware DMA burst */
-	mb[0] = nv->isp_config.c;
-	/* Enable DMA arbitration on dual channel controllers */
-	if (ha->ports > 1)
-		mb[0] |= BIT_13;
-	WRT_REG_WORD(&reg->cfg_1, mb[0]);
-
-#if 1	/* Is this safe? */
-	/* Set SCSI termination. */
-	WRT_REG_WORD(&reg->gpio_enable, (BIT_3 + BIT_2 + BIT_1 + BIT_0));
-	mb[0] = nv->termination.c & (BIT_3 + BIT_2 + BIT_1 + BIT_0);
-	WRT_REG_WORD(&reg->gpio_data, mb[0]);
-#endif
+	if (IS_ISP1040(ha)) {
+		uint16_t hwrev, cfg1, cdma_conf, ddma_conf;
+
+		hwrev = RD_REG_WORD(&reg->cfg_0) & ISP_CFG0_HWMSK;
+
+		cfg1 = RD_REG_WORD(&reg->cfg_1);
+		cdma_conf = RD_REG_WORD(&reg->cdma_cfg);
+		ddma_conf = RD_REG_WORD(&reg->ddma_cfg);
+
+		/* Busted fifo, says mjacob. */
+		if (hwrev == ISP_CFG0_1040A)
+			WRT_REG_WORD(&reg->cfg_1, cfg1 | ISP_CFG1_F64);
+		else
+			WRT_REG_WORD(&reg->cfg_1, cfg1 | ISP_CFG1_F64 | ISP_CFG1_BENAB);
+
+		WRT_REG_WORD(&reg->cdma_cfg, cdma_conf | CDMA_CONF_BENAB);
+		WRT_REG_WORD(&reg->ddma_cfg, cdma_conf | DDMA_CONF_BENAB);
+	} else {
+		/* Set ISP hardware DMA burst */
+		mb[0] = nv->isp_config.c;
+		/* Enable DMA arbitration on dual channel controllers */
+		if (ha->ports > 1)
+			mb[0] |= BIT_13;
+		WRT_REG_WORD(&reg->cfg_1, mb[0]);
+
+		/* Set SCSI termination. */
+		WRT_REG_WORD(&reg->gpio_enable, (BIT_3 + BIT_2 + BIT_1 + BIT_0));
+		mb[0] = nv->termination.c & (BIT_3 + BIT_2 + BIT_1 + BIT_0);
+		WRT_REG_WORD(&reg->gpio_data, mb[0]);
+	}
 
 	/* ISP parameter word. */
 	mb[0] = MBC_SET_SYSTEM_PARAMETER;
 	mb[1] = nv->isp_parameter;
 	status |= qla1280_mailbox_command(ha, BIT_1 | BIT_0, &mb[0]);
 
-#if 0
-	/* clock rate - for qla1240 and older, only */
-	mb[0] = MBC_SET_CLOCK_RATE;
-	mb[1] = 0x50;
- 	status |= qla1280_mailbox_command(ha, BIT_1 | BIT_0, &mb[0]);
-#endif
+	if (IS_ISP1x40(ha)) {
+		/* clock rate - for qla1240 and older, only */
+		mb[0] = MBC_SET_CLOCK_RATE;
+		mb[1] = 40;
+	 	status |= qla1280_mailbox_command(ha, BIT_1 | BIT_0, mb);
+	}
+
 	/* Firmware feature word. */
 	mb[0] = MBC_SET_FIRMWARE_FEATURES;
 	mask = BIT_5 | BIT_1 | BIT_0;
@@ -2515,112 +2635,18 @@
 	mb[2] = 2;	/* Command DMA Channel Burst Enable */
 	status |= qla1280_mailbox_command(ha, BIT_2 | BIT_1 | BIT_0, &mb[0]);
 
+	mb[0] = MBC_SET_TAG_AGE_LIMIT;
+	mb[1] = 8;
+	status |= qla1280_mailbox_command(ha, BIT_1 | BIT_0, &mb[0]);
+
 	/* Selection timeout. */
 	mb[0] = MBC_SET_SELECTION_TIMEOUT;
 	mb[1] = nv->bus[0].selection_timeout;
 	mb[2] = nv->bus[1].selection_timeout;
 	status |= qla1280_mailbox_command(ha, BIT_2 | BIT_1 | BIT_0, &mb[0]);
 
-	for (bus = 0; bus < ha->ports; bus++) {
-		/* SCSI Reset Disable. */
-		ha->bus_settings[bus].disable_scsi_reset =
-			nv->bus[bus].config_1.scsi_reset_disable;
-
-		/* Initiator ID. */
-		ha->bus_settings[bus].id = nv->bus[bus].config_1.initiator_id;
-		mb[0] = MBC_SET_INITIATOR_ID;
-		mb[1] = bus ? ha->bus_settings[bus].id | BIT_7 :
-			ha->bus_settings[bus].id;
-		status |= qla1280_mailbox_command(ha, BIT_1 | BIT_0, &mb[0]);
-
-		/* Reset Delay. */
-		ha->bus_settings[bus].bus_reset_delay =
-			nv->bus[bus].bus_reset_delay;
-
-		/* Command queue depth per device. */
-		ha->bus_settings[bus].hiwat = nv->bus[bus].max_queue_depth - 1;
-
-		/* Set target parameters. */
-		for (target = 0; target < MAX_TARGETS; target++) {
-			uint8_t mr = BIT_2 | BIT_1 | BIT_0;
-
-			/* Set Target Parameters. */
-			mb[0] = MBC_SET_TARGET_PARAMETERS;
-			mb[1] = (uint16_t) (bus ? target | BIT_7 : target);
-			mb[1] <<= 8;
-			/*
-			 * Do not enable wide, sync, and ppr for the initial
-			 * INQUIRY run. We enable this later if we determine
-			 * the target actually supports it.
-			 */
-			nv->bus[bus].target[target].parameter.f.
-				auto_request_sense = 1;
-			nv->bus[bus].target[target].parameter.f.
-				stop_queue_on_check = 0;
-
-			if (is1x160)
-				nv->bus[bus].target[target].ppr_1x160.
-					flags.enable_ppr = 0;
-			/*
-			 * No sync, wide, etc. while probing
-			 */
-			mb[2] = (nv->bus[bus].target[target].parameter.c << 8)&
-				~(TP_SYNC /*| TP_WIDE | TP_PPR*/);
-
-			if (is1x160)
-				mb[3] =	nv->bus[bus].target[target].flags.flags1x160.sync_offset << 8;
-			else
-				mb[3] =	nv->bus[bus].target[target].flags.flags1x80.sync_offset << 8;
-			mb[3] |= nv->bus[bus].target[target].sync_period;
-			mr |= BIT_3;
-
-			/*
-			 * We don't want to enable ppr etc. before we have 
-			 * determined that the target actually supports it
-			 */
-#if 0
-			if (is1x160) {
-				mb[2] |= nv->bus[bus].target[target].ppr_1x160.flags.enable_ppr << 5;
-
-				mb[6] =	nv->bus[bus].target[target].ppr_1x160.flags.ppr_options << 8;
-				mb[6] |= nv->bus[bus].target[target].ppr_1x160.flags.ppr_bus_width;
-				mr |= BIT_6;
-			}
-#endif
-
-			status = qla1280_mailbox_command(ha, mr, &mb[0]);
-
-			/* Save Tag queuing enable flag. */
-			mb[0] = BIT_0 << target;
-			if (nv->bus[bus].target[target].parameter.f.tag_queuing)
-				ha->bus_settings[bus].qtag_enables |= mb[0];
-
-			/* Save Device enable flag. */
-			if (is1x160) {
-				if (nv->bus[bus].target[target].flags.flags1x160.device_enable)
-					ha->bus_settings[bus].device_enables |= mb[0];
-				ha->bus_settings[bus].lun_disables |= 0;
-			} else {
-				if (nv->bus[bus].target[target].flags.flags1x80.device_enable)
-					ha->bus_settings[bus].device_enables |= mb[0];
-				/* Save LUN disable flag. */
-				if (nv->bus[bus].target[target].flags.flags1x80.lun_disable)
-				ha->bus_settings[bus].lun_disables |= mb[0];
-			}
-
-
-			/* Set Device Queue Parameters. */
-			for (lun = 0; lun < MAX_LUNS; lun++) {
-				mb[0] = MBC_SET_DEVICE_QUEUE;
-				mb[1] = (uint16_t)(bus ? target | BIT_7 : target);
-				mb[1] = mb[1] << 8 | lun;
-				mb[2] = nv->bus[bus].max_queue_depth;
-				mb[3] = nv->bus[bus].target[target].execution_throttle;
-				status |= qla1280_mailbox_command(ha, 0x0f,
-								  &mb[0]);
-			}
-		}
-	}
+	for (bus = 0; bus < ha->ports; bus++)
+		status |= qla1280_config_bus(ha, bus);
 
 	if (status)
 		dprintk(2, "qla1280_nvram_config: **** FAILED ****\n");
@@ -4231,6 +4257,7 @@
 static int
 qla1280_abort_isp(struct scsi_qla_host *ha)
 {
+	struct device_reg *reg = ha->iobase;
 	struct srb *sp;
 	int status = 0;
 	int cnt;
@@ -4238,69 +4265,53 @@
 
 	ENTER("qla1280_abort_isp");
 
-	if (!ha->flags.abort_isp_active && ha->flags.online) {
-		struct device_reg *reg = ha->iobase;
-		ha->flags.abort_isp_active = 1;
+	if (ha->flags.abort_isp_active || !ha->flags.online)
+		goto out;
+	
+	ha->flags.abort_isp_active = 1;
 
-		/* Disable ISP interrupts. */
-		qla1280_disable_intrs(ha);
-		WRT_REG_WORD(&reg->host_cmd, HC_PAUSE_RISC);
-		RD_REG_WORD(&reg->id_l);
+	/* Disable ISP interrupts. */
+	qla1280_disable_intrs(ha);
+	WRT_REG_WORD(&reg->host_cmd, HC_PAUSE_RISC);
+	RD_REG_WORD(&reg->id_l);
 
-		printk(KERN_INFO "scsi(%li): dequeuing outstanding commands\n",
-		       ha->host_no);
-		/* Dequeue all commands in outstanding command list. */
-		for (cnt = 0; cnt < MAX_OUTSTANDING_COMMANDS; cnt++) {
-			struct scsi_cmnd *cmd;
-			sp = ha->outstanding_cmds[cnt];
-			if (sp) {
+	printk(KERN_INFO "scsi(%li): dequeuing outstanding commands\n",
+	       ha->host_no);
+	/* Dequeue all commands in outstanding command list. */
+	for (cnt = 0; cnt < MAX_OUTSTANDING_COMMANDS; cnt++) {
+		struct scsi_cmnd *cmd;
+		sp = ha->outstanding_cmds[cnt];
+		if (sp) {
 
-				cmd = sp->cmd;
-				CMD_RESULT(cmd) = DID_RESET << 16;
+			cmd = sp->cmd;
+			CMD_RESULT(cmd) = DID_RESET << 16;
 
-				sp->cmd = NULL;
-				ha->outstanding_cmds[cnt] = NULL;
+			sp->cmd = NULL;
+			ha->outstanding_cmds[cnt] = NULL;
 
-				(*cmd->scsi_done)(cmd);
+			(*cmd->scsi_done)(cmd);
 
-				sp->flags = 0;
-			}
+			sp->flags = 0;
 		}
+	}
 
-		/* If firmware needs to be loaded */
-		if (qla1280_isp_firmware (ha)) {
-			if (!(status = qla1280_chip_diag(ha)))
-				status = qla1280_setup_chip(ha);
-		}
+	status = qla1280_load_firmware(ha);
+	if (status)
+		goto out;
 
-		if (!status) {
-			/* Setup adapter based on NVRAM parameters. */
-			qla1280_nvram_config (ha);
-
-			if (!(status = qla1280_init_rings(ha))) {
-				/* Issue SCSI reset. */
-				for (bus = 0; bus < ha->ports; bus++) {
-					qla1280_bus_reset(ha, bus);
-				}
-				/*
-				 * qla1280_bus_reset() will do the marker
-				 * dance - no reason to repeat here!
-				 */
-#if  0
-				/* Issue marker command. */
-				ha->flags.reset_marker = 0;
-				for (bus = 0; bus < ha->ports; bus++) {
-					ha->bus_settings[bus].
-						reset_marker = 0;
-					qla1280_marker(ha, bus, 0, 0,
-						       MK_SYNC_ALL);
-				}
-#endif
-				ha->flags.abort_isp_active = 0;
-			}
-		}
-	}
+	/* Setup adapter based on NVRAM parameters. */
+	qla1280_nvram_config (ha);
 
+	status = qla1280_init_rings(ha);
+	if (status)
+		goto out;
+		
+	/* Issue SCSI reset. */
+	for (bus = 0; bus < ha->ports; bus++)
+		qla1280_bus_reset(ha, bus);
+		
+	ha->flags.abort_isp_active = 0;
+ out:
 	if (status) {
 		printk(KERN_WARNING
 		       "qla1280: ISP error recovery failed, board disabled");
@@ -4936,6 +4947,7 @@
 MODULE_AUTHOR("Qlogic & Jes Sorensen");
 MODULE_DESCRIPTION("Qlogic ISP SCSI (qla1x80/qla1x160) driver");
 MODULE_LICENSE("GPL");
+MODULE_VERSION(QLA1280_VERSION);
 
 /*
  * Overrides for Emacs so that we almost follow Linus's tabbing style.
diff -Nru a/drivers/scsi/qla1280.h b/drivers/scsi/qla1280.h
--- a/drivers/scsi/qla1280.h	2004-10-18 14:57:04 -07:00
+++ b/drivers/scsi/qla1280.h	2004-10-18 14:57:04 -07:00
@@ -62,6 +62,7 @@
 #define WRT_REG_WORD(addr, data)	writew(data, addr)
 #else				/* MEMORY_MAPPED_IO */
 #define RD_REG_WORD(addr)		inw((unsigned long)addr)
+#define RD_REG_WORD_dmasync(addr)	RD_REG_WORD(addr)
 #define WRT_REG_WORD(addr, data)	outw(data, (unsigned long)addr)
 #endif				/* MEMORY_MAPPED_IO */
 
@@ -126,7 +127,20 @@
 	uint16_t id_l;		/* ID low */
 	uint16_t id_h;		/* ID high */
 	uint16_t cfg_0;		/* Configuration 0 */
+#define ISP_CFG0_HWMSK   0x000f	/* Hardware revision mask */
+#define ISP_CFG0_1020    BIT_0	/* ISP1020 */
+#define ISP_CFG0_1020A	 BIT_1	/* ISP1020A */
+#define ISP_CFG0_1040	 BIT_2	/* ISP1040 */
+#define ISP_CFG0_1040A	 BIT_3	/* ISP1040A */
+#define ISP_CFG0_1040B	 BIT_4	/* ISP1040B */
+#define ISP_CFG0_1040C	 BIT_5	/* ISP1040C */
 	uint16_t cfg_1;		/* Configuration 1 */
+#define ISP_CFG1_F128    BIT_6  /* 128-byte FIFO threshold */
+#define ISP_CFG1_F64     BIT_4|BIT_5 /* 128-byte FIFO threshold */
+#define ISP_CFG1_F32     BIT_5  /* 128-byte FIFO threshold */
+#define ISP_CFG1_F16     BIT_4  /* 128-byte FIFO threshold */
+#define ISP_CFG1_BENAB   BIT_2  /* Global Bus burst enable */
+#define ISP_CFG1_SXP     BIT_0  /* SXP register select */
 	uint16_t ictrl;		/* Interface control */
 #define ISP_RESET        BIT_0	/* ISP soft reset */
 #define ISP_EN_INT       BIT_1	/* ISP enable interrupts. */
@@ -147,7 +161,42 @@
 	uint16_t flash_data;	/* Flash BIOS data */
 	uint16_t flash_address;	/* Flash BIOS address */
 
-	uint16_t unused_1[0x2e];	/* 0x14-0x6f Gap */
+	uint16_t unused_1[0x06];
+	
+	/* cdma_* and ddma_* are 1040 only */
+	uint16_t cdma_cfg;
+#define CDMA_CONF_SENAB  BIT_3	/* SXP to DMA Data enable */
+#define CDMA_CONF_RIRQ   BIT_2	/* RISC interrupt enable */
+#define CDMA_CONF_BENAB  BIT_1	/* Bus burst enable */
+#define CDMA_CONF_DIR    BIT_0	/* DMA direction (0=fifo->host 1=host->fifo) */
+	uint16_t cdma_ctrl; 
+	uint16_t cdma_status;   
+	uint16_t cdma_fifo_status;
+	uint16_t cdma_count;
+	uint16_t cdma_reserved;
+	uint16_t cdma_address_count_0;
+	uint16_t cdma_address_count_1;
+	uint16_t cdma_address_count_2;
+	uint16_t cdma_address_count_3;
+
+	uint16_t unused_2[0x06];
+
+	uint16_t ddma_cfg;
+#define DDMA_CONF_SENAB  BIT_3	/* SXP to DMA Data enable */
+#define DDMA_CONF_RIRQ   BIT_2	/* RISC interrupt enable */
+#define DDMA_CONF_BENAB  BIT_1	/* Bus burst enable */
+#define DDMA_CONF_DIR    BIT_0	/* DMA direction (0=fifo->host 1=host->fifo) */
+	uint16_t ddma_ctrl;
+	uint16_t ddma_status; 
+	uint16_t ddma_fifo_status;
+	uint16_t ddma_xfer_count_low;
+	uint16_t ddma_xfer_count_high;
+	uint16_t ddma_addr_count_0;
+	uint16_t ddma_addr_count_1;
+	uint16_t ddma_addr_count_2;
+	uint16_t ddma_addr_count_3; 
+
+	uint16_t unused_3[0x0e];
 
 	uint16_t mailbox0;	/* Mailbox 0 */
 	uint16_t mailbox1;	/* Mailbox 1 */
@@ -158,18 +207,18 @@
 	uint16_t mailbox6;	/* Mailbox 6 */
 	uint16_t mailbox7;	/* Mailbox 7 */
 
-	uint16_t unused_2[0x20];/* 0x80-0xbf Gap */
+	uint16_t unused_4[0x20];/* 0x80-0xbf Gap */
 
 	uint16_t host_cmd;	/* Host command and control */
 #define HOST_INT      BIT_7	/* host interrupt bit */
 #define BIOS_ENABLE   BIT_0
 
-	uint16_t unused_6[0x5];	/* 0xc2-0xcb Gap */
+	uint16_t unused_5[0x5];	/* 0xc2-0xcb Gap */
 
 	uint16_t gpio_data;
 	uint16_t gpio_enable;
 
-	uint16_t unused_7[0x11];	/* d0-f0 */
+	uint16_t unused_6[0x11];	/* d0-f0 */
 	uint16_t scsiControlPins;	/* f2 */
 };
 
diff -Nru a/drivers/scsi/qla2xxx/ql2100.c b/drivers/scsi/qla2xxx/ql2100.c
--- a/drivers/scsi/qla2xxx/ql2100.c	2004-10-18 14:56:28 -07:00
+++ b/drivers/scsi/qla2xxx/ql2100.c	2004-10-18 14:56:28 -07:00
@@ -89,3 +89,4 @@
 MODULE_AUTHOR("QLogic Corporation");
 MODULE_DESCRIPTION("QLogic ISP21xx FC-SCSI Host Bus Adapter driver");
 MODULE_LICENSE("GPL");
+MODULE_VERSION(QLA2XXX_VERSION);
diff -Nru a/drivers/scsi/qla2xxx/ql2200.c b/drivers/scsi/qla2xxx/ql2200.c
--- a/drivers/scsi/qla2xxx/ql2200.c	2004-10-18 14:55:46 -07:00
+++ b/drivers/scsi/qla2xxx/ql2200.c	2004-10-18 14:55:46 -07:00
@@ -89,3 +89,4 @@
 MODULE_AUTHOR("QLogic Corporation");
 MODULE_DESCRIPTION("QLogic ISP22xx FC-SCSI Host Bus Adapter driver");
 MODULE_LICENSE("GPL");
+MODULE_VERSION(QLA2XXX_VERSION);
diff -Nru a/drivers/scsi/qla2xxx/ql2300.c b/drivers/scsi/qla2xxx/ql2300.c
--- a/drivers/scsi/qla2xxx/ql2300.c	2004-10-18 14:57:04 -07:00
+++ b/drivers/scsi/qla2xxx/ql2300.c	2004-10-18 14:57:04 -07:00
@@ -100,3 +100,4 @@
 MODULE_AUTHOR("QLogic Corporation");
 MODULE_DESCRIPTION("QLogic ISP2300 FC-SCSI Host Bus Adapter driver");
 MODULE_LICENSE("GPL");
+MODULE_VERSION(QLA2XXX_VERSION);
diff -Nru a/drivers/scsi/qla2xxx/ql2322.c b/drivers/scsi/qla2xxx/ql2322.c
--- a/drivers/scsi/qla2xxx/ql2322.c	2004-10-18 14:56:27 -07:00
+++ b/drivers/scsi/qla2xxx/ql2322.c	2004-10-18 14:56:27 -07:00
@@ -105,3 +105,4 @@
 MODULE_AUTHOR("QLogic Corporation");
 MODULE_DESCRIPTION("QLogic ISP2322 FC-SCSI Host Bus Adapter driver");
 MODULE_LICENSE("GPL");
+MODULE_VERSION(QLA2XXX_VERSION);
diff -Nru a/drivers/scsi/qla2xxx/ql6312.c b/drivers/scsi/qla2xxx/ql6312.c
--- a/drivers/scsi/qla2xxx/ql6312.c	2004-10-18 14:57:04 -07:00
+++ b/drivers/scsi/qla2xxx/ql6312.c	2004-10-18 14:57:04 -07:00
@@ -87,3 +87,4 @@
 MODULE_AUTHOR("QLogic Corporation");
 MODULE_DESCRIPTION("QLogic ISP6312 FC-SCSI Host Bus Adapter driver");
 MODULE_LICENSE("GPL");
+MODULE_VERSION(QLA2XXX_VERSION);
diff -Nru a/drivers/scsi/qla2xxx/ql6322.c b/drivers/scsi/qla2xxx/ql6322.c
--- a/drivers/scsi/qla2xxx/ql6322.c	2004-10-18 14:57:03 -07:00
+++ b/drivers/scsi/qla2xxx/ql6322.c	2004-10-18 14:57:03 -07:00
@@ -105,3 +105,4 @@
 MODULE_AUTHOR("QLogic Corporation");
 MODULE_DESCRIPTION("QLogic ISP6322 FC-SCSI Host Bus Adapter driver");
 MODULE_LICENSE("GPL");
+MODULE_VERSION(QLA2XXX_VERSION);
diff -Nru a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c
--- a/drivers/scsi/qla2xxx/qla_init.c	2004-10-18 14:57:03 -07:00
+++ b/drivers/scsi/qla2xxx/qla_init.c	2004-10-18 14:57:03 -07:00
@@ -783,7 +783,6 @@
 static void
 qla2x00_update_fw_options(scsi_qla_host_t *ha)
 {
-	/* Setup seriallink options */
 	uint16_t swing, emphasis;
 
 	memset(ha->fw_options, 0, sizeof(ha->fw_options));
@@ -807,7 +806,6 @@
 	emphasis = ha->fw_seriallink_options[0] & (BIT_4 | BIT_3);
 	emphasis >>= 3;
 	ha->fw_options[10] = (emphasis << 14) | (swing << 8) | 0x3;
-
 	/*  2G settings */
 	swing = ha->fw_seriallink_options[0] & (BIT_7 | BIT_6 | BIT_5);
 	swing >>= 5;
@@ -818,7 +816,7 @@
 	/*  Return command IOCBs without waiting for an ABTS to complete. */
 	ha->fw_options[3] |= BIT_13;
 
-	/* Update Serial Link options. */
+	/* Update firmware options. */
 	qla2x00_set_fw_options(ha, ha->fw_options);
 }
 
@@ -843,7 +841,7 @@
 
 	/* Clear outstanding commands array. */
 	for (cnt = 0; cnt < MAX_OUTSTANDING_COMMANDS; cnt++)
-		ha->outstanding_cmds[cnt] = 0;
+		ha->outstanding_cmds[cnt] = NULL;
 
 	ha->current_outstanding_cmd = 0;
 
@@ -869,15 +867,15 @@
 
 	spin_unlock_irqrestore(&ha->hardware_lock, flags);
 
+	/* Update any ISP specific firmware options before initialization. */
+	qla2x00_update_fw_options(ha);
+
 	DEBUG(printk("scsi(%ld): Issue init firmware.\n", ha->host_no));
 	rval = qla2x00_init_firmware(ha, sizeof(init_cb_t));
 	if (rval) {
 		DEBUG2_3(printk("scsi(%ld): Init firmware **** FAILED ****.\n",
 		    ha->host_no));
 	} else {
-		/* Update any ISP specific firmware options. */
-		qla2x00_update_fw_options(ha);
-
 		DEBUG3(printk("scsi(%ld): Init firmware -- success.\n",
 		    ha->host_no));
 	}
@@ -4133,7 +4131,7 @@
 		for (cnt = 1; cnt < MAX_OUTSTANDING_COMMANDS; cnt++) {
 			sp = ha->outstanding_cmds[cnt];
 			if (sp) {
-				ha->outstanding_cmds[cnt] = 0;
+				ha->outstanding_cmds[cnt] = NULL;
 				if (ha->actthreads)
 					ha->actthreads--;
 				sp->lun_queue->out_cnt--;
diff -Nru a/drivers/scsi/qla2xxx/qla_iocb.c b/drivers/scsi/qla2xxx/qla_iocb.c
--- a/drivers/scsi/qla2xxx/qla_iocb.c	2004-10-18 14:56:33 -07:00
+++ b/drivers/scsi/qla2xxx/qla_iocb.c	2004-10-18 14:56:33 -07:00
@@ -22,6 +22,8 @@
 #include <linux/blkdev.h>
 #include <linux/delay.h>
 
+#include <scsi/scsi_tcq.h>
+
 static inline uint16_t qla2x00_get_cmd_direction(struct scsi_cmnd *cmd);
 static inline cont_entry_t *qla2x00_prep_cont_type0_iocb(scsi_qla_host_t *);
 static inline cont_a64_entry_t *qla2x00_prep_cont_type1_iocb(scsi_qla_host_t *);
@@ -337,6 +339,7 @@
 	uint16_t	req_cnt;
 	uint16_t	tot_dsds;
 	device_reg_t	*reg;
+	char		tag[2];
 
 	/* Setup device pointers. */
 	ret = 0;
@@ -415,14 +418,17 @@
 	cmd_pkt->lun = cpu_to_le16(fclun->lun);
 
 	/* Update tagged queuing modifier */
-	cmd_pkt->control_flags = __constant_cpu_to_le16(CF_SIMPLE_TAG);
-	if (cmd->device->tagged_supported) {
-		switch (cmd->tag) {
-		case HEAD_OF_QUEUE_TAG:
+	if (scsi_populate_tag_msg(cmd, tag)) {
+		switch (tag[0]) {
+		case MSG_SIMPLE_TAG:
+			cmd_pkt->control_flags =
+			    __constant_cpu_to_le16(CF_SIMPLE_TAG);
+			break;
+		case MSG_HEAD_TAG:
 			cmd_pkt->control_flags =
 			    __constant_cpu_to_le16(CF_HEAD_TAG);
 			break;
-		case ORDERED_QUEUE_TAG:
+		case MSG_ORDERED_TAG:
 			cmd_pkt->control_flags =
 			    __constant_cpu_to_le16(CF_ORDERED_TAG);
 			break;
diff -Nru a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c
--- a/drivers/scsi/qla2xxx/qla_os.c	2004-10-18 14:57:04 -07:00
+++ b/drivers/scsi/qla2xxx/qla_os.c	2004-10-18 14:57:04 -07:00
@@ -1663,7 +1663,7 @@
 		goto out;
 
 	/* Waiting for our command in done_queue to be returned to OS.*/
-	if (qla2x00_eh_wait_for_pending_commands(ha))
+	if (!qla2x00_eh_wait_for_pending_commands(ha))
 		rval = FAILED;
 
  out:
@@ -1784,7 +1784,7 @@
 
 		ql2xmaxqdepth = queue_depth;
 
-		scsi_adjust_queue_depth(sdev, MSG_ORDERED_TAG, queue_depth);
+		scsi_activate_tcq(sdev, queue_depth);
 
 		qla_printk(KERN_INFO, ha,
 		    "scsi(%d:%d:%d:%d): Enabled tagged queuing, queue "
@@ -3590,7 +3590,7 @@
 {
 	srb_t *sp;
 
-	sp = mempool_alloc(ha->srb_mempool, GFP_KERNEL);
+	sp = mempool_alloc(ha->srb_mempool, GFP_ATOMIC);
 	if (sp)
 		atomic_set(&sp->ref_count, 1);
 	return (sp);
@@ -4517,3 +4517,4 @@
 MODULE_AUTHOR("QLogic Corporation");
 MODULE_DESCRIPTION("QLogic Fibre Channel HBA Driver");
 MODULE_LICENSE("GPL");
+MODULE_VERSION(QLA2XXX_VERSION);
diff -Nru a/drivers/scsi/qla2xxx/qla_version.h b/drivers/scsi/qla2xxx/qla_version.h
--- a/drivers/scsi/qla2xxx/qla_version.h	2004-10-18 14:56:29 -07:00
+++ b/drivers/scsi/qla2xxx/qla_version.h	2004-10-18 14:56:29 -07:00
@@ -19,9 +19,9 @@
 /*
  * Driver version 
  */
-#define QLA2XXX_VERSION      "8.00.00b14-k"
+#define QLA2XXX_VERSION      "8.00.00b15-k"
 
 #define QLA_DRIVER_MAJOR_VER	8
 #define QLA_DRIVER_MINOR_VER	0
 #define QLA_DRIVER_PATCH_VER	0
-#define QLA_DRIVER_BETA_VER	14
+#define QLA_DRIVER_BETA_VER	15
diff -Nru a/drivers/scsi/qlogicpti.c b/drivers/scsi/qlogicpti.c
--- a/drivers/scsi/qlogicpti.c	2004-10-18 14:56:48 -07:00
+++ b/drivers/scsi/qlogicpti.c	2004-10-18 14:56:48 -07:00
@@ -987,7 +987,7 @@
 	static char buf[80];
 	struct qlogicpti *qpti = (struct qlogicpti *) host->hostdata;
 
-	sprintf(buf, "PTI Qlogic,ISP SBUS SCSI irq %s regs at %lx",
+	sprintf(buf, "PTI Qlogic,ISP SBUS SCSI irq %s regs at %p",
 		__irq_itoa(qpti->qhost->irq), qpti->qregs);
 	return buf;
 }
diff -Nru a/drivers/scsi/qlogicpti.h b/drivers/scsi/qlogicpti.h
--- a/drivers/scsi/qlogicpti.h	2004-10-18 14:55:55 -07:00
+++ b/drivers/scsi/qlogicpti.h	2004-10-18 14:55:55 -07:00
@@ -335,7 +335,7 @@
 /* Software state for the driver. */
 struct qlogicpti {
 	/* These are the hot elements in the cache, so they come first. */
-	unsigned long             qregs;                /* Adapter registers          */
+	void __iomem             *qregs;                /* Adapter registers          */
 	struct pti_queue_entry   *res_cpu;              /* Ptr to RESPONSE bufs (CPU) */
 	struct pti_queue_entry   *req_cpu;              /* Ptr to REQUEST bufs (CPU)  */
 
@@ -370,7 +370,7 @@
 	struct	host_param        host_param;
 	struct	dev_param         dev_param[MAX_TARGETS];
 
-	unsigned long             sreg;
+	void __iomem              *sreg;
 #define SREG_TPOWER               0x80   /* State of termpwr           */
 #define SREG_FUSE                 0x40   /* State of on board fuse     */
 #define SREG_PDISAB               0x20   /* Disable state for power on */
diff -Nru a/drivers/scsi/sata_nv.c b/drivers/scsi/sata_nv.c
--- a/drivers/scsi/sata_nv.c	2004-10-18 14:56:17 -07:00
+++ b/drivers/scsi/sata_nv.c	2004-10-18 14:56:17 -07:00
@@ -20,6 +20,10 @@
  *  If you do not delete the provisions above, a recipient may use your
  *  version of this file under either the OSL or the GPL.
  *
+ *  0.03
+ *     - Fixed a bug where the hotplug handlers for non-CK804/MCP04 were using
+ *       mmio_base, which is only set for the CK804/MCP04 case.
+ *
  *  0.02
  *     - Added support for CK804 SATA controller.
  *
@@ -40,13 +44,12 @@
 #include <linux/libata.h>
 
 #define DRV_NAME			"sata_nv"
-#define DRV_VERSION			"0.02"
+#define DRV_VERSION			"0.03"
 
 #define NV_PORTS			2
 #define NV_PIO_MASK			0x1f
+#define NV_MWDMA_MASK			0x07
 #define NV_UDMA_MASK			0x7f
-#define NV_PORT0_BMDMA_REG_OFFSET	0x00
-#define NV_PORT1_BMDMA_REG_OFFSET	0x08
 #define NV_PORT0_SCR_REG_OFFSET		0x00
 #define NV_PORT1_SCR_REG_OFFSET		0x40
 
@@ -177,11 +180,12 @@
 static Scsi_Host_Template nv_sht = {
 	.module			= THIS_MODULE,
 	.name			= DRV_NAME,
+	.ioctl			= ata_scsi_ioctl,
 	.queuecommand		= ata_scsi_queuecmd,
 	.eh_strategy_handler	= ata_scsi_error,
 	.can_queue		= ATA_DEF_QUEUE,
 	.this_id		= ATA_SHT_THIS_ID,
-	.sg_tablesize		= ATA_MAX_PRD,
+	.sg_tablesize		= LIBATA_MAX_PRD,
 	.max_sectors		= ATA_MAX_SECTORS,
 	.cmd_per_lun		= ATA_SHT_CMD_PER_LUN,
 	.emulated		= ATA_SHT_EMULATED,
@@ -194,13 +198,14 @@
 
 static struct ata_port_operations nv_ops = {
 	.port_disable		= ata_port_disable,
-	.tf_load		= ata_tf_load_pio,
-	.tf_read		= ata_tf_read_pio,
-	.exec_command		= ata_exec_command_pio,
-	.check_status		= ata_check_status_pio,
+	.tf_load		= ata_tf_load,
+	.tf_read		= ata_tf_read,
+	.exec_command		= ata_exec_command,
+	.check_status		= ata_check_status,
+	.dev_select		= ata_std_dev_select,
 	.phy_reset		= sata_phy_reset,
-	.bmdma_setup		= ata_bmdma_setup_pio,
-	.bmdma_start		= ata_bmdma_start_pio,
+	.bmdma_setup		= ata_bmdma_setup,
+	.bmdma_start		= ata_bmdma_start,
 	.qc_prep		= ata_qc_prep,
 	.qc_issue		= ata_qc_issue_prot,
 	.eng_timeout		= ata_eng_timeout,
@@ -213,6 +218,18 @@
 	.host_stop		= nv_host_stop,
 };
 
+static struct ata_port_info nv_port_info = {
+	.sht		= &nv_sht,
+	.host_flags	= ATA_FLAG_SATA |
+			  ATA_FLAG_SATA_RESET |
+			  ATA_FLAG_SRST |
+			  ATA_FLAG_NO_LEGACY,
+	.pio_mask	= NV_PIO_MASK,
+	.mwdma_mask	= NV_MWDMA_MASK,
+	.udma_mask	= NV_UDMA_MASK,
+	.port_ops	= &nv_ops,
+};
+
 MODULE_AUTHOR("NVIDIA");
 MODULE_DESCRIPTION("low-level driver for NVIDIA nForce SATA controller");
 MODULE_LICENSE("GPL");
@@ -293,6 +310,7 @@
 {
 	static int printed_version = 0;
 	struct nv_host *host;
+	struct ata_port_info *ppi;
 	struct ata_probe_ent *probe_ent = NULL;
 	int rc;
 
@@ -314,7 +332,8 @@
 	if (rc)
 		goto err_out_regions;
 
-	probe_ent = kmalloc(sizeof(*probe_ent), GFP_KERNEL);
+	ppi = &nv_port_info;
+	probe_ent = ata_pci_init_native_mode(pdev, &ppi);
 	if (!probe_ent) {
 		rc = -ENOMEM;
 		goto err_out_regions;
@@ -328,39 +347,6 @@
 
 	host->host_desc = &nv_device_tbl[ent->driver_data];
 
-	memset(probe_ent, 0, sizeof(*probe_ent));
-	INIT_LIST_HEAD(&probe_ent->node);
-
-	probe_ent->pdev = pdev;
-	probe_ent->sht = &nv_sht;
-	probe_ent->host_flags = ATA_FLAG_SATA |
-				ATA_FLAG_SATA_RESET |
-				ATA_FLAG_SRST |
-				ATA_FLAG_NO_LEGACY;
-
-	probe_ent->port_ops = &nv_ops;
-	probe_ent->n_ports = NV_PORTS;
-	probe_ent->irq = pdev->irq;
-	probe_ent->irq_flags = SA_SHIRQ;
-	probe_ent->pio_mask = NV_PIO_MASK;
-	probe_ent->udma_mask = NV_UDMA_MASK;
-
-	probe_ent->port[0].cmd_addr = pci_resource_start(pdev, 0);
-	ata_std_ports(&probe_ent->port[0]);
-	probe_ent->port[0].altstatus_addr =
-	probe_ent->port[0].ctl_addr =
-		pci_resource_start(pdev, 1) | ATA_PCI_CTL_OFS;
-	probe_ent->port[0].bmdma_addr =
-		pci_resource_start(pdev, 4) | NV_PORT0_BMDMA_REG_OFFSET;
-
-	probe_ent->port[1].cmd_addr = pci_resource_start(pdev, 2);
-	ata_std_ports(&probe_ent->port[1]);
-	probe_ent->port[1].altstatus_addr =
-	probe_ent->port[1].ctl_addr =
-		pci_resource_start(pdev, 3) | ATA_PCI_CTL_OFS;
-	probe_ent->port[1].bmdma_addr =
-		pci_resource_start(pdev, 4) | NV_PORT1_BMDMA_REG_OFFSET;
-
 	probe_ent->private_data = host;
 
 	if (host->host_desc->host_flags & NV_HOST_FLAGS_SCR_MMIO) {
@@ -369,7 +355,7 @@
 		probe_ent->mmio_base = ioremap(pci_resource_start(pdev, 5),
 				pci_resource_len(pdev, 5));
 		if (probe_ent->mmio_base == NULL)
-			goto err_out_free_ent;
+			goto err_out_iounmap;
 
 		base = (unsigned long)probe_ent->mmio_base;
 
@@ -393,12 +379,16 @@
 
 	rc = ata_device_add(probe_ent);
 	if (rc != NV_PORTS)
-		goto err_out_free_ent;
+		goto err_out_iounmap;
 
 	kfree(probe_ent);
 
 	return 0;
 
+err_out_iounmap:
+	if (host->host_desc->host_flags & NV_HOST_FLAGS_SCR_MMIO)
+		iounmap(probe_ent->mmio_base);
+
 err_out_free_ent:
 	kfree(probe_ent);
 
@@ -415,33 +405,33 @@
 	u8 intr_mask;
 
 	outb(NV_INT_STATUS_HOTPLUG,
-		(unsigned long)probe_ent->mmio_base + NV_INT_STATUS);
+		probe_ent->port[0].scr_addr + NV_INT_STATUS);
 
-	intr_mask = inb((unsigned long)probe_ent->mmio_base + NV_INT_ENABLE);
+	intr_mask = inb(probe_ent->port[0].scr_addr + NV_INT_ENABLE);
 	intr_mask |= NV_INT_ENABLE_HOTPLUG;
 
-	outb(intr_mask, (unsigned long)probe_ent->mmio_base + NV_INT_ENABLE);
+	outb(intr_mask, probe_ent->port[0].scr_addr + NV_INT_ENABLE);
 }
 
 static void nv_disable_hotplug(struct ata_host_set *host_set)
 {
 	u8 intr_mask;
 
-	intr_mask = inb((unsigned long)host_set->mmio_base + NV_INT_ENABLE);
+	intr_mask = inb(host_set->ports[0]->ioaddr.scr_addr + NV_INT_ENABLE);
 
 	intr_mask &= ~(NV_INT_ENABLE_HOTPLUG);
 
-	outb(intr_mask, (unsigned long)host_set->mmio_base + NV_INT_ENABLE);
+	outb(intr_mask, host_set->ports[0]->ioaddr.scr_addr + NV_INT_ENABLE);
 }
 
 static void nv_check_hotplug(struct ata_host_set *host_set)
 {
 	u8 intr_status;
 
-	intr_status = inb((unsigned long)host_set->mmio_base + NV_INT_STATUS);
+	intr_status = inb(host_set->ports[0]->ioaddr.scr_addr + NV_INT_STATUS);
 
 	// Clear interrupt status.
-	outb(0xff, (unsigned long)host_set->mmio_base + NV_INT_STATUS);
+	outb(0xff, host_set->ports[0]->ioaddr.scr_addr + NV_INT_STATUS);
 
 	if (intr_status & NV_INT_STATUS_HOTPLUG) {
 		if (intr_status & NV_INT_STATUS_PDEV_ADDED)
diff -Nru a/drivers/scsi/sata_promise.c b/drivers/scsi/sata_promise.c
--- a/drivers/scsi/sata_promise.c	2004-10-18 14:56:48 -07:00
+++ b/drivers/scsi/sata_promise.c	2004-10-18 14:56:48 -07:00
@@ -74,7 +74,6 @@
 static u32 pdc_sata_scr_read (struct ata_port *ap, unsigned int sc_reg);
 static void pdc_sata_scr_write (struct ata_port *ap, unsigned int sc_reg, u32 val);
 static int pdc_sata_init_one (struct pci_dev *pdev, const struct pci_device_id *ent);
-static void pdc_dma_start(struct ata_queued_cmd *qc);
 static irqreturn_t pdc_interrupt (int irq, void *dev_instance, struct pt_regs *regs);
 static void pdc_eng_timeout(struct ata_port *ap);
 static int pdc_port_start(struct ata_port *ap);
@@ -83,14 +82,13 @@
 static void pdc_qc_prep(struct ata_queued_cmd *qc);
 static void pdc_tf_load_mmio(struct ata_port *ap, struct ata_taskfile *tf);
 static void pdc_exec_command_mmio(struct ata_port *ap, struct ata_taskfile *tf);
-static inline void pdc_dma_complete (struct ata_port *ap,
-                                     struct ata_queued_cmd *qc, int have_err);
 static void pdc_irq_clear(struct ata_port *ap);
 static int pdc_qc_issue_prot(struct ata_queued_cmd *qc);
 
 static Scsi_Host_Template pdc_sata_sht = {
 	.module			= THIS_MODULE,
 	.name			= DRV_NAME,
+	.ioctl			= ata_scsi_ioctl,
 	.queuecommand		= ata_scsi_queuecmd,
 	.eh_strategy_handler	= ata_scsi_error,
 	.can_queue		= ATA_DEF_QUEUE,
@@ -109,9 +107,10 @@
 static struct ata_port_operations pdc_sata_ops = {
 	.port_disable		= ata_port_disable,
 	.tf_load		= pdc_tf_load_mmio,
-	.tf_read		= ata_tf_read_mmio,
-	.check_status		= ata_check_status_mmio,
+	.tf_read		= ata_tf_read,
+	.check_status		= ata_check_status,
 	.exec_command		= pdc_exec_command_mmio,
+	.dev_select		= ata_std_dev_select,
 	.phy_reset		= pdc_phy_reset,
 	.qc_prep		= pdc_qc_prep,
 	.qc_issue		= pdc_qc_issue_prot,
@@ -130,7 +129,8 @@
 		.sht		= &pdc_sata_sht,
 		.host_flags	= ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY |
 				  ATA_FLAG_SRST | ATA_FLAG_MMIO,
-		.pio_mask	= 0x03, /* pio3-4 */
+		.pio_mask	= 0x1f, /* pio0-4 */
+		.mwdma_mask	= 0x07, /* mwdma0-2 */
 		.udma_mask	= 0x7f, /* udma0-6 ; FIXME */
 		.port_ops	= &pdc_sata_ops,
 	},
@@ -140,7 +140,8 @@
 		.sht		= &pdc_sata_sht,
 		.host_flags	= ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY |
 				  ATA_FLAG_SRST | ATA_FLAG_MMIO,
-		.pio_mask	= 0x03, /* pio3-4 */
+		.pio_mask	= 0x1f, /* pio0-4 */
+		.mwdma_mask	= 0x07, /* mwdma0-2 */
 		.udma_mask	= 0x7f, /* udma0-6 ; FIXME */
 		.port_ops	= &pdc_sata_ops,
 	},
@@ -269,26 +270,26 @@
 
 	VPRINTK("ENTER\n");
 
-	ata_qc_prep(qc);
-
-	i = pdc_pkt_header(&qc->tf, qc->ap->prd_dma,  qc->dev->devno, pp->pkt);
+	switch (qc->tf.protocol) {
+	case ATA_PROT_DMA:
+		ata_qc_prep(qc);
+		/* fall through */
 
-	if (qc->tf.flags & ATA_TFLAG_LBA48)
-		i = pdc_prep_lba48(&qc->tf, pp->pkt, i);
-	else
-		i = pdc_prep_lba28(&qc->tf, pp->pkt, i);
+	case ATA_PROT_NODATA:
+		i = pdc_pkt_header(&qc->tf, qc->ap->prd_dma,
+				   qc->dev->devno, pp->pkt);
 
-	pdc_pkt_footer(&qc->tf, pp->pkt, i);
-}
+		if (qc->tf.flags & ATA_TFLAG_LBA48)
+			i = pdc_prep_lba48(&qc->tf, pp->pkt, i);
+		else
+			i = pdc_prep_lba28(&qc->tf, pp->pkt, i);
 
-static inline void pdc_dma_complete (struct ata_port *ap,
-                                     struct ata_queued_cmd *qc,
-				     int have_err)
-{
-	u8 err_bit = have_err ? ATA_ERR : 0;
+		pdc_pkt_footer(&qc->tf, pp->pkt, i);
+		break;
 
-	/* get drive status; clear intr; complete txn */
-	ata_qc_complete(qc, ata_wait_idle(ap) | err_bit);
+	default:
+		break;
+	}
 }
 
 static void pdc_eng_timeout(struct ata_port *ap)
@@ -315,17 +316,9 @@
 
 	switch (qc->tf.protocol) {
 	case ATA_PROT_DMA:
-		printk(KERN_ERR "ata%u: DMA timeout\n", ap->id);
-		ata_qc_complete(qc, ata_wait_idle(ap) | ATA_ERR);
-		break;
-
 	case ATA_PROT_NODATA:
-		drv_stat = ata_busy_wait(ap, ATA_BUSY | ATA_DRQ, 1000);
-
-		printk(KERN_ERR "ata%u: command 0x%x timeout, stat 0x%x\n",
-		       ap->id, qc->tf.command, drv_stat);
-
-		ata_qc_complete(qc, drv_stat);
+		printk(KERN_ERR "ata%u: command timeout\n", ap->id);
+		ata_qc_complete(qc, ata_wait_idle(ap) | ATA_ERR);
 		break;
 
 	default:
@@ -358,13 +351,8 @@
 
 	switch (qc->tf.protocol) {
 	case ATA_PROT_DMA:
-		pdc_dma_complete(ap, qc, have_err);
-		handled = 1;
-		break;
-
-	case ATA_PROT_NODATA:   /* command completion, but no data xfer */
-		status = ata_busy_wait(ap, ATA_BUSY | ATA_DRQ, 1000);
-		DPRINTK("BUS_NODATA (drv_stat 0x%X)\n", status);
+	case ATA_PROT_NODATA:
+		status = ata_wait_idle(ap);
 		if (have_err)
 			status |= ATA_ERR;
 		ata_qc_complete(qc, status);
@@ -440,7 +428,7 @@
 	return IRQ_RETVAL(handled);
 }
 
-static inline void pdc_dma_start(struct ata_queued_cmd *qc)
+static inline void pdc_packet_start(struct ata_queued_cmd *qc)
 {
 	struct ata_port *ap = qc->ap;
 	struct pdc_port_priv *pp = ap->private_data;
@@ -462,7 +450,8 @@
 {
 	switch (qc->tf.protocol) {
 	case ATA_PROT_DMA:
-		pdc_dma_start(qc);
+	case ATA_PROT_NODATA:
+		pdc_packet_start(qc);
 		return 0;
 
 	case ATA_PROT_ATAPI_DMA:
@@ -478,15 +467,17 @@
 
 static void pdc_tf_load_mmio(struct ata_port *ap, struct ata_taskfile *tf)
 {
-	WARN_ON (tf->protocol == ATA_PROT_DMA);
-	ata_tf_load_mmio(ap, tf);
+	WARN_ON (tf->protocol == ATA_PROT_DMA ||
+		 tf->protocol == ATA_PROT_NODATA);
+	ata_tf_load(ap, tf);
 }
 
 
 static void pdc_exec_command_mmio(struct ata_port *ap, struct ata_taskfile *tf)
 {
-	WARN_ON (tf->protocol == ATA_PROT_DMA);
-	ata_exec_command_mmio(ap, tf);
+	WARN_ON (tf->protocol == ATA_PROT_DMA ||
+		 tf->protocol == ATA_PROT_NODATA);
+	ata_exec_command(ap, tf);
 }
 
 
@@ -539,8 +530,7 @@
 	writel(tmp, mmio + PDC_TBG_MODE);
 
 	readl(mmio + PDC_TBG_MODE);	/* flush */
-	set_current_state(TASK_UNINTERRUPTIBLE);
-	schedule_timeout(msecs_to_jiffies(10) + 1);
+	msleep(10);
 
 	/* adjust slew rate control register. */
 	tmp = readl(mmio + PDC_SLEW_CTL);
@@ -601,6 +591,7 @@
 	probe_ent->sht		= pdc_port_info[board_idx].sht;
 	probe_ent->host_flags	= pdc_port_info[board_idx].host_flags;
 	probe_ent->pio_mask	= pdc_port_info[board_idx].pio_mask;
+	probe_ent->mwdma_mask	= pdc_port_info[board_idx].mwdma_mask;
 	probe_ent->udma_mask	= pdc_port_info[board_idx].udma_mask;
 	probe_ent->port_ops	= pdc_port_info[board_idx].port_ops;
 
diff -Nru a/drivers/scsi/sata_sil.c b/drivers/scsi/sata_sil.c
--- a/drivers/scsi/sata_sil.c	2004-10-18 14:55:53 -07:00
+++ b/drivers/scsi/sata_sil.c	2004-10-18 14:55:53 -07:00
@@ -6,7 +6,7 @@
  *		    on emails.
  *
  *  Copyright 2003 Red Hat, Inc.
- *  Copyright 2003 Benjamin Herrenschmidt <benh@kernel.crashing.org>
+ *  Copyright 2003 Benjamin Herrenschmidt
  *
  *  The contents of this file are subject to the Open
  *  Software License version 1.1 that can be found at
@@ -106,6 +106,7 @@
 static Scsi_Host_Template sil_sht = {
 	.module			= THIS_MODULE,
 	.name			= DRV_NAME,
+	.ioctl			= ata_scsi_ioctl,
 	.queuecommand		= ata_scsi_queuecmd,
 	.eh_strategy_handler	= ata_scsi_error,
 	.can_queue		= ATA_DEF_QUEUE,
@@ -124,14 +125,15 @@
 static struct ata_port_operations sil_ops = {
 	.port_disable		= ata_port_disable,
 	.dev_config		= sil_dev_config,
-	.tf_load		= ata_tf_load_mmio,
-	.tf_read		= ata_tf_read_mmio,
-	.check_status		= ata_check_status_mmio,
-	.exec_command		= ata_exec_command_mmio,
+	.tf_load		= ata_tf_load,
+	.tf_read		= ata_tf_read,
+	.check_status		= ata_check_status,
+	.exec_command		= ata_exec_command,
+	.dev_select		= ata_std_dev_select,
 	.phy_reset		= sata_phy_reset,
 	.post_set_mode		= sil_post_set_mode,
-	.bmdma_setup            = ata_bmdma_setup_mmio,
-	.bmdma_start            = ata_bmdma_start_mmio,
+	.bmdma_setup            = ata_bmdma_setup,
+	.bmdma_start            = ata_bmdma_start,
 	.qc_prep		= ata_qc_prep,
 	.qc_issue		= ata_qc_issue_prot,
 	.eng_timeout		= ata_eng_timeout,
@@ -149,7 +151,8 @@
 		.sht		= &sil_sht,
 		.host_flags	= ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY |
 				  ATA_FLAG_SRST | ATA_FLAG_MMIO,
-		.pio_mask	= 0x03,			/* pio3-4 */
+		.pio_mask	= 0x1f,			/* pio0-4 */
+		.mwdma_mask	= 0x07,			/* mwdma0-2 */
 		.udma_mask	= 0x3f,			/* udma0-5 */
 		.port_ops	= &sil_ops,
 	}, /* sil_3114 */
@@ -157,7 +160,8 @@
 		.sht		= &sil_sht,
 		.host_flags	= ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY |
 				  ATA_FLAG_SRST | ATA_FLAG_MMIO,
-		.pio_mask	= 0x03,			/* pio3-4 */
+		.pio_mask	= 0x1f,			/* pio0-4 */
+		.mwdma_mask	= 0x07,			/* mwdma0-2 */
 		.udma_mask	= 0x3f,			/* udma0-5 */
 		.port_ops	= &sil_ops,
 	},
@@ -363,6 +367,7 @@
 	probe_ent->sht = sil_port_info[ent->driver_data].sht;
 	probe_ent->n_ports = (ent->driver_data == sil_3114) ? 4 : 2;
 	probe_ent->pio_mask = sil_port_info[ent->driver_data].pio_mask;
+	probe_ent->mwdma_mask = sil_port_info[ent->driver_data].mwdma_mask;
 	probe_ent->udma_mask = sil_port_info[ent->driver_data].udma_mask;
        	probe_ent->irq = pdev->irq;
        	probe_ent->irq_flags = SA_SHIRQ;
diff -Nru a/drivers/scsi/sata_sis.c b/drivers/scsi/sata_sis.c
--- a/drivers/scsi/sata_sis.c	2004-10-18 14:56:32 -07:00
+++ b/drivers/scsi/sata_sis.c	2004-10-18 14:56:32 -07:00
@@ -76,6 +76,7 @@
 static Scsi_Host_Template sis_sht = {
 	.module			= THIS_MODULE,
 	.name			= DRV_NAME,
+	.ioctl			= ata_scsi_ioctl,
 	.queuecommand		= ata_scsi_queuecmd,
 	.eh_strategy_handler	= ata_scsi_error,
 	.can_queue		= ATA_DEF_QUEUE,
@@ -93,13 +94,14 @@
 
 static struct ata_port_operations sis_ops = {
 	.port_disable		= ata_port_disable,
-	.tf_load		= ata_tf_load_pio,
-	.tf_read		= ata_tf_read_pio,
-	.check_status		= ata_check_status_pio,
-	.exec_command		= ata_exec_command_pio,
+	.tf_load		= ata_tf_load,
+	.tf_read		= ata_tf_read,
+	.check_status		= ata_check_status,
+	.exec_command		= ata_exec_command,
+	.dev_select		= ata_std_dev_select,
 	.phy_reset		= sata_phy_reset,
-	.bmdma_setup            = ata_bmdma_setup_pio,
-	.bmdma_start            = ata_bmdma_start_pio,
+	.bmdma_setup            = ata_bmdma_setup,
+	.bmdma_start            = ata_bmdma_start,
 	.qc_prep		= ata_qc_prep,
 	.qc_issue		= ata_qc_issue_prot,
 	.eng_timeout		= ata_eng_timeout,
@@ -111,6 +113,16 @@
 	.port_stop		= ata_port_stop,
 };
 
+static struct ata_port_info sis_port_info = {
+	.sht		= &sis_sht,
+	.host_flags	= ATA_FLAG_SATA | ATA_FLAG_SATA_RESET |
+			  ATA_FLAG_NO_LEGACY,
+	.pio_mask	= 0x1f,
+	.mwdma_mask	= 0x7,
+	.udma_mask	= 0x7f,
+	.port_ops	= &sis_ops,
+};
+
 
 MODULE_AUTHOR("Uwe Koziolek");
 MODULE_DESCRIPTION("low-level driver for Silicon Integratad Systems SATA controller");
@@ -184,6 +196,7 @@
 	struct ata_probe_ent *probe_ent = NULL;
 	int rc;
 	u32 genctl;
+	struct ata_port_info *ppi;
 
 	rc = pci_enable_device(pdev);
 	if (rc)
@@ -200,20 +213,13 @@
 	if (rc)
 		goto err_out_regions;
 
-	probe_ent = kmalloc(sizeof(*probe_ent), GFP_KERNEL);
+	ppi = &sis_port_info;
+	probe_ent = ata_pci_init_native_mode(pdev, &ppi);
 	if (!probe_ent) {
 		rc = -ENOMEM;
 		goto err_out_regions;
 	}
 
-	memset(probe_ent, 0, sizeof(*probe_ent));
-	probe_ent->pdev = pdev;
-	INIT_LIST_HEAD(&probe_ent->node);
-
-	probe_ent->sht = &sis_sht;
-	probe_ent->host_flags = ATA_FLAG_SATA | ATA_FLAG_SATA_RESET |
-				ATA_FLAG_NO_LEGACY;
-
 	/* check and see if the SCRs are in IO space or PCI cfg space */
 	pci_read_config_dword(pdev, SIS_GENCTL, &genctl);
 	if ((genctl & GENCTL_IOMAPPED_SCR) == 0)
@@ -230,31 +236,12 @@
 		probe_ent->host_flags |= SIS_FLAG_CFGSCR;
 	}
 
-	probe_ent->pio_mask = 0x03;
-	probe_ent->udma_mask = 0x7f;
-	probe_ent->port_ops = &sis_ops;
-
-	probe_ent->port[0].cmd_addr = pci_resource_start(pdev, 0);
-	ata_std_ports(&probe_ent->port[0]);
-	probe_ent->port[0].ctl_addr =
-		pci_resource_start(pdev, 1) | ATA_PCI_CTL_OFS;
-	probe_ent->port[0].bmdma_addr = pci_resource_start(pdev, 4);
-	if (!(probe_ent->host_flags & SIS_FLAG_CFGSCR))
+	if (!(probe_ent->host_flags & SIS_FLAG_CFGSCR)) {
 		probe_ent->port[0].scr_addr =
 			pci_resource_start(pdev, SIS_SCR_PCI_BAR);
-
-	probe_ent->port[1].cmd_addr = pci_resource_start(pdev, 2);
-	ata_std_ports(&probe_ent->port[1]);
-	probe_ent->port[1].ctl_addr =
-		pci_resource_start(pdev, 3) | ATA_PCI_CTL_OFS;
-	probe_ent->port[1].bmdma_addr = pci_resource_start(pdev, 4) + 8;
-	if (!(probe_ent->host_flags & SIS_FLAG_CFGSCR))
 		probe_ent->port[1].scr_addr =
 			pci_resource_start(pdev, SIS_SCR_PCI_BAR) + 64;
-
-	probe_ent->n_ports = 2;
-	probe_ent->irq = pdev->irq;
-	probe_ent->irq_flags = SA_SHIRQ;
+	}
 
 	pci_set_master(pdev);
 	pci_enable_intx(pdev);
@@ -284,6 +271,6 @@
 	pci_unregister_driver(&sis_pci_driver);
 }
 
-
 module_init(sis_init);
 module_exit(sis_exit);
+
diff -Nru a/drivers/scsi/sata_svw.c b/drivers/scsi/sata_svw.c
--- a/drivers/scsi/sata_svw.c	2004-10-18 14:56:33 -07:00
+++ b/drivers/scsi/sata_svw.c	2004-10-18 14:56:33 -07:00
@@ -148,7 +148,73 @@
         }
 }
 
+/**
+ *	k2_bmdma_setup_mmio - Set up PCI IDE BMDMA transaction (MMIO)
+ *	@qc: Info associated with this ATA transaction.
+ *
+ *	LOCKING:
+ *	spin_lock_irqsave(host_set lock)
+ */
+
+void k2_bmdma_setup_mmio (struct ata_queued_cmd *qc)
+{
+	struct ata_port *ap = qc->ap;
+	unsigned int rw = (qc->tf.flags & ATA_TFLAG_WRITE);
+	u8 dmactl;
+	void *mmio = (void *) ap->ioaddr.bmdma_addr;
+	/* load PRD table addr. */
+	mb();	/* make sure PRD table writes are visible to controller */
+	writel(ap->prd_dma, mmio + ATA_DMA_TABLE_OFS);
+
+	/* specify data direction, triple-check start bit is clear */
+	dmactl = readb(mmio + ATA_DMA_CMD);
+	dmactl &= ~(ATA_DMA_WR | ATA_DMA_START);
+	if (!rw)
+		dmactl |= ATA_DMA_WR;
+	writeb(dmactl, mmio + ATA_DMA_CMD);
+
+	/* issue r/w command if this is not a ATA DMA command*/
+	if (qc->tf.protocol != ATA_PROT_DMA)
+		ap->ops->exec_command(ap, &qc->tf);
+}
+
+/**
+ *	k2_bmdma_start_mmio - Start a PCI IDE BMDMA transaction (MMIO)
+ *	@qc: Info associated with this ATA transaction.
+ *
+ *	LOCKING:
+ *	spin_lock_irqsave(host_set lock)
+ */
 
+void k2_bmdma_start_mmio (struct ata_queued_cmd *qc)
+{
+	struct ata_port *ap = qc->ap;
+	void *mmio = (void *) ap->ioaddr.bmdma_addr;
+	u8 dmactl;
+
+	/* start host DMA transaction */
+	dmactl = readb(mmio + ATA_DMA_CMD);
+	writeb(dmactl | ATA_DMA_START, mmio + ATA_DMA_CMD);
+	/* There is a race condition in certain SATA controllers that can 
+	   be seen when the r/w command is given to the controller before the 
+	   host DMA is started. On a Read command, the controller would initiate
+	   the command to the drive even before it sees the DMA start. When there
+	   are very fast drives connected to the controller, or when the data request 
+	   hits in the drive cache, there is the possibility that the drive returns a part
+	   or all of the requested data to the controller before the DMA start is issued.
+	   In this case, the controller would become confused as to what to do with the data.
+	   In the worst case when all the data is returned back to the controller, the
+	   controller could hang. In other cases it could return partial data returning
+	   in data corruption. This problem has been seen in PPC systems and can also appear
+	   on an system with very fast disks, where the SATA controller is sitting behind a 
+	   number of bridges, and hence there is significant latency between the r/w command
+	   and the start command. */
+	/* issue r/w command if the access is to ATA*/
+	if (qc->tf.protocol == ATA_PROT_DMA)
+		ap->ops->exec_command(ap, &qc->tf);
+}
+
+									      
 static u8 k2_stat_check_status(struct ata_port *ap)
 {
        	return readl((void *) ap->ioaddr.status_addr);
@@ -205,6 +271,7 @@
 static Scsi_Host_Template k2_sata_sht = {
 	.module			= THIS_MODULE,
 	.name			= DRV_NAME,
+	.ioctl			= ata_scsi_ioctl,
 	.queuecommand		= ata_scsi_queuecmd,
 	.eh_strategy_handler	= ata_scsi_error,
 	.can_queue		= ATA_DEF_QUEUE,
@@ -229,10 +296,11 @@
 	.tf_load		= k2_sata_tf_load,
 	.tf_read		= k2_sata_tf_read,
 	.check_status		= k2_stat_check_status,
-	.exec_command		= ata_exec_command_mmio,
+	.exec_command		= ata_exec_command,
+	.dev_select		= ata_std_dev_select,
 	.phy_reset		= sata_phy_reset,
-	.bmdma_setup            = ata_bmdma_setup_mmio,
-	.bmdma_start            = ata_bmdma_start_mmio,
+	.bmdma_setup		= k2_bmdma_setup_mmio,
+	.bmdma_start		= k2_bmdma_start_mmio,
 	.qc_prep		= ata_qc_prep,
 	.qc_issue		= ata_qc_issue_prot,
 	.eng_timeout		= ata_eng_timeout,
@@ -343,6 +411,7 @@
 	 * if we don't fill these
 	 */
 	probe_ent->pio_mask = 0x1f;
+	probe_ent->mwdma_mask = 0x7;
 	probe_ent->udma_mask = 0x7f;
 
 	/* We have 4 ports per PCI function */
@@ -371,6 +440,8 @@
 
 static struct pci_device_id k2_sata_pci_tbl[] = {
 	{ 0x1166, 0x0240, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
+	{ 0x1166, 0x0241, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
+	{ 0x1166, 0x0242, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
 	{ }
 };
 
@@ -387,6 +458,7 @@
 {
 	return pci_module_init(&k2_sata_pci_driver);
 }
+
 
 static void __exit k2_sata_exit(void)
 {
diff -Nru a/drivers/scsi/sata_sx4.c b/drivers/scsi/sata_sx4.c
--- a/drivers/scsi/sata_sx4.c	2004-10-18 14:55:53 -07:00
+++ b/drivers/scsi/sata_sx4.c	2004-10-18 14:55:53 -07:00
@@ -146,8 +146,6 @@
 
 
 static int pdc_sata_init_one (struct pci_dev *pdev, const struct pci_device_id *ent);
-static void pdc20621_dma_setup(struct ata_queued_cmd *qc);
-static void pdc20621_dma_start(struct ata_queued_cmd *qc);
 static irqreturn_t pdc20621_interrupt (int irq, void *dev_instance, struct pt_regs *regs);
 static void pdc_eng_timeout(struct ata_port *ap);
 static void pdc_20621_phy_reset (struct ata_port *ap);
@@ -157,8 +155,6 @@
 static void pdc_tf_load_mmio(struct ata_port *ap, struct ata_taskfile *tf);
 static void pdc_exec_command_mmio(struct ata_port *ap, struct ata_taskfile *tf);
 static void pdc20621_host_stop(struct ata_host_set *host_set);
-static inline void pdc_dma_complete (struct ata_port *ap,
-                                     struct ata_queued_cmd *qc, int have_err);
 static unsigned int pdc20621_dimm_init(struct ata_probe_ent *pe);
 static int pdc20621_detect_dimm(struct ata_probe_ent *pe);
 static unsigned int pdc20621_i2c_read(struct ata_probe_ent *pe, 
@@ -172,11 +168,13 @@
 static void pdc20621_put_to_dimm(struct ata_probe_ent *pe, 
 				 void *psource, u32 offset, u32 size);
 static void pdc20621_irq_clear(struct ata_port *ap);
+static int pdc20621_qc_issue_prot(struct ata_queued_cmd *qc);
 
 
 static Scsi_Host_Template pdc_sata_sht = {
 	.module			= THIS_MODULE,
 	.name			= DRV_NAME,
+	.ioctl			= ata_scsi_ioctl,
 	.queuecommand		= ata_scsi_queuecmd,
 	.eh_strategy_handler	= ata_scsi_error,
 	.can_queue		= ATA_DEF_QUEUE,
@@ -195,14 +193,13 @@
 static struct ata_port_operations pdc_20621_ops = {
 	.port_disable		= ata_port_disable,
 	.tf_load		= pdc_tf_load_mmio,
-	.tf_read		= ata_tf_read_mmio,
-	.check_status		= ata_check_status_mmio,
+	.tf_read		= ata_tf_read,
+	.check_status		= ata_check_status,
 	.exec_command		= pdc_exec_command_mmio,
+	.dev_select		= ata_std_dev_select,
 	.phy_reset		= pdc_20621_phy_reset,
-	.bmdma_setup            = pdc20621_dma_setup,
-	.bmdma_start            = pdc20621_dma_start,
 	.qc_prep		= pdc20621_qc_prep,
-	.qc_issue		= ata_qc_issue_prot,
+	.qc_issue		= pdc20621_qc_issue_prot,
 	.eng_timeout		= pdc_eng_timeout,
 	.irq_handler		= pdc20621_interrupt,
 	.irq_clear		= pdc20621_irq_clear,
@@ -217,7 +214,8 @@
 		.sht		= &pdc_sata_sht,
 		.host_flags	= ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY |
 				  ATA_FLAG_SRST | ATA_FLAG_MMIO,
-		.pio_mask	= 0x03, /* pio3-4 */
+		.pio_mask	= 0x1f, /* pio0-4 */
+		.mwdma_mask	= 0x07, /* mwdma0-2 */
 		.udma_mask	= 0x7f, /* udma0-6 ; FIXME */
 		.port_ops	= &pdc_20621_ops,
 	},
@@ -377,7 +375,10 @@
 
 	/* dimm dma S/G, and next-pkt */
 	dw = i >> 2;
-	buf32[dw] = cpu_to_le32(dimm_sg);
+	if (tf->protocol == ATA_PROT_NODATA)
+		buf32[dw] = 0;
+	else
+		buf32[dw] = cpu_to_le32(dimm_sg);
 	buf32[dw + 1] = 0;
 	i += 8;
 
@@ -437,7 +438,7 @@
 		buf32[dw + 3]);
 }
 
-static void pdc20621_qc_prep(struct ata_queued_cmd *qc)
+static void pdc20621_dma_prep(struct ata_queued_cmd *qc)
 {
 	struct scatterlist *sg = qc->sg;
 	struct ata_port *ap = qc->ap;
@@ -449,8 +450,7 @@
 	unsigned int i, last, idx, total_len = 0, sgt_len;
 	u32 *buf = (u32 *) &pp->dimm_buf[PDC_DIMM_HEADER_SZ];
 
-	if (!(qc->flags & ATA_QCFLAG_DMAMAP))
-		return;
+	assert(qc->flags & ATA_QCFLAG_DMAMAP);
 
 	VPRINTK("ata%u: ENTER\n", ap->id);
 
@@ -501,6 +501,56 @@
 	VPRINTK("ata pkt buf ofs %u, prd size %u, mmio copied\n", i, sgt_len);
 }
 
+static void pdc20621_nodata_prep(struct ata_queued_cmd *qc)
+{
+	struct ata_port *ap = qc->ap;
+	struct pdc_port_priv *pp = ap->private_data;
+	void *mmio = ap->host_set->mmio_base;
+	struct pdc_host_priv *hpriv = ap->host_set->private_data;
+	void *dimm_mmio = hpriv->dimm_mmio;
+	unsigned int portno = ap->port_no;
+	unsigned int i;
+
+	VPRINTK("ata%u: ENTER\n", ap->id);
+
+	/* hard-code chip #0 */
+	mmio += PDC_CHIP0_OFS;
+
+	i = pdc20621_ata_pkt(&qc->tf, qc->dev->devno, &pp->dimm_buf[0], portno);
+
+	if (qc->tf.flags & ATA_TFLAG_LBA48)
+		i = pdc_prep_lba48(&qc->tf, &pp->dimm_buf[0], i);
+	else
+		i = pdc_prep_lba28(&qc->tf, &pp->dimm_buf[0], i);
+
+	pdc_pkt_footer(&qc->tf, &pp->dimm_buf[0], i);
+
+	/* copy three S/G tables and two packets to DIMM MMIO window */
+	memcpy_toio(dimm_mmio + (portno * PDC_DIMM_WINDOW_STEP),
+		    &pp->dimm_buf, PDC_DIMM_HEADER_SZ);
+
+	/* force host FIFO dump */
+	writel(0x00000001, mmio + PDC_20621_GENERAL_CTL);
+
+	readl(dimm_mmio);	/* MMIO PCI posting flush */
+
+	VPRINTK("ata pkt buf ofs %u, mmio copied\n", i);
+}
+
+static void pdc20621_qc_prep(struct ata_queued_cmd *qc)
+{
+	switch (qc->tf.protocol) {
+	case ATA_PROT_DMA:
+		pdc20621_dma_prep(qc);
+		break;
+	case ATA_PROT_NODATA:
+		pdc20621_nodata_prep(qc);
+		break;
+	default:
+		break;
+	}
+}
+
 static void __pdc20621_push_hdma(struct ata_queued_cmd *qc,
 				 unsigned int seq,
 				 u32 pkt_ofs)
@@ -576,13 +626,7 @@
 static inline void pdc20621_dump_hdma(struct ata_queued_cmd *qc) { }
 #endif /* ATA_VERBOSE_DEBUG */
 
-static void pdc20621_dma_setup(struct ata_queued_cmd *qc)
-{
-	/* nothing for now.  later, we will call standard
-	 * code in libata-core for ATAPI here */
-}
-
-static void pdc20621_dma_start(struct ata_queued_cmd *qc)
+static void pdc20621_packet_start(struct ata_queued_cmd *qc)
 {
 	struct ata_port *ap = qc->ap;
 	struct ata_host_set *host_set = ap->host_set;
@@ -590,24 +634,21 @@
 	void *mmio = host_set->mmio_base;
 	unsigned int rw = (qc->tf.flags & ATA_TFLAG_WRITE);
 	u8 seq = (u8) (port_no + 1);
-	unsigned int doing_hdma = 0, port_ofs;
+	unsigned int port_ofs;
 
 	/* hard-code chip #0 */
 	mmio += PDC_CHIP0_OFS;
 
 	VPRINTK("ata%u: ENTER\n", ap->id);
 
+	wmb();			/* flush PRD, pkt writes */
+
 	port_ofs = PDC_20621_DIMM_BASE + (PDC_DIMM_WINDOW_STEP * port_no);
 
 	/* if writing, we (1) DMA to DIMM, then (2) do ATA command */
-	if (rw) {
-		doing_hdma = 1;
+	if (rw && qc->tf.protocol == ATA_PROT_DMA) {
 		seq += 4;
-	}
-
-	wmb();			/* flush PRD, pkt writes */
 
-	if (doing_hdma) {
 		pdc20621_dump_hdma(qc);
 		pdc20621_push_hdma(qc, seq, port_ofs + PDC_DIMM_HOST_PKT);
 		VPRINTK("queued ofs 0x%x (%u), seq %u\n",
@@ -628,6 +669,25 @@
 	}
 }
 
+static int pdc20621_qc_issue_prot(struct ata_queued_cmd *qc)
+{
+	switch (qc->tf.protocol) {
+	case ATA_PROT_DMA:
+	case ATA_PROT_NODATA:
+		pdc20621_packet_start(qc);
+		return 0;
+
+	case ATA_PROT_ATAPI_DMA:
+		BUG();
+		break;
+
+	default:
+		break;
+	}
+
+	return ata_qc_issue_prot(qc);
+}
+
 static inline unsigned int pdc20621_host_intr( struct ata_port *ap,
                                           struct ata_queued_cmd *qc,
 					  unsigned int doing_hdma,
@@ -648,7 +708,8 @@
 		if (doing_hdma) {
 			VPRINTK("ata%u: read hdma, 0x%x 0x%x\n", ap->id,
 				readl(mmio + 0x104), readl(mmio + PDC_HDMA_CTLSTAT));
-			pdc_dma_complete(ap, qc, 0);
+			/* get drive status; clear intr; complete txn */
+			ata_qc_complete(qc, ata_wait_idle(ap));
 			pdc20621_pop_hdma(qc);
 		}
 
@@ -685,7 +746,8 @@
 		else {
 			VPRINTK("ata%u: write ata, 0x%x 0x%x\n", ap->id,
 				readl(mmio + 0x104), readl(mmio + PDC_HDMA_CTLSTAT));
-			pdc_dma_complete(ap, qc, 0);
+			/* get drive status; clear intr; complete txn */
+			ata_qc_complete(qc, ata_wait_idle(ap));
 			pdc20621_pop_hdma(qc);
 		}
 		handled = 1;
@@ -779,16 +841,6 @@
 	return IRQ_RETVAL(handled);
 }
 
-static inline void pdc_dma_complete (struct ata_port *ap,
-                                     struct ata_queued_cmd *qc,
-				     int have_err)
-{
-	u8 err_bit = have_err ? ATA_ERR : 0;
-
-	/* get drive status; clear intr; complete txn */
-	ata_qc_complete(qc, ata_wait_idle(ap) | err_bit);
-}
-
 static void pdc_eng_timeout(struct ata_port *ap)
 {
 	u8 drv_stat;
@@ -813,17 +865,9 @@
 
 	switch (qc->tf.protocol) {
 	case ATA_PROT_DMA:
-		printk(KERN_ERR "ata%u: DMA timeout\n", ap->id);
-		ata_qc_complete(qc, ata_wait_idle(ap) | ATA_ERR);
-		break;
-
 	case ATA_PROT_NODATA:
-		drv_stat = ata_busy_wait(ap, ATA_BUSY | ATA_DRQ, 1000);
-
-		printk(KERN_ERR "ata%u: command 0x%x timeout, stat 0x%x\n",
-		       ap->id, qc->tf.command, drv_stat);
-
-		ata_qc_complete(qc, drv_stat);
+		printk(KERN_ERR "ata%u: command timeout\n", ap->id);
+		ata_qc_complete(qc, ata_wait_idle(ap) | ATA_ERR);
 		break;
 
 	default:
@@ -842,15 +886,17 @@
 
 static void pdc_tf_load_mmio(struct ata_port *ap, struct ata_taskfile *tf)
 {
-	if (tf->protocol != ATA_PROT_DMA)
-		ata_tf_load_mmio(ap, tf);
+	WARN_ON (tf->protocol == ATA_PROT_DMA ||
+		 tf->protocol == ATA_PROT_NODATA);
+	ata_tf_load(ap, tf);
 }
 
 
 static void pdc_exec_command_mmio(struct ata_port *ap, struct ata_taskfile *tf)
 {
-	if (tf->protocol != ATA_PROT_DMA)
-		ata_exec_command_mmio(ap, tf);
+	WARN_ON (tf->protocol == ATA_PROT_DMA ||
+		 tf->protocol == ATA_PROT_NODATA);
+	ata_exec_command(ap, tf);
 }
 
 
@@ -1384,6 +1430,7 @@
 	probe_ent->sht		= pdc_port_info[board_idx].sht;
 	probe_ent->host_flags	= pdc_port_info[board_idx].host_flags;
 	probe_ent->pio_mask	= pdc_port_info[board_idx].pio_mask;
+	probe_ent->mwdma_mask	= pdc_port_info[board_idx].mwdma_mask;
 	probe_ent->udma_mask	= pdc_port_info[board_idx].udma_mask;
 	probe_ent->port_ops	= pdc_port_info[board_idx].port_ops;
 
@@ -1394,21 +1441,11 @@
 	probe_ent->private_data = hpriv;
 	base += PDC_CHIP0_OFS;
 
+	probe_ent->n_ports = 4;
 	pdc_sata_setup_port(&probe_ent->port[0], base + 0x200);
 	pdc_sata_setup_port(&probe_ent->port[1], base + 0x280);
-
-	/* notice 4-port boards */
-	switch (board_idx) {
-	case board_20621:
-       		probe_ent->n_ports = 4;
-
-		pdc_sata_setup_port(&probe_ent->port[2], base + 0x300);
-		pdc_sata_setup_port(&probe_ent->port[3], base + 0x380);
-		break;
-	default:
-		BUG();
-		break;
-	}
+	pdc_sata_setup_port(&probe_ent->port[2], base + 0x300);
+	pdc_sata_setup_port(&probe_ent->port[3], base + 0x380);
 
 	pci_set_master(pdev);
 
diff -Nru a/drivers/scsi/sata_via.c b/drivers/scsi/sata_via.c
--- a/drivers/scsi/sata_via.c	2004-10-18 14:56:17 -07:00
+++ b/drivers/scsi/sata_via.c	2004-10-18 14:56:17 -07:00
@@ -81,6 +81,7 @@
 static Scsi_Host_Template svia_sht = {
 	.module			= THIS_MODULE,
 	.name			= DRV_NAME,
+	.ioctl			= ata_scsi_ioctl,
 	.queuecommand		= ata_scsi_queuecmd,
 	.eh_strategy_handler	= ata_scsi_error,
 	.can_queue		= ATA_DEF_QUEUE,
@@ -99,15 +100,16 @@
 static struct ata_port_operations svia_sata_ops = {
 	.port_disable		= ata_port_disable,
 
-	.tf_load		= ata_tf_load_pio,
-	.tf_read		= ata_tf_read_pio,
-	.check_status		= ata_check_status_pio,
-	.exec_command		= ata_exec_command_pio,
+	.tf_load		= ata_tf_load,
+	.tf_read		= ata_tf_read,
+	.check_status		= ata_check_status,
+	.exec_command		= ata_exec_command,
+	.dev_select		= ata_std_dev_select,
 
 	.phy_reset		= sata_phy_reset,
 
-	.bmdma_setup            = ata_bmdma_setup_pio,
-	.bmdma_start            = ata_bmdma_start_pio,
+	.bmdma_setup            = ata_bmdma_setup,
+	.bmdma_start            = ata_bmdma_start,
 	.qc_prep		= ata_qc_prep,
 	.qc_issue		= ata_qc_issue_prot,
 
@@ -123,6 +125,15 @@
 	.port_stop		= ata_port_stop,
 };
 
+static struct ata_port_info svia_port_info = {
+	.sht		= &svia_sht,
+	.host_flags	= ATA_FLAG_SATA | ATA_FLAG_SRST | ATA_FLAG_NO_LEGACY,
+	.pio_mask	= 0x1f,
+	.mwdma_mask	= 0x07,
+	.udma_mask	= 0x7f,
+	.port_ops	= &svia_sata_ops,
+};
+
 MODULE_AUTHOR("Jeff Garzik");
 MODULE_DESCRIPTION("SCSI low-level driver for VIA SATA controllers");
 MODULE_LICENSE("GPL");
@@ -156,6 +167,7 @@
 	static int printed_version;
 	unsigned int i;
 	int rc;
+	struct ata_port_info *ppi;
 	struct ata_probe_ent *probe_ent;
 	u8 tmp8;
 
@@ -196,41 +208,17 @@
 	if (rc)
 		goto err_out_regions;
 
-	probe_ent = kmalloc(sizeof(*probe_ent), GFP_KERNEL);
+	ppi = &svia_port_info;
+	probe_ent = ata_pci_init_native_mode(pdev, &ppi);
 	if (!probe_ent) {
 		printk(KERN_ERR DRV_NAME "(%s): out of memory\n",
 		       pci_name(pdev));
 		rc = -ENOMEM;
 		goto err_out_regions;
 	}
-	memset(probe_ent, 0, sizeof(*probe_ent));
-	INIT_LIST_HEAD(&probe_ent->node);
-	probe_ent->pdev = pdev;
-	probe_ent->sht = &svia_sht;
-	probe_ent->host_flags = ATA_FLAG_SATA | ATA_FLAG_SRST |
-				ATA_FLAG_NO_LEGACY;
-	probe_ent->port_ops = &svia_sata_ops;
-	probe_ent->n_ports = 2;
-	probe_ent->irq = pdev->irq;
-	probe_ent->irq_flags = SA_SHIRQ;
-	probe_ent->pio_mask = 0x1f;
-	probe_ent->udma_mask = 0x7f;
-
-	probe_ent->port[0].cmd_addr = pci_resource_start(pdev, 0);
-	ata_std_ports(&probe_ent->port[0]);
-	probe_ent->port[0].altstatus_addr =
-	probe_ent->port[0].ctl_addr =
-		pci_resource_start(pdev, 1) | ATA_PCI_CTL_OFS;
-	probe_ent->port[0].bmdma_addr = pci_resource_start(pdev, 4);
+
 	probe_ent->port[0].scr_addr =
 		svia_scr_addr(pci_resource_start(pdev, 5), 0);
-
-	probe_ent->port[1].cmd_addr = pci_resource_start(pdev, 2);
-	ata_std_ports(&probe_ent->port[1]);
-	probe_ent->port[1].altstatus_addr =
-	probe_ent->port[1].ctl_addr =
-		pci_resource_start(pdev, 3) | ATA_PCI_CTL_OFS;
-	probe_ent->port[1].bmdma_addr = pci_resource_start(pdev, 4) + 8;
 	probe_ent->port[1].scr_addr =
 		svia_scr_addr(pci_resource_start(pdev, 5), 1);
 
diff -Nru a/drivers/scsi/sata_vsc.c b/drivers/scsi/sata_vsc.c
--- a/drivers/scsi/sata_vsc.c	2004-10-18 14:56:32 -07:00
+++ b/drivers/scsi/sata_vsc.c	2004-10-18 14:56:32 -07:00
@@ -190,6 +190,7 @@
 static Scsi_Host_Template vsc_sata_sht = {
 	.module			= THIS_MODULE,
 	.name			= DRV_NAME,
+	.ioctl			= ata_scsi_ioctl,
 	.queuecommand		= ata_scsi_queuecmd,
 	.eh_strategy_handler	= ata_scsi_error,
 	.can_queue		= ATA_DEF_QUEUE,
@@ -210,11 +211,12 @@
 	.port_disable		= ata_port_disable,
 	.tf_load		= vsc_sata_tf_load,
 	.tf_read		= vsc_sata_tf_read,
-	.exec_command		= ata_exec_command_mmio,
-	.check_status		= ata_check_status_mmio,
+	.exec_command		= ata_exec_command,
+	.check_status		= ata_check_status,
+	.dev_select		= ata_std_dev_select,
 	.phy_reset		= sata_phy_reset,
-	.bmdma_setup            = ata_bmdma_setup_mmio,
-	.bmdma_start            = ata_bmdma_start_mmio,
+	.bmdma_setup            = ata_bmdma_setup,
+	.bmdma_start            = ata_bmdma_start,
 	.qc_prep		= ata_qc_prep,
 	.qc_issue		= ata_qc_issue_prot,
 	.eng_timeout		= ata_eng_timeout,
@@ -320,6 +322,7 @@
 	 * if we don't fill these
 	 */
 	probe_ent->pio_mask = 0x1f;
+	probe_ent->mwdma_mask = 0x07;
 	probe_ent->udma_mask = 0x7f;
 
 	/* We have 4 ports per PCI function */
diff -Nru a/drivers/scsi/scsi.c b/drivers/scsi/scsi.c
--- a/drivers/scsi/scsi.c	2004-10-18 14:56:32 -07:00
+++ b/drivers/scsi/scsi.c	2004-10-18 14:56:32 -07:00
@@ -897,15 +897,16 @@
 	 */
 	if (tags <= 0)
 		return;
-	/*
-	 * Limit max queue depth on a single lun to 256 for now.  Remember,
-	 * we allocate a struct scsi_command for each of these and keep it
-	 * around forever.  Too deep of a depth just wastes memory.
-	 */
-	if (tags > 256)
-		return;
 
 	spin_lock_irqsave(&device_request_lock, flags);
+	spin_lock(sdev->request_queue->queue_lock);
+
+	/* Check to see if the queue is managed by the block layer
+	 * if it is, and we fail to adjust the depth, exit */
+	if (blk_queue_tagged(sdev->request_queue) &&
+	    blk_queue_resize_tags(sdev->request_queue, tags) != 0)
+		goto out;
+
 	sdev->queue_depth = tags;
 	switch (tagged) {
 		case MSG_ORDERED_TAG:
@@ -926,6 +927,8 @@
 			sdev->queue_depth = tags;
 			break;
 	}
+ out:
+	spin_unlock(sdev->request_queue->queue_lock);
 	spin_unlock_irqrestore(&device_request_lock, flags);
 }
 
diff -Nru a/drivers/scsi/scsi_error.c b/drivers/scsi/scsi_error.c
--- a/drivers/scsi/scsi_error.c	2004-10-18 14:55:53 -07:00
+++ b/drivers/scsi/scsi_error.c	2004-10-18 14:55:54 -07:00
@@ -22,7 +22,7 @@
 #include <linux/kernel.h>
 #include <linux/interrupt.h>
 #include <linux/blkdev.h>
-#include <linux/smp_lock.h>
+#include <linux/delay.h>
 
 #include <scsi/scsi.h>
 #include <scsi/scsi_dbg.h>
@@ -42,8 +42,8 @@
  * These should *probably* be handled by the host itself.
  * Since it is allowed to sleep, it probably should.
  */
-#define BUS_RESET_SETTLE_TIME   (10*HZ)
-#define HOST_RESET_SETTLE_TIME  (10*HZ)
+#define BUS_RESET_SETTLE_TIME   (10)
+#define HOST_RESET_SETTLE_TIME  (10)
 
 /* called with shost->host_lock held */
 void scsi_eh_wakeup(struct Scsi_Host *shost)
@@ -643,15 +643,13 @@
  * Notes:
  *    This has the unfortunate side effect that if a shost adapter does
  *    not automatically request sense information, that we end up shutting
- *    it down before we request it.  All shosts should be doing this
- *    anyways, so for now all I have to say is tough noogies if you end up
- *    in here.  On second thought, this is probably a good idea.  We
- *    *really* want to give authors an incentive to automatically request
- *    this.
+ *    it down before we request it.
  *
- *    In 2.5 this capability will be going away.
+ *    All drivers should request sense information internally these days,
+ *    so for now all I have to say is tough noogies if you end up in here.
  *
- *    Really?  --hch
+ *    XXX: Long term this code should go away, but that needs an audit of
+ *         all LLDDs first.
  **/
 static int scsi_eh_get_sense(struct list_head *work_q,
 			     struct list_head *done_q)
@@ -1044,7 +1042,7 @@
 
 	if (rtn == SUCCESS) {
 		if (!scmd->device->host->hostt->skip_settle_delay)
-			scsi_sleep(BUS_RESET_SETTLE_TIME);
+			ssleep(BUS_RESET_SETTLE_TIME);
 		spin_lock_irqsave(scmd->device->host->host_lock, flags);
 		scsi_report_bus_reset(scmd->device->host, scmd->device->channel);
 		spin_unlock_irqrestore(scmd->device->host->host_lock, flags);
@@ -1076,7 +1074,7 @@
 
 	if (rtn == SUCCESS) {
 		if (!scmd->device->host->hostt->skip_settle_delay)
-			scsi_sleep(HOST_RESET_SETTLE_TIME);
+			ssleep(HOST_RESET_SETTLE_TIME);
 		spin_lock_irqsave(scmd->device->host->host_lock, flags);
 		scsi_report_bus_reset(scmd->device->host, scmd->device->channel);
 		spin_unlock_irqrestore(scmd->device->host->host_lock, flags);
@@ -1216,43 +1214,6 @@
 }
 
 /**
- * scsi_sleep_done - timer function for scsi_sleep
- * @sem:	semphore to signal
- *
- **/
-static void scsi_sleep_done(unsigned long data)
-{
-	struct semaphore *sem = (struct semaphore *)data;
-
-	if (sem)
-		up(sem);
-}
-
-/**
- * scsi_sleep - sleep for specified timeout
- * @timeout:	timeout value
- *
- **/
-void scsi_sleep(int timeout)
-{
-	DECLARE_MUTEX_LOCKED(sem);
-	struct timer_list timer;
-
-	init_timer(&timer);
-	timer.data = (unsigned long)&sem;
-	timer.expires = jiffies + timeout;
-	timer.function = (void (*)(unsigned long))scsi_sleep_done;
-
-	SCSI_LOG_ERROR_RECOVERY(5, printk("sleeping for timer tics %d\n",
-					  timeout));
-
-	add_timer(&timer);
-
-	down(&sem);
-	del_timer(&timer);
-}
-
-/**
  * scsi_decide_disposition - Disposition a cmd on return from LLD.
  * @scmd:	SCSI cmd to examine.
  *
@@ -1639,8 +1600,6 @@
 	int rtn;
 	DECLARE_MUTEX_LOCKED(sem);
 
-	lock_kernel();
-
 	/*
 	 *    Flush resources
 	 */
@@ -1651,8 +1610,6 @@
 
 	shost->eh_wait = &sem;
 	shost->ehandler = current;
-
-	unlock_kernel();
 
 	/*
 	 * Wake up the thread that created us.
diff -Nru a/drivers/scsi/scsi_ioctl.c b/drivers/scsi/scsi_ioctl.c
--- a/drivers/scsi/scsi_ioctl.c	2004-10-18 14:57:04 -07:00
+++ b/drivers/scsi/scsi_ioctl.c	2004-10-18 14:57:04 -07:00
@@ -391,6 +391,21 @@
 	if (!scsi_block_when_processing_errors(sdev))
 		return -ENODEV;
 
+	/* Check for deprecated ioctls ... all the ioctls which don't
+	 * follow the new unique numbering scheme are deprecated */
+	switch (cmd) {
+	case SCSI_IOCTL_SEND_COMMAND:
+	case SCSI_IOCTL_TEST_UNIT_READY:
+	case SCSI_IOCTL_BENCHMARK_COMMAND:
+	case SCSI_IOCTL_SYNC:
+	case SCSI_IOCTL_START_UNIT:
+	case SCSI_IOCTL_STOP_UNIT:
+		printk(KERN_WARNING "program %s is using a deprecated SCSI ioctl, please convert it to SG_IO\n", current->comm);
+		break;
+	default:
+		break;
+	}
+
 	switch (cmd) {
 	case SCSI_IOCTL_GET_IDLUN:
 		if (verify_area(VERIFY_WRITE, arg, sizeof(struct scsi_idlun)))
@@ -417,12 +432,8 @@
 	case SCSI_IOCTL_DOORUNLOCK:
 		return scsi_set_medium_removal(sdev, SCSI_REMOVAL_ALLOW);
 	case SCSI_IOCTL_TEST_UNIT_READY:
-		scsi_cmd[0] = TEST_UNIT_READY;
-		scsi_cmd[1] = 0;
-		scsi_cmd[2] = scsi_cmd[3] = scsi_cmd[5] = 0;
-		scsi_cmd[4] = 0;
-		return ioctl_internal_command(sdev, scsi_cmd,
-				   IOCTL_NORMAL_TIMEOUT, NORMAL_RETRIES);
+		return scsi_test_unit_ready(sdev, IOCTL_NORMAL_TIMEOUT,
+					    NORMAL_RETRIES);
 	case SCSI_IOCTL_START_UNIT:
 		scsi_cmd[0] = START_STOP;
 		scsi_cmd[1] = 0;
diff -Nru a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c
--- a/drivers/scsi/scsi_lib.c	2004-10-18 14:56:32 -07:00
+++ b/drivers/scsi/scsi_lib.c	2004-10-18 14:56:32 -07:00
@@ -954,6 +954,22 @@
 	return BLKPREP_KILL;
 }
 
+static int scsi_issue_flush_fn(request_queue_t *q, struct gendisk *disk,
+			       sector_t *error_sector)
+{
+	struct scsi_device *sdev = q->queuedata;
+	struct scsi_driver *drv;
+
+	if (sdev->sdev_state != SDEV_RUNNING)
+		return -ENXIO;
+
+	drv = *(struct scsi_driver **) disk->private_data;
+	if (drv->issue_flush)
+		return drv->issue_flush(&sdev->sdev_gendev, error_sector);
+
+	return -EOPNOTSUPP;
+}
+
 static int scsi_prep_fn(struct request_queue *q, struct request *req)
 {
 	struct scsi_device *sdev = q->queuedata;
@@ -1335,7 +1351,8 @@
 	blk_queue_max_sectors(q, shost->max_sectors);
 	blk_queue_bounce_limit(q, scsi_calculate_bounce_limit(shost));
 	blk_queue_segment_boundary(q, shost->dma_boundary);
- 
+	blk_queue_issue_flush_fn(q, scsi_issue_flush_fn);
+
 	if (!shost->use_clustering)
 		clear_bit(QUEUE_FLAG_CLUSTER, &q->queue_flags);
 	return q;
@@ -1554,6 +1571,34 @@
 
 	return ret;
 }
+
+int
+scsi_test_unit_ready(struct scsi_device *sdev, int timeout, int retries)
+{
+	struct scsi_request *sreq;
+	char cmd[] = {
+		TEST_UNIT_READY, 0, 0, 0, 0, 0,
+	};
+	int result;
+	
+	sreq = scsi_allocate_request(sdev, GFP_KERNEL);
+	if (!sreq)
+		return -ENOMEM;
+
+		sreq->sr_data_direction = DMA_NONE;
+        scsi_wait_req(sreq, cmd, NULL, 0, timeout, retries);
+
+	if ((driver_byte(sreq->sr_result) & DRIVER_SENSE) &&
+	    (sreq->sr_sense_buffer[2] & 0x0f) == UNIT_ATTENTION &&
+	    sdev->removable) {
+		sdev->changed = 1;
+		sreq->sr_result = 0;
+	}
+	result = sreq->sr_result;
+	scsi_release_request(sreq);
+	return result;
+}
+EXPORT_SYMBOL(scsi_test_unit_ready);
 
 /**
  *	scsi_device_set_state - Take the given device through the device
diff -Nru a/drivers/scsi/scsi_scan.c b/drivers/scsi/scsi_scan.c
--- a/drivers/scsi/scsi_scan.c	2004-10-18 14:56:49 -07:00
+++ b/drivers/scsi/scsi_scan.c	2004-10-18 14:56:49 -07:00
@@ -200,7 +200,7 @@
  *     scsi_Device pointer, or NULL on failure.
  **/
 static struct scsi_device *scsi_alloc_sdev(struct Scsi_Host *shost,
-	       	uint channel, uint id, uint lun)
+	       	uint channel, uint id, uint lun, void *hostdata)
 {
 	struct scsi_device *sdev, *device;
 	unsigned long flags;
@@ -224,6 +224,8 @@
 	INIT_LIST_HEAD(&sdev->starved_entry);
 	spin_lock_init(&sdev->list_lock);
 
+	/* usually NULL and set by ->slave_alloc instead */
+	sdev->hostdata = hostdata;
 
 	/* if the device needs this changing, it may do so in the
 	 * slave_configure function */
@@ -697,7 +699,7 @@
  **/
 static int scsi_probe_and_add_lun(struct Scsi_Host *host,
 		uint channel, uint id, uint lun, int *bflagsp,
-		struct scsi_device **sdevp, int rescan)
+		struct scsi_device **sdevp, int rescan, void *hostdata)
 {
 	struct scsi_device *sdev;
 	struct scsi_request *sreq;
@@ -726,7 +728,7 @@
 		}
 	}
 
-	sdev = scsi_alloc_sdev(host, channel, id, lun);
+	sdev = scsi_alloc_sdev(host, channel, id, lun, hostdata);
 	if (!sdev)
 		goto out;
 	sreq = scsi_allocate_request(sdev, GFP_ATOMIC);
@@ -874,7 +876,7 @@
 	 */
 	for (lun = 1; lun < max_dev_lun; ++lun)
 		if ((scsi_probe_and_add_lun(shost, channel, id, lun,
-		      NULL, NULL, rescan) != SCSI_SCAN_LUN_PRESENT) &&
+		      NULL, NULL, rescan, NULL) != SCSI_SCAN_LUN_PRESENT) &&
 		    !sparse_lun)
 			return;
 }
@@ -1085,7 +1087,7 @@
 			int res;
 
 			res = scsi_probe_and_add_lun(sdev->host, sdev->channel,
-				sdev->id, lun, NULL, NULL, rescan);
+				sdev->id, lun, NULL, NULL, rescan, NULL);
 			if (res == SCSI_SCAN_NO_RESPONSE) {
 				/*
 				 * Got some results, but now none, abort.
@@ -1111,14 +1113,15 @@
 	return 0;
 }
 
-struct scsi_device *scsi_add_device(struct Scsi_Host *shost,
-				    uint channel, uint id, uint lun)
+struct scsi_device *__scsi_add_device(struct Scsi_Host *shost, uint channel,
+		uint id, uint lun, void *hostdata)
 {
 	struct scsi_device *sdev;
 	int res;
 
 	down(&shost->scan_mutex);
-	res = scsi_probe_and_add_lun(shost, channel, id, lun, NULL, &sdev, 1);
+	res = scsi_probe_and_add_lun(shost, channel, id, lun, NULL,
+				     &sdev, 1, hostdata);
 	if (res != SCSI_SCAN_LUN_PRESENT)
 		sdev = ERR_PTR(-ENODEV);
 	up(&shost->scan_mutex);
@@ -1178,7 +1181,7 @@
 		 * Scan for a specific host/chan/id/lun.
 		 */
 		scsi_probe_and_add_lun(shost, channel, id, lun, NULL, NULL,
-				       rescan);
+				       rescan, NULL);
 		return;
 	}
 
@@ -1187,7 +1190,7 @@
 	 * would not configure LUN 0 until all LUNs are scanned.
 	 */
 	res = scsi_probe_and_add_lun(shost, channel, id, 0, &bflags, &sdev,
-				     rescan);
+				     rescan, NULL);
 	if (res == SCSI_SCAN_LUN_PRESENT) {
 		if (scsi_report_lun_scan(sdev, bflags, rescan) != 0)
 			/*
@@ -1316,7 +1319,7 @@
 {
 	struct scsi_device *sdev;
 
-	sdev = scsi_alloc_sdev(shost, 0, shost->this_id, 0);
+	sdev = scsi_alloc_sdev(shost, 0, shost->this_id, 0, NULL);
 	if (sdev) {
 		sdev->borken = 0;
 	}
diff -Nru a/drivers/scsi/scsi_syms.c b/drivers/scsi/scsi_syms.c
--- a/drivers/scsi/scsi_syms.c	2004-10-18 14:56:31 -07:00
+++ b/drivers/scsi/scsi_syms.c	2004-10-18 14:56:31 -07:00
@@ -69,11 +69,9 @@
 EXPORT_SYMBOL(scsi_get_host_dev);
 EXPORT_SYMBOL(scsi_free_host_dev);
 
-EXPORT_SYMBOL(scsi_sleep);
-
 EXPORT_SYMBOL(scsi_io_completion);
 
-EXPORT_SYMBOL(scsi_add_device);
+EXPORT_SYMBOL(__scsi_add_device);
 EXPORT_SYMBOL(scsi_remove_device);
 EXPORT_SYMBOL(scsi_device_cancel);
 
diff -Nru a/drivers/scsi/scsi_sysfs.c b/drivers/scsi/scsi_sysfs.c
--- a/drivers/scsi/scsi_sysfs.c	2004-10-18 14:56:17 -07:00
+++ b/drivers/scsi/scsi_sysfs.c	2004-10-18 14:56:17 -07:00
@@ -525,8 +525,11 @@
  **/
 void scsi_remove_device(struct scsi_device *sdev)
 {
+	struct Scsi_Host *shost = sdev->host;
+
+	down(&shost->scan_mutex);
 	if (scsi_device_set_state(sdev, SDEV_CANCEL) != 0)
-		return;
+		goto out;
 
 	class_device_unregister(&sdev->sdev_classdev);
 	if (sdev->transport_classdev.class)
@@ -538,6 +541,9 @@
 	if (sdev->host->transportt->cleanup)
 		sdev->host->transportt->cleanup(sdev);
 	put_device(&sdev->sdev_gendev);
+
+out:
+	up(&shost->scan_mutex);
 }
 
 int scsi_register_driver(struct device_driver *drv)
diff -Nru a/drivers/scsi/scsiiom.c b/drivers/scsi/scsiiom.c
--- a/drivers/scsi/scsiiom.c	2004-10-18 14:55:54 -07:00
+++ b/drivers/scsi/scsiiom.c	2004-10-18 14:55:54 -07:00
@@ -213,8 +213,17 @@
 }
 #endif
 
+
+static void __inline__
+dc390_InvalidCmd(struct dc390_acb* pACB)
+{
+	if (pACB->pActiveDCB->pActiveSRB->SRBState & (SRB_START_ | SRB_MSGOUT))
+		DC390_write8(ScsiCmd, CLEAR_FIFO_CMD);
+}
+
+
 static irqreturn_t __inline__
-DC390_Interrupt( int irq, void *dev_id, struct pt_regs *regs)
+DC390_Interrupt(int irq, void *dev_id, struct pt_regs *regs)
 {
     struct dc390_acb *pACB, *pACB2;
     struct dc390_dcb *pDCB;
@@ -594,7 +603,7 @@
 }
 
 /* abort command */
-static void __inline__
+static void
 dc390_EnableMsgOut_Abort ( struct dc390_acb* pACB, struct dc390_srb* pSRB )
 {
     pSRB->MsgOutBuf[0] = ABORT; 
@@ -890,14 +899,22 @@
 
     if (pSRB == pACB->pTmpSRB)
     {
-	if (pDCB) printk (KERN_ERR "DC390: pSRB == pTmpSRB! (TagQ Error?) (%02i-%i)\n",
-			  pDCB->TargetID, pDCB->TargetLUN);
-	else printk (KERN_ERR "DC390: pSRB == pTmpSRB! (TagQ Error?) (DCB 0!)\n");
-
-	pSRB->pSRBDCB = pDCB;
-	dc390_EnableMsgOut_Abort (pACB, pSRB);
-	if (pDCB) pDCB->DCBFlag |= ABORT_DEV;
-	return;
+	if (pDCB)
+		printk(KERN_ERR "DC390: pSRB == pTmpSRB! (TagQ Error?) (%02i-%i)\n", pDCB->TargetID, pDCB->TargetLUN);
+	else
+		printk(KERN_ERR "DC390: pSRB == pTmpSRB! (TagQ Error?) (DCB 0!)\n");
+
+	/* Try to recover - some broken disks react badly to tagged INQUIRY */
+	if (pDCB && pACB->scan_devices && pDCB->GoingSRBCnt == 1) {
+		pSRB = pDCB->pGoingSRB;
+		pDCB->pActiveSRB = pSRB;
+	} else {
+		pSRB->pSRBDCB = pDCB;
+		dc390_EnableMsgOut_Abort(pACB, pSRB);
+		if (pDCB)
+			pDCB->DCBFlag |= ABORT_DEV;
+		return;
+	}
     }
 
     if( pSRB->SGIndex < pSRB->SGcount )
@@ -1138,7 +1155,7 @@
      }
     DC390_write8 (ScsiCmd, EN_SEL_RESEL);
     pSRB = pDCB->pActiveSRB;
-    pACB->pActiveDCB = 0;
+    pACB->pActiveDCB = NULL;
     pSRB->ScsiPhase = SCSI_NOP0;
     if( pSRB->SRBState & SRB_UNEXPECT_RESEL )
     {
@@ -1158,7 +1175,7 @@
 	    dc390_Free_insert (pACB, pSRB);
 	    pSRB = psrb;
 	}
-	pDCB->pGoingSRB = 0;
+	pDCB->pGoingSRB = NULL;
 	dc390_Waiting_process (pACB);
     }
     else
@@ -1187,7 +1204,7 @@
 	{
 disc1:
 	    dc390_freetag (pDCB, pSRB);
-	    pDCB->pActiveSRB = 0;
+	    pDCB->pActiveSRB = NULL;
 	    pSRB->SRBState = SRB_FREE;
 	    dc390_SRBdone( pACB, pDCB, pSRB);
 	}
@@ -1325,6 +1342,35 @@
 }
 
 
+static void __inline__
+dc390_RequestSense(struct dc390_acb* pACB, struct dc390_dcb* pDCB, struct dc390_srb* pSRB)
+{
+	struct scsi_cmnd *pcmd;
+
+	pcmd = pSRB->pcmd;
+
+	REMOVABLEDEBUG(printk(KERN_INFO "DC390: RequestSense(Cmd %02x, Id %02x, LUN %02x)\n",\
+			      pcmd->cmnd[0], pDCB->TargetID, pDCB->TargetLUN));
+
+	pSRB->SRBFlag |= AUTO_REQSENSE;
+	pSRB->SavedSGCount = pcmd->use_sg;
+	pSRB->SavedTotXLen = pSRB->TotalXferredLen;
+	pSRB->AdaptStatus = 0;
+	pSRB->TargetStatus = 0; /* CHECK_CONDITION<<1; */
+
+	/* We are called from SRBdone, original PCI mapping has been removed
+	 * already, new one is set up from StartSCSI */
+	pSRB->SGIndex = 0;
+
+	pSRB->TotalXferredLen = 0;
+	pSRB->SGToBeXferLen = 0;
+	if (dc390_StartSCSI(pACB, pDCB, pSRB)) {
+		dc390_Going_to_Waiting(pDCB, pSRB);
+		dc390_waiting_timer(pACB, HZ/5);
+	}
+}
+
+
 static void
 dc390_SRBdone( struct dc390_acb* pACB, struct dc390_dcb* pDCB, struct dc390_srb* pSRB )
 {
@@ -1352,26 +1398,7 @@
 	pSRB->SRBFlag &= ~AUTO_REQSENSE;
 	pSRB->AdaptStatus = 0;
 	pSRB->TargetStatus = CHECK_CONDITION << 1;
-#ifdef DC390_REMOVABLEDEBUG
-	switch (pcmd->sense_buffer[2] & 0x0f)
-	{	    
-	 case NOT_READY: printk (KERN_INFO "DC390: ReqSense: NOT_READY (Cmnd = 0x%02x, Dev = %i-%i, Stat = %i, Scan = %i)\n",
-				 pcmd->cmnd[0], pDCB->TargetID, pDCB->TargetLUN,
-				 status, pACB->scan_devices); break;
-	 case UNIT_ATTENTION: printk (KERN_INFO "DC390: ReqSense: UNIT_ATTENTION (Cmnd = 0x%02x, Dev = %i-%i, Stat = %i, Scan = %i)\n",
-				      pcmd->cmnd[0], pDCB->TargetID, pDCB->TargetLUN,
-				      status, pACB->scan_devices); break;
-	 case ILLEGAL_REQUEST: printk (KERN_INFO "DC390: ReqSense: ILLEGAL_REQUEST (Cmnd = 0x%02x, Dev = %i-%i, Stat = %i, Scan = %i)\n",
-				       pcmd->cmnd[0], pDCB->TargetID, pDCB->TargetLUN,
-				       status, pACB->scan_devices); break;
-	 case MEDIUM_ERROR: printk (KERN_INFO "DC390: ReqSense: MEDIUM_ERROR (Cmnd = 0x%02x, Dev = %i-%i, Stat = %i, Scan = %i)\n",
-				    pcmd->cmnd[0], pDCB->TargetID, pDCB->TargetLUN,
-				    status, pACB->scan_devices); break;
-	 case HARDWARE_ERROR: printk (KERN_INFO "DC390: ReqSense: HARDWARE_ERROR (Cmnd = 0x%02x, Dev = %i-%i, Stat = %i, Scan = %i)\n",
-				      pcmd->cmnd[0], pDCB->TargetID, pDCB->TargetLUN,
-				      status, pACB->scan_devices); break;
-	}
-#endif
+
 	//pcmd->result = MK_RES(DRIVER_SENSE,DID_OK,0,status);
 	if (status == (CHECK_CONDITION << 1))
 	{
@@ -1525,23 +1552,6 @@
 	    pDCB->Inquiry7 = ptr->Flags;
 
 ckc_e:
-    if( pACB->scan_devices )
-    {
-	if( pcmd->cmnd[0] == TEST_UNIT_READY ||
-	    pcmd->cmnd[0] == INQUIRY)
-	{
-#ifdef DC390_DEBUG0
-	    printk (KERN_INFO "DC390: %s: result: %08x", 
-		    (pcmd->cmnd[0] == INQUIRY? "INQUIRY": "TEST_UNIT_READY"),
-		    pcmd->result);
-	    if (pcmd->result & (DRIVER_SENSE << 24)) printk (" (sense: %02x %02x %02x %02x)\n",
-				   pcmd->sense_buffer[0], pcmd->sense_buffer[1],
-				   pcmd->sense_buffer[2], pcmd->sense_buffer[3]);
-	    else printk ("\n");
-#endif
-	}
-    }
-
     if( pcmd->cmnd[0] == INQUIRY && 
 	(pcmd->result == (DID_OK << 16) || status_byte(pcmd->result) & CHECK_CONDITION) )
      {
@@ -1586,18 +1596,6 @@
 	    psrb2 = psrb->pNextSRB;
 	    pcmd = psrb->pcmd;
 	    dc390_Free_insert (pACB, psrb);
-#ifndef USE_NEW_EH
-	    /* New EH will crash on being given timed out cmnds */
-	    if (pcmd == cmd)
-		pcmd->result = MK_RES(0,DID_ABORT,0,0);
-	    else
-		pcmd->result = MK_RES(0,DID_RESET,0,0);
-
-/*	    ReleaseSRB( pDCB, pSRB ); */
-
-	    DEBUG0(printk (KERN_DEBUG "DC390: DoingSRB_Done: done pid %li\n", pcmd->pid));
-	    pcmd->scsi_done( pcmd );
-#endif	
 	    psrb  = psrb2;
 	}
 	pdcb->GoingSRBCnt = 0;
@@ -1646,59 +1644,11 @@
 	pACB->ACBFlag |= RESET_DETECT;
 
 	dc390_ResetDevParam( pACB );
-	dc390_DoingSRB_Done( pACB, 0 );
+	dc390_DoingSRB_Done( pACB, NULL );
 	//dc390_RecoverSRB( pACB );
 	pACB->pActiveDCB = NULL;
 	pACB->ACBFlag = 0;
 	dc390_Waiting_process( pACB );
     }
     return;
-}
-
-
-static void __inline__
-dc390_RequestSense( struct dc390_acb* pACB, struct dc390_dcb* pDCB, struct dc390_srb* pSRB )
-{
-    struct scsi_cmnd *pcmd;
-
-    pcmd = pSRB->pcmd;
-
-    REMOVABLEDEBUG(printk (KERN_INFO "DC390: RequestSense (Cmd %02x, Id %02x, LUN %02x)\n",\
-	    pcmd->cmnd[0], pDCB->TargetID, pDCB->TargetLUN));
-
-    pSRB->SRBFlag |= AUTO_REQSENSE;
-    //pSRB->Segment0[0] = (u32) pSRB->CmdBlock[0];
-    //pSRB->Segment0[1] = (u32) pSRB->CmdBlock[4];
-    //pSRB->Segment1[0] = ((u32)(pcmd->cmd_len) << 8) + pSRB->SGcount;
-    //pSRB->Segment1[1] = pSRB->TotalXferredLen;
-    pSRB->SavedSGCount = pcmd->use_sg;
-    pSRB->SavedTotXLen = pSRB->TotalXferredLen;
-    pSRB->AdaptStatus = 0;
-    pSRB->TargetStatus = 0; /* CHECK_CONDITION<<1; */
-
-    /* We are called from SRBdone, original PCI mapping has been removed
-     * already, new one is set up from StartSCSI */
-    pSRB->SGIndex = 0;
-
-    //pSRB->CmdBlock[0] = REQUEST_SENSE;
-    //pSRB->CmdBlock[1] = pDCB->TargetLUN << 5;
-    //(u16) pSRB->CmdBlock[2] = 0;
-    //(u16) pSRB->CmdBlock[4] = sizeof(pcmd->sense_buffer);
-    //pSRB->ScsiCmdLen = 6;
-
-    pSRB->TotalXferredLen = 0;
-    pSRB->SGToBeXferLen = 0;
-    if( dc390_StartSCSI( pACB, pDCB, pSRB ) ) {
-	dc390_Going_to_Waiting ( pDCB, pSRB );
-	dc390_waiting_timer (pACB, HZ/5);
-    }
-}
-
-
-
-static void __inline__
-dc390_InvalidCmd( struct dc390_acb* pACB )
-{
-    if( pACB->pActiveDCB->pActiveSRB->SRBState & (SRB_START_+SRB_MSGOUT) )
-	DC390_write8 (ScsiCmd, CLEAR_FIFO_CMD);
 }
diff -Nru a/drivers/scsi/sd.c b/drivers/scsi/sd.c
--- a/drivers/scsi/sd.c	2004-10-18 14:56:49 -07:00
+++ b/drivers/scsi/sd.c	2004-10-18 14:56:49 -07:00
@@ -42,6 +42,7 @@
 #include <linux/genhd.h>
 #include <linux/hdreg.h>
 #include <linux/errno.h>
+#include <linux/idr.h>
 #include <linux/interrupt.h>
 #include <linux/init.h>
 #include <linux/blkdev.h>
@@ -62,12 +63,18 @@
 
 #include "scsi_logging.h"
 
-
 /*
- * Remaining dev_t-handling stuff
+ * More than enough for everybody ;)  The huge number of majors
+ * is a leftover from 16bit dev_t days, we don't really need that
+ * much numberspace.
  */
 #define SD_MAJORS	16
-#define SD_DISKS	32768	/* anything between 256 and 262144 */
+
+/*
+ * This is limited by the naming scheme enforced in sd_probe,
+ * add another character to it if you really need more disks.
+ */
+#define SD_MAX_DISKS	(((26 * 26) + 26 + 1) * 26)
 
 /*
  * Time out in seconds for disks and Magneto-opticals (which are slower).
@@ -96,8 +103,7 @@
 	unsigned	RCD : 1;	/* state of disk RCD bit, unused */
 };
 
-
-static unsigned long sd_index_bits[SD_DISKS / BITS_PER_LONG];
+static DEFINE_IDR(sd_index_idr);
 static spinlock_t sd_index_lock = SPIN_LOCK_UNLOCKED;
 
 /* This semaphore is used to mediate the 0->1 reference get in the
@@ -113,6 +119,7 @@
 static void sd_shutdown(struct device *dev);
 static void sd_rescan(struct device *);
 static int sd_init_command(struct scsi_cmnd *);
+static int sd_issue_flush(struct device *, sector_t *);
 static void sd_read_capacity(struct scsi_disk *sdkp, char *diskname,
 		 struct scsi_request *SRpnt, unsigned char *buffer);
 
@@ -126,9 +133,11 @@
 	},
 	.rescan			= sd_rescan,
 	.init_command		= sd_init_command,
+	.issue_flush		= sd_issue_flush,
 };
 
-/* Device no to disk mapping:
+/*
+ * Device no to disk mapping:
  * 
  *       major         disc2     disc  p1
  *   |............|.............|....|....| <- dev_t
@@ -141,7 +150,6 @@
  * As we stay compatible with our numbering scheme, we can reuse 
  * the well-know SCSI majors 8, 65--71, 136--143.
  */
-
 static int sd_major(int major_idx)
 {
 	switch (major_idx) {
@@ -157,14 +165,6 @@
 	}
 }
 
-static unsigned int make_sd_dev(unsigned int sd_nr, unsigned int part)
-{
-	return  (part & 0xf) | ((sd_nr & 0xf) << 4) |
-		(sd_major((sd_nr & 0xf0) >> 4) << 20) | (sd_nr & 0xfff00);
-}
-
-/* reverse mapping dev -> (sd_nr, part) not currently needed */
-
 #define to_scsi_disk(obj) container_of(obj,struct scsi_disk,kref)
 
 static inline struct scsi_disk *scsi_disk(struct gendisk *disk)
@@ -180,16 +180,14 @@
 	if (disk->private_data == NULL)
 		goto out;
 	sdkp = scsi_disk(disk);
-	if (!kref_get(&sdkp->kref))
-		goto out_sdkp;
+	kref_get(&sdkp->kref);
 	if (scsi_device_get(sdkp->device))
 		goto out_put;
 	up(&sd_ref_sem);
 	return sdkp;
 
  out_put:
-	kref_put(&sdkp->kref);
- out_sdkp:
+	kref_put(&sdkp->kref, scsi_disk_release);
 	sdkp = NULL;
  out:
 	up(&sd_ref_sem);
@@ -200,7 +198,7 @@
 {
 	down(&sd_ref_sem);
 	scsi_device_put(sdkp->device);
-	kref_put(&sdkp->kref);
+	kref_put(&sdkp->kref, scsi_disk_release);
 	up(&sd_ref_sem);
 }
 
@@ -648,7 +646,7 @@
 	 */
 	retval = -ENODEV;
 	if (scsi_block_when_processing_errors(sdp))
-		retval = scsi_ioctl(sdp, SCSI_IOCTL_TEST_UNIT_READY, NULL);
+		retval = scsi_test_unit_ready(sdp, SD_TIMEOUT, SD_MAX_RETRIES);
 
 	/*
 	 * Unable to test, unit probably not ready.   This usually
@@ -676,6 +674,62 @@
 	return 1;
 }
 
+static int sd_sync_cache(struct scsi_device *sdp)
+{
+	struct scsi_request *sreq;
+	int retries, res;
+
+	if (!scsi_device_online(sdp))
+		return -ENODEV;
+
+	sreq = scsi_allocate_request(sdp, GFP_KERNEL);
+	if (!sreq) {
+		printk("FAILED\n  No memory for request\n");
+		return -ENOMEM;
+	}
+
+	sreq->sr_data_direction = DMA_NONE;
+	for (retries = 3; retries > 0; --retries) {
+		unsigned char cmd[10] = { 0 };
+
+		cmd[0] = SYNCHRONIZE_CACHE;
+		/*
+		 * Leave the rest of the command zero to indicate
+		 * flush everything.
+		 */
+		scsi_wait_req(sreq, cmd, NULL, 0, SD_TIMEOUT, SD_MAX_RETRIES);
+		if (sreq->sr_result == 0)
+			break;
+	}
+
+	res = sreq->sr_result;
+	if (res) {
+		printk(KERN_WARNING "FAILED\n  status = %x, message = %02x, "
+				    "host = %d, driver = %02x\n  ",
+				    status_byte(res), msg_byte(res),
+				    host_byte(res), driver_byte(res));
+			if (driver_byte(res) & DRIVER_SENSE)
+				scsi_print_req_sense("sd", sreq);
+	}
+
+	scsi_release_request(sreq);
+	return res;
+}
+
+static int sd_issue_flush(struct device *dev, sector_t *error_sector)
+{
+	struct scsi_device *sdp = to_scsi_device(dev);
+	struct scsi_disk *sdkp = dev_get_drvdata(dev);
+
+	if (!sdkp)
+               return -ENODEV;
+
+	if (!sdkp->WCE)
+		return 0;
+
+	return sd_sync_cache(sdp);
+}
+
 static void sd_rescan(struct device *dev)
 {
 	struct scsi_disk *sdkp = dev_get_drvdata(dev);
@@ -1347,7 +1401,7 @@
 	struct scsi_disk *sdkp;
 	struct gendisk *gd;
 	u32 index;
-	int error, devno;
+	int error;
 
 	error = -ENODEV;
 	if ((sdp->type != TYPE_DISK) && (sdp->type != TYPE_MOD))
@@ -1362,27 +1416,23 @@
 		goto out;
 
 	memset (sdkp, 0, sizeof(*sdkp));
-	kref_init(&sdkp->kref, scsi_disk_release);
+	kref_init(&sdkp->kref);
 
-	/* Note: We can accomodate 64 partitions, but the genhd code
-	 * assumes partitions allocate consecutive minors, which they don't.
-	 * So for now stay with max 16 partitions and leave two spare bits. 
-	 * Later, we may change the genhd code and the alloc_disk() call
-	 * and the ->minors assignment here. 	KG, 2004-02-10
-	 */ 
 	gd = alloc_disk(16);
 	if (!gd)
 		goto out_free;
 
+	if (!idr_pre_get(&sd_index_idr, GFP_KERNEL))
+		goto out_put;
+
 	spin_lock(&sd_index_lock);
-	index = find_first_zero_bit(sd_index_bits, SD_DISKS);
-	if (index == SD_DISKS) {
-		spin_unlock(&sd_index_lock);
+	error = idr_get_new(&sd_index_idr, NULL, &index);
+	spin_unlock(&sd_index_lock);
+
+	if (index >= SD_MAX_DISKS)
 		error = -EBUSY;
+	if (error)
 		goto out_put;
-	}
-	__set_bit(index, sd_index_bits);
-	spin_unlock(&sd_index_lock);
 
 	sdkp->device = sdp;
 	sdkp->driver = &sd_template;
@@ -1397,15 +1447,14 @@
 			sdp->timeout = SD_MOD_TIMEOUT;
 	}
 
-	devno = make_sd_dev(index, 0);
-	gd->major = MAJOR(devno);
-	gd->first_minor = MINOR(devno);
+	gd->major = sd_major((index & 0xf0) >> 4);
+	gd->first_minor = ((index & 0xf) << 4) | (index & 0xfff00);
 	gd->minors = 16;
 	gd->fops = &sd_fops;
 
 	if (index < 26) {
 		sprintf(gd->disk_name, "sd%c", 'a' + index % 26);
-	} else if (index < (26*27)) {
+	} else if (index < (26 + 1) * 26) {
 		sprintf(gd->disk_name, "sd%c%c",
 			'a' + index / 26 - 1,'a' + index % 26);
 	} else {
@@ -1464,7 +1513,7 @@
 	del_gendisk(sdkp->disk);
 	sd_shutdown(dev);
 	down(&sd_ref_sem);
-	kref_put(&sdkp->kref);
+	kref_put(&sdkp->kref, scsi_disk_release);
 	up(&sd_ref_sem);
 
 	return 0;
@@ -1485,7 +1534,7 @@
 	struct gendisk *disk = sdkp->disk;
 	
 	spin_lock(&sd_index_lock);
-	clear_bit(sdkp->index, sd_index_bits);
+	idr_remove(&sd_index_idr, sdkp->index);
 	spin_unlock(&sd_index_lock);
 
 	disk->private_data = NULL;
@@ -1503,52 +1552,17 @@
 static void sd_shutdown(struct device *dev)
 {
 	struct scsi_device *sdp = to_scsi_device(dev);
-	struct scsi_disk *sdkp;
-	struct scsi_request *sreq;
-	int retries, res;
+	struct scsi_disk *sdkp = dev_get_drvdata(dev);
 
-	sdkp = dev_get_drvdata(dev);
 	if (!sdkp)
-               return;         /* this can happen */
+		return;         /* this can happen */
 
-	if (!scsi_device_online(sdp) || !sdkp->WCE)
+	if (!sdkp->WCE)
 		return;
 
-	printk(KERN_NOTICE "Synchronizing SCSI cache for disk %s: ",
+	printk(KERN_NOTICE "Synchronizing SCSI cache for disk %s: \n",
 			sdkp->disk->disk_name);
-
-	sreq = scsi_allocate_request(sdp, GFP_KERNEL);
-	if (!sreq) {
-		printk("FAILED\n  No memory for request\n");
-		return;
-	}
-
-	sreq->sr_data_direction = DMA_NONE;
-	for (retries = 3; retries > 0; --retries) {
-		unsigned char cmd[10] = { 0 };
-
-		cmd[0] = SYNCHRONIZE_CACHE;
-		/*
-		 * Leave the rest of the command zero to indicate
-		 * flush everything.
-		 */
-		scsi_wait_req(sreq, cmd, NULL, 0, SD_TIMEOUT, SD_MAX_RETRIES);
-		if (sreq->sr_result == 0)
-			break;
-	}
-
-	res = sreq->sr_result;
-	if (res) {
-		printk(KERN_WARNING "FAILED\n  status = %x, message = %02x, "
-				    "host = %d, driver = %02x\n  ",
-				    status_byte(res), msg_byte(res),
-				    host_byte(res), driver_byte(res));
-			if (driver_byte(res) & DRIVER_SENSE)
-				scsi_print_req_sense("sd", sreq);
-	}
-	
-	scsi_release_request(sreq);
-	printk("\n");
+	sd_sync_cache(sdp);
 }	
 
 /**
diff -Nru a/drivers/scsi/sg.c b/drivers/scsi/sg.c
--- a/drivers/scsi/sg.c	2004-10-18 14:56:29 -07:00
+++ b/drivers/scsi/sg.c	2004-10-18 14:56:29 -07:00
@@ -47,8 +47,9 @@
 #include <linux/devfs_fs_kernel.h>
 #include <linux/cdev.h>
 #include <linux/seq_file.h>
-
 #include <linux/blkdev.h>
+#include <linux/delay.h>
+
 #include "scsi.h"
 #include <scsi/scsi_host.h>
 #include <scsi/scsi_driver.h>
@@ -205,8 +206,6 @@
 static Sg_request *sg_add_request(Sg_fd * sfp);
 static int sg_remove_request(Sg_fd * sfp, Sg_request * srp);
 static int sg_res_in_use(Sg_fd * sfp);
-static int sg_ms_to_jif(unsigned int msecs);
-static inline unsigned sg_jif_to_ms(int jifs);
 static int sg_allow_access(unsigned char opcode, char dev_type);
 static int sg_build_direct(Sg_request * srp, Sg_fd * sfp, int dxfer_len);
 static Sg_device *sg_get_dev(int dev);
@@ -611,7 +610,7 @@
 			return -EBUSY;	/* reserve buffer already being used */
 		}
 	}
-	timeout = sg_ms_to_jif(srp->header.timeout);
+	timeout = msecs_to_jiffies(srp->header.timeout);
 	if ((!hp->cmdp) || (hp->cmd_len < 6) || (hp->cmd_len > sizeof (cmnd))) {
 		sg_remove_request(sfp, srp);
 		return -EMSGSIZE;
@@ -719,19 +718,6 @@
 	return 0;
 }
 
-static inline unsigned
-sg_jif_to_ms(int jifs)
-{
-	if (jifs <= 0)
-		return 0U;
-	else {
-		unsigned int j = (unsigned int) jifs;
-		return (j <
-			(UINT_MAX / 1000)) ? ((j * 1000) / HZ) : ((j / HZ) *
-								  1000);
-	}
-}
-
 static int
 sg_ioctl(struct inode *inode, struct file *filp,
 	 unsigned int cmd_in, unsigned long arg)
@@ -941,7 +927,7 @@
 					    srp->header.driver_status;
 					rinfo[val].duration =
 					    srp->done ? srp->header.duration :
-					    sg_jif_to_ms(
+					    jiffies_to_msecs(
 						jiffies - srp->header.duration);
 					rinfo[val].orphan = srp->orphan;
 					rinfo[val].sg_io_owned = srp->sg_io_owned;
@@ -1263,7 +1249,7 @@
 	srp->header.resid = SCpnt->resid;
 	/* N.B. unit of duration changes here from jiffies to millisecs */
 	srp->header.duration =
-	    sg_jif_to_ms(jiffies - (int) srp->header.duration);
+	    jiffies_to_msecs(jiffies - srp->header.duration);
 	if (0 != SRpnt->sr_result) {
 		memcpy(srp->sense_b, SRpnt->sr_sense_buffer,
 		       sizeof (srp->sense_b));
@@ -1547,7 +1533,7 @@
 	}
 
 	if (delay)
-		scsi_sleep(2);	/* dirty detach so delay device destruction */
+		msleep(10);	/* dirty detach so delay device destruction */
 }
 
 /* Set 'perm' (4th argument) to 0 to disable module_param's definition
@@ -2587,17 +2573,6 @@
 	free_pages((unsigned long) buff, order);
 }
 
-static int
-sg_ms_to_jif(unsigned int msecs)
-{
-	if ((UINT_MAX / 2U) < msecs)
-		return INT_MAX;	/* special case, set largest possible */
-	else
-		return ((int) msecs <
-			(INT_MAX / 1000)) ? (((int) msecs * HZ) / 1000)
-		    : (((int) msecs / 1000) * HZ);
-}
-
 static unsigned char allow_ops[] = { TEST_UNIT_READY, REQUEST_SENSE,
 	INQUIRY, READ_CAPACITY, READ_BUFFER, READ_6, READ_10, READ_12,
 	MODE_SENSE, MODE_SENSE_10, LOG_SENSE
@@ -2960,7 +2935,7 @@
 	for (k = 0; (fp = sg_get_nth_sfp(sdp, k)); ++k) {
 		seq_printf(s, "   FD(%d): timeout=%dms bufflen=%d "
 			   "(res)sgat=%d low_dma=%d\n", k + 1,
-			   sg_jif_to_ms(fp->timeout),
+			   jiffies_to_msecs(fp->timeout),
 			   fp->reserve.bufflen,
 			   (int) fp->reserve.k_use_sg,
 			   (int) fp->low_dma);
@@ -2996,8 +2971,8 @@
 				seq_printf(s, " dur=%d", hp->duration);
 			else
 				seq_printf(s, " t_o/elap=%d/%d",
-				  new_interface ? hp->timeout : sg_jif_to_ms(fp->timeout),
-				  sg_jif_to_ms(hp->duration ? (jiffies - hp->duration) : 0));
+				  new_interface ? hp->timeout : jiffies_to_msecs(fp->timeout),
+				  jiffies_to_msecs(hp->duration ? (jiffies - hp->duration) : 0));
 			seq_printf(s, "ms sgat=%d op=0x%02x\n", usg,
 				   (int) srp->data.cmd_opcode);
 		}
diff -Nru a/drivers/scsi/sr.c b/drivers/scsi/sr.c
--- a/drivers/scsi/sr.c	2004-10-18 14:57:19 -07:00
+++ b/drivers/scsi/sr.c	2004-10-18 14:57:19 -07:00
@@ -140,15 +140,13 @@
 	if (disk->private_data == NULL)
 		goto out;
 	cd = scsi_cd(disk);
-	if (!kref_get(&cd->kref))
-		goto out_null;
+	kref_get(&cd->kref);
 	if (scsi_device_get(cd->device))
 		goto out_put;
 	goto out;
 
  out_put:
-	kref_put(&cd->kref);
- out_null:
+	kref_put(&cd->kref, sr_kref_release);
 	cd = NULL;
  out:
 	up(&sr_ref_sem);
@@ -159,7 +157,7 @@
 {
 	down(&sr_ref_sem);
 	scsi_device_put(cd->device);
-	kref_put(&cd->kref);
+	kref_put(&cd->kref, sr_kref_release);
 	up(&sr_ref_sem);
 }
 
@@ -183,7 +181,7 @@
 		return -EINVAL;
 	}
 
-	retval = scsi_ioctl(cd->device, SCSI_IOCTL_TEST_UNIT_READY, NULL);
+	retval = scsi_test_unit_ready(cd->device, SR_TIMEOUT, MAX_RETRIES);
 	if (retval) {
 		/* Unable to test, unit probably not ready.  This usually
 		 * means there is no disc in the drive.  Mark as changed,
@@ -576,7 +574,7 @@
 		goto fail;
 	memset(cd, 0, sizeof(*cd));
 
-	kref_init(&cd->kref, sr_kref_release);
+	kref_init(&cd->kref);
 
 	disk = alloc_disk(1);
 	if (!disk)
@@ -937,7 +935,7 @@
 	del_gendisk(cd->disk);
 
 	down(&sr_ref_sem);
-	kref_put(&cd->kref);
+	kref_put(&cd->kref, sr_kref_release);
 	up(&sr_ref_sem);
 
 	return 0;
diff -Nru a/drivers/scsi/sr_ioctl.c b/drivers/scsi/sr_ioctl.c
--- a/drivers/scsi/sr_ioctl.c	2004-10-18 14:56:33 -07:00
+++ b/drivers/scsi/sr_ioctl.c	2004-10-18 14:56:33 -07:00
@@ -7,6 +7,7 @@
 #include <linux/blkdev.h>
 #include <linux/blkpg.h>
 #include <linux/cdrom.h>
+#include <linux/delay.h>
 #include <asm/io.h>
 #include <asm/uaccess.h>
 
@@ -131,7 +132,7 @@
 					printk(KERN_INFO "%s: CDROM not ready yet.\n", cd->cdi.name);
 				if (retries++ < 10) {
 					/* sleep 2 sec and try again */
-					scsi_sleep(2 * HZ);
+					ssleep(2);
 					goto retry;
 				} else {
 					/* 20 secs are enough? */
diff -Nru a/drivers/scsi/sym53c8xx_2/sym_defs.h b/drivers/scsi/sym53c8xx_2/sym_defs.h
--- a/drivers/scsi/sym53c8xx_2/sym_defs.h	2004-10-18 14:56:28 -07:00
+++ b/drivers/scsi/sym53c8xx_2/sym_defs.h	2004-10-18 14:56:28 -07:00
@@ -53,6 +53,9 @@
 #ifndef SYM_DEFS_H
 #define SYM_DEFS_H
 
+#define SYM_VERSION "2.1.18j"
+#define SYM_DRIVER_NAME	"sym-" SYM_VERSION
+
 /*
  *  Vendor.
  */
diff -Nru a/drivers/scsi/sym53c8xx_2/sym_glue.c b/drivers/scsi/sym53c8xx_2/sym_glue.c
--- a/drivers/scsi/sym53c8xx_2/sym_glue.c	2004-10-18 14:57:19 -07:00
+++ b/drivers/scsi/sym53c8xx_2/sym_glue.c	2004-10-18 14:57:19 -07:00
@@ -143,13 +143,6 @@
 }
 
 /*
- *  Driver host data structure.
- */
-struct host_data {
-	struct sym_hcb *ncb;
-};
-
-/*
  *  Used by the eh thread to wait for command completion.
  *  It is allocated on the eh thread stack.
  */
@@ -220,47 +213,12 @@
 	return use_sg;
 }
 
-static void __sync_scsi_data_for_cpu(struct pci_dev *pdev, struct scsi_cmnd *cmd)
-{
-	int dma_dir = cmd->sc_data_direction;
-
-	switch(SYM_UCMD_PTR(cmd)->data_mapped) {
-	case 2:
-		pci_dma_sync_sg_for_cpu(pdev, cmd->buffer, cmd->use_sg, dma_dir);
-		break;
-	case 1:
-		pci_dma_sync_single_for_cpu(pdev, SYM_UCMD_PTR(cmd)->data_mapping,
-					    cmd->request_bufflen, dma_dir);
-		break;
-	}
-}
-
-static void __sync_scsi_data_for_device(struct pci_dev *pdev, struct scsi_cmnd *cmd)
-{
-	int dma_dir = cmd->sc_data_direction;
-
-	switch(SYM_UCMD_PTR(cmd)->data_mapped) {
-	case 2:
-		pci_dma_sync_sg_for_device(pdev, cmd->buffer, cmd->use_sg, dma_dir);
-		break;
-	case 1:
-		pci_dma_sync_single_for_device(pdev, SYM_UCMD_PTR(cmd)->data_mapping,
-					       cmd->request_bufflen, dma_dir);
-		break;
-	}
-}
-
 #define unmap_scsi_data(np, cmd)	\
 		__unmap_scsi_data(np->s.device, cmd)
 #define map_scsi_single_data(np, cmd)	\
 		__map_scsi_single_data(np->s.device, cmd)
 #define map_scsi_sg_data(np, cmd)	\
 		__map_scsi_sg_data(np->s.device, cmd)
-#define sync_scsi_data_for_cpu(np, cmd)		\
-		__sync_scsi_data_for_cpu(np->s.device, cmd)
-#define sync_scsi_data_for_device(np, cmd)		\
-		__sync_scsi_data_for_device(np->s.device, cmd)
-
 /*
  *  Complete a pending CAM CCB.
  */
@@ -417,27 +375,6 @@
 
 
 /*
- *  Called on successfull INQUIRY response.
- */
-void sym_sniff_inquiry(struct sym_hcb *np, struct scsi_cmnd *cmd, int resid)
-{
-	int retv;
-
-	if (!cmd || cmd->use_sg)
-		return;
-
-	sync_scsi_data_for_cpu(np, cmd);
-	retv = __sym_sniff_inquiry(np, cmd->device->id, cmd->device->lun,
-				   (u_char *) cmd->request_buffer,
-				   cmd->request_bufflen - resid);
-	sync_scsi_data_for_device(np, cmd);
-	if (retv < 0)
-		return;
-	else if (retv)
-		sym_update_trans_settings(np, &np->target[cmd->device->id]);
-}
-
-/*
  *  Build the scatter/gather array for an I/O.
  */
 
@@ -730,14 +667,15 @@
  */
 static void sym_requeue_awaiting_cmds(struct sym_hcb *np)
 {
-	struct scsi_cmnd *cmd;
-	struct sym_ucmd *ucp = SYM_UCMD_PTR(cmd);
+	struct sym_ucmd *ucp;
 	SYM_QUEHEAD tmp_cmdq;
 	int sts;
 
 	sym_que_move(&np->s.wait_cmdq, &tmp_cmdq);
 
 	while ((ucp = (struct sym_ucmd *) sym_remque_head(&tmp_cmdq)) != 0) {
+		struct scsi_cmnd *cmd;
+
 		sym_insque_tail(&ucp->link_cmdq, &np->s.busy_cmdq);
 		cmd = SYM_SCMD_PTR(ucp);
 		sts = sym_queue_command(np, cmd);
@@ -1118,12 +1056,7 @@
 
 	np = ((struct host_data *) host->hostdata)->ncb;
 	tp = &np->target[device->id];
-
-	/*
-	 *  Get user settings for transfer parameters.
-	 */
-	tp->inq_byte7_valid = (INQ7_SYNC|INQ7_WIDE16);
-	sym_update_trans_settings(np, tp);
+	tp->sdev = device;
 
 	/*
 	 *  Allocate the LCB if not yet.
@@ -2283,6 +2216,7 @@
 }
 
 MODULE_LICENSE("Dual BSD/GPL");
+MODULE_VERSION(SYM_VERSION);
 
 /*
  * Driver host template.
@@ -2383,13 +2317,6 @@
 	struct sym_hcb *np = ((struct host_data *)sdev->host->hostdata)->ncb;
 	struct sym_tcb *tp = &np->target[sdev->id];
 
-	if (tp->tinfo.curr.options & PPR_OPT_DT) {
-		if (offset > np->maxoffs_dt)
-			offset = np->maxoffs_dt;
-	} else {
-		if (offset > np->maxoffs)
-			offset = np->maxoffs;
-	}
 	tp->tinfo.goal.offset = offset;
 }
 
@@ -2407,23 +2334,11 @@
 	struct sym_hcb *np = ((struct host_data *)sdev->host->hostdata)->ncb;
 	struct sym_tcb *tp = &np->target[sdev->id];
 
-	if (period <= 9 && np->minsync_dt) {
-		if (period < np->minsync_dt)
-			period = np->minsync_dt;
-		tp->tinfo.goal.options = PPR_OPT_DT;
-		tp->tinfo.goal.period = period;
-		if (!tp->tinfo.curr.offset ||
-					tp->tinfo.curr.offset > np->maxoffs_dt)
-			tp->tinfo.goal.offset = np->maxoffs_dt;
-	} else {
-		if (period < np->minsync)
-			period = np->minsync;
-		tp->tinfo.goal.options = 0;
-		tp->tinfo.goal.period = period;
-		if (!tp->tinfo.curr.offset ||
-					tp->tinfo.curr.offset > np->maxoffs)
-			tp->tinfo.goal.offset = np->maxoffs;
-	}
+	/* have to have DT for these transfers */
+	if (period <= np->minsync)
+		tp->tinfo.goal.options |= PPR_OPT_DT;
+
+	tp->tinfo.goal.period = period;
 }
 
 static void sym2_get_width(struct scsi_device *sdev)
@@ -2439,6 +2354,10 @@
 	struct sym_hcb *np = ((struct host_data *)sdev->host->hostdata)->ncb;
 	struct sym_tcb *tp = &np->target[sdev->id];
 
+	/* It is illegal to have DT set on narrow transfers */
+	if (width == 0)
+		tp->tinfo.goal.options &= ~PPR_OPT_DT;
+
 	tp->tinfo.goal.width = width;
 }
 
@@ -2455,17 +2374,10 @@
 	struct sym_hcb *np = ((struct host_data *)sdev->host->hostdata)->ncb;
 	struct sym_tcb *tp = &np->target[sdev->id];
 
-	if (!dt) {
-		/* if clearing DT, then we may need to reduce the
-		 * period and the offset */
-		if (tp->tinfo.curr.period < np->minsync)
-			tp->tinfo.goal.period = np->minsync;
-		if (tp->tinfo.curr.offset > np->maxoffs)
-			tp->tinfo.goal.offset = np->maxoffs;
-		tp->tinfo.goal.options &= ~PPR_OPT_DT;
-	} else {
+	if (dt)
 		tp->tinfo.goal.options |= PPR_OPT_DT;
-	}
+	else
+		tp->tinfo.goal.options &= ~PPR_OPT_DT;
 }
 	
 
diff -Nru a/drivers/scsi/sym53c8xx_2/sym_glue.h b/drivers/scsi/sym53c8xx_2/sym_glue.h
--- a/drivers/scsi/sym53c8xx_2/sym_glue.h	2004-10-18 14:57:04 -07:00
+++ b/drivers/scsi/sym53c8xx_2/sym_glue.h	2004-10-18 14:57:04 -07:00
@@ -90,7 +90,6 @@
 #define SYM_OPT_HANDLE_DIR_UNKNOWN
 #define SYM_OPT_HANDLE_DEVICE_QUEUEING
 #define SYM_OPT_NVRAM_PRE_READ
-#define SYM_OPT_SNIFF_INQUIRY
 #define SYM_OPT_LIMIT_COMMAND_REORDERING
 #define	SYM_OPT_ANNOUNCE_TRANSFER_RATE
 
@@ -289,32 +288,32 @@
  *  MEMORY mapped IO input / output
  */
 
-#define INB_OFF(o)        readb((char *)np->s.mmio_va + sym_offb(o))
-#define OUTB_OFF(o, val)  writeb((val), (char *)np->s.mmio_va + sym_offb(o))
+#define INB_OFF(o)        readb(np->s.mmio_va + sym_offb(o))
+#define OUTB_OFF(o, val)  writeb((val), np->s.mmio_va + sym_offb(o))
 
 #if	defined(__BIG_ENDIAN) && !defined(SYM_CONF_CHIP_BIG_ENDIAN)
 
-#define INW_OFF(o)        readw_l2b((char *)np->s.mmio_va + sym_offw(o))
-#define INL_OFF(o)        readl_l2b((char *)np->s.mmio_va + (o))
+#define INW_OFF(o)        readw_l2b(np->s.mmio_va + sym_offw(o))
+#define INL_OFF(o)        readl_l2b(np->s.mmio_va + (o))
 
-#define OUTW_OFF(o, val)  writew_b2l((val), (char *)np->s.mmio_va + sym_offw(o))
-#define OUTL_OFF(o, val)  writel_b2l((val), (char *)np->s.mmio_va + (o))
+#define OUTW_OFF(o, val)  writew_b2l((val), np->s.mmio_va + sym_offw(o))
+#define OUTL_OFF(o, val)  writel_b2l((val), np->s.mmio_va + (o))
 
 #elif	defined(__LITTLE_ENDIAN) && defined(SYM_CONF_CHIP_BIG_ENDIAN)
 
-#define INW_OFF(o)        readw_b2l((char *)np->s.mmio_va + sym_offw(o))
-#define INL_OFF(o)        readl_b2l((char *)np->s.mmio_va + (o))
+#define INW_OFF(o)        readw_b2l(np->s.mmio_va + sym_offw(o))
+#define INL_OFF(o)        readl_b2l(np->s.mmio_va + (o))
 
-#define OUTW_OFF(o, val)  writew_l2b((val), (char *)np->s.mmio_va + sym_offw(o))
-#define OUTL_OFF(o, val)  writel_l2b((val), (char *)np->s.mmio_va + (o))
+#define OUTW_OFF(o, val)  writew_l2b((val), np->s.mmio_va + sym_offw(o))
+#define OUTL_OFF(o, val)  writel_l2b((val), np->s.mmio_va + (o))
 
 #else
 
-#define INW_OFF(o)        readw_raw((char *)np->s.mmio_va + sym_offw(o))
-#define INL_OFF(o)        readl_raw((char *)np->s.mmio_va + (o))
+#define INW_OFF(o)        readw_raw(np->s.mmio_va + sym_offw(o))
+#define INL_OFF(o)        readl_raw(np->s.mmio_va + (o))
 
-#define OUTW_OFF(o, val)  writew_raw((val), (char *)np->s.mmio_va + sym_offw(o))
-#define OUTL_OFF(o, val)  writel_raw((val), (char *)np->s.mmio_va + (o))
+#define OUTW_OFF(o, val)  writew_raw((val), np->s.mmio_va + sym_offw(o))
+#define OUTL_OFF(o, val)  writel_raw((val), np->s.mmio_va + (o))
 
 #endif
 
@@ -391,8 +390,8 @@
 
 	struct Scsi_Host *host;
 
-	void *		mmio_va;	/* MMIO kernel virtual address	*/
-	void *		ram_va;		/* RAM  kernel virtual address	*/
+	void __iomem *	mmio_va;	/* MMIO kernel virtual address	*/
+	void __iomem *	ram_va;		/* RAM  kernel virtual address	*/
 	u_long		io_port;	/* IO port address cookie	*/
 	u_short		io_ws;		/* IO window size		*/
 	int		irq;		/* IRQ number			*/
@@ -424,7 +423,7 @@
 	int	irq;
 /* port and address fields to fit INB, OUTB macros */
 	u_long	io_port;
-	void *	mmio_va;
+	void __iomem *	mmio_va;
 	char	inst_name[16];
 };
 
@@ -437,6 +436,13 @@
 	struct sym_nvram *nvram;
 	u_short device_id;
 	u_char host_id;
+};
+
+/*
+ *  Driver host data structure.
+ */
+struct host_data {
+	struct sym_hcb *ncb;
 };
 
 /*
diff -Nru a/drivers/scsi/sym53c8xx_2/sym_hipd.c b/drivers/scsi/sym53c8xx_2/sym_hipd.c
--- a/drivers/scsi/sym53c8xx_2/sym_hipd.c	2004-10-18 14:55:53 -07:00
+++ b/drivers/scsi/sym53c8xx_2/sym_hipd.c	2004-10-18 14:55:53 -07:00
@@ -49,10 +49,6 @@
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  */
-
-#define SYM_VERSION "2.1.18j"
-#define SYM_DRIVER_NAME	"sym-" SYM_VERSION
-
 #include "sym_glue.h"
 #include "sym_nvram.h"
 
@@ -1042,28 +1038,11 @@
 	for (i = 0 ; i < SYM_CONF_MAX_TARGET ; i++) {
 		tcb_p tp = &np->target[i];
 
-		tp->tinfo.user.scsi_version = tp->tinfo.curr.scsi_version= 2;
-		tp->tinfo.user.spi_version  = tp->tinfo.curr.spi_version = 2;
-		tp->tinfo.user.period = np->minsync;
-		tp->tinfo.user.offset = np->maxoffs;
-		tp->tinfo.user.width  = np->maxwide ? BUS_16_BIT : BUS_8_BIT;
 		tp->usrflags |= (SYM_DISC_ENABLED | SYM_TAGS_ENABLED);
 		tp->usrtags = SYM_SETUP_MAX_TAG;
 
 		sym_nvram_setup_target (np, i, nvram);
 
-		/*
-		 * Some single-ended devices may crash on receiving a
-		 * PPR negotiation attempt.  Only try PPR if we're in
-		 * LVD mode.
-		 */
-		if (np->features & FE_ULTRA3) {
-			tp->tinfo.user.options |= PPR_OPT_DT;
-			tp->tinfo.user.period = np->minsync_dt;
-			tp->tinfo.user.offset = np->maxoffs_dt;
-			tp->tinfo.user.spi_version = 3;
-		}
-
 		if (!tp->usrtags)
 			tp->usrflags &= ~SYM_TAGS_ENABLED;
 	}
@@ -1497,6 +1476,55 @@
 }
 #endif
 
+static void sym_check_goals(struct scsi_device *sdev)
+{
+	struct sym_hcb *np = ((struct host_data *)sdev->host->hostdata)->ncb;
+	struct sym_trans *st = &np->target[sdev->id].tinfo.goal;
+
+	/* here we enforce all the fiddly SPI rules */
+
+	if (!scsi_device_wide(sdev))
+		st->width = 0;
+
+	if (!scsi_device_sync(sdev)) {
+		st->options = 0;
+		st->period = 0;
+		st->offset = 0;
+		return;
+	}
+		
+	if (scsi_device_dt(sdev)) {
+		if (scsi_device_dt_only(sdev))
+			st->options |= PPR_OPT_DT;
+
+		if (st->offset == 0)
+			st->options &= ~PPR_OPT_DT;
+	} else {
+		st->options &= ~PPR_OPT_DT;
+	}
+
+	if (!(np->features & FE_ULTRA3))
+		st->options &= ~PPR_OPT_DT;
+
+	if (st->options & PPR_OPT_DT) {
+		/* all DT transfers must be wide */
+		st->width = 1;
+		if (st->offset > np->maxoffs_dt)
+			st->offset = np->maxoffs_dt;
+		if (st->period < np->minsync_dt)
+			st->period = np->minsync_dt;
+		if (st->period > np->maxsync_dt)
+			st->period = np->maxsync_dt;
+	} else {
+		if (st->offset > np->maxoffs)
+			st->offset = np->maxoffs;
+		if (st->period < np->minsync)
+			st->period = np->minsync;
+		if (st->period > np->maxsync)
+			st->period = np->maxsync;
+	}
+}		
+
 /*
  *  Prepare the next negotiation message if needed.
  *
@@ -1508,6 +1536,10 @@
 {
 	tcb_p tp = &np->target[cp->target];
 	int msglen = 0;
+	struct scsi_device *sdev = tp->sdev;
+
+	if (likely(sdev))
+		sym_check_goals(sdev);
 
 	/*
 	 *  Early C1010 chips need a work-around for DT 
@@ -1518,19 +1550,21 @@
 	/*
 	 *  negotiate using PPR ?
 	 */
-	if (tp->tinfo.goal.options & PPR_OPT_MASK)
+	if (scsi_device_dt(sdev)) {
 		nego = NS_PPR;
-	/*
-	 *  negotiate wide transfers ?
-	 */
-	else if (tp->tinfo.curr.width != tp->tinfo.goal.width)
-		nego = NS_WIDE;
-	/*
-	 *  negotiate synchronous transfers?
-	 */
-	else if (tp->tinfo.curr.period != tp->tinfo.goal.period ||
-		 tp->tinfo.curr.offset != tp->tinfo.goal.offset)
-		nego = NS_SYNC;
+	} else {
+		/*
+		 *  negotiate wide transfers ?
+		 */
+		if (tp->tinfo.curr.width != tp->tinfo.goal.width)
+			nego = NS_WIDE;
+		/*
+		 *  negotiate synchronous transfers?
+		 */
+		else if (tp->tinfo.curr.period != tp->tinfo.goal.period ||
+			 tp->tinfo.curr.offset != tp->tinfo.goal.offset)
+			nego = NS_SYNC;
+	}
 
 	switch (nego) {
 	case NS_SYNC:
@@ -3999,7 +4033,6 @@
 static int  
 sym_sync_nego_check(hcb_p np, int req, int target)
 {
-	tcb_p tp = &np->target[target];
 	u_char	chg, ofs, per, fak, div;
 
 	if (DEBUG_FLAGS & DEBUG_NEGO) {
@@ -4019,19 +4052,11 @@
 	if (ofs) {
 		if (ofs > np->maxoffs)
 			{chg = 1; ofs = np->maxoffs;}
-		if (req) {
-			if (ofs > tp->tinfo.user.offset)
-				{chg = 1; ofs = tp->tinfo.user.offset;}
-		}
 	}
 
 	if (ofs) {
 		if (per < np->minsync)
 			{chg = 1; per = np->minsync;}
-		if (req) {
-			if (per < tp->tinfo.user.period)
-				{chg = 1; per = tp->tinfo.user.period;}
-		}
 	}
 
 	/*
@@ -4151,10 +4176,6 @@
 	}
 	if (!wide || !(np->features & FE_ULTRA3))
 		dt &= ~PPR_OPT_DT;
-	if (req) {
-		if (wide > tp->tinfo.user.width)
-			{chg = 1; wide = tp->tinfo.user.width;}
-	}
 
 	if (!(np->features & FE_U3EN))	/* Broken U3EN bit not supported */
 		dt &= ~PPR_OPT_DT;
@@ -4168,10 +4189,6 @@
 		}
 		else if (ofs > np->maxoffs)
 			{chg = 1; ofs = np->maxoffs;}
-		if (req) {
-			if (ofs > tp->tinfo.user.offset)
-				{chg = 1; ofs = tp->tinfo.user.offset;}
-		}
 	}
 
 	if (ofs) {
@@ -4181,10 +4198,6 @@
 		}
 		else if (per < np->minsync)
 			{chg = 1; per = np->minsync;}
-		if (req) {
-			if (per < tp->tinfo.user.period)
-				{chg = 1; per = tp->tinfo.user.period;}
-		}
 	}
 
 	/*
@@ -4286,7 +4299,6 @@
 static int  
 sym_wide_nego_check(hcb_p np, int req, int target)
 {
-	tcb_p tp = &np->target[target];
 	u_char	chg, wide;
 
 	if (DEBUG_FLAGS & DEBUG_NEGO) {
@@ -4305,10 +4317,6 @@
 	if (wide > np->maxwide) {
 		chg = 1;
 		wide = np->maxwide;
-	}
-	if (req) {
-		if (wide > tp->tinfo.user.width)
-			{chg = 1; wide = tp->tinfo.user.width;}
 	}
 
 	if (DEBUG_FLAGS & DEBUG_NEGO) {
diff -Nru a/drivers/scsi/sym53c8xx_2/sym_hipd.h b/drivers/scsi/sym53c8xx_2/sym_hipd.h
--- a/drivers/scsi/sym53c8xx_2/sym_hipd.h	2004-10-18 14:56:28 -07:00
+++ b/drivers/scsi/sym53c8xx_2/sym_hipd.h	2004-10-18 14:56:28 -07:00
@@ -69,11 +69,6 @@
  *        When this option is set, the driver will use a queue per 
  *        device and handle QUEUE FULL status requeuing internally.
  *
- *    SYM_OPT_SNIFF_INQUIRY
- *        When this option is set, the driver sniff out successful 
- *        INQUIRY response and performs negotiations accordingly.
- *        (set for Linux)
- *
  *    SYM_OPT_LIMIT_COMMAND_REORDERING
  *        When this option is set, the driver tries to limit tagged 
  *        command reordering to some reasonnable value.
@@ -82,7 +77,6 @@
 #if 0
 #define SYM_OPT_HANDLE_DIR_UNKNOWN
 #define SYM_OPT_HANDLE_DEVICE_QUEUEING
-#define SYM_OPT_SNIFF_INQUIRY
 #define SYM_OPT_LIMIT_COMMAND_REORDERING
 #endif
 
@@ -364,7 +358,6 @@
 struct sym_tinfo {
 	struct sym_trans curr;
 	struct sym_trans goal;
-	struct sym_trans user;
 #ifdef	SYM_OPT_ANNOUNCE_TRANSFER_RATE
 	struct sym_trans prev;
 #endif
@@ -465,18 +458,7 @@
 	 */
 	u_char	usrflags;
 	u_short	usrtags;
-
-#ifdef	SYM_OPT_SNIFF_INQUIRY
-	/*
-	 *  Some minimal information from INQUIRY response.
-	 */
-	u32	cmdq_map[(SYM_CONF_MAX_LUN+31)/32];
-	u_char	inq_version;
-	u_char	inq_byte7;
-	u_char	inq_byte56;
-	u_char	inq_byte7_valid;
-#endif
-
+	struct scsi_device *sdev;
 };
 
 /*
@@ -1167,26 +1149,6 @@
 #ifdef	SYM_OPT_ANNOUNCE_TRANSFER_RATE
 void sym_announce_transfer_rate(hcb_p np, int target);
 #endif
-
-/*
- *  Optionnaly, the driver may sniff inquiry data.
- */
-#ifdef	SYM_OPT_SNIFF_INQUIRY
-#define	INQ7_CMDQ	(0x02)
-#define	INQ7_SYNC	(0x10)
-#define	INQ7_WIDE16	(0x20)
-
-#define INQ56_CLOCKING	(3<<2)
-#define INQ56_ST_ONLY	(0<<2)
-#define INQ56_DT_ONLY	(1<<2)
-#define INQ56_ST_DT	(3<<2)
-
-void sym_update_trans_settings(hcb_p np, tcb_p tp);
-int  
-__sym_sniff_inquiry(hcb_p np, u_char tn, u_char ln,
-                    u_char *inq_data, int inq_len);
-#endif
-
 
 /*
  *  Build a scatter/gather entry.
diff -Nru a/drivers/scsi/sym53c8xx_2/sym_misc.c b/drivers/scsi/sym53c8xx_2/sym_misc.c
--- a/drivers/scsi/sym53c8xx_2/sym_misc.c	2004-10-18 14:56:50 -07:00
+++ b/drivers/scsi/sym53c8xx_2/sym_misc.c	2004-10-18 14:56:50 -07:00
@@ -216,121 +216,3 @@
 #undef __tprev
 #undef __tcurr
 #endif	/* SYM_OPT_ANNOUNCE_TRANSFER_RATE */
-
-
-#ifdef	SYM_OPT_SNIFF_INQUIRY
-/*
- *  Update transfer settings according to user settings 
- *  and bits sniffed out from INQUIRY response.
- */
-void sym_update_trans_settings(hcb_p np, tcb_p tp)
-{
-	memcpy(&tp->tinfo.goal, &tp->tinfo.user, sizeof(tp->tinfo.goal));
-
-	if (tp->inq_version >= 4) {
-		switch(tp->inq_byte56 & INQ56_CLOCKING) {
-		case INQ56_ST_ONLY:
-			tp->tinfo.goal.options = 0;
-			break;
-		case INQ56_DT_ONLY:
-		case INQ56_ST_DT:
-		default:
-			break;
-		}
-	}
-
-	if (!((tp->inq_byte7 & tp->inq_byte7_valid) & INQ7_WIDE16)) {
-		tp->tinfo.goal.width   = 0;
-		tp->tinfo.goal.options = 0;
-	}
-
-	if (!((tp->inq_byte7 & tp->inq_byte7_valid) & INQ7_SYNC)) {
-		tp->tinfo.goal.offset  = 0;
-		tp->tinfo.goal.options = 0;
-	}
-
-	if (tp->tinfo.goal.options & PPR_OPT_DT) {
-		if (tp->tinfo.goal.offset > np->maxoffs_dt)
-			tp->tinfo.goal.offset = np->maxoffs_dt;
-	}
-	else {
-		if (tp->tinfo.goal.offset > np->maxoffs)
-			tp->tinfo.goal.offset = np->maxoffs;
-	}
-}
-
-/*
- *  Snoop target capabilities from INQUIRY response.
- *  We only believe device versions >= SCSI-2 that use 
- *  appropriate response data format (2). But it seems 
- *  that some CCS devices also support SYNC (?).
- */
-int 
-__sym_sniff_inquiry(hcb_p np, u_char tn, u_char ln,
-                    u_char *inq_data, int inq_len)
-{
-	tcb_p tp = &np->target[tn];
-	u_char inq_version;
-	u_char inq_byte7;
-	u_char inq_byte56;
-
-	if (!inq_data || inq_len < 2)
-		return -1;
-
-	/*
-	 *  Check device type and qualifier.
-	 */
-	if ((inq_data[0] & 0xe0) == 0x60)
-		return -1;
-
-	/*
-	 *  Get SPC version.
-	 */
-	if (inq_len <= 2)
-		return -1;
-	inq_version = inq_data[2] & 0x7;
-
-	/*
-	 *  Get SYNC/WIDE16 capabilities.
-	 */
-	inq_byte7 = tp->inq_byte7;
-	if (inq_version >= 2 && (inq_data[3] & 0xf) == 2) {
-		if (inq_len > 7)
-			inq_byte7 = inq_data[7];
-	}
-	else if (inq_version == 1 && (inq_data[3] & 0xf) == 1)
-		inq_byte7 = INQ7_SYNC;
-
-	/*
-	 *  Get Tagged Command Queuing capability.
-	 */
-	if (inq_byte7 & INQ7_CMDQ)
-		sym_set_bit(tp->cmdq_map, ln);
-	else
-		sym_clr_bit(tp->cmdq_map, ln);
-	inq_byte7 &= ~INQ7_CMDQ;
-
-	/*
-	 *  Get CLOCKING capability.
-	 */
-	inq_byte56 = tp->inq_byte56;
-	if (inq_version >= 4 && inq_len > 56)
-		inq_byte56 = inq_data[56];
-#if 0
-printf("XXXXXX [%d] inq_version=%x inq_byte7=%x inq_byte56=%x XXXXX\n",
-	inq_len, inq_version, inq_byte7, inq_byte56);
-#endif
-	/*
-	 *  Trigger a negotiation if needed.
-	 */
-	if (tp->inq_version != inq_version ||
-	    tp->inq_byte7   != inq_byte7   ||
-	    tp->inq_byte56  != inq_byte56) {
-		tp->inq_version = inq_version;
-		tp->inq_byte7   = inq_byte7;
-		tp->inq_byte56  = inq_byte56;
-		return 1;
-	}
-	return 0;
-}
-#endif	/* SYM_OPT_SNIFF_INQUIRY */
diff -Nru a/drivers/scsi/sym53c8xx_2/sym_nvram.c b/drivers/scsi/sym53c8xx_2/sym_nvram.c
--- a/drivers/scsi/sym53c8xx_2/sym_nvram.c	2004-10-18 14:56:33 -07:00
+++ b/drivers/scsi/sym53c8xx_2/sym_nvram.c	2004-10-18 14:56:33 -07:00
@@ -53,11 +53,6 @@
 #include "sym_glue.h"
 #include "sym_nvram.h"
 
-/*
- *  Some poor and bogus sync table that refers to Tekram NVRAM layout.
- */
-static u_char Tekram_sync[16] =
-	{25,31,37,43, 50,62,75,125, 12,15,18,21, 6,7,9,10};
 #ifdef	SYM_CONF_DEBUG_NVRAM
 static u_char Tekram_boot_delay[7] = {3, 5, 10, 20, 30, 60, 120};
 #endif
@@ -100,8 +95,6 @@
 	struct sym_tcb *tp = &np->target[target];
 	Symbios_target *tn = &nvram->target[target];
 
-	tp->tinfo.user.period = tn->sync_period ? (tn->sync_period + 3) / 4 : 0;
-	tp->tinfo.user.width  = tn->bus_width == 0x10 ? BUS_16_BIT : BUS_8_BIT;
 	tp->usrtags =
 		(tn->flags & SYMBIOS_QUEUE_TAGS_ENABLED)? SYM_SETUP_MAX_TAG : 0;
 
@@ -121,15 +114,6 @@
 {
 	struct sym_tcb *tp = &np->target[target];
 	struct Tekram_target *tn = &nvram->target[target];
-	int i;
-
-	if (tn->flags & TEKRAM_SYNC_NEGO) {
-		i = tn->sync_index & 0xf;
-		tp->tinfo.user.period = Tekram_sync[i];
-	}
-
-	tp->tinfo.user.width = (tn->flags & TEKRAM_WIDE_NEGO) ?
-		BUS_16_BIT : BUS_8_BIT;
 
 	if (tn->flags & TEKRAM_TAGGED_COMMANDS) {
 		tp->usrtags = 2 << nvram->max_tags_index;
diff -Nru a/drivers/scsi/t128.c b/drivers/scsi/t128.c
--- a/drivers/scsi/t128.c	2004-10-18 14:57:03 -07:00
+++ b/drivers/scsi/t128.c	2004-10-18 14:57:03 -07:00
@@ -284,6 +284,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/tmscsim.c b/drivers/scsi/tmscsim.c
--- a/drivers/scsi/tmscsim.c	2004-10-18 14:57:19 -07:00
+++ b/drivers/scsi/tmscsim.c	2004-10-18 14:57:19 -07:00
@@ -240,17 +240,15 @@
 #include <linux/spinlock.h>
 #include <asm/io.h>
 
-#if 0
 #include <scsi/scsi.h>
 #include <scsi/scsi_cmnd.h>
 #include <scsi/scsi_device.h>
-#else
-#include "scsi.h"
-#endif
 #include <scsi/scsi_host.h>
 #include <scsi/scsicam.h>
 
-#include "dc390.h"
+
+#define DC390_BANNER "Tekram DC390/AM53C974"
+#define DC390_VERSION "2.1d 2004-05-27"
 
 #define PCI_DEVICE_ID_AMD53C974 	PCI_DEVICE_ID_AMD_SCSI
 
@@ -291,20 +289,14 @@
 static void dc390_DoingSRB_Done( struct dc390_acb* pACB, struct scsi_cmnd * cmd);
 static void dc390_ScsiRstDetect( struct dc390_acb* pACB );
 static void dc390_ResetSCSIBus( struct dc390_acb* pACB );
-static void __inline__ dc390_RequestSense( struct dc390_acb* pACB, struct dc390_dcb* pDCB, struct dc390_srb* pSRB );
-static void __inline__ dc390_InvalidCmd( struct dc390_acb* pACB );
-static void __inline__ dc390_EnableMsgOut_Abort (struct dc390_acb*, struct dc390_srb*);
+static void dc390_EnableMsgOut_Abort(struct dc390_acb*, struct dc390_srb*);
 static irqreturn_t do_DC390_Interrupt( int, void *, struct pt_regs *);
 
 static int    dc390_initAdapter(struct Scsi_Host *psh, unsigned long io_port, u8 Irq, u8 index );
 static void   dc390_updateDCB (struct dc390_acb* pACB, struct dc390_dcb* pDCB);
 
-static int DC390_proc_info (struct Scsi_Host *shpnt, char *buffer, char **start,
-			    off_t offset, int length, int inout);
-
 static struct dc390_acb*	dc390_pACB_start= NULL;
 static struct dc390_acb*	dc390_pACB_current = NULL;
-static unsigned long	dc390_lastabortedpid = 0;
 static u32	dc390_laststatus = 0;
 static u8	dc390_adapterCnt = 0;
 
@@ -612,16 +604,12 @@
  **********************************************************************/
 static struct dc390_dcb __inline__ *dc390_findDCB ( struct dc390_acb* pACB, u8 id, u8 lun)
 {
-   struct dc390_dcb* pDCB = pACB->pLinkDCB; if (!pDCB) return 0;
+   struct dc390_dcb* pDCB = pACB->pLinkDCB; if (!pDCB) return NULL;
    while (pDCB->TargetID != id || pDCB->TargetLUN != lun)
      {
 	pDCB = pDCB->pNextDCB;
 	if (pDCB == pACB->pLinkDCB)
-	  {
-	     DCBDEBUG(printk (KERN_WARNING "DC390: DCB not found (DCB=%p, DCBmap[%2x]=%2x)\n",
-			      pDCB, id, pACB->DCBmap[id]));
-	     return 0;
-	  }
+	     return NULL;
      }
    DCBDEBUG1( printk (KERN_DEBUG "DCB %p (%02x,%02x) found.\n",	\
 		      pDCB, pDCB->TargetID, pDCB->TargetLUN));
@@ -942,8 +930,6 @@
 {
     pSRB->pSRBDCB = pDCB;
     pSRB->pcmd = pcmd;
-    //pSRB->ScsiCmdLen = pcmd->cmd_len;
-    //memcpy (pSRB->CmdBlock, pcmd->cmnd, pcmd->cmd_len);
     
     pSRB->SGIndex = 0;
     pSRB->AdaptStatus = 0;
@@ -991,28 +977,6 @@
     struct dc390_srb*   pSRB;
     struct dc390_acb*   pACB = (struct dc390_acb*) cmd->device->host->hostdata;
 
-    DEBUG0(/*  if(pACB->scan_devices) */	\
-	printk(KERN_INFO "DC390: Queue Cmd=%02x,Tgt=%d,LUN=%d (pid=%li), buffer=%p\n",\
-	       cmd->cmnd[0],cmd->device->id,cmd->device->lun,cmd->pid, cmd->buffer));
-
-    /* TODO: Change the policy: Always accept TEST_UNIT_READY or INQUIRY 
-     * commands and alloc a DCB for the device if not yet there. DCB will
-     * be removed in dc390_SRBdone if SEL_TIMEOUT */
-    if (!(pACB->scan_devices) && !(pACB->DCBmap[cmd->device->id] & (1 << cmd->device->lun))) {
-	printk(KERN_INFO "DC390: Ignore target %02x lun %02x\n",
-		cmd->device->id, cmd->device->lun); 
-	goto fail;
-    }
-
-    /* Should it be: BUG_ON(!pDCB); ? */
-
-    if (!pDCB)
-    {  /* should never happen */
-	printk (KERN_ERR "DC390: no DCB found, target %02x lun %02x\n", 
-		cmd->device->id, cmd->device->lun);
-	goto fail;
-    }
-
     pACB->Cmds++;
     cmd->scsi_done = done;
     cmd->result = 0;
@@ -1033,145 +997,7 @@
 
  requeue:
     return 1;
- fail:
-    cmd->result = DID_BAD_TARGET << 16;
-    done(cmd);
-    return 0;
-}
-
-/* We ignore mapping problems, as we expect everybody to respect 
- * valid partition tables. Waiting for complaints ;-) */
-
-#ifdef CONFIG_SCSI_DC390T_TRADMAP
-/* 
- * The next function, partsize(), is copied from scsicam.c.
- *
- * This is ugly code duplication, but I didn't find another way to solve it:
- * We want to respect the partition table and if it fails, we apply the 
- * DC390 BIOS heuristic. Too bad, just calling scsicam_bios_param() doesn't do
- * the job, because we don't know, whether the values returned are from
- * the part. table or determined by setsize(). Unfortunately the setsize() 
- * values differ from the ones chosen by the DC390 BIOS.
- *
- * Looking forward to seeing suggestions for a better solution! KG, 98/10/14
- */
-#include <asm/unaligned.h>
-
-/*
- * Function : static int partsize(unsigned char *buf, unsigned long 
- *     capacity,unsigned int *cyls, unsigned int *hds, unsigned int *secs);
- *
- * Purpose : to determine the BIOS mapping used to create the partition
- *	table, storing the results in *cyls, *hds, and *secs 
- *
- * Returns : -1 on failure, 0 on success.
- *
- */
-
-static int partsize(unsigned char *buf, unsigned long capacity,
-    unsigned int  *cyls, unsigned int *hds, unsigned int *secs) {
-    struct partition *p, *largest = NULL;
-    int i, largest_cyl;
-    int cyl, ext_cyl, end_head, end_cyl, end_sector;
-    unsigned int logical_end, physical_end, ext_physical_end;
-    
-
-    if (*(unsigned short *) (buf+64) == 0xAA55) {
-	for (largest_cyl = -1, p = (struct partition *) buf, 
-    	    i = 0; i < 4; ++i, ++p) {
-    	    if (!p->sys_ind)
-    	    	continue;
-    	    cyl = p->cyl + ((p->sector & 0xc0) << 2);
-    	    if (cyl > largest_cyl) {
-    	    	largest_cyl = cyl;
-    	    	largest = p;
-    	    }
-    	}
-    }
-
-    if (largest) {
-    	end_cyl = largest->end_cyl + ((largest->end_sector & 0xc0) << 2);
-    	end_head = largest->end_head;
-    	end_sector = largest->end_sector & 0x3f;
-
-    	physical_end =  end_cyl * (end_head + 1) * end_sector +
-    	    end_head * end_sector + end_sector;
-
-	/* This is the actual _sector_ number at the end */
-	logical_end = get_unaligned(&largest->start_sect)
-			+ get_unaligned(&largest->nr_sects);
-
-	/* This is for >1023 cylinders */
-        ext_cyl= (logical_end-(end_head * end_sector + end_sector))
-                                        /(end_head + 1) / end_sector;
-	ext_physical_end = ext_cyl * (end_head + 1) * end_sector +
-            end_head * end_sector + end_sector;
-
-    	if ((logical_end == physical_end) ||
-	    (end_cyl==1023 && ext_physical_end==logical_end)) {
-    	    *secs = end_sector;
-    	    *hds = end_head + 1;
-    	    *cyls = capacity / ((end_head + 1) * end_sector);
-    	    return 0;
-    	}
-    }
-    return -1;
-}
-
-/***********************************************************************
- * Function:
- *   DC390_bios_param
- *
- * Description:
- *   Return the disk geometry for the given SCSI device.
- *   Respect the partition table, otherwise try own heuristic
- *
- * Note:
- *   In contrary to other externally callable funcs (DC390_), we don't lock
- ***********************************************************************/
-static int DC390_bios_param (struct scsi_device *sdev, struct block_device *bdev,
-			     sector_t capacity, int geom[])
-{
-    int heads, sectors, cylinders;
-    struct dc390_acb* pACB = (struct dc390_acb*) sdev->host->hostdata;
-    int ret_code = -1;
-    int size = capacity;
-    unsigned char *buf;
-
-    if ((buf = scsi_bios_ptable(bdev)))
-    {
-	/* try to infer mapping from partition table */
-	ret_code = partsize (buf, (unsigned long) size, (unsigned int *) geom + 2,
-			     (unsigned int *) geom + 0, (unsigned int *) geom + 1);
-	kfree (buf);
-    }
-    if (ret_code == -1)
-    {
-	heads = 64;
-	sectors = 32;
-	cylinders = size / (heads * sectors);
-
-	if ( (pACB->Gmode2 & GREATER_1G) && (cylinders > 1024) )
-	{
-		heads = 255;
-		sectors = 63;
-		cylinders = size / (heads * sectors);
-	}
-
-	geom[0] = heads;
-	geom[1] = sectors;
-	geom[2] = cylinders;
-    }
-
-    return (0);
 }
-#else
-static int DC390_bios_param (struct scsi_device *sdev, struct block_device *bdev,
-			     sector_t capacity, int geom[])
-{
-    return scsicam_bios_param (bdev, capacity, geom);
-}
-#endif
 
 static void dc390_dumpinfo (struct dc390_acb* pACB, struct dc390_dcb* pDCB, struct dc390_srb* pSRB)
 {
@@ -1219,146 +1045,54 @@
 }
 
 
-/***********************************************************************
- * Function : int DC390_abort (struct scsi_cmnd *cmd)
- *
- * Purpose : Abort an errant SCSI command
- *
- * Inputs : cmd - command to abort
- *
- * Returns : 0 on success, -1 on failure.
- *
- * Status: Buggy !
- ***********************************************************************/
-
-static int DC390_abort (struct scsi_cmnd *cmd)
+static int DC390_abort(struct scsi_cmnd *cmd)
 {
-    struct dc390_dcb *pDCB = (struct dc390_dcb*) cmd->device->hostdata;
-    struct dc390_srb *pSRB, *psrb;
-    u32  count, i;
-    int   status;
-    //unsigned long sbac;
-    struct dc390_acb *pACB = (struct dc390_acb*) cmd->device->host->hostdata;
-
-    printk ("DC390: Abort command (pid %li, Device %02i-%02i)\n",
-	    cmd->pid, cmd->device->id, cmd->device->lun);
-
-    if( !pDCB ) goto  NOT_RUN;
-
-    /* Added 98/07/02 KG */
-    /*
-    pSRB = pDCB->pActiveSRB;
-    if (pSRB && pSRB->pcmd == cmd )
-	goto ON_GOING;
-     */
-    
-    pSRB = pDCB->pWaitingSRB;
-    if( !pSRB )
-	goto  ON_GOING;
+	struct dc390_acb *pACB = (struct dc390_acb*) cmd->device->host->hostdata;
+	struct dc390_dcb *pDCB = (struct dc390_dcb*) cmd->device->hostdata;
+	struct dc390_srb *pSRB, *psrb;
 
-    /* Now scan Waiting queue */
-    if( pSRB->pcmd == cmd )
-    {
-	pDCB->pWaitingSRB = pSRB->pNextSRB;
-	goto  IN_WAIT;
-    }
-    else
-    {
-	psrb = pSRB;
-	if( !(psrb->pNextSRB) )
-	    goto ON_GOING;
-	while( psrb->pNextSRB->pcmd != cmd )
-	{
-	    psrb = psrb->pNextSRB;
-	    if( !(psrb->pNextSRB) || psrb == pSRB)
-		goto ON_GOING;
-	}
-	pSRB = psrb->pNextSRB;
-	psrb->pNextSRB = pSRB->pNextSRB;
-	if( pSRB == pDCB->pWaitLast )
-	    pDCB->pWaitLast = psrb;
-IN_WAIT:
-	dc390_Free_insert (pACB, pSRB);
+	printk("DC390: Abort command (pid %li, Device %02i-%02i)\n",
+	       cmd->pid, cmd->device->id, cmd->device->lun);
+
+	pSRB = pDCB->pWaitingSRB;
+	if (!pSRB)
+		goto on_going;
+
+	/* Now scan Waiting queue */
+	if (pSRB->pcmd != cmd) {
+		psrb = pSRB;
+		if (!(psrb->pNextSRB))
+			goto on_going;
+
+		while (psrb->pNextSRB->pcmd != cmd) {
+			psrb = psrb->pNextSRB;
+			if (!(psrb->pNextSRB) || psrb == pSRB)
+				goto on_going;
+		}
+
+		pSRB = psrb->pNextSRB;
+		psrb->pNextSRB = pSRB->pNextSRB;
+		if (pSRB == pDCB->pWaitLast)
+			pDCB->pWaitLast = psrb;
+	} else
+		pDCB->pWaitingSRB = pSRB->pNextSRB;
+
+	dc390_Free_insert(pACB, pSRB);
 	pDCB->WaitSRBCnt--;
 	INIT_LIST_HEAD((struct list_head*)&cmd->SCp);
-	status = SCSI_ABORT_SUCCESS;
-	goto  ABO_X;
-    }
 
-    /* SRB has already been sent ! */
-ON_GOING:
-    /* abort() is too stupid for already sent commands at the moment. 
-     * If it's called we are in trouble anyway, so let's dump some info 
-     * into the syslog at least. (KG, 98/08/20,99/06/20) */
-    dc390_dumpinfo (pACB, pDCB, pSRB);
-    pSRB = pDCB->pGoingSRB;
-    pDCB->DCBFlag |= ABORT_DEV_;
-    /* Now for the hard part: The command is currently processed */
-    for( count = pDCB->GoingSRBCnt, i=0; i<count; i++)
-    {
-	if( pSRB->pcmd != cmd )
-	    pSRB = pSRB->pNextSRB;
-	else
-	{
-	    if( (pACB->pActiveDCB == pDCB) && (pDCB->pActiveSRB == pSRB) )
-	    {
-		status = SCSI_ABORT_BUSY;
-		printk ("DC390: Abort current command (pid %li, SRB %p)\n",
-			cmd->pid, pSRB);
-		goto  ABO_X;
-	    }
-	    else
-	    {
-		status = SCSI_ABORT_SNOOZE;
-		goto  ABO_X;
-	    }
-	}
-    }
+	return SUCCESS;
 
-NOT_RUN:
-    status = SCSI_ABORT_NOT_RUNNING;
+on_going:
+	/* abort() is too stupid for already sent commands at the moment. 
+	 * If it's called we are in trouble anyway, so let's dump some info 
+	 * into the syslog at least. (KG, 98/08/20,99/06/20) */
+	dc390_dumpinfo(pACB, pDCB, pSRB);
 
-ABO_X:
-    cmd->result = DID_ABORT << 16;
-    printk(KERN_INFO "DC390: Aborted pid %li with status %i\n", cmd->pid, status);
-#if 0
-    if (cmd->pid == dc390_lastabortedpid) /* repeated failure ? */
-	{
-		/* Let's do something to help the bus getting clean again */
-		DC390_write8 (DMA_Cmd, DMA_IDLE_CMD);
-		DC390_write8 (ScsiCmd, DMA_COMMAND);
-		//DC390_write8 (ScsiCmd, CLEAR_FIFO_CMD);
-		//DC390_write8 (ScsiCmd, RESET_ATN_CMD);
-		DC390_write8 (ScsiCmd, NOP_CMD);
-		//udelay (10000);
-		//DC390_read8 (INT_Status);
-		//DC390_write8 (ScsiCmd, EN_SEL_RESEL);
-	}
-    sbac = DC390_read32 (DMA_ScsiBusCtrl);
-    if (sbac & SCSI_BUSY)
-    {	/* clear BSY, SEL and ATN */
-	printk (KERN_WARNING "DC390: Reset SCSI device: ");
-	//DC390_write32 (DMA_ScsiBusCtrl, (sbac | SCAM) & ~SCSI_LINES);
-	//udelay (250);
-	//sbac = DC390_read32 (DMA_ScsiBusCtrl);
-	//printk ("%08lx ", sbac);
-	//DC390_write32 (DMA_ScsiBusCtrl, sbac & ~(SCSI_LINES | SCAM));
-	//udelay (100);
-	//sbac = DC390_read32 (DMA_ScsiBusCtrl);
-	//printk ("%08lx ", sbac);
-	DC390_write8 (ScsiCmd, RST_DEVICE_CMD);
-	udelay (250);
-	DC390_write8 (ScsiCmd, NOP_CMD);
-	sbac = DC390_read32 (DMA_ScsiBusCtrl);
-	printk ("%08lx\n", sbac);
-    }
-#endif
-    dc390_lastabortedpid = cmd->pid;
-    //do_DC390_Interrupt (pACB->IRQLevel, 0, 0);
-#ifndef USE_NEW_EH	
-    if (status == SCSI_ABORT_SUCCESS) cmd->scsi_done(cmd);
-#endif	
-    return( status );
+	pDCB->DCBFlag |= ABORT_DEV_;
+	printk(KERN_INFO "DC390: Aborted pid %li\n", cmd->pid);
+
+	return FAILED;
 }
 
 
@@ -1385,93 +1119,38 @@
 
 }
 
-#if 0
-/* Moves all SRBs from Going to Waiting for all DCBs */
-static void dc390_RecoverSRB( struct dc390_acb* pACB )
+static int DC390_bus_reset (struct scsi_cmnd *cmd)
 {
-    struct dc390_dcb *pDCB, *pdcb;
-    struct dc390_srb *psrb, *psrb2;
-    u32   cnt, i;
-
-    pDCB = pACB->pLinkDCB;
-    if( !pDCB ) return;
-    pdcb = pDCB;
-    do
-    {
-	cnt = pdcb->GoingSRBCnt;
-	psrb = pdcb->pGoingSRB;
-	for (i=0; i<cnt; i++)
-	{
-	    psrb2 = psrb;
-	    psrb = psrb->pNextSRB;
-/*	    dc390_RewaitSRB( pDCB, psrb ); */
-	    if( pdcb->pWaitingSRB )
-	    {
-		psrb2->pNextSRB = pdcb->pWaitingSRB;
-		pdcb->pWaitingSRB = psrb2;
-	    }
-	    else
-	    {
-		pdcb->pWaitingSRB = psrb2;
-		pdcb->pWaitLast = psrb2;
-		psrb2->pNextSRB = NULL;
-	    }
-	}
-	pdcb->GoingSRBCnt = 0;
-	pdcb->pGoingSRB = NULL;
-	pdcb->TagMask = 0;
-	pdcb = pdcb->pNextDCB;
-    } while( pdcb != pDCB );
-}
-#endif
+	struct dc390_acb*    pACB = (struct dc390_acb*) cmd->device->host->hostdata;
+	u8   bval;
 
-/***********************************************************************
- * Function : int DC390_reset (struct scsi_cmnd *cmd, ...)
- *
- * Purpose : perform a hard reset on the SCSI bus
- *
- * Inputs : cmd - command which caused the SCSI RESET
- *	    resetFlags - how hard to try
- *
- * Returns : 0 on success.
- ***********************************************************************/
+	del_timer (&pACB->Waiting_Timer);
 
-static int DC390_reset (struct scsi_cmnd *cmd)
-{
-    u8   bval;
-    struct dc390_acb*    pACB = (struct dc390_acb*) cmd->device->host->hostdata;
+	bval = DC390_read8(CtrlReg1) | DIS_INT_ON_SCSI_RST;
+	DC390_write8(CtrlReg1, bval);	/* disable IRQ on bus reset */
 
-    printk(KERN_INFO "DC390: RESET ... ");
+	pACB->ACBFlag |= RESET_DEV;
+	dc390_ResetSCSIBus(pACB);
 
-    if (timer_pending (&pACB->Waiting_Timer)) del_timer (&pACB->Waiting_Timer);
-    bval = DC390_read8 (CtrlReg1);
-    bval |= DIS_INT_ON_SCSI_RST;
-    DC390_write8 (CtrlReg1, bval);	/* disable IRQ on bus reset */
-
-    pACB->ACBFlag |= RESET_DEV;
-    dc390_ResetSCSIBus( pACB );
-
-    dc390_ResetDevParam( pACB );
-    udelay (1000);
-    pACB->pScsiHost->last_reset = jiffies + 3*HZ/2 
+	dc390_ResetDevParam(pACB);
+	udelay(1000);
+	pACB->pScsiHost->last_reset = jiffies + 3*HZ/2 
 		+ HZ * dc390_eepromBuf[pACB->AdapterIndex][EE_DELAY];
     
-    DC390_write8 (ScsiCmd, CLEAR_FIFO_CMD);
-    DC390_read8 (INT_Status);		/* Reset Pending INT */
+	DC390_write8(ScsiCmd, CLEAR_FIFO_CMD);
+	DC390_read8(INT_Status);		/* Reset Pending INT */
 
-    dc390_DoingSRB_Done( pACB, cmd );
-    /* dc390_RecoverSRB (pACB); */
-    pACB->pActiveDCB = NULL;
+	dc390_DoingSRB_Done(pACB, cmd);
 
-    pACB->ACBFlag = 0;
-    bval = DC390_read8 (CtrlReg1);
-    bval &= ~DIS_INT_ON_SCSI_RST;
-    DC390_write8 (CtrlReg1, bval);	/* re-enable interrupt */
+	pACB->pActiveDCB = NULL;
+	pACB->ACBFlag = 0;
 
-    dc390_Waiting_process( pACB );
+	bval = DC390_read8(CtrlReg1) & ~DIS_INT_ON_SCSI_RST;
+	DC390_write8(CtrlReg1, bval);	/* re-enable interrupt */
 
-    printk("done\n");
-    return( SCSI_RESET_SUCCESS );
+	dc390_Waiting_process(pACB);
+
+	return SUCCESS;
 }
 
 #include "scsiiom.c"
@@ -1548,7 +1227,6 @@
 static void __devinit dc390_initACB (struct Scsi_Host *psh, unsigned long io_port, u8 Irq, u8 index)
 {
     struct dc390_acb*    pACB;
-    u8   i;
 
     psh->can_queue = MAX_CMD_QUEUE;
     psh->cmd_per_lun = MAX_CMD_PER_LUN;
@@ -1595,8 +1273,6 @@
     dc390_linkSRB( pACB );
     pACB->pTmpSRB = &pACB->TmpSRB;
     dc390_initSRB( pACB->pTmpSRB );
-    for(i=0; i<MAX_SCSI_ID; i++)
-	pACB->DCBmap[i] = 0;
     pACB->sel_timeout = SEL_TIMEOUT;
     pACB->glitch_cfg = EATER_25NS;
     pACB->Cmds = pACB->CmdInQ = pACB->CmdOutOfSRB = 0;
@@ -1706,7 +1382,7 @@
 static int dc390_slave_alloc(struct scsi_device *scsi_device)
 {
 	struct dc390_acb *pACB = (struct dc390_acb*) scsi_device->host->hostdata;
-	struct dc390_dcb *pDCB, *pDCB2 = 0;
+	struct dc390_dcb *pDCB, *pDCB2 = NULL;
 	uint id = scsi_device->id;
 	uint lun = scsi_device->lun;
 
@@ -1757,7 +1433,6 @@
 			pDCB->CtrlR4 |= NEGATE_REQACKDATA | NEGATE_REQACK;
 	}
 
-	pACB->DCBmap[id] |= (1 << lun);
 	dc390_updateDCB(pACB, pDCB);
 
 	pACB->scan_devices = 1;
@@ -1781,8 +1456,6 @@
 
 	BUG_ON(pDCB->GoingSRBCnt > 1);
 	
-	pACB->DCBmap[pDCB->TargetID] &= ~(1 << pDCB->TargetLUN);
-   
 	if (pDCB == pACB->pLinkDCB) {
 		if (pACB->pLastDCB == pDCB) {
 			pDCB->pNextDCB = NULL;
@@ -1818,15 +1491,13 @@
 static struct scsi_host_template driver_template = {
 	.module			= THIS_MODULE,
 	.proc_name		= "tmscsim", 
-	.proc_info		= DC390_proc_info,
 	.name			= DC390_BANNER " V" DC390_VERSION,
 	.slave_alloc		= dc390_slave_alloc,
 	.slave_configure	= dc390_slave_configure,
 	.slave_destroy		= dc390_slave_destroy,
 	.queuecommand		= DC390_queue_command,
 	.eh_abort_handler	= DC390_abort,
-	.eh_bus_reset_handler	= DC390_reset,
-	.bios_param		= DC390_bios_param,
+	.eh_bus_reset_handler	= DC390_bus_reset,
 	.can_queue		= 42,
 	.this_id		= 7,
 	.sg_tablesize		= SG_ALL,
@@ -1938,152 +1609,6 @@
 	scsi_host_put(scsi_host);
 	pci_set_drvdata(dev, NULL);
 }
-
-/********************************************************************
- * Function: DC390_proc_info(char* buffer, char **start,
- *			     off_t offset, int length, int hostno, int inout)
- *
- * Purpose: return SCSI Adapter/Device Info
- *
- * Input: buffer: Pointer to a buffer where to write info
- *	  start :
- *	  offset:
- *	  hostno: Host adapter index
- *	  inout : Read (=0) or set(!=0) info
- *
- * Output: buffer: contains info
- *	   length; length of info in buffer
- *
- * return value: length
- *
- ********************************************************************/
-
-#undef SPRINTF
-#define SPRINTF(args...) pos += sprintf(pos, ## args)
-
-#define YESNO(YN)		\
- if (YN) SPRINTF(" Yes ");	\
- else SPRINTF(" No  ")
-
-
-static int DC390_proc_info (struct Scsi_Host *shpnt, char *buffer, char **start,
-			    off_t offset, int length, int inout)
-{
-  int dev, spd, spd1;
-  char *pos = buffer;
-  struct dc390_acb* pACB;
-  struct dc390_dcb* pDCB;
-
-  pACB = dc390_pACB_start;
-
-  while(pACB != (struct dc390_acb*)-1)
-     {
-	if (shpnt == pACB->pScsiHost)
-		break;
-	pACB = pACB->pNextACB;
-     }
-
-  if (pACB == (struct dc390_acb*)-1) return(-ESRCH);
-
-  if(inout) /* Has data been written to the file ? */
-      return -ENOSYS;
-   
-  SPRINTF("Tekram DC390/AM53C974 PCI SCSI Host Adapter, ");
-  SPRINTF("Driver Version %s\n", DC390_VERSION);
-
-  SPRINTF("SCSI Host Nr %i, ", shpnt->host_no);
-  SPRINTF("%s Adapter Nr %i\n", dc390_adapname, pACB->AdapterIndex);
-  SPRINTF("IOPortBase 0x%04x, ", pACB->IOPortBase);
-  SPRINTF("IRQ %02i\n", pACB->IRQLevel);
-
-  SPRINTF("MaxID %i, MaxLUN %i, ", shpnt->max_id, shpnt->max_lun);
-  SPRINTF("AdapterID %i, SelTimeout %i ms, DelayReset %i s\n", 
-	  shpnt->this_id, (pACB->sel_timeout*164)/100,
-	  dc390_eepromBuf[pACB->AdapterIndex][EE_DELAY]);
-
-  SPRINTF("TagMaxNum %i, Status 0x%02x, ACBFlag 0x%02x, GlitchEater %i ns\n",
-	  pACB->TagMaxNum, pACB->status, pACB->ACBFlag, GLITCH_TO_NS(pACB->glitch_cfg)*12);
-
-  SPRINTF("Statistics: Cmnds %li, Cmnds not sent directly %i, Out of SRB conds %i\n",
-	  pACB->Cmds, pACB->CmdInQ, pACB->CmdOutOfSRB);
-  SPRINTF("            Lost arbitrations %i, Sel. connected %i, Connected: %s\n", 
-	  pACB->SelLost, pACB->SelConn, pACB->Connected? "Yes": "No");
-   
-  SPRINTF("Nr of DCBs: %i\n", pACB->DCBCnt);
-  SPRINTF("Map of attached LUNs: %02x %02x %02x %02x %02x %02x %02x %02x\n",
-	  pACB->DCBmap[0], pACB->DCBmap[1], pACB->DCBmap[2], pACB->DCBmap[3], 
-	  pACB->DCBmap[4], pACB->DCBmap[5], pACB->DCBmap[6], pACB->DCBmap[7]);
-
-  SPRINTF("Idx ID LUN Prty Sync DsCn SndS TagQ NegoPeriod SyncSpeed SyncOffs MaxCmd\n");
-
-  pDCB = pACB->pLinkDCB;
-  for (dev = 0; dev < pACB->DCBCnt; dev++)
-     {
-      SPRINTF("%02i  %02i  %02i ", dev, pDCB->TargetID, pDCB->TargetLUN);
-      YESNO(pDCB->DevMode & PARITY_CHK_);
-      YESNO(pDCB->SyncMode & SYNC_NEGO_DONE);
-      YESNO(pDCB->DevMode & EN_DISCONNECT_);
-      YESNO(pDCB->DevMode & SEND_START_);
-      YESNO(pDCB->SyncMode & EN_TAG_QUEUEING);
-      if (pDCB->SyncOffset & 0x0f)
-      {
-	 int sp = pDCB->SyncPeriod; if (! (pDCB->CtrlR3 & FAST_SCSI)) sp++;
-	 SPRINTF("  %03i ns ", (pDCB->NegoPeriod) << 2);
-	 spd = 40/(sp); spd1 = 40%(sp);
-	 spd1 = (spd1 * 10 + sp/2) / (sp);
-	 SPRINTF("   %2i.%1i M      %02i", spd, spd1, (pDCB->SyncOffset & 0x0f));
-      }
-      else SPRINTF(" (%03i ns)                 ", (pDCB->NegoPeriod) << 2);
-      /* Add more info ...*/
-      SPRINTF ("      %02i\n", pDCB->MaxCommand);
-      pDCB = pDCB->pNextDCB;
-     }
-    if (timer_pending(&pACB->Waiting_Timer)) SPRINTF ("Waiting queue timer running\n");
-    else SPRINTF ("\n");
-    pDCB = pACB->pLinkDCB;
-	
-    for (dev = 0; dev < pACB->DCBCnt; dev++)
-    {
-	struct dc390_srb* pSRB;
-	if (pDCB->WaitSRBCnt) 
-		    SPRINTF ("DCB (%02i-%i): Waiting: %i:", pDCB->TargetID, pDCB->TargetLUN,
-			     pDCB->WaitSRBCnt);
-	for (pSRB = pDCB->pWaitingSRB; pSRB; pSRB = pSRB->pNextSRB)
-		SPRINTF(" %li", pSRB->pcmd->pid);
-	if (pDCB->GoingSRBCnt) 
-		    SPRINTF ("\nDCB (%02i-%i): Going  : %i:", pDCB->TargetID, pDCB->TargetLUN,
-			     pDCB->GoingSRBCnt);
-	for (pSRB = pDCB->pGoingSRB; pSRB; pSRB = pSRB->pNextSRB)
-#if 0 //def DC390_DEBUGTRACE
-		SPRINTF(" %s\n  ", pSRB->debugtrace);
-#else
-		SPRINTF(" %li", pSRB->pcmd->pid);
-#endif
-	if (pDCB->WaitSRBCnt || pDCB->GoingSRBCnt) SPRINTF ("\n");
-	pDCB = pDCB->pNextDCB;
-    }
-	
-#ifdef DC390_DEBUGDCB
-    SPRINTF ("DCB list for ACB %p:\n", pACB);
-    pDCB = pACB->pLinkDCB;
-    SPRINTF ("%p", pDCB);
-    for (dev = 0; dev < pACB->DCBCnt; dev++, pDCB=pDCB->pNextDCB)
-	SPRINTF ("->%p", pDCB->pNextDCB);
-    SPRINTF("\n");
-#endif
-  
-  *start = buffer + offset;
-
-  if (pos - buffer < offset)
-    return 0;
-  else if (pos - buffer - offset < length)
-    return pos - buffer - offset;
-  else
-    return length;
-}
-
-#undef YESNO
-#undef SPRINTF
 
 static struct pci_driver dc390_driver = {
 	.name           = "tmscsim",
diff -Nru a/drivers/scsi/tmscsim.h b/drivers/scsi/tmscsim.h
--- a/drivers/scsi/tmscsim.h	2004-10-18 14:57:03 -07:00
+++ b/drivers/scsi/tmscsim.h	2004-10-18 14:57:03 -07:00
@@ -163,7 +163,6 @@
 struct dc390_srb	*pTmpSRB;
 
 u8		msgin123[4];
-u8		DCBmap[MAX_SCSI_ID];
 u8		Connected;
 u8		pad;
 
diff -Nru a/drivers/scsi/wd7000.c b/drivers/scsi/wd7000.c
--- a/drivers/scsi/wd7000.c	2004-10-18 14:57:04 -07:00
+++ b/drivers/scsi/wd7000.c	2004-10-18 14:57:04 -07:00
@@ -190,7 +190,6 @@
 #include <scsi/scsicam.h>
 
 
-#define ANY2SCSI_INLINE		/* undef this to use old macros */
 #undef  WD7000_DEBUG		/* general debug                */
 #ifdef WD7000_DEBUG
 #define dprintk printk
@@ -726,55 +725,17 @@
 
 __setup("wd7000=", wd7000_setup);
 
-#ifdef ANY2SCSI_INLINE
-/*
- * Since they're used a lot, I've redone the following from the macros
- * formerly in wd7000.h, hopefully to speed them up by getting rid of
- * all the shifting (it may not matter; GCC might have done as well anyway).
- *
- * xany2scsi and xscsi2int were not being used, and are no longer defined.
- * (They were simply 4-byte versions of these routines).
- */
-typedef union {			/* let's cheat... */
-	int i;
-	unchar u[sizeof(int)];	/* the sizeof(int) makes it more portable */
-} i_u;
-
-
 static inline void any2scsi(unchar * scsi, int any)
 {
-	*scsi++ = ((i_u) any).u[2];
-	*scsi++ = ((i_u) any).u[1];
-	*scsi++ = ((i_u) any).u[0];
+	*scsi++ = (unsigned)any >> 16;
+	*scsi++ = (unsigned)any >> 8;
+	*scsi++ = any;
 }
 
-
 static inline int scsi2int(unchar * scsi)
 {
-	i_u result;
-
-	result.i = 0;		/* clears unused bytes */
-	result.u[2] = *scsi++;
-	result.u[1] = *scsi++;
-	result.u[0] = *scsi++;
-
-	return (result.i);
+	return (scsi[0] << 16) | (scsi[1] << 8) | scsi[2];
 }
-#else
-/*
- * These are the old ones - I've just moved them here...
- */
-#undef any2scsi
-#define any2scsi(up, p)   (up)[0] = (((unsigned long) (p)) >> 16);	\
-			  (up)[1] = ((unsigned long) (p)) >> 8;		\
-			  (up)[2] = ((unsigned long) (p));
-
-#undef scsi2int
-#define scsi2int(up)   ( (((unsigned long) *(up)) << 16) +	\
-			 (((unsigned long) (up)[1]) << 8) +	\
-			 ((unsigned long) (up)[2]) )
-#endif
-
 
 static inline void wd7000_enable_intr(Adapter * host)
 {
diff -Nru a/drivers/serial/68328serial.c b/drivers/serial/68328serial.c
--- a/drivers/serial/68328serial.c	2004-10-18 14:57:04 -07:00
+++ b/drivers/serial/68328serial.c	2004-10-18 14:57:04 -07:00
@@ -435,10 +435,7 @@
 		return;
 #if 0
 	if (clear_bit(RS_EVENT_WRITE_WAKEUP, &info->event)) {
-		if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
-		    tty->ldisc.write_wakeup)
-			(tty->ldisc.write_wakeup)(tty);
-		wake_up_interruptible(&tty->write_wait);
+		tty_wakeup(tty);
 	}
 #endif   
 }
@@ -858,10 +855,7 @@
 	cli();
 	info->xmit_cnt = info->xmit_head = info->xmit_tail = 0;
 	sti();
-	wake_up_interruptible(&tty->write_wait);
-	if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
-	    tty->ldisc.write_wakeup)
-		(tty->ldisc.write_wakeup)(tty);
+	tty_wakeup(tty);
 }
 
 /*
@@ -1185,11 +1179,13 @@
 	shutdown(info);
 	if (tty->driver->flush_buffer)
 		tty->driver->flush_buffer(tty);
-	if (tty->ldisc.flush_buffer)
-		tty->ldisc.flush_buffer(tty);
+		
+	tty_ldisc_flush(tty);
 	tty->closing = 0;
 	info->event = 0;
 	info->tty = 0;
+#warning "This is not and has never been valid so fix it"	
+#if 0
 	if (tty->ldisc.num != ldiscs[N_TTY].num) {
 		if (tty->ldisc.close)
 			(tty->ldisc.close)(tty);
@@ -1198,6 +1194,7 @@
 		if (tty->ldisc.open)
 			(tty->ldisc.open)(tty);
 	}
+#endif	
 	if (info->blocked_open) {
 		if (info->close_delay) {
 			current->state = TASK_INTERRUPTIBLE;
diff -Nru a/drivers/serial/68360serial.c b/drivers/serial/68360serial.c
--- a/drivers/serial/68360serial.c	2004-10-18 14:57:04 -07:00
+++ b/drivers/serial/68360serial.c	2004-10-18 14:57:04 -07:00
@@ -700,12 +700,8 @@
 	if (!tty)
 		return;
 
-	if (test_and_clear_bit(RS_EVENT_WRITE_WAKEUP, &info->event)) {
-		if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
-		    tty->ldisc.write_wakeup)
-			(tty->ldisc.write_wakeup)(tty);
-		wake_up_interruptible(&tty->write_wait);
-	}
+	if (test_and_clear_bit(RS_EVENT_WRITE_WAKEUP, &info->event))
+		tty_wakeup(tty);
 }
 
 
@@ -1152,10 +1148,7 @@
 	/* There is nothing to "flush", whatever we gave the CPM
 	 * is on its way out.
 	 */
-	wake_up_interruptible(&tty->write_wait);
-	if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
-	    tty->ldisc.write_wakeup)
-		(tty->ldisc.write_wakeup)(tty);
+	tty_wakeup(tty);
 	info->flags &= ~TX_WAKEUP;
 }
 
@@ -1716,8 +1709,7 @@
 	shutdown(info);
 	if (tty->driver->flush_buffer)
 		tty->driver->flush_buffer(tty);
-	if (tty->ldisc.flush_buffer)
-		tty->ldisc.flush_buffer(tty);
+	tty_ldisc_flush(tty);		
 	tty->closing = 0;
 	info->event = 0;
 	info->tty = 0;
@@ -2592,7 +2584,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 irq 0x%02x is an %s\n",
+		printk(KERN_INFO "ttyS%d at irq 0x%02x is an %s\n",
 		       i, (unsigned int)(state->irq),
 		       (state->smc_scc_num & NUM_IS_SCC) ? "SCC" : "SMC");
 
diff -Nru a/drivers/serial/8250.c b/drivers/serial/8250.c
--- a/drivers/serial/8250.c	2004-10-18 14:55:54 -07:00
+++ b/drivers/serial/8250.c	2004-10-18 14:55:54 -07:00
@@ -130,6 +130,7 @@
 	struct timer_list	timer;		/* "no irq" timer */
 	struct list_head	list;		/* ports on this IRQ */
 	unsigned int		capabilities;	/* port capabilities */
+	unsigned int		tx_loadsz;	/* transmit fifo load size */
 	unsigned short		rev;
 	unsigned char		acr;
 	unsigned char		ier;
@@ -156,23 +157,23 @@
 /*
  * Here we define the default xmit fifo size used for each type of UART.
  */
-static const struct serial_uart_config uart_config[PORT_MAX_8250+1] = {
-	{ "unknown",	1,	0 },
-	{ "8250",	1,	0 },
-	{ "16450",	1,	0 },
-	{ "16550",	1,	0 },
-	{ "16550A",	16,	UART_CLEAR_FIFO | UART_USE_FIFO },
-	{ "Cirrus",	1, 	0 },
-	{ "ST16650",	1,	UART_CLEAR_FIFO | UART_STARTECH },
-	{ "ST16650V2",	32,	UART_CLEAR_FIFO | UART_USE_FIFO | UART_STARTECH },
-	{ "TI16750",	64,	UART_CLEAR_FIFO | UART_USE_FIFO },
-	{ "Startech",	1,	0 },
-	{ "16C950/954",	128,	UART_CLEAR_FIFO | UART_USE_FIFO },
-	{ "ST16654",	64,	UART_CLEAR_FIFO | UART_USE_FIFO | UART_STARTECH },
-	{ "XR16850",	128,	UART_CLEAR_FIFO | UART_USE_FIFO | UART_STARTECH },
-	{ "RSA",	2048,	UART_CLEAR_FIFO | UART_USE_FIFO },
-	{ "NS16550A",	16,	UART_CLEAR_FIFO | UART_USE_FIFO | UART_NATSEMI },
-	{ "XScale",	32,	UART_CLEAR_FIFO | UART_USE_FIFO  },
+static const struct serial8250_config uart_config[PORT_MAX_8250+1] = {
+	{ "unknown",	1,	1,	0 },
+	{ "8250",	1,	1,	0 },
+	{ "16450",	1,	1,	0 },
+	{ "16550",	1,	1,	0 },
+	{ "16550A",	16,	16,	UART_CAP_FIFO },
+	{ "Cirrus",	1, 	1,	0 },
+	{ "ST16650",	1,	1,	UART_CAP_FIFO | UART_CAP_SLEEP | UART_CAP_EFR },
+	{ "ST16650V2",	32,	16,	UART_CAP_FIFO | UART_CAP_SLEEP | UART_CAP_EFR },
+	{ "TI16750",	64,	64,	UART_CAP_FIFO | UART_CAP_SLEEP },
+	{ "Startech",	1,	1,	0 },
+	{ "16C950/954",	128,	128,	UART_CAP_FIFO },
+	{ "ST16654",	64,	32,	UART_CAP_FIFO | UART_CAP_SLEEP | UART_CAP_EFR },
+	{ "XR16850",	128,	128,	UART_CAP_FIFO | UART_CAP_SLEEP | UART_CAP_EFR },
+	{ "RSA",	2048,	2048,	UART_CAP_FIFO },
+	{ "NS16550A",	16,	16,	UART_CAP_FIFO | UART_NATSEMI },
+	{ "XScale",	32,	32,	UART_CAP_FIFO },
 };
 
 static _INLINE_ unsigned int serial_in(struct uart_8250_port *up, int offset)
@@ -187,6 +188,9 @@
 	case UPIO_MEM:
 		return readb(up->port.membase + offset);
 
+	case UPIO_MEM32:
+		return readl(up->port.membase + offset);
+
 	default:
 		return inb(up->port.iobase + offset);
 	}
@@ -207,6 +211,10 @@
 		writeb(value, up->port.membase + offset);
 		break;
 
+	case UPIO_MEM32:
+		writel(value, up->port.membase + offset);
+		break;
+
 	default:
 		outb(value, up->port.iobase + offset);
 	}
@@ -243,6 +251,41 @@
 	return value;
 }
 
+/*
+ * FIFO support.
+ */
+static inline void serial8250_clear_fifos(struct uart_8250_port *p)
+{
+	if (p->capabilities & UART_CAP_FIFO) {
+		serial_outp(p, UART_FCR, UART_FCR_ENABLE_FIFO);
+		serial_outp(p, UART_FCR, UART_FCR_ENABLE_FIFO |
+			       UART_FCR_CLEAR_RCVR | UART_FCR_CLEAR_XMIT);
+		serial_outp(p, UART_FCR, 0);
+	}
+}
+
+/*
+ * IER sleep support.  UARTs which have EFRs need the "extended
+ * capability" bit enabled.  Note that on XR16C850s, we need to
+ * reset LCR to write to IER.
+ */
+static inline void serial8250_set_sleep(struct uart_8250_port *p, int sleep)
+{
+	if (p->capabilities & UART_CAP_SLEEP) {
+		if (p->capabilities & UART_CAP_EFR) {
+			serial_outp(p, UART_LCR, 0xBF);
+			serial_outp(p, UART_EFR, UART_EFR_ECB);
+			serial_outp(p, UART_LCR, 0);
+		}
+		serial_outp(p, UART_IER, sleep ? UART_IERX_SLEEP : 0);
+		if (p->capabilities & UART_CAP_EFR) {
+			serial_outp(p, UART_LCR, 0xBF);
+			serial_outp(p, UART_EFR, 0);
+			serial_outp(p, UART_LCR, 0);
+		}
+	}
+}
+
 #ifdef CONFIG_SERIAL_8250_RSA
 /*
  * Attempts to turn on the RSA FIFO.  Returns zero on failure.
@@ -697,8 +740,9 @@
 #endif
 	serial_outp(up, UART_LCR, save_lcr);
 
-	up->port.fifosize = uart_config[up->port.type].dfl_xmit_fifo_size;
+	up->port.fifosize = uart_config[up->port.type].fifo_size;
 	up->capabilities = uart_config[up->port.type].flags;
+	up->tx_loadsz = uart_config[up->port.type].tx_loadsz;
 
 	if (up->port.type == PORT_UNKNOWN)
 		goto out;
@@ -711,10 +755,7 @@
 		serial_outp(up, UART_RSA_FRR, 0);
 #endif
 	serial_outp(up, UART_MCR, save_mcr);
-	serial_outp(up, UART_FCR, (UART_FCR_ENABLE_FIFO |
-				     UART_FCR_CLEAR_RCVR |
-				     UART_FCR_CLEAR_XMIT));
-	serial_outp(up, UART_FCR, 0);
+	serial8250_clear_fifos(up);
 	(void)serial_in(up, UART_RX);
 	serial_outp(up, UART_IER, 0);
 
@@ -923,7 +964,7 @@
 		return;
 	}
 
-	count = up->port.fifosize;
+	count = up->tx_loadsz;
 	do {
 		serial_out(up, UART_TX, xmit->buf[xmit->tail]);
 		xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
@@ -1227,12 +1268,7 @@
 	 * Clear the FIFO buffers and disable them.
 	 * (they will be reeanbled in set_termios())
 	 */
-	if (up->capabilities & UART_CLEAR_FIFO) {
-		serial_outp(up, UART_FCR, UART_FCR_ENABLE_FIFO);
-		serial_outp(up, UART_FCR, UART_FCR_ENABLE_FIFO |
-				UART_FCR_CLEAR_RCVR | UART_FCR_CLEAR_XMIT);
-		serial_outp(up, UART_FCR, 0);
-	}
+	serial8250_clear_fifos(up);
 
 	/*
 	 * Clear the interrupt registers.
@@ -1254,6 +1290,23 @@
 	}
 
 	/*
+	 * For a XR16C850, we need to set the trigger levels
+	 */
+	if (up->port.type == PORT_16850) {
+		unsigned char fctr;
+
+		serial_outp(up, UART_LCR, 0xbf);
+
+		fctr = serial_inp(up, UART_FCTR) & ~(UART_FCTR_RX|UART_FCTR_TX);
+		serial_outp(up, UART_FCTR, fctr | UART_FCTR_TRGD | UART_FCTR_RX);
+		serial_outp(up, UART_TRG, UART_TRG_96);
+		serial_outp(up, UART_FCTR, fctr | UART_FCTR_TRGD | UART_FCTR_TX);
+		serial_outp(up, UART_TRG, UART_TRG_96);
+
+		serial_outp(up, UART_LCR, 0);
+	}
+
+	/*
 	 * If the "interrupt" for this port doesn't correspond with any
 	 * hardware interrupt, we use a timer-based system.  The original
 	 * driver used to do this with IRQ0.
@@ -1345,10 +1398,7 @@
 	 * Disable break condition and FIFOs
 	 */
 	serial_out(up, UART_LCR, serial_inp(up, UART_LCR) & ~UART_LCR_SBC);
-	serial_outp(up, UART_FCR, UART_FCR_ENABLE_FIFO |
-				  UART_FCR_CLEAR_RCVR |
-				  UART_FCR_CLEAR_XMIT);
-	serial_outp(up, UART_FCR, 0);
+	serial8250_clear_fifos(up);
 
 #ifdef CONFIG_SERIAL_8250_RSA
 	/*
@@ -1440,7 +1490,7 @@
 	    up->rev == 0x5201)
 		quot ++;
 
-	if (up->capabilities & UART_USE_FIFO) {
+	if (up->capabilities & UART_CAP_FIFO && up->port.fifosize > 1) {
 		if (baud < 2400)
 			fcr = UART_FCR_ENABLE_FIFO | UART_FCR_TRIGGER_1;
 #ifdef CONFIG_SERIAL_8250_RSA
@@ -1514,7 +1564,7 @@
 
 	serial_out(up, UART_IER, up->ier);
 
-	if (up->capabilities & UART_STARTECH) {
+	if (up->capabilities & UART_CAP_EFR) {
 		serial_outp(up, UART_LCR, 0xBF);
 		serial_outp(up, UART_EFR,
 			    termios->c_cflag & CRTSCTS ? UART_EFR_CTS :0);
@@ -1554,71 +1604,12 @@
 serial8250_pm(struct uart_port *port, unsigned int state,
 	      unsigned int oldstate)
 {
-	struct uart_8250_port *up = (struct uart_8250_port *)port;
-	if (state) {
-		/* sleep */
-		if (up->capabilities & UART_STARTECH) {
-			/* Arrange to enter sleep mode */
-			serial_outp(up, UART_LCR, 0xBF);
-			serial_outp(up, UART_EFR, UART_EFR_ECB);
-			serial_outp(up, UART_LCR, 0);
-			serial_outp(up, UART_IER, UART_IERX_SLEEP);
-			serial_outp(up, UART_LCR, 0xBF);
-			serial_outp(up, UART_EFR, 0);
-			serial_outp(up, UART_LCR, 0);
-		}
-		if (up->port.type == PORT_16750) {
-			/* Arrange to enter sleep mode */
-			serial_outp(up, UART_IER, UART_IERX_SLEEP);
-		}
+	struct uart_8250_port *p = (struct uart_8250_port *)port;
 
-		if (up->pm)
-			up->pm(port, state, oldstate);
-	} else {
-		/* wake */
-		if (up->capabilities & UART_STARTECH) {
-			/* Wake up UART */
-			serial_outp(up, UART_LCR, 0xBF);
-			serial_outp(up, UART_EFR, UART_EFR_ECB);
-			/*
-			 * Turn off LCR == 0xBF so we actually set the IER
-			 * register on the XR16C850
-			 */
-			serial_outp(up, UART_LCR, 0);
-			serial_outp(up, UART_IER, 0);
-			/*
-			 * Now reset LCR so we can turn off the ECB bit
-			 */
-			serial_outp(up, UART_LCR, 0xBF);
-			serial_outp(up, UART_EFR, 0);
-			/*
-			 * For a XR16C850, we need to set the trigger levels
-			 */
-			if (up->port.type == PORT_16850) {
-				unsigned char fctr;
+	serial8250_set_sleep(p, state != 0);
 
-				fctr = serial_inp(up, UART_FCTR) &
-					 ~(UART_FCTR_RX | UART_FCTR_TX);
-				serial_outp(up, UART_FCTR, fctr |
-						UART_FCTR_TRGD |
-						UART_FCTR_RX);
-				serial_outp(up, UART_TRG, UART_TRG_96);
-				serial_outp(up, UART_FCTR, fctr |
-						UART_FCTR_TRGD |
-						UART_FCTR_TX);
-				serial_outp(up, UART_TRG, UART_TRG_96);
-			}
-			serial_outp(up, UART_LCR, 0);
-		}
-
-		if (up->port.type == PORT_16750) {
-			/* Wake up UART */
-			serial_outp(up, UART_IER, 0);
-		}
-
-		if (up->pm)
-			up->pm(port, state, oldstate);
-	}
+	if (p->pm)
+		p->pm(port, state, oldstate);
 }
 
 /*
diff -Nru a/drivers/serial/8250.h b/drivers/serial/8250.h
--- a/drivers/serial/8250.h	2004-10-18 14:55:53 -07:00
+++ b/drivers/serial/8250.h	2004-10-18 14:55:53 -07:00
@@ -33,6 +33,20 @@
 	unsigned short iomem_reg_shift;
 };
 
+/*
+ * This replaces serial_uart_config in include/linux/serial.h
+ */
+struct serial8250_config {
+	const char	*name;
+	unsigned int	fifo_size;
+	unsigned int	tx_loadsz;
+	unsigned int	flags;
+};
+
+#define UART_CAP_FIFO	(1 << 8)	/* UART has FIFO */
+#define UART_CAP_EFR	(1 << 9)	/* UART has EFR */
+#define UART_CAP_SLEEP	(1 << 10)	/* UART has IER sleep */
+
 #undef SERIAL_DEBUG_PCI
 
 #if defined(__i386__) && (defined(CONFIG_M386) || defined(CONFIG_M486))
diff -Nru a/drivers/serial/8250_pci.c b/drivers/serial/8250_pci.c
--- a/drivers/serial/8250_pci.c	2004-10-18 14:56:49 -07:00
+++ b/drivers/serial/8250_pci.c	2004-10-18 14:56:49 -07:00
@@ -83,7 +83,7 @@
 
 struct serial_private {
 	unsigned int		nr;
-	void			*remapped_bar[PCI_NUM_BAR_RESOURCES];
+	void __iomem		*remapped_bar[PCI_NUM_BAR_RESOURCES];
 	struct pci_serial_quirk	*quirk;
 	int			line[0];
 };
@@ -243,7 +243,8 @@
  */
 static int __devinit pci_plx9050_init(struct pci_dev *dev)
 {
-	u8 *p, irq_config;
+	u8 irq_config;
+	void __iomem *p;
 
 	if ((pci_resource_flags(dev, 0) & IORESOURCE_MEM) == 0) {
 		moan_device("no memory in bar 0", dev);
@@ -272,12 +273,12 @@
 	p = ioremap(pci_resource_start(dev, 0), 0x80);
 	if (p == NULL)
 		return -ENOMEM;
-	writel(irq_config, (unsigned long)p + 0x4c);
+	writel(irq_config, p + 0x4c);
 
 	/*
 	 * Read the register back to ensure that it took effect.
 	 */
-	readl((unsigned long)p + 0x4c);
+	readl(p + 0x4c);
 	iounmap(p);
 
 	return 0;
@@ -397,7 +398,8 @@
 
 static int pci_siig10x_init(struct pci_dev *dev)
 {
-	u16 data, *p;
+	u16 data;
+	void __iomem *p;
 
 	switch (dev->device & 0xfff8) {
 	case PCI_DEVICE_ID_SIIG_1S_10x:	/* 1S */
@@ -415,8 +417,8 @@
 	if (p == NULL)
 		return -ENOMEM;
 
-	writew(readw((unsigned long) p + 0x28) & data, (unsigned long) p + 0x28);
-	readw((unsigned long)p + 0x28);
+	writew(readw(p + 0x28) & data, p + 0x28);
+	readw(p + 0x28);
 	iounmap(p);
 	return 0;
 }
@@ -1068,6 +1070,9 @@
 	pbn_computone_6,
 	pbn_computone_8,
 	pbn_sbsxrsio,
+	pbn_exar_XR17C152,
+	pbn_exar_XR17C154,
+	pbn_exar_XR17C158,
 };
 
 /*
@@ -1488,7 +1493,30 @@
 		.base_baud	= 460800,
 		.uart_offset	= 256,
 		.reg_shift	= 4,
-	}
+	},
+	/*
+	 * Exar Corp. XR17C15[248] Dual/Quad/Octal UART
+	 *  Only basic 16550A support.
+	 *  XR17C15[24] are not tested, but they should work.
+	 */
+	[pbn_exar_XR17C152] = {
+		.flags		= FL_BASE0,
+		.num_ports	= 2,
+		.base_baud	= 921600,
+		.uart_offset	= 0x200,
+	},
+	[pbn_exar_XR17C154] = {
+		.flags		= FL_BASE0,
+		.num_ports	= 4,
+		.base_baud	= 921600,
+		.uart_offset	= 0x200,
+	},
+	[pbn_exar_XR17C158] = {
+		.flags		= FL_BASE0,
+		.num_ports	= 8,
+		.base_baud	= 921600,
+		.uart_offset	= 0x200,
+	},
 };
 
 /*
@@ -2146,6 +2174,22 @@
 	{	PCI_VENDOR_ID_DCI, PCI_DEVICE_ID_DCI_PCCOM8,
 		PCI_ANY_ID, PCI_ANY_ID, 0, 0,
 		pbn_b3_8_115200 },
+
+	/*
+	 * Exar Corp. XR17C15[248] Dual/Quad/Octal UART
+	 */
+	{	PCI_VENDOR_ID_EXAR, PCI_DEVICE_ID_EXAR_XR17C152,
+		PCI_ANY_ID, PCI_ANY_ID,
+		0,
+		0, pbn_exar_XR17C152 },
+	{	PCI_VENDOR_ID_EXAR, PCI_DEVICE_ID_EXAR_XR17C154,
+		PCI_ANY_ID, PCI_ANY_ID,
+		0,
+		0, pbn_exar_XR17C154 },
+	{	PCI_VENDOR_ID_EXAR, PCI_DEVICE_ID_EXAR_XR17C158,
+		PCI_ANY_ID, PCI_ANY_ID,
+		0,
+		0, pbn_exar_XR17C158 },
 
 	/*
 	 * These entries match devices with class COMMUNICATION_SERIAL,
diff -Nru a/drivers/serial/Kconfig b/drivers/serial/Kconfig
--- a/drivers/serial/Kconfig	2004-10-18 14:57:03 -07:00
+++ b/drivers/serial/Kconfig	2004-10-18 14:57:03 -07:00
@@ -450,7 +450,7 @@
 
 config PDC_CONSOLE
 	bool "PDC software console support"
-	depends on PARISC && !SERIAL_MUX
+	depends on PARISC && !SERIAL_MUX && VT
 	default n
 	help
 	  Saying Y here will enable the software based PDC console to be 
@@ -682,6 +682,7 @@
 	bool "SGI Altix L1 serial console support"
 	depends on IA64_GENERIC || IA64_SGI_SN2
 	select SERIAL_CORE
+	select SERIAL_CORE_CONSOLE
 	help
 		If you have an SGI Altix and you would like to use the system
 		controller serial port as your console (you want this!),
@@ -713,5 +714,17 @@
 	  Select the MPC52xx console baud rate.
 	  This value is only used if the bootloader doesn't pass in the
 	  console baudrate
+
+config SERIAL_ICOM
+	tristate "IBM Multiport Serial Adapter"
+	depends on PPC_ISERIES || PPC_PSERIES
+	select SERIAL_CORE
+	help
+	  This driver is for a family of multiport serial adapters
+	  including 2 port RVX, 2 port internal modem, 4 port internal
+	  modem and a split 1 port RVX and 1 port internal modem.
+
+	  This driver can also be built as a module.  If so, the module
+	  will be called icom.
 
 endmenu
diff -Nru a/drivers/serial/amba-pl011.c b/drivers/serial/amba-pl011.c
--- a/drivers/serial/amba-pl011.c	2004-10-18 14:57:05 -07:00
+++ b/drivers/serial/amba-pl011.c	2004-10-18 14:57:05 -07:00
@@ -696,7 +696,6 @@
 	int bits = 8;
 	int parity = 'n';
 	int flow = 'n';
-	int ret;
 
 	/*
 	 * Check whether an invalid uart number has been specified, and
diff -Nru a/drivers/serial/bast_sio.c b/drivers/serial/bast_sio.c
--- a/drivers/serial/bast_sio.c	2004-10-18 14:55:54 -07:00
+++ b/drivers/serial/bast_sio.c	2004-10-18 14:55:54 -07:00
@@ -1,3 +1,19 @@
+/* linux/drivers/serial/bast_sio.c
+ *
+ * Copyright (c) 2004 Simtec Electronics
+ *   Ben Dooks <ben@simtec.co.uk>
+ *
+ * http://www.simtec.co.uk/products/EB2410ITX/
+ *
+ * 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.
+ *
+ * Modifications:
+ *	23-Sep-2004  BJD  Added copyright header
+ *	23-Sep-2004  BJD  Added serial port remove code
+*/
+
 #include <linux/module.h>
 #include <linux/config.h>
 #include <linux/kernel.h>
@@ -20,10 +36,6 @@
 {
 	struct serial_struct serial_req;
 
-#if 0
-	printk("BAST: SuperIO serial (%08lx,%d)\n", port, irq);
-#endif
-
 	serial_req.flags      = UPF_AUTOPROBE | UPF_SHARE_IRQ;
 	serial_req.baud_base  = BASE_BAUD;
 	serial_req.irq        = irq;
@@ -37,11 +49,13 @@
 
 #define SERIAL_BASE (S3C2410_CS2 + BAST_PA_SUPERIO)
 
+static int port[2] = { -1, -1 };
+
 static int __init serial_bast_init(void)
 {
 	if (machine_is_bast()) {
-		serial_bast_register(SERIAL_BASE + 0x2f8, IRQ_PCSERIAL1);
-		serial_bast_register(SERIAL_BASE + 0x3f8, IRQ_PCSERIAL2);
+		port[0] = serial_bast_register(SERIAL_BASE + 0x2f8, IRQ_PCSERIAL1);
+		port[1] = serial_bast_register(SERIAL_BASE + 0x3f8, IRQ_PCSERIAL2);
 	}
 
 	return 0;
@@ -49,7 +63,10 @@
 
 static void __exit serial_bast_exit(void)
 {
-	/* todo -> remove both our ports */
+	if (port[0] != -1)
+		unregister_serial(port[0]);
+	if (port[1] != -1)
+		unregister_serial(port[1]);
 }
 
 
diff -Nru a/drivers/serial/icom.c b/drivers/serial/icom.c
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/drivers/serial/icom.c	2004-10-18 14:57:22 -07:00
@@ -0,0 +1,1702 @@
+/*
+  * icom.c
+  *
+  * Copyright (C) 2001 IBM Corporation. All rights reserved.
+  *
+  * Serial device driver.
+  *
+  * Based on code from serial.c
+  *
+  * 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
+  *
+  */
+#define SERIAL_DO_RESTART
+#include <linux/module.h>
+#include <linux/config.h>
+#include <linux/version.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/signal.h>
+#include <linux/sched.h>
+#include <linux/timer.h>
+#include <linux/interrupt.h>
+#include <linux/tty.h>
+#include <linux/termios.h>
+#include <linux/fs.h>
+#include <linux/tty_flip.h>
+#include <linux/serial.h>
+#include <linux/serial_reg.h>
+#include <linux/major.h>
+#include <linux/string.h>
+#include <linux/fcntl.h>
+#include <linux/ptrace.h>
+#include <linux/ioport.h>
+#include <linux/mm.h>
+#include <linux/slab.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/pci.h>
+#include <linux/vmalloc.h>
+#include <linux/smp.h>
+#include <linux/smp_lock.h>
+#include <linux/spinlock.h>
+#include <linux/kobject.h>
+#include <linux/firmware.h>
+
+#include <asm/system.h>
+#include <asm/segment.h>
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/uaccess.h>
+#include <asm/bitops.h>
+
+#include "icom.h"
+
+/*#define ICOM_TRACE		 enable port trace capabilities */
+
+#define ICOM_DRIVER_NAME "icom"
+#define ICOM_VERSION_STR "1.3.1"
+#define NR_PORTS	       128
+#define ICOM_PORT ((struct icom_port *)port)
+#define to_icom_adapter(d) container_of(d, struct icom_adapter, kobj)
+
+static const struct pci_device_id icom_pci_table[] = {
+	{
+	      .vendor = PCI_VENDOR_ID_IBM,
+	      .device = PCI_DEVICE_ID_IBM_ICOM_DEV_ID_1,
+	      .subvendor = PCI_ANY_ID,
+	      .subdevice = PCI_ANY_ID,
+	      .driver_data = ADAPTER_V1,
+	 },
+	{
+	      .vendor = PCI_VENDOR_ID_IBM,
+	      .device = PCI_DEVICE_ID_IBM_ICOM_DEV_ID_2,
+	      .subvendor = PCI_VENDOR_ID_IBM,
+	      .subdevice = PCI_DEVICE_ID_IBM_ICOM_V2_TWO_PORTS_RVX,
+	      .driver_data = ADAPTER_V2,
+	 },
+	{
+	      .vendor = PCI_VENDOR_ID_IBM,
+	      .device = PCI_DEVICE_ID_IBM_ICOM_DEV_ID_2,
+	      .subvendor = PCI_VENDOR_ID_IBM,
+	      .subdevice = PCI_DEVICE_ID_IBM_ICOM_V2_ONE_PORT_RVX_ONE_PORT_MDM,
+	      .driver_data = ADAPTER_V2,
+	 },
+	{
+	      .vendor = PCI_VENDOR_ID_IBM,
+	      .device = PCI_DEVICE_ID_IBM_ICOM_DEV_ID_2,
+	      .subvendor = PCI_VENDOR_ID_IBM,
+	      .subdevice = PCI_DEVICE_ID_IBM_ICOM_FOUR_PORT_MODEL,
+	      .driver_data = ADAPTER_V2,
+	 },
+	{}
+};
+
+struct lookup_proc_table start_proc[4] = {
+	{0, ICOM_CONTROL_START_A},
+	{0, ICOM_CONTROL_START_B},
+	{0, ICOM_CONTROL_START_C},
+	{0, ICOM_CONTROL_START_D}
+};
+
+
+struct lookup_proc_table stop_proc[4] = {
+	{0, ICOM_CONTROL_STOP_A},
+	{0, ICOM_CONTROL_STOP_B},
+	{0, ICOM_CONTROL_STOP_C},
+	{0, ICOM_CONTROL_STOP_D}
+};
+
+struct lookup_int_table int_mask_tbl[4] = {
+	{0, ICOM_INT_MASK_PRC_A},
+	{0, ICOM_INT_MASK_PRC_B},
+	{0, ICOM_INT_MASK_PRC_C},
+	{0, ICOM_INT_MASK_PRC_D},
+};
+
+
+MODULE_DEVICE_TABLE(pci, icom_pci_table);
+
+static LIST_HEAD(icom_adapter_head);
+
+/* spinlock for adapter initialization and changing adapter operations */
+static spinlock_t icom_lock;
+
+#ifdef ICOM_TRACE
+static inline void trace(struct icom_port *, char *, unsigned long) {};
+#else
+static inline void trace(struct icom_port *icom_port, char *trace_pt, unsigned long trace_data) {};
+#endif
+
+static void msleep(unsigned long msecs)
+{
+	set_current_state(TASK_UNINTERRUPTIBLE);
+	schedule_timeout(MSECS_TO_JIFFIES(msecs));
+}
+
+static void free_port_memory(struct icom_port *icom_port)
+{
+	struct pci_dev *dev = icom_port->adapter->pci_dev;
+
+	trace(icom_port, "RET_PORT_MEM", 0);
+	if (icom_port->recv_buf) {
+		pci_free_consistent(dev, 4096, icom_port->recv_buf,
+				    icom_port->recv_buf_pci);
+		icom_port->recv_buf = 0;
+	}
+	if (icom_port->xmit_buf) {
+		pci_free_consistent(dev, 4096, icom_port->xmit_buf,
+				    icom_port->xmit_buf_pci);
+		icom_port->xmit_buf = 0;
+	}
+	if (icom_port->statStg) {
+		pci_free_consistent(dev, 4096, icom_port->statStg,
+				    icom_port->statStg_pci);
+		icom_port->statStg = 0;
+	}
+
+	if (icom_port->xmitRestart) {
+		pci_free_consistent(dev, 4096, icom_port->xmitRestart,
+				    icom_port->xmitRestart_pci);
+		icom_port->xmitRestart = 0;
+	}
+}
+
+static int __init get_port_memory(struct icom_port *icom_port)
+{
+	int index;
+	unsigned long stgAddr;
+	unsigned long startStgAddr;
+	unsigned long offset;
+	struct pci_dev *dev = icom_port->adapter->pci_dev;
+
+	icom_port->xmit_buf =
+	    pci_alloc_consistent(dev, 4096, &icom_port->xmit_buf_pci);
+	if (!icom_port->xmit_buf) {
+		dev_err(&dev->dev, "Can not allocate Transmit buffer\n");
+		return -ENOMEM;
+	}
+
+	trace(icom_port, "GET_PORT_MEM",
+	      (unsigned long) icom_port->xmit_buf);
+
+	icom_port->recv_buf =
+	    pci_alloc_consistent(dev, 4096, &icom_port->recv_buf_pci);
+	if (!icom_port->recv_buf) {
+		dev_err(&dev->dev, "Can not allocate Receive buffer\n");
+		free_port_memory(icom_port);
+		return -ENOMEM;
+	}
+	trace(icom_port, "GET_PORT_MEM",
+	      (unsigned long) icom_port->recv_buf);
+
+	icom_port->statStg =
+	    pci_alloc_consistent(dev, 4096, &icom_port->statStg_pci);
+	if (!icom_port->statStg) {
+		dev_err(&dev->dev, "Can not allocate Status buffer\n");
+		free_port_memory(icom_port);
+		return -ENOMEM;
+	}
+	trace(icom_port, "GET_PORT_MEM",
+	      (unsigned long) icom_port->statStg);
+
+	icom_port->xmitRestart =
+	    pci_alloc_consistent(dev, 4096, &icom_port->xmitRestart_pci);
+	if (!icom_port->xmitRestart) {
+		dev_err(&dev->dev,
+			"Can not allocate xmit Restart buffer\n");
+		free_port_memory(icom_port);
+		return -ENOMEM;
+	}
+
+	memset(icom_port->statStg, 0, 4096);
+
+	/* FODs: Frame Out Descriptor Queue, this is a FIFO queue that
+           indicates that frames are to be transmitted
+	*/
+
+	stgAddr = (unsigned long) icom_port->statStg;
+	for (index = 0; index < NUM_XBUFFS; index++) {
+		trace(icom_port, "FOD_ADDR", stgAddr);
+		stgAddr = stgAddr + sizeof(icom_port->statStg->xmit[0]);
+		if (index < (NUM_XBUFFS - 1)) {
+			memset(&icom_port->statStg->xmit[index], 0, sizeof(struct xmit_status_area));
+			icom_port->statStg->xmit[index].leLengthASD =
+			    (unsigned short int) cpu_to_le16(XMIT_BUFF_SZ);
+			trace(icom_port, "FOD_ADDR", stgAddr);
+			trace(icom_port, "FOD_XBUFF",
+			      (unsigned long) icom_port->xmit_buf);
+			icom_port->statStg->xmit[index].leBuffer =
+			    cpu_to_le32(icom_port->xmit_buf_pci);
+		} else if (index == (NUM_XBUFFS - 1)) {
+			memset(&icom_port->statStg->xmit[index], 0, sizeof(struct xmit_status_area));
+			icom_port->statStg->xmit[index].leLengthASD =
+			    (unsigned short int) cpu_to_le16(XMIT_BUFF_SZ);
+			trace(icom_port, "FOD_XBUFF",
+			      (unsigned long) icom_port->xmit_buf);
+			icom_port->statStg->xmit[index].leBuffer =
+			    cpu_to_le32(icom_port->xmit_buf_pci);
+		} else {
+			memset(&icom_port->statStg->xmit[index], 0, sizeof(struct xmit_status_area));
+		}
+	}
+	/* FIDs */
+	startStgAddr = stgAddr;
+
+	/* fill in every entry, even if no buffer */
+	for (index = 0; index <  NUM_RBUFFS; index++) {
+		trace(icom_port, "FID_ADDR", stgAddr);
+		stgAddr = stgAddr + sizeof(icom_port->statStg->rcv[0]);
+		icom_port->statStg->rcv[index].leLength = 0;
+		icom_port->statStg->rcv[index].WorkingLength =
+		    (unsigned short int) cpu_to_le16(RCV_BUFF_SZ);
+		if (index < (NUM_RBUFFS - 1) ) {
+			offset = stgAddr - (unsigned long) icom_port->statStg;
+			icom_port->statStg->rcv[index].leNext =
+			      cpu_to_le32(icom_port-> statStg_pci + offset);
+			trace(icom_port, "FID_RBUFF",
+			      (unsigned long) icom_port->recv_buf);
+			icom_port->statStg->rcv[index].leBuffer =
+			    cpu_to_le32(icom_port->recv_buf_pci);
+		} else if (index == (NUM_RBUFFS -1) ) {
+			offset = startStgAddr - (unsigned long) icom_port->statStg;
+			icom_port->statStg->rcv[index].leNext =
+			    cpu_to_le32(icom_port-> statStg_pci + offset);
+			trace(icom_port, "FID_RBUFF",
+			      (unsigned long) icom_port->recv_buf + 2048);
+			icom_port->statStg->rcv[index].leBuffer =
+			    cpu_to_le32(icom_port->recv_buf_pci + 2048);
+		} else {
+			icom_port->statStg->rcv[index].leNext = 0;
+			icom_port->statStg->rcv[index].leBuffer = 0;
+		}
+	}
+
+	return 0;
+}
+
+static void stop_processor(struct icom_port *icom_port)
+{
+	unsigned long temp;
+	unsigned long flags;
+	int port;
+
+	spin_lock_irqsave(&icom_lock, flags);
+
+	port = icom_port->port;
+	if (port == 0 || port == 1)
+		stop_proc[port].global_control_reg = &icom_port->global_reg->control;
+	else
+		stop_proc[port].global_control_reg = &icom_port->global_reg->control_2;
+
+
+	if (port < 4) {
+		temp = readl(stop_proc[port].global_control_reg);
+		temp =
+	    		(temp & ~start_proc[port].processor_id) | stop_proc[port].processor_id;
+		writel(temp, stop_proc[port].global_control_reg);
+
+		/* write flush */
+		readl(stop_proc[port].global_control_reg);
+	} else {
+		dev_err(&icom_port->adapter->pci_dev->dev,
+                        "Invalid port assignment\n");
+	}
+
+	spin_unlock_irqrestore(&icom_lock, flags);
+}
+
+static void start_processor(struct icom_port *icom_port)
+{
+	unsigned long temp;
+	unsigned long flags;
+	int port;
+
+	spin_lock_irqsave(&icom_lock, flags);
+
+	port = icom_port->port;
+	if (port == 0 || port == 1)
+		start_proc[port].global_control_reg = &icom_port->global_reg->control;
+	else
+		start_proc[port].global_control_reg = &icom_port->global_reg->control_2;
+	if (port < 4) {
+		temp = readl(start_proc[port].global_control_reg);
+		temp =
+	    		(temp & ~stop_proc[port].processor_id) | start_proc[port].processor_id;
+		writel(temp, start_proc[port].global_control_reg);
+
+		/* write flush */
+		readl(start_proc[port].global_control_reg);
+	} else {
+		dev_err(&icom_port->adapter->pci_dev->dev,
+                        "Invalid port assignment\n");
+	}
+
+	spin_unlock_irqrestore(&icom_lock, flags);
+}
+
+static void load_code(struct icom_port *icom_port)
+{
+	const struct firmware *fw;
+	char *iram_ptr;
+	int index;
+	int status = 0;
+	char *dram_ptr = (char *) icom_port->dram;
+	dma_addr_t temp_pci;
+	unsigned char *new_page = NULL;
+	unsigned char cable_id = NO_CABLE;
+	struct pci_dev *dev = icom_port->adapter->pci_dev;
+
+	/* Clear out any pending interrupts */
+	writew(0x3FFF, (void *) icom_port->int_reg);
+
+	trace(icom_port, "CLEAR_INTERRUPTS", 0);
+
+	/* Stop processor */
+	stop_processor(icom_port);
+
+	/* Zero out DRAM */
+	memset_io(dram_ptr, 0, 512);
+
+	/* Load Call Setup into Adapter */
+	if (request_firmware(&fw, "icom_call_setup.bin", &dev->dev) < 0) {
+		dev_err(&dev->dev,"Unable to load icom_call_setup.bin firmware image\n");
+		status = -1;
+		goto load_code_exit;
+	}
+
+	if (fw->size > ICOM_DCE_IRAM_OFFSET) {
+		dev_err(&dev->dev, "Invalid firmware image for icom_call_setup.bin found.\n");
+		release_firmware(fw);
+		status = -1;
+		goto load_code_exit;
+	}
+
+	iram_ptr = (char *) icom_port->dram + ICOM_IRAM_OFFSET;
+	for (index = 0; index < fw->size; index++)
+		writeb(fw->data[index], &iram_ptr[index]);
+
+	release_firmware(fw);
+
+	/* Load Resident DCE portion of Adapter */
+	if (request_firmware(&fw, "icom_res_dce.bin", &dev->dev) < 0) {
+		dev_err(&dev->dev,"Unable to load icom_res_dce.bin firmware image\n");
+		status = -1;
+		goto load_code_exit;
+	}
+
+	if (fw->size > ICOM_IRAM_SIZE) {
+		dev_err(&dev->dev, "Invalid firmware image for icom_res_dce.bin found.\n");
+		release_firmware(fw);
+		status = -1;
+		goto load_code_exit;
+	}
+
+	iram_ptr = (char *) icom_port->dram + ICOM_IRAM_OFFSET;
+	for (index = ICOM_DCE_IRAM_OFFSET; index < fw->size; index++)
+		writeb(fw->data[index], &iram_ptr[index]);
+
+	release_firmware(fw);
+
+	/* Set Hardware level */
+	if ((icom_port->adapter->version | ADAPTER_V2) == ADAPTER_V2)
+		writeb(V2_HARDWARE, &(icom_port->dram->misc_flags));
+
+	/* Start the processor in Adapter */
+	start_processor(icom_port);
+
+	writeb((HDLC_PPP_PURE_ASYNC | HDLC_FF_FILL),
+	       &(icom_port->dram->HDLCConfigReg));
+	writeb(0x04, &(icom_port->dram->FlagFillIdleTimer));	/* 0.5 seconds */
+	writeb(0x00, &(icom_port->dram->CmdReg));
+	writeb(0x10, &(icom_port->dram->async_config3));
+	writeb((ICOM_ACFG_DRIVE1 | ICOM_ACFG_NO_PARITY | ICOM_ACFG_8BPC |
+		ICOM_ACFG_1STOP_BIT), &(icom_port->dram->async_config2));
+
+	/*Set up data in icom DRAM to indicate where personality
+	 *code is located and its length.
+	 */
+	new_page = pci_alloc_consistent(dev, 4096, &temp_pci);
+
+	if (!new_page) {
+		dev_err(&dev->dev, "Can not allocate DMA buffer\n");
+		status = -1;
+		goto load_code_exit;
+	}
+
+	if (request_firmware(&fw, "icom_asc.bin", &dev->dev) < 0) {
+		dev_err(&dev->dev,"Unable to load icom_asc.bin firmware image\n");
+		status = -1;
+		goto load_code_exit;
+	}
+
+	if (fw->size > ICOM_DCE_IRAM_OFFSET) {
+		dev_err(&dev->dev, "Invalid firmware image for icom_asc.bin found.\n");
+		release_firmware(fw);
+		status = -1;
+		goto load_code_exit;
+	}
+
+	for (index = 0; index < fw->size; index++)
+		new_page[index] = fw->data[index];
+
+	release_firmware(fw);
+
+	writeb((char) ((fw->size + 16)/16), &icom_port->dram->mac_length);
+	writel(temp_pci, &icom_port->dram->mac_load_addr);
+
+	/*Setting the syncReg to 0x80 causes adapter to start downloading
+	   the personality code into adapter instruction RAM.
+	   Once code is loaded, it will begin executing and, based on
+	   information provided above, will start DMAing data from
+	   shared memory to adapter DRAM.
+	 */
+	/* the wait loop below verifies this write operation has been done
+	   and processed
+	*/
+	writeb(START_DOWNLOAD, &icom_port->dram->sync);
+
+	/* Wait max 1 Sec for data download and processor to start */
+	for (index = 0; index < 10; index++) {
+		msleep(100);
+		if (readb(&icom_port->dram->misc_flags) & ICOM_HDW_ACTIVE)
+			break;
+	}
+
+	if (index == 10)
+		status = -1;
+
+	/*
+	 * check Cable ID
+	 */
+	cable_id = readb(&icom_port->dram->cable_id);
+
+	if (cable_id & ICOM_CABLE_ID_VALID) {
+		/* Get cable ID into the lower 4 bits (standard form) */
+		cable_id = (cable_id & ICOM_CABLE_ID_MASK) >> 4;
+		icom_port->cable_id = cable_id;
+	} else {
+		dev_err(&dev->dev,"Invalid or no cable attached\n");
+		icom_port->cable_id = NO_CABLE;
+	}
+
+      load_code_exit:
+
+	if (status != 0) {
+		/* Clear out any pending interrupts */
+		writew(0x3FFF, (void *) icom_port->int_reg);
+
+		/* Turn off port */
+		writeb(ICOM_DISABLE, &(icom_port->dram->disable));
+
+		/* Stop processor */
+		stop_processor(icom_port);
+
+		dev_err(&icom_port->adapter->pci_dev->dev,"Port not opertional\n");
+	}
+
+      if (new_page != NULL)
+	      pci_free_consistent(dev, 4096, new_page, temp_pci);
+}
+
+static int startup(struct icom_port *icom_port)
+{
+	unsigned long temp;
+	unsigned char cable_id, raw_cable_id;
+	unsigned long flags;
+	int port;
+
+	trace(icom_port, "STARTUP", 0);
+
+	if (icom_port->dram == 0x00000000) {
+		/* should NEVER be zero */
+		dev_err(&icom_port->adapter->pci_dev->dev,
+			"Unusable Port, port configuration missing\n");
+		return -ENODEV;
+	}
+
+	/*
+	 * check Cable ID
+	 */
+	raw_cable_id = readb(&icom_port->dram->cable_id);
+	trace(icom_port, "CABLE_ID", raw_cable_id);
+
+	/* Get cable ID into the lower 4 bits (standard form) */
+	cable_id = (raw_cable_id & ICOM_CABLE_ID_MASK) >> 4;
+
+	/* Check for valid Cable ID */
+	if (!(raw_cable_id & ICOM_CABLE_ID_VALID) ||
+	    (cable_id != icom_port->cable_id)) {
+
+		/* reload adapter code, pick up any potential changes in cable id */
+		load_code(icom_port);
+
+		/* still no sign of cable, error out */
+		raw_cable_id = readb(&icom_port->dram->cable_id);
+		cable_id = (raw_cable_id & ICOM_CABLE_ID_MASK) >> 4;
+		if (!(raw_cable_id & ICOM_CABLE_ID_VALID) ||
+		    (icom_port->cable_id == NO_CABLE))
+			return -EIO;
+	}
+
+	/*
+	 * Finally, clear and  enable interrupts
+	 */
+	spin_lock_irqsave(&icom_lock, flags);
+	port = icom_port->port;
+	if (port == 0 || port == 1)
+		int_mask_tbl[port].global_int_mask = &icom_port->global_reg->int_mask;
+	else
+		int_mask_tbl[port].global_int_mask = &icom_port->global_reg->int_mask_2;
+
+	if (port == 0 || port == 2)
+		writew(0x00FF,(void *) icom_port->int_reg);
+	else
+		writew(0x3F00,(void *) icom_port->int_reg);
+	if (port < 4) {
+		temp = readl(int_mask_tbl[port].global_int_mask);
+		writel(temp & ~int_mask_tbl[port].processor_id, int_mask_tbl[port].global_int_mask);
+
+		/* write flush */
+		readl(int_mask_tbl[port].global_int_mask);
+	} else {
+		dev_err(&icom_port->adapter->pci_dev->dev,
+                        "Invalid port assignment\n");
+	}
+
+	spin_unlock_irqrestore(&icom_lock, flags);
+	return 0;
+}
+
+static void shutdown(struct icom_port *icom_port)
+{
+	unsigned long temp;
+	unsigned char cmdReg;
+	unsigned long flags;
+	int port;
+
+	spin_lock_irqsave(&icom_lock, flags);
+	trace(icom_port, "SHUTDOWN", 0);
+
+	/*
+	 * disable all interrupts
+	 */
+	port = icom_port->port;
+	if (port == 0 || port == 1)
+		int_mask_tbl[port].global_int_mask = &icom_port->global_reg->int_mask;
+	else
+		int_mask_tbl[port].global_int_mask = &icom_port->global_reg->int_mask_2;
+
+	if (port < 4) {
+		temp = readl(int_mask_tbl[port].global_int_mask);
+		writel(temp | int_mask_tbl[port].processor_id, int_mask_tbl[port].global_int_mask);
+
+		/* write flush */
+		readl(int_mask_tbl[port].global_int_mask);
+	} else {
+		dev_err(&icom_port->adapter->pci_dev->dev,
+                        "Invalid port assignment\n");
+	}
+	spin_unlock_irqrestore(&icom_lock, flags);
+
+	/*
+	 * disable break condition
+	 */
+	cmdReg = readb(&icom_port->dram->CmdReg);
+	if ((cmdReg | CMD_SND_BREAK) == CMD_SND_BREAK) {
+		writeb(cmdReg & ~CMD_SND_BREAK, &icom_port->dram->CmdReg);
+	}
+}
+
+static int icom_write(struct uart_port *port)
+{
+	unsigned long data_count;
+	unsigned char cmdReg;
+	unsigned long offset;
+	int temp_tail = port->info->xmit.tail;
+
+	trace(ICOM_PORT, "WRITE", 0);
+
+	if (cpu_to_le16(ICOM_PORT->statStg->xmit[0].flags) &
+	    SA_FLAGS_READY_TO_XMIT) {
+		trace(ICOM_PORT, "WRITE_FULL", 0);
+		return 0;
+	}
+
+	data_count = 0;
+	while ((port->info->xmit.head != temp_tail) &&
+	       (data_count <= XMIT_BUFF_SZ)) {
+
+		ICOM_PORT->xmit_buf[data_count++] =
+		    port->info->xmit.buf[temp_tail];
+
+		temp_tail++;
+		temp_tail &= (UART_XMIT_SIZE - 1);
+	}
+
+	if (data_count) {
+		ICOM_PORT->statStg->xmit[0].flags =
+		    cpu_to_le16(SA_FLAGS_READY_TO_XMIT);
+		ICOM_PORT->statStg->xmit[0].leLength =
+		    cpu_to_le16(data_count);
+		offset =
+		    (unsigned long) &ICOM_PORT->statStg->xmit[0] -
+		    (unsigned long) ICOM_PORT->statStg;
+		*ICOM_PORT->xmitRestart =
+		    cpu_to_le32(ICOM_PORT->statStg_pci + offset);
+		cmdReg = readb(&ICOM_PORT->dram->CmdReg);
+		writeb(cmdReg | CMD_XMIT_RCV_ENABLE,
+		       &ICOM_PORT->dram->CmdReg);
+		writeb(START_XMIT, &ICOM_PORT->dram->StartXmitCmd);
+		trace(ICOM_PORT, "WRITE_START", data_count);
+		/* write flush */
+		readb(&ICOM_PORT->dram->StartXmitCmd);
+	}
+
+	return data_count;
+}
+
+static inline void check_modem_status(struct icom_port *icom_port)
+{
+	static char old_status = 0;
+	char delta_status;
+	unsigned char status;
+
+	spin_lock(&icom_port->uart_port.lock);
+
+	/*modem input register */
+	status = readb(&icom_port->dram->isr);
+	trace(icom_port, "CHECK_MODEM", status);
+	delta_status = status ^ old_status;
+	if (delta_status) {
+		if (delta_status & ICOM_RI)
+			icom_port->uart_port.icount.rng++;
+		if (delta_status & ICOM_DSR)
+			icom_port->uart_port.icount.dsr++;
+		if (delta_status & ICOM_DCD)
+			uart_handle_dcd_change(&icom_port->uart_port,
+					       delta_status & ICOM_DCD);
+		if (delta_status & ICOM_CTS)
+			uart_handle_cts_change(&icom_port->uart_port,
+					       delta_status & ICOM_CTS);
+
+		wake_up_interruptible(&icom_port->uart_port.info->
+				      delta_msr_wait);
+		old_status = status;
+	}
+	spin_unlock(&icom_port->uart_port.lock);
+}
+
+static void xmit_interrupt(u16 port_int_reg, struct icom_port *icom_port)
+{
+	unsigned short int count;
+	int i;
+
+	if (port_int_reg & (INT_XMIT_COMPLETED)) {
+		trace(icom_port, "XMIT_COMPLETE", 0);
+
+		/* clear buffer in use bit */
+		icom_port->statStg->xmit[0].flags &=
+			cpu_to_le16(~SA_FLAGS_READY_TO_XMIT);
+
+		count = (unsigned short int)
+			cpu_to_le16(icom_port->statStg->xmit[0].leLength);
+		icom_port->uart_port.icount.tx += count;
+
+		for (i=0; i<count &&
+			!uart_circ_empty(&icom_port->uart_port.info->xmit); i++) {
+
+			icom_port->uart_port.info->xmit.tail++;
+			icom_port->uart_port.info->xmit.tail &=
+				(UART_XMIT_SIZE - 1);
+		}
+
+		if (!icom_write(&icom_port->uart_port))
+			/* activate write queue */
+			uart_write_wakeup(&icom_port->uart_port);
+	} else
+		trace(icom_port, "XMIT_DISABLED", 0);
+}
+
+static void recv_interrupt(u16 port_int_reg, struct icom_port *icom_port)
+{
+	short int count, rcv_buff;
+	struct tty_struct *tty = icom_port->uart_port.info->tty;
+	unsigned short int status;
+	struct uart_icount *icount;
+	unsigned long offset;
+
+	trace(icom_port, "RCV_COMPLETE", 0);
+	rcv_buff = icom_port->next_rcv;
+
+	status = cpu_to_le16(icom_port->statStg->rcv[rcv_buff].flags);
+	while (status & SA_FL_RCV_DONE) {
+
+		trace(icom_port, "FID_STATUS", status);
+		count = cpu_to_le16(icom_port->statStg->rcv[rcv_buff].leLength);
+
+		trace(icom_port, "RCV_COUNT", count);
+		if (count > (TTY_FLIPBUF_SIZE - tty->flip.count))
+			count = TTY_FLIPBUF_SIZE - tty->flip.count;
+
+		trace(icom_port, "REAL_COUNT", count);
+
+		offset =
+			cpu_to_le32(icom_port->statStg->rcv[rcv_buff].leBuffer) -
+			icom_port->recv_buf_pci;
+
+		memcpy(tty->flip.char_buf_ptr,(unsigned char *)
+		       ((unsigned long)icom_port->recv_buf + offset), count);
+
+		if (count > 0) {
+			tty->flip.count += count - 1;
+			tty->flip.char_buf_ptr += count - 1;
+
+			memset(tty->flip.flag_buf_ptr, 0, count);
+			tty->flip.flag_buf_ptr += count - 1;
+		}
+
+		icount = &icom_port->uart_port.icount;
+		icount->rx += count;
+
+		/* Break detect logic */
+		if ((status & SA_FLAGS_FRAME_ERROR)
+		    && (tty->flip.char_buf_ptr[0] == 0x00)) {
+			status &= ~SA_FLAGS_FRAME_ERROR;
+			status |= SA_FLAGS_BREAK_DET;
+			trace(icom_port, "BREAK_DET", 0);
+		}
+
+		if (status &
+		    (SA_FLAGS_BREAK_DET | SA_FLAGS_PARITY_ERROR |
+		     SA_FLAGS_FRAME_ERROR | SA_FLAGS_OVERRUN)) {
+
+			if (status & SA_FLAGS_BREAK_DET)
+				icount->brk++;
+			if (status & SA_FLAGS_PARITY_ERROR)
+				icount->parity++;
+			if (status & SA_FLAGS_FRAME_ERROR)
+				icount->frame++;
+			if (status & SA_FLAGS_OVERRUN)
+				icount->overrun++;
+
+			/*
+			 * Now check to see if character should be
+			 * ignored, and mask off conditions which
+			 * should be ignored.
+			 */
+			if (status & icom_port->ignore_status_mask) {
+				trace(icom_port, "IGNORE_CHAR", 0);
+				goto ignore_char;
+			}
+
+			status &= icom_port->read_status_mask;
+
+			if (status & SA_FLAGS_BREAK_DET) {
+				*tty->flip.flag_buf_ptr = TTY_BREAK;
+			} else if (status & SA_FLAGS_PARITY_ERROR) {
+				trace(icom_port, "PARITY_ERROR", 0);
+				*tty->flip.flag_buf_ptr = TTY_PARITY;
+			} else if (status & SA_FLAGS_FRAME_ERROR)
+				*tty->flip.flag_buf_ptr = TTY_FRAME;
+
+			if (status & SA_FLAGS_OVERRUN) {
+				/*
+				 * Overrun is special, since it's
+				 * reported immediately, and doesn't
+				 * affect the current character
+				 */
+				if (tty->flip.count < TTY_FLIPBUF_SIZE) {
+					tty->flip.count++;
+					tty->flip.flag_buf_ptr++;
+					tty->flip.char_buf_ptr++;
+					*tty->flip.flag_buf_ptr = TTY_OVERRUN;
+				}
+			}
+		}
+
+		tty->flip.flag_buf_ptr++;
+		tty->flip.char_buf_ptr++;
+		tty->flip.count++;
+		ignore_char:
+			icom_port->statStg->rcv[rcv_buff].flags = 0;
+		icom_port->statStg->rcv[rcv_buff].leLength = 0;
+		icom_port->statStg->rcv[rcv_buff].WorkingLength =
+			(unsigned short int) cpu_to_le16(RCV_BUFF_SZ);
+
+		rcv_buff++;
+		if (rcv_buff == NUM_RBUFFS)
+			rcv_buff = 0;
+
+		status = cpu_to_le16(icom_port->statStg->rcv[rcv_buff].flags);
+	}
+	icom_port->next_rcv = rcv_buff;
+	tty_flip_buffer_push(tty);
+}
+
+static void process_interrupt(u16 port_int_reg,
+			      struct icom_port *icom_port)
+{
+
+	spin_lock(&icom_port->uart_port.lock);
+	trace(icom_port, "INTERRUPT", port_int_reg);
+
+	if (port_int_reg & (INT_XMIT_COMPLETED | INT_XMIT_DISABLED))
+		xmit_interrupt(port_int_reg, icom_port);
+
+	if (port_int_reg & INT_RCV_COMPLETED)
+		recv_interrupt(port_int_reg, icom_port);
+
+	spin_unlock(&icom_port->uart_port.lock);
+}
+
+static irqreturn_t icom_interrupt(int irq, void *dev_id,
+				  struct pt_regs *regs)
+{
+	unsigned long int_reg;
+	u32 adapter_interrupts;
+	u16 port_int_reg;
+	struct icom_adapter *icom_adapter;
+	struct icom_port *icom_port;
+
+	/* find icom_port for this interrupt */
+	icom_adapter = (struct icom_adapter *) dev_id;
+
+	if ((icom_adapter->version | ADAPTER_V2) == ADAPTER_V2) {
+		int_reg = icom_adapter->base_addr + 0x8024;
+
+		adapter_interrupts = readl((void *) int_reg);
+
+		if (adapter_interrupts & 0x00003FFF) {
+			/* port 2 interrupt,  NOTE:  for all ADAPTER_V2, port 2 will be active */
+			icom_port = &icom_adapter->port_info[2];
+			port_int_reg = (u16) adapter_interrupts;
+			process_interrupt(port_int_reg, icom_port);
+			check_modem_status(icom_port);
+		}
+		if (adapter_interrupts & 0x3FFF0000) {
+			/* port 3 interrupt */
+			icom_port = &icom_adapter->port_info[3];
+			if (icom_port->status == ICOM_PORT_ACTIVE) {
+				port_int_reg =
+				    (u16) (adapter_interrupts >> 16);
+				process_interrupt(port_int_reg, icom_port);
+				check_modem_status(icom_port);
+			}
+		}
+
+		/* Clear out any pending interrupts */
+		writel(adapter_interrupts, (void *) int_reg);
+
+		int_reg = icom_adapter->base_addr + 0x8004;
+	} else {
+		int_reg = icom_adapter->base_addr + 0x4004;
+	}
+
+	adapter_interrupts = readl((void *) int_reg);
+
+	if (adapter_interrupts & 0x00003FFF) {
+		/* port 0 interrupt, NOTE:  for all adapters, port 0 will be active */
+		icom_port = &icom_adapter->port_info[0];
+		port_int_reg = (u16) adapter_interrupts;
+		process_interrupt(port_int_reg, icom_port);
+		check_modem_status(icom_port);
+	}
+	if (adapter_interrupts & 0x3FFF0000) {
+		/* port 1 interrupt */
+		icom_port = &icom_adapter->port_info[1];
+		if (icom_port->status == ICOM_PORT_ACTIVE) {
+			port_int_reg = (u16) (adapter_interrupts >> 16);
+			process_interrupt(port_int_reg, icom_port);
+			check_modem_status(icom_port);
+		}
+	}
+
+	/* Clear out any pending interrupts */
+	writel(adapter_interrupts, (void *) int_reg);
+
+	/* flush the write */
+	adapter_interrupts = readl((void *) int_reg);
+
+	return IRQ_HANDLED;
+}
+
+/*
+ * ------------------------------------------------------------------
+ * Begin serial-core API
+ * ------------------------------------------------------------------
+ */
+static unsigned int icom_tx_empty(struct uart_port *port)
+{
+	int ret;
+	unsigned long flags;
+
+	spin_lock_irqsave(&port->lock, flags);
+	if (cpu_to_le16(ICOM_PORT->statStg->xmit[0].flags) &
+	    SA_FLAGS_READY_TO_XMIT)
+		ret = TIOCSER_TEMT;
+	else
+		ret = 0;
+
+	spin_unlock_irqrestore(&port->lock, flags);
+	return ret;
+}
+
+static void icom_set_mctrl(struct uart_port *port, unsigned int mctrl)
+{
+	unsigned char local_osr;
+
+	trace(ICOM_PORT, "SET_MODEM", 0);
+	local_osr = readb(&ICOM_PORT->dram->osr);
+
+	if (mctrl & TIOCM_RTS) {
+		trace(ICOM_PORT, "RAISE_RTS", 0);
+		local_osr |= ICOM_RTS;
+	} else {
+		trace(ICOM_PORT, "LOWER_RTS", 0);
+		local_osr &= ~ICOM_RTS;
+	}
+
+	if (mctrl & TIOCM_DTR) {
+		trace(ICOM_PORT, "RAISE_DTR", 0);
+		local_osr |= ICOM_DTR;
+	} else {
+		trace(ICOM_PORT, "LOWER_DTR", 0);
+		local_osr &= ~ICOM_DTR;
+	}
+
+	writeb(local_osr, &ICOM_PORT->dram->osr);
+}
+
+static unsigned int icom_get_mctrl(struct uart_port *port)
+{
+	unsigned char status;
+	unsigned int result;
+
+	trace(ICOM_PORT, "GET_MODEM", 0);
+
+	status = readb(&ICOM_PORT->dram->isr);
+
+	result = ((status & ICOM_DCD) ? TIOCM_CAR : 0)
+	    | ((status & ICOM_RI) ? TIOCM_RNG : 0)
+	    | ((status & ICOM_DSR) ? TIOCM_DSR : 0)
+	    | ((status & ICOM_CTS) ? TIOCM_CTS : 0);
+	return result;
+}
+
+static void icom_stop_tx(struct uart_port *port, unsigned int tty_stop)
+{
+	unsigned char cmdReg;
+
+	if (tty_stop) {
+		trace(ICOM_PORT, "STOP", 0);
+		cmdReg = readb(&ICOM_PORT->dram->CmdReg);
+		writeb(cmdReg | CMD_HOLD_XMIT, &ICOM_PORT->dram->CmdReg);
+	}
+}
+
+static void icom_start_tx(struct uart_port *port, unsigned int tty_start)
+{
+	unsigned char cmdReg;
+
+	trace(ICOM_PORT, "START", 0);
+	cmdReg = readb(&ICOM_PORT->dram->CmdReg);
+	if ((cmdReg & CMD_HOLD_XMIT) == CMD_HOLD_XMIT)
+		writeb(cmdReg & ~CMD_HOLD_XMIT,
+		       &ICOM_PORT->dram->CmdReg);
+
+	icom_write(port);
+}
+
+static void icom_send_xchar(struct uart_port *port, char ch)
+{
+	unsigned char xdata;
+	int index;
+	unsigned long flags;
+
+	trace(ICOM_PORT, "SEND_XCHAR", ch);
+
+	/* wait .1 sec to send char */
+	for (index = 0; index < 10; index++) {
+		spin_lock_irqsave(&port->lock, flags);
+		xdata = readb(&ICOM_PORT->dram->xchar);
+		if (xdata == 0x00) {
+			trace(ICOM_PORT, "QUICK_WRITE", 0);
+			writeb(ch, &ICOM_PORT->dram->xchar);
+
+			/* flush write operation */
+			xdata = readb(&ICOM_PORT->dram->xchar);
+			spin_unlock_irqrestore(&port->lock, flags);
+			break;
+		}
+		spin_unlock_irqrestore(&port->lock, flags);
+		msleep(10);
+	}
+}
+
+static void icom_stop_rx(struct uart_port *port)
+{
+	unsigned char cmdReg;
+
+	cmdReg = readb(&ICOM_PORT->dram->CmdReg);
+	writeb(cmdReg & ~CMD_RCV_ENABLE, &ICOM_PORT->dram->CmdReg);
+}
+
+static void icom_enable_ms(struct uart_port *port)
+{
+	/* no-op */
+}
+
+static void icom_break(struct uart_port *port, int break_state)
+{
+	unsigned char cmdReg;
+	unsigned long flags;
+
+	spin_lock_irqsave(&port->lock, flags);
+	trace(ICOM_PORT, "BREAK", 0);
+	cmdReg = readb(&ICOM_PORT->dram->CmdReg);
+	if (break_state == -1) {
+		writeb(cmdReg | CMD_SND_BREAK, &ICOM_PORT->dram->CmdReg);
+	} else {
+		writeb(cmdReg & ~CMD_SND_BREAK, &ICOM_PORT->dram->CmdReg);
+	}
+	spin_unlock_irqrestore(&port->lock, flags);
+}
+
+static int icom_open(struct uart_port *port)
+{
+	int retval;
+
+	kobject_get(&ICOM_PORT->adapter->kobj);
+	retval = startup(ICOM_PORT);
+
+	if (retval) {
+		kobject_put(&ICOM_PORT->adapter->kobj);
+		trace(ICOM_PORT, "STARTUP_ERROR", 0);
+		return retval;
+	}
+
+	return 0;
+}
+
+static void icom_close(struct uart_port *port)
+{
+	unsigned char cmdReg;
+
+	trace(ICOM_PORT, "CLOSE", 0);
+
+	/* stop receiver */
+	cmdReg = readb(&ICOM_PORT->dram->CmdReg);
+	writeb(cmdReg & (unsigned char) ~CMD_RCV_ENABLE,
+	       &ICOM_PORT->dram->CmdReg);
+
+	shutdown(ICOM_PORT);
+
+	kobject_put(&ICOM_PORT->adapter->kobj);
+}
+
+static void icom_set_termios(struct uart_port *port,
+			     struct termios *termios,
+			     struct termios *old_termios)
+{
+	int baud;
+	unsigned cflag, iflag;
+	int bits;
+	char new_config2;
+	char new_config3 = 0;
+	char tmp_byte;
+	int index;
+	int rcv_buff, xmit_buff;
+	unsigned long offset;
+	unsigned long flags;
+
+	spin_lock_irqsave(&port->lock, flags);
+	trace(ICOM_PORT, "CHANGE_SPEED", 0);
+
+	cflag = termios->c_cflag;
+	iflag = termios->c_iflag;
+
+	new_config2 = ICOM_ACFG_DRIVE1;
+
+	/* byte size and parity */
+	switch (cflag & CSIZE) {
+	case CS5:		/* 5 bits/char */
+		new_config2 |= ICOM_ACFG_5BPC;
+		bits = 7;
+		break;
+	case CS6:		/* 6 bits/char */
+		new_config2 |= ICOM_ACFG_6BPC;
+		bits = 8;
+		break;
+	case CS7:		/* 7 bits/char */
+		new_config2 |= ICOM_ACFG_7BPC;
+		bits = 9;
+		break;
+	case CS8:		/* 8 bits/char */
+		new_config2 |= ICOM_ACFG_8BPC;
+		bits = 10;
+		break;
+	default:
+		bits = 10;
+		break;
+	}
+	if (cflag & CSTOPB) {
+		/* 2 stop bits */
+		new_config2 |= ICOM_ACFG_2STOP_BIT;
+		bits++;
+	}
+	if (cflag & PARENB) {
+		/* parity bit enabled */
+		new_config2 |= ICOM_ACFG_PARITY_ENAB;
+		trace(ICOM_PORT, "PARENB", 0);
+		bits++;
+	}
+	if (cflag & PARODD) {
+		/* odd parity */
+		new_config2 |= ICOM_ACFG_PARITY_ODD;
+		trace(ICOM_PORT, "PARODD", 0);
+	}
+
+	/* Determine divisor based on baud rate */
+	baud = uart_get_baud_rate(port, termios, old_termios,
+				  icom_acfg_baud[0],
+				  icom_acfg_baud[BAUD_TABLE_LIMIT]);
+	if (!baud)
+		baud = 9600;	/* B0 transition handled in rs_set_termios */
+
+	for (index = 0; index < BAUD_TABLE_LIMIT; index++) {
+		if (icom_acfg_baud[index] == baud) {
+			new_config3 = index;
+			break;
+		}
+	}
+
+	uart_update_timeout(port, cflag, baud);
+
+	/* CTS flow control flag and modem status interrupts */
+	tmp_byte = readb(&(ICOM_PORT->dram->HDLCConfigReg));
+	if (cflag & CRTSCTS)
+		tmp_byte |= HDLC_HDW_FLOW;
+	else
+		tmp_byte &= ~HDLC_HDW_FLOW;
+	writeb(tmp_byte, &(ICOM_PORT->dram->HDLCConfigReg));
+
+	/*
+	 * Set up parity check flag
+	 */
+	ICOM_PORT->read_status_mask = SA_FLAGS_OVERRUN | SA_FL_RCV_DONE;
+	if (iflag & INPCK)
+		ICOM_PORT->read_status_mask |=
+		    SA_FLAGS_FRAME_ERROR | SA_FLAGS_PARITY_ERROR;
+
+	if ((iflag & BRKINT) || (iflag & PARMRK))
+		ICOM_PORT->read_status_mask |= SA_FLAGS_BREAK_DET;
+
+	/*
+	 * Characters to ignore
+	 */
+	ICOM_PORT->ignore_status_mask = 0;
+	if (iflag & IGNPAR)
+		ICOM_PORT->ignore_status_mask |=
+		    SA_FLAGS_PARITY_ERROR | SA_FLAGS_FRAME_ERROR;
+	if (iflag & IGNBRK) {
+		ICOM_PORT->ignore_status_mask |= SA_FLAGS_BREAK_DET;
+		/*
+		 * If we're ignore parity and break indicators, ignore
+		 * overruns too.  (For real raw support).
+		 */
+		if (iflag & IGNPAR)
+			ICOM_PORT->ignore_status_mask |= SA_FLAGS_OVERRUN;
+	}
+
+	/*
+	 * !!! ignore all characters if CREAD is not set
+	 */
+	if ((cflag & CREAD) == 0)
+		ICOM_PORT->ignore_status_mask |= SA_FL_RCV_DONE;
+
+	/* Turn off Receiver to prepare for reset */
+	writeb(CMD_RCV_DISABLE, &ICOM_PORT->dram->CmdReg);
+
+	for (index = 0; index < 10; index++) {
+		if (readb(&ICOM_PORT->dram->PrevCmdReg) == 0x00) {
+			break;
+		}
+	}
+
+	/* clear all current buffers of data */
+	for (rcv_buff = 0; rcv_buff < NUM_RBUFFS; rcv_buff++) {
+		ICOM_PORT->statStg->rcv[rcv_buff].flags = 0;
+		ICOM_PORT->statStg->rcv[rcv_buff].leLength = 0;
+		ICOM_PORT->statStg->rcv[rcv_buff].WorkingLength =
+		    (unsigned short int) cpu_to_le16(RCV_BUFF_SZ);
+	}
+
+	for (xmit_buff = 0; xmit_buff < NUM_XBUFFS; xmit_buff++) {
+		ICOM_PORT->statStg->xmit[xmit_buff].flags = 0;
+	}
+
+	/* activate changes and start xmit and receiver here */
+	/* Enable the receiver */
+	writeb(new_config3, &(ICOM_PORT->dram->async_config3));
+	writeb(new_config2, &(ICOM_PORT->dram->async_config2));
+	tmp_byte = readb(&(ICOM_PORT->dram->HDLCConfigReg));
+	tmp_byte |= HDLC_PPP_PURE_ASYNC | HDLC_FF_FILL;
+	writeb(tmp_byte, &(ICOM_PORT->dram->HDLCConfigReg));
+	writeb(0x04, &(ICOM_PORT->dram->FlagFillIdleTimer));	/* 0.5 seconds */
+	writeb(0xFF, &(ICOM_PORT->dram->ier));	/* enable modem signal interrupts */
+
+	/* reset processor */
+	writeb(CMD_RESTART, &ICOM_PORT->dram->CmdReg);
+
+	for (index = 0; index < 10; index++) {
+		if (readb(&ICOM_PORT->dram->CmdReg) == 0x00) {
+			break;
+		}
+	}
+
+	/* Enable Transmitter and Reciever */
+	offset =
+	    (unsigned long) &ICOM_PORT->statStg->rcv[0] -
+	    (unsigned long) ICOM_PORT->statStg;
+	writel(ICOM_PORT->statStg_pci + offset,
+	       &ICOM_PORT->dram->RcvStatusAddr);
+	ICOM_PORT->next_rcv = 0;
+	ICOM_PORT->put_length = 0;
+	*ICOM_PORT->xmitRestart = 0;
+	writel(ICOM_PORT->xmitRestart_pci,
+	       &ICOM_PORT->dram->XmitStatusAddr);
+	trace(ICOM_PORT, "XR_ENAB", 0);
+	writeb(CMD_XMIT_RCV_ENABLE, &ICOM_PORT->dram->CmdReg);
+
+	spin_unlock_irqrestore(&port->lock, flags);
+}
+
+static const char *icom_type(struct uart_port *port)
+{
+	return "icom";
+}
+
+static void icom_release_port(struct uart_port *port)
+{
+}
+
+static int icom_request_port(struct uart_port *port)
+{
+	return 0;
+}
+
+static void icom_config_port(struct uart_port *port, int flags)
+{
+	port->type = PORT_ICOM;
+}
+
+static struct uart_ops icom_ops = {
+	.tx_empty = icom_tx_empty,
+	.set_mctrl = icom_set_mctrl,
+	.get_mctrl = icom_get_mctrl,
+	.stop_tx = icom_stop_tx,
+	.start_tx = icom_start_tx,
+	.send_xchar = icom_send_xchar,
+	.stop_rx = icom_stop_rx,
+	.enable_ms = icom_enable_ms,
+	.break_ctl = icom_break,
+	.startup = icom_open,
+	.shutdown = icom_close,
+	.set_termios = icom_set_termios,
+	.type = icom_type,
+	.release_port = icom_release_port,
+	.request_port = icom_request_port,
+	.config_port = icom_config_port,
+};
+
+#define ICOM_CONSOLE NULL
+
+static struct uart_driver icom_uart_driver = {
+	.owner = THIS_MODULE,
+	.driver_name = ICOM_DRIVER_NAME,
+	.dev_name = "ttyA",
+	.major = ICOM_MAJOR,
+	.minor = ICOM_MINOR_START,
+	.nr = NR_PORTS,
+	.cons = ICOM_CONSOLE,
+};
+
+static int __devinit icom_init_ports(struct icom_adapter *icom_adapter)
+{
+	u32 subsystem_id = icom_adapter->subsystem_id;
+	int retval = 0;
+	int i;
+	struct icom_port *icom_port;
+
+	if (icom_adapter->version == ADAPTER_V1) {
+		icom_adapter->numb_ports = 2;
+
+		for (i = 0; i < 2; i++) {
+			icom_port = &icom_adapter->port_info[i];
+			icom_port->port = i;
+			icom_port->status = ICOM_PORT_ACTIVE;
+			icom_port->imbed_modem = ICOM_UNKNOWN;
+		}
+	} else {
+		if (subsystem_id == PCI_DEVICE_ID_IBM_ICOM_FOUR_PORT_MODEL) {
+			icom_adapter->numb_ports = 4;
+
+			for (i = 0; i < 4; i++) {
+				icom_port = &icom_adapter->port_info[i];
+
+				icom_port->port = i;
+				icom_port->status = ICOM_PORT_ACTIVE;
+				icom_port->imbed_modem = ICOM_IMBED_MODEM;
+			}
+		} else {
+			icom_adapter->numb_ports = 4;
+
+			icom_adapter->port_info[0].port = 0;
+			icom_adapter->port_info[0].status = ICOM_PORT_ACTIVE;
+
+			if (subsystem_id ==
+			    PCI_DEVICE_ID_IBM_ICOM_V2_ONE_PORT_RVX_ONE_PORT_MDM) {
+				icom_adapter->port_info[0].imbed_modem = ICOM_IMBED_MODEM;
+			} else {
+				icom_adapter->port_info[0].imbed_modem = ICOM_RVX;
+			}
+
+			icom_adapter->port_info[1].status = ICOM_PORT_OFF;
+
+			icom_adapter->port_info[2].port = 2;
+			icom_adapter->port_info[2].status = ICOM_PORT_ACTIVE;
+			icom_adapter->port_info[2].imbed_modem = ICOM_RVX;
+			icom_adapter->port_info[3].status = ICOM_PORT_OFF;
+		}
+	}
+
+	return retval;
+}
+
+static void icom_port_active(struct icom_port *icom_port, struct icom_adapter *icom_adapter, int port_num)
+{
+	if (icom_adapter->version == ADAPTER_V1) {
+		icom_port->global_reg = (struct icom_regs *) ((char *)
+			icom_adapter->base_addr + 0x4000);
+		icom_port->int_reg = (unsigned long) icom_adapter->base_addr +
+		    0x4004 + 2 - 2 * port_num;
+	} else {
+		icom_port->global_reg = (struct icom_regs *) ((char *)
+			icom_adapter->base_addr + 0x8000);
+		if (icom_port->port < 2)
+			icom_port->int_reg = (unsigned long) icom_adapter->base_addr +
+			    0x8004 + 2 - 2 * icom_port->port;
+		else
+			icom_port->int_reg = (unsigned long) icom_adapter->base_addr +
+			    0x8024 + 2 - 2 * (icom_port->port - 2);
+	}
+}
+static int __init icom_load_ports(struct icom_adapter *icom_adapter)
+{
+	struct icom_port *icom_port;
+	int port_num;
+	int retval;
+
+	for (port_num = 0; port_num < icom_adapter->numb_ports; port_num++) {
+
+		icom_port = &icom_adapter->port_info[port_num];
+
+		if (icom_port->status == ICOM_PORT_ACTIVE) {
+			icom_port_active(icom_port, icom_adapter, port_num);
+			icom_port->dram = (struct func_dram *) ((char *)
+					icom_adapter->base_addr +
+					0x2000 * icom_port->port);
+
+			icom_port->adapter = icom_adapter;
+
+			/* get port memory */
+			if ((retval = get_port_memory(icom_port)) != 0) {
+				dev_err(&icom_port->adapter->pci_dev->dev,
+					"Memory allocation for port FAILED\n");
+			}
+		}
+	}
+	return 0;
+}
+
+static int __devinit icom_alloc_adapter(struct icom_adapter
+					**icom_adapter_ref)
+{
+	int adapter_count = 0;
+	struct icom_adapter *icom_adapter;
+	struct icom_adapter *cur_adapter_entry;
+	struct list_head *tmp;
+
+	icom_adapter = (struct icom_adapter *)
+	    kmalloc(sizeof(struct icom_adapter), GFP_KERNEL);
+
+	if (!icom_adapter) {
+		return -ENOMEM;
+	}
+
+	memset(icom_adapter, 0, sizeof(struct icom_adapter));
+
+	list_for_each(tmp, &icom_adapter_head) {
+		cur_adapter_entry =
+		    list_entry(tmp, struct icom_adapter,
+			       icom_adapter_entry);
+		if (cur_adapter_entry->index != adapter_count) {
+			break;
+		}
+		adapter_count++;
+	}
+
+	icom_adapter->index = adapter_count;
+	list_add_tail(&icom_adapter->icom_adapter_entry, tmp);
+
+	*icom_adapter_ref = icom_adapter;
+	return 0;
+}
+
+static void icom_free_adapter(struct icom_adapter *icom_adapter)
+{
+	list_del(&icom_adapter->icom_adapter_entry);
+	kfree(icom_adapter);
+}
+
+static void icom_remove_adapter(struct icom_adapter *icom_adapter)
+{
+	struct icom_port *icom_port;
+	int index;
+
+	for (index = 0; index < icom_adapter->numb_ports; index++) {
+		icom_port = &icom_adapter->port_info[index];
+
+		if (icom_port->status == ICOM_PORT_ACTIVE) {
+			dev_info(&icom_adapter->pci_dev->dev,
+				 "Device removed\n");
+
+			uart_remove_one_port(&icom_uart_driver,
+					     &icom_port->uart_port);
+
+			/* be sure that DTR and RTS are dropped */
+			writeb(0x00, &icom_port->dram->osr);
+
+			/* Wait 0.1 Sec for simple Init to complete */
+			msleep(100);
+
+			/* Stop proccessor */
+			stop_processor(icom_port);
+
+			free_port_memory(icom_port);
+		}
+	}
+
+	free_irq(icom_adapter->irq_number, (void *) icom_adapter);
+	iounmap((void *) icom_adapter->base_addr);
+	icom_free_adapter(icom_adapter);
+	pci_release_regions(icom_adapter->pci_dev);
+}
+
+static void icom_kobj_release(struct kobject *kobj)
+{
+	struct icom_adapter *icom_adapter;
+
+	icom_adapter = to_icom_adapter(kobj);
+	icom_remove_adapter(icom_adapter);
+}
+
+static struct kobj_type icom_kobj_type = {
+	.release = icom_kobj_release,
+};
+
+static int __devinit icom_probe(struct pci_dev *dev,
+				const struct pci_device_id *ent)
+{
+	int index;
+        unsigned int command_reg;
+        int retval;
+        struct icom_adapter *icom_adapter;
+        struct icom_port *icom_port;
+
+        retval = pci_enable_device(dev);
+        if (retval) {
+		dev_err(&dev->dev, "Device enable FAILED\n");
+                return retval;
+	}
+
+	if ( (retval = pci_request_regions(dev, "icom"))) {
+		 dev_err(&dev->dev, "pci_request_region FAILED\n");
+		 pci_disable_device(dev);
+		 return retval;
+	 }
+
+        pci_set_master(dev);
+
+        if ( (retval = pci_read_config_dword(dev, PCI_COMMAND, &command_reg))) {
+		dev_err(&dev->dev, "PCI Config read FAILED\n");
+                return retval;
+        }
+
+	pci_write_config_dword(dev, PCI_COMMAND,
+		command_reg | PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER
+ 		| PCI_COMMAND_PARITY | PCI_COMMAND_SERR);
+
+        if (ent->driver_data == ADAPTER_V1) {
+		pci_write_config_dword(dev, 0x44, 0x8300830A);
+	 } else {
+		pci_write_config_dword(dev, 0x44, 0x42004200);
+		pci_write_config_dword(dev, 0x48, 0x42004200);
+         }
+
+
+	retval = icom_alloc_adapter(&icom_adapter);
+	if (retval) {
+		 dev_err(&dev->dev, "icom_alloc_adapter FAILED\n");
+		 retval = -EIO;
+		 goto probe_exit0;
+	}
+
+	 icom_adapter->base_addr_pci = pci_resource_start(dev, 0);
+	 icom_adapter->irq_number = dev->irq;
+	 icom_adapter->pci_dev = dev;
+	 icom_adapter->version = ent->driver_data;
+	 icom_adapter->subsystem_id = ent->subdevice;
+
+
+	retval = icom_init_ports(icom_adapter);
+	if (retval) {
+		dev_err(&dev->dev, "Port configuration failed\n");
+		goto probe_exit1;
+	}
+
+	 icom_adapter->base_addr =
+	     (unsigned long) ioremap(icom_adapter->base_addr_pci,
+						pci_resource_len(dev, 0));
+
+	if (!icom_adapter->base_addr)
+		goto probe_exit1;
+
+	 /* save off irq and request irq line */
+	 if ( (retval = request_irq(dev->irq, icom_interrupt,
+				   SA_INTERRUPT | SA_SHIRQ, ICOM_DRIVER_NAME,
+				   (void *) icom_adapter))) {
+		  goto probe_exit2;
+	 }
+
+	retval = icom_load_ports(icom_adapter);
+
+        for (index = 0; index < icom_adapter->numb_ports; index++) {
+		icom_port = &icom_adapter->port_info[index];
+
+		if (icom_port->status == ICOM_PORT_ACTIVE) {
+			icom_port->uart_port.irq = icom_port->adapter->irq_number;
+			icom_port->uart_port.type = PORT_ICOM;
+			icom_port->uart_port.iotype = UPIO_MEM;
+			icom_port->uart_port.membase =
+					       (char *) icom_adapter->base_addr_pci;
+			icom_port->uart_port.fifosize = 16;
+			icom_port->uart_port.ops = &icom_ops;
+			icom_port->uart_port.line =
+		        icom_port->port + icom_adapter->index * 4;
+			if (uart_add_one_port (&icom_uart_driver, &icom_port->uart_port)) {
+				icom_port->status = ICOM_PORT_OFF;
+				dev_err(&dev->dev, "Device add failed\n");
+			 } else
+			        dev_info(&dev->dev, "Device added\n");
+		}
+	}
+
+	kobject_init(&icom_adapter->kobj);
+	icom_adapter->kobj.ktype = &icom_kobj_type;
+	return 0;
+
+probe_exit2:
+	iounmap((void *) icom_adapter->base_addr);
+probe_exit1:
+	icom_free_adapter(icom_adapter);
+
+probe_exit0:
+	pci_release_regions(dev);
+	pci_disable_device(dev);
+
+        return retval;
+
+
+}
+
+static void __devexit icom_remove(struct pci_dev *dev)
+{
+	struct icom_adapter *icom_adapter;
+	struct list_head *tmp;
+
+	list_for_each(tmp, &icom_adapter_head) {
+		icom_adapter = list_entry(tmp, struct icom_adapter,
+					  icom_adapter_entry);
+		if (icom_adapter->pci_dev == dev) {
+			kobject_put(&icom_adapter->kobj);
+			return;
+		}
+	}
+
+	dev_err(&dev->dev, "Unable to find device to remove\n");
+}
+
+static struct pci_driver icom_pci_driver = {
+	.name = ICOM_DRIVER_NAME,
+	.id_table = icom_pci_table,
+	.probe = icom_probe,
+	.remove = __devexit_p(icom_remove),
+};
+
+static int __init icom_init(void)
+{
+	int ret;
+
+	spin_lock_init(&icom_lock);
+	icom_lock = (spinlock_t) SPIN_LOCK_UNLOCKED;
+
+	ret = uart_register_driver(&icom_uart_driver);
+	if (ret)
+		return ret;
+
+	ret = pci_register_driver(&icom_pci_driver);
+
+	if (ret < 0)
+		uart_unregister_driver(&icom_uart_driver);
+
+	return ret;
+}
+
+static void __exit icom_exit(void)
+{
+	pci_unregister_driver(&icom_pci_driver);
+	uart_unregister_driver(&icom_uart_driver);
+}
+
+module_init(icom_init);
+module_exit(icom_exit);
+
+#ifdef ICOM_TRACE
+static inline void trace(struct icom_port *icom_port, char *trace_pt,
+		  unsigned long trace_data)
+{
+	dev_info(&icom_port->adapter->pci_dev->dev, ":%d:%s - %lx\n",
+		 icom_port->port, trace_pt, trace_data);
+}
+#endif
+
+MODULE_AUTHOR("Michael Anderson <mjanders@us.ibm.com>");
+MODULE_DESCRIPTION("IBM iSeries Serial IOA driver");
+MODULE_SUPPORTED_DEVICE
+    ("IBM iSeries 2745, 2771, 2772, 2742, 2793 and 2805 Communications adapters");
+MODULE_LICENSE("GPL");
+
diff -Nru a/drivers/serial/icom.h b/drivers/serial/icom.h
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/drivers/serial/icom.h	2004-10-18 14:57:21 -07:00
@@ -0,0 +1,290 @@
+/*
+ * icom.h
+ *
+ * Copyright (C) 2001 Michael Anderson, IBM Corporation
+ *
+ * Serial device driver include file.
+ *
+ * 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
+ */
+
+#include<linux/serial_core.h>
+
+#define BAUD_TABLE_LIMIT	((sizeof(icom_acfg_baud)/sizeof(int)) - 1)
+static int icom_acfg_baud[] = {
+	300,
+	600,
+	900,
+	1200,
+	1800,
+	2400,
+	3600,
+	4800,
+	7200,
+	9600,
+	14400,
+	19200,
+	28800,
+	38400,
+	57600,
+	76800,
+	115200,
+	153600,
+	230400,
+	307200,
+	460800,
+};
+
+struct icom_regs {
+	u32 control;		/* Adapter Control Register     */
+	u32 interrupt;		/* Adapter Interrupt Register   */
+	u32 int_mask;		/* Adapter Interrupt Mask Reg   */
+	u32 int_pri;		/* Adapter Interrupt Priority r */
+	u32 int_reg_b;		/* Adapter non-masked Interrupt */
+	u32 resvd01;
+	u32 resvd02;
+	u32 resvd03;
+	u32 control_2;		/* Adapter Control Register 2   */
+	u32 interrupt_2;	/* Adapter Interrupt Register 2 */
+	u32 int_mask_2;		/* Adapter Interrupt Mask 2     */
+	u32 int_pri_2;		/* Adapter Interrupt Prior 2    */
+	u32 int_reg_2b;		/* Adapter non-masked 2         */
+};
+
+struct func_dram {
+	u32 reserved[108];	/* 0-1B0   reserved by personality code */
+	u32 RcvStatusAddr;	/* 1B0-1B3 Status Address for Next rcv */
+	u8 RcvStnAddr;		/* 1B4     Receive Station Addr */
+	u8 IdleState;		/* 1B5     Idle State */
+	u8 IdleMonitor;		/* 1B6     Idle Monitor */
+	u8 FlagFillIdleTimer;	/* 1B7     Flag Fill Idle Timer */
+	u32 XmitStatusAddr;	/* 1B8-1BB Transmit Status Address */
+	u8 StartXmitCmd;	/* 1BC     Start Xmit Command */
+	u8 HDLCConfigReg;	/* 1BD     Reserved */
+	u8 CauseCode;		/* 1BE     Cause code for fatal error */
+	u8 xchar;		/* 1BF     High priority send */
+	u32 reserved3;		/* 1C0-1C3 Reserved */
+	u8 PrevCmdReg;		/* 1C4     Reserved */
+	u8 CmdReg;		/* 1C5     Command Register */
+	u8 async_config2;	/* 1C6     Async Config Byte 2 */
+	u8 async_config3;	/* 1C7     Async Config Byte 3 */
+	u8 dce_resvd[20];	/* 1C8-1DB DCE Rsvd           */
+	u8 dce_resvd21;		/* 1DC     DCE Rsvd (21st byte */
+	u8 misc_flags;		/* 1DD     misc flags         */
+#define V2_HARDWARE     0x40
+#define ICOM_HDW_ACTIVE 0x01
+	u8 call_length;		/* 1DE     Phone #/CFI buff ln */
+	u8 call_length2;	/* 1DF     Upper byte (unused) */
+	u32 call_addr;		/* 1E0-1E3 Phn #/CFI buff addr */
+	u16 timer_value;	/* 1E4-1E5 general timer value */
+	u8 timer_command;	/* 1E6     general timer cmd  */
+	u8 dce_command;		/* 1E7     dce command reg    */
+	u8 dce_cmd_status;	/* 1E8     dce command stat   */
+	u8 x21_r1_ioff;		/* 1E9     dce ready counter  */
+	u8 x21_r0_ioff;		/* 1EA     dce not ready ctr  */
+	u8 x21_ralt_ioff;	/* 1EB     dce CNR counter    */
+	u8 x21_r1_ion;		/* 1EC     dce ready I on ctr */
+	u8 rsvd_ier;		/* 1ED     Rsvd for IER (if ne */
+	u8 ier;			/* 1EE     Interrupt Enable   */
+	u8 isr;			/* 1EF     Input Signal Reg   */
+	u8 osr;			/* 1F0     Output Signal Reg  */
+	u8 reset;		/* 1F1     Reset/Reload Reg   */
+	u8 disable;		/* 1F2     Disable Reg        */
+	u8 sync;		/* 1F3     Sync Reg           */
+	u8 error_stat;		/* 1F4     Error Status       */
+	u8 cable_id;		/* 1F5     Cable ID           */
+	u8 cs_length;		/* 1F6     CS Load Length     */
+	u8 mac_length;		/* 1F7     Mac Load Length    */
+	u32 cs_load_addr;	/* 1F8-1FB Call Load PCI Addr */
+	u32 mac_load_addr;	/* 1FC-1FF Mac Load PCI Addr  */
+};
+
+/*
+ * adapter defines and structures
+ */
+#define ICOM_CONTROL_START_A         0x00000008
+#define ICOM_CONTROL_STOP_A          0x00000004
+#define ICOM_CONTROL_START_B         0x00000002
+#define ICOM_CONTROL_STOP_B          0x00000001
+#define ICOM_CONTROL_START_C         0x00000008
+#define ICOM_CONTROL_STOP_C          0x00000004
+#define ICOM_CONTROL_START_D         0x00000002
+#define ICOM_CONTROL_STOP_D          0x00000001
+#define ICOM_IRAM_OFFSET             0x1000
+#define ICOM_IRAM_SIZE               0x0C00
+#define ICOM_DCE_IRAM_OFFSET         0x0A00
+#define ICOM_CABLE_ID_VALID          0x01
+#define ICOM_CABLE_ID_MASK           0xF0
+#define ICOM_DISABLE                 0x80
+#define CMD_XMIT_RCV_ENABLE          0xC0
+#define CMD_XMIT_ENABLE              0x40
+#define CMD_RCV_DISABLE              0x00
+#define CMD_RCV_ENABLE               0x80
+#define CMD_RESTART                  0x01
+#define CMD_HOLD_XMIT                0x02
+#define CMD_SND_BREAK                0x04
+#define RS232_CABLE                  0x06
+#define V24_CABLE                    0x0E
+#define V35_CABLE                    0x0C
+#define V36_CABLE                    0x02
+#define NO_CABLE                     0x00
+#define START_DOWNLOAD               0x80
+#define ICOM_INT_MASK_PRC_A          0x00003FFF
+#define ICOM_INT_MASK_PRC_B          0x3FFF0000
+#define ICOM_INT_MASK_PRC_C          0x00003FFF
+#define ICOM_INT_MASK_PRC_D          0x3FFF0000
+#define INT_RCV_COMPLETED            0x1000
+#define INT_XMIT_COMPLETED           0x2000
+#define INT_IDLE_DETECT              0x0800
+#define INT_RCV_DISABLED             0x0400
+#define INT_XMIT_DISABLED            0x0200
+#define INT_RCV_XMIT_SHUTDOWN        0x0100
+#define INT_FATAL_ERROR              0x0080
+#define INT_CABLE_PULL               0x0020
+#define INT_SIGNAL_CHANGE            0x0010
+#define HDLC_PPP_PURE_ASYNC          0x02
+#define HDLC_FF_FILL                 0x00
+#define HDLC_HDW_FLOW                0x01
+#define START_XMIT                   0x80
+#define ICOM_ACFG_DRIVE1             0x20
+#define ICOM_ACFG_NO_PARITY          0x00
+#define ICOM_ACFG_PARITY_ENAB        0x02
+#define ICOM_ACFG_PARITY_ODD         0x01
+#define ICOM_ACFG_8BPC               0x00
+#define ICOM_ACFG_7BPC               0x04
+#define ICOM_ACFG_6BPC               0x08
+#define ICOM_ACFG_5BPC               0x0C
+#define ICOM_ACFG_1STOP_BIT          0x00
+#define ICOM_ACFG_2STOP_BIT          0x10
+#define ICOM_DTR                     0x80
+#define ICOM_RTS                     0x40
+#define ICOM_RI                      0x08
+#define ICOM_DSR                     0x80
+#define ICOM_DCD                     0x20
+#define ICOM_CTS                     0x40
+
+#define NUM_XBUFFS 1
+#define NUM_RBUFFS 2
+#define RCV_BUFF_SZ 0x0200
+#define XMIT_BUFF_SZ 0x1000
+struct statusArea {
+    /**********************************************/
+	/* Transmit Status Area                       */
+    /**********************************************/
+	struct xmit_status_area{
+		u32 leNext;	/* Next entry in Little Endian on Adapter */
+		u32 leNextASD;
+		u32 leBuffer;	/* Buffer for entry in LE for Adapter */
+		u16 leLengthASD;
+		u16 leOffsetASD;
+		u16 leLength;	/* Length of data in segment */
+		u16 flags;
+#define SA_FLAGS_DONE           0x0080	/* Done with Segment */
+#define SA_FLAGS_CONTINUED      0x8000	/* More Segments */
+#define SA_FLAGS_IDLE           0x4000	/* Mark IDLE after frm */
+#define SA_FLAGS_READY_TO_XMIT  0x0800
+#define SA_FLAGS_STAT_MASK      0x007F
+	} xmit[NUM_XBUFFS];
+
+    /**********************************************/
+	/* Receive Status Area                        */
+    /**********************************************/
+	struct {
+		u32 leNext;	/* Next entry in Little Endian on Adapter */
+		u32 leNextASD;
+		u32 leBuffer;	/* Buffer for entry in LE for Adapter */
+		u16 WorkingLength;	/* size of segment */
+		u16 reserv01;
+		u16 leLength;	/* Length of data in segment */
+		u16 flags;
+#define SA_FL_RCV_DONE           0x0010	/* Data ready */
+#define SA_FLAGS_OVERRUN         0x0040
+#define SA_FLAGS_PARITY_ERROR    0x0080
+#define SA_FLAGS_FRAME_ERROR     0x0001
+#define SA_FLAGS_FRAME_TRUNC     0x0002
+#define SA_FLAGS_BREAK_DET       0x0004	/* set conditionally by device driver, not hardware */
+#define SA_FLAGS_RCV_MASK        0xFFE6
+	} rcv[NUM_RBUFFS];
+};
+
+struct icom_adapter;
+
+
+#define ICOM_MAJOR       243
+#define ICOM_MINOR_START 0
+
+struct icom_port {
+	struct uart_port uart_port;
+	u8 imbed_modem;
+#define ICOM_UNKNOWN		1
+#define ICOM_RVX		2
+#define ICOM_IMBED_MODEM	3
+	unsigned char cable_id;
+	unsigned char read_status_mask;
+	unsigned char ignore_status_mask;
+	unsigned long int_reg;
+	struct icom_regs *global_reg;
+	struct func_dram *dram;
+	int port;
+	struct statusArea *statStg;
+	dma_addr_t statStg_pci;
+	u32 *xmitRestart;
+	dma_addr_t xmitRestart_pci;
+	unsigned char *xmit_buf;
+	dma_addr_t xmit_buf_pci;
+	unsigned char *recv_buf;
+	dma_addr_t recv_buf_pci;
+	int next_rcv;
+	int put_length;
+	int status;
+#define ICOM_PORT_ACTIVE	1	/* Port exists. */
+#define ICOM_PORT_OFF		0	/* Port does not exist. */
+	int load_in_progress;
+	struct icom_adapter *adapter;
+};
+
+struct icom_adapter {
+	unsigned long base_addr;
+	unsigned long base_addr_pci;
+	unsigned char irq_number;
+	struct pci_dev *pci_dev;
+	struct icom_port port_info[4];
+	int index;
+	int version;
+#define ADAPTER_V1	0x0001
+#define ADAPTER_V2	0x0002
+	u32 subsystem_id;
+#define FOUR_PORT_MODEL				0x0252
+#define V2_TWO_PORTS_RVX			0x021A
+#define V2_ONE_PORT_RVX_ONE_PORT_IMBED_MDM	0x0251
+	int numb_ports;
+	struct list_head icom_adapter_entry;
+	struct kobject kobj;
+};
+
+/* prototype */
+extern void iCom_sercons_init(void);
+
+struct lookup_proc_table {
+	u32	*global_control_reg;
+	unsigned long	processor_id;
+};
+
+struct lookup_int_table {
+	u32	*global_int_mask;
+	unsigned long	processor_id;
+};
+
+#define MSECS_TO_JIFFIES(ms) (((ms)*HZ+999)/1000)
diff -Nru a/drivers/serial/mcfserial.c b/drivers/serial/mcfserial.c
--- a/drivers/serial/mcfserial.c	2004-10-18 14:56:29 -07:00
+++ b/drivers/serial/mcfserial.c	2004-10-18 14:56:29 -07:00
@@ -424,11 +424,7 @@
 	tty = info->tty;
 	if (!tty)
 		return;
-
-	if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
-	    tty->ldisc.write_wakeup)
-		(tty->ldisc.write_wakeup)(tty);
-	wake_up_interruptible(&tty->write_wait);
+	tty_wakeup(tty);
 }
 
 
@@ -835,10 +831,7 @@
 	info->xmit_cnt = info->xmit_head = info->xmit_tail = 0;
 	local_irq_restore(flags);
 
-	wake_up_interruptible(&tty->write_wait);
-	if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
-	    tty->ldisc.write_wakeup)
-		(tty->ldisc.write_wakeup)(tty);
+	tty_wakeup(tty);
 }
 
 /*
@@ -1232,11 +1225,12 @@
 	shutdown(info);
 	if (tty->driver->flush_buffer)
 		tty->driver->flush_buffer(tty);
-	if (tty->ldisc.flush_buffer)
-		tty->ldisc.flush_buffer(tty);
+	tty_ldisc_flush(tty);
+	
 	tty->closing = 0;
 	info->event = 0;
 	info->tty = 0;
+#if 0	
 	if (tty->ldisc.num != ldiscs[N_TTY].num) {
 		if (tty->ldisc.close)
 			(tty->ldisc.close)(tty);
@@ -1245,6 +1239,7 @@
 		if (tty->ldisc.open)
 			(tty->ldisc.open)(tty);
 	}
+#endif	
 	if (info->blocked_open) {
 		if (info->close_delay) {
 			current->state = TASK_INTERRUPTIBLE;
diff -Nru a/drivers/serial/pxa.c b/drivers/serial/pxa.c
--- a/drivers/serial/pxa.c	2004-10-18 14:57:03 -07:00
+++ b/drivers/serial/pxa.c	2004-10-18 14:57:03 -07:00
@@ -40,6 +40,7 @@
 #include <asm/io.h>
 #include <asm/hardware.h>
 #include <asm/irq.h>
+#include <asm/arch/pxa-regs.h>
 
 #if defined(CONFIG_SERIAL_PXA_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ)
 #define SUPPORT_SYSRQ
diff -Nru a/drivers/serial/s3c2410.c b/drivers/serial/s3c2410.c
--- a/drivers/serial/s3c2410.c	2004-10-18 14:56:31 -07:00
+++ b/drivers/serial/s3c2410.c	2004-10-18 14:56:31 -07:00
@@ -26,8 +26,6 @@
 #include <asm/hardware.h>
 #include <asm/arch/regs-serial.h>
 
-#include <asm/mach-types.h>
-
 #if 0
 #include <asm/debug-ll.h>
 #define dbg(x...) llprintk(x)
@@ -677,7 +675,7 @@
 
 		default:
 		case S3C2410_LCON_PNONE:
-			/* nothing */
+			*parity = 'n';
 		}
 
 		/* now calculate the baud rate */
diff -Nru a/drivers/serial/serial_core.c b/drivers/serial/serial_core.c
--- a/drivers/serial/serial_core.c	2004-10-18 14:56:20 -07:00
+++ b/drivers/serial/serial_core.c	2004-10-18 14:56:20 -07:00
@@ -107,15 +107,7 @@
 static void uart_tasklet_action(unsigned long data)
 {
 	struct uart_state *state = (struct uart_state *)data;
-	struct tty_struct *tty;
-
-	tty = state->info->tty;
-	if (tty) {
-		if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
-		    tty->ldisc.write_wakeup)
-			tty->ldisc.write_wakeup(tty);
-		wake_up_interruptible(&tty->write_wait);
-	}
+	tty_wakeup(state->info->tty);
 }
 
 static inline void
@@ -403,7 +395,7 @@
 	if (baud == 38400 && (port->flags & UPF_SPD_MASK) == UPF_SPD_CUST)
 		quot = port->custom_divisor;
 	else
-		quot = port->uartclk / (16 * baud);
+		quot = (port->uartclk + (8 * baud)) / (16 * baud);
 
 	return quot;
 }
@@ -581,10 +573,7 @@
 	spin_lock_irqsave(&port->lock, flags);
 	uart_circ_clear(&state->info->xmit);
 	spin_unlock_irqrestore(&port->lock, flags);
-	wake_up_interruptible(&tty->write_wait);
-	if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
-	    tty->ldisc.write_wakeup)
-		(tty->ldisc.write_wakeup)(tty);
+	tty_wakeup(tty);
 }
 
 /*
@@ -1216,7 +1205,7 @@
 {
 	struct uart_state *state = tty->driver_data;
 	struct uart_port *port;
-
+	
 	BUG_ON(!kernel_locked());
 
 	if (!state || !state->port)
@@ -1239,12 +1228,12 @@
 		 * one, we've got real problems, since it means the
 		 * serial port won't be shutdown.
 		 */
-		printk("uart_close: bad serial port count; tty->count is 1, "
+		printk(KERN_ERR "uart_close: bad serial port count; tty->count is 1, "
 		       "state->count is %d\n", state->count);
 		state->count = 1;
 	}
 	if (--state->count < 0) {
-		printk("rs_close: bad serial port count for %s: %d\n",
+		printk(KERN_ERR "uart_close: bad serial port count for %s: %d\n",
 		       tty->name, state->count);
 		state->count = 0;
 	}
@@ -1280,8 +1269,9 @@
 
 	uart_shutdown(state);
 	uart_flush_buffer(tty);
-	if (tty->ldisc.flush_buffer)
-		tty->ldisc.flush_buffer(tty);
+
+	tty_ldisc_flush(tty);	
+	
 	tty->closing = 0;
 	state->info->tty = NULL;
 
@@ -1978,6 +1968,7 @@
 		printk("I/O 0x%x offset 0x%x", port->iobase, port->hub6);
 		break;
 	case UPIO_MEM:
+	case UPIO_MEM32:
 		printk("MMIO 0x%lx", port->mapbase);
 		break;
 	}
diff -Nru a/drivers/serial/serial_cs.c b/drivers/serial/serial_cs.c
--- a/drivers/serial/serial_cs.c	2004-10-18 14:56:31 -07:00
+++ b/drivers/serial/serial_cs.c	2004-10-18 14:56:31 -07:00
@@ -363,9 +363,10 @@
 
 /*====================================================================*/
 
-static int simple_config(dev_link_t * link)
+static int simple_config(dev_link_t *link)
 {
 	static ioaddr_t base[5] = { 0x3f8, 0x2f8, 0x3e8, 0x2e8, 0x0 };
+	static int size_table[2] = { 8, 16 };
 	client_handle_t handle = link->handle;
 	struct serial_info *info = link->priv;
 	tuple_t tuple;
@@ -374,6 +375,7 @@
 	cistpl_cftable_entry_t *cf = &parse.cftable_entry;
 	config_info_t config;
 	int i, j, try;
+	int s;
 
 	/* If the card is already configured, look up the port and irq */
 	i = pcmcia_get_configuration_info(handle, &config);
@@ -399,29 +401,30 @@
 	tuple.Attributes = 0;
 	tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY;
 	/* Two tries: without IO aliases, then with aliases */
-	for (try = 0; try < 2; try++) {
-		i = first_tuple(handle, &tuple, &parse);
-		while (i != CS_NO_MORE_ITEMS) {
-			if (i != CS_SUCCESS)
-				goto next_entry;
-			if (cf->vpp1.present & (1 << CISTPL_POWER_VNOM))
-				link->conf.Vpp1 = link->conf.Vpp2 =
-				    cf->vpp1.param[CISTPL_POWER_VNOM] / 10000;
-			if ((cf->io.nwin > 0) && (cf->io.win[0].len == 8) &&
-			    (cf->io.win[0].base != 0)) {
-				link->conf.ConfigIndex = cf->index;
-				link->io.BasePort1 = cf->io.win[0].base;
-				link->io.IOAddrLines = (try == 0) ?
-				    16 : cf->io.flags & CISTPL_IO_LINES_MASK;
-				i = pcmcia_request_io(link->handle, &link->io);
-				if (i == CS_SUCCESS)
-					goto found_port;
+	for (s = 0; s < 2; s++) {
+		for (try = 0; try < 2; try++) {
+			i = first_tuple(handle, &tuple, &parse);
+			while (i != CS_NO_MORE_ITEMS) {
+				if (i != CS_SUCCESS)
+					goto next_entry;
+				if (cf->vpp1.present & (1 << CISTPL_POWER_VNOM))
+					link->conf.Vpp1 = link->conf.Vpp2 =
+					    cf->vpp1.param[CISTPL_POWER_VNOM] / 10000;
+				if ((cf->io.nwin > 0) && (cf->io.win[0].len == size_table[s]) &&
+					    (cf->io.win[0].base != 0)) {
+					link->conf.ConfigIndex = cf->index;
+					link->io.BasePort1 = cf->io.win[0].base;
+					link->io.IOAddrLines = (try == 0) ?
+					    16 : cf->io.flags & CISTPL_IO_LINES_MASK;
+					i = pcmcia_request_io(link->handle, &link->io);
+					if (i == CS_SUCCESS)
+						goto found_port;
+				}
+next_entry:
+				i = next_tuple(handle, &tuple, &parse);
 			}
-		      next_entry:
-			i = next_tuple(handle, &tuple, &parse);
 		}
 	}
-
 	/* Second pass: try to find an entry that isn't picky about
 	   its base address, then try to grab any standard serial port
 	   address, and finally try to get any free port. */
diff -Nru a/drivers/serial/sn_console.c b/drivers/serial/sn_console.c
--- a/drivers/serial/sn_console.c	2004-10-18 14:56:29 -07:00
+++ b/drivers/serial/sn_console.c	2004-10-18 14:56:29 -07:00
@@ -50,6 +50,7 @@
 #include <linux/miscdevice.h>
 #include <linux/serial_core.h>
 
+#include <asm/io.h>
 #include <asm/sn/simulator.h>
 #include <asm/sn/sn2/sn_private.h>
 #include <asm/sn/sn_sal.h>
@@ -80,6 +81,12 @@
 #define DEVICE_MAJOR 204
 #define DEVICE_MINOR 40
 
+#ifdef CONFIG_MAGIC_SYSRQ
+static char sysrq_serial_str[] = "\eSYS";
+static char *sysrq_serial_ptr = sysrq_serial_str;
+static unsigned long sysrq_requested;
+#endif /* CONFIG_MAGIC_SYSRQ */
+
 /*
  * Port definition - this kinda drives it all
  */
@@ -532,13 +539,15 @@
  * sn_receive_chars - Grab characters, pass them to tty layer
  * @port: Port to operate on
  * @regs: Saved registers (needed by uart_handle_sysrq_char)
+ * @flags: irq flags
  *
  * Note: If we're not registered with the serial core infrastructure yet,
  * we don't try to send characters to it...
  *
  */
 static void
-sn_receive_chars(struct sn_cons_port *port, struct pt_regs *regs)
+sn_receive_chars(struct sn_cons_port *port, struct pt_regs *regs,
+		 unsigned long flags)
 {
 	int ch;
 	struct tty_struct *tty;
@@ -569,10 +578,34 @@
 			       "obtaining data from the console (0x%0x)\n", ch);
 			break;
 		}
-#if defined(CONFIG_SERIAL_SGI_L1_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ)
-		if (uart_handle_sysrq_char(&port->sc_port, ch, regs))
-			continue;
-#endif				/* CONFIG_SERIAL_SGI_L1_CONSOLE && CONFIG_MAGIC_SYSRQ */
+#ifdef CONFIG_MAGIC_SYSRQ
+                if (sysrq_requested) {
+                        unsigned long sysrq_timeout = sysrq_requested + HZ*5;
+
+                        sysrq_requested = 0;
+                        if (ch && time_before(jiffies, sysrq_timeout)) {
+                                spin_unlock_irqrestore(&port->sc_port.lock, flags);
+                                handle_sysrq(ch, regs, NULL);
+                                spin_lock_irqsave(&port->sc_port.lock, flags);
+                                /* ignore actual sysrq command char */
+                                continue;
+                        }
+                }
+                if (ch == *sysrq_serial_ptr) {
+                        if (!(*++sysrq_serial_ptr)) {
+                                sysrq_requested = jiffies;
+                                sysrq_serial_ptr = sysrq_serial_str;
+                        }
+			/*
+			 * ignore the whole sysrq string except for the
+			 * leading escape
+			 */
+			if (ch != '\e')
+				continue;
+                }
+                else
+			sysrq_serial_ptr = sysrq_serial_str;
+#endif /* CONFIG_MAGIC_SYSRQ */
 
 		/* record the character to pass up to the tty layer */
 		if (tty) {
@@ -583,8 +616,6 @@
 			if (tty->flip.count == TTY_FLIPBUF_SIZE)
 				break;
 		}
-		else {
-		}
 		port->sc_port.icount.rx++;
 	}
 
@@ -695,7 +726,7 @@
 
 	spin_lock_irqsave(&port->sc_port.lock, flags);
 	if (status & SAL_CONSOLE_INTR_RECV) {
-		sn_receive_chars(port, regs);
+		sn_receive_chars(port, regs, flags);
 	}
 	if (status & SAL_CONSOLE_INTR_XMIT) {
 		sn_transmit_chars(port, TRANSMIT_BUFFERED);
@@ -714,7 +745,8 @@
 static int
 sn_sal_connect_interrupt(struct sn_cons_port *port)
 {
-	if (request_irq(SGI_UART_VECTOR, sn_sal_interrupt, SA_INTERRUPT,
+	if (request_irq(SGI_UART_VECTOR, sn_sal_interrupt,
+			SA_INTERRUPT | SA_SHIRQ,
 			"SAL console driver", port) >= 0) {
 		return SGI_UART_VECTOR;
 	}
@@ -743,7 +775,7 @@
 
 	if (!port->sc_port.irq) {
 		spin_lock_irqsave(&port->sc_port.lock, flags);
-		sn_receive_chars(port, NULL);
+		sn_receive_chars(port, NULL, flags);
 		sn_transmit_chars(port, TRANSMIT_RAW);
 		spin_unlock_irqrestore(&port->sc_port.lock, flags);
 		mod_timer(&port->sc_timer,
@@ -851,7 +883,6 @@
  * Kernel console definitions
  */
 
-#ifdef CONFIG_SERIAL_SGI_L1_CONSOLE
 static void sn_sal_console_write(struct console *, const char *, unsigned);
 static int __init sn_sal_console_setup(struct console *, char *);
 extern struct uart_driver sal_console_uart;
@@ -867,9 +898,6 @@
 };
 
 #define SAL_CONSOLE	&sal_console
-#else
-#define SAL_CONSOLE	0
-#endif				/* CONFIG_SERIAL_SGI_L1_CONSOLE */
 
 static struct uart_driver sal_console_uart = {
 	.owner = THIS_MODULE,
@@ -895,11 +923,11 @@
 {
 	int retval;
 
-	printk(KERN_INFO "sn_console: Console driver init\n");
-
 	if (!ia64_platform_is("sn2"))
 		return -ENODEV;
 
+	printk(KERN_INFO "sn_console: Console driver init\n");
+
 	if (USE_DYNAMIC_MINOR == 1) {
 		misc.minor = MISC_DYNAMIC_MINOR;
 		misc.name = DEVICE_NAME_DYNAMIC;
@@ -969,8 +997,6 @@
 module_init(sn_sal_module_init);
 module_exit(sn_sal_module_exit);
 
-#ifdef CONFIG_SERIAL_SGI_L1_CONSOLE
-
 /**
  * puts_raw_fixed - sn_sal_console_write helper for adding \r's as required
  * @puts_raw : puts function to do the writing
@@ -1085,7 +1111,9 @@
 			spin_unlock_irqrestore(&port->sc_port.lock, flags);
 
 			puts_raw_fixed(port->sc_ops->sal_puts_raw, s, count);
+#if defined(CONFIG_SMP) || defined(CONFIG_PREEMPT)
 		}
+#endif
 	}
 	else {
 		/* Not yet registered with serial core - simple case */
@@ -1190,5 +1218,3 @@
 }
 
 console_initcall(sn_sal_serial_console_init);
-
-#endif				/* CONFIG_SERIAL_SGI_L1_CONSOLE */
diff -Nru a/drivers/serial/sunsab.c b/drivers/serial/sunsab.c
--- a/drivers/serial/sunsab.c	2004-10-18 14:56:28 -07:00
+++ b/drivers/serial/sunsab.c	2004-10-18 14:56:28 -07:00
@@ -768,25 +768,6 @@
 	writeb((readb(&up->regs->rw.ccr2) & ~0xc0) | ((ebrg >> 2) & 0xc0),
 	       &up->regs->rw.ccr2);
 
-	if (cflag & CRTSCTS) {
-		writeb(readb(&up->regs->rw.mode) & ~SAB82532_MODE_RTS,
-		       &up->regs->rw.mode);
-		writeb(readb(&up->regs->rw.mode) | SAB82532_MODE_FRTS,
-		       &up->regs->rw.mode);
-		writeb(readb(&up->regs->rw.mode) & ~SAB82532_MODE_FCTS,
-		       &up->regs->rw.mode);
-		up->interrupt_mask1 &= ~SAB82532_IMR1_CSC;
-		writeb(up->interrupt_mask1, &up->regs->w.imr1);
-	} else {
-		writeb(readb(&up->regs->rw.mode) | SAB82532_MODE_RTS,
-		       &up->regs->rw.mode);
-		writeb(readb(&up->regs->rw.mode) & ~SAB82532_MODE_FRTS,
-		       &up->regs->rw.mode);
-		writeb(readb(&up->regs->rw.mode) | SAB82532_MODE_FCTS,
-		       &up->regs->rw.mode);
-		up->interrupt_mask1 |= SAB82532_IMR1_CSC;
-		writeb(up->interrupt_mask1, &up->regs->w.imr1);
-	}
 	writeb(readb(&up->regs->rw.mode) | SAB82532_MODE_RAC, &up->regs->rw.mode);
 
 }
@@ -940,6 +921,7 @@
 	writeb(up->interrupt_mask1, &up->regs->w.imr1);
 
 	sunsab_convert_to_sab(up, con->cflag, 0, baud);
+	sunsab_set_mctrl(&up->port, TIOCM_DTR | TIOCM_RTS);
 
 	spin_unlock_irqrestore(&up->port.lock, flags);
 	
diff -Nru a/drivers/serial/sunsu.c b/drivers/serial/sunsu.c
--- a/drivers/serial/sunsu.c	2004-10-18 14:56:17 -07:00
+++ b/drivers/serial/sunsu.c	2004-10-18 14:56:17 -07:00
@@ -98,7 +98,7 @@
 	unsigned int		irq;
 
 #ifdef CONFIG_SERIO
-	struct serio		serio;
+	struct serio		*serio;
 	int			serio_open;
 #endif
 };
@@ -520,7 +520,7 @@
 		/* Stop-A is handled by drivers/char/keyboard.c now. */
 		if (up->su_type == SU_PORT_KBD) {
 #ifdef CONFIG_SERIO
-			serio_interrupt(&up->serio, ch, 0, regs);
+			serio_interrupt(up->serio, ch, 0, regs);
 #endif
 		} else if (up->su_type == SU_PORT_MS) {
 			int ret = suncore_mouse_baud_detection(ch, is_break);
@@ -534,7 +534,7 @@
 
 			case 0:
 #ifdef CONFIG_SERIO
-				serio_interrupt(&up->serio, ch, 0, regs);
+				serio_interrupt(up->serio, ch, 0, regs);
 #endif
 				break;
 			};
@@ -994,7 +994,7 @@
 
 static int sunsu_serio_write(struct serio *serio, unsigned char ch)
 {
-	struct uart_sunsu_port *up = serio->driver;
+	struct uart_sunsu_port *up = serio->port_data;
 	unsigned long flags;
 	int lsr;
 
@@ -1014,7 +1014,7 @@
 
 static int sunsu_serio_open(struct serio *serio)
 {
-	struct uart_sunsu_port *up = serio->driver;
+	struct uart_sunsu_port *up = serio->port_data;
 	unsigned long flags;
 	int ret;
 
@@ -1031,7 +1031,7 @@
 
 static void sunsu_serio_close(struct serio *serio)
 {
-	struct uart_sunsu_port *up = serio->driver;
+	struct uart_sunsu_port *up = serio->port_data;
 	unsigned long flags;
 
 	spin_lock_irqsave(&sunsu_serio_lock, flags);
@@ -1284,54 +1284,58 @@
 	.major			= TTY_MAJOR,
 };
 
-static int __init sunsu_kbd_ms_init(void)
+static int __init sunsu_kbd_ms_init(struct uart_sunsu_port *up, int channel)
 {
-	struct uart_sunsu_port *up;
-	int i;
+	struct serio *serio;
 
-	for (i = 0, up = sunsu_ports; i < 2; i++, up++) {
-		up->port.line = i;
-		up->port.type = PORT_UNKNOWN;
-		up->port.uartclk = (SU_BASE_BAUD * 16);
+	up->port.line = channel;
+	up->port.type = PORT_UNKNOWN;
+	up->port.uartclk = (SU_BASE_BAUD * 16);
 
-		if (up->su_type == SU_PORT_KBD)
-			up->cflag = B1200 | CS8 | CLOCAL | CREAD;
-		else
-			up->cflag = B4800 | CS8 | CLOCAL | CREAD;
+	if (up->su_type == SU_PORT_KBD)
+		up->cflag = B1200 | CS8 | CLOCAL | CREAD;
+	else
+		up->cflag = B4800 | CS8 | CLOCAL | CREAD;
 
-		sunsu_autoconfig(up);
-		if (up->port.type == PORT_UNKNOWN)
-			continue;
+	sunsu_autoconfig(up);
+	if (up->port.type == PORT_UNKNOWN)
+		return -1;
 
-		printk(KERN_INFO "su%d at 0x%p (irq = %s) is a %s\n",
-		       i,
-		       up->port.membase, __irq_itoa(up->irq),
-		       sunsu_type(&up->port));
+	printk(KERN_INFO "su%d at 0x%p (irq = %s) is a %s\n",
+	       channel,
+	       up->port.membase, __irq_itoa(up->irq),
+	       sunsu_type(&up->port));
 
 #ifdef CONFIG_SERIO
-		memset(&up->serio, 0, sizeof(up->serio));
+	up->serio = serio = kmalloc(sizeof(struct serio), GFP_KERNEL);
+	if (serio) {
+		memset(serio, 0, sizeof(*serio));
 
-		up->serio.driver = up;
+		serio->port_data = up;
 
-		up->serio.type = SERIO_RS232;
+		serio->type = SERIO_RS232;
 		if (up->su_type == SU_PORT_KBD) {
-			up->serio.type |= SERIO_SUNKBD;
-			up->serio.name = "sukbd";
+			serio->type |= SERIO_SUNKBD;
+			strlcpy(serio->name, "sukbd", sizeof(serio->name));
 		} else {
-			up->serio.type |= (SERIO_SUN | (1 << 16));
-			up->serio.name = "sums";
+			serio->type |= (SERIO_SUN | (1 << 16));
+			strlcpy(serio->name, "sums", sizeof(serio->name));
 		}
-		up->serio.phys = (i == 0 ? "su/serio0" : "su/serio1");
+		strlcpy(serio->phys, (channel == 0 ? "su/serio0" : "su/serio1"),
+			sizeof(serio->phys));
 
-		up->serio.write = sunsu_serio_write;
-		up->serio.open = sunsu_serio_open;
-		up->serio.close = sunsu_serio_close;
+		serio->write = sunsu_serio_write;
+		serio->open = sunsu_serio_open;
+		serio->close = sunsu_serio_close;
 
-		serio_register_port(&up->serio);
+		serio_register_port(serio);
+	} else {
+		printk(KERN_WARNING "su%d: not enough memory for serio port\n",
+			channel);
+	}
 #endif
 
-		sunsu_startup(&up->port);
-	}
+	sunsu_startup(&up->port);
 	return 0;
 }
 
@@ -1680,10 +1684,12 @@
 	if (scan.msx != -1 && scan.kbx != -1) {
 		sunsu_ports[0].su_type = SU_PORT_MS;
 		sunsu_ports[0].port_node = scan.msnode;
+		sunsu_kbd_ms_init(&sunsu_ports[0], 0);
+
 		sunsu_ports[1].su_type = SU_PORT_KBD;
 		sunsu_ports[1].port_node = scan.kbnode;
+		sunsu_kbd_ms_init(&sunsu_ports[1], 1);
 
-		sunsu_kbd_ms_init();
 		return 0;
 	}
 
@@ -1715,7 +1721,10 @@
 		if (up->su_type == SU_PORT_MS ||
 		    up->su_type == SU_PORT_KBD) {
 #ifdef CONFIG_SERIO
-			serio_unregister_port(&up->serio);
+			if (up->serio) {
+				serio_unregister_port(up->serio);
+				up->serio = NULL;
+			}
 #endif
 		} else if (up->port.type != PORT_UNKNOWN) {
 			uart_remove_one_port(&sunsu_reg, &up->port);
diff -Nru a/drivers/serial/sunzilog.c b/drivers/serial/sunzilog.c
--- a/drivers/serial/sunzilog.c	2004-10-18 14:57:04 -07:00
+++ b/drivers/serial/sunzilog.c	2004-10-18 14:57:04 -07:00
@@ -107,7 +107,7 @@
 	unsigned char			prev_status;
 
 #ifdef CONFIG_SERIO
-	struct serio			serio;
+	struct serio			*serio;
 	int				serio_open;
 #endif
 };
@@ -291,7 +291,7 @@
 		/* Stop-A is handled by drivers/char/keyboard.c now. */
 #ifdef CONFIG_SERIO
 		if (up->serio_open)
-			serio_interrupt(&up->serio, ch, 0, regs);
+			serio_interrupt(up->serio, ch, 0, regs);
 #endif
 	} else if (ZS_IS_MOUSE(up)) {
 		int ret = suncore_mouse_baud_detection(ch, is_break);
@@ -306,7 +306,7 @@
 		case 0:
 #ifdef CONFIG_SERIO
 			if (up->serio_open)
-				serio_interrupt(&up->serio, ch, 0, regs);
+				serio_interrupt(up->serio, ch, 0, regs);
 #endif
 			break;
 		};
@@ -1295,7 +1295,7 @@
 
 static int sunzilog_serio_write(struct serio *serio, unsigned char ch)
 {
-	struct uart_sunzilog_port *up = serio->driver;
+	struct uart_sunzilog_port *up = serio->port_data;
 	unsigned long flags;
 
 	spin_lock_irqsave(&sunzilog_serio_lock, flags);
@@ -1309,7 +1309,7 @@
 
 static int sunzilog_serio_open(struct serio *serio)
 {
-	struct uart_sunzilog_port *up = serio->driver;
+	struct uart_sunzilog_port *up = serio->port_data;
 	unsigned long flags;
 	int ret;
 
@@ -1326,7 +1326,7 @@
 
 static void sunzilog_serio_close(struct serio *serio)
 {
-	struct uart_sunzilog_port *up = serio->driver;
+	struct uart_sunzilog_port *up = serio->port_data;
 	unsigned long flags;
 
 	spin_lock_irqsave(&sunzilog_serio_lock, flags);
@@ -1545,33 +1545,44 @@
 	up->curregs[R15] = BRKIE;
 	brg = BPS_TO_BRG(baud, ZS_CLOCK / ZS_CLOCK_DIVISOR);
 	sunzilog_convert_to_zs(up, up->cflag, 0, brg);
+	sunzilog_set_mctrl(&up->port, TIOCM_DTR | TIOCM_RTS);
+	__sunzilog_startup(up);
+}
 
 #ifdef CONFIG_SERIO
-	memset(&up->serio, 0, sizeof(up->serio));
+static void __init sunzilog_register_serio(struct uart_sunzilog_port *up, int channel)
+{
+	struct serio *serio;
 
-	up->serio.driver = up;
+	up->serio = serio = kmalloc(sizeof(struct serio), GFP_KERNEL);
+	if (serio) {
+		memset(serio, 0, sizeof(*serio));
 
-	up->serio.type = SERIO_RS232;
-	if (channel == KEYBOARD_LINE) {
-		up->serio.type |= SERIO_SUNKBD;
-		up->serio.name = "zskbd";
-	} else {
-		up->serio.type |= (SERIO_SUN | (1 << 16));
-		up->serio.name = "zsms";
-	}
-	up->serio.phys = (channel == KEYBOARD_LINE ?
-			  "zs/serio0" : "zs/serio1");
+		serio->port_data = up;
 
-	up->serio.write = sunzilog_serio_write;
-	up->serio.open = sunzilog_serio_open;
-	up->serio.close = sunzilog_serio_close;
-
-	serio_register_port(&up->serio);
-#endif
+		serio->type = SERIO_RS232;
+		if (channel == KEYBOARD_LINE) {
+			serio->type |= SERIO_SUNKBD;
+			strlcpy(serio->name, "zskbd", sizeof(serio->name));
+		} else {
+			serio->type |= (SERIO_SUN | (1 << 16));
+			strlcpy(serio->name, "zsms", sizeof(serio->name));
+		}
+		strlcpy(serio->phys,
+			(channel == KEYBOARD_LINE ? "zs/serio0" : "zs/serio1"),
+			sizeof(serio->phys));
+
+		serio->write = sunzilog_serio_write;
+		serio->open = sunzilog_serio_open;
+		serio->close = sunzilog_serio_close;
 
-	sunzilog_set_mctrl(&up->port, TIOCM_DTR | TIOCM_RTS);
-	__sunzilog_startup(up);
+		serio_register_port(serio);
+	} else {
+		printk(KERN_WARNING "zs%d: not enough memory for serio port\n",
+			channel);
+	}
 }
+#endif
 
 static void __init sunzilog_init_hw(void)
 {
@@ -1615,6 +1626,11 @@
 		}
 
 		spin_unlock_irqrestore(&up->port.lock, flags);
+
+#ifdef CONFIG_SERIO
+		if (i == KEYBOARD_LINE || i == MOUSE_LINE)
+			sunzilog_register_serio(up, i);
+#endif
 	}
 }
 
@@ -1732,10 +1748,15 @@
 	for (i = 0; i < NUM_CHANNELS; i++) {
 		struct uart_sunzilog_port *up = &sunzilog_port_table[i];
 
-		if (ZS_IS_KEYB(up) || ZS_IS_MOUSE(up))
-			continue;
-
-		uart_remove_one_port(&sunzilog_reg, &up->port);
+		if (ZS_IS_KEYB(up) || ZS_IS_MOUSE(up)) {
+#ifdef CONFIG_SERIO
+			if (up->serio) {
+				serio_unregister_port(up->serio);
+				up->serio = NULL;
+			}
+#endif
+		} else
+			uart_remove_one_port(&sunzilog_reg, &up->port);
 	}
 
 	uart_unregister_driver(&sunzilog_reg);
diff -Nru a/drivers/tc/zs.c b/drivers/tc/zs.c
--- a/drivers/tc/zs.c	2004-10-18 14:56:50 -07:00
+++ b/drivers/tc/zs.c	2004-10-18 14:56:50 -07:00
@@ -211,10 +211,6 @@
 static void change_speed(struct dec_serial *info);
 static void rs_wait_until_sent(struct tty_struct *tty, int timeout);
 
-#ifndef MIN
-#define MIN(a,b)	((a) < (b) ? (a) : (b))
-#endif
-
 /*
  * tmp_buf is used as a temporary buffer by serial_write.  We need to
  * lock it in case the copy_from_user blocks while swapping in a page,
@@ -683,10 +679,7 @@
 		return;
 
 	if (test_and_clear_bit(RS_EVENT_WRITE_WAKEUP, &info->event)) {
-		if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
-		    tty->ldisc.write_wakeup)
-			(tty->ldisc.write_wakeup)(tty);
-		wake_up_interruptible(&tty->write_wait);
+		tty_wakeup(tty);
 	}
 }
 
@@ -706,7 +699,7 @@
 	save_flags(flags); cli();
 
 #ifdef SERIAL_DEBUG_OPEN
-	printk("starting up ttyS%02d (irq %d)...", info->line, info->irq);
+	printk("starting up ttyS%d (irq %d)...", info->line, info->irq);
 #endif
 
 	/*
@@ -950,16 +943,16 @@
 	save_flags(flags);
 	while (1) {
 		cli();		
-		c = MIN(count, MIN(SERIAL_XMIT_SIZE - info->xmit_cnt - 1,
-				   SERIAL_XMIT_SIZE - info->xmit_head));
+		c = min_t(int, count, min(SERIAL_XMIT_SIZE - info->xmit_cnt - 1,
+					  SERIAL_XMIT_SIZE - info->xmit_head));
 		if (c <= 0)
 			break;
 
 		if (from_user) {
 			down(&tmp_buf_sem);
 			copy_from_user(tmp_buf, buf, c);
-			c = MIN(c, MIN(SERIAL_XMIT_SIZE - info->xmit_cnt - 1,
-				       SERIAL_XMIT_SIZE - info->xmit_head));
+			c = min_t(int, c, min(SERIAL_XMIT_SIZE - info->xmit_cnt - 1,
+					      SERIAL_XMIT_SIZE - info->xmit_head));
 			memcpy(info->xmit_buf + info->xmit_head, tmp_buf, c);
 			up(&tmp_buf_sem);
 		} else
@@ -1010,10 +1003,7 @@
 	cli();
 	info->xmit_cnt = info->xmit_head = info->xmit_tail = 0;
 	sti();
-	wake_up_interruptible(&tty->write_wait);
-	if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
-	    tty->ldisc.write_wakeup)
-		(tty->ldisc.write_wakeup)(tty);
+	tty_wakeup(tty);
 }
 
 /*
@@ -1356,7 +1346,7 @@
 	}
 	
 #ifdef SERIAL_DEBUG_OPEN
-	printk("rs_close ttyS%02d, count = %d\n", info->line, info->count);
+	printk("rs_close ttyS%d, count = %d\n", info->line, info->count);
 #endif
 	if ((tty->count == 1) && (info->count != 1)) {
 		/*
@@ -1371,7 +1361,7 @@
 		info->count = 1;
 	}
 	if (--info->count < 0) {
-		printk("rs_close: bad serial port count for ttyS%02d: %d\n",
+		printk("rs_close: bad serial port count for ttyS%d: %d\n",
 		       info->line, info->count);
 		info->count = 0;
 	}
@@ -1407,8 +1397,7 @@
 	shutdown(info);
 	if (tty->driver->flush_buffer)
 		tty->driver->flush_buffer(tty);
-	if (tty->ldisc.flush_buffer)
-		tty->ldisc.flush_buffer(tty);
+	tty_ldisc_flush(tty);
 	tty->closing = 0;
 	info->event = 0;
 	info->tty = 0;
@@ -1446,7 +1435,7 @@
 	if (char_time == 0)
 		char_time = 1;
 	if (timeout)
-		char_time = MIN(char_time, timeout);
+		char_time = min_t(unsigned long, char_time, timeout);
 	while ((read_zsreg(info->zs_channel, 1) & Tx_BUF_EMP) == 0) {
 		current->state = TASK_INTERRUPTIBLE;
 		schedule_timeout(char_time);
@@ -1531,7 +1520,7 @@
 	retval = 0;
 	add_wait_queue(&info->open_wait, &wait);
 #ifdef SERIAL_DEBUG_OPEN
-	printk("block_til_ready before block: ttyS%02d, count = %d\n",
+	printk("block_til_ready before block: ttyS%d, count = %d\n",
 	       info->line, info->count);
 #endif
 	cli();
@@ -1565,7 +1554,7 @@
 			break;
 		}
 #ifdef SERIAL_DEBUG_OPEN
-		printk("block_til_ready blocking: ttyS%02d, count = %d\n",
+		printk("block_til_ready blocking: ttyS%d, count = %d\n",
 		       info->line, info->count);
 #endif
 		schedule();
@@ -1576,7 +1565,7 @@
 		info->count++;
 	info->blocked_open--;
 #ifdef SERIAL_DEBUG_OPEN
-	printk("block_til_ready after blocking: ttyS%02d, count = %d\n",
+	printk("block_til_ready after blocking: ttyS%d, count = %d\n",
 	       info->line, info->count);
 #endif
 	if (retval)
@@ -1742,14 +1731,10 @@
 			 * We're called early and memory managment isn't up, yet.
 			 * Thus check_region would fail.
 			 */
-			if (check_region((unsigned long)
+			if (!request_region((unsigned long)
 					 zs_channels[n_channels].control,
-					 ZS_CHAN_IO_SIZE) < 0) {
+					 ZS_CHAN_IO_SIZE, "SCC"))
 				panic("SCC I/O region is not free");
-			}
-			request_region((unsigned long)
-				       zs_channels[n_channels].control,
-				       ZS_CHAN_IO_SIZE, "SCC");
 #endif
 			zs_soft[n_channels].zs_channel = &zs_channels[n_channels];
 			zs_soft[n_channels].irq = zs_parms->irq;
@@ -1896,7 +1881,7 @@
 		info->tqueue.data = info;
 		init_waitqueue_head(&info->open_wait);
 		init_waitqueue_head(&info->close_wait);
-		printk("ttyS%02d at 0x%08x (irq = %d)", info->line, 
+		printk("ttyS%d at 0x%08x (irq = %d)", info->line,
 		       info->port, info->irq);
 		printk(" is a Z85C30 SCC\n");
 		tty_register_device(serial_driver, info->line, NULL);
diff -Nru a/drivers/telephony/ixj.c b/drivers/telephony/ixj.c
--- a/drivers/telephony/ixj.c	2004-10-18 14:55:54 -07:00
+++ b/drivers/telephony/ixj.c	2004-10-18 14:55:54 -07:00
@@ -7718,6 +7718,23 @@
         cleanup();
 }
 
+static IXJ *new_ixj(unsigned long port)
+{
+	IXJ *res;
+	if (!request_region(port, 16, "ixj DSP")) {
+		printk(KERN_INFO "ixj: can't get I/O address 0x%lx\n", port);
+		return NULL;
+	}
+	res = ixj_alloc();
+	if (!res) {
+		release_region(port, 16);
+		printk(KERN_INFO "ixj: out of memory\n");
+		return NULL;
+	}
+	res->DSPbase = port;
+	return res;
+}
+
 int __init ixj_probe_isapnp(int *cnt)
 {               
 	int probe = 0;
@@ -7750,15 +7767,9 @@
 				return -ENODEV;
 			}
 
-			result = check_region(pnp_port_start(dev, 0), 16);
-			if (result) {
-				printk(KERN_INFO "ixj: can't get I/O address 0x%lx\n", pnp_port_start(dev, 0));
+			j = new_ixj(pnp_port_start(dev, 0));
+			if (!j)
 				break;
-			}
-
-			j = ixj_alloc();
-			j->DSPbase = pnp_port_start(dev,0);
-			request_region(j->DSPbase, 16, "ixj DSP");
 
 			if (func != 0x110)
 				j->XILINXbase = pnp_port_start(dev, 1);	/* get real port */
@@ -7806,22 +7817,15 @@
                         
 int __init ixj_probe_isa(int *cnt)
 {
-	int i, result, probe;
+	int i, probe;
 
 	/* Use passed parameters for older kernels without PnP */
 	for (i = 0; i < IXJMAX; i++) {
 		if (dspio[i]) {
-			IXJ *j;
+			IXJ *j = new_ixj(dspio[i]);
 
-			if ((result = check_region(ixj[*cnt].DSPbase, 16)) < 0) {
-				printk(KERN_INFO "ixj: can't get I/O address 0x%x\n", ixj[*cnt].DSPbase);
+			if (!j)
 				break;
-			}
-
-			j = ixj_alloc();
-
-			j->DSPbase = dspio[i];
-			request_region(j->DSPbase, 16, "ixj DSP");
 
 			j->XILINXbase = xio[i];
 			j->cardtype = 0;
@@ -7840,7 +7844,6 @@
 	struct pci_dev *pci = NULL;   
 	int i, probe = 0;
 	IXJ *j = NULL;
-	int result;
 
 	for (i = 0; i < IXJMAX - *cnt; i++) {
 		pci = pci_find_device(0x15E2, 0x0500, pci);
@@ -7849,20 +7852,12 @@
 
 		if (pci_enable_device(pci))
 			break;
-		if ((result = check_region(pci_resource_start(pci, 0), 16)) < 0) {
-			printk(KERN_INFO "ixj: can't get I/O address\n");
+		j = new_ixj(pci_resource_start(pci, 0));
+		if (!j)
 			break;
-		}
 
-		/* Grab a device slot */	
-		j = ixj_alloc();
-		if(j == NULL)
-			break;
-	
-		j->DSPbase = pci_resource_start(pci, 0);
 		j->serial = (PCIEE_GetSerialNumber)pci_resource_start(pci, 2);
 		j->XILINXbase = j->DSPbase + 0x10;
-		request_region(j->DSPbase, 16, "ixj DSP");
 		j->cardtype = QTI_PHONEJACK_PCI;
 		j->board = *cnt;
 		probe = ixj_selfprobe(j);
diff -Nru a/drivers/telephony/ixj.h b/drivers/telephony/ixj.h
--- a/drivers/telephony/ixj.h	2004-10-18 14:57:04 -07:00
+++ b/drivers/telephony/ixj.h	2004-10-18 14:57:04 -07:00
@@ -1188,12 +1188,12 @@
 	unsigned int cid_rec_codec;
 	unsigned int cid_rec_volume;
 	unsigned char cid_rec_flag;
-	char rec_mode;
+	signed char rec_mode;
 	unsigned int play_codec;
 	unsigned int cid_play_codec;
 	unsigned int cid_play_volume;
 	unsigned char cid_play_flag;
-	char play_mode;
+	signed char play_mode;
 	IXJ_FLAGS flags;
 	unsigned long busyflags;
 	unsigned int rec_frame_size;
diff -Nru a/drivers/usb/class/audio.c b/drivers/usb/class/audio.c
--- a/drivers/usb/class/audio.c	2004-10-18 14:57:04 -07:00
+++ b/drivers/usb/class/audio.c	2004-10-18 14:57:04 -07:00
@@ -1954,9 +1954,9 @@
 	struct usb_audio_state *s;
 
 	down(&open_sem);
-	for (devs = audiodevs.next; devs != &audiodevs; devs = devs->next) {
+	list_for_each(devs, &audiodevs) {
 		s = list_entry(devs, struct usb_audio_state, audiodev);
-		for (mdevs = s->mixerlist.next; mdevs != &s->mixerlist; mdevs = mdevs->next) {
+		list_for_each(mdevs, &s->mixerlist) {
 			ms = list_entry(mdevs, struct usb_mixerdev, list);
 			if (ms->dev_mixer == minor)
 				goto mixer_found;
@@ -2640,9 +2640,9 @@
 
 	for (;;) {
 		down(&open_sem);
-		for (devs = audiodevs.next; devs != &audiodevs; devs = devs->next) {
+		list_for_each(devs, &audiodevs) {
 			s = list_entry(devs, struct usb_audio_state, audiodev);
-			for (adevs = s->audiolist.next; adevs != &s->audiolist; adevs = adevs->next) {
+			list_for_each(adevs, &s->audiolist) {
 				as = list_entry(adevs, struct usb_audiodev, list);
 				if (!((as->dev_audio ^ minor) & ~0xf))
 					goto device_found;
@@ -3831,7 +3831,7 @@
 	usb_set_intfdata (intf, NULL);
 
 	/* deregister all audio and mixer devices, so no new processes can open this device */
-	for(list = s->audiolist.next; list != &s->audiolist; list = list->next) {
+	list_for_each(list, &s->audiolist) {
 		as = list_entry(list, struct usb_audiodev, list);
 		usbin_disc(as);
 		usbout_disc(as);
@@ -3843,7 +3843,7 @@
 		}
 		as->dev_audio = -1;
 	}
-	for(list = s->mixerlist.next; list != &s->mixerlist; list = list->next) {
+	list_for_each(list, &s->mixerlist) {
 		ms = list_entry(list, struct usb_mixerdev, list);
 		if (ms->dev_mixer >= 0) {
 			unregister_sound_mixer(ms->dev_mixer);
diff -Nru a/drivers/usb/class/bluetty.c b/drivers/usb/class/bluetty.c
--- a/drivers/usb/class/bluetty.c	2004-10-18 14:56:49 -07:00
+++ b/drivers/usb/class/bluetty.c	2004-10-18 14:56:49 -07:00
@@ -988,21 +988,13 @@
 static void bluetooth_softint(void *private)
 {
 	struct usb_bluetooth *bluetooth = get_usb_bluetooth ((struct usb_bluetooth *)private, __FUNCTION__);
-	struct tty_struct *tty;
 
 	dbg("%s", __FUNCTION__);
 
-	if (!bluetooth) {
+	if (!bluetooth)
 		return;
-	}
 
-	tty = bluetooth->tty;
-	if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) && tty->ldisc.write_wakeup) {
-		dbg("%s - write wakeup call.", __FUNCTION__);
-		(tty->ldisc.write_wakeup)(tty);
-	}
-
-	wake_up_interruptible(&tty->write_wait);
+	tty_wakeup(bluetooth->tty);
 }
 
 
diff -Nru a/drivers/usb/class/cdc-acm.c b/drivers/usb/class/cdc-acm.c
--- a/drivers/usb/class/cdc-acm.c	2004-10-18 14:56:33 -07:00
+++ b/drivers/usb/class/cdc-acm.c	2004-10-18 14:56:33 -07:00
@@ -142,7 +142,7 @@
 
 		case ACM_IRQ_LINE_STATE:
 
-			newctrl = le16_to_cpu(get_unaligned((__u16 *) data));
+			newctrl = le16_to_cpu(get_unaligned((__le16 *) data));
 
 			if (acm->tty && !acm->clocal && (acm->ctrlin & ~newctrl & ACM_CTRL_DCD)) {
 				dbg("calling hangup");
@@ -248,16 +248,11 @@
 static void acm_softint(void *private)
 {
 	struct acm *acm = private;
-	struct tty_struct *tty = acm->tty;
 	dbg("Entering acm_softint.\n");
 	
 	if (!ACM_READY(acm))
 		return;
-
-	if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) && tty->ldisc.write_wakeup)
-		(tty->ldisc.write_wakeup)(tty);
-
-	wake_up_interruptible(&tty->write_wait);
+	tty_wakeup(acm->tty);
 }
 
 /*
@@ -367,7 +362,7 @@
 	acm->writeurb->dev = acm->dev;
 
 	acm->ready_for_write = 0;
-	stat = usb_submit_urb(acm->writeurb, GFP_NOIO);
+	stat = usb_submit_urb(acm->writeurb, from_user ? GFP_KERNEL : GFP_ATOMIC);
 	if (stat < 0) {
 		dbg("usb_submit_urb(write bulk) failed");
 		acm->ready_for_write = 1;
@@ -583,19 +578,25 @@
 	}
 
 	if (!union_header) {
-		dev_dbg(&intf->dev,"No union descriptor, giving up\n");
-		return -ENODEV;
-	}
-
-	control_interface = usb_ifnum_to_if(usb_dev, union_header->bMasterInterface0);
-	data_interface = usb_ifnum_to_if(usb_dev, (data_interface_num = union_header->bSlaveInterface0));
-	if (!control_interface || !data_interface) {
-		dev_dbg(&intf->dev,"no interfaces\n");
-		return -ENODEV;
+		if (call_interface_num > 0) {
+			dev_dbg(&intf->dev,"No union descriptor, using call management descriptor\n");
+			data_interface = usb_ifnum_to_if(usb_dev, (data_interface_num = call_interface_num));
+			control_interface = intf;
+		} else {
+			dev_dbg(&intf->dev,"No union descriptor, giving up\n");
+			return -ENODEV;
+		}
+	} else {
+		control_interface = usb_ifnum_to_if(usb_dev, union_header->bMasterInterface0);
+		data_interface = usb_ifnum_to_if(usb_dev, (data_interface_num = union_header->bSlaveInterface0));
+		if (!control_interface || !data_interface) {
+			dev_dbg(&intf->dev,"no interfaces\n");
+			return -ENODEV;
+		}
 	}
 	
-	if (data_interface_num != call_interface_num)
-		dev_dbg(&intf->dev,"Seperate call control interface. That is not fully supported.");
+		if (data_interface_num != call_interface_num)
+			dev_dbg(&intf->dev,"Seperate call control interface. That is not fully supported.");
 
 	if (usb_interface_claimed(data_interface)) { /* valid in this context */
 		dev_dbg(&intf->dev,"The data interface isn't available\n");
diff -Nru a/drivers/usb/class/cdc-acm.h b/drivers/usb/class/cdc-acm.h
--- a/drivers/usb/class/cdc-acm.h	2004-10-18 14:57:04 -07:00
+++ b/drivers/usb/class/cdc-acm.h	2004-10-18 14:57:04 -07:00
@@ -70,7 +70,7 @@
  */
 
 struct acm_line {
-	__u32 speed;
+	__le32 speed;
 	__u8 stopbits;
 	__u8 parity;
 	__u8 databits;
diff -Nru a/drivers/usb/class/usb-midi.c b/drivers/usb/class/usb-midi.c
--- a/drivers/usb/class/usb-midi.c	2004-10-18 14:55:54 -07:00
+++ b/drivers/usb/class/usb-midi.c	2004-10-18 14:55:54 -07:00
@@ -55,39 +55,39 @@
 /* ------------------------------------------------------------------------- */
 
 static int singlebyte = 0;
-MODULE_PARM(singlebyte,"i");
+module_param(singlebyte, int, 0);
 MODULE_PARM_DESC(singlebyte,"Enable sending MIDI messages with single message packet");
 
 static int maxdevices = 4;
-MODULE_PARM(maxdevices,"i");
+module_param(maxdevices, int, 0);
 MODULE_PARM_DESC(maxdevices,"Max number of allocatable MIDI device");
 
 static int uvendor     = -1;
-MODULE_PARM(uvendor,"i");
+module_param(uvendor, int, 0);
 MODULE_PARM_DESC(uvendor, "The USB Vendor ID of a semi-compliant interface");
 
 static int uproduct    = -1;
-MODULE_PARM(uproduct,"i");
+module_param(uproduct, int, 0);
 MODULE_PARM_DESC(uproduct, "The USB Product ID of a semi-compliant interface");
 
 static int uinterface  = -1;
-MODULE_PARM(uinterface,"i");
+module_param(uinterface, int, 0);
 MODULE_PARM_DESC(uinterface, "The Interface number of a semi-compliant interface");
 
 static int ualt        = -1;
-MODULE_PARM(ualt,"i");
+module_param(ualt, int, 0);
 MODULE_PARM_DESC(ualt, "The optional alternative setting of a semi-compliant interface");
 
 static int umin        = -1;
-MODULE_PARM(umin,"i");
+module_param(umin, int, 0);
 MODULE_PARM_DESC(umin, "The input endpoint of a semi-compliant interface");
 
 static int umout       = -1;
-MODULE_PARM(umout,"i");
+module_param(umout, int, 0);
 MODULE_PARM_DESC(umout, "The output endpoint of a semi-compliant interface");
 
 static int ucable      = -1;
-MODULE_PARM(ucable,"i");
+module_param(ucable, int, 0);
 MODULE_PARM_DESC(ucable, "The cable number used for a semi-compliant interface");
 
 /** Note -- the usb_string() returns only Latin-1 characters.
@@ -95,7 +95,7 @@
  * unicode16LE-to-JIS routine is needed to wrap around usb_get_string().
  **/
 static unsigned short ulangid      = 0x0409; /** 0x0411 for Japanese **/
-MODULE_PARM(ulangid,"h");
+module_param(ulangid, ushort, 0);
 MODULE_PARM_DESC(ulangid, "The optional preferred USB Language ID for all devices");
 
 MODULE_AUTHOR("NAGANO Daisuke <breeze.nagano@nifty.ne.jp>");
@@ -817,9 +817,9 @@
 
 	for(;;) {
 		down(&open_sem);
-		for (devs = mididevs.next; devs != &mididevs; devs = devs->next) {
+		list_for_each(devs, &mididevs) {
 			s = list_entry(devs, struct usb_midi_state, mididev);
-			for (mdevs = s->midiDevList.next; mdevs != &s->midiDevList; mdevs = mdevs->next) {
+			list_for_each(mdevs, &s->midiDevList) {
 				m = list_entry(mdevs, struct usb_mididev, list);
 				if ( !((m->dev_midi ^ minor) & ~0xf) )
 					goto device_found;
@@ -2012,7 +2012,7 @@
 	s->usbdev = NULL;
 	usb_set_intfdata (intf, NULL);
 
-	for ( list = s->midiDevList.next; list != &s->midiDevList; list = list->next ) {
+	list_for_each(list, &s->midiDevList) {
 		m = list_entry(list, struct usb_mididev, list);
 		wake_up(&(m->min.ep->wait));
 		wake_up(&(m->mout.ep->wait));
diff -Nru a/drivers/usb/class/usblp.c b/drivers/usb/class/usblp.c
--- a/drivers/usb/class/usblp.c	2004-10-18 14:56:17 -07:00
+++ b/drivers/usb/class/usblp.c	2004-10-18 14:56:17 -07:00
@@ -221,7 +221,7 @@
 static int usblp_cache_device_id_string(struct usblp *usblp);
 
 /* forward reference to make our lives easier */
-extern struct usb_driver usblp_driver;
+static struct usb_driver usblp_driver;
 
 /*
  * Functions for usblp control messages.
@@ -397,10 +397,6 @@
 {
 	info("usblp%d: removed", usblp->minor);
 
-	usb_buffer_free (usblp->dev, USBLP_BUF_SIZE,
-			usblp->writebuf, usblp->writeurb->transfer_dma);
-	usb_buffer_free (usblp->dev, USBLP_BUF_SIZE,
-			usblp->readbuf, usblp->readurb->transfer_dma);
 	kfree (usblp->device_id_string);
 	kfree (usblp->statusbuf);
 	usb_free_urb(usblp->writeurb);
@@ -1129,7 +1125,7 @@
 	/* First two bytes are length in big-endian.
 	 * They count themselves, and we copy them into
 	 * the user's buffer. */
-	length = be16_to_cpu(*((u16 *)usblp->device_id_string));
+	length = be16_to_cpu(*((__be16 *)usblp->device_id_string));
 	if (length < 2)
 		length = 2;
 	else if (length >= USBLP_DEVICE_ID_SIZE)
@@ -1159,6 +1155,10 @@
 	usb_set_intfdata (intf, NULL);
 
 	usblp_unlink_urbs(usblp);
+	usb_buffer_free (usblp->dev, USBLP_BUF_SIZE,
+			usblp->writebuf, usblp->writeurb->transfer_dma);
+	usb_buffer_free (usblp->dev, USBLP_BUF_SIZE,
+			usblp->readbuf, usblp->readurb->transfer_dma);
 
 	if (!usblp->used)
 		usblp_cleanup (usblp);
@@ -1208,6 +1208,6 @@
 
 MODULE_AUTHOR( DRIVER_AUTHOR );
 MODULE_DESCRIPTION( DRIVER_DESC );
-MODULE_PARM(proto_bias, "i");
+module_param(proto_bias, int, S_IRUGO | S_IWUSR);
 MODULE_PARM_DESC(proto_bias, "Favourite protocol number");
 MODULE_LICENSE("GPL");
diff -Nru a/drivers/usb/core/Kconfig b/drivers/usb/core/Kconfig
--- a/drivers/usb/core/Kconfig	2004-10-18 14:57:03 -07:00
+++ b/drivers/usb/core/Kconfig	2004-10-18 14:57:03 -07:00
@@ -60,3 +60,40 @@
 
 	  If you are unsure about this, say N here.
 
+config USB_SUSPEND
+	bool "USB suspend/resume (EXPERIMENTAL)"
+	depends on USB && PM && EXPERIMENTAL
+	help
+	  If you say Y here, you can use driver calls or the sysfs
+	  "power/state" file to suspend or resume individual USB
+	  peripherals.  There are many related features, such as
+	  remote wakeup and driver-specific suspend processing, that
+	  may not yet work as expected.
+
+	  If you are unsure about this, say N here.
+
+
+config USB_OTG
+	bool
+	depends on USB && EXPERIMENTAL
+	select USB_SUSPEND
+	default n
+
+
+config USB_OTG_WHITELIST
+	bool "Rely on OTG Targeted Peripherals List"
+	depends on USB_OTG
+	default y
+	help
+	  If you say Y here, the "otg_whitelist.h" file will be used as a
+	  product whitelist, so USB peripherals not listed there will be
+	  rejected during enumeration.  This behavior is required by the
+	  USB OTG specification for all devices not on your product's
+	  "Targeted Peripherals List".
+
+	  Otherwise, peripherals not listed there will only generate a
+	  warning and enumeration will continue.  That's more like what
+	  normal Linux-USB hosts do (other than the warning), and is
+	  convenient for many stages of product development.
+
+
diff -Nru a/drivers/usb/core/config.c b/drivers/usb/core/config.c
--- a/drivers/usb/core/config.c	2004-10-18 14:55:54 -07:00
+++ b/drivers/usb/core/config.c	2004-10-18 14:55:54 -07:00
@@ -106,7 +106,7 @@
 	return buffer - buffer0 + i;
 }
 
-static void usb_release_interface_cache(struct kref *ref)
+void usb_release_interface_cache(struct kref *ref)
 {
 	struct usb_interface_cache *intfc = ref_to_usb_interface_cache(ref);
 	int j;
@@ -356,7 +356,7 @@
 		if (!intfc)
 			return -ENOMEM;
 		memset(intfc, 0, len);
-		kref_init(&intfc->ref, usb_release_interface_cache);
+		kref_init(&intfc->ref);
 	}
 
 	/* Skip over any Class Specific or Vendor Specific descriptors;
@@ -422,7 +422,8 @@
 
 		for (i = 0; i < cf->desc.bNumInterfaces; i++) {
 			if (cf->intf_cache[i])
-				kref_put(&cf->intf_cache[i]->ref);
+				kref_put(&cf->intf_cache[i]->ref, 
+					  usb_release_interface_cache);
 		}
 	}
 	kfree(dev->config);
diff -Nru a/drivers/usb/core/devices.c b/drivers/usb/core/devices.c
--- a/drivers/usb/core/devices.c	2004-10-18 14:57:04 -07:00
+++ b/drivers/usb/core/devices.c	2004-10-18 14:57:04 -07:00
@@ -283,9 +283,8 @@
 
 /* TBD:
  * 0. TBDs
- * 1. marking active config and ifaces (code lists all, but should mark
+ * 1. marking active interface altsettings (code lists all, but should mark
  *    which ones are active, if any)
- * 2. add <halted> status to each endpoint line
  */
 
 static char *usb_dump_config_descriptor(char *start, char *end, const struct usb_config_descriptor *desc, int active)
@@ -584,7 +583,7 @@
 
 	/* enumerate busses */
 	down (&usb_bus_list_lock);
-	for (buslist = usb_bus_list.next; buslist != &usb_bus_list; buslist = buslist->next) {
+	list_for_each(buslist, &usb_bus_list) {
 		/* print devices for this bus */
 		bus = list_entry(buslist, struct usb_bus, bus_list);
 
diff -Nru a/drivers/usb/core/devio.c b/drivers/usb/core/devio.c
--- a/drivers/usb/core/devio.c	2004-10-18 14:56:31 -07:00
+++ b/drivers/usb/core/devio.c	2004-10-18 14:56:32 -07:00
@@ -72,6 +72,8 @@
 	} while (0)
 
 
+#define	MAX_USBFS_BUFFER_SIZE	16384
+
 static inline int connected (struct usb_device *dev)
 {
 	return dev->state != USB_STATE_NOTATTACHED;
@@ -555,8 +557,10 @@
 		snoop(&dev->dev, "control read: bRequest=%02x bRrequestType=%02x wValue=%04x wIndex=%04x\n", 
 			ctrl.bRequest, ctrl.bRequestType, ctrl.wValue, ctrl.wIndex);
 
+		up(&dev->serialize);
 		i = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), ctrl.bRequest, ctrl.bRequestType,
 				       ctrl.wValue, ctrl.wIndex, tbuf, ctrl.wLength, tmo);
+		down(&dev->serialize);
 		if ((i > 0) && ctrl.wLength) {
 			if (usbfs_snoop) {
 				dev_info(&dev->dev, "control read: data ");
@@ -584,8 +588,10 @@
 				printk ("%02x ", (unsigned char)(tbuf)[j]);
 			printk("\n");
 		}
+		up(&dev->serialize);
 		i = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), ctrl.bRequest, ctrl.bRequestType,
 				       ctrl.wValue, ctrl.wIndex, tbuf, ctrl.wLength, tmo);
+		down(&dev->serialize);
 	}
 	free_page((unsigned long)tbuf);
 	if (i<0) {
@@ -619,6 +625,8 @@
 	if (!usb_maxpacket(dev, pipe, !(bulk.ep & USB_DIR_IN)))
 		return -EINVAL;
 	len1 = bulk.len;
+	if (len1 > MAX_USBFS_BUFFER_SIZE)
+		return -EINVAL;
 	if (!(tbuf = kmalloc(len1, GFP_KERNEL)))
 		return -ENOMEM;
 	tmo = (bulk.timeout * HZ + 999) / 1000;
@@ -627,7 +635,9 @@
 			kfree(tbuf);
 			return -EINVAL;
 		}
+		up(&dev->serialize);
 		i = usb_bulk_msg(dev, pipe, tbuf, len1, &len2, tmo);
+		down(&dev->serialize);
 		if (!i && len2) {
 			if (copy_to_user(bulk.data, tbuf, len2)) {
 				kfree(tbuf);
@@ -641,7 +651,9 @@
 				return -EFAULT;
 			}
 		}
+		up(&dev->serialize);
 		i = usb_bulk_msg(dev, pipe, tbuf, len1, &len2, tmo);
+		down(&dev->serialize);
 	}
 	kfree(tbuf);
 	if (i < 0) {
@@ -849,7 +861,7 @@
 
 	case USBDEVFS_URB_TYPE_BULK:
 		uurb.number_of_packets = 0;
-		if (uurb.buffer_length > 16384)
+		if (uurb.buffer_length > MAX_USBFS_BUFFER_SIZE)
 			return -EINVAL;
 		if (!access_ok((uurb.endpoint & USB_DIR_IN) ? VERIFY_WRITE : VERIFY_READ, uurb.buffer, uurb.buffer_length))
 			return -EFAULT;
@@ -891,7 +903,7 @@
 			interval = 1 << min (15, ep_desc->bInterval - 1);
 		else
 			interval = ep_desc->bInterval;
-		if (uurb.buffer_length > 16384)
+		if (uurb.buffer_length > MAX_USBFS_BUFFER_SIZE)
 			return -EINVAL;
 		if (!access_ok((uurb.endpoint & USB_DIR_IN) ? VERIFY_WRITE : VERIFY_READ, uurb.buffer, uurb.buffer_length))
 			return -EFAULT;
diff -Nru a/drivers/usb/core/hcd-pci.c b/drivers/usb/core/hcd-pci.c
--- a/drivers/usb/core/hcd-pci.c	2004-10-18 14:56:29 -07:00
+++ b/drivers/usb/core/hcd-pci.c	2004-10-18 14:56:29 -07:00
@@ -65,7 +65,7 @@
 {
 	struct hc_driver	*driver;
 	unsigned long		resource, len;
-	void			*base;
+	void __iomem		*base;
 	struct usb_hcd		*hcd;
 	int			retval, region;
 	char			buf [8], *bufp = buf;
@@ -121,7 +121,7 @@
 			dev_dbg (&dev->dev, "no i/o regions available\n");
 			return -EBUSY;
 		}
-		base = (void *) resource;
+		base = (void __iomem *) resource;
 	}
 
 	// driver->reset(), later on, will transfer device from
diff -Nru a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c
--- a/drivers/usb/core/hcd.c	2004-10-18 14:56:33 -07:00
+++ b/drivers/usb/core/hcd.c	2004-10-18 14:56:33 -07:00
@@ -708,6 +708,7 @@
 		bus->busnum = busnum;
 	} else {
 		printk (KERN_ERR "%s: too many buses\n", usbcore_name);
+		up(&usb_bus_list_lock);
 		return -E2BIG;
 	}
 
@@ -790,6 +791,8 @@
 	usb_dev->epmaxpacketin[0] = usb_dev->epmaxpacketout[0] = 64;
 	retval = usb_get_device_descriptor(usb_dev, USB_DT_DEVICE_SIZE);
 	if (retval != sizeof usb_dev->descriptor) {
+		usb_dev->bus->root_hub = NULL;
+		up (&usb_bus_list_lock);
 		dev_dbg (parent_dev, "can't read %s device descriptor %d\n",
 				usb_dev->dev.bus_id, retval);
 		return (retval < 0) ? retval : -EMSGSIZE;
@@ -1311,13 +1314,10 @@
 
 rescan:
 	/* (re)block new requests, as best we can */
-	if (endpoint & USB_DIR_IN) {
-		usb_endpoint_halt (udev, epnum, 0);
+	if (endpoint & USB_DIR_IN)
 		udev->epmaxpacketin [epnum] = 0;
-	} else {
-		usb_endpoint_halt (udev, epnum, 1);
+	else
 		udev->epmaxpacketout [epnum] = 0;
-	}
 
 	/* then kill any current requests */
 	spin_lock (&hcd_data_lock);
@@ -1402,6 +1402,45 @@
 		return hcd->driver->hub_resume (hcd);
 	return 0;
 }
+
+#endif
+
+/*-------------------------------------------------------------------------*/
+
+#ifdef	CONFIG_USB_OTG
+
+/**
+ * usb_bus_start_enum - start immediate enumeration (for OTG)
+ * @bus: the bus (must use hcd framework)
+ * @port: 1-based number of port; usually bus->otg_port
+ * Context: in_interrupt()
+ *
+ * Starts enumeration, with an immediate reset followed later by
+ * khubd identifying and possibly configuring the device.
+ * This is needed by OTG controller drivers, where it helps meet
+ * HNP protocol timing requirements for starting a port reset.
+ */
+int usb_bus_start_enum(struct usb_bus *bus, unsigned port_num)
+{
+	struct usb_hcd		*hcd;
+	int			status = -EOPNOTSUPP;
+
+	/* NOTE: since HNP can't start by grabbing the bus's address0_sem,
+	 * boards with root hubs hooked up to internal devices (instead of
+	 * just the OTG port) may need more attention to resetting...
+	 */
+	hcd = container_of (bus, struct usb_hcd, self);
+	if (port_num && hcd->driver->start_port_reset)
+		status = hcd->driver->start_port_reset(hcd, port_num);
+
+	/* run khubd shortly after (first) root port reset finishes;
+	 * it may issue others, until at least 50 msecs have passed.
+	 */
+	if (status == 0)
+		mod_timer(&hcd->rh_timer, jiffies + msecs_to_jiffies(10));
+	return status;
+}
+EXPORT_SYMBOL (usb_bus_start_enum);
 
 #endif
 
diff -Nru a/drivers/usb/core/hcd.h b/drivers/usb/core/hcd.h
--- a/drivers/usb/core/hcd.h	2004-10-18 14:56:28 -07:00
+++ b/drivers/usb/core/hcd.h	2004-10-18 14:56:28 -07:00
@@ -77,7 +77,7 @@
 	unsigned		can_wakeup:1;	/* hw supports wakeup? */
 	unsigned		remote_wakeup:1;/* sw should use wakeup? */
 	int			irq;		/* irq allocated */
-	void			*regs;		/* device memory/io */
+	void __iomem		*regs;		/* device memory/io */
 
 #ifdef	CONFIG_PCI
 	int			region;		/* pci region for regs */
@@ -212,6 +212,7 @@
 				char *buf, u16 wLength);
 	int		(*hub_suspend)(struct usb_hcd *);
 	int		(*hub_resume)(struct usb_hcd *);
+	int		(*start_port_reset)(struct usb_hcd *, unsigned port_num);
 };
 
 extern void usb_hcd_giveback_urb (struct usb_hcd *hcd, struct urb *urb, struct pt_regs *regs);
@@ -375,8 +376,6 @@
 
 extern int usb_find_interface_driver (struct usb_device *dev,
 	struct usb_interface *interface);
-
-#define usb_endpoint_halt(dev, ep, out) ((dev)->halted[out] |= (1 << (ep)))
 
 #define usb_endpoint_out(ep_dir)	(!((ep_dir) & USB_DIR_IN))
 
diff -Nru a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
--- a/drivers/usb/core/hub.c	2004-10-18 14:56:29 -07:00
+++ b/drivers/usb/core/hub.c	2004-10-18 14:56:29 -07:00
@@ -36,7 +36,7 @@
 #include "hcd.h"
 #include "hub.h"
 
-/* Protect all struct usb_device state members */
+/* Protect struct usb_device state and children members */
 static spinlock_t device_state_lock = SPIN_LOCK_UNLOCKED;
 
 /* Wakes up khubd */
@@ -143,7 +143,7 @@
 	unsigned		changed = 0;
 	int			cursor = -1;
 
-	if (hdev->state != USB_STATE_CONFIGURED)
+	if (hdev->state != USB_STATE_CONFIGURED || hub->quiescing)
 		return;
 
 	for (i = 0; i < hub->descriptor->bNbrPorts; i++) {
@@ -269,6 +269,9 @@
 	spin_unlock(&hub_event_lock);
 
 resubmit:
+	if (hub->quiescing)
+		return;
+
 	if ((status = usb_submit_urb (hub->urb, GFP_ATOMIC)) != 0
 			&& status != -ENODEV && status != -EPERM)
 		dev_err (&hub->intf->dev, "resubmit --> %d\n", status);
@@ -623,6 +626,33 @@
 
 static unsigned highspeed_hubs;
 
+static void hub_quiesce(struct usb_hub *hub)
+{
+	/* stop khubd and related activity */
+	hub->quiescing = 1;
+	usb_kill_urb(hub->urb);
+	if (hub->has_indicators)
+		cancel_delayed_work(&hub->leds);
+	if (hub->has_indicators || hub->tt.hub)
+		flush_scheduled_work();
+}
+
+#ifdef	CONFIG_USB_SUSPEND
+
+static void hub_reactivate(struct usb_hub *hub)
+{
+	int	status;
+
+	hub->quiescing = 0;
+	status = usb_submit_urb(hub->urb, GFP_NOIO);
+	if (status < 0)
+		dev_err(&hub->intf->dev, "reactivate --> %d\n", status);
+	if (hub->has_indicators && blinkenlights)
+		schedule_delayed_work(&hub->leds, LED_CYCLE_PERIOD);
+}
+
+#endif
+
 static void hub_disconnect(struct usb_interface *intf)
 {
 	struct usb_hub *hub = usb_get_intfdata (intf);
@@ -637,22 +667,14 @@
 
 	usb_set_intfdata (intf, NULL);
 
-	if (hub->urb) {
-		usb_kill_urb(hub->urb);
-		usb_free_urb(hub->urb);
-		hub->urb = NULL;
-	}
+	hub_quiesce(hub);
+	usb_free_urb(hub->urb);
+	hub->urb = NULL;
 
 	spin_lock_irq(&hub_event_lock);
 	list_del_init(&hub->event_list);
 	spin_unlock_irq(&hub_event_lock);
 
-	/* assuming we used keventd, it must quiesce too */
-	if (hub->has_indicators)
-		cancel_delayed_work (&hub->leds);
-	if (hub->has_indicators || hub->tt.hub)
-		flush_scheduled_work ();
-
 	if (hub->descriptor) {
 		kfree(hub->descriptor);
 		hub->descriptor = NULL;
@@ -772,6 +794,7 @@
 	}
 }
 
+/* caller has locked the hub and must own the device lock */
 static int hub_reset(struct usb_hub *hub)
 {
 	struct usb_device *hdev = hub->hdev;
@@ -789,7 +812,7 @@
 	else
 		return -1;
 
-	if (usb_reset_device(hdev))
+	if (__usb_reset_device(hdev))
 		return -1;
 
 	hub->urb->dev = hdev;                                                    
@@ -801,6 +824,7 @@
 	return 0;
 }
 
+/* caller has locked the hub */
 /* FIXME!  This routine should be subsumed into hub_reset */
 static void hub_start_disconnect(struct usb_device *hdev)
 {
@@ -832,12 +856,65 @@
 	udev->state = USB_STATE_NOTATTACHED;
 }
 
+/* grab device/port lock, returning index of that port (zero based).
+ * protects the upstream link used by this device from concurrent
+ * tree operations like suspend, resume, reset, and disconnect, which
+ * apply to everything downstream of a given port.
+ */
+static int locktree(struct usb_device *udev)
+{
+	int			t;
+	struct usb_device	*hdev;
+
+	if (!udev)
+		return -ENODEV;
+
+	/* root hub is always the first lock in the series */
+	hdev = udev->parent;
+	if (!hdev) {
+		down(&udev->serialize);
+		return 0;
+	}
+
+	/* on the path from root to us, lock everything from
+	 * top down, dropping parent locks when not needed
+	 *
+	 * NOTE: if disconnect were to ignore the locking, we'd need
+	 * to get extra refcounts to everything since hdev->children
+	 * and udev->parent could be invalidated while we work...
+	 */
+	t = locktree(hdev);
+	if (t < 0)
+		return t;
+	spin_lock_irq(&device_state_lock);
+	for (t = 0; t < hdev->maxchild; t++) {
+		if (hdev->children[t] == udev) {
+			/* everything is fail-fast once disconnect
+			 * processing starts
+			 */
+			if (udev->state == USB_STATE_NOTATTACHED)
+				break;
+
+			/* when everyone grabs locks top->bottom,
+			 * non-overlapping work may be concurrent
+			 */
+			spin_unlock_irq(&device_state_lock);
+			down(&udev->serialize);
+			up(&hdev->serialize);
+			return t;
+		}
+	}
+	spin_unlock_irq(&device_state_lock);
+	up(&hdev->serialize);
+	return -ENODEV;
+}
+
 /**
  * usb_set_device_state - change a device's current state (usbcore-internal)
  * @udev: pointer to device whose state should be changed
  * @new_state: new state value to be stored
  *
- * udev->state is _not_ protected by the udev->serialize semaphore.  This
+ * udev->state is _not_ protected by the device lock.  This
  * is so that devices can be marked as disconnected as soon as possible,
  * without having to wait for the semaphore to be released.  Instead,
  * changes to the state must be protected by the device_state_lock spinlock.
@@ -897,7 +974,7 @@
 
 /**
  * usb_disconnect - disconnect a device (usbcore-internal)
- * @pdev: pointer to device being disconnected
+ * @pdev: pointer to device being disconnected, into a locked hub
  * Context: !in_interrupt ()
  *
  * Something got disconnected. Get rid of it, and all of its children.
@@ -921,7 +998,8 @@
 	}
 
 	/* mark the device as inactive, so any further urb submissions for
-	 * this device will fail.
+	 * this device (and any of its children) will fail immediately.
+	 * this quiesces everyting except pending urbs.
 	 */
 	usb_set_device_state(udev, USB_STATE_NOTATTACHED);
 
@@ -940,6 +1018,7 @@
 
 	/* deallocate hcd/hardware state ... nuking all pending urbs and
 	 * cleaning up all state associated with the current configuration
+	 * so that the hardware is now fully quiesced.
 	 */
 	usb_disable_device(udev, 0);
 
@@ -952,7 +1031,7 @@
 	usbfs_remove_device(udev);
 	usb_remove_sysfs_dev_files(udev);
 
-	/* Avoid races with recursively_mark_NOTATTACHED() */
+	/* Avoid races with recursively_mark_NOTATTACHED() and locktree() */
 	spin_lock_irq(&device_state_lock);
 	*pdev = NULL;
 	spin_unlock_irq(&device_state_lock);
@@ -1016,6 +1095,10 @@
 {}
 #endif
 
+#ifdef	CONFIG_USB_OTG
+#include "otg_whitelist.h"
+#endif
+
 /**
  * usb_new_device - perform initial device setup (usbcore-internal)
  * @udev: newly addressed device (in ADDRESS state)
@@ -1065,6 +1148,79 @@
 		show_string(udev, "SerialNumber",
 				udev->descriptor.iSerialNumber);
 
+#ifdef	CONFIG_USB_OTG
+	/*
+	 * OTG-aware devices on OTG-capable root hubs may be able to use SRP,
+	 * to wake us after we've powered off VBUS; and HNP, switching roles
+	 * "host" to "peripheral".  The OTG descriptor helps figure this out.
+	 */
+	if (!udev->bus->is_b_host
+			&& udev->config
+			&& udev->parent == udev->bus->root_hub) {
+		struct usb_otg_descriptor	*desc = 0;
+		struct usb_bus			*bus = udev->bus;
+
+		/* descriptor may appear anywhere in config */
+		if (__usb_get_extra_descriptor (udev->rawdescriptors[0],
+					udev->config[0].desc.wTotalLength,
+					USB_DT_OTG, (void **) &desc) == 0) {
+			if (desc->bmAttributes & USB_OTG_HNP) {
+				unsigned		port;
+				struct usb_device	*root = udev->parent;
+				
+				for (port = 0; port < root->maxchild; port++) {
+					if (root->children[port] == udev)
+						break;
+				}
+				port++;
+
+				dev_info(&udev->dev,
+					"Dual-Role OTG device on %sHNP port\n",
+					(port == bus->otg_port)
+						? "" : "non-");
+
+				/* enable HNP before suspend, it's simpler */
+				if (port == bus->otg_port)
+					bus->b_hnp_enable = 1;
+				err = usb_control_msg(udev,
+					usb_sndctrlpipe(udev, 0),
+					USB_REQ_SET_FEATURE, 0,
+					bus->b_hnp_enable
+						? USB_DEVICE_B_HNP_ENABLE
+						: USB_DEVICE_A_ALT_HNP_SUPPORT,
+					0, NULL, 0, HZ * USB_CTRL_SET_TIMEOUT);
+				if (err < 0) {
+					/* OTG MESSAGE: report errors here,
+					 * customize to match your product.
+					 */
+					dev_info(&udev->dev,
+						"can't set HNP mode; %d\n",
+						err);
+					bus->b_hnp_enable = 0;
+				}
+			}
+		}
+	}
+
+	if (!is_targeted(udev)) {
+
+		/* Maybe it can talk to us, though we can't talk to it.
+		 * (Includes HNP test device.)
+		 */
+		if (udev->bus->b_hnp_enable || udev->bus->is_b_host) {
+			static int __usb_suspend_device (struct usb_device *,
+						int port, u32 state);
+			err = __usb_suspend_device(udev,
+					udev->bus->otg_port - 1,
+					PM_SUSPEND_MEM);
+			if (err < 0)
+				dev_dbg(&udev->dev, "HNP fail, %d\n", err);
+		}
+		err = -ENODEV;
+		goto fail;
+	}
+#endif
+
 	/* put device-specific files into sysfs */
 	err = device_add (&udev->dev);
 	if (err) {
@@ -1203,6 +1359,7 @@
 		if (status == -ENOTCONN || status == 0) {
 			clear_port_feature(hdev,
 				port + 1, USB_PORT_FEAT_C_RESET);
+			/* FIXME need disconnect() for NOTATTACHED device */
 			usb_set_device_state(udev, status
 					? USB_STATE_NOTATTACHED
 					: USB_STATE_DEFAULT);
@@ -1226,9 +1383,11 @@
 {
 	int ret;
 
-	if (hdev->children[port])
+	if (hdev->children[port]) {
+		/* FIXME need disconnect() for NOTATTACHED device */
 		usb_set_device_state(hdev->children[port],
 				USB_STATE_NOTATTACHED);
+	}
 	ret = clear_port_feature(hdev, port + 1, USB_PORT_FEAT_ENABLE);
 	if (ret)
 		dev_err(hubdev(hdev), "cannot disable port %d (err = %d)\n",
@@ -1239,7 +1398,490 @@
 
 #ifdef	CONFIG_USB_SUSPEND
 
-	/* no USB_SUSPEND yet! */
+/*
+ * Selective port suspend reduces power; most suspended devices draw
+ * less than 500 uA.  It's also used in OTG, along with remote wakeup.
+ * All devices below the suspended port are also suspended.
+ *
+ * Devices leave suspend state when the host wakes them up.  Some devices
+ * also support "remote wakeup", where the device can activate the USB
+ * tree above them to deliver data, such as a keypress or packet.  In
+ * some cases, this wakes the USB host.
+ */
+static int hub_port_suspend(struct usb_device *hdev, int port)
+{
+	int			status;
+	struct usb_device	*udev;
+
+	udev = hdev->children[port - 1];
+	// dev_dbg(hubdev(hdev), "suspend port %d\n", port);
+
+	/* enable remote wakeup when appropriate; this lets the device
+	 * wake up the upstream hub (including maybe the root hub).
+	 *
+	 * NOTE:  OTG devices may issue remote wakeup (or SRP) even when
+	 * we don't explicitly enable it here.
+	 */
+	if (udev->actconfig
+			// && FIXME (remote wakeup enabled on this bus)
+			// ... currently assuming it's always appropriate
+			&& (udev->actconfig->desc.bmAttributes
+				& USB_CONFIG_ATT_WAKEUP) != 0) {
+		status = usb_control_msg(udev, usb_sndctrlpipe(udev, 0),
+				USB_REQ_SET_FEATURE, USB_RECIP_DEVICE,
+				USB_DEVICE_REMOTE_WAKEUP, 0,
+				NULL, 0,
+				USB_CTRL_SET_TIMEOUT);
+		if (status)
+			dev_dbg(&udev->dev,
+				"won't remote wakeup, status %d\n",
+				status);
+	}
+
+	/* see 7.1.7.6 */
+	status = set_port_feature(hdev, port, USB_PORT_FEAT_SUSPEND);
+	if (status) {
+		dev_dbg(hubdev(hdev),
+			"can't suspend port %d, status %d\n",
+			port, status);
+		/* paranoia:  "should not happen" */
+		(void) usb_control_msg(udev, usb_sndctrlpipe(udev, 0),
+				USB_REQ_CLEAR_FEATURE, USB_RECIP_DEVICE,
+				USB_DEVICE_REMOTE_WAKEUP, 0,
+				NULL, 0,
+				USB_CTRL_SET_TIMEOUT);
+	} else {
+		/* device has up to 10 msec to fully suspend */
+		dev_dbg(&udev->dev, "usb suspend\n");
+		udev->state = USB_STATE_SUSPENDED;
+		msleep(10);
+	}
+	return status;
+}
+
+/*
+ * Devices on USB hub ports have only one "suspend" state, corresponding
+ * to ACPI D2 (PM_SUSPEND_MEM), "may cause the device to lose some context".
+ * State transitions include:
+ *
+ *   - suspend, resume ... when the VBUS power link stays live
+ *   - suspend, disconnect ... VBUS lost
+ *
+ * Once VBUS drop breaks the circuit, the port it's using has to go through
+ * normal re-enumeration procedures, starting with enabling VBUS power.
+ * Other than re-initializing the hub (plug/unplug, except for root hubs),
+ * Linux (2.6) currently has NO mechanisms to initiate that:  no khubd
+ * timer, no SRP, no requests through sysfs.
+ */
+static int __usb_suspend_device (struct usb_device *udev, int port, u32 state)
+{
+	int	status;
+
+	if (port < 0)
+		return port;
+
+	/* NOTE:  udev->serialize released on all real returns! */
+
+	if (state <= udev->dev.power.power_state
+			|| state < PM_SUSPEND_MEM
+			|| udev->state == USB_STATE_SUSPENDED
+			|| udev->state == USB_STATE_NOTATTACHED) {
+		up(&udev->serialize);
+		return 0;
+	}
+
+	/* suspend interface drivers; if this is a hub, it
+	 * suspends the child devices
+	 */
+	if (udev->actconfig) {
+		int	i;
+
+		for (i = 0; i < udev->actconfig->desc.bNumInterfaces; i++) {
+			struct usb_interface	*intf;
+			struct usb_driver	*driver;
+
+			intf = udev->actconfig->interface[i];
+			if (state <= intf->dev.power.power_state)
+				continue;
+			if (!intf->dev.driver)
+				continue;
+			driver = to_usb_driver(intf->dev.driver);
+
+			if (driver->suspend) {
+				status = driver->suspend(intf, state);
+				if (intf->dev.power.power_state != state
+						|| status)
+					dev_err(&intf->dev,
+						"suspend %d fail, code %d\n",
+						state, status);
+			}
+
+			/* only drivers with suspend() can ever resume();
+			 * and after power loss, even they won't.
+			 * bus_rescan_devices() can rebind drivers later.
+			 *
+			 * FIXME the PM core self-deadlocks when unbinding
+			 * drivers during suspend/resume ... everything grabs
+			 * dpm_sem (not a spinlock, ugh).  we want to unbind,
+			 * since we know every driver's probe/disconnect works
+			 * even for drivers that can't suspend.
+			 */
+			if (!driver->suspend || state > PM_SUSPEND_MEM) {
+#if 1
+				dev_warn(&intf->dev, "resume is unsafe!\n");
+#else
+				down_write(&usb_bus_type.rwsem);
+				device_release_driver(&intf->dev);
+				up_write(&usb_bus_type.rwsem);
+#endif
+			}
+		}
+	}
+
+	/*
+	 * FIXME this needs port power off call paths too, to help force
+	 * USB into the "generic" PM model.  At least for devices on
+	 * ports that aren't using ganged switching (usually root hubs).
+	 *
+	 * NOTE: SRP-capable links should adopt more aggressive poweroff
+	 * policies (when HNP doesn't apply) once we have mechanisms to
+	 * turn power back on!  (Likely not before 2.7...)
+	 */
+	if (state > PM_SUSPEND_MEM) {
+		dev_warn(&udev->dev, "no poweroff yet, suspending instead\n");
+		state = PM_SUSPEND_MEM;
+	}
+
+	/* "global suspend" of the HC-to-USB interface (root hub), or
+	 * "selective suspend" of just one hub-device link.
+	 */
+	if (!udev->parent) {
+		struct usb_bus	*bus = udev->bus;
+		if (bus && bus->op->hub_suspend)
+			status = bus->op->hub_suspend (bus);
+		else
+			status = -EOPNOTSUPP;
+	} else
+		status = hub_port_suspend(udev->parent, port + 1);
+
+	if (status == 0)
+		udev->dev.power.power_state = state;
+	up(&udev->serialize);
+	return status;
+}
+
+/**
+ * usb_suspend_device - suspend a usb device
+ * @udev: device that's no longer in active use
+ * @state: PM_SUSPEND_MEM to suspend
+ * Context: must be able to sleep; device not locked
+ *
+ * Suspends a USB device that isn't in active use, conserving power.
+ * Devices may wake out of a suspend, if anything important happens,
+ * using the remote wakeup mechanism.  They may also be taken out of
+ * suspend by the host, using usb_resume_device().  It's also routine
+ * to disconnect devices while they are suspended.
+ *
+ * Suspending OTG devices may trigger HNP, if that's been enabled
+ * between a pair of dual-role devices.  That will change roles, such
+ * as from A-Host to A-Peripheral or from B-Host back to B-Peripheral.
+ *
+ * Returns 0 on success, else negative errno.
+ */
+int usb_suspend_device(struct usb_device *udev, u32 state)
+{
+	return __usb_suspend_device(udev, locktree(udev), state);
+}
+
+/*
+ * hardware resume signaling is finished, either because of selective
+ * resume (by host) or remote wakeup (by device) ... now see what changed
+ * in the tree that's rooted at this device.
+ */
+static int finish_port_resume(struct usb_device *udev)
+{
+	int	status;
+	u16	devstatus;
+
+	/* caller owns udev->serialize */
+	dev_dbg(&udev->dev, "usb resume\n");
+	udev->dev.power.power_state = PM_SUSPEND_ON;
+
+	/* usb ch9 identifies four variants of SUSPENDED, based on what
+	 * state the device resumes to.  Linux currently won't see the
+	 * first two on the host side; they'd be inside hub_port_init()
+	 * during many timeouts, but khubd can't suspend until later.
+	 */
+	udev->state = udev->actconfig
+		? USB_STATE_CONFIGURED
+		: USB_STATE_ADDRESS;
+
+ 	/* 10.5.4.5 says be sure devices in the tree are still there.
+ 	 * For now let's assume the device didn't go crazy on resume,
+	 * and device drivers will know about any resume quirks.
+	 */
+	status = usb_get_status(udev, USB_RECIP_DEVICE, 0, &devstatus);
+	if (status < 0)
+		dev_dbg(&udev->dev,
+			"gone after usb resume? status %d\n",
+			status);
+	else if (udev->actconfig) {
+		unsigned	i;
+
+		le16_to_cpus(&devstatus);
+		if (devstatus & (1 << USB_DEVICE_REMOTE_WAKEUP)) {
+			status = usb_control_msg(udev,
+					usb_sndctrlpipe(udev, 0),
+					USB_REQ_CLEAR_FEATURE,
+						USB_RECIP_DEVICE,
+					USB_DEVICE_REMOTE_WAKEUP, 0,
+					NULL, 0,
+					USB_CTRL_SET_TIMEOUT);
+			if (status) {
+				dev_dbg(&udev->dev, "disable remote "
+					"wakeup, status %d\n", status);
+				status = 0;
+			}
+		}
+
+		/* resume interface drivers; if this is a hub, it
+		 * resumes the child devices
+		 */
+		for (i = 0; i < udev->actconfig->desc.bNumInterfaces; i++) {
+			struct usb_interface	*intf;
+			struct usb_driver	*driver;
+
+			intf = udev->actconfig->interface[i];
+			if (intf->dev.power.power_state == PM_SUSPEND_ON)
+				continue;
+			if (!intf->dev.driver) {
+				/* FIXME maybe force to alt 0 */
+				continue;
+			}
+			driver = to_usb_driver(intf->dev.driver);
+
+			/* bus_rescan_devices() may rebind drivers */
+			if (!driver->resume)
+				continue;
+
+			/* can we do better than just logging errors? */
+			status = driver->resume(intf);
+			if (intf->dev.power.power_state != PM_SUSPEND_ON
+					|| status)
+				dev_dbg(&intf->dev,
+					"resume fail, state %d code %d\n",
+					intf->dev.power.power_state, status);
+		}
+		status = 0;
+
+	} else if (udev->devnum <= 0) {
+		dev_dbg(&udev->dev, "bogus resume!\n");
+		status = -EINVAL;
+	}
+	return status;
+}
+
+static int
+hub_port_resume(struct usb_device *hdev, int port)
+{
+	int			status;
+	struct usb_device	*udev;
+
+	udev = hdev->children[port - 1];
+	// dev_dbg(hubdev(hdev), "resume port %d\n", port);
+
+	/* see 7.1.7.7; affects power usage, but not budgeting */
+	status = clear_port_feature(hdev, port, USB_PORT_FEAT_SUSPEND);
+	if (status) {
+		dev_dbg(&hdev->actconfig->interface[0]->dev,
+			"can't resume port %d, status %d\n",
+			port, status);
+	} else {
+		u16		devstatus;
+		u16		portchange;
+
+		/* drive resume for at least 20 msec */
+		dev_dbg(&udev->dev, "RESUME\n");
+		msleep(25);
+
+#define LIVE_FLAGS	( USB_PORT_STAT_POWER \
+			| USB_PORT_STAT_ENABLE \
+			| USB_PORT_STAT_CONNECTION)
+
+		/* Virtual root hubs can trigger on GET_PORT_STATUS to
+		 * stop resume signaling.  Then finish the resume
+		 * sequence.
+		 */
+		devstatus = portchange = 0;
+		status = hub_port_status(hdev, port - 1,
+				&devstatus, &portchange);
+		if (status < 0
+				|| (devstatus & LIVE_FLAGS) != LIVE_FLAGS
+				|| (devstatus & USB_PORT_STAT_SUSPEND) != 0
+				) {
+			dev_dbg(&hdev->actconfig->interface[0]->dev,
+				"port %d status %04x.%04x after resume, %d\n",
+				port, portchange, devstatus, status);
+		} else {
+			/* TRSMRCY = 10 msec */
+			msleep(10);
+			status = finish_port_resume(udev);
+		}
+	}
+	if (status < 0)
+		status = hub_port_disable(hdev, port);
+
+	return status;
+}
+
+static int hub_resume (struct usb_interface *intf);
+
+/**
+ * usb_resume_device - re-activate a suspended usb device
+ * @udev: device to re-activate
+ * Context: must be able to sleep; device not locked
+ *
+ * This will re-activate the suspended device, increasing power usage
+ * while letting drivers communicate again with its endpoints.
+ * USB resume explicitly guarantees that the power session between
+ * the host and the device is the same as it was when the device
+ * suspended.
+ *
+ * Returns 0 on success, else negative errno.
+ */
+int usb_resume_device(struct usb_device *udev)
+{
+	int			port, status;
+
+	port = locktree(udev);
+	if (port < 0)
+		return port;
+
+	/* "global resume" of the HC-to-USB interface (root hub), or
+	 * selective resume of one hub-to-device port
+	 */
+	if (!udev->parent) {
+		struct usb_bus	*bus = udev->bus;
+		if (bus && bus->op->hub_resume)
+			status = bus->op->hub_resume (bus);
+		else
+			status = -EOPNOTSUPP;
+		if (status == 0) {
+			/* TRSMRCY = 10 msec */
+			msleep(10);
+			status = hub_resume (bus->root_hub
+					->actconfig->interface[0]);
+		}
+	} else if (udev->state == USB_STATE_SUSPENDED) {
+		status = hub_port_resume(udev->parent, port + 1);
+	} else {
+		status = 0;
+		udev->dev.power.power_state = PM_SUSPEND_ON;
+	}
+	if (status < 0) {
+		dev_dbg(&udev->dev, "can't resume, status %d\n",
+			status);
+	}
+
+	up(&udev->serialize);
+
+	/* rebind drivers that had no suspend() */
+	bus_rescan_devices(&usb_bus_type);
+
+	return status;
+}
+
+static int remote_wakeup(struct usb_device *udev)
+{
+	int	status = 0;
+
+	/* don't repeat RESUME sequence if this device
+	 * was already woken up by some other task
+	 */
+	down(&udev->serialize);
+	if (udev->state == USB_STATE_SUSPENDED) {
+		dev_dbg(&udev->dev, "RESUME (wakeup)\n");
+		/* TRSMRCY = 10 msec */
+		msleep(10);
+		status = finish_port_resume(udev);
+	}
+	up(&udev->serialize);
+	return status;
+}
+
+static int hub_suspend(struct usb_interface *intf, u32 state)
+{
+	struct usb_hub		*hub = usb_get_intfdata (intf);
+	struct usb_device	*hdev = hub->hdev;
+	unsigned		port;
+	int			status;
+
+	/* stop khubd and related activity */
+	hub_quiesce(hub);
+
+	/* then suspend every port */
+	for (port = 0; port < hdev->maxchild; port++) {
+		struct usb_device	*udev;
+
+		udev = hdev->children [port];
+		if (!udev)
+			continue;
+		down(&udev->serialize);
+		status = __usb_suspend_device(udev, port, state);
+		if (status < 0)
+			dev_dbg(&intf->dev, "suspend port %d --> %d\n",
+				port, status);
+	}
+
+	intf->dev.power.power_state = state;
+	return 0;
+}
+
+static int hub_resume(struct usb_interface *intf)
+{
+	struct usb_device	*hdev = interface_to_usbdev(intf);
+	struct usb_hub		*hub = usb_get_intfdata (intf);
+	unsigned		port;
+	int			status;
+
+	for (port = 0; port < hdev->maxchild; port++) {
+		struct usb_device	*udev;
+		u16			portstat, portchange;
+
+		udev = hdev->children [port];
+		status = hub_port_status(hdev, port, &portstat, &portchange);
+		if (status == 0) {
+			if (portchange & USB_PORT_STAT_C_SUSPEND) {
+				clear_port_feature(hdev, port + 1,
+					USB_PORT_FEAT_C_SUSPEND);
+				portchange &= ~USB_PORT_STAT_C_SUSPEND;
+			}
+
+			/* let khubd handle disconnects etc */
+			if (portchange)
+				continue;
+		}
+
+		if (!udev)
+			continue;
+		down (&udev->serialize);
+		if (portstat & USB_PORT_STAT_SUSPEND)
+			status = hub_port_resume(hdev, port + 1);
+		else {
+			status = finish_port_resume(udev);
+			if (status < 0)
+				status = hub_port_disable(hdev, port);
+			if (status < 0)
+				dev_dbg(&intf->dev, "resume port %d --> %d\n",
+					port, status);
+		}
+		up(&udev->serialize);
+	}
+	intf->dev.power.power_state = PM_SUSPEND_ON;
+
+	hub_reactivate(hub);
+	return 0;
+}
 
 #else	/* !CONFIG_USB_SUSPEND */
 
@@ -1369,6 +2011,10 @@
 			hdev->bus->b_hnp_enable = 0;
 	}
 
+	retval = clear_port_feature(hdev, port, USB_PORT_FEAT_SUSPEND);
+	if (retval < 0 && retval != -EPIPE)
+		dev_dbg(&udev->dev, "can't clear suspend; %d\n", retval);
+
 	/* Some low speed devices have problems with the quick delay, so */
 	/*  be a bit pessimistic with those devices. RHbug #23670 */
 	if (oldspeed == USB_SPEED_LOW)
@@ -1479,8 +2125,6 @@
 				!= udev->descriptor.bMaxPacketSize0)) {
 		usb_disable_endpoint(udev, 0 + USB_DIR_IN);
 		usb_disable_endpoint(udev, 0 + USB_DIR_OUT);
-		usb_endpoint_running(udev, 0, 1);
-		usb_endpoint_running(udev, 0, 0);
 		udev->epmaxpacketin [0] = udev->descriptor.bMaxPacketSize0;
 		udev->epmaxpacketout[0] = udev->descriptor.bMaxPacketSize0;
 	}
@@ -1574,6 +2218,7 @@
  *	a port enable-change occurs (often caused by EMI);
  *	usb_reset_device() encounters changed descriptors (as from
  *		a firmware download)
+ * caller already locked the hub
  */
 static void hub_port_connect_change(struct usb_hub *hub, int port,
 					u16 portstatus, u16 portchange)
@@ -1596,6 +2241,12 @@
 		usb_disconnect(&hdev->children[port]);
 	clear_bit(port, hub->change_bits);
 
+#ifdef	CONFIG_USB_OTG
+	/* during HNP, don't repeat the debounce */
+	if (hdev->bus->is_b_host)
+		portchange &= ~USB_PORT_STAT_C_CONNECTION;
+#endif
+
 	if (portchange & USB_PORT_STAT_C_CONNECTION) {
 		status = hub_port_debounce(hdev, port);
 		if (status < 0) {
@@ -1780,7 +2431,8 @@
 
 		/* Lock the device, then check to see if we were
 		 * disconnected while waiting for the lock to succeed. */
-		down(&hdev->serialize);
+		if (locktree(hdev) < 0)
+			break;
 		if (hdev->state != USB_STATE_CONFIGURED ||
 				!hdev->actconfig ||
 				hub != usb_get_intfdata(
@@ -2034,7 +2686,7 @@
 }
 
 /**
- * usb_reset_devce - perform a USB port reset to reinitialize a device
+ * usb_reset_device - perform a USB port reset to reinitialize a device
  * @udev: device to reset (not in SUSPENDED or NOTATTACHED state)
  *
  * WARNING - don't reset any device unless drivers for all of its
@@ -2123,7 +2775,7 @@
 		struct usb_interface *intf = udev->actconfig->interface[i];
 		struct usb_interface_descriptor *desc;
 
-		/* set_interface resets host side toggle and halt status even
+		/* set_interface resets host side toggle even
 		 * for altsetting zero.  the interface may have no driver.
 		 */
 		desc = &intf->cur_altsetting->desc;
diff -Nru a/drivers/usb/core/hub.h b/drivers/usb/core/hub.h
--- a/drivers/usb/core/hub.h	2004-10-18 14:55:55 -07:00
+++ b/drivers/usb/core/hub.h	2004-10-18 14:55:55 -07:00
@@ -60,8 +60,8 @@
  * See USB 2.0 spec Table 11-19 and Table 11-20
  */
 struct usb_port_status {
-	__u16 wPortStatus;
-	__u16 wPortChange;	
+	__le16 wPortStatus;
+	__le16 wPortChange;	
 } __attribute__ ((packed));
 
 /* 
@@ -103,8 +103,8 @@
 #define HUB_CHAR_PORTIND        0x0080 /* D7       */
 
 struct usb_hub_status {
-	__u16 wHubStatus;
-	__u16 wHubChange;
+	__le16 wHubStatus;
+	__le16 wHubChange;
 } __attribute__ ((packed));
 
 /*
@@ -190,8 +190,8 @@
 	struct usb_device	*hdev;
 	struct urb		*urb;		/* for interrupt polling pipe */
 
-	/* buffer for urb ... 1 bit each for hub and children, rounded up */
-	char			(*buffer)[(USB_MAXCHILDREN + 1 + 7) / 8];
+	/* buffer for urb ... with extra space in case of babble */
+	char			(*buffer)[8];
 	dma_addr_t		buffer_dma;	/* DMA address for buffer */
 	union {
 		struct usb_hub_status	hub;
@@ -213,6 +213,8 @@
 	struct usb_tt		tt;		/* Transaction Translator */
 
 	u8			power_budget;	/* in 2mA units; or zero */
+
+	unsigned		quiescing:1;
 
 	unsigned		has_indicators:1;
 	enum hub_led_mode	indicator[USB_MAXCHILDREN];
diff -Nru a/drivers/usb/core/inode.c b/drivers/usb/core/inode.c
--- a/drivers/usb/core/inode.c	2004-10-18 14:55:54 -07:00
+++ b/drivers/usb/core/inode.c	2004-10-18 14:55:54 -07:00
@@ -345,30 +345,13 @@
 	return 0;
 }
 
-static void d_unhash(struct dentry *dentry)
-{
-	dget(dentry);
-	spin_lock(&dcache_lock);
-	switch (atomic_read(&dentry->d_count)) {
-	default:
-		spin_unlock(&dcache_lock);
-		shrink_dcache_parent(dentry);
-		spin_lock(&dcache_lock);
-		if (atomic_read(&dentry->d_count) != 2)
-			break;
-	case 2:
-		__d_drop(dentry);
-	}
-	spin_unlock(&dcache_lock);
-}
-
 static int usbfs_rmdir(struct inode *dir, struct dentry *dentry)
 {
 	int error = -ENOTEMPTY;
 	struct inode * inode = dentry->d_inode;
 
 	down(&inode->i_sem);
-	d_unhash(dentry);
+	dentry_unhash(dentry);
 	if (usbfs_empty(dentry)) {
 		dentry->d_inode->i_nlink -= 2;
 		dput(dentry);
diff -Nru a/drivers/usb/core/message.c b/drivers/usb/core/message.c
--- a/drivers/usb/core/message.c	2004-10-18 14:56:20 -07:00
+++ b/drivers/usb/core/message.c	2004-10-18 14:56:20 -07:00
@@ -248,7 +248,7 @@
 		 * unlink pending urbs so they won't rx/tx bad data.
 		 */
 		for (i = 0, found = 0; i < io->entries; i++) {
-			if (!io->urbs [i])
+			if (!io->urbs [i] || !io->urbs [i]->dev)
 				continue;
 			if (found) {
 				status = usb_unlink_urb (io->urbs [i]);
@@ -337,7 +337,7 @@
 	if (io->entries <= 0)
 		return io->entries;
 
-	io->count = 0;
+	io->count = io->entries;
 	io->urbs = kmalloc (io->entries * sizeof *io->urbs, mem_flags);
 	if (!io->urbs)
 		goto nomem;
@@ -347,7 +347,7 @@
 	if (usb_pipein (pipe))
 		urb_flags |= URB_SHORT_NOT_OK;
 
-	for (i = 0; i < io->entries; i++, io->count = i) {
+	for (i = 0; i < io->entries; i++) {
 		unsigned		len;
 
 		io->urbs [i] = usb_alloc_urb (0, mem_flags);
@@ -477,24 +477,19 @@
 
 			/* fail any uncompleted urbs */
 		default:
-			spin_lock_irq (&io->lock);
-			io->count -= entries - i;
-			if (io->status == -EINPROGRESS)
-				io->status = retval;
-			if (io->count == 0)
-				complete (&io->complete);
-			spin_unlock_irq (&io->lock);
-
-			io->urbs[i]->dev = NULL;
+			io->urbs [i]->dev = NULL;
 			io->urbs [i]->status = retval;
 			dev_dbg (&io->dev->dev, "%s, submit --> %d\n",
 				__FUNCTION__, retval);
 			usb_sg_cancel (io);
 		}
 		spin_lock_irq (&io->lock);
-		if (retval && io->status == -ECONNRESET)
+		if (retval && (io->status == 0 || io->status == -ECONNRESET))
 			io->status = retval;
 	}
+	io->count -= entries - i;
+	if (io->count == 0)
+		complete (&io->complete);
 	spin_unlock_irq (&io->lock);
 
 	/* OK, yes, this could be packaged as non-blocking.
@@ -577,8 +572,13 @@
 				USB_REQ_GET_DESCRIPTOR, USB_DIR_IN,
 				(type << 8) + index, 0, buf, size,
 				HZ * USB_CTRL_GET_TIMEOUT);
-		if (!(result == 0 || result == -EPIPE))
-			break;
+		if (result == 0 || result == -EPIPE)
+			continue;
+		if (result > 1 && ((u8 *)buf)[1] != type) {
+			result = -EPROTO;
+			continue;
+		}
+		break;
 	}
 	return result;
 }
@@ -854,9 +854,8 @@
 	 * the copy in usb-storage, for as long as we need two copies.
 	 */
 
-	/* toggle was reset by the clear, then ep was reactivated */
+	/* toggle was reset by the clear */
 	usb_settoggle(dev, usb_pipeendpoint(pipe), usb_pipeout(pipe), 0);
-	usb_endpoint_running(dev, usb_pipeendpoint(pipe), usb_pipeout(pipe));
 
 	return 0;
 }
@@ -870,9 +869,8 @@
  * Deallocates hcd/hardware state for this endpoint ... and nukes all
  * pending urbs.
  *
- * If the HCD hasn't registered a disable() function, this marks the
- * endpoint as halted and sets its maxpacket size to 0 to prevent
- * further submissions.
+ * If the HCD hasn't registered a disable() function, this sets the
+ * endpoint's maxpacket size to 0 to prevent further submissions.
  */
 void usb_disable_endpoint(struct usb_device *dev, unsigned int epaddr)
 {
@@ -881,13 +879,10 @@
 	else {
 		unsigned int epnum = epaddr & USB_ENDPOINT_NUMBER_MASK;
 
-		if (usb_endpoint_out(epaddr)) {
-			usb_endpoint_halt(dev, epnum, 1);
+		if (usb_endpoint_out(epaddr))
 			dev->epmaxpacketout[epnum] = 0;
-		} else {
-			usb_endpoint_halt(dev, epnum, 0);
+		else
 			dev->epmaxpacketin[epnum] = 0;
-		}
 	}
 }
 
@@ -930,7 +925,6 @@
 		usb_disable_endpoint(dev, i + USB_DIR_IN);
 	}
 	dev->toggle[0] = dev->toggle[1] = 0;
-	dev->halted[0] = dev->halted[1] = 0;
 
 	/* getting rid of interfaces will disconnect
 	 * any drivers bound to them (a key side effect)
@@ -966,9 +960,8 @@
  * @dev: the device whose interface is being enabled
  * @epd: pointer to the endpoint descriptor
  *
- * Marks the endpoint as running, resets its toggle, and stores
- * its maxpacket value.  For control endpoints, both the input
- * and output sides are handled.
+ * Resets the endpoint toggle and stores its maxpacket value.
+ * For control endpoints, both the input and output sides are handled.
  */
 void usb_enable_endpoint(struct usb_device *dev,
 		struct usb_endpoint_descriptor *epd)
@@ -980,12 +973,10 @@
 				USB_ENDPOINT_XFER_CONTROL);
 
 	if (usb_endpoint_out(epaddr) || is_control) {
-		usb_endpoint_running(dev, epnum, 1);
 		usb_settoggle(dev, epnum, 1, 0);
 		dev->epmaxpacketout[epnum] = maxsize;
 	}
 	if (!usb_endpoint_out(epaddr) || is_control) {
-		usb_endpoint_running(dev, epnum, 0);
 		usb_settoggle(dev, epnum, 0, 0);
 		dev->epmaxpacketin[epnum] = maxsize;
 	}
@@ -1048,6 +1039,9 @@
 	int ret;
 	int manual = 0;
 
+	if (dev->state == USB_STATE_SUSPENDED)
+		return -EHOSTUNREACH;
+
 	iface = usb_ifnum_to_if(dev, interface);
 	if (!iface) {
 		dev_dbg(&dev->dev, "selecting invalid interface %d\n",
@@ -1145,6 +1139,9 @@
 	int			i, retval;
 	struct usb_host_config	*config;
 
+	if (dev->state == USB_STATE_SUSPENDED)
+		return -EHOSTUNREACH;
+
 	/* caller must own dev->serialize (config won't change)
 	 * and the usb bus readlock (so driver bindings are stable);
 	 * so calls during probe() are fine
@@ -1166,7 +1163,6 @@
 	}
 
 	dev->toggle[0] = dev->toggle[1] = 0;
-	dev->halted[0] = dev->halted[1] = 0;
 
 	/* re-init hc/hcd interface/endpoint state */
 	for (i = 0; i < config->desc.bNumInterfaces; i++) {
@@ -1195,7 +1191,7 @@
 	struct usb_interface_cache *intfc =
 			altsetting_to_usb_interface_cache(intf->altsetting);
 
-	kref_put(&intfc->ref);
+	kref_put(&intfc->ref, usb_release_interface_cache);
 	kfree(intf);
 }
 
@@ -1257,6 +1253,9 @@
 	 */
 	if (cp && configuration == 0)
 		dev_warn(&dev->dev, "config 0 descriptor??\n");
+
+	if (dev->state == USB_STATE_SUSPENDED)
+		return -EHOSTUNREACH;
 
 	/* Allocate memory for new interfaces before doing anything else,
 	 * so that if we run out then nothing will have changed. */
diff -Nru a/drivers/usb/core/otg_whitelist.h b/drivers/usb/core/otg_whitelist.h
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/drivers/usb/core/otg_whitelist.h	2004-10-18 14:57:24 -07:00
@@ -0,0 +1,112 @@
+/*
+ * drivers/usb/core/otg_whitelist.h
+ *
+ * Copyright (C) 2004 Texas Instruments
+ *
+ * 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 OTG Whitelist is the OTG "Targeted Peripheral List".  It should
+ * mostly use of USB_DEVICE() or USB_DEVICE_VER() entries..
+ *
+ * YOU _SHOULD_ CHANGE THIS LIST TO MATCH YOUR PRODUCT AND ITS TESTING!
+ */ 
+
+static struct usb_device_id whitelist_table [] = {
+
+/* hubs are optional in OTG, but very handy ... */
+{ USB_DEVICE_INFO(USB_CLASS_HUB, 0, 0), },
+{ USB_DEVICE_INFO(USB_CLASS_HUB, 0, 1), },
+
+#ifdef	CONFIG_USB_PRINTER		/* ignoring nonstatic linkage! */
+/* FIXME actually, printers are NOT supposed to use device classes;
+ * they're supposed to use interface classes...
+ */
+{ USB_DEVICE_INFO(7, 1, 1) },
+{ USB_DEVICE_INFO(7, 1, 2) },
+{ USB_DEVICE_INFO(7, 1, 3) },
+#endif
+
+#ifdef	CONFIG_USB_CDCETHER
+/* Linux-USB CDC Ethernet gadget */
+{ USB_DEVICE(0x0525, 0xa4a1), },
+/* Linux-USB CDC Ethernet + RNDIS gadget */
+{ USB_DEVICE(0x0525, 0xa4a2), },
+#endif
+
+#if	defined(CONFIG_USB_TEST) || defined(CONFIG_USB_TEST_MODULE)
+/* gadget zero, for testing */
+{ USB_DEVICE(0x0525, 0xa4a0), },
+#endif
+
+{ }	/* Terminating entry */
+};
+
+static int is_targeted(struct usb_device *dev)
+{
+	struct usb_device_id	*id = whitelist_table;
+
+	/* possible in developer configs only! */
+	if (!dev->bus->otg_port)
+		return 1;
+
+	/* HNP test device is _never_ targeted (see OTG spec 6.6.6) */
+	if (dev->descriptor.idVendor == 0x1a0a
+			&& dev->descriptor.idProduct == 0xbadd)
+		return 0;
+
+	/* NOTE: can't use usb_match_id() since interface caches
+	 * aren't set up yet. this is cut/paste from that code.
+	 */
+	for (id = whitelist_table; id->match_flags; id++) {
+		if ((id->match_flags & USB_DEVICE_ID_MATCH_VENDOR) &&
+		    id->idVendor != dev->descriptor.idVendor)
+			continue;
+
+		if ((id->match_flags & USB_DEVICE_ID_MATCH_PRODUCT) &&
+		    id->idProduct != dev->descriptor.idProduct)
+			continue;
+
+		/* No need to test id->bcdDevice_lo != 0, since 0 is never
+		   greater than any unsigned number. */
+		if ((id->match_flags & USB_DEVICE_ID_MATCH_DEV_LO) &&
+		    (id->bcdDevice_lo > dev->descriptor.bcdDevice))
+			continue;
+
+		if ((id->match_flags & USB_DEVICE_ID_MATCH_DEV_HI) &&
+		    (id->bcdDevice_hi < dev->descriptor.bcdDevice))
+			continue;
+
+		if ((id->match_flags & USB_DEVICE_ID_MATCH_DEV_CLASS) &&
+		    (id->bDeviceClass != dev->descriptor.bDeviceClass))
+			continue;
+
+		if ((id->match_flags & USB_DEVICE_ID_MATCH_DEV_SUBCLASS) &&
+		    (id->bDeviceSubClass!= dev->descriptor.bDeviceSubClass))
+			continue;
+
+		if ((id->match_flags & USB_DEVICE_ID_MATCH_DEV_PROTOCOL) &&
+		    (id->bDeviceProtocol != dev->descriptor.bDeviceProtocol))
+			continue;
+
+		return 1;
+	}
+
+	/* add other match criteria here ... */
+
+
+	/* OTG MESSAGE: report errors here, customize to match your product */
+	dev_err(&dev->dev, "device v%04x p%04x is not supported\n",
+			dev->descriptor.idVendor,
+			dev->descriptor.idProduct);
+#ifdef	CONFIG_USB_OTG_WHITELIST
+	return 0;
+#else
+	return 1;
+#endif
+}
+
diff -Nru a/drivers/usb/core/urb.c b/drivers/usb/core/urb.c
--- a/drivers/usb/core/urb.c	2004-10-18 14:56:33 -07:00
+++ b/drivers/usb/core/urb.c	2004-10-18 14:56:33 -07:00
@@ -39,7 +39,7 @@
 {
 	if (urb) {
 		memset(urb, 0, sizeof(*urb));
-		kref_init(&urb->kref, urb_destroy);
+		kref_init(&urb->kref);
 		spin_lock_init(&urb->lock);
 	}
 }
@@ -88,7 +88,7 @@
 void usb_free_urb(struct urb *urb)
 {
 	if (urb)
-		kref_put(&urb->kref);
+		kref_put(&urb->kref, urb_destroy);
 }
 
 /**
@@ -255,13 +255,6 @@
 
 	if (!usb_pipecontrol (pipe) && dev->state < USB_STATE_CONFIGURED)
 		return -ENODEV;
-
-	/* (actually HCDs may need to duplicate this, endpoint might yet
-	 * stall due to queued bulk/intr transactions that complete after
-	 * we check)
-	 */
-	if (usb_endpoint_halted (dev, usb_pipeendpoint (pipe), is_out))
-		return -EPIPE;
 
 	/* FIXME there should be a sharable lock protecting us against
 	 * config/altsetting changes and disconnects, kicking in here.
diff -Nru a/drivers/usb/core/usb.c b/drivers/usb/core/usb.c
--- a/drivers/usb/core/usb.c	2004-10-18 14:56:32 -07:00
+++ b/drivers/usb/core/usb.c	2004-10-18 14:56:32 -07:00
@@ -93,6 +93,8 @@
 
 	if (!driver->probe)
 		return error;
+	if (interface_to_usbdev(intf)->state == USB_STATE_SUSPENDED)
+		return -EHOSTUNREACH;
 
 	id = usb_match_id (intf, driver->id_table);
 	if (id) {
diff -Nru a/drivers/usb/core/usb.h b/drivers/usb/core/usb.h
--- a/drivers/usb/core/usb.h	2004-10-18 14:56:17 -07:00
+++ b/drivers/usb/core/usb.h	2004-10-18 14:56:17 -07:00
@@ -10,6 +10,7 @@
 extern void usb_disable_endpoint (struct usb_device *dev, unsigned int epaddr);
 extern void usb_disable_interface (struct usb_device *dev,
 		struct usb_interface *intf);
+extern void usb_release_interface_cache(struct kref *ref);
 extern void usb_disable_device (struct usb_device *dev, int skip_ep0);
 
 extern void usb_enable_endpoint (struct usb_device *dev,
diff -Nru a/drivers/usb/gadget/Kconfig b/drivers/usb/gadget/Kconfig
--- a/drivers/usb/gadget/Kconfig	2004-10-18 14:56:28 -07:00
+++ b/drivers/usb/gadget/Kconfig	2004-10-18 14:56:28 -07:00
@@ -135,6 +135,18 @@
 	depends on USB_GADGET_SA1100
 	default USB_GADGET
 
+config USB_GADGET_LH7A40X
+	boolean "LH7A40X"
+	depends on ARCH_LH7A40X
+	help
+    This driver provides USB Device Controller driver for LH7A40x
+
+config USB_LH7A40X
+	tristate
+	depends on USB_GADGET_LH7A40X
+	default USB_GADGET
+
+
 config USB_GADGET_DUMMY_HCD
 	boolean "Dummy HCD (DEVELOPMENT)"
 	depends on USB && EXPERIMENTAL
@@ -163,6 +175,41 @@
 	depends on USB_GADGET_DUMMY_HCD
 	default USB_GADGET
 
+config USB_GADGET_OMAP
+	boolean "OMAP USB Device Controller"
+	depends on ARCH_OMAP
+	select ISP1301_OMAP if MACH_OMAP_H2
+	help
+	   Many Texas Instruments OMAP processors have flexible full
+	   speed USB device controllers, with support for up to 30
+	   endpoints (plus endpoint zero).  This driver supports the
+	   controller in the OMAP 1611, and should work with controllers
+	   in other OMAP processors too, given minor tweaks.
+
+	   Say "y" to link the driver statically, or "m" to build a
+	   dynamically linked module called "omap_udc" and force all
+	   gadget drivers to also be dynamically linked.
+
+config USB_OMAP
+	tristate
+	depends on USB_GADGET_OMAP
+	default USB_GADGET
+
+config USB_OTG
+	boolean "OTG Support"
+	depends on USB_GADGET_OMAP && ARCH_OMAP_OTG && USB_OHCI_HCD
+	help
+	   The most notable feature of USB OTG is support for a
+	   "Dual-Role" device, which can act as either a device
+	   or a host.  The initial role choice can be changed
+	   later, when two dual-role devices talk to each other.
+
+	   Select this only if your OMAP board has a Mini-AB connector.
+
+config USB_OMAP_PROC
+	boolean "/proc/driver/udc file"
+	depends on USB_GADGET_OMAP
+
 endchoice
 
 config USB_GADGET_DUALSPEED
@@ -275,7 +322,7 @@
 	  dynamically linked module called "gadgetfs".
 
 config USB_FILE_STORAGE
-	tristate "File-backed Storage Gadget (DEVELOPMENT)"
+	tristate "File-backed Storage Gadget"
 	# we don't support the SA1100 because of its limitations
 	depends on USB_GADGET_SA1100 = n
 	help
@@ -288,7 +335,7 @@
 	  dynamically linked module called "g_file_storage".
 
 config USB_FILE_STORAGE_TEST
-	bool "File-backed Storage Gadget test version"
+	bool "File-backed Storage Gadget testing version"
 	depends on USB_FILE_STORAGE
 	default n
 	help
diff -Nru a/drivers/usb/gadget/Makefile b/drivers/usb/gadget/Makefile
--- a/drivers/usb/gadget/Makefile	2004-10-18 14:55:55 -07:00
+++ b/drivers/usb/gadget/Makefile	2004-10-18 14:55:55 -07:00
@@ -5,13 +5,15 @@
 obj-$(CONFIG_USB_NET2280)	+= net2280.o
 obj-$(CONFIG_USB_PXA2XX)	+= pxa2xx_udc.o
 obj-$(CONFIG_USB_GOKU)		+= goku_udc.o
+obj-$(CONFIG_USB_OMAP)		+= omap_udc.o
+obj-$(CONFIG_USB_LH7A40X)	+= lh7a40x_udc.o
 
 #
 # USB gadget drivers
 #
 g_zero-objs			:= zero.o usbstring.o config.o epautoconf.o
 g_ether-objs			:= ether.o usbstring.o config.o epautoconf.o
-g_serial-objs			:= serial.o usbstring.o
+g_serial-objs			:= serial.o usbstring.o epautoconf.o
 gadgetfs-objs			:= inode.o
 g_file_storage-objs		:= file_storage.o usbstring.o config.o \
 					epautoconf.o
diff -Nru a/drivers/usb/gadget/dummy_hcd.c b/drivers/usb/gadget/dummy_hcd.c
--- a/drivers/usb/gadget/dummy_hcd.c	2004-10-18 14:55:54 -07:00
+++ b/drivers/usb/gadget/dummy_hcd.c	2004-10-18 14:55:54 -07:00
@@ -596,14 +596,13 @@
 
 /* "function" sysfs attribute */
 static ssize_t
-show_function (struct device *_dev, char *buf)
+show_function (struct device *dev, char *buf)
 {
-	struct dummy	*dum = the_controller;
+	struct dummy	*dum = gadget_dev_to_dummy (dev);
 
-	if (!dum->driver->function
-			|| strlen (dum->driver->function) > PAGE_SIZE)
+	if (!dum->driver || !dum->driver->function)
 		return 0;
-	return snprintf (buf, PAGE_SIZE, "%s\n", dum->driver->function);
+	return scnprintf (buf, PAGE_SIZE, "%s\n", dum->driver->function);
 }
 DEVICE_ATTR (function, S_IRUGO, show_function, NULL);
 
diff -Nru a/drivers/usb/gadget/ether.c b/drivers/usb/gadget/ether.c
--- a/drivers/usb/gadget/ether.c	2004-10-18 14:57:04 -07:00
+++ b/drivers/usb/gadget/ether.c	2004-10-18 14:57:04 -07:00
@@ -63,6 +63,7 @@
 
 /*
  * Ethernet gadget driver -- with CDC and non-CDC options
+ * Builds on hardware support for a full duplex link.
  *
  * CDC Ethernet is the standard USB solution for sending Ethernet frames
  * using USB.  Real hardware tends to use the same framing protocol but look
@@ -242,6 +243,10 @@
 #define	DEV_CONFIG_SUBSET
 #endif
 
+#ifdef CONFIG_USB_GADGET_LH7A40X
+#define DEV_CONFIG_CDC
+#endif
+
 #ifdef CONFIG_USB_GADGET_SA1100
 /* use non-CDC for backwards compatibility */
 #define	DEV_CONFIG_SUBSET
@@ -855,7 +860,7 @@
 static char				ethaddr [2 * ETH_ALEN + 1];
 #endif
 
-/* static strings, in iso 8859/1 */
+/* static strings, in UTF-8 */
 static struct usb_string		strings [] = {
 	{ STRING_MANUFACTURER,	manufacturer, },
 	{ STRING_PRODUCT,	product_desc, },
@@ -897,9 +902,9 @@
 
 	if (type == USB_DT_OTHER_SPEED_CONFIG)
 		hs = !hs;
-#define which_fn(t)	(hs ? & hs_ ## t ## _function : & fs_ ## t ## _function)
+#define which_fn(t)	(hs ? hs_ ## t ## _function : fs_ ## t ## _function)
 #else
-#define	which_fn(t)	(& fs_ ## t ## _function)
+#define	which_fn(t)	(fs_ ## t ## _function)
 #endif
 
 	if (index >= device_desc.bNumConfigurations)
@@ -911,14 +916,12 @@
 	 */
 	if (device_desc.bNumConfigurations == 2 && index == 0) {
 		config = &rndis_config;
-		function = (const struct usb_descriptor_header **)
-				which_fn (rndis);
+		function = which_fn (rndis);
 	} else
 #endif
 	{
 		config = &eth_config;
-		function = (const struct usb_descriptor_header **)
-				which_fn (eth);
+		function = which_fn (eth);
 	}
 
 	/* for now, don't advertise srp-only devices */
@@ -2329,6 +2332,8 @@
 		device_desc.bcdDevice = __constant_cpu_to_le16 (0x0207);
 	} else if (gadget_is_omap (gadget)) {
 		device_desc.bcdDevice = __constant_cpu_to_le16 (0x0208);
+	} else if (gadget_is_lh7a40x(gadget)) {
+		device_desc.bcdDevice = __constant_cpu_to_le16 (0x0209);
 	} else {
 		/* can't assume CDC works.  don't want to default to
 		 * anything less functional on CDC-capable hardware,
diff -Nru a/drivers/usb/gadget/file_storage.c b/drivers/usb/gadget/file_storage.c
--- a/drivers/usb/gadget/file_storage.c	2004-10-18 14:57:04 -07:00
+++ b/drivers/usb/gadget/file_storage.c	2004-10-18 14:57:04 -07:00
@@ -46,17 +46,16 @@
  *
  * Backing storage is provided by a regular file or a block device, specified
  * by the "file" module parameter.  Access can be limited to read-only by
- * setting the optional "ro" module parameter.
+ * setting the optional "ro" module parameter.  The gadget will indicate that
+ * it has removable media if the optional "removable" module parameter is set.
  *
  * The gadget supports the Control-Bulk (CB), Control-Bulk-Interrupt (CBI),
  * and Bulk-Only (also known as Bulk-Bulk-Bulk or BBB) transports, selected
  * by the optional "transport" module parameter.  It also supports the
  * following protocols: RBC (0x01), ATAPI or SFF-8020i (0x02), QIC-157 (0c03),
  * UFI (0x04), SFF-8070i (0x05), and transparent SCSI (0x06), selected by
- * the optional "protocol" module parameter.  For testing purposes the
- * gadget will indicate that it has removable media if the optional
- * "removable" module parameter is set.  In addition, the default Vendor ID,
- * Product ID, and release number can be overridden.
+ * the optional "protocol" module parameter.  In addition, the default
+ * Vendor ID, Product ID, and release number can be overridden.
  *
  * There is support for multiple logical units (LUNs), each of which has
  * its own backing file.  The number of LUNs can be set using the optional
@@ -79,13 +78,13 @@
  *					the files or block devices used for
  *					backing storage
  *	ro=b[,b...]		Default false, booleans for read-only access
+ *	removable		Default false, boolean for removable media
  *	luns=N			Default N = number of filenames, number of
  *					LUNs to support
  *	transport=XXX		Default BBB, transport name (CB, CBI, or BBB)
  *	protocol=YYY		Default SCSI, protocol name (RBC, 8020 or
  *					ATAPI, QIC, UFI, 8070, or SCSI;
  *					also 1 - 6)
- *	removable		Default false, boolean for removable media
  *	vendor=0xVVVV		Default 0x0525 (NetChip), USB Vendor ID
  *	product=0xPPPP		Default 0xa4a5 (FSG), USB Product ID
  *	release=0xRRRR		Override the USB release number (bcdDevice)
@@ -97,16 +96,16 @@
  *					boolean to permit the driver to halt
  *					bulk endpoints
  *
- * If CONFIG_USB_FILE_STORAGE_TEST is not set, only the "file" and "ro"
- * options are available; default values are used for everything else.
+ * If CONFIG_USB_FILE_STORAGE_TEST is not set, only the "file", "ro",
+ * "removable", and "luns" options are available; default values are used
+ * for everything else.
  *
  * The pathnames of the backing files and the ro settings are available in
  * the attribute files "file" and "ro" in the lun<n> subdirectory of the
- * gadget's sysfs directory.  If CONFIG_USB_FILE_STORAGE_TEST and the
- * "removable" option are both set, writing to these files will simulate
- * ejecting/loading the medium (writing an empty line means eject) and
- * adjusting a write-enable tab.  Changes to the ro setting are not allowed
- * when the medium is loaded.
+ * gadget's sysfs directory.  If the "removable" option is set, writing to
+ * these files will simulate ejecting/loading the medium (writing an empty
+ * line means eject) and adjusting a write-enable tab.  Changes to the ro
+ * setting are not allowed when the medium is loaded.
  *
  * This gadget driver is heavily based on "Gadget Zero" by David Brownell.
  */
@@ -178,7 +177,10 @@
  * Bulk-only specification requires a stall.  In such cases the driver
  * will halt the endpoint and set a flag indicating that it should clear
  * the halt in software during the next device reset.  Hopefully this
- * will permit everything to work correctly.
+ * will permit everything to work correctly.  Furthermore, although the
+ * specification allows the bulk-out endpoint to halt when the host sends
+ * too much data, implementing this would cause an unavoidable race.
+ * The driver will always use the "no-stall" approach for OUT transfers.
  *
  * One subtle point concerns sending status-stage responses for ep0
  * requests.  Some of these requests, such as device reset, can involve
@@ -246,7 +248,7 @@
 
 #define DRIVER_DESC		"File-backed Storage Gadget"
 #define DRIVER_NAME		"g_file_storage"
-#define DRIVER_VERSION		"21 March 2004"
+#define DRIVER_VERSION		"28 July 2004"
 
 static const char longname[] = DRIVER_DESC;
 static const char shortname[] = DRIVER_NAME;
@@ -371,14 +373,17 @@
 module_param_array(ro, bool, mod_data.num_ros, S_IRUGO);
 MODULE_PARM_DESC(ro, "true to force read-only");
 
+module_param_named(luns, mod_data.nluns, uint, S_IRUGO);
+MODULE_PARM_DESC(luns, "number of LUNs");
 
-/* In the non-TEST version, only the file and ro module parameters
+module_param_named(removable, mod_data.removable, bool, S_IRUGO);
+MODULE_PARM_DESC(removable, "true to simulate removable media");
+
+
+/* In the non-TEST version, only the module parameters listed above
  * are available. */
 #ifdef CONFIG_USB_FILE_STORAGE_TEST
 
-module_param_named(luns, mod_data.nluns, uint, S_IRUGO);
-MODULE_PARM_DESC(luns, "number of LUNs");
-
 module_param_named(transport, mod_data.transport_parm, charp, S_IRUGO);
 MODULE_PARM_DESC(transport, "type of transport (BBB, CBI, or CB)");
 
@@ -386,9 +391,6 @@
 MODULE_PARM_DESC(protocol, "type of protocol (RBC, 8020, QIC, UFI, "
 		"8070, or SCSI)");
 
-module_param_named(removable, mod_data.removable, bool, S_IRUGO);
-MODULE_PARM_DESC(removable, "true to simulate removable media");
-
 module_param_named(vendor, mod_data.vendor, ushort, S_IRUGO);
 MODULE_PARM_DESC(vendor, "USB Vendor ID");
 
@@ -525,11 +527,6 @@
  * parts of the driver that aren't used in the non-TEST version.  Even gcc
  * can recognize when a test of a constant expression yields a dead code
  * path.
- *
- * Also, in the non-TEST version, open_backing_file() is only used during
- * initialization and the sysfs attribute store_xxx routines aren't used
- * at all.  We will define NORMALLY_INIT to mark them as __init so they
- * don't occupy kernel code space unnecessarily.
  */
 
 #ifdef CONFIG_USB_FILE_STORAGE_TEST
@@ -537,16 +534,12 @@
 #define transport_is_bbb()	(mod_data.transport_type == USB_PR_BULK)
 #define transport_is_cbi()	(mod_data.transport_type == USB_PR_CBI)
 #define protocol_is_scsi()	(mod_data.protocol_type == USB_SC_SCSI)
-#define backing_file_is_open(curlun)	((curlun)->filp != NULL)
-#define NORMALLY_INIT
 
 #else
 
 #define transport_is_bbb()	1
 #define transport_is_cbi()	0
 #define protocol_is_scsi()	1
-#define backing_file_is_open(curlun)	1
-#define NORMALLY_INIT		__init
 
 #endif /* CONFIG_USB_FILE_STORAGE_TEST */
 
@@ -567,6 +560,8 @@
 	struct device	dev;
 };
 
+#define backing_file_is_open(curlun)	((curlun)->filp != NULL)
+
 static inline struct lun *dev_to_lun(struct device *dev)
 {
 	return container_of(dev, struct lun, dev);
@@ -659,6 +654,7 @@
 	unsigned long		atomic_bitflags;
 #define REGISTERED		0
 #define CLEAR_BULK_HALTS	1
+#define SUSPENDED		2
 
 	struct usb_ep		*bulk_in;
 	struct usb_ep		*bulk_out;
@@ -1041,8 +1037,6 @@
 		function = fs_function;
 
 	len = usb_gadget_config_buf(&config_desc, buf, EP0_BUFSIZE, function);
-	if (len < 0)
-		return len;
 	((struct usb_config_descriptor *) buf)->bDescriptorType = type;
 	return len;
 }
@@ -1172,9 +1166,10 @@
 	wakeup_thread(fsg);
 }
 
+
+#ifdef CONFIG_USB_FILE_STORAGE_TEST
 static void intr_in_complete(struct usb_ep *ep, struct usb_request *req)
 {
-#ifdef CONFIG_USB_FILE_STORAGE_TEST
 	struct fsg_dev		*fsg = (struct fsg_dev *) ep->driver_data;
 	struct fsg_buffhd	*bh = (struct fsg_buffhd *) req->context;
 
@@ -1190,17 +1185,21 @@
 	bh->state = BUF_STATE_EMPTY;
 	spin_unlock(&fsg->lock);
 	wakeup_thread(fsg);
-#endif /* CONFIG_USB_FILE_STORAGE_TEST */
 }
 
+#else
+static void intr_in_complete(struct usb_ep *ep, struct usb_request *req)
+{}
+#endif /* CONFIG_USB_FILE_STORAGE_TEST */
+
 
 /*-------------------------------------------------------------------------*/
 
 /* Ep0 class-specific handlers.  These always run in_irq. */
 
+#ifdef CONFIG_USB_FILE_STORAGE_TEST
 static void received_cbi_adsc(struct fsg_dev *fsg, struct fsg_buffhd *bh)
 {
-#ifdef CONFIG_USB_FILE_STORAGE_TEST
 	struct usb_request	*req = fsg->ep0req;
 	static u8		cbi_reset_cmnd[6] = {
 			SC_SEND_DIAGNOSTIC, 4, 0xff, 0xff, 0xff, 0xff};
@@ -1238,9 +1237,13 @@
 
 	spin_unlock(&fsg->lock);
 	wakeup_thread(fsg);
-#endif /* CONFIG_USB_FILE_STORAGE_TEST */
 }
 
+#else
+static void received_cbi_adsc(struct fsg_dev *fsg, struct fsg_buffhd *bh)
+{}
+#endif /* CONFIG_USB_FILE_STORAGE_TEST */
+
 
 static int class_setup_req(struct fsg_dev *fsg,
 		const struct usb_ctrlrequest *ctrl)
@@ -1465,8 +1468,8 @@
 	/* Respond with data/status or defer until later? */
 	if (rc >= 0 && rc != DELAYED_STATUS) {
 		fsg->ep0req->length = rc;
-		fsg->ep0req->zero = rc < ctrl->wLength
-				&& (rc % gadget->ep0->maxpacket) == 0;
+		fsg->ep0req->zero = (rc < ctrl->wLength &&
+				(rc % gadget->ep0->maxpacket) == 0);
 		fsg->ep0req_name = (ctrl->bRequestType & USB_DIR_IN ?
 				"ep0-in" : "ep0-out");
 		rc = ep0_queue(fsg);
@@ -2443,14 +2446,19 @@
 			rc = -EINTR;
 		}
 
-		/* We haven't processed all the incoming data.  If we are
-		 * allowed to stall, halt the bulk-out endpoint and cancel
-		 * any outstanding requests. */
+		/* We haven't processed all the incoming data.  Even though
+		 * we may be allowed to stall, doing so would cause a race.
+		 * The controller may already have ACK'ed all the remaining
+		 * bulk-out packets, in which case the host wouldn't see a
+		 * STALL.  Not realizing the endpoint was halted, it wouldn't
+		 * clear the halt -- leading to problems later on. */
+#if 0
 		else if (mod_data.can_stall) {
 			fsg_set_halt(fsg, fsg->bulk_out);
 			raise_exception(fsg, FSG_STATE_ABORT_BULK_OUT);
 			rc = -EINTR;
 		}
+#endif
 
 		/* We can't stall.  Read in the excess data and throw it
 		 * all away. */
@@ -2513,7 +2521,7 @@
 
 	} else if (mod_data.transport_type == USB_PR_CB) {
 
-		/* Control-Bulk transport has no status stage! */
+		/* Control-Bulk transport has no status phase! */
 		return 0;
 
 	} else {			// USB_PR_CBI
@@ -2603,8 +2611,10 @@
 	fsg->residue = fsg->usb_amount_left = fsg->data_size;
 
 	/* Conflicting data directions is a phase error */
-	if (fsg->data_dir != data_dir && fsg->data_size_from_cmnd > 0)
-		goto phase_error;
+	if (fsg->data_dir != data_dir && fsg->data_size_from_cmnd > 0) {
+		fsg->phase_error = 1;
+		return -EINVAL;
+	}
 
 	/* Verify the length of the command itself */
 	if (cmnd_size != fsg->cmnd_size) {
@@ -2613,8 +2623,10 @@
 		 * with cbw->Length == 12 (it should be 6). */
 		if (fsg->cmnd[0] == SC_REQUEST_SENSE && fsg->cmnd_size == 12)
 			cmnd_size = fsg->cmnd_size;
-		else
-			goto phase_error;
+		else {
+			fsg->phase_error = 1;
+			return -EINVAL;
+		}
 	}
 
 	/* Check that the LUN values are oonsistent */
@@ -2674,10 +2686,6 @@
 	}
 
 	return 0;
-
-phase_error:
-	fsg->phase_error = 1;
-	return -EINVAL;
 }
 
 
@@ -3424,8 +3432,7 @@
 /* If the next two routines are called while the gadget is registered,
  * the caller must own fsg->filesem for writing. */
 
-static int NORMALLY_INIT open_backing_file(struct lun *curlun,
-		const char *filename)
+static int open_backing_file(struct lun *curlun, const char *filename)
 {
 	int				ro;
 	struct file			*filp = NULL;
@@ -3550,8 +3557,7 @@
 }
 
 
-ssize_t NORMALLY_INIT store_ro(struct device *dev, const char *buf,
-		size_t count)
+ssize_t store_ro(struct device *dev, const char *buf, size_t count)
 {
 	ssize_t		rc = count;
 	struct lun	*curlun = dev_to_lun(dev);
@@ -3575,8 +3581,7 @@
 	return rc;
 }
 
-ssize_t NORMALLY_INIT store_file(struct device *dev, const char *buf,
-		size_t count)
+ssize_t store_file(struct device *dev, const char *buf, size_t count)
 {
 	struct lun	*curlun = dev_to_lun(dev);
 	struct fsg_dev	*fsg = (struct fsg_dev *) dev_get_drvdata(dev);
@@ -3708,6 +3713,8 @@
 			mod_data.release = __constant_cpu_to_le16(0x0307);
 		else if (gadget_is_omap(fsg->gadget))
 			mod_data.release = __constant_cpu_to_le16(0x0308);
+		else if (gadget_is_lh7a40x(gadget))
+			mod_data.release = __constant_cpu_to_le16 (0x0309);
 		else {
 			WARN(fsg, "controller '%s' not recognized\n",
 				fsg->gadget->name);
@@ -3805,9 +3812,8 @@
 		goto out;
 	}
 
-	/* Create the LUNs and open their backing files.  We can't register
-	 * the LUN devices until the gadget itself is registered, which
-	 * doesn't happen until after fsg_bind() returns. */
+	/* Create the LUNs, open their backing files, and register the
+	 * LUN devices in sysfs. */
 	fsg->luns = kmalloc(i * sizeof(struct lun), GFP_KERNEL);
 	if (!fsg->luns) {
 		rc = -ENOMEM;
@@ -3825,6 +3831,15 @@
 		snprintf(curlun->dev.bus_id, BUS_ID_SIZE,
 				"%s-lun%d", gadget->dev.bus_id, i);
 
+		if ((rc = device_register(&curlun->dev)) != 0)
+			INFO(fsg, "failed to register LUN%d: %d\n", i, rc);
+		else {
+			curlun->registered = 1;
+			curlun->dev.release = lun_release;
+			device_create_file(&curlun->dev, &dev_attr_ro);
+			device_create_file(&curlun->dev, &dev_attr_file);
+		}
+
 		if (file[i] && *file[i]) {
 			if ((rc = open_backing_file(curlun, file[i])) != 0)
 				goto out;
@@ -3974,6 +3989,25 @@
 
 /*-------------------------------------------------------------------------*/
 
+static void fsg_suspend(struct usb_gadget *gadget)
+{
+	struct fsg_dev		*fsg = get_gadget_data(gadget);
+
+	DBG(fsg, "suspend\n");
+	set_bit(SUSPENDED, &fsg->atomic_bitflags);
+}
+
+static void fsg_resume(struct usb_gadget *gadget)
+{
+	struct fsg_dev		*fsg = get_gadget_data(gadget);
+
+	DBG(fsg, "resume\n");
+	clear_bit(SUSPENDED, &fsg->atomic_bitflags);
+}
+
+
+/*-------------------------------------------------------------------------*/
+
 static struct usb_gadget_driver		fsg_driver = {
 #ifdef CONFIG_USB_GADGET_DUALSPEED
 	.speed		= USB_SPEED_HIGH,
@@ -3985,6 +4019,8 @@
 	.unbind		= fsg_unbind,
 	.disconnect	= fsg_disconnect,
 	.setup		= fsg_setup,
+	.suspend	= fsg_suspend,
+	.resume		= fsg_resume,
 
 	.driver		= {
 		.name		= (char *) shortname,
@@ -4024,8 +4060,6 @@
 {
 	int		rc;
 	struct fsg_dev	*fsg;
-	int		i;
-	struct lun	*curlun;
 
 	if ((rc = fsg_alloc()) != 0)
 		return rc;
@@ -4035,19 +4069,6 @@
 		return rc;
 	}
 	set_bit(REGISTERED, &fsg->atomic_bitflags);
-
-	/* Register the LUN devices and their attribute files */
-	for (i = 0; i < fsg->nluns; ++i) {
-		curlun = &fsg->luns[i];
-		if ((rc = device_register(&curlun->dev)) != 0)
-			INFO(fsg, "failed to register LUN%d: %d\n", i, rc);
-		else {
-			curlun->registered = 1;
-			curlun->dev.release = lun_release;
-			device_create_file(&curlun->dev, &dev_attr_ro);
-			device_create_file(&curlun->dev, &dev_attr_file);
-		}
-	}
 
 	/* Tell the thread to start working */
 	complete(&fsg->thread_notifier);
diff -Nru a/drivers/usb/gadget/gadget_chips.h b/drivers/usb/gadget/gadget_chips.h
--- a/drivers/usb/gadget/gadget_chips.h	2004-10-18 14:55:46 -07:00
+++ b/drivers/usb/gadget/gadget_chips.h	2004-10-18 14:55:46 -07:00
@@ -44,6 +44,12 @@
 #define	gadget_is_sa1100(g)	0
 #endif
 
+#ifdef CONFIG_USB_GADGET_LH7A40X
+#define	gadget_is_lh7a40x(g)	!strcmp("lh7a40x_udc", (g)->name)
+#else
+#define	gadget_is_lh7a40x(g)	0
+#endif
+
 #ifdef CONFIG_USB_GADGET_MQ11XX
 #define	gadget_is_mq11xx(g)	!strcmp("mq11xx_udc", (g)->name)
 #else
diff -Nru a/drivers/usb/gadget/inode.c b/drivers/usb/gadget/inode.c
--- a/drivers/usb/gadget/inode.c	2004-10-18 14:56:49 -07:00
+++ b/drivers/usb/gadget/inode.c	2004-10-18 14:56:49 -07:00
@@ -1,7 +1,7 @@
 /*
  * inode.c -- user mode filesystem api for usb gadget controllers
  *
- * Copyright (C) 2003 David Brownell
+ * Copyright (C) 2003-2004 David Brownell
  * Copyright (C) 2003 Agilent Technologies
  *
  * This program is free software; you can redistribute it and/or modify
@@ -71,7 +71,7 @@
  */
 
 #define	DRIVER_DESC	"USB Gadget filesystem"
-#define	DRIVER_VERSION	"18 Nov 2003"
+#define	DRIVER_VERSION	"24 Aug 2004"
 
 static const char driver_desc [] = DRIVER_DESC;
 static const char shortname [] = "gadgetfs";
@@ -229,37 +229,12 @@
 /*----------------------------------------------------------------------*/
 
 /* most "how to use the hardware" policy choices are in userspace:
- * mapping endpoint roles the driver needs to the capabilities that
- * the usb controller exposes.
+ * mapping endpoint roles (which the driver needs) to the capabilities
+ * which the usb controller has.  most of those capabilities are exposed
+ * implicitly, starting with the driver name and then endpoint names.
  */
 
-#ifdef	CONFIG_USB_GADGET_DUMMY_HCD
-/* act (mostly) like a net2280 */
-#define CONFIG_USB_GADGET_NET2280
-#endif
-
-#ifdef	CONFIG_USB_GADGET_NET2280
-#define CHIP			"net2280"
-#define HIGHSPEED
-#endif
-
-#ifdef	CONFIG_USB_GADGET_PXA2XX
-#define CHIP			"pxa2xx_udc"
-/* earlier hardware doesn't have UDCCFR, races set_{config,interface} */
-#warning works best with pxa255 or newer
-#endif
-
-#ifdef	CONFIG_USB_GADGET_GOKU
-#define CHIP			"goku_udc"
-#endif
-
-#ifdef	CONFIG_USB_GADGET_OMAP
-#define CHIP			"omap_udc"
-#endif
-
-#ifdef	CONFIG_USB_GADGET_SA1100
-#define CHIP			"sa1100"
-#endif
+static const char *CHIP;
 
 /*----------------------------------------------------------------------*/
 
@@ -558,7 +533,7 @@
 
 static int ep_aio_cancel(struct kiocb *iocb, struct io_event *e)
 {
-	struct kiocb_priv	*priv = (void *) &iocb->private;
+	struct kiocb_priv	*priv = iocb->private;
 	struct ep_data		*epdata;
 	int			value;
 
@@ -577,10 +552,10 @@
 	return value;
 }
 
-static long ep_aio_read_retry(struct kiocb *iocb)
+static ssize_t ep_aio_read_retry(struct kiocb *iocb)
 {
-	struct kiocb_priv	*priv = (void *) &iocb->private;
-	int			status = priv->actual;
+	struct kiocb_priv	*priv = iocb->private;
+	ssize_t			status = priv->actual;
 
 	/* we "retry" to get the right mm context for this: */
 	status = copy_to_user(priv->ubuf, priv->buf, priv->actual);
@@ -589,6 +564,7 @@
 	else
 		status = priv->actual;
 	kfree(priv->buf);
+	kfree(priv);
 	aio_put_req(iocb);
 	return status;
 }
@@ -596,7 +572,7 @@
 static void ep_aio_complete(struct usb_ep *ep, struct usb_request *req)
 {
 	struct kiocb		*iocb = req->context;
-	struct kiocb_priv	*priv = (void *) &iocb->private;
+	struct kiocb_priv	*priv = iocb->private;
 	struct ep_data		*epdata = priv->epdata;
 
 	/* lock against disconnect (and ideally, cancel) */
@@ -607,6 +583,8 @@
 			|| unlikely(0 == req->actual)
 			|| unlikely(kiocbIsCancelled(iocb))) {
 		kfree(req->buf);
+		kfree(priv);
+		iocb->private = NULL;
 		/* aio_complete() reports bytes-transferred _and_ faults */
 		if (unlikely(kiocbIsCancelled(iocb)))
 			aio_put_req(iocb);
@@ -631,17 +609,33 @@
 }
 
 static ssize_t
-ep_aio_rwtail(struct kiocb *iocb, char *buf, size_t len, struct ep_data *epdata)
+ep_aio_rwtail(
+	struct kiocb	*iocb,
+	char		*buf,
+	size_t		len,
+	struct ep_data	*epdata,
+	char __user	*ubuf
+)
 {
 	struct kiocb_priv	*priv = (void *) &iocb->private;
 	struct usb_request	*req;
 	ssize_t			value;
 
-	value = get_ready_ep(iocb->ki_filp->f_flags, epdata);
-	if (unlikely(value < 0)) {
+	priv = kmalloc(sizeof *priv, GFP_KERNEL);
+	if (!priv) {
+		value = -ENOMEM;
+fail:
 		kfree(buf);
 		return value;
 	}
+	iocb->private = priv;
+	priv->ubuf = ubuf;
+
+	value = get_ready_ep(iocb->ki_filp->f_flags, epdata);
+	if (unlikely(value < 0)) {
+		kfree(priv);
+		goto fail;
+	}
 
 	iocb->ki_cancel = ep_aio_cancel;
 	get_ep(epdata);
@@ -671,9 +665,10 @@
 
 	up(&epdata->lock);
 
-	if (unlikely(value))
+	if (unlikely(value)) {
+		kfree(priv);
 		put_ep(epdata);
-	else
+	} else
 		value = -EIOCBQUEUED;
 	return value;
 }
@@ -681,7 +676,6 @@
 static ssize_t
 ep_aio_read(struct kiocb *iocb, char __user *ubuf, size_t len, loff_t o)
 {
-	struct kiocb_priv	*priv = (void *) &iocb->private;
 	struct ep_data		*epdata = iocb->ki_filp->private_data;
 	char			*buf;
 
@@ -691,8 +685,7 @@
 	if (unlikely(!buf))
 		return -ENOMEM;
 	iocb->ki_retry = ep_aio_read_retry;
-	priv->ubuf = ubuf;
-	return ep_aio_rwtail(iocb, buf, len, epdata);
+	return ep_aio_rwtail(iocb, buf, len, epdata, ubuf);
 }
 
 static ssize_t
@@ -710,7 +703,7 @@
 		kfree(buf);
 		return -EFAULT;
 	}
-	return ep_aio_rwtail(iocb, buf, len, epdata);
+	return ep_aio_rwtail(iocb, buf, len, epdata, NULL);
 }
 
 /*----------------------------------------------------------------------*/
@@ -718,6 +711,8 @@
 /* used after endpoint configuration */
 static struct file_operations ep_io_operations = {
 	.owner =	THIS_MODULE,
+	.llseek =	no_llseek,
+
 	.read =		ep_read,
 	.write =	ep_write,
 	.ioctl =	ep_ioctl,
@@ -874,6 +869,8 @@
 /* used before endpoint configuration */
 static struct file_operations ep_config_operations = {
 	.owner =	THIS_MODULE,
+	.llseek =	no_llseek,
+
 	.open =		ep_open,
 	.write =	ep_config,
 	.release =	ep_release,
@@ -980,6 +977,18 @@
 				retval = usb_ep_queue (ep, req, GFP_ATOMIC);
 			dev->state = STATE_CONNECTED;
 
+			/* assume that was SET_CONFIGURATION */
+			if (dev->current_config) {
+				unsigned power;
+#ifdef	HIGHSPEED
+				if (dev->gadget->speed == USB_SPEED_HIGH)
+					power = dev->hs_config->bMaxPower;
+				else
+#endif
+					power = dev->config->bMaxPower;
+				usb_gadget_vbus_draw(dev->gadget, 2 * power);
+			}
+
 		} else {			/* collect OUT data */
 			if ((fd->f_flags & O_NONBLOCK) != 0
 					&& !dev->setup_out_ready) {
@@ -1230,6 +1239,8 @@
 /* used after device configuration */
 static struct file_operations ep0_io_operations = {
 	.owner =	THIS_MODULE,
+	.llseek =	no_llseek,
+
 	.read =		ep0_read,
 	.write =	ep0_write,
 	.fasync =	ep0_fasync,
@@ -1406,19 +1417,25 @@
 		if (0 == (u8) ctrl->wValue) {
 			value = 0;
 			dev->current_config = 0;
+			usb_gadget_vbus_draw(gadget, 8 /* mA */ );
 			// user mode expected to disable endpoints
 		} else {
-			u8	config;
+			u8	config, power;
 #ifdef	HIGHSPEED
-			if (gadget->speed == USB_SPEED_HIGH)
+			if (gadget->speed == USB_SPEED_HIGH) {
 				config = dev->hs_config->bConfigurationValue;
-			else
+				power = dev->hs_config->bMaxPower;
+			} else
 #endif
+			{
 				config = dev->config->bConfigurationValue;
+				power = dev->config->bMaxPower;
+			}
 
 			if (config == (u8) ctrl->wValue) {
 				value = 0;
 				dev->current_config = config;
+				usb_gadget_vbus_draw(gadget, 2 * power);
 			}
 		}
 
@@ -1636,8 +1653,8 @@
 	if (!dev)
 		return -ESRCH;
 	if (0 != strcmp (CHIP, gadget->name)) {
-		printk (KERN_ERR "%s expected " CHIP " controller not %s\n",
-			shortname, gadget->name);
+		printk (KERN_ERR "%s expected %s controller not %s\n",
+			shortname, CHIP, gadget->name);
 		return -ENODEV;
 	}
 
@@ -1727,6 +1744,26 @@
 
 /*----------------------------------------------------------------------*/
 
+static void gadgetfs_nop(struct usb_gadget *arg) { }
+
+static int gadgetfs_probe (struct usb_gadget *gadget)
+{
+	CHIP = gadget->name;
+	return -EISNAM;
+}
+
+static struct usb_gadget_driver probe_driver = {
+	.speed		= USB_SPEED_HIGH,
+	.bind		= gadgetfs_probe,
+	.unbind		= gadgetfs_nop,
+	.setup		= (void *)gadgetfs_nop,
+	.disconnect	= gadgetfs_nop,
+	.driver 	= {
+		.name		= "nop",
+	},
+};
+
+
 /* DEVICE INITIALIZATION
  *
  *     fd = open ("/dev/gadget/$CHIP", O_RDWR)
@@ -1763,6 +1800,7 @@
 		&& config->bConfigurationValue != 0
 		&& (config->bmAttributes & USB_CONFIG_ATT_ONE) != 0
 		&& (config->bmAttributes & USB_CONFIG_ATT_WAKEUP) == 0;
+	/* FIXME if gadget->is_otg, _must_ include an otg descriptor */
 	/* FIXME check lengths: walk to end */
 }
 
@@ -1881,6 +1919,8 @@
 
 static struct file_operations dev_init_operations = {
 	.owner =	THIS_MODULE,
+	.llseek =	no_llseek,
+
 	.open =		dev_open,
 	.write =	dev_config,
 	.fasync =	ep0_fasync,
@@ -1975,6 +2015,11 @@
 
 	if (the_device)
 		return -ESRCH;
+
+	/* fake probe to determine $CHIP */
+	(void) usb_gadget_register_driver (&probe_driver);
+	if (!CHIP)
+		return -ENODEV;
 
 	/* superblock */
 	sb->s_blocksize = PAGE_CACHE_SIZE;
diff -Nru a/drivers/usb/gadget/lh7a40x_udc.c b/drivers/usb/gadget/lh7a40x_udc.c
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/drivers/usb/gadget/lh7a40x_udc.c	2004-10-18 14:57:24 -07:00
@@ -0,0 +1,2168 @@
+/*
+ * linux/drivers/usb/gadget/lh7a40x_udc.c
+ * Sharp LH7A40x on-chip full speed USB device controllers
+ *
+ * Copyright (C) 2004 Mikko Lahteenmaki, Nordic ID
+ * Copyright (C) 2004 Bo Henriksen, Nordic ID
+ *
+ * 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
+ *
+ */
+
+#include "lh7a40x_udc.h"
+
+//#define DEBUG printk
+//#define DEBUG_EP0 printk
+//#define DEBUG_SETUP printk
+
+#ifndef DEBUG_EP0
+# define DEBUG_EP0(fmt,args...)
+#endif
+#ifndef DEBUG_SETUP
+# define DEBUG_SETUP(fmt,args...)
+#endif
+#ifndef DEBUG
+# define NO_STATES
+# define DEBUG(fmt,args...)
+#endif
+
+#define	DRIVER_DESC			"LH7A40x USB Device Controller"
+#define	DRIVER_VERSION		__DATE__
+
+#ifndef _BIT			/* FIXME - what happended to _BIT in 2.6.7bk18? */
+#define _BIT(x) (1<<(x))
+#endif
+
+struct lh7a40x_udc *the_controller;
+
+static const char driver_name[] = "lh7a40x_udc";
+static const char driver_desc[] = DRIVER_DESC;
+static const char ep0name[] = "ep0-control";
+
+/*
+  Local definintions.
+*/
+#define UDC_PROC_FILE
+
+#ifndef NO_STATES
+static char *state_names[] = {
+	"WAIT_FOR_SETUP",
+	"DATA_STATE_XMIT",
+	"DATA_STATE_NEED_ZLP",
+	"WAIT_FOR_OUT_STATUS",
+	"DATA_STATE_RECV"
+};
+#endif
+
+/*
+  Local declarations.
+*/
+static int lh7a40x_ep_enable(struct usb_ep *ep,
+			     const struct usb_endpoint_descriptor *);
+static int lh7a40x_ep_disable(struct usb_ep *ep);
+static struct usb_request *lh7a40x_alloc_request(struct usb_ep *ep, int);
+static void lh7a40x_free_request(struct usb_ep *ep, struct usb_request *);
+static void *lh7a40x_alloc_buffer(struct usb_ep *ep, unsigned, dma_addr_t *,
+				  int);
+static void lh7a40x_free_buffer(struct usb_ep *ep, void *, dma_addr_t,
+				unsigned);
+static int lh7a40x_queue(struct usb_ep *ep, struct usb_request *, int);
+static int lh7a40x_dequeue(struct usb_ep *ep, struct usb_request *);
+static int lh7a40x_set_halt(struct usb_ep *ep, int);
+static int lh7a40x_fifo_status(struct usb_ep *ep);
+static int lh7a40x_fifo_status(struct usb_ep *ep);
+static void lh7a40x_fifo_flush(struct usb_ep *ep);
+static void lh7a40x_ep0_kick(struct lh7a40x_udc *dev, struct lh7a40x_ep *ep);
+static void lh7a40x_handle_ep0(struct lh7a40x_udc *dev, u32 intr);
+
+static void done(struct lh7a40x_ep *ep, struct lh7a40x_request *req,
+		 int status);
+static void pio_irq_enable(int bEndpointAddress);
+static void pio_irq_disable(int bEndpointAddress);
+static void stop_activity(struct lh7a40x_udc *dev,
+			  struct usb_gadget_driver *driver);
+static void flush(struct lh7a40x_ep *ep);
+static void udc_enable(struct lh7a40x_udc *dev);
+static void udc_set_address(struct lh7a40x_udc *dev, unsigned char address);
+
+static struct usb_ep_ops lh7a40x_ep_ops = {
+	.enable = lh7a40x_ep_enable,
+	.disable = lh7a40x_ep_disable,
+
+	.alloc_request = lh7a40x_alloc_request,
+	.free_request = lh7a40x_free_request,
+
+	.alloc_buffer = lh7a40x_alloc_buffer,
+	.free_buffer = lh7a40x_free_buffer,
+
+	.queue = lh7a40x_queue,
+	.dequeue = lh7a40x_dequeue,
+
+	.set_halt = lh7a40x_set_halt,
+	.fifo_status = lh7a40x_fifo_status,
+	.fifo_flush = lh7a40x_fifo_flush,
+};
+
+/* Inline code */
+
+static __inline__ int write_packet(struct lh7a40x_ep *ep,
+				   struct lh7a40x_request *req, int max)
+{
+	u8 *buf;
+	int length, count;
+	volatile u32 *fifo = (volatile u32 *)ep->fifo;
+
+	buf = req->req.buf + req->req.actual;
+	prefetch(buf);
+
+	length = req->req.length - req->req.actual;
+	length = min(length, max);
+	req->req.actual += length;
+
+	DEBUG("Write %d (max %d), fifo %p\n", length, max, fifo);
+
+	count = length;
+	while (count--) {
+		*fifo = *buf++;
+	}
+
+	return length;
+}
+
+static __inline__ void usb_set_index(u32 ep)
+{
+	*(volatile u32 *)io_p2v(USB_INDEX) = ep;
+}
+
+static __inline__ u32 usb_read(u32 port)
+{
+	return *(volatile u32 *)io_p2v(port);
+}
+
+static __inline__ void usb_write(u32 val, u32 port)
+{
+	*(volatile u32 *)io_p2v(port) = val;
+}
+
+static __inline__ void usb_set(u32 val, u32 port)
+{
+	volatile u32 *ioport = (volatile u32 *)io_p2v(port);
+	u32 after = (*ioport) | val;
+	*ioport = after;
+}
+
+static __inline__ void usb_clear(u32 val, u32 port)
+{
+	volatile u32 *ioport = (volatile u32 *)io_p2v(port);
+	u32 after = (*ioport) & ~val;
+	*ioport = after;
+}
+
+/*-------------------------------------------------------------------------*/
+
+#define GPIO_PORTC_DR 	(0x80000E08)
+#define GPIO_PORTC_DDR 	(0x80000E18)
+#define GPIO_PORTC_PDR 	(0x80000E70)
+
+/* get port C pin data register */
+#define get_portc_pdr(bit) 		((usb_read(GPIO_PORTC_PDR) & _BIT(bit)) != 0)
+/* get port C data direction register */
+#define get_portc_ddr(bit) 		((usb_read(GPIO_PORTC_DDR) & _BIT(bit)) != 0)
+/* set port C data register */
+#define set_portc_dr(bit, val) 	(val ? usb_set(_BIT(bit), GPIO_PORTC_DR) : usb_clear(_BIT(bit), GPIO_PORTC_DR))
+/* set port C data direction register */
+#define set_portc_ddr(bit, val) (val ? usb_set(_BIT(bit), GPIO_PORTC_DDR) : usb_clear(_BIT(bit), GPIO_PORTC_DDR))
+
+/*
+ * LPD7A404 GPIO's:
+ * Port C bit 1 = USB Port 1 Power Enable
+ * Port C bit 2 = USB Port 1 Data Carrier Detect
+ */
+#define is_usb_connected() 		get_portc_pdr(2)
+
+#ifdef UDC_PROC_FILE
+
+static const char proc_node_name[] = "driver/udc";
+
+static int
+udc_proc_read(char *page, char **start, off_t off, int count,
+	      int *eof, void *_dev)
+{
+	char *buf = page;
+	struct lh7a40x_udc *dev = _dev;
+	char *next = buf;
+	unsigned size = count;
+	unsigned long flags;
+	int t;
+
+	if (off != 0)
+		return 0;
+
+	local_irq_save(flags);
+
+	/* basic device status */
+	t = scnprintf(next, size,
+		      DRIVER_DESC "\n"
+		      "%s version: %s\n"
+		      "Gadget driver: %s\n"
+		      "Host: %s\n\n",
+		      driver_name, DRIVER_VERSION,
+		      dev->driver ? dev->driver->driver.name : "(none)",
+		      is_usb_connected()? "full speed" : "disconnected");
+	size -= t;
+	next += t;
+
+	t = scnprintf(next, size,
+		      "GPIO:\n"
+		      " Port C bit 1: %d, dir %d\n"
+		      " Port C bit 2: %d, dir %d\n\n",
+		      get_portc_pdr(1), get_portc_ddr(1),
+		      get_portc_pdr(2), get_portc_ddr(2)
+	    );
+	size -= t;
+	next += t;
+
+	t = scnprintf(next, size,
+		      "DCP pullup: %d\n\n",
+		      (usb_read(USB_PM) & PM_USB_DCP) != 0);
+	size -= t;
+	next += t;
+
+	local_irq_restore(flags);
+	*eof = 1;
+	return count - size;
+}
+
+#define create_proc_files() 	create_proc_read_entry(proc_node_name, 0, NULL, udc_proc_read, dev)
+#define remove_proc_files() 	remove_proc_entry(proc_node_name, NULL)
+
+#else				/* !UDC_PROC_FILE */
+
+#define create_proc_files() do {} while (0)
+#define remove_proc_files() do {} while (0)
+
+#endif				/* UDC_PROC_FILE */
+
+/*
+ * 	udc_disable - disable USB device controller
+ */
+static void udc_disable(struct lh7a40x_udc *dev)
+{
+	DEBUG("%s, %p\n", __FUNCTION__, dev);
+
+	udc_set_address(dev, 0);
+
+	/* Disable interrupts */
+	usb_write(0, USB_IN_INT_EN);
+	usb_write(0, USB_OUT_INT_EN);
+	usb_write(0, USB_INT_EN);
+
+	/* Disable the USB */
+	usb_write(0, USB_PM);
+
+#ifdef CONFIG_ARCH_LH7A404
+	/* Disable USB power */
+	set_portc_dr(1, 0);
+#endif
+
+	/* if hardware supports it, disconnect from usb */
+	/* make_usb_disappear(); */
+
+	dev->ep0state = WAIT_FOR_SETUP;
+	dev->gadget.speed = USB_SPEED_UNKNOWN;
+	dev->usb_address = 0;
+}
+
+/*
+ * 	udc_reinit - initialize software state
+ */
+static void udc_reinit(struct lh7a40x_udc *dev)
+{
+	u32 i;
+
+	DEBUG("%s, %p\n", __FUNCTION__, dev);
+
+	/* device/ep0 records init */
+	INIT_LIST_HEAD(&dev->gadget.ep_list);
+	INIT_LIST_HEAD(&dev->gadget.ep0->ep_list);
+	dev->ep0state = WAIT_FOR_SETUP;
+
+	/* basic endpoint records init */
+	for (i = 0; i < UDC_MAX_ENDPOINTS; i++) {
+		struct lh7a40x_ep *ep = &dev->ep[i];
+
+		if (i != 0)
+			list_add_tail(&ep->ep.ep_list, &dev->gadget.ep_list);
+
+		ep->desc = 0;
+		ep->stopped = 0;
+		INIT_LIST_HEAD(&ep->queue);
+		ep->pio_irqs = 0;
+	}
+
+	/* the rest was statically initialized, and is read-only */
+}
+
+#define BYTES2MAXP(x)	(x / 8)
+#define MAXP2BYTES(x)	(x * 8)
+
+/* until it's enabled, this UDC should be completely invisible
+ * to any USB host.
+ */
+static void udc_enable(struct lh7a40x_udc *dev)
+{
+	int ep;
+
+	DEBUG("%s, %p\n", __FUNCTION__, dev);
+
+	dev->gadget.speed = USB_SPEED_UNKNOWN;
+
+#ifdef CONFIG_ARCH_LH7A404
+	/* Set Port C bit 1 & 2 as output */
+	set_portc_ddr(1, 1);
+	set_portc_ddr(2, 1);
+
+	/* Enable USB power */
+	set_portc_dr(1, 0);
+#endif
+
+	/*
+	 * C.f Chapter 18.1.3.1 Initializing the USB
+	 */
+
+	/* Disable the USB */
+	usb_clear(PM_USB_ENABLE, USB_PM);
+
+	/* Reset APB & I/O sides of the USB */
+	usb_set(USB_RESET_APB | USB_RESET_IO, USB_RESET);
+	mdelay(5);
+	usb_clear(USB_RESET_APB | USB_RESET_IO, USB_RESET);
+
+	/* Set MAXP values for each */
+	for (ep = 0; ep < UDC_MAX_ENDPOINTS; ep++) {
+		struct lh7a40x_ep *ep_reg = &dev->ep[ep];
+		u32 csr;
+
+		usb_set_index(ep);
+
+		switch (ep_reg->ep_type) {
+		case ep_bulk_in:
+		case ep_interrupt:
+			usb_clear(USB_IN_CSR2_USB_DMA_EN | USB_IN_CSR2_AUTO_SET,
+				  ep_reg->csr2);
+			/* Fall through */
+		case ep_control:
+			usb_write(BYTES2MAXP(ep_maxpacket(ep_reg)),
+				  USB_IN_MAXP);
+			break;
+		case ep_bulk_out:
+			usb_clear(USB_OUT_CSR2_USB_DMA_EN |
+				  USB_OUT_CSR2_AUTO_CLR, ep_reg->csr2);
+			usb_write(BYTES2MAXP(ep_maxpacket(ep_reg)),
+				  USB_OUT_MAXP);
+			break;
+		}
+
+		/* Read & Write CSR1, just in case */
+		csr = usb_read(ep_reg->csr1);
+		usb_write(csr, ep_reg->csr1);
+
+		flush(ep_reg);
+	}
+
+	/* Disable interrupts */
+	usb_write(0, USB_IN_INT_EN);
+	usb_write(0, USB_OUT_INT_EN);
+	usb_write(0, USB_INT_EN);
+
+	/* Enable interrupts */
+	usb_set(USB_IN_INT_EP0, USB_IN_INT_EN);
+	usb_set(USB_INT_RESET_INT | USB_INT_RESUME_INT, USB_INT_EN);
+	/* Dont enable rest of the interrupts */
+	/* usb_set(USB_IN_INT_EP3 | USB_IN_INT_EP1 | USB_IN_INT_EP0, USB_IN_INT_EN);
+	   usb_set(USB_OUT_INT_EP2, USB_OUT_INT_EN); */
+
+	/* Enable SUSPEND */
+	usb_set(PM_ENABLE_SUSPEND, USB_PM);
+
+	/* Enable the USB */
+	usb_set(PM_USB_ENABLE, USB_PM);
+
+#ifdef CONFIG_ARCH_LH7A404
+	/* NOTE: DOES NOT WORK! */
+	/* Let host detect UDC:
+	 * Software must write a 0 to the PMR:DCP_CTRL bit to turn this
+	 * transistor on and pull the USBDP pin HIGH.
+	 */
+	/* usb_clear(PM_USB_DCP, USB_PM);
+	   usb_set(PM_USB_DCP, USB_PM); */
+#endif
+}
+
+/*
+  Register entry point for the peripheral controller driver.
+*/
+int usb_gadget_register_driver(struct usb_gadget_driver *driver)
+{
+	struct lh7a40x_udc *dev = the_controller;
+	int retval;
+
+	DEBUG("%s: %s\n", __FUNCTION__, driver->driver.name);
+
+	if (!driver
+	    || driver->speed != USB_SPEED_FULL
+	    || !driver->bind
+	    || !driver->unbind || !driver->disconnect || !driver->setup)
+		return -EINVAL;
+	if (!dev)
+		return -ENODEV;
+	if (dev->driver)
+		return -EBUSY;
+
+	/* first hook up the driver ... */
+	dev->driver = driver;
+	dev->gadget.dev.driver = &driver->driver;
+
+	device_add(&dev->gadget.dev);
+	retval = driver->bind(&dev->gadget);
+	if (retval) {
+		printk("%s: bind to driver %s --> error %d\n", dev->gadget.name,
+		       driver->driver.name, retval);
+		device_del(&dev->gadget.dev);
+
+		dev->driver = 0;
+		dev->gadget.dev.driver = 0;
+		return retval;
+	}
+
+	/* ... then enable host detection and ep0; and we're ready
+	 * for set_configuration as well as eventual disconnect.
+	 * NOTE:  this shouldn't power up until later.
+	 */
+	printk("%s: registered gadget driver '%s'\n", dev->gadget.name,
+	       driver->driver.name);
+
+	udc_enable(dev);
+
+	return 0;
+}
+
+EXPORT_SYMBOL(usb_gadget_register_driver);
+
+/*
+  Unregister entry point for the peripheral controller driver.
+*/
+int usb_gadget_unregister_driver(struct usb_gadget_driver *driver)
+{
+	struct lh7a40x_udc *dev = the_controller;
+	unsigned long flags;
+
+	if (!dev)
+		return -ENODEV;
+	if (!driver || driver != dev->driver)
+		return -EINVAL;
+
+	spin_lock_irqsave(&dev->lock, flags);
+	dev->driver = 0;
+	stop_activity(dev, driver);
+	spin_unlock_irqrestore(&dev->lock, flags);
+
+	driver->unbind(&dev->gadget);
+	device_del(&dev->gadget.dev);
+
+	udc_disable(dev);
+
+	DEBUG("unregistered gadget driver '%s'\n", driver->driver.name);
+	return 0;
+}
+
+EXPORT_SYMBOL(usb_gadget_unregister_driver);
+
+/*-------------------------------------------------------------------------*/
+
+/** Write request to FIFO (max write == maxp size)
+ *  Return:  0 = still running, 1 = completed, negative = errno
+ *  NOTE: INDEX register must be set for EP
+ */
+static int write_fifo(struct lh7a40x_ep *ep, struct lh7a40x_request *req)
+{
+	u32 max;
+	u32 csr;
+
+	max = le16_to_cpu(ep->desc->wMaxPacketSize);
+
+	csr = usb_read(ep->csr1);
+	DEBUG("CSR: %x %d\n", csr, csr & USB_IN_CSR1_FIFO_NOT_EMPTY);
+
+	if (!(csr & USB_IN_CSR1_FIFO_NOT_EMPTY)) {
+		unsigned count;
+		int is_last, is_short;
+
+		count = write_packet(ep, req, max);
+		usb_set(USB_IN_CSR1_IN_PKT_RDY, ep->csr1);
+
+		/* last packet is usually short (or a zlp) */
+		if (unlikely(count != max))
+			is_last = is_short = 1;
+		else {
+			if (likely(req->req.length != req->req.actual)
+			    || req->req.zero)
+				is_last = 0;
+			else
+				is_last = 1;
+			/* interrupt/iso maxpacket may not fill the fifo */
+			is_short = unlikely(max < ep_maxpacket(ep));
+		}
+
+		DEBUG("%s: wrote %s %d bytes%s%s %d left %p\n", __FUNCTION__,
+		      ep->ep.name, count,
+		      is_last ? "/L" : "", is_short ? "/S" : "",
+		      req->req.length - req->req.actual, req);
+
+		/* requests complete when all IN data is in the FIFO */
+		if (is_last) {
+			done(ep, req, 0);
+			if (list_empty(&ep->queue)) {
+				pio_irq_disable(ep_index(ep));
+			}
+			return 1;
+		}
+	} else {
+		DEBUG("Hmm.. %d ep FIFO is not empty!\n", ep_index(ep));
+	}
+
+	return 0;
+}
+
+/** Read to request from FIFO (max read == bytes in fifo)
+ *  Return:  0 = still running, 1 = completed, negative = errno
+ *  NOTE: INDEX register must be set for EP
+ */
+static int read_fifo(struct lh7a40x_ep *ep, struct lh7a40x_request *req)
+{
+	u32 csr;
+	u8 *buf;
+	unsigned bufferspace, count, is_short;
+	volatile u32 *fifo = (volatile u32 *)ep->fifo;
+
+	/* make sure there's a packet in the FIFO. */
+	csr = usb_read(ep->csr1);
+	if (!(csr & USB_OUT_CSR1_OUT_PKT_RDY)) {
+		DEBUG("%s: Packet NOT ready!\n", __FUNCTION__);
+		return -EINVAL;
+	}
+
+	buf = req->req.buf + req->req.actual;
+	prefetchw(buf);
+	bufferspace = req->req.length - req->req.actual;
+
+	/* read all bytes from this packet */
+	count = usb_read(USB_OUT_FIFO_WC1);
+	req->req.actual += min(count, bufferspace);
+
+	is_short = (count < ep->ep.maxpacket);
+	DEBUG("read %s %02x, %d bytes%s req %p %d/%d\n",
+	      ep->ep.name, csr, count,
+	      is_short ? "/S" : "", req, req->req.actual, req->req.length);
+
+	while (likely(count-- != 0)) {
+		u8 byte = (u8) (*fifo & 0xff);
+
+		if (unlikely(bufferspace == 0)) {
+			/* this happens when the driver's buffer
+			 * is smaller than what the host sent.
+			 * discard the extra data.
+			 */
+			if (req->req.status != -EOVERFLOW)
+				printk("%s overflow %d\n", ep->ep.name, count);
+			req->req.status = -EOVERFLOW;
+		} else {
+			*buf++ = byte;
+			bufferspace--;
+		}
+	}
+
+	usb_clear(USB_OUT_CSR1_OUT_PKT_RDY, ep->csr1);
+
+	/* completion */
+	if (is_short || req->req.actual == req->req.length) {
+		done(ep, req, 0);
+		usb_set(USB_OUT_CSR1_FIFO_FLUSH, ep->csr1);
+
+		if (list_empty(&ep->queue))
+			pio_irq_disable(ep_index(ep));
+		return 1;
+	}
+
+	/* finished that packet.  the next one may be waiting... */
+	return 0;
+}
+
+/*
+ *	done - retire a request; caller blocked irqs
+ *  INDEX register is preserved to keep same
+ */
+static void done(struct lh7a40x_ep *ep, struct lh7a40x_request *req, int status)
+{
+	unsigned int stopped = ep->stopped;
+	u32 index;
+
+	DEBUG("%s, %p\n", __FUNCTION__, ep);
+	list_del_init(&req->queue);
+
+	if (likely(req->req.status == -EINPROGRESS))
+		req->req.status = status;
+	else
+		status = req->req.status;
+
+	if (status && status != -ESHUTDOWN)
+		DEBUG("complete %s req %p stat %d len %u/%u\n",
+		      ep->ep.name, &req->req, status,
+		      req->req.actual, req->req.length);
+
+	/* don't modify queue heads during completion callback */
+	ep->stopped = 1;
+	/* Read current index (completion may modify it) */
+	index = usb_read(USB_INDEX);
+
+	spin_unlock(&ep->dev->lock);
+	req->req.complete(&ep->ep, &req->req);
+	spin_lock(&ep->dev->lock);
+
+	/* Restore index */
+	usb_set_index(index);
+	ep->stopped = stopped;
+}
+
+/** Enable EP interrupt */
+static void pio_irq_enable(int ep)
+{
+	DEBUG("%s: %d\n", __FUNCTION__, ep);
+
+	switch (ep) {
+	case 1:
+		usb_set(USB_IN_INT_EP1, USB_IN_INT_EN);
+		break;
+	case 2:
+		usb_set(USB_OUT_INT_EP2, USB_OUT_INT_EN);
+		break;
+	case 3:
+		usb_set(USB_IN_INT_EP3, USB_IN_INT_EN);
+		break;
+	default:
+		DEBUG("Unknown endpoint: %d\n", ep);
+		break;
+	}
+}
+
+/** Disable EP interrupt */
+static void pio_irq_disable(int ep)
+{
+	DEBUG("%s: %d\n", __FUNCTION__, ep);
+
+	switch (ep) {
+	case 1:
+		usb_clear(USB_IN_INT_EP1, USB_IN_INT_EN);
+		break;
+	case 2:
+		usb_clear(USB_OUT_INT_EP2, USB_OUT_INT_EN);
+		break;
+	case 3:
+		usb_clear(USB_IN_INT_EP3, USB_IN_INT_EN);
+		break;
+	default:
+		DEBUG("Unknown endpoint: %d\n", ep);
+		break;
+	}
+}
+
+/*
+ * 	nuke - dequeue ALL requests
+ */
+void nuke(struct lh7a40x_ep *ep, int status)
+{
+	struct lh7a40x_request *req;
+
+	DEBUG("%s, %p\n", __FUNCTION__, ep);
+
+	/* Flush FIFO */
+	flush(ep);
+
+	/* called with irqs blocked */
+	while (!list_empty(&ep->queue)) {
+		req = list_entry(ep->queue.next, struct lh7a40x_request, queue);
+		done(ep, req, status);
+	}
+
+	/* Disable IRQ if EP is enabled (has decriptor) */
+	if (ep->desc)
+		pio_irq_disable(ep_index(ep));
+}
+
+/*
+void nuke_all(struct lh7a40x_udc *dev)
+{
+	int n;
+	for(n=0; n<UDC_MAX_ENDPOINTS; n++) {
+		struct lh7a40x_ep *ep = &dev->ep[n];
+		usb_set_index(n);
+		nuke(ep, 0);
+	}
+}*/
+
+/*
+static void flush_all(struct lh7a40x_udc *dev)
+{
+	int n;
+    for (n = 0; n < UDC_MAX_ENDPOINTS; n++)
+    {
+		struct lh7a40x_ep *ep = &dev->ep[n];
+		flush(ep);
+    }
+}
+*/
+
+/** Flush EP
+ * NOTE: INDEX register must be set before this call
+ */
+static void flush(struct lh7a40x_ep *ep)
+{
+	DEBUG("%s, %p\n", __FUNCTION__, ep);
+
+	switch (ep->ep_type) {
+	case ep_control:
+		/* check, by implication c.f. 15.1.2.11 */
+		break;
+
+	case ep_bulk_in:
+	case ep_interrupt:
+		/* if(csr & USB_IN_CSR1_IN_PKT_RDY) */
+		usb_set(USB_IN_CSR1_FIFO_FLUSH, ep->csr1);
+		break;
+
+	case ep_bulk_out:
+		/* if(csr & USB_OUT_CSR1_OUT_PKT_RDY) */
+		usb_set(USB_OUT_CSR1_FIFO_FLUSH, ep->csr1);
+		break;
+	}
+}
+
+/**
+ * lh7a40x_in_epn - handle IN interrupt
+ */
+static void lh7a40x_in_epn(struct lh7a40x_udc *dev, u32 ep_idx, u32 intr)
+{
+	u32 csr;
+	struct lh7a40x_ep *ep = &dev->ep[ep_idx];
+	struct lh7a40x_request *req;
+
+	usb_set_index(ep_idx);
+
+	csr = usb_read(ep->csr1);
+	DEBUG("%s: %d, csr %x\n", __FUNCTION__, ep_idx, csr);
+
+	if (csr & USB_IN_CSR1_SENT_STALL) {
+		DEBUG("USB_IN_CSR1_SENT_STALL\n");
+		usb_set(USB_IN_CSR1_SENT_STALL /*|USB_IN_CSR1_SEND_STALL */ ,
+			ep->csr1);
+		return;
+	}
+
+	if (!ep->desc) {
+		DEBUG("%s: NO EP DESC\n", __FUNCTION__);
+		return;
+	}
+
+	if (list_empty(&ep->queue))
+		req = 0;
+	else
+		req = list_entry(ep->queue.next, struct lh7a40x_request, queue);
+
+	DEBUG("req: %p\n", req);
+
+	if (!req)
+		return;
+
+	write_fifo(ep, req);
+}
+
+/* ********************************************************************************************* */
+/* Bulk OUT (recv)
+ */
+
+static void lh7a40x_out_epn(struct lh7a40x_udc *dev, u32 ep_idx, u32 intr)
+{
+	struct lh7a40x_ep *ep = &dev->ep[ep_idx];
+	struct lh7a40x_request *req;
+
+	DEBUG("%s: %d\n", __FUNCTION__, ep_idx);
+
+	usb_set_index(ep_idx);
+
+	if (ep->desc) {
+		u32 csr;
+		csr = usb_read(ep->csr1);
+
+		while ((csr =
+			usb_read(ep->
+				 csr1)) & (USB_OUT_CSR1_OUT_PKT_RDY |
+					   USB_OUT_CSR1_SENT_STALL)) {
+			DEBUG("%s: %x\n", __FUNCTION__, csr);
+
+			if (csr & USB_OUT_CSR1_SENT_STALL) {
+				DEBUG("%s: stall sent, flush fifo\n",
+				      __FUNCTION__);
+				/* usb_set(USB_OUT_CSR1_FIFO_FLUSH, ep->csr1); */
+				flush(ep);
+			} else if (csr & USB_OUT_CSR1_OUT_PKT_RDY) {
+				if (list_empty(&ep->queue))
+					req = 0;
+				else
+					req =
+					    list_entry(ep->queue.next,
+						       struct lh7a40x_request,
+						       queue);
+
+				if (!req) {
+					printk("%s: NULL REQ %d\n",
+					       __FUNCTION__, ep_idx);
+					flush(ep);
+					break;
+				} else {
+					read_fifo(ep, req);
+				}
+			}
+
+		}
+
+	} else {
+		/* Throw packet away.. */
+		printk("%s: No descriptor?!?\n", __FUNCTION__);
+		flush(ep);
+	}
+}
+
+static void stop_activity(struct lh7a40x_udc *dev,
+			  struct usb_gadget_driver *driver)
+{
+	int i;
+
+	/* don't disconnect drivers more than once */
+	if (dev->gadget.speed == USB_SPEED_UNKNOWN)
+		driver = 0;
+	dev->gadget.speed = USB_SPEED_UNKNOWN;
+
+	/* prevent new request submissions, kill any outstanding requests  */
+	for (i = 0; i < UDC_MAX_ENDPOINTS; i++) {
+		struct lh7a40x_ep *ep = &dev->ep[i];
+		ep->stopped = 1;
+
+		usb_set_index(i);
+		nuke(ep, -ESHUTDOWN);
+	}
+
+	/* report disconnect; the driver is already quiesced */
+	if (driver) {
+		spin_unlock(&dev->lock);
+		driver->disconnect(&dev->gadget);
+		spin_lock(&dev->lock);
+	}
+
+	/* re-init driver-visible data structures */
+	udc_reinit(dev);
+}
+
+/** Handle USB RESET interrupt
+ */
+static void lh7a40x_reset_intr(struct lh7a40x_udc *dev)
+{
+#if 0				/* def CONFIG_ARCH_LH7A404 */
+	/* Does not work always... */
+
+	DEBUG("%s: %d\n", __FUNCTION__, dev->usb_address);
+
+	if (!dev->usb_address) {
+		/*usb_set(USB_RESET_IO, USB_RESET);
+		   mdelay(5);
+		   usb_clear(USB_RESET_IO, USB_RESET); */
+		return;
+	}
+	/* Put the USB controller into reset. */
+	usb_set(USB_RESET_IO, USB_RESET);
+
+	/* Set Device ID to 0 */
+	udc_set_address(dev, 0);
+
+	/* Let PLL2 settle down */
+	mdelay(5);
+
+	/* Release the USB controller from reset */
+	usb_clear(USB_RESET_IO, USB_RESET);
+
+	/* Re-enable UDC */
+	udc_enable(dev);
+
+#endif
+	dev->gadget.speed = USB_SPEED_FULL;
+}
+
+/*
+ *	lh7a40x usb client interrupt handler.
+ */
+static irqreturn_t lh7a40x_udc_irq(int irq, void *_dev, struct pt_regs *r)
+{
+	struct lh7a40x_udc *dev = _dev;
+
+	DEBUG("\n\n");
+
+	spin_lock(&dev->lock);
+
+	for (;;) {
+		u32 intr_in = usb_read(USB_IN_INT);
+		u32 intr_out = usb_read(USB_OUT_INT);
+		u32 intr_int = usb_read(USB_INT);
+
+		/* Test also against enable bits.. (lh7a40x errata).. Sigh.. */
+		u32 in_en = usb_read(USB_IN_INT_EN);
+		u32 out_en = usb_read(USB_OUT_INT_EN);
+
+		if (!intr_out && !intr_in && !intr_int)
+			break;
+
+		DEBUG("%s (on state %s)\n", __FUNCTION__,
+		      state_names[dev->ep0state]);
+		DEBUG("intr_out = %x\n", intr_out);
+		DEBUG("intr_in  = %x\n", intr_in);
+		DEBUG("intr_int = %x\n", intr_int);
+
+		if (intr_in) {
+			usb_write(intr_in, USB_IN_INT);
+
+			if ((intr_in & USB_IN_INT_EP1)
+			    && (in_en & USB_IN_INT_EP1)) {
+				DEBUG("USB_IN_INT_EP1\n");
+				lh7a40x_in_epn(dev, 1, intr_in);
+			}
+			if ((intr_in & USB_IN_INT_EP3)
+			    && (in_en & USB_IN_INT_EP3)) {
+				DEBUG("USB_IN_INT_EP3\n");
+				lh7a40x_in_epn(dev, 3, intr_in);
+			}
+			if (intr_in & USB_IN_INT_EP0) {
+				DEBUG("USB_IN_INT_EP0 (control)\n");
+				lh7a40x_handle_ep0(dev, intr_in);
+			}
+		}
+
+		if (intr_out) {
+			usb_write(intr_out, USB_OUT_INT);
+
+			if ((intr_out & USB_OUT_INT_EP2)
+			    && (out_en & USB_OUT_INT_EP2)) {
+				DEBUG("USB_OUT_INT_EP2\n");
+				lh7a40x_out_epn(dev, 2, intr_out);
+			}
+		}
+
+		if (intr_int) {
+			usb_write(intr_int, USB_INT);
+
+			if (intr_int & USB_INT_RESET_INT) {
+				lh7a40x_reset_intr(dev);
+			}
+
+			if (intr_int & USB_INT_RESUME_INT) {
+				DEBUG("USB resume\n");
+
+				if (dev->gadget.speed != USB_SPEED_UNKNOWN
+				    && dev->driver
+				    && dev->driver->resume
+				    && is_usb_connected()) {
+					dev->driver->resume(&dev->gadget);
+				}
+			}
+
+			if (intr_int & USB_INT_SUSPEND_INT) {
+				DEBUG("USB suspend%s\n",
+				      is_usb_connected()? "" : "+disconnect");
+				if (!is_usb_connected()) {
+					stop_activity(dev, dev->driver);
+				} else if (dev->gadget.speed !=
+					   USB_SPEED_UNKNOWN && dev->driver
+					   && dev->driver->suspend) {
+					dev->driver->suspend(&dev->gadget);
+				}
+			}
+
+		}
+	}
+
+	spin_unlock(&dev->lock);
+
+	return IRQ_HANDLED;
+}
+
+static int lh7a40x_ep_enable(struct usb_ep *_ep,
+			     const struct usb_endpoint_descriptor *desc)
+{
+	struct lh7a40x_ep *ep;
+	struct lh7a40x_udc *dev;
+	unsigned long flags;
+
+	DEBUG("%s, %p\n", __FUNCTION__, _ep);
+
+	ep = container_of(_ep, struct lh7a40x_ep, ep);
+	if (!_ep || !desc || ep->desc || _ep->name == ep0name
+	    || desc->bDescriptorType != USB_DT_ENDPOINT
+	    || ep->bEndpointAddress != desc->bEndpointAddress
+	    || ep_maxpacket(ep) < le16_to_cpu(desc->wMaxPacketSize)) {
+		DEBUG("%s, bad ep or descriptor\n", __FUNCTION__);
+		return -EINVAL;
+	}
+
+	/* xfer types must match, except that interrupt ~= bulk */
+	if (ep->bmAttributes != desc->bmAttributes
+	    && ep->bmAttributes != USB_ENDPOINT_XFER_BULK
+	    && desc->bmAttributes != USB_ENDPOINT_XFER_INT) {
+		DEBUG("%s, %s type mismatch\n", __FUNCTION__, _ep->name);
+		return -EINVAL;
+	}
+
+	/* hardware _could_ do smaller, but driver doesn't */
+	if ((desc->bmAttributes == USB_ENDPOINT_XFER_BULK
+	     && le16_to_cpu(desc->wMaxPacketSize) != ep_maxpacket(ep))
+	    || !desc->wMaxPacketSize) {
+		DEBUG("%s, bad %s maxpacket\n", __FUNCTION__, _ep->name);
+		return -ERANGE;
+	}
+
+	dev = ep->dev;
+	if (!dev->driver || dev->gadget.speed == USB_SPEED_UNKNOWN) {
+		DEBUG("%s, bogus device state\n", __FUNCTION__);
+		return -ESHUTDOWN;
+	}
+
+	spin_lock_irqsave(&ep->dev->lock, flags);
+
+	ep->stopped = 0;
+	ep->desc = desc;
+	ep->pio_irqs = 0;
+	ep->ep.maxpacket = le16_to_cpu(desc->wMaxPacketSize);
+
+	/* Reset halt state (does flush) */
+	lh7a40x_set_halt(_ep, 0);
+
+	spin_unlock_irqrestore(&ep->dev->lock, flags);
+
+	DEBUG("%s: enabled %s\n", __FUNCTION__, _ep->name);
+	return 0;
+}
+
+/** Disable EP
+ *  NOTE: Sets INDEX register
+ */
+static int lh7a40x_ep_disable(struct usb_ep *_ep)
+{
+	struct lh7a40x_ep *ep;
+	unsigned long flags;
+
+	DEBUG("%s, %p\n", __FUNCTION__, _ep);
+
+	ep = container_of(_ep, struct lh7a40x_ep, ep);
+	if (!_ep || !ep->desc) {
+		DEBUG("%s, %s not enabled\n", __FUNCTION__,
+		      _ep ? ep->ep.name : NULL);
+		return -EINVAL;
+	}
+
+	spin_lock_irqsave(&ep->dev->lock, flags);
+
+	usb_set_index(ep_index(ep));
+
+	/* Nuke all pending requests (does flush) */
+	nuke(ep, -ESHUTDOWN);
+
+	/* Disable ep IRQ */
+	pio_irq_disable(ep_index(ep));
+
+	ep->desc = 0;
+	ep->stopped = 1;
+
+	spin_unlock_irqrestore(&ep->dev->lock, flags);
+
+	DEBUG("%s: disabled %s\n", __FUNCTION__, _ep->name);
+	return 0;
+}
+
+static struct usb_request *lh7a40x_alloc_request(struct usb_ep *ep,
+						 int gfp_flags)
+{
+	struct lh7a40x_request *req;
+
+	DEBUG("%s, %p\n", __FUNCTION__, ep);
+
+	req = kmalloc(sizeof *req, gfp_flags);
+	if (!req)
+		return 0;
+
+	memset(req, 0, sizeof *req);
+	INIT_LIST_HEAD(&req->queue);
+
+	return &req->req;
+}
+
+static void lh7a40x_free_request(struct usb_ep *ep, struct usb_request *_req)
+{
+	struct lh7a40x_request *req;
+
+	DEBUG("%s, %p\n", __FUNCTION__, ep);
+
+	req = container_of(_req, struct lh7a40x_request, req);
+	WARN_ON(!list_empty(&req->queue));
+	kfree(req);
+}
+
+static void *lh7a40x_alloc_buffer(struct usb_ep *ep, unsigned bytes,
+				  dma_addr_t * dma, int gfp_flags)
+{
+	char *retval;
+
+	DEBUG("%s (%p, %d, %d)\n", __FUNCTION__, ep, bytes, gfp_flags);
+
+	retval = kmalloc(bytes, gfp_flags & ~(__GFP_DMA | __GFP_HIGHMEM));
+	if (retval)
+		*dma = virt_to_bus(retval);
+	return retval;
+}
+
+static void lh7a40x_free_buffer(struct usb_ep *ep, void *buf, dma_addr_t dma,
+				unsigned bytes)
+{
+	DEBUG("%s, %p\n", __FUNCTION__, ep);
+	kfree(buf);
+}
+
+/** Queue one request
+ *  Kickstart transfer if needed
+ *  NOTE: Sets INDEX register
+ */
+static int lh7a40x_queue(struct usb_ep *_ep, struct usb_request *_req,
+			 int gfp_flags)
+{
+	struct lh7a40x_request *req;
+	struct lh7a40x_ep *ep;
+	struct lh7a40x_udc *dev;
+	unsigned long flags;
+
+	DEBUG("\n\n\n%s, %p\n", __FUNCTION__, _ep);
+
+	req = container_of(_req, struct lh7a40x_request, req);
+	if (unlikely
+	    (!_req || !_req->complete || !_req->buf
+	     || !list_empty(&req->queue))) {
+		DEBUG("%s, bad params\n", __FUNCTION__);
+		return -EINVAL;
+	}
+
+	ep = container_of(_ep, struct lh7a40x_ep, ep);
+	if (unlikely(!_ep || (!ep->desc && ep->ep.name != ep0name))) {
+		DEBUG("%s, bad ep\n", __FUNCTION__);
+		return -EINVAL;
+	}
+
+	dev = ep->dev;
+	if (unlikely(!dev->driver || dev->gadget.speed == USB_SPEED_UNKNOWN)) {
+		DEBUG("%s, bogus device state %p\n", __FUNCTION__, dev->driver);
+		return -ESHUTDOWN;
+	}
+
+	DEBUG("%s queue req %p, len %d buf %p\n", _ep->name, _req, _req->length,
+	      _req->buf);
+
+	spin_lock_irqsave(&dev->lock, flags);
+
+	_req->status = -EINPROGRESS;
+	_req->actual = 0;
+
+	/* kickstart this i/o queue? */
+	DEBUG("Add to %d Q %d %d\n", ep_index(ep), list_empty(&ep->queue),
+	      ep->stopped);
+	if (list_empty(&ep->queue) && likely(!ep->stopped)) {
+		u32 csr;
+
+		if (unlikely(ep_index(ep) == 0)) {
+			/* EP0 */
+			list_add_tail(&req->queue, &ep->queue);
+			lh7a40x_ep0_kick(dev, ep);
+			req = 0;
+		} else if (ep_is_in(ep)) {
+			/* EP1 & EP3 */
+			usb_set_index(ep_index(ep));
+			csr = usb_read(ep->csr1);
+			pio_irq_enable(ep_index(ep));
+			if ((csr & USB_IN_CSR1_FIFO_NOT_EMPTY) == 0) {
+				if (write_fifo(ep, req) == 1)
+					req = 0;
+			}
+		} else {
+			/* EP2 */
+			usb_set_index(ep_index(ep));
+			csr = usb_read(ep->csr1);
+			pio_irq_enable(ep_index(ep));
+			if (!(csr & USB_OUT_CSR1_FIFO_FULL)) {
+				if (read_fifo(ep, req) == 1)
+					req = 0;
+			}
+		}
+	}
+
+	/* pio or dma irq handler advances the queue. */
+	if (likely(req != 0))
+		list_add_tail(&req->queue, &ep->queue);
+
+	spin_unlock_irqrestore(&dev->lock, flags);
+
+	return 0;
+}
+
+/* dequeue JUST ONE request */
+static int lh7a40x_dequeue(struct usb_ep *_ep, struct usb_request *_req)
+{
+	struct lh7a40x_ep *ep;
+	struct lh7a40x_request *req;
+	unsigned long flags;
+
+	DEBUG("%s, %p\n", __FUNCTION__, _ep);
+
+	ep = container_of(_ep, struct lh7a40x_ep, ep);
+	if (!_ep || ep->ep.name == ep0name)
+		return -EINVAL;
+
+	spin_lock_irqsave(&ep->dev->lock, flags);
+
+	/* make sure it's actually queued on this endpoint */
+	list_for_each_entry(req, &ep->queue, queue) {
+		if (&req->req == _req)
+			break;
+	}
+	if (&req->req != _req) {
+		spin_unlock_irqrestore(&ep->dev->lock, flags);
+		return -EINVAL;
+	}
+
+	done(ep, req, -ECONNRESET);
+
+	spin_unlock_irqrestore(&ep->dev->lock, flags);
+	return 0;
+}
+
+/** Halt specific EP
+ *  Return 0 if success
+ *  NOTE: Sets INDEX register to EP !
+ */
+static int lh7a40x_set_halt(struct usb_ep *_ep, int value)
+{
+	struct lh7a40x_ep *ep;
+	unsigned long flags;
+
+	ep = container_of(_ep, struct lh7a40x_ep, ep);
+	if (unlikely(!_ep || (!ep->desc && ep->ep.name != ep0name))) {
+		DEBUG("%s, bad ep\n", __FUNCTION__);
+		return -EINVAL;
+	}
+
+	usb_set_index(ep_index(ep));
+
+	DEBUG("%s, ep %d, val %d\n", __FUNCTION__, ep_index(ep), value);
+
+	spin_lock_irqsave(&ep->dev->lock, flags);
+
+	if (ep_index(ep) == 0) {
+		/* EP0 */
+		usb_set(EP0_SEND_STALL, ep->csr1);
+	} else if (ep_is_in(ep)) {
+		u32 csr = usb_read(ep->csr1);
+		if (value && ((csr & USB_IN_CSR1_FIFO_NOT_EMPTY)
+			      || !list_empty(&ep->queue))) {
+			/*
+			 * Attempts to halt IN endpoints will fail (returning -EAGAIN)
+			 * if any transfer requests are still queued, or if the controller
+			 * FIFO still holds bytes that the host hasn’t collected.
+			 */
+			spin_unlock_irqrestore(&ep->dev->lock, flags);
+			DEBUG
+			    ("Attempt to halt IN endpoint failed (returning -EAGAIN) %d %d\n",
+			     (csr & USB_IN_CSR1_FIFO_NOT_EMPTY),
+			     !list_empty(&ep->queue));
+			return -EAGAIN;
+		}
+		flush(ep);
+		if (value)
+			usb_set(USB_IN_CSR1_SEND_STALL, ep->csr1);
+		else {
+			usb_clear(USB_IN_CSR1_SEND_STALL, ep->csr1);
+			usb_set(USB_IN_CSR1_CLR_DATA_TOGGLE, ep->csr1);
+		}
+
+	} else {
+
+		flush(ep);
+		if (value)
+			usb_set(USB_OUT_CSR1_SEND_STALL, ep->csr1);
+		else {
+			usb_clear(USB_OUT_CSR1_SEND_STALL, ep->csr1);
+			usb_set(USB_OUT_CSR1_CLR_DATA_REG, ep->csr1);
+		}
+	}
+
+	if (value) {
+		ep->stopped = 1;
+	} else {
+		ep->stopped = 0;
+	}
+
+	spin_unlock_irqrestore(&ep->dev->lock, flags);
+
+	DEBUG("%s %s halted\n", _ep->name, value == 0 ? "NOT" : "IS");
+
+	return 0;
+}
+
+/** Return bytes in EP FIFO
+ *  NOTE: Sets INDEX register to EP
+ */
+static int lh7a40x_fifo_status(struct usb_ep *_ep)
+{
+	u32 csr;
+	int count = 0;
+	struct lh7a40x_ep *ep;
+
+	ep = container_of(_ep, struct lh7a40x_ep, ep);
+	if (!_ep) {
+		DEBUG("%s, bad ep\n", __FUNCTION__);
+		return -ENODEV;
+	}
+
+	DEBUG("%s, %d\n", __FUNCTION__, ep_index(ep));
+
+	/* LPD can't report unclaimed bytes from IN fifos */
+	if (ep_is_in(ep))
+		return -EOPNOTSUPP;
+
+	usb_set_index(ep_index(ep));
+
+	csr = usb_read(ep->csr1);
+	if (ep->dev->gadget.speed != USB_SPEED_UNKNOWN ||
+	    csr & USB_OUT_CSR1_OUT_PKT_RDY) {
+		count = usb_read(USB_OUT_FIFO_WC1);
+	}
+
+	return count;
+}
+
+/** Flush EP FIFO
+ *  NOTE: Sets INDEX register to EP
+ */
+static void lh7a40x_fifo_flush(struct usb_ep *_ep)
+{
+	struct lh7a40x_ep *ep;
+
+	ep = container_of(_ep, struct lh7a40x_ep, ep);
+	if (unlikely(!_ep || (!ep->desc && ep->ep.name != ep0name))) {
+		DEBUG("%s, bad ep\n", __FUNCTION__);
+		return;
+	}
+
+	usb_set_index(ep_index(ep));
+	flush(ep);
+}
+
+/****************************************************************/
+/* End Point 0 related functions                                */
+/****************************************************************/
+
+/* return:  0 = still running, 1 = completed, negative = errno */
+static int write_fifo_ep0(struct lh7a40x_ep *ep, struct lh7a40x_request *req)
+{
+	u32 max;
+	unsigned count;
+	int is_last;
+
+	max = ep_maxpacket(ep);
+
+	DEBUG_EP0("%s\n", __FUNCTION__);
+
+	count = write_packet(ep, req, max);
+
+	/* last packet is usually short (or a zlp) */
+	if (unlikely(count != max))
+		is_last = 1;
+	else {
+		if (likely(req->req.length != req->req.actual) || req->req.zero)
+			is_last = 0;
+		else
+			is_last = 1;
+	}
+
+	DEBUG_EP0("%s: wrote %s %d bytes%s %d left %p\n", __FUNCTION__,
+		  ep->ep.name, count,
+		  is_last ? "/L" : "", req->req.length - req->req.actual, req);
+
+	/* requests complete when all IN data is in the FIFO */
+	if (is_last) {
+		done(ep, req, 0);
+		return 1;
+	}
+
+	return 0;
+}
+
+static __inline__ int lh7a40x_fifo_read(struct lh7a40x_ep *ep,
+					unsigned char *cp, int max)
+{
+	int bytes;
+	int count = usb_read(USB_OUT_FIFO_WC1);
+	volatile u32 *fifo = (volatile u32 *)ep->fifo;
+
+	if (count > max)
+		count = max;
+	bytes = count;
+	while (count--)
+		*cp++ = *fifo & 0xFF;
+	return bytes;
+}
+
+static __inline__ void lh7a40x_fifo_write(struct lh7a40x_ep *ep,
+					  unsigned char *cp, int count)
+{
+	volatile u32 *fifo = (volatile u32 *)ep->fifo;
+	DEBUG_EP0("fifo_write: %d %d\n", ep_index(ep), count);
+	while (count--)
+		*fifo = *cp++;
+}
+
+static int read_fifo_ep0(struct lh7a40x_ep *ep, struct lh7a40x_request *req)
+{
+	u32 csr;
+	u8 *buf;
+	unsigned bufferspace, count, is_short;
+	volatile u32 *fifo = (volatile u32 *)ep->fifo;
+
+	DEBUG_EP0("%s\n", __FUNCTION__);
+
+	csr = usb_read(USB_EP0_CSR);
+	if (!(csr & USB_OUT_CSR1_OUT_PKT_RDY))
+		return 0;
+
+	buf = req->req.buf + req->req.actual;
+	prefetchw(buf);
+	bufferspace = req->req.length - req->req.actual;
+
+	/* read all bytes from this packet */
+	if (likely(csr & EP0_OUT_PKT_RDY)) {
+		count = usb_read(USB_OUT_FIFO_WC1);
+		req->req.actual += min(count, bufferspace);
+	} else			/* zlp */
+		count = 0;
+
+	is_short = (count < ep->ep.maxpacket);
+	DEBUG_EP0("read %s %02x, %d bytes%s req %p %d/%d\n",
+		  ep->ep.name, csr, count,
+		  is_short ? "/S" : "", req, req->req.actual, req->req.length);
+
+	while (likely(count-- != 0)) {
+		u8 byte = (u8) (*fifo & 0xff);
+
+		if (unlikely(bufferspace == 0)) {
+			/* this happens when the driver's buffer
+			 * is smaller than what the host sent.
+			 * discard the extra data.
+			 */
+			if (req->req.status != -EOVERFLOW)
+				DEBUG_EP0("%s overflow %d\n", ep->ep.name,
+					  count);
+			req->req.status = -EOVERFLOW;
+		} else {
+			*buf++ = byte;
+			bufferspace--;
+		}
+	}
+
+	/* completion */
+	if (is_short || req->req.actual == req->req.length) {
+		done(ep, req, 0);
+		return 1;
+	}
+
+	/* finished that packet.  the next one may be waiting... */
+	return 0;
+}
+
+/**
+ * udc_set_address - set the USB address for this device
+ * @address:
+ *
+ * Called from control endpoint function after it decodes a set address setup packet.
+ */
+static void udc_set_address(struct lh7a40x_udc *dev, unsigned char address)
+{
+	DEBUG_EP0("%s: %d\n", __FUNCTION__, address);
+	/* c.f. 15.1.2.2 Table 15-4 address will be used after DATA_END is set */
+	dev->usb_address = address;
+	usb_set((address & USB_FA_FUNCTION_ADDR), USB_FA);
+	usb_set(USB_FA_ADDR_UPDATE | (address & USB_FA_FUNCTION_ADDR), USB_FA);
+	/* usb_read(USB_FA); */
+}
+
+/*
+ * DATA_STATE_RECV (OUT_PKT_RDY)
+ *      - if error
+ *              set EP0_CLR_OUT | EP0_DATA_END | EP0_SEND_STALL bits
+ *      - else
+ *              set EP0_CLR_OUT bit
+ 				if last set EP0_DATA_END bit
+ */
+static void lh7a40x_ep0_out(struct lh7a40x_udc *dev, u32 csr)
+{
+	struct lh7a40x_request *req;
+	struct lh7a40x_ep *ep = &dev->ep[0];
+	int ret;
+
+	DEBUG_EP0("%s: %x\n", __FUNCTION__, csr);
+
+	if (list_empty(&ep->queue))
+		req = 0;
+	else
+		req = list_entry(ep->queue.next, struct lh7a40x_request, queue);
+
+	if (req) {
+
+		if (req->req.length == 0) {
+			DEBUG_EP0("ZERO LENGTH OUT!\n");
+			usb_set((EP0_CLR_OUT | EP0_DATA_END), USB_EP0_CSR);
+			dev->ep0state = WAIT_FOR_SETUP;
+			return;
+		}
+		ret = read_fifo_ep0(ep, req);
+		if (ret) {
+			/* Done! */
+			DEBUG_EP0("%s: finished, waiting for status\n",
+				  __FUNCTION__);
+
+			usb_set((EP0_CLR_OUT | EP0_DATA_END), USB_EP0_CSR);
+			dev->ep0state = WAIT_FOR_SETUP;
+		} else {
+			/* Not done yet.. */
+			DEBUG_EP0("%s: not finished\n", __FUNCTION__);
+			usb_set(EP0_CLR_OUT, USB_EP0_CSR);
+		}
+	} else {
+		DEBUG_EP0("NO REQ??!\n");
+	}
+}
+
+/*
+ * DATA_STATE_XMIT
+ */
+static int lh7a40x_ep0_in(struct lh7a40x_udc *dev, u32 csr)
+{
+	struct lh7a40x_request *req;
+	struct lh7a40x_ep *ep = &dev->ep[0];
+	int ret, need_zlp = 0;
+
+	DEBUG_EP0("%s: %x\n", __FUNCTION__, csr);
+
+	if (list_empty(&ep->queue))
+		req = 0;
+	else
+		req = list_entry(ep->queue.next, struct lh7a40x_request, queue);
+
+	if (!req) {
+		DEBUG_EP0("%s: NULL REQ\n", __FUNCTION__);
+		return 0;
+	}
+
+	if (req->req.length == 0) {
+
+		usb_set((EP0_IN_PKT_RDY | EP0_DATA_END), USB_EP0_CSR);
+		dev->ep0state = WAIT_FOR_SETUP;
+		return 1;
+	}
+
+	if (req->req.length - req->req.actual == EP0_PACKETSIZE) {
+		/* Next write will end with the packet size, */
+		/* so we need Zero-length-packet */
+		need_zlp = 1;
+	}
+
+	ret = write_fifo_ep0(ep, req);
+
+	if (ret == 1 && !need_zlp) {
+		/* Last packet */
+		DEBUG_EP0("%s: finished, waiting for status\n", __FUNCTION__);
+
+		usb_set((EP0_IN_PKT_RDY | EP0_DATA_END), USB_EP0_CSR);
+		dev->ep0state = WAIT_FOR_SETUP;
+	} else {
+		DEBUG_EP0("%s: not finished\n", __FUNCTION__);
+		usb_set(EP0_IN_PKT_RDY, USB_EP0_CSR);
+	}
+
+	if (need_zlp) {
+		DEBUG_EP0("%s: Need ZLP!\n", __FUNCTION__);
+		usb_set(EP0_IN_PKT_RDY, USB_EP0_CSR);
+		dev->ep0state = DATA_STATE_NEED_ZLP;
+	}
+
+	return 1;
+}
+
+static int lh7a40x_handle_get_status(struct lh7a40x_udc *dev,
+				     struct usb_ctrlrequest *ctrl)
+{
+	struct lh7a40x_ep *ep0 = &dev->ep[0];
+	struct lh7a40x_ep *qep;
+	int reqtype = (ctrl->bRequestType & USB_RECIP_MASK);
+	u16 val = 0;
+
+	if (reqtype == USB_RECIP_INTERFACE) {
+		/* This is not supported.
+		 * And according to the USB spec, this one does nothing..
+		 * Just return 0
+		 */
+		DEBUG_SETUP("GET_STATUS: USB_RECIP_INTERFACE\n");
+	} else if (reqtype == USB_RECIP_DEVICE) {
+		DEBUG_SETUP("GET_STATUS: USB_RECIP_DEVICE\n");
+		val |= (1 << 0);	/* Self powered */
+		/*val |= (1<<1); *//* Remote wakeup */
+	} else if (reqtype == USB_RECIP_ENDPOINT) {
+		int ep_num = (ctrl->wIndex & ~USB_DIR_IN);
+
+		DEBUG_SETUP
+		    ("GET_STATUS: USB_RECIP_ENDPOINT (%d), ctrl->wLength = %d\n",
+		     ep_num, ctrl->wLength);
+
+		if (ctrl->wLength > 2 || ep_num > 3)
+			return -EOPNOTSUPP;
+
+		qep = &dev->ep[ep_num];
+		if (ep_is_in(qep) != ((ctrl->wIndex & USB_DIR_IN) ? 1 : 0)
+		    && ep_index(qep) != 0) {
+			return -EOPNOTSUPP;
+		}
+
+		usb_set_index(ep_index(qep));
+
+		/* Return status on next IN token */
+		switch (qep->ep_type) {
+		case ep_control:
+			val =
+			    (usb_read(qep->csr1) & EP0_SEND_STALL) ==
+			    EP0_SEND_STALL;
+			break;
+		case ep_bulk_in:
+		case ep_interrupt:
+			val =
+			    (usb_read(qep->csr1) & USB_IN_CSR1_SEND_STALL) ==
+			    USB_IN_CSR1_SEND_STALL;
+			break;
+		case ep_bulk_out:
+			val =
+			    (usb_read(qep->csr1) & USB_OUT_CSR1_SEND_STALL) ==
+			    USB_OUT_CSR1_SEND_STALL;
+			break;
+		}
+
+		/* Back to EP0 index */
+		usb_set_index(0);
+
+		DEBUG_SETUP("GET_STATUS, ep: %d (%x), val = %d\n", ep_num,
+			    ctrl->wIndex, val);
+	} else {
+		DEBUG_SETUP("Unknown REQ TYPE: %d\n", reqtype);
+		return -EOPNOTSUPP;
+	}
+
+	/* Clear "out packet ready" */
+	usb_set((EP0_CLR_OUT), USB_EP0_CSR);
+	/* Put status to FIFO */
+	lh7a40x_fifo_write(ep0, (u8 *) & val, sizeof(val));
+	/* Issue "In packet ready" */
+	usb_set((EP0_IN_PKT_RDY | EP0_DATA_END), USB_EP0_CSR);
+
+	return 0;
+}
+
+/*
+ * WAIT_FOR_SETUP (OUT_PKT_RDY)
+ *      - read data packet from EP0 FIFO
+ *      - decode command
+ *      - if error
+ *              set EP0_CLR_OUT | EP0_DATA_END | EP0_SEND_STALL bits
+ *      - else
+ *              set EP0_CLR_OUT | EP0_DATA_END bits
+ */
+static void lh7a40x_ep0_setup(struct lh7a40x_udc *dev, u32 csr)
+{
+	struct lh7a40x_ep *ep = &dev->ep[0];
+	struct usb_ctrlrequest ctrl;
+	int i, bytes, is_in;
+
+	DEBUG_SETUP("%s: %x\n", __FUNCTION__, csr);
+
+	/* Nuke all previous transfers */
+	nuke(ep, -EPROTO);
+
+	/* read control req from fifo (8 bytes) */
+	bytes = lh7a40x_fifo_read(ep, (unsigned char *)&ctrl, 8);
+
+	DEBUG_SETUP("Read CTRL REQ %d bytes\n", bytes);
+	DEBUG_SETUP("CTRL.bRequestType = %d (is_in %d)\n", ctrl.bRequestType,
+		    ctrl.bRequestType == USB_DIR_IN);
+	DEBUG_SETUP("CTRL.bRequest = %d\n", ctrl.bRequest);
+	DEBUG_SETUP("CTRL.wLength = %d\n", ctrl.wLength);
+	DEBUG_SETUP("CTRL.wValue = %d (%d)\n", ctrl.wValue, ctrl.wValue >> 8);
+	DEBUG_SETUP("CTRL.wIndex = %d\n", ctrl.wIndex);
+
+	/* Set direction of EP0 */
+	if (likely(ctrl.bRequestType & USB_DIR_IN)) {
+		ep->bEndpointAddress |= USB_DIR_IN;
+		is_in = 1;
+	} else {
+		ep->bEndpointAddress &= ~USB_DIR_IN;
+		is_in = 0;
+	}
+
+	dev->req_pending = 1;
+
+	/* Handle some SETUP packets ourselves */
+	switch (ctrl.bRequest) {
+	case USB_REQ_SET_ADDRESS:
+		if (ctrl.bRequestType != (USB_TYPE_STANDARD | USB_RECIP_DEVICE))
+			break;
+
+		DEBUG_SETUP("USB_REQ_SET_ADDRESS (%d)\n", ctrl.wValue);
+		udc_set_address(dev, ctrl.wValue);
+		usb_set((EP0_CLR_OUT | EP0_DATA_END), USB_EP0_CSR);
+		return;
+
+	case USB_REQ_GET_STATUS:{
+			if (lh7a40x_handle_get_status(dev, &ctrl) == 0)
+				return;
+
+	case USB_REQ_CLEAR_FEATURE:
+	case USB_REQ_SET_FEATURE:
+			if (ctrl.bRequestType == USB_RECIP_ENDPOINT) {
+				struct lh7a40x_ep *qep;
+				int ep_num = (ctrl.wIndex & 0x0f);
+
+				/* Support only HALT feature */
+				if (ctrl.wValue != 0 || ctrl.wLength != 0
+				    || ep_num > 3 || ep_num < 1)
+					break;
+
+				qep = &dev->ep[ep_num];
+				if (ctrl.bRequest == USB_REQ_SET_FEATURE) {
+					DEBUG_SETUP("SET_FEATURE (%d)\n",
+						    ep_num);
+					lh7a40x_set_halt(&qep->ep, 1);
+				} else {
+					DEBUG_SETUP("CLR_FEATURE (%d)\n",
+						    ep_num);
+					lh7a40x_set_halt(&qep->ep, 0);
+				}
+				usb_set_index(0);
+
+				/* Reply with a ZLP on next IN token */
+				usb_set((EP0_CLR_OUT | EP0_DATA_END),
+					USB_EP0_CSR);
+				return;
+			}
+			break;
+		}
+
+	default:
+		break;
+	}
+
+	if (likely(dev->driver)) {
+		/* device-2-host (IN) or no data setup command, process immediately */
+		spin_unlock(&dev->lock);
+		i = dev->driver->setup(&dev->gadget, &ctrl);
+		spin_lock(&dev->lock);
+
+		if (i < 0) {
+			/* setup processing failed, force stall */
+			DEBUG_SETUP
+			    ("  --> ERROR: gadget setup FAILED (stalling), setup returned %d\n",
+			     i);
+			usb_set_index(0);
+			usb_set((EP0_CLR_OUT | EP0_DATA_END | EP0_SEND_STALL),
+				USB_EP0_CSR);
+
+			/* ep->stopped = 1; */
+			dev->ep0state = WAIT_FOR_SETUP;
+		}
+	}
+}
+
+/*
+ * DATA_STATE_NEED_ZLP
+ */
+static void lh7a40x_ep0_in_zlp(struct lh7a40x_udc *dev, u32 csr)
+{
+	DEBUG_EP0("%s: %x\n", __FUNCTION__, csr);
+
+	/* c.f. Table 15-14 */
+	usb_set((EP0_IN_PKT_RDY | EP0_DATA_END), USB_EP0_CSR);
+	dev->ep0state = WAIT_FOR_SETUP;
+}
+
+/*
+ * handle ep0 interrupt
+ */
+static void lh7a40x_handle_ep0(struct lh7a40x_udc *dev, u32 intr)
+{
+	struct lh7a40x_ep *ep = &dev->ep[0];
+	u32 csr;
+
+	/* Set index 0 */
+	usb_set_index(0);
+ 	csr = usb_read(USB_EP0_CSR);
+
+	DEBUG_EP0("%s: csr = %x\n", __FUNCTION__, csr);
+
+	/*
+	 * For overview of what we should be doing see c.f. Chapter 18.1.2.4
+	 * We will follow that outline here modified by our own global state
+	 * indication which provides hints as to what we think should be
+	 * happening..
+	 */
+
+	/*
+	 * if SENT_STALL is set
+	 *      - clear the SENT_STALL bit
+	 */
+	if (csr & EP0_SENT_STALL) {
+		DEBUG_EP0("%s: EP0_SENT_STALL is set: %x\n", __FUNCTION__, csr);
+		usb_clear((EP0_SENT_STALL | EP0_SEND_STALL), USB_EP0_CSR);
+		nuke(ep, -ECONNABORTED);
+		dev->ep0state = WAIT_FOR_SETUP;
+		return;
+	}
+
+	/*
+	 * if a transfer is in progress && IN_PKT_RDY and OUT_PKT_RDY are clear
+	 *      - fill EP0 FIFO
+	 *      - if last packet
+	 *      -       set IN_PKT_RDY | DATA_END
+	 *      - else
+	 *              set IN_PKT_RDY
+	 */
+	if (!(csr & (EP0_IN_PKT_RDY | EP0_OUT_PKT_RDY))) {
+		DEBUG_EP0("%s: IN_PKT_RDY and OUT_PKT_RDY are clear\n",
+			  __FUNCTION__);
+
+		switch (dev->ep0state) {
+		case DATA_STATE_XMIT:
+			DEBUG_EP0("continue with DATA_STATE_XMIT\n");
+			lh7a40x_ep0_in(dev, csr);
+			return;
+		case DATA_STATE_NEED_ZLP:
+			DEBUG_EP0("continue with DATA_STATE_NEED_ZLP\n");
+			lh7a40x_ep0_in_zlp(dev, csr);
+			return;
+		default:
+			/* Stall? */
+			DEBUG_EP0("Odd state!! state = %s\n",
+				  state_names[dev->ep0state]);
+			dev->ep0state = WAIT_FOR_SETUP;
+			/* nuke(ep, 0); */
+			/* usb_set(EP0_SEND_STALL, ep->csr1); */
+			break;
+		}
+	}
+
+	/*
+	 * if SETUP_END is set
+	 *      - abort the last transfer
+	 *      - set SERVICED_SETUP_END_BIT
+	 */
+	if (csr & EP0_SETUP_END) {
+		DEBUG_EP0("%s: EP0_SETUP_END is set: %x\n", __FUNCTION__, csr);
+
+		usb_set(EP0_CLR_SETUP_END, USB_EP0_CSR);
+
+		nuke(ep, 0);
+		dev->ep0state = WAIT_FOR_SETUP;
+	}
+
+	/*
+	 * if EP0_OUT_PKT_RDY is set
+	 *      - read data packet from EP0 FIFO
+	 *      - decode command
+	 *      - if error
+	 *              set SERVICED_OUT_PKT_RDY | DATA_END bits | SEND_STALL
+	 *      - else
+	 *              set SERVICED_OUT_PKT_RDY | DATA_END bits
+	 */
+	if (csr & EP0_OUT_PKT_RDY) {
+
+		DEBUG_EP0("%s: EP0_OUT_PKT_RDY is set: %x\n", __FUNCTION__,
+			  csr);
+
+		switch (dev->ep0state) {
+		case WAIT_FOR_SETUP:
+			DEBUG_EP0("WAIT_FOR_SETUP\n");
+			lh7a40x_ep0_setup(dev, csr);
+			break;
+
+		case DATA_STATE_RECV:
+			DEBUG_EP0("DATA_STATE_RECV\n");
+			lh7a40x_ep0_out(dev, csr);
+			break;
+
+		default:
+			/* send stall? */
+			DEBUG_EP0("strange state!! 2. send stall? state = %d\n",
+				  dev->ep0state);
+			break;
+		}
+	}
+}
+
+static void lh7a40x_ep0_kick(struct lh7a40x_udc *dev, struct lh7a40x_ep *ep)
+{
+	u32 csr;
+
+	usb_set_index(0);
+	csr = usb_read(USB_EP0_CSR);
+
+	DEBUG_EP0("%s: %x\n", __FUNCTION__, csr);
+
+	/* Clear "out packet ready" */
+	usb_set(EP0_CLR_OUT, USB_EP0_CSR);
+
+	if (ep_is_in(ep)) {
+		dev->ep0state = DATA_STATE_XMIT;
+		lh7a40x_ep0_in(dev, csr);
+	} else {
+		dev->ep0state = DATA_STATE_RECV;
+		lh7a40x_ep0_out(dev, csr);
+	}
+}
+
+/* ---------------------------------------------------------------------------
+ * 	device-scoped parts of the api to the usb controller hardware
+ * ---------------------------------------------------------------------------
+ */
+
+static int lh7a40x_udc_get_frame(struct usb_gadget *_gadget)
+{
+	u32 frame1 = usb_read(USB_FRM_NUM1);	/* Least significant 8 bits */
+	u32 frame2 = usb_read(USB_FRM_NUM2);	/* Most significant 3 bits */
+	DEBUG("%s, %p\n", __FUNCTION__, _gadget);
+	return ((frame2 & 0x07) << 8) | (frame1 & 0xff);
+}
+
+static int lh7a40x_udc_wakeup(struct usb_gadget *_gadget)
+{
+	/* host may not have enabled remote wakeup */
+	/*if ((UDCCS0 & UDCCS0_DRWF) == 0)
+	   return -EHOSTUNREACH;
+	   udc_set_mask_UDCCR(UDCCR_RSM); */
+	return -ENOTSUPP;
+}
+
+static const struct usb_gadget_ops lh7a40x_udc_ops = {
+	.get_frame = lh7a40x_udc_get_frame,
+	.wakeup = lh7a40x_udc_wakeup,
+	/* current versions must always be self-powered */
+};
+
+static void nop_release(struct device *dev)
+{
+	DEBUG("%s %s\n", __FUNCTION__, dev->bus_id);
+}
+
+static struct lh7a40x_udc memory = {
+	.usb_address = 0,
+
+	.gadget = {
+		   .ops = &lh7a40x_udc_ops,
+		   .ep0 = &memory.ep[0].ep,
+		   .name = driver_name,
+		   .dev = {
+			   .bus_id = "gadget",
+			   .release = nop_release,
+			   },
+		   },
+
+	/* control endpoint */
+	.ep[0] = {
+		  .ep = {
+			 .name = ep0name,
+			 .ops = &lh7a40x_ep_ops,
+			 .maxpacket = EP0_PACKETSIZE,
+			 },
+		  .dev = &memory,
+
+		  .bEndpointAddress = 0,
+		  .bmAttributes = 0,
+
+		  .ep_type = ep_control,
+		  .fifo = io_p2v(USB_EP0_FIFO),
+		  .csr1 = USB_EP0_CSR,
+		  .csr2 = USB_EP0_CSR,
+		  },
+
+	/* first group of endpoints */
+	.ep[1] = {
+		  .ep = {
+			 .name = "ep1in-bulk",
+			 .ops = &lh7a40x_ep_ops,
+			 .maxpacket = 64,
+			 },
+		  .dev = &memory,
+
+		  .bEndpointAddress = USB_DIR_IN | 1,
+		  .bmAttributes = USB_ENDPOINT_XFER_BULK,
+
+		  .ep_type = ep_bulk_in,
+		  .fifo = io_p2v(USB_EP1_FIFO),
+		  .csr1 = USB_IN_CSR1,
+		  .csr2 = USB_IN_CSR2,
+		  },
+
+	.ep[2] = {
+		  .ep = {
+			 .name = "ep2out-bulk",
+			 .ops = &lh7a40x_ep_ops,
+			 .maxpacket = 64,
+			 },
+		  .dev = &memory,
+
+		  .bEndpointAddress = 2,
+		  .bmAttributes = USB_ENDPOINT_XFER_BULK,
+
+		  .ep_type = ep_bulk_out,
+		  .fifo = io_p2v(USB_EP2_FIFO),
+		  .csr1 = USB_OUT_CSR1,
+		  .csr2 = USB_OUT_CSR2,
+		  },
+
+	.ep[3] = {
+		  .ep = {
+			 .name = "ep3in-int",
+			 .ops = &lh7a40x_ep_ops,
+			 .maxpacket = 64,
+			 },
+		  .dev = &memory,
+
+		  .bEndpointAddress = USB_DIR_IN | 3,
+		  .bmAttributes = USB_ENDPOINT_XFER_INT,
+
+		  .ep_type = ep_interrupt,
+		  .fifo = io_p2v(USB_EP3_FIFO),
+		  .csr1 = USB_IN_CSR1,
+		  .csr2 = USB_IN_CSR2,
+		  },
+};
+
+/*
+ * 	probe - binds to the platform device
+ */
+static int lh7a40x_udc_probe(struct device *_dev)
+{
+	struct lh7a40x_udc *dev = &memory;
+	int retval;
+
+	DEBUG("%s: %p\n", __FUNCTION__, _dev);
+
+	spin_lock_init(&dev->lock);
+	dev->dev = _dev;
+
+	device_initialize(&dev->gadget.dev);
+	dev->gadget.dev.parent = _dev;
+
+	the_controller = dev;
+	dev_set_drvdata(_dev, dev);
+
+	udc_disable(dev);
+	udc_reinit(dev);
+
+	/* irq setup after old hardware state is cleaned up */
+	retval =
+	    request_irq(IRQ_USBINTR, lh7a40x_udc_irq, SA_INTERRUPT, driver_name,
+			dev);
+	if (retval != 0) {
+		DEBUG(KERN_ERR "%s: can't get irq %i, err %d\n", driver_name,
+		      IRQ_USBINTR, retval);
+		return -EBUSY;
+	}
+
+	create_proc_files();
+
+	return retval;
+}
+
+static int lh7a40x_udc_remove(struct device *_dev)
+{
+	struct lh7a40x_udc *dev = _dev->driver_data;
+
+	DEBUG("%s: %p\n", __FUNCTION__, dev);
+
+	udc_disable(dev);
+	remove_proc_files();
+	usb_gadget_unregister_driver(dev->driver);
+
+	free_irq(IRQ_USBINTR, dev);
+
+	dev_set_drvdata(_dev, 0);
+
+	the_controller = 0;
+
+	return 0;
+}
+
+/*-------------------------------------------------------------------------*/
+
+static struct device_driver udc_driver = {
+	.name = (char *)driver_name,
+	.bus = &platform_bus_type,
+	.probe = lh7a40x_udc_probe,
+	.remove = lh7a40x_udc_remove
+	    /* FIXME power management support */
+	    /* .suspend = ... disable UDC */
+	    /* .resume = ... re-enable UDC */
+};
+
+static int __init udc_init(void)
+{
+	DEBUG("%s: %s version %s\n", __FUNCTION__, driver_name, DRIVER_VERSION);
+	return driver_register(&udc_driver);
+}
+
+static void __exit udc_exit(void)
+{
+	driver_unregister(&udc_driver);
+}
+
+module_init(udc_init);
+module_exit(udc_exit);
+
+MODULE_DESCRIPTION(DRIVER_DESC);
+MODULE_AUTHOR("Mikko Lahteenmaki, Bo Henriksen");
+MODULE_LICENSE("GPL");
diff -Nru a/drivers/usb/gadget/lh7a40x_udc.h b/drivers/usb/gadget/lh7a40x_udc.h
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/drivers/usb/gadget/lh7a40x_udc.h	2004-10-18 14:57:24 -07:00
@@ -0,0 +1,261 @@
+/*
+ * linux/drivers/usb/gadget/lh7a40x_udc.h
+ * Sharp LH7A40x on-chip full speed USB device controllers
+ *
+ * Copyright (C) 2004 Mikko Lahteenmaki, Nordic ID
+ * Copyright (C) 2004 Bo Henriksen, Nordic ID
+ *
+ * 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
+ *
+ */
+
+#ifndef __LH7A40X_H_
+#define __LH7A40X_H_
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/ioport.h>
+#include <linux/types.h>
+#include <linux/version.h>
+#include <linux/errno.h>
+#include <linux/delay.h>
+#include <linux/sched.h>
+#include <linux/slab.h>
+#include <linux/init.h>
+#include <linux/timer.h>
+#include <linux/list.h>
+#include <linux/interrupt.h>
+#include <linux/proc_fs.h>
+#include <linux/mm.h>
+#include <linux/device.h>
+#include <linux/dma-mapping.h>
+
+#include <asm/byteorder.h>
+#include <asm/dma.h>
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/system.h>
+#include <asm/unaligned.h>
+#include <asm/hardware.h>
+
+#include <linux/usb_ch9.h>
+#include <linux/usb_gadget.h>
+
+/*
+ * Memory map
+ */
+
+#define USB_FA					0x80000200	// function address register
+#define USB_PM					0x80000204	// power management register
+
+#define USB_IN_INT				0x80000208	// IN interrupt register bank (EP0-EP3)
+#define USB_OUT_INT				0x80000210	// OUT interrupt register bank (EP2)
+#define USB_INT					0x80000218	// interrupt register bank
+
+#define USB_IN_INT_EN			0x8000021C	// IN interrupt enable register bank
+#define USB_OUT_INT_EN			0x80000224	// OUT interrupt enable register bank
+#define USB_INT_EN				0x8000022C	// USB interrupt enable register bank
+
+#define USB_FRM_NUM1			0x80000230	// Frame number1 register
+#define USB_FRM_NUM2			0x80000234	// Frame number2 register
+#define USB_INDEX				0x80000238	// index register
+
+#define USB_IN_MAXP				0x80000240	// IN MAXP register
+#define USB_IN_CSR1				0x80000244	// IN CSR1 register/EP0 CSR register
+#define USB_EP0_CSR				0x80000244	// IN CSR1 register/EP0 CSR register
+#define USB_IN_CSR2				0x80000248	// IN CSR2 register
+#define USB_OUT_MAXP			0x8000024C	// OUT MAXP register
+
+#define USB_OUT_CSR1			0x80000250	// OUT CSR1 register
+#define USB_OUT_CSR2			0x80000254	// OUT CSR2 register
+#define USB_OUT_FIFO_WC1		0x80000258	// OUT FIFO write count1 register
+#define USB_OUT_FIFO_WC2		0x8000025C	// OUT FIFO write count2 register
+
+#define USB_RESET				0x8000044C	// USB reset register
+
+#define	USB_EP0_FIFO			0x80000280
+#define	USB_EP1_FIFO			0x80000284
+#define	USB_EP2_FIFO			0x80000288
+#define	USB_EP3_FIFO			0x8000028c
+
+/*
+ * USB reset register
+ */
+#define USB_RESET_APB			(1<<1)	//resets USB APB control side WRITE
+#define USB_RESET_IO			(1<<0)	//resets USB IO side WRITE
+
+/*
+ * USB function address register
+ */
+#define USB_FA_ADDR_UPDATE		(1<<7)
+#define USB_FA_FUNCTION_ADDR	(0x7F)
+
+/*
+ * Power Management register
+ */
+#define PM_USB_DCP				(1<<5)
+#define PM_USB_ENABLE			(1<<4)
+#define PM_USB_RESET			(1<<3)
+#define PM_UC_RESUME			(1<<2)
+#define PM_SUSPEND_MODE			(1<<1)
+#define PM_ENABLE_SUSPEND		(1<<0)
+
+/*
+ * IN interrupt register
+ */
+#define USB_IN_INT_EP3				(1<<3)
+#define USB_IN_INT_EP1				(1<<1)
+#define USB_IN_INT_EP0				(1<<0)
+
+/*
+ * OUT interrupt register
+ */
+#define USB_OUT_INT_EP2				(1<<2)
+
+/*
+ * USB interrupt register
+ */
+#define USB_INT_RESET_INT			(1<<2)
+#define USB_INT_RESUME_INT			(1<<1)
+#define USB_INT_SUSPEND_INT			(1<<0)
+
+/*
+ * USB interrupt enable register
+ */
+#define USB_INT_EN_USB_RESET_INTER		(1<<2)
+#define USB_INT_EN_RESUME_INTER			(1<<1)
+#define USB_INT_EN_SUSPEND_INTER		(1<<0)
+
+/*
+ * INCSR1 register
+ */
+#define USB_IN_CSR1_CLR_DATA_TOGGLE		(1<<6)
+#define USB_IN_CSR1_SENT_STALL			(1<<5)
+#define USB_IN_CSR1_SEND_STALL			(1<<4)
+#define USB_IN_CSR1_FIFO_FLUSH			(1<<3)
+#define USB_IN_CSR1_FIFO_NOT_EMPTY		(1<<1)
+#define USB_IN_CSR1_IN_PKT_RDY			(1<<0)
+
+/*
+ * INCSR2 register
+ */
+#define USB_IN_CSR2_AUTO_SET			(1<<7)
+#define USB_IN_CSR2_USB_DMA_EN			(1<<4)
+
+/*
+ * OUT CSR1 register
+ */
+#define USB_OUT_CSR1_CLR_DATA_REG		(1<<7)
+#define USB_OUT_CSR1_SENT_STALL			(1<<6)
+#define USB_OUT_CSR1_SEND_STALL			(1<<5)
+#define USB_OUT_CSR1_FIFO_FLUSH			(1<<4)
+#define USB_OUT_CSR1_FIFO_FULL			(1<<1)
+#define USB_OUT_CSR1_OUT_PKT_RDY		(1<<0)
+
+/*
+ * OUT CSR2 register
+ */
+#define USB_OUT_CSR2_AUTO_CLR			(1<<7)
+#define USB_OUT_CSR2_USB_DMA_EN			(1<<4)
+
+/*
+ * EP0 CSR
+ */
+#define EP0_CLR_SETUP_END		(1<<7)	/* Clear "Setup Ends" Bit (w) */
+#define EP0_CLR_OUT				(1<<6)	/* Clear "Out packet ready" Bit (w) */
+#define EP0_SEND_STALL			(1<<5)	/* Send STALL Handshake (rw) */
+#define EP0_SETUP_END			(1<<4)	/* Setup Ends (r) */
+
+#define EP0_DATA_END			(1<<3)	/* Data end (rw) */
+#define EP0_SENT_STALL			(1<<2)	/* Sent Stall Handshake (r) */
+#define EP0_IN_PKT_RDY			(1<<1)	/* In packet ready (rw) */
+#define EP0_OUT_PKT_RDY			(1<<0)	/* Out packet ready (r) */
+
+/* general CSR */
+#define OUT_PKT_RDY		(1<<0)
+#define IN_PKT_RDY		(1<<0)
+
+/*
+ * IN/OUT MAXP register
+ */
+#define USB_OUT_MAXP_MAXP			(0xF)
+#define USB_IN_MAXP_MAXP			(0xF)
+
+// Max packet size
+//#define EP0_PACKETSIZE        0x10
+#define EP0_PACKETSIZE  	0x8
+#define EP0_MAXPACKETSIZE  	0x10
+
+#define UDC_MAX_ENDPOINTS       4
+
+#define WAIT_FOR_SETUP          0
+#define DATA_STATE_XMIT         1
+#define DATA_STATE_NEED_ZLP     2
+#define WAIT_FOR_OUT_STATUS     3
+#define DATA_STATE_RECV         4
+
+/* ********************************************************************************************* */
+/* IO
+ */
+
+typedef enum ep_type {
+	ep_control, ep_bulk_in, ep_bulk_out, ep_interrupt
+} ep_type_t;
+
+struct lh7a40x_ep {
+	struct usb_ep ep;
+	struct lh7a40x_udc *dev;
+
+	const struct usb_endpoint_descriptor *desc;
+	struct list_head queue;
+	unsigned long pio_irqs;
+
+	u8 stopped;
+	u8 bEndpointAddress;
+	u8 bmAttributes;
+
+	ep_type_t ep_type;
+	u32 fifo;
+	u32 csr1;
+	u32 csr2;
+};
+
+struct lh7a40x_request {
+	struct usb_request req;
+	struct list_head queue;
+};
+
+struct lh7a40x_udc {
+	struct usb_gadget gadget;
+	struct usb_gadget_driver *driver;
+	struct device *dev;
+	spinlock_t lock;
+
+	int ep0state;
+	struct lh7a40x_ep ep[UDC_MAX_ENDPOINTS];
+
+	unsigned char usb_address;
+
+	unsigned req_pending:1, req_std:1, req_config:1;
+};
+
+extern struct lh7a40x_udc *the_controller;
+
+#define ep_is_in(EP) 		(((EP)->bEndpointAddress&USB_DIR_IN)==USB_DIR_IN)
+#define ep_index(EP) 		((EP)->bEndpointAddress&0xF)
+#define ep_maxpacket(EP) 	((EP)->ep.maxpacket)
+
+#endif
diff -Nru a/drivers/usb/gadget/net2280.c b/drivers/usb/gadget/net2280.c
--- a/drivers/usb/gadget/net2280.c	2004-10-18 14:55:54 -07:00
+++ b/drivers/usb/gadget/net2280.c	2004-10-18 14:55:54 -07:00
@@ -7,13 +7,9 @@
  *
  * CODE STATUS HIGHLIGHTS
  *
- * Used with a gadget driver like "zero.c" this enumerates fine to Windows
- * or Linux hosts; handles disconnect, reconnect, and reset, for full or
- * high speed operation; and passes USB-IF "chapter 9" tests.
- *
- * Handles standard stress loads from the Linux "usbtest" driver, with
- * either DMA (default) or PIO (use_dma=n) used for ep-{a,b,c,d}.  Testing
- * with "ttcp" (and the "ether.c" driver) behaves nicely too.
+ * This driver should work well with most "gadget" drivers, including
+ * the File Storage, Serial, and Ethernet/RNDIS gadget drivers
+ * as well as Gadget Zero and Gadgetfs.
  *
  * DMA is enabled by default.  Drivers using transfer queues might use
  * DMA chaining to remove IRQ latencies between transfers.  (Except when
@@ -257,7 +253,7 @@
 	return 0;
 }
 
-static int handshake (u32 *ptr, u32 mask, u32 done, int usec)
+static int handshake (u32 __iomem *ptr, u32 mask, u32 done, int usec)
 {
 	u32	result;
 
@@ -276,7 +272,7 @@
 
 static struct usb_ep_ops net2280_ep_ops;
 
-static void ep_reset (struct net2280_regs *regs, struct net2280_ep *ep)
+static void ep_reset (struct net2280_regs __iomem *regs, struct net2280_ep *ep)
 {
 	u32		tmp;
 
@@ -307,14 +303,16 @@
 	/* init to our chosen defaults, notably so that we NAK OUT
 	 * packets until the driver queues a read (+note erratum 0112)
 	 */
-	writel (  (1 << SET_NAK_OUT_PACKETS_MODE)
+	tmp = (1 << SET_NAK_OUT_PACKETS_MODE)
 		| (1 << SET_NAK_OUT_PACKETS)
 		| (1 << CLEAR_EP_HIDE_STATUS_PHASE)
-		| (1 << CLEAR_INTERRUPT_MODE)
-		| (1 << CLEAR_CONTROL_STATUS_PHASE_HANDSHAKE)
-		| (1 << CLEAR_ENDPOINT_TOGGLE)
-		| (1 << CLEAR_ENDPOINT_HALT)
-		, &ep->regs->ep_rsp);
+		| (1 << CLEAR_INTERRUPT_MODE);
+
+	if (ep->num != 0) {
+		tmp |= (1 << CLEAR_ENDPOINT_TOGGLE)
+			| (1 << CLEAR_ENDPOINT_HALT);
+	}
+	writel (tmp, &ep->regs->ep_rsp);
 
 	/* scrub most status bits, and flush any fifo state */
 	writel (  (1 << TIMEOUT)
@@ -517,7 +515,7 @@
 static void
 write_fifo (struct net2280_ep *ep, struct usb_request *req)
 {
-	struct net2280_ep_regs	*regs = ep->regs;
+	struct net2280_ep_regs	__iomem *regs = ep->regs;
 	u8			*buf;
 	u32			tmp;
 	unsigned		count, total;
@@ -577,7 +575,8 @@
  */
 static void out_flush (struct net2280_ep *ep)
 {
-	u32	*statp, tmp;
+	u32	__iomem *statp;
+	u32	tmp;
 
 	ASSERT_OUT_NAKING (ep);
 
@@ -610,7 +609,7 @@
 static int
 read_fifo (struct net2280_ep *ep, struct net2280_request *req)
 {
-	struct net2280_ep_regs	*regs = ep->regs;
+	struct net2280_ep_regs	__iomem *regs = ep->regs;
 	u8			*buf = req->req.buf + req->req.actual;
 	unsigned		count, tmp, is_short;
 	unsigned		cleanup = 0, prevent = 0;
@@ -678,7 +677,7 @@
 	}
 	if (count) {
 		tmp = readl (&regs->ep_data);
-		cpu_to_le32s (&tmp);
+		/* LE conversion is implicit here: */
 		do {
 			*buf++ = (u8) tmp;
 			tmp >>= 8;
@@ -737,12 +736,12 @@
 		/* erratum 0116 workaround part 2 (no AUTOSTART) */
 		| (1 << DMA_ENABLE);
 
-static inline void spin_stop_dma (struct net2280_dma_regs *dma)
+static inline void spin_stop_dma (struct net2280_dma_regs __iomem *dma)
 {
 	handshake (&dma->dmactl, (1 << DMA_ENABLE), 0, 50);
 }
 
-static inline void stop_dma (struct net2280_dma_regs *dma)
+static inline void stop_dma (struct net2280_dma_regs __iomem *dma)
 {
 	writel (readl (&dma->dmactl) & ~(1 << DMA_ENABLE), &dma->dmactl);
 	spin_stop_dma (dma);
@@ -750,7 +749,7 @@
 
 static void start_queue (struct net2280_ep *ep, u32 dmactl, u32 td_dma)
 {
-	struct net2280_dma_regs	*dma = ep->dma;
+	struct net2280_dma_regs	__iomem *dma = ep->dma;
 
 	writel ((1 << VALID_BIT) | (ep->is_in << DMA_DIRECTION),
 			&dma->dmacount);
@@ -771,7 +770,7 @@
 static void start_dma (struct net2280_ep *ep, struct net2280_request *req)
 {
 	u32			tmp;
-	struct net2280_dma_regs	*dma = ep->dma;
+	struct net2280_dma_regs	__iomem *dma = ep->dma;
 
 	/* FIXME can't use DMA for ZLPs */
 
@@ -1419,10 +1418,34 @@
 	return 0;
 }
 
+static int net2280_pullup(struct usb_gadget *_gadget, int is_on)
+{
+	struct net2280  *dev;
+	u32             tmp;
+	unsigned long   flags;
+
+	if (!_gadget)
+		return -ENODEV;
+	dev = container_of (_gadget, struct net2280, gadget);
+
+	spin_lock_irqsave (&dev->lock, flags);
+	tmp = readl (&dev->usb->usbctl);
+	dev->softconnect = (is_on != 0);
+	if (is_on)
+		tmp |= (1 << USB_DETECT_ENABLE);
+	else
+		tmp &= ~(1 << USB_DETECT_ENABLE);
+	writel (tmp, &dev->usb->usbctl);
+	spin_unlock_irqrestore (&dev->lock, flags);
+
+	return 0;
+}
+
 static const struct usb_gadget_ops net2280_ops = {
 	.get_frame	= net2280_get_frame,
 	.wakeup		= net2280_wakeup,
 	.set_selfpowered = net2280_set_selfpowered,
+	.pullup		= net2280_pullup,
 };
 
 /*-------------------------------------------------------------------------*/
@@ -1807,8 +1830,6 @@
 {
 	u32	tmp;
 
-	/* force immediate bus disconnect, and synch through pci */
-	writel (0, &dev->usb->usbctl);
 	dev->gadget.speed = USB_SPEED_UNKNOWN;
 	(void) readl (&dev->usb->usbctl);
 
@@ -1902,10 +1923,8 @@
 		, &dev->usb->stdrsp);
 	writel (  (1 << USB_ROOT_PORT_WAKEUP_ENABLE)
 		| (1 << SELF_POWERED_USB_DEVICE)
-		/* erratum 0102 workaround */
-		| ((dev->chiprev == 0100) ? 0 : 1) << SUSPEND_IMMEDIATELY
 		| (1 << REMOTE_WAKEUP_SUPPORT)
-		| (1 << USB_DETECT_ENABLE)
+		| (dev->softconnect << USB_DETECT_ENABLE)
 		| (1 << SELF_POWERED_STATUS)
 		, &dev->usb->usbctl);
 
@@ -1957,6 +1976,7 @@
 		dev->ep [i].irqs = 0;
 
 	/* hook up the driver ... */
+	dev->softconnect = 1;
 	driver->driver.bus = NULL;
 	dev->driver = driver;
 	dev->gadget.dev.driver = &driver->driver;
@@ -2028,6 +2048,8 @@
 	stop_activity (dev, driver);
 	spin_unlock_irqrestore (&dev->lock, flags);
 
+	net2280_pullup (&dev->gadget, 0);
+
 	driver->unbind (&dev->gadget);
 	dev->gadget.dev.driver = NULL;
 	dev->driver = NULL;
@@ -2492,15 +2514,23 @@
 static void handle_stat1_irqs (struct net2280 *dev, u32 stat)
 {
 	struct net2280_ep	*ep;
-	u32			tmp, num, scratch;
+	u32			tmp, num, mask, scratch;
 
 	/* after disconnect there's nothing else to do! */
 	tmp = (1 << VBUS_INTERRUPT) | (1 << ROOT_PORT_RESET_INTERRUPT);
+	mask = (1 << HIGH_SPEED) | (1 << FULL_SPEED);
+
+	/* VBUS disconnect is indicated by VBUS_PIN and VBUS_INTERRUPT set.
+	 * Root Port Reset is indicated by ROOT_PORT_RESET_INTERRRUPT set and
+	 * both HIGH_SPEED and FULL_SPEED clear (as ROOT_PORT_RESET_INTERRUPT 
+	 * only indicates a change in the reset state).
+	 */
 	if (stat & tmp) {
 		writel (tmp, &dev->regs->irqstat1);
-		if (((stat & (1 << ROOT_PORT_RESET_INTERRUPT)) != 0
-			|| (readl (&dev->usb->usbctl) & (1 << VBUS_PIN)) == 0
-			) && dev->gadget.speed != USB_SPEED_UNKNOWN) {
+		if ((((stat & (1 << ROOT_PORT_RESET_INTERRUPT)) && 
+				((readl (&dev->usb->usbstat) & mask) == 0))
+				|| ((readl (&dev->usb->usbctl) & (1 << VBUS_PIN)) == 0) 
+			    ) && ( dev->gadget.speed != USB_SPEED_UNKNOWN)) {
 			DEBUG (dev, "disconnect %s\n",
 					dev->driver->driver.name);
 			stop_activity (dev, dev->driver);
@@ -2525,8 +2555,6 @@
 		if (stat & (1 << SUSPEND_REQUEST_INTERRUPT)) {
 			if (dev->driver->suspend)
 				dev->driver->suspend (&dev->gadget);
-			/* we use SUSPEND_IMMEDIATELY */
-			stat &= ~(1 << SUSPEND_REQUEST_INTERRUPT);
 		} else {
 			if (dev->driver->resume)
 				dev->driver->resume (&dev->gadget);
@@ -2553,7 +2581,7 @@
 	stat &= ~DMA_INTERRUPTS;
 	scratch >>= 9;
 	for (num = 0; scratch; num++) {
-		struct net2280_dma_regs	*dma;
+		struct net2280_dma_regs	__iomem *dma;
 
 		tmp = 1 << num;
 		if ((tmp & scratch) == 0)
@@ -2722,7 +2750,7 @@
 {
 	struct net2280		*dev;
 	unsigned long		resource, len;
-	void			*base = NULL;
+	void			__iomem *base = NULL;
 	int			retval, i;
 	char			buf [8], *bufp;
 
@@ -2780,14 +2808,15 @@
 		retval = -EFAULT;
 		goto done;
 	}
-	dev->regs = (struct net2280_regs *) base;
-	dev->usb = (struct net2280_usb_regs *) (base + 0x0080);
-	dev->pci = (struct net2280_pci_regs *) (base + 0x0100);
-	dev->dma = (struct net2280_dma_regs *) (base + 0x0180);
-	dev->dep = (struct net2280_dep_regs *) (base + 0x0200);
-	dev->epregs = (struct net2280_ep_regs *) (base + 0x0300);
+	dev->regs = (struct net2280_regs __iomem *) base;
+	dev->usb = (struct net2280_usb_regs __iomem *) (base + 0x0080);
+	dev->pci = (struct net2280_pci_regs __iomem *) (base + 0x0100);
+	dev->dma = (struct net2280_dma_regs __iomem *) (base + 0x0180);
+	dev->dep = (struct net2280_dep_regs __iomem *) (base + 0x0200);
+	dev->epregs = (struct net2280_ep_regs __iomem *) (base + 0x0300);
 
 	/* put into initial config, link up all endpoints */
+	writel (0, &dev->usb->usbctl);
 	usb_reset (dev);
 	usb_reinit (dev);
 
diff -Nru a/drivers/usb/gadget/net2280.h b/drivers/usb/gadget/net2280.h
--- a/drivers/usb/gadget/net2280.h	2004-10-18 14:56:49 -07:00
+++ b/drivers/usb/gadget/net2280.h	2004-10-18 14:56:49 -07:00
@@ -446,7 +446,7 @@
  */
 
 static inline u32
-get_idx_reg (struct net2280_regs *regs, u32 index)
+get_idx_reg (struct net2280_regs __iomem *regs, u32 index)
 {
 	writel (index, &regs->idxaddr);
 	/* NOTE:  synchs device/cpu memory views */
@@ -454,7 +454,7 @@
 }
 
 static inline void
-set_idx_reg (struct net2280_regs *regs, u32 index, u32 value)
+set_idx_reg (struct net2280_regs __iomem *regs, u32 index, u32 value)
 {
 	writel (index, &regs->idxaddr);
 	writel (value, &regs->idxdata);
@@ -507,8 +507,8 @@
 
 struct net2280_ep {
 	struct usb_ep				ep;
-	struct net2280_ep_regs			*regs;
-	struct net2280_dma_regs			*dma;
+	struct net2280_ep_regs			__iomem *regs;
+	struct net2280_dma_regs			__iomem *dma;
 	struct net2280_dma			*dummy;
 	dma_addr_t				td_dma;	/* of dummy */
 	struct net2280				*dev;
@@ -539,7 +539,7 @@
 /* count (<= 4) bytes in the next fifo write will be valid */
 static inline void set_fifo_bytecount (struct net2280_ep *ep, unsigned count)
 {
-	writeb (count, 2 + (u8 *) &ep->regs->ep_cfg);
+	writeb (count, 2 + (u8 __iomem *) &ep->regs->ep_cfg);
 }
 
 struct net2280_request {
@@ -559,18 +559,19 @@
 	struct usb_gadget_driver 	*driver;
 	unsigned			enabled : 1,
 					protocol_stall : 1,
+					softconnect : 1,
 					got_irq : 1,
 					region : 1;
 	u16				chiprev;
 
 	/* pci state used to access those endpoints */
 	struct pci_dev			*pdev;
-	struct net2280_regs		*regs;
-	struct net2280_usb_regs		*usb;
-	struct net2280_pci_regs		*pci;
-	struct net2280_dma_regs		*dma;
-	struct net2280_dep_regs		*dep;
-	struct net2280_ep_regs		*epregs;
+	struct net2280_regs		__iomem *regs;
+	struct net2280_usb_regs		__iomem *usb;
+	struct net2280_pci_regs		__iomem *pci;
+	struct net2280_dma_regs		__iomem *dma;
+	struct net2280_dep_regs		__iomem *dep;
+	struct net2280_ep_regs		__iomem *epregs;
 
 	struct pci_pool			*requests;
 	// statistics...
diff -Nru a/drivers/usb/gadget/omap_udc.c b/drivers/usb/gadget/omap_udc.c
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/drivers/usb/gadget/omap_udc.c	2004-10-18 14:57:22 -07:00
@@ -0,0 +1,2695 @@
+/*
+ * omap_udc.c -- for OMAP 1610 udc, with OTG support
+ *
+ * Copyright (C) 2004 Texas Instruments, Inc.
+ * 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#undef	DEBUG
+#undef	VERBOSE
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/ioport.h>
+#include <linux/types.h>
+#include <linux/errno.h>
+#include <linux/delay.h>
+#include <linux/sched.h>
+#include <linux/slab.h>
+#include <linux/init.h>
+#include <linux/timer.h>
+#include <linux/list.h>
+#include <linux/interrupt.h>
+#include <linux/proc_fs.h>
+#include <linux/mm.h>
+#include <linux/moduleparam.h>
+#include <linux/device.h>
+#include <linux/usb_ch9.h>
+#include <linux/usb_gadget.h>
+#include <linux/usb_otg.h>
+#include <linux/dma-mapping.h>
+
+#include <asm/byteorder.h>
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/system.h>
+#include <asm/unaligned.h>
+#include <asm/mach-types.h>
+
+#include <asm/arch/dma.h>
+#include <asm/arch/mux.h>
+#include <asm/arch/usb.h>
+
+#include "omap_udc.h"
+
+#undef	USB_TRACE
+
+/* OUT-dma seems to be behaving */
+#define	USE_DMA
+
+/* ISO too */
+#define	USE_ISO
+
+
+#define	DRIVER_DESC	"OMAP UDC driver"
+#define	DRIVER_VERSION	"24 August 2004"
+
+#define	DMA_ADDR_INVALID	(~(dma_addr_t)0)
+
+
+/*
+ * The OMAP UDC needs _very_ early endpoint setup:  before enabling the
+ * D+ pullup to allow enumeration.  That's too early for the gadget
+ * framework to use from usb_endpoint_enable(), which happens after
+ * enumeration as part of activating an interface.  (But if we add an
+ * optional new "UDC not yet running" state to the gadget driver model,
+ * even just during driver binding, the endpoint autoconfig logic is the
+ * natural spot to manufacture new endpoints.)
+ *
+ * So instead of using endpoint enable calls to control the hardware setup,
+ * this driver defines a "fifo mode" parameter.  It's used during driver
+ * initialization to choose among a set of pre-defined endpoint configs.
+ * See omap_udc_setup() for available modes, or to add others.  That code
+ * lives in an init section, so use this driver as a module if you need
+ * to change the fifo mode after the kernel boots.
+ *
+ * Gadget drivers normally ignore endpoints they don't care about, and
+ * won't include them in configuration descriptors.  That means only
+ * misbehaving hosts would even notice they exist.
+ */
+#ifdef	USE_ISO
+static unsigned fifo_mode = 3;
+#else
+static unsigned fifo_mode = 0;
+#endif
+
+/* "modprobe omap_udc fifo_mode=42", or else as a kernel
+ * boot parameter "omap_udc:fifo_mode=42"
+ */
+module_param (fifo_mode, uint, 0);
+MODULE_PARM_DESC (fifo_mode, "endpoint setup (0 == default)");
+
+
+#ifdef	USE_DMA
+static unsigned use_dma = 1;
+
+/* "modprobe omap_udc use_dma=y", or else as a kernel
+ * boot parameter "omap_udc:use_dma=y"
+ */
+module_param (use_dma, bool, 0);
+MODULE_PARM_DESC (use_dma, "enable/disable DMA");
+#else	/* !USE_DMA */
+
+/* save a bit of code */
+#define	use_dma		0
+#endif	/* !USE_DMA */
+
+
+static const char driver_name [] = "omap_udc";
+static const char driver_desc [] = DRIVER_DESC;
+
+/*-------------------------------------------------------------------------*/
+
+/* there's a notion of "current endpoint" for modifying endpoint
+ * state, and PIO access to its FIFO.  
+ */
+
+static void use_ep(struct omap_ep *ep, u16 select)
+{
+	u16	num = ep->bEndpointAddress & 0x0f;
+
+	if (ep->bEndpointAddress & USB_DIR_IN)
+		num |= UDC_EP_DIR;
+	UDC_EP_NUM_REG = num | select;
+	/* when select, MUST deselect later !! */
+}
+
+static inline void deselect_ep(void)
+{
+	UDC_EP_NUM_REG &= ~UDC_EP_SEL;
+	/* 6 wait states before TX will happen */
+}
+
+static void dma_channel_claim(struct omap_ep *ep, unsigned preferred);
+
+/*-------------------------------------------------------------------------*/
+
+static int omap_ep_enable(struct usb_ep *_ep,
+		const struct usb_endpoint_descriptor *desc)
+{
+	struct omap_ep	*ep = container_of(_ep, struct omap_ep, ep);
+	struct omap_udc	*udc;
+	unsigned long	flags;
+	u16		maxp;
+
+	/* catch various bogus parameters */
+	if (!_ep || !desc || ep->desc
+			|| desc->bDescriptorType != USB_DT_ENDPOINT
+			|| ep->bEndpointAddress != desc->bEndpointAddress
+			|| ep->maxpacket < le16_to_cpu
+						(desc->wMaxPacketSize)) {
+		DBG("%s, bad ep or descriptor\n", __FUNCTION__);
+		return -EINVAL;
+	}
+	maxp = le16_to_cpu (desc->wMaxPacketSize);
+	if ((desc->bmAttributes == USB_ENDPOINT_XFER_BULK
+				&& maxp != ep->maxpacket)
+			|| desc->wMaxPacketSize > ep->maxpacket
+			|| !desc->wMaxPacketSize) {
+		DBG("%s, bad %s maxpacket\n", __FUNCTION__, _ep->name);
+		return -ERANGE;
+	}
+
+#ifdef	USE_ISO
+	if ((desc->bmAttributes == USB_ENDPOINT_XFER_ISOC
+				&& desc->bInterval != 1)) {
+		/* hardware wants period = 1; USB allows 2^(Interval-1) */
+		DBG("%s, unsupported ISO period %dms\n", _ep->name,
+				1 << (desc->bInterval - 1));
+		return -EDOM;
+	}
+#else
+	if (desc->bmAttributes == USB_ENDPOINT_XFER_ISOC) {
+		DBG("%s, ISO nyet\n", _ep->name);
+		return -EDOM;
+	}
+#endif
+
+	/* xfer types must match, except that interrupt ~= bulk */
+	if (ep->bmAttributes != desc->bmAttributes
+			&& ep->bmAttributes != USB_ENDPOINT_XFER_BULK
+			&& desc->bmAttributes != USB_ENDPOINT_XFER_INT) {
+		DBG("%s, %s type mismatch\n", __FUNCTION__, _ep->name);
+		return -EINVAL;
+	}
+
+	udc = ep->udc;
+	if (!udc->driver || udc->gadget.speed == USB_SPEED_UNKNOWN) {
+		DBG("%s, bogus device state\n", __FUNCTION__);
+		return -ESHUTDOWN;
+	}
+
+	spin_lock_irqsave(&udc->lock, flags);
+
+	ep->desc = desc;
+	ep->irqs = 0;
+	ep->stopped = 0;
+	ep->ep.maxpacket = maxp;
+
+	/* set endpoint to initial state */
+	ep->dma_channel = 0;
+	ep->has_dma = 0;
+	ep->lch = -1;
+	use_ep(ep, UDC_EP_SEL);
+	UDC_CTRL_REG = UDC_RESET_EP;
+	ep->ackwait = 0;
+	deselect_ep();
+
+	if (ep->bmAttributes == USB_ENDPOINT_XFER_ISOC)
+		list_add(&ep->iso, &udc->iso);
+
+	/* maybe assign a DMA channel to this endpoint */
+	if (use_dma && desc->bmAttributes == USB_ENDPOINT_XFER_BULK
+			&& !(ep->bEndpointAddress & USB_DIR_IN))
+			/* FIXME ISO can dma, but prefers first channel.
+			 * IN can dma, but lacks debugging.
+			 */
+		dma_channel_claim(ep, 0);
+
+	/* PIO OUT may RX packets */
+	if (desc->bmAttributes != USB_ENDPOINT_XFER_ISOC
+			&& !ep->has_dma
+			&& !(ep->bEndpointAddress & USB_DIR_IN))
+		UDC_CTRL_REG = UDC_SET_FIFO_EN;
+
+	spin_unlock_irqrestore(&udc->lock, flags);
+	VDBG("%s enabled\n", _ep->name);
+	return 0;
+}
+
+static void nuke(struct omap_ep *, int status);
+
+static int omap_ep_disable(struct usb_ep *_ep)
+{
+	struct omap_ep	*ep = container_of(_ep, struct omap_ep, ep);
+	unsigned long	flags;
+
+	if (!_ep || !ep->desc) {
+		DBG("%s, %s not enabled\n", __FUNCTION__,
+			_ep ? ep->ep.name : NULL);
+		return -EINVAL;
+	}
+
+	spin_lock_irqsave(&ep->udc->lock, flags);
+	ep->desc = 0;
+	nuke (ep, -ESHUTDOWN);
+	ep->ep.maxpacket = ep->maxpacket;
+	ep->has_dma = 0;
+	UDC_CTRL_REG = UDC_SET_HALT;
+	list_del_init(&ep->iso);
+
+	spin_unlock_irqrestore(&ep->udc->lock, flags);
+
+	VDBG("%s disabled\n", _ep->name);
+	return 0;
+}
+
+/*-------------------------------------------------------------------------*/
+
+static struct usb_request *
+omap_alloc_request(struct usb_ep *ep, int gfp_flags)
+{
+	struct omap_req	*req;
+
+	req = kmalloc(sizeof *req, gfp_flags);
+	if (req) {
+		memset (req, 0, sizeof *req);
+		req->req.dma = DMA_ADDR_INVALID;
+		INIT_LIST_HEAD (&req->queue);
+	}
+	return &req->req;
+}
+
+static void
+omap_free_request(struct usb_ep *ep, struct usb_request *_req)
+{
+	struct omap_req	*req = container_of(_req, struct omap_req, req);
+
+	if (_req)
+		kfree (req);
+}
+
+/*-------------------------------------------------------------------------*/
+
+static void *
+omap_alloc_buffer(
+	struct usb_ep	*_ep,
+	unsigned	bytes,
+	dma_addr_t	*dma,
+	int		gfp_flags
+)
+{
+	void		*retval;
+	struct omap_ep	*ep;
+
+	ep = container_of(_ep, struct omap_ep, ep);
+	if (use_dma && ep->has_dma) {
+		static int	warned;
+		if (!warned && bytes < PAGE_SIZE) {
+			dev_warn(ep->udc->gadget.dev.parent,
+				"using dma_alloc_coherent for "
+				"small allocations wastes memory\n");
+			warned++;
+		}
+		return dma_alloc_coherent(ep->udc->gadget.dev.parent,
+				bytes, dma, gfp_flags);
+	}
+
+	retval = kmalloc(bytes, gfp_flags);
+	if (retval)
+		*dma = virt_to_phys(retval);
+	return retval;
+}
+
+static void omap_free_buffer(
+	struct usb_ep	*_ep,
+	void		*buf,
+	dma_addr_t	dma,
+	unsigned	bytes
+)
+{
+	struct omap_ep	*ep;
+
+	ep = container_of(_ep, struct omap_ep, ep);
+	if (use_dma && _ep && ep->has_dma)
+		dma_free_coherent(ep->udc->gadget.dev.parent, bytes, buf, dma);
+	else
+		kfree (buf);
+}
+
+/*-------------------------------------------------------------------------*/
+
+static void
+done(struct omap_ep *ep, struct omap_req *req, int status)
+{
+	unsigned		stopped = ep->stopped;
+
+	list_del_init(&req->queue);
+
+	if (req->req.status == -EINPROGRESS)
+		req->req.status = status;
+	else
+		status = req->req.status;
+
+	if (use_dma && ep->has_dma) {
+		if (req->mapped) {
+			dma_unmap_single(ep->udc->gadget.dev.parent,
+				req->req.dma, req->req.length,
+				(ep->bEndpointAddress & USB_DIR_IN)
+					? DMA_TO_DEVICE
+					: DMA_FROM_DEVICE);
+			req->req.dma = DMA_ADDR_INVALID;
+			req->mapped = 0;
+		} else
+			dma_sync_single_for_cpu(ep->udc->gadget.dev.parent,
+				req->req.dma, req->req.length,
+				(ep->bEndpointAddress & USB_DIR_IN)
+					? DMA_TO_DEVICE
+					: DMA_FROM_DEVICE);
+	}
+
+#ifndef	USB_TRACE
+	if (status && status != -ESHUTDOWN)
+#endif
+		VDBG("complete %s req %p stat %d len %u/%u\n",
+			ep->ep.name, &req->req, status,
+			req->req.actual, req->req.length);
+
+	/* don't modify queue heads during completion callback */
+	ep->stopped = 1;
+	spin_unlock(&ep->udc->lock);
+	req->req.complete(&ep->ep, &req->req);
+	spin_lock(&ep->udc->lock);
+	ep->stopped = stopped;
+}
+
+/*-------------------------------------------------------------------------*/
+
+#define	FIFO_FULL	(UDC_NON_ISO_FIFO_FULL | UDC_ISO_FIFO_FULL)
+#define	FIFO_UNWRITABLE	(UDC_EP_HALTED | FIFO_FULL)
+
+#define FIFO_EMPTY	(UDC_NON_ISO_FIFO_EMPTY | UDC_ISO_FIFO_EMPTY)
+#define FIFO_UNREADABLE (UDC_EP_HALTED | FIFO_EMPTY)
+
+static inline int 
+write_packet(u8 *buf, struct omap_req *req, unsigned max)
+{
+	unsigned	len;
+	u16		*wp;
+
+	len = min(req->req.length - req->req.actual, max);
+	req->req.actual += len;
+
+	max = len;
+	if (likely((((int)buf) & 1) == 0)) {
+		wp = (u16 *)buf;
+		while (max >= 2) {
+			UDC_DATA_REG = *wp++;
+			max -= 2;
+		}
+		buf = (u8 *)wp;
+	}
+	while (max--)
+		*(volatile u8 *)&UDC_DATA_REG = *buf++;
+	return len;
+}
+
+// FIXME change r/w fifo calling convention
+
+
+// return:  0 = still running, 1 = completed, negative = errno
+static int write_fifo(struct omap_ep *ep, struct omap_req *req)
+{
+	u8		*buf;
+	unsigned	count;
+	int		is_last;
+	u16		ep_stat;
+
+	buf = req->req.buf + req->req.actual;
+	prefetch(buf);
+
+	/* PIO-IN isn't double buffered except for iso */
+	ep_stat = UDC_STAT_FLG_REG;
+	if (ep_stat & FIFO_UNWRITABLE)
+		return 0;
+
+	count = ep->ep.maxpacket;
+	count = write_packet(buf, req, count);
+	UDC_CTRL_REG = UDC_SET_FIFO_EN;
+	ep->ackwait = 1;
+
+	/* last packet is often short (sometimes a zlp) */
+	if (count != ep->ep.maxpacket)
+		is_last = 1;
+	else if (req->req.length == req->req.actual
+			&& !req->req.zero)
+		is_last = 1;
+	else
+		is_last = 0;
+
+	/* NOTE:  requests complete when all IN data is in a
+	 * FIFO (or sometimes later, if a zlp was needed).
+	 * Use usb_ep_fifo_status() where needed.
+	 */
+	if (is_last)
+		done(ep, req, 0);
+	return is_last;
+}
+
+static inline int 
+read_packet(u8 *buf, struct omap_req *req, unsigned avail)
+{
+	unsigned	len;
+	u16		*wp;
+
+	len = min(req->req.length - req->req.actual, avail);
+	req->req.actual += len;
+	avail = len;
+
+	if (likely((((int)buf) & 1) == 0)) {
+		wp = (u16 *)buf;
+		while (avail >= 2) {
+			*wp++ = UDC_DATA_REG;
+			avail -= 2;
+		}
+		buf = (u8 *)wp;
+	}
+	while (avail--)
+		*buf++ = *(volatile u8 *)&UDC_DATA_REG;
+	return len;
+}
+
+// return:  0 = still running, 1 = queue empty, negative = errno
+static int read_fifo(struct omap_ep *ep, struct omap_req *req)
+{
+	u8		*buf;
+	unsigned	count, avail;
+	int		is_last;
+
+	buf = req->req.buf + req->req.actual;
+	prefetchw(buf);
+
+	for (;;) {
+		u16	ep_stat = UDC_STAT_FLG_REG;
+
+		is_last = 0;
+		if (ep_stat & FIFO_UNREADABLE)
+			break;
+
+		if (ep_stat & (UDC_NON_ISO_FIFO_FULL|UDC_ISO_FIFO_FULL))
+			avail = ep->ep.maxpacket;
+		else 
+			avail = UDC_RXFSTAT_REG;
+		count = read_packet(buf, req, avail);
+
+		// FIXME double buffered PIO OUT wasn't behaving...
+
+		/* partial packet reads may not be errors */
+		if (count < ep->ep.maxpacket) {
+			is_last = 1;
+			/* overflowed this request?  flush extra data */
+			if (count != avail) {
+				req->req.status = -EOVERFLOW;
+				avail -= count;
+				while (avail--)
+					(void) *(volatile u8 *)&UDC_DATA_REG;
+			}
+		} else if (req->req.length == req->req.actual)
+			is_last = 1;
+		else
+			is_last = 0;
+
+		if (!ep->bEndpointAddress)
+			break;
+		if (!ep->double_buf) {
+			UDC_CTRL_REG = UDC_SET_FIFO_EN;
+			if (!is_last)
+				break;
+		}
+
+		if (is_last) {
+			done(ep, req, 0);
+			if (list_empty(&ep->queue) || !ep->double_buf)
+				break;
+			req = container_of(ep->queue.next,
+					struct omap_req, queue);
+			is_last = 0;
+		}
+	}
+	return is_last;
+}
+
+/*-------------------------------------------------------------------------*/
+
+/* Each USB transfer request using DMA maps to one or more DMA transfers.
+ * When DMA completion isn't request completion, the UDC continues with
+ * the next DMA transfer for that USB transfer.
+ */
+
+static void next_in_dma(struct omap_ep *ep, struct omap_req *req)
+{
+	u16		txdma_ctrl;
+	unsigned	length = req->req.length - req->req.actual;
+
+	/* measure length in either bytes or packets */
+	if (length <= (UDC_TXN_TSC + 1)) {
+		txdma_ctrl = UDC_TXN_EOT | length;
+		omap_set_dma_transfer_params(ep->lch, OMAP_DMA_DATA_TYPE_S8,
+				length, 1, OMAP_DMA_SYNC_ELEMENT);
+	} else {
+		length = max(length / ep->maxpacket,
+				(unsigned) UDC_TXN_TSC + 1);
+ 		txdma_ctrl = length;
+		omap_set_dma_transfer_params(ep->lch, OMAP_DMA_DATA_TYPE_S8,
+				ep->ep.maxpacket, length,
+				OMAP_DMA_SYNC_ELEMENT);
+		length *= ep->maxpacket;
+	}
+
+	omap_set_dma_src_params(ep->lch, OMAP_DMA_PORT_EMIFF,
+		OMAP_DMA_AMODE_POST_INC, req->req.dma + req->req.actual);
+
+	omap_start_dma(ep->lch);
+	UDC_DMA_IRQ_EN_REG |= UDC_TX_DONE_IE(ep->dma_channel);
+	UDC_TXDMA_REG(ep->dma_channel) = UDC_TXN_START | txdma_ctrl;
+	req->dma_bytes = length;
+}
+
+static void finish_in_dma(struct omap_ep *ep, struct omap_req *req, int status)
+{
+	if (status == 0) {
+		req->req.actual += req->dma_bytes;
+
+		/* return if this request needs to send data or zlp */
+		if (req->req.actual < req->req.length)
+			return;
+		if (req->req.zero
+				&& req->dma_bytes != 0
+				&& (req->req.actual % ep->maxpacket) == 0)
+			return;
+	} else {
+		u32	last;
+
+		// FIXME this surely isn't #bytes transferred
+		last = (omap_readw(OMAP_DMA_CSSA_U(ep->lch)) << 16)
+				| omap_readw(OMAP_DMA_CSSA_L(ep->lch));
+		req->req.actual = last - req->req.dma;
+	}
+
+	/* tx completion */
+	omap_stop_dma(ep->lch);
+	UDC_DMA_IRQ_EN_REG &= ~UDC_TX_DONE_IE(ep->dma_channel);
+	done(ep, req, status);
+}
+
+static void next_out_dma(struct omap_ep *ep, struct omap_req *req)
+{
+	unsigned packets;
+
+	/* NOTE:  we filtered out "short reads" before, so we know
+	 * the buffer has only whole numbers of packets.
+	 */
+
+	/* set up this DMA transfer, enable the fifo, start */
+	packets = (req->req.length - req->req.actual) / ep->ep.maxpacket;
+	packets = min(packets, (unsigned)UDC_RXN_TC + 1);
+	req->dma_bytes = packets * ep->ep.maxpacket;
+	omap_set_dma_transfer_params(ep->lch, OMAP_DMA_DATA_TYPE_S8,
+			ep->ep.maxpacket, packets,
+			OMAP_DMA_SYNC_ELEMENT);
+	omap_set_dma_dest_params(ep->lch, OMAP_DMA_PORT_EMIFF,
+		OMAP_DMA_AMODE_POST_INC, req->req.dma + req->req.actual);
+
+	UDC_RXDMA_REG(ep->dma_channel) = UDC_RXN_STOP | (packets - 1);
+	UDC_DMA_IRQ_EN_REG |= UDC_RX_EOT_IE(ep->dma_channel);
+	UDC_EP_NUM_REG = (ep->bEndpointAddress & 0xf);
+	UDC_CTRL_REG = UDC_SET_FIFO_EN;
+
+	omap_start_dma(ep->lch);
+}
+
+static void
+finish_out_dma(struct omap_ep *ep, struct omap_req *req, int status)
+{
+	u16	count;
+
+	/* FIXME must be a better way to see how much dma
+	 * happened, even when it never got going...
+	 */
+	count = omap_readw(OMAP_DMA_CDAC(ep->lch));
+	count -= 0xffff & (req->req.dma + req->req.actual);
+	count += req->req.actual;
+	if (count <= req->req.length)
+		req->req.actual = count;
+	
+	if (count != req->dma_bytes || status)
+		omap_stop_dma(ep->lch);
+
+	/* if this wasn't short, request may need another transfer */
+	else if (req->req.actual < req->req.length)
+		return;
+
+	/* rx completion */
+	UDC_DMA_IRQ_EN_REG &= ~UDC_RX_EOT_IE(ep->dma_channel);
+	done(ep, req, status);
+}
+
+static void dma_irq(struct omap_udc *udc, u16 irq_src)
+{
+	u16		dman_stat = UDC_DMAN_STAT_REG;
+	struct omap_ep	*ep;
+	struct omap_req	*req;
+
+	/* IN dma: tx to host */
+	if (irq_src & UDC_TXN_DONE) {
+		ep = &udc->ep[16 + UDC_DMA_TX_SRC(dman_stat)];
+		ep->irqs++;
+		/* can see TXN_DONE after dma abort */
+		if (!list_empty(&ep->queue)) {
+			req = container_of(ep->queue.next,
+						struct omap_req, queue);
+			finish_in_dma(ep, req, 0);
+		}
+		UDC_IRQ_SRC_REG = UDC_TXN_DONE;
+
+		if (!list_empty (&ep->queue)) {
+			req = container_of(ep->queue.next,
+					struct omap_req, queue);
+			next_in_dma(ep, req);
+		}
+	}
+
+	/* OUT dma: rx from host */
+	if (irq_src & UDC_RXN_EOT) {
+		ep = &udc->ep[UDC_DMA_RX_SRC(dman_stat)];
+		ep->irqs++;
+		/* can see RXN_EOT after dma abort */
+		if (!list_empty(&ep->queue)) {
+			req = container_of(ep->queue.next,
+					struct omap_req, queue);
+			finish_out_dma(ep, req, 0);
+		}
+		UDC_IRQ_SRC_REG = UDC_RXN_EOT;
+
+		if (!list_empty (&ep->queue)) {
+			req = container_of(ep->queue.next,
+					struct omap_req, queue);
+			next_out_dma(ep, req);
+		}
+	}
+
+	if (irq_src & UDC_RXN_CNT) {
+		ep = &udc->ep[UDC_DMA_RX_SRC(dman_stat)];
+		DBG("%s, RX_CNT irq?\n", ep->ep.name);
+		UDC_IRQ_SRC_REG = UDC_RXN_CNT;
+	}
+}
+
+static void dma_error(int lch, u16 ch_status, void *data)
+{
+	struct omap_ep	*ep = data;
+
+	/* if ch_status & OMAP_DMA_DROP_IRQ ... */
+	/* if ch_status & OMAP_DMA_TOUT_IRQ ... */
+	ERR("%s dma error, lch %d status %02x\n", ep->ep.name, lch, ch_status);
+
+	/* complete current transfer ... */
+}
+
+static void dma_channel_claim(struct omap_ep *ep, unsigned channel)
+{
+	u16	reg;
+	int	status, restart, is_in;
+
+	is_in = ep->bEndpointAddress & USB_DIR_IN;
+	if (is_in)
+		reg = UDC_TXDMA_CFG_REG;
+	else
+		reg = UDC_RXDMA_CFG_REG;
+	reg |= 1 << 12;		/* "pulse" activated */
+
+	ep->dma_channel = 0;
+	ep->lch = -1;
+	if (channel == 0 || channel > 3) {
+		if ((reg & 0x0f00) == 0)
+			channel = 3;
+		else if ((reg & 0x00f0) == 0)
+			channel = 2;
+		else if ((reg & 0x000f) == 0)	/* preferred for ISO */
+			channel = 1;
+		else {
+			status = -EMLINK;
+			goto just_restart;
+		}
+	}
+	reg |= (0x0f & ep->bEndpointAddress) << (4 * (channel - 1));
+	ep->dma_channel = channel;
+
+	if (is_in) {
+		status = omap_request_dma(OMAP_DMA_USB_W2FC_TX0 - 1 + channel,
+			ep->ep.name, dma_error, ep, &ep->lch);
+		if (status == 0) {
+			UDC_TXDMA_CFG_REG = reg;
+			omap_set_dma_dest_params(ep->lch,
+				OMAP_DMA_PORT_TIPB,
+				OMAP_DMA_AMODE_CONSTANT,
+				(unsigned long) io_v2p((u32)&UDC_DATA_DMA_REG));
+		}
+	} else {
+		status = omap_request_dma(OMAP_DMA_USB_W2FC_RX0 - 1 + channel,
+			ep->ep.name, dma_error, ep, &ep->lch);
+		if (status == 0) {
+			UDC_RXDMA_CFG_REG = reg;
+			omap_set_dma_src_params(ep->lch,
+				OMAP_DMA_PORT_TIPB,
+				OMAP_DMA_AMODE_CONSTANT,
+				(unsigned long) io_v2p((u32)&UDC_DATA_DMA_REG));
+		}
+	}
+	if (status)
+		ep->dma_channel = 0;
+	else {
+		ep->has_dma = 1;
+		omap_disable_dma_irq(ep->lch, OMAP_DMA_BLOCK_IRQ);
+
+		/* channel type P: hw synch (fifo) */
+		omap_writew(2, OMAP_DMA_LCH_CTRL(ep->lch));
+	}
+
+just_restart:
+	/* restart any queue, even if the claim failed  */
+	restart = !ep->stopped && !list_empty(&ep->queue);
+
+	if (status)
+		DBG("%s no dma channel: %d%s\n", ep->ep.name, status,
+			restart ? " (restart)" : "");
+	else
+		DBG("%s claimed %cxdma%d lch %d%s\n", ep->ep.name,
+			is_in ? 't' : 'r',
+			ep->dma_channel - 1, ep->lch,
+			restart ? " (restart)" : "");
+
+	if (restart) {
+		struct omap_req	*req;
+		req = container_of(ep->queue.next, struct omap_req, queue);
+		if (ep->has_dma)
+			(is_in ? next_in_dma : next_out_dma)(ep, req);
+		else {
+			use_ep(ep, UDC_EP_SEL);
+			(is_in ? write_fifo : read_fifo)(ep, req);
+			deselect_ep();
+			/* IN: 6 wait states before it'll tx */
+		}
+	}
+}
+
+static void dma_channel_release(struct omap_ep *ep)
+{
+	int		shift = 4 * (ep->dma_channel - 1);
+	u16		mask = 0x0f << shift;
+	struct omap_req	*req;
+	int		active;
+
+	/* abort any active usb transfer request */
+	if (!list_empty(&ep->queue))
+		req = container_of(ep->queue.next, struct omap_req, queue);
+	else
+		req = 0;
+
+	active = ((1 << 7) & omap_readl(OMAP_DMA_CCR(ep->lch))) != 0;
+
+	DBG("%s release %s %cxdma%d %p\n", ep->ep.name,
+			active ? "active" : "idle",
+			(ep->bEndpointAddress & USB_DIR_IN) ? 't' : 'r',
+			ep->dma_channel - 1, req);
+
+	/* wait till current packet DMA finishes, and fifo empties */
+	if (ep->bEndpointAddress & USB_DIR_IN) {
+		UDC_TXDMA_CFG_REG &= ~mask;
+
+		if (req) {
+			if (active)
+				udelay(50);
+			finish_in_dma(ep, req, -ECONNRESET);
+			if (UDC_TXDMA_CFG_REG & mask)
+				WARN("%s, SPIN abort TX dma\n", ep->ep.name);
+		}
+
+		/* host may empty the fifo (or not...) */
+		while (UDC_TXDMA_CFG_REG & mask)
+			udelay(10);
+
+	} else {
+		UDC_RXDMA_CFG_REG &= ~mask;
+
+		/* dma empties the fifo */
+		while (active && (UDC_RXDMA_CFG_REG & mask))
+			udelay(10);
+		omap_stop_dma(ep->lch);
+		if (req)
+			finish_out_dma(ep, req, -ECONNRESET);
+	}
+	omap_free_dma(ep->lch);
+	ep->dma_channel = 0;
+	ep->lch = -1;
+	/* has_dma still set, till endpoint is fully quiesced */
+}
+
+
+/*-------------------------------------------------------------------------*/
+
+static int
+omap_ep_queue(struct usb_ep *_ep, struct usb_request *_req, int gfp_flags)
+{
+	struct omap_ep	*ep = container_of(_ep, struct omap_ep, ep);
+	struct omap_req	*req = container_of(_req, struct omap_req, req);
+	struct omap_udc	*udc;
+	unsigned long	flags;
+	int		is_iso = 0;
+
+	/* catch various bogus parameters */
+	if (!_req || !req->req.complete || !req->req.buf
+			|| !list_empty(&req->queue)) {
+		DBG("%s, bad params\n", __FUNCTION__);
+		return -EINVAL;
+	}
+	if (!_ep || (!ep->desc && ep->bEndpointAddress)) {
+		DBG("%s, bad ep\n", __FUNCTION__);
+		return -EINVAL;
+	}
+	if (ep->bmAttributes == USB_ENDPOINT_XFER_ISOC) {
+		if (req->req.length > ep->ep.maxpacket)
+			return -EMSGSIZE;
+		is_iso = 1;
+	}
+
+	/* this isn't bogus, but OMAP DMA isn't the only hardware to
+	 * have a hard time with partial packet reads...  reject it.
+	 */
+	if (use_dma
+			&& ep->has_dma
+			&& ep->bEndpointAddress != 0
+			&& (ep->bEndpointAddress & USB_DIR_IN) == 0
+			&& (req->req.length % ep->ep.maxpacket) != 0) {
+		DBG("%s, no partial packet OUT reads\n", __FUNCTION__);
+		return -EMSGSIZE;
+	}
+
+	udc = ep->udc;
+	if (!udc->driver || udc->gadget.speed == USB_SPEED_UNKNOWN)
+		return -ESHUTDOWN;
+
+	if (use_dma && ep->has_dma) {
+		if (req->req.dma == DMA_ADDR_INVALID) {
+			req->req.dma = dma_map_single(
+				ep->udc->gadget.dev.parent,
+				req->req.buf,
+				req->req.length,
+				(ep->bEndpointAddress & USB_DIR_IN)
+					? DMA_TO_DEVICE
+					: DMA_FROM_DEVICE);
+			req->mapped = 1;
+		} else {
+			dma_sync_single_for_device(
+				ep->udc->gadget.dev.parent,
+				req->req.dma, req->req.length,
+				(ep->bEndpointAddress & USB_DIR_IN)
+					? DMA_TO_DEVICE
+					: DMA_FROM_DEVICE);
+			req->mapped = 0;
+		}
+	}
+
+	VDBG("%s queue req %p, len %d buf %p\n",
+		ep->ep.name, _req, _req->length, _req->buf);
+
+	spin_lock_irqsave(&udc->lock, flags);
+
+	req->req.status = -EINPROGRESS;
+	req->req.actual = 0;
+
+	/* maybe kickstart non-iso i/o queues */
+	if (is_iso)
+		UDC_IRQ_EN_REG |= UDC_SOF_IE;
+	else if (list_empty(&ep->queue) && !ep->stopped && !ep->ackwait) {
+		int	is_in;
+
+		if (ep->bEndpointAddress == 0) {
+			if (!udc->ep0_pending || !list_empty (&ep->queue)) {
+				spin_unlock_irqrestore(&udc->lock, flags);
+				return -EL2HLT;
+			}
+
+			/* empty DATA stage? */
+			is_in = udc->ep0_in;
+			if (!req->req.length) {
+
+				/* chip became CONFIGURED or ADDRESSED
+				 * earlier; drivers may already have queued
+				 * requests to non-control endpoints
+				 */
+				if (udc->ep0_set_config) {
+					u16	irq_en = UDC_IRQ_EN_REG;
+
+					irq_en |= UDC_DS_CHG_IE | UDC_EP0_IE;
+					if (!udc->ep0_reset_config)
+						irq_en |= UDC_EPN_RX_IE
+							| UDC_EPN_TX_IE;
+					UDC_IRQ_EN_REG = irq_en;
+				}
+
+				/* STATUS is reverse direction */
+				UDC_EP_NUM_REG = is_in
+						? UDC_EP_SEL
+						: (UDC_EP_SEL|UDC_EP_DIR);
+				UDC_CTRL_REG = UDC_CLR_EP;
+				UDC_CTRL_REG = UDC_SET_FIFO_EN;
+				UDC_EP_NUM_REG = udc->ep0_in ? 0 : UDC_EP_DIR;
+
+				/* cleanup */
+				udc->ep0_pending = 0;
+				done(ep, req, 0);
+				req = 0;
+
+			/* non-empty DATA stage */
+			} else if (is_in) {
+				UDC_EP_NUM_REG = UDC_EP_SEL|UDC_EP_DIR;
+			} else {
+				if (udc->ep0_setup)
+					goto irq_wait;
+				UDC_EP_NUM_REG = UDC_EP_SEL;
+			}
+		} else {
+			is_in = ep->bEndpointAddress & USB_DIR_IN;
+			if (!ep->has_dma)
+				use_ep(ep, UDC_EP_SEL);
+			/* if ISO: SOF IRQs must be enabled/disabled! */
+		}
+
+		if (ep->has_dma)
+			(is_in ? next_in_dma : next_out_dma)(ep, req);
+		else if (req) {
+			if ((is_in ? write_fifo : read_fifo)(ep, req) == 1)
+				req = 0;
+			deselect_ep();
+			/* IN: 6 wait states before it'll tx */
+		}
+	}
+
+irq_wait:
+	/* irq handler advances the queue */
+	if (req != 0)
+		list_add_tail(&req->queue, &ep->queue);
+	spin_unlock_irqrestore(&udc->lock, flags);
+
+	return 0;
+}
+
+static int omap_ep_dequeue(struct usb_ep *_ep, struct usb_request *_req)
+{
+	struct omap_ep	*ep = container_of(_ep, struct omap_ep, ep);
+	struct omap_req	*req;
+	unsigned long	flags;
+
+	if (!_ep || !_req)
+		return -EINVAL;
+
+	spin_lock_irqsave(&ep->udc->lock, flags);
+
+	/* make sure it's actually queued on this endpoint */
+	list_for_each_entry (req, &ep->queue, queue) {
+		if (&req->req == _req)
+			break;
+	}
+	if (&req->req != _req) {
+		spin_unlock_irqrestore(&ep->udc->lock, flags);
+		return -EINVAL;
+	}
+
+	if (use_dma && ep->dma_channel && ep->queue.next == &req->queue) {
+		int channel = ep->dma_channel;
+
+		/* releasing the dma completion cancels the request,
+		 * reclaiming the channel restarts the queue
+		 */
+		dma_channel_release(ep);
+		dma_channel_claim(ep, channel);
+	} else 
+		done(ep, req, -ECONNRESET);
+	spin_unlock_irqrestore(&ep->udc->lock, flags);
+	return 0;
+}
+
+/*-------------------------------------------------------------------------*/
+
+static int omap_ep_set_halt(struct usb_ep *_ep, int value)
+{
+	struct omap_ep	*ep = container_of(_ep, struct omap_ep, ep);
+	unsigned long	flags;
+	int		status = -EOPNOTSUPP;
+
+	spin_lock_irqsave(&ep->udc->lock, flags);
+
+	/* just use protocol stalls for ep0; real halts are annoying */
+	if (ep->bEndpointAddress == 0) {
+		if (!ep->udc->ep0_pending)
+			status = -EINVAL;
+		else if (value) {
+			if (ep->udc->ep0_set_config) {
+				WARN("error changing config?\n");
+				UDC_SYSCON2_REG = UDC_CLR_CFG;
+			}
+			UDC_SYSCON2_REG = UDC_STALL_CMD;
+			ep->udc->ep0_pending = 0;
+			status = 0;
+		} else /* NOP */
+			status = 0;
+
+	/* otherwise, all active non-ISO endpoints can halt */
+	} else if (ep->bmAttributes != USB_ENDPOINT_XFER_ISOC && ep->desc) {
+
+		/* IN endpoints must already be idle */
+		if ((ep->bEndpointAddress & USB_DIR_IN)
+				&& !list_empty(&ep->queue)) { 
+			status = -EAGAIN;
+			goto done;
+		}
+
+		if (value) {
+			int	channel;
+
+			if (use_dma && ep->dma_channel
+					&& !list_empty(&ep->queue)) {
+				channel = ep->dma_channel;
+				dma_channel_release(ep);
+			} else
+				channel = 0;
+
+			use_ep(ep, UDC_EP_SEL);
+			if (UDC_STAT_FLG_REG & UDC_NON_ISO_FIFO_EMPTY) {
+				UDC_CTRL_REG = UDC_SET_HALT;
+				status = 0;
+			} else
+				status = -EAGAIN;
+			deselect_ep();
+
+			if (channel)
+				dma_channel_claim(ep, channel);
+		} else {
+			use_ep(ep, 0);
+			UDC_CTRL_REG = UDC_RESET_EP;
+			ep->ackwait = 0;
+			if (!(ep->bEndpointAddress & USB_DIR_IN))
+				UDC_CTRL_REG = UDC_SET_FIFO_EN;
+		}
+	}
+done:
+	VDBG("%s %s halt stat %d\n", ep->ep.name,
+		value ? "set" : "clear", status);
+
+	spin_unlock_irqrestore(&ep->udc->lock, flags);
+	return status;
+}
+
+static struct usb_ep_ops omap_ep_ops = {
+	.enable		= omap_ep_enable,
+	.disable	= omap_ep_disable,
+
+	.alloc_request	= omap_alloc_request,
+	.free_request	= omap_free_request,
+
+	.alloc_buffer	= omap_alloc_buffer,
+	.free_buffer	= omap_free_buffer,
+
+	.queue		= omap_ep_queue,
+	.dequeue	= omap_ep_dequeue,
+
+	.set_halt	= omap_ep_set_halt,
+	// fifo_status ... report bytes in fifo
+	// fifo_flush ... flush fifo
+};
+
+/*-------------------------------------------------------------------------*/
+
+static int omap_get_frame(struct usb_gadget *gadget)
+{
+	u16	sof = UDC_SOF_REG;
+	return (sof & UDC_TS_OK) ? (sof & UDC_TS) : -EL2NSYNC;
+}
+
+static int omap_wakeup(struct usb_gadget *gadget)
+{
+	struct omap_udc	*udc;
+	unsigned long	flags;
+	int		retval = -EHOSTUNREACH;
+
+	udc = container_of(gadget, struct omap_udc, gadget);
+
+	spin_lock_irqsave(&udc->lock, flags);
+	if (udc->devstat & UDC_SUS) {
+		/* NOTE:  OTG spec erratum says that OTG devices may
+		 * issue wakeups without host enable.
+		 */
+		if (udc->devstat & (UDC_B_HNP_ENABLE|UDC_R_WK_OK)) {
+			DBG("remote wakeup...\n");
+			UDC_SYSCON2_REG = UDC_RMT_WKP;
+			retval = 0;
+		}
+
+	/* NOTE:  non-OTG systems may use SRP TOO... */
+	} else if (!(udc->devstat & UDC_ATT)) {
+		if (udc->transceiver)
+			retval = otg_start_srp(udc->transceiver);
+	}
+	spin_unlock_irqrestore(&udc->lock, flags);
+
+	return retval;
+}
+
+static int
+omap_set_selfpowered(struct usb_gadget *gadget, int is_selfpowered)
+{
+	struct omap_udc	*udc;
+	unsigned long	flags;
+	u16		syscon1;
+
+	udc = container_of(gadget, struct omap_udc, gadget);
+	spin_lock_irqsave(&udc->lock, flags);
+	syscon1 = UDC_SYSCON1_REG;
+	if (is_selfpowered)
+		syscon1 |= UDC_SELF_PWR;
+	else
+		syscon1 &= ~UDC_SELF_PWR;
+	UDC_SYSCON1_REG = syscon1;
+	spin_unlock_irqrestore(&udc->lock, flags);
+
+	return 0;
+}
+
+static int can_pullup(struct omap_udc *udc)
+{
+	return udc->driver && udc->softconnect && udc->vbus_active;
+}
+
+static void pullup_enable(struct omap_udc *udc)
+{
+	UDC_SYSCON1_REG |= UDC_PULLUP_EN;
+#ifndef CONFIG_USB_OTG
+	OTG_CTRL_REG |= OTG_BSESSVLD;
+#endif
+	UDC_IRQ_EN_REG = UDC_DS_CHG_IE;
+}
+
+static void pullup_disable(struct omap_udc *udc)
+{
+#ifndef CONFIG_USB_OTG
+	OTG_CTRL_REG &= ~OTG_BSESSVLD;
+#endif
+	UDC_IRQ_EN_REG = UDC_DS_CHG_IE;
+	UDC_SYSCON1_REG &= ~UDC_PULLUP_EN;
+}
+
+/*
+ * Called by whatever detects VBUS sessions:  external transceiver
+ * driver, or maybe GPIO0 VBUS IRQ.
+ */
+static int omap_vbus_session(struct usb_gadget *gadget, int is_active)
+{
+	struct omap_udc	*udc;
+	unsigned long	flags;
+
+	udc = container_of(gadget, struct omap_udc, gadget);
+	spin_lock_irqsave(&udc->lock, flags);
+	VDBG("VBUS %s\n", is_active ? "on" : "off");
+	udc->vbus_active = (is_active != 0);
+	if (can_pullup(udc))
+		pullup_enable(udc);
+	else
+		pullup_disable(udc);
+	spin_unlock_irqrestore(&udc->lock, flags);
+	return 0;
+}
+
+static int omap_vbus_draw(struct usb_gadget *gadget, unsigned mA)
+{
+	struct omap_udc	*udc;
+
+	udc = container_of(gadget, struct omap_udc, gadget);
+	if (udc->transceiver)
+		return otg_set_power(udc->transceiver, mA);
+	return -EOPNOTSUPP;
+}
+
+static int omap_pullup(struct usb_gadget *gadget, int is_on)
+{
+	struct omap_udc	*udc;
+	unsigned long	flags;
+
+	udc = container_of(gadget, struct omap_udc, gadget);
+	spin_lock_irqsave(&udc->lock, flags);
+	udc->softconnect = (is_on != 0);
+	if (can_pullup(udc))
+		pullup_enable(udc);
+	else
+		pullup_disable(udc);
+	spin_unlock_irqrestore(&udc->lock, flags);
+	return 0;
+}
+
+static struct usb_gadget_ops omap_gadget_ops = {
+	.get_frame		= omap_get_frame,
+	.wakeup			= omap_wakeup,
+	.set_selfpowered	= omap_set_selfpowered,
+	.vbus_session		= omap_vbus_session,
+	.vbus_draw		= omap_vbus_draw,
+	.pullup			= omap_pullup,
+};
+
+/*-------------------------------------------------------------------------*/
+
+/* dequeue ALL requests; caller holds udc->lock */
+static void nuke(struct omap_ep *ep, int status)
+{
+	struct omap_req	*req;
+
+	ep->stopped = 1;
+
+	if (use_dma && ep->dma_channel)
+		dma_channel_release(ep);
+
+	use_ep(ep, 0);
+	UDC_CTRL_REG = UDC_CLR_EP;
+	if (ep->bEndpointAddress && ep->bmAttributes != USB_ENDPOINT_XFER_ISOC)
+		UDC_CTRL_REG = UDC_SET_HALT;
+
+	while (!list_empty(&ep->queue)) {
+		req = list_entry(ep->queue.next, struct omap_req, queue);
+		done(ep, req, status);
+	}
+}
+
+/* caller holds udc->lock */
+static void udc_quiesce(struct omap_udc *udc)
+{
+	struct omap_ep	*ep;
+
+	udc->gadget.speed = USB_SPEED_UNKNOWN;
+	nuke(&udc->ep[0], -ESHUTDOWN);
+	list_for_each_entry (ep, &udc->gadget.ep_list, ep.ep_list)
+		nuke(ep, -ESHUTDOWN);
+}
+
+/*-------------------------------------------------------------------------*/
+
+static void update_otg(struct omap_udc *udc)
+{
+	u16	devstat;
+
+	if (!udc->gadget.is_otg)
+		return;
+
+	if (OTG_CTRL_REG & OTG_ID)
+		devstat = UDC_DEVSTAT_REG;
+	else
+		devstat = 0;
+
+	udc->gadget.b_hnp_enable = !!(devstat & UDC_B_HNP_ENABLE);
+	udc->gadget.a_hnp_support = !!(devstat & UDC_A_HNP_SUPPORT);
+	udc->gadget.a_alt_hnp_support = !!(devstat & UDC_A_ALT_HNP_SUPPORT);
+
+	/* Enable HNP early, avoiding races on suspend irq path.
+	 * ASSUMES OTG state machine B_BUS_REQ input is true.
+	 */
+	if (udc->gadget.b_hnp_enable)
+		OTG_CTRL_REG = (OTG_CTRL_REG | OTG_B_HNPEN | OTG_B_BUSREQ)
+				& ~OTG_PULLUP;
+}
+
+static void ep0_irq(struct omap_udc *udc, u16 irq_src)
+{
+	struct omap_ep	*ep0 = &udc->ep[0];
+	struct omap_req	*req = 0;
+
+	ep0->irqs++;
+
+	/* Clear any pending requests and then scrub any rx/tx state
+	 * before starting to handle the SETUP request.
+	 */
+	if (irq_src & UDC_SETUP)
+		nuke(ep0, 0);
+
+	/* IN/OUT packets mean we're in the DATA or STATUS stage.  
+	 * This driver uses only uses protocol stalls (ep0 never halts),
+	 * and if we got this far the gadget driver already had a
+	 * chance to stall.  Tries to be forgiving of host oddities.
+	 *
+	 * NOTE:  the last chance gadget drivers have to stall control
+	 * requests is during their request completion callback.
+	 */
+	if (!list_empty(&ep0->queue))
+		req = container_of(ep0->queue.next, struct omap_req, queue);
+
+	/* IN == TX to host */
+	if (irq_src & UDC_EP0_TX) {
+		int	stat;
+
+		UDC_IRQ_SRC_REG = UDC_EP0_TX;
+		UDC_EP_NUM_REG = UDC_EP_SEL|UDC_EP_DIR;
+		stat = UDC_STAT_FLG_REG;
+		if (stat & UDC_ACK) {
+			if (udc->ep0_in) {
+				/* write next IN packet from response,
+				 * or set up the status stage.
+				 */
+				if (req)
+					stat = write_fifo(ep0, req);
+				UDC_EP_NUM_REG = UDC_EP_DIR;
+				if (!req && udc->ep0_pending) {
+					UDC_EP_NUM_REG = UDC_EP_SEL;
+					UDC_CTRL_REG = UDC_CLR_EP;
+					UDC_CTRL_REG = UDC_SET_FIFO_EN;
+					UDC_EP_NUM_REG = 0;
+					udc->ep0_pending = 0;
+				} /* else:  6 wait states before it'll tx */
+			} else {
+				/* ack status stage of OUT transfer */
+				UDC_EP_NUM_REG = UDC_EP_DIR;
+				if (req)
+					done(ep0, req, 0);
+			}
+			req = 0;
+		} else if (stat & UDC_STALL) {
+			UDC_CTRL_REG = UDC_CLR_HALT;
+			UDC_EP_NUM_REG = UDC_EP_DIR;
+		} else {
+			UDC_EP_NUM_REG = UDC_EP_DIR;
+		}
+	}
+
+	/* OUT == RX from host */
+	if (irq_src & UDC_EP0_RX) {
+		int	stat;
+
+		UDC_IRQ_SRC_REG = UDC_EP0_RX;
+		UDC_EP_NUM_REG = UDC_EP_SEL;
+		stat = UDC_STAT_FLG_REG;
+		if (stat & UDC_ACK) {
+			if (!udc->ep0_in) {
+				stat = 0;
+				/* read next OUT packet of request, maybe
+				 * reactiviting the fifo; stall on errors.
+				 */
+				if (!req || (stat = read_fifo(ep0, req)) < 0) {
+					UDC_SYSCON2_REG = UDC_STALL_CMD;
+					udc->ep0_pending = 0;
+					stat = 0;
+				} else if (stat == 0)
+					UDC_CTRL_REG = UDC_SET_FIFO_EN;
+				UDC_EP_NUM_REG = 0;
+				
+				/* activate status stage */
+				if (stat == 1) {
+					done(ep0, req, 0);
+					/* that may have STALLed ep0... */
+					UDC_EP_NUM_REG = UDC_EP_SEL|UDC_EP_DIR;
+					UDC_CTRL_REG = UDC_CLR_EP;
+					UDC_CTRL_REG = UDC_SET_FIFO_EN;
+					UDC_EP_NUM_REG = UDC_EP_DIR;
+					udc->ep0_pending = 0;
+				}
+			} else {
+				/* ack status stage of IN transfer */
+				UDC_EP_NUM_REG = 0;
+				if (req)
+					done(ep0, req, 0);
+			}
+		} else if (stat & UDC_STALL) {
+			UDC_CTRL_REG = UDC_CLR_HALT;
+			UDC_EP_NUM_REG = 0;
+		} else {
+			UDC_EP_NUM_REG = 0;
+		}
+	}
+
+	/* SETUP starts all control transfers */
+	if (irq_src & UDC_SETUP) {
+		union u {
+			u16			word[4];
+			struct usb_ctrlrequest	r;
+		} u;
+		int			status = -EINVAL;
+		struct omap_ep		*ep;
+
+		/* read the (latest) SETUP message */
+		do {
+			UDC_EP_NUM_REG = UDC_SETUP_SEL;
+			/* two bytes at a time */
+			u.word[0] = UDC_DATA_REG;
+			u.word[1] = UDC_DATA_REG;
+			u.word[2] = UDC_DATA_REG;
+			u.word[3] = UDC_DATA_REG;
+			UDC_EP_NUM_REG = 0;
+		} while (UDC_IRQ_SRC_REG & UDC_SETUP);
+		le16_to_cpus (&u.r.wValue);
+		le16_to_cpus (&u.r.wIndex);
+		le16_to_cpus (&u.r.wLength);
+
+		/* Delegate almost all control requests to the gadget driver,
+		 * except for a handful of ch9 status/feature requests that
+		 * hardware doesn't autodecode _and_ the gadget API hides.
+		 */
+		udc->ep0_in = (u.r.bRequestType & USB_DIR_IN) != 0;
+		udc->ep0_set_config = 0;
+		udc->ep0_pending = 1;
+		ep0->stopped = 0;
+		ep0->ackwait = 0;
+		switch (u.r.bRequest) {
+		case USB_REQ_SET_CONFIGURATION:
+			/* udc needs to know when ep != 0 is valid */
+			if (u.r.bRequestType != USB_RECIP_DEVICE)
+				goto delegate;
+			if (u.r.wLength != 0)
+				goto do_stall;
+			udc->ep0_set_config = 1;
+			udc->ep0_reset_config = (u.r.wValue == 0);
+			VDBG("set config %d\n", u.r.wValue);
+
+			/* update udc NOW since gadget driver may start
+			 * queueing requests immediately; clear config
+			 * later if it fails the request.
+			 */
+			if (udc->ep0_reset_config)
+				UDC_SYSCON2_REG = UDC_CLR_CFG;
+			else
+				UDC_SYSCON2_REG = UDC_DEV_CFG;
+			update_otg(udc);
+			goto delegate;
+		case USB_REQ_CLEAR_FEATURE:
+			/* clear endpoint halt */
+			if (u.r.bRequestType != USB_RECIP_ENDPOINT)
+				goto delegate;
+			if (u.r.wValue != USB_ENDPOINT_HALT
+					|| u.r.wLength != 0)
+				goto do_stall;
+			ep = &udc->ep[u.r.wIndex & 0xf];
+			if (ep != ep0) {
+				if (u.r.wIndex & USB_DIR_IN)
+					ep += 16;
+				if (ep->bmAttributes == USB_ENDPOINT_XFER_ISOC
+						|| !ep->desc)
+					goto do_stall;
+				use_ep(ep, 0);
+				UDC_CTRL_REG = UDC_RESET_EP;
+				ep->ackwait = 0;
+				if (!(ep->bEndpointAddress & USB_DIR_IN))
+					UDC_CTRL_REG = UDC_SET_FIFO_EN;
+			}
+			VDBG("%s halt cleared by host\n", ep->name);
+			goto ep0out_status_stage;
+		case USB_REQ_SET_FEATURE:
+			/* set endpoint halt */
+			if (u.r.bRequestType != USB_RECIP_ENDPOINT)
+				goto delegate;
+			if (u.r.wValue != USB_ENDPOINT_HALT
+					|| u.r.wLength != 0)
+				goto do_stall;
+			ep = &udc->ep[u.r.wIndex & 0xf];
+			if (u.r.wIndex & USB_DIR_IN)
+				ep += 16;
+			if (ep->bmAttributes == USB_ENDPOINT_XFER_ISOC
+					|| ep == ep0 || !ep->desc)
+				goto do_stall;
+			if (use_dma && ep->has_dma) {
+				/* this has rude side-effects (aborts) and
+				 * can't really work if DMA-IN is active
+				 */
+				DBG("%s host set_halt, NYET \n", ep->name);
+				goto do_stall;
+			}
+			use_ep(ep, 0);
+			/* can't halt if fifo isn't empty... */
+			UDC_CTRL_REG = UDC_CLR_EP;
+			UDC_CTRL_REG = UDC_SET_HALT;
+			VDBG("%s halted by host\n", ep->name);
+ep0out_status_stage:
+			status = 0;
+			UDC_EP_NUM_REG = UDC_EP_SEL|UDC_EP_DIR;
+			UDC_CTRL_REG = UDC_CLR_EP;
+			UDC_CTRL_REG = UDC_SET_FIFO_EN;
+			UDC_EP_NUM_REG = UDC_EP_DIR;
+			udc->ep0_pending = 0;
+			break;
+		case USB_REQ_GET_STATUS:
+			/* return interface status.  if we were pedantic,
+			 * we'd detect non-existent interfaces, and stall.
+			 */
+			if (u.r.bRequestType
+					!= (USB_DIR_IN|USB_RECIP_INTERFACE))
+				goto delegate;
+			/* return two zero bytes */
+			UDC_EP_NUM_REG = UDC_EP_SEL|UDC_EP_DIR;
+			UDC_DATA_REG = 0;
+			UDC_CTRL_REG = UDC_SET_FIFO_EN;
+			UDC_EP_NUM_REG = UDC_EP_DIR;
+			status = 0;
+			VDBG("GET_STATUS, interface %d\n", u.r.wIndex);
+			/* next, status stage */
+			break;
+		default:
+delegate:
+			/* activate the ep0out fifo right away */
+			if (!udc->ep0_in && u.r.wLength) {
+				UDC_EP_NUM_REG = 0;
+				UDC_CTRL_REG = UDC_SET_FIFO_EN;
+			}
+
+			/* gadget drivers see class/vendor specific requests,
+			 * {SET,GET}_{INTERFACE,DESCRIPTOR,CONFIGURATION},
+			 * and more
+			 */
+			VDBG("SETUP %02x.%02x v%04x i%04x l%04x\n",
+				u.r.bRequestType, u.r.bRequest,
+				u.r.wValue, u.r.wIndex, u.r.wLength);
+
+			/* The gadget driver may return an error here,
+			 * causing an immediate protocol stall.
+			 *
+			 * Else it must issue a response, either queueing a
+			 * response buffer for the DATA stage, or halting ep0
+			 * (causing a protocol stall, not a real halt).  A
+			 * zero length buffer means no DATA stage.
+			 *
+			 * It's fine to issue that response after the setup()
+			 * call returns, and this IRQ was handled.
+			 */
+			udc->ep0_setup = 1;
+			spin_unlock(&udc->lock);
+			status = udc->driver->setup (&udc->gadget, &u.r);
+			spin_lock(&udc->lock);
+			udc->ep0_setup = 0;
+		}
+
+		if (status < 0) {
+do_stall:
+			VDBG("req %02x.%02x protocol STALL; stat %d\n",
+					u.r.bRequestType, u.r.bRequest, status);
+			if (udc->ep0_set_config) {
+				if (udc->ep0_reset_config)
+					WARN("error resetting config?\n");
+				else
+					UDC_SYSCON2_REG = UDC_CLR_CFG;
+			}
+			UDC_SYSCON2_REG = UDC_STALL_CMD;
+			udc->ep0_pending = 0;
+		}
+	}
+}
+
+/*-------------------------------------------------------------------------*/
+
+#define OTG_FLAGS (UDC_B_HNP_ENABLE|UDC_A_HNP_SUPPORT|UDC_A_ALT_HNP_SUPPORT)
+
+static void devstate_irq(struct omap_udc *udc, u16 irq_src)
+{
+	u16	devstat, change;
+
+	devstat = UDC_DEVSTAT_REG;
+	change = devstat ^ udc->devstat;
+	udc->devstat = devstat;
+
+	if (change & (UDC_USB_RESET|UDC_ATT)) {
+		udc_quiesce(udc);
+
+		if (change & UDC_ATT) {
+			/* driver for any external transceiver will
+			 * have called omap_vbus_session() already
+			 */
+			if (devstat & UDC_ATT) {
+				udc->gadget.speed = USB_SPEED_FULL;
+				VDBG("connect\n");
+				if (!udc->transceiver)
+					pullup_enable(udc);
+				// if (driver->connect) call it
+			} else if (udc->gadget.speed != USB_SPEED_UNKNOWN) {
+				udc->gadget.speed = USB_SPEED_UNKNOWN;
+				if (!udc->transceiver)
+					pullup_disable(udc);
+				DBG("disconnect, gadget %s\n",
+					udc->driver->driver.name);
+				if (udc->driver->disconnect) {
+					spin_unlock(&udc->lock);
+					udc->driver->disconnect(&udc->gadget);
+					spin_lock(&udc->lock);
+				}
+			}
+			change &= ~UDC_ATT;
+		}
+
+		if (change & UDC_USB_RESET) {
+			if (devstat & UDC_USB_RESET) {
+				VDBG("RESET=1\n");
+			} else {
+				udc->gadget.speed = USB_SPEED_FULL;
+				INFO("USB reset done, gadget %s\n",
+					udc->driver->driver.name);
+				/* ep0 traffic is legal from now on */
+				UDC_IRQ_EN_REG = UDC_DS_CHG_IE | UDC_EP0_IE;
+			}
+			change &= ~UDC_USB_RESET;
+		}
+	}
+	if (change & UDC_SUS) {
+		if (udc->gadget.speed != USB_SPEED_UNKNOWN) {
+			// FIXME tell isp1301 to suspend/resume (?)
+			if (devstat & UDC_SUS) {
+				VDBG("suspend\n");
+				update_otg(udc);
+				/* HNP could be under way already */
+				if (udc->gadget.speed == USB_SPEED_FULL
+						&& udc->driver->suspend) {
+					spin_unlock(&udc->lock);
+					udc->driver->suspend(&udc->gadget);
+					spin_lock(&udc->lock);
+				}
+			} else {
+				VDBG("resume\n");
+				if (udc->gadget.speed == USB_SPEED_FULL
+						&& udc->driver->resume) {
+					spin_unlock(&udc->lock);
+					udc->driver->resume(&udc->gadget);
+					spin_lock(&udc->lock);
+				}
+			}
+		}
+		change &= ~UDC_SUS;
+	}
+	if (change & OTG_FLAGS) {
+		update_otg(udc);
+		change &= ~OTG_FLAGS;
+	}
+
+	change &= ~(UDC_CFG|UDC_DEF|UDC_ADD);
+	if (change)
+		VDBG("devstat %03x, ignore change %03x\n",
+			devstat,  change);
+
+	UDC_IRQ_SRC_REG = UDC_DS_CHG;
+}
+
+static irqreturn_t
+omap_udc_irq(int irq, void *_udc, struct pt_regs *r)
+{
+	struct omap_udc	*udc = _udc;
+	u16		irq_src;
+	irqreturn_t	status = IRQ_NONE;
+	unsigned long	flags;
+
+	spin_lock_irqsave(&udc->lock, flags);
+	irq_src = UDC_IRQ_SRC_REG;
+
+	/* Device state change (usb ch9 stuff) */
+	if (irq_src & UDC_DS_CHG) {
+		devstate_irq(_udc, irq_src);
+		status = IRQ_HANDLED;
+		irq_src &= ~UDC_DS_CHG;
+	}
+
+	/* EP0 control transfers */
+	if (irq_src & (UDC_EP0_RX|UDC_SETUP|UDC_EP0_TX)) {
+		ep0_irq(_udc, irq_src);
+		status = IRQ_HANDLED;
+		irq_src &= ~(UDC_EP0_RX|UDC_SETUP|UDC_EP0_TX);
+	}
+
+	/* DMA transfer completion */
+	if (use_dma && (irq_src & (UDC_TXN_DONE|UDC_RXN_CNT|UDC_RXN_EOT))) {
+		dma_irq(_udc, irq_src);
+		status = IRQ_HANDLED;
+		irq_src &= ~(UDC_TXN_DONE|UDC_RXN_CNT|UDC_RXN_EOT);
+	}
+
+	irq_src &= ~(UDC_SOF|UDC_EPN_TX|UDC_EPN_RX);
+	if (irq_src)
+		DBG("udc_irq, unhandled %03x\n", irq_src);
+	spin_unlock_irqrestore(&udc->lock, flags);
+
+	return status;
+}
+
+static irqreturn_t
+omap_udc_pio_irq(int irq, void *_dev, struct pt_regs *r)
+{
+	u16		epn_stat, irq_src;
+	irqreturn_t	status = IRQ_NONE;
+	struct omap_ep	*ep;
+	int		epnum;
+	struct omap_udc	*udc = _dev;
+	struct omap_req	*req;
+	unsigned long	flags;
+
+	spin_lock_irqsave(&udc->lock, flags);
+	epn_stat = UDC_EPN_STAT_REG;
+	irq_src = UDC_IRQ_SRC_REG;
+
+	/* handle OUT first, to avoid some wasteful NAKs */
+	if (irq_src & UDC_EPN_RX) {
+		epnum = (epn_stat >> 8) & 0x0f;
+		UDC_IRQ_SRC_REG = UDC_EPN_RX;
+		status = IRQ_HANDLED;
+		ep = &udc->ep[epnum];
+		ep->irqs++;
+
+		if (!list_empty(&ep->queue)) {
+			UDC_EP_NUM_REG = epnum | UDC_EP_SEL;
+			if ((UDC_STAT_FLG_REG & UDC_ACK)) {
+				int stat;
+				req = container_of(ep->queue.next,
+						struct omap_req, queue);
+				stat = read_fifo(ep, req);
+				// FIXME double buffered PIO OUT should work
+			}
+			UDC_EP_NUM_REG = epnum;
+		}
+	}
+
+	/* then IN transfers */
+	if (irq_src & UDC_EPN_TX) {
+		epnum = epn_stat & 0x0f;
+		UDC_IRQ_SRC_REG = UDC_EPN_TX;
+		status = IRQ_HANDLED;
+		ep = &udc->ep[16 + epnum];
+		ep->irqs++;
+		ep->ackwait = 0;
+
+		if (!list_empty(&ep->queue)) {
+			UDC_EP_NUM_REG = epnum | UDC_EP_DIR | UDC_EP_SEL;
+			if ((UDC_STAT_FLG_REG & UDC_ACK)) {
+				req = container_of(ep->queue.next,
+						struct omap_req, queue);
+				(void) write_fifo(ep, req);
+			}
+			UDC_EP_NUM_REG = epnum | UDC_EP_DIR;
+			/* 6 wait states before it'll tx */
+		}
+	}
+
+	spin_unlock_irqrestore(&udc->lock, flags);
+	return status;
+}
+
+#ifdef	USE_ISO
+static irqreturn_t
+omap_udc_iso_irq(int irq, void *_dev, struct pt_regs *r)
+{
+	struct omap_udc	*udc = _dev;
+	struct omap_ep	*ep;
+	int		pending = 0;
+	unsigned long	flags;
+
+	spin_lock_irqsave(&udc->lock, flags);
+
+	/* handle all non-DMA ISO transfers */
+	list_for_each_entry (ep, &udc->iso, iso) {
+		u16		stat;
+		struct omap_req	*req;
+
+		if (ep->has_dma || list_empty(&ep->queue))
+			continue;
+		req = list_entry(ep->queue.next, struct omap_req, queue);
+
+		use_ep(ep, UDC_EP_SEL);
+		stat = UDC_STAT_FLG_REG;
+
+		/* NOTE: like the other controller drivers, this isn't
+		 * currently reporting lost or damaged frames.
+		 */
+		if (ep->bEndpointAddress & USB_DIR_IN) {
+			if (stat & UDC_MISS_IN)
+				/* done(ep, req, -EPROTO) */;
+			else
+				write_fifo(ep, req);
+		} else {
+			int	status = 0;
+
+			if (stat & UDC_NO_RXPACKET)
+				status = -EREMOTEIO;
+			else if (stat & UDC_ISO_ERR)
+				status = -EILSEQ;
+			else if (stat & UDC_DATA_FLUSH)
+				status = -ENOSR;
+
+			if (status)
+				/* done(ep, req, status) */;
+			else
+				read_fifo(ep, req);
+		}
+		deselect_ep();
+		/* 6 wait states before next EP */
+
+		ep->irqs++;
+		if (!list_empty(&ep->queue))
+			pending = 1;
+	}
+	if (!pending)
+		UDC_IRQ_EN_REG &= ~UDC_SOF_IE;
+	UDC_IRQ_SRC_REG = UDC_SOF;
+
+	spin_unlock_irqrestore(&udc->lock, flags);
+	return IRQ_HANDLED;
+}
+#endif
+
+/*-------------------------------------------------------------------------*/
+
+static struct omap_udc *udc;
+
+int usb_gadget_register_driver (struct usb_gadget_driver *driver)
+{
+	int		status = -ENODEV;
+	struct omap_ep	*ep;
+	unsigned long	flags;
+
+	/* basic sanity tests */
+	if (!udc)
+		return -ENODEV;
+	if (!driver
+			// FIXME if otg, check:  driver->is_otg
+			|| driver->speed < USB_SPEED_FULL
+			|| !driver->bind
+			|| !driver->unbind
+			|| !driver->setup)
+		return -EINVAL;
+
+	spin_lock_irqsave(&udc->lock, flags);
+	if (udc->driver) {
+		spin_unlock_irqrestore(&udc->lock, flags);
+		return -EBUSY;
+	}
+
+	/* reset state */
+	list_for_each_entry (ep, &udc->gadget.ep_list, ep.ep_list) {
+		ep->irqs = 0;
+		if (ep->bmAttributes == USB_ENDPOINT_XFER_ISOC)
+			continue;
+		use_ep(ep, 0);
+		UDC_CTRL_REG = UDC_SET_HALT;
+	}
+	udc->ep0_pending = 0;
+	udc->ep[0].irqs = 0;
+	udc->softconnect = 1;
+
+	/* hook up the driver */
+	driver->driver.bus = 0;
+	udc->driver = driver;
+	udc->gadget.dev.driver = &driver->driver;
+	spin_unlock_irqrestore(&udc->lock, flags);
+
+	status = driver->bind (&udc->gadget);
+	if (status) {
+		DBG("bind to %s --> %d\n", driver->driver.name, status);
+		udc->gadget.dev.driver = 0;
+		udc->driver = 0;
+		goto done;
+	}
+	DBG("bound to driver %s\n", driver->driver.name);
+
+	UDC_IRQ_SRC_REG = UDC_IRQ_SRC_MASK;
+
+	/* connect to bus through transceiver */
+	if (udc->transceiver) {
+		status = otg_set_peripheral(udc->transceiver, &udc->gadget);
+		if (status < 0) {
+			ERR("can't bind to transceiver\n");
+			driver->unbind (&udc->gadget);
+			udc->gadget.dev.driver = 0;
+			udc->driver = 0;
+			goto done;
+		}
+	} else {
+		if (can_pullup(udc))
+			pullup_enable (udc);
+		else
+			pullup_disable (udc);
+	}
+
+done:
+	return status;
+}
+EXPORT_SYMBOL(usb_gadget_register_driver);
+
+int usb_gadget_unregister_driver (struct usb_gadget_driver *driver)
+{
+	unsigned long	flags;
+	int		status = -ENODEV;
+
+	if (!udc)
+		return -ENODEV;
+	if (!driver || driver != udc->driver)
+		return -EINVAL;
+
+	if (udc->transceiver)
+		(void) otg_set_peripheral(udc->transceiver, 0);
+	else
+		pullup_disable(udc);
+
+	spin_lock_irqsave(&udc->lock, flags);
+	udc_quiesce(udc);
+	spin_unlock_irqrestore(&udc->lock, flags);
+
+	driver->unbind(&udc->gadget);
+	udc->gadget.dev.driver = 0;
+	udc->driver = 0;
+
+
+	DBG("unregistered driver '%s'\n", driver->driver.name);
+	return status;
+}
+EXPORT_SYMBOL(usb_gadget_unregister_driver);
+
+
+/*-------------------------------------------------------------------------*/
+
+#ifdef CONFIG_USB_OMAP_PROC
+
+#include <linux/seq_file.h>
+
+static const char proc_filename[] = "driver/udc";
+
+#define FOURBITS "%s%s%s%s"
+#define EIGHTBITS FOURBITS FOURBITS
+
+static void proc_ep_show(struct seq_file *s, struct omap_ep *ep)
+{
+	u16		stat_flg;
+	struct omap_req	*req;
+	char		buf[20];
+
+	use_ep(ep, 0);
+
+	if (use_dma && ep->has_dma)
+		snprintf(buf, sizeof buf, "(%cxdma%d lch%d) ",
+			(ep->bEndpointAddress & USB_DIR_IN) ? 't' : 'r',
+			ep->dma_channel - 1, ep->lch);
+	else
+		buf[0] = 0;
+
+	stat_flg = UDC_STAT_FLG_REG;
+	seq_printf(s,
+		"\n%s %sirqs %ld stat %04x " EIGHTBITS FOURBITS "%s\n",
+		ep->name, buf, ep->irqs, stat_flg,
+		(stat_flg & UDC_NO_RXPACKET) ? "no_rxpacket " : "",
+		(stat_flg & UDC_MISS_IN) ? "miss_in " : "",
+		(stat_flg & UDC_DATA_FLUSH) ? "data_flush " : "",
+		(stat_flg & UDC_ISO_ERR) ? "iso_err " : "",
+		(stat_flg & UDC_ISO_FIFO_EMPTY) ? "iso_fifo_empty " : "",
+		(stat_flg & UDC_ISO_FIFO_FULL) ? "iso_fifo_full " : "",
+		(stat_flg & UDC_EP_HALTED) ? "HALT " : "",
+		(stat_flg & UDC_STALL) ? "STALL " : "",
+		(stat_flg & UDC_NAK) ? "NAK " : "",
+		(stat_flg & UDC_ACK) ? "ACK " : "",
+		(stat_flg & UDC_FIFO_EN) ? "fifo_en " : "",
+		(stat_flg & UDC_NON_ISO_FIFO_EMPTY) ? "fifo_empty " : "",
+		(stat_flg & UDC_NON_ISO_FIFO_FULL) ? "fifo_full " : "");
+
+	if (list_empty (&ep->queue))
+		seq_printf(s, "\t(queue empty)\n");
+	else
+		list_for_each_entry (req, &ep->queue, queue)
+			seq_printf(s, "\treq %p len %d/%d buf %p\n",
+					&req->req, req->req.actual,
+					req->req.length, req->req.buf);
+}
+
+static char *trx_mode(unsigned m)
+{
+	switch (m) {
+	case 3:
+	case 0:		return "6wire";
+	case 1:		return "4wire";
+	case 2:		return "3wire";
+	default:	return "unknown";
+	}
+}
+
+static int proc_udc_show(struct seq_file *s, void *_)
+{
+	u32		tmp;
+	struct omap_ep	*ep;
+	unsigned long	flags;
+
+	spin_lock_irqsave(&udc->lock, flags);
+
+	seq_printf(s, "%s, version: " DRIVER_VERSION
+#ifdef	USE_ISO
+		" (iso)"
+#endif
+		"%s\n",
+		driver_desc,
+		use_dma ?  " (dma)" : "");
+
+	tmp = UDC_REV_REG & 0xff; 
+	seq_printf(s,
+		"UDC rev %d.%d, OTG rev %d.%d, fifo mode %d, gadget %s\n"
+		"hmc %d, transceiver %08x %s\n",
+		tmp >> 4, tmp & 0xf,
+		OTG_REV_REG >> 4, OTG_REV_REG & 0xf,
+		fifo_mode,
+		udc->driver ? udc->driver->driver.name : "(none)",
+		HMC, USB_TRANSCEIVER_CTRL_REG,
+		udc->transceiver ? udc->transceiver->label : "");
+
+	/* OTG controller registers */
+	tmp = OTG_SYSCON_1_REG;
+	seq_printf(s, "otg_syscon1 %08x usb2 %s, usb1 %s, usb0 %s,"
+			FOURBITS "\n", tmp,
+		trx_mode(USB2_TRX_MODE(tmp)),
+		trx_mode(USB1_TRX_MODE(tmp)),
+		trx_mode(USB0_TRX_MODE(tmp)),
+		(tmp & OTG_IDLE_EN) ? " !otg" : "",
+		(tmp & HST_IDLE_EN) ? " !host" : "",
+		(tmp & DEV_IDLE_EN) ? " !dev" : "",
+		(tmp & OTG_RESET_DONE) ? " reset_done" : " reset_active");
+	tmp = OTG_SYSCON_2_REG;
+	seq_printf(s, "otg_syscon2 %08x%s" EIGHTBITS
+			" b_ase_brst=%d hmc=%d\n", tmp,
+		(tmp & OTG_EN) ? " otg_en" : "",
+		(tmp & USBX_SYNCHRO) ? " synchro" : "",
+		// much more SRP stuff
+		(tmp & SRP_DATA) ? " srp_data" : "",
+		(tmp & SRP_VBUS) ? " srp_vbus" : "",
+		(tmp & OTG_PADEN) ? " otg_paden" : "",
+		(tmp & HMC_PADEN) ? " hmc_paden" : "",
+		(tmp & UHOST_EN) ? " uhost_en" : "",
+		(tmp & HMC_TLLSPEED) ? " tllspeed" : "",
+		(tmp & HMC_TLLATTACH) ? " tllattach" : "",
+		B_ASE_BRST(tmp),
+		OTG_HMC(tmp));
+	tmp = OTG_CTRL_REG;
+	seq_printf(s, "otg_ctrl    %06x" EIGHTBITS EIGHTBITS "%s\n", tmp,
+		(tmp & OTG_ASESSVLD) ? " asess" : "",
+		(tmp & OTG_BSESSEND) ? " bsess_end" : "",
+		(tmp & OTG_BSESSVLD) ? " bsess" : "",
+		(tmp & OTG_VBUSVLD) ? " vbus" : "",
+		(tmp & OTG_ID) ? " id" : "",
+		(tmp & OTG_DRIVER_SEL) ? " DEVICE" : " HOST",
+		(tmp & OTG_A_SETB_HNPEN) ? " a_setb_hnpen" : "",
+		(tmp & OTG_A_BUSREQ) ? " a_bus" : "",
+		(tmp & OTG_B_HNPEN) ? " b_hnpen" : "",
+		(tmp & OTG_B_BUSREQ) ? " b_bus" : "",
+		(tmp & OTG_BUSDROP) ? " busdrop" : "",
+		(tmp & OTG_PULLDOWN) ? " down" : "",
+		(tmp & OTG_PULLUP) ? " up" : "",
+		(tmp & OTG_DRV_VBUS) ? " drv" : "",
+		(tmp & OTG_PD_VBUS) ? " pd_vb" : "",
+		(tmp & OTG_PU_VBUS) ? " pu_vb" : "",
+		(tmp & OTG_PU_ID) ? " pu_id" : ""
+		);
+	tmp = OTG_IRQ_EN_REG;
+	seq_printf(s, "otg_irq_en  %04x" "\n", tmp);
+	tmp = OTG_IRQ_SRC_REG;
+	seq_printf(s, "otg_irq_src %04x" "\n", tmp);
+	tmp = OTG_OUTCTRL_REG;
+	seq_printf(s, "otg_outctrl %04x" "\n", tmp);
+	tmp = OTG_TEST_REG;
+	seq_printf(s, "otg_test    %04x" "\n", tmp);
+
+	tmp = UDC_SYSCON1_REG;
+	seq_printf(s, "\nsyscon1     %04x" EIGHTBITS "\n", tmp,
+		(tmp & UDC_CFG_LOCK) ? " cfg_lock" : "",
+		(tmp & UDC_DATA_ENDIAN) ? " data_endian" : "",
+		(tmp & UDC_DMA_ENDIAN) ? " dma_endian" : "",
+		(tmp & UDC_NAK_EN) ? " nak" : "",
+		(tmp & UDC_AUTODECODE_DIS) ? " autodecode_dis" : "",
+		(tmp & UDC_SELF_PWR) ? " self_pwr" : "",
+		(tmp & UDC_SOFF_DIS) ? " soff_dis" : "",
+		(tmp & UDC_PULLUP_EN) ? " PULLUP" : "");
+	// syscon2 is write-only
+
+	/* UDC controller registers */
+	if (!(tmp & UDC_PULLUP_EN)) {
+		seq_printf(s, "(suspended)\n");
+		spin_unlock_irqrestore(&udc->lock, flags);
+		return 0;
+	}
+
+	tmp = UDC_DEVSTAT_REG;
+	seq_printf(s, "devstat     %04x" EIGHTBITS "%s%s\n", tmp,
+		(tmp & UDC_B_HNP_ENABLE) ? " b_hnp" : "",
+		(tmp & UDC_A_HNP_SUPPORT) ? " a_hnp" : "",
+		(tmp & UDC_A_ALT_HNP_SUPPORT) ? " a_alt_hnp" : "",
+		(tmp & UDC_R_WK_OK) ? " r_wk_ok" : "",
+		(tmp & UDC_USB_RESET) ? " usb_reset" : "",
+		(tmp & UDC_SUS) ? " SUS" : "",
+		(tmp & UDC_CFG) ? " CFG" : "",
+		(tmp & UDC_ADD) ? " ADD" : "",
+		(tmp & UDC_DEF) ? " DEF" : "",
+		(tmp & UDC_ATT) ? " ATT" : "");
+	seq_printf(s, "sof         %04x\n", UDC_SOF_REG);
+	tmp = UDC_IRQ_EN_REG;
+	seq_printf(s, "irq_en      %04x" FOURBITS "%s\n", tmp,
+		(tmp & UDC_SOF_IE) ? " sof" : "",
+		(tmp & UDC_EPN_RX_IE) ? " epn_rx" : "",
+		(tmp & UDC_EPN_TX_IE) ? " epn_tx" : "",
+		(tmp & UDC_DS_CHG_IE) ? " ds_chg" : "",
+		(tmp & UDC_EP0_IE) ? " ep0" : "");
+	tmp = UDC_IRQ_SRC_REG;
+	seq_printf(s, "irq_src     %04x" EIGHTBITS "%s%s\n", tmp,
+		(tmp & UDC_TXN_DONE) ? " txn_done" : "",
+		(tmp & UDC_RXN_CNT) ? " rxn_cnt" : "",
+		(tmp & UDC_RXN_EOT) ? " rxn_eot" : "",
+		(tmp & UDC_SOF) ? " sof" : "",
+		(tmp & UDC_EPN_RX) ? " epn_rx" : "",
+		(tmp & UDC_EPN_TX) ? " epn_tx" : "",
+		(tmp & UDC_DS_CHG) ? " ds_chg" : "",
+		(tmp & UDC_SETUP) ? " setup" : "",
+		(tmp & UDC_EP0_RX) ? " ep0out" : "",
+		(tmp & UDC_EP0_TX) ? " ep0in" : "");
+	if (use_dma) {
+		unsigned i;
+
+		tmp = UDC_DMA_IRQ_EN_REG;
+		seq_printf(s, "dma_irq_en  %04x%s" EIGHTBITS "\n", tmp,
+			(tmp & UDC_TX_DONE_IE(3)) ? " tx2_done" : "",
+			(tmp & UDC_RX_CNT_IE(3)) ? " rx2_cnt" : "",
+			(tmp & UDC_RX_EOT_IE(3)) ? " rx2_eot" : "",
+
+			(tmp & UDC_TX_DONE_IE(2)) ? " tx1_done" : "",
+			(tmp & UDC_RX_CNT_IE(2)) ? " rx1_cnt" : "",
+			(tmp & UDC_RX_EOT_IE(2)) ? " rx1_eot" : "",
+
+			(tmp & UDC_TX_DONE_IE(1)) ? " tx0_done" : "",
+			(tmp & UDC_RX_CNT_IE(1)) ? " rx0_cnt" : "",
+			(tmp & UDC_RX_EOT_IE(1)) ? " rx0_eot" : "");
+
+		tmp = UDC_RXDMA_CFG_REG;
+		seq_printf(s, "rxdma_cfg   %04x\n", tmp);
+		if (tmp) {
+			for (i = 0; i < 3; i++) {
+				if ((tmp & (0x0f << (i * 4))) == 0)
+					continue;
+				seq_printf(s, "rxdma[%d]    %04x\n", i,
+						UDC_RXDMA_REG(i + 1));
+			}
+		}
+		tmp = UDC_TXDMA_CFG_REG;
+		seq_printf(s, "txdma_cfg   %04x\n", tmp);
+		if (tmp) {
+			for (i = 0; i < 3; i++) {
+				if (!(tmp & (0x0f << (i * 4))))
+					continue;
+				seq_printf(s, "txdma[%d]    %04x\n", i,
+						UDC_TXDMA_REG(i + 1));
+			}
+		}
+	}
+
+	tmp = UDC_DEVSTAT_REG;
+	if (tmp & UDC_ATT) {
+		proc_ep_show(s, &udc->ep[0]);
+		if (tmp & UDC_ADD) {
+			list_for_each_entry (ep, &udc->gadget.ep_list,
+					ep.ep_list) {
+				if (ep->desc)
+					proc_ep_show(s, ep);
+			}
+		}
+	}
+	spin_unlock_irqrestore(&udc->lock, flags);
+	return 0;
+}
+
+static int proc_udc_open(struct inode *inode, struct file *file)
+{
+	return single_open(file, proc_udc_show, 0);
+}
+
+static struct file_operations proc_ops = {
+	.open		= proc_udc_open,
+	.read		= seq_read,
+	.llseek		= seq_lseek,
+	.release	= single_release,
+};
+
+static void create_proc_file(void)
+{
+	struct proc_dir_entry *pde;
+
+	pde = create_proc_entry (proc_filename, 0, NULL);
+	if (pde)
+		pde->proc_fops = &proc_ops;
+}
+
+static void remove_proc_file(void)
+{
+	remove_proc_entry(proc_filename, 0);
+}
+
+#else
+
+static inline void create_proc_file(void) {}
+static inline void remove_proc_file(void) {}
+
+#endif
+
+/*-------------------------------------------------------------------------*/
+
+/* Before this controller can enumerate, we need to pick an endpoint
+ * configuration, or "fifo_mode"  That involves allocating 2KB of packet
+ * buffer space among the endpoints we'll be operating.
+ */
+static unsigned __init
+omap_ep_setup(char *name, u8 addr, u8 type,
+		unsigned buf, unsigned maxp, int dbuf)
+{
+	struct omap_ep	*ep;
+	u16		epn_rxtx = 0;
+
+	/* OUT endpoints first, then IN */
+	ep = &udc->ep[addr & 0xf];
+	if (addr & USB_DIR_IN)
+		ep += 16;
+
+	/* in case of ep init table bugs */
+	BUG_ON(ep->name[0]);
+
+	/* chip setup ... bit values are same for IN, OUT */
+	if (type == USB_ENDPOINT_XFER_ISOC) {
+		switch (maxp) {
+		case 8:		epn_rxtx = 0 << 12; break;
+		case 16:	epn_rxtx = 1 << 12; break;
+		case 32:	epn_rxtx = 2 << 12; break;
+		case 64:	epn_rxtx = 3 << 12; break;
+		case 128:	epn_rxtx = 4 << 12; break;
+		case 256:	epn_rxtx = 5 << 12; break;
+		case 512:	epn_rxtx = 6 << 12; break;
+		default:	BUG();
+		}
+		epn_rxtx |= UDC_EPN_RX_ISO;
+		dbuf = 1;
+	} else {
+		/* pio-out could potentially double-buffer,
+		 * as can (should!) DMA-IN
+		 */
+		if (!use_dma || (addr & USB_DIR_IN))
+			dbuf = 0;
+
+		switch (maxp) {
+		case 8:		epn_rxtx = 0 << 12; break;
+		case 16:	epn_rxtx = 1 << 12; break;
+		case 32:	epn_rxtx = 2 << 12; break;
+		case 64:	epn_rxtx = 3 << 12; break;
+		default:	BUG();
+		}
+		if (dbuf && addr)
+			epn_rxtx |= UDC_EPN_RX_DB;
+	}
+	if (addr)
+		epn_rxtx |= UDC_EPN_RX_VALID;
+	BUG_ON(buf & 0x07);
+	epn_rxtx |= buf >> 3;
+
+	DBG("%s addr %02x rxtx %04x maxp %d%s buf %d\n",
+		name, addr, epn_rxtx, maxp, dbuf ? "x2" : "", buf);
+
+	if (addr & USB_DIR_IN)
+		UDC_EP_TX_REG(addr & 0xf) = epn_rxtx;
+	else
+		UDC_EP_RX_REG(addr) = epn_rxtx;
+
+	/* next endpoint's buffer starts after this one's */
+	buf += maxp;
+	if (dbuf)
+		buf += maxp;
+	BUG_ON(buf > 2048);
+
+	/* set up driver data structures */
+	BUG_ON(strlen(name) >= sizeof ep->name);
+	strlcpy(ep->name, name, sizeof ep->name);
+	INIT_LIST_HEAD(&ep->queue);
+	INIT_LIST_HEAD(&ep->iso);
+	ep->bEndpointAddress = addr;
+	ep->bmAttributes = type;
+	ep->double_buf = dbuf;
+	ep->udc = udc; 
+
+	ep->ep.name = ep->name;
+	ep->ep.ops = &omap_ep_ops;
+	ep->ep.maxpacket = ep->maxpacket = maxp;
+	list_add_tail (&ep->ep.ep_list, &udc->gadget.ep_list);
+
+	return buf;
+}
+
+static void omap_udc_release(struct device *dev)
+{
+	complete(udc->done);
+	kfree (udc);
+	udc = 0;
+}
+
+static int __init
+omap_udc_setup(struct platform_device *odev, struct otg_transceiver *xceiv)
+{
+	unsigned	tmp, buf;
+
+	/* abolish any previous hardware state */
+	UDC_SYSCON1_REG = 0;
+	UDC_IRQ_EN_REG = 0;
+	UDC_IRQ_SRC_REG = UDC_IRQ_SRC_MASK;
+	UDC_DMA_IRQ_EN_REG = 0;
+	UDC_RXDMA_CFG_REG = 0;
+	UDC_TXDMA_CFG_REG = 0;
+
+	/* UDC_PULLUP_EN gates the chip clock */
+	// OTG_SYSCON_1_REG |= DEV_IDLE_EN;
+
+	udc = kmalloc (sizeof *udc, SLAB_KERNEL);
+	if (!udc)
+		return -ENOMEM;
+
+	memset(udc, 0, sizeof *udc);
+	spin_lock_init (&udc->lock);
+
+	udc->gadget.ops = &omap_gadget_ops;
+	udc->gadget.ep0 = &udc->ep[0].ep;
+	INIT_LIST_HEAD(&udc->gadget.ep_list);
+	INIT_LIST_HEAD(&udc->iso);
+	udc->gadget.speed = USB_SPEED_UNKNOWN;
+	udc->gadget.name = driver_name;
+
+	device_initialize(&udc->gadget.dev);
+	strcpy (udc->gadget.dev.bus_id, "gadget");
+	udc->gadget.dev.release = omap_udc_release;
+	udc->gadget.dev.parent = &odev->dev;
+	if (use_dma)
+		udc->gadget.dev.dma_mask = odev->dev.dma_mask;
+
+	udc->transceiver = xceiv;
+
+	/* ep0 is special; put it right after the SETUP buffer */
+	buf = omap_ep_setup("ep0", 0, USB_ENDPOINT_XFER_CONTROL,
+			8 /* after SETUP */, 64 /* maxpacket */, 0);
+	list_del_init(&udc->ep[0].ep.ep_list);
+
+	/* initially disable all non-ep0 endpoints */
+	for (tmp = 1; tmp < 15; tmp++) {
+		UDC_EP_RX_REG(tmp) = 0;
+		UDC_EP_TX_REG(tmp) = 0;
+	}
+
+#define OMAP_BULK_EP(name,addr) \
+	buf = omap_ep_setup(name "-bulk", addr, \
+			USB_ENDPOINT_XFER_BULK, buf, 64, 1);
+#define OMAP_INT_EP(name,addr, maxp) \
+	buf = omap_ep_setup(name "-int", addr, \
+			USB_ENDPOINT_XFER_INT, buf, maxp, 0);
+#define OMAP_ISO_EP(name,addr, maxp) \
+	buf = omap_ep_setup(name "-iso", addr, \
+			USB_ENDPOINT_XFER_ISOC, buf, maxp, 1);
+
+	switch (fifo_mode) {
+	case 0:
+		OMAP_BULK_EP("ep1in",  USB_DIR_IN  | 1);
+		OMAP_BULK_EP("ep2out", USB_DIR_OUT | 2);
+		OMAP_INT_EP("ep3in",   USB_DIR_IN  | 3, 16);
+		break;
+	case 1:
+		OMAP_BULK_EP("ep1in",  USB_DIR_IN  | 1);
+		OMAP_BULK_EP("ep2out", USB_DIR_OUT | 2);
+		OMAP_BULK_EP("ep3in",  USB_DIR_IN  | 3);
+		OMAP_BULK_EP("ep4out", USB_DIR_OUT | 4);
+
+		OMAP_BULK_EP("ep5in",  USB_DIR_IN  | 5);
+		OMAP_BULK_EP("ep5out", USB_DIR_OUT | 5);
+		OMAP_BULK_EP("ep6in",  USB_DIR_IN  | 6);
+		OMAP_BULK_EP("ep6out", USB_DIR_OUT | 6);
+
+		OMAP_BULK_EP("ep7in",  USB_DIR_IN  | 7);
+		OMAP_BULK_EP("ep7out", USB_DIR_OUT | 7);
+		OMAP_BULK_EP("ep8in",  USB_DIR_IN  | 8);
+		OMAP_BULK_EP("ep8out", USB_DIR_OUT | 8);
+
+		OMAP_INT_EP("ep9in",   USB_DIR_IN  | 9, 16);
+		OMAP_INT_EP("ep10out", USB_DIR_IN  | 10, 16);
+		OMAP_INT_EP("ep11in",  USB_DIR_IN  | 9, 16);
+		OMAP_INT_EP("ep12out", USB_DIR_IN  | 10, 16);
+		break;
+
+#ifdef	USE_ISO
+	case 2:			/* mixed iso/bulk */
+		OMAP_ISO_EP("ep1in",   USB_DIR_IN  | 1, 256);
+		OMAP_ISO_EP("ep2out",  USB_DIR_OUT | 2, 256);
+		OMAP_ISO_EP("ep3in",   USB_DIR_IN  | 3, 128);
+		OMAP_ISO_EP("ep4out",  USB_DIR_OUT | 4, 128);
+
+		OMAP_INT_EP("ep5in",   USB_DIR_IN  | 5, 16);
+
+		OMAP_BULK_EP("ep6in",  USB_DIR_IN  | 6);
+		OMAP_BULK_EP("ep7out", USB_DIR_OUT | 7);
+		OMAP_INT_EP("ep8in",   USB_DIR_IN  | 8, 16);
+		break;
+	case 3:			/* mixed bulk/iso */
+		OMAP_BULK_EP("ep1in",  USB_DIR_IN  | 1);
+		OMAP_BULK_EP("ep2out", USB_DIR_OUT | 2);
+		OMAP_INT_EP("ep3in",   USB_DIR_IN  | 3, 16);
+
+		OMAP_BULK_EP("ep4in",  USB_DIR_IN  | 4);
+		OMAP_BULK_EP("ep5out", USB_DIR_OUT | 5);
+		OMAP_INT_EP("ep6in",   USB_DIR_IN  | 6, 16);
+
+		OMAP_ISO_EP("ep7in",   USB_DIR_IN  | 7, 256);
+		OMAP_ISO_EP("ep8out",  USB_DIR_OUT | 8, 256);
+		OMAP_INT_EP("ep9in",   USB_DIR_IN  | 9, 16);
+		break;
+#endif
+
+	/* add more modes as needed */
+
+	default:
+		ERR("unsupported fifo_mode #%d\n", fifo_mode);
+		return -ENODEV;
+	}
+	UDC_SYSCON1_REG = UDC_CFG_LOCK|UDC_SELF_PWR;
+	INFO("fifo mode %d, %d bytes not used\n", fifo_mode, 2048 - buf);
+	return 0;
+}
+
+static int __init omap_udc_probe(struct device *dev)
+{
+	struct platform_device	*odev = to_platform_device(dev);
+	int			status = -ENODEV;
+	int			hmc;
+	struct otg_transceiver	*xceiv = 0;
+	const char		*type = 0;
+	struct omap_usb_config	*config = dev->platform_data;
+
+	/* NOTE:  "knows" the order of the resources! */
+	if (!request_mem_region(odev->resource[0].start, 
+			odev->resource[0].end - odev->resource[0].start + 1,
+			driver_name)) {
+		DBG("request_mem_region failed\n");
+		return -EBUSY;
+	}
+
+	INFO("OMAP UDC rev %d.%d, OTG rev %d.%d, %s receptacle\n",
+		UDC_REV_REG >> 4, UDC_REV_REG & 0xf,
+		OTG_REV_REG >> 4, OTG_REV_REG & 0xf,
+		config->otg ? "Mini-AB" : "B/Mini-B");
+
+	/* use the mode given to us by board init code */
+	hmc = HMC;
+	switch (hmc) {
+	case 3:
+	case 11:
+	case 19:
+	case 25:
+		xceiv = otg_get_transceiver();
+		if (!xceiv) {
+			DBG("external transceiver not registered!\n");
+			goto cleanup0;
+		}
+		type = xceiv->label;
+		break;
+	case 0:			/* POWERUP DEFAULT == 0 */
+	case 4:
+	case 12:
+	case 20:
+		type = "INTEGRATED";
+		break;
+	case 21:			/* internal loopback */
+		type = "(loopback)";
+		break;
+	case 14:			/* transceiverless */
+		type = "(none)";
+		break;
+
+	default:
+		ERR("unrecognized UDC HMC mode %d\n", hmc);
+		return -ENODEV;
+	}
+	INFO("hmc mode %d, transceiver %s\n", hmc, type);
+
+	/* a "gadget" abstracts/virtualizes the controller */
+	status = omap_udc_setup(odev, xceiv);
+	if (status) {
+		goto cleanup0;
+	}
+	xceiv = 0;
+	// "udc" is now valid
+	pullup_disable(udc);
+	udc->gadget.is_otg = (config->otg != 0);
+
+	/* USB general purpose IRQ:  ep0, state changes, dma, etc */
+	status = request_irq(odev->resource[1].start, omap_udc_irq,
+			SA_SAMPLE_RANDOM, driver_name, udc);
+	if (status != 0) {
+		ERR( "can't get irq %ld, err %d\n",
+			odev->resource[1].start, status);
+		goto cleanup1;
+	}
+
+	/* USB "non-iso" IRQ (PIO for all but ep0) */
+	status = request_irq(odev->resource[2].start, omap_udc_pio_irq,
+			SA_SAMPLE_RANDOM, "omap_udc pio", udc);
+	if (status != 0) {
+		ERR( "can't get irq %ld, err %d\n",
+			odev->resource[2].start, status);
+		goto cleanup2;
+	}
+#ifdef	USE_ISO
+	status = request_irq(odev->resource[3].start, omap_udc_iso_irq,
+			SA_INTERRUPT, "omap_udc iso", udc);
+	if (status != 0) {
+		ERR("can't get irq %ld, err %d\n",
+			odev->resource[3].start, status);
+		goto cleanup3;
+	}
+#endif
+
+	create_proc_file();
+	device_add(&udc->gadget.dev);
+	return 0;
+
+#ifdef	USE_ISO
+cleanup3:
+	free_irq(odev->resource[2].start, udc);
+#endif
+
+cleanup2:
+	free_irq(odev->resource[1].start, udc);
+
+cleanup1:
+	kfree (udc);
+	udc = 0;
+
+cleanup0:
+	if (xceiv)
+		put_device(xceiv->dev);
+	release_mem_region(odev->resource[0].start,
+			odev->resource[0].end - odev->resource[0].start + 1);
+	return status;
+}
+
+static int __exit omap_udc_remove(struct device *dev)
+{
+	struct platform_device	*odev = to_platform_device(dev);
+	DECLARE_COMPLETION(done);
+
+	if (!udc)
+		return -ENODEV;
+
+	udc->done = &done;
+
+	pullup_disable(udc);
+	if (udc->transceiver) {
+		put_device(udc->transceiver->dev);
+		udc->transceiver = 0;
+	}
+	UDC_SYSCON1_REG = 0;
+
+	remove_proc_file();
+
+#ifdef	USE_ISO
+	free_irq(odev->resource[3].start, udc);
+#endif
+	free_irq(odev->resource[2].start, udc);
+	free_irq(odev->resource[1].start, udc);
+
+	release_mem_region(odev->resource[0].start,
+			odev->resource[0].end - odev->resource[0].start + 1);
+
+	device_unregister(&udc->gadget.dev);
+	wait_for_completion(&done);
+
+	return 0;
+}
+
+/* suspend/resume/wakeup from sysfs (echo > power/state) */
+
+static int omap_udc_suspend(struct device *dev, u32 state, u32 level)
+{
+	if (level != 0)
+		return 0;
+
+	DBG("suspend, state %d\n", state);
+	omap_pullup(&udc->gadget, 0);
+	udc->gadget.dev.power.power_state = 3;
+	udc->gadget.dev.parent->power.power_state = 3;
+	return 0;
+}
+
+static int omap_udc_resume(struct device *dev, u32 level)
+{
+	if (level != 0)
+		return 0;
+
+	DBG("resume + wakeup/SRP\n");
+	udc->gadget.dev.parent->power.power_state = 0;
+	udc->gadget.dev.power.power_state = 0;
+	omap_pullup(&udc->gadget, 1);
+
+	/* maybe the host would enumerate us if we nudged it */
+	msleep(100);
+	return omap_wakeup(&udc->gadget);
+}
+
+/*-------------------------------------------------------------------------*/
+
+static struct device_driver udc_driver = {
+	.name		= (char *) driver_name,
+	.bus		= &platform_bus_type,
+	.probe		= omap_udc_probe,
+	.remove		= __exit_p(omap_udc_remove),
+	.suspend	= omap_udc_suspend,
+	.resume		= omap_udc_resume,
+};
+
+static int __init udc_init(void)
+{
+	/* should work on many OMAP systems with at most minor changes,
+	 * but the 1510 doesn't have an OTG controller.
+	 */
+	if (cpu_is_omap1510()) {
+		DBG("no OMAP1510 support yet\n");
+		return -ENODEV;
+	}
+	INFO("%s, version: " DRIVER_VERSION "%s\n", driver_desc,
+		use_dma ?  " (dma)" : "");
+	return driver_register(&udc_driver);
+}
+module_init(udc_init);
+
+static void __exit udc_exit(void)
+{
+	driver_unregister(&udc_driver);
+}
+module_exit(udc_exit);
+
+MODULE_DESCRIPTION(DRIVER_DESC);
+MODULE_LICENSE("GPL");
+
diff -Nru a/drivers/usb/gadget/omap_udc.h b/drivers/usb/gadget/omap_udc.h
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/drivers/usb/gadget/omap_udc.h	2004-10-18 14:57:23 -07:00
@@ -0,0 +1,199 @@
+/*
+ * omap_udc.h -- for omap 3.2 udc, with OTG support
+ *
+ * 2004 (C) Texas Instruments, Inc.
+ * 2004 (C) David Brownell
+ */
+
+/*
+ * USB device/endpoint management registers
+ */
+#define UDC_REG(offset)              __REG16(UDC_BASE + (offset))
+
+#define	UDC_REV_REG			UDC_REG(0x0)	/* Revision */
+#define	UDC_EP_NUM_REG			UDC_REG(0x4)	/* Which endpoint */
+#	define	UDC_SETUP_SEL		(1 << 6)
+#	define	UDC_EP_SEL		(1 << 5)
+#	define	UDC_EP_DIR		(1 << 4)
+	/* low 4 bits for endpoint number */
+#define	UDC_DATA_REG			UDC_REG(0x08)	/* Endpoint FIFO */
+#define	UDC_CTRL_REG			UDC_REG(0x0C)	/* Endpoint control */
+#	define	UDC_CLR_HALT		(1 << 7)
+#	define	UDC_SET_HALT		(1 << 6)
+#	define	UDC_SET_FIFO_EN		(1 << 2)
+#	define	UDC_CLR_EP		(1 << 1)
+#	define	UDC_RESET_EP		(1 << 0)
+#define	UDC_STAT_FLG_REG		UDC_REG(0x10)	/* Endpoint status */
+#	define	UDC_NO_RXPACKET		(1 << 15)
+#	define	UDC_MISS_IN		(1 << 14)
+#	define	UDC_DATA_FLUSH		(1 << 13)
+#	define	UDC_ISO_ERR		(1 << 12)
+#	define	UDC_ISO_FIFO_EMPTY	(1 << 9)
+#	define	UDC_ISO_FIFO_FULL	(1 << 8)
+#	define	UDC_EP_HALTED		(1 << 6)
+#	define	UDC_STALL		(1 << 5)
+#	define	UDC_NAK			(1 << 4)
+#	define	UDC_ACK			(1 << 3)
+#	define	UDC_FIFO_EN		(1 << 2)
+#	define	UDC_NON_ISO_FIFO_EMPTY	(1 << 1)
+#	define	UDC_NON_ISO_FIFO_FULL	(1 << 0)
+#define	UDC_RXFSTAT_REG			UDC_REG(0x14)	/* OUT bytecount */
+#define	UDC_SYSCON1_REG			UDC_REG(0x18)	/* System config 1 */
+#	define	UDC_CFG_LOCK		(1 << 8)
+#	define	UDC_DATA_ENDIAN		(1 << 7)
+#	define	UDC_DMA_ENDIAN		(1 << 6)
+#	define	UDC_NAK_EN		(1 << 4)
+#	define	UDC_AUTODECODE_DIS	(1 << 3)
+#	define	UDC_SELF_PWR		(1 << 2)
+#	define	UDC_SOFF_DIS		(1 << 1)
+#	define	UDC_PULLUP_EN		(1 << 0)
+#define	UDC_SYSCON2_REG			UDC_REG(0x1C)	/* System config 2 */
+#	define	UDC_RMT_WKP		(1 << 6)
+#	define	UDC_STALL_CMD		(1 << 5)
+#	define	UDC_DEV_CFG		(1 << 3)
+#	define	UDC_CLR_CFG		(1 << 2)
+#define	UDC_DEVSTAT_REG			UDC_REG(0x20)	/* Device status */
+#	define	UDC_B_HNP_ENABLE	(1 << 9)
+#	define	UDC_A_HNP_SUPPORT	(1 << 8)
+#	define	UDC_A_ALT_HNP_SUPPORT	(1 << 7)
+#	define	UDC_R_WK_OK		(1 << 6)
+#	define	UDC_USB_RESET		(1 << 5)
+#	define	UDC_SUS			(1 << 4)
+#	define	UDC_CFG			(1 << 3)
+#	define	UDC_ADD			(1 << 2)
+#	define	UDC_DEF			(1 << 1)
+#	define	UDC_ATT			(1 << 0)
+#define	UDC_SOF_REG			UDC_REG(0x24)	/* Start of frame */
+#	define	UDC_FT_LOCK		(1 << 12)
+#	define	UDC_TS_OK		(1 << 11)
+#	define	UDC_TS			0x03ff
+#define	UDC_IRQ_EN_REG			UDC_REG(0x28)	/* Interrupt enable */
+#	define	UDC_SOF_IE		(1 << 7)
+#	define	UDC_EPN_RX_IE		(1 << 5)
+#	define	UDC_EPN_TX_IE		(1 << 4)
+#	define	UDC_DS_CHG_IE		(1 << 3)
+#	define	UDC_EP0_IE		(1 << 0)
+#define	UDC_DMA_IRQ_EN_REG		UDC_REG(0x2C)	/* DMA irq enable */
+	/* rx/tx dma channels numbered 1-3 not 0-2 */
+#	define	UDC_TX_DONE_IE(n)	(1 << (4 * (n) - 2))
+#	define	UDC_RX_CNT_IE(n)	(1 << (4 * (n) - 3))
+#	define	UDC_RX_EOT_IE(n)	(1 << (4 * (n) - 4))
+#define	UDC_IRQ_SRC_REG			UDC_REG(0x30)	/* Interrupt source */
+#	define	UDC_TXN_DONE		(1 << 10)
+#	define	UDC_RXN_CNT		(1 << 9)
+#	define	UDC_RXN_EOT		(1 << 8)
+#	define	UDC_SOF			(1 << 7)
+#	define	UDC_EPN_RX		(1 << 5)
+#	define	UDC_EPN_TX		(1 << 4)
+#	define	UDC_DS_CHG		(1 << 3)
+#	define	UDC_SETUP		(1 << 2)
+#	define	UDC_EP0_RX		(1 << 1)
+#	define	UDC_EP0_TX		(1 << 0)
+#	define	UDC_IRQ_SRC_MASK	0x7bf
+#define	UDC_EPN_STAT_REG		UDC_REG(0x34)	/* EP irq status */
+#define	UDC_DMAN_STAT_REG		UDC_REG(0x38)	/* DMA irq status */
+#	define	UDC_DMA_RX_SB		(1 << 12)
+#	define	UDC_DMA_RX_SRC(x)	(((x)>>8) & 0xf)
+#	define	UDC_DMA_TX_SRC(x)	(((x)>>0) & 0xf)
+
+
+/* DMA configuration registers:  up to three channels in each direction.  */
+#define	UDC_RXDMA_CFG_REG		UDC_REG(0x40)	/* 3 eps for RX DMA */
+#define	UDC_TXDMA_CFG_REG		UDC_REG(0x44)	/* 3 eps for TX DMA */
+#define	UDC_DATA_DMA_REG		UDC_REG(0x48)	/* rx/tx fifo addr */
+
+/* rx/tx dma control, numbering channels 1-3 not 0-2 */
+#define	UDC_TXDMA_REG(chan)		UDC_REG(0x50 - 4 + 4 * (chan))
+#	define UDC_TXN_EOT		(1 << 15)	/* bytes vs packets */
+#	define UDC_TXN_START		(1 << 14)	/* start transfer */
+#	define UDC_TXN_TSC		0x03ff		/* units in xfer */
+#define	UDC_RXDMA_REG(chan)		UDC_REG(0x60 - 4 + 4 * (chan))
+#	define UDC_RXN_STOP		(1 << 15)	/* enable EOT irq */
+#	define UDC_RXN_TC		0x00ff		/* packets in xfer */
+
+
+/*
+ * Endpoint configuration registers (used before CFG_LOCK is set)
+ * UDC_EP_TX_REG(0) is unused
+ */
+#define	UDC_EP_RX_REG(endpoint)		UDC_REG(0x80 + (endpoint)*4)
+#	define	UDC_EPN_RX_VALID	(1 << 15)
+#	define	UDC_EPN_RX_DB		(1 << 14)
+	/* buffer size in bits 13, 12 */
+#	define	UDC_EPN_RX_ISO		(1 << 11)
+	/* buffer pointer in low 11 bits */
+#define	UDC_EP_TX_REG(endpoint)		UDC_REG(0xc0 + (endpoint)*4)
+	/* same bitfields as in RX_REG */
+
+/*-------------------------------------------------------------------------*/
+
+struct omap_req {
+	struct usb_request		req;
+	struct list_head		queue;
+	unsigned			dma_bytes;
+	unsigned			mapped:1;
+};
+
+struct omap_ep {
+	struct usb_ep			ep;
+	struct list_head		queue;
+	unsigned long			irqs;
+	struct list_head		iso;
+	const struct usb_endpoint_descriptor	*desc;
+	char				name[14];
+	u16				maxpacket;
+	u8				bEndpointAddress;
+	u8				bmAttributes;
+	unsigned			double_buf:1;
+	unsigned			stopped:1;
+	unsigned			ackwait:1;
+	unsigned			has_dma:1;
+	u8				dma_channel;
+	int				lch;
+	struct omap_udc			*udc;
+};
+
+struct omap_udc {
+	struct usb_gadget		gadget;
+	struct usb_gadget_driver	*driver;
+	spinlock_t			lock;
+	struct omap_ep			ep[32];
+	u16				devstat;
+	struct otg_transceiver		*transceiver;
+	struct list_head		iso;
+	unsigned			softconnect:1;
+	unsigned			vbus_active:1;
+	unsigned			ep0_pending:1;
+	unsigned			ep0_in:1;
+	unsigned			ep0_set_config:1;
+	unsigned			ep0_reset_config:1;
+	unsigned			ep0_setup:1;
+	unsigned			hmc:6;
+
+	struct completion		*done;
+};
+
+/*-------------------------------------------------------------------------*/
+
+#ifdef DEBUG
+#define DBG(stuff...)		printk(KERN_DEBUG "udc: " stuff)
+#else
+#define DBG(stuff...)		do{}while(0)
+#endif
+
+#ifdef VERBOSE
+#    define VDBG		DBG
+#else
+#    define VDBG(stuff...)	do{}while(0)
+#endif
+
+#define ERR(stuff...)		printk(KERN_ERR "udc: " stuff)
+#define WARN(stuff...)		printk(KERN_WARNING "udc: " stuff)
+#define INFO(stuff...)		printk(KERN_INFO "udc: " stuff)
+
+/*-------------------------------------------------------------------------*/
+
+// #define	HMC_1510	((MOD_CONF_CTRL_0_REG >> 1) & 0x3f)
+#define	HMC_1610	(OTG_SYSCON_2_REG & 0x3f)
+#define	HMC		 HMC_1610
+
diff -Nru a/drivers/usb/gadget/pxa2xx_udc.c b/drivers/usb/gadget/pxa2xx_udc.c
--- a/drivers/usb/gadget/pxa2xx_udc.c	2004-10-18 14:56:33 -07:00
+++ b/drivers/usb/gadget/pxa2xx_udc.c	2004-10-18 14:56:33 -07:00
@@ -54,6 +54,7 @@
 #include <asm/mach-types.h>
 #include <asm/unaligned.h>
 #include <asm/hardware.h>
+#include <asm/arch/pxa-regs.h>
 
 #include <linux/usb_ch9.h>
 #include <linux/usb_gadget.h>
@@ -116,7 +117,7 @@
 
 #ifdef	USE_DMA
 static int use_dma = 1;
-MODULE_PARM (use_dma, "i");
+module_param(use_dma, bool, 0);
 MODULE_PARM_DESC (use_dma, "true to use dma");
 
 static void dma_nodesc_handler (int dmach, void *_ep, struct pt_regs *r);
@@ -146,7 +147,7 @@
  * ... so mode = 3 (or 7, 15, etc) does it for both
  */
 static ushort fifo_mode = 0;
-MODULE_PARM (fifo_mode, "h");
+module_param(fifo_mode, ushort, 0);
 MODULE_PARM_DESC (fifo_mode, "pxa2xx udc fifo mode");
 #endif
 
@@ -1508,7 +1509,7 @@
 	/* caller must be able to sleep in order to cope
 	 * with startup transients.
 	 */
-	schedule_timeout(HZ/10);
+	msleep(100);
 
 	/* enable suspend/resume and reset irqs */
 	udc_clear_mask_UDCCR(UDCCR_SRM | UDCCR_REM);
diff -Nru a/drivers/usb/gadget/serial.c b/drivers/usb/gadget/serial.c
--- a/drivers/usb/gadget/serial.c	2004-10-18 14:56:49 -07:00
+++ b/drivers/usb/gadget/serial.c	2004-10-18 14:56:49 -07:00
@@ -48,6 +48,8 @@
 #include <linux/usb_ch9.h>
 #include <linux/usb_gadget.h>
 
+#include "gadget_chips.h"
+
 
 /* Wait Cond */
 
@@ -123,8 +125,8 @@
 
 /* Defines */
 
-#define GS_VERSION_STR			"v0.1"
-#define GS_VERSION_NUM			0x0001
+#define GS_VERSION_STR			"v1.0"
+#define GS_VERSION_NUM			0x0100
 
 #define GS_LONG_NAME			"Gadget Serial"
 #define GS_SHORT_NAME			"g_serial"
@@ -173,164 +175,6 @@
 #endif /* G_SERIAL_DEBUG */
 
 
-/* USB Controllers */
-
-/*
- * NetChip 2280, PCI based.
- *
- * This has half a dozen configurable endpoints, four with dedicated
- * DMA channels to manage their FIFOs.  It supports high speed.
- * Those endpoints can be arranged in any desired configuration.
- */
-#ifdef	CONFIG_USB_GADGET_NET2280
-#define CHIP				"net2280"
-#define EP0_MAXPACKET			64
-static const char EP_OUT_NAME[] =	"ep-a";
-#define EP_OUT_NUM			2
-static const char EP_IN_NAME[] =	"ep-b";
-#define EP_IN_NUM			2
-#define HIGHSPEED
-#define SELFPOWER			USB_CONFIG_ATT_SELFPOWER
-
-extern int net2280_set_fifo_mode(struct usb_gadget *gadget, int mode);
-
-static inline void hw_optimize(struct usb_gadget *gadget)
-{
-	/* we can have bigger ep-a/ep-b fifos (2KB each, 4 packets
-	 * for highspeed bulk) because we're not using ep-c/ep-d.
-	 */
-	net2280_set_fifo_mode (gadget, 1);
-}
-#endif
-
-
-/*
- * Dummy_hcd, software-based loopback controller.
- *
- * This imitates the abilities of the NetChip 2280, so we will use
- * the same configuration.
- */
-#ifdef	CONFIG_USB_GADGET_DUMMY_HCD
-#define CHIP				"dummy"
-#define EP0_MAXPACKET			64
-static const char EP_OUT_NAME[] =	"ep-a";
-#define EP_OUT_NUM			2
-static const char EP_IN_NAME[] =	"ep-b";
-#define EP_IN_NUM			2
-#define HIGHSPEED
-#define SELFPOWER			USB_CONFIG_ATT_SELFPOWER
-
-/* no hw optimizations to apply */
-#define hw_optimize(g)			do {} while (0)
-#endif
-
-
-/*
- * PXA-2xx UDC:  widely used in second gen Linux-capable PDAs.
- *
- * This has fifteen fixed-function full speed endpoints, and it
- * can support all USB transfer types.
- *
- * These supports three or four configurations, with fixed numbers.
- * The hardware interprets SET_INTERFACE, net effect is that you
- * can't use altsettings or reset the interfaces independently.
- * So stick to a single interface.
- */
-#ifdef	CONFIG_USB_GADGET_PXA2XX
-#define CHIP				"pxa2xx"
-#define EP0_MAXPACKET			16
-static const char EP_OUT_NAME[] =	"ep2out-bulk";
-#define EP_OUT_NUM			2
-static const char EP_IN_NAME[] =	"ep1in-bulk";
-#define EP_IN_NUM			1
-#define SELFPOWER 			USB_CONFIG_ATT_SELFPOWER
-
-/* no hw optimizations to apply */
-#define hw_optimize(g)			do {} while (0)
-#endif
-
-#ifdef	CONFIG_USB_GADGET_OMAP
-#define CHIP			"omap"
-#define EP0_MAXPACKET			64
-static const char EP_OUT_NAME [] = "ep2out-bulk";
-#define EP_OUT_NUM	2
-static const char EP_IN_NAME [] = "ep1in-bulk";
-#define EP_IN_NUM	1
-#define SELFPOWER 			USB_CONFIG_ATT_SELFPOWER
-/* supports remote wakeup, but this driver doesn't */
-
-/* no hw optimizations to apply */
-#define hw_optimize(g) do {} while (0)
-#endif
-
-
-/*
- * SA-1100 UDC:  widely used in first gen Linux-capable PDAs.
- *
- * This has only two fixed function endpoints, which can only
- * be used for bulk (or interrupt) transfers.  (Plus control.)
- *
- * Since it can't flush its TX fifos without disabling the UDC,
- * the current configuration or altsettings can't change except
- * in special situations.  So this is a case of "choose it right
- * during enumeration" ...
- */
-#ifdef	CONFIG_USB_GADGET_SA1100
-#define CHIP				"sa1100"
-#define EP0_MAXPACKET			8
-static const char EP_OUT_NAME[] =	"ep1out-bulk";
-#define EP_OUT_NUM			1
-static const char EP_IN_NAME [] =	"ep2in-bulk";
-#define EP_IN_NUM			2
-#define SELFPOWER			USB_CONFIG_ATT_SELFPOWER
-
-/* no hw optimizations to apply */
-#define hw_optimize(g)			do {} while (0)
-#endif
-
-
-/*
- * Toshiba TC86C001 ("Goku-S") UDC
- *
- * This has three semi-configurable full speed bulk/interrupt endpoints.
- */
-#ifdef	CONFIG_USB_GADGET_GOKU
-#define CHIP				"goku"
-#define DRIVER_VERSION_NUM		0x0116
-#define EP0_MAXPACKET			8
-static const char EP_OUT_NAME [] =	"ep1-bulk";
-#define EP_OUT_NUM			1
-static const char EP_IN_NAME [] =	"ep2-bulk";
-#define EP_IN_NUM			2
-#define SELFPOWER			USB_CONFIG_ATT_SELFPOWER
-
-/* no hw optimizations to apply */
-#define hw_optimize(g)			do {} while (0)
-#endif
-
-/*
- * USB Controller Defaults
- */
-#ifndef EP0_MAXPACKET
-#error Configure some USB peripheral controller for g_serial!
-#endif
-
-#ifndef SELFPOWER
-/* default: say we rely on bus power */
-#define SELFPOWER   			0
-/* else value must be USB_CONFIG_ATT_SELFPOWER */
-#endif
-
-#ifndef	MAX_USB_POWER
-/* any hub supports this steady state bus power consumption */
-#define MAX_USB_POWER			100	/* mA */
-#endif
-
-#ifndef	WAKEUP
-/* default: this driver won't do remote wakeup */
-#define WAKEUP				0
-/* else value must be USB_CONFIG_ATT_WAKEUP */
-#endif
 
 /* Thanks to NetChip Technologies for donating this product ID.
  *
@@ -449,11 +293,17 @@
 static unsigned int gs_buf_get(struct gs_buf *gb, char *buf,
 	unsigned int count);
 
+/* external functions */
+extern int net2280_set_fifo_mode(struct usb_gadget *gadget, int mode);
+
 
 /* Globals */
 
 static struct gs_dev *gs_device;
 
+static const char *EP_IN_NAME;
+static const char *EP_OUT_NAME;
+
 static struct semaphore	gs_open_close_sem[GS_NUM_PORTS];
 
 static unsigned int read_q_size = GS_DEFAULT_READ_Q_SIZE;
@@ -483,7 +333,7 @@
 
 /* gadget driver struct */
 static struct usb_gadget_driver gs_gadget_driver = {
-#ifdef HIGHSPEED
+#ifdef CONFIG_USB_GADGET_DUALSPEED
 	.speed =		USB_SPEED_HIGH,
 #else
 	.speed =		USB_SPEED_FULL,
@@ -510,8 +360,9 @@
 #define GS_CONFIG_STR_ID	4
 
 /* static strings, in iso 8859/1 */
+static char manufacturer[40];
 static struct usb_string gs_strings[] = {
-	{ GS_MANUFACTURER_STR_ID, UTS_SYSNAME " " UTS_RELEASE " with " CHIP },
+	{ GS_MANUFACTURER_STR_ID, manufacturer },
 	{ GS_PRODUCT_STR_ID, GS_LONG_NAME },
 	{ GS_SERIAL_STR_ID, "0" },
 	{ GS_CONFIG_STR_ID, "Bulk" },
@@ -523,15 +374,13 @@
 	.strings =		gs_strings,
 };
 
-static const struct usb_device_descriptor gs_device_desc = {
+static struct usb_device_descriptor gs_device_desc = {
 	.bLength =		USB_DT_DEVICE_SIZE,
 	.bDescriptorType =	USB_DT_DEVICE,
 	.bcdUSB =		__constant_cpu_to_le16(0x0200),
 	.bDeviceClass =		USB_CLASS_VENDOR_SPEC,
-	.bMaxPacketSize0 =	EP0_MAXPACKET,
 	.idVendor =		__constant_cpu_to_le16(GS_VENDOR_ID),
 	.idProduct =		__constant_cpu_to_le16(GS_PRODUCT_ID),
-	.bcdDevice =		__constant_cpu_to_le16(GS_VERSION_NUM),
 	.iManufacturer =	GS_MANUFACTURER_STR_ID,
 	.iProduct =		GS_PRODUCT_STR_ID,
 	.iSerialNumber =	GS_SERIAL_STR_ID,
@@ -545,8 +394,8 @@
 	.bNumInterfaces =	GS_NUM_INTERFACES,
 	.bConfigurationValue =	GS_BULK_CONFIG_ID,
 	.iConfiguration =	GS_CONFIG_STR_ID,
-	.bmAttributes =		USB_CONFIG_ATT_ONE | SELFPOWER | WAKEUP,
-	.bMaxPower =		(MAX_USB_POWER + 1) / 2,
+	.bmAttributes =		USB_CONFIG_ATT_ONE | USB_CONFIG_ATT_SELFPOWER,
+	.bMaxPower =		1,
 };
 
 static const struct usb_interface_descriptor gs_interface_desc = {
@@ -557,46 +406,41 @@
 	.iInterface =		GS_CONFIG_STR_ID,
 };
 
-static const struct usb_endpoint_descriptor gs_fullspeed_in_desc = {
+static struct usb_endpoint_descriptor gs_fullspeed_in_desc = {
 	.bLength =		USB_DT_ENDPOINT_SIZE,
 	.bDescriptorType =	USB_DT_ENDPOINT,
-	.bEndpointAddress =	EP_IN_NUM | USB_DIR_IN,
+	.bEndpointAddress =	USB_DIR_IN,
 	.bmAttributes =		USB_ENDPOINT_XFER_BULK,
-	.wMaxPacketSize =	__constant_cpu_to_le16(64),
 };
 
-static const struct usb_endpoint_descriptor gs_fullspeed_out_desc = {
+static struct usb_endpoint_descriptor gs_fullspeed_out_desc = {
 	.bLength =		USB_DT_ENDPOINT_SIZE,
 	.bDescriptorType =	USB_DT_ENDPOINT,
-	.bEndpointAddress =	EP_OUT_NUM | USB_DIR_OUT,
+	.bEndpointAddress =	USB_DIR_OUT,
 	.bmAttributes =		USB_ENDPOINT_XFER_BULK,
-	.wMaxPacketSize =	__constant_cpu_to_le16(64),
 };
 
-static const struct usb_endpoint_descriptor gs_highspeed_in_desc = {
+static struct usb_endpoint_descriptor gs_highspeed_in_desc = {
 	.bLength =		USB_DT_ENDPOINT_SIZE,
 	.bDescriptorType =	USB_DT_ENDPOINT,
-	.bEndpointAddress =	EP_IN_NUM | USB_DIR_IN,
 	.bmAttributes =		USB_ENDPOINT_XFER_BULK,
 	.wMaxPacketSize =	__constant_cpu_to_le16(512),
 };
 
-static const struct usb_endpoint_descriptor gs_highspeed_out_desc = {
+static struct usb_endpoint_descriptor gs_highspeed_out_desc = {
 	.bLength =		USB_DT_ENDPOINT_SIZE,
 	.bDescriptorType =	USB_DT_ENDPOINT,
-	.bEndpointAddress =	EP_OUT_NUM | USB_DIR_OUT,
 	.bmAttributes =		USB_ENDPOINT_XFER_BULK,
 	.wMaxPacketSize =	__constant_cpu_to_le16(512),
 };
 
-#ifdef HIGHSPEED
-static const struct usb_qualifier_descriptor gs_qualifier_desc = {
+#ifdef CONFIG_USB_GADGET_DUALSPEED
+static struct usb_qualifier_descriptor gs_qualifier_desc = {
 	.bLength =		sizeof(struct usb_qualifier_descriptor),
 	.bDescriptorType =	USB_DT_DEVICE_QUALIFIER,
 	.bcdUSB =		__constant_cpu_to_le16 (0x0200),
 	.bDeviceClass =		USB_CLASS_VENDOR_SPEC,
 	/* assumes ep0 uses the same value for both speeds ... */
-	.bMaxPacketSize0 =	EP0_MAXPACKET,
 	.bNumConfigurations =	GS_NUM_CONFIGS,
 };
 #endif
@@ -608,17 +452,17 @@
 MODULE_LICENSE("GPL");
 
 #if G_SERIAL_DEBUG
-MODULE_PARM(debug, "i");
-MODULE_PARM_DESC(debug, "Enable debugging, 0=off, 1=on");
+module_param(debug, int, S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(debug, "Enable debugging, 0=off, 1=on, larger values for more messages");
 #endif
 
-MODULE_PARM(read_q_size, "i");
+module_param(read_q_size, int, 0);
 MODULE_PARM_DESC(read_q_size, "Read request queue size, default=32");
 
-MODULE_PARM(write_q_size, "i");
+module_param(write_q_size, int, 0);
 MODULE_PARM_DESC(write_q_size, "Write request queue size, default=32");
 
-MODULE_PARM(write_buf_size, "i");
+module_param(write_buf_size, int, 0);
 MODULE_PARM_DESC(write_buf_size, "Write buffer size, default=8192");
 
 module_init(gs_module_init);
@@ -1416,18 +1260,81 @@
 static int gs_bind(struct usb_gadget *gadget)
 {
 	int ret;
+	struct usb_ep *ep;
 	struct gs_dev *dev;
 
+	usb_ep_autoconfig_reset(gadget);
+
+	ep = usb_ep_autoconfig(gadget, &gs_fullspeed_in_desc);
+	if (!ep)
+		goto autoconf_fail;
+	EP_IN_NAME = ep->name;
+	ep->driver_data = ep;	/* claim the endpoint */
+
+	ep = usb_ep_autoconfig(gadget, &gs_fullspeed_out_desc);
+	if (!ep)
+		goto autoconf_fail;
+	EP_OUT_NAME = ep->name;
+	ep->driver_data = ep;	/* claim the endpoint */
+
+	/* device specific bcdDevice value in device descriptor */
+	if (gadget_is_net2280(gadget)) {
+		gs_device_desc.bcdDevice =
+			__constant_cpu_to_le16(GS_VERSION_NUM|0x0001);
+	} else if (gadget_is_pxa(gadget)) {
+		gs_device_desc.bcdDevice =
+			__constant_cpu_to_le16(GS_VERSION_NUM|0x0002);
+	} else if (gadget_is_sh(gadget)) {
+		gs_device_desc.bcdDevice =
+			__constant_cpu_to_le16(GS_VERSION_NUM|0x0003);
+	} else if (gadget_is_sa1100(gadget)) {
+		gs_device_desc.bcdDevice =
+			__constant_cpu_to_le16(GS_VERSION_NUM|0x0004);
+	} else if (gadget_is_goku(gadget)) {
+		gs_device_desc.bcdDevice =
+			__constant_cpu_to_le16(GS_VERSION_NUM|0x0005);
+	} else if (gadget_is_mq11xx(gadget)) {
+		gs_device_desc.bcdDevice =
+			__constant_cpu_to_le16(GS_VERSION_NUM|0x0006);
+	} else if (gadget_is_omap(gadget)) {
+		gs_device_desc.bcdDevice =
+			__constant_cpu_to_le16(GS_VERSION_NUM|0x0007);
+	} else if (gadget_is_lh7a40x(gadget)) {
+		gs_device_desc.bcdDevice =
+			__constant_cpu_to_le16(GS_VERSION_NUM|0x0008);
+	} else {
+		printk(KERN_WARNING "gs_bind: controller '%s' not recognized\n",
+			gadget->name);
+		/* unrecognized, but safe unless bulk is REALLY quirky */
+		gs_device_desc.bcdDevice =
+			__constant_cpu_to_le16(GS_VERSION_NUM|0x0099);
+	}
+
+	gs_device_desc.bMaxPacketSize0 = gadget->ep0->maxpacket;
+#ifdef CONFIG_USB_GADGET_DUALSPEED
+	/* assume ep0 uses the same packet size for both speeds */
+	gs_qualifier_desc.bMaxPacketSize0 = gs_device_desc.bMaxPacketSize0;
+	/* assume endpoints are dual-speed */
+	gs_highspeed_in_desc.bEndpointAddress =
+		gs_fullspeed_in_desc.bEndpointAddress;
+	gs_highspeed_out_desc.bEndpointAddress =
+		gs_fullspeed_out_desc.bEndpointAddress;
+#endif /* CONFIG_USB_GADGET_DUALSPEED */
+
+	usb_gadget_set_selfpowered(gadget);
+
 	gs_device = dev = kmalloc(sizeof(struct gs_dev), GFP_KERNEL);
 	if (dev == NULL)
 		return -ENOMEM;
 
-	set_gadget_data(gadget, dev);
+	snprintf (manufacturer, sizeof(manufacturer),
+		UTS_SYSNAME " " UTS_RELEASE " with %s", gadget->name);
 
 	memset(dev, 0, sizeof(struct gs_dev));
 	dev->dev_gadget = gadget;
 	spin_lock_init(&dev->dev_lock);
 	INIT_LIST_HEAD(&dev->dev_req_list);
+	set_gadget_data(gadget, dev);
 
 	if ((ret=gs_alloc_ports(dev, GFP_KERNEL)) != 0) {
 		printk(KERN_ERR "gs_bind: cannot allocate ports\n");
@@ -1450,6 +1357,10 @@
 		GS_LONG_NAME, GS_VERSION_STR);
 
 	return 0;
+
+autoconf_fail:
+	printk(KERN_ERR "gs_bind: cannot autoconfigure on %s\n", gadget->name);
+	return -ENODEV;
 }
 
 /*
@@ -1505,15 +1416,17 @@
 			memcpy(req->buf, &gs_device_desc, ret);
 			break;
 
-#ifdef HIGHSPEED
+#ifdef CONFIG_USB_GADGET_DUALSPEED
 		case USB_DT_DEVICE_QUALIFIER:
+			if (!gadget->is_dualspeed)
+				break;
 			ret = min(ctrl->wLength,
 				(u16)sizeof(struct usb_qualifier_descriptor));
 			memcpy(req->buf, &gs_qualifier_desc, ret);
 			break;
 
 		case USB_DT_OTHER_SPEED_CONFIG:
-#endif /* HIGHSPEED */
+#endif /* CONFIG_USB_GADGET_DUALSPEED */
 		case USB_DT_CONFIG:
 			ret = gs_build_config_desc(req->buf, gadget->speed,
 				ctrl->wValue >> 8, ctrl->wValue & 0xff);
@@ -1677,7 +1590,9 @@
 	if (config != GS_BULK_CONFIG_ID)
 		return -EINVAL;
 
-	hw_optimize(gadget);
+	/* device specific optimizations */
+	if (gadget_is_net2280(gadget))
+		net2280_set_fifo_mode(gadget, 1);
 
 	gadget_for_each_ep(ep, gadget) {
 
diff -Nru a/drivers/usb/gadget/zero.c b/drivers/usb/gadget/zero.c
--- a/drivers/usb/gadget/zero.c	2004-10-18 14:56:29 -07:00
+++ b/drivers/usb/gadget/zero.c	2004-10-18 14:56:29 -07:00
@@ -399,7 +399,7 @@
 static char				manufacturer [40];
 static char				serial [40];
 
-/* static strings, in iso 8859/1 */
+/* static strings, in UTF-8 */
 static struct usb_string		strings [] = {
 	{ STRING_MANUFACTURER, manufacturer, },
 	{ STRING_PRODUCT, longname, },
@@ -960,7 +960,8 @@
 		case USB_DT_STRING:
 			/* wIndex == language code.
 			 * this driver only handles one language, you can
-			 * add others even if they don't use iso8859/1
+			 * add string tables for other languages, using
+			 * any UTF-8 characters
 			 */
 			value = usb_gadget_get_string (&stringtab,
 					ctrl->wValue & 0xff, req->buf);
@@ -1185,6 +1186,8 @@
 		device_desc.bcdDevice = __constant_cpu_to_le16 (0x0207);
 	} else if (gadget_is_omap (gadget)) {
 		device_desc.bcdDevice = __constant_cpu_to_le16 (0x0208);
+	} else if (gadget_is_lh7a40x(gadget)) {
+		device_desc.bcdDevice = __constant_cpu_to_le16 (0x0209);
 	} else {
 		/* gadget zero is so simple (for now, no altsettings) that
 		 * it SHOULD NOT have problems with bulk-capable hardware.
@@ -1229,6 +1232,12 @@
 	hs_source_desc.bEndpointAddress = fs_source_desc.bEndpointAddress;
 	hs_sink_desc.bEndpointAddress = fs_sink_desc.bEndpointAddress;
 #endif
+
+	if (gadget->is_otg) {
+		otg_descriptor.bmAttributes |= USB_OTG_HNP,
+		source_sink_config.bmAttributes |= USB_CONFIG_ATT_WAKEUP;
+		loopback_config.bmAttributes |= USB_CONFIG_ATT_WAKEUP;
+	}
 
 	if (gadget->is_otg) {
 		otg_descriptor.bmAttributes |= USB_OTG_HNP,
diff -Nru a/drivers/usb/host/Kconfig b/drivers/usb/host/Kconfig
--- a/drivers/usb/host/Kconfig	2004-10-18 14:57:04 -07:00
+++ b/drivers/usb/host/Kconfig	2004-10-18 14:57:04 -07:00
@@ -52,6 +52,7 @@
 config USB_OHCI_HCD
 	tristate "OHCI HCD support"
 	depends on USB
+	select ISP1301_OMAP if MACH_OMAP_H2
 	---help---
 	  The Open Host Controller Interface (OHCI) is a standard for accessing
 	  USB 1.1 host controller hardware.  It does more in hardware than Intel's
diff -Nru a/drivers/usb/host/ehci-dbg.c b/drivers/usb/host/ehci-dbg.c
--- a/drivers/usb/host/ehci-dbg.c	2004-10-18 14:56:49 -07:00
+++ b/drivers/usb/host/ehci-dbg.c	2004-10-18 14:56:49 -07:00
@@ -119,16 +119,16 @@
 dbg_qtd (const char *label, struct ehci_hcd *ehci, struct ehci_qtd *qtd)
 {
 	ehci_dbg (ehci, "%s td %p n%08x %08x t%08x p0=%08x\n", label, qtd,
-		cpu_to_le32p (&qtd->hw_next),
-		cpu_to_le32p (&qtd->hw_alt_next),
-		cpu_to_le32p (&qtd->hw_token),
-		cpu_to_le32p (&qtd->hw_buf [0]));
+		le32_to_cpup (&qtd->hw_next),
+		le32_to_cpup (&qtd->hw_alt_next),
+		le32_to_cpup (&qtd->hw_token),
+		le32_to_cpup (&qtd->hw_buf [0]));
 	if (qtd->hw_buf [1])
 		ehci_dbg (ehci, "  p1=%08x p2=%08x p3=%08x p4=%08x\n",
-			cpu_to_le32p (&qtd->hw_buf [1]),
-			cpu_to_le32p (&qtd->hw_buf [2]),
-			cpu_to_le32p (&qtd->hw_buf [3]),
-			cpu_to_le32p (&qtd->hw_buf [4]));
+			le32_to_cpup (&qtd->hw_buf [1]),
+			le32_to_cpup (&qtd->hw_buf [2]),
+			le32_to_cpup (&qtd->hw_buf [3]),
+			le32_to_cpup (&qtd->hw_buf [4]));
 }
 
 static void __attribute__((__unused__))
@@ -331,14 +331,14 @@
 		default: tmp = '?'; break; \
 		}; tmp; })
 
-static inline char token_mark (u32 token)
+static inline char token_mark (__le32 token)
 {
-	token = le32_to_cpu (token);
-	if (token & QTD_STS_ACTIVE)
+	__u32 v = le32_to_cpu (token);
+	if (v & QTD_STS_ACTIVE)
 		return '*';
-	if (token & QTD_STS_HALT)
+	if (v & QTD_STS_HALT)
 		return '-';
-	if (!IS_SHORT_READ (token))
+	if (!IS_SHORT_READ (v))
 		return ' ';
 	/* tries to advance through hw_alt_next */
 	return '/';
@@ -371,25 +371,25 @@
 			mark = '.';	/* use hw_qtd_next */
 		/* else alt_next points to some other qtd */
 	}
-	scratch = cpu_to_le32p (&qh->hw_info1);
-	hw_curr = (mark == '*') ? cpu_to_le32p (&qh->hw_current) : 0;
+	scratch = le32_to_cpup (&qh->hw_info1);
+	hw_curr = (mark == '*') ? le32_to_cpup (&qh->hw_current) : 0;
 	temp = scnprintf (next, size,
 			"qh/%p dev%d %cs ep%d %08x %08x (%08x%c %s nak%d)",
 			qh, scratch & 0x007f,
 			speed_char (scratch),
 			(scratch >> 8) & 0x000f,
-			scratch, cpu_to_le32p (&qh->hw_info2),
-			cpu_to_le32p (&qh->hw_token), mark,
+			scratch, le32_to_cpup (&qh->hw_info2),
+			le32_to_cpup (&qh->hw_token), mark,
 			(__constant_cpu_to_le32 (QTD_TOGGLE) & qh->hw_token)
 				? "data1" : "data0",
-			(cpu_to_le32p (&qh->hw_alt_next) >> 1) & 0x0f);
+			(le32_to_cpup (&qh->hw_alt_next) >> 1) & 0x0f);
 	size -= temp;
 	next += temp;
 
 	/* hc may be modifying the list as we read it ... */
 	list_for_each (entry, &qh->qtd_list) {
 		td = list_entry (entry, struct ehci_qtd, qtd_list);
-		scratch = cpu_to_le32p (&td->hw_token);
+		scratch = le32_to_cpup (&td->hw_token);
 		mark = ' ';
 		if (hw_curr == td->qtd_dma)
 			mark = '*';
@@ -488,7 +488,8 @@
 	union ehci_shadow	p, *seen;
 	unsigned		temp, size, seen_count;
 	char			*next;
-	unsigned		i, tag;
+	unsigned		i;
+	__le32			tag;
 
 	if (!(seen = kmalloc (DBG_SCHED_LIMIT * sizeof *seen, SLAB_ATOMIC)))
 		return 0;
@@ -541,7 +542,7 @@
 				}
 				/* show more info the first time around */
 				if (temp == seen_count && p.ptr) {
-					u32	scratch = cpu_to_le32p (
+					u32	scratch = le32_to_cpup (
 							&p.qh->hw_info1);
 					struct ehci_qtd	*qtd;
 					char		*type = "";
diff -Nru a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c
--- a/drivers/usb/host/ehci-hcd.c	2004-10-18 14:56:33 -07:00
+++ b/drivers/usb/host/ehci-hcd.c	2004-10-18 14:56:33 -07:00
@@ -155,7 +155,7 @@
  * before driver shutdown. But it also seems to be caused by bugs in cardbus
  * bridge shutdown:  shutting down the bridge before the devices using it.
  */
-static int handshake (u32 *ptr, u32 mask, u32 done, int usec)
+static int handshake (u32 __iomem *ptr, u32 mask, u32 done, int usec)
 {
 	u32	result;
 
@@ -289,7 +289,7 @@
 static int bios_handoff (struct ehci_hcd *ehci, int where, u32 cap)
 {
 	if (cap & (1 << 16)) {
-		int msec = 500;
+		int msec = 5000;
 		struct pci_dev *pdev = to_pci_dev(ehci->hcd.self.controller);
 
 		/* request handoff to OS */
@@ -305,7 +305,10 @@
 		if (cap & (1 << 16)) {
 			ehci_err (ehci, "BIOS handoff failed (%d, %04x)\n",
 				where, cap);
-			return 1;
+			// some BIOS versions seem buggy...
+			// return 1;
+			ehci_warn (ehci, "continuing after BIOS bug...\n");
+			return 0;
 		} 
 		ehci_dbg (ehci, "BIOS handoff succeeded\n");
 	}
@@ -337,8 +340,8 @@
 
 	spin_lock_init (&ehci->lock);
 
-	ehci->caps = (struct ehci_caps *) hcd->regs;
-	ehci->regs = (struct ehci_regs *) (hcd->regs + 
+	ehci->caps = hcd->regs;
+	ehci->regs = (hcd->regs + 
 				HC_LENGTH (readl (&ehci->caps->hc_capbase)));
 	dbg_hcs_params (ehci, "reset");
 	dbg_hcc_params (ehci, "reset");
@@ -692,9 +695,18 @@
 	timer_action_done (ehci, TIMER_IO_WATCHDOG);
 	if (ehci->reclaim_ready)
 		end_unlink_async (ehci, regs);
+
+	/* another CPU may drop ehci->lock during a schedule scan while
+	 * it reports urb completions.  this flag guards against bogus
+	 * attempts at re-entrant schedule scanning.
+	 */
+	if (ehci->scanning)
+		return;
+	ehci->scanning = 1;
 	scan_async (ehci, regs);
 	if (ehci->next_uframe != -1)
 		scan_periodic (ehci, regs);
+	ehci->scanning = 0;
 
 	/* the IO watchdog guards against hardware or driver bugs that
 	 * misplace IRQs, and should let us run completely without IRQs.
diff -Nru a/drivers/usb/host/ehci-hub.c b/drivers/usb/host/ehci-hub.c
--- a/drivers/usb/host/ehci-hub.c	2004-10-18 14:57:04 -07:00
+++ b/drivers/usb/host/ehci-hub.c	2004-10-18 14:57:04 -07:00
@@ -146,8 +146,8 @@
 
 #else
 
-#define ehci_hub_suspend	0
-#define ehci_hub_resume		0
+#define ehci_hub_suspend	NULL
+#define ehci_hub_resume		NULL
 
 #endif	/* CONFIG_PM */
 
@@ -455,7 +455,7 @@
 #endif
 		dbg_port (ehci, "GetStatus", wIndex + 1, temp);
 		// we "know" this alignment is good, caller used kmalloc()...
-		*((u32 *) buf) = cpu_to_le32 (status);
+		*((__le32 *) buf) = cpu_to_le32 (status);
 		break;
 	case SetHubFeature:
 		switch (wValue) {
diff -Nru a/drivers/usb/host/ehci-mem.c b/drivers/usb/host/ehci-mem.c
--- a/drivers/usb/host/ehci-mem.c	2004-10-18 14:57:03 -07:00
+++ b/drivers/usb/host/ehci-mem.c	2004-10-18 14:57:03 -07:00
@@ -114,7 +114,7 @@
 		return qh;
 
 	memset (qh, 0, sizeof *qh);
-	kref_init(&qh->kref, qh_destroy);
+	kref_init(&qh->kref);
 	qh->ehci = ehci;
 	qh->qh_dma = dma;
 	// INIT_LIST_HEAD (&qh->qh_list);
@@ -139,7 +139,7 @@
 
 static inline void qh_put (struct ehci_qh *qh)
 {
-	kref_put(&qh->kref);
+	kref_put(&qh->kref, qh_destroy);
 }
 
 /*-------------------------------------------------------------------------*/
@@ -235,9 +235,9 @@
 	}
 
 	/* Hardware periodic table */
-	ehci->periodic = (u32 *)
+	ehci->periodic = (__le32 *)
 		dma_alloc_coherent (ehci->hcd.self.controller,
-			ehci->periodic_size * sizeof (u32),
+			ehci->periodic_size * sizeof(__le32),
 			&ehci->periodic_dma, 0);
 	if (ehci->periodic == 0) {
 		goto fail;
diff -Nru a/drivers/usb/host/ehci-q.c b/drivers/usb/host/ehci-q.c
--- a/drivers/usb/host/ehci-q.c	2004-10-18 14:56:49 -07:00
+++ b/drivers/usb/host/ehci-q.c	2004-10-18 14:56:49 -07:00
@@ -153,17 +153,9 @@
 			usb_pipein (urb->pipe) ? "in" : "out",
 			token, urb->status);
 
-		/* stall indicates some recovery action is needed */
-		if (urb->status == -EPIPE) {
-			int	pipe = urb->pipe;
-
-			if (!usb_pipecontrol (pipe))
-				usb_endpoint_halt (urb->dev,
-					usb_pipeendpoint (pipe),
-					usb_pipeout (pipe));
-
 		/* if async CSPLIT failed, try cleaning out the TT buffer */
-		} else if (urb->dev->tt && !usb_pipeint (urb->pipe)
+		if (urb->status != -EPIPE
+				&& urb->dev->tt && !usb_pipeint (urb->pipe)
 				&& ((token & QTD_STS_MMF) != 0
 					|| QTD_CERR(token) == 0)
 				&& (!ehci_is_ARC(ehci)
@@ -729,7 +721,7 @@
 
 static void qh_link_async (struct ehci_hcd *ehci, struct ehci_qh *qh)
 {
-	u32		dma = QH_NEXT (qh->qh_dma);
+	__le32		dma = QH_NEXT (qh->qh_dma);
 	struct ehci_qh	*head;
 
 	/* (re)start the async schedule? */
@@ -764,7 +756,7 @@
 
 /*-------------------------------------------------------------------------*/
 
-#define	QH_ADDR_MASK	__constant_le32_to_cpu(0x7f)
+#define	QH_ADDR_MASK	__constant_cpu_to_le32(0x7f)
 
 /*
  * For control/bulk/interrupt, return QH with these TDs appended.
@@ -848,7 +840,7 @@
 		if (likely (qtd != 0)) {
 			struct ehci_qtd		*dummy;
 			dma_addr_t		dma;
-			u32			token;
+			__le32			token;
 
 			/* to avoid racing the HC, use the dummy td instead of
 			 * the first td of our list (becomes new dummy).  both
diff -Nru a/drivers/usb/host/ehci-sched.c b/drivers/usb/host/ehci-sched.c
--- a/drivers/usb/host/ehci-sched.c	2004-10-18 14:56:28 -07:00
+++ b/drivers/usb/host/ehci-sched.c	2004-10-18 14:56:28 -07:00
@@ -44,7 +44,7 @@
  * @tag: hardware tag for type of this record
  */
 static union ehci_shadow *
-periodic_next_shadow (union ehci_shadow *periodic, int tag)
+periodic_next_shadow (union ehci_shadow *periodic, __le32 tag)
 {
 	switch (tag) {
 	case Q_TYPE_QH:
@@ -64,7 +64,7 @@
 static int periodic_unlink (struct ehci_hcd *ehci, unsigned frame, void *ptr)
 {
 	union ehci_shadow	*prev_p = &ehci->pshadow [frame];
-	u32			*hw_p = &ehci->periodic [frame];
+	__le32			*hw_p = &ehci->periodic [frame];
 	union ehci_shadow	here = *prev_p;
 	union ehci_shadow	*next_p;
 
@@ -98,7 +98,7 @@
 static unsigned short
 periodic_usecs (struct ehci_hcd *ehci, unsigned frame, unsigned uframe)
 {
-	u32			*hw_p = &ehci->periodic [frame];
+	__le32			*hw_p = &ehci->periodic [frame];
 	union ehci_shadow	*q = &ehci->pshadow [frame];
 	unsigned		usecs = 0;
 
@@ -196,7 +196,7 @@
 	 */
 	for (; frame < ehci->periodic_size; frame += period) {
 		union ehci_shadow	here;
-		u32			type;
+		__le32			type;
 
 		here = ehci->pshadow [frame];
 		type = Q_NEXT_TYPE (ehci->periodic [frame]);
@@ -403,7 +403,7 @@
 	unsigned		frame,
 	unsigned		uframe,
 	const struct ehci_qh	*qh,
-	u32			*c_maskp
+	__le32			*c_maskp
 )
 {
     	int		retval = -ENOSPC;
@@ -412,7 +412,7 @@
 		goto done;
 	if (!qh->c_usecs) {
 		retval = 0;
-		*c_maskp = cpu_to_le32 (0);
+		*c_maskp = 0;
 		goto done;
 	}
 
@@ -447,7 +447,7 @@
 {
 	int 		status;
 	unsigned	uframe;
-	u32		c_mask;
+	__le32		c_mask;
 	unsigned	frame;		/* 0..(qh->period - 1), or NO_FRAME */
 
 	qh->hw_next = EHCI_LIST_END;
@@ -1008,8 +1008,7 @@
 		uframe += period_uframes;
 	} while (uframe < mod);
 
-	stream->splits = stream->raw_mask << (uframe & 7);
-	cpu_to_le32s (&stream->splits);
+	stream->splits = cpu_to_le32(stream->raw_mask << (uframe & 7));
 	return 1;
 }
 
@@ -1812,7 +1811,7 @@
 
 	for (;;) {
 		union ehci_shadow	q, *q_p;
-		u32			type, *hw_p;
+		__le32			type, *hw_p;
 		unsigned		uframes;
 
 		/* don't scan past the live uframe */
diff -Nru a/drivers/usb/host/ehci.h b/drivers/usb/host/ehci.h
--- a/drivers/usb/host/ehci.h	2004-10-18 14:56:50 -07:00
+++ b/drivers/usb/host/ehci.h	2004-10-18 14:56:50 -07:00
@@ -52,12 +52,13 @@
 	/* async schedule support */
 	struct ehci_qh		*async;
 	struct ehci_qh		*reclaim;
-	int			reclaim_ready : 1;
+	unsigned		reclaim_ready : 1;
+	unsigned		scanning : 1;
 
 	/* periodic schedule support */
 #define	DEFAULT_I_TDPS		1024		/* some HCs can do less */
 	unsigned		periodic_size;
-	u32			*periodic;	/* hw periodic table */
+	__le32			*periodic;	/* hw periodic table */
 	dma_addr_t		periodic_dma;
 	unsigned		i_thresh;	/* uframes HC might cache */
 
@@ -70,9 +71,9 @@
 
 	/* glue to PCI and HCD framework */
 	struct usb_hcd		hcd;
-	struct ehci_caps	*caps;
-	struct ehci_regs	*regs;
-	u32			hcs_params;	/* cached register copy */
+	struct ehci_caps __iomem *caps;
+	struct ehci_regs __iomem *regs;
+	__u32			hcs_params;	/* cached register copy */
 
 	/* per-HC memory pools (could be per-bus, but ...) */
 	struct dma_pool		*qh_pool;	/* qh per active urb */
@@ -272,9 +273,9 @@
  */
 struct ehci_qtd {
 	/* first part defined by EHCI spec */
-	u32			hw_next;	  /* see EHCI 3.5.1 */
-	u32			hw_alt_next;      /* see EHCI 3.5.2 */
-	u32			hw_token;         /* see EHCI 3.5.3 */       
+	__le32			hw_next;	  /* see EHCI 3.5.1 */
+	__le32			hw_alt_next;      /* see EHCI 3.5.2 */
+	__le32			hw_token;         /* see EHCI 3.5.3 */       
 #define	QTD_TOGGLE	(1 << 31)	/* data toggle */
 #define	QTD_LENGTH(tok)	(((tok)>>16) & 0x7fff)
 #define	QTD_IOC		(1 << 15)	/* interrupt on complete */
@@ -288,8 +289,8 @@
 #define	QTD_STS_MMF	(1 << 2)	/* incomplete split transaction */
 #define	QTD_STS_STS	(1 << 1)	/* split transaction state */
 #define	QTD_STS_PING	(1 << 0)	/* issue PING? */
-	u32			hw_buf [5];        /* see EHCI 3.5.4 */
-	u32			hw_buf_hi [5];        /* Appendix B */
+	__le32			hw_buf [5];        /* see EHCI 3.5.4 */
+	__le32			hw_buf_hi [5];        /* Appendix B */
 
 	/* the rest is HCD-private */
 	dma_addr_t		qtd_dma;		/* qtd address */
@@ -349,18 +350,18 @@
 
 struct ehci_qh {
 	/* first part defined by EHCI spec */
-	u32			hw_next;	 /* see EHCI 3.6.1 */
-	u32			hw_info1;        /* see EHCI 3.6.2 */
+	__le32			hw_next;	 /* see EHCI 3.6.1 */
+	__le32			hw_info1;        /* see EHCI 3.6.2 */
 #define	QH_HEAD		0x00008000
-	u32			hw_info2;        /* see EHCI 3.6.2 */
-	u32			hw_current;	 /* qtd list - see EHCI 3.6.4 */
+	__le32			hw_info2;        /* see EHCI 3.6.2 */
+	__le32			hw_current;	 /* qtd list - see EHCI 3.6.4 */
 	
 	/* qtd overlay (hardware parts of a struct ehci_qtd) */
-	u32			hw_qtd_next;
-	u32			hw_alt_next;
-	u32			hw_token;
-	u32			hw_buf [5];
-	u32			hw_buf_hi [5];
+	__le32			hw_qtd_next;
+	__le32			hw_alt_next;
+	__le32			hw_token;
+	__le32			hw_buf [5];
+	__le32			hw_buf_hi [5];
 
 	/* the rest is HCD-private */
 	dma_addr_t		qh_dma;		/* address of qh */
@@ -396,7 +397,7 @@
 struct ehci_iso_packet {
 	/* These will be copied to iTD when scheduling */
 	u64			bufp;		/* itd->hw_bufp{,_hi}[pg] |= */
-	u32			transaction;	/* itd->hw_transaction[i] |= */
+	__le32			transaction;	/* itd->hw_transaction[i] |= */
 	u8			cross;		/* buf crosses pages */
 	/* for full speed OUT splits */
 	u16			buf1;
@@ -418,8 +419,8 @@
  */
 struct ehci_iso_stream {
 	/* first two fields match QH, but info1 == 0 */
-	u32			hw_next;
-	u32			hw_info1;
+	__le32			hw_next;
+	__le32			hw_info1;
 
 	u32			refcount;
 	u8			bEndpointAddress;
@@ -433,7 +434,7 @@
 	unsigned long		start;		/* jiffies */
 	unsigned long		rescheduled;
 	int			next_uframe;
-	u32			splits;
+	__le32			splits;
 
 	/* the rest is derived from the endpoint descriptor,
 	 * trusting urb->interval == f(epdesc->bInterval) and
@@ -446,12 +447,12 @@
 	unsigned		bandwidth;
 
 	/* This is used to initialize iTD's hw_bufp fields */
-	u32			buf0;		
-	u32			buf1;		
-	u32			buf2;
+	__le32			buf0;		
+	__le32			buf1;		
+	__le32			buf2;
 
 	/* this is used to initialize sITD's tt info */
-	u32			address;
+	__le32			address;
 };
 
 /*-------------------------------------------------------------------------*/
@@ -464,8 +465,8 @@
  */
 struct ehci_itd {
 	/* first part defined by EHCI spec */
-	u32			hw_next;           /* see EHCI 3.3.1 */
-	u32			hw_transaction [8]; /* see EHCI 3.3.2 */
+	__le32			hw_next;           /* see EHCI 3.3.1 */
+	__le32			hw_transaction [8]; /* see EHCI 3.3.2 */
 #define EHCI_ISOC_ACTIVE        (1<<31)        /* activate transfer this slot */
 #define EHCI_ISOC_BUF_ERR       (1<<30)        /* Data buffer error */
 #define EHCI_ISOC_BABBLE        (1<<29)        /* babble detected */
@@ -475,8 +476,8 @@
 
 #define ITD_ACTIVE	__constant_cpu_to_le32(EHCI_ISOC_ACTIVE)
 
-	u32			hw_bufp [7];	/* see EHCI 3.3.3 */ 
-	u32			hw_bufp_hi [7];	/* Appendix B */
+	__le32			hw_bufp [7];	/* see EHCI 3.3.3 */ 
+	__le32			hw_bufp_hi [7];	/* Appendix B */
 
 	/* the rest is HCD-private */
 	dma_addr_t		itd_dma;	/* for this itd */
@@ -503,11 +504,11 @@
  */
 struct ehci_sitd {
 	/* first part defined by EHCI spec */
-	u32			hw_next;
+	__le32			hw_next;
 /* uses bit field macros above - see EHCI 0.95 Table 3-8 */
-	u32			hw_fullspeed_ep;	/* EHCI table 3-9 */
-	u32			hw_uframe;		/* EHCI table 3-10 */
-	u32			hw_results;		/* EHCI table 3-11 */
+	__le32			hw_fullspeed_ep;	/* EHCI table 3-9 */
+	__le32			hw_uframe;		/* EHCI table 3-10 */
+	__le32			hw_results;		/* EHCI table 3-11 */
 #define	SITD_IOC	(1 << 31)	/* interrupt on completion */
 #define	SITD_PAGE	(1 << 30)	/* buffer 0/1 */
 #define	SITD_LENGTH(x)	(0x3ff & ((x)>>16))
@@ -521,9 +522,9 @@
 
 #define SITD_ACTIVE	__constant_cpu_to_le32(SITD_STS_ACTIVE)
 
-	u32			hw_buf [2];		/* EHCI table 3-12 */
-	u32			hw_backpointer;		/* EHCI table 3-13 */
-	u32			hw_buf_hi [2];		/* Appendix B */
+	__le32			hw_buf [2];		/* EHCI table 3-12 */
+	__le32			hw_backpointer;		/* EHCI table 3-13 */
+	__le32			hw_buf_hi [2];		/* Appendix B */
 
 	/* the rest is HCD-private */
 	dma_addr_t		sitd_dma;
@@ -548,8 +549,8 @@
  * it hits a "restore" FSTN; then it returns to finish other uframe 0/1 work.
  */
 struct ehci_fstn {
-	u32			hw_next;	/* any periodic q entry */
-	u32			hw_prev;	/* qh or EHCI_LIST_END */
+	__le32			hw_next;	/* any periodic q entry */
+	__le32			hw_prev;	/* qh or EHCI_LIST_END */
 
 	/* the rest is HCD-private */
 	dma_addr_t		fstn_dma;
diff -Nru a/drivers/usb/host/hc_simple.c b/drivers/usb/host/hc_simple.c
--- a/drivers/usb/host/hc_simple.c	2004-10-18 14:57:18 -07:00
+++ b/drivers/usb/host/hc_simple.c	2004-10-18 14:57:18 -07:00
@@ -146,11 +146,6 @@
 	if (!urb->dev || !urb->dev->bus || urb->hcpriv)
 		return -EINVAL;
 
-	if (usb_endpoint_halted
-	    (urb->dev, usb_pipeendpoint (pipe), usb_pipeout (pipe))) {
-		printk ("hci_submit_urb: endpoint_halted\n");
-		return -EPIPE;
-	}
 	hci = (hci_t *) urb->dev->bus->hcpriv;
 
 	/* a request to the virtual root hub */
diff -Nru a/drivers/usb/host/hc_sl811.c b/drivers/usb/host/hc_sl811.c
--- a/drivers/usb/host/hc_sl811.c	2004-10-18 14:56:49 -07:00
+++ b/drivers/usb/host/hc_sl811.c	2004-10-18 14:56:49 -07:00
@@ -106,14 +106,14 @@
 
 static int sofWaitCnt = 0;
 
-MODULE_PARM (urb_debug, "i");
+module_param(urb_debug, int, 0);
 MODULE_PARM_DESC (urb_debug, "debug urb messages, default is 0 (no)");
 
-MODULE_PARM (base_addr, "i");
+module_param(base_addr, int, 0);
 MODULE_PARM_DESC (base_addr, "sl811 base address 0xd3800000");
-MODULE_PARM (data_reg_addr, "i");
+module_param(data_reg_addr, int, 0);
 MODULE_PARM_DESC (data_reg_addr, "sl811 data register address 0xd3810000");
-MODULE_PARM (irq, "i");
+module_param(irq, int, 0);
 MODULE_PARM_DESC (irq, "IRQ 34 (default)");
 
 static int hc_reset (hci_t * hci);
diff -Nru a/drivers/usb/host/ohci-dbg.c b/drivers/usb/host/ohci-dbg.c
--- a/drivers/usb/host/ohci-dbg.c	2004-10-18 14:56:50 -07:00
+++ b/drivers/usb/host/ohci-dbg.c	2004-10-18 14:56:50 -07:00
@@ -131,7 +131,7 @@
 static void
 ohci_dump_status (struct ohci_hcd *controller, char **next, unsigned *size)
 {
-	struct ohci_regs	*regs = controller->regs;
+	struct ohci_regs __iomem *regs = controller->regs;
 	u32			temp;
 
 	temp = ohci_readl (&regs->revision) & 0xff;
@@ -336,7 +336,7 @@
 ohci_dump_ed (const struct ohci_hcd *ohci, const char *label,
 		const struct ed *ed, int verbose)
 {
-	u32	tmp = ed->hwINFO;
+	__le32	tmp = ed->hwINFO;
 	char	*type = "";
 
 	ohci_dbg (ohci, "%s, ed %p state 0x%x type %s; next ed %08x\n",
@@ -359,7 +359,7 @@
 		type,
 		0x007f & le32_to_cpu (tmp));
 	ohci_dbg (ohci, "  tds: head %08x %s%s tail %08x%s\n",
-		tmp = le32_to_cpup (&ed->hwHeadP),
+		le32_to_cpup (&ed->hwHeadP),
 		(ed->hwHeadP & ED_C) ? data1 : data0,
 		(ed->hwHeadP & ED_H) ? " HALT" : "",
 		le32_to_cpup (&ed->hwTailP),
@@ -415,8 +415,8 @@
 
 	/* dump a snapshot of the bulk or control schedule */
 	while (ed) {
-		u32			info = ed->hwINFO;
-		u32			scratch = cpu_to_le32p (&ed->hwINFO);
+		__le32			info = ed->hwINFO;
+		u32			scratch = le32_to_cpup (&ed->hwINFO);
 		struct list_head	*entry;
 		struct td		*td;
 
@@ -439,7 +439,7 @@
 			u32		cbp, be;
 
 			td = list_entry (entry, struct td, td_list);
-			scratch = cpu_to_le32p (&td->hwINFO);
+			scratch = le32_to_cpup (&td->hwINFO);
 			cbp = le32_to_cpup (&td->hwCBP);
 			be = le32_to_cpup (&td->hwBE);
 			temp = scnprintf (buf, size,
@@ -541,8 +541,8 @@
 
 			/* show more info the first time around */
 			if (temp == seen_count) {
-				u32	info = ed->hwINFO;
-				u32	scratch = cpu_to_le32p (&ed->hwINFO);
+				__le32	info = ed->hwINFO;
+				u32	scratch = le32_to_cpup (&ed->hwINFO);
 				struct list_head	*entry;
 				unsigned		qlen = 0;
 
@@ -599,7 +599,7 @@
 	struct usb_bus		*bus;
 	struct usb_hcd		*hcd;
 	struct ohci_hcd		*ohci;
-	struct ohci_regs	*regs;
+	struct ohci_regs __iomem *regs;
 	unsigned long		flags;
 	unsigned		temp, size;
 	char			*next;
diff -Nru a/drivers/usb/host/ohci-hcd.c b/drivers/usb/host/ohci-hcd.c
--- a/drivers/usb/host/ohci-hcd.c	2004-10-18 14:55:54 -07:00
+++ b/drivers/usb/host/ohci-hcd.c	2004-10-18 14:55:54 -07:00
@@ -97,6 +97,7 @@
 #include <linux/list.h>
 #include <linux/interrupt.h>  /* for in_interrupt () */
 #include <linux/usb.h>
+#include <linux/usb_otg.h>
 #include "../core/hcd.h"
 #include <linux/dma-mapping.h> 
 #include <linux/dmapool.h>    /* needed by ohci-mem.c when no PCI */
@@ -593,7 +594,7 @@
 static irqreturn_t ohci_irq (struct usb_hcd *hcd, struct pt_regs *ptregs)
 {
 	struct ohci_hcd		*ohci = hcd_to_ohci (hcd);
-	struct ohci_regs	*regs = ohci->regs;
+	struct ohci_regs __iomem *regs = ohci->regs;
  	int			ints; 
 
 	/* we can eliminate a (slow) ohci_readl()
@@ -693,7 +694,7 @@
 
 /* must not be called from interrupt context */
 
-#ifdef CONFIG_PM
+#if	defined(CONFIG_USB_SUSPEND) || defined(CONFIG_PM)
 
 static void mark_children_gone (struct usb_device *dev)
 {
diff -Nru a/drivers/usb/host/ohci-hub.c b/drivers/usb/host/ohci-hub.c
--- a/drivers/usb/host/ohci-hub.c	2004-10-18 14:55:55 -07:00
+++ b/drivers/usb/host/ohci-hub.c	2004-10-18 14:55:55 -07:00
@@ -435,6 +435,89 @@
 
 /*-------------------------------------------------------------------------*/
 
+#ifdef	CONFIG_USB_OTG
+
+static int ohci_start_port_reset (struct usb_hcd *hcd, unsigned port)
+{
+	struct ohci_hcd	*ohci = hcd_to_ohci (hcd);
+	u32			status;
+
+	if (!port)
+		return -EINVAL;
+	port--;
+
+	/* start port reset before HNP protocol times out */
+	status = ohci_readl(&ohci->regs->roothub.portstatus [port]);
+	if (!(status & RH_PS_CCS))
+		return -ENODEV;
+
+	/* khubd will finish the reset later */
+	writel(RH_PS_PRS, &ohci->regs->roothub.portstatus [port]);
+	return 0;
+}
+
+static void start_hnp(struct ohci_hcd *ohci);
+
+#else
+
+#define	ohci_start_port_reset		NULL
+
+#endif
+
+/*-------------------------------------------------------------------------*/
+
+
+/* See usb 7.1.7.5:  root hubs must issue at least 50 msec reset signaling,
+ * not necessarily continuous ... to guard against resume signaling.
+ * The short timeout is safe for non-root hubs, and is backward-compatible
+ * with earlier Linux hosts.
+ */
+#ifdef	CONFIG_USB_SUSPEND
+#define	PORT_RESET_MSEC		50
+#else
+#define	PORT_RESET_MSEC		10
+#endif
+
+/* this timer value might be vendor-specific ... */
+#define	PORT_RESET_HW_MSEC	10
+
+/* wrap-aware logic stolen from <linux/jiffies.h> */
+#define tick_before(t1,t2) ((((s16)(t1))-((s16)(t2))) < 0)
+
+/* called from some task, normally khubd */
+static inline void root_port_reset (struct ohci_hcd *ohci, unsigned port)
+{
+	u32 __iomem *portstat = &ohci->regs->roothub.portstatus [port];
+	u32	temp;
+	u16	now = readl(&ohci->regs->fmnumber);
+	u16	reset_done = now + PORT_RESET_MSEC;
+
+	/* build a "continuous enough" reset signal, with up to
+	 * 3msec gap between pulses.  scheduler HZ==100 must work;
+	 * this might need to be deadline-scheduled.
+	 */
+	do {
+		/* spin until any current reset finishes */
+		for (;;) {
+			temp = ohci_readl (portstat);
+			if (!(temp & RH_PS_PRS))
+				break;
+			udelay (500);
+		} 
+
+		if (!(temp & RH_PS_CCS))
+			break;
+		if (temp & RH_PS_PRSC)
+			writel (RH_PS_PRSC, portstat);
+
+		/* start the next reset, sleep till it's probably done */
+		writel (RH_PS_PRS, portstat);
+		msleep(PORT_RESET_HW_MSEC);
+		now = readl(&ohci->regs->fmnumber);
+	} while (tick_before(now, reset_done));
+	/* caller synchronizes using PRSC */
+}
+
 static int ohci_hub_control (
 	struct usb_hcd	*hcd,
 	u16		typeReq,
@@ -503,14 +586,14 @@
 		break;
 	case GetHubStatus:
 		temp = roothub_status (ohci) & ~(RH_HS_CRWE | RH_HS_DRWE);
-		*(u32 *) buf = cpu_to_le32 (temp);
+		*(__le32 *) buf = cpu_to_le32 (temp);
 		break;
 	case GetPortStatus:
 		if (!wIndex || wIndex > ports)
 			goto error;
 		wIndex--;
 		temp = roothub_portstatus (ohci, wIndex);
-		*(u32 *) buf = cpu_to_le32 (temp);
+		*(__le32 *) buf = cpu_to_le32 (temp);
 
 #ifndef	OHCI_VERBOSE_DEBUG
 	if (*(u16*)(buf+2))	/* only if wPortChange is interesting */
@@ -533,6 +616,12 @@
 		wIndex--;
 		switch (wValue) {
 		case USB_PORT_FEAT_SUSPEND:
+#ifdef	CONFIG_USB_OTG
+			if (ohci->hcd.self.otg_port == (wIndex + 1)
+					&& ohci->hcd.self.b_hnp_enable)
+				start_hnp(ohci);
+			else
+#endif
 			writel (RH_PS_PSS,
 				&ohci->regs->roothub.portstatus [wIndex]);
 			break;
@@ -541,10 +630,7 @@
 				&ohci->regs->roothub.portstatus [wIndex]);
 			break;
 		case USB_PORT_FEAT_RESET:
-			temp = ohci_readl (&ohci->regs->roothub.portstatus [wIndex]);
-			if (temp & RH_PS_CCS)
-				writel (RH_PS_PRS,
-				    &ohci->regs->roothub.portstatus [wIndex]);
+			root_port_reset (ohci, wIndex);
 			break;
 		default:
 			goto error;
diff -Nru a/drivers/usb/host/ohci-omap.c b/drivers/usb/host/ohci-omap.c
--- a/drivers/usb/host/ohci-omap.c	2004-10-18 14:56:48 -07:00
+++ b/drivers/usb/host/ohci-omap.c	2004-10-18 14:56:48 -07:00
@@ -2,27 +2,30 @@
  * OHCI HCD (Host Controller Driver) for USB.
  *
  * (C) Copyright 1999 Roman Weissgaerber <weissg@vienna.at>
- * (C) Copyright 2000-2002 David Brownell <dbrownell@users.sourceforge.net>
+ * (C) Copyright 2000-2004 David Brownell <dbrownell@users.sourceforge.net>
  * (C) Copyright 2002 Hewlett-Packard Company
  * 
  * OMAP Bus Glue
  *
  * Written by Christopher Hoover <ch@hpl.hp.com>
- * Based on fragments of previous driver by Rusell King et al.
+ * Based on fragments of previous driver by Russell King et al.
  *
  * Modified for OMAP from ohci-sa1111.c by Tony Lindgren <tony@atomide.com>
  * Based on the 2.4 OMAP OHCI driver originally done by MontaVista Software Inc.
  *
  * This file is licenced under the GPL.
  */
- 
+
 #include <asm/hardware.h>
 #include <asm/io.h>
+#include <asm/mach-types.h>
 
-#include <asm/arch/bus.h>
 #include <asm/arch/hardware.h>
 #include <asm/arch/mux.h>
 #include <asm/arch/irqs.h>
+#include <asm/arch/gpio.h>
+#include <asm/arch/fpga.h>
+#include <asm/arch/usb.h>
 
 #include "ohci-omap.h"
 
@@ -34,122 +37,53 @@
 extern int ocpi_enable(void);
 
 /*
- * Use the first port only by default. Override with hmc_mode option.
- *
- * NOTE: Many OMAP-1510 Innovators supposedly have bad wiring for the USB ports
- *       1 & 2, so only port 0 will work. To use the OHCI on the first port, use 
- *       the Innovator USB client cable with a client-to-client connector and modify
- *       either the cable or the hub to feed 5V VBUS back to Innovator. VBUS should
- *       be the red lead in the cable.
- *
- *       To mount USB hard disk as root, see the patch for do_mounts.c that tries 
- *       remounting the root, and use root=0801 if your root is on sda1. Does not 
- *       work with devfs.
- */
-static int default_hmc_mode = 16;
-static int hmc_mode = 1234;
-
-/*
- * Set the USB host pin multiplexing and the selected HMC mode
- */
-static int omap_usb_set_hmc_mode(int hmc_mode)
-{
-	unsigned int val;
-
-	switch (hmc_mode) {
-	case 0:
-		/* 0: function, 1: disabled, 2: disabled */
-		omap_cfg_reg(W4_USB_PUEN);
-		omap_cfg_reg(R18_1510_USB_GPIO0);
-		break;
-	case 4:
-		/* 0: function 1: host 2: host */
-		omap_cfg_reg(usb1_speed);
-		omap_cfg_reg(usb1_susp);
-		omap_cfg_reg(usb1_seo);
-		omap_cfg_reg(usb1_txen);
-		omap_cfg_reg(usb1_txd);
-		omap_cfg_reg(usb1_vp);
-		omap_cfg_reg(usb1_vm);
-		omap_cfg_reg(usb1_rcv);
-		omap_cfg_reg(usb2_susp);
-		omap_cfg_reg(usb2_seo);
-		omap_cfg_reg(usb2_txen);
-		omap_cfg_reg(usb2_txd);
-		omap_cfg_reg(usb2_vp);
-		omap_cfg_reg(usb2_vm);
-		omap_cfg_reg(usb2_rcv);
-		break;
-	case 16:
-		/* 0: host, 1: disabled, 2: disabled */
-		omap_cfg_reg(W9_USB0_TXEN);
-		omap_cfg_reg(AA9_USB0_VP);
-		omap_cfg_reg(Y5_USB0_RCV);
-		omap_cfg_reg(R9_USB0_VM);
-		omap_cfg_reg(V6_USB0_TXD);
-		omap_cfg_reg(W5_USB0_SE0);
-		break;
-	default:
-		printk("Unknown USB host configuration: %i\n", hmc_mode);
-		return -ENODEV;
-	}
-
-	/* Write the selected HMC mode */
-	val = readl(MOD_CONF_CTRL_0) & ~HMC_CLEAR;
-	val |= (hmc_mode << 1);
-	writel(val, MOD_CONF_CTRL_0);
-
-	return 0;
-}
-
-/*
  * OHCI clock initialization for OMAP-1510 and 1610
  */
 static int omap_ohci_clock_power(int on)
 {
 	if (on) {
-		if (cpu_is_omap_1510()) {
+		if (cpu_is_omap1510()) {
 			/* Use DPLL, not APLL */
-			writel(readl(ULPD_APLL_CTRL_REG) & ~APLL_NDPLL_SWITCH,
-			       ULPD_APLL_CTRL_REG);
+			omap_writel(omap_readl(ULPD_APLL_CTRL) & ~APLL_NDPLL_SWITCH,
+			       ULPD_APLL_CTRL);
 
 			/* Enable DPLL */
-			writel(readl(ULPD_DPLL_CTRL_REG) | DPLL_PLL_ENABLE,
-			       ULPD_DPLL_CTRL_REG);
+			omap_writel(omap_readl(ULPD_DPLL_CTRL) | DPLL_PLL_ENABLE,
+			       ULPD_DPLL_CTRL);
 
 			/* Software request for USB 48MHz clock */
-			writel(readl(ULPD_SOFT_REQ_REG) | SOFT_REQ_REG_REQ,
-			       ULPD_SOFT_REQ_REG);
+			omap_writel(omap_readl(ULPD_SOFT_REQ) | SOFT_REQ_REG_REQ,
+			       ULPD_SOFT_REQ);
 
-			while (!(readl(ULPD_DPLL_CTRL_REG) & DPLL_LOCK));
+			while (!(omap_readl(ULPD_DPLL_CTRL) & DPLL_LOCK));
 		}
 
-		if (cpu_is_omap_1610()) {
+		if (cpu_is_omap16xx()) {
 			/* Enable OHCI */
-			writel(readl(ULPD_SOFT_REQ_REG) | SOFT_USB_OTG_REQ,
-				ULPD_SOFT_REQ_REG);
+			omap_writel(omap_readl(ULPD_SOFT_REQ) | SOFT_USB_OTG_REQ,
+				ULPD_SOFT_REQ);
 
 			/* USB host clock request if not using OTG */
-			writel(readl(ULPD_SOFT_REQ_REG) | SOFT_USB_REQ,
-				ULPD_SOFT_REQ_REG);
+			omap_writel(omap_readl(ULPD_SOFT_REQ) | SOFT_USB_REQ,
+				ULPD_SOFT_REQ);
 
-			writel(readl(ULPD_STATUS_REQ_REG) | USB_HOST_DPLL_REQ,
-			     ULPD_STATUS_REQ_REG);
+			omap_writel(omap_readl(ULPD_STATUS_REQ) | USB_HOST_DPLL_REQ,
+			     ULPD_STATUS_REQ);
 		}
 
 		/* Enable 48MHz clock to USB */
-		writel(readl(ULPD_CLOCK_CTRL_REG) | USB_MCLK_EN,
-		       ULPD_CLOCK_CTRL_REG);
+		omap_writel(omap_readl(ULPD_CLOCK_CTRL) | USB_MCLK_EN,
+		       ULPD_CLOCK_CTRL);
 
-		writel(readl(ARM_IDLECT2) | (1 << EN_LBFREECK) | (1 << EN_LBCK),
+		omap_writel(omap_readl(ARM_IDLECT2) | (1 << EN_LBFREECK) | (1 << EN_LBCK),
 		       ARM_IDLECT2);
 
-		writel(readl(MOD_CONF_CTRL_0) | USB_HOST_HHC_UHOST_EN,
+		omap_writel(omap_readl(MOD_CONF_CTRL_0) | USB_HOST_HHC_UHOST_EN,
 		       MOD_CONF_CTRL_0);
 	} else {
 		/* Disable 48MHz clock to USB */
-		writel(readl(ULPD_CLOCK_CTRL_REG) & ~USB_MCLK_EN,
-		       ULPD_CLOCK_CTRL_REG);
+		omap_writel(omap_readl(ULPD_CLOCK_CTRL) & ~USB_MCLK_EN,
+		       ULPD_CLOCK_CTRL);
 
 		/* FIXME: The DPLL stays on for now */
 	}
@@ -163,13 +97,19 @@
 static int omap_ohci_transceiver_power(int on)
 {
 	if (on) {
-		if (omap_is_innovator())
-			writel(readl(OMAP1510_FPGA_HOST_CTRL) | 0x20, 
-			       OMAP1510_FPGA_HOST_CTRL);
+		if (machine_is_omap_innovator() && cpu_is_omap1510())
+			fpga_write(fpga_read(INNOVATOR_FPGA_CAM_USB_CONTROL) | 0x20, 
+			       INNOVATOR_FPGA_CAM_USB_CONTROL);
+		else if (machine_is_omap_osk()) {
+			/* FIXME: GPIO1 -> 1 on the TPS65010 I2C chip */
+		}
 	} else {
-		if (omap_is_innovator())
-			writel(readl(OMAP1510_FPGA_HOST_CTRL) & ~0x20, 
-			       OMAP1510_FPGA_HOST_CTRL);
+		if (machine_is_omap_innovator() && cpu_is_omap1510())
+			fpga_write(fpga_read(INNOVATOR_FPGA_CAM_USB_CONTROL) & ~0x20, 
+			       INNOVATOR_FPGA_CAM_USB_CONTROL);
+		else if (machine_is_omap_osk()) {
+			/* FIXME: GPIO1 -> 0 on the TPS65010 I2C chip */
+		}
 	}
 
 	return 0;
@@ -181,10 +121,10 @@
 static int omap_1510_local_bus_power(int on)
 {
 	if (on) {
-		writel((1 << 1) | (1 << 0), OMAP1510_LB_MMU_CTL);
+		omap_writel((1 << 1) | (1 << 0), OMAP1510_LB_MMU_CTL);
 		udelay(200);
 	} else {
-		writel(0, OMAP1510_LB_MMU_CTL);
+		omap_writel(0, OMAP1510_LB_MMU_CTL);
 	}
 
 	return 0;
@@ -193,8 +133,8 @@
 /*
  * OMAP-1510 specific Local Bus initialization
  * NOTE: This assumes 32MB memory size in OMAP1510LB_MEMSIZE.
- *       See also arch/mach-omap/memory.h for __virt_to_bus() and 
- *       __bus_to_virt() which need to match with the physical 
+ *       See also arch/mach-omap/memory.h for __virt_to_dma() and 
+ *       __dma_to_virt() which need to match with the physical 
  *       Local Bus address below.
  */
 static int omap_1510_local_bus_init(void)
@@ -202,125 +142,115 @@
 	unsigned int tlb;
 	unsigned long lbaddr, physaddr;
 
-	writel((readl(OMAP1510_LB_CLOCK_DIV) & 0xfffffff8) | 0x4, 
+	omap_writel((omap_readl(OMAP1510_LB_CLOCK_DIV) & 0xfffffff8) | 0x4, 
 	       OMAP1510_LB_CLOCK_DIV);
 
 	/* Configure the Local Bus MMU table */
 	for (tlb = 0; tlb < OMAP1510_LB_MEMSIZE; tlb++) {
 		lbaddr = tlb * 0x00100000 + OMAP1510_LB_OFFSET;
 		physaddr = tlb * 0x00100000 + PHYS_OFFSET;
-		writel((lbaddr & 0x0fffffff) >> 22, OMAP1510_LB_MMU_CAM_H);
-		writel(((lbaddr & 0x003ffc00) >> 6) | 0xc, 
+		omap_writel((lbaddr & 0x0fffffff) >> 22, OMAP1510_LB_MMU_CAM_H);
+		omap_writel(((lbaddr & 0x003ffc00) >> 6) | 0xc, 
 		       OMAP1510_LB_MMU_CAM_L);
-		writel(physaddr >> 16, OMAP1510_LB_MMU_RAM_H);
-		writel((physaddr & 0x0000fc00) | 0x300, OMAP1510_LB_MMU_RAM_L);
-		writel(tlb << 4, OMAP1510_LB_MMU_LCK);
-		writel(0x1, OMAP1510_LB_MMU_LD_TLB);
+		omap_writel(physaddr >> 16, OMAP1510_LB_MMU_RAM_H);
+		omap_writel((physaddr & 0x0000fc00) | 0x300, OMAP1510_LB_MMU_RAM_L);
+		omap_writel(tlb << 4, OMAP1510_LB_MMU_LCK);
+		omap_writel(0x1, OMAP1510_LB_MMU_LD_TLB);
 	}
 
 	/* Enable the walking table */
-	writel(readl(OMAP1510_LB_MMU_CTL) | (1 << 3), OMAP1510_LB_MMU_CTL);
+	omap_writel(omap_readl(OMAP1510_LB_MMU_CTL) | (1 << 3), OMAP1510_LB_MMU_CTL);
 	udelay(200);
 
 	return 0;
 }
 
-/*
- * OMAP-1610 specific hardware initialization
- *
- * Intended to configure OMAP-1610 USB host and OTG ports depending on 
- * the HMC mode selected.
- *
- * FIXME: Currently only supports alternate ping group 2 mode, should
- *        be easy to modify for other configurations once there is some
- *        hardware to test with.
- */
-static int omap_1610_usb_init(int mode)
-{
-	u_int val = 0;
-
-	/* Configure the OMAP transceiver settings */
-	val |= (1 << 8); /* CONF_USB2_UNI TRM p 15-205*/
-	val |= (4 << 4); /* TRM p 5-59, p 15-157 (1224) */
-
-	//val |= (1 << 3); /* Isolate integrated transceiver from port 0 */
-	val |= (1 << 2); /* Disable pulldown on integrated transceiver DM */
-	val |= (1 << 1); /* Disable pulldown on integraded transceiver DP */
-
-	writel(val, USB_TRANSCEIVER_CTRL);
-
-	/* Set the USB0_TRX_MODE */
-	val = 0;
-	val &= ~OTG_IDLE_EN;
-	val &= ~DEV_IDLE_EN;
-	val &= ~(7 << 16);	/* Clear USB0_TRX_MODE */
-	val |= (3 << 16);	/* 0 or 3, 6-wire DAT/SE0, TRM p 15-159 */
-	writel(val, OTG_SYSCON_1);
-
-	/* 
-	 * Control via OTG, see TRM p 15-163
-	 */
-	val = 0;
-	//val |= 1;		/* REVISIT: Enable OTG = 1 */
+#ifdef	CONFIG_USB_OTG
 
-	/* Control via OTG */
-	val &= ~HMC_PADEN;
-	val &= ~OTG_PADEN;
-	val |= UHOST_EN;	
-
-	val &= ~0x3f;		/* Clear HMC mode */
-	val |= mode;		/* Set HMC mode */
-	val &= ~(7 << 16);	/* Clear ASE0_BRST */
-	val |= (4 << 16);	/* Must be 4 */
-	val |= USBX_SYNCHRO;	/* Must be set */
-	val |= SRP_VBUS;
-	writel(val, OTG_SYSCON_2);
+static void start_hnp(struct ohci_hcd *ohci)
+{
+	const unsigned	port = ohci->hcd.self.otg_port - 1;
+	unsigned long	flags;
 
-	/* Enable OTG idle */
-	//writel(readl(OTG_SYSCON_1) | OTG_IDLE_EN, OTG_SYSCON_1);
+	otg_start_hnp(ohci->transceiver);
 
-	return 0;
+	local_irq_save(flags);
+	ohci->transceiver->state = OTG_STATE_A_SUSPEND;
+	writel (RH_PS_PSS, &ohci->regs->roothub.portstatus [port]);
+	OTG_CTRL_REG &= ~OTG_A_BUSREQ;
+	local_irq_restore(flags);
 }
 
+#endif
+
 /*-------------------------------------------------------------------------*/
 
-static void omap_start_hc(struct omap_dev *dev)
+static int omap_start_hc(struct ohci_hcd *ohci, struct platform_device *pdev)
 {
-	printk(KERN_DEBUG __FILE__ 
-	       ": starting OMAP OHCI USB Controller\n");
+	struct omap_usb_config	*config = pdev->dev.platform_data;
+	int			need_transceiver = (config->otg != 0);
 
-	/* 
-	 * Set the HMC mode for the USB ports
-	 */
-#if 0
-	/* See note about the Innovator wiring above */
-	if (omap_is_innovator())
-		hmc_mode = 4;	/* 0: function 1: host 2: host */
-#endif
+	dev_dbg(&pdev->dev, "starting USB Controller\n");
+
+	if (config->otg) {
+		ohci->hcd.self.otg_port = config->otg;
+		/* default/minimum OTG power budget:  8 mA */
+		ohci->power_budget = 8;
+	}
 
-	if (cpu_is_omap_1610())
+	/* boards can use OTG transceivers in non-OTG modes */
+	need_transceiver = need_transceiver
+			|| machine_is_omap_h2();
+
+	if (cpu_is_omap16xx())
 		ocpi_enable();
 
-	omap_usb_set_hmc_mode(hmc_mode);
+#ifdef	CONFIG_ARCH_OMAP_OTG
+	if (need_transceiver) {
+		ohci->transceiver = otg_get_transceiver();
+		if (ohci->transceiver) {
+			int	status = otg_set_host(ohci->transceiver,
+						&ohci->hcd.self);
+			dev_dbg(&pdev->dev, "init %s transceiver, status %d\n",
+					ohci->transceiver->label, status);
+			if (status) {
+				if (ohci->transceiver)
+					put_device(ohci->transceiver->dev);
+				return status;
+			}
+		} else {
+			dev_err(&pdev->dev, "can't find transceiver\n");
+			return -ENODEV;
+		}
+	}
+#endif
+
+	if (machine_is_omap_osk()) {
+		omap_request_gpio(9);
+		omap_set_gpio_direction(9, 1);
+		omap_set_gpio_dataout(9, 1);
+	}
 
 	omap_ohci_clock_power(1);
+
 	omap_ohci_transceiver_power(1);
 
-	if (cpu_is_omap_1510()) {
+	if (cpu_is_omap1510()) {
 		omap_1510_local_bus_power(1);
 		omap_1510_local_bus_init();
 	}
 
-	if (cpu_is_omap_1610())
-		omap_1610_usb_init(hmc_mode);
+	/* board init will have already handled HMC and mux setup.
+	 * any external transceiver should already be initialized
+	 * too, so all configured ports use the right signaling now.
+	 */
 
-	//omap_enable_device(dev);
+	return 0;
 }
 
-static void omap_stop_hc(struct omap_dev *dev)
+static void omap_stop_hc(struct platform_device *pdev)
 {
-	printk(KERN_DEBUG __FILE__ 
-	       ": stopping OMAP OHCI USB Controller\n");
+	dev_dbg(&pdev->dev, "stopping USB Controller\n");
 
 	/*
 	 * FIXME: Put the USB host controller into reset.
@@ -336,16 +266,7 @@
 
 /*-------------------------------------------------------------------------*/
 
-static irqreturn_t usb_hcd_omap_hcim_irq (int irq, void *__hcd, struct pt_regs * r)
-{
-	struct usb_hcd *hcd = __hcd;
-
-	return usb_hcd_irq(irq, hcd, r);
-}
-
-/*-------------------------------------------------------------------------*/
-
-void usb_hcd_omap_remove (struct usb_hcd *, struct omap_dev *);
+void usb_hcd_omap_remove (struct usb_hcd *, struct platform_device *);
 
 /* configure so an HC device and id are always provided */
 /* always called with process context; sleeping is OK */
@@ -358,59 +279,71 @@
  * Allocates basic resources for this USB host controller, and
  * then invokes the start() method for the HCD associated with it
  * through the hotplug entry's driver_data.
- *
- * Store this function in the HCD's struct pci_driver as probe().
  */
 int usb_hcd_omap_probe (const struct hc_driver *driver,
-			  struct usb_hcd **hcd_out,
-			  struct omap_dev *dev)
+			  struct platform_device *pdev)
 {
 	int retval;
 	struct usb_hcd *hcd = 0;
+	struct ohci_hcd *ohci;
 
-	if (!request_mem_region(dev->res.start, 
-				dev->res.end - dev->res.start + 1, hcd_name)) {
-		dbg("request_mem_region failed");
-		return -EBUSY;
+	if (pdev->num_resources != 2) {
+		printk(KERN_ERR "hcd probe: invalid num_resources: %i\n", 
+		       pdev->num_resources);
+		return -ENODEV;
+	}
+
+	if (pdev->resource[0].flags != IORESOURCE_MEM 
+	    || pdev->resource[1].flags != IORESOURCE_IRQ) {
+		printk(KERN_ERR "hcd probe: invalid resource type\n");
+		return -ENODEV;
 	}
 
-	omap_start_hc(dev);
+	if (!request_mem_region(pdev->resource[0].start, 
+				pdev->resource[0].end - pdev->resource[0].start + 1, hcd_name)) {
+		dev_dbg(&pdev->dev, "request_mem_region failed\n");
+		return -EBUSY;
+	}
 
 	hcd = driver->hcd_alloc ();
 	if (hcd == NULL){
-		dbg ("hcd_alloc failed");
+		dev_dbg(&pdev->dev, "hcd_alloc failed\n");
 		retval = -ENOMEM;
 		goto err1;
 	}
+	dev_set_drvdata(&pdev->dev, hcd);
+	ohci = hcd_to_ohci(hcd);
 
 	hcd->driver = (struct hc_driver *) driver;
 	hcd->description = driver->description;
-	hcd->irq = dev->irq[0];
-	hcd->regs = dev->mapbase;
-	hcd->self.controller = &dev->dev;
+	hcd->irq = pdev->resource[1].start;
+	hcd->regs = (void *)pdev->resource[0].start;
+	hcd->self.controller = &pdev->dev;
+
+	retval = omap_start_hc(ohci, pdev);
+	if (retval < 0)
+		goto err2;
 
 	retval = hcd_buffer_create (hcd);
 	if (retval != 0) {
-		dbg ("pool alloc fail");
+		dev_dbg(&pdev->dev, "pool alloc fail\n");
 		goto err1;
 	}
 
-	retval = request_irq (hcd->irq, 
-			      usb_hcd_omap_hcim_irq, 
+	retval = request_irq (hcd->irq, usb_hcd_irq, 
 			      SA_INTERRUPT, hcd->description, hcd);
 	if (retval != 0) {
-		dbg("request_irq failed");
+		dev_dbg(&pdev->dev, "request_irq failed\n");
 		retval = -EBUSY;
 		goto err2;
 	}
 
-	info ("%s (OMAP) at 0x%p, irq %d\n",
-	      hcd->description, hcd->regs, hcd->irq);
+	dev_info(&pdev->dev, "at 0x%p, irq %d\n", hcd->regs, hcd->irq);
 
 	usb_bus_init (&hcd->self);
 	hcd->self.op = &usb_hcd_operations;
 	hcd->self.hcpriv = (void *) hcd;
-	hcd->self.bus_name = "omap";
+	hcd->self.bus_name = pdev->dev.bus_id;
 	hcd->product_desc = "OMAP OHCI";
 
 	INIT_LIST_HEAD (&hcd->dev_list);
@@ -418,11 +351,10 @@
 
 	if ((retval = driver->start (hcd)) < 0) 
 	{
-		usb_hcd_omap_remove(hcd, dev);
+		usb_hcd_omap_remove(hcd, pdev);
 		return retval;
 	}
 
-	*hcd_out = hcd;
 	return 0;
 
  err2:
@@ -430,10 +362,12 @@
 	if (hcd)
 		driver->hcd_free(hcd);
  err1:
-	omap_stop_hc(dev);
+	omap_stop_hc(pdev);
 
-	release_mem_region(dev->res.start, dev->res.end - dev->res.start + 1);
+	release_mem_region(pdev->resource[0].start, 
+			   pdev->resource[0].end - pdev->resource[0].start + 1);
 
+	dev_set_drvdata(&pdev->dev, 0);
 	return retval;
 }
 
@@ -451,24 +385,27 @@
  * context, normally "rmmod", "apmd", or something similar.
  *
  */
-void usb_hcd_omap_remove (struct usb_hcd *hcd, struct omap_dev *dev)
+void usb_hcd_omap_remove (struct usb_hcd *hcd, struct platform_device *pdev)
 {
 	void *base;
 
-	info ("remove: %s, state %x", hcd->self.bus_name, hcd->state);
+	dev_info(&pdev->dev, "remove: state %x\n", hcd->state);
 
 	if (in_interrupt ())
 		BUG ();
 
 	hcd->state = USB_STATE_QUIESCING;
 
-	dbg ("%s: roothub graceful disconnect", hcd->self.bus_name);
+	dev_dbg(&pdev->dev, "roothub graceful disconnect\n");
 	usb_disconnect (&hcd->self.root_hub);
 
 	hcd->driver->stop (hcd);
 	hcd_buffer_destroy (hcd);
 	hcd->state = USB_STATE_HALT;
 
+	if (machine_is_omap_osk())
+		omap_free_gpio(9);
+
 	free_irq (hcd->irq, hcd);
 
 	usb_deregister_bus (&hcd->self);
@@ -476,9 +413,10 @@
 	base = hcd->regs;
 	hcd->driver->hcd_free (hcd);
 
-	omap_stop_hc(dev);
+	omap_stop_hc(pdev);
 
-	release_mem_region(dev->res.start, dev->res.end - dev->res.start + 1);
+	release_mem_region(pdev->resource[0].start, 
+			   pdev->resource[0].end - pdev->resource[0].start + 1);
 }
 
 /*-------------------------------------------------------------------------*/
@@ -486,11 +424,13 @@
 static int __devinit
 ohci_omap_start (struct usb_hcd *hcd)
 {
+	struct omap_usb_config *config;
 	struct ohci_hcd	*ohci = hcd_to_ohci (hcd);
 	int		ret;
 
-	ohci->hcca = dma_alloc_consistent (hcd->self.controller,
-			sizeof *ohci->hcca, &ohci->hcca_dma);
+	config = hcd->self.controller->platform_data;
+	ohci->hcca = dma_alloc_coherent (hcd->self.controller,
+			sizeof *ohci->hcca, &ohci->hcca_dma, 0);
 	if (!ohci->hcca)
 		return -ENOMEM;
 
@@ -500,6 +440,10 @@
 		return ret;
 	}
 	ohci->regs = hcd->regs;
+
+	if (config->otg || config->rwc)
+		writel(OHCI_CTRL_RWC, &ohci->regs->control);
+
 	if (hc_reset (ohci) < 0) {
 		ohci_stop (hcd);
 		return -ENODEV;
@@ -510,6 +454,9 @@
 		ohci_stop (hcd);
 		return -EBUSY;
 	}
+	if (ohci->power_budget)
+		hub_set_power_budget(ohci->hcd.self.root_hub,
+					ohci->power_budget);
 	create_debug_files (ohci);
 
 #ifdef	DEBUG
@@ -533,10 +480,6 @@
 	 * basic lifecycle operations
 	 */
 	.start =		ohci_omap_start,
-#ifdef	CONFIG_PM
-	/* suspend:		ohci_omap_suspend,  -- tbd */
-	/* resume:		ohci_omap_resume,   -- tbd */
-#endif
 	.stop =			ohci_stop,
 
 	/*
@@ -566,104 +509,130 @@
 	.hub_suspend =		ohci_hub_suspend,
 	.hub_resume =		ohci_hub_resume,
 #endif
+	.start_port_reset =	ohci_start_port_reset,
 };
 
 /*-------------------------------------------------------------------------*/
 
-static int ohci_hcd_omap_drv_probe(struct omap_dev *dev)
+static int ohci_hcd_omap_drv_probe(struct device *dev)
 {
-	struct usb_hcd *hcd = NULL;
-	int ret;
-
-	if (usb_disabled())
-		return -ENODEV;
+	return usb_hcd_omap_probe(&ohci_omap_hc_driver,
+				to_platform_device(dev));
+}
 
-	ret = usb_hcd_omap_probe(&ohci_omap_hc_driver, &hcd, dev);
+static int ohci_hcd_omap_drv_remove(struct device *dev)
+{
+	struct platform_device	*pdev = to_platform_device(dev);
+	struct usb_hcd		*hcd = dev_get_drvdata(dev);
+	struct ohci_hcd		*ohci = hcd_to_ohci (hcd);
 
-	if (ret == 0)
-		omap_set_drvdata(dev, hcd);
+	usb_hcd_omap_remove(hcd, pdev);
+	if (ohci->transceiver) {
+		(void) otg_set_host(ohci->transceiver, 0);
+		put_device(ohci->transceiver->dev);
+	}
+	dev_set_drvdata(dev, NULL);
 
-	return ret;
+	return 0;
 }
 
-static int ohci_hcd_omap_drv_remove(struct omap_dev *dev)
+/*-------------------------------------------------------------------------*/
+
+#if	defined(CONFIG_USB_SUSPEND) || defined(CONFIG_PM)
+
+/* states match PCI usage, always suspending the root hub except that
+ * 4 ~= D3cold (ACPI D3) with clock off (resume sees reset).
+ */
+
+static int ohci_omap_suspend(struct device *dev, u32 state, u32 level)
 {
-	struct usb_hcd *hcd = omap_get_drvdata(dev);
+	struct ohci_hcd	*ohci = hcd_to_ohci(dev_get_drvdata(dev));
+	int		status = -EINVAL;
 
-	usb_hcd_omap_remove(hcd, dev);
+	if (state <= dev->power.power_state)
+		return 0;
 
-	omap_set_drvdata(dev, NULL);
+	dev_dbg(dev, "suspend to %d\n", state);
+	down(&ohci->hcd.self.root_hub->serialize);
+	status = ohci_hub_suspend(&ohci->hcd);
+	if (status == 0) {
+		if (state >= 4) {
+			/* power off + reset */
+			OTG_SYSCON_2_REG &= ~UHOST_EN;
+			ohci->hcd.self.root_hub->state = USB_STATE_SUSPENDED;
+			state = 4;
+		}
+		ohci->hcd.state = HCD_STATE_SUSPENDED;
+		dev->power.power_state = state;
+	}
+	up(&ohci->hcd.self.root_hub->serialize);
+	return status;
+}
 
-	return 0;
+static int ohci_omap_resume(struct device *dev, u32 level)
+{
+	struct ohci_hcd	*ohci = hcd_to_ohci(dev_get_drvdata(dev));
+	int		status = 0;
+
+	switch (dev->power.power_state) {
+	case 0:
+		break;
+	case 4:
+		if (time_before(jiffies, ohci->next_statechange))
+			msleep(5);
+		ohci->next_statechange = jiffies;
+		OTG_SYSCON_2_REG |= UHOST_EN;
+		/* FALLTHROUGH */
+	default:
+		dev_dbg(dev, "resume from %d\n", dev->power.power_state);
+#ifdef	CONFIG_USB_SUSPEND
+		/* get extra cleanup even if remote wakeup isn't in use */
+		status = usb_resume_device(ohci->hcd.self.root_hub);
+#else
+		down(&ohci->hcd.self.root_hub->serialize);
+		status = ohci_hub_resume(&ohci->hcd);
+		up(&ohci->hcd.self.root_hub->serialize);
+#endif
+		if (status == 0)
+			dev->power.power_state = 0;
+		break;
+	}
+	return status;
 }
 
+#endif
+
+/*-------------------------------------------------------------------------*/
+
 /*
  * Driver definition to register with the OMAP bus
  */
-static struct omap_driver ohci_hcd_omap_driver = {
-	.drv = {
-		.name	= OMAP_OHCI_NAME,
-	},
-	.devid		= OMAP_OCP_DEVID_USB,
-	.busid		= OMAP_BUS_OCP,
-	.clocks		= 0,
+static struct device_driver ohci_hcd_omap_driver = {
+	.name		= "ohci",
+	.bus		= &platform_bus_type,
 	.probe		= ohci_hcd_omap_drv_probe,
 	.remove		= ohci_hcd_omap_drv_remove,
-};
-
-/* Any dma_mask must be set for OHCI to work */
-static u64 omap_dmamask = 0xffffffffUL;	
-
-/*
- * Device definition to match the driver above
- */
-static struct omap_dev ohci_hcd_omap_device = {
-	.name		= OMAP_OHCI_NAME,
-	.devid		= OMAP_OCP_DEVID_USB,
-	.busid		= OMAP_BUS_OCP,
-	.mapbase	= (void *)OMAP_OHCI_BASE,
-	.dma_mask	= &omap_dmamask,	/* Needed only for OHCI */
-	.res = {
-		.start	= OMAP_OHCI_BASE,
-		.end	= OMAP_OHCI_BASE + OMAP_OHCI_SIZE,
-	},
-	.irq = {
-		INT_USB_HHC_1,
-	},
+#if	defined(CONFIG_USB_SUSPEND) || defined(CONFIG_PM)
+	.suspend	= ohci_omap_suspend,
+	.resume		= ohci_omap_resume,
+#endif
 };
 
 static int __init ohci_hcd_omap_init (void)
 {
-	int ret;
-
-	dbg (DRIVER_INFO " (OMAP)");
-	dbg ("block sizes: ed %d td %d\n",
-		sizeof (struct ed), sizeof (struct td));
-
-	if (hmc_mode < 0 || hmc_mode > 25)
-		hmc_mode = default_hmc_mode;
-
-	/* Register the driver with OMAP bus */
-	ret = omap_driver_register(&ohci_hcd_omap_driver);
-	if (ret != 0)
+	printk (KERN_DEBUG "%s: " DRIVER_INFO " (OMAP)\n", hcd_name);
+	if (usb_disabled())
 		return -ENODEV;
 
-	/* Register the device with OMAP bus */
-	ret = omap_device_register(&ohci_hcd_omap_device);
-	if (ret != 0) {
-		omap_driver_unregister(&ohci_hcd_omap_driver);
-		return -ENODEV;
-	}
+	pr_debug("%s: block sizes: ed %Zd td %Zd\n", hcd_name,
+		sizeof (struct ed), sizeof (struct td));
 
-	return ret;
+	return driver_register(&ohci_hcd_omap_driver);
 }
 
-MODULE_PARM(hmc_mode, "hmc_mode");
-
 static void __exit ohci_hcd_omap_cleanup (void)
 {
-	omap_device_unregister(&ohci_hcd_omap_device);
-	omap_driver_unregister(&ohci_hcd_omap_driver);
+	driver_unregister(&ohci_hcd_omap_driver);
 }
 
 module_init (ohci_hcd_omap_init);
diff -Nru a/drivers/usb/host/ohci-omap.h b/drivers/usb/host/ohci-omap.h
--- a/drivers/usb/host/ohci-omap.h	2004-10-18 14:56:32 -07:00
+++ /dev/null	Wed Dec 31 16:00:00 196900
@@ -1,57 +0,0 @@
-/*
- * linux/drivers/usb/host/ohci-omap.h
- *
- * OMAP OHCI USB controller specific defines
- */
-
-/* OMAP USB OHCI common defines */
-#define OMAP_OHCI_NAME		"omap-ohci"
-#define OMAP_OHCI_BASE		0xfffba000
-#define OMAP_OHCI_SIZE		4096
-
-#define HMC_CLEAR		(0x3f << 1)
-#define APLL_NDPLL_SWITCH	0x0001
-#define DPLL_PLL_ENABLE		0x0010
-#define DPLL_LOCK		0x0001
-#define SOFT_REQ_REG_REQ	0x0001
-#define USB_MCLK_EN		0x0010
-#define USB_HOST_HHC_UHOST_EN	0x00000200
-#define SOFT_USB_OTG_REQ	(1 << 8)
-#define SOFT_USB_REQ		(1 << 3)
-#define STATUS_REQ_REG		0xfffe0840
-#define USB_HOST_DPLL_REQ	(1 << 8)
-#define SOFT_DPLL_REQ		(1 << 0)
-
-/* OMAP-1510 USB OHCI defines */
-#define OMAP1510_LB_MEMSIZE	32		/* Should be same as SDRAM size */
-#define OMAP1510_LB_CLOCK_DIV	0xfffec10c
-#define OMAP1510_LB_MMU_CTL	0xfffec208	
-#define OMAP1510_LB_MMU_LCK	0xfffec224
-#define OMAP1510_LB_MMU_LD_TLB	0xfffec228
-#define OMAP1510_LB_MMU_CAM_H	0xfffec22c
-#define OMAP1510_LB_MMU_CAM_L	0xfffec230
-#define OMAP1510_LB_MMU_RAM_H	0xfffec234
-#define OMAP1510_LB_MMU_RAM_L	0xfffec238
-
-/* OMAP-1610 USB OHCI defines */
-#define USB_TRANSCEIVER_CTRL	0xfffe1064
-#define OTG_REV			0xfffb0400
-
-#define OTG_SYSCON_1		0xfffb0404
-#define OTG_IDLE_EN		(1 << 15)
-#define DEV_IDLE_EN		(1 << 13)
-
-#define OTG_SYSCON_2		0xfffb0408
-#define OTG_CTRL		0xfffb040c
-#define OTG_IRQ_EN		0xfffb0410
-#define OTG_IRQ_SRC		0xfffb0414
-
-#define OTG_EN			(1 << 31)
-#define USBX_SYNCHRO		(1 << 30)
-#define SRP_VBUS		(1 << 12)
-#define OTG_PADEN		(1 << 10)
-#define HMC_PADEN		(1 << 9)
-#define UHOST_EN		(1 << 8)
-
-/* Hardware specific defines */
-#define OMAP1510_FPGA_HOST_CTRL	0xe800020c
diff -Nru a/drivers/usb/host/ohci-pci.c b/drivers/usb/host/ohci-pci.c
--- a/drivers/usb/host/ohci-pci.c	2004-10-18 14:56:48 -07:00
+++ b/drivers/usb/host/ohci-pci.c	2004-10-18 14:56:48 -07:00
@@ -242,6 +242,7 @@
 	.hub_suspend =		ohci_hub_suspend,
 	.hub_resume =		ohci_hub_resume,
 #endif
+	.start_port_reset =	ohci_start_port_reset,
 };
 
 /*-------------------------------------------------------------------------*/
@@ -276,7 +277,7 @@
 	if (usb_disabled())
 		return -ENODEV;
 
-	printk (KERN_DEBUG "%s: block sizes: ed %Zd td %Zd\n", hcd_name,
+	pr_debug ("%s: block sizes: ed %Zd td %Zd\n", hcd_name,
 		sizeof (struct ed), sizeof (struct td));
 	return pci_module_init (&ohci_pci_driver);
 }
diff -Nru a/drivers/usb/host/ohci-q.c b/drivers/usb/host/ohci-q.c
--- a/drivers/usb/host/ohci-q.c	2004-10-18 14:57:04 -07:00
+++ b/drivers/usb/host/ohci-q.c	2004-10-18 14:57:04 -07:00
@@ -136,7 +136,7 @@
 
 	for (i = ed->branch; i < NUM_INTS; i += ed->interval) {
 		struct ed	**prev = &ohci->periodic [i];
-		u32		*prev_p = &ohci->hcca->int_table [i];
+		__le32		*prev_p = &ohci->hcca->int_table [i];
 		struct ed	*here = *prev;
 
 		/* sorting each branch by period (slow before fast)
@@ -156,7 +156,7 @@
 				ed->hwNextED = *prev_p;
 			wmb ();
 			*prev = ed;
-			*prev_p = cpu_to_le32p (&ed->dma);
+			*prev_p = cpu_to_le32(ed->dma);
 			wmb();
 		}
 		ohci->load [i] += ed->load;
@@ -257,7 +257,7 @@
 	for (i = ed->branch; i < NUM_INTS; i += ed->interval) {
 		struct ed	*temp;
 		struct ed	**prev = &ohci->periodic [i];
-		u32		*prev_p = &ohci->hcca->int_table [i];
+		__le32		*prev_p = &ohci->hcca->int_table [i];
 
 		while (*prev && (temp = *prev) != ed) {
 			prev_p = &temp->hwNextED;
@@ -427,20 +427,21 @@
 	 */
   	if (ed->state == ED_IDLE) {
 		u32	info;
+		__le32	hw_info;
 
 		info = usb_pipedevice (pipe);
 		info |= (ep >> 1) << 7;
 		info |= usb_maxpacket (udev, pipe, is_out) << 16;
-		info = cpu_to_le32 (info);
+		hw_info = cpu_to_le32 (info);
 		if (udev->speed == USB_SPEED_LOW)
-			info |= ED_LOWSPEED;
+			hw_info |= ED_LOWSPEED;
 		/* only control transfers store pids in tds */
 		if (type != PIPE_CONTROL) {
-			info |= is_out ? ED_OUT : ED_IN;
+			hw_info |= is_out ? ED_OUT : ED_IN;
 			if (type != PIPE_BULK) {
 				/* periodic transfers... */
 				if (type == PIPE_ISOCHRONOUS)
-					info |= ED_ISO;
+					hw_info |= ED_ISO;
 				else if (interval > 32)	/* iso can be bigger */
 					interval = 32;
 				ed->interval = interval;
@@ -451,7 +452,7 @@
 						/ 1000;
 			}
 		}
-		ed->hwINFO = info;
+		ed->hwINFO = hw_info;
 	}
 
 done:
@@ -751,12 +752,6 @@
 
   		cc = TD_CC_GET (tdINFO);
 
-		/* control endpoints only have soft stalls */
-  		if (type != PIPE_CONTROL && cc == TD_CC_STALL)
-			usb_endpoint_halt (urb->dev,
-				usb_pipeendpoint (urb->pipe),
-				usb_pipeout (urb->pipe));
-
 		/* update packet status if needed (short is normally ok) */
 		if (cc == TD_DATAUNDERRUN
 				&& !(urb->transfer_flags & URB_SHORT_NOT_OK))
@@ -795,7 +790,7 @@
   	struct urb		*urb = td->urb;
 	struct ed		*ed = td->ed;
 	struct list_head	*tmp = td->td_list.next;
-	u32			toggle = ed->hwHeadP & ED_C;
+	__le32			toggle = ed->hwHeadP & ED_C;
 
 	/* clear ed halt; this is the td that caused it, but keep it inactive
 	 * until its urb->complete() has a chance to clean up.
@@ -810,7 +805,7 @@
 	 */
 	while (tmp != &ed->td_list) {
 		struct td	*next;
-		u32		info;
+		__le32		info;
 
 		next = list_entry (tmp, struct td, td_list);
 		tmp = next->td_list.next;
@@ -906,9 +901,6 @@
 
 /*-------------------------------------------------------------------------*/
 
-/* wrap-aware logic stolen from <linux/jiffies.h> */
-#define tick_before(t1,t2) ((((s16)(t1))-((s16)(t2))) < 0)
-
 /* there are some urbs/eds to unlink; called in_irq(), with HCD locked */
 static void
 finish_unlinks (struct ohci_hcd *ohci, u16 tick, struct pt_regs *regs)
@@ -919,7 +911,7 @@
 	for (last = &ohci->ed_rm_list, ed = *last; ed != NULL; ed = *last) {
 		struct list_head	*entry, *tmp;
 		int			completed, modified;
-		u32			*prev;
+		__le32			*prev;
 
 		/* only take off EDs that the HC isn't using, accounting for
 		 * frame counter wraps and EDs with partially retired TDs
@@ -937,7 +929,7 @@
 
 				td = list_entry (ed->td_list.next, struct td,
 							td_list);
-				head = cpu_to_le32 (ed->hwHeadP) & TD_MASK;
+				head = le32_to_cpu (ed->hwHeadP) & TD_MASK;
 
 				/* INTR_WDH may need to clean up first */
 				if (td->td_dma != head)
@@ -968,7 +960,7 @@
 			struct td	*td;
 			struct urb	*urb;
 			urb_priv_t	*urb_priv;
-			u32		savebits;
+			__le32		savebits;
 
 			td = list_entry (entry, struct td, td_list);
 			urb = td->urb;
diff -Nru a/drivers/usb/host/ohci.h b/drivers/usb/host/ohci.h
--- a/drivers/usb/host/ohci.h	2004-10-18 14:57:05 -07:00
+++ b/drivers/usb/host/ohci.h	2004-10-18 14:57:05 -07:00
@@ -16,7 +16,7 @@
  */
 struct ed {
 	/* first fields are hardware-specified, le32 */
-	__u32			hwINFO;       	/* endpoint config bitmap */
+	__le32			hwINFO;       	/* endpoint config bitmap */
 	/* info bits defined by hcd */
 #define ED_DEQUEUE	__constant_cpu_to_le32(1 << 27)
 	/* info bits defined by the hardware */
@@ -25,11 +25,11 @@
 #define ED_LOWSPEED	__constant_cpu_to_le32(1 << 13)
 #define ED_OUT		__constant_cpu_to_le32(0x01 << 11)
 #define ED_IN		__constant_cpu_to_le32(0x02 << 11)
-	__u32			hwTailP;	/* tail of TD list */
-	__u32			hwHeadP;	/* head of TD list (hc r/w) */
+	__le32			hwTailP;	/* tail of TD list */
+	__le32			hwHeadP;	/* head of TD list (hc r/w) */
 #define ED_C		__constant_cpu_to_le32(0x02)	/* toggle carry */
 #define ED_H		__constant_cpu_to_le32(0x01)	/* halted */
-	__u32			hwNextED;	/* next ED in list */
+	__le32			hwNextED;	/* next ED in list */
 
 	/* rest are purely for the driver's use */
 	dma_addr_t		dma;		/* addr of ED */
@@ -71,7 +71,7 @@
  */
 struct td {
 	/* first fields are hardware-specified, le32 */
-	__u32		hwINFO;		/* transfer info bitmask */
+	__le32		hwINFO;		/* transfer info bitmask */
 
 	/* hwINFO bits for both general and iso tds: */
 #define TD_CC       0xf0000000			/* condition code */
@@ -100,13 +100,13 @@
 
 	/* (no hwINFO #defines yet for iso tds) */
 
-  	__u32		hwCBP;		/* Current Buffer Pointer (or 0) */
-  	__u32		hwNextTD;	/* Next TD Pointer */
-  	__u32		hwBE;		/* Memory Buffer End Pointer */
+  	__le32		hwCBP;		/* Current Buffer Pointer (or 0) */
+  	__le32		hwNextTD;	/* Next TD Pointer */
+  	__le32		hwBE;		/* Memory Buffer End Pointer */
 
 	/* PSW is only for ISO */
 #define MAXPSW 1		/* hardware allows 8 */
-  	__u16		hwPSW [MAXPSW];
+  	__le16		hwPSW [MAXPSW];
 
 	/* rest are purely for the driver's use */
   	__u8		index;
@@ -171,16 +171,16 @@
  */
 struct ohci_hcca {
 #define NUM_INTS 32
-	__u32	int_table [NUM_INTS];	/* periodic schedule */
+	__le32	int_table [NUM_INTS];	/* periodic schedule */
 
 	/* 
 	 * OHCI defines u16 frame_no, followed by u16 zero pad.
 	 * Since some processors can't do 16 bit bus accesses,
 	 * portable access must be a 32 bit byteswapped access.
 	 */
-	u32	frame_no;		/* current frame number */
+	__le32	frame_no;		/* current frame number */
 #define OHCI_FRAME_NO(hccap) ((u16)le32_to_cpup(&(hccap)->frame_no))
-	__u32	done_head;		/* info returned for an interrupt */
+	__le32	done_head;		/* info returned for an interrupt */
 	u8	reserved_for_hc [116];
 	u8	what [4];		/* spec only identifies 252 bytes :) */
 } __attribute__ ((aligned(256)));
@@ -343,7 +343,7 @@
 	/*
 	 * I/O memory used to communicate with the HC (dma-consistent)
 	 */
-	struct ohci_regs	*regs;
+	struct ohci_regs __iomem *regs;
 
 	/*
 	 * main memory used to communicate with the HC (dma-consistent).
@@ -360,6 +360,13 @@
  	struct ed		*periodic [NUM_INTS];	/* shadow int_table */
 
 	/*
+	 * OTG controllers and transceivers need software interaction;
+	 * other external transceivers should be software-transparent 
+	 */
+	struct otg_transceiver	*transceiver;
+	unsigned		power_budget;
+
+	/*
 	 * memory management for queue data structures
 	 */
 	struct dma_pool		*td_cache;
@@ -443,7 +450,7 @@
 #else
 	/* Standard version of ohci_readl uses standard, platform
 	 * specific implementation. */
-static inline unsigned int ohci_readl (void* regs)
+static inline unsigned int ohci_readl (void __iomem * regs)
 {
 	return readl (regs);
 }
diff -Nru a/drivers/usb/host/uhci-hcd.c b/drivers/usb/host/uhci-hcd.c
--- a/drivers/usb/host/uhci-hcd.c	2004-10-18 14:57:03 -07:00
+++ b/drivers/usb/host/uhci-hcd.c	2004-10-18 14:57:03 -07:00
@@ -82,7 +82,7 @@
 #else
 static int debug = 0;
 #endif
-MODULE_PARM(debug, "i");
+module_param(debug, int, S_IRUGO | S_IWUSR);
 MODULE_PARM_DESC(debug, "Debug level");
 static char *errbuf;
 #define ERRBUF_LEN    (32 * 1024)
@@ -232,7 +232,7 @@
 /*
  * Inserts a td into qh list at the top.
  */
-static void uhci_insert_tds_in_qh(struct uhci_qh *qh, struct urb *urb, u32 breadth)
+static void uhci_insert_tds_in_qh(struct uhci_qh *qh, struct urb *urb, __le32 breadth)
 {
 	struct list_head *tmp, *head;
 	struct urb_priv *urbp = (struct urb_priv *)urb->hcpriv;
@@ -376,7 +376,7 @@
 static void uhci_remove_qh(struct uhci_hcd *uhci, struct uhci_qh *qh)
 {
 	struct uhci_qh *pqh;
-	u32 newlink;
+	__le32 newlink;
 	unsigned int age;
 
 	if (!qh)
@@ -1120,10 +1120,6 @@
 
 td_error:
 	ret = uhci_map_status(status, uhci_packetout(td_token(td)));
-	if (ret == -EPIPE)
-		/* endpoint has stalled - mark it halted */
-		usb_endpoint_halt(urb->dev, uhci_endpoint(td_token(td)),
-	    			uhci_packetout(td_token(td)));
 
 err:
 	/* 
@@ -1344,7 +1340,7 @@
 
 static int uhci_urb_enqueue(struct usb_hcd *hcd, struct urb *urb, int mem_flags)
 {
-	int ret = -EINVAL;
+	int ret;
 	struct uhci_hcd *uhci = hcd_to_uhci(hcd);
 	unsigned long flags;
 	struct urb *eurb;
@@ -1352,7 +1348,8 @@
 
 	spin_lock_irqsave(&uhci->schedule_lock, flags);
 
-	if (urb->status != -EINPROGRESS)	/* URB already unlinked! */
+	ret = urb->status;
+	if (ret != -EINPROGRESS)		/* URB already unlinked! */
 		goto out;
 
 	eurb = uhci_find_urb_ep(uhci, urb);
@@ -1637,13 +1634,6 @@
 		if (up->fsbr && !up->fsbr_timeout && time_after_eq(jiffies, up->fsbrtime + IDLE_TIMEOUT))
 			uhci_fsbr_timeout(uhci, u);
 
-		/* Check if the URB timed out */
-		if (u->timeout && u->status == -EINPROGRESS &&
-			time_after_eq(jiffies, up->inserttime + u->timeout)) {
-			u->status = -ETIMEDOUT;
-			list_move_tail(&up->urb_list, &list);
-		}
-
 		spin_unlock(&u->lock);
 	}
 	spin_unlock_irqrestore(&uhci->schedule_lock, flags);
@@ -2258,7 +2248,8 @@
 			irq = 7;
 
 		/* Only place we don't use the frame list routines */
-		uhci->fl->frame[i] = cpu_to_le32(uhci->skelqh[irq]->dma_handle);
+		uhci->fl->frame[i] = UHCI_PTR_QH |
+				cpu_to_le32(uhci->skelqh[irq]->dma_handle);
 	}
 
 	/*
diff -Nru a/drivers/usb/host/uhci-hcd.h b/drivers/usb/host/uhci-hcd.h
--- a/drivers/usb/host/uhci-hcd.h	2004-10-18 14:56:49 -07:00
+++ b/drivers/usb/host/uhci-hcd.h	2004-10-18 14:56:49 -07:00
@@ -80,7 +80,7 @@
 #define CAN_SCHEDULE_FRAMES	1000	/* how far future frames can be scheduled */
 
 struct uhci_frame_list {
-	u32 frame[UHCI_NUMFRAMES];
+	__le32 frame[UHCI_NUMFRAMES];
 
 	void *frame_cpu[UHCI_NUMFRAMES];
 
@@ -105,8 +105,8 @@
  */
 struct uhci_qh {
 	/* Hardware fields */
-	u32 link;			/* Next queue */
-	u32 element;			/* Queue element pointer */
+	__le32 link;			/* Next queue */
+	__le32 element;			/* Queue element pointer */
 
 	/* Software fields */
 	dma_addr_t dma_handle;
@@ -185,10 +185,10 @@
  */
 struct uhci_td {
 	/* Hardware fields */
-	u32 link;
-	u32 status;
-	u32 token;
-	u32 buffer;
+	__le32 link;
+	__le32 status;
+	__le32 token;
+	__le32 buffer;
 
 	/* Software fields */
 	dma_addr_t dma_handle;
diff -Nru a/drivers/usb/host/uhci-hub.c b/drivers/usb/host/uhci-hub.c
--- a/drivers/usb/host/uhci-hub.c	2004-10-18 14:55:54 -07:00
+++ b/drivers/usb/host/uhci-hub.c	2004-10-18 14:55:54 -07:00
@@ -82,7 +82,7 @@
 		*/
 
 	case GetHubStatus:
-		*(__u32 *)buf = cpu_to_le32(0);
+		*(__le32 *)buf = cpu_to_le32(0);
 		OK(4);		/* hub power */
 	case GetPortStatus:
 		if (!wIndex || wIndex > uhci->rh_numports)
@@ -126,8 +126,8 @@
 			dev_dbg(uhci_dev(uhci), "port %d portsc %04x\n",
 					wIndex, status);
 
-		*(__u16 *)buf = cpu_to_le16(wPortStatus);
-		*(__u16 *)(buf + 2) = cpu_to_le16(wPortChange);
+		*(__le16 *)buf = cpu_to_le16(wPortStatus);
+		*(__le16 *)(buf + 2) = cpu_to_le16(wPortChange);
 		OK(4);
 	case SetHubFeature:		/* We don't implement these */
 	case ClearHubFeature:
diff -Nru a/drivers/usb/image/microtek.c b/drivers/usb/image/microtek.c
--- a/drivers/usb/image/microtek.c	2004-10-18 14:57:05 -07:00
+++ b/drivers/usb/image/microtek.c	2004-10-18 14:57:05 -07:00
@@ -214,8 +214,8 @@
 #ifdef MTS_DO_DEBUG
 
 static inline void mts_debug_dump(struct mts_desc* desc) {
-	MTS_DEBUG("desc at 0x%x: halted = %02x%02x, toggle = %02x%02x\n",
-		  (int)desc,(int)desc->usb_dev->halted[1],(int)desc->usb_dev->halted[0],
+	MTS_DEBUG("desc at 0x%x: toggle = %02x%02x\n",
+		  (int)desc,
 		  (int)desc->usb_dev->toggle[1],(int)desc->usb_dev->toggle[0]
 		);
 	MTS_DEBUG("ep_out=%x ep_response=%x ep_image=%x\n",
diff -Nru a/drivers/usb/input/aiptek.c b/drivers/usb/input/aiptek.c
--- a/drivers/usb/input/aiptek.c	2004-10-18 14:56:49 -07:00
+++ b/drivers/usb/input/aiptek.c	2004-10-18 14:56:49 -07:00
@@ -494,9 +494,9 @@
 		} else {
 			input_regs(inputdev, regs);
 
-			x = le16_to_cpu(get_unaligned((__u16 *) (data + 1)));
-			y = le16_to_cpu(get_unaligned((__u16 *) (data + 3)));
-			z = le16_to_cpu(get_unaligned((__u16 *) (data + 6)));
+			x = le16_to_cpu(get_unaligned((__le16 *) (data + 1)));
+			y = le16_to_cpu(get_unaligned((__le16 *) (data + 3)));
+			z = le16_to_cpu(get_unaligned((__le16 *) (data + 6)));
 
 			p = (data[5] & 0x01) != 0 ? 1 : 0;
 			dv = (data[5] & 0x02) != 0 ? 1 : 0;
@@ -573,8 +573,8 @@
 			aiptek->diagnostic = AIPTEK_DIAGNOSTIC_TOOL_DISALLOWED;
 		} else {
 			input_regs(inputdev, regs);
-			x = le16_to_cpu(get_unaligned((__u16 *) (data + 1)));
-			y = le16_to_cpu(get_unaligned((__u16 *) (data + 3)));
+			x = le16_to_cpu(get_unaligned((__le16 *) (data + 1)));
+			y = le16_to_cpu(get_unaligned((__le16 *) (data + 3)));
 
 			jitterable = data[5] & 0x1c;
 
@@ -632,7 +632,7 @@
 		pck = (data[1] & aiptek->curSetting.stylusButtonUpper) != 0 ? 1 : 0;
 
 		macro = data[3];
-		z = le16_to_cpu(get_unaligned((__u16 *) (data + 4)));
+		z = le16_to_cpu(get_unaligned((__le16 *) (data + 4)));
 
 		if (dv != 0) {
 			input_regs(inputdev, regs);
@@ -729,7 +729,7 @@
 	 * hat switches (which just so happen to be the macroKeys.)
 	 */
 	else if (data[0] == 6) {
-		macro = le16_to_cpu(get_unaligned((__u16 *) (data + 1)));
+		macro = le16_to_cpu(get_unaligned((__le16 *) (data + 1)));
 		input_regs(inputdev, regs);
 
 		if (macro > 0) {
@@ -930,7 +930,7 @@
 		    buf[0], buf[1], buf[2]);
 		ret = -EIO;
 	} else {
-		ret = le16_to_cpu(get_unaligned((__u16 *) (buf + 1)));
+		ret = le16_to_cpu(get_unaligned((__le16 *) (buf + 1)));
 	}
 	kfree(buf);
 	return ret;
@@ -2289,9 +2289,9 @@
 MODULE_DESCRIPTION(DRIVER_DESC);
 MODULE_LICENSE("GPL");
 
-MODULE_PARM(programmableDelay, "i");
+module_param(programmableDelay, int, 0);
 MODULE_PARM_DESC(programmableDelay, "delay used during tablet programming");
-MODULE_PARM(jitterDelay, "i");
+module_param(jitterDelay, int, 0);
 MODULE_PARM_DESC(jitterDelay, "stylus/mouse settlement delay");
 
 module_init(aiptek_init);
diff -Nru a/drivers/usb/input/ati_remote.c b/drivers/usb/input/ati_remote.c
--- a/drivers/usb/input/ati_remote.c	2004-10-18 14:56:48 -07:00
+++ b/drivers/usb/input/ati_remote.c	2004-10-18 14:56:48 -07:00
@@ -112,11 +112,11 @@
 #define ATI_INPUTNUM      1     /* Which input device to register as */
 
 static unsigned long channel_mask = 0;
-module_param(channel_mask, ulong, 444);
+module_param(channel_mask, ulong, 0444);
 MODULE_PARM_DESC(channel_mask, "Bitmask of remote control channels to ignore");
 
 static int debug = 0;
-module_param(debug, int, 444);
+module_param(debug, int, 0444);
 MODULE_PARM_DESC(debug, "Enable extra debug messages and information");
 
 #define dbginfo(dev, format, arg...) do { if (debug) dev_info(dev , format , ## arg); } while (0)
diff -Nru a/drivers/usb/input/hid-core.c b/drivers/usb/input/hid-core.c
--- a/drivers/usb/input/hid-core.c	2004-10-18 14:56:33 -07:00
+++ b/drivers/usb/input/hid-core.c	2004-10-18 14:56:33 -07:00
@@ -219,17 +219,13 @@
 		dbg("logical range invalid %d %d", parser->global.logical_minimum, parser->global.logical_maximum);
 		return -1;
 	}
-	usages = parser->local.usage_index;
+	
+	if (!(usages = max_t(int, parser->local.usage_index, parser->global.report_count)))
+		return 0; /* Ignore padding fields */
 
 	offset = report->size;
 	report->size += parser->global.report_size * parser->global.report_count;
 
-	if (usages < parser->global.report_count)
-		usages = parser->global.report_count;
-
-	if (usages == 0)
-		return 0; /* ignore padding fields */
-
 	if ((field = hid_register_field(report, usages, parser->global.report_count)) == NULL)
 		return 0;
 
@@ -609,16 +605,16 @@
 		case 2:
 			if ((end - start) < 2) 
 				return NULL;
-			item->data.u16 = le16_to_cpu(get_unaligned((__u16*)start));
-			start = (__u8 *)((__u16 *)start + 1);
+			item->data.u16 = le16_to_cpu(get_unaligned((__le16*)start));
+			start = (__u8 *)((__le16 *)start + 1);
 			return start;
 
 		case 3:
 			item->size++;
 			if ((end - start) < 4)
 				return NULL;
-			item->data.u32 = le32_to_cpu(get_unaligned((__u32*)start));
-			start = (__u8 *)((__u32 *)start + 1);
+			item->data.u32 = le32_to_cpu(get_unaligned((__le32*)start));
+			start = (__u8 *)((__le32 *)start + 1);
 			return start;
 	}
 
@@ -760,15 +756,15 @@
 static __inline__ __u32 extract(__u8 *report, unsigned offset, unsigned n)
 {
 	report += (offset >> 5) << 2; offset &= 31;
-	return (le64_to_cpu(get_unaligned((__u64*)report)) >> offset) & ((1 << n) - 1);
+	return (le64_to_cpu(get_unaligned((__le64*)report)) >> offset) & ((1 << n) - 1);
 }
 
 static __inline__ void implement(__u8 *report, unsigned offset, unsigned n, __u32 value)
 {
 	report += (offset >> 5) << 2; offset &= 31;
-	put_unaligned((get_unaligned((__u64*)report)
+	put_unaligned((get_unaligned((__le64*)report)
 		& cpu_to_le64(~((((__u64) 1 << n) - 1) << offset)))
-		| cpu_to_le64((__u64)value << offset), (__u64*)report);
+		| cpu_to_le64((__u64)value << offset), (__le64*)report);
 }
 
 /*
@@ -923,20 +919,22 @@
 	int			status;
 
 	switch (urb->status) {
-	case 0:			/* success */
-		hid_input_report(HID_INPUT_REPORT, urb, regs);
-		break;
-	case -ECONNRESET:	/* unlink */
-	case -ENOENT:
-	case -ESHUTDOWN:
-		return;
-	default:		/* error */
-		dbg("nonzero status in input irq %d", urb->status);
+		case 0:			/* success */
+			hid_input_report(HID_INPUT_REPORT, urb, regs);
+			break;
+		case -ECONNRESET:	/* unlink */
+		case -ENOENT:
+		case -ESHUTDOWN:
+			return;
+		case -ETIMEDOUT:	/* NAK */
+			break;
+		default:		/* error */
+			warn("input irq status %d received", urb->status);
 	}
 	
-	status = usb_submit_urb (urb, SLAB_ATOMIC);
+	status = usb_submit_urb(urb, SLAB_ATOMIC);
 	if (status)
-		err ("can't resubmit intr, %s-%s/input%d, status %d",
+		err("can't resubmit intr, %s-%s/input%d, status %d",
 				hid->dev->bus->bus_name, hid->dev->devpath,
 				hid->ifnum, status);
 }
@@ -1137,23 +1135,31 @@
 	struct hid_device *hid = urb->context;
 	unsigned long flags;
 
-	if (urb->status)
-		warn("output irq status %d received", urb->status);
+	switch (urb->status) {
+		case 0:			/* success */
+		case -ECONNRESET:	/* unlink */
+		case -ENOENT:
+		case -ESHUTDOWN:
+			break;
+		default:		/* error */
+			warn("output irq status %d received", urb->status);
+	}
 
 	spin_lock_irqsave(&hid->outlock, flags);
 
 	hid->outtail = (hid->outtail + 1) & (HID_OUTPUT_FIFO_SIZE - 1);
 
 	if (hid->outhead != hid->outtail) {
-		hid_submit_out(hid);
+		if (hid_submit_out(hid)) {
+			clear_bit(HID_OUT_RUNNING, &hid->iofl);;
+			wake_up(&hid->wait);
+		}
 		spin_unlock_irqrestore(&hid->outlock, flags);
 		return;
 	}
 
 	clear_bit(HID_OUT_RUNNING, &hid->iofl);
-
 	spin_unlock_irqrestore(&hid->outlock, flags);
-
 	wake_up(&hid->wait);
 }
 
@@ -1166,26 +1172,34 @@
 	struct hid_device *hid = urb->context;
 	unsigned long flags;
 
-	if (urb->status)
-		warn("ctrl urb status %d received", urb->status);
-
 	spin_lock_irqsave(&hid->ctrllock, flags);
 
-	if (hid->ctrl[hid->ctrltail].dir == USB_DIR_IN) 
-		hid_input_report(hid->ctrl[hid->ctrltail].report->type, urb, regs);
+	switch (urb->status) {
+		case 0:			/* success */
+			if (hid->ctrl[hid->ctrltail].dir == USB_DIR_IN) 
+				hid_input_report(hid->ctrl[hid->ctrltail].report->type, urb, regs);
+		case -ECONNRESET:	/* unlink */
+		case -ENOENT:
+		case -ESHUTDOWN:
+		case -EPIPE:		/* report not available */
+			break;
+		default:		/* error */
+			warn("ctrl urb status %d received", urb->status);
+	}
 
 	hid->ctrltail = (hid->ctrltail + 1) & (HID_CONTROL_FIFO_SIZE - 1);
 
 	if (hid->ctrlhead != hid->ctrltail) {
-		hid_submit_ctrl(hid);
+		if (hid_submit_ctrl(hid)) {
+			clear_bit(HID_CTRL_RUNNING, &hid->iofl);
+			wake_up(&hid->wait);
+		}
 		spin_unlock_irqrestore(&hid->ctrllock, flags);
 		return;
 	}
 
 	clear_bit(HID_CTRL_RUNNING, &hid->iofl);
-
 	spin_unlock_irqrestore(&hid->ctrllock, flags);
-
 	wake_up(&hid->wait);
 }
 
@@ -1211,7 +1225,8 @@
 		hid->outhead = head;
 
 		if (!test_and_set_bit(HID_OUT_RUNNING, &hid->iofl))
-			hid_submit_out(hid);
+			if (hid_submit_out(hid))
+				clear_bit(HID_OUT_RUNNING, &hid->iofl);
 
 		spin_unlock_irqrestore(&hid->outlock, flags);
 		return;
@@ -1230,7 +1245,8 @@
 	hid->ctrlhead = head;
 
 	if (!test_and_set_bit(HID_CTRL_RUNNING, &hid->iofl))
-		hid_submit_ctrl(hid);
+		if (hid_submit_ctrl(hid))
+			clear_bit(HID_CTRL_RUNNING, &hid->iofl);
 
 	spin_unlock_irqrestore(&hid->ctrllock, flags);
 }
@@ -1282,7 +1298,7 @@
 void hid_close(struct hid_device *hid)
 {
 	if (!--hid->open)
-		usb_unlink_urb(hid->urbin);
+		usb_kill_urb(hid->urbin);
 }
 
 /*
@@ -1439,6 +1455,11 @@
 #define USB_DEVICE_ID_1_PHIDGETSERVO_20	0x8101
 #define USB_DEVICE_ID_4_PHIDGETSERVO_20	0x8104
 
+#define USB_VENDOR_ID_CODEMERCS		0x07c0
+#define USB_DEVICE_ID_CODEMERCS_IOW40	0x1500
+#define USB_DEVICE_ID_CODEMERCS_IOW24	0x1501
+
+
 static struct hid_blacklist {
 	__u16 idVendor;
 	__u16 idProduct;
@@ -1453,20 +1474,20 @@
 	{ USB_VENDOR_ID_AIPTEK, USB_DEVICE_ID_AIPTEK_23, HID_QUIRK_IGNORE },
 	{ USB_VENDOR_ID_AIPTEK, USB_DEVICE_ID_AIPTEK_24, HID_QUIRK_IGNORE },
 	{ USB_VENDOR_ID_BERKSHIRE, USB_DEVICE_ID_BERKSHIRE_PCWD, HID_QUIRK_IGNORE },
+	{ USB_VENDOR_ID_CODEMERCS, USB_DEVICE_ID_CODEMERCS_IOW40, HID_QUIRK_IGNORE },
+	{ USB_VENDOR_ID_CODEMERCS, USB_DEVICE_ID_CODEMERCS_IOW24, HID_QUIRK_IGNORE },
 	{ USB_VENDOR_ID_ESSENTIAL_REALITY, USB_DEVICE_ID_ESSENTIAL_REALITY_P5, HID_QUIRK_IGNORE },
 	{ USB_VENDOR_ID_KBGEAR, USB_DEVICE_ID_KBGEAR_JAMSTUDIO, HID_QUIRK_IGNORE },
 	{ USB_VENDOR_ID_GRIFFIN, USB_DEVICE_ID_POWERMATE, HID_QUIRK_IGNORE },
 	{ USB_VENDOR_ID_GRIFFIN, USB_DEVICE_ID_SOUNDKNOB, HID_QUIRK_IGNORE },
 	{ USB_VENDOR_ID_MGE, USB_DEVICE_ID_MGE_UPS, HID_QUIRK_IGNORE },
 	{ USB_VENDOR_ID_MGE, USB_DEVICE_ID_MGE_UPS1, HID_QUIRK_IGNORE },
-
 	{ USB_VENDOR_ID_ONTRAK, USB_DEVICE_ID_ONTRAK_ADU100, HID_QUIRK_IGNORE },
 	{ USB_VENDOR_ID_ONTRAK, USB_DEVICE_ID_ONTRAK_ADU100 + 100, HID_QUIRK_IGNORE },
 	{ USB_VENDOR_ID_ONTRAK, USB_DEVICE_ID_ONTRAK_ADU100 + 200, HID_QUIRK_IGNORE },
 	{ USB_VENDOR_ID_ONTRAK, USB_DEVICE_ID_ONTRAK_ADU100 + 300, HID_QUIRK_IGNORE },
 	{ USB_VENDOR_ID_ONTRAK, USB_DEVICE_ID_ONTRAK_ADU100 + 400, HID_QUIRK_IGNORE },
 	{ USB_VENDOR_ID_ONTRAK, USB_DEVICE_ID_ONTRAK_ADU100 + 500, HID_QUIRK_IGNORE },
-
 	{ USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_PENPARTNER, HID_QUIRK_IGNORE },
 	{ USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_GRAPHIRE, HID_QUIRK_IGNORE },
 	{ USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_GRAPHIRE + 1, HID_QUIRK_IGNORE },
@@ -1619,11 +1640,17 @@
 
 		struct usb_endpoint_descriptor *endpoint;
 		int pipe;
+		int interval;
 
 		endpoint = &interface->endpoint[n].desc;
 		if ((endpoint->bmAttributes & 3) != 3)		/* Not an interrupt endpoint */
 			continue;
 
+		/* handle potential highspeed HID correctly */
+		interval = endpoint->bInterval;
+		if (dev->speed == USB_SPEED_HIGH)
+			interval = 1 << (interval - 1);
+
 		if (endpoint->bEndpointAddress & USB_DIR_IN) {
 			int len;
 
@@ -1636,9 +1663,9 @@
 			if (len > HID_BUFFER_SIZE)
 				len = HID_BUFFER_SIZE;
 			usb_fill_int_urb(hid->urbin, dev, pipe, hid->inbuf, len,
-					 hid_irq_in, hid, endpoint->bInterval);
+					 hid_irq_in, hid, interval);
 			hid->urbin->transfer_dma = hid->inbuf_dma;
-			hid->urbin->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
+			hid->urbin->transfer_flags |=(URB_NO_TRANSFER_DMA_MAP | URB_ASYNC_UNLINK);
 		} else {
 			if (hid->urbout)
 				continue;
@@ -1646,9 +1673,9 @@
 				goto fail;
 			pipe = usb_sndintpipe(dev, endpoint->bEndpointAddress);
 			usb_fill_int_urb(hid->urbout, dev, pipe, hid->outbuf, 0,
-					  hid_irq_out, hid, 1);
+					 hid_irq_out, hid, interval);
 			hid->urbout->transfer_dma = hid->outbuf_dma;
-			hid->urbout->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
+			hid->urbout->transfer_flags |= (URB_NO_TRANSFER_DMA_MAP | URB_ASYNC_UNLINK);
 		}
 	}
 
@@ -1698,8 +1725,7 @@
 			     hid->ctrlbuf, 1, hid_ctrl, hid);
 	hid->urbctrl->setup_dma = hid->cr_dma;
 	hid->urbctrl->transfer_dma = hid->ctrlbuf_dma;
-	hid->urbctrl->transfer_flags |= (URB_NO_TRANSFER_DMA_MAP
-				| URB_NO_SETUP_DMA_MAP);
+	hid->urbctrl->transfer_flags |= (URB_NO_TRANSFER_DMA_MAP | URB_NO_SETUP_DMA_MAP | URB_ASYNC_UNLINK);
 
 	return hid;
 
@@ -1725,9 +1751,9 @@
 		return;
 
 	usb_set_intfdata(intf, NULL);
-	usb_unlink_urb(hid->urbin);
-	usb_unlink_urb(hid->urbout);
-	usb_unlink_urb(hid->urbctrl);
+	usb_kill_urb(hid->urbin);
+	usb_kill_urb(hid->urbout);
+	usb_kill_urb(hid->urbctrl);
 
 	if (hid->claimed & HID_CLAIMED_INPUT)
 		hidinput_disconnect(hid);
@@ -1835,8 +1861,8 @@
 
 static void __exit hid_exit(void)
 {
-	hiddev_exit();
 	usb_deregister(&hid_driver);
+	hiddev_exit();
 }
 
 module_init(hid_init);
diff -Nru a/drivers/usb/input/hiddev.c b/drivers/usb/input/hiddev.c
--- a/drivers/usb/input/hiddev.c	2004-10-18 14:56:29 -07:00
+++ b/drivers/usb/input/hiddev.c	2004-10-18 14:56:29 -07:00
@@ -223,16 +223,6 @@
 	return retval < 0 ? retval : 0;
 }
 
-/*
- * De-allocate a hiddev structure
- */
-static struct usb_class_driver hiddev_class;
-static void hiddev_cleanup(struct hiddev *hiddev)
-{
-	hiddev_table[hiddev->hid->minor - HIDDEV_MINOR_BASE] = NULL;
-	usb_deregister_dev(hiddev->hid->intf, &hiddev_class);
-	kfree(hiddev);
-}
 
 /*
  * release file op
@@ -253,7 +243,7 @@
 		if (list->hiddev->exist) 
 			hid_close(list->hiddev->hid);
 		else
-			hiddev_cleanup(list->hiddev);
+			kfree(list->hiddev);
 	}
 
 	kfree(list);
@@ -636,16 +626,19 @@
 				goto inval;
 
 			field = report->field[uref->field_index];
-			if (uref->usage_index >= field->maxusage)
-				goto inval;
 
-			if (cmd == HIDIOCGUSAGES || cmd == HIDIOCSUSAGES) {
-				if (uref_multi->num_values >= HID_MAX_USAGES || 
-				    uref->usage_index >= field->maxusage || 
-				   (uref->usage_index + uref_multi->num_values) >= field->maxusage)
+			if (cmd == HIDIOCGCOLLECTIONINDEX) {
+				if (uref->usage_index >= field->maxusage)
 					goto inval;
+			} else if (uref->usage_index >= field->report_count)
+				goto inval;
+
+			else if ((cmd == HIDIOCGUSAGES || cmd == HIDIOCSUSAGES) &&
+				 (uref_multi->num_values >= HID_MAX_MULTI_USAGES ||
+				  uref->usage_index + uref_multi->num_values >= field->report_count ||
+				  uref->usage_index + uref_multi->num_values < uref->usage_index))
+				goto inval;
 			}
-		}
 
 		switch (cmd) {
 			case HIDIOCGUSAGE:
@@ -795,17 +788,21 @@
  * This is where hid.c calls us to disconnect a hiddev device from the
  * corresponding hid device (usually because the usb device has disconnected)
  */
+static struct usb_class_driver hiddev_class;
 void hiddev_disconnect(struct hid_device *hid)
 {
 	struct hiddev *hiddev = hid->hiddev;
 
 	hiddev->exist = 0;
 
+	hiddev_table[hiddev->hid->minor - HIDDEV_MINOR_BASE] = NULL;
+	usb_deregister_dev(hiddev->hid->intf, &hiddev_class);
+
 	if (hiddev->open) {
 		hid_close(hiddev->hid);
 		wake_up_interruptible(&hiddev->wait);
 	} else {
-		hiddev_cleanup(hiddev);
+		kfree(hiddev);
 	}
 }
 
diff -Nru a/drivers/usb/input/kbtab.c b/drivers/usb/input/kbtab.c
--- a/drivers/usb/input/kbtab.c	2004-10-18 14:55:54 -07:00
+++ b/drivers/usb/input/kbtab.c	2004-10-18 14:55:54 -07:00
@@ -26,10 +26,9 @@
 
 #define USB_VENDOR_ID_KBGEAR	0x084e
 
-static int       kb_pressure_click = 0x10;
-MODULE_PARM     (kb_pressure_click,"i");
-MODULE_PARM_DESC(kb_pressure_click,
-		 "pressure threshold for clicks");
+static int kb_pressure_click = 0x10;
+module_param(kb_pressure_click, int, 0);
+MODULE_PARM_DESC(kb_pressure_click, "pressure threshold for clicks");
 
 struct kbtab {
 	signed char *data;
@@ -67,8 +66,8 @@
 		goto exit;
 	}
 
-	kbtab->x = le16_to_cpu(get_unaligned((u16 *) &data[1]));
-	kbtab->y = le16_to_cpu(get_unaligned((u16 *) &data[3]));
+	kbtab->x = le16_to_cpu(get_unaligned((__le16 *) &data[1]));
+	kbtab->y = le16_to_cpu(get_unaligned((__le16 *) &data[3]));
 
 	kbtab->pressure = (data[5]);
 
diff -Nru a/drivers/usb/input/wacom.c b/drivers/usb/input/wacom.c
--- a/drivers/usb/input/wacom.c	2004-10-18 14:55:54 -07:00
+++ b/drivers/usb/input/wacom.c	2004-10-18 14:55:54 -07:00
@@ -285,8 +285,8 @@
 
 	input_regs(dev, regs);
 	input_report_key(dev, BTN_TOOL_PEN, 1);
-	input_report_abs(dev, ABS_X, le16_to_cpu(get_unaligned((u16 *) &data[1])));
-	input_report_abs(dev, ABS_Y, le16_to_cpu(get_unaligned((u16 *) &data[3])));
+	input_report_abs(dev, ABS_X, le16_to_cpu(get_unaligned((__le16 *) &data[1])));
+	input_report_abs(dev, ABS_Y, le16_to_cpu(get_unaligned((__le16 *) &data[3])));
 	input_report_abs(dev, ABS_PRESSURE, (signed char)data[6] + 127);
 	input_report_key(dev, BTN_TOUCH, ((signed char)data[6] > -80) && !(data[5] & 0x20));
 	input_report_key(dev, BTN_STYLUS, (data[5] & 0x40));
@@ -329,8 +329,8 @@
 	if (data[0] != 2)
 		dbg("wacom_graphire_irq: received unknown report #%d", data[0]);
 
-	x = le16_to_cpu(*(u16 *) &data[2]);
-	y = le16_to_cpu(*(u16 *) &data[4]);
+	x = le16_to_cpu(*(__le16 *) &data[2]);
+	y = le16_to_cpu(*(__le16 *) &data[4]);
 
 	input_regs(dev, regs);
 
@@ -367,7 +367,7 @@
 		input_report_abs(dev, ABS_Y, y);
 	}
 
-	input_report_abs(dev, ABS_PRESSURE, le16_to_cpu(*(u16 *) &data[6]));
+	input_report_abs(dev, ABS_PRESSURE, le16_to_cpu(*(__le16 *) &data[6]));
 	input_report_key(dev, BTN_TOUCH, data[1] & 0x01);
 	input_report_key(dev, BTN_STYLUS, data[1] & 0x02);
 	input_report_key(dev, BTN_STYLUS2, data[1] & 0x04);
@@ -456,8 +456,8 @@
 		goto exit;
 	}
 
-	input_report_abs(dev, ABS_X, be16_to_cpu(*(u16 *) &data[2]));
-	input_report_abs(dev, ABS_Y, be16_to_cpu(*(u16 *) &data[4]));
+	input_report_abs(dev, ABS_X, be16_to_cpu(*(__be16 *) &data[2]));
+	input_report_abs(dev, ABS_Y, be16_to_cpu(*(__be16 *) &data[4]));
 	input_report_abs(dev, ABS_DISTANCE, data[9]);
 
 	if ((data[1] & 0xb8) == 0xa0) {						/* general pen packet */
diff -Nru a/drivers/usb/media/Kconfig b/drivers/usb/media/Kconfig
--- a/drivers/usb/media/Kconfig	2004-10-18 14:55:53 -07:00
+++ b/drivers/usb/media/Kconfig	2004-10-18 14:55:53 -07:00
@@ -106,46 +106,6 @@
 	  To compile this driver as a module, choose M here: the
 	  module will be called ov511.
 
-config USB_PWC
-	tristate "USB Philips Cameras"
-	depends on USB && VIDEO_DEV
-	---help---
-	  Say Y or M here if you want to use one of these Philips & OEM
-          webcams:
-           * Philips PCA645, PCA646
-           * Philips PCVC675, PCVC680, PCVC690
-           * Philips PCVC720/40, PCVC730, PCVC740, PCVC750
-	   * Askey VC010
-	   * Logitech QuickCam Pro 3000, 4000, 'Zoom', 'Notebook Pro' 
-             and 'Orbit'/'Sphere'
-           * Samsung MPC-C10, MPC-C30
-	   * Creative Webcam 5, Pro Ex
-	   * SOTEC Afina Eye
-	   * Visionite VCS-UC300, VCS-UM100
-	   
-	  The PCA635, PCVC665 and PCVC720/20 are not supported by this driver
-	  and never will be, but the 665 and 720/20 are supported by other 
-	  drivers.
-
-	  This driver has an optional plugin (called PWCX), which is 
-	  distributed as a binary module only. It contains code that allow you 
-	  to use higher resolutions and framerates but may not be distributed 
-	  as source. But even without this plugin you can these cams for most
-	  applications.
-
-	  See <file:Documentation/usb/philips.txt> for more information and
-	  installation instructions.
-
-	  The built-in microphone is enabled by selecting USB Audio support.
-
-	  This driver uses the Video For Linux API. You must say Y or M to
-	  "Video For Linux" (under Character Devices) to use this driver.
-	  Information on this API and pointers to "v4l" programs may be found
-	  at <file:Documentation/video4linux/API.html>.
-
-	  To compile this driver as a module, choose M here: the
-	  module will be called pwc.
-
 config USB_SE401
 	tristate "USB SE401 Camera support"
 	depends on USB && VIDEO_DEV
@@ -163,11 +123,11 @@
 	  module will be called se401.
 
 config USB_SN9C102
-	tristate "USB SN9C10[12] PC Camera Controller support (EXPERIMENTAL)"
-	depends on USB && VIDEO_DEV && EXPERIMENTAL
+	tristate "USB SN9C10[12] PC Camera Controller support"
+	depends on USB && VIDEO_DEV
 	---help---
-	  Say Y here if you want support for cameras based on SN9C101 and
-	  SN9C102 PC Camera Controllers.
+	  Say Y here if you want support for cameras based on SONiX SN9C101
+	  or SN9C102 PC Camera Controllers.
 
 	  See <file:Documentation/usb/sn9c102.txt> for more informations.
 
diff -Nru a/drivers/usb/media/Makefile b/drivers/usb/media/Makefile
--- a/drivers/usb/media/Makefile	2004-10-18 14:55:46 -07:00
+++ b/drivers/usb/media/Makefile	2004-10-18 14:55:46 -07:00
@@ -2,15 +2,13 @@
 # Makefile for USB Media drivers
 #
 
-pwc-objs	:= pwc-if.o pwc-misc.o pwc-ctrl.o pwc-uncompress.o
-sn9c102-objs	:= sn9c102_core.o sn9c102_pas106b.o sn9c102_tas5110c1b.o sn9c102_tas5130d1b.o
+sn9c102-objs	:= sn9c102_core.o sn9c102_pas106b.o sn9c102_tas5110c1b.o sn9c102_tas5130d1b.o sn9c102_pas202bcb.o
 
 obj-$(CONFIG_USB_DABUSB)	+= dabusb.o
 obj-$(CONFIG_USB_DSBR)		+= dsbr100.o
 obj-$(CONFIG_USB_IBMCAM)	+= ibmcam.o usbvideo.o ultracam.o
 obj-$(CONFIG_USB_KONICAWC)	+= konicawc.o usbvideo.o
 obj-$(CONFIG_USB_OV511)		+= ov511.o
-obj-$(CONFIG_USB_PWC)		+= pwc.o
 obj-$(CONFIG_USB_SE401)		+= se401.o
 obj-$(CONFIG_USB_SN9C102)	+= sn9c102.o
 obj-$(CONFIG_USB_STV680)	+= stv680.o
diff -Nru a/drivers/usb/media/dabusb.c b/drivers/usb/media/dabusb.c
--- a/drivers/usb/media/dabusb.c	2004-10-18 14:56:33 -07:00
+++ b/drivers/usb/media/dabusb.c	2004-10-18 14:56:33 -07:00
@@ -61,7 +61,7 @@
 
 static dabusb_t dabusb[NRDABUSB];
 static int buffers = 256;
-extern struct usb_driver dabusb_driver;
+static struct usb_driver dabusb_driver;
 
 /*-------------------------------------------------------------------*/
 
@@ -868,7 +868,7 @@
 MODULE_DESCRIPTION( DRIVER_DESC );
 MODULE_LICENSE("GPL");
 
-MODULE_PARM (buffers, "i");
+module_param(buffers, int, 0);
 MODULE_PARM_DESC (buffers, "Number of buffers (default=256)");
 
 module_init (dabusb_init);
diff -Nru a/drivers/usb/media/dsbr100.c b/drivers/usb/media/dsbr100.c
--- a/drivers/usb/media/dsbr100.c	2004-10-18 14:56:28 -07:00
+++ b/drivers/usb/media/dsbr100.c	2004-10-18 14:56:28 -07:00
@@ -107,7 +107,7 @@
 static int usb_dsbr100_close(struct inode *inode, struct file *file);
 
 static int radio_nr = -1;
-MODULE_PARM(radio_nr, "i");
+module_param(radio_nr, int, 0);
 
 /* Data for one (physical) device */
 typedef struct {
diff -Nru a/drivers/usb/media/ibmcam.c b/drivers/usb/media/ibmcam.c
--- a/drivers/usb/media/ibmcam.c	2004-10-18 14:56:27 -07:00
+++ b/drivers/usb/media/ibmcam.c	2004-10-18 14:56:27 -07:00
@@ -124,38 +124,38 @@
 /* Settings for camera model 3 */
 static int init_model3_input = 0;
 
-MODULE_PARM(debug, "i");
+module_param(debug, int, 0);
 MODULE_PARM_DESC(debug, "Debug level: 0-9 (default=0)");
-MODULE_PARM(flags, "i");
+module_param(flags, int, 0);
 MODULE_PARM_DESC(flags, "Bitfield: 0=VIDIOCSYNC, 1=B/W, 2=show hints, 3=show stats, 4=test pattern, 5=separate frames, 6=clean frames");
-MODULE_PARM(framerate, "i");
+module_param(framerate, int, 0);
 MODULE_PARM_DESC(framerate, "Framerate setting: 0=slowest, 6=fastest (default=2)");
-MODULE_PARM(lighting, "i");
+module_param(lighting, int, 0);
 MODULE_PARM_DESC(lighting, "Photosensitivity: 0=bright, 1=medium (default), 2=low light");
-MODULE_PARM(sharpness, "i");
+module_param(sharpness, int, 0);
 MODULE_PARM_DESC(sharpness, "Model1 noise reduction: 0=smooth, 6=sharp (default=4)");
-MODULE_PARM(size, "i");
+module_param(size, int, 0);
 MODULE_PARM_DESC(size, "Image size: 0=128x96 1=160x120 2=176x144 3=320x240 4=352x240 5=352x288 6=640x480  (default=5)");
-MODULE_PARM(init_brightness, "i");
+module_param(init_brightness, int, 0);
 MODULE_PARM_DESC(init_brightness, "Brightness preconfiguration: 0-255 (default=128)");
-MODULE_PARM(init_contrast, "i");
+module_param(init_contrast, int, 0);
 MODULE_PARM_DESC(init_contrast, "Contrast preconfiguration: 0-255 (default=192)");
-MODULE_PARM(init_color, "i");
+module_param(init_color, int, 0);
 MODULE_PARM_DESC(init_color, "Color preconfiguration: 0-255 (default=128)");
-MODULE_PARM(init_hue, "i");
+module_param(init_hue, int, 0);
 MODULE_PARM_DESC(init_hue, "Hue preconfiguration: 0-255 (default=128)");
-MODULE_PARM(hue_correction, "i");
+module_param(hue_correction, int, 0);
 MODULE_PARM_DESC(hue_correction, "YUV colorspace regulation: 0-255 (default=128)");
 
-MODULE_PARM(init_model2_rg2, "i");
+module_param(init_model2_rg2, int, 0);
 MODULE_PARM_DESC(init_model2_rg2, "Model2 preconfiguration: 0-255 (default=47)");
-MODULE_PARM(init_model2_sat, "i");
+module_param(init_model2_sat, int, 0);
 MODULE_PARM_DESC(init_model2_sat, "Model2 preconfiguration: 0-255 (default=52)");
-MODULE_PARM(init_model2_yb, "i");
+module_param(init_model2_yb, int, 0);
 MODULE_PARM_DESC(init_model2_yb, "Model2 preconfiguration: 0-255 (default=160)");
 
 /* 01.01.08 - Added for RCA video in support -LO */
-MODULE_PARM(init_model3_input, "i");
+module_param(init_model3_input, int, 0);
 MODULE_PARM_DESC(init_model3_input, "Model3 input: 0=CCD 1=RCA");
 
 MODULE_AUTHOR ("Dmitri");
diff -Nru a/drivers/usb/media/konicawc.c b/drivers/usb/media/konicawc.c
--- a/drivers/usb/media/konicawc.c	2004-10-18 14:55:53 -07:00
+++ b/drivers/usb/media/konicawc.c	2004-10-18 14:55:53 -07:00
@@ -68,7 +68,7 @@
 /* Some default values for initial camera settings,
    can be set by modprobe */
 
-static enum frame_sizes size;	
+static int size;	
 static int speed = 6;		/* Speed (fps) 0 (slowest) to 6 (fastest) */
 static int brightness =	MAX_BRIGHTNESS/2;
 static int contrast =	MAX_CONTRAST/2;
@@ -362,8 +362,8 @@
 		else if (!urb->status && !cam->last_data_urb->status)
 			len = konicawc_compress_iso(uvd, cam->last_data_urb, urb);
 
-		resubmit_urb(uvd, urb);
 		resubmit_urb(uvd, cam->last_data_urb);
+		resubmit_urb(uvd, urb);
 		cam->last_data_urb = NULL;
 		uvd->stats.urb_length = len;
 		uvd->stats.data_count += len;
@@ -928,23 +928,23 @@
 MODULE_LICENSE("GPL");
 MODULE_AUTHOR("Simon Evans <spse@secret.org.uk>");
 MODULE_DESCRIPTION(DRIVER_DESC);
-MODULE_PARM(speed, "i");
+module_param(speed, int, 0);
 MODULE_PARM_DESC(speed, "Initial speed: 0 (slowest) - 6 (fastest)");
-MODULE_PARM(size, "i");
+module_param(size, int, 0);
 MODULE_PARM_DESC(size, "Initial Size 0: 160x120 1: 160x136 2: 176x144 3: 320x240");
-MODULE_PARM(brightness, "i");
+module_param(brightness, int, 0);
 MODULE_PARM_DESC(brightness, "Initial brightness 0 - 108");
-MODULE_PARM(contrast, "i");
+module_param(contrast, int, 0);
 MODULE_PARM_DESC(contrast, "Initial contrast 0 - 108");
-MODULE_PARM(saturation, "i");
+module_param(saturation, int, 0);
 MODULE_PARM_DESC(saturation, "Initial saturation 0 - 108");
-MODULE_PARM(sharpness, "i");
+module_param(sharpness, int, 0);
 MODULE_PARM_DESC(sharpness, "Initial brightness 0 - 108");
-MODULE_PARM(whitebal, "i");
+module_param(whitebal, int, 0);
 MODULE_PARM_DESC(whitebal, "Initial white balance 0 - 363");
 
 #ifdef CONFIG_USB_DEBUG
-MODULE_PARM(debug, "i");
+module_param(debug, int, S_IRUGO | S_IWUSR);
 MODULE_PARM_DESC(debug, "Debug level: 0-9 (default=0)");
 #endif
 
diff -Nru a/drivers/usb/media/ov511.c b/drivers/usb/media/ov511.c
--- a/drivers/usb/media/ov511.c	2004-10-18 14:56:28 -07:00
+++ b/drivers/usb/media/ov511.c	2004-10-18 14:56:28 -07:00
@@ -119,78 +119,79 @@
 static int mirror;
 static int ov518_color;
 
-MODULE_PARM(autobright, "i");
+module_param(autobright, int, 0);
 MODULE_PARM_DESC(autobright, "Sensor automatically changes brightness");
-MODULE_PARM(autogain, "i");
+module_param(autogain, int, 0);
 MODULE_PARM_DESC(autogain, "Sensor automatically changes gain");
-MODULE_PARM(autoexp, "i");
+module_param(autoexp, int, 0);
 MODULE_PARM_DESC(autoexp, "Sensor automatically changes exposure");
-MODULE_PARM(debug, "i");
+module_param(debug, int, 0);
 MODULE_PARM_DESC(debug,
   "Debug level: 0=none, 1=inits, 2=warning, 3=config, 4=functions, 5=max");
-MODULE_PARM(snapshot, "i");
+module_param(snapshot, int, 0);
 MODULE_PARM_DESC(snapshot, "Enable snapshot mode");
-MODULE_PARM(cams, "i");
+module_param(cams, int, 0);
 MODULE_PARM_DESC(cams, "Number of simultaneous cameras");
-MODULE_PARM(compress, "i");
+module_param(compress, int, 0);
 MODULE_PARM_DESC(compress, "Turn on compression");
-MODULE_PARM(testpat, "i");
+module_param(testpat, int, 0);
 MODULE_PARM_DESC(testpat,
   "Replace image with vertical bar testpattern (only partially working)");
-MODULE_PARM(dumppix, "i");
+module_param(dumppix, int, 0);
 MODULE_PARM_DESC(dumppix, "Dump raw pixel data");
-MODULE_PARM(led, "i");
+module_param(led, int, 0);
 MODULE_PARM_DESC(led,
   "LED policy (OV511+ or later). 0=off, 1=on (default), 2=auto (on when open)");
-MODULE_PARM(dump_bridge, "i");
+module_param(dump_bridge, int, 0);
 MODULE_PARM_DESC(dump_bridge, "Dump the bridge registers");
-MODULE_PARM(dump_sensor, "i");
+module_param(dump_sensor, int, 0);
 MODULE_PARM_DESC(dump_sensor, "Dump the sensor registers");
-MODULE_PARM(printph, "i");
+module_param(printph, int, 0);
 MODULE_PARM_DESC(printph, "Print frame start/end headers");
-MODULE_PARM(phy, "i");
+module_param(phy, int, 0);
 MODULE_PARM_DESC(phy, "Prediction range (horiz. Y)");
-MODULE_PARM(phuv, "i");
+module_param(phuv, int, 0);
 MODULE_PARM_DESC(phuv, "Prediction range (horiz. UV)");
-MODULE_PARM(pvy, "i");
+module_param(pvy, int, 0);
 MODULE_PARM_DESC(pvy, "Prediction range (vert. Y)");
-MODULE_PARM(pvuv, "i");
+module_param(pvuv, int, 0);
 MODULE_PARM_DESC(pvuv, "Prediction range (vert. UV)");
-MODULE_PARM(qhy, "i");
+module_param(qhy, int, 0);
 MODULE_PARM_DESC(qhy, "Quantization threshold (horiz. Y)");
-MODULE_PARM(qhuv, "i");
+module_param(qhuv, int, 0);
 MODULE_PARM_DESC(qhuv, "Quantization threshold (horiz. UV)");
-MODULE_PARM(qvy, "i");
+module_param(qvy, int, 0);
 MODULE_PARM_DESC(qvy, "Quantization threshold (vert. Y)");
-MODULE_PARM(qvuv, "i");
+module_param(qvuv, int, 0);
 MODULE_PARM_DESC(qvuv, "Quantization threshold (vert. UV)");
-MODULE_PARM(lightfreq, "i");
+module_param(lightfreq, int, 0);
 MODULE_PARM_DESC(lightfreq,
   "Light frequency. Set to 50 or 60 Hz, or zero for default settings");
-MODULE_PARM(bandingfilter, "i");
+module_param(bandingfilter, int, 0);
 MODULE_PARM_DESC(bandingfilter,
   "Enable banding filter (to reduce effects of fluorescent lighting)");
-MODULE_PARM(clockdiv, "i");
+module_param(clockdiv, int, 0);
 MODULE_PARM_DESC(clockdiv, "Force pixel clock divisor to a specific value");
-MODULE_PARM(packetsize, "i");
+module_param(packetsize, int, 0);
 MODULE_PARM_DESC(packetsize, "Force a specific isoc packet size");
-MODULE_PARM(framedrop, "i");
+module_param(framedrop, int, 0);
 MODULE_PARM_DESC(framedrop, "Force a specific frame drop register setting");
-MODULE_PARM(fastset, "i");
+module_param(fastset, int, 0);
 MODULE_PARM_DESC(fastset, "Allows picture settings to take effect immediately");
-MODULE_PARM(force_palette, "i");
+module_param(force_palette, int, 0);
 MODULE_PARM_DESC(force_palette, "Force the palette to a specific value");
-MODULE_PARM(backlight, "i");
+module_param(backlight, int, 0);
 MODULE_PARM_DESC(backlight, "For objects that are lit from behind");
-MODULE_PARM(unit_video, "1-" __MODULE_STRING(OV511_MAX_UNIT_VIDEO) "i");
+static int num_uv;
+module_param_array(unit_video, int, num_uv, 0);
 MODULE_PARM_DESC(unit_video,
   "Force use of specific minor number(s). 0 is not allowed.");
-MODULE_PARM(remove_zeros, "i");
+module_param(remove_zeros, int, 0);
 MODULE_PARM_DESC(remove_zeros,
   "Remove zero-padding from uncompressed incoming data");
-MODULE_PARM(mirror, "i");
+module_param(mirror, int, 0);
 MODULE_PARM_DESC(mirror, "Reverse image horizontally");
-MODULE_PARM(ov518_color, "i");
+module_param(ov518_color, int, 0);
 MODULE_PARM_DESC(ov518_color, "Enable OV518 color (experimental)");
 
 MODULE_AUTHOR(DRIVER_AUTHOR);
@@ -472,7 +473,7 @@
 
 	down(&ov->cbuf_lock);
 
-	*((u32 *)ov->cbuf) = __cpu_to_le32(val);
+	*((__le32 *)ov->cbuf) = __cpu_to_le32(val);
 
 	rc = usb_control_msg(ov->dev,
 			     usb_sndctrlpipe(ov->dev, 0),
@@ -1169,7 +1170,7 @@
 		return -EIO;
 
 	/* Wait for it to initialize */
-	schedule_timeout(1 + 150 * HZ / 1000);
+	msleep(150);
 
 	for (i = 0, success = 0; i < i2c_detect_tries && !success; i++) {
 		if ((i2c_r(ov, OV7610_REG_ID_HIGH) == 0x7F) &&
@@ -1182,7 +1183,7 @@
 		if (i2c_w(ov, 0x12, 0x80) < 0)
 			return -EIO;
 		/* Wait for it to initialize */
-		schedule_timeout(1 + 150 * HZ / 1000);
+		msleep(150);
 		/* Dummy read to sync I2C */
 		if (i2c_r(ov, 0x00) < 0)
 			return -EIO;
@@ -4947,7 +4948,7 @@
 			return -1;
 
 		/* Wait for it to initialize */
-		schedule_timeout(1 + 150 * HZ / 1000);
+		msleep(150);
 
 		i = 0;
 		success = 0;
diff -Nru a/drivers/usb/media/pwc-ctrl.c b/drivers/usb/media/pwc-ctrl.c
--- a/drivers/usb/media/pwc-ctrl.c	2004-10-18 14:57:04 -07:00
+++ /dev/null	Wed Dec 31 16:00:00 196900
@@ -1,1644 +0,0 @@
-/* Driver for Philips webcam
-   Functions that send various control messages to the webcam, including
-   video modes.
-   (C) 1999-2003 Nemosoft Unv. (webcam@smcc.demon.nl)
-
-   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
-*/
-
-/*
-   Changes
-   2001/08/03  Alvarado   Added methods for changing white balance and 
-                          red/green gains
- */
-
-/* Control functions for the cam; brightness, contrast, video mode, etc. */
-
-#ifdef __KERNEL__
-#include <asm/uaccess.h> 
-#endif
-#include <asm/errno.h>
-#include <linux/version.h>
- 
-#include "pwc.h"
-#include "pwc-ioctl.h"
-#include "pwc-uncompress.h"
-
-/* Request types: video */
-#define SET_LUM_CTL			0x01
-#define GET_LUM_CTL			0x02
-#define SET_CHROM_CTL			0x03
-#define GET_CHROM_CTL			0x04
-#define SET_STATUS_CTL			0x05
-#define GET_STATUS_CTL			0x06
-#define SET_EP_STREAM_CTL		0x07
-#define GET_EP_STREAM_CTL		0x08
-#define SET_MPT_CTL			0x0D
-#define GET_MPT_CTL			0x0E
-
-/* Selectors for the Luminance controls [GS]ET_LUM_CTL */
-#define AGC_MODE_FORMATTER			0x2000
-#define PRESET_AGC_FORMATTER			0x2100
-#define SHUTTER_MODE_FORMATTER			0x2200
-#define PRESET_SHUTTER_FORMATTER		0x2300
-#define PRESET_CONTOUR_FORMATTER		0x2400
-#define AUTO_CONTOUR_FORMATTER			0x2500
-#define BACK_LIGHT_COMPENSATION_FORMATTER	0x2600
-#define CONTRAST_FORMATTER			0x2700
-#define DYNAMIC_NOISE_CONTROL_FORMATTER		0x2800
-#define FLICKERLESS_MODE_FORMATTER		0x2900
-#define AE_CONTROL_SPEED			0x2A00
-#define BRIGHTNESS_FORMATTER			0x2B00
-#define GAMMA_FORMATTER				0x2C00
-
-/* Selectors for the Chrominance controls [GS]ET_CHROM_CTL */
-#define WB_MODE_FORMATTER			0x1000
-#define AWB_CONTROL_SPEED_FORMATTER		0x1100
-#define AWB_CONTROL_DELAY_FORMATTER		0x1200
-#define PRESET_MANUAL_RED_GAIN_FORMATTER	0x1300
-#define PRESET_MANUAL_BLUE_GAIN_FORMATTER	0x1400
-#define COLOUR_MODE_FORMATTER			0x1500
-#define SATURATION_MODE_FORMATTER1		0x1600
-#define SATURATION_MODE_FORMATTER2		0x1700
-
-/* Selectors for the Status controls [GS]ET_STATUS_CTL */
-#define SAVE_USER_DEFAULTS_FORMATTER		0x0200
-#define RESTORE_USER_DEFAULTS_FORMATTER		0x0300
-#define RESTORE_FACTORY_DEFAULTS_FORMATTER	0x0400
-#define READ_AGC_FORMATTER			0x0500
-#define READ_SHUTTER_FORMATTER			0x0600
-#define READ_RED_GAIN_FORMATTER			0x0700
-#define READ_BLUE_GAIN_FORMATTER		0x0800
-#define SENSOR_TYPE_FORMATTER1			0x0C00
-#define READ_RAW_Y_MEAN_FORMATTER		0x3100
-#define SET_POWER_SAVE_MODE_FORMATTER		0x3200
-#define MIRROR_IMAGE_FORMATTER			0x3300
-#define LED_FORMATTER				0x3400
-#define SENSOR_TYPE_FORMATTER2			0x3700
-
-/* Formatters for the Video Endpoint controls [GS]ET_EP_STREAM_CTL */
-#define VIDEO_OUTPUT_CONTROL_FORMATTER		0x0100
-
-/* Formatters for the motorized pan & tilt [GS]ET_MPT_CTL */
-#define PT_RELATIVE_CONTROL_FORMATTER		0x01
-#define PT_RESET_CONTROL_FORMATTER		0x02
-#define PT_STATUS_FORMATTER			0x03
-
-static char *size2name[PSZ_MAX] =
-{
-	"subQCIF",
-	"QSIF",
-	"QCIF",
-	"SIF",
-	"CIF",
-	"VGA",
-};  
-
-/********/
-
-/* Entries for the Nala (645/646) camera; the Nala doesn't have compression 
-   preferences, so you either get compressed or non-compressed streams.
-   
-   An alternate value of 0 means this mode is not available at all.
- */
-
-struct Nala_table_entry {
-	char alternate;			/* USB alternate setting */
-	int compressed;			/* Compressed yes/no */
-
-	unsigned char mode[3];		/* precomputed mode table */
-};
-
-static struct Nala_table_entry Nala_table[PSZ_MAX][8] =
-{
-#include "pwc_nala.h"
-};
-
-/* This tables contains entries for the 675/680/690 (Timon) camera, with
-   4 different qualities (no compression, low, medium, high).
-   It lists the bandwidth requirements for said mode by its alternate interface
-   number. An alternate of 0 means that the mode is unavailable.
-
-   There are 6 * 4 * 4 entries:
-     6 different resolutions subqcif, qsif, qcif, sif, cif, vga
-     6 framerates: 5, 10, 15, 20, 25, 30
-     4 compression modi: none, low, medium, high
-
-   When an uncompressed mode is not available, the next available compressed mode
-   will be chosen (unless the decompressor is absent). Sometimes there are only
-   1 or 2 compressed modes available; in that case entries are duplicated.
-*/
-struct Timon_table_entry
-{
-	char alternate;			/* USB alternate interface */
-	unsigned short packetsize;	/* Normal packet size */
-	unsigned short bandlength;	/* Bandlength when decompressing */
-	unsigned char mode[13];		/* precomputed mode settings for cam */
-};
-
-static struct Timon_table_entry Timon_table[PSZ_MAX][6][4] =
-{
-#include "pwc_timon.h"
-};
-
-/* Entries for the Kiara (730/740/750) camera */
-
-struct Kiara_table_entry
-{
-	char alternate;			/* USB alternate interface */
-	unsigned short packetsize;	/* Normal packet size */
-	unsigned short bandlength;	/* Bandlength when decompressing */
-	unsigned char mode[12];		/* precomputed mode settings for cam */
-};
-
-static struct Kiara_table_entry Kiara_table[PSZ_MAX][6][4] =
-{
-#include "pwc_kiara.h"
-};
-
-
-/****************************************************************************/
-
-
-#define SendControlMsg(request, value, buflen) \
-	usb_control_msg(pdev->udev, usb_sndctrlpipe(pdev->udev, 0), \
-		request, \
-		USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, \
-		value, \
-		pdev->vcinterface, \
-		&buf, buflen, HZ / 2)
-
-#define RecvControlMsg(request, value, buflen) \
-	usb_control_msg(pdev->udev, usb_rcvctrlpipe(pdev->udev, 0), \
-		request, \
-		USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE, \
-		value, \
-		pdev->vcinterface, \
-		&buf, buflen, HZ / 2)
-
-
-#if PWC_DEBUG
-void pwc_hexdump(void *p, int len)
-{
-	int i;
-	unsigned char *s;
-	char buf[100], *d;
-
-	s = (unsigned char *)p;
-	d = buf;
-	*d = '\0';
-	Debug("Doing hexdump @ %p, %d bytes.\n", p, len);
-	for (i = 0; i < len; i++) {
-		d += sprintf(d, "%02X ", *s++);
-		if ((i & 0xF) == 0xF) {
-			Debug("%s\n", buf);
-			d = buf;
-			*d = '\0';
-		}
-	}
-	if ((i & 0xF) != 0)
-		Debug("%s\n", buf);
-}
-#endif
-
-static inline int send_video_command(struct usb_device *udev, int index, void *buf, int buflen)
-{
-	return usb_control_msg(udev,
-		usb_sndctrlpipe(udev, 0),
-		SET_EP_STREAM_CTL,
-		USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
-		VIDEO_OUTPUT_CONTROL_FORMATTER,
-		index,
-		buf, buflen, HZ);
-}
-
-
-
-static inline int set_video_mode_Nala(struct pwc_device *pdev, int size, int frames)
-{
-	unsigned char buf[3];
-	int ret, fps;
-	struct Nala_table_entry *pEntry;
-	int frames2frames[31] =
-	{ /* closest match of framerate */
-	   0,  0,  0,  0,  4,  /*  0-4  */
-	   5,  5,  7,  7, 10,  /*  5-9  */
-          10, 10, 12, 12, 15,  /* 10-14 */
-          15, 15, 15, 20, 20,  /* 15-19 */
-          20, 20, 20, 24, 24,  /* 20-24 */
-          24, 24, 24, 24, 24,  /* 25-29 */
-          24                   /* 30    */
-	};
-	int frames2table[31] = 
-	{ 0, 0, 0, 0, 0, /*  0-4  */
-	  1, 1, 1, 2, 2, /*  5-9  */
-	  3, 3, 4, 4, 4, /* 10-14 */
-	  5, 5, 5, 5, 5, /* 15-19 */
-	  6, 6, 6, 6, 7, /* 20-24 */
-	  7, 7, 7, 7, 7, /* 25-29 */
-	  7              /* 30    */
-	};
-	
-	if (size < 0 || size > PSZ_CIF || frames < 4 || frames > 25)
-		return -EINVAL;
-	frames = frames2frames[frames];
-	fps = frames2table[frames];
-	pEntry = &Nala_table[size][fps];
-	if (pEntry->alternate == 0)
-		return -EINVAL;
-
-	if (pEntry->compressed && pdev->decompressor == NULL)
-		return -ENOENT; /* Not supported. */
-
-	memcpy(buf, pEntry->mode, 3);	
-	ret = send_video_command(pdev->udev, pdev->vendpoint, buf, 3);
-	if (ret < 0) {
-		Debug("Failed to send video command... %d\n", ret);
-		return ret;
-	}
-	if (pEntry->compressed && pdev->decompressor != 0 && pdev->vpalette != VIDEO_PALETTE_RAW)
-		pdev->decompressor->init(pdev->type, pdev->release, buf, pdev->decompress_data);
-
-	pdev->cmd_len = 3;
-	memcpy(pdev->cmd_buf, buf, 3);
-
-	/* Set various parameters */
-	pdev->vframes = frames;
-	pdev->vsize = size;
-	pdev->valternate = pEntry->alternate;
-	pdev->image = pwc_image_sizes[size];
-	pdev->frame_size = (pdev->image.x * pdev->image.y * 3) / 2;
-	if (pEntry->compressed) {
-		if (pdev->release < 5) { /* 4 fold compression */
-			pdev->vbandlength = 528;
-			pdev->frame_size /= 4;
-		}
-		else {
-			pdev->vbandlength = 704;
-			pdev->frame_size /= 3;
-		}
-	}
-	else
-		pdev->vbandlength = 0;
-	return 0;
-}
-
-
-static inline int set_video_mode_Timon(struct pwc_device *pdev, int size, int frames, int compression, int snapshot)
-{
-	unsigned char buf[13];
-	struct Timon_table_entry *pChoose;
-	int ret, fps;
-
-	if (size >= PSZ_MAX || frames < 5 || frames > 30 || compression < 0 || compression > 3)
-		return -EINVAL;
-	if (size == PSZ_VGA && frames > 15)
-		return -EINVAL;
-	fps = (frames / 5) - 1;
-
-	/* Find a supported framerate with progressively higher compression ratios
-	   if the preferred ratio is not available.
-	*/
-	pChoose = NULL;
-	if (pdev->decompressor == NULL) {
-#if PWC_DEBUG
-		Debug("Trying to find uncompressed mode.\n");
-#endif
-		pChoose = &Timon_table[size][fps][0];
-	}
-	else {
-		while (compression <= 3) {
-			pChoose = &Timon_table[size][fps][compression];
-			if (pChoose->alternate != 0)
-				break;
-			compression++;
-		}
-	}
-	if (pChoose == NULL || pChoose->alternate == 0)
-		return -ENOENT; /* Not supported. */
-
-	memcpy(buf, pChoose->mode, 13);
-	if (snapshot)
-		buf[0] |= 0x80;
-	ret = send_video_command(pdev->udev, pdev->vendpoint, buf, 13);
-	if (ret < 0)
-		return ret;
-
-	if (pChoose->bandlength > 0 && pdev->decompressor != 0 && pdev->vpalette != VIDEO_PALETTE_RAW)
-		pdev->decompressor->init(pdev->type, pdev->release, buf, pdev->decompress_data);
-
-	pdev->cmd_len = 13;
-	memcpy(pdev->cmd_buf, buf, 13);
-
-	/* Set various parameters */
-	pdev->vframes = frames;
-	pdev->vsize = size;
-	pdev->vsnapshot = snapshot;
-	pdev->valternate = pChoose->alternate;
-	pdev->image = pwc_image_sizes[size];
-	pdev->vbandlength = pChoose->bandlength;
-	if (pChoose->bandlength > 0)
-		pdev->frame_size = (pChoose->bandlength * pdev->image.y) / 4;
-	else
-		pdev->frame_size = (pdev->image.x * pdev->image.y * 12) / 8;
-	return 0;
-}
-
-
-static inline int set_video_mode_Kiara(struct pwc_device *pdev, int size, int frames, int compression, int snapshot)
-{
-	struct Kiara_table_entry *pChoose = NULL;
-	int fps, ret;
-	unsigned char buf[12];
-	struct Kiara_table_entry RawEntry = {6, 773, 1272, {0xAD, 0xF4, 0x10, 0x27, 0xB6, 0x24, 0x96, 0x02, 0x30, 0x05, 0x03, 0x80}};
-
-	if (size >= PSZ_MAX || frames < 5 || frames > 30 || compression < 0 || compression > 3)
-		return -EINVAL;
-	if (size == PSZ_VGA && frames > 15)
-		return -EINVAL;
-	fps = (frames / 5) - 1;
-
-	/* special case: VGA @ 5 fps and snapshot is raw bayer mode */
-	if (size == PSZ_VGA && frames == 5 && snapshot)
-	{
-		/* Only available in case the raw palette is selected or 
-		   we have the decompressor available. This mode is 
-		   only available in compressed form 
-		*/
-		if (pdev->vpalette == VIDEO_PALETTE_RAW || pdev->decompressor != NULL)
-		{
-	                Info("Choosing VGA/5 BAYER mode (%d).\n", pdev->vpalette);
-			pChoose = &RawEntry;
-		}
-		else
-		{
-			Info("VGA/5 BAYER mode _must_ have a decompressor available, or use RAW palette.\n");
-		}
-	}
-	else
-	{
-        	/* Find a supported framerate with progressively higher compression ratios
-		   if the preferred ratio is not available.
-                   Skip this step when using RAW modes.
-		*/
-		if (pdev->decompressor == NULL && pdev->vpalette != VIDEO_PALETTE_RAW) {
-#if PWC_DEBUG
-			Debug("Trying to find uncompressed mode.\n");
-#endif
-			pChoose = &Kiara_table[size][fps][0];
-		}
-		else {
-			while (compression <= 3) {
-				pChoose = &Kiara_table[size][fps][compression];
-				if (pChoose->alternate != 0)
-					break;
-				compression++;
-			}
-   		}
-	}
-	if (pChoose == NULL || pChoose->alternate == 0)
-		return -ENOENT; /* Not supported. */
-
-	/* usb_control_msg won't take staticly allocated arrays as argument?? */
-	memcpy(buf, pChoose->mode, 12);
-	if (snapshot)
-		buf[0] |= 0x80;
-
-	/* Firmware bug: video endpoint is 5, but commands are sent to endpoint 4 */
-	ret = send_video_command(pdev->udev, 4 /* pdev->vendpoint */, buf, 12);
-	if (ret < 0)
-		return ret;
-
-	if (pChoose->bandlength > 0 && pdev->decompressor != 0 && pdev->vpalette != VIDEO_PALETTE_RAW)
-		pdev->decompressor->init(pdev->type, pdev->release, buf, pdev->decompress_data);
-
-	pdev->cmd_len = 12;
-	memcpy(pdev->cmd_buf, buf, 12);
-	/* All set and go */
-	pdev->vframes = frames;
-	pdev->vsize = size;
-	pdev->vsnapshot = snapshot;
-	pdev->valternate = pChoose->alternate;
-	pdev->image = pwc_image_sizes[size];
-	pdev->vbandlength = pChoose->bandlength;
-	if (pdev->vbandlength > 0)
-		pdev->frame_size = (pdev->vbandlength * pdev->image.y) / 4;
-	else
-		pdev->frame_size = (pdev->image.x * pdev->image.y * 12) / 8;
-	return 0;
-}
-
-
-
-/**
-   @pdev: device structure
-   @width: viewport width
-   @height: viewport height
-   @frame: framerate, in fps
-   @compression: preferred compression ratio
-   @snapshot: snapshot mode or streaming
- */
-int pwc_set_video_mode(struct pwc_device *pdev, int width, int height, int frames, int compression, int snapshot)
-{
-        int ret, size;
-
-        Trace(TRACE_FLOW, "set_video_mode(%dx%d @ %d, palette %d).\n", width, height, frames, pdev->vpalette);
-	size = pwc_decode_size(pdev, width, height);
-	if (size < 0) {
-		Debug("Could not find suitable size.\n");
-		return -ERANGE;
-	}
-	Debug("decode_size = %d.\n", size);
-
-        ret = -EINVAL;
-	switch(pdev->type) {
-	case 645:
-	case 646:
-		ret = set_video_mode_Nala(pdev, size, frames);
-		break;
-
-	case 675:
-	case 680:
-	case 690:
-		ret = set_video_mode_Timon(pdev, size, frames, compression, snapshot);
-		break;
-	
-	case 720:
-	case 730:
-	case 740:
-	case 750:
-		ret = set_video_mode_Kiara(pdev, size, frames, compression, snapshot);
-		break;
-	}
-	if (ret < 0) {
-		if (ret == -ENOENT)
-			Info("Video mode %s@%d fps is only supported with the decompressor module (pwcx).\n", size2name[size], frames);
-		else {
-			Err("Failed to set video mode %s@%d fps; return code = %d\n", size2name[size], frames, ret);
-		}
-		return ret;
-	}
-	pdev->view.x = width;
-	pdev->view.y = height;
-	pdev->frame_total_size = pdev->frame_size + pdev->frame_header_size + pdev->frame_trailer_size;
-	pwc_set_image_buffer_size(pdev);
-	Trace(TRACE_SIZE, "Set viewport to %dx%d, image size is %dx%d.\n", width, height, pwc_image_sizes[size].x, pwc_image_sizes[size].y);
-	return 0;
-}
-
-
-void pwc_set_image_buffer_size(struct pwc_device *pdev)
-{
-	int i, factor = 0, filler = 0;
-
-	/* for PALETTE_YUV420P */
-	switch(pdev->vpalette)
-	{
-	case VIDEO_PALETTE_YUV420P:
-		factor = 6;
-		filler = 128;
-		break;
-	case VIDEO_PALETTE_RAW:
-		factor = 6; /* can be uncompressed YUV420P */
-		filler = 0;
-		break;
-	}
-
-	/* Set sizes in bytes */
-	pdev->image.size = pdev->image.x * pdev->image.y * factor / 4;
-	pdev->view.size  = pdev->view.x  * pdev->view.y  * factor / 4;
-
-	/* Align offset, or you'll get some very weird results in
-	   YUV420 mode... x must be multiple of 4 (to get the Y's in
-	   place), and y even (or you'll mixup U & V). This is less of a
-	   problem for YUV420P.
-	 */
-	pdev->offset.x = ((pdev->view.x - pdev->image.x) / 2) & 0xFFFC;
-	pdev->offset.y = ((pdev->view.y - pdev->image.y) / 2) & 0xFFFE;
-
-	/* Fill buffers with gray or black */
-	for (i = 0; i < MAX_IMAGES; i++) {
-		if (pdev->image_ptr[i] != NULL)
-			memset(pdev->image_ptr[i], filler, pdev->view.size);
-	}
-}
-
-
-
-/* BRIGHTNESS */
-
-int pwc_get_brightness(struct pwc_device *pdev)
-{
-	char buf;
-	int ret;
-
-	ret = RecvControlMsg(GET_LUM_CTL, BRIGHTNESS_FORMATTER, 1);	
-	if (ret < 0)
-		return ret;
-	return buf << 9;
-}
-
-int pwc_set_brightness(struct pwc_device *pdev, int value)
-{
-	char buf;
-
-	if (value < 0)
-		value = 0;
-	if (value > 0xffff)
-		value = 0xffff;
-	buf = (value >> 9) & 0x7f;
-	return SendControlMsg(SET_LUM_CTL, BRIGHTNESS_FORMATTER, 1);
-}
-
-/* CONTRAST */
-
-int pwc_get_contrast(struct pwc_device *pdev)
-{
-	char buf;
-	int ret;
-
-	ret = RecvControlMsg(GET_LUM_CTL, CONTRAST_FORMATTER, 1);
-	if (ret < 0)
-		return ret;
-	return buf << 10;
-}
-
-int pwc_set_contrast(struct pwc_device *pdev, int value)
-{
-	char buf;
-
-	if (value < 0)
-		value = 0;
-	if (value > 0xffff)
-		value = 0xffff;
-	buf = (value >> 10) & 0x3f;
-	return SendControlMsg(SET_LUM_CTL, CONTRAST_FORMATTER, 1);
-}
-
-/* GAMMA */
-
-int pwc_get_gamma(struct pwc_device *pdev)
-{
-	char buf;
-	int ret;
-	
-	ret = RecvControlMsg(GET_LUM_CTL, GAMMA_FORMATTER, 1);
-	if (ret < 0)
-		return ret;
-	return buf << 11;
-}
-
-int pwc_set_gamma(struct pwc_device *pdev, int value)
-{
-	char buf;
-
-	if (value < 0)
-		value = 0;
-	if (value > 0xffff)
-		value = 0xffff;
-	buf = (value >> 11) & 0x1f;
-	return SendControlMsg(SET_LUM_CTL, GAMMA_FORMATTER, 1);
-}
-
-
-/* SATURATION */
-
-int pwc_get_saturation(struct pwc_device *pdev)
-{
-	char buf;
-	int ret;
-
-	if (pdev->type < 675)
-		return -1;
-	ret = RecvControlMsg(GET_CHROM_CTL, pdev->type < 730 ? SATURATION_MODE_FORMATTER2 : SATURATION_MODE_FORMATTER1, 1);
-	if (ret < 0)
-		return ret;
-	return 32768 + buf * 327;
-}
-
-int pwc_set_saturation(struct pwc_device *pdev, int value)
-{
-	char buf;
-
-	if (pdev->type < 675)
-		return -EINVAL;
-	if (value < 0)
-		value = 0;
-	if (value > 0xffff)
-		value = 0xffff;
-	/* saturation ranges from -100 to +100 */
-	buf = (value - 32768) / 327;
-	return SendControlMsg(SET_CHROM_CTL, pdev->type < 730 ? SATURATION_MODE_FORMATTER2 : SATURATION_MODE_FORMATTER1, 1);
-}
-
-/* AGC */
-
-static inline int pwc_set_agc(struct pwc_device *pdev, int mode, int value)
-{
-	char buf;
-	int ret;
-	
-	if (mode)
-		buf = 0x0; /* auto */
-	else
-		buf = 0xff; /* fixed */
-
-	ret = SendControlMsg(SET_LUM_CTL, AGC_MODE_FORMATTER, 1);
-	
-	if (!mode && ret >= 0) {
-		if (value < 0)
-			value = 0;
-		if (value > 0xffff)
-			value = 0xffff;
-		buf = (value >> 10) & 0x3F;
-		ret = SendControlMsg(SET_LUM_CTL, PRESET_AGC_FORMATTER, 1);
-	}
-	if (ret < 0)
-		return ret;
-	return 0;
-}
-
-static inline int pwc_get_agc(struct pwc_device *pdev, int *value)
-{
-	unsigned char buf;
-	int ret;
-	
-	ret = RecvControlMsg(GET_LUM_CTL, AGC_MODE_FORMATTER, 1);
-	if (ret < 0)
-		return ret;
-
-	if (buf != 0) { /* fixed */
-		ret = RecvControlMsg(GET_LUM_CTL, PRESET_AGC_FORMATTER, 1);
-		if (ret < 0)
-			return ret;
-		if (buf > 0x3F)
-			buf = 0x3F;
-		*value = (buf << 10);		
-	}
-	else { /* auto */
-		ret = RecvControlMsg(GET_STATUS_CTL, READ_AGC_FORMATTER, 1);
-		if (ret < 0)
-			return ret;
-		/* Gah... this value ranges from 0x00 ... 0x9F */
-		if (buf > 0x9F)
-			buf = 0x9F;
-		*value = -(48 + buf * 409);
-	}
-
-	return 0;
-}
-
-static inline int pwc_set_shutter_speed(struct pwc_device *pdev, int mode, int value)
-{
-	char buf[2];
-	int speed, ret;
-
-
-	if (mode)
-		buf[0] = 0x0;	/* auto */
-	else
-		buf[0] = 0xff; /* fixed */
-	
-	ret = SendControlMsg(SET_LUM_CTL, SHUTTER_MODE_FORMATTER, 1);
-
-	if (!mode && ret >= 0) {
-		if (value < 0)
-			value = 0;
-		if (value > 0xffff)
-			value = 0xffff;
-		switch(pdev->type) {
-		case 675:
-		case 680:
-		case 690:
-			/* speed ranges from 0x0 to 0x290 (656) */
-			speed = (value / 100);
-			buf[1] = speed >> 8;
-			buf[0] = speed & 0xff;
-			break;
-		case 720:
-		case 730:
-		case 740:
-		case 750:
-			/* speed seems to range from 0x0 to 0xff */
-			buf[1] = 0;
-			buf[0] = value >> 8;
-			break;
-		}
-
-		ret = SendControlMsg(SET_LUM_CTL, PRESET_SHUTTER_FORMATTER, 2);
-	}
-	return ret;
-}	
-
-
-/* POWER */
-
-int pwc_camera_power(struct pwc_device *pdev, int power)
-{
-	char buf;
-
-	if (pdev->type < 675 || (pdev->type < 730 && pdev->release < 6))
-		return 0;	/* Not supported by Nala or Timon < release 6 */
-
-	if (power)
-		buf = 0x00; /* active */
-	else
-		buf = 0xFF; /* power save */
-	return SendControlMsg(SET_STATUS_CTL, SET_POWER_SAVE_MODE_FORMATTER, 1);
-}
-
-
-
-/* private calls */
-
-static inline int pwc_restore_user(struct pwc_device *pdev)
-{
-	char buf; /* dummy */
-	return SendControlMsg(SET_STATUS_CTL, RESTORE_USER_DEFAULTS_FORMATTER, 0);
-}
-
-static inline int pwc_save_user(struct pwc_device *pdev)
-{
-	char buf; /* dummy */
-	return SendControlMsg(SET_STATUS_CTL, SAVE_USER_DEFAULTS_FORMATTER, 0);
-}
-
-static inline int pwc_restore_factory(struct pwc_device *pdev)
-{
-	char buf; /* dummy */
-	return SendControlMsg(SET_STATUS_CTL, RESTORE_FACTORY_DEFAULTS_FORMATTER, 0);
-}
-
- /* ************************************************* */
- /* Patch by Alvarado: (not in the original version   */
-
- /*
-  * the camera recognizes modes from 0 to 4:
-  *
-  * 00: indoor (incandescant lighting)
-  * 01: outdoor (sunlight)
-  * 02: fluorescent lighting
-  * 03: manual
-  * 04: auto
-  */ 
-static inline int pwc_set_awb(struct pwc_device *pdev, int mode)
-{
-	char buf;
-	int ret;
-	
-	if (mode < 0)
-	    mode = 0;
-	
-	if (mode > 4)
-	    mode = 4;
-	
-	buf = mode & 0x07; /* just the lowest three bits */
-	
-	ret = SendControlMsg(SET_CHROM_CTL, WB_MODE_FORMATTER, 1);
-	
-	if (ret < 0)
-		return ret;
-	return 0;
-}
-
-static inline int pwc_get_awb(struct pwc_device *pdev)
-{
-	unsigned char buf;
-	int ret;
-	
-	ret = RecvControlMsg(GET_CHROM_CTL, WB_MODE_FORMATTER, 1);
-
-	if (ret < 0) 
-		return ret;
-	return buf;
-}
-
-static inline int pwc_set_red_gain(struct pwc_device *pdev, int value)
-{
-        unsigned char buf;
-
-	if (value < 0)
-		value = 0;
-	if (value > 0xffff)
-		value = 0xffff;
-	/* only the msb is considered */
-	buf = value >> 8;
-	return SendControlMsg(SET_CHROM_CTL, PRESET_MANUAL_RED_GAIN_FORMATTER, 1);
-}
-
-static inline int pwc_get_red_gain(struct pwc_device *pdev, int *value)
-{
-	unsigned char buf;
-	int ret;
-	
-	ret = RecvControlMsg(GET_CHROM_CTL, PRESET_MANUAL_RED_GAIN_FORMATTER, 1);
-	if (ret < 0)
-	    return ret;
-	*value = buf << 8;
-	return 0;
-}
-
-
-static inline int pwc_set_blue_gain(struct pwc_device *pdev, int value)
-{
-	unsigned char buf;
-
-	if (value < 0)
-		value = 0;
-	if (value > 0xffff)
-		value = 0xffff;
-	/* only the msb is considered */
-	buf = value >> 8;
-	return SendControlMsg(SET_CHROM_CTL, PRESET_MANUAL_BLUE_GAIN_FORMATTER, 1);
-}
-
-static inline int pwc_get_blue_gain(struct pwc_device *pdev, int *value)
-{
-	unsigned char buf;
-	int ret;
-	
-	ret = RecvControlMsg(GET_CHROM_CTL, PRESET_MANUAL_BLUE_GAIN_FORMATTER, 1);
-	if (ret < 0)
-	    return ret;
-	*value = buf << 8;
-	return 0;
-}
-
-
-/* The following two functions are different, since they only read the
-   internal red/blue gains, which may be different from the manual 
-   gains set or read above.
- */   
-static inline int pwc_read_red_gain(struct pwc_device *pdev, int *value)
-{
-	unsigned char buf;
-	int ret;
-	
-	ret = RecvControlMsg(GET_STATUS_CTL, READ_RED_GAIN_FORMATTER, 1);
-	if (ret < 0)
-		return ret;
-	*value = buf << 8;
-	return 0;
-}
-
-static inline int pwc_read_blue_gain(struct pwc_device *pdev, int *value)
-{
-	unsigned char buf;
-	int ret;
-	
-	ret = RecvControlMsg(GET_STATUS_CTL, READ_BLUE_GAIN_FORMATTER, 1);
-	if (ret < 0)
-		return ret;
-	*value = buf << 8;
-	return 0;
-}
-
-
-static inline int pwc_set_wb_speed(struct pwc_device *pdev, int speed)
-{
-	unsigned char buf;
-	
-	/* useful range is 0x01..0x20 */
-	buf = speed / 0x7f0;
-	return SendControlMsg(SET_CHROM_CTL, AWB_CONTROL_SPEED_FORMATTER, 1);
-}
-
-static inline int pwc_get_wb_speed(struct pwc_device *pdev, int *value)
-{
-	unsigned char buf;
-	int ret;
-	
-	ret = RecvControlMsg(GET_CHROM_CTL, AWB_CONTROL_SPEED_FORMATTER, 1);
-	if (ret < 0)
-		return ret;
-	*value = buf * 0x7f0;
-	return 0;
-}
-
-
-static inline int pwc_set_wb_delay(struct pwc_device *pdev, int delay)
-{
-	unsigned char buf;
-	
-	/* useful range is 0x01..0x3F */
-	buf = (delay >> 10);
-	return SendControlMsg(SET_CHROM_CTL, AWB_CONTROL_DELAY_FORMATTER, 1);
-}
-
-static inline int pwc_get_wb_delay(struct pwc_device *pdev, int *value)
-{
-	unsigned char buf;
-	int ret;
-	
-	ret = RecvControlMsg(GET_CHROM_CTL, AWB_CONTROL_DELAY_FORMATTER, 1);
-	if (ret < 0)
-		return ret;
-	*value = buf << 10;
-	return 0;
-}
-
-
-int pwc_set_leds(struct pwc_device *pdev, int on_value, int off_value)
-{
-	unsigned char buf[2];
-
-	if (pdev->type < 730)
-		return 0;
-	on_value /= 100;
-	off_value /= 100;
-	if (on_value < 0)
-		on_value = 0;
-	if (on_value > 0xff)
-		on_value = 0xff;
-	if (off_value < 0)
-		off_value = 0;
-	if (off_value > 0xff)
-		off_value = 0xff;
-
-	buf[0] = on_value;
-	buf[1] = off_value;
-
-	return SendControlMsg(SET_STATUS_CTL, LED_FORMATTER, 2);
-}
-
-int pwc_get_leds(struct pwc_device *pdev, int *on_value, int *off_value)
-{
-	unsigned char buf[2];
-	int ret;
-	
-	if (pdev->type < 730) {
-		*on_value = -1;
-		*off_value = -1;
-		return 0;
-	}
-
-	ret = RecvControlMsg(GET_STATUS_CTL, LED_FORMATTER, 2);
-	if (ret < 0)
-		return ret;
-	*on_value = buf[0] * 100;
-	*off_value = buf[1] * 100;
-	return 0;
-}
-
-static inline int pwc_set_contour(struct pwc_device *pdev, int contour)
-{
-	unsigned char buf;
-	int ret;
-	
-	if (contour < 0)
-		buf = 0xff; /* auto contour on */
-	else
-		buf = 0x0; /* auto contour off */
-	ret = SendControlMsg(SET_LUM_CTL, AUTO_CONTOUR_FORMATTER, 1);
-	if (ret < 0)
-		return ret;
-	
-	if (contour < 0)
-		return 0;
-	if (contour > 0xffff)
-		contour = 0xffff;
-	
-	buf = (contour >> 10); /* contour preset is [0..3f] */
-	ret = SendControlMsg(SET_LUM_CTL, PRESET_CONTOUR_FORMATTER, 1);
-	if (ret < 0)	
-		return ret;	
-	return 0;
-}
-
-static inline int pwc_get_contour(struct pwc_device *pdev, int *contour)
-{
-	unsigned char buf;
-	int ret;
-	
-	ret = RecvControlMsg(GET_LUM_CTL, AUTO_CONTOUR_FORMATTER, 1);
-	if (ret < 0)
-		return ret;
-
-	if (buf == 0) {
-		/* auto mode off, query current preset value */
-		ret = RecvControlMsg(GET_LUM_CTL, PRESET_CONTOUR_FORMATTER, 1);
-		if (ret < 0)	
-			return ret;
-		*contour = buf << 10;
-	}
-	else
-		*contour = -1;
-	return 0;
-}
-
-
-static inline int pwc_set_backlight(struct pwc_device *pdev, int backlight)
-{
-	unsigned char buf;
-	
-	if (backlight)
-		buf = 0xff;
-	else
-		buf = 0x0;
-	return SendControlMsg(SET_LUM_CTL, BACK_LIGHT_COMPENSATION_FORMATTER, 1);
-}
-
-static inline int pwc_get_backlight(struct pwc_device *pdev, int *backlight)
-{
-	int ret;
-	unsigned char buf;
-	
-	ret = RecvControlMsg(GET_LUM_CTL, BACK_LIGHT_COMPENSATION_FORMATTER, 1);
-	if (ret < 0)
-		return ret;
-	*backlight = buf;
-	return 0;
-}
-
-
-static inline int pwc_set_flicker(struct pwc_device *pdev, int flicker)
-{
-	unsigned char buf;
-	
-	if (flicker)
-		buf = 0xff;
-	else
-		buf = 0x0;
-	return SendControlMsg(SET_LUM_CTL, FLICKERLESS_MODE_FORMATTER, 1);
-}
-
-static inline int pwc_get_flicker(struct pwc_device *pdev, int *flicker)
-{
-	int ret;
-	unsigned char buf;
-	
-	ret = RecvControlMsg(GET_LUM_CTL, FLICKERLESS_MODE_FORMATTER, 1);
-	if (ret < 0)
-		return ret;
-	*flicker = buf;
-	return 0;
-}
-
-
-static inline int pwc_set_dynamic_noise(struct pwc_device *pdev, int noise)
-{
-	unsigned char buf;
-
-	if (noise < 0)
-		noise = 0;
-	if (noise > 3)
-		noise = 3;
-	buf = noise;
-	return SendControlMsg(SET_LUM_CTL, DYNAMIC_NOISE_CONTROL_FORMATTER, 1);
-}
-
-static inline int pwc_get_dynamic_noise(struct pwc_device *pdev, int *noise)
-{
-	int ret;
-	unsigned char buf;
-	
-	ret = RecvControlMsg(GET_LUM_CTL, DYNAMIC_NOISE_CONTROL_FORMATTER, 1);
-	if (ret < 0)
-		return ret;
-	*noise = buf;
-	return 0;
-}
-
-int pwc_mpt_reset(struct pwc_device *pdev, int flags)
-{
-	unsigned char buf;
-	
-	buf = flags & 0x03; // only lower two bits are currently used
-	return SendControlMsg(SET_MPT_CTL, PT_RESET_CONTROL_FORMATTER, 1);
-}
-
-static inline int pwc_mpt_set_angle(struct pwc_device *pdev, int pan, int tilt)
-{
-	unsigned char buf[4];
-	
-	/* set new relative angle; angles are expressed in degrees * 100,
-	   but cam as .5 degree resolution, hence devide by 200. Also
-	   the angle must be multiplied by 64 before it's send to
-	   the cam (??)
-	 */
-	pan  =  64 * pan  / 100;
-	tilt = -64 * tilt / 100; /* positive tilt is down, which is not what the user would expect */
-	buf[0] = pan & 0xFF;
-	buf[1] = (pan >> 8) & 0xFF;
-	buf[2] = tilt & 0xFF;
-	buf[3] = (tilt >> 8) & 0xFF;
-	return SendControlMsg(SET_MPT_CTL, PT_RELATIVE_CONTROL_FORMATTER, 4);
-}
-
-static inline int pwc_mpt_get_status(struct pwc_device *pdev, struct pwc_mpt_status *status)
-{
-	int ret;
-	unsigned char buf[5];
-	
-	ret = RecvControlMsg(GET_MPT_CTL, PT_STATUS_FORMATTER, 5);
-	if (ret < 0)
-		return ret;
-	status->status = buf[0] & 0x7; // 3 bits are used for reporting
-	status->time_pan = (buf[1] << 8) + buf[2];
-	status->time_tilt = (buf[3] << 8) + buf[4];
-	return 0;
-}
-
-
-int pwc_get_cmos_sensor(struct pwc_device *pdev, int *sensor)
-{
-	unsigned char buf;
-	int ret = -1, request;
-	
-	if (pdev->type < 675)
-		request = SENSOR_TYPE_FORMATTER1;
-	else if (pdev->type < 730)
-		return -1; /* The Vesta series doesn't have this call */
-	else
-		request = SENSOR_TYPE_FORMATTER2;
-	
-	ret = RecvControlMsg(GET_STATUS_CTL, request, 1);
-	if (ret < 0)
-		return ret;
-	if (pdev->type < 675)
-		*sensor = buf | 0x100;
-	else
-		*sensor = buf;
-	return 0;
-}
-
-
- /* End of Add-Ons                                    */
- /* ************************************************* */
-
-/* Linux 2.5.something and 2.6 pass direct pointers to arguments of
-   ioctl() calls. With 2.4, you have to do tedious copy_from_user()
-   and copy_to_user() calls. With these macros we circumvent this,
-   and let me maintain only one source file. The functionality is
-   exactly the same otherwise.
- */   
-
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0)
-
-/* define local variable for arg */
-#define ARG_DEF(ARG_type, ARG_name)\
-	ARG_type *ARG_name = arg;
-/* copy arg to local variable */	
-#define ARG_IN(ARG_name) /* nothing */
-/* argument itself (referenced) */
-#define ARGR(ARG_name) (*ARG_name)
-/* argument address */
-#define ARGA(ARG_name) ARG_name
-/* copy local variable to arg */
-#define ARG_OUT(ARG_name) /* nothing */
-
-#else
-
-#define ARG_DEF(ARG_type, ARG_name)\
-	ARG_type ARG_name;
-#define ARG_IN(ARG_name)\
-	if (copy_from_user(&ARG_name, arg, sizeof(ARG_name))) {\
-		ret = -EFAULT;\
-		break;\
-	}
-#define ARGR(ARG_name) ARG_name
-#define ARGA(ARG_name) &ARG_name
-#define ARG_OUT(ARG_name)\
-	if (copy_to_user(arg, &ARG_name, sizeof(ARG_name))) {\
-		ret = -EFAULT;\
-		break;\
-	}
-
-#endif
-
-int pwc_ioctl(struct pwc_device *pdev, unsigned int cmd, void *arg)
-{
-	int ret = 0;
-
-	switch(cmd) {
-	case VIDIOCPWCRUSER:
-	{
-		if (pwc_restore_user(pdev))
-			ret = -EINVAL;
-		break;
-	}
-	
-	case VIDIOCPWCSUSER:
-	{
-		if (pwc_save_user(pdev))
-			ret = -EINVAL;
-		break;
-	}
-		
-	case VIDIOCPWCFACTORY:
-	{
-		if (pwc_restore_factory(pdev))
-			ret = -EINVAL;
-		break;
-	}
-	
-	case VIDIOCPWCSCQUAL:
-	{	
-		ARG_DEF(int, qual)
-
-		ARG_IN(qual)
-		if (ARGR(qual) < 0 || ARGR(qual) > 3)
-			ret = -EINVAL;
-		else
-			ret = pwc_try_video_mode(pdev, pdev->view.x, pdev->view.y, pdev->vframes, ARGR(qual), pdev->vsnapshot);
-		if (ret >= 0)
-			pdev->vcompression = ARGR(qual);
-		break;
-	}
-	
-	case VIDIOCPWCGCQUAL:
-	{
-		ARG_DEF(int, qual)
-		
-		ARGR(qual) = pdev->vcompression;
-		ARG_OUT(qual)
-		break;
-	}
-	
-	case VIDIOCPWCPROBE:
-	{
-		ARG_DEF(struct pwc_probe, probe)
-		
-		strcpy(ARGR(probe).name, pdev->vdev->name);
-		ARGR(probe).type = pdev->type;
-		ARG_OUT(probe)
-		break;
-	}
-
-	case VIDIOCPWCGSERIAL:
-	{
-		ARG_DEF(struct pwc_serial, serial)
-		
-		strcpy(ARGR(serial).serial, pdev->serial);
-		ARG_OUT(serial)
-		break;
-	}
-
-	case VIDIOCPWCSAGC:
-	{
-		ARG_DEF(int, agc)
-
-		ARG_IN(agc)
-		if (pwc_set_agc(pdev, ARGR(agc) < 0 ? 1 : 0, ARGR(agc)))
-			ret = -EINVAL;
-		break;
-	}
-	
-	case VIDIOCPWCGAGC:
-	{
-		ARG_DEF(int, agc)
-		
-		if (pwc_get_agc(pdev, ARGA(agc)))
-			ret = -EINVAL;
-		ARG_OUT(agc)
-		break;
-	}
-	
-	case VIDIOCPWCSSHUTTER:
-	{
-		ARG_DEF(int, shutter_speed)
-
-		ARG_IN(shutter_speed)
-		ret = pwc_set_shutter_speed(pdev, ARGR(shutter_speed) < 0 ? 1 : 0, ARGR(shutter_speed));
-		break;
-	}
-	
-        case VIDIOCPWCSAWB:
-	{
-		ARG_DEF(struct pwc_whitebalance, wb)
-		
-		ARG_IN(wb)
-		ret = pwc_set_awb(pdev, ARGR(wb).mode);
-		if (ret >= 0 && ARGR(wb).mode == PWC_WB_MANUAL) {
-			pwc_set_red_gain(pdev, ARGR(wb).manual_red);
-			pwc_set_blue_gain(pdev, ARGR(wb).manual_blue);
-		}
-		break;
-	}
-
-	case VIDIOCPWCGAWB:
-	{
-		ARG_DEF(struct pwc_whitebalance, wb)
-
-		memset(ARGA(wb), 0, sizeof(struct pwc_whitebalance));
-		ARGR(wb).mode = pwc_get_awb(pdev);
-		if (ARGR(wb).mode < 0)
-			ret = -EINVAL;
-		else {
-			if (ARGR(wb).mode == PWC_WB_MANUAL) {
-				ret = pwc_get_red_gain(pdev, &ARGR(wb).manual_red);
-				if (ret < 0)
-					break;
-				ret = pwc_get_blue_gain(pdev, &ARGR(wb).manual_blue);
-				if (ret < 0)
-					break;
-			}
-			if (ARGR(wb).mode == PWC_WB_AUTO) {
-				ret = pwc_read_red_gain(pdev, &ARGR(wb).read_red);
-				if (ret < 0)
-					break;
- 				ret =pwc_read_blue_gain(pdev, &ARGR(wb).read_blue);
- 				if (ret < 0)
- 					break;
-			}
-		}
-		ARG_OUT(wb)
-		break;
-	}
-	
-	case VIDIOCPWCSAWBSPEED:
-	{
-		ARG_DEF(struct pwc_wb_speed, wbs)
-		
-		if (ARGR(wbs).control_speed > 0) {
-			ret = pwc_set_wb_speed(pdev, ARGR(wbs).control_speed);
-		}
-		if (ARGR(wbs).control_delay > 0) {
-			ret = pwc_set_wb_delay(pdev, ARGR(wbs).control_delay);
-		}
-		break;
-	}
-	
-	case VIDIOCPWCGAWBSPEED:
-	{
-		ARG_DEF(struct pwc_wb_speed, wbs)
-		
-		ret = pwc_get_wb_speed(pdev, &ARGR(wbs).control_speed);
-		if (ret < 0)
-			break;
-		ret = pwc_get_wb_delay(pdev, &ARGR(wbs).control_delay);
-		if (ret < 0)
-			break;
-		ARG_OUT(wbs)
-		break;
-	}
-
-        case VIDIOCPWCSLED:
-	{
-		ARG_DEF(struct pwc_leds, leds)
-
-		ARG_IN(leds)
-		ret = pwc_set_leds(pdev, ARGR(leds).led_on, ARGR(leds).led_off);
-	    	break;
-	}
-
-
-	case VIDIOCPWCGLED:
-	{
-		ARG_DEF(struct pwc_leds, leds)
-		
-		ret = pwc_get_leds(pdev, &ARGR(leds).led_on, &ARGR(leds).led_off);
-		ARG_OUT(leds)
-		break;
-	}
-
-	case VIDIOCPWCSCONTOUR:
-	{
-		ARG_DEF(int, contour)
-
-		ARG_IN(contour)
-		ret = pwc_set_contour(pdev, ARGR(contour));
-		break;
-	}
-			
-	case VIDIOCPWCGCONTOUR:
-	{
-		ARG_DEF(int, contour)
-		
-		ret = pwc_get_contour(pdev, ARGA(contour));
-		ARG_OUT(contour)
-		break;
-	}
-	
-	case VIDIOCPWCSBACKLIGHT:
-	{
-		ARG_DEF(int, backlight)
-		
-		ARG_IN(backlight)
-		ret = pwc_set_backlight(pdev, ARGR(backlight));
-		break;
-	}
-
-	case VIDIOCPWCGBACKLIGHT:
-	{
-		ARG_DEF(int, backlight)
-		
-		ret = pwc_get_backlight(pdev, ARGA(backlight));
-		ARG_OUT(backlight)
-		break;
-	}
-	
-	case VIDIOCPWCSFLICKER:
-	{
-		ARG_DEF(int, flicker)
-		
-		ARG_IN(flicker)
-		ret = pwc_set_flicker(pdev, ARGR(flicker));
-		break;
-	}
-
-	case VIDIOCPWCGFLICKER:
-	{
-		ARG_DEF(int, flicker)
-		
-		ret = pwc_get_flicker(pdev, ARGA(flicker));
-		ARG_OUT(flicker)
-		break;
-	}
-	
-	case VIDIOCPWCSDYNNOISE:
-	{
-		ARG_DEF(int, dynnoise)
-		
-		ARG_IN(dynnoise)
-		ret = pwc_set_dynamic_noise(pdev, ARGR(dynnoise));
-		break;
-	}
-	
-	case VIDIOCPWCGDYNNOISE:
-	{
-		ARG_DEF(int, dynnoise)
-
-		ret = pwc_get_dynamic_noise(pdev, ARGA(dynnoise));
-		ARG_OUT(dynnoise);
-		break;
-	}
-
-	case VIDIOCPWCGREALSIZE:
-	{
-		ARG_DEF(struct pwc_imagesize, size)
-		
-		ARGR(size).width = pdev->image.x;
-		ARGR(size).height = pdev->image.y;
-		ARG_OUT(size)
-		break;
- 	}
- 	
- 	case VIDIOCPWCMPTRESET:
- 	{
- 		if (pdev->features & FEATURE_MOTOR_PANTILT)
- 		{
-	 		ARG_DEF(int, flags)
-
- 			ARG_IN(flags)
-			ret = pwc_mpt_reset(pdev, ARGR(flags));
- 			if (ret >= 0)
- 			{
- 				pdev->pan_angle = 0;
- 				pdev->tilt_angle = 0;
- 			}
- 		}
- 		else
- 		{
- 			ret = -ENXIO;
- 		}
- 		break;		
- 	}
- 	
- 	case VIDIOCPWCMPTGRANGE:
- 	{
- 		if (pdev->features & FEATURE_MOTOR_PANTILT)
- 		{
- 			ARG_DEF(struct pwc_mpt_range, range)
- 			
- 			ARGR(range) = pdev->angle_range;
- 			ARG_OUT(range)
- 		}
- 		else
- 		{	
- 			ret = -ENXIO;
- 		}
- 		break;
- 	}
- 	
- 	case VIDIOCPWCMPTSANGLE:
- 	{
- 		int new_pan, new_tilt;
- 		
- 		if (pdev->features & FEATURE_MOTOR_PANTILT)
- 		{
-	 		ARG_DEF(struct pwc_mpt_angles, angles)
-
-	 		ARG_IN(angles)
-			/* The camera can only set relative angles, so
-			   do some calculations when getting an absolute angle .
-			 */
-			if (ARGR(angles).absolute)
-			{
- 				new_pan  = ARGR(angles).pan; 
- 				new_tilt = ARGR(angles).tilt;
- 			}
- 			else
- 			{
- 				new_pan  = pdev->pan_angle  + ARGR(angles).pan;
- 				new_tilt = pdev->tilt_angle + ARGR(angles).tilt;
-			}
-			/* check absolute ranges */
-			if (new_pan  < pdev->angle_range.pan_min  ||
-			    new_pan  > pdev->angle_range.pan_max  ||
-			    new_tilt < pdev->angle_range.tilt_min ||
-			    new_tilt > pdev->angle_range.tilt_max)
-			{
-				ret = -ERANGE;
-			}
-			else
-			{
-				/* go to relative range, check again */
-				new_pan  -= pdev->pan_angle;
-				new_tilt -= pdev->tilt_angle;
-				/* angles are specified in degrees * 100, thus the limit = 36000 */
-				if (new_pan < -36000 || new_pan > 36000 || new_tilt < -36000 || new_tilt > 36000)
-					ret = -ERANGE;
-			}
-			if (ret == 0) /* no errors so far */
-			{
-				ret = pwc_mpt_set_angle(pdev, new_pan, new_tilt);
-				if (ret >= 0)
-				{
-					pdev->pan_angle  += new_pan;
-					pdev->tilt_angle += new_tilt;
-				}
-				if (ret == -EPIPE) /* stall -> out of range */
-					ret = -ERANGE;				
-			}
- 		}
- 		else
- 		{
- 			ret = -ENXIO;
- 		}
- 		break;
- 	}
-
- 	case VIDIOCPWCMPTGANGLE:
- 	{
- 		
- 		if (pdev->features & FEATURE_MOTOR_PANTILT)
- 		{
-	 		ARG_DEF(struct pwc_mpt_angles, angles)
-
- 			ARGR(angles).absolute = 1;
- 			ARGR(angles).pan  = pdev->pan_angle;
- 			ARGR(angles).tilt = pdev->tilt_angle;
- 			ARG_OUT(angles)
- 		}
- 		else
- 		{
- 			ret = -ENXIO;
- 		}
- 		break;
- 	}
- 
- 	case VIDIOCPWCMPTSTATUS:
- 	{
- 		if (pdev->features & FEATURE_MOTOR_PANTILT)
- 		{
- 			ARG_DEF(struct pwc_mpt_status, status)
- 			
- 			ret = pwc_mpt_get_status(pdev, ARGA(status));
- 			ARG_OUT(status)
- 		}
- 		else
- 		{
- 			ret = -ENXIO;
- 		}
- 		break;
-	}
-
-	case VIDIOCPWCGVIDCMD:
-	{
-		ARG_DEF(struct pwc_video_command, cmd);
-		
-                ARGR(cmd).type = pdev->type;
-		ARGR(cmd).release = pdev->release;
-		ARGR(cmd).command_len = pdev->cmd_len;
-		memcpy(&ARGR(cmd).command_buf, pdev->cmd_buf, pdev->cmd_len);
-		ARGR(cmd).bandlength = pdev->vbandlength;
-		ARGR(cmd).frame_size = pdev->frame_size;
-		ARG_OUT(cmd)
-		break;
-	}
-
-	default:
-		ret = -ENOIOCTLCMD;
-		break;
-	}
-	
-	if (ret > 0)
-		return 0;
-	return ret;
-}
-
-
-
diff -Nru a/drivers/usb/media/pwc-if.c b/drivers/usb/media/pwc-if.c
--- a/drivers/usb/media/pwc-if.c	2004-10-18 14:56:49 -07:00
+++ /dev/null	Wed Dec 31 16:00:00 196900
@@ -1,2193 +0,0 @@
-/* Linux driver for Philips webcam
-   USB and Video4Linux interface part.
-   (C) 1999-2004 Nemosoft Unv.
-
-   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 code forms the interface between the USB layers and the Philips
-   specific stuff. Some adanved stuff of the driver falls under an
-   NDA, signed between me and Philips B.V., Eindhoven, the Netherlands, and
-   is thus not distributed in source form. The binary pwcx.o module 
-   contains the code that falls under the NDA.
-   
-   In case you're wondering: 'pwc' stands for "Philips WebCam", but 
-   I really didn't want to type 'philips_web_cam' every time (I'm lazy as
-   any Linux kernel hacker, but I don't like uncomprehensible abbreviations
-   without explanation).
-   
-   Oh yes, convention: to disctinguish between all the various pointers to
-   device-structures, I use these names for the pointer variables:
-   udev: struct usb_device *
-   vdev: struct video_device *
-   pdev: struct pwc_devive *
-*/
-
-/* Contributors:
-   - Alvarado: adding whitebalance code
-   - Alistar Moire: QuickCam 3000 Pro device/product ID
-   - Tony Hoyle: Creative Labs Webcam 5 device/product ID
-   - Mark Burazin: solving hang in VIDIOCSYNC when camera gets unplugged
-   - Jk Fang: Sotec Afina Eye ID
-   - Xavier Roche: QuickCam Pro 4000 ID
-   - Jens Knudsen: QuickCam Zoom ID
-   - J. Debert: QuickCam for Notebooks ID
-*/
-
-#include <linux/errno.h>
-#include <linux/init.h>
-#include <linux/mm.h>
-#include <linux/module.h>
-#include <linux/poll.h>
-#include <linux/slab.h>
-#include <linux/vmalloc.h>
-#include <asm/io.h>
-
-#include "pwc.h"
-#include "pwc-ioctl.h"
-#include "pwc-uncompress.h"
-
-/* Function prototypes and driver templates */
-
-/* hotplug device table support */
-static struct usb_device_id pwc_device_table [] = {
-	{ USB_DEVICE(0x0471, 0x0302) }, /* Philips models */
-	{ USB_DEVICE(0x0471, 0x0303) },
-	{ USB_DEVICE(0x0471, 0x0304) },
-	{ USB_DEVICE(0x0471, 0x0307) },
-	{ USB_DEVICE(0x0471, 0x0308) },
-	{ USB_DEVICE(0x0471, 0x030C) },
-	{ USB_DEVICE(0x0471, 0x0310) },
-	{ USB_DEVICE(0x0471, 0x0311) },
-	{ USB_DEVICE(0x0471, 0x0312) },
-	{ USB_DEVICE(0x0471, 0x0313) }, /* the 'new' 720K */
-	{ USB_DEVICE(0x069A, 0x0001) }, /* Askey */
-	{ USB_DEVICE(0x046D, 0x08B0) }, /* Logitech QuickCam Pro 3000 */
-	{ USB_DEVICE(0x046D, 0x08B1) }, /* Logitech QuickCam Notebook Pro */
-	{ USB_DEVICE(0x046D, 0x08B2) }, /* Logitech QuickCam Pro 4000 */
-	{ USB_DEVICE(0x046D, 0x08B3) }, /* Logitech QuickCam Zoom (old model) */
-	{ USB_DEVICE(0x046D, 0x08B4) }, /* Logitech QuickCam Zoom (new model) */
-	{ USB_DEVICE(0x046D, 0x08B5) }, /* Logitech QuickCam Orbit/Sphere */
-	{ USB_DEVICE(0x046D, 0x08B6) }, /* Logitech (reserved) */
-	{ USB_DEVICE(0x046D, 0x08B7) }, /* Logitech (reserved) */
-	{ USB_DEVICE(0x046D, 0x08B8) }, /* Logitech (reserved) */
-	{ USB_DEVICE(0x055D, 0x9000) }, /* Samsung */
-	{ USB_DEVICE(0x055D, 0x9001) },
-	{ USB_DEVICE(0x041E, 0x400C) }, /* Creative Webcam 5 */
-	{ USB_DEVICE(0x041E, 0x4011) }, /* Creative Webcam Pro Ex */
-	{ USB_DEVICE(0x04CC, 0x8116) }, /* Afina Eye */
-	{ USB_DEVICE(0x06BE, 0x8116) }, /* new Afina Eye */
-	{ USB_DEVICE(0x0d81, 0x1910) }, /* Visionite */
-	{ USB_DEVICE(0x0d81, 0x1900) },
-	{ }
-};
-MODULE_DEVICE_TABLE(usb, pwc_device_table);
-
-static int usb_pwc_probe(struct usb_interface *intf, const struct usb_device_id *id);
-static void usb_pwc_disconnect(struct usb_interface *intf);
-
-static struct usb_driver pwc_driver = {
-	.owner =		THIS_MODULE,
-	.name =			"Philips webcam",	/* name */
-	.id_table =		pwc_device_table,
-	.probe =		usb_pwc_probe,		/* probe() */
-	.disconnect =		usb_pwc_disconnect,	/* disconnect() */
-};
-
-#define MAX_DEV_HINTS	20
-#define MAX_ISOC_ERRORS	20
-
-static int default_size = PSZ_QCIF;
-static int default_fps = 10;
-static int default_fbufs = 3;   /* Default number of frame buffers */
-static int default_mbufs = 2;	/* Default number of mmap() buffers */
-       int pwc_trace = TRACE_MODULE | TRACE_FLOW | TRACE_PWCX;
-static int power_save = 0;
-static int led_on = 100, led_off = 0; /* defaults to LED that is on while in use */
-       int pwc_preferred_compression = 2; /* 0..3 = uncompressed..high */
-static struct {
-	int type;
-	char serial_number[30];
-	int device_node;
-	struct pwc_device *pdev;
-} device_hint[MAX_DEV_HINTS];
-
-/***/
-
-static int pwc_video_open(struct inode *inode, struct file *file);
-static int pwc_video_close(struct inode *inode, struct file *file);
-static ssize_t pwc_video_read(struct file *file, char __user *buf,
-			  size_t count, loff_t *ppos);
-static unsigned int pwc_video_poll(struct file *file, poll_table *wait);
-static int  pwc_video_ioctl(struct inode *inode, struct file *file,
-			    unsigned int ioctlnr, unsigned long arg);
-static int  pwc_video_mmap(struct file *file, struct vm_area_struct *vma);
-
-static struct file_operations pwc_fops = {
-	.owner =	THIS_MODULE,
-	.open =		pwc_video_open,
-	.release =     	pwc_video_close,
-	.read =		pwc_video_read,
-	.poll =		pwc_video_poll,
-	.mmap =		pwc_video_mmap,
-	.ioctl =        pwc_video_ioctl,
-	.llseek =       no_llseek,
-};
-static struct video_device pwc_template = {
-	.owner =	THIS_MODULE,
-	.name =		"Philips Webcam",	/* Filled in later */
-	.type =		VID_TYPE_CAPTURE,
-	.hardware =	VID_HARDWARE_PWC,
-	.release =	video_device_release,
-	.fops =         &pwc_fops,
-	.minor =        -1,
-};
-
-/***************************************************************************/
-
-/* Okay, this is some magic that I worked out and the reasoning behind it...
-
-   The biggest problem with any USB device is of course: "what to do 
-   when the user unplugs the device while it is in use by an application?"
-   We have several options:
-   1) Curse them with the 7 plagues when they do (requires divine intervention)
-   2) Tell them not to (won't work: they'll do it anyway)
-   3) Oops the kernel (this will have a negative effect on a user's uptime)
-   4) Do something sensible.
-   
-   Of course, we go for option 4.
-
-   It happens that this device will be linked to two times, once from
-   usb_device and once from the video_device in their respective 'private'
-   pointers. This is done when the device is probed() and all initialization
-   succeeded. The pwc_device struct links back to both structures.
-
-   When a device is unplugged while in use it will be removed from the 
-   list of known USB devices; I also de-register it as a V4L device, but 
-   unfortunately I can't free the memory since the struct is still in use
-   by the file descriptor. This free-ing is then deferend until the first
-   opportunity. Crude, but it works.
-   
-   A small 'advantage' is that if a user unplugs the cam and plugs it back
-   in, it should get assigned the same video device minor, but unfortunately
-   it's non-trivial to re-link the cam back to the video device... (that 
-   would surely be magic! :))
-*/
-
-/***************************************************************************/
-/* Private functions */
-
-/* Here we want the physical address of the memory.
- * This is used when initializing the contents of the area.
- */
-static inline unsigned long kvirt_to_pa(unsigned long adr) 
-{
-        unsigned long kva, ret;
-
-	kva = (unsigned long) page_address(vmalloc_to_page((void *)adr));
-	kva |= adr & (PAGE_SIZE-1); /* restore the offset */
-	ret = __pa(kva);
-        return ret;
-}
-
-static void * rvmalloc(unsigned long size)
-{
-	void * mem;
-	unsigned long adr;
-
-	size=PAGE_ALIGN(size);
-        mem=vmalloc_32(size);
-	if (mem) 
-	{
-		memset(mem, 0, size); /* Clear the ram out, no junk to the user */
-	        adr=(unsigned long) mem;
-		while (size > 0) 
-                {
-			SetPageReserved(vmalloc_to_page((void *)adr));
-			adr+=PAGE_SIZE;
-			size-=PAGE_SIZE;
-		}
-	}
-	return mem;
-}
-
-static void rvfree(void * mem, unsigned long size)
-{
-        unsigned long adr;
-
-	if (mem) 
-	{
-	        adr=(unsigned long) mem;
-		while ((long) size > 0) 
-                {
-			ClearPageReserved(vmalloc_to_page((void *)adr));
-			adr+=PAGE_SIZE;
-			size-=PAGE_SIZE;
-		}
-		vfree(mem);
-	}
-}
-
-
-
-
-static int pwc_allocate_buffers(struct pwc_device *pdev)
-{
-	int i;
-	void *kbuf;
-
-	Trace(TRACE_MEMORY, ">> pwc_allocate_buffers(pdev = 0x%p)\n", pdev);
-
-	if (pdev == NULL)
-		return -ENXIO;
-		
-#ifdef PWC_MAGIC
-	if (pdev->magic != PWC_MAGIC) {
-		Err("allocate_buffers(): magic failed.\n");
-		return -ENXIO;
-	}
-#endif	
-	/* Allocate Isochronuous pipe buffers */
-	for (i = 0; i < MAX_ISO_BUFS; i++) {
-		if (pdev->sbuf[i].data == NULL) {
-			kbuf = kmalloc(ISO_BUFFER_SIZE, GFP_KERNEL);
-			if (kbuf == NULL) {
-				Err("Failed to allocate iso buffer %d.\n", i);
-				return -ENOMEM;
-			}
-			Trace(TRACE_MEMORY, "Allocated iso buffer at %p.\n", kbuf);
-			pdev->sbuf[i].data = kbuf;
-			memset(kbuf, 0, ISO_BUFFER_SIZE);
-		}
-	}
-
-	/* Allocate frame buffer structure */
-	if (pdev->fbuf == NULL) {
-		kbuf = kmalloc(default_fbufs * sizeof(struct pwc_frame_buf), GFP_KERNEL);
-		if (kbuf == NULL) {
-			Err("Failed to allocate frame buffer structure.\n");
-			return -ENOMEM;
-		}
-		Trace(TRACE_MEMORY, "Allocated frame buffer structure at %p.\n", kbuf);
-		pdev->fbuf = kbuf;
-		memset(kbuf, 0, default_fbufs * sizeof(struct pwc_frame_buf));
-	}
-	/* create frame buffers, and make circular ring */
-	for (i = 0; i < default_fbufs; i++) {
-		if (pdev->fbuf[i].data == NULL) {
-			kbuf = vmalloc(PWC_FRAME_SIZE); /* need vmalloc since frame buffer > 128K */
-			if (kbuf == NULL) {
-				Err("Failed to allocate frame buffer %d.\n", i);
-				return -ENOMEM;
-			}
-			Trace(TRACE_MEMORY, "Allocated frame buffer %d at %p.\n", i, kbuf);
-			pdev->fbuf[i].data = kbuf;
-			memset(kbuf, 128, PWC_FRAME_SIZE);
-		}
-	}
-	
-	/* Allocate decompressor table space */
-	kbuf = NULL;
-	if (pdev->decompressor != NULL) {
-		kbuf = kmalloc(pdev->decompressor->table_size, GFP_KERNEL);
-		if (kbuf == NULL) {
-			Err("Failed to allocate decompress table.\n");
-			return -ENOMEM;
-		}
-		Trace(TRACE_MEMORY, "Allocated decompress table %p.\n", kbuf);
-	}
-	pdev->decompress_data = kbuf;
-	
-	/* Allocate image buffer; double buffer for mmap() */
-	kbuf = rvmalloc(default_mbufs * pdev->len_per_image);
-	if (kbuf == NULL) {
-		Err("Failed to allocate image buffer(s).\n");
-		return -ENOMEM;
-	}
-	Trace(TRACE_MEMORY, "Allocated image buffer at %p.\n", kbuf);
-	pdev->image_data = kbuf;
-	for (i = 0; i < default_mbufs; i++)
-		pdev->image_ptr[i] = kbuf + i * pdev->len_per_image;
-	for (; i < MAX_IMAGES; i++)
-		pdev->image_ptr[i] = NULL;
-
-	kbuf = NULL;
-	  
-	Trace(TRACE_MEMORY, "<< pwc_allocate_buffers()\n");
-	return 0;
-}
-
-static void pwc_free_buffers(struct pwc_device *pdev)
-{
-	int i;
-
-	Trace(TRACE_MEMORY, "Entering free_buffers(%p).\n", pdev);
-
-	if (pdev == NULL)
-		return;
-#ifdef PWC_MAGIC
-	if (pdev->magic != PWC_MAGIC) {
-		Err("free_buffers(): magic failed.\n");
-		return;
-	}
-#endif	
-
-	/* Release Iso-pipe buffers */
-	for (i = 0; i < MAX_ISO_BUFS; i++)
-		if (pdev->sbuf[i].data != NULL) {
-			Trace(TRACE_MEMORY, "Freeing ISO buffer at %p.\n", pdev->sbuf[i].data);
-			kfree(pdev->sbuf[i].data);
-			pdev->sbuf[i].data = NULL;
-		}
-
-	/* The same for frame buffers */
-	if (pdev->fbuf != NULL) {
-		for (i = 0; i < default_fbufs; i++) {
-			if (pdev->fbuf[i].data != NULL) {
-				Trace(TRACE_MEMORY, "Freeing frame buffer %d at %p.\n", i, pdev->fbuf[i].data);
-				vfree(pdev->fbuf[i].data);
-				pdev->fbuf[i].data = NULL;
-			}
-		}
-		kfree(pdev->fbuf);
-		pdev->fbuf = NULL;
-	}
-
-	/* Intermediate decompression buffer & tables */
-	if (pdev->decompress_data != NULL) {
-		Trace(TRACE_MEMORY, "Freeing decompression buffer at %p.\n", pdev->decompress_data);
-		kfree(pdev->decompress_data);
-		pdev->decompress_data = NULL;
-	}
-	pdev->decompressor = NULL;
-
-	/* Release image buffers */
-	if (pdev->image_data != NULL) {
-		Trace(TRACE_MEMORY, "Freeing image buffer at %p.\n", pdev->image_data);
-		rvfree(pdev->image_data, default_mbufs * pdev->len_per_image);
-	}
-	pdev->image_data = NULL;
-	
-	Trace(TRACE_MEMORY, "Leaving free_buffers().\n");
-}
-
-/* The frame & image buffer mess. 
-
-   Yes, this is a mess. Well, it used to be simple, but alas...  In this
-   module, 3 buffers schemes are used to get the data from the USB bus to
-   the user program. The first scheme involves the ISO buffers (called thus
-   since they transport ISO data from the USB controller), and not really
-   interesting. Suffices to say the data from this buffer is quickly 
-   gathered in an interrupt handler (pwc_isoc_handler) and placed into the
-   frame buffer.
-
-   The frame buffer is the second scheme, and is the central element here.
-   It collects the data from a single frame from the camera (hence, the
-   name). Frames are delimited by the USB camera with a short USB packet,
-   so that's easy to detect. The frame buffers form a list that is filled
-   by the camera+USB controller and drained by the user process through
-   either read() or mmap().
-
-   The image buffer is the third scheme, in which frames are decompressed
-   and converted into planar format. For mmap() there is more than
-   one image buffer available.
-
-   The frame buffers provide the image buffering. In case the user process
-   is a bit slow, this introduces lag and some undesired side-effects.
-   The problem arises when the frame buffer is full. I used to drop the last
-   frame, which makes the data in the queue stale very quickly. But dropping
-   the frame at the head of the queue proved to be a litte bit more difficult.
-   I tried a circular linked scheme, but this introduced more problems than
-   it solved.
-
-   Because filling and draining are completely asynchronous processes, this
-   requires some fiddling with pointers and mutexes.
-
-   Eventually, I came up with a system with 2 lists: an 'empty' frame list
-   and a 'full' frame list:
-     * Initially, all frame buffers but one are on the 'empty' list; the one
-       remaining buffer is our initial fill frame.
-     * If a frame is needed for filling, we try to take it from the 'empty' 
-       list, unless that list is empty, in which case we take the buffer at 
-       the head of the 'full' list.
-     * When our fill buffer has been filled, it is appended to the 'full'
-       list.
-     * If a frame is needed by read() or mmap(), it is taken from the head of
-       the 'full' list, handled, and then appended to the 'empty' list. If no
-       buffer is present on the 'full' list, we wait.
-   The advantage is that the buffer that is currently being decompressed/
-   converted, is on neither list, and thus not in our way (any other scheme
-   I tried had the problem of old data lingering in the queue).
-
-   Whatever strategy you choose, it always remains a tradeoff: with more
-   frame buffers the chances of a missed frame are reduced. On the other
-   hand, on slower machines it introduces lag because the queue will
-   always be full.
- */
-
-/**
-  \brief Find next frame buffer to fill. Take from empty or full list, whichever comes first.
- */
-static inline int pwc_next_fill_frame(struct pwc_device *pdev)
-{
-	int ret;
-	unsigned long flags;
-
-	ret = 0;
-	spin_lock_irqsave(&pdev->ptrlock, flags);
-	if (pdev->fill_frame != NULL) {
-		/* append to 'full' list */
-		if (pdev->full_frames == NULL) {
-			pdev->full_frames = pdev->fill_frame;
-			pdev->full_frames_tail = pdev->full_frames;
-		}
-		else {
-			pdev->full_frames_tail->next = pdev->fill_frame;
-			pdev->full_frames_tail = pdev->fill_frame;
-		}
-	}
-	if (pdev->empty_frames != NULL) {
-		/* We have empty frames available. That's easy */
-		pdev->fill_frame = pdev->empty_frames;
-		pdev->empty_frames = pdev->empty_frames->next;
-	}
-	else {
-		/* Hmm. Take it from the full list */
-#if PWC_DEBUG
-		/* sanity check */
-		if (pdev->full_frames == NULL) {
-			Err("Neither empty or full frames available!\n");
-			spin_unlock_irqrestore(&pdev->ptrlock, flags);
-			return -EINVAL;
-		}
-#endif
-		pdev->fill_frame = pdev->full_frames;
-		pdev->full_frames = pdev->full_frames->next;
-		ret = 1;
-	}
-	pdev->fill_frame->next = NULL;
-#if PWC_DEBUG
-	Trace(TRACE_SEQUENCE, "Assigning sequence number %d.\n", pdev->sequence);
-	pdev->fill_frame->sequence = pdev->sequence++;
-#endif
-	spin_unlock_irqrestore(&pdev->ptrlock, flags);
-	return ret;
-}
-
-
-/**
-  \brief Reset all buffers, pointers and lists, except for the image_used[] buffer.
-
-  If the image_used[] buffer is cleared too, mmap()/VIDIOCSYNC will run into trouble.
- */
-static void pwc_reset_buffers(struct pwc_device *pdev)
-{
-	int i;
-	unsigned long flags;
-
-	spin_lock_irqsave(&pdev->ptrlock, flags);
-	pdev->full_frames = NULL;
-	pdev->full_frames_tail = NULL;
-	for (i = 0; i < default_fbufs; i++) {
-		pdev->fbuf[i].filled = 0;
-		if (i > 0)
-			pdev->fbuf[i].next = &pdev->fbuf[i - 1];
-		else
-			pdev->fbuf->next = NULL;
-	}
-	pdev->empty_frames = &pdev->fbuf[default_fbufs - 1];
-	pdev->empty_frames_tail = pdev->fbuf;
-	pdev->read_frame = NULL;
-	pdev->fill_frame = pdev->empty_frames;
-	pdev->empty_frames = pdev->empty_frames->next;
-
-	pdev->image_read_pos = 0;
-	pdev->fill_image = 0;
-	spin_unlock_irqrestore(&pdev->ptrlock, flags);
-}
-
-
-/**
-  \brief Do all the handling for getting one frame: get pointer, decompress, advance pointers.
- */
-static int pwc_handle_frame(struct pwc_device *pdev)
-{
-	int ret = 0;
-	unsigned long flags;
-
-	spin_lock_irqsave(&pdev->ptrlock, flags);
-	/* First grab our read_frame; this is removed from all lists, so
-	   we can release the lock after this without problems */
-	if (pdev->read_frame != NULL) {
-		/* This can't theoretically happen */
-		Err("Huh? Read frame still in use?\n");
-	}
-	else {
-		if (pdev->full_frames == NULL) {
-			Err("Woops. No frames ready.\n");
-		}
-		else {
-			pdev->read_frame = pdev->full_frames;
-			pdev->full_frames = pdev->full_frames->next;
-			pdev->read_frame->next = NULL;
-		}
-
-		if (pdev->read_frame != NULL) {
-#if PWC_DEBUG
-			Trace(TRACE_SEQUENCE, "Decompressing frame %d\n", pdev->read_frame->sequence);
-#endif
-			/* Decompression is a lenghty process, so it's outside of the lock.
-			   This gives the isoc_handler the opportunity to fill more frames
-			   in the mean time.
-			*/
-			spin_unlock_irqrestore(&pdev->ptrlock, flags);
-			ret = pwc_decompress(pdev);
-			spin_lock_irqsave(&pdev->ptrlock, flags);
-
-			/* We're done with read_buffer, tack it to the end of the empty buffer list */
-			if (pdev->empty_frames == NULL) {
-				pdev->empty_frames = pdev->read_frame;
-				pdev->empty_frames_tail = pdev->empty_frames;
-			}
-			else {
-				pdev->empty_frames_tail->next = pdev->read_frame;
-				pdev->empty_frames_tail = pdev->read_frame;
-			}
-			pdev->read_frame = NULL;
-		}
-	}
-	spin_unlock_irqrestore(&pdev->ptrlock, flags);
-	return ret;
-}
-
-/**
-  \brief Advance pointers of image buffer (after each user request)
-*/
-static inline void pwc_next_image(struct pwc_device *pdev)
-{
-	pdev->image_used[pdev->fill_image] = 0;
-	pdev->fill_image = (pdev->fill_image + 1) % default_mbufs;
-}
-
-
-/* This gets called for the Isochronous pipe (video). This is done in
- * interrupt time, so it has to be fast, not crash, and not stall. Neat.
- */
-static void pwc_isoc_handler(struct urb *urb, struct pt_regs *regs)
-{
-	struct pwc_device *pdev;
-	int i, fst, flen;
-	int awake;
-	struct pwc_frame_buf *fbuf;
-	unsigned char *fillptr = NULL;
-	unsigned char *iso_buf = NULL;
-
-	awake = 0;
-	pdev = (struct pwc_device *)urb->context;
-	if (pdev == NULL) {
-		Err("isoc_handler() called with NULL device?!\n");
-		return;
-	}
-#ifdef PWC_MAGIC
-	if (pdev->magic != PWC_MAGIC) {
-		Err("isoc_handler() called with bad magic!\n");
-		return;
-	}
-#endif
-	if (urb->status == -ENOENT || urb->status == -ECONNRESET) {
-		Trace(TRACE_OPEN, "pwc_isoc_handler(): URB (%p) unlinked %ssynchronuously.\n", urb, urb->status == -ENOENT ? "" : "a");
-		return;
-	}
-	if (urb->status != -EINPROGRESS && urb->status != 0) {
-		const char *errmsg;
-
-		errmsg = "Unknown";
-		switch(urb->status) {
-			case -ENOSR:		errmsg = "Buffer error (overrun)"; break;
-			case -EPIPE:		errmsg = "Stalled (device not responding)"; break;
-			case -EOVERFLOW:	errmsg = "Babble (bad cable?)"; break;
-			case -EPROTO:		errmsg = "Bit-stuff error (bad cable?)"; break;
-			case -EILSEQ:		errmsg = "CRC/Timeout (could be anything)"; break;
-			case -ETIMEDOUT:	errmsg = "NAK (device does not respond)"; break;
-		}
-		Trace(TRACE_FLOW, "pwc_isoc_handler() called with status %d [%s].\n", urb->status, errmsg);
-		/* Give up after a number of contiguous errors on the USB bus. 
-		   Appearantly something is wrong so we simulate an unplug event.
-		 */
-		if (++pdev->visoc_errors > MAX_ISOC_ERRORS)
-		{
-			Info("Too many ISOC errors, bailing out.\n");
-			pdev->error_status = EIO;
-			awake = 1;
-			wake_up_interruptible(&pdev->frameq);
-		}
-		goto handler_end; // ugly, but practical
-	}
-
-	fbuf = pdev->fill_frame;
-	if (fbuf == NULL) {
-		Err("pwc_isoc_handler without valid fill frame.\n");
-		awake = 1;
-		goto handler_end;
-	}
-	else {
-		fillptr = fbuf->data + fbuf->filled;
-	}
-
-	/* Reset ISOC error counter. We did get here, after all. */
-	pdev->visoc_errors = 0;
-
-	/* vsync: 0 = don't copy data
-	          1 = sync-hunt
-	          2 = synched
-	 */
-	/* Compact data */
-	for (i = 0; i < urb->number_of_packets; i++) {
-		fst  = urb->iso_frame_desc[i].status;
-		flen = urb->iso_frame_desc[i].actual_length;
-		iso_buf = urb->transfer_buffer + urb->iso_frame_desc[i].offset;
-		if (fst == 0) {
-			if (flen > 0) { /* if valid data... */
-				if (pdev->vsync > 0) { /* ...and we are not sync-hunting... */
-					pdev->vsync = 2;
-
-					/* ...copy data to frame buffer, if possible */
-					if (flen + fbuf->filled > pdev->frame_total_size) {
-						Trace(TRACE_FLOW, "Frame buffer overflow (flen = %d, frame_total_size = %d).\n", flen, pdev->frame_total_size);
-						pdev->vsync = 0; /* Hmm, let's wait for an EOF (end-of-frame) */
-						pdev->vframes_error++;
-					}
-					else {
-						memmove(fillptr, iso_buf, flen);
-						fillptr += flen;
-					}
-				}
-				fbuf->filled += flen;
-			} /* ..flen > 0 */
-
-			if (flen < pdev->vlast_packet_size) {
-				/* Shorter packet... We probably have the end of an image-frame; 
-				   wake up read() process and let select()/poll() do something.
-				   Decompression is done in user time over there.
-				 */
-				if (pdev->vsync == 2) {
-					/* The ToUCam Fun CMOS sensor causes the firmware to send 2 or 3 bogus 
-					   frames on the USB wire after an exposure change. This conditition is 
-					   however detected  in the cam and a bit is set in the header.
-					 */
-					if (pdev->type == 730) {
-						unsigned char *ptr = (unsigned char *)fbuf->data;
-						
-						if (ptr[1] == 1 && ptr[0] & 0x10) {
-#if PWC_DEBUG
-							Debug("Hyundai CMOS sensor bug. Dropping frame %d.\n", fbuf->sequence);
-#endif
-							pdev->drop_frames += 2;
-							pdev->vframes_error++;
-						}
-						if ((ptr[0] ^ pdev->vmirror) & 0x01) {
-							if (ptr[0] & 0x01)
-								Info("Snapshot button pressed.\n");
-							else
-								Info("Snapshot button released.\n");
-						}
-						if ((ptr[0] ^ pdev->vmirror) & 0x02) {
-							if (ptr[0] & 0x02)
-								Info("Image is mirrored.\n");
-							else
-								Info("Image is normal.\n");
-						}
-						pdev->vmirror = ptr[0] & 0x03;
-						/* Sometimes the trailer of the 730 is still sent as a 4 byte packet 
-						   after a short frame; this condition is filtered out specifically. A 4 byte
-						   frame doesn't make sense anyway.
-						   So we get either this sequence: 
-						   	drop_bit set -> 4 byte frame -> short frame -> good frame
-						   Or this one:
-						   	drop_bit set -> short frame -> good frame
-						   So we drop either 3 or 2 frames in all!
-						 */
-						if (fbuf->filled == 4)
-							pdev->drop_frames++;
-					}
-
-					/* In case we were instructed to drop the frame, do so silently.
-					   The buffer pointers are not updated either (but the counters are reset below).
-					 */
-					if (pdev->drop_frames > 0)
-						pdev->drop_frames--;
-					else {
-						/* Check for underflow first */
-						if (fbuf->filled < pdev->frame_total_size) {
-							Trace(TRACE_FLOW, "Frame buffer underflow (%d bytes); discarded.\n", fbuf->filled);
-							pdev->vframes_error++;
-						}
-						else {
-							/* Send only once per EOF */
-							awake = 1; /* delay wake_ups */
-
-							/* Find our next frame to fill. This will always succeed, since we
-							 * nick a frame from either empty or full list, but if we had to
-							 * take it from the full list, it means a frame got dropped.
-							 */
-							if (pwc_next_fill_frame(pdev)) {
-								pdev->vframes_dumped++;
-								if ((pdev->vframe_count > FRAME_LOWMARK) && (pwc_trace & TRACE_FLOW)) {
-									if (pdev->vframes_dumped < 20)
-										Trace(TRACE_FLOW, "Dumping frame %d.\n", pdev->vframe_count);
-									if (pdev->vframes_dumped == 20)
-										Trace(TRACE_FLOW, "Dumping frame %d (last message).\n", pdev->vframe_count);
-								}
-							}
-							fbuf = pdev->fill_frame;
-						}
-					} /* !drop_frames */
-					pdev->vframe_count++;
-				}
-				fbuf->filled = 0;
-				fillptr = fbuf->data;
-				pdev->vsync = 1;
-			} /* .. flen < last_packet_size */
-			pdev->vlast_packet_size = flen;
-		} /* ..status == 0 */
-#if PWC_DEBUG
-		/* This is normally not interesting to the user, unless you are really debugging something */
-		else {
-			static int iso_error = 0;
-			iso_error++;
-			if (iso_error < 20)
-				Trace(TRACE_FLOW, "Iso frame %d of USB has error %d\n", i, fst);
-		}
-#endif
-	}
-
-handler_end:
-	if (awake)
-		wake_up_interruptible(&pdev->frameq);
-
-	urb->dev = pdev->udev;
-	i = usb_submit_urb(urb, GFP_ATOMIC);
-	if (i != 0)
-		Err("Error (%d) re-submitting urb in pwc_isoc_handler.\n", i);
-}
-
-
-static int pwc_isoc_init(struct pwc_device *pdev)
-{
-	struct usb_device *udev;
-	struct urb *urb;
-	int i, j, ret;
-
-	struct usb_interface *intf;
-	struct usb_host_interface *idesc = NULL;
-
-	if (pdev == NULL)
-		return -EFAULT;
-	if (pdev->iso_init)
-		return 0;
-	pdev->vsync = 0;
-	udev = pdev->udev;
-
-	/* Get the current alternate interface, adjust packet size */
-	if (!udev->actconfig)
-		return -EFAULT;
-	intf = usb_ifnum_to_if(udev, 0);
-	if (intf)
-		idesc = usb_altnum_to_altsetting(intf, pdev->valternate);
-	if (!idesc)
-		return -EFAULT;
-
-	/* Search video endpoint */
-	pdev->vmax_packet_size = -1;
-	for (i = 0; i < idesc->desc.bNumEndpoints; i++)
-		if ((idesc->endpoint[i].desc.bEndpointAddress & 0xF) == pdev->vendpoint) {
-			pdev->vmax_packet_size = idesc->endpoint[i].desc.wMaxPacketSize;
-			break;
-		}
-	
-	if (pdev->vmax_packet_size < 0 || pdev->vmax_packet_size > ISO_MAX_FRAME_SIZE) {
-		Err("Failed to find packet size for video endpoint in current alternate setting.\n");
-		return -ENFILE; /* Odd error, that should be noticable */
-	}
-
-	/* Set alternate interface */
-	ret = 0;
-	Trace(TRACE_OPEN, "Setting alternate interface %d\n", pdev->valternate);
-	ret = usb_set_interface(pdev->udev, 0, pdev->valternate);
-	if (ret < 0)
-		return ret;
-
-	for (i = 0; i < MAX_ISO_BUFS; i++) {
-		urb = usb_alloc_urb(ISO_FRAMES_PER_DESC, GFP_KERNEL);
-		if (urb == NULL) {
-			Err("Failed to allocate urb %d\n", i);
-			ret = -ENOMEM;
-			break;
-		}
-		pdev->sbuf[i].urb = urb;
-		Trace(TRACE_MEMORY, "Allocated URB at 0x%p\n", urb);
-	}
-	if (ret) {
-		/* De-allocate in reverse order */
-		while (i >= 0) {
-			if (pdev->sbuf[i].urb != NULL)
-				usb_free_urb(pdev->sbuf[i].urb);
-			pdev->sbuf[i].urb = NULL;
-			i--;
-		}
-		return ret;
-	}
-
-	/* init URB structure */	
-	for (i = 0; i < MAX_ISO_BUFS; i++) {
-		urb = pdev->sbuf[i].urb;
-
-		urb->interval = 1; // devik
-		urb->dev = udev;
-	        urb->pipe = usb_rcvisocpipe(udev, pdev->vendpoint);
-		urb->transfer_flags = URB_ISO_ASAP;
-	        urb->transfer_buffer = pdev->sbuf[i].data;
-	        urb->transfer_buffer_length = ISO_BUFFER_SIZE;
-	        urb->complete = pwc_isoc_handler;
-	        urb->context = pdev;
-		urb->start_frame = 0;
-		urb->number_of_packets = ISO_FRAMES_PER_DESC;
-		for (j = 0; j < ISO_FRAMES_PER_DESC; j++) {
-			urb->iso_frame_desc[j].offset = j * ISO_MAX_FRAME_SIZE;
-			urb->iso_frame_desc[j].length = pdev->vmax_packet_size;
-		}
-	}
-
-	/* link */
-	for (i = 0; i < MAX_ISO_BUFS; i++) {
-		ret = usb_submit_urb(pdev->sbuf[i].urb, GFP_KERNEL);
-		if (ret)
-			Err("isoc_init() submit_urb %d failed with error %d\n", i, ret);
-		else
-			Trace(TRACE_MEMORY, "URB 0x%p submitted.\n", pdev->sbuf[i].urb);
-	}
-
-	/* All is done... */
-	pdev->iso_init = 1;
-	Trace(TRACE_OPEN, "<< pwc_isoc_init()\n");
-	return 0;
-}
-
-static void pwc_isoc_cleanup(struct pwc_device *pdev)
-{
-	int i;
-
-	Trace(TRACE_OPEN, ">> pwc_isoc_cleanup()\n");
-	if (pdev == NULL)
-		return;
-
-	/* Unlinking ISOC buffers one by one */
-	for (i = 0; i < MAX_ISO_BUFS; i++) {
-		struct urb *urb;
-
-		urb = pdev->sbuf[i].urb;
-		if (urb != 0) {
-			if (pdev->iso_init) {
-				Trace(TRACE_MEMORY, "Unlinking URB %p\n", urb);
-				usb_unlink_urb(urb);
-			}
-			Trace(TRACE_MEMORY, "Freeing URB\n");
-			usb_free_urb(urb);
-			pdev->sbuf[i].urb = NULL;
-		}
-	}
-
-	/* Stop camera, but only if we are sure the camera is still there (unplug
-	   is signalled by EPIPE) 
-	 */
-	if (pdev->error_status && pdev->error_status != EPIPE) {
-		Trace(TRACE_OPEN, "Setting alternate interface 0.\n");
-		usb_set_interface(pdev->udev, 0, 0);
-	}
-
-	pdev->iso_init = 0;
-	Trace(TRACE_OPEN, "<< pwc_isoc_cleanup()\n");
-}
-
-int pwc_try_video_mode(struct pwc_device *pdev, int width, int height, int new_fps, int new_compression, int new_snapshot)
-{
-	int ret, start;
-
-	/* Stop isoc stuff */
-	pwc_isoc_cleanup(pdev);
-	/* Reset parameters */
-	pwc_reset_buffers(pdev);
-	/* Try to set video mode... */
-	start = ret = pwc_set_video_mode(pdev, width, height, new_fps, new_compression, new_snapshot);
-	if (ret) { 
-	        Trace(TRACE_FLOW, "pwc_set_video_mode attempt 1 failed.\n");
-		/* That failed... restore old mode (we know that worked) */
-		start = pwc_set_video_mode(pdev, pdev->view.x, pdev->view.y, pdev->vframes, pdev->vcompression, pdev->vsnapshot);
-		if (start) {
-		        Trace(TRACE_FLOW, "pwc_set_video_mode attempt 2 failed.\n");
-		}
-	}
-	if (start == 0)
-	{
-		if (pwc_isoc_init(pdev) < 0)
-		{
-			Info("Failed to restart ISOC transfers in pwc_try_video_mode.\n");
-			ret = -EAGAIN; /* let's try again, who knows if it works a second time */
-		}
-	}
-	pdev->drop_frames++; /* try to avoid garbage during switch */
-	return ret; /* Return original error code */
-}
-
-
-/***************************************************************************/
-/* Video4Linux functions */
-
-static int pwc_video_open(struct inode *inode, struct file *file)
-{
-	int i;
-	struct video_device *vdev = video_devdata(file);
-	struct pwc_device *pdev;
-
-	Trace(TRACE_OPEN, ">> video_open called(vdev = 0x%p).\n", vdev);
-	
-	pdev = (struct pwc_device *)vdev->priv;
-	if (pdev == NULL)
-		BUG();
-	if (pdev->vopen)
-		return -EBUSY;
-	
-	down(&pdev->modlock);
-	if (!pdev->usb_init) {
-		Trace(TRACE_OPEN, "Doing first time initialization.\n");
-		pdev->usb_init = 1;
-		
-		if (pwc_trace & TRACE_OPEN)
-		{
-			/* Query sensor type */
-			const char *sensor_type = NULL;
-			int ret;
-
-			ret = pwc_get_cmos_sensor(pdev, &i);
-			if (ret >= 0)
-			{
-				switch(i) {
-				case 0x00:  sensor_type = "Hyundai CMOS sensor"; break;
-				case 0x20:  sensor_type = "Sony CCD sensor + TDA8787"; break;
-				case 0x2E:  sensor_type = "Sony CCD sensor + Exas 98L59"; break;
-				case 0x2F:  sensor_type = "Sony CCD sensor + ADI 9804"; break;
-				case 0x30:  sensor_type = "Sharp CCD sensor + TDA8787"; break;
-				case 0x3E:  sensor_type = "Sharp CCD sensor + Exas 98L59"; break;
-				case 0x3F:  sensor_type = "Sharp CCD sensor + ADI 9804"; break;
-				case 0x40:  sensor_type = "UPA 1021 sensor"; break;
-				case 0x100: sensor_type = "VGA sensor"; break;
-				case 0x101: sensor_type = "PAL MR sensor"; break;
-				default:    sensor_type = "unknown type of sensor"; break;
-				}
-			}
-			if (sensor_type != NULL)
-				Info("This %s camera is equipped with a %s (%d).\n", pdev->vdev->name, sensor_type, i);
-		}
-	}
-
-	/* Turn on camera */
-	if (power_save) {
-		i = pwc_camera_power(pdev, 1);
-		if (i < 0)
-			Info("Failed to restore power to the camera! (%d)\n", i);
-	}
-	/* Set LED on/off time */
-	if (pwc_set_leds(pdev, led_on, led_off) < 0)
-		Info("Failed to set LED on/off time.\n");
-
-	/* Find our decompressor, if any */
-	pdev->decompressor = pwc_find_decompressor(pdev->type);
-#if PWC_DEBUG	
-	Debug("Found decompressor for %d at 0x%p\n", pdev->type, pdev->decompressor);
-#endif
-	pwc_construct(pdev); /* set min/max sizes correct */
-
-	/* So far, so good. Allocate memory. */
-	i = pwc_allocate_buffers(pdev);
-	if (i < 0) {
-		Trace(TRACE_OPEN, "Failed to allocate buffer memory.\n");
-		up(&pdev->modlock);
-		return i;
-	}
-	
-	/* Reset buffers & parameters */
-	pwc_reset_buffers(pdev);
-	for (i = 0; i < default_mbufs; i++)
-		pdev->image_used[i] = 0;
-	pdev->vframe_count = 0;
-	pdev->vframes_dumped = 0;
-	pdev->vframes_error = 0;
-	pdev->visoc_errors = 0;
-	pdev->error_status = 0;
-#if PWC_DEBUG
-	pdev->sequence = 0;
-#endif
-	pwc_construct(pdev); /* set min/max sizes correct */
-
-	/* Set some defaults */
-	pdev->vsnapshot = 0;
-
-	/* Start iso pipe for video; first try the last used video size
-	   (or the default one); if that fails try QCIF/10 or QSIF/10;
-	   it that fails too, give up.
-	 */
-	i = pwc_set_video_mode(pdev, pwc_image_sizes[pdev->vsize].x, pwc_image_sizes[pdev->vsize].y, pdev->vframes, pdev->vcompression, 0);
-	if (i)	{
-		Trace(TRACE_OPEN, "First attempt at set_video_mode failed.\n");
-		if (pdev->type == 730 || pdev->type == 740 || pdev->type == 750)
-			i = pwc_set_video_mode(pdev, pwc_image_sizes[PSZ_QSIF].x, pwc_image_sizes[PSZ_QSIF].y, 10, pdev->vcompression, 0);
-		else
-			i = pwc_set_video_mode(pdev, pwc_image_sizes[PSZ_QCIF].x, pwc_image_sizes[PSZ_QCIF].y, 10, pdev->vcompression, 0);
-	}
-	if (i) {
-		Trace(TRACE_OPEN, "Second attempt at set_video_mode failed.\n");
-		up(&pdev->modlock);
-		return i;
-	}
-	
-	i = pwc_isoc_init(pdev);
-	if (i) {
-		Trace(TRACE_OPEN, "Failed to init ISOC stuff = %d.\n", i);
-		up(&pdev->modlock);
-		return i;
-	}
-
-	pdev->vopen++;
-	file->private_data = vdev;
-	/* lock decompressor; this has a small race condition, since we 
-	   could in theory unload pwcx.o between pwc_find_decompressor()
-	   above and this call. I doubt it's ever going to be a problem.
-	 */
-	if (pdev->decompressor != NULL)
-		pdev->decompressor->lock();
-	up(&pdev->modlock);
-	Trace(TRACE_OPEN, "<< video_open() returns 0.\n");
-	return 0;
-}
-
-/* Note that all cleanup is done in the reverse order as in _open */
-static int pwc_video_close(struct inode *inode, struct file *file)
-{
-	struct video_device *vdev = file->private_data;
-	struct pwc_device *pdev;
-	int i;
-
-	Trace(TRACE_OPEN, ">> video_close called(vdev = 0x%p).\n", vdev);
-
-	pdev = (struct pwc_device *)vdev->priv;
-	if (pdev->vopen == 0)
-		Info("video_close() called on closed device?\n");
-
-	/* Dump statistics, but only if a reasonable amount of frames were
-	   processed (to prevent endless log-entries in case of snap-shot
-	   programs)
-	 */
-	if (pdev->vframe_count > 20)
-		Info("Closing video device: %d frames received, dumped %d frames, %d frames with errors.\n", pdev->vframe_count, pdev->vframes_dumped, pdev->vframes_error);
-
-	if (pdev->decompressor != NULL) {
-		pdev->decompressor->exit();
-		pdev->decompressor->unlock();
-		pdev->decompressor = NULL;
-	}
-
-	pwc_isoc_cleanup(pdev);
-	pwc_free_buffers(pdev);
-
-	/* Turn off LEDS and power down camera, but only when not unplugged */
-	if (pdev->error_status != EPIPE) {
-		/* Turn LEDs off */
-		if (pwc_set_leds(pdev, 0, 0) < 0)
-			Info("Failed to set LED on/off time.\n");
-		if (power_save) {
-			i = pwc_camera_power(pdev, 0);
-			if (i < 0)
-				Err("Failed to power down camera (%d)\n", i);
-		}
-	}
-	pdev->vopen = 0;
-	Trace(TRACE_OPEN, "<< video_close()\n");
-	return 0;
-}
-
-/*
- *	FIXME: what about two parallel reads ????
- *      ANSWER: Not supported. You can't open the device more than once,
-                despite what the V4L1 interface says. First, I don't see
-                the need, second there's no mechanism of alerting the
-                2nd/3rd/... process of events like changing image size.
-                And I don't see the point of blocking that for the
-                2nd/3rd/... process.
-                In multi-threaded environments reading parallel from any
-                device is tricky anyhow.
- */
-
-static ssize_t pwc_video_read(struct file *file, char __user *buf,
-			  size_t count, loff_t *ppos)
-{
-	struct video_device *vdev = file->private_data;
-	struct pwc_device *pdev;
-	int noblock = file->f_flags & O_NONBLOCK;
-	DECLARE_WAITQUEUE(wait, current);
-        int bytes_to_read;
-
-	Trace(TRACE_READ, "video_read(0x%p, %p, %zd) called.\n", vdev, buf, count);
-	if (vdev == NULL)
-		return -EFAULT;
-	pdev = vdev->priv;
-	if (pdev == NULL)
-		return -EFAULT;
-	if (pdev->error_status)
-		return -pdev->error_status; /* Something happened, report what. */
-
-	/* In case we're doing partial reads, we don't have to wait for a frame */
-	if (pdev->image_read_pos == 0) {
-		/* Do wait queueing according to the (doc)book */
-		add_wait_queue(&pdev->frameq, &wait);
-		while (pdev->full_frames == NULL) {
-			/* Check for unplugged/etc. here */
-			if (pdev->error_status) {
-				remove_wait_queue(&pdev->frameq, &wait);
-				set_current_state(TASK_RUNNING);
-				return -pdev->error_status ;
-			}
-	                if (noblock) {
-	                	remove_wait_queue(&pdev->frameq, &wait);
-	                	set_current_state(TASK_RUNNING);
-	                	return -EWOULDBLOCK;
-	                }
-	                if (signal_pending(current)) {
-	                	remove_wait_queue(&pdev->frameq, &wait);
-	                	set_current_state(TASK_RUNNING);
-	                	return -ERESTARTSYS;
-	                }
-	                schedule();
-	               	set_current_state(TASK_INTERRUPTIBLE);
-		}
-		remove_wait_queue(&pdev->frameq, &wait);
-		set_current_state(TASK_RUNNING);
-                                                                                                                                                                                
-		/* Decompress and release frame */
-		if (pwc_handle_frame(pdev))
-			return -EFAULT;
-	}
-
-	Trace(TRACE_READ, "Copying data to user space.\n");
-	if (pdev->vpalette == VIDEO_PALETTE_RAW)
-		bytes_to_read = pdev->frame_size;
-	else
- 		bytes_to_read = pdev->view.size;
-
-	/* copy bytes to user space; we allow for partial reads */
-	if (count + pdev->image_read_pos > bytes_to_read)
-		count = bytes_to_read - pdev->image_read_pos;
-	if (copy_to_user(buf, pdev->image_ptr[pdev->fill_image] + pdev->image_read_pos, count))
-		return -EFAULT;
-	pdev->image_read_pos += count;
-	if (pdev->image_read_pos >= bytes_to_read) { /* All data has been read */
-		pdev->image_read_pos = 0;
-		pwc_next_image(pdev);
-	}
-	return count;
-}
-
-static unsigned int pwc_video_poll(struct file *file, poll_table *wait)
-{
-	struct video_device *vdev = file->private_data;
-	struct pwc_device *pdev;
-
-	if (vdev == NULL)
-		return -EFAULT;
-	pdev = vdev->priv;
-	if (pdev == NULL)
-		return -EFAULT;
-
-	poll_wait(file, &pdev->frameq, wait);
-	if (pdev->error_status)
-		return POLLERR;
-	if (pdev->full_frames != NULL) /* we have frames waiting */
-		return (POLLIN | POLLRDNORM);
-
-	return 0;
-}
-
-static int pwc_video_do_ioctl(struct inode *inode, struct file *file,
-			      unsigned int cmd, void *arg)
-{
-	struct video_device *vdev = file->private_data;
-	struct pwc_device *pdev;
-	DECLARE_WAITQUEUE(wait, current);
-
-	if (vdev == NULL)
-		return -EFAULT;
-	pdev = vdev->priv;
-	if (pdev == NULL)
-		return -EFAULT;
-
-	switch (cmd) {
-		/* Query cabapilities */
-		case VIDIOCGCAP:
-		{
-			struct video_capability *caps = arg;
-
-			strcpy(caps->name, vdev->name);
-			caps->type = VID_TYPE_CAPTURE;
-			caps->channels = 1;
-			caps->audios = 1;
-			caps->minwidth  = pdev->view_min.x;
-			caps->minheight = pdev->view_min.y;
-			caps->maxwidth  = pdev->view_max.x;
-			caps->maxheight = pdev->view_max.y;
-			break;
-		}
-
-		/* Channel functions (simulate 1 channel) */
-		case VIDIOCGCHAN:
-		{
-			struct video_channel *v = arg;
-
-			if (v->channel != 0)
-				return -EINVAL;
-			v->flags = 0;
-			v->tuners = 0;
-			v->type = VIDEO_TYPE_CAMERA;
-			strcpy(v->name, "Webcam");
-			return 0;
-		}
-
-		case VIDIOCSCHAN:
-		{
-			/* The spec says the argument is an integer, but
-			   the bttv driver uses a video_channel arg, which
-			   makes sense becasue it also has the norm flag.
-			 */
-			struct video_channel *v = arg;
-			if (v->channel != 0)
-				return -EINVAL;
-			return 0;
-		}
-
-
-		/* Picture functions; contrast etc. */
-		case VIDIOCGPICT:
-		{
-			struct video_picture *p = arg;
-			int val;
-
-			val = pwc_get_brightness(pdev);
-			if (val >= 0)
-				p->brightness = val;
-			else
-				p->brightness = 0xffff;
-			val = pwc_get_contrast(pdev);
-			if (val >= 0)
-				p->contrast = val;
-			else
-				p->contrast = 0xffff;
-			/* Gamma, Whiteness, what's the difference? :) */
-			val = pwc_get_gamma(pdev);
-			if (val >= 0)
-				p->whiteness = val;
-			else
-				p->whiteness = 0xffff;
-			val = pwc_get_saturation(pdev);
-			if (val >= 0)
-				p->colour = val;
-			else
-				p->colour = 0xffff;
-			p->depth = 24;
-			p->palette = pdev->vpalette;
-			p->hue = 0xFFFF; /* N/A */
-			break;
-		}
-
-		case VIDIOCSPICT:
-		{
-			struct video_picture *p = arg;
-			/*
-			 *	FIXME:	Suppose we are mid read
-			        ANSWER: No problem: the firmware of the camera
-			                can handle brightness/contrast/etc
-			                changes at _any_ time, and the palette
-			                is used exactly once in the uncompress
-			                routine.
-			 */
-			pwc_set_brightness(pdev, p->brightness);
-			pwc_set_contrast(pdev, p->contrast);
-			pwc_set_gamma(pdev, p->whiteness);
-			pwc_set_saturation(pdev, p->colour);
-			if (p->palette && p->palette != pdev->vpalette) {
-				switch (p->palette) {
-					case VIDEO_PALETTE_YUV420P:
-					case VIDEO_PALETTE_RAW:
-						pdev->vpalette = p->palette;
-						return pwc_try_video_mode(pdev, pdev->image.x, pdev->image.y, pdev->vframes, pdev->vcompression, pdev->vsnapshot);
-						break;
-					default:
-						return -EINVAL;
-						break;
-				}
-			}
-			break;
-		}
-
-		/* Window/size parameters */		
-		case VIDIOCGWIN:
-		{
-			struct video_window *vw = arg;
-			
-			vw->x = 0;
-			vw->y = 0;
-			vw->width = pdev->view.x;
-			vw->height = pdev->view.y;
-			vw->chromakey = 0;
-			vw->flags = (pdev->vframes << PWC_FPS_SHIFT) | 
-			           (pdev->vsnapshot ? PWC_FPS_SNAPSHOT : 0);
-			break;
-		}
-		
-		case VIDIOCSWIN:
-		{
-			struct video_window *vw = arg;
-			int fps, snapshot, ret;
-
-			fps = (vw->flags & PWC_FPS_FRMASK) >> PWC_FPS_SHIFT;
-			snapshot = vw->flags & PWC_FPS_SNAPSHOT;
-			if (fps == 0)
-				fps = pdev->vframes;
-			if (pdev->view.x == vw->width && pdev->view.y && fps == pdev->vframes && snapshot == pdev->vsnapshot)
-				return 0;
-			ret = pwc_try_video_mode(pdev, vw->width, vw->height, fps, pdev->vcompression, snapshot);
-			if (ret)
-				return ret;
-			break;		
-		}
-		
-		/* We don't have overlay support (yet) */
-		case VIDIOCGFBUF:
-		{
-			struct video_buffer *vb = arg;
-
-			memset(vb,0,sizeof(*vb));
-			break;
-		}
-
-		/* mmap() functions */
-		case VIDIOCGMBUF:
-		{
-			/* Tell the user program how much memory is needed for a mmap() */
-			struct video_mbuf *vm = arg;
-			int i;
-
-			memset(vm, 0, sizeof(*vm));
-			vm->size = default_mbufs * pdev->len_per_image;
-			vm->frames = default_mbufs; /* double buffering should be enough for most applications */
-			for (i = 0; i < default_mbufs; i++)
-				vm->offsets[i] = i * pdev->len_per_image;
-			break;
-		}
-
-		case VIDIOCMCAPTURE:
-		{
-			/* Start capture into a given image buffer (called 'frame' in video_mmap structure) */
-			struct video_mmap *vm = arg;
-
-			Trace(TRACE_READ, "VIDIOCMCAPTURE: %dx%d, frame %d, format %d\n", vm->width, vm->height, vm->frame, vm->format);
-			if (vm->frame < 0 || vm->frame >= default_mbufs)
-				return -EINVAL;
-
-			/* xawtv is nasty. It probes the available palettes
-			   by setting a very small image size and trying
-			   various palettes... The driver doesn't support
-			   such small images, so I'm working around it.
-			 */
-			if (vm->format)
-			{
-				switch (vm->format)
-				{
-					case VIDEO_PALETTE_YUV420P:
-					case VIDEO_PALETTE_RAW:
-						break;
-					default:
-						return -EINVAL;
-						break;
-				}
-			}
-
-			if ((vm->width != pdev->view.x || vm->height != pdev->view.y) &&
-			    (vm->width >= pdev->view_min.x && vm->height >= pdev->view_min.y)) {
-				int ret;
-
-				Trace(TRACE_OPEN, "VIDIOCMCAPTURE: changing size to please xawtv :-(.\n");
-				ret = pwc_try_video_mode(pdev, vm->width, vm->height, pdev->vframes, pdev->vcompression, pdev->vsnapshot);
-				if (ret)
-					return ret;
-			} /* ... size mismatch */
-
-			/* FIXME: should we lock here? */
-			if (pdev->image_used[vm->frame])
-				return -EBUSY;	/* buffer wasn't available. Bummer */
-			pdev->image_used[vm->frame] = 1;
-
-			/* Okay, we're done here. In the SYNC call we wait until a 
-			   frame comes available, then expand image into the given 
-			   buffer.
-			   In contrast to the CPiA cam the Philips cams deliver a
-			   constant stream, almost like a grabber card. Also,
-			   we have separate buffers for the rawdata and the image,
-			   meaning we can nearly always expand into the requested buffer.
-			 */
-			Trace(TRACE_READ, "VIDIOCMCAPTURE done.\n");
-			break;
-		}
-
-		case VIDIOCSYNC:
-		{
-			/* The doc says: "Whenever a buffer is used it should
-			   call VIDIOCSYNC to free this frame up and continue."
-			   
-			   The only odd thing about this whole procedure is 
-			   that MCAPTURE flags the buffer as "in use", and
-			   SYNC immediately unmarks it, while it isn't 
-			   after SYNC that you know that the buffer actually
-			   got filled! So you better not start a CAPTURE in
-			   the same frame immediately (use double buffering). 
-			   This is not a problem for this cam, since it has 
-			   extra intermediate buffers, but a hardware 
-			   grabber card will then overwrite the buffer 
-			   you're working on.
-			 */
-			int *mbuf = arg;
-			int ret;
-
-			Trace(TRACE_READ, "VIDIOCSYNC called (%d).\n", *mbuf);
-
-			/* bounds check */
-			if (*mbuf < 0 || *mbuf >= default_mbufs)
-				return -EINVAL;
-			/* check if this buffer was requested anyway */
-			if (pdev->image_used[*mbuf] == 0)
-				return -EINVAL;
-
-			/* Add ourselves to the frame wait-queue.
-			   
-			   FIXME: needs auditing for safety.
-			   QUESTION: In what respect? I think that using the
-			             frameq is safe now.
-			 */
-			add_wait_queue(&pdev->frameq, &wait);
-			while (pdev->full_frames == NULL) {
-				if (pdev->error_status) {
-					remove_wait_queue(&pdev->frameq, &wait);
-					set_current_state(TASK_RUNNING);
-					return -pdev->error_status;
-				}
-			
-	                	if (signal_pending(current)) {
-	                		remove_wait_queue(&pdev->frameq, &wait);
-		                	set_current_state(TASK_RUNNING);
-		                	return -ERESTARTSYS;
-	        	        }
-	                	schedule();
-		                set_current_state(TASK_INTERRUPTIBLE);
-			}
-			remove_wait_queue(&pdev->frameq, &wait);
-			set_current_state(TASK_RUNNING);
-				
-			/* The frame is ready. Expand in the image buffer 
-			   requested by the user. I don't care if you 
-			   mmap() 5 buffers and request data in this order: 
-			   buffer 4 2 3 0 1 2 3 0 4 3 1 . . .
-			   Grabber hardware may not be so forgiving.
-			 */
-			Trace(TRACE_READ, "VIDIOCSYNC: frame ready.\n");
-			pdev->fill_image = *mbuf; /* tell in which buffer we want the image to be expanded */
-			/* Decompress, etc */
-			ret = pwc_handle_frame(pdev);
-			pdev->image_used[*mbuf] = 0;
-			if (ret)
-				return -EFAULT;
-			break;
-		}
-		
-		case VIDIOCGAUDIO:
-		{
-			struct video_audio *v = arg;
-			
-			strcpy(v->name, "Microphone");
-			v->audio = -1; /* unknown audio minor */
-			v->flags = 0;
-			v->mode = VIDEO_SOUND_MONO;
-			v->volume = 0;
-			v->bass = 0;
-			v->treble = 0;
-			v->balance = 0x8000;
-			v->step = 1;
-			break;	
-		}
-		
-		case VIDIOCSAUDIO:
-		{
-			/* Dummy: nothing can be set */
-			break;
-		}
-		
-		case VIDIOCGUNIT:
-		{
-			struct video_unit *vu = arg;
-			
-			vu->video = pdev->vdev->minor & 0x3F;
-			vu->audio = -1; /* not known yet */
-			vu->vbi = -1;
-			vu->radio = -1;
-			vu->teletext = -1;
-			break;
-		}
-		default:
-			return pwc_ioctl(pdev, cmd, arg);
-	} /* ..switch */
-	return 0;
-}	
-
-static int pwc_video_ioctl(struct inode *inode, struct file *file,
-			   unsigned int cmd, unsigned long arg)
-{
-	return video_usercopy(inode, file, cmd, arg, pwc_video_do_ioctl);
-}
-
-
-static int pwc_video_mmap(struct file *file, struct vm_area_struct *vma)
-{
-	struct video_device *vdev = file->private_data;
-	struct pwc_device *pdev;
-	unsigned long start = vma->vm_start;
-	unsigned long size  = vma->vm_end-vma->vm_start;
-	unsigned long page, pos;
-	
-	Trace(TRACE_MEMORY, "mmap(0x%p, 0x%lx, %lu) called.\n", vdev, start, size);
-	pdev = vdev->priv;
-
-	pos = (unsigned long)pdev->image_data;
-	while (size > 0) {
-		page = kvirt_to_pa(pos);
-		if (remap_page_range(vma, start, page, PAGE_SIZE, PAGE_SHARED))
-			return -EAGAIN;
-
-		start += PAGE_SIZE;
-		pos += PAGE_SIZE;
-		if (size > PAGE_SIZE)
-			size -= PAGE_SIZE;
-		else
-			size = 0;
-	}
-
-	return 0;
-}
-
-/***************************************************************************/
-/* USB functions */
-
-/* This function gets called when a new device is plugged in or the usb core
- * is loaded.
- */
-
-static int usb_pwc_probe(struct usb_interface *intf, const struct usb_device_id *id)
-{
-	struct usb_device *udev = interface_to_usbdev(intf);
-	struct pwc_device *pdev = NULL;
-	int vendor_id, product_id, type_id;
-	int i, hint;
-	int features = 0;
-	int video_nr = -1; /* default: use next available device */
-	char serial_number[30], *name;
-
-	/* Check if we can handle this device */
-	Trace(TRACE_PROBE, "probe() called [%04X %04X], if %d\n", 
-		udev->descriptor.idVendor, udev->descriptor.idProduct, 
-		intf->altsetting->desc.bInterfaceNumber);
-
-	/* the interfaces are probed one by one. We are only interested in the
-	   video interface (0) now.
-	   Interface 1 is the Audio Control, and interface 2 Audio itself.
-	 */
-	if (intf->altsetting->desc.bInterfaceNumber > 0)
-		return -ENODEV;
-
-	vendor_id = udev->descriptor.idVendor;
-	product_id = udev->descriptor.idProduct;
-
-	if (vendor_id == 0x0471) {
-		switch (product_id) {
-		case 0x0302:
-			Info("Philips PCA645VC USB webcam detected.\n");
-			name = "Philips 645 webcam";
-			type_id = 645;
-			break;
-		case 0x0303:
-			Info("Philips PCA646VC USB webcam detected.\n");
-			name = "Philips 646 webcam";
-			type_id = 646;
-			break;
-		case 0x0304:
-			Info("Askey VC010 type 2 USB webcam detected.\n");
-			name = "Askey VC010 webcam";
-			type_id = 646;
-			break;
-		case 0x0307:
-			Info("Philips PCVC675K (Vesta) USB webcam detected.\n");
-			name = "Philips 675 webcam";
-			type_id = 675;
-			break;
-		case 0x0308:
-			Info("Philips PCVC680K (Vesta Pro) USB webcam detected.\n");
-			name = "Philips 680 webcam";
-			type_id = 680;
-			break;
-		case 0x030C:
-			Info("Philips PCVC690K (Vesta Pro Scan) USB webcam detected.\n");
-			name = "Philips 690 webcam";
-			type_id = 690;
-			break;
-		case 0x0310:
-			Info("Philips PCVC730K (ToUCam Fun)/PCVC830 (ToUCam II) USB webcam detected.\n");
-			name = "Philips 730 webcam";
-			type_id = 730;
-			break;
-		case 0x0311:
-			Info("Philips PCVC740K (ToUCam Pro)/PCVC840 (ToUCam II) USB webcam detected.\n");
-			name = "Philips 740 webcam";
-			type_id = 740;
-			break;
-		case 0x0312:
-			Info("Philips PCVC750K (ToUCam Pro Scan) USB webcam detected.\n");
-			name = "Philips 750 webcam";
-			type_id = 750;
-			break;
-		case 0x0313:
-			Info("Philips PCVC720K/40 (ToUCam XS) USB webcam detected.\n");
-			name = "Philips 720K/40 webcam";
-			type_id = 720;
-			break;
-		default:
-			return -ENODEV;
-			break;
-		}
-	}
-	else if (vendor_id == 0x069A) {
-		switch(product_id) {
-		case 0x0001:
-			Info("Askey VC010 type 1 USB webcam detected.\n");
-			name = "Askey VC010 webcam";
-			type_id = 645;
-			break;
-		default:
-			return -ENODEV;
-			break;
-		}
-	}
-	else if (vendor_id == 0x046d) {
-		switch(product_id) {
-		case 0x08b0:
-			Info("Logitech QuickCam Pro 3000 USB webcam detected.\n");
-			name = "Logitech QuickCam Pro 3000";
-			type_id = 740; /* CCD sensor */
-			break;
-		case 0x08b1:
-			Info("Logitech QuickCam Notebook Pro USB webcam detected.\n");
-			name = "Logitech QuickCam Notebook Pro";
-			type_id = 740; /* CCD sensor */
-			break;
-		case 0x08b2:
-			Info("Logitech QuickCam 4000 Pro USB webcam detected.\n");
-			name = "Logitech QuickCam Pro 4000";
-			type_id = 740; /* CCD sensor */
-			break;
-		case 0x08b3:
-			Info("Logitech QuickCam Zoom USB webcam detected.\n");
-			name = "Logitech QuickCam Zoom";
-			type_id = 740; /* CCD sensor */
-			break;
-		case 0x08B4:
-			Info("Logitech QuickCam Zoom (new model) USB webcam detected.\n");
-			name = "Logitech QuickCam Zoom";
-			type_id = 740; /* CCD sensor */
-			break;
-		case 0x08b5:
-			Info("Logitech QuickCam Orbit/Sphere USB webcam detected.\n");
-			name = "Logitech QuickCam Orbit";
-			type_id = 740; /* CCD sensor */
-			features |= FEATURE_MOTOR_PANTILT;
-			break;
-		case 0x08b6:
-		case 0x08b7:
-		case 0x08b8:
-			Info("Logitech QuickCam detected (reserved ID).\n");
-			name = "Logitech QuickCam (res.)";
-			type_id = 730; /* Assuming CMOS */
-			break;
-        	default:
-			return -ENODEV;
-        		break;
-        	}
-        }
-	else if (vendor_id == 0x055d) {
-		/* I don't know the difference between the C10 and the C30;
-		   I suppose the difference is the sensor, but both cameras
-		   work equally well with a type_id of 675
-		 */
-		switch(product_id) {
-		case 0x9000:
-			Info("Samsung MPC-C10 USB webcam detected.\n");
-			name = "Samsung MPC-C10";
-			type_id = 675;
-			break;
-		case 0x9001:
-			Info("Samsung MPC-C30 USB webcam detected.\n");
-			name = "Samsung MPC-C30";
-			type_id = 675;
-			break;
-		default:
-			return -ENODEV;
-			break;
-		}
-	}
-	else if (vendor_id == 0x041e) {
-		switch(product_id) {
-		case 0x400c:
-			Info("Creative Labs Webcam 5 detected.\n");
-			name = "Creative Labs Webcam 5";
-			type_id = 730;
-			break;
-		case 0x4011:
-			Info("Creative Labs Webcam Pro Ex detected.\n");
-			name = "Creative Labs Webcam Pro Ex";
-			type_id = 740;
-			break;
-		default:
-			return -ENODEV;
-			break;
-		}
-	}
-	else if (vendor_id == 0x04cc) {
-		switch(product_id) {
-		case 0x8116:
-			Info("Sotec Afina Eye USB webcam detected.\n");
-			name = "Sotec Afina Eye";
-			type_id = 730;
-			break;
-		default:
-			return -ENODEV;
-			break;
-		}
-	}
-	else if (vendor_id == 0x06be) {
-		switch(product_id) {
-		case 0x8116:
-			/* Basicly the same as the Sotec Afina Eye */                
-			Info("AME CU-001 USB webcam detected.\n");
-			name = "AME CU-001";
-			type_id = 730;
-			break;
-		default:
-			return -ENODEV;
-			break;
-		}
-	}
-	else if (vendor_id == 0x06be) {
-		switch(product_id) {
-		case 0x8116:
-			/* This is essentially the same cam as the Sotec Afina Eye */
-			Info("AME Co. Afina Eye USB webcam detected.\n");
-			name = "AME Co. Afina Eye";
-			type_id = 750;
-			break;
-		default:
-			return -ENODEV;
-			break;
-		}
-	
-	}
-	else if (vendor_id == 0x0d81) {
-		switch(product_id) {
-		case 0x1900:
-			Info("Visionite VCS-UC300 USB webcam detected.\n");
-			name = "Visionite VCS-UC300";
-			type_id = 740; /* CCD sensor */
-			break;
-		case 0x1910:
-			Info("Visionite VCS-UM100 USB webcam detected.\n");
-			name = "Visionite VCS-UM100";
-			type_id = 730; /* CMOS sensor */
-			break;
-		default:
-			return -ENODEV;
-			break;
-		}
-	}
-	else 
-		return -ENODEV; /* Not any of the know types; but the list keeps growing. */
-
-	memset(serial_number, 0, 30);
-	usb_string(udev, udev->descriptor.iSerialNumber, serial_number, 29);
-	Trace(TRACE_PROBE, "Device serial number is %s\n", serial_number);
-
-	if (udev->descriptor.bNumConfigurations > 1)
-		Info("Warning: more than 1 configuration available.\n");
-
-	/* Allocate structure, initialize pointers, mutexes, etc. and link it to the usb_device */
-	pdev = kmalloc(sizeof(struct pwc_device), GFP_KERNEL);
-	if (pdev == NULL) {
-		Err("Oops, could not allocate memory for pwc_device.\n");
-		return -ENOMEM;
-	}
-	memset(pdev, 0, sizeof(struct pwc_device));
-	pdev->type = type_id;
-	pdev->vsize = default_size;
-	pdev->vframes = default_fps;
-	strcpy(pdev->serial, serial_number);
-	pdev->features = features;
-	if (vendor_id == 0x046D && product_id == 0x08B5)
-	{
-		/* Logitech QuickCam Orbit
-	           The ranges have been determined experimentally; they may differ from cam to cam.
-	           Also, the exact ranges left-right and up-down are different for my cam
-	          */
-		pdev->angle_range.pan_min  = -7000;
-		pdev->angle_range.pan_max  =  7000;
-		pdev->angle_range.tilt_min = -3000;
-		pdev->angle_range.tilt_max =  2500;
-	}
-
-	init_MUTEX(&pdev->modlock);
-	pdev->ptrlock = SPIN_LOCK_UNLOCKED;
-
-	pdev->udev = udev;
-	init_waitqueue_head(&pdev->frameq);
-	pdev->vcompression = pwc_preferred_compression;
-
-	/* Allocate video_device structure */
-	pdev->vdev = video_device_alloc();
-	if (pdev->vdev == 0)
-	{
-		Err("Err, cannot allocate video_device struture. Failing probe.");
-		kfree(pdev);
-		return -ENOMEM;
-	}
-	memcpy(pdev->vdev, &pwc_template, sizeof(pwc_template));
-	strcpy(pdev->vdev->name, name);
-	pdev->vdev->owner = THIS_MODULE;
-	video_set_drvdata(pdev->vdev, pdev);
-
-	pdev->release = udev->descriptor.bcdDevice;
-	Trace(TRACE_PROBE, "Release: %04x\n", pdev->release);
-
-	/* Now search device_hint[] table for a match, so we can hint a node number. */
-	for (hint = 0; hint < MAX_DEV_HINTS; hint++) {
-		if (((device_hint[hint].type == -1) || (device_hint[hint].type == pdev->type)) &&
-		     (device_hint[hint].pdev == NULL)) {
-			/* so far, so good... try serial number */
-			if ((device_hint[hint].serial_number[0] == '*') || !strcmp(device_hint[hint].serial_number, serial_number)) {
-			    	/* match! */
-			    	video_nr = device_hint[hint].device_node;
-			    	Trace(TRACE_PROBE, "Found hint, will try to register as /dev/video%d\n", video_nr);
-			    	break;
-			}
-		}
-	}
-
-	pdev->vdev->release = video_device_release;
-	i = video_register_device(pdev->vdev, VFL_TYPE_GRABBER, video_nr);
-	if (i < 0) {
-		Err("Failed to register as video device (%d).\n", i);
-		video_device_release(pdev->vdev); /* Drip... drip... drip... */
-		kfree(pdev); /* Oops, no memory leaks please */
-		return -EIO;
-	}
-	else {
-		Info("Registered as /dev/video%d.\n", pdev->vdev->minor & 0x3F);
-	}
-
-	/* occupy slot */
-	if (hint < MAX_DEV_HINTS) 
-		device_hint[hint].pdev = pdev;
-
-	Trace(TRACE_PROBE, "probe() function returning struct at 0x%p.\n", pdev);
-	usb_set_intfdata (intf, pdev);
-	return 0;
-}
-
-/* The user janked out the cable... */
-static void usb_pwc_disconnect(struct usb_interface *intf)
-{
-	struct pwc_device *pdev;
-	int hint;
-
-	lock_kernel();
-	pdev = usb_get_intfdata (intf);
-	usb_set_intfdata (intf, NULL);
-	if (pdev == NULL) {
-		Err("pwc_disconnect() Called without private pointer.\n");
-		goto disconnect_out;
-	}
-	if (pdev->udev == NULL) {
-		Err("pwc_disconnect() already called for %p\n", pdev);
-		goto disconnect_out;
-	}
-	if (pdev->udev != interface_to_usbdev(intf)) {
-		Err("pwc_disconnect() Woops: pointer mismatch udev/pdev.\n");
-		goto disconnect_out;
-	}
-#ifdef PWC_MAGIC	
-	if (pdev->magic != PWC_MAGIC) {
-		Err("pwc_disconnect() Magic number failed. Consult your scrolls and try again.\n");
-		goto disconnect_out;
-	}
-#endif
-	
-	/* We got unplugged; this is signalled by an EPIPE error code */
-	if (pdev->vopen) {
-		Info("Disconnected while webcam is in use!\n");
-		pdev->error_status = EPIPE;
-	}
-
-	/* Alert waiting processes */
-	wake_up_interruptible(&pdev->frameq);
-	/* Wait until device is closed */
-	while (pdev->vopen)
-		schedule();
-	/* Device is now closed, so we can safely unregister it */
-	Trace(TRACE_PROBE, "Unregistering video device in disconnect().\n");
-	video_unregister_device(pdev->vdev);
-
-	/* Free memory (don't set pdev to 0 just yet) */
-	kfree(pdev);
-
-disconnect_out:
-	/* search device_hint[] table if we occupy a slot, by any chance */
-	for (hint = 0; hint < MAX_DEV_HINTS; hint++)
-		if (device_hint[hint].pdev == pdev)
-			device_hint[hint].pdev = NULL;
-
-	unlock_kernel();
-}
-
-
-/* *grunt* We have to do atoi ourselves :-( */
-static int pwc_atoi(const char *s)
-{
-	int k = 0;
-
-	k = 0;
-	while (*s != '\0' && *s >= '0' && *s <= '9') {
-		k = 10 * k + (*s - '0');
-		s++;
-	}
-	return k;
-}
-
-
-/* 
- * Initialization code & module stuff 
- */
-
-static char *size = NULL;
-static int fps = 0;
-static int fbufs = 0;
-static int mbufs = 0;
-static int trace = -1;
-static int compression = -1;
-static int leds[2] = { -1, -1 };
-static char *dev_hint[MAX_DEV_HINTS] = { };
-
-MODULE_PARM(size, "s");
-MODULE_PARM_DESC(size, "Initial image size. One of sqcif, qsif, qcif, sif, cif, vga");
-MODULE_PARM(fps, "i");
-MODULE_PARM_DESC(fps, "Initial frames per second. Varies with model, useful range 5-30");
-MODULE_PARM(fbufs, "i");
-MODULE_PARM_DESC(fbufs, "Number of internal frame buffers to reserve");
-MODULE_PARM(mbufs, "i");
-MODULE_PARM_DESC(mbufs, "Number of external (mmap()ed) image buffers");
-MODULE_PARM(trace, "i");
-MODULE_PARM_DESC(trace, "For debugging purposes");
-MODULE_PARM(power_save, "i");
-MODULE_PARM_DESC(power_save, "Turn power save feature in camera on or off");
-MODULE_PARM(compression, "i");
-MODULE_PARM_DESC(compression, "Preferred compression quality. Range 0 (uncompressed) to 3 (high compression)");
-MODULE_PARM(leds, "2i");
-MODULE_PARM_DESC(leds, "LED on,off time in milliseconds");
-MODULE_PARM(dev_hint, "0-20s");
-MODULE_PARM_DESC(dev_hint, "Device node hints");
-
-MODULE_DESCRIPTION("Philips & OEM USB webcam driver");
-MODULE_AUTHOR("Nemosoft Unv. <webcam@smcc.demon.nl>");
-MODULE_LICENSE("GPL");
-
-static int __init usb_pwc_init(void)
-{
-	int i, sz;
-	char *sizenames[PSZ_MAX] = { "sqcif", "qsif", "qcif", "sif", "cif", "vga" };
-
-	Info("Philips webcam module version " PWC_VERSION " loaded.\n");
-	Info("Supports Philips PCA645/646, PCVC675/680/690, PCVC720[40]/730/740/750 & PCVC830/840.\n");
-	Info("Also supports the Askey VC010, various Logitech Quickcams, Samsung MPC-C10 and MPC-C30,\n");
-	Info("the Creative WebCam 5 & Pro Ex, SOTEC Afina Eye and Visionite VCS-UC300 and VCS-UM100.\n");
-
-	if (fps) {
-		if (fps < 4 || fps > 30) {
-			Err("Framerate out of bounds (4-30).\n");
-			return -EINVAL;
-		}
-		default_fps = fps;
-		Info("Default framerate set to %d.\n", default_fps);
-	}
-
-	if (size) {
-		/* string; try matching with array */
-		for (sz = 0; sz < PSZ_MAX; sz++) {
-			if (!strcmp(sizenames[sz], size)) { /* Found! */
-				default_size = sz;
-				break;
-			}
-		}
-		if (sz == PSZ_MAX) {
-			Err("Size not recognized; try size=[sqcif | qsif | qcif | sif | cif | vga].\n");
-			return -EINVAL;
-		}
-		Info("Default image size set to %s [%dx%d].\n", sizenames[default_size], pwc_image_sizes[default_size].x, pwc_image_sizes[default_size].y);
-	}
-	if (mbufs) {
-		if (mbufs < 1 || mbufs > MAX_IMAGES) {
-			Err("Illegal number of mmap() buffers; use a number between 1 and %d.\n", MAX_IMAGES);
-			return -EINVAL;
-		}
-		default_mbufs = mbufs;
-		Info("Number of image buffers set to %d.\n", default_mbufs);
-	}
-	if (fbufs) {
-		if (fbufs < 2 || fbufs > MAX_FRAMES) {
-			Err("Illegal number of frame buffers; use a number between 2 and %d.\n", MAX_FRAMES);
-			return -EINVAL;
-		}
-		default_fbufs = fbufs;
-		Info("Number of frame buffers set to %d.\n", default_fbufs);
-	}
-	if (trace >= 0) {
-		Info("Trace options: 0x%04x\n", trace);
-		pwc_trace = trace;
-	}
-	if (compression >= 0) {
-		if (compression > 3) {
-			Err("Invalid compression setting; use a number between 0 (uncompressed) and 3 (high).\n");
-			return -EINVAL;
-		}
-		pwc_preferred_compression = compression;
-		Info("Preferred compression set to %d.\n", pwc_preferred_compression);
-	}
-	if (power_save)
-		Info("Enabling power save on open/close.\n");
-	if (leds[0] >= 0)
-		led_on = leds[0];
-	if (leds[1] >= 0)
-		led_off = leds[1];
-
-	/* Big device node whoopla. Basicly, it allows you to assign a
-	   device node (/dev/videoX) to a camera, based on its type
-	   & serial number. The format is [type[.serialnumber]:]node.
-
-	   Any camera that isn't matched by these rules gets the next
-	   available free device node.
-	 */
-	for (i = 0; i < MAX_DEV_HINTS; i++) {
-		char *s, *colon, *dot;
-
-		/* This loop also initializes the array */
-		device_hint[i].pdev = NULL;
-		s = dev_hint[i];
-		if (s != NULL && *s != '\0') {
-			device_hint[i].type = -1; /* wildcard */
-			strcpy(device_hint[i].serial_number, "*");
-
-			/* parse string: chop at ':' & '/' */
-			colon = dot = s;
-			while (*colon != '\0' && *colon != ':')
-				colon++;
-			while (*dot != '\0' && *dot != '.')
-				dot++;
-			/* Few sanity checks */
-			if (*dot != '\0' && dot > colon) {
-				Err("Malformed camera hint: the colon must be after the dot.\n");
-				return -EINVAL;
-			}
-
-			if (*colon == '\0') {
-				/* No colon */
-				if (*dot != '\0') {
-					Err("Malformed camera hint: no colon + device node given.\n");
-					return -EINVAL;
-				}
-				else {
-					/* No type or serial number specified, just a number. */
-					device_hint[i].device_node = pwc_atoi(s);
-				}
-			}
-			else {
-				/* There's a colon, so we have at least a type and a device node */
-				device_hint[i].type = pwc_atoi(s);
-				device_hint[i].device_node = pwc_atoi(colon + 1);
-				if (*dot != '\0') {
-					/* There's a serial number as well */
-					int k;
-					
-					dot++;
-					k = 0;
-					while (*dot != ':' && k < 29) {
-						device_hint[i].serial_number[k++] = *dot;
-						dot++;
-					}
-					device_hint[i].serial_number[k] = '\0';
-				}
-			}
-#if PWC_DEBUG		
-			Debug("device_hint[%d]:\n", i);
-			Debug("  type    : %d\n", device_hint[i].type);
-			Debug("  serial# : %s\n", device_hint[i].serial_number);
-			Debug("  node    : %d\n", device_hint[i].device_node);
-#endif			
-		}
-		else
-			device_hint[i].type = 0; /* not filled */
-	} /* ..for MAX_DEV_HINTS */
-
- 	Trace(TRACE_PROBE, "Registering driver at address 0x%p.\n", &pwc_driver);
-	return usb_register(&pwc_driver);
-}
-
-static void __exit usb_pwc_exit(void)
-{
-	Trace(TRACE_MODULE, "Deregistering driver.\n");
-	usb_deregister(&pwc_driver);
-	Info("Philips webcam module removed.\n");
-}
-
-module_init(usb_pwc_init);
-module_exit(usb_pwc_exit);
-
diff -Nru a/drivers/usb/media/pwc-ioctl.h b/drivers/usb/media/pwc-ioctl.h
--- a/drivers/usb/media/pwc-ioctl.h	2004-10-18 14:56:29 -07:00
+++ /dev/null	Wed Dec 31 16:00:00 196900
@@ -1,279 +0,0 @@
-#ifndef PWC_IOCTL_H
-#define PWC_IOCTL_H
-
-/* (C) 2001-2004 Nemosoft Unv.    webcam@smcc.demon.nl
-
-   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 is pwc-ioctl.h belonging to PWC 8.12.1
-   It contains structures and defines to communicate from user space
-   directly to the driver.
- */
-
-/*
-   Changes
-   2001/08/03  Alvarado   Added ioctl constants to access methods for
-                          changing white balance and red/blue gains
-   2002/12/15  G. H. Fernandez-Toribio   VIDIOCGREALSIZE
-   2003/12/13  Nemosft Unv. Some modifications to make interfacing to
-               PWCX easier
- */
-
-/* These are private ioctl() commands, specific for the Philips webcams.
-   They contain functions not found in other webcams, and settings not
-   specified in the Video4Linux API.
-
-   The #define names are built up like follows:
-   VIDIOC		VIDeo IOCtl prefix
-         PWC		Philps WebCam
-            G           optional: Get
-            S           optional: Set
-             ... 	the function
- */
-
-
- /* Enumeration of image sizes */
-#define PSZ_SQCIF	0x00
-#define PSZ_QSIF	0x01
-#define PSZ_QCIF	0x02
-#define PSZ_SIF		0x03
-#define PSZ_CIF		0x04
-#define PSZ_VGA		0x05
-#define PSZ_MAX		6
-
-
-/* The frame rate is encoded in the video_window.flags parameter using
-   the upper 16 bits, since some flags are defined nowadays. The following
-   defines provide a mask and shift to filter out this value.
-
-   In 'Snapshot' mode the camera freezes its automatic exposure and colour
-   balance controls.
- */
-#define PWC_FPS_SHIFT		16
-#define PWC_FPS_MASK		0x00FF0000
-#define PWC_FPS_FRMASK		0x003F0000
-#define PWC_FPS_SNAPSHOT	0x00400000
-
-
-/* structure for transfering x & y coordinates */
-struct pwc_coord
-{
-	int x, y;		/* guess what */
-	int size;		/* size, or offset */
-};
-
-
-/* Used with VIDIOCPWCPROBE */
-struct pwc_probe
-{
-	char name[32];
-	int type;
-};
-
-struct pwc_serial
-{
-	char serial[30];	/* String with serial number. Contains terminating 0 */
-};
-	
-/* pwc_whitebalance.mode values */
-#define PWC_WB_INDOOR		0
-#define PWC_WB_OUTDOOR		1
-#define PWC_WB_FL		2
-#define PWC_WB_MANUAL		3
-#define PWC_WB_AUTO		4
-
-/* Used with VIDIOCPWC[SG]AWB (Auto White Balance). 
-   Set mode to one of the PWC_WB_* values above.
-   *red and *blue are the respective gains of these colour components inside 
-   the camera; range 0..65535
-   When 'mode' == PWC_WB_MANUAL, 'manual_red' and 'manual_blue' are set or read; 
-   otherwise undefined.
-   'read_red' and 'read_blue' are read-only.
-*/   
-struct pwc_whitebalance
-{
-	int mode;
-	int manual_red, manual_blue;	/* R/W */
-	int read_red, read_blue;	/* R/O */
-};
-
-/* 
-   'control_speed' and 'control_delay' are used in automatic whitebalance mode,
-   and tell the camera how fast it should react to changes in lighting, and 
-   with how much delay. Valid values are 0..65535.
-*/
-struct pwc_wb_speed
-{
-	int control_speed;
-	int control_delay;
-
-};
-
-/* Used with VIDIOCPWC[SG]LED */
-struct pwc_leds
-{
-	int led_on;			/* Led on-time; range = 0..25000 */
-	int led_off;			/* Led off-time; range = 0..25000  */
-};
-
-/* Image size (used with GREALSIZE) */
-struct pwc_imagesize
-{
-	int width;
-	int height;
-};
-
-/* Defines and structures for Motorized Pan & Tilt */
-#define PWC_MPT_PAN		0x01
-#define PWC_MPT_TILT		0x02
-#define PWC_MPT_TIMEOUT		0x04 /* for status */
-
-/* Set angles; when absolute != 0, the angle is absolute and the 
-   driver calculates the relative offset for you. This can only
-   be used with VIDIOCPWCSANGLE; VIDIOCPWCGANGLE always returns
-   absolute angles.
- */   
-struct pwc_mpt_angles
-{
-	int absolute;		/* write-only */
-	int pan;		/* degrees * 100 */
-	int tilt;		/* degress * 100 */
-};
-
-/* Range of angles of the camera, both horizontally and vertically.
- */
-struct pwc_mpt_range
-{
-	int pan_min, pan_max;		/* degrees * 100 */
-	int tilt_min, tilt_max;
-};
-
-struct pwc_mpt_status
-{
-	int status;
-	int time_pan;
-	int time_tilt;
-};
-
-
-/* This is used for out-of-kernel decompression. With it, you can get
-   all the necessary information to initialize and use the decompressor
-   routines in standalone applications.
- */   
-struct pwc_video_command
-{
-	int type;		/* camera type (645, 675, 730, etc.) */
-	int release;		/* release number */
-
-        int size;		/* one of PSZ_* */
-        int alternate;
-	int command_len;	/* length of USB video command */
-	unsigned char command_buf[13];	/* Actual USB video command */
-	int bandlength;		/* >0 = compressed */
-	int frame_size;		/* Size of one (un)compressed frame */
-};
-
-/* Flags for PWCX subroutines. Not all modules honour all flags. */
-#define PWCX_FLAG_PLANAR	0x0001
-#define PWCX_FLAG_BAYER		0x0008
-
-
-/* IOCTL definitions */
-
- /* Restore user settings */
-#define VIDIOCPWCRUSER		_IO('v', 192)
- /* Save user settings */
-#define VIDIOCPWCSUSER		_IO('v', 193)
- /* Restore factory settings */
-#define VIDIOCPWCFACTORY	_IO('v', 194)
-
- /* You can manipulate the compression factor. A compression preference of 0
-    means use uncompressed modes when available; 1 is low compression, 2 is
-    medium and 3 is high compression preferred. Of course, the higher the
-    compression, the lower the bandwidth used but more chance of artefacts
-    in the image. The driver automatically chooses a higher compression when
-    the preferred mode is not available.
-  */
- /* Set preferred compression quality (0 = uncompressed, 3 = highest compression) */
-#define VIDIOCPWCSCQUAL		_IOW('v', 195, int)
- /* Get preferred compression quality */
-#define VIDIOCPWCGCQUAL		_IOR('v', 195, int)
-
-
-/* Retrieve serial number of camera */
-#define VIDIOCPWCGSERIAL	_IOR('v', 198, struct pwc_serial)
-
- /* This is a probe function; since so many devices are supported, it
-    becomes difficult to include all the names in programs that want to
-    check for the enhanced Philips stuff. So in stead, try this PROBE;
-    it returns a structure with the original name, and the corresponding
-    Philips type.
-    To use, fill the structure with zeroes, call PROBE and if that succeeds,
-    compare the name with that returned from VIDIOCGCAP; they should be the
-    same. If so, you can be assured it is a Philips (OEM) cam and the type
-    is valid.
- */
-#define VIDIOCPWCPROBE		_IOR('v', 199, struct pwc_probe)
-
- /* Set AGC (Automatic Gain Control); int < 0 = auto, 0..65535 = fixed */
-#define VIDIOCPWCSAGC		_IOW('v', 200, int)
- /* Get AGC; int < 0 = auto; >= 0 = fixed, range 0..65535 */
-#define VIDIOCPWCGAGC		_IOR('v', 200, int)
- /* Set shutter speed; int < 0 = auto; >= 0 = fixed, range 0..65535 */
-#define VIDIOCPWCSSHUTTER	_IOW('v', 201, int)
-
- /* Color compensation (Auto White Balance) */
-#define VIDIOCPWCSAWB           _IOW('v', 202, struct pwc_whitebalance)
-#define VIDIOCPWCGAWB           _IOR('v', 202, struct pwc_whitebalance)
-
- /* Auto WB speed */
-#define VIDIOCPWCSAWBSPEED	_IOW('v', 203, struct pwc_wb_speed)
-#define VIDIOCPWCGAWBSPEED	_IOR('v', 203, struct pwc_wb_speed)
-
- /* LEDs on/off/blink; int range 0..65535 */
-#define VIDIOCPWCSLED           _IOW('v', 205, struct pwc_leds)
-#define VIDIOCPWCGLED           _IOR('v', 205, struct pwc_leds)
-
-  /* Contour (sharpness); int < 0 = auto, 0..65536 = fixed */
-#define VIDIOCPWCSCONTOUR	_IOW('v', 206, int)
-#define VIDIOCPWCGCONTOUR	_IOR('v', 206, int)
-
-  /* Backlight compensation; 0 = off, otherwise on */
-#define VIDIOCPWCSBACKLIGHT	_IOW('v', 207, int)
-#define VIDIOCPWCGBACKLIGHT	_IOR('v', 207, int)
-
-  /* Flickerless mode; = 0 off, otherwise on */
-#define VIDIOCPWCSFLICKER	_IOW('v', 208, int)
-#define VIDIOCPWCGFLICKER	_IOR('v', 208, int)  
-
-  /* Dynamic noise reduction; 0 off, 3 = high noise reduction */
-#define VIDIOCPWCSDYNNOISE	_IOW('v', 209, int)
-#define VIDIOCPWCGDYNNOISE	_IOR('v', 209, int)
-
- /* Real image size as used by the camera; tells you whether or not there's a gray border around the image */
-#define VIDIOCPWCGREALSIZE	_IOR('v', 210, struct pwc_imagesize)
-
- /* Motorized pan & tilt functions */ 
-#define VIDIOCPWCMPTRESET	_IOW('v', 211, int)
-#define VIDIOCPWCMPTGRANGE	_IOR('v', 211, struct pwc_mpt_range)
-#define VIDIOCPWCMPTSANGLE	_IOW('v', 212, struct pwc_mpt_angles)
-#define VIDIOCPWCMPTGANGLE	_IOR('v', 212, struct pwc_mpt_angles)
-#define VIDIOCPWCMPTSTATUS	_IOR('v', 213, struct pwc_mpt_status)
-
- /* Get the USB set-video command; needed for initializing libpwcx */
-#define VIDIOCPWCGVIDCMD	_IOR('v', 215, struct pwc_video_command)
-
-#endif
diff -Nru a/drivers/usb/media/pwc-misc.c b/drivers/usb/media/pwc-misc.c
--- a/drivers/usb/media/pwc-misc.c	2004-10-18 14:56:28 -07:00
+++ /dev/null	Wed Dec 31 16:00:00 196900
@@ -1,146 +0,0 @@
-/* Linux driver for Philips webcam 
-   Various miscellaneous functions and tables.
-   (C) 1999-2003 Nemosoft Unv. (webcam@smcc.demon.nl)
-
-   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
-*/
-
-#include <linux/slab.h>
-
-#include "pwc.h"
-
-struct pwc_coord pwc_image_sizes[PSZ_MAX] =
-{
-	{ 128,  96, 0 },
-	{ 160, 120, 0 },
-	{ 176, 144, 0 },
-	{ 320, 240, 0 },
-	{ 352, 288, 0 },
-	{ 640, 480, 0 },
-};
-
-/* x,y -> PSZ_ */
-int pwc_decode_size(struct pwc_device *pdev, int width, int height)
-{
-	int i, find;
-
-	/* Make sure we don't go beyond our max size.
-           NB: we have different limits for RAW and normal modes. In case
-           you don't have the decompressor loaded or use RAW mode, 
-           the maximum viewable size is smaller.
-        */
-	if (pdev->vpalette == VIDEO_PALETTE_RAW)
-	{
-		if (width > pdev->abs_max.x || height > pdev->abs_max.y)
-		{
-			Debug("VIDEO_PALETTE_RAW: going beyond abs_max.\n");
-                	return -1;
-                }
-	}
-	else
-	{
-		if (width > pdev->view_max.x || height > pdev->view_max.y)
-		{
-			Debug("VIDEO_PALETTE_ not RAW: going beyond view_max.\n");
-			return -1;
-		}
-	}
-
-	/* Find the largest size supported by the camera that fits into the
-	   requested size.
-	 */
-	find = -1;
-	for (i = 0; i < PSZ_MAX; i++) {
-		if (pdev->image_mask & (1 << i)) {
-			if (pwc_image_sizes[i].x <= width && pwc_image_sizes[i].y <= height)
-				find = i;
-		}
-	}
-	return find;
-}
-
-/* initialize variables depending on type and decompressor*/
-void pwc_construct(struct pwc_device *pdev)
-{
-	switch(pdev->type) {
-	case 645:
-	case 646:
-		pdev->view_min.x = 128;
-		pdev->view_min.y =  96;
-		pdev->view_max.x = 352;
-		pdev->view_max.y = 288;
-                pdev->abs_max.x  = 352;
-                pdev->abs_max.y  = 288;
-		pdev->image_mask = 1 << PSZ_SQCIF | 1 << PSZ_QCIF | 1 << PSZ_CIF;
-		pdev->vcinterface = 2;
-		pdev->vendpoint = 4;
-		pdev->frame_header_size = 0;
-		pdev->frame_trailer_size = 0;
-		break;
-	case 675:
-	case 680:
-	case 690:
-		pdev->view_min.x = 128;
-		pdev->view_min.y =  96;
-		/* Anthill bug #38: PWC always reports max size, even without PWCX */
-		if (pdev->decompressor != NULL) {
-			pdev->view_max.x = 640;
-			pdev->view_max.y = 480;
-		}
-		else {
-			pdev->view_max.x = 352;
-			pdev->view_max.y = 288;
-		}
-		pdev->image_mask = 1 << PSZ_SQCIF | 1 << PSZ_QSIF | 1 << PSZ_QCIF | 1 << PSZ_SIF | 1 << PSZ_CIF | 1 << PSZ_VGA;
-                pdev->abs_max.x = 640;
-                pdev->abs_max.y = 480;
-		pdev->vcinterface = 3;
-		pdev->vendpoint = 4;
-		pdev->frame_header_size = 0;
-		pdev->frame_trailer_size = 0;
-		break;
-	case 720:
-	case 730:
-	case 740:
-	case 750:
-		pdev->view_min.x = 160;
-		pdev->view_min.y = 120;
-		/* Anthill bug #38: PWC always reports max size, even without PWCX */
-		if (pdev->decompressor != NULL) {
-			pdev->view_max.x = 640;
-			pdev->view_max.y = 480;
-		}
-		else {
-			/* We use CIF, not SIF since some tools really need CIF. So we cheat a bit. */
-			pdev->view_max.x = 352;
-			pdev->view_max.y = 288;
-		}
-		pdev->image_mask = 1 << PSZ_QSIF | 1 << PSZ_SIF | 1 << PSZ_VGA;
-                pdev->abs_max.x = 640;
-                pdev->abs_max.y = 480;
-		pdev->vcinterface = 3;
-		pdev->vendpoint = 5;
-		pdev->frame_header_size = TOUCAM_HEADER_SIZE;
-		pdev->frame_trailer_size = TOUCAM_TRAILER_SIZE;
-		break;
-	}
-	pdev->vpalette = VIDEO_PALETTE_YUV420P; /* default */
-	pdev->view_min.size = pdev->view_min.x * pdev->view_min.y;
-	pdev->view_max.size = pdev->view_max.x * pdev->view_max.y;
-	/* length of image, in YUV format; always allocate enough memory. */
-	pdev->len_per_image = (pdev->abs_max.x * pdev->abs_max.y * 3) / 2;
-}
-
-
diff -Nru a/drivers/usb/media/pwc-uncompress.c b/drivers/usb/media/pwc-uncompress.c
--- a/drivers/usb/media/pwc-uncompress.c	2004-10-18 14:56:32 -07:00
+++ /dev/null	Wed Dec 31 16:00:00 196900
@@ -1,180 +0,0 @@
-/* Linux driver for Philips webcam
-   Decompression frontend.
-   (C) 1999-2003 Nemosoft Unv. (webcam@smcc.demon.nl)
-
-   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 is where the decompression routines register and unregister 
-   themselves. It also has a decompressor wrapper function.
-*/
-
-#include <asm/current.h>
-#include <asm/types.h>
-// #include <linux/sched.h>
-
-#include "pwc.h"
-#include "pwc-uncompress.h"
-
-
-/* This contains a list of all registered decompressors */
-static LIST_HEAD(pwc_decompressor_list);
-
-/* Should the pwc_decompress structure ever change, we increase the 
-   version number so that we don't get nasty surprises, or can 
-   dynamically adjust our structure.
- */
-const int pwc_decompressor_version = PWC_MAJOR;
-
-/* Add decompressor to list, ignoring duplicates */
-void pwc_register_decompressor(struct pwc_decompressor *pwcd)
-{
-	if (pwc_find_decompressor(pwcd->type) == NULL) {
-		Trace(TRACE_PWCX, "Adding decompressor for model %d.\n", pwcd->type);
-		list_add_tail(&pwcd->pwcd_list, &pwc_decompressor_list);
-	}
-}
-
-/* Remove decompressor from list */
-void pwc_unregister_decompressor(int type)
-{
-	struct pwc_decompressor *find;
-	
-	find = pwc_find_decompressor(type);
-	if (find != NULL) {
-		Trace(TRACE_PWCX, "Removing decompressor for model %d.\n", type);
-		list_del(&find->pwcd_list);
-	}
-}
-
-/* Find decompressor in list */
-struct pwc_decompressor *pwc_find_decompressor(int type)
-{
-	struct list_head *tmp;
-	struct pwc_decompressor *pwcd;
-
-	list_for_each(tmp, &pwc_decompressor_list) {
-		pwcd  = list_entry(tmp, struct pwc_decompressor, pwcd_list);
-		if (pwcd->type == type)
-			return pwcd;
-	}
-	return NULL;
-}
-
-
-
-int pwc_decompress(struct pwc_device *pdev)
-{
-	struct pwc_frame_buf *fbuf;
-	int n, line, col, stride;
-	void *yuv, *image;
-	u16 *src;
-	u16 *dsty, *dstu, *dstv;
-
-	if (pdev == NULL)
-		return -EFAULT;
-#if defined(__KERNEL__) && defined(PWC_MAGIC)
-	if (pdev->magic != PWC_MAGIC) {
-		Err("pwc_decompress(): magic failed.\n");
-		return -EFAULT;
-	}
-#endif
-
-	fbuf = pdev->read_frame;
-	if (fbuf == NULL)
-		return -EFAULT;
-	image = pdev->image_ptr[pdev->fill_image];
-	if (!image)
-		return -EFAULT;
-
-	yuv = fbuf->data + pdev->frame_header_size;  /* Skip header */
-
-	/* Raw format; that's easy... */
-	if (pdev->vpalette == VIDEO_PALETTE_RAW)
-	{
-		memcpy(image, yuv, pdev->frame_size);
-		return 0;
-	}
-
-	if (pdev->vbandlength == 0) {
-		/* Uncompressed mode. We copy the data into the output buffer,
-		   using the viewport size (which may be larger than the image
-		   size). Unfortunately we have to do a bit of byte stuffing
-		   to get the desired output format/size.
-		 */
-			/*
-			 * We do some byte shuffling here to go from the
-			 * native format to YUV420P.
-			 */
-			src = (u16 *)yuv;
-			n = pdev->view.x * pdev->view.y;
-
-			/* offset in Y plane */
-			stride = pdev->view.x * pdev->offset.y + pdev->offset.x;
-			dsty = (u16 *)(image + stride);
-
-			/* offsets in U/V planes */
-			stride = pdev->view.x * pdev->offset.y / 4 + pdev->offset.x / 2;
-			dstu = (u16 *)(image + n +         stride);
-			dstv = (u16 *)(image + n + n / 4 + stride);
-
-			/* increment after each line */
-			stride = (pdev->view.x - pdev->image.x) / 2; /* u16 is 2 bytes */
-
-			for (line = 0; line < pdev->image.y; line++) {
-				for (col = 0; col < pdev->image.x; col += 4) {
-					*dsty++ = *src++;
-					*dsty++ = *src++;
-					if (line & 1)
-						*dstv++ = *src++;
-					else
-						*dstu++ = *src++;
-				}
-				dsty += stride;
-				if (line & 1)
-					dstv += (stride >> 1);
-				else
-					dstu += (stride >> 1);
-			}
-	}
-	else {
-		/* Compressed; the decompressor routines will write the data
-		   in planar format immediately.
-		 */
-		int flags;
-                
-                flags = PWCX_FLAG_PLANAR;
-                if (pdev->vsize == PSZ_VGA && pdev->vframes == 5 && pdev->vsnapshot)
-                	flags |= PWCX_FLAG_BAYER;
-
-		if (pdev->decompressor)
-			pdev->decompressor->decompress(
-				&pdev->image, &pdev->view, &pdev->offset,
-				yuv, image,
-				flags,
-				pdev->decompress_data, pdev->vbandlength);
-		else
-			return -ENXIO; /* No such device or address: missing decompressor */
-	}
-	return 0;
-}
-
-/* Make sure these functions are available for the decompressor plugin
-   both when this code is compiled into the kernel or as as module.
- */
-
-EXPORT_SYMBOL_NOVERS(pwc_decompressor_version);
-EXPORT_SYMBOL(pwc_register_decompressor);
-EXPORT_SYMBOL(pwc_unregister_decompressor);
diff -Nru a/drivers/usb/media/pwc-uncompress.h b/drivers/usb/media/pwc-uncompress.h
--- a/drivers/usb/media/pwc-uncompress.h	2004-10-18 14:56:28 -07:00
+++ /dev/null	Wed Dec 31 16:00:00 196900
@@ -1,84 +0,0 @@
-/* (C) 1999-2003 Nemosoft Unv. (webcam@smcc.demon.nl)
-
-   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 is the bridge between the kernel module and the plugin; it
-   describes the structures and datatypes used in both modules. Any
-   significant change should be reflected by increasing the 
-   pwc_decompressor_version major number.
- */
-#ifndef PWC_UNCOMPRESS_H
-#define PWC_UNCOMPRESS_H
-
-#include <linux/config.h>
-#include <linux/linkage.h>
-#include <linux/list.h>
-
-#include "pwc-ioctl.h"
-
-/* from pwc-dec.h */
-#define PWCX_FLAG_PLANAR        0x0001
-/* */
-
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/* The decompressor structure. 
-   Every type of decompressor registers itself with the main module. 
-   When a device is opened, it looks up the correct compressor, and
-   uses that when a compressed video mode is requested.
- */
-struct pwc_decompressor
-{
-	int  type;		/* type of camera (645, 680, etc) */
-	int  table_size;	/* memory needed */
-
-	void (* init)(int type, int release, void *buffer, void *table);	/* Initialization routine; should be called after each set_video_mode */
-	void (* exit)(void);	/* Cleanup routine */
-	void (* decompress)(struct pwc_coord *image, struct pwc_coord *view,
-			    struct pwc_coord *offset,
-                            void *src, void *dst, int flags,
-	                    void *table, int bandlength);
-	void (* lock)(void);	/* make sure module cannot be unloaded */
-	void (* unlock)(void);	/* release lock on module */
-
-	struct list_head pwcd_list;
-};
-
-
-/* Our structure version number. Is set to the version number major */
-extern const int pwc_decompressor_version;
-
-/* Adds decompressor to list, based on its 'type' field (which matches the 'type' field in pwc_device; ignores any double requests */
-extern void pwc_register_decompressor(struct pwc_decompressor *pwcd);
-/* Removes decompressor, based on the type number */
-extern void pwc_unregister_decompressor(int type);
-/* Returns pointer to decompressor struct, or NULL if it doesn't exist */
-extern struct pwc_decompressor *pwc_find_decompressor(int type);
-
-#ifdef CONFIG_USB_PWCX
-/* If the decompressor is compiled in, we must call these manually */
-extern int usb_pwcx_init(void);
-extern void usb_pwcx_exit(void);
-#endif
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif
diff -Nru a/drivers/usb/media/pwc.h b/drivers/usb/media/pwc.h
--- a/drivers/usb/media/pwc.h	2004-10-18 14:56:33 -07:00
+++ /dev/null	Wed Dec 31 16:00:00 196900
@@ -1,271 +0,0 @@
-/* (C) 1999-2003 Nemosoft Unv. (webcam@smcc.demon.nl)
-
-   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
-*/
-
-#ifndef PWC_H
-#define PWC_H
-
-#include <linux/version.h>
-
-#include <linux/config.h>
-#include <linux/module.h>
-#include <linux/usb.h>
-#include <linux/spinlock.h>
-#include <linux/videodev.h>
-#include <linux/wait.h>
-#include <linux/smp_lock.h>
-#include <asm/semaphore.h>
-#include <asm/errno.h>
-
-#include "pwc-uncompress.h"
-#include "pwc-ioctl.h"
-
-/* Defines and structures for the Philips webcam */
-/* Used for checking memory corruption/pointer validation */
-#define PWC_MAGIC 0x89DC10ABUL
-#undef PWC_MAGIC
-
-/* Turn some debugging options on/off */
-#define PWC_DEBUG 0
-
-/* Trace certain actions in the driver */
-#define TRACE_MODULE	0x0001
-#define TRACE_PROBE	0x0002
-#define TRACE_OPEN	0x0004
-#define TRACE_READ	0x0008
-#define TRACE_MEMORY	0x0010
-#define TRACE_FLOW	0x0020
-#define TRACE_SIZE	0x0040
-#define TRACE_PWCX	0x0080
-#define TRACE_SEQUENCE	0x1000
-
-#define Trace(R, A...) if (pwc_trace & R) printk(KERN_DEBUG PWC_NAME " " A)
-#define Debug(A...) printk(KERN_DEBUG PWC_NAME " " A)
-#define Info(A...)  printk(KERN_INFO  PWC_NAME " " A)
-#define Err(A...)   printk(KERN_ERR   PWC_NAME " " A)
-
-
-/* Defines for ToUCam cameras */
-#define TOUCAM_HEADER_SIZE		8
-#define TOUCAM_TRAILER_SIZE		4
-
-#define FEATURE_MOTOR_PANTILT		0x0001
-
-/* Version block */
-#define PWC_MAJOR	9
-#define PWC_MINOR	0
-#define PWC_VERSION 	"9.0.1"
-#define PWC_NAME 	"pwc"
-
-/* Turn certain features on/off */
-#define PWC_INT_PIPE 0
-
-/* Ignore errors in the first N frames, to allow for startup delays */
-#define FRAME_LOWMARK 5
-
-/* Size and number of buffers for the ISO pipe. */
-#define MAX_ISO_BUFS		2
-#define ISO_FRAMES_PER_DESC	10
-#define ISO_MAX_FRAME_SIZE	960
-#define ISO_BUFFER_SIZE 	(ISO_FRAMES_PER_DESC * ISO_MAX_FRAME_SIZE)
-
-/* Frame buffers: contains compressed or uncompressed video data. */
-#define MAX_FRAMES		5
-/* Maximum size after decompression is 640x480 YUV data, 1.5 * 640 * 480 */
-#define PWC_FRAME_SIZE 		(460800 + TOUCAM_HEADER_SIZE + TOUCAM_TRAILER_SIZE)
-
-/* Absolute maximum number of buffers available for mmap() */
-#define MAX_IMAGES 		10
-
-/* The following structures were based on cpia.h. Why reinvent the wheel? :-) */
-struct pwc_iso_buf
-{
-	void *data;
-	int  length;
-	int  read;
-	struct urb *urb;
-};
-
-/* intermediate buffers with raw data from the USB cam */
-struct pwc_frame_buf
-{
-   void *data;
-   volatile int filled;		/* number of bytes filled */
-   struct pwc_frame_buf *next;	/* list */
-#if PWC_DEBUG
-   int sequence;		/* Sequence number */
-#endif
-};
-
-struct pwc_device
-{
-   struct video_device *vdev;
-#ifdef PWC_MAGIC
-   int magic;
-#endif
-   /* Pointer to our usb_device */
-   struct usb_device *udev;
-   
-   int type;                    /* type of cam (645, 646, 675, 680, 690, 720, 730, 740, 750) */
-   int release;			/* release number */
-   int features;		/* feature bits */
-   char serial[30];		/* serial number (string) */
-   int error_status;		/* set when something goes wrong with the cam (unplugged, USB errors) */
-   int usb_init;		/* set when the cam has been initialized over USB */
-
-   /*** Video data ***/
-   int vopen;			/* flag */
-   int vendpoint;		/* video isoc endpoint */
-   int vcinterface;		/* video control interface */
-   int valternate;		/* alternate interface needed */
-   int vframes, vsize;		/* frames-per-second & size (see PSZ_*) */
-   int vpalette;		/* palette: 420P, RAW or RGBBAYER */
-   int vframe_count;		/* received frames */
-   int vframes_dumped; 		/* counter for dumped frames */
-   int vframes_error;		/* frames received in error */
-   int vmax_packet_size;	/* USB maxpacket size */
-   int vlast_packet_size;	/* for frame synchronisation */
-   int visoc_errors;		/* number of contiguous ISOC errors */
-   int vcompression;		/* desired compression factor */
-   int vbandlength;		/* compressed band length; 0 is uncompressed */
-   char vsnapshot;		/* snapshot mode */
-   char vsync;			/* used by isoc handler */
-   char vmirror;		/* for ToUCaM series */
-   
-   int cmd_len;
-   unsigned char cmd_buf[13];
-
-   /* The image acquisition requires 3 to 4 steps:
-      1. data is gathered in short packets from the USB controller
-      2. data is synchronized and packed into a frame buffer
-      3a. in case data is compressed, decompress it directly into image buffer
-      3b. in case data is uncompressed, copy into image buffer with viewport
-      4. data is transferred to the user process
-
-      Note that MAX_ISO_BUFS != MAX_FRAMES != MAX_IMAGES....
-      We have in effect a back-to-back-double-buffer system.
-    */
-   /* 1: isoc */
-   struct pwc_iso_buf sbuf[MAX_ISO_BUFS];
-   char iso_init;
-
-   /* 2: frame */
-   struct pwc_frame_buf *fbuf;	/* all frames */
-   struct pwc_frame_buf *empty_frames, *empty_frames_tail;	/* all empty frames */
-   struct pwc_frame_buf *full_frames, *full_frames_tail;	/* all filled frames */
-   struct pwc_frame_buf *fill_frame;	/* frame currently being filled */
-   struct pwc_frame_buf *read_frame;	/* frame currently read by user process */
-   int frame_header_size, frame_trailer_size;
-   int frame_size;
-   int frame_total_size; /* including header & trailer */
-   int drop_frames;
-#if PWC_DEBUG
-   int sequence;			/* Debugging aid */
-#endif
-
-   /* 3: decompression */
-   struct pwc_decompressor *decompressor;	/* function block with decompression routines */
-   void *decompress_data;		/* private data for decompression engine */
-
-   /* 4: image */
-   /* We have an 'image' and a 'view', where 'image' is the fixed-size image
-      as delivered by the camera, and 'view' is the size requested by the
-      program. The camera image is centered in this viewport, laced with
-      a gray or black border. view_min <= image <= view <= view_max;
-    */
-   int image_mask;			/* bitmask of supported sizes */
-   struct pwc_coord view_min, view_max;	/* minimum and maximum viewable sizes */
-   struct pwc_coord abs_max;            /* maximum supported size with compression */
-   struct pwc_coord image, view;	/* image and viewport size */
-   struct pwc_coord offset;		/* offset within the viewport */
-
-   void *image_data;			/* total buffer, which is subdivided into ... */
-   void *image_ptr[MAX_IMAGES];		/* ...several images... */
-   int fill_image;			/* ...which are rotated. */
-   int len_per_image;			/* length per image */
-   int image_read_pos;			/* In case we read data in pieces, keep track of were we are in the imagebuffer */
-   int image_used[MAX_IMAGES];		/* For MCAPTURE and SYNC */
-
-   struct semaphore modlock;		/* to prevent races in video_open(), etc */
-   spinlock_t ptrlock;			/* for manipulating the buffer pointers */
-
-   /*** motorized pan/tilt feature */
-   struct pwc_mpt_range angle_range;
-   int pan_angle;			/* in degrees * 100 */
-   int tilt_angle;			/* absolute angle; 0,0 is home position */
-
-   /*** Misc. data ***/
-   wait_queue_head_t frameq;		/* When waiting for a frame to finish... */
-#if PWC_INT_PIPE
-   void *usb_int_handler;		/* for the interrupt endpoint */
-#endif
-};
-
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/* Global variables */
-extern int pwc_trace;
-extern int pwc_preferred_compression;
-
-/** functions in pwc-if.c */
-int pwc_try_video_mode(struct pwc_device *pdev, int width, int height, int new_fps, int new_compression, int new_snapshot);
-
-/** Functions in pwc-misc.c */
-/* sizes in pixels */
-extern struct pwc_coord pwc_image_sizes[PSZ_MAX];
-
-int pwc_decode_size(struct pwc_device *pdev, int width, int height);
-void pwc_construct(struct pwc_device *pdev);
-
-/** Functions in pwc-ctrl.c */
-/* Request a certain video mode. Returns < 0 if not possible */
-extern int pwc_set_video_mode(struct pwc_device *pdev, int width, int height, int frames, int compression, int snapshot);
-/* Calculate the number of bytes per image (not frame) */
-extern void pwc_set_image_buffer_size(struct pwc_device *pdev);
-
-/* Various controls; should be obvious. Value 0..65535, or < 0 on error */
-extern int pwc_get_brightness(struct pwc_device *pdev);
-extern int pwc_set_brightness(struct pwc_device *pdev, int value);
-extern int pwc_get_contrast(struct pwc_device *pdev);
-extern int pwc_set_contrast(struct pwc_device *pdev, int value);
-extern int pwc_get_gamma(struct pwc_device *pdev);
-extern int pwc_set_gamma(struct pwc_device *pdev, int value);
-extern int pwc_get_saturation(struct pwc_device *pdev);
-extern int pwc_set_saturation(struct pwc_device *pdev, int value);
-extern int pwc_set_leds(struct pwc_device *pdev, int on_value, int off_value);
-extern int pwc_get_leds(struct pwc_device *pdev, int *on_value, int *off_value);
-extern int pwc_get_cmos_sensor(struct pwc_device *pdev, int *sensor);
-
-/* Power down or up the camera; not supported by all models */
-extern int pwc_camera_power(struct pwc_device *pdev, int power);
-
-/* Private ioctl()s; see pwc-ioctl.h */
-extern int pwc_ioctl(struct pwc_device *pdev, unsigned int cmd, void *arg);
-
-
-/** pwc-uncompress.c */
-/* Expand frame to image, possibly including decompression. Uses read_frame and fill_image */
-extern int pwc_decompress(struct pwc_device *pdev);
-
-#ifdef __cplusplus
-}
-#endif
-
-
-#endif
diff -Nru a/drivers/usb/media/pwc_kiara.h b/drivers/usb/media/pwc_kiara.h
--- a/drivers/usb/media/pwc_kiara.h	2004-10-18 14:56:28 -07:00
+++ /dev/null	Wed Dec 31 16:00:00 196900
@@ -1,270 +0,0 @@
-   /* SQCIF */
-   {
-      /* 5 fps */
-      {
-         {0, },
-         {0, },
-         {0, },
-         {0, },
-      },
-      /* 10 fps */
-      {
-         {0, },
-         {0, },
-         {0, },
-         {0, },
-      },
-      /* 15 fps */
-      {
-         {0, },
-         {0, },
-         {0, },
-         {0, },
-      },
-      /* 20 fps */
-      {
-         {0, },
-         {0, },
-         {0, },
-         {0, },
-      },
-      /* 25 fps */
-      {
-         {0, },
-         {0, },
-         {0, },
-         {0, },
-      },
-      /* 30 fps */
-      {
-         {0, },
-         {0, },
-         {0, },
-         {0, },
-      },
-   },
-   /* QSIF */
-   {
-      /* 5 fps */
-      {
-         {1, 146,    0, {0x1D, 0xF4, 0x30, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x92, 0x00, 0x80}},
-         {1, 146,    0, {0x1D, 0xF4, 0x30, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x92, 0x00, 0x80}},
-         {1, 146,    0, {0x1D, 0xF4, 0x30, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x92, 0x00, 0x80}},
-         {1, 146,    0, {0x1D, 0xF4, 0x30, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x92, 0x00, 0x80}},
-      },
-      /* 10 fps */
-      {
-         {2, 291,    0, {0x1C, 0xF4, 0x30, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x23, 0x01, 0x80}},
-         {1, 192,  630, {0x14, 0xF4, 0x30, 0x13, 0xA9, 0x12, 0xE1, 0x17, 0x08, 0xC0, 0x00, 0x80}},
-         {1, 192,  630, {0x14, 0xF4, 0x30, 0x13, 0xA9, 0x12, 0xE1, 0x17, 0x08, 0xC0, 0x00, 0x80}},
-         {1, 192,  630, {0x14, 0xF4, 0x30, 0x13, 0xA9, 0x12, 0xE1, 0x17, 0x08, 0xC0, 0x00, 0x80}},
-      },
-      /* 15 fps */
-      {
-         {3, 437,    0, {0x1B, 0xF4, 0x30, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0xB5, 0x01, 0x80}},
-         {2, 292,  640, {0x13, 0xF4, 0x30, 0x13, 0xF7, 0x13, 0x2F, 0x13, 0x20, 0x24, 0x01, 0x80}},
-         {2, 292,  640, {0x13, 0xF4, 0x30, 0x13, 0xF7, 0x13, 0x2F, 0x13, 0x20, 0x24, 0x01, 0x80}},
-         {1, 192,  420, {0x13, 0xF4, 0x30, 0x0D, 0x1B, 0x0C, 0x53, 0x1E, 0x18, 0xC0, 0x00, 0x80}},
-      },
-      /* 20 fps */
-      {
-         {4, 589,    0, {0x1A, 0xF4, 0x30, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x4D, 0x02, 0x80}},
-         {3, 448,  730, {0x12, 0xF4, 0x30, 0x16, 0xC9, 0x16, 0x01, 0x0E, 0x18, 0xC0, 0x01, 0x80}},
-         {2, 292,  476, {0x12, 0xF4, 0x30, 0x0E, 0xD8, 0x0E, 0x10, 0x19, 0x18, 0x24, 0x01, 0x80}},
-         {1, 192,  312, {0x12, 0xF4, 0x50, 0x09, 0xB3, 0x08, 0xEB, 0x1E, 0x18, 0xC0, 0x00, 0x80}},
-      },
-      /* 25 fps */
-      {
-         {5, 703,    0, {0x19, 0xF4, 0x30, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0xBF, 0x02, 0x80}},
-         {3, 447,  610, {0x11, 0xF4, 0x30, 0x13, 0x0B, 0x12, 0x43, 0x14, 0x28, 0xBF, 0x01, 0x80}},
-         {2, 292,  398, {0x11, 0xF4, 0x50, 0x0C, 0x6C, 0x0B, 0xA4, 0x1E, 0x28, 0x24, 0x01, 0x80}},
-         {1, 193,  262, {0x11, 0xF4, 0x50, 0x08, 0x23, 0x07, 0x5B, 0x1E, 0x28, 0xC1, 0x00, 0x80}},
-      },
-      /* 30 fps */
-      {
-         {8, 874,    0, {0x18, 0xF4, 0x30, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x6A, 0x03, 0x80}},
-         {5, 704,  730, {0x10, 0xF4, 0x30, 0x16, 0xC9, 0x16, 0x01, 0x0E, 0x28, 0xC0, 0x02, 0x80}},
-         {3, 448,  492, {0x10, 0xF4, 0x30, 0x0F, 0x5D, 0x0E, 0x95, 0x15, 0x28, 0xC0, 0x01, 0x80}},
-         {2, 292,  320, {0x10, 0xF4, 0x50, 0x09, 0xFB, 0x09, 0x33, 0x1E, 0x28, 0x24, 0x01, 0x80}},
-      },
-   },
-   /* QCIF */
-   {
-      /* 5 fps */
-      {
-         {0, },
-         {0, },
-         {0, },
-         {0, },
-      },
-      /* 10 fps */
-      {
-         {0, },
-         {0, },
-         {0, },
-         {0, },
-      },
-      /* 15 fps */
-      {
-         {0, },
-         {0, },
-         {0, },
-         {0, },
-      },
-      /* 20 fps */
-      {
-         {0, },
-         {0, },
-         {0, },
-         {0, },
-      },
-      /* 25 fps */
-      {
-         {0, },
-         {0, },
-         {0, },
-         {0, },
-      },
-      /* 30 fps */
-      {
-         {0, },
-         {0, },
-         {0, },
-         {0, },
-      },
-   },
-   /* SIF */
-   {
-      /* 5 fps */
-      {
-         {4, 582,    0, {0x0D, 0xF4, 0x30, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x46, 0x02, 0x80}},
-         {3, 387, 1276, {0x05, 0xF4, 0x30, 0x27, 0xD8, 0x26, 0x48, 0x03, 0x10, 0x83, 0x01, 0x80}},
-         {2, 291,  960, {0x05, 0xF4, 0x30, 0x1D, 0xF2, 0x1C, 0x62, 0x04, 0x10, 0x23, 0x01, 0x80}},
-         {1, 191,  630, {0x05, 0xF4, 0x50, 0x13, 0xA9, 0x12, 0x19, 0x05, 0x18, 0xBF, 0x00, 0x80}},
-      },
-      /* 10 fps */
-      {
-         {0, },
-         {6, 775, 1278, {0x04, 0xF4, 0x30, 0x27, 0xE8, 0x26, 0x58, 0x05, 0x30, 0x07, 0x03, 0x80}},
-         {3, 447,  736, {0x04, 0xF4, 0x30, 0x16, 0xFB, 0x15, 0x6B, 0x05, 0x28, 0xBF, 0x01, 0x80}},
-         {2, 292,  480, {0x04, 0xF4, 0x70, 0x0E, 0xF9, 0x0D, 0x69, 0x09, 0x28, 0x24, 0x01, 0x80}},
-      },
-      /* 15 fps */
-      {
-         {0, },
-         {9, 955, 1050, {0x03, 0xF4, 0x30, 0x20, 0xCF, 0x1F, 0x3F, 0x06, 0x48, 0xBB, 0x03, 0x80}},
-         {4, 592,  650, {0x03, 0xF4, 0x30, 0x14, 0x44, 0x12, 0xB4, 0x08, 0x30, 0x50, 0x02, 0x80}},
-         {3, 448,  492, {0x03, 0xF4, 0x50, 0x0F, 0x52, 0x0D, 0xC2, 0x09, 0x38, 0xC0, 0x01, 0x80}},
-      },
-      /* 20 fps */
-      {
-         {0, },
-         {9, 958,  782, {0x02, 0xF4, 0x30, 0x18, 0x6A, 0x16, 0xDA, 0x0B, 0x58, 0xBE, 0x03, 0x80}},
-         {5, 703,  574, {0x02, 0xF4, 0x50, 0x11, 0xE7, 0x10, 0x57, 0x0B, 0x40, 0xBF, 0x02, 0x80}},
-         {3, 446,  364, {0x02, 0xF4, 0x90, 0x0B, 0x5C, 0x09, 0xCC, 0x0E, 0x38, 0xBE, 0x01, 0x80}},
-      },
-      /* 25 fps */
-      {
-         {0, },
-         {9, 958,  654, {0x01, 0xF4, 0x30, 0x14, 0x66, 0x12, 0xD6, 0x0B, 0x50, 0xBE, 0x03, 0x80}},
-         {6, 776,  530, {0x01, 0xF4, 0x50, 0x10, 0x8C, 0x0E, 0xFC, 0x0C, 0x48, 0x08, 0x03, 0x80}},
-         {4, 592,  404, {0x01, 0xF4, 0x70, 0x0C, 0x96, 0x0B, 0x06, 0x0B, 0x48, 0x50, 0x02, 0x80}},
-      },
-      /* 30 fps */
-      {
-         {0, },
-         {9, 957,  526, {0x00, 0xF4, 0x50, 0x10, 0x68, 0x0E, 0xD8, 0x0D, 0x58, 0xBD, 0x03, 0x80}},
-         {6, 775,  426, {0x00, 0xF4, 0x70, 0x0D, 0x48, 0x0B, 0xB8, 0x0F, 0x50, 0x07, 0x03, 0x80}},
-         {4, 590,  324, {0x00, 0x7A, 0x88, 0x0A, 0x1C, 0x08, 0xB4, 0x0E, 0x50, 0x4E, 0x02, 0x80}},
-      },
-   },
-   /* CIF */
-   {
-      /* 5 fps */
-      {
-         {0, },
-         {0, },
-         {0, },
-         {0, },
-      },
-      /* 10 fps */
-      {
-         {0, },
-         {0, },
-         {0, },
-         {0, },
-      },
-      /* 15 fps */
-      {
-         {0, },
-         {0, },
-         {0, },
-         {0, },
-      },
-      /* 20 fps */
-      {
-         {0, },
-         {0, },
-         {0, },
-         {0, },
-      },
-      /* 25 fps */
-      {
-         {0, },
-         {0, },
-         {0, },
-         {0, },
-      },
-      /* 30 fps */
-      {
-         {0, },
-         {0, },
-         {0, },
-         {0, },
-      },
-   },
-   /* VGA */
-   {
-      /* 5 fps */
-      {
-         {0, },
-         {6, 773, 1272, {0x25, 0xF4, 0x30, 0x27, 0xB6, 0x24, 0x96, 0x02, 0x30, 0x05, 0x03, 0x80}},
-         {4, 592,  976, {0x25, 0xF4, 0x50, 0x1E, 0x78, 0x1B, 0x58, 0x03, 0x30, 0x50, 0x02, 0x80}},
-         {3, 448,  738, {0x25, 0xF4, 0x90, 0x17, 0x0C, 0x13, 0xEC, 0x04, 0x30, 0xC0, 0x01, 0x80}},
-      },
-      /* 10 fps */
-      {
-         {0, },
-         {9, 956,  788, {0x24, 0xF4, 0x70, 0x18, 0x9C, 0x15, 0x7C, 0x03, 0x48, 0xBC, 0x03, 0x80}},
-         {6, 776,  640, {0x24, 0xF4, 0xB0, 0x13, 0xFC, 0x11, 0x2C, 0x04, 0x48, 0x08, 0x03, 0x80}},
-         {4, 592,  488, {0x24, 0x7A, 0xE8, 0x0F, 0x3C, 0x0C, 0x6C, 0x06, 0x48, 0x50, 0x02, 0x80}},
-      },
-      /* 15 fps */
-      {
-         {0, },
-         {9, 957,  526, {0x23, 0x7A, 0xE8, 0x10, 0x68, 0x0D, 0x98, 0x06, 0x58, 0xBD, 0x03, 0x80}},
-         {9, 957,  526, {0x23, 0x7A, 0xE8, 0x10, 0x68, 0x0D, 0x98, 0x06, 0x58, 0xBD, 0x03, 0x80}},
-         {8, 895,  492, {0x23, 0x7A, 0xE8, 0x0F, 0x5D, 0x0C, 0x8D, 0x06, 0x58, 0x7F, 0x03, 0x80}},
-      },
-      /* 20 fps */
-      {
-         {0, },
-         {0, },
-         {0, },
-         {0, },
-      },
-      /* 25 fps */
-      {
-         {0, },
-         {0, },
-         {0, },
-         {0, },
-      },
-      /* 30 fps */
-      {
-         {0, },
-         {0, },
-         {0, },
-         {0, },
-      },
-   },
diff -Nru a/drivers/usb/media/pwc_nala.h b/drivers/usb/media/pwc_nala.h
--- a/drivers/usb/media/pwc_nala.h	2004-10-18 14:56:20 -07:00
+++ /dev/null	Wed Dec 31 16:00:00 196900
@@ -1,66 +0,0 @@
-   /* SQCIF */
-   {
-      {0, 0, {0x04, 0x01, 0x03}},
-      {8, 0, {0x05, 0x01, 0x03}},
-      {7, 0, {0x08, 0x01, 0x03}},
-      {7, 0, {0x0A, 0x01, 0x03}},
-      {6, 0, {0x0C, 0x01, 0x03}},
-      {5, 0, {0x0F, 0x01, 0x03}},
-      {4, 0, {0x14, 0x01, 0x03}},
-      {3, 0, {0x18, 0x01, 0x03}},
-   },
-   /* QSIF */
-   {
-      {0},
-      {0},
-      {0},
-      {0},
-      {0},
-      {0},
-      {0},
-      {0},
-   },
-   /* QCIF */
-   {
-      {0, 0, {0x04, 0x01, 0x02}},
-      {8, 0, {0x05, 0x01, 0x02}},
-      {7, 0, {0x08, 0x01, 0x02}},
-      {6, 0, {0x0A, 0x01, 0x02}},
-      {5, 0, {0x0C, 0x01, 0x02}},
-      {4, 0, {0x0F, 0x01, 0x02}},
-      {1, 0, {0x14, 0x01, 0x02}},
-      {1, 0, {0x18, 0x01, 0x02}},
-   },
-   /* SIF */
-   {
-      {0},
-      {0},
-      {0},
-      {0},
-      {0},
-      {0},
-      {0},
-      {0},
-   },
-   /* CIF */
-   {
-      {4, 0, {0x04, 0x01, 0x01}},
-      {7, 1, {0x05, 0x03, 0x01}},
-      {6, 1, {0x08, 0x03, 0x01}},
-      {4, 1, {0x0A, 0x03, 0x01}},
-      {3, 1, {0x0C, 0x03, 0x01}},
-      {2, 1, {0x0F, 0x03, 0x01}},
-      {0},
-      {0},
-   },
-   /* VGA */
-   {  
-      {0},
-      {0},
-      {0},
-      {0},
-      {0},
-      {0},
-      {0},
-      {0},
-   },
diff -Nru a/drivers/usb/media/pwc_timon.h b/drivers/usb/media/pwc_timon.h
--- a/drivers/usb/media/pwc_timon.h	2004-10-18 14:56:49 -07:00
+++ /dev/null	Wed Dec 31 16:00:00 196900
@@ -1,270 +0,0 @@
-   /* SQCIF */
-   {
-      /* 5 fps */
-      {
-         {1, 140,    0, {0x05, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x8C, 0xFC, 0x80, 0x02}},
-         {1, 140,    0, {0x05, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x8C, 0xFC, 0x80, 0x02}},
-         {1, 140,    0, {0x05, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x8C, 0xFC, 0x80, 0x02}},
-         {1, 140,    0, {0x05, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x8C, 0xFC, 0x80, 0x02}},
-      },
-      /* 10 fps */
-      {
-         {2, 280,    0, {0x04, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x18, 0xA9, 0x80, 0x02}},
-         {2, 280,    0, {0x04, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x18, 0xA9, 0x80, 0x02}},
-         {2, 280,    0, {0x04, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x18, 0xA9, 0x80, 0x02}},
-         {2, 280,    0, {0x04, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x18, 0xA9, 0x80, 0x02}},
-      },
-      /* 15 fps */
-      {
-         {3, 410,    0, {0x03, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x9A, 0x71, 0x80, 0x02}},
-         {3, 410,    0, {0x03, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x9A, 0x71, 0x80, 0x02}},
-         {3, 410,    0, {0x03, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x9A, 0x71, 0x80, 0x02}},
-         {3, 410,    0, {0x03, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x9A, 0x71, 0x80, 0x02}},
-      },
-      /* 20 fps */
-      {
-         {4, 559,    0, {0x02, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x2F, 0x56, 0x80, 0x02}},
-         {4, 559,    0, {0x02, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x2F, 0x56, 0x80, 0x02}},
-         {4, 559,    0, {0x02, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x2F, 0x56, 0x80, 0x02}},
-         {4, 559,    0, {0x02, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x2F, 0x56, 0x80, 0x02}},
-      },
-      /* 25 fps */
-      {
-         {5, 659,    0, {0x01, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x93, 0x46, 0x80, 0x02}},
-         {5, 659,    0, {0x01, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x93, 0x46, 0x80, 0x02}},
-         {5, 659,    0, {0x01, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x93, 0x46, 0x80, 0x02}},
-         {5, 659,    0, {0x01, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x93, 0x46, 0x80, 0x02}},
-      },
-      /* 30 fps */
-      {
-         {7, 838,    0, {0x00, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x46, 0x3B, 0x80, 0x02}},
-         {7, 838,    0, {0x00, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x46, 0x3B, 0x80, 0x02}},
-         {7, 838,    0, {0x00, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x46, 0x3B, 0x80, 0x02}},
-         {7, 838,    0, {0x00, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x46, 0x3B, 0x80, 0x02}},
-      },
-   },
-   /* QSIF */
-   {
-      /* 5 fps */
-      {
-         {1, 146,    0, {0x2D, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x92, 0xFC, 0xC0, 0x02}},
-         {1, 146,    0, {0x2D, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x92, 0xFC, 0xC0, 0x02}},
-         {1, 146,    0, {0x2D, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x92, 0xFC, 0xC0, 0x02}},
-         {1, 146,    0, {0x2D, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x92, 0xFC, 0xC0, 0x02}},
-      },
-      /* 10 fps */
-      {
-         {2, 291,    0, {0x2C, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x23, 0xA1, 0xC0, 0x02}},
-         {1, 191,  630, {0x2C, 0xF4, 0x05, 0x13, 0xA9, 0x12, 0xE1, 0x17, 0x08, 0xBF, 0xF4, 0xC0, 0x02}},
-         {1, 191,  630, {0x2C, 0xF4, 0x05, 0x13, 0xA9, 0x12, 0xE1, 0x17, 0x08, 0xBF, 0xF4, 0xC0, 0x02}},
-         {1, 191,  630, {0x2C, 0xF4, 0x05, 0x13, 0xA9, 0x12, 0xE1, 0x17, 0x08, 0xBF, 0xF4, 0xC0, 0x02}},
-      },
-      /* 15 fps */
-      {
-         {3, 437,    0, {0x2B, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0xB5, 0x6D, 0xC0, 0x02}},
-         {2, 291,  640, {0x2B, 0xF4, 0x05, 0x13, 0xF7, 0x13, 0x2F, 0x13, 0x08, 0x23, 0xA1, 0xC0, 0x02}},
-         {2, 291,  640, {0x2B, 0xF4, 0x05, 0x13, 0xF7, 0x13, 0x2F, 0x13, 0x08, 0x23, 0xA1, 0xC0, 0x02}},
-         {1, 191,  420, {0x2B, 0xF4, 0x0D, 0x0D, 0x1B, 0x0C, 0x53, 0x1E, 0x08, 0xBF, 0xF4, 0xC0, 0x02}},
-      },
-      /* 20 fps */
-      {
-         {4, 588,    0, {0x2A, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x4C, 0x52, 0xC0, 0x02}},
-         {3, 447,  730, {0x2A, 0xF4, 0x05, 0x16, 0xC9, 0x16, 0x01, 0x0E, 0x18, 0xBF, 0x69, 0xC0, 0x02}},
-         {2, 292,  476, {0x2A, 0xF4, 0x0D, 0x0E, 0xD8, 0x0E, 0x10, 0x19, 0x18, 0x24, 0xA1, 0xC0, 0x02}},
-         {1, 192,  312, {0x2A, 0xF4, 0x1D, 0x09, 0xB3, 0x08, 0xEB, 0x1E, 0x18, 0xC0, 0xF4, 0xC0, 0x02}},
-      },
-      /* 25 fps */
-      {
-         {5, 703,    0, {0x29, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0xBF, 0x42, 0xC0, 0x02}},
-         {3, 447,  610, {0x29, 0xF4, 0x05, 0x13, 0x0B, 0x12, 0x43, 0x14, 0x18, 0xBF, 0x69, 0xC0, 0x02}},
-         {2, 292,  398, {0x29, 0xF4, 0x0D, 0x0C, 0x6C, 0x0B, 0xA4, 0x1E, 0x18, 0x24, 0xA1, 0xC0, 0x02}},
-         {1, 192,  262, {0x29, 0xF4, 0x25, 0x08, 0x23, 0x07, 0x5B, 0x1E, 0x18, 0xC0, 0xF4, 0xC0, 0x02}},
-      },
-      /* 30 fps */
-      {
-         {8, 873,    0, {0x28, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x69, 0x37, 0xC0, 0x02}},
-         {5, 704,  774, {0x28, 0xF4, 0x05, 0x18, 0x21, 0x17, 0x59, 0x0F, 0x18, 0xC0, 0x42, 0xC0, 0x02}},
-         {3, 448,  492, {0x28, 0xF4, 0x05, 0x0F, 0x5D, 0x0E, 0x95, 0x15, 0x18, 0xC0, 0x69, 0xC0, 0x02}},
-         {2, 291,  320, {0x28, 0xF4, 0x1D, 0x09, 0xFB, 0x09, 0x33, 0x1E, 0x18, 0x23, 0xA1, 0xC0, 0x02}},
-      },
-   },
-   /* QCIF */
-   {
-      /* 5 fps */
-      {
-         {1, 193,    0, {0x0D, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x12, 0x00, 0xC1, 0xF4, 0xC0, 0x02}},
-         {1, 193,    0, {0x0D, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x12, 0x00, 0xC1, 0xF4, 0xC0, 0x02}},
-         {1, 193,    0, {0x0D, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x12, 0x00, 0xC1, 0xF4, 0xC0, 0x02}},
-         {1, 193,    0, {0x0D, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x12, 0x00, 0xC1, 0xF4, 0xC0, 0x02}},
-      },
-      /* 10 fps */
-      {
-         {3, 385,    0, {0x0C, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x12, 0x00, 0x81, 0x79, 0xC0, 0x02}},
-         {2, 291,  800, {0x0C, 0xF4, 0x05, 0x18, 0xF4, 0x18, 0x18, 0x11, 0x08, 0x23, 0xA1, 0xC0, 0x02}},
-         {2, 291,  800, {0x0C, 0xF4, 0x05, 0x18, 0xF4, 0x18, 0x18, 0x11, 0x08, 0x23, 0xA1, 0xC0, 0x02}},
-         {1, 194,  532, {0x0C, 0xF4, 0x05, 0x10, 0x9A, 0x0F, 0xBE, 0x1B, 0x08, 0xC2, 0xF0, 0xC0, 0x02}},
-      },
-      /* 15 fps */
-      {
-         {4, 577,    0, {0x0B, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x12, 0x00, 0x41, 0x52, 0xC0, 0x02}},
-         {3, 447,  818, {0x0B, 0xF4, 0x05, 0x19, 0x89, 0x18, 0xAD, 0x0F, 0x10, 0xBF, 0x69, 0xC0, 0x02}},
-         {2, 292,  534, {0x0B, 0xF4, 0x05, 0x10, 0xA3, 0x0F, 0xC7, 0x19, 0x10, 0x24, 0xA1, 0xC0, 0x02}},
-         {1, 195,  356, {0x0B, 0xF4, 0x15, 0x0B, 0x11, 0x0A, 0x35, 0x1E, 0x10, 0xC3, 0xF0, 0xC0, 0x02}},
-      },
-      /* 20 fps */
-      {
-         {6, 776,    0, {0x0A, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x12, 0x00, 0x08, 0x3F, 0xC0, 0x02}},
-         {4, 591,  804, {0x0A, 0xF4, 0x05, 0x19, 0x1E, 0x18, 0x42, 0x0F, 0x18, 0x4F, 0x4E, 0xC0, 0x02}},
-         {3, 447,  608, {0x0A, 0xF4, 0x05, 0x12, 0xFD, 0x12, 0x21, 0x15, 0x18, 0xBF, 0x69, 0xC0, 0x02}},
-         {2, 291,  396, {0x0A, 0xF4, 0x15, 0x0C, 0x5E, 0x0B, 0x82, 0x1E, 0x18, 0x23, 0xA1, 0xC0, 0x02}},
-      },
-      /* 25 fps */
-      {
-         {9, 928,    0, {0x09, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x12, 0x00, 0xA0, 0x33, 0xC0, 0x02}},
-         {5, 703,  800, {0x09, 0xF4, 0x05, 0x18, 0xF4, 0x18, 0x18, 0x10, 0x18, 0xBF, 0x42, 0xC0, 0x02}},
-         {3, 447,  508, {0x09, 0xF4, 0x0D, 0x0F, 0xD2, 0x0E, 0xF6, 0x1B, 0x18, 0xBF, 0x69, 0xC0, 0x02}},
-         {2, 292,  332, {0x09, 0xF4, 0x1D, 0x0A, 0x5A, 0x09, 0x7E, 0x1E, 0x18, 0x24, 0xA1, 0xC0, 0x02}},
-      },
-      /* 30 fps */
-      {
-         {0, },
-         {9, 956,  876, {0x08, 0xF4, 0x05, 0x1B, 0x58, 0x1A, 0x7C, 0x0E, 0x20, 0xBC, 0x33, 0x10, 0x02}},
-         {4, 592,  542, {0x08, 0xF4, 0x05, 0x10, 0xE4, 0x10, 0x08, 0x17, 0x20, 0x50, 0x4E, 0x10, 0x02}},
-         {2, 291,  266, {0x08, 0xF4, 0x25, 0x08, 0x48, 0x07, 0x6C, 0x1E, 0x20, 0x23, 0xA1, 0x10, 0x02}},
-      },
-   },
-   /* SIF */
-   {
-      /* 5 fps */
-      {
-         {4, 582,    0, {0x35, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x46, 0x52, 0x60, 0x02}},
-         {3, 387, 1276, {0x35, 0xF4, 0x05, 0x27, 0xD8, 0x26, 0x48, 0x03, 0x10, 0x83, 0x79, 0x60, 0x02}},
-         {2, 291,  960, {0x35, 0xF4, 0x0D, 0x1D, 0xF2, 0x1C, 0x62, 0x04, 0x10, 0x23, 0xA1, 0x60, 0x02}},
-         {1, 191,  630, {0x35, 0xF4, 0x1D, 0x13, 0xA9, 0x12, 0x19, 0x05, 0x08, 0xBF, 0xF4, 0x60, 0x02}},
-      },
-      /* 10 fps */
-      {
-         {0, },
-         {6, 775, 1278, {0x34, 0xF4, 0x05, 0x27, 0xE8, 0x26, 0x58, 0x05, 0x30, 0x07, 0x3F, 0x10, 0x02}},
-         {3, 447,  736, {0x34, 0xF4, 0x15, 0x16, 0xFB, 0x15, 0x6B, 0x05, 0x18, 0xBF, 0x69, 0x10, 0x02}},
-         {2, 291,  480, {0x34, 0xF4, 0x2D, 0x0E, 0xF9, 0x0D, 0x69, 0x09, 0x18, 0x23, 0xA1, 0x10, 0x02}},
-      },
-      /* 15 fps */
-      {
-         {0, },
-         {9, 955, 1050, {0x33, 0xF4, 0x05, 0x20, 0xCF, 0x1F, 0x3F, 0x06, 0x48, 0xBB, 0x33, 0x10, 0x02}},
-         {4, 591,  650, {0x33, 0xF4, 0x15, 0x14, 0x44, 0x12, 0xB4, 0x08, 0x30, 0x4F, 0x4E, 0x10, 0x02}},
-         {3, 448,  492, {0x33, 0xF4, 0x25, 0x0F, 0x52, 0x0D, 0xC2, 0x09, 0x28, 0xC0, 0x69, 0x10, 0x02}},
-      },
-      /* 20 fps */
-      {
-         {0, },
-         {9, 958,  782, {0x32, 0xF4, 0x0D, 0x18, 0x6A, 0x16, 0xDA, 0x0B, 0x58, 0xBE, 0x33, 0xD0, 0x02}},
-         {5, 703,  574, {0x32, 0xF4, 0x1D, 0x11, 0xE7, 0x10, 0x57, 0x0B, 0x40, 0xBF, 0x42, 0xD0, 0x02}},
-         {3, 446,  364, {0x32, 0xF4, 0x3D, 0x0B, 0x5C, 0x09, 0xCC, 0x0E, 0x30, 0xBE, 0x69, 0xD0, 0x02}},
-      },
-      /* 25 fps */
-      {
-         {0, },
-         {9, 958,  654, {0x31, 0xF4, 0x15, 0x14, 0x66, 0x12, 0xD6, 0x0B, 0x50, 0xBE, 0x33, 0x90, 0x02}},
-         {6, 776,  530, {0x31, 0xF4, 0x25, 0x10, 0x8C, 0x0E, 0xFC, 0x0C, 0x48, 0x08, 0x3F, 0x90, 0x02}},
-         {4, 592,  404, {0x31, 0xF4, 0x35, 0x0C, 0x96, 0x0B, 0x06, 0x0B, 0x38, 0x50, 0x4E, 0x90, 0x02}},
-      },
-      /* 30 fps */
-      {
-         {0, },
-         {9, 957,  526, {0x30, 0xF4, 0x25, 0x10, 0x68, 0x0E, 0xD8, 0x0D, 0x58, 0xBD, 0x33, 0x60, 0x02}},
-         {6, 775,  426, {0x30, 0xF4, 0x35, 0x0D, 0x48, 0x0B, 0xB8, 0x0F, 0x50, 0x07, 0x3F, 0x60, 0x02}},
-         {4, 590,  324, {0x30, 0x7A, 0x4B, 0x0A, 0x1C, 0x08, 0xB4, 0x0E, 0x40, 0x4E, 0x52, 0x60, 0x02}},
-      },
-   },
-   /* CIF */
-   {
-      /* 5 fps */
-      {
-         {6, 771,    0, {0x15, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x03, 0x3F, 0x80, 0x02}},
-         {4, 465, 1278, {0x15, 0xF4, 0x05, 0x27, 0xEE, 0x26, 0x36, 0x03, 0x18, 0xD1, 0x65, 0x80, 0x02}},
-         {2, 291,  800, {0x15, 0xF4, 0x15, 0x18, 0xF4, 0x17, 0x3C, 0x05, 0x18, 0x23, 0xA1, 0x80, 0x02}},
-         {1, 193,  528, {0x15, 0xF4, 0x2D, 0x10, 0x7E, 0x0E, 0xC6, 0x0A, 0x18, 0xC1, 0xF4, 0x80, 0x02}},
-      },
-      /* 10 fps */
-      {
-         {0, },
-         {9, 932, 1278, {0x14, 0xF4, 0x05, 0x27, 0xEE, 0x26, 0x36, 0x04, 0x30, 0xA4, 0x33, 0x10, 0x02}},
-         {4, 591,  812, {0x14, 0xF4, 0x15, 0x19, 0x56, 0x17, 0x9E, 0x06, 0x28, 0x4F, 0x4E, 0x10, 0x02}},
-         {2, 291,  400, {0x14, 0xF4, 0x3D, 0x0C, 0x7A, 0x0A, 0xC2, 0x0E, 0x28, 0x23, 0xA1, 0x10, 0x02}},
-      },
-      /* 15 fps */
-      {
-         {0, },
-         {9, 956,  876, {0x13, 0xF4, 0x0D, 0x1B, 0x58, 0x19, 0xA0, 0x05, 0x38, 0xBC, 0x33, 0x60, 0x02}},
-         {5, 703,  644, {0x13, 0xF4, 0x1D, 0x14, 0x1C, 0x12, 0x64, 0x08, 0x38, 0xBF, 0x42, 0x60, 0x02}},
-         {3, 448,  410, {0x13, 0xF4, 0x3D, 0x0C, 0xC4, 0x0B, 0x0C, 0x0E, 0x38, 0xC0, 0x69, 0x60, 0x02}},
-      },
-      /* 20 fps */
-      {
-         {0, },
-         {9, 956,  650, {0x12, 0xF4, 0x1D, 0x14, 0x4A, 0x12, 0x92, 0x09, 0x48, 0xBC, 0x33, 0x10, 0x03}},
-         {6, 776,  528, {0x12, 0xF4, 0x2D, 0x10, 0x7E, 0x0E, 0xC6, 0x0A, 0x40, 0x08, 0x3F, 0x10, 0x03}},
-         {4, 591,  402, {0x12, 0xF4, 0x3D, 0x0C, 0x8F, 0x0A, 0xD7, 0x0E, 0x40, 0x4F, 0x4E, 0x10, 0x03}},
-      },
-      /* 25 fps */
-      {
-         {0, },
-         {9, 956,  544, {0x11, 0xF4, 0x25, 0x10, 0xF4, 0x0F, 0x3C, 0x0A, 0x48, 0xBC, 0x33, 0xC0, 0x02}},
-         {7, 840,  478, {0x11, 0xF4, 0x2D, 0x0E, 0xEB, 0x0D, 0x33, 0x0B, 0x48, 0x48, 0x3B, 0xC0, 0x02}},
-         {5, 703,  400, {0x11, 0xF4, 0x3D, 0x0C, 0x7A, 0x0A, 0xC2, 0x0E, 0x48, 0xBF, 0x42, 0xC0, 0x02}},
-      },
-      /* 30 fps */
-      {
-         {0, },
-         {9, 956,  438, {0x10, 0xF4, 0x35, 0x0D, 0xAC, 0x0B, 0xF4, 0x0D, 0x50, 0xBC, 0x33, 0x10, 0x02}},
-         {7, 838,  384, {0x10, 0xF4, 0x45, 0x0B, 0xFD, 0x0A, 0x45, 0x0F, 0x50, 0x46, 0x3B, 0x10, 0x02}},
-         {6, 773,  354, {0x10, 0x7A, 0x4B, 0x0B, 0x0C, 0x09, 0x80, 0x10, 0x50, 0x05, 0x3F, 0x10, 0x02}},
-      },
-   },
-   /* VGA */
-   {
-      /* 5 fps */
-      {
-         {0, },
-         {6, 773, 1272, {0x1D, 0xF4, 0x15, 0x27, 0xB6, 0x24, 0x96, 0x02, 0x30, 0x05, 0x3F, 0x10, 0x02}},
-         {4, 592,  976, {0x1D, 0xF4, 0x25, 0x1E, 0x78, 0x1B, 0x58, 0x03, 0x30, 0x50, 0x4E, 0x10, 0x02}},
-         {3, 448,  738, {0x1D, 0xF4, 0x3D, 0x17, 0x0C, 0x13, 0xEC, 0x04, 0x30, 0xC0, 0x69, 0x10, 0x02}},
-      },
-      /* 10 fps */
-      {
-         {0, },
-         {9, 956,  788, {0x1C, 0xF4, 0x35, 0x18, 0x9C, 0x15, 0x7C, 0x03, 0x48, 0xBC, 0x33, 0x10, 0x02}},
-         {6, 776,  640, {0x1C, 0x7A, 0x53, 0x13, 0xFC, 0x11, 0x2C, 0x04, 0x48, 0x08, 0x3F, 0x10, 0x02}},
-         {4, 592,  488, {0x1C, 0x7A, 0x6B, 0x0F, 0x3C, 0x0C, 0x6C, 0x06, 0x48, 0x50, 0x4E, 0x10, 0x02}},
-      },
-      /* 15 fps */
-      {
-         {0, },
-         {9, 957,  526, {0x1B, 0x7A, 0x63, 0x10, 0x68, 0x0D, 0x98, 0x06, 0x58, 0xBD, 0x33, 0x80, 0x02}},
-         {9, 957,  526, {0x1B, 0x7A, 0x63, 0x10, 0x68, 0x0D, 0x98, 0x06, 0x58, 0xBD, 0x33, 0x80, 0x02}},
-         {8, 895,  492, {0x1B, 0x7A, 0x6B, 0x0F, 0x5D, 0x0C, 0x8D, 0x06, 0x58, 0x7F, 0x37, 0x80, 0x02}},
-      },
-      /* 20 fps */
-      {
-         {0, },
-         {0, },
-         {0, },
-         {0, },
-      },
-      /* 25 fps */
-      {
-         {0, },
-         {0, },
-         {0, },
-         {0, },
-      },
-      /* 30 fps */
-      {
-         {0, },
-         {0, },
-         {0, },
-         {0, },
-      },
-   },
diff -Nru a/drivers/usb/media/se401.c b/drivers/usb/media/se401.c
--- a/drivers/usb/media/se401.c	2004-10-18 14:56:28 -07:00
+++ b/drivers/usb/media/se401.c	2004-10-18 14:56:28 -07:00
@@ -53,9 +53,9 @@
 MODULE_AUTHOR("Jeroen Vreeken <pe1rxq@amsat.org>");
 MODULE_DESCRIPTION("SE401 USB Camera Driver");
 MODULE_LICENSE("GPL");
-MODULE_PARM(flickerless, "i");
+module_param(flickerless, int, 0);
 MODULE_PARM_DESC(flickerless, "Net frequency to adjust exposure time to (0/50/60)");
-MODULE_PARM(video_nr, "i");
+module_param(video_nr, int, 0);
 
 static struct usb_driver se401_driver;
 
diff -Nru a/drivers/usb/media/sn9c102.h b/drivers/usb/media/sn9c102.h
--- a/drivers/usb/media/sn9c102.h	2004-10-18 14:56:31 -07:00
+++ b/drivers/usb/media/sn9c102.h	2004-10-18 14:56:31 -07:00
@@ -31,6 +31,7 @@
 #include <linux/types.h>
 #include <linux/param.h>
 #include <linux/rwsem.h>
+#include <asm/semaphore.h>
 
 #include "sn9c102_sensor.h"
 
@@ -39,6 +40,7 @@
 #define SN9C102_DEBUG
 #define SN9C102_DEBUG_LEVEL       2
 #define SN9C102_MAX_DEVICES       64
+#define SN9C102_PRESERVE_IMGSCALE 0
 #define SN9C102_MAX_FRAMES        32
 #define SN9C102_URBS              2
 #define SN9C102_ISO_PACKETS       7
@@ -51,8 +53,8 @@
 #define SN9C102_MODULE_AUTHOR   "(C) 2004 Luca Risolia"
 #define SN9C102_AUTHOR_EMAIL    "<luca.risolia@studio.unibo.it>"
 #define SN9C102_MODULE_LICENSE  "GPL"
-#define SN9C102_MODULE_VERSION  "1:1.01-beta"
-#define SN9C102_MODULE_VERSION_CODE  KERNEL_VERSION(1, 0, 1)
+#define SN9C102_MODULE_VERSION  "1:1.08"
+#define SN9C102_MODULE_VERSION_CODE  KERNEL_VERSION(1, 0, 8)
 
 SN9C102_ID_TABLE;
 SN9C102_SENSOR_TABLE;
diff -Nru a/drivers/usb/media/sn9c102_core.c b/drivers/usb/media/sn9c102_core.c
--- a/drivers/usb/media/sn9c102_core.c	2004-10-18 14:55:54 -07:00
+++ b/drivers/usb/media/sn9c102_core.c	2004-10-18 14:55:54 -07:00
@@ -31,6 +31,7 @@
 #include <linux/time.h>
 #include <linux/delay.h>
 #include <linux/stddef.h>
+#include <linux/compiler.h>
 #include <linux/ioctl.h>
 #include <linux/poll.h>
 #include <linux/stat.h>
@@ -83,7 +84,7 @@
 
 /*****************************************************************************/
 
-typedef char sn9c102_sof_header_t[7];
+typedef char sn9c102_sof_header_t[12];
 typedef char sn9c102_eof_header_t[4];
 
 static sn9c102_sof_header_t sn9c102_sof_header[] = {
@@ -91,8 +92,6 @@
 	{0xff, 0xff, 0x00, 0xc4, 0xc4, 0x96, 0x01},
 };
 
-/* Number of random bytes that complete the SOF above headers */
-#define SN9C102_SOFLEN 5
 
 static sn9c102_eof_header_t sn9c102_eof_header[] = {
 	{0x00, 0x00, 0x00, 0x00},
@@ -237,9 +236,6 @@
 	u8* buff = cam->control_buffer;
 	int res;
 
-	if (index == 0x18)
-		value = (value & 0xcf) | (cam->reg[0x18] & 0x30);
-
 	*buff = value;
 
 	res = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), 0x08, 0x41,
@@ -443,14 +439,15 @@
 
 static void* sn9c102_find_sof_header(void* mem, size_t len)
 {
-	size_t soflen=sizeof(sn9c102_sof_header_t), SOFLEN=SN9C102_SOFLEN, i;
+	size_t soflen = sizeof(sn9c102_sof_header_t), i;
 	u8 j, n = sizeof(sn9c102_sof_header) / soflen;
 
-	for (i = 0; (len >= soflen+SOFLEN) && (i <= len-soflen-SOFLEN); i++)
+	for (i = 0; (len >= soflen) && (i <= len - soflen); i++)
 		for (j = 0; j < n; j++)
-			if (!memcmp(mem + i, sn9c102_sof_header[j], soflen))
+			/* It's enough to compare 7 bytes */
+			if (!memcmp(mem + i, sn9c102_sof_header[j], 7))
 				/* Skips the header */
-				return mem + i + soflen + SOFLEN;
+				return mem + i + soflen;
 
 	return NULL;
 }
@@ -517,10 +514,12 @@
 
 		PDBGG("Isochrnous frame: length %u, #%u i", len, i)
 
-		/* NOTE: It is probably correct to assume that SOF and EOF
+		/*
+		   NOTE: It is probably correct to assume that SOF and EOF
 		         headers do not occur between two consecutive packets,
 		         but who knows..Whatever is the truth, this assumption
-		         doesn't introduce bugs. */
+		         doesn't introduce bugs.
+		*/
 
 redo:
 		sof = sn9c102_find_sof_header(pos, len);
@@ -764,9 +763,11 @@
 	return (u8)val;
 }
 
-/* NOTE 1: being inside one of the following methods implies that the v4l
+/*
+   NOTE 1: being inside one of the following methods implies that the v4l
            device exists for sure (see kobjects and reference counters)
-   NOTE 2: buffers are PAGE_SIZE long */
+   NOTE 2: buffers are PAGE_SIZE long
+*/
 
 static ssize_t sn9c102_show_reg(struct class_device* cd, char* buf)
 {
@@ -1019,24 +1020,6 @@
 
 
 static ssize_t
-sn9c102_store_redblue(struct class_device* cd, const char* buf, size_t len)
-{
-	ssize_t res = 0;
-	u8 value;
-	ssize_t count;
-
-	value = sn9c102_strtou8(buf, len, &count);
-	if (!count)
-		return -EINVAL;
-
-	if ((res = sn9c102_store_reg(cd, "0x10", 4)) >= 0)
-		res = sn9c102_store_val(cd, buf, len);
-
-	return res;
-}
-
-
-static ssize_t
 sn9c102_store_green(struct class_device* cd, const char* buf, size_t len)
 {
 	ssize_t res = 0;
@@ -1062,7 +1045,6 @@
                          sn9c102_show_i2c_reg, sn9c102_store_i2c_reg);
 static CLASS_DEVICE_ATTR(i2c_val, S_IRUGO | S_IWUSR,
                          sn9c102_show_i2c_val, sn9c102_store_i2c_val);
-static CLASS_DEVICE_ATTR(redblue, S_IWUGO, NULL, sn9c102_store_redblue);
 static CLASS_DEVICE_ATTR(green, S_IWUGO, NULL, sn9c102_store_green);
 
 
@@ -1072,7 +1054,6 @@
 
 	video_device_create_file(v4ldev, &class_device_attr_reg);
 	video_device_create_file(v4ldev, &class_device_attr_val);
-	video_device_create_file(v4ldev, &class_device_attr_redblue);
 	video_device_create_file(v4ldev, &class_device_attr_green);
 	if (cam->sensor->slave_write_id && cam->sensor->slave_read_id) {
 		video_device_create_file(v4ldev, &class_device_attr_i2c_reg);
@@ -1118,10 +1099,6 @@
 	   ae_endy = v_size / 2;
 	int err = 0;
 
-	/* These are a sort of stroboscopic signal for some sensors */
-	err += sn9c102_write_reg(cam, h_size, 0x1a);
-	err += sn9c102_write_reg(cam, v_size, 0x1b);
-
 	err += sn9c102_write_reg(cam, h_start, 0x12);
 	err += sn9c102_write_reg(cam, v_start, 0x13);
 	err += sn9c102_write_reg(cam, h_size, 0x15);
@@ -1134,8 +1111,7 @@
 		return -EIO;
 
 	PDBGG("h_start, v_start, h_size, v_size, ho_size, vo_size "
-	      "%u %u %u %u %u %u", h_start, v_start, h_size, v_size, ho_size,
-	      vo_size)
+	      "%u %u %u %u", h_start, v_start, h_size, v_size)
 
 	return 0;
 }
@@ -1229,7 +1205,10 @@
 	struct sn9c102_device* cam;
 	int err = 0;
 
-	/* This the only safe way to prevent race conditions with disconnect */
+	/*
+	   This is the only safe way to prevent race conditions with
+	   disconnect
+	*/
 	if (!down_read_trylock(&sn9c102_disconnect))
 		return -ERESTARTSYS;
 
@@ -1727,6 +1706,12 @@
 				return -EINVAL;
 			}
 
+		/* Preserve R,G or B origin */
+		rect->left = (s->_rect.left & 1L) ?
+		             rect->left | 1L : rect->left & ~1L;
+		rect->top = (s->_rect.top & 1L) ?
+		            rect->top | 1L : rect->top & ~1L;
+
 		if (rect->width < 16)
 			rect->width = 16;
 		if (rect->height < 16)
@@ -1747,13 +1732,15 @@
 		rect->width &= ~15L;
 		rect->height &= ~15L;
 
-		{ /* calculate the scaling factor */
+		if (SN9C102_PRESERVE_IMGSCALE) {
+			/* Calculate the actual scaling factor */
 			u32 a, b;
 			a = rect->width * rect->height;
 			b = pix_format->width * pix_format->height;
-			scale = b ? (u8)((a / b) <= 1 ? 1 : ((a / b) == 3 ? 2 :
-			            ((a / b) > 4 ? 4 : (a / b)))) : 1;
-		}
+			scale = b ? (u8)((a / b) < 4 ? 1 :
+		                        ((a / b) < 16 ? 2 : 4)) : 1;
+		} else
+			scale = 1;
 
 		if (cam->stream == STREAM_ON) {
 			cam->stream = STREAM_INTERRUPT;
@@ -1879,12 +1866,12 @@
 
 		memcpy(&rect, &(s->_rect), sizeof(rect));
 
-		{ /* calculate the scaling factor */
+		{ /* calculate the actual scaling factor */
 			u32 a, b;
 			a = rect.width * rect.height;
 			b = pix->width * pix->height;
-			scale = b ? (u8)((a / b) <= 1 ? 1 : ((a / b) == 3 ? 2 :
-			            ((a / b) > 4 ? 4 : (a / b)))) : 1;
+			scale = b ? (u8)((a / b) < 4 ? 1 :
+		                        ((a / b) < 16 ? 2 : 4)) : 1;
 		}
 
 		rect.width = scale * pix->width;
@@ -1895,13 +1882,21 @@
 		if (rect.height < 16)
 			rect.height = 16;
 		if (rect.width > bounds->left + bounds->width - rect.left)
-			rect.width = bounds->left+bounds->width - rect.left;
+			rect.width = bounds->left + bounds->width - rect.left;
 		if (rect.height > bounds->top + bounds->height - rect.top)
 			rect.height = bounds->top + bounds->height - rect.top;
 
 		rect.width &= ~15L;
 		rect.height &= ~15L;
 
+		{ /* adjust the scaling factor */
+			u32 a, b;
+			a = rect.width * rect.height;
+			b = pix->width * pix->height;
+			scale = b ? (u8)((a / b) < 4 ? 1 :
+		                        ((a / b) < 16 ? 2 : 4)) : 1;
+		}
+
 		pix->width = rect.width / scale;
 		pix->height = rect.height / scale;
 
@@ -2119,7 +2114,7 @@
 		spin_lock_irqsave(&cam->queue_lock, lock_flags);
 		f = list_entry(cam->outqueue.next, struct sn9c102_frame_t,
 		               frame);
-		list_del(&cam->outqueue);
+		list_del(cam->outqueue.next);
 		spin_unlock_irqrestore(&cam->queue_lock, lock_flags);
 
 		f->state = F_UNUSED;
diff -Nru a/drivers/usb/media/sn9c102_pas106b.c b/drivers/usb/media/sn9c102_pas106b.c
--- a/drivers/usb/media/sn9c102_pas106b.c	2004-10-18 14:55:54 -07:00
+++ b/drivers/usb/media/sn9c102_pas106b.c	2004-10-18 14:55:54 -07:00
@@ -40,13 +40,12 @@
 	err += sn9c102_i2c_write(cam, 0x02, 0x0c);
 	err += sn9c102_i2c_write(cam, 0x03, 0x12);
 	err += sn9c102_i2c_write(cam, 0x04, 0x05);
-	err += sn9c102_i2c_write(cam, 0x05, 0x22);
-	err += sn9c102_i2c_write(cam, 0x06, 0xac);
-	err += sn9c102_i2c_write(cam, 0x07, 0x00);
+	err += sn9c102_i2c_write(cam, 0x05, 0x5a);
+	err += sn9c102_i2c_write(cam, 0x06, 0x88);
+	err += sn9c102_i2c_write(cam, 0x07, 0x80);
 	err += sn9c102_i2c_write(cam, 0x08, 0x01);
-	err += sn9c102_i2c_write(cam, 0x0a, 0x00);
+	err += sn9c102_i2c_write(cam, 0x0a, 0x01);
 	err += sn9c102_i2c_write(cam, 0x0b, 0x00);
-	err += sn9c102_i2c_write(cam, 0x0d, 0x00);
 	err += sn9c102_i2c_write(cam, 0x10, 0x06);
 	err += sn9c102_i2c_write(cam, 0x11, 0x06);
 	err += sn9c102_i2c_write(cam, 0x12, 0x00);
@@ -64,11 +63,30 @@
 {
 	switch (ctrl->id) {
 	case V4L2_CID_RED_BALANCE:
-		return (ctrl->value = sn9c102_i2c_read(cam, 0x0c))<0 ? -EIO:0;
+		if ((ctrl->value = sn9c102_i2c_read(cam, 0x0c)) < 0)
+			return -EIO;
+		ctrl->value &= 0x1f;
+		return 0;
 	case V4L2_CID_BLUE_BALANCE:
-		return (ctrl->value = sn9c102_i2c_read(cam, 0x09))<0 ? -EIO:0;
+		if ((ctrl->value = sn9c102_i2c_read(cam, 0x09)) < 0)
+			return -EIO;
+		ctrl->value &= 0x1f;
+		return 0;
+	case V4L2_CID_GAIN:
+		if ((ctrl->value = sn9c102_i2c_read(cam, 0x0e)) < 0)
+			return -EIO;
+		ctrl->value &= 0x1f;
+		return 0;
 	case V4L2_CID_BRIGHTNESS:
-		return (ctrl->value = sn9c102_i2c_read(cam, 0x0e))<0 ? -EIO:0;
+		if ((ctrl->value = sn9c102_i2c_read(cam, 0x0d)) < 0)
+			return -EIO;
+		ctrl->value &= 0x1f;
+		return 0;
+	case V4L2_CID_CONTRAST:
+		if ((ctrl->value = sn9c102_i2c_read(cam, 0x0f)) < 0)
+			return -EIO;
+		ctrl->value &= 0x07;
+		return 0;
 	default:
 		return -EINVAL;
 	}
@@ -87,9 +105,15 @@
 	case V4L2_CID_BLUE_BALANCE:
 		err += sn9c102_i2c_write(cam, 0x09, ctrl->value & 0x1f);
 		break;
-	case V4L2_CID_BRIGHTNESS:
+	case V4L2_CID_GAIN:
 		err += sn9c102_i2c_write(cam, 0x0e, ctrl->value & 0x1f);
 		break;
+	case V4L2_CID_BRIGHTNESS:
+		err += sn9c102_i2c_write(cam, 0x0d, 0x1f-(ctrl->value & 0x1f));
+		break;
+	case V4L2_CID_CONTRAST:
+		err += sn9c102_i2c_write(cam, 0x0f, ctrl->value & 0x03);
+		break;
 	default:
 		return -EINVAL;
 	}
@@ -130,7 +154,7 @@
 			.minimum = 0x00,
 			.maximum = 0x1f,
 			.step = 0x01,
-			.default_value = 0x03,
+			.default_value = 0x04,
 			.flags = 0,
 		},
 		{
@@ -140,7 +164,17 @@
 			.minimum = 0x00,
 			.maximum = 0x1f,
 			.step = 0x01,
-			.default_value = 0x02,
+			.default_value = 0x06,
+			.flags = 0,
+		},
+		{
+			.id = V4L2_CID_GAIN,
+			.type = V4L2_CTRL_TYPE_INTEGER,
+			.name = "global gain",
+			.minimum = 0x00,
+			.maximum = 0x1f,
+			.step = 0x01,
+			.default_value = 0x0d,
 			.flags = 0,
 		},
 		{
@@ -150,7 +184,17 @@
 			.minimum = 0x00,
 			.maximum = 0x1f,
 			.step = 0x01,
-			.default_value = 0x06,
+			.default_value = 0x1f,
+			.flags = 0,
+		},
+		{
+			.id = V4L2_CID_CONTRAST,
+			.type = V4L2_CTRL_TYPE_INTEGER,
+			.name = "contrast",
+			.minimum = 0x00,
+			.maximum = 0x07,
+			.step = 0x01,
+			.default_value = 0x00, /* 0x00~0x03 have same effect */
 			.flags = 0,
 		},
 	},
@@ -185,11 +229,13 @@
 	int r0 = 0, r1 = 0, err = 0;
 	unsigned int pid = 0;
 
-	/* Minimal initialization to enable the I2C communication
-	   NOTE: do NOT change the values! */
+	/*
+	   Minimal initialization to enable the I2C communication
+	   NOTE: do NOT change the values!
+	*/
 	err += sn9c102_write_reg(cam, 0x01, 0x01); /* sensor power down */
 	err += sn9c102_write_reg(cam, 0x00, 0x01); /* sensor power on */
-	err += sn9c102_write_reg(cam, 0x28, 0x17); /* sensor clock at 48 MHz */
+	err += sn9c102_write_reg(cam, 0x28, 0x17); /* sensor clock at 24 MHz */
 	if (err)
 		return -EIO;
 
diff -Nru a/drivers/usb/media/sn9c102_pas202bcb.c b/drivers/usb/media/sn9c102_pas202bcb.c
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/drivers/usb/media/sn9c102_pas202bcb.c	2004-10-18 14:57:24 -07:00
@@ -0,0 +1,238 @@
+/***************************************************************************
+ * Driver for PAS202BCB image sensor connected to the SN9C10[12] PC Camera *
+ * Controllers                                                             *
+ *                                                                         *
+ * Copyright (C) 2004 by Carlos Eduardo Medaglia Dyonisio                  *
+ *                       <medaglia@undl.org.br>                            *
+ *                       http://cadu.homelinux.com:8080/                   *
+ *                                                                         *
+ * 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.               *
+ ***************************************************************************/
+
+#include <linux/delay.h>
+#include "sn9c102_sensor.h"
+
+
+static struct sn9c102_sensor pas202bcb;
+
+
+static int pas202bcb_init(struct sn9c102_device* cam)
+{
+	int err = 0;
+
+	err += sn9c102_write_reg(cam, 0x00, 0x10);
+	err += sn9c102_write_reg(cam, 0x00, 0x11);
+	err += sn9c102_write_reg(cam, 0x00, 0x14);
+	err += sn9c102_write_reg(cam, 0x20, 0x17);
+	err += sn9c102_write_reg(cam, 0x20, 0x19);
+	err += sn9c102_write_reg(cam, 0x09, 0x18);
+
+	err += sn9c102_i2c_write(cam, 0x02, 0x0c);
+	err += sn9c102_i2c_write(cam, 0x03, 0x40);
+	err += sn9c102_i2c_write(cam, 0x04, 0x07);
+	err += sn9c102_i2c_write(cam, 0x05, 0x25);
+	err += sn9c102_i2c_write(cam, 0x0d, 0x2c);
+	err += sn9c102_i2c_write(cam, 0x0e, 0x01);
+	err += sn9c102_i2c_write(cam, 0x0f, 0xa9);
+	err += sn9c102_i2c_write(cam, 0x08, 0x01);
+	err += sn9c102_i2c_write(cam, 0x0b, 0x01);
+	err += sn9c102_i2c_write(cam, 0x13, 0x63);
+	err += sn9c102_i2c_write(cam, 0x15, 0x70);
+	err += sn9c102_i2c_write(cam, 0x11, 0x01);
+
+	msleep(400);
+
+	return err;
+}
+
+
+static int pas202bcb_get_ctrl(struct sn9c102_device* cam, 
+                              struct v4l2_control* ctrl)
+{
+	switch (ctrl->id) {
+	case V4L2_CID_RED_BALANCE:
+		if ((ctrl->value = sn9c102_i2c_read(cam, 0x09)) < 0)
+			return -EIO;
+		ctrl->value &= 0x0f;
+		return 0;
+	case V4L2_CID_BLUE_BALANCE:
+		if ((ctrl->value = sn9c102_i2c_read(cam, 0x07)) < 0)
+			return -EIO;
+		ctrl->value &= 0x0f;
+		return 0;
+	case V4L2_CID_GAIN:
+		if ((ctrl->value = sn9c102_i2c_read(cam, 0x10)) < 0)
+			return -EIO;
+		ctrl->value &= 0x1f;
+		return 0;
+	case V4L2_CID_BRIGHTNESS:
+		if ((ctrl->value = sn9c102_i2c_read(cam, 0x06)) < 0)
+			return -EIO;
+		ctrl->value &= 0x0f;
+		return 0;
+	default:
+		return -EINVAL;
+	}
+}
+
+
+static int pas202bcb_set_ctrl(struct sn9c102_device* cam, 
+                              const struct v4l2_control* ctrl)
+{
+	int err = 0;
+
+	switch (ctrl->id) {
+	case V4L2_CID_RED_BALANCE:
+		err += sn9c102_i2c_write(cam, 0x09, ctrl->value & 0x0f);
+		break;
+	case V4L2_CID_BLUE_BALANCE:
+		err += sn9c102_i2c_write(cam, 0x07, ctrl->value & 0x0f);
+		break;
+	case V4L2_CID_GAIN:
+		err += sn9c102_i2c_write(cam, 0x10, ctrl->value & 0x1f);
+		break;
+	case V4L2_CID_BRIGHTNESS:
+		err += sn9c102_i2c_write(cam, 0x06, 0x0f-(ctrl->value & 0x0f));
+		break;
+	default:
+		return -EINVAL;
+	}
+	err += sn9c102_i2c_write(cam, 0x11, 0x01);
+
+	return err;
+}
+
+
+static int pas202bcb_set_crop(struct sn9c102_device* cam, 
+                              const struct v4l2_rect* rect)
+{
+	struct sn9c102_sensor* s = &pas202bcb;
+	int err = 0;
+	u8 h_start = (u8)(rect->left - s->cropcap.bounds.left) + 4,
+	   v_start = (u8)(rect->top - s->cropcap.bounds.top) + 3;
+
+	err += sn9c102_write_reg(cam, h_start, 0x12);
+	err += sn9c102_write_reg(cam, v_start, 0x13);
+
+	return err;
+}
+
+
+static struct sn9c102_sensor pas202bcb = {
+	.name = "PAS202BCB",
+	.maintainer = "Carlos Eduardo Medaglia Dyonisio "
+	              "<medaglia@undl.org.br>",
+	.frequency = SN9C102_I2C_400KHZ | SN9C102_I2C_100KHZ,
+	.interface = SN9C102_I2C_2WIRES,
+	.slave_read_id = 0x40,
+	.slave_write_id = 0x40,
+	.init = &pas202bcb_init,
+	.qctrl = {
+		{
+			.id = V4L2_CID_RED_BALANCE,
+			.type = V4L2_CTRL_TYPE_INTEGER,
+			.name = "red balance",
+			.minimum = 0x00,
+			.maximum = 0x0f,
+			.step = 0x01,
+			.default_value = 0x01,
+			.flags = 0,
+		},
+		{
+			.id = V4L2_CID_BLUE_BALANCE,
+			.type = V4L2_CTRL_TYPE_INTEGER,
+			.name = "blue balance",
+			.minimum = 0x00,
+			.maximum = 0x0f,
+			.step = 0x01,
+			.default_value = 0x05,
+			.flags = 0,
+		},
+		{
+			.id = V4L2_CID_GAIN,
+			.type = V4L2_CTRL_TYPE_INTEGER,
+			.name = "global gain",
+			.minimum = 0x00,
+			.maximum = 0x1f,
+			.step = 0x01,
+			.default_value = 0x0c,
+			.flags = 0,
+		},
+		{
+			.id = V4L2_CID_BRIGHTNESS,
+			.type = V4L2_CTRL_TYPE_INTEGER,
+			.name = "brightness",
+			.minimum = 0x00,
+			.maximum = 0x0f,
+			.step = 0x01,
+			.default_value = 0x0f,
+			.flags = 0,
+		},
+	},
+	.get_ctrl = &pas202bcb_get_ctrl,
+	.set_ctrl = &pas202bcb_set_ctrl,
+	.cropcap = {
+		.bounds = {
+			.left = 0,
+			.top = 0,
+			.width = 640,
+			.height = 480,
+		},
+		.defrect = {
+			.left = 0,
+			.top = 0,
+			.width = 640,
+			.height = 480,
+		},
+	},
+	.set_crop = &pas202bcb_set_crop,
+	.pix_format = {
+		.width = 640,
+		.height = 480,
+		.pixelformat = V4L2_PIX_FMT_SBGGR8,
+		.priv = 8,
+	}
+};
+
+
+int sn9c102_probe_pas202bcb(struct sn9c102_device* cam)
+{       
+	int r0 = 0, r1 = 0, err = 0;
+	unsigned int pid = 0;
+
+	/*
+	 *  Minimal initialization to enable the I2C communication
+	 *  NOTE: do NOT change the values!
+	 */
+	err += sn9c102_write_reg(cam, 0x01, 0x01); /* sensor power down */
+	err += sn9c102_write_reg(cam, 0x00, 0x01); /* sensor power on */
+	err += sn9c102_write_reg(cam, 0x28, 0x17); /* sensor clock at 24 MHz */
+	if (err)
+		return -EIO;
+
+	r0 = sn9c102_i2c_try_read(cam, &pas202bcb, 0x00);
+	r1 = sn9c102_i2c_try_read(cam, &pas202bcb, 0x01);
+	
+	if (r0 < 0 || r1 < 0)
+		return -EIO;
+
+	pid = (r0 << 4) | ((r1 & 0xf0) >> 4);
+	if (pid != 0x017)
+		return -ENODEV;
+
+	sn9c102_attach_sensor(cam, &pas202bcb);
+
+	return 0;
+}
diff -Nru a/drivers/usb/media/sn9c102_sensor.h b/drivers/usb/media/sn9c102_sensor.h
--- a/drivers/usb/media/sn9c102_sensor.h	2004-10-18 14:56:27 -07:00
+++ b/drivers/usb/media/sn9c102_sensor.h	2004-10-18 14:56:27 -07:00
@@ -33,7 +33,8 @@
 
 /*****************************************************************************/
 
-/* OVERVIEW.
+/*
+   OVERVIEW.
    This is a small interface that allows you to add support for any CCD/CMOS
    image sensors connected to the SN9C10X bridges. The entire API is documented
    below. In the most general case, to support a sensor there are three steps
@@ -48,26 +49,33 @@
    "sn9c102_pas106b.c" is an example of all this stuff. Remember that you do
    NOT need to touch the source code of the core module for the things to work
    properly, unless you find bugs or flaws in it. Finally, do not forget to
-   read the V4L2 API for completeness. */
+   read the V4L2 API for completeness.
+*/
 
 /*****************************************************************************/
- 
-/* Probing functions: on success, you must attach the sensor to the camera
+
+/*
+   Probing functions: on success, you must attach the sensor to the camera
    by calling sn9c102_attach_sensor() provided below.
    To enable the I2C communication, you might need to perform a really basic
    initialization of the SN9C10X chip by using the write function declared 
    ahead.
-   Functions must return 0 on success, the appropriate error otherwise. */
+   Functions must return 0 on success, the appropriate error otherwise.
+*/
 extern int sn9c102_probe_pas106b(struct sn9c102_device* cam);
+extern int sn9c102_probe_pas202bcb(struct sn9c102_device* cam);
 extern int sn9c102_probe_tas5110c1b(struct sn9c102_device* cam);
 extern int sn9c102_probe_tas5130d1b(struct sn9c102_device* cam);
 
-/* Add the above entries to this table. Be sure to add the entry in the right
+/*
+   Add the above entries to this table. Be sure to add the entry in the right
    place, since, on failure, the next probing routine is called according to 
-   the order of the list below, from top to bottom */
+   the order of the list below, from top to bottom.
+*/
 #define SN9C102_SENSOR_TABLE                                                  \
 static int (*sn9c102_sensor_table[])(struct sn9c102_device*) = {              \
-	&sn9c102_probe_pas106b, /* strong detection based on SENSOR vid/pid */\
+	&sn9c102_probe_pas106b, /* strong detection based on SENSOR ids */    \
+	&sn9c102_probe_pas202bcb, /* strong detection based on SENSOR ids */  \
 	&sn9c102_probe_tas5110c1b, /* detection based on USB pid/vid */       \
 	&sn9c102_probe_tas5130d1b, /* detection based on USB pid/vid */       \
 	NULL,                                                                 \
@@ -81,28 +89,29 @@
 /* Each SN9C10X camera has proper PID/VID identifiers. Add them here in case.*/
 #define SN9C102_ID_TABLE                                                      \
 static const struct usb_device_id sn9c102_id_table[] = {                      \
-	{ USB_DEVICE(0xc45, 0x6001), },                                       \
+	{ USB_DEVICE(0xc45, 0x6001), }, /* TAS5110C1B */                      \
 	{ USB_DEVICE(0xc45, 0x6005), }, /* TAS5110C1B */                      \
 	{ USB_DEVICE(0xc45, 0x6009), }, /* PAS106B */                         \
 	{ USB_DEVICE(0xc45, 0x600d), }, /* PAS106B */                         \
 	{ USB_DEVICE(0xc45, 0x6024), },                                       \
-	{ USB_DEVICE(0xc45, 0x6025), }, /* TAS5130D1B Maybe also TAS5110C1B */\
-	{ USB_DEVICE(0xc45, 0x6028), }, /* Maybe PAS202B */                   \
-	{ USB_DEVICE(0xc45, 0x6029), },                                       \
-	{ USB_DEVICE(0xc45, 0x602a), }, /* Maybe HV7131[D|E1] */              \
-	{ USB_DEVICE(0xc45, 0x602c), }, /* Maybe OV7620 */                    \
-	{ USB_DEVICE(0xc45, 0x6030), }, /* Maybe MI03 */                      \
-	{ USB_DEVICE(0xc45, 0x8001), },                                       \
+	{ USB_DEVICE(0xc45, 0x6025), }, /* TAS5130D1B and TAS5110C1B */       \
+	{ USB_DEVICE(0xc45, 0x6028), }, /* PAS202BCB */                       \
+	{ USB_DEVICE(0xc45, 0x6029), }, /* PAS106B */                         \
+	{ USB_DEVICE(0xc45, 0x602a), }, /* HV7131[D|E1] */                    \
+	{ USB_DEVICE(0xc45, 0x602c), }, /* OV7620 */                          \
+	{ USB_DEVICE(0xc45, 0x6030), }, /* MI03 */                            \
 	{ }                                                                   \
 };
 
 /*****************************************************************************/
 
-/* Read/write routines: they always return -1 on error, 0 or the read value
+/*
+   Read/write routines: they always return -1 on error, 0 or the read value
    otherwise. NOTE that a real read operation is not supported by the SN9C10X
    chip for some of its registers. To work around this problem, a pseudo-read
    call is provided instead: it returns the last successfully written value 
-   on the register (0 if it has never been written), the usual -1 on error. */
+   on the register (0 if it has never been written), the usual -1 on error.
+*/
 
 /* The "try" I2C I/O versions are used when probing the sensor */
 extern int sn9c102_i2c_try_write(struct sn9c102_device*,struct sn9c102_sensor*,
@@ -110,10 +119,12 @@
 extern int sn9c102_i2c_try_read(struct sn9c102_device*,struct sn9c102_sensor*,
                                 u8 address);
 
-/* This must be used if and only if the sensor doesn't implement the standard
-   I2C protocol, like the TASC sensors. There a number of good reasons why you
-   must use the single-byte versions of this function: do not abuse. It writes
-   n bytes, from data0 to datan, (registers 0x09 - 0x09+n of SN9C10X chip) */
+/*
+   This must be used if and only if the sensor doesn't implement the standard
+   I2C protocol. There a number of good reasons why you must use the 
+   single-byte versions of this function: do not abuse. It writes n bytes, 
+   from data0 to datan, (registers 0x09 - 0x09+n of SN9C10X chip).
+*/
 extern int sn9c102_i2c_try_raw_write(struct sn9c102_device* cam,
                                      struct sn9c102_sensor* sensor, u8 n, 
                                      u8 data0, u8 data1, u8 data2, u8 data3,
@@ -127,12 +138,14 @@
 extern int sn9c102_write_reg(struct sn9c102_device*, u8 value, u16 index);
 extern int sn9c102_pread_reg(struct sn9c102_device*, u16 index);
 
-/* NOTE: there are no debugging functions here. To uniform the output you must
+/*
+   NOTE: there are no debugging functions here. To uniform the output you must
    use the dev_info()/dev_warn()/dev_err() macros defined in device.h, already
    included here, the argument being the struct device 'dev' of the sensor
    structure. Do NOT use these macros before the sensor is attached or the
    kernel will crash! However you should not need to notify the user about
-   common errors or other messages, since this is done by the master module. */
+   common errors or other messages, since this is done by the master module.
+*/
 
 /*****************************************************************************/
 
@@ -150,24 +163,31 @@
 	char name[32], /* sensor name */
 	     maintainer[64]; /* name of the mantainer <email> */
 
-	/* These sensor capabilities must be provided if the SN9C10X controller
+	/*
+	   These sensor capabilities must be provided if the SN9C10X controller
 	   needs to communicate through the sensor serial interface by using
-	   at least one of the i2c functions available */
+	   at least one of the i2c functions available.
+	*/
 	enum sn9c102_i2c_frequency frequency;
 	enum sn9c102_i2c_interface interface;
 
-	/* These identifiers must be provided if the image sensor implements
+	/*
+	   These identifiers must be provided if the image sensor implements
 	   the standard I2C protocol. TASC sensors don't, although they have a
 	   serial interface: so this is a case where the "raw" I2C version
-	   could be helpful. */
+	   could be helpful.
+	*/
 	u8 slave_read_id, slave_write_id; /* reg. 0x09 */
 
-	/* NOTE: Where not noted,most of the functions below are not mandatory.
+	/*
+	   NOTE: Where not noted,most of the functions below are not mandatory.
 	         Set to null if you do not implement them. If implemented,
-	         they must return 0 on success, the proper error otherwise. */
+	         they must return 0 on success, the proper error otherwise.
+	*/
 
 	int (*init)(struct sn9c102_device* cam);
-	/* This function is called after the sensor has been attached. 
+	/*
+	   This function is called after the sensor has been attached. 
 	   It should be used to initialize the sensor only, but may also
 	   configure part of the SN9C10X chip if necessary. You don't need to
 	   setup picture settings like brightness, contrast, etc.. here, if
@@ -177,23 +197,29 @@
 	   specified in the v4l2_queryctrl list of supported controls;
 	   Same suggestions apply for other settings, _if_ the corresponding
 	   methods are present; if not, the initialization must configure the
-	   sensor according to the default configuration structures below. */
+	   sensor according to the default configuration structures below.
+	*/
 
 	struct v4l2_queryctrl qctrl[V4L2_CID_LASTP1-V4L2_CID_BASE];
-	/* Optional list of default controls, defined as indicated in the 
-	   V4L2 API. Menu type controls are not handled by this interface. */
+	/*
+	   Optional list of default controls, defined as indicated in the 
+	   V4L2 API. Menu type controls are not handled by this interface.
+	*/
 
 	int (*get_ctrl)(struct sn9c102_device* cam, struct v4l2_control* ctrl);
 	int (*set_ctrl)(struct sn9c102_device* cam,
 	                const struct v4l2_control* ctrl);
-	/* You must implement at least the set_ctrl method if you have defined
+	/*
+	   You must implement at least the set_ctrl method if you have defined
 	   the list above. The returned value must follow the V4L2
 	   specifications for the VIDIOC_G|C_CTRL ioctls. V4L2_CID_H|VCENTER
 	   are not supported by this driver, so do not implement them. Also,
-	   passed values are NOT checked to see if they are out of bounds. */
+	   passed values are NOT checked to see if they are out of bounds.
+	*/
 
 	struct v4l2_cropcap cropcap;
-	/* Think the image sensor as a grid of R,G,B monochromatic pixels
+	/*
+	   Think the image sensor as a grid of R,G,B monochromatic pixels
 	   disposed according to a particular Bayer pattern, which describes
 	   the complete array of pixels, from (0,0) to (xmax, ymax). We will
 	   use this coordinate system from now on. It is assumed the sensor
@@ -221,11 +247,13 @@
 	   NOTE: once you have defined the bounds of the active window
 	         (struct cropcap.bounds) you must not change them.anymore.
 	   Only 'bounds' and 'defrect' fields are mandatory, other fields
-	   will be ignored. */
+	   will be ignored.
+	*/
 
 	int (*set_crop)(struct sn9c102_device* cam,
 	                const struct v4l2_rect* rect);
-	/* To be called on VIDIOC_C_SETCROP. The core module always calls a
+	/*
+	   To be called on VIDIOC_C_SETCROP. The core module always calls a
 	   default routine which configures the appropriate SN9C10X regs (also
 	   scaling), but you may need to override/adjust specific stuff.
 	   'rect' contains width and height values that are multiple of 16: in
@@ -237,10 +265,12 @@
 	         frame after each HSYNC or VSYNC, so that the image starts with
 	         real RGB data (see regs 0x12,0x13) (having set H_SIZE and,
 	         V_SIZE you don't have to care about blank pixels or blank
-	         lines at the end of each line or frame). */
+	         lines at the end of each line or frame).
+	*/
 
 	struct v4l2_pix_format pix_format;
-	/* What you have to define here are: initial 'width' and 'height' of
+	/*
+	   What you have to define here are: initial 'width' and 'height' of
 	   the target rectangle, the bayer 'pixelformat' and 'priv' which we'll
 	   be used to indicate the number of bits per pixel, 8 or 9. 
 	   Nothing more.
@@ -249,20 +279,27 @@
 	           suggest 1/1.
 	   NOTE 2: as said above, you have to program the SN9C10X chip to get
 	           rid of any blank pixels, so that the output of the sensor
-	           matches the RGB bayer sequence (i.e. BGBGBG...GRGRGR). */
+	           matches the RGB bayer sequence (i.e. BGBGBG...GRGRGR).
+	*/
 
 	const struct device* dev;
-	/* This is the argument for dev_err(), dev_info() and dev_warn(). It
+	/*
+	   This is the argument for dev_err(), dev_info() and dev_warn(). It
 	   is used for debugging purposes. You must not access the struct
-	   before the sensor is attached. */
+	   before the sensor is attached.
+	*/
 
 	const struct usb_device* usbdev;
-	/* Points to the usb_device struct after the sensor is attached.
-	   Do not touch unless you know what you are doing. */
+	/*
+	   Points to the usb_device struct after the sensor is attached.
+	   Do not touch unless you know what you are doing.
+	*/
 
-	/* Do NOT write to the data below, it's READ ONLY. It is used by the
+	/*
+	   Do NOT write to the data below, it's READ ONLY. It is used by the
 	   core module to store successfully updated values of the above
-	   settings, for rollbacks..etc..in case of errors during atomic I/O */
+	   settings, for rollbacks..etc..in case of errors during atomic I/O
+	*/
 	struct v4l2_queryctrl _qctrl[V4L2_CID_LASTP1-V4L2_CID_BASE];
 	struct v4l2_rect _rect;
 };
diff -Nru a/drivers/usb/media/sn9c102_tas5110c1b.c b/drivers/usb/media/sn9c102_tas5110c1b.c
--- a/drivers/usb/media/sn9c102_tas5110c1b.c	2004-10-18 14:55:46 -07:00
+++ b/drivers/usb/media/sn9c102_tas5110c1b.c	2004-10-18 14:55:46 -07:00
@@ -33,15 +33,33 @@
 	err += sn9c102_write_reg(cam, 0x44, 0x01);
 	err += sn9c102_write_reg(cam, 0x00, 0x10);
 	err += sn9c102_write_reg(cam, 0x00, 0x11);
-	err += sn9c102_write_reg(cam, 0x00, 0x14);
+	err += sn9c102_write_reg(cam, 0x0a, 0x14);
 	err += sn9c102_write_reg(cam, 0x60, 0x17);
 	err += sn9c102_write_reg(cam, 0x06, 0x18);
-	err += sn9c102_write_reg(cam, 0xcb, 0x19);
+	err += sn9c102_write_reg(cam, 0xfb, 0x19);
+
+	err += sn9c102_i2c_try_raw_write(cam, &tas5110c1b, 4, 0x11, 0x00, 0xc0,
+	                                 0x80, 0, 0);
 
 	return err;
 }
 
 
+static int tas5110c1b_set_ctrl(struct sn9c102_device* cam, 
+                               const struct v4l2_control* ctrl)
+{
+	switch (ctrl->id) {
+	case V4L2_CID_GAIN:
+		return sn9c102_i2c_try_raw_write(cam, &tas5110c1b, 4, 0x11,
+		                                 0x02, 0x20,
+		                                 0xff - (ctrl->value & 0xff),
+		                                 0, 0);
+	default:
+		return -EINVAL;
+	}
+}
+
+
 static int tas5110c1b_set_crop(struct sn9c102_device* cam, 
                                const struct v4l2_rect* rect)
 {
@@ -53,6 +71,11 @@
 	err += sn9c102_write_reg(cam, h_start, 0x12);
 	err += sn9c102_write_reg(cam, v_start, 0x13);
 
+	/* Don't change ! */
+	err += sn9c102_write_reg(cam, 0x14, 0x1a);
+	err += sn9c102_write_reg(cam, 0x0a, 0x1b);
+	err += sn9c102_write_reg(cam, 0xfb, 0x19);
+
 	return err;
 }
 
@@ -60,7 +83,22 @@
 static struct sn9c102_sensor tas5110c1b = {
 	.name = "TAS5110C1B",
 	.maintainer = "Luca Risolia <luca.risolia@studio.unibo.it>",
+	.frequency = SN9C102_I2C_100KHZ,
+	.interface = SN9C102_I2C_3WIRES,
 	.init = &tas5110c1b_init,
+	.qctrl = {
+		{
+			.id = V4L2_CID_GAIN,
+			.type = V4L2_CTRL_TYPE_INTEGER,
+			.name = "global gain",
+			.minimum = 0x00,
+			.maximum = 0xff,
+			.step = 0x01,
+			.default_value = 0x48,
+			.flags = 0,
+		},
+	},
+	.set_ctrl = &tas5110c1b_set_ctrl,
 	.cropcap = {
 		.bounds = {
 			.left = 0,
@@ -90,8 +128,9 @@
 	/* This sensor has no identifiers, so let's attach it anyway */
 	sn9c102_attach_sensor(cam, &tas5110c1b);
 
-	/* At the moment, only devices whose PID is 0x6005 have this sensor */
-	if (tas5110c1b.usbdev->descriptor.idProduct != 0x6005)
+	/* At the moment, sensor detection is based on USB pid/vid */
+	if (tas5110c1b.usbdev->descriptor.idProduct != 0x6001 &&
+	    tas5110c1b.usbdev->descriptor.idProduct != 0x6005)
 		return -ENODEV;
 
 	return 0;
diff -Nru a/drivers/usb/media/sn9c102_tas5130d1b.c b/drivers/usb/media/sn9c102_tas5130d1b.c
--- a/drivers/usb/media/sn9c102_tas5130d1b.c	2004-10-18 14:56:32 -07:00
+++ b/drivers/usb/media/sn9c102_tas5130d1b.c	2004-10-18 14:56:32 -07:00
@@ -37,38 +37,45 @@
 	err += sn9c102_write_reg(cam, 0x00, 0x14);
 	err += sn9c102_write_reg(cam, 0x60, 0x17);
 	err += sn9c102_write_reg(cam, 0x07, 0x18);
-	err += sn9c102_write_reg(cam, 0x33, 0x19);
 
 	err += sn9c102_i2c_try_raw_write(cam, &tas5130d1b, 4, 0x11, 0x00, 0x40,
 	                                 0x47, 0, 0);
-	err += sn9c102_i2c_try_raw_write(cam, &tas5130d1b, 4, 0x11, 0x02, 0x20,
-	                                 0xa9, 0, 0);
-	err += sn9c102_i2c_try_raw_write(cam, &tas5130d1b, 4, 0x11, 0x00, 0xc0,
-	                                 0x49, 0, 0);
-	err += sn9c102_i2c_try_raw_write(cam, &tas5130d1b, 4, 0x11, 0x02, 0x20,
-	                                 0x6c, 0, 0);
-	err += sn9c102_i2c_try_raw_write(cam, &tas5130d1b, 4, 0x11, 0x00, 0xc0,
-	                                 0x08, 0, 0);
-	err += sn9c102_i2c_try_raw_write(cam, &tas5130d1b, 4, 0x11, 0x00, 0x20,
-	                                 0x00, 0, 0);
-
-	err += sn9c102_write_reg(cam, 0x63, 0x19);
 
 	return err;
 }
 
 
+static int tas5130d1b_set_ctrl(struct sn9c102_device* cam, 
+                               const struct v4l2_control* ctrl)
+{
+	switch (ctrl->id) {
+	case V4L2_CID_GAIN:
+		return sn9c102_i2c_try_raw_write(cam, &tas5130d1b, 4, 0x11,
+		                                 0x02, 0x20,
+		                                 0xff - (ctrl->value & 0xff),
+		                                 0, 0);
+	default:
+		return -EINVAL;
+	}
+}
+
+
 static int tas5130d1b_set_crop(struct sn9c102_device* cam, 
                                const struct v4l2_rect* rect)
 {
 	struct sn9c102_sensor* s = &tas5130d1b;
-	int err = 0;
 	u8 h_start = (u8)(rect->left - s->cropcap.bounds.left) + 104,
 	   v_start = (u8)(rect->top - s->cropcap.bounds.top) + 12;
+	int err = 0;
 
 	err += sn9c102_write_reg(cam, h_start, 0x12);
 	err += sn9c102_write_reg(cam, v_start, 0x13);
 
+	/* Do NOT change! */
+	err += sn9c102_write_reg(cam, 0x1d, 0x1a);
+	err += sn9c102_write_reg(cam, 0x10, 0x1b);
+	err += sn9c102_write_reg(cam, 0xf3, 0x19);
+
 	return err;
 }
 
@@ -79,6 +86,19 @@
 	.frequency = SN9C102_I2C_100KHZ,
 	.interface = SN9C102_I2C_3WIRES,
 	.init = &tas5130d1b_init,
+	.qctrl = {
+		{
+			.id = V4L2_CID_GAIN,
+			.type = V4L2_CTRL_TYPE_INTEGER,
+			.name = "global gain",
+			.minimum = 0x00,
+			.maximum = 0xff,
+			.step = 0x01,
+			.default_value = 0x00,
+			.flags = 0,
+		},
+	},
+	.set_ctrl = &tas5130d1b_set_ctrl,
 	.cropcap = {
 		.bounds = {
 			.left = 0,
@@ -108,13 +128,9 @@
 	/* This sensor has no identifiers, so let's attach it anyway */
 	sn9c102_attach_sensor(cam, &tas5130d1b);
 
-	/* At the moment, only devices whose PID is 0x6025 have this sensor */
+	/* At the moment, sensor detection is based on USB pid/vid */
 	if (tas5130d1b.usbdev->descriptor.idProduct != 0x6025)
 		return -ENODEV;
 
-	dev_info(tas5130d1b.dev, "TAS5130D1B detected, but the support for it "
-	                         "is disabled at the moment - needs further "
-	                         "testing -\n");
-
-	return -ENODEV;
+	return 0;
 }
diff -Nru a/drivers/usb/media/stv680.c b/drivers/usb/media/stv680.c
--- a/drivers/usb/media/stv680.c	2004-10-18 14:56:48 -07:00
+++ b/drivers/usb/media/stv680.c	2004-10-18 14:56:48 -07:00
@@ -93,11 +93,11 @@
 MODULE_AUTHOR (DRIVER_AUTHOR);
 MODULE_DESCRIPTION (DRIVER_DESC);
 MODULE_LICENSE ("GPL");
-MODULE_PARM (debug, "i");
+module_param(debug, int, S_IRUGO | S_IWUSR);
 MODULE_PARM_DESC (debug, "Debug enabled or not");
-MODULE_PARM (swapRGB_on, "i");
+module_param(swapRGB_on, int, 0);
 MODULE_PARM_DESC (swapRGB_on, "Red/blue swap: 1=always, 0=auto, -1=never");
-MODULE_PARM (video_nr, "i");
+module_param(video_nr, int, 0);
 
 /********************************************************************
  *
@@ -704,7 +704,6 @@
 				   usb_rcvbulkpipe (stv680->udev, stv680->bulk_in_endpointAddr),
 				   stv680->sbuf[i].data, stv680->rawbufsize,
 				   stv680_video_irq, stv680);
-		urb->timeout = PENCAM_TIMEOUT * 2;
 		stv680->urb[i] = urb;
 		err = usb_submit_urb (stv680->urb[i], GFP_KERNEL);
 		if (err)
diff -Nru a/drivers/usb/media/ultracam.c b/drivers/usb/media/ultracam.c
--- a/drivers/usb/media/ultracam.c	2004-10-18 14:56:17 -07:00
+++ b/drivers/usb/media/ultracam.c	2004-10-18 14:56:17 -07:00
@@ -60,9 +60,9 @@
 static int init_hue = 128;
 static int hue_correction = 128;
 
-MODULE_PARM(debug, "i");
+module_param(debug, int, S_IRUGO | S_IWUSR);
 MODULE_PARM_DESC(debug, "Debug level: 0-9 (default=0)");
-MODULE_PARM(flags, "i");
+module_param(flags, int, 0);
 MODULE_PARM_DESC(flags,
 		"Bitfield: 0=VIDIOCSYNC, "
 		"1=B/W, "
@@ -71,18 +71,18 @@
 		"4=test pattern, "
 		"5=separate frames, "
 		"6=clean frames");
-MODULE_PARM(framerate, "i");
+module_param(framerate, int, 0);
 MODULE_PARM_DESC(framerate, "Framerate setting: 0=slowest, 6=fastest (default=2)");
 
-MODULE_PARM(init_brightness, "i");
+module_param(init_brightness, int, 0);
 MODULE_PARM_DESC(init_brightness, "Brightness preconfiguration: 0-255 (default=128)");
-MODULE_PARM(init_contrast, "i");
+module_param(init_contrast, int, 0);
 MODULE_PARM_DESC(init_contrast, "Contrast preconfiguration: 0-255 (default=192)");
-MODULE_PARM(init_color, "i");
+module_param(init_color, int, 0);
 MODULE_PARM_DESC(init_color, "Color preconfiguration: 0-255 (default=128)");
-MODULE_PARM(init_hue, "i");
+module_param(init_hue, int, 0);
 MODULE_PARM_DESC(init_hue, "Hue preconfiguration: 0-255 (default=128)");
-MODULE_PARM(hue_correction, "i");
+module_param(hue_correction, int, 0);
 MODULE_PARM_DESC(hue_correction, "YUV colorspace regulation: 0-255 (default=128)");
 
 /*
diff -Nru a/drivers/usb/media/usbvideo.c b/drivers/usb/media/usbvideo.c
--- a/drivers/usb/media/usbvideo.c	2004-10-18 14:57:05 -07:00
+++ b/drivers/usb/media/usbvideo.c	2004-10-18 14:57:05 -07:00
@@ -34,7 +34,7 @@
 #endif
 
 static int video_nr = -1;
-MODULE_PARM(video_nr, "i");
+module_param(video_nr, int, 0);
 
 /*
  * Local prototypes.
diff -Nru a/drivers/usb/misc/auerswald.c b/drivers/usb/misc/auerswald.c
--- a/drivers/usb/misc/auerswald.c	2004-10-18 14:56:28 -07:00
+++ b/drivers/usb/misc/auerswald.c	2004-10-18 14:56:28 -07:00
@@ -269,7 +269,7 @@
 /* Forwards */
 static void auerswald_ctrlread_complete (struct urb * urb, struct pt_regs *regs);
 static void auerswald_removeservice (pauerswald_t cp, pauerscon_t scp);
-extern struct usb_driver auerswald_driver;
+static struct usb_driver auerswald_driver;
 
 
 /*-------------------------------------------------------------------*/
@@ -1037,7 +1037,8 @@
 
         /* now extract the information */
         channelid = cp->intbufp[2];
-        bytecount = le16_to_cpup (&cp->intbufp[3]);
+        bytecount = (unsigned char)cp->intbufp[3];
+        bytecount |= (unsigned char)cp->intbufp[4] << 8;
 
         /* check the channel id */
         if (channelid >= AUH_TYPESIZE) {
@@ -1930,7 +1931,7 @@
 	struct usb_device *usbdev = interface_to_usbdev(intf);
 	pauerswald_t cp = NULL;
 	unsigned int u = 0;
-	char *pbuf;
+	__le16 *pbuf;
 	int ret;
 
 	dbg ("probe: vendor id 0x%x, device id 0x%x",
@@ -1976,8 +1977,7 @@
 	dbg ("Version is %X", cp->version);
 
 	/* allow some time to settle the device */
-	set_current_state(TASK_UNINTERRUPTIBLE);
-	schedule_timeout(HZ/3);
+	msleep(334);
 
 	/* Try to get a suitable textual description of the device */
 	/* Device name:*/
@@ -2003,7 +2003,7 @@
 	info("device is a %s", cp->dev_desc);
 
         /* get the maximum allowed control transfer length */
-        pbuf = (char *) kmalloc (2, GFP_KERNEL);    /* use an allocated buffer because of urb target */
+        pbuf = (__le16 *) kmalloc (2, GFP_KERNEL);    /* use an allocated buffer because of urb target */
         if (!pbuf) {
 		err( "out of memory");
 		goto pfail;
diff -Nru a/drivers/usb/misc/legousbtower.c b/drivers/usb/misc/legousbtower.c
--- a/drivers/usb/misc/legousbtower.c	2004-10-18 14:56:29 -07:00
+++ b/drivers/usb/misc/legousbtower.c	2004-10-18 14:56:29 -07:00
@@ -71,6 +71,8 @@
  *   - make device locking interruptible
  * 2004-04-30 - 0.95 Juergen Stuber <starblue@users.sourceforge.net>
  *   - check for valid udev on resubmitting and unlinking urbs
+ * 2004-08-03 - 0.96 Juergen Stuber <starblue@users.sourceforge.net>
+ *   - move reset into open to clean out spurious data
  */
 
 #include <linux/config.h>
@@ -98,12 +100,12 @@
 
 
 /* Version Information */
-#define DRIVER_VERSION "v0.95"
+#define DRIVER_VERSION "v0.96"
 #define DRIVER_AUTHOR "Juergen Stuber <starblue@sourceforge.net>"
 #define DRIVER_DESC "LEGO USB Tower Driver"
 
 /* Module parameters */
-MODULE_PARM(debug, "i");
+module_param(debug, int, S_IRUGO | S_IWUSR);
 MODULE_PARM_DESC(debug, "Debug enabled or not");
 
 /* The defaults are chosen to work with the latest versions of leJOS and NQC.
@@ -113,8 +115,8 @@
  * In this case read_buffer_size should exceed the maximal packet length
  * (417 for datalog uploads), and packet_timeout should be set.
  */
-static size_t read_buffer_size = 480;
-MODULE_PARM(read_buffer_size, "i");
+static int read_buffer_size = 480;
+module_param(read_buffer_size, int, 0);
 MODULE_PARM_DESC(read_buffer_size, "Read buffer size");
 
 /* Some legacy software likes to send packets in one piece.
@@ -123,8 +125,8 @@
  * A problem with long writes is that the following read may time out
  * if the software is not prepared to wait long enough.
  */
-static size_t write_buffer_size = 480;
-MODULE_PARM(write_buffer_size, "i");
+static int write_buffer_size = 480;
+module_param(write_buffer_size, int, 0);
 MODULE_PARM_DESC(write_buffer_size, "Write buffer size");
 
 /* Some legacy software expects reads to contain whole LASM packets.
@@ -138,7 +140,7 @@
  * Set it to 0 to disable.
  */
 static int packet_timeout = 50;
-MODULE_PARM(packet_timeout, "i");
+module_param(packet_timeout, int, 0);
 MODULE_PARM_DESC(packet_timeout, "Packet timeout in ms");
 
 /* Some legacy software expects blocking reads to time out.
@@ -146,7 +148,7 @@
  * Set it to 0 to disable.
  */
 static int read_timeout = 200;
-MODULE_PARM(read_timeout, "i");
+module_param(read_timeout, int, 0);
 MODULE_PARM_DESC(read_timeout, "Read timeout in ms");
 
 /* As of kernel version 2.6.4 ehci-hcd uses an
@@ -159,11 +161,11 @@
  * or set to 0 to use the standard interval from the endpoint descriptors.
  */
 static int interrupt_in_interval = 2;
-MODULE_PARM(interrupt_in_interval, "i");
+module_param(interrupt_in_interval, int, 0);
 MODULE_PARM_DESC(interrupt_in_interval, "Interrupt in interval in ms");
 
 static int interrupt_out_interval = 8;
-MODULE_PARM(interrupt_out_interval, "i");
+module_param(interrupt_out_interval, int, 0);
 MODULE_PARM_DESC(interrupt_out_interval, "Interrupt out interval in ms");
 
 /* Define these values to match your device */
@@ -175,18 +177,18 @@
 #define LEGO_USB_TOWER_REQUEST_GET_VERSION	0xFD
 
 struct tower_reset_reply {
-	__u16 size;		/* little-endian */
+	__le16 size;		/* little-endian */
 	__u8 err_code;
 	__u8 spare;
 } __attribute__ ((packed));
 
 struct tower_get_version_reply {
-	__u16 size;		/* little-endian */
+	__le16 size;		/* little-endian */
 	__u8 err_code;
 	__u8 spare;
 	__u8 major;
 	__u8 minor;
-	__u16 build_no;		/* little-endian */
+	__le16 build_no;		/* little-endian */
 } __attribute__ ((packed));
 
 
@@ -341,6 +343,8 @@
 	int subminor;
 	int retval = 0;
 	struct usb_interface *interface;
+	struct tower_reset_reply reset_reply;
+	int result;
 
 	dbg(2, "%s: enter", __FUNCTION__);
 
@@ -378,6 +382,22 @@
 	}
 	dev->open_count = 1;
 
+	/* reset the tower */
+	result = usb_control_msg (dev->udev,
+				  usb_rcvctrlpipe(dev->udev, 0),
+				  LEGO_USB_TOWER_REQUEST_RESET,
+				  USB_TYPE_VENDOR | USB_DIR_IN | USB_RECIP_DEVICE,
+				  0,
+				  0,
+				  &reset_reply,
+				  sizeof(reset_reply),
+				  HZ);
+	if (result < 0) {
+		err("LEGO USB Tower reset control request failed");
+		retval = result;
+		goto unlock_exit;
+	}
+
 	/* initialize in direction */
 	dev->read_buffer_length = 0;
 	dev->read_packet_length = 0;
@@ -694,7 +714,7 @@
 	}
 
 	/* write the data into interrupt_out_buffer from userspace */
-	bytes_to_write = min(count, write_buffer_size);
+	bytes_to_write = min_t(int, count, write_buffer_size);
 	dbg(4, "%s: count = %Zd, bytes_to_write = %Zd", __FUNCTION__, count, bytes_to_write);
 
 	if (copy_from_user (dev->interrupt_out_buffer, buffer, bytes_to_write)) {
@@ -828,7 +848,6 @@
 	struct lego_usb_tower *dev = NULL;
 	struct usb_host_interface *iface_desc;
 	struct usb_endpoint_descriptor* endpoint;
-	struct tower_reset_reply reset_reply;
 	struct tower_get_version_reply get_version_reply;
 	int i;
 	int retval = -ENOMEM;
@@ -950,22 +969,6 @@
 
 	/* let the user know what node this device is now attached to */
 	info ("LEGO USB Tower #%d now attached to major %d minor %d", (dev->minor - LEGO_USB_TOWER_MINOR_BASE), USB_MAJOR, dev->minor);
-
-	/* reset the tower */
-	result = usb_control_msg (udev,
-				  usb_rcvctrlpipe(udev, 0),
-				  LEGO_USB_TOWER_REQUEST_RESET,
-				  USB_TYPE_VENDOR | USB_DIR_IN | USB_RECIP_DEVICE,
-				  0,
-				  0,
-				  &reset_reply,
-				  sizeof(reset_reply),
-				  HZ);
-	if (result < 0) {
-		err("LEGO USB Tower reset control request failed");
-		retval = result;
-		goto error;
-	}
 
 	/* get the firmware version and log it */
 	result = usb_control_msg (udev,
diff -Nru a/drivers/usb/misc/phidgetservo.c b/drivers/usb/misc/phidgetservo.c
--- a/drivers/usb/misc/phidgetservo.c	2004-10-18 14:56:48 -07:00
+++ b/drivers/usb/misc/phidgetservo.c	2004-10-18 14:56:48 -07:00
@@ -12,8 +12,6 @@
  * controllers available at: http://www.phidgets.com/ 
  *
  * Note that the driver takes input as: degrees.minutes
- * -23 < degrees < 203
- * 0 < minutes < 59
  *
  * CAUTION: Generally you should use 0 < degrees < 180 as anything else
  * is probably beyond the range of your servo and may damage it.
@@ -21,6 +19,10 @@
  * Jun 16, 2004: Sean Young <sean@mess.org>
  *  - cleanups
  *  - was using memory after kfree()
+ * Aug 8, 2004: Sean Young <sean@mess.org>
+ *  - set the highest angle as high as the hardware allows, there are 
+ *    some odd servos out there
+ *
  */
 
 #include <linux/config.h>
@@ -87,6 +89,9 @@
 	int retval;
 	unsigned char *buffer;
 
+	if (degrees < -23 || degrees > 362)
+		return -EINVAL;
+
 	buffer = kmalloc(6, GFP_KERNEL);
 	if (!buffer) {
 		dev_err(&servo->udev->dev, "%s - out of memory\n",
@@ -157,6 +162,9 @@
 	int retval;
 	unsigned char *buffer;
 
+	if (degrees < -23 || degrees > 278)
+		return -EINVAL;
+
 	buffer = kmalloc(2, GFP_KERNEL);
 	if (!buffer) {
 		dev_err(&servo->udev->dev, "%s - out of memory\n",
@@ -212,10 +220,8 @@
 		return -EINVAL;						\
 	}								\
 									\
-	if (degrees < -23 || degrees > (180 + 23) ||			\
-	    minutes < 0 || minutes > 59) {				\
+	if (minutes < 0 || minutes > 59) 				\
 		return -EINVAL;						\
-	}								\
 									\
 	if (servo->type & SERVO_VERSION_30)				\
 		retval = change_position_v30 (servo, value, degrees, 	\
diff -Nru a/drivers/usb/misc/tiglusb.c b/drivers/usb/misc/tiglusb.c
--- a/drivers/usb/misc/tiglusb.c	2004-10-18 14:55:54 -07:00
+++ b/drivers/usb/misc/tiglusb.c	2004-10-18 14:55:54 -07:00
@@ -560,7 +560,7 @@
 MODULE_DESCRIPTION (DRIVER_DESC);
 MODULE_LICENSE (DRIVER_LICENSE);
 
-MODULE_PARM (timeout, "i");
+module_param(timeout, int, 0);
 MODULE_PARM_DESC (timeout, "Timeout in tenths of seconds (default=1.5 seconds)");
 
 /* --------------------------------------------------------------------- */
diff -Nru a/drivers/usb/misc/usbtest.c b/drivers/usb/misc/usbtest.c
--- a/drivers/usb/misc/usbtest.c	2004-10-18 14:57:04 -07:00
+++ b/drivers/usb/misc/usbtest.c	2004-10-18 14:57:04 -07:00
@@ -1054,8 +1054,7 @@
 	urb = simple_alloc_urb (testdev_to_usbdev (dev), pipe, size);
 	if (!urb)
 		return -ENOMEM;
-	if (async)
-		urb->transfer_flags |= URB_ASYNC_UNLINK;
+	urb->transfer_flags |= URB_ASYNC_UNLINK;
 	urb->context = &completion;
 	urb->complete = unlink1_callback;
 
@@ -1074,17 +1073,20 @@
 	 * hcd states and code paths, even with little other system load.
 	 */
 	msleep (jiffies % (2 * INTERRUPT_RATE));
+	if (async) {
 retry:
-	retval = usb_unlink_urb (urb);
-	if (retval == -EBUSY || retval == -EIDRM) {
-		/* we can't unlink urbs while they're completing.
-		 * or if they've completed, and we haven't resubmitted.
-		 * "normal" drivers would prevent resubmission, but
-		 * since we're testing unlink paths, we can't.
-		 */
-		dev_dbg (&dev->intf->dev, "unlink retry\n");
-		goto retry;
-	}
+		retval = usb_unlink_urb (urb);
+		if (retval == -EBUSY || retval == -EIDRM) {
+			/* we can't unlink urbs while they're completing.
+			 * or if they've completed, and we haven't resubmitted.
+			 * "normal" drivers would prevent resubmission, but
+			 * since we're testing unlink paths, we can't.
+			 */
+			dev_dbg (&dev->intf->dev, "unlink retry\n");
+			goto retry;
+		}
+	} else
+		usb_kill_urb (urb);
 	if (!(retval == 0 || retval == -EINPROGRESS)) {
 		dev_dbg (&dev->intf->dev, "unlink fail %d\n", retval);
 		return retval;
@@ -1095,9 +1097,10 @@
 	simple_free_urb (urb);
 
 	if (async)
-		return (retval != -ECONNRESET) ? -ECONNRESET : 0;
+		return (retval == -ECONNRESET) ? 0 : retval - 1000;
 	else
-		return (retval != -ENOENT) ? -ENOENT : 0;
+		return (retval == -ENOENT || retval == -EPERM) ?
+				0 : retval - 2000;
 }
 
 static int unlink_simple (struct usbtest_dev *dev, int pipe, int len)
diff -Nru a/drivers/usb/net/catc.c b/drivers/usb/net/catc.c
--- a/drivers/usb/net/catc.c	2004-10-18 14:56:29 -07:00
+++ b/drivers/usb/net/catc.c	2004-10-18 14:56:29 -07:00
@@ -242,7 +242,7 @@
 
 	do {
 		if(!catc->is_f5u011) {
-			pkt_len = le16_to_cpup((u16*)pkt_start);
+			pkt_len = le16_to_cpup((__le16*)pkt_start);
 			if (pkt_len > urb->actual_length) {
 				catc->stats.rx_length_errors++;
 				catc->stats.rx_errors++;
@@ -303,7 +303,7 @@
 		else if (data[1] & 0x20)
 			linksts = LinkBad;
 	} else {
-		hasdata = (unsigned int)(be16_to_cpup((u16*)data) & 0x0fff);
+		hasdata = (unsigned int)(be16_to_cpup((__be16*)data) & 0x0fff);
 		if (data[0] == 0x90)
 			linksts = LinkGood;
 		else if (data[0] == 0xA0)
diff -Nru a/drivers/usb/net/kaweth.c b/drivers/usb/net/kaweth.c
--- a/drivers/usb/net/kaweth.c	2004-10-18 14:56:48 -07:00
+++ b/drivers/usb/net/kaweth.c	2004-10-18 14:56:48 -07:00
@@ -203,7 +203,7 @@
 	__u8 reserved2;
 	eth_addr_t hw_addr;
 	__u32 statistics_mask;
-	__u16 segment_size;
+	__le16 segment_size;
 	__u16 max_multicast_filters;
 	__u8 reserved3;
 } __attribute__ ((packed));
@@ -588,7 +588,7 @@
 	int count = urb->actual_length;
 	int count2 = urb->transfer_buffer_length;
 
-	__u16 pkt_len = le16_to_cpup((u16 *)kaweth->rx_buf);
+	__u16 pkt_len = le16_to_cpup((__le16 *)kaweth->rx_buf);
 
 	struct sk_buff *skb;
 
@@ -668,7 +668,7 @@
 		INTBUFFERSIZE,
 		int_callback,
 		kaweth,
-		HZ/4);
+		8);
 	kaweth->irq_urb->transfer_dma = kaweth->intbufferhandle;
 	kaweth->irq_urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
 
@@ -763,7 +763,7 @@
 static int kaweth_start_xmit(struct sk_buff *skb, struct net_device *net)
 {
 	struct kaweth_device *kaweth = net->priv;
-	u16 *private_header;
+	__le16 *private_header;
 
 	int res;
 
@@ -794,7 +794,7 @@
 		}
 	}
 
-	private_header = (u16 *)__skb_push(skb, 2);
+	private_header = (__le16 *)__skb_push(skb, 2);
 	*private_header = cpu_to_le16(skb->len-2);
 	kaweth->tx_skb = skb;
 
diff -Nru a/drivers/usb/net/pegasus.c b/drivers/usb/net/pegasus.c
--- a/drivers/usb/net/pegasus.c	2004-10-18 14:57:04 -07:00
+++ b/drivers/usb/net/pegasus.c	2004-10-18 14:57:04 -07:00
@@ -78,8 +78,8 @@
 MODULE_AUTHOR(DRIVER_AUTHOR);
 MODULE_DESCRIPTION(DRIVER_DESC);
 MODULE_LICENSE("GPL");
-MODULE_PARM(loopback, "i");
-MODULE_PARM(mii_mode, "i");
+module_param(loopback, bool, 0);
+module_param(mii_mode, bool, 0);
 MODULE_PARM_DESC(loopback, "Enable MAC loopback mode (bit 0)");
 MODULE_PARM_DESC(mii_mode, "Enable HomePNA mode (bit 0),default=MII mode = 0");
 
@@ -286,7 +286,7 @@
 {
 	int i;
 	__u8 data[4] = { phy, 0, 0, indx };
-	__u16 regdi;
+	__le16 regdi;
 
 	set_register(pegasus, PhyCtrl, 0);
 	set_registers(pegasus, PhyAddr, sizeof (data), data);
@@ -347,7 +347,7 @@
 {
 	int i;
 	__u8 tmp;
-	__u16 retdatai;
+	__le16 retdatai;
 
 	set_register(pegasus, EpromCtrl, 0);
 	set_register(pegasus, EpromOffset, index);
@@ -417,7 +417,7 @@
 
 	for (i = 0; i < 3; i++) {
 		read_eprom_word(pegasus, i, &w16);
-		((__u16 *) id)[i] = cpu_to_le16p(&w16);
+		((__le16 *) id)[i] = cpu_to_le16p(&w16);
 	}
 }
 
@@ -581,7 +581,7 @@
 	if (!count)
 		goto goon;
 
-	rx_status = le32_to_cpu(*(int *) (urb->transfer_buffer + count - 4));
+	rx_status = le32_to_cpu(*(__le32 *) (urb->transfer_buffer + count - 4));
 	if (rx_status & 0x000e0000) {
 		dbg("%s: RX packet error %x", net->name, rx_status & 0xe0000);
 		pegasus->stats.rx_errors++;
@@ -594,7 +594,7 @@
 		goto goon;
 	}
 	if (pegasus->chip == 0x8513) {
-		pkt_len = le32_to_cpu(*(int *)urb->transfer_buffer);
+		pkt_len = le32_to_cpu(*(__le32 *)urb->transfer_buffer);
 		pkt_len &= 0x0fff;
 		pegasus->rx_skb->data += 2;
 	} else {
@@ -774,7 +774,7 @@
 
 	netif_stop_queue(net);
 
-	((__u16 *) pegasus->tx_buff)[0] = cpu_to_le16(l16);
+	((__le16 *) pegasus->tx_buff)[0] = cpu_to_le16(l16);
 	memcpy(pegasus->tx_buff + 2, skb->data, skb->len);
 	usb_fill_bulk_urb(pegasus->tx_urb, pegasus->usb,
 			  usb_sndbulkpipe(pegasus->usb, 2),
diff -Nru a/drivers/usb/net/rtl8150.c b/drivers/usb/net/rtl8150.c
--- a/drivers/usb/net/rtl8150.c	2004-10-18 14:56:33 -07:00
+++ b/drivers/usb/net/rtl8150.c	2004-10-18 14:56:33 -07:00
@@ -160,7 +160,7 @@
 	spinlock_t rx_pool_lock;
 	struct usb_ctrlrequest dr;
 	int intr_interval;
-	u16 rx_creg;
+	__le16 rx_creg;
 	u8 *intr_buff;
 	u8 phy;
 };
@@ -265,7 +265,7 @@
 
 	if (i < MII_TIMEOUT) {
 		get_registers(dev, PHYDAT, 2, data);
-		*reg = le16_to_cpup(data);
+		*reg = data[0] | (data[1] << 8);
 		return 0;
 	} else
 		return 1;
@@ -450,7 +450,7 @@
 		goto goon;
 
 	res = urb->actual_length;
-	rx_stat = le16_to_cpu(*(short *)(urb->transfer_buffer + res - 4));
+	rx_stat = le16_to_cpu(*(__le16 *)(urb->transfer_buffer + res - 4));
 	pkt_len = res - 4;
 
 	skb_put(dev->rx_skb, pkt_len);
diff -Nru a/drivers/usb/net/usbnet.c b/drivers/usb/net/usbnet.c
--- a/drivers/usb/net/usbnet.c	2004-10-18 14:56:32 -07:00
+++ b/drivers/usb/net/usbnet.c	2004-10-18 14:56:32 -07:00
@@ -166,7 +166,7 @@
 #define CONTROL_TIMEOUT_JIFFIES ((CONTROL_TIMEOUT_MS * HZ)/1000)
 
 // between wakeups
-#define UNLINK_TIMEOUT_JIFFIES ((3  /*ms*/ * HZ)/1000)
+#define UNLINK_TIMEOUT_MS	3
 
 /*-------------------------------------------------------------------------*/
 
@@ -268,7 +268,7 @@
 
 /* use ethtool to change the level for any given device */
 static int msg_level = 1;
-MODULE_PARM (msg_level, "i");
+module_param (msg_level, int, 0);
 MODULE_PARM_DESC (msg_level, "Initial message level (default = 1)");
 
 
@@ -937,8 +937,8 @@
 
 	u8	iMACAddress;
 	u32	bmEthernetStatistics;
-	u16	wMaxSegmentSize;
-	u16	wNumberMCFilters;
+	__le16	wMaxSegmentSize;
+	__le16	wNumberMCFilters;
 	u8	bNumberPowerFilters;
 } __attribute__ ((packed));
 
@@ -1074,7 +1074,7 @@
 					info->u->bLength);
 				goto bad_desc;
 			}
-			dev->net->mtu = cpu_to_le16p (
+			dev->net->mtu = le16_to_cpup (
 						&info->ether->wMaxSegmentSize)
 					- ETH_HLEN;
 			/* because of Zaurus, we may be ignoring the host
@@ -2591,8 +2591,7 @@
 	while (skb_queue_len (&dev->rxq)
 			&& skb_queue_len (&dev->txq)
 			&& skb_queue_len (&dev->done)) {
-		set_current_state (TASK_UNINTERRUPTIBLE);
-		schedule_timeout (UNLINK_TIMEOUT_JIFFIES);
+		msleep(UNLINK_TIMEOUT_MS);
 		devdbg (dev, "waited for %d urb completions", temp);
 	}
 	dev->wait = NULL;
diff -Nru a/drivers/usb/serial/cyberjack.c b/drivers/usb/serial/cyberjack.c
--- a/drivers/usb/serial/cyberjack.c	2004-10-18 14:57:03 -07:00
+++ b/drivers/usb/serial/cyberjack.c	2004-10-18 14:57:03 -07:00
@@ -44,7 +44,7 @@
 /*
  * Version Information
  */
-#define DRIVER_VERSION "v1.0"
+#define DRIVER_VERSION "v1.01"
 #define DRIVER_AUTHOR "Matthias Bruestle"
 #define DRIVER_DESC "REINER SCT cyberJack pinpad/e-com USB Chipcard Reader Driver"
 
@@ -111,6 +111,7 @@
 static int cyberjack_startup (struct usb_serial *serial)
 {
 	struct cyberjack_private *priv;
+	int i;
 
 	dbg("%s", __FUNCTION__);
 
@@ -128,6 +129,16 @@
 
 	init_waitqueue_head(&serial->port[0]->write_wait);
 
+	for (i = 0; i < serial->num_ports; ++i) {
+		int result;
+		serial->port[i]->interrupt_in_urb->dev = serial->dev;
+		result = usb_submit_urb(serial->port[i]->interrupt_in_urb, 
+					GFP_KERNEL);
+		if (result)
+			err(" usb_submit_urb(read int) failed");
+		dbg("%s - usb_submit_urb(int urb)", __FUNCTION__);
+	}
+
 	return( 0 );
 }
 
@@ -138,6 +149,7 @@
 	dbg("%s", __FUNCTION__);
 
 	for (i=0; i < serial->num_ports; ++i) {
+		usb_unlink_urb (serial->port[i]->interrupt_in_urb);
 		/* My special items, the standard routines free my urbs */
 		kfree(usb_get_serial_port_data(serial->port[i]));
 		usb_set_serial_port_data(serial->port[i], NULL);
@@ -168,17 +180,6 @@
 	priv->wrsent = 0;
 	spin_unlock_irqrestore(&priv->lock, flags);
 
-	/* shutdown any bulk reads that might be going on */
-	usb_unlink_urb (port->write_urb);
-	usb_unlink_urb (port->read_urb);
-	usb_unlink_urb (port->interrupt_in_urb);
-
-	port->interrupt_in_urb->dev = port->serial->dev;
-	result = usb_submit_urb(port->interrupt_in_urb, GFP_KERNEL);
-	if (result)
-		err(" usb_submit_urb(read int) failed");
-	dbg("%s - usb_submit_urb(int urb)", __FUNCTION__);
-
 	return result;
 }
 
@@ -190,11 +191,6 @@
 		/* shutdown any bulk reads that might be going on */
 		usb_unlink_urb (port->write_urb);
 		usb_unlink_urb (port->read_urb);
-		usb_unlink_urb (port->interrupt_in_urb);
-		dbg("%s - usb_clear_halt", __FUNCTION__ );
-		usb_clear_halt(port->serial->dev, port->write_urb->pipe);
-		usb_clear_halt(port->serial->dev, port->read_urb->pipe);
-		usb_clear_halt(port->serial->dev, port->interrupt_in_urb->pipe);
 	}
 }
 
@@ -376,6 +372,10 @@
 	}
 
 	tty = port->tty;
+	if (!tty) {
+		dbg("%s - ignoring since device not open\n", __FUNCTION__);
+		return;
+	}
 	if (urb->actual_length) {
 		for (i = 0; i < urb->actual_length ; ++i) {
 			/* if we insert more than TTY_FLIPBUF_SIZE characters, we drop them. */
diff -Nru a/drivers/usb/serial/digi_acceleport.c b/drivers/usb/serial/digi_acceleport.c
--- a/drivers/usb/serial/digi_acceleport.c	2004-10-18 14:56:29 -07:00
+++ b/drivers/usb/serial/digi_acceleport.c	2004-10-18 14:56:29 -07:00
@@ -624,14 +624,7 @@
 	wake_up_interruptible( &port->write_wait );
 
 	/* wake up line discipline */
-	if( (tty->flags & (1 << TTY_DO_WRITE_WAKEUP))
-	&& tty->ldisc.write_wakeup )
-		(tty->ldisc.write_wakeup)(tty);
-
-	/* wake up other tty processes */
-	wake_up_interruptible( &tty->write_wait );
-	/* For 2.2.16 backport -- wake_up_interruptible( &tty->poll_wait ); */
-
+	tty_wakeup(tty);
 }
 
 
@@ -1553,13 +1546,17 @@
 dbg( "digi_close: TOP: port=%d, open_count=%d", priv->dp_port_num, port->open_count );
 
 
+	/* if disconnected, just clear flags */
+	if (!usb_get_intfdata(port->serial->interface))
+		goto exit;
+
 	/* do cleanup only after final close on this port */
 	spin_lock_irqsave( &priv->dp_port_lock, flags );
 	priv->dp_in_close = 1;
 	spin_unlock_irqrestore( &priv->dp_port_lock, flags );
 
 	/* tell line discipline to process only XON/XOFF */
-        tty->closing = 1;
+	tty->closing = 1;
 
 	/* wait for output to drain */
 	if( (filp->f_flags&(O_NDELAY|O_NONBLOCK)) == 0 ) {
@@ -1569,8 +1566,7 @@
 	/* flush driver and line discipline buffers */
 	if( tty->driver->flush_buffer )
 		tty->driver->flush_buffer( tty );
-	if( tty->ldisc.flush_buffer )
-		tty->ldisc.flush_buffer( tty );
+	tty_ldisc_flush(tty);
 
 	if (port->serial->dev) {
 		/* wait for transmit idle */
@@ -1624,6 +1620,7 @@
 
 	tty->closing = 0;
 
+exit:
 	spin_lock_irqsave( &priv->dp_port_lock, flags );
 	priv->dp_write_urb_in_use = 0;
 	priv->dp_in_close = 0;
diff -Nru a/drivers/usb/serial/empeg.c b/drivers/usb/serial/empeg.c
--- a/drivers/usb/serial/empeg.c	2004-10-18 14:57:04 -07:00
+++ b/drivers/usb/serial/empeg.c	2004-10-18 14:57:04 -07:00
@@ -516,11 +516,7 @@
 	 */
 	port->tty->low_latency = 1;
 
-	/* Notify the tty driver that the termios have changed. */
-	port->tty->ldisc.set_termios(port->tty, NULL);
-
 	return;
-
 }
 
 
diff -Nru a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c
--- a/drivers/usb/serial/ftdi_sio.c	2004-10-18 14:56:49 -07:00
+++ b/drivers/usb/serial/ftdi_sio.c	2004-10-18 14:56:49 -07:00
@@ -17,6 +17,11 @@
  * See http://ftdi-usb-sio.sourceforge.net for upto date testing info
  *	and extra documentation
  *
+ * (21/Jul/2004) Ian Abbott
+ *      Incorporated Steven Turner's code to add support for the FT2232C chip.
+ *      The prelimilary port to the 2.6 kernel was by Rus V. Brushkoff.  I have
+ *      fixed a couple of things.
+ *
  * (27/May/2004) Ian Abbott
  *      Improved throttling code, mostly stolen from the WhiteHEAT driver.
  *
@@ -259,7 +264,7 @@
 /*
  * Version Information
  */
-#define DRIVER_VERSION "v1.4.0"
+#define DRIVER_VERSION "v1.4.1"
 #define DRIVER_AUTHOR "Greg Kroah-Hartman <greg@kroah.com>, Bill Ryder <bryder@sgi.com>, Kuba Ober <kuba@mareimbrium.org>"
 #define DRIVER_DESC "USB FTDI Serial Converters Driver"
 
@@ -489,11 +494,18 @@
 };
 
 
+static struct usb_device_id id_table_FT2232C[] = {
+	{ USB_DEVICE(FTDI_VID, FTDI_8U2232C_PID) },
+	{ }						/* Terminating entry */
+};
+
+
 static struct usb_device_id id_table_combined [] = {
 	{ USB_DEVICE(FTDI_VID, FTDI_IRTRANS_PID) },
 	{ USB_DEVICE(FTDI_VID, FTDI_SIO_PID) },
 	{ USB_DEVICE(FTDI_VID, FTDI_8U232AM_PID) },
 	{ USB_DEVICE(FTDI_VID, FTDI_8U232AM_ALT_PID) },
+	{ USB_DEVICE(FTDI_VID, FTDI_8U2232C_PID) },
 	{ USB_DEVICE(FTDI_VID, FTDI_RELAIS_PID) },
 	{ USB_DEVICE(INTERBIOMETRICS_VID, INTERBIOMETRICS_IOBOARD_PID) },
 	{ USB_DEVICE(INTERBIOMETRICS_VID, INTERBIOMETRICS_MINI_IOBOARD_PID) },
@@ -621,6 +633,8 @@
 	__u8 rx_flags;		/* receive state flags (throttling) */
 	spinlock_t rx_lock;	/* spinlock for receive state */
 
+	__u16 interface;	/* FT2232C port interface (0 for FT232/245) */
+
 	int force_baud;		/* if non-zero, force the baud rate to this value */
 	int force_rtscts;	/* if non-zero, force RTS-CTS to always be enabled */
 };
@@ -637,6 +651,7 @@
 static int  ftdi_SIO_startup		(struct usb_serial *serial);
 static int  ftdi_8U232AM_startup	(struct usb_serial *serial);
 static int  ftdi_FT232BM_startup	(struct usb_serial *serial);
+static int  ftdi_FT2232C_startup	(struct usb_serial *serial);
 static int  ftdi_USB_UIRT_startup	(struct usb_serial *serial);
 static int  ftdi_HE_TIRA1_startup	(struct usb_serial *serial);
 static void ftdi_shutdown		(struct usb_serial *serial);
@@ -739,6 +754,32 @@
 	.shutdown =		ftdi_shutdown,
 };
 
+static struct usb_serial_device_type ftdi_FT2232C_device = {
+	.owner =		THIS_MODULE,
+	.name =			"FTDI FT2232C Compatible",
+	.id_table =		id_table_FT2232C,
+	.num_interrupt_in =	0,
+	.num_bulk_in =		1,
+	.num_bulk_out =		1,
+	.num_ports =		1,
+	.open =			ftdi_open,
+	.close =		ftdi_close,
+	.throttle =		ftdi_throttle,
+	.unthrottle =		ftdi_unthrottle,
+	.write =		ftdi_write,
+	.write_room =		ftdi_write_room,
+	.chars_in_buffer =	ftdi_chars_in_buffer,
+	.read_bulk_callback =	ftdi_read_bulk_callback,
+	.write_bulk_callback =	ftdi_write_bulk_callback,
+	.tiocmget =             ftdi_tiocmget,
+	.tiocmset =             ftdi_tiocmset,
+	.ioctl =		ftdi_ioctl,
+	.set_termios =		ftdi_set_termios,
+	.break_ctl =		ftdi_break_ctl,
+	.attach =		ftdi_FT2232C_startup,
+	.shutdown =		ftdi_shutdown,
+};
+
 static struct usb_serial_device_type ftdi_USB_UIRT_device = {
 	.owner =		THIS_MODULE,
 	.name =			"USB-UIRT Infrared Tranceiver",
@@ -866,7 +907,7 @@
 			       usb_sndctrlpipe(port->serial->dev, 0),
 			       FTDI_SIO_SET_MODEM_CTRL_REQUEST, 
 			       FTDI_SIO_SET_MODEM_CTRL_REQUEST_TYPE,
-			       ftdi_high_or_low, 0, 
+			       ftdi_high_or_low, priv->interface, 
 			       buf, 0, WDR_TIMEOUT);
 
 	kfree(buf);
@@ -896,7 +937,7 @@
 			       usb_sndctrlpipe(port->serial->dev, 0),
 			       FTDI_SIO_SET_MODEM_CTRL_REQUEST, 
 			       FTDI_SIO_SET_MODEM_CTRL_REQUEST_TYPE,
-			       ftdi_high_or_low, 0, 
+			       ftdi_high_or_low, priv->interface, 
 			       buf, 0, WDR_TIMEOUT);
 
 	kfree(buf);
@@ -909,6 +950,7 @@
 
 static int change_speed(struct usb_serial_port *port)
 {
+	struct ftdi_private *priv = usb_get_serial_port_data(port);
 	char *buf;
         __u16 urb_value;
 	__u16 urb_index;
@@ -922,6 +964,9 @@
 	urb_index_value = get_ftdi_divisor(port);
 	urb_value = (__u16)urb_index_value;
 	urb_index = (__u16)(urb_index_value >> 16);
+	if (priv->interface) {	/* FT2232C */
+		urb_index = (__u16)((urb_index << 8) | priv->interface);
+	}
 	
 	rv = usb_control_msg(port->serial->dev,
 			    usb_sndctrlpipe(port->serial->dev, 0),
@@ -1015,7 +1060,12 @@
 		}
 		break;
 	case FT232BM: /* FT232BM chip */
-		chip_name = "FT232BM";
+	case FT2232C: /* FT2232C chip */
+		if (priv->chip_type == FT2232C) {
+			chip_name = "FT2232C";
+		} else {
+			chip_name = "FT232BM";
+		}
 		if (baud <= 3000000) {
 			div_value = ftdi_232bm_baud_to_divisor(baud);
 		} else {
@@ -1231,6 +1281,35 @@
 	return (0);
 } /* ftdi_FT232BM_startup */
 
+/* Startup for the FT2232C chip */
+/* Called from usbserial:serial_probe */
+static int ftdi_FT2232C_startup (struct usb_serial *serial)
+{ /* ftdi_FT2232C_startup */
+	struct ftdi_private *priv;
+	int err;
+	int inter;
+
+	dbg("%s",__FUNCTION__);
+	err = ftdi_common_startup(serial);
+	if (err){
+		return (err);
+	}
+
+	priv = usb_get_serial_port_data(serial->port[0]);
+	priv->chip_type = FT2232C;
+	inter = serial->interface->altsetting->desc.bInterfaceNumber;
+
+	if (inter) {
+		priv->interface = INTERFACE_B;
+	}
+	else  {
+		priv->interface = INTERFACE_A;
+	}
+	priv->baud_base = 48000000 / 2; /* Would be / 16, but FT2232C supports multiple of 0.125 divisor fractions! */
+	
+	return (0);
+} /* ftdi_FT2232C_startup */
+
 /* Startup for the USB-UIRT device, which requires hardwired baudrate (38400 gets mapped to 312500) */
 /* Called from usbserial:serial_probe */
 static int ftdi_USB_UIRT_startup (struct usb_serial *serial)
@@ -1323,7 +1402,7 @@
 	usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
 			FTDI_SIO_RESET_REQUEST, FTDI_SIO_RESET_REQUEST_TYPE, 
 			FTDI_SIO_RESET_SIO, 
-			0, buf, 0, WDR_TIMEOUT);
+			priv->interface, buf, 0, WDR_TIMEOUT);
 
 	/* Termios defaults are set by usb_serial_init. We don't change
 	   port->tty->termios - this would loose speed settings, etc.
@@ -1373,6 +1452,7 @@
 static void ftdi_close (struct usb_serial_port *port, struct file *filp)
 { /* ftdi_close */
 	unsigned int c_cflag = port->tty->termios->c_cflag;
+	struct ftdi_private *priv = usb_get_serial_port_data(port);
 	char buf[1];
 
 	dbg("%s", __FUNCTION__);
@@ -1383,7 +1463,8 @@
 				    usb_sndctrlpipe(port->serial->dev, 0),
 				    FTDI_SIO_SET_FLOW_CTRL_REQUEST,
 				    FTDI_SIO_SET_FLOW_CTRL_REQUEST_TYPE,
-				    0, 0, buf, 0, WDR_TIMEOUT) < 0) {
+				    0, priv->interface, buf, 0,
+				    WDR_TIMEOUT) < 0) {
 			err("error from flowcontrol urb");
 		}	    
 
@@ -1796,7 +1877,7 @@
 	if (usb_control_msg(port->serial->dev, usb_sndctrlpipe(port->serial->dev, 0),
 			    FTDI_SIO_SET_DATA_REQUEST, 
 			    FTDI_SIO_SET_DATA_REQUEST_TYPE,
-			    urb_value , 0,
+			    urb_value , priv->interface,
 			    buf, 0, WDR_TIMEOUT) < 0) {
 		err("%s FAILED to enable/disable break state (state was %d)", __FUNCTION__,break_state);
 	}	   
@@ -1875,7 +1956,7 @@
 	if (usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
 			    FTDI_SIO_SET_DATA_REQUEST, 
 			    FTDI_SIO_SET_DATA_REQUEST_TYPE,
-			    urb_value , 0,
+			    urb_value , priv->interface,
 			    buf, 0, 100) < 0) {
 		err("%s FAILED to set databits/stopbits/parity", __FUNCTION__);
 	}	   
@@ -1886,7 +1967,7 @@
 		if (usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
 				    FTDI_SIO_SET_FLOW_CTRL_REQUEST, 
 				    FTDI_SIO_SET_FLOW_CTRL_REQUEST_TYPE,
-				    0, 0, 
+				    0, priv->interface, 
 				    buf, 0, WDR_TIMEOUT) < 0) {
 			err("%s error from disable flowcontrol urb", __FUNCTION__);
 		}	    
@@ -1903,6 +1984,13 @@
 		if (change_speed(port)) {
 			err("%s urb failed to set baurdrate", __FUNCTION__);
 		}
+		/* Ensure  RTS and DTR are raised */
+		else if (set_dtr(port, HIGH) < 0){
+			err("%s Error from DTR HIGH urb", __FUNCTION__);
+		}
+		else if (set_rts(port, HIGH) < 0){
+			err("%s Error from RTS HIGH urb", __FUNCTION__);
+		}	
 	}
 
 	/* Set flow control */
@@ -1913,7 +2001,7 @@
 				    usb_sndctrlpipe(dev, 0),
 				    FTDI_SIO_SET_FLOW_CTRL_REQUEST, 
 				    FTDI_SIO_SET_FLOW_CTRL_REQUEST_TYPE,
-				    0 , FTDI_SIO_RTS_CTS_HS,
+				    0 , (FTDI_SIO_RTS_CTS_HS | priv->interface),
 				    buf, 0, WDR_TIMEOUT) < 0) {
 			err("urb failed to set to rts/cts flow control");
 		}		
@@ -1939,7 +2027,8 @@
 					    usb_sndctrlpipe(dev, 0),
 					    FTDI_SIO_SET_FLOW_CTRL_REQUEST,
 					    FTDI_SIO_SET_FLOW_CTRL_REQUEST_TYPE,
-					    urb_value , FTDI_SIO_XON_XOFF_HS,
+					    urb_value , (FTDI_SIO_XON_XOFF_HS
+							 | priv->interface),
 					    buf, 0, WDR_TIMEOUT) < 0) {
 				err("urb failed to set to xon/xoff flow control");
 			}
@@ -1951,7 +2040,7 @@
 					    usb_sndctrlpipe(dev, 0),
 					    FTDI_SIO_SET_FLOW_CTRL_REQUEST, 
 					    FTDI_SIO_SET_FLOW_CTRL_REQUEST_TYPE,
-					    0, 0, 
+					    0, priv->interface, 
 					    buf, 0, WDR_TIMEOUT) < 0) {
 				err("urb failed to clear flow control");
 			}				
@@ -1985,13 +2074,14 @@
 		break;
 	case FT8U232AM:
 	case FT232BM:
+	case FT2232C:
 		/* the 8U232AM returns a two byte value (the sio is a 1 byte value) - in the same
 		   format as the data returned from the in point */
 		if ((ret = usb_control_msg(port->serial->dev, 
 					   usb_rcvctrlpipe(port->serial->dev, 0),
 					   FTDI_SIO_GET_MODEM_STATUS_REQUEST, 
 					   FTDI_SIO_GET_MODEM_STATUS_REQUEST_TYPE,
-					   0, 0, 
+					   0, priv->interface, 
 					   buf, 2, WDR_TIMEOUT)) < 0 ) {
 			err("%s Could not get modem status of device - err: %d", __FUNCTION__,
 			    ret);
@@ -2206,6 +2296,9 @@
 	retval = usb_serial_register(&ftdi_FT232BM_device);
 	if (retval)
 		goto failed_FT232BM_register;
+	retval = usb_serial_register(&ftdi_FT2232C_device);
+	if (retval)
+		goto failed_FT2232C_register;
 	retval = usb_serial_register(&ftdi_USB_UIRT_device);
 	if (retval)
 		goto failed_USB_UIRT_register;
@@ -2223,6 +2316,8 @@
 failed_HE_TIRA1_register:
 	usb_serial_deregister(&ftdi_USB_UIRT_device);
 failed_USB_UIRT_register:
+	usb_serial_deregister(&ftdi_FT2232C_device);
+failed_FT2232C_register:
 	usb_serial_deregister(&ftdi_FT232BM_device);
 failed_FT232BM_register:
 	usb_serial_deregister(&ftdi_8U232AM_device);
@@ -2241,6 +2336,7 @@
 	usb_deregister (&ftdi_driver);
 	usb_serial_deregister (&ftdi_HE_TIRA1_device);
 	usb_serial_deregister (&ftdi_USB_UIRT_device);
+	usb_serial_deregister (&ftdi_FT2232C_device);
 	usb_serial_deregister (&ftdi_FT232BM_device);
 	usb_serial_deregister (&ftdi_8U232AM_device);
 	usb_serial_deregister (&ftdi_SIO_device);
diff -Nru a/drivers/usb/serial/ftdi_sio.h b/drivers/usb/serial/ftdi_sio.h
--- a/drivers/usb/serial/ftdi_sio.h	2004-10-18 14:56:50 -07:00
+++ b/drivers/usb/serial/ftdi_sio.h	2004-10-18 14:56:50 -07:00
@@ -26,6 +26,7 @@
 #define FTDI_SIO_PID	0x8372	/* Product Id SIO application of 8U100AX  */
 #define FTDI_8U232AM_PID 0x6001 /* Similar device to SIO above */
 #define FTDI_8U232AM_ALT_PID 0x6006 /* FTDI's alternate PID for above */
+#define FTDI_8U2232C_PID 0x6010 /* Dual channel device */
 #define FTDI_RELAIS_PID	0xFA10  /* Relais device from Rudolf Gugler */
 #define FTDI_NF_RIC_VID	0x0DCD	/* Vendor Id */
 #define FTDI_NF_RIC_PID	0x0001	/* Product Id */
@@ -234,6 +235,21 @@
 #define FTDI_SIO_SET_EVENT_CHAR	6 /* Set the event character */
 #define FTDI_SIO_SET_ERROR_CHAR	7 /* Set the error character */
 
+/* Port interface code for FT2232C */
+#define INTERFACE_A		1
+#define INTERFACE_B		2
+
+
+/*
+ *   BmRequestType:  1100 0000b
+ *   bRequest:       FTDI_E2_READ
+ *   wValue:         0
+ *   wIndex:         Address of word to read
+ *   wLength:        2
+ *   Data:           Will return a word of data from E2Address
+ *
+ */
+
 /* Port Identifier Table */
 #define PIT_DEFAULT 		0 /* SIOA */
 #define PIT_SIOA		1 /* SIOA */
@@ -333,6 +349,7 @@
 	SIO = 1,
 	FT8U232AM = 2,
 	FT232BM = 3,
+	FT2232C = 4,
 } ftdi_chip_type_t;
 
 typedef enum {
diff -Nru a/drivers/usb/serial/io_edgeport.c b/drivers/usb/serial/io_edgeport.c
--- a/drivers/usb/serial/io_edgeport.c	2004-10-18 14:55:54 -07:00
+++ b/drivers/usb/serial/io_edgeport.c	2004-10-18 14:55:54 -07:00
@@ -479,7 +479,7 @@
 static void load_application_firmware	(struct edgeport_serial *edge_serial);
 
 
-static void unicode_to_ascii		(char *string, short *unicode, int unicode_size);
+static void unicode_to_ascii		(char *string, __le16 *unicode, int unicode_size);
 
 
 
@@ -504,7 +504,7 @@
 	__u32 BootNewVer;
 	__u8 BootMajorVersion;                  
 	__u8 BootMinorVersion;                  
-	__u16 BootBuildNumber;
+	__le16 BootBuildNumber;
 	__u8 *BootImage;      
 	__u32 BootSize;
 	struct edge_firmware_image_record *record;
@@ -653,7 +653,7 @@
 
 	memset (product_info, 0, sizeof(struct edgeport_product_info));
 
-	product_info->ProductId		= (__u16)(edge_serial->serial->dev->descriptor.idProduct & ~ION_DEVICE_ID_GENERATION_2);
+	product_info->ProductId		= (__u16)(edge_serial->serial->dev->descriptor.idProduct & ~ION_DEVICE_ID_80251_NETCHIP);
 	product_info->NumPorts		= edge_serial->manuf_descriptor.NumPorts;
 	product_info->ProdInfoVer	= 0;
 
@@ -669,7 +669,7 @@
 	memcpy(product_info->ManufactureDescDate, edge_serial->manuf_descriptor.DescDate, sizeof(edge_serial->manuf_descriptor.DescDate));
 
 	// check if this is 2nd generation hardware
-	if (edge_serial->serial->dev->descriptor.idProduct & ION_DEVICE_ID_GENERATION_2) {
+	if (edge_serial->serial->dev->descriptor.idProduct & ION_DEVICE_ID_80251_NETCHIP) {
 		product_info->FirmwareMajorVersion	= OperationalCodeImageVersion_GEN2.MajorVersion;
 		product_info->FirmwareMinorVersion	= OperationalCodeImageVersion_GEN2.MinorVersion;
 		product_info->FirmwareBuildNumber	= cpu_to_le16(OperationalCodeImageVersion_GEN2.BuildNumber);
@@ -900,12 +900,7 @@
 
 	if (tty && edge_port->open) {
 		/* let the tty driver wakeup if it has a special write_wakeup function */
-		if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) && tty->ldisc.write_wakeup) {
-			(tty->ldisc.write_wakeup)(tty);
-		}
-
-		/* tell the tty driver that something has changed */
-		wake_up_interruptible(&tty->write_wait);
+		tty_wakeup(tty);
 	}
 
 	// Release the Write URB
@@ -1389,7 +1384,7 @@
 	//	to bother queueing a write. If it's too small, say a few bytes,
 	//	it's better to wait for more credits so we can do a larger
 	//	write.
-	if (edge_port->txCredits < EDGE_FW_GET_TX_CREDITS_SEND_THRESHOLD(edge_port->maxTxCredits)) {
+	if (edge_port->txCredits < EDGE_FW_GET_TX_CREDITS_SEND_THRESHOLD(edge_port->maxTxCredits,EDGE_FW_BULK_MAX_PACKET_SIZE)) {
 		dbg("%s(%d) Not enough credit - fifo %d TxCredit %d", __FUNCTION__, edge_port->port->number, fifo->count, edge_port->txCredits );
 		return;
 	}
@@ -2747,7 +2742,7 @@
  *	ASCII range, but it's only for debugging...
  *	NOTE: expects the unicode in LE format
  ****************************************************************************/
-static void unicode_to_ascii (char *string, short *unicode, int unicode_size)
+static void unicode_to_ascii (char *string, __le16 *unicode, int unicode_size)
 {
 	int i;
 	for (i = 0; i < unicode_size; ++i) {
@@ -3007,9 +3002,6 @@
 static int __init edgeport_init(void)
 {
 	int retval;
-	retval = usb_serial_register(&edgeport_1port_device);
-	if (retval) 
-		goto failed_1port_device_register;
 	retval = usb_serial_register(&edgeport_2port_device);
 	if (retval)
 		goto failed_2port_device_register;
@@ -3031,8 +3023,6 @@
 failed_4port_device_register:
 	usb_serial_deregister(&edgeport_2port_device);
 failed_2port_device_register:
-	usb_serial_deregister(&edgeport_1port_device);
-failed_1port_device_register:
 	return retval;
 }
 
@@ -3045,7 +3035,6 @@
 static void __exit edgeport_exit (void)
 {
 	usb_deregister (&io_driver);
-	usb_serial_deregister (&edgeport_1port_device);
 	usb_serial_deregister (&edgeport_2port_device);
 	usb_serial_deregister (&edgeport_4port_device);
 	usb_serial_deregister (&edgeport_8port_device);
diff -Nru a/drivers/usb/serial/io_edgeport.h b/drivers/usb/serial/io_edgeport.h
--- a/drivers/usb/serial/io_edgeport.h	2004-10-18 14:56:33 -07:00
+++ b/drivers/usb/serial/io_edgeport.h	2004-10-18 14:56:33 -07:00
@@ -107,11 +107,11 @@
 
 	__u8	BootMajorVersion;		/* Boot Firmware version: xx. */
 	__u8	BootMinorVersion;		/*	   		  yy. */
-	__u16	BootBuildNumber;		/*		      	  zzzz (LE format) */
+	__le16	BootBuildNumber;		/*		      	  zzzz (LE format) */
 
 	__u8	FirmwareMajorVersion;		/* Operational Firmware version:xx. */
 	__u8	FirmwareMinorVersion;		/*				yy. */
-	__u16	FirmwareBuildNumber;		/*				zzzz (LE format) */
+	__le16	FirmwareBuildNumber;		/*				zzzz (LE format) */
 
 	__u8	ManufactureDescDate[3];		/* MM/DD/YY when descriptor template was compiled */
 	__u8	Unused1[1];			/* Available */
diff -Nru a/drivers/usb/serial/io_fw_down.h b/drivers/usb/serial/io_fw_down.h
--- a/drivers/usb/serial/io_fw_down.h	2004-10-18 14:57:04 -07:00
+++ b/drivers/usb/serial/io_fw_down.h	2004-10-18 14:57:04 -07:00
@@ -17,7 +17,7 @@
 		unsigned short	Addr;
 		unsigned short	Len;
 		unsigned char	Data[0];
-	} __attribute ((packed));
+	} __attribute__ ((packed));
 
 	struct edge_firmware_version_info {
 		unsigned char	MajorVersion;
@@ -36,11 +36,11 @@
 
 // Segment #1, Start Address 00ff0000, Length 6
 0xff,0x00,0x00,0x00,0x06,0x00,
-    0x02, 0x00, 0x80, 0x02, 0x49, 0x39, 
+    0x02, 0x00, 0x80, 0x02, 0x44, 0xb0, 
 
 // Segment #2, Start Address 00ff000b, Length 3
 0xff,0x00,0x0b,0x00,0x03,0x00,
-    0x02, 0x44, 0x1a, 
+    0x02, 0x44, 0x72, 
 
 // Segment #3, Start Address 00ff0013, Length 3
 0xff,0x00,0x13,0x00,0x03,0x00,
@@ -72,11 +72,11 @@
 
 // Segment #10, Start Address 00ff004b, Length 3
 0xff,0x00,0x4b,0x00,0x03,0x00,
-    0x02, 0x70, 0xd4, 
+    0x02, 0x6e, 0xc4, 
 
 // Segment #11, Start Address 00ff0053, Length 3
 0xff,0x00,0x53,0x00,0x03,0x00,
-    0x02, 0x77, 0x9d, 
+    0x02, 0x75, 0x8d, 
 
 // Segment #12, Start Address 00ff007b, Length 3
 0xff,0x00,0x7b,0x00,0x03,0x00,
@@ -86,657 +86,745 @@
 0xff,0x00,0x80,0x00,0x07,0x00,
     0x7e, 0x14, 0x00, 0x00, 0x02, 0x40, 0x51, 
 
-// Segment #14, Start Address 00ff4000, Length 15920
-0xff,0x00,0x00,0x40,0x30,0x3e,
+// Segment #14, Start Address 00ff3000, Length 2178
+0xff,0x00,0x00,0x30,0x82,0x08,
+    0x12, 0x37, 0x28, 0x12, 0x30, 0x3e, 0x12, 0x30, 0x54, 0x12, 0x30, 0xe5, 0x12, 0x31, 0x68, 0x12, 
+    0x35, 0x20, 0x12, 0x38, 0x58, 0x12, 0x31, 0x15, 0x12, 0x31, 0x40, 0x12, 0x30, 0xa0, 0x80, 0xe0, 
+    0xe5, 0x23, 0x60, 0x19, 0x7e, 0x14, 0x00, 0x00, 0x09, 0xb1, 0x01, 0xcf, 0xb4, 0x00, 0x02, 0x80, 
+    0x05, 0x14, 0x19, 0xb1, 0x01, 0xcf, 0xa5, 0x0b, 0xbe, 0x31, 0x2f, 0x78, 0xeb, 0x22, 0xc2, 0xaf, 
+    0x7e, 0xb3, 0x3f, 0xf1, 0xb4, 0x01, 0x0a, 0xc0, 0xf1, 0x75, 0xf1, 0x02, 0x12, 0x70, 0xef, 0xd0, 
+    0xf1, 0xd2, 0xaf, 0x22, 0xc2, 0xaf, 0xe5, 0x22, 0x60, 0x43, 0x7e, 0x07, 0x01, 0xe1, 0xbe, 0x04, 
+    0x03, 0x80, 0x38, 0x39, 0x7e, 0x04, 0x80, 0x00, 0x7e, 0x20, 0x00, 0x13, 0x50, 0x21, 0x09, 0xa0, 
+    0x00, 0x04, 0x4e, 0xa0, 0x05, 0x19, 0xa0, 0x00, 0x04, 0x0a, 0x32, 0x09, 0x53, 0x67, 0x8e, 0x5e, 
+    0x51, 0x27, 0x68, 0x0b, 0x09, 0xa0, 0x00, 0x10, 0x4e, 0xa0, 0x01, 0x19, 0xa0, 0x00, 0x10, 0x2e, 
+    0x04, 0x01, 0x00, 0xa5, 0x0a, 0xbe, 0x21, 0x2f, 0x78, 0xd1, 0x75, 0x22, 0x00, 0xd2, 0xaf, 0x22, 
+    0xc2, 0xaf, 0x7e, 0x20, 0x00, 0x7e, 0x30, 0x01, 0x7c, 0xb2, 0x23, 0x0a, 0x2b, 0x49, 0x32, 0x01, 
+    0x8f, 0xbe, 0x34, 0x00, 0x00, 0x68, 0x12, 0x7e, 0xb1, 0x21, 0xa5, 0x4b, 0x7a, 0xb1, 0x21, 0xca, 
+    0x19, 0x49, 0x22, 0x30, 0xd5, 0x99, 0x24, 0xda, 0x19, 0x3e, 0x30, 0xa5, 0x0a, 0xbe, 0x21, 0x2f, 
+    0x78, 0xd6, 0xd2, 0xaf, 0x22, 0x46, 0x0f, 0x49, 0x67, 0x4c, 0xbf, 0x50, 0x17, 0x53, 0x6f, 0x56, 
+    0xc7, 0x5a, 0x1f, 0x5d, 0x77, 0xc2, 0xaf, 0xe5, 0x32, 0x60, 0x14, 0x7e, 0x20, 0x00, 0x13, 0x50, 
+    0x07, 0xca, 0xb8, 0x12, 0x31, 0x02, 0xda, 0xb8, 0xa5, 0x0a, 0xbe, 0x21, 0x2f, 0x78, 0xef, 0xd2, 
+    0xaf, 0x22, 0xca, 0x28, 0x12, 0x67, 0xab, 0xda, 0x28, 0x40, 0x09, 0x0a, 0x22, 0x09, 0xb2, 0x67, 
+    0x8e, 0xf4, 0x52, 0x32, 0x22, 0xc2, 0xaf, 0xe5, 0x34, 0x60, 0x14, 0x7e, 0x20, 0x00, 0x13, 0x50, 
+    0x07, 0xca, 0xb8, 0x12, 0x31, 0x32, 0xda, 0xb8, 0xa5, 0x0a, 0xbe, 0x21, 0x2f, 0x78, 0xef, 0xd2, 
+    0xaf, 0x22, 0xca, 0x28, 0x0a, 0x22, 0x09, 0x42, 0x00, 0x3e, 0x12, 0x69, 0xc2, 0xda, 0x28, 0x22, 
+    0xc2, 0xaf, 0xe5, 0x35, 0x60, 0x14, 0x7e, 0x20, 0x00, 0x13, 0x50, 0x07, 0xca, 0xb8, 0x12, 0x31, 
+    0x5d, 0xda, 0xb8, 0xa5, 0x0a, 0xbe, 0x21, 0x2f, 0x78, 0xef, 0xd2, 0xaf, 0x22, 0xca, 0x28, 0x7e, 
+    0x40, 0x00, 0x12, 0x6c, 0x5b, 0xda, 0x28, 0x22, 0xc2, 0xaf, 0xe5, 0x23, 0x60, 0x14, 0x7e, 0x20, 
+    0x00, 0x13, 0x50, 0x07, 0xca, 0xb8, 0x12, 0x31, 0x85, 0xda, 0xb8, 0xa5, 0x0a, 0xbe, 0x21, 0x2f, 
+    0x78, 0xef, 0xd2, 0xaf, 0x22, 0x7c, 0xb2, 0x23, 0x0a, 0x2b, 0x49, 0x22, 0x31, 0x90, 0x89, 0x24, 
+    0x31, 0xa0, 0x32, 0x10, 0x32, 0x80, 0x32, 0xf0, 0x33, 0x60, 0x33, 0xd0, 0x34, 0x40, 0x34, 0xb0, 
+    0x7e, 0x27, 0x01, 0x8f, 0xbe, 0x24, 0x00, 0x00, 0x78, 0x24, 0x7e, 0x24, 0x80, 0x00, 0x09, 0xb2, 
+    0x00, 0x14, 0xca, 0xb8, 0x5e, 0xb0, 0x1e, 0xda, 0xb8, 0x68, 0x0b, 0xca, 0x19, 0x7d, 0x12, 0x12, 
+    0x49, 0x30, 0x7d, 0x21, 0xda, 0x19, 0x30, 0xe6, 0x18, 0x7e, 0x60, 0x00, 0x80, 0x1e, 0xbe, 0x27, 
+    0x01, 0x9f, 0x68, 0x0d, 0x7a, 0x27, 0x01, 0x9f, 0x7e, 0x60, 0x9c, 0x7a, 0x63, 0x01, 0xcf, 0x80, 
+    0x2e, 0x7e, 0x63, 0x01, 0xcf, 0xa5, 0xbe, 0x00, 0x26, 0x7e, 0x60, 0x01, 0x7e, 0xb0, 0x00, 0x7e, 
+    0xa0, 0xc8, 0x12, 0x62, 0xb6, 0x40, 0x18, 0x75, 0x31, 0xb3, 0x12, 0x7c, 0x15, 0xc2, 0x18, 0x6c, 
+    0x00, 0x7a, 0x03, 0x01, 0xcf, 0xc0, 0xf1, 0x75, 0xf1, 0x01, 0x12, 0x6f, 0xd9, 0xd0, 0xf1, 0x22, 
+    0x7e, 0x27, 0x01, 0x91, 0xbe, 0x24, 0x00, 0x00, 0x78, 0x24, 0x7e, 0x24, 0x81, 0x00, 0x09, 0xb2, 
+    0x00, 0x14, 0xca, 0xb8, 0x5e, 0xb0, 0x1e, 0xda, 0xb8, 0x68, 0x0b, 0xca, 0x19, 0x7d, 0x12, 0x12, 
+    0x4c, 0x88, 0x7d, 0x21, 0xda, 0x19, 0x30, 0xe6, 0x18, 0x7e, 0x60, 0x00, 0x80, 0x1e, 0xbe, 0x27, 
+    0x01, 0xa1, 0x68, 0x0d, 0x7a, 0x27, 0x01, 0xa1, 0x7e, 0x60, 0x9c, 0x7a, 0x63, 0x01, 0xd0, 0x80, 
+    0x2e, 0x7e, 0x63, 0x01, 0xd0, 0xa5, 0xbe, 0x00, 0x26, 0x7e, 0x60, 0x01, 0x7e, 0xb0, 0x00, 0x7e, 
+    0xa0, 0xc8, 0x12, 0x62, 0xb6, 0x40, 0x18, 0x75, 0x31, 0xb3, 0x12, 0x7c, 0x15, 0xc2, 0x19, 0x6c, 
+    0x00, 0x7a, 0x03, 0x01, 0xd0, 0xc0, 0xf1, 0x75, 0xf1, 0x01, 0x12, 0x6f, 0xd9, 0xd0, 0xf1, 0x22, 
+    0x7e, 0x27, 0x01, 0x93, 0xbe, 0x24, 0x00, 0x00, 0x78, 0x24, 0x7e, 0x24, 0x82, 0x00, 0x09, 0xb2, 
+    0x00, 0x14, 0xca, 0xb8, 0x5e, 0xb0, 0x1e, 0xda, 0xb8, 0x68, 0x0b, 0xca, 0x19, 0x7d, 0x12, 0x12, 
+    0x4f, 0xe0, 0x7d, 0x21, 0xda, 0x19, 0x30, 0xe6, 0x18, 0x7e, 0x60, 0x00, 0x80, 0x1e, 0xbe, 0x27, 
+    0x01, 0xa3, 0x68, 0x0d, 0x7a, 0x27, 0x01, 0xa3, 0x7e, 0x60, 0x9c, 0x7a, 0x63, 0x01, 0xd1, 0x80, 
+    0x2e, 0x7e, 0x63, 0x01, 0xd1, 0xa5, 0xbe, 0x00, 0x26, 0x7e, 0x60, 0x01, 0x7e, 0xb0, 0x00, 0x7e, 
+    0xa0, 0xc8, 0x12, 0x62, 0xb6, 0x40, 0x18, 0x75, 0x31, 0xb3, 0x12, 0x7c, 0x15, 0xc2, 0x1a, 0x6c, 
+    0x00, 0x7a, 0x03, 0x01, 0xd1, 0xc0, 0xf1, 0x75, 0xf1, 0x01, 0x12, 0x6f, 0xd9, 0xd0, 0xf1, 0x22, 
+    0x7e, 0x27, 0x01, 0x95, 0xbe, 0x24, 0x00, 0x00, 0x78, 0x24, 0x7e, 0x24, 0x83, 0x00, 0x09, 0xb2, 
+    0x00, 0x14, 0xca, 0xb8, 0x5e, 0xb0, 0x1e, 0xda, 0xb8, 0x68, 0x0b, 0xca, 0x19, 0x7d, 0x12, 0x12, 
+    0x53, 0x38, 0x7d, 0x21, 0xda, 0x19, 0x30, 0xe6, 0x18, 0x7e, 0x60, 0x00, 0x80, 0x1e, 0xbe, 0x27, 
+    0x01, 0xa5, 0x68, 0x0d, 0x7a, 0x27, 0x01, 0xa5, 0x7e, 0x60, 0x9c, 0x7a, 0x63, 0x01, 0xd2, 0x80, 
+    0x2e, 0x7e, 0x63, 0x01, 0xd2, 0xa5, 0xbe, 0x00, 0x26, 0x7e, 0x60, 0x01, 0x7e, 0xb0, 0x00, 0x7e, 
+    0xa0, 0xc8, 0x12, 0x62, 0xb6, 0x40, 0x18, 0x75, 0x31, 0xb3, 0x12, 0x7c, 0x15, 0xc2, 0x1b, 0x6c, 
+    0x00, 0x7a, 0x03, 0x01, 0xd2, 0xc0, 0xf1, 0x75, 0xf1, 0x01, 0x12, 0x6f, 0xd9, 0xd0, 0xf1, 0x22, 
+    0x7e, 0x27, 0x01, 0x97, 0xbe, 0x24, 0x00, 0x00, 0x78, 0x24, 0x7e, 0x24, 0x84, 0x00, 0x09, 0xb2, 
+    0x00, 0x14, 0xca, 0xb8, 0x5e, 0xb0, 0x1e, 0xda, 0xb8, 0x68, 0x0b, 0xca, 0x19, 0x7d, 0x12, 0x12, 
+    0x56, 0x90, 0x7d, 0x21, 0xda, 0x19, 0x30, 0xe6, 0x18, 0x7e, 0x60, 0x00, 0x80, 0x1e, 0xbe, 0x27, 
+    0x01, 0xa7, 0x68, 0x0d, 0x7a, 0x27, 0x01, 0xa7, 0x7e, 0x60, 0x9c, 0x7a, 0x63, 0x01, 0xd3, 0x80, 
+    0x2e, 0x7e, 0x63, 0x01, 0xd3, 0xa5, 0xbe, 0x00, 0x26, 0x7e, 0x60, 0x01, 0x7e, 0xb0, 0x00, 0x7e, 
+    0xa0, 0xc8, 0x12, 0x62, 0xb6, 0x40, 0x18, 0x75, 0x31, 0xb3, 0x12, 0x7c, 0x15, 0xc2, 0x1c, 0x6c, 
+    0x00, 0x7a, 0x03, 0x01, 0xd3, 0xc0, 0xf1, 0x75, 0xf1, 0x01, 0x12, 0x6f, 0xd9, 0xd0, 0xf1, 0x22, 
+    0x7e, 0x27, 0x01, 0x99, 0xbe, 0x24, 0x00, 0x00, 0x78, 0x24, 0x7e, 0x24, 0x85, 0x00, 0x09, 0xb2, 
+    0x00, 0x14, 0xca, 0xb8, 0x5e, 0xb0, 0x1e, 0xda, 0xb8, 0x68, 0x0b, 0xca, 0x19, 0x7d, 0x12, 0x12, 
+    0x59, 0xe8, 0x7d, 0x21, 0xda, 0x19, 0x30, 0xe6, 0x18, 0x7e, 0x60, 0x00, 0x80, 0x1e, 0xbe, 0x27, 
+    0x01, 0xa9, 0x68, 0x0d, 0x7a, 0x27, 0x01, 0xa9, 0x7e, 0x60, 0x9c, 0x7a, 0x63, 0x01, 0xd4, 0x80, 
+    0x2e, 0x7e, 0x63, 0x01, 0xd4, 0xa5, 0xbe, 0x00, 0x26, 0x7e, 0x60, 0x01, 0x7e, 0xb0, 0x00, 0x7e, 
+    0xa0, 0xc8, 0x12, 0x62, 0xb6, 0x40, 0x18, 0x75, 0x31, 0xb3, 0x12, 0x7c, 0x15, 0xc2, 0x1d, 0x6c, 
+    0x00, 0x7a, 0x03, 0x01, 0xd4, 0xc0, 0xf1, 0x75, 0xf1, 0x01, 0x12, 0x6f, 0xd9, 0xd0, 0xf1, 0x22, 
+    0x7e, 0x27, 0x01, 0x9b, 0xbe, 0x24, 0x00, 0x00, 0x78, 0x24, 0x7e, 0x24, 0x86, 0x00, 0x09, 0xb2, 
+    0x00, 0x14, 0xca, 0xb8, 0x5e, 0xb0, 0x1e, 0xda, 0xb8, 0x68, 0x0b, 0xca, 0x19, 0x7d, 0x12, 0x12, 
+    0x5d, 0x40, 0x7d, 0x21, 0xda, 0x19, 0x30, 0xe6, 0x18, 0x7e, 0x60, 0x00, 0x80, 0x1e, 0xbe, 0x27, 
+    0x01, 0xab, 0x68, 0x0d, 0x7a, 0x27, 0x01, 0xab, 0x7e, 0x60, 0x9c, 0x7a, 0x63, 0x01, 0xd5, 0x80, 
+    0x2e, 0x7e, 0x63, 0x01, 0xd5, 0xa5, 0xbe, 0x00, 0x26, 0x7e, 0x60, 0x01, 0x7e, 0xb0, 0x00, 0x7e, 
+    0xa0, 0xc8, 0x12, 0x62, 0xb6, 0x40, 0x18, 0x75, 0x31, 0xb3, 0x12, 0x7c, 0x15, 0xc2, 0x1e, 0x6c, 
+    0x00, 0x7a, 0x03, 0x01, 0xd5, 0xc0, 0xf1, 0x75, 0xf1, 0x01, 0x12, 0x6f, 0xd9, 0xd0, 0xf1, 0x22, 
+    0x7e, 0x27, 0x01, 0x9d, 0xbe, 0x24, 0x00, 0x00, 0x78, 0x24, 0x7e, 0x24, 0x87, 0x00, 0x09, 0xb2, 
+    0x00, 0x14, 0xca, 0xb8, 0x5e, 0xb0, 0x1e, 0xda, 0xb8, 0x68, 0x0b, 0xca, 0x19, 0x7d, 0x12, 0x12, 
+    0x60, 0x98, 0x7d, 0x21, 0xda, 0x19, 0x30, 0xe6, 0x18, 0x7e, 0x60, 0x00, 0x80, 0x1e, 0xbe, 0x27, 
+    0x01, 0xad, 0x68, 0x0d, 0x7a, 0x27, 0x01, 0xad, 0x7e, 0x60, 0x9c, 0x7a, 0x63, 0x01, 0xd6, 0x80, 
+    0x2e, 0x7e, 0x63, 0x01, 0xd6, 0xa5, 0xbe, 0x00, 0x26, 0x7e, 0x60, 0x01, 0x7e, 0xb0, 0x00, 0x7e, 
+    0xa0, 0xc8, 0x12, 0x62, 0xb6, 0x40, 0x18, 0x75, 0x31, 0xb3, 0x12, 0x7c, 0x15, 0xc2, 0x1f, 0x6c, 
+    0x00, 0x7a, 0x03, 0x01, 0xd6, 0xc0, 0xf1, 0x75, 0xf1, 0x01, 0x12, 0x6f, 0xd9, 0xd0, 0xf1, 0x22, 
+    0xc2, 0xaf, 0xe5, 0x24, 0x60, 0x14, 0x7e, 0x20, 0x00, 0x13, 0x50, 0x07, 0xca, 0xb8, 0x12, 0x35, 
+    0x3d, 0xda, 0xb8, 0xa5, 0x0a, 0xbe, 0x21, 0x2f, 0x78, 0xef, 0xd2, 0xaf, 0x22, 0x7c, 0xb2, 0x23, 
+    0x0a, 0x2b, 0x49, 0x22, 0x35, 0x48, 0x89, 0x24, 0x35, 0x58, 0x35, 0x92, 0x35, 0xcc, 0x36, 0x06, 
+    0x36, 0x40, 0x36, 0x7a, 0x36, 0xb4, 0x36, 0xee, 0x7e, 0x24, 0x80, 0x00, 0x09, 0xb2, 0x00, 0x14, 
+    0xca, 0xb8, 0x5e, 0xb0, 0x1e, 0xda, 0xb8, 0x68, 0x0b, 0xca, 0x19, 0x7d, 0x12, 0x12, 0x49, 0x30, 
+    0x7d, 0x21, 0xda, 0x19, 0x5e, 0xb0, 0x01, 0x7e, 0xa0, 0x90, 0x12, 0x62, 0x93, 0x40, 0x12, 0x75, 
+    0x31, 0xb8, 0x12, 0x7c, 0x15, 0xc2, 0x20, 0xc0, 0xf1, 0x75, 0xf1, 0x01, 0x12, 0x6f, 0xd9, 0xd0, 
+    0xf1, 0x22, 0x7e, 0x24, 0x81, 0x00, 0x09, 0xb2, 0x00, 0x14, 0xca, 0xb8, 0x5e, 0xb0, 0x1e, 0xda, 
+    0xb8, 0x68, 0x0b, 0xca, 0x19, 0x7d, 0x12, 0x12, 0x4c, 0x88, 0x7d, 0x21, 0xda, 0x19, 0x5e, 0xb0, 
+    0x01, 0x7e, 0xa0, 0x90, 0x12, 0x62, 0x93, 0x40, 0x12, 0x75, 0x31, 0xb8, 0x12, 0x7c, 0x15, 0xc2, 
+    0x21, 0xc0, 0xf1, 0x75, 0xf1, 0x01, 0x12, 0x6f, 0xd9, 0xd0, 0xf1, 0x22, 0x7e, 0x24, 0x82, 0x00, 
+    0x09, 0xb2, 0x00, 0x14, 0xca, 0xb8, 0x5e, 0xb0, 0x1e, 0xda, 0xb8, 0x68, 0x0b, 0xca, 0x19, 0x7d, 
+    0x12, 0x12, 0x4f, 0xe0, 0x7d, 0x21, 0xda, 0x19, 0x5e, 0xb0, 0x01, 0x7e, 0xa0, 0x90, 0x12, 0x62, 
+    0x93, 0x40, 0x12, 0x75, 0x31, 0xb8, 0x12, 0x7c, 0x15, 0xc2, 0x22, 0xc0, 0xf1, 0x75, 0xf1, 0x01, 
+    0x12, 0x6f, 0xd9, 0xd0, 0xf1, 0x22, 0x7e, 0x24, 0x83, 0x00, 0x09, 0xb2, 0x00, 0x14, 0xca, 0xb8, 
+    0x5e, 0xb0, 0x1e, 0xda, 0xb8, 0x68, 0x0b, 0xca, 0x19, 0x7d, 0x12, 0x12, 0x53, 0x38, 0x7d, 0x21, 
+    0xda, 0x19, 0x5e, 0xb0, 0x01, 0x7e, 0xa0, 0x90, 0x12, 0x62, 0x93, 0x40, 0x12, 0x75, 0x31, 0xb8, 
+    0x12, 0x7c, 0x15, 0xc2, 0x23, 0xc0, 0xf1, 0x75, 0xf1, 0x01, 0x12, 0x6f, 0xd9, 0xd0, 0xf1, 0x22, 
+    0x7e, 0x24, 0x84, 0x00, 0x09, 0xb2, 0x00, 0x14, 0xca, 0xb8, 0x5e, 0xb0, 0x1e, 0xda, 0xb8, 0x68, 
+    0x0b, 0xca, 0x19, 0x7d, 0x12, 0x12, 0x56, 0x90, 0x7d, 0x21, 0xda, 0x19, 0x5e, 0xb0, 0x01, 0x7e, 
+    0xa0, 0x90, 0x12, 0x62, 0x93, 0x40, 0x12, 0x75, 0x31, 0xb8, 0x12, 0x7c, 0x15, 0xc2, 0x24, 0xc0, 
+    0xf1, 0x75, 0xf1, 0x01, 0x12, 0x6f, 0xd9, 0xd0, 0xf1, 0x22, 0x7e, 0x24, 0x85, 0x00, 0x09, 0xb2, 
+    0x00, 0x14, 0xca, 0xb8, 0x5e, 0xb0, 0x1e, 0xda, 0xb8, 0x68, 0x0b, 0xca, 0x19, 0x7d, 0x12, 0x12, 
+    0x59, 0xe8, 0x7d, 0x21, 0xda, 0x19, 0x5e, 0xb0, 0x01, 0x7e, 0xa0, 0x90, 0x12, 0x62, 0x93, 0x40, 
+    0x12, 0x75, 0x31, 0xb8, 0x12, 0x7c, 0x15, 0xc2, 0x25, 0xc0, 0xf1, 0x75, 0xf1, 0x01, 0x12, 0x6f, 
+    0xd9, 0xd0, 0xf1, 0x22, 0x7e, 0x24, 0x86, 0x00, 0x09, 0xb2, 0x00, 0x14, 0xca, 0xb8, 0x5e, 0xb0, 
+    0x1e, 0xda, 0xb8, 0x68, 0x0b, 0xca, 0x19, 0x7d, 0x12, 0x12, 0x5d, 0x40, 0x7d, 0x21, 0xda, 0x19, 
+    0x5e, 0xb0, 0x01, 0x7e, 0xa0, 0x90, 0x12, 0x62, 0x93, 0x40, 0x12, 0x75, 0x31, 0xb8, 0x12, 0x7c, 
+    0x15, 0xc2, 0x26, 0xc0, 0xf1, 0x75, 0xf1, 0x01, 0x12, 0x6f, 0xd9, 0xd0, 0xf1, 0x22, 0x7e, 0x24, 
+    0x87, 0x00, 0x09, 0xb2, 0x00, 0x14, 0xca, 0xb8, 0x5e, 0xb0, 0x1e, 0xda, 0xb8, 0x68, 0x0b, 0xca, 
+    0x19, 0x7d, 0x12, 0x12, 0x60, 0x98, 0x7d, 0x21, 0xda, 0x19, 0x5e, 0xb0, 0x01, 0x7e, 0xa0, 0x90, 
+    0x12, 0x62, 0x93, 0x40, 0x12, 0x75, 0x31, 0xb8, 0x12, 0x7c, 0x15, 0xc2, 0x27, 0xc0, 0xf1, 0x75, 
+    0xf1, 0x01, 0x12, 0x6f, 0xd9, 0xd0, 0xf1, 0x22, 0xc2, 0xaf, 0xe5, 0x33, 0x60, 0x14, 0x7e, 0x20, 
+    0x00, 0x13, 0x50, 0x07, 0xca, 0xb8, 0x12, 0x37, 0x45, 0xda, 0xb8, 0xa5, 0x0a, 0xbe, 0x21, 0x2f, 
+    0x78, 0xef, 0xd2, 0xaf, 0x22, 0x7c, 0xb2, 0x23, 0x0a, 0x2b, 0x49, 0x22, 0x37, 0x50, 0x89, 0x24, 
+    0x37, 0x60, 0x37, 0x7f, 0x37, 0x9e, 0x37, 0xbd, 0x37, 0xdc, 0x37, 0xfb, 0x38, 0x1a, 0x38, 0x39, 
+    0x7e, 0x24, 0x80, 0x00, 0xca, 0x19, 0x7d, 0x12, 0x12, 0x48, 0x1b, 0xda, 0x19, 0x10, 0x04, 0x02, 
+    0x80, 0x0c, 0xd2, 0x01, 0xc0, 0xf1, 0x75, 0xf1, 0x01, 0x12, 0x6f, 0xd9, 0xd0, 0xf1, 0x22, 0x7e, 
+    0x24, 0x81, 0x00, 0xca, 0x19, 0x7d, 0x12, 0x12, 0x4b, 0x73, 0xda, 0x19, 0x10, 0x04, 0x02, 0x80, 
+    0x0c, 0xd2, 0x01, 0xc0, 0xf1, 0x75, 0xf1, 0x01, 0x12, 0x6f, 0xd9, 0xd0, 0xf1, 0x22, 0x7e, 0x24, 
+    0x82, 0x00, 0xca, 0x19, 0x7d, 0x12, 0x12, 0x4e, 0xcb, 0xda, 0x19, 0x10, 0x04, 0x02, 0x80, 0x0c, 
+    0xd2, 0x01, 0xc0, 0xf1, 0x75, 0xf1, 0x01, 0x12, 0x6f, 0xd9, 0xd0, 0xf1, 0x22, 0x7e, 0x24, 0x83, 
+    0x00, 0xca, 0x19, 0x7d, 0x12, 0x12, 0x52, 0x23, 0xda, 0x19, 0x10, 0x04, 0x02, 0x80, 0x0c, 0xd2, 
+    0x01, 0xc0, 0xf1, 0x75, 0xf1, 0x01, 0x12, 0x6f, 0xd9, 0xd0, 0xf1, 0x22, 0x7e, 0x24, 0x84, 0x00, 
+    0xca, 0x19, 0x7d, 0x12, 0x12, 0x55, 0x7b, 0xda, 0x19, 0x10, 0x04, 0x02, 0x80, 0x0c, 0xd2, 0x01, 
+    0xc0, 0xf1, 0x75, 0xf1, 0x01, 0x12, 0x6f, 0xd9, 0xd0, 0xf1, 0x22, 0x7e, 0x24, 0x85, 0x00, 0xca, 
+    0x19, 0x7d, 0x12, 0x12, 0x58, 0xd3, 0xda, 0x19, 0x10, 0x04, 0x02, 0x80, 0x0c, 0xd2, 0x01, 0xc0, 
+    0xf1, 0x75, 0xf1, 0x01, 0x12, 0x6f, 0xd9, 0xd0, 0xf1, 0x22, 0x7e, 0x24, 0x86, 0x00, 0xca, 0x19, 
+    0x7d, 0x12, 0x12, 0x5c, 0x2b, 0xda, 0x19, 0x10, 0x04, 0x02, 0x80, 0x0c, 0xd2, 0x01, 0xc0, 0xf1, 
+    0x75, 0xf1, 0x01, 0x12, 0x6f, 0xd9, 0xd0, 0xf1, 0x22, 0x7e, 0x24, 0x87, 0x00, 0xca, 0x19, 0x7d, 
+    0x12, 0x12, 0x5f, 0x83, 0xda, 0x19, 0x10, 0x04, 0x02, 0x80, 0x0c, 0xd2, 0x01, 0xc0, 0xf1, 0x75, 
+    0xf1, 0x01, 0x12, 0x6f, 0xd9, 0xd0, 0xf1, 0x22, 0xc2, 0xaf, 0xc0, 0xf1, 0x75, 0xf1, 0x01, 0xa9, 
+    0x32, 0xf2, 0x1a, 0x7e, 0x07, 0x01, 0xe1, 0xbe, 0x04, 0x00, 0x00, 0x78, 0x10, 0xe5, 0xf5, 0x33, 
+    0x82, 0xe7, 0x40, 0x09, 0x85, 0x31, 0x31, 0x12, 0x7c, 0x15, 0x75, 0xf6, 0x00, 0xd0, 0xf1, 0xd2, 
+    0xaf, 0x22, 
+
+// Segment #15, Start Address 00ff4000, Length 15381
+0xff,0x00,0x00,0x40,0x15,0x3c,
     0x7e, 0x04, 0x00, 0x01, 0x7e, 0x14, 0x7f, 0xf8, 0x7e, 0x24, 0x00, 0xfe, 0x7d, 0x31, 0x0b, 0x1a, 
-    0x50, 0x1b, 0x0a, 0x50, 0x7e, 0x14, 0x40, 0x1b, 0x02, 0x40, 0x6a, 0x7e, 0xf8, 0x00, 0x59, 0xd2, 
-    0x04, 0xc2, 0x94, 0xd2, 0x95, 0x7e, 0xf4, 0x40, 0x2c, 0x02, 0x40, 0x7c, 0x12, 0x7f, 0x3f, 0xf5, 
-    0x2e, 0x7a, 0xa1, 0x2d, 0x7a, 0x11, 0x58, 0x12, 0x77, 0xda, 0x12, 0x40, 0xdc, 0x7e, 0xb3, 0x3f, 
-    0xf1, 0x60, 0x03, 0x12, 0x43, 0x68, 0x75, 0xf1, 0x00, 0x12, 0x78, 0x7f, 0xd2, 0xaf, 0x02, 0x44, 
-    0x06, 0x7e, 0x04, 0x00, 0xff, 0x7e, 0x18, 0x40, 0x5f, 0x7a, 0x1c, 0x00, 0x01, 0x89, 0x18, 0xa9, 
+    0x50, 0x1b, 0x0a, 0x50, 0x7e, 0x14, 0x40, 0x1b, 0x02, 0x40, 0x6a, 0x7e, 0xf8, 0x00, 0x6f, 0xd2, 
+    0x04, 0xc2, 0x94, 0xd2, 0x95, 0x7e, 0xf4, 0x40, 0x2c, 0x02, 0x40, 0x7c, 0x12, 0x7d, 0x30, 0xf5, 
+    0x2f, 0x7a, 0xa1, 0x30, 0x7a, 0x11, 0x6e, 0x12, 0x75, 0xca, 0x12, 0x40, 0xdc, 0x7e, 0xb3, 0x3f, 
+    0xf1, 0x60, 0x03, 0x12, 0x43, 0xd4, 0x75, 0xf1, 0x00, 0x12, 0x76, 0x6f, 0xd2, 0xaf, 0x02, 0x30, 
+    0x00, 0x7e, 0x04, 0x00, 0xff, 0x7e, 0x18, 0x40, 0x5f, 0x7a, 0x1c, 0x00, 0x01, 0x89, 0x18, 0xa9, 
     0x25, 0x87, 0x03, 0xa9, 0xd5, 0x87, 0xd2, 0x93, 0x89, 0x08, 0x7e, 0x04, 0x00, 0xff, 0x7e, 0x18, 
     0x40, 0x78, 0x7a, 0x1c, 0x00, 0x01, 0x89, 0x18, 0xc2, 0x93, 0x89, 0x08, 0x7e, 0x08, 0x00, 0x20, 
-    0x7e, 0x44, 0x04, 0x00, 0x7e, 0x40, 0x00, 0x7e, 0xe4, 0x40, 0x8e, 0x02, 0x7e, 0x4b, 0x7e, 0x08, 
-    0x01, 0x59, 0x7e, 0x44, 0x28, 0x7c, 0x7e, 0x40, 0x00, 0x7e, 0xe4, 0x40, 0xa0, 0x02, 0x7e, 0x4b, 
-    0x7e, 0x08, 0x00, 0x59, 0x7e, 0x44, 0x01, 0x00, 0x7e, 0x40, 0x53, 0x7e, 0xe4, 0x40, 0xb2, 0x02, 
-    0x7e, 0x4b, 0x75, 0x57, 0x20, 0x75, 0x56, 0x30, 0x7e, 0x04, 0x00, 0x08, 0x75, 0x54, 0x58, 0x75, 
-    0x55, 0x08, 0x75, 0x51, 0x08, 0x75, 0x53, 0x01, 0x75, 0x89, 0x01, 0x75, 0x8a, 0x01, 0x75, 0x8c, 
-    0x00, 0xd2, 0x8c, 0x7e, 0x04, 0x00, 0x02, 0x7a, 0x05, 0x42, 0x89, 0xf4, 0x75, 0xb7, 0x7f, 0x75, 
+    0x7e, 0x44, 0x04, 0x00, 0x7e, 0x40, 0x00, 0x7e, 0xe4, 0x40, 0x8e, 0x02, 0x7c, 0x30, 0x7e, 0x08, 
+    0x01, 0x6f, 0x7e, 0x44, 0x28, 0x7c, 0x7e, 0x40, 0x00, 0x7e, 0xe4, 0x40, 0xa0, 0x02, 0x7c, 0x30, 
+    0x7e, 0x08, 0x00, 0x6f, 0x7e, 0x44, 0x01, 0x00, 0x7e, 0x40, 0x53, 0x7e, 0xe4, 0x40, 0xb2, 0x02, 
+    0x7c, 0x30, 0x75, 0x6d, 0x20, 0x75, 0x6c, 0x30, 0x7e, 0x04, 0x00, 0x08, 0x75, 0x6a, 0x58, 0x75, 
+    0x6b, 0x08, 0x75, 0x67, 0x08, 0x75, 0x69, 0x01, 0x75, 0x89, 0x01, 0x75, 0x8a, 0x01, 0x75, 0x8c, 
+    0x00, 0xd2, 0x8c, 0x7e, 0x04, 0x00, 0x02, 0x7a, 0x05, 0x58, 0x89, 0xf4, 0x75, 0xb7, 0x7f, 0x75, 
     0xb8, 0x7f, 0x75, 0xb3, 0x07, 0x75, 0xb2, 0x07, 0xd2, 0xa9, 0x22, 0xd2, 0x92, 0xe4, 0xd5, 0xe0, 
-    0xfd, 0xc2, 0x92, 0x7e, 0x24, 0x80, 0x00, 0x7e, 0x11, 0x2e, 0x7e, 0xa0, 0x08, 0x19, 0xa2, 0x00, 
-    0x10, 0x2e, 0x24, 0x01, 0x00, 0xa5, 0xd9, 0xf2, 0x7e, 0x20, 0x00, 0x12, 0x41, 0x72, 0x0b, 0x20, 
-    0xbe, 0x21, 0x2e, 0x78, 0xf6, 0x22, 0x7e, 0x04, 0x80, 0x00, 0x4c, 0x02, 0x74, 0xbf, 0x19, 0xb0, 
+    0xfd, 0xc2, 0x92, 0x7e, 0x24, 0x80, 0x00, 0x7e, 0x11, 0x2f, 0x7e, 0xa0, 0x08, 0x19, 0xa2, 0x00, 
+    0x10, 0x2e, 0x24, 0x01, 0x00, 0xa5, 0xd9, 0xf2, 0x7e, 0x20, 0x00, 0x12, 0x41, 0x7e, 0x0b, 0x20, 
+    0xbe, 0x21, 0x2f, 0x78, 0xf6, 0x22, 0x7e, 0x04, 0x80, 0x00, 0x4c, 0x02, 0x74, 0xbf, 0x19, 0xb0, 
     0x00, 0x0c, 0x74, 0x10, 0x19, 0xb0, 0x00, 0x08, 0x74, 0x80, 0x19, 0xb0, 0x00, 0x0c, 0x7e, 0x54, 
     0x00, 0x02, 0x19, 0xa0, 0x00, 0x04, 0x19, 0xb0, 0x00, 0x00, 0x74, 0x03, 0x19, 0xb0, 0x00, 0x0c, 
-    0x74, 0x07, 0x20, 0x68, 0x02, 0x74, 0x0f, 0x19, 0xb0, 0x00, 0x04, 0x30, 0x6b, 0x17, 0x74, 0xbf, 
-    0x19, 0xb0, 0x00, 0x0c, 0x74, 0x28, 0x20, 0x68, 0x02, 0x74, 0x20, 0x19, 0xb0, 0x00, 0x04, 0x74, 
-    0x03, 0x19, 0xb0, 0x00, 0x0c, 0x74, 0xa7, 0x19, 0xb0, 0x00, 0x08, 0x74, 0x0c, 0x19, 0xb0, 0x00, 
-    0x10, 0x22, 0x7e, 0x04, 0x80, 0x00, 0x4c, 0x02, 0xe4, 0x19, 0xb0, 0x00, 0x04, 0x09, 0xb0, 0x00, 
-    0x10, 0x54, 0x08, 0x19, 0xb0, 0x00, 0x10, 0x74, 0xa7, 0x19, 0xb0, 0x00, 0x08, 0x22, 0x7c, 0xb2, 
-    0x23, 0x0a, 0x2b, 0x49, 0x22, 0x41, 0x99, 0x89, 0x24, 0x41, 0xa9, 0x41, 0xc6, 0x41, 0xe3, 0x42, 
-    0x00, 0x42, 0x1d, 0x42, 0x3a, 0x42, 0x57, 0x42, 0x74, 0xc2, 0x10, 0xc2, 0x18, 0xc2, 0x08, 0x7e, 
-    0x04, 0x09, 0xcd, 0x7a, 0x07, 0x01, 0x59, 0x7a, 0x07, 0x01, 0x69, 0x6d, 0x00, 0x7a, 0x07, 0x01, 
-    0x79, 0x7a, 0x07, 0x01, 0x89, 0x22, 0xc2, 0x11, 0xc2, 0x19, 0xc2, 0x09, 0x7e, 0x04, 0x0d, 0xcd, 
-    0x7a, 0x07, 0x01, 0x5b, 0x7a, 0x07, 0x01, 0x6b, 0x6d, 0x00, 0x7a, 0x07, 0x01, 0x7b, 0x7a, 0x07, 
-    0x01, 0x8b, 0x22, 0xc2, 0x12, 0xc2, 0x1a, 0xc2, 0x0a, 0x7e, 0x04, 0x11, 0xcd, 0x7a, 0x07, 0x01, 
-    0x5d, 0x7a, 0x07, 0x01, 0x6d, 0x6d, 0x00, 0x7a, 0x07, 0x01, 0x7d, 0x7a, 0x07, 0x01, 0x8d, 0x22, 
-    0xc2, 0x13, 0xc2, 0x1b, 0xc2, 0x0b, 0x7e, 0x04, 0x15, 0xcd, 0x7a, 0x07, 0x01, 0x5f, 0x7a, 0x07, 
-    0x01, 0x6f, 0x6d, 0x00, 0x7a, 0x07, 0x01, 0x7f, 0x7a, 0x07, 0x01, 0x8f, 0x22, 0xc2, 0x14, 0xc2, 
-    0x1c, 0xc2, 0x0c, 0x7e, 0x04, 0x19, 0xcd, 0x7a, 0x07, 0x01, 0x61, 0x7a, 0x07, 0x01, 0x71, 0x6d, 
-    0x00, 0x7a, 0x07, 0x01, 0x81, 0x7a, 0x07, 0x01, 0x91, 0x22, 0xc2, 0x15, 0xc2, 0x1d, 0xc2, 0x0d, 
-    0x7e, 0x04, 0x1d, 0xcd, 0x7a, 0x07, 0x01, 0x63, 0x7a, 0x07, 0x01, 0x73, 0x6d, 0x00, 0x7a, 0x07, 
-    0x01, 0x83, 0x7a, 0x07, 0x01, 0x93, 0x22, 0xc2, 0x16, 0xc2, 0x1e, 0xc2, 0x0e, 0x7e, 0x04, 0x21, 
-    0xcd, 0x7a, 0x07, 0x01, 0x65, 0x7a, 0x07, 0x01, 0x75, 0x6d, 0x00, 0x7a, 0x07, 0x01, 0x85, 0x7a, 
-    0x07, 0x01, 0x95, 0x22, 0xc2, 0x17, 0xc2, 0x1f, 0xc2, 0x0f, 0x7e, 0x04, 0x25, 0xcd, 0x7a, 0x07, 
-    0x01, 0x67, 0x7a, 0x07, 0x01, 0x77, 0x6d, 0x00, 0x7a, 0x07, 0x01, 0x87, 0x7a, 0x07, 0x01, 0x97, 
-    0x22, 0x7c, 0xb2, 0x23, 0x0a, 0x2b, 0x49, 0x22, 0x42, 0x9c, 0x89, 0x24, 0x42, 0xac, 0x42, 0xc3, 
-    0x42, 0xda, 0x42, 0xf1, 0x43, 0x08, 0x43, 0x1f, 0x43, 0x36, 0x43, 0x4d, 0x30, 0x40, 0x07, 0x20, 
-    0x58, 0x04, 0xc2, 0x28, 0x80, 0x0c, 0x30, 0x48, 0x07, 0x20, 0x50, 0x04, 0xc2, 0x28, 0x80, 0x02, 
-    0xd2, 0x28, 0x22, 0x30, 0x41, 0x07, 0x20, 0x59, 0x04, 0xc2, 0x29, 0x80, 0x0c, 0x30, 0x49, 0x07, 
-    0x20, 0x51, 0x04, 0xc2, 0x29, 0x80, 0x02, 0xd2, 0x29, 0x22, 0x30, 0x42, 0x07, 0x20, 0x5a, 0x04, 
-    0xc2, 0x2a, 0x80, 0x0c, 0x30, 0x4a, 0x07, 0x20, 0x52, 0x04, 0xc2, 0x2a, 0x80, 0x02, 0xd2, 0x2a, 
-    0x22, 0x30, 0x43, 0x07, 0x20, 0x5b, 0x04, 0xc2, 0x2b, 0x80, 0x0c, 0x30, 0x4b, 0x07, 0x20, 0x53, 
-    0x04, 0xc2, 0x2b, 0x80, 0x02, 0xd2, 0x2b, 0x22, 0x30, 0x44, 0x07, 0x20, 0x5c, 0x04, 0xc2, 0x2c, 
-    0x80, 0x0c, 0x30, 0x4c, 0x07, 0x20, 0x54, 0x04, 0xc2, 0x2c, 0x80, 0x02, 0xd2, 0x2c, 0x22, 0x30, 
-    0x45, 0x07, 0x20, 0x5d, 0x04, 0xc2, 0x2d, 0x80, 0x0c, 0x30, 0x4d, 0x07, 0x20, 0x55, 0x04, 0xc2, 
-    0x2d, 0x80, 0x02, 0xd2, 0x2d, 0x22, 0x30, 0x46, 0x07, 0x20, 0x5e, 0x04, 0xc2, 0x2e, 0x80, 0x0c, 
-    0x30, 0x4e, 0x07, 0x20, 0x56, 0x04, 0xc2, 0x2e, 0x80, 0x02, 0xd2, 0x2e, 0x22, 0x30, 0x47, 0x07, 
-    0x20, 0x5f, 0x04, 0xc2, 0x2f, 0x80, 0x0c, 0x30, 0x4f, 0x07, 0x20, 0x57, 0x04, 0xc2, 0x2f, 0x80, 
-    0x02, 0xd2, 0x2f, 0x22, 0x43, 0xcc, 0x43, 0x79, 0xbe, 0xb0, 0x02, 0x40, 0x01, 0x22, 0x23, 0x0a, 
-    0x5b, 0x49, 0x55, 0x43, 0x64, 0x99, 0x54, 0xd3, 0x22, 0xa9, 0xc5, 0x87, 0x12, 0x43, 0xd7, 0x7e, 
-    0x04, 0x05, 0xcd, 0x7a, 0x07, 0x01, 0xc1, 0x7a, 0x07, 0x01, 0xc3, 0x7e, 0x04, 0x01, 0xcd, 0x7a, 
-    0x07, 0x01, 0xc7, 0x7a, 0x07, 0x01, 0xc9, 0x7e, 0x04, 0x76, 0xbd, 0x7a, 0x05, 0x4b, 0x75, 0xf1, 
-    0x01, 0x75, 0xe1, 0x1f, 0x75, 0xe4, 0x04, 0x75, 0xf4, 0x04, 0x75, 0xf1, 0x02, 0x75, 0xe1, 0x03, 
-    0x75, 0xe4, 0x04, 0x75, 0xf4, 0x04, 0x43, 0xa2, 0x1c, 0x12, 0x40, 0xeb, 0x7e, 0x20, 0x00, 0x12, 
-    0x41, 0x8e, 0x0b, 0x20, 0xbe, 0x21, 0x2e, 0x78, 0xf6, 0xd2, 0xa8, 0x22, 0xa9, 0xd5, 0x87, 0x12, 
-    0x43, 0xd7, 0xd2, 0x92, 0xc2, 0xa8, 0x22, 0x75, 0xa3, 0x00, 0x53, 0xa2, 0x03, 0x75, 0xc1, 0x00, 
-    0x53, 0xc0, 0x03, 0x7e, 0x00, 0x05, 0x7a, 0x01, 0xf1, 0x43, 0xf4, 0x80, 0x43, 0xe4, 0x80, 0xe5, 
-    0xf2, 0x54, 0x7f, 0x44, 0x08, 0xf5, 0xf2, 0xe5, 0xe2, 0x54, 0x7f, 0x44, 0x08, 0xf5, 0xe2, 0x75, 
-    0xe1, 0x10, 0xa5, 0xd8, 0xe1, 0x22, 0x12, 0x44, 0x76, 0x12, 0x44, 0x8c, 0x12, 0x45, 0x27, 0x12, 
-    0x45, 0x57, 0x12, 0x49, 0x0f, 0x12, 0x44, 0xd8, 0x80, 0xec, 0xca, 0x09, 0x12, 0x44, 0x58, 0x10, 
-    0x01, 0x12, 0xd5, 0x51, 0x1e, 0x63, 0x53, 0x01, 0x7e, 0x00, 0x54, 0x2e, 0x01, 0x53, 0xa5, 0xe6, 
-    0xf5, 0x51, 0x80, 0x12, 0x20, 0x02, 0x1e, 0x75, 0x53, 0x00, 0x85, 0x54, 0x51, 0xd2, 0x02, 0x74, 
-    0x00, 0x80, 0x0d, 0x30, 0x02, 0x0f, 0xc2, 0x02, 0x7e, 0x00, 0x56, 0x2e, 0x01, 0x53, 0xa5, 0xe6, 
-    0x53, 0x90, 0xcf, 0x42, 0x90, 0xda, 0x09, 0x32, 0xe5, 0x23, 0x60, 0x19, 0x7e, 0x14, 0x00, 0x00, 
-    0x09, 0xb1, 0x01, 0xb9, 0xb4, 0x00, 0x02, 0x80, 0x05, 0x14, 0x19, 0xb1, 0x01, 0xb9, 0xa5, 0x0a, 
-    0xbe, 0x21, 0x2e, 0x78, 0xeb, 0x22, 0xc2, 0xaf, 0x7e, 0xb3, 0x3f, 0xf1, 0xb4, 0x01, 0x0a, 0xc0, 
-    0xf1, 0x75, 0xf1, 0x02, 0x12, 0x72, 0xff, 0xd0, 0xf1, 0xd2, 0xaf, 0x22, 0xc2, 0xaf, 0xe5, 0x22, 
-    0x60, 0x43, 0x7e, 0x07, 0x01, 0xcb, 0xbe, 0x04, 0x03, 0x80, 0x38, 0x39, 0x7e, 0x04, 0x80, 0x00, 
-    0x7e, 0x20, 0x00, 0x13, 0x50, 0x21, 0x09, 0xa0, 0x00, 0x04, 0x4e, 0xa0, 0x05, 0x19, 0xa0, 0x00, 
-    0x04, 0x0a, 0x32, 0x09, 0x53, 0x6a, 0x93, 0x5e, 0x51, 0x27, 0x68, 0x0b, 0x09, 0xa0, 0x00, 0x10, 
-    0x4e, 0xa0, 0x01, 0x19, 0xa0, 0x00, 0x10, 0x2e, 0x04, 0x01, 0x00, 0xa5, 0x0a, 0xbe, 0x21, 0x2e, 
-    0x78, 0xd1, 0x75, 0x22, 0x00, 0xd2, 0xaf, 0x22, 0xc2, 0xaf, 0xe5, 0x26, 0x60, 0x36, 0x7e, 0x20, 
-    0x00, 0x7e, 0x30, 0x01, 0xe5, 0x26, 0xa5, 0x5b, 0x68, 0x21, 0x7c, 0xb2, 0x23, 0x0a, 0x2b, 0x49, 
-    0x32, 0x01, 0x79, 0xbe, 0x34, 0x00, 0x00, 0x68, 0x12, 0x7e, 0xb1, 0x21, 0xa5, 0x4b, 0x7a, 0xb1, 
-    0x21, 0xca, 0x19, 0x49, 0x22, 0x45, 0x17, 0x99, 0x24, 0xda, 0x19, 0x3e, 0x30, 0xa5, 0x0a, 0xbe, 
-    0x21, 0x2e, 0x78, 0xd0, 0xd2, 0xaf, 0x22, 0x4a, 0x98, 0x4d, 0xcd, 0x51, 0x02, 0x54, 0x37, 0x57, 
-    0x6c, 0x5a, 0xa1, 0x5d, 0xd6, 0x61, 0x0b, 0xc2, 0xaf, 0xe5, 0x24, 0x60, 0x14, 0x7e, 0x20, 0x00, 
-    0x13, 0x50, 0x07, 0xca, 0xb8, 0x12, 0x45, 0x44, 0xda, 0xb8, 0xa5, 0x0a, 0xbe, 0x21, 0x2e, 0x78, 
-    0xef, 0xd2, 0xaf, 0x22, 0xca, 0x28, 0x12, 0x6a, 0xac, 0xda, 0x28, 0x40, 0x09, 0x0a, 0x22, 0x09, 
-    0xb2, 0x6a, 0x93, 0xf4, 0x52, 0x24, 0x22, 0xc2, 0xaf, 0xe5, 0x23, 0x60, 0x14, 0x7e, 0x20, 0x00, 
-    0x13, 0x50, 0x07, 0xca, 0xb8, 0x12, 0x45, 0x74, 0xda, 0xb8, 0xa5, 0x0a, 0xbe, 0x21, 0x2e, 0x78, 
-    0xef, 0xd2, 0xaf, 0x22, 0x7c, 0xb2, 0x23, 0x0a, 0x2b, 0x49, 0x22, 0x45, 0x7f, 0x89, 0x24, 0x45, 
-    0x8f, 0x45, 0xff, 0x46, 0x6f, 0x46, 0xdf, 0x47, 0x4f, 0x47, 0xbf, 0x48, 0x2f, 0x48, 0x9f, 0x7e, 
-    0x27, 0x01, 0x79, 0xbe, 0x24, 0x00, 0x00, 0x78, 0x24, 0x7e, 0x24, 0x80, 0x00, 0x09, 0xb2, 0x00, 
-    0x14, 0xca, 0xb8, 0x5e, 0xb0, 0x1e, 0xda, 0xb8, 0x68, 0x0b, 0xca, 0x19, 0x7d, 0x12, 0x12, 0x4d, 
-    0x96, 0x7d, 0x21, 0xda, 0x19, 0x30, 0xe6, 0x18, 0x7e, 0x60, 0x00, 0x80, 0x1e, 0xbe, 0x27, 0x01, 
-    0x89, 0x68, 0x0d, 0x7a, 0x27, 0x01, 0x89, 0x7e, 0x60, 0x9c, 0x7a, 0x63, 0x01, 0xb9, 0x80, 0x2e, 
-    0x7e, 0x63, 0x01, 0xb9, 0xa5, 0xbe, 0x00, 0x26, 0x7e, 0x60, 0x01, 0x7e, 0xb0, 0x00, 0x7e, 0xa0, 
-    0xc8, 0x12, 0x65, 0xbf, 0x40, 0x18, 0x75, 0x2f, 0xb3, 0x12, 0x7e, 0x30, 0xc2, 0x18, 0x6c, 0x00, 
-    0x7a, 0x03, 0x01, 0xb9, 0xc0, 0xf1, 0x75, 0xf1, 0x01, 0x12, 0x71, 0xe9, 0xd0, 0xf1, 0x22, 0x7e, 
-    0x27, 0x01, 0x7b, 0xbe, 0x24, 0x00, 0x00, 0x78, 0x24, 0x7e, 0x24, 0x81, 0x00, 0x09, 0xb2, 0x00, 
-    0x14, 0xca, 0xb8, 0x5e, 0xb0, 0x1e, 0xda, 0xb8, 0x68, 0x0b, 0xca, 0x19, 0x7d, 0x12, 0x12, 0x50, 
-    0xcb, 0x7d, 0x21, 0xda, 0x19, 0x30, 0xe6, 0x18, 0x7e, 0x60, 0x00, 0x80, 0x1e, 0xbe, 0x27, 0x01, 
-    0x8b, 0x68, 0x0d, 0x7a, 0x27, 0x01, 0x8b, 0x7e, 0x60, 0x9c, 0x7a, 0x63, 0x01, 0xba, 0x80, 0x2e, 
-    0x7e, 0x63, 0x01, 0xba, 0xa5, 0xbe, 0x00, 0x26, 0x7e, 0x60, 0x01, 0x7e, 0xb0, 0x00, 0x7e, 0xa0, 
-    0xc8, 0x12, 0x65, 0xbf, 0x40, 0x18, 0x75, 0x2f, 0xb3, 0x12, 0x7e, 0x30, 0xc2, 0x19, 0x6c, 0x00, 
-    0x7a, 0x03, 0x01, 0xba, 0xc0, 0xf1, 0x75, 0xf1, 0x01, 0x12, 0x71, 0xe9, 0xd0, 0xf1, 0x22, 0x7e, 
-    0x27, 0x01, 0x7d, 0xbe, 0x24, 0x00, 0x00, 0x78, 0x24, 0x7e, 0x24, 0x82, 0x00, 0x09, 0xb2, 0x00, 
-    0x14, 0xca, 0xb8, 0x5e, 0xb0, 0x1e, 0xda, 0xb8, 0x68, 0x0b, 0xca, 0x19, 0x7d, 0x12, 0x12, 0x54, 
-    0x00, 0x7d, 0x21, 0xda, 0x19, 0x30, 0xe6, 0x18, 0x7e, 0x60, 0x00, 0x80, 0x1e, 0xbe, 0x27, 0x01, 
-    0x8d, 0x68, 0x0d, 0x7a, 0x27, 0x01, 0x8d, 0x7e, 0x60, 0x9c, 0x7a, 0x63, 0x01, 0xbb, 0x80, 0x2e, 
-    0x7e, 0x63, 0x01, 0xbb, 0xa5, 0xbe, 0x00, 0x26, 0x7e, 0x60, 0x01, 0x7e, 0xb0, 0x00, 0x7e, 0xa0, 
-    0xc8, 0x12, 0x65, 0xbf, 0x40, 0x18, 0x75, 0x2f, 0xb3, 0x12, 0x7e, 0x30, 0xc2, 0x1a, 0x6c, 0x00, 
-    0x7a, 0x03, 0x01, 0xbb, 0xc0, 0xf1, 0x75, 0xf1, 0x01, 0x12, 0x71, 0xe9, 0xd0, 0xf1, 0x22, 0x7e, 
-    0x27, 0x01, 0x7f, 0xbe, 0x24, 0x00, 0x00, 0x78, 0x24, 0x7e, 0x24, 0x83, 0x00, 0x09, 0xb2, 0x00, 
-    0x14, 0xca, 0xb8, 0x5e, 0xb0, 0x1e, 0xda, 0xb8, 0x68, 0x0b, 0xca, 0x19, 0x7d, 0x12, 0x12, 0x57, 
-    0x35, 0x7d, 0x21, 0xda, 0x19, 0x30, 0xe6, 0x18, 0x7e, 0x60, 0x00, 0x80, 0x1e, 0xbe, 0x27, 0x01, 
-    0x8f, 0x68, 0x0d, 0x7a, 0x27, 0x01, 0x8f, 0x7e, 0x60, 0x9c, 0x7a, 0x63, 0x01, 0xbc, 0x80, 0x2e, 
-    0x7e, 0x63, 0x01, 0xbc, 0xa5, 0xbe, 0x00, 0x26, 0x7e, 0x60, 0x01, 0x7e, 0xb0, 0x00, 0x7e, 0xa0, 
-    0xc8, 0x12, 0x65, 0xbf, 0x40, 0x18, 0x75, 0x2f, 0xb3, 0x12, 0x7e, 0x30, 0xc2, 0x1b, 0x6c, 0x00, 
-    0x7a, 0x03, 0x01, 0xbc, 0xc0, 0xf1, 0x75, 0xf1, 0x01, 0x12, 0x71, 0xe9, 0xd0, 0xf1, 0x22, 0x7e, 
-    0x27, 0x01, 0x81, 0xbe, 0x24, 0x00, 0x00, 0x78, 0x24, 0x7e, 0x24, 0x84, 0x00, 0x09, 0xb2, 0x00, 
-    0x14, 0xca, 0xb8, 0x5e, 0xb0, 0x1e, 0xda, 0xb8, 0x68, 0x0b, 0xca, 0x19, 0x7d, 0x12, 0x12, 0x5a, 
-    0x6a, 0x7d, 0x21, 0xda, 0x19, 0x30, 0xe6, 0x18, 0x7e, 0x60, 0x00, 0x80, 0x1e, 0xbe, 0x27, 0x01, 
-    0x91, 0x68, 0x0d, 0x7a, 0x27, 0x01, 0x91, 0x7e, 0x60, 0x9c, 0x7a, 0x63, 0x01, 0xbd, 0x80, 0x2e, 
-    0x7e, 0x63, 0x01, 0xbd, 0xa5, 0xbe, 0x00, 0x26, 0x7e, 0x60, 0x01, 0x7e, 0xb0, 0x00, 0x7e, 0xa0, 
-    0xc8, 0x12, 0x65, 0xbf, 0x40, 0x18, 0x75, 0x2f, 0xb3, 0x12, 0x7e, 0x30, 0xc2, 0x1c, 0x6c, 0x00, 
-    0x7a, 0x03, 0x01, 0xbd, 0xc0, 0xf1, 0x75, 0xf1, 0x01, 0x12, 0x71, 0xe9, 0xd0, 0xf1, 0x22, 0x7e, 
-    0x27, 0x01, 0x83, 0xbe, 0x24, 0x00, 0x00, 0x78, 0x24, 0x7e, 0x24, 0x85, 0x00, 0x09, 0xb2, 0x00, 
-    0x14, 0xca, 0xb8, 0x5e, 0xb0, 0x1e, 0xda, 0xb8, 0x68, 0x0b, 0xca, 0x19, 0x7d, 0x12, 0x12, 0x5d, 
-    0x9f, 0x7d, 0x21, 0xda, 0x19, 0x30, 0xe6, 0x18, 0x7e, 0x60, 0x00, 0x80, 0x1e, 0xbe, 0x27, 0x01, 
-    0x93, 0x68, 0x0d, 0x7a, 0x27, 0x01, 0x93, 0x7e, 0x60, 0x9c, 0x7a, 0x63, 0x01, 0xbe, 0x80, 0x2e, 
-    0x7e, 0x63, 0x01, 0xbe, 0xa5, 0xbe, 0x00, 0x26, 0x7e, 0x60, 0x01, 0x7e, 0xb0, 0x00, 0x7e, 0xa0, 
-    0xc8, 0x12, 0x65, 0xbf, 0x40, 0x18, 0x75, 0x2f, 0xb3, 0x12, 0x7e, 0x30, 0xc2, 0x1d, 0x6c, 0x00, 
-    0x7a, 0x03, 0x01, 0xbe, 0xc0, 0xf1, 0x75, 0xf1, 0x01, 0x12, 0x71, 0xe9, 0xd0, 0xf1, 0x22, 0x7e, 
-    0x27, 0x01, 0x85, 0xbe, 0x24, 0x00, 0x00, 0x78, 0x24, 0x7e, 0x24, 0x86, 0x00, 0x09, 0xb2, 0x00, 
-    0x14, 0xca, 0xb8, 0x5e, 0xb0, 0x1e, 0xda, 0xb8, 0x68, 0x0b, 0xca, 0x19, 0x7d, 0x12, 0x12, 0x60, 
-    0xd4, 0x7d, 0x21, 0xda, 0x19, 0x30, 0xe6, 0x18, 0x7e, 0x60, 0x00, 0x80, 0x1e, 0xbe, 0x27, 0x01, 
-    0x95, 0x68, 0x0d, 0x7a, 0x27, 0x01, 0x95, 0x7e, 0x60, 0x9c, 0x7a, 0x63, 0x01, 0xbf, 0x80, 0x2e, 
-    0x7e, 0x63, 0x01, 0xbf, 0xa5, 0xbe, 0x00, 0x26, 0x7e, 0x60, 0x01, 0x7e, 0xb0, 0x00, 0x7e, 0xa0, 
-    0xc8, 0x12, 0x65, 0xbf, 0x40, 0x18, 0x75, 0x2f, 0xb3, 0x12, 0x7e, 0x30, 0xc2, 0x1e, 0x6c, 0x00, 
-    0x7a, 0x03, 0x01, 0xbf, 0xc0, 0xf1, 0x75, 0xf1, 0x01, 0x12, 0x71, 0xe9, 0xd0, 0xf1, 0x22, 0x7e, 
-    0x27, 0x01, 0x87, 0xbe, 0x24, 0x00, 0x00, 0x78, 0x24, 0x7e, 0x24, 0x87, 0x00, 0x09, 0xb2, 0x00, 
-    0x14, 0xca, 0xb8, 0x5e, 0xb0, 0x1e, 0xda, 0xb8, 0x68, 0x0b, 0xca, 0x19, 0x7d, 0x12, 0x12, 0x64, 
-    0x09, 0x7d, 0x21, 0xda, 0x19, 0x30, 0xe6, 0x18, 0x7e, 0x60, 0x00, 0x80, 0x1e, 0xbe, 0x27, 0x01, 
-    0x97, 0x68, 0x0d, 0x7a, 0x27, 0x01, 0x97, 0x7e, 0x60, 0x9c, 0x7a, 0x63, 0x01, 0xc0, 0x80, 0x2e, 
-    0x7e, 0x63, 0x01, 0xc0, 0xa5, 0xbe, 0x00, 0x26, 0x7e, 0x60, 0x01, 0x7e, 0xb0, 0x00, 0x7e, 0xa0, 
-    0xc8, 0x12, 0x65, 0xbf, 0x40, 0x18, 0x75, 0x2f, 0xb3, 0x12, 0x7e, 0x30, 0xc2, 0x1f, 0x6c, 0x00, 
-    0x7a, 0x03, 0x01, 0xc0, 0xc0, 0xf1, 0x75, 0xf1, 0x01, 0x12, 0x71, 0xe9, 0xd0, 0xf1, 0x22, 0xc2, 
-    0xaf, 0xc0, 0xf1, 0x75, 0xf1, 0x01, 0xa9, 0x32, 0xf2, 0x1a, 0x7e, 0x07, 0x01, 0xcb, 0xbe, 0x04, 
-    0x00, 0x00, 0x78, 0x10, 0xe5, 0xf5, 0x33, 0x82, 0xe7, 0x40, 0x09, 0x85, 0x31, 0x2f, 0x12, 0x7e, 
-    0x30, 0x75, 0xf6, 0x00, 0xd0, 0xf1, 0xd2, 0xaf, 0x22, 0xc0, 0xd0, 0xc0, 0xd1, 0xc0, 0xe0, 0xc0, 
-    0xf0, 0xca, 0x0b, 0xca, 0x1b, 0xca, 0x2b, 0xd2, 0x01, 0x75, 0x2f, 0x89, 0x12, 0x7e, 0x30, 0x7e, 
-    0x14, 0x80, 0x00, 0x09, 0xb1, 0x00, 0x08, 0x20, 0xe0, 0x03, 0x02, 0x49, 0xd8, 0x20, 0x70, 0x5a, 
-    0xa5, 0x0a, 0x09, 0xb1, 0x00, 0x08, 0x20, 0xe0, 0x03, 0x02, 0x49, 0xf0, 0x20, 0x71, 0x4b, 0xa5, 
-    0x0a, 0x09, 0xb1, 0x00, 0x08, 0x20, 0xe0, 0x03, 0x02, 0x4a, 0x08, 0xa5, 0x0a, 0x09, 0xb1, 0x00, 
-    0x08, 0x20, 0xe0, 0x03, 0x02, 0x4a, 0x20, 0x20, 0x72, 0x30, 0xa5, 0x0a, 0x09, 0xb1, 0x00, 0x08, 
-    0x20, 0xe0, 0x03, 0x02, 0x4a, 0x38, 0xa5, 0x0a, 0x09, 0xb1, 0x00, 0x08, 0x20, 0xe0, 0x03, 0x02, 
-    0x4a, 0x50, 0xa5, 0x0a, 0x09, 0xb1, 0x00, 0x08, 0x20, 0xe0, 0x03, 0x02, 0x4a, 0x68, 0xa5, 0x0a, 
-    0x09, 0xb1, 0x00, 0x08, 0x20, 0xe0, 0x03, 0x02, 0x4a, 0x80, 0x30, 0x04, 0x0c, 0xc2, 0x04, 0xc0, 
-    0xf1, 0x75, 0xf1, 0x01, 0x12, 0x71, 0xe9, 0xd0, 0xf1, 0xda, 0x2b, 0xda, 0x1b, 0xda, 0x0b, 0xd0, 
-    0xf0, 0xd0, 0xe0, 0xd0, 0xd1, 0xd0, 0xd0, 0x32, 0x75, 0x2f, 0x80, 0x12, 0x7e, 0x30, 0x54, 0x3e, 
-    0x0a, 0x5b, 0x7e, 0x44, 0x00, 0xff, 0x69, 0x52, 0x66, 0x34, 0xca, 0x06, 0x4f, 0x49, 0x89, 0x54, 
-    0x75, 0x2f, 0x81, 0x12, 0x7e, 0x30, 0x54, 0x3e, 0x0a, 0x5b, 0x7e, 0x44, 0x00, 0xff, 0x69, 0x52, 
-    0x66, 0x74, 0xca, 0x06, 0x4f, 0x49, 0x89, 0x54, 0x75, 0x2f, 0x82, 0x12, 0x7e, 0x30, 0x54, 0x3e, 
-    0x0a, 0x5b, 0x7e, 0x44, 0x00, 0xff, 0x69, 0x52, 0x66, 0xb4, 0xca, 0x06, 0x4f, 0x49, 0x89, 0x54, 
-    0x75, 0x2f, 0x83, 0x12, 0x7e, 0x30, 0x54, 0x3e, 0x0a, 0x5b, 0x7e, 0x44, 0x00, 0xff, 0x69, 0x52, 
-    0x66, 0xf4, 0xca, 0x06, 0x4f, 0x49, 0x89, 0x54, 0x75, 0x2f, 0x84, 0x12, 0x7e, 0x30, 0x54, 0x3e, 
-    0x0a, 0x5b, 0x7e, 0x44, 0x00, 0xff, 0x69, 0x52, 0x67, 0x34, 0xca, 0x06, 0x4f, 0x49, 0x89, 0x54, 
-    0x75, 0x2f, 0x85, 0x12, 0x7e, 0x30, 0x54, 0x3e, 0x0a, 0x5b, 0x7e, 0x44, 0x00, 0xff, 0x69, 0x52, 
-    0x67, 0x74, 0xca, 0x06, 0x4f, 0x49, 0x89, 0x54, 0x75, 0x2f, 0x86, 0x12, 0x7e, 0x30, 0x54, 0x3e, 
-    0x0a, 0x5b, 0x7e, 0x44, 0x00, 0xff, 0x69, 0x52, 0x67, 0xb4, 0xca, 0x06, 0x4f, 0x49, 0x89, 0x54, 
-    0x75, 0x2f, 0x87, 0x12, 0x7e, 0x30, 0x54, 0x3e, 0x0a, 0x5b, 0x7e, 0x44, 0x00, 0xff, 0x69, 0x52, 
-    0x67, 0xf4, 0xca, 0x06, 0x4f, 0x49, 0x89, 0x54, 0x10, 0x08, 0x01, 0x22, 0x20, 0x28, 0x03, 0xd2, 
-    0x08, 0x22, 0x75, 0x2f, 0xa0, 0x12, 0x7e, 0x30, 0x7e, 0x14, 0x80, 0x00, 0x80, 0x06, 0x20, 0x28, 
-    0x03, 0xd2, 0x08, 0x22, 0x09, 0xb1, 0x00, 0x14, 0xca, 0xb8, 0x5e, 0xb0, 0x1e, 0xda, 0xb8, 0x68, 
-    0x03, 0x12, 0x4d, 0x96, 0x30, 0x30, 0x06, 0x20, 0xe6, 0x4f, 0xd2, 0x08, 0x22, 0x30, 0xe6, 0x02, 
-    0xd2, 0x60, 0x7e, 0x37, 0x01, 0x79, 0x7e, 0x27, 0x01, 0x99, 0x9d, 0x32, 0x40, 0x31, 0x7d, 0x02, 
-    0x2e, 0x05, 0x32, 0x7a, 0x05, 0x32, 0x7a, 0x37, 0x01, 0x79, 0x7e, 0x37, 0x01, 0x59, 0x7d, 0x43, 
-    0x2d, 0x42, 0xbe, 0x44, 0x0d, 0xcc, 0x38, 0x68, 0x7a, 0x47, 0x01, 0x59, 0x75, 0x2f, 0x94, 0x12, 
-    0x7e, 0x30, 0x7a, 0x51, 0x2f, 0x12, 0x7e, 0x30, 0x12, 0x68, 0x34, 0x10, 0x60, 0xc4, 0x22, 0xc2, 
-    0x60, 0x2d, 0x23, 0x68, 0x78, 0x6d, 0x33, 0x80, 0x1a, 0x7e, 0x27, 0x01, 0x79, 0xbe, 0x24, 0x00, 
-    0x00, 0x68, 0x6a, 0xbe, 0x27, 0x01, 0x99, 0x28, 0x04, 0x7e, 0x27, 0x01, 0x99, 0x7e, 0x37, 0x01, 
-    0x79, 0x9d, 0x32, 0x7d, 0x02, 0x2e, 0x05, 0x32, 0x7a, 0x05, 0x32, 0x7a, 0x37, 0x01, 0x79, 0x7e, 
-    0x37, 0x01, 0x59, 0x7d, 0x43, 0x2d, 0x42, 0xbe, 0x44, 0x0d, 0xcc, 0x38, 0x13, 0x7a, 0x47, 0x01, 
-    0x59, 0x75, 0x2f, 0x94, 0x12, 0x7e, 0x30, 0x7a, 0x51, 0x2f, 0x12, 0x7e, 0x30, 0x02, 0x68, 0x34, 
-    0x75, 0x2f, 0x94, 0x12, 0x7e, 0x30, 0x7a, 0x51, 0x2f, 0x12, 0x7e, 0x30, 0x9e, 0x44, 0x0d, 0xcd, 
-    0x9d, 0x24, 0x12, 0x68, 0x34, 0x7e, 0x34, 0x09, 0xcd, 0x7d, 0x24, 0x2d, 0x43, 0x7a, 0x47, 0x01, 
-    0x59, 0x12, 0x68, 0x34, 0xbe, 0x25, 0x20, 0x78, 0x03, 0x02, 0x4b, 0x0b, 0x22, 0xd2, 0x08, 0x7e, 
-    0x04, 0x09, 0xcd, 0x7a, 0x07, 0x01, 0x59, 0x7a, 0x07, 0x01, 0x69, 0x75, 0x2f, 0x94, 0x12, 0x7e, 
-    0x30, 0x75, 0x2f, 0x00, 0x12, 0x7e, 0x30, 0x22, 0x75, 0x2f, 0x92, 0x12, 0x7e, 0x30, 0xd2, 0x04, 
-    0x09, 0xb1, 0x00, 0x14, 0xca, 0xb8, 0x54, 0x82, 0xda, 0xb8, 0x78, 0x70, 0x7e, 0x37, 0x01, 0xcb, 
-    0x7e, 0x27, 0x01, 0xa9, 0x2e, 0x24, 0x00, 0x02, 0x2d, 0x32, 0xbe, 0x34, 0x04, 0x00, 0x38, 0x3c, 
-    0x7d, 0x02, 0x2e, 0x05, 0x30, 0x7a, 0x05, 0x30, 0x7a, 0x37, 0x01, 0xcb, 0x7e, 0x37, 0x01, 0xc9, 
-    0x7d, 0x43, 0x2d, 0x42, 0xbe, 0x44, 0x05, 0xcc, 0x38, 0x44, 0x7a, 0x47, 0x01, 0xc9, 0x7e, 0x24, 
-    0x00, 0x00, 0x2e, 0x27, 0x01, 0xa9, 0x1b, 0x38, 0x20, 0x0b, 0x35, 0x7a, 0x51, 0x2f, 0x12, 0x7e, 
-    0x30, 0xbe, 0x50, 0x38, 0x78, 0x03, 0x02, 0x69, 0x1f, 0x02, 0x69, 0x04, 0x75, 0x2f, 0x99, 0x12, 
-    0x7e, 0x30, 0x09, 0xb1, 0x00, 0x04, 0x54, 0xfa, 0x19, 0xb1, 0x00, 0x04, 0x30, 0x38, 0x0a, 0x09, 
-    0xb1, 0x00, 0x10, 0x54, 0xfe, 0x19, 0xb1, 0x00, 0x10, 0xd2, 0x10, 0x22, 0x80, 0x7f, 0x7a, 0x51, 
-    0x2f, 0x12, 0x7e, 0x30, 0x9e, 0x44, 0x05, 0xcd, 0x9d, 0x24, 0x7e, 0x64, 0x00, 0x00, 0x2e, 0x67, 
-    0x01, 0xa9, 0x9e, 0x24, 0x00, 0x02, 0x40, 0x17, 0x1b, 0x38, 0x60, 0x0b, 0x35, 0x12, 0x69, 0x04, 
-    0x7e, 0x34, 0x01, 0xcd, 0x7d, 0x24, 0x2d, 0x43, 0x7a, 0x47, 0x01, 0xc9, 0x02, 0x69, 0x04, 0x7a, 
-    0x39, 0xc0, 0x7e, 0x34, 0x01, 0xcd, 0x7a, 0x39, 0xd0, 0x0b, 0x34, 0x1b, 0x44, 0x80, 0xe5, 0x9d, 
-    0x32, 0x7c, 0xb6, 0x54, 0x0f, 0x23, 0x23, 0x23, 0x44, 0x00, 0x7a, 0x69, 0xb0, 0x7a, 0x79, 0x70, 
-    0x0b, 0x35, 0x75, 0x2f, 0x93, 0x12, 0x7e, 0x30, 0x7a, 0x71, 0x2f, 0x12, 0x7e, 0x30, 0xbd, 0x04, 
-    0x68, 0x2b, 0x7a, 0x07, 0x01, 0xc9, 0x7e, 0x47, 0x01, 0xcb, 0x2d, 0x43, 0x7a, 0x47, 0x01, 0xcb, 
-    0x2e, 0x35, 0x30, 0x7a, 0x35, 0x30, 0x22, 0xd2, 0x04, 0x09, 0xb1, 0x00, 0x14, 0x20, 0xe0, 0x13, 
-    0x22, 0x7e, 0x04, 0x01, 0xcd, 0x80, 0x28, 0x7e, 0x04, 0x01, 0xcd, 0x80, 0x2a, 0x7e, 0x04, 0x01, 
-    0xcd, 0x80, 0xcf, 0x7e, 0x07, 0x01, 0xcb, 0x7e, 0x24, 0x03, 0xfe, 0x9d, 0x20, 0x28, 0x40, 0x7e, 
-    0x07, 0x01, 0xc9, 0x7e, 0x44, 0x05, 0xcd, 0x7d, 0x60, 0x0b, 0x04, 0xbd, 0x04, 0x68, 0xd2, 0x7d, 
-    0x70, 0x0b, 0x04, 0xbd, 0x04, 0x68, 0xd0, 0x7d, 0x54, 0x9d, 0x50, 0xbd, 0x25, 0x40, 0x02, 0x7d, 
-    0x25, 0x7d, 0x32, 0x09, 0xb1, 0x00, 0x14, 0xca, 0xb8, 0x54, 0x1f, 0xb4, 0x01, 0x31, 0xda, 0xb8, 
-    0x7e, 0x19, 0xb0, 0x7a, 0x09, 0xb0, 0x0b, 0x04, 0x1b, 0x24, 0x78, 0xe7, 0x02, 0x4c, 0x6f, 0x75, 
-    0x2f, 0x99, 0x12, 0x7e, 0x30, 0x09, 0xb1, 0x00, 0x04, 0x54, 0xfa, 0x19, 0xb1, 0x00, 0x04, 0x30, 
-    0x38, 0x0a, 0x09, 0xb1, 0x00, 0x10, 0x54, 0xfe, 0x19, 0xb1, 0x00, 0x10, 0xd2, 0x10, 0x22, 0xda, 
-    0xb8, 0x30, 0xe0, 0xd8, 0xbd, 0x32, 0x68, 0x07, 0xca, 0xb8, 0x12, 0x4c, 0x6f, 0xda, 0xb8, 0x02, 
-    0x4d, 0x96, 0x09, 0xb1, 0x00, 0x18, 0x7e, 0xa0, 0x88, 0x75, 0x2f, 0x90, 0x12, 0x7e, 0x30, 0xf5, 
-    0x2f, 0x12, 0x7e, 0x30, 0xa5, 0xfd, 0x5e, 0x50, 0x0a, 0x68, 0x1d, 0xa5, 0xfd, 0x5e, 0x50, 0x20, 
-    0x68, 0x04, 0xd2, 0x58, 0x80, 0x02, 0xc2, 0x58, 0xa5, 0xfd, 0x5e, 0x50, 0x80, 0x68, 0x04, 0xd2, 
-    0x50, 0x80, 0x02, 0xc2, 0x50, 0x12, 0x42, 0xac, 0x02, 0x65, 0x9c, 0x75, 0x2f, 0x91, 0x12, 0x7e, 
-    0x30, 0x09, 0xb1, 0x00, 0x14, 0x7a, 0xb1, 0x2f, 0x12, 0x7e, 0x30, 0x20, 0xe0, 0x08, 0xd2, 0x04, 
-    0x7e, 0xa0, 0x80, 0x02, 0x65, 0x9c, 0xd2, 0x04, 0x30, 0xe1, 0x06, 0x7e, 0xa0, 0x80, 0x12, 0x65, 
-    0x9c, 0xca, 0xb8, 0x5e, 0xb0, 0x1c, 0xda, 0xb8, 0x68, 0x12, 0x7e, 0xa0, 0xc0, 0x09, 0x61, 0x00, 
-    0x00, 0x12, 0x65, 0xbf, 0x09, 0xb1, 0x00, 0x14, 0x20, 0xe0, 0xdb, 0x22, 0x02, 0x4c, 0xc3, 0x75, 
-    0x2f, 0x95, 0x12, 0x7e, 0x30, 0x22, 0x75, 0x2f, 0x96, 0x12, 0x7e, 0x30, 0x22, 0x10, 0x09, 0x01, 
-    0x22, 0x20, 0x29, 0x03, 0xd2, 0x09, 0x22, 0x75, 0x2f, 0xa1, 0x12, 0x7e, 0x30, 0x7e, 0x14, 0x81, 
-    0x00, 0x80, 0x06, 0x20, 0x29, 0x03, 0xd2, 0x09, 0x22, 0x09, 0xb1, 0x00, 0x14, 0xca, 0xb8, 0x5e, 
-    0xb0, 0x1e, 0xda, 0xb8, 0x68, 0x03, 0x12, 0x50, 0xcb, 0x30, 0x31, 0x06, 0x20, 0xe6, 0x4f, 0xd2, 
-    0x09, 0x22, 0x30, 0xe6, 0x02, 0xd2, 0x61, 0x7e, 0x37, 0x01, 0x7b, 0x7e, 0x27, 0x01, 0x9b, 0x9d, 
-    0x32, 0x40, 0x31, 0x7d, 0x02, 0x2e, 0x05, 0x34, 0x7a, 0x05, 0x34, 0x7a, 0x37, 0x01, 0x7b, 0x7e, 
-    0x37, 0x01, 0x5b, 0x7d, 0x43, 0x2d, 0x42, 0xbe, 0x44, 0x11, 0xcc, 0x38, 0x68, 0x7a, 0x47, 0x01, 
-    0x5b, 0x75, 0x2f, 0x94, 0x12, 0x7e, 0x30, 0x7a, 0x51, 0x2f, 0x12, 0x7e, 0x30, 0x12, 0x68, 0x34, 
-    0x10, 0x61, 0xc4, 0x22, 0xc2, 0x61, 0x2d, 0x23, 0x68, 0x78, 0x6d, 0x33, 0x80, 0x1a, 0x7e, 0x27, 
-    0x01, 0x7b, 0xbe, 0x24, 0x00, 0x00, 0x68, 0x6a, 0xbe, 0x27, 0x01, 0x9b, 0x28, 0x04, 0x7e, 0x27, 
-    0x01, 0x9b, 0x7e, 0x37, 0x01, 0x7b, 0x9d, 0x32, 0x7d, 0x02, 0x2e, 0x05, 0x34, 0x7a, 0x05, 0x34, 
-    0x7a, 0x37, 0x01, 0x7b, 0x7e, 0x37, 0x01, 0x5b, 0x7d, 0x43, 0x2d, 0x42, 0xbe, 0x44, 0x11, 0xcc, 
-    0x38, 0x13, 0x7a, 0x47, 0x01, 0x5b, 0x75, 0x2f, 0x94, 0x12, 0x7e, 0x30, 0x7a, 0x51, 0x2f, 0x12, 
-    0x7e, 0x30, 0x02, 0x68, 0x34, 0x75, 0x2f, 0x94, 0x12, 0x7e, 0x30, 0x7a, 0x51, 0x2f, 0x12, 0x7e, 
-    0x30, 0x9e, 0x44, 0x11, 0xcd, 0x9d, 0x24, 0x12, 0x68, 0x34, 0x7e, 0x34, 0x0d, 0xcd, 0x7d, 0x24, 
-    0x2d, 0x43, 0x7a, 0x47, 0x01, 0x5b, 0x12, 0x68, 0x34, 0xbe, 0x25, 0x20, 0x78, 0x03, 0x02, 0x4e, 
-    0x40, 0x22, 0xd2, 0x09, 0x7e, 0x04, 0x0d, 0xcd, 0x7a, 0x07, 0x01, 0x5b, 0x7a, 0x07, 0x01, 0x6b, 
-    0x75, 0x2f, 0x94, 0x12, 0x7e, 0x30, 0x75, 0x2f, 0x00, 0x12, 0x7e, 0x30, 0x22, 0x75, 0x2f, 0x92, 
-    0x12, 0x7e, 0x30, 0xd2, 0x04, 0x09, 0xb1, 0x00, 0x14, 0xca, 0xb8, 0x54, 0x82, 0xda, 0xb8, 0x78, 
-    0x70, 0x7e, 0x37, 0x01, 0xcb, 0x7e, 0x27, 0x01, 0xab, 0x2e, 0x24, 0x00, 0x02, 0x2d, 0x32, 0xbe, 
-    0x34, 0x04, 0x00, 0x38, 0x3c, 0x7d, 0x02, 0x2e, 0x05, 0x30, 0x7a, 0x05, 0x30, 0x7a, 0x37, 0x01, 
-    0xcb, 0x7e, 0x37, 0x01, 0xc9, 0x7d, 0x43, 0x2d, 0x42, 0xbe, 0x44, 0x05, 0xcc, 0x38, 0x44, 0x7a, 
-    0x47, 0x01, 0xc9, 0x7e, 0x24, 0x01, 0x00, 0x2e, 0x27, 0x01, 0xab, 0x1b, 0x38, 0x20, 0x0b, 0x35, 
-    0x7a, 0x51, 0x2f, 0x12, 0x7e, 0x30, 0xbe, 0x50, 0x38, 0x78, 0x03, 0x02, 0x69, 0x1f, 0x02, 0x69, 
-    0x04, 0x75, 0x2f, 0x99, 0x12, 0x7e, 0x30, 0x09, 0xb1, 0x00, 0x04, 0x54, 0xfa, 0x19, 0xb1, 0x00, 
-    0x04, 0x30, 0x39, 0x0a, 0x09, 0xb1, 0x00, 0x10, 0x54, 0xfe, 0x19, 0xb1, 0x00, 0x10, 0xd2, 0x11, 
-    0x22, 0x80, 0x7f, 0x7a, 0x51, 0x2f, 0x12, 0x7e, 0x30, 0x9e, 0x44, 0x05, 0xcd, 0x9d, 0x24, 0x7e, 
-    0x64, 0x01, 0x00, 0x2e, 0x67, 0x01, 0xab, 0x9e, 0x24, 0x00, 0x02, 0x40, 0x17, 0x1b, 0x38, 0x60, 
-    0x0b, 0x35, 0x12, 0x69, 0x04, 0x7e, 0x34, 0x01, 0xcd, 0x7d, 0x24, 0x2d, 0x43, 0x7a, 0x47, 0x01, 
-    0xc9, 0x02, 0x69, 0x04, 0x7a, 0x39, 0xc0, 0x7e, 0x34, 0x01, 0xcd, 0x7a, 0x39, 0xd0, 0x0b, 0x34, 
-    0x1b, 0x44, 0x80, 0xe5, 0x9d, 0x32, 0x7c, 0xb6, 0x54, 0x0f, 0x23, 0x23, 0x23, 0x44, 0x01, 0x7a, 
-    0x69, 0xb0, 0x7a, 0x79, 0x70, 0x0b, 0x35, 0x75, 0x2f, 0x93, 0x12, 0x7e, 0x30, 0x7a, 0x71, 0x2f, 
-    0x12, 0x7e, 0x30, 0xbd, 0x04, 0x68, 0x2b, 0x7a, 0x07, 0x01, 0xc9, 0x7e, 0x47, 0x01, 0xcb, 0x2d, 
-    0x43, 0x7a, 0x47, 0x01, 0xcb, 0x2e, 0x35, 0x30, 0x7a, 0x35, 0x30, 0x22, 0xd2, 0x04, 0x09, 0xb1, 
-    0x00, 0x14, 0x20, 0xe0, 0x13, 0x22, 0x7e, 0x04, 0x01, 0xcd, 0x80, 0x28, 0x7e, 0x04, 0x01, 0xcd, 
-    0x80, 0x2a, 0x7e, 0x04, 0x01, 0xcd, 0x80, 0xcf, 0x7e, 0x07, 0x01, 0xcb, 0x7e, 0x24, 0x03, 0xfe, 
-    0x9d, 0x20, 0x28, 0x40, 0x7e, 0x07, 0x01, 0xc9, 0x7e, 0x44, 0x05, 0xcd, 0x7d, 0x60, 0x0b, 0x04, 
-    0xbd, 0x04, 0x68, 0xd2, 0x7d, 0x70, 0x0b, 0x04, 0xbd, 0x04, 0x68, 0xd0, 0x7d, 0x54, 0x9d, 0x50, 
-    0xbd, 0x25, 0x40, 0x02, 0x7d, 0x25, 0x7d, 0x32, 0x09, 0xb1, 0x00, 0x14, 0xca, 0xb8, 0x54, 0x1f, 
-    0xb4, 0x01, 0x31, 0xda, 0xb8, 0x7e, 0x19, 0xb0, 0x7a, 0x09, 0xb0, 0x0b, 0x04, 0x1b, 0x24, 0x78, 
-    0xe7, 0x02, 0x4f, 0xa4, 0x75, 0x2f, 0x99, 0x12, 0x7e, 0x30, 0x09, 0xb1, 0x00, 0x04, 0x54, 0xfa, 
-    0x19, 0xb1, 0x00, 0x04, 0x30, 0x39, 0x0a, 0x09, 0xb1, 0x00, 0x10, 0x54, 0xfe, 0x19, 0xb1, 0x00, 
-    0x10, 0xd2, 0x11, 0x22, 0xda, 0xb8, 0x30, 0xe0, 0xd8, 0xbd, 0x32, 0x68, 0x07, 0xca, 0xb8, 0x12, 
-    0x4f, 0xa4, 0xda, 0xb8, 0x02, 0x50, 0xcb, 0x09, 0xb1, 0x00, 0x18, 0x7e, 0xa0, 0x88, 0x75, 0x2f, 
-    0x90, 0x12, 0x7e, 0x30, 0xf5, 0x2f, 0x12, 0x7e, 0x30, 0xa5, 0xfd, 0x5e, 0x50, 0x0a, 0x68, 0x1d, 
-    0xa5, 0xfd, 0x5e, 0x50, 0x20, 0x68, 0x04, 0xd2, 0x59, 0x80, 0x02, 0xc2, 0x59, 0xa5, 0xfd, 0x5e, 
-    0x50, 0x80, 0x68, 0x04, 0xd2, 0x51, 0x80, 0x02, 0xc2, 0x51, 0x12, 0x42, 0xc3, 0x02, 0x65, 0x9c, 
-    0x75, 0x2f, 0x91, 0x12, 0x7e, 0x30, 0x09, 0xb1, 0x00, 0x14, 0x7a, 0xb1, 0x2f, 0x12, 0x7e, 0x30, 
-    0x20, 0xe0, 0x08, 0xd2, 0x04, 0x7e, 0xa0, 0x80, 0x02, 0x65, 0x9c, 0xd2, 0x04, 0x30, 0xe1, 0x06, 
-    0x7e, 0xa0, 0x80, 0x12, 0x65, 0x9c, 0xca, 0xb8, 0x5e, 0xb0, 0x1c, 0xda, 0xb8, 0x68, 0x12, 0x7e, 
-    0xa0, 0xc0, 0x09, 0x61, 0x00, 0x00, 0x12, 0x65, 0xbf, 0x09, 0xb1, 0x00, 0x14, 0x20, 0xe0, 0xdb, 
-    0x22, 0x02, 0x4f, 0xf8, 0x75, 0x2f, 0x95, 0x12, 0x7e, 0x30, 0x22, 0x75, 0x2f, 0x96, 0x12, 0x7e, 
-    0x30, 0x22, 0x10, 0x0a, 0x01, 0x22, 0x20, 0x2a, 0x03, 0xd2, 0x0a, 0x22, 0x75, 0x2f, 0xa2, 0x12, 
-    0x7e, 0x30, 0x7e, 0x14, 0x82, 0x00, 0x80, 0x06, 0x20, 0x2a, 0x03, 0xd2, 0x0a, 0x22, 0x09, 0xb1, 
-    0x00, 0x14, 0xca, 0xb8, 0x5e, 0xb0, 0x1e, 0xda, 0xb8, 0x68, 0x03, 0x12, 0x54, 0x00, 0x30, 0x32, 
-    0x06, 0x20, 0xe6, 0x4f, 0xd2, 0x0a, 0x22, 0x30, 0xe6, 0x02, 0xd2, 0x62, 0x7e, 0x37, 0x01, 0x7d, 
-    0x7e, 0x27, 0x01, 0x9d, 0x9d, 0x32, 0x40, 0x31, 0x7d, 0x02, 0x2e, 0x05, 0x36, 0x7a, 0x05, 0x36, 
-    0x7a, 0x37, 0x01, 0x7d, 0x7e, 0x37, 0x01, 0x5d, 0x7d, 0x43, 0x2d, 0x42, 0xbe, 0x44, 0x15, 0xcc, 
-    0x38, 0x68, 0x7a, 0x47, 0x01, 0x5d, 0x75, 0x2f, 0x94, 0x12, 0x7e, 0x30, 0x7a, 0x51, 0x2f, 0x12, 
-    0x7e, 0x30, 0x12, 0x68, 0x34, 0x10, 0x62, 0xc4, 0x22, 0xc2, 0x62, 0x2d, 0x23, 0x68, 0x78, 0x6d, 
-    0x33, 0x80, 0x1a, 0x7e, 0x27, 0x01, 0x7d, 0xbe, 0x24, 0x00, 0x00, 0x68, 0x6a, 0xbe, 0x27, 0x01, 
-    0x9d, 0x28, 0x04, 0x7e, 0x27, 0x01, 0x9d, 0x7e, 0x37, 0x01, 0x7d, 0x9d, 0x32, 0x7d, 0x02, 0x2e, 
-    0x05, 0x36, 0x7a, 0x05, 0x36, 0x7a, 0x37, 0x01, 0x7d, 0x7e, 0x37, 0x01, 0x5d, 0x7d, 0x43, 0x2d, 
-    0x42, 0xbe, 0x44, 0x15, 0xcc, 0x38, 0x13, 0x7a, 0x47, 0x01, 0x5d, 0x75, 0x2f, 0x94, 0x12, 0x7e, 
-    0x30, 0x7a, 0x51, 0x2f, 0x12, 0x7e, 0x30, 0x02, 0x68, 0x34, 0x75, 0x2f, 0x94, 0x12, 0x7e, 0x30, 
-    0x7a, 0x51, 0x2f, 0x12, 0x7e, 0x30, 0x9e, 0x44, 0x15, 0xcd, 0x9d, 0x24, 0x12, 0x68, 0x34, 0x7e, 
-    0x34, 0x11, 0xcd, 0x7d, 0x24, 0x2d, 0x43, 0x7a, 0x47, 0x01, 0x5d, 0x12, 0x68, 0x34, 0xbe, 0x25, 
-    0x20, 0x78, 0x03, 0x02, 0x51, 0x75, 0x22, 0xd2, 0x0a, 0x7e, 0x04, 0x11, 0xcd, 0x7a, 0x07, 0x01, 
-    0x5d, 0x7a, 0x07, 0x01, 0x6d, 0x75, 0x2f, 0x94, 0x12, 0x7e, 0x30, 0x75, 0x2f, 0x00, 0x12, 0x7e, 
-    0x30, 0x22, 0x75, 0x2f, 0x92, 0x12, 0x7e, 0x30, 0xd2, 0x04, 0x09, 0xb1, 0x00, 0x14, 0xca, 0xb8, 
-    0x54, 0x82, 0xda, 0xb8, 0x78, 0x70, 0x7e, 0x37, 0x01, 0xcb, 0x7e, 0x27, 0x01, 0xad, 0x2e, 0x24, 
-    0x00, 0x02, 0x2d, 0x32, 0xbe, 0x34, 0x04, 0x00, 0x38, 0x3c, 0x7d, 0x02, 0x2e, 0x05, 0x30, 0x7a, 
-    0x05, 0x30, 0x7a, 0x37, 0x01, 0xcb, 0x7e, 0x37, 0x01, 0xc9, 0x7d, 0x43, 0x2d, 0x42, 0xbe, 0x44, 
-    0x05, 0xcc, 0x38, 0x44, 0x7a, 0x47, 0x01, 0xc9, 0x7e, 0x24, 0x02, 0x00, 0x2e, 0x27, 0x01, 0xad, 
-    0x1b, 0x38, 0x20, 0x0b, 0x35, 0x7a, 0x51, 0x2f, 0x12, 0x7e, 0x30, 0xbe, 0x50, 0x38, 0x78, 0x03, 
-    0x02, 0x69, 0x1f, 0x02, 0x69, 0x04, 0x75, 0x2f, 0x99, 0x12, 0x7e, 0x30, 0x09, 0xb1, 0x00, 0x04, 
-    0x54, 0xfa, 0x19, 0xb1, 0x00, 0x04, 0x30, 0x3a, 0x0a, 0x09, 0xb1, 0x00, 0x10, 0x54, 0xfe, 0x19, 
-    0xb1, 0x00, 0x10, 0xd2, 0x12, 0x22, 0x80, 0x7f, 0x7a, 0x51, 0x2f, 0x12, 0x7e, 0x30, 0x9e, 0x44, 
-    0x05, 0xcd, 0x9d, 0x24, 0x7e, 0x64, 0x02, 0x00, 0x2e, 0x67, 0x01, 0xad, 0x9e, 0x24, 0x00, 0x02, 
-    0x40, 0x17, 0x1b, 0x38, 0x60, 0x0b, 0x35, 0x12, 0x69, 0x04, 0x7e, 0x34, 0x01, 0xcd, 0x7d, 0x24, 
-    0x2d, 0x43, 0x7a, 0x47, 0x01, 0xc9, 0x02, 0x69, 0x04, 0x7a, 0x39, 0xc0, 0x7e, 0x34, 0x01, 0xcd, 
-    0x7a, 0x39, 0xd0, 0x0b, 0x34, 0x1b, 0x44, 0x80, 0xe5, 0x9d, 0x32, 0x7c, 0xb6, 0x54, 0x0f, 0x23, 
-    0x23, 0x23, 0x44, 0x02, 0x7a, 0x69, 0xb0, 0x7a, 0x79, 0x70, 0x0b, 0x35, 0x75, 0x2f, 0x93, 0x12, 
-    0x7e, 0x30, 0x7a, 0x71, 0x2f, 0x12, 0x7e, 0x30, 0xbd, 0x04, 0x68, 0x2b, 0x7a, 0x07, 0x01, 0xc9, 
-    0x7e, 0x47, 0x01, 0xcb, 0x2d, 0x43, 0x7a, 0x47, 0x01, 0xcb, 0x2e, 0x35, 0x30, 0x7a, 0x35, 0x30, 
-    0x22, 0xd2, 0x04, 0x09, 0xb1, 0x00, 0x14, 0x20, 0xe0, 0x13, 0x22, 0x7e, 0x04, 0x01, 0xcd, 0x80, 
-    0x28, 0x7e, 0x04, 0x01, 0xcd, 0x80, 0x2a, 0x7e, 0x04, 0x01, 0xcd, 0x80, 0xcf, 0x7e, 0x07, 0x01, 
-    0xcb, 0x7e, 0x24, 0x03, 0xfe, 0x9d, 0x20, 0x28, 0x40, 0x7e, 0x07, 0x01, 0xc9, 0x7e, 0x44, 0x05, 
-    0xcd, 0x7d, 0x60, 0x0b, 0x04, 0xbd, 0x04, 0x68, 0xd2, 0x7d, 0x70, 0x0b, 0x04, 0xbd, 0x04, 0x68, 
-    0xd0, 0x7d, 0x54, 0x9d, 0x50, 0xbd, 0x25, 0x40, 0x02, 0x7d, 0x25, 0x7d, 0x32, 0x09, 0xb1, 0x00, 
-    0x14, 0xca, 0xb8, 0x54, 0x1f, 0xb4, 0x01, 0x31, 0xda, 0xb8, 0x7e, 0x19, 0xb0, 0x7a, 0x09, 0xb0, 
-    0x0b, 0x04, 0x1b, 0x24, 0x78, 0xe7, 0x02, 0x52, 0xd9, 0x75, 0x2f, 0x99, 0x12, 0x7e, 0x30, 0x09, 
-    0xb1, 0x00, 0x04, 0x54, 0xfa, 0x19, 0xb1, 0x00, 0x04, 0x30, 0x3a, 0x0a, 0x09, 0xb1, 0x00, 0x10, 
-    0x54, 0xfe, 0x19, 0xb1, 0x00, 0x10, 0xd2, 0x12, 0x22, 0xda, 0xb8, 0x30, 0xe0, 0xd8, 0xbd, 0x32, 
-    0x68, 0x07, 0xca, 0xb8, 0x12, 0x52, 0xd9, 0xda, 0xb8, 0x02, 0x54, 0x00, 0x09, 0xb1, 0x00, 0x18, 
-    0x7e, 0xa0, 0x88, 0x75, 0x2f, 0x90, 0x12, 0x7e, 0x30, 0xf5, 0x2f, 0x12, 0x7e, 0x30, 0xa5, 0xfd, 
-    0x5e, 0x50, 0x0a, 0x68, 0x1d, 0xa5, 0xfd, 0x5e, 0x50, 0x20, 0x68, 0x04, 0xd2, 0x5a, 0x80, 0x02, 
-    0xc2, 0x5a, 0xa5, 0xfd, 0x5e, 0x50, 0x80, 0x68, 0x04, 0xd2, 0x52, 0x80, 0x02, 0xc2, 0x52, 0x12, 
-    0x42, 0xda, 0x02, 0x65, 0x9c, 0x75, 0x2f, 0x91, 0x12, 0x7e, 0x30, 0x09, 0xb1, 0x00, 0x14, 0x7a, 
-    0xb1, 0x2f, 0x12, 0x7e, 0x30, 0x20, 0xe0, 0x08, 0xd2, 0x04, 0x7e, 0xa0, 0x80, 0x02, 0x65, 0x9c, 
-    0xd2, 0x04, 0x30, 0xe1, 0x06, 0x7e, 0xa0, 0x80, 0x12, 0x65, 0x9c, 0xca, 0xb8, 0x5e, 0xb0, 0x1c, 
-    0xda, 0xb8, 0x68, 0x12, 0x7e, 0xa0, 0xc0, 0x09, 0x61, 0x00, 0x00, 0x12, 0x65, 0xbf, 0x09, 0xb1, 
-    0x00, 0x14, 0x20, 0xe0, 0xdb, 0x22, 0x02, 0x53, 0x2d, 0x75, 0x2f, 0x95, 0x12, 0x7e, 0x30, 0x22, 
-    0x75, 0x2f, 0x96, 0x12, 0x7e, 0x30, 0x22, 0x10, 0x0b, 0x01, 0x22, 0x20, 0x2b, 0x03, 0xd2, 0x0b, 
-    0x22, 0x75, 0x2f, 0xa3, 0x12, 0x7e, 0x30, 0x7e, 0x14, 0x83, 0x00, 0x80, 0x06, 0x20, 0x2b, 0x03, 
+    0x74, 0x07, 0xa9, 0x20, 0x30, 0x0b, 0xa9, 0x35, 0x30, 0x05, 0xbe, 0x20, 0x01, 0x28, 0x02, 0x74, 
+    0x0f, 0x19, 0xb0, 0x00, 0x04, 0xa9, 0x33, 0x30, 0x18, 0x74, 0xbf, 0x19, 0xb0, 0x00, 0x0c, 0x74, 
+    0x28, 0xa9, 0x20, 0x30, 0x02, 0x74, 0x20, 0x19, 0xb0, 0x00, 0x04, 0x74, 0x03, 0x19, 0xb0, 0x00, 
+    0x0c, 0x74, 0xa7, 0x19, 0xb0, 0x00, 0x08, 0x74, 0x0c, 0x19, 0xb0, 0x00, 0x10, 0x22, 0x7e, 0x04, 
+    0x80, 0x00, 0x4c, 0x02, 0xe4, 0x19, 0xb0, 0x00, 0x04, 0x09, 0xb0, 0x00, 0x10, 0x54, 0x08, 0x19, 
+    0xb0, 0x00, 0x10, 0x74, 0xa7, 0x19, 0xb0, 0x00, 0x08, 0x22, 0x7c, 0xb2, 0x23, 0x0a, 0x2b, 0x49, 
+    0x22, 0x41, 0xa5, 0x89, 0x24, 0x41, 0xb5, 0x41, 0xd4, 0x41, 0xf3, 0x42, 0x12, 0x42, 0x31, 0x42, 
+    0x50, 0x42, 0x6f, 0x42, 0x8e, 0xc2, 0x10, 0xc2, 0x18, 0xc2, 0x20, 0xc2, 0x08, 0x7e, 0x04, 0x09, 
+    0xe3, 0x7a, 0x07, 0x01, 0x6f, 0x7a, 0x07, 0x01, 0x7f, 0x6d, 0x00, 0x7a, 0x07, 0x01, 0x8f, 0x7a, 
+    0x07, 0x01, 0x9f, 0x22, 0xc2, 0x11, 0xc2, 0x19, 0xc2, 0x21, 0xc2, 0x09, 0x7e, 0x04, 0x0d, 0xe3, 
+    0x7a, 0x07, 0x01, 0x71, 0x7a, 0x07, 0x01, 0x81, 0x6d, 0x00, 0x7a, 0x07, 0x01, 0x91, 0x7a, 0x07, 
+    0x01, 0xa1, 0x22, 0xc2, 0x12, 0xc2, 0x1a, 0xc2, 0x22, 0xc2, 0x0a, 0x7e, 0x04, 0x11, 0xe3, 0x7a, 
+    0x07, 0x01, 0x73, 0x7a, 0x07, 0x01, 0x83, 0x6d, 0x00, 0x7a, 0x07, 0x01, 0x93, 0x7a, 0x07, 0x01, 
+    0xa3, 0x22, 0xc2, 0x13, 0xc2, 0x1b, 0xc2, 0x23, 0xc2, 0x0b, 0x7e, 0x04, 0x15, 0xe3, 0x7a, 0x07, 
+    0x01, 0x75, 0x7a, 0x07, 0x01, 0x85, 0x6d, 0x00, 0x7a, 0x07, 0x01, 0x95, 0x7a, 0x07, 0x01, 0xa5, 
+    0x22, 0xc2, 0x14, 0xc2, 0x1c, 0xc2, 0x24, 0xc2, 0x0c, 0x7e, 0x04, 0x19, 0xe3, 0x7a, 0x07, 0x01, 
+    0x77, 0x7a, 0x07, 0x01, 0x87, 0x6d, 0x00, 0x7a, 0x07, 0x01, 0x97, 0x7a, 0x07, 0x01, 0xa7, 0x22, 
+    0xc2, 0x15, 0xc2, 0x1d, 0xc2, 0x25, 0xc2, 0x0d, 0x7e, 0x04, 0x1d, 0xe3, 0x7a, 0x07, 0x01, 0x79, 
+    0x7a, 0x07, 0x01, 0x89, 0x6d, 0x00, 0x7a, 0x07, 0x01, 0x99, 0x7a, 0x07, 0x01, 0xa9, 0x22, 0xc2, 
+    0x16, 0xc2, 0x1e, 0xc2, 0x26, 0xc2, 0x0e, 0x7e, 0x04, 0x21, 0xe3, 0x7a, 0x07, 0x01, 0x7b, 0x7a, 
+    0x07, 0x01, 0x8b, 0x6d, 0x00, 0x7a, 0x07, 0x01, 0x9b, 0x7a, 0x07, 0x01, 0xab, 0x22, 0xc2, 0x17, 
+    0xc2, 0x1f, 0xc2, 0x27, 0xc2, 0x0f, 0x7e, 0x04, 0x25, 0xe3, 0x7a, 0x07, 0x01, 0x7d, 0x7a, 0x07, 
+    0x01, 0x8d, 0x6d, 0x00, 0x7a, 0x07, 0x01, 0x9d, 0x7a, 0x07, 0x01, 0xad, 0x22, 0x7c, 0xb2, 0x23, 
+    0x0a, 0x2b, 0x49, 0x22, 0x42, 0xb8, 0x89, 0x24, 0x42, 0xc8, 0x42, 0xe9, 0x43, 0x0a, 0x43, 0x2b, 
+    0x43, 0x4c, 0x43, 0x6d, 0x43, 0x8e, 0x43, 0xaf, 0x30, 0x50, 0x07, 0x20, 0x68, 0x04, 0xc2, 0x28, 
+    0x80, 0x16, 0x30, 0x40, 0x07, 0x20, 0x60, 0x04, 0xc2, 0x28, 0x80, 0x0c, 0x30, 0x48, 0x07, 0x20, 
+    0x58, 0x04, 0xc2, 0x28, 0x80, 0x02, 0xd2, 0x28, 0x22, 0x30, 0x51, 0x07, 0x20, 0x69, 0x04, 0xc2, 
+    0x29, 0x80, 0x16, 0x30, 0x41, 0x07, 0x20, 0x61, 0x04, 0xc2, 0x29, 0x80, 0x0c, 0x30, 0x49, 0x07, 
+    0x20, 0x59, 0x04, 0xc2, 0x29, 0x80, 0x02, 0xd2, 0x29, 0x22, 0x30, 0x52, 0x07, 0x20, 0x6a, 0x04, 
+    0xc2, 0x2a, 0x80, 0x16, 0x30, 0x42, 0x07, 0x20, 0x62, 0x04, 0xc2, 0x2a, 0x80, 0x0c, 0x30, 0x4a, 
+    0x07, 0x20, 0x5a, 0x04, 0xc2, 0x2a, 0x80, 0x02, 0xd2, 0x2a, 0x22, 0x30, 0x53, 0x07, 0x20, 0x6b, 
+    0x04, 0xc2, 0x2b, 0x80, 0x16, 0x30, 0x43, 0x07, 0x20, 0x63, 0x04, 0xc2, 0x2b, 0x80, 0x0c, 0x30, 
+    0x4b, 0x07, 0x20, 0x5b, 0x04, 0xc2, 0x2b, 0x80, 0x02, 0xd2, 0x2b, 0x22, 0x30, 0x54, 0x07, 0x20, 
+    0x6c, 0x04, 0xc2, 0x2c, 0x80, 0x16, 0x30, 0x44, 0x07, 0x20, 0x64, 0x04, 0xc2, 0x2c, 0x80, 0x0c, 
+    0x30, 0x4c, 0x07, 0x20, 0x5c, 0x04, 0xc2, 0x2c, 0x80, 0x02, 0xd2, 0x2c, 0x22, 0x30, 0x55, 0x07, 
+    0x20, 0x6d, 0x04, 0xc2, 0x2d, 0x80, 0x16, 0x30, 0x45, 0x07, 0x20, 0x65, 0x04, 0xc2, 0x2d, 0x80, 
+    0x0c, 0x30, 0x4d, 0x07, 0x20, 0x5d, 0x04, 0xc2, 0x2d, 0x80, 0x02, 0xd2, 0x2d, 0x22, 0x30, 0x56, 
+    0x07, 0x20, 0x6e, 0x04, 0xc2, 0x2e, 0x80, 0x16, 0x30, 0x46, 0x07, 0x20, 0x66, 0x04, 0xc2, 0x2e, 
+    0x80, 0x0c, 0x30, 0x4e, 0x07, 0x20, 0x5e, 0x04, 0xc2, 0x2e, 0x80, 0x02, 0xd2, 0x2e, 0x22, 0x30, 
+    0x57, 0x07, 0x20, 0x6f, 0x04, 0xc2, 0x2f, 0x80, 0x16, 0x30, 0x47, 0x07, 0x20, 0x67, 0x04, 0xc2, 
+    0x2f, 0x80, 0x0c, 0x30, 0x4f, 0x07, 0x20, 0x5f, 0x04, 0xc2, 0x2f, 0x80, 0x02, 0xd2, 0x2f, 0x22, 
+    0x44, 0x38, 0x43, 0xe5, 0xbe, 0xb0, 0x02, 0x40, 0x01, 0x22, 0x23, 0x0a, 0x5b, 0x49, 0x55, 0x43, 
+    0xd0, 0x99, 0x54, 0xd3, 0x22, 0xa9, 0xc5, 0x87, 0x12, 0x44, 0x43, 0x7e, 0x04, 0x05, 0xe3, 0x7a, 
+    0x07, 0x01, 0xd7, 0x7a, 0x07, 0x01, 0xd9, 0x7e, 0x04, 0x01, 0xe3, 0x7a, 0x07, 0x01, 0xdd, 0x7a, 
+    0x07, 0x01, 0xdf, 0x7e, 0x04, 0x74, 0xad, 0x7a, 0x05, 0x61, 0x75, 0xf1, 0x01, 0x75, 0xe1, 0x1f, 
+    0x75, 0xe4, 0x04, 0x75, 0xf4, 0x04, 0x75, 0xf1, 0x02, 0x75, 0xe1, 0x03, 0x75, 0xe4, 0x04, 0x75, 
+    0xf4, 0x04, 0x43, 0xa2, 0x1c, 0x12, 0x40, 0xeb, 0x7e, 0x20, 0x00, 0x12, 0x41, 0x9a, 0x0b, 0x20, 
+    0xbe, 0x21, 0x2f, 0x78, 0xf6, 0xd2, 0xa8, 0x22, 0xa9, 0xd5, 0x87, 0x12, 0x44, 0x43, 0xd2, 0x92, 
+    0xc2, 0xa8, 0x22, 0x75, 0xa3, 0x00, 0x53, 0xa2, 0x03, 0x75, 0xc1, 0x00, 0x53, 0xc0, 0x03, 0x7e, 
+    0x00, 0x05, 0x7a, 0x01, 0xf1, 0x43, 0xf4, 0x80, 0x43, 0xe4, 0x80, 0xe5, 0xf2, 0x54, 0x7f, 0x44, 
+    0x08, 0xf5, 0xf2, 0xe5, 0xe2, 0x54, 0x7f, 0x44, 0x08, 0xf5, 0xe2, 0x75, 0xe1, 0x10, 0xa5, 0xd8, 
+    0xe1, 0x22, 0xca, 0x09, 0x12, 0x30, 0x20, 0x10, 0x01, 0x12, 0xd5, 0x67, 0x1e, 0x63, 0x69, 0x01, 
+    0x7e, 0x00, 0x6a, 0x2e, 0x01, 0x69, 0xa5, 0xe6, 0xf5, 0x67, 0x80, 0x12, 0x20, 0x02, 0x1e, 0x75, 
+    0x69, 0x00, 0x85, 0x6a, 0x67, 0xd2, 0x02, 0x74, 0x00, 0x80, 0x0d, 0x30, 0x02, 0x0f, 0xc2, 0x02, 
+    0x7e, 0x00, 0x6c, 0x2e, 0x01, 0x69, 0xa5, 0xe6, 0x53, 0x90, 0xcf, 0x42, 0x90, 0xda, 0x09, 0x32, 
+    0xc0, 0xd0, 0xc0, 0xd1, 0xc0, 0xe0, 0xc0, 0xf0, 0xca, 0x0b, 0xca, 0x1b, 0xca, 0x2b, 0xd2, 0x01, 
+    0x75, 0x31, 0x89, 0x12, 0x7c, 0x15, 0x7e, 0x14, 0x80, 0x00, 0x09, 0xb1, 0x00, 0x08, 0x20, 0xe0, 
+    0x03, 0x02, 0x45, 0x4f, 0x20, 0x78, 0x5a, 0xa5, 0x0a, 0x09, 0xb1, 0x00, 0x08, 0x20, 0xe0, 0x03, 
+    0x02, 0x45, 0x67, 0x20, 0x79, 0x4b, 0xa5, 0x0a, 0x09, 0xb1, 0x00, 0x08, 0x20, 0xe0, 0x03, 0x02, 
+    0x45, 0x7f, 0xa5, 0x0a, 0x09, 0xb1, 0x00, 0x08, 0x20, 0xe0, 0x03, 0x02, 0x45, 0x97, 0x20, 0x7a, 
+    0x30, 0xa5, 0x0a, 0x09, 0xb1, 0x00, 0x08, 0x20, 0xe0, 0x03, 0x02, 0x45, 0xaf, 0xa5, 0x0a, 0x09, 
+    0xb1, 0x00, 0x08, 0x20, 0xe0, 0x03, 0x02, 0x45, 0xc7, 0xa5, 0x0a, 0x09, 0xb1, 0x00, 0x08, 0x20, 
+    0xe0, 0x03, 0x02, 0x45, 0xdf, 0xa5, 0x0a, 0x09, 0xb1, 0x00, 0x08, 0x20, 0xe0, 0x03, 0x02, 0x45, 
+    0xf7, 0x30, 0x04, 0x0c, 0xc2, 0x04, 0xc0, 0xf1, 0x75, 0xf1, 0x01, 0x12, 0x6f, 0xd9, 0xd0, 0xf1, 
+    0xda, 0x2b, 0xda, 0x1b, 0xda, 0x0b, 0xd0, 0xf0, 0xd0, 0xe0, 0xd0, 0xd1, 0xd0, 0xd0, 0x32, 0x75, 
+    0x31, 0x80, 0x12, 0x7c, 0x15, 0x54, 0x3e, 0x0a, 0x5b, 0x7e, 0x44, 0x00, 0xff, 0x69, 0x52, 0x63, 
+    0x2b, 0xca, 0x06, 0xc6, 0x44, 0x89, 0x54, 0x75, 0x31, 0x81, 0x12, 0x7c, 0x15, 0x54, 0x3e, 0x0a, 
+    0x5b, 0x7e, 0x44, 0x00, 0xff, 0x69, 0x52, 0x63, 0x6b, 0xca, 0x06, 0xc6, 0x44, 0x89, 0x54, 0x75, 
+    0x31, 0x82, 0x12, 0x7c, 0x15, 0x54, 0x3e, 0x0a, 0x5b, 0x7e, 0x44, 0x00, 0xff, 0x69, 0x52, 0x63, 
+    0xab, 0xca, 0x06, 0xc6, 0x44, 0x89, 0x54, 0x75, 0x31, 0x83, 0x12, 0x7c, 0x15, 0x54, 0x3e, 0x0a, 
+    0x5b, 0x7e, 0x44, 0x00, 0xff, 0x69, 0x52, 0x63, 0xeb, 0xca, 0x06, 0xc6, 0x44, 0x89, 0x54, 0x75, 
+    0x31, 0x84, 0x12, 0x7c, 0x15, 0x54, 0x3e, 0x0a, 0x5b, 0x7e, 0x44, 0x00, 0xff, 0x69, 0x52, 0x64, 
+    0x2b, 0xca, 0x06, 0xc6, 0x44, 0x89, 0x54, 0x75, 0x31, 0x85, 0x12, 0x7c, 0x15, 0x54, 0x3e, 0x0a, 
+    0x5b, 0x7e, 0x44, 0x00, 0xff, 0x69, 0x52, 0x64, 0x6b, 0xca, 0x06, 0xc6, 0x44, 0x89, 0x54, 0x75, 
+    0x31, 0x86, 0x12, 0x7c, 0x15, 0x54, 0x3e, 0x0a, 0x5b, 0x7e, 0x44, 0x00, 0xff, 0x69, 0x52, 0x64, 
+    0xab, 0xca, 0x06, 0xc6, 0x44, 0x89, 0x54, 0x75, 0x31, 0x87, 0x12, 0x7c, 0x15, 0x54, 0x3e, 0x0a, 
+    0x5b, 0x7e, 0x44, 0x00, 0xff, 0x69, 0x52, 0x64, 0xeb, 0xca, 0x06, 0xc6, 0x44, 0x89, 0x54, 0x10, 
+    0x08, 0x01, 0x22, 0x20, 0x28, 0x03, 0xd2, 0x08, 0x22, 0x75, 0x31, 0xa0, 0x12, 0x7c, 0x15, 0x7e, 
+    0x14, 0x80, 0x00, 0x80, 0x06, 0x20, 0x28, 0x03, 0xd2, 0x08, 0x22, 0x09, 0xb1, 0x00, 0x14, 0xca, 
+    0xb8, 0x5e, 0xb0, 0x1e, 0xda, 0xb8, 0x68, 0x03, 0x12, 0x49, 0x30, 0x20, 0xe6, 0x03, 0xd2, 0x08, 
+    0x22, 0x30, 0x30, 0x49, 0xd2, 0x70, 0x7e, 0x37, 0x01, 0x8f, 0x7e, 0x27, 0x01, 0xaf, 0x9d, 0x32, 
+    0x40, 0x31, 0x7d, 0x02, 0x2e, 0x05, 0x48, 0x7a, 0x05, 0x48, 0x7a, 0x37, 0x01, 0x8f, 0x7e, 0x37, 
+    0x01, 0x6f, 0x7d, 0x43, 0x2d, 0x42, 0xbe, 0x44, 0x0d, 0xe2, 0x38, 0x68, 0x7a, 0x47, 0x01, 0x6f, 
+    0x75, 0x31, 0x94, 0x12, 0x7c, 0x15, 0x7a, 0x51, 0x31, 0x12, 0x7c, 0x15, 0x12, 0x65, 0x2b, 0x10, 
+    0x70, 0xc4, 0x22, 0xc2, 0x70, 0x2d, 0x23, 0x68, 0x78, 0x6d, 0x33, 0x80, 0x1a, 0x7e, 0x27, 0x01, 
+    0x8f, 0xbe, 0x24, 0x00, 0x00, 0x68, 0x6a, 0xbe, 0x27, 0x01, 0xaf, 0x28, 0x04, 0x7e, 0x27, 0x01, 
+    0xaf, 0x7e, 0x37, 0x01, 0x8f, 0x9d, 0x32, 0x7d, 0x02, 0x2e, 0x05, 0x48, 0x7a, 0x05, 0x48, 0x7a, 
+    0x37, 0x01, 0x8f, 0x7e, 0x37, 0x01, 0x6f, 0x7d, 0x43, 0x2d, 0x42, 0xbe, 0x44, 0x0d, 0xe2, 0x38, 
+    0x13, 0x7a, 0x47, 0x01, 0x6f, 0x75, 0x31, 0x94, 0x12, 0x7c, 0x15, 0x7a, 0x51, 0x31, 0x12, 0x7c, 
+    0x15, 0x02, 0x65, 0x2b, 0x75, 0x31, 0x94, 0x12, 0x7c, 0x15, 0x7a, 0x51, 0x31, 0x12, 0x7c, 0x15, 
+    0x9e, 0x44, 0x0d, 0xe3, 0x9d, 0x24, 0x12, 0x65, 0x2b, 0x7e, 0x34, 0x09, 0xe3, 0x7d, 0x24, 0x2d, 
+    0x43, 0x7a, 0x47, 0x01, 0x6f, 0x12, 0x65, 0x2b, 0xbe, 0x25, 0x20, 0x78, 0x03, 0x02, 0x46, 0x7f, 
+    0x22, 0xd2, 0x08, 0x7e, 0x04, 0x09, 0xe3, 0x7a, 0x07, 0x01, 0x6f, 0x7a, 0x07, 0x01, 0x7f, 0x75, 
+    0x31, 0x94, 0x12, 0x7c, 0x15, 0x75, 0x31, 0x00, 0x12, 0x7c, 0x15, 0x22, 0x75, 0x31, 0x92, 0x12, 
+    0x7c, 0x15, 0xd2, 0x04, 0x09, 0xb1, 0x00, 0x14, 0xca, 0xb8, 0x54, 0x82, 0xda, 0xb8, 0x78, 0x70, 
+    0x7e, 0x37, 0x01, 0xe1, 0x7e, 0x27, 0x01, 0xbf, 0x2e, 0x24, 0x00, 0x02, 0x2d, 0x32, 0xbe, 0x34, 
+    0x04, 0x00, 0x38, 0x3c, 0x7d, 0x02, 0x2e, 0x05, 0x46, 0x7a, 0x05, 0x46, 0x7a, 0x37, 0x01, 0xe1, 
+    0x7e, 0x37, 0x01, 0xdf, 0x7d, 0x43, 0x2d, 0x42, 0xbe, 0x44, 0x05, 0xe2, 0x38, 0x44, 0x7a, 0x47, 
+    0x01, 0xdf, 0x7e, 0x24, 0x00, 0x00, 0x2e, 0x27, 0x01, 0xbf, 0x1b, 0x38, 0x20, 0x0b, 0x35, 0x7a, 
+    0x51, 0x31, 0x12, 0x7c, 0x15, 0xbe, 0x50, 0x38, 0x78, 0x03, 0x02, 0x66, 0x16, 0x02, 0x65, 0xfb, 
+    0x75, 0x31, 0x99, 0x12, 0x7c, 0x15, 0x09, 0xb1, 0x00, 0x04, 0x54, 0xfa, 0x19, 0xb1, 0x00, 0x04, 
+    0x30, 0x38, 0x0a, 0x09, 0xb1, 0x00, 0x10, 0x54, 0xfe, 0x19, 0xb1, 0x00, 0x10, 0xd2, 0x10, 0x22, 
+    0x80, 0x7d, 0x7a, 0x51, 0x31, 0x12, 0x7c, 0x15, 0x9e, 0x44, 0x05, 0xe3, 0x9d, 0x24, 0x7e, 0x64, 
+    0x00, 0x00, 0x2e, 0x67, 0x01, 0xbf, 0x9e, 0x24, 0x00, 0x02, 0x40, 0x17, 0x1b, 0x38, 0x60, 0x0b, 
+    0x35, 0x12, 0x65, 0xfb, 0x7e, 0x34, 0x01, 0xe3, 0x7d, 0x24, 0x2d, 0x43, 0x7a, 0x47, 0x01, 0xdf, 
+    0x02, 0x65, 0xfb, 0x7a, 0x39, 0xc0, 0x7e, 0x34, 0x01, 0xe3, 0x7a, 0x39, 0xd0, 0x0b, 0x34, 0x1b, 
+    0x44, 0x80, 0xe5, 0x9d, 0x32, 0x7c, 0xb6, 0x54, 0x0f, 0x23, 0x23, 0x23, 0x44, 0x00, 0x7a, 0x69, 
+    0xb0, 0x7a, 0x79, 0x70, 0x0b, 0x35, 0x75, 0x31, 0x93, 0x12, 0x7c, 0x15, 0x7a, 0x71, 0x31, 0x12, 
+    0x7c, 0x15, 0xbd, 0x04, 0x68, 0x29, 0x7a, 0x07, 0x01, 0xdf, 0x7e, 0x47, 0x01, 0xe1, 0x2d, 0x43, 
+    0x7a, 0x47, 0x01, 0xe1, 0x2e, 0x35, 0x46, 0x7a, 0x35, 0x46, 0x22, 0x09, 0xb1, 0x00, 0x14, 0x20, 
+    0xe0, 0x13, 0x22, 0x7e, 0x04, 0x01, 0xe3, 0x80, 0x2a, 0x7e, 0x04, 0x01, 0xe3, 0x80, 0x2c, 0x7e, 
+    0x04, 0x01, 0xe3, 0x80, 0xd1, 0xd2, 0x04, 0x7e, 0x07, 0x01, 0xe1, 0x7e, 0x24, 0x03, 0xfe, 0x9d, 
+    0x20, 0x28, 0x40, 0x7e, 0x07, 0x01, 0xdf, 0x7e, 0x44, 0x05, 0xe3, 0x7d, 0x60, 0x0b, 0x04, 0xbd, 
+    0x04, 0x68, 0xd0, 0x7d, 0x70, 0x0b, 0x04, 0xbd, 0x04, 0x68, 0xce, 0x7d, 0x54, 0x9d, 0x50, 0xbd, 
+    0x25, 0x40, 0x02, 0x7d, 0x25, 0x7d, 0x32, 0x09, 0xb1, 0x00, 0x14, 0xca, 0xb8, 0x54, 0x1f, 0xb4, 
+    0x01, 0x31, 0xda, 0xb8, 0x7e, 0x19, 0xb0, 0x7a, 0x09, 0xb0, 0x0b, 0x04, 0x1b, 0x24, 0x78, 0xe7, 
+    0x02, 0x47, 0xe3, 0x75, 0x31, 0x99, 0x12, 0x7c, 0x15, 0x09, 0xb1, 0x00, 0x04, 0x54, 0xfa, 0x19, 
+    0xb1, 0x00, 0x04, 0x30, 0x38, 0x0a, 0x09, 0xb1, 0x00, 0x10, 0x54, 0xfe, 0x19, 0xb1, 0x00, 0x10, 
+    0xd2, 0x10, 0x22, 0xda, 0xb8, 0x30, 0xe0, 0xd8, 0xbd, 0x32, 0x68, 0x07, 0xca, 0xb8, 0x12, 0x47, 
+    0xe3, 0xda, 0xb8, 0x02, 0x49, 0x30, 0x09, 0xb1, 0x00, 0x18, 0x7e, 0xa0, 0x88, 0x75, 0x31, 0x90, 
+    0x12, 0x7c, 0x15, 0xf5, 0x31, 0x12, 0x7c, 0x15, 0xa5, 0xfc, 0x5e, 0xb0, 0xf0, 0xa5, 0xfd, 0x09, 
+    0xb1, 0x00, 0x18, 0x4c, 0x4b, 0x5e, 0xb0, 0xf0, 0xbc, 0xb5, 0x78, 0xf1, 0x5e, 0x40, 0x0f, 0x4c, 
+    0x54, 0x7c, 0xb5, 0x5e, 0x50, 0x0b, 0x68, 0x2a, 0xa5, 0xfd, 0x5e, 0x50, 0x10, 0x68, 0x04, 0xd2, 
+    0x68, 0x80, 0x02, 0xc2, 0x68, 0xa5, 0xfd, 0x5e, 0x50, 0x20, 0x68, 0x04, 0xd2, 0x60, 0x80, 0x02, 
+    0xc2, 0x60, 0xa5, 0xfd, 0x5e, 0x50, 0x80, 0x68, 0x04, 0xd2, 0x58, 0x80, 0x02, 0xc2, 0x58, 0x12, 
+    0x42, 0xc8, 0x02, 0x62, 0x93, 0x75, 0x31, 0x91, 0x12, 0x7c, 0x15, 0x09, 0xb1, 0x00, 0x14, 0x7a, 
+    0xb1, 0x31, 0x12, 0x7c, 0x15, 0x20, 0xe0, 0x08, 0xd2, 0x04, 0x7e, 0xa0, 0x80, 0x02, 0x62, 0x93, 
+    0xd2, 0x04, 0x30, 0xe1, 0x06, 0x7e, 0xa0, 0x80, 0x12, 0x62, 0x93, 0xca, 0xb8, 0x5e, 0xb0, 0x1c, 
+    0xda, 0xb8, 0x68, 0x12, 0x7e, 0xa0, 0xc0, 0x09, 0x61, 0x00, 0x00, 0x12, 0x62, 0xb6, 0x09, 0xb1, 
+    0x00, 0x14, 0x20, 0xe0, 0xdb, 0x22, 0x02, 0x48, 0x35, 0x75, 0x31, 0x95, 0x12, 0x7c, 0x15, 0x22, 
+    0x75, 0x31, 0x96, 0x12, 0x7c, 0x15, 0x22, 0x10, 0x09, 0x01, 0x22, 0x20, 0x29, 0x03, 0xd2, 0x09, 
+    0x22, 0x75, 0x31, 0xa1, 0x12, 0x7c, 0x15, 0x7e, 0x14, 0x81, 0x00, 0x80, 0x06, 0x20, 0x29, 0x03, 
+    0xd2, 0x09, 0x22, 0x09, 0xb1, 0x00, 0x14, 0xca, 0xb8, 0x5e, 0xb0, 0x1e, 0xda, 0xb8, 0x68, 0x03, 
+    0x12, 0x4c, 0x88, 0x20, 0xe6, 0x03, 0xd2, 0x09, 0x22, 0x30, 0x31, 0x49, 0xd2, 0x71, 0x7e, 0x37, 
+    0x01, 0x91, 0x7e, 0x27, 0x01, 0xb1, 0x9d, 0x32, 0x40, 0x31, 0x7d, 0x02, 0x2e, 0x05, 0x4a, 0x7a, 
+    0x05, 0x4a, 0x7a, 0x37, 0x01, 0x91, 0x7e, 0x37, 0x01, 0x71, 0x7d, 0x43, 0x2d, 0x42, 0xbe, 0x44, 
+    0x11, 0xe2, 0x38, 0x68, 0x7a, 0x47, 0x01, 0x71, 0x75, 0x31, 0x94, 0x12, 0x7c, 0x15, 0x7a, 0x51, 
+    0x31, 0x12, 0x7c, 0x15, 0x12, 0x65, 0x2b, 0x10, 0x71, 0xc4, 0x22, 0xc2, 0x71, 0x2d, 0x23, 0x68, 
+    0x78, 0x6d, 0x33, 0x80, 0x1a, 0x7e, 0x27, 0x01, 0x91, 0xbe, 0x24, 0x00, 0x00, 0x68, 0x6a, 0xbe, 
+    0x27, 0x01, 0xb1, 0x28, 0x04, 0x7e, 0x27, 0x01, 0xb1, 0x7e, 0x37, 0x01, 0x91, 0x9d, 0x32, 0x7d, 
+    0x02, 0x2e, 0x05, 0x4a, 0x7a, 0x05, 0x4a, 0x7a, 0x37, 0x01, 0x91, 0x7e, 0x37, 0x01, 0x71, 0x7d, 
+    0x43, 0x2d, 0x42, 0xbe, 0x44, 0x11, 0xe2, 0x38, 0x13, 0x7a, 0x47, 0x01, 0x71, 0x75, 0x31, 0x94, 
+    0x12, 0x7c, 0x15, 0x7a, 0x51, 0x31, 0x12, 0x7c, 0x15, 0x02, 0x65, 0x2b, 0x75, 0x31, 0x94, 0x12, 
+    0x7c, 0x15, 0x7a, 0x51, 0x31, 0x12, 0x7c, 0x15, 0x9e, 0x44, 0x11, 0xe3, 0x9d, 0x24, 0x12, 0x65, 
+    0x2b, 0x7e, 0x34, 0x0d, 0xe3, 0x7d, 0x24, 0x2d, 0x43, 0x7a, 0x47, 0x01, 0x71, 0x12, 0x65, 0x2b, 
+    0xbe, 0x25, 0x20, 0x78, 0x03, 0x02, 0x49, 0xd7, 0x22, 0xd2, 0x09, 0x7e, 0x04, 0x0d, 0xe3, 0x7a, 
+    0x07, 0x01, 0x71, 0x7a, 0x07, 0x01, 0x81, 0x75, 0x31, 0x94, 0x12, 0x7c, 0x15, 0x75, 0x31, 0x00, 
+    0x12, 0x7c, 0x15, 0x22, 0x75, 0x31, 0x92, 0x12, 0x7c, 0x15, 0xd2, 0x04, 0x09, 0xb1, 0x00, 0x14, 
+    0xca, 0xb8, 0x54, 0x82, 0xda, 0xb8, 0x78, 0x70, 0x7e, 0x37, 0x01, 0xe1, 0x7e, 0x27, 0x01, 0xc1, 
+    0x2e, 0x24, 0x00, 0x02, 0x2d, 0x32, 0xbe, 0x34, 0x04, 0x00, 0x38, 0x3c, 0x7d, 0x02, 0x2e, 0x05, 
+    0x46, 0x7a, 0x05, 0x46, 0x7a, 0x37, 0x01, 0xe1, 0x7e, 0x37, 0x01, 0xdf, 0x7d, 0x43, 0x2d, 0x42, 
+    0xbe, 0x44, 0x05, 0xe2, 0x38, 0x44, 0x7a, 0x47, 0x01, 0xdf, 0x7e, 0x24, 0x01, 0x00, 0x2e, 0x27, 
+    0x01, 0xc1, 0x1b, 0x38, 0x20, 0x0b, 0x35, 0x7a, 0x51, 0x31, 0x12, 0x7c, 0x15, 0xbe, 0x50, 0x38, 
+    0x78, 0x03, 0x02, 0x66, 0x16, 0x02, 0x65, 0xfb, 0x75, 0x31, 0x99, 0x12, 0x7c, 0x15, 0x09, 0xb1, 
+    0x00, 0x04, 0x54, 0xfa, 0x19, 0xb1, 0x00, 0x04, 0x30, 0x39, 0x0a, 0x09, 0xb1, 0x00, 0x10, 0x54, 
+    0xfe, 0x19, 0xb1, 0x00, 0x10, 0xd2, 0x11, 0x22, 0x80, 0x7d, 0x7a, 0x51, 0x31, 0x12, 0x7c, 0x15, 
+    0x9e, 0x44, 0x05, 0xe3, 0x9d, 0x24, 0x7e, 0x64, 0x01, 0x00, 0x2e, 0x67, 0x01, 0xc1, 0x9e, 0x24, 
+    0x00, 0x02, 0x40, 0x17, 0x1b, 0x38, 0x60, 0x0b, 0x35, 0x12, 0x65, 0xfb, 0x7e, 0x34, 0x01, 0xe3, 
+    0x7d, 0x24, 0x2d, 0x43, 0x7a, 0x47, 0x01, 0xdf, 0x02, 0x65, 0xfb, 0x7a, 0x39, 0xc0, 0x7e, 0x34, 
+    0x01, 0xe3, 0x7a, 0x39, 0xd0, 0x0b, 0x34, 0x1b, 0x44, 0x80, 0xe5, 0x9d, 0x32, 0x7c, 0xb6, 0x54, 
+    0x0f, 0x23, 0x23, 0x23, 0x44, 0x01, 0x7a, 0x69, 0xb0, 0x7a, 0x79, 0x70, 0x0b, 0x35, 0x75, 0x31, 
+    0x93, 0x12, 0x7c, 0x15, 0x7a, 0x71, 0x31, 0x12, 0x7c, 0x15, 0xbd, 0x04, 0x68, 0x29, 0x7a, 0x07, 
+    0x01, 0xdf, 0x7e, 0x47, 0x01, 0xe1, 0x2d, 0x43, 0x7a, 0x47, 0x01, 0xe1, 0x2e, 0x35, 0x46, 0x7a, 
+    0x35, 0x46, 0x22, 0x09, 0xb1, 0x00, 0x14, 0x20, 0xe0, 0x13, 0x22, 0x7e, 0x04, 0x01, 0xe3, 0x80, 
+    0x2a, 0x7e, 0x04, 0x01, 0xe3, 0x80, 0x2c, 0x7e, 0x04, 0x01, 0xe3, 0x80, 0xd1, 0xd2, 0x04, 0x7e, 
+    0x07, 0x01, 0xe1, 0x7e, 0x24, 0x03, 0xfe, 0x9d, 0x20, 0x28, 0x40, 0x7e, 0x07, 0x01, 0xdf, 0x7e, 
+    0x44, 0x05, 0xe3, 0x7d, 0x60, 0x0b, 0x04, 0xbd, 0x04, 0x68, 0xd0, 0x7d, 0x70, 0x0b, 0x04, 0xbd, 
+    0x04, 0x68, 0xce, 0x7d, 0x54, 0x9d, 0x50, 0xbd, 0x25, 0x40, 0x02, 0x7d, 0x25, 0x7d, 0x32, 0x09, 
+    0xb1, 0x00, 0x14, 0xca, 0xb8, 0x54, 0x1f, 0xb4, 0x01, 0x31, 0xda, 0xb8, 0x7e, 0x19, 0xb0, 0x7a, 
+    0x09, 0xb0, 0x0b, 0x04, 0x1b, 0x24, 0x78, 0xe7, 0x02, 0x4b, 0x3b, 0x75, 0x31, 0x99, 0x12, 0x7c, 
+    0x15, 0x09, 0xb1, 0x00, 0x04, 0x54, 0xfa, 0x19, 0xb1, 0x00, 0x04, 0x30, 0x39, 0x0a, 0x09, 0xb1, 
+    0x00, 0x10, 0x54, 0xfe, 0x19, 0xb1, 0x00, 0x10, 0xd2, 0x11, 0x22, 0xda, 0xb8, 0x30, 0xe0, 0xd8, 
+    0xbd, 0x32, 0x68, 0x07, 0xca, 0xb8, 0x12, 0x4b, 0x3b, 0xda, 0xb8, 0x02, 0x4c, 0x88, 0x09, 0xb1, 
+    0x00, 0x18, 0x7e, 0xa0, 0x88, 0x75, 0x31, 0x90, 0x12, 0x7c, 0x15, 0xf5, 0x31, 0x12, 0x7c, 0x15, 
+    0xa5, 0xfc, 0x5e, 0xb0, 0xf0, 0xa5, 0xfd, 0x09, 0xb1, 0x00, 0x18, 0x4c, 0x4b, 0x5e, 0xb0, 0xf0, 
+    0xbc, 0xb5, 0x78, 0xf1, 0x5e, 0x40, 0x0f, 0x4c, 0x54, 0x7c, 0xb5, 0x5e, 0x50, 0x0b, 0x68, 0x2a, 
+    0xa5, 0xfd, 0x5e, 0x50, 0x10, 0x68, 0x04, 0xd2, 0x69, 0x80, 0x02, 0xc2, 0x69, 0xa5, 0xfd, 0x5e, 
+    0x50, 0x20, 0x68, 0x04, 0xd2, 0x61, 0x80, 0x02, 0xc2, 0x61, 0xa5, 0xfd, 0x5e, 0x50, 0x80, 0x68, 
+    0x04, 0xd2, 0x59, 0x80, 0x02, 0xc2, 0x59, 0x12, 0x42, 0xe9, 0x02, 0x62, 0x93, 0x75, 0x31, 0x91, 
+    0x12, 0x7c, 0x15, 0x09, 0xb1, 0x00, 0x14, 0x7a, 0xb1, 0x31, 0x12, 0x7c, 0x15, 0x20, 0xe0, 0x08, 
+    0xd2, 0x04, 0x7e, 0xa0, 0x80, 0x02, 0x62, 0x93, 0xd2, 0x04, 0x30, 0xe1, 0x06, 0x7e, 0xa0, 0x80, 
+    0x12, 0x62, 0x93, 0xca, 0xb8, 0x5e, 0xb0, 0x1c, 0xda, 0xb8, 0x68, 0x12, 0x7e, 0xa0, 0xc0, 0x09, 
+    0x61, 0x00, 0x00, 0x12, 0x62, 0xb6, 0x09, 0xb1, 0x00, 0x14, 0x20, 0xe0, 0xdb, 0x22, 0x02, 0x4b, 
+    0x8d, 0x75, 0x31, 0x95, 0x12, 0x7c, 0x15, 0x22, 0x75, 0x31, 0x96, 0x12, 0x7c, 0x15, 0x22, 0x10, 
+    0x0a, 0x01, 0x22, 0x20, 0x2a, 0x03, 0xd2, 0x0a, 0x22, 0x75, 0x31, 0xa2, 0x12, 0x7c, 0x15, 0x7e, 
+    0x14, 0x82, 0x00, 0x80, 0x06, 0x20, 0x2a, 0x03, 0xd2, 0x0a, 0x22, 0x09, 0xb1, 0x00, 0x14, 0xca, 
+    0xb8, 0x5e, 0xb0, 0x1e, 0xda, 0xb8, 0x68, 0x03, 0x12, 0x4f, 0xe0, 0x20, 0xe6, 0x03, 0xd2, 0x0a, 
+    0x22, 0x30, 0x32, 0x49, 0xd2, 0x72, 0x7e, 0x37, 0x01, 0x93, 0x7e, 0x27, 0x01, 0xb3, 0x9d, 0x32, 
+    0x40, 0x31, 0x7d, 0x02, 0x2e, 0x05, 0x4c, 0x7a, 0x05, 0x4c, 0x7a, 0x37, 0x01, 0x93, 0x7e, 0x37, 
+    0x01, 0x73, 0x7d, 0x43, 0x2d, 0x42, 0xbe, 0x44, 0x15, 0xe2, 0x38, 0x68, 0x7a, 0x47, 0x01, 0x73, 
+    0x75, 0x31, 0x94, 0x12, 0x7c, 0x15, 0x7a, 0x51, 0x31, 0x12, 0x7c, 0x15, 0x12, 0x65, 0x2b, 0x10, 
+    0x72, 0xc4, 0x22, 0xc2, 0x72, 0x2d, 0x23, 0x68, 0x78, 0x6d, 0x33, 0x80, 0x1a, 0x7e, 0x27, 0x01, 
+    0x93, 0xbe, 0x24, 0x00, 0x00, 0x68, 0x6a, 0xbe, 0x27, 0x01, 0xb3, 0x28, 0x04, 0x7e, 0x27, 0x01, 
+    0xb3, 0x7e, 0x37, 0x01, 0x93, 0x9d, 0x32, 0x7d, 0x02, 0x2e, 0x05, 0x4c, 0x7a, 0x05, 0x4c, 0x7a, 
+    0x37, 0x01, 0x93, 0x7e, 0x37, 0x01, 0x73, 0x7d, 0x43, 0x2d, 0x42, 0xbe, 0x44, 0x15, 0xe2, 0x38, 
+    0x13, 0x7a, 0x47, 0x01, 0x73, 0x75, 0x31, 0x94, 0x12, 0x7c, 0x15, 0x7a, 0x51, 0x31, 0x12, 0x7c, 
+    0x15, 0x02, 0x65, 0x2b, 0x75, 0x31, 0x94, 0x12, 0x7c, 0x15, 0x7a, 0x51, 0x31, 0x12, 0x7c, 0x15, 
+    0x9e, 0x44, 0x15, 0xe3, 0x9d, 0x24, 0x12, 0x65, 0x2b, 0x7e, 0x34, 0x11, 0xe3, 0x7d, 0x24, 0x2d, 
+    0x43, 0x7a, 0x47, 0x01, 0x73, 0x12, 0x65, 0x2b, 0xbe, 0x25, 0x20, 0x78, 0x03, 0x02, 0x4d, 0x2f, 
+    0x22, 0xd2, 0x0a, 0x7e, 0x04, 0x11, 0xe3, 0x7a, 0x07, 0x01, 0x73, 0x7a, 0x07, 0x01, 0x83, 0x75, 
+    0x31, 0x94, 0x12, 0x7c, 0x15, 0x75, 0x31, 0x00, 0x12, 0x7c, 0x15, 0x22, 0x75, 0x31, 0x92, 0x12, 
+    0x7c, 0x15, 0xd2, 0x04, 0x09, 0xb1, 0x00, 0x14, 0xca, 0xb8, 0x54, 0x82, 0xda, 0xb8, 0x78, 0x70, 
+    0x7e, 0x37, 0x01, 0xe1, 0x7e, 0x27, 0x01, 0xc3, 0x2e, 0x24, 0x00, 0x02, 0x2d, 0x32, 0xbe, 0x34, 
+    0x04, 0x00, 0x38, 0x3c, 0x7d, 0x02, 0x2e, 0x05, 0x46, 0x7a, 0x05, 0x46, 0x7a, 0x37, 0x01, 0xe1, 
+    0x7e, 0x37, 0x01, 0xdf, 0x7d, 0x43, 0x2d, 0x42, 0xbe, 0x44, 0x05, 0xe2, 0x38, 0x44, 0x7a, 0x47, 
+    0x01, 0xdf, 0x7e, 0x24, 0x02, 0x00, 0x2e, 0x27, 0x01, 0xc3, 0x1b, 0x38, 0x20, 0x0b, 0x35, 0x7a, 
+    0x51, 0x31, 0x12, 0x7c, 0x15, 0xbe, 0x50, 0x38, 0x78, 0x03, 0x02, 0x66, 0x16, 0x02, 0x65, 0xfb, 
+    0x75, 0x31, 0x99, 0x12, 0x7c, 0x15, 0x09, 0xb1, 0x00, 0x04, 0x54, 0xfa, 0x19, 0xb1, 0x00, 0x04, 
+    0x30, 0x3a, 0x0a, 0x09, 0xb1, 0x00, 0x10, 0x54, 0xfe, 0x19, 0xb1, 0x00, 0x10, 0xd2, 0x12, 0x22, 
+    0x80, 0x7d, 0x7a, 0x51, 0x31, 0x12, 0x7c, 0x15, 0x9e, 0x44, 0x05, 0xe3, 0x9d, 0x24, 0x7e, 0x64, 
+    0x02, 0x00, 0x2e, 0x67, 0x01, 0xc3, 0x9e, 0x24, 0x00, 0x02, 0x40, 0x17, 0x1b, 0x38, 0x60, 0x0b, 
+    0x35, 0x12, 0x65, 0xfb, 0x7e, 0x34, 0x01, 0xe3, 0x7d, 0x24, 0x2d, 0x43, 0x7a, 0x47, 0x01, 0xdf, 
+    0x02, 0x65, 0xfb, 0x7a, 0x39, 0xc0, 0x7e, 0x34, 0x01, 0xe3, 0x7a, 0x39, 0xd0, 0x0b, 0x34, 0x1b, 
+    0x44, 0x80, 0xe5, 0x9d, 0x32, 0x7c, 0xb6, 0x54, 0x0f, 0x23, 0x23, 0x23, 0x44, 0x02, 0x7a, 0x69, 
+    0xb0, 0x7a, 0x79, 0x70, 0x0b, 0x35, 0x75, 0x31, 0x93, 0x12, 0x7c, 0x15, 0x7a, 0x71, 0x31, 0x12, 
+    0x7c, 0x15, 0xbd, 0x04, 0x68, 0x29, 0x7a, 0x07, 0x01, 0xdf, 0x7e, 0x47, 0x01, 0xe1, 0x2d, 0x43, 
+    0x7a, 0x47, 0x01, 0xe1, 0x2e, 0x35, 0x46, 0x7a, 0x35, 0x46, 0x22, 0x09, 0xb1, 0x00, 0x14, 0x20, 
+    0xe0, 0x13, 0x22, 0x7e, 0x04, 0x01, 0xe3, 0x80, 0x2a, 0x7e, 0x04, 0x01, 0xe3, 0x80, 0x2c, 0x7e, 
+    0x04, 0x01, 0xe3, 0x80, 0xd1, 0xd2, 0x04, 0x7e, 0x07, 0x01, 0xe1, 0x7e, 0x24, 0x03, 0xfe, 0x9d, 
+    0x20, 0x28, 0x40, 0x7e, 0x07, 0x01, 0xdf, 0x7e, 0x44, 0x05, 0xe3, 0x7d, 0x60, 0x0b, 0x04, 0xbd, 
+    0x04, 0x68, 0xd0, 0x7d, 0x70, 0x0b, 0x04, 0xbd, 0x04, 0x68, 0xce, 0x7d, 0x54, 0x9d, 0x50, 0xbd, 
+    0x25, 0x40, 0x02, 0x7d, 0x25, 0x7d, 0x32, 0x09, 0xb1, 0x00, 0x14, 0xca, 0xb8, 0x54, 0x1f, 0xb4, 
+    0x01, 0x31, 0xda, 0xb8, 0x7e, 0x19, 0xb0, 0x7a, 0x09, 0xb0, 0x0b, 0x04, 0x1b, 0x24, 0x78, 0xe7, 
+    0x02, 0x4e, 0x93, 0x75, 0x31, 0x99, 0x12, 0x7c, 0x15, 0x09, 0xb1, 0x00, 0x04, 0x54, 0xfa, 0x19, 
+    0xb1, 0x00, 0x04, 0x30, 0x3a, 0x0a, 0x09, 0xb1, 0x00, 0x10, 0x54, 0xfe, 0x19, 0xb1, 0x00, 0x10, 
+    0xd2, 0x12, 0x22, 0xda, 0xb8, 0x30, 0xe0, 0xd8, 0xbd, 0x32, 0x68, 0x07, 0xca, 0xb8, 0x12, 0x4e, 
+    0x93, 0xda, 0xb8, 0x02, 0x4f, 0xe0, 0x09, 0xb1, 0x00, 0x18, 0x7e, 0xa0, 0x88, 0x75, 0x31, 0x90, 
+    0x12, 0x7c, 0x15, 0xf5, 0x31, 0x12, 0x7c, 0x15, 0xa5, 0xfc, 0x5e, 0xb0, 0xf0, 0xa5, 0xfd, 0x09, 
+    0xb1, 0x00, 0x18, 0x4c, 0x4b, 0x5e, 0xb0, 0xf0, 0xbc, 0xb5, 0x78, 0xf1, 0x5e, 0x40, 0x0f, 0x4c, 
+    0x54, 0x7c, 0xb5, 0x5e, 0x50, 0x0b, 0x68, 0x2a, 0xa5, 0xfd, 0x5e, 0x50, 0x10, 0x68, 0x04, 0xd2, 
+    0x6a, 0x80, 0x02, 0xc2, 0x6a, 0xa5, 0xfd, 0x5e, 0x50, 0x20, 0x68, 0x04, 0xd2, 0x62, 0x80, 0x02, 
+    0xc2, 0x62, 0xa5, 0xfd, 0x5e, 0x50, 0x80, 0x68, 0x04, 0xd2, 0x5a, 0x80, 0x02, 0xc2, 0x5a, 0x12, 
+    0x43, 0x0a, 0x02, 0x62, 0x93, 0x75, 0x31, 0x91, 0x12, 0x7c, 0x15, 0x09, 0xb1, 0x00, 0x14, 0x7a, 
+    0xb1, 0x31, 0x12, 0x7c, 0x15, 0x20, 0xe0, 0x08, 0xd2, 0x04, 0x7e, 0xa0, 0x80, 0x02, 0x62, 0x93, 
+    0xd2, 0x04, 0x30, 0xe1, 0x06, 0x7e, 0xa0, 0x80, 0x12, 0x62, 0x93, 0xca, 0xb8, 0x5e, 0xb0, 0x1c, 
+    0xda, 0xb8, 0x68, 0x12, 0x7e, 0xa0, 0xc0, 0x09, 0x61, 0x00, 0x00, 0x12, 0x62, 0xb6, 0x09, 0xb1, 
+    0x00, 0x14, 0x20, 0xe0, 0xdb, 0x22, 0x02, 0x4e, 0xe5, 0x75, 0x31, 0x95, 0x12, 0x7c, 0x15, 0x22, 
+    0x75, 0x31, 0x96, 0x12, 0x7c, 0x15, 0x22, 0x10, 0x0b, 0x01, 0x22, 0x20, 0x2b, 0x03, 0xd2, 0x0b, 
+    0x22, 0x75, 0x31, 0xa3, 0x12, 0x7c, 0x15, 0x7e, 0x14, 0x83, 0x00, 0x80, 0x06, 0x20, 0x2b, 0x03, 
     0xd2, 0x0b, 0x22, 0x09, 0xb1, 0x00, 0x14, 0xca, 0xb8, 0x5e, 0xb0, 0x1e, 0xda, 0xb8, 0x68, 0x03, 
-    0x12, 0x57, 0x35, 0x30, 0x33, 0x06, 0x20, 0xe6, 0x4f, 0xd2, 0x0b, 0x22, 0x30, 0xe6, 0x02, 0xd2, 
-    0x63, 0x7e, 0x37, 0x01, 0x7f, 0x7e, 0x27, 0x01, 0x9f, 0x9d, 0x32, 0x40, 0x31, 0x7d, 0x02, 0x2e, 
-    0x05, 0x38, 0x7a, 0x05, 0x38, 0x7a, 0x37, 0x01, 0x7f, 0x7e, 0x37, 0x01, 0x5f, 0x7d, 0x43, 0x2d, 
-    0x42, 0xbe, 0x44, 0x19, 0xcc, 0x38, 0x68, 0x7a, 0x47, 0x01, 0x5f, 0x75, 0x2f, 0x94, 0x12, 0x7e, 
-    0x30, 0x7a, 0x51, 0x2f, 0x12, 0x7e, 0x30, 0x12, 0x68, 0x34, 0x10, 0x63, 0xc4, 0x22, 0xc2, 0x63, 
-    0x2d, 0x23, 0x68, 0x78, 0x6d, 0x33, 0x80, 0x1a, 0x7e, 0x27, 0x01, 0x7f, 0xbe, 0x24, 0x00, 0x00, 
-    0x68, 0x6a, 0xbe, 0x27, 0x01, 0x9f, 0x28, 0x04, 0x7e, 0x27, 0x01, 0x9f, 0x7e, 0x37, 0x01, 0x7f, 
-    0x9d, 0x32, 0x7d, 0x02, 0x2e, 0x05, 0x38, 0x7a, 0x05, 0x38, 0x7a, 0x37, 0x01, 0x7f, 0x7e, 0x37, 
-    0x01, 0x5f, 0x7d, 0x43, 0x2d, 0x42, 0xbe, 0x44, 0x19, 0xcc, 0x38, 0x13, 0x7a, 0x47, 0x01, 0x5f, 
-    0x75, 0x2f, 0x94, 0x12, 0x7e, 0x30, 0x7a, 0x51, 0x2f, 0x12, 0x7e, 0x30, 0x02, 0x68, 0x34, 0x75, 
-    0x2f, 0x94, 0x12, 0x7e, 0x30, 0x7a, 0x51, 0x2f, 0x12, 0x7e, 0x30, 0x9e, 0x44, 0x19, 0xcd, 0x9d, 
-    0x24, 0x12, 0x68, 0x34, 0x7e, 0x34, 0x15, 0xcd, 0x7d, 0x24, 0x2d, 0x43, 0x7a, 0x47, 0x01, 0x5f, 
-    0x12, 0x68, 0x34, 0xbe, 0x25, 0x20, 0x78, 0x03, 0x02, 0x54, 0xaa, 0x22, 0xd2, 0x0b, 0x7e, 0x04, 
-    0x15, 0xcd, 0x7a, 0x07, 0x01, 0x5f, 0x7a, 0x07, 0x01, 0x6f, 0x75, 0x2f, 0x94, 0x12, 0x7e, 0x30, 
-    0x75, 0x2f, 0x00, 0x12, 0x7e, 0x30, 0x22, 0x75, 0x2f, 0x92, 0x12, 0x7e, 0x30, 0xd2, 0x04, 0x09, 
-    0xb1, 0x00, 0x14, 0xca, 0xb8, 0x54, 0x82, 0xda, 0xb8, 0x78, 0x70, 0x7e, 0x37, 0x01, 0xcb, 0x7e, 
-    0x27, 0x01, 0xaf, 0x2e, 0x24, 0x00, 0x02, 0x2d, 0x32, 0xbe, 0x34, 0x04, 0x00, 0x38, 0x3c, 0x7d, 
-    0x02, 0x2e, 0x05, 0x30, 0x7a, 0x05, 0x30, 0x7a, 0x37, 0x01, 0xcb, 0x7e, 0x37, 0x01, 0xc9, 0x7d, 
-    0x43, 0x2d, 0x42, 0xbe, 0x44, 0x05, 0xcc, 0x38, 0x44, 0x7a, 0x47, 0x01, 0xc9, 0x7e, 0x24, 0x03, 
-    0x00, 0x2e, 0x27, 0x01, 0xaf, 0x1b, 0x38, 0x20, 0x0b, 0x35, 0x7a, 0x51, 0x2f, 0x12, 0x7e, 0x30, 
-    0xbe, 0x50, 0x38, 0x78, 0x03, 0x02, 0x69, 0x1f, 0x02, 0x69, 0x04, 0x75, 0x2f, 0x99, 0x12, 0x7e, 
-    0x30, 0x09, 0xb1, 0x00, 0x04, 0x54, 0xfa, 0x19, 0xb1, 0x00, 0x04, 0x30, 0x3b, 0x0a, 0x09, 0xb1, 
-    0x00, 0x10, 0x54, 0xfe, 0x19, 0xb1, 0x00, 0x10, 0xd2, 0x13, 0x22, 0x80, 0x7f, 0x7a, 0x51, 0x2f, 
-    0x12, 0x7e, 0x30, 0x9e, 0x44, 0x05, 0xcd, 0x9d, 0x24, 0x7e, 0x64, 0x03, 0x00, 0x2e, 0x67, 0x01, 
-    0xaf, 0x9e, 0x24, 0x00, 0x02, 0x40, 0x17, 0x1b, 0x38, 0x60, 0x0b, 0x35, 0x12, 0x69, 0x04, 0x7e, 
-    0x34, 0x01, 0xcd, 0x7d, 0x24, 0x2d, 0x43, 0x7a, 0x47, 0x01, 0xc9, 0x02, 0x69, 0x04, 0x7a, 0x39, 
-    0xc0, 0x7e, 0x34, 0x01, 0xcd, 0x7a, 0x39, 0xd0, 0x0b, 0x34, 0x1b, 0x44, 0x80, 0xe5, 0x9d, 0x32, 
-    0x7c, 0xb6, 0x54, 0x0f, 0x23, 0x23, 0x23, 0x44, 0x03, 0x7a, 0x69, 0xb0, 0x7a, 0x79, 0x70, 0x0b, 
-    0x35, 0x75, 0x2f, 0x93, 0x12, 0x7e, 0x30, 0x7a, 0x71, 0x2f, 0x12, 0x7e, 0x30, 0xbd, 0x04, 0x68, 
-    0x2b, 0x7a, 0x07, 0x01, 0xc9, 0x7e, 0x47, 0x01, 0xcb, 0x2d, 0x43, 0x7a, 0x47, 0x01, 0xcb, 0x2e, 
-    0x35, 0x30, 0x7a, 0x35, 0x30, 0x22, 0xd2, 0x04, 0x09, 0xb1, 0x00, 0x14, 0x20, 0xe0, 0x13, 0x22, 
-    0x7e, 0x04, 0x01, 0xcd, 0x80, 0x28, 0x7e, 0x04, 0x01, 0xcd, 0x80, 0x2a, 0x7e, 0x04, 0x01, 0xcd, 
-    0x80, 0xcf, 0x7e, 0x07, 0x01, 0xcb, 0x7e, 0x24, 0x03, 0xfe, 0x9d, 0x20, 0x28, 0x40, 0x7e, 0x07, 
-    0x01, 0xc9, 0x7e, 0x44, 0x05, 0xcd, 0x7d, 0x60, 0x0b, 0x04, 0xbd, 0x04, 0x68, 0xd2, 0x7d, 0x70, 
-    0x0b, 0x04, 0xbd, 0x04, 0x68, 0xd0, 0x7d, 0x54, 0x9d, 0x50, 0xbd, 0x25, 0x40, 0x02, 0x7d, 0x25, 
-    0x7d, 0x32, 0x09, 0xb1, 0x00, 0x14, 0xca, 0xb8, 0x54, 0x1f, 0xb4, 0x01, 0x31, 0xda, 0xb8, 0x7e, 
-    0x19, 0xb0, 0x7a, 0x09, 0xb0, 0x0b, 0x04, 0x1b, 0x24, 0x78, 0xe7, 0x02, 0x56, 0x0e, 0x75, 0x2f, 
-    0x99, 0x12, 0x7e, 0x30, 0x09, 0xb1, 0x00, 0x04, 0x54, 0xfa, 0x19, 0xb1, 0x00, 0x04, 0x30, 0x3b, 
-    0x0a, 0x09, 0xb1, 0x00, 0x10, 0x54, 0xfe, 0x19, 0xb1, 0x00, 0x10, 0xd2, 0x13, 0x22, 0xda, 0xb8, 
-    0x30, 0xe0, 0xd8, 0xbd, 0x32, 0x68, 0x07, 0xca, 0xb8, 0x12, 0x56, 0x0e, 0xda, 0xb8, 0x02, 0x57, 
-    0x35, 0x09, 0xb1, 0x00, 0x18, 0x7e, 0xa0, 0x88, 0x75, 0x2f, 0x90, 0x12, 0x7e, 0x30, 0xf5, 0x2f, 
-    0x12, 0x7e, 0x30, 0xa5, 0xfd, 0x5e, 0x50, 0x0a, 0x68, 0x1d, 0xa5, 0xfd, 0x5e, 0x50, 0x20, 0x68, 
-    0x04, 0xd2, 0x5b, 0x80, 0x02, 0xc2, 0x5b, 0xa5, 0xfd, 0x5e, 0x50, 0x80, 0x68, 0x04, 0xd2, 0x53, 
-    0x80, 0x02, 0xc2, 0x53, 0x12, 0x42, 0xf1, 0x02, 0x65, 0x9c, 0x75, 0x2f, 0x91, 0x12, 0x7e, 0x30, 
-    0x09, 0xb1, 0x00, 0x14, 0x7a, 0xb1, 0x2f, 0x12, 0x7e, 0x30, 0x20, 0xe0, 0x08, 0xd2, 0x04, 0x7e, 
-    0xa0, 0x80, 0x02, 0x65, 0x9c, 0xd2, 0x04, 0x30, 0xe1, 0x06, 0x7e, 0xa0, 0x80, 0x12, 0x65, 0x9c, 
-    0xca, 0xb8, 0x5e, 0xb0, 0x1c, 0xda, 0xb8, 0x68, 0x12, 0x7e, 0xa0, 0xc0, 0x09, 0x61, 0x00, 0x00, 
-    0x12, 0x65, 0xbf, 0x09, 0xb1, 0x00, 0x14, 0x20, 0xe0, 0xdb, 0x22, 0x02, 0x56, 0x62, 0x75, 0x2f, 
-    0x95, 0x12, 0x7e, 0x30, 0x22, 0x75, 0x2f, 0x96, 0x12, 0x7e, 0x30, 0x22, 0x10, 0x0c, 0x01, 0x22, 
-    0x20, 0x2c, 0x03, 0xd2, 0x0c, 0x22, 0x75, 0x2f, 0xa4, 0x12, 0x7e, 0x30, 0x7e, 0x14, 0x84, 0x00, 
-    0x80, 0x06, 0x20, 0x2c, 0x03, 0xd2, 0x0c, 0x22, 0x09, 0xb1, 0x00, 0x14, 0xca, 0xb8, 0x5e, 0xb0, 
-    0x1e, 0xda, 0xb8, 0x68, 0x03, 0x12, 0x5a, 0x6a, 0x30, 0x34, 0x06, 0x20, 0xe6, 0x4f, 0xd2, 0x0c, 
-    0x22, 0x30, 0xe6, 0x02, 0xd2, 0x64, 0x7e, 0x37, 0x01, 0x81, 0x7e, 0x27, 0x01, 0xa1, 0x9d, 0x32, 
-    0x40, 0x31, 0x7d, 0x02, 0x2e, 0x05, 0x3a, 0x7a, 0x05, 0x3a, 0x7a, 0x37, 0x01, 0x81, 0x7e, 0x37, 
-    0x01, 0x61, 0x7d, 0x43, 0x2d, 0x42, 0xbe, 0x44, 0x1d, 0xcc, 0x38, 0x68, 0x7a, 0x47, 0x01, 0x61, 
-    0x75, 0x2f, 0x94, 0x12, 0x7e, 0x30, 0x7a, 0x51, 0x2f, 0x12, 0x7e, 0x30, 0x12, 0x68, 0x34, 0x10, 
-    0x64, 0xc4, 0x22, 0xc2, 0x64, 0x2d, 0x23, 0x68, 0x78, 0x6d, 0x33, 0x80, 0x1a, 0x7e, 0x27, 0x01, 
-    0x81, 0xbe, 0x24, 0x00, 0x00, 0x68, 0x6a, 0xbe, 0x27, 0x01, 0xa1, 0x28, 0x04, 0x7e, 0x27, 0x01, 
-    0xa1, 0x7e, 0x37, 0x01, 0x81, 0x9d, 0x32, 0x7d, 0x02, 0x2e, 0x05, 0x3a, 0x7a, 0x05, 0x3a, 0x7a, 
-    0x37, 0x01, 0x81, 0x7e, 0x37, 0x01, 0x61, 0x7d, 0x43, 0x2d, 0x42, 0xbe, 0x44, 0x1d, 0xcc, 0x38, 
-    0x13, 0x7a, 0x47, 0x01, 0x61, 0x75, 0x2f, 0x94, 0x12, 0x7e, 0x30, 0x7a, 0x51, 0x2f, 0x12, 0x7e, 
-    0x30, 0x02, 0x68, 0x34, 0x75, 0x2f, 0x94, 0x12, 0x7e, 0x30, 0x7a, 0x51, 0x2f, 0x12, 0x7e, 0x30, 
-    0x9e, 0x44, 0x1d, 0xcd, 0x9d, 0x24, 0x12, 0x68, 0x34, 0x7e, 0x34, 0x19, 0xcd, 0x7d, 0x24, 0x2d, 
-    0x43, 0x7a, 0x47, 0x01, 0x61, 0x12, 0x68, 0x34, 0xbe, 0x25, 0x20, 0x78, 0x03, 0x02, 0x57, 0xdf, 
-    0x22, 0xd2, 0x0c, 0x7e, 0x04, 0x19, 0xcd, 0x7a, 0x07, 0x01, 0x61, 0x7a, 0x07, 0x01, 0x71, 0x75, 
-    0x2f, 0x94, 0x12, 0x7e, 0x30, 0x75, 0x2f, 0x00, 0x12, 0x7e, 0x30, 0x22, 0x75, 0x2f, 0x92, 0x12, 
-    0x7e, 0x30, 0xd2, 0x04, 0x09, 0xb1, 0x00, 0x14, 0xca, 0xb8, 0x54, 0x82, 0xda, 0xb8, 0x78, 0x70, 
-    0x7e, 0x37, 0x01, 0xcb, 0x7e, 0x27, 0x01, 0xb1, 0x2e, 0x24, 0x00, 0x02, 0x2d, 0x32, 0xbe, 0x34, 
-    0x04, 0x00, 0x38, 0x3c, 0x7d, 0x02, 0x2e, 0x05, 0x30, 0x7a, 0x05, 0x30, 0x7a, 0x37, 0x01, 0xcb, 
-    0x7e, 0x37, 0x01, 0xc9, 0x7d, 0x43, 0x2d, 0x42, 0xbe, 0x44, 0x05, 0xcc, 0x38, 0x44, 0x7a, 0x47, 
-    0x01, 0xc9, 0x7e, 0x24, 0x04, 0x00, 0x2e, 0x27, 0x01, 0xb1, 0x1b, 0x38, 0x20, 0x0b, 0x35, 0x7a, 
-    0x51, 0x2f, 0x12, 0x7e, 0x30, 0xbe, 0x50, 0x38, 0x78, 0x03, 0x02, 0x69, 0x1f, 0x02, 0x69, 0x04, 
-    0x75, 0x2f, 0x99, 0x12, 0x7e, 0x30, 0x09, 0xb1, 0x00, 0x04, 0x54, 0xfa, 0x19, 0xb1, 0x00, 0x04, 
+    0x12, 0x53, 0x38, 0x20, 0xe6, 0x03, 0xd2, 0x0b, 0x22, 0x30, 0x33, 0x49, 0xd2, 0x73, 0x7e, 0x37, 
+    0x01, 0x95, 0x7e, 0x27, 0x01, 0xb5, 0x9d, 0x32, 0x40, 0x31, 0x7d, 0x02, 0x2e, 0x05, 0x4e, 0x7a, 
+    0x05, 0x4e, 0x7a, 0x37, 0x01, 0x95, 0x7e, 0x37, 0x01, 0x75, 0x7d, 0x43, 0x2d, 0x42, 0xbe, 0x44, 
+    0x19, 0xe2, 0x38, 0x68, 0x7a, 0x47, 0x01, 0x75, 0x75, 0x31, 0x94, 0x12, 0x7c, 0x15, 0x7a, 0x51, 
+    0x31, 0x12, 0x7c, 0x15, 0x12, 0x65, 0x2b, 0x10, 0x73, 0xc4, 0x22, 0xc2, 0x73, 0x2d, 0x23, 0x68, 
+    0x78, 0x6d, 0x33, 0x80, 0x1a, 0x7e, 0x27, 0x01, 0x95, 0xbe, 0x24, 0x00, 0x00, 0x68, 0x6a, 0xbe, 
+    0x27, 0x01, 0xb5, 0x28, 0x04, 0x7e, 0x27, 0x01, 0xb5, 0x7e, 0x37, 0x01, 0x95, 0x9d, 0x32, 0x7d, 
+    0x02, 0x2e, 0x05, 0x4e, 0x7a, 0x05, 0x4e, 0x7a, 0x37, 0x01, 0x95, 0x7e, 0x37, 0x01, 0x75, 0x7d, 
+    0x43, 0x2d, 0x42, 0xbe, 0x44, 0x19, 0xe2, 0x38, 0x13, 0x7a, 0x47, 0x01, 0x75, 0x75, 0x31, 0x94, 
+    0x12, 0x7c, 0x15, 0x7a, 0x51, 0x31, 0x12, 0x7c, 0x15, 0x02, 0x65, 0x2b, 0x75, 0x31, 0x94, 0x12, 
+    0x7c, 0x15, 0x7a, 0x51, 0x31, 0x12, 0x7c, 0x15, 0x9e, 0x44, 0x19, 0xe3, 0x9d, 0x24, 0x12, 0x65, 
+    0x2b, 0x7e, 0x34, 0x15, 0xe3, 0x7d, 0x24, 0x2d, 0x43, 0x7a, 0x47, 0x01, 0x75, 0x12, 0x65, 0x2b, 
+    0xbe, 0x25, 0x20, 0x78, 0x03, 0x02, 0x50, 0x87, 0x22, 0xd2, 0x0b, 0x7e, 0x04, 0x15, 0xe3, 0x7a, 
+    0x07, 0x01, 0x75, 0x7a, 0x07, 0x01, 0x85, 0x75, 0x31, 0x94, 0x12, 0x7c, 0x15, 0x75, 0x31, 0x00, 
+    0x12, 0x7c, 0x15, 0x22, 0x75, 0x31, 0x92, 0x12, 0x7c, 0x15, 0xd2, 0x04, 0x09, 0xb1, 0x00, 0x14, 
+    0xca, 0xb8, 0x54, 0x82, 0xda, 0xb8, 0x78, 0x70, 0x7e, 0x37, 0x01, 0xe1, 0x7e, 0x27, 0x01, 0xc5, 
+    0x2e, 0x24, 0x00, 0x02, 0x2d, 0x32, 0xbe, 0x34, 0x04, 0x00, 0x38, 0x3c, 0x7d, 0x02, 0x2e, 0x05, 
+    0x46, 0x7a, 0x05, 0x46, 0x7a, 0x37, 0x01, 0xe1, 0x7e, 0x37, 0x01, 0xdf, 0x7d, 0x43, 0x2d, 0x42, 
+    0xbe, 0x44, 0x05, 0xe2, 0x38, 0x44, 0x7a, 0x47, 0x01, 0xdf, 0x7e, 0x24, 0x03, 0x00, 0x2e, 0x27, 
+    0x01, 0xc5, 0x1b, 0x38, 0x20, 0x0b, 0x35, 0x7a, 0x51, 0x31, 0x12, 0x7c, 0x15, 0xbe, 0x50, 0x38, 
+    0x78, 0x03, 0x02, 0x66, 0x16, 0x02, 0x65, 0xfb, 0x75, 0x31, 0x99, 0x12, 0x7c, 0x15, 0x09, 0xb1, 
+    0x00, 0x04, 0x54, 0xfa, 0x19, 0xb1, 0x00, 0x04, 0x30, 0x3b, 0x0a, 0x09, 0xb1, 0x00, 0x10, 0x54, 
+    0xfe, 0x19, 0xb1, 0x00, 0x10, 0xd2, 0x13, 0x22, 0x80, 0x7d, 0x7a, 0x51, 0x31, 0x12, 0x7c, 0x15, 
+    0x9e, 0x44, 0x05, 0xe3, 0x9d, 0x24, 0x7e, 0x64, 0x03, 0x00, 0x2e, 0x67, 0x01, 0xc5, 0x9e, 0x24, 
+    0x00, 0x02, 0x40, 0x17, 0x1b, 0x38, 0x60, 0x0b, 0x35, 0x12, 0x65, 0xfb, 0x7e, 0x34, 0x01, 0xe3, 
+    0x7d, 0x24, 0x2d, 0x43, 0x7a, 0x47, 0x01, 0xdf, 0x02, 0x65, 0xfb, 0x7a, 0x39, 0xc0, 0x7e, 0x34, 
+    0x01, 0xe3, 0x7a, 0x39, 0xd0, 0x0b, 0x34, 0x1b, 0x44, 0x80, 0xe5, 0x9d, 0x32, 0x7c, 0xb6, 0x54, 
+    0x0f, 0x23, 0x23, 0x23, 0x44, 0x03, 0x7a, 0x69, 0xb0, 0x7a, 0x79, 0x70, 0x0b, 0x35, 0x75, 0x31, 
+    0x93, 0x12, 0x7c, 0x15, 0x7a, 0x71, 0x31, 0x12, 0x7c, 0x15, 0xbd, 0x04, 0x68, 0x29, 0x7a, 0x07, 
+    0x01, 0xdf, 0x7e, 0x47, 0x01, 0xe1, 0x2d, 0x43, 0x7a, 0x47, 0x01, 0xe1, 0x2e, 0x35, 0x46, 0x7a, 
+    0x35, 0x46, 0x22, 0x09, 0xb1, 0x00, 0x14, 0x20, 0xe0, 0x13, 0x22, 0x7e, 0x04, 0x01, 0xe3, 0x80, 
+    0x2a, 0x7e, 0x04, 0x01, 0xe3, 0x80, 0x2c, 0x7e, 0x04, 0x01, 0xe3, 0x80, 0xd1, 0xd2, 0x04, 0x7e, 
+    0x07, 0x01, 0xe1, 0x7e, 0x24, 0x03, 0xfe, 0x9d, 0x20, 0x28, 0x40, 0x7e, 0x07, 0x01, 0xdf, 0x7e, 
+    0x44, 0x05, 0xe3, 0x7d, 0x60, 0x0b, 0x04, 0xbd, 0x04, 0x68, 0xd0, 0x7d, 0x70, 0x0b, 0x04, 0xbd, 
+    0x04, 0x68, 0xce, 0x7d, 0x54, 0x9d, 0x50, 0xbd, 0x25, 0x40, 0x02, 0x7d, 0x25, 0x7d, 0x32, 0x09, 
+    0xb1, 0x00, 0x14, 0xca, 0xb8, 0x54, 0x1f, 0xb4, 0x01, 0x31, 0xda, 0xb8, 0x7e, 0x19, 0xb0, 0x7a, 
+    0x09, 0xb0, 0x0b, 0x04, 0x1b, 0x24, 0x78, 0xe7, 0x02, 0x51, 0xeb, 0x75, 0x31, 0x99, 0x12, 0x7c, 
+    0x15, 0x09, 0xb1, 0x00, 0x04, 0x54, 0xfa, 0x19, 0xb1, 0x00, 0x04, 0x30, 0x3b, 0x0a, 0x09, 0xb1, 
+    0x00, 0x10, 0x54, 0xfe, 0x19, 0xb1, 0x00, 0x10, 0xd2, 0x13, 0x22, 0xda, 0xb8, 0x30, 0xe0, 0xd8, 
+    0xbd, 0x32, 0x68, 0x07, 0xca, 0xb8, 0x12, 0x51, 0xeb, 0xda, 0xb8, 0x02, 0x53, 0x38, 0x09, 0xb1, 
+    0x00, 0x18, 0x7e, 0xa0, 0x88, 0x75, 0x31, 0x90, 0x12, 0x7c, 0x15, 0xf5, 0x31, 0x12, 0x7c, 0x15, 
+    0xa5, 0xfc, 0x5e, 0xb0, 0xf0, 0xa5, 0xfd, 0x09, 0xb1, 0x00, 0x18, 0x4c, 0x4b, 0x5e, 0xb0, 0xf0, 
+    0xbc, 0xb5, 0x78, 0xf1, 0x5e, 0x40, 0x0f, 0x4c, 0x54, 0x7c, 0xb5, 0x5e, 0x50, 0x0b, 0x68, 0x2a, 
+    0xa5, 0xfd, 0x5e, 0x50, 0x10, 0x68, 0x04, 0xd2, 0x6b, 0x80, 0x02, 0xc2, 0x6b, 0xa5, 0xfd, 0x5e, 
+    0x50, 0x20, 0x68, 0x04, 0xd2, 0x63, 0x80, 0x02, 0xc2, 0x63, 0xa5, 0xfd, 0x5e, 0x50, 0x80, 0x68, 
+    0x04, 0xd2, 0x5b, 0x80, 0x02, 0xc2, 0x5b, 0x12, 0x43, 0x2b, 0x02, 0x62, 0x93, 0x75, 0x31, 0x91, 
+    0x12, 0x7c, 0x15, 0x09, 0xb1, 0x00, 0x14, 0x7a, 0xb1, 0x31, 0x12, 0x7c, 0x15, 0x20, 0xe0, 0x08, 
+    0xd2, 0x04, 0x7e, 0xa0, 0x80, 0x02, 0x62, 0x93, 0xd2, 0x04, 0x30, 0xe1, 0x06, 0x7e, 0xa0, 0x80, 
+    0x12, 0x62, 0x93, 0xca, 0xb8, 0x5e, 0xb0, 0x1c, 0xda, 0xb8, 0x68, 0x12, 0x7e, 0xa0, 0xc0, 0x09, 
+    0x61, 0x00, 0x00, 0x12, 0x62, 0xb6, 0x09, 0xb1, 0x00, 0x14, 0x20, 0xe0, 0xdb, 0x22, 0x02, 0x52, 
+    0x3d, 0x75, 0x31, 0x95, 0x12, 0x7c, 0x15, 0x22, 0x75, 0x31, 0x96, 0x12, 0x7c, 0x15, 0x22, 0x10, 
+    0x0c, 0x01, 0x22, 0x20, 0x2c, 0x03, 0xd2, 0x0c, 0x22, 0x75, 0x31, 0xa4, 0x12, 0x7c, 0x15, 0x7e, 
+    0x14, 0x84, 0x00, 0x80, 0x06, 0x20, 0x2c, 0x03, 0xd2, 0x0c, 0x22, 0x09, 0xb1, 0x00, 0x14, 0xca, 
+    0xb8, 0x5e, 0xb0, 0x1e, 0xda, 0xb8, 0x68, 0x03, 0x12, 0x56, 0x90, 0x20, 0xe6, 0x03, 0xd2, 0x0c, 
+    0x22, 0x30, 0x34, 0x49, 0xd2, 0x74, 0x7e, 0x37, 0x01, 0x97, 0x7e, 0x27, 0x01, 0xb7, 0x9d, 0x32, 
+    0x40, 0x31, 0x7d, 0x02, 0x2e, 0x05, 0x50, 0x7a, 0x05, 0x50, 0x7a, 0x37, 0x01, 0x97, 0x7e, 0x37, 
+    0x01, 0x77, 0x7d, 0x43, 0x2d, 0x42, 0xbe, 0x44, 0x1d, 0xe2, 0x38, 0x68, 0x7a, 0x47, 0x01, 0x77, 
+    0x75, 0x31, 0x94, 0x12, 0x7c, 0x15, 0x7a, 0x51, 0x31, 0x12, 0x7c, 0x15, 0x12, 0x65, 0x2b, 0x10, 
+    0x74, 0xc4, 0x22, 0xc2, 0x74, 0x2d, 0x23, 0x68, 0x78, 0x6d, 0x33, 0x80, 0x1a, 0x7e, 0x27, 0x01, 
+    0x97, 0xbe, 0x24, 0x00, 0x00, 0x68, 0x6a, 0xbe, 0x27, 0x01, 0xb7, 0x28, 0x04, 0x7e, 0x27, 0x01, 
+    0xb7, 0x7e, 0x37, 0x01, 0x97, 0x9d, 0x32, 0x7d, 0x02, 0x2e, 0x05, 0x50, 0x7a, 0x05, 0x50, 0x7a, 
+    0x37, 0x01, 0x97, 0x7e, 0x37, 0x01, 0x77, 0x7d, 0x43, 0x2d, 0x42, 0xbe, 0x44, 0x1d, 0xe2, 0x38, 
+    0x13, 0x7a, 0x47, 0x01, 0x77, 0x75, 0x31, 0x94, 0x12, 0x7c, 0x15, 0x7a, 0x51, 0x31, 0x12, 0x7c, 
+    0x15, 0x02, 0x65, 0x2b, 0x75, 0x31, 0x94, 0x12, 0x7c, 0x15, 0x7a, 0x51, 0x31, 0x12, 0x7c, 0x15, 
+    0x9e, 0x44, 0x1d, 0xe3, 0x9d, 0x24, 0x12, 0x65, 0x2b, 0x7e, 0x34, 0x19, 0xe3, 0x7d, 0x24, 0x2d, 
+    0x43, 0x7a, 0x47, 0x01, 0x77, 0x12, 0x65, 0x2b, 0xbe, 0x25, 0x20, 0x78, 0x03, 0x02, 0x53, 0xdf, 
+    0x22, 0xd2, 0x0c, 0x7e, 0x04, 0x19, 0xe3, 0x7a, 0x07, 0x01, 0x77, 0x7a, 0x07, 0x01, 0x87, 0x75, 
+    0x31, 0x94, 0x12, 0x7c, 0x15, 0x75, 0x31, 0x00, 0x12, 0x7c, 0x15, 0x22, 0x75, 0x31, 0x92, 0x12, 
+    0x7c, 0x15, 0xd2, 0x04, 0x09, 0xb1, 0x00, 0x14, 0xca, 0xb8, 0x54, 0x82, 0xda, 0xb8, 0x78, 0x70, 
+    0x7e, 0x37, 0x01, 0xe1, 0x7e, 0x27, 0x01, 0xc7, 0x2e, 0x24, 0x00, 0x02, 0x2d, 0x32, 0xbe, 0x34, 
+    0x04, 0x00, 0x38, 0x3c, 0x7d, 0x02, 0x2e, 0x05, 0x46, 0x7a, 0x05, 0x46, 0x7a, 0x37, 0x01, 0xe1, 
+    0x7e, 0x37, 0x01, 0xdf, 0x7d, 0x43, 0x2d, 0x42, 0xbe, 0x44, 0x05, 0xe2, 0x38, 0x44, 0x7a, 0x47, 
+    0x01, 0xdf, 0x7e, 0x24, 0x04, 0x00, 0x2e, 0x27, 0x01, 0xc7, 0x1b, 0x38, 0x20, 0x0b, 0x35, 0x7a, 
+    0x51, 0x31, 0x12, 0x7c, 0x15, 0xbe, 0x50, 0x38, 0x78, 0x03, 0x02, 0x66, 0x16, 0x02, 0x65, 0xfb, 
+    0x75, 0x31, 0x99, 0x12, 0x7c, 0x15, 0x09, 0xb1, 0x00, 0x04, 0x54, 0xfa, 0x19, 0xb1, 0x00, 0x04, 
     0x30, 0x3c, 0x0a, 0x09, 0xb1, 0x00, 0x10, 0x54, 0xfe, 0x19, 0xb1, 0x00, 0x10, 0xd2, 0x14, 0x22, 
-    0x80, 0x7f, 0x7a, 0x51, 0x2f, 0x12, 0x7e, 0x30, 0x9e, 0x44, 0x05, 0xcd, 0x9d, 0x24, 0x7e, 0x64, 
-    0x04, 0x00, 0x2e, 0x67, 0x01, 0xb1, 0x9e, 0x24, 0x00, 0x02, 0x40, 0x17, 0x1b, 0x38, 0x60, 0x0b, 
-    0x35, 0x12, 0x69, 0x04, 0x7e, 0x34, 0x01, 0xcd, 0x7d, 0x24, 0x2d, 0x43, 0x7a, 0x47, 0x01, 0xc9, 
-    0x02, 0x69, 0x04, 0x7a, 0x39, 0xc0, 0x7e, 0x34, 0x01, 0xcd, 0x7a, 0x39, 0xd0, 0x0b, 0x34, 0x1b, 
+    0x80, 0x7d, 0x7a, 0x51, 0x31, 0x12, 0x7c, 0x15, 0x9e, 0x44, 0x05, 0xe3, 0x9d, 0x24, 0x7e, 0x64, 
+    0x04, 0x00, 0x2e, 0x67, 0x01, 0xc7, 0x9e, 0x24, 0x00, 0x02, 0x40, 0x17, 0x1b, 0x38, 0x60, 0x0b, 
+    0x35, 0x12, 0x65, 0xfb, 0x7e, 0x34, 0x01, 0xe3, 0x7d, 0x24, 0x2d, 0x43, 0x7a, 0x47, 0x01, 0xdf, 
+    0x02, 0x65, 0xfb, 0x7a, 0x39, 0xc0, 0x7e, 0x34, 0x01, 0xe3, 0x7a, 0x39, 0xd0, 0x0b, 0x34, 0x1b, 
     0x44, 0x80, 0xe5, 0x9d, 0x32, 0x7c, 0xb6, 0x54, 0x0f, 0x23, 0x23, 0x23, 0x44, 0x04, 0x7a, 0x69, 
-    0xb0, 0x7a, 0x79, 0x70, 0x0b, 0x35, 0x75, 0x2f, 0x93, 0x12, 0x7e, 0x30, 0x7a, 0x71, 0x2f, 0x12, 
-    0x7e, 0x30, 0xbd, 0x04, 0x68, 0x2b, 0x7a, 0x07, 0x01, 0xc9, 0x7e, 0x47, 0x01, 0xcb, 0x2d, 0x43, 
-    0x7a, 0x47, 0x01, 0xcb, 0x2e, 0x35, 0x30, 0x7a, 0x35, 0x30, 0x22, 0xd2, 0x04, 0x09, 0xb1, 0x00, 
-    0x14, 0x20, 0xe0, 0x13, 0x22, 0x7e, 0x04, 0x01, 0xcd, 0x80, 0x28, 0x7e, 0x04, 0x01, 0xcd, 0x80, 
-    0x2a, 0x7e, 0x04, 0x01, 0xcd, 0x80, 0xcf, 0x7e, 0x07, 0x01, 0xcb, 0x7e, 0x24, 0x03, 0xfe, 0x9d, 
-    0x20, 0x28, 0x40, 0x7e, 0x07, 0x01, 0xc9, 0x7e, 0x44, 0x05, 0xcd, 0x7d, 0x60, 0x0b, 0x04, 0xbd, 
-    0x04, 0x68, 0xd2, 0x7d, 0x70, 0x0b, 0x04, 0xbd, 0x04, 0x68, 0xd0, 0x7d, 0x54, 0x9d, 0x50, 0xbd, 
+    0xb0, 0x7a, 0x79, 0x70, 0x0b, 0x35, 0x75, 0x31, 0x93, 0x12, 0x7c, 0x15, 0x7a, 0x71, 0x31, 0x12, 
+    0x7c, 0x15, 0xbd, 0x04, 0x68, 0x29, 0x7a, 0x07, 0x01, 0xdf, 0x7e, 0x47, 0x01, 0xe1, 0x2d, 0x43, 
+    0x7a, 0x47, 0x01, 0xe1, 0x2e, 0x35, 0x46, 0x7a, 0x35, 0x46, 0x22, 0x09, 0xb1, 0x00, 0x14, 0x20, 
+    0xe0, 0x13, 0x22, 0x7e, 0x04, 0x01, 0xe3, 0x80, 0x2a, 0x7e, 0x04, 0x01, 0xe3, 0x80, 0x2c, 0x7e, 
+    0x04, 0x01, 0xe3, 0x80, 0xd1, 0xd2, 0x04, 0x7e, 0x07, 0x01, 0xe1, 0x7e, 0x24, 0x03, 0xfe, 0x9d, 
+    0x20, 0x28, 0x40, 0x7e, 0x07, 0x01, 0xdf, 0x7e, 0x44, 0x05, 0xe3, 0x7d, 0x60, 0x0b, 0x04, 0xbd, 
+    0x04, 0x68, 0xd0, 0x7d, 0x70, 0x0b, 0x04, 0xbd, 0x04, 0x68, 0xce, 0x7d, 0x54, 0x9d, 0x50, 0xbd, 
     0x25, 0x40, 0x02, 0x7d, 0x25, 0x7d, 0x32, 0x09, 0xb1, 0x00, 0x14, 0xca, 0xb8, 0x54, 0x1f, 0xb4, 
     0x01, 0x31, 0xda, 0xb8, 0x7e, 0x19, 0xb0, 0x7a, 0x09, 0xb0, 0x0b, 0x04, 0x1b, 0x24, 0x78, 0xe7, 
-    0x02, 0x59, 0x43, 0x75, 0x2f, 0x99, 0x12, 0x7e, 0x30, 0x09, 0xb1, 0x00, 0x04, 0x54, 0xfa, 0x19, 
+    0x02, 0x55, 0x43, 0x75, 0x31, 0x99, 0x12, 0x7c, 0x15, 0x09, 0xb1, 0x00, 0x04, 0x54, 0xfa, 0x19, 
     0xb1, 0x00, 0x04, 0x30, 0x3c, 0x0a, 0x09, 0xb1, 0x00, 0x10, 0x54, 0xfe, 0x19, 0xb1, 0x00, 0x10, 
-    0xd2, 0x14, 0x22, 0xda, 0xb8, 0x30, 0xe0, 0xd8, 0xbd, 0x32, 0x68, 0x07, 0xca, 0xb8, 0x12, 0x59, 
-    0x43, 0xda, 0xb8, 0x02, 0x5a, 0x6a, 0x09, 0xb1, 0x00, 0x18, 0x7e, 0xa0, 0x88, 0x75, 0x2f, 0x90, 
-    0x12, 0x7e, 0x30, 0xf5, 0x2f, 0x12, 0x7e, 0x30, 0xa5, 0xfd, 0x5e, 0x50, 0x0a, 0x68, 0x1d, 0xa5, 
-    0xfd, 0x5e, 0x50, 0x20, 0x68, 0x04, 0xd2, 0x5c, 0x80, 0x02, 0xc2, 0x5c, 0xa5, 0xfd, 0x5e, 0x50, 
-    0x80, 0x68, 0x04, 0xd2, 0x54, 0x80, 0x02, 0xc2, 0x54, 0x12, 0x43, 0x08, 0x02, 0x65, 0x9c, 0x75, 
-    0x2f, 0x91, 0x12, 0x7e, 0x30, 0x09, 0xb1, 0x00, 0x14, 0x7a, 0xb1, 0x2f, 0x12, 0x7e, 0x30, 0x20, 
-    0xe0, 0x08, 0xd2, 0x04, 0x7e, 0xa0, 0x80, 0x02, 0x65, 0x9c, 0xd2, 0x04, 0x30, 0xe1, 0x06, 0x7e, 
-    0xa0, 0x80, 0x12, 0x65, 0x9c, 0xca, 0xb8, 0x5e, 0xb0, 0x1c, 0xda, 0xb8, 0x68, 0x12, 0x7e, 0xa0, 
-    0xc0, 0x09, 0x61, 0x00, 0x00, 0x12, 0x65, 0xbf, 0x09, 0xb1, 0x00, 0x14, 0x20, 0xe0, 0xdb, 0x22, 
-    0x02, 0x59, 0x97, 0x75, 0x2f, 0x95, 0x12, 0x7e, 0x30, 0x22, 0x75, 0x2f, 0x96, 0x12, 0x7e, 0x30, 
-    0x22, 0x10, 0x0d, 0x01, 0x22, 0x20, 0x2d, 0x03, 0xd2, 0x0d, 0x22, 0x75, 0x2f, 0xa5, 0x12, 0x7e, 
-    0x30, 0x7e, 0x14, 0x85, 0x00, 0x80, 0x06, 0x20, 0x2d, 0x03, 0xd2, 0x0d, 0x22, 0x09, 0xb1, 0x00, 
-    0x14, 0xca, 0xb8, 0x5e, 0xb0, 0x1e, 0xda, 0xb8, 0x68, 0x03, 0x12, 0x5d, 0x9f, 0x30, 0x35, 0x06, 
-    0x20, 0xe6, 0x4f, 0xd2, 0x0d, 0x22, 0x30, 0xe6, 0x02, 0xd2, 0x65, 0x7e, 0x37, 0x01, 0x83, 0x7e, 
-    0x27, 0x01, 0xa3, 0x9d, 0x32, 0x40, 0x31, 0x7d, 0x02, 0x2e, 0x05, 0x3c, 0x7a, 0x05, 0x3c, 0x7a, 
-    0x37, 0x01, 0x83, 0x7e, 0x37, 0x01, 0x63, 0x7d, 0x43, 0x2d, 0x42, 0xbe, 0x44, 0x21, 0xcc, 0x38, 
-    0x68, 0x7a, 0x47, 0x01, 0x63, 0x75, 0x2f, 0x94, 0x12, 0x7e, 0x30, 0x7a, 0x51, 0x2f, 0x12, 0x7e, 
-    0x30, 0x12, 0x68, 0x34, 0x10, 0x65, 0xc4, 0x22, 0xc2, 0x65, 0x2d, 0x23, 0x68, 0x78, 0x6d, 0x33, 
-    0x80, 0x1a, 0x7e, 0x27, 0x01, 0x83, 0xbe, 0x24, 0x00, 0x00, 0x68, 0x6a, 0xbe, 0x27, 0x01, 0xa3, 
-    0x28, 0x04, 0x7e, 0x27, 0x01, 0xa3, 0x7e, 0x37, 0x01, 0x83, 0x9d, 0x32, 0x7d, 0x02, 0x2e, 0x05, 
-    0x3c, 0x7a, 0x05, 0x3c, 0x7a, 0x37, 0x01, 0x83, 0x7e, 0x37, 0x01, 0x63, 0x7d, 0x43, 0x2d, 0x42, 
-    0xbe, 0x44, 0x21, 0xcc, 0x38, 0x13, 0x7a, 0x47, 0x01, 0x63, 0x75, 0x2f, 0x94, 0x12, 0x7e, 0x30, 
-    0x7a, 0x51, 0x2f, 0x12, 0x7e, 0x30, 0x02, 0x68, 0x34, 0x75, 0x2f, 0x94, 0x12, 0x7e, 0x30, 0x7a, 
-    0x51, 0x2f, 0x12, 0x7e, 0x30, 0x9e, 0x44, 0x21, 0xcd, 0x9d, 0x24, 0x12, 0x68, 0x34, 0x7e, 0x34, 
-    0x1d, 0xcd, 0x7d, 0x24, 0x2d, 0x43, 0x7a, 0x47, 0x01, 0x63, 0x12, 0x68, 0x34, 0xbe, 0x25, 0x20, 
-    0x78, 0x03, 0x02, 0x5b, 0x14, 0x22, 0xd2, 0x0d, 0x7e, 0x04, 0x1d, 0xcd, 0x7a, 0x07, 0x01, 0x63, 
-    0x7a, 0x07, 0x01, 0x73, 0x75, 0x2f, 0x94, 0x12, 0x7e, 0x30, 0x75, 0x2f, 0x00, 0x12, 0x7e, 0x30, 
-    0x22, 0x75, 0x2f, 0x92, 0x12, 0x7e, 0x30, 0xd2, 0x04, 0x09, 0xb1, 0x00, 0x14, 0xca, 0xb8, 0x54, 
-    0x82, 0xda, 0xb8, 0x78, 0x70, 0x7e, 0x37, 0x01, 0xcb, 0x7e, 0x27, 0x01, 0xb3, 0x2e, 0x24, 0x00, 
-    0x02, 0x2d, 0x32, 0xbe, 0x34, 0x04, 0x00, 0x38, 0x3c, 0x7d, 0x02, 0x2e, 0x05, 0x30, 0x7a, 0x05, 
-    0x30, 0x7a, 0x37, 0x01, 0xcb, 0x7e, 0x37, 0x01, 0xc9, 0x7d, 0x43, 0x2d, 0x42, 0xbe, 0x44, 0x05, 
-    0xcc, 0x38, 0x44, 0x7a, 0x47, 0x01, 0xc9, 0x7e, 0x24, 0x05, 0x00, 0x2e, 0x27, 0x01, 0xb3, 0x1b, 
-    0x38, 0x20, 0x0b, 0x35, 0x7a, 0x51, 0x2f, 0x12, 0x7e, 0x30, 0xbe, 0x50, 0x38, 0x78, 0x03, 0x02, 
-    0x69, 0x1f, 0x02, 0x69, 0x04, 0x75, 0x2f, 0x99, 0x12, 0x7e, 0x30, 0x09, 0xb1, 0x00, 0x04, 0x54, 
-    0xfa, 0x19, 0xb1, 0x00, 0x04, 0x30, 0x3d, 0x0a, 0x09, 0xb1, 0x00, 0x10, 0x54, 0xfe, 0x19, 0xb1, 
-    0x00, 0x10, 0xd2, 0x15, 0x22, 0x80, 0x7f, 0x7a, 0x51, 0x2f, 0x12, 0x7e, 0x30, 0x9e, 0x44, 0x05, 
-    0xcd, 0x9d, 0x24, 0x7e, 0x64, 0x05, 0x00, 0x2e, 0x67, 0x01, 0xb3, 0x9e, 0x24, 0x00, 0x02, 0x40, 
-    0x17, 0x1b, 0x38, 0x60, 0x0b, 0x35, 0x12, 0x69, 0x04, 0x7e, 0x34, 0x01, 0xcd, 0x7d, 0x24, 0x2d, 
-    0x43, 0x7a, 0x47, 0x01, 0xc9, 0x02, 0x69, 0x04, 0x7a, 0x39, 0xc0, 0x7e, 0x34, 0x01, 0xcd, 0x7a, 
-    0x39, 0xd0, 0x0b, 0x34, 0x1b, 0x44, 0x80, 0xe5, 0x9d, 0x32, 0x7c, 0xb6, 0x54, 0x0f, 0x23, 0x23, 
-    0x23, 0x44, 0x05, 0x7a, 0x69, 0xb0, 0x7a, 0x79, 0x70, 0x0b, 0x35, 0x75, 0x2f, 0x93, 0x12, 0x7e, 
-    0x30, 0x7a, 0x71, 0x2f, 0x12, 0x7e, 0x30, 0xbd, 0x04, 0x68, 0x2b, 0x7a, 0x07, 0x01, 0xc9, 0x7e, 
-    0x47, 0x01, 0xcb, 0x2d, 0x43, 0x7a, 0x47, 0x01, 0xcb, 0x2e, 0x35, 0x30, 0x7a, 0x35, 0x30, 0x22, 
-    0xd2, 0x04, 0x09, 0xb1, 0x00, 0x14, 0x20, 0xe0, 0x13, 0x22, 0x7e, 0x04, 0x01, 0xcd, 0x80, 0x28, 
-    0x7e, 0x04, 0x01, 0xcd, 0x80, 0x2a, 0x7e, 0x04, 0x01, 0xcd, 0x80, 0xcf, 0x7e, 0x07, 0x01, 0xcb, 
-    0x7e, 0x24, 0x03, 0xfe, 0x9d, 0x20, 0x28, 0x40, 0x7e, 0x07, 0x01, 0xc9, 0x7e, 0x44, 0x05, 0xcd, 
-    0x7d, 0x60, 0x0b, 0x04, 0xbd, 0x04, 0x68, 0xd2, 0x7d, 0x70, 0x0b, 0x04, 0xbd, 0x04, 0x68, 0xd0, 
-    0x7d, 0x54, 0x9d, 0x50, 0xbd, 0x25, 0x40, 0x02, 0x7d, 0x25, 0x7d, 0x32, 0x09, 0xb1, 0x00, 0x14, 
-    0xca, 0xb8, 0x54, 0x1f, 0xb4, 0x01, 0x31, 0xda, 0xb8, 0x7e, 0x19, 0xb0, 0x7a, 0x09, 0xb0, 0x0b, 
-    0x04, 0x1b, 0x24, 0x78, 0xe7, 0x02, 0x5c, 0x78, 0x75, 0x2f, 0x99, 0x12, 0x7e, 0x30, 0x09, 0xb1, 
+    0xd2, 0x14, 0x22, 0xda, 0xb8, 0x30, 0xe0, 0xd8, 0xbd, 0x32, 0x68, 0x07, 0xca, 0xb8, 0x12, 0x55, 
+    0x43, 0xda, 0xb8, 0x02, 0x56, 0x90, 0x09, 0xb1, 0x00, 0x18, 0x7e, 0xa0, 0x88, 0x75, 0x31, 0x90, 
+    0x12, 0x7c, 0x15, 0xf5, 0x31, 0x12, 0x7c, 0x15, 0xa5, 0xfc, 0x5e, 0xb0, 0xf0, 0xa5, 0xfd, 0x09, 
+    0xb1, 0x00, 0x18, 0x4c, 0x4b, 0x5e, 0xb0, 0xf0, 0xbc, 0xb5, 0x78, 0xf1, 0x5e, 0x40, 0x0f, 0x4c, 
+    0x54, 0x7c, 0xb5, 0x5e, 0x50, 0x0b, 0x68, 0x2a, 0xa5, 0xfd, 0x5e, 0x50, 0x10, 0x68, 0x04, 0xd2, 
+    0x6c, 0x80, 0x02, 0xc2, 0x6c, 0xa5, 0xfd, 0x5e, 0x50, 0x20, 0x68, 0x04, 0xd2, 0x64, 0x80, 0x02, 
+    0xc2, 0x64, 0xa5, 0xfd, 0x5e, 0x50, 0x80, 0x68, 0x04, 0xd2, 0x5c, 0x80, 0x02, 0xc2, 0x5c, 0x12, 
+    0x43, 0x4c, 0x02, 0x62, 0x93, 0x75, 0x31, 0x91, 0x12, 0x7c, 0x15, 0x09, 0xb1, 0x00, 0x14, 0x7a, 
+    0xb1, 0x31, 0x12, 0x7c, 0x15, 0x20, 0xe0, 0x08, 0xd2, 0x04, 0x7e, 0xa0, 0x80, 0x02, 0x62, 0x93, 
+    0xd2, 0x04, 0x30, 0xe1, 0x06, 0x7e, 0xa0, 0x80, 0x12, 0x62, 0x93, 0xca, 0xb8, 0x5e, 0xb0, 0x1c, 
+    0xda, 0xb8, 0x68, 0x12, 0x7e, 0xa0, 0xc0, 0x09, 0x61, 0x00, 0x00, 0x12, 0x62, 0xb6, 0x09, 0xb1, 
+    0x00, 0x14, 0x20, 0xe0, 0xdb, 0x22, 0x02, 0x55, 0x95, 0x75, 0x31, 0x95, 0x12, 0x7c, 0x15, 0x22, 
+    0x75, 0x31, 0x96, 0x12, 0x7c, 0x15, 0x22, 0x10, 0x0d, 0x01, 0x22, 0x20, 0x2d, 0x03, 0xd2, 0x0d, 
+    0x22, 0x75, 0x31, 0xa5, 0x12, 0x7c, 0x15, 0x7e, 0x14, 0x85, 0x00, 0x80, 0x06, 0x20, 0x2d, 0x03, 
+    0xd2, 0x0d, 0x22, 0x09, 0xb1, 0x00, 0x14, 0xca, 0xb8, 0x5e, 0xb0, 0x1e, 0xda, 0xb8, 0x68, 0x03, 
+    0x12, 0x59, 0xe8, 0x20, 0xe6, 0x03, 0xd2, 0x0d, 0x22, 0x30, 0x35, 0x49, 0xd2, 0x75, 0x7e, 0x37, 
+    0x01, 0x99, 0x7e, 0x27, 0x01, 0xb9, 0x9d, 0x32, 0x40, 0x31, 0x7d, 0x02, 0x2e, 0x05, 0x52, 0x7a, 
+    0x05, 0x52, 0x7a, 0x37, 0x01, 0x99, 0x7e, 0x37, 0x01, 0x79, 0x7d, 0x43, 0x2d, 0x42, 0xbe, 0x44, 
+    0x21, 0xe2, 0x38, 0x68, 0x7a, 0x47, 0x01, 0x79, 0x75, 0x31, 0x94, 0x12, 0x7c, 0x15, 0x7a, 0x51, 
+    0x31, 0x12, 0x7c, 0x15, 0x12, 0x65, 0x2b, 0x10, 0x75, 0xc4, 0x22, 0xc2, 0x75, 0x2d, 0x23, 0x68, 
+    0x78, 0x6d, 0x33, 0x80, 0x1a, 0x7e, 0x27, 0x01, 0x99, 0xbe, 0x24, 0x00, 0x00, 0x68, 0x6a, 0xbe, 
+    0x27, 0x01, 0xb9, 0x28, 0x04, 0x7e, 0x27, 0x01, 0xb9, 0x7e, 0x37, 0x01, 0x99, 0x9d, 0x32, 0x7d, 
+    0x02, 0x2e, 0x05, 0x52, 0x7a, 0x05, 0x52, 0x7a, 0x37, 0x01, 0x99, 0x7e, 0x37, 0x01, 0x79, 0x7d, 
+    0x43, 0x2d, 0x42, 0xbe, 0x44, 0x21, 0xe2, 0x38, 0x13, 0x7a, 0x47, 0x01, 0x79, 0x75, 0x31, 0x94, 
+    0x12, 0x7c, 0x15, 0x7a, 0x51, 0x31, 0x12, 0x7c, 0x15, 0x02, 0x65, 0x2b, 0x75, 0x31, 0x94, 0x12, 
+    0x7c, 0x15, 0x7a, 0x51, 0x31, 0x12, 0x7c, 0x15, 0x9e, 0x44, 0x21, 0xe3, 0x9d, 0x24, 0x12, 0x65, 
+    0x2b, 0x7e, 0x34, 0x1d, 0xe3, 0x7d, 0x24, 0x2d, 0x43, 0x7a, 0x47, 0x01, 0x79, 0x12, 0x65, 0x2b, 
+    0xbe, 0x25, 0x20, 0x78, 0x03, 0x02, 0x57, 0x37, 0x22, 0xd2, 0x0d, 0x7e, 0x04, 0x1d, 0xe3, 0x7a, 
+    0x07, 0x01, 0x79, 0x7a, 0x07, 0x01, 0x89, 0x75, 0x31, 0x94, 0x12, 0x7c, 0x15, 0x75, 0x31, 0x00, 
+    0x12, 0x7c, 0x15, 0x22, 0x75, 0x31, 0x92, 0x12, 0x7c, 0x15, 0xd2, 0x04, 0x09, 0xb1, 0x00, 0x14, 
+    0xca, 0xb8, 0x54, 0x82, 0xda, 0xb8, 0x78, 0x70, 0x7e, 0x37, 0x01, 0xe1, 0x7e, 0x27, 0x01, 0xc9, 
+    0x2e, 0x24, 0x00, 0x02, 0x2d, 0x32, 0xbe, 0x34, 0x04, 0x00, 0x38, 0x3c, 0x7d, 0x02, 0x2e, 0x05, 
+    0x46, 0x7a, 0x05, 0x46, 0x7a, 0x37, 0x01, 0xe1, 0x7e, 0x37, 0x01, 0xdf, 0x7d, 0x43, 0x2d, 0x42, 
+    0xbe, 0x44, 0x05, 0xe2, 0x38, 0x44, 0x7a, 0x47, 0x01, 0xdf, 0x7e, 0x24, 0x05, 0x00, 0x2e, 0x27, 
+    0x01, 0xc9, 0x1b, 0x38, 0x20, 0x0b, 0x35, 0x7a, 0x51, 0x31, 0x12, 0x7c, 0x15, 0xbe, 0x50, 0x38, 
+    0x78, 0x03, 0x02, 0x66, 0x16, 0x02, 0x65, 0xfb, 0x75, 0x31, 0x99, 0x12, 0x7c, 0x15, 0x09, 0xb1, 
     0x00, 0x04, 0x54, 0xfa, 0x19, 0xb1, 0x00, 0x04, 0x30, 0x3d, 0x0a, 0x09, 0xb1, 0x00, 0x10, 0x54, 
-    0xfe, 0x19, 0xb1, 0x00, 0x10, 0xd2, 0x15, 0x22, 0xda, 0xb8, 0x30, 0xe0, 0xd8, 0xbd, 0x32, 0x68, 
-    0x07, 0xca, 0xb8, 0x12, 0x5c, 0x78, 0xda, 0xb8, 0x02, 0x5d, 0x9f, 0x09, 0xb1, 0x00, 0x18, 0x7e, 
-    0xa0, 0x88, 0x75, 0x2f, 0x90, 0x12, 0x7e, 0x30, 0xf5, 0x2f, 0x12, 0x7e, 0x30, 0xa5, 0xfd, 0x5e, 
-    0x50, 0x0a, 0x68, 0x1d, 0xa5, 0xfd, 0x5e, 0x50, 0x20, 0x68, 0x04, 0xd2, 0x5d, 0x80, 0x02, 0xc2, 
-    0x5d, 0xa5, 0xfd, 0x5e, 0x50, 0x80, 0x68, 0x04, 0xd2, 0x55, 0x80, 0x02, 0xc2, 0x55, 0x12, 0x43, 
-    0x1f, 0x02, 0x65, 0x9c, 0x75, 0x2f, 0x91, 0x12, 0x7e, 0x30, 0x09, 0xb1, 0x00, 0x14, 0x7a, 0xb1, 
-    0x2f, 0x12, 0x7e, 0x30, 0x20, 0xe0, 0x08, 0xd2, 0x04, 0x7e, 0xa0, 0x80, 0x02, 0x65, 0x9c, 0xd2, 
-    0x04, 0x30, 0xe1, 0x06, 0x7e, 0xa0, 0x80, 0x12, 0x65, 0x9c, 0xca, 0xb8, 0x5e, 0xb0, 0x1c, 0xda, 
-    0xb8, 0x68, 0x12, 0x7e, 0xa0, 0xc0, 0x09, 0x61, 0x00, 0x00, 0x12, 0x65, 0xbf, 0x09, 0xb1, 0x00, 
-    0x14, 0x20, 0xe0, 0xdb, 0x22, 0x02, 0x5c, 0xcc, 0x75, 0x2f, 0x95, 0x12, 0x7e, 0x30, 0x22, 0x75, 
-    0x2f, 0x96, 0x12, 0x7e, 0x30, 0x22, 0x10, 0x0e, 0x01, 0x22, 0x20, 0x2e, 0x03, 0xd2, 0x0e, 0x22, 
-    0x75, 0x2f, 0xa6, 0x12, 0x7e, 0x30, 0x7e, 0x14, 0x86, 0x00, 0x80, 0x06, 0x20, 0x2e, 0x03, 0xd2, 
-    0x0e, 0x22, 0x09, 0xb1, 0x00, 0x14, 0xca, 0xb8, 0x5e, 0xb0, 0x1e, 0xda, 0xb8, 0x68, 0x03, 0x12, 
-    0x60, 0xd4, 0x30, 0x36, 0x06, 0x20, 0xe6, 0x4f, 0xd2, 0x0e, 0x22, 0x30, 0xe6, 0x02, 0xd2, 0x66, 
-    0x7e, 0x37, 0x01, 0x85, 0x7e, 0x27, 0x01, 0xa5, 0x9d, 0x32, 0x40, 0x31, 0x7d, 0x02, 0x2e, 0x05, 
-    0x3e, 0x7a, 0x05, 0x3e, 0x7a, 0x37, 0x01, 0x85, 0x7e, 0x37, 0x01, 0x65, 0x7d, 0x43, 0x2d, 0x42, 
-    0xbe, 0x44, 0x25, 0xcc, 0x38, 0x68, 0x7a, 0x47, 0x01, 0x65, 0x75, 0x2f, 0x94, 0x12, 0x7e, 0x30, 
-    0x7a, 0x51, 0x2f, 0x12, 0x7e, 0x30, 0x12, 0x68, 0x34, 0x10, 0x66, 0xc4, 0x22, 0xc2, 0x66, 0x2d, 
-    0x23, 0x68, 0x78, 0x6d, 0x33, 0x80, 0x1a, 0x7e, 0x27, 0x01, 0x85, 0xbe, 0x24, 0x00, 0x00, 0x68, 
-    0x6a, 0xbe, 0x27, 0x01, 0xa5, 0x28, 0x04, 0x7e, 0x27, 0x01, 0xa5, 0x7e, 0x37, 0x01, 0x85, 0x9d, 
-    0x32, 0x7d, 0x02, 0x2e, 0x05, 0x3e, 0x7a, 0x05, 0x3e, 0x7a, 0x37, 0x01, 0x85, 0x7e, 0x37, 0x01, 
-    0x65, 0x7d, 0x43, 0x2d, 0x42, 0xbe, 0x44, 0x25, 0xcc, 0x38, 0x13, 0x7a, 0x47, 0x01, 0x65, 0x75, 
-    0x2f, 0x94, 0x12, 0x7e, 0x30, 0x7a, 0x51, 0x2f, 0x12, 0x7e, 0x30, 0x02, 0x68, 0x34, 0x75, 0x2f, 
-    0x94, 0x12, 0x7e, 0x30, 0x7a, 0x51, 0x2f, 0x12, 0x7e, 0x30, 0x9e, 0x44, 0x25, 0xcd, 0x9d, 0x24, 
-    0x12, 0x68, 0x34, 0x7e, 0x34, 0x21, 0xcd, 0x7d, 0x24, 0x2d, 0x43, 0x7a, 0x47, 0x01, 0x65, 0x12, 
-    0x68, 0x34, 0xbe, 0x25, 0x20, 0x78, 0x03, 0x02, 0x5e, 0x49, 0x22, 0xd2, 0x0e, 0x7e, 0x04, 0x21, 
-    0xcd, 0x7a, 0x07, 0x01, 0x65, 0x7a, 0x07, 0x01, 0x75, 0x75, 0x2f, 0x94, 0x12, 0x7e, 0x30, 0x75, 
-    0x2f, 0x00, 0x12, 0x7e, 0x30, 0x22, 0x75, 0x2f, 0x92, 0x12, 0x7e, 0x30, 0xd2, 0x04, 0x09, 0xb1, 
-    0x00, 0x14, 0xca, 0xb8, 0x54, 0x82, 0xda, 0xb8, 0x78, 0x70, 0x7e, 0x37, 0x01, 0xcb, 0x7e, 0x27, 
-    0x01, 0xb5, 0x2e, 0x24, 0x00, 0x02, 0x2d, 0x32, 0xbe, 0x34, 0x04, 0x00, 0x38, 0x3c, 0x7d, 0x02, 
-    0x2e, 0x05, 0x30, 0x7a, 0x05, 0x30, 0x7a, 0x37, 0x01, 0xcb, 0x7e, 0x37, 0x01, 0xc9, 0x7d, 0x43, 
-    0x2d, 0x42, 0xbe, 0x44, 0x05, 0xcc, 0x38, 0x44, 0x7a, 0x47, 0x01, 0xc9, 0x7e, 0x24, 0x06, 0x00, 
-    0x2e, 0x27, 0x01, 0xb5, 0x1b, 0x38, 0x20, 0x0b, 0x35, 0x7a, 0x51, 0x2f, 0x12, 0x7e, 0x30, 0xbe, 
-    0x50, 0x38, 0x78, 0x03, 0x02, 0x69, 0x1f, 0x02, 0x69, 0x04, 0x75, 0x2f, 0x99, 0x12, 0x7e, 0x30, 
-    0x09, 0xb1, 0x00, 0x04, 0x54, 0xfa, 0x19, 0xb1, 0x00, 0x04, 0x30, 0x3e, 0x0a, 0x09, 0xb1, 0x00, 
-    0x10, 0x54, 0xfe, 0x19, 0xb1, 0x00, 0x10, 0xd2, 0x16, 0x22, 0x80, 0x7f, 0x7a, 0x51, 0x2f, 0x12, 
-    0x7e, 0x30, 0x9e, 0x44, 0x05, 0xcd, 0x9d, 0x24, 0x7e, 0x64, 0x06, 0x00, 0x2e, 0x67, 0x01, 0xb5, 
-    0x9e, 0x24, 0x00, 0x02, 0x40, 0x17, 0x1b, 0x38, 0x60, 0x0b, 0x35, 0x12, 0x69, 0x04, 0x7e, 0x34, 
-    0x01, 0xcd, 0x7d, 0x24, 0x2d, 0x43, 0x7a, 0x47, 0x01, 0xc9, 0x02, 0x69, 0x04, 0x7a, 0x39, 0xc0, 
-    0x7e, 0x34, 0x01, 0xcd, 0x7a, 0x39, 0xd0, 0x0b, 0x34, 0x1b, 0x44, 0x80, 0xe5, 0x9d, 0x32, 0x7c, 
-    0xb6, 0x54, 0x0f, 0x23, 0x23, 0x23, 0x44, 0x06, 0x7a, 0x69, 0xb0, 0x7a, 0x79, 0x70, 0x0b, 0x35, 
-    0x75, 0x2f, 0x93, 0x12, 0x7e, 0x30, 0x7a, 0x71, 0x2f, 0x12, 0x7e, 0x30, 0xbd, 0x04, 0x68, 0x2b, 
-    0x7a, 0x07, 0x01, 0xc9, 0x7e, 0x47, 0x01, 0xcb, 0x2d, 0x43, 0x7a, 0x47, 0x01, 0xcb, 0x2e, 0x35, 
-    0x30, 0x7a, 0x35, 0x30, 0x22, 0xd2, 0x04, 0x09, 0xb1, 0x00, 0x14, 0x20, 0xe0, 0x13, 0x22, 0x7e, 
-    0x04, 0x01, 0xcd, 0x80, 0x28, 0x7e, 0x04, 0x01, 0xcd, 0x80, 0x2a, 0x7e, 0x04, 0x01, 0xcd, 0x80, 
-    0xcf, 0x7e, 0x07, 0x01, 0xcb, 0x7e, 0x24, 0x03, 0xfe, 0x9d, 0x20, 0x28, 0x40, 0x7e, 0x07, 0x01, 
-    0xc9, 0x7e, 0x44, 0x05, 0xcd, 0x7d, 0x60, 0x0b, 0x04, 0xbd, 0x04, 0x68, 0xd2, 0x7d, 0x70, 0x0b, 
-    0x04, 0xbd, 0x04, 0x68, 0xd0, 0x7d, 0x54, 0x9d, 0x50, 0xbd, 0x25, 0x40, 0x02, 0x7d, 0x25, 0x7d, 
-    0x32, 0x09, 0xb1, 0x00, 0x14, 0xca, 0xb8, 0x54, 0x1f, 0xb4, 0x01, 0x31, 0xda, 0xb8, 0x7e, 0x19, 
-    0xb0, 0x7a, 0x09, 0xb0, 0x0b, 0x04, 0x1b, 0x24, 0x78, 0xe7, 0x02, 0x5f, 0xad, 0x75, 0x2f, 0x99, 
-    0x12, 0x7e, 0x30, 0x09, 0xb1, 0x00, 0x04, 0x54, 0xfa, 0x19, 0xb1, 0x00, 0x04, 0x30, 0x3e, 0x0a, 
-    0x09, 0xb1, 0x00, 0x10, 0x54, 0xfe, 0x19, 0xb1, 0x00, 0x10, 0xd2, 0x16, 0x22, 0xda, 0xb8, 0x30, 
-    0xe0, 0xd8, 0xbd, 0x32, 0x68, 0x07, 0xca, 0xb8, 0x12, 0x5f, 0xad, 0xda, 0xb8, 0x02, 0x60, 0xd4, 
-    0x09, 0xb1, 0x00, 0x18, 0x7e, 0xa0, 0x88, 0x75, 0x2f, 0x90, 0x12, 0x7e, 0x30, 0xf5, 0x2f, 0x12, 
-    0x7e, 0x30, 0xa5, 0xfd, 0x5e, 0x50, 0x0a, 0x68, 0x1d, 0xa5, 0xfd, 0x5e, 0x50, 0x20, 0x68, 0x04, 
-    0xd2, 0x5e, 0x80, 0x02, 0xc2, 0x5e, 0xa5, 0xfd, 0x5e, 0x50, 0x80, 0x68, 0x04, 0xd2, 0x56, 0x80, 
-    0x02, 0xc2, 0x56, 0x12, 0x43, 0x36, 0x02, 0x65, 0x9c, 0x75, 0x2f, 0x91, 0x12, 0x7e, 0x30, 0x09, 
-    0xb1, 0x00, 0x14, 0x7a, 0xb1, 0x2f, 0x12, 0x7e, 0x30, 0x20, 0xe0, 0x08, 0xd2, 0x04, 0x7e, 0xa0, 
-    0x80, 0x02, 0x65, 0x9c, 0xd2, 0x04, 0x30, 0xe1, 0x06, 0x7e, 0xa0, 0x80, 0x12, 0x65, 0x9c, 0xca, 
-    0xb8, 0x5e, 0xb0, 0x1c, 0xda, 0xb8, 0x68, 0x12, 0x7e, 0xa0, 0xc0, 0x09, 0x61, 0x00, 0x00, 0x12, 
-    0x65, 0xbf, 0x09, 0xb1, 0x00, 0x14, 0x20, 0xe0, 0xdb, 0x22, 0x02, 0x60, 0x01, 0x75, 0x2f, 0x95, 
-    0x12, 0x7e, 0x30, 0x22, 0x75, 0x2f, 0x96, 0x12, 0x7e, 0x30, 0x22, 0x10, 0x0f, 0x01, 0x22, 0x20, 
-    0x2f, 0x03, 0xd2, 0x0f, 0x22, 0x75, 0x2f, 0xa7, 0x12, 0x7e, 0x30, 0x7e, 0x14, 0x87, 0x00, 0x80, 
-    0x06, 0x20, 0x2f, 0x03, 0xd2, 0x0f, 0x22, 0x09, 0xb1, 0x00, 0x14, 0xca, 0xb8, 0x5e, 0xb0, 0x1e, 
-    0xda, 0xb8, 0x68, 0x03, 0x12, 0x64, 0x09, 0x30, 0x37, 0x06, 0x20, 0xe6, 0x4f, 0xd2, 0x0f, 0x22, 
-    0x30, 0xe6, 0x02, 0xd2, 0x67, 0x7e, 0x37, 0x01, 0x87, 0x7e, 0x27, 0x01, 0xa7, 0x9d, 0x32, 0x40, 
-    0x31, 0x7d, 0x02, 0x2e, 0x05, 0x40, 0x7a, 0x05, 0x40, 0x7a, 0x37, 0x01, 0x87, 0x7e, 0x37, 0x01, 
-    0x67, 0x7d, 0x43, 0x2d, 0x42, 0xbe, 0x44, 0x29, 0xcc, 0x38, 0x68, 0x7a, 0x47, 0x01, 0x67, 0x75, 
-    0x2f, 0x94, 0x12, 0x7e, 0x30, 0x7a, 0x51, 0x2f, 0x12, 0x7e, 0x30, 0x12, 0x68, 0x34, 0x10, 0x67, 
-    0xc4, 0x22, 0xc2, 0x67, 0x2d, 0x23, 0x68, 0x78, 0x6d, 0x33, 0x80, 0x1a, 0x7e, 0x27, 0x01, 0x87, 
-    0xbe, 0x24, 0x00, 0x00, 0x68, 0x6a, 0xbe, 0x27, 0x01, 0xa7, 0x28, 0x04, 0x7e, 0x27, 0x01, 0xa7, 
-    0x7e, 0x37, 0x01, 0x87, 0x9d, 0x32, 0x7d, 0x02, 0x2e, 0x05, 0x40, 0x7a, 0x05, 0x40, 0x7a, 0x37, 
-    0x01, 0x87, 0x7e, 0x37, 0x01, 0x67, 0x7d, 0x43, 0x2d, 0x42, 0xbe, 0x44, 0x29, 0xcc, 0x38, 0x13, 
-    0x7a, 0x47, 0x01, 0x67, 0x75, 0x2f, 0x94, 0x12, 0x7e, 0x30, 0x7a, 0x51, 0x2f, 0x12, 0x7e, 0x30, 
-    0x02, 0x68, 0x34, 0x75, 0x2f, 0x94, 0x12, 0x7e, 0x30, 0x7a, 0x51, 0x2f, 0x12, 0x7e, 0x30, 0x9e, 
-    0x44, 0x29, 0xcd, 0x9d, 0x24, 0x12, 0x68, 0x34, 0x7e, 0x34, 0x25, 0xcd, 0x7d, 0x24, 0x2d, 0x43, 
-    0x7a, 0x47, 0x01, 0x67, 0x12, 0x68, 0x34, 0xbe, 0x25, 0x20, 0x78, 0x03, 0x02, 0x61, 0x7e, 0x22, 
-    0xd2, 0x0f, 0x7e, 0x04, 0x25, 0xcd, 0x7a, 0x07, 0x01, 0x67, 0x7a, 0x07, 0x01, 0x77, 0x75, 0x2f, 
-    0x94, 0x12, 0x7e, 0x30, 0x75, 0x2f, 0x00, 0x12, 0x7e, 0x30, 0x22, 0x75, 0x2f, 0x92, 0x12, 0x7e, 
-    0x30, 0xd2, 0x04, 0x09, 0xb1, 0x00, 0x14, 0xca, 0xb8, 0x54, 0x82, 0xda, 0xb8, 0x78, 0x70, 0x7e, 
-    0x37, 0x01, 0xcb, 0x7e, 0x27, 0x01, 0xb7, 0x2e, 0x24, 0x00, 0x02, 0x2d, 0x32, 0xbe, 0x34, 0x04, 
-    0x00, 0x38, 0x3c, 0x7d, 0x02, 0x2e, 0x05, 0x30, 0x7a, 0x05, 0x30, 0x7a, 0x37, 0x01, 0xcb, 0x7e, 
-    0x37, 0x01, 0xc9, 0x7d, 0x43, 0x2d, 0x42, 0xbe, 0x44, 0x05, 0xcc, 0x38, 0x44, 0x7a, 0x47, 0x01, 
-    0xc9, 0x7e, 0x24, 0x07, 0x00, 0x2e, 0x27, 0x01, 0xb7, 0x1b, 0x38, 0x20, 0x0b, 0x35, 0x7a, 0x51, 
-    0x2f, 0x12, 0x7e, 0x30, 0xbe, 0x50, 0x38, 0x78, 0x03, 0x02, 0x69, 0x1f, 0x02, 0x69, 0x04, 0x75, 
-    0x2f, 0x99, 0x12, 0x7e, 0x30, 0x09, 0xb1, 0x00, 0x04, 0x54, 0xfa, 0x19, 0xb1, 0x00, 0x04, 0x30, 
-    0x3f, 0x0a, 0x09, 0xb1, 0x00, 0x10, 0x54, 0xfe, 0x19, 0xb1, 0x00, 0x10, 0xd2, 0x17, 0x22, 0x80, 
-    0x7f, 0x7a, 0x51, 0x2f, 0x12, 0x7e, 0x30, 0x9e, 0x44, 0x05, 0xcd, 0x9d, 0x24, 0x7e, 0x64, 0x07, 
-    0x00, 0x2e, 0x67, 0x01, 0xb7, 0x9e, 0x24, 0x00, 0x02, 0x40, 0x17, 0x1b, 0x38, 0x60, 0x0b, 0x35, 
-    0x12, 0x69, 0x04, 0x7e, 0x34, 0x01, 0xcd, 0x7d, 0x24, 0x2d, 0x43, 0x7a, 0x47, 0x01, 0xc9, 0x02, 
-    0x69, 0x04, 0x7a, 0x39, 0xc0, 0x7e, 0x34, 0x01, 0xcd, 0x7a, 0x39, 0xd0, 0x0b, 0x34, 0x1b, 0x44, 
-    0x80, 0xe5, 0x9d, 0x32, 0x7c, 0xb6, 0x54, 0x0f, 0x23, 0x23, 0x23, 0x44, 0x07, 0x7a, 0x69, 0xb0, 
-    0x7a, 0x79, 0x70, 0x0b, 0x35, 0x75, 0x2f, 0x93, 0x12, 0x7e, 0x30, 0x7a, 0x71, 0x2f, 0x12, 0x7e, 
-    0x30, 0xbd, 0x04, 0x68, 0x2b, 0x7a, 0x07, 0x01, 0xc9, 0x7e, 0x47, 0x01, 0xcb, 0x2d, 0x43, 0x7a, 
-    0x47, 0x01, 0xcb, 0x2e, 0x35, 0x30, 0x7a, 0x35, 0x30, 0x22, 0xd2, 0x04, 0x09, 0xb1, 0x00, 0x14, 
-    0x20, 0xe0, 0x13, 0x22, 0x7e, 0x04, 0x01, 0xcd, 0x80, 0x28, 0x7e, 0x04, 0x01, 0xcd, 0x80, 0x2a, 
-    0x7e, 0x04, 0x01, 0xcd, 0x80, 0xcf, 0x7e, 0x07, 0x01, 0xcb, 0x7e, 0x24, 0x03, 0xfe, 0x9d, 0x20, 
-    0x28, 0x40, 0x7e, 0x07, 0x01, 0xc9, 0x7e, 0x44, 0x05, 0xcd, 0x7d, 0x60, 0x0b, 0x04, 0xbd, 0x04, 
-    0x68, 0xd2, 0x7d, 0x70, 0x0b, 0x04, 0xbd, 0x04, 0x68, 0xd0, 0x7d, 0x54, 0x9d, 0x50, 0xbd, 0x25, 
-    0x40, 0x02, 0x7d, 0x25, 0x7d, 0x32, 0x09, 0xb1, 0x00, 0x14, 0xca, 0xb8, 0x54, 0x1f, 0xb4, 0x01, 
-    0x31, 0xda, 0xb8, 0x7e, 0x19, 0xb0, 0x7a, 0x09, 0xb0, 0x0b, 0x04, 0x1b, 0x24, 0x78, 0xe7, 0x02, 
-    0x62, 0xe2, 0x75, 0x2f, 0x99, 0x12, 0x7e, 0x30, 0x09, 0xb1, 0x00, 0x04, 0x54, 0xfa, 0x19, 0xb1, 
-    0x00, 0x04, 0x30, 0x3f, 0x0a, 0x09, 0xb1, 0x00, 0x10, 0x54, 0xfe, 0x19, 0xb1, 0x00, 0x10, 0xd2, 
-    0x17, 0x22, 0xda, 0xb8, 0x30, 0xe0, 0xd8, 0xbd, 0x32, 0x68, 0x07, 0xca, 0xb8, 0x12, 0x62, 0xe2, 
-    0xda, 0xb8, 0x02, 0x64, 0x09, 0x09, 0xb1, 0x00, 0x18, 0x7e, 0xa0, 0x88, 0x75, 0x2f, 0x90, 0x12, 
-    0x7e, 0x30, 0xf5, 0x2f, 0x12, 0x7e, 0x30, 0xa5, 0xfd, 0x5e, 0x50, 0x0a, 0x68, 0x1d, 0xa5, 0xfd, 
-    0x5e, 0x50, 0x20, 0x68, 0x04, 0xd2, 0x5f, 0x80, 0x02, 0xc2, 0x5f, 0xa5, 0xfd, 0x5e, 0x50, 0x80, 
-    0x68, 0x04, 0xd2, 0x57, 0x80, 0x02, 0xc2, 0x57, 0x12, 0x43, 0x4d, 0x02, 0x65, 0x9c, 0x75, 0x2f, 
-    0x91, 0x12, 0x7e, 0x30, 0x09, 0xb1, 0x00, 0x14, 0x7a, 0xb1, 0x2f, 0x12, 0x7e, 0x30, 0x20, 0xe0, 
-    0x08, 0xd2, 0x04, 0x7e, 0xa0, 0x80, 0x02, 0x65, 0x9c, 0xd2, 0x04, 0x30, 0xe1, 0x06, 0x7e, 0xa0, 
-    0x80, 0x12, 0x65, 0x9c, 0xca, 0xb8, 0x5e, 0xb0, 0x1c, 0xda, 0xb8, 0x68, 0x12, 0x7e, 0xa0, 0xc0, 
-    0x09, 0x61, 0x00, 0x00, 0x12, 0x65, 0xbf, 0x09, 0xb1, 0x00, 0x14, 0x20, 0xe0, 0xdb, 0x22, 0x02, 
-    0x63, 0x36, 0x75, 0x2f, 0x95, 0x12, 0x7e, 0x30, 0x22, 0x75, 0x2f, 0x96, 0x12, 0x7e, 0x30, 0x22, 
-    0x7c, 0x02, 0x7e, 0x14, 0x80, 0x00, 0x4c, 0x20, 0x09, 0xb1, 0x00, 0x18, 0xa5, 0xfd, 0x5e, 0x50, 
-    0x20, 0x68, 0x04, 0xd2, 0x58, 0x80, 0x02, 0xc2, 0x58, 0xa5, 0xfd, 0x5e, 0x50, 0x80, 0x68, 0x04, 
-    0xd2, 0x50, 0x80, 0x02, 0xc2, 0x50, 0x02, 0x65, 0x88, 0x7c, 0x02, 0x7e, 0x14, 0x80, 0x00, 0x4c, 
-    0x20, 0x09, 0xb1, 0x00, 0x18, 0xa5, 0xfd, 0x5e, 0x50, 0x20, 0x68, 0x04, 0xd2, 0x59, 0x80, 0x02, 
-    0xc2, 0x59, 0xa5, 0xfd, 0x5e, 0x50, 0x80, 0x68, 0x04, 0xd2, 0x51, 0x80, 0x02, 0xc2, 0x51, 0x02, 
-    0x65, 0x88, 0x7c, 0x02, 0x7e, 0x14, 0x80, 0x00, 0x4c, 0x20, 0x09, 0xb1, 0x00, 0x18, 0xa5, 0xfd, 
-    0x5e, 0x50, 0x20, 0x68, 0x04, 0xd2, 0x5a, 0x80, 0x02, 0xc2, 0x5a, 0xa5, 0xfd, 0x5e, 0x50, 0x80, 
-    0x68, 0x04, 0xd2, 0x52, 0x80, 0x02, 0xc2, 0x52, 0x02, 0x65, 0x88, 0x7c, 0x02, 0x7e, 0x14, 0x80, 
-    0x00, 0x4c, 0x20, 0x09, 0xb1, 0x00, 0x18, 0xa5, 0xfd, 0x5e, 0x50, 0x20, 0x68, 0x04, 0xd2, 0x5b, 
-    0x80, 0x02, 0xc2, 0x5b, 0xa5, 0xfd, 0x5e, 0x50, 0x80, 0x68, 0x04, 0xd2, 0x53, 0x80, 0x02, 0xc2, 
-    0x53, 0x02, 0x65, 0x88, 0x7c, 0x02, 0x7e, 0x14, 0x80, 0x00, 0x4c, 0x20, 0x09, 0xb1, 0x00, 0x18, 
-    0xa5, 0xfd, 0x5e, 0x50, 0x20, 0x68, 0x04, 0xd2, 0x5c, 0x80, 0x02, 0xc2, 0x5c, 0xa5, 0xfd, 0x5e, 
-    0x50, 0x80, 0x68, 0x04, 0xd2, 0x54, 0x80, 0x02, 0xc2, 0x54, 0x02, 0x65, 0x88, 0x7c, 0x02, 0x7e, 
-    0x14, 0x80, 0x00, 0x4c, 0x20, 0x09, 0xb1, 0x00, 0x18, 0xa5, 0xfd, 0x5e, 0x50, 0x20, 0x68, 0x04, 
-    0xd2, 0x5d, 0x80, 0x02, 0xc2, 0x5d, 0xa5, 0xfd, 0x5e, 0x50, 0x80, 0x68, 0x04, 0xd2, 0x55, 0x80, 
-    0x02, 0xc2, 0x55, 0x02, 0x65, 0x88, 0x7c, 0x02, 0x7e, 0x14, 0x80, 0x00, 0x4c, 0x20, 0x09, 0xb1, 
-    0x00, 0x18, 0xa5, 0xfd, 0x5e, 0x50, 0x20, 0x68, 0x04, 0xd2, 0x5e, 0x80, 0x02, 0xc2, 0x5e, 0xa5, 
-    0xfd, 0x5e, 0x50, 0x80, 0x68, 0x04, 0xd2, 0x56, 0x80, 0x02, 0xc2, 0x56, 0x02, 0x65, 0x88, 0x7c, 
-    0x02, 0x7e, 0x14, 0x80, 0x00, 0x4c, 0x20, 0x09, 0xb1, 0x00, 0x18, 0xa5, 0xfd, 0x5e, 0x50, 0x20, 
-    0x68, 0x04, 0xd2, 0x5f, 0x80, 0x02, 0xc2, 0x5f, 0xa5, 0xfd, 0x5e, 0x50, 0x80, 0x68, 0x04, 0xd2, 
-    0x57, 0x80, 0x02, 0xc2, 0x57, 0x02, 0x65, 0x88, 0x54, 0xf0, 0xc4, 0xa5, 0xff, 0xc4, 0xa5, 0x4f, 
-    0x75, 0x2f, 0x90, 0x12, 0x7e, 0x30, 0xf5, 0x2f, 0x12, 0x7e, 0x30, 0x22, 0xca, 0x19, 0x5e, 0x20, 
-    0x07, 0x4c, 0xa2, 0x7e, 0x74, 0x29, 0xcd, 0xca, 0x79, 0x7a, 0x79, 0xa0, 0x0b, 0x74, 0x7a, 0x79, 
-    0xb0, 0x0b, 0x74, 0xda, 0x79, 0x7e, 0x30, 0x02, 0x7e, 0x64, 0x00, 0x02, 0x02, 0x65, 0xe7, 0xca, 
-    0x19, 0x5e, 0x20, 0x07, 0x4c, 0xa2, 0x7e, 0x74, 0x29, 0xcd, 0xca, 0x79, 0x7a, 0x79, 0xa0, 0x0b, 
-    0x74, 0x7a, 0x79, 0xb0, 0x0b, 0x74, 0x7a, 0x79, 0x60, 0x0b, 0x74, 0xda, 0x79, 0x7e, 0x30, 0x03, 
-    0x7e, 0x64, 0x00, 0x03, 0x02, 0x65, 0xe7, 0xd2, 0x04, 0x7e, 0x27, 0x01, 0xcb, 0x2d, 0x26, 0xbe, 
-    0x24, 0x04, 0x00, 0x38, 0x2e, 0x7e, 0x07, 0x01, 0xc9, 0x7e, 0x44, 0x05, 0xcd, 0x7e, 0x79, 0xa0, 
-    0x7a, 0x09, 0xa0, 0x0b, 0x04, 0x0b, 0x74, 0xbd, 0x04, 0x68, 0x23, 0xa5, 0xdb, 0xef, 0x7a, 0x27, 
-    0x01, 0xcb, 0x7e, 0x25, 0x30, 0x2d, 0x26, 0x7a, 0x25, 0x30, 0x7a, 0x07, 0x01, 0xc9, 0xda, 0x19, 
-    0xc2, 0xd7, 0x22, 0x75, 0x2f, 0x9a, 0x12, 0x7e, 0x30, 0xda, 0x19, 0xd2, 0xd7, 0x22, 0x7e, 0x04, 
-    0x01, 0xcd, 0x80, 0xd7, 0x4d, 0x42, 0x4a, 0xae, 0x4b, 0xa8, 0x4d, 0x7b, 0x49, 0x4f, 0x49, 0x4f, 
-    0x4c, 0xa7, 0x49, 0x4f, 0x4d, 0xbf, 0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, 
-    0x49, 0x4f, 0x49, 0x4f, 0x4d, 0xc6, 0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, 
-    0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, 
-    0x49, 0x4f, 0x49, 0x4f, 0x50, 0x77, 0x4d, 0xe3, 0x4e, 0xdd, 0x50, 0xb0, 0x49, 0x4f, 0x49, 0x4f, 
-    0x4f, 0xdc, 0x49, 0x4f, 0x50, 0xf4, 0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, 
-    0x49, 0x4f, 0x49, 0x4f, 0x50, 0xfb, 0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, 
-    0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, 
-    0x49, 0x4f, 0x49, 0x4f, 0x53, 0xac, 0x51, 0x18, 0x52, 0x12, 0x53, 0xe5, 0x49, 0x4f, 0x49, 0x4f, 
-    0x53, 0x11, 0x49, 0x4f, 0x54, 0x29, 0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, 
-    0x49, 0x4f, 0x49, 0x4f, 0x54, 0x30, 0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, 
-    0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, 
-    0x49, 0x4f, 0x49, 0x4f, 0x56, 0xe1, 0x54, 0x4d, 0x55, 0x47, 0x57, 0x1a, 0x49, 0x4f, 0x49, 0x4f, 
-    0x56, 0x46, 0x49, 0x4f, 0x57, 0x5e, 0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, 
-    0x49, 0x4f, 0x49, 0x4f, 0x57, 0x65, 0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, 
-    0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, 
-    0x49, 0x4f, 0x49, 0x4f, 0x5a, 0x16, 0x57, 0x82, 0x58, 0x7c, 0x5a, 0x4f, 0x49, 0x4f, 0x49, 0x4f, 
-    0x59, 0x7b, 0x49, 0x4f, 0x5a, 0x93, 0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, 
-    0x49, 0x4f, 0x49, 0x4f, 0x5a, 0x9a, 0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, 
-    0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, 
-    0x49, 0x4f, 0x49, 0x4f, 0x5d, 0x4b, 0x5a, 0xb7, 0x5b, 0xb1, 0x5d, 0x84, 0x49, 0x4f, 0x49, 0x4f, 
-    0x5c, 0xb0, 0x49, 0x4f, 0x5d, 0xc8, 0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, 
-    0x49, 0x4f, 0x49, 0x4f, 0x5d, 0xcf, 0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, 
-    0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, 
-    0x49, 0x4f, 0x49, 0x4f, 0x60, 0x80, 0x5d, 0xec, 0x5e, 0xe6, 0x60, 0xb9, 0x49, 0x4f, 0x49, 0x4f, 
-    0x5f, 0xe5, 0x49, 0x4f, 0x60, 0xfd, 0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, 
-    0x49, 0x4f, 0x49, 0x4f, 0x61, 0x04, 0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, 
-    0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, 
-    0x49, 0x4f, 0x49, 0x4f, 0x63, 0xb5, 0x61, 0x21, 0x62, 0x1b, 0x63, 0xee, 0x49, 0x4f, 0x49, 0x4f, 
-    0x63, 0x1a, 0x49, 0x4f, 0x64, 0x32, 0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, 
-    0x49, 0x4f, 0x49, 0x4f, 0x64, 0x39, 0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, 
-    0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, 
-    0x49, 0x4f, 0x49, 0x4f, 0xca, 0x29, 0x1e, 0x50, 0x40, 0x0d, 0x7e, 0x54, 0x0b, 0x10, 0x9c, 0xb5, 
-    0xa4, 0x2e, 0x54, 0x68, 0x51, 0x89, 0x54, 0x7e, 0x39, 0x00, 0x7a, 0x19, 0x00, 0x0b, 0x34, 0x80, 
-    0xe9, 0x0b, 0x38, 0x00, 0x7a, 0x19, 0x00, 0x7a, 0x19, 0x10, 0x0b, 0x35, 0x0b, 0x38, 0x00, 0x7a, 
-    0x19, 0x00, 0x7a, 0x19, 0x10, 0x0b, 0x35, 0x0b, 0x38, 0x00, 0x7a, 0x19, 0x00, 0x7a, 0x19, 0x10, 
-    0x0b, 0x35, 0x0b, 0x38, 0x00, 0x7a, 0x19, 0x00, 0x7a, 0x19, 0x10, 0x0b, 0x35, 0x0b, 0x38, 0x00, 
-    0x7a, 0x19, 0x00, 0x7a, 0x19, 0x10, 0x0b, 0x35, 0x0b, 0x38, 0x00, 0x7a, 0x19, 0x00, 0x7a, 0x19, 
+    0xfe, 0x19, 0xb1, 0x00, 0x10, 0xd2, 0x15, 0x22, 0x80, 0x7d, 0x7a, 0x51, 0x31, 0x12, 0x7c, 0x15, 
+    0x9e, 0x44, 0x05, 0xe3, 0x9d, 0x24, 0x7e, 0x64, 0x05, 0x00, 0x2e, 0x67, 0x01, 0xc9, 0x9e, 0x24, 
+    0x00, 0x02, 0x40, 0x17, 0x1b, 0x38, 0x60, 0x0b, 0x35, 0x12, 0x65, 0xfb, 0x7e, 0x34, 0x01, 0xe3, 
+    0x7d, 0x24, 0x2d, 0x43, 0x7a, 0x47, 0x01, 0xdf, 0x02, 0x65, 0xfb, 0x7a, 0x39, 0xc0, 0x7e, 0x34, 
+    0x01, 0xe3, 0x7a, 0x39, 0xd0, 0x0b, 0x34, 0x1b, 0x44, 0x80, 0xe5, 0x9d, 0x32, 0x7c, 0xb6, 0x54, 
+    0x0f, 0x23, 0x23, 0x23, 0x44, 0x05, 0x7a, 0x69, 0xb0, 0x7a, 0x79, 0x70, 0x0b, 0x35, 0x75, 0x31, 
+    0x93, 0x12, 0x7c, 0x15, 0x7a, 0x71, 0x31, 0x12, 0x7c, 0x15, 0xbd, 0x04, 0x68, 0x29, 0x7a, 0x07, 
+    0x01, 0xdf, 0x7e, 0x47, 0x01, 0xe1, 0x2d, 0x43, 0x7a, 0x47, 0x01, 0xe1, 0x2e, 0x35, 0x46, 0x7a, 
+    0x35, 0x46, 0x22, 0x09, 0xb1, 0x00, 0x14, 0x20, 0xe0, 0x13, 0x22, 0x7e, 0x04, 0x01, 0xe3, 0x80, 
+    0x2a, 0x7e, 0x04, 0x01, 0xe3, 0x80, 0x2c, 0x7e, 0x04, 0x01, 0xe3, 0x80, 0xd1, 0xd2, 0x04, 0x7e, 
+    0x07, 0x01, 0xe1, 0x7e, 0x24, 0x03, 0xfe, 0x9d, 0x20, 0x28, 0x40, 0x7e, 0x07, 0x01, 0xdf, 0x7e, 
+    0x44, 0x05, 0xe3, 0x7d, 0x60, 0x0b, 0x04, 0xbd, 0x04, 0x68, 0xd0, 0x7d, 0x70, 0x0b, 0x04, 0xbd, 
+    0x04, 0x68, 0xce, 0x7d, 0x54, 0x9d, 0x50, 0xbd, 0x25, 0x40, 0x02, 0x7d, 0x25, 0x7d, 0x32, 0x09, 
+    0xb1, 0x00, 0x14, 0xca, 0xb8, 0x54, 0x1f, 0xb4, 0x01, 0x31, 0xda, 0xb8, 0x7e, 0x19, 0xb0, 0x7a, 
+    0x09, 0xb0, 0x0b, 0x04, 0x1b, 0x24, 0x78, 0xe7, 0x02, 0x58, 0x9b, 0x75, 0x31, 0x99, 0x12, 0x7c, 
+    0x15, 0x09, 0xb1, 0x00, 0x04, 0x54, 0xfa, 0x19, 0xb1, 0x00, 0x04, 0x30, 0x3d, 0x0a, 0x09, 0xb1, 
+    0x00, 0x10, 0x54, 0xfe, 0x19, 0xb1, 0x00, 0x10, 0xd2, 0x15, 0x22, 0xda, 0xb8, 0x30, 0xe0, 0xd8, 
+    0xbd, 0x32, 0x68, 0x07, 0xca, 0xb8, 0x12, 0x58, 0x9b, 0xda, 0xb8, 0x02, 0x59, 0xe8, 0x09, 0xb1, 
+    0x00, 0x18, 0x7e, 0xa0, 0x88, 0x75, 0x31, 0x90, 0x12, 0x7c, 0x15, 0xf5, 0x31, 0x12, 0x7c, 0x15, 
+    0xa5, 0xfc, 0x5e, 0xb0, 0xf0, 0xa5, 0xfd, 0x09, 0xb1, 0x00, 0x18, 0x4c, 0x4b, 0x5e, 0xb0, 0xf0, 
+    0xbc, 0xb5, 0x78, 0xf1, 0x5e, 0x40, 0x0f, 0x4c, 0x54, 0x7c, 0xb5, 0x5e, 0x50, 0x0b, 0x68, 0x2a, 
+    0xa5, 0xfd, 0x5e, 0x50, 0x10, 0x68, 0x04, 0xd2, 0x6d, 0x80, 0x02, 0xc2, 0x6d, 0xa5, 0xfd, 0x5e, 
+    0x50, 0x20, 0x68, 0x04, 0xd2, 0x65, 0x80, 0x02, 0xc2, 0x65, 0xa5, 0xfd, 0x5e, 0x50, 0x80, 0x68, 
+    0x04, 0xd2, 0x5d, 0x80, 0x02, 0xc2, 0x5d, 0x12, 0x43, 0x6d, 0x02, 0x62, 0x93, 0x75, 0x31, 0x91, 
+    0x12, 0x7c, 0x15, 0x09, 0xb1, 0x00, 0x14, 0x7a, 0xb1, 0x31, 0x12, 0x7c, 0x15, 0x20, 0xe0, 0x08, 
+    0xd2, 0x04, 0x7e, 0xa0, 0x80, 0x02, 0x62, 0x93, 0xd2, 0x04, 0x30, 0xe1, 0x06, 0x7e, 0xa0, 0x80, 
+    0x12, 0x62, 0x93, 0xca, 0xb8, 0x5e, 0xb0, 0x1c, 0xda, 0xb8, 0x68, 0x12, 0x7e, 0xa0, 0xc0, 0x09, 
+    0x61, 0x00, 0x00, 0x12, 0x62, 0xb6, 0x09, 0xb1, 0x00, 0x14, 0x20, 0xe0, 0xdb, 0x22, 0x02, 0x58, 
+    0xed, 0x75, 0x31, 0x95, 0x12, 0x7c, 0x15, 0x22, 0x75, 0x31, 0x96, 0x12, 0x7c, 0x15, 0x22, 0x10, 
+    0x0e, 0x01, 0x22, 0x20, 0x2e, 0x03, 0xd2, 0x0e, 0x22, 0x75, 0x31, 0xa6, 0x12, 0x7c, 0x15, 0x7e, 
+    0x14, 0x86, 0x00, 0x80, 0x06, 0x20, 0x2e, 0x03, 0xd2, 0x0e, 0x22, 0x09, 0xb1, 0x00, 0x14, 0xca, 
+    0xb8, 0x5e, 0xb0, 0x1e, 0xda, 0xb8, 0x68, 0x03, 0x12, 0x5d, 0x40, 0x20, 0xe6, 0x03, 0xd2, 0x0e, 
+    0x22, 0x30, 0x36, 0x49, 0xd2, 0x76, 0x7e, 0x37, 0x01, 0x9b, 0x7e, 0x27, 0x01, 0xbb, 0x9d, 0x32, 
+    0x40, 0x31, 0x7d, 0x02, 0x2e, 0x05, 0x54, 0x7a, 0x05, 0x54, 0x7a, 0x37, 0x01, 0x9b, 0x7e, 0x37, 
+    0x01, 0x7b, 0x7d, 0x43, 0x2d, 0x42, 0xbe, 0x44, 0x25, 0xe2, 0x38, 0x68, 0x7a, 0x47, 0x01, 0x7b, 
+    0x75, 0x31, 0x94, 0x12, 0x7c, 0x15, 0x7a, 0x51, 0x31, 0x12, 0x7c, 0x15, 0x12, 0x65, 0x2b, 0x10, 
+    0x76, 0xc4, 0x22, 0xc2, 0x76, 0x2d, 0x23, 0x68, 0x78, 0x6d, 0x33, 0x80, 0x1a, 0x7e, 0x27, 0x01, 
+    0x9b, 0xbe, 0x24, 0x00, 0x00, 0x68, 0x6a, 0xbe, 0x27, 0x01, 0xbb, 0x28, 0x04, 0x7e, 0x27, 0x01, 
+    0xbb, 0x7e, 0x37, 0x01, 0x9b, 0x9d, 0x32, 0x7d, 0x02, 0x2e, 0x05, 0x54, 0x7a, 0x05, 0x54, 0x7a, 
+    0x37, 0x01, 0x9b, 0x7e, 0x37, 0x01, 0x7b, 0x7d, 0x43, 0x2d, 0x42, 0xbe, 0x44, 0x25, 0xe2, 0x38, 
+    0x13, 0x7a, 0x47, 0x01, 0x7b, 0x75, 0x31, 0x94, 0x12, 0x7c, 0x15, 0x7a, 0x51, 0x31, 0x12, 0x7c, 
+    0x15, 0x02, 0x65, 0x2b, 0x75, 0x31, 0x94, 0x12, 0x7c, 0x15, 0x7a, 0x51, 0x31, 0x12, 0x7c, 0x15, 
+    0x9e, 0x44, 0x25, 0xe3, 0x9d, 0x24, 0x12, 0x65, 0x2b, 0x7e, 0x34, 0x21, 0xe3, 0x7d, 0x24, 0x2d, 
+    0x43, 0x7a, 0x47, 0x01, 0x7b, 0x12, 0x65, 0x2b, 0xbe, 0x25, 0x20, 0x78, 0x03, 0x02, 0x5a, 0x8f, 
+    0x22, 0xd2, 0x0e, 0x7e, 0x04, 0x21, 0xe3, 0x7a, 0x07, 0x01, 0x7b, 0x7a, 0x07, 0x01, 0x8b, 0x75, 
+    0x31, 0x94, 0x12, 0x7c, 0x15, 0x75, 0x31, 0x00, 0x12, 0x7c, 0x15, 0x22, 0x75, 0x31, 0x92, 0x12, 
+    0x7c, 0x15, 0xd2, 0x04, 0x09, 0xb1, 0x00, 0x14, 0xca, 0xb8, 0x54, 0x82, 0xda, 0xb8, 0x78, 0x70, 
+    0x7e, 0x37, 0x01, 0xe1, 0x7e, 0x27, 0x01, 0xcb, 0x2e, 0x24, 0x00, 0x02, 0x2d, 0x32, 0xbe, 0x34, 
+    0x04, 0x00, 0x38, 0x3c, 0x7d, 0x02, 0x2e, 0x05, 0x46, 0x7a, 0x05, 0x46, 0x7a, 0x37, 0x01, 0xe1, 
+    0x7e, 0x37, 0x01, 0xdf, 0x7d, 0x43, 0x2d, 0x42, 0xbe, 0x44, 0x05, 0xe2, 0x38, 0x44, 0x7a, 0x47, 
+    0x01, 0xdf, 0x7e, 0x24, 0x06, 0x00, 0x2e, 0x27, 0x01, 0xcb, 0x1b, 0x38, 0x20, 0x0b, 0x35, 0x7a, 
+    0x51, 0x31, 0x12, 0x7c, 0x15, 0xbe, 0x50, 0x38, 0x78, 0x03, 0x02, 0x66, 0x16, 0x02, 0x65, 0xfb, 
+    0x75, 0x31, 0x99, 0x12, 0x7c, 0x15, 0x09, 0xb1, 0x00, 0x04, 0x54, 0xfa, 0x19, 0xb1, 0x00, 0x04, 
+    0x30, 0x3e, 0x0a, 0x09, 0xb1, 0x00, 0x10, 0x54, 0xfe, 0x19, 0xb1, 0x00, 0x10, 0xd2, 0x16, 0x22, 
+    0x80, 0x7d, 0x7a, 0x51, 0x31, 0x12, 0x7c, 0x15, 0x9e, 0x44, 0x05, 0xe3, 0x9d, 0x24, 0x7e, 0x64, 
+    0x06, 0x00, 0x2e, 0x67, 0x01, 0xcb, 0x9e, 0x24, 0x00, 0x02, 0x40, 0x17, 0x1b, 0x38, 0x60, 0x0b, 
+    0x35, 0x12, 0x65, 0xfb, 0x7e, 0x34, 0x01, 0xe3, 0x7d, 0x24, 0x2d, 0x43, 0x7a, 0x47, 0x01, 0xdf, 
+    0x02, 0x65, 0xfb, 0x7a, 0x39, 0xc0, 0x7e, 0x34, 0x01, 0xe3, 0x7a, 0x39, 0xd0, 0x0b, 0x34, 0x1b, 
+    0x44, 0x80, 0xe5, 0x9d, 0x32, 0x7c, 0xb6, 0x54, 0x0f, 0x23, 0x23, 0x23, 0x44, 0x06, 0x7a, 0x69, 
+    0xb0, 0x7a, 0x79, 0x70, 0x0b, 0x35, 0x75, 0x31, 0x93, 0x12, 0x7c, 0x15, 0x7a, 0x71, 0x31, 0x12, 
+    0x7c, 0x15, 0xbd, 0x04, 0x68, 0x29, 0x7a, 0x07, 0x01, 0xdf, 0x7e, 0x47, 0x01, 0xe1, 0x2d, 0x43, 
+    0x7a, 0x47, 0x01, 0xe1, 0x2e, 0x35, 0x46, 0x7a, 0x35, 0x46, 0x22, 0x09, 0xb1, 0x00, 0x14, 0x20, 
+    0xe0, 0x13, 0x22, 0x7e, 0x04, 0x01, 0xe3, 0x80, 0x2a, 0x7e, 0x04, 0x01, 0xe3, 0x80, 0x2c, 0x7e, 
+    0x04, 0x01, 0xe3, 0x80, 0xd1, 0xd2, 0x04, 0x7e, 0x07, 0x01, 0xe1, 0x7e, 0x24, 0x03, 0xfe, 0x9d, 
+    0x20, 0x28, 0x40, 0x7e, 0x07, 0x01, 0xdf, 0x7e, 0x44, 0x05, 0xe3, 0x7d, 0x60, 0x0b, 0x04, 0xbd, 
+    0x04, 0x68, 0xd0, 0x7d, 0x70, 0x0b, 0x04, 0xbd, 0x04, 0x68, 0xce, 0x7d, 0x54, 0x9d, 0x50, 0xbd, 
+    0x25, 0x40, 0x02, 0x7d, 0x25, 0x7d, 0x32, 0x09, 0xb1, 0x00, 0x14, 0xca, 0xb8, 0x54, 0x1f, 0xb4, 
+    0x01, 0x31, 0xda, 0xb8, 0x7e, 0x19, 0xb0, 0x7a, 0x09, 0xb0, 0x0b, 0x04, 0x1b, 0x24, 0x78, 0xe7, 
+    0x02, 0x5b, 0xf3, 0x75, 0x31, 0x99, 0x12, 0x7c, 0x15, 0x09, 0xb1, 0x00, 0x04, 0x54, 0xfa, 0x19, 
+    0xb1, 0x00, 0x04, 0x30, 0x3e, 0x0a, 0x09, 0xb1, 0x00, 0x10, 0x54, 0xfe, 0x19, 0xb1, 0x00, 0x10, 
+    0xd2, 0x16, 0x22, 0xda, 0xb8, 0x30, 0xe0, 0xd8, 0xbd, 0x32, 0x68, 0x07, 0xca, 0xb8, 0x12, 0x5b, 
+    0xf3, 0xda, 0xb8, 0x02, 0x5d, 0x40, 0x09, 0xb1, 0x00, 0x18, 0x7e, 0xa0, 0x88, 0x75, 0x31, 0x90, 
+    0x12, 0x7c, 0x15, 0xf5, 0x31, 0x12, 0x7c, 0x15, 0xa5, 0xfc, 0x5e, 0xb0, 0xf0, 0xa5, 0xfd, 0x09, 
+    0xb1, 0x00, 0x18, 0x4c, 0x4b, 0x5e, 0xb0, 0xf0, 0xbc, 0xb5, 0x78, 0xf1, 0x5e, 0x40, 0x0f, 0x4c, 
+    0x54, 0x7c, 0xb5, 0x5e, 0x50, 0x0b, 0x68, 0x2a, 0xa5, 0xfd, 0x5e, 0x50, 0x10, 0x68, 0x04, 0xd2, 
+    0x6e, 0x80, 0x02, 0xc2, 0x6e, 0xa5, 0xfd, 0x5e, 0x50, 0x20, 0x68, 0x04, 0xd2, 0x66, 0x80, 0x02, 
+    0xc2, 0x66, 0xa5, 0xfd, 0x5e, 0x50, 0x80, 0x68, 0x04, 0xd2, 0x5e, 0x80, 0x02, 0xc2, 0x5e, 0x12, 
+    0x43, 0x8e, 0x02, 0x62, 0x93, 0x75, 0x31, 0x91, 0x12, 0x7c, 0x15, 0x09, 0xb1, 0x00, 0x14, 0x7a, 
+    0xb1, 0x31, 0x12, 0x7c, 0x15, 0x20, 0xe0, 0x08, 0xd2, 0x04, 0x7e, 0xa0, 0x80, 0x02, 0x62, 0x93, 
+    0xd2, 0x04, 0x30, 0xe1, 0x06, 0x7e, 0xa0, 0x80, 0x12, 0x62, 0x93, 0xca, 0xb8, 0x5e, 0xb0, 0x1c, 
+    0xda, 0xb8, 0x68, 0x12, 0x7e, 0xa0, 0xc0, 0x09, 0x61, 0x00, 0x00, 0x12, 0x62, 0xb6, 0x09, 0xb1, 
+    0x00, 0x14, 0x20, 0xe0, 0xdb, 0x22, 0x02, 0x5c, 0x45, 0x75, 0x31, 0x95, 0x12, 0x7c, 0x15, 0x22, 
+    0x75, 0x31, 0x96, 0x12, 0x7c, 0x15, 0x22, 0x10, 0x0f, 0x01, 0x22, 0x20, 0x2f, 0x03, 0xd2, 0x0f, 
+    0x22, 0x75, 0x31, 0xa7, 0x12, 0x7c, 0x15, 0x7e, 0x14, 0x87, 0x00, 0x80, 0x06, 0x20, 0x2f, 0x03, 
+    0xd2, 0x0f, 0x22, 0x09, 0xb1, 0x00, 0x14, 0xca, 0xb8, 0x5e, 0xb0, 0x1e, 0xda, 0xb8, 0x68, 0x03, 
+    0x12, 0x60, 0x98, 0x20, 0xe6, 0x03, 0xd2, 0x0f, 0x22, 0x30, 0x37, 0x49, 0xd2, 0x77, 0x7e, 0x37, 
+    0x01, 0x9d, 0x7e, 0x27, 0x01, 0xbd, 0x9d, 0x32, 0x40, 0x31, 0x7d, 0x02, 0x2e, 0x05, 0x56, 0x7a, 
+    0x05, 0x56, 0x7a, 0x37, 0x01, 0x9d, 0x7e, 0x37, 0x01, 0x7d, 0x7d, 0x43, 0x2d, 0x42, 0xbe, 0x44, 
+    0x29, 0xe2, 0x38, 0x68, 0x7a, 0x47, 0x01, 0x7d, 0x75, 0x31, 0x94, 0x12, 0x7c, 0x15, 0x7a, 0x51, 
+    0x31, 0x12, 0x7c, 0x15, 0x12, 0x65, 0x2b, 0x10, 0x77, 0xc4, 0x22, 0xc2, 0x77, 0x2d, 0x23, 0x68, 
+    0x78, 0x6d, 0x33, 0x80, 0x1a, 0x7e, 0x27, 0x01, 0x9d, 0xbe, 0x24, 0x00, 0x00, 0x68, 0x6a, 0xbe, 
+    0x27, 0x01, 0xbd, 0x28, 0x04, 0x7e, 0x27, 0x01, 0xbd, 0x7e, 0x37, 0x01, 0x9d, 0x9d, 0x32, 0x7d, 
+    0x02, 0x2e, 0x05, 0x56, 0x7a, 0x05, 0x56, 0x7a, 0x37, 0x01, 0x9d, 0x7e, 0x37, 0x01, 0x7d, 0x7d, 
+    0x43, 0x2d, 0x42, 0xbe, 0x44, 0x29, 0xe2, 0x38, 0x13, 0x7a, 0x47, 0x01, 0x7d, 0x75, 0x31, 0x94, 
+    0x12, 0x7c, 0x15, 0x7a, 0x51, 0x31, 0x12, 0x7c, 0x15, 0x02, 0x65, 0x2b, 0x75, 0x31, 0x94, 0x12, 
+    0x7c, 0x15, 0x7a, 0x51, 0x31, 0x12, 0x7c, 0x15, 0x9e, 0x44, 0x29, 0xe3, 0x9d, 0x24, 0x12, 0x65, 
+    0x2b, 0x7e, 0x34, 0x25, 0xe3, 0x7d, 0x24, 0x2d, 0x43, 0x7a, 0x47, 0x01, 0x7d, 0x12, 0x65, 0x2b, 
+    0xbe, 0x25, 0x20, 0x78, 0x03, 0x02, 0x5d, 0xe7, 0x22, 0xd2, 0x0f, 0x7e, 0x04, 0x25, 0xe3, 0x7a, 
+    0x07, 0x01, 0x7d, 0x7a, 0x07, 0x01, 0x8d, 0x75, 0x31, 0x94, 0x12, 0x7c, 0x15, 0x75, 0x31, 0x00, 
+    0x12, 0x7c, 0x15, 0x22, 0x75, 0x31, 0x92, 0x12, 0x7c, 0x15, 0xd2, 0x04, 0x09, 0xb1, 0x00, 0x14, 
+    0xca, 0xb8, 0x54, 0x82, 0xda, 0xb8, 0x78, 0x70, 0x7e, 0x37, 0x01, 0xe1, 0x7e, 0x27, 0x01, 0xcd, 
+    0x2e, 0x24, 0x00, 0x02, 0x2d, 0x32, 0xbe, 0x34, 0x04, 0x00, 0x38, 0x3c, 0x7d, 0x02, 0x2e, 0x05, 
+    0x46, 0x7a, 0x05, 0x46, 0x7a, 0x37, 0x01, 0xe1, 0x7e, 0x37, 0x01, 0xdf, 0x7d, 0x43, 0x2d, 0x42, 
+    0xbe, 0x44, 0x05, 0xe2, 0x38, 0x44, 0x7a, 0x47, 0x01, 0xdf, 0x7e, 0x24, 0x07, 0x00, 0x2e, 0x27, 
+    0x01, 0xcd, 0x1b, 0x38, 0x20, 0x0b, 0x35, 0x7a, 0x51, 0x31, 0x12, 0x7c, 0x15, 0xbe, 0x50, 0x38, 
+    0x78, 0x03, 0x02, 0x66, 0x16, 0x02, 0x65, 0xfb, 0x75, 0x31, 0x99, 0x12, 0x7c, 0x15, 0x09, 0xb1, 
+    0x00, 0x04, 0x54, 0xfa, 0x19, 0xb1, 0x00, 0x04, 0x30, 0x3f, 0x0a, 0x09, 0xb1, 0x00, 0x10, 0x54, 
+    0xfe, 0x19, 0xb1, 0x00, 0x10, 0xd2, 0x17, 0x22, 0x80, 0x7d, 0x7a, 0x51, 0x31, 0x12, 0x7c, 0x15, 
+    0x9e, 0x44, 0x05, 0xe3, 0x9d, 0x24, 0x7e, 0x64, 0x07, 0x00, 0x2e, 0x67, 0x01, 0xcd, 0x9e, 0x24, 
+    0x00, 0x02, 0x40, 0x17, 0x1b, 0x38, 0x60, 0x0b, 0x35, 0x12, 0x65, 0xfb, 0x7e, 0x34, 0x01, 0xe3, 
+    0x7d, 0x24, 0x2d, 0x43, 0x7a, 0x47, 0x01, 0xdf, 0x02, 0x65, 0xfb, 0x7a, 0x39, 0xc0, 0x7e, 0x34, 
+    0x01, 0xe3, 0x7a, 0x39, 0xd0, 0x0b, 0x34, 0x1b, 0x44, 0x80, 0xe5, 0x9d, 0x32, 0x7c, 0xb6, 0x54, 
+    0x0f, 0x23, 0x23, 0x23, 0x44, 0x07, 0x7a, 0x69, 0xb0, 0x7a, 0x79, 0x70, 0x0b, 0x35, 0x75, 0x31, 
+    0x93, 0x12, 0x7c, 0x15, 0x7a, 0x71, 0x31, 0x12, 0x7c, 0x15, 0xbd, 0x04, 0x68, 0x29, 0x7a, 0x07, 
+    0x01, 0xdf, 0x7e, 0x47, 0x01, 0xe1, 0x2d, 0x43, 0x7a, 0x47, 0x01, 0xe1, 0x2e, 0x35, 0x46, 0x7a, 
+    0x35, 0x46, 0x22, 0x09, 0xb1, 0x00, 0x14, 0x20, 0xe0, 0x13, 0x22, 0x7e, 0x04, 0x01, 0xe3, 0x80, 
+    0x2a, 0x7e, 0x04, 0x01, 0xe3, 0x80, 0x2c, 0x7e, 0x04, 0x01, 0xe3, 0x80, 0xd1, 0xd2, 0x04, 0x7e, 
+    0x07, 0x01, 0xe1, 0x7e, 0x24, 0x03, 0xfe, 0x9d, 0x20, 0x28, 0x40, 0x7e, 0x07, 0x01, 0xdf, 0x7e, 
+    0x44, 0x05, 0xe3, 0x7d, 0x60, 0x0b, 0x04, 0xbd, 0x04, 0x68, 0xd0, 0x7d, 0x70, 0x0b, 0x04, 0xbd, 
+    0x04, 0x68, 0xce, 0x7d, 0x54, 0x9d, 0x50, 0xbd, 0x25, 0x40, 0x02, 0x7d, 0x25, 0x7d, 0x32, 0x09, 
+    0xb1, 0x00, 0x14, 0xca, 0xb8, 0x54, 0x1f, 0xb4, 0x01, 0x31, 0xda, 0xb8, 0x7e, 0x19, 0xb0, 0x7a, 
+    0x09, 0xb0, 0x0b, 0x04, 0x1b, 0x24, 0x78, 0xe7, 0x02, 0x5f, 0x4b, 0x75, 0x31, 0x99, 0x12, 0x7c, 
+    0x15, 0x09, 0xb1, 0x00, 0x04, 0x54, 0xfa, 0x19, 0xb1, 0x00, 0x04, 0x30, 0x3f, 0x0a, 0x09, 0xb1, 
+    0x00, 0x10, 0x54, 0xfe, 0x19, 0xb1, 0x00, 0x10, 0xd2, 0x17, 0x22, 0xda, 0xb8, 0x30, 0xe0, 0xd8, 
+    0xbd, 0x32, 0x68, 0x07, 0xca, 0xb8, 0x12, 0x5f, 0x4b, 0xda, 0xb8, 0x02, 0x60, 0x98, 0x09, 0xb1, 
+    0x00, 0x18, 0x7e, 0xa0, 0x88, 0x75, 0x31, 0x90, 0x12, 0x7c, 0x15, 0xf5, 0x31, 0x12, 0x7c, 0x15, 
+    0xa5, 0xfc, 0x5e, 0xb0, 0xf0, 0xa5, 0xfd, 0x09, 0xb1, 0x00, 0x18, 0x4c, 0x4b, 0x5e, 0xb0, 0xf0, 
+    0xbc, 0xb5, 0x78, 0xf1, 0x5e, 0x40, 0x0f, 0x4c, 0x54, 0x7c, 0xb5, 0x5e, 0x50, 0x0b, 0x68, 0x2a, 
+    0xa5, 0xfd, 0x5e, 0x50, 0x10, 0x68, 0x04, 0xd2, 0x6f, 0x80, 0x02, 0xc2, 0x6f, 0xa5, 0xfd, 0x5e, 
+    0x50, 0x20, 0x68, 0x04, 0xd2, 0x67, 0x80, 0x02, 0xc2, 0x67, 0xa5, 0xfd, 0x5e, 0x50, 0x80, 0x68, 
+    0x04, 0xd2, 0x5f, 0x80, 0x02, 0xc2, 0x5f, 0x12, 0x43, 0xaf, 0x02, 0x62, 0x93, 0x75, 0x31, 0x91, 
+    0x12, 0x7c, 0x15, 0x09, 0xb1, 0x00, 0x14, 0x7a, 0xb1, 0x31, 0x12, 0x7c, 0x15, 0x20, 0xe0, 0x08, 
+    0xd2, 0x04, 0x7e, 0xa0, 0x80, 0x02, 0x62, 0x93, 0xd2, 0x04, 0x30, 0xe1, 0x06, 0x7e, 0xa0, 0x80, 
+    0x12, 0x62, 0x93, 0xca, 0xb8, 0x5e, 0xb0, 0x1c, 0xda, 0xb8, 0x68, 0x12, 0x7e, 0xa0, 0xc0, 0x09, 
+    0x61, 0x00, 0x00, 0x12, 0x62, 0xb6, 0x09, 0xb1, 0x00, 0x14, 0x20, 0xe0, 0xdb, 0x22, 0x02, 0x5f, 
+    0x9d, 0x75, 0x31, 0x95, 0x12, 0x7c, 0x15, 0x22, 0x75, 0x31, 0x96, 0x12, 0x7c, 0x15, 0x22, 0x7c, 
+    0x02, 0x7e, 0x14, 0x80, 0x00, 0x4c, 0x20, 0x09, 0xb1, 0x00, 0x18, 0xa5, 0xfd, 0x5e, 0x50, 0x10, 
+    0x68, 0x04, 0xd2, 0x68, 0x80, 0x02, 0xc2, 0x68, 0xa5, 0xfd, 0x5e, 0x50, 0x20, 0x68, 0x04, 0xd2, 
+    0x60, 0x80, 0x02, 0xc2, 0x60, 0xa5, 0xfd, 0x5e, 0x50, 0x80, 0x68, 0x04, 0xd2, 0x58, 0x80, 0x02, 
+    0xc2, 0x58, 0x02, 0x62, 0x7f, 0x7c, 0x02, 0x7e, 0x14, 0x80, 0x00, 0x4c, 0x20, 0x09, 0xb1, 0x00, 
+    0x18, 0xa5, 0xfd, 0x5e, 0x50, 0x10, 0x68, 0x04, 0xd2, 0x69, 0x80, 0x02, 0xc2, 0x69, 0xa5, 0xfd, 
+    0x5e, 0x50, 0x20, 0x68, 0x04, 0xd2, 0x61, 0x80, 0x02, 0xc2, 0x61, 0xa5, 0xfd, 0x5e, 0x50, 0x80, 
+    0x68, 0x04, 0xd2, 0x59, 0x80, 0x02, 0xc2, 0x59, 0x02, 0x62, 0x7f, 0x7c, 0x02, 0x7e, 0x14, 0x80, 
+    0x00, 0x4c, 0x20, 0x09, 0xb1, 0x00, 0x18, 0xa5, 0xfd, 0x5e, 0x50, 0x10, 0x68, 0x04, 0xd2, 0x6a, 
+    0x80, 0x02, 0xc2, 0x6a, 0xa5, 0xfd, 0x5e, 0x50, 0x20, 0x68, 0x04, 0xd2, 0x62, 0x80, 0x02, 0xc2, 
+    0x62, 0xa5, 0xfd, 0x5e, 0x50, 0x80, 0x68, 0x04, 0xd2, 0x5a, 0x80, 0x02, 0xc2, 0x5a, 0x02, 0x62, 
+    0x7f, 0x7c, 0x02, 0x7e, 0x14, 0x80, 0x00, 0x4c, 0x20, 0x09, 0xb1, 0x00, 0x18, 0xa5, 0xfd, 0x5e, 
+    0x50, 0x10, 0x68, 0x04, 0xd2, 0x6b, 0x80, 0x02, 0xc2, 0x6b, 0xa5, 0xfd, 0x5e, 0x50, 0x20, 0x68, 
+    0x04, 0xd2, 0x63, 0x80, 0x02, 0xc2, 0x63, 0xa5, 0xfd, 0x5e, 0x50, 0x80, 0x68, 0x04, 0xd2, 0x5b, 
+    0x80, 0x02, 0xc2, 0x5b, 0x02, 0x62, 0x7f, 0x7c, 0x02, 0x7e, 0x14, 0x80, 0x00, 0x4c, 0x20, 0x09, 
+    0xb1, 0x00, 0x18, 0xa5, 0xfd, 0x5e, 0x50, 0x10, 0x68, 0x04, 0xd2, 0x6c, 0x80, 0x02, 0xc2, 0x6c, 
+    0xa5, 0xfd, 0x5e, 0x50, 0x20, 0x68, 0x04, 0xd2, 0x64, 0x80, 0x02, 0xc2, 0x64, 0xa5, 0xfd, 0x5e, 
+    0x50, 0x80, 0x68, 0x04, 0xd2, 0x5c, 0x80, 0x02, 0xc2, 0x5c, 0x02, 0x62, 0x7f, 0x7c, 0x02, 0x7e, 
+    0x14, 0x80, 0x00, 0x4c, 0x20, 0x09, 0xb1, 0x00, 0x18, 0xa5, 0xfd, 0x5e, 0x50, 0x10, 0x68, 0x04, 
+    0xd2, 0x6d, 0x80, 0x02, 0xc2, 0x6d, 0xa5, 0xfd, 0x5e, 0x50, 0x20, 0x68, 0x04, 0xd2, 0x65, 0x80, 
+    0x02, 0xc2, 0x65, 0xa5, 0xfd, 0x5e, 0x50, 0x80, 0x68, 0x04, 0xd2, 0x5d, 0x80, 0x02, 0xc2, 0x5d, 
+    0x02, 0x62, 0x7f, 0x7c, 0x02, 0x7e, 0x14, 0x80, 0x00, 0x4c, 0x20, 0x09, 0xb1, 0x00, 0x18, 0xa5, 
+    0xfd, 0x5e, 0x50, 0x10, 0x68, 0x04, 0xd2, 0x6e, 0x80, 0x02, 0xc2, 0x6e, 0xa5, 0xfd, 0x5e, 0x50, 
+    0x20, 0x68, 0x04, 0xd2, 0x66, 0x80, 0x02, 0xc2, 0x66, 0xa5, 0xfd, 0x5e, 0x50, 0x80, 0x68, 0x04, 
+    0xd2, 0x5e, 0x80, 0x02, 0xc2, 0x5e, 0x02, 0x62, 0x7f, 0x7c, 0x02, 0x7e, 0x14, 0x80, 0x00, 0x4c, 
+    0x20, 0x09, 0xb1, 0x00, 0x18, 0xa5, 0xfd, 0x5e, 0x50, 0x10, 0x68, 0x04, 0xd2, 0x6f, 0x80, 0x02, 
+    0xc2, 0x6f, 0xa5, 0xfd, 0x5e, 0x50, 0x20, 0x68, 0x04, 0xd2, 0x67, 0x80, 0x02, 0xc2, 0x67, 0xa5, 
+    0xfd, 0x5e, 0x50, 0x80, 0x68, 0x04, 0xd2, 0x5f, 0x80, 0x02, 0xc2, 0x5f, 0x02, 0x62, 0x7f, 0x54, 
+    0xf0, 0xc4, 0xa5, 0xff, 0xc4, 0xa5, 0x4f, 0x75, 0x31, 0x90, 0x12, 0x7c, 0x15, 0xf5, 0x31, 0x12, 
+    0x7c, 0x15, 0x22, 0xca, 0x19, 0x5e, 0x20, 0x07, 0x4c, 0xa2, 0x7e, 0x74, 0x29, 0xe3, 0xca, 0x79, 
+    0x7a, 0x79, 0xa0, 0x0b, 0x74, 0x7a, 0x79, 0xb0, 0x0b, 0x74, 0xda, 0x79, 0x7e, 0x30, 0x02, 0x7e, 
+    0x64, 0x00, 0x02, 0x02, 0x62, 0xde, 0xca, 0x19, 0x5e, 0x20, 0x07, 0x4c, 0xa2, 0x7e, 0x74, 0x29, 
+    0xe3, 0xca, 0x79, 0x7a, 0x79, 0xa0, 0x0b, 0x74, 0x7a, 0x79, 0xb0, 0x0b, 0x74, 0x7a, 0x79, 0x60, 
+    0x0b, 0x74, 0xda, 0x79, 0x7e, 0x30, 0x03, 0x7e, 0x64, 0x00, 0x03, 0x02, 0x62, 0xde, 0xd2, 0x04, 
+    0x7e, 0x27, 0x01, 0xe1, 0x2d, 0x26, 0xbe, 0x24, 0x04, 0x00, 0x38, 0x2e, 0x7e, 0x07, 0x01, 0xdf, 
+    0x7e, 0x44, 0x05, 0xe3, 0x7e, 0x79, 0xa0, 0x7a, 0x09, 0xa0, 0x0b, 0x04, 0x0b, 0x74, 0xbd, 0x04, 
+    0x68, 0x23, 0xa5, 0xdb, 0xef, 0x7a, 0x27, 0x01, 0xe1, 0x7e, 0x25, 0x46, 0x2d, 0x26, 0x7a, 0x25, 
+    0x46, 0x7a, 0x07, 0x01, 0xdf, 0xda, 0x19, 0xc2, 0xd7, 0x22, 0x75, 0x31, 0x9a, 0x12, 0x7c, 0x15, 
+    0xda, 0x19, 0xd2, 0xd7, 0x22, 0x7e, 0x04, 0x01, 0xe3, 0x80, 0xd7, 0x48, 0xb6, 0x46, 0x25, 0x47, 
+    0x1c, 0x49, 0x15, 0x44, 0xc6, 0x44, 0xc6, 0x48, 0x1b, 0x44, 0xc6, 0x49, 0x59, 0x44, 0xc6, 0x44, 
+    0xc6, 0x44, 0xc6, 0x44, 0xc6, 0x44, 0xc6, 0x44, 0xc6, 0x44, 0xc6, 0x49, 0x60, 0x44, 0xc6, 0x44, 
+    0xc6, 0x44, 0xc6, 0x44, 0xc6, 0x44, 0xc6, 0x44, 0xc6, 0x44, 0xc6, 0x44, 0xc6, 0x44, 0xc6, 0x44, 
+    0xc6, 0x44, 0xc6, 0x44, 0xc6, 0x44, 0xc6, 0x44, 0xc6, 0x44, 0xc6, 0x4c, 0x0e, 0x49, 0x7d, 0x4a, 
+    0x74, 0x4c, 0x6d, 0x44, 0xc6, 0x44, 0xc6, 0x4b, 0x73, 0x44, 0xc6, 0x4c, 0xb1, 0x44, 0xc6, 0x44, 
+    0xc6, 0x44, 0xc6, 0x44, 0xc6, 0x44, 0xc6, 0x44, 0xc6, 0x44, 0xc6, 0x4c, 0xb8, 0x44, 0xc6, 0x44, 
+    0xc6, 0x44, 0xc6, 0x44, 0xc6, 0x44, 0xc6, 0x44, 0xc6, 0x44, 0xc6, 0x44, 0xc6, 0x44, 0xc6, 0x44, 
+    0xc6, 0x44, 0xc6, 0x44, 0xc6, 0x44, 0xc6, 0x44, 0xc6, 0x44, 0xc6, 0x4f, 0x66, 0x4c, 0xd5, 0x4d, 
+    0xcc, 0x4f, 0xc5, 0x44, 0xc6, 0x44, 0xc6, 0x4e, 0xcb, 0x44, 0xc6, 0x50, 0x09, 0x44, 0xc6, 0x44, 
+    0xc6, 0x44, 0xc6, 0x44, 0xc6, 0x44, 0xc6, 0x44, 0xc6, 0x44, 0xc6, 0x50, 0x10, 0x44, 0xc6, 0x44, 
+    0xc6, 0x44, 0xc6, 0x44, 0xc6, 0x44, 0xc6, 0x44, 0xc6, 0x44, 0xc6, 0x44, 0xc6, 0x44, 0xc6, 0x44, 
+    0xc6, 0x44, 0xc6, 0x44, 0xc6, 0x44, 0xc6, 0x44, 0xc6, 0x44, 0xc6, 0x52, 0xbe, 0x50, 0x2d, 0x51, 
+    0x24, 0x53, 0x1d, 0x44, 0xc6, 0x44, 0xc6, 0x52, 0x23, 0x44, 0xc6, 0x53, 0x61, 0x44, 0xc6, 0x44, 
+    0xc6, 0x44, 0xc6, 0x44, 0xc6, 0x44, 0xc6, 0x44, 0xc6, 0x44, 0xc6, 0x53, 0x68, 0x44, 0xc6, 0x44, 
+    0xc6, 0x44, 0xc6, 0x44, 0xc6, 0x44, 0xc6, 0x44, 0xc6, 0x44, 0xc6, 0x44, 0xc6, 0x44, 0xc6, 0x44, 
+    0xc6, 0x44, 0xc6, 0x44, 0xc6, 0x44, 0xc6, 0x44, 0xc6, 0x44, 0xc6, 0x56, 0x16, 0x53, 0x85, 0x54, 
+    0x7c, 0x56, 0x75, 0x44, 0xc6, 0x44, 0xc6, 0x55, 0x7b, 0x44, 0xc6, 0x56, 0xb9, 0x44, 0xc6, 0x44, 
+    0xc6, 0x44, 0xc6, 0x44, 0xc6, 0x44, 0xc6, 0x44, 0xc6, 0x44, 0xc6, 0x56, 0xc0, 0x44, 0xc6, 0x44, 
+    0xc6, 0x44, 0xc6, 0x44, 0xc6, 0x44, 0xc6, 0x44, 0xc6, 0x44, 0xc6, 0x44, 0xc6, 0x44, 0xc6, 0x44, 
+    0xc6, 0x44, 0xc6, 0x44, 0xc6, 0x44, 0xc6, 0x44, 0xc6, 0x44, 0xc6, 0x59, 0x6e, 0x56, 0xdd, 0x57, 
+    0xd4, 0x59, 0xcd, 0x44, 0xc6, 0x44, 0xc6, 0x58, 0xd3, 0x44, 0xc6, 0x5a, 0x11, 0x44, 0xc6, 0x44, 
+    0xc6, 0x44, 0xc6, 0x44, 0xc6, 0x44, 0xc6, 0x44, 0xc6, 0x44, 0xc6, 0x5a, 0x18, 0x44, 0xc6, 0x44, 
+    0xc6, 0x44, 0xc6, 0x44, 0xc6, 0x44, 0xc6, 0x44, 0xc6, 0x44, 0xc6, 0x44, 0xc6, 0x44, 0xc6, 0x44, 
+    0xc6, 0x44, 0xc6, 0x44, 0xc6, 0x44, 0xc6, 0x44, 0xc6, 0x44, 0xc6, 0x5c, 0xc6, 0x5a, 0x35, 0x5b, 
+    0x2c, 0x5d, 0x25, 0x44, 0xc6, 0x44, 0xc6, 0x5c, 0x2b, 0x44, 0xc6, 0x5d, 0x69, 0x44, 0xc6, 0x44, 
+    0xc6, 0x44, 0xc6, 0x44, 0xc6, 0x44, 0xc6, 0x44, 0xc6, 0x44, 0xc6, 0x5d, 0x70, 0x44, 0xc6, 0x44, 
+    0xc6, 0x44, 0xc6, 0x44, 0xc6, 0x44, 0xc6, 0x44, 0xc6, 0x44, 0xc6, 0x44, 0xc6, 0x44, 0xc6, 0x44, 
+    0xc6, 0x44, 0xc6, 0x44, 0xc6, 0x44, 0xc6, 0x44, 0xc6, 0x44, 0xc6, 0x60, 0x1e, 0x5d, 0x8d, 0x5e, 
+    0x84, 0x60, 0x7d, 0x44, 0xc6, 0x44, 0xc6, 0x5f, 0x83, 0x44, 0xc6, 0x60, 0xc1, 0x44, 0xc6, 0x44, 
+    0xc6, 0x44, 0xc6, 0x44, 0xc6, 0x44, 0xc6, 0x44, 0xc6, 0x44, 0xc6, 0x60, 0xc8, 0x44, 0xc6, 0x44, 
+    0xc6, 0x44, 0xc6, 0x44, 0xc6, 0x44, 0xc6, 0x44, 0xc6, 0x44, 0xc6, 0x44, 0xc6, 0x44, 0xc6, 0x44, 
+    0xc6, 0x44, 0xc6, 0x44, 0xc6, 0x44, 0xc6, 0x44, 0xc6, 0x44, 0xc6, 0xca, 0x29, 0x1e, 0x50, 0x40, 
+    0x0d, 0x7e, 0x54, 0x0b, 0x10, 0x9c, 0xb5, 0xa4, 0x2e, 0x54, 0x65, 0x48, 0x89, 0x54, 0x7e, 0x39, 
+    0x00, 0x7a, 0x19, 0x00, 0x0b, 0x34, 0x80, 0xe9, 0x0b, 0x38, 0x00, 0x7a, 0x19, 0x00, 0x7a, 0x19, 
     0x10, 0x0b, 0x35, 0x0b, 0x38, 0x00, 0x7a, 0x19, 0x00, 0x7a, 0x19, 0x10, 0x0b, 0x35, 0x0b, 0x38, 
     0x00, 0x7a, 0x19, 0x00, 0x7a, 0x19, 0x10, 0x0b, 0x35, 0x0b, 0x38, 0x00, 0x7a, 0x19, 0x00, 0x7a, 
     0x19, 0x10, 0x0b, 0x35, 0x0b, 0x38, 0x00, 0x7a, 0x19, 0x00, 0x7a, 0x19, 0x10, 0x0b, 0x35, 0x0b, 
@@ -744,12 +832,12 @@
     0x7a, 0x19, 0x10, 0x0b, 0x35, 0x0b, 0x38, 0x00, 0x7a, 0x19, 0x00, 0x7a, 0x19, 0x10, 0x0b, 0x35, 
     0x0b, 0x38, 0x00, 0x7a, 0x19, 0x00, 0x7a, 0x19, 0x10, 0x0b, 0x35, 0x0b, 0x38, 0x00, 0x7a, 0x19, 
     0x00, 0x7a, 0x19, 0x10, 0x0b, 0x35, 0x0b, 0x38, 0x00, 0x7a, 0x19, 0x00, 0x7a, 0x19, 0x10, 0x0b, 
-    0x35, 0xda, 0x29, 0x22, 0x1e, 0x50, 0x40, 0x0d, 0x7e, 0x54, 0x0b, 0x1c, 0x9c, 0xb5, 0xa4, 0x2e, 
-    0x54, 0x69, 0x1f, 0x89, 0x54, 0x7e, 0x19, 0x00, 0x7a, 0x39, 0x00, 0x0b, 0x34, 0x80, 0xe9, 0x7e, 
-    0x19, 0x00, 0x7e, 0x19, 0x10, 0x1b, 0x38, 0x00, 0x0b, 0x35, 0x7e, 0x19, 0x00, 0x7e, 0x19, 0x10, 
-    0x1b, 0x38, 0x00, 0x0b, 0x35, 0x7e, 0x19, 0x00, 0x7e, 0x19, 0x10, 0x1b, 0x38, 0x00, 0x0b, 0x35, 
-    0x7e, 0x19, 0x00, 0x7e, 0x19, 0x10, 0x1b, 0x38, 0x00, 0x0b, 0x35, 0x7e, 0x19, 0x00, 0x7e, 0x19, 
-    0x10, 0x1b, 0x38, 0x00, 0x0b, 0x35, 0x7e, 0x19, 0x00, 0x7e, 0x19, 0x10, 0x1b, 0x38, 0x00, 0x0b, 
+    0x35, 0x0b, 0x38, 0x00, 0x7a, 0x19, 0x00, 0x7a, 0x19, 0x10, 0x0b, 0x35, 0x0b, 0x38, 0x00, 0x7a, 
+    0x19, 0x00, 0x7a, 0x19, 0x10, 0x0b, 0x35, 0x0b, 0x38, 0x00, 0x7a, 0x19, 0x00, 0x7a, 0x19, 0x10, 
+    0x0b, 0x35, 0x0b, 0x38, 0x00, 0x7a, 0x19, 0x00, 0x7a, 0x19, 0x10, 0x0b, 0x35, 0x0b, 0x38, 0x00, 
+    0x7a, 0x19, 0x00, 0x7a, 0x19, 0x10, 0x0b, 0x35, 0xda, 0x29, 0x22, 0x1e, 0x50, 0x40, 0x0d, 0x7e, 
+    0x54, 0x0b, 0x1c, 0x9c, 0xb5, 0xa4, 0x2e, 0x54, 0x66, 0x16, 0x89, 0x54, 0x7e, 0x19, 0x00, 0x7a, 
+    0x39, 0x00, 0x0b, 0x34, 0x80, 0xe9, 0x7e, 0x19, 0x00, 0x7e, 0x19, 0x10, 0x1b, 0x38, 0x00, 0x0b, 
     0x35, 0x7e, 0x19, 0x00, 0x7e, 0x19, 0x10, 0x1b, 0x38, 0x00, 0x0b, 0x35, 0x7e, 0x19, 0x00, 0x7e, 
     0x19, 0x10, 0x1b, 0x38, 0x00, 0x0b, 0x35, 0x7e, 0x19, 0x00, 0x7e, 0x19, 0x10, 0x1b, 0x38, 0x00, 
     0x0b, 0x35, 0x7e, 0x19, 0x00, 0x7e, 0x19, 0x10, 0x1b, 0x38, 0x00, 0x0b, 0x35, 0x7e, 0x19, 0x00, 
@@ -765,157 +853,176 @@
     0x19, 0x10, 0x1b, 0x38, 0x00, 0x0b, 0x35, 0x7e, 0x19, 0x00, 0x7e, 0x19, 0x10, 0x1b, 0x38, 0x00, 
     0x0b, 0x35, 0x7e, 0x19, 0x00, 0x7e, 0x19, 0x10, 0x1b, 0x38, 0x00, 0x0b, 0x35, 0x7e, 0x19, 0x00, 
     0x7e, 0x19, 0x10, 0x1b, 0x38, 0x00, 0x0b, 0x35, 0x7e, 0x19, 0x00, 0x7e, 0x19, 0x10, 0x1b, 0x38, 
-    0x00, 0x0b, 0x35, 0x22, 0x6a, 0x9b, 0x6c, 0x4f, 0x6c, 0x67, 0x6c, 0x82, 0x6d, 0x1d, 0x6d, 0xb5, 
-    0x6d, 0xd0, 0x6e, 0x62, 0x6d, 0xeb, 0x6e, 0x2c, 0x7c, 0xb3, 0xbe, 0xb0, 0x09, 0x28, 0x14, 0x75, 
-    0x2f, 0x09, 0x12, 0x7e, 0x30, 0x75, 0x57, 0x10, 0xc0, 0xf1, 0x75, 0xf1, 0x01, 0x43, 0xe1, 0xc0, 
-    0xd0, 0xf1, 0x22, 0xc0, 0xa8, 0xc2, 0xaf, 0x23, 0x6c, 0xaa, 0x2e, 0x54, 0x6a, 0x54, 0x0b, 0x58, 
-    0x50, 0x89, 0x54, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x75, 0x2f, 0xb0, 0x12, 0x7e, 
-    0x30, 0x0a, 0x22, 0x09, 0xb2, 0x6a, 0x93, 0x42, 0x24, 0xd0, 0xa8, 0x22, 0x7c, 0xb2, 0x23, 0x0a, 
-    0x3b, 0x49, 0x33, 0x6a, 0xb7, 0x89, 0x34, 0x6a, 0xc7, 0x6a, 0xf5, 0x6b, 0x23, 0x6b, 0x51, 0x6b, 
-    0x7f, 0x6b, 0xad, 0x6b, 0xdb, 0x6c, 0x09, 0x12, 0x41, 0xa9, 0xd2, 0x28, 0xd2, 0x08, 0xc2, 0x40, 
-    0xc2, 0x48, 0xc2, 0x38, 0xc2, 0x30, 0x6d, 0x00, 0x7a, 0x03, 0x01, 0xb9, 0x7e, 0x04, 0x00, 0x20, 
-    0x7a, 0x07, 0x01, 0x99, 0x7e, 0x04, 0x00, 0x38, 0x7a, 0x07, 0x01, 0xa9, 0x12, 0x41, 0x16, 0x12, 
-    0x64, 0x40, 0x02, 0x6c, 0x37, 0x12, 0x41, 0xc6, 0xd2, 0x29, 0xd2, 0x09, 0xc2, 0x41, 0xc2, 0x49, 
-    0xc2, 0x39, 0xc2, 0x31, 0x6d, 0x00, 0x7a, 0x03, 0x01, 0xba, 0x7e, 0x04, 0x00, 0x20, 0x7a, 0x07, 
-    0x01, 0x9b, 0x7e, 0x04, 0x00, 0x38, 0x7a, 0x07, 0x01, 0xab, 0x12, 0x41, 0x16, 0x12, 0x64, 0x69, 
-    0x02, 0x6c, 0x37, 0x12, 0x41, 0xe3, 0xd2, 0x2a, 0xd2, 0x0a, 0xc2, 0x42, 0xc2, 0x4a, 0xc2, 0x3a, 
-    0xc2, 0x32, 0x6d, 0x00, 0x7a, 0x03, 0x01, 0xbb, 0x7e, 0x04, 0x00, 0x20, 0x7a, 0x07, 0x01, 0x9d, 
-    0x7e, 0x04, 0x00, 0x38, 0x7a, 0x07, 0x01, 0xad, 0x12, 0x41, 0x16, 0x12, 0x64, 0x92, 0x02, 0x6c, 
-    0x37, 0x12, 0x42, 0x00, 0xd2, 0x2b, 0xd2, 0x0b, 0xc2, 0x43, 0xc2, 0x4b, 0xc2, 0x3b, 0xc2, 0x33, 
-    0x6d, 0x00, 0x7a, 0x03, 0x01, 0xbc, 0x7e, 0x04, 0x00, 0x20, 0x7a, 0x07, 0x01, 0x9f, 0x7e, 0x04, 
-    0x00, 0x38, 0x7a, 0x07, 0x01, 0xaf, 0x12, 0x41, 0x16, 0x12, 0x64, 0xbb, 0x02, 0x6c, 0x37, 0x12, 
-    0x42, 0x1d, 0xd2, 0x2c, 0xd2, 0x0c, 0xc2, 0x44, 0xc2, 0x4c, 0xc2, 0x3c, 0xc2, 0x34, 0x6d, 0x00, 
-    0x7a, 0x03, 0x01, 0xbd, 0x7e, 0x04, 0x00, 0x20, 0x7a, 0x07, 0x01, 0xa1, 0x7e, 0x04, 0x00, 0x38, 
-    0x7a, 0x07, 0x01, 0xb1, 0x12, 0x41, 0x16, 0x12, 0x64, 0xe4, 0x02, 0x6c, 0x37, 0x12, 0x42, 0x3a, 
-    0xd2, 0x2d, 0xd2, 0x0d, 0xc2, 0x45, 0xc2, 0x4d, 0xc2, 0x3d, 0xc2, 0x35, 0x6d, 0x00, 0x7a, 0x03, 
-    0x01, 0xbe, 0x7e, 0x04, 0x00, 0x20, 0x7a, 0x07, 0x01, 0xa3, 0x7e, 0x04, 0x00, 0x38, 0x7a, 0x07, 
-    0x01, 0xb3, 0x12, 0x41, 0x16, 0x12, 0x65, 0x0d, 0x02, 0x6c, 0x37, 0x12, 0x42, 0x57, 0xd2, 0x2e, 
-    0xd2, 0x0e, 0xc2, 0x46, 0xc2, 0x4e, 0xc2, 0x3e, 0xc2, 0x36, 0x6d, 0x00, 0x7a, 0x03, 0x01, 0xbf, 
-    0x7e, 0x04, 0x00, 0x20, 0x7a, 0x07, 0x01, 0xa5, 0x7e, 0x04, 0x00, 0x38, 0x7a, 0x07, 0x01, 0xb5, 
-    0x12, 0x41, 0x16, 0x12, 0x65, 0x36, 0x02, 0x6c, 0x37, 0x12, 0x42, 0x74, 0xd2, 0x2f, 0xd2, 0x0f, 
-    0xc2, 0x47, 0xc2, 0x4f, 0xc2, 0x3f, 0xc2, 0x37, 0x6d, 0x00, 0x7a, 0x03, 0x01, 0xc0, 0x7e, 0x04, 
-    0x00, 0x20, 0x7a, 0x07, 0x01, 0xa7, 0x7e, 0x04, 0x00, 0x38, 0x7a, 0x07, 0x01, 0xb7, 0x12, 0x41, 
-    0x16, 0x12, 0x65, 0x5f, 0x02, 0x6c, 0x37, 0x7e, 0xa0, 0xd0, 0x7e, 0x60, 0x0f, 0x12, 0x65, 0xbf, 
-    0x40, 0x0c, 0xc0, 0xf1, 0x75, 0xf1, 0x01, 0x12, 0x71, 0xe9, 0xd0, 0xf1, 0xc2, 0xd7, 0x22, 0x75, 
-    0x2f, 0xb1, 0x12, 0x7e, 0x30, 0x0a, 0x52, 0x23, 0x6d, 0x00, 0x59, 0x05, 0x00, 0x32, 0x12, 0x41, 
-    0x72, 0x12, 0x41, 0x8e, 0xd0, 0xa8, 0x22, 0x75, 0x2f, 0xb2, 0x12, 0x7e, 0x30, 0x0a, 0x22, 0x09, 
-    0xb2, 0x6a, 0x93, 0x42, 0x23, 0x7e, 0xb0, 0x9c, 0x19, 0xb2, 0x01, 0xb9, 0x12, 0x45, 0x74, 0xd0, 
-    0xa8, 0x22, 0x7e, 0x04, 0x80, 0x00, 0x4c, 0x02, 0x09, 0x30, 0x00, 0x0c, 0x74, 0xbf, 0x19, 0xb0, 
-    0x00, 0x0c, 0x09, 0xb0, 0x00, 0x08, 0x19, 0x30, 0x00, 0x0c, 0x7c, 0x74, 0x5e, 0x70, 0x01, 0x68, 
-    0x12, 0x44, 0x40, 0xca, 0xb8, 0x09, 0xb0, 0x00, 0x10, 0x44, 0x02, 0x19, 0xb0, 0x00, 0x10, 0xda, 
-    0xb8, 0x80, 0x02, 0x54, 0xbf, 0x7c, 0x74, 0x5e, 0x70, 0x08, 0x68, 0x04, 0x44, 0x08, 0x80, 0x02, 
-    0x54, 0xf7, 0x09, 0x30, 0x00, 0x0c, 0xca, 0xb8, 0x74, 0xbf, 0x19, 0xb0, 0x00, 0x0c, 0xda, 0xb8, 
-    0x19, 0xb0, 0x00, 0x08, 0x19, 0x30, 0x00, 0x0c, 0x0a, 0x62, 0x09, 0xb6, 0x6a, 0x93, 0x3e, 0x20, 
-    0x0a, 0x62, 0x7c, 0x74, 0x5e, 0x70, 0x02, 0x68, 0x20, 0x42, 0x27, 0xca, 0xb8, 0x74, 0x61, 0x19, 
-    0xb0, 0x00, 0x08, 0x7e, 0x44, 0x00, 0x10, 0x59, 0x46, 0x01, 0xa9, 0x09, 0xb0, 0x00, 0x10, 0x44, 
-    0x01, 0x19, 0xb0, 0x00, 0x10, 0xda, 0xb8, 0x80, 0x11, 0xf4, 0x52, 0x27, 0x74, 0xa1, 0x19, 0xb0, 
-    0x00, 0x08, 0x7e, 0x44, 0x00, 0x38, 0x59, 0x46, 0x01, 0xa9, 0xd0, 0xa8, 0x22, 0x7c, 0x74, 0x7e, 
-    0x04, 0x80, 0x00, 0x4c, 0x02, 0x09, 0x30, 0x00, 0x0c, 0x74, 0xbf, 0x19, 0xb0, 0x00, 0x0c, 0x09, 
-    0xb0, 0x00, 0x08, 0x7c, 0x74, 0x5e, 0x70, 0x01, 0x68, 0x04, 0x44, 0x80, 0x80, 0x02, 0x54, 0x7f, 
-    0x7c, 0x74, 0x5e, 0x70, 0x08, 0x68, 0x04, 0x44, 0x02, 0x80, 0x02, 0x54, 0xfd, 0x19, 0xb0, 0x00, 
-    0x08, 0x19, 0x30, 0x00, 0x0c, 0x0a, 0x62, 0x09, 0xb6, 0x6a, 0x93, 0xa5, 0xfd, 0xf4, 0xa5, 0xfe, 
-    0xca, 0x28, 0x3e, 0x20, 0x0a, 0x62, 0xda, 0x28, 0x7c, 0x74, 0x5e, 0x70, 0x02, 0x68, 0x10, 0xa5, 
-    0xed, 0x42, 0x28, 0x42, 0x26, 0x7e, 0x44, 0x00, 0x08, 0x59, 0x46, 0x01, 0x99, 0x80, 0x04, 0xa5, 
-    0xee, 0x52, 0x28, 0x7c, 0x74, 0x5e, 0x70, 0x04, 0x68, 0x10, 0xa5, 0xed, 0x42, 0x29, 0x42, 0x26, 
-    0x7e, 0x44, 0x00, 0x08, 0x59, 0x46, 0x01, 0x99, 0x80, 0x15, 0xa5, 0xee, 0x52, 0x29, 0x7c, 0x74, 
-    0x5e, 0x70, 0x02, 0x78, 0x0a, 0x52, 0x26, 0x7e, 0x44, 0x00, 0x20, 0x59, 0x46, 0x01, 0x99, 0x12, 
-    0x42, 0x91, 0xd0, 0xa8, 0x22, 0x7e, 0x04, 0x80, 0x00, 0x4c, 0x02, 0x09, 0x30, 0x00, 0x0c, 0x74, 
-    0xbf, 0x19, 0xb0, 0x00, 0x0c, 0x19, 0x40, 0x00, 0x10, 0x19, 0x30, 0x00, 0x0c, 0xd0, 0xa8, 0x22, 
-    0x7e, 0x04, 0x80, 0x00, 0x4c, 0x02, 0x09, 0x30, 0x00, 0x0c, 0x74, 0xbf, 0x19, 0xb0, 0x00, 0x0c, 
-    0x19, 0x40, 0x00, 0x18, 0x19, 0x30, 0x00, 0x0c, 0xd0, 0xa8, 0x22, 0x75, 0x2f, 0xb5, 0x12, 0x7e, 
-    0x30, 0x7e, 0x04, 0x80, 0x00, 0x4c, 0x02, 0x09, 0xb0, 0x00, 0x0c, 0x44, 0x40, 0x19, 0xb0, 0x00, 
-    0x0c, 0xe5, 0x58, 0xb4, 0x07, 0x23, 0x09, 0xb0, 0x00, 0x10, 0x4e, 0xb0, 0x02, 0x19, 0xb0, 0x00, 
-    0x10, 0x09, 0x30, 0x00, 0x0c, 0x74, 0xbf, 0x19, 0xb0, 0x00, 0x0c, 0x09, 0xb0, 0x00, 0x04, 0x54, 
-    0xf7, 0x19, 0xb0, 0x00, 0x04, 0x19, 0x30, 0x00, 0x0c, 0xd0, 0xa8, 0x22, 0x75, 0x2f, 0xb6, 0x12, 
-    0x7e, 0x30, 0x7e, 0x04, 0x80, 0x00, 0x4c, 0x02, 0xe5, 0x58, 0xb4, 0x07, 0x18, 0x09, 0x30, 0x00, 
-    0x0c, 0x74, 0xbf, 0x19, 0xb0, 0x00, 0x0c, 0x09, 0xb0, 0x00, 0x04, 0x44, 0x08, 0x19, 0xb0, 0x00, 
-    0x04, 0x19, 0x30, 0x00, 0x0c, 0x09, 0xb0, 0x00, 0x0c, 0x54, 0xbf, 0x19, 0xb0, 0x00, 0x0c, 0xd0, 
-    0xa8, 0x22, 0x75, 0x2f, 0xb4, 0x12, 0x7e, 0x30, 0x7a, 0x21, 0x2f, 0x12, 0x7e, 0x30, 0x7a, 0x41, 
-    0x2f, 0x12, 0x7e, 0x30, 0x7e, 0xb0, 0x01, 0x7e, 0xa0, 0xc8, 0x7c, 0x64, 0x12, 0x65, 0xbf, 0xc0, 
-    0xf1, 0x75, 0xf1, 0x01, 0x12, 0x71, 0xe9, 0xd0, 0xf1, 0xd0, 0xa8, 0x22, 0x6e, 0x9c, 0x6e, 0xe3, 
-    0x6f, 0x2a, 0x6f, 0x71, 0x6f, 0xb8, 0x6f, 0xff, 0x70, 0x46, 0x70, 0x8d, 0x75, 0x2f, 0x55, 0x12, 
-    0x7e, 0x30, 0x75, 0x2f, 0x00, 0x12, 0x7e, 0x30, 0x7a, 0x61, 0x2f, 0x12, 0x7e, 0x30, 0x7a, 0x71, 
-    0x2f, 0x12, 0x7e, 0x30, 0x7e, 0x17, 0x01, 0x69, 0x7e, 0x27, 0x01, 0x79, 0x2d, 0x23, 0x7e, 0x09, 
-    0xb0, 0x0b, 0x04, 0x7a, 0x19, 0xb0, 0x0b, 0x14, 0xbe, 0x14, 0x0d, 0xcc, 0x38, 0x0f, 0x1b, 0x34, 
-    0x78, 0xec, 0x7a, 0x17, 0x01, 0x69, 0x7a, 0x27, 0x01, 0x79, 0x02, 0x4a, 0x98, 0x7e, 0x14, 0x09, 
-    0xcd, 0x80, 0xeb, 0x75, 0x2f, 0x55, 0x12, 0x7e, 0x30, 0x75, 0x2f, 0x01, 0x12, 0x7e, 0x30, 0x7a, 
-    0x61, 0x2f, 0x12, 0x7e, 0x30, 0x7a, 0x71, 0x2f, 0x12, 0x7e, 0x30, 0x7e, 0x17, 0x01, 0x6b, 0x7e, 
-    0x27, 0x01, 0x7b, 0x2d, 0x23, 0x7e, 0x09, 0xb0, 0x0b, 0x04, 0x7a, 0x19, 0xb0, 0x0b, 0x14, 0xbe, 
-    0x14, 0x11, 0xcc, 0x38, 0x0f, 0x1b, 0x34, 0x78, 0xec, 0x7a, 0x17, 0x01, 0x6b, 0x7a, 0x27, 0x01, 
-    0x7b, 0x02, 0x4d, 0xcd, 0x7e, 0x14, 0x0d, 0xcd, 0x80, 0xeb, 0x75, 0x2f, 0x55, 0x12, 0x7e, 0x30, 
-    0x75, 0x2f, 0x02, 0x12, 0x7e, 0x30, 0x7a, 0x61, 0x2f, 0x12, 0x7e, 0x30, 0x7a, 0x71, 0x2f, 0x12, 
-    0x7e, 0x30, 0x7e, 0x17, 0x01, 0x6d, 0x7e, 0x27, 0x01, 0x7d, 0x2d, 0x23, 0x7e, 0x09, 0xb0, 0x0b, 
-    0x04, 0x7a, 0x19, 0xb0, 0x0b, 0x14, 0xbe, 0x14, 0x15, 0xcc, 0x38, 0x0f, 0x1b, 0x34, 0x78, 0xec, 
-    0x7a, 0x17, 0x01, 0x6d, 0x7a, 0x27, 0x01, 0x7d, 0x02, 0x51, 0x02, 0x7e, 0x14, 0x11, 0xcd, 0x80, 
-    0xeb, 0x75, 0x2f, 0x55, 0x12, 0x7e, 0x30, 0x75, 0x2f, 0x03, 0x12, 0x7e, 0x30, 0x7a, 0x61, 0x2f, 
-    0x12, 0x7e, 0x30, 0x7a, 0x71, 0x2f, 0x12, 0x7e, 0x30, 0x7e, 0x17, 0x01, 0x6f, 0x7e, 0x27, 0x01, 
-    0x7f, 0x2d, 0x23, 0x7e, 0x09, 0xb0, 0x0b, 0x04, 0x7a, 0x19, 0xb0, 0x0b, 0x14, 0xbe, 0x14, 0x19, 
-    0xcc, 0x38, 0x0f, 0x1b, 0x34, 0x78, 0xec, 0x7a, 0x17, 0x01, 0x6f, 0x7a, 0x27, 0x01, 0x7f, 0x02, 
-    0x54, 0x37, 0x7e, 0x14, 0x15, 0xcd, 0x80, 0xeb, 0x75, 0x2f, 0x55, 0x12, 0x7e, 0x30, 0x75, 0x2f, 
-    0x04, 0x12, 0x7e, 0x30, 0x7a, 0x61, 0x2f, 0x12, 0x7e, 0x30, 0x7a, 0x71, 0x2f, 0x12, 0x7e, 0x30, 
-    0x7e, 0x17, 0x01, 0x71, 0x7e, 0x27, 0x01, 0x81, 0x2d, 0x23, 0x7e, 0x09, 0xb0, 0x0b, 0x04, 0x7a, 
-    0x19, 0xb0, 0x0b, 0x14, 0xbe, 0x14, 0x1d, 0xcc, 0x38, 0x0f, 0x1b, 0x34, 0x78, 0xec, 0x7a, 0x17, 
-    0x01, 0x71, 0x7a, 0x27, 0x01, 0x81, 0x02, 0x57, 0x6c, 0x7e, 0x14, 0x19, 0xcd, 0x80, 0xeb, 0x75, 
-    0x2f, 0x55, 0x12, 0x7e, 0x30, 0x75, 0x2f, 0x05, 0x12, 0x7e, 0x30, 0x7a, 0x61, 0x2f, 0x12, 0x7e, 
-    0x30, 0x7a, 0x71, 0x2f, 0x12, 0x7e, 0x30, 0x7e, 0x17, 0x01, 0x73, 0x7e, 0x27, 0x01, 0x83, 0x2d, 
-    0x23, 0x7e, 0x09, 0xb0, 0x0b, 0x04, 0x7a, 0x19, 0xb0, 0x0b, 0x14, 0xbe, 0x14, 0x21, 0xcc, 0x38, 
-    0x0f, 0x1b, 0x34, 0x78, 0xec, 0x7a, 0x17, 0x01, 0x73, 0x7a, 0x27, 0x01, 0x83, 0x02, 0x5a, 0xa1, 
-    0x7e, 0x14, 0x1d, 0xcd, 0x80, 0xeb, 0x75, 0x2f, 0x55, 0x12, 0x7e, 0x30, 0x75, 0x2f, 0x06, 0x12, 
-    0x7e, 0x30, 0x7a, 0x61, 0x2f, 0x12, 0x7e, 0x30, 0x7a, 0x71, 0x2f, 0x12, 0x7e, 0x30, 0x7e, 0x17, 
-    0x01, 0x75, 0x7e, 0x27, 0x01, 0x85, 0x2d, 0x23, 0x7e, 0x09, 0xb0, 0x0b, 0x04, 0x7a, 0x19, 0xb0, 
-    0x0b, 0x14, 0xbe, 0x14, 0x25, 0xcc, 0x38, 0x0f, 0x1b, 0x34, 0x78, 0xec, 0x7a, 0x17, 0x01, 0x75, 
-    0x7a, 0x27, 0x01, 0x85, 0x02, 0x5d, 0xd6, 0x7e, 0x14, 0x21, 0xcd, 0x80, 0xeb, 0x75, 0x2f, 0x55, 
-    0x12, 0x7e, 0x30, 0x75, 0x2f, 0x07, 0x12, 0x7e, 0x30, 0x7a, 0x61, 0x2f, 0x12, 0x7e, 0x30, 0x7a, 
-    0x71, 0x2f, 0x12, 0x7e, 0x30, 0x7e, 0x17, 0x01, 0x77, 0x7e, 0x27, 0x01, 0x87, 0x2d, 0x23, 0x7e, 
-    0x09, 0xb0, 0x0b, 0x04, 0x7a, 0x19, 0xb0, 0x0b, 0x14, 0xbe, 0x14, 0x29, 0xcc, 0x38, 0x0f, 0x1b, 
-    0x34, 0x78, 0xec, 0x7a, 0x17, 0x01, 0x77, 0x7a, 0x27, 0x01, 0x87, 0x02, 0x61, 0x0b, 0x7e, 0x14, 
-    0x25, 0xcd, 0x80, 0xeb, 0xca, 0xb8, 0xc0, 0xf1, 0x75, 0x2f, 0x02, 0x12, 0x7e, 0x30, 0xe5, 0xc0, 
-    0x54, 0x03, 0x68, 0x05, 0x12, 0x77, 0xdd, 0x80, 0xf5, 0x30, 0xc2, 0x08, 0x75, 0xf1, 0x01, 0x12, 
-    0x71, 0xe9, 0x80, 0x14, 0x30, 0xc3, 0x08, 0x75, 0xf1, 0x01, 0x12, 0x71, 0x0d, 0x80, 0x09, 0x30, 
-    0xc4, 0x06, 0x75, 0xf1, 0x02, 0x12, 0x72, 0xf9, 0xd0, 0xf1, 0xda, 0xb8, 0x32, 0x75, 0x2f, 0x10, 
-    0x12, 0x7e, 0x30, 0xca, 0x0b, 0xca, 0x39, 0xca, 0x59, 0xc2, 0xc3, 0xa9, 0x21, 0xe2, 0x5c, 0xe5, 
-    0xe5, 0x54, 0xc0, 0x68, 0x4f, 0xe5, 0xe6, 0x6c, 0xaa, 0x7e, 0x37, 0x01, 0xc5, 0x2d, 0x35, 0xbe, 
-    0x34, 0x04, 0x00, 0x38, 0x4a, 0x7a, 0x37, 0x01, 0xc5, 0x7e, 0x37, 0x01, 0xc3, 0x7d, 0x43, 0x2d, 
-    0x45, 0xbe, 0x44, 0x09, 0xcc, 0x38, 0x40, 0x7a, 0x47, 0x01, 0xc3, 0x75, 0x2f, 0x11, 0x12, 0x7e, 
-    0x30, 0x7a, 0xb1, 0x2f, 0x12, 0x7e, 0x30, 0x12, 0x73, 0xc8, 0xa9, 0x21, 0xe5, 0x1f, 0xa9, 0xd4, 
+    0x00, 0x0b, 0x35, 0x7e, 0x19, 0x00, 0x7e, 0x19, 0x10, 0x1b, 0x38, 0x00, 0x0b, 0x35, 0x7e, 0x19, 
+    0x00, 0x7e, 0x19, 0x10, 0x1b, 0x38, 0x00, 0x0b, 0x35, 0x7e, 0x19, 0x00, 0x7e, 0x19, 0x10, 0x1b, 
+    0x38, 0x00, 0x0b, 0x35, 0x7e, 0x19, 0x00, 0x7e, 0x19, 0x10, 0x1b, 0x38, 0x00, 0x0b, 0x35, 0x7e, 
+    0x19, 0x00, 0x7e, 0x19, 0x10, 0x1b, 0x38, 0x00, 0x0b, 0x35, 0x22, 0x67, 0x96, 0x69, 0x63, 0x69, 
+    0x7b, 0x6a, 0x49, 0x6a, 0xe4, 0x6b, 0x8e, 0x6b, 0xa9, 0x6c, 0x3b, 0x6b, 0xc4, 0x6c, 0x05, 0x69, 
+    0x96, 0x69, 0xaa, 0x7c, 0xb3, 0xbe, 0xb0, 0x0b, 0x28, 0x14, 0x75, 0x31, 0x09, 0x12, 0x7c, 0x15, 
+    0x75, 0x6d, 0x10, 0xc0, 0xf1, 0x75, 0xf1, 0x01, 0x43, 0xe1, 0xc0, 0xd0, 0xf1, 0x22, 0xc0, 0xa8, 
+    0xc2, 0xaf, 0x23, 0x6c, 0xaa, 0x2e, 0x54, 0x67, 0x4b, 0x0b, 0x58, 0x50, 0x89, 0x54, 0x01, 0x02, 
+    0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x75, 0x31, 0xb0, 0x12, 0x7c, 0x15, 0x0a, 0x32, 0x09, 0xb3, 
+    0x67, 0x8e, 0x42, 0x32, 0x19, 0x43, 0x00, 0x36, 0xd0, 0xa8, 0x22, 0x7c, 0xb2, 0x23, 0x0a, 0x3b, 
+    0x49, 0x33, 0x67, 0xcb, 0x0a, 0x22, 0x09, 0x32, 0x00, 0x36, 0x09, 0xb2, 0x67, 0x8e, 0xa5, 0xbb, 
+    0x00, 0x05, 0xf4, 0x52, 0x33, 0x80, 0x02, 0x42, 0x33, 0x89, 0x34, 0x67, 0xdb, 0x68, 0x09, 0x68, 
+    0x37, 0x68, 0x65, 0x68, 0x93, 0x68, 0xc1, 0x68, 0xef, 0x69, 0x1d, 0x12, 0x41, 0xb5, 0xd2, 0x28, 
+    0xd2, 0x08, 0xc2, 0x40, 0xc2, 0x48, 0xc2, 0x38, 0xc2, 0x30, 0x6d, 0x00, 0x7a, 0x03, 0x01, 0xcf, 
+    0x7e, 0x04, 0x00, 0x20, 0x7a, 0x07, 0x01, 0xaf, 0x7e, 0x04, 0x00, 0x38, 0x7a, 0x07, 0x01, 0xbf, 
+    0x12, 0x41, 0x16, 0x12, 0x60, 0xcf, 0x02, 0x69, 0x4b, 0x12, 0x41, 0xd4, 0xd2, 0x29, 0xd2, 0x09, 
+    0xc2, 0x41, 0xc2, 0x49, 0xc2, 0x39, 0xc2, 0x31, 0x6d, 0x00, 0x7a, 0x03, 0x01, 0xd0, 0x7e, 0x04, 
+    0x00, 0x20, 0x7a, 0x07, 0x01, 0xb1, 0x7e, 0x04, 0x00, 0x38, 0x7a, 0x07, 0x01, 0xc1, 0x12, 0x41, 
+    0x16, 0x12, 0x61, 0x05, 0x02, 0x69, 0x4b, 0x12, 0x41, 0xf3, 0xd2, 0x2a, 0xd2, 0x0a, 0xc2, 0x42, 
+    0xc2, 0x4a, 0xc2, 0x3a, 0xc2, 0x32, 0x6d, 0x00, 0x7a, 0x03, 0x01, 0xd1, 0x7e, 0x04, 0x00, 0x20, 
+    0x7a, 0x07, 0x01, 0xb3, 0x7e, 0x04, 0x00, 0x38, 0x7a, 0x07, 0x01, 0xc3, 0x12, 0x41, 0x16, 0x12, 
+    0x61, 0x3b, 0x02, 0x69, 0x4b, 0x12, 0x42, 0x12, 0xd2, 0x2b, 0xd2, 0x0b, 0xc2, 0x43, 0xc2, 0x4b, 
+    0xc2, 0x3b, 0xc2, 0x33, 0x6d, 0x00, 0x7a, 0x03, 0x01, 0xd2, 0x7e, 0x04, 0x00, 0x20, 0x7a, 0x07, 
+    0x01, 0xb5, 0x7e, 0x04, 0x00, 0x38, 0x7a, 0x07, 0x01, 0xc5, 0x12, 0x41, 0x16, 0x12, 0x61, 0x71, 
+    0x02, 0x69, 0x4b, 0x12, 0x42, 0x31, 0xd2, 0x2c, 0xd2, 0x0c, 0xc2, 0x44, 0xc2, 0x4c, 0xc2, 0x3c, 
+    0xc2, 0x34, 0x6d, 0x00, 0x7a, 0x03, 0x01, 0xd3, 0x7e, 0x04, 0x00, 0x20, 0x7a, 0x07, 0x01, 0xb7, 
+    0x7e, 0x04, 0x00, 0x38, 0x7a, 0x07, 0x01, 0xc7, 0x12, 0x41, 0x16, 0x12, 0x61, 0xa7, 0x02, 0x69, 
+    0x4b, 0x12, 0x42, 0x50, 0xd2, 0x2d, 0xd2, 0x0d, 0xc2, 0x45, 0xc2, 0x4d, 0xc2, 0x3d, 0xc2, 0x35, 
+    0x6d, 0x00, 0x7a, 0x03, 0x01, 0xd4, 0x7e, 0x04, 0x00, 0x20, 0x7a, 0x07, 0x01, 0xb9, 0x7e, 0x04, 
+    0x00, 0x38, 0x7a, 0x07, 0x01, 0xc9, 0x12, 0x41, 0x16, 0x12, 0x61, 0xdd, 0x02, 0x69, 0x4b, 0x12, 
+    0x42, 0x6f, 0xd2, 0x2e, 0xd2, 0x0e, 0xc2, 0x46, 0xc2, 0x4e, 0xc2, 0x3e, 0xc2, 0x36, 0x6d, 0x00, 
+    0x7a, 0x03, 0x01, 0xd5, 0x7e, 0x04, 0x00, 0x20, 0x7a, 0x07, 0x01, 0xbb, 0x7e, 0x04, 0x00, 0x38, 
+    0x7a, 0x07, 0x01, 0xcb, 0x12, 0x41, 0x16, 0x12, 0x62, 0x13, 0x02, 0x69, 0x4b, 0x12, 0x42, 0x8e, 
+    0xd2, 0x2f, 0xd2, 0x0f, 0xc2, 0x47, 0xc2, 0x4f, 0xc2, 0x3f, 0xc2, 0x37, 0x6d, 0x00, 0x7a, 0x03, 
+    0x01, 0xd6, 0x7e, 0x04, 0x00, 0x20, 0x7a, 0x07, 0x01, 0xbd, 0x7e, 0x04, 0x00, 0x38, 0x7a, 0x07, 
+    0x01, 0xcd, 0x12, 0x41, 0x16, 0x12, 0x62, 0x49, 0x02, 0x69, 0x4b, 0x7e, 0xa0, 0xd0, 0x7e, 0x60, 
+    0x0f, 0x12, 0x62, 0xb6, 0x40, 0x0c, 0xc0, 0xf1, 0x75, 0xf1, 0x01, 0x12, 0x6f, 0xd9, 0xd0, 0xf1, 
+    0xc2, 0xd7, 0x22, 0x75, 0x31, 0xb1, 0x12, 0x7c, 0x15, 0x0a, 0x52, 0x23, 0x6d, 0x00, 0x59, 0x05, 
+    0x00, 0x48, 0x12, 0x41, 0x7e, 0x12, 0x41, 0x9a, 0xd0, 0xa8, 0x22, 0x75, 0x31, 0xb2, 0x12, 0x7c, 
+    0x15, 0x0a, 0x22, 0x09, 0xb2, 0x67, 0x8e, 0x42, 0x23, 0x7e, 0xb0, 0x9c, 0x19, 0xb2, 0x01, 0xcf, 
+    0x12, 0x31, 0x85, 0xd0, 0xa8, 0x22, 0x75, 0x31, 0xb7, 0x12, 0x7c, 0x15, 0x0a, 0x22, 0x09, 0xb2, 
+    0x67, 0x8e, 0x42, 0x24, 0x12, 0x35, 0x3d, 0xd0, 0xa8, 0x22, 0x75, 0x31, 0xb9, 0x12, 0x7c, 0x15, 
+    0x0a, 0x32, 0x09, 0xb3, 0x67, 0x8e, 0x42, 0x34, 0x19, 0x43, 0x00, 0x3e, 0x12, 0x69, 0xc2, 0xd0, 
+    0xa8, 0x22, 0x7c, 0xb2, 0x23, 0x0a, 0x0b, 0x7c, 0xb4, 0x20, 0xe0, 0x04, 0x6d, 0x33, 0x80, 0x04, 
+    0x49, 0x30, 0x01, 0x8f, 0x7e, 0xa0, 0xd8, 0xa5, 0xef, 0xca, 0x0b, 0xca, 0x29, 0x12, 0x62, 0xb6, 
+    0xda, 0x29, 0xda, 0x0b, 0x40, 0x62, 0x75, 0x31, 0xba, 0x12, 0x7c, 0x15, 0x7c, 0xb4, 0x30, 0xe0, 
+    0x1e, 0x6d, 0x33, 0x59, 0x30, 0x01, 0x8f, 0x7e, 0x34, 0x09, 0xe3, 0x0a, 0x82, 0x7e, 0x94, 0x04, 
+    0x00, 0xad, 0x89, 0x2d, 0x39, 0x59, 0x30, 0x01, 0x6f, 0x59, 0x30, 0x01, 0x7f, 0x7c, 0xb4, 0x30, 
+    0xe1, 0x10, 0x7e, 0x04, 0x80, 0x00, 0x4c, 0x02, 0x09, 0xb0, 0x00, 0x08, 0x44, 0x04, 0x19, 0xb0, 
+    0x00, 0x08, 0x0a, 0x02, 0x09, 0xb0, 0x67, 0x8e, 0x42, 0x21, 0xf4, 0x52, 0x34, 0x7c, 0xb2, 0x23, 
+    0x0a, 0x0b, 0xca, 0x19, 0x49, 0x00, 0x30, 0xd5, 0x99, 0x04, 0xda, 0x19, 0xc0, 0xf1, 0x75, 0xf1, 
+    0x01, 0x12, 0x6f, 0xd9, 0xd0, 0xf1, 0xc2, 0xd7, 0x22, 0x7e, 0x04, 0x80, 0x00, 0x4c, 0x02, 0x09, 
+    0x30, 0x00, 0x0c, 0x74, 0xbf, 0x19, 0xb0, 0x00, 0x0c, 0x09, 0xb0, 0x00, 0x08, 0x19, 0x30, 0x00, 
+    0x0c, 0x7c, 0x74, 0x5e, 0x70, 0x01, 0x68, 0x12, 0x44, 0x40, 0xca, 0xb8, 0x09, 0xb0, 0x00, 0x10, 
+    0x44, 0x02, 0x19, 0xb0, 0x00, 0x10, 0xda, 0xb8, 0x80, 0x02, 0x54, 0xbf, 0x7c, 0x74, 0x5e, 0x70, 
+    0x08, 0x68, 0x04, 0x44, 0x08, 0x80, 0x02, 0x54, 0xf7, 0x09, 0x30, 0x00, 0x0c, 0xca, 0xb8, 0x74, 
+    0xbf, 0x19, 0xb0, 0x00, 0x0c, 0xda, 0xb8, 0x19, 0xb0, 0x00, 0x08, 0x19, 0x30, 0x00, 0x0c, 0x0a, 
+    0x62, 0x09, 0xb6, 0x67, 0x8e, 0x3e, 0x20, 0x0a, 0x62, 0x7c, 0x74, 0x5e, 0x70, 0x02, 0x68, 0x20, 
+    0x42, 0x27, 0xca, 0xb8, 0x74, 0x61, 0x19, 0xb0, 0x00, 0x08, 0x7e, 0x44, 0x00, 0x10, 0x59, 0x46, 
+    0x01, 0xbf, 0x09, 0xb0, 0x00, 0x10, 0x44, 0x01, 0x19, 0xb0, 0x00, 0x10, 0xda, 0xb8, 0x80, 0x11, 
+    0xf4, 0x52, 0x27, 0x74, 0xa1, 0x19, 0xb0, 0x00, 0x08, 0x7e, 0x44, 0x00, 0x38, 0x59, 0x46, 0x01, 
+    0xbf, 0xd0, 0xa8, 0x22, 0x7c, 0x74, 0x7e, 0x04, 0x80, 0x00, 0x4c, 0x02, 0x0a, 0x62, 0x09, 0xb6, 
+    0x67, 0x8e, 0xa5, 0xfd, 0xf4, 0xa5, 0xfe, 0xca, 0x28, 0x3e, 0x20, 0x0a, 0x62, 0xa5, 0xee, 0x52, 
+    0x26, 0x7e, 0x44, 0x00, 0x20, 0x59, 0x46, 0x01, 0xaf, 0xda, 0x28, 0x09, 0x30, 0x00, 0x0c, 0x74, 
+    0xbf, 0x19, 0xb0, 0x00, 0x0c, 0x09, 0xb0, 0x00, 0x08, 0x7c, 0x74, 0x5e, 0x70, 0x01, 0x68, 0x0c, 
+    0x44, 0x80, 0xca, 0xb8, 0xa5, 0xed, 0x42, 0x2a, 0xda, 0xb8, 0x80, 0x0a, 0x54, 0x7f, 0xca, 0xb8, 
+    0xa5, 0xee, 0x52, 0x2a, 0xda, 0xb8, 0x7c, 0x74, 0x5e, 0x70, 0x08, 0x68, 0x04, 0x44, 0x02, 0x80, 
+    0x02, 0x54, 0xfd, 0x19, 0xb0, 0x00, 0x08, 0x19, 0x30, 0x00, 0x0c, 0x7c, 0x74, 0x5e, 0x70, 0x02, 
+    0x68, 0x10, 0xa5, 0xed, 0x42, 0x28, 0x42, 0x26, 0x7e, 0x44, 0x00, 0x08, 0x59, 0x46, 0x01, 0xaf, 
+    0x80, 0x04, 0xa5, 0xee, 0x52, 0x28, 0x7c, 0x74, 0x5e, 0x70, 0x04, 0x68, 0x10, 0xa5, 0xed, 0x42, 
+    0x29, 0x42, 0x26, 0x7e, 0x44, 0x00, 0x08, 0x59, 0x46, 0x01, 0xaf, 0x80, 0x0b, 0xa5, 0xee, 0x52, 
+    0x29, 0x7c, 0x74, 0x5e, 0x70, 0x02, 0x78, 0x00, 0x12, 0x42, 0xad, 0xd0, 0xa8, 0x22, 0x7e, 0x04, 
+    0x80, 0x00, 0x4c, 0x02, 0x09, 0x30, 0x00, 0x0c, 0x74, 0xbf, 0x19, 0xb0, 0x00, 0x0c, 0x19, 0x40, 
+    0x00, 0x10, 0x19, 0x30, 0x00, 0x0c, 0xd0, 0xa8, 0x22, 0x7e, 0x04, 0x80, 0x00, 0x4c, 0x02, 0x09, 
+    0x30, 0x00, 0x0c, 0x74, 0xbf, 0x19, 0xb0, 0x00, 0x0c, 0x19, 0x40, 0x00, 0x18, 0x19, 0x30, 0x00, 
+    0x0c, 0xd0, 0xa8, 0x22, 0x75, 0x31, 0xb5, 0x12, 0x7c, 0x15, 0x7e, 0x04, 0x80, 0x00, 0x4c, 0x02, 
+    0x09, 0xb0, 0x00, 0x0c, 0x44, 0x40, 0x19, 0xb0, 0x00, 0x0c, 0xe5, 0x6e, 0xb4, 0x07, 0x23, 0x09, 
+    0xb0, 0x00, 0x10, 0x4e, 0xb0, 0x02, 0x19, 0xb0, 0x00, 0x10, 0x09, 0x30, 0x00, 0x0c, 0x74, 0xbf, 
+    0x19, 0xb0, 0x00, 0x0c, 0x09, 0xb0, 0x00, 0x04, 0x54, 0xf7, 0x19, 0xb0, 0x00, 0x04, 0x19, 0x30, 
+    0x00, 0x0c, 0xd0, 0xa8, 0x22, 0x75, 0x31, 0xb6, 0x12, 0x7c, 0x15, 0x7e, 0x04, 0x80, 0x00, 0x4c, 
+    0x02, 0xe5, 0x6e, 0xb4, 0x07, 0x18, 0x09, 0x30, 0x00, 0x0c, 0x74, 0xbf, 0x19, 0xb0, 0x00, 0x0c, 
+    0x09, 0xb0, 0x00, 0x04, 0x44, 0x08, 0x19, 0xb0, 0x00, 0x04, 0x19, 0x30, 0x00, 0x0c, 0x09, 0xb0, 
+    0x00, 0x0c, 0x54, 0xbf, 0x19, 0xb0, 0x00, 0x0c, 0xd0, 0xa8, 0x22, 0x75, 0x31, 0xb4, 0x12, 0x7c, 
+    0x15, 0x7a, 0x21, 0x31, 0x12, 0x7c, 0x15, 0x7a, 0x41, 0x31, 0x12, 0x7c, 0x15, 0x0a, 0x32, 0x09, 
+    0xb3, 0x67, 0x8e, 0x42, 0x35, 0x12, 0x6c, 0x5b, 0xd0, 0xa8, 0x22, 0x7e, 0xb0, 0x01, 0x7e, 0xa0, 
+    0xc8, 0x7c, 0x64, 0x12, 0x62, 0xb6, 0x40, 0x13, 0x0a, 0x32, 0x09, 0xb3, 0x67, 0x8e, 0xf4, 0x52, 
+    0x35, 0xc0, 0xf1, 0x75, 0xf1, 0x01, 0x12, 0x6f, 0xd9, 0xd0, 0xf1, 0x22, 0x6c, 0x8c, 0x6c, 0xd3, 
+    0x6d, 0x1a, 0x6d, 0x61, 0x6d, 0xa8, 0x6d, 0xef, 0x6e, 0x36, 0x6e, 0x7d, 0x75, 0x31, 0x55, 0x12, 
+    0x7c, 0x15, 0x75, 0x31, 0x00, 0x12, 0x7c, 0x15, 0x7a, 0x61, 0x31, 0x12, 0x7c, 0x15, 0x7a, 0x71, 
+    0x31, 0x12, 0x7c, 0x15, 0x7e, 0x17, 0x01, 0x7f, 0x7e, 0x27, 0x01, 0x8f, 0x2d, 0x23, 0x7e, 0x09, 
+    0xb0, 0x0b, 0x04, 0x7a, 0x19, 0xb0, 0x0b, 0x14, 0xbe, 0x14, 0x0d, 0xe2, 0x38, 0x0f, 0x1b, 0x34, 
+    0x78, 0xec, 0x7a, 0x17, 0x01, 0x7f, 0x7a, 0x27, 0x01, 0x8f, 0x02, 0x46, 0x0f, 0x7e, 0x14, 0x09, 
+    0xe3, 0x80, 0xeb, 0x75, 0x31, 0x55, 0x12, 0x7c, 0x15, 0x75, 0x31, 0x01, 0x12, 0x7c, 0x15, 0x7a, 
+    0x61, 0x31, 0x12, 0x7c, 0x15, 0x7a, 0x71, 0x31, 0x12, 0x7c, 0x15, 0x7e, 0x17, 0x01, 0x81, 0x7e, 
+    0x27, 0x01, 0x91, 0x2d, 0x23, 0x7e, 0x09, 0xb0, 0x0b, 0x04, 0x7a, 0x19, 0xb0, 0x0b, 0x14, 0xbe, 
+    0x14, 0x11, 0xe2, 0x38, 0x0f, 0x1b, 0x34, 0x78, 0xec, 0x7a, 0x17, 0x01, 0x81, 0x7a, 0x27, 0x01, 
+    0x91, 0x02, 0x49, 0x67, 0x7e, 0x14, 0x0d, 0xe3, 0x80, 0xeb, 0x75, 0x31, 0x55, 0x12, 0x7c, 0x15, 
+    0x75, 0x31, 0x02, 0x12, 0x7c, 0x15, 0x7a, 0x61, 0x31, 0x12, 0x7c, 0x15, 0x7a, 0x71, 0x31, 0x12, 
+    0x7c, 0x15, 0x7e, 0x17, 0x01, 0x83, 0x7e, 0x27, 0x01, 0x93, 0x2d, 0x23, 0x7e, 0x09, 0xb0, 0x0b, 
+    0x04, 0x7a, 0x19, 0xb0, 0x0b, 0x14, 0xbe, 0x14, 0x15, 0xe2, 0x38, 0x0f, 0x1b, 0x34, 0x78, 0xec, 
+    0x7a, 0x17, 0x01, 0x83, 0x7a, 0x27, 0x01, 0x93, 0x02, 0x4c, 0xbf, 0x7e, 0x14, 0x11, 0xe3, 0x80, 
+    0xeb, 0x75, 0x31, 0x55, 0x12, 0x7c, 0x15, 0x75, 0x31, 0x03, 0x12, 0x7c, 0x15, 0x7a, 0x61, 0x31, 
+    0x12, 0x7c, 0x15, 0x7a, 0x71, 0x31, 0x12, 0x7c, 0x15, 0x7e, 0x17, 0x01, 0x85, 0x7e, 0x27, 0x01, 
+    0x95, 0x2d, 0x23, 0x7e, 0x09, 0xb0, 0x0b, 0x04, 0x7a, 0x19, 0xb0, 0x0b, 0x14, 0xbe, 0x14, 0x19, 
+    0xe2, 0x38, 0x0f, 0x1b, 0x34, 0x78, 0xec, 0x7a, 0x17, 0x01, 0x85, 0x7a, 0x27, 0x01, 0x95, 0x02, 
+    0x50, 0x17, 0x7e, 0x14, 0x15, 0xe3, 0x80, 0xeb, 0x75, 0x31, 0x55, 0x12, 0x7c, 0x15, 0x75, 0x31, 
+    0x04, 0x12, 0x7c, 0x15, 0x7a, 0x61, 0x31, 0x12, 0x7c, 0x15, 0x7a, 0x71, 0x31, 0x12, 0x7c, 0x15, 
+    0x7e, 0x17, 0x01, 0x87, 0x7e, 0x27, 0x01, 0x97, 0x2d, 0x23, 0x7e, 0x09, 0xb0, 0x0b, 0x04, 0x7a, 
+    0x19, 0xb0, 0x0b, 0x14, 0xbe, 0x14, 0x1d, 0xe2, 0x38, 0x0f, 0x1b, 0x34, 0x78, 0xec, 0x7a, 0x17, 
+    0x01, 0x87, 0x7a, 0x27, 0x01, 0x97, 0x02, 0x53, 0x6f, 0x7e, 0x14, 0x19, 0xe3, 0x80, 0xeb, 0x75, 
+    0x31, 0x55, 0x12, 0x7c, 0x15, 0x75, 0x31, 0x05, 0x12, 0x7c, 0x15, 0x7a, 0x61, 0x31, 0x12, 0x7c, 
+    0x15, 0x7a, 0x71, 0x31, 0x12, 0x7c, 0x15, 0x7e, 0x17, 0x01, 0x89, 0x7e, 0x27, 0x01, 0x99, 0x2d, 
+    0x23, 0x7e, 0x09, 0xb0, 0x0b, 0x04, 0x7a, 0x19, 0xb0, 0x0b, 0x14, 0xbe, 0x14, 0x21, 0xe2, 0x38, 
+    0x0f, 0x1b, 0x34, 0x78, 0xec, 0x7a, 0x17, 0x01, 0x89, 0x7a, 0x27, 0x01, 0x99, 0x02, 0x56, 0xc7, 
+    0x7e, 0x14, 0x1d, 0xe3, 0x80, 0xeb, 0x75, 0x31, 0x55, 0x12, 0x7c, 0x15, 0x75, 0x31, 0x06, 0x12, 
+    0x7c, 0x15, 0x7a, 0x61, 0x31, 0x12, 0x7c, 0x15, 0x7a, 0x71, 0x31, 0x12, 0x7c, 0x15, 0x7e, 0x17, 
+    0x01, 0x8b, 0x7e, 0x27, 0x01, 0x9b, 0x2d, 0x23, 0x7e, 0x09, 0xb0, 0x0b, 0x04, 0x7a, 0x19, 0xb0, 
+    0x0b, 0x14, 0xbe, 0x14, 0x25, 0xe2, 0x38, 0x0f, 0x1b, 0x34, 0x78, 0xec, 0x7a, 0x17, 0x01, 0x8b, 
+    0x7a, 0x27, 0x01, 0x9b, 0x02, 0x5a, 0x1f, 0x7e, 0x14, 0x21, 0xe3, 0x80, 0xeb, 0x75, 0x31, 0x55, 
+    0x12, 0x7c, 0x15, 0x75, 0x31, 0x07, 0x12, 0x7c, 0x15, 0x7a, 0x61, 0x31, 0x12, 0x7c, 0x15, 0x7a, 
+    0x71, 0x31, 0x12, 0x7c, 0x15, 0x7e, 0x17, 0x01, 0x8d, 0x7e, 0x27, 0x01, 0x9d, 0x2d, 0x23, 0x7e, 
+    0x09, 0xb0, 0x0b, 0x04, 0x7a, 0x19, 0xb0, 0x0b, 0x14, 0xbe, 0x14, 0x29, 0xe2, 0x38, 0x0f, 0x1b, 
+    0x34, 0x78, 0xec, 0x7a, 0x17, 0x01, 0x8d, 0x7a, 0x27, 0x01, 0x9d, 0x02, 0x5d, 0x77, 0x7e, 0x14, 
+    0x25, 0xe3, 0x80, 0xeb, 0xca, 0xb8, 0xc0, 0xf1, 0x75, 0x31, 0x02, 0x12, 0x7c, 0x15, 0xe5, 0xc0, 
+    0x54, 0x03, 0x68, 0x05, 0x12, 0x75, 0xcd, 0x80, 0xf5, 0x30, 0xc2, 0x08, 0x75, 0xf1, 0x01, 0x12, 
+    0x6f, 0xd9, 0x80, 0x14, 0x30, 0xc3, 0x08, 0x75, 0xf1, 0x01, 0x12, 0x6e, 0xfd, 0x80, 0x09, 0x30, 
+    0xc4, 0x06, 0x75, 0xf1, 0x02, 0x12, 0x70, 0xe9, 0xd0, 0xf1, 0xda, 0xb8, 0x32, 0x75, 0x31, 0x10, 
+    0x12, 0x7c, 0x15, 0xca, 0x0b, 0xca, 0x39, 0xca, 0x59, 0xc2, 0xc3, 0xa9, 0x21, 0xe2, 0x5c, 0xe5, 
+    0xe5, 0x54, 0xc0, 0x68, 0x4f, 0xe5, 0xe6, 0x6c, 0xaa, 0x7e, 0x37, 0x01, 0xdb, 0x2d, 0x35, 0xbe, 
+    0x34, 0x04, 0x00, 0x38, 0x4a, 0x7a, 0x37, 0x01, 0xdb, 0x7e, 0x37, 0x01, 0xd9, 0x7d, 0x43, 0x2d, 
+    0x45, 0xbe, 0x44, 0x09, 0xe2, 0x38, 0x40, 0x7a, 0x47, 0x01, 0xd9, 0x75, 0x31, 0x11, 0x12, 0x7c, 
+    0x15, 0x7a, 0xb1, 0x31, 0x12, 0x7c, 0x15, 0x12, 0x71, 0xb8, 0xa9, 0x21, 0xe5, 0x1f, 0xa9, 0xd4, 
     0xe4, 0xa9, 0x24, 0xe4, 0xfc, 0xc2, 0xc3, 0xa9, 0x21, 0xe2, 0x3b, 0xe5, 0xe5, 0x54, 0xc0, 0x78, 
-    0xb4, 0x12, 0x76, 0x6a, 0xda, 0x59, 0xda, 0x39, 0xda, 0x0b, 0x22, 0x80, 0x29, 0x80, 0x58, 0x75, 
-    0x2f, 0x16, 0x12, 0x7e, 0x30, 0x80, 0xed, 0x75, 0x2f, 0x12, 0x12, 0x7e, 0x30, 0x7a, 0xb1, 0x2f, 
-    0x12, 0x7e, 0x30, 0x9e, 0x44, 0x09, 0xcd, 0x9d, 0x54, 0x12, 0x73, 0xc8, 0x7e, 0x34, 0x05, 0xcd, 
-    0x7d, 0x54, 0x2d, 0x43, 0x80, 0xa1, 0xe5, 0xe5, 0x54, 0x03, 0x78, 0x12, 0x75, 0x2f, 0x13, 0x12, 
-    0x7e, 0x30, 0x7e, 0x0f, 0x29, 0xe9, 0x0b, 0x0c, 0x7a, 0x0f, 0x29, 0xe9, 0x80, 0xa7, 0x75, 0x2f, 
-    0x14, 0x12, 0x7e, 0x30, 0x7e, 0x0f, 0x29, 0xed, 0x0b, 0x0c, 0x7a, 0x0f, 0x29, 0xed, 0xa9, 0xd7, 
-    0xe4, 0xa9, 0x27, 0xe4, 0xfc, 0x80, 0x9d, 0x75, 0x2f, 0x15, 0x12, 0x7e, 0x30, 0x7e, 0x0f, 0x29, 
-    0xf1, 0x0b, 0x0c, 0x7a, 0x0f, 0x29, 0xf1, 0x80, 0xe5, 0x75, 0x2f, 0x18, 0x12, 0x7e, 0x30, 0xca, 
+    0xb4, 0x12, 0x74, 0x5a, 0xda, 0x59, 0xda, 0x39, 0xda, 0x0b, 0x22, 0x80, 0x29, 0x80, 0x58, 0x75, 
+    0x31, 0x16, 0x12, 0x7c, 0x15, 0x80, 0xed, 0x75, 0x31, 0x12, 0x12, 0x7c, 0x15, 0x7a, 0xb1, 0x31, 
+    0x12, 0x7c, 0x15, 0x9e, 0x44, 0x09, 0xe3, 0x9d, 0x54, 0x12, 0x71, 0xb8, 0x7e, 0x34, 0x05, 0xe3, 
+    0x7d, 0x54, 0x2d, 0x43, 0x80, 0xa1, 0xe5, 0xe5, 0x54, 0x03, 0x78, 0x12, 0x75, 0x31, 0x13, 0x12, 
+    0x7c, 0x15, 0x7e, 0x0f, 0x29, 0xff, 0x0b, 0x0c, 0x7a, 0x0f, 0x29, 0xff, 0x80, 0xa7, 0x75, 0x31, 
+    0x14, 0x12, 0x7c, 0x15, 0x7e, 0x0f, 0x2a, 0x03, 0x0b, 0x0c, 0x7a, 0x0f, 0x2a, 0x03, 0xa9, 0xd7, 
+    0xe4, 0xa9, 0x27, 0xe4, 0xfc, 0x80, 0x9d, 0x75, 0x31, 0x15, 0x12, 0x7c, 0x15, 0x7e, 0x0f, 0x2a, 
+    0x07, 0x0b, 0x0c, 0x7a, 0x0f, 0x2a, 0x07, 0x80, 0xe5, 0x75, 0x31, 0x18, 0x12, 0x7c, 0x15, 0xca, 
     0x09, 0xca, 0x39, 0xca, 0x2b, 0xc2, 0xc2, 0xa9, 0x21, 0xf2, 0x52, 0xe5, 0xf5, 0x33, 0x82, 0xe7, 
-    0x40, 0x44, 0x7e, 0x37, 0x01, 0xcb, 0x7e, 0x54, 0x00, 0x40, 0x9d, 0x35, 0x40, 0x43, 0x7a, 0x37, 
-    0x01, 0xcb, 0x7e, 0x37, 0x01, 0xc7, 0x7d, 0x43, 0x2d, 0x45, 0xbe, 0x44, 0x05, 0xcc, 0x38, 0x52, 
-    0x7a, 0x47, 0x01, 0xc7, 0x7d, 0x45, 0x12, 0x75, 0x26, 0xa9, 0x20, 0xf5, 0x22, 0x75, 0x2f, 0x19, 
-    0x12, 0x7e, 0x30, 0x7a, 0x91, 0x2f, 0x12, 0x7e, 0x30, 0x7a, 0x81, 0xf7, 0x7a, 0x91, 0xf6, 0xe5, 
+    0x40, 0x44, 0x7e, 0x37, 0x01, 0xe1, 0x7e, 0x54, 0x00, 0x40, 0x9d, 0x35, 0x40, 0x43, 0x7a, 0x37, 
+    0x01, 0xe1, 0x7e, 0x37, 0x01, 0xdd, 0x7d, 0x43, 0x2d, 0x45, 0xbe, 0x44, 0x05, 0xe2, 0x38, 0x52, 
+    0x7a, 0x47, 0x01, 0xdd, 0x7d, 0x45, 0x12, 0x73, 0x16, 0xa9, 0x20, 0xf5, 0x22, 0x75, 0x31, 0x19, 
+    0x12, 0x7c, 0x15, 0x7a, 0x91, 0x31, 0x12, 0x7c, 0x15, 0x7a, 0x81, 0xf7, 0x7a, 0x91, 0xf6, 0xe5, 
     0xf5, 0x33, 0x82, 0xe7, 0x50, 0xbc, 0xda, 0x2b, 0xda, 0x39, 0xda, 0x09, 0x22, 0x80, 0x41, 0x80, 
-    0x64, 0x2d, 0x53, 0x6d, 0x33, 0x70, 0xb7, 0x7e, 0x04, 0x01, 0xcd, 0x7a, 0x07, 0x01, 0xc9, 0x7a, 
-    0x07, 0x01, 0xc7, 0xa9, 0x32, 0xf2, 0xdf, 0x85, 0x30, 0x2f, 0x12, 0x7e, 0x30, 0x75, 0xf6, 0x00, 
-    0x80, 0xd4, 0xca, 0x59, 0x9e, 0x44, 0x05, 0xcd, 0x9d, 0x54, 0x12, 0x75, 0x26, 0x7e, 0x34, 0x01, 
-    0xcd, 0x7d, 0x54, 0x2d, 0x43, 0x7a, 0x47, 0x01, 0xc7, 0x12, 0x75, 0x26, 0xda, 0x49, 0x80, 0x99, 
-    0xe5, 0xf5, 0x54, 0x03, 0x78, 0x1f, 0x7e, 0x0f, 0x29, 0xd9, 0x0b, 0x0c, 0x7a, 0x0f, 0x29, 0xd9, 
-    0x80, 0x9d, 0x7e, 0x0f, 0x29, 0xe1, 0x0b, 0x0c, 0x7a, 0x0f, 0x29, 0xe1, 0xa9, 0xd7, 0xf4, 0xa9, 
-    0x27, 0xf4, 0xfc, 0x80, 0x8a, 0x7e, 0x0f, 0x29, 0xdd, 0x0b, 0x0c, 0x7a, 0x0f, 0x29, 0xdd, 0x80, 
-    0xeb, 0xe5, 0xf5, 0x54, 0x03, 0x78, 0x1f, 0x7e, 0x2f, 0x29, 0xf9, 0x0b, 0x2c, 0x7a, 0x2f, 0x29, 
-    0xf9, 0x80, 0x34, 0x7e, 0x2f, 0x2a, 0x01, 0x0b, 0x2c, 0x7a, 0x2f, 0x2a, 0x01, 0xa9, 0xd7, 0xf4, 
-    0xa9, 0x27, 0xf4, 0xfc, 0x80, 0x21, 0x7e, 0x2f, 0x29, 0xfd, 0x0b, 0x2c, 0x7a, 0x2f, 0x29, 0xfd, 
-    0x80, 0xeb, 0xda, 0x2b, 0xda, 0x1b, 0xda, 0x0b, 0x22, 0x75, 0x2f, 0x28, 0x12, 0x7e, 0x30, 0xca, 
+    0x64, 0x2d, 0x53, 0x6d, 0x33, 0x70, 0xb7, 0x7e, 0x04, 0x01, 0xe3, 0x7a, 0x07, 0x01, 0xdf, 0x7a, 
+    0x07, 0x01, 0xdd, 0xa9, 0x32, 0xf2, 0xdf, 0x85, 0x30, 0x31, 0x12, 0x7c, 0x15, 0x75, 0xf6, 0x00, 
+    0x80, 0xd4, 0xca, 0x59, 0x9e, 0x44, 0x05, 0xe3, 0x9d, 0x54, 0x12, 0x73, 0x16, 0x7e, 0x34, 0x01, 
+    0xe3, 0x7d, 0x54, 0x2d, 0x43, 0x7a, 0x47, 0x01, 0xdd, 0x12, 0x73, 0x16, 0xda, 0x49, 0x80, 0x99, 
+    0xe5, 0xf5, 0x54, 0x03, 0x78, 0x1f, 0x7e, 0x0f, 0x29, 0xef, 0x0b, 0x0c, 0x7a, 0x0f, 0x29, 0xef, 
+    0x80, 0x9d, 0x7e, 0x0f, 0x29, 0xf7, 0x0b, 0x0c, 0x7a, 0x0f, 0x29, 0xf7, 0xa9, 0xd7, 0xf4, 0xa9, 
+    0x27, 0xf4, 0xfc, 0x80, 0x8a, 0x7e, 0x0f, 0x29, 0xf3, 0x0b, 0x0c, 0x7a, 0x0f, 0x29, 0xf3, 0x80, 
+    0xeb, 0xe5, 0xf5, 0x54, 0x03, 0x78, 0x1f, 0x7e, 0x2f, 0x2a, 0x0f, 0x0b, 0x2c, 0x7a, 0x2f, 0x2a, 
+    0x0f, 0x80, 0x34, 0x7e, 0x2f, 0x2a, 0x17, 0x0b, 0x2c, 0x7a, 0x2f, 0x2a, 0x17, 0xa9, 0xd7, 0xf4, 
+    0xa9, 0x27, 0xf4, 0xfc, 0x80, 0x21, 0x7e, 0x2f, 0x2a, 0x13, 0x0b, 0x2c, 0x7a, 0x2f, 0x2a, 0x13, 
+    0x80, 0xeb, 0xda, 0x2b, 0xda, 0x1b, 0xda, 0x0b, 0x22, 0x75, 0x31, 0x28, 0x12, 0x7c, 0x15, 0xca, 
     0x0b, 0xca, 0x1b, 0xca, 0x2b, 0xc2, 0xc4, 0xa9, 0x21, 0xf2, 0xb6, 0xe5, 0xf5, 0x33, 0x72, 0xe7, 
-    0x40, 0xe0, 0x7e, 0x0d, 0x30, 0x7e, 0x1d, 0x34, 0x7e, 0x2d, 0x38, 0x7e, 0x3d, 0x3c, 0x7e, 0x85, 
-    0x40, 0x7d, 0x90, 0x4d, 0x91, 0x4d, 0x92, 0x4d, 0x93, 0x4d, 0x94, 0x4d, 0x95, 0x4d, 0x96, 0x4d, 
+    0x40, 0xe0, 0x7e, 0x0d, 0x46, 0x7e, 0x1d, 0x4a, 0x7e, 0x2d, 0x4e, 0x7e, 0x3d, 0x52, 0x7e, 0x85, 
+    0x56, 0x7d, 0x90, 0x4d, 0x91, 0x4d, 0x92, 0x4d, 0x93, 0x4d, 0x94, 0x4d, 0x95, 0x4d, 0x96, 0x4d, 
     0x97, 0x4d, 0x98, 0x68, 0x72, 0x7a, 0x11, 0xf3, 0x7a, 0x01, 0xf3, 0x7a, 0x31, 0xf3, 0x7a, 0x21, 
     0xf3, 0x7a, 0x51, 0xf3, 0x7a, 0x41, 0xf3, 0x7a, 0x71, 0xf3, 0x7a, 0x61, 0xf3, 0x7a, 0x91, 0xf3, 
-    0x7a, 0x81, 0xf3, 0x30, 0x73, 0x1a, 0x7a, 0xb1, 0xf3, 0x7a, 0xa1, 0xf3, 0x7a, 0xd1, 0xf3, 0x7a, 
+    0x7a, 0x81, 0xf3, 0x30, 0x7b, 0x1a, 0x7a, 0xb1, 0xf3, 0x7a, 0xa1, 0xf3, 0x7a, 0xd1, 0xf3, 0x7a, 
     0xc1, 0xf3, 0x7a, 0xf1, 0xf3, 0x7a, 0xe1, 0xf3, 0x7d, 0x78, 0x7a, 0xf1, 0xf3, 0x7a, 0xe1, 0xf3, 
-    0xa9, 0x30, 0xf5, 0x03, 0x02, 0x72, 0xe6, 0x75, 0x2f, 0x29, 0x12, 0x7e, 0x30, 0x20, 0x73, 0x0b, 
-    0x75, 0x2f, 0x0a, 0x12, 0x7e, 0x30, 0x75, 0xf6, 0x0a, 0x80, 0x09, 0x75, 0x2f, 0x12, 0x12, 0x7e, 
-    0x30, 0x75, 0xf6, 0x12, 0x6d, 0x00, 0x7d, 0x10, 0x7a, 0x0d, 0x30, 0x7a, 0x0d, 0x34, 0x7a, 0x0d, 
-    0x38, 0x7a, 0x0d, 0x3c, 0x7a, 0x05, 0x40, 0xda, 0x2b, 0xda, 0x1b, 0xda, 0x0b, 0x22, 0x1e, 0xb0, 
-    0x40, 0x0c, 0x7e, 0xa0, 0x0a, 0xa4, 0x7e, 0x04, 0x75, 0x0b, 0x9d, 0x05, 0x89, 0x04, 0x7e, 0xa1, 
+    0xa9, 0x30, 0xf5, 0x03, 0x02, 0x70, 0xd6, 0x75, 0x31, 0x29, 0x12, 0x7c, 0x15, 0x20, 0x7b, 0x0b, 
+    0x75, 0x31, 0x0a, 0x12, 0x7c, 0x15, 0x75, 0xf6, 0x0a, 0x80, 0x09, 0x75, 0x31, 0x12, 0x12, 0x7c, 
+    0x15, 0x75, 0xf6, 0x12, 0x6d, 0x00, 0x7d, 0x10, 0x7a, 0x0d, 0x46, 0x7a, 0x0d, 0x4a, 0x7a, 0x0d, 
+    0x4e, 0x7a, 0x0d, 0x52, 0x7a, 0x05, 0x56, 0xda, 0x2b, 0xda, 0x1b, 0xda, 0x0b, 0x22, 0x1e, 0xb0, 
+    0x40, 0x0c, 0x7e, 0xa0, 0x0a, 0xa4, 0x7e, 0x04, 0x72, 0xfb, 0x9d, 0x05, 0x89, 0x04, 0x7e, 0xa1, 
     0xe3, 0x7a, 0x39, 0xa0, 0x0b, 0x34, 0x80, 0xea, 0xb4, 0x40, 0xe3, 0x7e, 0xa1, 0xe3, 0xe5, 0xe3, 
     0x1b, 0x38, 0x50, 0x0b, 0x35, 0x7e, 0xa1, 0xe3, 0xe5, 0xe3, 0x1b, 0x38, 0x50, 0x0b, 0x35, 0x7e, 
     0xa1, 0xe3, 0xe5, 0xe3, 0x1b, 0x38, 0x50, 0x0b, 0x35, 0x7e, 0xa1, 0xe3, 0xe5, 0xe3, 0x1b, 0x38, 
@@ -937,7 +1044,7 @@
     0x50, 0x0b, 0x35, 0x7e, 0xa1, 0xe3, 0xe5, 0xe3, 0x1b, 0x38, 0x50, 0x0b, 0x35, 0x7e, 0xa1, 0xe3, 
     0xe5, 0xe3, 0x1b, 0x38, 0x50, 0x0b, 0x35, 0x7e, 0xa1, 0xe3, 0xe5, 0xe3, 0x1b, 0x38, 0x50, 0x0b, 
     0x35, 0x7e, 0xa1, 0xe3, 0xe5, 0xe3, 0x1b, 0x38, 0x50, 0x0b, 0x35, 0x22, 0x1e, 0xb0, 0x40, 0x0c, 
-    0x7e, 0xa0, 0x0a, 0xa4, 0x7e, 0x04, 0x76, 0x69, 0x9d, 0x05, 0x89, 0x04, 0x7e, 0x39, 0xa0, 0x7a, 
+    0x7e, 0xa0, 0x0a, 0xa4, 0x7e, 0x04, 0x74, 0x59, 0x9d, 0x05, 0x89, 0x04, 0x7e, 0x39, 0xa0, 0x7a, 
     0xa1, 0xf3, 0x0b, 0x34, 0x80, 0xea, 0xb4, 0x40, 0xe3, 0x0b, 0x38, 0x50, 0x7a, 0xa1, 0xf3, 0xf5, 
     0xf3, 0x0b, 0x35, 0x0b, 0x38, 0x50, 0x7a, 0xa1, 0xf3, 0xf5, 0xf3, 0x0b, 0x35, 0x0b, 0x38, 0x50, 
     0x7a, 0xa1, 0xf3, 0xf5, 0xf3, 0x0b, 0x35, 0x0b, 0x38, 0x50, 0x7a, 0xa1, 0xf3, 0xf5, 0xf3, 0x0b, 
@@ -958,144 +1065,144 @@
     0x7a, 0xa1, 0xf3, 0xf5, 0xf3, 0x0b, 0x35, 0x0b, 0x38, 0x50, 0x7a, 0xa1, 0xf3, 0xf5, 0xf3, 0x0b, 
     0x35, 0x0b, 0x38, 0x50, 0x7a, 0xa1, 0xf3, 0xf5, 0xf3, 0x0b, 0x35, 0x0b, 0x38, 0x50, 0x7a, 0xa1, 
     0xf3, 0xf5, 0xf3, 0x0b, 0x35, 0x0b, 0x38, 0x50, 0x7a, 0xa1, 0xf3, 0xf5, 0xf3, 0x0b, 0x35, 0x0b, 
-    0x38, 0x50, 0x7a, 0xa1, 0xf3, 0xf5, 0xf3, 0x0b, 0x35, 0x22, 0xc2, 0xaf, 0x7e, 0x37, 0x01, 0xc5, 
-    0x4d, 0x33, 0x68, 0x3b, 0x7e, 0x07, 0x01, 0xc1, 0x7e, 0x54, 0x09, 0xcd, 0x9d, 0x50, 0xbd, 0x35, 
-    0x40, 0x02, 0x7d, 0x35, 0xca, 0x39, 0x7e, 0x65, 0x4b, 0x99, 0x64, 0xda, 0x39, 0x7e, 0x07, 0x01, 
-    0xc5, 0x9d, 0x03, 0x7a, 0x07, 0x01, 0xc5, 0x2e, 0x37, 0x01, 0xc1, 0x7a, 0x37, 0x01, 0xc1, 0xbe, 
-    0x34, 0x09, 0xcc, 0x28, 0xc7, 0x7e, 0x34, 0x05, 0xcd, 0x7a, 0x37, 0x01, 0xc1, 0x80, 0xbd, 0xd2, 
-    0xaf, 0x22, 0x75, 0x2f, 0x53, 0x12, 0x7e, 0x30, 0x7e, 0x15, 0x4d, 0x80, 0x11, 0x75, 0x2f, 0x51, 
-    0x12, 0x7e, 0x30, 0x0b, 0x08, 0x10, 0x0b, 0x05, 0x9e, 0x34, 0x00, 0x02, 0x28, 0x4d, 0x7c, 0xb2, 
-    0x20, 0xe7, 0x27, 0x54, 0x07, 0x23, 0x0a, 0x2b, 0x49, 0x22, 0x6e, 0x8c, 0x7c, 0xb2, 0x54, 0x78, 
-    0x03, 0x03, 0x03, 0x7c, 0x2b, 0x9d, 0x13, 0x40, 0x1a, 0x68, 0x12, 0x7a, 0x15, 0x4d, 0x7a, 0x25, 
-    0x4f, 0x7e, 0x64, 0x77, 0x47, 0x7a, 0x65, 0x4b, 0x89, 0x24, 0x02, 0x77, 0x55, 0x7e, 0x64, 0x76, 
-    0xbd, 0x80, 0xf2, 0x2d, 0x13, 0x9d, 0x31, 0xca, 0x39, 0x7d, 0x31, 0x2d, 0x10, 0xca, 0x19, 0xca, 
-    0x29, 0x99, 0x24, 0xda, 0x29, 0xda, 0x09, 0xda, 0x39, 0x80, 0xa2, 0x7a, 0x15, 0x4d, 0x7e, 0x64, 
-    0x77, 0x33, 0x4d, 0x33, 0x78, 0x09, 0x7c, 0xb2, 0x20, 0xe7, 0x2a, 0x7e, 0x64, 0x76, 0xb2, 0x7a, 
-    0x65, 0x4b, 0x22, 0x75, 0x2f, 0x52, 0x12, 0x7e, 0x30, 0x7e, 0x21, 0x4d, 0x7e, 0x09, 0x30, 0x0b, 
-    0x04, 0x1b, 0x34, 0x78, 0x89, 0x80, 0xd4, 0x75, 0x2f, 0x54, 0x12, 0x7e, 0x30, 0x7e, 0x15, 0x4d, 
-    0x7e, 0x25, 0x4f, 0x80, 0x90, 0x5e, 0x20, 0x07, 0x54, 0x78, 0x7e, 0x44, 0x77, 0xd1, 0x30, 0xe6, 
-    0x16, 0x4d, 0x33, 0x68, 0x26, 0x1b, 0x34, 0x7e, 0x09, 0x40, 0x0b, 0x04, 0x7e, 0x44, 0x6a, 0x68, 
-    0x20, 0xe3, 0x04, 0x7e, 0x44, 0x77, 0xd9, 0xca, 0x09, 0xca, 0x39, 0x99, 0x44, 0xda, 0x39, 0xda, 
-    0x09, 0x7e, 0x64, 0x76, 0xbd, 0x4d, 0x33, 0x68, 0xa6, 0x89, 0x64, 0x7a, 0x15, 0x4d, 0xf5, 0x4f, 
-    0x7e, 0x64, 0x77, 0x96, 0x80, 0x99, 0x7e, 0x15, 0x4d, 0xe5, 0x4f, 0x80, 0xc4, 0xc0, 0xd0, 0xc0, 
-    0xd1, 0xc0, 0xe0, 0xca, 0x19, 0xa9, 0x20, 0xdf, 0x12, 0xa9, 0x21, 0xdf, 0x1b, 0x75, 0x2f, 0x01, 
-    0x12, 0x7e, 0x30, 0x53, 0xdf, 0xf7, 0x12, 0x40, 0xdc, 0x80, 0x0d, 0x75, 0x2f, 0xfe, 0x12, 0x7e, 
-    0x30, 0x7e, 0x14, 0x00, 0x53, 0x02, 0x40, 0x51, 0xda, 0x19, 0xd0, 0xe0, 0xd0, 0xd1, 0xd0, 0xd0, 
-    0x32, 0x03, 0xa5, 0xcb, 0x19, 0xb1, 0x80, 0x00, 0x22, 0x22, 0x02, 0x78, 0x52, 0xca, 0x0b, 0xca, 
+    0x38, 0x50, 0x7a, 0xa1, 0xf3, 0xf5, 0xf3, 0x0b, 0x35, 0x22, 0xc2, 0xaf, 0x7e, 0x37, 0x01, 0xdb, 
+    0x4d, 0x33, 0x68, 0x3b, 0x7e, 0x07, 0x01, 0xd7, 0x7e, 0x54, 0x09, 0xe3, 0x9d, 0x50, 0xbd, 0x35, 
+    0x40, 0x02, 0x7d, 0x35, 0xca, 0x39, 0x7e, 0x65, 0x61, 0x99, 0x64, 0xda, 0x39, 0x7e, 0x07, 0x01, 
+    0xdb, 0x9d, 0x03, 0x7a, 0x07, 0x01, 0xdb, 0x2e, 0x37, 0x01, 0xd7, 0x7a, 0x37, 0x01, 0xd7, 0xbe, 
+    0x34, 0x09, 0xe2, 0x28, 0xc7, 0x7e, 0x34, 0x05, 0xe3, 0x7a, 0x37, 0x01, 0xd7, 0x80, 0xbd, 0xd2, 
+    0xaf, 0x22, 0x75, 0x31, 0x53, 0x12, 0x7c, 0x15, 0x7e, 0x15, 0x63, 0x80, 0x11, 0x75, 0x31, 0x51, 
+    0x12, 0x7c, 0x15, 0x0b, 0x08, 0x10, 0x0b, 0x05, 0x9e, 0x34, 0x00, 0x02, 0x28, 0x4d, 0x7c, 0xb2, 
+    0x20, 0xe7, 0x27, 0x54, 0x07, 0x23, 0x0a, 0x2b, 0x49, 0x22, 0x6c, 0x7c, 0x7c, 0xb2, 0x54, 0x78, 
+    0x03, 0x03, 0x03, 0x7c, 0x2b, 0x9d, 0x13, 0x40, 0x1a, 0x68, 0x12, 0x7a, 0x15, 0x63, 0x7a, 0x25, 
+    0x65, 0x7e, 0x64, 0x75, 0x37, 0x7a, 0x65, 0x61, 0x89, 0x24, 0x02, 0x75, 0x45, 0x7e, 0x64, 0x74, 
+    0xad, 0x80, 0xf2, 0x2d, 0x13, 0x9d, 0x31, 0xca, 0x39, 0x7d, 0x31, 0x2d, 0x10, 0xca, 0x19, 0xca, 
+    0x29, 0x99, 0x24, 0xda, 0x29, 0xda, 0x09, 0xda, 0x39, 0x80, 0xa2, 0x7a, 0x15, 0x63, 0x7e, 0x64, 
+    0x75, 0x23, 0x4d, 0x33, 0x78, 0x09, 0x7c, 0xb2, 0x20, 0xe7, 0x2a, 0x7e, 0x64, 0x74, 0xa2, 0x7a, 
+    0x65, 0x61, 0x22, 0x75, 0x31, 0x52, 0x12, 0x7c, 0x15, 0x7e, 0x21, 0x63, 0x7e, 0x09, 0x30, 0x0b, 
+    0x04, 0x1b, 0x34, 0x78, 0x89, 0x80, 0xd4, 0x75, 0x31, 0x54, 0x12, 0x7c, 0x15, 0x7e, 0x15, 0x63, 
+    0x7e, 0x25, 0x65, 0x80, 0x90, 0x5e, 0x20, 0x07, 0x54, 0x78, 0x7e, 0x44, 0x75, 0xc1, 0x30, 0xe6, 
+    0x16, 0x4d, 0x33, 0x68, 0x26, 0x1b, 0x34, 0x7e, 0x09, 0x40, 0x0b, 0x04, 0x7e, 0x44, 0x67, 0x63, 
+    0x20, 0xe3, 0x04, 0x7e, 0x44, 0x75, 0xc9, 0xca, 0x09, 0xca, 0x39, 0x99, 0x44, 0xda, 0x39, 0xda, 
+    0x09, 0x7e, 0x64, 0x74, 0xad, 0x4d, 0x33, 0x68, 0xa6, 0x89, 0x64, 0x7a, 0x15, 0x63, 0xf5, 0x65, 
+    0x7e, 0x64, 0x75, 0x86, 0x80, 0x99, 0x7e, 0x15, 0x63, 0xe5, 0x65, 0x80, 0xc4, 0xc0, 0xd0, 0xc0, 
+    0xd1, 0xc0, 0xe0, 0xca, 0x19, 0xa9, 0x20, 0xdf, 0x12, 0xa9, 0x21, 0xdf, 0x1b, 0x75, 0x31, 0x01, 
+    0x12, 0x7c, 0x15, 0x53, 0xdf, 0xf7, 0x12, 0x40, 0xdc, 0x80, 0x0d, 0x75, 0x31, 0xfe, 0x12, 0x7c, 
+    0x15, 0x7e, 0x14, 0x00, 0x53, 0x02, 0x40, 0x51, 0xda, 0x19, 0xd0, 0xe0, 0xd0, 0xd1, 0xd0, 0xd0, 
+    0x32, 0x03, 0xa5, 0xcb, 0x19, 0xb1, 0x80, 0x00, 0x22, 0x22, 0x02, 0x76, 0x42, 0xca, 0x0b, 0xca, 
     0x1b, 0xca, 0x2b, 0xca, 0x3b, 0xca, 0x4b, 0xca, 0x5b, 0xca, 0x6b, 0xca, 0x7b, 0xca, 0xeb, 0xc0, 
-    0xf1, 0x7e, 0xb3, 0x2a, 0x1d, 0xb4, 0x00, 0x02, 0x80, 0x19, 0xb4, 0x01, 0x16, 0x30, 0xc0, 0x08, 
-    0x75, 0xf1, 0x00, 0x12, 0x78, 0x3c, 0x80, 0x1f, 0x30, 0xc1, 0x1c, 0x75, 0xf1, 0x00, 0x12, 0x78, 
-    0xcd, 0x80, 0x14, 0x30, 0xc1, 0x08, 0x75, 0xf1, 0x00, 0x12, 0x78, 0xcd, 0x80, 0x09, 0x30, 0xc0, 
-    0x06, 0x75, 0xf1, 0x00, 0x12, 0x78, 0x3c, 0xd0, 0xf1, 0xda, 0xeb, 0xda, 0x7b, 0xda, 0x6b, 0xda, 
+    0xf1, 0x7e, 0xb3, 0x2a, 0x33, 0xb4, 0x00, 0x02, 0x80, 0x19, 0xb4, 0x01, 0x16, 0x30, 0xc0, 0x08, 
+    0x75, 0xf1, 0x00, 0x12, 0x76, 0x2c, 0x80, 0x1f, 0x30, 0xc1, 0x1c, 0x75, 0xf1, 0x00, 0x12, 0x76, 
+    0xbd, 0x80, 0x14, 0x30, 0xc1, 0x08, 0x75, 0xf1, 0x00, 0x12, 0x76, 0xbd, 0x80, 0x09, 0x30, 0xc0, 
+    0x06, 0x75, 0xf1, 0x00, 0x12, 0x76, 0x2c, 0xd0, 0xf1, 0xda, 0xeb, 0xda, 0x7b, 0xda, 0x6b, 0xda, 
     0x5b, 0xda, 0x4b, 0xda, 0x3b, 0xda, 0x2b, 0xda, 0x1b, 0xda, 0x0b, 0x22, 0xc2, 0xc0, 0x7e, 0xb3, 
-    0x2a, 0x1d, 0xb4, 0x02, 0x07, 0x12, 0x78, 0x5e, 0x02, 0x78, 0x52, 0x22, 0xb4, 0x01, 0xfc, 0x02, 
-    0x78, 0x98, 0x7e, 0x00, 0x00, 0x7a, 0x03, 0x2a, 0x1d, 0x7a, 0x03, 0x2a, 0x1e, 0x22, 0x7e, 0xb3, 
-    0x2a, 0x15, 0x54, 0x60, 0x60, 0x05, 0xb4, 0x40, 0x15, 0x80, 0x13, 0x7e, 0xb3, 0x2a, 0x16, 0xb4, 
-    0x05, 0x0c, 0x75, 0x2f, 0x71, 0x12, 0x7e, 0x30, 0x7e, 0xb3, 0x2a, 0x18, 0xf5, 0x8f, 0x22, 0x75, 
-    0xf6, 0x00, 0x22, 0xbe, 0x57, 0x2a, 0x1b, 0x28, 0x04, 0x7e, 0x57, 0x2a, 0x1b, 0x7a, 0x0f, 0x2a, 
-    0x20, 0x7a, 0x57, 0x2a, 0x24, 0x02, 0x78, 0x98, 0x7e, 0xef, 0x2a, 0x20, 0x7e, 0xf7, 0x2a, 0x24, 
-    0x7e, 0x07, 0x2a, 0x24, 0x4d, 0x00, 0x68, 0x21, 0x7e, 0x00, 0x00, 0x7e, 0xeb, 0xb0, 0xf5, 0xf3, 
-    0xa3, 0xa5, 0x08, 0x1b, 0xf4, 0x68, 0x04, 0xa5, 0xb8, 0x08, 0xf0, 0x7a, 0xef, 0x2a, 0x20, 0x7a, 
-    0xf7, 0x2a, 0x24, 0x75, 0x2f, 0x06, 0x12, 0x7e, 0x30, 0x7a, 0x01, 0xf6, 0x22, 0xc2, 0xc1, 0x75, 
-    0x2f, 0x03, 0x12, 0x7e, 0x30, 0xa9, 0x36, 0xe2, 0x16, 0xe5, 0xf5, 0x54, 0xc0, 0x68, 0x07, 0xa9, 
-    0xd7, 0xf4, 0xa9, 0x27, 0xf4, 0xfc, 0x53, 0xe1, 0x3f, 0x43, 0xf2, 0x88, 0x02, 0x79, 0x44, 0x7e, 
-    0xb3, 0x2a, 0x1e, 0xb4, 0x02, 0x0f, 0xa9, 0xd4, 0xe4, 0x7e, 0xb0, 0x00, 0x7a, 0xb3, 0x2a, 0x1e, 
-    0x7a, 0xb3, 0x2a, 0x1d, 0x22, 0xb4, 0x01, 0x39, 0x7e, 0x21, 0xe6, 0x7c, 0x32, 0x7e, 0x13, 0x2a, 
-    0x1f, 0x2c, 0x21, 0x7a, 0x23, 0x2a, 0x1f, 0x7e, 0x00, 0x00, 0x2e, 0x04, 0x2a, 0x26, 0xe5, 0xe3, 
-    0x7a, 0x09, 0xb0, 0x0b, 0x04, 0xa5, 0xdb, 0xf6, 0xa9, 0xd4, 0xe4, 0x75, 0x2f, 0x70, 0x12, 0x7e, 
-    0x30, 0x7e, 0xb3, 0x2a, 0x1f, 0x7e, 0xa3, 0x2a, 0x1c, 0xbc, 0xab, 0x78, 0x03, 0x12, 0x79, 0xdb, 
-    0x22, 0x02, 0x7d, 0x44, 0xe5, 0xe6, 0xb4, 0x08, 0x65, 0xa9, 0xc4, 0xe2, 0x7e, 0x01, 0xe3, 0x7e, 
-    0x11, 0xe3, 0x7e, 0x31, 0xe3, 0x7e, 0x21, 0xe3, 0x7e, 0x51, 0xe3, 0x7e, 0x41, 0xe3, 0x7e, 0x71, 
-    0xe3, 0x7e, 0x61, 0xe3, 0x7a, 0x0f, 0x2a, 0x15, 0x7a, 0x1f, 0x2a, 0x19, 0x75, 0x2f, 0x04, 0x12, 
-    0x7e, 0x30, 0x7a, 0x01, 0x2f, 0x12, 0x7e, 0x30, 0x7a, 0x11, 0x2f, 0x12, 0x7e, 0x30, 0x7a, 0x21, 
-    0x2f, 0x12, 0x7e, 0x30, 0x7a, 0x31, 0x2f, 0x12, 0x7e, 0x30, 0x7a, 0x41, 0x2f, 0x12, 0x7e, 0x30, 
-    0x7a, 0x51, 0x2f, 0x12, 0x7e, 0x30, 0x7a, 0x61, 0x2f, 0x12, 0x7e, 0x30, 0x7a, 0x71, 0x2f, 0x12, 
-    0x7e, 0x30, 0xa9, 0xd4, 0xe4, 0xa9, 0xd7, 0xf4, 0xa9, 0xc6, 0xe2, 0x12, 0x79, 0xaf, 0x22, 0x6d, 
-    0x00, 0x7e, 0x14, 0x01, 0x02, 0x7a, 0x07, 0x2a, 0x24, 0x7a, 0x03, 0x2a, 0x1f, 0x7e, 0xb3, 0x2a, 
-    0x15, 0x20, 0xe7, 0x0f, 0x7a, 0x23, 0x2a, 0x1e, 0x7a, 0x33, 0x2a, 0x1d, 0xbe, 0x07, 0x2a, 0x1b, 
-    0x68, 0x09, 0x22, 0x7a, 0x33, 0x2a, 0x1e, 0x7a, 0x23, 0x2a, 0x1d, 0x7e, 0xb3, 0x2a, 0x15, 0x54, 
-    0xe3, 0x23, 0x23, 0x30, 0xe0, 0x02, 0xd2, 0xe5, 0x30, 0xe7, 0x02, 0xd2, 0xe4, 0x30, 0xe5, 0x06, 
-    0x30, 0xe4, 0x03, 0x02, 0x7d, 0x44, 0x54, 0x3e, 0xf5, 0xf0, 0x03, 0x54, 0x1f, 0xc3, 0x25, 0xf0, 
-    0x90, 0x7a, 0x07, 0x75, 0x84, 0xff, 0x73, 0x02, 0x7b, 0x5b, 0x02, 0x7a, 0x4f, 0x02, 0x7b, 0xf8, 
-    0x02, 0x7c, 0x13, 0x02, 0x7a, 0xf4, 0x02, 0x7a, 0xb5, 0x02, 0x7c, 0x2c, 0x02, 0x7c, 0x2c, 0x02, 
-    0x7c, 0x2f, 0x02, 0x7c, 0x2f, 0x02, 0x7c, 0x2f, 0x02, 0x7c, 0x2f, 0x02, 0x7c, 0x2f, 0x02, 0x7c, 
-    0x2f, 0x02, 0x7c, 0x2f, 0x02, 0x7c, 0x2f, 0x02, 0x7c, 0x35, 0x02, 0x7c, 0xe9, 0x02, 0x7c, 0x32, 
-    0x02, 0x7c, 0x32, 0x02, 0x7c, 0x32, 0x02, 0x7c, 0x32, 0x02, 0x7c, 0x32, 0x02, 0x7c, 0x32, 0x7e, 
-    0xb3, 0x2a, 0x16, 0xb4, 0x06, 0x2a, 0x7e, 0xb3, 0x2a, 0x17, 0x60, 0x56, 0x7c, 0x0b, 0x7e, 0x13, 
-    0x2a, 0x18, 0x7e, 0x17, 0x2a, 0x19, 0x75, 0x2f, 0x72, 0x12, 0x7e, 0x30, 0x7a, 0x01, 0x2f, 0x12, 
-    0x7e, 0x30, 0x7a, 0x11, 0x2f, 0x12, 0x7e, 0x30, 0x12, 0x7d, 0x4e, 0x40, 0x35, 0x02, 0x78, 0x83, 
-    0xb4, 0x08, 0x10, 0x75, 0x2f, 0x74, 0x12, 0x7e, 0x30, 0x7e, 0xb3, 0x3f, 0xf1, 0xf5, 0xf3, 0x75, 
-    0xf6, 0x01, 0x22, 0xb4, 0x00, 0x1c, 0x75, 0x2f, 0x75, 0x12, 0x7e, 0x30, 0x7e, 0xb3, 0x3f, 0xf2, 
-    0x30, 0xe0, 0x05, 0x75, 0xf3, 0x02, 0x80, 0x03, 0x75, 0xf3, 0x00, 0x75, 0xf3, 0x00, 0x75, 0xf6, 
-    0x02, 0x22, 0x02, 0x7d, 0x44, 0x7e, 0xb3, 0x2a, 0x16, 0xb4, 0x00, 0x35, 0x75, 0x2f, 0x76, 0x12, 
-    0x7e, 0x30, 0x7e, 0xb3, 0x2a, 0x1a, 0x54, 0x0f, 0xf5, 0xf1, 0x7e, 0xb3, 0x2a, 0x1a, 0x20, 0xe7, 
-    0x09, 0xe5, 0xe1, 0x30, 0xe7, 0x0d, 0x74, 0x01, 0x80, 0x0b, 0xe5, 0xe1, 0x30, 0xe6, 0x04, 0x74, 
-    0x01, 0x80, 0x02, 0x74, 0x00, 0x53, 0xf1, 0x80, 0xf5, 0xf3, 0x75, 0xf3, 0x00, 0x75, 0xf6, 0x02, 
-    0x22, 0x02, 0x7d, 0x44, 0xc0, 0xf1, 0x7e, 0xb3, 0x2a, 0x1a, 0x54, 0x0f, 0x42, 0xf1, 0x7e, 0xb3, 
-    0x2a, 0x18, 0xb4, 0x00, 0x45, 0x7e, 0xb3, 0x2a, 0x16, 0xb4, 0x01, 0x24, 0x75, 0x2f, 0x77, 0x12, 
-    0x7e, 0x30, 0x7e, 0xb3, 0x2a, 0x1a, 0x54, 0x0f, 0x78, 0x05, 0x53, 0xe1, 0x3f, 0x80, 0x37, 0x7e, 
-    0xb3, 0x2a, 0x1a, 0x20, 0xe7, 0x05, 0x53, 0xe1, 0x7f, 0x80, 0x2b, 0x53, 0xe1, 0xbf, 0x80, 0x26, 
-    0xb4, 0x03, 0x17, 0x75, 0x2f, 0x78, 0x12, 0x7e, 0x30, 0x7e, 0xb3, 0x2a, 0x1a, 0x20, 0xe7, 0x05, 
-    0x43, 0xe1, 0x80, 0x80, 0x11, 0x43, 0xe1, 0x40, 0x80, 0x0c, 0x43, 0xe1, 0xc0, 0xd0, 0xf1, 0x75, 
-    0x2f, 0x07, 0x12, 0x7e, 0x30, 0x22, 0xd0, 0xf1, 0x02, 0x78, 0x7f, 0x7e, 0xb3, 0x2a, 0x16, 0xb4, 
-    0x09, 0x23, 0x75, 0x2f, 0x79, 0x12, 0x7e, 0x30, 0x7e, 0xb3, 0x2a, 0x18, 0xbe, 0xb3, 0x3f, 0xf1, 
-    0x68, 0x11, 0xca, 0xb8, 0xc0, 0xf1, 0x12, 0x43, 0x68, 0xd0, 0xf1, 0xda, 0xb8, 0x50, 0x76, 0x7a, 
-    0xb3, 0x3f, 0xf1, 0x80, 0x6d, 0xb4, 0x05, 0x08, 0x75, 0x2f, 0x7a, 0x12, 0x7e, 0x30, 0x80, 0x62, 
-    0xb4, 0x03, 0x19, 0x75, 0x2f, 0x7b, 0x12, 0x7e, 0x30, 0x7e, 0xb3, 0x2a, 0x18, 0xb4, 0x01, 0x55, 
-    0x7e, 0xb3, 0x3f, 0xf2, 0x44, 0x01, 0x7a, 0xb3, 0x3f, 0xf2, 0x80, 0x46, 0xb4, 0x01, 0x19, 0x75, 
-    0x2f, 0x7c, 0x12, 0x7e, 0x30, 0x7e, 0xb3, 0x2a, 0x18, 0xb4, 0x01, 0x39, 0x7e, 0xb3, 0x3f, 0xf2, 
-    0x54, 0xfe, 0x7a, 0xb3, 0x3f, 0xf2, 0x80, 0x2a, 0xb4, 0x07, 0x2a, 0x7e, 0xb3, 0x2a, 0x17, 0x60, 
-    0x24, 0x7c, 0x0b, 0x7e, 0x13, 0x2a, 0x18, 0x7e, 0x17, 0x2a, 0x19, 0x75, 0x2f, 0x73, 0x12, 0x7e, 
-    0x30, 0x7a, 0x01, 0x2f, 0x12, 0x7e, 0x30, 0x7a, 0x11, 0x2f, 0x12, 0x7e, 0x30, 0x12, 0x7d, 0x7a, 
-    0x40, 0x03, 0x02, 0x78, 0x7f, 0x02, 0x7d, 0x44, 0x7e, 0xb3, 0x2a, 0x16, 0xb4, 0x0b, 0xf6, 0x75, 
-    0x2f, 0x7d, 0x12, 0x7e, 0x30, 0x7e, 0xb3, 0x2a, 0x18, 0x7e, 0xa3, 0x2a, 0x1a, 0x4c, 0xab, 0x78, 
-    0xe4, 0x80, 0xdf, 0x7e, 0xb3, 0x2a, 0x16, 0xb4, 0x0a, 0xdb, 0x75, 0x2f, 0x7e, 0x12, 0x7e, 0x30, 
-    0x7e, 0xb3, 0x2a, 0x18, 0x70, 0xcf, 0xf5, 0xf3, 0x75, 0xf6, 0x01, 0x22, 0x02, 0x7d, 0x44, 0x02, 
-    0x7d, 0x44, 0x02, 0x7d, 0x44, 0x7e, 0xb3, 0x2a, 0x16, 0xb4, 0x04, 0x20, 0x75, 0x2f, 0xc3, 0x12, 
-    0x7e, 0x30, 0x7e, 0x04, 0x00, 0x01, 0x7e, 0x17, 0x2a, 0x17, 0x7e, 0x18, 0x2a, 0x26, 0x7a, 0x1c, 
-    0x00, 0x00, 0x7e, 0x47, 0x2a, 0x1b, 0x12, 0x7e, 0x3c, 0x02, 0x7c, 0xe3, 0xb4, 0x06, 0x3a, 0x75, 
-    0x2f, 0xc1, 0x12, 0x7e, 0x30, 0x7e, 0x58, 0x00, 0x00, 0x7a, 0x5c, 0x00, 0xfe, 0x7d, 0xca, 0x7e, 
-    0xd7, 0x2a, 0x17, 0x7e, 0x78, 0x2a, 0x26, 0x7a, 0x7c, 0x00, 0x00, 0x7e, 0x77, 0x2a, 0x1b, 0x75, 
-    0x2f, 0xc1, 0x12, 0x7e, 0x30, 0xc0, 0xa8, 0xc0, 0x87, 0xc2, 0xaf, 0xa9, 0xd5, 0x87, 0x12, 0x7e, 
-    0x75, 0xd0, 0x87, 0xd0, 0xa8, 0x40, 0x4f, 0x80, 0x4a, 0xb4, 0x00, 0x1c, 0xc2, 0xaf, 0xa9, 0xd5, 
-    0x87, 0x12, 0x78, 0x7f, 0xe4, 0x8d, 0xef, 0x8d, 0xef, 0x8d, 0xef, 0xd5, 0xe0, 0xf7, 0xc0, 0xd1, 
-    0xca, 0x02, 0xff, 0xca, 0x06, 0x00, 0x00, 0x32, 0xb4, 0x09, 0x12, 0x7e, 0x57, 0x2a, 0x17, 0x4d, 
-    0x55, 0x68, 0x05, 0xa9, 0xd2, 0xb1, 0x80, 0x03, 0xa9, 0xc2, 0xb1, 0x80, 0x16, 0xb4, 0x07, 0x16, 
-    0xc2, 0xaf, 0x7e, 0x07, 0x2a, 0x19, 0x7e, 0x17, 0x2a, 0x17, 0xc0, 0xd1, 0xca, 0x18, 0xca, 0x38, 
-    0xca, 0x28, 0x32, 0x02, 0x78, 0x7f, 0x02, 0x7d, 0x44, 0x7e, 0xb3, 0x2a, 0x16, 0xb4, 0x03, 0x15, 
-    0x75, 0x2f, 0xc2, 0x12, 0x7e, 0x30, 0x7e, 0x04, 0x00, 0x01, 0x7e, 0x17, 0x2a, 0x17, 0x7e, 0x57, 
-    0x2a, 0x1b, 0x02, 0x78, 0x83, 0xb4, 0x05, 0x39, 0x75, 0x2f, 0xc0, 0x12, 0x7e, 0x30, 0xc0, 0xa8, 
-    0xc0, 0x87, 0xc2, 0xaf, 0xa9, 0xd5, 0x87, 0x7e, 0x08, 0x2a, 0x26, 0x7a, 0x0c, 0x00, 0x00, 0x7e, 
-    0x24, 0x00, 0xfe, 0x7e, 0x37, 0x2a, 0x17, 0x7e, 0x47, 0x2a, 0x1b, 0x12, 0x7e, 0x3c, 0xd0, 0x87, 
-    0xd0, 0xa8, 0x7e, 0x08, 0x2a, 0x26, 0x7a, 0x0c, 0x00, 0x00, 0x7e, 0x57, 0x2a, 0x1b, 0x02, 0x78, 
-    0x83, 0x02, 0x7d, 0x44, 0x75, 0x2f, 0x07, 0x12, 0x7e, 0x30, 0x43, 0xe1, 0xc0, 0x22, 0xc0, 0xa8, 
-    0xc0, 0x87, 0xc2, 0xaf, 0xa9, 0xd5, 0x87, 0x12, 0x7d, 0xb9, 0x40, 0x19, 0x7e, 0x08, 0x2a, 0x26, 
-    0x7a, 0x0c, 0x00, 0x00, 0xca, 0x0b, 0xca, 0x49, 0x12, 0x7e, 0x3c, 0xda, 0x59, 0xda, 0x0b, 0xd0, 
-    0x87, 0xd0, 0xa8, 0xc3, 0x22, 0xd0, 0x87, 0xd0, 0xa8, 0x22, 0xc0, 0xa8, 0xc0, 0x87, 0xc2, 0xaf, 
-    0xa9, 0xd5, 0x87, 0x12, 0x7d, 0xb9, 0x40, 0x2b, 0x7e, 0x58, 0x00, 0x00, 0x7a, 0x5c, 0x00, 0xfe, 
-    0x7f, 0x61, 0x7e, 0x78, 0x2a, 0x26, 0x7a, 0x7c, 0x00, 0x00, 0x7e, 0x77, 0x2a, 0x1b, 0xbd, 0x74, 
-    0x78, 0x11, 0x75, 0x2f, 0xc1, 0x12, 0x7e, 0x30, 0x12, 0x7e, 0x75, 0x40, 0x06, 0xd0, 0x87, 0xd0, 
-    0xa8, 0xc3, 0x22, 0xd0, 0x87, 0xd0, 0xa8, 0xd3, 0x22, 0x7e, 0x24, 0x00, 0xfe, 0x7e, 0x34, 0x7f, 
-    0xca, 0x0b, 0x1a, 0x50, 0xc5, 0xf0, 0x7d, 0x62, 0x7d, 0x75, 0x7d, 0x87, 0x7e, 0x34, 0x7f, 0xc2, 
-    0x7e, 0x1b, 0xb0, 0x7e, 0x34, 0x7f, 0x03, 0xb4, 0x01, 0x04, 0x7e, 0x34, 0x7f, 0xcc, 0x7e, 0x1b, 
-    0xb0, 0xbc, 0x0b, 0x50, 0x49, 0x3e, 0x00, 0x3e, 0x00, 0x0a, 0x50, 0x2d, 0x75, 0x0b, 0x3a, 0x30, 
-    0x69, 0x53, 0x00, 0x02, 0xbd, 0x38, 0x50, 0x02, 0x2d, 0x38, 0xbc, 0x1b, 0x50, 0x30, 0x3e, 0x10, 
-    0x3e, 0x10, 0x0a, 0x51, 0x2d, 0x35, 0x69, 0x41, 0x00, 0x02, 0x0b, 0x1a, 0x30, 0xbd, 0x38, 0x50, 
-    0x02, 0x2d, 0x38, 0xbe, 0x44, 0xff, 0xff, 0x78, 0x05, 0x7e, 0x1b, 0x90, 0x0a, 0x49, 0x4d, 0x44, 
-    0x68, 0x0c, 0xbe, 0x44, 0x00, 0xff, 0x28, 0x04, 0x7e, 0x44, 0x00, 0xff, 0xc3, 0x22, 0xd3, 0x22, 
+    0x2a, 0x33, 0xb4, 0x02, 0x07, 0x12, 0x76, 0x4e, 0x02, 0x76, 0x42, 0x22, 0xb4, 0x01, 0xfc, 0x02, 
+    0x76, 0x88, 0x7e, 0x00, 0x00, 0x7a, 0x03, 0x2a, 0x33, 0x7a, 0x03, 0x2a, 0x34, 0x22, 0x7e, 0xb3, 
+    0x2a, 0x2b, 0x54, 0x60, 0x60, 0x05, 0xb4, 0x40, 0x15, 0x80, 0x13, 0x7e, 0xb3, 0x2a, 0x2c, 0xb4, 
+    0x05, 0x0c, 0x75, 0x31, 0x71, 0x12, 0x7c, 0x15, 0x7e, 0xb3, 0x2a, 0x2e, 0xf5, 0x8f, 0x22, 0x75, 
+    0xf6, 0x00, 0x22, 0xbe, 0x57, 0x2a, 0x31, 0x28, 0x04, 0x7e, 0x57, 0x2a, 0x31, 0x7a, 0x0f, 0x2a, 
+    0x36, 0x7a, 0x57, 0x2a, 0x3a, 0x02, 0x76, 0x88, 0x7e, 0xef, 0x2a, 0x36, 0x7e, 0xf7, 0x2a, 0x3a, 
+    0x7e, 0x07, 0x2a, 0x3a, 0x4d, 0x00, 0x68, 0x21, 0x7e, 0x00, 0x00, 0x7e, 0xeb, 0xb0, 0xf5, 0xf3, 
+    0xa3, 0xa5, 0x08, 0x1b, 0xf4, 0x68, 0x04, 0xa5, 0xb8, 0x08, 0xf0, 0x7a, 0xef, 0x2a, 0x36, 0x7a, 
+    0xf7, 0x2a, 0x3a, 0x75, 0x31, 0x06, 0x12, 0x7c, 0x15, 0x7a, 0x01, 0xf6, 0x22, 0xc2, 0xc1, 0x75, 
+    0x31, 0x03, 0x12, 0x7c, 0x15, 0xa9, 0x36, 0xe2, 0x16, 0xe5, 0xf5, 0x54, 0xc0, 0x68, 0x07, 0xa9, 
+    0xd7, 0xf4, 0xa9, 0x27, 0xf4, 0xfc, 0x53, 0xe1, 0x3f, 0x43, 0xf2, 0x88, 0x02, 0x77, 0x29, 0x7e, 
+    0xb3, 0x2a, 0x34, 0xb4, 0x02, 0x04, 0xa9, 0xd4, 0xe4, 0x22, 0xb4, 0x01, 0x39, 0x7e, 0x21, 0xe6, 
+    0x7c, 0x32, 0x7e, 0x13, 0x2a, 0x35, 0x2c, 0x21, 0x7a, 0x23, 0x2a, 0x35, 0x7e, 0x00, 0x00, 0x2e, 
+    0x04, 0x2a, 0x3c, 0xe5, 0xe3, 0x7a, 0x09, 0xb0, 0x0b, 0x04, 0xa5, 0xdb, 0xf6, 0xa9, 0xd4, 0xe4, 
+    0x75, 0x31, 0x70, 0x12, 0x7c, 0x15, 0x7e, 0xb3, 0x2a, 0x35, 0x7e, 0xa3, 0x2a, 0x32, 0xbc, 0xab, 
+    0x78, 0x03, 0x12, 0x77, 0xc0, 0x22, 0x02, 0x7b, 0x29, 0xe5, 0xe6, 0xb4, 0x08, 0x65, 0xa9, 0xc4, 
+    0xe2, 0x7e, 0x01, 0xe3, 0x7e, 0x11, 0xe3, 0x7e, 0x31, 0xe3, 0x7e, 0x21, 0xe3, 0x7e, 0x51, 0xe3, 
+    0x7e, 0x41, 0xe3, 0x7e, 0x71, 0xe3, 0x7e, 0x61, 0xe3, 0x7a, 0x0f, 0x2a, 0x2b, 0x7a, 0x1f, 0x2a, 
+    0x2f, 0x75, 0x31, 0x04, 0x12, 0x7c, 0x15, 0x7a, 0x01, 0x31, 0x12, 0x7c, 0x15, 0x7a, 0x11, 0x31, 
+    0x12, 0x7c, 0x15, 0x7a, 0x21, 0x31, 0x12, 0x7c, 0x15, 0x7a, 0x31, 0x31, 0x12, 0x7c, 0x15, 0x7a, 
+    0x41, 0x31, 0x12, 0x7c, 0x15, 0x7a, 0x51, 0x31, 0x12, 0x7c, 0x15, 0x7a, 0x61, 0x31, 0x12, 0x7c, 
+    0x15, 0x7a, 0x71, 0x31, 0x12, 0x7c, 0x15, 0xa9, 0xd4, 0xe4, 0xa9, 0xd7, 0xf4, 0xa9, 0xc6, 0xe2, 
+    0x12, 0x77, 0x94, 0x22, 0x6d, 0x00, 0x7e, 0x14, 0x01, 0x02, 0x7a, 0x07, 0x2a, 0x3a, 0x7a, 0x03, 
+    0x2a, 0x35, 0x7e, 0xb3, 0x2a, 0x2b, 0x20, 0xe7, 0x0f, 0x7a, 0x23, 0x2a, 0x34, 0x7a, 0x33, 0x2a, 
+    0x33, 0xbe, 0x07, 0x2a, 0x31, 0x68, 0x09, 0x22, 0x7a, 0x33, 0x2a, 0x34, 0x7a, 0x23, 0x2a, 0x33, 
+    0x7e, 0xb3, 0x2a, 0x2b, 0x54, 0xe3, 0x23, 0x23, 0x30, 0xe0, 0x02, 0xd2, 0xe5, 0x30, 0xe7, 0x02, 
+    0xd2, 0xe4, 0x30, 0xe5, 0x06, 0x30, 0xe4, 0x03, 0x02, 0x7b, 0x29, 0x54, 0x3e, 0xf5, 0xf0, 0x03, 
+    0x54, 0x1f, 0xc3, 0x25, 0xf0, 0x90, 0x77, 0xec, 0x75, 0x84, 0xff, 0x73, 0x02, 0x79, 0x40, 0x02, 
+    0x78, 0x34, 0x02, 0x79, 0xdd, 0x02, 0x79, 0xf8, 0x02, 0x78, 0xd9, 0x02, 0x78, 0x9a, 0x02, 0x7a, 
+    0x11, 0x02, 0x7a, 0x11, 0x02, 0x7a, 0x14, 0x02, 0x7a, 0x14, 0x02, 0x7a, 0x14, 0x02, 0x7a, 0x14, 
+    0x02, 0x7a, 0x14, 0x02, 0x7a, 0x14, 0x02, 0x7a, 0x14, 0x02, 0x7a, 0x14, 0x02, 0x7a, 0x1a, 0x02, 
+    0x7a, 0xce, 0x02, 0x7a, 0x17, 0x02, 0x7a, 0x17, 0x02, 0x7a, 0x17, 0x02, 0x7a, 0x17, 0x02, 0x7a, 
+    0x17, 0x02, 0x7a, 0x17, 0x7e, 0xb3, 0x2a, 0x2c, 0xb4, 0x06, 0x2a, 0x7e, 0xb3, 0x2a, 0x2d, 0x60, 
+    0x56, 0x7c, 0x0b, 0x7e, 0x13, 0x2a, 0x2e, 0x7e, 0x17, 0x2a, 0x2f, 0x75, 0x31, 0x72, 0x12, 0x7c, 
+    0x15, 0x7a, 0x01, 0x31, 0x12, 0x7c, 0x15, 0x7a, 0x11, 0x31, 0x12, 0x7c, 0x15, 0x12, 0x7b, 0x33, 
+    0x40, 0x35, 0x02, 0x76, 0x73, 0xb4, 0x08, 0x10, 0x75, 0x31, 0x74, 0x12, 0x7c, 0x15, 0x7e, 0xb3, 
+    0x3f, 0xf1, 0xf5, 0xf3, 0x75, 0xf6, 0x01, 0x22, 0xb4, 0x00, 0x1c, 0x75, 0x31, 0x75, 0x12, 0x7c, 
+    0x15, 0x7e, 0xb3, 0x3f, 0xf2, 0x30, 0xe0, 0x05, 0x75, 0xf3, 0x02, 0x80, 0x03, 0x75, 0xf3, 0x00, 
+    0x75, 0xf3, 0x00, 0x75, 0xf6, 0x02, 0x22, 0x02, 0x7b, 0x29, 0x7e, 0xb3, 0x2a, 0x2c, 0xb4, 0x00, 
+    0x35, 0x75, 0x31, 0x76, 0x12, 0x7c, 0x15, 0x7e, 0xb3, 0x2a, 0x30, 0x54, 0x0f, 0xf5, 0xf1, 0x7e, 
+    0xb3, 0x2a, 0x30, 0x20, 0xe7, 0x09, 0xe5, 0xe1, 0x30, 0xe7, 0x0d, 0x74, 0x01, 0x80, 0x0b, 0xe5, 
+    0xe1, 0x30, 0xe6, 0x04, 0x74, 0x01, 0x80, 0x02, 0x74, 0x00, 0x53, 0xf1, 0x80, 0xf5, 0xf3, 0x75, 
+    0xf3, 0x00, 0x75, 0xf6, 0x02, 0x22, 0x02, 0x7b, 0x29, 0xc0, 0xf1, 0x7e, 0xb3, 0x2a, 0x30, 0x54, 
+    0x0f, 0x42, 0xf1, 0x7e, 0xb3, 0x2a, 0x2e, 0xb4, 0x00, 0x45, 0x7e, 0xb3, 0x2a, 0x2c, 0xb4, 0x01, 
+    0x24, 0x75, 0x31, 0x77, 0x12, 0x7c, 0x15, 0x7e, 0xb3, 0x2a, 0x30, 0x54, 0x0f, 0x78, 0x05, 0x53, 
+    0xe1, 0x3f, 0x80, 0x37, 0x7e, 0xb3, 0x2a, 0x30, 0x20, 0xe7, 0x05, 0x53, 0xe1, 0x7f, 0x80, 0x2b, 
+    0x53, 0xe1, 0xbf, 0x80, 0x26, 0xb4, 0x03, 0x17, 0x75, 0x31, 0x78, 0x12, 0x7c, 0x15, 0x7e, 0xb3, 
+    0x2a, 0x30, 0x20, 0xe7, 0x05, 0x43, 0xe1, 0x80, 0x80, 0x11, 0x43, 0xe1, 0x40, 0x80, 0x0c, 0x43, 
+    0xe1, 0xc0, 0xd0, 0xf1, 0x75, 0x31, 0x07, 0x12, 0x7c, 0x15, 0x22, 0xd0, 0xf1, 0x02, 0x76, 0x6f, 
+    0x7e, 0xb3, 0x2a, 0x2c, 0xb4, 0x09, 0x23, 0x75, 0x31, 0x79, 0x12, 0x7c, 0x15, 0x7e, 0xb3, 0x2a, 
+    0x2e, 0xbe, 0xb3, 0x3f, 0xf1, 0x68, 0x11, 0xca, 0xb8, 0xc0, 0xf1, 0x12, 0x43, 0xd4, 0xd0, 0xf1, 
+    0xda, 0xb8, 0x50, 0x76, 0x7a, 0xb3, 0x3f, 0xf1, 0x80, 0x6d, 0xb4, 0x05, 0x08, 0x75, 0x31, 0x7a, 
+    0x12, 0x7c, 0x15, 0x80, 0x62, 0xb4, 0x03, 0x19, 0x75, 0x31, 0x7b, 0x12, 0x7c, 0x15, 0x7e, 0xb3, 
+    0x2a, 0x2e, 0xb4, 0x01, 0x55, 0x7e, 0xb3, 0x3f, 0xf2, 0x44, 0x01, 0x7a, 0xb3, 0x3f, 0xf2, 0x80, 
+    0x46, 0xb4, 0x01, 0x19, 0x75, 0x31, 0x7c, 0x12, 0x7c, 0x15, 0x7e, 0xb3, 0x2a, 0x2e, 0xb4, 0x01, 
+    0x39, 0x7e, 0xb3, 0x3f, 0xf2, 0x54, 0xfe, 0x7a, 0xb3, 0x3f, 0xf2, 0x80, 0x2a, 0xb4, 0x07, 0x2a, 
+    0x7e, 0xb3, 0x2a, 0x2d, 0x60, 0x24, 0x7c, 0x0b, 0x7e, 0x13, 0x2a, 0x2e, 0x7e, 0x17, 0x2a, 0x2f, 
+    0x75, 0x31, 0x73, 0x12, 0x7c, 0x15, 0x7a, 0x01, 0x31, 0x12, 0x7c, 0x15, 0x7a, 0x11, 0x31, 0x12, 
+    0x7c, 0x15, 0x12, 0x7b, 0x5f, 0x40, 0x03, 0x02, 0x76, 0x6f, 0x02, 0x7b, 0x29, 0x7e, 0xb3, 0x2a, 
+    0x2c, 0xb4, 0x0b, 0xf6, 0x75, 0x31, 0x7d, 0x12, 0x7c, 0x15, 0x7e, 0xb3, 0x2a, 0x2e, 0x7e, 0xa3, 
+    0x2a, 0x30, 0x4c, 0xab, 0x78, 0xe4, 0x80, 0xdf, 0x7e, 0xb3, 0x2a, 0x2c, 0xb4, 0x0a, 0xdb, 0x75, 
+    0x31, 0x7e, 0x12, 0x7c, 0x15, 0x7e, 0xb3, 0x2a, 0x2e, 0x70, 0xcf, 0xf5, 0xf3, 0x75, 0xf6, 0x01, 
+    0x22, 0x02, 0x7b, 0x29, 0x02, 0x7b, 0x29, 0x02, 0x7b, 0x29, 0x7e, 0xb3, 0x2a, 0x2c, 0xb4, 0x04, 
+    0x20, 0x75, 0x31, 0xc3, 0x12, 0x7c, 0x15, 0x7e, 0x04, 0x00, 0x01, 0x7e, 0x17, 0x2a, 0x2d, 0x7e, 
+    0x18, 0x2a, 0x3c, 0x7a, 0x1c, 0x00, 0x00, 0x7e, 0x47, 0x2a, 0x31, 0x12, 0x7c, 0x21, 0x02, 0x7a, 
+    0xc8, 0xb4, 0x06, 0x3a, 0x75, 0x31, 0xc1, 0x12, 0x7c, 0x15, 0x7e, 0x58, 0x00, 0x00, 0x7a, 0x5c, 
+    0x00, 0xfe, 0x7d, 0xca, 0x7e, 0xd7, 0x2a, 0x2d, 0x7e, 0x78, 0x2a, 0x3c, 0x7a, 0x7c, 0x00, 0x00, 
+    0x7e, 0x77, 0x2a, 0x31, 0x75, 0x31, 0xc1, 0x12, 0x7c, 0x15, 0xc0, 0xa8, 0xc0, 0x87, 0xc2, 0xaf, 
+    0xa9, 0xd5, 0x87, 0x12, 0x7c, 0x5a, 0xd0, 0x87, 0xd0, 0xa8, 0x40, 0x4f, 0x80, 0x4a, 0xb4, 0x00, 
+    0x1c, 0xc2, 0xaf, 0xa9, 0xd5, 0x87, 0x12, 0x76, 0x6f, 0xe4, 0x8d, 0xef, 0x8d, 0xef, 0x8d, 0xef, 
+    0xd5, 0xe0, 0xf7, 0xc0, 0xd1, 0xca, 0x02, 0xff, 0xca, 0x06, 0x00, 0x00, 0x32, 0xb4, 0x09, 0x12, 
+    0x7e, 0x57, 0x2a, 0x2d, 0x4d, 0x55, 0x68, 0x05, 0xa9, 0xd2, 0xb1, 0x80, 0x03, 0xa9, 0xc2, 0xb1, 
+    0x80, 0x16, 0xb4, 0x07, 0x16, 0xc2, 0xaf, 0x7e, 0x07, 0x2a, 0x2f, 0x7e, 0x17, 0x2a, 0x2d, 0xc0, 
+    0xd1, 0xca, 0x18, 0xca, 0x38, 0xca, 0x28, 0x32, 0x02, 0x76, 0x6f, 0x02, 0x7b, 0x29, 0x7e, 0xb3, 
+    0x2a, 0x2c, 0xb4, 0x03, 0x15, 0x75, 0x31, 0xc2, 0x12, 0x7c, 0x15, 0x7e, 0x04, 0x00, 0x01, 0x7e, 
+    0x17, 0x2a, 0x2d, 0x7e, 0x57, 0x2a, 0x31, 0x02, 0x76, 0x73, 0xb4, 0x05, 0x39, 0x75, 0x31, 0xc0, 
+    0x12, 0x7c, 0x15, 0xc0, 0xa8, 0xc0, 0x87, 0xc2, 0xaf, 0xa9, 0xd5, 0x87, 0x7e, 0x08, 0x2a, 0x3c, 
+    0x7a, 0x0c, 0x00, 0x00, 0x7e, 0x24, 0x00, 0xfe, 0x7e, 0x37, 0x2a, 0x2d, 0x7e, 0x47, 0x2a, 0x31, 
+    0x12, 0x7c, 0x21, 0xd0, 0x87, 0xd0, 0xa8, 0x7e, 0x08, 0x2a, 0x3c, 0x7a, 0x0c, 0x00, 0x00, 0x7e, 
+    0x57, 0x2a, 0x31, 0x02, 0x76, 0x73, 0x02, 0x7b, 0x29, 0x75, 0x31, 0x07, 0x12, 0x7c, 0x15, 0x43, 
+    0xe1, 0xc0, 0x22, 0xc0, 0xa8, 0xc0, 0x87, 0xc2, 0xaf, 0xa9, 0xd5, 0x87, 0x12, 0x7b, 0x9e, 0x40, 
+    0x19, 0x7e, 0x08, 0x2a, 0x3c, 0x7a, 0x0c, 0x00, 0x00, 0xca, 0x0b, 0xca, 0x49, 0x12, 0x7c, 0x21, 
+    0xda, 0x59, 0xda, 0x0b, 0xd0, 0x87, 0xd0, 0xa8, 0xc3, 0x22, 0xd0, 0x87, 0xd0, 0xa8, 0x22, 0xc0, 
+    0xa8, 0xc0, 0x87, 0xc2, 0xaf, 0xa9, 0xd5, 0x87, 0x12, 0x7b, 0x9e, 0x40, 0x2b, 0x7e, 0x58, 0x00, 
+    0x00, 0x7a, 0x5c, 0x00, 0xfe, 0x7f, 0x61, 0x7e, 0x78, 0x2a, 0x3c, 0x7a, 0x7c, 0x00, 0x00, 0x7e, 
+    0x77, 0x2a, 0x31, 0xbd, 0x74, 0x78, 0x11, 0x75, 0x31, 0xc1, 0x12, 0x7c, 0x15, 0x12, 0x7c, 0x5a, 
+    0x40, 0x06, 0xd0, 0x87, 0xd0, 0xa8, 0xc3, 0x22, 0xd0, 0x87, 0xd0, 0xa8, 0xd3, 0x22, 0x7e, 0x24, 
+    0x00, 0xfe, 0x7e, 0x34, 0x7f, 0xca, 0x0b, 0x1a, 0x50, 0xc5, 0xf0, 0x7d, 0x62, 0x7d, 0x75, 0x7d, 
+    0x87, 0x7e, 0x34, 0x7f, 0xc2, 0x7e, 0x1b, 0xb0, 0x7e, 0x34, 0x7f, 0x03, 0xb4, 0x01, 0x04, 0x7e, 
+    0x34, 0x7f, 0xcc, 0x7e, 0x1b, 0xb0, 0xbc, 0x0b, 0x50, 0x49, 0x3e, 0x00, 0x3e, 0x00, 0x0a, 0x50, 
+    0x2d, 0x75, 0x0b, 0x3a, 0x30, 0x69, 0x53, 0x00, 0x02, 0xbd, 0x38, 0x50, 0x02, 0x2d, 0x38, 0xbc, 
+    0x1b, 0x50, 0x30, 0x3e, 0x10, 0x3e, 0x10, 0x0a, 0x51, 0x2d, 0x35, 0x69, 0x41, 0x00, 0x02, 0x0b, 
+    0x1a, 0x30, 0xbd, 0x38, 0x50, 0x02, 0x2d, 0x38, 0xbe, 0x44, 0xff, 0xff, 0x78, 0x05, 0x7e, 0x1b, 
+    0x90, 0x0a, 0x49, 0x4d, 0x44, 0x68, 0x0c, 0xbe, 0x44, 0x00, 0xff, 0x28, 0x04, 0x7e, 0x44, 0x00, 
+    0xff, 0xc3, 0x22, 0xd3, 0x22, 
 
-// Segment #15, Start Address 00ff7fc6, Length 4
+// Segment #16, Start Address 00ff7fc6, Length 4
 0xff,0x00,0xc6,0x7f,0x04,0x00,
-    0x01, 0x0c, 0x03, 0x00, 
+    0x01, 0x10, 0x04, 0x00, 
 
-// Segment #16, Start Address 00ff7e30, Length 315
-0xff,0x00,0x30,0x7e,0x3b,0x01,
-    0xca, 0x08, 0x7e, 0x01, 0x2f, 0x7a, 0x03, 0x3f, 0xf0, 0xda, 0x08, 0x22, 0x7e, 0x1b, 0xc0, 0x7a, 
+// Segment #17, Start Address 00ff7c15, Length 330
+0xff,0x00,0x15,0x7c,0x4a,0x01,
+    0xca, 0x08, 0x7e, 0x01, 0x31, 0x7a, 0x03, 0x3f, 0xf0, 0xda, 0x08, 0x22, 0x7e, 0x1b, 0xc0, 0x7a, 
     0x0b, 0xc0, 0x0b, 0x14, 0x0b, 0x34, 0x1b, 0x44, 0x78, 0xf2, 0x22, 0x7f, 0x6f, 0x7f, 0xf0, 0x1b, 
     0xfc, 0x7c, 0x54, 0x7d, 0x32, 0x80, 0x08, 0xca, 0x1b, 0xca, 0x1b, 0xca, 0x1b, 0xca, 0x1b, 0x9e, 
     0x44, 0x00, 0x10, 0x50, 0xf2, 0x2e, 0x44, 0x00, 0x10, 0x68, 0x06, 0xca, 0x48, 0x1b, 0x44, 0x78, 
     0xfa, 0x7f, 0xf6, 0x89, 0xe4, 0xca, 0x6b, 0x5e, 0xd4, 0x00, 0x3f, 0x68, 0x20, 0x7e, 0x84, 0x00, 
-    0x40, 0x9d, 0x8d, 0xda, 0x6b, 0xbd, 0x87, 0x38, 0x16, 0xca, 0x79, 0x7d, 0x78, 0x12, 0x7e, 0x9f, 
+    0x40, 0x9d, 0x8d, 0xda, 0x6b, 0xbd, 0x87, 0x38, 0x16, 0xca, 0x79, 0x7d, 0x78, 0x12, 0x7c, 0x84, 
     0xda, 0x79, 0x40, 0x08, 0x9d, 0x78, 0x68, 0x02, 0x80, 0x05, 0xc2, 0xd7, 0x22, 0xda, 0x6b, 0x43, 
     0x90, 0x30, 0x74, 0xaa, 0x39, 0xb5, 0x55, 0x55, 0x74, 0x55, 0x39, 0xb5, 0x2a, 0xaa, 0x74, 0xa0, 
     0x39, 0xb5, 0x55, 0x55, 0x7e, 0x04, 0x00, 0x40, 0x9d, 0x70, 0x50, 0x06, 0x2d, 0x70, 0x7d, 0x07, 
@@ -1104,16 +1211,17 @@
     0x1b, 0x54, 0x78, 0xf5, 0x80, 0x2c, 0x6d, 0x00, 0x7c, 0x20, 0x7f, 0x16, 0x9f, 0x10, 0x7f, 0x27, 
     0x9f, 0x20, 0x7e, 0x2b, 0x00, 0x7e, 0x1b, 0x10, 0xbc, 0x01, 0x78, 0x16, 0x0b, 0x2c, 0x0b, 0x1c, 
     0xa5, 0xdb, 0xef, 0x7c, 0xb6, 0x20, 0xe0, 0x03, 0x63, 0x90, 0x30, 0x4d, 0x77, 0x78, 0x93, 0xc2, 
-    0xd7, 0x22, 0xd2, 0xd7, 0x22, 0x00, 0x04, 0x00, 0x04, 0x00, 0x00, 0x06, 0x04, 0x02, 0x04, 0x00, 
-    0x02, 0x01, 0x04, 0x01, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x02, 
-    0x02, 0x02, 0x04, 0x00, 0x08, 0x10, 0x02, 0x10, 0x04, 0x02, 0x08, 0x00, 0x01, 0x01, 0x08, 0x7e, 
-    0x18, 0x7f, 0xbd, 0x7a, 0x1c, 0x00, 0xfe, 0x0b, 0x1a, 0x00, 0xbe, 0x10, 0x14, 0x38, 0x1a, 0x0a, 
-    0x51, 0x23, 0x7e, 0x18, 0x7f, 0x15, 0x7a, 0x1c, 0x00, 0xff, 0x2d, 0x35, 0x0b, 0x1a, 0x50, 0x60, 
-    0x08, 0xa5, 0xb8, 0x02, 0x03, 0x4e, 0xa0, 0x08, 0x22, 0x80, 0xfe, 
+    0xd7, 0x22, 0xd2, 0xd7, 0x22, 0x00, 0x04, 0x00, 0x04, 0x42, 0x08, 0x06, 0x04, 0x02, 0x04, 0x00, 
+    0x02, 0x01, 0x04, 0x01, 0x02, 0x82, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x02, 
+    0x02, 0x02, 0x04, 0x02, 0x08, 0x10, 0x02, 0x10, 0x04, 0x02, 0x08, 0x00, 0x01, 0x01, 0x08, 0x00, 
+    0x01, 0x00, 0x02, 0x00, 0x02, 0x02, 0x08, 0x02, 0x04, 0x20, 0x04, 0x7e, 0x18, 0x7f, 0xbd, 0x7a, 
+    0x1c, 0x00, 0xfe, 0x0b, 0x1a, 0x00, 0x5e, 0x10, 0x1f, 0xbe, 0x10, 0x1a, 0x38, 0x1a, 0x0a, 0x51, 
+    0x23, 0x7e, 0x18, 0x7c, 0xfa, 0x7a, 0x1c, 0x00, 0xff, 0x2d, 0x35, 0x0b, 0x1a, 0x50, 0x60, 0x08, 
+    0xa5, 0xb8, 0x02, 0x03, 0x4e, 0xa0, 0x08, 0x22, 0x80, 0xfe, 
 };
 
 static struct edge_firmware_version_info IMAGE_VERSION_NAME = {
-	1, 12, 3 };		// Major, Minor, Build
+	1, 16, 4 };		// Major, Minor, Build
 
 #undef IMAGE_VERSION_NAME
 
diff -Nru a/drivers/usb/serial/io_fw_down3.h b/drivers/usb/serial/io_fw_down3.h
--- a/drivers/usb/serial/io_fw_down3.h	2004-10-18 14:56:50 -07:00
+++ b/drivers/usb/serial/io_fw_down3.h	2004-10-18 14:56:50 -07:00
@@ -1,11 +1,11 @@
 //**************************************************************
 //* Edgeport Binary Image (for TI based products)
-//* Generated by TIBin2C v1.00
+//* Generated by TIBin2C v2.00 (watchport)
 //* Copyright (C) 2001 Inside Out Networks, All rights reserved.
 //**************************************************************
 
 
-static int IMAGE_SIZE = 12166;
+static int IMAGE_SIZE = 12749;
 
 struct EDGE_FIRMWARE_VERSION_INFO
 {
@@ -16,7 +16,7 @@
 
 static struct EDGE_FIRMWARE_VERSION_INFO IMAGE_VERSION_NAME =
 {
-	4, 1, 0		// Major, Minor, Build
+	4, 10, 0		// Major, Minor, Build
 
 };
 
@@ -27,20 +27,20 @@
 //      WORD    Length;
 //      BYTE    CheckSum;
 //  };
-0x83, 0x2f, 
-0x33, 
+0xca, 0x31, 
+0xa8, 
 
-0x02, 0x24, 0x84, 0x02, 0x1f, 0x36, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x1e, 0x00, 0x00, 
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x01, 0x1a, 0x85, 0x45, 
-0x8c, 0x85, 0x46, 0x8a, 0xc0, 0xe0, 0xc0, 0xd0, 0xc0, 0xf0, 0xc0, 0x82, 0xc0, 0x83, 0xc0, 0x00, 
-0xc0, 0x01, 0xc0, 0x02, 0xc0, 0x03, 0xc0, 0x04, 0xc0, 0x05, 0xc0, 0x06, 0xc0, 0x07, 0xe5, 0x44, 
-0x24, 0x08, 0xf8, 0xe6, 0x60, 0x2b, 0xe5, 0x44, 0x24, 0x10, 0xf8, 0xa6, 0x81, 0xe5, 0x44, 0x75, 
-0xf0, 0x21, 0xa4, 0x24, 0x05, 0xf5, 0x82, 0xe4, 0x34, 0xf8, 0xf5, 0x83, 0x78, 0x92, 0xe5, 0x81, 
-0x04, 0xc3, 0x98, 0xf9, 0x94, 0x22, 0x40, 0x03, 0x02, 0x11, 0x1a, 0xe6, 0xf0, 0x08, 0xa3, 0xd9, 
-0xfa, 0x74, 0x08, 0x25, 0x44, 0xf8, 0x05, 0x44, 0x08, 0xe6, 0x54, 0x80, 0x70, 0x0c, 0xe5, 0x44, 
-0xb4, 0x07, 0xf3, 0x78, 0x08, 0x75, 0x44, 0x00, 0x80, 0xef, 0xe5, 0x44, 0x24, 0x10, 0xf8, 0x86, 
-0x81, 0xe5, 0x44, 0x75, 0xf0, 0x21, 0xa4, 0x24, 0x05, 0xf5, 0x82, 0xe4, 0x34, 0xf8, 0xf5, 0x83, 
-0x78, 0x92, 0xe5, 0x81, 0x04, 0xc3, 0x98, 0xf9, 0xe0, 0xf6, 0x08, 0xa3, 0xd9, 0xfa, 0xd0, 0x07, 
+0x02, 0x26, 0xfe, 0x02, 0x21, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x1e, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x01, 0x1a, 0x85, 0x3f, 
+0x8c, 0x85, 0x40, 0x8a, 0xc0, 0xe0, 0xc0, 0xd0, 0xc0, 0xf0, 0xc0, 0x82, 0xc0, 0x83, 0xc0, 0x00, 
+0xc0, 0x01, 0xc0, 0x02, 0xc0, 0x03, 0xc0, 0x04, 0xc0, 0x05, 0xc0, 0x06, 0xc0, 0x07, 0xe5, 0x3e, 
+0x24, 0x08, 0xf8, 0xe6, 0x60, 0x2b, 0xe5, 0x3e, 0x24, 0x10, 0xf8, 0xa6, 0x81, 0xe5, 0x3e, 0x75, 
+0xf0, 0x21, 0xa4, 0x24, 0x05, 0xf5, 0x82, 0xe4, 0x34, 0xf8, 0xf5, 0x83, 0x78, 0x8c, 0xe5, 0x81, 
+0x04, 0xc3, 0x98, 0xf9, 0x94, 0x22, 0x40, 0x03, 0x02, 0x11, 0x94, 0xe6, 0xf0, 0x08, 0xa3, 0xd9, 
+0xfa, 0x74, 0x08, 0x25, 0x3e, 0xf8, 0x05, 0x3e, 0x08, 0xe6, 0x54, 0x80, 0x70, 0x0c, 0xe5, 0x3e, 
+0xb4, 0x07, 0xf3, 0x78, 0x08, 0x75, 0x3e, 0x00, 0x80, 0xef, 0xe5, 0x3e, 0x24, 0x10, 0xf8, 0x86, 
+0x81, 0xe5, 0x3e, 0x75, 0xf0, 0x21, 0xa4, 0x24, 0x05, 0xf5, 0x82, 0xe4, 0x34, 0xf8, 0xf5, 0x83, 
+0x78, 0x8c, 0xe5, 0x81, 0x04, 0xc3, 0x98, 0xf9, 0xe0, 0xf6, 0x08, 0xa3, 0xd9, 0xfa, 0xd0, 0x07, 
 0xd0, 0x06, 0xd0, 0x05, 0xd0, 0x04, 0xd0, 0x03, 0xd0, 0x02, 0xd0, 0x01, 0xd0, 0x00, 0xd0, 0x83, 
 0xd0, 0x82, 0xd0, 0xf0, 0xd0, 0xd0, 0xd0, 0xe0, 0x32, 0x30, 0x01, 0x4d, 0x30, 0xb4, 0x48, 0x10, 
 0x00, 0x45, 0x90, 0xff, 0x08, 0xe0, 0x54, 0x20, 0xf8, 0x90, 0xff, 0x48, 0xe0, 0x54, 0x20, 0xf9, 
@@ -50,747 +50,783 @@
 0xa3, 0xe0, 0xcb, 0xf0, 0x6b, 0x60, 0x02, 0x7e, 0x04, 0x22, 0xc0, 0xe0, 0xc0, 0xd0, 0xc0, 0xf0, 
 0xc0, 0x82, 0xc0, 0x83, 0xc0, 0x00, 0xc0, 0x01, 0xc0, 0x02, 0xc0, 0x03, 0xc0, 0x04, 0xc0, 0x05, 
 0xc0, 0x06, 0xc0, 0x07, 0x90, 0xff, 0x93, 0x74, 0x01, 0xf0, 0xe5, 0x81, 0x94, 0xfd, 0x40, 0x03, 
-0x02, 0x11, 0x1a, 0x85, 0x47, 0x8d, 0x85, 0x48, 0x8b, 0x74, 0xae, 0xf5, 0x82, 0x74, 0xfa, 0xf5, 
+0x02, 0x11, 0x94, 0x85, 0x41, 0x8d, 0x85, 0x42, 0x8b, 0x74, 0xaf, 0xf5, 0x82, 0x74, 0xfa, 0xf5, 
 0x83, 0xe0, 0xb4, 0x01, 0x1b, 0xc0, 0x82, 0xc0, 0x83, 0x90, 0xff, 0x4a, 0xe0, 0x30, 0xe7, 0x2c, 
 0x90, 0xff, 0x4e, 0xe0, 0x30, 0xe7, 0x25, 0xd0, 0x83, 0xd0, 0x82, 0x74, 0x02, 0xf0, 0x80, 0x20, 
-0xb4, 0x02, 0x1d, 0xc0, 0x82, 0xc0, 0x83, 0x90, 0xff, 0x7a, 0xe0, 0x30, 0xe7, 0x05, 0x12, 0x25, 
-0x13, 0x80, 0x09, 0xd0, 0x83, 0xd0, 0x82, 0x74, 0x03, 0xf0, 0x80, 0x04, 0xd0, 0x83, 0xd0, 0x82, 
+0xb4, 0x02, 0x1d, 0xc0, 0x82, 0xc0, 0x83, 0x90, 0xff, 0x7a, 0xe0, 0x30, 0xe7, 0x05, 0x12, 0x27, 
+0x8d, 0x80, 0x09, 0xd0, 0x83, 0xd0, 0x82, 0x74, 0x03, 0xf0, 0x80, 0x04, 0xd0, 0x83, 0xd0, 0x82, 
 0xa3, 0xe0, 0xb4, 0x01, 0x1b, 0xc0, 0x82, 0xc0, 0x83, 0x90, 0xff, 0x52, 0xe0, 0x30, 0xe7, 0x2c, 
-0x90, 0xff, 0x56, 0xe0, 0x30, 0xe7, 0x25, 0xd0, 0x83, 0xd0, 0x82, 0x74, 0x02, 0xf0, 0x80, 0x20, 
-0xb4, 0x02, 0x1d, 0xc0, 0x82, 0xc0, 0x83, 0x90, 0xff, 0x7a, 0xe0, 0x30, 0xe7, 0x05, 0x12, 0x25, 
-0x13, 0x80, 0x09, 0xd0, 0x83, 0xd0, 0x82, 0x74, 0x03, 0xf0, 0x80, 0x04, 0xd0, 0x83, 0xd0, 0x82, 
-0x20, 0x02, 0x03, 0x30, 0x01, 0x7b, 0x74, 0x16, 0xf5, 0x82, 0x74, 0xf9, 0xf5, 0x83, 0xe0, 0x14, 
-0xfc, 0xf0, 0xa3, 0xe0, 0xfd, 0xa3, 0xe0, 0xfe, 0x64, 0x04, 0x70, 0x0f, 0xec, 0x70, 0x62, 0x7e, 
-0x01, 0x12, 0x00, 0xc9, 0x7c, 0x0a, 0x7d, 0xfa, 0x02, 0x02, 0x22, 0x12, 0x00, 0xc9, 0xee, 0x64, 
-0x04, 0x60, 0x1d, 0xec, 0x70, 0x4b, 0x7c, 0x0a, 0xed, 0x14, 0xfd, 0x70, 0x15, 0xee, 0x64, 0x02, 
-0x60, 0x07, 0x7e, 0x02, 0x7d, 0x32, 0x02, 0x02, 0x22, 0x7e, 0x01, 0x7d, 0xfa, 0x02, 0x02, 0x22, 
-0x7c, 0x0a, 0x74, 0x16, 0xf5, 0x82, 0x74, 0xf9, 0xf5, 0x83, 0xec, 0xf0, 0xa3, 0xed, 0xf0, 0xa3, 
-0xee, 0xf0, 0x14, 0x60, 0x18, 0x20, 0xe1, 0x0f, 0x20, 0x01, 0x06, 0xd2, 0xb1, 0xc2, 0xb0, 0x80, 
-0x10, 0xc2, 0xb1, 0xd2, 0xb0, 0x80, 0x0a, 0xc2, 0xb1, 0xc2, 0xb0, 0x80, 0x04, 0xd2, 0xb0, 0xd2, 
-0xb1, 0x78, 0x19, 0x79, 0x09, 0x7a, 0x07, 0xe7, 0x70, 0x04, 0xa6, 0x00, 0x80, 0x0b, 0xe6, 0x60, 
-0x08, 0x16, 0xe6, 0x70, 0x04, 0xe7, 0x44, 0x80, 0xf7, 0x08, 0x09, 0xda, 0xea, 0xe5, 0x43, 0x60, 
-0x13, 0x14, 0xf5, 0x43, 0x70, 0x0e, 0xe5, 0x44, 0x24, 0x08, 0xf8, 0x76, 0x00, 0x12, 0x10, 0x95, 
-0xd2, 0x8c, 0xd2, 0x8d, 0xd0, 0x07, 0xd0, 0x06, 0xd0, 0x05, 0xd0, 0x04, 0xd0, 0x03, 0xd0, 0x02, 
-0xd0, 0x01, 0xd0, 0x00, 0xd0, 0x83, 0xd0, 0x82, 0xd0, 0xf0, 0xd0, 0xd0, 0xd0, 0xe0, 0x32, 0x90, 
-0xff, 0x04, 0xe0, 0x90, 0xfa, 0xb5, 0xf0, 0x90, 0xff, 0x06, 0xe0, 0xfc, 0xa3, 0xe0, 0xfa, 0xec, 
-0xff, 0xea, 0xfe, 0xef, 0xc3, 0x94, 0x08, 0xee, 0x94, 0x01, 0x50, 0x02, 0x80, 0x04, 0x7e, 0x01, 
-0x7f, 0x08, 0x8e, 0x34, 0x8f, 0x35, 0x90, 0xff, 0x02, 0xe0, 0xfc, 0xa3, 0xe0, 0xfa, 0xec, 0xff, 
-0xea, 0x90, 0xfa, 0xb9, 0xf0, 0xef, 0xa3, 0xf0, 0x12, 0x18, 0x49, 0x78, 0x24, 0x7c, 0x00, 0x7d, 
-0x00, 0x12, 0x19, 0x6c, 0x7e, 0x00, 0x7f, 0x05, 0x12, 0x13, 0x8f, 0xe4, 0xf5, 0x53, 0xe5, 0x53, 
-0xc3, 0x94, 0x02, 0x50, 0x0f, 0x12, 0x18, 0x2a, 0xe4, 0x12, 0x13, 0xfb, 0x05, 0x53, 0x04, 0x12, 
-0x18, 0x1b, 0x80, 0xea, 0x12, 0x18, 0x49, 0x90, 0xff, 0x00, 0xe0, 0xff, 0x54, 0x60, 0x24, 0xc0, 
-0x70, 0x03, 0x02, 0x08, 0xb8, 0x24, 0x40, 0x60, 0x03, 0x02, 0x0e, 0xac, 0x90, 0xfa, 0xb5, 0xe0, 
-0xfe, 0x54, 0x0f, 0xf5, 0x53, 0xee, 0x30, 0xe7, 0x03, 0xd3, 0x80, 0x01, 0xc3, 0x92, 0x0a, 0x90, 
-0xff, 0x01, 0xe0, 0x12, 0x15, 0x0f, 0x03, 0x55, 0x00, 0x04, 0x28, 0x01, 0x05, 0x2f, 0x03, 0x05, 
-0xf6, 0x05, 0x06, 0x38, 0x06, 0x07, 0x9a, 0x08, 0x07, 0xe2, 0x09, 0x08, 0x3e, 0x0a, 0x08, 0x7e, 
-0x0b, 0x00, 0x00, 0x0e, 0xac, 0xe5, 0x2c, 0x20, 0xe7, 0x03, 0x02, 0x0e, 0xac, 0x90, 0xfa, 0xb9, 
-0xe0, 0x70, 0x02, 0xa3, 0xe0, 0x60, 0x03, 0x02, 0x0e, 0xac, 0xe5, 0x35, 0x64, 0x02, 0x45, 0x34, 
-0x60, 0x03, 0x02, 0x0e, 0xac, 0xef, 0x54, 0x1f, 0x14, 0x60, 0x2b, 0x14, 0x60, 0x47, 0x24, 0x02, 
-0x60, 0x03, 0x02, 0x0e, 0xac, 0xee, 0x60, 0x03, 0x02, 0x0e, 0xac, 0x12, 0x18, 0x2a, 0x74, 0x01, 
-0x12, 0x13, 0xfb, 0x78, 0x6d, 0xe6, 0x30, 0xe0, 0x08, 0x12, 0x18, 0x2a, 0x74, 0x02, 0x12, 0x13, 
-0xfb, 0x7f, 0x02, 0x02, 0x2f, 0x6a, 0xe5, 0x2c, 0x20, 0xe1, 0x09, 0x90, 0xfa, 0xb5, 0xe0, 0x60, 
-0x03, 0x02, 0x0e, 0xac, 0x90, 0xfa, 0xb5, 0xe0, 0xd3, 0x94, 0x01, 0x40, 0x03, 0x02, 0x0e, 0xac, 
-0x7f, 0x02, 0x02, 0x2f, 0x6a, 0xe5, 0x2c, 0x20, 0xe1, 0x0e, 0x90, 0xfa, 0xb5, 0xe0, 0xff, 0x60, 
-0x07, 0x64, 0x80, 0x60, 0x03, 0x02, 0x0e, 0xac, 0x12, 0x0f, 0x38, 0x40, 0x03, 0x02, 0x0e, 0xac, 
-0xe5, 0x53, 0x70, 0x19, 0x30, 0x0a, 0x0b, 0x90, 0xff, 0x80, 0x12, 0x18, 0x27, 0x12, 0x13, 0xfb, 
-0x80, 0x24, 0x90, 0xff, 0x82, 0x12, 0x18, 0x27, 0x12, 0x13, 0xfb, 0x80, 0x19, 0x15, 0x53, 0x30, 
-0x0a, 0x0b, 0x12, 0x18, 0xbd, 0x12, 0x18, 0x25, 0x12, 0x13, 0xfb, 0x80, 0x09, 0x12, 0x18, 0xcb, 
-0x12, 0x18, 0x25, 0x12, 0x13, 0xfb, 0x12, 0x18, 0x2a, 0x12, 0x13, 0xb5, 0x60, 0x05, 0x74, 0x01, 
-0x12, 0x13, 0xfb, 0x7f, 0x02, 0x02, 0x2f, 0x6a, 0xe5, 0x2c, 0x30, 0xe7, 0x03, 0x02, 0x0e, 0xac, 
-0xe5, 0x35, 0x45, 0x34, 0x60, 0x03, 0x02, 0x0e, 0xac, 0x12, 0x18, 0xd9, 0x14, 0x60, 0x2d, 0x14, 
-0x60, 0x59, 0x24, 0x02, 0x60, 0x03, 0x02, 0x0e, 0xac, 0x90, 0xfa, 0xb9, 0xe0, 0x70, 0x04, 0xa3, 
-0xe0, 0x64, 0x01, 0x60, 0x03, 0x02, 0x0e, 0xac, 0x90, 0xfa, 0xb5, 0xe0, 0x60, 0x03, 0x02, 0x0e, 
-0xac, 0x78, 0x6d, 0xe6, 0x54, 0xfe, 0xf6, 0xe4, 0xff, 0x02, 0x2f, 0x6a, 0xe5, 0x2c, 0x20, 0xe1, 
-0x06, 0x20, 0xe0, 0x03, 0x02, 0x0e, 0xac, 0xe5, 0x2c, 0x30, 0xe0, 0x09, 0x90, 0xfa, 0xb5, 0xe0, 
-0x60, 0x03, 0x02, 0x0e, 0xac, 0xe5, 0x2c, 0x30, 0xe1, 0x0c, 0x90, 0xfa, 0xb5, 0xe0, 0xd3, 0x94, 
-0x01, 0x40, 0x03, 0x02, 0x0e, 0xac, 0xe4, 0xff, 0x02, 0x2f, 0x6a, 0x90, 0xfa, 0xb9, 0xe0, 0x70, 
-0x02, 0xa3, 0xe0, 0x60, 0x03, 0x02, 0x0e, 0xac, 0x12, 0x0f, 0x38, 0x40, 0x03, 0x02, 0x0e, 0xac, 
-0xe5, 0x2c, 0x20, 0xe1, 0x06, 0x20, 0xe0, 0x03, 0x02, 0x0e, 0xac, 0xe5, 0x2c, 0x30, 0xe0, 0x07, 
-0xe5, 0x53, 0x60, 0x03, 0x02, 0x0e, 0xac, 0xe5, 0x53, 0x70, 0x0f, 0x90, 0xff, 0x82, 0xe0, 0x54, 
-0xf7, 0xf0, 0x90, 0xff, 0x80, 0xe0, 0x54, 0xf7, 0xf0, 0x22, 0xe5, 0x53, 0x24, 0xfe, 0x60, 0x1b, 
-0x04, 0x70, 0x2e, 0x30, 0x0a, 0x0c, 0xa2, 0x0a, 0xe4, 0x33, 0xfd, 0x7f, 0x03, 0x12, 0x2a, 0xce, 
-0x80, 0x1f, 0xe4, 0xfd, 0x7f, 0x03, 0x12, 0x2a, 0xce, 0x80, 0x16, 0x30, 0x0a, 0x0c, 0xa2, 0x0a, 
-0xe4, 0x33, 0xfd, 0x7f, 0x04, 0x12, 0x2a, 0xce, 0x80, 0x07, 0xe4, 0xfd, 0x7f, 0x04, 0x12, 0x2a, 
-0xce, 0x15, 0x53, 0x30, 0x0a, 0x0b, 0x12, 0x18, 0xbd, 0xf5, 0x83, 0xe0, 0x54, 0xf7, 0xf0, 0x80, 
-0x09, 0x12, 0x18, 0xcb, 0xf5, 0x83, 0xe0, 0x54, 0xf7, 0xf0, 0xe4, 0xff, 0x02, 0x2f, 0x6a, 0xe5, 
-0x2c, 0x30, 0xe7, 0x03, 0x02, 0x0e, 0xac, 0xe5, 0x35, 0x45, 0x34, 0x60, 0x03, 0x02, 0x0e, 0xac, 
-0x12, 0x18, 0xd9, 0x14, 0x60, 0x2d, 0x14, 0x60, 0x55, 0x24, 0x02, 0x60, 0x03, 0x02, 0x0e, 0xac, 
-0x90, 0xfa, 0xb9, 0xe0, 0x70, 0x04, 0xa3, 0xe0, 0x64, 0x01, 0x60, 0x03, 0x02, 0x0e, 0xac, 0x90, 
-0xfa, 0xb5, 0xe0, 0x60, 0x03, 0x02, 0x0e, 0xac, 0x78, 0x6d, 0xe6, 0x44, 0x01, 0xf6, 0xe4, 0xff, 
-0x02, 0x2f, 0x6a, 0xe5, 0x2c, 0x20, 0xe1, 0x06, 0x20, 0xe0, 0x03, 0x02, 0x0e, 0xac, 0xe5, 0x2c, 
-0x30, 0xe0, 0x07, 0xe5, 0x53, 0x60, 0x03, 0x02, 0x0e, 0xac, 0xe5, 0x2c, 0x30, 0xe1, 0x0a, 0xe5, 
-0x53, 0xd3, 0x94, 0x01, 0x40, 0x03, 0x02, 0x0e, 0xac, 0xe4, 0xff, 0x02, 0x2f, 0x6a, 0x90, 0xfa, 
-0xb9, 0xe0, 0x70, 0x02, 0xa3, 0xe0, 0x60, 0x03, 0x02, 0x0e, 0xac, 0x90, 0xfa, 0xb5, 0xe0, 0xff, 
-0x12, 0x2f, 0x3b, 0x40, 0x03, 0x02, 0x0e, 0xac, 0xe5, 0x2c, 0x20, 0xe1, 0x06, 0x20, 0xe0, 0x03, 
-0x02, 0x0e, 0xac, 0xe5, 0x53, 0x70, 0x09, 0x30, 0x0a, 0x03, 0x02, 0x19, 0x7a, 0x02, 0x19, 0x3e, 
-0xe5, 0x2c, 0x20, 0xe1, 0x03, 0x02, 0x0e, 0xac, 0x15, 0x53, 0x30, 0x0a, 0x0b, 0x12, 0x18, 0xbd, 
-0xf5, 0x83, 0xe0, 0x44, 0x08, 0xf0, 0x80, 0x09, 0x12, 0x18, 0xcb, 0xf5, 0x83, 0xe0, 0x44, 0x08, 
-0xf0, 0xe4, 0xff, 0x02, 0x2f, 0x6a, 0xe5, 0x2c, 0x30, 0xe7, 0x03, 0x02, 0x0e, 0xac, 0xe5, 0x35, 
-0x45, 0x34, 0x60, 0x03, 0x02, 0x0e, 0xac, 0x90, 0xfa, 0xb5, 0xe0, 0x60, 0x03, 0x02, 0x0e, 0xac, 
-0x12, 0x18, 0xd9, 0x60, 0x03, 0x02, 0x0e, 0xac, 0xe5, 0x2c, 0x30, 0xe1, 0x03, 0x02, 0x0e, 0xac, 
-0x90, 0xfa, 0xba, 0xe0, 0x90, 0xff, 0xff, 0xf0, 0xe0, 0x60, 0x05, 0x43, 0x2c, 0x01, 0x80, 0x03, 
-0x53, 0x2c, 0xfe, 0xe4, 0xff, 0x02, 0x2f, 0x6a, 0xe5, 0x2c, 0x20, 0xe7, 0x03, 0x02, 0x0e, 0xac, 
-0xe5, 0x35, 0x45, 0x34, 0x70, 0x03, 0x02, 0x0e, 0xac, 0x12, 0x18, 0xd9, 0x60, 0x03, 0x02, 0x0e, 
-0xac, 0x90, 0xfa, 0xb9, 0xe0, 0xfc, 0xa3, 0xe0, 0xfd, 0xec, 0x24, 0xfe, 0x60, 0x3a, 0x14, 0x60, 
-0x75, 0x24, 0x02, 0x60, 0x03, 0x02, 0x0e, 0xac, 0xed, 0x60, 0x03, 0x02, 0x0e, 0xac, 0x12, 0x18, 
-0x49, 0x12, 0x19, 0x73, 0x7d, 0x03, 0x12, 0x0e, 0xf3, 0x60, 0x03, 0x02, 0x0e, 0xac, 0x12, 0x0e, 
-0xb0, 0x90, 0xfa, 0xb2, 0xe0, 0xfd, 0xa3, 0x12, 0x18, 0x93, 0x12, 0x0f, 0x0f, 0x50, 0x02, 0x80, 
-0x04, 0xae, 0x34, 0xaf, 0x35, 0x02, 0x0f, 0x40, 0x12, 0x18, 0x49, 0x90, 0xf9, 0x65, 0xe0, 0x30, 
-0xe4, 0x0d, 0x12, 0x19, 0x73, 0x7d, 0x14, 0x12, 0x0e, 0xf3, 0x60, 0x10, 0x02, 0x0e, 0xac, 0x12, 
-0x19, 0x73, 0x7d, 0x04, 0x12, 0x0f, 0x47, 0x60, 0x03, 0x02, 0x0e, 0xac, 0x12, 0x0e, 0xb0, 0x90, 
-0xfa, 0xb2, 0xe0, 0xfd, 0xa3, 0x12, 0x18, 0x93, 0x12, 0x0f, 0x0f, 0x50, 0x02, 0x80, 0x04, 0xae, 
-0x34, 0xaf, 0x35, 0x02, 0x0f, 0x40, 0x12, 0x19, 0x73, 0x7d, 0x05, 0x12, 0x0f, 0x47, 0x60, 0x03, 
-0x02, 0x0e, 0xac, 0x7b, 0x01, 0x7a, 0xfa, 0x79, 0xb2, 0x12, 0x18, 0x90, 0x7d, 0x01, 0x12, 0x23, 
-0xee, 0x90, 0xfa, 0xb3, 0xe4, 0x75, 0xf0, 0x03, 0x12, 0x14, 0x2f, 0x90, 0xfa, 0xba, 0xe0, 0x90, 
-0xfa, 0xb1, 0xf0, 0xe4, 0xf5, 0x52, 0x90, 0xfa, 0xb1, 0xe0, 0xff, 0xe5, 0x52, 0xc3, 0x9f, 0x50, 
-0x24, 0x12, 0x18, 0x8a, 0x12, 0x0f, 0x52, 0xff, 0xfd, 0x90, 0xfa, 0xb3, 0xe4, 0x8d, 0xf0, 0x12, 
-0x14, 0x2f, 0x90, 0xfa, 0xb2, 0xe0, 0xc3, 0x9f, 0xf0, 0xd3, 0x94, 0x00, 0x50, 0x03, 0x02, 0x0e, 
-0xac, 0x05, 0x52, 0x80, 0xd1, 0x12, 0x18, 0x8a, 0x12, 0x0f, 0x52, 0x24, 0xfe, 0xff, 0x90, 0xfa, 
-0xb2, 0xf0, 0xfd, 0xa3, 0xe4, 0x75, 0xf0, 0x02, 0x12, 0x14, 0x2f, 0x7a, 0xf9, 0x79, 0x6e, 0x7b, 
-0x01, 0x8b, 0x2d, 0x8a, 0x2e, 0x89, 0x2f, 0xe9, 0x24, 0x02, 0xf9, 0xe4, 0x3a, 0xfa, 0x12, 0x18, 
-0x90, 0x12, 0x23, 0xee, 0x8f, 0x52, 0x05, 0x52, 0x05, 0x52, 0x12, 0x18, 0x2a, 0xe5, 0x52, 0x12, 
-0x13, 0xfb, 0x12, 0x18, 0x2a, 0x90, 0x00, 0x01, 0x74, 0x03, 0x12, 0x14, 0x0d, 0xaf, 0x52, 0x7e, 
-0x00, 0xc3, 0xef, 0x95, 0x35, 0xee, 0x95, 0x34, 0x50, 0x02, 0x80, 0x04, 0xae, 0x34, 0xaf, 0x35, 
-0x8e, 0x30, 0x8f, 0x31, 0x02, 0x29, 0x2d, 0x02, 0x0e, 0xac, 0xe5, 0x2c, 0x20, 0xe7, 0x03, 0x02, 
-0x0e, 0xac, 0xe5, 0x35, 0x64, 0x01, 0x45, 0x34, 0x60, 0x03, 0x02, 0x0e, 0xac, 0x90, 0xfa, 0xb5, 
-0xe0, 0x60, 0x03, 0x02, 0x0e, 0xac, 0x90, 0xfa, 0xb9, 0xe0, 0x70, 0x02, 0xa3, 0xe0, 0x60, 0x03, 
-0x02, 0x0e, 0xac, 0x12, 0x18, 0xd9, 0x60, 0x03, 0x02, 0x0e, 0xac, 0xe5, 0x2c, 0x20, 0xe0, 0x06, 
-0x20, 0xe1, 0x03, 0x02, 0x0e, 0xac, 0x75, 0x2d, 0x00, 0x75, 0x2e, 0x00, 0x75, 0x2f, 0x29, 0x02, 
-0x0f, 0x2f, 0xe5, 0x2c, 0x30, 0xe7, 0x03, 0x02, 0x0e, 0xac, 0xe5, 0x35, 0x45, 0x34, 0x60, 0x03, 
-0x02, 0x0e, 0xac, 0x90, 0xfa, 0xb5, 0xe0, 0x60, 0x03, 0x02, 0x0e, 0xac, 0xd3, 0x90, 0xfa, 0xba, 
-0xe0, 0x94, 0x01, 0x90, 0xfa, 0xb9, 0xe0, 0x94, 0x00, 0x40, 0x03, 0x02, 0x0e, 0xac, 0x12, 0x18, 
-0xd9, 0x60, 0x03, 0x02, 0x0e, 0xac, 0xe5, 0x2c, 0x20, 0xe0, 0x06, 0x20, 0xe1, 0x03, 0x02, 0x0e, 
-0xac, 0x90, 0xfa, 0xba, 0xe0, 0xf5, 0x29, 0xe5, 0x29, 0x70, 0x08, 0x43, 0x2c, 0x01, 0x53, 0x2c, 
-0xfd, 0x80, 0x06, 0x53, 0x2c, 0xfe, 0x43, 0x2c, 0x02, 0xe4, 0xff, 0x02, 0x2f, 0x6a, 0xe5, 0x2c, 
-0x20, 0xe7, 0x03, 0x02, 0x0e, 0xac, 0xe5, 0x35, 0x64, 0x01, 0x45, 0x34, 0x60, 0x03, 0x02, 0x0e, 
-0xac, 0x90, 0xfa, 0xb5, 0xe0, 0x60, 0x03, 0x02, 0x0e, 0xac, 0x90, 0xfa, 0xb9, 0xe0, 0x70, 0x02, 
-0xa3, 0xe0, 0x60, 0x03, 0x02, 0x0e, 0xac, 0x12, 0x18, 0xd9, 0x64, 0x01, 0x60, 0x03, 0x02, 0x0e, 
-0xac, 0xe5, 0x2c, 0x20, 0xe1, 0x03, 0x02, 0x0e, 0xac, 0x7f, 0x01, 0x02, 0x2f, 0x6a, 0xe5, 0x2c, 
-0x30, 0xe7, 0x03, 0x02, 0x0e, 0xac, 0xe5, 0x35, 0x45, 0x34, 0x60, 0x03, 0x02, 0x0e, 0xac, 0xd3, 
-0x90, 0xfa, 0xba, 0xe0, 0x94, 0x00, 0x90, 0xfa, 0xb9, 0xe0, 0x94, 0x00, 0x40, 0x03, 0x02, 0x0e, 
-0xac, 0x12, 0x18, 0xd9, 0x64, 0x01, 0x60, 0x03, 0x02, 0x0e, 0xac, 0xe5, 0x2c, 0x20, 0xe1, 0x03, 
-0x02, 0x0e, 0xac, 0xe4, 0xff, 0x02, 0x2f, 0x6a, 0x90, 0xff, 0x01, 0x12, 0x19, 0x8a, 0xef, 0x12, 
-0x13, 0xfb, 0x90, 0xfa, 0xb5, 0x12, 0x19, 0x8a, 0x90, 0x00, 0x01, 0xef, 0x12, 0x14, 0x0d, 0x90, 
-0x00, 0x02, 0xe4, 0x12, 0x14, 0x0d, 0x74, 0x03, 0x12, 0x18, 0x1b, 0x90, 0xfa, 0xb9, 0xe0, 0xff, 
-0xa3, 0xe0, 0x85, 0x2f, 0x82, 0x85, 0x2e, 0x83, 0xcf, 0xf0, 0xa3, 0xef, 0xf0, 0x90, 0xff, 0x01, 
-0xe0, 0x12, 0x15, 0x0f, 0x09, 0x3d, 0x02, 0x09, 0x5f, 0x04, 0x09, 0x81, 0x05, 0x09, 0xad, 0x06, 
-0x09, 0xcb, 0x07, 0x09, 0xe9, 0x08, 0x0a, 0x07, 0x09, 0x0a, 0x25, 0x0b, 0x0a, 0xda, 0x80, 0x0c, 
-0xfa, 0x81, 0x0d, 0x1c, 0x82, 0x0b, 0x21, 0x83, 0x0b, 0x6a, 0x84, 0x0b, 0x89, 0x85, 0x0b, 0xc5, 
-0x86, 0x0c, 0x07, 0x87, 0x0c, 0x95, 0x88, 0x0c, 0xd0, 0x89, 0x0a, 0x43, 0x92, 0x0a, 0x43, 0x93, 
-0x0d, 0xcf, 0xc0, 0x0e, 0x00, 0xc1, 0x0e, 0x11, 0xc2, 0x00, 0x00, 0x0e, 0x9b, 0xe5, 0x2c, 0x20, 
-0xe7, 0x05, 0x7f, 0x05, 0x02, 0x2e, 0xa5, 0x12, 0x18, 0xe0, 0x60, 0x03, 0x04, 0x70, 0x09, 0xef, 
-0xfd, 0x7c, 0x00, 0x7f, 0x07, 0x02, 0x10, 0x9c, 0xe4, 0xfd, 0x7f, 0x07, 0x02, 0x2c, 0xc0, 0xe5, 
-0x2c, 0x20, 0xe7, 0x05, 0x7f, 0x05, 0x02, 0x2e, 0xa5, 0x12, 0x18, 0xe0, 0x60, 0x03, 0x04, 0x70, 
-0x09, 0xef, 0xfd, 0x7c, 0x00, 0x7f, 0x0c, 0x02, 0x10, 0x9c, 0xe4, 0xfd, 0x7f, 0x07, 0x02, 0x2c, 
-0xc0, 0xe5, 0x2c, 0x30, 0xe7, 0x03, 0x02, 0x0e, 0xaf, 0x12, 0x19, 0x99, 0x50, 0x06, 0xe5, 0x35, 
-0x45, 0x34, 0x70, 0x05, 0x7f, 0x02, 0x02, 0x2e, 0xa5, 0x90, 0xfa, 0xb5, 0xe0, 0x24, 0xfe, 0x24, 
-0xfd, 0x50, 0x02, 0x80, 0x03, 0x02, 0x2f, 0x28, 0x7f, 0x07, 0x02, 0x2e, 0xa5, 0xe5, 0x2c, 0x30, 
-0xe7, 0x03, 0x02, 0x0e, 0xaf, 0x12, 0x18, 0xe0, 0x60, 0x03, 0x04, 0x70, 0x09, 0xef, 0xfd, 0x7c, 
-0x00, 0x7f, 0x08, 0x02, 0x10, 0x9c, 0x7f, 0x07, 0x02, 0x2e, 0xa5, 0xe5, 0x2c, 0x30, 0xe7, 0x03, 
-0x02, 0x0e, 0xaf, 0x12, 0x18, 0xe0, 0x60, 0x03, 0x04, 0x70, 0x09, 0xef, 0xfd, 0x7c, 0x00, 0x7f, 
-0x09, 0x02, 0x10, 0x9c, 0x7f, 0x07, 0x02, 0x2e, 0xa5, 0xe5, 0x2c, 0x30, 0xe7, 0x03, 0x02, 0x0e, 
-0xaf, 0x12, 0x18, 0xe0, 0x60, 0x03, 0x04, 0x70, 0x09, 0xef, 0xfd, 0x7c, 0x00, 0x7f, 0x0a, 0x02, 
-0x10, 0x9c, 0x7f, 0x07, 0x02, 0x2e, 0xa5, 0xe5, 0x2c, 0x30, 0xe7, 0x03, 0x02, 0x0e, 0xaf, 0x12, 
-0x18, 0xe0, 0x60, 0x03, 0x04, 0x70, 0x09, 0xef, 0xfd, 0x7c, 0x00, 0x7f, 0x0b, 0x02, 0x10, 0x9c, 
-0x7f, 0x07, 0x02, 0x2e, 0xa5, 0xe5, 0x2c, 0x30, 0xe7, 0x03, 0x02, 0x0e, 0xaf, 0x12, 0x18, 0xe0, 
-0x60, 0x03, 0x04, 0x70, 0x09, 0xef, 0xfd, 0x7c, 0x00, 0x7f, 0x0e, 0x02, 0x10, 0x9c, 0x7f, 0x07, 
-0x02, 0x2e, 0xa5, 0xe5, 0x2c, 0x30, 0xe7, 0x56, 0x12, 0x18, 0xd9, 0x70, 0x4a, 0x90, 0xff, 0x02, 
-0xe0, 0xf5, 0x52, 0xe5, 0x52, 0xb4, 0x82, 0x05, 0x75, 0x52, 0x61, 0x80, 0x12, 0xe5, 0x52, 0xb4, 
-0x83, 0x05, 0x75, 0x52, 0x62, 0x80, 0x08, 0xe5, 0x52, 0xc4, 0x54, 0xf0, 0x04, 0xf5, 0x52, 0x12, 
-0x17, 0x8b, 0x12, 0x19, 0x6c, 0x12, 0x22, 0xb8, 0x12, 0x18, 0xe8, 0x12, 0x13, 0xce, 0x60, 0x05, 
-0x12, 0x2f, 0x76, 0x80, 0x06, 0x85, 0x2a, 0x30, 0x85, 0x2b, 0x31, 0x75, 0x2d, 0x01, 0x75, 0x2e, 
-0xf9, 0x75, 0x2f, 0x71, 0x02, 0x29, 0x2d, 0xe4, 0xfd, 0x7f, 0x05, 0x02, 0x2c, 0xc0, 0x12, 0x18, 
-0xd9, 0x60, 0x05, 0x7f, 0x05, 0x02, 0x2e, 0xa5, 0x12, 0x19, 0x99, 0x40, 0x05, 0x7f, 0x03, 0x02, 
-0x2e, 0xa5, 0x90, 0xff, 0x02, 0xe0, 0xf5, 0x52, 0xe5, 0x52, 0xb4, 0x82, 0x05, 0x75, 0x52, 0x61, 
-0x80, 0x12, 0xe5, 0x52, 0xb4, 0x83, 0x05, 0x75, 0x52, 0x62, 0x80, 0x08, 0xe5, 0x52, 0xc4, 0x54, 
-0xf0, 0x04, 0xf5, 0x52, 0x12, 0x17, 0x8b, 0x02, 0x2f, 0x28, 0x12, 0x19, 0xa3, 0x12, 0x27, 0x19, 
-0x12, 0x18, 0x9b, 0xe0, 0x54, 0x7f, 0xf0, 0x00, 0x00, 0x00, 0xe0, 0x90, 0xfa, 0xb6, 0xf0, 0x78, 
-0x6e, 0x12, 0x14, 0xeb, 0x90, 0x00, 0x02, 0x12, 0x13, 0xce, 0x30, 0xe7, 0xf2, 0x90, 0x00, 0x02, 
-0xe4, 0x12, 0x14, 0x0d, 0x90, 0xfa, 0xb6, 0xe0, 0x44, 0x80, 0xff, 0xf0, 0x78, 0x82, 0xe6, 0xfc, 
-0x08, 0xe6, 0x8c, 0x83, 0x12, 0x18, 0xa3, 0xef, 0xf0, 0x12, 0x2f, 0x80, 0xe4, 0xff, 0x02, 0x2e, 
-0xa5, 0x90, 0xfa, 0xb5, 0xe0, 0x64, 0x01, 0x70, 0x1f, 0x90, 0xfa, 0xb9, 0xe0, 0xff, 0x7e, 0x00, 
-0x70, 0x06, 0xa3, 0xe0, 0xf5, 0x90, 0x80, 0x2d, 0xc2, 0xaf, 0xef, 0xf4, 0x52, 0x90, 0x90, 0xfa, 
-0xba, 0xe0, 0x42, 0x90, 0xd2, 0xaf, 0x80, 0x1d, 0x90, 0xfa, 0xb9, 0xe0, 0xff, 0x7e, 0x00, 0x70, 
-0x06, 0xa3, 0xe0, 0xf5, 0xb0, 0x80, 0x0e, 0xc2, 0xaf, 0xef, 0xf4, 0x52, 0xb0, 0x90, 0xfa, 0xba, 
-0xe0, 0x42, 0xb0, 0xd2, 0xaf, 0xe4, 0xff, 0x02, 0x2e, 0xa5, 0x12, 0x18, 0x49, 0x90, 0xfa, 0xb5, 
-0xe0, 0xb4, 0x01, 0x0a, 0x12, 0x18, 0x2a, 0xe5, 0x90, 0x12, 0x13, 0xfb, 0x80, 0x08, 0x12, 0x18, 
-0x2a, 0xe5, 0xb0, 0x12, 0x13, 0xfb, 0x02, 0x0f, 0x2f, 0x90, 0xf9, 0x65, 0xe0, 0x20, 0xe1, 0x30, 
-0x12, 0x18, 0x53, 0x60, 0x18, 0x04, 0x70, 0x28, 0x90, 0xfa, 0xb6, 0xe0, 0x60, 0x09, 0x90, 0xff, 
-0xa4, 0xe0, 0x44, 0x10, 0xf0, 0x80, 0x19, 0x12, 0x19, 0xad, 0xf0, 0x80, 0x13, 0x90, 0xfa, 0xb6, 
-0xe0, 0x60, 0x09, 0x90, 0xff, 0xb4, 0xe0, 0x44, 0x10, 0xf0, 0x80, 0x04, 0x12, 0x19, 0xb4, 0xf0, 
-0xe4, 0xff, 0x02, 0x2e, 0xa5, 0x90, 0xf9, 0x65, 0xe0, 0x20, 0xe1, 0x36, 0x12, 0x18, 0x53, 0x60, 
-0x1b, 0x04, 0x70, 0x2e, 0x90, 0xfa, 0xb6, 0xe0, 0x60, 0x09, 0x90, 0xff, 0xa4, 0xe0, 0x44, 0x20, 
-0xf0, 0x80, 0x1f, 0x90, 0xff, 0xa4, 0xe0, 0x54, 0xdf, 0xf0, 0x80, 0x16, 0x90, 0xfa, 0xb6, 0xe0, 
-0x60, 0x09, 0x90, 0xff, 0xb4, 0xe0, 0x44, 0x20, 0xf0, 0x80, 0x07, 0x90, 0xff, 0xb4, 0xe0, 0x54, 
-0xdf, 0xf0, 0xe4, 0xff, 0x02, 0x2e, 0xa5, 0x12, 0x18, 0x53, 0x60, 0x46, 0x04, 0x60, 0x03, 0x02, 
-0x0c, 0x90, 0x90, 0xfa, 0xb6, 0xe0, 0x60, 0x17, 0x90, 0xff, 0xa4, 0xe0, 0x44, 0x04, 0xf0, 0x90, 
-0xf9, 0x65, 0xe0, 0x30, 0xe1, 0x6a, 0x90, 0xff, 0xa4, 0xe0, 0x44, 0x02, 0xf0, 0x80, 0x61, 0x90, 
-0xff, 0xa4, 0xe0, 0x54, 0xfb, 0xf0, 0x90, 0xf9, 0x65, 0xe0, 0x30, 0xe1, 0x53, 0x30, 0x95, 0x09, 
-0x90, 0xff, 0xa4, 0xe0, 0x44, 0x02, 0xf0, 0x80, 0x47, 0x90, 0xff, 0xa4, 0xe0, 0x54, 0xfd, 0xf0, 
-0x80, 0x3e, 0x90, 0xfa, 0xb6, 0xe0, 0x60, 0x17, 0x90, 0xff, 0xb4, 0xe0, 0x44, 0x04, 0xf0, 0x90, 
-0xf9, 0x65, 0xe0, 0x30, 0xe1, 0x2a, 0x90, 0xff, 0xb4, 0xe0, 0x44, 0x02, 0xf0, 0x80, 0x21, 0x90, 
-0xff, 0xb4, 0xe0, 0x54, 0xfb, 0xf0, 0x90, 0xf9, 0x65, 0xe0, 0x30, 0xe1, 0x13, 0x30, 0x93, 0x09, 
-0x90, 0xff, 0xb4, 0xe0, 0x44, 0x02, 0xf0, 0x80, 0x07, 0x90, 0xff, 0xb4, 0xe0, 0x54, 0xfd, 0xf0, 
-0xe4, 0xff, 0x02, 0x2e, 0xa5, 0x12, 0x18, 0x53, 0x60, 0x1b, 0x04, 0x70, 0x2e, 0x90, 0xfa, 0xb6, 
-0xe0, 0x60, 0x09, 0x90, 0xff, 0xa2, 0xe0, 0x44, 0x40, 0xf0, 0x80, 0x1f, 0x90, 0xff, 0xa2, 0xe0, 
-0x54, 0xbf, 0xf0, 0x80, 0x16, 0x90, 0xfa, 0xb6, 0xe0, 0x60, 0x09, 0x90, 0xff, 0xb2, 0xe0, 0x44, 
-0x40, 0xf0, 0x80, 0x07, 0x90, 0xff, 0xb2, 0xe0, 0x54, 0xbf, 0xf0, 0xe4, 0xff, 0x02, 0x2e, 0xa5, 
-0x12, 0x18, 0x49, 0x12, 0x18, 0x5b, 0x60, 0x0f, 0x04, 0x70, 0x16, 0x90, 0xff, 0xa4, 0xe0, 0x12, 
-0x18, 0x2a, 0x12, 0x13, 0xfb, 0x80, 0x0a, 0x90, 0xff, 0xb4, 0xe0, 0x12, 0x18, 0x2a, 0x12, 0x13, 
-0xfb, 0x75, 0x30, 0x00, 0x75, 0x31, 0x01, 0x02, 0x29, 0x2d, 0xe4, 0xff, 0x12, 0x2e, 0xa5, 0x12, 
-0x19, 0x46, 0x7f, 0x03, 0x12, 0x11, 0x9f, 0x90, 0xff, 0xfc, 0xe0, 0x54, 0x7f, 0xf0, 0x7f, 0xff, 
-0x7e, 0x00, 0x12, 0x2d, 0xee, 0xc2, 0x90, 0xc2, 0xaf, 0x00, 0x80, 0xfd, 0xe4, 0xf5, 0x54, 0xf5, 
-0x55, 0x90, 0xfa, 0xbb, 0x74, 0x3e, 0xf0, 0xa3, 0xe4, 0xf0, 0x90, 0xfa, 0xb3, 0xf0, 0xa3, 0x74, 
-0x15, 0xf0, 0xe0, 0x54, 0x3f, 0xff, 0xc3, 0x74, 0x40, 0x9f, 0x90, 0xfa, 0xb8, 0xf0, 0xd3, 0x94, 
-0x00, 0xe4, 0x94, 0x3e, 0x40, 0x08, 0x90, 0xfa, 0xbc, 0xe0, 0x90, 0xfa, 0xb8, 0xf0, 0x12, 0x0e, 
-0xd6, 0xe5, 0x23, 0x45, 0x22, 0x70, 0x73, 0x12, 0x18, 0x62, 0x90, 0xfa, 0xbb, 0x12, 0x19, 0x65, 
-0x60, 0x27, 0xd3, 0xef, 0x94, 0x40, 0xee, 0x94, 0x00, 0x40, 0x08, 0x90, 0xfa, 0xb8, 0x74, 0x40, 
-0xf0, 0x80, 0x08, 0x90, 0xfa, 0xbc, 0xe0, 0x90, 0xfa, 0xb8, 0xf0, 0x12, 0x0e, 0xd6, 0xe5, 0x23, 
-0x45, 0x22, 0x70, 0x46, 0x12, 0x18, 0x62, 0x80, 0xd1, 0x75, 0x52, 0x02, 0x90, 0xfa, 0xbb, 0xe4, 
-0xf0, 0xa3, 0x04, 0xf0, 0x90, 0xfa, 0xb3, 0xe4, 0xf0, 0xa3, 0x74, 0x0f, 0xf0, 0x7b, 0x00, 0x7a, 
-0x00, 0x79, 0x52, 0x90, 0xfa, 0xbc, 0xe0, 0xf5, 0x50, 0x7d, 0x0f, 0x7c, 0x00, 0x12, 0x26, 0x25, 
-0x75, 0x22, 0x00, 0x8f, 0x23, 0x7b, 0x00, 0x7a, 0x00, 0x79, 0x52, 0xe4, 0xf5, 0x40, 0xf5, 0x41, 
-0x7d, 0x01, 0x12, 0x23, 0xee, 0xe4, 0xf5, 0x22, 0xf5, 0x23, 0xaf, 0x23, 0x02, 0x2e, 0xa5, 0x90, 
-0xfa, 0xba, 0xe0, 0x90, 0xfa, 0xb6, 0xf0, 0x30, 0xe7, 0x10, 0xe0, 0x54, 0x0f, 0x90, 0xf9, 0x62, 
-0xf0, 0xd3, 0x94, 0x00, 0x40, 0x15, 0xc2, 0x95, 0x80, 0x11, 0x90, 0xfa, 0xb6, 0xe0, 0x54, 0x0f, 
-0x90, 0xf9, 0x61, 0xf0, 0xd3, 0x94, 0x00, 0x40, 0x02, 0xc2, 0x94, 0xe4, 0xff, 0x02, 0x2e, 0xa5, 
-0x12, 0x19, 0xa3, 0xbf, 0x01, 0x04, 0xd2, 0x93, 0x80, 0x02, 0xc2, 0x93, 0xe4, 0xff, 0x02, 0x2e, 
-0xa5, 0x90, 0xfa, 0xba, 0xe0, 0x90, 0xfa, 0xb6, 0xf0, 0x54, 0x03, 0x14, 0x60, 0x0a, 0x14, 0x60, 
-0x0f, 0x14, 0x60, 0x08, 0x24, 0x03, 0x70, 0x2b, 0xd2, 0x91, 0x80, 0x27, 0xc2, 0x91, 0x80, 0x23, 
-0x12, 0x19, 0xad, 0x12, 0x0e, 0xfe, 0x60, 0x04, 0xd2, 0x91, 0x80, 0x17, 0x90, 0xff, 0xa4, 0xe0, 
-0x44, 0x10, 0x12, 0x0e, 0xfe, 0xff, 0xbf, 0xa0, 0x04, 0xc2, 0x91, 0x80, 0x02, 0xd2, 0x91, 0x12, 
-0x19, 0xad, 0xf0, 0x90, 0xfa, 0xb6, 0xe0, 0x54, 0x0c, 0xff, 0x13, 0x13, 0x54, 0x3f, 0x14, 0x60, 
-0x0a, 0x14, 0x60, 0x0f, 0x14, 0x60, 0x08, 0x24, 0x03, 0x70, 0x2b, 0xd2, 0x92, 0x80, 0x27, 0xc2, 
-0x92, 0x80, 0x23, 0x12, 0x19, 0xb4, 0x12, 0x0f, 0x1e, 0x60, 0x04, 0xd2, 0x92, 0x80, 0x17, 0x90, 
-0xff, 0xb4, 0xe0, 0x44, 0x10, 0x12, 0x0f, 0x1e, 0xff, 0xbf, 0xa0, 0x04, 0xc2, 0x92, 0x80, 0x02, 
-0xd2, 0x92, 0x12, 0x19, 0xb4, 0xf0, 0xe4, 0xff, 0x02, 0x2e, 0xa5, 0xe5, 0x2c, 0x30, 0xe7, 0x07, 
-0xe4, 0xfd, 0x7f, 0x05, 0x02, 0x2c, 0xc0, 0x7f, 0x05, 0x02, 0x2e, 0xa5, 0x12, 0x2f, 0x76, 0x22, 
-0x7b, 0x01, 0x7a, 0xfa, 0x79, 0xb2, 0x90, 0xfa, 0xb3, 0xe0, 0xf5, 0x40, 0xa3, 0xe0, 0xf5, 0x41, 
-0x7d, 0x01, 0x12, 0x23, 0xee, 0x90, 0xfa, 0xb3, 0xe4, 0x75, 0xf0, 0x03, 0x12, 0x14, 0x2f, 0xab, 
-0x2d, 0xaa, 0x2e, 0xa9, 0x2f, 0x22, 0xaa, 0x54, 0xa9, 0x55, 0x7b, 0xff, 0x90, 0xfa, 0xb3, 0xe0, 
-0xfc, 0xa3, 0xe0, 0xfd, 0x90, 0xfa, 0xb8, 0xe0, 0xf5, 0x50, 0x12, 0x26, 0x25, 0x75, 0x22, 0x00, 
-0x8f, 0x23, 0x22, 0x12, 0x20, 0xc5, 0x7e, 0x00, 0x8e, 0x22, 0x8f, 0x23, 0xef, 0x22, 0xf0, 0x7f, 
-0x01, 0x12, 0x11, 0x9f, 0x90, 0xff, 0xa6, 0xe0, 0x90, 0xfa, 0xb7, 0xf0, 0x54, 0xa0, 0x22, 0x12, 
-0x23, 0xee, 0x8f, 0x52, 0x7e, 0x00, 0xc3, 0xef, 0x95, 0x35, 0xee, 0x95, 0x34, 0x22, 0xf0, 0x7f, 
-0x01, 0x12, 0x11, 0x9f, 0x90, 0xff, 0xb6, 0xe0, 0x90, 0xfa, 0xb7, 0xf0, 0x54, 0xa0, 0x22, 0x75, 
-0x30, 0x00, 0x75, 0x31, 0x01, 0x02, 0x29, 0x2d, 0x90, 0xfa, 0xb5, 0xe0, 0xff, 0x02, 0x2f, 0x3b, 
-0x8e, 0x30, 0x8f, 0x31, 0x02, 0x29, 0x2d, 0x12, 0x20, 0xc5, 0x7e, 0x00, 0x8e, 0x22, 0x8f, 0x23, 
-0xef, 0x22, 0x7d, 0x01, 0x12, 0x23, 0xee, 0x90, 0xfa, 0xb0, 0xe0, 0x22, 0xef, 0x90, 0xf8, 0x04, 
-0xf0, 0x22, 0xc0, 0xa8, 0xc2, 0xaf, 0xee, 0x60, 0x0a, 0xc0, 0x05, 0x7d, 0x7f, 0xdd, 0xfe, 0xde, 
-0xfa, 0xd0, 0x05, 0xef, 0xc3, 0x94, 0x15, 0x50, 0x03, 0xd0, 0xa8, 0x22, 0x13, 0x70, 0x03, 0xd0, 
-0xa8, 0x22, 0xff, 0xd5, 0x07, 0xfd, 0xd0, 0xa8, 0x22, 0xc0, 0x00, 0xc0, 0x01, 0xc0, 0x02, 0xc0, 
-0x04, 0xc0, 0x05, 0xe5, 0x44, 0x24, 0x08, 0xf8, 0x86, 0x05, 0x53, 0x05, 0x7f, 0x7c, 0xff, 0x12, 
-0x0f, 0xfe, 0x7f, 0x00, 0x7e, 0x00, 0xe5, 0x49, 0x60, 0x46, 0xfc, 0x90, 0xf9, 0x19, 0xe0, 0x54, 
-0x7f, 0x6d, 0x70, 0x0f, 0xc0, 0x83, 0xc0, 0x82, 0xa3, 0xe0, 0xfe, 0xa3, 0xe0, 0xff, 0xa3, 0x15, 
-0x49, 0x80, 0x07, 0xa3, 0xa3, 0xa3, 0xdc, 0xe6, 0x80, 0x26, 0xdc, 0x06, 0xd0, 0x82, 0xd0, 0x83, 
-0x80, 0x1e, 0xe0, 0xf8, 0xa3, 0xe0, 0xf9, 0xa3, 0xe0, 0xfa, 0xd0, 0x82, 0xd0, 0x83, 0xe8, 0xf0, 
-0xa3, 0xe9, 0xf0, 0xa3, 0xea, 0xf0, 0xa3, 0xc0, 0x83, 0xc0, 0x82, 0xa3, 0xa3, 0xa3, 0x80, 0xda, 
-0x12, 0x10, 0x95, 0xd0, 0x05, 0xd0, 0x04, 0xd0, 0x02, 0xd0, 0x01, 0xd0, 0x00, 0x22, 0x85, 0xa8, 
-0x4a, 0x75, 0xa8, 0x88, 0xec, 0x70, 0x02, 0x7c, 0x3f, 0x8c, 0x43, 0x22, 0xe5, 0x44, 0x24, 0x08, 
-0xf8, 0x76, 0x00, 0x12, 0x10, 0xec, 0x80, 0xfb, 0xc0, 0x00, 0xc0, 0x01, 0xc0, 0x02, 0xc0, 0x04, 
-0xc0, 0x06, 0x7c, 0xff, 0x12, 0x0f, 0xfe, 0xe5, 0x49, 0x60, 0x42, 0xfe, 0x90, 0xf9, 0x19, 0xe0, 
-0x54, 0x7f, 0x6f, 0x70, 0x0b, 0xc0, 0x83, 0xc0, 0x82, 0xa3, 0xa3, 0xa3, 0x15, 0x49, 0x80, 0x07, 
-0xa3, 0xa3, 0xa3, 0xde, 0xea, 0x80, 0x26, 0xde, 0x06, 0xd0, 0x82, 0xd0, 0x83, 0x80, 0xd8, 0xe0, 
-0xf8, 0xa3, 0xe0, 0xf9, 0xa3, 0xe0, 0xfa, 0xd0, 0x82, 0xd0, 0x83, 0xe8, 0xf0, 0xa3, 0xe9, 0xf0, 
-0xa3, 0xea, 0xf0, 0xa3, 0xc0, 0x83, 0xc0, 0x82, 0xa3, 0xa3, 0xa3, 0x80, 0xda, 0x78, 0x08, 0x08, 
-0x79, 0x18, 0x09, 0x7c, 0x01, 0xe6, 0x54, 0x7f, 0x6f, 0x70, 0x06, 0x76, 0x00, 0x77, 0x00, 0x80, 
-0x06, 0x08, 0x09, 0x0c, 0xbc, 0x08, 0xee, 0x12, 0x10, 0x95, 0xd0, 0x06, 0xd0, 0x04, 0xd0, 0x02, 
-0xd0, 0x01, 0xd0, 0x00, 0x22, 0x75, 0x43, 0x00, 0x85, 0x4a, 0xa8, 0x22, 0xc0, 0xf0, 0xc0, 0x82, 
-0xc0, 0x83, 0xc3, 0xe5, 0x49, 0x24, 0xe8, 0x50, 0x05, 0x12, 0x10, 0xec, 0x80, 0xf4, 0xef, 0x60, 
-0x31, 0x90, 0x2e, 0x2c, 0xe4, 0x93, 0xc3, 0x9f, 0x40, 0x2f, 0xc0, 0x04, 0x7c, 0xff, 0x12, 0x0f, 
-0xfe, 0xd0, 0x04, 0x43, 0x07, 0x80, 0xe5, 0x49, 0x75, 0xf0, 0x03, 0xa4, 0x24, 0x19, 0xf5, 0x82, 
-0xe4, 0x34, 0xf9, 0xf5, 0x83, 0xef, 0xf0, 0xec, 0xa3, 0xf0, 0xed, 0xa3, 0xf0, 0x05, 0x49, 0x12, 
-0x10, 0x95, 0xd0, 0x83, 0xd0, 0x82, 0xd0, 0xf0, 0x22, 0x02, 0x11, 0x1a, 0xc0, 0x04, 0x7c, 0x20, 
-0xd2, 0x8c, 0xd2, 0x8d, 0xd5, 0x04, 0xfd, 0xd0, 0x04, 0x22, 0x75, 0xa8, 0x00, 0x75, 0x88, 0x00, 
-0x75, 0xb8, 0x00, 0x75, 0xf0, 0x00, 0x75, 0xd0, 0x00, 0xe4, 0xf8, 0x90, 0xf8, 0x04, 0xf0, 0x90, 
-0x00, 0x00, 0xf6, 0x08, 0xb8, 0x00, 0xfb, 0x02, 0x00, 0x00, 0xc2, 0xaf, 0xe4, 0x90, 0xff, 0x48, 
-0xf0, 0x90, 0xff, 0x50, 0xf0, 0x90, 0xff, 0x08, 0xf0, 0x90, 0xff, 0x10, 0xf0, 0x90, 0xff, 0x80, 
-0xf0, 0xa3, 0xa3, 0xf0, 0xd2, 0xb1, 0xc2, 0xb0, 0x7e, 0xff, 0x7f, 0xff, 0x12, 0x0f, 0x62, 0x7e, 
-0xff, 0x7f, 0xff, 0x12, 0x0f, 0x62, 0x7e, 0xff, 0x7f, 0xff, 0x12, 0x0f, 0x62, 0xd2, 0xb0, 0xd2, 
-0xb1, 0x7e, 0xff, 0x7f, 0xff, 0x12, 0x0f, 0x62, 0x7e, 0xff, 0x7f, 0xff, 0x12, 0x0f, 0x62, 0x7e, 
-0xff, 0x7f, 0xff, 0x12, 0x0f, 0x62, 0x80, 0xcc, 0xc3, 0xee, 0x94, 0x02, 0x50, 0x04, 0x7e, 0x03, 
-0x7f, 0xe8, 0xef, 0xf4, 0xff, 0xee, 0xf4, 0xfe, 0x0f, 0xbf, 0x00, 0x01, 0x0e, 0x8f, 0x48, 0x8e, 
-0x47, 0x22, 0xc3, 0xef, 0x94, 0xbc, 0xee, 0x94, 0x02, 0x50, 0x04, 0x7e, 0x07, 0x7f, 0xd0, 0xef, 
-0xf4, 0xff, 0xee, 0xf4, 0xfe, 0x0f, 0xbf, 0x00, 0x01, 0x0e, 0x8f, 0x46, 0x8e, 0x45, 0x22, 0xef, 
-0x70, 0x01, 0x22, 0xc0, 0x00, 0xe5, 0x44, 0x24, 0x18, 0xf8, 0xa6, 0x07, 0xe5, 0x44, 0x24, 0x08, 
-0xf8, 0xc6, 0x54, 0x7f, 0xf6, 0xe6, 0x30, 0xe7, 0x03, 0xd0, 0x00, 0x22, 0x12, 0x10, 0xec, 0x80, 
+0x90, 0xff, 0x56, 0xe0, 0x30, 0xe7, 0x25, 0xd0, 0x83, 0xd0, 0x82, 0x74, 0x02, 0xf0, 0x80, 0x25, 
+0xb4, 0x02, 0x22, 0xc0, 0x82, 0xc0, 0x83, 0x90, 0xff, 0x7a, 0xe0, 0x30, 0xe7, 0x05, 0x12, 0x27, 
+0x8d, 0x80, 0x09, 0xd0, 0x83, 0xd0, 0x82, 0x74, 0x03, 0xf0, 0x80, 0x09, 0xd0, 0x83, 0xd0, 0x82, 
+0x80, 0x03, 0x02, 0x02, 0x62, 0x74, 0x15, 0xf5, 0x82, 0x74, 0xf9, 0xf5, 0x83, 0xe0, 0x20, 0x04, 
+0xf1, 0x20, 0x02, 0x03, 0x30, 0x01, 0xeb, 0x74, 0x18, 0xf5, 0x82, 0x74, 0xf9, 0xf5, 0x83, 0xe0, 
+0x14, 0xfc, 0xf0, 0xa3, 0xe0, 0xfd, 0xa3, 0xe0, 0xfe, 0x64, 0x04, 0x70, 0x0f, 0xec, 0x70, 0x62, 
+0x7e, 0x01, 0x12, 0x00, 0xc9, 0x7c, 0x0a, 0x7d, 0xfa, 0x02, 0x02, 0x33, 0x12, 0x00, 0xc9, 0xee, 
+0x64, 0x04, 0x60, 0x1d, 0xec, 0x70, 0x4b, 0x7c, 0x0a, 0xed, 0x14, 0xfd, 0x70, 0x15, 0xee, 0x64, 
+0x02, 0x60, 0x07, 0x7e, 0x02, 0x7d, 0x32, 0x02, 0x02, 0x33, 0x7e, 0x01, 0x7d, 0xfa, 0x02, 0x02, 
+0x33, 0x7c, 0x0a, 0x74, 0x18, 0xf5, 0x82, 0x74, 0xf9, 0xf5, 0x83, 0xec, 0xf0, 0xa3, 0xed, 0xf0, 
+0xa3, 0xee, 0xf0, 0x14, 0x60, 0x18, 0x20, 0xe1, 0x0f, 0x20, 0x01, 0x06, 0xd2, 0xb1, 0xc2, 0xb0, 
+0x80, 0x10, 0xc2, 0xb1, 0xd2, 0xb0, 0x80, 0x0a, 0xc2, 0xb1, 0xc2, 0xb0, 0x80, 0x04, 0xd2, 0xb0, 
+0xd2, 0xb1, 0x78, 0x19, 0x79, 0x09, 0x7a, 0x07, 0xe7, 0x70, 0x04, 0xa6, 0x00, 0x80, 0x0b, 0xe6, 
+0x60, 0x08, 0x16, 0xe6, 0x70, 0x04, 0xe7, 0x44, 0x80, 0xf7, 0x08, 0x09, 0xda, 0xea, 0xe5, 0x3d, 
+0x60, 0x13, 0x14, 0xf5, 0x3d, 0x70, 0x0e, 0xe5, 0x3e, 0x24, 0x08, 0xf8, 0x76, 0x00, 0x12, 0x11, 
+0x0f, 0xd2, 0x8c, 0xd2, 0x8d, 0xd0, 0x07, 0xd0, 0x06, 0xd0, 0x05, 0xd0, 0x04, 0xd0, 0x03, 0xd0, 
+0x02, 0xd0, 0x01, 0xd0, 0x00, 0xd0, 0x83, 0xd0, 0x82, 0xd0, 0xf0, 0xd0, 0xd0, 0xd0, 0xe0, 0x32, 
+0x90, 0xff, 0x04, 0xe0, 0x90, 0xfa, 0xb6, 0xf0, 0x90, 0xff, 0x06, 0xe0, 0xfc, 0xa3, 0xe0, 0xfa, 
+0xec, 0xff, 0xea, 0xfe, 0xef, 0xc3, 0x94, 0x08, 0xee, 0x94, 0x01, 0x50, 0x02, 0x80, 0x04, 0x7e, 
+0x01, 0x7f, 0x08, 0x8e, 0x3b, 0x8f, 0x3c, 0x90, 0xff, 0x02, 0xe0, 0xfc, 0xa3, 0xe0, 0xfa, 0xec, 
+0xff, 0xea, 0x90, 0xfa, 0xba, 0xf0, 0xef, 0xa3, 0xf0, 0x12, 0x1c, 0x30, 0xe4, 0xf5, 0x4d, 0xe5, 
+0x4d, 0xc3, 0x94, 0x02, 0x50, 0x0f, 0x12, 0x1c, 0x11, 0xe4, 0x12, 0x1a, 0x38, 0x05, 0x4d, 0x04, 
+0x12, 0x1c, 0x02, 0x80, 0xea, 0x12, 0x1c, 0x30, 0x90, 0xff, 0x00, 0xe0, 0xff, 0x54, 0x60, 0x24, 
+0xc0, 0x70, 0x03, 0x02, 0x08, 0xc5, 0x24, 0x40, 0x60, 0x03, 0x02, 0x0f, 0x26, 0x90, 0xfa, 0xb6, 
+0xe0, 0xfe, 0x54, 0x0f, 0xf5, 0x4d, 0xee, 0x30, 0xe7, 0x03, 0xd3, 0x80, 0x01, 0xc3, 0x92, 0x0a, 
+0x90, 0xff, 0x01, 0xe0, 0x12, 0x1b, 0x4c, 0x03, 0x56, 0x00, 0x04, 0x29, 0x01, 0x05, 0x3c, 0x03, 
+0x06, 0x03, 0x05, 0x06, 0x45, 0x06, 0x07, 0xa7, 0x08, 0x07, 0xef, 0x09, 0x08, 0x4b, 0x0a, 0x08, 
+0x8b, 0x0b, 0x00, 0x00, 0x0f, 0x26, 0xe5, 0x35, 0x20, 0xe7, 0x03, 0x02, 0x0f, 0x26, 0x90, 0xfa, 
+0xba, 0xe0, 0x70, 0x02, 0xa3, 0xe0, 0x60, 0x03, 0x02, 0x0f, 0x26, 0xe5, 0x3c, 0x64, 0x02, 0x45, 
+0x3b, 0x60, 0x03, 0x02, 0x0f, 0x26, 0xef, 0x54, 0x1f, 0x14, 0x60, 0x2b, 0x14, 0x60, 0x47, 0x24, 
+0x02, 0x60, 0x03, 0x02, 0x0f, 0x26, 0xee, 0x60, 0x03, 0x02, 0x0f, 0x26, 0x12, 0x1c, 0x11, 0x74, 
+0x01, 0x12, 0x1a, 0x38, 0x78, 0x67, 0xe6, 0x30, 0xe0, 0x08, 0x12, 0x1c, 0x11, 0x74, 0x02, 0x12, 
+0x1a, 0x38, 0x7f, 0x02, 0x02, 0x31, 0xb1, 0xe5, 0x35, 0x20, 0xe1, 0x09, 0x90, 0xfa, 0xb6, 0xe0, 
+0x60, 0x03, 0x02, 0x0f, 0x26, 0x90, 0xfa, 0xb6, 0xe0, 0xd3, 0x94, 0x01, 0x40, 0x03, 0x02, 0x0f, 
+0x26, 0x7f, 0x02, 0x02, 0x31, 0xb1, 0xe5, 0x35, 0x20, 0xe1, 0x0e, 0x90, 0xfa, 0xb6, 0xe0, 0xff, 
+0x60, 0x07, 0x64, 0x80, 0x60, 0x03, 0x02, 0x0f, 0x26, 0x12, 0x0f, 0xb2, 0x40, 0x03, 0x02, 0x0f, 
+0x26, 0xe5, 0x4d, 0x70, 0x19, 0x30, 0x0a, 0x0b, 0x90, 0xff, 0x80, 0x12, 0x1c, 0x0e, 0x12, 0x1a, 
+0x38, 0x80, 0x24, 0x90, 0xff, 0x82, 0x12, 0x1c, 0x0e, 0x12, 0x1a, 0x38, 0x80, 0x19, 0x15, 0x4d, 
+0x30, 0x0a, 0x0b, 0x12, 0x1c, 0xa5, 0x12, 0x1c, 0x0c, 0x12, 0x1a, 0x38, 0x80, 0x09, 0x12, 0x1c, 
+0xb3, 0x12, 0x1c, 0x0c, 0x12, 0x1a, 0x38, 0x12, 0x1c, 0x11, 0x12, 0x19, 0xf2, 0x60, 0x05, 0x74, 
+0x01, 0x12, 0x1a, 0x38, 0x7f, 0x02, 0x02, 0x31, 0xb1, 0xe5, 0x35, 0x30, 0xe7, 0x03, 0x02, 0x0f, 
+0x26, 0xe5, 0x3c, 0x45, 0x3b, 0x60, 0x03, 0x02, 0x0f, 0x26, 0x12, 0x1c, 0xc9, 0x14, 0x60, 0x2d, 
+0x14, 0x60, 0x59, 0x24, 0x02, 0x60, 0x03, 0x02, 0x0f, 0x26, 0x90, 0xfa, 0xba, 0xe0, 0x70, 0x04, 
+0xa3, 0xe0, 0x64, 0x01, 0x60, 0x03, 0x02, 0x0f, 0x26, 0x90, 0xfa, 0xb6, 0xe0, 0x60, 0x03, 0x02, 
+0x0f, 0x26, 0x78, 0x67, 0xe6, 0x54, 0xfe, 0xf6, 0xe4, 0xff, 0x02, 0x31, 0xb1, 0xe5, 0x35, 0x20, 
+0xe1, 0x06, 0x20, 0xe0, 0x03, 0x02, 0x0f, 0x26, 0xe5, 0x35, 0x30, 0xe0, 0x09, 0x90, 0xfa, 0xb6, 
+0xe0, 0x60, 0x03, 0x02, 0x0f, 0x26, 0xe5, 0x35, 0x30, 0xe1, 0x0c, 0x90, 0xfa, 0xb6, 0xe0, 0xd3, 
+0x94, 0x01, 0x40, 0x03, 0x02, 0x0f, 0x26, 0xe4, 0xff, 0x02, 0x31, 0xb1, 0x90, 0xfa, 0xba, 0xe0, 
+0x70, 0x02, 0xa3, 0xe0, 0x60, 0x03, 0x02, 0x0f, 0x26, 0x12, 0x0f, 0xb2, 0x40, 0x03, 0x02, 0x0f, 
+0x26, 0xe5, 0x35, 0x20, 0xe1, 0x06, 0x20, 0xe0, 0x03, 0x02, 0x0f, 0x26, 0xe5, 0x35, 0x30, 0xe0, 
+0x07, 0xe5, 0x4d, 0x60, 0x03, 0x02, 0x0f, 0x26, 0xe5, 0x4d, 0x70, 0x0f, 0x90, 0xff, 0x82, 0xe0, 
+0x54, 0xf7, 0xf0, 0x90, 0xff, 0x80, 0xe0, 0x54, 0xf7, 0xf0, 0x22, 0xe5, 0x4d, 0x24, 0xfe, 0x60, 
+0x20, 0x24, 0xfb, 0x60, 0x34, 0x24, 0x06, 0x70, 0x35, 0x30, 0x0a, 0x0c, 0xa2, 0x0a, 0xe4, 0x33, 
+0xfd, 0x7f, 0x03, 0x12, 0x2d, 0xa8, 0x80, 0x26, 0xe4, 0xfd, 0x7f, 0x03, 0x12, 0x2d, 0xa8, 0x80, 
+0x1d, 0x30, 0x0a, 0x0c, 0xa2, 0x0a, 0xe4, 0x33, 0xfd, 0x7f, 0x04, 0x12, 0x2d, 0xa8, 0x80, 0x0e, 
+0xe4, 0xfd, 0x7f, 0x04, 0x12, 0x2d, 0xa8, 0x80, 0x05, 0x7f, 0x87, 0x12, 0x31, 0x32, 0x15, 0x4d, 
+0x30, 0x0a, 0x0b, 0x12, 0x1c, 0xa5, 0xf5, 0x83, 0xe0, 0x54, 0xf7, 0xf0, 0x80, 0x09, 0x12, 0x1c, 
+0xb3, 0xf5, 0x83, 0xe0, 0x54, 0xf7, 0xf0, 0xe4, 0xff, 0x02, 0x31, 0xb1, 0xe5, 0x35, 0x30, 0xe7, 
+0x03, 0x02, 0x0f, 0x26, 0xe5, 0x3c, 0x45, 0x3b, 0x60, 0x03, 0x02, 0x0f, 0x26, 0x12, 0x1c, 0xc9, 
+0x14, 0x60, 0x2d, 0x14, 0x60, 0x55, 0x24, 0x02, 0x60, 0x03, 0x02, 0x0f, 0x26, 0x90, 0xfa, 0xba, 
+0xe0, 0x70, 0x04, 0xa3, 0xe0, 0x64, 0x01, 0x60, 0x03, 0x02, 0x0f, 0x26, 0x90, 0xfa, 0xb6, 0xe0, 
+0x60, 0x03, 0x02, 0x0f, 0x26, 0x78, 0x67, 0xe6, 0x44, 0x01, 0xf6, 0xe4, 0xff, 0x02, 0x31, 0xb1, 
+0xe5, 0x35, 0x20, 0xe1, 0x06, 0x20, 0xe0, 0x03, 0x02, 0x0f, 0x26, 0xe5, 0x35, 0x30, 0xe0, 0x07, 
+0xe5, 0x4d, 0x60, 0x03, 0x02, 0x0f, 0x26, 0xe5, 0x35, 0x30, 0xe1, 0x0a, 0xe5, 0x4d, 0xd3, 0x94, 
+0x01, 0x40, 0x03, 0x02, 0x0f, 0x26, 0xe4, 0xff, 0x02, 0x31, 0xb1, 0x90, 0xfa, 0xba, 0xe0, 0x70, 
+0x02, 0xa3, 0xe0, 0x60, 0x03, 0x02, 0x0f, 0x26, 0x90, 0xfa, 0xb6, 0xe0, 0xff, 0x12, 0x31, 0x82, 
+0x40, 0x03, 0x02, 0x0f, 0x26, 0xe5, 0x35, 0x20, 0xe1, 0x06, 0x20, 0xe0, 0x03, 0x02, 0x0f, 0x26, 
+0xe5, 0x4d, 0x70, 0x09, 0x30, 0x0a, 0x03, 0x02, 0x1d, 0x64, 0x02, 0x1d, 0x2f, 0xe5, 0x35, 0x20, 
+0xe1, 0x03, 0x02, 0x0f, 0x26, 0x15, 0x4d, 0x30, 0x0a, 0x0b, 0x12, 0x1c, 0xa5, 0xf5, 0x83, 0xe0, 
+0x44, 0x08, 0xf0, 0x80, 0x09, 0x12, 0x1c, 0xb3, 0xf5, 0x83, 0xe0, 0x44, 0x08, 0xf0, 0xe4, 0xff, 
+0x02, 0x31, 0xb1, 0xe5, 0x35, 0x30, 0xe7, 0x03, 0x02, 0x0f, 0x26, 0xe5, 0x3c, 0x45, 0x3b, 0x60, 
+0x03, 0x02, 0x0f, 0x26, 0x90, 0xfa, 0xb6, 0xe0, 0x60, 0x03, 0x02, 0x0f, 0x26, 0x12, 0x1c, 0xc9, 
+0x60, 0x03, 0x02, 0x0f, 0x26, 0xe5, 0x35, 0x30, 0xe1, 0x03, 0x02, 0x0f, 0x26, 0x90, 0xfa, 0xbb, 
+0xe0, 0x90, 0xff, 0xff, 0xf0, 0xe0, 0x60, 0x05, 0x43, 0x35, 0x01, 0x80, 0x03, 0x53, 0x35, 0xfe, 
+0xe4, 0xff, 0x02, 0x31, 0xb1, 0xe5, 0x35, 0x20, 0xe7, 0x03, 0x02, 0x0f, 0x26, 0xe5, 0x3c, 0x45, 
+0x3b, 0x70, 0x03, 0x02, 0x0f, 0x26, 0x12, 0x1c, 0xc9, 0x60, 0x03, 0x02, 0x0f, 0x26, 0x90, 0xfa, 
+0xba, 0xe0, 0xfc, 0xa3, 0xe0, 0xfd, 0xec, 0x24, 0xfe, 0x60, 0x3a, 0x14, 0x60, 0x75, 0x24, 0x02, 
+0x60, 0x03, 0x02, 0x0f, 0x26, 0xed, 0x60, 0x03, 0x02, 0x0f, 0x26, 0x12, 0x1c, 0x30, 0x12, 0x1d, 
+0x5d, 0x7d, 0x03, 0x12, 0x0f, 0x6d, 0x60, 0x03, 0x02, 0x0f, 0x26, 0x12, 0x0f, 0x2a, 0x90, 0xfa, 
+0xb3, 0xe0, 0xfd, 0xa3, 0x12, 0x1c, 0x7b, 0x12, 0x0f, 0x89, 0x50, 0x02, 0x80, 0x04, 0xae, 0x3b, 
+0xaf, 0x3c, 0x02, 0x0f, 0xba, 0x12, 0x1c, 0x30, 0x90, 0xf9, 0x15, 0xe0, 0x30, 0xe4, 0x0d, 0x12, 
+0x1d, 0x5d, 0x7d, 0x14, 0x12, 0x0f, 0x6d, 0x60, 0x10, 0x02, 0x0f, 0x26, 0x12, 0x1d, 0x5d, 0x7d, 
+0x04, 0x12, 0x0f, 0xc1, 0x60, 0x03, 0x02, 0x0f, 0x26, 0x12, 0x0f, 0x2a, 0x90, 0xfa, 0xb3, 0xe0, 
+0xfd, 0xa3, 0x12, 0x1c, 0x7b, 0x12, 0x0f, 0x89, 0x50, 0x02, 0x80, 0x04, 0xae, 0x3b, 0xaf, 0x3c, 
+0x02, 0x0f, 0xba, 0x12, 0x1d, 0x5d, 0x7d, 0x05, 0x12, 0x0f, 0xc1, 0x60, 0x03, 0x02, 0x0f, 0x26, 
+0x7b, 0x01, 0x7a, 0xfa, 0x79, 0xb3, 0x12, 0x1c, 0x78, 0x7d, 0x01, 0x12, 0x25, 0xd7, 0x90, 0xfa, 
+0xb4, 0xe4, 0x75, 0xf0, 0x03, 0x12, 0x1a, 0x6c, 0x90, 0xfa, 0xbb, 0xe0, 0x90, 0xfa, 0xb2, 0xf0, 
+0xe4, 0xf5, 0x4c, 0x90, 0xfa, 0xb2, 0xe0, 0xff, 0xe5, 0x4c, 0xc3, 0x9f, 0x50, 0x24, 0x12, 0x1c, 
+0x72, 0x12, 0x0f, 0xcc, 0xff, 0xfd, 0x90, 0xfa, 0xb4, 0xe4, 0x8d, 0xf0, 0x12, 0x1a, 0x6c, 0x90, 
+0xfa, 0xb3, 0xe0, 0xc3, 0x9f, 0xf0, 0xd3, 0x94, 0x00, 0x50, 0x03, 0x02, 0x0f, 0x26, 0x05, 0x4c, 
+0x80, 0xd1, 0x12, 0x1c, 0x72, 0x12, 0x0f, 0xcc, 0x24, 0xfe, 0xff, 0x90, 0xfa, 0xb3, 0xf0, 0xfd, 
+0xa3, 0xe4, 0x75, 0xf0, 0x02, 0x12, 0x1a, 0x6c, 0x7a, 0xf9, 0x79, 0x6f, 0x7b, 0x01, 0x8b, 0x36, 
+0x8a, 0x37, 0x89, 0x38, 0xe9, 0x24, 0x02, 0xf9, 0xe4, 0x3a, 0xfa, 0x12, 0x1c, 0x78, 0x12, 0x25, 
+0xd7, 0x8f, 0x4c, 0x05, 0x4c, 0x05, 0x4c, 0x12, 0x1c, 0x11, 0xe5, 0x4c, 0x12, 0x1a, 0x38, 0x12, 
+0x1c, 0x11, 0x90, 0x00, 0x01, 0x74, 0x03, 0x12, 0x1a, 0x4a, 0xaf, 0x4c, 0x7e, 0x00, 0xc3, 0xef, 
+0x95, 0x3c, 0xee, 0x95, 0x3b, 0x50, 0x02, 0x80, 0x04, 0xae, 0x3b, 0xaf, 0x3c, 0x8e, 0x39, 0x8f, 
+0x3a, 0x02, 0x2c, 0x07, 0x02, 0x0f, 0x26, 0xe5, 0x35, 0x20, 0xe7, 0x03, 0x02, 0x0f, 0x26, 0xe5, 
+0x3c, 0x64, 0x01, 0x45, 0x3b, 0x60, 0x03, 0x02, 0x0f, 0x26, 0x90, 0xfa, 0xb6, 0xe0, 0x60, 0x03, 
+0x02, 0x0f, 0x26, 0x90, 0xfa, 0xba, 0xe0, 0x70, 0x02, 0xa3, 0xe0, 0x60, 0x03, 0x02, 0x0f, 0x26, 
+0x12, 0x1c, 0xc9, 0x60, 0x03, 0x02, 0x0f, 0x26, 0xe5, 0x35, 0x20, 0xe0, 0x06, 0x20, 0xe1, 0x03, 
+0x02, 0x0f, 0x26, 0x75, 0x36, 0x00, 0x75, 0x37, 0x00, 0x75, 0x38, 0x32, 0x02, 0x0f, 0xa9, 0xe5, 
+0x35, 0x30, 0xe7, 0x03, 0x02, 0x0f, 0x26, 0xe5, 0x3c, 0x45, 0x3b, 0x60, 0x03, 0x02, 0x0f, 0x26, 
+0x90, 0xfa, 0xb6, 0xe0, 0x60, 0x03, 0x02, 0x0f, 0x26, 0xd3, 0x90, 0xfa, 0xbb, 0xe0, 0x94, 0x01, 
+0x90, 0xfa, 0xba, 0xe0, 0x94, 0x00, 0x40, 0x03, 0x02, 0x0f, 0x26, 0x12, 0x1c, 0xc9, 0x60, 0x03, 
+0x02, 0x0f, 0x26, 0xe5, 0x35, 0x20, 0xe0, 0x06, 0x20, 0xe1, 0x03, 0x02, 0x0f, 0x26, 0x90, 0xfa, 
+0xbb, 0xe0, 0xf5, 0x32, 0xe5, 0x32, 0x70, 0x08, 0x43, 0x35, 0x01, 0x53, 0x35, 0xfd, 0x80, 0x06, 
+0x53, 0x35, 0xfe, 0x43, 0x35, 0x02, 0xe4, 0xff, 0x02, 0x31, 0xb1, 0xe5, 0x35, 0x20, 0xe7, 0x03, 
+0x02, 0x0f, 0x26, 0xe5, 0x3c, 0x64, 0x01, 0x45, 0x3b, 0x60, 0x03, 0x02, 0x0f, 0x26, 0x90, 0xfa, 
+0xb6, 0xe0, 0x60, 0x03, 0x02, 0x0f, 0x26, 0x90, 0xfa, 0xba, 0xe0, 0x70, 0x02, 0xa3, 0xe0, 0x60, 
+0x03, 0x02, 0x0f, 0x26, 0x12, 0x1c, 0xc9, 0x64, 0x01, 0x60, 0x03, 0x02, 0x0f, 0x26, 0xe5, 0x35, 
+0x20, 0xe1, 0x03, 0x02, 0x0f, 0x26, 0x7f, 0x01, 0x02, 0x31, 0xb1, 0xe5, 0x35, 0x30, 0xe7, 0x03, 
+0x02, 0x0f, 0x26, 0xe5, 0x3c, 0x45, 0x3b, 0x60, 0x03, 0x02, 0x0f, 0x26, 0xd3, 0x90, 0xfa, 0xbb, 
+0xe0, 0x94, 0x00, 0x90, 0xfa, 0xba, 0xe0, 0x94, 0x00, 0x40, 0x03, 0x02, 0x0f, 0x26, 0x12, 0x1c, 
+0xc9, 0x64, 0x01, 0x60, 0x03, 0x02, 0x0f, 0x26, 0xe5, 0x35, 0x20, 0xe1, 0x03, 0x02, 0x0f, 0x26, 
+0xe4, 0xff, 0x02, 0x31, 0xb1, 0x90, 0xff, 0x01, 0x12, 0x1d, 0x74, 0xef, 0x12, 0x1a, 0x38, 0x90, 
+0xfa, 0xb6, 0x12, 0x1d, 0x74, 0x90, 0x00, 0x01, 0xef, 0x12, 0x1a, 0x4a, 0x90, 0x00, 0x02, 0xe4, 
+0x12, 0x1a, 0x4a, 0x74, 0x03, 0x12, 0x1c, 0x02, 0x90, 0xfa, 0xba, 0xe0, 0xff, 0xa3, 0xe0, 0x85, 
+0x38, 0x82, 0x85, 0x37, 0x83, 0xcf, 0xf0, 0xa3, 0xef, 0xf0, 0x90, 0xff, 0x01, 0xe0, 0x12, 0x1b, 
+0x4c, 0x09, 0x4a, 0x02, 0x09, 0x6c, 0x04, 0x09, 0x8e, 0x05, 0x09, 0xba, 0x06, 0x09, 0xd8, 0x07, 
+0x09, 0xf6, 0x08, 0x0a, 0x14, 0x09, 0x0a, 0x32, 0x0b, 0x0a, 0xe7, 0x80, 0x0d, 0x6f, 0x81, 0x0d, 
+0xa0, 0x82, 0x0b, 0x2e, 0x83, 0x0b, 0x77, 0x84, 0x0b, 0x96, 0x85, 0x0b, 0xdb, 0x86, 0x0c, 0x26, 
+0x87, 0x0c, 0xb7, 0x88, 0x0d, 0x42, 0x89, 0x0a, 0x50, 0x92, 0x0a, 0x50, 0x93, 0x0e, 0x53, 0xc0, 
+0x0e, 0x7f, 0xc1, 0x0e, 0x90, 0xc2, 0x00, 0x00, 0x0f, 0x15, 0xe5, 0x35, 0x20, 0xe7, 0x05, 0x7f, 
+0x05, 0x02, 0x30, 0xec, 0x12, 0x1c, 0xc1, 0x60, 0x03, 0x04, 0x70, 0x09, 0xef, 0xfd, 0x7c, 0x00, 
+0x7f, 0x07, 0x02, 0x11, 0x16, 0xe4, 0xfd, 0x7f, 0x07, 0x02, 0x2f, 0x18, 0xe5, 0x35, 0x20, 0xe7, 
+0x05, 0x7f, 0x05, 0x02, 0x30, 0xec, 0x12, 0x1c, 0xc1, 0x60, 0x03, 0x04, 0x70, 0x09, 0xef, 0xfd, 
+0x7c, 0x00, 0x7f, 0x0c, 0x02, 0x11, 0x16, 0xe4, 0xfd, 0x7f, 0x07, 0x02, 0x2f, 0x18, 0xe5, 0x35, 
+0x30, 0xe7, 0x03, 0x02, 0x0f, 0x29, 0x12, 0x1d, 0x92, 0x50, 0x06, 0xe5, 0x3c, 0x45, 0x3b, 0x70, 
+0x05, 0x7f, 0x02, 0x02, 0x30, 0xec, 0x90, 0xfa, 0xb6, 0xe0, 0x24, 0xfe, 0x24, 0xfd, 0x50, 0x02, 
+0x80, 0x03, 0x02, 0x31, 0x6f, 0x7f, 0x07, 0x02, 0x30, 0xec, 0xe5, 0x35, 0x30, 0xe7, 0x03, 0x02, 
+0x0f, 0x29, 0x12, 0x1c, 0xc1, 0x60, 0x03, 0x04, 0x70, 0x09, 0xef, 0xfd, 0x7c, 0x00, 0x7f, 0x08, 
+0x02, 0x11, 0x16, 0x7f, 0x07, 0x02, 0x30, 0xec, 0xe5, 0x35, 0x30, 0xe7, 0x03, 0x02, 0x0f, 0x29, 
+0x12, 0x1c, 0xc1, 0x60, 0x03, 0x04, 0x70, 0x09, 0xef, 0xfd, 0x7c, 0x00, 0x7f, 0x09, 0x02, 0x11, 
+0x16, 0x7f, 0x07, 0x02, 0x30, 0xec, 0xe5, 0x35, 0x30, 0xe7, 0x03, 0x02, 0x0f, 0x29, 0x12, 0x1c, 
+0xc1, 0x60, 0x03, 0x04, 0x70, 0x09, 0xef, 0xfd, 0x7c, 0x00, 0x7f, 0x0a, 0x02, 0x11, 0x16, 0x7f, 
+0x07, 0x02, 0x30, 0xec, 0xe5, 0x35, 0x30, 0xe7, 0x03, 0x02, 0x0f, 0x29, 0x12, 0x1c, 0xc1, 0x60, 
+0x03, 0x04, 0x70, 0x09, 0xef, 0xfd, 0x7c, 0x00, 0x7f, 0x0b, 0x02, 0x11, 0x16, 0x7f, 0x07, 0x02, 
+0x30, 0xec, 0xe5, 0x35, 0x30, 0xe7, 0x03, 0x02, 0x0f, 0x29, 0x12, 0x1c, 0xc1, 0x60, 0x03, 0x04, 
+0x70, 0x09, 0xef, 0xfd, 0x7c, 0x00, 0x7f, 0x0e, 0x02, 0x11, 0x16, 0x7f, 0x07, 0x02, 0x30, 0xec, 
+0xe5, 0x35, 0x30, 0xe7, 0x56, 0x12, 0x1c, 0xc9, 0x70, 0x4a, 0x90, 0xff, 0x02, 0xe0, 0xf5, 0x4c, 
+0xe5, 0x4c, 0xb4, 0x82, 0x05, 0x75, 0x4c, 0x61, 0x80, 0x12, 0xe5, 0x4c, 0xb4, 0x83, 0x05, 0x75, 
+0x4c, 0x62, 0x80, 0x08, 0xe5, 0x4c, 0xc4, 0x54, 0xf0, 0x04, 0xf5, 0x4c, 0x12, 0x1b, 0x72, 0x12, 
+0x1d, 0x8b, 0x12, 0x25, 0x39, 0x12, 0x1c, 0xd9, 0x12, 0x1a, 0x0b, 0x60, 0x05, 0x12, 0x31, 0xbd, 
+0x80, 0x06, 0x85, 0x33, 0x39, 0x85, 0x34, 0x3a, 0x75, 0x36, 0x01, 0x75, 0x37, 0xf9, 0x75, 0x38, 
+0x72, 0x02, 0x2c, 0x07, 0xe4, 0xfd, 0x7f, 0x05, 0x02, 0x2f, 0x18, 0x12, 0x1c, 0xc9, 0x60, 0x05, 
+0x7f, 0x05, 0x02, 0x30, 0xec, 0x12, 0x1d, 0x92, 0x40, 0x05, 0x7f, 0x03, 0x02, 0x30, 0xec, 0x90, 
+0xff, 0x02, 0xe0, 0xf5, 0x4c, 0xe5, 0x4c, 0xb4, 0x82, 0x05, 0x75, 0x4c, 0x61, 0x80, 0x12, 0xe5, 
+0x4c, 0xb4, 0x83, 0x05, 0x75, 0x4c, 0x62, 0x80, 0x08, 0xe5, 0x4c, 0xc4, 0x54, 0xf0, 0x04, 0xf5, 
+0x4c, 0x12, 0x1b, 0x72, 0x02, 0x31, 0x6f, 0x12, 0x1d, 0x9c, 0x12, 0x2a, 0x06, 0x12, 0x1c, 0x83, 
+0xe0, 0x54, 0x7f, 0xf0, 0x00, 0x00, 0x00, 0xe0, 0x90, 0xfa, 0xb7, 0xf0, 0x78, 0x68, 0x12, 0x1b, 
+0x28, 0x90, 0x00, 0x02, 0x12, 0x1a, 0x0b, 0x30, 0xe7, 0xf2, 0x90, 0x00, 0x02, 0xe4, 0x12, 0x1a, 
+0x4a, 0x90, 0xfa, 0xb7, 0xe0, 0x44, 0x80, 0xff, 0xf0, 0x78, 0x7c, 0xe6, 0xfc, 0x08, 0xe6, 0x8c, 
+0x83, 0x12, 0x1c, 0x8b, 0xef, 0xf0, 0x12, 0x31, 0xc7, 0xe4, 0xff, 0x02, 0x30, 0xec, 0x90, 0xfa, 
+0xb6, 0xe0, 0x64, 0x01, 0x70, 0x1f, 0x90, 0xfa, 0xba, 0xe0, 0xff, 0x7e, 0x00, 0x70, 0x06, 0xa3, 
+0xe0, 0xf5, 0x90, 0x80, 0x2d, 0xc2, 0xaf, 0xef, 0xf4, 0x52, 0x90, 0x90, 0xfa, 0xbb, 0xe0, 0x42, 
+0x90, 0xd2, 0xaf, 0x80, 0x1d, 0x90, 0xfa, 0xba, 0xe0, 0xff, 0x7e, 0x00, 0x70, 0x06, 0xa3, 0xe0, 
+0xf5, 0xb0, 0x80, 0x0e, 0xc2, 0xaf, 0xef, 0xf4, 0x52, 0xb0, 0x90, 0xfa, 0xbb, 0xe0, 0x42, 0xb0, 
+0xd2, 0xaf, 0xe4, 0xff, 0x02, 0x30, 0xec, 0x12, 0x1c, 0x30, 0x90, 0xfa, 0xb6, 0xe0, 0xb4, 0x01, 
+0x0a, 0x12, 0x1c, 0x11, 0xe5, 0x90, 0x12, 0x1a, 0x38, 0x80, 0x08, 0x12, 0x1c, 0x11, 0xe5, 0xb0, 
+0x12, 0x1a, 0x38, 0x02, 0x0f, 0xa9, 0x90, 0xfa, 0xb6, 0xe0, 0xff, 0x24, 0x12, 0x12, 0x1c, 0x41, 
+0x20, 0xe1, 0x33, 0x12, 0x1c, 0xd0, 0xef, 0x24, 0xfc, 0x60, 0x18, 0x04, 0x70, 0x28, 0x90, 0xfa, 
+0xb7, 0xe0, 0x60, 0x09, 0x90, 0xff, 0xa4, 0xe0, 0x44, 0x10, 0xf0, 0x80, 0x19, 0x12, 0x1d, 0xa6, 
+0xf0, 0x80, 0x13, 0x90, 0xfa, 0xb7, 0xe0, 0x60, 0x09, 0x90, 0xff, 0xb4, 0xe0, 0x44, 0x10, 0xf0, 
+0x80, 0x04, 0x12, 0x1d, 0xad, 0xf0, 0xe4, 0xff, 0x02, 0x30, 0xec, 0x90, 0xfa, 0xb6, 0xe0, 0xff, 
+0x24, 0x12, 0x12, 0x1c, 0x41, 0x20, 0xe1, 0x39, 0x12, 0x1c, 0xd0, 0xef, 0x24, 0xfc, 0x60, 0x1b, 
+0x04, 0x70, 0x2e, 0x90, 0xfa, 0xb7, 0xe0, 0x60, 0x09, 0x90, 0xff, 0xa4, 0xe0, 0x44, 0x20, 0xf0, 
+0x80, 0x1f, 0x90, 0xff, 0xa4, 0xe0, 0x54, 0xdf, 0xf0, 0x80, 0x16, 0x90, 0xfa, 0xb7, 0xe0, 0x60, 
+0x09, 0x90, 0xff, 0xb4, 0xe0, 0x44, 0x20, 0xf0, 0x80, 0x07, 0x90, 0xff, 0xb4, 0xe0, 0x54, 0xdf, 
+0xf0, 0xe4, 0xff, 0x02, 0x30, 0xec, 0x12, 0x1c, 0xd0, 0x12, 0x1c, 0xc1, 0x60, 0x4d, 0x04, 0x60, 
+0x03, 0x02, 0x0c, 0xb2, 0x90, 0xfa, 0xb7, 0xe0, 0x60, 0x0f, 0x90, 0xff, 0xa4, 0x12, 0x1c, 0x3a, 
+0x30, 0xe1, 0x6f, 0x12, 0x1d, 0x7c, 0x02, 0x0c, 0xb2, 0x90, 0xff, 0xa4, 0xe0, 0x54, 0xfb, 0x12, 
+0x1c, 0x3d, 0xfe, 0x30, 0xe1, 0x5c, 0x30, 0xe2, 0x11, 0x30, 0xb4, 0x05, 0x12, 0x1d, 0x7c, 0x80, 
+0x51, 0x90, 0xff, 0xa4, 0xe0, 0x54, 0xfd, 0xf0, 0x80, 0x48, 0x30, 0x95, 0x05, 0x12, 0x1d, 0x7c, 
+0x80, 0x40, 0x90, 0xff, 0xa4, 0xe0, 0x54, 0xfd, 0xf0, 0x80, 0x37, 0x90, 0xfa, 0xb7, 0xe0, 0x60, 
+0x12, 0x90, 0xff, 0xb4, 0x12, 0x1c, 0x3a, 0x30, 0xe1, 0x28, 0x90, 0xff, 0xb4, 0xe0, 0x44, 0x02, 
+0xf0, 0x80, 0x1f, 0x90, 0xff, 0xb4, 0xe0, 0x54, 0xfb, 0x12, 0x1c, 0x3d, 0x30, 0xe1, 0x13, 0x30, 
+0x93, 0x09, 0x90, 0xff, 0xb4, 0xe0, 0x44, 0x02, 0xf0, 0x80, 0x07, 0x90, 0xff, 0xb4, 0xe0, 0x54, 
+0xfd, 0xf0, 0xe4, 0xff, 0x02, 0x30, 0xec, 0x12, 0x1c, 0xd0, 0x90, 0xfa, 0xb6, 0xe0, 0x24, 0xfc, 
+0x60, 0x40, 0x04, 0x70, 0x78, 0x90, 0xfa, 0xb7, 0xe0, 0x60, 0x1d, 0x90, 0xff, 0xa2, 0xe0, 0x44, 
+0x40, 0xf0, 0xa3, 0xe0, 0xff, 0x30, 0xe7, 0x65, 0xd2, 0x03, 0xa3, 0xe0, 0x54, 0xdf, 0xf0, 0x90, 
+0xff, 0xa3, 0xef, 0x54, 0x7f, 0xf0, 0x80, 0x55, 0x30, 0x03, 0x0e, 0x90, 0xff, 0xa3, 0xe0, 0x44, 
+0x80, 0xf0, 0xc2, 0x03, 0xa3, 0xe0, 0x44, 0x20, 0xf0, 0x90, 0xff, 0xa2, 0xe0, 0x54, 0xbf, 0xf0, 
+0x80, 0x3b, 0x90, 0xfa, 0xb7, 0xe0, 0x60, 0x1d, 0x90, 0xff, 0xb2, 0xe0, 0x44, 0x40, 0xf0, 0xa3, 
+0xe0, 0xff, 0x30, 0xe7, 0x28, 0xd2, 0x04, 0xa3, 0xe0, 0x54, 0xdf, 0xf0, 0x90, 0xff, 0xb3, 0xef, 
+0x54, 0x7f, 0xf0, 0x80, 0x18, 0x30, 0x04, 0x0e, 0x90, 0xff, 0xb3, 0xe0, 0x44, 0x80, 0xf0, 0xc2, 
+0x04, 0xa3, 0xe0, 0x44, 0x20, 0xf0, 0x90, 0xff, 0xb2, 0xe0, 0x54, 0xbf, 0xf0, 0xe4, 0xff, 0x02, 
+0x30, 0xec, 0x12, 0x1c, 0x30, 0x90, 0xfa, 0xb6, 0xe0, 0x24, 0xfc, 0x60, 0x0f, 0x04, 0x70, 0x16, 
+0x90, 0xff, 0xa6, 0xe0, 0x12, 0x1c, 0x11, 0x12, 0x1a, 0x38, 0x80, 0x0a, 0x90, 0xff, 0xb6, 0xe0, 
+0x12, 0x1c, 0x11, 0x12, 0x1a, 0x38, 0x75, 0x39, 0x00, 0x75, 0x3a, 0x01, 0x02, 0x2c, 0x07, 0xe4, 
+0xff, 0x12, 0x30, 0xec, 0x12, 0x1d, 0x37, 0x7f, 0x03, 0x12, 0x12, 0x19, 0x90, 0xf9, 0x15, 0xe0, 
+0x30, 0xe4, 0x08, 0x90, 0xff, 0x93, 0x74, 0x80, 0xf0, 0x80, 0x10, 0x90, 0xff, 0xfc, 0xe0, 0x54, 
+0x7f, 0xf0, 0x7f, 0xff, 0x7e, 0x00, 0x12, 0x30, 0x16, 0xc2, 0x90, 0xc2, 0xaf, 0x00, 0x80, 0xfd, 
+0xe4, 0xf5, 0x4e, 0xf5, 0x4f, 0x90, 0xfa, 0xbc, 0x74, 0x3e, 0xf0, 0xa3, 0xe4, 0xf0, 0x90, 0xfa, 
+0xb4, 0xf0, 0xa3, 0x74, 0x15, 0xf0, 0xe0, 0x54, 0x3f, 0xff, 0xc3, 0x74, 0x40, 0x9f, 0x90, 0xfa, 
+0xb9, 0xf0, 0xd3, 0x94, 0x00, 0xe4, 0x94, 0x3e, 0x40, 0x08, 0x90, 0xfa, 0xbd, 0xe0, 0x90, 0xfa, 
+0xb9, 0xf0, 0x12, 0x0f, 0x50, 0xe5, 0x31, 0x45, 0x30, 0x70, 0x73, 0x12, 0x1c, 0x4a, 0x90, 0xfa, 
+0xbc, 0x12, 0x1d, 0x56, 0x60, 0x27, 0xd3, 0xef, 0x94, 0x40, 0xee, 0x94, 0x00, 0x40, 0x08, 0x90, 
+0xfa, 0xb9, 0x74, 0x40, 0xf0, 0x80, 0x08, 0x90, 0xfa, 0xbd, 0xe0, 0x90, 0xfa, 0xb9, 0xf0, 0x12, 
+0x0f, 0x50, 0xe5, 0x31, 0x45, 0x30, 0x70, 0x46, 0x12, 0x1c, 0x4a, 0x80, 0xd1, 0x75, 0x4c, 0x02, 
+0x90, 0xfa, 0xbc, 0xe4, 0xf0, 0xa3, 0x04, 0xf0, 0x90, 0xfa, 0xb4, 0xe4, 0xf0, 0xa3, 0x74, 0x0f, 
+0xf0, 0x7b, 0x00, 0x7a, 0x00, 0x79, 0x4c, 0x90, 0xfa, 0xbd, 0xe0, 0xf5, 0x4a, 0x7d, 0x0f, 0x7c, 
+0x00, 0x12, 0x28, 0x9f, 0x75, 0x30, 0x00, 0x8f, 0x31, 0x7b, 0x00, 0x7a, 0x00, 0x79, 0x4c, 0xe4, 
+0xf5, 0x2d, 0xf5, 0x2e, 0x7d, 0x01, 0x12, 0x25, 0xd7, 0xe4, 0xf5, 0x30, 0xf5, 0x31, 0xaf, 0x31, 
+0x02, 0x30, 0xec, 0x12, 0x1c, 0xd0, 0x30, 0xe7, 0x10, 0xe0, 0x54, 0x0f, 0x90, 0xf9, 0x64, 0xf0, 
+0xd3, 0x94, 0x00, 0x40, 0x15, 0xc2, 0x95, 0x80, 0x11, 0x90, 0xfa, 0xb7, 0xe0, 0x54, 0x0f, 0x90, 
+0xf9, 0x63, 0xf0, 0xd3, 0x94, 0x00, 0x40, 0x02, 0xc2, 0x94, 0xe4, 0xff, 0x02, 0x30, 0xec, 0x12, 
+0x1d, 0x9c, 0xbf, 0x01, 0x04, 0xd2, 0x93, 0x80, 0x02, 0xc2, 0x93, 0xe4, 0xff, 0x02, 0x30, 0xec, 
+0x12, 0x1c, 0xd0, 0x54, 0x03, 0x14, 0x60, 0x0a, 0x14, 0x60, 0x0f, 0x14, 0x60, 0x08, 0x24, 0x03, 
+0x70, 0x2b, 0xd2, 0x91, 0x80, 0x27, 0xc2, 0x91, 0x80, 0x23, 0x12, 0x1d, 0xa6, 0x12, 0x0f, 0x78, 
+0x60, 0x04, 0xd2, 0x91, 0x80, 0x17, 0x90, 0xff, 0xa4, 0xe0, 0x44, 0x10, 0x12, 0x0f, 0x78, 0xff, 
+0xbf, 0xa0, 0x04, 0xc2, 0x91, 0x80, 0x02, 0xd2, 0x91, 0x12, 0x1d, 0xa6, 0xf0, 0x90, 0xfa, 0xb7, 
+0xe0, 0x54, 0x0c, 0xff, 0x13, 0x13, 0x54, 0x3f, 0x14, 0x60, 0x0a, 0x14, 0x60, 0x0f, 0x14, 0x60, 
+0x08, 0x24, 0x03, 0x70, 0x2b, 0xd2, 0x92, 0x80, 0x27, 0xc2, 0x92, 0x80, 0x23, 0x12, 0x1d, 0xad, 
+0x12, 0x0f, 0x98, 0x60, 0x04, 0xd2, 0x92, 0x80, 0x17, 0x90, 0xff, 0xb4, 0xe0, 0x44, 0x10, 0x12, 
+0x0f, 0x98, 0xff, 0xbf, 0xa0, 0x04, 0xc2, 0x92, 0x80, 0x02, 0xd2, 0x92, 0x12, 0x1d, 0xad, 0xf0, 
+0xe4, 0xff, 0x02, 0x30, 0xec, 0xe5, 0x35, 0x30, 0xe7, 0x07, 0xe4, 0xfd, 0x7f, 0x05, 0x02, 0x2f, 
+0x18, 0x7f, 0x05, 0x02, 0x30, 0xec, 0x12, 0x31, 0xbd, 0x22, 0x7b, 0x01, 0x7a, 0xfa, 0x79, 0xb3, 
+0x90, 0xfa, 0xb4, 0xe0, 0xf5, 0x2d, 0xa3, 0xe0, 0xf5, 0x2e, 0x7d, 0x01, 0x12, 0x25, 0xd7, 0x90, 
+0xfa, 0xb4, 0xe4, 0x75, 0xf0, 0x03, 0x12, 0x1a, 0x6c, 0xab, 0x36, 0xaa, 0x37, 0xa9, 0x38, 0x22, 
+0xaa, 0x4e, 0xa9, 0x4f, 0x7b, 0xff, 0x90, 0xfa, 0xb4, 0xe0, 0xfc, 0xa3, 0xe0, 0xfd, 0x90, 0xfa, 
+0xb9, 0xe0, 0xf5, 0x4a, 0x12, 0x28, 0x9f, 0x75, 0x30, 0x00, 0x8f, 0x31, 0x22, 0x12, 0x22, 0xa0, 
+0x7e, 0x00, 0x8e, 0x30, 0x8f, 0x31, 0xef, 0x22, 0xf0, 0x7f, 0x01, 0x12, 0x12, 0x19, 0x90, 0xff, 
+0xa6, 0xe0, 0x90, 0xfa, 0xb8, 0xf0, 0x54, 0xa0, 0x22, 0x12, 0x25, 0xd7, 0x8f, 0x4c, 0x7e, 0x00, 
+0xc3, 0xef, 0x95, 0x3c, 0xee, 0x95, 0x3b, 0x22, 0xf0, 0x7f, 0x01, 0x12, 0x12, 0x19, 0x90, 0xff, 
+0xb6, 0xe0, 0x90, 0xfa, 0xb8, 0xf0, 0x54, 0xa0, 0x22, 0x75, 0x39, 0x00, 0x75, 0x3a, 0x01, 0x02, 
+0x2c, 0x07, 0x90, 0xfa, 0xb6, 0xe0, 0xff, 0x02, 0x31, 0x82, 0x8e, 0x39, 0x8f, 0x3a, 0x02, 0x2c, 
+0x07, 0x12, 0x22, 0xa0, 0x7e, 0x00, 0x8e, 0x30, 0x8f, 0x31, 0xef, 0x22, 0x7d, 0x01, 0x12, 0x25, 
+0xd7, 0x90, 0xfa, 0xb1, 0xe0, 0x22, 0xef, 0x90, 0xf8, 0x04, 0xf0, 0x22, 0xc0, 0xa8, 0xc2, 0xaf, 
+0xee, 0x60, 0x0a, 0xc0, 0x05, 0x7d, 0x7f, 0xdd, 0xfe, 0xde, 0xfa, 0xd0, 0x05, 0xef, 0xc3, 0x94, 
+0x15, 0x50, 0x03, 0xd0, 0xa8, 0x22, 0x13, 0x70, 0x03, 0xd0, 0xa8, 0x22, 0xff, 0xd5, 0x07, 0xfd, 
+0xd0, 0xa8, 0x22, 0xc0, 0x00, 0xc0, 0x01, 0xc0, 0x02, 0xc0, 0x04, 0xc0, 0x05, 0xe5, 0x3e, 0x24, 
+0x08, 0xf8, 0x86, 0x05, 0x53, 0x05, 0x7f, 0x7c, 0xff, 0x12, 0x10, 0x78, 0x7f, 0x00, 0x7e, 0x00, 
+0xe5, 0x43, 0x60, 0x46, 0xfc, 0x90, 0xf9, 0x1b, 0xe0, 0x54, 0x7f, 0x6d, 0x70, 0x0f, 0xc0, 0x83, 
+0xc0, 0x82, 0xa3, 0xe0, 0xfe, 0xa3, 0xe0, 0xff, 0xa3, 0x15, 0x43, 0x80, 0x07, 0xa3, 0xa3, 0xa3, 
+0xdc, 0xe6, 0x80, 0x26, 0xdc, 0x06, 0xd0, 0x82, 0xd0, 0x83, 0x80, 0x1e, 0xe0, 0xf8, 0xa3, 0xe0, 
+0xf9, 0xa3, 0xe0, 0xfa, 0xd0, 0x82, 0xd0, 0x83, 0xe8, 0xf0, 0xa3, 0xe9, 0xf0, 0xa3, 0xea, 0xf0, 
+0xa3, 0xc0, 0x83, 0xc0, 0x82, 0xa3, 0xa3, 0xa3, 0x80, 0xda, 0x12, 0x11, 0x0f, 0xd0, 0x05, 0xd0, 
+0x04, 0xd0, 0x02, 0xd0, 0x01, 0xd0, 0x00, 0x22, 0x85, 0xa8, 0x44, 0x75, 0xa8, 0x88, 0xec, 0x70, 
+0x02, 0x7c, 0x3f, 0x8c, 0x3d, 0x22, 0xe5, 0x3e, 0x24, 0x08, 0xf8, 0x76, 0x00, 0x12, 0x11, 0x66, 
+0x80, 0xfb, 0xc0, 0x00, 0xc0, 0x01, 0xc0, 0x02, 0xc0, 0x04, 0xc0, 0x06, 0x7c, 0xff, 0x12, 0x10, 
+0x78, 0xe5, 0x43, 0x60, 0x42, 0xfe, 0x90, 0xf9, 0x1b, 0xe0, 0x54, 0x7f, 0x6f, 0x70, 0x0b, 0xc0, 
+0x83, 0xc0, 0x82, 0xa3, 0xa3, 0xa3, 0x15, 0x43, 0x80, 0x07, 0xa3, 0xa3, 0xa3, 0xde, 0xea, 0x80, 
+0x26, 0xde, 0x06, 0xd0, 0x82, 0xd0, 0x83, 0x80, 0xd8, 0xe0, 0xf8, 0xa3, 0xe0, 0xf9, 0xa3, 0xe0, 
+0xfa, 0xd0, 0x82, 0xd0, 0x83, 0xe8, 0xf0, 0xa3, 0xe9, 0xf0, 0xa3, 0xea, 0xf0, 0xa3, 0xc0, 0x83, 
+0xc0, 0x82, 0xa3, 0xa3, 0xa3, 0x80, 0xda, 0x78, 0x08, 0x08, 0x79, 0x18, 0x09, 0x7c, 0x01, 0xe6, 
+0x54, 0x7f, 0x6f, 0x70, 0x06, 0x76, 0x00, 0x77, 0x00, 0x80, 0x06, 0x08, 0x09, 0x0c, 0xbc, 0x08, 
+0xee, 0x12, 0x11, 0x0f, 0xd0, 0x06, 0xd0, 0x04, 0xd0, 0x02, 0xd0, 0x01, 0xd0, 0x00, 0x22, 0x75, 
+0x3d, 0x00, 0x85, 0x44, 0xa8, 0x22, 0xc0, 0xf0, 0xc0, 0x82, 0xc0, 0x83, 0xc3, 0xe5, 0x43, 0x24, 
+0xe8, 0x50, 0x05, 0x12, 0x11, 0x66, 0x80, 0xf4, 0xef, 0x60, 0x31, 0x90, 0x30, 0x54, 0xe4, 0x93, 
+0xc3, 0x9f, 0x40, 0x2f, 0xc0, 0x04, 0x7c, 0xff, 0x12, 0x10, 0x78, 0xd0, 0x04, 0x43, 0x07, 0x80, 
+0xe5, 0x43, 0x75, 0xf0, 0x03, 0xa4, 0x24, 0x1b, 0xf5, 0x82, 0xe4, 0x34, 0xf9, 0xf5, 0x83, 0xef, 
+0xf0, 0xec, 0xa3, 0xf0, 0xed, 0xa3, 0xf0, 0x05, 0x43, 0x12, 0x11, 0x0f, 0xd0, 0x83, 0xd0, 0x82, 
+0xd0, 0xf0, 0x22, 0x02, 0x11, 0x94, 0xc0, 0x04, 0x7c, 0x20, 0xd2, 0x8c, 0xd2, 0x8d, 0xd5, 0x04, 
+0xfd, 0xd0, 0x04, 0x22, 0x75, 0xa8, 0x00, 0x75, 0x88, 0x00, 0x75, 0xb8, 0x00, 0x75, 0xf0, 0x00, 
+0x75, 0xd0, 0x00, 0xe4, 0xf8, 0x90, 0xf8, 0x04, 0xf0, 0x90, 0x00, 0x00, 0xf6, 0x08, 0xb8, 0x00, 
+0xfb, 0x02, 0x00, 0x00, 0xc2, 0xaf, 0xe4, 0x90, 0xff, 0x48, 0xf0, 0x90, 0xff, 0x50, 0xf0, 0x90, 
+0xff, 0x08, 0xf0, 0x90, 0xff, 0x10, 0xf0, 0x90, 0xff, 0x80, 0xf0, 0xa3, 0xa3, 0xf0, 0xd2, 0xb1, 
+0xc2, 0xb0, 0x7e, 0xff, 0x7f, 0xff, 0x12, 0x0f, 0xdc, 0x7e, 0xff, 0x7f, 0xff, 0x12, 0x0f, 0xdc, 
+0x7e, 0xff, 0x7f, 0xff, 0x12, 0x0f, 0xdc, 0xd2, 0xb0, 0xd2, 0xb1, 0x7e, 0xff, 0x7f, 0xff, 0x12, 
+0x0f, 0xdc, 0x7e, 0xff, 0x7f, 0xff, 0x12, 0x0f, 0xdc, 0x7e, 0xff, 0x7f, 0xff, 0x12, 0x0f, 0xdc, 
+0x80, 0xcc, 0xc3, 0xee, 0x94, 0x02, 0x50, 0x04, 0x7e, 0x03, 0x7f, 0xe8, 0xef, 0xf4, 0xff, 0xee, 
+0xf4, 0xfe, 0x0f, 0xbf, 0x00, 0x01, 0x0e, 0x8f, 0x42, 0x8e, 0x41, 0x22, 0xc3, 0xef, 0x94, 0xbc, 
+0xee, 0x94, 0x02, 0x50, 0x04, 0x7e, 0x07, 0x7f, 0xd0, 0xef, 0xf4, 0xff, 0xee, 0xf4, 0xfe, 0x0f, 
+0xbf, 0x00, 0x01, 0x0e, 0x8f, 0x40, 0x8e, 0x3f, 0x22, 0xef, 0x70, 0x01, 0x22, 0xc0, 0x00, 0xc0, 
+0xa8, 0xc2, 0xaf, 0xe5, 0x3e, 0x24, 0x18, 0xf8, 0xa6, 0x07, 0xe5, 0x3e, 0x24, 0x08, 0xf8, 0xc6, 
+0x54, 0x7f, 0xf6, 0xd0, 0xa8, 0xe6, 0x30, 0xe7, 0x03, 0xd0, 0x00, 0x22, 0x12, 0x11, 0x66, 0x80, 
 0xf4, 0xc0, 0x00, 0x7f, 0x01, 0xef, 0x24, 0x08, 0xf8, 0xe6, 0x60, 0x09, 0x0f, 0xbf, 0x08, 0xf5, 
-0x12, 0x10, 0xec, 0x80, 0xee, 0xd0, 0x00, 0x22, 0xc0, 0xf0, 0xc0, 0x82, 0xc0, 0x83, 0xc0, 0x00, 
-0xc0, 0x06, 0xc0, 0x04, 0xed, 0x24, 0x10, 0xf8, 0x76, 0xa0, 0xed, 0x75, 0xf0, 0x21, 0xa4, 0x24, 
+0x12, 0x11, 0x66, 0x80, 0xee, 0xd0, 0x00, 0x22, 0xc0, 0xf0, 0xc0, 0x82, 0xc0, 0x83, 0xc0, 0x00, 
+0xc0, 0x06, 0xc0, 0x04, 0xed, 0x24, 0x10, 0xf8, 0x76, 0x9a, 0xed, 0x75, 0xf0, 0x21, 0xa4, 0x24, 
 0x05, 0xf5, 0x82, 0xe4, 0x34, 0xf8, 0xf5, 0x83, 0xc0, 0x82, 0xc0, 0x83, 0xa3, 0xa3, 0xe4, 0x78, 
-0x0d, 0xf0, 0xa3, 0xd8, 0xfc, 0xef, 0x54, 0x7f, 0x75, 0xf0, 0x02, 0xa4, 0x24, 0x0e, 0xf5, 0x82, 
-0xe5, 0xf0, 0x34, 0x2e, 0xf5, 0x83, 0xe4, 0x93, 0xfe, 0x74, 0x01, 0x93, 0xfc, 0xd0, 0x83, 0xd0, 
+0x0d, 0xf0, 0xa3, 0xd8, 0xfc, 0xef, 0x54, 0x7f, 0x75, 0xf0, 0x02, 0xa4, 0x24, 0x36, 0xf5, 0x82, 
+0xe5, 0xf0, 0x34, 0x30, 0xf5, 0x83, 0xe4, 0x93, 0xfe, 0x74, 0x01, 0x93, 0xfc, 0xd0, 0x83, 0xd0, 
 0x82, 0xec, 0xf0, 0xa3, 0xee, 0xf0, 0xed, 0x24, 0x08, 0xf8, 0xef, 0x44, 0x80, 0xf6, 0xd0, 0x04, 
-0xd0, 0x06, 0xd0, 0x00, 0xd0, 0x83, 0xd0, 0x82, 0xd0, 0xf0, 0x22, 0x75, 0x44, 0x00, 0x75, 0x49, 
+0xd0, 0x06, 0xd0, 0x00, 0xd0, 0x83, 0xd0, 0x82, 0xd0, 0xf0, 0x22, 0x75, 0x3e, 0x00, 0x75, 0x43, 
 0x00, 0x7a, 0x08, 0x79, 0x18, 0x78, 0x08, 0x76, 0x00, 0x77, 0x00, 0x08, 0x09, 0xda, 0xf8, 0x90, 
-0xf8, 0x04, 0xe0, 0xfc, 0x90, 0x2e, 0x2c, 0xe4, 0x93, 0xc3, 0x9c, 0x50, 0x05, 0xe4, 0x90, 0xf8, 
+0xf8, 0x04, 0xe0, 0xfc, 0x90, 0x30, 0x54, 0xe4, 0x93, 0xc3, 0x9c, 0x50, 0x05, 0xe4, 0x90, 0xf8, 
 0x04, 0xf0, 0x78, 0x08, 0x74, 0x80, 0x44, 0x7f, 0xf6, 0x74, 0x01, 0x44, 0x10, 0xf5, 0x89, 0x75, 
-0xb8, 0x00, 0xd2, 0xab, 0xd2, 0xa9, 0x22, 0x75, 0x81, 0x91, 0xd2, 0x8e, 0xd2, 0x8c, 0xd2, 0xaf, 
-0xe5, 0x49, 0x60, 0x36, 0xff, 0x90, 0xf9, 0x19, 0xe0, 0x54, 0x80, 0x60, 0x28, 0x78, 0x08, 0x79, 
+0xb8, 0x00, 0xd2, 0xab, 0xd2, 0xa9, 0x22, 0x75, 0x81, 0x8b, 0xd2, 0x8e, 0xd2, 0x8c, 0xd2, 0xaf, 
+0xe5, 0x43, 0x60, 0x36, 0xff, 0x90, 0xf9, 0x1b, 0xe0, 0x54, 0x80, 0x60, 0x28, 0x78, 0x08, 0x79, 
 0x08, 0xe0, 0x54, 0x7f, 0xfa, 0x7b, 0x00, 0xe6, 0x54, 0x7f, 0xb5, 0x02, 0x02, 0x7b, 0xff, 0x08, 
-0xd9, 0xf5, 0xeb, 0x70, 0x10, 0xea, 0xf0, 0xc0, 0x07, 0x12, 0x11, 0xc1, 0xad, 0x07, 0xaf, 0x02, 
-0x12, 0x11, 0xd8, 0xd0, 0x07, 0xa3, 0xa3, 0xa3, 0xdf, 0xce, 0x12, 0x10, 0xec, 0x80, 0xc1, 0xe7, 
-0x09, 0xf6, 0x08, 0xdf, 0xfa, 0x80, 0x46, 0xe7, 0x09, 0xf2, 0x08, 0xdf, 0xfa, 0x80, 0x3e, 0x88, 
-0x82, 0x8c, 0x83, 0xe7, 0x09, 0xf0, 0xa3, 0xdf, 0xfa, 0x80, 0x32, 0xe3, 0x09, 0xf6, 0x08, 0xdf, 
-0xfa, 0x80, 0x78, 0xe3, 0x09, 0xf2, 0x08, 0xdf, 0xfa, 0x80, 0x70, 0x88, 0x82, 0x8c, 0x83, 0xe3, 
-0x09, 0xf0, 0xa3, 0xdf, 0xfa, 0x80, 0x64, 0x89, 0x82, 0x8a, 0x83, 0xe0, 0xa3, 0xf6, 0x08, 0xdf, 
-0xfa, 0x80, 0x58, 0x89, 0x82, 0x8a, 0x83, 0xe0, 0xa3, 0xf2, 0x08, 0xdf, 0xfa, 0x80, 0x4c, 0x80, 
-0xd2, 0x80, 0xfa, 0x80, 0xc6, 0x80, 0xd4, 0x80, 0x69, 0x80, 0xf2, 0x80, 0x33, 0x80, 0x10, 0x80, 
-0xa6, 0x80, 0xea, 0x80, 0x9a, 0x80, 0xa8, 0x80, 0xda, 0x80, 0xe2, 0x80, 0xca, 0x80, 0x33, 0x89, 
-0x82, 0x8a, 0x83, 0xec, 0xfa, 0xe4, 0x93, 0xa3, 0xc8, 0xc5, 0x82, 0xc8, 0xcc, 0xc5, 0x83, 0xcc, 
-0xf0, 0xa3, 0xc8, 0xc5, 0x82, 0xc8, 0xcc, 0xc5, 0x83, 0xcc, 0xdf, 0xe9, 0xde, 0xe7, 0x80, 0x0d, 
-0x89, 0x82, 0x8a, 0x83, 0xe4, 0x93, 0xa3, 0xf6, 0x08, 0xdf, 0xf9, 0xec, 0xfa, 0xa9, 0xf0, 0xed, 
-0xfb, 0x22, 0x89, 0x82, 0x8a, 0x83, 0xec, 0xfa, 0xe0, 0xa3, 0xc8, 0xc5, 0x82, 0xc8, 0xcc, 0xc5, 
-0x83, 0xcc, 0xf0, 0xa3, 0xc8, 0xc5, 0x82, 0xc8, 0xcc, 0xc5, 0x83, 0xcc, 0xdf, 0xea, 0xde, 0xe8, 
-0x80, 0xdb, 0x89, 0x82, 0x8a, 0x83, 0xe4, 0x93, 0xa3, 0xf2, 0x08, 0xdf, 0xf9, 0x80, 0xcc, 0x88, 
-0xf0, 0xef, 0x60, 0x01, 0x0e, 0x4e, 0x60, 0xc3, 0x88, 0xf0, 0xed, 0x24, 0x02, 0xb4, 0x04, 0x00, 
-0x50, 0xb9, 0xf5, 0x82, 0xeb, 0x24, 0x02, 0xb4, 0x04, 0x00, 0x50, 0xaf, 0x23, 0x23, 0x45, 0x82, 
-0x23, 0x90, 0x13, 0x0f, 0x73, 0xbb, 0x01, 0x06, 0x89, 0x82, 0x8a, 0x83, 0xe0, 0x22, 0x50, 0x02, 
-0xe7, 0x22, 0xbb, 0xfe, 0x02, 0xe3, 0x22, 0x89, 0x82, 0x8a, 0x83, 0xe4, 0x93, 0x22, 0xbb, 0x01, 
-0x0c, 0xe5, 0x82, 0x29, 0xf5, 0x82, 0xe5, 0x83, 0x3a, 0xf5, 0x83, 0xe0, 0x22, 0x50, 0x06, 0xe9, 
-0x25, 0x82, 0xf8, 0xe6, 0x22, 0xbb, 0xfe, 0x06, 0xe9, 0x25, 0x82, 0xf8, 0xe2, 0x22, 0xe5, 0x82, 
-0x29, 0xf5, 0x82, 0xe5, 0x83, 0x3a, 0xf5, 0x83, 0xe4, 0x93, 0x22, 0xbb, 0x01, 0x06, 0x89, 0x82, 
-0x8a, 0x83, 0xf0, 0x22, 0x50, 0x02, 0xf7, 0x22, 0xbb, 0xfe, 0x01, 0xf3, 0x22, 0xf8, 0xbb, 0x01, 
-0x0d, 0xe5, 0x82, 0x29, 0xf5, 0x82, 0xe5, 0x83, 0x3a, 0xf5, 0x83, 0xe8, 0xf0, 0x22, 0x50, 0x06, 
-0xe9, 0x25, 0x82, 0xc8, 0xf6, 0x22, 0xbb, 0xfe, 0x05, 0xe9, 0x25, 0x82, 0xc8, 0xf2, 0x22, 0xc5, 
-0xf0, 0xf8, 0xa3, 0xe0, 0x28, 0xf0, 0xc5, 0xf0, 0xf8, 0xe5, 0x82, 0x15, 0x82, 0x70, 0x02, 0x15, 
-0x83, 0xe0, 0x38, 0xf0, 0x22, 0xa3, 0xf8, 0xe0, 0xc5, 0xf0, 0x25, 0xf0, 0xf0, 0xe5, 0x82, 0x15, 
-0x82, 0x70, 0x02, 0x15, 0x83, 0xe0, 0xc8, 0x38, 0xf0, 0xe8, 0x22, 0xbb, 0x01, 0x10, 0xe5, 0x82, 
-0x29, 0xf5, 0x82, 0xe5, 0x83, 0x3a, 0xf5, 0x83, 0xe0, 0xf5, 0xf0, 0xa3, 0xe0, 0x22, 0x50, 0x09, 
-0xe9, 0x25, 0x82, 0xf8, 0x86, 0xf0, 0x08, 0xe6, 0x22, 0xbb, 0xfe, 0x0a, 0xe9, 0x25, 0x82, 0xf8, 
-0xe2, 0xf5, 0xf0, 0x08, 0xe2, 0x22, 0xe5, 0x83, 0x2a, 0xf5, 0x83, 0xe9, 0x93, 0xf5, 0xf0, 0xa3, 
-0xe9, 0x93, 0x22, 0xbb, 0x01, 0x0a, 0x89, 0x82, 0x8a, 0x83, 0xf0, 0xe5, 0xf0, 0xa3, 0xf0, 0x22, 
-0x50, 0x06, 0xf7, 0x09, 0xa7, 0xf0, 0x19, 0x22, 0xbb, 0xfe, 0x06, 0xf3, 0xe5, 0xf0, 0x09, 0xf3, 
-0x19, 0x22, 0xf8, 0xbb, 0x01, 0x11, 0xe5, 0x82, 0x29, 0xf5, 0x82, 0xe5, 0x83, 0x3a, 0xf5, 0x83, 
-0xe8, 0xf0, 0xe5, 0xf0, 0xa3, 0xf0, 0x22, 0x50, 0x09, 0xe9, 0x25, 0x82, 0xc8, 0xf6, 0x08, 0xa6, 
-0xf0, 0x22, 0xbb, 0xfe, 0x09, 0xe9, 0x25, 0x82, 0xc8, 0xf2, 0xe5, 0xf0, 0x08, 0xf2, 0x22, 0xa4, 
-0x25, 0x82, 0xf5, 0x82, 0xe5, 0xf0, 0x35, 0x83, 0xf5, 0x83, 0x22, 0xe6, 0xfb, 0x08, 0xe6, 0xfa, 
-0x08, 0xe6, 0xf9, 0x22, 0xeb, 0xf6, 0x08, 0xea, 0xf6, 0x08, 0xe9, 0xf6, 0x22, 0xe0, 0xfb, 0xa3, 
-0xe0, 0xfa, 0xa3, 0xe0, 0xf9, 0x22, 0xeb, 0xf0, 0xa3, 0xea, 0xf0, 0xa3, 0xe9, 0xf0, 0x22, 0xd0, 
-0x83, 0xd0, 0x82, 0xf8, 0xe4, 0x93, 0x70, 0x12, 0x74, 0x01, 0x93, 0x70, 0x0d, 0xa3, 0xa3, 0x93, 
-0xf8, 0x74, 0x01, 0x93, 0xf5, 0x82, 0x88, 0x83, 0xe4, 0x73, 0x74, 0x02, 0x93, 0x68, 0x60, 0xef, 
-0xa3, 0xa3, 0xa3, 0x80, 0xdf, 0x90, 0xff, 0xfa, 0x74, 0x08, 0xf0, 0xa3, 0x74, 0x16, 0xf0, 0x90, 
-0xff, 0xf9, 0x74, 0x02, 0xf0, 0x90, 0xfa, 0xcb, 0xe4, 0xf0, 0xa3, 0x74, 0x0b, 0xf0, 0x7b, 0x00, 
-0x7a, 0x00, 0x79, 0x37, 0x75, 0x40, 0x00, 0xf5, 0x41, 0x7d, 0x01, 0x12, 0x23, 0xee, 0xe5, 0x37, 
-0x24, 0x80, 0x90, 0xff, 0xf8, 0xf0, 0xe5, 0x37, 0x64, 0x07, 0x60, 0x0b, 0xe5, 0x37, 0x64, 0x06, 
-0x60, 0x05, 0xe5, 0x37, 0xb4, 0x14, 0x1b, 0xd2, 0x94, 0xd2, 0x95, 0xd2, 0x92, 0xd2, 0x93, 0xe5, 
-0x37, 0xb4, 0x07, 0x08, 0x90, 0xf9, 0x65, 0x74, 0x02, 0xf0, 0x80, 0x06, 0x90, 0xf9, 0x65, 0x74, 
-0x01, 0xf0, 0x90, 0xfa, 0xcb, 0xe4, 0xf0, 0xa3, 0x74, 0x0d, 0xf0, 0x12, 0x17, 0x71, 0x90, 0xff, 
-0xf5, 0xe5, 0x37, 0xf0, 0x7b, 0x01, 0x7a, 0xfa, 0x79, 0xcb, 0xe4, 0xfd, 0x12, 0x20, 0xc5, 0x90, 
-0xfa, 0xcb, 0xe4, 0x75, 0xf0, 0x03, 0x12, 0x14, 0x2f, 0x12, 0x17, 0x71, 0xe5, 0x37, 0x30, 0xe7, 
-0x02, 0xd2, 0x02, 0xe4, 0xf5, 0x2c, 0xf5, 0x2a, 0xf5, 0x2b, 0xf5, 0x29, 0x12, 0x19, 0x92, 0x12, 
-0x18, 0x49, 0x12, 0x19, 0x6c, 0x90, 0xf9, 0x66, 0x12, 0x15, 0x06, 0x90, 0xf9, 0x6b, 0x12, 0x15, 
-0x06, 0x90, 0xff, 0xff, 0xe4, 0xf0, 0x90, 0xff, 0x83, 0xe0, 0xe4, 0xf0, 0x90, 0xff, 0x81, 0x74, 
-0x80, 0xf0, 0xa3, 0x74, 0x84, 0xf0, 0x90, 0xff, 0x80, 0xf0, 0xe4, 0xf5, 0x37, 0xe5, 0x37, 0x12, 
-0x18, 0xbf, 0xf5, 0x83, 0xe4, 0xf0, 0xe5, 0x37, 0x12, 0x18, 0xcd, 0xf5, 0x83, 0xe4, 0xf0, 0x05, 
-0x37, 0xe5, 0x37, 0xb4, 0x07, 0xe7, 0x78, 0x80, 0x76, 0xfe, 0x08, 0x76, 0xf0, 0x90, 0x2f, 0x06, 
-0xe4, 0x93, 0xff, 0x78, 0x7e, 0xf6, 0xfd, 0xad, 0x07, 0x90, 0x2f, 0x13, 0xe4, 0x93, 0xff, 0x08, 
-0xf6, 0xff, 0xed, 0x54, 0x0f, 0xfd, 0x12, 0x18, 0xaf, 0x74, 0x84, 0xf0, 0xed, 0x75, 0xf0, 0x08, 
-0xa4, 0x24, 0x47, 0xf5, 0x82, 0xe4, 0x34, 0xff, 0xf5, 0x83, 0xef, 0xf0, 0xc3, 0x74, 0xf0, 0x9f, 
-0x78, 0x81, 0xf6, 0x74, 0xfe, 0x94, 0x00, 0x18, 0x12, 0x18, 0x41, 0xce, 0xc3, 0x13, 0xce, 0x13, 
-0xd8, 0xf9, 0xff, 0xed, 0x12, 0x19, 0x07, 0xef, 0xf0, 0xed, 0x12, 0x19, 0x2d, 0xe4, 0xf5, 0x37, 
-0xe5, 0x37, 0x90, 0x2f, 0x00, 0x93, 0xff, 0x78, 0x7e, 0xf6, 0xfd, 0xe5, 0x37, 0x25, 0xe0, 0x24, 
-0x07, 0xf5, 0x82, 0xe4, 0x34, 0x2f, 0xf5, 0x83, 0xe4, 0x93, 0x08, 0xf6, 0xed, 0x30, 0xe7, 0x53, 
-0x18, 0xe6, 0x54, 0x0f, 0xf9, 0x12, 0x18, 0xaf, 0x12, 0x19, 0x15, 0x24, 0x47, 0xf5, 0x82, 0xe4, 
-0x34, 0xff, 0x12, 0x18, 0x31, 0xce, 0xc3, 0x13, 0xce, 0x13, 0xd8, 0xf9, 0xff, 0xe9, 0x12, 0x19, 
-0x07, 0xef, 0xf0, 0x12, 0x18, 0x38, 0xce, 0xc3, 0x13, 0xce, 0x13, 0xd8, 0xf9, 0x12, 0x19, 0x1a, 
-0x24, 0x45, 0xf5, 0x82, 0xe4, 0x34, 0xff, 0xf5, 0x83, 0xef, 0xf0, 0xe9, 0x12, 0x19, 0x2d, 0xe9, 
-0x75, 0xf0, 0x08, 0xa4, 0x24, 0x46, 0xf5, 0x82, 0xe4, 0x34, 0xff, 0xf5, 0x83, 0x74, 0x80, 0xf0, 
-0x02, 0x17, 0x46, 0x78, 0x7e, 0xe6, 0x54, 0x0f, 0xf9, 0x12, 0x18, 0xf9, 0x12, 0x19, 0x15, 0x24, 
-0x07, 0xf5, 0x82, 0xe4, 0x34, 0xff, 0x12, 0x18, 0x31, 0xce, 0xc3, 0x13, 0xce, 0x13, 0xd8, 0xf9, 
-0x12, 0x19, 0x1a, 0x24, 0x01, 0xf5, 0x82, 0xe4, 0x34, 0xff, 0xf5, 0x83, 0xef, 0xf0, 0x12, 0x18, 
-0x38, 0xce, 0xc3, 0x13, 0xce, 0x13, 0xd8, 0xf9, 0x12, 0x19, 0x1a, 0x24, 0x05, 0xf5, 0x82, 0xe4, 
-0x34, 0xff, 0xf5, 0x83, 0xef, 0xf0, 0xe9, 0x75, 0xf0, 0x08, 0xa4, 0x24, 0x02, 0xf5, 0x82, 0xe4, 
-0x34, 0xff, 0xf5, 0x83, 0xe4, 0xf0, 0xe9, 0x75, 0xf0, 0x08, 0xa4, 0x24, 0x06, 0xf5, 0x82, 0xe4, 
-0x34, 0xff, 0xf5, 0x83, 0xe4, 0xf0, 0x05, 0x37, 0xe5, 0x37, 0x64, 0x04, 0x60, 0x03, 0x02, 0x16, 
-0x70, 0x90, 0x2f, 0x05, 0xe4, 0x93, 0xff, 0x78, 0x7e, 0xf6, 0x12, 0x18, 0xf7, 0xe4, 0xf0, 0x90, 
-0x2f, 0x04, 0x93, 0xff, 0xf6, 0x12, 0x18, 0xad, 0xe4, 0xf0, 0x90, 0xff, 0xfd, 0x74, 0x05, 0xf0, 
-0x22, 0x7b, 0x00, 0x7a, 0x00, 0x79, 0x37, 0x90, 0xfa, 0xcb, 0xe4, 0x75, 0xf0, 0x01, 0x12, 0x14, 
-0x45, 0x85, 0xf0, 0x41, 0xf5, 0x40, 0x7d, 0x01, 0x02, 0x23, 0xee, 0xab, 0x2d, 0xaa, 0x2e, 0xa9, 
-0x2f, 0xe5, 0x52, 0x12, 0x13, 0xfb, 0x74, 0x01, 0x25, 0x2f, 0xf5, 0x2f, 0xe4, 0x35, 0x2e, 0xf5, 
-0x2e, 0xab, 0x2d, 0xfa, 0xa9, 0x2f, 0x74, 0x11, 0x12, 0x13, 0xfb, 0x74, 0x01, 0x25, 0x2f, 0xf5, 
-0x2f, 0xe4, 0x35, 0x2e, 0xf5, 0x2e, 0x90, 0xff, 0x06, 0xe0, 0xab, 0x2d, 0xaa, 0x2e, 0xa9, 0x2f, 
-0x12, 0x13, 0xfb, 0x74, 0x01, 0x25, 0x2f, 0xf5, 0x2f, 0xe4, 0x35, 0x2e, 0xf5, 0x2e, 0xab, 0x2d, 
-0xfa, 0xa9, 0x2f, 0xe4, 0x12, 0x13, 0xfb, 0x04, 0x25, 0x2f, 0xf5, 0x2f, 0xe4, 0x35, 0x2e, 0xf5, 
-0x2e, 0xab, 0x2d, 0xfa, 0xa9, 0x2f, 0xe4, 0x12, 0x13, 0xfb, 0x04, 0x25, 0x2f, 0xf5, 0x2f, 0xe4, 
-0x35, 0x2e, 0xf5, 0x2e, 0x90, 0xff, 0x04, 0xe0, 0xab, 0x2d, 0xaa, 0x2e, 0xa9, 0x2f, 0x12, 0x13, 
-0xfb, 0x74, 0x01, 0x25, 0x2f, 0xf5, 0x2f, 0xe4, 0x35, 0x2e, 0xf5, 0x2e, 0x90, 0xff, 0x05, 0xe0, 
-0xab, 0x2d, 0xaa, 0x2e, 0xa9, 0x2f, 0x12, 0x13, 0xfb, 0x74, 0x01, 0x25, 0x2f, 0xf5, 0x2f, 0xe4, 
-0x35, 0x2e, 0xf5, 0x2e, 0x22, 0xf5, 0x83, 0xe0, 0x54, 0x08, 0xab, 0x2d, 0xaa, 0x2e, 0xa9, 0x2f, 
-0x22, 0xf5, 0x83, 0xef, 0xf0, 0xfd, 0x7c, 0x00, 0xc3, 0x78, 0x81, 0xe6, 0x9d, 0xf6, 0x18, 0xe6, 
-0x9c, 0xf6, 0xe6, 0xfe, 0x08, 0xe6, 0x78, 0x03, 0x22, 0x75, 0x2d, 0x01, 0x75, 0x2e, 0xf9, 0x75, 
-0x2f, 0x6e, 0x22, 0x90, 0xfa, 0xba, 0xe0, 0x90, 0xfa, 0xb6, 0xf0, 0x90, 0xfa, 0xb5, 0xe0, 0x24, 
-0xfc, 0x22, 0x90, 0xfa, 0xb8, 0xe0, 0xff, 0x7e, 0x00, 0xc3, 0x90, 0xfa, 0xbc, 0xe0, 0x9f, 0xf0, 
-0x90, 0xfa, 0xbb, 0xe0, 0x9e, 0xf0, 0x90, 0xfa, 0xb3, 0xee, 0x8f, 0xf0, 0x12, 0x14, 0x2f, 0xef, 
-0x25, 0x55, 0xf5, 0x55, 0xee, 0x35, 0x54, 0xf5, 0x54, 0x22, 0x7b, 0x01, 0x7a, 0xfa, 0x79, 0xb0, 
-0x90, 0xfa, 0xb3, 0xe0, 0xf5, 0x40, 0xa3, 0xe0, 0xf5, 0x41, 0x22, 0x78, 0x82, 0xe6, 0xfe, 0x08, 
-0xe6, 0x8e, 0x83, 0x24, 0x04, 0xf5, 0x82, 0xe4, 0x35, 0x83, 0xf5, 0x83, 0x22, 0x54, 0x0f, 0x75, 
-0xf0, 0x08, 0xa4, 0x24, 0x40, 0xf5, 0x82, 0xe4, 0x34, 0xff, 0xf5, 0x83, 0x22, 0xe5, 0x53, 0x75, 
-0xf0, 0x08, 0xa4, 0x24, 0x48, 0xf5, 0x82, 0xe4, 0x34, 0xff, 0x22, 0xe5, 0x53, 0x75, 0xf0, 0x08, 
-0xa4, 0x24, 0x08, 0xf5, 0x82, 0xe4, 0x34, 0xff, 0x22, 0x90, 0xff, 0x00, 0xe0, 0x54, 0x1f, 0x22, 
-0x90, 0xfa, 0xb5, 0xe0, 0xff, 0x24, 0xfc, 0x22, 0x75, 0x2a, 0x00, 0x8f, 0x2b, 0x90, 0xf9, 0x6b, 
-0x12, 0x14, 0xfd, 0x90, 0x00, 0x02, 0x22, 0x54, 0x0f, 0x75, 0xf0, 0x08, 0xa4, 0x24, 0x00, 0xf5, 
-0x82, 0xe4, 0x34, 0xff, 0xf5, 0x83, 0x22, 0x75, 0xf0, 0x08, 0xa4, 0x24, 0x41, 0xf5, 0x82, 0xe4, 
-0x34, 0xff, 0xf5, 0x83, 0x22, 0x74, 0x80, 0xf0, 0x08, 0xe6, 0xff, 0xe9, 0x75, 0xf0, 0x08, 0xa4, 
-0x22, 0x74, 0xae, 0x25, 0x36, 0xf5, 0x82, 0xe4, 0x34, 0xfa, 0xf5, 0x83, 0x22, 0x75, 0xf0, 0x08, 
-0xa4, 0x24, 0x42, 0xf5, 0x82, 0xe4, 0x34, 0xff, 0xf5, 0x83, 0x74, 0x80, 0xf0, 0x22, 0x90, 0xff, 
-0x82, 0xe0, 0x44, 0x08, 0xf0, 0x22, 0x90, 0xff, 0xfe, 0xe0, 0x44, 0x03, 0xf0, 0x90, 0xff, 0xfc, 
-0xe0, 0x54, 0xfd, 0xf0, 0x22, 0x78, 0x6d, 0xe6, 0x54, 0xfd, 0xf6, 0x90, 0xff, 0xfd, 0x74, 0x65, 
-0xf0, 0x22, 0x12, 0x14, 0xdf, 0xe0, 0xfe, 0xa3, 0xe0, 0xff, 0x4e, 0x22, 0x7b, 0x01, 0x7a, 0xf9, 
-0x79, 0x6e, 0x22, 0x7b, 0x01, 0x7a, 0xfa, 0x79, 0xb3, 0x22, 0x90, 0xff, 0x80, 0xe0, 0x44, 0x08, 
-0xf0, 0x22, 0x90, 0xff, 0x83, 0xe0, 0x54, 0x7f, 0xf0, 0x22, 0xe0, 0xff, 0x90, 0xf9, 0x66, 0x02, 
-0x14, 0xfd, 0x75, 0x30, 0x01, 0x75, 0x31, 0x09, 0x22, 0xd3, 0xe5, 0x35, 0x94, 0x08, 0xe5, 0x34, 
-0x94, 0x01, 0x22, 0x90, 0xfa, 0xba, 0xe0, 0xff, 0x90, 0xfa, 0xb6, 0xf0, 0x22, 0x90, 0xff, 0xa4, 
-0xe0, 0x54, 0xef, 0x22, 0x90, 0xff, 0xb4, 0xe0, 0x54, 0xef, 0x22, 0x8f, 0x38, 0x12, 0x27, 0x19, 
-0x78, 0x86, 0xe6, 0xfe, 0x08, 0xe6, 0xff, 0x8e, 0x83, 0x24, 0x08, 0x12, 0x20, 0x25, 0xe0, 0xfd, 
-0x12, 0x20, 0xa6, 0x8a, 0x83, 0x24, 0x0a, 0x12, 0x20, 0x25, 0xed, 0xf0, 0x12, 0x20, 0x7c, 0x24, 
-0x07, 0x12, 0x20, 0x25, 0xe0, 0xff, 0x12, 0x20, 0xbe, 0x24, 0x09, 0x12, 0x20, 0x25, 0xef, 0xf0, 
-0x90, 0xf9, 0x65, 0xe0, 0x30, 0xe4, 0x20, 0x08, 0x12, 0x20, 0x2f, 0xc0, 0x83, 0xc0, 0x82, 0xa3, 
-0xe0, 0x25, 0xe0, 0xff, 0x05, 0x82, 0xd5, 0x82, 0x02, 0x15, 0x83, 0x15, 0x82, 0xe0, 0x33, 0xd0, 
-0x82, 0xd0, 0x83, 0xf0, 0xa3, 0xef, 0xf0, 0x78, 0x86, 0x12, 0x20, 0x2f, 0xe0, 0xfc, 0xa3, 0xe0, 
-0xfd, 0xec, 0xff, 0x12, 0x20, 0xa6, 0x8a, 0x83, 0x24, 0x08, 0x12, 0x20, 0x25, 0xef, 0xf0, 0xed, 
-0x12, 0x20, 0xbe, 0x24, 0x07, 0x12, 0x20, 0x25, 0xed, 0xf0, 0x8b, 0x82, 0x8a, 0x83, 0xa3, 0xa3, 
-0xe0, 0xff, 0x53, 0x07, 0xc7, 0x08, 0xe6, 0xfc, 0x08, 0xe6, 0xfd, 0x12, 0x20, 0x69, 0xa3, 0xe0, 
-0x30, 0xe3, 0x12, 0x8d, 0x82, 0x8c, 0x83, 0xe5, 0x82, 0x24, 0x05, 0x12, 0x20, 0x25, 0xe0, 0x90, 
-0x2f, 0x4d, 0x93, 0x42, 0x07, 0x53, 0x07, 0xfb, 0x12, 0x20, 0xae, 0x24, 0x06, 0x12, 0x20, 0x25, 
-0xe0, 0x60, 0x03, 0x43, 0x07, 0x04, 0x53, 0x07, 0xfc, 0x78, 0x86, 0x12, 0x20, 0x96, 0x24, 0x04, 
-0x12, 0x20, 0x25, 0xe0, 0x42, 0x07, 0x43, 0x07, 0x80, 0x12, 0x20, 0xa6, 0xf5, 0x82, 0x8a, 0x83, 
-0xa3, 0xa3, 0xef, 0xf0, 0x12, 0x20, 0xbe, 0x24, 0x04, 0x12, 0x20, 0x25, 0xe0, 0xff, 0x8d, 0x82, 
-0x8c, 0x83, 0xa3, 0xa3, 0xe0, 0xfc, 0xa3, 0xe0, 0xfd, 0x30, 0xe1, 0x05, 0x53, 0x07, 0xdf, 0x80, 
-0x03, 0x43, 0x07, 0x20, 0xec, 0x30, 0xe4, 0x05, 0x53, 0x07, 0xef, 0x80, 0x03, 0x43, 0x07, 0x10, 
-0x90, 0xf9, 0x65, 0xe0, 0xfe, 0x54, 0x03, 0x60, 0x4c, 0x53, 0x07, 0xdf, 0xee, 0x30, 0xe1, 0x42, 
-0x12, 0x20, 0xae, 0x24, 0x09, 0x12, 0x20, 0x25, 0xe0, 0x14, 0x60, 0x31, 0x14, 0x60, 0x29, 0x14, 
-0x60, 0x26, 0x14, 0x60, 0x28, 0x24, 0x04, 0x70, 0x2c, 0xe5, 0x38, 0xb4, 0x03, 0x0d, 0x30, 0x95, 
-0x05, 0x43, 0x07, 0x02, 0x80, 0x1f, 0x53, 0x07, 0xfd, 0x80, 0x1a, 0x30, 0x93, 0x05, 0x43, 0x07, 
-0x02, 0x80, 0x12, 0x53, 0x07, 0xfd, 0x80, 0x0d, 0x43, 0x07, 0x02, 0x80, 0x08, 0x53, 0x07, 0xfd, 
-0x80, 0x03, 0x53, 0x07, 0xfd, 0x12, 0x20, 0x94, 0x24, 0x04, 0x12, 0x20, 0x25, 0xef, 0xf0, 0x8d, 
-0x82, 0x8c, 0x83, 0xa3, 0xa3, 0xa3, 0xe0, 0xff, 0x90, 0xf9, 0x65, 0xe0, 0xfe, 0x54, 0x03, 0x60, 
-0x4a, 0xee, 0x30, 0xe1, 0x43, 0x08, 0x12, 0x20, 0xb0, 0x24, 0x09, 0x12, 0x20, 0x25, 0xe0, 0x14, 
-0x60, 0x2c, 0x14, 0x60, 0x2e, 0x14, 0x60, 0x26, 0x14, 0x60, 0x28, 0x24, 0x04, 0x70, 0x2c, 0xe5, 
-0x38, 0xb4, 0x03, 0x0d, 0x30, 0x94, 0x05, 0x53, 0x07, 0x7f, 0x80, 0x1f, 0x43, 0x07, 0x80, 0x80, 
-0x1a, 0x30, 0x92, 0x05, 0x53, 0x07, 0x7f, 0x80, 0x12, 0x43, 0x07, 0x80, 0x80, 0x0d, 0x53, 0x07, 
-0x7f, 0x80, 0x08, 0x43, 0x07, 0x80, 0x80, 0x03, 0x53, 0x07, 0x7f, 0x78, 0x86, 0x12, 0x20, 0x65, 
-0xe0, 0xfc, 0xa3, 0xe0, 0xfd, 0x30, 0xe0, 0x05, 0x43, 0x07, 0x20, 0x80, 0x03, 0x53, 0x07, 0xdf, 
-0xec, 0x30, 0xe3, 0x05, 0x43, 0x07, 0x40, 0x80, 0x03, 0x53, 0x07, 0xbf, 0xec, 0x30, 0xe0, 0x05, 
-0x43, 0x07, 0x10, 0x80, 0x03, 0x53, 0x07, 0xef, 0xed, 0x30, 0xe4, 0x05, 0x43, 0x07, 0x08, 0x80, 
-0x03, 0x53, 0x07, 0xf7, 0xed, 0x30, 0xe5, 0x05, 0x43, 0x07, 0x04, 0x80, 0x03, 0x53, 0x07, 0xfb, 
-0xed, 0x30, 0xe6, 0x05, 0x43, 0x07, 0x01, 0x80, 0x03, 0x53, 0x07, 0xfe, 0xed, 0x30, 0xe7, 0x05, 
-0x43, 0x07, 0x02, 0x80, 0x03, 0x53, 0x07, 0xfd, 0x78, 0x84, 0x12, 0x20, 0x65, 0xa3, 0xef, 0xf0, 
-0x12, 0x2f, 0x80, 0x7f, 0x00, 0x22, 0x12, 0x0f, 0x89, 0x78, 0x8e, 0xef, 0xf6, 0x12, 0x27, 0x19, 
-0x12, 0x20, 0x70, 0x8e, 0x83, 0x24, 0x09, 0x12, 0x20, 0x25, 0xe0, 0xfd, 0x12, 0x20, 0x53, 0x90, 
-0x00, 0x0a, 0x12, 0x20, 0x78, 0x24, 0x0a, 0x12, 0x20, 0x25, 0xe0, 0x90, 0x00, 0x0b, 0x12, 0x14, 
-0x0d, 0x12, 0x20, 0x70, 0xf5, 0x82, 0x8e, 0x83, 0xa3, 0xa3, 0xa3, 0xe0, 0xf5, 0x59, 0x12, 0x20, 
-0x7c, 0x24, 0x04, 0x12, 0x20, 0x25, 0xe0, 0xf5, 0x5a, 0x8f, 0x82, 0x8e, 0x83, 0xa3, 0xa3, 0xe0, 
-0xf5, 0x5b, 0xe5, 0x59, 0xc4, 0x13, 0x13, 0x13, 0x54, 0x01, 0x78, 0x8e, 0xf6, 0xd3, 0x94, 0x00, 
-0x40, 0x06, 0xe5, 0x5a, 0x30, 0xe1, 0x01, 0x06, 0x78, 0x8e, 0xe6, 0x12, 0x20, 0x52, 0x90, 0x00, 
-0x0c, 0xef, 0x12, 0x14, 0x0d, 0x78, 0x86, 0x12, 0x20, 0x2f, 0xa3, 0xa3, 0xe0, 0xfe, 0xa3, 0xe0, 
-0xff, 0x53, 0x07, 0x0c, 0x53, 0x06, 0xe6, 0xe5, 0x59, 0x30, 0xe5, 0x03, 0x43, 0x07, 0x01, 0xe5, 
-0x5a, 0x20, 0xe5, 0x0e, 0xe5, 0x59, 0x54, 0x7f, 0x70, 0x08, 0xe5, 0x59, 0x20, 0xe7, 0x03, 0x43, 
-0x07, 0x02, 0xe5, 0x59, 0x30, 0xe3, 0x03, 0x43, 0x07, 0x10, 0xe5, 0x59, 0x30, 0xe2, 0x03, 0x43, 
-0x07, 0x20, 0xe5, 0x59, 0x54, 0x03, 0x60, 0x03, 0x43, 0x07, 0x40, 0xe5, 0x59, 0x30, 0xe1, 0x03, 
-0x43, 0x07, 0x80, 0xe5, 0x59, 0x30, 0xe4, 0x03, 0x43, 0x06, 0x01, 0xe5, 0x59, 0x30, 0xe6, 0x03, 
-0x43, 0x06, 0x08, 0xe5, 0x5a, 0x20, 0xe4, 0x0e, 0xe5, 0x59, 0x54, 0x7f, 0x70, 0x08, 0xe5, 0x59, 
-0x20, 0xe7, 0x03, 0x43, 0x06, 0x10, 0x53, 0x07, 0xfb, 0x53, 0x06, 0x79, 0x90, 0x00, 0x05, 0xee, 
-0x8f, 0xf0, 0x12, 0x14, 0xb2, 0xe5, 0x5b, 0x30, 0xe3, 0x12, 0x54, 0x30, 0xff, 0xc4, 0x54, 0x0f, 
-0x12, 0x20, 0x52, 0x90, 0x00, 0x08, 0xef, 0x12, 0x14, 0x0d, 0x80, 0x0a, 0x12, 0x20, 0x53, 0x90, 
-0x00, 0x08, 0xe4, 0x12, 0x14, 0x0d, 0xe5, 0x5b, 0x54, 0x03, 0x12, 0x20, 0x52, 0x90, 0x00, 0x07, 
-0xef, 0x12, 0x14, 0x0d, 0xe5, 0x5b, 0x54, 0x04, 0xff, 0xc3, 0x13, 0x90, 0x00, 0x09, 0x12, 0x14, 
-0x0d, 0x90, 0x00, 0x07, 0x12, 0x13, 0xce, 0x70, 0x13, 0x12, 0x20, 0x53, 0xe9, 0x24, 0x09, 0xf9, 
-0xe4, 0x3a, 0xfa, 0x12, 0x13, 0xb5, 0xff, 0xc3, 0x13, 0x12, 0x13, 0xfb, 0x12, 0x20, 0x94, 0x24, 
-0x08, 0x12, 0x20, 0x25, 0xe0, 0xfe, 0x8d, 0x82, 0x8c, 0x83, 0xe5, 0x82, 0x24, 0x07, 0x12, 0x20, 
-0x25, 0xe0, 0xfd, 0xee, 0xed, 0x12, 0x20, 0x52, 0x90, 0x00, 0x03, 0xee, 0x8f, 0xf0, 0x12, 0x14, 
-0xb2, 0x12, 0x2f, 0x80, 0x7d, 0x0a, 0xe4, 0xff, 0x12, 0x2c, 0xc0, 0x02, 0x10, 0x0c, 0x90, 0xfa, 
-0xe2, 0xe0, 0xb4, 0x03, 0x06, 0x7e, 0x00, 0x7f, 0x40, 0x80, 0x04, 0x7e, 0x00, 0x7f, 0x08, 0x90, 
-0xfa, 0xd6, 0xee, 0xf0, 0xa3, 0xef, 0xf0, 0x90, 0x00, 0x05, 0x12, 0x13, 0xce, 0xff, 0x7e, 0x00, 
-0x90, 0xfa, 0xd2, 0xee, 0xf0, 0xa3, 0xef, 0xf0, 0x70, 0x03, 0x7f, 0x08, 0x22, 0x90, 0x00, 0x08, 
-0x12, 0x14, 0x5b, 0xff, 0x90, 0xfa, 0xd4, 0xe5, 0xf0, 0xf0, 0xa3, 0xef, 0xf0, 0xae, 0x02, 0xaf, 
-0x01, 0x8e, 0x56, 0x8f, 0x57, 0x74, 0x0a, 0x25, 0x57, 0xf5, 0x57, 0xe4, 0x35, 0x56, 0xf5, 0x56, 
-0x90, 0xfa, 0xd7, 0xe0, 0xff, 0x14, 0xfe, 0x90, 0xfa, 0xd5, 0xe0, 0x5e, 0xfe, 0xc3, 0xef, 0x9e, 
-0xff, 0x90, 0xfa, 0xd9, 0xf0, 0xc3, 0x90, 0xfa, 0xd3, 0xe0, 0x9f, 0x90, 0xfa, 0xd2, 0xe0, 0x94, 
-0x00, 0x50, 0x06, 0xa3, 0xe0, 0x90, 0xfa, 0xd9, 0xf0, 0x12, 0x1e, 0x2d, 0x60, 0x03, 0xe0, 0xff, 
-0x22, 0x12, 0x2a, 0x80, 0x90, 0xfa, 0xd2, 0xe0, 0xfe, 0xa3, 0xe0, 0xff, 0x4e, 0x60, 0x2b, 0x90, 
-0xfa, 0xd6, 0xe0, 0xfc, 0xa3, 0xe0, 0xfd, 0xd3, 0xef, 0x9d, 0xee, 0x9c, 0x40, 0x07, 0xe0, 0x90, 
-0xfa, 0xd9, 0xf0, 0x80, 0x08, 0x90, 0xfa, 0xd3, 0xe0, 0x90, 0xfa, 0xd9, 0xf0, 0x12, 0x1e, 0x2d, 
-0x60, 0x03, 0xe0, 0xff, 0x22, 0x12, 0x2a, 0x80, 0x80, 0xca, 0x7b, 0x00, 0x7a, 0x00, 0x79, 0x58, 
-0xe4, 0xf5, 0x40, 0xf5, 0x41, 0x7d, 0x01, 0x12, 0x23, 0xee, 0x7f, 0x00, 0x22, 0xaa, 0x56, 0xa9, 
-0x57, 0x7b, 0x01, 0x90, 0xfa, 0xd4, 0xe0, 0xfc, 0xa3, 0xe0, 0xfd, 0x90, 0xfa, 0xd9, 0xe0, 0xf5, 
-0x50, 0x12, 0x26, 0x25, 0x90, 0xfa, 0xd8, 0xef, 0xf0, 0x22, 0xef, 0x24, 0xae, 0x60, 0x52, 0x24, 
-0xfe, 0x60, 0x2e, 0x24, 0xfe, 0x70, 0x03, 0x02, 0x1e, 0xed, 0x24, 0x06, 0x60, 0x03, 0x02, 0x1f, 
-0x35, 0x78, 0x77, 0xe6, 0x54, 0xfb, 0xf6, 0x90, 0xff, 0xa5, 0xe0, 0xf5, 0x36, 0x44, 0x0f, 0xf0, 
-0x74, 0x33, 0x90, 0xfa, 0x90, 0xf0, 0xe5, 0x36, 0xa3, 0xf0, 0x90, 0xfa, 0xae, 0x74, 0x01, 0xf0, 
-0x22, 0x78, 0x78, 0xe6, 0x54, 0xfb, 0xf6, 0x90, 0xff, 0xb5, 0xe0, 0xf5, 0x36, 0x44, 0x0f, 0xf0, 
-0x74, 0x43, 0x90, 0xfa, 0x92, 0xf0, 0xe5, 0x36, 0xa3, 0xf0, 0x90, 0xfa, 0xaf, 0x74, 0x01, 0xf0, 
-0x22, 0x90, 0xfa, 0x9c, 0xe0, 0xa3, 0x20, 0xe5, 0x03, 0x02, 0x1f, 0x35, 0x90, 0xff, 0xa6, 0xe0, 
-0x90, 0xfa, 0xc9, 0xf0, 0xa3, 0xf0, 0x90, 0xfa, 0xc9, 0xe0, 0xff, 0x54, 0x0f, 0xfe, 0x60, 0x10, 
-0x90, 0xff, 0xa6, 0x12, 0x20, 0x83, 0x90, 0xff, 0xa6, 0xe0, 0x90, 0xfa, 0xc9, 0xf0, 0x80, 0xe6, 
-0x90, 0xfa, 0xca, 0xe0, 0xff, 0x74, 0x34, 0xfe, 0x12, 0x29, 0xda, 0xef, 0x70, 0x57, 0x90, 0xfa, 
-0xca, 0xe0, 0xff, 0x74, 0x34, 0x90, 0xfa, 0x94, 0xf0, 0xef, 0xa3, 0xf0, 0x22, 0x90, 0xfa, 0xa6, 
-0xe0, 0xa3, 0x30, 0xe5, 0x40, 0x90, 0xff, 0xb6, 0xe0, 0x90, 0xfa, 0xc9, 0xf0, 0xa3, 0xf0, 0x90, 
-0xfa, 0xc9, 0xe0, 0xff, 0x54, 0x0f, 0xfe, 0x60, 0x10, 0x90, 0xff, 0xb6, 0x12, 0x20, 0x83, 0x90, 
-0xff, 0xb6, 0xe0, 0x90, 0xfa, 0xc9, 0xf0, 0x80, 0xe6, 0x90, 0xfa, 0xca, 0xe0, 0xff, 0x74, 0x44, 
-0xfe, 0x12, 0x29, 0xda, 0xef, 0x70, 0x0e, 0x90, 0xfa, 0xca, 0xe0, 0xff, 0x74, 0x44, 0x90, 0xfa, 
-0x96, 0xf0, 0xef, 0xa3, 0xf0, 0x22, 0xc0, 0xe0, 0xc0, 0xf0, 0xc0, 0x83, 0xc0, 0x82, 0xc0, 0xd0, 
-0x75, 0xd0, 0x00, 0xc0, 0x00, 0xc0, 0x01, 0xc0, 0x02, 0xc0, 0x03, 0xc0, 0x04, 0xc0, 0x05, 0xc0, 
-0x06, 0xc0, 0x07, 0x90, 0xff, 0x92, 0xe0, 0xff, 0x90, 0xfa, 0xc8, 0xf0, 0x90, 0xff, 0x92, 0xe4, 
-0xf0, 0xef, 0x12, 0x15, 0x0f, 0x1f, 0xed, 0x26, 0x1f, 0xed, 0x2e, 0x1f, 0x90, 0x30, 0x1f, 0x90, 
-0x32, 0x1f, 0x9e, 0x38, 0x1f, 0xb0, 0x3a, 0x1f, 0xe2, 0x3e, 0x1f, 0xcd, 0x44, 0x1f, 0xc2, 0x46, 
-0x1f, 0xd8, 0x50, 0x1f, 0xd8, 0x52, 0x1f, 0xd8, 0x54, 0x1f, 0xd8, 0x56, 0x00, 0x00, 0x1f, 0xf2, 
-0x90, 0xfa, 0xc8, 0xe0, 0xfd, 0x7c, 0x00, 0x7f, 0x01, 0x12, 0x10, 0x9c, 0x80, 0x62, 0x7c, 0x00, 
-0x7d, 0x01, 0x7f, 0x03, 0x12, 0x10, 0x9c, 0x90, 0xff, 0xfe, 0xe0, 0x44, 0x20, 0xf0, 0x80, 0x50, 
-0x7c, 0x00, 0x7d, 0x01, 0x7f, 0x02, 0x12, 0x10, 0x9c, 0x90, 0xff, 0xfe, 0xe0, 0x44, 0x40, 0xf0, 
-0x80, 0x3e, 0x7c, 0x00, 0x7d, 0x01, 0x7f, 0x05, 0x12, 0x10, 0x9c, 0x80, 0x33, 0x7c, 0x00, 0x7d, 
-0x01, 0x7f, 0x06, 0x12, 0x10, 0x9c, 0x80, 0x28, 0x90, 0xfa, 0xc8, 0xe0, 0xff, 0x12, 0x1e, 0x4a, 
-0x80, 0x1e, 0x7c, 0x00, 0x7d, 0x01, 0x7f, 0x04, 0x12, 0x10, 0x9c, 0x80, 0x13, 0x12, 0x25, 0x13, 
-0x80, 0x0e, 0x90, 0xfa, 0xc8, 0xe0, 0x24, 0x00, 0xff, 0xe4, 0x34, 0xff, 0xfe, 0x12, 0x29, 0xda, 
-0xd0, 0x07, 0xd0, 0x06, 0xd0, 0x05, 0xd0, 0x04, 0xd0, 0x03, 0xd0, 0x02, 0xd0, 0x01, 0xd0, 0x00, 
-0xd0, 0xd0, 0xd0, 0x82, 0xd0, 0x83, 0xd0, 0xf0, 0xd0, 0xe0, 0x32, 0x78, 0x82, 0xe6, 0xfe, 0x08, 
-0xe6, 0x24, 0x04, 0x8e, 0x83, 0xf5, 0x82, 0xe4, 0x35, 0x83, 0xf5, 0x83, 0x22, 0x78, 0x82, 0xe6, 
-0xfe, 0x08, 0xe6, 0xf5, 0x82, 0x8e, 0x83, 0x22, 0x78, 0x86, 0xe6, 0xfe, 0x08, 0xe6, 0xaa, 0x06, 
-0xf8, 0xac, 0x02, 0x7d, 0x01, 0x7b, 0xff, 0x7a, 0x2f, 0x79, 0x52, 0x7e, 0x00, 0x7f, 0x0a, 0x02, 
-0x13, 0x8f, 0xff, 0x90, 0xf9, 0x6b, 0x02, 0x14, 0xfd, 0x90, 0xf9, 0x66, 0x12, 0x14, 0xfd, 0x90, 
-0x00, 0x04, 0x02, 0x13, 0xce, 0xe6, 0xfc, 0x08, 0xe6, 0xf5, 0x82, 0x8c, 0x83, 0xa3, 0xa3, 0x22, 
-0x78, 0x84, 0xe6, 0xfe, 0x08, 0xe6, 0xff, 0x22, 0xed, 0x12, 0x14, 0x0d, 0x8f, 0x82, 0x8e, 0x83, 
-0xe5, 0x82, 0x22, 0xef, 0xf0, 0x90, 0xfa, 0xca, 0xe0, 0x54, 0x0f, 0x4e, 0xfe, 0xf0, 0xef, 0x54, 
-0xf0, 0x4e, 0xf0, 0x22, 0x78, 0x84, 0xe6, 0xfc, 0x08, 0xe6, 0xfd, 0x8c, 0x83, 0x22, 0xa6, 0x07, 
-0xe6, 0x24, 0x74, 0xf8, 0xe6, 0x22, 0x78, 0x84, 0xe6, 0xfa, 0x08, 0xe6, 0xfb, 0x22, 0x78, 0x86, 
-0xe6, 0xfc, 0x08, 0xe6, 0x8c, 0x83, 0x22, 0x26, 0xf6, 0x18, 0xee, 0x36, 0xf6, 0x22, 0x8b, 0x82, 
-0x8a, 0x83, 0xe5, 0x82, 0x22, 0x8b, 0x38, 0x8a, 0x39, 0x89, 0x3a, 0x8d, 0x3b, 0x90, 0xfa, 0xce, 
-0xe4, 0xf0, 0xa3, 0x74, 0x02, 0xf0, 0x7b, 0x01, 0x7a, 0xfa, 0x79, 0xcd, 0x90, 0xfa, 0xce, 0xe0, 
-0xf5, 0x40, 0xa3, 0xe0, 0xf5, 0x41, 0x7d, 0x01, 0x12, 0x23, 0xee, 0x90, 0xfa, 0xcd, 0xe0, 0x65, 
-0x3b, 0x60, 0x46, 0xa3, 0xe0, 0xff, 0xa3, 0xe0, 0xa3, 0xcf, 0xf0, 0xa3, 0xef, 0xf0, 0x12, 0x21, 
-0x54, 0x90, 0xfa, 0xcd, 0xe0, 0xff, 0x90, 0xfa, 0xd0, 0xe4, 0x8f, 0xf0, 0x12, 0x14, 0x2f, 0x12, 
-0x21, 0x54, 0x90, 0xfa, 0xd0, 0xe0, 0xff, 0xa3, 0xe0, 0x90, 0xfa, 0xce, 0xcf, 0xf0, 0xa3, 0xef, 
-0xf0, 0x90, 0xfa, 0xcd, 0xe0, 0xa3, 0x75, 0xf0, 0x00, 0x12, 0x14, 0x2f, 0x90, 0xfa, 0xce, 0xe4, 
-0x75, 0xf0, 0x04, 0x12, 0x14, 0x2f, 0x02, 0x20, 0xd6, 0x90, 0xfa, 0xcf, 0xe0, 0x24, 0x01, 0xff, 
-0x90, 0xfa, 0xce, 0xe0, 0x34, 0x00, 0xab, 0x38, 0xaa, 0x39, 0xa9, 0x3a, 0x8f, 0xf0, 0x12, 0x14, 
-0x93, 0x7f, 0x00, 0x22, 0x7b, 0x01, 0x7a, 0xfa, 0x79, 0xcd, 0x90, 0xfa, 0xce, 0xe4, 0x75, 0xf0, 
-0x01, 0x12, 0x14, 0x2f, 0x85, 0xf0, 0x41, 0xf5, 0x40, 0x7d, 0x01, 0x02, 0x23, 0xee, 0x8f, 0x68, 
-0x12, 0x27, 0x19, 0x12, 0x20, 0x70, 0x8e, 0x83, 0x24, 0x0b, 0x12, 0x20, 0x25, 0xe0, 0x54, 0xfb, 
-0xf0, 0x44, 0x02, 0xf0, 0x08, 0x12, 0x20, 0x65, 0xe0, 0xa3, 0x30, 0xe5, 0x0c, 0x12, 0x20, 0x7c, 
-0x24, 0x0b, 0x12, 0x20, 0x25, 0xe0, 0x44, 0x01, 0xf0, 0x78, 0x82, 0xe6, 0xfe, 0x08, 0xe6, 0xff, 
-0xf5, 0x82, 0x8e, 0x83, 0xe0, 0x54, 0xb8, 0xfd, 0xf0, 0xe5, 0x68, 0x24, 0xfe, 0x44, 0x20, 0xfc, 
-0x4d, 0xf0, 0xe5, 0x82, 0x24, 0x04, 0x12, 0x20, 0x25, 0xe0, 0x54, 0xb8, 0xf0, 0x4c, 0xf0, 0x8f, 
-0x82, 0x8e, 0x83, 0xa3, 0x74, 0x03, 0xf0, 0x18, 0xe6, 0xfe, 0x08, 0xe6, 0xff, 0x8e, 0x83, 0x24, 
-0x05, 0x12, 0x20, 0x25, 0xc0, 0x83, 0xc0, 0x82, 0xe0, 0xfd, 0x74, 0x95, 0x25, 0x68, 0xf5, 0x82, 
-0xe4, 0x34, 0xfa, 0xf5, 0x83, 0xe0, 0x54, 0xfc, 0x44, 0x03, 0xfc, 0xed, 0x4c, 0xd0, 0x82, 0xd0, 
-0x83, 0xf0, 0x8f, 0x82, 0x8e, 0x83, 0xe0, 0x44, 0x80, 0xf0, 0xe5, 0x82, 0x24, 0x04, 0x12, 0x20, 
-0x25, 0xe0, 0x44, 0x80, 0xf0, 0x12, 0x2f, 0x80, 0x74, 0x74, 0x25, 0x68, 0xf8, 0x74, 0x04, 0x46, 
-0xf6, 0x7f, 0x00, 0x22, 0x8b, 0x62, 0x8a, 0x63, 0x89, 0x64, 0x12, 0x2a, 0x62, 0x90, 0xfa, 0xbf, 
-0x12, 0x15, 0x06, 0xaa, 0x63, 0xa9, 0x64, 0x90, 0xfa, 0xc2, 0x12, 0x15, 0x06, 0x90, 0xfa, 0xc3, 
-0xe4, 0x75, 0xf0, 0x0a, 0x12, 0x14, 0x2f, 0x90, 0xfa, 0xc2, 0x12, 0x14, 0xfd, 0xe9, 0x24, 0x01, 
-0xf9, 0xe4, 0x3a, 0xfa, 0x90, 0xfa, 0xc5, 0x12, 0x15, 0x06, 0xab, 0x62, 0xaa, 0x63, 0xa9, 0x64, 
-0x12, 0x2a, 0x6e, 0xe0, 0xff, 0xc3, 0x13, 0xf0, 0xe4, 0x78, 0x88, 0xf6, 0x90, 0xfa, 0xbd, 0xe0, 
-0xff, 0x78, 0x88, 0xe6, 0xc3, 0x9f, 0x50, 0x4a, 0x90, 0xfa, 0xbf, 0x12, 0x2a, 0x43, 0xff, 0x78, 
-0x89, 0xf6, 0x90, 0xfa, 0xc2, 0x12, 0x2a, 0x43, 0xfe, 0xf4, 0x5f, 0xff, 0x78, 0x89, 0xf6, 0x12, 
-0x2a, 0x40, 0x5e, 0x4f, 0xff, 0x78, 0x89, 0xf6, 0x12, 0x2a, 0x49, 0x75, 0xf0, 0x02, 0x12, 0x14, 
-0x2f, 0x90, 0xfa, 0xc3, 0xe4, 0x75, 0xf0, 0x02, 0x12, 0x14, 0x2f, 0xab, 0x62, 0xaa, 0x63, 0xa9, 
-0x64, 0x90, 0x00, 0x04, 0x12, 0x13, 0xce, 0x30, 0xe4, 0x03, 0x12, 0x2a, 0x58, 0x78, 0x88, 0x06, 
-0x80, 0xaa, 0xe4, 0x90, 0xfa, 0xbe, 0xf0, 0x22, 0x8b, 0x5c, 0x8a, 0x5d, 0x89, 0x5e, 0x90, 0xfa, 
-0xbe, 0x74, 0x06, 0xf0, 0xe4, 0x90, 0xfa, 0xbd, 0xf0, 0x12, 0x13, 0xb5, 0x24, 0x6e, 0x60, 0x26, 
-0x14, 0x70, 0x70, 0x12, 0x2a, 0x2f, 0x60, 0x09, 0x24, 0x30, 0x70, 0x12, 0x12, 0x22, 0x14, 0x80, 
-0x62, 0x12, 0x2a, 0x79, 0x12, 0x1d, 0x5e, 0x90, 0xfa, 0xbe, 0xef, 0xf0, 0x80, 0x55, 0x90, 0xfa, 
-0xbe, 0x74, 0x81, 0xf0, 0x80, 0x4d, 0x12, 0x2a, 0x2f, 0x60, 0x09, 0x24, 0x30, 0x70, 0x3e, 0x12, 
-0x29, 0x85, 0x80, 0x3f, 0xe5, 0x5e, 0x24, 0x03, 0xf9, 0xe4, 0x35, 0x5d, 0xfa, 0x7b, 0x01, 0xc0, 
-0x03, 0xc0, 0x02, 0xc0, 0x01, 0x12, 0x2a, 0x79, 0x90, 0x00, 0x05, 0x12, 0x13, 0xce, 0xfd, 0x90, 
-0x00, 0x08, 0x12, 0x14, 0x5b, 0xf5, 0x41, 0x85, 0xf0, 0x40, 0xd0, 0x01, 0xd0, 0x02, 0xd0, 0x03, 
-0x12, 0x23, 0xee, 0x90, 0xfa, 0xbd, 0xef, 0xf0, 0xe4, 0xa3, 0xf0, 0x80, 0x06, 0x90, 0xfa, 0xbe, 
-0x74, 0x81, 0xf0, 0x90, 0xfa, 0xbe, 0xe0, 0x12, 0x2a, 0x79, 0x90, 0x00, 0x02, 0x12, 0x14, 0x0d, 
-0x90, 0xfa, 0xbd, 0xe0, 0xff, 0x22, 0x12, 0x0f, 0x89, 0x7f, 0x02, 0x12, 0x11, 0x9f, 0x78, 0x6d, 
-0xe6, 0x44, 0x02, 0xf6, 0xd2, 0xb0, 0xd2, 0xb1, 0xd2, 0xb3, 0x90, 0xff, 0xa4, 0xe0, 0x90, 0xfa, 
-0x7a, 0xf0, 0x90, 0xff, 0xb4, 0xe0, 0x90, 0xfa, 0x7b, 0xf0, 0x90, 0xff, 0xa2, 0xe0, 0x90, 0xfa, 
-0x78, 0xf0, 0x90, 0xff, 0xb2, 0xe0, 0x90, 0xfa, 0x79, 0xf0, 0x90, 0xff, 0xa4, 0x74, 0x30, 0xf0, 
-0x90, 0xff, 0xb4, 0xf0, 0x90, 0xff, 0xa2, 0x74, 0x40, 0xf0, 0x90, 0xff, 0xb2, 0xf0, 0x90, 0xfa, 
-0xe3, 0xe5, 0xa8, 0xf0, 0x75, 0xa8, 0x81, 0x90, 0xff, 0x92, 0xe0, 0x60, 0x04, 0xe4, 0xf0, 0x80, 
-0xf6, 0x90, 0xff, 0xfd, 0x74, 0x3a, 0xf0, 0x43, 0x87, 0x01, 0x00, 0x00, 0x00, 0x90, 0xfa, 0x7a, 
-0xe0, 0x90, 0xff, 0xa4, 0xf0, 0x90, 0xfa, 0x7b, 0xe0, 0x90, 0xff, 0xb4, 0xf0, 0x90, 0xfa, 0x78, 
-0xe0, 0x90, 0xff, 0xa2, 0xf0, 0x90, 0xfa, 0x79, 0xe0, 0x90, 0xff, 0xb2, 0xf0, 0x90, 0xf9, 0x15, 
-0xe0, 0x60, 0x02, 0xc2, 0xb3, 0x90, 0xfa, 0xe3, 0xe0, 0xf5, 0xa8, 0x02, 0x10, 0x0c, 0x8b, 0x3c, 
-0x8a, 0x3d, 0x89, 0x3e, 0x8d, 0x3f, 0xe5, 0x3f, 0x70, 0x03, 0xaf, 0x3f, 0x22, 0x12, 0x2a, 0xa8, 
-0x70, 0x16, 0x12, 0x2a, 0xc7, 0xe5, 0x40, 0x90, 0xff, 0xf1, 0xf0, 0x12, 0x2e, 0xd4, 0x50, 0xf2, 
-0x12, 0x24, 0x7b, 0x40, 0x0b, 0x7f, 0x00, 0x22, 0x12, 0x2a, 0xc7, 0x12, 0x24, 0x7b, 0x50, 0xf8, 
-0x90, 0xff, 0xf3, 0x74, 0xa1, 0xf0, 0xe5, 0x3f, 0xb4, 0x01, 0x07, 0x90, 0xff, 0xf0, 0xe0, 0x44, 
-0x02, 0xf0, 0x90, 0xff, 0xf1, 0xe4, 0xf0, 0xf5, 0x42, 0xe5, 0x3f, 0x14, 0xff, 0xe5, 0x42, 0xc3, 
-0x9f, 0x50, 0x2a, 0x12, 0x2e, 0xbd, 0x40, 0x03, 0xaf, 0x42, 0x22, 0xc3, 0xe5, 0x3f, 0x95, 0x42, 
-0xff, 0xbf, 0x02, 0x07, 0x90, 0xff, 0xf0, 0xe0, 0x44, 0x02, 0xf0, 0x12, 0x2a, 0xba, 0x05, 0x42, 
-0x74, 0x01, 0x25, 0x3e, 0xf5, 0x3e, 0xe4, 0x35, 0x3d, 0xf5, 0x3d, 0x80, 0xcc, 0x12, 0x2e, 0xbd, 
-0x40, 0x03, 0x7f, 0x18, 0x22, 0x12, 0x2a, 0xba, 0xaf, 0x3f, 0x22, 0x90, 0xff, 0xf1, 0xe5, 0x41, 
-0xf0, 0x02, 0x2e, 0xd4, 0x75, 0xa8, 0x40, 0x78, 0x7f, 0xe4, 0xf6, 0xd8, 0xfd, 0x75, 0x81, 0x91, 
-0x02, 0x24, 0xce, 0x02, 0x2e, 0x88, 0xe4, 0x93, 0xa3, 0xf8, 0xe4, 0x93, 0xa3, 0x40, 0x03, 0xf6, 
-0x80, 0x01, 0xf2, 0x08, 0xdf, 0xf4, 0x80, 0x29, 0xe4, 0x93, 0xa3, 0xf8, 0x54, 0x07, 0x24, 0x0c, 
-0xc8, 0xc3, 0x33, 0xc4, 0x54, 0x0f, 0x44, 0x20, 0xc8, 0x83, 0x40, 0x04, 0xf4, 0x56, 0x80, 0x01, 
-0x46, 0xf6, 0xdf, 0xe4, 0x80, 0x0b, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x90, 0x28, 
-0xcb, 0xe4, 0x7e, 0x01, 0x93, 0x60, 0xbc, 0xa3, 0xff, 0x54, 0x3f, 0x30, 0xe5, 0x09, 0x54, 0x1f, 
-0xfe, 0xe4, 0x93, 0xa3, 0x60, 0x01, 0x0e, 0xcf, 0x54, 0xc0, 0x25, 0xe0, 0x60, 0xa8, 0x40, 0xb8, 
-0xe4, 0x93, 0xa3, 0xfa, 0xe4, 0x93, 0xa3, 0xf8, 0xe4, 0x93, 0xa3, 0xc8, 0xc5, 0x82, 0xc8, 0xca, 
-0xc5, 0x83, 0xca, 0xf0, 0xa3, 0xc8, 0xc5, 0x82, 0xc8, 0xca, 0xc5, 0x83, 0xca, 0xdf, 0xe9, 0xde, 
-0xe7, 0x80, 0xbe, 0xe4, 0xf5, 0x36, 0x12, 0x19, 0x21, 0xe0, 0xb4, 0x04, 0x0d, 0xe5, 0x36, 0x24, 
-0x03, 0xff, 0x12, 0x2d, 0x4f, 0x12, 0x19, 0x21, 0xe4, 0xf0, 0x05, 0x36, 0xe5, 0x36, 0xc3, 0x94, 
-0x02, 0x40, 0xe3, 0xe4, 0xf5, 0x36, 0x75, 0xf0, 0x02, 0xe5, 0x36, 0x90, 0xfa, 0x90, 0x12, 0x19, 
-0x62, 0x60, 0x2c, 0x12, 0x29, 0xda, 0xef, 0x60, 0x52, 0x75, 0xf0, 0x02, 0xe5, 0x36, 0x90, 0xfa, 
-0x90, 0x12, 0x14, 0xdf, 0xe4, 0xf0, 0xa3, 0xf0, 0x75, 0xf0, 0x0a, 0xe5, 0x36, 0x90, 0xfa, 0x9c, 
-0x12, 0x14, 0xdf, 0xe0, 0xa3, 0x30, 0xe6, 0x33, 0x12, 0x19, 0x21, 0x74, 0x04, 0xf0, 0x22, 0x75, 
-0xf0, 0x02, 0xe5, 0x36, 0x90, 0xfa, 0x94, 0x12, 0x19, 0x62, 0x60, 0x16, 0x12, 0x29, 0xda, 0xef, 
-0x60, 0x19, 0x75, 0xf0, 0x02, 0xe5, 0x36, 0x90, 0xfa, 0x94, 0x12, 0x14, 0xdf, 0xe4, 0xf0, 0xa3, 
-0xf0, 0x22, 0x05, 0x36, 0xe5, 0x36, 0xc3, 0x94, 0x02, 0x40, 0x9b, 0x22, 0xe4, 0xff, 0x90, 0xff, 
-0x83, 0xe0, 0x54, 0x0f, 0xfe, 0xef, 0xc3, 0x9e, 0x50, 0x17, 0x74, 0xf0, 0x2f, 0xf5, 0x82, 0xe4, 
-0x34, 0xfe, 0xf5, 0x83, 0xe0, 0x12, 0x18, 0x2a, 0x12, 0x13, 0xfb, 0x0f, 0x12, 0x18, 0x19, 0x80, 
-0xdd, 0xef, 0xfd, 0xc3, 0xe5, 0x31, 0x9d, 0xf5, 0x31, 0xe5, 0x30, 0x94, 0x00, 0xf5, 0x30, 0xd3, 
-0xe5, 0x31, 0x94, 0x00, 0xe5, 0x30, 0x94, 0x00, 0x40, 0x06, 0xe4, 0x90, 0xff, 0x83, 0xf0, 0x22, 
-0x12, 0x19, 0x3e, 0x12, 0x19, 0x92, 0x12, 0x19, 0x8c, 0x12, 0x13, 0xb5, 0x24, 0x6e, 0x60, 0x1e, 
-0x14, 0x60, 0x1b, 0x24, 0x8e, 0x70, 0x2d, 0x90, 0x00, 0x01, 0x12, 0x13, 0xce, 0xff, 0x24, 0xfc, 
-0x60, 0x03, 0x04, 0x70, 0x1f, 0xef, 0xfd, 0x7c, 0x00, 0x7f, 0x0d, 0x02, 0x10, 0x9c, 0x12, 0x19, 
-0x6c, 0x12, 0x22, 0xb8, 0x12, 0x18, 0xe8, 0x12, 0x13, 0xce, 0x60, 0x03, 0x02, 0x2f, 0x76, 0xe4, 
-0xff, 0x12, 0x2f, 0x6a, 0x22, 0x8b, 0x4b, 0x8a, 0x4c, 0x89, 0x4d, 0x8c, 0x4e, 0x8d, 0x4f, 0xd2, 
-0x00, 0x12, 0x2a, 0xa8, 0x70, 0x16, 0x12, 0x2a, 0xc7, 0xe5, 0x4e, 0x90, 0xff, 0xf1, 0xf0, 0x12, 
-0x2e, 0xd4, 0x50, 0xf2, 0x12, 0x26, 0x9a, 0x40, 0x0b, 0x7f, 0x18, 0x22, 0x12, 0x2a, 0xc7, 0x12, 
-0x26, 0x9a, 0x50, 0xf8, 0xe4, 0xf5, 0x51, 0xe5, 0x50, 0x14, 0xff, 0xe5, 0x51, 0xc3, 0x9f, 0x50, 
-0x17, 0x12, 0x26, 0x8a, 0x40, 0x03, 0x7f, 0x18, 0x22, 0x05, 0x51, 0x74, 0x01, 0x25, 0x4d, 0xf5, 
-0x4d, 0xe4, 0x35, 0x4c, 0xf5, 0x4c, 0x80, 0xdf, 0x90, 0xff, 0xf0, 0xe0, 0x44, 0x01, 0xf0, 0x12, 
-0x26, 0x8a, 0x40, 0x03, 0x7f, 0x18, 0x22, 0x7f, 0x00, 0x22, 0xab, 0x4b, 0xaa, 0x4c, 0xa9, 0x4d, 
-0x12, 0x13, 0xb5, 0x90, 0xff, 0xf1, 0xf0, 0x02, 0x2e, 0xd4, 0x90, 0xff, 0xf1, 0xe5, 0x4f, 0xf0, 
-0x02, 0x2e, 0xd4, 0x7b, 0x01, 0x7a, 0xfa, 0x79, 0xcb, 0xe4, 0xfd, 0x12, 0x20, 0xc5, 0x90, 0xfa, 
-0xcb, 0xe4, 0x75, 0xf0, 0x09, 0x12, 0x14, 0x2f, 0x7b, 0x00, 0x7a, 0x00, 0x79, 0x37, 0x90, 0xfa, 
-0xcb, 0xe4, 0x75, 0xf0, 0x01, 0x12, 0x14, 0x45, 0x85, 0xf0, 0x41, 0xf5, 0x40, 0x7d, 0x01, 0x12, 
-0x23, 0xee, 0x90, 0xff, 0xf7, 0xe5, 0x37, 0x12, 0x26, 0xfe, 0x90, 0xff, 0xf6, 0xe5, 0x37, 0xf0, 
-0x90, 0xfa, 0xcb, 0xe4, 0xf0, 0xa3, 0x74, 0x06, 0x12, 0x26, 0xfe, 0xe5, 0x37, 0x30, 0xe0, 0x07, 
-0x90, 0xff, 0xfc, 0x74, 0x94, 0xf0, 0x22, 0x90, 0xff, 0xfc, 0x74, 0x90, 0xf0, 0x22, 0xf0, 0x7b, 
-0x00, 0x7a, 0x00, 0x79, 0x37, 0x90, 0xfa, 0xcb, 0xe4, 0x75, 0xf0, 0x01, 0x12, 0x14, 0x45, 0x85, 
-0xf0, 0x41, 0xf5, 0x40, 0x7d, 0x01, 0x02, 0x23, 0xee, 0x15, 0x6b, 0xa8, 0x6b, 0xa6, 0x07, 0x30, 
-0x08, 0x05, 0x12, 0x10, 0xec, 0x80, 0xf8, 0xd2, 0x08, 0xa8, 0x6b, 0xe6, 0xff, 0xb4, 0x03, 0x0f, 
-0x78, 0x82, 0x76, 0xff, 0x08, 0x76, 0xe0, 0x08, 0x76, 0xff, 0x08, 0x76, 0xa0, 0x80, 0x0d, 0x78, 
-0x82, 0x76, 0xff, 0x08, 0x76, 0xe2, 0x08, 0x76, 0xff, 0x08, 0x76, 0xb0, 0x78, 0x86, 0x76, 0xfa, 
-0x08, 0x76, 0x9a, 0xef, 0x24, 0xfd, 0x75, 0xf0, 0x0a, 0xa4, 0xae, 0xf0, 0x12, 0x20, 0xb7, 0x7b, 
-0x01, 0x7a, 0xff, 0x79, 0x48, 0x78, 0x6e, 0x12, 0x14, 0xf4, 0xa8, 0x6b, 0xe6, 0x24, 0xfd, 0x75, 
-0xf0, 0x08, 0xa4, 0xff, 0xae, 0xf0, 0x78, 0x70, 0x12, 0x20, 0xb7, 0x79, 0x08, 0x78, 0x71, 0x12, 
-0x14, 0xf4, 0x78, 0x73, 0xef, 0x12, 0x20, 0xb7, 0x05, 0x6b, 0x22, 0x90, 0xff, 0xf0, 0xe0, 0x54, 
-0xab, 0xf0, 0xe0, 0x44, 0x20, 0xf0, 0x90, 0xfa, 0xe2, 0x74, 0x02, 0xf0, 0x7b, 0x01, 0x7a, 0xfa, 
-0x79, 0xcb, 0xe4, 0xf5, 0x40, 0xf5, 0x41, 0x7d, 0x01, 0x12, 0x23, 0xee, 0x7e, 0x00, 0x90, 0xfa, 
-0xe0, 0xee, 0xf0, 0xa3, 0xef, 0xf0, 0x64, 0x01, 0x70, 0x10, 0x90, 0xfa, 0xcb, 0xe0, 0xb4, 0x52, 
-0x09, 0x90, 0xf9, 0x65, 0xe0, 0x54, 0xef, 0xf0, 0x80, 0x29, 0x90, 0xfa, 0xe0, 0xe0, 0x70, 0x04, 
-0xa3, 0xe0, 0x64, 0x01, 0x70, 0x10, 0x90, 0xfa, 0xcb, 0xe0, 0xb4, 0x10, 0x09, 0x90, 0xf9, 0x65, 
-0xe0, 0x44, 0x10, 0xf0, 0x80, 0x0d, 0x90, 0xfa, 0xe2, 0x74, 0x03, 0xf0, 0x90, 0xf9, 0x65, 0xe0, 
-0x54, 0xef, 0xf0, 0x90, 0xff, 0xf0, 0xe0, 0x44, 0x20, 0xf0, 0x22, 0x90, 0xff, 0x93, 0x74, 0x2a, 
-0xf0, 0x90, 0xff, 0xff, 0xe0, 0x60, 0x06, 0x90, 0xff, 0xfc, 0x74, 0x10, 0xf0, 0x90, 0xff, 0x91, 
-0xe0, 0x44, 0x90, 0xf0, 0x12, 0x27, 0x8b, 0x12, 0x15, 0x35, 0x12, 0x2d, 0xa5, 0x7e, 0x07, 0x7f, 
-0xd0, 0x12, 0x11, 0x68, 0x7e, 0x0f, 0x7f, 0xa0, 0x12, 0x11, 0x82, 0xe4, 0x78, 0x7d, 0xf6, 0x78, 
-0x7d, 0xe6, 0xff, 0xc3, 0x94, 0x06, 0x50, 0x0b, 0x74, 0x74, 0x2f, 0xf8, 0xe4, 0xf6, 0x78, 0x7d, 
-0x06, 0x80, 0xec, 0x7f, 0x03, 0x12, 0x2c, 0x5b, 0x90, 0xf9, 0x65, 0xe0, 0x20, 0xe4, 0x05, 0x7f, 
-0x04, 0x12, 0x2c, 0x5b, 0x90, 0xff, 0x9b, 0xe4, 0xf0, 0x90, 0xff, 0x9a, 0xf0, 0x90, 0xff, 0xe8, 
-0xe0, 0x54, 0x1f, 0xf0, 0xd2, 0xa8, 0x22, 0x12, 0x0f, 0x89, 0x78, 0x90, 0xef, 0xf6, 0x12, 0x27, 
-0x19, 0x12, 0x20, 0x59, 0x30, 0xe0, 0x25, 0x12, 0x20, 0x2d, 0xe0, 0x54, 0x7f, 0xf0, 0x78, 0x71, 
-0x12, 0x14, 0xeb, 0x90, 0x00, 0x02, 0x12, 0x13, 0xce, 0x30, 0xe7, 0x09, 0x90, 0x00, 0x02, 0xe4, 
-0x12, 0x14, 0x0d, 0x80, 0xe9, 0x12, 0x20, 0x2d, 0xe0, 0x44, 0x80, 0xf0, 0x12, 0x20, 0x59, 0x30, 
-0xe1, 0x1e, 0x12, 0x20, 0x1b, 0xe0, 0x54, 0x7f, 0xf0, 0x12, 0x2f, 0x15, 0x78, 0x6e, 0x12, 0x14, 
-0xeb, 0x90, 0x00, 0x02, 0x74, 0x80, 0x12, 0x14, 0x0d, 0x12, 0x20, 0x1b, 0xe0, 0x44, 0x80, 0xf0, 
-0x12, 0x2f, 0x80, 0xe4, 0xff, 0x12, 0x2e, 0xa5, 0x02, 0x10, 0x0c, 0x03, 0x6e, 0x01, 0xff, 0x48, 
-0x03, 0x71, 0x01, 0xff, 0x08, 0x02, 0x6c, 0x00, 0x00, 0x44, 0xfa, 0x94, 0x00, 0x00, 0x00, 0x00, 
-0x44, 0xfa, 0x90, 0x00, 0x00, 0x00, 0x00, 0x42, 0xfa, 0xae, 0x00, 0x00, 0x42, 0xfa, 0x7a, 0x00, 
-0x00, 0x42, 0xfa, 0x78, 0x00, 0x00, 0x42, 0xf9, 0x69, 0xff, 0xff, 0x42, 0xfa, 0x76, 0x00, 0x00, 
-0x43, 0xf9, 0x16, 0x0a, 0x32, 0x02, 0x41, 0xf9, 0x63, 0x20, 0x41, 0xf9, 0x64, 0x20, 0x41, 0xf9, 
-0x61, 0x00, 0x41, 0xf9, 0x62, 0x00, 0x44, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, 0xf9, 0x65, 
-0x00, 0x41, 0xf9, 0x15, 0x00, 0x01, 0x20, 0x00, 0x41, 0xf8, 0x04, 0x00, 0x00, 0x12, 0x19, 0x82, 
-0xe5, 0x31, 0x64, 0x09, 0x70, 0x04, 0xe5, 0x30, 0x64, 0x01, 0x60, 0x48, 0xc3, 0xe5, 0x31, 0x94, 
-0x08, 0xe5, 0x30, 0x94, 0x00, 0x40, 0x11, 0x7f, 0x08, 0xef, 0xe5, 0x31, 0x94, 0x08, 0xf5, 0x31, 
-0xe5, 0x30, 0x94, 0x00, 0xf5, 0x30, 0x80, 0x05, 0xaf, 0x31, 0x12, 0x19, 0x92, 0xe4, 0xfe, 0xee, 
-0xc3, 0x9f, 0x50, 0x19, 0x12, 0x18, 0x2a, 0x12, 0x13, 0xb5, 0xfd, 0x74, 0xf8, 0x2e, 0xf5, 0x82, 
-0xe4, 0x34, 0xfe, 0xf5, 0x83, 0xed, 0xf0, 0x0e, 0x12, 0x18, 0x19, 0x80, 0xe2, 0xef, 0x54, 0x7f, 
-0x90, 0xff, 0x81, 0xf0, 0x22, 0x8b, 0x5f, 0x8a, 0x60, 0x89, 0x61, 0x12, 0x2a, 0x6e, 0x70, 0x05, 
-0xa3, 0x74, 0x08, 0xf0, 0x22, 0xab, 0x5f, 0xaa, 0x60, 0xa9, 0x61, 0x12, 0x2a, 0x62, 0x90, 0xfa, 
-0xc5, 0x12, 0x15, 0x06, 0xe5, 0x61, 0x24, 0x03, 0xf9, 0xe4, 0x35, 0x60, 0xfa, 0x90, 0xfa, 0xbf, 
-0x12, 0x15, 0x06, 0xe4, 0x90, 0xfa, 0xbe, 0xf0, 0x78, 0x91, 0xf6, 0x90, 0xfa, 0xbd, 0xe0, 0xff, 
-0x78, 0x91, 0xe6, 0xc3, 0x9f, 0x50, 0x12, 0x12, 0x2a, 0x40, 0xff, 0x12, 0x2a, 0x49, 0x12, 0x2a, 
-0x5c, 0x78, 0x91, 0x06, 0x12, 0x2a, 0x58, 0x80, 0xe2, 0x22, 0xad, 0x07, 0xac, 0x06, 0x90, 0x2f, 
-0x06, 0xe4, 0x93, 0xff, 0x78, 0x7a, 0xf6, 0x54, 0x0f, 0x12, 0x19, 0x07, 0xe0, 0x08, 0x76, 0x00, 
-0x08, 0xf6, 0x18, 0x12, 0x18, 0x42, 0xc3, 0x33, 0xce, 0x33, 0xce, 0xd8, 0xf9, 0xff, 0x78, 0x7b, 
-0xee, 0xf6, 0x08, 0xef, 0xf6, 0xee, 0x44, 0xf8, 0x18, 0xf6, 0xef, 0x08, 0xf6, 0x90, 0xff, 0x7a, 
-0xe0, 0x20, 0xe7, 0x03, 0x7f, 0x00, 0x22, 0x78, 0x7b, 0xe6, 0xfe, 0x08, 0xe6, 0xf5, 0x82, 0x8e, 
-0x83, 0xec, 0xf0, 0xa3, 0xed, 0xf0, 0x90, 0xff, 0x7a, 0x74, 0x02, 0xf0, 0x7f, 0x01, 0x22, 0xab, 
-0x5c, 0xaa, 0x5d, 0xa9, 0x5e, 0x90, 0x00, 0x03, 0x12, 0x13, 0xce, 0x54, 0xf0, 0x24, 0xa0, 0x22, 
-0x90, 0xfa, 0xc5, 0x12, 0x14, 0xfd, 0x02, 0x13, 0xb5, 0x90, 0xfa, 0xbf, 0x12, 0x14, 0xfd, 0xef, 
-0x12, 0x13, 0xfb, 0x90, 0xfa, 0xc6, 0xe4, 0x22, 0x90, 0xfa, 0xc0, 0xe4, 0x75, 0xf0, 0x01, 0x02, 
-0x14, 0x2f, 0x90, 0x00, 0x08, 0x12, 0x14, 0x5b, 0xaa, 0xf0, 0xf9, 0x7b, 0x01, 0x22, 0x90, 0x00, 
-0x05, 0x12, 0x13, 0xce, 0x90, 0xfa, 0xbd, 0xf0, 0x22, 0xab, 0x5c, 0xaa, 0x5d, 0xa9, 0x5e, 0x22, 
-0x90, 0xfa, 0xd9, 0xe0, 0xff, 0x7e, 0x00, 0xc3, 0x90, 0xfa, 0xd3, 0xe0, 0x9f, 0xf0, 0x90, 0xfa, 
-0xd2, 0xe0, 0x9e, 0xf0, 0x90, 0xfa, 0xd4, 0xee, 0x8f, 0xf0, 0x12, 0x14, 0x2f, 0xef, 0x25, 0x57, 
-0xf5, 0x57, 0xee, 0x35, 0x56, 0xf5, 0x56, 0x22, 0x90, 0xff, 0xf0, 0xe0, 0x54, 0xfe, 0xf0, 0xe0, 
-0x54, 0xfd, 0xf0, 0x90, 0xfa, 0xe2, 0xe0, 0x64, 0x03, 0x22, 0x90, 0xff, 0xf2, 0xe0, 0xab, 0x3c, 
-0xaa, 0x3d, 0xa9, 0x3e, 0x02, 0x13, 0xfb, 0x90, 0xff, 0xf3, 0x74, 0xa0, 0xf0, 0x22, 0x8f, 0x6a, 
-0xed, 0x70, 0x0f, 0xe5, 0x6a, 0xb4, 0x03, 0x05, 0x7f, 0x01, 0x02, 0x2e, 0xeb, 0x7f, 0x02, 0x02, 
-0x2e, 0xeb, 0xaf, 0x6a, 0x12, 0x27, 0x19, 0x74, 0x74, 0x25, 0x6a, 0xf8, 0xe6, 0x30, 0xe2, 0x0b, 
-0xd2, 0x09, 0x12, 0x18, 0x9b, 0xe0, 0x54, 0x7f, 0xf0, 0x80, 0x02, 0xc2, 0x09, 0xe5, 0x6a, 0xb4, 
-0x03, 0x07, 0x7f, 0x81, 0x12, 0x2e, 0xeb, 0x80, 0x05, 0x7f, 0x82, 0x12, 0x2e, 0xeb, 0x30, 0x09, 
-0x07, 0x12, 0x18, 0x9b, 0xe0, 0x44, 0x80, 0xf0, 0x12, 0x2f, 0x80, 0x22, 0x12, 0x0f, 0x89, 0x90, 
-0xff, 0xfd, 0xe0, 0x44, 0x60, 0xf0, 0xd2, 0x01, 0x90, 0xff, 0xfc, 0xe0, 0x44, 0x02, 0xf0, 0x90, 
-0xff, 0x00, 0xe0, 0x30, 0xe7, 0x13, 0x90, 0xff, 0x83, 0xe0, 0x44, 0x80, 0xf0, 0x43, 0x2c, 0x80, 
-0x90, 0xff, 0xfc, 0xe0, 0x44, 0x01, 0xf0, 0x80, 0x0d, 0x12, 0x19, 0x3e, 0x53, 0x2c, 0x7f, 0x90, 
-0xff, 0xfc, 0xe0, 0x54, 0xfe, 0xf0, 0x90, 0xff, 0x81, 0xe0, 0x44, 0x80, 0xf0, 0x12, 0x02, 0x9f, 
-0x12, 0x19, 0x46, 0x02, 0x10, 0x0c, 0x12, 0x0f, 0x89, 0x78, 0x8a, 0x12, 0x20, 0x9e, 0x30, 0xe1, 
-0x07, 0x7f, 0x13, 0x12, 0x2e, 0xa5, 0x80, 0x34, 0x90, 0xf9, 0x65, 0xe0, 0x54, 0x03, 0x60, 0x16, 
-0x78, 0x8a, 0xe6, 0xb4, 0x03, 0x09, 0x90, 0xff, 0xa4, 0xe0, 0x54, 0xdf, 0xf0, 0x80, 0x07, 0x90, 
-0xff, 0xb4, 0xe0, 0x54, 0xdf, 0xf0, 0xc2, 0xb3, 0x90, 0xf9, 0x15, 0xe0, 0x04, 0xf0, 0x78, 0x8a, 
-0xe6, 0xff, 0x12, 0x20, 0x59, 0xfd, 0x12, 0x2d, 0x21, 0x12, 0x2e, 0xa5, 0x02, 0x10, 0x0c, 0x12, 
-0x0f, 0x89, 0x78, 0x8f, 0xef, 0xf6, 0xd2, 0x00, 0x12, 0x27, 0x19, 0x90, 0xf9, 0x66, 0x12, 0x14, 
-0xfd, 0xe9, 0x24, 0x03, 0xf9, 0xe4, 0x3a, 0xfa, 0xc0, 0x02, 0x78, 0x86, 0xe6, 0xfe, 0x08, 0xe6, 
-0xaa, 0x06, 0xf8, 0xac, 0x02, 0x7d, 0x01, 0xd0, 0x02, 0x12, 0x20, 0x4b, 0x12, 0x2f, 0x80, 0x78, 
-0x8f, 0xe6, 0xff, 0x12, 0x19, 0xbb, 0x12, 0x2e, 0xa5, 0x02, 0x10, 0x0c, 0x12, 0x0f, 0x89, 0x78, 
-0x8b, 0xef, 0xf6, 0x12, 0x2e, 0x4c, 0x12, 0x2e, 0xa5, 0x90, 0xf9, 0x65, 0xe0, 0x54, 0x03, 0x60, 
-0x16, 0x78, 0x8b, 0xe6, 0xb4, 0x03, 0x09, 0x90, 0xff, 0xa4, 0xe0, 0x44, 0x20, 0xf0, 0x80, 0x07, 
-0x90, 0xff, 0xb4, 0xe0, 0x44, 0x20, 0xf0, 0x90, 0xf9, 0x15, 0xe0, 0x14, 0xf0, 0xe0, 0x70, 0x02, 
-0xd2, 0xb3, 0x02, 0x10, 0x0c, 0x8f, 0x69, 0x12, 0x27, 0x19, 0x12, 0x20, 0x2d, 0xe0, 0x54, 0x3f, 
-0xf0, 0xe5, 0x82, 0x24, 0x04, 0x12, 0x20, 0x25, 0xe0, 0x54, 0x3f, 0xf0, 0x08, 0xe6, 0xfe, 0x08, 
-0xe6, 0x8e, 0x83, 0x24, 0x0b, 0x12, 0x20, 0x25, 0xe0, 0x54, 0xf8, 0xf0, 0x12, 0x2f, 0x80, 0x74, 
-0x74, 0x25, 0x69, 0xf8, 0x74, 0xfb, 0x56, 0xf6, 0x7f, 0x00, 0x22, 0x8f, 0x37, 0xc2, 0x08, 0x12, 
-0x27, 0x19, 0x12, 0x20, 0x38, 0x78, 0x84, 0x12, 0x20, 0x1d, 0xe0, 0x44, 0x01, 0xf0, 0x12, 0x20, 
-0x70, 0x12, 0x20, 0x21, 0xe0, 0x20, 0xe0, 0xf6, 0xef, 0x24, 0x0b, 0xf5, 0x82, 0xe4, 0x3e, 0xf5, 
-0x83, 0xe0, 0x54, 0xf8, 0xf0, 0x12, 0x2f, 0x80, 0xaf, 0x37, 0x12, 0x19, 0xbb, 0x22, 0x12, 0x0f, 
-0x89, 0x12, 0x27, 0x19, 0x12, 0x20, 0x70, 0x24, 0x06, 0x12, 0x20, 0x23, 0xe0, 0xfd, 0x12, 0x20, 
-0x53, 0x90, 0x00, 0x03, 0x12, 0x20, 0x78, 0x24, 0x05, 0x12, 0x20, 0x25, 0xe0, 0x90, 0x00, 0x04, 
-0x12, 0x14, 0x0d, 0x12, 0x2f, 0x80, 0x7d, 0x02, 0xe4, 0xff, 0x12, 0x2c, 0xc0, 0x02, 0x10, 0x0c, 
-0xae, 0x05, 0x12, 0x18, 0xed, 0xef, 0x12, 0x14, 0x0d, 0x0e, 0x0e, 0x0e, 0xee, 0xd3, 0x95, 0x35, 
-0xe4, 0x95, 0x34, 0x40, 0x02, 0xae, 0x35, 0xee, 0xd3, 0x94, 0x08, 0x74, 0x80, 0x94, 0x81, 0x40, 
-0x0a, 0x7e, 0x03, 0x90, 0x00, 0x02, 0x74, 0x02, 0x12, 0x14, 0x0d, 0xaf, 0x06, 0x12, 0x2f, 0x6a, 
-0x22, 0x12, 0x0f, 0x89, 0x78, 0x8c, 0x12, 0x20, 0x9e, 0x30, 0xe2, 0x07, 0x7f, 0x13, 0x12, 0x2e, 
-0xa5, 0x80, 0x1b, 0x78, 0x8c, 0xe6, 0x24, 0x74, 0xf8, 0xe6, 0x20, 0xe1, 0x07, 0x7f, 0x12, 0x12, 
-0x2e, 0xa5, 0x80, 0x0a, 0x78, 0x8c, 0xe6, 0xff, 0x12, 0x21, 0x6e, 0x12, 0x2e, 0xa5, 0x02, 0x10, 
-0x0c, 0xae, 0x07, 0xed, 0x54, 0x03, 0x64, 0x01, 0x60, 0x03, 0x7f, 0x10, 0x22, 0xed, 0x54, 0x7c, 
-0xc3, 0x94, 0x04, 0x50, 0x03, 0x7f, 0x0b, 0x22, 0x74, 0x74, 0x2e, 0xf8, 0x74, 0x02, 0x46, 0xf6, 
-0x74, 0x95, 0x2e, 0xf5, 0x82, 0xe4, 0x34, 0xfa, 0xf5, 0x83, 0xed, 0xf0, 0x7f, 0x00, 0x22, 0xbf, 
-0x03, 0x06, 0x7c, 0xff, 0x7d, 0xe0, 0x80, 0x04, 0x7c, 0xff, 0x7d, 0xe2, 0x8d, 0x82, 0x8c, 0x83, 
-0xe0, 0x44, 0x80, 0xf0, 0xe5, 0x82, 0x24, 0x04, 0x12, 0x20, 0x25, 0xe0, 0x44, 0x80, 0xf0, 0x74, 
-0x74, 0x2f, 0xf8, 0x74, 0x04, 0x46, 0xf6, 0x7f, 0x00, 0x22, 0x12, 0x0f, 0x89, 0xe5, 0x31, 0x64, 
-0x09, 0x70, 0x04, 0xe5, 0x30, 0x64, 0x01, 0x60, 0x16, 0x90, 0xff, 0x83, 0xe0, 0x54, 0x0f, 0xff, 
-0xc3, 0xe5, 0x31, 0x9f, 0xe5, 0x30, 0x94, 0x00, 0x40, 0x05, 0x12, 0x25, 0x9c, 0x80, 0x03, 0x12, 
-0x2f, 0x76, 0x02, 0x10, 0x0c, 0x90, 0xff, 0xfc, 0xe0, 0x20, 0xe7, 0x1f, 0xc2, 0xaf, 0x7d, 0xff, 
-0xac, 0x05, 0x1d, 0xec, 0x60, 0x15, 0x7e, 0x04, 0x7f, 0x00, 0xef, 0x1f, 0xaa, 0x06, 0x70, 0x01, 
-0x1e, 0x4a, 0x60, 0xec, 0x90, 0xff, 0x92, 0xe4, 0xf0, 0x80, 0xef, 0x22, 0x12, 0x0f, 0x89, 0x78, 
-0x6c, 0xe6, 0xfe, 0x08, 0xe6, 0xff, 0x30, 0xe0, 0x12, 0x30, 0xe1, 0x0f, 0x90, 0xff, 0xfc, 0xe0, 
-0x44, 0x20, 0xf0, 0x7f, 0x04, 0x12, 0x11, 0x9f, 0x12, 0x19, 0x55, 0x02, 0x10, 0x0c, 0x8e, 0x65, 
-0x8f, 0x66, 0xe5, 0x66, 0x15, 0x66, 0xae, 0x65, 0x70, 0x02, 0x15, 0x65, 0xd3, 0x94, 0x00, 0xee, 
-0x94, 0x00, 0x40, 0x09, 0x7e, 0x07, 0x7f, 0xd0, 0x12, 0x0f, 0x62, 0x80, 0xe5, 0x22, 0x11, 0x1a, 
-0x2b, 0x1c, 0x23, 0x56, 0x2f, 0x5c, 0x2d, 0xcc, 0x2d, 0x7a, 0x2e, 0x6b, 0x2c, 0x8e, 0x2b, 0x66, 
-0x2b, 0xec, 0x2c, 0xf1, 0x2e, 0x2d, 0x1b, 0xe6, 0x2b, 0xaf, 0x28, 0x67, 0x0e, 0x12, 0x0f, 0x89, 
-0x78, 0x8d, 0x12, 0x20, 0x9e, 0x20, 0xe2, 0x07, 0x7f, 0x11, 0x12, 0x2e, 0xa5, 0x80, 0x0a, 0x78, 
-0x8d, 0xe6, 0xff, 0x12, 0x2c, 0x25, 0x12, 0x2e, 0xa5, 0x02, 0x10, 0x0c, 0x8f, 0x67, 0x12, 0x2c, 
-0x25, 0xaf, 0x67, 0x12, 0x27, 0x19, 0x12, 0x20, 0x38, 0x12, 0x2f, 0x80, 0x74, 0x74, 0x25, 0x67, 
-0xf8, 0x74, 0xfd, 0x56, 0xf6, 0xaf, 0x67, 0x12, 0x19, 0xbb, 0x22, 0x12, 0x0f, 0x89, 0xe5, 0x31, 
-0x64, 0x09, 0x70, 0x04, 0xe5, 0x30, 0x64, 0x01, 0x60, 0x05, 0x12, 0x29, 0x2d, 0x80, 0x06, 0x12, 
-0x19, 0x7a, 0x12, 0x19, 0x82, 0x02, 0x10, 0x0c, 0x12, 0x27, 0xfb, 0x12, 0x12, 0x3b, 0x90, 0xf8, 
-0x04, 0xe0, 0xff, 0x60, 0x05, 0x7d, 0x01, 0x12, 0x11, 0xd8, 0x12, 0x26, 0xa3, 0x12, 0x12, 0x77, 
-0x12, 0x10, 0xfa, 0x80, 0xe3, 0x12, 0x18, 0xed, 0xef, 0x12, 0x14, 0x0d, 0xe4, 0xf5, 0x2a, 0xf5, 
-0x2b, 0xef, 0x60, 0x03, 0x02, 0x2f, 0x76, 0xe4, 0xff, 0x12, 0x2f, 0x6a, 0x22, 0x90, 0xff, 0xf0, 
-0xe0, 0xff, 0x54, 0xa0, 0x60, 0xf7, 0xef, 0x30, 0xe5, 0x08, 0x90, 0xff, 0xf0, 0x44, 0x20, 0xf0, 
-0xc3, 0x22, 0xd3, 0x22, 0x90, 0xff, 0xf0, 0xe0, 0xff, 0x54, 0x28, 0x60, 0xf7, 0xef, 0x30, 0xe5, 
-0x08, 0x90, 0xff, 0xf0, 0x44, 0x20, 0xf0, 0xc3, 0x22, 0xd3, 0x22, 0xef, 0x30, 0xe7, 0x08, 0x12, 
-0x18, 0xad, 0xe0, 0x54, 0xdf, 0xf0, 0x22, 0xef, 0x12, 0x18, 0xf7, 0xe0, 0x54, 0xdf, 0xf0, 0x22, 
-0x81, 0x01, 0x82, 0x02, 0x83, 0x03, 0x87, 0x40, 0x00, 0x40, 0x00, 0x40, 0x00, 0x40, 0x00, 0x40, 
-0x00, 0x40, 0x00, 0x08, 0x00, 0x78, 0x84, 0x12, 0x20, 0x2f, 0xa3, 0xa3, 0xe0, 0xff, 0x30, 0xe7, 
-0x06, 0x54, 0x7f, 0xf0, 0x44, 0x80, 0xf0, 0x22, 0x85, 0x34, 0x30, 0x85, 0x35, 0x31, 0x90, 0xff, 
-0x82, 0xe0, 0x54, 0xf7, 0xf0, 0xa3, 0xe0, 0x54, 0x7f, 0xf0, 0x22, 0xe4, 0xfe, 0xee, 0x90, 0x2f, 
-0x00, 0x93, 0xb5, 0x07, 0x02, 0xd3, 0x22, 0x0e, 0xbe, 0x07, 0xf2, 0xc3, 0x22, 0x00, 0x08, 0x18, 
-0x38, 0x28, 0x01, 0x81, 0x10, 0x0a, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12, 0x0f, 0x89, 0x7f, 
-0x02, 0x12, 0x10, 0x18, 0x12, 0x19, 0x55, 0x02, 0x10, 0x0c, 0x75, 0x30, 0x00, 0x8f, 0x31, 0x12, 
-0x18, 0x49, 0x12, 0x29, 0x2d, 0x22, 0x12, 0x19, 0x82, 0x12, 0x19, 0x3e, 0x12, 0x19, 0x7a, 0x22, 
-0xc2, 0x08, 0x22, 
+0xd9, 0xf5, 0xeb, 0x70, 0x10, 0xea, 0xf0, 0xc0, 0x07, 0x12, 0x12, 0x41, 0xad, 0x07, 0xaf, 0x02, 
+0x12, 0x12, 0x58, 0xd0, 0x07, 0xa3, 0xa3, 0xa3, 0xdf, 0xce, 0x12, 0x11, 0x66, 0x80, 0xc1, 0x8f, 
+0x24, 0x12, 0x2a, 0x06, 0x78, 0x80, 0xe6, 0xfe, 0x08, 0xe6, 0xff, 0x8e, 0x83, 0x24, 0x08, 0x12, 
+0x21, 0xf3, 0xe0, 0xfd, 0x12, 0x22, 0x8a, 0x8a, 0x83, 0x24, 0x0a, 0x12, 0x21, 0xf3, 0xed, 0xf0, 
+0x12, 0x22, 0x56, 0x24, 0x07, 0x12, 0x21, 0xf3, 0xe0, 0xff, 0x12, 0x22, 0x99, 0x24, 0x09, 0x12, 
+0x21, 0xf3, 0xef, 0xf0, 0x90, 0xf9, 0x15, 0xe0, 0x30, 0xe4, 0x20, 0x08, 0x12, 0x22, 0x09, 0xc0, 
+0x83, 0xc0, 0x82, 0xa3, 0xe0, 0x25, 0xe0, 0xff, 0x05, 0x82, 0xd5, 0x82, 0x02, 0x15, 0x83, 0x15, 
+0x82, 0xe0, 0x33, 0xd0, 0x82, 0xd0, 0x83, 0xf0, 0xa3, 0xef, 0xf0, 0x78, 0x80, 0x12, 0x22, 0x09, 
+0xe0, 0xfc, 0xa3, 0xe0, 0xfd, 0xec, 0xff, 0x12, 0x22, 0x8a, 0x8a, 0x83, 0x24, 0x08, 0x12, 0x21, 
+0xf3, 0xef, 0xf0, 0xed, 0x12, 0x22, 0x99, 0x24, 0x07, 0x12, 0x21, 0xf3, 0xed, 0xf0, 0x12, 0x21, 
+0xfb, 0xe0, 0xff, 0x30, 0xe7, 0x19, 0x12, 0x22, 0x6e, 0x12, 0x21, 0xf3, 0xe0, 0x60, 0x09, 0x12, 
+0x21, 0xfb, 0xef, 0x44, 0x02, 0xf0, 0x80, 0x07, 0x12, 0x21, 0xfb, 0xef, 0x54, 0xfd, 0xf0, 0x78, 
+0x7e, 0x12, 0x22, 0x09, 0xa3, 0xa3, 0xe0, 0xff, 0x53, 0x07, 0xc7, 0x08, 0xe6, 0xfc, 0x08, 0xe6, 
+0xfd, 0x12, 0x22, 0x43, 0xa3, 0xe0, 0x30, 0xe3, 0x12, 0x8d, 0x82, 0x8c, 0x83, 0xe5, 0x82, 0x24, 
+0x05, 0x12, 0x21, 0xf3, 0xe0, 0x90, 0x31, 0x94, 0x93, 0x42, 0x07, 0x53, 0x07, 0xfb, 0x78, 0x80, 
+0xe6, 0xfc, 0x08, 0xe6, 0x8c, 0x83, 0x24, 0x06, 0x12, 0x21, 0xf3, 0xe0, 0x60, 0x03, 0x43, 0x07, 
+0x04, 0x53, 0x07, 0xfc, 0x78, 0x80, 0x12, 0x22, 0x7a, 0x24, 0x04, 0x12, 0x21, 0xf3, 0xe0, 0x42, 
+0x07, 0x43, 0x07, 0x80, 0x12, 0x22, 0x8a, 0xf5, 0x82, 0x8a, 0x83, 0xa3, 0xa3, 0xef, 0xf0, 0x12, 
+0x22, 0x99, 0x24, 0x04, 0x12, 0x21, 0xf3, 0xe0, 0xff, 0x8d, 0x82, 0x8c, 0x83, 0xa3, 0xa3, 0xe0, 
+0xfc, 0xa3, 0xe0, 0xfd, 0x30, 0xe1, 0x05, 0x53, 0x07, 0xdf, 0x80, 0x03, 0x43, 0x07, 0x20, 0xec, 
+0x30, 0xe4, 0x05, 0x53, 0x07, 0xef, 0x80, 0x03, 0x43, 0x07, 0x10, 0x12, 0x21, 0xfb, 0xe0, 0xfe, 
+0x54, 0x03, 0x60, 0x73, 0x53, 0x07, 0xdf, 0xee, 0x30, 0xe1, 0x69, 0x78, 0x80, 0x12, 0x22, 0x6f, 
+0x12, 0x21, 0xf3, 0xe0, 0x12, 0x1b, 0x4c, 0x14, 0xa6, 0x00, 0x14, 0xda, 0x01, 0x14, 0xdf, 0x03, 
+0x14, 0xda, 0x05, 0x14, 0xdf, 0x07, 0x14, 0xda, 0x09, 0x14, 0xdf, 0x0b, 0x14, 0xda, 0x0d, 0x14, 
+0xdf, 0x0f, 0x00, 0x00, 0x14, 0xe7, 0xe5, 0x24, 0x64, 0x03, 0x70, 0x21, 0x90, 0xf9, 0x15, 0xe0, 
+0x30, 0xe2, 0x0d, 0x30, 0xb4, 0x05, 0x43, 0x07, 0x02, 0x80, 0x2c, 0x53, 0x07, 0xfd, 0x80, 0x27, 
+0x30, 0x95, 0x05, 0x43, 0x07, 0x02, 0x80, 0x1f, 0x53, 0x07, 0xfd, 0x80, 0x1a, 0x30, 0x93, 0x05, 
+0x43, 0x07, 0x02, 0x80, 0x12, 0x53, 0x07, 0xfd, 0x80, 0x0d, 0x43, 0x07, 0x02, 0x80, 0x08, 0x53, 
+0x07, 0xfd, 0x80, 0x03, 0x53, 0x07, 0xfd, 0x12, 0x22, 0x78, 0x24, 0x04, 0x12, 0x21, 0xf3, 0xef, 
+0xf0, 0x8d, 0x82, 0x8c, 0x83, 0xa3, 0xa3, 0xa3, 0xe0, 0xff, 0x12, 0x21, 0xfb, 0xe0, 0xfe, 0x54, 
+0x03, 0x70, 0x03, 0x02, 0x15, 0xd7, 0xee, 0x20, 0xe1, 0x03, 0x02, 0x15, 0xd4, 0x12, 0x22, 0x6e, 
+0x12, 0x21, 0xf3, 0xe0, 0x12, 0x1b, 0x4c, 0x15, 0x36, 0x00, 0x15, 0x6c, 0x01, 0x15, 0x6c, 0x03, 
+0x15, 0xa0, 0x05, 0x15, 0xa0, 0x07, 0x15, 0x86, 0x09, 0x15, 0x86, 0x0b, 0x15, 0xba, 0x0d, 0x15, 
+0xba, 0x0f, 0x00, 0x00, 0x15, 0xd7, 0xe5, 0x24, 0x64, 0x03, 0x70, 0x23, 0x90, 0xf9, 0x15, 0xe0, 
+0x30, 0xe2, 0x0f, 0x30, 0xb1, 0x06, 0x53, 0x07, 0x7f, 0x02, 0x15, 0xd7, 0x43, 0x07, 0x80, 0x02, 
+0x15, 0xd7, 0x30, 0x94, 0x05, 0x53, 0x07, 0x7f, 0x80, 0x7d, 0x43, 0x07, 0x80, 0x80, 0x78, 0x30, 
+0x92, 0x05, 0x53, 0x07, 0x7f, 0x80, 0x70, 0x43, 0x07, 0x80, 0x80, 0x6b, 0xe5, 0x24, 0xb4, 0x03, 
+0x09, 0x90, 0xff, 0x9e, 0xe0, 0x54, 0xef, 0xf0, 0x80, 0x07, 0x90, 0xff, 0x9e, 0xe0, 0x54, 0xdf, 
+0xf0, 0x53, 0x07, 0x7f, 0x80, 0x51, 0xe5, 0x24, 0xb4, 0x03, 0x09, 0x90, 0xff, 0x9e, 0xe0, 0x44, 
+0x10, 0xf0, 0x80, 0x07, 0x90, 0xff, 0x9e, 0xe0, 0x44, 0x20, 0xf0, 0x53, 0x07, 0x7f, 0x80, 0x37, 
+0xe5, 0x24, 0xb4, 0x03, 0x09, 0x90, 0xff, 0x9e, 0xe0, 0x54, 0xef, 0xf0, 0x80, 0x07, 0x90, 0xff, 
+0x9e, 0xe0, 0x54, 0xdf, 0xf0, 0x43, 0x07, 0x80, 0x80, 0x1d, 0xe5, 0x24, 0xb4, 0x03, 0x09, 0x90, 
+0xff, 0x9e, 0xe0, 0x44, 0x10, 0xf0, 0x80, 0x07, 0x90, 0xff, 0x9e, 0xe0, 0x44, 0x20, 0xf0, 0x43, 
+0x07, 0x80, 0x80, 0x03, 0x53, 0x07, 0x7f, 0x78, 0x80, 0x12, 0x22, 0x3f, 0xe0, 0xfc, 0xa3, 0xe0, 
+0xfd, 0x30, 0xe0, 0x05, 0x43, 0x07, 0x20, 0x80, 0x03, 0x53, 0x07, 0xdf, 0xec, 0x30, 0xe3, 0x05, 
+0x43, 0x07, 0x40, 0x80, 0x03, 0x53, 0x07, 0xbf, 0xec, 0x30, 0xe0, 0x05, 0x43, 0x07, 0x10, 0x80, 
+0x03, 0x53, 0x07, 0xef, 0xed, 0x30, 0xe4, 0x05, 0x43, 0x07, 0x08, 0x80, 0x03, 0x53, 0x07, 0xf7, 
+0xed, 0x30, 0xe5, 0x05, 0x43, 0x07, 0x04, 0x80, 0x03, 0x53, 0x07, 0xfb, 0xed, 0x30, 0xe6, 0x05, 
+0x43, 0x07, 0x01, 0x80, 0x03, 0x53, 0x07, 0xfe, 0xed, 0x30, 0xe7, 0x05, 0x43, 0x07, 0x02, 0x80, 
+0x03, 0x53, 0x07, 0xfd, 0x78, 0x7e, 0x12, 0x22, 0x3f, 0xa3, 0xef, 0xf0, 0x12, 0x31, 0xc7, 0x7f, 
+0x00, 0x22, 0x90, 0xff, 0xfa, 0x74, 0x08, 0xf0, 0xa3, 0x74, 0x16, 0xf0, 0x90, 0xff, 0xf9, 0x74, 
+0x02, 0xf0, 0x7b, 0x01, 0x7a, 0xfa, 0x79, 0xcc, 0xe4, 0xfd, 0x12, 0x22, 0xa0, 0x90, 0xfa, 0xcc, 
+0xe4, 0x75, 0xf0, 0x03, 0x12, 0x1a, 0x6c, 0x12, 0x18, 0xe2, 0xe5, 0x23, 0x30, 0xe7, 0x02, 0xd2, 
+0x02, 0x7b, 0x00, 0x7a, 0x00, 0x79, 0x24, 0x90, 0xfa, 0xcc, 0xe0, 0xf5, 0x2d, 0xa3, 0xe0, 0xf5, 
+0x2e, 0x7d, 0x01, 0x12, 0x25, 0xd7, 0x90, 0xfa, 0xcc, 0xe4, 0xf0, 0xa3, 0x74, 0x0b, 0xf0, 0x7b, 
+0x00, 0x7a, 0x00, 0x79, 0x23, 0x75, 0x2d, 0x00, 0xf5, 0x2e, 0x7d, 0x01, 0x12, 0x25, 0xd7, 0xe5, 
+0x23, 0x24, 0x80, 0x90, 0xff, 0xf8, 0xf0, 0xe5, 0x23, 0x64, 0x07, 0x60, 0x1e, 0xe5, 0x23, 0x64, 
+0x06, 0x60, 0x18, 0xe5, 0x23, 0x64, 0x14, 0x60, 0x12, 0xe5, 0x23, 0x64, 0x41, 0x60, 0x0c, 0xe5, 
+0x23, 0x64, 0x1a, 0x70, 0x46, 0xe5, 0x24, 0x64, 0x02, 0x70, 0x40, 0xe5, 0x23, 0xb4, 0x07, 0x16, 
+0xd2, 0x94, 0xd2, 0x95, 0xd2, 0x92, 0xd2, 0x93, 0x90, 0xf9, 0x15, 0xe0, 0x44, 0x02, 0xf0, 0xa3, 
+0xe0, 0x44, 0x02, 0xf0, 0x80, 0x1e, 0xe5, 0x23, 0xb4, 0x41, 0x12, 0x90, 0xf9, 0x15, 0xe0, 0x44, 
+0x06, 0xf0, 0xa3, 0xe0, 0x44, 0x06, 0xf0, 0xd2, 0xb1, 0xd2, 0xb4, 0x80, 0x07, 0x90, 0xf9, 0x15, 
+0xe0, 0x44, 0x01, 0xf0, 0x90, 0xf9, 0x16, 0xe0, 0x44, 0x01, 0xf0, 0xe5, 0x23, 0x64, 0x42, 0x60, 
+0x05, 0xe5, 0x23, 0xb4, 0x43, 0x0c, 0x90, 0xf9, 0x15, 0xe0, 0x44, 0x80, 0xf0, 0xa3, 0xe0, 0x44, 
+0x80, 0xf0, 0x90, 0xfa, 0xcc, 0xe4, 0xf0, 0xa3, 0x74, 0x0d, 0xf0, 0x12, 0x18, 0xe2, 0x90, 0xff, 
+0xf5, 0xe5, 0x23, 0xf0, 0xe4, 0xf5, 0x35, 0xf5, 0x33, 0xf5, 0x34, 0xf5, 0x32, 0x12, 0x1d, 0x84, 
+0x12, 0x1c, 0x30, 0x12, 0x1d, 0x8b, 0x90, 0xf9, 0x67, 0x12, 0x1b, 0x43, 0x90, 0xf9, 0x6c, 0x12, 
+0x1b, 0x43, 0x90, 0xff, 0xff, 0xe4, 0xf0, 0x90, 0xff, 0x83, 0xe0, 0xe4, 0xf0, 0x90, 0xff, 0x81, 
+0x74, 0x80, 0xf0, 0xa3, 0x74, 0x84, 0xf0, 0x90, 0xff, 0x80, 0xf0, 0xe4, 0xf5, 0x23, 0xe5, 0x23, 
+0x12, 0x1c, 0xa7, 0xf5, 0x83, 0xe4, 0xf0, 0xe5, 0x23, 0x12, 0x1c, 0xb5, 0xf5, 0x83, 0xe4, 0xf0, 
+0x05, 0x23, 0xe5, 0x23, 0xb4, 0x07, 0xe7, 0x78, 0x7a, 0x76, 0xfe, 0x08, 0x76, 0xf0, 0x90, 0x31, 
+0x4d, 0xe4, 0x93, 0xff, 0x78, 0x78, 0xf6, 0xfd, 0xad, 0x07, 0x90, 0x31, 0x5a, 0xe4, 0x93, 0xff, 
+0x08, 0xf6, 0xff, 0xed, 0x54, 0x0f, 0xfd, 0x12, 0x1c, 0x97, 0x74, 0x84, 0xf0, 0xed, 0x75, 0xf0, 
+0x08, 0xa4, 0x24, 0x47, 0xf5, 0x82, 0xe4, 0x34, 0xff, 0xf5, 0x83, 0xef, 0xf0, 0xc3, 0x74, 0xf0, 
+0x9f, 0x78, 0x7b, 0xf6, 0x74, 0xfe, 0x94, 0x00, 0x18, 0x12, 0x1c, 0x28, 0xce, 0xc3, 0x13, 0xce, 
+0x13, 0xd8, 0xf9, 0xff, 0xed, 0x12, 0x1c, 0xf8, 0xef, 0xf0, 0xed, 0x12, 0x1d, 0x1e, 0xe4, 0xf5, 
+0x23, 0xe5, 0x23, 0x90, 0x31, 0x47, 0x93, 0xff, 0x78, 0x78, 0xf6, 0xfd, 0xe5, 0x23, 0x25, 0xe0, 
+0x24, 0x4e, 0xf5, 0x82, 0xe4, 0x34, 0x31, 0xf5, 0x83, 0xe4, 0x93, 0x08, 0xf6, 0xed, 0x30, 0xe7, 
+0x53, 0x18, 0xe6, 0x54, 0x0f, 0xf9, 0x12, 0x1c, 0x97, 0x12, 0x1d, 0x06, 0x24, 0x47, 0xf5, 0x82, 
+0xe4, 0x34, 0xff, 0x12, 0x1c, 0x18, 0xce, 0xc3, 0x13, 0xce, 0x13, 0xd8, 0xf9, 0xff, 0xe9, 0x12, 
+0x1c, 0xf8, 0xef, 0xf0, 0x12, 0x1c, 0x1f, 0xce, 0xc3, 0x13, 0xce, 0x13, 0xd8, 0xf9, 0x12, 0x1d, 
+0x0b, 0x24, 0x45, 0xf5, 0x82, 0xe4, 0x34, 0xff, 0xf5, 0x83, 0xef, 0xf0, 0xe9, 0x12, 0x1d, 0x1e, 
+0xe9, 0x75, 0xf0, 0x08, 0xa4, 0x24, 0x46, 0xf5, 0x82, 0xe4, 0x34, 0xff, 0xf5, 0x83, 0x74, 0x80, 
+0xf0, 0x02, 0x18, 0xb7, 0x78, 0x78, 0xe6, 0x54, 0x0f, 0xf9, 0x12, 0x1c, 0xea, 0x12, 0x1d, 0x06, 
+0x24, 0x07, 0xf5, 0x82, 0xe4, 0x34, 0xff, 0x12, 0x1c, 0x18, 0xce, 0xc3, 0x13, 0xce, 0x13, 0xd8, 
+0xf9, 0x12, 0x1d, 0x0b, 0x24, 0x01, 0xf5, 0x82, 0xe4, 0x34, 0xff, 0xf5, 0x83, 0xef, 0xf0, 0x12, 
+0x1c, 0x1f, 0xce, 0xc3, 0x13, 0xce, 0x13, 0xd8, 0xf9, 0x12, 0x1d, 0x0b, 0x24, 0x05, 0xf5, 0x82, 
+0xe4, 0x34, 0xff, 0xf5, 0x83, 0xef, 0xf0, 0xe9, 0x75, 0xf0, 0x08, 0xa4, 0x24, 0x02, 0xf5, 0x82, 
+0xe4, 0x34, 0xff, 0xf5, 0x83, 0xe4, 0xf0, 0xe9, 0x75, 0xf0, 0x08, 0xa4, 0x24, 0x06, 0xf5, 0x82, 
+0xe4, 0x34, 0xff, 0xf5, 0x83, 0xe4, 0xf0, 0x05, 0x23, 0xe5, 0x23, 0x64, 0x04, 0x60, 0x03, 0x02, 
+0x17, 0xe1, 0x90, 0x31, 0x4c, 0xe4, 0x93, 0xff, 0x78, 0x78, 0xf6, 0x12, 0x1c, 0xe8, 0xe4, 0xf0, 
+0x90, 0x31, 0x4b, 0x93, 0xff, 0xf6, 0x12, 0x1c, 0x95, 0xe4, 0xf0, 0x90, 0xff, 0xfd, 0x74, 0x05, 
+0xf0, 0x22, 0x7b, 0x00, 0x7a, 0x00, 0x79, 0x23, 0x90, 0xfa, 0xcc, 0xe4, 0x75, 0xf0, 0x01, 0x12, 
+0x1a, 0x82, 0x85, 0xf0, 0x2e, 0xf5, 0x2d, 0x7d, 0x01, 0x02, 0x25, 0xd7, 0xe7, 0x09, 0xf6, 0x08, 
+0xdf, 0xfa, 0x80, 0x46, 0xe7, 0x09, 0xf2, 0x08, 0xdf, 0xfa, 0x80, 0x3e, 0x88, 0x82, 0x8c, 0x83, 
+0xe7, 0x09, 0xf0, 0xa3, 0xdf, 0xfa, 0x80, 0x32, 0xe3, 0x09, 0xf6, 0x08, 0xdf, 0xfa, 0x80, 0x78, 
+0xe3, 0x09, 0xf2, 0x08, 0xdf, 0xfa, 0x80, 0x70, 0x88, 0x82, 0x8c, 0x83, 0xe3, 0x09, 0xf0, 0xa3, 
+0xdf, 0xfa, 0x80, 0x64, 0x89, 0x82, 0x8a, 0x83, 0xe0, 0xa3, 0xf6, 0x08, 0xdf, 0xfa, 0x80, 0x58, 
+0x89, 0x82, 0x8a, 0x83, 0xe0, 0xa3, 0xf2, 0x08, 0xdf, 0xfa, 0x80, 0x4c, 0x80, 0xd2, 0x80, 0xfa, 
+0x80, 0xc6, 0x80, 0xd4, 0x80, 0x69, 0x80, 0xf2, 0x80, 0x33, 0x80, 0x10, 0x80, 0xa6, 0x80, 0xea, 
+0x80, 0x9a, 0x80, 0xa8, 0x80, 0xda, 0x80, 0xe2, 0x80, 0xca, 0x80, 0x33, 0x89, 0x82, 0x8a, 0x83, 
+0xec, 0xfa, 0xe4, 0x93, 0xa3, 0xc8, 0xc5, 0x82, 0xc8, 0xcc, 0xc5, 0x83, 0xcc, 0xf0, 0xa3, 0xc8, 
+0xc5, 0x82, 0xc8, 0xcc, 0xc5, 0x83, 0xcc, 0xdf, 0xe9, 0xde, 0xe7, 0x80, 0x0d, 0x89, 0x82, 0x8a, 
+0x83, 0xe4, 0x93, 0xa3, 0xf6, 0x08, 0xdf, 0xf9, 0xec, 0xfa, 0xa9, 0xf0, 0xed, 0xfb, 0x22, 0x89, 
+0x82, 0x8a, 0x83, 0xec, 0xfa, 0xe0, 0xa3, 0xc8, 0xc5, 0x82, 0xc8, 0xcc, 0xc5, 0x83, 0xcc, 0xf0, 
+0xa3, 0xc8, 0xc5, 0x82, 0xc8, 0xcc, 0xc5, 0x83, 0xcc, 0xdf, 0xea, 0xde, 0xe8, 0x80, 0xdb, 0x89, 
+0x82, 0x8a, 0x83, 0xe4, 0x93, 0xa3, 0xf2, 0x08, 0xdf, 0xf9, 0x80, 0xcc, 0x88, 0xf0, 0xef, 0x60, 
+0x01, 0x0e, 0x4e, 0x60, 0xc3, 0x88, 0xf0, 0xed, 0x24, 0x02, 0xb4, 0x04, 0x00, 0x50, 0xb9, 0xf5, 
+0x82, 0xeb, 0x24, 0x02, 0xb4, 0x04, 0x00, 0x50, 0xaf, 0x23, 0x23, 0x45, 0x82, 0x23, 0x90, 0x19, 
+0x4c, 0x73, 0xbb, 0x01, 0x06, 0x89, 0x82, 0x8a, 0x83, 0xe0, 0x22, 0x50, 0x02, 0xe7, 0x22, 0xbb, 
+0xfe, 0x02, 0xe3, 0x22, 0x89, 0x82, 0x8a, 0x83, 0xe4, 0x93, 0x22, 0xbb, 0x01, 0x0c, 0xe5, 0x82, 
+0x29, 0xf5, 0x82, 0xe5, 0x83, 0x3a, 0xf5, 0x83, 0xe0, 0x22, 0x50, 0x06, 0xe9, 0x25, 0x82, 0xf8, 
+0xe6, 0x22, 0xbb, 0xfe, 0x06, 0xe9, 0x25, 0x82, 0xf8, 0xe2, 0x22, 0xe5, 0x82, 0x29, 0xf5, 0x82, 
+0xe5, 0x83, 0x3a, 0xf5, 0x83, 0xe4, 0x93, 0x22, 0xbb, 0x01, 0x06, 0x89, 0x82, 0x8a, 0x83, 0xf0, 
+0x22, 0x50, 0x02, 0xf7, 0x22, 0xbb, 0xfe, 0x01, 0xf3, 0x22, 0xf8, 0xbb, 0x01, 0x0d, 0xe5, 0x82, 
+0x29, 0xf5, 0x82, 0xe5, 0x83, 0x3a, 0xf5, 0x83, 0xe8, 0xf0, 0x22, 0x50, 0x06, 0xe9, 0x25, 0x82, 
+0xc8, 0xf6, 0x22, 0xbb, 0xfe, 0x05, 0xe9, 0x25, 0x82, 0xc8, 0xf2, 0x22, 0xc5, 0xf0, 0xf8, 0xa3, 
+0xe0, 0x28, 0xf0, 0xc5, 0xf0, 0xf8, 0xe5, 0x82, 0x15, 0x82, 0x70, 0x02, 0x15, 0x83, 0xe0, 0x38, 
+0xf0, 0x22, 0xa3, 0xf8, 0xe0, 0xc5, 0xf0, 0x25, 0xf0, 0xf0, 0xe5, 0x82, 0x15, 0x82, 0x70, 0x02, 
+0x15, 0x83, 0xe0, 0xc8, 0x38, 0xf0, 0xe8, 0x22, 0xbb, 0x01, 0x10, 0xe5, 0x82, 0x29, 0xf5, 0x82, 
+0xe5, 0x83, 0x3a, 0xf5, 0x83, 0xe0, 0xf5, 0xf0, 0xa3, 0xe0, 0x22, 0x50, 0x09, 0xe9, 0x25, 0x82, 
+0xf8, 0x86, 0xf0, 0x08, 0xe6, 0x22, 0xbb, 0xfe, 0x0a, 0xe9, 0x25, 0x82, 0xf8, 0xe2, 0xf5, 0xf0, 
+0x08, 0xe2, 0x22, 0xe5, 0x83, 0x2a, 0xf5, 0x83, 0xe9, 0x93, 0xf5, 0xf0, 0xa3, 0xe9, 0x93, 0x22, 
+0xbb, 0x01, 0x0a, 0x89, 0x82, 0x8a, 0x83, 0xf0, 0xe5, 0xf0, 0xa3, 0xf0, 0x22, 0x50, 0x06, 0xf7, 
+0x09, 0xa7, 0xf0, 0x19, 0x22, 0xbb, 0xfe, 0x06, 0xf3, 0xe5, 0xf0, 0x09, 0xf3, 0x19, 0x22, 0xf8, 
+0xbb, 0x01, 0x11, 0xe5, 0x82, 0x29, 0xf5, 0x82, 0xe5, 0x83, 0x3a, 0xf5, 0x83, 0xe8, 0xf0, 0xe5, 
+0xf0, 0xa3, 0xf0, 0x22, 0x50, 0x09, 0xe9, 0x25, 0x82, 0xc8, 0xf6, 0x08, 0xa6, 0xf0, 0x22, 0xbb, 
+0xfe, 0x09, 0xe9, 0x25, 0x82, 0xc8, 0xf2, 0xe5, 0xf0, 0x08, 0xf2, 0x22, 0xa4, 0x25, 0x82, 0xf5, 
+0x82, 0xe5, 0xf0, 0x35, 0x83, 0xf5, 0x83, 0x22, 0xe6, 0xfb, 0x08, 0xe6, 0xfa, 0x08, 0xe6, 0xf9, 
+0x22, 0xeb, 0xf6, 0x08, 0xea, 0xf6, 0x08, 0xe9, 0xf6, 0x22, 0xe0, 0xfb, 0xa3, 0xe0, 0xfa, 0xa3, 
+0xe0, 0xf9, 0x22, 0xeb, 0xf0, 0xa3, 0xea, 0xf0, 0xa3, 0xe9, 0xf0, 0x22, 0xd0, 0x83, 0xd0, 0x82, 
+0xf8, 0xe4, 0x93, 0x70, 0x12, 0x74, 0x01, 0x93, 0x70, 0x0d, 0xa3, 0xa3, 0x93, 0xf8, 0x74, 0x01, 
+0x93, 0xf5, 0x82, 0x88, 0x83, 0xe4, 0x73, 0x74, 0x02, 0x93, 0x68, 0x60, 0xef, 0xa3, 0xa3, 0xa3, 
+0x80, 0xdf, 0xab, 0x36, 0xaa, 0x37, 0xa9, 0x38, 0xe5, 0x4c, 0x12, 0x1a, 0x38, 0x74, 0x01, 0x25, 
+0x38, 0xf5, 0x38, 0xe4, 0x35, 0x37, 0xf5, 0x37, 0xab, 0x36, 0xfa, 0xa9, 0x38, 0x74, 0x11, 0x12, 
+0x1a, 0x38, 0x74, 0x01, 0x25, 0x38, 0xf5, 0x38, 0xe4, 0x35, 0x37, 0xf5, 0x37, 0x90, 0xff, 0x06, 
+0xe0, 0xab, 0x36, 0xaa, 0x37, 0xa9, 0x38, 0x12, 0x1a, 0x38, 0x74, 0x01, 0x25, 0x38, 0xf5, 0x38, 
+0xe4, 0x35, 0x37, 0xf5, 0x37, 0xab, 0x36, 0xfa, 0xa9, 0x38, 0xe4, 0x12, 0x1a, 0x38, 0x04, 0x25, 
+0x38, 0xf5, 0x38, 0xe4, 0x35, 0x37, 0xf5, 0x37, 0xab, 0x36, 0xfa, 0xa9, 0x38, 0xe4, 0x12, 0x1a, 
+0x38, 0x04, 0x25, 0x38, 0xf5, 0x38, 0xe4, 0x35, 0x37, 0xf5, 0x37, 0x90, 0xff, 0x04, 0xe0, 0xab, 
+0x36, 0xaa, 0x37, 0xa9, 0x38, 0x12, 0x1a, 0x38, 0x74, 0x01, 0x25, 0x38, 0xf5, 0x38, 0xe4, 0x35, 
+0x37, 0xf5, 0x37, 0x90, 0xff, 0x05, 0xe0, 0xab, 0x36, 0xaa, 0x37, 0xa9, 0x38, 0x12, 0x1a, 0x38, 
+0x74, 0x01, 0x25, 0x38, 0xf5, 0x38, 0xe4, 0x35, 0x37, 0xf5, 0x37, 0x22, 0xf5, 0x83, 0xe0, 0x54, 
+0x08, 0xab, 0x36, 0xaa, 0x37, 0xa9, 0x38, 0x22, 0xf5, 0x83, 0xef, 0xf0, 0xfd, 0x7c, 0x00, 0xc3, 
+0x78, 0x7b, 0xe6, 0x9d, 0xf6, 0x18, 0xe6, 0x9c, 0xf6, 0xe6, 0xfe, 0x08, 0xe6, 0x78, 0x03, 0x22, 
+0x75, 0x36, 0x01, 0x75, 0x37, 0xf9, 0x75, 0x38, 0x6f, 0x22, 0xe0, 0x44, 0x04, 0xf0, 0x74, 0x12, 
+0x2f, 0xf5, 0x82, 0xe4, 0x34, 0xf9, 0xf5, 0x83, 0xe0, 0x22, 0x90, 0xfa, 0xb9, 0xe0, 0xff, 0x7e, 
+0x00, 0xc3, 0x90, 0xfa, 0xbd, 0xe0, 0x9f, 0xf0, 0x90, 0xfa, 0xbc, 0xe0, 0x9e, 0xf0, 0x90, 0xfa, 
+0xb4, 0xee, 0x8f, 0xf0, 0x12, 0x1a, 0x6c, 0xef, 0x25, 0x4f, 0xf5, 0x4f, 0xee, 0x35, 0x4e, 0xf5, 
+0x4e, 0x22, 0x7b, 0x01, 0x7a, 0xfa, 0x79, 0xb1, 0x90, 0xfa, 0xb4, 0xe0, 0xf5, 0x2d, 0xa3, 0xe0, 
+0xf5, 0x2e, 0x22, 0x78, 0x7c, 0xe6, 0xfe, 0x08, 0xe6, 0x8e, 0x83, 0x24, 0x04, 0xf5, 0x82, 0xe4, 
+0x35, 0x83, 0xf5, 0x83, 0x22, 0x54, 0x0f, 0x75, 0xf0, 0x08, 0xa4, 0x24, 0x40, 0xf5, 0x82, 0xe4, 
+0x34, 0xff, 0xf5, 0x83, 0x22, 0xe5, 0x4d, 0x75, 0xf0, 0x08, 0xa4, 0x24, 0x48, 0xf5, 0x82, 0xe4, 
+0x34, 0xff, 0x22, 0xe5, 0x4d, 0x75, 0xf0, 0x08, 0xa4, 0x24, 0x08, 0xf5, 0x82, 0xe4, 0x34, 0xff, 
+0x22, 0x90, 0xfa, 0xb6, 0xe0, 0xff, 0x24, 0xfc, 0x22, 0x90, 0xff, 0x00, 0xe0, 0x54, 0x1f, 0x22, 
+0x90, 0xfa, 0xbb, 0xe0, 0x90, 0xfa, 0xb7, 0xf0, 0x22, 0x75, 0x33, 0x00, 0x8f, 0x34, 0x90, 0xf9, 
+0x6c, 0x12, 0x1b, 0x3a, 0x90, 0x00, 0x02, 0x22, 0x54, 0x0f, 0x75, 0xf0, 0x08, 0xa4, 0x24, 0x00, 
+0xf5, 0x82, 0xe4, 0x34, 0xff, 0xf5, 0x83, 0x22, 0x75, 0xf0, 0x08, 0xa4, 0x24, 0x41, 0xf5, 0x82, 
+0xe4, 0x34, 0xff, 0xf5, 0x83, 0x22, 0x74, 0x80, 0xf0, 0x08, 0xe6, 0xff, 0xe9, 0x75, 0xf0, 0x08, 
+0xa4, 0x22, 0x74, 0xaf, 0x25, 0x22, 0xf5, 0x82, 0xe4, 0x34, 0xfa, 0xf5, 0x83, 0x22, 0x75, 0xf0, 
+0x08, 0xa4, 0x24, 0x42, 0xf5, 0x82, 0xe4, 0x34, 0xff, 0xf5, 0x83, 0x74, 0x80, 0xf0, 0x22, 0x90, 
+0xff, 0x82, 0xe0, 0x44, 0x08, 0xf0, 0x22, 0x90, 0xff, 0xfe, 0xe0, 0x44, 0x03, 0xf0, 0x90, 0xff, 
+0xfc, 0xe0, 0x54, 0xfd, 0xf0, 0x22, 0x78, 0x67, 0xe6, 0x54, 0xfd, 0xf6, 0x90, 0xff, 0xfd, 0x74, 
+0x65, 0xf0, 0x22, 0x12, 0x1b, 0x1c, 0xe0, 0xfe, 0xa3, 0xe0, 0xff, 0x4e, 0x22, 0x7b, 0x01, 0x7a, 
+0xfa, 0x79, 0xb4, 0x22, 0x90, 0xff, 0x80, 0xe0, 0x44, 0x08, 0xf0, 0x22, 0x90, 0xff, 0x83, 0xe0, 
+0x54, 0x7f, 0xf0, 0x22, 0xe0, 0xff, 0x90, 0xf9, 0x67, 0x02, 0x1b, 0x3a, 0x90, 0xff, 0xa4, 0xe0, 
+0x44, 0x02, 0xf0, 0x22, 0x75, 0x39, 0x01, 0x75, 0x3a, 0x09, 0x22, 0x7b, 0x01, 0x7a, 0xf9, 0x79, 
+0x6f, 0x22, 0xd3, 0xe5, 0x3c, 0x94, 0x08, 0xe5, 0x3b, 0x94, 0x01, 0x22, 0x90, 0xfa, 0xbb, 0xe0, 
+0xff, 0x90, 0xfa, 0xb7, 0xf0, 0x22, 0x90, 0xff, 0xa4, 0xe0, 0x54, 0xef, 0x22, 0x90, 0xff, 0xb4, 
+0xe0, 0x54, 0xef, 0x22, 0x12, 0x10, 0x03, 0x78, 0x88, 0xef, 0xf6, 0x12, 0x2a, 0x06, 0x12, 0x22, 
+0x4a, 0x8e, 0x83, 0x24, 0x09, 0x12, 0x21, 0xf3, 0xe0, 0xfd, 0x12, 0x22, 0x2d, 0x90, 0x00, 0x0a, 
+0x12, 0x22, 0x52, 0x24, 0x0a, 0x12, 0x21, 0xf3, 0xe0, 0x90, 0x00, 0x0b, 0x12, 0x1a, 0x4a, 0x12, 
+0x22, 0x4a, 0xf5, 0x82, 0x8e, 0x83, 0xa3, 0xa3, 0xa3, 0xe0, 0xf5, 0x53, 0x12, 0x22, 0x56, 0x24, 
+0x04, 0x12, 0x21, 0xf3, 0xe0, 0xf5, 0x54, 0x8f, 0x82, 0x8e, 0x83, 0xa3, 0xa3, 0xe0, 0xf5, 0x55, 
+0xe5, 0x53, 0xc4, 0x13, 0x13, 0x13, 0x54, 0x01, 0x78, 0x88, 0xf6, 0xd3, 0x94, 0x00, 0x40, 0x06, 
+0xe5, 0x54, 0x30, 0xe1, 0x01, 0x06, 0x78, 0x88, 0xe6, 0x12, 0x22, 0x2c, 0x90, 0x00, 0x0c, 0xef, 
+0x12, 0x1a, 0x4a, 0x78, 0x80, 0x12, 0x22, 0x09, 0xa3, 0xa3, 0xe0, 0xfe, 0xa3, 0xe0, 0xff, 0x53, 
+0x07, 0x0c, 0x53, 0x06, 0xe6, 0xe5, 0x53, 0x30, 0xe5, 0x03, 0x43, 0x07, 0x01, 0xe5, 0x54, 0x20, 
+0xe5, 0x0e, 0xe5, 0x53, 0x54, 0x7f, 0x70, 0x08, 0xe5, 0x53, 0x20, 0xe7, 0x03, 0x43, 0x07, 0x02, 
+0xe5, 0x53, 0x30, 0xe3, 0x03, 0x43, 0x07, 0x10, 0xe5, 0x53, 0x30, 0xe2, 0x03, 0x43, 0x07, 0x20, 
+0xe5, 0x53, 0x54, 0x03, 0x60, 0x03, 0x43, 0x07, 0x40, 0xe5, 0x53, 0x30, 0xe1, 0x03, 0x43, 0x07, 
+0x80, 0xe5, 0x53, 0x30, 0xe4, 0x03, 0x43, 0x06, 0x01, 0xe5, 0x53, 0x30, 0xe6, 0x03, 0x43, 0x06, 
+0x08, 0xe5, 0x54, 0x20, 0xe4, 0x0e, 0xe5, 0x53, 0x54, 0x7f, 0x70, 0x08, 0xe5, 0x53, 0x20, 0xe7, 
+0x03, 0x43, 0x06, 0x10, 0x53, 0x07, 0xfb, 0x53, 0x06, 0x79, 0x90, 0x00, 0x05, 0xee, 0x8f, 0xf0, 
+0x12, 0x1a, 0xef, 0xe5, 0x55, 0x30, 0xe3, 0x12, 0x54, 0x30, 0xff, 0xc4, 0x54, 0x0f, 0x12, 0x22, 
+0x2c, 0x90, 0x00, 0x08, 0xef, 0x12, 0x1a, 0x4a, 0x80, 0x0a, 0x12, 0x22, 0x2d, 0x90, 0x00, 0x08, 
+0xe4, 0x12, 0x1a, 0x4a, 0xe5, 0x55, 0x54, 0x03, 0x12, 0x22, 0x2c, 0x90, 0x00, 0x07, 0xef, 0x12, 
+0x1a, 0x4a, 0xe5, 0x55, 0x54, 0x04, 0xff, 0xc3, 0x13, 0x90, 0x00, 0x09, 0x12, 0x1a, 0x4a, 0x90, 
+0x00, 0x07, 0x12, 0x1a, 0x0b, 0x70, 0x13, 0x12, 0x22, 0x2d, 0xe9, 0x24, 0x09, 0xf9, 0xe4, 0x3a, 
+0xfa, 0x12, 0x19, 0xf2, 0xff, 0xc3, 0x13, 0x12, 0x1a, 0x38, 0x12, 0x22, 0x78, 0x24, 0x08, 0x12, 
+0x21, 0xf3, 0xe0, 0xfe, 0x8d, 0x82, 0x8c, 0x83, 0xe5, 0x82, 0x24, 0x07, 0x12, 0x21, 0xf3, 0xe0, 
+0xfd, 0xee, 0xed, 0x12, 0x22, 0x2c, 0x90, 0x00, 0x03, 0xee, 0x8f, 0xf0, 0x12, 0x1a, 0xef, 0x12, 
+0x31, 0xc7, 0x7d, 0x0a, 0xe4, 0xff, 0x12, 0x2f, 0x18, 0x02, 0x10, 0x86, 0x90, 0xfa, 0xe3, 0xe0, 
+0xb4, 0x03, 0x06, 0x7e, 0x00, 0x7f, 0x40, 0x80, 0x04, 0x7e, 0x00, 0x7f, 0x08, 0x90, 0xfa, 0xd7, 
+0xee, 0xf0, 0xa3, 0xef, 0xf0, 0x90, 0x00, 0x05, 0x12, 0x1a, 0x0b, 0xff, 0x7e, 0x00, 0x90, 0xfa, 
+0xd3, 0xee, 0xf0, 0xa3, 0xef, 0xf0, 0x70, 0x03, 0x7f, 0x08, 0x22, 0x90, 0x00, 0x08, 0x12, 0x1a, 
+0x98, 0xff, 0x90, 0xfa, 0xd5, 0xe5, 0xf0, 0xf0, 0xa3, 0xef, 0xf0, 0xae, 0x02, 0xaf, 0x01, 0x8e, 
+0x50, 0x8f, 0x51, 0x74, 0x0a, 0x25, 0x51, 0xf5, 0x51, 0xe4, 0x35, 0x50, 0xf5, 0x50, 0x90, 0xfa, 
+0xd8, 0xe0, 0xff, 0x14, 0xfe, 0x90, 0xfa, 0xd6, 0xe0, 0x5e, 0xfe, 0xc3, 0xef, 0x9e, 0xff, 0x90, 
+0xfa, 0xda, 0xf0, 0xc3, 0x90, 0xfa, 0xd4, 0xe0, 0x9f, 0x90, 0xfa, 0xd3, 0xe0, 0x94, 0x00, 0x50, 
+0x06, 0xa3, 0xe0, 0x90, 0xfa, 0xda, 0xf0, 0x12, 0x1f, 0xfb, 0x60, 0x03, 0xe0, 0xff, 0x22, 0x12, 
+0x2d, 0x5a, 0x90, 0xfa, 0xd3, 0xe0, 0xfe, 0xa3, 0xe0, 0xff, 0x4e, 0x60, 0x2b, 0x90, 0xfa, 0xd7, 
+0xe0, 0xfc, 0xa3, 0xe0, 0xfd, 0xd3, 0xef, 0x9d, 0xee, 0x9c, 0x40, 0x07, 0xe0, 0x90, 0xfa, 0xda, 
+0xf0, 0x80, 0x08, 0x90, 0xfa, 0xd4, 0xe0, 0x90, 0xfa, 0xda, 0xf0, 0x12, 0x1f, 0xfb, 0x60, 0x03, 
+0xe0, 0xff, 0x22, 0x12, 0x2d, 0x5a, 0x80, 0xca, 0x7b, 0x00, 0x7a, 0x00, 0x79, 0x52, 0xe4, 0xf5, 
+0x2d, 0xf5, 0x2e, 0x7d, 0x01, 0x12, 0x25, 0xd7, 0x7f, 0x00, 0x22, 0xaa, 0x50, 0xa9, 0x51, 0x7b, 
+0x01, 0x90, 0xfa, 0xd5, 0xe0, 0xfc, 0xa3, 0xe0, 0xfd, 0x90, 0xfa, 0xda, 0xe0, 0xf5, 0x4a, 0x12, 
+0x28, 0x9f, 0x90, 0xfa, 0xd9, 0xef, 0xf0, 0x22, 0xef, 0x24, 0xae, 0x60, 0x52, 0x24, 0xfe, 0x60, 
+0x2e, 0x24, 0xfe, 0x70, 0x03, 0x02, 0x20, 0xbb, 0x24, 0x06, 0x60, 0x03, 0x02, 0x21, 0x03, 0x78, 
+0x71, 0xe6, 0x54, 0xfb, 0xf6, 0x90, 0xff, 0xa5, 0xe0, 0xf5, 0x22, 0x44, 0x0f, 0xf0, 0x74, 0x33, 
+0x90, 0xfa, 0x91, 0xf0, 0xe5, 0x22, 0xa3, 0xf0, 0x90, 0xfa, 0xaf, 0x74, 0x01, 0xf0, 0x22, 0x78, 
+0x72, 0xe6, 0x54, 0xfb, 0xf6, 0x90, 0xff, 0xb5, 0xe0, 0xf5, 0x22, 0x44, 0x0f, 0xf0, 0x74, 0x43, 
+0x90, 0xfa, 0x93, 0xf0, 0xe5, 0x22, 0xa3, 0xf0, 0x90, 0xfa, 0xb0, 0x74, 0x01, 0xf0, 0x22, 0x90, 
+0xfa, 0x9d, 0xe0, 0xa3, 0x20, 0xe5, 0x03, 0x02, 0x21, 0x03, 0x90, 0xff, 0xa6, 0xe0, 0x90, 0xfa, 
+0xca, 0xf0, 0xa3, 0xf0, 0x90, 0xfa, 0xca, 0xe0, 0xff, 0x54, 0x0f, 0xfe, 0x60, 0x10, 0x90, 0xff, 
+0xa6, 0x12, 0x22, 0x5d, 0x90, 0xff, 0xa6, 0xe0, 0x90, 0xfa, 0xca, 0xf0, 0x80, 0xe6, 0x90, 0xfa, 
+0xcb, 0xe0, 0xff, 0x74, 0x34, 0xfe, 0x12, 0x2c, 0xb4, 0xef, 0x70, 0x57, 0x90, 0xfa, 0xcb, 0xe0, 
+0xff, 0x74, 0x34, 0x90, 0xfa, 0x95, 0xf0, 0xef, 0xa3, 0xf0, 0x22, 0x90, 0xfa, 0xa7, 0xe0, 0xa3, 
+0x30, 0xe5, 0x40, 0x90, 0xff, 0xb6, 0xe0, 0x90, 0xfa, 0xca, 0xf0, 0xa3, 0xf0, 0x90, 0xfa, 0xca, 
+0xe0, 0xff, 0x54, 0x0f, 0xfe, 0x60, 0x10, 0x90, 0xff, 0xb6, 0x12, 0x22, 0x5d, 0x90, 0xff, 0xb6, 
+0xe0, 0x90, 0xfa, 0xca, 0xf0, 0x80, 0xe6, 0x90, 0xfa, 0xcb, 0xe0, 0xff, 0x74, 0x44, 0xfe, 0x12, 
+0x2c, 0xb4, 0xef, 0x70, 0x0e, 0x90, 0xfa, 0xcb, 0xe0, 0xff, 0x74, 0x44, 0x90, 0xfa, 0x97, 0xf0, 
+0xef, 0xa3, 0xf0, 0x22, 0xc0, 0xe0, 0xc0, 0xf0, 0xc0, 0x83, 0xc0, 0x82, 0xc0, 0xd0, 0x75, 0xd0, 
+0x00, 0xc0, 0x00, 0xc0, 0x01, 0xc0, 0x02, 0xc0, 0x03, 0xc0, 0x04, 0xc0, 0x05, 0xc0, 0x06, 0xc0, 
+0x07, 0x90, 0xff, 0x92, 0xe0, 0xff, 0x90, 0xfa, 0xc9, 0xf0, 0x90, 0xff, 0x92, 0xe4, 0xf0, 0xef, 
+0x12, 0x1b, 0x4c, 0x21, 0xbb, 0x26, 0x21, 0xbb, 0x2e, 0x21, 0x5e, 0x30, 0x21, 0x5e, 0x32, 0x21, 
+0x6c, 0x38, 0x21, 0x7e, 0x3a, 0x21, 0xb0, 0x3e, 0x21, 0x9b, 0x44, 0x21, 0x90, 0x46, 0x21, 0xa6, 
+0x50, 0x21, 0xa6, 0x52, 0x21, 0xa6, 0x54, 0x21, 0xa6, 0x56, 0x00, 0x00, 0x21, 0xc0, 0x90, 0xfa, 
+0xc9, 0xe0, 0xfd, 0x7c, 0x00, 0x7f, 0x01, 0x12, 0x11, 0x16, 0x80, 0x62, 0x7c, 0x00, 0x7d, 0x01, 
+0x7f, 0x03, 0x12, 0x11, 0x16, 0x90, 0xff, 0xfe, 0xe0, 0x44, 0x20, 0xf0, 0x80, 0x50, 0x7c, 0x00, 
+0x7d, 0x01, 0x7f, 0x02, 0x12, 0x11, 0x16, 0x90, 0xff, 0xfe, 0xe0, 0x44, 0x40, 0xf0, 0x80, 0x3e, 
+0x7c, 0x00, 0x7d, 0x01, 0x7f, 0x05, 0x12, 0x11, 0x16, 0x80, 0x33, 0x7c, 0x00, 0x7d, 0x01, 0x7f, 
+0x06, 0x12, 0x11, 0x16, 0x80, 0x28, 0x90, 0xfa, 0xc9, 0xe0, 0xff, 0x12, 0x20, 0x18, 0x80, 0x1e, 
+0x7c, 0x00, 0x7d, 0x01, 0x7f, 0x04, 0x12, 0x11, 0x16, 0x80, 0x13, 0x12, 0x27, 0x8d, 0x80, 0x0e, 
+0x90, 0xfa, 0xc9, 0xe0, 0x24, 0x00, 0xff, 0xe4, 0x34, 0xff, 0xfe, 0x12, 0x2c, 0xb4, 0xd0, 0x07, 
+0xd0, 0x06, 0xd0, 0x05, 0xd0, 0x04, 0xd0, 0x03, 0xd0, 0x02, 0xd0, 0x01, 0xd0, 0x00, 0xd0, 0xd0, 
+0xd0, 0x82, 0xd0, 0x83, 0xd0, 0xf0, 0xd0, 0xe0, 0x32, 0x78, 0x7c, 0xe6, 0xfe, 0x08, 0xe6, 0x24, 
+0x04, 0x8e, 0x83, 0xf5, 0x82, 0xe4, 0x35, 0x83, 0xf5, 0x83, 0x22, 0x74, 0x12, 0x25, 0x24, 0xf5, 
+0x82, 0xe4, 0x34, 0xf9, 0xf5, 0x83, 0x22, 0x78, 0x7c, 0xe6, 0xfe, 0x08, 0xe6, 0xf5, 0x82, 0x8e, 
+0x83, 0x22, 0x78, 0x80, 0xe6, 0xfe, 0x08, 0xe6, 0xaa, 0x06, 0xf8, 0xac, 0x02, 0x7d, 0x01, 0x7b, 
+0xff, 0x7a, 0x31, 0x79, 0x99, 0x7e, 0x00, 0x7f, 0x0a, 0x02, 0x19, 0xcc, 0xff, 0x90, 0xf9, 0x6c, 
+0x02, 0x1b, 0x3a, 0x90, 0xf9, 0x67, 0x12, 0x1b, 0x3a, 0x90, 0x00, 0x04, 0x02, 0x1a, 0x0b, 0xe6, 
+0xfc, 0x08, 0xe6, 0xf5, 0x82, 0x8c, 0x83, 0xa3, 0xa3, 0x22, 0x78, 0x7e, 0xe6, 0xfe, 0x08, 0xe6, 
+0xff, 0x22, 0xed, 0x12, 0x1a, 0x4a, 0x8f, 0x82, 0x8e, 0x83, 0xe5, 0x82, 0x22, 0xef, 0xf0, 0x90, 
+0xfa, 0xcb, 0xe0, 0x54, 0x0f, 0x4e, 0xfe, 0xf0, 0xef, 0x54, 0xf0, 0x4e, 0xf0, 0x22, 0x08, 0xe6, 
+0xfc, 0x08, 0xe6, 0x8c, 0x83, 0x24, 0x09, 0x22, 0x78, 0x7e, 0xe6, 0xfc, 0x08, 0xe6, 0xfd, 0x8c, 
+0x83, 0x22, 0xa6, 0x07, 0xe6, 0x24, 0x6e, 0xf8, 0xe6, 0x22, 0x78, 0x7e, 0xe6, 0xfa, 0x08, 0xe6, 
+0xfb, 0x22, 0x26, 0xf6, 0x18, 0xee, 0x36, 0xf6, 0x22, 0x8b, 0x82, 0x8a, 0x83, 0xe5, 0x82, 0x22, 
+0x8b, 0x25, 0x8a, 0x26, 0x89, 0x27, 0x8d, 0x28, 0x90, 0xfa, 0xcf, 0xe4, 0xf0, 0xa3, 0x74, 0x02, 
+0xf0, 0x7b, 0x01, 0x7a, 0xfa, 0x79, 0xce, 0x90, 0xfa, 0xcf, 0xe0, 0xf5, 0x2d, 0xa3, 0xe0, 0xf5, 
+0x2e, 0x7d, 0x01, 0x12, 0x25, 0xd7, 0x90, 0xfa, 0xce, 0xe0, 0x65, 0x28, 0x60, 0x46, 0xa3, 0xe0, 
+0xff, 0xa3, 0xe0, 0xa3, 0xcf, 0xf0, 0xa3, 0xef, 0xf0, 0x12, 0x23, 0x2f, 0x90, 0xfa, 0xce, 0xe0, 
+0xff, 0x90, 0xfa, 0xd1, 0xe4, 0x8f, 0xf0, 0x12, 0x1a, 0x6c, 0x12, 0x23, 0x2f, 0x90, 0xfa, 0xd1, 
+0xe0, 0xff, 0xa3, 0xe0, 0x90, 0xfa, 0xcf, 0xcf, 0xf0, 0xa3, 0xef, 0xf0, 0x90, 0xfa, 0xce, 0xe0, 
+0xa3, 0x75, 0xf0, 0x00, 0x12, 0x1a, 0x6c, 0x90, 0xfa, 0xcf, 0xe4, 0x75, 0xf0, 0x04, 0x12, 0x1a, 
+0x6c, 0x02, 0x22, 0xb1, 0x90, 0xfa, 0xd0, 0xe0, 0x24, 0x01, 0xff, 0x90, 0xfa, 0xcf, 0xe0, 0x34, 
+0x00, 0xab, 0x25, 0xaa, 0x26, 0xa9, 0x27, 0x8f, 0xf0, 0x12, 0x1a, 0xd0, 0x7f, 0x00, 0x22, 0x7b, 
+0x01, 0x7a, 0xfa, 0x79, 0xce, 0x90, 0xfa, 0xcf, 0xe4, 0x75, 0xf0, 0x01, 0x12, 0x1a, 0x6c, 0x85, 
+0xf0, 0x2e, 0xf5, 0x2d, 0x7d, 0x01, 0x02, 0x25, 0xd7, 0x8f, 0x62, 0x12, 0x2a, 0x06, 0x12, 0x22, 
+0x4a, 0x8e, 0x83, 0x24, 0x0b, 0x12, 0x21, 0xf3, 0xe0, 0x54, 0xfb, 0xf0, 0x44, 0x02, 0xf0, 0x08, 
+0x12, 0x22, 0x3f, 0xe0, 0xa3, 0x30, 0xe5, 0x0c, 0x12, 0x22, 0x56, 0x24, 0x0b, 0x12, 0x21, 0xf3, 
+0xe0, 0x44, 0x01, 0xf0, 0x78, 0x7c, 0xe6, 0xfe, 0x08, 0xe6, 0xff, 0xf5, 0x82, 0x8e, 0x83, 0xe0, 
+0x54, 0xb8, 0xfd, 0xf0, 0xe5, 0x62, 0x24, 0xfe, 0x44, 0x20, 0xfc, 0x4d, 0xf0, 0xe5, 0x82, 0x24, 
+0x04, 0x12, 0x21, 0xf3, 0xe0, 0x54, 0xb8, 0xf0, 0x4c, 0xf0, 0x8f, 0x82, 0x8e, 0x83, 0xa3, 0x74, 
+0x03, 0xf0, 0x18, 0xe6, 0xfe, 0x08, 0xe6, 0xff, 0x8e, 0x83, 0x24, 0x05, 0x12, 0x21, 0xf3, 0xc0, 
+0x83, 0xc0, 0x82, 0xe0, 0xfd, 0x74, 0x96, 0x25, 0x62, 0xf5, 0x82, 0xe4, 0x34, 0xfa, 0xf5, 0x83, 
+0xe0, 0x54, 0xfc, 0x44, 0x03, 0xfc, 0xed, 0x4c, 0xd0, 0x82, 0xd0, 0x83, 0xf0, 0x8f, 0x82, 0x8e, 
+0x83, 0xe0, 0x44, 0x80, 0xf0, 0xe5, 0x82, 0x24, 0x04, 0x12, 0x21, 0xf3, 0xe0, 0x44, 0x80, 0xf0, 
+0x12, 0x31, 0xc7, 0x74, 0x6e, 0x25, 0x62, 0xf8, 0x74, 0x04, 0x46, 0xf6, 0x7f, 0x00, 0x22, 0x12, 
+0x10, 0x03, 0x7f, 0x02, 0x12, 0x12, 0x19, 0x78, 0x67, 0xe6, 0x44, 0x02, 0xf6, 0xd2, 0xb0, 0xd2, 
+0xb1, 0x90, 0xf9, 0x15, 0xe0, 0x30, 0xe7, 0x07, 0x90, 0xff, 0x9e, 0xe4, 0xf0, 0x80, 0x36, 0xd2, 
+0xb3, 0x90, 0xff, 0xa4, 0xe0, 0x90, 0xfa, 0x7b, 0xf0, 0x90, 0xff, 0xb4, 0xe0, 0x90, 0xfa, 0x7c, 
+0xf0, 0x90, 0xff, 0xa2, 0xe0, 0x90, 0xfa, 0x79, 0xf0, 0x90, 0xff, 0xb2, 0xe0, 0x90, 0xfa, 0x7a, 
+0xf0, 0x90, 0xff, 0xa4, 0x74, 0x30, 0xf0, 0x90, 0xff, 0xb4, 0xf0, 0x90, 0xff, 0xa2, 0x74, 0x40, 
+0xf0, 0x90, 0xff, 0xb2, 0xf0, 0x90, 0xfa, 0xe4, 0xe5, 0xa8, 0xf0, 0x75, 0xa8, 0x81, 0x90, 0xff, 
+0x92, 0xe0, 0x60, 0x04, 0xe4, 0xf0, 0x80, 0xf6, 0x90, 0xff, 0xfd, 0x74, 0x3a, 0xf0, 0x43, 0x87, 
+0x01, 0x00, 0x00, 0x00, 0x90, 0xfa, 0x7b, 0xe0, 0x90, 0xff, 0xa4, 0xf0, 0x90, 0xfa, 0x7c, 0xe0, 
+0x90, 0xff, 0xb4, 0xf0, 0x90, 0xfa, 0x79, 0xe0, 0x90, 0xff, 0xa2, 0xf0, 0x90, 0xfa, 0x7a, 0xe0, 
+0x90, 0xff, 0xb2, 0xf0, 0x90, 0xf9, 0x17, 0xe0, 0x60, 0x02, 0xc2, 0xb3, 0x90, 0xfa, 0xe4, 0xe0, 
+0xf5, 0xa8, 0x02, 0x10, 0x86, 0x8b, 0x5c, 0x8a, 0x5d, 0x89, 0x5e, 0x12, 0x2d, 0x3c, 0x90, 0xfa, 
+0xc0, 0x12, 0x1b, 0x43, 0xaa, 0x5d, 0xa9, 0x5e, 0x90, 0xfa, 0xc3, 0x12, 0x1b, 0x43, 0x90, 0xfa, 
+0xc4, 0xe4, 0x75, 0xf0, 0x0a, 0x12, 0x1a, 0x6c, 0x90, 0xfa, 0xc3, 0x12, 0x1b, 0x3a, 0xe9, 0x24, 
+0x01, 0xf9, 0xe4, 0x3a, 0xfa, 0x90, 0xfa, 0xc6, 0x12, 0x1b, 0x43, 0xab, 0x5c, 0xaa, 0x5d, 0xa9, 
+0x5e, 0x12, 0x2d, 0x48, 0xe0, 0xff, 0xc3, 0x13, 0xf0, 0xe4, 0x78, 0x82, 0xf6, 0x90, 0xfa, 0xbe, 
+0xe0, 0xff, 0x78, 0x82, 0xe6, 0xc3, 0x9f, 0x50, 0x4a, 0x90, 0xfa, 0xc0, 0x12, 0x2d, 0x1d, 0xff, 
+0x78, 0x83, 0xf6, 0x90, 0xfa, 0xc3, 0x12, 0x2d, 0x1d, 0xfe, 0xf4, 0x5f, 0xff, 0x78, 0x83, 0xf6, 
+0x12, 0x2d, 0x1a, 0x5e, 0x4f, 0xff, 0x78, 0x83, 0xf6, 0x12, 0x2d, 0x23, 0x75, 0xf0, 0x02, 0x12, 
+0x1a, 0x6c, 0x90, 0xfa, 0xc4, 0xe4, 0x75, 0xf0, 0x02, 0x12, 0x1a, 0x6c, 0xab, 0x5c, 0xaa, 0x5d, 
+0xa9, 0x5e, 0x90, 0x00, 0x04, 0x12, 0x1a, 0x0b, 0x30, 0xe4, 0x03, 0x12, 0x2d, 0x32, 0x78, 0x82, 
+0x06, 0x80, 0xaa, 0xe4, 0x90, 0xfa, 0xbf, 0xf0, 0x22, 0x8b, 0x56, 0x8a, 0x57, 0x89, 0x58, 0x90, 
+0xfa, 0xbf, 0x74, 0x06, 0xf0, 0xe4, 0x90, 0xfa, 0xbe, 0xf0, 0x12, 0x19, 0xf2, 0x24, 0x6e, 0x60, 
+0x26, 0x14, 0x70, 0x70, 0x12, 0x2d, 0x09, 0x60, 0x09, 0x24, 0x30, 0x70, 0x12, 0x12, 0x24, 0x95, 
+0x80, 0x62, 0x12, 0x2d, 0x53, 0x12, 0x1f, 0x2c, 0x90, 0xfa, 0xbf, 0xef, 0xf0, 0x80, 0x55, 0x90, 
+0xfa, 0xbf, 0x74, 0x81, 0xf0, 0x80, 0x4d, 0x12, 0x2d, 0x09, 0x60, 0x09, 0x24, 0x30, 0x70, 0x3e, 
+0x12, 0x2c, 0x5f, 0x80, 0x3f, 0xe5, 0x58, 0x24, 0x03, 0xf9, 0xe4, 0x35, 0x57, 0xfa, 0x7b, 0x01, 
+0xc0, 0x03, 0xc0, 0x02, 0xc0, 0x01, 0x12, 0x2d, 0x53, 0x90, 0x00, 0x05, 0x12, 0x1a, 0x0b, 0xfd, 
+0x90, 0x00, 0x08, 0x12, 0x1a, 0x98, 0xf5, 0x2e, 0x85, 0xf0, 0x2d, 0xd0, 0x01, 0xd0, 0x02, 0xd0, 
+0x03, 0x12, 0x25, 0xd7, 0x90, 0xfa, 0xbe, 0xef, 0xf0, 0xe4, 0xa3, 0xf0, 0x80, 0x06, 0x90, 0xfa, 
+0xbf, 0x74, 0x81, 0xf0, 0x90, 0xfa, 0xbf, 0xe0, 0x12, 0x2d, 0x53, 0x90, 0x00, 0x02, 0x12, 0x1a, 
+0x4a, 0x90, 0xfa, 0xbe, 0xe0, 0xff, 0x22, 0x8b, 0x29, 0x8a, 0x2a, 0x89, 0x2b, 0x8d, 0x2c, 0xe5, 
+0x2c, 0x70, 0x03, 0xaf, 0x2c, 0x22, 0x12, 0x2d, 0x82, 0x70, 0x16, 0x12, 0x2d, 0xa1, 0xe5, 0x2d, 
+0x90, 0xff, 0xf1, 0xf0, 0x12, 0x31, 0x1b, 0x50, 0xf2, 0x12, 0x26, 0x64, 0x40, 0x0b, 0x7f, 0x00, 
+0x22, 0x12, 0x2d, 0xa1, 0x12, 0x26, 0x64, 0x50, 0xf8, 0x90, 0xff, 0xf3, 0x74, 0xa1, 0xf0, 0xe5, 
+0x2c, 0xb4, 0x01, 0x07, 0x90, 0xff, 0xf0, 0xe0, 0x44, 0x02, 0xf0, 0x90, 0xff, 0xf1, 0xe4, 0xf0, 
+0xf5, 0x2f, 0xe5, 0x2c, 0x14, 0xff, 0xe5, 0x2f, 0xc3, 0x9f, 0x50, 0x2a, 0x12, 0x31, 0x04, 0x40, 
+0x03, 0xaf, 0x2f, 0x22, 0xc3, 0xe5, 0x2c, 0x95, 0x2f, 0xff, 0xbf, 0x02, 0x07, 0x90, 0xff, 0xf0, 
+0xe0, 0x44, 0x02, 0xf0, 0x12, 0x2d, 0x94, 0x05, 0x2f, 0x74, 0x01, 0x25, 0x2b, 0xf5, 0x2b, 0xe4, 
+0x35, 0x2a, 0xf5, 0x2a, 0x80, 0xcc, 0x12, 0x31, 0x04, 0x40, 0x03, 0x7f, 0x18, 0x22, 0x12, 0x2d, 
+0x94, 0xaf, 0x2c, 0x22, 0x90, 0xff, 0xf1, 0xe5, 0x2e, 0xf0, 0x02, 0x31, 0x1b, 0x12, 0x10, 0x03, 
+0x78, 0x84, 0x12, 0x22, 0x82, 0x30, 0xe1, 0x08, 0x7f, 0x13, 0x12, 0x30, 0xec, 0x02, 0x26, 0xfb, 
+0x78, 0x84, 0xe6, 0xf9, 0x24, 0x12, 0x12, 0x21, 0xff, 0xe0, 0xff, 0x30, 0xe7, 0x40, 0x54, 0x03, 
+0x60, 0x1e, 0xe9, 0xb4, 0x03, 0x0d, 0x90, 0xff, 0x9e, 0xe0, 0x54, 0xfe, 0xf0, 0xe0, 0x44, 0x04, 
+0xf0, 0x80, 0x46, 0x90, 0xff, 0x9e, 0xe0, 0x54, 0xfd, 0xf0, 0xe0, 0x44, 0x08, 0xf0, 0x80, 0x39, 
+0xe9, 0xb4, 0x03, 0x0d, 0x90, 0xff, 0x9e, 0xe0, 0x54, 0xfb, 0xf0, 0xe0, 0x44, 0x01, 0xf0, 0x80, 
+0x28, 0x90, 0xff, 0x9e, 0xe0, 0x54, 0xf7, 0xf0, 0xe0, 0x44, 0x02, 0xf0, 0x80, 0x1b, 0xef, 0x54, 
+0x03, 0x60, 0x14, 0xe9, 0xb4, 0x03, 0x09, 0x90, 0xff, 0xa4, 0xe0, 0x54, 0xdf, 0xf0, 0x80, 0x07, 
+0x90, 0xff, 0xb4, 0xe0, 0x54, 0xdf, 0xf0, 0xc2, 0xb3, 0x90, 0xf9, 0x17, 0xe0, 0x04, 0xf0, 0xaf, 
+0x01, 0x12, 0x22, 0x33, 0xfd, 0x12, 0x2f, 0x49, 0x12, 0x30, 0xec, 0x02, 0x10, 0x86, 0x75, 0xa8, 
+0x40, 0x78, 0x7f, 0xe4, 0xf6, 0xd8, 0xfd, 0x75, 0x81, 0x8b, 0x02, 0x27, 0x48, 0x02, 0x30, 0xcf, 
+0xe4, 0x93, 0xa3, 0xf8, 0xe4, 0x93, 0xa3, 0x40, 0x03, 0xf6, 0x80, 0x01, 0xf2, 0x08, 0xdf, 0xf4, 
+0x80, 0x29, 0xe4, 0x93, 0xa3, 0xf8, 0x54, 0x07, 0x24, 0x0c, 0xc8, 0xc3, 0x33, 0xc4, 0x54, 0x0f, 
+0x44, 0x20, 0xc8, 0x83, 0x40, 0x04, 0xf4, 0x56, 0x80, 0x01, 0x46, 0xf6, 0xdf, 0xe4, 0x80, 0x0b, 
+0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x90, 0x2b, 0x4c, 0xe4, 0x7e, 0x01, 0x93, 0x60, 
+0xbc, 0xa3, 0xff, 0x54, 0x3f, 0x30, 0xe5, 0x09, 0x54, 0x1f, 0xfe, 0xe4, 0x93, 0xa3, 0x60, 0x01, 
+0x0e, 0xcf, 0x54, 0xc0, 0x25, 0xe0, 0x60, 0xa8, 0x40, 0xb8, 0xe4, 0x93, 0xa3, 0xfa, 0xe4, 0x93, 
+0xa3, 0xf8, 0xe4, 0x93, 0xa3, 0xc8, 0xc5, 0x82, 0xc8, 0xca, 0xc5, 0x83, 0xca, 0xf0, 0xa3, 0xc8, 
+0xc5, 0x82, 0xc8, 0xca, 0xc5, 0x83, 0xca, 0xdf, 0xe9, 0xde, 0xe7, 0x80, 0xbe, 0xe4, 0xf5, 0x22, 
+0x12, 0x1d, 0x12, 0xe0, 0xb4, 0x04, 0x0d, 0xe5, 0x22, 0x24, 0x03, 0xff, 0x12, 0x2f, 0x77, 0x12, 
+0x1d, 0x12, 0xe4, 0xf0, 0x05, 0x22, 0xe5, 0x22, 0xc3, 0x94, 0x02, 0x40, 0xe3, 0xe4, 0xf5, 0x22, 
+0x75, 0xf0, 0x02, 0xe5, 0x22, 0x90, 0xfa, 0x91, 0x12, 0x1d, 0x53, 0x60, 0x2c, 0x12, 0x2c, 0xb4, 
+0xef, 0x60, 0x52, 0x75, 0xf0, 0x02, 0xe5, 0x22, 0x90, 0xfa, 0x91, 0x12, 0x1b, 0x1c, 0xe4, 0xf0, 
+0xa3, 0xf0, 0x75, 0xf0, 0x0a, 0xe5, 0x22, 0x90, 0xfa, 0x9d, 0x12, 0x1b, 0x1c, 0xe0, 0xa3, 0x30, 
+0xe6, 0x33, 0x12, 0x1d, 0x12, 0x74, 0x04, 0xf0, 0x22, 0x75, 0xf0, 0x02, 0xe5, 0x22, 0x90, 0xfa, 
+0x95, 0x12, 0x1d, 0x53, 0x60, 0x16, 0x12, 0x2c, 0xb4, 0xef, 0x60, 0x19, 0x75, 0xf0, 0x02, 0xe5, 
+0x22, 0x90, 0xfa, 0x95, 0x12, 0x1b, 0x1c, 0xe4, 0xf0, 0xa3, 0xf0, 0x22, 0x05, 0x22, 0xe5, 0x22, 
+0xc3, 0x94, 0x02, 0x40, 0x9b, 0x22, 0xe4, 0xff, 0x90, 0xff, 0x83, 0xe0, 0x54, 0x0f, 0xfe, 0xef, 
+0xc3, 0x9e, 0x50, 0x17, 0x74, 0xf0, 0x2f, 0xf5, 0x82, 0xe4, 0x34, 0xfe, 0xf5, 0x83, 0xe0, 0x12, 
+0x1c, 0x11, 0x12, 0x1a, 0x38, 0x0f, 0x12, 0x1c, 0x00, 0x80, 0xdd, 0xef, 0xfd, 0xc3, 0xe5, 0x3a, 
+0x9d, 0xf5, 0x3a, 0xe5, 0x39, 0x94, 0x00, 0xf5, 0x39, 0xd3, 0xe5, 0x3a, 0x94, 0x00, 0xe5, 0x39, 
+0x94, 0x00, 0x40, 0x06, 0xe4, 0x90, 0xff, 0x83, 0xf0, 0x22, 0x12, 0x1d, 0x2f, 0x12, 0x1d, 0x84, 
+0x12, 0x1d, 0x76, 0x12, 0x19, 0xf2, 0x24, 0x6e, 0x60, 0x1e, 0x14, 0x60, 0x1b, 0x24, 0x8e, 0x70, 
+0x2d, 0x90, 0x00, 0x01, 0x12, 0x1a, 0x0b, 0xff, 0x24, 0xfc, 0x60, 0x03, 0x04, 0x70, 0x1f, 0xef, 
+0xfd, 0x7c, 0x00, 0x7f, 0x0d, 0x02, 0x11, 0x16, 0x12, 0x1d, 0x8b, 0x12, 0x25, 0x39, 0x12, 0x1c, 
+0xd9, 0x12, 0x1a, 0x0b, 0x60, 0x03, 0x02, 0x31, 0xbd, 0xe4, 0xff, 0x12, 0x31, 0xb1, 0x22, 0x8b, 
+0x45, 0x8a, 0x46, 0x89, 0x47, 0x8c, 0x48, 0x8d, 0x49, 0xd2, 0x00, 0x12, 0x2d, 0x82, 0x70, 0x16, 
+0x12, 0x2d, 0xa1, 0xe5, 0x48, 0x90, 0xff, 0xf1, 0xf0, 0x12, 0x31, 0x1b, 0x50, 0xf2, 0x12, 0x29, 
+0x14, 0x40, 0x0b, 0x7f, 0x18, 0x22, 0x12, 0x2d, 0xa1, 0x12, 0x29, 0x14, 0x50, 0xf8, 0xe4, 0xf5, 
+0x4b, 0xe5, 0x4a, 0x14, 0xff, 0xe5, 0x4b, 0xc3, 0x9f, 0x50, 0x17, 0x12, 0x29, 0x04, 0x40, 0x03, 
+0x7f, 0x18, 0x22, 0x05, 0x4b, 0x74, 0x01, 0x25, 0x47, 0xf5, 0x47, 0xe4, 0x35, 0x46, 0xf5, 0x46, 
+0x80, 0xdf, 0x90, 0xff, 0xf0, 0xe0, 0x44, 0x01, 0xf0, 0x12, 0x29, 0x04, 0x40, 0x03, 0x7f, 0x18, 
+0x22, 0x7f, 0x00, 0x22, 0xab, 0x45, 0xaa, 0x46, 0xa9, 0x47, 0x12, 0x19, 0xf2, 0x90, 0xff, 0xf1, 
+0xf0, 0x02, 0x31, 0x1b, 0x90, 0xff, 0xf1, 0xe5, 0x49, 0xf0, 0x02, 0x31, 0x1b, 0x7b, 0x01, 0x7a, 
+0xfa, 0x79, 0xcc, 0xe4, 0xfd, 0x12, 0x22, 0xa0, 0x90, 0xfa, 0xcc, 0xe4, 0x75, 0xf0, 0x09, 0x12, 
+0x1a, 0x6c, 0x7b, 0x00, 0x7a, 0x00, 0x79, 0x23, 0x90, 0xfa, 0xcc, 0xe4, 0x75, 0xf0, 0x01, 0x12, 
+0x1a, 0x82, 0x85, 0xf0, 0x2e, 0xf5, 0x2d, 0x7d, 0x01, 0x12, 0x25, 0xd7, 0x90, 0xff, 0xf7, 0xe5, 
+0x23, 0x12, 0x29, 0x78, 0x90, 0xff, 0xf6, 0xe5, 0x23, 0xf0, 0x90, 0xfa, 0xcc, 0xe4, 0xf0, 0xa3, 
+0x74, 0x06, 0x12, 0x29, 0x78, 0xe5, 0x23, 0x30, 0xe0, 0x07, 0x90, 0xff, 0xfc, 0x74, 0x94, 0xf0, 
+0x22, 0x90, 0xff, 0xfc, 0x74, 0x90, 0xf0, 0x22, 0xf0, 0x7b, 0x00, 0x7a, 0x00, 0x79, 0x23, 0x90, 
+0xfa, 0xcc, 0xe4, 0x75, 0xf0, 0x01, 0x12, 0x1a, 0x82, 0x85, 0xf0, 0x2e, 0xf5, 0x2d, 0x7d, 0x01, 
+0x02, 0x25, 0xd7, 0x90, 0xff, 0x93, 0x74, 0x2a, 0xf0, 0x90, 0xff, 0xff, 0xe0, 0x60, 0x06, 0x90, 
+0xff, 0xfc, 0x74, 0x10, 0xf0, 0x90, 0xff, 0x91, 0xe0, 0x44, 0x90, 0xf0, 0xe4, 0x90, 0xf9, 0x15, 
+0xf0, 0xa3, 0xf0, 0x12, 0x2a, 0x78, 0x12, 0x16, 0x42, 0x12, 0x2f, 0xcd, 0x7e, 0x07, 0x7f, 0xd0, 
+0x12, 0x11, 0xe2, 0x7e, 0x0f, 0x7f, 0xa0, 0x12, 0x11, 0xfc, 0xe4, 0x78, 0x77, 0xf6, 0x78, 0x77, 
+0xe6, 0xff, 0xc3, 0x94, 0x06, 0x50, 0x0b, 0x74, 0x6e, 0x2f, 0xf8, 0xe4, 0xf6, 0x78, 0x77, 0x06, 
+0x80, 0xec, 0x7f, 0x03, 0x12, 0x2e, 0xb3, 0x90, 0xf9, 0x15, 0xe0, 0x20, 0xe4, 0x05, 0x7f, 0x04, 
+0x12, 0x2e, 0xb3, 0x90, 0xff, 0x9b, 0xe4, 0xf0, 0x90, 0xff, 0x9a, 0xf0, 0x90, 0xff, 0xe8, 0xe0, 
+0x54, 0x1f, 0xf0, 0xd2, 0xa8, 0x22, 0x15, 0x65, 0xa8, 0x65, 0xa6, 0x07, 0x30, 0x08, 0x05, 0x12, 
+0x11, 0x66, 0x80, 0xf8, 0xd2, 0x08, 0xa8, 0x65, 0xe6, 0xff, 0xb4, 0x03, 0x0f, 0x78, 0x7c, 0x76, 
+0xff, 0x08, 0x76, 0xe0, 0x08, 0x76, 0xff, 0x08, 0x76, 0xa0, 0x80, 0x0d, 0x78, 0x7c, 0x76, 0xff, 
+0x08, 0x76, 0xe2, 0x08, 0x76, 0xff, 0x08, 0x76, 0xb0, 0x78, 0x80, 0x76, 0xfa, 0x08, 0x76, 0x9b, 
+0xef, 0x24, 0xfd, 0x75, 0xf0, 0x0a, 0xa4, 0xae, 0xf0, 0x12, 0x22, 0x92, 0x7b, 0x01, 0x7a, 0xff, 
+0x79, 0x48, 0x78, 0x68, 0x12, 0x1b, 0x31, 0xa8, 0x65, 0xe6, 0x24, 0xfd, 0x75, 0xf0, 0x08, 0xa4, 
+0xff, 0xae, 0xf0, 0x78, 0x6a, 0x12, 0x22, 0x92, 0x79, 0x08, 0x78, 0x6b, 0x12, 0x1b, 0x31, 0x78, 
+0x6d, 0xef, 0x12, 0x22, 0x92, 0x05, 0x65, 0x22, 0x90, 0xff, 0xf0, 0xe0, 0x54, 0xab, 0xf0, 0xe0, 
+0x44, 0x20, 0xf0, 0x90, 0xfa, 0xe3, 0x74, 0x02, 0xf0, 0x7b, 0x01, 0x7a, 0xfa, 0x79, 0xcc, 0xe4, 
+0xf5, 0x2d, 0xf5, 0x2e, 0x7d, 0x01, 0x12, 0x25, 0xd7, 0x7e, 0x00, 0x90, 0xfa, 0xe1, 0xee, 0xf0, 
+0xa3, 0xef, 0xf0, 0x64, 0x01, 0x70, 0x10, 0x90, 0xfa, 0xcc, 0xe0, 0xb4, 0x52, 0x09, 0x90, 0xf9, 
+0x15, 0xe0, 0x54, 0xef, 0xf0, 0x80, 0x29, 0x90, 0xfa, 0xe1, 0xe0, 0x70, 0x04, 0xa3, 0xe0, 0x64, 
+0x01, 0x70, 0x10, 0x90, 0xfa, 0xcc, 0xe0, 0xb4, 0x10, 0x09, 0x90, 0xf9, 0x15, 0xe0, 0x44, 0x10, 
+0xf0, 0x80, 0x0d, 0x90, 0xfa, 0xe3, 0x74, 0x03, 0xf0, 0x90, 0xf9, 0x15, 0xe0, 0x54, 0xef, 0xf0, 
+0x90, 0xff, 0xf0, 0xe0, 0x44, 0x20, 0xf0, 0x22, 0x12, 0x10, 0x03, 0x78, 0x8a, 0xef, 0xf6, 0x12, 
+0x2a, 0x06, 0x12, 0x22, 0x33, 0x30, 0xe0, 0x25, 0x12, 0x22, 0x07, 0xe0, 0x54, 0x7f, 0xf0, 0x78, 
+0x6b, 0x12, 0x1b, 0x28, 0x90, 0x00, 0x02, 0x12, 0x1a, 0x0b, 0x30, 0xe7, 0x09, 0x90, 0x00, 0x02, 
+0xe4, 0x12, 0x1a, 0x4a, 0x80, 0xe9, 0x12, 0x22, 0x07, 0xe0, 0x44, 0x80, 0xf0, 0x12, 0x22, 0x33, 
+0x30, 0xe1, 0x1e, 0x12, 0x21, 0xe9, 0xe0, 0x54, 0x7f, 0xf0, 0x12, 0x31, 0x5c, 0x78, 0x68, 0x12, 
+0x1b, 0x28, 0x90, 0x00, 0x02, 0x74, 0x80, 0x12, 0x1a, 0x4a, 0x12, 0x21, 0xe9, 0xe0, 0x44, 0x80, 
+0xf0, 0x12, 0x31, 0xc7, 0xe4, 0xff, 0x12, 0x30, 0xec, 0x02, 0x10, 0x86, 0x03, 0x68, 0x01, 0xff, 
+0x48, 0x03, 0x6b, 0x01, 0xff, 0x08, 0x02, 0x66, 0x00, 0x00, 0x44, 0xfa, 0x95, 0x00, 0x00, 0x00, 
+0x00, 0x44, 0xfa, 0x91, 0x00, 0x00, 0x00, 0x00, 0x42, 0xfa, 0xaf, 0x00, 0x00, 0x42, 0xfa, 0x7b, 
+0x00, 0x00, 0x42, 0xfa, 0x79, 0x00, 0x00, 0x42, 0xf9, 0x6a, 0xff, 0xff, 0x42, 0xfa, 0x77, 0x00, 
+0x00, 0x43, 0xf9, 0x18, 0x0a, 0x32, 0x02, 0x41, 0xf9, 0x65, 0x20, 0x41, 0xf9, 0x66, 0x20, 0x41, 
+0xf9, 0x63, 0x00, 0x41, 0xf9, 0x64, 0x00, 0x44, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x42, 0xf9, 
+0x15, 0x00, 0x00, 0x41, 0xf9, 0x17, 0x00, 0x01, 0x20, 0x00, 0x41, 0xf8, 0x04, 0x00, 0x00, 0x12, 
+0x10, 0x03, 0x78, 0x85, 0xef, 0xf6, 0x12, 0x30, 0x93, 0x12, 0x30, 0xec, 0x78, 0x85, 0xe6, 0xff, 
+0x24, 0x12, 0x12, 0x21, 0xff, 0xe0, 0xfe, 0x30, 0xe7, 0x16, 0xef, 0xb4, 0x03, 0x09, 0x90, 0xff, 
+0x9e, 0xe0, 0x54, 0xfa, 0xf0, 0x80, 0x22, 0x90, 0xff, 0x9e, 0xe0, 0x54, 0xf5, 0xf0, 0x80, 0x19, 
+0xee, 0x54, 0x03, 0x60, 0x14, 0xef, 0xb4, 0x03, 0x09, 0x90, 0xff, 0xa4, 0xe0, 0x44, 0x20, 0xf0, 
+0x80, 0x07, 0x90, 0xff, 0xb4, 0xe0, 0x44, 0x20, 0xf0, 0x90, 0xf9, 0x17, 0xe0, 0x14, 0xf0, 0xe0, 
+0x70, 0x02, 0xd2, 0xb3, 0x02, 0x10, 0x86, 0x12, 0x1d, 0x6c, 0xe5, 0x3a, 0x64, 0x09, 0x70, 0x04, 
+0xe5, 0x39, 0x64, 0x01, 0x60, 0x48, 0xc3, 0xe5, 0x3a, 0x94, 0x08, 0xe5, 0x39, 0x94, 0x00, 0x40, 
+0x11, 0x7f, 0x08, 0xef, 0xe5, 0x3a, 0x94, 0x08, 0xf5, 0x3a, 0xe5, 0x39, 0x94, 0x00, 0xf5, 0x39, 
+0x80, 0x05, 0xaf, 0x3a, 0x12, 0x1d, 0x84, 0xe4, 0xfe, 0xee, 0xc3, 0x9f, 0x50, 0x19, 0x12, 0x1c, 
+0x11, 0x12, 0x19, 0xf2, 0xfd, 0x74, 0xf8, 0x2e, 0xf5, 0x82, 0xe4, 0x34, 0xfe, 0xf5, 0x83, 0xed, 
+0xf0, 0x0e, 0x12, 0x1c, 0x00, 0x80, 0xe2, 0xef, 0x54, 0x7f, 0x90, 0xff, 0x81, 0xf0, 0x22, 0x8b, 
+0x59, 0x8a, 0x5a, 0x89, 0x5b, 0x12, 0x2d, 0x48, 0x70, 0x05, 0xa3, 0x74, 0x08, 0xf0, 0x22, 0xab, 
+0x59, 0xaa, 0x5a, 0xa9, 0x5b, 0x12, 0x2d, 0x3c, 0x90, 0xfa, 0xc6, 0x12, 0x1b, 0x43, 0xe5, 0x5b, 
+0x24, 0x03, 0xf9, 0xe4, 0x35, 0x5a, 0xfa, 0x90, 0xfa, 0xc0, 0x12, 0x1b, 0x43, 0xe4, 0x90, 0xfa, 
+0xbf, 0xf0, 0x78, 0x8b, 0xf6, 0x90, 0xfa, 0xbe, 0xe0, 0xff, 0x78, 0x8b, 0xe6, 0xc3, 0x9f, 0x50, 
+0x12, 0x12, 0x2d, 0x1a, 0xff, 0x12, 0x2d, 0x23, 0x12, 0x2d, 0x36, 0x78, 0x8b, 0x06, 0x12, 0x2d, 
+0x32, 0x80, 0xe2, 0x22, 0xad, 0x07, 0xac, 0x06, 0x90, 0x31, 0x4d, 0xe4, 0x93, 0xff, 0x78, 0x74, 
+0xf6, 0x54, 0x0f, 0x12, 0x1c, 0xf8, 0xe0, 0x08, 0x76, 0x00, 0x08, 0xf6, 0x18, 0x12, 0x1c, 0x29, 
+0xc3, 0x33, 0xce, 0x33, 0xce, 0xd8, 0xf9, 0xff, 0x78, 0x75, 0xee, 0xf6, 0x08, 0xef, 0xf6, 0xee, 
+0x44, 0xf8, 0x18, 0xf6, 0xef, 0x08, 0xf6, 0x90, 0xff, 0x7a, 0xe0, 0x20, 0xe7, 0x03, 0x7f, 0x00, 
+0x22, 0x78, 0x75, 0xe6, 0xfe, 0x08, 0xe6, 0xf5, 0x82, 0x8e, 0x83, 0xec, 0xf0, 0xa3, 0xed, 0xf0, 
+0x90, 0xff, 0x7a, 0x74, 0x02, 0xf0, 0x7f, 0x01, 0x22, 0xab, 0x56, 0xaa, 0x57, 0xa9, 0x58, 0x90, 
+0x00, 0x03, 0x12, 0x1a, 0x0b, 0x54, 0xf0, 0x24, 0xa0, 0x22, 0x90, 0xfa, 0xc6, 0x12, 0x1b, 0x3a, 
+0x02, 0x19, 0xf2, 0x90, 0xfa, 0xc0, 0x12, 0x1b, 0x3a, 0xef, 0x12, 0x1a, 0x38, 0x90, 0xfa, 0xc7, 
+0xe4, 0x22, 0x90, 0xfa, 0xc1, 0xe4, 0x75, 0xf0, 0x01, 0x02, 0x1a, 0x6c, 0x90, 0x00, 0x08, 0x12, 
+0x1a, 0x98, 0xaa, 0xf0, 0xf9, 0x7b, 0x01, 0x22, 0x90, 0x00, 0x05, 0x12, 0x1a, 0x0b, 0x90, 0xfa, 
+0xbe, 0xf0, 0x22, 0xab, 0x56, 0xaa, 0x57, 0xa9, 0x58, 0x22, 0x90, 0xfa, 0xda, 0xe0, 0xff, 0x7e, 
+0x00, 0xc3, 0x90, 0xfa, 0xd4, 0xe0, 0x9f, 0xf0, 0x90, 0xfa, 0xd3, 0xe0, 0x9e, 0xf0, 0x90, 0xfa, 
+0xd5, 0xee, 0x8f, 0xf0, 0x12, 0x1a, 0x6c, 0xef, 0x25, 0x51, 0xf5, 0x51, 0xee, 0x35, 0x50, 0xf5, 
+0x50, 0x22, 0x90, 0xff, 0xf0, 0xe0, 0x54, 0xfe, 0xf0, 0xe0, 0x54, 0xfd, 0xf0, 0x90, 0xfa, 0xe3, 
+0xe0, 0x64, 0x03, 0x22, 0x90, 0xff, 0xf2, 0xe0, 0xab, 0x29, 0xaa, 0x2a, 0xa9, 0x2b, 0x02, 0x1a, 
+0x38, 0x90, 0xff, 0xf3, 0x74, 0xa0, 0xf0, 0x22, 0x8f, 0x64, 0xed, 0x70, 0x0f, 0xe5, 0x64, 0xb4, 
+0x03, 0x05, 0x7f, 0x01, 0x02, 0x31, 0x32, 0x7f, 0x02, 0x02, 0x31, 0x32, 0xaf, 0x64, 0x12, 0x2a, 
+0x06, 0x74, 0x6e, 0x25, 0x64, 0xf8, 0xe6, 0x30, 0xe2, 0x0b, 0xd2, 0x09, 0x12, 0x1c, 0x83, 0xe0, 
+0x54, 0x7f, 0xf0, 0x80, 0x02, 0xc2, 0x09, 0xe5, 0x64, 0xb4, 0x03, 0x07, 0x7f, 0x81, 0x12, 0x31, 
+0x32, 0x80, 0x05, 0x7f, 0x82, 0x12, 0x31, 0x32, 0x30, 0x09, 0x07, 0x12, 0x1c, 0x83, 0xe0, 0x44, 
+0x80, 0xf0, 0x12, 0x31, 0xc7, 0x22, 0x12, 0x10, 0x03, 0x90, 0xff, 0xfd, 0xe0, 0x44, 0x60, 0xf0, 
+0xd2, 0x01, 0x90, 0xff, 0xfc, 0xe0, 0x44, 0x02, 0xf0, 0x90, 0xff, 0x00, 0xe0, 0x30, 0xe7, 0x13, 
+0x90, 0xff, 0x83, 0xe0, 0x44, 0x80, 0xf0, 0x43, 0x35, 0x80, 0x90, 0xff, 0xfc, 0xe0, 0x44, 0x01, 
+0xf0, 0x80, 0x0d, 0x12, 0x1d, 0x2f, 0x53, 0x35, 0x7f, 0x90, 0xff, 0xfc, 0xe0, 0x54, 0xfe, 0xf0, 
+0x90, 0xff, 0x81, 0xe0, 0x44, 0x80, 0xf0, 0x12, 0x02, 0xb0, 0x12, 0x1d, 0x37, 0x02, 0x10, 0x86, 
+0x12, 0x10, 0x03, 0x78, 0x89, 0xef, 0xf6, 0xd2, 0x00, 0x12, 0x2a, 0x06, 0x90, 0xf9, 0x67, 0x12, 
+0x1b, 0x3a, 0xe9, 0x24, 0x03, 0xf9, 0xe4, 0x3a, 0xfa, 0xc0, 0x02, 0x78, 0x80, 0xe6, 0xfe, 0x08, 
+0xe6, 0xaa, 0x06, 0xf8, 0xac, 0x02, 0x7d, 0x01, 0xd0, 0x02, 0x12, 0x22, 0x25, 0x12, 0x31, 0xc7, 
+0x78, 0x89, 0xe6, 0xff, 0x12, 0x13, 0x3f, 0x12, 0x30, 0xec, 0x02, 0x10, 0x86, 0x8f, 0x63, 0x12, 
+0x2a, 0x06, 0x12, 0x22, 0x07, 0xe0, 0x54, 0x3f, 0xf0, 0xe5, 0x82, 0x24, 0x04, 0x12, 0x21, 0xf3, 
+0xe0, 0x54, 0x3f, 0xf0, 0x08, 0xe6, 0xfe, 0x08, 0xe6, 0x8e, 0x83, 0x24, 0x0b, 0x12, 0x21, 0xf3, 
+0xe0, 0x54, 0xf8, 0xf0, 0x12, 0x31, 0xc7, 0x74, 0x6e, 0x25, 0x63, 0xf8, 0x74, 0xfb, 0x56, 0xf6, 
+0x7f, 0x00, 0x22, 0x8f, 0x23, 0xc2, 0x08, 0x12, 0x2a, 0x06, 0x12, 0x22, 0x12, 0x78, 0x7e, 0x12, 
+0x21, 0xeb, 0xe0, 0x44, 0x01, 0xf0, 0x12, 0x22, 0x4a, 0x12, 0x21, 0xef, 0xe0, 0x20, 0xe0, 0xf6, 
+0xef, 0x24, 0x0b, 0xf5, 0x82, 0xe4, 0x3e, 0xf5, 0x83, 0xe0, 0x54, 0xf8, 0xf0, 0x12, 0x31, 0xc7, 
+0xaf, 0x23, 0x12, 0x13, 0x3f, 0x22, 0x12, 0x10, 0x03, 0x12, 0x2a, 0x06, 0x12, 0x22, 0x4a, 0x24, 
+0x06, 0x12, 0x21, 0xf1, 0xe0, 0xfd, 0x12, 0x22, 0x2d, 0x90, 0x00, 0x03, 0x12, 0x22, 0x52, 0x24, 
+0x05, 0x12, 0x21, 0xf3, 0xe0, 0x90, 0x00, 0x04, 0x12, 0x1a, 0x4a, 0x12, 0x31, 0xc7, 0x7d, 0x02, 
+0xe4, 0xff, 0x12, 0x2f, 0x18, 0x02, 0x10, 0x86, 0xae, 0x05, 0x12, 0x1c, 0xde, 0xef, 0x12, 0x1a, 
+0x4a, 0x0e, 0x0e, 0x0e, 0xee, 0xd3, 0x95, 0x3c, 0xe4, 0x95, 0x3b, 0x40, 0x02, 0xae, 0x3c, 0xee, 
+0xd3, 0x94, 0x08, 0x74, 0x80, 0x94, 0x81, 0x40, 0x0a, 0x7e, 0x03, 0x90, 0x00, 0x02, 0x74, 0x02, 
+0x12, 0x1a, 0x4a, 0xaf, 0x06, 0x12, 0x31, 0xb1, 0x22, 0xae, 0x07, 0xed, 0x54, 0x03, 0x64, 0x01, 
+0x60, 0x03, 0x7f, 0x10, 0x22, 0xed, 0x54, 0x7c, 0xc3, 0x94, 0x04, 0x50, 0x03, 0x7f, 0x0b, 0x22, 
+0x74, 0x6e, 0x2e, 0xf8, 0x74, 0x02, 0x46, 0xf6, 0x74, 0x96, 0x2e, 0xf5, 0x82, 0xe4, 0x34, 0xfa, 
+0xf5, 0x83, 0xed, 0xf0, 0x7f, 0x00, 0x22, 0xbf, 0x03, 0x06, 0x7c, 0xff, 0x7d, 0xe0, 0x80, 0x04, 
+0x7c, 0xff, 0x7d, 0xe2, 0x8d, 0x82, 0x8c, 0x83, 0xe0, 0x44, 0x80, 0xf0, 0xe5, 0x82, 0x24, 0x04, 
+0x12, 0x21, 0xf3, 0xe0, 0x44, 0x80, 0xf0, 0x74, 0x6e, 0x2f, 0xf8, 0x74, 0x04, 0x46, 0xf6, 0x7f, 
+0x00, 0x22, 0x12, 0x10, 0x03, 0xe5, 0x3a, 0x64, 0x09, 0x70, 0x04, 0xe5, 0x39, 0x64, 0x01, 0x60, 
+0x16, 0x90, 0xff, 0x83, 0xe0, 0x54, 0x0f, 0xff, 0xc3, 0xe5, 0x3a, 0x9f, 0xe5, 0x39, 0x94, 0x00, 
+0x40, 0x05, 0x12, 0x28, 0x16, 0x80, 0x03, 0x12, 0x31, 0xbd, 0x02, 0x10, 0x86, 0x90, 0xff, 0xfc, 
+0xe0, 0x20, 0xe7, 0x1f, 0xc2, 0xaf, 0x7d, 0xff, 0xac, 0x05, 0x1d, 0xec, 0x60, 0x15, 0x7e, 0x04, 
+0x7f, 0x00, 0xef, 0x1f, 0xaa, 0x06, 0x70, 0x01, 0x1e, 0x4a, 0x60, 0xec, 0x90, 0xff, 0x92, 0xe4, 
+0xf0, 0x80, 0xef, 0x22, 0x12, 0x10, 0x03, 0x78, 0x66, 0xe6, 0xfe, 0x08, 0xe6, 0xff, 0x30, 0xe0, 
+0x12, 0x30, 0xe1, 0x0f, 0x90, 0xff, 0xfc, 0xe0, 0x44, 0x20, 0xf0, 0x7f, 0x04, 0x12, 0x12, 0x19, 
+0x12, 0x1d, 0x46, 0x02, 0x10, 0x86, 0x8e, 0x5f, 0x8f, 0x60, 0xe5, 0x60, 0x15, 0x60, 0xae, 0x5f, 
+0x70, 0x02, 0x15, 0x5f, 0xd3, 0x94, 0x00, 0xee, 0x94, 0x00, 0x40, 0x09, 0x7e, 0x07, 0x7f, 0xd0, 
+0x12, 0x0f, 0xdc, 0x80, 0xe5, 0x22, 0x11, 0x94, 0x2d, 0xf6, 0x23, 0xef, 0x31, 0xa3, 0x2f, 0xf4, 
+0x2f, 0xa2, 0x30, 0xb2, 0x2e, 0xe6, 0x26, 0x6d, 0x2b, 0xaf, 0x30, 0x55, 0x30, 0x74, 0x1d, 0xb4, 
+0x2e, 0x40, 0x2a, 0xe8, 0x0e, 0x12, 0x10, 0x03, 0x78, 0x86, 0x12, 0x22, 0x82, 0x20, 0xe1, 0x07, 
+0x7f, 0x12, 0x12, 0x30, 0xec, 0x80, 0x0a, 0x78, 0x86, 0xe6, 0xff, 0x12, 0x23, 0x49, 0x12, 0x30, 
+0xec, 0x02, 0x10, 0x86, 0x12, 0x10, 0x03, 0x78, 0x87, 0x12, 0x22, 0x82, 0x20, 0xe2, 0x07, 0x7f, 
+0x11, 0x12, 0x30, 0xec, 0x80, 0x0a, 0x78, 0x87, 0xe6, 0xff, 0x12, 0x2e, 0x7d, 0x12, 0x30, 0xec, 
+0x02, 0x10, 0x86, 0x8f, 0x61, 0x12, 0x2e, 0x7d, 0xaf, 0x61, 0x12, 0x2a, 0x06, 0x12, 0x22, 0x12, 
+0x12, 0x31, 0xc7, 0x74, 0x6e, 0x25, 0x61, 0xf8, 0x74, 0xfd, 0x56, 0xf6, 0xaf, 0x61, 0x12, 0x13, 
+0x3f, 0x22, 0x12, 0x10, 0x03, 0xe5, 0x3a, 0x64, 0x09, 0x70, 0x04, 0xe5, 0x39, 0x64, 0x01, 0x60, 
+0x05, 0x12, 0x2c, 0x07, 0x80, 0x06, 0x12, 0x1d, 0x64, 0x12, 0x1d, 0x6c, 0x02, 0x10, 0x86, 0x12, 
+0x29, 0x93, 0x12, 0x12, 0xbb, 0x90, 0xf8, 0x04, 0xe0, 0xff, 0x60, 0x05, 0x7d, 0x01, 0x12, 0x12, 
+0x58, 0x12, 0x29, 0x1d, 0x12, 0x12, 0xf7, 0x12, 0x11, 0x74, 0x80, 0xe3, 0x12, 0x1c, 0xde, 0xef, 
+0x12, 0x1a, 0x4a, 0xe4, 0xf5, 0x33, 0xf5, 0x34, 0xef, 0x60, 0x03, 0x02, 0x31, 0xbd, 0xe4, 0xff, 
+0x12, 0x31, 0xb1, 0x22, 0x90, 0xff, 0xf0, 0xe0, 0xff, 0x54, 0xa0, 0x60, 0xf7, 0xef, 0x30, 0xe5, 
+0x08, 0x90, 0xff, 0xf0, 0x44, 0x20, 0xf0, 0xc3, 0x22, 0xd3, 0x22, 0x90, 0xff, 0xf0, 0xe0, 0xff, 
+0x54, 0x28, 0x60, 0xf7, 0xef, 0x30, 0xe5, 0x08, 0x90, 0xff, 0xf0, 0x44, 0x20, 0xf0, 0xc3, 0x22, 
+0xd3, 0x22, 0xef, 0x30, 0xe7, 0x08, 0x12, 0x1c, 0x95, 0xe0, 0x54, 0xdf, 0xf0, 0x22, 0xef, 0x12, 
+0x1c, 0xe8, 0xe0, 0x54, 0xdf, 0xf0, 0x22, 0x81, 0x01, 0x82, 0x02, 0x83, 0x03, 0x87, 0x40, 0x00, 
+0x40, 0x00, 0x40, 0x00, 0x40, 0x00, 0x40, 0x00, 0x40, 0x00, 0x08, 0x00, 0x78, 0x7e, 0x12, 0x22, 
+0x09, 0xa3, 0xa3, 0xe0, 0xff, 0x30, 0xe7, 0x06, 0x54, 0x7f, 0xf0, 0x44, 0x80, 0xf0, 0x22, 0x85, 
+0x3b, 0x39, 0x85, 0x3c, 0x3a, 0x90, 0xff, 0x82, 0xe0, 0x54, 0xf7, 0xf0, 0xa3, 0xe0, 0x54, 0x7f, 
+0xf0, 0x22, 0xe4, 0xfe, 0xee, 0x90, 0x31, 0x47, 0x93, 0xb5, 0x07, 0x02, 0xd3, 0x22, 0x0e, 0xbe, 
+0x07, 0xf2, 0xc3, 0x22, 0x00, 0x08, 0x18, 0x28, 0x38, 0x01, 0x81, 0x10, 0x0a, 0x02, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x12, 0x10, 0x03, 0x7f, 0x02, 0x12, 0x10, 0x92, 0x12, 0x1d, 0x46, 0x02, 0x10, 
+0x86, 0x75, 0x39, 0x00, 0x8f, 0x3a, 0x12, 0x1c, 0x30, 0x12, 0x2c, 0x07, 0x22, 0x12, 0x1d, 0x6c, 
+0x12, 0x1d, 0x2f, 0x12, 0x1d, 0x64, 0x22, 0xc2, 0x08, 0x22, 
 };
 
 #undef IMAGE_VERSION_NAME
diff -Nru a/drivers/usb/serial/io_tables.h b/drivers/usb/serial/io_tables.h
--- a/drivers/usb/serial/io_tables.h	2004-10-18 14:56:33 -07:00
+++ b/drivers/usb/serial/io_tables.h	2004-10-18 14:56:33 -07:00
@@ -14,22 +14,12 @@
 #ifndef IO_TABLES_H
 #define IO_TABLES_H
 
-static struct usb_device_id edgeport_1port_id_table [] = {
-	{ USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_EDGEPORT_PARALLEL_PORT) },
-	{ }
-};
-
 static struct usb_device_id edgeport_2port_id_table [] = {
 	{ USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_EDGEPORT_2) },
 	{ USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_EDGEPORT_2I) },
 	{ USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_EDGEPORT_421) },
 	{ USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_EDGEPORT_21) },
 	{ USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_EDGEPORT_2_DIN) },
-	{ USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_BB_EDGEPORT_2) },
-	{ USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_BB_EDGEPORT_2I) },
-	{ USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_BB_EDGEPORT_421) },
-	{ USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_BB_EDGEPORT_21) },
-	{ USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_BB_EDGEPORT_2_DIN) },
 	{ }
 };
 
@@ -41,12 +31,9 @@
 	{ USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_EDGEPORT_4I) },
 	{ USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_EDGEPORT_8_DUAL_CPU) },
 	{ USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_EDGEPORT_4_DIN) },
+	{ USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_EDGEPORT_22I) },
+	{ USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_EDGEPORT_412_4) },
 	{ USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_EDGEPORT_COMPATIBLE) },
-	{ USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_BB_EDGEPORT_4) },
-	{ USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_BB_EDGEPORT_4T) },
-	{ USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_BB_EDGEPORT_4I) },
-	{ USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_BB_EDGEPORT_8_DUAL_CPU) },
-	{ USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_BB_EDGEPORT_4_DIN) },
 	{ }
 };
 
@@ -54,9 +41,9 @@
 	{ USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_EDGEPORT_8) },
 	{ USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_EDGEPORT_16_DUAL_CPU) },
 	{ USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_EDGEPORT_8I) },
-	{ USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_BB_EDGEPORT_8) },
-	{ USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_BB_EDGEPORT_16_DUAL_CPU) },
-	{ USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_BB_EDGEPORT_8I) },
+	{ USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_EDGEPORT_8R) },
+	{ USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_EDGEPORT_8RR) },
+	{ USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_EDGEPORT_412_8) },
 	{ }
 };
 
@@ -69,7 +56,6 @@
 	{ USB_DEVICE(USB_VENDOR_ID_ION,	ION_DEVICE_ID_EDGEPORT_2) },
 	{ USB_DEVICE(USB_VENDOR_ID_ION,	ION_DEVICE_ID_EDGEPORT_4I) },
 	{ USB_DEVICE(USB_VENDOR_ID_ION,	ION_DEVICE_ID_EDGEPORT_2I) },
-	{ USB_DEVICE(USB_VENDOR_ID_ION,	ION_DEVICE_ID_EDGEPORT_PARALLEL_PORT) },
 	{ USB_DEVICE(USB_VENDOR_ID_ION,	ION_DEVICE_ID_EDGEPORT_421) },
 	{ USB_DEVICE(USB_VENDOR_ID_ION,	ION_DEVICE_ID_EDGEPORT_21) },
 	{ USB_DEVICE(USB_VENDOR_ID_ION,	ION_DEVICE_ID_EDGEPORT_8_DUAL_CPU) },
@@ -77,50 +63,17 @@
 	{ USB_DEVICE(USB_VENDOR_ID_ION,	ION_DEVICE_ID_EDGEPORT_2_DIN) },
 	{ USB_DEVICE(USB_VENDOR_ID_ION,	ION_DEVICE_ID_EDGEPORT_4_DIN) },
 	{ USB_DEVICE(USB_VENDOR_ID_ION,	ION_DEVICE_ID_EDGEPORT_16_DUAL_CPU) },
+	{ USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_EDGEPORT_22I) },
+	{ USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_EDGEPORT_412_4) },
 	{ USB_DEVICE(USB_VENDOR_ID_ION,	ION_DEVICE_ID_EDGEPORT_COMPATIBLE) },
 	{ USB_DEVICE(USB_VENDOR_ID_ION,	ION_DEVICE_ID_EDGEPORT_8I) },
-	{ USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_BB_EDGEPORT_2) },
-	{ USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_BB_EDGEPORT_2I) },
-	{ USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_BB_EDGEPORT_421) },
-	{ USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_BB_EDGEPORT_21) },
-	{ USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_BB_EDGEPORT_2_DIN) },
-	{ USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_BB_EDGEPORT_4) },
-	{ USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_BB_EDGEPORT_4T) },
-	{ USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_BB_EDGEPORT_4I) },
-	{ USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_BB_EDGEPORT_8_DUAL_CPU) },
-	{ USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_BB_EDGEPORT_4_DIN) },
-	{ USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_BB_EDGEPORT_8) },
-	{ USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_BB_EDGEPORT_16_DUAL_CPU) },
-	{ USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_BB_EDGEPORT_8I) },
+	{ USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_EDGEPORT_8R) },
+	{ USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_EDGEPORT_8RR) },
+	{ USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_EDGEPORT_412_8) },
 	{ }							/* Terminating entry */
 };
 
 MODULE_DEVICE_TABLE (usb, id_table_combined);
-
-static struct usb_serial_device_type edgeport_1port_device = {
-	.owner			= THIS_MODULE,
-	.name			= "Edgeport 1 port adapter",
-	.short_name		= "edgeport_1",
-	.id_table		= edgeport_1port_id_table,
-	.num_interrupt_in	= 1,
-	.num_bulk_in		= 1,
-	.num_bulk_out		= 1,
-	.num_ports		= 1,
-	.open			= edge_open,
-	.close			= edge_close,
-	.throttle		= edge_throttle,
-	.unthrottle		= edge_unthrottle,
-	.attach			= edge_startup,
-	.shutdown		= edge_shutdown,
-	.ioctl			= edge_ioctl,
-	.set_termios		= edge_set_termios,
-	.tiocmget		= edge_tiocmget,
-	.tiocmset		= edge_tiocmset,
-	.write			= edge_write,
-	.write_room		= edge_write_room,
-	.chars_in_buffer	= edge_chars_in_buffer,
-	.break_ctl		= edge_break,
-};
 
 static struct usb_serial_device_type edgeport_2port_device = {
 	.owner			= THIS_MODULE,
diff -Nru a/drivers/usb/serial/io_ti.c b/drivers/usb/serial/io_ti.c
--- a/drivers/usb/serial/io_ti.c	2004-10-18 14:57:04 -07:00
+++ b/drivers/usb/serial/io_ti.c	2004-10-18 14:57:04 -07:00
@@ -124,15 +124,11 @@
 	{ USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_TI_EDGEPORT_2C) },
 	{ USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_TI_EDGEPORT_2I) },
 	{ USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_TI_EDGEPORT_421) },
-	{ USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_TI_EDGEPORT_421_BOOT) },
-	{ USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_TI_EDGEPORT_421_DOWN) },
 	{ USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_TI_EDGEPORT_21) },
-	{ USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_TI_EDGEPORT_21_BOOT) },
-	{ USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_TI_EDGEPORT_21_DOWN) },
 	{ USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_TI_EDGEPORT_42) },
 	{ USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_TI_EDGEPORT_4) },
 	{ USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_TI_EDGEPORT_4I) },
-	{ USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_TI_EDGEPORT_22) },
+	{ USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_TI_EDGEPORT_22I) },
 	{ }
 };
 
@@ -143,15 +139,11 @@
 	{ USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_TI_EDGEPORT_2C) },
 	{ USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_TI_EDGEPORT_2I) },
 	{ USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_TI_EDGEPORT_421) },
-	{ USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_TI_EDGEPORT_421_BOOT) },
-	{ USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_TI_EDGEPORT_421_DOWN) },
 	{ USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_TI_EDGEPORT_21) },
-	{ USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_TI_EDGEPORT_21_BOOT) },
-	{ USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_TI_EDGEPORT_21_DOWN) },
 	{ USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_TI_EDGEPORT_42) },
 	{ USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_TI_EDGEPORT_4) },
 	{ USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_TI_EDGEPORT_4I) },
-	{ USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_TI_EDGEPORT_22) },
+	{ USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_TI_EDGEPORT_22I) },
 	{ }
 };
 
@@ -278,7 +270,7 @@
 {
 	int status = 0;
 	__u8 read_length;
-	__u16 be_start_address;
+	__be16 be_start_address;
 	
 	dbg ("%s - @ %x for %d", __FUNCTION__, start_address, length);
 
@@ -395,7 +387,7 @@
 {
 	int status = 0;
 	int write_length;
-	__u16 be_start_address;
+	__be16 be_start_address;
 
 	/* We can only send a maximum of 1 aligned byte page at a time */
 	
@@ -1804,12 +1796,7 @@
 	tty = port->tty;
 	if (tty) {
 		/* let the tty driver wakeup if it has a special write_wakeup function */
-		if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) && tty->ldisc.write_wakeup) {
-			(tty->ldisc.write_wakeup)(tty);
-		}
-
-		/* tell the tty driver that something has changed */
-		wake_up_interruptible(&tty->write_wait);
+		tty_wakeup(tty);
 	}
 }
 
diff -Nru a/drivers/usb/serial/io_usbvend.h b/drivers/usb/serial/io_usbvend.h
--- a/drivers/usb/serial/io_usbvend.h	2004-10-18 14:56:49 -07:00
+++ b/drivers/usb/serial/io_usbvend.h	2004-10-18 14:56:49 -07:00
@@ -18,14 +18,6 @@
 #if !defined(_USBVEND_H)
 #define	_USBVEND_H
 
-#ifndef __KERNEL__
-#include "ionprag.h"	/* Extra I/O Networks pragmas */
-
-#include <usbdi.h>
-
-#include "iondef.h"	/* Standard I/O Networks definitions */
-#endif
-
 /************************************************************************
  *
  *		D e f i n e s   /   T y p e d e f s
@@ -37,6 +29,7 @@
 // 
 
 #define	USB_VENDOR_ID_ION	0x1608		// Our VID
+#define	USB_VENDOR_ID_TI	0x0451		// TI VID
 
 //
 // Definitions of USB product IDs (PID)
@@ -48,36 +41,41 @@
 
 // ION-device OEM IDs
 #define	ION_OEM_ID_ION		0		// 00h Inside Out Networks
-#define	ION_OEM_ID_NLYNX	1		// 01h NLynx Systems	  
+#define	ION_OEM_ID_NLYNX	1		// 01h NLynx Systems
 #define	ION_OEM_ID_GENERIC	2		// 02h Generic OEM
 #define	ION_OEM_ID_MAC		3		// 03h Mac Version
 #define	ION_OEM_ID_MEGAWOLF	4		// 04h Lupusb OEM Mac version (MegaWolf)
 #define	ION_OEM_ID_MULTITECH	5		// 05h Multitech Rapidports
+#define	ION_OEM_ID_AGILENT	6		// 06h AGILENT board
 
-	
-// ION-device Device IDs
-// Product IDs - assigned to match middle digit of serial number
 
+// ION-device Device IDs
+// Product IDs - assigned to match middle digit of serial number (No longer true)
 
-// The ION_DEVICE_ID_GENERATION_2 bit (0x20) will be ORed into the existing edgeport
-// PIDs to identify 80251+Netchip hardware.  This will guarantee that if a second
-// generation edgeport device is plugged into a PC with an older (pre 2.0) driver,
-// it will not enumerate.
+#define ION_DEVICE_ID_80251_NETCHIP	0x020	// This bit is set in the PID if this edgeport hardware$
+						// is based on the 80251+Netchip.  
 
-#define ION_DEVICE_ID_GENERATION_2	0x020	// This bit is set in the PID if this edgeport hardware
-															// is based on the 80251+Netchip.  
+#define ION_DEVICE_ID_GENERATION_1	0x00	// Value for 930 based edgeports
+#define ION_DEVICE_ID_GENERATION_2	0x01	// Value for 80251+Netchip.
+#define ION_DEVICE_ID_GENERATION_3	0x02	// Value for Texas Instruments TUSB5052 chip
+#define ION_DEVICE_ID_GENERATION_4	0x03	// Watchport Family of products
+#define ION_GENERATION_MASK		0x03
+
+#define ION_DEVICE_ID_HUB_MASK		0x0080	// This bit in the PID designates a HUB device
+						// for example 8C would be a 421 4 port hub
+						// and 8D would be a 2 port embedded hub
 
-#define EDGEPORT_DEVICE_ID_MASK			0x3df	// Not including GEN_2 bit
+#define EDGEPORT_DEVICE_ID_MASK			0x0ff	// Not including OEM or GENERATION fields
 
 #define	ION_DEVICE_ID_UNCONFIGURED_EDGE_DEVICE	0x000	// In manufacturing only
 #define ION_DEVICE_ID_EDGEPORT_4		0x001	// Edgeport/4 RS232
-//	ION_DEVICE_ID_HUBPORT_7			0x002	// Hubport/7 (Placeholder, not used by software)
+#define	ION_DEVICE_ID_EDGEPORT_8R		0x002	// Edgeport with RJ45 no Ring
 #define ION_DEVICE_ID_RAPIDPORT_4		0x003	// Rapidport/4
 #define ION_DEVICE_ID_EDGEPORT_4T		0x004	// Edgeport/4 RS232 for Telxon (aka "Fleetport")
 #define ION_DEVICE_ID_EDGEPORT_2		0x005	// Edgeport/2 RS232
 #define ION_DEVICE_ID_EDGEPORT_4I		0x006	// Edgeport/4 RS422
 #define ION_DEVICE_ID_EDGEPORT_2I		0x007	// Edgeport/2 RS422/RS485
-//	ION_DEVICE_ID_HUBPORT_4			0x008	// Hubport/4 (Placeholder, not used by software)
+#define	ION_DEVICE_ID_EDGEPORT_8RR		0x008	// Edgeport with RJ45 with Data and RTS/CTS only
 //	ION_DEVICE_ID_EDGEPORT_8_HANDBUILT	0x009	// Hand-built Edgeport/8 (Placeholder, used in middle digit of serial number only!)
 //	ION_DEVICE_ID_MULTIMODEM_4X56		0x00A	// MultiTech version of RP/4 (Placeholder, used in middle digit of serial number only!)
 #define	ION_DEVICE_ID_EDGEPORT_PARALLEL_PORT	0x00B	// Edgeport/(4)21 Parallel port (USS720)
@@ -90,41 +88,134 @@
 #define ION_DEVICE_ID_EDGEPORT_16_DUAL_CPU	0x012	// Half of an Edgeport/16 (the kind with 2 EP/8s)
 #define ION_DEVICE_ID_EDGEPORT_COMPATIBLE	0x013	// Edgeport Compatible, for NCR, Axiohm etc. testing
 #define ION_DEVICE_ID_EDGEPORT_8I		0x014	// Edgeport/8 RS422 (single-CPU)
+#define ION_DEVICE_ID_EDGEPORT_1		0x015	// Edgeport/1 RS232
+#define ION_DEVICE_ID_EPOS44			0x016	// Half of an EPOS/44 (TIUMP BASED)
+#define ION_DEVICE_ID_EDGEPORT_42		0x017	// Edgeport/42
+#define ION_DEVICE_ID_EDGEPORT_412_8		0x018	// Edgeport/412 8 port part
+#define ION_DEVICE_ID_EDGEPORT_412_4		0x019	// Edgeport/412	4 port part
+#define ION_DEVICE_ID_EDGEPORT_22I		0x01A	// Edgeport/22I is an Edgeport/4 with ports 1&2 RS422 and ports 3&4 RS232
+
+// Compact Form factor TI based devices  2c, 21c, 22c, 221c
+#define ION_DEVICE_ID_EDGEPORT_2C		0x01B	// Edgeport/2c is a TI based Edgeport/2 - Small I2c
+#define ION_DEVICE_ID_EDGEPORT_221C		0x01C	// Edgeport/221c is a TI based Edgeport/2 with lucent chip and
+							// 2 external hub ports - Large I2C
+#define ION_DEVICE_ID_EDGEPORT_22C		0x01D	// Edgeport/22c is a TI based Edgeport/2 with
+							// 2 external hub ports - Large I2C
+#define ION_DEVICE_ID_EDGEPORT_21C		0x01E	// Edgeport/21c is a TI based Edgeport/2 with lucent chip
+							// Small I2C
+
+
+/*
+ *  DANGER DANGER The 0x20 bit was used to indicate a 8251/netchip GEN 2 device.
+ *  Since the MAC, Linux, and Optimal drivers still used the old code
+ *  I suggest that you skip the 0x20 bit when creating new PIDs
+ */
+
+
+// Generation 3 devices -- 3410 based edgport/1 (256 byte I2C)
+#define ION_DEVICE_ID_TI3410_EDGEPORT_1		0x040	// Edgeport/1 RS232
+#define ION_DEVICE_ID_TI3410_EDGEPORT_1I	0x041	// Edgeport/1i- RS422 model
+
+// Ti based software switchable RS232/RS422/RS485 devices
+#define ION_DEVICE_ID_EDGEPORT_4S		0x042	// Edgeport/4s - software switchable model
+#define ION_DEVICE_ID_EDGEPORT_8S		0x043	// Edgeport/8s - software switchable model
+
+// Usb to Ethernet dongle
+#define ION_DEVICE_ID_EDGEPORT_E		0x0E0	// Edgeport/E Usb to Ethernet
+
+// Edgeport TI based devices
+#define ION_DEVICE_ID_TI_EDGEPORT_4		0x0201	// Edgeport/4 RS232
+#define ION_DEVICE_ID_TI_EDGEPORT_2		0x0205	// Edgeport/2 RS232
+#define ION_DEVICE_ID_TI_EDGEPORT_4I		0x0206	// Edgeport/4i RS422
+#define ION_DEVICE_ID_TI_EDGEPORT_2I		0x0207	// Edgeport/2i RS422/RS485
+#define ION_DEVICE_ID_TI_EDGEPORT_421		0x020C	// Edgeport/421 4 hub 2 RS232 + Parallel (lucent on a different hub port)
+#define ION_DEVICE_ID_TI_EDGEPORT_21		0x020D	// Edgeport/21 2 RS232 + Parallel (lucent on a different hub port)
+#define ION_DEVICE_ID_TI_EDGEPORT_8		0x020F	// Edgeport/8 (single-CPU)
+#define ION_DEVICE_ID_TI_EDGEPORT_1		0x0215	// Edgeport/1 RS232
+#define ION_DEVICE_ID_TI_EDGEPORT_42		0x0217	// Edgeport/42 4 hub 2 RS232
+#define ION_DEVICE_ID_TI_EDGEPORT_22I  		0x021A	// Edgeport/22I is an Edgeport/4 with ports 1&2 RS422 and ports 3&4 RS232
+#define ION_DEVICE_ID_TI_EDGEPORT_2C		0x021B	// Edgeport/2c RS232
+#define ION_DEVICE_ID_TI_EDGEPORT_221C		0x021C	// Edgeport/221c is a TI based Edgeport/2 with lucent chip and
+							// 2 external hub ports - Large I2C
+#define ION_DEVICE_ID_TI_EDGEPORT_22C		0x021D	// Edgeport/22c is a TI based Edgeport/2 with
+							// 2 external hub ports - Large I2C
+#define ION_DEVICE_ID_TI_EDGEPORT_21C		0x021E	// Edgeport/21c is a TI based Edgeport/2 with lucent chip
+
+// Generation 3 devices -- 3410 based edgport/1 (256 byte I2C) 
+#define ION_DEVICE_ID_TI_TI3410_EDGEPORT_1	0x240	// Edgeport/1 RS232
+#define ION_DEVICE_ID_TI_TI3410_EDGEPORT_1I	0x241	// Edgeport/1i- RS422 model
+
+// Ti based software switchable RS232/RS422/RS485 devices
+#define ION_DEVICE_ID_TI_EDGEPORT_4S		0x242	// Edgeport/4s - software switchable model
+#define ION_DEVICE_ID_IT_EDGEPORT_8S		0x243	// Edgeport/8s - software switchable model
+
+
+/************************************************************************
+ *
+ *                        Generation 4 devices
+ *
+ ************************************************************************/
+
+// Watchport based on 3410 both 1-wire and binary products (16K I2C)
+#define ION_DEVICE_ID_WP_UNSERIALIZED		0x300	// Watchport based on 3410 both 1-wire and binary products
+#define ION_DEVICE_ID_WP_PROXIMITY		0x301	// Watchport/P Discontinued
+#define ION_DEVICE_ID_WP_MOTION			0x302	// Watchport/M
+#define ION_DEVICE_ID_WP_MOISTURE		0x303	// Watchport/W
+#define ION_DEVICE_ID_WP_TEMPERATURE		0x304	// Watchport/T
+#define ION_DEVICE_ID_WP_HUMIDITY		0x305	// Watchport/H
+
+#define ION_DEVICE_ID_WP_POWER			0x306	// Watchport
+#define ION_DEVICE_ID_WP_LIGHT			0x307	// Watchport
+#define ION_DEVICE_ID_WP_RADIATION		0x308	// Watchport
+#define ION_DEVICE_ID_WP_ACCELERATION		0x309	// Watchport/A
+#define ION_DEVICE_ID_WP_DISTANCE		0x30A	// Watchport/D Discontinued
+#define ION_DEVICE_ID_WP_PROX_DIST		0x30B	// Watchport/D uses distance sensor
+							// Default to /P function
+
+#define ION_DEVICE_ID_PLUS_PWR_HP4CD		0x30C	// 5052 Plus Power HubPort/4CD+ (for Dell)
+#define ION_DEVICE_ID_PLUS_PWR_HP4C		0x30D	// 5052 Plus Power HubPort/4C+ 
+#define ION_DEVICE_ID_PLUS_PWR_PCI		0x30E	// 3410 Plus Power PCI Host Controller 4 port
+
+
+//
+// Definitions for AXIOHM USB product IDs
+//
+#define	USB_VENDOR_ID_AXIOHM			0x05D9	// Axiohm VID
+
+#define AXIOHM_DEVICE_ID_MASK			0xffff
+#define AXIOHM_DEVICE_ID_EPIC_A758		0xA758
+#define AXIOHM_DEVICE_ID_EPIC_A794		0xA794
+#define AXIOHM_DEVICE_ID_EPIC_A225		0xA225
+
+
+//
+// Definitions for NCR USB product IDs
+//
+#define	USB_VENDOR_ID_NCR			0x0404	// NCR VID
+
+#define NCR_DEVICE_ID_MASK			0xffff
+#define NCR_DEVICE_ID_EPIC_0202			0x0202
+#define NCR_DEVICE_ID_EPIC_0203			0x0203
+#define NCR_DEVICE_ID_EPIC_0310			0x0310
+#define NCR_DEVICE_ID_EPIC_0311			0x0311
+#define NCR_DEVICE_ID_EPIC_0312			0x0312
+
+
+//
+// Definitions for SYMBOL USB product IDs
+//
+#define USB_VENDOR_ID_SYMBOL			0x05E0	// Symbol VID
+#define SYMBOL_DEVICE_ID_MASK			0xffff
+#define SYMBOL_DEVICE_ID_KEYFOB			0x0700
+
+
+//
+// Definitions for other product IDs
 #define ION_DEVICE_ID_MT4X56USB			0x1403	// OEM device
 
-// BlackBox OEM devices
-#define ION_DEVICE_ID_BB_EDGEPORT_4		0x001	// Edgeport/4 RS232
-#define ION_DEVICE_ID_BB_EDGEPORT_4T		0x004	// Edgeport/4 RS232 for Telxon (aka "Fleetport")
-#define ION_DEVICE_ID_BB_EDGEPORT_2		0x005	// Edgeport/2 RS232
-#define ION_DEVICE_ID_BB_EDGEPORT_4I		0x006	// Edgeport/4 RS422
-#define ION_DEVICE_ID_BB_EDGEPORT_2I		0x007	// Edgeport/2 RS422/RS485
-#define	ION_DEVICE_ID_BB_EDGEPORT_421		0x00C	// Edgeport/421 Hub+RS232+Parallel
-#define	ION_DEVICE_ID_BB_EDGEPORT_21		0x00D	// Edgeport/21  RS232+Parallel
-#define ION_DEVICE_ID_BB_EDGEPORT_8_DUAL_CPU	0x00E	// Half of an Edgeport/8 (the kind with 2 EP/4s on 1 PCB)
-#define ION_DEVICE_ID_BB_EDGEPORT_8		0x00F	// Edgeport/8 (single-CPU)
-#define ION_DEVICE_ID_BB_EDGEPORT_2_DIN		0x010	// Edgeport/2 RS232 with Apple DIN connector
-#define ION_DEVICE_ID_BB_EDGEPORT_4_DIN		0x011	// Edgeport/4 RS232 with Apple DIN connector
-#define ION_DEVICE_ID_BB_EDGEPORT_16_DUAL_CPU	0x012	// Half of an Edgeport/16 (the kind with 2 EP/8s)
-#define ION_DEVICE_ID_BB_EDGEPORT_8I		0x014	// Edgeport/8 RS422 (single-CPU)
-
-
-/* Edgeport TI based devices */
-#define ION_DEVICE_ID_TI_EDGEPORT_4		0x0201	/* Edgeport/4 RS232 */
-#define ION_DEVICE_ID_TI_EDGEPORT_2		0x0205	/* Edgeport/2 RS232 */
-#define ION_DEVICE_ID_TI_EDGEPORT_4I		0x0206	/* Edgeport/4i RS422 */
-#define ION_DEVICE_ID_TI_EDGEPORT_2I		0x0207	/* Edgeport/2i RS422/RS485 */
-#define ION_DEVICE_ID_TI_EDGEPORT_421		0x020C	/* Edgeport/421 4 hub 2 RS232 + Parallel (lucent on a different hub port) */
-#define ION_DEVICE_ID_TI_EDGEPORT_21		0x020D	/* Edgeport/21 2 RS232 + Parallel (lucent on a different hub port) */
-#define ION_DEVICE_ID_TI_EDGEPORT_1		0x0215	/* Edgeport/1 RS232 */
-#define ION_DEVICE_ID_TI_EDGEPORT_42		0x0217	/* Edgeport/42 4 hub 2 RS232 */
-#define ION_DEVICE_ID_TI_EDGEPORT_22		0x021A	/* Edgeport/22  Edgeport/22I is an Edgeport/4 with ports 1&2 RS422 and ports 3&4 RS232 */
-#define ION_DEVICE_ID_TI_EDGEPORT_2C		0x021B	/* Edgeport/2c RS232 */
-
-#define ION_DEVICE_ID_TI_EDGEPORT_421_BOOT	0x0240	/* Edgeport/421 in boot mode */
-#define ION_DEVICE_ID_TI_EDGEPORT_421_DOWN	0x0241	/* Edgeport/421 in download mode first interface is 2 RS232 (Note that the second interface of this multi interface device should be a standard USB class 7 printer port) */
-#define ION_DEVICE_ID_TI_EDGEPORT_21_BOOT	0x0242	/* Edgeport/21 in boot mode */
-#define ION_DEVICE_ID_TI_EDGEPORT_21_DOWN	0x0243	/*Edgeport/42 in download mode: first interface is 2 RS232 (Note that the second interface of this multi interface device should be a standard USB class 7 printer port) */
 
+#define	GENERATION_ID_FROM_USB_PRODUCT_ID( ProductId )				\
+			( (__u16) ((ProductId >> 8) & (ION_GENERATION_MASK)) )
 
 #define	MAKE_USB_PRODUCT_ID( OemId, DeviceId )					\
 			( (__u16) (((OemId) << 10) || (DeviceId)) )
@@ -143,7 +234,7 @@
 
 // TxCredits value below which driver won't bother sending (to prevent too many small writes).
 // Send only if above 25%
-#define EDGE_FW_GET_TX_CREDITS_SEND_THRESHOLD(InitialCredit)	(max(((InitialCredit) / 4), EDGE_FW_BULK_MAX_PACKET_SIZE))
+#define EDGE_FW_GET_TX_CREDITS_SEND_THRESHOLD(InitialCredit, MaxPacketSize) (max( ((InitialCredit) / 4), (MaxPacketSize) ))
 
 #define	EDGE_FW_BULK_MAX_PACKET_SIZE		64	// Max Packet Size for Bulk In Endpoint (EP1)
 #define EDGE_FW_BULK_READ_BUFFER_SIZE		1024	// Size to use for Bulk reads
@@ -158,8 +249,8 @@
 // Definitions of I/O Networks vendor-specific requests
 // for default endpoint
 //
-//	bmRequestType = 00100000	Set vendor-specific, to device
-//	bmRequestType = 10100000	Get vendor-specific, to device
+//	bmRequestType = 01000000	Set vendor-specific, to device
+//	bmRequestType = 11000000	Get vendor-specific, to device
 //
 // These are the definitions for the bRequest field for the
 // above bmRequestTypes.
@@ -184,11 +275,87 @@
 #define USB_REQUEST_ION_ENABLE_SUSPEND	9	// Enable/Disable suspend feature
 						// (wValue != 0: Enable; wValue = 0: Disable)
 
+#define USB_REQUEST_ION_SEND_IOSP	10	// Send an IOSP command to the edgeport over the control pipe	
+#define USB_REQUEST_ION_RECV_IOSP	11	// Receive an IOSP command from the edgeport over the control pipe
+
+
+#define USB_REQUEST_ION_DIS_INT_TIMER	0x80	// Sent to Axiohm to enable/ disable
+						// interrupt token timer
+						// wValue = 1, enable (default)
+						// wValue = 0, disable
 
 //
 // Define parameter values for our vendor-specific commands
 //
 
+//
+// Edgeport Compatiblity Descriptor
+//
+// This descriptor is only returned by Edgeport-compatible devices
+// supporting the EPiC spec. True ION devices do not return this
+// descriptor, but instead return STALL on receipt of the
+// GET_EPIC_DESC command. The driver interprets a STALL to mean that
+// this is a "real" Edgeport.
+//
+
+struct edge_compatibility_bits
+{
+	// This __u32 defines which Vendor-specific commands/functionality
+	// the device supports on the default EP0 pipe.
+
+	__u32	VendEnableSuspend	:  1;	// 0001 Set if device supports ION_ENABLE_SUSPEND
+	__u32	VendUnused		: 31;	// Available for future expansion, must be 0
+
+	// This __u32 defines which IOSP commands are supported over the
+	// bulk pipe EP1.
+
+											// xxxx Set if device supports:
+	__u32	IOSPOpen		:  1;	// 0001	OPEN / OPEN_RSP (Currently must be 1)
+	__u32	IOSPClose		:  1;	// 0002	CLOSE
+	__u32	IOSPChase		:  1;	// 0004	CHASE / CHASE_RSP
+	__u32	IOSPSetRxFlow		:  1;	// 0008	SET_RX_FLOW
+	__u32	IOSPSetTxFlow		:  1;	// 0010	SET_TX_FLOW
+	__u32	IOSPSetXChar		:  1;	// 0020	SET_XON_CHAR/SET_XOFF_CHAR
+	__u32	IOSPRxCheck		:  1;	// 0040	RX_CHECK_REQ/RX_CHECK_RSP
+	__u32	IOSPSetClrBreak		:  1;	// 0080	SET_BREAK/CLEAR_BREAK
+	__u32	IOSPWriteMCR		:  1;	// 0100	MCR register writes (set/clr DTR/RTS)
+	__u32	IOSPWriteLCR		:  1;	// 0200	LCR register writes (wordlen/stop/parity)
+	__u32	IOSPSetBaudRate		:  1;	// 0400	setting Baud rate (writes to LCR.80h and DLL/DLM register)
+	__u32	IOSPDisableIntPipe	:  1;	// 0800 Do not use the interrupt pipe for TxCredits or RxButesAvailable
+	__u32	IOSPRxDataAvail		:  1;   // 1000 Return status of RX Fifo (Data available in Fifo)
+	__u32	IOSPTxPurge		:  1;	// 2000 Purge TXBuffer and/or Fifo in Edgeport hardware
+	__u32	IOSPUnused		: 18;	// Available for future expansion, must be 0
+
+	// This __u32 defines which 'general' features are supported
+
+	__u32	TrueEdgeport		:  1;	// 0001	Set if device is a 'real' Edgeport
+											// (Used only by driver, NEVER set by an EPiC device)
+	__u32	GenUnused		: 31;	// Available for future expansion, must be 0
+
+};
+
+struct edge_compatibility_descriptor
+{
+	__u8	Length;				// Descriptor Length (per USB spec)
+	__u8	DescType;			// Descriptor Type (per USB spec, =DEVICE type)
+	__u8	EpicVer;			// Version of EPiC spec supported
+											// (Currently must be 1)
+	__u8	NumPorts;			// Number of serial ports supported
+	__u8	iDownloadFile;			// Index of string containing download code filename
+											// 0=no download, FF=download compiled into driver.
+	__u8	Unused[ 3 ];			// Available for future expansion, must be 0
+											// (Currently must be 0).
+	__u8	MajorVersion;			// Firmware version: xx.
+	__u8	MinorVersion;			//  yy.
+	__le16	BuildNumber;			//  zzzz (LE format)
+
+	// The following structure contains __u32s, with each bit
+	// specifying whether the EPiC device supports the given
+	// command or functionality.
+
+	struct edge_compatibility_bits	Supports;
+
+};
 
 // Values for iDownloadFile
 #define	EDGE_DOWNLOAD_FILE_NONE		0	// No download requested
@@ -272,30 +439,30 @@
 
 	__u8	NumPorts;				// F08 Number of ports
 	__u8	DescDate[3];				// F09 MM/DD/YY when descriptor template was compiler,
-							//	   so host can track changes to USB-only descriptors.
+							//     so host can track changes to USB-only descriptors.
 
 	__u8	SerNumLength;				// F0C USB string descriptor len
 	__u8	SerNumDescType;				// F0D USB descriptor type (=STRING type)
-	__u16	SerialNumber[MAX_SERIALNUMBER_LEN];	// F0E "01-01-000100" Unicode Serial Number
+	__le16	SerialNumber[MAX_SERIALNUMBER_LEN];	// F0E "01-01-000100" Unicode Serial Number
 
 	__u8	AssemblyNumLength;			// F26 USB string descriptor len
 	__u8	AssemblyNumDescType;			// F27 USB descriptor type (=STRING type)
-	__u16	AssemblyNumber[MAX_ASSEMBLYNUMBER_LEN];	// F28 "350-1000-01-A " assembly number
+	__le16	AssemblyNumber[MAX_ASSEMBLYNUMBER_LEN];	// F28 "350-1000-01-A " assembly number
 
 	__u8	OemAssyNumLength;			// F44 USB string descriptor len
 	__u8	OemAssyNumDescType;			// F45 USB descriptor type (=STRING type)
-	__u16	OemAssyNumber[MAX_ASSEMBLYNUMBER_LEN];	// F46 "xxxxxxxxxxxxxx" OEM assembly number
+	__le16	OemAssyNumber[MAX_ASSEMBLYNUMBER_LEN];	// F46 "xxxxxxxxxxxxxx" OEM assembly number
 
 	__u8	ManufDateLength;			// F62 USB string descriptor len
 	__u8	ManufDateDescType;			// F63 USB descriptor type (=STRING type)
-	__u16	ManufDate[6];				// F64 "MMDDYY" manufacturing date
+	__le16	ManufDate[6];				// F64 "MMDDYY" manufacturing date
 
 	__u8	Reserved3[0x4D];			// F70 -- unused, set to 0 --
 
 	__u8	UartType;				// FBD Uart Type
 	__u8	IonPid;					// FBE Product ID, == LSB of USB DevDesc.PID
-							//     (Note: Edgeport/4s before 11/98 will have
-							//		00 here instead of 01)
+							//      (Note: Edgeport/4s before 11/98 will have
+							//       00 here instead of 01)
 	__u8	IonConfig;				// FBF Config byte for ION manufacturing use
 							// FBF end of structure, total len = 3C0h
 
@@ -312,7 +479,7 @@
 // both 00 and 01 values mean '654.
 #define MANUF_UART_EXAR_654_EARLY	0	// Exar 16C654 in Edgeport/4s before 11/98
 #define MANUF_UART_EXAR_654		1	// Exar 16C654
-#define MANUF_UART_EXAR_2852		2	// Exar 16C2852 
+#define MANUF_UART_EXAR_2852		2	// Exar 16C2852
 
 //
 // Note: The CpuRev and BoardRev values do not conform to manufacturing
@@ -334,25 +501,22 @@
 #define MANUF_BOARD_REV_GENERATION_2	0x20	// Second generaiton edgeport
 
 
-
-
 // Values of bottom 5 bits of CpuRev & BoardRev for
 // Implementation 1 (ie, 251+Netchip-based)
 #define	MANUF_CPU_REV_1			1	// C251TB Rev 1 (Need actual Intel rev here)
 
 #define MANUF_BOARD_REV_A		1	// First rev of 251+Netchip design
 
-
-
 #define	MANUF_SERNUM_LENGTH		sizeof(((struct edge_manuf_descriptor *)0)->SerialNumber)
 #define	MANUF_ASSYNUM_LENGTH		sizeof(((struct edge_manuf_descriptor *)0)->AssemblyNumber)
 #define	MANUF_OEMASSYNUM_LENGTH		sizeof(((struct edge_manuf_descriptor *)0)->OemAssyNumber)
 #define	MANUF_MANUFDATE_LENGTH		sizeof(((struct edge_manuf_descriptor *)0)->ManufDate)
 
-#define	MANUF_ION_CONFIG_MASTER		0x80	// 1=Master mode, 0=Normal
-#define	MANUF_ION_CONFIG_DIAG		0x40	// 1=Run h/w diags, 0=norm
-#define	MANUF_ION_CONFIG_DIAG_NO_LOOP	0x20	// As above but no ext loopback test
-
+#define	MANUF_ION_CONFIG_DIAG_NO_LOOP	0x20	// As below but no ext loopback test
+#define	MANUF_ION_CONFIG_DIAG		0x40	// 930 based device: 1=Run h/w diags, 0=norm
+						// TIUMP Device    : 1=IONSERIAL needs to run Final Test
+#define	MANUF_ION_CONFIG_MASTER		0x80	// 930 based device:  1=Master mode, 0=Normal
+						// TIUMP Device    :  1=First device on a multi TIUMP Device
 
 //
 // This structure describes parameters for the boot code, and
@@ -368,19 +532,19 @@
 	__u8		DescVer;		// C2 Desc version/format
 	__u8		Reserved1;		// C3 -- unused, set to 0 --
 
-	__u16		BootCodeLength;		// C4 Boot code goes from FF:0000 to FF:(len-1)
+	__le16		BootCodeLength;		// C4 Boot code goes from FF:0000 to FF:(len-1)
 						//	  (LE format)
 
 	__u8		MajorVersion;		// C6 Firmware version: xx.
 	__u8		MinorVersion;		// C7			yy.
-	__u16		BuildNumber;		// C8			zzzz (LE format)
+	__le16		BuildNumber;		// C8			zzzz (LE format)
 	
 	__u16		EnumRootDescTable;	// CA Root of ROM-based descriptor table
 	__u8		NumDescTypes;		// CC Number of supported descriptor types
 
 	__u8		Reserved4;		// CD Fix Compiler Packing
 
-	__u16		Capabilities;		// CE-CF Capabilities flags (LE format)
+	__le16		Capabilities;		// CE-CF Capabilities flags (LE format)
 	__u8		Reserved2[0x28];	// D0 -- unused, set to 0 --
 	__u8		UConfig0;		// F8 930-defined CPU configuration byte 0
 	__u8		UConfig1;		// F9 930-defined CPU configuration byte 1
@@ -398,23 +562,29 @@
 #define	BOOT_CAP_RESET_CMD	0x0001	// If set, boot correctly supports ION_RESET_DEVICE
 
 
-
 /************************************************************************
                  T I   U M P   D E F I N I T I O N S
  ***********************************************************************/
 
+// Chip definitions in I2C
+#define UMP5152			0x52
+#define UMP3410			0x10
+
+
 //************************************************************************
 //	TI I2C Format Definitions
 //************************************************************************
-#define I2C_DESC_TYPE_INFO_BASIC	1
-#define I2C_DESC_TYPE_FIRMWARE_BASIC	2
-#define I2C_DESC_TYPE_DEVICE		3
-#define I2C_DESC_TYPE_CONFIG		4
-#define I2C_DESC_TYPE_STRING		5
-#define I2C_DESC_TYPE_FIRMWARE_BLANK 	0xf2
+#define I2C_DESC_TYPE_INFO_BASIC	0x01
+#define I2C_DESC_TYPE_FIRMWARE_BASIC	0x02
+#define I2C_DESC_TYPE_DEVICE		0x03
+#define I2C_DESC_TYPE_CONFIG		0x04
+#define I2C_DESC_TYPE_STRING		0x05
+#define I2C_DESC_TYPE_FIRMWARE_AUTO	0x07	// for 3410 download
+#define I2C_DESC_TYPE_CONFIG_KLUDGE	0x14	// for 3410
+#define I2C_DESC_TYPE_WATCHPORT_VERSION	0x15	// firmware version number for watchport
+#define I2C_DESC_TYPE_WATCHPORT_CALIBRATION_DATA 0x16	// Watchport Calibration Data
 
-#define I2C_DESC_TYPE_MAX		5
-// 3410 may define types 6, 7 for other firmware downloads
+#define I2C_DESC_TYPE_FIRMWARE_BLANK	0xf2
 
 // Special section defined by ION
 #define I2C_DESC_TYPE_ION		0	// Not defined by TI
@@ -428,7 +598,9 @@
 	__u8	Data[0];		// Data starts here
 }__attribute__((packed));
 
-struct ti_i2c_firmware_rec 
+// for 5152 devices only (type 2 record)
+// for 3410 the version is stored in the WATCHPORT_FIRMWARE_VERSION descriptor
+struct ti_i2c_firmware_rec
 {
 	__u8	Ver_Major;		// Firmware Major version number
 	__u8	Ver_Minor;		// Firmware Minor version number
@@ -436,6 +608,14 @@
 }__attribute__((packed));
 
 
+struct watchport_firmware_version
+{
+// Added 2 bytes for version number
+	__u8	Version_Major;		//  Download Version (for Watchport)
+	__u8	Version_Minor;
+}__attribute__((packed));
+
+
 // Structure of header of download image in fw_down.h
 struct ti_i2c_image_header
 {
@@ -461,6 +641,15 @@
 } __attribute__((packed));
 
 
+// CPU / Board Rev Definitions
+#define TI_CPU_REV_5052			2	// 5052 based edgeports
+#define TI_CPU_REV_3410			3	// 3410 based edgeports
+
+#define TI_BOARD_REV_TI_EP		0	// Basic ti based edgeport
+#define TI_BOARD_REV_COMPACT		1	// Compact board
+#define TI_BOARD_REV_WATCHPORT		2	// Watchport
+
+
 #define TI_GET_CPU_REVISION(x)		(__u8)((((x)>>4)&0x0f))
 #define TI_GET_BOARD_REVISION(x)	(__u8)(((x)&0x0f))
 
@@ -469,20 +658,30 @@
 
 #define TI_MAX_I2C_SIZE			( 16 * 1024 )
 
-/* TI USB 5052 definitions */
+#define TI_MANUF_VERSION_0		0	
+
+// IonConig2 flags
+#define TI_CONFIG2_RS232		0x01
+#define TI_CONFIG2_RS422		0x02
+#define TI_CONFIG2_RS485		0x04
+#define TI_CONFIG2_SWITCHABLE		0x08
+
+#define TI_CONFIG2_WATCHPORT		0x10
+
+
 struct edge_ti_manuf_descriptor
 {
 	__u8 IonConfig;		//  Config byte for ION manufacturing use
 	__u8 IonConfig2;	//  Expansion
-	__u8 Version;		//  Verqsion
+	__u8 Version;		//  Version
 	__u8 CpuRev_BoardRev;	//  CPU revision level (0xF0) and Board Rev Level (0x0F)
 	__u8 NumPorts;		//  Number of ports	for this UMP
 	__u8 NumVirtualPorts;	//  Number of Virtual ports
 	__u8 HubConfig1;	//  Used to configure the Hub
 	__u8 HubConfig2;	//  Used to configure the Hub
 	__u8 TotalPorts;	//  Total Number of Com Ports for the entire device (All UMPs)
-	__u8 Reserved;
+	__u8 Reserved;		//  Reserved
 }__attribute__((packed));
 
 
-#endif		// if !defined()
+#endif		// if !defined(_USBVEND_H)
diff -Nru a/drivers/usb/serial/ipaq.c b/drivers/usb/serial/ipaq.c
--- a/drivers/usb/serial/ipaq.c	2004-10-18 14:56:49 -07:00
+++ b/drivers/usb/serial/ipaq.c	2004-10-18 14:56:49 -07:00
@@ -127,6 +127,7 @@
 	{ USB_DEVICE(TOSHIBA_VENDOR_ID, TOSHIBA_E740_ID) },
 	{ USB_DEVICE(TOSHIBA_VENDOR_ID, TOSHIBA_E335_ID) },
 	{ USB_DEVICE(HTC_VENDOR_ID, HTC_PRODUCT_ID) },
+	{ USB_DEVICE(HTC_VENDOR_ID, HTC_HIMALAYA_ID) },
 	{ USB_DEVICE(NEC_VENDOR_ID, NEC_PRODUCT_ID) },
 	{ USB_DEVICE(ASUS_VENDOR_ID, ASUS_A600_PRODUCT_ID) },
 	{ USB_DEVICE(ASUS_VENDOR_ID, ASUS_A620_PRODUCT_ID) },
@@ -188,6 +189,7 @@
 	usb_set_serial_port_data(port, priv);
 	priv->active = 0;
 	priv->queue_len = 0;
+	priv->free_len = 0;
 	INIT_LIST_HEAD(&priv->queue);
 	INIT_LIST_HEAD(&priv->freelist);
 
diff -Nru a/drivers/usb/serial/ipaq.h b/drivers/usb/serial/ipaq.h
--- a/drivers/usb/serial/ipaq.h	2004-10-18 14:55:54 -07:00
+++ b/drivers/usb/serial/ipaq.h	2004-10-18 14:55:54 -07:00
@@ -78,6 +78,7 @@
 
 #define HTC_VENDOR_ID		0x0bb4
 #define HTC_PRODUCT_ID		0x00ce
+#define HTC_HIMALAYA_ID		0x0a02
 
 #define NEC_VENDOR_ID		0x0409
 #define NEC_PRODUCT_ID		0x00d5
diff -Nru a/drivers/usb/serial/ir-usb.c b/drivers/usb/serial/ir-usb.c
--- a/drivers/usb/serial/ir-usb.c	2004-10-18 14:56:29 -07:00
+++ b/drivers/usb/serial/ir-usb.c	2004-10-18 14:56:29 -07:00
@@ -449,6 +449,10 @@
 			 */
 			tty = port->tty;
 
+			/*
+			 *	FIXME: must not do this in IRQ context,
+			 *	must honour TTY_DONT_FLIP
+			 */
 			tty->ldisc.receive_buf(
 				tty,
 				data+1,
diff -Nru a/drivers/usb/serial/keyspan_pda.c b/drivers/usb/serial/keyspan_pda.c
--- a/drivers/usb/serial/keyspan_pda.c	2004-10-18 14:56:33 -07:00
+++ b/drivers/usb/serial/keyspan_pda.c	2004-10-18 14:56:33 -07:00
@@ -186,13 +186,7 @@
 	wake_up_interruptible( &port->write_wait );
 
 	/* wake up line discipline */
-	if( (tty->flags & (1 << TTY_DO_WRITE_WAKEUP))
-	&& tty->ldisc.write_wakeup )
-		(tty->ldisc.write_wakeup)(tty);
-
-	/* wake up other tty processes */
-	wake_up_interruptible( &tty->write_wait );
-	/* For 2.2.16 backport -- wake_up_interruptible( &tty->poll_wait ); */
+	tty_wakeup(tty);
 }
 
 static void keyspan_pda_request_unthrottle( struct usb_serial *serial )
diff -Nru a/drivers/usb/serial/mct_u232.c b/drivers/usb/serial/mct_u232.c
--- a/drivers/usb/serial/mct_u232.c	2004-10-18 14:56:48 -07:00
+++ b/drivers/usb/serial/mct_u232.c	2004-10-18 14:56:48 -07:00
@@ -579,11 +579,7 @@
 
 	if (write_blocking) {
 		wake_up_interruptible(&port->write_wait);
-		if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
-		    tty->ldisc.write_wakeup)
-			(tty->ldisc.write_wakeup)(tty);
-		wake_up_interruptible(&tty->write_wait);
-		
+		tty_wakeup(tty);
 	} else {
 		/* from generic_write_bulk_callback */
 		schedule_work(&port->work);
diff -Nru a/drivers/usb/serial/pl2303.c b/drivers/usb/serial/pl2303.c
--- a/drivers/usb/serial/pl2303.c	2004-10-18 14:56:29 -07:00
+++ b/drivers/usb/serial/pl2303.c	2004-10-18 14:56:29 -07:00
@@ -659,7 +659,7 @@
 		state = BREAK_OFF;
 	else
 		state = BREAK_ON;
-	dbg("%s - turning break %s", state==BREAK_OFF ? "off" : "on", __FUNCTION__);
+	dbg("%s - turning break %s", __FUNCTION__, state==BREAK_OFF ? "off" : "on");
 
 	result = usb_control_msg (serial->dev, usb_sndctrlpipe (serial->dev, 0),
 				  BREAK_REQUEST, BREAK_REQUEST_TYPE, state, 
diff -Nru a/drivers/usb/serial/usb-serial.c b/drivers/usb/serial/usb-serial.c
--- a/drivers/usb/serial/usb-serial.c	2004-10-18 14:57:20 -07:00
+++ b/drivers/usb/serial/usb-serial.c	2004-10-18 14:57:20 -07:00
@@ -421,6 +421,63 @@
 	return;
 }
 
+static void destroy_serial(struct kref *kref)
+{
+	struct usb_serial *serial;
+	struct usb_serial_port *port;
+	int i;
+
+	serial = to_usb_serial(kref);
+
+	dbg ("%s - %s", __FUNCTION__, serial->type->name);
+
+	serial->type->shutdown(serial);
+
+	/* return the minor range that this device had */
+	return_serial(serial);
+
+	for (i = 0; i < serial->num_ports; ++i)
+		serial->port[i]->open_count = 0;
+
+	/* the ports are cleaned up and released in port_release() */
+	for (i = 0; i < serial->num_ports; ++i)
+		if (serial->port[i]->dev.parent != NULL) {
+			device_unregister(&serial->port[i]->dev);
+			serial->port[i] = NULL;
+		}
+
+	/* If this is a "fake" port, we have to clean it up here, as it will
+	 * not get cleaned up in port_release() as it was never registered with
+	 * the driver core */
+	if (serial->num_ports < serial->num_port_pointers) {
+		for (i = serial->num_ports; i < serial->num_port_pointers; ++i) {
+			port = serial->port[i];
+			if (!port)
+				continue;
+			if (port->read_urb) {
+				usb_unlink_urb(port->read_urb);
+				usb_free_urb(port->read_urb);
+			}
+			if (port->write_urb) {
+				usb_unlink_urb(port->write_urb);
+				usb_free_urb(port->write_urb);
+			}
+			if (port->interrupt_in_urb) {
+				usb_unlink_urb(port->interrupt_in_urb);
+				usb_free_urb(port->interrupt_in_urb);
+			}
+			kfree(port->bulk_in_buffer);
+			kfree(port->bulk_out_buffer);
+			kfree(port->interrupt_in_buffer);
+		}
+	}
+
+	usb_put_dev(serial->dev);
+
+	/* free up any memory that we allocated */
+	kfree (serial);
+}
+
 /*****************************************************************************
  * Driver tty interface functions
  *****************************************************************************/
@@ -465,7 +522,7 @@
 		if (retval) {
 			port->open_count = 0;
 			module_put(serial->type->owner);
-			kref_put(&serial->kref);
+			kref_put(&serial->kref, destroy_serial);
 		}
 	}
 bailout:
@@ -496,7 +553,7 @@
 	}
 
 	module_put(port->serial->type->owner);
-	kref_put(&port->serial->kref);
+	kref_put(&port->serial->kref, destroy_serial);
 }
 
 static int serial_write (struct tty_struct * tty, int from_user, const unsigned char *buf, int count)
@@ -654,13 +711,6 @@
 	;
 }
 
-static void serial_shutdown (struct usb_serial *serial)
-{
-	dbg ("%s", __FUNCTION__);
-
-	serial->type->shutdown(serial);
-}
-
 static int serial_read_proc (char *page, char **start, off_t off, int count, int *eof, void *data)
 {
 	struct usb_serial *serial;
@@ -694,7 +744,7 @@
 			begin += length;
 			length = 0;
 		}
-		kref_put(&serial->kref);
+		kref_put(&serial->kref, destroy_serial);
 	}
 	*eof = 1;
 done:
@@ -755,68 +805,7 @@
 	if (!tty)
 		return;
 
-	if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) && tty->ldisc.write_wakeup) {
-		dbg("%s - write wakeup call.", __FUNCTION__);
-		(tty->ldisc.write_wakeup)(tty);
-	}
-
-	wake_up_interruptible(&tty->write_wait);
-}
-
-static void destroy_serial(struct kref *kref)
-{
-	struct usb_serial *serial;
-	struct usb_serial_port *port;
-	int i;
-
-	serial = to_usb_serial(kref);
-
-	dbg ("%s - %s", __FUNCTION__, serial->type->name);
-	serial_shutdown (serial);
-
-	/* return the minor range that this device had */
-	return_serial(serial);
-
-	for (i = 0; i < serial->num_ports; ++i)
-		serial->port[i]->open_count = 0;
-
-	/* the ports are cleaned up and released in port_release() */
-	for (i = 0; i < serial->num_ports; ++i)
-		if (serial->port[i]->dev.parent != NULL) {
-			device_unregister(&serial->port[i]->dev);
-			serial->port[i] = NULL;
-		}
-
-	/* If this is a "fake" port, we have to clean it up here, as it will
-	 * not get cleaned up in port_release() as it was never registered with
-	 * the driver core */
-	if (serial->num_ports < serial->num_port_pointers) {
-		for (i = serial->num_ports; i < serial->num_port_pointers; ++i) {
-			port = serial->port[i];
-			if (!port)
-				continue;
-			if (port->read_urb) {
-				usb_unlink_urb(port->read_urb);
-				usb_free_urb(port->read_urb);
-			}
-			if (port->write_urb) {
-				usb_unlink_urb(port->write_urb);
-				usb_free_urb(port->write_urb);
-			}
-			if (port->interrupt_in_urb) {
-				usb_unlink_urb(port->interrupt_in_urb);
-				usb_free_urb(port->interrupt_in_urb);
-			}
-			kfree(port->bulk_in_buffer);
-			kfree(port->bulk_out_buffer);
-			kfree(port->interrupt_in_buffer);
-		}
-	}
-
-	usb_put_dev(serial->dev);
-
-	/* free up any memory that we allocated */
-	kfree (serial);
+	tty_wakeup(tty);
 }
 
 static void port_release(struct device *dev)
@@ -859,7 +848,7 @@
 	serial->interface = interface;
 	serial->vendor = dev->descriptor.idVendor;
 	serial->product = dev->descriptor.idProduct;
-	kref_init(&serial->kref, destroy_serial);
+	kref_init(&serial->kref);
 
 	return serial;
 }
@@ -1209,7 +1198,7 @@
 	if (serial) {
 		/* let the last holder of this object 
 		 * cause it to be cleaned up */
-		kref_put(&serial->kref);
+		kref_put(&serial->kref, destroy_serial);
 	}
 	dev_info(dev, "device disconnected\n");
 }
diff -Nru a/drivers/usb/serial/whiteheat.c b/drivers/usb/serial/whiteheat.c
--- a/drivers/usb/serial/whiteheat.c	2004-10-18 14:56:28 -07:00
+++ b/drivers/usb/serial/whiteheat.c	2004-10-18 14:56:28 -07:00
@@ -668,8 +668,7 @@
 
 	if (port->tty->driver->flush_buffer)
 		port->tty->driver->flush_buffer(port->tty);
-	if (port->tty->ldisc.flush_buffer)
-		port->tty->ldisc.flush_buffer(port->tty);
+	tty_ldisc_flush(port->tty);
 
 	firm_report_tx_done(port);
 
diff -Nru a/drivers/usb/storage/datafab.c b/drivers/usb/storage/datafab.c
--- a/drivers/usb/storage/datafab.c	2004-10-18 14:57:04 -07:00
+++ b/drivers/usb/storage/datafab.c	2004-10-18 14:57:04 -07:00
@@ -50,16 +50,19 @@
  * in that routine.
  */
 
+#include <linux/sched.h>
+#include <linux/errno.h>
+#include <linux/slab.h>
+
+#include <scsi/scsi.h>
+#include <scsi/scsi_cmnd.h>
+
 #include "transport.h"
 #include "protocol.h"
 #include "usb.h"
 #include "debug.h"
 #include "datafab.h"
 
-#include <linux/sched.h>
-#include <linux/errno.h>
-#include <linux/slab.h>
-
 static int datafab_determine_lun(struct us_data *us,
 				 struct datafab_info *info);
 
@@ -388,7 +391,7 @@
 
 
 static int datafab_handle_mode_sense(struct us_data *us,
-				     Scsi_Cmnd * srb, 
+				     struct scsi_cmnd * srb, 
 				     int sense_6)
 {
 	static unsigned char rw_err_page[12] = {
@@ -483,7 +486,7 @@
 	if (sense_6)
 		ptr[0] = i - 1;
 	else
-		((u16 *) ptr)[0] = cpu_to_be16(i - 2);
+		((__be16 *) ptr)[0] = cpu_to_be16(i - 2);
 	usb_stor_set_xfer_buf(ptr, i, srb);
 
 	return USB_STOR_TRANSPORT_GOOD;
@@ -498,7 +501,7 @@
 
 // Transport for the Datafab MDCFE-B
 //
-int datafab_transport(Scsi_Cmnd * srb, struct us_data *us)
+int datafab_transport(struct scsi_cmnd * srb, struct us_data *us)
 {
 	struct datafab_info *info;
 	int rc;
@@ -540,8 +543,8 @@
 
 		// build the reply
 		// we need the last sector, not the number of sectors
-		((u32 *) ptr)[0] = cpu_to_be32(info->sectors - 1);
-		((u32 *) ptr)[1] = cpu_to_be32(info->ssize);
+		((__be32 *) ptr)[0] = cpu_to_be32(info->sectors - 1);
+		((__be32 *) ptr)[1] = cpu_to_be32(info->ssize);
 		usb_stor_set_xfer_buf(ptr, 8, srb);
 
 		return USB_STOR_TRANSPORT_GOOD;
@@ -625,12 +628,12 @@
 
 	if (srb->cmnd[0] == MODE_SENSE) {
 		US_DEBUGP("datafab_transport:  MODE_SENSE_6 detected\n");
-		return datafab_handle_mode_sense(us, srb, TRUE);
+		return datafab_handle_mode_sense(us, srb, 1);
 	}
 
 	if (srb->cmnd[0] == MODE_SENSE_10) {
 		US_DEBUGP("datafab_transport:  MODE_SENSE_10 detected\n");
-		return datafab_handle_mode_sense(us, srb, FALSE);
+		return datafab_handle_mode_sense(us, srb, 0);
 	}
 
 	if (srb->cmnd[0] == ALLOW_MEDIUM_REMOVAL) {
diff -Nru a/drivers/usb/storage/datafab.h b/drivers/usb/storage/datafab.h
--- a/drivers/usb/storage/datafab.h	2004-10-18 14:56:49 -07:00
+++ b/drivers/usb/storage/datafab.h	2004-10-18 14:56:49 -07:00
@@ -24,7 +24,7 @@
 #ifndef _USB_DATAFAB_MDCFE_B_H
 #define _USB_DATAFAB_MDCFE_B_H
 
-extern int datafab_transport(Scsi_Cmnd *srb, struct us_data *us);
+extern int datafab_transport(struct scsi_cmnd *srb, struct us_data *us);
 
 struct datafab_info {
 	unsigned long   sectors;	// total sector count
diff -Nru a/drivers/usb/storage/debug.c b/drivers/usb/storage/debug.c
--- a/drivers/usb/storage/debug.c	2004-10-18 14:55:55 -07:00
+++ b/drivers/usb/storage/debug.c	2004-10-18 14:55:55 -07:00
@@ -44,9 +44,15 @@
  * 675 Mass Ave, Cambridge, MA 02139, USA.
  */
 
+#include <linux/cdrom.h>
+#include <scsi/scsi.h>
+#include <scsi/scsi_cmnd.h>
+
 #include "debug.h"
+#include "scsi.h"
+
 
-void usb_stor_show_command(Scsi_Cmnd *srb)
+void usb_stor_show_command(struct scsi_cmnd *srb)
 {
 	char *what = NULL;
 	int i;
diff -Nru a/drivers/usb/storage/debug.h b/drivers/usb/storage/debug.h
--- a/drivers/usb/storage/debug.h	2004-10-18 14:57:19 -07:00
+++ b/drivers/usb/storage/debug.h	2004-10-18 14:57:19 -07:00
@@ -46,13 +46,13 @@
 
 #include <linux/config.h>
 #include <linux/kernel.h>
-#include <linux/cdrom.h>
-#include "usb.h"
+
+struct scsi_cmnd;
 
 #define USB_STORAGE "usb-storage: "
 
 #ifdef CONFIG_USB_STORAGE_DEBUG
-void usb_stor_show_command(Scsi_Cmnd *srb);
+void usb_stor_show_command(struct scsi_cmnd *srb);
 void usb_stor_show_sense( unsigned char key,
 		unsigned char asc, unsigned char ascq );
 #define US_DEBUGP(x...) printk( KERN_DEBUG USB_STORAGE x )
diff -Nru a/drivers/usb/storage/dpcm.c b/drivers/usb/storage/dpcm.c
--- a/drivers/usb/storage/dpcm.c	2004-10-18 14:56:49 -07:00
+++ b/drivers/usb/storage/dpcm.c	2004-10-18 14:56:49 -07:00
@@ -30,6 +30,10 @@
  */
 
 #include <linux/config.h>
+#include <scsi/scsi.h>
+#include <scsi/scsi_cmnd.h>
+#include <scsi/scsi_device.h>
+
 #include "transport.h"
 #include "protocol.h"
 #include "usb.h"
@@ -41,7 +45,7 @@
  * Transport for the Microtech DPCM-USB
  *
  */
-int dpcm_transport(Scsi_Cmnd *srb, struct us_data *us)
+int dpcm_transport(struct scsi_cmnd *srb, struct us_data *us)
 {
   int ret;
 
diff -Nru a/drivers/usb/storage/dpcm.h b/drivers/usb/storage/dpcm.h
--- a/drivers/usb/storage/dpcm.h	2004-10-18 14:56:27 -07:00
+++ b/drivers/usb/storage/dpcm.h	2004-10-18 14:56:27 -07:00
@@ -29,6 +29,6 @@
 #ifndef _MICROTECH_DPCM_USB_H
 #define _MICROTECH_DPCM_USB_H
 
-extern int dpcm_transport(Scsi_Cmnd *srb, struct us_data *us);
+extern int dpcm_transport(struct scsi_cmnd *srb, struct us_data *us);
 
 #endif
diff -Nru a/drivers/usb/storage/freecom.c b/drivers/usb/storage/freecom.c
--- a/drivers/usb/storage/freecom.c	2004-10-18 14:57:04 -07:00
+++ b/drivers/usb/storage/freecom.c	2004-10-18 14:57:04 -07:00
@@ -29,12 +29,16 @@
  */
 
 #include <linux/config.h>
+#include <linux/hdreg.h>
+
+#include <scsi/scsi.h>
+#include <scsi/scsi_cmnd.h>
+
 #include "transport.h"
 #include "protocol.h"
 #include "usb.h"
 #include "debug.h"
 #include "freecom.h"
-#include "linux/hdreg.h"
 
 #ifdef CONFIG_USB_STORAGE_DEBUG
 static void pdump (void *, int);
@@ -55,14 +59,14 @@
 struct freecom_xfer_wrap {
 	u8    Type;		/* Command type. */
 	u8    Timeout;		/* Timeout in seconds. */
-	u32   Count;		/* Number of bytes to transfer. */
+	__le32   Count;		/* Number of bytes to transfer. */
 	u8    Pad[58];
 } __attribute__ ((packed));
 
 struct freecom_ide_out {
 	u8    Type;		/* Type + IDE register. */
 	u8    Pad;
-	u16   Value;		/* Value to write. */
+	__le16   Value;		/* Value to write. */
 	u8    Pad2[60];
 };
 
@@ -74,7 +78,7 @@
 struct freecom_status {
 	u8    Status;
 	u8    Reason;
-	u16   Count;
+	__le16   Count;
 	u8    Pad[60];
 };
 
@@ -105,7 +109,7 @@
 #define FCM_STATUS_PACKET_LENGTH	4
 
 static int
-freecom_readdata (Scsi_Cmnd *srb, struct us_data *us,
+freecom_readdata (struct scsi_cmnd *srb, struct us_data *us,
 		unsigned int ipipe, unsigned int opipe, int count)
 {
 	struct freecom_xfer_wrap *fxfr =
@@ -139,7 +143,7 @@
 }
 
 static int
-freecom_writedata (Scsi_Cmnd *srb, struct us_data *us,
+freecom_writedata (struct scsi_cmnd *srb, struct us_data *us,
 		int unsigned ipipe, unsigned int opipe, int count)
 {
 	struct freecom_xfer_wrap *fxfr =
@@ -176,7 +180,7 @@
  * Transport for the Freecom USB/IDE adaptor.
  *
  */
-int freecom_transport(Scsi_Cmnd *srb, struct us_data *us)
+int freecom_transport(struct scsi_cmnd *srb, struct us_data *us)
 {
 	struct freecom_cb_wrap *fcb;
 	struct freecom_status  *fst;
@@ -302,7 +306,7 @@
 	 * move in. */
 
 	switch (us->srb->sc_data_direction) {
-	case SCSI_DATA_READ:
+	case DMA_FROM_DEVICE:
 		/* catch bogus "read 0 length" case */
 		if (!length)
 			break;
@@ -334,7 +338,7 @@
 		US_DEBUGP("Transfer happy\n");
 		break;
 
-	case SCSI_DATA_WRITE:
+	case DMA_TO_DEVICE:
 		/* catch bogus "write 0 length" case */
 		if (!length)
 			break;
@@ -364,7 +368,7 @@
 		break;
 
 
-	case SCSI_DATA_NONE:
+	case DMA_NONE:
 		/* Easy, do nothing. */
 		break;
 
diff -Nru a/drivers/usb/storage/freecom.h b/drivers/usb/storage/freecom.h
--- a/drivers/usb/storage/freecom.h	2004-10-18 14:56:21 -07:00
+++ b/drivers/usb/storage/freecom.h	2004-10-18 14:56:21 -07:00
@@ -29,7 +29,7 @@
 #ifndef _FREECOM_USB_H
 #define _FREECOM_USB_H
 
-extern int freecom_transport(Scsi_Cmnd *srb, struct us_data *us);
+extern int freecom_transport(struct scsi_cmnd *srb, struct us_data *us);
 extern int usb_stor_freecom_reset(struct us_data *us);
 extern int freecom_init (struct us_data *us);
 
diff -Nru a/drivers/usb/storage/isd200.c b/drivers/usb/storage/isd200.c
--- a/drivers/usb/storage/isd200.c	2004-10-18 14:56:31 -07:00
+++ b/drivers/usb/storage/isd200.c	2004-10-18 14:56:31 -07:00
@@ -44,6 +44,16 @@
 
 /* Include files */
 
+#include <linux/jiffies.h>
+#include <linux/errno.h>
+#include <linux/slab.h>
+#include <linux/hdreg.h>
+#include <linux/ide.h>
+
+#include <scsi/scsi.h>
+#include <scsi/scsi_cmnd.h>
+#include <scsi/scsi_device.h>
+
 #include "transport.h"
 #include "protocol.h"
 #include "usb.h"
@@ -51,11 +61,6 @@
 #include "scsiglue.h"
 #include "isd200.h"
 
-#include <linux/jiffies.h>
-#include <linux/errno.h>
-#include <linux/slab.h>
-#include <linux/hdreg.h>
-#include <linux/ide.h>
 
 /* Timeout defines (in Seconds) */
 
@@ -290,8 +295,8 @@
  */
 
 struct read_capacity_data {
-	unsigned long LogicalBlockAddress;
-	unsigned long BytesPerBlock;
+	__be32 LogicalBlockAddress;
+	__be32 BytesPerBlock;
 };
 
 /*
@@ -349,7 +354,7 @@
  * RETURNS:
  *    void
  */
-static void isd200_build_sense(struct us_data *us, Scsi_Cmnd *srb)
+static void isd200_build_sense(struct us_data *us, struct scsi_cmnd *srb)
 {
 	struct isd200_info *info = (struct isd200_info *)us->extra;
 	struct sense_data *buf = (struct sense_data *) &srb->sense_buffer[0];
@@ -427,7 +432,7 @@
 		ata.generic.RegisterSelect =
 		  REG_CYLINDER_LOW | REG_CYLINDER_HIGH |
 		  REG_STATUS | REG_ERROR;
-		srb->sc_data_direction = SCSI_DATA_READ;
+		srb->sc_data_direction = DMA_FROM_DEVICE;
 		srb->request_buffer = pointer;
 		srb->request_bufflen = value;
 		break;
@@ -439,7 +444,7 @@
 					   ACTION_SELECT_5;
 		ata.generic.RegisterSelect = REG_DEVICE_HEAD;
 		ata.write.DeviceHeadByte = value;
-		srb->sc_data_direction = SCSI_DATA_NONE;
+		srb->sc_data_direction = DMA_NONE;
 		break;
 
 	case ACTION_RESET:
@@ -448,7 +453,7 @@
 					   ACTION_SELECT_3|ACTION_SELECT_4;
 		ata.generic.RegisterSelect = REG_DEVICE_CONTROL;
 		ata.write.DeviceControlByte = ATA_DC_RESET_CONTROLLER;
-		srb->sc_data_direction = SCSI_DATA_NONE;
+		srb->sc_data_direction = DMA_NONE;
 		break;
 
 	case ACTION_REENABLE:
@@ -457,7 +462,7 @@
 					   ACTION_SELECT_3|ACTION_SELECT_4;
 		ata.generic.RegisterSelect = REG_DEVICE_CONTROL;
 		ata.write.DeviceControlByte = ATA_DC_REENABLE_CONTROLLER;
-		srb->sc_data_direction = SCSI_DATA_NONE;
+		srb->sc_data_direction = DMA_NONE;
 		break;
 
 	case ACTION_SOFT_RESET:
@@ -466,14 +471,14 @@
 		ata.generic.RegisterSelect = REG_DEVICE_HEAD | REG_COMMAND;
 		ata.write.DeviceHeadByte = info->DeviceHead;
 		ata.write.CommandByte = WIN_SRST;
-		srb->sc_data_direction = SCSI_DATA_NONE;
+		srb->sc_data_direction = DMA_NONE;
 		break;
 
 	case ACTION_IDENTIFY:
 		US_DEBUGP("   isd200_action(IDENTIFY)\n");
 		ata.generic.RegisterSelect = REG_COMMAND;
 		ata.write.CommandByte = WIN_IDENTIFY;
-		srb->sc_data_direction = SCSI_DATA_READ;
+		srb->sc_data_direction = DMA_FROM_DEVICE;
 		srb->request_buffer = (void *) info->id;
 		srb->request_bufflen = sizeof(struct hd_driveid);
 		break;
@@ -535,7 +540,7 @@
  * the device and receive the response.
  */
 static void isd200_invoke_transport( struct us_data *us, 
-			      Scsi_Cmnd *srb, 
+			      struct scsi_cmnd *srb, 
 			      union ata_cdb *ataCdb )
 {
 	int need_auto_sense = 0;
@@ -839,7 +844,7 @@
 	unsigned long endTime;
 	struct isd200_info *info = (struct isd200_info *)us->extra;
 	unsigned char *regs = info->RegsBuf;
-	int recheckAsMaster = FALSE;
+	int recheckAsMaster = 0;
 
 	if ( detect )
 		endTime = jiffies + ISD200_ENUM_DETECT_TIMEOUT * HZ;
@@ -847,7 +852,7 @@
 		endTime = jiffies + ISD200_ENUM_BSY_TIMEOUT * HZ;
 
 	/* loop until we detect !BSY or timeout */
-	while(TRUE) {
+	while(1) {
 #ifdef CONFIG_USB_STORAGE_DEBUG
 		char* mstr = master_slave == ATA_ADDRESS_DEVHEAD_STD ?
 			"Master" : "Slave";
@@ -899,9 +904,9 @@
 			   itself okay as a master also
 			*/
 			if ((master_slave & ATA_ADDRESS_DEVHEAD_SLAVE) &&
-			    (recheckAsMaster == FALSE)) {
+			    !recheckAsMaster) {
 				US_DEBUGP("   Identified ATAPI device as slave.  Rechecking again as master\n");
-				recheckAsMaster = TRUE;
+				recheckAsMaster = 1;
 				master_slave = ATA_ADDRESS_DEVHEAD_STD;
 			} else {
 				US_DEBUGP("   Identified ATAPI device\n");
@@ -948,15 +953,15 @@
 	if (retStatus == ISD200_GOOD) {
 		int isslave;
 		/* master or slave? */
-		retStatus = isd200_try_enum( us, ATA_ADDRESS_DEVHEAD_STD, FALSE );
+		retStatus = isd200_try_enum( us, ATA_ADDRESS_DEVHEAD_STD, 0);
 		if (retStatus == ISD200_GOOD)
-			retStatus = isd200_try_enum( us, ATA_ADDRESS_DEVHEAD_SLAVE, FALSE );
+			retStatus = isd200_try_enum( us, ATA_ADDRESS_DEVHEAD_SLAVE, 0);
 
 		if (retStatus == ISD200_GOOD) {
 			retStatus = isd200_srst(us);
 			if (retStatus == ISD200_GOOD)
 				/* ata or atapi? */
-				retStatus = isd200_try_enum( us, ATA_ADDRESS_DEVHEAD_STD, TRUE );
+				retStatus = isd200_try_enum( us, ATA_ADDRESS_DEVHEAD_STD, 1);
 		}
 
 		isslave = (info->DeviceHead & ATA_ADDRESS_DEVHEAD_SLAVE) ? 1 : 0;
@@ -1011,7 +1016,8 @@
 			} else {
 				/* ATA Command Identify successful */
 				int i;
-				__u16 *src, *dest;
+				__be16 *src;
+				__u16 *dest;
 				ide_fix_driveid(id);
 
 				US_DEBUGP("   Identify Data Structure:\n");
@@ -1063,17 +1069,17 @@
 				}
 
 				/* Fill in vendor identification fields */
-				src = (__u16*)id->model;
+				src = (__be16*)id->model;
 				dest = (__u16*)info->InquiryData.VendorId;
 				for (i=0;i<4;i++)
 					dest[i] = be16_to_cpu(src[i]);
 
-				src = (__u16*)(id->model+8);
+				src = (__be16*)(id->model+8);
 				dest = (__u16*)info->InquiryData.ProductId;
 				for (i=0;i<8;i++)
 					dest[i] = be16_to_cpu(src[i]);
 
-				src = (__u16*)id->fw_rev;
+				src = (__be16*)id->fw_rev;
 				dest = (__u16*)info->InquiryData.ProductRevisionLevel;
 				for (i=0;i<2;i++)
 					dest[i] = be16_to_cpu(src[i]);
@@ -1121,15 +1127,15 @@
  * Translate SCSI commands to ATA commands.
  *
  * RETURNS:
- *    TRUE if the command needs to be sent to the transport layer
- *    FALSE otherwise
+ *    1 if the command needs to be sent to the transport layer
+ *    0 otherwise
  */
-static int isd200_scsi_to_ata(Scsi_Cmnd *srb, struct us_data *us,
+static int isd200_scsi_to_ata(struct scsi_cmnd *srb, struct us_data *us,
 			      union ata_cdb * ataCdb)
 {
 	struct isd200_info *info = (struct isd200_info *)us->extra;
 	struct hd_driveid *id = info->id;
-	int sendToTransport = TRUE;
+	int sendToTransport = 1;
 	unsigned char sectnum, head;
 	unsigned short cylinder;
 	unsigned long lba;
@@ -1147,7 +1153,7 @@
 		usb_stor_set_xfer_buf((unsigned char *) &info->InquiryData,
 				sizeof(info->InquiryData), srb);
 		srb->result = SAM_STAT_GOOD;
-		sendToTransport = FALSE;
+		sendToTransport = 0;
 		break;
 
 	case MODE_SENSE:
@@ -1167,7 +1173,7 @@
 		} else {
 			US_DEBUGP("   Media Status not supported, just report okay\n");
 			srb->result = SAM_STAT_GOOD;
-			sendToTransport = FALSE;
+			sendToTransport = 0;
 		}
 		break;
 
@@ -1185,7 +1191,7 @@
 		} else {
 			US_DEBUGP("   Media Status not supported, just report okay\n");
 			srb->result = SAM_STAT_GOOD;
-			sendToTransport = FALSE;
+			sendToTransport = 0;
 		}
 		break;
 
@@ -1209,15 +1215,14 @@
 		usb_stor_set_xfer_buf((unsigned char *) &readCapacityData,
 				sizeof(readCapacityData), srb);
 		srb->result = SAM_STAT_GOOD;
-		sendToTransport = FALSE;
+		sendToTransport = 0;
 	}
 	break;
 
 	case READ_10:
 		US_DEBUGP("   ATA OUT - SCSIOP_READ\n");
 
-		lba = *(unsigned long *)&srb->cmnd[2]; 
-		lba = cpu_to_be32(lba);
+		lba = be32_to_cpu(*(__be32 *)&srb->cmnd[2]);
 		blockCount = (unsigned long)srb->cmnd[7]<<8 | (unsigned long)srb->cmnd[8];
 
 		if (id->capability & CAPABILITY_LBA) {
@@ -1249,8 +1254,7 @@
 	case WRITE_10:
 		US_DEBUGP("   ATA OUT - SCSIOP_WRITE\n");
 
-		lba = *(unsigned long *)&srb->cmnd[2]; 
-		lba = cpu_to_be32(lba);
+		lba = be32_to_cpu(*(__be32 *)&srb->cmnd[2]);
 		blockCount = (unsigned long)srb->cmnd[7]<<8 | (unsigned long)srb->cmnd[8];
 
 		if (id->capability & CAPABILITY_LBA) {
@@ -1293,7 +1297,7 @@
 		} else {
 			US_DEBUGP("   Not removeable media, just report okay\n");
 			srb->result = SAM_STAT_GOOD;
-			sendToTransport = FALSE;
+			sendToTransport = 0;
 		}
 		break;
 
@@ -1319,14 +1323,14 @@
 		} else {
 			US_DEBUGP("   Nothing to do, just report okay\n");
 			srb->result = SAM_STAT_GOOD;
-			sendToTransport = FALSE;
+			sendToTransport = 0;
 		}
 		break;
 
 	default:
 		US_DEBUGP("Unsupported SCSI command - 0x%X\n", srb->cmnd[0]);
 		srb->result = DID_ERROR << 16;
-		sendToTransport = FALSE;
+		sendToTransport = 0;
 		break;
 	}
 
@@ -1424,9 +1428,9 @@
  *
  */
 
-void isd200_ata_command(Scsi_Cmnd *srb, struct us_data *us)
+void isd200_ata_command(struct scsi_cmnd *srb, struct us_data *us)
 {
-	int sendToTransport = TRUE;
+	int sendToTransport = 1;
 	union ata_cdb ataCdb;
 
 	/* Make sure driver was initialized */
diff -Nru a/drivers/usb/storage/isd200.h b/drivers/usb/storage/isd200.h
--- a/drivers/usb/storage/isd200.h	2004-10-18 14:56:13 -07:00
+++ b/drivers/usb/storage/isd200.h	2004-10-18 14:56:13 -07:00
@@ -25,7 +25,7 @@
 #ifndef _USB_ISD200_H
 #define _USB_ISD200_H
 
-extern void isd200_ata_command(Scsi_Cmnd *srb, struct us_data *us);
+extern void isd200_ata_command(struct scsi_cmnd *srb, struct us_data *us);
 extern int isd200_Initialization(struct us_data *us);
 
 #endif
diff -Nru a/drivers/usb/storage/jumpshot.c b/drivers/usb/storage/jumpshot.c
--- a/drivers/usb/storage/jumpshot.c	2004-10-18 14:55:54 -07:00
+++ b/drivers/usb/storage/jumpshot.c	2004-10-18 14:55:54 -07:00
@@ -47,15 +47,19 @@
   * in that routine.
   */
 
+#include <linux/sched.h>
+#include <linux/errno.h>
+#include <linux/slab.h>
+
+#include <scsi/scsi.h>
+#include <scsi/scsi_cmnd.h>
+
 #include "transport.h"
 #include "protocol.h"
 #include "usb.h"
 #include "debug.h"
 #include "jumpshot.h"
 
-#include <linux/sched.h>
-#include <linux/errno.h>
-#include <linux/slab.h>
 
 static inline int jumpshot_bulk_read(struct us_data *us,
 				     unsigned char *data, 
@@ -319,7 +323,7 @@
 }
 
 static int jumpshot_handle_mode_sense(struct us_data *us,
-				      Scsi_Cmnd * srb, 
+				      struct scsi_cmnd * srb, 
 				      int sense_6)
 {
 	static unsigned char rw_err_page[12] = {
@@ -409,7 +413,7 @@
 	if (sense_6)
 		ptr[0] = i - 1;
 	else
-		((u16 *) ptr)[0] = cpu_to_be16(i - 2);
+		((__be16 *) ptr)[0] = cpu_to_be16(i - 2);
 	usb_stor_set_xfer_buf(ptr, i, srb);
 
 	return USB_STOR_TRANSPORT_GOOD;
@@ -426,7 +430,7 @@
 
 // Transport for the Lexar 'Jumpshot'
 //
-int jumpshot_transport(Scsi_Cmnd * srb, struct us_data *us)
+int jumpshot_transport(struct scsi_cmnd * srb, struct us_data *us)
 {
 	struct jumpshot_info *info;
 	int rc;
@@ -471,8 +475,8 @@
 
 		// build the reply
 		//
-		((u32 *) ptr)[0] = cpu_to_be32(info->sectors - 1);
-		((u32 *) ptr)[1] = cpu_to_be32(info->ssize);
+		((__be32 *) ptr)[0] = cpu_to_be32(info->sectors - 1);
+		((__be32 *) ptr)[1] = cpu_to_be32(info->ssize);
 		usb_stor_set_xfer_buf(ptr, 8, srb);
 
 		return USB_STOR_TRANSPORT_GOOD;
@@ -551,12 +555,12 @@
 
 	if (srb->cmnd[0] == MODE_SENSE) {
 		US_DEBUGP("jumpshot_transport:  MODE_SENSE_6 detected\n");
-		return jumpshot_handle_mode_sense(us, srb, TRUE);
+		return jumpshot_handle_mode_sense(us, srb, 1);
 	}
 
 	if (srb->cmnd[0] == MODE_SENSE_10) {
 		US_DEBUGP("jumpshot_transport:  MODE_SENSE_10 detected\n");
-		return jumpshot_handle_mode_sense(us, srb, FALSE);
+		return jumpshot_handle_mode_sense(us, srb, 0);
 	}
 
 	if (srb->cmnd[0] == ALLOW_MEDIUM_REMOVAL) {
diff -Nru a/drivers/usb/storage/jumpshot.h b/drivers/usb/storage/jumpshot.h
--- a/drivers/usb/storage/jumpshot.h	2004-10-18 14:56:33 -07:00
+++ b/drivers/usb/storage/jumpshot.h	2004-10-18 14:56:33 -07:00
@@ -24,7 +24,7 @@
 #ifndef _USB_JUMPSHOT_H
 #define _USB_JUMPSHOT_H
 
-extern int jumpshot_transport(Scsi_Cmnd *srb, struct us_data *us);
+extern int jumpshot_transport(struct scsi_cmnd *srb, struct us_data *us);
 
 struct jumpshot_info {
    unsigned long   sectors;     // total sector count
diff -Nru a/drivers/usb/storage/protocol.c b/drivers/usb/storage/protocol.c
--- a/drivers/usb/storage/protocol.c	2004-10-18 14:55:54 -07:00
+++ b/drivers/usb/storage/protocol.c	2004-10-18 14:55:54 -07:00
@@ -45,6 +45,8 @@
  */
 
 #include <linux/highmem.h>
+#include <scsi/scsi.h>
+#include <scsi/scsi_cmnd.h>
 #include "protocol.h"
 #include "usb.h"
 #include "debug.h"
@@ -59,7 +61,7 @@
  * Fix-up the return data from an INQUIRY command to show 
  * ANSI SCSI rev 2 so we don't confuse the SCSI layers above us
  */
-static void fix_inquiry_data(Scsi_Cmnd *srb)
+static void fix_inquiry_data(struct scsi_cmnd *srb)
 {
 	unsigned char databuf[3];
 	unsigned int index, offset;
@@ -91,10 +93,10 @@
  * Fix-up the return data from a READ CAPACITY command. My Feiya reader
  * returns a value that is 1 too large.
  */
-static void fix_read_capacity(Scsi_Cmnd *srb)
+static void fix_read_capacity(struct scsi_cmnd *srb)
 {
 	unsigned int index, offset;
-	u32 c;
+	__be32 c;
 	unsigned long capacity;
 
 	/* verify that it's a READ CAPACITY command */
@@ -120,11 +122,11 @@
  * Protocol routines
  ***********************************************************************/
 
-void usb_stor_qic157_command(Scsi_Cmnd *srb, struct us_data *us)
+void usb_stor_qic157_command(struct scsi_cmnd *srb, struct us_data *us)
 {
 	/* Pad the ATAPI command with zeros 
 	 *
-	 * NOTE: This only works because a Scsi_Cmnd struct field contains
+	 * NOTE: This only works because a scsi_cmnd struct field contains
 	 * a unsigned char cmnd[16], so we know we have storage available
 	 */
 	for (; srb->cmd_len<12; srb->cmd_len++)
@@ -141,11 +143,11 @@
 	}
 }
 
-void usb_stor_ATAPI_command(Scsi_Cmnd *srb, struct us_data *us)
+void usb_stor_ATAPI_command(struct scsi_cmnd *srb, struct us_data *us)
 {
 	/* Pad the ATAPI command with zeros 
 	 *
-	 * NOTE: This only works because a Scsi_Cmnd struct field contains
+	 * NOTE: This only works because a scsi_cmnd struct field contains
 	 * a unsigned char cmnd[16], so we know we have storage available
 	 */
 
@@ -166,12 +168,12 @@
 }
 
 
-void usb_stor_ufi_command(Scsi_Cmnd *srb, struct us_data *us)
+void usb_stor_ufi_command(struct scsi_cmnd *srb, struct us_data *us)
 {
 	/* fix some commands -- this is a form of mode translation
 	 * UFI devices only accept 12 byte long commands 
 	 *
-	 * NOTE: This only works because a Scsi_Cmnd struct field contains
+	 * NOTE: This only works because a scsi_cmnd struct field contains
 	 * a unsigned char cmnd[16], so we know we have storage available
 	 */
 
@@ -213,7 +215,8 @@
 	}
 }
 
-void usb_stor_transparent_scsi_command(Scsi_Cmnd *srb, struct us_data *us)
+void usb_stor_transparent_scsi_command(struct scsi_cmnd *srb,
+				       struct us_data *us)
 {
 	/* send the command to the transport layer */
 	usb_stor_invoke_transport(srb, us);
@@ -241,7 +244,7 @@
  * pick up from where this one left off. */
 
 unsigned int usb_stor_access_xfer_buf(unsigned char *buffer,
-	unsigned int buflen, Scsi_Cmnd *srb, unsigned int *index,
+	unsigned int buflen, struct scsi_cmnd *srb, unsigned int *index,
 	unsigned int *offset, enum xfer_buf_dir dir)
 {
 	unsigned int cnt;
@@ -327,7 +330,7 @@
 /* Store the contents of buffer into srb's transfer buffer and set the
  * SCSI residue. */
 void usb_stor_set_xfer_buf(unsigned char *buffer,
-	unsigned int buflen, Scsi_Cmnd *srb)
+	unsigned int buflen, struct scsi_cmnd *srb)
 {
 	unsigned int index = 0, offset = 0;
 
diff -Nru a/drivers/usb/storage/protocol.h b/drivers/usb/storage/protocol.h
--- a/drivers/usb/storage/protocol.h	2004-10-18 14:56:29 -07:00
+++ b/drivers/usb/storage/protocol.h	2004-10-18 14:56:29 -07:00
@@ -41,9 +41,8 @@
 #ifndef _PROTOCOL_H_
 #define _PROTOCOL_H_
 
-#include <linux/blkdev.h>
-#include "scsi.h"
-#include "usb.h"
+struct scsi_cmnd;
+struct us_data;
 
 /* Sub Classes */
 
@@ -60,18 +59,19 @@
 #define US_SC_DEVICE	0xff		/* Use device's value */
 
 /* Protocol handling routines */
-extern void usb_stor_ATAPI_command(Scsi_Cmnd*, struct us_data*);
-extern void usb_stor_qic157_command(Scsi_Cmnd*, struct us_data*);
-extern void usb_stor_ufi_command(Scsi_Cmnd*, struct us_data*);
-extern void usb_stor_transparent_scsi_command(Scsi_Cmnd*, struct us_data*);
+extern void usb_stor_ATAPI_command(struct scsi_cmnd*, struct us_data*);
+extern void usb_stor_qic157_command(struct scsi_cmnd*, struct us_data*);
+extern void usb_stor_ufi_command(struct scsi_cmnd*, struct us_data*);
+extern void usb_stor_transparent_scsi_command(struct scsi_cmnd*,
+		struct us_data*);
 
-/* Scsi_Cmnd transfer buffer access utilities */
+/* struct scsi_cmnd transfer buffer access utilities */
 enum xfer_buf_dir	{TO_XFER_BUF, FROM_XFER_BUF};
 
 extern unsigned int usb_stor_access_xfer_buf(unsigned char *buffer,
-	unsigned int buflen, Scsi_Cmnd *srb, unsigned int *index,
+	unsigned int buflen, struct scsi_cmnd *srb, unsigned int *index,
 	unsigned int *offset, enum xfer_buf_dir dir);
 
 extern void usb_stor_set_xfer_buf(unsigned char *buffer,
-	unsigned int buflen, Scsi_Cmnd *srb);
+	unsigned int buflen, struct scsi_cmnd *srb);
 #endif
diff -Nru a/drivers/usb/storage/scsiglue.c b/drivers/usb/storage/scsiglue.c
--- a/drivers/usb/storage/scsiglue.c	2004-10-18 14:56:32 -07:00
+++ b/drivers/usb/storage/scsiglue.c	2004-10-18 14:56:32 -07:00
@@ -44,17 +44,23 @@
  * with this program; if not, write to the Free Software Foundation, Inc.,
  * 675 Mass Ave, Cambridge, MA 02139, USA.
  */
-#include "scsiglue.h"
-#include "usb.h"
-#include "debug.h"
-#include "transport.h"
-#include "protocol.h"
 
 #include <linux/slab.h>
 #include <linux/module.h>
+
+#include <scsi/scsi.h>
+#include <scsi/scsi_cmnd.h>
 #include <scsi/scsi_devinfo.h>
+#include <scsi/scsi_device.h>
+#include <scsi/scsi_eh.h>
 #include <scsi/scsi_host.h>
 
+#include "scsiglue.h"
+#include "usb.h"
+#include "debug.h"
+#include "transport.h"
+#include "protocol.h"
+
 /***********************************************************************
  * Host functions 
  ***********************************************************************/
@@ -92,17 +98,15 @@
 	 * the end, scatter-gather buffers follow page boundaries. */
 	blk_queue_dma_alignment(sdev->request_queue, (512 - 1));
 
-	/* Devices using Genesys Logic chips cause a lot of trouble for
-	 * high-speed transfers; they die unpredictably when given more
-	 * than 64 KB of data at a time.  If we detect such a device,
-	 * reduce the maximum transfer size to 64 KB = 128 sectors. */
-
-#define USB_VENDOR_ID_GENESYS	0x05e3		// Needs a standard location
-
+	/* According to the technical support people at Genesys Logic,
+	 * devices using their chips have problems transferring more than
+	 * 32 KB at a time.  In practice people have found that 64 KB
+	 * works okay and that's what Windows does.  But we'll be
+	 * conservative; people can always use the sysfs interface to
+	 * increase max_sectors. */
 	if (us->pusb_dev->descriptor.idVendor == USB_VENDOR_ID_GENESYS &&
-			us->pusb_dev->speed == USB_SPEED_HIGH &&
-			sdev->request_queue->max_sectors > 128)
-		blk_queue_max_sectors(sdev->request_queue, 128);
+			sdev->request_queue->max_sectors > 64)
+		blk_queue_max_sectors(sdev->request_queue, 64);
 
 	/* We can't put these settings in slave_alloc() because that gets
 	 * called before the device type is known.  Consequently these
@@ -146,7 +150,8 @@
 
 /* queue a command */
 /* This is always called with scsi_lock(srb->host) held */
-static int queuecommand( Scsi_Cmnd *srb , void (*done)(Scsi_Cmnd *))
+static int queuecommand(struct scsi_cmnd *srb,
+			void (*done)(struct scsi_cmnd *))
 {
 	struct us_data *us = (struct us_data *)srb->device->host->hostdata[0];
 
@@ -176,7 +181,7 @@
 
 /* Command abort */
 /* This is always called with scsi_lock(srb->host) held */
-static int command_abort( Scsi_Cmnd *srb )
+static int command_abort(struct scsi_cmnd *srb )
 {
 	struct Scsi_Host *host = srb->device->host;
 	struct us_data *us = (struct us_data *) host->hostdata[0];
@@ -223,7 +228,7 @@
 /* This invokes the transport reset mechanism to reset the state of the
  * device */
 /* This is always called with scsi_lock(srb->host) held */
-static int device_reset( Scsi_Cmnd *srb )
+static int device_reset(struct scsi_cmnd *srb)
 {
 	struct us_data *us = (struct us_data *)srb->device->host->hostdata[0];
 	int result;
@@ -258,7 +263,7 @@
 /* It refuses to work if there's more than one interface in
  * the device, so that other users are not affected. */
 /* This is always called with scsi_lock(srb->host) held */
-static int bus_reset( Scsi_Cmnd *srb )
+static int bus_reset(struct scsi_cmnd *srb)
 {
 	struct us_data *us = (struct us_data *)srb->device->host->hostdata[0];
 	int result;
@@ -444,10 +449,10 @@
 	 * periodically someone should test to see which setting is more
 	 * optimal.
 	 */
-	.use_clustering =		TRUE,
+	.use_clustering =		1,
 
 	/* emulated HBA */
-	.emulated =			TRUE,
+	.emulated =			1,
 
 	/* we do our own delay after a device or bus reset */
 	.skip_settle_delay =		1,
diff -Nru a/drivers/usb/storage/scsiglue.h b/drivers/usb/storage/scsiglue.h
--- a/drivers/usb/storage/scsiglue.h	2004-10-18 14:56:32 -07:00
+++ b/drivers/usb/storage/scsiglue.h	2004-10-18 14:56:32 -07:00
@@ -41,17 +41,15 @@
 #ifndef _SCSIGLUE_H_
 #define _SCSIGLUE_H_
 
-#include <linux/blkdev.h>
-#include "scsi.h"
 #include <scsi/scsi_host.h>
-#include "usb.h"
+
+struct us_data;
+struct scsi_cmnd;
 
 extern void usb_stor_report_device_reset(struct us_data *us);
 
 extern unsigned char usb_stor_sense_notready[18];
 extern unsigned char usb_stor_sense_invalidCDB[18];
 extern struct scsi_host_template usb_stor_host_template;
-extern int usb_stor_scsiSense10to6(Scsi_Cmnd*);
-extern int usb_stor_scsiSense6to10(Scsi_Cmnd*);
 
 #endif
diff -Nru a/drivers/usb/storage/sddr09.c b/drivers/usb/storage/sddr09.c
--- a/drivers/usb/storage/sddr09.c	2004-10-18 14:56:49 -07:00
+++ b/drivers/usb/storage/sddr09.c	2004-10-18 14:56:49 -07:00
@@ -41,16 +41,19 @@
  * EF: compute checksum (?)
  */
 
+#include <linux/sched.h>
+#include <linux/errno.h>
+#include <linux/slab.h>
+
+#include <scsi/scsi.h>
+#include <scsi/scsi_cmnd.h>
+
 #include "transport.h"
 #include "protocol.h"
 #include "usb.h"
 #include "debug.h"
 #include "sddr09.h"
 
-#include <linux/version.h>
-#include <linux/sched.h>
-#include <linux/errno.h>
-#include <linux/slab.h>
 
 #define short_pack(lsb,msb) ( ((u16)(lsb)) | ( ((u16)(msb))<<8 ) )
 #define LSB_of(s) ((s)&0xFF)
@@ -1401,7 +1404,7 @@
 /*
  * Transport for the Sandisk SDDR-09
  */
-int sddr09_transport(Scsi_Cmnd *srb, struct us_data *us)
+int sddr09_transport(struct scsi_cmnd *srb, struct us_data *us)
 {
 	static unsigned char sensekey = 0, sensecode = 0;
 	static unsigned char havefakesense = 0;
@@ -1486,11 +1489,11 @@
 
 		capacity = (info->lbact << info->blockshift) - 1;
 
-		((u32 *) ptr)[0] = cpu_to_be32(capacity);
+		((__be32 *) ptr)[0] = cpu_to_be32(capacity);
 
 		// Report page size
 
-		((u32 *) ptr)[1] = cpu_to_be32(info->pagesize);
+		((__be32 *) ptr)[1] = cpu_to_be32(info->pagesize);
 		usb_stor_set_xfer_buf(ptr, 8, srb);
 
 		return USB_STOR_TRANSPORT_GOOD;
@@ -1507,7 +1510,7 @@
 				  "mode page 0x%x\n", modepage);
 
 			memcpy(ptr, mode_page_01, sizeof(mode_page_01));
-			((u16*)ptr)[0] = cpu_to_be16(sizeof(mode_page_01) - 2);
+			((__be16*)ptr)[0] = cpu_to_be16(sizeof(mode_page_01) - 2);
 			ptr[3] = (info->flags & SDDR09_WP) ? 0x80 : 0;
 			usb_stor_set_xfer_buf(ptr, sizeof(mode_page_01), srb);
 			return USB_STOR_TRANSPORT_GOOD;
@@ -1581,13 +1584,13 @@
 	if (srb->request_bufflen == 0)
 		return USB_STOR_TRANSPORT_GOOD;
 
-	if (srb->sc_data_direction == SCSI_DATA_WRITE ||
-	    srb->sc_data_direction == SCSI_DATA_READ) {
-		unsigned int pipe = (srb->sc_data_direction == SCSI_DATA_WRITE)
+	if (srb->sc_data_direction == DMA_TO_DEVICE ||
+	    srb->sc_data_direction == DMA_FROM_DEVICE) {
+		unsigned int pipe = (srb->sc_data_direction == DMA_TO_DEVICE)
 				? us->send_bulk_pipe : us->recv_bulk_pipe;
 
 		US_DEBUGP("SDDR09: %s %d bytes\n",
-			  (srb->sc_data_direction == SCSI_DATA_WRITE) ?
+			  (srb->sc_data_direction == DMA_TO_DEVICE) ?
 			  "sending" : "receiving",
 			  srb->request_bufflen);
 
diff -Nru a/drivers/usb/storage/sddr09.h b/drivers/usb/storage/sddr09.h
--- a/drivers/usb/storage/sddr09.h	2004-10-18 14:56:17 -07:00
+++ b/drivers/usb/storage/sddr09.h	2004-10-18 14:56:17 -07:00
@@ -29,7 +29,7 @@
 
 /* Sandisk SDDR-09 stuff */
 
-extern int sddr09_transport(Scsi_Cmnd *srb, struct us_data *us);
+extern int sddr09_transport(struct scsi_cmnd *srb, struct us_data *us);
 
 struct sddr09_card_info {
 	unsigned long	capacity;	/* Size of card in bytes */
diff -Nru a/drivers/usb/storage/sddr55.c b/drivers/usb/storage/sddr55.c
--- a/drivers/usb/storage/sddr55.c	2004-10-18 14:56:28 -07:00
+++ b/drivers/usb/storage/sddr55.c	2004-10-18 14:56:28 -07:00
@@ -24,15 +24,19 @@
  * 675 Mass Ave, Cambridge, MA 02139, USA.
  */
 
+#include <linux/jiffies.h>
+#include <linux/errno.h>
+#include <linux/slab.h>
+
+#include <scsi/scsi.h>
+#include <scsi/scsi_cmnd.h>
+
 #include "transport.h"
 #include "protocol.h"
 #include "usb.h"
 #include "debug.h"
 #include "sddr55.h"
 
-#include <linux/jiffies.h>
-#include <linux/errno.h>
-#include <linux/slab.h>
 
 #define short_pack(lsb,msb) ( ((u16)(lsb)) | ( ((u16)(msb))<<8 ) )
 #define LSB_of(s) ((s)&0xFF)
@@ -74,7 +78,7 @@
 sddr55_bulk_transport(struct us_data *us, int direction,
 		      unsigned char *data, unsigned int len) {
 	struct sddr55_card_info *info = (struct sddr55_card_info *)us->extra;
-	unsigned int pipe = (direction == SCSI_DATA_READ) ?
+	unsigned int pipe = (direction == DMA_FROM_DEVICE) ?
 			us->recv_bulk_pipe : us->send_bulk_pipe;
 
 	if (!len)
@@ -99,7 +103,7 @@
 	command[5] = 0xB0;
 	command[7] = 0x80;
 	result = sddr55_bulk_transport(us,
-		SCSI_DATA_WRITE, command, 8);
+		DMA_TO_DEVICE, command, 8);
 
 	US_DEBUGP("Result for send_command in status %d\n",
 		result);
@@ -110,7 +114,7 @@
 	}
 
 	result = sddr55_bulk_transport(us,
-		SCSI_DATA_READ, status,	4);
+		DMA_FROM_DEVICE, status,	4);
 
 	/* expect to get short transfer if no card fitted */
 	if (result == USB_STOR_XFER_SHORT || result == USB_STOR_XFER_STALLED) {
@@ -139,7 +143,7 @@
 
 	/* now read status */
 	result = sddr55_bulk_transport(us,
-		SCSI_DATA_READ, status,	2);
+		DMA_FROM_DEVICE, status,	2);
 
 	if (result != USB_STOR_XFER_GOOD) {
 		set_sense_info (4, 0, 0);	/* hardware error */
@@ -215,7 +219,7 @@
 
 			/* send command */
 			result = sddr55_bulk_transport(us,
-				SCSI_DATA_WRITE, command, 8);
+				DMA_TO_DEVICE, command, 8);
 
 			US_DEBUGP("Result for send_command in read_data %d\n",
 				result);
@@ -227,7 +231,7 @@
 
 			/* read data */
 			result = sddr55_bulk_transport(us,
-				SCSI_DATA_READ, buffer, len);
+				DMA_FROM_DEVICE, buffer, len);
 
 			if (result != USB_STOR_XFER_GOOD) {
 				result = USB_STOR_TRANSPORT_ERROR;
@@ -236,7 +240,7 @@
 
 			/* now read status */
 			result = sddr55_bulk_transport(us,
-				SCSI_DATA_READ, status, 2);
+				DMA_FROM_DEVICE, status, 2);
 
 			if (result != USB_STOR_XFER_GOOD) {
 				result = USB_STOR_TRANSPORT_ERROR;
@@ -390,7 +394,7 @@
 
 		/* send command */
 		result = sddr55_bulk_transport(us,
-			SCSI_DATA_WRITE, command, 8);
+			DMA_TO_DEVICE, command, 8);
 
 		if (result != USB_STOR_XFER_GOOD) {
 			US_DEBUGP("Result for send_command in write_data %d\n",
@@ -404,7 +408,7 @@
 
 		/* send the data */
 		result = sddr55_bulk_transport(us,
-			SCSI_DATA_WRITE, buffer, len);
+			DMA_TO_DEVICE, buffer, len);
 
 		if (result != USB_STOR_XFER_GOOD) {
 			US_DEBUGP("Result for send_data in write_data %d\n",
@@ -417,7 +421,7 @@
 		}
 
 		/* now read status */
-		result = sddr55_bulk_transport(us, SCSI_DATA_READ, status, 6);
+		result = sddr55_bulk_transport(us, DMA_FROM_DEVICE, status, 6);
 
 		if (result != USB_STOR_XFER_GOOD) {
 			US_DEBUGP("Result for get_status in write_data %d\n",
@@ -483,7 +487,7 @@
 	memset(command, 0, 8);
 	command[5] = 0xB0;
 	command[7] = 0x84;
-	result = sddr55_bulk_transport(us, SCSI_DATA_WRITE, command, 8);
+	result = sddr55_bulk_transport(us, DMA_TO_DEVICE, command, 8);
 
 	US_DEBUGP("Result of send_control for device ID is %d\n",
 		result);
@@ -492,7 +496,7 @@
 		return USB_STOR_TRANSPORT_ERROR;
 
 	result = sddr55_bulk_transport(us,
-		SCSI_DATA_READ, content, 4);
+		DMA_FROM_DEVICE, content, 4);
 
 	if (result != USB_STOR_XFER_GOOD)
 		return USB_STOR_TRANSPORT_ERROR;
@@ -502,7 +506,7 @@
 
 	if (content[0] != 0xff)	{
     		result = sddr55_bulk_transport(us,
-			SCSI_DATA_READ, content, 2);
+			DMA_FROM_DEVICE, content, 2);
 	}
 
 	return USB_STOR_TRANSPORT_GOOD;
@@ -624,21 +628,21 @@
 	command[6] = numblocks * 2 / 256;
 	command[7] = 0x8A;
 
-	result = sddr55_bulk_transport(us, SCSI_DATA_WRITE, command, 8);
+	result = sddr55_bulk_transport(us, DMA_TO_DEVICE, command, 8);
 
 	if ( result != USB_STOR_XFER_GOOD) {
 		kfree (buffer);
 		return -1;
 	}
 
-	result = sddr55_bulk_transport(us, SCSI_DATA_READ, buffer, numblocks * 2);
+	result = sddr55_bulk_transport(us, DMA_FROM_DEVICE, buffer, numblocks * 2);
 
 	if ( result != USB_STOR_XFER_GOOD) {
 		kfree (buffer);
 		return -1;
 	}
 
-	result = sddr55_bulk_transport(us, SCSI_DATA_READ, command, 2);
+	result = sddr55_bulk_transport(us, DMA_FROM_DEVICE, command, 2);
 
 	if ( result != USB_STOR_XFER_GOOD) {
 		kfree (buffer);
@@ -734,7 +738,7 @@
 /*
  * Transport for the Sandisk SDDR-55
  */
-int sddr55_transport(Scsi_Cmnd *srb, struct us_data *us)
+int sddr55_transport(struct scsi_cmnd *srb, struct us_data *us)
 {
 	int result;
 	static unsigned char inquiry_response[8] = {
@@ -834,8 +838,8 @@
 		capacity /= PAGESIZE;
 		capacity--;
 
-		((u32 *) ptr)[0] = cpu_to_be32(capacity);
-		((u32 *) ptr)[1] = cpu_to_be32(PAGESIZE);
+		((__be32 *) ptr)[0] = cpu_to_be32(capacity);
+		((__be32 *) ptr)[1] = cpu_to_be32(PAGESIZE);
 		usb_stor_set_xfer_buf(ptr, 8, srb);
 
 		sddr55_read_map(us);
diff -Nru a/drivers/usb/storage/sddr55.h b/drivers/usb/storage/sddr55.h
--- a/drivers/usb/storage/sddr55.h	2004-10-18 14:56:49 -07:00
+++ b/drivers/usb/storage/sddr55.h	2004-10-18 14:56:49 -07:00
@@ -28,7 +28,7 @@
 
 /* Sandisk SDDR-55 stuff */
 
-extern int sddr55_transport(Scsi_Cmnd *srb, struct us_data *us);
+extern int sddr55_transport(struct scsi_cmnd *srb, struct us_data *us);
 extern int sddr55_reset(struct us_data *us);
 
 #endif
diff -Nru a/drivers/usb/storage/shuttle_usbat.c b/drivers/usb/storage/shuttle_usbat.c
--- a/drivers/usb/storage/shuttle_usbat.c	2004-10-18 14:55:54 -07:00
+++ b/drivers/usb/storage/shuttle_usbat.c	2004-10-18 14:55:54 -07:00
@@ -39,16 +39,20 @@
  * 675 Mass Ave, Cambridge, MA 02139, USA.
  */
 
+#include <linux/sched.h>
+#include <linux/errno.h>
+#include <linux/slab.h>
+#include <linux/cdrom.h>
+
+#include <scsi/scsi.h>
+#include <scsi/scsi_cmnd.h>
+
 #include "transport.h"
 #include "protocol.h"
 #include "usb.h"
 #include "debug.h"
 #include "shuttle_usbat.h"
 
-#include <linux/sched.h>
-#include <linux/errno.h>
-#include <linux/slab.h>
-
 #define short_pack(LSB,MSB) ( ((u16)(LSB)) | ( ((u16)(MSB))<<8 ) )
 #define LSB_of(s) ((s)&0xFF)
 #define MSB_of(s) ((s)>>8)
@@ -275,7 +279,7 @@
 			       int minutes)
 {
 	int result;
-	unsigned int pipe = (direction == SCSI_DATA_READ) ?
+	unsigned int pipe = (direction == DMA_FROM_DEVICE) ?
 			us->recv_bulk_pipe : us->send_bulk_pipe;
 
 	// Not really sure the 0x07, 0x17, 0xfc, 0xe7 is necessary here,
@@ -315,9 +319,9 @@
 		} else
 			cmdlen = 8;
 
-		command[cmdlen-8] = (direction==SCSI_DATA_WRITE ? 0x40 : 0xC0);
+		command[cmdlen-8] = (direction==DMA_TO_DEVICE ? 0x40 : 0xC0);
 		command[cmdlen-7] = access |
-				(direction==SCSI_DATA_WRITE ? 0x05 : 0x04);
+				(direction==DMA_TO_DEVICE ? 0x05 : 0x04);
 		command[cmdlen-6] = data_reg;
 		command[cmdlen-5] = status_reg;
 		command[cmdlen-4] = timeout;
@@ -355,7 +359,7 @@
 
 
 		//US_DEBUGP("Transfer %s %d bytes, sg buffers %d\n",
-		//	direction == SCSI_DATA_WRITE ? "out" : "in",
+		//	direction == DMA_TO_DEVICE ? "out" : "in",
 		//	len, use_sg);
 
 		result = usb_stor_bulk_transfer_sg(us,
@@ -388,7 +392,7 @@
 			 * the bulk output pipe only the first time.
 			 */
 
-			if (direction==SCSI_DATA_READ && i==0) {
+			if (direction==DMA_FROM_DEVICE && i==0) {
 				if (usb_stor_clear_halt(us,
 						us->send_bulk_pipe) < 0)
 					return USB_STOR_TRANSPORT_ERROR;
@@ -399,7 +403,7 @@
 			 */
 
  			result = usbat_read(us, USBAT_ATA, 
-				direction==SCSI_DATA_WRITE ? 0x17 : 0x0E, 
+				direction==DMA_TO_DEVICE ? 0x17 : 0x0E, 
 				status);
 
 			if (result!=USB_STOR_XFER_GOOD)
@@ -410,7 +414,7 @@
 				return USB_STOR_TRANSPORT_FAILED;
 
 			US_DEBUGP("Redoing %s\n",
-			  direction==SCSI_DATA_WRITE ? "write" : "read");
+			  direction==DMA_TO_DEVICE ? "write" : "read");
 
 		} else if (result != USB_STOR_XFER_GOOD)
 			return USB_STOR_TRANSPORT_ERROR;
@@ -420,7 +424,7 @@
 	}
 
 	US_DEBUGP("Bummer! %s bulk data 20 times failed.\n",
-		direction==SCSI_DATA_WRITE ? "Writing" : "Reading");
+		direction==DMA_TO_DEVICE ? "Writing" : "Reading");
 
 	return USB_STOR_TRANSPORT_FAILED;
 }
@@ -520,7 +524,7 @@
 static int usbat_handle_read10(struct us_data *us,
 			       unsigned char *registers,
 			       unsigned char *data,
-			       Scsi_Cmnd *srb)
+			       struct scsi_cmnd *srb)
 {
 	int result = USB_STOR_TRANSPORT_GOOD;
 	unsigned char *buffer;
@@ -537,7 +541,7 @@
 		result = usbat_rw_block_test(us, USBAT_ATA, 
 			registers, data, 19,
 			0x10, 0x17, 0xFD, 0x30,
-			SCSI_DATA_READ,
+			DMA_FROM_DEVICE,
 			srb->request_buffer, 
 			srb->request_bufflen, srb->use_sg, 1);
 
@@ -606,7 +610,7 @@
 		result = usbat_rw_block_test(us, USBAT_ATA, 
 			registers, data, 19,
 			0x10, 0x17, 0xFD, 0x30,
-			SCSI_DATA_READ,
+			DMA_FROM_DEVICE,
 			buffer,
 			len, 0, 1);
 
@@ -803,7 +807,7 @@
 /*
  * Transport for the HP 8200e
  */
-int hp8200e_transport(Scsi_Cmnd *srb, struct us_data *us)
+int hp8200e_transport(struct scsi_cmnd *srb, struct us_data *us)
 {
 	int result;
 	unsigned char *status = us->iobuf;
@@ -847,12 +851,12 @@
 	if (srb->cmnd[0] == TEST_UNIT_READY)
 		transferred = 0;
 
-	if (srb->sc_data_direction == SCSI_DATA_WRITE) {
+	if (srb->sc_data_direction == DMA_TO_DEVICE) {
 
 		result = usbat_rw_block_test(us, USBAT_ATA, 
 			registers, data, 19,
 			0x10, 0x17, 0xFD, 0x30,
-			SCSI_DATA_WRITE,
+			DMA_TO_DEVICE,
 			srb->request_buffer, 
 			len, srb->use_sg, 10);
 
@@ -900,7 +904,7 @@
 	// If there is response data to be read in 
 	// then do it here.
 
-	if (len != 0 && (srb->sc_data_direction == SCSI_DATA_READ)) {
+	if (len != 0 && (srb->sc_data_direction == DMA_FROM_DEVICE)) {
 
 		// How many bytes to read in? Check cylL register
 
diff -Nru a/drivers/usb/storage/shuttle_usbat.h b/drivers/usb/storage/shuttle_usbat.h
--- a/drivers/usb/storage/shuttle_usbat.h	2004-10-18 14:55:54 -07:00
+++ b/drivers/usb/storage/shuttle_usbat.h	2004-10-18 14:55:54 -07:00
@@ -53,7 +53,7 @@
 #define USBAT_UIO_ADPRST	0x01 // Reset SCM chip
 
 /* HP 8200e stuff */
-extern int hp8200e_transport(Scsi_Cmnd *srb, struct us_data *us);
+extern int hp8200e_transport(struct scsi_cmnd *srb, struct us_data *us);
 extern int init_8200e(struct us_data *us);
 
 #endif
diff -Nru a/drivers/usb/storage/transport.c b/drivers/usb/storage/transport.c
--- a/drivers/usb/storage/transport.c	2004-10-18 14:56:28 -07:00
+++ b/drivers/usb/storage/transport.c	2004-10-18 14:56:28 -07:00
@@ -46,15 +46,20 @@
  */
 
 #include <linux/config.h>
+#include <linux/sched.h>
+#include <linux/errno.h>
+#include <linux/slab.h>
+
+#include <scsi/scsi.h>
+#include <scsi/scsi_cmnd.h>
+#include <scsi/scsi_device.h>
+
 #include "transport.h"
 #include "protocol.h"
 #include "scsiglue.h"
 #include "usb.h"
 #include "debug.h"
 
-#include <linux/sched.h>
-#include <linux/errno.h>
-#include <linux/slab.h>
 
 /***********************************************************************
  * Data transfer routines
@@ -260,9 +265,7 @@
 		USB_ENDPOINT_HALT, endp,
 		NULL, 0, 3*HZ);
 
-	/* reset the toggles and endpoint flags */
-	usb_endpoint_running(us->pusb_dev, usb_pipeendpoint(pipe),
-		usb_pipeout(pipe));
+	/* reset the endpoint toggle */
 	usb_settoggle(us->pusb_dev, usb_pipeendpoint(pipe),
 		usb_pipeout(pipe), 0);
 
@@ -522,7 +525,7 @@
  * This is used by the protocol layers to actually send the message to
  * the device and receive the response.
  */
-void usb_stor_invoke_transport(Scsi_Cmnd *srb, struct us_data *us)
+void usb_stor_invoke_transport(struct scsi_cmnd *srb, struct us_data *us)
 {
 	int need_auto_sense;
 	int result;
@@ -569,7 +572,7 @@
 	 * can signal most data-in errors by stalling the bulk-in pipe.
 	 */
 	if ((us->protocol == US_PR_CB || us->protocol == US_PR_DPCM_USB) &&
-			srb->sc_data_direction != SCSI_DATA_READ) {
+			srb->sc_data_direction != DMA_FROM_DEVICE) {
 		US_DEBUGP("-- CB transport device requiring auto-sense\n");
 		need_auto_sense = 1;
 	}
@@ -629,7 +632,7 @@
 
 		/* set the transfer direction */
 		old_sc_data_direction = srb->sc_data_direction;
-		srb->sc_data_direction = SCSI_DATA_READ;
+		srb->sc_data_direction = DMA_FROM_DEVICE;
 
 		/* use the new buffer we have */
 		old_request_buffer = srb->request_buffer;
@@ -749,7 +752,7 @@
  * Control/Bulk/Interrupt transport
  */
 
-int usb_stor_CBI_transport(Scsi_Cmnd *srb, struct us_data *us)
+int usb_stor_CBI_transport(struct scsi_cmnd *srb, struct us_data *us)
 {
 	unsigned int transfer_length = srb->request_bufflen;
 	unsigned int pipe = 0;
@@ -778,7 +781,7 @@
 	/* DATA STAGE */
 	/* transfer the data payload for this command, if one exists*/
 	if (transfer_length) {
-		pipe = srb->sc_data_direction == SCSI_DATA_READ ? 
+		pipe = srb->sc_data_direction == DMA_FROM_DEVICE ? 
 				us->recv_bulk_pipe : us->send_bulk_pipe;
 		result = usb_stor_bulk_transfer_sg(us, pipe,
 					srb->request_buffer, transfer_length,
@@ -849,7 +852,7 @@
 /*
  * Control/Bulk transport
  */
-int usb_stor_CB_transport(Scsi_Cmnd *srb, struct us_data *us)
+int usb_stor_CB_transport(struct scsi_cmnd *srb, struct us_data *us)
 {
 	unsigned int transfer_length = srb->request_bufflen;
 	int result;
@@ -877,7 +880,7 @@
 	/* DATA STAGE */
 	/* transfer the data payload for this command, if one exists*/
 	if (transfer_length) {
-		unsigned int pipe = srb->sc_data_direction == SCSI_DATA_READ ? 
+		unsigned int pipe = srb->sc_data_direction == DMA_FROM_DEVICE ? 
 				us->recv_bulk_pipe : us->send_bulk_pipe;
 		result = usb_stor_bulk_transfer_sg(us, pipe,
 					srb->request_buffer, transfer_length,
@@ -908,6 +911,7 @@
 	int result;
 
 	/* issue the command */
+	us->iobuf[0] = 0;
 	result = usb_stor_control_msg(us, us->recv_ctrl_pipe,
 				 US_BULK_GET_MAX_LUN, 
 				 USB_DIR_IN | USB_TYPE_CLASS | 
@@ -918,7 +922,7 @@
 		  result, us->iobuf[0]);
 
 	/* if we have a successful request, return the result */
-	if (result == 1)
+	if (result >= 0)
 		return us->iobuf[0];
 
 	/* 
@@ -939,7 +943,7 @@
 	return -1;
 }
 
-int usb_stor_Bulk_transport(Scsi_Cmnd *srb, struct us_data *us)
+int usb_stor_Bulk_transport(struct scsi_cmnd *srb, struct us_data *us)
 {
 	struct bulk_cb_wrap *bcb = (struct bulk_cb_wrap *) us->iobuf;
 	struct bulk_cs_wrap *bcs = (struct bulk_cs_wrap *) us->iobuf;
@@ -952,7 +956,7 @@
 	/* set up the command wrapper */
 	bcb->Signature = cpu_to_le32(US_BULK_CB_SIGN);
 	bcb->DataTransferLength = cpu_to_le32(transfer_length);
-	bcb->Flags = srb->sc_data_direction == SCSI_DATA_READ ? 1 << 7 : 0;
+	bcb->Flags = srb->sc_data_direction == DMA_FROM_DEVICE ? 1 << 7 : 0;
 	bcb->Tag = srb->serial_number;
 	bcb->Lun = srb->device->lun;
 	if (us->flags & US_FL_SCM_MULT_TARG)
@@ -977,8 +981,14 @@
 
 	/* DATA STAGE */
 	/* send/receive data payload, if there is any */
+
+	/* Genesys Logic interface chips need a 100us delay between the
+	 * command phase and the data phase */
+	if (us->pusb_dev->descriptor.idVendor == USB_VENDOR_ID_GENESYS)
+		udelay(100);
+
 	if (transfer_length) {
-		unsigned int pipe = srb->sc_data_direction == SCSI_DATA_READ ? 
+		unsigned int pipe = srb->sc_data_direction == DMA_FROM_DEVICE ? 
 				us->recv_bulk_pipe : us->send_bulk_pipe;
 		result = usb_stor_bulk_transfer_sg(us, pipe,
 					srb->request_buffer, transfer_length,
diff -Nru a/drivers/usb/storage/transport.h b/drivers/usb/storage/transport.h
--- a/drivers/usb/storage/transport.h	2004-10-18 14:56:28 -07:00
+++ b/drivers/usb/storage/transport.h	2004-10-18 14:56:28 -07:00
@@ -44,7 +44,8 @@
 #include <linux/config.h>
 #include <linux/blkdev.h>
 #include "usb.h"
-#include "scsi.h"
+
+struct scsi_cmnd;
 
 /* Protocols */
 
@@ -82,9 +83,9 @@
 
 /* command block wrapper */
 struct bulk_cb_wrap {
-	__u32	Signature;		/* contains 'USBC' */
+	__le32	Signature;		/* contains 'USBC' */
 	__u32	Tag;			/* unique per command id */
-	__u32	DataTransferLength;	/* size of data */
+	__le32	DataTransferLength;	/* size of data */
 	__u8	Flags;			/* direction in bit 0 */
 	__u8	Lun;			/* LUN normally 0 */
 	__u8	Length;			/* of of the CDB */
@@ -98,9 +99,9 @@
 
 /* command status wrapper */
 struct bulk_cs_wrap {
-	__u32	Signature;		/* should = 'USBS' */
+	__le32	Signature;		/* should = 'USBS' */
 	__u32	Tag;			/* same as original command */
-	__u32	Residue;		/* amount not transferred */
+	__le32	Residue;		/* amount not transferred */
 	__u8	Status;			/* see below */
 	__u8	Filler[18];
 };
@@ -150,16 +151,16 @@
 
 #define US_CBI_ADSC		0
 
-extern int usb_stor_CBI_transport(Scsi_Cmnd*, struct us_data*);
+extern int usb_stor_CBI_transport(struct scsi_cmnd *, struct us_data*);
 
-extern int usb_stor_CB_transport(Scsi_Cmnd*, struct us_data*);
+extern int usb_stor_CB_transport(struct scsi_cmnd *, struct us_data*);
 extern int usb_stor_CB_reset(struct us_data*);
 
-extern int usb_stor_Bulk_transport(Scsi_Cmnd*, struct us_data*);
+extern int usb_stor_Bulk_transport(struct scsi_cmnd *, struct us_data*);
 extern int usb_stor_Bulk_max_lun(struct us_data*);
 extern int usb_stor_Bulk_reset(struct us_data*);
 
-extern void usb_stor_invoke_transport(Scsi_Cmnd*, struct us_data*);
+extern void usb_stor_invoke_transport(struct scsi_cmnd *, struct us_data*);
 extern void usb_stor_stop_transport(struct us_data*);
 
 extern int usb_stor_control_msg(struct us_data *us, unsigned int pipe,
diff -Nru a/drivers/usb/storage/unusual_devs.h b/drivers/usb/storage/unusual_devs.h
--- a/drivers/usb/storage/unusual_devs.h	2004-10-18 14:56:49 -07:00
+++ b/drivers/usb/storage/unusual_devs.h	2004-10-18 14:56:49 -07:00
@@ -45,11 +45,6 @@
  *
  */
 
-UNUSUAL_DEV(  0x03ee, 0x0000, 0x0000, 0x0245, 
-		"Mitsumi",
-		"CD-R/RW Drive",
-		US_SC_8020, US_PR_CBI, NULL, 0), 
-
 UNUSUAL_DEV(  0x03ee, 0x6901, 0x0000, 0x0100,
 		"Mitsumi",
 		"USB FDD",
@@ -373,6 +368,15 @@
 		US_SC_DEVICE,  US_PR_DEVICE, NULL,
 		US_FL_SINGLE_LUN),
 
+/* Reported by Johann Cardon <johann.cardon@free.fr>
+ * This entry is needed only because the device reports
+ * bInterfaceClass = 0xff (vendor-specific)
+ */
+UNUSUAL_DEV(  0x057b, 0x0022, 0x0000, 0x9999, 
+		"Y-E Data",
+		"Silicon Media R/W",
+		US_SC_DEVICE, US_PR_DEVICE, NULL, 0),
+
 /* Fabrizio Fellini <fello@libero.it> */
 UNUSUAL_DEV(  0x0595, 0x4343, 0x0000, 0x2210,
 		"Fujifilm",
@@ -384,11 +388,15 @@
 		"USB Hard Disk",
 		US_SC_RBC, US_PR_CB, NULL, 0 ), 
 
-/* Submitted by Jol Bourquard <numlock@freesurf.ch> */
+/* Submitted by Joel Bourquard <numlock@freesurf.ch>
+ * Some versions of this device need the SubClass and Protocol overrides
+ * while others don't.
+ */
 UNUSUAL_DEV(  0x05ab, 0x0060, 0x1104, 0x1110,
 		"In-System",
 		"PyroGate External CD-ROM Enclosure (FCD-523)",
-		US_SC_SCSI, US_PR_BULK, NULL, 0 ),
+		US_SC_SCSI, US_PR_BULK, NULL,
+		US_FL_NEED_OVERRIDE ),
 
 #ifdef CONFIG_USB_STORAGE_ISD200
 UNUSUAL_DEV(  0x05ab, 0x0031, 0x0100, 0x0110,
@@ -482,6 +490,13 @@
 		US_FL_SINGLE_LUN ),
 #endif
 
+/* Reported by Darsen Lu <darsen@micro.ee.nthu.edu.tw> */
+UNUSUAL_DEV( 0x066f, 0x8000, 0x0001, 0x0001,
+		"SigmaTel",
+		"USBMSC Audio Player",
+		US_SC_DEVICE, US_PR_DEVICE, NULL,
+		US_FL_FIX_CAPACITY ),
+
 /* Submitted by Benny Sjostrand <benny@hostmobility.com> */
 UNUSUAL_DEV( 0x0686, 0x4011, 0x0001, 0x0001,
 		"Minolta",
@@ -510,11 +525,13 @@
 		US_SC_SCSI, US_PR_CB, NULL,
 		US_FL_SINGLE_LUN ),
 
+#if !defined(CONFIG_BLK_DEV_UB) && !defined(CONFIG_BLK_DEV_UB_MODULE)
 UNUSUAL_DEV(  0x0781, 0x0002, 0x0009, 0x0009, 
 		"Sandisk",
 		"ImageMate SDDR-31",
 		US_SC_DEVICE, US_PR_DEVICE, NULL,
 		US_FL_IGNORE_SER ),
+#endif
 
 UNUSUAL_DEV(  0x0781, 0x0100, 0x0100, 0x0100,
 		"Sandisk",
@@ -685,7 +702,7 @@
 		"Trumpion",
 		"t33520 USB Flash Card Controller",
 		US_SC_DEVICE, US_PR_BULK, NULL,
-		US_FL_MODE_XLATE),
+		US_FL_NEED_OVERRIDE | US_FL_MODE_XLATE),
 
 /* Trumpion Microelectronics MP3 player (felipe_alfaro@linuxmail.org) */
 UNUSUAL_DEV( 0x090a, 0x1200, 0x0000, 0x9999,
diff -Nru a/drivers/usb/storage/usb.c b/drivers/usb/storage/usb.c
--- a/drivers/usb/storage/usb.c	2004-10-18 14:56:27 -07:00
+++ b/drivers/usb/storage/usb.c	2004-10-18 14:56:27 -07:00
@@ -50,6 +50,11 @@
 #include <linux/config.h>
 #include <linux/sched.h>
 #include <linux/errno.h>
+
+#include <scsi/scsi.h>
+#include <scsi/scsi_cmnd.h>
+#include <scsi/scsi_device.h>
+
 #include "usb.h"
 #include "scsiglue.h"
 #include "transport.h"
@@ -133,7 +138,9 @@
 	{ USB_INTERFACE_INFO(USB_CLASS_MASS_STORAGE, US_SC_QIC, US_PR_BULK) },
 	{ USB_INTERFACE_INFO(USB_CLASS_MASS_STORAGE, US_SC_UFI, US_PR_BULK) },
 	{ USB_INTERFACE_INFO(USB_CLASS_MASS_STORAGE, US_SC_8070, US_PR_BULK) },
+#if !defined(CONFIG_BLK_DEV_UB) && !defined(CONFIG_BLK_DEV_UB_MODULE)
 	{ USB_INTERFACE_INFO(USB_CLASS_MASS_STORAGE, US_SC_SCSI, US_PR_BULK) },
+#endif
 
 	/* Terminating entry */
 	{ }
@@ -207,8 +214,10 @@
 	  .useTransport = US_PR_BULK},
 	{ .useProtocol = US_SC_8070,
 	  .useTransport = US_PR_BULK},
+#if !defined(CONFIG_BLK_DEV_UB) && !defined(CONFIG_BLK_DEV_UB_MODULE)
 	{ .useProtocol = US_SC_SCSI,
 	  .useTransport = US_PR_BULK},
+#endif
 
 	/* Terminating entry */
 	{ NULL }
@@ -322,7 +331,7 @@
 		/* reject the command if the direction indicator 
 		 * is UNKNOWN
 		 */
-		if (us->srb->sc_data_direction == SCSI_DATA_UNKNOWN) {
+		if (us->srb->sc_data_direction == DMA_BIDIRECTIONAL) {
 			US_DEBUGP("UNKNOWN data direction\n");
 			us->srb->result = DID_ERROR << 16;
 		}
@@ -423,6 +432,13 @@
 	us->pusb_dev = interface_to_usbdev(intf);
 	us->pusb_intf = intf;
 	us->ifnum = intf->cur_altsetting->desc.bInterfaceNumber;
+	US_DEBUGP("Vendor: 0x%04x, Product: 0x%04x, Revision: 0x%04x\n",
+			us->pusb_dev->descriptor.idVendor,
+			us->pusb_dev->descriptor.idProduct,
+			us->pusb_dev->descriptor.bcdDevice);
+	US_DEBUGP("Interface Subclass: 0x%02x, Protocol: 0x%02x\n",
+			intf->cur_altsetting->desc.bInterfaceSubClass,
+			intf->cur_altsetting->desc.bInterfaceProtocol);
 
 	/* Store our private data in the interface */
 	usb_set_intfdata(intf, us);
@@ -453,11 +469,6 @@
 	struct us_unusual_dev *unusual_dev = &us_unusual_dev_list[id_index];
 	struct usb_device_id *id = &storage_usb_ids[id_index];
 
-	if (unusual_dev->vendorName)
-		US_DEBUGP("Vendor: %s\n", unusual_dev->vendorName);
-	if (unusual_dev->productName)
-		US_DEBUGP("Product: %s\n", unusual_dev->productName);
-
 	/* Store the entries */
 	us->unusual_dev = unusual_dev;
 	us->subclass = (unusual_dev->useProtocol == US_SC_DEVICE) ?
@@ -528,6 +539,8 @@
 	}
 	if (strlen(us->serial) == 0)
 		strcpy(us->serial, "None");
+
+	US_DEBUGP("Vendor: %s,  Product: %s\n", us->vendor, us->product);
 }
 
 /* Get the transport settings */
@@ -715,8 +728,6 @@
 			ep_int = ep;
 		}
 	}
-	US_DEBUGP("Endpoints: In: 0x%p Out: 0x%p Int: 0x%p (Period %d)\n",
-		  ep_in, ep_out, ep_int, ep_int ? ep_int->bInterval : 0);
 
 	if (!ep_in || !ep_out || (us->protocol == US_PR_CBI && !ep_int)) {
 		US_DEBUGP("Endpoint sanity check failed! Rejecting dev.\n");
@@ -880,9 +891,6 @@
 	int result;
 
 	US_DEBUGP("USB Mass Storage device detected\n");
-	US_DEBUGP("altsetting is %d, id_index is %d\n",
-			intf->cur_altsetting->desc.bAlternateSetting,
-			id_index);
 
 	/* Allocate the us_data structure and initialize the mutexes */
 	us = (struct us_data *) kmalloc(sizeof(*us), GFP_KERNEL);
diff -Nru a/drivers/usb/storage/usb.h b/drivers/usb/storage/usb.h
--- a/drivers/usb/storage/usb.h	2004-10-18 14:56:33 -07:00
+++ b/drivers/usb/storage/usb.h	2004-10-18 14:56:33 -07:00
@@ -48,10 +48,9 @@
 #include <linux/blkdev.h>
 #include <linux/smp_lock.h>
 #include <linux/completion.h>
-#include "scsi.h"
-#include <scsi/scsi_host.h>
 
 struct us_data;
+struct scsi_cmnd;
 
 /*
  * Unusual device list definitions 
@@ -102,9 +101,9 @@
 
 #define US_IOBUF_SIZE		64	/* Size of the DMA-mapped I/O buffer */
 
-typedef int (*trans_cmnd)(Scsi_Cmnd*, struct us_data*);
+typedef int (*trans_cmnd)(struct scsi_cmnd *, struct us_data*);
 typedef int (*trans_reset)(struct us_data*);
-typedef void (*proto_cmnd)(Scsi_Cmnd*, struct us_data*);
+typedef void (*proto_cmnd)(struct scsi_cmnd*, struct us_data*);
 typedef void (*extra_data_destructor)(void *);	 /* extra data destructor   */
 
 /* we allocate one of these for every device that we remember */
@@ -144,7 +143,7 @@
 
 	/* SCSI interfaces */
 	struct Scsi_Host	*host;		 /* our dummy host data */
-	Scsi_Cmnd		*srb;		 /* current srb		*/
+	struct scsi_cmnd	*srb;		 /* current srb		*/
 
 	/* thread information */
 	int			pid;		 /* control thread	 */
@@ -179,5 +178,9 @@
  * single queue element srb for write access */
 #define scsi_unlock(host)	spin_unlock_irq(host->host_lock)
 #define scsi_lock(host)		spin_lock_irq(host->host_lock)
+
+
+/* Vendor ID list for devices that require special handling */
+#define USB_VENDOR_ID_GENESYS		0x05e3	/* Genesys Logic */
 
 #endif
diff -Nru a/drivers/usb/usb-skeleton.c b/drivers/usb/usb-skeleton.c
--- a/drivers/usb/usb-skeleton.c	2004-10-18 14:56:29 -07:00
+++ b/drivers/usb/usb-skeleton.c	2004-10-18 14:56:29 -07:00
@@ -1,42 +1,15 @@
 /*
- * USB Skeleton driver - 1.1
+ * USB Skeleton driver - 2.0
  *
- * Copyright (C) 2001-2003 Greg Kroah-Hartman (greg@kroah.com)
+ * Copyright (C) 2001-2004 Greg Kroah-Hartman (greg@kroah.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, version 2.
  *
- *
- * This driver is to be used as a skeleton driver to be able to create a
- * USB driver quickly.  The design of it is based on the usb-serial and
- * dc2xx drivers.
- *
- * Thanks to Oliver Neukum, David Brownell, and Alan Stern for their help
- * in debugging this driver.
- *
- *
- * History:
- *
- * 2003-05-06 - 1.1 - changes due to usb core changes with usb_register_dev()
- * 2003-02-25 - 1.0 - fix races involving urb->status, unlink_urb(), and
- *			disconnect.  Fix transfer amount in read().  Use
- *			macros instead of magic numbers in probe().  Change
- *			size variables to size_t.  Show how to eliminate
- *			DMA bounce buffer.
- * 2002_12_12 - 0.9 - compile fixes and got rid of fixed minor array.
- * 2002_09_26 - 0.8 - changes due to USB core conversion to struct device
- *			driver.
- * 2002_02_12 - 0.7 - zero out dev in probe function for devices that do
- *			not have both a bulk in and bulk out endpoint.
- *			Thanks to Holger Waechtler for the fix.
- * 2001_11_05 - 0.6 - fix minor locking problem in skel_disconnect.
- *			Thanks to Pete Zaitcev for the fix.
- * 2001_09_04 - 0.5 - fix devfs bug in skel_disconnect. Thanks to wim delvaux
- * 2001_08_21 - 0.4 - more small bug fixes.
- * 2001_05_29 - 0.3 - more bug fixes based on review from linux-usb-devel
- * 2001_05_24 - 0.2 - bug fixes based on review from linux-usb-devel people
- * 2001_05_01 - 0.1 - first version
+ * This driver is based on the 2.6.3 version of drivers/usb/usb-skeleton.c 
+ * but has been rewritten to be easy to read and use, as no locks are now
+ * needed anymore.
  *
  */
 
@@ -46,31 +19,10 @@
 #include <linux/init.h>
 #include <linux/slab.h>
 #include <linux/module.h>
-#include <linux/smp_lock.h>
-#include <linux/completion.h>
+#include <linux/kref.h>
 #include <asm/uaccess.h>
 #include <linux/usb.h>
 
-#ifdef CONFIG_USB_DEBUG
-	static int debug = 1;
-#else
-	static int debug;
-#endif
-
-/* Use our own dbg macro */
-#undef dbg
-#define dbg(format, arg...) do { if (debug) printk(KERN_DEBUG __FILE__ ": " format "\n" , ## arg); } while (0)
-
-
-/* Version Information */
-#define DRIVER_VERSION "v1.0"
-#define DRIVER_AUTHOR "Greg Kroah-Hartman, greg@kroah.com"
-#define DRIVER_DESC "USB Skeleton Driver"
-
-/* Module parameters */
-MODULE_PARM(debug, "i");
-MODULE_PARM_DESC(debug, "Debug enabled or not");
-
 
 /* Define these values to match your devices */
 #define USB_SKEL_VENDOR_ID	0xfff0
@@ -79,11 +31,8 @@
 /* table of devices that work with this driver */
 static struct usb_device_id skel_table [] = {
 	{ USB_DEVICE(USB_SKEL_VENDOR_ID, USB_SKEL_PRODUCT_ID) },
-	/* "Gadget Zero" firmware runs under Linux */
-	{ USB_DEVICE(0x0525, 0xa4a0) },
 	{ }					/* Terminating entry */
 };
-
 MODULE_DEVICE_TABLE (usb, skel_table);
 
 
@@ -92,413 +41,195 @@
 
 /* Structure to hold all of our device specific stuff */
 struct usb_skel {
-	struct usb_device *	udev;			/* save off the usb device pointer */
+	struct usb_device *	udev;			/* the usb device for this device */
 	struct usb_interface *	interface;		/* the interface for this device */
-	unsigned char		minor;			/* the starting minor number for this device */
-	unsigned char		num_ports;		/* the number of ports this device has */
-	char			num_interrupt_in;	/* number of interrupt in endpoints we have */
-	char			num_bulk_in;		/* number of bulk in endpoints we have */
-	char			num_bulk_out;		/* number of bulk out endpoints we have */
-
 	unsigned char *		bulk_in_buffer;		/* the buffer to receive data */
 	size_t			bulk_in_size;		/* the size of the receive buffer */
 	__u8			bulk_in_endpointAddr;	/* the address of the bulk in endpoint */
-
-	unsigned char *		bulk_out_buffer;	/* the buffer to send data */
-	size_t			bulk_out_size;		/* the size of the send buffer */
-	struct urb *		write_urb;		/* the urb used to send data */
 	__u8			bulk_out_endpointAddr;	/* the address of the bulk out endpoint */
-	atomic_t		write_busy;		/* true iff write urb is busy */
-	struct completion	write_finished;		/* wait for the write to finish */
-
-	int			open;			/* if the port is open or not */
-	int			present;		/* if the device is not disconnected */
-	struct semaphore	sem;			/* locks this structure */
+	struct kref		kref;
 };
+#define to_skel_dev(d) container_of(d, struct usb_skel, kref)
 
+static struct usb_driver skel_driver;
 
-/* prevent races between open() and disconnect() */
-static DECLARE_MUTEX (disconnect_sem);
-
-/* local function prototypes */
-static ssize_t skel_read	(struct file *file, char *buffer, size_t count, loff_t *ppos);
-static ssize_t skel_write	(struct file *file, const char *buffer, size_t count, loff_t *ppos);
-static int skel_ioctl		(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg);
-static int skel_open		(struct inode *inode, struct file *file);
-static int skel_release		(struct inode *inode, struct file *file);
-
-static int skel_probe		(struct usb_interface *interface, const struct usb_device_id *id);
-static void skel_disconnect	(struct usb_interface *interface);
-
-static void skel_write_bulk_callback	(struct urb *urb, struct pt_regs *regs);
-
-/*
- * File operations needed when we register this driver.
- * This assumes that this driver NEEDS file operations,
- * of course, which means that the driver is expected
- * to have a node in the /dev directory. If the USB
- * device were for a network interface then the driver
- * would use "struct net_driver" instead, and a serial
- * device would use "struct tty_driver".
- */
-static struct file_operations skel_fops = {
-	/*
-	 * The owner field is part of the module-locking
-	 * mechanism. The idea is that the kernel knows
-	 * which module to increment the use-counter of
-	 * BEFORE it calls the device's open() function.
-	 * This also means that the kernel can decrement
-	 * the use-counter again before calling release()
-	 * or should the open() function fail.
-	 */
-	.owner =	THIS_MODULE,
-
-	.read =		skel_read,
-	.write =	skel_write,
-	.ioctl =	skel_ioctl,
-	.open =		skel_open,
-	.release =	skel_release,
-};
-
-/* 
- * usb class driver info in order to get a minor number from the usb core,
- * and to have the device registered with devfs and the driver core
- */
-static struct usb_class_driver skel_class = {
-	.name =		"usb/skel%d",
-	.fops =		&skel_fops,
-	.mode =		S_IFCHR | S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH,
-	.minor_base =	USB_SKEL_MINOR_BASE,
-};
-
-/* usb specific object needed to register this driver with the usb subsystem */
-static struct usb_driver skel_driver = {
-	.owner =	THIS_MODULE,
-	.name =		"skeleton",
-	.probe =	skel_probe,
-	.disconnect =	skel_disconnect,
-	.id_table =	skel_table,
-};
-
-
-/**
- *	usb_skel_debug_data
- */
-static inline void usb_skel_debug_data (const char *function, int size, const unsigned char *data)
-{
-	int i;
-
-	if (!debug)
-		return;
-
-	printk (KERN_DEBUG __FILE__": %s - length = %d, data = ",
-		function, size);
-	for (i = 0; i < size; ++i) {
-		printk ("%.2x ", data[i]);
-	}
-	printk ("\n");
-}
-
+static void skel_delete(struct kref *kref)
+{	
+	struct usb_skel *dev = to_skel_dev(kref);
 
-/**
- *	skel_delete
- */
-static inline void skel_delete (struct usb_skel *dev)
-{
+	usb_put_dev(dev->udev);
 	kfree (dev->bulk_in_buffer);
-	usb_buffer_free (dev->udev, dev->bulk_out_size,
-				dev->bulk_out_buffer,
-				dev->write_urb->transfer_dma);
-	usb_free_urb (dev->write_urb);
 	kfree (dev);
 }
 
-
-/**
- *	skel_open
- */
-static int skel_open (struct inode *inode, struct file *file)
+static int skel_open(struct inode *inode, struct file *file)
 {
-	struct usb_skel *dev = NULL;
+	struct usb_skel *dev;
 	struct usb_interface *interface;
 	int subminor;
 	int retval = 0;
 
-	dbg("%s", __FUNCTION__);
-
 	subminor = iminor(inode);
 
-	/* prevent disconnects */
-	down (&disconnect_sem);
-
-	interface = usb_find_interface (&skel_driver, subminor);
+	interface = usb_find_interface(&skel_driver, subminor);
 	if (!interface) {
 		err ("%s - error, can't find device for minor %d",
 		     __FUNCTION__, subminor);
 		retval = -ENODEV;
-		goto exit_no_device;
+		goto exit;
 	}
 
 	dev = usb_get_intfdata(interface);
 	if (!dev) {
 		retval = -ENODEV;
-		goto exit_no_device;
+		goto exit;
 	}
 
-	/* lock this device */
-	down (&dev->sem);
-
-	/* increment our usage count for the driver */
-	++dev->open;
+	/* increment our usage count for the device */
+	kref_get(&dev->kref);
 
 	/* save our object in the file's private structure */
 	file->private_data = dev;
 
-	/* unlock this device */
-	up (&dev->sem);
-
-exit_no_device:
-	up (&disconnect_sem);
+exit:
 	return retval;
 }
 
-
-/**
- *	skel_release
- */
-static int skel_release (struct inode *inode, struct file *file)
+static int skel_release(struct inode *inode, struct file *file)
 {
 	struct usb_skel *dev;
-	int retval = 0;
 
 	dev = (struct usb_skel *)file->private_data;
-	if (dev == NULL) {
-		dbg ("%s - object is NULL", __FUNCTION__);
+	if (dev == NULL)
 		return -ENODEV;
-	}
-
-	dbg("%s - minor %d", __FUNCTION__, dev->minor);
-
-	/* lock our device */
-	down (&dev->sem);
-
-	if (dev->open <= 0) {
-		dbg ("%s - device not opened", __FUNCTION__);
-		retval = -ENODEV;
-		goto exit_not_opened;
-	}
-
-	/* wait for any bulk writes that might be going on to finish up */
-	if (atomic_read (&dev->write_busy))
-		wait_for_completion (&dev->write_finished);
-
-	--dev->open;
 
-	if (!dev->present && !dev->open) {
-		/* the device was unplugged before the file was released */
-		up (&dev->sem);
-		skel_delete (dev);
-		return 0;
-	}
-
-exit_not_opened:
-	up (&dev->sem);
-
-	return retval;
+	/* decrement the count on our device */
+	kref_put(&dev->kref, skel_delete);
+	return 0;
 }
 
-
-/**
- *	skel_read
- */
-static ssize_t skel_read (struct file *file, char *buffer, size_t count, loff_t *ppos)
+static ssize_t skel_read(struct file *file, char *buffer, size_t count, loff_t *ppos)
 {
 	struct usb_skel *dev;
 	int retval = 0;
 
 	dev = (struct usb_skel *)file->private_data;
-
-	dbg("%s - minor %d, count = %d", __FUNCTION__, dev->minor, count);
-
-	/* lock this object */
-	down (&dev->sem);
-
-	/* verify that the device wasn't unplugged */
-	if (!dev->present) {
-		up (&dev->sem);
-		return -ENODEV;
-	}
-
+	
 	/* do a blocking bulk read to get data from the device */
-	retval = usb_bulk_msg (dev->udev,
-			       usb_rcvbulkpipe (dev->udev,
-						dev->bulk_in_endpointAddr),
-			       dev->bulk_in_buffer,
-			       min (dev->bulk_in_size, count),
-			       &count, HZ*10);
+	retval = usb_bulk_msg(dev->udev,
+			      usb_rcvbulkpipe(dev->udev, dev->bulk_in_endpointAddr),
+			      dev->bulk_in_buffer,
+			      min(dev->bulk_in_size, count),
+			      &count, HZ*10);
 
 	/* if the read was successful, copy the data to userspace */
 	if (!retval) {
-		if (copy_to_user (buffer, dev->bulk_in_buffer, count))
+		if (copy_to_user(buffer, dev->bulk_in_buffer, count))
 			retval = -EFAULT;
 		else
 			retval = count;
 	}
 
-	/* unlock the device */
-	up (&dev->sem);
 	return retval;
 }
 
+static void skel_write_bulk_callback(struct urb *urb, struct pt_regs *regs)
+{
+	struct usb_skel *dev;
 
-/**
- *	skel_write
- *
- *	A device driver has to decide how to report I/O errors back to the
- *	user.  The safest course is to wait for the transfer to finish before
- *	returning so that any errors will be reported reliably.  skel_read()
- *	works like this.  But waiting for I/O is slow, so many drivers only
- *	check for errors during I/O initiation and do not report problems
- *	that occur during the actual transfer.  That's what we will do here.
- *
- *	A driver concerned with maximum I/O throughput would use double-
- *	buffering:  Two urbs would be devoted to write transfers, so that
- *	one urb could always be active while the other was waiting for the
- *	user to send more data.
- */
-static ssize_t skel_write (struct file *file, const char *buffer, size_t count, loff_t *ppos)
+	dev = (struct usb_skel *)urb->context;
+
+	/* sync/async unlink faults aren't errors */
+	if (urb->status && 
+	    !(urb->status == -ENOENT || 
+	      urb->status == -ECONNRESET ||
+	      urb->status == -ESHUTDOWN)) {
+		dbg("%s - nonzero write bulk status received: %d",
+		    __FUNCTION__, urb->status);
+	}
+
+	/* free up our allocated buffer */
+	usb_buffer_free(urb->dev, urb->transfer_buffer_length, 
+			urb->transfer_buffer, urb->transfer_dma);
+}
+
+static ssize_t skel_write(struct file *file, const char *user_buffer, size_t count, loff_t *ppos)
 {
 	struct usb_skel *dev;
-	ssize_t bytes_written = 0;
 	int retval = 0;
+	struct urb *urb = NULL;
+	char *buf = NULL;
 
 	dev = (struct usb_skel *)file->private_data;
 
-	dbg("%s - minor %d, count = %d", __FUNCTION__, dev->minor, count);
-
-	/* lock this object */
-	down (&dev->sem);
-
-	/* verify that the device wasn't unplugged */
-	if (!dev->present) {
-		retval = -ENODEV;
+	/* verify that we actually have some data to write */
+	if (count == 0)
 		goto exit;
+
+	/* create a urb, and a buffer for it, and copy the data to the urb */
+	urb = usb_alloc_urb(0, GFP_KERNEL);
+	if (!urb) {
+		retval = -ENOMEM;
+		goto error;
 	}
 
-	/* verify that we actually have some data to write */
-	if (count == 0) {
-		dbg("%s - write request of 0 bytes", __FUNCTION__);
-		goto exit;
+	buf = usb_buffer_alloc(dev->udev, count, GFP_KERNEL, &urb->transfer_dma);
+	if (!buf) {
+		retval = -ENOMEM;
+		goto error;
 	}
 
-	/* wait for a previous write to finish up; we don't use a timeout
-	 * and so a nonresponsive device can delay us indefinitely.
-	 */
-	if (atomic_read (&dev->write_busy))
-		wait_for_completion (&dev->write_finished);
-
-	/* we can only write as much as our buffer will hold */
-	bytes_written = min (dev->bulk_out_size, count);
-
-	/* copy the data from userspace into our transfer buffer;
-	 * this is the only copy required.
-	 */
-	if (copy_from_user(dev->write_urb->transfer_buffer, buffer,
-			   bytes_written)) {
+	if (copy_from_user(buf, user_buffer, count)) {
 		retval = -EFAULT;
-		goto exit;
+		goto error;
 	}
 
-	usb_skel_debug_data (__FUNCTION__, bytes_written,
-			     dev->write_urb->transfer_buffer);
-
-	/* this urb was already set up, except for this write size */
-	dev->write_urb->transfer_buffer_length = bytes_written;
+	/* initialize the urb properly */
+	usb_fill_bulk_urb(urb, dev->udev,
+			  usb_sndbulkpipe(dev->udev, dev->bulk_out_endpointAddr),
+			  buf, count, skel_write_bulk_callback, dev);
+	urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
 
 	/* send the data out the bulk port */
-	/* a character device write uses GFP_KERNEL,
-	 unless a spinlock is held */
-	init_completion (&dev->write_finished);
-	atomic_set (&dev->write_busy, 1);
-	retval = usb_submit_urb(dev->write_urb, GFP_KERNEL);
+	retval = usb_submit_urb(urb, GFP_KERNEL);
 	if (retval) {
-		atomic_set (&dev->write_busy, 0);
-		err("%s - failed submitting write urb, error %d",
-		    __FUNCTION__, retval);
-	} else {
-		retval = bytes_written;
+		err("%s - failed submitting write urb, error %d", __FUNCTION__, retval);
+		goto error;
 	}
 
+	/* release our reference to this urb, the USB core will eventually free it entirely */
+	usb_free_urb(urb);
+
 exit:
-	/* unlock the device */
-	up (&dev->sem);
+	return count;
 
+error:
+	usb_buffer_free(dev->udev, count, buf, urb->transfer_dma);
+	usb_free_urb(urb);
 	return retval;
 }
 
+static struct file_operations skel_fops = {
+	.owner =	THIS_MODULE,
+	.read =		skel_read,
+	.write =	skel_write,
+	.open =		skel_open,
+	.release =	skel_release,
+};
 
-/**
- *	skel_ioctl
- */
-static int skel_ioctl (struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
-{
-	struct usb_skel *dev;
-
-	dev = (struct usb_skel *)file->private_data;
-
-	/* lock this object */
-	down (&dev->sem);
-
-	/* verify that the device wasn't unplugged */
-	if (!dev->present) {
-		up (&dev->sem);
-		return -ENODEV;
-	}
-
-	dbg("%s - minor %d, cmd 0x%.4x, arg %ld", __FUNCTION__,
-	    dev->minor, cmd, arg);
-
-	/* fill in your device specific stuff here */
-
-	/* unlock the device */
-	up (&dev->sem);
-
-	/* return that we did not understand this ioctl call */
-	return -ENOTTY;
-}
-
-
-/**
- *	skel_write_bulk_callback
+/* 
+ * usb class driver info in order to get a minor number from the usb core,
+ * and to have the device registered with devfs and the driver core
  */
-static void skel_write_bulk_callback (struct urb *urb, struct pt_regs *regs)
-{
-	struct usb_skel *dev = (struct usb_skel *)urb->context;
-
-	dbg("%s - minor %d", __FUNCTION__, dev->minor);
-
-	/* sync/async unlink faults aren't errors */
-	if (urb->status && !(urb->status == -ENOENT ||
-				urb->status == -ECONNRESET)) {
-		dbg("%s - nonzero write bulk status received: %d",
-		    __FUNCTION__, urb->status);
-	}
-
-	/* notify anyone waiting that the write has finished */
-	atomic_set (&dev->write_busy, 0);
-	complete (&dev->write_finished);
-}
-
+static struct usb_class_driver skel_class = {
+	.name =		"usb/skel%d",
+	.fops =		&skel_fops,
+	.mode =		S_IFCHR | S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH,
+	.minor_base =	USB_SKEL_MINOR_BASE,
+};
 
-/**
- *	skel_probe
- *
- *	Called by the usb core when a new device is connected that it thinks
- *	this driver might be interested in.
- */
 static int skel_probe(struct usb_interface *interface, const struct usb_device_id *id)
 {
-	struct usb_device *udev = interface_to_usbdev(interface);
 	struct usb_skel *dev = NULL;
 	struct usb_host_interface *iface_desc;
 	struct usb_endpoint_descriptor *endpoint;
@@ -506,28 +237,21 @@
 	int i;
 	int retval = -ENOMEM;
 
-	/* See if the device offered us matches what we can accept */
-	if ((udev->descriptor.idVendor != USB_SKEL_VENDOR_ID) ||
-	    (udev->descriptor.idProduct != USB_SKEL_PRODUCT_ID)) {
-		return -ENODEV;
-	}
-
 	/* allocate memory for our device state and initialize it */
-	dev = kmalloc (sizeof(struct usb_skel), GFP_KERNEL);
+	dev = kmalloc(sizeof(*dev), GFP_KERNEL);
 	if (dev == NULL) {
-		err ("Out of memory");
-		return -ENOMEM;
+		err("Out of memory");
+		goto error;
 	}
-	memset (dev, 0x00, sizeof (*dev));
+	memset(dev, 0x00, sizeof(*dev));
+	kref_init(&dev->kref);
 
-	init_MUTEX (&dev->sem);
-	dev->udev = udev;
+	dev->udev = usb_get_dev(interface_to_usbdev(interface));
 	dev->interface = interface;
 
 	/* set up the endpoint information */
-	/* check out the endpoints */
 	/* use only the first bulk-in and bulk-out endpoints */
-	iface_desc = &interface->altsetting[0];
+	iface_desc = interface->cur_altsetting;
 	for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i) {
 		endpoint = &iface_desc->endpoint[i].desc;
 
@@ -539,9 +263,9 @@
 			buffer_size = endpoint->wMaxPacketSize;
 			dev->bulk_in_size = buffer_size;
 			dev->bulk_in_endpointAddr = endpoint->bEndpointAddress;
-			dev->bulk_in_buffer = kmalloc (buffer_size, GFP_KERNEL);
+			dev->bulk_in_buffer = kmalloc(buffer_size, GFP_KERNEL);
 			if (!dev->bulk_in_buffer) {
-				err("Couldn't allocate bulk_in_buffer");
+				err("Could not allocate bulk_in_buffer");
 				goto error;
 			}
 		}
@@ -551,153 +275,85 @@
 		    ((endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK)
 					== USB_ENDPOINT_XFER_BULK)) {
 			/* we found a bulk out endpoint */
-			/* a probe() may sleep and has no restrictions on memory allocations */
-			dev->write_urb = usb_alloc_urb(0, GFP_KERNEL);
-			if (!dev->write_urb) {
-				err("No free urbs available");
-				goto error;
-			}
 			dev->bulk_out_endpointAddr = endpoint->bEndpointAddress;
-
-			/* on some platforms using this kind of buffer alloc
-			 * call eliminates a dma "bounce buffer".
-			 *
-			 * NOTE: you'd normally want i/o buffers that hold
-			 * more than one packet, so that i/o delays between
-			 * packets don't hurt throughput.
-			 */
-			buffer_size = endpoint->wMaxPacketSize;
-			dev->bulk_out_size = buffer_size;
-			dev->write_urb->transfer_flags = (URB_NO_TRANSFER_DMA_MAP |
-					URB_ASYNC_UNLINK);
-			dev->bulk_out_buffer = usb_buffer_alloc (udev,
-					buffer_size, GFP_KERNEL,
-					&dev->write_urb->transfer_dma);
-			if (!dev->bulk_out_buffer) {
-				err("Couldn't allocate bulk_out_buffer");
-				goto error;
-			}
-			usb_fill_bulk_urb(dev->write_urb, udev,
-				      usb_sndbulkpipe(udev,
-						      endpoint->bEndpointAddress),
-				      dev->bulk_out_buffer, buffer_size,
-				      skel_write_bulk_callback, dev);
 		}
 	}
 	if (!(dev->bulk_in_endpointAddr && dev->bulk_out_endpointAddr)) {
-		err("Couldn't find both bulk-in and bulk-out endpoints");
+		err("Could not find both bulk-in and bulk-out endpoints");
 		goto error;
 	}
 
-	/* allow device read, write and ioctl */
-	dev->present = 1;
+	/* save our data pointer in this interface device */
+	usb_set_intfdata(interface, dev);
 
 	/* we can register the device now, as it is ready */
-	usb_set_intfdata (interface, dev);
-	retval = usb_register_dev (interface, &skel_class);
+	retval = usb_register_dev(interface, &skel_class);
 	if (retval) {
 		/* something prevented us from registering this driver */
-		err ("Not able to get a minor for this device.");
-		usb_set_intfdata (interface, NULL);
+		err("Not able to get a minor for this device.");
+		usb_set_intfdata(interface, NULL);
 		goto error;
 	}
 
-	dev->minor = interface->minor;
-
 	/* let the user know what node this device is now attached to */
-	info ("USB Skeleton device now attached to USBSkel-%d", dev->minor);
+	info("USB Skeleton device now attached to USBSkel-%d", interface->minor);
 	return 0;
 
 error:
-	skel_delete (dev);
+	if (dev)
+		kref_put(&dev->kref, skel_delete);
 	return retval;
 }
 
-
-/**
- *	skel_disconnect
- *
- *	Called by the usb core when the device is removed from the system.
- *
- *	This routine guarantees that the driver will not submit any more urbs
- *	by clearing dev->udev.  It is also supposed to terminate any currently
- *	active urbs.  Unfortunately, usb_bulk_msg(), used in skel_read(), does
- *	not provide any way to do this.  But at least we can cancel an active
- *	write.
- */
 static void skel_disconnect(struct usb_interface *interface)
 {
 	struct usb_skel *dev;
-	int minor;
+	int minor = interface->minor;
 
-	/* prevent races with open() */
-	down (&disconnect_sem);
+	/* prevent skel_open() from racing skel_disconnect() */
+	lock_kernel();
 
-	dev = usb_get_intfdata (interface);
-	usb_set_intfdata (interface, NULL);
-
-	down (&dev->sem);
-
-	minor = dev->minor;
+	dev = usb_get_intfdata(interface);
+	usb_set_intfdata(interface, NULL);
 
 	/* give back our minor */
-	usb_deregister_dev (interface, &skel_class);
+	usb_deregister_dev(interface, &skel_class);
 
-	/* terminate an ongoing write */
-	if (atomic_read (&dev->write_busy)) {
-		usb_unlink_urb (dev->write_urb);
-		wait_for_completion (&dev->write_finished);
-	}
-
-	/* prevent device read, write and ioctl */
-	dev->present = 0;
-
-	up (&dev->sem);
+	unlock_kernel();
 
-	/* if the device is opened, skel_release will clean this up */
-	if (!dev->open)
-		skel_delete (dev);
-
-	up (&disconnect_sem);
+	/* decrement our usage count */
+	kref_put(&dev->kref, skel_delete);
 
 	info("USB Skeleton #%d now disconnected", minor);
 }
 
+static struct usb_driver skel_driver = {
+	.owner =	THIS_MODULE,
+	.name =		"skeleton",
+	.probe =	skel_probe,
+	.disconnect =	skel_disconnect,
+	.id_table =	skel_table,
+};
 
-
-/**
- *	usb_skel_init
- */
 static int __init usb_skel_init(void)
 {
 	int result;
 
 	/* register this driver with the USB subsystem */
 	result = usb_register(&skel_driver);
-	if (result) {
-		err("usb_register failed. Error number %d",
-		    result);
-		return result;
-	}
+	if (result)
+		err("usb_register failed. Error number %d", result);
 
-	info(DRIVER_DESC " " DRIVER_VERSION);
-	return 0;
+	return result;
 }
 
-
-/**
- *	usb_skel_exit
- */
 static void __exit usb_skel_exit(void)
 {
 	/* deregister this driver with the USB subsystem */
 	usb_deregister(&skel_driver);
 }
 
-
 module_init (usb_skel_init);
 module_exit (usb_skel_exit);
 
-MODULE_AUTHOR(DRIVER_AUTHOR);
-MODULE_DESCRIPTION(DRIVER_DESC);
 MODULE_LICENSE("GPL");
diff -Nru a/drivers/video/68328fb.c b/drivers/video/68328fb.c
--- a/drivers/video/68328fb.c	2004-10-18 14:56:48 -07:00
+++ b/drivers/video/68328fb.c	2004-10-18 14:56:48 -07:00
@@ -199,6 +199,15 @@
 	 */
 	switch (var->bits_per_pixel) {
 	case 1:
+		var->red.offset = 0;
+		var->red.length = 1;
+		var->green.offset = 0;
+		var->green.length = 1;
+		var->blue.offset = 0;
+		var->blue.length = 1;
+		var->transp.offset = 0;
+		var->transp.length = 0;
+		break;
 	case 8:
 		var->red.offset = 0;
 		var->red.length = 8;
@@ -430,6 +439,13 @@
 
 int __init mc68x328fb_init(void)
 {
+#ifndef MODULE
+	char *option = NULL;
+
+	if (fb_get_options("68328fb", &option))
+		return -ENODEV;
+	mc68x328fb_setup(option);
+#endif
 	/*
 	 *  initialize the default mode from the LCD controller registers
 	 */
@@ -452,8 +468,12 @@
 		get_line_length(mc68x328fb_default.xres_virtual, mc68x328fb_default.bits_per_pixel);
 	fb_info.fix.visual = (mc68x328fb_default.bits_per_pixel) == 1 ?
 		MC68X328FB_MONO_VISUAL : FB_VISUAL_PSEUDOCOLOR;
+	if (fb_info.var.bits_per_pixel == 1) {
+		fb_info.var.red.length = fb_info.var.green.length = fb_info.var.blue.length = 1;
+		fb_info.var.red.offset = fb_info.var.green.offset = fb_info.var.blue.offset = 0;
+	}
 	fb_info.pseudo_palette = &mc68x328fb_pseudo_palette;
-	fb_info.flags = FBINFO_FLAG_DEFAULT;
+	fb_info.flags = FBINFO_DEFAULT | FBINFO_HWACCEL_YPAN;
 
 	fb_alloc_cmap(&fb_info.cmap, 256, 0);
 
@@ -471,6 +491,8 @@
 	return 0;
 }
 
+module_init(mc68x328fb_init);
+
 #ifdef MODULE
 
 static void __exit mc68x328fb_cleanup(void)
@@ -478,7 +500,6 @@
 	unregister_framebuffer(&fb_info);
 }
 
-module_init(mc68x328fb_init);
 module_exit(mc68x328fb_cleanup);
 
 MODULE_LICENSE("GPL");
diff -Nru a/drivers/video/Kconfig b/drivers/video/Kconfig
--- a/drivers/video/Kconfig	2004-10-18 14:55:54 -07:00
+++ b/drivers/video/Kconfig	2004-10-18 14:55:54 -07:00
@@ -38,6 +38,17 @@
 	  (e.g. an accelerated X server) and that are not frame buffer
 	  device-aware may cause unexpected results. If unsure, say N.
 
+config FB_MODE_HELPERS
+        bool "Enable Video Mode Handling Helpers"
+        depends on FB
+	default y
+	---help---
+	  This enables functions for handling video modes using the
+	  Generalized Timing Formula and the EDID parser. A few drivers rely
+          on this feature such as the radeonfb, rivafb, and the i810fb. If
+	  your driver does not take advantage of this feature, choosing Y will
+	  just increase the kernel size by about 5K.
+
 config FB_CIRRUS
 	tristate "Cirrus Logic support"
 	depends on FB && (ZORRO || PCI)
@@ -68,6 +79,19 @@
 	help
 	  Support the Permedia2 FIFO disconnect feature (see CONFIG_FB_PM2).
 
+config FB_ARMCLCD
+	tristate "ARM PrimeCell PL110 support"
+	depends on FB && ARM && ARM_AMBA
+	help
+	  This framebuffer device driver is for the ARM PrimeCell PL110
+	  Colour LCD controller.  ARM PrimeCells provide the building
+	  blocks for System on a Chip devices.
+
+	  If you want to compile this as a module (=code which can be
+	  inserted into and removed from the running kernel), say M
+	  here and read <file:Documentation/modules.txt>.  The module
+	  will be called amba-clcd.
+
 config FB_ACORN
 	bool "Acorn VIDC support"
 	depends on FB && ARM && ARCH_ACORN
@@ -392,40 +416,21 @@
 	  (<file:drivers/video/pvr2fb.c>). Please see the file
 	  <file:Documentation/fb/pvr2fb.txt>.
 
-config FB_E1355
+config FB_EPSON1355
 	bool "Epson 1355 framebuffer support"
-	depends on FB && SUPERH
+	depends on FB && (SUPERH || ARCH_CEIVA)
 	help
 	  Build in support for the SED1355 Epson Research Embedded RAMDAC
 	  LCD/CRT Controller (since redesignated as the S1D13505) as a
 	  framebuffer.  Product specs at
 	  <http://www.erd.epson.com/vdc/html/products.htm>.
 
-config E1355_REG_BASE
-	hex "Register Base Address"
-	depends on FB_E1355
-	default "a8000000"
-	help
-	  Epson SED1355/S1D13505 LCD/CRT controller register base address.
-	  See the manuals at
-	  <http://www.erd.epson.com/vdc/html/contents/S1D13505.htm> for
-	  discussion.
-
-config E1355_FB_BASE
-	hex "Framebuffer Base Address"
-	depends on FB_E1355
-	default "a8200000"
-	help
-	  Epson SED1355/S1D13505 LCD/CRT controller memory base address.  See
-	  the manuals at
-	  <http://www.erd.epson.com/vdc/html/contents/S1D13505.htm> for
-	  discussion.
-
 config FB_RIVA
 	tristate "nVidia Riva support"
 	depends on FB && PCI
 	select I2C_ALGOBIT if FB_RIVA_I2C
 	select I2C if FB_RIVA_I2C
+	select FB_MODE_HELPERS
 	help
 	  This driver supports graphics boards with the nVidia Riva/Geforce
 	  chips.
@@ -457,7 +462,10 @@
 
 config FB_I810
 	tristate "Intel 810/815 support (EXPERIMENTAL)"
-	depends on FB && AGP && AGP_INTEL && EXPERIMENTAL && PCI	
+	depends on FB && EXPERIMENTAL && PCI && X86 && !X86_64
+	select AGP
+	select AGP_INTEL
+	select FB_MODE_HELPERS
 	help
 	  This driver supports the on-board graphics built in to the Intel 810 
           and 815 chipsets.  Say Y if you have and plan to use such a board.
@@ -661,6 +669,7 @@
 	depends on FB && PCI
 	select I2C_ALGOBIT if FB_RADEON_I2C
 	select I2C if FB_RADEON_I2C
+	select FB_MODE_HELPERS
 	help
 	  Choose this option if you want to use an ATI Radeon graphics card as
 	  a framebuffer device.  There are both PCI and AGP versions.  You
@@ -766,6 +775,7 @@
 config FB_NEOMAGIC
 	tristate "NeoMagic display support"
 	depends on FB && PCI
+	select FB_MODE_HELPERS
 	help
 	  This driver supports notebooks with NeoMagic PCI chips.
 	  Say Y if you have such a graphics card. 
diff -Nru a/drivers/video/Makefile b/drivers/video/Makefile
--- a/drivers/video/Makefile	2004-10-18 14:55:55 -07:00
+++ b/drivers/video/Makefile	2004-10-18 14:55:55 -07:00
@@ -13,80 +13,88 @@
 obj-$(CONFIG_PPC)                 += macmodes.o
 endif
 
-obj-$(CONFIG_FB_ACORN)            += acornfb.o cfbfillrect.o cfbcopyarea.o cfbimgblt.o
+# Hardware specific drivers go first
+obj-$(CONFIG_FB_RETINAZ3)         += retz3fb.o
 obj-$(CONFIG_FB_AMIGA)            += amifb.o c2p.o
+obj-$(CONFIG_FB_CLPS711X)         += clps711xfb.o cfbfillrect.o cfbcopyarea.o cfbimgblt.o
+obj-$(CONFIG_FB_CYBER)            += cyberfb.o
+obj-$(CONFIG_FB_CYBER2000)        += cyber2000fb.o cfbfillrect.o cfbcopyarea.o cfbimgblt.o
 obj-$(CONFIG_FB_PM2)              += pm2fb.o cfbfillrect.o cfbcopyarea.o cfbimgblt.o
 obj-$(CONFIG_FB_PM3)		  += pm3fb.o
-obj-$(CONFIG_FB_APOLLO)           += dnfb.o cfbfillrect.o cfbimgblt.o
-obj-$(CONFIG_FB_Q40)              += q40fb.o cfbfillrect.o cfbcopyarea.o cfbimgblt.o
-obj-$(CONFIG_FB_ATARI)            += atafb.o
-obj-$(CONFIG_FB_68328)            += 68328fb.o cfbfillrect.o cfbcopyarea.o cfbimgblt.o
+
+obj-$(CONFIG_FB_MATROX)		  += matrox/ cfbfillrect.o cfbcopyarea.o cfbimgblt.o
+obj-$(CONFIG_FB_RIVA)		  += riva/ cfbimgblt.o vgastate.o
+obj-$(CONFIG_FB_ATY)		  += aty/ cfbcopyarea.o cfbfillrect.o cfbimgblt.o
+obj-$(CONFIG_FB_ATY128)		  += aty/ cfbcopyarea.o cfbfillrect.o cfbimgblt.o
+obj-$(CONFIG_FB_RADEON)		  += aty/ cfbcopyarea.o cfbfillrect.o cfbimgblt.o
+obj-$(CONFIG_FB_SIS)		  += sis/ cfbcopyarea.o cfbfillrect.o cfbimgblt.o
+obj-$(CONFIG_FB_KYRO)             += kyro/ cfbfillrect.o cfbcopyarea.o cfbimgblt.o
+
+obj-$(CONFIG_FB_I810)             += cfbcopyarea.o cfbfillrect.o cfbimgblt.o \
+				     vgastate.o
 obj-$(CONFIG_FB_RADEON_OLD)	  += radeonfb.o cfbfillrect.o cfbcopyarea.o cfbimgblt.o
 obj-$(CONFIG_FB_NEOMAGIC)         += neofb.o cfbfillrect.o cfbcopyarea.o cfbimgblt.o vgastate.o
-obj-$(CONFIG_FB_IGA)              += igafb.o cfbfillrect.o cfbcopyarea.o cfbimgblt.o
+obj-$(CONFIG_FB_VIRGE)            += virgefb.o
+obj-$(CONFIG_FB_3DFX)             += tdfxfb.o cfbimgblt.o
+ifneq ($(CONFIG_FB_3DFX_ACCEL),y)
+obj-$(CONFIG_FB_3DFX)             += cfbfillrect.o cfbcopyarea.o
+endif
 obj-$(CONFIG_FB_CONTROL)          += controlfb.o macmodes.o cfbfillrect.o cfbcopyarea.o cfbimgblt.o
 obj-$(CONFIG_FB_PLATINUM)         += platinumfb.o macmodes.o cfbfillrect.o cfbcopyarea.o cfbimgblt.o
 obj-$(CONFIG_FB_VALKYRIE)         += valkyriefb.o macmodes.o cfbfillrect.o cfbcopyarea.o cfbimgblt.o
 obj-$(CONFIG_FB_CT65550)          += chipsfb.o cfbfillrect.o cfbcopyarea.o cfbimgblt.o
-obj-$(CONFIG_FB_CLPS711X)         += clps711xfb.o cfbfillrect.o cfbcopyarea.o cfbimgblt.o
-obj-$(CONFIG_FB_CYBER)            += cyberfb.o
-obj-$(CONFIG_FB_CYBER2000)        += cyber2000fb.o cfbfillrect.o cfbcopyarea.o cfbimgblt.o
-obj-$(CONFIG_FB_GBE)              += gbefb.o cfbfillrect.o cfbcopyarea.o cfbimgblt.o
-obj-$(CONFIG_FB_SGIVW)            += sgivwfb.o cfbfillrect.o cfbcopyarea.o cfbimgblt.o
-obj-$(CONFIG_FB_3DFX)             += tdfxfb.o cfbimgblt.o
-obj-$(CONFIG_FB_MAC)              += macfb.o macmodes.o cfbfillrect.o cfbcopyarea.o cfbimgblt.o 
-obj-$(CONFIG_FB_HP300)            += hpfb.o cfbfillrect.o cfbimgblt.o
-obj-$(CONFIG_FB_OF)               += offb.o cfbfillrect.o cfbimgblt.o cfbcopyarea.o
 obj-$(CONFIG_FB_IMSTT)            += imsttfb.o cfbimgblt.o
-obj-$(CONFIG_FB_RETINAZ3)         += retz3fb.o
-obj-$(CONFIG_FB_CIRRUS)		  += cirrusfb.o cfbfillrect.o cfbimgblt.o cfbcopyarea.o
-obj-$(CONFIG_FB_TRIDENT)	  += tridentfb.o cfbfillrect.o cfbimgblt.o cfbcopyarea.o
 obj-$(CONFIG_FB_S3TRIO)           += S3triofb.o
-obj-$(CONFIG_FB_TGA)              += tgafb.o cfbfillrect.o cfbcopyarea.o cfbimgblt.o 
-obj-$(CONFIG_FB_VESA)             += vesafb.o cfbfillrect.o cfbcopyarea.o cfbimgblt.o 
-obj-$(CONFIG_FB_VGA16)            += vga16fb.o cfbfillrect.o cfbcopyarea.o \
-	                             cfbimgblt.o vgastate.o 
-obj-$(CONFIG_FB_VIRGE)            += virgefb.o
-obj-$(CONFIG_FB_G364)             += g364fb.o cfbfillrect.o cfbcopyarea.o cfbimgblt.o
 obj-$(CONFIG_FB_FM2)              += fm2fb.o cfbfillrect.o cfbcopyarea.o cfbimgblt.o
+obj-$(CONFIG_FB_TRIDENT)	  += tridentfb.o cfbfillrect.o cfbimgblt.o cfbcopyarea.o
 obj-$(CONFIG_FB_STI)              += stifb.o cfbfillrect.o cfbcopyarea.o cfbimgblt.o
-obj-$(CONFIG_FB_PMAG_BA)          += pmag-ba-fb.o cfbfillrect.o cfbcopyarea.o cfbimgblt.o
-obj-$(CONFIG_FB_PMAGB_B)          += pmagb-b-fb.o cfbfillrect.o cfbcopyarea.o cfbimgblt.o
-obj-$(CONFIG_FB_MAXINE)           += maxinefb.o cfbfillrect.o cfbcopyarea.o cfbimgblt.o
-obj-$(CONFIG_FB_TX3912)           += tx3912fb.o cfbfillrect.o cfbcopyarea.o cfbimgblt.o
-
-obj-$(CONFIG_FB_MATROX)		  += matrox/ cfbfillrect.o cfbcopyarea.o cfbimgblt.o
-obj-$(CONFIG_FB_RIVA)		  += riva/ cfbimgblt.o vgastate.o 
-obj-$(CONFIG_FB_SIS)		  += sis/ cfbcopyarea.o cfbfillrect.o cfbimgblt.o
-obj-$(CONFIG_FB_ATY)		  += aty/ cfbcopyarea.o cfbfillrect.o cfbimgblt.o
-obj-$(CONFIG_FB_ATY128)		  += aty/ cfbcopyarea.o cfbfillrect.o cfbimgblt.o
-obj-$(CONFIG_FB_RADEON)		  += aty/ cfbcopyarea.o cfbfillrect.o cfbimgblt.o
-obj-$(CONFIG_FB_I810)             += i810/ cfbfillrect.o cfbcopyarea.o \
-	                             cfbimgblt.o vgastate.o
-
-obj-$(CONFIG_FB_SUN3)             += sun3fb.o
+obj-$(CONFIG_FB_FFB)              += ffb.o sbuslib.o cfbimgblt.o cfbcopyarea.o
+obj-$(CONFIG_FB_CG6)              += cg6.o sbuslib.o cfbimgblt.o cfbcopyarea.o
+obj-$(CONFIG_FB_CG3)              += cg3.o sbuslib.o cfbimgblt.o cfbcopyarea.o \
+				     cfbfillrect.o
+obj-$(CONFIG_FB_BW2)              += bw2.o sbuslib.o cfbimgblt.o cfbcopyarea.o \
+				     cfbfillrect.o
+obj-$(CONFIG_FB_CG14)             += cg14.o sbuslib.o cfbimgblt.o cfbcopyarea.o \
+				     cfbfillrect.o
+obj-$(CONFIG_FB_P9100)            += p9100.o sbuslib.o cfbimgblt.o cfbcopyarea.o \
+				     cfbfillrect.o
+obj-$(CONFIG_FB_TCX)              += tcx.o sbuslib.o cfbimgblt.o cfbcopyarea.o \
+				     cfbfillrect.o
+obj-$(CONFIG_FB_LEO)              += leo.o sbuslib.o cfbimgblt.o cfbcopyarea.o \
+				     cfbfillrect.o
+obj-$(CONFIG_FB_SGIVW)            += sgivwfb.o cfbfillrect.o cfbcopyarea.o cfbimgblt.o
+obj-$(CONFIG_FB_ACORN)            += acornfb.o cfbfillrect.o cfbcopyarea.o cfbimgblt.o
+obj-$(CONFIG_FB_ATARI)            += atafb.o
+obj-$(CONFIG_FB_MAC)              += macfb.o macmodes.o cfbfillrect.o cfbcopyarea.o cfbimgblt.o
 obj-$(CONFIG_FB_HGA)              += hgafb.o cfbfillrect.o cfbcopyarea.o cfbimgblt.o 
+obj-$(CONFIG_FB_IGA)              += igafb.o cfbfillrect.o cfbcopyarea.o cfbimgblt.o
+obj-$(CONFIG_FB_APOLLO)           += dnfb.o cfbfillrect.o cfbimgblt.o
+obj-$(CONFIG_FB_Q40)              += q40fb.o cfbfillrect.o cfbcopyarea.o cfbimgblt.o
+obj-$(CONFIG_FB_TGA)              += tgafb.o cfbfillrect.o cfbcopyarea.o cfbimgblt.o
+obj-$(CONFIG_FB_HP300)            += hpfb.o cfbfillrect.o cfbimgblt.o
+obj-$(CONFIG_FB_G364)             += g364fb.o cfbfillrect.o cfbcopyarea.o cfbimgblt.o
 obj-$(CONFIG_FB_SA1100)           += sa1100fb.o cfbfillrect.o cfbcopyarea.o cfbimgblt.o
-obj-$(CONFIG_FB_VIRTUAL)          += vfb.o cfbfillrect.o cfbcopyarea.o cfbimgblt.o 
+obj-$(CONFIG_FB_SUN3)             += sun3fb.o
 obj-$(CONFIG_FB_HIT)              += hitfb.o cfbfillrect.o cfbimgblt.o
-obj-$(CONFIG_FB_E1355)            += epson1355fb.o
+obj-$(CONFIG_FB_TX3912)           += tx3912fb.o cfbfillrect.o cfbcopyarea.o cfbimgblt.o
+obj-$(CONFIG_FB_EPSON1355)	  += epson1355fb.o cfbfillrect.o cfbcopyarea.o cfbimgblt.o
 obj-$(CONFIG_FB_PVR2)             += pvr2fb.o cfbfillrect.o cfbcopyarea.o cfbimgblt.o
-obj-$(CONFIG_FB_KYRO)             += kyro/ cfbfillrect.o cfbcopyarea.o cfbimgblt.o
+obj-$(CONFIG_FB_PMAG_BA)          += pmag-ba-fb.o cfbfillrect.o cfbcopyarea.o cfbimgblt.o
+obj-$(CONFIG_FB_PMAGB_B)          += pmagb-b-fb.o cfbfillrect.o cfbcopyarea.o cfbimgblt.o
+obj-$(CONFIG_FB_MAXINE)           += maxinefb.o cfbfillrect.o cfbcopyarea.o cfbimgblt.o
 obj-$(CONFIG_FB_VOODOO1)          += sstfb.o cfbfillrect.o cfbcopyarea.o cfbimgblt.o
+obj-$(CONFIG_FB_ARMCLCD)	  += amba-clcd.o cfbfillrect.o cfbcopyarea.o cfbimgblt.o
+obj-$(CONFIG_FB_68328)            += 68328fb.o cfbfillrect.o cfbcopyarea.o cfbimgblt.o
+obj-$(CONFIG_FB_GBE)              += gbefb.o cfbfillrect.o cfbcopyarea.o cfbimgblt.o
+obj-$(CONFIG_FB_CIRRUS)		  += cirrusfb.o cfbfillrect.o cfbimgblt.o cfbcopyarea.o
 obj-$(CONFIG_FB_ASILIANT)	  += asiliantfb.o cfbfillrect.o cfbcopyarea.o cfbimgblt.o
+obj-$(CONFIG_FB_PXA)		  += pxafb.o cfbimgblt.o cfbcopyarea.o cfbfillrect.o
+
+# Platform or fallback drivers go here
+obj-$(CONFIG_FB_VESA)             += vesafb.o cfbfillrect.o cfbcopyarea.o cfbimgblt.o
+obj-$(CONFIG_FB_VGA16)            += vga16fb.o cfbfillrect.o cfbcopyarea.o \
+	                             cfbimgblt.o vgastate.o
+obj-$(CONFIG_FB_OF)               += offb.o cfbfillrect.o cfbimgblt.o cfbcopyarea.o
 
-obj-$(CONFIG_FB_FFB)               += ffb.o sbuslib.o cfbimgblt.o cfbcopyarea.o
-obj-$(CONFIG_FB_CG6)               += cg6.o sbuslib.o cfbimgblt.o cfbcopyarea.o
-obj-$(CONFIG_FB_CG3)               += cg3.o sbuslib.o cfbimgblt.o cfbcopyarea.o \
-				      cfbfillrect.o
-obj-$(CONFIG_FB_BW2)               += bw2.o sbuslib.o cfbimgblt.o cfbcopyarea.o \
-				      cfbfillrect.o
-obj-$(CONFIG_FB_CG14)              += cg14.o sbuslib.o cfbimgblt.o cfbcopyarea.o \
-				      cfbfillrect.o
-obj-$(CONFIG_FB_P9100)             += p9100.o sbuslib.o cfbimgblt.o cfbcopyarea.o \
-				      cfbfillrect.o
-obj-$(CONFIG_FB_TCX)               += tcx.o sbuslib.o cfbimgblt.o cfbcopyarea.o \
-				      cfbfillrect.o
-obj-$(CONFIG_FB_LEO)               += leo.o sbuslib.o cfbimgblt.o cfbcopyarea.o \
-				      cfbfillrect.o
-obj-$(CONFIG_FB_PXA)		   += pxafb.o cfbimgblt.o cfbcopyarea.o cfbfillrect.o
+# the test framebuffer is last
+obj-$(CONFIG_FB_VIRTUAL)          += vfb.o cfbfillrect.o cfbcopyarea.o cfbimgblt.o
diff -Nru a/drivers/video/acornfb.c b/drivers/video/acornfb.c
--- a/drivers/video/acornfb.c	2004-10-18 14:57:04 -07:00
+++ b/drivers/video/acornfb.c	2004-10-18 14:57:04 -07:00
@@ -1010,7 +1010,7 @@
 	first = 0;
 
 	fb_info.fbops		= &acornfb_ops;
-	fb_info.flags		= FBINFO_FLAG_DEFAULT;
+	fb_info.flags		= FBINFO_DEFAULT | FBINFO_HWACCEL_YPAN;
 	fb_info.pseudo_palette	= current_par.pseudo_palette;
 
 	strcpy(fb_info.fix.id, "Acorn");
@@ -1291,6 +1291,11 @@
 	unsigned long size;
 	u_int h_sync, v_sync;
 	int rc, i;
+	char *option = NULL;
+
+	if (fb_get_options("acornfb", &option))
+		return -ENODEV;
+	acornfb_setup(option);
 
 	acornfb_init_fbinfo();
 
@@ -1455,6 +1460,8 @@
 		return -EINVAL;
 	return 0;
 }
+
+module_init(acornfb_init);
 
 MODULE_AUTHOR("Russell King");
 MODULE_DESCRIPTION("VIDC 1/1a/20 framebuffer driver");
diff -Nru a/drivers/video/amba-clcd.c b/drivers/video/amba-clcd.c
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/drivers/video/amba-clcd.c	2004-10-18 14:57:24 -07:00
@@ -0,0 +1,515 @@
+/*
+ *  linux/drivers/video/amba-clcd.c
+ *
+ * Copyright (C) 2001 ARM Limited, by David A Rusling
+ * Updated to 2.5, Deep Blue Solutions Ltd.
+ *
+ * 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.
+ *
+ *  ARM PrimeCell PL110 Color LCD Controller
+ */
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/string.h>
+#include <linux/slab.h>
+#include <linux/delay.h>
+#include <linux/fb.h>
+#include <linux/init.h>
+#include <linux/ioport.h>
+#include <linux/list.h>
+
+#include <asm/hardware/amba.h>
+#include <asm/hardware/clock.h>
+
+#include <asm/hardware/amba_clcd.h>
+
+#define to_clcd(info)	container_of(info, struct clcd_fb, fb)
+
+/* This is limited to 16 characters when displayed by X startup */
+static const char *clcd_name = "CLCD FB";
+
+/*
+ * Unfortunately, the enable/disable functions may be called either from
+ * process or IRQ context, and we _need_ to delay.  This is _not_ good.
+ */
+static inline void clcdfb_sleep(unsigned int ms)
+{
+	if (in_atomic()) {
+		mdelay(ms);
+	} else {
+		msleep(ms);
+	}
+}
+
+static inline void clcdfb_set_start(struct clcd_fb *fb)
+{
+	unsigned long ustart = fb->fb.fix.smem_start;
+	unsigned long lstart;
+
+	ustart += fb->fb.var.yoffset * fb->fb.fix.line_length;
+	lstart = ustart + fb->fb.var.yres * fb->fb.fix.line_length / 2;
+
+	writel(ustart, fb->regs + CLCD_UBAS);
+	writel(lstart, fb->regs + CLCD_LBAS);
+}
+
+static void clcdfb_disable(struct clcd_fb *fb)
+{
+	u32 val;
+
+	if (fb->board->disable)
+		fb->board->disable(fb);
+
+	val = readl(fb->regs + CLCD_CNTL);
+	if (val & CNTL_LCDPWR) {
+		val &= ~CNTL_LCDPWR;
+		writel(val, fb->regs + CLCD_CNTL);
+
+		clcdfb_sleep(20);
+	}
+	if (val & CNTL_LCDEN) {
+		val &= ~CNTL_LCDEN;
+		writel(val, fb->regs + CLCD_CNTL);
+	}
+
+	/*
+	 * Disable CLCD clock source.
+	 */
+	clk_disable(fb->clk);
+}
+
+static void clcdfb_enable(struct clcd_fb *fb, u32 cntl)
+{
+	/*
+	 * Enable the CLCD clock source.
+	 */
+	clk_enable(fb->clk);
+
+	/*
+	 * Bring up by first enabling..
+	 */
+	cntl |= CNTL_LCDEN;
+	writel(cntl, fb->regs + CLCD_CNTL);
+
+	clcdfb_sleep(20);
+
+	/*
+	 * and now apply power.
+	 */
+	cntl |= CNTL_LCDPWR;
+	writel(cntl, fb->regs + CLCD_CNTL);
+
+	/*
+	 * finally, enable the interface.
+	 */
+	if (fb->board->enable)
+		fb->board->enable(fb);
+}
+
+static int
+clcdfb_set_bitfields(struct clcd_fb *fb, struct fb_var_screeninfo *var)
+{
+	int ret = 0;
+
+	memset(&var->transp, 0, sizeof(var->transp));
+	memset(&var->red, 0, sizeof(var->red));
+	memset(&var->green, 0, sizeof(var->green));
+	memset(&var->blue, 0, sizeof(var->blue));
+
+	switch (var->bits_per_pixel) {
+	case 1:
+	case 2:
+	case 4:
+	case 8:
+		var->red.length		= 8;
+		var->red.offset		= 0;
+		var->green.length	= 8;
+		var->green.offset	= 0;
+		var->blue.length	= 8;
+		var->blue.offset	= 0;
+		break;
+	case 16:
+		var->red.length		= 5;
+		var->green.length	= 5;
+		var->blue.length	= 5;
+		if (fb->panel->cntl & CNTL_BGR) {
+			var->red.offset		= 10;
+			var->green.offset	= 5;
+			var->blue.offset	= 0;
+		} else {
+			var->red.offset		= 0;
+			var->green.offset	= 5;
+			var->blue.offset	= 10;
+		}
+		break;
+	case 24:
+		if (fb->panel->cntl & CNTL_LCDTFT) {
+			var->red.length		= 8;
+			var->green.length	= 8;
+			var->blue.length	= 8;
+
+			if (fb->panel->cntl & CNTL_BGR) {
+				var->red.offset		= 16;
+				var->green.offset	= 8;
+				var->blue.offset	= 0;
+			} else {
+				var->red.offset		= 0;
+				var->green.offset	= 8;
+				var->blue.offset	= 16;
+			}
+			break;
+		}
+	default:
+		ret = -EINVAL;
+		break;
+	}
+
+	return ret;
+}
+
+static int clcdfb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
+{
+	struct clcd_fb *fb = to_clcd(info);
+	int ret = -EINVAL;
+
+	if (fb->board->check)
+		ret = fb->board->check(fb, var);
+	if (ret == 0)
+		ret = clcdfb_set_bitfields(fb, var);
+
+	return ret;
+}
+
+static int clcdfb_set_par(struct fb_info *info)
+{
+	struct clcd_fb *fb = to_clcd(info);
+	struct clcd_regs regs;
+
+	fb->fb.fix.line_length = fb->fb.var.xres_virtual *
+				 fb->fb.var.bits_per_pixel / 8;
+
+	if (fb->fb.var.bits_per_pixel <= 8)
+		fb->fb.fix.visual = FB_VISUAL_PSEUDOCOLOR;
+	else
+		fb->fb.fix.visual = FB_VISUAL_TRUECOLOR;
+
+	fb->board->decode(fb, &regs);
+
+	clcdfb_disable(fb);
+
+	writel(regs.tim0, fb->regs + CLCD_TIM0);
+	writel(regs.tim1, fb->regs + CLCD_TIM1);
+	writel(regs.tim2, fb->regs + CLCD_TIM2);
+	writel(regs.tim3, fb->regs + CLCD_TIM3);
+
+	clcdfb_set_start(fb);
+
+	clk_set_rate(fb->clk, (1000000000 / regs.pixclock) * 1000);
+
+	fb->clcd_cntl = regs.cntl;
+
+	clcdfb_enable(fb, regs.cntl);
+
+#ifdef DEBUG
+	printk(KERN_INFO "CLCD: Registers set to\n"
+	       KERN_INFO "  %08x %08x %08x %08x\n"
+	       KERN_INFO "  %08x %08x %08x %08x\n",
+		readl(fb->regs + CLCD_TIM0), readl(fb->regs + CLCD_TIM1),
+		readl(fb->regs + CLCD_TIM2), readl(fb->regs + CLCD_TIM3),
+		readl(fb->regs + CLCD_UBAS), readl(fb->regs + CLCD_LBAS),
+		readl(fb->regs + CLCD_IENB), readl(fb->regs + CLCD_CNTL));
+#endif
+
+	return 0;
+}
+
+static inline u32 convert_bitfield(int val, struct fb_bitfield *bf)
+{
+	unsigned int mask = (1 << bf->length) - 1;
+
+	return (val >> (16 - bf->length) & mask) << bf->offset;
+}
+
+/*
+ *  Set a single color register. The values supplied have a 16 bit
+ *  magnitude.  Return != 0 for invalid regno.
+ */
+static int
+clcdfb_setcolreg(unsigned int regno, unsigned int red, unsigned int green,
+		 unsigned int blue, unsigned int transp, struct fb_info *info)
+{
+	struct clcd_fb *fb = to_clcd(info);
+
+	if (regno < 16)
+		fb->cmap[regno] = convert_bitfield(transp, &fb->fb.var.transp) |
+				  convert_bitfield(blue, &fb->fb.var.blue) |
+				  convert_bitfield(green, &fb->fb.var.green) |
+				  convert_bitfield(red, &fb->fb.var.red);
+
+	if (fb->fb.var.bits_per_pixel == 8 && regno < 256) {
+		int hw_reg = CLCD_PALETTE + ((regno * 2) & ~3);
+		u32 val, mask, newval;
+
+		newval  = (red >> 11)  & 0x001f;
+		newval |= (green >> 6) & 0x03e0;
+		newval |= (blue >> 1)  & 0x7c00;
+
+		/*
+		 * 3.2.11: if we're configured for big endian
+		 * byte order, the palette entries are swapped.
+		 */
+		if (fb->clcd_cntl & CNTL_BEBO)
+			regno ^= 1;
+
+		if (regno & 1) {
+			newval <<= 16;
+			mask = 0x0000ffff;
+		} else {
+			mask = 0xffff0000;
+		}
+
+		val = readl(fb->regs + hw_reg) & mask;
+		writel(val | newval, fb->regs + hw_reg);
+	}
+
+	return regno > 255;
+}
+
+/*
+ *  Blank the screen if blank_mode != 0, else unblank. If blank == NULL
+ *  then the caller blanks by setting the CLUT (Color Look Up Table) to all
+ *  black. Return 0 if blanking succeeded, != 0 if un-/blanking failed due
+ *  to e.g. a video mode which doesn't support it. Implements VESA suspend
+ *  and powerdown modes on hardware that supports disabling hsync/vsync:
+ *    blank_mode == 2: suspend vsync
+ *    blank_mode == 3: suspend hsync
+ *    blank_mode == 4: powerdown
+ */
+static int clcdfb_blank(int blank_mode, struct fb_info *info)
+{
+	struct clcd_fb *fb = to_clcd(info);
+
+	if (blank_mode != 0) {
+		clcdfb_disable(fb);
+	} else {
+		clcdfb_enable(fb, fb->clcd_cntl);
+	}
+	return 0;
+}
+
+static struct fb_ops clcdfb_ops = {
+	.owner		= THIS_MODULE,
+	.fb_check_var	= clcdfb_check_var,
+	.fb_set_par	= clcdfb_set_par,
+	.fb_setcolreg	= clcdfb_setcolreg,
+	.fb_blank	= clcdfb_blank,
+	.fb_fillrect	= cfb_fillrect,
+	.fb_copyarea	= cfb_copyarea,
+	.fb_imageblit	= cfb_imageblit,
+	.fb_cursor	= soft_cursor,
+};
+
+static int clcdfb_register(struct clcd_fb *fb)
+{
+	int ret;
+
+	fb->clk = clk_get(&fb->dev->dev, "CLCDCLK");
+	if (IS_ERR(fb->clk)) {
+		ret = PTR_ERR(fb->clk);
+		goto out;
+	}
+
+	ret = clk_use(fb->clk);
+	if (ret)
+		goto free_clk;
+
+	fb->fb.fix.mmio_start	= fb->dev->res.start;
+	fb->fb.fix.mmio_len	= SZ_4K;
+
+	fb->regs = ioremap(fb->fb.fix.mmio_start, fb->fb.fix.mmio_len);
+	if (!fb->regs) {
+		printk(KERN_ERR "CLCD: unable to remap registers\n");
+		ret = -ENOMEM;
+		goto unuse_clk;
+	}
+
+	fb->fb.fbops		= &clcdfb_ops;
+	fb->fb.flags		= FBINFO_FLAG_DEFAULT;
+	fb->fb.pseudo_palette	= fb->cmap;
+
+	strncpy(fb->fb.fix.id, clcd_name, sizeof(fb->fb.fix.id));
+	fb->fb.fix.type		= FB_TYPE_PACKED_PIXELS;
+	fb->fb.fix.type_aux	= 0;
+	fb->fb.fix.xpanstep	= 0;
+	fb->fb.fix.ypanstep	= 0;
+	fb->fb.fix.ywrapstep	= 0;
+	fb->fb.fix.accel	= FB_ACCEL_NONE;
+
+	fb->fb.var.xres		= fb->panel->mode.xres;
+	fb->fb.var.yres		= fb->panel->mode.yres;
+	fb->fb.var.xres_virtual	= fb->panel->mode.xres;
+	fb->fb.var.yres_virtual	= fb->panel->mode.yres;
+	fb->fb.var.bits_per_pixel = fb->panel->bpp;
+	fb->fb.var.grayscale	= fb->panel->grayscale;
+	fb->fb.var.pixclock	= fb->panel->mode.pixclock;
+	fb->fb.var.left_margin	= fb->panel->mode.left_margin;
+	fb->fb.var.right_margin	= fb->panel->mode.right_margin;
+	fb->fb.var.upper_margin	= fb->panel->mode.upper_margin;
+	fb->fb.var.lower_margin	= fb->panel->mode.lower_margin;
+	fb->fb.var.hsync_len	= fb->panel->mode.hsync_len;
+	fb->fb.var.vsync_len	= fb->panel->mode.vsync_len;
+	fb->fb.var.sync		= fb->panel->mode.sync;
+	fb->fb.var.vmode	= fb->panel->mode.vmode;
+	fb->fb.var.activate	= FB_ACTIVATE_NOW;
+	fb->fb.var.nonstd	= 0;
+	fb->fb.var.height	= fb->panel->height;
+	fb->fb.var.width	= fb->panel->width;
+	fb->fb.var.accel_flags	= 0;
+
+	fb->fb.monspecs.hfmin	= 0;
+	fb->fb.monspecs.hfmax   = 100000;
+	fb->fb.monspecs.vfmin	= 0;
+	fb->fb.monspecs.vfmax	= 400;
+	fb->fb.monspecs.dclkmin = 1000000;
+	fb->fb.monspecs.dclkmax	= 100000000;
+
+	/*
+	 * Make sure that the bitfields are set appropriately.
+	 */
+	clcdfb_set_bitfields(fb, &fb->fb.var);
+
+	/*
+	 * Allocate colourmap.
+	 */
+	fb_alloc_cmap(&fb->fb.cmap, 256, 0);
+
+	/*
+	 * Ensure interrupts are disabled.
+	 */
+	writel(0, fb->regs + CLCD_IENB);
+
+	fb_set_var(&fb->fb, &fb->fb.var);
+
+        printk(KERN_INFO "CLCD: %s hardware, %s display\n",
+               fb->board->name, fb->panel->mode.name);
+
+	ret = register_framebuffer(&fb->fb);
+	if (ret == 0)
+		goto out;
+
+	printk(KERN_ERR "CLCD: cannot register framebuffer (%d)\n", ret);
+
+	iounmap(fb->regs);
+ unuse_clk:
+	clk_unuse(fb->clk);
+ free_clk:
+	clk_put(fb->clk);
+ out:
+	return ret;
+}
+
+static int clcdfb_probe(struct amba_device *dev, void *id)
+{
+	struct clcd_board *board = dev->dev.platform_data;
+	struct clcd_fb *fb;
+	int ret;
+
+	if (!board)
+		return -EINVAL;
+
+	ret = amba_request_regions(dev, NULL);
+	if (ret) {
+		printk(KERN_ERR "CLCD: unable to reserve regs region\n");
+		goto out;
+	}
+
+	fb = (struct clcd_fb *) kmalloc(sizeof(struct clcd_fb), GFP_KERNEL);
+	if (!fb) {
+		printk(KERN_INFO "CLCD: could not allocate new clcd_fb struct\n");
+		ret = -ENOMEM;
+		goto free_region;
+	}
+	memset(fb, 0, sizeof(struct clcd_fb));
+
+	fb->dev = dev;
+	fb->board = board;
+
+	ret = fb->board->setup(fb);
+	if (ret)
+		goto free_fb;
+
+	ret = clcdfb_register(fb); 
+	if (ret == 0) {
+		amba_set_drvdata(dev, fb);
+		goto out;
+	}
+
+	fb->board->remove(fb);
+ free_fb:
+	kfree(fb);
+ free_region:
+	amba_release_regions(dev);
+ out:
+	return ret;
+}
+
+static int clcdfb_remove(struct amba_device *dev)
+{
+	struct clcd_fb *fb = amba_get_drvdata(dev);
+
+	amba_set_drvdata(dev, NULL);
+
+	clcdfb_disable(fb);
+	unregister_framebuffer(&fb->fb);
+	iounmap(fb->regs);
+	clk_unuse(fb->clk);
+	clk_put(fb->clk);
+
+	fb->board->remove(fb);
+
+	kfree(fb);
+
+	amba_release_regions(dev);
+
+	return 0;
+}
+
+static struct amba_id clcdfb_id_table[] = {
+	{
+		.id	= 0x00041110,
+		.mask	= 0x000fffff,
+	},
+	{ 0, 0 },
+};
+
+static struct amba_driver clcd_driver = {
+	.drv 		= {
+		.name	= "clcd-pl110",
+	},
+	.probe		= clcdfb_probe,
+	.remove		= clcdfb_remove,
+	.id_table	= clcdfb_id_table,
+};
+
+int __init amba_clcdfb_init(void)
+{
+	if (fb_get_options("ambafb", NULL))
+		return -ENODEV;
+
+	return amba_driver_register(&clcd_driver);
+}
+
+module_init(amba_clcdfb_init);
+
+static void __exit amba_clcdfb_exit(void)
+{
+	amba_driver_unregister(&clcd_driver);
+}
+
+module_exit(amba_clcdfb_exit);
+
+MODULE_DESCRIPTION("ARM PrimeCell PL110 CLCD core driver");
+MODULE_LICENSE("GPL");
diff -Nru a/drivers/video/amifb.c b/drivers/video/amifb.c
--- a/drivers/video/amifb.c	2004-10-18 14:56:50 -07:00
+++ b/drivers/video/amifb.c	2004-10-18 14:56:50 -07:00
@@ -1307,6 +1307,8 @@
 		info->fix.ywrapstep = 1;
 		info->fix.xpanstep = 0;
 		info->fix.ypanstep = 0;
+		info->flags = FBINFO_DEFAULT | FBINFO_HWACCEL_YWRAP |
+		    FBINFO_READS_FAST; /* override SCROLL_REDRAW */
 	} else {
 		info->fix.ywrapstep = 0;
 		if (par->vmode & FB_VMODE_SMOOTH_XPAN)
@@ -1314,6 +1316,7 @@
 		else
 			info->fix.xpanstep = 16<<maxfmode;
 		info->fix.ypanstep = 1;
+		info->flags = FBINFO_DEFAULT | FBINFO_HWACCEL_YPAN;
 	}
 	return 0;
 }
@@ -2254,6 +2257,13 @@
 	u_long chipptr;
 	u_int defmode;
 
+#ifndef MODULE
+	char *option = NULL;
+
+	if (fb_get_options("amifb", &option))
+		return -ENODEV;
+	amifb_setup(option);
+#endif
 	if (!MACH_IS_AMIGA || !AMIGAHW_PRESENT(AMI_VIDEO))
 		return -ENXIO;
 
@@ -2382,7 +2392,7 @@
 
 	fb_info.fbops = &amifb_ops;
 	fb_info.par = &currentpar;
-	fb_info.flags = FBINFO_FLAG_DEFAULT;
+	fb_info.flags = FBINFO_DEFAULT;
 
 	if (!fb_find_mode(&fb_info.var, &fb_info, mode_option, ami_modedb,
 			  NUM_TOTAL_MODES, &ami_modedb[defmode], 4)) {
@@ -3811,13 +3821,10 @@
 }
 
 
+module_init(amifb_init);
+
 #ifdef MODULE
 MODULE_LICENSE("GPL");
-
-int init_module(void)
-{
-	return amifb_init();
-}
 
 void cleanup_module(void)
 {
diff -Nru a/drivers/video/asiliantfb.c b/drivers/video/asiliantfb.c
--- a/drivers/video/asiliantfb.c	2004-10-18 14:57:03 -07:00
+++ b/drivers/video/asiliantfb.c	2004-10-18 14:57:03 -07:00
@@ -524,7 +524,7 @@
 	p->fix.smem_start	= addr;
 	p->var			= asiliantfb_var;
 	p->fbops		= &asiliantfb_ops;
-	p->flags		= FBINFO_FLAG_DEFAULT;
+	p->flags		= FBINFO_DEFAULT;
 
 	fb_alloc_cmap(&p->cmap, 256, 0);
 
@@ -609,8 +609,13 @@
 
 int __init asiliantfb_init(void)
 {
+	if (fb_get_options("asiliantfb", NULL))
+		return -ENODEV;
+
 	return pci_module_init(&asiliantfb_driver);
 }
+
+module_init(asiliantfb_init);
 
 static void __exit asiliantfb_exit(void)
 {
diff -Nru a/drivers/video/aty/aty128fb.c b/drivers/video/aty/aty128fb.c
--- a/drivers/video/aty/aty128fb.c	2004-10-18 14:56:29 -07:00
+++ b/drivers/video/aty/aty128fb.c	2004-10-18 14:56:29 -07:00
@@ -2439,6 +2439,14 @@
 
 int __init aty128fb_init(void)
 {
+#ifndef MODULE
+	char *option = NULL;
+
+	if (fb_get_options("aty128fb", &option))
+		return -ENODEV;
+	aty128fb_setup(option);
+#endif
+
 	return pci_module_init(&aty128fb_driver);
 }
 
@@ -2447,8 +2455,9 @@
 	pci_unregister_driver(&aty128fb_driver);
 }
 
-#ifdef MODULE
 module_init(aty128fb_init);
+
+#ifdef MODULE
 module_exit(aty128fb_exit);
 
 MODULE_AUTHOR("(c)1999-2003 Brad Douglas <brad@neruo.com>");
diff -Nru a/drivers/video/aty/atyfb_base.c b/drivers/video/aty/atyfb_base.c
--- a/drivers/video/aty/atyfb_base.c	2004-10-18 14:56:48 -07:00
+++ b/drivers/video/aty/atyfb_base.c	2004-10-18 14:56:48 -07:00
@@ -1902,7 +1902,7 @@
 	return 1;
 }
 
-int __init atyfb_init(void)
+int __init atyfb_do_init(void)
 {
 #if defined(CONFIG_PCI)
 	unsigned long addr, res_start, res_size;
@@ -1917,12 +1917,14 @@
 	char prop[128];
 	int node, len, j;
 	u32 mem, chip_id;
+#else
+	u16 tmp;
+#endif
 
+#ifdef __sparc__
 	/* Do not attach when we have a serial console. */
 	if (!con_is_present())
 		return -ENXIO;
-#else
-	u16 tmp;
 #endif
 
 	while ((pdev =
@@ -2377,6 +2379,19 @@
 	return 0;
 }
 
+int __init atyfb_init(void)
+{
+#ifndef MODULE
+	char *option = NULL;
+
+	if (fb_get_options("atyfb", &option))
+		return -ENODEV;
+	atyfb_setup(option);
+#endif
+	return atyfb_do_init();
+}
+
+
 #ifndef MODULE
 int __init atyfb_setup(char *options)
 {
@@ -2445,6 +2460,7 @@
 	}
 	return 0;
 }
+module_init(atyfb_init);
 #endif				/* !MODULE */
 
 #ifdef CONFIG_ATARI
diff -Nru a/drivers/video/aty/radeon_base.c b/drivers/video/aty/radeon_base.c
--- a/drivers/video/aty/radeon_base.c	2004-10-18 14:56:28 -07:00
+++ b/drivers/video/aty/radeon_base.c	2004-10-18 14:56:28 -07:00
@@ -282,7 +282,7 @@
 
 static int __devinit radeon_map_ROM(struct radeonfb_info *rinfo, struct pci_dev *dev)
 {
-	void *rom;
+	void __iomem *rom;
 	struct resource *r;
 	u16 dptr;
 	u8 rom_type;
@@ -395,13 +395,13 @@
 	 * if we end up having conflicts
 	 */
         u32  segstart;
-        unsigned char *rom_base = NULL;
+	void __iomem *rom_base = NULL;
                                                 
         for(segstart=0x000c0000; segstart<0x000f0000; segstart+=0x00001000) {
-                rom_base = (char *)ioremap(segstart, 0x10000);
+                rom_base = ioremap(segstart, 0x10000);
 		if (rom_base == NULL)
 			return -ENOMEM;
-                if ((*rom_base == 0x55) && (((*(rom_base + 1)) & 0xff) == 0xaa))
+                if (readb(rom_base) == 0x55 && readb(rom_base + 1) == 0xaa)
 	                break;
                 iounmap(rom_base);
 		rom_base = NULL;
@@ -1702,68 +1702,6 @@
 }
 
 
-
-static ssize_t radeonfb_read(struct file *file, char __user *buf, size_t count, loff_t *ppos)
-{
-	unsigned long p = *ppos;
-	struct inode *inode = file->f_dentry->d_inode;
-	int fbidx = iminor(inode);
-	struct fb_info *info = registered_fb[fbidx];
-	struct radeonfb_info *rinfo = info->par;
-	
-	if (p >= rinfo->mapped_vram)
-	    return 0;
-	if (count >= rinfo->mapped_vram)
-	    count = rinfo->mapped_vram;
-	if (count + p > rinfo->mapped_vram)
-		count = rinfo->mapped_vram - p;
-	radeonfb_sync(info);
-	if (count) {
-	    char *base_addr;
-
-	    base_addr = info->screen_base;
-	    count -= copy_to_user(buf, base_addr+p, count);
-	    if (!count)
-		return -EFAULT;
-	    *ppos += count;
-	}
-	return count;
-}
-
-static ssize_t radeonfb_write(struct file *file, const char __user *buf, size_t count,
-			      loff_t *ppos)
-{
-	unsigned long p = *ppos;
-	struct inode *inode = file->f_dentry->d_inode;
-	int fbidx = iminor(inode);
-	struct fb_info *info = registered_fb[fbidx];
-	struct radeonfb_info *rinfo = info->par;
-	int err;
-
-	if (p > rinfo->mapped_vram)
-	    return -ENOSPC;
-	if (count >= rinfo->mapped_vram)
-	    count = rinfo->mapped_vram;
-	err = 0;
-	if (count + p > rinfo->mapped_vram) {
-	    count = rinfo->mapped_vram - p;
-	    err = -ENOSPC;
-	}
-	radeonfb_sync(info);
-	if (count) {
-	    char *base_addr;
-
-	    base_addr = info->screen_base;
-	    count -= copy_from_user(base_addr+p, buf, count);
-	    *ppos += count;
-	    err = -EFAULT;
-	}
-	if (count)
-		return count;
-	return err;
-}
-
-
 static struct fb_ops radeonfb_ops = {
 	.owner			= THIS_MODULE,
 	.fb_check_var		= radeonfb_check_var,
@@ -1776,8 +1714,6 @@
 	.fb_fillrect		= radeonfb_fillrect,
 	.fb_copyarea		= radeonfb_copyarea,
 	.fb_imageblit		= radeonfb_imageblit,
-	.fb_read		= radeonfb_read,
-	.fb_write		= radeonfb_write,
 	.fb_cursor		= soft_cursor,
 };
 
@@ -1795,8 +1731,8 @@
 		    | FBINFO_HWACCEL_XPAN
 		    | FBINFO_HWACCEL_YPAN;
 	info->fbops = &radeonfb_ops;
-	info->screen_base = (char *)rinfo->fb_base;
-
+	info->screen_base = rinfo->fb_base;
+	info->screen_size = rinfo->mapped_vram;
 	/* Fill fix common fields */
 	strlcpy(info->fix.id, rinfo->name, sizeof(info->fix.id));
         info->fix.smem_start = rinfo->fb_base_phys;
@@ -1932,7 +1868,7 @@
 #undef SET_MC_FB_FROM_APERTURE
 static void fixup_memory_mappings(struct radeonfb_info *rinfo)
 {
-	u32 save_crtc_gen_cntl, save_crtc2_gen_cntl;
+	u32 save_crtc_gen_cntl, save_crtc2_gen_cntl = 0;
 	u32 save_crtc_ext_cntl;
 	u32 aper_base, aper_size;
 	u32 agp_base;
@@ -2069,19 +2005,22 @@
 	struct fb_info *info;
 	struct radeonfb_info *rinfo;
 	u32 tmp;
+	int ret;
 
 	RTRACE("radeonfb_pci_register BEGIN\n");
 	
 	/* Enable device in PCI config */
-	if (pci_enable_device(pdev) != 0) {
+	ret = pci_enable_device(pdev);
+	if (ret < 0) {
 		printk(KERN_ERR "radeonfb: Cannot enable PCI device\n");
-		return -ENODEV;
+		goto err_out;
 	}
 
 	info = framebuffer_alloc(sizeof(struct radeonfb_info), &pdev->dev);
 	if (!info) {
 		printk (KERN_ERR "radeonfb: could not allocate memory\n");
-		return -ENODEV;
+		ret = -ENOMEM;
+		goto err_disable;
 	}
 	rinfo = info->par;
 	rinfo->info = info;	
@@ -2106,23 +2045,19 @@
 	rinfo->mmio_base_phys = pci_resource_start (pdev, 2);
 
 	/* request the mem regions */
-	if (!request_mem_region (rinfo->fb_base_phys,
-				 pci_resource_len(pdev, 0), "radeonfb")) {
-		printk (KERN_ERR "radeonfb: cannot reserve FB region\n");
-		goto free_rinfo;
-	}
-
-	if (!request_mem_region (rinfo->mmio_base_phys,
-				 pci_resource_len(pdev, 2), "radeonfb")) {
-		printk (KERN_ERR "radeonfb: cannot reserve MMIO region\n");
-		goto release_fb;
+	ret = pci_request_regions(pdev, "radeonfb");
+	if (ret < 0) {
+		printk( KERN_ERR "radeonfb: cannot reserve PCI regions."
+			"  Someone already got them?\n");
+		goto err_release_fb;
 	}
 
 	/* map the regions */
-	rinfo->mmio_base = (unsigned long) ioremap (rinfo->mmio_base_phys, RADEON_REGSIZE);
+	rinfo->mmio_base = ioremap(rinfo->mmio_base_phys, RADEON_REGSIZE);
 	if (!rinfo->mmio_base) {
-		printk (KERN_ERR "radeonfb: cannot map MMIO\n");
-		goto release_mmio;
+		printk(KERN_ERR "radeonfb: cannot map MMIO\n");
+		ret = -EIO;
+		goto err_release_pci;
 	}
 
 	/* On PPC, the firmware sets up a memory mapping that tends
@@ -2226,33 +2161,24 @@
 
 	RTRACE("radeonfb: probed %s %ldk videoram\n", (rinfo->ram_type), (rinfo->video_ram/1024));
 
-	rinfo->mapped_vram = MAX_MAPPED_VRAM;
-	if (rinfo->video_ram < rinfo->mapped_vram)
-		rinfo->mapped_vram = rinfo->video_ram;
-	for (;;) {
-		rinfo->fb_base = (unsigned long) ioremap (rinfo->fb_base_phys,
-							  rinfo->mapped_vram);
-		if (rinfo->fb_base == 0 && rinfo->mapped_vram > MIN_MAPPED_VRAM) {
-			rinfo->mapped_vram /= 2;
-			continue;
-		}
-		memset_io(rinfo->fb_base, 0, rinfo->mapped_vram);
-		break;
-	}
+	rinfo->mapped_vram = min_t(unsigned long, MAX_MAPPED_VRAM, rinfo->video_ram);
+
+	do {
+		rinfo->fb_base = ioremap (rinfo->fb_base_phys,
+					  rinfo->mapped_vram);
+	} while (   rinfo->fb_base == 0 &&
+		  ((rinfo->mapped_vram /=2) >= MIN_MAPPED_VRAM) );
 
-	if (!rinfo->fb_base) {
+	if (rinfo->fb_base)
+		memset_io(rinfo->fb_base, 0, rinfo->mapped_vram);
+	else {
 		printk (KERN_ERR "radeonfb: cannot map FB\n");
-		goto unmap_rom;
+		ret = -EIO;
+		goto err_unmap_rom;
 	}
 
 	RTRACE("radeonfb: mapped %ldk videoram\n", rinfo->mapped_vram/1024);
 
-
-	/* Argh. Scary arch !!! */
-#ifdef CONFIG_PPC64
-	rinfo->fb_base = IO_TOKEN_TO_ADDR(rinfo->fb_base);
-#endif
-
 	/*
 	 * Check for required workaround for PLL accesses
 	 */
@@ -2330,9 +2256,10 @@
 		printk("radeonfb: Power Management enabled for Mobility chipsets\n");
 	}
 
-	if (register_framebuffer(info) < 0) {
+	ret = register_framebuffer(info);
+	if (ret < 0) {
 		printk (KERN_ERR "radeonfb: could not register framebuffer\n");
-		goto unmap_fb;
+		goto err_unmap_fb;
 	}
 
 #ifdef CONFIG_MTRR
@@ -2358,30 +2285,30 @@
 	RTRACE("radeonfb_pci_register END\n");
 
 	return 0;
-unmap_fb:
-	iounmap ((void*)rinfo->fb_base);
-unmap_rom:	
+err_unmap_fb:
+	iounmap(rinfo->fb_base);
+err_unmap_rom:
 	if (rinfo->mon1_EDID)
 	    kfree(rinfo->mon1_EDID);
 	if (rinfo->mon2_EDID)
 	    kfree(rinfo->mon2_EDID);
 	if (rinfo->mon1_modedb)
 		fb_destroy_modedb(rinfo->mon1_modedb);
+	fb_dealloc_cmap(&info->cmap);
 #ifdef CONFIG_FB_RADEON_I2C
 	radeon_delete_i2c_busses(rinfo);
 #endif
 	if (rinfo->bios_seg)
 		radeon_unmap_ROM(rinfo, pdev);
-	iounmap ((void*)rinfo->mmio_base);
-release_mmio:
-	release_mem_region (rinfo->mmio_base_phys,
-			    pci_resource_len(pdev, 2));
-release_fb:	
-	release_mem_region (rinfo->fb_base_phys,
-			    pci_resource_len(pdev, 0));
-free_rinfo:	
+	iounmap(rinfo->mmio_base);
+err_release_pci:
+	pci_release_regions(pdev);
+err_release_fb:
 	framebuffer_release(info);
-	return -ENODEV;
+err_disable:
+	pci_disable_device(pdev);
+err_out:
+	return ret;
 }
 
 
@@ -2410,13 +2337,10 @@
 
         unregister_framebuffer(info);
 
-        iounmap ((void*)rinfo->mmio_base);
-        iounmap ((void*)rinfo->fb_base);
+        iounmap(rinfo->mmio_base);
+        iounmap(rinfo->fb_base);
  
-	release_mem_region (rinfo->mmio_base_phys,
-			    pci_resource_len(pdev, 2));
-	release_mem_region (rinfo->fb_base_phys,
-			    pci_resource_len(pdev, 0));
+ 	pci_release_regions(pdev);
 
 	if (rinfo->mon1_EDID)
 		kfree(rinfo->mon1_EDID);
@@ -2427,7 +2351,9 @@
 #ifdef CONFIG_FB_RADEON_I2C
 	radeon_delete_i2c_busses(rinfo);
 #endif        
+	fb_dealloc_cmap(&info->cmap);
         framebuffer_release(info);
+	pci_disable_device(pdev);
 }
 
 
@@ -2442,9 +2368,17 @@
 #endif /* CONFIG_PM */
 };
 
+int __init radeonfb_setup (char *options);
 
 int __init radeonfb_init (void)
 {
+#ifndef MODULE
+	char *option = NULL;
+
+	if (fb_get_options("radeonfb", &option))
+		return -ENODEV;
+	radeonfb_setup(option);
+#endif
 	return pci_module_init (&radeonfb_driver);
 }
 
@@ -2489,9 +2423,9 @@
 	return 0;
 }
 
+module_init(radeonfb_init);
 
 #ifdef MODULE
-module_init(radeonfb_init);
 module_exit(radeonfb_exit);
 #endif
 
diff -Nru a/drivers/video/aty/radeon_monitor.c b/drivers/video/aty/radeon_monitor.c
--- a/drivers/video/aty/radeon_monitor.c	2004-10-18 14:55:46 -07:00
+++ b/drivers/video/aty/radeon_monitor.c	2004-10-18 14:55:46 -07:00
@@ -55,7 +55,7 @@
 	u8 *pedid = NULL;
 	u8 *pmt = NULL;
 	u8 *tmp;
-        int i, mt;  
+        int i, mt = MT_NONE;  
 	
 	RTRACE("analyzing OF properties...\n");
 	pmt = (u8 *)get_property(dp, "display-type", NULL);
@@ -72,7 +72,9 @@
 	else if (strcmp(pmt, "NONE")) {
 		printk(KERN_WARNING "radeonfb: Unknown OF display-type: %s\n", pmt);
 		return MT_NONE;
-	}
+	} else
+		return MT_NONE;
+
 	for (i = 0; propnames[i] != NULL; ++i) {
 		pedid = (u8 *)get_property(dp, propnames[i], NULL);
 		if (pedid != NULL)
@@ -645,15 +647,23 @@
 		rinfo->panel_info.fbk_divider = 0xad;
 		rinfo->panel_info.use_bios_dividers = 1;
 	}
+	/* Aluminium PowerBook 15" */
+	if (machine_is_compatible("PowerBook5,4")) {
+		rinfo->panel_info.ref_divider = rinfo->pll.ref_div;
+		rinfo->panel_info.post_divider = 0x2;
+		rinfo->panel_info.fbk_divider = 0x8e;
+		rinfo->panel_info.use_bios_dividers = 1;
+	}
 	/* Aluminium PowerBook 17" */
-	if (machine_is_compatible("PowerBook5,3")) {
+	if (machine_is_compatible("PowerBook5,3") ||
+	    machine_is_compatible("PowerBook5,5")) {
 		rinfo->panel_info.ref_divider = rinfo->pll.ref_div;
 		rinfo->panel_info.post_divider = 0x4;
 		rinfo->panel_info.fbk_divider = 0x80;
 		rinfo->panel_info.use_bios_dividers = 1;
 	}
 	/* iBook G4 */
-        if (machine_is_compatible("PowerBook6,3") |
+        if (machine_is_compatible("PowerBook6,3") ||
             machine_is_compatible("PowerBook6,5")) {
 		rinfo->panel_info.ref_divider = rinfo->pll.ref_div;
 		rinfo->panel_info.post_divider = 0x6;
diff -Nru a/drivers/video/aty/radeonfb.h b/drivers/video/aty/radeonfb.h
--- a/drivers/video/aty/radeonfb.h	2004-10-18 14:57:19 -07:00
+++ b/drivers/video/aty/radeonfb.h	2004-10-18 14:57:19 -07:00
@@ -262,14 +262,14 @@
 	unsigned long		mmio_base_phys;
 	unsigned long		fb_base_phys;
 
-	unsigned long		mmio_base;
-	unsigned long		fb_base;
+	void __iomem		*mmio_base;
+	void __iomem		*fb_base;
 
-	unsigned long 		fb_local_base;
+	unsigned long		fb_local_base;
 
 	struct pci_dev		*pdev;
 
-	u8			*bios_seg;
+	void __iomem		*bios_seg;
 	int			fp_bios_start;
 
 	u32			pseudo_palette[17];
diff -Nru a/drivers/video/bw2.c b/drivers/video/bw2.c
--- a/drivers/video/bw2.c	2004-10-18 14:56:33 -07:00
+++ b/drivers/video/bw2.c	2004-10-18 14:56:33 -07:00
@@ -323,7 +323,7 @@
 		resp = &res;
 		all->info.var.xres = all->info.var.xres_virtual = 1152;
 		all->info.var.yres = all->info.var.yres_virtual = 900;
-		all->info.bits_per_pixel = 1;
+		all->info.var.bits_per_pixel = 1;
 		linebytes = 1152 / 8;
 	} else
 #else
@@ -337,6 +337,10 @@
 					       all->info.var.xres);
 	}
 #endif
+	all->info.var.red.length = all->info.var.green.length =
+		all->info.var.blue.length = all->info.var.bits_per_pixel;
+	all->info.var.red.offset = all->info.var.green.offset =
+		all->info.var.blue.offset = 0;
 
 	all->par.regs = (struct bw2_regs *)
 		sbus_ioremap(resp, BWTWO_REGISTER_OFFSET,
@@ -347,7 +351,7 @@
 
 	all->par.fbsize = PAGE_ALIGN(linebytes * all->info.var.yres);
 
-	all->info.flags = FBINFO_FLAG_DEFAULT;
+	all->info.flags = FBINFO_DEFAULT;
 	all->info.fbops = &bw2_ops;
 #if defined(CONFIG_SPARC32)
 	if (sdev)
@@ -382,6 +386,9 @@
 	struct sbus_bus *sbus;
 	struct sbus_dev *sdev;
 
+	if (fb_get_options("bw2fb", &option))
+		return -ENODEV;
+
 #ifdef CONFIG_SUN4
 	bw2_init_one(NULL);
 #endif
@@ -412,8 +419,9 @@
 	return 0;
 }
 
-#ifdef MODULE
 module_init(bw2_init);
+
+#ifdef MODULE
 module_exit(bw2_exit);
 #endif
 
diff -Nru a/drivers/video/cfbcopyarea.c b/drivers/video/cfbcopyarea.c
--- a/drivers/video/cfbcopyarea.c	2004-10-18 14:57:03 -07:00
+++ b/drivers/video/cfbcopyarea.c	2004-10-18 14:57:03 -07:00
@@ -43,8 +43,9 @@
 #define BYTES_PER_LONG 8
 #endif
 
-static void bitcpy(unsigned long *dst, int dst_idx, const unsigned long *src,
-		   int src_idx, unsigned long n)
+static void bitcpy(unsigned long __iomem *dst, int dst_idx,
+		   const unsigned long __iomem *src, int src_idx,
+		   unsigned long n)
 {
 	unsigned long first, last;
 	int shift = dst_idx-src_idx, left, right;
@@ -185,8 +186,8 @@
 	}
 }
 
-static void bitcpy_rev(unsigned long *dst, int dst_idx,
-		       const unsigned long *src, int src_idx, unsigned long n)
+static void bitcpy_rev(unsigned long __iomem *dst, int dst_idx,
+		       const unsigned long __iomem *src, int src_idx, unsigned long n)
 {
 	unsigned long first, last;
 	int shift = dst_idx-src_idx, left, right;
@@ -344,7 +345,7 @@
 	int x2, y2, old_dx, old_dy, vxres, vyres;
 	unsigned long next_line = p->fix.line_length;
 	int dst_idx = 0, src_idx = 0, rev_copy = 0;
-	unsigned long *dst = NULL, *src = NULL;
+	unsigned long __iomem *dst = NULL, *src = NULL;
 
 	if (p->state != FBINFO_STATE_RUNNING)
 		return;
@@ -394,7 +395,7 @@
 		rev_copy = 1;
 	}
 
-	dst = src = (unsigned long *)((unsigned long)p->screen_base & 
+	dst = src = (unsigned long __iomem *)((unsigned long)p->screen_base & 
 				      ~(BYTES_PER_LONG-1));
 	dst_idx = src_idx = (unsigned long)p->screen_base & (BYTES_PER_LONG-1);
 	dst_idx += dy*next_line*8 + dx*p->var.bits_per_pixel;
diff -Nru a/drivers/video/cfbfillrect.c b/drivers/video/cfbfillrect.c
--- a/drivers/video/cfbfillrect.c	2004-10-18 14:56:32 -07:00
+++ b/drivers/video/cfbfillrect.c	2004-10-18 14:56:32 -07:00
@@ -119,7 +119,7 @@
      *  Unaligned 32-bit pattern fill using 32/64-bit memory accesses
      */
 
-void bitfill32(unsigned long *dst, int dst_idx, u32 pat, u32 n)
+void bitfill32(unsigned long __iomem *dst, int dst_idx, u32 pat, u32 n)
 {
 	unsigned long val = pat;
 	unsigned long first, last;
@@ -178,7 +178,7 @@
      *  used for the next 32/64-bit word
      */
 
-void bitfill(unsigned long *dst, int dst_idx, unsigned long pat, int left,
+void bitfill(unsigned long __iomem *dst, int dst_idx, unsigned long pat, int left,
 	     int right, u32 n)
 {
 	unsigned long first, last;
@@ -228,7 +228,7 @@
 	}
 }
 
-void bitfill32_rev(unsigned long *dst, int dst_idx, u32 pat, u32 n)
+void bitfill32_rev(unsigned long __iomem *dst, int dst_idx, u32 pat, u32 n)
 {
 	unsigned long val = pat, dat;
 	unsigned long first, last;
@@ -300,7 +300,7 @@
      *  used for the next 32/64-bit word
      */
 
-void bitfill_rev(unsigned long *dst, int dst_idx, unsigned long pat, int left,
+void bitfill_rev(unsigned long __iomem *dst, int dst_idx, unsigned long pat, int left,
 	     int right, u32 n)
 {
 	unsigned long first, last, dat;
@@ -364,7 +364,7 @@
 	u32 bpp = p->var.bits_per_pixel;
 	unsigned long x2, y2, vxres, vyres;
 	unsigned long height, width, fg;
-	unsigned long *dst;
+	unsigned long __iomem *dst;
 	int dst_idx, left;
 
 	if (p->state != FBINFO_STATE_RUNNING)
@@ -397,7 +397,7 @@
 	else
 		fg = rect->color;
 	
-	dst = (unsigned long *)((unsigned long)p->screen_base & 
+	dst = (unsigned long __iomem *)((unsigned long)p->screen_base & 
 				~(BYTES_PER_LONG-1));
 	dst_idx = ((unsigned long)p->screen_base & (BYTES_PER_LONG-1))*8;
 	dst_idx += rect->dy*p->fix.line_length*8+rect->dx*bpp;
@@ -407,7 +407,7 @@
 		p->fbops->fb_sync(p);
 	if (!left) {
 		u32 pat = pixel_to_pat32(p, fg);
-		void (*fill_op32)(unsigned long *dst, int dst_idx, u32 pat, 
+		void (*fill_op32)(unsigned long __iomem *dst, int dst_idx, u32 pat, 
 				  u32 n) = NULL;
 		
 		switch (rect->rop) {
@@ -429,7 +429,7 @@
 		unsigned long pat = pixel_to_pat(p, fg, (left-dst_idx) % bpp);
 		int right = bpp-left;
 		int r;
-		void (*fill_op)(unsigned long *dst, int dst_idx, 
+		void (*fill_op)(unsigned long __iomem *dst, int dst_idx, 
 				unsigned long pat, int left, int right, 
 				u32 n) = NULL;
 		
diff -Nru a/drivers/video/cfbimgblt.c b/drivers/video/cfbimgblt.c
--- a/drivers/video/cfbimgblt.c	2004-10-18 14:56:32 -07:00
+++ b/drivers/video/cfbimgblt.c	2004-10-18 14:56:32 -07:00
@@ -87,21 +87,22 @@
 #endif
 
 static inline void color_imageblit(const struct fb_image *image, 
-				   struct fb_info *p, u8 *dst1, 
+				   struct fb_info *p, u8 __iomem *dst1, 
 				   u32 start_index,
 				   u32 pitch_index)
 {
 	/* Draw the penguin */
-	u32 *dst, *dst2, color = 0, val, shift;
+	u32 __iomem *dst, *dst2;
+	u32 color = 0, val, shift;
 	int i, n, bpp = p->var.bits_per_pixel;
 	u32 null_bits = 32 - bpp;
 	u32 *palette = (u32 *) p->pseudo_palette;
 	const u8 *src = image->data;
 
-	dst2 = (u32 *) dst1;
+	dst2 = (u32 __iomem *) dst1;
 	for (i = image->height; i--; ) {
 		n = image->width;
-		dst = (u32 *) dst1;
+		dst = (u32 __iomem *) dst1;
 		shift = 0;
 		val = 0;
 		
@@ -136,7 +137,7 @@
 		dst1 += p->fix.line_length;
 		if (pitch_index) {
 			dst2 += p->fix.line_length;
-			dst1 = (u8 *)((long)dst2 & ~(sizeof(u32) - 1));
+			dst1 = (u8 __iomem *)((long __force)dst2 & ~(sizeof(u32) - 1));
 
 			start_index += pitch_index;
 			start_index &= 32 - 1;
@@ -145,25 +146,26 @@
 }
 
 static inline void slow_imageblit(const struct fb_image *image, struct fb_info *p, 
-				  u8 *dst1, u32 fgcolor,
+				  u8 __iomem *dst1, u32 fgcolor,
 				  u32 bgcolor, 
 				  u32 start_index,
 				  u32 pitch_index)
 {
 	u32 shift, color = 0, bpp = p->var.bits_per_pixel;
-	u32 *dst, *dst2, val, pitch = p->fix.line_length;
+	u32 __iomem *dst, *dst2;
+	u32 val, pitch = p->fix.line_length;
 	u32 null_bits = 32 - bpp;
 	u32 spitch = (image->width+7)/8;
 	const u8 *src = image->data, *s;
 	u32 i, j, l;
 	
-	dst2 = (u32 *) dst1;
+	dst2 = (u32 __iomem *) dst1;
 
 	for (i = image->height; i--; ) {
 		shift = val = 0;
 		l = 8;
 		j = image->width;
-		dst = (u32 *) dst1;
+		dst = (u32 __iomem *) dst1;
 		s = src;
 
 		/* write leading bits */
@@ -201,7 +203,7 @@
 		src += spitch;	
 		if (pitch_index) {
 			dst2 += pitch;
-			dst1 = (u8 *)((long)dst2 & ~(sizeof(u32) - 1));
+			dst1 = (u8 __iomem *)((long __force)dst2 & ~(sizeof(u32) - 1));
 			start_index += pitch_index;
 			start_index &= 32 - 1;
 		}
@@ -218,14 +220,14 @@
  *           beginning and end of a scanline is dword aligned
  */
 static inline void fast_imageblit(const struct fb_image *image, struct fb_info *p, 
-				  u8 *dst1, u32 fgcolor, 
+				  u8 __iomem *dst1, u32 fgcolor, 
 				  u32 bgcolor) 
 {
 	u32 fgx = fgcolor, bgx = bgcolor, bpp = p->var.bits_per_pixel;
 	u32 ppw = 32/bpp, spitch = (image->width + 7)/8;
 	u32 bit_mask, end_mask, eorx, shift;
 	const char *s = image->data, *src;
-	u32 *dst;
+	u32 __iomem *dst;
 	u32 *tab = NULL;
 	int i, j, k;
 		
@@ -253,7 +255,7 @@
 	k = image->width/ppw;
 
 	for (i = image->height; i--; ) {
-		dst = (u32 *) dst1, shift = 8; src = s;
+		dst = (u32 __iomem *) dst1, shift = 8; src = s;
 		
 		for (j = k; j--; ) {
 			shift -= ppw;
@@ -273,7 +275,7 @@
 	u32 width = image->width, height = image->height; 
 	u32 dx = image->dx, dy = image->dy;
 	int x2, y2, vxres, vyres;
-	u8 *dst1;
+	u8 __iomem *dst1;
 
 	if (p->state != FBINFO_STATE_RUNNING)
 		return;
@@ -325,7 +327,7 @@
 		else 
 			slow_imageblit(image, p, dst1, fgcolor, bgcolor,
 					start_index, pitch_index);
-	} else if (image->depth <= bpp) 
+	} else
 		color_imageblit(image, p, dst1, start_index, pitch_index);
 }
 
diff -Nru a/drivers/video/cg14.c b/drivers/video/cg14.c
--- a/drivers/video/cg14.c	2004-10-18 14:57:04 -07:00
+++ b/drivers/video/cg14.c	2004-10-18 14:57:04 -07:00
@@ -550,7 +550,7 @@
 	all->par.mode = MDI_8_PIX;
 	all->par.ramsize = (is_8mb ? 0x800000 : 0x400000);
 
-	all->info.flags = FBINFO_FLAG_DEFAULT;
+	all->info.flags = FBINFO_DEFAULT | FBINFO_HWACCEL_YPAN;
 	all->info.fbops = &cg14_ops;
 	all->info.currcon = -1;
 	all->info.par = &all->par;
@@ -584,6 +584,9 @@
 	struct sbus_bus *sbus;
 	struct sbus_dev *sdev;
 
+	if (fb_get_options("cg14fb", NULL))
+		return -ENODEV;
+
 #ifdef CONFIG_SPARC32
 	{
 		int root, node;
@@ -626,8 +629,9 @@
 	return 0;
 }
 
-#ifdef MODULE
 module_init(cg14_init);
+
+#ifdef MODULE
 module_exit(cg14_exit);
 #endif
 
diff -Nru a/drivers/video/cg3.c b/drivers/video/cg3.c
--- a/drivers/video/cg3.c	2004-10-18 14:56:33 -07:00
+++ b/drivers/video/cg3.c	2004-10-18 14:56:33 -07:00
@@ -398,7 +398,7 @@
 		sbus_ioremap(&sdev->resource[0], CG3_REGS_OFFSET,
 			     sizeof(struct cg3_regs), "cg3 regs");
 
-	all->info.flags = FBINFO_FLAG_DEFAULT;
+	all->info.flags = FBINFO_DEFAULT;
 	all->info.fbops = &cg3_ops;
 #ifdef CONFIG_SPARC32
 	all->info.screen_base = (char *)
@@ -444,6 +444,9 @@
 	struct sbus_bus *sbus;
 	struct sbus_dev *sdev;
 
+	if (fb_get_options("cg3fb", NULL))
+		return -ENODEV;
+
 	for_all_sbusdev(sdev, sbus) {
 		if (!strcmp(sdev->prom_name, "cgthree") ||
 		    !strcmp(sdev->prom_name, "cgRDI"))
@@ -473,8 +476,9 @@
 	return 0;
 }
 
-#ifdef MODULE
 module_init(cg3_init);
+
+#ifdef MODULE
 module_exit(cg3_exit);
 #endif
 
diff -Nru a/drivers/video/cg6.c b/drivers/video/cg6.c
--- a/drivers/video/cg6.c	2004-10-18 14:56:27 -07:00
+++ b/drivers/video/cg6.c	2004-10-18 14:56:27 -07:00
@@ -712,7 +712,8 @@
 		sbus_ioremap(&sdev->resource[0], CG6_FHC_OFFSET,
 			     sizeof(u32), "cgsix fhc");
 
-	all->info.flags = FBINFO_FLAG_DEFAULT;
+	all->info.flags = FBINFO_DEFAULT | FBINFO_HWACCEL_IMAGEBLIT |
+                          FBINFO_HWACCEL_COPYAREA | FBINFO_HWACCEL_FILLRECT;
 	all->info.fbops = &cg6_ops;
 #ifdef CONFIG_SPARC32
 	all->info.screen_base = (char *)
@@ -759,6 +760,9 @@
 	struct sbus_bus *sbus;
 	struct sbus_dev *sdev;
 
+	if (fb_get_options("cg6fb", NULL))
+		return -ENODEV;
+
 	for_all_sbusdev(sdev, sbus) {
 		if (!strcmp(sdev->prom_name, "cgsix") ||
 		    !strcmp(sdev->prom_name, "cgthree+"))
@@ -788,8 +792,9 @@
 	return 0;
 }
 
-#ifdef MODULE
 module_init(cg6_init);
+
+#ifdef MODULE
 module_exit(cg6_exit);
 #endif
 
diff -Nru a/drivers/video/chipsfb.c b/drivers/video/chipsfb.c
--- a/drivers/video/chipsfb.c	2004-10-18 14:56:29 -07:00
+++ b/drivers/video/chipsfb.c	2004-10-18 14:56:29 -07:00
@@ -362,7 +362,7 @@
 	p->var = chipsfb_var;
 
 	p->fbops = &chipsfb_ops;
-	p->flags = FBINFO_FLAG_DEFAULT;
+	p->flags = FBINFO_DEFAULT;
 
 	fb_alloc_cmap(&p->cmap, 256, 0);
 
@@ -462,8 +462,13 @@
 
 int __init chips_init(void)
 {
+	if (fb_get_options("chipsfb", NULL))
+		return -ENODEV;
+
 	return pci_module_init(&chipsfb_driver);
 }
+
+module_init(chips_init);
 
 static void __exit chipsfb_exit(void)
 {
diff -Nru a/drivers/video/cirrusfb.c b/drivers/video/cirrusfb.c
--- a/drivers/video/cirrusfb.c	2004-10-18 14:56:50 -07:00
+++ b/drivers/video/cirrusfb.c	2004-10-18 14:56:50 -07:00
@@ -752,6 +752,12 @@
 
 	switch (var->bits_per_pixel) {
 	case 1:
+		var->red.offset = 0;
+		var->red.length = 1;
+		var->green.offset = 0;
+		var->green.length = 1;
+		var->blue.offset = 0;
+		var->blue.length = 1;
 		break;
 
 	case 8:
@@ -2600,6 +2606,14 @@
 {
 	int error = 0;
 
+#ifndef MODULE
+	char *option = NULL;
+
+	if (fb_get_options("cirrusfb", &option))
+		return -ENODEV;
+	cirrusfb_setup(option);
+#endif
+
 #ifdef CONFIG_ZORRO
 	error |= zorro_module_init(&cirrusfb_zorro_driver);
 #endif
@@ -2657,8 +2671,9 @@
 #endif
 }
 
-#ifdef MODULE
 module_init(cirrusfb_init);
+
+#ifdef MODULE
 module_exit(cirrusfb_exit);
 #endif
 
diff -Nru a/drivers/video/clps711xfb.c b/drivers/video/clps711xfb.c
--- a/drivers/video/clps711xfb.c	2004-10-18 14:56:17 -07:00
+++ b/drivers/video/clps711xfb.c	2004-10-18 14:56:17 -07:00
@@ -364,6 +364,9 @@
 {
 	int err = -ENOMEM;
 
+	if (fb_get_options("clps711xfb", NULL))
+		return -ENODEV;
+
 	cfb = kmalloc(sizeof(*cfb), GFP_KERNEL);
 	if (!cfb)
 		goto out;
@@ -372,7 +375,7 @@
 	strcpy(cfb->fix.id, "clps711x");
 
 	cfb->fbops		= &clps7111fb_ops;
-	cfb->flags		= FBINFO_FLAG_DEFAULT;
+	cfb->flags		= FBINFO_DEFAULT;
 
 	clps711x_guess_lcd_params(cfb);
 
@@ -432,9 +435,7 @@
 	}
 }
 
-#ifdef MODULE
 module_init(clps711xfb_init);
-#endif
 module_exit(clps711xfb_exit);
 
 MODULE_AUTHOR("Russell King <rmk@arm.linux.org.uk>");
diff -Nru a/drivers/video/console/Kconfig b/drivers/video/console/Kconfig
--- a/drivers/video/console/Kconfig	2004-10-18 14:56:20 -07:00
+++ b/drivers/video/console/Kconfig	2004-10-18 14:56:20 -07:00
@@ -6,7 +6,7 @@
 
 config VGA_CONSOLE
 	bool "VGA text console" if EMBEDDED || !X86
-	depends on !ARCH_ACORN && !ARCH_EBSA110 && !4xx && !8xx && !SPARC32 && !SPARC64 && !M68K
+	depends on !ARCH_ACORN && !ARCH_EBSA110 && !4xx && !8xx && !SPARC32 && !SPARC64 && !M68K && !PARISC
 	default y
 	help
 	  Saying Y here will allow you to use Linux in text mode through a
@@ -43,7 +43,7 @@
 	  about the Video mode selection support. If unsure, say N.
 
 config MDA_CONSOLE
-	depends on !M68K
+	depends on !M68K && ISA
 	tristate "MDA text console (dual-headed) (EXPERIMENTAL)"
 	---help---
 	  Say Y here if you have an old MDA or monochrome Hercules graphics
@@ -67,7 +67,7 @@
 #  bool 'IODC console' CONFIG_IODC_CONSOLE
 config STI_CONSOLE
         tristate "STI text console" 
-        depends on PARISC
+        depends on PARISC && FRAMEBUFFER_CONSOLE
         default y
         help
           The STI console is the builtin display/keyboard on HP-PARISC
diff -Nru a/drivers/video/console/fbcon.c b/drivers/video/console/fbcon.c
--- a/drivers/video/console/fbcon.c	2004-10-18 14:56:48 -07:00
+++ b/drivers/video/console/fbcon.c	2004-10-18 14:56:48 -07:00
@@ -314,6 +314,28 @@
 	return 0;
 }
 
+static int fbcon_takeover(void)
+{
+	int err, i;
+
+	if (!num_registered_fb)
+		return -ENODEV;
+
+	for (i = first_fb_vc; i <= last_fb_vc; i++)
+		con2fb_map[i] = info_idx;
+
+	err = take_over_console(&fb_con, first_fb_vc, last_fb_vc,
+				fbcon_is_default);
+	if (err) {
+		for (i = first_fb_vc; i <= last_fb_vc; i++) {
+			con2fb_map[i] = -1;
+		}
+		info_idx = -1;
+	}
+
+	return err;
+}
+
 /**
  *	set_con2fb_map - map console to frame buffer device
  *	@unit: virtual console number to map
@@ -322,7 +344,7 @@
  *	Maps a virtual console @unit to a frame buffer device
  *	@newidx.
  */
-int set_con2fb_map(int unit, int newidx)
+static int set_con2fb_map(int unit, int newidx)
 {
 	struct vc_data *vc = vc_cons[unit].d;
 	int oldidx = con2fb_map[unit];
@@ -338,8 +360,7 @@
 
 	if (!search_for_mapped_con()) {
 		info_idx = newidx;
-		fb_console_init();
-		return 0;
+		return fbcon_takeover();
 	}
 
 	if (oldidx != -1)
@@ -405,6 +426,87 @@
 /*
  * Accelerated handlers.
  */
+static inline int get_color(struct vc_data *vc, struct fb_info *info,
+			    u16 c, int is_fg)
+{
+	int depth = fb_get_color_depth(info);
+	int color = 0;
+
+	if (depth != 1)
+		color = (is_fg) ? attr_fgcol((vc->vc_hi_font_mask) ? 9 : 8, c)
+			: attr_bgcol((vc->vc_hi_font_mask) ? 13 : 12, c);
+
+	switch (depth) {
+	case 1:
+	{
+		/* 0 or 1 */
+		int fg = (info->fix.visual != FB_VISUAL_MONO01) ? 1 : 0;
+		int bg = (info->fix.visual != FB_VISUAL_MONO01) ? 0 : 1;
+
+		color = (is_fg) ? fg : bg;
+		break;
+	}
+	case 2:
+		/*
+		 * Scale down 16-colors to 4 colors. Default 4-color palette
+		 * is grayscale.
+		 */
+		color /= 4;
+		break;
+	case 3:
+		/*
+		 * Last 8 entries of default 16-color palette is a more intense
+		 * version of the first 8 (i.e., same chrominance, different
+		 * luminance).
+		 */
+		color &= 7;
+		break;
+	}
+
+	return color;
+}
+
+#define FBCON_ATTRIBUTE_UNDERLINE 1
+#define FBCON_ATTRIBUTE_REVERSE   2
+#define FBCON_ATTRIBUTE_BOLD      4
+
+static inline int get_attribute(struct fb_info *info, u16 c)
+{
+	int attribute = 0;
+
+	if (fb_get_color_depth(info) == 1) {
+		if (attr_underline(c))
+			attribute |= FBCON_ATTRIBUTE_UNDERLINE;
+		if (attr_reverse(c))
+			attribute |= FBCON_ATTRIBUTE_REVERSE;
+		if (attr_bold(c))
+			attribute |= FBCON_ATTRIBUTE_BOLD;
+	}
+
+	return attribute;
+}
+
+static inline void update_attr(u8 *dst, u8 *src, int attribute,
+			       struct vc_data *vc)
+{
+	int i, offset = (vc->vc_font.height < 10) ? 1 : 2;
+	int width = (vc->vc_font.width + 7) >> 3;
+	unsigned int cellsize = vc->vc_font.height * width;
+	u8 c;
+
+	offset = cellsize - (offset * width);
+	for (i = 0; i < cellsize; i++) {
+		c = src[i];
+		if (attribute & FBCON_ATTRIBUTE_UNDERLINE && i >= offset)
+			c = 0xff;
+		if (attribute & FBCON_ATTRIBUTE_BOLD)
+			c |= c >> 1;
+		if (attribute & FBCON_ATTRIBUTE_REVERSE)
+			c = ~c;
+		dst[i] = c;
+	}
+}
+
 void accel_bmove(struct vc_data *vc, struct fb_info *info, int sy, 
 		int sx, int dy, int dx, int height, int width)
 {
@@ -455,13 +557,19 @@
 	unsigned int shift_low = 0, mod = vc->vc_font.width % 8;
 	unsigned int shift_high = 8, pitch, cnt, size, k;
 	unsigned int idx = vc->vc_font.width >> 3;
+	unsigned int attribute = get_attribute(info, scr_readw(s));
 	struct fb_image image;
-	u8 *src, *dst;
+	u8 *src, *dst, *buf = NULL;
+
+	if (attribute) {
+		buf = kmalloc(cellsize, GFP_KERNEL);
+		if (!buf)
+			return;
+	}
+
+	image.fg_color = get_color(vc, info, scr_readw(s), 1);
+	image.bg_color = get_color(vc, info, scr_readw(s), 0);
 
-	image.fg_color = attr_fgcol((vc->vc_hi_font_mask) ? 9 : 8,
-				    scr_readw(s));
-	image.bg_color = attr_bgcol((vc->vc_hi_font_mask) ? 13 : 12,
-				    scr_readw(s));
 	image.dx = xx * vc->vc_font.width;
 	image.dy = yy * vc->vc_font.height;
 	image.height = vc->vc_font.height;
@@ -491,6 +599,12 @@
 			while (k--) {
 				src = vc->vc_font.data + (scr_readw(s++)&
 							  charmask)*cellsize;
+
+				if (attribute) {
+					update_attr(buf, src, attribute, vc);
+					src = buf;
+				}
+
 				move_unaligned(info, &info->pixmap, dst, pitch,
 					       src, idx, image.height,
 					       shift_high, shift_low, mod);
@@ -503,6 +617,12 @@
 			while (k--) {
 				src = vc->vc_font.data + (scr_readw(s++)&
 							  charmask)*cellsize;
+
+				if (attribute) {
+					update_attr(buf, src, attribute, vc);
+					src = buf;
+				}
+
 				move_aligned(info, &info->pixmap, dst, pitch,
 					     src, idx, image.height);
 				dst += width;
@@ -512,6 +632,9 @@
 		image.dx += cnt * vc->vc_font.width;
 		count -= cnt;
 	}
+
+	if (buf)
+		kfree(buf);
 }
 
 void accel_clear_margins(struct vc_data *vc, struct fb_info *info,
@@ -550,6 +673,47 @@
  *  Low Level Operations
  */
 /* NOTE: fbcon cannot be __init: it may be called from take_over_console later */
+static int var_to_display(struct display *disp,
+			  struct fb_var_screeninfo *var,
+			  struct fb_info *info)
+{
+	disp->xres_virtual = var->xres_virtual;
+	disp->yres_virtual = var->yres_virtual;
+	disp->bits_per_pixel = var->bits_per_pixel;
+	disp->grayscale = var->grayscale;
+	disp->nonstd = var->nonstd;
+	disp->accel_flags = var->accel_flags;
+	disp->height = var->height;
+	disp->width = var->width;
+	disp->red = var->red;
+	disp->green = var->green;
+	disp->blue = var->blue;
+	disp->transp = var->transp;
+	disp->mode = fb_match_mode(var, &info->modelist);
+	if (disp->mode == NULL)
+		/* This should not happen */
+		return -EINVAL;
+	return 0;
+}
+
+static void display_to_var(struct fb_var_screeninfo *var,
+			   struct display *disp)
+{
+	fb_videomode_to_var(var, disp->mode);
+	var->xres_virtual = disp->xres_virtual;
+	var->yres_virtual = disp->yres_virtual;
+	var->bits_per_pixel = disp->bits_per_pixel;
+	var->grayscale = disp->grayscale;
+	var->nonstd = disp->nonstd;
+	var->accel_flags = disp->accel_flags;
+	var->height = disp->height;
+	var->width = disp->width;
+	var->red = disp->red;
+	var->green = disp->green;
+	var->blue = disp->blue;
+	var->transp = disp->transp;
+}
+
 static const char *fbcon_startup(void)
 {
 	const char *display_desc = "frame buffer device";
@@ -723,6 +887,9 @@
 
 	info->var.xoffset = info->var.yoffset = p->yscroll = 0;	/* reset wrap/pan */
 
+	if (var_to_display(p, &info->var, info))
+		return;
+
 	/* If we are not the first console on this
 	   fb, copy the font from that console */
 	t = &fb_display[display_fg];
@@ -737,7 +904,7 @@
 	}
 	if (p->userfont)
 		charcnt = FNTCHARCNT(p->fontdata);
-	vc->vc_can_do_color = info->var.bits_per_pixel != 1;
+	vc->vc_can_do_color = (fb_get_color_depth(info) != 1);
 	vc->vc_complement_mask = vc->vc_can_do_color ? 0x7700 : 0x0800;
 	if (charcnt == 256) {
 		vc->vc_hi_font_mask = 0;
@@ -780,9 +947,15 @@
 
 	if (logo) {
 		/* Need to make room for the logo */
-		int cnt;
+		int cnt, erase = vc->vc_video_erase_char;
 		int step;
 
+		/*
+		 * remove underline attribute from erase character
+		 * if black and white framebuffer.
+		 */
+		if (fb_get_color_depth(info) == 1)
+			erase &= ~0x400;
 		logo_height = fb_prepare_logo(info);
 		logo_lines = (logo_height + vc->vc_font.height - 1) /
 			     vc->vc_font.height;
@@ -796,8 +969,7 @@
 			save = kmalloc(logo_lines * new_cols * 2, GFP_KERNEL);
 			if (save) {
 				int i = cols < new_cols ? cols : new_cols;
-				scr_memsetw(save, vc->vc_video_erase_char,
-					    logo_lines * new_cols * 2);
+				scr_memsetw(save, erase, logo_lines * new_cols * 2);
 				r = q - step;
 				for (cnt = 0; cnt < logo_lines; cnt++, r += i)
 					scr_memcpyw(save + cnt * new_cols, r, 2 * i);
@@ -817,7 +989,7 @@
 			}
 		}
 		scr_memsetw((unsigned short *) vc->vc_origin,
-			    vc->vc_video_erase_char,
+			    erase,
 			    vc->vc_size_row * logo_lines);
 
 		if (CON_IS_VISIBLE(vc) && vt_cons[vc->vc_num]->vc_mode == KD_TEXT) {
@@ -926,55 +1098,6 @@
 		accel_clear(vc, info, real_y(p, sy), sx, height, width);
 }
 
-static void fbcon_putc(struct vc_data *vc, int c, int ypos, int xpos)
-{
-	struct fb_info *info = registered_fb[(int) con2fb_map[vc->vc_num]];
-	unsigned short charmask = vc->vc_hi_font_mask ? 0x1ff : 0xff;
-	unsigned int scan_align = info->pixmap.scan_align - 1;
-	unsigned int buf_align = info->pixmap.buf_align - 1;
-	unsigned int width = (vc->vc_font.width + 7) >> 3;
-	int bgshift = (vc->vc_hi_font_mask) ? 13 : 12;
-	int fgshift = (vc->vc_hi_font_mask) ? 9 : 8;
-	struct display *p = &fb_display[vc->vc_num];
-	unsigned int size, pitch;
-	struct fb_image image;
-	u8 *src, *dst;
-
-	if (!info->fbops->fb_blank && console_blanked)
-		return;
-	if (info->state != FBINFO_STATE_RUNNING)
-		return;
-
-	if (vt_cons[vc->vc_num]->vc_mode != KD_TEXT)
-		return;
-
-	image.dx = xpos * vc->vc_font.width;
-	image.dy = real_y(p, ypos) * vc->vc_font.height;
-	image.width = vc->vc_font.width;
-	image.height = vc->vc_font.height;
-	image.fg_color = attr_fgcol(fgshift, c);
-	image.bg_color = attr_bgcol(bgshift, c);
-	image.depth = 1;
-
-	src = vc->vc_font.data + (c & charmask) * vc->vc_font.height * width;
-
-	pitch = width + scan_align;
-	pitch &= ~scan_align;
-	size = pitch * vc->vc_font.height;
-	size += buf_align;
-	size &= ~buf_align;
-
-	dst = fb_get_buffer_offset(info, &info->pixmap, size);
-	image.data = dst;
-
-	if (info->pixmap.outbuf)
-		fb_iomove_buf_aligned(info, &info->pixmap, dst, pitch, src, width, image.height);
-	else
-		fb_sysmove_buf_aligned(info, &info->pixmap, dst, pitch, src, width, image.height);
-
-	info->fbops->fb_imageblit(info, &image);
-}
-
 static void fbcon_putcs(struct vc_data *vc, const unsigned short *s,
 			int count, int ypos, int xpos)
 {
@@ -992,17 +1115,22 @@
 	accel_putcs(vc, info, s, count, real_y(p, ypos), xpos);
 }
 
+static void fbcon_putc(struct vc_data *vc, int c, int ypos, int xpos)
+{
+	fbcon_putcs(vc, (const unsigned short *) &c, 1, ypos, xpos);
+}
+
 static void fbcon_cursor(struct vc_data *vc, int mode)
 {
+	struct fb_cursor cursor;
 	struct fb_info *info = registered_fb[(int) con2fb_map[vc->vc_num]];
 	unsigned short charmask = vc->vc_hi_font_mask ? 0x1ff : 0xff;
-	int bgshift = (vc->vc_hi_font_mask) ? 13 : 12;
-	int fgshift = (vc->vc_hi_font_mask) ? 9 : 8;
 	struct display *p = &fb_display[vc->vc_num];
 	int w = (vc->vc_font.width + 7) >> 3, c;
-	int y = real_y(p, vc->vc_y);
-	struct fb_cursor cursor;
-	
+	int y = real_y(p, vc->vc_y), fg, bg;
+	int attribute;
+	u8 *src;
+
 	if (mode & CM_SOFTBACK) {
 		mode &= ~CM_SOFTBACK;
 		if (softback_lines) {
@@ -1015,8 +1143,22 @@
 		fbcon_set_origin(vc);
 
  	c = scr_readw((u16 *) vc->vc_pos);
+	attribute = get_attribute(info, c);
+	src = vc->vc_font.data + ((c & charmask) * (w * vc->vc_font.height));
+	if (attribute) {
+		u8 *dst;
+
+		dst = kmalloc(w * vc->vc_font.height, GFP_ATOMIC);
+		if (!dst)
+			return;
+		if (info->cursor.data)
+			kfree(info->cursor.data);
+		info->cursor.data = dst;
+		update_attr(dst, src, attribute, vc);
+		src = dst;
+	}
 
-	cursor.image.data = vc->vc_font.data + ((c & charmask) * (w * vc->vc_font.height));
+	cursor.image.data = src;
 	cursor.set = FB_CUR_SETCUR;
 	cursor.image.depth = 1;
 	
@@ -1031,11 +1173,13 @@
 	case CM_MOVE:
 	case CM_DRAW:
 		info->cursor.enable = 1;
-		
-		if (info->cursor.image.fg_color != attr_fgcol(fgshift, c) ||
-	    	    info->cursor.image.bg_color != attr_bgcol(bgshift, c)) {
-			cursor.image.fg_color = attr_fgcol(fgshift, c);
-			cursor.image.bg_color = attr_bgcol(bgshift, c);
+		fg = get_color(vc, info, c, 1);
+		bg = get_color(vc, info, c, 0);
+
+		if (info->cursor.image.fg_color != fg ||
+		    info->cursor.image.bg_color != bg) {
+			cursor.image.fg_color = fg;
+			cursor.image.bg_color = bg;
 			cursor.set |= FB_CUR_SETCMAP;
 		}
 		
@@ -1058,17 +1202,19 @@
 			cursor.set |= FB_CUR_SETHOT;
 		}
 
-		if ((cursor.set & FB_CUR_SETSIZE) || ((vc->vc_cursor_type & 0x0f) != p->cursor_shape)
+		if ((cursor.set & FB_CUR_SETSIZE) ||
+		    ((vc->vc_cursor_type & 0x0f) != p->cursor_shape)
 		    || info->cursor.mask == NULL) {
 			char *mask = kmalloc(w*vc->vc_font.height, GFP_ATOMIC);
 			int cur_height, size, i = 0;
+			u8 msk = 0xff;
 
-			if (!mask)	return;	
+			if (!mask)
+				return;
 		
 			if (info->cursor.mask)
 				kfree(info->cursor.mask);
 			info->cursor.mask = mask;
-	
 			p->cursor_shape = vc->vc_cursor_type & 0x0f;
 			cursor.set |= FB_CUR_SETSHAPE;
 
@@ -1095,10 +1241,10 @@
 			}
 			size = (vc->vc_font.height - cur_height) * w;
 			while (size--)
-				mask[i++] = 0;
+				mask[i++] = ~msk;
 			size = cur_height * w;
 			while (size--)
-				mask[i++] = 0xff;
+				mask[i++] = msk;
 		}
         	info->cursor.rop = ROP_XOR;
 		info->fbops->fb_cursor(info, &cursor);
@@ -1126,6 +1272,8 @@
 	int rows, cols, charcnt = 256;
 
 	info->var.xoffset = info->var.yoffset = p->yscroll = 0;
+	if (var_to_display(p, &info->var, info))
+		return;
 	t = &fb_display[display_fg];
 	if (!vc->vc_font.data) {
 		vc->vc_font.data = p->fontdata = t->fontdata;
@@ -1139,7 +1287,7 @@
 	if (p->userfont)
 		charcnt = FNTCHARCNT(p->fontdata);
 
-	vc->vc_can_do_color = info->var.bits_per_pixel != 1;
+	vc->vc_can_do_color = (fb_get_color_depth(info) != 1);
 	vc->vc_complement_mask = vc->vc_can_do_color ? 0x7700 : 0x0800;
 	if (charcnt == 256) {
 		vc->vc_hi_font_mask = 0;
@@ -1813,7 +1961,7 @@
 	struct fb_info *info = registered_fb[(int) con2fb_map[vc->vc_num]];
 	struct display *p = &fb_display[vc->vc_num];
 	struct fb_var_screeninfo var = info->var;
-	int err; int x_diff, y_diff;
+	int x_diff, y_diff;
 	int fw = vc->vc_font.width;
 	int fh = vc->vc_font.height;
 
@@ -1822,15 +1970,31 @@
 	x_diff = info->var.xres - var.xres;
 	y_diff = info->var.yres - var.yres;
 	if (x_diff < 0 || x_diff > fw || (y_diff < 0 || y_diff > fh)) {
-		char mode[40];
+		struct fb_videomode *mode;
 
 		DPRINTK("attempting resize %ix%i\n", var.xres, var.yres);
-		snprintf(mode, 40, "%ix%i", var.xres, var.yres);
-		err = fb_find_mode(&var, info, mode, info->monspecs.modedb,
-				   info->monspecs.modedb_len, NULL,
-				   info->var.bits_per_pixel);
-		if (!err || width > var.xres/fw || height > var.yres/fh)
+		mode = fb_find_best_mode(&var, &info->modelist);
+		if (mode == NULL)
 			return -EINVAL;
+		fb_videomode_to_var(&var, mode);
+		if (width > var.xres/fw || height > var.yres/fh)
+			return -EINVAL;
+		/*
+		 * The following can probably have any value... Do we need to
+		 * set all of them?
+		 */
+		var.bits_per_pixel = p->bits_per_pixel;
+		var.xres_virtual = p->xres_virtual;
+		var.yres_virtual = p->yres_virtual;
+		var.accel_flags = p->accel_flags;
+		var.width = p->width;
+		var.height = p->height;
+		var.red = p->red;
+		var.green = p->green;
+		var.blue = p->blue;
+		var.transp = p->transp;
+		var.nonstd = p->nonstd;
+
 		DPRINTK("resize now %ix%i\n", var.xres, var.yres);
 		if (CON_IS_VISIBLE(vc)) {
 			var.activate = FB_ACTIVATE_NOW |
@@ -1838,6 +2002,7 @@
 			fb_set_var(info, &var);
 			info->flags &= ~FBINFO_MISC_MODESWITCH;
 		}
+		var_to_display(p, &info->var, info);
 	}
 	updatescrollmode(p, info, vc);
 	return 0;
@@ -1847,6 +2012,7 @@
 {
 	struct fb_info *info = registered_fb[(int) con2fb_map[vc->vc_num]];
 	struct display *p = &fb_display[vc->vc_num];
+	struct fb_var_screeninfo var;
 	int i;
 
 	if (softback_top) {
@@ -1872,8 +2038,6 @@
 			conp2->vc_top = 0;
 		logo_shown = -1;
 	}
-	if (info)
-		info->var.yoffset = p->yscroll = 0;
 
 	/*
 	 * FIXME: If we have multiple fbdev's loaded, we need to
@@ -1888,7 +2052,18 @@
 			registered_fb[i]->currcon = vc->vc_num;
 	}
 
- 	fbcon_resize(vc, vc->vc_cols, vc->vc_rows);
+	memset(&var, 0, sizeof(struct fb_var_screeninfo));
+	fb_videomode_to_var(&var, p->mode);
+	display_to_var(&var, p);
+	var.activate = FB_ACTIVATE_NOW;
+
+	/*
+	 * make sure we don't unnecessarily trip the memcmp()
+	 * in fb_set_var()
+	 */
+	info->var.activate = var.activate;
+	info->var.yoffset = info->var.xoffset = p->yscroll = 0;
+	fb_set_var(info, &var);
 
 	if (info->flags & FBINFO_MISC_MODESWITCH) {
 		if (info->fbops->fb_set_par)
@@ -1896,6 +2071,10 @@
 		info->flags &= ~FBINFO_MISC_MODESWITCH;
 	}
 
+	vc->vc_can_do_color = (fb_get_color_depth(info) != 1);
+	vc->vc_complement_mask = vc->vc_can_do_color ? 0x7700 : 0x0800;
+	updatescrollmode(p, info, vc);
+
 	switch (p->scrollmode) {
 	case SCROLL_WRAP_MOVE:
 		scrollback_phys_max = p->vrows - vc->vc_rows;
@@ -2290,26 +2469,31 @@
 static int fbcon_set_palette(struct vc_data *vc, unsigned char *table)
 {
 	struct fb_info *info = registered_fb[(int) con2fb_map[vc->vc_num]];
-	int i, j, k;
+	int i, j, k, depth;
 	u8 val;
 
-	if (!vc->vc_can_do_color
-	    || (!info->fbops->fb_blank && console_blanked))
+	if (!info->fbops->fb_blank && console_blanked)
 		return -EINVAL;
-	for (i = j = 0; i < 16; i++) {
-		k = table[i];
-		val = vc->vc_palette[j++];
-		palette_red[k] = (val << 8) | val;
-		val = vc->vc_palette[j++];
-		palette_green[k] = (val << 8) | val;
-		val = vc->vc_palette[j++];
-		palette_blue[k] = (val << 8) | val;
-	}
-	if (info->var.bits_per_pixel <= 4)
-		palette_cmap.len = 1 << info->var.bits_per_pixel;
-	else
+	depth = fb_get_color_depth(info);
+	if (depth > 3) {
+		for (i = j = 0; i < 16; i++) {
+			k = table[i];
+			val = vc->vc_palette[j++];
+			palette_red[k] = (val << 8) | val;
+			val = vc->vc_palette[j++];
+			palette_green[k] = (val << 8) | val;
+			val = vc->vc_palette[j++];
+			palette_blue[k] = (val << 8) | val;
+		}
 		palette_cmap.len = 16;
-	palette_cmap.start = 0;
+		palette_cmap.start = 0;
+	/*
+	 * If framebuffer is capable of less than 16 colors,
+	 * use default palette of fbcon.
+	 */
+	} else
+		fb_copy_cmap(fb_default_cmap(1 << depth), &palette_cmap);
+
 	return fb_set_cmap(&palette_cmap, info);
 }
 
@@ -2516,10 +2700,9 @@
 	p = &fb_display[vc->vc_num];
 
 	info->var.xoffset = info->var.yoffset = p->yscroll = 0;
-	vc->vc_can_do_color = info->var.bits_per_pixel != 1;
-	vc->vc_complement_mask = vc->vc_can_do_color ? 0x7700 : 0x0800;
 
 	if (CON_IS_VISIBLE(vc)) {
+		var_to_display(p, &info->var, info);
 		cols = info->var.xres / vc->vc_font.width;
 		rows = info->var.yres / vc->vc_font.height;
 		vc_resize(vc->vc_num, cols, rows);
@@ -2542,10 +2725,52 @@
 	}
 }
 
+static int fbcon_mode_deleted(struct fb_info *info,
+			      struct fb_videomode *mode)
+{
+	struct fb_info *fb_info;
+	struct display *p;
+	int i, j, found = 0;
+
+	/* before deletion, ensure that mode is not in use */
+	for (i = first_fb_vc; i <= last_fb_vc; i++) {
+		j = (int) con2fb_map[i];
+		if (j == -1)
+			continue;
+		fb_info = registered_fb[j];
+		if (fb_info != info)
+			continue;
+		p = &fb_display[i];
+		if (!p || !p->mode)
+			continue;
+		if (fb_mode_is_equal(p->mode, mode)) {
+			found = 1;
+			break;
+		}
+	}
+	return found;
+}
+
+static int fbcon_fb_registered(int idx)
+{
+	int ret = 0;
+
+	if (info_idx == -1) {
+		info_idx = idx;
+		ret = fbcon_takeover();
+	}
+
+	return ret;
+}
+
 static int fbcon_event_notify(struct notifier_block *self, 
 			      unsigned long action, void *data)
 {
-	struct fb_info *info = (struct fb_info *) data;
+	struct fb_event *event = (struct fb_event *) data;
+	struct fb_info *info = event->info;
+	struct fb_videomode *mode;
+	struct fb_con2fbmap *con2fb;
+	int ret = 0;
 
 	switch(action) {
 	case FB_EVENT_SUSPEND:
@@ -2557,9 +2782,24 @@
 	case FB_EVENT_MODE_CHANGE:
 		fbcon_modechanged(info);
 		break;
+	case FB_EVENT_MODE_DELETE:
+		mode = (struct fb_videomode *) event->data;
+		ret = fbcon_mode_deleted(info, mode);
+		break;
+	case FB_EVENT_FB_REGISTERED:
+		ret = fbcon_fb_registered(info->node);
+		break;
+	case FB_EVENT_SET_CONSOLE_MAP:
+		con2fb = (struct fb_con2fbmap *) event->data;
+		ret = set_con2fb_map(con2fb->console - 1, con2fb->framebuffer);
+		break;
+	case FB_EVENT_GET_CONSOLE_MAP:
+		con2fb = (struct fb_con2fbmap *) event->data;
+		con2fb->framebuffer = con2fb_map[con2fb->console - 1];
+		break;
 	}
 
-	return 0;
+	return ret;
 }
 
 /*
@@ -2595,60 +2835,43 @@
 static struct notifier_block fbcon_event_notifier = {
 	.notifier_call	= fbcon_event_notify,
 };
-static int fbcon_event_notifier_registered;
 
-/* can't be __init as it can be called by set_con2fb_map() later */
-int fb_console_init(void)
+int __init fb_console_init(void)
 {
-	int err, i;
+	int i;
+
+	acquire_console_sem();
+	fb_register_client(&fbcon_event_notifier);
+	release_console_sem();
 
 	for (i = 0; i < MAX_NR_CONSOLES; i++)
 		con2fb_map[i] = -1;
 
-	if (!num_registered_fb)
-		return -ENODEV;
-
-	if (info_idx == -1) {
+	if (num_registered_fb) {
 		for (i = 0; i < FB_MAX; i++) {
 			if (registered_fb[i] != NULL) {
 				info_idx = i;
 				break;
 			}
 		}
+		fbcon_takeover();
 	}
-	for (i = first_fb_vc; i <= last_fb_vc; i++)
-		con2fb_map[i] = info_idx;
-	err = take_over_console(&fb_con, first_fb_vc, last_fb_vc,
-				fbcon_is_default);
-	if (err) {
-		for (i = first_fb_vc; i <= last_fb_vc; i++) {
-			con2fb_map[i] = -1;
-		}
-		return err;
-	}
-	acquire_console_sem();
-	if (!fbcon_event_notifier_registered) {
-		fb_register_client(&fbcon_event_notifier);
-		fbcon_event_notifier_registered = 1;
-	} 
-	release_console_sem();
+
 	return 0;
 }
 
+module_init(fb_console_init);
+
 #ifdef MODULE
 
 void __exit fb_console_exit(void)
 {
 	acquire_console_sem();
-	if (fbcon_event_notifier_registered) {
-		fb_unregister_client(&fbcon_event_notifier);
-		fbcon_event_notifier_registered = 0;
-	}
+	fb_unregister_client(&fbcon_event_notifier);
 	release_console_sem();
 	give_up_console(&fb_con);
 }	
 
-module_init(fb_console_init);
 module_exit(fb_console_exit);
 
 #endif
diff -Nru a/drivers/video/console/fbcon.h b/drivers/video/console/fbcon.h
--- a/drivers/video/console/fbcon.h	2004-10-18 14:56:48 -07:00
+++ b/drivers/video/console/fbcon.h	2004-10-18 14:56:48 -07:00
@@ -33,12 +33,21 @@
     short yscroll;                  /* Hardware scrolling */
     int vrows;                      /* number of virtual rows */
     int cursor_shape;
+    u32 xres_virtual;
+    u32 yres_virtual;
+    u32 height;
+    u32 width;
+    u32 bits_per_pixel;
+    u32 grayscale;
+    u32 nonstd;
+    u32 accel_flags;
+    struct fb_bitfield red;
+    struct fb_bitfield green;
+    struct fb_bitfield blue;
+    struct fb_bitfield transp;
+    struct fb_videomode *mode;
 };
 
-/* drivers/video/console/fbcon.c */
-extern signed char con2fb_map[MAX_NR_CONSOLES];
-extern int set_con2fb_map(int unit, int newidx);
-
     /*
      *  Attribute Decoding
      */
@@ -56,8 +65,8 @@
 /* Monochrome */
 #define attr_bold(s) \
 	((s) & 0x200)
-#define attr_reverse(s, inverse) \
-	(((s) & 0x800) ^ (inverse ? 0x800 : 0))
+#define attr_reverse(s) \
+	((s) & 0x800)
 #define attr_underline(s) \
 	((s) & 0x400)
 #define attr_blink(s) \
diff -Nru a/drivers/video/controlfb.c b/drivers/video/controlfb.c
--- a/drivers/video/controlfb.c	2004-10-18 14:56:17 -07:00
+++ b/drivers/video/controlfb.c	2004-10-18 14:56:17 -07:00
@@ -556,6 +556,11 @@
 int __init control_init(void)
 {
 	struct device_node *dp;
+	char *option = NULL;
+
+	if (fb_get_options("controlfb", &option))
+		return -ENODEV;
+	control_setup(option);
 
 	dp = find_devices("control");
 	if (dp != 0 && !control_of_init(dp))
@@ -564,6 +569,7 @@
 	return -ENXIO;
 }
 
+module_init(control_init);
 
 /* Work out which banks of VRAM we have installed. */
 /* danj: I guess the card just ignores writes to nonexistant VRAM... */
@@ -1010,7 +1016,7 @@
 	info->par = &p->par;
 	info->fbops = &controlfb_ops;
 	info->pseudo_palette = p->pseudo_palette;
-        info->flags = FBINFO_FLAG_DEFAULT;
+        info->flags = FBINFO_DEFAULT | FBINFO_HWACCEL_YPAN;
 	info->screen_base = (char *) p->frame_buffer + CTRLFB_OFF;
 
 	fb_alloc_cmap(&info->cmap, 256, 0);
diff -Nru a/drivers/video/cyber2000fb.c b/drivers/video/cyber2000fb.c
--- a/drivers/video/cyber2000fb.c	2004-10-18 14:56:17 -07:00
+++ b/drivers/video/cyber2000fb.c	2004-10-18 14:56:17 -07:00
@@ -1166,7 +1166,7 @@
 	.vmode		= FB_VMODE_NONINTERLACED
 };
 
-static char igs_regs[] __devinitdata = {
+static char igs_regs[] = {
 	EXT_CRT_IRQ,		0,
 	EXT_CRT_TEST,		0,
 	EXT_SYNC_CTL,		0,
@@ -1281,7 +1281,7 @@
 	cfb->fb.var.accel_flags	= FB_ACCELF_TEXT;
 
 	cfb->fb.fbops		= &cyber2000fb_ops;
-	cfb->fb.flags		= FBINFO_FLAG_DEFAULT;
+	cfb->fb.flags		= FBINFO_DEFAULT | FBINFO_HWACCEL_YPAN;
 	cfb->fb.pseudo_palette	= (void *)(cfb + 1);
 
 	fb_alloc_cmap(&cfb->fb.cmap, NR_PALETTE, 0);
@@ -1289,7 +1289,7 @@
 	return cfb;
 }
 
-static void __devinit
+static void
 cyberpro_free_fb_info(struct cfb_info *cfb)
 {
 	if (cfb) {
@@ -1712,11 +1712,21 @@
  * I don't think we can use the "module_init" stuff here because
  * the fbcon stuff may not be initialised yet.  Hence the #ifdef
  * around module_init.
+ *
+ * Tony: "module_init" is now required
  */
 int __init cyber2000fb_init(void)
 {
 	int ret = -1, err;
 
+#ifndef MODULE
+	char *option = NULL;
+
+	if (fb_get_options("cyber2000fb", NULL))
+		return -ENODEV;
+	cyber2000fb_setup(option);
+#endif
+
 #ifdef CONFIG_ARCH_SHARK
 	err = cyberpro_vl_probe();
 	if (!err) {
@@ -1738,9 +1748,7 @@
 	pci_unregister_driver(&cyberpro_driver);
 }
 
-#ifdef MODULE
 module_init(cyber2000fb_init);
-#endif
 module_exit(cyberpro_exit);
 
 MODULE_AUTHOR("Russell King");
diff -Nru a/drivers/video/dnfb.c b/drivers/video/dnfb.c
--- a/drivers/video/dnfb.c	2004-10-18 14:56:49 -07:00
+++ b/drivers/video/dnfb.c	2004-10-18 14:56:49 -07:00
@@ -239,6 +239,9 @@
 	info->fbops = &dn_fb_ops;
 	info->fix = dnfb_fix;
 	info->var = dnfb_var;
+	info->var.red.length = 1;
+	info->var.red.offset = 0;
+	info->var.green = info->var.blue = info->var.red;
 	info->screen_base = (u_char *) info->fix.smem_start;
 
 	err = fb_alloc_cmap(&info->cmap, 2, 0);
@@ -281,6 +284,9 @@
 {
 	int ret;
 
+	if (fb_get_options("dnfb", NULL))
+		return -ENODEV;
+
 	ret = driver_register(&dnfb_driver);
 
 	if (!ret) {
@@ -290,5 +296,7 @@
 	}
 	return ret;
 }
+
+module_init(dnfb_init);
 
 MODULE_LICENSE("GPL");
diff -Nru a/drivers/video/epson1355fb.c b/drivers/video/epson1355fb.c
--- a/drivers/video/epson1355fb.c	2004-10-18 14:55:54 -07:00
+++ b/drivers/video/epson1355fb.c	2004-10-18 14:55:54 -07:00
@@ -1,541 +1,771 @@
 /*
- * linux/drivers/video/epson1355fb.c
- *	-- Support for the Epson SED1355 LCD/CRT controller
+ * linux/drivers/video/epson1355fb.c -- Epson S1D13505 frame buffer for 2.5.
  *
- * Copyright (C) 2000 Philipp Rumpf <prumpf@tux.org>
+ * Epson Research S1D13505 Embedded RAMDAC LCD/CRT Controller
+ *   (previously known as SED1355)
  *
- * based on linux/drivers/video/skeletonfb.c, which was
+ * Cf. http://www.erd.epson.com/vdc/html/S1D13505.html
+ *
+ *
+ * Copyright (C) Hewlett-Packard Company.  All rights reserved.
+ *
+ * Written by Christopher Hoover <ch@hpl.hp.com>
+ *
+ * Adapted from:
+ *
+ *  linux/drivers/video/skeletonfb.c
+ *  Modified to new api Jan 2001 by James Simmons (jsimmons@infradead.org)
  *  Created 28 Dec 1997 by Geert Uytterhoeven
  *
+ *  linux/drivers/video/epson1355fb.c (2.4 driver)
+ *  Copyright (C) 2000 Philipp Rumpf <prumpf@tux.org>
+ *
  * 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.
- */
-/* TODO (roughly in order of priority):
- * 16 bpp support
- * crt support
- * hw cursor support
- * SwivelView
+ * License. See the file COPYING in the main directory of this archive for
+ * more details.
+ *
+ *
+ * Noteworthy Issues
+ * -----------------
+ *
+ * This driver is complicated by the fact that this is a 16-bit chip
+ * and, on at least one platform (ceiva), we can only do 16-bit reads
+ * and writes to the framebuffer.  We hide this from user space
+ * except in the case of mmap().
+ *
+ *
+ * To Do
+ * -----
+ *
+ * - Test 8-bit pseudocolor mode
+ * - Allow setting bpp, virtual resolution
+ * - Implement horizontal panning
+ * - (maybe) Implement hardware cursor
  */
 
-#include <asm/io.h>
-#include <linux/config.h>
-#include <linux/delay.h>
-#include <linux/errno.h>
-#include <linux/fb.h>
-#include <linux/init.h>
-#include <linux/kernel.h>
-#include <linux/slab.h>
-#include <linux/mm.h>
 #include <linux/module.h>
-#include <linux/sched.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
 #include <linux/string.h>
+#include <linux/mm.h>
 #include <linux/tty.h>
-#include <video/fbcon-cfb8.h>
-#include <video/fbcon-mfb.h>
-#include <video/fbcon.h>
-
-/* Register defines.  The docs don't seem to provide nice mnemonic names
- * so I made them up myself ... */
-
-#define E1355_PANEL	0x02
-#define E1355_DISPLAY	0x0D
-#define E1355_MISC	0x1B
-#define E1355_GPIO	0x20
-#define E1355_LUT_INDEX 0x24
-#define E1355_LUT_DATA	0x26
+#include <linux/slab.h>
+#include <linux/delay.h>
+#include <linux/fb.h>
+#include <linux/init.h>
+#include <linux/ioport.h>
+#include <asm/types.h>
+#include <asm/io.h>
+#include <asm/uaccess.h>
+
+#include <video/epson1355.h>
+
+struct epson1355_par {
+	unsigned long reg_addr;
+};
+
+/* ------------------------------------------------------------------------- */
 
 #ifdef CONFIG_SUPERH
-#define E1355_REG_BASE	CONFIG_E1355_REG_BASE
-#define E1355_FB_BASE	CONFIG_E1355_FB_BASE
 
-static inline u8 e1355_read_reg(int index)
+static inline u8 epson1355_read_reg(int index)
 {
-	return ctrl_inb(E1355_REG_BASE + index);
+	return ctrl_inb(par.reg_addr + index);
 }
 
-static inline void e1355_write_reg(u8 data, int index)
+static inline void epson1355_write_reg(u8 data, int index)
 {
-	ctrl_outb(data, E1355_REG_BASE + index);
+	ctrl_outb(data, par.reg_addr + index);
 }
 
-static inline u16 e1355_read_reg16(int index)
+#elif defined(CONFIG_ARM)
+
+# ifdef CONFIG_ARCH_CEIVA
+#  include <asm/arch/hardware.h>
+#  define EPSON1355FB_BASE_PHYS	(CEIVA_PHYS_SED1355)
+# endif
+
+static inline u8 epson1355_read_reg(struct epson1355_par *par, int index)
 {
-	return e1355_read_reg(index) + (e1355_read_reg(index+1) << 8);
+	return __raw_readb(par->reg_addr + index);
 }
 
-static inline void e1355_write_reg16(u16 data, int index)
+static inline void epson1355_write_reg(struct epson1355_par *par, u8 data, int index)
 {
-	e1355_write_reg((data&0xff), index);
-	e1355_write_reg(((data>>8)&0xff), index + 1);
+	__raw_writeb(data, par->reg_addr + index);
 }
+
 #else
-#error unknown architecture
+# error "no architecture-specific epson1355_{read,write}_reg"
 #endif
 
-struct e1355fb_info {
-	struct fb_info_gen gen;
-};
-
-static int current_par_valid = 0;
-static struct display disp;
+#ifndef EPSON1355FB_BASE_PHYS
+# error  "EPSON1355FB_BASE_PHYS is not defined"
+#endif
 
-static struct fb_var_screeninfo default_var;
+#define EPSON1355FB_REGS_OFS	(0)
+#define EPSON1355FB_REGS_PHYS	(EPSON1355FB_BASE_PHYS + EPSON1355FB_REGS_OFS)
+#define EPSON1355FB_REGS_LEN	(64)
 
-int e1355fb_init(void);
-int e1355fb_setup(char*);
-static int e1355_encode_var(struct fb_var_screeninfo *var, const void *par,
-			    struct fb_info_gen *info);
-/* ------------------- chipset specific functions -------------------------- */
+#define EPSON1355FB_FB_OFS	(0x00200000)
+#define EPSON1355FB_FB_PHYS	(EPSON1355FB_BASE_PHYS + EPSON1355FB_FB_OFS)
+#define EPSON1355FB_FB_LEN	(2 * 1024 * 1024)
 
+/* ------------------------------------------------------------------------- */
 
-static void disable_hw_cursor(void)
+static inline u16 epson1355_read_reg16(struct epson1355_par *par, int index)
 {
-	u8 curs;
+	u8 lo = epson1355_read_reg(par, index);
+	u8 hi = epson1355_read_reg(par, index + 1);
 
-	curs = e1355_read_reg(0x27);
-	curs &= ~0xc0;
-	e1355_write_reg(curs, 0x27);
+	return (hi << 8) | lo;
 }
 
-static void e1355_detect(void)
+static inline void epson1355_write_reg16(struct epson1355_par *par, u16 data, int index)
 {
-	u8 rev;
+	u8 lo = data & 0xff;
+	u8 hi = (data >> 8) & 0xff;
 
-	e1355_write_reg(0x00, E1355_MISC);
+	epson1355_write_reg(par, lo, index);
+	epson1355_write_reg(par, hi, index + 1);
+}
 
-	rev = e1355_read_reg(0x00);
+static inline u32 epson1355_read_reg20(struct epson1355_par *par, int index)
+{
+	u8 b0 = epson1355_read_reg(par, index);
+	u8 b1 = epson1355_read_reg(par, index + 1);
+	u8 b2 = epson1355_read_reg(par, index + 2);
 
-	if ((rev & 0xfc) != 0x0c) {
-		printk(KERN_WARNING "Epson 1355 not detected\n");
-	}
+	return (b2 & 0x0f) << 16 | (b1 << 8) | b0;
+}
 
-	/* XXX */
-	disable_hw_cursor();
+static inline void epson1355_write_reg20(struct epson1355_par *par, u32 data, int index)
+{
+	u8 b0 = data & 0xff;
+	u8 b1 = (data >> 8) & 0xff;
+	u8 b2 = (data >> 16) & 0x0f;
 
-	e1355_encode_var(&default_var, NULL, NULL);
+	epson1355_write_reg(par, b0, index);
+	epson1355_write_reg(par, b1, index + 1);
+	epson1355_write_reg(par, b2, index + 2);
 }
 
-struct e1355_par {
-	u32 xres;
-	u32 yres;
+/* ------------------------------------------------------------------------- */
 
-	int bpp;
-	int mem_bpp;
+static void set_lut(struct epson1355_par *par, u8 index, u8 r, u8 g, u8 b)
+{
+	epson1355_write_reg(par, index, REG_LUT_ADDR);
+	epson1355_write_reg(par, r, REG_LUT_DATA);
+	epson1355_write_reg(par, g, REG_LUT_DATA);
+	epson1355_write_reg(par, b, REG_LUT_DATA);
+}
 
-	u32 panel_xres;
-	u32 panel_yres;
-	
-	int panel_width;
-	int panel_ymul;
-};
 
-static int e1355_encode_fix(struct fb_fix_screeninfo *fix,
-			    const void *raw_par,
-			    struct fb_info_gen *info)
-{
-	const struct e1355_par *par = raw_par;
-	
-	memset(fix, 0, sizeof *fix);
-	
-	fix->type= FB_TYPE_PACKED_PIXELS;
+/**
+ *  	epson1355fb_setcolreg - sets a color register.
+ *      @regno: Which register in the CLUT we are programming
+ *      @red: The red value which can be up to 16 bits wide
+ *	@green: The green value which can be up to 16 bits wide
+ *	@blue:  The blue value which can be up to 16 bits wide.
+ *	@transp: If supported the alpha value which can be up to 16 bits wide.
+ *      @info: frame buffer info structure
+ *
+ *	Returns negative errno on error, or zero on success.
+ */
+static int epson1355fb_setcolreg(unsigned regno, unsigned r, unsigned g,
+				 unsigned b, unsigned transp,
+				 struct fb_info *info)
+{
+	struct epson1355_par *par = info->par;
+
+	if (info->var.grayscale)
+		r = g = b = (19595 * r + 38470 * g + 7471 * b) >> 16;
+
+	switch (info->fix.visual) {
+	case FB_VISUAL_TRUECOLOR:
+		if (regno >= 16)
+			return -EINVAL;
 
-	if (!par)
-		BUG();
+		((u32 *) info->pseudo_palette)[regno] =
+		    (r & 0xf800) | (g & 0xfc00) >> 5 | (b & 0xf800) >> 11;
 
-	if (par->bpp == 1) {
-		fix->visual = FB_VISUAL_MONO10;
-	} else if (par->bpp <= 8) {
-		fix->visual = FB_VISUAL_PSEUDOCOLOR;
-	} else {
-		fix->visual = FB_VISUAL_TRUECOLOR;
-	}
+		break;
+	case FB_VISUAL_PSEUDOCOLOR:
+		if (regno >= 256)
+			return -EINVAL;
 
-	return 0;
-}
+		set_lut(par, regno, r >> 8, g >> 8, b >> 8);
 
-static int e1355_set_bpp(struct e1355_par *par, int bpp)
-{
-	int code;
-	u8 disp;
-	u16 bytes_per_line;
-
-	switch(bpp) {
-	case 1:
-		code = 0; break;
-	case 2:
-		code = 1; break;
-	case 4:
-		code = 2; break;
-	case 8:
-		code = 3; break;
-	case 16:
-		code = 5; break;
+		break;
 	default:
-		return -EINVAL; break;
+		return -ENOSYS;
 	}
-
-	disp = e1355_read_reg(E1355_DISPLAY);
-	disp &= ~0x1c;
-	disp |= code << 2;
-	e1355_write_reg(disp, E1355_DISPLAY);
-	
-	bytes_per_line = (par->xres * bpp) >> 3;
-	
-	e1355_write_reg16(bytes_per_line, 0x16);
-
-	par->bpp = bpp;
-
 	return 0;
 }
-		
-static int e1355_decode_var(const struct fb_var_screeninfo *var,
-			    void *raw_par,
-			    struct fb_info_gen *info)
+
+/* ------------------------------------------------------------------------- */
+
+/**
+ *      epson1355fb_pan_display - Pans the display.
+ *      @var: frame buffer variable screen structure
+ *      @info: frame buffer structure that represents a single frame buffer
+ *
+ *	Pan (or wrap, depending on the `vmode' field) the display using the
+ *  	`xoffset' and `yoffset' fields of the `var' structure.
+ *  	If the values don't fit, return -EINVAL.
+ *
+ *      Returns negative errno on error, or zero on success.
+ */
+static int epson1355fb_pan_display(struct fb_var_screeninfo *var,
+				   struct fb_info *info)
 {
-	struct e1355_par *par = raw_par;
-	int ret;
+	struct epson1355_par *par = info->par;
+	u32 start;
 
-	if (!par)
-		BUG();
+	if (var->xoffset != 0)	/* not yet ... */
+		return -EINVAL;
 
-	/*
-	 * Don't allow setting any of these yet: xres and yres don't
-	 * make sense for LCD panels; xres_virtual and yres_virtual
-	 * should be supported fine by our hardware though.
-	 */
-	if (var->xres != par->xres ||
-	    var->yres != par->yres ||
-	    var->xres != var->xres_virtual ||
-	    var->yres != var->yres_virtual ||
-	    var->xoffset != 0 ||
-	    var->yoffset != 0)
+	if (var->yoffset + info->var.yres > info->var.yres_virtual)
 		return -EINVAL;
 
-	if(var->bits_per_pixel != par->bpp) {
-		ret = e1355_set_bpp(par, var->bits_per_pixel);
+	start = (info->fix.line_length >> 1) * var->yoffset;
 
-		if (ret)
-			goto out_err;
-	}
-		
-	return 0;
+	epson1355_write_reg20(par, start, REG_SCRN1_DISP_START_ADDR0);
 
- out_err:
-	return ret;
+	return 0;
 }
 
-static void dump_panel_data(void)
+/* ------------------------------------------------------------------------- */
+
+static void lcd_enable(struct epson1355_par *par, int enable)
 {
-	u8 panel = e1355_read_reg(E1355_PANEL);
-	int width[2][4] = { { 4, 8, 16, -1 }, { 9, 12, 16, -1 } };
+	u8 mode = epson1355_read_reg(par, REG_DISPLAY_MODE);
 
-	printk("%s %s %s panel, width %d bits\n",
-	       panel & 2 ? "dual" : "single",
-	       panel & 4 ? "color" : "mono",
-	       panel & 1 ? "TFT" : "passive",
-	       width[panel&1][(panel>>4)&3]);
+	if (enable)
+		mode |= 1;
+	else
+		mode &= ~1;
 
-	printk("resolution %d x %d\n",
-	       (e1355_read_reg(0x04) + 1) * 8,
-	       ((e1355_read_reg16(0x08) + 1) * (1 + ((panel & 3) == 2))));
+	epson1355_write_reg(par, mode, REG_DISPLAY_MODE);
 }
 
-static int e1355_bpp_to_var(int bpp, struct fb_var_screeninfo *var)
+#if defined(CONFIG_ARCH_CEIVA)
+static void backlight_enable(int enable)
 {
-	switch(bpp) {
-	case 1:
-	case 2:
-	case 4:
-	case 8:
-		var->bits_per_pixel = bpp;
-		var->red.offset = var->green.offset = var->blue.offset = 0;
-		var->red.length = var->green.length = var->blue.length = bpp;
+	/* ### this should be protected by a spinlock ... */
+	u8 pddr = clps_readb(PDDR);
+	if (enable)
+		pddr |= (1 << 5);
+	else
+		pddr &= ~(1 << 5);
+	clps_writeb(pddr, PDDR);
+}
+#else
+static void backlight_enable(int enable)
+{
+}
+#endif
+
+
+/**
+ *      epson1355fb_blank - blanks the display.
+ *      @blank_mode: the blank mode we want.
+ *      @info: frame buffer structure that represents a single frame buffer
+ *
+ *      Blank the screen if blank_mode != 0, else unblank. Return 0 if
+ *      blanking succeeded, != 0 if un-/blanking failed due to e.g. a
+ *      video mode which doesn't support it. Implements VESA suspend
+ *      and powerdown modes on hardware that supports disabling hsync/vsync:
+ *      blank_mode == 2: suspend vsync
+ *      blank_mode == 3: suspend hsync
+ *      blank_mode == 4: powerdown
+ *
+ *      Returns negative errno on error, or zero on success.
+ *
+ */
+static int epson1355fb_blank(int blank_mode, struct fb_info *info)
+{
+	struct epson1355_par *par = info->par;
+
+	switch (blank_mode) {
+	case VESA_NO_BLANKING:
+		lcd_enable(par, 1);
+		backlight_enable(1);
 		break;
-	case 16:
-		var->bits_per_pixel = 16;
-		var->red.offset = 11;
-		var->red.length = 5;
-		var->green.offset = 5;
-		var->green.length = 6;
-		var->blue.offset = 0;
-		var->blue.length = 5;
+	case VESA_VSYNC_SUSPEND:
+	case VESA_HSYNC_SUSPEND:
+		backlight_enable(0);
 		break;
+	case VESA_POWERDOWN:
+		backlight_enable(0);
+		lcd_enable(par, 0);
+		break;
+	default:
+		return -EINVAL;
 	}
-
 	return 0;
 }
 
-static int e1355_encode_var(struct fb_var_screeninfo *var, const void *raw_par,
-			    struct fb_info_gen *info)
+/* ------------------------------------------------------------------------- */
+
+/*
+ * We can't use the cfb generic routines, as we have to limit
+ * ourselves to 16-bit or 8-bit loads and stores to this 16-bit
+ * chip.
+ */
+
+static inline void epson1355fb_fb_writel(unsigned long v, unsigned long *a)
 {
-	u8 panel, display;
-	u32 xres, xres_virtual, yres;
-	static int width[2][4] = { { 4, 8, 16, -1 }, { 9, 12, 16, -1 } };
-	static int bpp_tab[8] = { 1, 2, 4, 8, 15, 16 };
-	int bpp, hw_bpp;
-	int is_color, is_dual, is_tft;
-	int lcd_enabled, crt_enabled;
+	u16 *p = (u16 *) a;
+	u16 l = v & 0xffff;
+	u16 h = v >> 16;
 
-	panel = e1355_read_reg(E1355_PANEL);
-	display = e1355_read_reg(E1355_DISPLAY);
+	fb_writew(l, p);
+	fb_writew(h, p + 1);
+}
 
-	is_color = (panel & 0x04) != 0;
-	is_dual  = (panel & 0x02) != 0;
-	is_tft   = (panel & 0x01) != 0;
+static inline unsigned long epson1355fb_fb_readl(const unsigned long *a)
+{
+	const u16 *p = (u16 *) a;
+	u16 l = fb_readw(p);
+	u16 h = fb_readw(p + 1);
 
-	bpp = bpp_tab[(display>>2)&7]; 
-	e1355_bpp_to_var(bpp, var);
+	return (h << 16) | l;
+}
 
-	crt_enabled = (display & 0x02) != 0;
-	lcd_enabled = (display & 0x02) != 0;
+#define FB_READL epson1355fb_fb_readl
+#define FB_WRITEL epson1355fb_fb_writel
 
-	hw_bpp = width[is_tft][(panel>>4)&3];
+/* ------------------------------------------------------------------------- */
 
-	xres = e1355_read_reg(0x04) + 1;
-	yres = e1355_read_reg16(0x08) + 1;
-	
-	xres *= 8;
-	/* talk about weird hardware .. */
-	yres *= (is_dual && !crt_enabled) ? 2 : 1;
-
-	xres_virtual = e1355_read_reg16(0x16);
-	/* it's in 2-byte words initially */
-	xres_virtual *= 16;
-	xres_virtual /= var->bits_per_pixel;
+static inline unsigned long copy_from_user16(void *to, const void *from,
+					     unsigned long n)
+{
+	u16 *dst = (u16 *) to;
+	u16 *src = (u16 *) from;
 
-	var->xres = xres;
-	var->yres = yres;
-	var->xres_virtual = xres_virtual;
-	var->yres_virtual = yres;
+	if (!access_ok(VERIFY_READ, from, n))
+		return n;
 
-	var->xoffset = var->yoffset = 0;
+	while (n > 1) {
+		u16 v;
+		if (__get_user(v, src))
+			return n;
 
-	var->grayscale = !is_color;
-	
-	return 0;
-}
+		fb_writew(v, dst);
 
-#define is_dual(panel) (((panel)&3)==2)
+		src++, dst++;
+		n -= 2;
+	}
 
-static void get_panel_data(struct e1355_par *par)
-{
-	u8 panel;
-	int width[2][4] = { { 4, 8, 16, -1 }, { 9, 12, 16, -1 } };
+	if (n) {
+		u8 v;
 
-	panel = e1355_read_reg(E1355_PANEL);
+		if (__get_user(v, ((u8 *) src)))
+			return n;
 
-	par->panel_width = width[panel&1][(panel>>4)&3];
-	par->panel_xres = (e1355_read_reg(0x04) + 1) * 8;
-	par->panel_ymul = is_dual(panel) ? 2 : 1;
-	par->panel_yres = ((e1355_read_reg16(0x08) + 1)
-			   * par->panel_ymul);
+		fb_writeb(v, dst);
+	}
+	return 0;
 }
 
-static void e1355_get_par(void *raw_par, struct fb_info_gen *info)
+static inline unsigned long copy_to_user16(void *to, const void *from,
+					   unsigned long n)
 {
-	struct e1355_par *par = raw_par;
+	u16 *dst = (u16 *) to;
+	u16 *src = (u16 *) from;
 
-	get_panel_data(par);
-}
+	if (!access_ok(VERIFY_WRITE, to, n))
+		return n;
 
-static void e1355_set_par(const void *par, struct fb_info_gen *info)
-{
-}
+	while (n > 1) {
+		u16 v = fb_readw(src);
 
-static int e1355_getcolreg(unsigned regno, unsigned *red, unsigned *green,
-			   unsigned *blue, unsigned *transp,
-			   struct fb_info *info)
-{
-	u8 r, g, b;
+		if (__put_user(v, dst))
+			return n;
 
-	e1355_write_reg(regno, E1355_LUT_INDEX);
-	r = e1355_read_reg(E1355_LUT_DATA);
-	g = e1355_read_reg(E1355_LUT_DATA);
-	b = e1355_read_reg(E1355_LUT_DATA);
+		src++, dst++;
+		n -= 2;
+	}
 
-	*red = r << 8;
-	*green = g << 8;
-	*blue = b << 8;
+	if (n) {
+		u8 v = fb_readb(src);
 
+		if (__put_user(v, ((u8 *) dst)))
+			return n;
+	}
 	return 0;
 }
 
-static int e1355fb_setcolreg(unsigned regno, unsigned red, unsigned green,
-			     unsigned blue, unsigned transp,
-			     struct fb_info *info)
-{
-	u8 r = (red >> 8) & 0xf0;
-	u8 g = (green>>8) & 0xf0;
-	u8 b = (blue>> 8) & 0xf0;
-
-	e1355_write_reg(regno, E1355_LUT_INDEX);
-	e1355_write_reg(r, E1355_LUT_DATA);
-	e1355_write_reg(g, E1355_LUT_DATA);
-	e1355_write_reg(b, E1355_LUT_DATA);
-	
-	return 0;
-}
 
-static int e1355_pan_display(const struct fb_var_screeninfo *var,
-			     struct fb_info_gen *info)
+static ssize_t
+epson1355fb_read(struct file *file, char *buf, size_t count, loff_t * ppos)
 {
-	BUG();
-	
-	return -EINVAL;
+	struct inode *inode = file->f_dentry->d_inode;
+	int fbidx = iminor(inode);
+	struct fb_info *info = registered_fb[fbidx];
+	unsigned long p = *ppos;
+
+	/* from fbmem.c except for our own copy_*_user */
+	if (!info || !info->screen_base)
+		return -ENODEV;
+
+	if (p >= info->fix.smem_len)
+		return 0;
+	if (count >= info->fix.smem_len)
+		count = info->fix.smem_len;
+	if (count + p > info->fix.smem_len)
+		count = info->fix.smem_len - p;
+
+	if (count) {
+		char *base_addr;
+
+		base_addr = info->screen_base;
+		count -= copy_to_user16(buf, base_addr + p, count);
+		if (!count)
+			return -EFAULT;
+		*ppos += count;
+	}
+	return count;
 }
 
-/*
- * The AERO_HACKS parts disable/enable the backlight on the Compaq Aero 8000.
- * I'm not sure they aren't dangerous to the hardware, so be warned.
- */
-#undef AERO_HACKS
+static ssize_t
+epson1355fb_write(struct file *file, const char *buf,
+		  size_t count, loff_t * ppos)
+{
+	struct inode *inode = file->f_dentry->d_inode;
+	int fbidx = iminor(inode);
+	struct fb_info *info = registered_fb[fbidx];
+	unsigned long p = *ppos;
+	int err;
+
+	/* from fbmem.c except for our own copy_*_user */
+	if (!info || !info->screen_base)
+		return -ENODEV;
+
+	/* from fbmem.c except for our own copy_*_user */
+	if (p > info->fix.smem_len)
+		return -ENOSPC;
+	if (count >= info->fix.smem_len)
+		count = info->fix.smem_len;
+	err = 0;
+	if (count + p > info->fix.smem_len) {
+		count = info->fix.smem_len - p;
+		err = -ENOSPC;
+	}
 
-static int e1355_blank(int blank_mode, struct fb_info_gen *info)
-{
-	u8 disp;
+	if (count) {
+		char *base_addr;
 
-	switch (blank_mode) {
-	case VESA_NO_BLANKING:
-		disp = e1355_read_reg(E1355_DISPLAY);
-		disp |= 1;
-		e1355_write_reg(disp, E1355_DISPLAY);
- 		
-#ifdef AERO_HACKS
-		e1355_write_reg(0x6, 0x20);
-#endif
-		break;
+		base_addr = info->screen_base;
+		count -= copy_from_user16(base_addr + p, buf, count);
+		*ppos += count;
+		err = -EFAULT;
+	}
+	if (count)
+		return count;
+	return err;
+}
+
+/* ------------------------------------------------------------------------- */
+
+static struct fb_ops epson1355fb_fbops = {
+	.owner 		= THIS_MODULE,
+	.fb_setcolreg 	= epson1355fb_setcolreg,
+	.fb_pan_display = epson1355fb_pan_display,
+	.fb_blank 	= epson1355fb_blank,
+	.fb_fillrect 	= cfb_fillrect,
+	.fb_copyarea 	= cfb_copyarea,
+	.fb_imageblit 	= cfb_imageblit,
+	.fb_read 	= epson1355fb_read,
+	.fb_write 	= epson1355fb_write,
+	.fb_cursor 	= soft_cursor,
+};
 
-	case VESA_VSYNC_SUSPEND:
-	case VESA_HSYNC_SUSPEND:
-	case VESA_POWERDOWN:
-		disp = e1355_read_reg(E1355_DISPLAY);
-		disp &= ~1;
-		e1355_write_reg(disp, E1355_DISPLAY);
+/* ------------------------------------------------------------------------- */
 
-#ifdef AERO_HACKS
-		e1355_write_reg(0x0, 0x20);
-#endif
-		break;
+static __init unsigned int get_fb_size(struct fb_info *info)
+{
+	unsigned int size = 2 * 1024 * 1024;
+	char *p = info->screen_base;
 
-	default:
-		return -EINVAL;
-	}
+	/* the 512k framebuffer is aliased at start + 0x80000 * n */
+	fb_writeb(1, p);
+	fb_writeb(0, p + 0x80000);
+	if (!fb_readb(p))
+		size = 512 * 1024;
 
-	return 0;
+	fb_writeb(0, p);
+
+	return size;
 }
 
-static struct display_switch e1355_dispsw;
+static int epson1355_width_tab[2][4] __initdata =
+    { {4, 8, 16, -1}, {9, 12, 16, -1} };
+static int epson1355_bpp_tab[8] __initdata = { 1, 2, 4, 8, 15, 16 };
 
-static void e1355_set_disp(const void *unused, struct display *disp,
-			   struct fb_info_gen *info)
+static void __init fetch_hw_state(struct fb_info *info, struct epson1355_par *par)
 {
-	struct display_switch *d;
+	struct fb_var_screeninfo *var = &info->var;
+	struct fb_fix_screeninfo *fix = &info->fix;
+	u8 panel, display;
+	u16 offset;
+	u32 xres, yres;
+	u32 xres_virtual, yres_virtual;
+	int bpp, lcd_bpp;
+	int is_color, is_dual, is_tft;
+	int lcd_enabled, crt_enabled;
 
-	disp->dispsw = &e1355_dispsw;
-	
-	switch(disp->var.bits_per_pixel) {
-#ifdef FBCON_HAS_MFB
-	case 1:
-		d = &fbcon_mfb; break;
-#endif	       
-#ifdef FBCON_HAS_CFB8
+	fix->type = FB_TYPE_PACKED_PIXELS;
+
+	display = epson1355_read_reg(par, REG_DISPLAY_MODE);
+	bpp = epson1355_bpp_tab[(display >> 2) & 7];
+
+	switch (bpp) {
 	case 8:
-		d = &fbcon_cfb8; break;
-#endif
+		fix->visual = FB_VISUAL_PSEUDOCOLOR;
+		var->bits_per_pixel = 8;
+		var->red.offset = var->green.offset = var->blue.offset = 0;
+		var->red.length = var->green.length = var->blue.length = 8;
+		break;
+	case 16:
+		/* 5-6-5 RGB */
+		fix->visual = FB_VISUAL_TRUECOLOR;
+		var->bits_per_pixel = 16;
+		var->red.offset = 11;
+		var->red.length = 5;
+		var->green.offset = 5;
+		var->green.length = 6;
+		var->blue.offset = 0;
+		var->blue.length = 5;
+		break;
 	default:
-		BUG(); break;
+		BUG();
 	}
+	fb_alloc_cmap(&(info->cmap), 256, 0);
 
-	memcpy(&e1355_dispsw, d, sizeof *d);
+	panel = epson1355_read_reg(par, REG_PANEL_TYPE);
+	is_color = (panel & 0x04) != 0;
+	is_dual = (panel & 0x02) != 0;
+	is_tft = (panel & 0x01) != 0;
+	crt_enabled = (display & 0x02) != 0;
+	lcd_enabled = (display & 0x01) != 0;
+	lcd_bpp = epson1355_width_tab[is_tft][(panel >> 4) & 3];
 
-	/* reading is terribly slow for us */
-#if 0 /* XXX: need to work out why this doesn't work */
-	e1355_dispsw.bmove = fbcon_redraw_bmove;
-#endif
-}
+	xres = (epson1355_read_reg(par, REG_HORZ_DISP_WIDTH) + 1) * 8;
+	yres = (epson1355_read_reg16(par, REG_VERT_DISP_HEIGHT0) + 1) *
+	    ((is_dual && !crt_enabled) ? 2 : 1);
+	offset = epson1355_read_reg16(par, REG_MEM_ADDR_OFFSET0) & 0x7ff;
+	xres_virtual = offset * 16 / bpp;
+	yres_virtual = fix->smem_len / (offset * 2);
 
-/* ------------ Interfaces to hardware functions ------------ */
+	var->xres = xres;
+	var->yres = yres;
+	var->xres_virtual = xres_virtual;
+	var->yres_virtual = yres_virtual;
+	var->xoffset = var->yoffset = 0;
 
+	fix->line_length = offset * 2;
 
-struct fbgen_hwswitch e1355_switch = {
-	.detect =	e1355_detect,
-	.encode_fix =	e1355_encode_fix,
-	.decode_var =	e1355_decode_var,
-	.encode_var =	e1355_encode_var,
-	.get_par =	e1355_get_par,
-	.set_par =	e1355_set_par,
-	.getcolreg =	e1355_getcolreg,
-	.pan_display =	e1355_pan_display,
-	.blank =	e1355_blank,
-	.set_disp =	e1355_set_disp,
-};
+	fix->xpanstep = 0;	/* no pan yet */
+	fix->ypanstep = 1;
+	fix->ywrapstep = 0;
+	fix->accel = FB_ACCEL_NONE;
 
+	var->grayscale = !is_color;
 
-/* ------------ Hardware Independent Functions ------------ */
+#ifdef DEBUG
+	printk(KERN_INFO
+	       "epson1355fb: xres=%d, yres=%d, "
+	       "is_color=%d, is_dual=%d, is_tft=%d\n",
+	       xres, yres, is_color, is_dual, is_tft);
+	printk(KERN_INFO
+	       "epson1355fb: bpp=%d, lcd_bpp=%d, "
+	       "crt_enabled=%d, lcd_enabled=%d\n",
+	       bpp, lcd_bpp, crt_enabled, lcd_enabled);
+#endif
+}
 
 
-static struct fb_ops e1355fb_ops = {
-	.owner =	THIS_MODULE,
-	.fb_get_fix =	fbgen_get_fix,
-	.fb_get_var =	fbgen_get_var,
-	.fb_set_var =	fbgen_set_var,
-	.fb_get_cmap =	fbgen_get_cmap,
-	.fb_set_cmap =	gen_set_cmap,
-	.fb_setcolreg =	e1355fb_setcolreg,
-	.fb_pan_display =fbgen_pan_display,
-	.fb_blank =	fbgen_blank,
-};
+static void clearfb16(struct fb_info *info)
+{
+	u16 *dst = (u16 *) info->screen_base;
+	unsigned long n = info->fix.smem_len;
 
-static struct e1355fb_info fb_info;
+	while (n > 1) {
+		fb_writew(0, dst);
+		dst++, n -= 2;
+	}
+
+	if (n)
+		fb_writeb(0, dst);
+}
 
-int __init e1355fb_setup(char *str)
+static void epson1355fb_platform_release(struct device *device)
 {
-	return 0;
 }
 
-int __init e1355fb_init(void)
+static int epson1355fb_remove(struct device *device)
 {
-	fb_info.gen.fbhw = &e1355_switch;
-	fb_info.gen.fbhw->detect();
-	strcpy(fb_info.gen.info.modename, "SED1355");
-	fb_info.gen.info.changevar = NULL;
-	fb_info.gen.info.fbops = &e1355fb_ops;
-	fb_info.gen.info.screen_base = (void *)E1355_FB_BASE;
-	fb_info.gen.currcon = -1;
-	fb_info.gen.info.disp = &disp;
-	fb_info.gen.parsize = sizeof(struct e1355_par);
-	fb_info.gen.info.switch_con = &fbgen_switch;
-	fb_info.gen.info.updatevar = &fbgen_update_var;
-	fb_info.gen.info.flags = FBINFO_FLAG_DEFAULT;
-	/* This should give a reasonable default video mode */
-	fbgen_get_var(&disp.var, -1, &fb_info.gen.info);
-	fbgen_do_set_var(&disp.var, 1, &fb_info.gen);
-	fbgen_set_disp(-1, &fb_info.gen);
-	if (disp.var.bits_per_pixel > 1) 
-		do_install_cmap(0, &fb_info.gen);
-	if (register_framebuffer(&fb_info.gen.info) < 0)
-		return -EINVAL;
-	printk(KERN_INFO "fb%d: %s frame buffer device\n", fb_info.gen.info.node,
-	       fb_info.gen.info.modename);
+	struct fb_info *info = dev_get_drvdata(device);
+	struct epson1355_par *par = info->par;
+
+	backlight_enable(0);
+	if (par) {
+		lcd_enable(par, 0);
+		if (par && par->reg_addr)
+			iounmap((void *) par->reg_addr);
+	}
 
+	if (info) {
+		fb_dealloc_cmap(&info->cmap);
+		if (info->screen_base)
+			iounmap(info->screen_base);
+		framebuffer_release(info);
+	}
+	release_mem_region(EPSON1355FB_FB_PHYS, EPSON1355FB_FB_LEN);
+	release_mem_region(EPSON1355FB_REGS_PHYS, EPSON1355FB_REGS_LEN);
 	return 0;
 }
 
+int __init epson1355fb_probe(struct device *device)
+{
+	struct platform_device *dev = to_platform_device(device);
+	struct epson1355_par *default_par;
+	struct fb_info *info;
+	u8 revision;
+	int rc = 0;
+
+	if (!request_mem_region(EPSON1355FB_REGS_PHYS, EPSON1355FB_REGS_LEN, "S1D13505 registers")) {
+		printk(KERN_ERR "epson1355fb: unable to reserve "
+		       "registers at 0x%0x\n", EPSON1355FB_REGS_PHYS);
+		rc = -EBUSY;
+		goto bail;
+	}
+
+	if (!request_mem_region(EPSON1355FB_FB_PHYS, EPSON1355FB_FB_LEN,
+				"S1D13505 framebuffer")) {
+		printk(KERN_ERR "epson1355fb: unable to reserve "
+		       "framebuffer at 0x%0x\n", EPSON1355FB_FB_PHYS);
+		rc = -EBUSY;
+		goto bail;
+	}
 
-    /*
-     *  Cleanup
-     */
+	info = framebuffer_alloc(sizeof(struct epson1355_par) + sizeof(u32) * 256, &dev->dev);
+	if (!info)
+		rc = -ENOMEM;
+		goto bail;
+
+	default_par = info->par;
+	default_par->reg_addr = (unsigned long) ioremap(EPSON1355FB_REGS_PHYS, EPSON1355FB_REGS_LEN);
+	if (!default_par->reg_addr) {
+		printk(KERN_ERR "epson1355fb: unable to map registers\n");
+		rc = -ENOMEM;
+		goto bail;
+	}
+	info->pseudo_palette = (void *)(default_par + 1);
 
-void e1355fb_cleanup(struct fb_info *info)
-{
+	info->screen_base = ioremap(EPSON1355FB_FB_PHYS, EPSON1355FB_FB_LEN);
+	if (!info->screen_base) {
+		printk(KERN_ERR "epson1355fb: unable to map framebuffer\n");
+		rc = -ENOMEM;
+		goto bail;
+	}
+
+	revision = epson1355_read_reg(default_par, REG_REVISION_CODE);
+	if ((revision >> 2) != 3) {
+		printk(KERN_INFO "epson1355fb: epson1355 not found\n");
+		rc = -ENODEV;
+		goto bail;
+	}
+
+	info->fix.mmio_start = EPSON1355FB_REGS_PHYS;
+	info->fix.mmio_len = EPSON1355FB_REGS_LEN;
+	info->fix.smem_start = EPSON1355FB_FB_PHYS;
+	info->fix.smem_len = get_fb_size(info);
+
+	printk(KERN_INFO "epson1355fb: regs mapped at 0x%lx, fb %d KiB mapped at 0x%p\n",
+	       default_par->reg_addr, info->fix.smem_len / 1024, info->screen_base);
+
+	strcpy(info->fix.id, "S1D13505");
+	info->par = default_par;
+	info->fbops = &epson1355fb_fbops;
+	info->flags = FBINFO_DEFAULT | FBINFO_HWACCEL_YPAN;
+
+	/* we expect the boot loader to have initialized the chip
+	   with appropriate parameters from which we can determinte
+	   the flavor of lcd panel attached */
+	fetch_hw_state(info, default_par);
+
+	/* turn this puppy on ... */
+	clearfb16(info);
+	backlight_enable(1);
+	lcd_enable(default_par, 1);
+
+	if (register_framebuffer(info) < 0) {
+		rc = -EINVAL;
+		goto bail;
+	}
 	/*
-	 *  If your driver supports multiple boards, you should unregister and
-	 *  clean up all instances.
+	 * Our driver data.
 	 */
+	dev_set_drvdata(&dev->dev, info);
+
+	printk(KERN_INFO "fb%d: %s frame buffer device\n",
+	       info->node, info->fix.id);
+
+	return 0;
+
+      bail:
+	epson1355fb_remove(device);
+	return rc;
+}
+
+static struct device_driver epson1355fb_driver = {
+	.name	= "epson1355fb",
+	.bus	= &platform_bus_type,
+	.probe	= epson1355fb_probe,
+	.remove	= epson1355fb_remove,
+};
+
+static struct platform_device epson1355fb_device = {
+	.name	= "epson1355fb",
+	.id	= 0,
+	.dev	= {
+		.release = epson1355fb_platform_release,
+	}
+};
+
+int __init epson1355fb_init(void)
+{
+	int ret = 0;
+
+	if (fb_get_options("epson1355fb", NULL))
+		return -ENODEV;
+
+	ret = driver_register(&epson1355fb_driver);
+	if (!ret) {
+		ret = platform_device_register(&epson1355fb_device);
+		if (ret)
+			driver_unregister(&epson1355fb_driver);
+	}
+	return ret;
+}
+
+module_init(epson1355fb_init);
 	
-	unregister_framebuffer(info);
-	/* ... */
+#ifdef MODULE
+static void __exit epson1355fb_exit(void)
+{
+	platform_device_unregister(&epson1355fb_device);
+	driver_unregister(&epson1355fb_driver);
 }
 
+/* ------------------------------------------------------------------------- */
+
+module_exit(epson1355fb_exit);
+#endif
+
+MODULE_AUTHOR("Christopher Hoover <ch@hpl.hp.com>");
+MODULE_DESCRIPTION("Framebuffer driver for Epson S1D13505");
 MODULE_LICENSE("GPL");
diff -Nru a/drivers/video/fbmem.c b/drivers/video/fbmem.c
--- a/drivers/video/fbmem.c	2004-10-18 14:55:46 -07:00
+++ b/drivers/video/fbmem.c	2004-10-18 14:55:46 -07:00
@@ -47,385 +47,34 @@
 
 #include <linux/fb.h>
 
-#ifdef CONFIG_FRAMEBUFFER_CONSOLE
-#include "console/fbcon.h"
-#endif
     /*
      *  Frame buffer device initialization and setup routines
      */
 
-extern int acornfb_init(void);
-extern int acornfb_setup(char*);
-extern int amifb_init(void);
-extern int amifb_setup(char*);
-extern int atafb_init(void);
-extern int atafb_setup(char*);
-extern int macfb_init(void);
-extern int macfb_setup(char*);
-extern int cyberfb_init(void);
-extern int cyberfb_setup(char*);
-extern int pm2fb_init(void);
-extern int pm2fb_setup(char*);
-extern int pm3fb_init(void);
-extern int pm3fb_setup(char*);
-extern int clps711xfb_init(void);
-extern int cyber2000fb_init(void);
-extern int cyber2000fb_setup(char*);
-extern int retz3fb_init(void);
-extern int retz3fb_setup(char*);
-extern int cirrusfb_init(void);
-extern int cirrusfb_setup(char*);
-extern int hitfb_init(void);
-extern int vfb_init(void);
-extern int vfb_setup(char*);
-extern int offb_init(void);
-extern int atyfb_init(void);
-extern int atyfb_setup(char*);
-extern int aty128fb_init(void);
-extern int aty128fb_setup(char*);
-extern int neofb_init(void);
-extern int neofb_setup(char*);
-extern int igafb_init(void);
-extern int igafb_setup(char*);
-extern int imsttfb_init(void);
-extern int imsttfb_setup(char*);
-extern int dnfb_init(void);
-extern int tgafb_init(void);
-extern int tgafb_setup(char*);
-extern int virgefb_init(void);
-extern int virgefb_setup(char*);
-extern int resolver_video_setup(char*);
-extern int s3triofb_init(void);
-extern int vesafb_init(void);
-extern int vesafb_setup(char*);
-extern int vga16fb_init(void);
-extern int vga16fb_setup(char*);
-extern int hgafb_init(void);
-extern int hgafb_setup(char*);
-extern int matroxfb_init(void);
-extern int matroxfb_setup(char*);
-extern int hpfb_init(void);
-extern int platinumfb_init(void);
-extern int platinumfb_setup(char*);
-extern int control_init(void);
-extern int control_setup(char*);
-extern int valkyriefb_init(void);
-extern int valkyriefb_setup(char*);
-extern int chips_init(void);
-extern int g364fb_init(void);
-extern int sa1100fb_init(void);
-extern int pxafb_init(void);
-extern int pxafb_setup(char*);
-extern int fm2fb_init(void);
-extern int fm2fb_setup(char*);
-extern int q40fb_init(void);
-extern int sun3fb_init(void);
-extern int sun3fb_setup(char *);
-extern int sgivwfb_init(void);
-extern int sgivwfb_setup(char*);
-extern int gbefb_init(void);
-extern int gbefb_setup(char*);
-extern int rivafb_init(void);
-extern int rivafb_setup(char*);
-extern int tdfxfb_init(void);
-extern int tdfxfb_setup(char*);
-extern int tridentfb_init(void);
-extern int tridentfb_setup(char*);
-extern int sisfb_init(void);
-extern int sisfb_setup(char*);
-extern int stifb_init(void);
-extern int stifb_setup(char*);
-extern int pmagbafb_init(void);
-extern int pmagbbfb_init(void);
-extern int maxinefb_init(void);
-extern int tx3912fb_init(void);
-extern int tx3912fb_setup(char*);
-extern int radeonfb_init(void);
-extern int radeonfb_setup(char*);
-extern int radeonfb_old_init(void);
-extern int radeonfb_old_setup(char*);
-extern int e1355fb_init(void);
-extern int e1355fb_setup(char*);
-extern int pvr2fb_init(void);
-extern int pvr2fb_setup(char*);
-extern int sstfb_init(void);
-extern int sstfb_setup(char*);
-extern int i810fb_init(void);
-extern int i810fb_setup(char*);
-extern int ffb_init(void);
-extern int ffb_setup(char*);
-extern int cg6_init(void);
-extern int cg6_setup(char*);
-extern int cg3_init(void);
-extern int cg3_setup(char*);
-extern int bw2_init(void);
-extern int bw2_setup(char*);
-extern int cg14_init(void);
-extern int cg14_setup(char*);
-extern int p9100_init(void);
-extern int p9100_setup(char*);
-extern int tcx_init(void);
-extern int tcx_setup(char*);
-extern int leo_init(void);
-extern int leo_setup(char*);
-extern int kyrofb_init(void);
-extern int kyrofb_setup(char*);
-extern int mc68x328fb_init(void);
-extern int mc68x328fb_setup(char *);
-extern int asiliantfb_init(void);
-
-static struct {
-	const char *name;
-	int (*init)(void);
-	int (*setup)(char*);
-} fb_drivers[] __initdata = {
-
-	/*
-	 * Chipset specific drivers that use resource management
-	 */
-#ifdef CONFIG_FB_RETINAZ3
-	{ "retz3fb", retz3fb_init, retz3fb_setup },
-#endif
-#ifdef CONFIG_FB_AMIGA
-	{ "amifb", amifb_init, amifb_setup },
-#endif
-#ifdef CONFIG_FB_CLPS711X
-	{ "clps711xfb", clps711xfb_init, NULL },
-#endif
-#ifdef CONFIG_FB_CYBER
-	{ "cyberfb", cyberfb_init, cyberfb_setup },
-#endif
-#ifdef CONFIG_FB_CYBER2000
-	{ "cyber2000fb", cyber2000fb_init, cyber2000fb_setup },
-#endif
-#ifdef CONFIG_FB_PM2
-	{ "pm2fb", pm2fb_init, pm2fb_setup },
-#endif
-#ifdef CONFIG_FB_PM3
-	{ "pm3fb", pm3fb_init, pm3fb_setup },
-#endif           
-#ifdef CONFIG_FB_CIRRUS
-	{ "cirrusfb", cirrusfb_init, cirrusfb_setup },
-#endif
-#ifdef CONFIG_FB_ATY
-	{ "atyfb", atyfb_init, atyfb_setup },
-#endif
-#ifdef CONFIG_FB_MATROX
-	{ "matroxfb", matroxfb_init, matroxfb_setup },
-#endif
-#ifdef CONFIG_FB_ATY128
-	{ "aty128fb", aty128fb_init, aty128fb_setup },
-#endif
-#ifdef CONFIG_FB_NEOMAGIC
-	{ "neofb", neofb_init, neofb_setup },
-#endif
-#ifdef CONFIG_FB_VIRGE
-	{ "virgefb", virgefb_init, virgefb_setup },
-#endif
-#ifdef CONFIG_FB_RIVA
-	{ "rivafb", rivafb_init, rivafb_setup },
-#endif
-#ifdef CONFIG_FB_3DFX
-	{ "tdfxfb", tdfxfb_init, tdfxfb_setup },
-#endif
-#ifdef CONFIG_FB_RADEON
-	{ "radeonfb", radeonfb_init, radeonfb_setup },
-#endif
-#ifdef CONFIG_FB_RADEON_OLD
-	{ "radeonfb_old", radeonfb_old_init, radeonfb_old_setup },
-#endif
-#ifdef CONFIG_FB_CONTROL
-	{ "controlfb", control_init, control_setup },
-#endif
-#ifdef CONFIG_FB_PLATINUM
-	{ "platinumfb", platinumfb_init, platinumfb_setup },
-#endif
-#ifdef CONFIG_FB_VALKYRIE
-	{ "valkyriefb", valkyriefb_init, valkyriefb_setup },
-#endif
-#ifdef CONFIG_FB_CT65550
-	{ "chipsfb", chips_init, NULL },
-#endif
-#ifdef CONFIG_FB_IMSTT
-	{ "imsttfb", imsttfb_init, imsttfb_setup },
-#endif
-#ifdef CONFIG_FB_S3TRIO
-	{ "s3triofb", s3triofb_init, NULL },
-#endif 
-#ifdef CONFIG_FB_FM2
-	{ "fm2fb", fm2fb_init, fm2fb_setup },
-#endif 
-#ifdef CONFIG_FB_SIS
-	{ "sisfb", sisfb_init, sisfb_setup },
-#endif
-#ifdef CONFIG_FB_TRIDENT
-	{ "tridentfb", tridentfb_init, tridentfb_setup },
-#endif
-#ifdef CONFIG_FB_I810
-	{ "i810fb", i810fb_init, i810fb_setup },
-#endif	
-#ifdef CONFIG_FB_STI
-	{ "stifb", stifb_init, stifb_setup },
-#endif
-#ifdef CONFIG_FB_FFB
-	{ "ffb", ffb_init, ffb_setup },
-#endif
-#ifdef CONFIG_FB_CG6
-	{ "cg6fb", cg6_init, cg6_setup },
-#endif
-#ifdef CONFIG_FB_CG3
-	{ "cg3fb", cg3_init, cg3_setup },
-#endif
-#ifdef CONFIG_FB_BW2
-	{ "bw2fb", bw2_init, bw2_setup },
-#endif
-#ifdef CONFIG_FB_CG14
-	{ "cg14fb", cg14_init, cg14_setup },
-#endif
-#ifdef CONFIG_FB_P9100
-	{ "p9100fb", p9100_init, p9100_setup },
-#endif
-#ifdef CONFIG_FB_TCX
-	{ "tcxfb", tcx_init, tcx_setup },
-#endif
-#ifdef CONFIG_FB_LEO
-	{ "leofb", leo_init, leo_setup },
-#endif
-
-	/*
-	 * Generic drivers that are used as fallbacks
-	 * 
-	 * These depend on resource management and must be initialized
-	 * _after_ all other frame buffer devices that use resource
-	 * management!
-	 */
-
-#ifdef CONFIG_FB_OF
-	{ "offb", offb_init, NULL },
-#endif
-#ifdef CONFIG_FB_VESA
-	{ "vesafb", vesafb_init, vesafb_setup },
-#endif 
-
-	/*
-	 * Chipset specific drivers that don't use resource management (yet)
-	 */
-
-#ifdef CONFIG_FB_SGIVW
-	{ "sgivwfb", sgivwfb_init, sgivwfb_setup },
-#endif
-#ifdef CONFIG_FB_GBE
-	{ "gbefb", gbefb_init, gbefb_setup },
-#endif
-#ifdef CONFIG_FB_ACORN
-	{ "acornfb", acornfb_init, acornfb_setup },
-#endif
-#ifdef CONFIG_FB_ATARI
-	{ "atafb", atafb_init, atafb_setup },
-#endif
-#ifdef CONFIG_FB_MAC
-	{ "macfb", macfb_init, macfb_setup },
-#endif
-#ifdef CONFIG_FB_HGA
-	{ "hgafb", hgafb_init, hgafb_setup },
-#endif 
-#ifdef CONFIG_FB_IGA
-	{ "igafb", igafb_init, igafb_setup },
-#endif
-#ifdef CONFIG_APOLLO
-	{ "apollofb", dnfb_init, NULL },
-#endif
-#ifdef CONFIG_FB_Q40
-	{ "q40fb", q40fb_init, NULL },
-#endif
-#ifdef CONFIG_FB_TGA
-	{ "tgafb", tgafb_init, tgafb_setup },
-#endif
-#ifdef CONFIG_FB_HP300
-	{ "hpfb", hpfb_init, NULL },
-#endif 
-#ifdef CONFIG_FB_G364
-	{ "g364fb", g364fb_init, NULL },
-#endif
-#ifdef CONFIG_FB_SA1100
-	{ "sa1100fb", sa1100fb_init, NULL },
-#endif
-#ifdef CONFIG_FB_PXA
-	{ "pxafb", pxafb_init, pxafb_setup },
-#endif
-#ifdef CONFIG_FB_SUN3
-	{ "sun3fb", sun3fb_init, sun3fb_setup },
-#endif
-#ifdef CONFIG_FB_HIT
-	{ "hitfb", hitfb_init, NULL },
-#endif
-#ifdef CONFIG_FB_TX3912
-	{ "tx3912fb", tx3912fb_init, tx3912fb_setup },
-#endif
-#ifdef CONFIG_FB_E1355
-	{ "e1355fb", e1355fb_init, e1355fb_setup },
-#endif
-#ifdef CONFIG_FB_PVR2
-	{ "pvr2fb", pvr2fb_init, pvr2fb_setup },
-#endif
-#ifdef CONFIG_FB_PMAG_BA
-	{ "pmagbafb", pmagbafb_init, NULL },
-#endif          
-#ifdef CONFIG_FB_PMAGB_B
-	{ "pmagbbfb", pmagbbfb_init, NULL },
-#endif
-#ifdef CONFIG_FB_MAXINE
-	{ "maxinefb", maxinefb_init, NULL },
-#endif            
-#ifdef CONFIG_FB_VOODOO1
-	{ "sstfb", sstfb_init, sstfb_setup },
-#endif
-#ifdef CONFIG_FB_KYRO
-	{ "kyrofb", kyrofb_init, kyrofb_setup },
-#endif
-#ifdef CONFIG_FB_68328
-	{ "68328fb", mc68x328fb_init, mc68x328fb_setup },
-#endif
-#ifdef CONFIG_FB_ASILIANT
-	{ "asiliantfb", asiliantfb_init, NULL },
-#endif
-
-	/*
-	 * Generic drivers that don't use resource management (yet)
-	 */
-
-#ifdef CONFIG_FB_VGA16
-	{ "vga16fb", vga16fb_init, vga16fb_setup },
-#endif 
-
-#ifdef CONFIG_GSP_RESOLVER
-	/* Not a real frame buffer device... */
-	{ "resolverfb", NULL, resolver_video_setup },
-#endif
-
-#ifdef CONFIG_FB_VIRTUAL
-	/*
-	 * Vfb must be last to avoid that it becomes your primary display if
-	 * other display devices are present
-	 */
-	{ "vfb", vfb_init, vfb_setup },
-#endif
-};
-
-#define NUM_FB_DRIVERS	(sizeof(fb_drivers)/sizeof(*fb_drivers))
 #define FBPIXMAPSIZE	16384
 
-extern const char *global_mode_option;
-
-static initcall_t pref_init_funcs[FB_MAX];
-static int num_pref_init_funcs __initdata = 0;
 static struct notifier_block *fb_notifier_list;
 struct fb_info *registered_fb[FB_MAX];
 int num_registered_fb;
 
-#ifdef CONFIG_FB_OF
-static int ofonly __initdata = 0;
-#endif
+/*
+ * Helpers
+ */
+
+int fb_get_color_depth(struct fb_info *info)
+{
+	struct fb_var_screeninfo *var = &info->var;
+
+	if (var->green.length == var->blue.length &&
+	    var->green.length == var->red.length &&
+	    !var->green.offset && !var->blue.offset &&
+	    !var->red.offset)
+		return var->green.length;
+	else
+		return (var->green.length + var->red.length +
+			var->blue.length);
+}
+EXPORT_SYMBOL(fb_get_color_depth);
 
 /*
  * Drawing helpers.
@@ -646,9 +295,12 @@
 			       const struct linux_logo *logo, u8 *dst,
 			       int depth)
 {
-	int i, j, shift;
+	int i, j, k, fg = 1;
 	const u8 *src = logo->data;
-	u8 d, xor = 0;
+	u8 d, xor = (info->fix.visual == FB_VISUAL_MONO01) ? 0xff : 0;
+
+	if (fb_get_color_depth(info) == 3)
+		fg = 7;
 
 	switch (depth) {
 	case 4:
@@ -662,17 +314,14 @@
 				}
 			}
 		break;
-	case ~1:
-		xor = 0xff;
 	case 1:
 		for (i = 0; i < logo->height; i++) {
-			shift = 7;
-			d = *src++ ^ xor;
-			for (j = 0; j < logo->width; j++) {
-				*dst++ = (d >> shift) & 1;
-				shift = (shift-1) & 7;
-				if (shift == 7)
-					d = *src++ ^ xor;
+			for (j = 0; j < logo->width; src++) {
+				d = *src ^ xor;
+				for (k = 7; k >= 0; k--) {
+					*dst++ = ((d >> k) & 1) ? fg : 0;
+					j++;
+				}
 			}
 		}
 		break;
@@ -715,26 +364,35 @@
 
 int fb_prepare_logo(struct fb_info *info)
 {
+	int depth = fb_get_color_depth(info);
+
 	memset(&fb_logo, 0, sizeof(struct logo_data));
 
-	switch (info->fix.visual) {
-	case FB_VISUAL_TRUECOLOR:
-		if (info->var.bits_per_pixel >= 8)
+	if (info->fix.visual == FB_VISUAL_DIRECTCOLOR) {
+		depth = info->var.blue.length;
+		if (info->var.red.length < depth)
+			depth = info->var.red.length;
+		if (info->var.green.length < depth)
+			depth = info->var.green.length;
+	}
+
+	if (depth >= 8) {
+		switch (info->fix.visual) {
+		case FB_VISUAL_TRUECOLOR:
 			fb_logo.needs_truepalette = 1;
-		break;
-	case FB_VISUAL_DIRECTCOLOR:
-		if (info->var.bits_per_pixel >= 24) {
+			break;
+		case FB_VISUAL_DIRECTCOLOR:
 			fb_logo.needs_directpalette = 1;
 			fb_logo.needs_cmapreset = 1;
+			break;
+		case FB_VISUAL_PSEUDOCOLOR:
+			fb_logo.needs_cmapreset = 1;
+			break;
 		}
-		break;
-	case FB_VISUAL_PSEUDOCOLOR:
-		fb_logo.needs_cmapreset = 1;
-		break;
 	}
 
 	/* Return if no suitable logo was found */
-	fb_logo.logo = fb_find_logo(info->var.bits_per_pixel);
+	fb_logo.logo = fb_find_logo(depth);
 	
 	if (!fb_logo.logo || fb_logo.logo->height > info->var.yres) {
 		fb_logo.logo = NULL;
@@ -761,7 +419,7 @@
 	if (fb_logo.logo == NULL || info->state != FBINFO_STATE_RUNNING)
 		return 0;
 
-	image.depth = fb_logo.depth;
+	image.depth = 8;
 	image.data = fb_logo.logo->data;
 
 	if (fb_logo.needs_cmapreset)
@@ -782,7 +440,7 @@
 		info->pseudo_palette = palette;
 	}
 
-	if (fb_logo.depth == 4) {
+	if (fb_logo.depth <= 4) {
 		logo_new = kmalloc(fb_logo.logo->width * fb_logo.logo->height, 
 				   GFP_KERNEL);
 		if (logo_new == NULL) {
@@ -846,6 +504,9 @@
 	struct inode *inode = file->f_dentry->d_inode;
 	int fbidx = iminor(inode);
 	struct fb_info *info = registered_fb[fbidx];
+	u32 *buffer, *dst, *src;
+	int c, i, cnt = 0, err = 0;
+	unsigned long total_size;
 
 	if (!info || ! info->screen_base)
 		return -ENODEV;
@@ -856,24 +517,55 @@
 	if (info->fbops->fb_read)
 		return info->fbops->fb_read(file, buf, count, ppos);
 	
-	if (p >= info->fix.smem_len)
+	total_size = info->screen_size;
+	if (total_size == 0)
+		total_size = info->fix.smem_len;
+
+	if (p >= total_size)
 	    return 0;
-	if (count >= info->fix.smem_len)
-	    count = info->fix.smem_len;
-	if (count + p > info->fix.smem_len)
-		count = info->fix.smem_len - p;
+	if (count >= total_size)
+	    count = total_size;
+	if (count + p > total_size)
+		count = total_size - p;
+
+	cnt = 0;
+	buffer = kmalloc((count > PAGE_SIZE) ? PAGE_SIZE : count,
+			 GFP_KERNEL);
+	if (!buffer)
+		return -ENOMEM;
+
+	src = (u32 *) (info->screen_base + p);
+
 	if (info->fbops->fb_sync)
 		info->fbops->fb_sync(info);
-	if (count) {
-	    char *base_addr;
 
-	    base_addr = info->screen_base;
-	    count -= copy_to_user(buf, base_addr+p, count);
-	    if (!count)
-		return -EFAULT;
-	    *ppos += count;
+	while (count) {
+		c  = (count > PAGE_SIZE) ? PAGE_SIZE : count;
+		dst = buffer;
+		for (i = c >> 2; i--; )
+			*dst++ = fb_readl(src++);
+		if (c & 3) {
+			u8 *dst8 = (u8 *) dst;
+			u8 *src8 = (u8 *) src;
+
+			for (i = c & 3; i--;)
+				*dst8++ = fb_readb(src8++);
+
+			src = (u32 *) src8;
+		}
+
+		if (copy_to_user(buf, buffer, c)) {
+			err = -EFAULT;
+			break;
+		}
+		*ppos += c;
+		buf += c;
+		cnt += c;
+		count -= c;
 	}
-	return count;
+
+	kfree(buffer);
+	return (err) ? err : cnt;
 }
 
 static ssize_t
@@ -883,7 +575,9 @@
 	struct inode *inode = file->f_dentry->d_inode;
 	int fbidx = iminor(inode);
 	struct fb_info *info = registered_fb[fbidx];
-	int err;
+	u32 *buffer, *dst, *src;
+	int c, i, cnt = 0, err;
+	unsigned long total_size;
 
 	if (!info || !info->screen_base)
 		return -ENODEV;
@@ -894,28 +588,56 @@
 	if (info->fbops->fb_write)
 		return info->fbops->fb_write(file, buf, count, ppos);
 	
-	if (p > info->fix.smem_len)
+	total_size = info->screen_size;
+	if (total_size == 0)
+		total_size = info->fix.smem_len;
+
+	if (p > total_size)
 	    return -ENOSPC;
-	if (count >= info->fix.smem_len)
-	    count = info->fix.smem_len;
+	if (count >= total_size)
+	    count = total_size;
 	err = 0;
-	if (count + p > info->fix.smem_len) {
-	    count = info->fix.smem_len - p;
+	if (count + p > total_size) {
+	    count = total_size - p;
 	    err = -ENOSPC;
 	}
+	cnt = 0;
+	buffer = kmalloc((count > PAGE_SIZE) ? PAGE_SIZE : count,
+			 GFP_KERNEL);
+	if (!buffer)
+		return -ENOMEM;
+
+	dst = (u32 *) (info->screen_base + p);
+
 	if (info->fbops->fb_sync)
 		info->fbops->fb_sync(info);
-	if (count) {
-	    char *base_addr;
 
-	    base_addr = info->screen_base;
-	    count -= copy_from_user(base_addr+p, buf, count);
-	    *ppos += count;
-	    err = -EFAULT;
+	while (count) {
+		c = (count > PAGE_SIZE) ? PAGE_SIZE : count;
+		src = buffer;
+		if (copy_from_user(src, buf, c)) {
+			err = -EFAULT;
+			break;
+		}
+		for (i = c >> 2; i--; )
+			fb_writel(*src++, dst++);
+		if (c & 3) {
+			u8 *src8 = (u8 *) src;
+			u8 *dst8 = (u8 *) dst;
+
+			for (i = c & 3; i--; )
+				fb_writeb(*src8++, dst8++);
+
+			dst = (u32 *) dst8;
+		}
+		*ppos += c;
+		buf += c;
+		cnt += c;
+		count -= c;
 	}
-	if (count)
-		return count;
-	return err;
+	kfree(buffer);
+
+	return (err) ? err : cnt;
 }
 
 #ifdef CONFIG_KMOD
@@ -942,20 +664,21 @@
 {
 	struct fb_cursor_user cursor_user;
 	struct fb_cursor cursor;
-	char *data = NULL, *mask = NULL;
+	char *data = NULL, *mask = NULL, *info_mask = NULL;
 	u16 *red = NULL, *green = NULL, *blue = NULL, *transp = NULL;
 	int err = -EINVAL;
 	
 	if (copy_from_user(&cursor_user, sprite, sizeof(struct fb_cursor_user)))
 		return -EFAULT;
 
-	memcpy(&cursor, &cursor_user, sizeof(cursor));
-	cursor.mask = NULL;
-	cursor.image.data = NULL;
-	cursor.image.cmap.red = NULL;
-	cursor.image.cmap.green = NULL;
-	cursor.image.cmap.blue = NULL;
-	cursor.image.cmap.transp = NULL;
+	memcpy(&cursor, &cursor_user, sizeof(cursor_user));
+	cursor.mask = info->cursor.mask;
+	cursor.image.data = info->cursor.image.data;
+	cursor.image.cmap.red = info->cursor.image.cmap.red;
+	cursor.image.cmap.green = info->cursor.image.cmap.green;
+	cursor.image.cmap.blue = info->cursor.image.cmap.blue;
+	cursor.image.cmap.transp = info->cursor.image.cmap.transp;
+	cursor.data = NULL;
 
 	if (cursor.set & FB_CUR_SETCUR)
 		info->cursor.enable = 1;
@@ -1014,6 +737,8 @@
 		
 		cursor.image.data = data;
 		cursor.mask = mask;
+		info_mask = (char *) info->cursor.mask;
+		info->cursor.mask = mask;
 	}
 	info->cursor.set = cursor.set;
 	info->cursor.rop = cursor.rop;
@@ -1025,6 +750,8 @@
 	kfree(green);
 	kfree(blue);
 	kfree(transp);
+	if (info_mask)
+		info->cursor.mask = info_mask;
 	return err;
 }
 
@@ -1055,6 +782,30 @@
 {
 	int err;
 
+	if (var->activate & FB_ACTIVATE_INV_MODE) {
+		struct fb_videomode mode1, mode2;
+		int ret = 0;
+
+		fb_var_to_videomode(&mode1, var);
+		fb_var_to_videomode(&mode2, &info->var);
+		/* make sure we don't delete the videomode of current var */
+		ret = fb_mode_is_equal(&mode1, &mode2);
+
+		if (!ret) {
+		    struct fb_event event;
+
+		    event.info = info;
+		    event.data = &mode1;
+		    ret = notifier_call_chain(&fb_notifier_list,
+					      FB_EVENT_MODE_DELETE, &event);
+		}
+
+		if (!ret)
+		    fb_delete_videomode(&mode1, &info->modelist);
+
+		return ret;
+	}
+
 	if ((var->activate & FB_ACTIVATE_FORCE) ||
 	    memcmp(&info->var, var, sizeof(struct fb_var_screeninfo))) {
 		if (!info->fbops->fb_check_var) {
@@ -1066,6 +817,7 @@
 			return err;
 
 		if ((var->activate & FB_ACTIVATE_MASK) == FB_ACTIVATE_NOW) {
+			struct fb_videomode mode;
 			info->var = *var;
 
 			if (info->fbops->fb_set_par)
@@ -1075,10 +827,16 @@
 
 			fb_set_cmap(&info->cmap, info);
 
+			fb_var_to_videomode(&mode, &info->var);
+			fb_add_videomode(&mode, &info->modelist);
+
 			if (info->flags & FBINFO_MISC_MODECHANGEUSER) {
+				struct fb_event event;
+
 				info->flags &= ~FBINFO_MISC_MODECHANGEUSER;
+				event.info = info;
 				notifier_call_chain(&fb_notifier_list,
-						    FB_EVENT_MODE_CHANGE, info);
+						    FB_EVENT_MODE_CHANGE, &event);
 			}
 		}
 	}
@@ -1114,10 +872,9 @@
 	struct fb_ops *fb = info->fbops;
 	struct fb_var_screeninfo var;
 	struct fb_fix_screeninfo fix;
-#ifdef CONFIG_FRAMEBUFFER_CONSOLE
 	struct fb_con2fbmap con2fb;
-#endif
 	struct fb_cmap_user cmap;
+	struct fb_event event;
 	void __user *argp = (void __user *)arg;
 	int i;
 	
@@ -1166,13 +923,16 @@
 		i = fb_cursor(info, argp);
 		release_console_sem();
 		return i;
-#ifdef CONFIG_FRAMEBUFFER_CONSOLE
 	case FBIOGET_CON2FBMAP:
 		if (copy_from_user(&con2fb, argp, sizeof(con2fb)))
 			return -EFAULT;
 		if (con2fb.console < 1 || con2fb.console > MAX_NR_CONSOLES)
 		    return -EINVAL;
-		con2fb.framebuffer = con2fb_map[con2fb.console-1];
+		con2fb.framebuffer = -1;
+		event.info = info;
+		event.data = &con2fb;
+		notifier_call_chain(&fb_notifier_list,
+				    FB_EVENT_GET_CONSOLE_MAP, &event);
 		return copy_to_user(argp, &con2fb,
 				    sizeof(con2fb)) ? -EFAULT : 0;
 	case FBIOPUT_CON2FBMAP:
@@ -1188,11 +948,14 @@
 #endif /* CONFIG_KMOD */
 		if (!registered_fb[con2fb.framebuffer])
 		    return -EINVAL;
-		if (con2fb.console > 0 && con2fb.console < MAX_NR_CONSOLES)
-			return set_con2fb_map(con2fb.console-1,
-					      con2fb.framebuffer);
+		if (con2fb.console > 0 && con2fb.console < MAX_NR_CONSOLES) {
+			event.info = info;
+			event.data = &con2fb;
+			return notifier_call_chain(&fb_notifier_list,
+						   FB_EVENT_SET_CONSOLE_MAP,
+						   &event);
+		}
 		return -EINVAL;
-#endif	/* CONFIG_FRAMEBUFFER_CONSOLE */
 	case FBIOBLANK:
 		acquire_console_sem();
 		i = fb_blank(info, arg);
@@ -1371,6 +1134,7 @@
 {
 	int i;
 	struct class_device *c;
+	struct fb_event event;
 
 	if (num_registered_fb == FB_MAX)
 		return -ENXIO;
@@ -1410,10 +1174,23 @@
 	}
 	fb_info->sprite.offset = 0;
 
+	if (!fb_info->modelist.prev ||
+	    !fb_info->modelist.next ||
+	    list_empty(&fb_info->modelist)) {
+	        struct fb_videomode mode;
+
+		INIT_LIST_HEAD(&fb_info->modelist);
+		fb_var_to_videomode(&mode, &fb_info->var);
+		fb_add_videomode(&mode, &fb_info->modelist);
+	}
+
 	registered_fb[i] = fb_info;
 
 	devfs_mk_cdev(MKDEV(FB_MAJOR, i),
 			S_IFCHR | S_IRUGO | S_IWUGO, "fb/%d", i);
+	event.info = fb_info;
+	notifier_call_chain(&fb_notifier_list,
+			    FB_EVENT_FB_REGISTERED, &event);
 	return 0;
 }
 
@@ -1442,6 +1219,7 @@
 		kfree(fb_info->pixmap.addr);
 	if (fb_info->sprite.addr && (fb_info->sprite.flags & FB_PIXMAP_DEFAULT))
 		kfree(fb_info->sprite.addr);
+	fb_destroy_modelist(&fb_info->modelist);
 	registered_fb[i]=NULL;
 	num_registered_fb--;
 	class_simple_device_remove(MKDEV(FB_MAJOR, i));
@@ -1477,12 +1255,15 @@
  */
 void fb_set_suspend(struct fb_info *info, int state)
 {
+	struct fb_event event;
+
+	event.info = info;
 	if (state) {
-		notifier_call_chain(&fb_notifier_list, FB_EVENT_SUSPEND, info);
+		notifier_call_chain(&fb_notifier_list, FB_EVENT_SUSPEND, &event);
 		info->state = FBINFO_STATE_SUSPENDED;
 	} else {
 		info->state = FBINFO_STATE_RUNNING;
-		notifier_call_chain(&fb_notifier_list, FB_EVENT_RESUME, info);
+		notifier_call_chain(&fb_notifier_list, FB_EVENT_RESUME, &event);
 	}
 }
 
@@ -1495,11 +1276,9 @@
  *
  */
 
-void __init 
+int __init
 fbmem_init(void)
 {
-	int i;
-
 	create_proc_read_entry("fb", 0, NULL, fbmem_read_proc, NULL);
 
 	devfs_mk_dir("fb");
@@ -1511,26 +1290,53 @@
 		printk(KERN_WARNING "Unable to create fb class; errno = %ld\n", PTR_ERR(fb_class));
 		fb_class = NULL;
 	}
+	return 0;
+}
+module_init(fbmem_init);
+
+#define NR_FB_DRIVERS 64
+static char *video_options[NR_FB_DRIVERS];
+static int ofonly;
 
-#ifdef CONFIG_FB_OF
-	if (ofonly) {
-		offb_init();
-		return;
+/**
+ * fb_get_options - get kernel boot parameters
+ * @name - framebuffer name as it would appear in
+ *         the boot parameter line
+ *         (video=<name>:<options>)
+ *
+ * NOTE: Needed to maintain backwards compatibility
+ */
+int fb_get_options(char *name, char **option)
+{
+	char *opt, *options = NULL;
+	int opt_len, retval = 0;
+	int name_len = strlen(name), i;
+
+	if (name_len && ofonly && strncmp(name, "offb", 4))
+		retval = 1;
+
+	if (name_len && !retval) {
+		for (i = 0; i < NR_FB_DRIVERS; i++) {
+			if (video_options[i] == NULL)
+				continue;
+			opt_len = strlen(video_options[i]);
+			if (!opt_len)
+				continue;
+			opt = video_options[i];
+			if (!strncmp(name, opt, name_len) &&
+			    opt[name_len] == ':')
+				options = opt + name_len + 1;
+		}
 	}
-#endif
+	if (options && !strncmp(options, "off", 3))
+		retval = 1;
 
-	/*
-	 *  Probe for all builtin frame buffer devices
-	 */
-	for (i = 0; i < num_pref_init_funcs; i++)
-		pref_init_funcs[i]();
+	if (option)
+		*option = options;
 
-	for (i = 0; i < NUM_FB_DRIVERS; i++)
-		if (fb_drivers[i].init)
-			fb_drivers[i].init();
+	return retval;
 }
 
-
 /**
  *	video_setup - process command line options
  *	@options: string of options
@@ -1538,6 +1344,8 @@
  *	Process command line options for frame buffer subsystem.
  *
  *	NOTE: This function is a __setup and __init function.
+ *            It only stores the options.  Drivers have to call
+ *            fb_get_options() as necessary.
  *
  *	Returns zero.
  *
@@ -1545,48 +1353,22 @@
 
 int __init video_setup(char *options)
 {
-	int i, j;
+	int i;
 
 	if (!options || !*options)
 		return 0;
-	   
-#ifdef CONFIG_FB_OF
-	if (!strcmp(options, "ofonly")) {
-		ofonly = 1;
-		return 0;
-	}
-#endif
-
-	if (num_pref_init_funcs == FB_MAX)
-		return 0;
 
-	for (i = 0; i < NUM_FB_DRIVERS; i++) {
-		j = strlen(fb_drivers[i].name);
-		if (!strncmp(options, fb_drivers[i].name, j) &&
-			options[j] == ':') {
-			if (!strcmp(options+j+1, "off"))
-				fb_drivers[i].init = NULL;
-			else {
-				if (fb_drivers[i].init) {
-					pref_init_funcs[num_pref_init_funcs++] =
-						fb_drivers[i].init;
-					fb_drivers[i].init = NULL;
-				}
-				if (fb_drivers[i].setup)
-					fb_drivers[i].setup(options+j+1);
-			}
-			return 0;
+	for (i = 0; i < NR_FB_DRIVERS; i++) {
+		if (!strncmp(options, "ofonly", 6))
+			ofonly = 1;
+		if (video_options[i] == NULL) {
+			video_options[i] = options;
+			break;
 		}
 	}
 
-	/*
-	 * If we get here no fb was specified.
-	 * We consider the argument to be a global video mode option.
-	 */
-	global_mode_option = options;
 	return 0;
 }
-
 __setup("video=", video_setup);
 
     /*
@@ -1611,5 +1393,6 @@
 EXPORT_SYMBOL(fb_set_suspend);
 EXPORT_SYMBOL(fb_register_client);
 EXPORT_SYMBOL(fb_unregister_client);
+EXPORT_SYMBOL(fb_get_options);
 
 MODULE_LICENSE("GPL");
diff -Nru a/drivers/video/fbmon.c b/drivers/video/fbmon.c
--- a/drivers/video/fbmon.c	2004-10-18 14:57:03 -07:00
+++ b/drivers/video/fbmon.c	2004-10-18 14:57:03 -07:00
@@ -49,6 +49,22 @@
 #define DPRINTK(fmt, args...)
 #endif
 
+#define FBMON_FIX_HEADER 1
+
+#ifdef CONFIG_FB_MODE_HELPERS
+struct broken_edid {
+	u8  manufacturer[4];
+	u32 model;
+	u32 fix;
+};
+
+static struct broken_edid brokendb[] = {
+	/* DEC FR-PCXAV-YZ */
+	{ .manufacturer = "DEC",
+	  .model        = 0x073a,
+	  .fix          = FBMON_FIX_HEADER,
+	},
+};
 
 const unsigned char edid_v1_header[] = { 0x00, 0xff, 0xff, 0xff,
 	0xff, 0xff, 0xff, 0x00
@@ -65,30 +81,77 @@
   while (i-- && (*--s == 0x20)) *s = 0;
 }
 
+static void fix_broken_edid(unsigned char *edid)
+{
+	unsigned char *block = edid + ID_MANUFACTURER_NAME, manufacturer[4];
+	u32 model, i;
+
+	manufacturer[0] = ((block[0] & 0x7c) >> 2) + '@';
+	manufacturer[1] = ((block[0] & 0x03) << 3) +
+		((block[1] & 0xe0) >> 5) + '@';
+	manufacturer[2] = (block[1] & 0x1f) + '@';
+	manufacturer[3] = 0;
+	model = block[2] + (block[3] << 8);
+
+	for (i = 0; i < ARRAY_SIZE(brokendb); i++) {
+		if (!strncmp(manufacturer, brokendb[i].manufacturer, 4) &&
+			brokendb[i].model == model) {
+			switch (brokendb[i].fix) {
+			case FBMON_FIX_HEADER:
+				printk("fbmon: The EDID header of "
+				       "Manufacturer: %s Model: 0x%x is "
+				       "known to be broken,\n"
+				       "fbmon: trying a header "
+				       "reconstruct\n", manufacturer, model);
+				memcpy(edid, edid_v1_header, 8);
+				break;
+			}
+		}
+	}
+}
+
 static int edid_checksum(unsigned char *edid)
 {
-	unsigned char i, csum = 0;
+	unsigned char i, csum = 0, all_null = 0;
 
-	for (i = 0; i < EDID_LENGTH; i++)
+	for (i = 0; i < EDID_LENGTH; i++) {
 		csum += edid[i];
+		all_null |= edid[i];
+	}
 
-	if (csum == 0x00) {
+	if (csum == 0x00 && all_null) {
 		/* checksum passed, everything's good */
 		return 1;
-	} else {
+	}
+
+	fix_broken_edid(edid);
+	csum = all_null = 0;
+	for (i = 0; i < EDID_LENGTH; i++) {
+		csum += edid[i];
+		all_null |= edid[i];
+	}
+	if (csum != 0x00 || !all_null) {
 		printk("EDID checksum failed, aborting\n");
 		return 0;
 	}
+	return 1;
 }
 
 static int edid_check_header(unsigned char *edid)
 {
-	if ((edid[0] != 0x00) || (edid[1] != 0xff) || (edid[2] != 0xff) ||
-	    (edid[3] != 0xff) || (edid[4] != 0xff) || (edid[5] != 0xff) ||
-	    (edid[6] != 0xff)) {
-		printk
-		    ("EDID header doesn't match EDID v1 header, aborting\n");
-		return 0;
+	int i, fix = 0;
+
+	for (i = 0; i < 8; i++) {
+		if (edid[i] != edid_v1_header[i])
+			fix = 1;
+	}
+	if (!fix)
+		return 1;
+
+	fix_broken_edid(edid);
+	for (i = 0; i < 8; i++) {
+		if (edid[i] != edid_v1_header[i])
+			return 0;
 	}
 	return 1;
 }
@@ -1094,6 +1157,36 @@
 	
 	return 0;
 }
+#else
+int fb_parse_edid(unsigned char *edid, struct fb_var_screeninfo *var)
+{
+	return 1;
+}
+void fb_edid_to_monspecs(unsigned char *edid, struct fb_monspecs *specs)
+{
+	specs = NULL;
+}
+char *get_EDID_from_firmware(struct device *dev)
+{
+	return NULL;
+}
+struct fb_videomode *fb_create_modedb(unsigned char *edid, int *dbsize)
+{
+	return NULL;
+}
+void fb_destroy_modedb(struct fb_videomode *modedb)
+{
+}
+int fb_get_monitor_limits(unsigned char *edid, struct fb_monspecs *specs)
+{
+	return 1;
+}
+int fb_get_mode(int flags, u32 val, struct fb_var_screeninfo *var,
+		struct fb_info *info)
+{
+	return -EINVAL;
+}
+#endif /* CONFIG_FB_MODE_HELPERS */
 	
 /*
  * fb_validate_mode - validates var against monitor capabilities
diff -Nru a/drivers/video/ffb.c b/drivers/video/ffb.c
--- a/drivers/video/ffb.c	2004-10-18 14:57:19 -07:00
+++ b/drivers/video/ffb.c	2004-10-18 14:57:19 -07:00
@@ -362,61 +362,6 @@
 	struct list_head	list;
 };
 
-#undef FFB_DO_DEBUG_LOG
-
-#ifdef FFB_DO_DEBUG_LOG
-#define FFB_DEBUG_LOG_ENTS	32
-static struct ffb_log {
-	int op;
-#define OP_FILLRECT	1
-#define OP_IMAGEBLIT	2
-
-	int depth, x, y, w, h;
-} ffb_debug_log[FFB_DEBUG_LOG_ENTS];
-static int ffb_debug_log_ent;
-
-static void ffb_do_log(unsigned long unused)
-{
-	int i;
-
-	for (i = 0; i < FFB_DEBUG_LOG_ENTS; i++) {
-		struct ffb_log *p = &ffb_debug_log[i];
-
-		printk("FFB_LOG: OP[%s] depth(%d) x(%d) y(%d) w(%d) h(%d)\n",
-		       (p->op == OP_FILLRECT ? "FILLRECT" : "IMAGEBLIT"),
-		       p->depth, p->x, p->y, p->w, p->h);
-	}
-}
-static struct timer_list ffb_log_timer =
-	TIMER_INITIALIZER(ffb_do_log, 0, 0);
-
-static void ffb_log(int op, int depth, int x, int y, int w, int h)
-{
-	if (ffb_debug_log_ent < FFB_DEBUG_LOG_ENTS) {
-		struct ffb_log *p = &ffb_debug_log[ffb_debug_log_ent];
-
-		if (ffb_debug_log_ent != 0 &&
-		    p[-1].op == op && p[-1].depth == depth)
-			return;
-		p->op = op;
-		p->depth = depth;
-		p->x = x;
-		p->y = y;
-		p->w = w;
-		p->h = h;
-
-		if (++ffb_debug_log_ent == FFB_DEBUG_LOG_ENTS) {
-			ffb_log_timer.expires = jiffies + 2;
-			add_timer(&ffb_log_timer);
-		}
-	}
-}
-#else
-#define ffb_log(a,b,c,d,e,f)	do { } while(0)
-#endif
-
-#undef FORCE_WAIT_EVERY_ROP
-
 static void FFBFifo(struct ffb_par *par, int n)
 {
 	struct ffb_fbc *fbc;
@@ -479,7 +424,7 @@
 	upa_writel(0x2000707f, &fbc->fbc);
 	upa_writel(par->rop_cache, &fbc->rop);
 	upa_writel(0xffffffff, &fbc->pmask);
-	upa_writel((0 << 16) | (32 << 0), &fbc->fontinc);
+	upa_writel((1 << 16) | (0 << 0), &fbc->fontinc);
 	upa_writel(par->fg_cache, &fbc->fg);
 	upa_writel(par->bg_cache, &fbc->bg);
 	FFBWait(par);
@@ -526,8 +471,6 @@
 	if (rect->rop != ROP_COPY && rect->rop != ROP_XOR)
 		BUG();
 
-	ffb_log(OP_FILLRECT, 0, rect->dx, rect->dy, rect->width, rect->height);
-
 	fg = ((u32 *)info->pseudo_palette)[rect->color];
 
 	spin_lock_irqsave(&par->lock, flags);
@@ -548,9 +491,6 @@
 	upa_writel(rect->dx, &fbc->bx);
 	upa_writel(rect->height, &fbc->bh);
 	upa_writel(rect->width, &fbc->bw);
-#ifdef FORCE_WAIT_EVERY_ROP
-	FFBWait(par);
-#endif
 
 	spin_unlock_irqrestore(&par->lock, flags);
 }
@@ -572,7 +512,7 @@
 	unsigned long flags;
 
 	if (area->dx != area->sx ||
-	    area->dy == area->dy) {
+	    area->dy == area->sy) {
 		cfb_copyarea(info, area);
 		return;
 	}
@@ -609,10 +549,7 @@
 	unsigned long flags;
 	u32 fg, bg, xy;
 	u64 fgbg;
-	int i, width;
-
-	ffb_log(OP_IMAGEBLIT, image->depth,
-		image->dx, image->dy, image->width, image->height);
+	int i, width, stride;
 
 	if (image->depth > 1) {
 		cfb_imageblit(info, image);
@@ -623,6 +560,8 @@
 	bg = ((u32 *)info->pseudo_palette)[image->bg_color];
 	fgbg = ((u64) fg << 32) | (u64) bg;
 	xy = (image->dy << 16) | image->dx;
+	width = image->width;
+	stride = ((width + 7) >> 3);
 
 	spin_lock_irqsave(&par->lock, flags);
 
@@ -632,55 +571,49 @@
 		*(u64 *)&par->fg_cache = fgbg;
 	}
 
-	ffb_rop(par, FFB_ROP_NEW);
+	if (width >= 32) {
+		FFBFifo(par, 1);
+		upa_writel(32, &fbc->fontw);
+	}
 
-	for (i = 0; i < image->height; i++) {
-		width = image->width;
+	while (width >= 32) {
+		const u8 *next_data = data + 4;
 
 		FFBFifo(par, 1);
 		upa_writel(xy, &fbc->fontxy);
-		xy += (1 << 16);
-
-		while (width >= 32) {
-			u32 val;
+		xy += (32 << 0);
 
-			FFBFifo(par, 2);
-			upa_writel(32, &fbc->fontw);
-
-			val = ((u32)data[0] << 24) |
-			      ((u32)data[1] << 16) |
-			      ((u32)data[2] <<  8) |
-			      ((u32)data[3] <<  0);
+		for (i = 0; i < image->height; i++) {
+			u32 val = (((u32)data[0] << 24) |
+				   ((u32)data[1] << 16) |
+				   ((u32)data[2] <<  8) |
+				   ((u32)data[3] <<  0));
+			FFBFifo(par, 1);
 			upa_writel(val, &fbc->font);
 
-			data += 4;
-			width -= 32;
+			data += stride;
 		}
 
-		if (width) {
-			u32 val;
+		data = next_data;
+		width -= 32;
+	}
 
-			FFBFifo(par, 2);
-			upa_writel(width, &fbc->fontw);
-			if (width <= 8) {
-				val = (u32) data[0] << 24;
-				data += 1;
-			} else if (width <= 16) {
-				val = ((u32) data[0] << 24) |
-				      ((u32) data[1] << 16);
-				data += 2;
-			} else {
-				val = ((u32) data[0] << 24) |
-				      ((u32) data[1] << 16) |
-				      ((u32) data[2] <<  8);
-				data += 3;
-			}
+	if (width) {
+		FFBFifo(par, 2);
+		upa_writel(width, &fbc->fontw);
+		upa_writel(xy, &fbc->fontxy);
+
+		for (i = 0; i < image->height; i++) {
+			u32 val = (((u32)data[0] << 24) |
+				   ((u32)data[1] << 16) |
+				   ((u32)data[2] <<  8) |
+				   ((u32)data[3] <<  0));
+			FFBFifo(par, 1);
 			upa_writel(val, &fbc->font);
+
+			data += stride;
 		}
 	}
-#ifdef FORCE_WAIT_EVERY_ROP
-	FFBWait(par);
-#endif
 
 	spin_unlock_irqrestore(&par->lock, flags);
 }
@@ -1027,7 +960,13 @@
 	all->par.prom_node = node;
 	all->par.prom_parent_node = parent;
 
-	all->info.flags = FBINFO_FLAG_DEFAULT;
+	/* Don't mention copyarea, so SCROLL_REDRAW is always
+	 * used.  It is the fastest on this chip.
+	 */
+	all->info.flags = (FBINFO_DEFAULT |
+			   /* FBINFO_HWACCEL_COPYAREA | */
+			   FBINFO_HWACCEL_FILLRECT |
+			   FBINFO_HWACCEL_IMAGEBLIT);
 	all->info.fbops = &ffb_ops;
 	all->info.screen_base = (char *) all->par.physbase + FFB_DFB24_POFF;
 	all->info.currcon = -1;
@@ -1110,6 +1049,9 @@
 {
 	int root;
 
+	if (fb_get_options("ffb", NULL))
+		return -ENODEV;
+
 	ffb_scan_siblings(prom_root_node);
 
 	root = prom_getchild(prom_root_node);
@@ -1140,8 +1082,9 @@
 	return 0;
 }
 
-#ifdef MODULE
 module_init(ffb_init);
+
+#ifdef MODULE
 module_exit(ffb_exit);
 #endif
 
diff -Nru a/drivers/video/fm2fb.c b/drivers/video/fm2fb.c
--- a/drivers/video/fm2fb.c	2004-10-18 14:56:28 -07:00
+++ b/drivers/video/fm2fb.c	2004-10-18 14:56:28 -07:00
@@ -280,7 +280,7 @@
 	info->pseudo_palette = info->par;
 	info->par = NULL;
 	info->fix = fb_fix;
-	info->flags = FBINFO_FLAG_DEFAULT;
+	info->flags = FBINFO_DEFAULT;
 
 	if (register_framebuffer(info) < 0) {
 		fb_dealloc_cmap(&info->cmap);
@@ -292,12 +292,18 @@
 	return 0;
 }
 
+int __init fm2fb_setup(char *options);
+
 int __init fm2fb_init(void)
 {
+	char *option = NULL;
+
+	if (fb_get_options("fm2fb", &option))
+		return -ENODEV;
+	fm2fb_setup(option);
 	return zorro_register_driver(&fm2fb_driver);
 }
 
-int __init fm2fb_setup(char *options)
 {
 	char *this_opt;
 
@@ -313,4 +319,5 @@
 	return 0;
 }
 
+module_init(fm2fb_init);
 MODULE_LICENSE("GPL");
diff -Nru a/drivers/video/g364fb.c b/drivers/video/g364fb.c
--- a/drivers/video/g364fb.c	2004-10-18 14:55:54 -07:00
+++ b/drivers/video/g364fb.c	2004-10-18 14:55:54 -07:00
@@ -202,6 +202,9 @@
 	    (volatile unsigned int *) CURS_PAL_REG;
 	int mem, i, j;
 
+	if (fb_get_options("g364fb", NULL))
+		return -ENODEV;
+
 	/* TBD: G364 detection */
 
 	/* get the resolution set by ARC console */
@@ -241,7 +244,7 @@
 	fb_info.screen_base = (char *) G364_MEM_BASE;	/* virtual kernel address */
 	fb_info.var = fb_var;
 	fb_info.fix = fb_fix;
-	fb_info.flags = FBINFO_FLAG_DEFAULT;
+	fb_info.flags = FBINFO_DEFAULT | FBINFO_HWACCEL_YPAN;
 
 	fb_alloc_cmap(&fb_info.cmap, 255, 0);
 
@@ -250,4 +253,5 @@
 	return 0;
 }
 
+module_init(g364fb_init);
 MODULE_LICENSE("GPL");
diff -Nru a/drivers/video/gbefb.c b/drivers/video/gbefb.c
--- a/drivers/video/gbefb.c	2004-10-18 14:56:28 -07:00
+++ b/drivers/video/gbefb.c	2004-10-18 14:56:28 -07:00
@@ -1083,6 +1083,14 @@
 {
 	int i, ret = 0;
 
+#ifndef MODULE
+	char *option = NULL;
+
+	if (fb_get_options("gbefb", &option))
+		return -ENODEV;
+	gbefb_setup(options);
+#endif
+
 	if (!request_mem_region(GBE_BASE, sizeof(struct sgi_gbe), "GBE")) {
 		printk(KERN_ERR "gbefb: couldn't reserve mmio region\n");
 		return -EBUSY;
@@ -1135,7 +1143,7 @@
 	fb_info.currcon = -1;
 	fb_info.fbops = &gbefb_ops;
 	fb_info.pseudo_palette = pseudo_palette;
-	fb_info.flags = FBINFO_FLAG_DEFAULT;
+	fb_info.flags = FBINFO_DEFAULT;
 	fb_info.screen_base = gbe_mem;
 	fb_alloc_cmap(&fb_info.cmap, 256, 0);
 
@@ -1192,8 +1200,9 @@
 	iounmap(gbe);
 }
 
-#ifdef MODULE
 module_init(gbefb_init);
+
+#ifdef MODULE
 module_exit(gbefb_exit);
 #endif
 
diff -Nru a/drivers/video/hgafb.c b/drivers/video/hgafb.c
--- a/drivers/video/hgafb.c	2004-10-18 14:56:49 -07:00
+++ b/drivers/video/hgafb.c	2004-10-18 14:56:49 -07:00
@@ -547,6 +547,9 @@
 
 int __init hgafb_init(void)
 {
+	if (fb_get_options("hgafb", NULL))
+		return -ENODEV;
+
 	if (! hga_card_detect()) {
 		printk(KERN_INFO "hgafb: HGA card not detected.\n");
 		return -EINVAL;
@@ -558,7 +561,7 @@
 	hga_fix.smem_start = VGA_MAP_MEM(hga_vram_base);
 	hga_fix.smem_len = hga_vram_len;
 
-	fb_info.flags = FBINFO_FLAG_DEFAULT;
+	fb_info.flags = FBINFO_DEFAULT | FBINFO_HWACCEL_YPAN;
 	fb_info.var = hga_default_var;
 	fb_info.fix = hga_fix;
 	fb_info.monspecs.hfmin = 0;
@@ -609,8 +612,8 @@
 
 MODULE_PARM(nologo, "i");
 MODULE_PARM_DESC(nologo, "Disables startup logo if != 0 (default=0)");
+module_init(hgafb_init);
 
 #ifdef MODULE
-module_init(hgafb_init);
 module_exit(hgafb_exit);
 #endif
diff -Nru a/drivers/video/hitfb.c b/drivers/video/hitfb.c
--- a/drivers/video/hitfb.c	2004-10-18 14:55:55 -07:00
+++ b/drivers/video/hitfb.c	2004-10-18 14:55:55 -07:00
@@ -270,6 +270,9 @@
 	unsigned short lcdclor, ldr3, ldvndr;
 	int size;
 
+	if (fb_get_options("hitfb", NULL))
+		return -ENODEV;
+
 	hitfb_fix.smem_start = CONFIG_HD64461_IOBASE + 0x02000000;
 	hitfb_fix.smem_len = (MACH_HP690) ? 1024 * 1024 : 512 * 1024;
 
@@ -321,7 +324,7 @@
 	fb_info.var = hitfb_var;
 	fb_info.fix = hitfb_fix;
 	fb_info.pseudo_palette = pseudo_palette;
-	fb_info.flags = FBINFO_FLAG_DEFAULT;
+	fb_info.flags = FBINFO_DEFAULT | FBINFO_HWACCEL_YPAN;
 
 	fb_info.screen_base = (void *)hitfb_fix.smem_start;
 
@@ -341,8 +344,9 @@
 	unregister_framebuffer(&fb_info);
 }
 
-#ifdef MODULE
 module_init(hitfb_init);
+
+#ifdef MODULE
 module_exit(hitfb_exit);
 #endif
 
diff -Nru a/drivers/video/hpfb.c b/drivers/video/hpfb.c
--- a/drivers/video/hpfb.c	2004-10-18 14:56:32 -07:00
+++ b/drivers/video/hpfb.c	2004-10-18 14:56:32 -07:00
@@ -115,6 +115,9 @@
 {
 	unsigned long fboff;
 
+	if (fb_get_options("hpfb", NULL))
+		return -ENODEV;
+
 	fboff = (in_8(base + TOPCAT_FBOMSB) << 8) | in_8(base + TOPCAT_FBOLSB);
 
 	hpfb_fix.smem_start = 0xf0000000 | (in_8(base + fboff) << 16);
@@ -151,7 +154,7 @@
 	 *	Let there be consoles..
 	 */
 	fb_info.fbops = &hpfb_ops;
-	fb_info.flags = FBINFO_FLAG_DEFAULT;
+	fb_info.flags = FBINFO_DEFAULT;
 	fb_info.var   = hpfb_defined;
 	fb_info.fix   = hpfb_fix;
 	fb_info.screen_base = (char *)hpfb_fix.smem_start;	// FIXME
@@ -211,4 +214,5 @@
 	return 0;
 }
 
+module_init(hpfb_init);
 MODULE_LICENSE("GPL");
diff -Nru a/drivers/video/i810/i810_dvt.c b/drivers/video/i810/i810_dvt.c
--- a/drivers/video/i810/i810_dvt.c	2004-10-18 14:56:49 -07:00
+++ b/drivers/video/i810/i810_dvt.c	2004-10-18 14:56:49 -07:00
@@ -193,19 +193,19 @@
 
 void round_off_xres(u32 *xres) 
 {
-	if (*xres < 800) 
+	if (*xres <= 640)
 		*xres = 640;
-	if (*xres < 1024 && *xres >= 800) 
+	else if (*xres <= 800)
 		*xres = 800;
-	if (*xres < 1152 && *xres >= 1024)
+	else if (*xres <= 1024)
 		*xres = 1024;
-	if (*xres < 1280 && *xres >= 1152)
+	else if (*xres <= 1152)
 		*xres = 1152;
-	if (*xres < 1600 && *xres >= 1280)
+	else if (*xres <= 1280)
 		*xres = 1280;
-	if (*xres >= 1600)
+	else
 		*xres = 1600;
-}		
+}
 
 inline void round_off_yres(u32 *xres, u32 *yres)
 {
diff -Nru a/drivers/video/i810/i810_main.c b/drivers/video/i810/i810_main.c
--- a/drivers/video/i810/i810_main.c	2004-10-18 14:56:28 -07:00
+++ b/drivers/video/i810/i810_main.c	2004-10-18 14:56:28 -07:00
@@ -1353,11 +1353,15 @@
 
 	encode_fix(&info->fix, info);
 
-	if (info->var.accel_flags && !(par->dev_flags & LOCKUP)) 
+	if (info->var.accel_flags && !(par->dev_flags & LOCKUP)) {
+		info->flags = FBINFO_DEFAULT | FBINFO_HWACCEL_YPAN |
+		FBINFO_HWACCEL_COPYAREA | FBINFO_HWACCEL_FILLRECT |
+		FBINFO_HWACCEL_IMAGEBLIT;
 		info->pixmap.scan_align = 2;
-	else 
+	} else {
 		info->pixmap.scan_align = 1;
-	
+		info->flags = FBINFO_DEFAULT | FBINFO_HWACCEL_YPAN;
+	}
 	return 0;
 }
 
@@ -1388,16 +1392,17 @@
 {
 	struct i810fb_par *par = (struct i810fb_par *)info->par;
 	u8 *mmio = par->mmio_start_virtual;	
-	u8 data[64 * 8];
-	
+
 	if (!info->var.accel_flags || par->dev_flags & LOCKUP) 
 		return soft_cursor(info, cursor);
 
 	if (cursor->image.width > 64 || cursor->image.height > 64)
 		return -ENXIO;
 
-	if ((i810_readl(CURBASE, mmio) & 0xf) != par->cursor_heap.physical)
+	if ((i810_readl(CURBASE, mmio) & 0xf) != par->cursor_heap.physical) {
 		i810_init_cursor(par);
+		cursor->set |= FB_CUR_SETALL;
+	}
 
 	i810_enable_cursor(mmio, OFF);
 
@@ -1409,50 +1414,56 @@
 
 		info->cursor.image.dx = cursor->image.dx;
 		info->cursor.image.dy = cursor->image.dy;
-		
-		tmp = cursor->image.dx - info->var.xoffset;
-		tmp |= (cursor->image.dy - info->var.yoffset) << 16;
-	    
+		tmp = (info->cursor.image.dx - info->var.xoffset) & 0xffff;
+		tmp |= (info->cursor.image.dy - info->var.yoffset) << 16;
 		i810_writel(CURPOS, mmio, tmp);
 	}
 
 	if (cursor->set & FB_CUR_SETSIZE) {
+		i810_reset_cursor_image(par);
 		info->cursor.image.height = cursor->image.height;
 		info->cursor.image.width = cursor->image.width;
-		i810_reset_cursor_image(par);
 	}
 
 	if (cursor->set & FB_CUR_SETCMAP) {
-		info->cursor.image.fg_color = cursor->image.fg_color;
-		info->cursor.image.bg_color = cursor->image.bg_color;
 		i810_load_cursor_colors(cursor->image.fg_color,
 					cursor->image.bg_color,
 					info);
+		info->cursor.image.fg_color = cursor->image.fg_color;
+		info->cursor.image.bg_color = cursor->image.bg_color;
+
 	}
 
-	if (cursor->set & FB_CUR_SETSHAPE) {
+	if (cursor->set & (FB_CUR_SETSHAPE)) {
 		int size = ((info->cursor.image.width + 7) >> 3) * 
-			     info->cursor.image.height;
+			info->cursor.image.height;
 		int i;
+		u8 *data = kmalloc(64 * 8, GFP_KERNEL);
+
+		if (data == NULL)
+			return -ENOMEM;
+		info->cursor.image.data = cursor->image.data;
 
 		switch (info->cursor.rop) {
 		case ROP_XOR:
 			for (i = 0; i < size; i++)
-				data[i] = cursor->image.data[i] ^ info->cursor.mask[i]; 
+				data[i] = info->cursor.image.data[i] ^ info->cursor.mask[i];
 			break;
 		case ROP_COPY:
 		default:
 			for (i = 0; i < size; i++)
-				data[i] = cursor->image.data[i] & info->cursor.mask[i]; 
+				data[i] = info->cursor.image.data[i] & info->cursor.mask[i];
 			break;
 		}
 		i810_load_cursor_image(info->cursor.image.width, 
 				       info->cursor.image.height, data,
 				       par);
+		kfree(data);
 	}
 
 	if (info->cursor.enable)
 		i810_enable_cursor(mmio, ON);
+
 	return 0;
 }
 
@@ -1641,9 +1652,11 @@
 		hsync1 = HFMIN;
 	if (!hsync2) 
 		hsync2 = HFMAX;
-	info->monspecs.hfmax = hsync2;
-	info->monspecs.hfmin = hsync1;
-	if (hsync2 < hsync1) 
+	if (!info->monspecs.hfmax)
+		info->monspecs.hfmax = hsync2;
+	if (!info->monspecs.hfmin)
+		info->monspecs.hfmin = hsync1;
+	if (hsync2 < hsync1)
 		info->monspecs.hfmin = hsync2;
 
 	if (!vsync1)
@@ -1652,8 +1665,10 @@
 		vsync2 = VFMAX;
 	if (IS_DVT && vsync1 < 60)
 		vsync1 = 60;
-	info->monspecs.vfmax = vsync2;
-	info->monspecs.vfmin = vsync1;		
+	if (!info->monspecs.vfmax)
+		info->monspecs.vfmax = vsync2;
+	if (!info->monspecs.vfmin)
+		info->monspecs.vfmin = vsync1;
 	if (vsync2 < vsync1) 
 		info->monspecs.vfmin = vsync2;
 }
@@ -1724,6 +1739,7 @@
 	pci_read_config_byte(par->dev, 0x50, &reg);
 	reg &= FREQ_MASK;
 	par->mem_freq = (reg) ? 133 : 100;
+
 }
 
 static int __devinit 
@@ -1836,8 +1852,9 @@
 {
 	struct fb_info    *info;
 	struct i810fb_par *par = NULL;
-	int err, vfreq, hfreq, pixclock;
+	int i, err = -1, vfreq, hfreq, pixclock;
 
+	i = 0;
 	if (!(info = kmalloc(sizeof(struct fb_info), GFP_KERNEL))) {
 		i810fb_release_resource(info, par);
 		return -ENOMEM;
@@ -1879,8 +1896,6 @@
 	info->screen_base = par->fb.virtual;
 	info->fbops = &par->i810fb_ops;
 	info->pseudo_palette = par->pseudo_palette;
-	info->flags = FBINFO_FLAG_DEFAULT;
-	
 	fb_alloc_cmap(&info->cmap, 256, 0);
 
 	if ((err = info->fbops->fb_check_var(&info->var, info))) {
@@ -1957,8 +1972,7 @@
 
 		kfree(par);
 	}
-	if (info) 
-		kfree(info);
+	kfree(info);
 }
 
 static void __exit i810fb_remove_pci(struct pci_dev *dev)
@@ -1975,10 +1989,11 @@
 #ifndef MODULE
 int __init i810fb_init(void)
 {
-	if (agp_intel_init()) {
-		printk("i810fb_init: cannot initialize intel agpgart\n");
+	char *option = NULL;
+
+	if (fb_get_options("i810fb", &option))
 		return -ENODEV;
-	}
+	i810fb_setup(option);
 
 	if (pci_register_driver(&i810fb_driver) > 0)
 		return 0;
@@ -2054,9 +2069,8 @@
 {
 	pci_unregister_driver(&i810fb_driver);
 }
-module_init(i810fb_init);
 module_exit(i810fb_exit);
 
 #endif /* MODULE */
 
-
+module_init(i810fb_init);
diff -Nru a/drivers/video/igafb.c b/drivers/video/igafb.c
--- a/drivers/video/igafb.c	2004-10-18 14:56:32 -07:00
+++ b/drivers/video/igafb.c	2004-10-18 14:56:32 -07:00
@@ -357,7 +357,7 @@
                 video_cmap_len = 256;
 
 	info->fbops = &igafb_ops;
-	info->flags = FBINFO_FLAG_DEFAULT;
+	info->flags = FBINFO_DEFAULT;
 
 	fb_alloc_cmap(&info->cmap, video_cmap_len, 0);
 
@@ -381,6 +381,9 @@
 	unsigned long addr;
 	int size, iga2000 = 0;
 
+	if (fb_get_options("igafb", NULL))
+		return -ENODEV;
+
         /* Do not attach when we have a serial console. */
         if (!con_is_present())
                 return -ENXIO;
@@ -572,4 +575,5 @@
     return 0;
 }
 
+module_init(igafb_init);
 MODULE_LICENSE("GPL");
diff -Nru a/drivers/video/imsttfb.c b/drivers/video/imsttfb.c
--- a/drivers/video/imsttfb.c	2004-10-18 14:56:31 -07:00
+++ b/drivers/video/imsttfb.c	2004-10-18 14:56:31 -07:00
@@ -1442,7 +1442,10 @@
 	info->var.pixclock = 1000000 / getclkMHz(par);
 
 	info->fbops = &imsttfb_ops;
-	info->flags = FBINFO_FLAG_DEFAULT;
+	info->flags = FBINFO_DEFAULT |
+                      FBINFO_HWACCEL_COPYAREA |
+	              FBINFO_HWACCEL_FILLRECT |
+	              FBINFO_HWACCEL_YPAN;
 
 	fb_alloc_cmap(&info->cmap, 0, 0);
 
@@ -1599,6 +1602,14 @@
 
 int __init imsttfb_init(void)
 {
+#ifndef MODULE
+	char *option = NULL;
+
+	if (fb_get_options("imsttfb", &option))
+		return -ENODEV;
+
+	imsttfb_setup(option);
+#endif
 	return pci_module_init(&imsttfb_pci_driver);
 }
  
@@ -1609,7 +1620,7 @@
 
 #ifdef MODULE
 MODULE_LICENSE("GPL");
-module_init(imsttfb_init);
 #endif
+module_init(imsttfb_init);
 module_exit(imsttfb_exit);
 
diff -Nru a/drivers/video/kyro/fbdev.c b/drivers/video/kyro/fbdev.c
--- a/drivers/video/kyro/fbdev.c	2004-10-18 14:55:54 -07:00
+++ b/drivers/video/kyro/fbdev.c	2004-10-18 14:55:54 -07:00
@@ -712,7 +712,7 @@
 	info->fix		= kyro_fix;
 	info->par		= currentpar;
 	info->pseudo_palette	= (void *)(currentpar + 1);
-	info->flags		= FBINFO_FLAG_DEFAULT;
+	info->flags		= FBINFO_DEFAULT;
 
 	SetCoreClockPLL(deviceInfo.pSTGReg, pdev);
 
@@ -787,6 +787,13 @@
 
 int __init kyrofb_init(void)
 {
+#ifndef MODULE
+	char *option = NULL;
+
+	if (fb_get_options("kyrofb", &option))
+		return -ENODEV;
+	kyrofb_setup(option);
+#endif
 	return pci_module_init(&kyrofb_pci_driver);
 }
 
@@ -795,8 +802,9 @@
 	pci_unregister_driver(&kyrofb_pci_driver);
 }
 
-#ifdef MODULE
 module_init(kyrofb_init);
+
+#ifdef MODULE
 module_exit(kyrofb_exit);
 #endif
 
diff -Nru a/drivers/video/leo.c b/drivers/video/leo.c
--- a/drivers/video/leo.c	2004-10-18 14:56:50 -07:00
+++ b/drivers/video/leo.c	2004-10-18 14:56:50 -07:00
@@ -588,7 +588,7 @@
 		sbus_ioremap(&sdev->resource[0], LEO_OFF_LX_CURSOR,
 			     sizeof(struct leo_cursor), "leolx cursor");
 
-	all->info.flags = FBINFO_FLAG_DEFAULT;
+	all->info.flags = FBINFO_DEFAULT | FBINFO_HWACCEL_YPAN;
 	all->info.fbops = &leo_ops;
 	all->info.currcon = -1;
 	all->info.par = &all->par;
@@ -626,6 +626,9 @@
 	struct sbus_bus *sbus;
 	struct sbus_dev *sdev;
 
+	if (fb_get_options("leofb", NULL))
+		return -ENODEV;
+
 	for_all_sbusdev(sdev, sbus) {
 		if (!strcmp(sdev->prom_name, "leo"))
 			leo_init_one(sdev);
@@ -654,8 +657,8 @@
 	return 0;
 }
 
-#ifdef MODULE
 module_init(leo_init);
+#ifdef MODULE
 module_exit(leo_exit);
 #endif
 
diff -Nru a/drivers/video/macfb.c b/drivers/video/macfb.c
--- a/drivers/video/macfb.c	2004-10-18 14:55:55 -07:00
+++ b/drivers/video/macfb.c	2004-10-18 14:55:55 -07:00
@@ -614,6 +614,11 @@
 {
 	int video_cmap_len, video_is_nubus = 0;
 	struct nubus_dev* ndev = NULL;
+	char *option = NULL;
+
+	if (fb_get_options("macfb", &option))
+		return -ENODEV;
+	macfb_setup(option);
 
 	if (!MACH_IS_MAC) 
 		return;
@@ -660,6 +665,9 @@
 	case 1:
 		/* XXX: I think this will catch any program that tries
 		   to do FBIO_PUTCMAP when the visual is monochrome */
+		macfb_defined.red.length = macfb_defined.bits_per_pixel;
+		macfb_defined.green.length = macfb_defined.bits_per_pixel;
+		macfb_defined.blue.length = macfb_defined.bits_per_pixel;
 		video_cmap_len = 0;
 		macfb_fix.visual = FB_VISUAL_MONO01;
 		break;
@@ -947,7 +955,7 @@
 	fb_info.var		= macfb_defined;
 	fb_info.fix		= macfb_fix;
 	fb_info.pseudo_palette	= pseudo_palette;
-	fb_info.flags		= FBINFO_FLAG_DEFAULT;
+	fb_info.flags		= FBINFO_DEFAULT;
 
 	fb_alloc_cmap(&fb_info.cmap, video_cmap_len, 0);
 	
@@ -958,4 +966,5 @@
 	       fb_info.node, fb_info.fix.id);
 }
 
+module_init(macfb_init);
 MODULE_LICENSE("GPL");
diff -Nru a/drivers/video/matrox/matroxfb_base.c b/drivers/video/matrox/matroxfb_base.c
--- a/drivers/video/matrox/matroxfb_base.c	2004-10-18 14:56:48 -07:00
+++ b/drivers/video/matrox/matroxfb_base.c	2004-10-18 14:56:48 -07:00
@@ -2415,8 +2415,14 @@
 
 int __init matroxfb_init(void)
 {
+	char *option = NULL;
+
 	DBG(__FUNCTION__)
 
+	if (fb_get_options("matroxfb", &option))
+		return -ENODEV;
+	matroxfb_setup(option);
+
 	if (disabled)
 		return -ENXIO;
 	if (!initialized) {
@@ -2427,6 +2433,8 @@
 	/* never return failure, user can hotplug matrox later... */
 	return 0;
 }
+
+module_init(matroxfb_init);
 
 #else
 
diff -Nru a/drivers/video/matrox/matroxfb_base.h b/drivers/video/matrox/matroxfb_base.h
--- a/drivers/video/matrox/matroxfb_base.h	2004-10-18 14:56:32 -07:00
+++ b/drivers/video/matrox/matroxfb_base.h	2004-10-18 14:56:32 -07:00
@@ -99,21 +99,16 @@
 #endif
 #endif
 
-#if defined(__alpha__) || defined(__mc68000__)
+#if defined(__alpha__) || defined(__mc68000__) || defined(__i386__) || defined(__x86_64__)
 #define READx_WORKS
 #define MEMCPYTOIO_WORKS
 #else
+/* ppc/ppc64 must use __raw_{read,write}[bwl] as we drive adapter 
+   in big-endian mode for compatibility with XFree mga driver, and
+   so we do not want little-endian {read,write}[bwl] */
 #define READx_FAILS
-/* recheck __ppc__, maybe that __ppc__ needs MEMCPYTOIO_WRITEL */
-/* I benchmarked PII/350MHz with G200... MEMCPY, MEMCPYTOIO and WRITEL are on same speed ( <2% diff) */
-/* so that means that G200 speed (or AGP speed?) is our limit... I do not have benchmark to test, how */
-/* much of PCI bandwidth is used during transfers... */
-#if defined(__i386__) || defined(__x86_64__)
-#define MEMCPYTOIO_MEMCPY
-#else
 #define MEMCPYTOIO_WRITEL
 #endif
-#endif
 
 #if defined(__mc68000__)
 #define MAP_BUSTOVIRT
@@ -160,7 +155,7 @@
 #endif
 
 typedef struct {
-	u_int8_t*	vaddr;
+	u_int8_t __iomem*	vaddr;
 } vaddr_t;
 
 #ifdef READx_WORKS
@@ -189,27 +184,27 @@
 }
 #else
 static inline unsigned int mga_readb(vaddr_t va, unsigned int offs) {
-	return *(volatile u_int8_t*)(va.vaddr + offs);
+	return __raw_readb(va.vaddr + offs);
 }
 
 static inline unsigned int mga_readw(vaddr_t va, unsigned int offs) {
-	return *(volatile u_int16_t*)(va.vaddr + offs);
+	return __raw_readw(va.vaddr + offs);
 }
 
 static inline u_int32_t mga_readl(vaddr_t va, unsigned int offs) {
-	return *(volatile u_int32_t*)(va.vaddr + offs);
+	return __raw_readl(va.vaddr + offs);
 }
 
 static inline void mga_writeb(vaddr_t va, unsigned int offs, u_int8_t value) {
-	*(volatile u_int8_t*)(va.vaddr + offs) = value;
+	__raw_writeb(value, va.vaddr + offs);
 }
 
 static inline void mga_writew(vaddr_t va, unsigned int offs, u_int16_t value) {
-	*(volatile u_int16_t*)(va.vaddr + offs) = value;
+	__raw_writew(value, va.vaddr + offs);
 }
 
 static inline void mga_writel(vaddr_t va, unsigned int offs, u_int32_t value) {
-	*(volatile u_int32_t*)(va.vaddr + offs) = value;
+	__raw_writel(value, va.vaddr + offs);
 }
 #endif
 
@@ -238,8 +233,6 @@
 		memcpy(&tmp, src, len);
 		mga_writel(va, offs, tmp);
 	}
-#elif defined(MEMCPYTOIO_MEMCPY)
-	memcpy(va.vaddr + offs, src, len);
 #else
 #error "Sorry, do not know how to write block of data to device"
 #endif
@@ -249,7 +242,7 @@
 	va->vaddr += offs;
 }
 
-static inline void* vaddr_va(vaddr_t va) {
+static inline void __iomem* vaddr_va(vaddr_t va) {
 	return va.vaddr;
 }
 
diff -Nru a/drivers/video/matrox/matroxfb_crtc2.c b/drivers/video/matrox/matroxfb_crtc2.c
--- a/drivers/video/matrox/matroxfb_crtc2.c	2004-10-18 14:56:50 -07:00
+++ b/drivers/video/matrox/matroxfb_crtc2.c	2004-10-18 14:56:50 -07:00
@@ -721,6 +721,9 @@
 		.remove =	matroxfb_crtc2_remove };
 
 static int matroxfb_crtc2_init(void) {
+	if (fb_get_options("matrox_crtc2fb", NULL))
+		return -ENODEV;
+
 	matroxfb_register_driver(&crtc2);
 	return 0;
 }
diff -Nru a/drivers/video/matrox/matroxfb_crtc2.h b/drivers/video/matrox/matroxfb_crtc2.h
--- a/drivers/video/matrox/matroxfb_crtc2.h	2004-10-18 14:56:13 -07:00
+++ b/drivers/video/matrox/matroxfb_crtc2.h	2004-10-18 14:56:13 -07:00
@@ -27,7 +27,7 @@
 		unsigned int	len;
 			      } mmio;
 
-	int			interlaced:1;
+	unsigned int		interlaced:1;
 
 	u_int32_t cmap[17];
 };
diff -Nru a/drivers/video/matrox/matroxfb_misc.c b/drivers/video/matrox/matroxfb_misc.c
--- a/drivers/video/matrox/matroxfb_misc.c	2004-10-18 14:56:33 -07:00
+++ b/drivers/video/matrox/matroxfb_misc.c	2004-10-18 14:56:33 -07:00
@@ -391,7 +391,7 @@
 	CRITEND
 }
 
-static void get_pins(unsigned char* pins, struct matrox_bios* bd) {
+static void get_pins(unsigned char __iomem* pins, struct matrox_bios* bd) {
 	unsigned int b0 = readb(pins);
 	
 	if (b0 == 0x2E && readb(pins+1) == 0x41) {
@@ -427,7 +427,7 @@
 	}
 }
 
-static void get_bios_version(unsigned char* vbios, struct matrox_bios* bd) {
+static void get_bios_version(unsigned char __iomem * vbios, struct matrox_bios* bd) {
 	unsigned int pcir_offset;
 	
 	pcir_offset = readb(vbios + 24) | (readb(vbios + 25) << 8);
@@ -452,7 +452,7 @@
 	}
 }
 
-static void get_bios_output(unsigned char* vbios, struct matrox_bios* bd) {
+static void get_bios_output(unsigned char __iomem* vbios, struct matrox_bios* bd) {
 	unsigned char b;
 	
 	b = readb(vbios + 0x7FF1);
@@ -462,7 +462,7 @@
 	bd->output.state = b;
 }
 
-static void get_bios_tvout(unsigned char* vbios, struct matrox_bios* bd) {
+static void get_bios_tvout(unsigned char __iomem* vbios, struct matrox_bios* bd) {
 	unsigned int i;
 	
 	/* Check for 'IBM .*(V....TVO' string - it means TVO BIOS */
@@ -489,7 +489,7 @@
 	}
 }
 
-static void parse_bios(unsigned char* vbios, struct matrox_bios* bd) {
+static void parse_bios(unsigned char __iomem* vbios, struct matrox_bios* bd) {
 	unsigned int pins_offset;
 	
 	if (readb(vbios) != 0x55 || readb(vbios + 1) != 0xAA) {
@@ -738,7 +738,7 @@
 	pci_write_config_dword(pdev, PCI_OPTION_REG, opt);
 #ifdef CONFIG_X86
 	if (!ACCESS_FBINFO(bios).bios_valid) {
-		unsigned char* b;
+		unsigned char __iomem* b;
 
 		b = ioremap(0x000C0000, 65536);
 		if (!b) {
diff -Nru a/drivers/video/maxinefb.c b/drivers/video/maxinefb.c
--- a/drivers/video/maxinefb.c	2004-10-18 14:56:27 -07:00
+++ b/drivers/video/maxinefb.c	2004-10-18 14:56:27 -07:00
@@ -126,6 +126,9 @@
 	unsigned long fb_start;
 	int i;
 
+	if (fb_get_options("maxinefb", NULL))
+		return -ENODEV;
+
 	/* Validate we're on the proper machine type */
 	if (mips_machtype != MACH_DS5000_XX) {
 		return -EINVAL;
@@ -159,7 +162,7 @@
 	fb_info.screen_base = (char *) maxinefb_fix.smem_start;
 	fb_info.var = maxinefb_defined;
 	fb_info.fix = maxinefb_fix;
-	fb_info.flags = FBINFO_FLAG_DEFAULT;
+	fb_info.flags = FBINFO_DEFAULT;
 
 	fb_alloc_cmap(&fb_info.cmap, 256, 0);
 
@@ -175,7 +178,7 @@
 
 #ifdef MODULE
 MODULE_LICENSE("GPL");
-module_init(maxinefb_init);
 #endif
+module_init(maxinefb_init);
 module_exit(maxinefb_exit);
 
diff -Nru a/drivers/video/modedb.c b/drivers/video/modedb.c
--- a/drivers/video/modedb.c	2004-10-18 14:56:29 -07:00
+++ b/drivers/video/modedb.c	2004-10-18 14:56:29 -07:00
@@ -39,7 +39,7 @@
 
 #define DEFAULT_MODEDB_INDEX	0
 
-static const struct fb_videomode modedb[] = {
+static const __init struct fb_videomode modedb[] = {
     {
 	/* 640x400 @ 70 Hz, 31.5 kHz hsync */
 	NULL, 70, 640, 400, 39721, 40, 24, 39, 9, 96, 2,
@@ -251,6 +251,7 @@
     },
 };
 
+#ifdef CONFIG_FB_MODE_HELPERS
 const struct fb_videomode vesa_modes[] = {
 	/* 0 640x350-85 VESA */
 	{ NULL, 85, 640, 350, 31746,  96, 32, 60, 32, 64, 3,
@@ -374,6 +375,8 @@
 	{ NULL, 60, 1920, 1440, 3367, 352, 144, 56, 1, 224, 3,
 	  FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
 };
+EXPORT_SYMBOL(vesa_modes);
+#endif /* CONFIG_FB_MODE_HELPERS */
 
 static int my_atoi(const char *name)
 {
@@ -404,7 +407,7 @@
  */
 
 int fb_try_mode(struct fb_var_screeninfo *var, struct fb_info *info,
-		  const struct fb_videomode *mode, unsigned int bpp)
+		const struct fb_videomode *mode, unsigned int bpp)
 {
     int err = 0;
 
@@ -570,5 +573,261 @@
     return 0;
 }
 
-EXPORT_SYMBOL(vesa_modes);
+/**
+ * fb_var_to_videomode - convert fb_var_screeninfo to fb_videomode
+ * @mode: pointer to struct fb_videomode
+ * @var: pointer to struct fb_var_screeninfo
+ */
+void fb_var_to_videomode(struct fb_videomode *mode,
+			 struct fb_var_screeninfo *var)
+{
+	u32 pixclock, hfreq, htotal, vtotal;
+
+	mode->name = NULL;
+	mode->xres = var->xres;
+	mode->yres = var->yres;
+	mode->pixclock = var->pixclock;
+	mode->hsync_len = var->hsync_len;
+	mode->vsync_len = var->vsync_len;
+	mode->left_margin = var->left_margin;
+	mode->right_margin = var->right_margin;
+	mode->upper_margin = var->upper_margin;
+	mode->lower_margin = var->lower_margin;
+	mode->sync = var->sync;
+	mode->vmode = var->vmode & FB_VMODE_MASK;
+	mode->flag = FB_MODE_IS_FROM_VAR;
+	if (!var->pixclock)
+		return;
+
+	pixclock = PICOS2KHZ(var->pixclock) * 1000;
+
+	htotal = var->xres + var->right_margin + var->hsync_len +
+		var->left_margin;
+	vtotal = var->yres + var->lower_margin + var->vsync_len +
+		var->upper_margin;
+
+	if (var->vmode & FB_VMODE_INTERLACED)
+		vtotal /= 2;
+	if (var->vmode & FB_VMODE_DOUBLE)
+		vtotal *= 2;
+
+	hfreq = pixclock/htotal;
+	mode->refresh = hfreq/vtotal;
+}
+
+/**
+ * fb_videomode_to_var - convert fb_videomode to fb_var_screeninfo
+ * @var: pointer to struct fb_var_screeninfo
+ * @mode: pointer to struct fb_videomode
+ */
+void fb_videomode_to_var(struct fb_var_screeninfo *var,
+			       struct fb_videomode *mode)
+{
+	var->xres = mode->xres;
+	var->yres = mode->yres;
+	var->pixclock = mode->pixclock;
+	var->left_margin = mode->left_margin;
+	var->hsync_len = mode->hsync_len;
+	var->vsync_len = mode->vsync_len;
+	var->right_margin = mode->right_margin;
+	var->upper_margin = mode->upper_margin;
+	var->lower_margin = mode->lower_margin;
+	var->sync = mode->sync;
+	var->vmode = mode->vmode & FB_VMODE_MASK;
+}
+
+/**
+ * fb_mode_is_equal - compare 2 videomodes
+ * @mode1: first videomode
+ * @mode2: second videomode
+ *
+ * RETURNS:
+ * 1 if equal, 0 if not
+ */
+int fb_mode_is_equal(struct fb_videomode *mode1,
+		     struct fb_videomode *mode2)
+{
+	return (mode1->xres         == mode2->xres &&
+		mode1->yres         == mode2->yres &&
+		mode1->pixclock     == mode2->pixclock &&
+		mode1->hsync_len    == mode2->hsync_len &&
+		mode1->vsync_len    == mode2->vsync_len &&
+		mode1->left_margin  == mode2->left_margin &&
+		mode1->right_margin == mode2->right_margin &&
+		mode1->upper_margin == mode2->upper_margin &&
+		mode1->lower_margin == mode2->lower_margin &&
+		mode1->sync         == mode2->sync &&
+		mode1->vmode        == mode2->vmode);
+}
+
+/**
+ * fb_find_best_mode - find best matching videomode
+ * @var: pointer to struct fb_var_screeninfo
+ * @head: pointer to struct list_head of modelist
+ *
+ * RETURNS:
+ * struct fb_videomode, NULL if none found
+ *
+ * IMPORTANT:
+ * This function assumes that all modelist entries in
+ * info->modelist are valid.
+ *
+ * NOTES:
+ * Finds best matching videomode which has an equal or greater dimension than
+ * var->xres and var->yres.  If more than 1 videomode is found, will return
+ * the videomode with the highest refresh rate
+ */
+struct fb_videomode *fb_find_best_mode(struct fb_var_screeninfo *var,
+				       struct list_head *head)
+{
+	struct list_head *pos;
+	struct fb_modelist *modelist;
+	struct fb_videomode *mode, *best = NULL;
+	u32 diff = -1;
+
+	list_for_each(pos, head) {
+		u32 d;
+
+		modelist = list_entry(pos, struct fb_modelist, list);
+		mode = &modelist->mode;
+
+		if (mode->xres >= var->xres && mode->yres >= var->yres) {
+			d = (mode->xres - var->xres) +
+				(mode->yres - var->yres);
+			if (diff > d) {
+				diff = d;
+				best = mode;
+			} else if (diff == d && mode->refresh > best->refresh)
+			    best = mode;
+		}
+	}
+	return best;
+}
+
+/**
+ * fb_match_mode - find a videomode which exactly matches the timings in var
+ * @var: pointer to struct fb_var_screeninfo
+ * @head: pointer to struct list_head of modelist
+ *
+ * RETURNS:
+ * struct fb_videomode, NULL if none found
+ */
+struct fb_videomode *fb_match_mode(struct fb_var_screeninfo *var,
+				   struct list_head *head)
+{
+	struct list_head *pos;
+	struct fb_modelist *modelist;
+	struct fb_videomode *m, mode;
+
+	fb_var_to_videomode(&mode, var);
+	list_for_each(pos, head) {
+		modelist = list_entry(pos, struct fb_modelist, list);
+		m = &modelist->mode;
+		if (fb_mode_is_equal(m, &mode))
+			return m;
+	}
+	return NULL;
+}
+
+/**
+ * fb_add_videomode: adds videomode entry to modelist
+ * @mode: videomode to add
+ * @head: struct list_head of modelist
+ *
+ * NOTES:
+ * Will only add unmatched mode entries
+ */
+int fb_add_videomode(struct fb_videomode *mode, struct list_head *head)
+{
+	struct list_head *pos;
+	struct fb_modelist *modelist;
+	struct fb_videomode *m;
+	int found = 0;
+
+	list_for_each(pos, head) {
+		modelist = list_entry(pos, struct fb_modelist, list);
+		m = &modelist->mode;
+		if (fb_mode_is_equal(m, mode)) {
+			found = 1;
+			break;
+		}
+	}
+	if (!found) {
+		modelist = kmalloc(sizeof(struct fb_modelist),
+						  GFP_KERNEL);
+
+		if (!modelist)
+			return -ENOMEM;
+		modelist->mode = *mode;
+		list_add(&modelist->list, head);
+	}
+	return 0;
+}
+
+/**
+ * fb_delete_videomode: removed videomode entry from modelist
+ * @mode: videomode to remove
+ * @head: struct list_head of modelist
+ *
+ * NOTES:
+ * Will remove all matching mode entries
+ */
+void fb_delete_videomode(struct fb_videomode *mode, struct list_head *head)
+{
+	struct list_head *pos, *n;
+	struct fb_modelist *modelist;
+	struct fb_videomode *m;
+
+	list_for_each_safe(pos, n, head) {
+		modelist = list_entry(pos, struct fb_modelist, list);
+		m = &modelist->mode;
+		if (fb_mode_is_equal(m, mode)) {
+			list_del(pos);
+			kfree(pos);
+		}
+	}
+}
+
+/**
+ * fb_destroy_modelist: destroy modelist
+ * @head: struct list_head of modelist
+ */
+void fb_destroy_modelist(struct list_head *head)
+{
+	struct list_head *pos, *n;
+
+	list_for_each_safe(pos, n, head) {
+		list_del(pos);
+		kfree(pos);
+	}
+}
+
+/**
+ * fb_videomode_to_modelist: convert mode array to mode list
+ * @modedb: array of struct fb_videomode
+ * @num: number of entries in array
+ * @head: struct list_head of modelist
+ */
+void fb_videomode_to_modelist(struct fb_videomode *modedb, int num,
+			      struct list_head *head)
+{
+	int i;
+
+	INIT_LIST_HEAD(head);
+
+	for (i = 0; i < num; i++) {
+		if (fb_add_videomode(&modedb[i], head))
+			return;
+	}
+}
+
+EXPORT_SYMBOL(fb_videomode_to_var);
+EXPORT_SYMBOL(fb_var_to_videomode);
+EXPORT_SYMBOL(fb_mode_is_equal);
+EXPORT_SYMBOL(fb_add_videomode);
+EXPORT_SYMBOL(fb_delete_videomode);
+EXPORT_SYMBOL(fb_destroy_modelist);
+EXPORT_SYMBOL(fb_match_mode);
+EXPORT_SYMBOL(fb_find_best_mode);
+EXPORT_SYMBOL(fb_videomode_to_modelist);
 EXPORT_SYMBOL(fb_find_mode);
diff -Nru a/drivers/video/neofb.c b/drivers/video/neofb.c
--- a/drivers/video/neofb.c	2004-10-18 14:56:33 -07:00
+++ b/drivers/video/neofb.c	2004-10-18 14:56:33 -07:00
@@ -93,7 +93,7 @@
 static int libretto;
 static int nostretch;
 static int nopciburst;
-
+static char *mode_option __initdata = NULL;
 
 #ifdef MODULE
 
@@ -111,6 +111,8 @@
 		 "Disable stretching of modes smaller than LCD.");
 MODULE_PARM(nopciburst, "i");
 MODULE_PARM_DESC(nopciburst, "Disable PCI burst mode.");
+MODULE_PARM(mode_option, "s");
+MODULE_PARM_DESC(mode_option, "Preferred video mode ('640x480-8@60', etc)");
 
 #endif
 
@@ -544,6 +546,10 @@
 		bltMod = NEO_MODE1_DEPTH16;
 		pitch = var->xres_virtual * 2;
 		break;
+	case 24:
+		bltMod = NEO_MODE1_DEPTH24;
+		pitch = var->xres_virtual * 3;
+		break;
 	default:
 		printk(KERN_ERR
 		       "neofb: neo2200_accel_init: unexpected bits per pixel!\n");
@@ -562,7 +568,7 @@
 	struct neofb_par *par = (struct neofb_par *) info->par;
 	int cnt = atomic_read(&par->ref_count);
 
-	if (cnt) {
+	if (!cnt) {
 		memset(&par->state, 0, sizeof(struct vgastate));
 		par->state.flags = VGA_SAVE_MODE | VGA_SAVE_FONTS;
 		save_vga(&par->state);
@@ -695,6 +701,7 @@
 		var->green.offset = 8;
 		var->green.length = 8;
 		var->blue.offset = 0;
+		var->blue.length = 8;
 		break;
 
 #ifdef NO_32BIT_SUPPORT_YET
@@ -994,41 +1001,6 @@
 	/* Since we program the clocks ourselves, always use VCLK3. */
 	par->MiscOutReg |= 0x0C;
 
-	/* linear colormap for non palettized modes */
-	switch (info->var.bits_per_pixel) {
-	case 8:
-		/* PseudoColor, 256 */
-		info->fix.visual = FB_VISUAL_PSEUDOCOLOR;
-		break;
-	case 16:
-		/* DirectColor, 64k */
-		info->fix.visual = FB_VISUAL_DIRECTCOLOR;
-
-		for (i = 0; i < 64; i++) {
-			outb(i, 0x3c8);
-
-			outb(i << 1, 0x3c9);
-			outb(i, 0x3c9);
-			outb(i << 1, 0x3c9);
-		}
-		break;
-	case 24:
-#ifdef NO_32BIT_SUPPORT_YET
-	case 32:
-#endif
-		/* TrueColor, 16m */
-		info->fix.visual = FB_VISUAL_TRUECOLOR;
-
-		for (i = 0; i < 256; i++) {
-			outb(i, 0x3c8);
-
-			outb(i, 0x3c9);
-			outb(i, 0x3c9);
-			outb(i, 0x3c9);
-		}
-		break;
-	}
-
 	/* alread unlocked above */
 	/* BOGUS  vga_wgfx(NULL, 0x09, 0x26); */
 
@@ -1090,6 +1062,41 @@
 	 * This function handles restoring the generic VGA registers.  */
 	vgaHWRestore(info, par);
 
+	/* linear colormap for non palettized modes */
+	switch (info->var.bits_per_pixel) {
+	case 8:
+		/* PseudoColor, 256 */
+		info->fix.visual = FB_VISUAL_PSEUDOCOLOR;
+		break;
+	case 16:
+		/* TrueColor, 64k */
+		info->fix.visual = FB_VISUAL_TRUECOLOR;
+
+		for (i = 0; i < 64; i++) {
+			outb(i, 0x3c8);
+
+			outb(i << 1, 0x3c9);
+			outb(i, 0x3c9);
+			outb(i << 1, 0x3c9);
+		}
+		break;
+	case 24:
+#ifdef NO_32BIT_SUPPORT_YET
+	case 32:
+#endif
+		/* TrueColor, 16m */
+		info->fix.visual = FB_VISUAL_TRUECOLOR;
+
+		for (i = 0; i < 256; i++) {
+			outb(i, 0x3c8);
+
+			outb(i, 0x3c9);
+			outb(i, 0x3c9);
+			outb(i, 0x3c9);
+		}
+		break;
+	}
+
 	vga_wgfx(NULL, 0x0E, par->ExtCRTDispAddr);
 	vga_wgfx(NULL, 0x0F, par->ExtCRTOffset);
 	temp = vga_rgfx(NULL, 0x10);
@@ -1276,7 +1283,7 @@
 static int neofb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
 			   u_int transp, struct fb_info *fb)
 {
-	if (regno >= 255)
+	if (regno >= fb->cmap.len || regno > 255)
 		return -EINVAL;
 
 	switch (fb->var.bits_per_pixel) {
@@ -1288,25 +1295,20 @@
 		outb(blue >> 10, 0x3c9);
 		break;
 	case 16:
-		if (regno < 16)
-			((u16 *) fb->pseudo_palette)[regno] =
-			    ((red & 0xf800)) | ((green & 0xfc00) >> 5) |
-			    ((blue & 0xf800) >> 11);
+		((u32 *) fb->pseudo_palette)[regno] =
+				((red & 0xf800)) | ((green & 0xfc00) >> 5) |
+				((blue & 0xf800) >> 11);
 		break;
 	case 24:
-		if (regno < 16)
-			((u32 *) fb->pseudo_palette)[regno] =
-			    ((red & 0xff00) << 8) | ((green & 0xff00)) |
-			    ((blue & 0xff00) >> 8);
+		((u32 *) fb->pseudo_palette)[regno] =
+				((red & 0xff00) << 8) | ((green & 0xff00)) |
+				((blue & 0xff00) >> 8);
 		break;
 #ifdef NO_32BIT_SUPPORT_YET
 	case 32:
-		if (regno < 16)
-			((u32 *) fb->pseudo_palette)[regno] =
-			    ((transp & 0xff00) << 16) | ((red & 0xff00) <<
-							 8) | ((green &
-								0xff00)) |
-			    ((blue & 0xff00) >> 8);
+		((u32 *) fb->pseudo_palette)[regno] =
+				((transp & 0xff00) << 16) | ((red & 0xff00) << 8) |
+				((green & 0xff00)) | ((blue & 0xff00) >> 8);
 		break;
 #endif
 	default:
@@ -1318,27 +1320,33 @@
 /*
  *    (Un)Blank the display.
  */
-static int neofb_blank(int blank, struct fb_info *info)
+int neofb_blank(int blank_mode, struct fb_info *info)
 {
 	/*
-	 *  Blank the screen if blank_mode != 0, else unblank. If
-	 *  blank == NULL then the caller blanks by setting the CLUT
-	 *  (Color Look Up Table) to all black. Return 0 if blanking
-	 *  succeeded, != 0 if un-/blanking failed due to e.g. a
-	 *  video mode which doesn't support it. Implements VESA
-	 *  suspend and powerdown modes on hardware that supports
-	 *  disabling hsync/vsync:
-	 *    blank_mode == 2: suspend vsync
-	 *    blank_mode == 3: suspend hsync
-	 *    blank_mode == 4: powerdown
+	 *  Blank the screen if blank_mode != 0, else unblank.
+	 *  Return 0 if blanking succeeded, != 0 if un-/blanking failed due to
+	 *  e.g. a video mode which doesn't support it. Implements VESA suspend
+	 *  and powerdown modes for monitors, and backlight control on LCDs.
+	 *    blank_mode == 0: unblanked (backlight on)
+	 *    blank_mode == 1: blank (backlight on)
+	 *    blank_mode == 2: suspend vsync (backlight off)
+	 *    blank_mode == 3: suspend hsync (backlight off)
+	 *    blank_mode == 4: powerdown (backlight off)
 	 *
-	 *  wms...Enable VESA DMPS compatible powerdown mode
+	 *  wms...Enable VESA DPMS compatible powerdown mode
 	 *  run "setterm -powersave powerdown" to take advantage
 	 */
+	struct neofb_par *par = (struct neofb_par *)info->par;
+	int seqflags, lcdflags, dpmsflags, reg;
 
-	switch (blank) {
+	switch (blank_mode) {
 	case 4:		/* powerdown - both sync lines down */
+		seqflags = VGA_SR01_SCREEN_OFF; /* Disable sequencer */
+		lcdflags = 0;			/* LCD off */
+		dpmsflags = NEO_GR01_SUPPRESS_HSYNC |
+			    NEO_GR01_SUPPRESS_VSYNC;
 #ifdef CONFIG_TOSHIBA
+		/* Do we still need this ? */
 		/* attempt to turn off backlight on toshiba; also turns off external */
 		{
 			SMMRegisters regs;
@@ -1351,13 +1359,26 @@
 #endif
 		break;
 	case 3:		/* hsync off */
+		seqflags = VGA_SR01_SCREEN_OFF;	/* Disable sequencer */
+		lcdflags = 0;			/* LCD off */
+		dpmsflags = NEO_GR01_SUPPRESS_HSYNC;
 		break;
 	case 2:		/* vsync off */
-		break;
-	case 1:		/* just software blanking of screen */
-		break;
-	default:		/* case 0, or anything else: unblank */
+		seqflags = VGA_SR01_SCREEN_OFF;	/* Disable sequencer */
+		lcdflags = 0;			/* LCD off */
+		dpmsflags = NEO_GR01_SUPPRESS_VSYNC;
+		break;
+	case 1:		/* just blank screen (backlight stays on) */
+		seqflags = VGA_SR01_SCREEN_OFF;	/* Disable sequencer */
+		lcdflags = par->PanelDispCntlReg1 & 0x02; /* LCD normal */
+		dpmsflags = 0;			/* no hsync/vsync suppression */
+		break;
+	case 0:		/* unblank */
+		seqflags = 0;			/* Enable sequencer */
+		lcdflags = par->PanelDispCntlReg1 & 0x02; /* LCD normal */
+		dpmsflags = 0x00;	/* no hsync/vsync suppression */
 #ifdef CONFIG_TOSHIBA
+		/* Do we still need this ? */
 		/* attempt to re-enable backlight/external on toshiba */
 		{
 			SMMRegisters regs;
@@ -1369,7 +1390,19 @@
 		}
 #endif
 		break;
+	default:	/* Anything else we don't understand; return 1 to tell
+			 * fb_blank we didn't aactually do anything */
+		return 1;
 	}
+
+	neoUnlock();
+	reg = (vga_rseq(NULL, 0x01) & ~0x20) | seqflags;
+	vga_wseq(NULL, 0x01, reg);
+	reg = (vga_rgfx(NULL, 0x20) & ~0x02) | lcdflags;
+	vga_wgfx(NULL, 0x20, reg);
+	reg = (vga_rgfx(NULL, 0x01) & ~0xF0) | 0x80 | dpmsflags;
+	vga_wgfx(NULL, 0x01, reg);
+	neoLock(&par->state);
 	return 0;
 }
 
@@ -1396,8 +1429,9 @@
 		par->neo2200->fgColor = rect->color;
 		break;
 	case 16:
+	case 24:
 		par->neo2200->fgColor =
-		    ((u16 *) (info->pseudo_palette))[rect->color];
+		    ((u32 *) (info->pseudo_palette))[rect->color];
 		break;
 	}
 
@@ -1440,31 +1474,57 @@
 	    (area->height << 16) | (area->width & 0xffff);
 }
 
-/*
 static void
 neo2200_imageblit(struct fb_info *info, const struct fb_image *image)
 {
 	struct neofb_par *par = (struct neofb_par *) info->par;
+	int s_pitch = (image->width * image->depth + 7) >> 3;
+	int scan_align = info->pixmap.scan_align - 1;
+	int buf_align = info->pixmap.buf_align - 1;
+	int bltCntl_flags, d_pitch, data_len;
+
+	// The data is padded for the hardware
+	d_pitch = (s_pitch + scan_align) & ~scan_align;
+	data_len = ((d_pitch * image->height) + buf_align) & ~buf_align;
 
 	neo2200_sync(info);
 
+	if (image->depth == 1) {
+		if (info->var.bits_per_pixel == 24 && image->width < 16) {
+			/* FIXME. There is a bug with accelerated color-expanded
+			 * transfers in 24 bit mode if the image being transferred
+			 * is less than 16 bits wide. This is due to insufficient
+			 * padding when writing the image. We need to adjust
+			 * struct fb_pixmap. Not yet done. */
+			return cfb_imageblit(info, image);
+		}
+		bltCntl_flags = NEO_BC0_SRC_MONO;
+	} else if (image->depth == info->var.bits_per_pixel) {
+		bltCntl_flags = 0;
+	} else {
+		/* We don't currently support hardware acceleration if image
+		 * depth is different from display */
+		return cfb_imageblit(info, image);
+	}
+
 	switch (info->var.bits_per_pixel) {
 	case 8:
 		par->neo2200->fgColor = image->fg_color;
 		par->neo2200->bgColor = image->bg_color;
 		break;
 	case 16:
+	case 24:
 		par->neo2200->fgColor =
-		    ((u16 *) (info->pseudo_palette))[image->fg_color];
+		    ((u32 *) (info->pseudo_palette))[image->fg_color];
 		par->neo2200->bgColor =
-		    ((u16 *) (info->pseudo_palette))[image->bg_color];
+		    ((u32 *) (info->pseudo_palette))[image->bg_color];
 		break;
 	}
 
 	par->neo2200->bltCntl = NEO_BC0_SYS_TO_VID |
-	    NEO_BC0_SRC_MONO | NEO_BC3_SKIP_MAPPING |
-	    //                      NEO_BC3_DST_XY_ADDR |
-	    0x0c0000;
+		NEO_BC3_SKIP_MAPPING | bltCntl_flags |
+		// NEO_BC3_DST_XY_ADDR |
+		0x0c0000;
 
 	par->neo2200->srcStart = 0;
 //      par->neo2200->dstStart = (image->dy << 16) | (image->dx & 0xffff);
@@ -1474,10 +1534,8 @@
 	par->neo2200->xyExt =
 	    (image->height << 16) | (image->width & 0xffff);
 
-	memcpy(par->mmio_vbase + 0x100000, image->data,
-	       (image->width * image->height) >> 3);
+	memcpy(par->mmio_vbase + 0x100000, image->data, data_len);
 }
-*/
 
 static void
 neofb_fillrect(struct fb_info *info, const struct fb_fillrect *rect)
@@ -1514,23 +1572,18 @@
 static void
 neofb_imageblit(struct fb_info *info, const struct fb_image *image)
 {
-/*
-	if (image->depth == 1) {
-		switch (info->fix.accel) {
-			case FB_ACCEL_NEOMAGIC_NM2200:
-			case FB_ACCEL_NEOMAGIC_NM2230:
-			case FB_ACCEL_NEOMAGIC_NM2360:
-			case FB_ACCEL_NEOMAGIC_NM2380:
-				neo2200_imageblit(info, image);
-				break;
-			default:
-				cfb_imageblit(info, image);
-				break;
-		}
-	} else
-*/
-		cfb_imageblit(info, image);
-}	
+	switch (info->fix.accel) {
+		case FB_ACCEL_NEOMAGIC_NM2200:
+		case FB_ACCEL_NEOMAGIC_NM2230:
+		case FB_ACCEL_NEOMAGIC_NM2360:
+		case FB_ACCEL_NEOMAGIC_NM2380:
+			neo2200_imageblit(info, image);
+			break;
+		default:
+			cfb_imageblit(info, image);
+			break;
+	}
+}
 
 static int 
 neofb_sync(struct fb_info *info)
@@ -1623,48 +1676,9 @@
 
 /* --------------------------------------------------------------------- */
 
-static struct fb_var_screeninfo __devinitdata neofb_var640x480x8 = {
-	.accel_flags    = FB_ACCELF_TEXT,
-	.xres           = 640,
-	.yres           = 480,
-	.xres_virtual   = 640,
-	.yres_virtual   = 30000,
-	.bits_per_pixel = 8,
-	.pixclock       = 39722,
-	.left_margin    = 48,
-	.right_margin   = 16,
-	.upper_margin   = 33,
-	.lower_margin   = 10,
-	.hsync_len      = 96,
-	.vsync_len      = 2,
-	.vmode          = FB_VMODE_NONINTERLACED
-};
-
-static struct fb_var_screeninfo __devinitdata neofb_var800x600x8 = {
-	.accel_flags    = FB_ACCELF_TEXT,
-	.xres           = 800,
-	.yres           = 600,
-	.xres_virtual   = 800,
-	.yres_virtual   = 30000,
-	.bits_per_pixel = 8,
-	.pixclock       = 25000,
-	.left_margin    = 88,
-	.right_margin   = 40,
-	.upper_margin   = 23,
-	.lower_margin   = 1,
-	.hsync_len      = 128,
-	.vsync_len      = 4,
-	.sync           = FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
-	.vmode          = FB_VMODE_NONINTERLACED
-};
-
-static struct fb_var_screeninfo __devinitdata neofb_var800x480x8 = {
-	.accel_flags    = FB_ACCELF_TEXT,
+static struct fb_videomode __devinitdata mode800x480 = {
 	.xres           = 800,
 	.yres           = 480,
-	.xres_virtual   = 800,
-	.yres_virtual   = 30000,
-	.bits_per_pixel = 8,
 	.pixclock       = 25000,
 	.left_margin    = 88,
 	.right_margin   = 40,
@@ -1676,44 +1690,6 @@
 	.vmode          = FB_VMODE_NONINTERLACED
 };
 
-static struct fb_var_screeninfo __devinitdata neofb_var1024x768x8 = {
-	.accel_flags    = FB_ACCELF_TEXT,
-	.xres           = 1024,
-	.yres           = 768,
-	.xres_virtual   = 1024,
-	.yres_virtual   = 30000,
-	.bits_per_pixel = 8,
-	.pixclock       = 15385,
-	.left_margin    = 160,
-	.right_margin   = 24,
-	.upper_margin   = 29,
-	.lower_margin   = 3,
-	.hsync_len      = 136,
-	.vsync_len      = 6,
-	.sync           = FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
-	.vmode          = FB_VMODE_NONINTERLACED
-};
-
-#ifdef NOT_DONE
-static struct fb_var_screeninfo __devinitdata neofb_var1280x1024x8 = {
-	.accel_flags    = FB_ACCELF_TEXT,
-	.xres           = 1280,
-	.yres           = 1024,
-	.xres_virtual   = 1280,
-	.yres_virtual   = 30000,
-	.bits_per_pixel = 8,
-	.pixclock       = 9260,
-	.left_margin    = 248,
-	.right_margin   = 48,
-	.upper_margin   = 38,
-	.lower_margin   = 1,
-	.hsync_len      = 112,
-	.vsync_len      = 3,
-	.sync           = FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
-	.vmode          = FB_VMODE_NONINTERLACED
-};
-#endif
-
 static int __devinit neo_map_mmio(struct fb_info *info,
 				  struct pci_dev *dev)
 {
@@ -1803,11 +1779,15 @@
 
 static void neo_unmap_video(struct fb_info *info)
 {
+	DBG("neo_unmap_video");
+
 #ifdef CONFIG_MTRR
-	struct neofb_par *par = (struct neofb_par *) info->par;
+	{
+		struct neofb_par *par = (struct neofb_par *) info->par;
 
-	mtrr_del(par->mtrr, info->fix.smem_start,
-		 info->fix.smem_len);
+		mtrr_del(par->mtrr, info->fix.smem_start,
+			 info->fix.smem_len);
+	}
 #endif
 	iounmap(info->screen_base);
 	info->screen_base = NULL;
@@ -1816,32 +1796,17 @@
 			   info->fix.smem_len);
 }
 
-static int __devinit neo_init_hw(struct fb_info *info)
+static int __devinit neo_scan_monitor(struct fb_info *info)
 {
 	struct neofb_par *par = (struct neofb_par *) info->par;
 	unsigned char type, display;
-	int videoRam = 896;
-	int maxClock = 65000;
-	int CursorMem = 1024;
-	int CursorOff = 0x100;
-	int linearSize = 1024;
-	int maxWidth = 1024;
-	int maxHeight = 1024;
 	int w;
 
-	DBG("neo_init_hw");
-
-	neoUnlock();
-
-#if 0
-	printk(KERN_DEBUG "--- Neo extended register dump ---\n");
-	for (w = 0; w < 0x85; w++)
-		printk(KERN_DEBUG "CR %p: %p\n", (void *) w,
-		       (void *) vga_rcrt(NULL, w);
-	for (w = 0; w < 0xC7; w++)
-		printk(KERN_DEBUG "GR %p: %p\n", (void *) w,
-		       (void *) vga_rgfx(NULL, w));
-#endif
+	// Eventually we will have i2c support.
+	info->monspecs.modedb = kmalloc(sizeof(struct fb_videomode), GFP_KERNEL);
+	if (!info->monspecs.modedb)
+		return -ENOMEM;
+	info->monspecs.modedb_len = 1;
 
 	/* Determine the panel type */
 	vga_wgfx(NULL, 0x09, 0x26);
@@ -1860,26 +1825,34 @@
 	vga_wgfx(NULL, 0x09, 0x00);
 	switch ((w & 0x18) >> 3) {
 	case 0x00:
+		// 640x480@60
 		par->NeoPanelWidth = 640;
 		par->NeoPanelHeight = 480;
-		info->var = neofb_var640x480x8;
+		memcpy(info->monspecs.modedb, &vesa_modes[3], sizeof(struct fb_videomode));
 		break;
 	case 0x01:
 		par->NeoPanelWidth = 800;
-		par->NeoPanelHeight = par->libretto ? 480 : 600;
-		info->var = par->libretto ? neofb_var800x480x8 : neofb_var800x600x8;
+		if (par->libretto) {
+			par->NeoPanelHeight = 480;
+			memcpy(info->monspecs.modedb, &mode800x480, sizeof(struct fb_videomode));
+		} else {
+			// 800x600@60
+			par->NeoPanelHeight = 600;
+			memcpy(info->monspecs.modedb, &vesa_modes[8], sizeof(struct fb_videomode));
+		}
 		break;
 	case 0x02:
+		// 1024x768@60
 		par->NeoPanelWidth = 1024;
 		par->NeoPanelHeight = 768;
-		info->var = neofb_var1024x768x8;
+		memcpy(info->monspecs.modedb, &vesa_modes[13], sizeof(struct fb_videomode));
 		break;
 	case 0x03:
-		/* 1280x1024 panel support needs to be added */
+		/* 1280x1024@60 panel support needs to be added */
 #ifdef NOT_DONE
 		par->NeoPanelWidth = 1280;
 		par->NeoPanelHeight = 1024;
-		info->var = neofb_var1280x1024x8;
+		memcpy(info->monspecs.modedb, &vesa_modes[20], sizeof(struct fb_videomode));
 		break;
 #else
 		printk(KERN_ERR
@@ -1887,9 +1860,10 @@
 		return -1;
 #endif
 	default:
+		// 640x480@60
 		par->NeoPanelWidth = 640;
 		par->NeoPanelHeight = 480;
-		info->var = neofb_var640x480x8;
+		memcpy(info->monspecs.modedb, &vesa_modes[3], sizeof(struct fb_videomode));
 		break;
 	}
 
@@ -1898,7 +1872,33 @@
 	       par->NeoPanelHeight,
 	       (type & 0x02) ? "color" : "monochrome",
 	       (type & 0x10) ? "TFT" : "dual scan");
+	return 0;
+}
 
+static int __devinit neo_init_hw(struct fb_info *info)
+{
+	struct neofb_par *par = (struct neofb_par *) info->par;
+	int videoRam = 896;
+	int maxClock = 65000;
+	int CursorMem = 1024;
+	int CursorOff = 0x100;
+	int linearSize = 1024;
+	int maxWidth = 1024;
+	int maxHeight = 1024;
+
+	DBG("neo_init_hw");
+
+	neoUnlock();
+
+#if 0
+	printk(KERN_DEBUG "--- Neo extended register dump ---\n");
+	for (int w = 0; w < 0x85; w++)
+		printk(KERN_DEBUG "CR %p: %p\n", (void *) w,
+		       (void *) vga_rcrt(NULL, w);
+	for (int w = 0; w < 0xC7; w++)
+		printk(KERN_DEBUG "GR %p: %p\n", (void *) w,
+		       (void *) vga_rgfx(NULL, w));
+#endif
 	switch (info->fix.accel) {
 	case FB_ACCEL_NEOMAGIC_NM2070:
 		videoRam = 896;
@@ -2055,7 +2055,9 @@
 	info->fix.accel = id->driver_data;
 
 	info->fbops = &neofb_ops;
-	info->flags = FBINFO_FLAG_DEFAULT;
+	info->flags = FBINFO_DEFAULT | FBINFO_HWACCEL_YPAN |
+		FBINFO_HWACCEL_IMAGEBLIT | FBINFO_HWACCEL_COPYAREA |
+		FBINFO_HWACCEL_COPYAREA;
 	info->pseudo_palette = (void *) (par + 1);
 	return info;
 }
@@ -2078,8 +2080,7 @@
 {
 	struct fb_info *info;
 	u_int h_sync, v_sync;
-	int err;
-	int video_len;
+	int video_len, err;
 
 	DBG("neofb_probe");
 
@@ -2096,6 +2097,10 @@
 	if (err)
 		goto err_map_mmio;
 
+	err = neo_scan_monitor(info);
+	if (err)
+		goto err_scan_monitor;
+
 	video_len = neo_init_hw(info);
 	if (video_len < 0) {
 		err = video_len;
@@ -2106,8 +2111,11 @@
 	if (err)
 		goto err_init_hw;
 
-	if (neofb_check_var(&info->var, info))
+	if (!fb_find_mode(&info->var, info, mode_option, NULL, 0,
+			info->monspecs.modedb, 16)) {
+		printk(KERN_ERR "neofb: Unable to find usable video mode.\n");
 		goto err_map_video;
+	}
 
 	/*
 	 * Calculate the hsync and vsync frequencies.  Note that
@@ -2149,6 +2157,8 @@
 err_map_video:
 	neo_unmap_video(info);
 err_init_hw:
+	fb_destroy_modedb(info->monspecs.modedb);
+err_scan_monitor:
 	neo_unmap_mmio(info);
 err_map_mmio:
 	neo_free_fb_info(info);
@@ -2172,6 +2182,7 @@
 			       "neofb: danger danger!  Oopsen imminent!\n");
 
 		neo_unmap_video(info);
+		fb_destroy_modedb(info->monspecs.modedb);
 		neo_unmap_mmio(info);
 		neo_free_fb_info(info);
 
@@ -2240,31 +2251,39 @@
 
 		if (!strncmp(this_opt, "internal", 8))
 			internal = 1;
-		if (!strncmp(this_opt, "external", 8))
+		else if (!strncmp(this_opt, "external", 8))
 			external = 1;
-		if (!strncmp(this_opt, "nostretch", 9))
+		else if (!strncmp(this_opt, "nostretch", 9))
 			nostretch = 1;
-		if (!strncmp(this_opt, "nopciburst", 10))
+		else if (!strncmp(this_opt, "nopciburst", 10))
 			nopciburst = 1;
-		if (!strncmp(this_opt, "libretto", 8))
+		else if (!strncmp(this_opt, "libretto", 8))
 			libretto = 1;
+		else
+			mode_option = this_opt;
 	}
-
 	return 0;
 }
 
 int __init neofb_init(void)
 {
+#ifndef MODULE
+	char *option = NULL;
+
+	if (fb_get_options("neofb", &option))
+		return -ENODEV;
+	neofb_setup(option);
+#endif
 	return pci_register_driver(&neofb_driver);
 }
 
-#ifdef MODULE
+module_init(neofb_init);
 
+#ifdef MODULE
 static void __exit neofb_exit(void)
 {
 	pci_unregister_driver(&neofb_driver);
 }
 
-module_init(neofb_init);
 module_exit(neofb_exit);
 #endif				/* MODULE */
diff -Nru a/drivers/video/offb.c b/drivers/video/offb.c
--- a/drivers/video/offb.c	2004-10-18 14:57:04 -07:00
+++ b/drivers/video/offb.c	2004-10-18 14:57:04 -07:00
@@ -28,7 +28,8 @@
 #include <linux/ioport.h>
 #include <asm/io.h>
 #include <asm/prom.h>
-#ifdef CONFIG_BOOTX_TEXT
+
+#ifdef CONFIG_PPC32
 #include <asm/bootx.h>
 #endif
 
@@ -70,7 +71,7 @@
 			  u_int transp, struct fb_info *info);
 static int offb_blank(int blank, struct fb_info *info);
 
-#ifdef CONFIG_BOOTX_TEXT
+#ifdef CONFIG_PPC32
 extern boot_infos_t *boot_infos;
 #endif
 
@@ -245,18 +246,20 @@
 
 int __init offb_init(void)
 {
-	struct device_node *dp;
-	unsigned int dpy;
+	struct device_node *dp = NULL, *boot_disp = NULL;
 #if defined(CONFIG_BOOTX_TEXT) && defined(CONFIG_PPC32)
-	struct device_node *displays = find_type_devices("display");
 	struct device_node *macos_display = NULL;
+#endif
+	if (fb_get_options("offb", NULL))
+		return -ENODEV;
 
+#if defined(CONFIG_BOOTX_TEXT) && defined(CONFIG_PPC32)
 	/* If we're booted from BootX... */
-	if (prom_num_displays == 0 && boot_infos != 0) {
+	if (boot_infos != 0) {
 		unsigned long addr =
 		    (unsigned long) boot_infos->dispDeviceBase;
 		/* find the device node corresponding to the macos display */
-		for (dp = displays; dp != NULL; dp = dp->next) {
+		while ((dp = of_find_node_by_type(dp, "display"))) {
 			int i;
 			/*
 			 * Grrr...  It looks like the MacOS ATI driver
@@ -325,10 +328,19 @@
 	}
 #endif /* defined(CONFIG_BOOTX_TEXT) && defined(CONFIG_PPC32) */
 
-	for (dpy = 0; dpy < prom_num_displays; dpy++) {
-		if ((dp = find_path_device(prom_display_paths[dpy])))
+	for (dp = NULL; (dp = of_find_node_by_type(dp, "display"));) {
+		if (get_property(dp, "linux,opened", NULL) &&
+		    get_property(dp, "linux,boot-display", NULL)) {
+			boot_disp = dp;
 			offb_init_nodriver(dp);
+		}
 	}
+	for (dp = NULL; (dp = of_find_node_by_type(dp, "display"));) {
+		if (get_property(dp, "linux,opened", NULL) &&
+		    dp != boot_disp)
+			offb_init_nodriver(dp);
+	}
+
 	return 0;
 }
 
@@ -527,7 +539,7 @@
 	info->screen_base = ioremap(address, fix->smem_len);
 	info->par = par;
 	info->pseudo_palette = (void *) (info + 1);
-	info->flags = FBINFO_FLAG_DEFAULT;
+	info->flags = FBINFO_DEFAULT;
 
 	fb_alloc_cmap(&info->cmap, 256, 0);
 
@@ -541,4 +553,5 @@
 	       info->node, full_name);
 }
 
+module_init(offb_init);
 MODULE_LICENSE("GPL");
diff -Nru a/drivers/video/p9100.c b/drivers/video/p9100.c
--- a/drivers/video/p9100.c	2004-10-18 14:56:48 -07:00
+++ b/drivers/video/p9100.c	2004-10-18 14:56:48 -07:00
@@ -297,7 +297,7 @@
 		sbus_ioremap(&sdev->resource[0], 0,
 			     sizeof(struct p9100_regs), "p9100 regs");
 
-	all->info.flags = FBINFO_FLAG_DEFAULT;
+	all->info.flags = FBINFO_DEFAULT;
 	all->info.fbops = &p9100_ops;
 #ifdef CONFIG_SPARC32
 	all->info.screen_base = (char *)
@@ -340,6 +340,9 @@
 	struct sbus_bus *sbus;
 	struct sbus_dev *sdev;
 
+	if (fb_get_options("p9100fb", NULL))
+		return -ENODEV;
+
 	for_all_sbusdev(sdev, sbus) {
 		if (!strcmp(sdev->prom_name, "p9100"))
 			p9100_init_one(sdev);
@@ -368,8 +371,9 @@
 	return 0;
 }
 
-#ifdef MODULE
 module_init(p9100_init);
+
+#ifdef MODULE
 module_exit(p9100_exit);
 #endif
 
diff -Nru a/drivers/video/platinumfb.c b/drivers/video/platinumfb.c
--- a/drivers/video/platinumfb.c	2004-10-18 14:56:28 -07:00
+++ b/drivers/video/platinumfb.c	2004-10-18 14:56:28 -07:00
@@ -311,7 +311,7 @@
 	/* Fill fb_info */
 	info->fbops = &platinumfb_ops;
 	info->pseudo_palette = pinfo->pseudo_palette;
-        info->flags = FBINFO_FLAG_DEFAULT;
+        info->flags = FBINFO_DEFAULT;
 	info->screen_base = (char *) pinfo->frame_buffer + 0x20;
 
 	fb_alloc_cmap(&info->cmap, 256, 0);
@@ -667,6 +667,13 @@
 
 int __init platinumfb_init(void)
 {
+#ifndef MODULE
+	char *option = NULL;
+
+	if (fb_get_options("platinumfb", &option))
+		return -ENODEV;
+	platinumfb_setup(option);
+#endif
 	of_register_driver(&platinum_driver);
 
 	return 0;
@@ -679,8 +686,8 @@
 
 MODULE_LICENSE("GPL");
 MODULE_DESCRIPTION("framebuffer driver for Apple Platinum video");
+module_init(platinumfb_init);
 
 #ifdef MODULE
-module_init(platinumfb_init);
 module_exit(platinumfb_exit);
 #endif
diff -Nru a/drivers/video/pm2fb.c b/drivers/video/pm2fb.c
--- a/drivers/video/pm2fb.c	2004-10-18 14:57:05 -07:00
+++ b/drivers/video/pm2fb.c	2004-10-18 14:57:05 -07:00
@@ -1124,7 +1124,8 @@
 	info->fbops		= &pm2fb_ops;
 	info->fix		= pm2fb_fix; 	
 	info->pseudo_palette	= (void *)(default_par + 1); 
-	info->flags		= FBINFO_FLAG_DEFAULT;
+	info->flags		= FBINFO_DEFAULT |
+                                  FBINFO_HWACCEL_YPAN;
 
 #ifndef MODULE
 	if (!mode)
@@ -1214,8 +1215,18 @@
  *  Initialization
  */
 
+int __init pm2fb_setup(char *options);
+
 int __init pm2fb_init(void)
 {
+#ifndef MODULE
+	char *option = NULL;
+
+	if (fb_get_options("pm2fb", &option))
+		return -ENODEV;
+	pm2fb_setup(option);
+#endif
+
 	return pci_module_init(&pm2fb_driver);
 }
 
@@ -1265,9 +1276,7 @@
 
 
 
-#ifdef MODULE
 module_init(pm2fb_init);
-#endif 
 module_exit(pm2fb_exit);
 
 MODULE_PARM(mode,"s");
diff -Nru a/drivers/video/pmag-ba-fb.c b/drivers/video/pmag-ba-fb.c
--- a/drivers/video/pmag-ba-fb.c	2004-10-18 14:57:04 -07:00
+++ b/drivers/video/pmag-ba-fb.c	2004-10-18 14:57:04 -07:00
@@ -142,7 +142,7 @@
 	info->var = pmagbafb_defined;
 	info->fix = pmagbafb_fix; 
 	info->screen_base = pmagbafb_fix.smem_start;
-	info->flags = FBINFO_FLAG_DEFAULT;
+	info->flags = FBINFO_DEFAULT;
 
 	fb_alloc_cmap(&fb_info.cmap, 256, 0);
 	
@@ -160,6 +160,9 @@
 	int sid;
 	int found = 0;
 
+	if (fb_get_options("pmagbafb", NULL))
+		return -ENODEV;
+
 	if (TURBOCHANNEL) {
 		while ((sid = search_tc_card("PMAG-BA")) >= 0) {
 			found = 1;
@@ -172,4 +175,5 @@
 	}
 }
 
+module_init(pmagbafb_init);
 MODULE_LICENSE("GPL");
diff -Nru a/drivers/video/pmagb-b-fb.c b/drivers/video/pmagb-b-fb.c
--- a/drivers/video/pmagb-b-fb.c	2004-10-18 14:56:33 -07:00
+++ b/drivers/video/pmagb-b-fb.c	2004-10-18 14:56:33 -07:00
@@ -145,7 +145,7 @@
 	info->var = pmagbbfb_defined;
 	info->fix = pmagbbfb_fix;
 	info->screen_base = pmagbbfb_fix.smem_start; 
-	info->flags = FBINFO_FLAG_DEFAULT;
+	info->flags = FBINFO_DEFAULT;
 
 	fb_alloc_cmap(&fb_info.cmap, 256, 0);
 
@@ -163,6 +163,9 @@
 	int sid;
 	int found = 0;
 
+	if (fb_get_options("pmagbbfb", NULL))
+		return -ENODEV;
+
 	if (TURBOCHANNEL) {
 		while ((sid = search_tc_card("PMAGB-BA")) >= 0) {
 			found = 1;
@@ -175,4 +178,5 @@
 	}
 }
 
+module_init(pmagbbfb_init);
 MODULE_LICENSE("GPL");
diff -Nru a/drivers/video/pvr2fb.c b/drivers/video/pvr2fb.c
--- a/drivers/video/pvr2fb.c	2004-10-18 14:55:54 -07:00
+++ b/drivers/video/pvr2fb.c	2004-10-18 14:55:54 -07:00
@@ -795,7 +795,7 @@
 	fb_info->fix		= pvr2_fix;
 	fb_info->par		= currentpar;
 	fb_info->pseudo_palette	= (void *)(fb_info->par + 1);
-	fb_info->flags		= FBINFO_FLAG_DEFAULT;
+	fb_info->flags		= FBINFO_DEFAULT | FBINFO_HWACCEL_YPAN;
 
 	if (video_output == VO_VGA)
 		defmode = DEFMODE_VGA;
@@ -1057,6 +1057,13 @@
 	int i, ret = -ENODEV;
 	int size;
 
+#ifndef MODULE
+	char *option = NULL;
+
+	if (fb_get_options("pvr2fb", &option))
+		return -ENODEV;
+	pvr2fb_setup(option);
+#endif
 	size = sizeof(struct fb_info) + sizeof(struct pvr2fb_par) + 16 * sizeof(u32);
 
 	fb_info = kmalloc(size, GFP_KERNEL);
@@ -1108,9 +1115,7 @@
 	kfree(fb_info);
 }
 
-#ifdef MODULE
 module_init(pvr2fb_init);
-#endif
 module_exit(pvr2fb_exit);
 
 MODULE_AUTHOR("Paul Mundt <lethal@linux-sh.org>, M. R. Brown <mrbrown@0xd6.org>");
diff -Nru a/drivers/video/pxafb.c b/drivers/video/pxafb.c
--- a/drivers/video/pxafb.c	2004-10-18 14:56:28 -07:00
+++ b/drivers/video/pxafb.c	2004-10-18 14:56:28 -07:00
@@ -43,6 +43,7 @@
 #include <asm/io.h>
 #include <asm/irq.h>
 #include <asm/uaccess.h>
+#include <asm/arch/pxa-regs.h>
 #include <asm/arch/bitfield.h>
 #include <asm/arch/pxafb.h>
 
@@ -1040,7 +1041,7 @@
 	fbi->fb.var.vmode	= FB_VMODE_NONINTERLACED;
 
 	fbi->fb.fbops		= &pxafb_ops;
-	fbi->fb.flags		= FBINFO_FLAG_DEFAULT;
+	fbi->fb.flags		= FBINFO_DEFAULT;
 	fbi->fb.node		= -1;
 	fbi->fb.currcon		= -1;
 
@@ -1359,11 +1360,6 @@
 #endif
 };
 
-int __devinit pxafb_init(void)
-{
-	return driver_register(&pxafb_driver);
-}
-
 #ifndef MODULE
 int __devinit pxafb_setup(char *options)
 {
@@ -1373,12 +1369,25 @@
 	return 0;
 }
 #else
-module_init(pxafb_init);
 # ifdef CONFIG_FB_PXA_PARAMETERS
 module_param_string(options, g_options, sizeof(g_options), 0);
 MODULE_PARM_DESC(options, "LCD parameters (see Documentation/fb/pxafb.txt)");
 # endif
 #endif
+
+int __devinit pxafb_init(void)
+{
+#ifndef MODULE
+	char *option = NULL;
+
+	if (fb_get_options("pxafb", &option))
+		return -ENODEV;
+	pxafb_setup(option);
+#endif
+	return driver_register(&pxafb_driver);
+}
+
+module_init(pxafb_init);
 
 MODULE_DESCRIPTION("loadable framebuffer driver for PXA");
 MODULE_LICENSE("GPL");
diff -Nru a/drivers/video/q40fb.c b/drivers/video/q40fb.c
--- a/drivers/video/q40fb.c	2004-10-18 14:56:27 -07:00
+++ b/drivers/video/q40fb.c	2004-10-18 14:56:27 -07:00
@@ -105,7 +105,7 @@
 	info->var = q40fb_var;
 	info->fix = q40fb_fix;
 	info->fbops = &q40fb_ops;
-	info->flags = FBINFO_FLAG_DEFAULT;  /* not as module for now */
+	info->flags = FBINFO_DEFAULT;  /* not as module for now */
 	info->pseudo_palette = info->par;
 	info->par = NULL;
 	info->screen_base = (char *) q40fb_fix.smem_start;
@@ -143,6 +143,9 @@
 {
 	int ret = 0;
 
+	if (fb_get_options("q40fb", NULL))
+		return -ENODEV;
+
 	ret = driver_register(&q40fb_driver);
 
 	if (!ret) {
@@ -153,4 +156,5 @@
 	return ret;
 }
 
+module_init(q40fb_init);
 MODULE_LICENSE("GPL");
diff -Nru a/drivers/video/radeonfb.c b/drivers/video/radeonfb.c
--- a/drivers/video/radeonfb.c	2004-10-18 14:57:04 -07:00
+++ b/drivers/video/radeonfb.c	2004-10-18 14:57:04 -07:00
@@ -360,13 +360,13 @@
 	unsigned long mmio_base_phys;
 	unsigned long fb_base_phys;
 
-	unsigned long mmio_base;
-	unsigned long fb_base;
+	void __iomem *mmio_base;
+	void __iomem *fb_base;
 
 	struct pci_dev *pdev;
 
 	unsigned char *EDID;
-	unsigned char *bios_seg;
+	unsigned char __iomem *bios_seg;
 
 	u32 pseudo_palette[17];
 	struct { u8 red, green, blue, pad; } palette[256];
@@ -702,8 +702,8 @@
 static int __devinit radeon_set_fbinfo (struct radeonfb_info *rinfo);
 static int __devinit radeon_init_disp (struct radeonfb_info *rinfo);
 static int radeon_init_disp_var (struct radeonfb_info *rinfo, struct fb_var_screeninfo *var);
-static char *radeon_find_rom(struct radeonfb_info *rinfo);
-static void radeon_get_pllinfo(struct radeonfb_info *rinfo, char *bios_seg);
+static void __iomem *radeon_find_rom(struct radeonfb_info *rinfo);
+static void radeon_get_pllinfo(struct radeonfb_info *rinfo, void __iomem *bios_seg);
 static void radeon_get_moninfo (struct radeonfb_info *rinfo);
 static int radeon_get_dfpinfo (struct radeonfb_info *rinfo);
 static int radeon_get_dfpinfo_BIOS(struct radeonfb_info *rinfo);
@@ -735,12 +735,12 @@
 #endif /* CONFIG_PPC_OF */
 
 
-static char *radeon_find_rom(struct radeonfb_info *rinfo)
+static void __iomem *radeon_find_rom(struct radeonfb_info *rinfo)
 {       
 #if defined(__i386__)
         u32  segstart;
-        char *rom_base;
-        char *rom;
+        char __iomem *rom_base;
+        char __iomem *rom;
         int  stage;
         int  i,j;       
         char aty_rom_sig[] = "761295520";
@@ -753,7 +753,7 @@
                         
                 stage = 1;
                 
-                rom_base = (char *)ioremap(segstart, 0x1000);
+                rom_base = ioremap(segstart, 0x1000);
 
                 if ((*rom_base == 0x55) && (((*(rom_base + 1)) & 0xff) == 0xaa))
                         stage = 2;
@@ -804,10 +804,10 @@
 
 
 
-static void radeon_get_pllinfo(struct radeonfb_info *rinfo, char *bios_seg)
+static void radeon_get_pllinfo(struct radeonfb_info *rinfo, void __iomem *bios_seg)
 {
-        void *bios_header;
-        void *header_ptr;
+        void __iomem *bios_header;
+        void __iomem *header_ptr;
         u16 bios_header_offset, pll_info_offset;
         PLL_BLOCK pll;
 
@@ -1077,7 +1077,7 @@
 
 static int radeon_get_dfpinfo_BIOS(struct radeonfb_info *rinfo)
 {
-	char *fpbiosstart, *tmp, *tmp0;
+	char __iomem *fpbiosstart, *tmp, *tmp0;
 	char stmp[30];
 	int i;
 
@@ -2250,9 +2250,9 @@
 	info->currcon = -1;
 	info->par = rinfo;
 	info->pseudo_palette = rinfo->pseudo_palette;
-        info->flags = FBINFO_FLAG_DEFAULT;
+        info->flags = FBINFO_DEFAULT | FBINFO_HWACCEL_YPAN;
         info->fbops = &radeonfb_ops;
-        info->screen_base = (char *)rinfo->fb_base;
+        info->screen_base = rinfo->fb_base;
 
 	/* Fill fix common fields */
 	strlcpy(info->fix.id, rinfo->name, sizeof(info->fix.id));
@@ -2851,7 +2851,7 @@
 	}
 
 	/* map the regions */
-	rinfo->mmio_base = (unsigned long) ioremap (rinfo->mmio_base_phys, RADEON_REGSIZE);
+	rinfo->mmio_base = ioremap (rinfo->mmio_base_phys, RADEON_REGSIZE);
 	if (!rinfo->mmio_base) {
 		printk ("radeonfb: cannot map MMIO\n");
 		release_mem_region (rinfo->mmio_base_phys,
@@ -2978,7 +2978,7 @@
 	if ((rinfo->dviDisp_type == MT_DFP) || (rinfo->dviDisp_type == MT_LCD) ||
 	    (rinfo->crtDisp_type == MT_DFP)) {
 		if (!radeon_get_dfpinfo(rinfo)) {
-			iounmap ((void*)rinfo->mmio_base);
+			iounmap(rinfo->mmio_base);
 			release_mem_region (rinfo->mmio_base_phys,
 					    pci_resource_len(pdev, 2));
 			release_mem_region (rinfo->fb_base_phys,
@@ -2988,10 +2988,10 @@
 		}
 	}
 
-	rinfo->fb_base = (unsigned long) ioremap (rinfo->fb_base_phys, rinfo->video_ram);
+	rinfo->fb_base = ioremap (rinfo->fb_base_phys, rinfo->video_ram);
 	if (!rinfo->fb_base) {
 		printk ("radeonfb: cannot map FB\n");
-		iounmap ((void*)rinfo->mmio_base);
+		iounmap(rinfo->mmio_base);
 		release_mem_region (rinfo->mmio_base_phys,
 				    pci_resource_len(pdev, 2));
 		release_mem_region (rinfo->fb_base_phys,
@@ -3043,8 +3043,8 @@
 
 	if (register_framebuffer ((struct fb_info *) rinfo) < 0) {
 		printk ("radeonfb: could not register framebuffer\n");
-		iounmap ((void*)rinfo->fb_base);
-		iounmap ((void*)rinfo->mmio_base);
+		iounmap(rinfo->fb_base);
+		iounmap(rinfo->mmio_base);
 		release_mem_region (rinfo->mmio_base_phys,
 				    pci_resource_len(pdev, 2));
 		release_mem_region (rinfo->fb_base_phys,
@@ -3113,8 +3113,8 @@
 
         unregister_framebuffer ((struct fb_info *) rinfo);
                 
-        iounmap ((void*)rinfo->mmio_base);
-        iounmap ((void*)rinfo->fb_base);
+        iounmap(rinfo->mmio_base);
+        iounmap(rinfo->fb_base);
  
 	release_mem_region (rinfo->mmio_base_phys,
 			    pci_resource_len(pdev, 2));
@@ -3132,9 +3132,17 @@
 	.remove		= __devexit_p(radeonfb_pci_unregister),
 };
 
+int __init radeonfb_old_setup (char *options);
 
 int __init radeonfb_old_init (void)
 {
+#ifndef MODULE
+	char *option = NULL;
+
+	if (fb_get_options("radeonfb_old", &option))
+		return -ENODEV;
+	radeonfb_old_setup(option);
+#endif
 	return pci_module_init (&radeonfb_driver);
 }
 
@@ -3172,8 +3180,9 @@
 	return 0;
 }
 
-#ifdef MODULE
 module_init(radeonfb_old_init);
+
+#ifdef MODULE
 module_exit(radeonfb_old_exit);
 #endif
 
diff -Nru a/drivers/video/riva/fbdev.c b/drivers/video/riva/fbdev.c
--- a/drivers/video/riva/fbdev.c	2004-10-18 14:56:48 -07:00
+++ b/drivers/video/riva/fbdev.c	2004-10-18 14:56:48 -07:00
@@ -111,177 +111,87 @@
  *
  * ------------------------------------------------------------------------- */
 
-enum riva_chips {
-	CH_RIVA_128 = 0,
-	CH_RIVA_TNT,
-	CH_RIVA_TNT2,
-	CH_RIVA_UTNT2,
-	CH_RIVA_VTNT2,
-	CH_RIVA_UVTNT2,
-	CH_RIVA_ITNT2,
-	CH_GEFORCE_SDR,
-	CH_GEFORCE_DDR,
-	CH_QUADRO,
-	CH_GEFORCE2_MX,
-	CH_GEFORCE2_MX2,
-	CH_GEFORCE2_GO,
-	CH_QUADRO2_MXR,
-	CH_GEFORCE2_GTS,
-	CH_GEFORCE2_GTS2,
-	CH_GEFORCE2_ULTRA,
-	CH_QUADRO2_PRO,
-	CH_GEFORCE4_MX_460,
-	CH_GEFORCE4_MX_440,
-	CH_GEFORCE4_MX_420,
-	CH_GEFORCE4_440_GO,
-	CH_GEFORCE4_420_GO,
-	CH_GEFORCE4_420_GO_M32,
-	CH_QUADRO4_500XGL,
-	CH_GEFORCE4_440_GO_M64,
-	CH_QUADRO4_200,
-	CH_QUADRO4_550XGL,
-	CH_QUADRO4_500_GOGL,
-	CH_IGEFORCE2,
-	CH_GEFORCE3,
-	CH_GEFORCE3_1,
-	CH_GEFORCE3_2,
-	CH_QUADRO_DDC,
-	CH_GEFORCE4_TI_4600,
-	CH_GEFORCE4_TI_4400,
-	CH_GEFORCE4_TI_4200,
-	CH_QUADRO4_900XGL,
-	CH_QUADRO4_750XGL,
-	CH_QUADRO4_700XGL
-};
-
-/* directly indexed by riva_chips enum, above */
-static struct riva_chip_info {
-	const char *name;
-	unsigned arch_rev;
-} riva_chip_info[] __initdata = {
-	{ "RIVA-128", NV_ARCH_03 },
-	{ "RIVA-TNT", NV_ARCH_04 },
-	{ "RIVA-TNT2", NV_ARCH_04 },
-	{ "RIVA-UTNT2", NV_ARCH_04 },
-	{ "RIVA-VTNT2", NV_ARCH_04 },
-	{ "RIVA-UVTNT2", NV_ARCH_04 },
-	{ "RIVA-ITNT2", NV_ARCH_04 },
-	{ "GeForce-SDR", NV_ARCH_10 },
-	{ "GeForce-DDR", NV_ARCH_10 },
-	{ "Quadro", NV_ARCH_10 },
-	{ "GeForce2-MX", NV_ARCH_10 },
-	{ "GeForce2-MX", NV_ARCH_10 },
-	{ "GeForce2-GO", NV_ARCH_10 },
-	{ "Quadro2-MXR", NV_ARCH_10 },
-	{ "GeForce2-GTS", NV_ARCH_10 },
-	{ "GeForce2-GTS", NV_ARCH_10 },
-	{ "GeForce2-ULTRA", NV_ARCH_10 },
-	{ "Quadro2-PRO", NV_ARCH_10 },
-	{ "GeForce4-MX-460", NV_ARCH_10 },
-	{ "GeForce4-MX-440", NV_ARCH_10 },
-	{ "GeForce4-MX-420", NV_ARCH_10 },
-	{ "GeForce4-440-GO", NV_ARCH_10 },
-	{ "GeForce4-420-GO", NV_ARCH_10 },
-	{ "GeForce4-420-GO-M32", NV_ARCH_10 },
-	{ "Quadro4-500-XGL", NV_ARCH_10 },
-	{ "GeForce4-440-GO-M64", NV_ARCH_10 },
-	{ "Quadro4-200", NV_ARCH_10 },
-	{ "Quadro4-550-XGL", NV_ARCH_10 },
-	{ "Quadro4-500-GOGL", NV_ARCH_10 },
-	{ "GeForce2", NV_ARCH_10 },
-	{ "GeForce3", NV_ARCH_20 }, 
-	{ "GeForce3 Ti 200", NV_ARCH_20 },
-	{ "GeForce3 Ti 500", NV_ARCH_20 },
-	{ "Quadro DDC", NV_ARCH_20 },
-	{ "GeForce4 Ti 4600", NV_ARCH_20 },
-	{ "GeForce4 Ti 4400", NV_ARCH_20 },
-	{ "GeForce4 Ti 4200", NV_ARCH_20 },
-	{ "Quadro4-900-XGL", NV_ARCH_20 },
-	{ "Quadro4-750-XGL", NV_ARCH_20 },
-	{ "Quadro4-700-XGL", NV_ARCH_20 }
-};
-
 static struct pci_device_id rivafb_pci_tbl[] = {
 	{ PCI_VENDOR_ID_NVIDIA_SGS, PCI_DEVICE_ID_NVIDIA_SGS_RIVA128,
-	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_RIVA_128 },
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
 	{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_TNT,
-	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_RIVA_TNT },
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
 	{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_TNT2,
-	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_RIVA_TNT2 },
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
 	{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_UTNT2,
-	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_RIVA_UTNT2 },
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
 	{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_VTNT2,
-	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_RIVA_VTNT2 },
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
 	{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_UVTNT2,
-	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_RIVA_VTNT2 },
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
 	{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_ITNT2,
-	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_RIVA_ITNT2 },
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
 	{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE_SDR,
-	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_GEFORCE_SDR },
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
 	{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE_DDR,
-	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_GEFORCE_DDR },
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
 	{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_QUADRO,
-	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_QUADRO },
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
 	{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE2_MX,
-	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_GEFORCE2_MX },
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
 	{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE2_MX2,
-	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_GEFORCE2_MX2 },
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
 	{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE2_GO,
-	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_GEFORCE2_GO },
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
 	{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_QUADRO2_MXR,
-	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_QUADRO2_MXR },
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
 	{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE2_GTS,
-	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_GEFORCE2_GTS },
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
 	{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE2_GTS2,
-	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_GEFORCE2_GTS2 },
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
 	{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE2_ULTRA,
-	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_GEFORCE2_ULTRA },
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
 	{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_QUADRO2_PRO,
-	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_QUADRO2_PRO },
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
 	{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE4_MX_460,
-	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_GEFORCE4_MX_460 },
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
 	{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE4_MX_440,
-	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_GEFORCE4_MX_440 },
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
 	{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE4_MX_420,
-	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_GEFORCE4_MX_420 },
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
 	{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE4_440_GO,
-	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_GEFORCE4_440_GO },
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
 	{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE4_420_GO,
-	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_GEFORCE4_420_GO },
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
 	{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE4_420_GO_M32,
-	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_GEFORCE4_420_GO_M32 },
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
 	{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_QUADRO4_500XGL,
-	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_QUADRO4_500XGL },
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
 	{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE4_440_GO_M64,
-	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_GEFORCE4_440_GO_M64 },
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
 	{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_QUADRO4_200,
-	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_QUADRO4_200 },
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
 	{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_QUADRO4_550XGL,
-	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_QUADRO4_550XGL },
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
 	{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_QUADRO4_500_GOGL,
-	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_QUADRO4_500_GOGL },
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
 	{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_IGEFORCE2,
-	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_IGEFORCE2 },
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
 	{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE3,
-	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_GEFORCE3 },
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
 	{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE3_1,
-	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_GEFORCE3_1 },
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
 	{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE3_2,
-	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_GEFORCE3_2 },
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
 	{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_QUADRO_DDC,
-	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_QUADRO_DDC },
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
 	{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE4_TI_4600,
-	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_GEFORCE4_TI_4600 },
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
 	{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE4_TI_4400,
-	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_GEFORCE4_TI_4400 },
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
 	{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE4_TI_4200,
-	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_GEFORCE4_TI_4200 },
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
  	{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_QUADRO4_900XGL,
-	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_QUADRO4_900XGL },
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
 	{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_QUADRO4_750XGL,
-	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_QUADRO4_750XGL },
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
 	{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_QUADRO4_700XGL,
-	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_QUADRO4_700XGL },
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
 	{ 0, } /* terminate list */
 };
 MODULE_DEVICE_TABLE(pci, rivafb_pci_tbl);
@@ -293,7 +203,6 @@
  * ------------------------------------------------------------------------- */
 
 /* command line data, set in rivafb_setup() */
-static u32 pseudo_palette[17];
 static int flatpanel __initdata = -1; /* Autodetect later */
 static int forceCRTC __initdata = -1;
 #ifdef CONFIG_MTRR
@@ -303,14 +212,13 @@
 static char *mode_option __initdata = NULL;
 static int  strictmode       = 0;
 
-static struct fb_fix_screeninfo rivafb_fix = {
-	.id		= "nVidia",
+static struct fb_fix_screeninfo __initdata rivafb_fix = {
 	.type		= FB_TYPE_PACKED_PIXELS,
 	.xpanstep	= 1,
 	.ypanstep	= 1,
 };
 
-static struct fb_var_screeninfo rivafb_default_var = {
+static struct fb_var_screeninfo __initdata rivafb_default_var = {
 	.xres		= 640,
 	.yres		= 480,
 	.xres_virtual	= 640,
@@ -533,6 +441,8 @@
 	int i, j, k = 0;
 	u32 b, tmp;
 	u32 *data = (u32 *)data8;
+	bg = le16_to_cpu(bg);
+	fg = le16_to_cpu(fg);
 
 	for (i = 0; i < h; i++) {
 		b = *data++;
@@ -606,7 +516,7 @@
 		       unsigned char *green, unsigned char *blue)
 {
 	
-	VGA_WR08(chip->PDIO, 0x3c8, regnum);
+	VGA_WR08(chip->PDIO, 0x3c7, regnum);
 	*red = VGA_RD08(chip->PDIO, 0x3c9);
 	*green = VGA_RD08(chip->PDIO, 0x3c9);
 	*blue = VGA_RD08(chip->PDIO, 0x3c9);
@@ -1090,13 +1000,15 @@
 
 	NVTRACE_ENTER();
 	if (!cnt) {
+#ifdef CONFIG_X86
 		memset(&par->state, 0, sizeof(struct vgastate));
 		par->state.flags = VGA_SAVE_MODE  | VGA_SAVE_FONTS;
 		/* save the DAC for Riva128 */
 		if (par->riva.Architecture == NV_ARCH_03)
 			par->state.flags |= VGA_SAVE_CMAP;
 		save_vga(&par->state);
-
+#endif
+		riva_common_setup(par);
 		RivaGetConfig(&par->riva, par->Chipset);
 		/* vgaHWunlock() + riva unlock (0x7F) */
 		CRTCout(par, 0x11, 0xFF);
@@ -1121,7 +1033,9 @@
 		par->riva.LockUnlock(&par->riva, 0);
 		par->riva.LoadStateExt(&par->riva, &par->initial_state.ext);
 		riva_load_state(par, &par->initial_state);
+#ifdef CONFIG_X86
 		restore_vga(&par->state);
+#endif
 		par->riva.LockUnlock(&par->riva, 1);
 	}
 	atomic_dec(&par->ref_count);
@@ -1131,7 +1045,8 @@
 
 static int rivafb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
 {
-	struct fb_monspecs *specs = &info->monspecs;
+	struct fb_videomode *mode;
+	struct riva_par *par = (struct riva_par *) info->par;
 	int nom, den;		/* translating from pixels->bytes */
 	int mode_valid = 0;
 	
@@ -1148,6 +1063,9 @@
 		/* fall through */
 	case 16:
 		var->bits_per_pixel = 16;
+		/* The Riva128 supports RGB555 only */
+		if (par->riva.Architecture == NV_ARCH_03)
+			var->green.length = 5;
 		if (var->green.length == 5) {
 			/* 0rrrrrgg gggbbbbb */
 			var->red.offset = 10;
@@ -1190,62 +1108,21 @@
 			mode_valid = 1;
 	}
 
-	/* find best mode from modedb */
-	if (!mode_valid && specs->modedb_len) {
-		int i, best, best_refresh, best_x, best_y, diff_x, diff_y;
-
-		best_refresh = best = best_x = best_y = 0;
-		diff_x = diff_y = -1;
-
-		for (i = 0; i < specs->modedb_len; i++) {
-			if (var->xres <= specs->modedb[i].xres &&
-			    !(specs->modedb[i].flag & FB_MODE_IS_CALCULATED) &&
-			    specs->modedb[i].xres - var->xres < diff_x) {
-				best_x = specs->modedb[i].xres;
-				diff_x = best_x - var->xres;
-			}
-			if (!diff_x) break;
-		}
-
-		if (diff_x != -1) {
-			for (i = 0; i < specs->modedb_len; i++) {
-				if (best_x == specs->modedb[i].xres &&
-				    var->yres <= specs->modedb[i].yres &&
-				    !(specs->modedb[i].flag &
-				      FB_MODE_IS_CALCULATED) &&
-				    specs->modedb[i].yres-var->yres < diff_y) {
-					best_y = specs->modedb[i].yres;
-					diff_y = best_y - var->yres;
-				}
-				if (!diff_y) break;
-			}
-		}
-
-		if (diff_y != -1) {
-			for (i = 0; i < specs->modedb_len; i++) {
-				if (best_x == specs->modedb[i].xres &&
-				    best_y == specs->modedb[i].yres &&
-				    !(specs->modedb[i].flag &
-				      FB_MODE_IS_CALCULATED) &&
-				    specs->modedb[i].refresh > best_refresh) {
-					best_refresh=specs->modedb[i].refresh;
-					best = i;
-				}
-			}
-		}
-
-		if (best_refresh) {
-			riva_update_var(var, &specs->modedb[best]);
-			mode_valid = 1;
-		}
-	}
-
 	/* calculate modeline if supported by monitor */
 	if (!mode_valid && info->monspecs.gtf) {
 		if (!fb_get_mode(FB_MAXTIMINGS, 0, var, info))
 			mode_valid = 1;
 	}
-	if (!mode_valid && info->monspecs.modedb_len)
+
+	if (!mode_valid) {
+		mode = fb_find_best_mode(var, &info->modelist);
+		if (mode) {
+			riva_update_var(var, mode);
+			mode_valid = 1;
+		}
+	}
+
+	if (!mode_valid && !list_empty(&info->modelist))
 		return -EINVAL;
 
 	if (var->xres_virtual < var->xres)
@@ -1293,6 +1170,7 @@
 	info->fix.line_length = (info->var.xres_virtual * (info->var.bits_per_pixel >> 3));
 	info->fix.visual = (info->var.bits_per_pixel == 8) ?
 				FB_VISUAL_PSEUDOCOLOR : FB_VISUAL_DIRECTCOLOR;
+
 	NVTRACE_LEAVE();
 	return 0;
 }
@@ -1413,7 +1291,7 @@
 	int i;
 
 	if (regno >= riva_get_cmap_len(&info->var))
-		return -EINVAL;
+			return -EINVAL;
 
 	if (info->var.grayscale) {
 		/* gray = 0.30*R + 0.59*G + 0.11*B */
@@ -1421,6 +1299,31 @@
 		    (red * 77 + green * 151 + blue * 28) >> 8;
 	}
 
+	if (regno < 16 && info->fix.visual == FB_VISUAL_DIRECTCOLOR) {
+		((u32 *) info->pseudo_palette)[regno] =
+			(regno << info->var.red.offset) |
+			(regno << info->var.green.offset) |
+			(regno << info->var.blue.offset);
+		/*
+		 * The Riva128 2D engine requires color information in
+		 * TrueColor format even if framebuffer is in DirectColor
+		 */
+		if (par->riva.Architecture == NV_ARCH_03) {
+			switch (info->var.bits_per_pixel) {
+			case 16:
+				par->palette[regno] = ((red & 0xf800) >> 1) |
+					((green & 0xf800) >> 6) |
+					((blue & 0xf800) >> 11);
+				break;
+			case 32:
+				par->palette[regno] = ((red & 0xff00) << 8) |
+					((green & 0xff00)) |
+					((blue & 0xff00) >> 8);
+				break;
+			}
+		}
+	}
+
 	switch (info->var.bits_per_pixel) {
 	case 8:
 		/* "transparent" stuff is completely ignored. */
@@ -1428,45 +1331,27 @@
 		break;
 	case 16:
 		if (info->var.green.length == 5) {
-			if (regno < 16) {
-				/* 0rrrrrgg gggbbbbb */
-				((u32 *)info->pseudo_palette)[regno] =
-					((red & 0xf800) >> 1) |
-					((green & 0xf800) >> 6) |
-					((blue & 0xf800) >> 11);
-			}
-			for (i = 0; i < 8; i++) 
+			for (i = 0; i < 8; i++) {
 				riva_wclut(chip, regno*8+i, red >> 8,
 					   green >> 8, blue >> 8);
+			}
 		} else {
 			u8 r, g, b;
 
-			if (regno < 16) {
-				/* rrrrrggg gggbbbbb */
-				((u32 *)info->pseudo_palette)[regno] =
-					((red & 0xf800) >> 0) |
-					((green & 0xf800) >> 5) |
-					((blue & 0xf800) >> 11);
-			}
 			if (regno < 32) {
 				for (i = 0; i < 8; i++) {
-					riva_wclut(chip, regno*8+i, red >> 8, 
-						   green >> 8, blue >> 8);
+					riva_wclut(chip, regno*8+i,
+						   red >> 8, green >> 8,
+						   blue >> 8);
 				}
 			}
-			for (i = 0; i < 4; i++) {
-				riva_rclut(chip, regno*2+i, &r, &g, &b);
-				riva_wclut(chip, regno*4+i, r, green >> 8, b);
-			}
+			riva_rclut(chip, regno*4, &r, &g, &b);
+			for (i = 0; i < 4; i++)
+				riva_wclut(chip, regno*4+i, r,
+					   green >> 8, b);
 		}
 		break;
 	case 32:
-		if (regno < 16) {
-			((u32 *)info->pseudo_palette)[regno] =
-				((red & 0xff00) << 8) |
-				((green & 0xff00)) | ((blue & 0xff00) >> 8);
-			
-		}
 		riva_wclut(chip, regno, red >> 8, green >> 8, blue >> 8);
 		break;
 	default:
@@ -1495,8 +1380,12 @@
 
 	if (info->var.bits_per_pixel == 8)
 		color = rect->color;
-	else
-		color = ((u32 *)info->pseudo_palette)[rect->color];
+	else {
+		if (par->riva.Architecture != NV_ARCH_03)
+			color = ((u32 *)info->pseudo_palette)[rect->color];
+		else
+			color = par->palette[rect->color];
+	}
 
 	switch (rect->rop) {
 	case ROP_XOR:
@@ -1592,15 +1481,17 @@
 		bgx = image->bg_color;
 		break;
 	case 16:
-		fgx = ((u32 *)info->pseudo_palette)[image->fg_color];
-		bgx = ((u32 *)info->pseudo_palette)[image->bg_color];
+	case 32:
+		if (par->riva.Architecture != NV_ARCH_03) {
+			fgx = ((u32 *)info->pseudo_palette)[image->fg_color];
+			bgx = ((u32 *)info->pseudo_palette)[image->bg_color];
+		} else {
+			fgx = par->palette[image->fg_color];
+			bgx = par->palette[image->bg_color];
+		}
 		if (info->var.green.length == 6)
 			convert_bgcolor_16(&bgx);	
 		break;
-	case 32:
-		fgx = ((u32 *)info->pseudo_palette)[image->fg_color];
-		bgx = ((u32 *)info->pseudo_palette)[image->bg_color];
-		break;
 	}
 
 	RIVA_FIFO_FREE(par->riva, Bitmap, 7);
@@ -1769,6 +1660,7 @@
 static int __devinit riva_set_fbinfo(struct fb_info *info)
 {
 	unsigned int cmap_len;
+	struct riva_par *par = (struct riva_par *) info->par;
 
 	NVTRACE_ENTER();
 	info->flags = FBINFO_DEFAULT
@@ -1781,7 +1673,8 @@
 	info->var = rivafb_default_var;
 	info->fix.visual = (info->var.bits_per_pixel == 8) ?
 				FB_VISUAL_PSEUDOCOLOR : FB_VISUAL_DIRECTCOLOR;
-	info->pseudo_palette = pseudo_palette;
+
+	info->pseudo_palette = par->pseudo_palette;
 
 	cmap_len = riva_get_cmap_len(&info->var);
 	fb_alloc_cmap(&info->cmap, cmap_len, 0);	
@@ -1796,7 +1689,7 @@
 }
 
 #ifdef CONFIG_PPC_OF
-static int riva_get_EDID_OF(struct fb_info *info, struct pci_dev *pd)
+static int __devinit riva_get_EDID_OF(struct fb_info *info, struct pci_dev *pd)
 {
 	struct riva_par *par = (struct riva_par *) info->par;
 	struct device_node *dp;
@@ -1828,7 +1721,28 @@
 }
 #endif /* CONFIG_PPC_OF */
 
-static void riva_update_default_var(struct fb_var_screeninfo *var, struct fb_info *info)
+#if defined(CONFIG_FB_RIVA_I2C) && !defined(CONFIG_PPC_OF)
+static int __devinit riva_get_EDID_i2c(struct fb_info *info)
+{
+	struct riva_par *par = (struct riva_par *) info->par;
+	int i;
+
+	NVTRACE_ENTER();
+	riva_create_i2c_busses(par);
+	for (i = par->bus; i >= 1; i--) {
+		riva_probe_i2c_connector(par, i, &par->EDID);
+		if (par->EDID) {
+			printk("rivafb: Found EDID Block from BUS %i\n", i);
+			break;
+		}
+	}
+	NVTRACE_LEAVE();
+	return (par->EDID) ? 1 : 0;
+}
+#endif /* CONFIG_FB_RIVA_I2C */
+
+static void __devinit riva_update_default_var(struct fb_var_screeninfo *var,
+					      struct fb_info *info)
 {
 	struct fb_monspecs *specs = &info->monspecs;
 	struct fb_videomode modedb;
@@ -1862,41 +1776,28 @@
 }
 
 
-static void riva_get_EDID(struct fb_info *info, struct pci_dev *pdev)
+static void __devinit riva_get_EDID(struct fb_info *info, struct pci_dev *pdev)
 {
-	struct riva_par *par;
-	int i;
-
 	NVTRACE_ENTER();
 #ifdef CONFIG_PPC_OF
 	if (!riva_get_EDID_OF(info, pdev))
 		printk("rivafb: could not retrieve EDID from OF\n");
-#else
-	/* XXX use other methods later */
-#ifdef CONFIG_FB_RIVA_I2C
-
-	par = (struct riva_par *) info->par;
-	riva_create_i2c_busses(par);
-	for (i = par->bus; i >= 1; i--) {
-		riva_probe_i2c_connector(par, i, &par->EDID);
-		if (par->EDID) {
-			printk("rivafb: Found EDID Block from BUS %i\n", i);
-			break;
-		}
-	}
-	riva_delete_i2c_busses(par);
-#endif
+#elif CONFIG_FB_RIVA_I2C
+	if (!riva_get_EDID_i2c(info))
+		printk("rivafb: could not retrieve EDID from DDC/I2C\n");
 #endif
 	NVTRACE_LEAVE();
 }
 
 
-static void riva_get_edidinfo(struct fb_info *info)
+static void __devinit riva_get_edidinfo(struct fb_info *info)
 {
 	struct fb_var_screeninfo *var = &rivafb_default_var;
 	struct riva_par *par = (struct riva_par *) info->par;
 
 	fb_edid_to_monspecs(par->EDID, &info->monspecs);
+	fb_videomode_to_modelist(info->monspecs.modedb, info->monspecs.modedb_len,
+				 &info->modelist);
 	riva_update_default_var(var, info);
 
 	/* if user specified flatpanel, we respect that */
@@ -1910,16 +1811,52 @@
  *
  * ------------------------------------------------------------------------- */
 
+static u32 __devinit riva_get_arch(struct pci_dev *pd)
+{
+    	u32 arch = 0;
+
+	switch (pd->device & 0x0ff0) {
+		case 0x0100:   /* GeForce 256 */
+		case 0x0110:   /* GeForce2 MX */
+		case 0x0150:   /* GeForce2 */
+		case 0x0170:   /* GeForce4 MX */
+		case 0x0180:   /* GeForce4 MX (8x AGP) */
+		case 0x01A0:   /* nForce */
+		case 0x01F0:   /* nForce2 */
+		     arch =  NV_ARCH_10;
+		     break;
+		case 0x0200:   /* GeForce3 */
+		case 0x0250:   /* GeForce4 Ti */
+		case 0x0280:   /* GeForce4 Ti (8x AGP) */
+		     arch =  NV_ARCH_20;
+		     break;
+		case 0x0300:   /* GeForceFX 5800 */
+		case 0x0310:   /* GeForceFX 5600 */
+		case 0x0320:   /* GeForceFX 5200 */
+		case 0x0330:   /* GeForceFX 5900 */
+		case 0x0340:   /* GeForceFX 5700 */
+		     arch =  NV_ARCH_30;
+		     break;
+		case 0x0020:   /* TNT, TNT2 */
+		     arch =  NV_ARCH_04;
+		     break;
+		case 0x0010:   /* Riva128 */
+		     arch =  NV_ARCH_03;
+		     break;
+		default:   /* unknown architecture */
+		     break;
+	}
+	return arch;
+}
+
 static int __devinit rivafb_probe(struct pci_dev *pd,
 			     	const struct pci_device_id *ent)
 {
-	struct riva_chip_info *rci = &riva_chip_info[ent->driver_data];
 	struct riva_par *default_par;
 	struct fb_info *info;
 
 	NVTRACE_ENTER();
 	assert(pd != NULL);
-	assert(rci != NULL);
 
 	info = kmalloc(sizeof(struct fb_info), GFP_KERNEL);
 	if (!info)
@@ -1948,12 +1885,27 @@
 		goto err_out_request;
 	}
 
-	strcat(rivafb_fix.id, rci->name);
-	default_par->riva.Architecture = rci->arch_rev;
+	default_par->riva.Architecture = riva_get_arch(pd);
 
 	default_par->Chipset = (pd->vendor << 16) | pd->device;
 	printk(KERN_INFO PFX "nVidia device/chipset %X\n",default_par->Chipset);
 	
+#ifdef CONFIG_PCI_NAMES
+	printk(KERN_INFO PFX "%s\n", pd->pretty_name);
+#endif
+
+	if(default_par->riva.Architecture == 0) {
+		printk(KERN_ERR PFX "unknown NV_ARCH\n");
+		goto err_out_kfree1;
+	}
+	if(default_par->riva.Architecture == NV_ARCH_10 ||
+	   default_par->riva.Architecture == NV_ARCH_20 ||
+	   default_par->riva.Architecture == NV_ARCH_30) {
+		sprintf(rivafb_fix.id, "NV%x", (pd->device & 0x0ff0) >> 4);
+	} else {
+		sprintf(rivafb_fix.id, "NV%x", default_par->riva.Architecture);
+	}
+
 	default_par->FlatPanel = flatpanel;
 	if (flatpanel == 1)
 		printk(KERN_INFO PFX "flatpanel support enabled\n");
@@ -1995,15 +1947,14 @@
 			goto err_out_free_nv3_pramin;
 		}
 		rivafb_fix.accel = FB_ACCEL_NV3;
-		default_par->bus = 1;
 		break;
 	case NV_ARCH_04:
 	case NV_ARCH_10:
 	case NV_ARCH_20:
+	case NV_ARCH_30:
 		default_par->riva.PCRTC0 = (unsigned *)(default_par->ctrl_base + 0x00600000);
 		default_par->riva.PRAMIN = (unsigned *)(default_par->ctrl_base + 0x00710000);
 		rivafb_fix.accel = FB_ACCEL_NV4;
-		default_par->bus = 2;
 		break;
 	}
 
@@ -2015,7 +1966,6 @@
 
 	rivafb_fix.smem_len = riva_get_memlen(default_par) * 1024;
 	default_par->dclk_max = riva_get_maxdclk(default_par) * 1000;
-
 	info->screen_base = ioremap(rivafb_fix.smem_start,
 				    rivafb_fix.smem_len);
 	if (!info->screen_base) {
@@ -2048,6 +1998,10 @@
 		goto err_out_iounmap_fb;
 	}
 
+	fb_destroy_modedb(info->monspecs.modedb);
+	info->monspecs.modedb_len = 0;
+	info->monspecs.modedb = NULL;
+
 	if (register_framebuffer(info) < 0) {
 		printk(KERN_ERR PFX
 			"error registering riva framebuffer\n");
@@ -2057,10 +2011,9 @@
 	pci_set_drvdata(pd, info);
 
 	printk(KERN_INFO PFX
-		"PCI nVidia NV%x framebuffer ver %s (%s, %dMB @ 0x%lX)\n",
-		default_par->riva.Architecture,
-		RIVAFB_VERSION,
+		"PCI nVidia %s framebuffer ver %s (%dMB @ 0x%lX)\n",
 		info->fix.id,
+		RIVAFB_VERSION,
 		info->fix.smem_len / (1024 * 1024),
 		info->fix.smem_start);
 #ifdef CONFIG_PMAC_BACKLIGHT
@@ -2072,6 +2025,9 @@
 	return 0;
 
 err_out_iounmap_fb:
+#ifdef CONFIG_FB_RIVA_I2C
+	riva_delete_i2c_busses((struct riva_par *) info->par);
+#endif
 	iounmap(info->screen_base);
 err_out_free_base1:
 	if (default_par->riva.Architecture == NV_ARCH_03) 
@@ -2101,6 +2057,12 @@
 	if (!info)
 		return;
 
+#ifdef CONFIG_FB_RIVA_I2C
+	riva_delete_i2c_busses(par);
+	if (par->EDID)
+		kfree(par->EDID);
+#endif
+
 	unregister_framebuffer(info);
 #ifdef CONFIG_MTRR
 	if (par->mtrr.vram_valid)
@@ -2114,7 +2076,6 @@
 		iounmap((caddr_t)par->riva.PRAMIN);
 	pci_release_regions(pd);
 	pci_disable_device(pd);
-	fb_destroy_modedb(info->monspecs.modedb);
 	kfree(info->pixmap.addr);
 	kfree(par);
 	kfree(info);
@@ -2177,8 +2138,15 @@
  *
  * ------------------------------------------------------------------------- */
 
-int __init rivafb_init(void)
+int __devinit rivafb_init(void)
 {
+#ifndef MODULE
+	char *option = NULL;
+
+	if (fb_get_options("rivafb", &option))
+		return -ENODEV;
+	rivafb_setup(option);
+#endif
 	if (pci_register_driver(&rivafb_driver) > 0)
 		return 0;
 	pci_unregister_driver(&rivafb_driver);
@@ -2186,13 +2154,14 @@
 }
 
 
+module_init(rivafb_init);
+
 #ifdef MODULE
 static void __exit rivafb_exit(void)
 {
 	pci_unregister_driver(&rivafb_driver);
 }
 
-module_init(rivafb_init);
 module_exit(rivafb_exit);
 
 MODULE_PARM(flatpanel, "i");
@@ -2203,9 +2172,9 @@
 #ifdef CONFIG_MTRR
 MODULE_PARM(nomtrr, "i");
 MODULE_PARM_DESC(nomtrr, "Disables MTRR support (0 or 1=disabled) (default=0)");
+#endif
 MODULE_PARM(strictmode, "i");
 MODULE_PARM_DESC(strictmode, "Only use video modes from EDID");
-#endif
 #endif /* MODULE */
 
 MODULE_AUTHOR("Ani Joshi, maintainer");
diff -Nru a/drivers/video/riva/nv_driver.c b/drivers/video/riva/nv_driver.c
--- a/drivers/video/riva/nv_driver.c	2004-10-18 14:56:49 -07:00
+++ b/drivers/video/riva/nv_driver.c	2004-10-18 14:56:49 -07:00
@@ -205,6 +205,7 @@
 		break;
 	case NV_ARCH_10:
 	case NV_ARCH_20:
+	case NV_ARCH_30:
 		if(chipset == NV_CHIP_IGEFORCE2) {
 
 			dev = pci_find_slot(0, 1);
@@ -274,6 +275,7 @@
 	case NV_ARCH_04:
 	case NV_ARCH_10:
 	case NV_ARCH_20:
+	case NV_ARCH_30:
 		switch ((chip->PFB[0x00000000/4] >> 3) & 0x00000003) {
 		case 3:
 			dclk = 800000;
diff -Nru a/drivers/video/riva/riva_hw.c b/drivers/video/riva/riva_hw.c
--- a/drivers/video/riva/riva_hw.c	2004-10-18 14:57:19 -07:00
+++ b/drivers/video/riva/riva_hw.c	2004-10-18 14:57:19 -07:00
@@ -1274,6 +1274,7 @@
             break;
         case NV_ARCH_10:
         case NV_ARCH_20:
+        case NV_ARCH_30:
             if((chip->Chipset == NV_CHIP_IGEFORCE2) ||
                (chip->Chipset == NV_CHIP_0x01F0))
             {
@@ -1299,9 +1300,10 @@
             break;
     }
 
-    /* Paul Richards: below if block borks things in kernel for some reason */
-    /* if((bpp != 8) && (chip->Architecture != NV_ARCH_03))
-    state->general |= 0x00000030; */
+     /* Paul Richards: below if block borks things in kernel for some reason */
+     /* Tony: Below is needed to set hardware in DirectColor */
+    if((bpp != 8) && (chip->Architecture != NV_ARCH_03))
+	    state->general |= 0x00000030;
 
     state->vpll     = (p << 16) | (n << 8) | m;
     state->repaint0 = (((width/8)*pixelDepth) & 0x700) >> 3;
@@ -1349,6 +1351,7 @@
             break;
         case NV_ARCH_10:
         case NV_ARCH_20:
+        case NV_ARCH_30:
             /*
              * Initialize state for the RivaTriangle3D05 routines.
              */
@@ -1458,6 +1461,7 @@
             break;
         case NV_ARCH_10:
         case NV_ARCH_20:
+        case NV_ARCH_30:
             if(chip->twoHeads) {
                VGA_WR08(chip->PCIO, 0x03D4, 0x44);
                VGA_WR08(chip->PCIO, 0x03D5, state->crtcOwner);
@@ -1754,6 +1758,7 @@
             break;
         case NV_ARCH_10:
         case NV_ARCH_20:
+        case NV_ARCH_30:
             state->offset0  = chip->PGRAPH[0x00000640/4];
             state->offset1  = chip->PGRAPH[0x00000644/4];
             state->offset2  = chip->PGRAPH[0x00000648/4];
@@ -2184,6 +2189,7 @@
             break;
         case NV_ARCH_10:
         case NV_ARCH_20:
+        case NV_ARCH_30:
             nv10GetConfig(chip, chipset);
             break;
         default:
diff -Nru a/drivers/video/riva/riva_hw.h b/drivers/video/riva/riva_hw.h
--- a/drivers/video/riva/riva_hw.h	2004-10-18 14:57:03 -07:00
+++ b/drivers/video/riva/riva_hw.h	2004-10-18 14:57:03 -07:00
@@ -89,12 +89,14 @@
 #define VGA_RD08(p,i)   NV_RD08(p,i)
 
 /*
- * Define supported architectures.
+ * Define different architectures.
  */
 #define NV_ARCH_03  0x03
 #define NV_ARCH_04  0x04
 #define NV_ARCH_10  0x10
 #define NV_ARCH_20  0x20
+#define NV_ARCH_30  0x30
+#define NV_ARCH_40  0x40
 
 /***************************************************************************\
 *                                                                           *
diff -Nru a/drivers/video/riva/rivafb-i2c.c b/drivers/video/riva/rivafb-i2c.c
--- a/drivers/video/riva/rivafb-i2c.c	2004-10-18 14:56:32 -07:00
+++ b/drivers/video/riva/rivafb-i2c.c	2004-10-18 14:56:32 -07:00
@@ -106,6 +106,7 @@
 	chan->algo.getsda		= riva_gpio_getsda;
 	chan->algo.getscl		= riva_gpio_getscl;
 	chan->algo.udelay		= 40;
+	chan->algo.mdelay               = 5;
 	chan->algo.timeout		= 20;
 	chan->algo.data 		= chan;
 
@@ -130,19 +131,34 @@
 	par->chan[1].par	= par;
 	par->chan[2].par        = par;
 
-	switch (par->riva.Architecture) {
-#if 0		/* no support yet for other nVidia chipsets */
+	par->bus = 0;
+
+	switch ((par->pdev->device >> 4) & 0xff) {
+	case 0x17:
+	case 0x18:
+	case 0x25:
+	case 0x28:
+	case 0x30:
+	case 0x31:
+	case 0x32:
+	case 0x33:
+	case 0x34:
 		par->chan[2].ddc_base   = 0x50;
-		riva_setup_i2c_bus(&par->chan[2], "BUS2");
-#endif
-	case NV_ARCH_10:
-	case NV_ARCH_20:
-	case NV_ARCH_04:
+		par->bus++;
+		riva_setup_i2c_bus(&par->chan[2], "BUS3");
+	case 0x04:
+	case 0x05:
+	case 0x10:
+	case 0x11:
+	case 0x15:
+	case 0x20:
 		par->chan[1].ddc_base	= 0x36;
-		riva_setup_i2c_bus(&par->chan[1], "BUS1");
-	case NV_ARCH_03:
+		par->bus++;
+		riva_setup_i2c_bus(&par->chan[1], "BUS2");
+	case 0x03:
 		par->chan[0].ddc_base	= 0x3e;
-		riva_setup_i2c_bus(&par->chan[0], "BUS0");
+		par->bus++;
+		riva_setup_i2c_bus(&par->chan[0], "BUS1");
 	}
 }
 
diff -Nru a/drivers/video/riva/rivafb.h b/drivers/video/riva/rivafb.h
--- a/drivers/video/riva/rivafb.h	2004-10-18 14:56:28 -07:00
+++ b/drivers/video/riva/rivafb.h	2004-10-18 14:56:28 -07:00
@@ -44,16 +44,17 @@
 
 struct riva_par {
 	RIVA_HW_INST riva;	/* interface to riva_hw.c */
-
+	u32 pseudo_palette[16]; /* default palette */
+	u32 palette[16];        /* for Riva128 */
 	caddr_t ctrl_base;	/* virtual control register base addr */
 	unsigned dclk_max;	/* max DCLK */
 
 	struct riva_regs initial_state;	/* initial startup video mode */
 	struct riva_regs current_state;
+#ifdef CONFIG_X86
 	struct vgastate state;
+#endif
 	atomic_t ref_count;
-	u32 cursor_data[32 * 32/4];
-	int cursor_reset;
 	unsigned char *EDID;
 	unsigned int Chipset;
 	int forceCRTC;
diff -Nru a/drivers/video/sa1100fb.c b/drivers/video/sa1100fb.c
--- a/drivers/video/sa1100fb.c	2004-10-18 14:56:27 -07:00
+++ b/drivers/video/sa1100fb.c	2004-10-18 14:56:27 -07:00
@@ -1671,7 +1671,7 @@
 	fbi->fb.var.vmode	= FB_VMODE_NONINTERLACED;
 
 	fbi->fb.fbops		= &sa1100fb_ops;
-	fbi->fb.flags		= FBINFO_FLAG_DEFAULT;
+	fbi->fb.flags		= FBINFO_DEFAULT;
 	fbi->fb.monspecs	= monspecs;
 	fbi->fb.currcon		= -1;
 	fbi->fb.pseudo_palette	= (fbi + 1);
@@ -1804,6 +1804,9 @@
 
 int __init sa1100fb_init(void)
 {
+	if (fb_get_options("sa1100fb", NULL))
+		return -ENODEV;
+
 	return driver_register(&sa1100fb_driver);
 }
 
@@ -1848,5 +1851,6 @@
 	return 0;
 }
 
+module_init(sa1100fb_init);
 MODULE_DESCRIPTION("StrongARM-1100/1110 framebuffer driver");
 MODULE_LICENSE("GPL");
diff -Nru a/drivers/video/sgivwfb.c b/drivers/video/sgivwfb.c
--- a/drivers/video/sgivwfb.c	2004-10-18 14:56:31 -07:00
+++ b/drivers/video/sgivwfb.c	2004-10-18 14:56:31 -07:00
@@ -22,7 +22,7 @@
 #include <asm/mtrr.h>
 
 #define INCLUDE_TIMING_TABLE_DATA
-#define DBE_REG_BASE default_par.regs
+#define DBE_REG_BASE par->regs
 #include <video/sgivw.h>
 
 struct sgivw_par {
@@ -44,9 +44,6 @@
 extern unsigned long sgivwfb_mem_phys;
 extern unsigned long sgivwfb_mem_size;
 
-static struct sgivw_par default_par;
-static u32 pseudo_palette[17];
-static struct fb_info fb_info;
 static int ypan = 0;
 static int ywrap = 0;
 
@@ -162,7 +159,7 @@
  *              console.
  */
 
-static void dbe_TurnOffDma(void)
+static void dbe_TurnOffDma(struct sgivw_par *par)
 {
 	unsigned int readVal;
 	int i;
@@ -367,7 +364,7 @@
 /*
  *  Setup flatpanel related registers.
  */
-static void sgivwfb_setup_flatpanel(struct dbe_timing_info *currentTiming)
+static void sgivwfb_setup_flatpanel(struct sgivw_par *par, struct dbe_timing_info *currentTiming)
 {
 	int fp_wid, fp_hgt, fp_vbs, fp_vbe;
 	u32 outputVal = 0;
@@ -429,7 +426,7 @@
 	/* Turn on dotclock PLL */
 	DBE_SETREG(ctrlstat, 0x20000000);
 
-	dbe_TurnOffDma();
+	dbe_TurnOffDma(par);
 
 	/* dbe_CalculateScreenParams(); */
 	maxPixelsPerTileX = 512 / bytesPerPixel;
@@ -453,7 +450,7 @@
 		DBE_SETREG(vt_xy, 0x00000000);
 		udelay(1);
 	} else
-		dbe_TurnOffDma();
+		dbe_TurnOffDma(par);
 
 	/* dbe_Initdbe(); */
 	for (i = 0; i < 256; i++) {
@@ -567,7 +564,7 @@
 	DBE_SETREG(vt_hcmap, outputVal);
 
 	if (flatpanel_id != -1)
-		sgivwfb_setup_flatpanel(currentTiming);
+		sgivwfb_setup_flatpanel(par, currentTiming);
 
 	outputVal = 0;
 	temp = currentTiming->vblank_start - currentTiming->vblank_end - 1;
@@ -752,16 +749,30 @@
 /*
  *  Initialisation
  */
-int __init sgivwfb_init(void)
+static void sgivwfb_release(struct device *device)
+{
+}
+
+static int __init sgivwfb_probe(struct device *device)
 {
+	struct platform_device *dev = to_platform_device(device);
+	struct sgivw_par *par;
+	struct fb_info *info;
 	char *monitor;
 
+	info = framebuffer_alloc(sizeof(struct sgivw_par) + sizeof(u32) * 256, &dev->dev);
+	if (!info)
+		return -ENOMEM;
+	par = info->par;
+
 	if (!request_mem_region(DBE_REG_PHYS, DBE_REG_SIZE, "sgivwfb")) {
 		printk(KERN_ERR "sgivwfb: couldn't reserve mmio region\n");
+		framebuffer_release(info);
 		return -EBUSY;
 	}
-	default_par.regs = (struct asregs *) ioremap_nocache(DBE_REG_PHYS, DBE_REG_SIZE);
-	if (!default_par.regs) {
+
+	par->regs = (struct asregs *) ioremap_nocache(DBE_REG_PHYS, DBE_REG_SIZE);
+	if (!par->regs) {
 		printk(KERN_ERR "sgivwfb: couldn't ioremap registers\n");
 		goto fail_ioremap_regs;
 	}
@@ -773,66 +784,118 @@
 	sgivwfb_fix.ywrapstep = ywrap;
 	sgivwfb_fix.ypanstep = ypan;
 
-	fb_info.fix = sgivwfb_fix;
+	info->fix = sgivwfb_fix;
 
 	switch (flatpanel_id) {
 		case FLATPANEL_SGI_1600SW:
-			fb_info.var = sgivwfb_var1600sw;
+			info->var = sgivwfb_var1600sw;
 			monitor = "SGI 1600SW flatpanel";
 			break;
 		default:
-			fb_info.var = sgivwfb_var;
+			info->var = sgivwfb_var;
 			monitor = "CRT";
 	}
 
 	printk(KERN_INFO "sgivwfb: %s monitor selected\n", monitor);
 
-	fb_info.fbops = &sgivwfb_ops;
-	fb_info.pseudo_palette = pseudo_palette;
-	fb_info.par = &default_par;
-	fb_info.flags = FBINFO_FLAG_DEFAULT;
+	info->fbops = &sgivwfb_ops;
+	info->pseudo_palette = (void *) (par + 1);
+	info->flags = FBINFO_DEFAULT;
 
-	fb_info.screen_base = ioremap_nocache((unsigned long) sgivwfb_mem_phys, sgivwfb_mem_size);
-	if (!fb_info.screen_base) {
+	info->screen_base = ioremap_nocache((unsigned long) sgivwfb_mem_phys, sgivwfb_mem_size);
+	if (!info->screen_base) {
 		printk(KERN_ERR "sgivwfb: couldn't ioremap screen_base\n");
 		goto fail_ioremap_fbmem;
 	}
 
-	fb_alloc_cmap(&fb_info.cmap, 256, 0);
+	if (fb_alloc_cmap(&info->cmap, 256, 0) < 0)
+		goto fail_color_map;
 
-	if (register_framebuffer(&fb_info) < 0) {
+	if (register_framebuffer(info) < 0) {
 		printk(KERN_ERR "sgivwfb: couldn't register framebuffer\n");
 		goto fail_register_framebuffer;
 	}
 
+	dev_set_drvdata(&dev->dev, info);
+
 	printk(KERN_INFO "fb%d: SGI DBE frame buffer device, using %ldK of video memory at %#lx\n",      
-		fb_info.node, sgivwfb_mem_size >> 10, sgivwfb_mem_phys);
+		info->node, sgivwfb_mem_size >> 10, sgivwfb_mem_phys);
 	return 0;
 
 fail_register_framebuffer:
-	iounmap((char *) fb_info.screen_base);
+	fb_dealloc_cmap(&info->cmap);
+fail_color_map:
+	iounmap((char *) info->screen_base);
 fail_ioremap_fbmem:
-	iounmap(default_par.regs);
+	iounmap(par->regs);
 fail_ioremap_regs:
 	release_mem_region(DBE_REG_PHYS, DBE_REG_SIZE);
+	framebuffer_release(info);
 	return -ENXIO;
 }
 
-#ifdef MODULE
-MODULE_LICENSE("GPL");
+static int sgivwfb_remove(struct device *device)
+{
+	struct fb_info *info = dev_get_drvdata(device);
+
+	if (info) {
+		struct sgivw_par *par = info->par;
+
+		unregister_framebuffer(info);
+		dbe_TurnOffDma(par);
+		iounmap(par->regs);
+		iounmap(info->screen_base);
+		release_mem_region(DBE_REG_PHYS, DBE_REG_SIZE);
+	}
+	return 0;
+}
 
-int init_module(void)
+static struct device_driver sgivwfb_driver = {
+	.name	= "sgivwfb",
+	.bus	= &platform_bus_type,
+	.probe	= sgivwfb_probe,
+	.remove	= sgivwfb_remove,
+};
+
+static struct platform_device sgivwfb_device = {
+	.name	= "sgivwfb",
+	.id	= 0,
+	.dev	= {
+		.release = sgivwfb_release,
+	}
+};
+
+int __init sgivwfb_init(void)
 {
-	return sgivwfb_init();
+	int ret;
+
+#ifndef MODULE
+	char *option = NULL;
+
+	if (fb_get_options("sgivwfb", &option))
+		return -ENODEV;
+	sgivwfb_setup(option);
+#endif
+	ret = driver_register(&sgivwfb_driver);
+	if (!ret) {
+		ret = platform_device_register(&sgivwfb_device);
+		if (ret)
+			driver_unregister(&sgivwfb_driver);
+	}
+	return ret;
 }
 
-void cleanup_module(void)
+module_init(sgivwfb_init);
+
+#ifdef MODULE
+MODULE_LICENSE("GPL");
+
+static void __exit sgivwfb_exit(void)
 {
-	unregister_framebuffer(&fb_info);
-	dbe_TurnOffDma();
-	iounmap(regs);
-	iounmap(&fb_info.screen_base);
-	release_mem_region(DBE_REG_PHYS, DBE_REG_SIZE);
+	platform_device_unregister(&sgivwfb_device);
+	driver_unregister(&sgivwfb_driver);
 }
+
+module_exit(sgivwfb_exit);
 
 #endif				/* MODULE */
diff -Nru a/drivers/video/sis/sis.h b/drivers/video/sis/sis.h
--- a/drivers/video/sis/sis.h	2004-10-18 14:56:48 -07:00
+++ b/drivers/video/sis/sis.h	2004-10-18 14:56:48 -07:00
@@ -360,10 +360,10 @@
 	unsigned long 	mmio_base;
 	unsigned long 	vga_base;
 
-	unsigned long  	video_vbase;
-	unsigned long 	mmio_vbase;
-	char  *	      	bios_vbase;
-	char  *	      	bios_abase;
+	void __iomem *	video_vbase;
+	void __iomem *	mmio_vbase;
+	void __iomem * 	bios_vbase;
+	void *		bios_abase;
 
 	int 		mtrr;
 
@@ -392,8 +392,8 @@
 #endif
 
 	u32 		heapstart;        /* offset  */
-	unsigned long  	sisfb_heap_start; /* address */
-	unsigned long  	sisfb_heap_end;   /* address */
+	void __iomem * 	sisfb_heap_start; /* address */
+	void __iomem * 	sisfb_heap_end;   /* address */
 	u32 	      	sisfb_heap_size;
 	int		havenoheap;
 #if 0
@@ -469,7 +469,7 @@
 	u8 		detectedpdca;
 	u8 		detectedlcda;
 
-	unsigned long 	hwcursor_vbase;
+	void __iomem * 	hwcursor_vbase;
 
 	int 		chronteltype;
 	int    		tvxpos, tvypos;
diff -Nru a/drivers/video/sis/sis_main.c b/drivers/video/sis/sis_main.c
--- a/drivers/video/sis/sis_main.c	2004-10-18 14:56:48 -07:00
+++ b/drivers/video/sis/sis_main.c	2004-10-18 14:56:48 -07:00
@@ -3952,19 +3952,19 @@
 }
 #endif
 
-static char * __devinit sis_find_rom(struct pci_dev *pdev)
+static void __iomem * __devinit sis_find_rom(struct pci_dev *pdev)
 {
 	struct sis_video_info *ivideo = pci_get_drvdata(pdev);
 
 #if defined(__i386__) || defined(__x86_64__)
         u32  segstart;
-        unsigned char *rom_base, *rom;
+	void __iomem *rom_base, *rom;
         int  romptr;
 	unsigned short pciid;
 
         for(segstart=0x000c0000; segstart<0x000f0000; segstart+=0x00001000) {
 
-            rom_base = (unsigned char *)ioremap(segstart, 0x10000);
+            rom_base = ioremap(segstart, 0x10000);
 	    if(!rom_base) continue;
 
 	    if((readb(rom_base) != 0x55) || (readb(rom_base + 1) != 0xaa)) {
@@ -3998,7 +3998,7 @@
 	    iounmap(rom_base);
         }
 #else
-	unsigned char *rom_base, *rom, *myrombase = NULL;
+	void __iomem *rom_base, *rom, *myrombase = NULL;
         int  romptr;
 	unsigned short pciid;
 	u32 backup;
@@ -4037,7 +4037,7 @@
 
 #ifdef CONFIG_FB_SIS_300
 static int __devinit
-sisfb_chkbuswidth300(struct pci_dev *pdev, ULONG FBAddress)
+sisfb_chkbuswidth300(struct pci_dev *pdev, void __iomem *FBAddress)
 {
 	struct sis_video_info *ivideo = pci_get_drvdata(pdev);
 	int i, j;
@@ -4080,7 +4080,7 @@
 sisfb_setramsize300(struct pci_dev *pdev)
 {
 	struct  sis_video_info *ivideo = pci_get_drvdata(pdev);
-  	ULONG 	FBAddr = (ULONG)ivideo->sishw_ext.pjVideoMemoryAddress, Addr;
+	void __iomem *FBAddr = ivideo->sishw_ext.pjVideoMemoryAddress, *Addr;
 	USHORT 	SR13, SR14=0, buswidth, Done, data, TotalCapacity, PhysicalAdrOtherPage=0;
 	int     PseudoRankCapacity, PseudoTotalCapacity, PseudoAdrPinCount;
    	int     RankCapacity, AdrPinCount, BankNumHigh, BankNumMid, MB2Bank;
@@ -4959,7 +4959,7 @@
 		ivideo->modeprechange = 0x03;
 #if defined(__i386__) || defined(__x86_64__)
 		{
-			unsigned char *tt = ioremap(0, 0x1000);
+			unsigned char __iomem *tt = ioremap(0, 0x1000);
 			if(tt) {
 			   	ivideo->modeprechange = tt[0x449];
 			   	iounmap(tt);
@@ -4993,7 +4993,8 @@
 	}
 #endif
 
-	ivideo->bios_vbase = ivideo->bios_abase = NULL;
+	ivideo->bios_abase = NULL;
+	ivideo->bios_vbase = NULL;
 	if(ivideo->sisfb_userom) {
 	    ivideo->sishw_ext.pjVirtualRomBase = sis_find_rom(pdev);
 #if defined(__i386__) || defined(__x86_64__)
@@ -5147,8 +5148,8 @@
 		return -ENODEV;
 	}
 
-	ivideo->video_vbase = (unsigned long)ioremap(ivideo->video_base, ivideo->video_size);
-	ivideo->sishw_ext.pjVideoMemoryAddress = (unsigned char *)ivideo->video_vbase;
+	ivideo->video_vbase = ioremap(ivideo->video_base, ivideo->video_size);
+	ivideo->sishw_ext.pjVideoMemoryAddress = ivideo->video_vbase;
 	if(!ivideo->video_vbase) {
 	   	printk(KERN_ERR "sisfb: Fatal error: Unable to map frame buffer memory\n");
 	   	release_mem_region(ivideo->video_base, ivideo->video_size);
@@ -5160,10 +5161,10 @@
 	   	return -ENODEV;
 	}
 
-	ivideo->mmio_vbase = (unsigned long)ioremap(ivideo->mmio_base, ivideo->mmio_size);
+	ivideo->mmio_vbase = ioremap(ivideo->mmio_base, ivideo->mmio_size);
 	if(!ivideo->mmio_vbase) {
 	   	printk(KERN_ERR "sisfb: Fatal error: Unable to map MMIO region\n");
-	   	iounmap((void *)ivideo->video_vbase);
+	   	iounmap(ivideo->video_vbase);
 	   	release_mem_region(ivideo->video_base, ivideo->video_size);
 	   	release_mem_region(ivideo->mmio_base, ivideo->mmio_size);
 		if(ivideo->bios_abase) vfree(ivideo->bios_abase);
@@ -5173,10 +5174,10 @@
 	   	return -ENODEV;
 	}
 
-	printk(KERN_INFO "sisfb: Framebuffer at 0x%lx, mapped to 0x%lx, size %ldk\n",
+	printk(KERN_INFO "sisfb: Framebuffer at 0x%lx, mapped to 0x%p, size %ldk\n",
 	       	ivideo->video_base, ivideo->video_vbase, ivideo->video_size / 1024);
 
-	printk(KERN_INFO "sisfb: MMIO at 0x%lx, mapped to 0x%lx, size %ldk\n",
+	printk(KERN_INFO "sisfb: MMIO at 0x%lx, mapped to 0x%p, size %ldk\n",
 	       	ivideo->mmio_base, ivideo->mmio_vbase, ivideo->mmio_size / 1024);
 
 	if((ivideo->havenoheap = sisfb_heap_init(ivideo))) {
@@ -5450,8 +5451,8 @@
 		if(SiSSetMode(&ivideo->SiS_Pr, &ivideo->sishw_ext, ivideo->mode_no) == 0) {
 			printk(KERN_ERR "sisfb: Fatal error: Setting mode[0x%x] failed\n",
 									ivideo->mode_no);
-			iounmap((void *)ivideo->video_vbase);
-			iounmap((void *)ivideo->mmio_vbase);
+			iounmap(ivideo->video_vbase);
+			iounmap(ivideo->mmio_vbase);
 			release_mem_region(ivideo->video_base, ivideo->video_size);
 			release_mem_region(ivideo->mmio_base, ivideo->mmio_size);
 			if(ivideo->bios_abase) vfree(ivideo->bios_abase);
@@ -5549,7 +5550,7 @@
 #endif
 		sis_fb_info->var = ivideo->default_var;
 		sis_fb_info->fix = ivideo->sisfb_fix;
-		sis_fb_info->screen_base = (char *)ivideo->video_vbase;
+		sis_fb_info->screen_base = ivideo->video_vbase;
 		sis_fb_info->fbops = &sisfb_ops;
 
 		sisfb_get_fix(&sis_fb_info->fix, -1, sis_fb_info);
@@ -5574,8 +5575,8 @@
 
 		if(register_framebuffer(sis_fb_info) < 0) {
 			printk(KERN_ERR "sisfb: Fatal error: Failed to register framebuffer\n");
-			iounmap((void *)ivideo->video_vbase);
-			iounmap((void *)ivideo->mmio_vbase);
+			iounmap(ivideo->video_vbase);
+			iounmap(ivideo->mmio_vbase);
 			release_mem_region(ivideo->video_base, ivideo->video_size);
 			release_mem_region(ivideo->mmio_base, ivideo->mmio_size);
 			if(ivideo->bios_abase) vfree(ivideo->bios_abase);
@@ -5669,8 +5670,8 @@
 #endif
 
 	/* Unmap */
-	iounmap((void *)ivideo->video_vbase);
-	iounmap((void *)ivideo->mmio_vbase);
+	iounmap(ivideo->video_vbase);
+	iounmap(ivideo->mmio_vbase);
 	if(ivideo->bios_vbase) iounmap(ivideo->bios_vbase);
 	if(ivideo->bios_abase)    vfree(ivideo->bios_abase);
 
@@ -5718,8 +5719,23 @@
 
 int __init sisfb_init(void)
 {
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,8)
+#ifndef MODULE
+	char *option = NULL;
+
+	if (fb_get_options("sisfb", &option))
+		return -ENODEV;
+	sisfb_setup(option);
+#endif
+#endif
 	return(pci_module_init(&sisfb_driver));
 }
+
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,8)
+#ifndef MODULE
+module_init(sisfb_init);
+#endif
+#endif
 
 /*****************************************************/
 /*                      MODULE                       */
diff -Nru a/drivers/video/sis/sis_main.h b/drivers/video/sis/sis_main.h
--- a/drivers/video/sis/sis_main.h	2004-10-18 14:56:27 -07:00
+++ b/drivers/video/sis/sis_main.h	2004-10-18 14:56:27 -07:00
@@ -880,7 +880,7 @@
 		      	struct fb_info *info);
 static void     sisfb_pre_setmode(struct sis_video_info *ivideo);
 static void     sisfb_post_setmode(struct sis_video_info *ivideo);
-static char *   sis_find_rom(struct pci_dev *pdev);
+static void __iomem *sis_find_rom(struct pci_dev *pdev);
 static BOOLEAN  sisfb_CheckVBRetrace(struct sis_video_info *ivideo);
 static BOOLEAN  sisfbcheckvretracecrt2(struct sis_video_info *ivideo);
 static BOOLEAN  sisfbcheckvretracecrt1(struct sis_video_info *ivideo);
diff -Nru a/drivers/video/skeletonfb.c b/drivers/video/skeletonfb.c
--- a/drivers/video/skeletonfb.c	2004-10-18 14:56:17 -07:00
+++ b/drivers/video/skeletonfb.c	2004-10-18 14:56:17 -07:00
@@ -583,6 +583,17 @@
 static void __exit xxxfb_cleanup(void)
 {
     /*
+     *  For kernel boot options (in 'video=xxxfb:<options>' format)
+     */
+#ifndef MODULE
+    char *option = NULL;
+
+    if (fb_get_options("xxxfb", &option))
+	    return -ENODEV;
+    xxxfb_setup(option);
+#endif
+
+    /*
      *  If your driver supports multiple boards, you should unregister and
      *  clean up all instances.
      */
@@ -639,9 +650,7 @@
      *  Modularization
      */
 
-#ifdef MODULE
 module_init(xxxfb_init);
-#endif 
 module_exit(xxxfb_cleanup);
 
 MODULE_LICENSE("GPL");
diff -Nru a/drivers/video/softcursor.c b/drivers/video/softcursor.c
--- a/drivers/video/softcursor.c	2004-10-18 14:56:32 -07:00
+++ b/drivers/video/softcursor.c	2004-10-18 14:56:32 -07:00
@@ -22,7 +22,8 @@
 	unsigned int scan_align = info->sprite.scan_align - 1;
 	unsigned int buf_align = info->sprite.buf_align - 1;
 	unsigned int i, size, dsize, s_pitch, d_pitch;
-	u8 *dst, src[64];
+	struct fb_cursor *cur;
+	u8 *dst, *src;
 
 	if (cursor->set & FB_CUR_SETSIZE) {
 		info->cursor.image.height = cursor->image.height;
@@ -48,9 +49,17 @@
 		info->cursor.image.depth = cursor->image.depth;
 	}	
 
+	info->cursor.image.data = cursor->image.data;
+
 	if (info->state != FBINFO_STATE_RUNNING)
 		return 0;
 
+	src = kmalloc(64 + sizeof(struct fb_cursor), GFP_ATOMIC);
+	if (!src)
+		return -ENOMEM;
+	cur = (struct fb_cursor *) (src + 64);
+	*cur = info->cursor;
+
 	s_pitch = (info->cursor.image.width + 7) >> 3;
 	dsize = s_pitch * info->cursor.image.height;
 	d_pitch = (s_pitch + scan_align) & ~scan_align;
@@ -79,9 +88,12 @@
 	else
 		fb_sysmove_buf_aligned(info, &info->sprite, dst, d_pitch, src,
 				   s_pitch, info->cursor.image.height);
-	info->cursor.image.data = dst;
+	cur->image.data = dst;
 	
-	info->fbops->fb_imageblit(info, &info->cursor.image);
+	info->fbops->fb_imageblit(info, &cur->image);
+
+	kfree(src);
+
 	return 0;
 }
 
diff -Nru a/drivers/video/sstfb.c b/drivers/video/sstfb.c
--- a/drivers/video/sstfb.c	2004-10-18 14:56:33 -07:00
+++ b/drivers/video/sstfb.c	2004-10-18 14:56:33 -07:00
@@ -1473,7 +1473,7 @@
 	f_ddprintk("membase_phys: %#lx\n", fix->smem_start);
 	f_ddprintk("fbbase_virt: %p\n", info->screen_base);
 
-	info->flags	= FBINFO_FLAG_DEFAULT;
+	info->flags	= FBINFO_DEFAULT;
 	info->fbops	= &sstfb_ops;
 	info->currcon	= -1;
 	info->pseudo_palette = &all->pseudo_palette;
@@ -1571,6 +1571,13 @@
 
 int __devinit sstfb_init(void)
 {
+#ifndef MODULE
+	char *option = NULL;
+
+	if (fb_get_options("sstfb", &option))
+		return -ENODEV;
+	sstfb_setup(option);
+#endif
 	return pci_module_init(&sstfb_driver);
 }
 
@@ -1693,9 +1700,9 @@
 	sstfb_drawrect_XY(info, 250, 250, 120, 100, 0xf800, idx);
 }
 
+module_init(sstfb_init);
 
 #ifdef MODULE
-module_init(sstfb_init);
 module_exit(sstfb_exit);
 #endif
 
diff -Nru a/drivers/video/stifb.c b/drivers/video/stifb.c
--- a/drivers/video/stifb.c	2004-10-18 14:57:19 -07:00
+++ b/drivers/video/stifb.c	2004-10-18 14:57:19 -07:00
@@ -1298,6 +1298,7 @@
 	    case 1:
 		fix->type = FB_TYPE_PLANES;	/* well, sort of */
 		fix->visual = FB_VISUAL_MONO10;
+		var->red.length = var->green.length = var->blue.length = 1;
 		break;
 	    case 8:
 		fix->type = FB_TYPE_PACKED_PIXELS;
@@ -1324,7 +1325,7 @@
 	strcpy(fix->id, "stifb");
 	info->fbops = &stifb_ops;
 	info->screen_base = (void*) REGION_BASE(fb,1);
-	info->flags = FBINFO_FLAG_DEFAULT;
+	info->flags = FBINFO_DEFAULT;
 	info->currcon = -1;
 
 	/* This has to been done !!! */
@@ -1376,11 +1377,21 @@
 static int stifb_disabled __initdata;
 
 int __init
+stifb_setup(char *options);
+
+int __init
 stifb_init(void)
 {
 	struct sti_struct *sti;
 	int i;
 	
+#ifndef MODULE
+	char *option = NULL;
+
+	if (fb_get_options("stifb", &option))
+		return -ENODEV;
+	stifb_setup(option);
+#endif
 	if (stifb_disabled) {
 		printk(KERN_INFO "stifb: disabled by \"stifb=off\" kernel parameter\n");
 		return -ENXIO;
@@ -1451,9 +1462,7 @@
 
 __setup("stifb=", stifb_setup);
 
-#ifdef MODULE
 module_init(stifb_init);
-#endif
 module_exit(stifb_cleanup);
 
 MODULE_AUTHOR("Helge Deller <deller@gmx.de>, Thomas Bogendoerfer <tsbogend@alpha.franken.de>");
diff -Nru a/drivers/video/tcx.c b/drivers/video/tcx.c
--- a/drivers/video/tcx.c	2004-10-18 14:55:46 -07:00
+++ b/drivers/video/tcx.c	2004-10-18 14:55:46 -07:00
@@ -412,7 +412,7 @@
 		all->par.mmap_map[i].poff = sdev->reg_addrs[j].phys_addr;
 	}
 
-	all->info.flags = FBINFO_FLAG_DEFAULT;
+	all->info.flags = FBINFO_DEFAULT;
 	all->info.fbops = &tcx_ops;
 #ifdef CONFIG_SPARC32
 	all->info.screen_base = (char *)
@@ -468,6 +468,9 @@
 	struct sbus_bus *sbus;
 	struct sbus_dev *sdev;
 
+	if (fb_get_options("tcxfb", NULL))
+		return -ENODEV;
+
 	for_all_sbusdev(sdev, sbus) {
 		if (!strcmp(sdev->prom_name, "tcx"))
 			tcx_init_one(sdev);
@@ -496,8 +499,9 @@
 	return 0;
 }
 
-#ifdef MODULE
 module_init(tcx_init);
+
+#ifdef MODULE
 module_exit(tcx_exit);
 #endif
 
diff -Nru a/drivers/video/tdfxfb.c b/drivers/video/tdfxfb.c
--- a/drivers/video/tdfxfb.c	2004-10-18 14:56:27 -07:00
+++ b/drivers/video/tdfxfb.c	2004-10-18 14:56:27 -07:00
@@ -1,4 +1,3 @@
-
 /*
  *
  * tdfxfb.c
@@ -126,8 +125,9 @@
 /*
  * PCI driver prototypes
  */
-static int tdfxfb_probe(struct pci_dev *pdev, const struct pci_device_id *id);
-static void tdfxfb_remove(struct pci_dev *pdev);
+static int __devinit tdfxfb_probe(struct pci_dev *pdev,
+				  const struct pci_device_id *id);
+static void __devexit tdfxfb_remove(struct pci_dev *pdev);
 
 static struct pci_device_id tdfxfb_id_table[] = {
 	{ PCI_VENDOR_ID_3DFX, PCI_DEVICE_ID_3DFX_BANSHEE,
@@ -155,7 +155,7 @@
  *  Frame buffer device API
  */
 int tdfxfb_init(void);
-void tdfxfb_setup(char *options, int *ints); 
+void tdfxfb_setup(char *options);
 
 static int tdfxfb_check_var(struct fb_var_screeninfo *var, struct fb_info *fb); 
 static int tdfxfb_set_par(struct fb_info *info); 
@@ -163,15 +163,12 @@
 			    u_int transp, struct fb_info *info); 
 static int tdfxfb_blank(int blank, struct fb_info *info); 
 static int tdfxfb_pan_display(struct fb_var_screeninfo *var, struct fb_info *info);
+static int banshee_wait_idle(struct fb_info *info);
+#ifdef CONFIG_FB_3DFX_ACCEL
 static void tdfxfb_fillrect(struct fb_info *info, const struct fb_fillrect *rect);
 static void tdfxfb_copyarea(struct fb_info *info, const struct fb_copyarea *area);  
 static void tdfxfb_imageblit(struct fb_info *info, const struct fb_image *image); 
-#ifdef CONFIG_FB_3DFX_ACCEL
-static int tdfxfb_cursor(struct fb_info *info, struct fb_cursor *cursor);
-#else /* !CONFIG_FB_3DFX_ACCEL */
-#define tdfxfb_cursor soft_cursor
 #endif /* CONFIG_FB_3DFX_ACCEL */
-static int banshee_wait_idle(struct fb_info *info);
 
 static struct fb_ops tdfxfb_ops = {
 	.owner		= THIS_MODULE,
@@ -180,11 +177,17 @@
 	.fb_setcolreg	= tdfxfb_setcolreg,
 	.fb_blank	= tdfxfb_blank,
 	.fb_pan_display	= tdfxfb_pan_display,
+	.fb_sync	= banshee_wait_idle,
+#ifdef CONFIG_FB_3DFX_ACCEL
 	.fb_fillrect	= tdfxfb_fillrect,
 	.fb_copyarea	= tdfxfb_copyarea,
 	.fb_imageblit	= tdfxfb_imageblit,
-	.fb_sync	= banshee_wait_idle,
-	.fb_cursor	= tdfxfb_cursor,
+#else
+	.fb_fillrect	= cfb_fillrect,
+	.fb_copyarea	= cfb_copyarea,
+	.fb_imageblit	= cfb_imageblit,
+#endif
+	.fb_cursor	= soft_cursor,
 };
 
 /*
@@ -497,23 +500,21 @@
 		return -EINVAL;
 	}
 
-	if (var->xres != var->xres_virtual) {
-		DPRINTK("virtual x resolution != physical x resolution not supported\n");
-		return -EINVAL;
-	}
+	if (var->xres != var->xres_virtual)
+		var->xres_virtual = var->xres;
 
-	if (var->yres > var->yres_virtual) {
-		DPRINTK("virtual y resolution < physical y resolution not possible\n");
-		return -EINVAL;
-	}
+	if (var->yres > var->yres_virtual)
+		var->yres_virtual = var->yres;
 
 	if (var->xoffset) {
 		DPRINTK("xoffset not supported\n");
 		return -EINVAL;
 	}
 
-	/* fixme: does Voodoo3 support interlace? Banshee doesn't */
-	if ((var->vmode & FB_VMODE_MASK) == FB_VMODE_INTERLACED) {
+	/* Banshee doesn't support interlace, but Voodoo4/5 and probably Voodoo3 do. */
+	/* no direct information about device id now? use max_pixclock for this... */
+	if (((var->vmode & FB_VMODE_MASK) == FB_VMODE_INTERLACED) &&
+			(par->max_pixclock < VOODOO3_MAX_PIXCLOCK)) {
 		DPRINTK("interlace not supported\n");
 		return -EINVAL;
 	}
@@ -532,9 +533,12 @@
 	}
   
 	if (lpitch * var->yres_virtual > info->fix.smem_len) {
-		DPRINTK("no memory for screen (%ux%ux%u)\n",
-		var->xres, var->yres_virtual, var->bits_per_pixel);
-		return -EINVAL;
+		var->yres_virtual = info->fix.smem_len/lpitch;
+		if (var->yres_virtual < var->yres) {
+			DPRINTK("no memory for screen (%ux%ux%u)\n",
+			var->xres, var->yres_virtual, var->bits_per_pixel);
+			return -EINVAL;
+		}
 	}
   
 	if (PICOS2KHZ(var->pixclock) > par->max_pixclock) {
@@ -584,7 +588,6 @@
 	int fout, freq;
 	u32 wd, cpp;
   
-	info->cmap.len = (info->var.bits_per_pixel == 8) ? 256 : 16;
 	par->baseline  = 0;
  
 	memset(&reg, 0, sizeof(reg));
@@ -620,10 +623,17 @@
 	hbs = hd;
 	hbe = ht;
 
-	vbs = vd = info->var.yres - 1;
-	vs  = vd + info->var.lower_margin;
-	ve  = vs + info->var.vsync_len;
-	vbe = vt = ve + info->var.upper_margin - 1;
+	if ((info->var.vmode & FB_VMODE_MASK) == FB_VMODE_DOUBLE) {
+		vbs = vd = (info->var.yres << 1) - 1;
+		vs  = vd + (info->var.lower_margin << 1);
+		ve  = vs + (info->var.vsync_len << 1);
+		vbe = vt = ve + (info->var.upper_margin << 1) - 1;
+	} else {
+		vbs = vd = info->var.yres - 1;
+		vs  = vd + info->var.lower_margin;
+		ve  = vs + info->var.vsync_len;
+		vbe = vt = ve + info->var.upper_margin - 1;
+	}
   
 	/* this is all pretty standard VGA register stuffing */
 	reg.misc[0x00] = 0x0f | 
@@ -746,8 +756,16 @@
 	reg.gfxpll = do_calc_pll(..., &fout);
 #endif
 
-	reg.screensize = info->var.xres | (info->var.yres << 12);
-	reg.vidcfg &= ~VIDCFG_HALF_MODE;
+	if ((info->var.vmode & FB_VMODE_MASK) == FB_VMODE_DOUBLE) {
+		reg.screensize = info->var.xres | (info->var.yres << 13);
+		reg.vidcfg |= VIDCFG_HALF_MODE;
+		reg.crt[0x09] |= 0x80;
+	} else {
+		reg.screensize = info->var.xres | (info->var.yres << 12);
+		reg.vidcfg &= ~VIDCFG_HALF_MODE;
+	}
+	if ((info->var.vmode & FB_VMODE_MASK) == FB_VMODE_INTERLACED)
+		reg.vidcfg |= VIDCFG_INTERLACE;
 	reg.miscinit0 = tdfx_inl(par, MISCINIT0);
 
 #if defined(__BIG_ENDIAN)
@@ -787,7 +805,7 @@
 	struct tdfx_par *par = (struct tdfx_par *) info->par;
 	u32 rgbcol;
    
-	if (regno >= info->cmap.len) return 1;
+	if (regno >= info->cmap.len || regno > 255) return 1;
    
 	switch (info->fix.visual) {
 		case FB_VISUAL_PSEUDOCOLOR:
@@ -876,6 +894,7 @@
 	return 0;
 }
 
+#ifdef CONFIG_FB_3DFX_ACCEL
 /*
  * FillRect 2D command (solidfill or invert (via ROP_XOR))   
  */
@@ -894,7 +913,11 @@
 
 	banshee_make_room(par, 5);
 	tdfx_outl(par,	DSTFORMAT, fmt);
-	tdfx_outl(par,	COLORFORE, rect->color);
+	if (info->fix.visual == FB_VISUAL_PSEUDOCOLOR) {
+		tdfx_outl(par,	COLORFORE, rect->color);
+	} else { /* FB_VISUAL_TRUECOLOR */
+		tdfx_outl(par, COLORFORE, ((u32*)(info->pseudo_palette))[rect->color]);
+	}
 	tdfx_outl(par,	COMMAND_2D, COMMAND_2D_FILLRECT | (tdfx_rop << 24));
 	tdfx_outl(par,	DSTSIZE,    rect->width | (rect->height << 16));
 	tdfx_outl(par,	LAUNCH_2D,  rect->dx | (rect->dy << 16));
@@ -1004,8 +1027,9 @@
 	}
 	banshee_wait_idle(info);
 }
+#endif /* CONFIG_FB_3DFX_ACCEL */
 
-#ifdef CONFIG_FB_3DFX_ACCEL
+#ifdef TDFX_HARDWARE_CURSOR
 static int tdfxfb_cursor(struct fb_info *info, struct fb_cursor *cursor)
 {
 	struct tdfx_par *par = (struct tdfx_par *) info->par;
@@ -1043,7 +1067,7 @@
 		struct fb_cmap cmap = cursor->image.cmap;
 		unsigned long bg_color, fg_color;
 
-		cmap.len = 2;/* Voodoo 3+ only support 2 color cursors*/
+		cmap.len = 2; /* Voodoo 3+ only support 2 color cursors */
 		fg_color = ((cmap.red[cmap.start] << 16) |
 			    (cmap.green[cmap.start] << 8)  |
 			    (cmap.blue[cmap.start]));
@@ -1101,7 +1125,7 @@
 		 */
 		u8 *cursorbase = (u8 *) info->cursor.image.data;
 		char *bitmap = (char *)cursor->image.data;
-		const char *mask = cursor->mask;
+		char *mask = (char *) cursor->mask;
 		int i, j, k, h = 0;
 
 		for (i = 0; i < 64; i++) {
@@ -1142,7 +1166,7 @@
 	spin_unlock_irqrestore(&par->DAClock, flags);
 	return 0;
 }
-#endif /* CONFIG_FB_3DFX_ACCEL */
+#endif
 
 /**
  *      tdfxfb_probe - Device Initializiation
@@ -1158,22 +1182,20 @@
 {
 	struct tdfx_par *default_par;
 	struct fb_info *info;
-	int size, err;
+	int size, err, lpitch;
 
 	if ((err = pci_enable_device(pdev))) {
 		printk(KERN_WARNING "tdfxfb: Can't enable pdev: %d\n", err);
 		return err;
 	}
 
-	size = sizeof(struct fb_info)+sizeof(struct tdfx_par)+16*sizeof(u32);
+	size = sizeof(struct tdfx_par)+256*sizeof(u32);
 
-	info = kmalloc(size, GFP_KERNEL);
+	info = framebuffer_alloc(size, &pdev->dev);
 
 	if (!info)	return -ENOMEM;
 		
-	memset(info, 0, size);
-    
-	default_par = (struct tdfx_par *) (info + 1);
+	default_par = info->par;
  
 	/* Configure the default fb_fix_screeninfo first */
 	switch (pdev->device) {
@@ -1251,24 +1273,44 @@
    
 	info->fbops		= &tdfxfb_ops;
 	info->fix		= tdfx_fix; 	
-	info->par		= default_par;
 	info->pseudo_palette	= (void *)(default_par + 1); 
-	info->flags		= FBINFO_FLAG_DEFAULT;
+	info->flags		= FBINFO_DEFAULT | FBINFO_HWACCEL_YPAN;
+#ifdef CONFIG_FB_3DFX_ACCEL
+	info->flags             |= FBINFO_HWACCEL_FILLRECT |
+		FBINFO_HWACCEL_COPYAREA | FBINFO_HWACCEL_IMAGEBLIT;
+#endif
 
-#ifndef MODULE
 	if (!mode_option)
 		mode_option = "640x480@60";
 	 
 	err = fb_find_mode(&info->var, info, mode_option, NULL, 0, NULL, 8); 
 	if (!err || err == 4)
-#endif
 		info->var = tdfx_var;
 
-	size = (info->var.bits_per_pixel == 8) ? 256 : 16;
-	fb_alloc_cmap(&info->cmap, size, 0);  
+	/* maximize virtual vertical length */
+	lpitch = info->var.xres_virtual * ((info->var.bits_per_pixel + 7) >> 3);
+	info->var.yres_virtual = info->fix.smem_len/lpitch;
+	if (info->var.yres_virtual < info->var.yres)
+		goto out_err;
+
+#ifdef CONFIG_FB_3DFX_ACCEL
+	/*
+	 * FIXME: Limit var->yres_virtual to 4096 because of screen artifacts
+	 * during scrolling. This is only present if 2D acceleration is
+	 * enabled.
+	 */
+	if (info->var.yres_virtual > 4096)
+		info->var.yres_virtual = 4096;
+#endif /* CONFIG_FB_3DFX_ACCEL */
+
+	if (fb_alloc_cmap(&info->cmap, 256, 0) < 0) {
+		printk(KERN_WARNING "tdfxfb: Can't allocate color map\n");
+		goto out_err;
+	}
 
 	if (register_framebuffer(info) < 0) {
 		printk("tdfxfb: can't register framebuffer\n");
+		fb_dealloc_cmap(&info->cmap);
 		goto out_err;
 	}
 	/*
@@ -1285,7 +1327,7 @@
 		iounmap(default_par->regbase_virt);
 	if (info->screen_base)
 		iounmap(info->screen_base);
-	kfree(info);
+	framebuffer_release(info);
 	return -ENXIO;
 }
 
@@ -1315,11 +1357,19 @@
 	release_mem_region(pci_resource_start(pdev, 0),
 			   pci_resource_len(pdev, 0));
 	pci_set_drvdata(pdev, NULL);
-	kfree(info);
+	framebuffer_release(info);
 }
 
 int __init tdfxfb_init(void)
 {
+#ifndef MODULE
+	char *option = NULL;
+
+	if (fb_get_options("tdfxfb", &option))
+		return -ENODEV;
+
+	tdfxfb_setup(option);
+#endif
         return pci_module_init(&tdfxfb_driver);
 }
 
@@ -1332,14 +1382,12 @@
 MODULE_DESCRIPTION("3Dfx framebuffer device driver");
 MODULE_LICENSE("GPL");
  
-#ifdef MODULE
 module_init(tdfxfb_init);
-#endif
 module_exit(tdfxfb_exit);
 
 
 #ifndef MODULE
-void tdfxfb_setup(char *options, int *ints)
+void tdfxfb_setup(char *options)
 { 
 	char* this_opt;
 
diff -Nru a/drivers/video/tgafb.c b/drivers/video/tgafb.c
--- a/drivers/video/tgafb.c	2004-10-18 14:56:48 -07:00
+++ b/drivers/video/tgafb.c	2004-10-18 14:56:48 -07:00
@@ -1426,7 +1426,8 @@
 	pci_read_config_byte(pdev, PCI_REVISION_ID, &all->par.tga_chip_rev);
 
 	/* Setup framebuffer.  */
-	all->info.flags = FBINFO_FLAG_DEFAULT;
+	all->info.flags = FBINFO_DEFAULT | FBINFO_HWACCEL_COPYAREA |
+                          FBINFO_HWACCEL_IMAGEBLIT | FBINFO_HWACCEL_FILLRECT;
 	all->info.fbops = &tgafb_ops;
 	all->info.screen_base = (char *) all->par.tga_fb_base;
 	all->info.currcon = -1;
@@ -1476,12 +1477,6 @@
 	return ret;
 }
 
-int __init
-tgafb_init(void)
-{
-	return pci_module_init(&tgafb_driver);
-}
-
 #ifdef MODULE
 static void __exit
 tgafb_pci_unregister(struct pci_dev *pdev)
@@ -1528,12 +1523,26 @@
 }
 #endif /* !MODULE */
 
+int __init
+tgafb_init(void)
+{
+#ifndef MODULE
+	char *option = NULL;
+
+	if (fb_get_options("tgafb", &option))
+		return -ENODEV;
+	tgafb_setup(option);
+#endif
+	return pci_module_init(&tgafb_driver);
+}
+
 /*
  *  Modularisation
  */
 
-#ifdef MODULE
 module_init(tgafb_init);
+
+#ifdef MODULE
 module_exit(tgafb_exit);
 #endif
 
diff -Nru a/drivers/video/tridentfb.c b/drivers/video/tridentfb.c
--- a/drivers/video/tridentfb.c	2004-10-18 14:56:32 -07:00
+++ b/drivers/video/tridentfb.c	2004-10-18 14:56:32 -07:00
@@ -28,7 +28,7 @@
 
 struct tridentfb_par {
 	int vclk;		//in MHz
-	unsigned long io_virt;	//iospace virtual memory address
+	void __iomem * io_virt;	//iospace virtual memory address
 };
 
 unsigned char eng_oper;		//engine operation...
@@ -1107,7 +1107,7 @@
 		return -1;
 	}
 
-	default_par.io_virt = (unsigned long)ioremap_nocache(tridentfb_fix.mmio_start, tridentfb_fix.mmio_len);
+	default_par.io_virt = ioremap_nocache(tridentfb_fix.mmio_start, tridentfb_fix.mmio_len);
 
 	if (!default_par.io_virt) {
 		release_region(tridentfb_fix.mmio_start, tridentfb_fix.mmio_len);
@@ -1149,7 +1149,10 @@
 	fb_info.fbops = &tridentfb_ops;
 
 
-	fb_info.flags = FBINFO_FLAG_DEFAULT;
+	fb_info.flags = FBINFO_DEFAULT | FBINFO_HWACCEL_YPAN;
+#ifdef CONFIG_FB_TRIDENT_ACCEL
+	fb_info.flags |= FBINFO_HWACCEL_COPYAREA | FBINFO_HWACCEL_FILLRECT;
+#endif
 	fb_info.pseudo_palette = pseudo_pal;
 
 	if (!fb_find_mode(&default_var,&fb_info,mode,NULL,0,NULL,bpp))
@@ -1175,8 +1178,8 @@
 {
 	struct tridentfb_par *par = (struct tridentfb_par*)fb_info.par;
 	unregister_framebuffer(&fb_info);
-	iounmap((void *)par->io_virt);
-	iounmap((void*)fb_info.screen_base);
+	iounmap(par->io_virt);
+	iounmap(fb_info.screen_base);
 	release_mem_region(tridentfb_fix.smem_start, tridentfb_fix.smem_len);
 	release_region(tridentfb_fix.mmio_start, tridentfb_fix.mmio_len);
 }
@@ -1215,8 +1218,17 @@
 	.remove		= __devexit_p(trident_pci_remove)
 };
 
+int tridentfb_setup(char *options);
+
 int __init tridentfb_init(void)
 {
+#ifndef MODULE
+	char *option = NULL;
+
+	if (fb_get_options("tridentfb", &option))
+		return -ENODEV;
+	tridentfb_setup(option);
+#endif
 	output("Trident framebuffer %s initializing\n", VERSION);
 	return pci_module_init(&tridentfb_pci_driver);
 }
@@ -1276,9 +1288,7 @@
 	.fb_cursor = soft_cursor,
 };
 
-#ifdef MODULE
 module_init(tridentfb_init);
-#endif
 module_exit(tridentfb_exit);
 
 MODULE_AUTHOR("Jani Monoses <jani@iv.ro>");
diff -Nru a/drivers/video/tx3912fb.c b/drivers/video/tx3912fb.c
--- a/drivers/video/tx3912fb.c	2004-10-18 14:56:33 -07:00
+++ b/drivers/video/tx3912fb.c	2004-10-18 14:56:33 -07:00
@@ -60,6 +60,9 @@
 	.blue =		{ 0, 2, 0 },
 #else
 	.bits_per_pixel =4,
+	.red =		{ 0, 4, 0 },	/* ??? */
+	.green =	{ 0, 4, 0 },
+	.blue =		{ 0, 4, 0 },
 #endif
 	.activate =	FB_ACTIVATE_NOW,
 	.width =	-1,
@@ -205,6 +208,8 @@
 	return 0;
 }
 
+int __init tx3912fb_setup(char *options);
+
 /*
  * Initialization of the framebuffer
  */
@@ -212,6 +217,11 @@
 {
 	u_long tx3912fb_paddr = 0;
 	int size = (info->var.bits_per_pixel == 8) ? 256 : 16;
+	char *option = NULL;
+
+	if (fb_get_options("tx3912fb", &option))
+		return -ENODEV;
+	tx3912fb_setup(option);
 
 	/* Disable the video logic */
 	outl(inl(TX3912_VIDEO_CTRL1) &
@@ -296,7 +306,7 @@
 	fb_info.var = tx3912fb_var;
 	fb_info.fix = tx3912fb_fix;
 	fb_info.pseudo_palette = pseudo_palette;
-	fb_info.flags = FBINFO_FLAG_DEFAULT;
+	fb_info.flags = FBINFO_DEFAULT;
 
 	/* Clear the framebuffer */
 	memset((void *) fb_info.fix.smem_start, 0xff, fb_info.fix.smem_len);
@@ -326,4 +336,5 @@
 	return 0;
 }
 
+module_init(tx3912fb_init);
 MODULE_LICENSE("GPL");
diff -Nru a/drivers/video/valkyriefb.c b/drivers/video/valkyriefb.c
--- a/drivers/video/valkyriefb.c	2004-10-18 14:56:50 -07:00
+++ b/drivers/video/valkyriefb.c	2004-10-18 14:56:50 -07:00
@@ -322,6 +322,11 @@
 	struct fb_info_valkyrie	*p;
 	unsigned long frame_buffer_phys, cmap_regs_phys, flags;
 	int err;
+	char *option = NULL;
+
+	if (fb_get_options("valkyriefb", &option))
+		return -ENODEV;
+	valkyriefb_setup(option);
 
 #ifdef CONFIG_MAC
 	if (!MACH_IS_MAC)
@@ -540,7 +545,7 @@
 {
 	info->fbops = &valkyriefb_ops;
 	info->screen_base = (char *) p->frame_buffer + 0x1000;
-	info->flags = FBINFO_FLAG_DEFAULT;
+	info->flags = FBINFO_DEFAULT;
 	info->pseudo_palette = p->pseudo_palette;
 	fb_alloc_cmap(&info->cmap, 256, 0);
 	info->par = &p->par;
@@ -579,4 +584,5 @@
 	return 0;
 }
 
+module_init(valkyriefb_init);
 MODULE_LICENSE("GPL");
diff -Nru a/drivers/video/vesafb.c b/drivers/video/vesafb.c
--- a/drivers/video/vesafb.c	2004-10-18 14:55:54 -07:00
+++ b/drivers/video/vesafb.c	2004-10-18 14:55:54 -07:00
@@ -87,15 +87,17 @@
 	return 0;
 }
 
-static void vesa_setpalette(int regno, unsigned red, unsigned green, unsigned blue)
+static void vesa_setpalette(int regno, unsigned red, unsigned green,
+			    unsigned blue, struct fb_var_screeninfo *var)
 {
 #ifdef __i386__
 	struct { u_char blue, green, red, pad; } entry;
+	int shift = 16 - var->green.length;
 
 	if (pmi_setpal) {
-		entry.red   = red   >> 10;
-		entry.green = green >> 10;
-		entry.blue  = blue  >> 10;
+		entry.red   = red   >> shift;
+		entry.green = green >> shift;
+		entry.blue  = blue  >> shift;
 		entry.pad   = 0;
 	        __asm__ __volatile__(
                 "call *(%%esi)"
@@ -109,9 +111,9 @@
 	} else {
 		/* without protected mode interface, try VGA registers... */
 		outb_p(regno,       dac_reg);
-		outb_p(red   >> 10, dac_val);
-		outb_p(green >> 10, dac_val);
-		outb_p(blue  >> 10, dac_val);
+		outb_p(red   >> shift, dac_val);
+		outb_p(green >> shift, dac_val);
+		outb_p(blue  >> shift, dac_val);
 	}
 #endif
 }
@@ -132,7 +134,7 @@
 
 	switch (info->var.bits_per_pixel) {
 	case 8:
-		vesa_setpalette(regno,red,green,blue);
+		vesa_setpalette(regno,red,green,blue, &info->var);
 		break;
 	case 16:
 		if (info->var.red.offset == 10) {
@@ -331,30 +333,26 @@
 	vesafb_defined.left_margin  = (vesafb_defined.xres / 8) & 0xf8;
 	vesafb_defined.hsync_len    = (vesafb_defined.xres / 8) & 0xf8;
 	
-	if (vesafb_defined.bits_per_pixel > 8) {
-		vesafb_defined.red.offset    = screen_info.red_pos;
-		vesafb_defined.red.length    = screen_info.red_size;
-		vesafb_defined.green.offset  = screen_info.green_pos;
-		vesafb_defined.green.length  = screen_info.green_size;
-		vesafb_defined.blue.offset   = screen_info.blue_pos;
-		vesafb_defined.blue.length   = screen_info.blue_size;
-		vesafb_defined.transp.offset = screen_info.rsvd_pos;
-		vesafb_defined.transp.length = screen_info.rsvd_size;
-		printk(KERN_INFO "vesafb: directcolor: "
-		       "size=%d:%d:%d:%d, shift=%d:%d:%d:%d\n",
-		       screen_info.rsvd_size,
-		       screen_info.red_size,
-		       screen_info.green_size,
-		       screen_info.blue_size,
-		       screen_info.rsvd_pos,
-		       screen_info.red_pos,
-		       screen_info.green_pos,
-		       screen_info.blue_pos);
-	} else {
-		vesafb_defined.red.length   = 6;
-		vesafb_defined.green.length = 6;
-		vesafb_defined.blue.length  = 6;
-	}
+	vesafb_defined.red.offset    = screen_info.red_pos;
+	vesafb_defined.red.length    = screen_info.red_size;
+	vesafb_defined.green.offset  = screen_info.green_pos;
+	vesafb_defined.green.length  = screen_info.green_size;
+	vesafb_defined.blue.offset   = screen_info.blue_pos;
+	vesafb_defined.blue.length   = screen_info.blue_size;
+	vesafb_defined.transp.offset = screen_info.rsvd_pos;
+	vesafb_defined.transp.length = screen_info.rsvd_size;
+	printk(KERN_INFO "vesafb: %s: "
+	       "size=%d:%d:%d:%d, shift=%d:%d:%d:%d\n",
+	       (vesafb_defined.bits_per_pixel > 8) ?
+	       "Truecolor" : "Pseudocolor",
+	       screen_info.rsvd_size,
+	       screen_info.red_size,
+	       screen_info.green_size,
+	       screen_info.blue_size,
+	       screen_info.rsvd_pos,
+	       screen_info.red_pos,
+	       screen_info.green_pos,
+	       screen_info.blue_pos);
 
 	vesafb_fix.ypanstep  = ypan     ? 1 : 0;
 	vesafb_fix.ywrapstep = (ypan>1) ? 1 : 0;
@@ -412,7 +410,11 @@
 int __init vesafb_init(void)
 {
 	int ret;
+	char *option = NULL;
 
+	/* ignore error return of fb_get_options */
+	fb_get_options("vesafb", &option);
+	vesafb_setup(option);
 	ret = driver_register(&vesafb_driver);
 
 	if (!ret) {
@@ -422,6 +424,7 @@
 	}
 	return ret;
 }
+module_init(vesafb_init);
 
 /*
  * Overrides for Emacs so that we follow Linus's tabbing style.
diff -Nru a/drivers/video/vfb.c b/drivers/video/vfb.c
--- a/drivers/video/vfb.c	2004-10-18 14:55:46 -07:00
+++ b/drivers/video/vfb.c	2004-10-18 14:55:46 -07:00
@@ -496,6 +496,14 @@
 {
 	int ret = 0;
 
+#ifndef MODULE
+	char *option = NULL;
+
+	if (fb_get_options("vfb", &option))
+		return -ENODEV;
+	vfb_setup(option);
+#endif
+
 	if (!vfb_enable)
 		return -ENXIO;
 
@@ -509,6 +517,8 @@
 	return ret;
 }
 
+module_init(vfb_init);
+
 #ifdef MODULE
 static void __exit vfb_exit(void)
 {
@@ -516,7 +526,6 @@
 	driver_unregister(&vfb_driver);
 }
 
-module_init(vfb_init);
 module_exit(vfb_exit);
 
 MODULE_LICENSE("GPL");
diff -Nru a/drivers/video/vga16fb.c b/drivers/video/vga16fb.c
--- a/drivers/video/vga16fb.c	2004-10-18 14:56:27 -07:00
+++ b/drivers/video/vga16fb.c	2004-10-18 14:56:27 -07:00
@@ -1342,7 +1342,14 @@
 {
 	int i;
 	int ret;
+#ifndef MODULE
+	char *option = NULL;
 
+	if (fb_get_options("vga16fb", &option))
+		return -ENODEV;
+
+	vga16fb_setup(option);
+#endif
 	printk(KERN_DEBUG "vga16fb: initializing\n");
 
 	/* XXX share VGA_FB_PHYS and I/O region with vgacon and others */
@@ -1418,8 +1425,8 @@
 
 #ifdef MODULE
 MODULE_LICENSE("GPL");
-module_init(vga16fb_init);
 #endif
+module_init(vga16fb_init);
 module_exit(vga16fb_exit);
 
 
diff -Nru a/drivers/video/vgastate.c b/drivers/video/vgastate.c
--- a/drivers/video/vgastate.c	2004-10-18 14:56:29 -07:00
+++ b/drivers/video/vgastate.c	2004-10-18 14:56:29 -07:00
@@ -32,21 +32,21 @@
 	__u8 misc;
 };	
 
-static inline unsigned char vga_rcrtcs(caddr_t regbase, unsigned short iobase, 
+static inline unsigned char vga_rcrtcs(void __iomem *regbase, unsigned short iobase, 
 				       unsigned char reg)
 {
 	vga_w(regbase, iobase + 0x4, reg);
 	return vga_r(regbase, iobase + 0x5);
 }
 
-static inline void vga_wcrtcs(caddr_t regbase, unsigned short iobase, 
+static inline void vga_wcrtcs(void __iomem *regbase, unsigned short iobase, 
 			      unsigned char reg, unsigned char val)
 {
 	vga_w(regbase, iobase + 0x4, reg);
 	vga_w(regbase, iobase + 0x5, val);
 }
 
-static void save_vga_text(struct vgastate *state, caddr_t fbbase)
+static void save_vga_text(struct vgastate *state, void __iomem *fbbase)
 {
 	struct regstate *saved = (struct regstate *) state->vidstate;
 	int i;
@@ -134,7 +134,7 @@
 	vga_wseq(state->vgabase, VGA_SEQ_CLOCK_MODE, seq1);
 }
 
-static void restore_vga_text(struct vgastate *state, caddr_t fbbase)
+static void restore_vga_text(struct vgastate *state, void __iomem *fbbase)
 {
 	struct regstate *saved = (struct regstate *) state->vidstate;
 	int i;
@@ -403,7 +403,7 @@
 	}
 
 	if (state->flags & VGA_SAVE_FONTS) {
-		caddr_t fbbase;
+		void __iomem *fbbase;
 
 		/* exit if window is less than 32K */
 		if (state->memsize && state->memsize < 4 * 8192) {
@@ -473,7 +473,7 @@
 		restore_vga_mode(state);
 
 	if (state->flags & VGA_SAVE_FONTS) {
-		caddr_t fbbase = ioremap(state->membase, state->memsize);
+		void __iomem *fbbase = ioremap(state->membase, state->memsize);
 
 		if (!fbbase) {
 			vga_cleanup(state);
diff -Nru a/drivers/w1/Kconfig b/drivers/w1/Kconfig
--- a/drivers/w1/Kconfig	2004-10-18 14:56:49 -07:00
+++ b/drivers/w1/Kconfig	2004-10-18 14:56:49 -07:00
@@ -21,11 +21,37 @@
 	  This support is also available as a module.  If so, the module 
 	  will be called matrox_w1.ko.
 
+config W1_DS9490
+	tristate "DS9490R transport layer driver"
+	depends on W1 && USB
+	help
+	  Say Y here if you want to have a driver for DS9490R UWB <-> W1 bridge.
+
+	  This support is also available as a module.  If so, the module 
+	  will be called ds9490r.ko.
+
+config W1_DS9490R_BRIDGE
+	tristate "DS9490R USB <-> W1 transport layer for 1-wire"
+	depends on W1_DS9490
+	help
+	  Say Y here if you want to communicate with your 1-wire devices
+	  using DS9490R USB bridge.
+
+	  This support is also available as a module.  If so, the module 
+	  will be called ds_w1_bridge.ko.
+
 config W1_THERM
 	tristate "Thermal family implementation"
 	depends on W1
 	help
 	  Say Y here if you want to connect 1-wire thermal sensors to you
 	  wire.
+
+config W1_SMEM
+	tristate "Simple 64bit memory family implementation"
+	depends on W1
+	help
+	  Say Y here if you want to connect 1-wire 
+	  simple 64bit memory rom(ds2401/ds2411/ds1990*) to you wire.
 
 endmenu
diff -Nru a/drivers/w1/Makefile b/drivers/w1/Makefile
--- a/drivers/w1/Makefile	2004-10-18 14:56:31 -07:00
+++ b/drivers/w1/Makefile	2004-10-18 14:56:31 -07:00
@@ -7,3 +7,10 @@
 
 obj-$(CONFIG_W1_MATROX)		+= matrox_w1.o
 obj-$(CONFIG_W1_THERM)		+= w1_therm.o
+obj-$(CONFIG_W1_SMEM)		+= w1_smem.o
+
+obj-$(CONFIG_W1_DS9490)		+= ds9490r.o 
+ds9490r-objs    := dscore.o
+
+obj-$(CONFIG_W1_DS9490_BRIDGE)	+= ds_w1_bridge.o
+
diff -Nru a/drivers/w1/ds_w1_bridge.c b/drivers/w1/ds_w1_bridge.c
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/drivers/w1/ds_w1_bridge.c	2004-10-18 14:57:21 -07:00
@@ -0,0 +1,174 @@
+/*
+ * 	ds_w1_bridge.c
+ *
+ * Copyright (c) 2004 Evgeniy Polyakov <johnpol@2ka.mipt.ru>
+ * 
+ *
+ * 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
+ */
+
+#include <linux/module.h>
+#include <linux/types.h>
+
+#include "../w1/w1.h"
+#include "../w1/w1_int.h"
+#include "dscore.h"
+	
+static struct ds_device *ds_dev;
+static struct w1_bus_master *ds_bus_master;
+
+static u8 ds9490r_touch_bit(unsigned long data, u8 bit)
+{
+	u8 ret;
+	struct ds_device *dev = (struct ds_device *)data;
+
+	if (ds_touch_bit(dev, bit, &ret))
+		return 0;
+
+	return ret;
+}
+
+static void ds9490r_write_bit(unsigned long data, u8 bit)
+{
+	struct ds_device *dev = (struct ds_device *)data;
+
+	ds_write_bit(dev, bit);
+}
+
+static void ds9490r_write_byte(unsigned long data, u8 byte)
+{
+	struct ds_device *dev = (struct ds_device *)data;
+
+	ds_write_byte(dev, byte);
+}
+
+static u8 ds9490r_read_bit(unsigned long data)
+{
+	struct ds_device *dev = (struct ds_device *)data;
+	int err;
+	u8 bit = 0;
+
+	err = ds_touch_bit(dev, 1, &bit);
+	if (err)
+		return 0;
+	//err = ds_read_bit(dev, &bit);
+	//if (err)
+	//	return 0;
+
+	return bit & 1;
+}
+
+static u8 ds9490r_read_byte(unsigned long data)
+{
+	struct ds_device *dev = (struct ds_device *)data;
+	int err;
+	u8 byte = 0;
+
+	err = ds_read_byte(dev, &byte);
+	if (err)
+		return 0;
+
+	return byte;
+}
+
+static void ds9490r_write_block(unsigned long data, u8 *buf, int len)
+{
+	struct ds_device *dev = (struct ds_device *)data;
+
+	ds_write_block(dev, buf, len);
+}
+
+static u8 ds9490r_read_block(unsigned long data, u8 *buf, int len)
+{
+	struct ds_device *dev = (struct ds_device *)data;
+	int err;
+
+	err = ds_read_block(dev, buf, len);
+	if (err < 0)
+		return 0;
+
+	return len;
+}
+
+static u8 ds9490r_reset(unsigned long data)
+{
+	struct ds_device *dev = (struct ds_device *)data;
+	struct ds_status st;
+	int err;
+
+	memset(&st, 0, sizeof(st));
+
+	err = ds_reset(dev, &st);
+	if (err)
+		return 1;
+
+	return 0;
+}
+
+static int __devinit ds_w1_init(void)
+{
+	int err;
+	
+	ds_bus_master = kmalloc(sizeof(*ds_bus_master), GFP_KERNEL);
+	if (!ds_bus_master) {
+		printk(KERN_ERR "Failed to allocate DS9490R USB<->W1 bus_master structure.\n");
+		return -ENOMEM;
+	}
+
+	ds_dev = ds_get_device();
+	if (!ds_dev) {
+		printk(KERN_ERR "DS9490R is not registered.\n");
+		err =  -ENODEV;
+		goto err_out_free_bus_master;
+	}
+
+	memset(ds_bus_master, 0, sizeof(*ds_bus_master));
+
+	ds_bus_master->data 		= (unsigned long)ds_dev;
+	ds_bus_master->touch_bit 	= &ds9490r_touch_bit;
+	ds_bus_master->read_bit 	= &ds9490r_read_bit;
+	ds_bus_master->write_bit 	= &ds9490r_write_bit;
+	ds_bus_master->read_byte 	= &ds9490r_read_byte;
+	ds_bus_master->write_byte 	= &ds9490r_write_byte;
+	ds_bus_master->read_block 	= &ds9490r_read_block;
+	ds_bus_master->write_block 	= &ds9490r_write_block;
+	ds_bus_master->reset_bus	= &ds9490r_reset;
+
+	err = w1_add_master_device(ds_bus_master);
+	if (err)
+		goto err_out_put_device;
+
+	return 0;
+
+err_out_put_device:
+	ds_put_device(ds_dev);
+err_out_free_bus_master:
+	kfree(ds_bus_master);
+
+	return err;
+}
+
+static void __devexit ds_w1_fini(void)
+{
+	w1_remove_master_device(ds_bus_master);
+	ds_put_device(ds_dev);
+	kfree(ds_bus_master);
+}
+
+module_init(ds_w1_init);
+module_exit(ds_w1_fini);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Evgeniy Polyakov <johnpol@2ka.mipt.ru>");
diff -Nru a/drivers/w1/dscore.c b/drivers/w1/dscore.c
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/drivers/w1/dscore.c	2004-10-18 14:57:24 -07:00
@@ -0,0 +1,783 @@
+/*
+ * 	dscore.c
+ *
+ * Copyright (c) 2004 Evgeniy Polyakov <johnpol@2ka.mipt.ru>
+ * 
+ *
+ * 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
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/mod_devicetable.h>
+#include <linux/usb.h>
+
+#include "dscore.h"
+
+static struct usb_device_id ds_id_table [] = {
+	{ USB_DEVICE(0x04fa, 0x2490) },
+	{ },
+};
+MODULE_DEVICE_TABLE(usb, ds_id_table);
+
+int ds_probe(struct usb_interface *, const struct usb_device_id *);
+void ds_disconnect(struct usb_interface *);
+
+inline int ds_touch_bit(struct ds_device *, u8, u8 *);
+inline int ds_read_byte(struct ds_device *, u8 *);
+inline int ds_read_bit(struct ds_device *, u8 *);
+inline int ds_write_byte(struct ds_device *, u8);
+inline int ds_write_bit(struct ds_device *, u8);
+inline int ds_start_pulse(struct ds_device *, int);
+inline int ds_set_speed(struct ds_device *, int);
+inline int ds_reset(struct ds_device *, struct ds_status *);
+inline int ds_detect(struct ds_device *, struct ds_status *);
+inline int ds_stop_pulse(struct ds_device *, int);
+inline int ds_send_data(struct ds_device *, unsigned char *, int);
+inline int ds_recv_data(struct ds_device *, unsigned char *, int);
+inline int ds_recv_status(struct ds_device *, struct ds_status *);
+inline struct ds_device * ds_get_device(void);
+inline void ds_put_device(struct ds_device *);
+
+static inline void ds_dump_status(unsigned char *, unsigned char *, int);
+static inline int ds_send_control(struct ds_device *, u16, u16);
+static inline int ds_send_control_mode(struct ds_device *, u16, u16);
+static inline int ds_send_control_cmd(struct ds_device *, u16, u16);
+
+
+static struct usb_driver ds_driver = {
+	.owner =	THIS_MODULE,
+	.name =		"DS9490R",
+	.probe =	ds_probe,
+	.disconnect =	ds_disconnect,
+	.id_table =	ds_id_table,
+};
+
+static struct ds_device *ds_dev;
+
+struct ds_device * ds_get_device(void)
+{
+	if (ds_dev)
+		atomic_inc(&ds_dev->refcnt);
+	return ds_dev;
+}
+
+void ds_put_device(struct ds_device *dev)
+{
+	atomic_dec(&dev->refcnt);
+}
+
+static int ds_send_control_cmd(struct ds_device *dev, u16 value, u16 index)
+{
+	int err;
+	
+	err = usb_control_msg(dev->udev, usb_sndctrlpipe(dev->udev, dev->ep[EP_CONTROL]), 
+			CONTROL_CMD, 0x40, value, index, NULL, 0, HZ);
+	if (err < 0) {
+		printk(KERN_ERR "Failed to send command control message %x.%x: err=%d.\n", 
+				value, index, err);
+		return err;
+	}
+
+	return err;
+}
+
+static int ds_send_control_mode(struct ds_device *dev, u16 value, u16 index)
+{
+	int err;
+	
+	err = usb_control_msg(dev->udev, usb_sndctrlpipe(dev->udev, dev->ep[EP_CONTROL]), 
+			MODE_CMD, 0x40, value, index, NULL, 0, HZ);
+	if (err < 0) {
+		printk(KERN_ERR "Failed to send mode control message %x.%x: err=%d.\n", 
+				value, index, err);
+		return err;
+	}
+
+	return err;
+}
+
+static int ds_send_control(struct ds_device *dev, u16 value, u16 index)
+{
+	int err;
+	
+	err = usb_control_msg(dev->udev, usb_sndctrlpipe(dev->udev, dev->ep[EP_CONTROL]), 
+			COMM_CMD, 0x40, value, index, NULL, 0, HZ);
+	if (err < 0) {
+		printk(KERN_ERR "Failed to send control message %x.%x: err=%d.\n", 
+				value, index, err);
+		return err;
+	}
+
+	return err;
+}
+
+static inline void ds_dump_status(unsigned char *buf, unsigned char *str, int off)
+{
+	printk("%45s: %8x\n", str, buf[off]);
+}
+
+int ds_recv_status_nodump(struct ds_device *dev, struct ds_status *st, unsigned char *buf, int size)
+{
+	int count, err;
+		
+	memset(st, 0, sizeof(st));
+	
+	count = 0;
+	err = usb_bulk_msg(dev->udev, usb_rcvbulkpipe(dev->udev, dev->ep[EP_STATUS]), buf, size, &count, 100);
+	if (err < 0) {
+		printk(KERN_ERR "Failed to read 1-wire data from 0x%x: err=%d.\n", dev->ep[EP_STATUS], err);
+		return err;
+	}
+	
+	if (count >= sizeof(*st))
+		memcpy(st, buf, sizeof(*st));
+
+	return count;
+}
+
+int ds_recv_status(struct ds_device *dev, struct ds_status *st)
+{
+	unsigned char buf[64];
+	int count, err = 0, i;
+	
+	memcpy(st, buf, sizeof(*st));
+		
+	count = ds_recv_status_nodump(dev, st, buf, sizeof(buf));
+	if (count < 0)
+		return err;
+	
+	printk("0x%x: count=%d, status: ", dev->ep[EP_STATUS], count);
+	for (i=0; i<count; ++i)
+		printk("%02x ", buf[i]);
+	printk("\n");
+
+	if (count >= 16) {
+		ds_dump_status(buf, "enable flag", 0);
+		ds_dump_status(buf, "1-wire speed", 1);
+		ds_dump_status(buf, "strong pullup duration", 2);
+		ds_dump_status(buf, "programming pulse duration", 3);
+		ds_dump_status(buf, "pulldown slew rate control", 4);
+		ds_dump_status(buf, "write-1 low time", 5);
+		ds_dump_status(buf, "data sample offset/write-0 recovery time", 6);
+		ds_dump_status(buf, "reserved (test register)", 7);
+		ds_dump_status(buf, "device status flags", 8);
+		ds_dump_status(buf, "communication command byte 1", 9);
+		ds_dump_status(buf, "communication command byte 2", 10);
+		ds_dump_status(buf, "communication command buffer status", 11);
+		ds_dump_status(buf, "1-wire data output buffer status", 12);
+		ds_dump_status(buf, "1-wire data input buffer status", 13);
+		ds_dump_status(buf, "reserved", 14);
+		ds_dump_status(buf, "reserved", 15);
+	}
+
+	memcpy(st, buf, sizeof(*st));
+
+	if (st->status & ST_EPOF) {
+		printk(KERN_INFO "Resetting device after ST_EPOF.\n");
+		err = ds_send_control_cmd(dev, CTL_RESET_DEVICE, 0);
+		if (err)
+			return err;
+		count = ds_recv_status_nodump(dev, st, buf, sizeof(buf));
+		if (count < 0)
+			return err;
+	}
+#if 0
+	if (st->status & ST_IDLE) {
+		printk(KERN_INFO "Resetting pulse after ST_IDLE.\n");
+		err = ds_start_pulse(dev, PULLUP_PULSE_DURATION);
+		if (err)
+			return err;
+	}
+#endif
+	
+	return err;
+}
+
+int ds_recv_data(struct ds_device *dev, unsigned char *buf, int size)
+{
+	int count, err;
+	struct ds_status st;
+	
+	count = 0;
+	err = usb_bulk_msg(dev->udev, usb_rcvbulkpipe(dev->udev, dev->ep[EP_DATA_IN]), 
+				buf, size, &count, HZ);
+	if (err < 0) {
+		printk(KERN_INFO "Clearing ep0x%x.\n", dev->ep[EP_DATA_IN]);
+		usb_clear_halt(dev->udev, usb_rcvbulkpipe(dev->udev, dev->ep[EP_DATA_IN]));
+		ds_recv_status(dev, &st);
+		return err;
+	}
+
+#if 0
+	{
+		int i;
+
+		printk("%s: count=%d: ", __func__, count);
+		for (i=0; i<count; ++i)
+			printk("%02x ", buf[i]);
+		printk("\n");
+	}
+#endif
+	return count;
+}
+
+int ds_send_data(struct ds_device *dev, unsigned char *buf, int len)
+{
+	int count, err;
+	
+	count = 0;
+	err = usb_bulk_msg(dev->udev, usb_sndbulkpipe(dev->udev, dev->ep[EP_DATA_OUT]), buf, len, &count, HZ);
+	if (err < 0) {
+		printk(KERN_ERR "Failed to read 1-wire data from 0x02: err=%d.\n", err);
+		return err;
+	}
+
+	return err;
+}
+
+int ds_stop_pulse(struct ds_device *dev, int limit)
+{
+	struct ds_status st;
+	int count = 0, err = 0;
+	u8 buf[0x20];
+	
+	do {
+		err = ds_send_control(dev, CTL_HALT_EXE_IDLE, 0);
+		if (err)
+			break;
+		err = ds_send_control(dev, CTL_RESUME_EXE, 0);
+		if (err)
+			break;
+		err = ds_recv_status_nodump(dev, &st, buf, sizeof(buf));
+		if (err)
+			break;
+
+		if ((st.status & ST_SPUA) == 0) {
+			err = ds_send_control_mode(dev, MOD_PULSE_EN, 0);
+			if (err)
+				break;
+		}
+	} while(++count < limit);
+
+	return err;
+}
+
+int ds_detect(struct ds_device *dev, struct ds_status *st)
+{
+	int err;
+	
+	err = ds_send_control_cmd(dev, CTL_RESET_DEVICE, 0);
+	if (err)
+		return err;
+
+	err = ds_send_control(dev, COMM_SET_DURATION | COMM_IM, 0);
+	if (err)
+		return err;
+	
+	err = ds_send_control(dev, COMM_SET_DURATION | COMM_IM | COMM_TYPE, 0x40);
+	if (err)
+		return err;
+	
+	err = ds_send_control_mode(dev, MOD_PULSE_EN, PULSE_PROG);
+	if (err)
+		return err;
+
+	err = ds_recv_status(dev, st);
+
+	return err;
+}
+
+int ds_wait_status(struct ds_device *dev, struct ds_status *st)
+{
+	u8 buf[0x20];
+	int err, count = 0;
+
+	do {
+		err = ds_recv_status_nodump(dev, st, buf, sizeof(buf));
+#if 0
+		if (err >= 0) {	
+			int i;
+			printk("0x%x: count=%d, status: ", dev->ep[EP_STATUS], err);
+			for (i=0; i<err; ++i)
+				printk("%02x ", buf[i]);
+			printk("\n");
+		}
+#endif
+	} while(!(buf[0x08] & 0x20) && !(err < 0) && ++count < 100);
+
+
+	if (((err > 16) && (buf[0x10] & 0x01)) || count >= 100 || err < 0) {
+		ds_recv_status(dev, st);
+		return -1;
+	}
+	else {
+		return 0;
+	}
+}
+
+int ds_reset(struct ds_device *dev, struct ds_status *st)
+{
+	int err;
+
+	//err = ds_send_control(dev, COMM_1_WIRE_RESET | COMM_F | COMM_IM | COMM_SE, SPEED_FLEXIBLE);
+	err = ds_send_control(dev, 0x43, SPEED_NORMAL);
+	if (err)
+		return err;
+
+	ds_wait_status(dev, st);
+#if 0
+	if (st->command_buffer_status) {
+		printk(KERN_INFO "Short circuit.\n");
+		return -EIO;
+	}
+#endif
+	
+	return 0;
+}
+
+int ds_set_speed(struct ds_device *dev, int speed)
+{
+	int err;
+	
+	if (speed != SPEED_NORMAL && speed != SPEED_FLEXIBLE && speed != SPEED_OVERDRIVE)
+		return -EINVAL;
+
+	if (speed != SPEED_OVERDRIVE)
+		speed = SPEED_FLEXIBLE;
+
+	speed &= 0xff;
+	
+	err = ds_send_control_mode(dev, MOD_1WIRE_SPEED, speed);
+	if (err)
+		return err;
+
+	return err;
+}
+
+int ds_start_pulse(struct ds_device *dev, int delay)
+{
+	int err;
+	u8 del = 1 + (u8)(delay >> 4);
+	struct ds_status st;
+	
+#if 0
+	err = ds_stop_pulse(dev, 10);
+	if (err)
+		return err;
+
+	err = ds_send_control_mode(dev, MOD_PULSE_EN, PULSE_SPUE);
+	if (err)
+		return err;
+#endif
+	err = ds_send_control(dev, COMM_SET_DURATION | COMM_IM, del);
+	if (err)
+		return err;
+
+	err = ds_send_control(dev, COMM_PULSE | COMM_IM | COMM_F, 0);
+	if (err)
+		return err;
+
+	mdelay(delay);
+
+	ds_wait_status(dev, &st);
+	
+	return err;
+}
+
+int ds_touch_bit(struct ds_device *dev, u8 bit, u8 *tbit)
+{
+	int err, count;
+	struct ds_status st;
+	u16 value = (COMM_BIT_IO | COMM_IM) | ((bit) ? COMM_D : 0);
+	u16 cmd;
+	
+	err = ds_send_control(dev, value, 0);
+	if (err)
+		return err;
+
+	count = 0;
+	do {
+		err = ds_wait_status(dev, &st);
+		if (err)
+			return err;
+
+		cmd = st.command0 | (st.command1 << 8);
+	} while (cmd != value && ++count < 10);
+
+	if (err < 0 || count >= 10) {
+		printk(KERN_ERR "Failed to obtain status.\n");
+		return -EINVAL;
+	}
+
+	err = ds_recv_data(dev, tbit, sizeof(*tbit));
+	if (err < 0)
+		return err;
+
+	return 0;
+}
+
+int ds_write_bit(struct ds_device *dev, u8 bit)
+{
+	int err;
+	struct ds_status st;
+	
+	err = ds_send_control(dev, COMM_BIT_IO | COMM_IM | (bit) ? COMM_D : 0, 0);
+	if (err)
+		return err;
+
+	ds_wait_status(dev, &st);
+
+	return 0;
+}
+
+int ds_write_byte(struct ds_device *dev, u8 byte)
+{
+	int err;
+	struct ds_status st;
+	u8 rbyte;
+	
+	err = ds_send_control(dev, COMM_BYTE_IO | COMM_IM | COMM_SPU, byte);
+	if (err)
+		return err;
+
+	err = ds_wait_status(dev, &st);
+	if (err)
+		return err;
+		
+	err = ds_recv_data(dev, &rbyte, sizeof(rbyte));
+	if (err < 0)
+		return err;
+	
+	ds_start_pulse(dev, PULLUP_PULSE_DURATION);
+
+	return !(byte == rbyte);
+}
+
+int ds_read_bit(struct ds_device *dev, u8 *bit)
+{
+	int err;
+
+	err = ds_send_control_mode(dev, MOD_PULSE_EN, PULSE_SPUE);
+	if (err)
+		return err;
+	
+	err = ds_send_control(dev, COMM_BIT_IO | COMM_IM | COMM_SPU | COMM_D, 0);
+	if (err)
+		return err;
+	
+	err = ds_recv_data(dev, bit, sizeof(*bit));
+	if (err < 0)
+		return err;
+
+	return 0;
+}
+
+int ds_read_byte(struct ds_device *dev, u8 *byte)
+{
+	int err;
+	struct ds_status st;
+
+	err = ds_send_control(dev, COMM_BYTE_IO | COMM_IM , 0xff);
+	if (err)
+		return err;
+
+	ds_wait_status(dev, &st);
+	
+	err = ds_recv_data(dev, byte, sizeof(*byte));
+	if (err < 0)
+		return err;
+
+	return 0;
+}
+
+inline int ds_read_block(struct ds_device *dev, u8 *buf, int len)
+{
+	struct ds_status st;
+	int err;
+
+	if (len > 64*1024)
+		return -E2BIG;
+
+	memset(buf, 0xFF, len);
+	
+	err = ds_send_data(dev, buf, len);
+	if (err < 0)
+		return err;
+	
+	err = ds_send_control(dev, COMM_BLOCK_IO | COMM_IM | COMM_SPU, len);
+	if (err)
+		return err;
+
+	ds_wait_status(dev, &st);
+	
+	memset(buf, 0x00, len);
+	err = ds_recv_data(dev, buf, len);
+
+	return err;
+}
+
+inline int ds_write_block(struct ds_device *dev, u8 *buf, int len)
+{
+	int err;
+	struct ds_status st;
+	
+	err = ds_send_data(dev, buf, len);
+	if (err < 0)
+		return err;
+	
+	ds_wait_status(dev, &st);
+
+	err = ds_send_control(dev, COMM_BLOCK_IO | COMM_IM | COMM_SPU, len);
+	if (err)
+		return err;
+
+	ds_wait_status(dev, &st);
+
+	err = ds_recv_data(dev, buf, len);
+	if (err < 0)
+		return err;
+
+	ds_start_pulse(dev, PULLUP_PULSE_DURATION);
+	
+	return !(err == len);
+}
+
+int ds_search(struct ds_device *dev, u64 init, u64 *buf, u8 id_number, int conditional_search)
+{
+	int err;
+	u16 value, index;
+	struct ds_status st;
+
+	memset(buf, 0, sizeof(buf));
+	
+	err = ds_send_data(ds_dev, (unsigned char *)&init, 8);
+	if (err)
+		return err;
+	
+	ds_wait_status(ds_dev, &st);
+
+	value = COMM_SEARCH_ACCESS | COMM_IM | COMM_SM | COMM_F | COMM_RTS;
+	index = (conditional_search ? 0xEC : 0xF0) | (id_number << 8);
+	err = ds_send_control(ds_dev, value, index);
+	if (err)
+		return err;
+
+	ds_wait_status(ds_dev, &st);
+
+	err = ds_recv_data(ds_dev, (unsigned char *)buf, 8*id_number);
+	if (err < 0)
+		return err;
+
+	return err/8;
+}
+
+int ds_match_access(struct ds_device *dev, u64 init)
+{
+	int err;
+	struct ds_status st;
+
+	err = ds_send_data(dev, (unsigned char *)&init, sizeof(init));
+	if (err)
+		return err;
+	
+	ds_wait_status(dev, &st);
+
+	err = ds_send_control(dev, COMM_MATCH_ACCESS | COMM_IM | COMM_RST, 0x0055);
+	if (err)
+		return err;
+
+	ds_wait_status(dev, &st);
+
+	return 0;
+}
+
+int ds_set_path(struct ds_device *dev, u64 init)
+{
+	int err;
+	struct ds_status st;
+	u8 buf[9];
+
+	memcpy(buf, &init, 8);
+	buf[8] = BRANCH_MAIN;
+	
+	err = ds_send_data(dev, buf, sizeof(buf));
+	if (err)
+		return err;
+	
+	ds_wait_status(dev, &st);
+
+	err = ds_send_control(dev, COMM_SET_PATH | COMM_IM | COMM_RST, 0);
+	if (err)
+		return err;
+
+	ds_wait_status(dev, &st);
+
+	return 0;
+}
+
+int ds_probe(struct usb_interface *intf, const struct usb_device_id *udev_id)
+{
+	struct usb_device *udev = interface_to_usbdev(intf);
+	struct usb_endpoint_descriptor *endpoint;
+	struct usb_host_interface *iface_desc;
+	int i, err;
+
+	ds_dev = kmalloc(sizeof(struct ds_device), GFP_KERNEL);
+	if (!ds_dev) {
+		printk(KERN_INFO "Failed to allocate new DS9490R structure.\n");
+		return -ENOMEM;
+	}
+
+	ds_dev->udev = usb_get_dev(udev);
+	usb_set_intfdata(intf, ds_dev);
+
+	err = usb_set_interface(ds_dev->udev, intf->altsetting[0].desc.bInterfaceNumber, 3);
+	if (err) {
+		printk(KERN_ERR "Failed to set alternative setting 3 for %d interface: err=%d.\n",
+				intf->altsetting[0].desc.bInterfaceNumber, err);
+		return err;
+	}
+
+	err = usb_reset_configuration(ds_dev->udev);
+	if (err) {
+		printk(KERN_ERR "Failed to reset configuration: err=%d.\n", err);
+		return err;
+	}
+	
+	iface_desc = &intf->altsetting[0];
+	if (iface_desc->desc.bNumEndpoints != NUM_EP-1) {
+		printk(KERN_INFO "Num endpoints=%d. It is not DS9490R.\n", iface_desc->desc.bNumEndpoints);
+		return -ENODEV;
+	}
+
+	atomic_set(&ds_dev->refcnt, 0);
+	memset(ds_dev->ep, 0, sizeof(ds_dev->ep));
+	
+	/*
+	 * This loop doesn'd show control 0 endpoint, 
+	 * so we will fill only 1-3 endpoints entry.
+	 */
+	for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i) {
+		endpoint = &iface_desc->endpoint[i].desc;
+
+		ds_dev->ep[i+1] = endpoint->bEndpointAddress;
+		
+		printk("%d: addr=%x, size=%d, dir=%s, type=%x\n",
+			i, endpoint->bEndpointAddress, endpoint->wMaxPacketSize,
+			(endpoint->bEndpointAddress & USB_DIR_IN)?"IN":"OUT",
+			endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK);
+	}
+	
+#if 0
+	{
+		int err, i;
+		u64 buf[3];
+		u64 init=0xb30000002078ee81ull;
+		struct ds_status st;
+		
+		ds_reset(ds_dev, &st);
+		err = ds_search(ds_dev, init, buf, 3, 0);
+		if (err < 0)
+			return err;
+		for (i=0; i<err; ++i)
+			printk("%d: %llx\n", i, buf[i]);
+		
+		printk("Resetting...\n");	
+		ds_reset(ds_dev, &st);
+		printk("Setting path for %llx.\n", init);
+		err = ds_set_path(ds_dev, init);
+		if (err)
+			return err;
+		printk("Calling MATCH_ACCESS.\n");
+		err = ds_match_access(ds_dev, init);
+		if (err)
+			return err;
+
+		printk("Searching the bus...\n");
+		err = ds_search(ds_dev, init, buf, 3, 0);
+
+		printk("ds_search() returned %d\n", err);
+		
+		if (err < 0)
+			return err;
+		for (i=0; i<err; ++i)
+			printk("%d: %llx\n", i, buf[i]);
+		
+		return 0;
+	}
+#endif
+
+	return 0;
+}
+
+void ds_disconnect(struct usb_interface *intf)
+{
+	struct ds_device *dev;
+	
+	dev = usb_get_intfdata (intf);
+	usb_set_intfdata (intf, NULL);
+
+	while(atomic_read(&dev->refcnt))
+		schedule_timeout(HZ);
+
+	usb_put_dev(dev->udev);
+	kfree(dev);
+	ds_dev = NULL;
+}
+
+int ds_init(void)
+{
+	int err;
+
+	err = usb_register(&ds_driver);
+	if (err) {
+		printk(KERN_INFO "Failed to register DS9490R USB device: err=%d.\n", err);
+		return err;
+	}
+
+	return 0;
+}
+
+void ds_fini(void)
+{
+	usb_deregister(&ds_driver);
+}
+
+module_init(ds_init);
+module_exit(ds_fini);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Evgeniy Polyakov <johnpol@2ka.mipt.ru>");
+
+EXPORT_SYMBOL(ds_touch_bit);
+EXPORT_SYMBOL(ds_read_byte);
+EXPORT_SYMBOL(ds_read_bit);
+EXPORT_SYMBOL(ds_read_block);
+EXPORT_SYMBOL(ds_write_byte);
+EXPORT_SYMBOL(ds_write_bit);
+EXPORT_SYMBOL(ds_write_block);
+EXPORT_SYMBOL(ds_start_pulse);
+EXPORT_SYMBOL(ds_set_speed);
+EXPORT_SYMBOL(ds_reset);
+EXPORT_SYMBOL(ds_detect);
+EXPORT_SYMBOL(ds_stop_pulse);
+EXPORT_SYMBOL(ds_send_data);
+EXPORT_SYMBOL(ds_recv_data);
+EXPORT_SYMBOL(ds_recv_status);
+EXPORT_SYMBOL(ds_search);
+EXPORT_SYMBOL(ds_get_device);
+EXPORT_SYMBOL(ds_put_device);
+
diff -Nru a/drivers/w1/dscore.h b/drivers/w1/dscore.h
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/drivers/w1/dscore.h	2004-10-18 14:57:23 -07:00
@@ -0,0 +1,173 @@
+/*
+ * 	dscore.h
+ *
+ * Copyright (c) 2004 Evgeniy Polyakov <johnpol@2ka.mipt.ru>
+ * 
+ *
+ * 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
+ */
+
+#ifndef __DSCORE_H
+#define __DSCORE_H
+
+#include <linux/usb.h>
+#include <asm/atomic.h>
+
+/* COMMAND TYPE CODES */
+#define CONTROL_CMD			0x00
+#define COMM_CMD			0x01
+#define MODE_CMD			0x02
+
+/* CONTROL COMMAND CODES */
+#define CTL_RESET_DEVICE		0x0000
+#define CTL_START_EXE			0x0001
+#define CTL_RESUME_EXE			0x0002
+#define CTL_HALT_EXE_IDLE		0x0003
+#define CTL_HALT_EXE_DONE		0x0004
+#define CTL_FLUSH_COMM_CMDS		0x0007
+#define CTL_FLUSH_RCV_BUFFER		0x0008
+#define CTL_FLUSH_XMT_BUFFER		0x0009
+#define CTL_GET_COMM_CMDS		0x000A
+
+/* MODE COMMAND CODES */
+#define MOD_PULSE_EN			0x0000
+#define MOD_SPEED_CHANGE_EN		0x0001
+#define MOD_1WIRE_SPEED			0x0002
+#define MOD_STRONG_PU_DURATION		0x0003
+#define MOD_PULLDOWN_SLEWRATE		0x0004
+#define MOD_PROG_PULSE_DURATION		0x0005
+#define MOD_WRITE1_LOWTIME		0x0006
+#define MOD_DSOW0_TREC			0x0007
+
+/* COMMUNICATION COMMAND CODES */
+#define COMM_ERROR_ESCAPE		0x0601
+#define COMM_SET_DURATION		0x0012
+#define COMM_BIT_IO			0x0020
+#define COMM_PULSE			0x0030
+#define COMM_1_WIRE_RESET		0x0042
+#define COMM_BYTE_IO			0x0052
+#define COMM_MATCH_ACCESS		0x0064
+#define COMM_BLOCK_IO			0x0074
+#define COMM_READ_STRAIGHT		0x0080
+#define COMM_DO_RELEASE			0x6092
+#define COMM_SET_PATH			0x00A2
+#define COMM_WRITE_SRAM_PAGE		0x00B2
+#define COMM_WRITE_EPROM		0x00C4
+#define COMM_READ_CRC_PROT_PAGE		0x00D4
+#define COMM_READ_REDIRECT_PAGE_CRC	0x21E4
+#define COMM_SEARCH_ACCESS		0x00F4
+
+/* Communication command bits */
+#define COMM_TYPE			0x0008
+#define COMM_SE				0x0008
+#define COMM_D				0x0008
+#define COMM_Z				0x0008
+#define COMM_CH				0x0008
+#define COMM_SM				0x0008
+#define COMM_R				0x0008
+#define COMM_IM				0x0001
+
+#define COMM_PS				0x4000
+#define COMM_PST			0x4000
+#define COMM_CIB			0x4000
+#define COMM_RTS			0x4000
+#define COMM_DT				0x2000
+#define COMM_SPU			0x1000
+#define COMM_F				0x0800
+#define COMM_NTP			0x0400
+#define COMM_ICP			0x0200
+#define COMM_RST			0x0100
+
+#define PULSE_PROG			0x01
+#define PULSE_SPUE			0x02
+
+#define BRANCH_MAIN			0xCC
+#define BRANCH_AUX			0x33
+
+/*
+ * Duration of the strong pull-up pulse in milliseconds.
+ */
+#define PULLUP_PULSE_DURATION		750
+
+/* Status flags */
+#define ST_SPUA				0x01  /* Strong Pull-up is active */
+#define ST_PRGA				0x02  /* 12V programming pulse is being generated */
+#define ST_12VP				0x04  /* external 12V programming voltage is present */
+#define ST_PMOD				0x08  /* DS2490 powered from USB and external sources */
+#define ST_HALT				0x10  /* DS2490 is currently halted */
+#define ST_IDLE				0x20  /* DS2490 is currently idle */
+#define ST_EPOF				0x80
+
+#define SPEED_NORMAL			0x00
+#define SPEED_FLEXIBLE			0x01
+#define SPEED_OVERDRIVE			0x02
+
+#define NUM_EP				4
+#define EP_CONTROL			0
+#define EP_STATUS			1
+#define EP_DATA_OUT			2
+#define EP_DATA_IN			3
+
+struct ds_device
+{
+	struct usb_device 	*udev;
+	struct usb_interface	*intf;
+
+	int			ep[NUM_EP];
+
+	atomic_t		refcnt;
+};
+
+struct ds_status
+{
+	u8			enable;
+	u8			speed;
+	u8			pullup_dur;
+	u8			ppuls_dur;
+	u8			pulldown_slew;
+	u8			write1_time;
+	u8			write0_time;
+	u8			reserved0;
+	u8			status;
+	u8			command0;
+	u8			command1;
+	u8			command_buffer_status;
+	u8			data_out_buffer_status;
+	u8			data_in_buffer_status;
+	u8			reserved1;
+	u8			reserved2;
+
+};
+
+inline int ds_touch_bit(struct ds_device *, u8, u8 *);
+inline int ds_read_byte(struct ds_device *, u8 *);
+inline int ds_read_bit(struct ds_device *, u8 *);
+inline int ds_write_byte(struct ds_device *, u8);
+inline int ds_write_bit(struct ds_device *, u8);
+inline int ds_start_pulse(struct ds_device *, int);
+inline int ds_set_speed(struct ds_device *, int);
+inline int ds_reset(struct ds_device *, struct ds_status *);
+inline int ds_detect(struct ds_device *, struct ds_status *);
+inline int ds_stop_pulse(struct ds_device *, int);
+inline int ds_send_data(struct ds_device *, unsigned char *, int);
+inline int ds_recv_data(struct ds_device *, unsigned char *, int);
+inline int ds_recv_status(struct ds_device *, struct ds_status *);
+inline struct ds_device * ds_get_device(void);
+inline void ds_put_device(struct ds_device *);
+inline int ds_write_block(struct ds_device *, u8 *, int);
+inline int ds_read_block(struct ds_device *, u8 *, int);
+
+#endif /* __DSCORE_H */
+
diff -Nru a/drivers/w1/matrox_w1.c b/drivers/w1/matrox_w1.c
--- a/drivers/w1/matrox_w1.c	2004-10-18 14:56:34 -07:00
+++ b/drivers/w1/matrox_w1.c	2004-10-18 14:56:34 -07:00
@@ -94,7 +94,7 @@
 /*
  * These functions read and write DDC Data bit.
  *
- * Using tristate pins, since i can't  fin any open-drain pin in whole motherboard.
+ * Using tristate pins, since i can't find any open-drain pin in whole motherboard.
  * Unfortunately we can't connect to Intel's 82801xx IO controller
  * since we don't know motherboard schema, wich has pretty unused(may be not) GPIO.
  *
diff -Nru a/drivers/w1/w1.c b/drivers/w1/w1.c
--- a/drivers/w1/w1.c	2004-10-18 14:56:28 -07:00
+++ b/drivers/w1/w1.c	2004-10-18 14:56:28 -07:00
@@ -45,7 +45,7 @@
 MODULE_AUTHOR("Evgeniy Polyakov <johnpol@2ka.mipt.ru>");
 MODULE_DESCRIPTION("Driver for 1-wire Dallas network protocol.");
 
-static int w1_timeout = 5 * HZ;
+static int w1_timeout = 10;
 int w1_max_slave_count = 10;
 
 module_param_named(timeout, w1_timeout, int, 0);
@@ -137,25 +137,95 @@
 	.show = &w1_default_read_name,
 };
 
-static ssize_t w1_master_attribute_show(struct device *dev, char *buf)
+ssize_t w1_master_attribute_show_name(struct device *dev, char *buf)
+{
+	struct w1_master *md = container_of (dev, struct w1_master, dev);
+	ssize_t count;
+	
+	if (down_interruptible (&md->mutex))
+		return -EBUSY;
+
+	count = sprintf(buf, "%s\n", md->name);
+	
+	up(&md->mutex);
+
+	return count;
+}
+
+ssize_t w1_master_attribute_show_pointer(struct device *dev, char *buf)
+{
+	struct w1_master *md = container_of(dev, struct w1_master, dev);
+	ssize_t count;
+	
+	if (down_interruptible(&md->mutex))
+		return -EBUSY;
+
+	count = sprintf(buf, "0x%p\n", md->bus_master);
+	
+	up(&md->mutex);
+	return count;
+}
+
+ssize_t w1_master_attribute_show_timeout(struct device *dev, char *buf)
+{
+	ssize_t count;
+	count = sprintf(buf, "%d\n", w1_timeout);
+	return count;
+}
+
+ssize_t w1_master_attribute_show_max_slave_count(struct device *dev, char *buf)
+{
+	struct w1_master *md = container_of(dev, struct w1_master, dev);
+	ssize_t count;
+	
+	if (down_interruptible(&md->mutex))
+		return -EBUSY;
+
+	count = sprintf(buf, "%d\n", md->max_slave_count);
+	
+	up(&md->mutex);
+	return count;
+}
+
+ssize_t w1_master_attribute_show_attempts(struct device *dev, char *buf)
+{
+	struct w1_master *md = container_of(dev, struct w1_master, dev);
+	ssize_t count;
+	
+	if (down_interruptible(&md->mutex))
+		return -EBUSY;
+
+	count = sprintf(buf, "%lu\n", md->attempts);
+	
+	up(&md->mutex);
+	return count;
+}
+
+ssize_t w1_master_attribute_show_slave_count(struct device *dev, char *buf)
+{
+	struct w1_master *md = container_of(dev, struct w1_master, dev);
+	ssize_t count;
+	
+	if (down_interruptible(&md->mutex))
+		return -EBUSY;
+
+	count = sprintf(buf, "%d\n", md->slave_count);
+	
+	up(&md->mutex);
+	return count;
+}
+
+ssize_t w1_master_attribute_show_slaves(struct device *dev, char *buf)
+
 {
-	return sprintf(buf, "please fix me\n");
-#if 0
 	struct w1_master *md = container_of(dev, struct w1_master, dev);
 	int c = PAGE_SIZE;
 
 	if (down_interruptible(&md->mutex))
 		return -EBUSY;
 
-	c -= snprintf(buf + PAGE_SIZE - c, c, "%s\n", md->name);
-	c -= snprintf(buf + PAGE_SIZE - c, c,
-		       "bus_master=0x%p, timeout=%d, max_slave_count=%d, attempts=%lu\n",
-		       md->bus_master, w1_timeout, md->max_slave_count,
-		       md->attempts);
-	c -= snprintf(buf + PAGE_SIZE - c, c, "%d slaves: ",
-		       md->slave_count);
 	if (md->slave_count == 0)
-		c -= snprintf(buf + PAGE_SIZE - c, c, "no.\n");
+		c -= snprintf(buf + PAGE_SIZE - c, c, "not found.\n");
 	else {
 		struct list_head *ent, *n;
 		struct w1_slave *sl;
@@ -163,25 +233,70 @@
 		list_for_each_safe(ent, n, &md->slist) {
 			sl = list_entry(ent, struct w1_slave, w1_slave_entry);
 
-			c -= snprintf(buf + PAGE_SIZE - c, c, "%s[%p] ",
-				       sl->name, sl);
+ 			c -= snprintf(buf + PAGE_SIZE - c, c, "%s\n", sl->name);
 		}
-		c -= snprintf(buf + PAGE_SIZE - c, c, "\n");
 	}
 
 	up(&md->mutex);
 
 	return PAGE_SIZE - c;
-#endif
 }
 
-struct device_attribute w1_master_attribute = {
+static struct device_attribute w1_master_attribute_slaves = {
 	.attr = {
-			.name = "w1_master_stats",
+ 			.name = "w1_master_slaves",
 			.mode = S_IRUGO,
 			.owner = THIS_MODULE,
 	},
-	.show = &w1_master_attribute_show,
+ 	.show = &w1_master_attribute_show_slaves,
+};
+static struct device_attribute w1_master_attribute_slave_count = {
+	.attr = {
+			.name = "w1_master_slave_count",
+			.mode = S_IRUGO,
+			.owner = THIS_MODULE
+	},
+	.show = &w1_master_attribute_show_slave_count,
+};
+static struct device_attribute w1_master_attribute_attempts = {
+	.attr = {
+			.name = "w1_master_attempts",
+			.mode = S_IRUGO,
+			.owner = THIS_MODULE
+	},
+	.show = &w1_master_attribute_show_attempts,
+};
+static struct device_attribute w1_master_attribute_max_slave_count = {
+	.attr = {
+			.name = "w1_master_max_slave_count",
+			.mode = S_IRUGO,
+			.owner = THIS_MODULE
+	},
+	.show = &w1_master_attribute_show_max_slave_count,
+};
+static struct device_attribute w1_master_attribute_timeout = {
+	.attr = {
+			.name = "w1_master_timeout",
+			.mode = S_IRUGO,
+			.owner = THIS_MODULE
+	},
+	.show = &w1_master_attribute_show_timeout,
+};
+static struct device_attribute w1_master_attribute_pointer = {
+	.attr = {
+			.name = "w1_master_pointer",
+			.mode = S_IRUGO,
+			.owner = THIS_MODULE
+	},
+	.show = &w1_master_attribute_show_pointer,
+};
+static struct device_attribute w1_master_attribute_name = {
+	.attr = {
+			.name = "w1_master_name",
+			.mode = S_IRUGO,
+			.owner = THIS_MODULE
+	},
+	.show = &w1_master_attribute_show_name,
 };
 
 static struct bin_attribute w1_slave_bin_attribute = {
@@ -204,11 +319,11 @@
 	sl->dev.release = &w1_slave_release;
 
 	snprintf(&sl->dev.bus_id[0], sizeof(sl->dev.bus_id),
-		  "%x-%llx",
+		  "%02x-%012llx",
 		  (unsigned int) sl->reg_num.family,
 		  (unsigned long long) sl->reg_num.id);
 	snprintf (&sl->name[0], sizeof(sl->name),
-		  "%x-%llx",
+		  "%02x-%012llx",
 		  (unsigned int) sl->reg_num.family,
 		  (unsigned long long) sl->reg_num.id);
 
@@ -223,12 +338,16 @@
 		return err;
 	}
 
-	w1_slave_bin_attribute.read = sl->family->fops->rbin;
-	w1_slave_attribute.show = sl->family->fops->rname;
-	w1_slave_attribute_val.show = sl->family->fops->rval;
-	w1_slave_attribute_val.attr.name = sl->family->fops->rvalname;
+	memcpy(&sl->attr_bin, &w1_slave_bin_attribute, sizeof(sl->attr_bin));
+	memcpy(&sl->attr_name, &w1_slave_attribute, sizeof(sl->attr_name));
+	memcpy(&sl->attr_val, &w1_slave_attribute_val, sizeof(sl->attr_val));
+	
+	sl->attr_bin.read = sl->family->fops->rbin;
+	sl->attr_name.show = sl->family->fops->rname;
+	sl->attr_val.show = sl->family->fops->rval;
+	sl->attr_val.attr.name = sl->family->fops->rvalname;
 
-	err = device_create_file(&sl->dev, &w1_slave_attribute);
+	err = device_create_file(&sl->dev, &sl->attr_name);
 	if (err < 0) {
 		dev_err(&sl->dev,
 			 "sysfs file creation for [%s] failed. err=%d\n",
@@ -237,23 +356,23 @@
 		return err;
 	}
 
-	err = device_create_file(&sl->dev, &w1_slave_attribute_val);
+	err = device_create_file(&sl->dev, &sl->attr_val);
 	if (err < 0) {
 		dev_err(&sl->dev,
 			 "sysfs file creation for [%s] failed. err=%d\n",
 			 sl->dev.bus_id, err);
-		device_remove_file(&sl->dev, &w1_slave_attribute);
+		device_remove_file(&sl->dev, &sl->attr_name);
 		device_unregister(&sl->dev);
 		return err;
 	}
 
-	err = sysfs_create_bin_file(&sl->dev.kobj, &w1_slave_bin_attribute);
+	err = sysfs_create_bin_file(&sl->dev.kobj, &sl->attr_bin);
 	if (err < 0) {
 		dev_err(&sl->dev,
 			 "sysfs file creation for [%s] failed. err=%d\n",
 			 sl->dev.bus_id, err);
-		device_remove_file(&sl->dev, &w1_slave_attribute);
-		device_remove_file(&sl->dev, &w1_slave_attribute_val);
+		device_remove_file(&sl->dev, &sl->attr_name);
+		device_remove_file(&sl->dev, &sl->attr_val);
 		device_unregister(&sl->dev);
 		return err;
 	}
@@ -268,6 +387,7 @@
 	struct w1_slave *sl;
 	struct w1_family *f;
 	int err;
+	struct w1_netlink_msg msg;
 
 	sl = kmalloc(sizeof(struct w1_slave), GFP_KERNEL);
 	if (!sl) {
@@ -281,6 +401,7 @@
 
 	sl->owner = THIS_MODULE;
 	sl->master = dev;
+	set_bit(W1_SLAVE_ACTIVE, (long *)&sl->flags);
 
 	memcpy(&sl->reg_num, rn, sizeof(sl->reg_num));
 	atomic_set(&sl->refcnt, 0);
@@ -290,8 +411,8 @@
 	f = w1_family_registered(rn->family);
 	if (!f) {
 		spin_unlock(&w1_flock);
-		dev_info(&dev->dev, "Family %x is not registered.\n",
-			  rn->family);
+		dev_info(&dev->dev, "Family %x for %02x.%012llx.%02x is not registered.\n",
+			  rn->family, rn->family, rn->id, rn->crc);
 		kfree(sl);
 		return -ENODEV;
 	}
@@ -312,20 +433,31 @@
 
 	dev->slave_count++;
 
+	memcpy(&msg.id.id, rn, sizeof(msg.id.id));
+	msg.type = W1_SLAVE_ADD;
+	w1_netlink_send(dev, &msg);
+
 	return 0;
 }
 
 static void w1_slave_detach(struct w1_slave *sl)
 {
+	struct w1_netlink_msg msg;
+	
 	dev_info(&sl->dev, "%s: detaching %s.\n", __func__, sl->name);
 
 	while (atomic_read(&sl->refcnt))
 		schedule_timeout(10);
 
-	sysfs_remove_bin_file(&sl->dev.kobj, &w1_slave_bin_attribute);
-	device_remove_file(&sl->dev, &w1_slave_attribute);
+	sysfs_remove_bin_file (&sl->dev.kobj, &sl->attr_bin);
+	device_remove_file(&sl->dev, &sl->attr_name);
+	device_remove_file(&sl->dev, &sl->attr_val);
 	device_unregister(&sl->dev);
 	w1_family_put(sl->family);
+
+	memcpy(&msg.id.id, &sl->reg_num, sizeof(msg.id.id));
+	msg.type = W1_SLAVE_REMOVE;
+	w1_netlink_send(sl->master, &msg);
 }
 
 static void w1_search(struct w1_master *dev)
@@ -337,12 +469,9 @@
 	struct list_head *ent;
 	struct w1_slave *sl;
 	int family_found = 0;
-	struct w1_netlink_msg msg;
 
 	dev->attempts++;
 
-	memset(&msg, 0, sizeof(msg));
-
 	search_bit = id_bit = comp_bit = 0;
 	rn = tmp = last = 0;
 	last_device = last_zero = last_family_desc = 0;
@@ -368,8 +497,6 @@
 		}
 
 #if 1
-		memset(&msg, 0, sizeof(msg));
-
 		w1_write_8(dev, W1_SEARCH);
 		for (i = 0; i < 64; ++i) {
 			/*
@@ -413,9 +540,6 @@
 
 		}
 #endif
-		msg.id.w1_id = rn;
-		msg.val = w1_calc_crc8((u8 *) & rn, 7);
-		w1_netlink_send(dev, &msg);
 
 		if (desc_bit == last_zero)
 			last_device = 1;
@@ -432,8 +556,10 @@
 
 			if (sl->reg_num.family == tmp->family &&
 			    sl->reg_num.id == tmp->id &&
-			    sl->reg_num.crc == tmp->crc)
+			    sl->reg_num.crc == tmp->crc) {
+				set_bit(W1_SLAVE_ACTIVE, (long *)&sl->flags);
 				break;
+			}
 			else if (sl->reg_num.family == tmp->family) {
 				family_found = 1;
 				break;
@@ -443,12 +569,38 @@
 		}
 
 		if (slave_count == dev->slave_count &&
-		    msg.val && (*((__u8 *) & msg.val) == msg.id.id.crc)) {
+		    ((rn >> 56) & 0xff) == w1_calc_crc8((u8 *)&rn, 7)) {
 			w1_attach_slave_device(dev, (struct w1_reg_num *) &rn);
 		}
 	}
 }
 
+int w1_create_master_attributes(struct w1_master *dev)
+{
+	if (	device_create_file(&dev->dev, &w1_master_attribute_slaves) < 0 ||
+		device_create_file(&dev->dev, &w1_master_attribute_slave_count) < 0 ||
+		device_create_file(&dev->dev, &w1_master_attribute_attempts) < 0 ||
+		device_create_file(&dev->dev, &w1_master_attribute_max_slave_count) < 0 ||
+		device_create_file(&dev->dev, &w1_master_attribute_timeout) < 0||
+		device_create_file(&dev->dev, &w1_master_attribute_pointer) < 0||
+		device_create_file(&dev->dev, &w1_master_attribute_name) < 0)
+		return -EINVAL;
+
+	return 0;
+}
+
+void w1_destroy_master_attributes(struct w1_master *dev)
+{
+	device_remove_file(&dev->dev, &w1_master_attribute_slaves);
+	device_remove_file(&dev->dev, &w1_master_attribute_slave_count);
+	device_remove_file(&dev->dev, &w1_master_attribute_attempts);
+	device_remove_file(&dev->dev, &w1_master_attribute_max_slave_count);
+	device_remove_file(&dev->dev, &w1_master_attribute_timeout);
+	device_remove_file(&dev->dev, &w1_master_attribute_pointer);
+	device_remove_file(&dev->dev, &w1_master_attribute_name);
+}
+
+
 int w1_control(void *data)
 {
 	struct w1_slave *sl;
@@ -462,7 +614,7 @@
 	while (!control_needs_exit || have_to_wait) {
 		have_to_wait = 0;
 
-		timeout = w1_timeout;
+		timeout = w1_timeout*HZ;
 		do {
 			timeout = interruptible_sleep_on_timeout(&w1_control_wait, timeout);
 			if (current->flags & PF_FREEZE)
@@ -516,7 +668,7 @@
 					kfree(sl);
 				}
 			}
-			device_remove_file(&dev->dev, &w1_master_attribute);
+			w1_destroy_master_attributes(dev);
 			atomic_dec(&dev->refcnt);
 		}
 	}
@@ -528,12 +680,14 @@
 {
 	struct w1_master *dev = (struct w1_master *) data;
 	unsigned long timeout;
+	struct list_head *ent, *n;
+	struct w1_slave *sl;
 
 	daemonize("%s", dev->name);
 	allow_signal(SIGTERM);
 
 	while (!dev->need_exit) {
-		timeout = w1_timeout;
+		timeout = w1_timeout*HZ;
 		do {
 			timeout = interruptible_sleep_on_timeout(&dev->kwait, timeout);
 			if (current->flags & PF_FREEZE)
@@ -551,7 +705,28 @@
 
 		if (down_interruptible(&dev->mutex))
 			continue;
-		w1_search(dev);
+
+		list_for_each_safe(ent, n, &dev->slist) {
+			sl = list_entry(ent, struct w1_slave, w1_slave_entry);
+
+			if (sl)
+				clear_bit(W1_SLAVE_ACTIVE, (long *)&sl->flags);
+		}
+		
+      		w1_search(dev);
+		
+		list_for_each_safe(ent, n, &dev->slist) {
+			sl = list_entry(ent, struct w1_slave, w1_slave_entry);
+
+			if (sl && !test_bit(W1_SLAVE_ACTIVE, (unsigned long *)&sl->flags)) {
+				list_del (&sl->w1_slave_entry);
+
+				w1_slave_detach (sl);
+				kfree (sl);
+
+				dev->slave_count--;
+			}
+		}
 		up(&dev->mutex);
 	}
 
@@ -621,3 +796,6 @@
 
 module_init(w1_init);
 module_exit(w1_fini);
+
+EXPORT_SYMBOL(w1_create_master_attributes);
+EXPORT_SYMBOL(w1_destroy_master_attributes);
diff -Nru a/drivers/w1/w1.h b/drivers/w1/w1.h
--- a/drivers/w1/w1.h	2004-10-18 14:57:19 -07:00
+++ b/drivers/w1/w1.h	2004-10-18 14:57:19 -07:00
@@ -52,6 +52,8 @@
 #define W1_READ_PSUPPLY		0xB4
 #define W1_MATCH_ROM		0x55
 
+#define W1_SLAVE_ACTIVE		(1<<0)
+
 struct w1_slave
 {
 	struct module		*owner;
@@ -60,11 +62,15 @@
 	struct w1_reg_num	reg_num;
 	atomic_t		refcnt;
 	u8			rom[9];
+	u32			flags;
 
 	struct w1_master	*master;
 	struct w1_family 	*family;
 	struct device 		dev;
 	struct completion 	dev_released;
+
+	struct bin_attribute 	attr_bin;
+	struct device_attribute	attr_name, attr_val;
 };
 
 struct w1_bus_master
@@ -73,6 +79,16 @@
 
 	u8			(*read_bit)(unsigned long);
 	void			(*write_bit)(unsigned long, u8);
+  	
+	u8			(*read_byte)(unsigned long);
+  	void			(*write_byte)(unsigned long, u8);
+  	
+	u8			(*read_block)(unsigned long, u8 *, int);
+	void			(*write_block)(unsigned long, u8 *, int);
+	
+  	u8			(*touch_bit)(unsigned long, u8);
+  
+  	u8			(*reset_bus)(unsigned long);
 };
 
 struct w1_master
@@ -106,6 +122,9 @@
 	u32			seq, groups;
 	struct sock 		*nls;
 };
+
+int w1_create_master_attributes(struct w1_master *);
+void w1_destroy_master_attributes(struct w1_master *);
 
 #endif /* __KERNEL__ */
 
diff -Nru a/drivers/w1/w1_family.c b/drivers/w1/w1_family.c
--- a/drivers/w1/w1_family.c	2004-10-18 14:56:33 -07:00
+++ b/drivers/w1/w1_family.c	2004-10-18 14:56:33 -07:00
@@ -27,11 +27,22 @@
 spinlock_t w1_flock = SPIN_LOCK_UNLOCKED;
 static LIST_HEAD(w1_families);
 
+static int w1_check_family(struct w1_family *f)
+{
+	if (!f->fops->rname || !f->fops->rbin || !f->fops->rval || !f->fops->rvalname)
+		return -EINVAL;
+
+	return 0;
+}
+
 int w1_register_family(struct w1_family *newf)
 {
 	struct list_head *ent, *n;
 	struct w1_family *f;
 	int ret = 0;
+
+	if (w1_check_family(newf))
+		return -EINVAL;
 
 	spin_lock(&w1_flock);
 	list_for_each_safe(ent, n, &w1_families) {
diff -Nru a/drivers/w1/w1_family.h b/drivers/w1/w1_family.h
--- a/drivers/w1/w1_family.h	2004-10-18 14:57:04 -07:00
+++ b/drivers/w1/w1_family.h	2004-10-18 14:57:04 -07:00
@@ -28,7 +28,7 @@
 
 #define W1_FAMILY_DEFAULT	0
 #define W1_FAMILY_THERM		0x10
-#define W1_FAMILY_IBUT		0xff /* ? */
+#define W1_FAMILY_SMEM		0x01
 
 #define MAXNAMELEN		32
 
diff -Nru a/drivers/w1/w1_int.c b/drivers/w1/w1_int.c
--- a/drivers/w1/w1_int.c	2004-10-18 14:57:03 -07:00
+++ b/drivers/w1/w1_int.c	2004-10-18 14:57:03 -07:00
@@ -24,13 +24,13 @@
 
 #include "w1.h"
 #include "w1_log.h"
+#include "w1_netlink.h"
 
 static u32 w1_ids = 1;
 
 extern struct device_driver w1_driver;
 extern struct bus_type w1_bus_type;
 extern struct device w1_device;
-extern struct device_attribute w1_master_attribute;
 extern int w1_max_slave_count;
 extern struct list_head w1_masters;
 extern spinlock_t w1_mlock;
@@ -119,6 +119,7 @@
 {
 	struct w1_master *dev;
 	int retval = 0;
+	struct w1_netlink_msg msg;
 
 	dev = w1_alloc_dev(w1_ids++, w1_max_slave_count, &w1_driver, &w1_device);
 	if (!dev)
@@ -133,7 +134,7 @@
 		goto err_out_free_dev;
 	}
 
-	retval = device_create_file(&dev->dev, &w1_master_attribute);
+	retval =  w1_create_master_attributes(dev);
 	if (retval)
 		goto err_out_kill_thread;
 
@@ -145,6 +146,11 @@
 	list_add(&dev->w1_master_entry, &w1_masters);
 	spin_unlock(&w1_mlock);
 
+	msg.id.mst.id = dev->id;
+	msg.id.mst.pid = dev->kpid;
+	msg.type = W1_MASTER_ADD;
+	w1_netlink_send(dev, &msg);
+
 	return 0;
 
 err_out_kill_thread:
@@ -164,6 +170,7 @@
 void __w1_remove_master_device(struct w1_master *dev)
 {
 	int err;
+	struct w1_netlink_msg msg;
 
 	dev->need_exit = 1;
 	err = kill_proc(dev->kpid, SIGTERM, 1);
@@ -174,6 +181,11 @@
 
 	while (atomic_read(&dev->refcnt))
 		schedule_timeout(10);
+
+	msg.id.mst.id = dev->id;
+	msg.id.mst.pid = dev->kpid;
+	msg.type = W1_MASTER_REMOVE;
+	w1_netlink_send(dev, &msg);
 
 	w1_free_dev(dev);
 }
diff -Nru a/drivers/w1/w1_io.c b/drivers/w1/w1_io.c
--- a/drivers/w1/w1_io.c	2004-10-18 14:56:33 -07:00
+++ b/drivers/w1/w1_io.c	2004-10-18 14:56:33 -07:00
@@ -55,6 +55,14 @@
 	udelay(tm * w1_delay_parm);
 }
 
+u8 w1_touch_bit(struct w1_master *dev, int bit)
+{
+	if (dev->bus_master->touch_bit)
+		return dev->bus_master->touch_bit(dev->bus_master->data, bit);
+	else
+		return w1_read_bit(dev);
+}
+
 void w1_write_bit(struct w1_master *dev, int bit)
 {
 	if (bit) {
@@ -74,8 +82,11 @@
 {
 	int i;
 
-	for (i = 0; i < 8; ++i)
-		w1_write_bit(dev, (byte >> i) & 0x1);
+	if (dev->bus_master->write_byte)
+		dev->bus_master->write_byte(dev->bus_master->data, byte);
+	else
+		for (i = 0; i < 8; ++i)
+			w1_write_bit(dev, (byte >> i) & 0x1);
 }
 
 u8 w1_read_bit(struct w1_master *dev)
@@ -98,23 +109,57 @@
 	int i;
 	u8 res = 0;
 
-	for (i = 0; i < 8; ++i)
-		res |= (w1_read_bit(dev) << i);
+	if (dev->bus_master->read_byte)
+		res = dev->bus_master->read_byte(dev->bus_master->data);
+	else
+		for (i = 0; i < 8; ++i)
+			res |= (w1_read_bit(dev) << i);
 
 	return res;
 }
 
+void w1_write_block(struct w1_master *dev, u8 *buf, int len)
+{
+	int i;
+
+	if (dev->bus_master->write_block)
+		dev->bus_master->write_block(dev->bus_master->data, buf, len);
+	else
+		for (i = 0; i < len; ++i)
+			w1_write_8(dev, buf[i]);
+}
+
+u8 w1_read_block(struct w1_master *dev, u8 *buf, int len)
+{
+	int i;
+	u8 ret;
+
+	if (dev->bus_master->read_block)
+		ret = dev->bus_master->read_block(dev->bus_master->data, buf, len);
+	else {
+		for (i = 0; i < len; ++i)
+			buf[i] = w1_read_8(dev);
+		ret = len;
+	}
+
+	return ret;
+}
+
 int w1_reset_bus(struct w1_master *dev)
 {
-	int result;
+	int result = 0;
 
-	dev->bus_master->write_bit(dev->bus_master->data, 0);
-	w1_delay(480);
-	dev->bus_master->write_bit(dev->bus_master->data, 1);
-	w1_delay(70);
+	if (dev->bus_master->reset_bus)
+		result = dev->bus_master->reset_bus(dev->bus_master->data) & 0x1;
+	else {
+		dev->bus_master->write_bit(dev->bus_master->data, 0);
+		w1_delay(480);
+		dev->bus_master->write_bit(dev->bus_master->data, 1);
+		w1_delay(70);
 
-	result = dev->bus_master->read_bit(dev->bus_master->data) & 0x1;
-	w1_delay(410);
+		result = dev->bus_master->read_bit(dev->bus_master->data) & 0x1;
+		w1_delay(410);
+	}
 
 	return result;
 }
@@ -136,3 +181,5 @@
 EXPORT_SYMBOL(w1_reset_bus);
 EXPORT_SYMBOL(w1_calc_crc8);
 EXPORT_SYMBOL(w1_delay);
+EXPORT_SYMBOL(w1_read_block);
+EXPORT_SYMBOL(w1_write_block);
diff -Nru a/drivers/w1/w1_io.h b/drivers/w1/w1_io.h
--- a/drivers/w1/w1_io.h	2004-10-18 14:57:03 -07:00
+++ b/drivers/w1/w1_io.h	2004-10-18 14:57:03 -07:00
@@ -25,11 +25,14 @@
 #include "w1.h"
 
 void w1_delay(unsigned long);
+u8 w1_touch_bit(struct w1_master *, int);
 void w1_write_bit(struct w1_master *, int);
 void w1_write_8(struct w1_master *, u8);
 u8 w1_read_bit(struct w1_master *);
 u8 w1_read_8(struct w1_master *);
 int w1_reset_bus(struct w1_master *);
 u8 w1_calc_crc8(u8 *, int);
+void w1_write_block(struct w1_master *, u8 *, int);
+u8 w1_read_block(struct w1_master *, u8 *, int);
 
 #endif /* __W1_IO_H */
diff -Nru a/drivers/w1/w1_netlink.h b/drivers/w1/w1_netlink.h
--- a/drivers/w1/w1_netlink.h	2004-10-18 14:56:33 -07:00
+++ b/drivers/w1/w1_netlink.h	2004-10-18 14:56:33 -07:00
@@ -26,14 +26,27 @@
 
 #include "w1.h"
 
+enum w1_netlink_message_types {
+	W1_SLAVE_ADD = 0,
+	W1_SLAVE_REMOVE,
+	W1_MASTER_ADD,
+	W1_MASTER_REMOVE,
+};
+
 struct w1_netlink_msg 
 {
+	__u8				type;
+	__u8				reserved[3];
 	union
 	{
 		struct w1_reg_num 	id;
 		__u64			w1_id;
+		struct
+		{
+			__u32		id;
+			__u32		pid;
+		} mst;
 	} id;
-	__u64				val;
 };
 
 #ifdef __KERNEL__
diff -Nru a/drivers/w1/w1_smem.c b/drivers/w1/w1_smem.c
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/drivers/w1/w1_smem.c	2004-10-18 14:57:23 -07:00
@@ -0,0 +1,118 @@
+/*
+ * 	w1_smem.c
+ *
+ * Copyright (c) 2004 Evgeniy Polyakov <johnpol@2ka.mipt.ru>
+ * 
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the smems 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
+ */
+
+#include <asm/types.h>
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/device.h>
+#include <linux/types.h>
+
+#include "w1.h"
+#include "w1_io.h"
+#include "w1_int.h"
+#include "w1_family.h"
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Evgeniy Polyakov <johnpol@2ka.mipt.ru>");
+MODULE_DESCRIPTION("Driver for 1-wire Dallas network protocol, 64bit memory family.");
+
+static ssize_t w1_smem_read_name(struct device *, char *);
+static ssize_t w1_smem_read_val(struct device *, char *);
+static ssize_t w1_smem_read_bin(struct kobject *, char *, loff_t, size_t);
+
+static struct w1_family_ops w1_smem_fops = {
+	.rname = &w1_smem_read_name,
+	.rbin = &w1_smem_read_bin,
+	.rval = &w1_smem_read_val,
+	.rvalname = "id",
+};
+
+static ssize_t w1_smem_read_name(struct device *dev, char *buf)
+{
+	struct w1_slave *sl = container_of(dev, struct w1_slave, dev);
+
+	return sprintf(buf, "%s\n", sl->name);
+}
+
+static ssize_t w1_smem_read_val(struct device *dev, char *buf)
+{
+	struct w1_slave *sl = container_of(dev, struct w1_slave, dev);
+	int i;
+	ssize_t count = 0;
+	
+	for (i = 0; i < 9; ++i)
+		count += sprintf(buf + count, "%02x ", ((u8 *)&sl->reg_num)[i]);
+	count += sprintf(buf + count, "\n");
+
+	return count;
+}
+
+static ssize_t w1_smem_read_bin(struct kobject *kobj, char *buf, loff_t off, size_t count)
+{
+	struct w1_slave *sl = container_of(container_of(kobj, struct device, kobj),
+			      			struct w1_slave, dev);
+	int i;
+
+	atomic_inc(&sl->refcnt);
+	if (down_interruptible(&sl->master->mutex)) {
+		count = 0;
+		goto out_dec;
+	}
+
+	if (off > W1_SLAVE_DATA_SIZE) {
+		count = 0;
+		goto out;
+	}
+	if (off + count > W1_SLAVE_DATA_SIZE) {
+		count = 0;
+		goto out;
+	}
+	for (i = 0; i < 9; ++i)
+		count += sprintf(buf + count, "%02x ", ((u8 *)&sl->reg_num)[i]);
+	count += sprintf(buf + count, "\n");
+	
+out:
+	up(&sl->master->mutex);
+out_dec:
+	atomic_dec(&sl->refcnt);
+
+	return count;
+}
+
+static struct w1_family w1_smem_family = {
+	.fid = W1_FAMILY_SMEM,
+	.fops = &w1_smem_fops,
+};
+
+static int __init w1_smem_init(void)
+{
+	return w1_register_family(&w1_smem_family);
+}
+
+static void __exit w1_smem_fini(void)
+{
+	w1_unregister_family(&w1_smem_family);
+}
+
+module_init(w1_smem_init);
+module_exit(w1_smem_fini);
diff -Nru a/drivers/w1/w1_therm.c b/drivers/w1/w1_therm.c
--- a/drivers/w1/w1_therm.c	2004-10-18 14:55:55 -07:00
+++ b/drivers/w1/w1_therm.c	2004-10-18 14:55:55 -07:00
@@ -36,6 +36,11 @@
 MODULE_AUTHOR("Evgeniy Polyakov <johnpol@2ka.mipt.ru>");
 MODULE_DESCRIPTION("Driver for 1-wire Dallas network protocol, temperature family.");
 
+static u8 bad_roms[][9] = {
+				{0xaa, 0x00, 0x4b, 0x46, 0xff, 0xff, 0x0c, 0x10, 0x87}, 
+				{}
+			};
+
 static ssize_t w1_therm_read_name(struct device *, char *);
 static ssize_t w1_therm_read_temp(struct device *, char *);
 static ssize_t w1_therm_read_bin(struct kobject *, char *, loff_t, size_t);
@@ -69,14 +74,24 @@
 	return sprintf(buf, "%d\n", temp * 1000);
 }
 
+static int w1_therm_check_rom(u8 rom[9])
+{
+	int i;
+
+	for (i=0; i<sizeof(bad_roms)/9; ++i)
+		if (!memcmp(bad_roms[i], rom, 9))
+			return 1;
+
+	return 0;
+}
+
 static ssize_t w1_therm_read_bin(struct kobject *kobj, char *buf, loff_t off, size_t count)
 {
 	struct w1_slave *sl = container_of(container_of(kobj, struct device, kobj),
 			      			struct w1_slave, dev);
 	struct w1_master *dev = sl->master;
 	u8 rom[9], crc, verdict;
-	size_t icount;
-	int i;
+	int i, max_trying = 10;
 	u16 temp;
 
 	atomic_inc(&sl->refcnt);
@@ -89,10 +104,10 @@
 		count = 0;
 		goto out;
 	}
-	if (off + count > W1_SLAVE_DATA_SIZE)
-		count = W1_SLAVE_DATA_SIZE - off;
-
-	icount = count;
+	if (off + count > W1_SLAVE_DATA_SIZE) {
+		count = 0;
+		goto out;
+	}
 
 	memset(buf, 0, count);
 	memset(rom, 0, sizeof(rom));
@@ -100,56 +115,54 @@
 	count = 0;
 	verdict = 0;
 	crc = 0;
-	if (!w1_reset_bus(dev)) {
-		u64 id = *(u64 *) & sl->reg_num;
-		int count = 0;
-
-		w1_write_8(dev, W1_MATCH_ROM);
-		for (i = 0; i < 8; ++i)
-			w1_write_8(dev, (id >> i * 8) & 0xff);
-
-		w1_write_8(dev, W1_CONVERT_TEMP);
-
-		while (dev->bus_master->read_bit(dev->bus_master->data) == 0
-		       && count < 10) {
-			w1_delay(1);
-			count++;
-		}
-
-		if (count < 10) {
-			if (!w1_reset_bus(dev)) {
-				w1_write_8(dev, W1_MATCH_ROM);
-				for (i = 0; i < 8; ++i)
-					w1_write_8(dev,
-						   (id >> i * 8) & 0xff);
-
-				w1_write_8(dev, W1_READ_SCRATCHPAD);
-				for (i = 0; i < 9; ++i)
-					rom[i] = w1_read_8(dev);
 
-				crc = w1_calc_crc8(rom, 8);
-
-				if (rom[8] == crc && rom[0])
-					verdict = 1;
+	while (max_trying--) {
+		if (!w1_reset_bus (dev)) {
+			int count = 0;
+			u8 match[9] = {W1_MATCH_ROM, };
+
+			memcpy(&match[1], (u64 *) & sl->reg_num, 8);
+			
+			w1_write_block(dev, match, 9);
+
+			w1_write_8(dev, W1_CONVERT_TEMP);
+
+			if (count < 10) {
+				if (!w1_reset_bus(dev)) {
+					w1_write_block(dev, match, 9);
+
+					w1_write_8(dev, W1_READ_SCRATCHPAD);
+					if ((count = w1_read_block(dev, rom, 9)) != 9) {
+						dev_warn(&dev->dev, "w1_read_block() returned %d instead of 9.\n", count);
+					}
+
+					crc = w1_calc_crc8(rom, 8);
+
+					if (rom[8] == crc && rom[0])
+						verdict = 1;
+				}
 			}
+			else
+				dev_warn(&dev->dev,
+					  "18S20 doesn't respond to CONVERT_TEMP.\n");
 		}
-		else
-			dev_warn(&dev->dev,
-				  "18S20 doesn't respond to CONVERT_TEMP.\n");
+
+		if (!w1_therm_check_rom(rom))
+			break;
 	}
 
 	for (i = 0; i < 9; ++i)
-		count += snprintf(buf + count, icount - count, "%02x ", rom[i]);
-	count += snprintf(buf + count, icount - count, ": crc=%02x %s\n",
+		count += sprintf(buf + count, "%02x ", rom[i]);
+	count += sprintf(buf + count, ": crc=%02x %s\n",
 			   crc, (verdict) ? "YES" : "NO");
 	if (verdict)
 		memcpy(sl->rom, rom, sizeof(sl->rom));
 	for (i = 0; i < 9; ++i)
-		count += snprintf(buf + count, icount - count, "%02x ", sl->rom[i]);
+		count += sprintf(buf + count, "%02x ", sl->rom[i]);
 	temp = 0;
 	temp <<= sl->rom[1] / 2;
 	temp |= sl->rom[0] / 2;
-	count += snprintf(buf + count, icount - count, "t=%u\n", temp);
+	count += sprintf(buf + count, "t=%u\n", temp);
 out:
 	up(&dev->mutex);
 out_dec:
diff -Nru a/drivers/zorro/Makefile b/drivers/zorro/Makefile
--- a/drivers/zorro/Makefile	2004-10-18 14:56:28 -07:00
+++ b/drivers/zorro/Makefile	2004-10-18 14:56:28 -07:00
@@ -5,7 +5,7 @@
 obj-$(CONFIG_ZORRO)	+= zorro.o zorro-driver.o zorro-sysfs.o names.o
 obj-$(CONFIG_PROC_FS)	+= proc.o
 
-host-progs 		:= gen-devlist
+hostprogs-y 		:= gen-devlist
 
 # Files generated that shall be removed upon make clean
 clean-files := devlist.h
diff -Nru a/fs/Kconfig b/fs/Kconfig
--- a/fs/Kconfig	2004-10-18 14:56:33 -07:00
+++ b/fs/Kconfig	2004-10-18 14:56:33 -07:00
@@ -289,7 +289,7 @@
 # 	Never use this symbol for ifdefs.
 #
 	bool
-	depends on EXT2_FS_POSIX_ACL || EXT3_FS_POSIX_ACL || JFS_POSIX_ACL || REISERFS_FS_POSIX_ACL
+	depends on EXT2_FS_POSIX_ACL || EXT3_FS_POSIX_ACL || JFS_POSIX_ACL || REISERFS_FS_POSIX_ACL || NFSD_V4
 	default y
 
 config XFS_FS
@@ -650,18 +650,21 @@
 	default 437
 	help
 	  This option should be set to the codepage of your FAT filesystems.
-	  It can be overridden with the 'codepage' mount option.
+	  It can be overridden with the "codepage" mount option.
+	  See <file:Documentation/filesystems/vfat.txt> for more information.
 
 config FAT_DEFAULT_IOCHARSET
 	string "Default iocharset for FAT"
 	depends on VFAT_FS
 	default "iso8859-1"
 	help
-	  Set this to the default I/O character set you'd like FAT to use.
-	  It should probably match the character set that most of your
-	  FAT filesystems use, and can be overridded with the 'iocharset'
-	  mount option for FAT filesystems.  Note that UTF8 is *not* a
-	  supported charset for FAT filesystems.
+	  Set this to the default input/output character set you'd
+	  like FAT to use. It should probably match the character set
+	  that most of your FAT filesystems use, and can be overridden
+	  with the "iocharset" mount option for FAT filesystems.
+	  Note that "utf8" is not recommended for FAT filesystems.
+	  If unsure, you shouldn't set "utf8" here.
+	  See <file:Documentation/filesystems/vfat.txt> for more information.
 
 config UMSDOS_FS
 #dep_tristate '    UMSDOS: Unix-like file system on top of standard MSDOS fs' CONFIG_UMSDOS_FS $CONFIG_MSDOS_FS
@@ -1213,7 +1216,7 @@
 endchoice
 
 config CRAMFS
-	tristate "Compressed ROM file system support"
+	tristate "Compressed ROM file system support (cramfs)"
 	select ZLIB_INFLATE
 	help
 	  Saying Y here includes support for CramFs (Compressed ROM File
@@ -1415,8 +1418,8 @@
 	bool "Provide NFSv3 client support"
 	depends on NFS_FS
 	help
-	  Say Y here if you want your NFS client to be able to speak the newer
-	  version 3 of the NFS protocol.
+	  Say Y here if you want your NFS client to be able to speak version
+	  3 of the NFS protocol.
 
 	  If unsure, say Y.
 
@@ -1495,6 +1498,7 @@
 config NFSD_V4
 	bool "Provide NFSv4 server support (EXPERIMENTAL)"
 	depends on NFSD_V3 && EXPERIMENTAL
+	select NFSD_TCP
 	help
 	  If you would like to include the NFSv4 server as well as the NFSv2
 	  and NFSv3 servers, say Y here.  This feature is experimental, and
@@ -1556,6 +1560,22 @@
 
 	  Note: Requires an auxiliary userspace daemon which may be found on
 		http://www.citi.umich.edu/projects/nfsv4/
+
+	  If unsure, say N.
+
+config RPCSEC_GSS_SPKM3
+	tristate "Secure RPC: SPKM3 mechanism (EXPERIMENTAL)"
+	depends on SUNRPC && EXPERIMENTAL
+	select SUNRPC_GSS
+	select CRYPTO
+	select CRYPTO_MD5
+	select CRYPTO_DES
+	help
+	  Provides for secure RPC calls by means of a gss-api
+	  mechanism based on the SPKM3 public-key mechanism.
+
+	  Note: Requires an auxiliary userspace daemon which may be found on
+	  	http://www.citi.umich.edu/projects/nfsv4/
 
 	  If unsure, say N.
 
diff -Nru a/fs/Makefile b/fs/Makefile
--- a/fs/Makefile	2004-10-18 14:56:33 -07:00
+++ b/fs/Makefile	2004-10-18 14:56:33 -07:00
@@ -91,3 +91,5 @@
 obj-$(CONFIG_XFS_FS)		+= xfs/
 obj-$(CONFIG_AFS_FS)		+= afs/
 obj-$(CONFIG_BEFS_FS)		+= befs/
+obj-$(CONFIG_HOSTFS)		+= hostfs/
+obj-$(CONFIG_HPPFS)		+= hppfs/
diff -Nru a/fs/adfs/adfs.h b/fs/adfs/adfs.h
--- a/fs/adfs/adfs.h	2004-10-18 14:57:03 -07:00
+++ b/fs/adfs/adfs.h	2004-10-18 14:57:03 -07:00
@@ -64,15 +64,9 @@
 	unsigned int		dm_endbit;
 };
 
-/* dir stuff */
-
-
 /* Inode stuff */
-int adfs_get_block(struct inode *inode, sector_t block,
-		   struct buffer_head *bh, int create);
 struct inode *adfs_iget(struct super_block *sb, struct object_info *obj);
-void adfs_read_inode(struct inode *inode);
-void adfs_write_inode(struct inode *inode,int unused);
+int adfs_write_inode(struct inode *inode,int unused);
 int adfs_notify_change(struct dentry *dentry, struct iattr *attr);
 
 /* map.c */
@@ -83,9 +77,6 @@
 void __adfs_error(struct super_block *sb, const char *function,
 		  const char *fmt, ...);
 #define adfs_error(sb, fmt...) __adfs_error(sb, __FUNCTION__, fmt)
-
-/* namei.c */
-extern struct dentry *adfs_lookup(struct inode *dir, struct dentry *dentry, struct nameidata *);
 
 /* super.c */
 
diff -Nru a/fs/adfs/dir.c b/fs/adfs/dir.c
--- a/fs/adfs/dir.c	2004-10-18 14:56:33 -07:00
+++ b/fs/adfs/dir.c	2004-10-18 14:56:33 -07:00
@@ -268,7 +268,8 @@
 	.d_compare	= adfs_compare,
 };
 
-struct dentry *adfs_lookup(struct inode *dir, struct dentry *dentry, struct nameidata *nd)
+static struct dentry *
+adfs_lookup(struct inode *dir, struct dentry *dentry, struct nameidata *nd)
 {
 	struct inode *inode = NULL;
 	struct object_info obj;
diff -Nru a/fs/adfs/dir_f.c b/fs/adfs/dir_f.c
--- a/fs/adfs/dir_f.c	2004-10-18 14:56:33 -07:00
+++ b/fs/adfs/dir_f.c	2004-10-18 14:56:33 -07:00
@@ -93,7 +93,7 @@
 #define dir_u32(idx)				\
 	({ int _buf = idx >> blocksize_bits;	\
 	   int _off = idx - (_buf << blocksize_bits);\
-	  *(u32 *)(bh[_buf]->b_data + _off);	\
+	  *(__le32 *)(bh[_buf]->b_data + _off);	\
 	})
 
 #define bufoff(_bh,_idx)			\
@@ -112,7 +112,7 @@
 {
 	struct buffer_head * const *bh = dir->bh;
 	const int blocksize_bits = dir->sb->s_blocksize_bits;
-	union { u32 *ptr32; u8 *ptr8; } ptr, end;
+	union { __le32 *ptr32; u8 *ptr8; } ptr, end;
 	u32 dircheck = 0;
 	int last = 5 - 26;
 	int i = 0;
@@ -125,7 +125,7 @@
 	do {
 		last += 26;
 		do {
-			dircheck = cpu_to_le32(dir_u32(i)) ^ ror13(dircheck);
+			dircheck = le32_to_cpu(dir_u32(i)) ^ ror13(dircheck);
 
 			i += sizeof(u32);
 		} while (i < (last & ~3));
@@ -155,8 +155,8 @@
 	end.ptr8 = ptr.ptr8 + 36;
 
 	do {
-		unsigned int v = *ptr.ptr32++;
-		dircheck = cpu_to_le32(v) ^ ror13(dircheck);
+		__le32 v = *ptr.ptr32++;
+		dircheck = le32_to_cpu(v) ^ ror13(dircheck);
 	} while (ptr.ptr32 < end.ptr32);
 
 	return (dircheck ^ (dircheck >> 8) ^ (dircheck >> 16) ^ (dircheck >> 24)) & 0xff;
@@ -165,7 +165,7 @@
 /*
  * Read and check that a directory is valid
  */
-int
+static int
 adfs_dir_read(struct super_block *sb, unsigned long object_id,
 	      unsigned int size, struct adfs_dir *dir)
 {
@@ -260,7 +260,7 @@
  * get a directory entry.  Note that the caller is responsible
  * for holding the relevant locks.
  */
-int
+static int
 __adfs_dir_get(struct adfs_dir *dir, int pos, struct object_info *obj)
 {
 	struct super_block *sb = dir->sb;
@@ -290,7 +290,7 @@
 	return 0;
 }
 
-int
+static int
 __adfs_dir_put(struct adfs_dir *dir, int pos, struct object_info *obj)
 {
 	struct super_block *sb = dir->sb;
diff -Nru a/fs/adfs/dir_fplus.h b/fs/adfs/dir_fplus.h
--- a/fs/adfs/dir_fplus.h	2004-10-18 14:56:28 -07:00
+++ b/fs/adfs/dir_fplus.h	2004-10-18 14:56:28 -07:00
@@ -18,27 +18,27 @@
 struct adfs_bigdirheader {
 	__u8	startmasseq;
 	__u8	bigdirversion[3];
-	__u32	bigdirstartname;
-	__u32	bigdirnamelen;
-	__u32	bigdirsize;
-	__u32	bigdirentries;
-	__u32	bigdirnamesize;
-	__u32	bigdirparent;
+	__le32	bigdirstartname;
+	__le32	bigdirnamelen;
+	__le32	bigdirsize;
+	__le32	bigdirentries;
+	__le32	bigdirnamesize;
+	__le32	bigdirparent;
 	char	bigdirname[1];
 };
 
 struct adfs_bigdirentry {
-	__u32	bigdirload;
-	__u32	bigdirexec;
-	__u32	bigdirlen;
-	__u32	bigdirindaddr;
-	__u32	bigdirattr;
-	__u32	bigdirobnamelen;
-	__u32	bigdirobnameptr;
+	__le32	bigdirload;
+	__le32	bigdirexec;
+	__le32	bigdirlen;
+	__le32	bigdirindaddr;
+	__le32	bigdirattr;
+	__le32	bigdirobnamelen;
+	__le32	bigdirobnameptr;
 };
 
 struct adfs_bigdirtail {
-	__u32	bigdirendname;
+	__le32	bigdirendname;
 	__u8	bigdirendmasseq;
 	__u8	reserved[2];
 	__u8	bigdircheckbyte;
diff -Nru a/fs/adfs/inode.c b/fs/adfs/inode.c
--- a/fs/adfs/inode.c	2004-10-18 14:56:28 -07:00
+++ b/fs/adfs/inode.c	2004-10-18 14:56:28 -07:00
@@ -24,8 +24,9 @@
  * Lookup/Create a block at offset 'block' into 'inode'.  We currently do
  * not support creation of new blocks, so we return -EIO for this case.
  */
-int
-adfs_get_block(struct inode *inode, sector_t block, struct buffer_head *bh, int create)
+static int
+adfs_get_block(struct inode *inode, sector_t block, struct buffer_head *bh,
+	       int create)
 {
 	if (block < 0)
 		goto abort_negative;
@@ -372,10 +373,11 @@
  * The adfs-specific inode data has already been updated by
  * adfs_notify_change()
  */
-void adfs_write_inode(struct inode *inode, int unused)
+int adfs_write_inode(struct inode *inode, int unused)
 {
 	struct super_block *sb = inode->i_sb;
 	struct object_info obj;
+	int ret;
 
 	lock_kernel();
 	obj.file_id	= inode->i_ino;
@@ -386,7 +388,8 @@
 	obj.attr	= ADFS_I(inode)->attr;
 	obj.size	= inode->i_size;
 
-	adfs_dir_update(sb, &obj);
+	ret = adfs_dir_update(sb, &obj);
 	unlock_kernel();
+	return ret;
 }
 MODULE_LICENSE("GPL");
diff -Nru a/fs/adfs/map.c b/fs/adfs/map.c
--- a/fs/adfs/map.c	2004-10-18 14:56:29 -07:00
+++ b/fs/adfs/map.c	2004-10-18 14:56:29 -07:00
@@ -92,9 +92,8 @@
 		 * find end of fragment
 		 */
 		{
-			u32 v, *_map = (u32 *)map;
-
-			v = le32_to_cpu(_map[mapptr >> 5]) >> (mapptr & 31);
+			__le32 *_map = (__le32 *)map;
+			u32 v = le32_to_cpu(_map[mapptr >> 5]) >> (mapptr & 31);
 			while (v == 0) {
 				mapptr = (mapptr & ~31) + 32;
 				if (mapptr >= mapsize)
@@ -171,9 +170,8 @@
 		 * find end of fragment
 		 */
 		{
-			u32 v, *_map = (u32 *)map;
-
-			v = le32_to_cpu(_map[mapptr >> 5]) >> (mapptr & 31);
+			__le32 *_map = (__le32 *)map;
+			u32 v = le32_to_cpu(_map[mapptr >> 5]) >> (mapptr & 31);
 			while (v == 0) {
 				mapptr = (mapptr & ~31) + 32;
 				if (mapptr >= mapsize)
diff -Nru a/fs/adfs/super.c b/fs/adfs/super.c
--- a/fs/adfs/super.c	2004-10-18 14:55:53 -07:00
+++ b/fs/adfs/super.c	2004-10-18 14:55:53 -07:00
@@ -62,7 +62,7 @@
 	 * are unable to represent sector offsets in
 	 * 32 bits.  This works out at 2.0 TB.
 	 */
-	if (dr->disc_size_high >> dr->log2secsize)
+	if (le32_to_cpu(dr->disc_size_high) >> dr->log2secsize)
 		return 1;
 
 	/* idlen must be no greater than 19 v2 [1.0] */
@@ -241,7 +241,7 @@
 {
 	adfs_inode_cachep = kmem_cache_create("adfs_inode_cache",
 					     sizeof(struct adfs_inode_info),
-					     0, SLAB_HWCACHE_ALIGN|SLAB_RECLAIM_ACCOUNT,
+					     0, SLAB_RECLAIM_ACCOUNT,
 					     init_once, NULL);
 	if (adfs_inode_cachep == NULL)
 		return -ENOMEM;
@@ -300,8 +300,8 @@
 	i = zone - 1;
 	dm[0].dm_startblk = 0;
 	dm[0].dm_startbit = ADFS_DR_SIZE_BITS;
-	dm[i].dm_endbit   = (dr->disc_size_high << (32 - dr->log2bpmb)) +
-			    (dr->disc_size >> dr->log2bpmb) +
+	dm[i].dm_endbit   = (le32_to_cpu(dr->disc_size_high) << (32 - dr->log2bpmb)) +
+			    (le32_to_cpu(dr->disc_size) >> dr->log2bpmb) +
 			    (ADFS_DR_SIZE_BITS - i * zone_size);
 
 	if (adfs_checkmap(sb, dm))
@@ -439,7 +439,7 @@
 	 * get the root_size from the disc record.
 	 */
 	if (asb->s_version) {
-		root_obj.size = dr->root_size;
+		root_obj.size = le32_to_cpu(dr->root_size);
 		asb->s_dir     = &adfs_fplus_dir_ops;
 		asb->s_namelen = ADFS_FPLUS_NAME_LEN;
 	} else {
diff -Nru a/fs/affs/amigaffs.c b/fs/affs/amigaffs.c
--- a/fs/affs/amigaffs.c	2004-10-18 14:56:20 -07:00
+++ b/fs/affs/amigaffs.c	2004-10-18 14:56:20 -07:00
@@ -84,7 +84,8 @@
 {
 	struct super_block *sb;
 	struct buffer_head *bh;
-	u32 rem_ino, hash_ino, ino;
+	u32 rem_ino, hash_ino;
+	__be32 ino;
 	int offset, retval;
 
 	sb = dir->i_sb;
@@ -203,9 +204,9 @@
 
 	while ((ino = be32_to_cpu(AFFS_TAIL(sb, bh)->link_chain)) != 0) {
 		if (ino == link_ino) {
-			ino = AFFS_TAIL(sb, link_bh)->link_chain;
-			AFFS_TAIL(sb, bh)->link_chain = ino;
-			affs_adjust_checksum(bh, be32_to_cpu(ino) - link_ino);
+			__be32 ino2 = AFFS_TAIL(sb, link_bh)->link_chain;
+			AFFS_TAIL(sb, bh)->link_chain = ino2;
+			affs_adjust_checksum(bh, be32_to_cpu(ino2) - link_ino);
 			mark_buffer_dirty_inode(bh, inode);
 			retval = 0;
 			/* Fix the link count, if bh is a normal header block without links */
@@ -341,12 +342,12 @@
 u32
 affs_checksum_block(struct super_block *sb, struct buffer_head *bh)
 {
-	u32 *ptr = (u32 *)bh->b_data;
+	__be32 *ptr = (__be32 *)bh->b_data;
 	u32 sum;
 	int bsize;
 
 	sum = 0;
-	for (bsize = sb->s_blocksize / sizeof(u32); bsize > 0; bsize--)
+	for (bsize = sb->s_blocksize / sizeof(__be32); bsize > 0; bsize--)
 		sum += be32_to_cpu(*ptr++);
 	return sum;
 }
@@ -359,9 +360,10 @@
 void
 affs_fix_checksum(struct super_block *sb, struct buffer_head *bh)
 {
-	int cnt = sb->s_blocksize / sizeof(u32);
-	u32 *ptr = (u32 *)bh->b_data;
-	u32 checksum, *checksumptr;
+	int cnt = sb->s_blocksize / sizeof(__be32);
+	__be32 *ptr = (__be32 *)bh->b_data;
+	u32 checksum;
+	__be32 *checksumptr;
 
 	checksumptr = ptr + 5;
 	*checksumptr = 0;
@@ -384,9 +386,9 @@
 	minute  = secs / 60;
 	secs   -= minute * 60;
 
-	ds->days = be32_to_cpu(days);
-	ds->mins = be32_to_cpu(minute);
-	ds->ticks = be32_to_cpu(secs * 50);
+	ds->days = cpu_to_be32(days);
+	ds->mins = cpu_to_be32(minute);
+	ds->ticks = cpu_to_be32(secs * 50);
 }
 
 mode_t
diff -Nru a/fs/affs/bitmap.c b/fs/affs/bitmap.c
--- a/fs/affs/bitmap.c	2004-10-18 14:57:04 -07:00
+++ b/fs/affs/bitmap.c	2004-10-18 14:57:04 -07:00
@@ -21,7 +21,7 @@
 
 static int nibblemap[] = { 0,1,1,2,1,2,2,3,1,2,2,3,2,3,3,4 };
 
-u32
+static u32
 affs_count_free_bits(u32 blocksize, const void *data)
 {
 	const u32 *map;
@@ -72,7 +72,7 @@
 	struct affs_bm_info *bm;
 	struct buffer_head *bh;
 	u32 blk, bmap, bit, mask, tmp;
-	u32 *data;
+	__be32 *data;
 
 	pr_debug("AFFS: free_block(%u)\n", block);
 
@@ -97,7 +97,7 @@
 	}
 
 	mask = 1 << (bit & 31);
-	data = (u32 *)bh->b_data + bit / 32 + 1;
+	data = (__be32 *)bh->b_data + bit / 32 + 1;
 
 	/* mark block free */
 	tmp = be32_to_cpu(*data);
@@ -106,8 +106,8 @@
 	*data = cpu_to_be32(tmp | mask);
 
 	/* fix checksum */
-	tmp = be32_to_cpu(*(u32 *)bh->b_data);
-	*(u32 *)bh->b_data = cpu_to_be32(tmp - mask);
+	tmp = be32_to_cpu(*(__be32 *)bh->b_data);
+	*(__be32 *)bh->b_data = cpu_to_be32(tmp - mask);
 
 	mark_buffer_dirty(bh);
 	sb->s_dirt = 1;
@@ -149,7 +149,7 @@
 	struct affs_sb_info *sbi;
 	struct affs_bm_info *bm;
 	struct buffer_head *bh;
-	u32 *data, *enddata;
+	__be32 *data, *enddata;
 	u32 blk, bmap, bit, mask, mask2, tmp;
 	int i;
 
@@ -211,8 +211,8 @@
 
 	/* find an unused block in this bitmap block */
 	bit = blk % sbi->s_bmap_bits;
-	data = (u32 *)bh->b_data + bit / 32 + 1;
-	enddata = (u32 *)((u8 *)bh->b_data + sb->s_blocksize);
+	data = (__be32 *)bh->b_data + bit / 32 + 1;
+	enddata = (__be32 *)((u8 *)bh->b_data + sb->s_blocksize);
 	mask = ~0UL << (bit & 31);
 	blk &= ~31UL;
 
@@ -228,8 +228,8 @@
 			 * if scan didn't start at 0, try next bmap
 			 */
 			goto find_bmap;
-	} while (!(tmp = *data));
-	tmp = be32_to_cpu(tmp);
+	} while (!*data);
+	tmp = be32_to_cpu(*data);
 	mask = ~0;
 
 find_bit:
@@ -251,8 +251,8 @@
 	*data = cpu_to_be32(tmp & ~mask);
 
 	/* fix checksum */
-	tmp = be32_to_cpu(*(u32 *)bh->b_data);
-	*(u32 *)bh->b_data = cpu_to_be32(tmp + mask);
+	tmp = be32_to_cpu(*(__be32 *)bh->b_data);
+	*(__be32 *)bh->b_data = cpu_to_be32(tmp + mask);
 
 	mark_buffer_dirty(bh);
 	sb->s_dirt = 1;
@@ -276,7 +276,7 @@
 {
 	struct affs_bm_info *bm;
 	struct buffer_head *bmap_bh = NULL, *bh = NULL;
-	u32 *bmap_blk;
+	__be32 *bmap_blk;
 	u32 size, blk, end, offset, mask;
 	int i, res = 0;
 	struct affs_sb_info *sbi = AFFS_SB(sb);
@@ -304,7 +304,7 @@
 	}
 	memset(sbi->s_bitmap, 0, size);
 
-	bmap_blk = (u32 *)sbi->s_root_bh->b_data;
+	bmap_blk = (__be32 *)sbi->s_root_bh->b_data;
 	blk = sb->s_blocksize / 4 - 49;
 	end = blk + 25;
 
@@ -340,7 +340,7 @@
 			res = -EIO;
 			goto out;
 		}
-		bmap_blk = (u32 *)bmap_bh->b_data;
+		bmap_blk = (__be32 *)bmap_bh->b_data;
 		blk = 0;
 		end = sb->s_blocksize / 4 - 1;
 	}
@@ -354,23 +354,23 @@
 		u32 old, new;
 
 		/* Mark unused bits in the last word as allocated */
-		old = be32_to_cpu(((u32 *)bh->b_data)[offset]);
+		old = be32_to_cpu(((__be32 *)bh->b_data)[offset]);
 		new = old & mask;
 		//if (old != new) {
-			((u32 *)bh->b_data)[offset] = cpu_to_be32(new);
+			((__be32 *)bh->b_data)[offset] = cpu_to_be32(new);
 			/* fix checksum */
 			//new -= old;
-			//old = be32_to_cpu(*(u32 *)bh->b_data);
-			//*(u32 *)bh->b_data = cpu_to_be32(old - new);
+			//old = be32_to_cpu(*(__be32 *)bh->b_data);
+			//*(__be32 *)bh->b_data = cpu_to_be32(old - new);
 			//mark_buffer_dirty(bh);
 		//}
 		/* correct offset for the bitmap count below */
 		//offset++;
 	}
 	while (++offset < sb->s_blocksize / 4)
-		((u32 *)bh->b_data)[offset] = 0;
-	((u32 *)bh->b_data)[0] = 0;
-	((u32 *)bh->b_data)[0] = cpu_to_be32(-affs_checksum_block(sb, bh));
+		((__be32 *)bh->b_data)[offset] = 0;
+	((__be32 *)bh->b_data)[0] = 0;
+	((__be32 *)bh->b_data)[0] = cpu_to_be32(-affs_checksum_block(sb, bh));
 	mark_buffer_dirty(bh);
 
 	/* recalculate bitmap count for last block */
diff -Nru a/fs/affs/inode.c b/fs/affs/inode.c
--- a/fs/affs/inode.c	2004-10-18 14:56:29 -07:00
+++ b/fs/affs/inode.c	2004-10-18 14:56:29 -07:00
@@ -181,7 +181,7 @@
 	return;
 }
 
-void
+int
 affs_write_inode(struct inode *inode, int unused)
 {
 	struct super_block	*sb = inode->i_sb;
@@ -194,14 +194,14 @@
 
 	if (!inode->i_nlink)
 		// possibly free block
-		return;
+		return 0;
 	bh = affs_bread(sb, inode->i_ino);
 	if (!bh) {
 		affs_error(sb,"write_inode","Cannot read block %lu",inode->i_ino);
-		return;
+		return -EIO;
 	}
 	tail = AFFS_TAIL(sb, bh);
-	if (tail->stype == be32_to_cpu(ST_ROOT)) {
+	if (tail->stype == cpu_to_be32(ST_ROOT)) {
 		secs_to_datestamp(inode->i_mtime.tv_sec,&AFFS_ROOT_TAIL(sb, bh)->root_change);
 	} else {
 		tail->protect = cpu_to_be32(AFFS_I(inode)->i_protect);
@@ -226,6 +226,7 @@
 	mark_buffer_dirty_inode(bh, inode);
 	affs_brelse(bh);
 	affs_free_prealloc(inode);
+	return 0;
 }
 
 int
@@ -396,7 +397,7 @@
 	AFFS_TAIL(sb, bh)->parent = cpu_to_be32(dir->i_ino);
 
 	if (inode_bh) {
-		u32 chain;
+		__be32 chain;
 	       	chain = AFFS_TAIL(sb, inode_bh)->link_chain;
 		AFFS_TAIL(sb, bh)->original = cpu_to_be32(inode->i_ino);
 		AFFS_TAIL(sb, bh)->link_chain = chain;
diff -Nru a/fs/affs/namei.c b/fs/affs/namei.c
--- a/fs/affs/namei.c	2004-10-18 14:56:28 -07:00
+++ b/fs/affs/namei.c	2004-10-18 14:56:28 -07:00
@@ -37,7 +37,7 @@
 	.d_compare	= affs_compare_dentry,
 };
 
-struct dentry_operations affs_intl_dentry_operations = {
+static struct dentry_operations affs_intl_dentry_operations = {
 	.d_hash		= affs_intl_hash_dentry,
 	.d_compare	= affs_intl_compare_dentry,
 };
diff -Nru a/fs/affs/super.c b/fs/affs/super.c
--- a/fs/affs/super.c	2004-10-18 14:56:48 -07:00
+++ b/fs/affs/super.c	2004-10-18 14:56:48 -07:00
@@ -44,7 +44,7 @@
 	pr_debug("AFFS: put_super()\n");
 
 	if (!(sb->s_flags & MS_RDONLY)) {
-		AFFS_ROOT_TAIL(sb, sbi->s_root_bh)->bm_flag = be32_to_cpu(1);
+		AFFS_ROOT_TAIL(sb, sbi->s_root_bh)->bm_flag = cpu_to_be32(1);
 		secs_to_datestamp(get_seconds(),
 				  &AFFS_ROOT_TAIL(sb, sbi->s_root_bh)->disk_change);
 		affs_fix_checksum(sb, sbi->s_root_bh);
@@ -70,7 +70,7 @@
 		//	if (sbi->s_bitmap[i].bm_bh) {
 		//		if (buffer_dirty(sbi->s_bitmap[i].bm_bh)) {
 		//			clean = 0;
-		AFFS_ROOT_TAIL(sb, sbi->s_root_bh)->bm_flag = be32_to_cpu(clean);
+		AFFS_ROOT_TAIL(sb, sbi->s_root_bh)->bm_flag = cpu_to_be32(clean);
 		secs_to_datestamp(get_seconds(),
 				  &AFFS_ROOT_TAIL(sb, sbi->s_root_bh)->disk_change);
 		affs_fix_checksum(sb, sbi->s_root_bh);
@@ -115,7 +115,7 @@
 {
 	affs_inode_cachep = kmem_cache_create("affs_inode_cache",
 					     sizeof(struct affs_inode_info),
-					     0, SLAB_HWCACHE_ALIGN|SLAB_RECLAIM_ACCOUNT,
+					     0, SLAB_RECLAIM_ACCOUNT,
 					     init_once, NULL);
 	if (affs_inode_cachep == NULL)
 		return -ENOMEM;
@@ -387,7 +387,7 @@
 		printk(KERN_ERR "AFFS: Cannot read boot block\n");
 		goto out_error;
 	}
-	chksum = be32_to_cpu(*(u32 *)boot_bh->b_data);
+	chksum = be32_to_cpu(*(__be32 *)boot_bh->b_data);
 	brelse(boot_bh);
 
 	/* Dircache filesystems are compatible with non-dircache ones
diff -Nru a/fs/afs/cmservice.c b/fs/afs/cmservice.c
--- a/fs/afs/cmservice.c	2004-10-18 14:56:29 -07:00
+++ b/fs/afs/cmservice.c	2004-10-18 14:56:29 -07:00
@@ -424,7 +424,7 @@
 		{
 			struct afs_callback *cb, *pcb;
 			int loop;
-			u32 *fp, *bp;
+			__be32 *fp, *bp;
 
 			fp = rxrpc_call_alloc_scratch(call, qty);
 
diff -Nru a/fs/afs/dir.c b/fs/afs/dir.c
--- a/fs/afs/dir.c	2004-10-18 14:56:28 -07:00
+++ b/fs/afs/dir.c	2004-10-18 14:56:28 -07:00
@@ -65,9 +65,9 @@
 	struct {
 		uint8_t		valid;
 		uint8_t		unused[1];
-		uint16_t	hash_next;
-		uint32_t	vnode;
-		uint32_t	unique;
+		__be16		hash_next;
+		__be32		vnode;
+		__be32		unique;
 		uint8_t		name[16];
 		uint8_t		overflow[4];	/* if any char of the name (inc
 						 * NUL) reaches here, consume
@@ -78,8 +78,8 @@
 
 /* AFS directory page header (one at the beginning of every 2048-byte chunk) */
 struct afs_dir_pagehdr {
-	uint16_t	npages;
-	uint16_t	magic;
+	__be16		npages;
+	__be16		magic;
 #define AFS_DIR_MAGIC htons(1234)
 	uint8_t		nentries;
 	uint8_t		bitmap[8];
@@ -308,7 +308,7 @@
 			      blkoff + offset * sizeof(union afs_dirent),
 			      ntohl(dire->u.vnode),
 			      filldir == afs_dir_lookup_filldir ?
-			      dire->u.unique : DT_UNKNOWN);
+			      ntohl(dire->u.unique) : DT_UNKNOWN);
 		if (ret < 0) {
 			_leave(" = 0 [full]");
 			return 0;
@@ -416,7 +416,7 @@
 	struct afs_dir_lookup_cookie *cookie = _cookie;
 
 	_enter("{%s,%Zu},%s,%u,,%lu,%u",
-	       cookie->name, cookie->nlen, name, nlen, ino, ntohl(dtype));
+	       cookie->name, cookie->nlen, name, nlen, ino, dtype);
 
 	if (cookie->nlen != nlen || memcmp(cookie->name, name, nlen) != 0) {
 		_leave(" = 0 [no]");
@@ -424,7 +424,7 @@
 	}
 
 	cookie->fid.vnode = ino;
-	cookie->fid.unique = ntohl(dtype);
+	cookie->fid.unique = dtype;
 	cookie->found = 1;
 
 	_leave(" = -1 [found]");
diff -Nru a/fs/afs/fsclient.c b/fs/afs/fsclient.c
--- a/fs/afs/fsclient.c	2004-10-18 14:57:04 -07:00
+++ b/fs/afs/fsclient.c	2004-10-18 14:57:04 -07:00
@@ -307,7 +307,7 @@
 	struct kvec piov[1];
 	size_t sent;
 	int ret;
-	u32 *bp;
+	__be32 *bp;
 
 	DECLARE_WAITQUEUE(myself, current);
 
@@ -432,7 +432,7 @@
 	struct kvec piov[1];
 	size_t sent;
 	int ret;
-	u32 *bp;
+	__be32 *bp;
 
 	DECLARE_WAITQUEUE(myself, current);
 
@@ -583,7 +583,7 @@
 	struct kvec piov[1];
 	size_t sent;
 	int ret;
-	u32 *bp;
+	__be32 *bp;
 
 	DECLARE_WAITQUEUE(myself, current);
 
diff -Nru a/fs/afs/inode.c b/fs/afs/inode.c
--- a/fs/afs/inode.c	2004-10-18 14:57:19 -07:00
+++ b/fs/afs/inode.c	2004-10-18 14:57:19 -07:00
@@ -93,9 +93,10 @@
 
 /*****************************************************************************/
 /*
- * attempt to fetch the status of an inode, coelescing multiple simultaneous fetches
+ * attempt to fetch the status of an inode, coelescing multiple simultaneous
+ * fetches
  */
-int afs_inode_fetch_status(struct inode *inode)
+static int afs_inode_fetch_status(struct inode *inode)
 {
 	struct afs_vnode *vnode;
 	int ret;
diff -Nru a/fs/afs/main.c b/fs/afs/main.c
--- a/fs/afs/main.c	2004-10-18 14:56:27 -07:00
+++ b/fs/afs/main.c	2004-10-18 14:56:27 -07:00
@@ -10,6 +10,7 @@
  */
 
 #include <linux/module.h>
+#include <linux/moduleparam.h>
 #include <linux/init.h>
 #include <linux/sched.h>
 #include <linux/completion.h>
@@ -47,7 +48,7 @@
 
 static char *rootcell;
 
-MODULE_PARM(rootcell, "s");
+module_param(rootcell, charp, 0);
 MODULE_PARM_DESC(rootcell, "root AFS cell name and VL server IP addr list");
 
 
diff -Nru a/fs/afs/mntpt.c b/fs/afs/mntpt.c
--- a/fs/afs/mntpt.c	2004-10-18 14:56:16 -07:00
+++ b/fs/afs/mntpt.c	2004-10-18 14:56:16 -07:00
@@ -235,8 +235,8 @@
  */
 static int afs_mntpt_follow_link(struct dentry *dentry, struct nameidata *nd)
 {
-	struct nameidata newnd;
 	struct vfsmount *newmnt;
+	struct dentry *old_dentry;
 	int err;
 
 	kenter("%p{%s},{%s:%p{%s}}",
@@ -247,15 +247,19 @@
 	       nd->dentry->d_name.name);
 
 	newmnt = afs_mntpt_do_automount(dentry);
-	if (IS_ERR(newmnt))
+	if (IS_ERR(newmnt)) {
+		path_release(nd);
 		return PTR_ERR(newmnt);
+	}
+
+	old_dentry = nd->dentry;
+	nd->dentry = dentry;
+	err = do_add_mount(newmnt, nd, 0, &afs_vfsmounts);
+	nd->dentry = old_dentry;
 
-	newnd = *nd;
-	newnd.dentry = dentry;
-	err = do_add_mount(newmnt, &newnd, 0, &afs_vfsmounts);
+	path_release(nd);
 
 	if (!err) {
-		path_release(nd);
 		mntget(newmnt);
 		nd->mnt = newmnt;
 		dget(newmnt->mnt_root);
diff -Nru a/fs/afs/vlclient.c b/fs/afs/vlclient.c
--- a/fs/afs/vlclient.c	2004-10-18 14:55:53 -07:00
+++ b/fs/afs/vlclient.c	2004-10-18 14:55:53 -07:00
@@ -89,18 +89,19 @@
 	}
 } /* end afs_rxvl_aemap() */
 
+#if 0
 /*****************************************************************************/
 /*
- * probe a volume location server to see if it is still alive
+ * probe a volume location server to see if it is still alive -- unused
  */
-int afs_rxvl_probe(struct afs_server *server, int alloc_flags)
+static int afs_rxvl_probe(struct afs_server *server, int alloc_flags)
 {
 	struct rxrpc_connection *conn;
 	struct rxrpc_call *call;
 	struct kvec piov[1];
 	size_t sent;
 	int ret;
-	u32 param[1];
+	__be32 param[1];
 
 	DECLARE_WAITQUEUE(myself, current);
 
@@ -173,6 +174,7 @@
 	return ret;
 
 } /* end afs_rxvl_probe() */
+#endif
 
 /*****************************************************************************/
 /*
@@ -191,7 +193,7 @@
 	unsigned tmp;
 	size_t sent;
 	int ret, loop;
-	u32 *bp, param[2], zero;
+	__be32 *bp, param[2], zero;
 
 	_enter(",%*.*s,%u,", volnamesz, volnamesz, volname, volnamesz);
 
@@ -326,7 +328,7 @@
 	unsigned tmp;
 	size_t sent;
 	int ret, loop;
-	u32 *bp, param[3];
+	__be32 *bp, param[3];
 
 	_enter(",%x,%d,", volid, voltype);
 
@@ -462,7 +464,7 @@
 	struct kvec piov[1];
 	size_t sent;
 	int ret;
-	u32 param[3];
+	__be32 param[3];
 
 	_enter(",%x,%d,", volid, voltype);
 
@@ -545,7 +547,8 @@
 int afs_rxvl_get_entry_by_id_async2(struct afs_async_op *op,
 				    struct afs_cache_vlocation *entry)
 {
-	unsigned *bp, tmp;
+	__be32 *bp;
+	__u32 tmp;
 	int loop, ret;
 
 	_enter("{op=%p cst=%u}", op, op->call->app_call_state);
diff -Nru a/fs/afs/vlclient.h b/fs/afs/vlclient.h
--- a/fs/afs/vlclient.h	2004-10-18 14:55:54 -07:00
+++ b/fs/afs/vlclient.h	2004-10-18 14:55:54 -07:00
@@ -71,9 +71,6 @@
 
 };
 
-/* probe a volume location server to see if it is still alive */
-extern int afs_rxvl_probe(struct afs_server *server, int alloc_flags);
-
 /* look up a volume location database entry by name */
 extern int afs_rxvl_get_entry_by_name(struct afs_server *server,
 				      const char *volname,
diff -Nru a/fs/afs/vlocation.c b/fs/afs/vlocation.c
--- a/fs/afs/vlocation.c	2004-10-18 14:56:28 -07:00
+++ b/fs/afs/vlocation.c	2004-10-18 14:56:28 -07:00
@@ -29,6 +29,7 @@
 static void afs_vlocation_update_timer(struct afs_timer *timer);
 static void afs_vlocation_update_attend(struct afs_async_op *op);
 static void afs_vlocation_update_discard(struct afs_async_op *op);
+static void __afs_put_vlocation(struct afs_vlocation *vlocation);
 
 static void __afs_vlocation_timeout(struct afs_timer *timer)
 {
@@ -455,7 +456,7 @@
  * finish using a volume location record
  * - caller must have cell->vol_sem write-locked
  */
-void __afs_put_vlocation(struct afs_vlocation *vlocation)
+static void __afs_put_vlocation(struct afs_vlocation *vlocation)
 {
 	struct afs_cell *cell;
 
diff -Nru a/fs/afs/vnode.c b/fs/afs/vnode.c
--- a/fs/afs/vnode.c	2004-10-18 14:56:28 -07:00
+++ b/fs/afs/vnode.c	2004-10-18 14:56:28 -07:00
@@ -86,9 +86,9 @@
  * - starts callback expiry timer
  * - adds to server's callback list
  */
-void afs_vnode_finalise_status_update(struct afs_vnode *vnode,
-				      struct afs_server *server,
-				      int ret)
+static void afs_vnode_finalise_status_update(struct afs_vnode *vnode,
+					     struct afs_server *server,
+					     int ret)
 {
 	struct afs_server *oldserver = NULL;
 
diff -Nru a/fs/afs/volume.h b/fs/afs/volume.h
--- a/fs/afs/volume.h	2004-10-18 14:56:50 -07:00
+++ b/fs/afs/volume.h	2004-10-18 14:56:50 -07:00
@@ -99,7 +99,6 @@
 
 #define afs_get_vlocation(V) do { atomic_inc(&(V)->usage); } while(0)
 
-extern void __afs_put_vlocation(struct afs_vlocation *vlocation);
 extern void afs_put_vlocation(struct afs_vlocation *vlocation);
 extern void afs_vlocation_do_timeout(struct afs_vlocation *vlocation);
 
diff -Nru a/fs/aio.c b/fs/aio.c
--- a/fs/aio.c	2004-10-18 14:56:29 -07:00
+++ b/fs/aio.c	2004-10-18 14:56:29 -07:00
@@ -39,6 +39,9 @@
 #define dprintk(x...)	do { ; } while (0)
 #endif
 
+long aio_run = 0; /* for testing only */
+long aio_wakeups = 0; /* for testing only */
+
 /*------ sysctl variables----*/
 atomic_t aio_nr = ATOMIC_INIT(0);	/* current system wide number of aio requests */
 unsigned aio_max_nr = 0x10000;	/* system wide maximum number of aio requests */
@@ -277,6 +280,7 @@
 		struct kiocb *iocb = list_kiocb(pos);
 		list_del_init(&iocb->ki_list);
 		cancel = iocb->ki_cancel;
+		kiocbSetCancelled(iocb);
 		if (cancel) {
 			iocb->ki_users++;
 			spin_unlock_irq(&ctx->ctx_lock);
@@ -337,6 +341,11 @@
 		aio_cancel_all(ctx);
 
 		wait_for_all_aios(ctx);
+		/*
+		 * this is an overkill, but ensures we don't leave
+		 * the ctx on the aio_wq
+		 */
+		flush_workqueue(aio_wq);
 
 		if (1 != atomic_read(&ctx->users))
 			printk(KERN_DEBUG
@@ -359,6 +368,8 @@
 	if (unlikely(ctx->reqs_active))
 		BUG();
 
+	cancel_delayed_work(&ctx->wq);
+	flush_workqueue(aio_wq);
 	aio_free_ring(ctx);
 	mmdrop(ctx->mm);
 	ctx->mm = NULL;
@@ -398,6 +409,7 @@
 	req->ki_obj.user = NULL;
 	req->ki_dtor = NULL;
 	req->private = NULL;
+	INIT_LIST_HEAD(&req->ki_run_list);
 
 	/* Check if the completion queue has enough free space to
 	 * accept an event from this io.
@@ -543,85 +555,367 @@
 	return ioctx;
 }
 
+/*
+ * use_mm
+ *	Makes the calling kernel thread take on the specified
+ *	mm context.
+ *	Called by the retry thread execute retries within the
+ *	iocb issuer's mm context, so that copy_from/to_user
+ *	operations work seamlessly for aio.
+ *	(Note: this routine is intended to be called only
+ *	from a kernel thread context)
+ */
 static void use_mm(struct mm_struct *mm)
 {
 	struct mm_struct *active_mm;
+	struct task_struct *tsk = current;
 
+	task_lock(tsk);
+	active_mm = tsk->active_mm;
 	atomic_inc(&mm->mm_count);
-	task_lock(current);
-	active_mm = current->active_mm;
-	current->mm = mm;
-	if (mm != active_mm) {
-		current->active_mm = mm;
-		activate_mm(active_mm, mm);
-	}
-	task_unlock(current);
+	tsk->mm = mm;
+	tsk->active_mm = mm;
+	activate_mm(active_mm, mm);
+	task_unlock(tsk);
+
 	mmdrop(active_mm);
 }
 
-static void unuse_mm(struct mm_struct *mm)
+/*
+ * unuse_mm
+ *	Reverses the effect of use_mm, i.e. releases the
+ *	specified mm context which was earlier taken on
+ *	by the calling kernel thread
+ *	(Note: this routine is intended to be called only
+ *	from a kernel thread context)
+ *
+ * Comments: Called with ctx->ctx_lock held. This nests
+ * task_lock instead ctx_lock.
+ */
+void unuse_mm(struct mm_struct *mm)
 {
-	task_lock(current);
-	current->mm = NULL;
-	task_unlock(current);
+	struct task_struct *tsk = current;
+
+	task_lock(tsk);
+	tsk->mm = NULL;
 	/* active_mm is still 'mm' */
-	enter_lazy_tlb(mm, current);
+	enter_lazy_tlb(mm, tsk);
+	task_unlock(tsk);
 }
 
-/* Run on kevent's context.  FIXME: needs to be per-cpu and warn if an
- * operation blocks.
+/*
+ * Queue up a kiocb to be retried. Assumes that the kiocb
+ * has already been marked as kicked, and places it on
+ * the retry run list for the corresponding ioctx, if it
+ * isn't already queued. Returns 1 if it actually queued
+ * the kiocb (to tell the caller to activate the work
+ * queue to process it), or 0, if it found that it was
+ * already queued.
+ *
+ * Should be called with the spin lock iocb->ki_ctx->ctx_lock
+ * held
  */
-static void aio_kick_handler(void *data)
+static inline int __queue_kicked_iocb(struct kiocb *iocb)
 {
-	struct kioctx *ctx = data;
+	struct kioctx *ctx = iocb->ki_ctx;
 
-	use_mm(ctx->mm);
+	if (list_empty(&iocb->ki_run_list)) {
+		list_add_tail(&iocb->ki_run_list,
+			&ctx->run_list);
+		iocb->ki_queued++;
+		return 1;
+	}
+	return 0;
+}
 
-	spin_lock_irq(&ctx->ctx_lock);
-	while (!list_empty(&ctx->run_list)) {
-		struct kiocb *iocb;
-		long ret;
+/* aio_run_iocb
+ *	This is the core aio execution routine. It is
+ *	invoked both for initial i/o submission and
+ *	subsequent retries via the aio_kick_handler.
+ *	Expects to be invoked with iocb->ki_ctx->lock
+ *	already held. The lock is released and reaquired
+ *	as needed during processing.
+ *
+ * Calls the iocb retry method (already setup for the
+ * iocb on initial submission) for operation specific
+ * handling, but takes care of most of common retry
+ * execution details for a given iocb. The retry method
+ * needs to be non-blocking as far as possible, to avoid
+ * holding up other iocbs waiting to be serviced by the
+ * retry kernel thread.
+ *
+ * The trickier parts in this code have to do with
+ * ensuring that only one retry instance is in progress
+ * for a given iocb at any time. Providing that guarantee
+ * simplifies the coding of individual aio operations as
+ * it avoids various potential races.
+ */
+static ssize_t aio_run_iocb(struct kiocb *iocb)
+{
+	struct kioctx	*ctx = iocb->ki_ctx;
+	ssize_t (*retry)(struct kiocb *);
+	ssize_t ret;
 
-		iocb = list_entry(ctx->run_list.next, struct kiocb,
-				  ki_run_list);
-		list_del(&iocb->ki_run_list);
-		iocb->ki_users ++;
-		spin_unlock_irq(&ctx->ctx_lock);
+	if (iocb->ki_retried++ > 1024*1024) {
+		printk("Maximal retry count.  Bytes done %Zd\n",
+			iocb->ki_nbytes - iocb->ki_left);
+		return -EAGAIN;
+	}
+
+	if (!(iocb->ki_retried & 0xff)) {
+		pr_debug("%ld retry: %d of %d (kick %ld, Q %ld run %ld, wake %ld)\n",
+			iocb->ki_retried,
+			iocb->ki_nbytes - iocb->ki_left, iocb->ki_nbytes,
+			iocb->ki_kicked, iocb->ki_queued, aio_run, aio_wakeups);
+	}
 
-		kiocbClearKicked(iocb);
-		ret = iocb->ki_retry(iocb);
-		if (-EIOCBQUEUED != ret) {
+	if (!(retry = iocb->ki_retry)) {
+		printk("aio_run_iocb: iocb->ki_retry = NULL\n");
+		return 0;
+	}
+
+	/*
+	 * We don't want the next retry iteration for this
+	 * operation to start until this one has returned and
+	 * updated the iocb state. However, wait_queue functions
+	 * can trigger a kick_iocb from interrupt context in the
+	 * meantime, indicating that data is available for the next
+	 * iteration. We want to remember that and enable the
+	 * next retry iteration _after_ we are through with
+	 * this one.
+	 *
+	 * So, in order to be able to register a "kick", but
+	 * prevent it from being queued now, we clear the kick
+	 * flag, but make the kick code *think* that the iocb is
+	 * still on the run list until we are actually done.
+	 * When we are done with this iteration, we check if
+	 * the iocb was kicked in the meantime and if so, queue
+	 * it up afresh.
+	 */
+
+	kiocbClearKicked(iocb);
+
+	/*
+	 * This is so that aio_complete knows it doesn't need to
+	 * pull the iocb off the run list (We can't just call
+	 * INIT_LIST_HEAD because we don't want a kick_iocb to
+	 * queue this on the run list yet)
+	 */
+	iocb->ki_run_list.next = iocb->ki_run_list.prev = NULL;
+	spin_unlock_irq(&ctx->ctx_lock);
+
+	/* Quit retrying if the i/o has been cancelled */
+	if (kiocbIsCancelled(iocb)) {
+		ret = -EINTR;
+		aio_complete(iocb, ret, 0);
+		/* must not access the iocb after this */
+		goto out;
+	}
+
+	/*
+	 * Now we are all set to call the retry method in async
+	 * context. By setting this thread's io_wait context
+	 * to point to the wait queue entry inside the currently
+	 * running iocb for the duration of the retry, we ensure
+	 * that async notification wakeups are queued by the
+	 * operation instead of blocking waits, and when notified,
+	 * cause the iocb to be kicked for continuation (through
+	 * the aio_wake_function callback).
+	 */
+	BUG_ON(current->io_wait != NULL);
+	current->io_wait = &iocb->ki_wait;
+	ret = retry(iocb);
+	current->io_wait = NULL;
+
+	if (-EIOCBRETRY != ret) {
+ 		if (-EIOCBQUEUED != ret) {
+			BUG_ON(!list_empty(&iocb->ki_wait.task_list));
 			aio_complete(iocb, ret, 0);
-			iocb = NULL;
+			/* must not access the iocb after this */
 		}
+	} else {
+		/*
+		 * Issue an additional retry to avoid waiting forever if
+		 * no waits were queued (e.g. in case of a short read).
+		 */
+		if (list_empty(&iocb->ki_wait.task_list))
+			kiocbSetKicked(iocb);
+	}
+out:
+	spin_lock_irq(&ctx->ctx_lock);
 
-		spin_lock_irq(&ctx->ctx_lock);
-		if (NULL != iocb)
-			__aio_put_req(ctx, iocb);
+	if (-EIOCBRETRY == ret) {
+		/*
+		 * OK, now that we are done with this iteration
+		 * and know that there is more left to go,
+		 * this is where we let go so that a subsequent
+		 * "kick" can start the next iteration
+		 */
+
+		/* will make __queue_kicked_iocb succeed from here on */
+		INIT_LIST_HEAD(&iocb->ki_run_list);
+		/* we must queue the next iteration ourselves, if it
+		 * has already been kicked */
+		if (kiocbIsKicked(iocb)) {
+			__queue_kicked_iocb(iocb);
+		}
 	}
+	return ret;
+}
+
+/*
+ * __aio_run_iocbs:
+ * 	Process all pending retries queued on the ioctx
+ * 	run list.
+ * Assumes it is operating within the aio issuer's mm
+ * context. Expects to be called with ctx->ctx_lock held
+ */
+static int __aio_run_iocbs(struct kioctx *ctx)
+{
+	struct kiocb *iocb;
+	int count = 0;
+	LIST_HEAD(run_list);
+
+	list_splice_init(&ctx->run_list, &run_list);
+	while (!list_empty(&run_list)) {
+		iocb = list_entry(run_list.next, struct kiocb,
+			ki_run_list);
+		list_del(&iocb->ki_run_list);
+		/*
+		 * Hold an extra reference while retrying i/o.
+		 */
+		iocb->ki_users++;       /* grab extra reference */
+		aio_run_iocb(iocb);
+		if (__aio_put_req(ctx, iocb))  /* drop extra ref */
+			put_ioctx(ctx);
+		count++;
+ 	}
+	aio_run++;
+	if (!list_empty(&ctx->run_list))
+		return 1;
+	return 0;
+}
+
+static void aio_queue_work(struct kioctx * ctx)
+{
+	unsigned long timeout;
+	/*
+	 * if someone is waiting, get the work started right
+	 * away, otherwise, use a longer delay
+	 */
+	smp_mb();
+	if (waitqueue_active(&ctx->wait))
+		timeout = 1;
+	else
+		timeout = HZ/10;
+	queue_delayed_work(aio_wq, &ctx->wq, timeout);
+}
+
+
+/*
+ * aio_run_iocbs:
+ * 	Process all pending retries queued on the ioctx
+ * 	run list.
+ * Assumes it is operating within the aio issuer's mm
+ * context.
+ */
+static inline void aio_run_iocbs(struct kioctx *ctx)
+{
+	int requeue;
+
+	spin_lock_irq(&ctx->ctx_lock);
+
+	requeue = __aio_run_iocbs(ctx);
 	spin_unlock_irq(&ctx->ctx_lock);
+	if (requeue)
+		aio_queue_work(ctx);
+}
 
-	unuse_mm(ctx->mm);
+/*
+ * just like aio_run_iocbs, but keeps running them until
+ * the list stays empty
+ */
+static inline void aio_run_all_iocbs(struct kioctx *ctx)
+{
+	spin_lock_irq(&ctx->ctx_lock);
+	while (__aio_run_iocbs(ctx))
+		;
+	spin_unlock_irq(&ctx->ctx_lock);
 }
 
-void fastcall kick_iocb(struct kiocb *iocb)
+/*
+ * aio_kick_handler:
+ * 	Work queue handler triggered to process pending
+ * 	retries on an ioctx. Takes on the aio issuer's
+ *	mm context before running the iocbs, so that
+ *	copy_xxx_user operates on the issuer's address
+ *      space.
+ * Run on aiod's context.
+ */
+static void aio_kick_handler(void *data)
 {
-	struct kioctx	*ctx = iocb->ki_ctx;
+	struct kioctx *ctx = data;
+	mm_segment_t oldfs = get_fs();
+	int requeue;
 
+	set_fs(USER_DS);
+	use_mm(ctx->mm);
+	spin_lock_irq(&ctx->ctx_lock);
+	requeue =__aio_run_iocbs(ctx);
+ 	unuse_mm(ctx->mm);
+	spin_unlock_irq(&ctx->ctx_lock);
+	set_fs(oldfs);
+	/*
+	 * we're in a worker thread already, don't use queue_delayed_work,
+	 */
+	if (requeue)
+		queue_work(aio_wq, &ctx->wq);
+}
+
+
+/*
+ * Called by kick_iocb to queue the kiocb for retry
+ * and if required activate the aio work queue to process
+ * it
+ */
+void queue_kicked_iocb(struct kiocb *iocb)
+{
+ 	struct kioctx	*ctx = iocb->ki_ctx;
+	unsigned long flags;
+	int run = 0;
+
+	WARN_ON((!list_empty(&iocb->ki_wait.task_list)));
+
+	spin_lock_irqsave(&ctx->ctx_lock, flags);
+	run = __queue_kicked_iocb(iocb);
+	spin_unlock_irqrestore(&ctx->ctx_lock, flags);
+	if (run) {
+		aio_queue_work(ctx);
+		aio_wakeups++;
+	}
+}
+
+/*
+ * kick_iocb:
+ *      Called typically from a wait queue callback context
+ *      (aio_wake_function) to trigger a retry of the iocb.
+ *      The retry is usually executed by aio workqueue
+ *      threads (See aio_kick_handler).
+ */
+void fastcall kick_iocb(struct kiocb *iocb)
+{
 	/* sync iocbs are easy: they can only ever be executing from a 
 	 * single context. */
 	if (is_sync_kiocb(iocb)) {
 		kiocbSetKicked(iocb);
-		wake_up_process(iocb->ki_obj.tsk);
+	        wake_up_process(iocb->ki_obj.tsk);
 		return;
 	}
 
+	iocb->ki_kicked++;
+	/* If its already kicked we shouldn't queue it again */
 	if (!kiocbTryKick(iocb)) {
-		unsigned long flags;
-		spin_lock_irqsave(&ctx->ctx_lock, flags);
-		list_add_tail(&iocb->ki_run_list, &ctx->run_list);
-		spin_unlock_irqrestore(&ctx->ctx_lock, flags);
-		queue_work(aio_wq, &ctx->wq);
+		queue_kicked_iocb(iocb);
 	}
 }
 EXPORT_SYMBOL(kick_iocb);
@@ -675,6 +969,16 @@
 	 */
 	spin_lock_irqsave(&ctx->ctx_lock, flags);
 
+	if (iocb->ki_run_list.prev && !list_empty(&iocb->ki_run_list))
+		list_del_init(&iocb->ki_run_list);
+
+	/*
+	 * cancelled requests don't get events, userland was given one
+	 * when the event got cancelled.
+	 */
+	if (kiocbIsCancelled(iocb))
+		goto put_rq;
+
 	ring = kmap_atomic(info->ring_pages[0], KM_IRQ1);
 
 	tail = info->tail;
@@ -703,6 +1007,11 @@
 
 	pr_debug("added to ring %p at [%lu]\n", iocb, tail);
 
+	pr_debug("%ld retries: %d of %d (kicked %ld, Q %ld run %ld wake %ld)\n",
+		iocb->ki_retried,
+		iocb->ki_nbytes - iocb->ki_left, iocb->ki_nbytes,
+		iocb->ki_kicked, iocb->ki_queued, aio_run, aio_wakeups);
+put_rq:
 	/* everything turned out well, dispose of the aiocb. */
 	ret = __aio_put_req(ctx, iocb);
 
@@ -759,7 +1068,7 @@
 	return ret;
 }
 
-struct timeout {
+struct aio_timeout {
 	struct timer_list	timer;
 	int			timed_out;
 	struct task_struct	*p;
@@ -767,13 +1076,13 @@
 
 static void timeout_func(unsigned long data)
 {
-	struct timeout *to = (struct timeout *)data;
+	struct aio_timeout *to = (struct aio_timeout *)data;
 
 	to->timed_out = 1;
 	wake_up_process(to->p);
 }
 
-static inline void init_timeout(struct timeout *to)
+static inline void init_timeout(struct aio_timeout *to)
 {
 	init_timer(&to->timer);
 	to->timer.data = (unsigned long)to;
@@ -782,7 +1091,7 @@
 	to->p = current;
 }
 
-static inline void set_timeout(long start_jiffies, struct timeout *to,
+static inline void set_timeout(long start_jiffies, struct aio_timeout *to,
 			       const struct timespec *ts)
 {
 	to->timer.expires = start_jiffies + timespec_to_jiffies(ts);
@@ -792,7 +1101,7 @@
 		to->timed_out = 1;
 }
 
-static inline void clear_timeout(struct timeout *to)
+static inline void clear_timeout(struct aio_timeout *to)
 {
 	del_singleshot_timer_sync(&to->timer);
 }
@@ -808,14 +1117,16 @@
 	int			ret;
 	int			i = 0;
 	struct io_event		ent;
-	struct timeout		to;
+	struct aio_timeout	to;
+	int 			event_loop = 0; /* testing only */
+	int			retry = 0;
 
 	/* needed to zero any padding within an entry (there shouldn't be 
 	 * any, but C is fun!
 	 */
 	memset(&ent, 0, sizeof(ent));
+retry:
 	ret = 0;
-
 	while (likely(i < nr)) {
 		ret = aio_read_evt(ctx, &ent);
 		if (unlikely(ret <= 0))
@@ -844,6 +1155,13 @@
 
 	/* End fast path */
 
+	/* racey check, but it gets redone */
+	if (!retry && unlikely(!list_empty(&ctx->run_list))) {
+		retry = 1;
+		aio_run_all_iocbs(ctx);
+		goto retry;
+	}
+
 	init_timeout(&to);
 	if (timeout) {
 		struct timespec	ts;
@@ -858,7 +1176,6 @@
 		add_wait_queue_exclusive(&ctx->wait, &wait);
 		do {
 			set_task_state(tsk, TASK_INTERRUPTIBLE);
-
 			ret = aio_read_evt(ctx, &ent);
 			if (ret)
 				break;
@@ -868,6 +1185,7 @@
 			if (to.timed_out)	/* Only check after read evt */
 				break;
 			schedule();
+			event_loop++;
 			if (signal_pending(tsk)) {
 				ret = -EINTR;
 				break;
@@ -895,6 +1213,9 @@
 	if (timeout)
 		clear_timeout(&to);
 out:
+	pr_debug("event loop executed %d times\n", event_loop);
+	pr_debug("aio_run %ld\n", aio_run);
+	pr_debug("aio_wakeups %ld\n", aio_wakeups);
 	return i ? i : ret;
 }
 
@@ -962,7 +1283,7 @@
 		ret = put_user(ioctx->user_id, ctxp);
 		if (!ret)
 			return 0;
-	 	get_ioctx(ioctx);
+
 		io_destroy(ioctx);
 	}
 
@@ -987,13 +1308,181 @@
 	return -EINVAL;
 }
 
+/*
+ * Default retry method for aio_read (also used for first time submit)
+ * Responsible for updating iocb state as retries progress
+ */
+static ssize_t aio_pread(struct kiocb *iocb)
+{
+	struct file *file = iocb->ki_filp;
+	struct address_space *mapping = file->f_mapping;
+	struct inode *inode = mapping->host;
+	ssize_t ret = 0;
+
+	ret = file->f_op->aio_read(iocb, iocb->ki_buf,
+		iocb->ki_left, iocb->ki_pos);
+
+	/*
+	 * Can't just depend on iocb->ki_left to determine
+	 * whether we are done. This may have been a short read.
+	 */
+	if (ret > 0) {
+		iocb->ki_buf += ret;
+		iocb->ki_left -= ret;
+		/*
+		 * For pipes and sockets we return once we have
+		 * some data; for regular files we retry till we
+		 * complete the entire read or find that we can't
+		 * read any more data (e.g short reads).
+		 */
+		if (!S_ISFIFO(inode->i_mode) && !S_ISSOCK(inode->i_mode))
+			ret = -EIOCBRETRY;
+	}
+
+	/* This means we must have transferred all that we could */
+	/* No need to retry anymore */
+	if ((ret == 0) || (iocb->ki_left == 0))
+		ret = iocb->ki_nbytes - iocb->ki_left;
+
+	return ret;
+}
+
+/*
+ * Default retry method for aio_write (also used for first time submit)
+ * Responsible for updating iocb state as retries progress
+ */
+static ssize_t aio_pwrite(struct kiocb *iocb)
+{
+	struct file *file = iocb->ki_filp;
+	ssize_t ret = 0;
+
+	ret = file->f_op->aio_write(iocb, iocb->ki_buf,
+		iocb->ki_left, iocb->ki_pos);
+
+	if (ret > 0) {
+		iocb->ki_buf += ret;
+		iocb->ki_left -= ret;
+
+		ret = -EIOCBRETRY;
+	}
+
+	/* This means we must have transferred all that we could */
+	/* No need to retry anymore */
+	if ((ret == 0) || (iocb->ki_left == 0))
+		ret = iocb->ki_nbytes - iocb->ki_left;
+
+	return ret;
+}
+
+static ssize_t aio_fdsync(struct kiocb *iocb)
+{
+	struct file *file = iocb->ki_filp;
+	ssize_t ret = -EINVAL;
+
+	if (file->f_op->aio_fsync)
+		ret = file->f_op->aio_fsync(iocb, 1);
+	return ret;
+}
+
+static ssize_t aio_fsync(struct kiocb *iocb)
+{
+	struct file *file = iocb->ki_filp;
+	ssize_t ret = -EINVAL;
+
+	if (file->f_op->aio_fsync)
+		ret = file->f_op->aio_fsync(iocb, 0);
+	return ret;
+}
+
+/*
+ * aio_setup_iocb:
+ *	Performs the initial checks and aio retry method
+ *	setup for the kiocb at the time of io submission.
+ */
+ssize_t aio_setup_iocb(struct kiocb *kiocb)
+{
+	struct file *file = kiocb->ki_filp;
+	ssize_t ret = 0;
+
+	switch (kiocb->ki_opcode) {
+	case IOCB_CMD_PREAD:
+		ret = -EBADF;
+		if (unlikely(!(file->f_mode & FMODE_READ)))
+			break;
+		ret = -EFAULT;
+		if (unlikely(!access_ok(VERIFY_WRITE, kiocb->ki_buf,
+			kiocb->ki_left)))
+			break;
+		ret = -EINVAL;
+		if (file->f_op->aio_read)
+			kiocb->ki_retry = aio_pread;
+		break;
+	case IOCB_CMD_PWRITE:
+		ret = -EBADF;
+		if (unlikely(!(file->f_mode & FMODE_WRITE)))
+			break;
+		ret = -EFAULT;
+		if (unlikely(!access_ok(VERIFY_READ, kiocb->ki_buf,
+			kiocb->ki_left)))
+			break;
+		ret = -EINVAL;
+		if (file->f_op->aio_write)
+			kiocb->ki_retry = aio_pwrite;
+		break;
+	case IOCB_CMD_FDSYNC:
+		ret = -EINVAL;
+		if (file->f_op->aio_fsync)
+			kiocb->ki_retry = aio_fdsync;
+		break;
+	case IOCB_CMD_FSYNC:
+		ret = -EINVAL;
+		if (file->f_op->aio_fsync)
+			kiocb->ki_retry = aio_fsync;
+		break;
+	default:
+		dprintk("EINVAL: io_submit: no operation provided\n");
+		ret = -EINVAL;
+	}
+
+	if (!kiocb->ki_retry)
+		return ret;
+
+	return 0;
+}
+
+/*
+ * aio_wake_function:
+ * 	wait queue callback function for aio notification,
+ * 	Simply triggers a retry of the operation via kick_iocb.
+ *
+ * 	This callback is specified in the wait queue entry in
+ *	a kiocb	(current->io_wait points to this wait queue
+ *	entry when an aio operation executes; it is used
+ * 	instead of a synchronous wait when an i/o blocking
+ *	condition is encountered during aio).
+ *
+ * Note:
+ * This routine is executed with the wait queue lock held.
+ * Since kick_iocb acquires iocb->ctx->ctx_lock, it nests
+ * the ioctx lock inside the wait queue lock. This is safe
+ * because this callback isn't used for wait queues which
+ * are nested inside ioctx lock (i.e. ctx->wait)
+ */
+int aio_wake_function(wait_queue_t *wait, unsigned mode, int sync, void *key)
+{
+	struct kiocb *iocb = container_of(wait, struct kiocb, ki_wait);
+
+	list_del_init(&wait->task_list);
+	kick_iocb(iocb);
+	return 1;
+}
+
 int fastcall io_submit_one(struct kioctx *ctx, struct iocb __user *user_iocb,
 			 struct iocb *iocb)
 {
 	struct kiocb *req;
 	struct file *file;
 	ssize_t ret;
-	char __user *buf;
 
 	/* enforce forwards compatibility on users */
 	if (unlikely(iocb->aio_reserved1 || iocb->aio_reserved2 ||
@@ -1034,58 +1523,31 @@
 	req->ki_user_data = iocb->aio_data;
 	req->ki_pos = iocb->aio_offset;
 
-	buf = (char __user *)(unsigned long)iocb->aio_buf;
+	req->ki_buf = (char __user *)(unsigned long)iocb->aio_buf;
+	req->ki_left = req->ki_nbytes = iocb->aio_nbytes;
+	req->ki_opcode = iocb->aio_lio_opcode;
+	init_waitqueue_func_entry(&req->ki_wait, aio_wake_function);
+	INIT_LIST_HEAD(&req->ki_wait.task_list);
+	req->ki_run_list.next = req->ki_run_list.prev = NULL;
+	req->ki_retry = NULL;
+	req->ki_retried = 0;
+	req->ki_kicked = 0;
+	req->ki_queued = 0;
+	aio_run = 0;
+	aio_wakeups = 0;
 
-	switch (iocb->aio_lio_opcode) {
-	case IOCB_CMD_PREAD:
-		ret = -EBADF;
-		if (unlikely(!(file->f_mode & FMODE_READ)))
-			goto out_put_req;
-		ret = -EFAULT;
-		if (unlikely(!access_ok(VERIFY_WRITE, buf, iocb->aio_nbytes)))
-			goto out_put_req;
-		ret = security_file_permission (file, MAY_READ);
-		if (ret)
-			goto out_put_req;
-		ret = -EINVAL;
-		if (file->f_op->aio_read)
-			ret = file->f_op->aio_read(req, buf,
-					iocb->aio_nbytes, req->ki_pos);
-		break;
-	case IOCB_CMD_PWRITE:
-		ret = -EBADF;
-		if (unlikely(!(file->f_mode & FMODE_WRITE)))
-			goto out_put_req;
-		ret = -EFAULT;
-		if (unlikely(!access_ok(VERIFY_READ, buf, iocb->aio_nbytes)))
-			goto out_put_req;
-		ret = security_file_permission (file, MAY_WRITE);
-		if (ret)
-			goto out_put_req;
-		ret = -EINVAL;
-		if (file->f_op->aio_write)
-			ret = file->f_op->aio_write(req, buf,
-					iocb->aio_nbytes, req->ki_pos);
-		break;
-	case IOCB_CMD_FDSYNC:
-		ret = -EINVAL;
-		if (file->f_op->aio_fsync)
-			ret = file->f_op->aio_fsync(req, 1);
-		break;
-	case IOCB_CMD_FSYNC:
-		ret = -EINVAL;
-		if (file->f_op->aio_fsync)
-			ret = file->f_op->aio_fsync(req, 0);
-		break;
-	default:
-		dprintk("EINVAL: io_submit: no operation provided\n");
-		ret = -EINVAL;
-	}
+	ret = aio_setup_iocb(req);
 
+	if (ret)
+		goto out_put_req;
+
+	spin_lock_irq(&ctx->ctx_lock);
+	list_add_tail(&req->ki_run_list, &ctx->run_list);
+	/* drain the run list */
+	while (__aio_run_iocbs(ctx))
+		;
+	spin_unlock_irq(&ctx->ctx_lock);
 	aio_put_req(req);	/* drop extra ref to req */
-	if (likely(-EIOCBQUEUED == ret))
-		return 0;
-	aio_complete(req, ret, 0);	/* will drop i/o ref to req */
 	return 0;
 
 out_put_req:
@@ -1201,6 +1663,7 @@
 	if (kiocb && kiocb->ki_cancel) {
 		cancel = kiocb->ki_cancel;
 		kiocb->ki_users ++;
+		kiocbSetCancelled(kiocb);
 	} else
 		cancel = NULL;
 	spin_unlock_irq(&ctx->ctx_lock);
diff -Nru a/fs/autofs/root.c b/fs/autofs/root.c
--- a/fs/autofs/root.c	2004-10-18 14:56:31 -07:00
+++ b/fs/autofs/root.c	2004-10-18 14:56:31 -07:00
@@ -238,9 +238,15 @@
 	 * a signal. If so we can force a restart..
 	 */
 	if (dentry->d_flags & DCACHE_AUTOFS_PENDING) {
+		/* See if we were interrupted */
 		if (signal_pending(current)) {
-			unlock_kernel();
-			return ERR_PTR(-ERESTARTNOINTR);
+			sigset_t *sigset = &current->pending.signal;
+			if (sigismember (sigset, SIGKILL) ||
+			    sigismember (sigset, SIGQUIT) ||
+			    sigismember (sigset, SIGINT)) {
+				unlock_kernel();
+				return ERR_PTR(-ERESTARTNOINTR);
+			}
 		}
 	}
 	unlock_kernel();
diff -Nru a/fs/autofs4/autofs_i.h b/fs/autofs4/autofs_i.h
--- a/fs/autofs4/autofs_i.h	2004-10-18 14:56:48 -07:00
+++ b/fs/autofs4/autofs_i.h	2004-10-18 14:56:48 -07:00
@@ -138,7 +138,6 @@
 }
 
 struct inode *autofs4_get_inode(struct super_block *, struct autofs_info *);
-struct autofs_info *autofs4_init_inf(struct autofs_sb_info *, mode_t mode);
 void autofs4_free_ino(struct autofs_info *);
 
 /* Expiration */
diff -Nru a/fs/autofs4/expire.c b/fs/autofs4/expire.c
--- a/fs/autofs4/expire.c	2004-10-18 14:56:48 -07:00
+++ b/fs/autofs4/expire.c	2004-10-18 14:56:48 -07:00
@@ -146,10 +146,10 @@
 	return 1;
 }
 
-struct dentry *autofs4_check_leaves(struct vfsmount *mnt,
-				    struct dentry *parent,
-				    unsigned long timeout,
-				    int do_now)
+static struct dentry *autofs4_check_leaves(struct vfsmount *mnt,
+					   struct dentry *parent,
+					   unsigned long timeout,
+					   int do_now)
 {
 	struct dentry *this_parent = parent;
 	struct list_head *next;
diff -Nru a/fs/befs/befs.h b/fs/befs/befs.h
--- a/fs/befs/befs.h	2004-10-18 14:56:50 -07:00
+++ b/fs/befs/befs.h	2004-10-18 14:56:50 -07:00
@@ -96,7 +96,6 @@
 void befs_dump_inode(const struct super_block *sb, befs_inode *);
 void befs_dump_index_entry(const struct super_block *sb, befs_btree_super *);
 void befs_dump_index_node(const struct super_block *sb, befs_btree_nodehead *);
-void befs_dump_inode_addr(const struct super_block *sb, befs_inode_addr);
 /****************************/
 
 
diff -Nru a/fs/befs/debug.c b/fs/befs/debug.c
--- a/fs/befs/debug.c	2004-10-18 14:57:05 -07:00
+++ b/fs/befs/debug.c	2004-10-18 14:57:05 -07:00
@@ -222,11 +222,13 @@
 #endif				//CONFIG_BEFS_DEBUG
 }
 
+/* unused */
 void
 befs_dump_small_data(const struct super_block *sb, befs_small_data * sd)
 {
 }
 
+/* unused */
 void
 befs_dump_run(const struct super_block *sb, befs_block_run run)
 {
diff -Nru a/fs/befs/linuxvfs.c b/fs/befs/linuxvfs.c
--- a/fs/befs/linuxvfs.c	2004-10-18 14:56:29 -07:00
+++ b/fs/befs/linuxvfs.c	2004-10-18 14:56:29 -07:00
@@ -64,22 +64,22 @@
 /* slab cache for befs_inode_info objects */
 static kmem_cache_t *befs_inode_cachep;
 
-struct file_operations befs_dir_operations = {
+static struct file_operations befs_dir_operations = {
 	.read		= generic_read_dir,
 	.readdir	= befs_readdir,
 };
 
-struct inode_operations befs_dir_inode_operations = {
+static struct inode_operations befs_dir_inode_operations = {
 	.lookup		= befs_lookup,
 };
 
-struct file_operations befs_file_operations = {
+static struct file_operations befs_file_operations = {
 	.llseek		= default_llseek,
 	.read		= generic_file_read,
 	.mmap		= generic_file_readonly_mmap,
 };
 
-struct address_space_operations befs_aops = {
+static struct address_space_operations befs_aops = {
 	.readpage	= befs_readpage,
 	.sync_page	= block_sync_page,
 	.bmap		= befs_bmap,
@@ -433,7 +433,7 @@
 {
 	befs_inode_cachep = kmem_cache_create("befs_inode_cache",
 					      sizeof (struct befs_inode_info),
-					      0, SLAB_HWCACHE_ALIGN|SLAB_RECLAIM_ACCOUNT,
+					      0, SLAB_RECLAIM_ACCOUNT,
 					      init_once, NULL);
 	if (befs_inode_cachep == NULL) {
 		printk(KERN_ERR "befs_init_inodecache: "
@@ -857,10 +857,14 @@
 		befs_sb->nls = load_nls(befs_sb->mount_opts.iocharset);
 		if (!befs_sb->nls) {
 			befs_warning(sb, "Cannot load nls %s"
-				     "loding default nls",
-				     befs_sb->mount_opts.iocharset);
+					" loading default nls",
+					befs_sb->mount_opts.iocharset);
 			befs_sb->nls = load_nls_default();
 		}
+	/* load default nls if none is specified  in mount options */
+	} else {
+		befs_debug(sb, "Loading default nls");
+		befs_sb->nls = load_nls_default();
 	}
 
 	return 0;
diff -Nru a/fs/bfs/inode.c b/fs/bfs/inode.c
--- a/fs/bfs/inode.c	2004-10-18 14:56:29 -07:00
+++ b/fs/bfs/inode.c	2004-10-18 14:56:29 -07:00
@@ -85,7 +85,7 @@
 	brelse(bh);
 }
 
-static void bfs_write_inode(struct inode * inode, int unused)
+static int bfs_write_inode(struct inode * inode, int unused)
 {
 	unsigned long ino = inode->i_ino;
 	struct bfs_inode * di;
@@ -94,7 +94,7 @@
 
 	if (ino < BFS_ROOT_INO || ino > BFS_SB(inode->i_sb)->si_lasti) {
 		printf("Bad inode number %s:%08lx\n", inode->i_sb->s_id, ino);
-		return;
+		return -EIO;
 	}
 
 	lock_kernel();
@@ -103,7 +103,7 @@
 	if (!bh) {
 		printf("Unable to read inode %s:%08lx\n", inode->i_sb->s_id, ino);
 		unlock_kernel();
-		return;
+		return -EIO;
 	}
 
 	off = (ino - BFS_ROOT_INO)%BFS_INODES_PER_BLOCK;
@@ -129,6 +129,7 @@
 	mark_buffer_dirty(bh);
 	brelse(bh);
 	unlock_kernel();
+	return 0;
 }
 
 static void bfs_delete_inode(struct inode * inode)
@@ -245,7 +246,7 @@
 {
 	bfs_inode_cachep = kmem_cache_create("bfs_inode_cache",
 					     sizeof(struct bfs_inode_info),
-					     0, SLAB_HWCACHE_ALIGN|SLAB_RECLAIM_ACCOUNT,
+					     0, SLAB_RECLAIM_ACCOUNT,
 					     init_once, NULL);
 	if (bfs_inode_cachep == NULL)
 		return -ENOMEM;
diff -Nru a/fs/binfmt_aout.c b/fs/binfmt_aout.c
--- a/fs/binfmt_aout.c	2004-10-18 14:56:17 -07:00
+++ b/fs/binfmt_aout.c	2004-10-18 14:56:17 -07:00
@@ -307,7 +307,7 @@
 		(current->mm->start_data = N_DATADDR(ex));
 	current->mm->brk = ex.a_bss +
 		(current->mm->start_brk = N_BSSADDR(ex));
-	current->mm->free_area_cache = TASK_UNMAPPED_BASE;
+	current->mm->free_area_cache = current->mm->mmap_base;
 
 	current->mm->rss = 0;
 	current->mm->mmap = NULL;
diff -Nru a/fs/binfmt_elf.c b/fs/binfmt_elf.c
--- a/fs/binfmt_elf.c	2004-10-18 14:56:29 -07:00
+++ b/fs/binfmt_elf.c	2004-10-18 14:56:29 -07:00
@@ -40,6 +40,7 @@
 
 #include <asm/uaccess.h>
 #include <asm/param.h>
+#include <asm/page.h>
 
 #include <linux/elf.h>
 
@@ -487,25 +488,33 @@
 	unsigned long elf_entry, interp_load_addr = 0;
 	unsigned long start_code, end_code, start_data, end_data;
 	unsigned long reloc_func_desc = 0;
-	struct elfhdr elf_ex;
-	struct elfhdr interp_elf_ex;
-  	struct exec interp_ex;
 	char passed_fileno[6];
 	struct files_struct *files;
 	int have_pt_gnu_stack, executable_stack = EXSTACK_DEFAULT;
 	unsigned long def_flags = 0;
+	struct {
+		struct elfhdr elf_ex;
+		struct elfhdr interp_elf_ex;
+  		struct exec interp_ex;
+	} *loc;
+
+	loc = kmalloc(sizeof(*loc), GFP_KERNEL);
+	if (!loc) {
+		retval = -ENOMEM;
+		goto out_ret;
+	}
 	
 	/* Get the exec-header */
-	elf_ex = *((struct elfhdr *) bprm->buf);
+	loc->elf_ex = *((struct elfhdr *) bprm->buf);
 
 	retval = -ENOEXEC;
 	/* First of all, some simple consistency checks */
-	if (memcmp(elf_ex.e_ident, ELFMAG, SELFMAG) != 0)
+	if (memcmp(loc->elf_ex.e_ident, ELFMAG, SELFMAG) != 0)
 		goto out;
 
-	if (elf_ex.e_type != ET_EXEC && elf_ex.e_type != ET_DYN)
+	if (loc->elf_ex.e_type != ET_EXEC && loc->elf_ex.e_type != ET_DYN)
 		goto out;
-	if (!elf_check_arch(&elf_ex))
+	if (!elf_check_arch(&loc->elf_ex))
 		goto out;
 	if (!bprm->file->f_op||!bprm->file->f_op->mmap)
 		goto out;
@@ -513,16 +522,16 @@
 	/* Now read in all of the header information */
 
 	retval = -ENOMEM;
-	if (elf_ex.e_phentsize != sizeof(struct elf_phdr))
+	if (loc->elf_ex.e_phentsize != sizeof(struct elf_phdr))
 		goto out;
-	if (elf_ex.e_phnum > 65536U / sizeof(struct elf_phdr))
+	if (loc->elf_ex.e_phnum > 65536U / sizeof(struct elf_phdr))
 		goto out;
-	size = elf_ex.e_phnum * sizeof(struct elf_phdr);
+	size = loc->elf_ex.e_phnum * sizeof(struct elf_phdr);
 	elf_phdata = (struct elf_phdr *) kmalloc(size, GFP_KERNEL);
 	if (!elf_phdata)
 		goto out;
 
-	retval = kernel_read(bprm->file, elf_ex.e_phoff, (char *) elf_phdata, size);
+	retval = kernel_read(bprm->file, loc->elf_ex.e_phoff, (char *) elf_phdata, size);
 	if (retval < 0)
 		goto out_free_ph;
 
@@ -553,7 +562,7 @@
 	start_data = 0;
 	end_data = 0;
 
-	for (i = 0; i < elf_ex.e_phnum; i++) {
+	for (i = 0; i < loc->elf_ex.e_phnum; i++) {
 		if (elf_ppnt->p_type == PT_INTERP) {
 			/* This is the program interpreter used for
 			 * shared libraries - for now assume that this
@@ -600,7 +609,7 @@
 			 * switch really is going to happen - do this in
 			 * flush_thread().	- akpm
 			 */
-			SET_PERSONALITY(elf_ex, ibcs2_interpreter);
+			SET_PERSONALITY(loc->elf_ex, ibcs2_interpreter);
 
 			interpreter = open_exec(elf_interpreter);
 			retval = PTR_ERR(interpreter);
@@ -611,15 +620,15 @@
 				goto out_free_dentry;
 
 			/* Get the exec headers */
-			interp_ex = *((struct exec *) bprm->buf);
-			interp_elf_ex = *((struct elfhdr *) bprm->buf);
+			loc->interp_ex = *((struct exec *) bprm->buf);
+			loc->interp_elf_ex = *((struct elfhdr *) bprm->buf);
 			break;
 		}
 		elf_ppnt++;
 	}
 
 	elf_ppnt = elf_phdata;
-	for (i = 0; i < elf_ex.e_phnum; i++, elf_ppnt++)
+	for (i = 0; i < loc->elf_ex.e_phnum; i++, elf_ppnt++)
 		if (elf_ppnt->p_type == PT_GNU_STACK) {
 			if (elf_ppnt->p_flags & PF_X)
 				executable_stack = EXSTACK_ENABLE_X;
@@ -627,19 +636,19 @@
 				executable_stack = EXSTACK_DISABLE_X;
 			break;
 		}
-	have_pt_gnu_stack = (i < elf_ex.e_phnum);
+	have_pt_gnu_stack = (i < loc->elf_ex.e_phnum);
 
 	/* Some simple consistency checks for the interpreter */
 	if (elf_interpreter) {
 		interpreter_type = INTERPRETER_ELF | INTERPRETER_AOUT;
 
 		/* Now figure out which format our binary is */
-		if ((N_MAGIC(interp_ex) != OMAGIC) &&
-		    (N_MAGIC(interp_ex) != ZMAGIC) &&
-		    (N_MAGIC(interp_ex) != QMAGIC))
+		if ((N_MAGIC(loc->interp_ex) != OMAGIC) &&
+		    (N_MAGIC(loc->interp_ex) != ZMAGIC) &&
+		    (N_MAGIC(loc->interp_ex) != QMAGIC))
 			interpreter_type = INTERPRETER_ELF;
 
-		if (memcmp(interp_elf_ex.e_ident, ELFMAG, SELFMAG) != 0)
+		if (memcmp(loc->interp_elf_ex.e_ident, ELFMAG, SELFMAG) != 0)
 			interpreter_type &= ~INTERPRETER_ELF;
 
 		retval = -ELIBBAD;
@@ -655,11 +664,11 @@
 		}
 		/* Verify the interpreter has a valid arch */
 		if ((interpreter_type == INTERPRETER_ELF) &&
-		    !elf_check_arch(&interp_elf_ex))
+		    !elf_check_arch(&loc->interp_elf_ex))
 			goto out_free_dentry;
 	} else {
 		/* Executables without an interpreter also need a personality  */
-		SET_PERSONALITY(elf_ex, ibcs2_interpreter);
+		SET_PERSONALITY(loc->elf_ex, ibcs2_interpreter);
 	}
 
 	/* OK, we are done with that, now set up the arg stuff,
@@ -699,14 +708,16 @@
 
 	/* Do this immediately, since STACK_TOP as used in setup_arg_pages
 	   may depend on the personality.  */
-	SET_PERSONALITY(elf_ex, ibcs2_interpreter);
-	if (elf_read_implies_exec(elf_ex, have_pt_gnu_stack))
+	SET_PERSONALITY(loc->elf_ex, ibcs2_interpreter);
+	if (elf_read_implies_exec(loc->elf_ex, have_pt_gnu_stack))
 		current->personality |= READ_IMPLIES_EXEC;
 
+	arch_pick_mmap_layout(current->mm);
+
 	/* Do this so that we can load the interpreter, if need be.  We will
 	   change some of these later */
 	current->mm->rss = 0;
-	current->mm->free_area_cache = TASK_UNMAPPED_BASE;
+	current->mm->free_area_cache = current->mm->mmap_base;
 	retval = setup_arg_pages(bprm, executable_stack);
 	if (retval < 0) {
 		send_sig(SIGKILL, current, 0);
@@ -720,7 +731,7 @@
 	   the image should be loaded at fixed address, not at a variable
 	   address. */
 
-	for(i = 0, elf_ppnt = elf_phdata; i < elf_ex.e_phnum; i++, elf_ppnt++) {
+	for(i = 0, elf_ppnt = elf_phdata; i < loc->elf_ex.e_phnum; i++, elf_ppnt++) {
 		int elf_prot = 0, elf_flags;
 		unsigned long k, vaddr;
 
@@ -755,9 +766,9 @@
 		elf_flags = MAP_PRIVATE|MAP_DENYWRITE|MAP_EXECUTABLE;
 
 		vaddr = elf_ppnt->p_vaddr;
-		if (elf_ex.e_type == ET_EXEC || load_addr_set) {
+		if (loc->elf_ex.e_type == ET_EXEC || load_addr_set) {
 			elf_flags |= MAP_FIXED;
-		} else if (elf_ex.e_type == ET_DYN) {
+		} else if (loc->elf_ex.e_type == ET_DYN) {
 			/* Try and get dynamic programs out of the way of the default mmap
 			   base, as well as whatever program they might try to exec.  This
 			   is because the brk will follow the loader, and is not movable.  */
@@ -771,7 +782,7 @@
 		if (!load_addr_set) {
 			load_addr_set = 1;
 			load_addr = (elf_ppnt->p_vaddr - elf_ppnt->p_offset);
-			if (elf_ex.e_type == ET_DYN) {
+			if (loc->elf_ex.e_type == ET_DYN) {
 				load_bias += error -
 				             ELF_PAGESTART(load_bias + vaddr);
 				load_addr += load_bias;
@@ -808,7 +819,7 @@
 			elf_brk = k;
 	}
 
-	elf_ex.e_entry += load_bias;
+	loc->elf_ex.e_entry += load_bias;
 	elf_bss += load_bias;
 	elf_brk += load_bias;
 	start_code += load_bias;
@@ -830,10 +841,10 @@
 
 	if (elf_interpreter) {
 		if (interpreter_type == INTERPRETER_AOUT)
-			elf_entry = load_aout_interp(&interp_ex,
+			elf_entry = load_aout_interp(&loc->interp_ex,
 						     interpreter);
 		else
-			elf_entry = load_elf_interp(&interp_elf_ex,
+			elf_entry = load_elf_interp(&loc->interp_elf_ex,
 						    interpreter,
 						    &interp_load_addr);
 		if (BAD_ADDR(elf_entry)) {
@@ -848,7 +859,7 @@
 		fput(interpreter);
 		kfree(elf_interpreter);
 	} else {
-		elf_entry = elf_ex.e_entry;
+		elf_entry = loc->elf_ex.e_entry;
 	}
 
 	kfree(elf_phdata);
@@ -860,7 +871,7 @@
 
 	compute_creds(bprm);
 	current->flags &= ~PF_FORKNOEXEC;
-	create_elf_tables(bprm, &elf_ex, (interpreter_type == INTERPRETER_AOUT),
+	create_elf_tables(bprm, &loc->elf_ex, (interpreter_type == INTERPRETER_AOUT),
 			load_addr, interp_load_addr);
 	/* N.B. passed_fileno might not be initialized? */
 	if (interpreter_type == INTERPRETER_AOUT)
@@ -905,6 +916,8 @@
 	}
 	retval = 0;
 out:
+	kfree(loc);
+out_ret:
 	return retval;
 
 	/* error cleanup */
@@ -1176,10 +1189,27 @@
 	prstatus->pr_ppid = p->parent->pid;
 	prstatus->pr_pgrp = process_group(p);
 	prstatus->pr_sid = p->signal->session;
-	jiffies_to_timeval(p->utime, &prstatus->pr_utime);
-	jiffies_to_timeval(p->stime, &prstatus->pr_stime);
-	jiffies_to_timeval(p->cutime, &prstatus->pr_cutime);
-	jiffies_to_timeval(p->cstime, &prstatus->pr_cstime);
+	if (p->pid == p->tgid) {
+		/*
+		 * This is the record for the group leader.  Add in the
+		 * cumulative times of previous dead threads.  This total
+		 * won't include the time of each live thread whose state
+		 * is included in the core dump.  The final total reported
+		 * to our parent process when it calls wait4 will include
+		 * those sums as well as the little bit more time it takes
+		 * this and each other thread to finish dying after the
+		 * core dump synchronization phase.
+		 */
+		jiffies_to_timeval(p->utime + p->signal->utime,
+				   &prstatus->pr_utime);
+		jiffies_to_timeval(p->stime + p->signal->stime,
+				   &prstatus->pr_stime);
+	} else {
+		jiffies_to_timeval(p->utime, &prstatus->pr_utime);
+		jiffies_to_timeval(p->stime, &prstatus->pr_stime);
+	}
+	jiffies_to_timeval(p->signal->cutime, &prstatus->pr_cutime);
+	jiffies_to_timeval(p->signal->cstime, &prstatus->pr_cstime);
 }
 
 static void fill_psinfo(struct elf_prpsinfo *psinfo, struct task_struct *p,
@@ -1224,6 +1254,7 @@
 	struct list_head list;
 	struct elf_prstatus prstatus;	/* NT_PRSTATUS */
 	elf_fpregset_t fpu;		/* NT_PRFPREG */
+	struct task_struct *thread;
 #ifdef ELF_CORE_COPY_XFPREGS
 	elf_fpxregset_t xfpu;		/* NT_PRXFPREG */
 #endif
@@ -1236,18 +1267,10 @@
  * we need to keep a linked list of every threads pr_status and then
  * create a single section for them in the final core file.
  */
-static int elf_dump_thread_status(long signr, struct task_struct * p, struct list_head * thread_list)
+static int elf_dump_thread_status(long signr, struct elf_thread_status *t)
 {
-
-	struct elf_thread_status *t;
 	int sz = 0;
-
-	t = kmalloc(sizeof(*t), GFP_ATOMIC);
-	if (!t)
-		return 0;
-	memset(t, 0, sizeof(*t));
-
-	INIT_LIST_HEAD(&t->list);
+	struct task_struct *p = t->thread;
 	t->num_notes = 0;
 
 	fill_prstatus(&t->prstatus, p, signr);
@@ -1270,7 +1293,6 @@
 		sz += notesize(&t->notes[2]);
 	}
 #endif	
-	list_add(&t->list, thread_list);
 	return sz;
 }
 
@@ -1341,22 +1363,32 @@
 		goto cleanup;
 #endif
 
-	/* capture the status of all other threads */
 	if (signr) {
+		struct elf_thread_status *tmp;
 		read_lock(&tasklist_lock);
 		do_each_thread(g,p)
 			if (current->mm == p->mm && current != p) {
-				int sz = elf_dump_thread_status(signr, p, &thread_list);
-				if (!sz) {
+				tmp = kmalloc(sizeof(*tmp), GFP_ATOMIC);
+				if (!tmp) {
 					read_unlock(&tasklist_lock);
 					goto cleanup;
-				} else
-					thread_status_size += sz;
+				}
+				memset(tmp, 0, sizeof(*tmp));
+				INIT_LIST_HEAD(&tmp->list);
+				tmp->thread = p;
+				list_add(&tmp->list, &thread_list);
 			}
 		while_each_thread(g,p);
 		read_unlock(&tasklist_lock);
+		list_for_each(t, &thread_list) {
+			struct elf_thread_status *tmp;
+			int sz;
+
+			tmp = list_entry(t, struct elf_thread_status, list);
+			sz = elf_dump_thread_status(signr, tmp);
+			thread_status_size += sz;
+		}
 	}
-
 	/* now collect the dump for the current */
 	memset(prstatus, 0, sizeof(*prstatus));
 	fill_prstatus(prstatus, current, signr);
diff -Nru a/fs/bio.c b/fs/bio.c
--- a/fs/bio.c	2004-10-18 14:56:33 -07:00
+++ b/fs/bio.c	2004-10-18 14:56:33 -07:00
@@ -137,33 +137,29 @@
  **/
 struct bio *bio_alloc(int gfp_mask, int nr_iovecs)
 {
-	struct bio_vec *bvl = NULL;
-	unsigned long idx;
-	struct bio *bio;
-
-	bio = mempool_alloc(bio_pool, gfp_mask);
-	if (unlikely(!bio))
-		goto out;
-
-	bio_init(bio);
+	struct bio *bio = mempool_alloc(bio_pool, gfp_mask);
 
-	if (unlikely(!nr_iovecs))
-		goto noiovec;
+	if (likely(bio)) {
+		struct bio_vec *bvl = NULL;
 
-	bvl = bvec_alloc(gfp_mask, nr_iovecs, &idx);
-	if (bvl) {
-		bio->bi_flags |= idx << BIO_POOL_OFFSET;
-		bio->bi_max_vecs = bvec_array[idx].nr_vecs;
-noiovec:
+		bio_init(bio);
+		if (likely(nr_iovecs)) {
+			unsigned long idx;
+
+			bvl = bvec_alloc(gfp_mask, nr_iovecs, &idx);
+			if (unlikely(!bvl)) {
+				mempool_free(bio, bio_pool);
+				bio = NULL;
+				goto out;
+			}
+			bio->bi_flags |= idx << BIO_POOL_OFFSET;
+			bio->bi_max_vecs = bvec_array[idx].nr_vecs;
+		}
 		bio->bi_io_vec = bvl;
 		bio->bi_destructor = bio_destructor;
-out:
-		return bio;
 	}
-
-	mempool_free(bio, bio_pool);
-	bio = NULL;
-	goto out;
+out:
+	return bio;
 }
 
 /**
@@ -376,6 +372,38 @@
 			      len, offset);
 }
 
+struct bio_map_data {
+	struct bio_vec *iovecs;
+	void __user *userptr;
+};
+
+static void bio_set_map_data(struct bio_map_data *bmd, struct bio *bio)
+{
+	memcpy(bmd->iovecs, bio->bi_io_vec, sizeof(struct bio_vec) * bio->bi_vcnt);
+	bio->bi_private = bmd;
+}
+
+static void bio_free_map_data(struct bio_map_data *bmd)
+{
+	kfree(bmd->iovecs);
+	kfree(bmd);
+}
+
+static struct bio_map_data *bio_alloc_map_data(int nr_segs)
+{
+	struct bio_map_data *bmd = kmalloc(sizeof(*bmd), GFP_KERNEL);
+
+	if (!bmd)
+		return NULL;
+
+	bmd->iovecs = kmalloc(sizeof(struct bio_vec) * nr_segs, GFP_KERNEL);
+	if (bmd->iovecs)
+		return bmd;
+
+	kfree(bmd);
+	return NULL;
+}
+
 /**
  *	bio_uncopy_user	-	finish previously mapped bio
  *	@bio: bio being terminated
@@ -385,23 +413,22 @@
  */
 int bio_uncopy_user(struct bio *bio)
 {
+	struct bio_map_data *bmd = bio->bi_private;
+	const int read = bio_data_dir(bio) == READ;
 	struct bio_vec *bvec;
 	int i, ret = 0;
 
-	if (bio_data_dir(bio) == READ) {
-		char *uaddr = bio->bi_private;
+	__bio_for_each_segment(bvec, bio, i, 0) {
+		char *addr = page_address(bvec->bv_page);
+		unsigned int len = bmd->iovecs[i].bv_len;
 
-		__bio_for_each_segment(bvec, bio, i, 0) {
-			char *addr = page_address(bvec->bv_page);
-
-			if (!ret && copy_to_user(uaddr, addr, bvec->bv_len))
-				ret = -EFAULT;
+		if (read && !ret && copy_to_user(bmd->userptr, addr, len))
+			ret = -EFAULT;
 
-			__free_page(bvec->bv_page);
-			uaddr += bvec->bv_len;
-		}
+		__free_page(bvec->bv_page);
+		bmd->userptr += len;
 	}
-
+	bio_free_map_data(bmd);
 	bio_put(bio);
 	return ret;
 }
@@ -422,14 +449,25 @@
 {
 	unsigned long end = (uaddr + len + PAGE_SIZE - 1) >> PAGE_SHIFT;
 	unsigned long start = uaddr >> PAGE_SHIFT;
+	struct bio_map_data *bmd;
 	struct bio_vec *bvec;
 	struct page *page;
 	struct bio *bio;
 	int i, ret;
 
+	bmd = bio_alloc_map_data(end - start);
+	if (!bmd)
+		return ERR_PTR(-ENOMEM);
+
+	bmd->userptr = (void __user *) uaddr;
+
 	bio = bio_alloc(GFP_KERNEL, end - start);
-	if (!bio)
+	if (!bio) {
+		bio_free_map_data(bmd);
 		return ERR_PTR(-ENOMEM);
+	}
+
+	bio->bi_rw |= (!write_to_vm << BIO_RW);
 
 	ret = 0;
 	while (len) {
@@ -452,31 +490,30 @@
 		len -= bytes;
 	}
 
+	if (ret)
+		goto cleanup;
+
 	/*
 	 * success
 	 */
-	if (!ret) {
-		if (!write_to_vm) {
-			bio->bi_rw |= (1 << BIO_RW);
-			/*
-	 		 * for a write, copy in data to kernel pages
-			 */
-			ret = -EFAULT;
-			bio_for_each_segment(bvec, bio, i) {
-				char *addr = page_address(bvec->bv_page);
+	if (!write_to_vm) {
+		char __user *p = (char __user *) uaddr;
 
-				if (copy_from_user(addr, (char *) uaddr, bvec->bv_len))
-					goto cleanup;
-			}
-		}
+		/*
+		 * for a write, copy in data to kernel pages
+		 */
+		ret = -EFAULT;
+		bio_for_each_segment(bvec, bio, i) {
+			char *addr = page_address(bvec->bv_page);
 
-		bio->bi_private = (void *) uaddr;
-		return bio;
+			if (copy_from_user(addr, p, bvec->bv_len))
+				goto cleanup;
+			p += bvec->bv_len;
+		}
 	}
 
-	/*
-	 * cleanup
-	 */
+	bio_set_map_data(bmd, bio);
+	return bio;
 cleanup:
 	bio_for_each_segment(bvec, bio, i)
 		__free_page(bvec->bv_page);
@@ -607,18 +644,6 @@
 {
 	struct bio_vec *bvec;
 	int i;
-
-	/*
-	 * find original bio if it was bounced
-	 */
-	if (bio->bi_private) {
-		/*
-		 * someone stole our bio, must not happen
-		 */
-		BUG_ON(!bio_flagged(bio, BIO_BOUNCED));
-	
-		bio = bio->bi_private;
-	}
 
 	/*
 	 * make sure we dirty pages we wrote to
diff -Nru a/fs/buffer.c b/fs/buffer.c
--- a/fs/buffer.c	2004-10-18 14:56:33 -07:00
+++ b/fs/buffer.c	2004-10-18 14:56:33 -07:00
@@ -39,6 +39,7 @@
 #include <linux/cpu.h>
 #include <asm/bitops.h>
 
+static int fsync_buffers_list(spinlock_t *lock, struct list_head *list);
 static void invalidate_bh_lrus(void);
 
 #define BH_ENTRY(list) list_entry((list), struct buffer_head, b_assoc_buffers)
@@ -213,7 +214,7 @@
 	if (uptodate) {
 		set_buffer_uptodate(bh);
 	} else {
-		if (printk_ratelimit()) {
+		if (!buffer_eopnotsupp(bh) && printk_ratelimit()) {
 			buffer_io_error(bh);
 			printk(KERN_WARNING "lost page write due to "
 					"I/O error on %s\n",
@@ -725,12 +726,11 @@
  * PageLocked prevents anyone from starting writeback of a page which is
  * under read I/O (PageWriteback is only ever set against a locked page).
  */
-void mark_buffer_async_read(struct buffer_head *bh)
+static void mark_buffer_async_read(struct buffer_head *bh)
 {
 	bh->b_end_io = end_buffer_async_read;
 	set_buffer_async_read(bh);
 }
-EXPORT_SYMBOL(mark_buffer_async_read);
 
 void mark_buffer_async_write(struct buffer_head *bh)
 {
@@ -789,14 +789,6 @@
  * b_inode back.
  */
 
-void buffer_insert_list(spinlock_t *lock,
-		struct buffer_head *bh, struct list_head *list)
-{
-	spin_lock(lock);
-	list_move_tail(&bh->b_assoc_buffers, list);
-	spin_unlock(lock);
-}
-
 /*
  * The buffer's backing address_space's private_lock must be held
  */
@@ -899,9 +891,12 @@
 		if (mapping->assoc_mapping != buffer_mapping)
 			BUG();
 	}
-	if (list_empty(&bh->b_assoc_buffers))
-		buffer_insert_list(&buffer_mapping->private_lock,
-				bh, &mapping->private_list);
+	if (list_empty(&bh->b_assoc_buffers)) {
+		spin_lock(&buffer_mapping->private_lock);
+		list_move_tail(&bh->b_assoc_buffers,
+				&mapping->private_list);
+		spin_unlock(&buffer_mapping->private_lock);
+	}
 }
 EXPORT_SYMBOL(mark_buffer_dirty_inode);
 
@@ -982,7 +977,7 @@
  * the osync code to catch these locked, dirty buffers without requeuing
  * any newly dirty buffers for write.
  */
-int fsync_buffers_list(spinlock_t *lock, struct list_head *list)
+static int fsync_buffers_list(spinlock_t *lock, struct list_head *list)
 {
 	struct buffer_head *bh;
 	struct list_head tmp;
@@ -1551,6 +1546,7 @@
 {
 	struct buffer_head *bh = __find_get_block(bdev, block, size);
 
+	might_sleep();
 	if (bh == NULL)
 		bh = __getblk_slow(bdev, block, size);
 	return bh;
@@ -1776,6 +1772,8 @@
 {
 	struct buffer_head *old_bh;
 
+	might_sleep();
+
 	old_bh = __find_get_block_slow(bdev, block, 0);
 	if (old_bh) {
 		clear_buffer_dirty(old_bh);
@@ -2756,21 +2754,33 @@
 	if (bio->bi_size)
 		return 1;
 
+	if (err == -EOPNOTSUPP) {
+		set_bit(BIO_EOPNOTSUPP, &bio->bi_flags);
+		set_bit(BH_Eopnotsupp, &bh->b_state);
+	}
+
 	bh->b_end_io(bh, test_bit(BIO_UPTODATE, &bio->bi_flags));
 	bio_put(bio);
 	return 0;
 }
 
-void submit_bh(int rw, struct buffer_head * bh)
+int submit_bh(int rw, struct buffer_head * bh)
 {
 	struct bio *bio;
+	int ret = 0;
 
 	BUG_ON(!buffer_locked(bh));
 	BUG_ON(!buffer_mapped(bh));
 	BUG_ON(!bh->b_end_io);
 
-	/* Only clear out a write error when rewriting */
-	if (test_set_buffer_req(bh) && rw == WRITE)
+	if (buffer_ordered(bh) && (rw == WRITE))
+		rw = WRITE_BARRIER;
+
+	/*
+	 * Only clear out a write error when rewriting, should this
+	 * include WRITE_SYNC as well?
+	 */
+	if (test_set_buffer_req(bh) && (rw == WRITE || rw == WRITE_BARRIER))
 		clear_buffer_write_io_error(bh);
 
 	/*
@@ -2792,7 +2802,14 @@
 	bio->bi_end_io = end_bio_bh_io_sync;
 	bio->bi_private = bh;
 
+	bio_get(bio);
 	submit_bio(rw, bio);
+
+	if (bio_flagged(bio, BIO_EOPNOTSUPP))
+		ret = -EOPNOTSUPP;
+
+	bio_put(bio);
+	return ret;
 }
 
 /**
@@ -2851,20 +2868,30 @@
 
 /*
  * For a data-integrity writeout, we need to wait upon any in-progress I/O
- * and then start new I/O and then wait upon it.
+ * and then start new I/O and then wait upon it.  The caller must have a ref on
+ * the buffer_head.
  */
-void sync_dirty_buffer(struct buffer_head *bh)
+int sync_dirty_buffer(struct buffer_head *bh)
 {
+	int ret = 0;
+
 	WARN_ON(atomic_read(&bh->b_count) < 1);
 	lock_buffer(bh);
 	if (test_clear_buffer_dirty(bh)) {
 		get_bh(bh);
 		bh->b_end_io = end_buffer_write_sync;
-		submit_bh(WRITE, bh);
+		ret = submit_bh(WRITE, bh);
 		wait_on_buffer(bh);
+		if (buffer_eopnotsupp(bh)) {
+			clear_buffer_eopnotsupp(bh);
+			ret = -EOPNOTSUPP;
+		}
+		if (!ret && !buffer_uptodate(bh))
+			ret = -EIO;
 	} else {
 		unlock_buffer(bh);
 	}
+	return ret;
 }
 
 /*
@@ -3121,14 +3148,12 @@
 EXPORT_SYMBOL(block_sync_page);
 EXPORT_SYMBOL(block_truncate_page);
 EXPORT_SYMBOL(block_write_full_page);
-EXPORT_SYMBOL(buffer_insert_list);
 EXPORT_SYMBOL(cont_prepare_write);
 EXPORT_SYMBOL(end_buffer_async_write);
 EXPORT_SYMBOL(end_buffer_read_sync);
 EXPORT_SYMBOL(end_buffer_write_sync);
 EXPORT_SYMBOL(file_fsync);
 EXPORT_SYMBOL(fsync_bdev);
-EXPORT_SYMBOL(fsync_buffers_list);
 EXPORT_SYMBOL(generic_block_bmap);
 EXPORT_SYMBOL(generic_commit_write);
 EXPORT_SYMBOL(generic_cont_expand);
diff -Nru a/fs/cifs/AUTHORS b/fs/cifs/AUTHORS
--- a/fs/cifs/AUTHORS	2004-10-18 14:55:54 -07:00
+++ b/fs/cifs/AUTHORS	2004-10-18 14:55:54 -07:00
@@ -24,6 +24,7 @@
 Sergey Vlasov
 Richard Hughes
 Yury Umanets
+Mark Hamzy
 
 Test case and Bug Report contributors
 -------------------------------------
@@ -31,7 +32,9 @@
 and debug of problems they have found:  Jochen Dolze, David Blaine,
 Rene Scharfe, Martin Josefsson, Alexander Wild, Anthony Liguori,
 Lars Muller, Urban Widmark, Massimiliano Ferrero, Howard Owen,
-Olaf Kirch, Kieron Briggs, Nick Millington and others. 
+Olaf Kirch, Kieron Briggs, Nick Millington and others. Also special
+mention to the Stanford Checker (SWAT) which pointed out many minor
+bugs in error paths.
 
 And thanks to the IBM LTC and Power test teams and SuSE testers for
 finding multiple bugs during excellent stress test runs.
diff -Nru a/fs/cifs/CHANGES b/fs/cifs/CHANGES
--- a/fs/cifs/CHANGES	2004-10-18 14:56:50 -07:00
+++ b/fs/cifs/CHANGES	2004-10-18 14:56:50 -07:00
@@ -1,7 +1,9 @@
 Version 1.22
 ------------
 Add config option to enable XATTR (extended attribute) support, mapping
-xattr names in the "user." namespace space to SMB/CIFS EAs.
+xattr names in the "user." namespace space to SMB/CIFS EAs. Lots of
+minor fixes pointed out by the Stanford SWAT checker (mostly missing
+or out of order NULL pointer checks in little used error paths).
 
 Version 1.21
 ------------
diff -Nru a/fs/cifs/asn1.c b/fs/cifs/asn1.c
--- a/fs/cifs/asn1.c	2004-10-18 14:55:54 -07:00
+++ b/fs/cifs/asn1.c	2004-10-18 14:55:54 -07:00
@@ -375,7 +375,7 @@
 	return 1;
 }
 
-static unsigned char
+static int 
 asn1_oid_decode(struct asn1_ctx *ctx,
 		unsigned char *eoc, unsigned long **oid, unsigned int *len)
 {
@@ -454,11 +454,11 @@
 	struct asn1_ctx ctx;
 	unsigned char *end;
 	unsigned char *sequence_end;
-	unsigned long *oid;
+	unsigned long *oid = NULL;
 	unsigned int cls, con, tag, oidlen, rc;
 	int use_ntlmssp = FALSE;
 
-    *secType = NTLM; /* BB eventually make Kerberos or NLTMSSP the default */
+	*secType = NTLM; /* BB eventually make Kerberos or NLTMSSP the default */
 
 	/* cifs_dump_mem(" Received SecBlob ", security_blob, length); */
 
@@ -543,16 +543,19 @@
 				return 0;
 			}
 			if ((tag == ASN1_OJI) && (con == ASN1_PRI)) {
-				asn1_oid_decode(&ctx, end, &oid, &oidlen);
-				cFYI(1,
-				     ("OID len = %d oid = 0x%lx 0x%lx 0x%lx 0x%lx",
-				      oidlen, *oid, *(oid + 1), *(oid + 2),
-				      *(oid + 3)));
-				rc = compare_oid(oid, oidlen, NTLMSSP_OID,
+				rc = asn1_oid_decode(&ctx, end, &oid, &oidlen);
+				if(rc) {		
+					cFYI(1,
+					  ("OID len = %d oid = 0x%lx 0x%lx 0x%lx 0x%lx",
+					   oidlen, *oid, *(oid + 1), *(oid + 2),
+					   *(oid + 3)));
+					rc = compare_oid(oid, oidlen, NTLMSSP_OID,
 						 NTLMSSP_OID_LEN);
-				kfree(oid);
-				if (rc)
-					use_ntlmssp = TRUE;
+					if(oid)
+						kfree(oid);
+					if (rc)
+						use_ntlmssp = TRUE;
+				}
 			} else {
 				cFYI(1,("This should be an oid what is going on? "));
 			}
diff -Nru a/fs/cifs/cifs_debug.c b/fs/cifs/cifs_debug.c
--- a/fs/cifs/cifs_debug.c	2004-10-18 14:56:29 -07:00
+++ b/fs/cifs/cifs_debug.c	2004-10-18 14:56:29 -07:00
@@ -126,26 +126,28 @@
 	i = 0;
 	read_lock(&GlobalSMBSeslock);
 	list_for_each(tmp, &GlobalTreeConnectionList) {
+		__u32 dev_type;
 		i++;
 		tcon = list_entry(tmp, struct cifsTconInfo, cifsConnectionList);
+		dev_type = le32_to_cpu(tcon->fsDevInfo.DeviceType);
 		length =
 		    sprintf(buf,
 			    "\n%d) %s Uses: %d Type: %s Characteristics: 0x%x Attributes: 0x%x\nPathComponentMax: %d Status: %d",
 			    i, tcon->treeName,
 			    atomic_read(&tcon->useCount),
 			    tcon->nativeFileSystem,
-			    tcon->fsDevInfo.DeviceCharacteristics,
-			    tcon->fsAttrInfo.Attributes,
-			    tcon->fsAttrInfo.MaxPathNameComponentLength,tcon->tidStatus);
+			    le32_to_cpu(tcon->fsDevInfo.DeviceCharacteristics),
+			    le32_to_cpu(tcon->fsAttrInfo.Attributes),
+			    le32_to_cpu(tcon->fsAttrInfo.MaxPathNameComponentLength),
+			    tcon->tidStatus);
 		buf += length;        
-		if (tcon->fsDevInfo.DeviceType == FILE_DEVICE_DISK)
+		if (dev_type == FILE_DEVICE_DISK)
 			length = sprintf(buf, " type: DISK ");
-		else if (tcon->fsDevInfo.DeviceType == FILE_DEVICE_CD_ROM)
+		else if (dev_type == FILE_DEVICE_CD_ROM)
 			length = sprintf(buf, " type: CDROM ");
 		else
 			length =
-			    sprintf(buf, " type: %d ",
-				    tcon->fsDevInfo.DeviceType);
+			    sprintf(buf, " type: %d ", dev_type);
 		buf += length;
 		if(tcon->tidStatus == CifsNeedReconnect) {
 			buf += sprintf(buf, "\tDISCONNECTED ");
diff -Nru a/fs/cifs/cifsencrypt.c b/fs/cifs/cifsencrypt.c
--- a/fs/cifs/cifsencrypt.c	2004-10-18 14:56:33 -07:00
+++ b/fs/cifs/cifsencrypt.c	2004-10-18 14:56:33 -07:00
@@ -61,7 +61,7 @@
 	if((cifs_pdu == NULL) || (ses == NULL))
 		return -EINVAL;
 
-	if((le32_to_cpu(cifs_pdu->Flags2) & SMBFLG2_SECURITY_SIGNATURE) == 0) 
+	if((cifs_pdu->Flags2 & SMBFLG2_SECURITY_SIGNATURE) == 0) 
 		return rc;
 
 	spin_lock(&GlobalMid_Lock);
@@ -107,13 +107,11 @@
 	if(memcmp(cifs_pdu->Signature.SecuritySignature,"BSRSPYL ",8)==0)
 		cFYI(1,("dummy signature received for smb command 0x%x",cifs_pdu->Command));
 
-	expected_sequence_number = cpu_to_le32(expected_sequence_number);
-
 	/* save off the origiginal signature so we can modify the smb and check
 		its signature against what the server sent */
 	memcpy(server_response_sig,cifs_pdu->Signature.SecuritySignature,8);
 
-	cifs_pdu->Signature.Sequence.SequenceNumber = expected_sequence_number;
+	cifs_pdu->Signature.Sequence.SequenceNumber = cpu_to_le32(expected_sequence_number);
 	cifs_pdu->Signature.Sequence.Reserved = 0;
 
 	rc = cifs_calculate_signature(cifs_pdu, mac_key,
@@ -153,7 +151,7 @@
 	wchar_t * unicode_buf;
 	unsigned int i,user_name_len,dom_name_len;
 
-	if(ses)
+	if(ses == NULL)
 		return -EINVAL;
 
 	E_md4hash(ses->password, temp_hash);
@@ -167,7 +165,13 @@
 		return -EINVAL;
   
 	ucase_buf = kmalloc((MAX_USERNAME_SIZE+1), GFP_KERNEL);
+	if(ucase_buf == NULL)
+		return -ENOMEM;
 	unicode_buf = kmalloc((MAX_USERNAME_SIZE+1)*4, GFP_KERNEL);
+	if(unicode_buf == NULL) {
+		kfree(ucase_buf);
+		return -ENOMEM;
+	}
    
 	for(i=0;i<user_name_len;i++)
 		ucase_buf[i] = nls_info->charset2upper[(int)ses->userName[i]];
diff -Nru a/fs/cifs/cifsfs.c b/fs/cifs/cifsfs.c
--- a/fs/cifs/cifsfs.c	2004-10-18 14:56:32 -07:00
+++ b/fs/cifs/cifsfs.c	2004-10-18 14:56:32 -07:00
@@ -255,12 +255,14 @@
 	if (cifs_sb) {
 		if (cifs_sb->tcon) {
 			seq_printf(s, ",unc=%s", cifs_sb->tcon->treeName);
-			if ((cifs_sb->tcon->ses) && (cifs_sb->tcon->ses->userName))
-				seq_printf(s, ",username=%s",
+			if (cifs_sb->tcon->ses) {
+				if (cifs_sb->tcon->ses->userName)
+					seq_printf(s, ",username=%s",
 					   cifs_sb->tcon->ses->userName);
-			if(cifs_sb->tcon->ses->domainName)
-				seq_printf(s, ",domain=%s",
-					cifs_sb->tcon->ses->domainName);
+				if(cifs_sb->tcon->ses->domainName)
+					seq_printf(s, ",domain=%s",
+					   cifs_sb->tcon->ses->domainName);
+			}
 		}
 		seq_printf(s, ",rsize=%d",cifs_sb->rsize);
 		seq_printf(s, ",wsize=%d",cifs_sb->wsize);
@@ -510,8 +512,9 @@
 };
 
 struct inode_operations cifs_symlink_inode_ops = {
-	.readlink = cifs_readlink,
+	.readlink = generic_readlink, 
 	.follow_link = cifs_follow_link,
+	.put_link = cifs_put_link,
 	.permission = cifs_permission,
 	/* BB add the following two eventually */
 	/* revalidate: cifs_revalidate,
@@ -561,7 +564,7 @@
 {
 	cifs_inode_cachep = kmem_cache_create("cifs_inode_cache",
 					      sizeof (struct cifsInodeInfo),
-					      0, SLAB_HWCACHE_ALIGN|SLAB_RECLAIM_ACCOUNT,
+					      0, SLAB_RECLAIM_ACCOUNT,
 					      cifs_init_once, NULL);
 	if (cifs_inode_cachep == NULL)
 		return -ENOMEM;
@@ -756,11 +759,14 @@
 			if (!rc) {
 				rc = register_filesystem(&cifs_fs_type);
 				if (!rc) {                
-					kernel_thread(cifs_oplock_thread, NULL, 
+					rc = (int)kernel_thread(cifs_oplock_thread, NULL, 
 						CLONE_FS | CLONE_FILES | CLONE_VM);
-					return rc; /* Success */
-				} else
-					cifs_destroy_request_bufs();
+					if(rc > 0)
+						return 0;
+					else 
+						cERROR(1,("error %d create oplock thread",rc));
+				}
+				cifs_destroy_request_bufs();
 			}
 			cifs_destroy_mids();
 		}
diff -Nru a/fs/cifs/cifsfs.h b/fs/cifs/cifsfs.h
--- a/fs/cifs/cifsfs.h	2004-10-18 14:56:17 -07:00
+++ b/fs/cifs/cifsfs.h	2004-10-18 14:56:17 -07:00
@@ -81,6 +81,7 @@
 
 /* Functions related to symlinks */
 extern int cifs_follow_link(struct dentry *direntry, struct nameidata *nd);
+extern void cifs_put_link(struct dentry *direntry, struct nameidata *nd);
 extern int cifs_readlink(struct dentry *direntry, char __user *buffer, int buflen);
 extern int cifs_symlink(struct inode *inode, struct dentry *direntry,
 			const char *symname);
diff -Nru a/fs/cifs/cifsglob.h b/fs/cifs/cifsglob.h
--- a/fs/cifs/cifsglob.h	2004-10-18 14:56:17 -07:00
+++ b/fs/cifs/cifsglob.h	2004-10-18 14:56:17 -07:00
@@ -126,7 +126,7 @@
 	enum protocolEnum protocolType;	
 	char versionMajor;
 	char versionMinor;
-	int svlocal:1;		/* local server or remote */
+	unsigned svlocal:1;	/* local server or remote */
 	atomic_t socketUseCount; /* number of open cifs sessions on socket */
 	atomic_t inFlight;  /* number of requests on the wire to server */
 	enum statusEnum tcpStatus; /* what we think the status is */
@@ -222,7 +222,7 @@
 	FILE_SYSTEM_DEVICE_INFO fsDevInfo;
 	FILE_SYSTEM_ATTRIBUTE_INFO fsAttrInfo;	/* ok if file system name truncated */
 	FILE_SYSTEM_UNIX_INFO fsUnixInfo;
-	int retry:1;
+	unsigned retry:1;
 	/* BB add field for back pointer to sb struct? */
 };
 
@@ -250,10 +250,10 @@
 	/* lock scope id (0 if none) */
 	struct file * pfile; /* needed for writepage */
 	struct inode * pInode; /* needed for oplock break */
-	int endOfSearch:1;	/* we have reached end of search */
-	int closePend:1;	/* file is marked to close */
-	int emptyDir:1;
-	int invalidHandle:1;  /* file closed via session abend */
+	unsigned endOfSearch:1;	/* we have reached end of search */
+	unsigned closePend:1;	/* file is marked to close */
+	unsigned emptyDir:1;
+	unsigned invalidHandle:1;  /* file closed via session abend */
 	struct semaphore fh_sem; /* prevents reopen race after dead ses*/
 	char * search_resume_name;
 	unsigned int resume_name_length;
@@ -272,9 +272,9 @@
 	__u32 cifsAttrs; /* e.g. DOS archive bit, sparse, compressed, system */
 	atomic_t inUse;	 /* num concurrent users (local openers cifs) of file*/
 	unsigned long time;	/* jiffies of last update/check of inode */
-	int clientCanCacheRead:1; /* read oplock */
-	int clientCanCacheAll:1;  /* read and writebehind oplock */
-	int oplockPending:1;
+	unsigned clientCanCacheRead:1; /* read oplock */
+	unsigned clientCanCacheAll:1;  /* read and writebehind oplock */
+	unsigned oplockPending:1;
 	struct inode vfs_inode;
 };
 
diff -Nru a/fs/cifs/cifspdu.h b/fs/cifs/cifspdu.h
--- a/fs/cifs/cifspdu.h	2004-10-18 14:56:50 -07:00
+++ b/fs/cifs/cifspdu.h	2004-10-18 14:56:50 -07:00
@@ -137,15 +137,15 @@
 /*
  * SMB flag2 definitions 
  */
-#define SMBFLG2_KNOWS_LONG_NAMES 0x0001	/* can send long (non-8.3) path names in response */
-#define SMBFLG2_KNOWS_EAS 0x0002
-#define SMBFLG2_SECURITY_SIGNATURE 0x0004
-#define SMBFLG2_IS_LONG_NAME 0x0040
-#define SMBFLG2_EXT_SEC 0x0800
-#define SMBFLG2_DFS 0x1000
-#define SMBFLG2_PAGING_IO 0x2000
-#define SMBFLG2_ERR_STATUS 0x4000
-#define SMBFLG2_UNICODE 0x8000
+#define SMBFLG2_KNOWS_LONG_NAMES cpu_to_le16(1)	/* can send long (non-8.3) path names in response */
+#define SMBFLG2_KNOWS_EAS cpu_to_le16(2)
+#define SMBFLG2_SECURITY_SIGNATURE cpu_to_le16(4)
+#define SMBFLG2_IS_LONG_NAME cpu_to_le16(0x40)
+#define SMBFLG2_EXT_SEC cpu_to_le16(0x80)
+#define SMBFLG2_DFS cpu_to_le16(0x1000)
+#define SMBFLG2_PAGING_IO cpu_to_le16(0x2000)
+#define SMBFLG2_ERR_STATUS cpu_to_le16(0x4000)
+#define SMBFLG2_UNICODE cpu_to_le16(0x8000)
 
 /*
  * These are the file access permission bits defined in CIFS for the
@@ -303,23 +303,23 @@
 		struct {
 			__u8 ErrorClass;
 			__u8 Reserved;
-			__u16 Error;	/* note: treated as little endian (le) on wire */
+			__le16 Error;
 		} DosError;
-		__u32 CifsError;	/* note: le */
+		__le32 CifsError;
 	} Status;
 	__u8 Flags;
-	__u16 Flags2;		/* note: le */
-	__u16 PidHigh;		/* note: le */
+	__le16 Flags2;		/* note: le */
+	__le16 PidHigh;
 	union {
 		struct {
-			__u32 SequenceNumber;  /* le */
+			__le32 SequenceNumber;  /* le */
 			__u32 Reserved; /* zero */
 		} Sequence;
 		__u8 SecuritySignature[8];	/* le */
 	} Signature;
 	__u8 pad[2];
 	__u16 Tid;
-	__u16 Pid;		/* note: le */
+	__le16 Pid;
 	__u16 Uid;
 	__u16 Mid;
 	__u8 WordCount;
@@ -328,7 +328,7 @@
 #define BCC(smb_var) ( *(__u16 *)((char *)smb_var + sizeof(struct smb_hdr) + (2* smb_var->WordCount) ) )
 
 /* given a pointer to an smb_hdr retrieve the pointer to the byte area */
-#define pByteArea(smb_var) ((char *)smb_var + sizeof(struct smb_hdr) + (2* smb_var->WordCount) + 2 )
+#define pByteArea(smb_var) ((unsigned char *)smb_var + sizeof(struct smb_hdr) + (2* smb_var->WordCount) + 2 )
 
 /*
  * Computer Name Length
@@ -373,23 +373,23 @@
 
 typedef struct negotiate_req {
 	struct smb_hdr hdr;	/* wct = 0 */
-	__u16 ByteCount;
+	__le16 ByteCount;
 	unsigned char DialectsArray[1];
 } NEGOTIATE_REQ;
 
 typedef struct negotiate_rsp {
 	struct smb_hdr hdr;	/* wct = 17 */
-	__u16 DialectIndex;
+	__le16 DialectIndex;
 	__u8 SecurityMode;
-	__u16 MaxMpxCount;
-	__u16 MaxNumberVcs;
-	__u32 MaxBufferSize;
-	__u32 MaxRawSize;
-	__u32 SessionKey;
-	__u32 Capabilities;	/* see below */
-	__u32 SystemTimeLow;
-	__u32 SystemTimeHigh;
-	__u16 ServerTimeZone;
+	__le16 MaxMpxCount;
+	__le16 MaxNumberVcs;
+	__le32 MaxBufferSize;
+	__le32 MaxRawSize;
+	__le32 SessionKey;
+	__le32 Capabilities;	/* see below */
+	__le32 SystemTimeLow;
+	__le32 SystemTimeHigh;
+	__le16 ServerTimeZone;
 	__u8 EncryptionKeyLength;
 	__u16 ByteCount;
 	union {
@@ -436,15 +436,15 @@
 		struct smb_hdr hdr;	/* wct = 12 */
 		__u8 AndXCommand;
 		__u8 AndXReserved;
-		__u16 AndXOffset;
-		__u16 MaxBufferSize;
-		__u16 MaxMpxCount;
-		__u16 VcNumber;
+		__le16 AndXOffset;
+		__le16 MaxBufferSize;
+		__le16 MaxMpxCount;
+		__le16 VcNumber;
 		__u32 SessionKey;
-		__u16 SecurityBlobLength;
+		__le16 SecurityBlobLength;
 		__u32 Reserved;
-		__u32 Capabilities;	/* see below */
-		__u16 ByteCount;
+		__le32 Capabilities;	/* see below */
+		__le16 ByteCount;
 		unsigned char SecurityBlob[1];	/* followed by */
 		/* STRING NativeOS */
 		/* STRING NativeLanMan */
@@ -454,16 +454,16 @@
 		struct smb_hdr hdr;	/* wct = 13 */
 		__u8 AndXCommand;
 		__u8 AndXReserved;
-		__u16 AndXOffset;
-		__u16 MaxBufferSize;
-		__u16 MaxMpxCount;
-		__u16 VcNumber;
+		__le16 AndXOffset;
+		__le16 MaxBufferSize;
+		__le16 MaxMpxCount;
+		__le16 VcNumber;
 		__u32 SessionKey;
-		__u16 CaseInsensitivePasswordLength;	/* ASCII password length */
-		__u16 CaseSensitivePasswordLength;	/* Unicode password length */
+		__le16 CaseInsensitivePasswordLength;	/* ASCII password length */
+		__le16 CaseSensitivePasswordLength;	/* Unicode password length */
 		__u32 Reserved;	/* see below */
-		__u32 Capabilities;
-		__u16 ByteCount;
+		__le32 Capabilities;
+		__le16 ByteCount;
 		unsigned char CaseInsensitivePassword[1];	/* followed by: */
 		/* unsigned char * CaseSensitivePassword; */
 		/* STRING AccountName */
@@ -476,9 +476,9 @@
 		struct smb_hdr hdr;	/* wct = 4 */
 		__u8 AndXCommand;
 		__u8 AndXReserved;
-		__u16 AndXOffset;
-		__u16 Action;	/* see below */
-		__u16 SecurityBlobLength;
+		__le16 AndXOffset;
+		__le16 Action;	/* see below */
+		__le16 SecurityBlobLength;
 		__u16 ByteCount;
 		unsigned char SecurityBlob[1];	/* followed by */
 /*      unsigned char  * NativeOS;      */
@@ -490,14 +490,14 @@
 		struct smb_hdr hdr;	/* wct = 10 */
 		__u8 AndXCommand;
 		__u8 AndXReserved;
-		__u16 AndXOffset;
-		__u16 MaxBufferSize;
-		__u16 MaxMpxCount;
-		__u16 VcNumber;
+		__le16 AndXOffset;
+		__le16 MaxBufferSize;
+		__le16 MaxMpxCount;
+		__le16 VcNumber;
 		__u32 SessionKey;
-		__u16 PassswordLength;
+		__le16 PassswordLength;
 		__u32 Reserved;
-		__u16 ByteCount;
+		__le16 ByteCount;
 		unsigned char AccountPassword[1];	/* followed by */
 		/* STRING AccountName */
 		/* STRING PrimaryDomain */
@@ -509,8 +509,8 @@
 		struct smb_hdr hdr;	/* wct = 3 */
 		__u8 AndXCommand;
 		__u8 AndXReserved;
-		__u16 AndXOffset;
-		__u16 Action;	/* see below */
+		__le16 AndXOffset;
+		__le16 Action;	/* see below */
 		__u16 ByteCount;
 		unsigned char NativeOS[1];	/* followed by */
 /*	unsigned char * NativeLanMan; */
@@ -537,10 +537,10 @@
 	struct smb_hdr hdr;	/* wct = 4 */
 	__u8 AndXCommand;
 	__u8 AndXReserved;
-	__u16 AndXOffset;
-	__u16 Flags;		/* see below */
-	__u16 PasswordLength;
-	__u16 ByteCount;
+	__le16 AndXOffset;
+	__le16 Flags;		/* see below */
+	__le16 PasswordLength;
+	__le16 ByteCount;
 	unsigned char Password[1];	/* followed by */
 /* STRING Path    *//* \\server\share name */
 	/* STRING Service */
@@ -550,8 +550,8 @@
 	struct smb_hdr hdr;	/* wct = 3 *//* note that Win2000 has sent wct=7 in some cases on responses. Four unspecified words followed OptionalSupport */
 	__u8 AndXCommand;
 	__u8 AndXReserved;
-	__u16 AndXOffset;
-	__u16 OptionalSupport;	/* see below */
+	__le16 AndXOffset;
+	__le16 OptionalSupport;	/* see below */
 	__u16 ByteCount;
 	unsigned char Service[1];	/* always ASCII, not Unicode */
 	/* STRING NativeFileSystem */
@@ -619,20 +619,20 @@
 	struct smb_hdr hdr;	/* wct = 24 */
 	__u8 AndXCommand;
 	__u8 AndXReserved;
-	__u16 AndXOffset;
+	__le16 AndXOffset;
 	__u8 Reserved;		/* Must Be Zero */
-	__u16 NameLength;
-	__u32 OpenFlags;
-	__u32 RootDirectoryFid;
-	__u32 DesiredAccess;
-	__u64 AllocationSize;
-	__u32 FileAttributes;
-	__u32 ShareAccess;
-	__u32 CreateDisposition;
-	__u32 CreateOptions;
-	__u32 ImpersonationLevel;
+	__le16 NameLength;
+	__le32 OpenFlags;
+	__le32 RootDirectoryFid;
+	__le32 DesiredAccess;
+	__le64 AllocationSize;
+	__le32 FileAttributes;
+	__le32 ShareAccess;
+	__le32 CreateDisposition;
+	__le32 CreateOptions;
+	__le32 ImpersonationLevel;
 	__u8 SecurityFlags;
-	__u16 ByteCount;
+	__le16 ByteCount;
 	char fileName[1];
 } OPEN_REQ;
 
@@ -649,19 +649,19 @@
 	struct smb_hdr hdr;	/* wct = 34 BB */
 	__u8 AndXCommand;
 	__u8 AndXReserved;
-	__u16 AndXOffset;
+	__le16 AndXOffset;
 	__u8 OplockLevel;
 	__u16 Fid;
-	__u32 CreateAction;
-	__u64 CreationTime;
-	__u64 LastAccessTime;
-	__u64 LastWriteTime;
-	__u64 ChangeTime;
-	__u32 FileAttributes;
-	__u64 AllocationSize;
-	__u64 EndOfFile;
-	__u16 FileType;
-	__u16 DeviceState;
+	__le32 CreateAction;
+	__le64 CreationTime;
+	__le64 LastAccessTime;
+	__le64 LastWriteTime;
+	__le64 ChangeTime;
+	__le32 FileAttributes;
+	__le64 AllocationSize;
+	__le64 EndOfFile;
+	__le16 FileType;
+	__le16 DeviceState;
 	__u8 DirectoryFlag;
 	__u16 ByteCount;	/* bct = 0 */
 } OPEN_RSP;
@@ -670,17 +670,17 @@
 	struct smb_hdr hdr;	/* wct = 14 */
 	__u8 AndXCommand;
 	__u8 AndXReserved;
-	__u16 AndXOffset;
+	__le16 AndXOffset;
 	__u16 Fid;
-	__u32 OffsetLow;
+	__le32 OffsetLow;
 	__u32 Reserved;
-	__u16 WriteMode;
-	__u16 Remaining;
-	__u16 DataLengthHigh;
-	__u16 DataLengthLow;
-	__u16 DataOffset;
-	__u32 OffsetHigh;
-	__u16 ByteCount;
+	__le16 WriteMode;
+	__le16 Remaining;
+	__le16 DataLengthHigh;
+	__le16 DataLengthLow;
+	__le16 DataOffset;
+	__le32 OffsetHigh;
+	__le16 ByteCount;
 	__u8 Pad;		/* BB check for whether padded to DWORD boundary and optimum performance here */
 	char Data[1];
 } WRITE_REQ;
@@ -689,10 +689,10 @@
 	struct smb_hdr hdr;	/* wct = 6 */
 	__u8 AndXCommand;
 	__u8 AndXReserved;
-	__u16 AndXOffset;
-	__u16 Count;
-	__u16 Remaining;
-	__u32 Reserved;
+	__le16 AndXOffset;
+	__le16 Count;
+	__le16 Remaining;
+	__le32 Reserved;
 	__u16 ByteCount;
 } WRITE_RSP;
 
@@ -700,28 +700,28 @@
 	struct smb_hdr hdr;	/* wct = 12 */
 	__u8 AndXCommand;
 	__u8 AndXReserved;
-	__u16 AndXOffset;
+	__le16 AndXOffset;
 	__u16 Fid;
-	__u32 OffsetLow;
-	__u16 MaxCount;
-	__u16 MinCount;		/* obsolete */
-	__u32 MaxCountHigh;
-	__u16 Remaining;
-	__u32 OffsetHigh;
-	__u16 ByteCount;
+	__le32 OffsetLow;
+	__le16 MaxCount;
+	__le16 MinCount;		/* obsolete */
+	__le32 MaxCountHigh;
+	__le16 Remaining;
+	__le32 OffsetHigh;
+	__le16 ByteCount;
 } READ_REQ;
 
 typedef struct smb_com_read_rsp {
 	struct smb_hdr hdr;	/* wct = 12 */
 	__u8 AndXCommand;
 	__u8 AndXReserved;
-	__u16 AndXOffset;
-	__u16 Remaining;
-	__u16 DataCompactionMode;
-	__u16 Reserved;
-	__u16 DataLength;
-	__u16 DataOffset;
-	__u16 DataLengthHigh;
+	__le16 AndXOffset;
+	__le16 Remaining;
+	__le16 DataCompactionMode;
+	__le16 Reserved;
+	__le16 DataLength;
+	__le16 DataOffset;
+	__le16 DataLengthHigh;
 	__u64 Reserved2;
 	__u16 ByteCount;
 	__u8 Pad;		/* BB check for whether padded to DWORD boundary and optimum performance here */
@@ -729,12 +729,12 @@
 } READ_RSP;
 
 typedef struct locking_andx_range {
-	__u16 Pid;
-	__u16 Pad;
-	__u32 OffsetHigh;
-	__u32 OffsetLow;
-	__u32 LengthHigh;
-	__u32 LengthLow;
+	__le16 Pid;
+	__le16 Pad;
+	__le32 OffsetHigh;
+	__le32 OffsetLow;
+	__le32 LengthHigh;
+	__le32 LengthLow;
 } LOCKING_ANDX_RANGE;
 
 #define LOCKING_ANDX_SHARED_LOCK     0x01
@@ -747,14 +747,14 @@
 	struct smb_hdr hdr;	/* wct = 8 */
 	__u8 AndXCommand;
 	__u8 AndXReserved;
-	__u16 AndXOffset;
+	__le16 AndXOffset;
 	__u16 Fid;
 	__u8 LockType;
 	__u8 OplockLevel;
-	__u32 Timeout;
-	__u16 NumberOfUnlocks;
-	__u16 NumberOfLocks;
-	__u16 ByteCount;
+	__le32 Timeout;
+	__le16 NumberOfUnlocks;
+	__le16 NumberOfLocks;
+	__le16 ByteCount;
 	LOCKING_ANDX_RANGE Locks[1];
 } LOCK_REQ;
 
@@ -762,14 +762,14 @@
 	struct smb_hdr hdr;	/* wct = 2 */
 	__u8 AndXCommand;
 	__u8 AndXReserved;
-	__u16 AndXOffset;
+	__le16 AndXOffset;
 	__u16 ByteCount;
 } LOCK_RSP;
 
 typedef struct smb_com_rename_req {
 	struct smb_hdr hdr;	/* wct = 1 */
-	__u16 SearchAttributes;	/* target file attributes */
-	__u16 ByteCount;
+	__le16 SearchAttributes;	/* target file attributes */
+	__le16 ByteCount;
 	__u8 BufferFormat;	/* 4 = ASCII or Unicode */
 	unsigned char OldFileName[1];
 	/* followed by __u8 BufferFormat2 */
@@ -787,9 +787,9 @@
 typedef struct smb_com_copy_req {
 	struct smb_hdr hdr;	/* wct = 3 */
 	__u16 Tid2;
-	__u16 OpenFunction;
-	__u16 Flags;
-	__u16 ByteCount;
+	__le16 OpenFunction;
+	__le16 Flags;
+	__le16 ByteCount;
 	__u8 BufferFormat;	/* 4 = ASCII or Unicode */ 
 	unsigned char OldFileName[1];
 	/* followed by __u8 BufferFormat2 */
@@ -798,7 +798,7 @@
 
 typedef struct smb_com_copy_rsp {
 	struct smb_hdr hdr;     /* wct = 1 */
-	__u16 CopyCount;    /* number of files copied */
+	__le16 CopyCount;    /* number of files copied */
 	__u16 ByteCount;    /* may be zero */
 	__u8 BufferFormat;  /* 0x04 - only present if errored file follows */
 	unsigned char ErrorFileName[1]; /* only present if error in copy */
@@ -810,10 +810,10 @@
 
 typedef struct smb_com_nt_rename_req {	/* A5 - also used for create hardlink */
 	struct smb_hdr hdr;	/* wct = 4 */
-	__u16 SearchAttributes;	/* target file attributes */
-	__u16 Flags;		/* spec says Information Level */
-	__u32 ClusterCount;
-	__u16 ByteCount;
+	__le16 SearchAttributes;	/* target file attributes */
+	__le16 Flags;		/* spec says Information Level */
+	__le32 ClusterCount;
+	__le16 ByteCount;
 	__u8 BufferFormat;	/* 4 = ASCII or Unicode */
 	unsigned char OldFileName[1];
 	/* followed by __u8 BufferFormat2 */
@@ -827,8 +827,8 @@
 
 typedef struct smb_com_delete_file_req {
 	struct smb_hdr hdr;	/* wct = 1 */
-	__u16 SearchAttributes;
-	__u16 ByteCount;
+	__le16 SearchAttributes;
+	__le16 ByteCount;
 	__u8 BufferFormat;	/* 4 = ASCII */
 	unsigned char fileName[1];
 } DELETE_FILE_REQ;
@@ -840,7 +840,7 @@
 
 typedef struct smb_com_delete_directory_req {
 	struct smb_hdr hdr;	/* wct = 0 */
-	__u16 ByteCount;
+	__le16 ByteCount;
 	__u8 BufferFormat;	/* 4 = ASCII */
 	unsigned char DirName[1];
 } DELETE_DIRECTORY_REQ;
@@ -852,7 +852,7 @@
 
 typedef struct smb_com_create_directory_req {
 	struct smb_hdr hdr;	/* wct = 0 */
-	__u16 ByteCount;
+	__le16 ByteCount;
 	__u8 BufferFormat;	/* 4 = ASCII */
 	unsigned char DirName[1];
 } CREATE_DIRECTORY_REQ;
@@ -870,22 +870,22 @@
 	struct smb_hdr hdr;	/* wct = 23 */
 	__u8 MaxSetupCount;
 	__u16 Reserved;
-	__u32 TotalParameterCount;
-	__u32 TotalDataCount;
-	__u32 MaxParameterCount;
-	__u32 MaxDataCount;
-	__u32 ParameterCount;
-	__u32 ParameterOffset;
-	__u32 DataCount;
-	__u32 DataOffset;
+	__le32 TotalParameterCount;
+	__le32 TotalDataCount;
+	__le32 MaxParameterCount;
+	__le32 MaxDataCount;
+	__le32 ParameterCount;
+	__le32 ParameterOffset;
+	__le32 DataCount;
+	__le32 DataOffset;
 	__u8 SetupCount; /* four setup words follow subcommand */
 	/* SNIA spec incorrectly included spurious pad here */
-	__u16 SubCommand;/* 2 = IOCTL/FSCTL */
-	__u32 FunctionCode;
+	__le16 SubCommand;/* 2 = IOCTL/FSCTL */
+	__le32 FunctionCode;
 	__u16 Fid;
 	__u8 IsFsctl;    /* 1 = File System Control, 0 = device control (IOCTL)*/
 	__u8 IsRootFlag; /* 1 = apply command to root of share (must be DFS share)*/
-	__u16 ByteCount;
+	__le16 ByteCount;
 	__u8 Pad[3];
 	__u8 Data[1];
 } TRANSACT_IOCTL_REQ;
@@ -893,16 +893,16 @@
 typedef struct smb_com_transaction_ioctl_rsp {
 	struct smb_hdr hdr;	/* wct = 19 */
 	__u8 Reserved[3];
-	__u32 TotalParameterCount;
-	__u32 TotalDataCount;
-	__u32 ParameterCount;
-	__u32 ParameterOffset;
-	__u32 ParameterDisplacement;
-	__u32 DataCount;
-	__u32 DataOffset;
-	__u32 DataDisplacement;
+	__le32 TotalParameterCount;
+	__le32 TotalDataCount;
+	__le32 ParameterCount;
+	__le32 ParameterOffset;
+	__le32 ParameterDisplacement;
+	__le32 DataCount;
+	__le32 DataOffset;
+	__le32 DataDisplacement;
 	__u8 SetupCount;	/* 1 */
-	__u16 ReturnedDataLen;
+	__le16 ReturnedDataLen;
 	__u16 ByteCount;
 	__u8 Pad[3];
 } TRANSACT_IOCTL_RSP;
@@ -911,22 +911,22 @@
 	struct smb_hdr hdr;     /* wct = 23 */
 	__u8 MaxSetupCount;
 	__u16 Reserved;
-	__u32 TotalParameterCount;
-	__u32 TotalDataCount;
-	__u32 MaxParameterCount;
-	__u32 MaxDataCount;
-	__u32 ParameterCount;
-	__u32 ParameterOffset;
-	__u32 DataCount;
-	__u32 DataOffset;
+	__le32 TotalParameterCount;
+	__le32 TotalDataCount;
+	__le32 MaxParameterCount;
+	__le32 MaxDataCount;
+	__le32 ParameterCount;
+	__le32 ParameterOffset;
+	__le32 DataCount;
+	__le32 DataOffset;
 	__u8 SetupCount; /* four setup words follow subcommand */
 	/* SNIA spec incorrectly included spurious pad here */
-	__u16 SubCommand;/* 4 = Change Notify */
-	__u32 CompletionFilter;  /* operation to monitor */
+	__le16 SubCommand;/* 4 = Change Notify */
+	__le32 CompletionFilter;  /* operation to monitor */
 	__u16 Fid;
 	__u8 WatchTree;  /* 1 = Monitor subdirectories */
 	__u8 Reserved2;
-	__u16 ByteCount;
+	__le16 ByteCount;
 /* __u8 Pad[3];*/
 /*	__u8 Data[1];*/
 } TRANSACT_CHANGE_NOTIFY_REQ;
@@ -934,14 +934,14 @@
 typedef struct smb_com_transaction_change_notify_rsp {
 	struct smb_hdr hdr;	/* wct = 18 */
 	__u8 Reserved[3];
-	__u32 TotalParameterCount;
-	__u32 TotalDataCount;
-	__u32 ParameterCount;
-	__u32 ParameterOffset;
-	__u32 ParameterDisplacement;
-	__u32 DataCount;
-	__u32 DataOffset;
-	__u32 DataDisplacement;
+	__le32 TotalParameterCount;
+	__le32 TotalDataCount;
+	__le32 ParameterCount;
+	__le32 ParameterOffset;
+	__le32 ParameterDisplacement;
+	__le32 DataCount;
+	__le32 DataOffset;
+	__le32 DataDisplacement;
 	__u8 SetupCount;   /* 0 */
 	__u16 ByteCount;
 	/* __u8 Pad[3]; */
@@ -1090,40 +1090,40 @@
 
 typedef struct smb_com_transaction2_qpi_req {
 	struct smb_hdr hdr;	/* wct = 14+ */
-	__u16 TotalParameterCount;
-	__u16 TotalDataCount;
-	__u16 MaxParameterCount;
-	__u16 MaxDataCount;
+	__le16 TotalParameterCount;
+	__le16 TotalDataCount;
+	__le16 MaxParameterCount;
+	__le16 MaxDataCount;
 	__u8 MaxSetupCount;
 	__u8 Reserved;
-	__u16 Flags;
-	__u32 Timeout;
+	__le16 Flags;
+	__le32 Timeout;
 	__u16 Reserved2;
-	__u16 ParameterCount;
-	__u16 ParameterOffset;
-	__u16 DataCount;
-	__u16 DataOffset;
+	__le16 ParameterCount;
+	__le16 ParameterOffset;
+	__le16 DataCount;
+	__le16 DataOffset;
 	__u8 SetupCount;
 	__u8 Reserved3;
-	__u16 SubCommand;	/* one setup word */
-	__u16 ByteCount;
+	__le16 SubCommand;	/* one setup word */
+	__le16 ByteCount;
 	__u8 Pad;
-	__u16 InformationLevel;
+	__le16 InformationLevel;
 	__u32 Reserved4;
 	char FileName[1];
 } TRANSACTION2_QPI_REQ;
 
 typedef struct smb_com_transaction2_qpi_rsp {
 	struct smb_hdr hdr;	/* wct = 10 + SetupCount */
-	__u16 TotalParameterCount;
-	__u16 TotalDataCount;
-	__u16 Reserved;
-	__u16 ParameterCount;
-	__u16 ParameterOffset;
-	__u16 ParameterDisplacement;
-	__u16 DataCount;
-	__u16 DataOffset;
-	__u16 DataDisplacement;
+	__le16 TotalParameterCount;
+	__le16 TotalDataCount;
+	__le16 Reserved;
+	__le16 ParameterCount;
+	__le16 ParameterOffset;
+	__le16 ParameterDisplacement;
+	__le16 DataCount;
+	__le16 DataOffset;
+	__le16 DataDisplacement;
 	__u8 SetupCount;
 	__u8 Reserved1;		/* should be zero setup words following */
 	__u16 ByteCount;
@@ -1132,41 +1132,41 @@
 
 typedef struct smb_com_transaction2_spi_req {
 	struct smb_hdr hdr;	/* wct = 15 */
-	__u16 TotalParameterCount;
-	__u16 TotalDataCount;
-	__u16 MaxParameterCount;
-	__u16 MaxDataCount;
+	__le16 TotalParameterCount;
+	__le16 TotalDataCount;
+	__le16 MaxParameterCount;
+	__le16 MaxDataCount;
 	__u8 MaxSetupCount;
 	__u8 Reserved;
-	__u16 Flags;
-	__u32 Timeout;
+	__le16 Flags;
+	__le32 Timeout;
 	__u16 Reserved2;
-	__u16 ParameterCount;
-	__u16 ParameterOffset;
-	__u16 DataCount;
-	__u16 DataOffset;
+	__le16 ParameterCount;
+	__le16 ParameterOffset;
+	__le16 DataCount;
+	__le16 DataOffset;
 	__u8 SetupCount;
 	__u8 Reserved3;
-	__u16 SubCommand;	/* one setup word */
-	__u16 ByteCount;
+	__le16 SubCommand;	/* one setup word */
+	__le16 ByteCount;
 	__u8 Pad;
 	__u16 Pad1;
-	__u16 InformationLevel;
+	__le16 InformationLevel;
 	__u32 Reserved4;
 	char FileName[1];
 } TRANSACTION2_SPI_REQ;
 
 typedef struct smb_com_transaction2_spi_rsp {
 	struct smb_hdr hdr;	/* wct = 10 + SetupCount */
-	__u16 TotalParameterCount;
-	__u16 TotalDataCount;
+	__le16 TotalParameterCount;
+	__le16 TotalDataCount;
 	__u16 Reserved;
-	__u16 ParameterCount;
-	__u16 ParameterOffset;
-	__u16 ParameterDisplacement;
-	__u16 DataCount;
-	__u16 DataOffset;
-	__u16 DataDisplacement;
+	__le16 ParameterCount;
+	__le16 ParameterOffset;
+	__le16 ParameterDisplacement;
+	__le16 DataCount;
+	__le16 DataOffset;
+	__le16 DataDisplacement;
 	__u8 SetupCount;
 	__u8 Reserved1;		/* should be zero setup words following */
 	__u16 ByteCount;
@@ -1174,49 +1174,49 @@
 } TRANSACTION2_SPI_RSP;
 
 struct set_file_rename {
-	__u32 overwrite;   /* 1 = overwrite dest */
+	__le32 overwrite;   /* 1 = overwrite dest */
 	__u32 root_fid;   /* zero */
-	__u32 target_name_len;
+	__le32 target_name_len;
 	char  target_name[0];  /* Must be unicode */
 };
 
 struct smb_com_transaction2_sfi_req {
 	struct smb_hdr hdr;	/* wct = 15 */
-	__u16 TotalParameterCount;
-	__u16 TotalDataCount;
-	__u16 MaxParameterCount;
-	__u16 MaxDataCount;
+	__le16 TotalParameterCount;
+	__le16 TotalDataCount;
+	__le16 MaxParameterCount;
+	__le16 MaxDataCount;
 	__u8 MaxSetupCount;
 	__u8 Reserved;
-	__u16 Flags;
-	__u32 Timeout;
+	__le16 Flags;
+	__le32 Timeout;
 	__u16 Reserved2;
-	__u16 ParameterCount;
-	__u16 ParameterOffset;
-	__u16 DataCount;
-	__u16 DataOffset;
+	__le16 ParameterCount;
+	__le16 ParameterOffset;
+	__le16 DataCount;
+	__le16 DataOffset;
 	__u8 SetupCount;
 	__u8 Reserved3;
-	__u16 SubCommand;	/* one setup word */
-	__u16 ByteCount;
+	__le16 SubCommand;	/* one setup word */
+	__le16 ByteCount;
 	__u8 Pad;
 	__u16 Pad1;
 	__u16 Fid;
-	__u16 InformationLevel;
+	__le16 InformationLevel;
 	__u16 Reserved4;	
 };
 
 struct smb_com_transaction2_sfi_rsp {
 	struct smb_hdr hdr;	/* wct = 10 + SetupCount */
-	__u16 TotalParameterCount;
-	__u16 TotalDataCount;
+	__le16 TotalParameterCount;
+	__le16 TotalDataCount;
 	__u16 Reserved;
-	__u16 ParameterCount;
-	__u16 ParameterOffset;
-	__u16 ParameterDisplacement;
-	__u16 DataCount;
-	__u16 DataOffset;
-	__u16 DataDisplacement;
+	__le16 ParameterCount;
+	__le16 ParameterOffset;
+	__le16 ParameterDisplacement;
+	__le16 DataCount;
+	__le16 DataOffset;
+	__le16 DataDisplacement;
 	__u8 SetupCount;
 	__u8 Reserved1;		/* should be zero setup words following */
 	__u16 ByteCount;
@@ -1240,43 +1240,43 @@
 
 typedef struct smb_com_transaction2_ffirst_req {
 	struct smb_hdr hdr;	/* wct = 15 */
-	__u16 TotalParameterCount;
-	__u16 TotalDataCount;
-	__u16 MaxParameterCount;
-	__u16 MaxDataCount;
+	__le16 TotalParameterCount;
+	__le16 TotalDataCount;
+	__le16 MaxParameterCount;
+	__le16 MaxDataCount;
 	__u8 MaxSetupCount;
 	__u8 Reserved;
-	__u16 Flags;
-	__u32 Timeout;
+	__le16 Flags;
+	__le32 Timeout;
 	__u16 Reserved2;
-	__u16 ParameterCount;
-	__u16 ParameterOffset;
-	__u16 DataCount;
-	__u16 DataOffset;
+	__le16 ParameterCount;
+	__le16 ParameterOffset;
+	__le16 DataCount;
+	__le16 DataOffset;
 	__u8 SetupCount;	/* one */
 	__u8 Reserved3;
-	__u16 SubCommand;	/* TRANS2_FIND_FIRST */
-	__u16 ByteCount;
+	__le16 SubCommand;	/* TRANS2_FIND_FIRST */
+	__le16 ByteCount;
 	__u8 Pad;
-	__u16 SearchAttributes;
-	__u16 SearchCount;
-	__u16 SearchFlags;
-	__u16 InformationLevel;
-	__u32 SearchStorageType;
+	__le16 SearchAttributes;
+	__le16 SearchCount;
+	__le16 SearchFlags;
+	__le16 InformationLevel;
+	__le32 SearchStorageType;
 	char FileName[1];
 } TRANSACTION2_FFIRST_REQ;
 
 typedef struct smb_com_transaction2_ffirst_rsp {
 	struct smb_hdr hdr;	/* wct = 10 */
-	__u16 TotalParameterCount;
-	__u16 TotalDataCount;
+	__le16 TotalParameterCount;
+	__le16 TotalDataCount;
 	__u16 Reserved;
-	__u16 ParameterCount;
-	__u16 ParameterOffset;
-	__u16 ParameterDisplacement;
-	__u16 DataCount;
-	__u16 DataOffset;
-	__u16 DataDisplacement;
+	__le16 ParameterCount;
+	__le16 ParameterOffset;
+	__le16 ParameterDisplacement;
+	__le16 DataCount;
+	__le16 DataOffset;
+	__le16 DataDisplacement;
 	__u8 SetupCount;
 	__u8 Reserved1;		/* should be zero setup words following */
 	__u16 ByteCount;
@@ -1284,61 +1284,61 @@
 
 typedef struct smb_com_transaction2_ffirst_rsp_parms {
 	__u16 SearchHandle;
-	__u16 SearchCount;
-	__u16 EndofSearch;
-	__u16 EAErrorOffset;
-	__u16 LastNameOffset;
+	__le16 SearchCount;
+	__le16 EndofSearch;
+	__le16 EAErrorOffset;
+	__le16 LastNameOffset;
 } T2_FFIRST_RSP_PARMS;
 
 typedef struct smb_com_transaction2_fnext_req {
 	struct smb_hdr hdr;	/* wct = 15 */
-	__u16 TotalParameterCount;
-	__u16 TotalDataCount;
-	__u16 MaxParameterCount;
-	__u16 MaxDataCount;
+	__le16 TotalParameterCount;
+	__le16 TotalDataCount;
+	__le16 MaxParameterCount;
+	__le16 MaxDataCount;
 	__u8 MaxSetupCount;
 	__u8 Reserved;
-	__u16 Flags;
-	__u32 Timeout;
+	__le16 Flags;
+	__le32 Timeout;
 	__u16 Reserved2;
-	__u16 ParameterCount;
-	__u16 ParameterOffset;
-	__u16 DataCount;
-	__u16 DataOffset;
+	__le16 ParameterCount;
+	__le16 ParameterOffset;
+	__le16 DataCount;
+	__le16 DataOffset;
 	__u8 SetupCount;	/* one */
 	__u8 Reserved3;
-	__u16 SubCommand;	/* TRANS2_FIND_NEXT */
-	__u16 ByteCount;
+	__le16 SubCommand;	/* TRANS2_FIND_NEXT */
+	__le16 ByteCount;
 	__u8 Pad;
 	__u16 SearchHandle;
-	__u16 SearchCount;
-	__u16 InformationLevel;
+	__le16 SearchCount;
+	__le16 InformationLevel;
 	__u32 ResumeKey;
-	__u16 SearchFlags;
+	__le16 SearchFlags;
 	char ResumeFileName[1];
 } TRANSACTION2_FNEXT_REQ;
 
 typedef struct smb_com_transaction2_fnext_rsp {
 	struct smb_hdr hdr;	/* wct = 10 */
-	__u16 TotalParameterCount;
-	__u16 TotalDataCount;
+	__le16 TotalParameterCount;
+	__le16 TotalDataCount;
 	__u16 Reserved;
-	__u16 ParameterCount;
-	__u16 ParameterOffset;
-	__u16 ParameterDisplacement;
-	__u16 DataCount;
-	__u16 DataOffset;
-	__u16 DataDisplacement;
+	__le16 ParameterCount;
+	__le16 ParameterOffset;
+	__le16 ParameterDisplacement;
+	__le16 DataCount;
+	__le16 DataOffset;
+	__le16 DataDisplacement;
 	__u8 SetupCount;
 	__u8 Reserved1;		/* should be zero setup words following */
 	__u16 ByteCount;
 } TRANSACTION2_FNEXT_RSP;
 
 typedef struct smb_com_transaction2_fnext_rsp_parms {
-	__u16 SearchCount;
-	__u16 EndofSearch;
-	__u16 EAErrorOffset;
-	__u16 LastNameOffset;
+	__le16 SearchCount;
+	__le16 EndofSearch;
+	__le16 EAErrorOffset;
+	__le16 LastNameOffset;
 } T2_FNEXT_RSP_PARMS;
 
 /* QFSInfo Levels */
@@ -1354,38 +1354,38 @@
 
 typedef struct smb_com_transaction2_qfsi_req {
 	struct smb_hdr hdr;	/* wct = 14+ */
-	__u16 TotalParameterCount;
-	__u16 TotalDataCount;
-	__u16 MaxParameterCount;
-	__u16 MaxDataCount;
+	__le16 TotalParameterCount;
+	__le16 TotalDataCount;
+	__le16 MaxParameterCount;
+	__le16 MaxDataCount;
 	__u8 MaxSetupCount;
 	__u8 Reserved;
-	__u16 Flags;
-	__u32 Timeout;
+	__le16 Flags;
+	__le32 Timeout;
 	__u16 Reserved2;
-	__u16 ParameterCount;
-	__u16 ParameterOffset;
-	__u16 DataCount;
-	__u16 DataOffset;
+	__le16 ParameterCount;
+	__le16 ParameterOffset;
+	__le16 DataCount;
+	__le16 DataOffset;
 	__u8 SetupCount;
 	__u8 Reserved3;
-	__u16 SubCommand;	/* one setup word */
-	__u16 ByteCount;
+	__le16 SubCommand;	/* one setup word */
+	__le16 ByteCount;
 	__u8 Pad;
-	__u16 InformationLevel;
+	__le16 InformationLevel;
 } TRANSACTION2_QFSI_REQ;
 
 typedef struct smb_com_transaction_qfsi_rsp {
 	struct smb_hdr hdr;	/* wct = 10 + SetupCount */
-	__u16 TotalParameterCount;
-	__u16 TotalDataCount;
+	__le16 TotalParameterCount;
+	__le16 TotalDataCount;
 	__u16 Reserved;
-	__u16 ParameterCount;
-	__u16 ParameterOffset;
-	__u16 ParameterDisplacement;
-	__u16 DataCount;
-	__u16 DataOffset;
-	__u16 DataDisplacement;
+	__le16 ParameterCount;
+	__le16 ParameterOffset;
+	__le16 ParameterDisplacement;
+	__le16 DataCount;
+	__le16 DataOffset;
+	__le16 DataDisplacement;
 	__u8 SetupCount;
 	__u8 Reserved1;		/* should be zero setup words following */
 	__u16 ByteCount;
@@ -1394,58 +1394,58 @@
 
 typedef struct smb_com_transaction2_get_dfs_refer_req {
 	struct smb_hdr hdr;	/* wct = 15 */
-	__u16 TotalParameterCount;
-	__u16 TotalDataCount;
-	__u16 MaxParameterCount;
-	__u16 MaxDataCount;
+	__le16 TotalParameterCount;
+	__le16 TotalDataCount;
+	__le16 MaxParameterCount;
+	__le16 MaxDataCount;
 	__u8 MaxSetupCount;
 	__u8 Reserved;
-	__u16 Flags;
-	__u32 Timeout;
+	__le16 Flags;
+	__le32 Timeout;
 	__u16 Reserved2;
-	__u16 ParameterCount;
-	__u16 ParameterOffset;
-	__u16 DataCount;
-	__u16 DataOffset;
+	__le16 ParameterCount;
+	__le16 ParameterOffset;
+	__le16 DataCount;
+	__le16 DataOffset;
 	__u8 SetupCount;
 	__u8 Reserved3;
-	__u16 SubCommand;	/* one setup word */
-	__u16 ByteCount;
+	__le16 SubCommand;	/* one setup word */
+	__le16 ByteCount;
 	__u8 Pad[3];		/* Win2K has sent 0x0F01 (max resp length perhaps?) followed by one byte pad - doesn't seem to matter though */
-	__u16 MaxReferralLevel;
+	__le16 MaxReferralLevel;
 	char RequestFileName[1];
 } TRANSACTION2_GET_DFS_REFER_REQ;
 
 typedef struct dfs_referral_level_3 {
-	__u16 VersionNumber;
-	__u16 ReferralSize;
-	__u16 ServerType;	/* 0x0001 = CIFS server */
-	__u16 ReferralFlags;	/* or proximity - not clear which since always set to zero - SNIA spec says 0x01 means strip off PathConsumed chars before submitting RequestFileName to remote node */
-	__u16 TimeToLive;
-	__u16 Proximity;
-	__u16 DfsPathOffset;
-	__u16 DfsAlternatePathOffset;
-	__u16 NetworkAddressOffset;
+	__le16 VersionNumber;
+	__le16 ReferralSize;
+	__le16 ServerType;	/* 0x0001 = CIFS server */
+	__le16 ReferralFlags;	/* or proximity - not clear which since always set to zero - SNIA spec says 0x01 means strip off PathConsumed chars before submitting RequestFileName to remote node */
+	__le16 TimeToLive;
+	__le16 Proximity;
+	__le16 DfsPathOffset;
+	__le16 DfsAlternatePathOffset;
+	__le16 NetworkAddressOffset;
 } REFERRAL3;
 
 typedef struct smb_com_transaction_get_dfs_refer_rsp {
 	struct smb_hdr hdr;	/* wct = 10 */
-	__u16 TotalParameterCount;
-	__u16 TotalDataCount;
+	__le16 TotalParameterCount;
+	__le16 TotalDataCount;
 	__u16 Reserved;
-	__u16 ParameterCount;
-	__u16 ParameterOffset;
-	__u16 ParameterDisplacement;
-	__u16 DataCount;
-	__u16 DataOffset;
-	__u16 DataDisplacement;
+	__le16 ParameterCount;
+	__le16 ParameterOffset;
+	__le16 ParameterDisplacement;
+	__le16 DataCount;
+	__le16 DataOffset;
+	__le16 DataDisplacement;
 	__u8 SetupCount;
 	__u8 Reserved1;		/* zero setup words following */
 	__u16 ByteCount;
 	__u8 Pad;
-	__u16 PathConsumed;
-	__u16 NumberOfReferrals;
-	__u16 DFSFlags;
+	__le16 PathConsumed;
+	__le16 NumberOfReferrals;
+	__le16 DFSFlags;
 	__u16 Pad2;
 	REFERRAL3 referrals[1];	/* array of level 3 dfs_referral structures */
 	/* followed by the strings pointed to by the referral structures */
@@ -1531,16 +1531,16 @@
 };
 
 typedef struct {
-	__u64 TotalAllocationUnits;
-	__u64 FreeAllocationUnits;
-	__u32 SectorsPerAllocationUnit;
-	__u32 BytesPerSector;
+	__le64 TotalAllocationUnits;
+	__le64 FreeAllocationUnits;
+	__le32 SectorsPerAllocationUnit;
+	__le32 BytesPerSector;
 } FILE_SYSTEM_INFO;		/* size info, level 0x103 */
 
 typedef struct {
-	__u16 MajorVersionNumber;
-	__u16 MinorVersionNumber;
-	__u64 Capability;
+	__le16 MajorVersionNumber;
+	__le16 MinorVersionNumber;
+	__le64 Capability;
 } FILE_SYSTEM_UNIX_INFO;	/* Unix extensions info, level 0x200 */
 /* Linux/Unix extensions capability flags */
 #define CIFS_UNIX_FCNTL_CAP             0x00000001 /* support for fcntl locks */
@@ -1567,55 +1567,55 @@
 #define FILE_DEVICE_NETWORK_REDIRECTOR  0x00000028
 
 typedef struct {
-	__u32 DeviceType;
-	__u32 DeviceCharacteristics;
+	__le32 DeviceType;
+	__le32 DeviceCharacteristics;
 } FILE_SYSTEM_DEVICE_INFO;	/* device info, level 0x104 */
 
 typedef struct {
-	__u32 Attributes;
-	__u32 MaxPathNameComponentLength;
-	__u32 FileSystemNameLen;
+	__le32 Attributes;
+	__le32 MaxPathNameComponentLength;
+	__le32 FileSystemNameLen;
 	char FileSystemName[52];	/* do not really need to save this - so potentially get only subset of name */
 } FILE_SYSTEM_ATTRIBUTE_INFO;
 
 typedef struct {		/* data block encoding of response to level 263 QPathInfo */
-	__u64 CreationTime;
-	__u64 LastAccessTime;
-	__u64 LastWriteTime;
-	__u64 ChangeTime;
-	__u32 Attributes;
+	__le64 CreationTime;
+	__le64 LastAccessTime;
+	__le64 LastWriteTime;
+	__le64 ChangeTime;
+	__le32 Attributes;
 	__u32 Pad1;
-	__u64 AllocationSize;
-	__u64 EndOfFile;	/* size ie offset to first free byte in file */
-	__u32 NumberOfLinks;	/* hard links */
+	__le64 AllocationSize;
+	__le64 EndOfFile;	/* size ie offset to first free byte in file */
+	__le32 NumberOfLinks;	/* hard links */
 	__u8 DeletePending;
 	__u8 Directory;
 	__u16 Pad2;
 	__u64 IndexNumber;
-	__u32 EASize;
-	__u32 AccessFlags;
+	__le32 EASize;
+	__le32 AccessFlags;
 	__u64 IndexNumber1;
-	__u64 CurrentByteOffset;
-	__u32 Mode;
-	__u32 AlignmentRequirement;
-	__u32 FileNameLength;
+	__le64 CurrentByteOffset;
+	__le32 Mode;
+	__le32 AlignmentRequirement;
+	__le32 FileNameLength;
 	char FileName[1];
 } FILE_ALL_INFO;		/* level 263 QPathInfo */
 
 typedef struct {
-	__u64 EndOfFile;
-	__u64 NumOfBytes;
-	__u64 LastStatusChange;	/*SNIA spec says DCE time for the three time fields */
-	__u64 LastAccessTime;
-	__u64 LastModificationTime;
-	__u64 Uid;
-	__u64 Gid;
-	__u32 Type;
-	__u64 DevMajor;
-	__u64 DevMinor;
+	__le64 EndOfFile;
+	__le64 NumOfBytes;
+	__le64 LastStatusChange;	/*SNIA spec says DCE time for the three time fields */
+	__le64 LastAccessTime;
+	__le64 LastModificationTime;
+	__le64 Uid;
+	__le64 Gid;
+	__le32 Type;
+	__le64 DevMajor;
+	__le64 DevMinor;
 	__u64 UniqueId;
-	__u64 Permissions;
-	__u64 Nlinks;
+	__le64 Permissions;
+	__le64 Nlinks;
 } FILE_UNIX_BASIC_INFO;		/* level 512 QPathInfo */
 
 typedef struct {
@@ -1645,52 +1645,52 @@
 #define UNIX_SOCKET    6
 
 typedef struct {
-	__u32 NextEntryOffset;
-	__u32 ResumeKey;
-	__u64 EndOfFile;
-	__u64 NumOfBytes;
-	__u64 LastStatusChange;	/*SNIA spec says DCE time for the three time fields */
-	__u64 LastAccessTime;
-	__u64 LastModificationTime;
-	__u64 Uid;
-	__u64 Gid;
-	__u32 Type;
-	__u64 DevMajor;
-	__u64 DevMinor;
-	__u64 UniqueId;
-	__u64 Permissions;
-	__u64 Nlinks;
+	__le32 NextEntryOffset;
+	__le32 ResumeKey;
+	__le64 EndOfFile;
+	__le64 NumOfBytes;
+	__le64 LastStatusChange;	/*SNIA spec says DCE time for the three time fields */
+	__le64 LastAccessTime;
+	__le64 LastModificationTime;
+	__le64 Uid;
+	__le64 Gid;
+	__le32 Type;
+	__le64 DevMajor;
+	__le64 DevMinor;
+	__le64 UniqueId;
+	__le64 Permissions;
+	__le64 Nlinks;
 	char FileName[1];
 } FILE_UNIX_INFO;
 
 typedef struct {
-	__u64 CreationTime;
-	__u64 LastAccessTime;
-	__u64 LastWriteTime;
-	__u64 ChangeTime;
-	__u32 Attributes;
+	__le64 CreationTime;
+	__le64 LastAccessTime;
+	__le64 LastWriteTime;
+	__le64 ChangeTime;
+	__le32 Attributes;
 	__u32 Pad;
 } FILE_BASIC_INFO;		/* size info, level 0x101 */
 
 struct file_allocation_info {
-	__u64 AllocationSize;
+	__le64 AllocationSize;
 };		/* size info, level 0x103 */
 
 struct file_end_of_file_info {
-	__u64 FileSize;		/* offset to end of file */
+	__le64 FileSize;		/* offset to end of file */
 };	/* size info, level 0x104 */
 
 typedef struct {
-	__u32 NextEntryOffset;
+	__le32 NextEntryOffset;
 	__u32 FileIndex;
-	__u64 CreationTime;
-	__u64 LastAccessTime;
-	__u64 LastWriteTime;
-	__u64 ChangeTime;
-	__u64 EndOfFile;
-	__u64 AllocationSize;
-	__u32 ExtFileAttributes;
-	__u32 FileNameLength;
+	__le64 CreationTime;
+	__le64 LastAccessTime;
+	__le64 LastWriteTime;
+	__le64 ChangeTime;
+	__le64 EndOfFile;
+	__le64 AllocationSize;
+	__le32 ExtFileAttributes;
+	__le32 FileNameLength;
 	char FileName[1];
 } FILE_DIRECTORY_INFO;   /* level 257 FF response data area */
 
@@ -1707,7 +1707,7 @@
 struct fea {
 	unsigned char EA_flags;
 	__u8 name_len;
-	__u16 value_len;
+	__le16 value_len;
 	char name[1];
 	/* optionally followed by value */
 };
@@ -1715,7 +1715,7 @@
 #define FEA_NEEDEA         0x80	/* need EA bit */
 
 struct fealist {
-	__u32 list_len;
+	__le32 list_len;
 	struct fea list[1];
 };
 
@@ -1726,6 +1726,7 @@
 	void (*free) (struct data_blob * data_blob);
 };
 
+
 #ifdef CONFIG_CIFS_POSIX
 /* 
 	For better POSIX semantics from Linux client, (even better
@@ -1774,9 +1775,9 @@
 	
 	COPY (note support for copy across directories) - FUTURE, OPTIONAL
 	setting/getting OS/2 EAs - FUTURE (BB can this handle
-	        setting Linux xattrs perfectly)         - OPTIONAL
-    dnotify                                         - FUTURE, OPTIONAL
-    quota                                           - FUTURE, OPTIONAL
+	setting Linux xattrs perfectly)         - OPTIONAL
+	dnotify                                 - FUTURE, OPTIONAL
+	quota                                   - FUTURE, OPTIONAL
 			
 	Note that various requests implemented for NT interop such as 
 		NT_TRANSACT (IOCTL) QueryReparseInfo
@@ -1801,6 +1802,34 @@
 	
 	
  */
+
+/* xsymlink is a symlink format that can be used
+   to save symlink info in a regular file when 
+   mounted to operating systems that do not
+   support the cifs Unix extensions or EAs (for xattr
+   based symlinks).  For such a file to be recognized
+   as containing symlink data: 
+
+   1) file size must be 1067, 
+   2) signature must begin file data,
+   3) length field must be set to ASCII representation
+	of a number which is less than or equal to 1024, 
+   4) md5 must match that of the path data */
+
+struct xsymlink {
+	/* 1067 bytes */
+	char signature[4]; /* XSym */ /* not null terminated */
+	char cr0;         /* \n */
+/* ASCII representation of length (4 bytes decimal) terminated by \n not null */
+	char length[4];
+	char cr1;         /* \n */
+/* md5 of valid subset of path ie path[0] through path[length-1] */
+	__u8 md5[32];    
+	char cr2;        /* \n */
+/* if room left, then end with \n then 0x20s by convention but not required */
+	char path[1024];  
+};
+
 #endif 
 
 #pragma pack()			/* resume default structure packing */
diff -Nru a/fs/cifs/cifsproto.h b/fs/cifs/cifsproto.h
--- a/fs/cifs/cifsproto.h	2004-10-18 14:55:54 -07:00
+++ b/fs/cifs/cifsproto.h	2004-10-18 14:55:54 -07:00
@@ -37,7 +37,7 @@
 extern unsigned int _GetXid(void);
 extern void _FreeXid(unsigned int);
 #define GetXid() (int)_GetXid(); cFYI(1,("CIFS VFS: in %s as Xid: %d with uid: %d",__FUNCTION__, xid,current->fsuid));
-#define FreeXid(curr_xid) {_FreeXid(curr_xid); cFYI(1,("CIFS VFS: leaving %s (xid = %d) rc = %d",__FUNCTION__,curr_xid,rc));}
+#define FreeXid(curr_xid) {_FreeXid(curr_xid); cFYI(1,("CIFS VFS: leaving %s (xid = %d) rc = %d",__FUNCTION__,curr_xid,(int)rc));}
 extern char *build_path_from_dentry(struct dentry *);
 extern char *build_wildcard_path_from_dentry(struct dentry *direntry);
 extern void renew_parental_timestamps(struct dentry *direntry);
diff -Nru a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c
--- a/fs/cifs/cifssmb.c	2004-10-18 14:56:18 -07:00
+++ b/fs/cifs/cifssmb.c	2004-10-18 14:56:18 -07:00
@@ -183,6 +183,7 @@
 	int rc = 0;
 	int bytes_returned;
 	struct TCP_Server_Info * server;
+	u16 count;
 
 	if(ses->server)
 		server = ses->server;
@@ -199,12 +200,12 @@
 	if (extended_security)
 		pSMB->hdr.Flags2 |= SMBFLG2_EXT_SEC;
 
-	pSMB->ByteCount = strlen(protocols[0].name) + 1;
+	count = strlen(protocols[0].name) + 1;
 	strncpy(pSMB->DialectsArray, protocols[0].name, 30);	
     /* null guaranteed to be at end of source and target buffers anyway */
 
-	pSMB->hdr.smb_buf_length += pSMB->ByteCount;
-	pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
+	pSMB->hdr.smb_buf_length += count;
+	pSMB->ByteCount = cpu_to_le16(count);
 
 	rc = SendReceive(xid, ses, (struct smb_hdr *) pSMB,
 			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
@@ -234,10 +235,12 @@
 
 		/* BB might be helpful to save off the domain of server here */
 
-		if (pSMBr->hdr.Flags2 & SMBFLG2_EXT_SEC) {
-			if (pSMBr->ByteCount < 16)
+		if ((pSMBr->hdr.Flags2 & SMBFLG2_EXT_SEC) && 
+			(server->capabilities & CAP_EXTENDED_SECURITY)) {
+			count = pSMBr->ByteCount;
+			if (count < 16)
 				rc = -EIO;
-			else if (pSMBr->ByteCount == 16) {
+			else if (count == 16) {
 				server->secType = RawNTLMSSP;
 				if (server->socketUseCount.counter > 1) {
 					if (memcmp
@@ -260,8 +263,8 @@
 				rc = decode_negTokenInit(pSMBr->u.
 							 extended_response.
 							 SecurityBlob,
-							 pSMBr->ByteCount -
-							 16, &server->secType);
+							 count - 16,
+							 &server->secType);
 			}
 		} else
 			server->capabilities &= ~CAP_EXTENDED_SECURITY;
@@ -365,9 +368,12 @@
 
 	rc = smb_init(SMB_COM_LOGOFF_ANDX, 2, NULL /* no tcon anymore */,
 		 (void **) &pSMB, (void **) &smb_buffer_response);
-
-	if(ses->server->secMode & (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
-		pSMB->hdr.Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
+	
+	if(ses->server) {
+		if(ses->server->secMode & 
+		   (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
+			pSMB->hdr.Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
+	}
 
 	if (rc) {
 		up(&ses->sesSem);
@@ -430,10 +436,9 @@
 	}
 	pSMB->SearchAttributes =
 	    cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM);
-	pSMB->ByteCount = name_len + 1;
 	pSMB->BufferFormat = 0x04;
-	pSMB->hdr.smb_buf_length += pSMB->ByteCount;
-	pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
+	pSMB->hdr.smb_buf_length += name_len + 1;
+	pSMB->ByteCount = cpu_to_le16(name_len + 1);
 	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
 			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
 	if (rc) {
@@ -482,10 +487,9 @@
 		strncpy(pSMB->DirName, dirName, name_len);
 	}
 
-	pSMB->ByteCount = name_len + 1;
 	pSMB->BufferFormat = 0x04;
-	pSMB->hdr.smb_buf_length += pSMB->ByteCount;
-	pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
+	pSMB->hdr.smb_buf_length += name_len + 1;
+	pSMB->ByteCount = cpu_to_le16(name_len + 1);
 	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
 			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
 	if (rc) {
@@ -533,10 +537,9 @@
 		strncpy(pSMB->DirName, name, name_len);
 	}
 
-	pSMB->ByteCount = name_len + 1 /* for buf format */ ;
 	pSMB->BufferFormat = 0x04;
-	pSMB->hdr.smb_buf_length += pSMB->ByteCount;
-	pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
+	pSMB->hdr.smb_buf_length += name_len + 1;
+	pSMB->ByteCount = cpu_to_le16(name_len + 1);
 	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
 			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
 	if (rc) {
@@ -566,6 +569,7 @@
 	OPEN_RSP *pSMBr = NULL;
 	int bytes_returned;
 	int name_len;
+	__u16 count;
 
 openRetry:
 	rc = smb_init(SMB_COM_NT_CREATE_ANDX, 24, tcon, (void **) &pSMB,
@@ -576,7 +580,7 @@
 	pSMB->AndXCommand = 0xFF;	/* none */
 
 	if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
-		pSMB->ByteCount = 1;	/* account for one byte pad to word boundary */
+		count = 1;	/* account for one byte pad to word boundary */
 		name_len =
 		    cifs_strtoUCS((wchar_t *) (pSMB->fileName + 1),
 				  fileName, 530
@@ -586,7 +590,7 @@
 		name_len *= 2;
 		pSMB->NameLength = cpu_to_le16(name_len);
 	} else {		/* BB improve the check for buffer overruns BB */
-		pSMB->ByteCount = 0;	/* no pad */
+		count = 0;	/* no pad */
 		name_len = strnlen(fileName, 530);
 		name_len++;	/* trailing null */
 		pSMB->NameLength = cpu_to_le16(name_len);
@@ -599,30 +603,29 @@
 	}
 	pSMB->DesiredAccess = cpu_to_le32(access_flags);
 	pSMB->AllocationSize = 0;
-	pSMB->FileAttributes = ATTR_NORMAL;
+	pSMB->FileAttributes = cpu_to_le32(ATTR_NORMAL);
 	/* XP does not handle ATTR_POSIX_SEMANTICS */
 	/* but it helps speed up case sensitive checks for other
 	servers such as Samba */
 	if (tcon->ses->capabilities & CAP_UNIX)
-		pSMB->FileAttributes |= ATTR_POSIX_SEMANTICS;
+		pSMB->FileAttributes |= cpu_to_le32(ATTR_POSIX_SEMANTICS);
 
 	/* if ((omode & S_IWUGO) == 0)
-		pSMB->FileAttributes |= ATTR_READONLY;*/
+		pSMB->FileAttributes |= cpu_to_le32(ATTR_READONLY);*/
 	/*  Above line causes problems due to vfs splitting create into two
 		pieces - need to set mode after file created not while it is
 		being created */
-	pSMB->FileAttributes = cpu_to_le32(pSMB->FileAttributes);
 	pSMB->ShareAccess = cpu_to_le32(FILE_SHARE_ALL);
 	pSMB->CreateDisposition = cpu_to_le32(openDisposition);
 	pSMB->CreateOptions = cpu_to_le32(create_options);
 	pSMB->ImpersonationLevel = cpu_to_le32(SECURITY_IMPERSONATION);	/* BB ??*/
 	pSMB->SecurityFlags =
-	    cpu_to_le32(SECURITY_CONTEXT_TRACKING | SECURITY_EFFECTIVE_ONLY);
+	    SECURITY_CONTEXT_TRACKING | SECURITY_EFFECTIVE_ONLY;
 
-	pSMB->ByteCount += name_len;
-	pSMB->hdr.smb_buf_length += pSMB->ByteCount;
+	count += name_len;
+	pSMB->hdr.smb_buf_length += count;
 
-	pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
+	pSMB->ByteCount = cpu_to_le16(count);
 	/* long_op set to 1 to allow for oplock break timeouts */
 	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
 			 (struct smb_hdr *) pSMBr, &bytes_returned, 1);
@@ -694,24 +697,24 @@
 	if (rc) {
 		cERROR(1, ("Send error in read = %d", rc));
 	} else {
-		pSMBr->DataLength = le16_to_cpu(pSMBr->DataLength);
-		*nbytes = pSMBr->DataLength;
+		__u16 data_length = le16_to_cpu(pSMBr->DataLength);
+		*nbytes = data_length;
 		/*check that DataLength would not go beyond end of SMB */
-		if ((pSMBr->DataLength > CIFS_MAX_MSGSIZE) 
-				|| (pSMBr->DataLength > count)) {
-			cFYI(1,("bad length %d for count %d",pSMBr->DataLength,count));
+		if ((data_length > CIFS_MAX_MSGSIZE) 
+				|| (data_length > count)) {
+			cFYI(1,("bad length %d for count %d",data_length,count));
 			rc = -EIO;
 			*nbytes = 0;
 		} else {
 			pReadData =
 			    (char *) (&pSMBr->hdr.Protocol) +
 			    le16_to_cpu(pSMBr->DataOffset);
-/*			if(rc = copy_to_user(buf, pReadData, pSMBr->DataLength)) {
+/*			if(rc = copy_to_user(buf, pReadData, data_length)) {
 				cERROR(1,("Faulting on read rc = %d",rc));
 				rc = -EFAULT;
 			}*/ /* can not use copy_to_user when using page cache*/
 			if(*buf)
-			    memcpy(*buf,pReadData,pSMBr->DataLength);
+			    memcpy(*buf,pReadData,data_length);
 		}
 	}
 	if (pSMB) {
@@ -736,6 +739,8 @@
 	WRITE_REQ *pSMB = NULL;
 	WRITE_RSP *pSMBr = NULL;
 	int bytes_returned;
+	unsigned bytes_sent;
+	__u16 byte_count;
 
 	rc = smb_init(SMB_COM_WRITE_ANDX, 14, tcon, (void **) &pSMB,
 		      (void **) &pSMBr);
@@ -750,21 +755,20 @@
 	pSMB->OffsetLow = cpu_to_le32(offset & 0xFFFFFFFF);
 	pSMB->OffsetHigh = cpu_to_le32(offset >> 32);
 	pSMB->Remaining = 0;
-	if (count > ((tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE) & 0xFFFFFF00))
-		pSMB->DataLengthLow =
-		    (tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE) & 0xFFFFFF00;
-	else
-		pSMB->DataLengthLow = count;
+	bytes_sent = (tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE) & ~0xFF;
+	if (bytes_sent > count)
+		bytes_sent = count;
 	pSMB->DataLengthHigh = 0;
 	pSMB->DataOffset =
 	    cpu_to_le16(offsetof(struct smb_com_write_req,Data) - 4);
 
-	memcpy(pSMB->Data,buf,pSMB->DataLengthLow);
+	memcpy(pSMB->Data,buf,bytes_sent);
 
-	pSMB->ByteCount += pSMB->DataLengthLow + 1 /* pad */ ;
-	pSMB->DataLengthLow = cpu_to_le16(pSMB->DataLengthLow);
-	pSMB->hdr.smb_buf_length += pSMB->ByteCount;
-	pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
+	byte_count = bytes_sent + 1 /* pad */ ;
+	pSMB->DataLengthLow = cpu_to_le16(bytes_sent);
+	pSMB->DataLengthHigh = 0;
+	pSMB->hdr.smb_buf_length += byte_count;
+	pSMB->ByteCount = cpu_to_le16(byte_count);
 
 	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
 			 (struct smb_hdr *) pSMBr, &bytes_returned, long_op);
@@ -794,7 +798,7 @@
 	LOCK_RSP *pSMBr = NULL;
 	int bytes_returned;
 	int timeout = 0;
-	__u64 temp;
+	__u16 count;
 
 	cFYI(1, ("In CIFSSMBLock - timeout %d numLock %d",waitFlag,numLock));
 	rc = smb_init(SMB_COM_LOCKING_ANDX, 8, tcon, (void **) &pSMB,
@@ -807,33 +811,31 @@
 		pSMB->Timeout = 0;
 	} else if (waitFlag == TRUE) {
 		timeout = 3;  /* blocking operation, no timeout */
-		pSMB->Timeout = -1; /* blocking - do not time out */
+		pSMB->Timeout = cpu_to_le32(-1);/* blocking - do not time out */
 	} else {
 		pSMB->Timeout = 0;
 	}
 
-	pSMB->NumberOfLocks = cpu_to_le32(numLock);
-	pSMB->NumberOfUnlocks = cpu_to_le32(numUnlock);
+	pSMB->NumberOfLocks = cpu_to_le16(numLock);
+	pSMB->NumberOfUnlocks = cpu_to_le16(numUnlock);
 	pSMB->LockType = lockType;
 	pSMB->AndXCommand = 0xFF;	/* none */
 	pSMB->Fid = smb_file_id; /* netfid stays le */
 
-	if(numLock != 0) {
+	if((numLock != 0) || (numUnlock != 0)) {
 		pSMB->Locks[0].Pid = cpu_to_le16(current->tgid);
 		/* BB where to store pid high? */
-		temp = cpu_to_le64(len);
-		pSMB->Locks[0].LengthLow = (__u32)(temp & 0xFFFFFFFF);
-		pSMB->Locks[0].LengthHigh =  (__u32)(temp>>32);
-		temp = cpu_to_le64(offset);
-		pSMB->Locks[0].OffsetLow = (__u32)(temp & 0xFFFFFFFF);
-		pSMB->Locks[0].OffsetHigh = (__u32)(temp>>32);
-		pSMB->ByteCount = sizeof (LOCKING_ANDX_RANGE);
+		pSMB->Locks[0].LengthLow = cpu_to_le32((u32)len);
+		pSMB->Locks[0].LengthHigh = cpu_to_le32((u32)(len>>32));
+		pSMB->Locks[0].OffsetLow = cpu_to_le32((u32)offset);
+		pSMB->Locks[0].OffsetHigh = cpu_to_le32((u32)(offset>>32));
+		count = sizeof(LOCKING_ANDX_RANGE);
 	} else {
 		/* oplock break */
-		pSMB->ByteCount = 0;
+		count = 0;
 	}
-	pSMB->hdr.smb_buf_length += pSMB->ByteCount;
-	pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
+	pSMB->hdr.smb_buf_length += count;
+	pSMB->ByteCount = cpu_to_le16(count);
 
 	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
 			 (struct smb_hdr *) pSMBr, &bytes_returned, timeout);
@@ -897,6 +899,7 @@
 	RENAME_RSP *pSMBr = NULL;
 	int bytes_returned;
 	int name_len, name_len2;
+	__u16 count;
 
 	cFYI(1, ("In CIFSSMBRename"));
 renameRetry:
@@ -938,9 +941,9 @@
 		name_len2++;	/* signature byte */
 	}
 
-	pSMB->ByteCount = 1 /* 1st signature byte */  + name_len + name_len2;
-	pSMB->hdr.smb_buf_length += pSMB->ByteCount;
-	pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
+	count = 1 /* 1st signature byte */  + name_len + name_len2;
+	pSMB->hdr.smb_buf_length += count;
+	pSMB->ByteCount = cpu_to_le16(count);
 
 	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
 			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
@@ -974,6 +977,7 @@
 	int rc = 0;
 	int bytes_returned = 0;
 	int len_of_str;
+	__u16 params, param_offset, offset, count, byte_count;
 
 	cFYI(1, ("Rename to File by handle"));
 	rc = smb_init(SMB_COM_TRANSACTION2, 15, pTcon, (void **) &pSMB,
@@ -981,28 +985,27 @@
 	if (rc)
 		return rc;
 
-	pSMB->ParameterCount = 6;
+	params = 6;
 	pSMB->MaxSetupCount = 0;
 	pSMB->Reserved = 0;
 	pSMB->Flags = 0;
 	pSMB->Timeout = 0;
 	pSMB->Reserved2 = 0;
-	pSMB->ParameterOffset = offsetof(struct smb_com_transaction2_sfi_req,
-				Fid) - 4;
-	pSMB->DataOffset = pSMB->ParameterOffset + pSMB->ParameterCount;
+	param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
+	offset = param_offset + params;
 
-	data_offset = (char *) (&pSMB->hdr.Protocol) + pSMB->DataOffset;
+	data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
 	rename_info = (struct set_file_rename *) data_offset;
 	pSMB->MaxParameterCount = cpu_to_le16(2);
 	pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB PDU from sess */
 	pSMB->SetupCount = 1;
 	pSMB->Reserved3 = 0;
 	pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
-	pSMB->ByteCount = 3 /* pad */  + pSMB->ParameterCount;
-	pSMB->ParameterCount = cpu_to_le16(pSMB->ParameterCount);
+	byte_count = 3 /* pad */  + params;
+	pSMB->ParameterCount = cpu_to_le16(params);
 	pSMB->TotalParameterCount = pSMB->ParameterCount;
-	pSMB->ParameterOffset = cpu_to_le16(pSMB->ParameterOffset);
-	pSMB->DataOffset = cpu_to_le16(pSMB->DataOffset);
+	pSMB->ParameterOffset = cpu_to_le16(param_offset);
+	pSMB->DataOffset = cpu_to_le16(offset);
 	/* construct random name ".cifs_tmp<inodenum><mid>" */
 	rename_info->overwrite = cpu_to_le32(1);
 	rename_info->root_fid  = 0;
@@ -1014,16 +1017,16 @@
 		len_of_str = cifs_strtoUCS((wchar_t *) rename_info->target_name, target_name, 530, nls_codepage);
 	}
 	rename_info->target_name_len = cpu_to_le32(2 * len_of_str);
-	pSMB->DataCount = 12 /* sizeof(struct set_file_rename) */ + (2 * len_of_str) + 2;
-	pSMB->ByteCount += pSMB->DataCount;
-	pSMB->DataCount = cpu_to_le16(pSMB->DataCount);
+	count = 12 /* sizeof(struct set_file_rename) */ + (2 * len_of_str) + 2;
+	byte_count += count;
+	pSMB->DataCount = cpu_to_le16(count);
 	pSMB->TotalDataCount = pSMB->DataCount;
 	pSMB->Fid = netfid;
 	pSMB->InformationLevel =
 		cpu_to_le16(SMB_SET_FILE_RENAME_INFORMATION);
 	pSMB->Reserved4 = 0;
-	pSMB->hdr.smb_buf_length += pSMB->ByteCount;
-	pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
+	pSMB->hdr.smb_buf_length += byte_count;
+	pSMB->ByteCount = cpu_to_le16(byte_count);
 	rc = SendReceive(xid, pTcon->ses, (struct smb_hdr *) pSMB,
                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
 	if (rc) {
@@ -1053,6 +1056,7 @@
 	COPY_RSP *pSMBr = NULL;
 	int bytes_returned;
 	int name_len, name_len2;
+	__u16 count;
 
 	cFYI(1, ("In CIFSSMBCopy"));
 copyRetry:
@@ -1064,9 +1068,7 @@
 	pSMB->BufferFormat = 0x04;
 	pSMB->Tid2 = target_tid;
 
-	if(flags & COPY_TREE)
-		pSMB->Flags |= COPY_TREE;
-	pSMB->Flags = cpu_to_le16(pSMB->Flags);
+	pSMB->Flags = cpu_to_le16(flags & COPY_TREE);
 
 	if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
 		name_len = cifs_strtoUCS((wchar_t *) pSMB->OldFileName, 
@@ -1095,15 +1097,15 @@
 		name_len2++;    /* signature byte */
 	}
 
-	pSMB->ByteCount = 1 /* 1st signature byte */  + name_len + name_len2;
-	pSMB->hdr.smb_buf_length += pSMB->ByteCount;
-	pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
+	count = 1 /* 1st signature byte */  + name_len + name_len2;
+	pSMB->hdr.smb_buf_length += count;
+	pSMB->ByteCount = cpu_to_le16(count);
 
 	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
 		(struct smb_hdr *) pSMBr, &bytes_returned, 0);
 	if (rc) {
 		cFYI(1, ("Send error in copy = %d with %d files copied",
-			rc, pSMBr->CopyCount));
+			rc, le16_to_cpu(pSMBr->CopyCount)));
 	}
 	if (pSMB)
 		cifs_buf_release(pSMB);
@@ -1126,6 +1128,7 @@
 	int name_len_target;
 	int rc = 0;
 	int bytes_returned = 0;
+	__u16 params, param_offset, offset, byte_count;
 
 	cFYI(1, ("In Symlink Unix style"));
 createSymLinkRetry:
@@ -1147,17 +1150,17 @@
 		name_len++;	/* trailing null */
 		strncpy(pSMB->FileName, fromName, name_len);
 	}
-	pSMB->ParameterCount = 6 + name_len;
+	params = 6 + name_len;
 	pSMB->MaxSetupCount = 0;
 	pSMB->Reserved = 0;
 	pSMB->Flags = 0;
 	pSMB->Timeout = 0;
 	pSMB->Reserved2 = 0;
-	pSMB->ParameterOffset = offsetof(struct smb_com_transaction2_spi_req,
+	param_offset = offsetof(struct smb_com_transaction2_spi_req,
                                      InformationLevel) - 4;
-	pSMB->DataOffset = pSMB->ParameterOffset + pSMB->ParameterCount;
+	offset = param_offset + params;
 
-	data_offset = (char *) (&pSMB->hdr.Protocol) + pSMB->DataOffset;
+	data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
 	if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
 		name_len_target =
 		    cifs_strtoUCS((wchar_t *) data_offset, toName, 530
@@ -1171,24 +1174,23 @@
 		strncpy(data_offset, toName, name_len_target);
 	}
 
-	pSMB->DataCount = name_len_target;
 	pSMB->MaxParameterCount = cpu_to_le16(2);
 	/* BB find exact max on data count below from sess */
 	pSMB->MaxDataCount = cpu_to_le16(1000);
 	pSMB->SetupCount = 1;
 	pSMB->Reserved3 = 0;
 	pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
-	pSMB->ByteCount = 3 /* pad */  + pSMB->ParameterCount + pSMB->DataCount;
-	pSMB->DataCount = cpu_to_le16(pSMB->DataCount);
-	pSMB->ParameterCount = cpu_to_le16(pSMB->ParameterCount);
+	byte_count = 3 /* pad */  + params + name_len_target;
+	pSMB->DataCount = cpu_to_le16(name_len_target);
+	pSMB->ParameterCount = cpu_to_le16(params);
 	pSMB->TotalDataCount = pSMB->DataCount;
 	pSMB->TotalParameterCount = pSMB->ParameterCount;
-	pSMB->ParameterOffset = cpu_to_le16(pSMB->ParameterOffset);
-	pSMB->DataOffset = cpu_to_le16(pSMB->DataOffset);
+	pSMB->ParameterOffset = cpu_to_le16(param_offset);
+	pSMB->DataOffset = cpu_to_le16(offset);
 	pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_LINK);
 	pSMB->Reserved4 = 0;
-	pSMB->hdr.smb_buf_length += pSMB->ByteCount;
-	pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
+	pSMB->hdr.smb_buf_length += byte_count;
+	pSMB->ByteCount = cpu_to_le16(byte_count);
 	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
 			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
 	if (rc) {
@@ -1218,6 +1220,7 @@
 	int name_len_target;
 	int rc = 0;
 	int bytes_returned = 0;
+	__u16 params, param_offset, offset, byte_count;
 
 	cFYI(1, ("In Create Hard link Unix style"));
 createHardLinkRetry:
@@ -1238,17 +1241,17 @@
 		name_len++;	/* trailing null */
 		strncpy(pSMB->FileName, toName, name_len);
 	}
-	pSMB->ParameterCount = 6 + name_len;
+	params = 6 + name_len;
 	pSMB->MaxSetupCount = 0;
 	pSMB->Reserved = 0;
 	pSMB->Flags = 0;
 	pSMB->Timeout = 0;
 	pSMB->Reserved2 = 0;
-	pSMB->ParameterOffset = offsetof(struct smb_com_transaction2_spi_req,
+	param_offset = offsetof(struct smb_com_transaction2_spi_req,
                                      InformationLevel) - 4;
-	pSMB->DataOffset = pSMB->ParameterOffset + pSMB->ParameterCount;
+	offset = param_offset + params;
 
-	data_offset = (char *) (&pSMB->hdr.Protocol) + pSMB->DataOffset;
+	data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
 	if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
 		name_len_target =
 		    cifs_strtoUCS((wchar_t *) data_offset, fromName, 530
@@ -1262,24 +1265,23 @@
 		strncpy(data_offset, fromName, name_len_target);
 	}
 
-	pSMB->DataCount = name_len_target;
 	pSMB->MaxParameterCount = cpu_to_le16(2);
 	/* BB find exact max on data count below from sess*/
 	pSMB->MaxDataCount = cpu_to_le16(1000);
 	pSMB->SetupCount = 1;
 	pSMB->Reserved3 = 0;
 	pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
-	pSMB->ByteCount = 3 /* pad */  + pSMB->ParameterCount + pSMB->DataCount;
-	pSMB->ParameterCount = cpu_to_le16(pSMB->ParameterCount);
+	byte_count = 3 /* pad */  + params + name_len_target;
+	pSMB->ParameterCount = cpu_to_le16(params);
 	pSMB->TotalParameterCount = pSMB->ParameterCount;
-	pSMB->DataCount = cpu_to_le16(pSMB->DataCount);
+	pSMB->DataCount = cpu_to_le16(name_len_target);
 	pSMB->TotalDataCount = pSMB->DataCount;
-	pSMB->ParameterOffset = cpu_to_le16(pSMB->ParameterOffset);
-	pSMB->DataOffset = cpu_to_le16(pSMB->DataOffset);
+	pSMB->ParameterOffset = cpu_to_le16(param_offset);
+	pSMB->DataOffset = cpu_to_le16(offset);
 	pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_HLINK);
 	pSMB->Reserved4 = 0;
-	pSMB->hdr.smb_buf_length += pSMB->ByteCount;
-	pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
+	pSMB->hdr.smb_buf_length += byte_count;
+	pSMB->ByteCount = cpu_to_le16(byte_count);
 	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
 			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
 	if (rc) {
@@ -1304,6 +1306,7 @@
 	RENAME_RSP *pSMBr = NULL;
 	int bytes_returned;
 	int name_len, name_len2;
+	__u16 count;
 
 	cFYI(1, ("In CIFSCreateHardLink"));
 winCreateHardLinkRetry:
@@ -1348,9 +1351,9 @@
 		name_len2++;	/* signature byte */
 	}
 
-	pSMB->ByteCount = 1 /* string type byte */  + name_len + name_len2;
-	pSMB->hdr.smb_buf_length += pSMB->ByteCount;
-	pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
+	count = 1 /* string type byte */  + name_len + name_len2;
+	pSMB->hdr.smb_buf_length += count;
+	pSMB->ByteCount = cpu_to_le16(count);
 
 	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
 			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
@@ -1377,6 +1380,7 @@
 	int rc = 0;
 	int bytes_returned;
 	int name_len;
+	__u16 params, byte_count;
 
 	cFYI(1, ("In QPathSymLinkInfo (Unix) for path %s", searchName));
 
@@ -1399,8 +1403,7 @@
 		strncpy(pSMB->FileName, searchName, name_len);
 	}
 
-	pSMB->TotalParameterCount =
-	    2 /* level */  + 4 /* rsrvd */  + name_len /* incl null */ ;
+	params = 2 /* level */  + 4 /* rsrvd */  + name_len /* incl null */ ;
 	pSMB->TotalDataCount = 0;
 	pSMB->MaxParameterCount = cpu_to_le16(2);
 	/* BB find exact max data count below from sess structure BB */
@@ -1417,38 +1420,38 @@
 	pSMB->SetupCount = 1;
 	pSMB->Reserved3 = 0;
 	pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
-	pSMB->ByteCount = pSMB->TotalParameterCount + 1 /* pad */ ;
-	pSMB->TotalParameterCount = cpu_to_le16(pSMB->TotalParameterCount);
+	byte_count = params + 1 /* pad */ ;
+	pSMB->TotalParameterCount = cpu_to_le16(params);
 	pSMB->ParameterCount = pSMB->TotalParameterCount;
 	pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_UNIX_LINK);
 	pSMB->Reserved4 = 0;
-	pSMB->hdr.smb_buf_length += pSMB->ByteCount;
-	pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
+	pSMB->hdr.smb_buf_length += byte_count;
+	pSMB->ByteCount = cpu_to_le16(byte_count);
 
 	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
 			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
 	if (rc) {
 		cFYI(1, ("Send error in QuerySymLinkInfo = %d", rc));
 	} else {		/* decode response */
-		pSMBr->DataOffset = le16_to_cpu(pSMBr->DataOffset);
-		pSMBr->DataCount = le16_to_cpu(pSMBr->DataCount);
-		if ((pSMBr->ByteCount < 2) || (pSMBr->DataOffset > 512))
+		__u16 data_offset = le16_to_cpu(pSMBr->DataOffset);
+		__u16 count = le16_to_cpu(pSMBr->DataCount);
+		if ((pSMBr->ByteCount < 2) || (data_offset > 512))
 		/* BB also check enough total bytes returned */
 			rc = -EIO;	/* bad smb */
 		else {
 			if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE) {
 				name_len = UniStrnlen((wchar_t *) ((char *)
-					&pSMBr->hdr.Protocol +pSMBr->DataOffset),
-					min_t(const int, buflen,pSMBr->DataCount) / 2);
+					&pSMBr->hdr.Protocol +data_offset),
+					min_t(const int, buflen,count) / 2);
 				cifs_strfromUCS_le(symlinkinfo,
 					(wchar_t *) ((char *)&pSMBr->hdr.Protocol +
-						pSMBr->DataOffset),
+						data_offset),
 					name_len, nls_codepage);
 			} else {
 				strncpy(symlinkinfo,
 					(char *) &pSMBr->hdr.Protocol + 
-						pSMBr->DataOffset,
-					min_t(const int, buflen, pSMBr->DataCount));
+						data_offset,
+					min_t(const int, buflen, count));
 			}
 			symlinkinfo[buflen] = 0;
 	/* just in case so calling code does not go off the end of buffer */
@@ -1505,16 +1508,16 @@
 	if (rc) {
 		cFYI(1, ("Send error in QueryReparseLinkInfo = %d", rc));
 	} else {		/* decode response */
-		pSMBr->DataOffset = le16_to_cpu(pSMBr->DataOffset);
-		pSMBr->DataCount = le16_to_cpu(pSMBr->DataCount);
-		if ((pSMBr->ByteCount < 2) || (pSMBr->DataOffset > 512))
+		__u32 data_offset = le32_to_cpu(pSMBr->DataOffset);
+		__u32 data_count = le32_to_cpu(pSMBr->DataCount);
+		if ((pSMBr->ByteCount < 2) || (data_offset > 512))
 		/* BB also check enough total bytes returned */
 			rc = -EIO;	/* bad smb */
 		else {
-			if(pSMBr->DataCount && (pSMBr->DataCount < 2048)) {
+			if(data_count && (data_count < 2048)) {
 		/* could also validate reparse tag && better check name length */
 				struct reparse_data * reparse_buf = (struct reparse_data *)
-					((char *)&pSMBr->hdr.Protocol + pSMBr->DataOffset);
+					((char *)&pSMBr->hdr.Protocol + data_offset);
 				if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE) {
 					name_len = UniStrnlen((wchar_t *)
 							(reparse_buf->LinkNamesBuf + 
@@ -1559,6 +1562,7 @@
 	int rc = 0;
 	int bytes_returned;
 	int name_len;
+	__u16 params, byte_count;
 
 	cFYI(1, ("In QPathInfo path %s", searchName));
 QPathInfoRetry:
@@ -1580,8 +1584,7 @@
 		strncpy(pSMB->FileName, searchName, name_len);
 	}
 
-	pSMB->TotalParameterCount = 2 /* level */  + 4 /* reserved */  +
-	    name_len /* includes null */ ;
+	params = 2 /* level */ + 4 /* reserved */ + name_len /* includes NUL */ ;
 	pSMB->TotalDataCount = 0;
 	pSMB->MaxParameterCount = cpu_to_le16(2);
 	pSMB->MaxDataCount = cpu_to_le16(4000);	/* BB find exact max SMB PDU from sess structure BB */
@@ -1597,29 +1600,29 @@
 	pSMB->SetupCount = 1;
 	pSMB->Reserved3 = 0;
 	pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
-	pSMB->ByteCount = pSMB->TotalParameterCount + 1 /* pad */ ;
-	pSMB->TotalParameterCount = cpu_to_le16(pSMB->TotalParameterCount);
+	byte_count = params + 1 /* pad */ ;
+	pSMB->TotalParameterCount = cpu_to_le16(params);
 	pSMB->ParameterCount = pSMB->TotalParameterCount;
 	pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_ALL_INFO);
 	pSMB->Reserved4 = 0;
-	pSMB->hdr.smb_buf_length += pSMB->ByteCount;
-	pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
+	pSMB->hdr.smb_buf_length += byte_count;
+	pSMB->ByteCount = cpu_to_le16(byte_count);
 
 	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
 			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
 	if (rc) {
 		cFYI(1, ("Send error in QPathInfo = %d", rc));
 	} else {		/* decode response */
-		pSMBr->DataOffset = le16_to_cpu(pSMBr->DataOffset);
+		__u16 data_offset = le16_to_cpu(pSMBr->DataOffset);
 		/* BB also check enough total bytes returned */
 		/* BB we need to improve the validity checking
 		of these trans2 responses */
-		if ((pSMBr->ByteCount < 40) || (pSMBr->DataOffset > 512)) 
+		if ((pSMBr->ByteCount < 40) || (data_offset > 512)) 
 			rc = -EIO;	/* bad smb */
 		else if (pFindData){
 			memcpy((char *) pFindData,
 			       (char *) &pSMBr->hdr.Protocol +
-			       pSMBr->DataOffset, sizeof (FILE_ALL_INFO));
+			       data_offset, sizeof (FILE_ALL_INFO));
 		} else
 		    rc = -ENOMEM;
 	}
@@ -1643,6 +1646,7 @@
 	int rc = 0;
 	int bytes_returned = 0;
 	int name_len;
+	__u16 params, byte_count;
 
 	cFYI(1, ("In QPathInfo (Unix) the path %s", searchName));
 UnixQPathInfoRetry:
@@ -1664,8 +1668,7 @@
 		strncpy(pSMB->FileName, searchName, name_len);
 	}
 
-	pSMB->TotalParameterCount = 2 /* level */  + 4 /* reserved */  +
-	    name_len /* includes null */ ;
+	params = 2 /* level */ + 4 /* reserved */ + name_len /* includes NUL */ ;
 	pSMB->TotalDataCount = 0;
 	pSMB->MaxParameterCount = cpu_to_le16(2);
 	/* BB find exact max SMB PDU from sess structure BB */
@@ -1682,31 +1685,31 @@
 	pSMB->SetupCount = 1;
 	pSMB->Reserved3 = 0;
 	pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
-	pSMB->ByteCount = pSMB->TotalParameterCount + 1 /* pad */ ;
-	pSMB->TotalParameterCount = cpu_to_le16(pSMB->TotalParameterCount);
+	byte_count = params + 1 /* pad */ ;
+	pSMB->TotalParameterCount = cpu_to_le16(params);
 	pSMB->ParameterCount = pSMB->TotalParameterCount;
 	pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_UNIX_BASIC);
 	pSMB->Reserved4 = 0;
-	pSMB->hdr.smb_buf_length += pSMB->ByteCount;
-	pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
+	pSMB->hdr.smb_buf_length += byte_count;
+	pSMB->ByteCount = cpu_to_le16(byte_count);
 
 	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
 			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
 	if (rc) {
 		cFYI(1, ("Send error in QPathInfo = %d", rc));
 	} else {		/* decode response */
-		pSMBr->DataOffset = le16_to_cpu(pSMBr->DataOffset);
+		__u16 data_offset = le16_to_cpu(pSMBr->DataOffset);
 		/* BB also check if enough total bytes returned */
 		if ((pSMBr->ByteCount < sizeof(FILE_UNIX_BASIC_INFO)) || 
-			(pSMBr->DataOffset > 512) || 
-			(pSMBr->DataOffset < sizeof(struct smb_hdr))) {
+			(data_offset > 512) || 
+			(data_offset < sizeof(struct smb_hdr))) {
 			cFYI(1,("UnixQPathinfo invalid data offset %d bytes returned %d",
-					(int)pSMBr->DataOffset,bytes_returned));
+					(int)data_offset,bytes_returned));
 			rc = -EIO;	/* bad smb */
 		} else {
 			memcpy((char *) pFindData,
 			       (char *) &pSMBr->hdr.Protocol +
-			       pSMBr->DataOffset,
+			       data_offset,
 			       sizeof (FILE_UNIX_BASIC_INFO));
 		}
 	}
@@ -1729,6 +1732,7 @@
 	int rc = 0;
 	int bytes_returned;
 	int name_len;
+	__u16 params, byte_count;
 
 	cFYI(1, ("In FindUnique"));
 findUniqueRetry:
@@ -1750,7 +1754,7 @@
 		strncpy(pSMB->FileName, searchName, name_len);
 	}
 
-	pSMB->TotalParameterCount = 12 + name_len /* includes null */ ;
+	params = 12 + name_len /* includes null */ ;
 	pSMB->TotalDataCount = 0;	/* no EAs */
 	pSMB->MaxParameterCount = cpu_to_le16(2);
 	pSMB->MaxDataCount = cpu_to_le16(4000);	/* BB find exact max SMB PDU from sess structure BB */
@@ -1766,8 +1770,8 @@
 	pSMB->SetupCount = 1;	/* one byte, no need to le convert */
 	pSMB->Reserved3 = 0;
 	pSMB->SubCommand = cpu_to_le16(TRANS2_FIND_FIRST);
-	pSMB->ByteCount = pSMB->TotalParameterCount + 1 /* pad */ ;
-	pSMB->TotalParameterCount = cpu_to_le16(pSMB->TotalDataCount);
+	byte_count = params + 1 /* pad */ ;
+	pSMB->TotalParameterCount = cpu_to_le16(params);
 	pSMB->ParameterCount = pSMB->TotalParameterCount;
 	pSMB->SearchAttributes =
 	    cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM |
@@ -1776,8 +1780,8 @@
 	pSMB->SearchFlags = cpu_to_le16(1);
 	pSMB->InformationLevel = cpu_to_le16(SMB_FIND_FILE_DIRECTORY_INFO);
 	pSMB->SearchStorageType = 0;	/* BB what should we set this to? BB */
-	pSMB->hdr.smb_buf_length += pSMB->ByteCount;
-	pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
+	pSMB->hdr.smb_buf_length += byte_count;
+	pSMB->ByteCount = cpu_to_le16(byte_count);
 
 	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
 			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
@@ -1810,6 +1814,7 @@
 	int rc = 0;
 	int bytes_returned;
 	int name_len;
+	__u16 params, byte_count;
 
 	cFYI(1, ("In FindFirst"));
 findFirstRetry:
@@ -1831,7 +1836,7 @@
 		strncpy(pSMB->FileName, searchName, name_len);
 	}
 
-	pSMB->TotalParameterCount = 12 + name_len /* includes null */ ;
+	params = 12 + name_len /* includes null */ ;
 	pSMB->TotalDataCount = 0;	/* no EAs */
 	pSMB->MaxParameterCount = cpu_to_le16(10);
 	pSMB->MaxDataCount = cpu_to_le16((tcon->ses->server->maxBuf -
@@ -1841,8 +1846,8 @@
 	pSMB->Flags = 0;
 	pSMB->Timeout = 0;
 	pSMB->Reserved2 = 0;
-	pSMB->ByteCount = pSMB->TotalParameterCount + 1 /* pad */ ;
-	pSMB->TotalParameterCount = cpu_to_le16(pSMB->TotalParameterCount);
+	byte_count = params + 1 /* pad */ ;
+	pSMB->TotalParameterCount = cpu_to_le16(params);
 	pSMB->ParameterCount = pSMB->TotalParameterCount;
 	pSMB->ParameterOffset = cpu_to_le16(offsetof(struct 
         smb_com_transaction2_ffirst_req, SearchAttributes) - 4);
@@ -1867,8 +1872,8 @@
 		*pUnixFlag = FALSE;
 	}
 	pSMB->SearchStorageType = 0;	/* BB what should we set this to? It is not clear if it matters BB */
-	pSMB->hdr.smb_buf_length += pSMB->ByteCount;
-	pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
+	pSMB->hdr.smb_buf_length += byte_count;
+	pSMB->ByteCount = cpu_to_le16(byte_count);
 
 	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
 			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
@@ -1885,11 +1890,6 @@
 		       (char *) &pSMBr->hdr.Protocol +
 		       le16_to_cpu(pSMBr->ParameterOffset),
 		       sizeof (T2_FFIRST_RSP_PARMS));
-		/* search handle can stay LE and EAoffset not needed so not converted */
-		findParms->EndofSearch = le16_to_cpu(findParms->EndofSearch);
-		findParms->LastNameOffset =
-		    le16_to_cpu(findParms->LastNameOffset);
-		findParms->SearchCount = le16_to_cpu(findParms->SearchCount);
 		response_data =
 		    (char *) &pSMBr->hdr.Protocol +
 		    le16_to_cpu(pSMBr->DataOffset);
@@ -1916,6 +1916,7 @@
 	char *response_data;
 	int rc = 0;
 	int bytes_returned;
+	__u16 params, byte_count;
 
 	cFYI(1, ("In FindNext"));
 
@@ -1927,7 +1928,8 @@
 	if (rc)
 		return rc;
 
-	pSMB->TotalParameterCount = 14;	/* includes 2 bytes of null string, converted to LE below */
+	params = 14;	/* includes 2 bytes of null string, converted to LE below */
+	byte_count = 0;
 	pSMB->TotalDataCount = 0;	/* no EAs */
 	pSMB->MaxParameterCount = cpu_to_le16(8);
 	pSMB->MaxDataCount =
@@ -1963,15 +1965,15 @@
 	/* BB add check to make sure we do not cross end of smb */
 	if(name_len < CIFS_MAX_MSGSIZE) {
 		memcpy(pSMB->ResumeFileName, resume_file_name, name_len);
-		pSMB->ByteCount += name_len;
+		byte_count += name_len;
 	}
-	pSMB->TotalParameterCount += name_len;
-	pSMB->ByteCount = pSMB->TotalParameterCount + 1 /* pad */ ;
-	pSMB->TotalParameterCount = cpu_to_le16(pSMB->TotalParameterCount);
+	params += name_len;
+	byte_count = params + 1 /* pad */ ;
+	pSMB->TotalParameterCount = cpu_to_le16(params);
 	pSMB->ParameterCount = pSMB->TotalParameterCount;
 	/* BB improve error handling here */
-	pSMB->hdr.smb_buf_length += pSMB->ByteCount;
-	pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
+	pSMB->hdr.smb_buf_length += byte_count;
+	pSMB->ByteCount = cpu_to_le16(byte_count);
 
 	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
 			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
@@ -1991,10 +1993,6 @@
 		       (char *) &pSMBr->hdr.Protocol +
 		       le16_to_cpu(pSMBr->ParameterOffset),
 		       sizeof (T2_FNEXT_RSP_PARMS));
-		findParms->EndofSearch = le16_to_cpu(findParms->EndofSearch);
-		findParms->LastNameOffset =
-		    le16_to_cpu(findParms->LastNameOffset);
-		findParms->SearchCount = le16_to_cpu(findParms->SearchCount);
 		response_data =
 		    (char *) &pSMBr->hdr.Protocol +
 		    le16_to_cpu(pSMBr->DataOffset);
@@ -2060,6 +2058,7 @@
 	int name_len;
 	unsigned int i;
 	char * temp;
+	__u16 params, byte_count;
 	*number_of_UNC_in_array = 0;
 	*targetUNCs = NULL;
 
@@ -2096,7 +2095,7 @@
 		strncpy(pSMB->RequestFileName, searchName, name_len);
 	}
 
-	pSMB->ParameterCount = 2 /* level */  + name_len /*includes null */ ;
+	params = 2 /* level */  + name_len /*includes null */ ;
 	pSMB->TotalDataCount = 0;
 	pSMB->DataCount = 0;
 	pSMB->DataOffset = 0;
@@ -2112,12 +2111,12 @@
 	pSMB->SetupCount = 1;
 	pSMB->Reserved3 = 0;
 	pSMB->SubCommand = cpu_to_le16(TRANS2_GET_DFS_REFERRAL);
-	pSMB->ByteCount = pSMB->ParameterCount + 3 /* pad */ ;
-	pSMB->ParameterCount = cpu_to_le16(pSMB->ParameterCount);
+	byte_count = params + 3 /* pad */ ;
+	pSMB->ParameterCount = cpu_to_le16(params);
 	pSMB->TotalParameterCount = pSMB->ParameterCount;
 	pSMB->MaxReferralLevel = cpu_to_le16(3);
-	pSMB->hdr.smb_buf_length += pSMB->ByteCount;
-	pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
+	pSMB->hdr.smb_buf_length += byte_count;
+	pSMB->ByteCount = cpu_to_le16(byte_count);
 
 	rc = SendReceive(xid, ses, (struct smb_hdr *) pSMB,
 			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
@@ -2125,20 +2124,21 @@
 		cFYI(1, ("Send error in GetDFSRefer = %d", rc));
 	} else {		/* decode response */
 /* BB Add logic to parse referrals here */
-		pSMBr->DataOffset = le16_to_cpu(pSMBr->DataOffset);
-		pSMBr->DataCount = le16_to_cpu(pSMBr->DataCount);
+		__u16 data_offset = le16_to_cpu(pSMBr->DataOffset);
+		__u16 data_count = le16_to_cpu(pSMBr->DataCount);
 		cFYI(1,
 		     ("Decoding GetDFSRefer response.  BCC: %d  Offset %d",
-		      pSMBr->ByteCount, pSMBr->DataOffset));
-		if ((pSMBr->ByteCount < 17) || (pSMBr->DataOffset > 512))	/* BB also check enough total bytes returned */
+		      pSMBr->ByteCount, data_offset));
+		if ((pSMBr->ByteCount < 17) || (data_offset > 512))	/* BB also check enough total bytes returned */
 			rc = -EIO;	/* bad smb */
 		else {
 			referrals = 
 			    (struct dfs_referral_level_3 *) 
 					(8 /* sizeof start of data block */ +
-					pSMBr->DataOffset +
+					data_offset +
 					(char *) &pSMBr->hdr.Protocol); 
-			cFYI(1,("num_referrals: %d dfs flags: 0x%x ... \nfor referral one refer size: 0x%x srv type: 0x%x refer flags: 0x%x ttl: 0x%x",pSMBr->NumberOfReferrals,pSMBr->DFSFlags, referrals->ReferralSize,referrals->ServerType,referrals->ReferralFlags,referrals->TimeToLive));
+			cFYI(1,("num_referrals: %d dfs flags: 0x%x ... \nfor referral one refer size: 0x%x srv type: 0x%x refer flags: 0x%x ttl: 0x%x",
+				le16_to_cpu(pSMBr->NumberOfReferrals),le16_to_cpu(pSMBr->DFSFlags), le16_to_cpu(referrals->ReferralSize),le16_to_cpu(referrals->ServerType),le16_to_cpu(referrals->ReferralFlags),le16_to_cpu(referrals->TimeToLive)));
 			/* BB This field is actually two bytes in from start of
 			   data block so we could do safety check that DataBlock
 			   begins at address of pSMBr->NumberOfReferrals */
@@ -2152,19 +2152,19 @@
 			name_len = 0;
 			for(i=0;i<*number_of_UNC_in_array;i++) {
 				/* make sure that DfsPathOffset not past end */
-				referrals->DfsPathOffset = le16_to_cpu(referrals->DfsPathOffset);
-				if(referrals->DfsPathOffset > pSMBr->DataCount) {
+				__u16 offset = le16_to_cpu(referrals->DfsPathOffset);
+				if (offset > data_count) {
 					/* if invalid referral, stop here and do 
 					not try to copy any more */
 					*number_of_UNC_in_array = i;
 					break;
 				} 
-				temp = ((char *)referrals) + referrals->DfsPathOffset;
+				temp = ((char *)referrals) + offset;
 
 				if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE) {
-					name_len += UniStrnlen((wchar_t *)temp,pSMBr->DataCount);
+					name_len += UniStrnlen((wchar_t *)temp,data_count);
 				} else {
-					name_len += strnlen(temp,pSMBr->DataCount);
+					name_len += strnlen(temp,data_count);
 				}
 				referrals++;
 				/* BB add check that referral pointer does not fall off end PDU */
@@ -2173,15 +2173,19 @@
 			/* BB add check for name_len bigger than bcc */
 			*targetUNCs = 
 				kmalloc(name_len+1+ (*number_of_UNC_in_array),GFP_KERNEL);
+			if(*targetUNCs == NULL) {
+				rc = -ENOMEM;
+				goto GetDFSRefExit;
+			}
 			/* copy the ref strings */
 			referrals =  
 			    (struct dfs_referral_level_3 *) 
 					(8 /* sizeof data hdr */ +
-					pSMBr->DataOffset + 
+					data_offset + 
 					(char *) &pSMBr->hdr.Protocol);
 
 			for(i=0;i<*number_of_UNC_in_array;i++) {
-				temp = ((char *)referrals) + referrals->DfsPathOffset;
+				temp = ((char *)referrals) + le16_to_cpu(referrals->DfsPathOffset);
 				if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE) {
 					cifs_strfromUCS_le(*targetUNCs,
 						(wchar_t *) temp, name_len, nls_codepage);
@@ -2196,6 +2200,7 @@
 		}
 
 	}
+GetDFSRefExit:
 	if (pSMB)
 		cifs_buf_release(pSMB);
 
@@ -2215,6 +2220,7 @@
 	FILE_SYSTEM_INFO *response_data;
 	int rc = 0;
 	int bytes_returned = 0;
+	__u16 params, byte_count;
 
 	cFYI(1, ("In QFSInfo"));
 QFSInfoRetry:
@@ -2223,7 +2229,7 @@
 	if (rc)
 		return rc;
 
-	pSMB->TotalParameterCount = 2;	/* level */
+	params = 2;	/* level */
 	pSMB->TotalDataCount = 0;
 	pSMB->MaxParameterCount = cpu_to_le16(2);
 	pSMB->MaxDataCount = cpu_to_le16(1000);	/* BB find exact max SMB PDU from sess structure BB */
@@ -2232,8 +2238,8 @@
 	pSMB->Flags = 0;
 	pSMB->Timeout = 0;
 	pSMB->Reserved2 = 0;
-	pSMB->ByteCount = pSMB->TotalParameterCount + 1 /* pad */ ;
-	pSMB->TotalParameterCount = cpu_to_le16(pSMB->TotalParameterCount);
+	byte_count = params + 1 /* pad */ ;
+	pSMB->TotalParameterCount = cpu_to_le16(params);
 	pSMB->ParameterCount = pSMB->TotalParameterCount;
 	pSMB->ParameterOffset = cpu_to_le16(offsetof(
         struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
@@ -2243,25 +2249,25 @@
 	pSMB->Reserved3 = 0;
 	pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
 	pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FS_SIZE_INFO);
-	pSMB->hdr.smb_buf_length += pSMB->ByteCount;
-	pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
+	pSMB->hdr.smb_buf_length += byte_count;
+	pSMB->ByteCount = cpu_to_le16(byte_count);
 
 	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
 			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
 	if (rc) {
 		cERROR(1, ("Send error in QFSInfo = %d", rc));
 	} else {		/* decode response */
-		pSMBr->DataOffset = le16_to_cpu(pSMBr->DataOffset);
+		__u16 data_offset = le16_to_cpu(pSMBr->DataOffset);
 		cFYI(1,
 		     ("Decoding qfsinfo response.  BCC: %d  Offset %d",
-		      pSMBr->ByteCount, pSMBr->DataOffset));
-		if ((pSMBr->ByteCount < 24) || (pSMBr->DataOffset > 512))	/* BB also check enough total bytes returned */
+		      pSMBr->ByteCount, data_offset));
+		if ((pSMBr->ByteCount < 24) || (data_offset > 512))	/* BB also check enough total bytes returned */
 			rc = -EIO;	/* bad smb */
 		else {
 			response_data =
 			    (FILE_SYSTEM_INFO
 			     *) (((char *) &pSMBr->hdr.Protocol) +
-				 pSMBr->DataOffset);
+				 data_offset);
 			FSData->f_bsize =
 			    le32_to_cpu(response_data->BytesPerSector) *
 			    le32_to_cpu(response_data->
@@ -2296,6 +2302,7 @@
 	FILE_SYSTEM_ATTRIBUTE_INFO *response_data;
 	int rc = 0;
 	int bytes_returned = 0;
+	__u16 params, byte_count;
 
 	cFYI(1, ("In QFSAttributeInfo"));
 QFSAttributeRetry:
@@ -2304,7 +2311,7 @@
 	if (rc)
 		return rc;
 
-	pSMB->TotalParameterCount = 2;	/* level */
+	params = 2;	/* level */
 	pSMB->TotalDataCount = 0;
 	pSMB->MaxParameterCount = cpu_to_le16(2);
 	pSMB->MaxDataCount = cpu_to_le16(1000);	/* BB find exact max SMB PDU from sess structure BB */
@@ -2313,8 +2320,8 @@
 	pSMB->Flags = 0;
 	pSMB->Timeout = 0;
 	pSMB->Reserved2 = 0;
-	pSMB->ByteCount = pSMB->TotalParameterCount + 1 /* pad */ ;
-	pSMB->TotalParameterCount = cpu_to_le16(pSMB->TotalParameterCount);
+	byte_count = params + 1 /* pad */ ;
+	pSMB->TotalParameterCount = cpu_to_le16(params);
 	pSMB->ParameterCount = pSMB->TotalParameterCount;
 	pSMB->ParameterOffset = cpu_to_le16(offsetof(
         struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
@@ -2324,27 +2331,22 @@
 	pSMB->Reserved3 = 0;
 	pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
 	pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FS_ATTRIBUTE_INFO);
-	pSMB->hdr.smb_buf_length += pSMB->ByteCount;
-	pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
+	pSMB->hdr.smb_buf_length += byte_count;
+	pSMB->ByteCount = cpu_to_le16(byte_count);
 
 	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
 			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
 	if (rc) {
 		cERROR(1, ("Send error in QFSAttributeInfo = %d", rc));
 	} else {		/* decode response */
-		pSMBr->DataOffset = le16_to_cpu(pSMBr->DataOffset);
-		if ((pSMBr->ByteCount < 13) || (pSMBr->DataOffset > 512)) {	/* BB also check enough bytes returned */
+		__u16 data_offset = le16_to_cpu(pSMBr->DataOffset);
+		if ((pSMBr->ByteCount < 13) || (data_offset > 512)) {	/* BB also check enough bytes returned */
 			rc = -EIO;	/* bad smb */
 		} else {
 			response_data =
 			    (FILE_SYSTEM_ATTRIBUTE_INFO
 			     *) (((char *) &pSMBr->hdr.Protocol) +
-				 pSMBr->DataOffset);
-			response_data->Attributes = le32_to_cpu(response_data->Attributes);
-			response_data->MaxPathNameComponentLength = 
-				le32_to_cpu(response_data->MaxPathNameComponentLength);
-			response_data->FileSystemNameLen = 
-				le32_to_cpu(response_data->FileSystemNameLen);
+				 data_offset);
 			memcpy(&tcon->fsAttrInfo, response_data,
 			       sizeof (FILE_SYSTEM_ATTRIBUTE_INFO));
 		}
@@ -2368,6 +2370,7 @@
 	FILE_SYSTEM_DEVICE_INFO *response_data;
 	int rc = 0;
 	int bytes_returned = 0;
+	__u16 params, byte_count;
 
 	cFYI(1, ("In QFSDeviceInfo"));
 QFSDeviceRetry:
@@ -2376,7 +2379,7 @@
 	if (rc)
 		return rc;
 
-	pSMB->TotalParameterCount = 2;	/* level */
+	params = 2;	/* level */
 	pSMB->TotalDataCount = 0;
 	pSMB->MaxParameterCount = cpu_to_le16(2);
 	pSMB->MaxDataCount = cpu_to_le16(1000);	/* BB find exact max SMB PDU from sess structure BB */
@@ -2385,8 +2388,8 @@
 	pSMB->Flags = 0;
 	pSMB->Timeout = 0;
 	pSMB->Reserved2 = 0;
-	pSMB->ByteCount = pSMB->TotalParameterCount + 1 /* pad */ ;
-	pSMB->TotalParameterCount = cpu_to_le16(pSMB->TotalParameterCount);
+	byte_count = params + 1 /* pad */ ;
+	pSMB->TotalParameterCount = cpu_to_le16(params);
 	pSMB->ParameterCount = pSMB->TotalParameterCount;
 	pSMB->ParameterOffset = cpu_to_le16(offsetof(
         struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
@@ -2397,27 +2400,23 @@
 	pSMB->Reserved3 = 0;
 	pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
 	pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FS_DEVICE_INFO);
-	pSMB->hdr.smb_buf_length += pSMB->ByteCount;
-	pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
+	pSMB->hdr.smb_buf_length += byte_count;
+	pSMB->ByteCount = cpu_to_le16(byte_count);
 
 	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
 			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
 	if (rc) {
 		cFYI(1, ("Send error in QFSDeviceInfo = %d", rc));
 	} else {		/* decode response */
-		pSMBr->DataOffset = le16_to_cpu(pSMBr->DataOffset);
+		__u16 data_offset = le16_to_cpu(pSMBr->DataOffset);
 		if ((pSMBr->ByteCount < sizeof (FILE_SYSTEM_DEVICE_INFO))
-                 || (pSMBr->DataOffset > 512))
+                 || (data_offset > 512))
 			rc = -EIO;	/* bad smb */
 		else {
 			response_data =
 			    (FILE_SYSTEM_DEVICE_INFO
 			     *) (((char *) &pSMBr->hdr.Protocol) +
-				 pSMBr->DataOffset);
-			response_data->DeviceType = 
-				le32_to_cpu(response_data->DeviceType);
-			response_data->DeviceCharacteristics = 
-				le32_to_cpu(response_data->DeviceCharacteristics);
+				 data_offset);
 			memcpy(&tcon->fsDevInfo, response_data,
 			       sizeof (FILE_SYSTEM_DEVICE_INFO));
 		}
@@ -2441,6 +2440,7 @@
 	FILE_SYSTEM_UNIX_INFO *response_data;
 	int rc = 0;
 	int bytes_returned = 0;
+	__u16 params, byte_count;
 
 	cFYI(1, ("In QFSUnixInfo"));
 QFSUnixRetry:
@@ -2449,7 +2449,7 @@
 	if (rc)
 		return rc;
 
-	pSMB->ParameterCount = 2;	/* level */
+	params = 2;	/* level */
 	pSMB->TotalDataCount = 0;
 	pSMB->DataCount = 0;
 	pSMB->DataOffset = 0;
@@ -2460,8 +2460,8 @@
 	pSMB->Flags = 0;
 	pSMB->Timeout = 0;
 	pSMB->Reserved2 = 0;
-	pSMB->ByteCount = pSMB->ParameterCount + 1 /* pad */ ;
-	pSMB->ParameterCount = cpu_to_le16(pSMB->ParameterCount);
+	byte_count = params + 1 /* pad */ ;
+	pSMB->ParameterCount = cpu_to_le16(params);
 	pSMB->TotalParameterCount = pSMB->ParameterCount;
 	pSMB->ParameterOffset = cpu_to_le16(offsetof(struct 
         smb_com_transaction2_qfsi_req, InformationLevel) - 4);
@@ -2469,28 +2469,22 @@
 	pSMB->Reserved3 = 0;
 	pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
 	pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_CIFS_UNIX_INFO);
-	pSMB->hdr.smb_buf_length += pSMB->ByteCount;
-	pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
+	pSMB->hdr.smb_buf_length += byte_count;
+	pSMB->ByteCount = cpu_to_le16(byte_count);
 
 	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
 			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
 	if (rc) {
 		cERROR(1, ("Send error in QFSUnixInfo = %d", rc));
 	} else {		/* decode response */
-		pSMBr->DataOffset = cpu_to_le16(pSMBr->DataOffset);
-		if ((pSMBr->ByteCount < 13) || (pSMBr->DataOffset > 512)) {
+		__u16 data_offset = le16_to_cpu(pSMBr->DataOffset);
+		if ((pSMBr->ByteCount < 13) || (data_offset > 512)) {
 			rc = -EIO;	/* bad smb */
 		} else {
 			response_data =
 			    (FILE_SYSTEM_UNIX_INFO
 			     *) (((char *) &pSMBr->hdr.Protocol) +
-				 pSMBr->DataOffset);
-			response_data->MajorVersionNumber =
-				le16_to_cpu(response_data->MajorVersionNumber);
-			response_data->MinorVersionNumber =
-				le16_to_cpu(response_data->MinorVersionNumber);
-			response_data->Capability =
-				le64_to_cpu(response_data->Capability);
+				 data_offset);
 			memcpy(&tcon->fsUnixInfo, response_data,
 			       sizeof (FILE_SYSTEM_UNIX_INFO));
 		}
@@ -2521,6 +2515,7 @@
 	int name_len;
 	int rc = 0;
 	int bytes_returned = 0;
+	__u16 params, byte_count, data_count, param_offset, offset;
 
 	cFYI(1, ("In SetEOF"));
 SetEOFRetry:
@@ -2541,8 +2536,8 @@
 		name_len++;	/* trailing null */
 		strncpy(pSMB->FileName, fileName, name_len);
 	}
-	pSMB->ParameterCount = 6 + name_len;
-	pSMB->DataCount = sizeof (struct file_end_of_file_info);
+	params = 6 + name_len;
+	data_count = sizeof (struct file_end_of_file_info);
 	pSMB->MaxParameterCount = cpu_to_le16(2);
 	pSMB->MaxDataCount = cpu_to_le16(1000);	/* BB find max SMB size from sess */
 	pSMB->MaxSetupCount = 0;
@@ -2550,9 +2545,9 @@
 	pSMB->Flags = 0;
 	pSMB->Timeout = 0;
 	pSMB->Reserved2 = 0;
-	pSMB->ParameterOffset = offsetof(struct smb_com_transaction2_spi_req,
+	param_offset = offsetof(struct smb_com_transaction2_spi_req,
                                      InformationLevel) - 4;
-	pSMB->DataOffset = pSMB->ParameterOffset + pSMB->ParameterCount;
+	offset = param_offset + params;
 	if(SetAllocation) {
         	if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
 	            pSMB->InformationLevel =
@@ -2571,21 +2566,21 @@
 
 	parm_data =
 	    (struct file_end_of_file_info *) (((char *) &pSMB->hdr.Protocol) +
-				       pSMB->DataOffset);
-	pSMB->ParameterOffset = cpu_to_le16(pSMB->ParameterOffset);
-	pSMB->DataOffset = cpu_to_le16(pSMB->DataOffset);
+				       offset);
+	pSMB->ParameterOffset = cpu_to_le16(param_offset);
+	pSMB->DataOffset = cpu_to_le16(offset);
 	pSMB->SetupCount = 1;
 	pSMB->Reserved3 = 0;
 	pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
-	pSMB->ByteCount = 3 /* pad */  + pSMB->ParameterCount + pSMB->DataCount;
-	pSMB->DataCount = cpu_to_le16(pSMB->DataCount);
+	byte_count = 3 /* pad */  + params + data_count;
+	pSMB->DataCount = cpu_to_le16(data_count);
 	pSMB->TotalDataCount = pSMB->DataCount;
-	pSMB->ParameterCount = cpu_to_le16(pSMB->ParameterCount);
+	pSMB->ParameterCount = cpu_to_le16(params);
 	pSMB->TotalParameterCount = pSMB->ParameterCount;
 	pSMB->Reserved4 = 0;
-	pSMB->hdr.smb_buf_length += pSMB->ByteCount;
+	pSMB->hdr.smb_buf_length += byte_count;
 	parm_data->FileSize = cpu_to_le64(size);
-	pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
+	pSMB->ByteCount = cpu_to_le16(byte_count);
 	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
 			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
 	if (rc) {
@@ -2611,7 +2606,7 @@
 	struct file_end_of_file_info *parm_data;
 	int rc = 0;
 	int bytes_returned = 0;
-	__u32 tmp;
+	__u16 params, param_offset, offset, byte_count, count;
 
 	cFYI(1, ("SetFileSize (via SetFileInfo) %lld",
 			(long long)size));
@@ -2620,40 +2615,36 @@
 	if (rc)
 		return rc;
 
-	tmp = cpu_to_le32(pid_of_opener);  /* override pid of current process
-                                         so network fid will be valid */
-	pSMB->hdr.Pid = tmp & 0xFFFF;
-	tmp >>= 16;
-	pSMB->hdr.PidHigh = tmp & 0xFFFF;
+	pSMB->hdr.Pid = cpu_to_le16((__u16)pid_of_opener);
+	pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid_of_opener >> 16));
     
-	pSMB->ParameterCount = 6;
+	params = 6;
 	pSMB->MaxSetupCount = 0;
 	pSMB->Reserved = 0;
 	pSMB->Flags = 0;
 	pSMB->Timeout = 0;
 	pSMB->Reserved2 = 0;
-	pSMB->ParameterOffset = offsetof(struct smb_com_transaction2_sfi_req,
-                                     Fid) - 4;
-	pSMB->DataOffset = pSMB->ParameterOffset + pSMB->ParameterCount;
+	param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
+	offset = param_offset + params;
 
-	data_offset = (char *) (&pSMB->hdr.Protocol) + pSMB->DataOffset;	
+	data_offset = (char *) (&pSMB->hdr.Protocol) + offset;	
 
-	pSMB->DataCount = sizeof(struct file_end_of_file_info);
+	count = sizeof(struct file_end_of_file_info);
 	pSMB->MaxParameterCount = cpu_to_le16(2);
 	pSMB->MaxDataCount = cpu_to_le16(1000);	/* BB find max SMB PDU from sess */
 	pSMB->SetupCount = 1;
 	pSMB->Reserved3 = 0;
 	pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
-	pSMB->ByteCount = 3 /* pad */  + pSMB->ParameterCount + pSMB->DataCount;
-	pSMB->DataCount = cpu_to_le16(pSMB->DataCount);
-	pSMB->ParameterCount = cpu_to_le16(pSMB->ParameterCount);
+	byte_count = 3 /* pad */  + params + count;
+	pSMB->DataCount = cpu_to_le16(count);
+	pSMB->ParameterCount = cpu_to_le16(params);
 	pSMB->TotalDataCount = pSMB->DataCount;
 	pSMB->TotalParameterCount = pSMB->ParameterCount;
-	pSMB->ParameterOffset = cpu_to_le16(pSMB->ParameterOffset);
+	pSMB->ParameterOffset = cpu_to_le16(param_offset);
 	parm_data =
 		(struct file_end_of_file_info *) (((char *) &pSMB->hdr.Protocol) +
-			pSMB->DataOffset);
-	pSMB->DataOffset = cpu_to_le16(pSMB->DataOffset); /* now safe to change to le */
+			offset);
+	pSMB->DataOffset = cpu_to_le16(offset);
 	parm_data->FileSize = cpu_to_le64(size);
 	pSMB->Fid = fid;
 	if(SetAllocation) {
@@ -2672,8 +2663,8 @@
 		        cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO);
 	}
 	pSMB->Reserved4 = 0;
-	pSMB->hdr.smb_buf_length += pSMB->ByteCount;
-	pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
+	pSMB->hdr.smb_buf_length += byte_count;
+	pSMB->ByteCount = cpu_to_le16(byte_count);
 	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
 			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
 	if (rc) {
@@ -2702,6 +2693,7 @@
 	int rc = 0;
 	int bytes_returned = 0;
 	char *data_offset;
+	__u16 params, param_offset, offset, byte_count, count;
 
 	cFYI(1, ("In SetTimes"));
 
@@ -2724,8 +2716,8 @@
 		strncpy(pSMB->FileName, fileName, name_len);
 	}
 
-	pSMB->ParameterCount = 6 + name_len;
-	pSMB->DataCount = sizeof (FILE_BASIC_INFO);
+	params = 6 + name_len;
+	count = sizeof (FILE_BASIC_INFO);
 	pSMB->MaxParameterCount = cpu_to_le16(2);
 	pSMB->MaxDataCount = cpu_to_le16(1000);	/* BB find exact max SMB PDU from sess structure BB */
 	pSMB->MaxSetupCount = 0;
@@ -2733,19 +2725,19 @@
 	pSMB->Flags = 0;
 	pSMB->Timeout = 0;
 	pSMB->Reserved2 = 0;
-	pSMB->ParameterOffset = offsetof(struct smb_com_transaction2_spi_req,
+	param_offset = offsetof(struct smb_com_transaction2_spi_req,
                                      InformationLevel) - 4;
-	pSMB->DataOffset = pSMB->ParameterOffset + pSMB->ParameterCount;
-	data_offset = (char *) (&pSMB->hdr.Protocol) + pSMB->DataOffset;
-	pSMB->ParameterOffset = cpu_to_le16(pSMB->ParameterOffset);
-	pSMB->DataOffset = cpu_to_le16(pSMB->DataOffset);
+	offset = param_offset + params;
+	data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
+	pSMB->ParameterOffset = cpu_to_le16(param_offset);
+	pSMB->DataOffset = cpu_to_le16(offset);
 	pSMB->SetupCount = 1;
 	pSMB->Reserved3 = 0;
 	pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
-	pSMB->ByteCount = 3 /* pad */  + pSMB->ParameterCount + pSMB->DataCount;
+	byte_count = 3 /* pad */  + params + count;
 
-	pSMB->DataCount = cpu_to_le16(pSMB->DataCount);
-	pSMB->ParameterCount = cpu_to_le16(pSMB->ParameterCount);
+	pSMB->DataCount = cpu_to_le16(count);
+	pSMB->ParameterCount = cpu_to_le16(params);
 	pSMB->TotalDataCount = pSMB->DataCount;
 	pSMB->TotalParameterCount = pSMB->ParameterCount;
 	if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
@@ -2753,9 +2745,9 @@
 	else
 		pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO);
 	pSMB->Reserved4 = 0;
-	pSMB->hdr.smb_buf_length += pSMB->ByteCount;
+	pSMB->hdr.smb_buf_length += byte_count;
 	memcpy(data_offset, data, sizeof (FILE_BASIC_INFO));
-	pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
+	pSMB->ByteCount = cpu_to_le16(byte_count);
 	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
 			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
 	if (rc) {
@@ -2771,7 +2763,6 @@
 	return rc;
 }
 
-
 int
 CIFSSMBSetTimesLegacy(int xid, struct cifsTconInfo *tcon, char *fileName,
 		FILE_INFO_STANDARD * data, const struct nls_table *nls_codepage)
@@ -2782,6 +2773,7 @@
 	int rc = 0;
 	int bytes_returned = 0;
 	char *data_offset;
+	__u16 params, param_offset, count, offset, byte_count;
 
 	cFYI(1, ("In SetTimesLegacy"));
 
@@ -2805,8 +2797,8 @@
 	}
 /* BB fixme - we have to map to FILE_STANDARD_INFO (level 1 info
 	in parent function, from the better and ususal FILE_BASIC_INFO */
-	pSMB->ParameterCount = 6 + name_len;
-	pSMB->DataCount = sizeof (FILE_INFO_STANDARD);
+	params = 6 + name_len;
+	count = sizeof (FILE_INFO_STANDARD);
 	pSMB->MaxParameterCount = cpu_to_le16(2);
 	pSMB->MaxDataCount = cpu_to_le16(1000);	/* BB find exact max SMB PDU from sess structure BB */
 	pSMB->MaxSetupCount = 0;
@@ -2814,19 +2806,19 @@
 	pSMB->Flags = 0;
 	pSMB->Timeout = 0;
 	pSMB->Reserved2 = 0;
-	pSMB->ParameterOffset = offsetof(struct smb_com_transaction2_spi_req,
+	param_offset = offsetof(struct smb_com_transaction2_spi_req,
                                      InformationLevel) - 4;
-	pSMB->DataOffset = pSMB->ParameterOffset + pSMB->ParameterCount;
-	data_offset = (char *) (&pSMB->hdr.Protocol) + pSMB->DataOffset;
-	pSMB->ParameterOffset = cpu_to_le16(pSMB->ParameterOffset);
-	pSMB->DataOffset = cpu_to_le16(pSMB->DataOffset);
+	offset = param_offset + params;
+	data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
+	pSMB->ParameterOffset = cpu_to_le16(param_offset);
+	pSMB->DataOffset = cpu_to_le16(offset);
 	pSMB->SetupCount = 1;
 	pSMB->Reserved3 = 0;
 	pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
-	pSMB->ByteCount = 3 /* pad */  + pSMB->ParameterCount + pSMB->DataCount;
+	byte_count = 3 /* pad */  + params + count;
 
-	pSMB->DataCount = cpu_to_le16(pSMB->DataCount);
-	pSMB->ParameterCount = cpu_to_le16(pSMB->ParameterCount);
+	pSMB->DataCount = cpu_to_le16(count);
+	pSMB->ParameterCount = cpu_to_le16(params);
 	pSMB->TotalDataCount = pSMB->DataCount;
 	pSMB->TotalParameterCount = pSMB->ParameterCount;
 	/* I doubt that passthrough levels apply to this old
@@ -2836,9 +2828,9 @@
 	else*/
 		pSMB->InformationLevel = cpu_to_le16(SMB_INFO_STANDARD);
 	pSMB->Reserved4 = 0;
-	pSMB->hdr.smb_buf_length += pSMB->ByteCount;
+	pSMB->hdr.smb_buf_length += byte_count;
 	memcpy(data_offset, data, sizeof (FILE_INFO_STANDARD));
-	pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
+	pSMB->ByteCount = cpu_to_le16(byte_count);
 	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
 			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
 	if (rc) {
@@ -2865,6 +2857,7 @@
 	int rc = 0;
 	int bytes_returned = 0;
 	FILE_UNIX_BASIC_INFO *data_offset;
+	__u16 params, param_offset, offset, count, byte_count;
 
 	cFYI(1, ("In SetUID/GID/Mode"));
 setPermsRetry:
@@ -2886,8 +2879,8 @@
 		strncpy(pSMB->FileName, fileName, name_len);
 	}
 
-	pSMB->ParameterCount = 6 + name_len;
-	pSMB->DataCount = sizeof (FILE_UNIX_BASIC_INFO);
+	params = 6 + name_len;
+	count = sizeof (FILE_UNIX_BASIC_INFO);
 	pSMB->MaxParameterCount = cpu_to_le16(2);
 	pSMB->MaxDataCount = cpu_to_le16(1000);	/* BB find exact max SMB PDU from sess structure BB */
 	pSMB->MaxSetupCount = 0;
@@ -2895,25 +2888,25 @@
 	pSMB->Flags = 0;
 	pSMB->Timeout = 0;
 	pSMB->Reserved2 = 0;
-	pSMB->ParameterOffset = offsetof(struct smb_com_transaction2_spi_req,
+	param_offset = offsetof(struct smb_com_transaction2_spi_req,
                                      InformationLevel) - 4;
-	pSMB->DataOffset = pSMB->ParameterOffset + pSMB->ParameterCount;
+	offset = param_offset + params;
 	data_offset =
 	    (FILE_UNIX_BASIC_INFO *) ((char *) &pSMB->hdr.Protocol +
-				      pSMB->DataOffset);
-	pSMB->DataOffset = cpu_to_le16(pSMB->DataOffset);
-	pSMB->ParameterOffset = cpu_to_le16(pSMB->ParameterOffset);
+				      offset);
+	pSMB->DataOffset = cpu_to_le16(offset);
+	pSMB->ParameterOffset = cpu_to_le16(param_offset);
 	pSMB->SetupCount = 1;
 	pSMB->Reserved3 = 0;
 	pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
-	pSMB->ByteCount = 3 /* pad */  + pSMB->ParameterCount + pSMB->DataCount;
-	pSMB->ParameterCount = cpu_to_le16(pSMB->ParameterCount);
-	pSMB->DataCount = cpu_to_le16(pSMB->DataCount);
+	byte_count = 3 /* pad */  + params + count;
+	pSMB->ParameterCount = cpu_to_le16(params);
+	pSMB->DataCount = cpu_to_le16(count);
 	pSMB->TotalParameterCount = pSMB->ParameterCount;
 	pSMB->TotalDataCount = pSMB->DataCount;
 	pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_BASIC);
 	pSMB->Reserved4 = 0;
-	pSMB->hdr.smb_buf_length += pSMB->ByteCount;
+	pSMB->hdr.smb_buf_length += byte_count;
 	data_offset->Uid = cpu_to_le64(uid);
 	data_offset->Gid = cpu_to_le64(gid);
 	/* better to leave device as zero when it is  */
@@ -2937,7 +2930,7 @@
 		data_offset->Type = cpu_to_le32(UNIX_SOCKET);
 
 
-	pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
+	pSMB->ByteCount = cpu_to_le16(byte_count);
 	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
 			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
 	if (rc) {
@@ -2986,7 +2979,6 @@
 	pSMB->Fid = netfid; /* file handle always le */
 	pSMB->ByteCount = 0;
 
-	pSMB->hdr.smb_buf_length += pSMB->ByteCount;
 	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
 			(struct smb_hdr *) pSMBr, &bytes_returned, 0);
 	if (rc) {
@@ -3013,6 +3005,7 @@
 	int name_len;
 	struct fea * temp_fea;
 	char * temp_ptr;
+	__u16 params, byte_count;
 
 	cFYI(1, ("In Query All EAs path %s", searchName));
 QAllEAsRetry:
@@ -3034,8 +3027,7 @@
 		strncpy(pSMB->FileName, searchName, name_len);
 	}
 
-	pSMB->TotalParameterCount = 2 /* level */  + 4 /* reserved */  +
-	    name_len /* includes null */ ;
+	params = 2 /* level */ + 4 /* reserved */ + name_len /* includes NUL */ ;
 	pSMB->TotalDataCount = 0;
 	pSMB->MaxParameterCount = cpu_to_le16(2);
 	pSMB->MaxDataCount = cpu_to_le16(4000);	/* BB find exact max SMB PDU from sess structure BB */
@@ -3051,29 +3043,29 @@
 	pSMB->SetupCount = 1;
 	pSMB->Reserved3 = 0;
 	pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
-	pSMB->ByteCount = pSMB->TotalParameterCount + 1 /* pad */ ;
-	pSMB->TotalParameterCount = cpu_to_le16(pSMB->TotalParameterCount);
+	byte_count = params + 1 /* pad */ ;
+	pSMB->TotalParameterCount = cpu_to_le16(params);
 	pSMB->ParameterCount = pSMB->TotalParameterCount;
 	pSMB->InformationLevel = cpu_to_le16(SMB_INFO_QUERY_ALL_EAS);
 	pSMB->Reserved4 = 0;
-	pSMB->hdr.smb_buf_length += pSMB->ByteCount;
-	pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
+	pSMB->hdr.smb_buf_length += byte_count;
+	pSMB->ByteCount = cpu_to_le16(byte_count);
 
 	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
 			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
 	if (rc) {
 		cFYI(1, ("Send error in QueryAllEAs = %d", rc));
 	} else {		/* decode response */
-		pSMBr->DataOffset = le16_to_cpu(pSMBr->DataOffset);
+		__u16 data_offset = le16_to_cpu(pSMBr->DataOffset);
 		/* BB also check enough total bytes returned */
 		/* BB we need to improve the validity checking
 		of these trans2 responses */
-		if ((pSMBr->ByteCount < 4) || (pSMBr->DataOffset > 512)) 
+		if ((pSMBr->ByteCount < 4) || (data_offset > 512)) 
 			rc = -EIO;	/* bad smb */
 	   /* else if (pFindData){
 			memcpy((char *) pFindData,
 			       (char *) &pSMBr->hdr.Protocol +
-			       pSMBr->DataOffset, kl);
+			       data_offset, kl);
 		}*/ else {
 			/* check that length of list is not more than bcc */
 			/* check that each entry does not go beyond length
@@ -3083,14 +3075,12 @@
 			struct fealist * ea_response_data;
 			rc = 0;
 			/* validate_trans2_offsets() */
-			/* BB to check if(start of smb + pSMBr->DataOffset > &bcc+ bcc)*/
+			/* BB to check if(start of smb + data_offset > &bcc+ bcc)*/
 			ea_response_data = (struct fealist *)
 				(((char *) &pSMBr->hdr.Protocol) +
-				pSMBr->DataOffset);
-			ea_response_data->list_len = 
-				cpu_to_le32(ea_response_data->list_len);
-			cFYI(1,("ea length %d",ea_response_data->list_len));
-			name_len = ea_response_data->list_len;
+				data_offset);
+			name_len = le32_to_cpu(ea_response_data->list_len);
+			cFYI(1,("ea length %d", name_len));
 			if(name_len <= 8) {
 			/* returned EA size zeroed at top of function */
 				cFYI(1,("empty EA list returned from server"));
@@ -3100,12 +3090,13 @@
 				temp_fea = ea_response_data->list;
 				temp_ptr = (char *)temp_fea;
 				while(name_len > 0) {
+					__u16 value_len;
 					name_len -= 4;
 					temp_ptr += 4;
 					rc += temp_fea->name_len;
 				/* account for prefix user. and trailing null */
 					rc = rc + 5 + 1; 
-					if(rc<buf_size) {
+					if(rc<(int)buf_size) {
 						memcpy(EAData,"user.",5);
 						EAData+=5;
 						memcpy(EAData,temp_ptr,temp_fea->name_len);
@@ -3125,9 +3116,9 @@
 					/* account for trailing null */
 					name_len--;
 					temp_ptr++;
-					temp_fea->value_len = cpu_to_le16(temp_fea->value_len);
-					name_len -= temp_fea->value_len;
-					temp_ptr += temp_fea->value_len;
+					value_len = le16_to_cpu(temp_fea->value_len);
+					name_len -= value_len;
+					temp_ptr += value_len;
 					/* BB check that temp_ptr is still within smb BB*/
 				/* no trailing null to account for in value len */
 					/* go on to next EA */
@@ -3141,7 +3132,7 @@
 	if (rc == -EAGAIN)
 		goto QAllEAsRetry;
 
-	return rc;
+	return (ssize_t)rc;
 }
 
 ssize_t CIFSSMBQueryEA(const int xid,struct cifsTconInfo * tcon,
@@ -3156,6 +3147,7 @@
 	int name_len;
 	struct fea * temp_fea;
 	char * temp_ptr;
+	__u16 params, byte_count;
 
 	cFYI(1, ("In Query EA path %s", searchName));
 QEARetry:
@@ -3177,8 +3169,7 @@
 		strncpy(pSMB->FileName, searchName, name_len);
 	}
 
-	pSMB->TotalParameterCount = 2 /* level */  + 4 /* reserved */  +
-	    name_len /* includes null */ ;
+	params = 2 /* level */ + 4 /* reserved */ + name_len /* includes NUL */ ;
 	pSMB->TotalDataCount = 0;
 	pSMB->MaxParameterCount = cpu_to_le16(2);
 	pSMB->MaxDataCount = cpu_to_le16(4000);	/* BB find exact max SMB PDU from sess structure BB */
@@ -3194,29 +3185,29 @@
 	pSMB->SetupCount = 1;
 	pSMB->Reserved3 = 0;
 	pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
-	pSMB->ByteCount = pSMB->TotalParameterCount + 1 /* pad */ ;
-	pSMB->TotalParameterCount = cpu_to_le16(pSMB->TotalParameterCount);
+	byte_count = params + 1 /* pad */ ;
+	pSMB->TotalParameterCount = cpu_to_le16(params);
 	pSMB->ParameterCount = pSMB->TotalParameterCount;
 	pSMB->InformationLevel = cpu_to_le16(SMB_INFO_QUERY_ALL_EAS);
 	pSMB->Reserved4 = 0;
-	pSMB->hdr.smb_buf_length += pSMB->ByteCount;
-	pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
+	pSMB->hdr.smb_buf_length += byte_count;
+	pSMB->ByteCount = cpu_to_le16(byte_count);
 
 	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
 			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
 	if (rc) {
 		cFYI(1, ("Send error in Query EA = %d", rc));
 	} else {		/* decode response */
-		pSMBr->DataOffset = le16_to_cpu(pSMBr->DataOffset);
+		__u16 data_offset = le16_to_cpu(pSMBr->DataOffset);
 		/* BB also check enough total bytes returned */
 		/* BB we need to improve the validity checking
 		of these trans2 responses */
-		if ((pSMBr->ByteCount < 4) || (pSMBr->DataOffset > 512)) 
+		if ((pSMBr->ByteCount < 4) || (data_offset > 512)) 
 			rc = -EIO;	/* bad smb */
 	   /* else if (pFindData){
 			memcpy((char *) pFindData,
 			       (char *) &pSMBr->hdr.Protocol +
-			       pSMBr->DataOffset, kl);
+			       data_offset, kl);
 		}*/ else {
 			/* check that length of list is not more than bcc */
 			/* check that each entry does not go beyond length
@@ -3226,14 +3217,12 @@
 			struct fealist * ea_response_data;
 			rc = -ENOENT;
 			/* validate_trans2_offsets() */
-			/* BB to check if(start of smb + pSMBr->DataOffset > &bcc+ bcc)*/
+			/* BB to check if(start of smb + data_offset > &bcc+ bcc)*/
 			ea_response_data = (struct fealist *)
 				(((char *) &pSMBr->hdr.Protocol) +
-				pSMBr->DataOffset);
-			ea_response_data->list_len = 
-				cpu_to_le32(ea_response_data->list_len);
-			cFYI(1,("ea length %d",ea_response_data->list_len));
-			name_len = ea_response_data->list_len;
+				data_offset);
+			name_len = le32_to_cpu(ea_response_data->list_len);
+			cFYI(1,("ea length %d", name_len));
 			if(name_len <= 8) {
 			/* returned EA size zeroed at top of function */
 				cFYI(1,("empty EA list returned from server"));
@@ -3245,17 +3234,18 @@
 				/* loop through checking if we have a matching
 				name and then return the associated value */
 				while(name_len > 0) {
+					__u16 value_len;
 					name_len -= 4;
 					temp_ptr += 4;
-					temp_fea->value_len = cpu_to_le16(temp_fea->value_len);
+					value_len = le16_to_cpu(temp_fea->value_len);
 				/* BB validate that value_len falls within SMB, 
 				even though maximum for name_len is 255 */ 
 					if(memcmp(temp_fea->name,ea_name,
 						  temp_fea->name_len) == 0) {
 						/* found a match */
-						rc = temp_fea->value_len;
+						rc = value_len;
 				/* account for prefix user. and trailing null */
-						if(rc<=buf_size) {
+						if(rc<=(int)buf_size) {
 							memcpy(ea_value,
 								temp_fea->name+temp_fea->name_len+1,
 								rc);
@@ -3274,8 +3264,8 @@
 					/* account for trailing null */
 					name_len--;
 					temp_ptr++;
-					name_len -= temp_fea->value_len;
-					temp_ptr += temp_fea->value_len;
+					name_len -= value_len;
+					temp_ptr += value_len;
 				/* no trailing null to account for in value len */
 					/* go on to next EA */
 					temp_fea = (struct fea *)temp_ptr;
@@ -3288,7 +3278,7 @@
 	if (rc == -EAGAIN)
 		goto QEARetry;
 
-	return rc;
+	return (ssize_t)rc;
 }
 
 int
@@ -3302,6 +3292,7 @@
 	int name_len;
 	int rc = 0;
 	int bytes_returned = 0;
+	__u16 params, param_offset, byte_count, offset, count;
 
 	cFYI(1, ("In SetEA"));
 SetEARetry:
@@ -3323,7 +3314,7 @@
 		strncpy(pSMB->FileName, fileName, name_len);
 	}
 
-	pSMB->ParameterCount = 6 + name_len;
+	params = 6 + name_len;
 
 	/* done calculating parms using name_len of file name,
 	now use name_len to calculate length of ea name
@@ -3333,7 +3324,7 @@
 	else
 		name_len = strnlen(ea_name,255);
 
-	pSMB->DataCount = sizeof(*parm_data) + ea_value_len + name_len + 1;
+	count = sizeof(*parm_data) + ea_value_len + name_len + 1;
 	pSMB->MaxParameterCount = cpu_to_le16(2);
 	pSMB->MaxDataCount = cpu_to_le16(1000);	/* BB find max SMB size from sess */
 	pSMB->MaxSetupCount = 0;
@@ -3341,23 +3332,23 @@
 	pSMB->Flags = 0;
 	pSMB->Timeout = 0;
 	pSMB->Reserved2 = 0;
-	pSMB->ParameterOffset = offsetof(struct smb_com_transaction2_spi_req,
+	param_offset = offsetof(struct smb_com_transaction2_spi_req,
                                      InformationLevel) - 4;
-	pSMB->DataOffset = pSMB->ParameterOffset + pSMB->ParameterCount;
+	offset = param_offset + params;
 	pSMB->InformationLevel =
 		cpu_to_le16(SMB_SET_FILE_EA);
 
 	parm_data =
 		(struct fealist *) (((char *) &pSMB->hdr.Protocol) +
-				       pSMB->DataOffset);
-	pSMB->ParameterOffset = cpu_to_le16(pSMB->ParameterOffset);
-	pSMB->DataOffset = cpu_to_le16(pSMB->DataOffset);
+				       offset);
+	pSMB->ParameterOffset = cpu_to_le16(param_offset);
+	pSMB->DataOffset = cpu_to_le16(offset);
 	pSMB->SetupCount = 1;
 	pSMB->Reserved3 = 0;
 	pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
-	pSMB->ByteCount = 3 /* pad */  + pSMB->ParameterCount + pSMB->DataCount;
-	pSMB->DataCount = cpu_to_le16(pSMB->DataCount);
-	parm_data->list_len = (__u32)(pSMB->DataCount);
+	byte_count = 3 /* pad */  + params + count;
+	pSMB->DataCount = cpu_to_le16(count);
+	parm_data->list_len = cpu_to_le32(count);
 	parm_data->list[0].EA_flags = 0;
 	/* we checked above that name len is less than 255 */
 	parm_data->list[0].name_len = (__u8)name_len;;
@@ -3374,11 +3365,11 @@
 		memcpy(parm_data->list[0].name+name_len+1,ea_value,ea_value_len);
 
 	pSMB->TotalDataCount = pSMB->DataCount;
-	pSMB->ParameterCount = cpu_to_le16(pSMB->ParameterCount);
+	pSMB->ParameterCount = cpu_to_le16(params);
 	pSMB->TotalParameterCount = pSMB->ParameterCount;
 	pSMB->Reserved4 = 0;
-	pSMB->hdr.smb_buf_length += pSMB->ByteCount;
-	pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
+	pSMB->hdr.smb_buf_length += byte_count;
+	pSMB->ByteCount = cpu_to_le16(byte_count);
 	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
 			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
 	if (rc) {
diff -Nru a/fs/cifs/connect.c b/fs/cifs/connect.c
--- a/fs/cifs/connect.c	2004-10-18 14:57:03 -07:00
+++ b/fs/cifs/connect.c	2004-10-18 14:57:03 -07:00
@@ -64,11 +64,11 @@
 	gid_t linux_gid;
 	mode_t file_mode;
 	mode_t dir_mode;
-	int rw:1;
-	int retry:1;
-	int intr:1;
-	int setuids:1;
-	int noperm:1;
+	unsigned rw:1;
+	unsigned retry:1;
+	unsigned intr:1;
+	unsigned setuids:1;
+	unsigned noperm:1;
 	unsigned int rsize;
 	unsigned int wsize;
 	unsigned int sockopt;
@@ -313,7 +313,7 @@
 					connected to port 139 (the NACK is 
 					since we do not begin with RFC1001
 					session initialize frame) */
-					server->addr.sockAddr.sin_port = CIFS_PORT;
+					server->addr.sockAddr.sin_port = htons(CIFS_PORT);
 					cifs_reconnect(server);
 					csocket = server->ssocket;
 					wake_up(&server->response_q);
@@ -814,19 +814,23 @@
 }
 
 static struct cifsSesInfo *
-cifs_find_tcp_session(__u32 new_target_ip_addr,
+cifs_find_tcp_session(struct in_addr * target_ip_addr, 
+		struct in6_addr *target_ip6_addr,
 		 char *userName, struct TCP_Server_Info **psrvTcp)
 {
 	struct list_head *tmp;
 	struct cifsSesInfo *ses;
-
 	*psrvTcp = NULL;
 	read_lock(&GlobalSMBSeslock);
+
 	list_for_each(tmp, &GlobalSMBSessionList) {
 		ses = list_entry(tmp, struct cifsSesInfo, cifsSessionList);
 		if (ses->server) {
-			if (ses->server->addr.sockAddr.sin_addr.s_addr ==
-			    new_target_ip_addr) {
+			if((target_ip_addr && 
+				(ses->server->addr.sockAddr.sin_addr.s_addr
+				  == target_ip_addr->s_addr)) || (target_ip6_addr
+				&& memcmp(&ses->server->addr.sockAddr6.sin6_addr,
+					target_ip6_addr,sizeof(*target_ip6_addr)))){
 				/* BB lock server and tcp session and increment use count here?? */
 				*psrvTcp = ses->server;	/* found a match on the TCP session */
 				/* BB check if reconnection needed */
@@ -845,7 +849,7 @@
 }
 
 static struct cifsTconInfo *
-find_unc(__u32 new_target_ip_addr, char *uncName, char *userName)
+find_unc(__be32 new_target_ip_addr, char *uncName, char *userName)
 {
 	struct list_head *tmp;
 	struct cifsTconInfo *tcon;
@@ -964,7 +968,7 @@
 {
 	int rc = 0;
 	int connected = 0;
-	unsigned short int orig_port = 0;
+	__be16 orig_port = 0;
 
 	if(*csocket == NULL) {
 		rc = sock_create_kern(PF_INET, SOCK_STREAM, IPPROTO_TCP, csocket);
@@ -1029,7 +1033,7 @@
 
 	/* send RFC1001 sessinit */
 
-	if(psin_server->sin_port == htons(139)) {
+	if(psin_server->sin_port == htons(RFC1001_PORT)) {
 		/* some servers require RFC1001 sessinit before sending
 		negprot - BB check reconnection in case where second 
 		sessinit is sent but no second negprot */
@@ -1072,6 +1076,7 @@
 {
 	int rc = 0;
 	int connected = 0;
+	__be16 orig_port = 0;
 
 	if(*csocket == NULL) {
 		rc = sock_create_kern(PF_INET6, SOCK_STREAM, IPPROTO_TCP, csocket);
@@ -1097,6 +1102,10 @@
 	} 
 
 	if(!connected) {
+		/* save original port so we can retry user specified port  
+			later if fall back ports fail this time  */
+
+		orig_port = psin_server->sin6_port;
 		/* do not retry on the same port we just failed on */
 		if(psin_server->sin6_port != htons(CIFS_PORT)) {
 			psin_server->sin6_port = htons(CIFS_PORT);
@@ -1119,6 +1128,8 @@
 	/* give up here - unless we want to retry on different
 		protocol families some day */
 	if (!connected) {
+		if(orig_port)
+			psin_server->sin6_port = orig_port;
 		cFYI(1,("Error %d connecting to server via ipv6",rc));
 		sock_release(*csocket);
 		*csocket = NULL;
@@ -1138,6 +1149,7 @@
 {
 	int rc = 0;
 	int xid;
+	int address_type = AF_INET;
 	struct socket *csocket = NULL;
 	struct sockaddr_in sin_server;
 	struct sockaddr_in6 sin_server6;
@@ -1179,12 +1191,16 @@
 	if (volume_info.UNCip && volume_info.UNC) {
 		rc = cifs_inet_pton(AF_INET, volume_info.UNCip,&sin_server.sin_addr.s_addr);
 
-		if(rc == 0) {
+		if(rc <= 0) {
 			/* not ipv4 address, try ipv6 */
 			rc = cifs_inet_pton(AF_INET6,volume_info.UNCip,&sin_server6.sin6_addr.in6_u); 
-		} 
+			if(rc > 0)
+				address_type = AF_INET6;
+		} else {
+			address_type = AF_INET;
+		}
        
-		if(rc != 1) {
+		if(rc <= 0) {
 			/* we failed translating address */
 			if(volume_info.UNC)
 				kfree(volume_info.UNC);
@@ -1234,9 +1250,24 @@
 		}
 	}
 
-	existingCifsSes =
-	    cifs_find_tcp_session(sin_server.sin_addr.s_addr,
-			     volume_info.username, &srvTcp);
+	if(address_type == AF_INET)
+		existingCifsSes = cifs_find_tcp_session(&sin_server.sin_addr,
+			NULL /* no ipv6 addr */,
+			volume_info.username, &srvTcp);
+	else if(address_type == AF_INET6)
+		existingCifsSes = cifs_find_tcp_session(NULL /* no ipv4 addr */,
+			&sin_server6.sin6_addr,
+			volume_info.username, &srvTcp);
+	else {
+		if(volume_info.UNC)
+			kfree(volume_info.UNC);
+		if(volume_info.password)
+			kfree(volume_info.password);
+		FreeXid(xid);
+		return -EINVAL;
+	}
+
+
 	if (srvTcp) {
 		cFYI(1, ("Existing tcp session with server found "));                
 	} else {	/* create socket */
@@ -1283,8 +1314,19 @@
 			so no need to spinlock this init of tcpStatus */
 			srvTcp->tcpStatus = CifsNew;
 			init_MUTEX(&srvTcp->tcpSem);
-			kernel_thread((void *)(void *)cifs_demultiplex_thread, srvTcp,
+			rc = (int)kernel_thread((void *)(void *)cifs_demultiplex_thread, srvTcp,
 				      CLONE_FS | CLONE_FILES | CLONE_VM);
+			if(rc < 0) {
+				rc = -ENOMEM;
+				sock_release(csocket);
+				if(volume_info.UNC)
+					kfree(volume_info.UNC);
+				if(volume_info.password)
+					kfree(volume_info.password);
+				FreeXid(xid);
+				return rc;
+			} else
+				rc = 0;
 			memcpy(srvTcp->workstation_RFC1001_name, volume_info.source_rfc1001_name,16);
 		}
 	}
@@ -1464,15 +1506,20 @@
 	SESSION_SETUP_ANDX *pSMB;
 	SESSION_SETUP_ANDX *pSMBr;
 	char *bcc_ptr;
-	char *user = ses->userName;
-	char *domain = ses->domainName;
+	char *user;
+	char *domain;
 	int rc = 0;
 	int remaining_words = 0;
 	int bytes_returned = 0;
 	int len;
+	__u32 capabilities;
+	__u16 count;
 
 	cFYI(1, ("In sesssetup "));
-
+	if(ses == NULL)
+		return -EINVAL;
+	user = ses->userName;
+	domain = ses->domainName;
 	smb_buffer = cifs_buf_get();
 	if (smb_buffer == 0) {
 		return -ENOMEM;
@@ -1491,22 +1538,20 @@
 	if(ses->server->secMode & (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
 		smb_buffer->Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
 
-	pSMB->req_no_secext.Capabilities =
-	    CAP_LARGE_FILES | CAP_NT_SMBS | CAP_LEVEL_II_OPLOCKS;
+	capabilities = CAP_LARGE_FILES | CAP_NT_SMBS | CAP_LEVEL_II_OPLOCKS;
 	if (ses->capabilities & CAP_UNICODE) {
 		smb_buffer->Flags2 |= SMBFLG2_UNICODE;
-		pSMB->req_no_secext.Capabilities |= CAP_UNICODE;
+		capabilities |= CAP_UNICODE;
 	}
 	if (ses->capabilities & CAP_STATUS32) {
 		smb_buffer->Flags2 |= SMBFLG2_ERR_STATUS;
-		pSMB->req_no_secext.Capabilities |= CAP_STATUS32;
+		capabilities |= CAP_STATUS32;
 	}
 	if (ses->capabilities & CAP_DFS) {
 		smb_buffer->Flags2 |= SMBFLG2_DFS;
-		pSMB->req_no_secext.Capabilities |= CAP_DFS;
+		capabilities |= CAP_DFS;
 	}
-	pSMB->req_no_secext.Capabilities =
-	    cpu_to_le32(pSMB->req_no_secext.Capabilities);
+	pSMB->req_no_secext.Capabilities = cpu_to_le32(capabilities);
 	/* pSMB->req_no_secext.CaseInsensitivePasswordLength =
 	   CIFS_SESSION_KEY_SIZE; */
 	pSMB->req_no_secext.CaseInsensitivePasswordLength = 0;
@@ -1578,9 +1623,9 @@
 		strcpy(bcc_ptr, CIFS_NETWORK_OPSYS);
 		bcc_ptr += strlen(CIFS_NETWORK_OPSYS) + 1;
 	}
-	BCC(smb_buffer) = (long) bcc_ptr - (long) pByteArea(smb_buffer);
-	smb_buffer->smb_buf_length += BCC(smb_buffer);
-	BCC(smb_buffer) = cpu_to_le16(BCC(smb_buffer));
+	count = (long) bcc_ptr - (long) pByteArea(smb_buffer);
+	smb_buffer->smb_buf_length += count;
+	pSMB->req_no_secext.ByteCount = cpu_to_le16(count);
 
 	rc = SendReceive(xid, ses, smb_buffer, smb_buffer_response,
 			 &bytes_returned, 1);
@@ -1588,114 +1633,106 @@
 /* rc = map_smb_to_linux_error(smb_buffer_response); now done in SendReceive */
 	} else if ((smb_buffer_response->WordCount == 3)
 		   || (smb_buffer_response->WordCount == 4)) {
-		pSMBr->resp.Action = le16_to_cpu(pSMBr->resp.Action);
-		if (pSMBr->resp.Action & GUEST_LOGIN)
+		__u16 action = le16_to_cpu(pSMBr->resp.Action);
+		__u16 blob_len = le16_to_cpu(pSMBr->resp.SecurityBlobLength);
+		if (action & GUEST_LOGIN)
 			cFYI(1, (" Guest login"));	/* do we want to mark SesInfo struct ? */
-		if (ses) {
-			ses->Suid = smb_buffer_response->Uid;	/* UID left in wire format (le) */
-			cFYI(1, ("UID = %d ", ses->Suid));
+		ses->Suid = smb_buffer_response->Uid;	/* UID left in wire format (le) */
+		cFYI(1, ("UID = %d ", ses->Suid));
          /* response can have either 3 or 4 word count - Samba sends 3 */
-			bcc_ptr = pByteArea(smb_buffer_response);	
-			if ((pSMBr->resp.hdr.WordCount == 3)
-			    || ((pSMBr->resp.hdr.WordCount == 4)
-				&& (pSMBr->resp.SecurityBlobLength <
-				    pSMBr->resp.ByteCount))) {
-				if (pSMBr->resp.hdr.WordCount == 4)
-					bcc_ptr +=
-					    pSMBr->resp.SecurityBlobLength;
-
-				if (smb_buffer->Flags2 & SMBFLG2_UNICODE) {
-					if ((long) (bcc_ptr) % 2) {
-						remaining_words =
-						    (BCC(smb_buffer_response)
-						     - 1) / 2;
-						bcc_ptr++;	/* Unicode strings must be word aligned */
-					} else {
-						remaining_words =
-						    BCC
-						    (smb_buffer_response) / 2;
-					}
-					len =
-					    UniStrnlen((wchar_t *) bcc_ptr,
-						       remaining_words - 1);
+		bcc_ptr = pByteArea(smb_buffer_response);	
+		if ((pSMBr->resp.hdr.WordCount == 3)
+		    || ((pSMBr->resp.hdr.WordCount == 4)
+			&& (blob_len < pSMBr->resp.ByteCount))) {
+			if (pSMBr->resp.hdr.WordCount == 4)
+				bcc_ptr += blob_len;
+
+			if (smb_buffer->Flags2 & SMBFLG2_UNICODE) {
+				if ((long) (bcc_ptr) % 2) {
+					remaining_words =
+					    (BCC(smb_buffer_response) - 1) /2;
+					bcc_ptr++;	/* Unicode strings must be word aligned */
+				} else {
+					remaining_words =
+						BCC(smb_buffer_response) / 2;
+				}
+				len =
+				    UniStrnlen((wchar_t *) bcc_ptr,
+					       remaining_words - 1);
 /* We look for obvious messed up bcc or strings in response so we do not go off
    the end since (at least) WIN2K and Windows XP have a major bug in not null
    terminating last Unicode string in response  */
-					ses->serverOS = cifs_kcalloc(2 * (len + 1), GFP_KERNEL);
-					cifs_strfromUCS_le(ses->serverOS,
-							   (wchar_t *)bcc_ptr, len,nls_codepage);
+				ses->serverOS = cifs_kcalloc(2 * (len + 1), GFP_KERNEL);
+				cifs_strfromUCS_le(ses->serverOS,
+					   (wchar_t *)bcc_ptr, len,nls_codepage);
+				bcc_ptr += 2 * (len + 1);
+				remaining_words -= len + 1;
+				ses->serverOS[2 * len] = 0;
+				ses->serverOS[1 + (2 * len)] = 0;
+				if (remaining_words > 0) {
+					len = UniStrnlen((wchar_t *)bcc_ptr,
+							 remaining_words-1);
+					ses->serverNOS =cifs_kcalloc(2 * (len + 1),GFP_KERNEL);
+					cifs_strfromUCS_le(ses->serverNOS,
+							   (wchar_t *)bcc_ptr,len,nls_codepage);
 					bcc_ptr += 2 * (len + 1);
+					ses->serverNOS[2 * len] = 0;
+					ses->serverNOS[1 + (2 * len)] = 0;
 					remaining_words -= len + 1;
-					ses->serverOS[2 * len] = 0;
-					ses->serverOS[1 + (2 * len)] = 0;
 					if (remaining_words > 0) {
-						len = UniStrnlen((wchar_t *)bcc_ptr,
-								 remaining_words
-								 - 1);
-						ses->serverNOS =cifs_kcalloc(2 * (len + 1),GFP_KERNEL);
-						cifs_strfromUCS_le(ses->serverNOS,
-								   (wchar_t *)bcc_ptr,len,nls_codepage);
-						bcc_ptr += 2 * (len + 1);
-						ses->serverNOS[2 * len] = 0;
-						ses->serverNOS[1 + (2 * len)] = 0;
-						remaining_words -= len + 1;
-						if (remaining_words > 0) {
-							len = UniStrnlen((wchar_t *) bcc_ptr, remaining_words);	
+						len = UniStrnlen((wchar_t *) bcc_ptr, remaining_words);	
           /* last string is not always null terminated (for e.g. for Windows XP & 2000) */
-							ses->serverDomain =
-							    cifs_kcalloc(2*(len+1),GFP_KERNEL);
-							cifs_strfromUCS_le(ses->serverDomain,
-							     (wchar_t *)bcc_ptr,len,nls_codepage);
-							bcc_ptr += 2 * (len + 1);
-							ses->serverDomain[2*len] = 0;
-							ses->serverDomain[1+(2*len)] = 0;
-						} /* else no more room so create dummy domain string */
-						else
-							ses->serverDomain =
-							    cifs_kcalloc(2,
-								    GFP_KERNEL);
-					} else {	/* no room so create dummy domain and NOS string */
 						ses->serverDomain =
-						    cifs_kcalloc(2, GFP_KERNEL);
-						ses->serverNOS =
-						    cifs_kcalloc(2, GFP_KERNEL);
-					}
-				} else {	/* ASCII */
-					len = strnlen(bcc_ptr, 1024);
-					if (((long) bcc_ptr + len) - (long)
-					    pByteArea(smb_buffer_response)
+						    cifs_kcalloc(2*(len+1),GFP_KERNEL);
+						cifs_strfromUCS_le(ses->serverDomain,
+						     (wchar_t *)bcc_ptr,len,nls_codepage);
+						bcc_ptr += 2 * (len + 1);
+						ses->serverDomain[2*len] = 0;
+						ses->serverDomain[1+(2*len)] = 0;
+					} /* else no more room so create dummy domain string */
+					else
+						ses->serverDomain =
+						    cifs_kcalloc(2,
+							    GFP_KERNEL);
+				} else {	/* no room so create dummy domain and NOS string */
+					ses->serverDomain =
+					    cifs_kcalloc(2, GFP_KERNEL);
+					ses->serverNOS =
+					    cifs_kcalloc(2, GFP_KERNEL);
+				}
+			} else {	/* ASCII */
+				len = strnlen(bcc_ptr, 1024);
+				if (((long) bcc_ptr + len) - (long)
+				    pByteArea(smb_buffer_response)
 					    <= BCC(smb_buffer_response)) {
-						ses->serverOS = cifs_kcalloc(len + 1,GFP_KERNEL);
-						strncpy(ses->serverOS,bcc_ptr, len);
+					ses->serverOS = cifs_kcalloc(len + 1,GFP_KERNEL);
+					strncpy(ses->serverOS,bcc_ptr, len);
 
-						bcc_ptr += len;
-						bcc_ptr[0] = 0;	/* null terminate the string */
-						bcc_ptr++;
+					bcc_ptr += len;
+					bcc_ptr[0] = 0;	/* null terminate the string */
+					bcc_ptr++;
 
-						len = strnlen(bcc_ptr, 1024);
-						ses->serverNOS = cifs_kcalloc(len + 1,GFP_KERNEL);
-						strncpy(ses->serverNOS, bcc_ptr, len);
-						bcc_ptr += len;
-						bcc_ptr[0] = 0;
-						bcc_ptr++;
+					len = strnlen(bcc_ptr, 1024);
+					ses->serverNOS = cifs_kcalloc(len + 1,GFP_KERNEL);
+					strncpy(ses->serverNOS, bcc_ptr, len);
+					bcc_ptr += len;
+					bcc_ptr[0] = 0;
+					bcc_ptr++;
 
-						len = strnlen(bcc_ptr, 1024);
-						ses->serverDomain = cifs_kcalloc(len + 1,GFP_KERNEL);
-						strncpy(ses->serverDomain, bcc_ptr, len);
-						bcc_ptr += len;
-						bcc_ptr[0] = 0;
-						bcc_ptr++;
-					} else
-						cFYI(1,
-						     ("Variable field of length %d extends beyond end of smb ",
-						      len));
-				}
-			} else {
-				cERROR(1,
-				       (" Security Blob Length extends beyond end of SMB"));
+					len = strnlen(bcc_ptr, 1024);
+					ses->serverDomain = cifs_kcalloc(len + 1,GFP_KERNEL);
+					strncpy(ses->serverDomain, bcc_ptr, len);
+					bcc_ptr += len;
+					bcc_ptr[0] = 0;
+					bcc_ptr++;
+				} else
+					cFYI(1,
+					     ("Variable field of length %d extends beyond end of smb ",
+					      len));
 			}
 		} else {
-			cERROR(1, ("No session structure passed in."));
+			cERROR(1,
+			       (" Security Blob Length extends beyond end of SMB"));
 		}
 	} else {
 		cERROR(1,
@@ -1720,14 +1757,20 @@
 	SESSION_SETUP_ANDX *pSMB;
 	SESSION_SETUP_ANDX *pSMBr;
 	char *bcc_ptr;
-	char *user = ses->userName;
-	char *domain = ses->domainName;
+	char *user;
+	char *domain;
 	int rc = 0;
 	int remaining_words = 0;
 	int bytes_returned = 0;
 	int len;
+	__u32 capabilities;
+	__u16 count;
 
 	cFYI(1, ("In spnego sesssetup "));
+	if(ses == NULL)
+		return -EINVAL;
+	user = ses->userName;
+	domain = ses->domainName;
 
 	smb_buffer = cifs_buf_get();
 	if (smb_buffer == 0) {
@@ -1747,22 +1790,21 @@
 	if(ses->server->secMode & (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
 		smb_buffer->Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
 
-	pSMB->req.Capabilities =
-	    CAP_LARGE_FILES | CAP_NT_SMBS | CAP_LEVEL_II_OPLOCKS |
+	capabilities = CAP_LARGE_FILES | CAP_NT_SMBS | CAP_LEVEL_II_OPLOCKS |
 	    CAP_EXTENDED_SECURITY;
 	if (ses->capabilities & CAP_UNICODE) {
 		smb_buffer->Flags2 |= SMBFLG2_UNICODE;
-		pSMB->req.Capabilities |= CAP_UNICODE;
+		capabilities |= CAP_UNICODE;
 	}
 	if (ses->capabilities & CAP_STATUS32) {
 		smb_buffer->Flags2 |= SMBFLG2_ERR_STATUS;
-		pSMB->req.Capabilities |= CAP_STATUS32;
+		capabilities |= CAP_STATUS32;
 	}
 	if (ses->capabilities & CAP_DFS) {
 		smb_buffer->Flags2 |= SMBFLG2_DFS;
-		pSMB->req.Capabilities |= CAP_DFS;
+		capabilities |= CAP_DFS;
 	}
-	pSMB->req.Capabilities = cpu_to_le32(pSMB->req.Capabilities);
+	pSMB->req.Capabilities = cpu_to_le32(capabilities);
 
 	pSMB->req.SecurityBlobLength = cpu_to_le16(SecurityBlobLength);
 	bcc_ptr = pByteArea(smb_buffer);
@@ -1823,9 +1865,9 @@
 		strcpy(bcc_ptr, CIFS_NETWORK_OPSYS);
 		bcc_ptr += strlen(CIFS_NETWORK_OPSYS) + 1;
 	}
-	BCC(smb_buffer) = (long) bcc_ptr - (long) pByteArea(smb_buffer);
-	smb_buffer->smb_buf_length += BCC(smb_buffer);
-	BCC(smb_buffer) = cpu_to_le16(BCC(smb_buffer));
+	count = (long) bcc_ptr - (long) pByteArea(smb_buffer);
+	smb_buffer->smb_buf_length += count;
+	pSMB->req.ByteCount = cpu_to_le16(count);
 
 	rc = SendReceive(xid, ses, smb_buffer, smb_buffer_response,
 			 &bytes_returned, 1);
@@ -1833,10 +1875,10 @@
 /*    rc = map_smb_to_linux_error(smb_buffer_response);  *//* done in SendReceive now */
 	} else if ((smb_buffer_response->WordCount == 3)
 		   || (smb_buffer_response->WordCount == 4)) {
-		pSMBr->resp.Action = le16_to_cpu(pSMBr->resp.Action);
-		pSMBr->resp.SecurityBlobLength =
+		__u16 action = le16_to_cpu(pSMBr->resp.Action);
+		__u16 blob_len =
 		    le16_to_cpu(pSMBr->resp.SecurityBlobLength);
-		if (pSMBr->resp.Action & GUEST_LOGIN)
+		if (action & GUEST_LOGIN)
 			cFYI(1, (" Guest login"));	/* BB do we want to set anything in SesInfo struct ? */
 		if (ses) {
 			ses->Suid = smb_buffer_response->Uid;	/* UID left in wire format (le) */
@@ -1847,14 +1889,14 @@
 
 			if ((pSMBr->resp.hdr.WordCount == 3)
 			    || ((pSMBr->resp.hdr.WordCount == 4)
-				&& (pSMBr->resp.SecurityBlobLength <
+				&& (blob_len <
 				    pSMBr->resp.ByteCount))) {
 				if (pSMBr->resp.hdr.WordCount == 4) {
 					bcc_ptr +=
-					    pSMBr->resp.SecurityBlobLength;
+					    blob_len;
 					cFYI(1,
 					     ("Security Blob Length %d ",
-					      pSMBr->resp.SecurityBlobLength));
+					      blob_len));
 				}
 
 				if (smb_buffer->Flags2 & SMBFLG2_UNICODE) {
@@ -1979,7 +2021,7 @@
 	SESSION_SETUP_ANDX *pSMB;
 	SESSION_SETUP_ANDX *pSMBr;
 	char *bcc_ptr;
-	char *domain = ses->domainName;
+	char *domain;
 	int rc = 0;
 	int remaining_words = 0;
 	int bytes_returned = 0;
@@ -1987,8 +2029,13 @@
 	int SecurityBlobLength = sizeof (NEGOTIATE_MESSAGE);
 	PNEGOTIATE_MESSAGE SecurityBlob;
 	PCHALLENGE_MESSAGE SecurityBlob2;
+	__u32 negotiate_flags, capabilities;
+	__u16 count;
 
 	cFYI(1, ("In NTLMSSP sesssetup (negotiate) "));
+	if(ses == NULL)
+		return -EINVAL;
+	domain = ses->domainName;
 	*pNTLMv2_flag = FALSE;
 	smb_buffer = cifs_buf_get();
 	if (smb_buffer == 0) {
@@ -2011,35 +2058,34 @@
 	if(ses->server->secMode & (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
 		smb_buffer->Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
 
-	pSMB->req.Capabilities =
-	    CAP_LARGE_FILES | CAP_NT_SMBS | CAP_LEVEL_II_OPLOCKS |
+	capabilities = CAP_LARGE_FILES | CAP_NT_SMBS | CAP_LEVEL_II_OPLOCKS |
 	    CAP_EXTENDED_SECURITY;
 	if (ses->capabilities & CAP_UNICODE) {
 		smb_buffer->Flags2 |= SMBFLG2_UNICODE;
-		pSMB->req.Capabilities |= CAP_UNICODE;
+		capabilities |= CAP_UNICODE;
 	}
 	if (ses->capabilities & CAP_STATUS32) {
 		smb_buffer->Flags2 |= SMBFLG2_ERR_STATUS;
-		pSMB->req.Capabilities |= CAP_STATUS32;
+		capabilities |= CAP_STATUS32;
 	}
 	if (ses->capabilities & CAP_DFS) {
 		smb_buffer->Flags2 |= SMBFLG2_DFS;
-		pSMB->req.Capabilities |= CAP_DFS;
+		capabilities |= CAP_DFS;
 	}
-	pSMB->req.Capabilities = cpu_to_le32(pSMB->req.Capabilities);
+	pSMB->req.Capabilities = cpu_to_le32(capabilities);
 
 	bcc_ptr = (char *) &pSMB->req.SecurityBlob;
 	SecurityBlob = (PNEGOTIATE_MESSAGE) bcc_ptr;
 	strncpy(SecurityBlob->Signature, NTLMSSP_SIGNATURE, 8);
 	SecurityBlob->MessageType = NtLmNegotiate;
-	SecurityBlob->NegotiateFlags =
+	negotiate_flags =
 	    NTLMSSP_NEGOTIATE_UNICODE | NTLMSSP_NEGOTIATE_OEM |
 	    NTLMSSP_REQUEST_TARGET | NTLMSSP_NEGOTIATE_NTLM | 0x80000000 |
 	    /* NTLMSSP_NEGOTIATE_ALWAYS_SIGN | */ NTLMSSP_NEGOTIATE_128;
 	if(sign_CIFS_PDUs)
-		SecurityBlob->NegotiateFlags |= NTLMSSP_NEGOTIATE_SIGN;
+		negotiate_flags |= NTLMSSP_NEGOTIATE_SIGN;
 	if(ntlmv2_support)
-		SecurityBlob->NegotiateFlags |= NTLMSSP_NEGOTIATE_NTLMV2;
+		negotiate_flags |= NTLMSSP_NEGOTIATE_NTLMV2;
 	/* setup pointers to domain name and workstation name */
 	bcc_ptr += SecurityBlobLength;
 
@@ -2052,20 +2098,20 @@
 		SecurityBlob->DomainName.Length = 0;
 		SecurityBlob->DomainName.MaximumLength = 0;
 	} else {
-		SecurityBlob->NegotiateFlags |=
-		    NTLMSSP_NEGOTIATE_DOMAIN_SUPPLIED;
+		__u16 len;
+		negotiate_flags |= NTLMSSP_NEGOTIATE_DOMAIN_SUPPLIED;
 		strncpy(bcc_ptr, domain, 63);
-		SecurityBlob->DomainName.Length = strnlen(domain, 64);
+		len = strnlen(domain, 64);
 		SecurityBlob->DomainName.MaximumLength =
-		    cpu_to_le16(SecurityBlob->DomainName.Length);
+		    cpu_to_le16(len);
 		SecurityBlob->DomainName.Buffer =
 		    cpu_to_le32((long) &SecurityBlob->
 				DomainString -
 				(long) &SecurityBlob->Signature);
-		bcc_ptr += SecurityBlob->DomainName.Length;
-		SecurityBlobLength += SecurityBlob->DomainName.Length;
+		bcc_ptr += len;
+		SecurityBlobLength += len;
 		SecurityBlob->DomainName.Length =
-		    cpu_to_le16(SecurityBlob->DomainName.Length);
+		    cpu_to_le16(len);
 	}
 	if (ses->capabilities & CAP_UNICODE) {
 		if ((long) bcc_ptr % 2) {
@@ -2102,28 +2148,27 @@
 		bcc_ptr++;	/* empty domain field */
 		*bcc_ptr = 0;
 	}
-	SecurityBlob->NegotiateFlags =
-	    cpu_to_le32(SecurityBlob->NegotiateFlags);
+	SecurityBlob->NegotiateFlags = cpu_to_le32(negotiate_flags);
 	pSMB->req.SecurityBlobLength = cpu_to_le16(SecurityBlobLength);
-	BCC(smb_buffer) = (long) bcc_ptr - (long) pByteArea(smb_buffer);
-	smb_buffer->smb_buf_length += BCC(smb_buffer);
-	BCC(smb_buffer) = cpu_to_le16(BCC(smb_buffer));
+	count = (long) bcc_ptr - (long) pByteArea(smb_buffer);
+	smb_buffer->smb_buf_length += count;
+	pSMB->req.ByteCount = cpu_to_le16(count);
 
 	rc = SendReceive(xid, ses, smb_buffer, smb_buffer_response,
 			 &bytes_returned, 1);
 
 	if (smb_buffer_response->Status.CifsError ==
-	    (NT_STATUS_MORE_PROCESSING_REQUIRED))
+	    cpu_to_le32(NT_STATUS_MORE_PROCESSING_REQUIRED))
 		rc = 0;
 
 	if (rc) {
 /*    rc = map_smb_to_linux_error(smb_buffer_response);  *//* done in SendReceive now */
 	} else if ((smb_buffer_response->WordCount == 3)
 		   || (smb_buffer_response->WordCount == 4)) {
-		pSMBr->resp.Action = le16_to_cpu(pSMBr->resp.Action);
-		pSMBr->resp.SecurityBlobLength =
-		    le16_to_cpu(pSMBr->resp.SecurityBlobLength);
-		if (pSMBr->resp.Action & GUEST_LOGIN)
+		__u16 action = le16_to_cpu(pSMBr->resp.Action);
+		__u16 blob_len = le16_to_cpu(pSMBr->resp.SecurityBlobLength);
+
+		if (action & GUEST_LOGIN)
 			cFYI(1, (" Guest login"));	
         /* Do we want to set anything in SesInfo struct when guest login? */
 
@@ -2140,14 +2185,14 @@
 			cFYI(1, ("UID = %d ", ses->Suid));
 			if ((pSMBr->resp.hdr.WordCount == 3)
 			    || ((pSMBr->resp.hdr.WordCount == 4)
-				&& (pSMBr->resp.SecurityBlobLength <
+				&& (blob_len <
 				    pSMBr->resp.ByteCount))) {
+
 				if (pSMBr->resp.hdr.WordCount == 4) {
-					bcc_ptr +=
-					    pSMBr->resp.SecurityBlobLength;
+					bcc_ptr += blob_len;
 					cFYI(1,
 					     ("Security Blob Length %d ",
-					      pSMBr->resp.SecurityBlobLength));
+					      blob_len));
 				}
 
 				cFYI(1, ("NTLMSSP Challenge rcvd "));
@@ -2155,16 +2200,16 @@
 				memcpy(ses->server->cryptKey,
 				       SecurityBlob2->Challenge,
 				       CIFS_CRYPTO_KEY_SIZE);
-				if(SecurityBlob2->NegotiateFlags & NTLMSSP_NEGOTIATE_NTLMV2)
+				if(SecurityBlob2->NegotiateFlags & cpu_to_le32(NTLMSSP_NEGOTIATE_NTLMV2))
 					*pNTLMv2_flag = TRUE;
 
 				if((SecurityBlob2->NegotiateFlags & 
-					NTLMSSP_NEGOTIATE_ALWAYS_SIGN) 
+					cpu_to_le32(NTLMSSP_NEGOTIATE_ALWAYS_SIGN)) 
 					|| (sign_CIFS_PDUs > 1))
 						ses->server->secMode |= 
 							SECMODE_SIGN_REQUIRED;	
 				if ((SecurityBlob2->NegotiateFlags & 
-					NTLMSSP_NEGOTIATE_SIGN) && (sign_CIFS_PDUs))
+					cpu_to_le32(NTLMSSP_NEGOTIATE_SIGN)) && (sign_CIFS_PDUs))
 						ses->server->secMode |= 
 							SECMODE_SIGN_ENABLED;
 
@@ -2308,7 +2353,6 @@
 
 	return rc;
 }
-
 static int
 CIFSNTLMSSPAuthSessSetup(unsigned int xid, struct cifsSesInfo *ses,
 		char *ntlm_session_key, int ntlmv2_flag,
@@ -2319,17 +2363,22 @@
 	SESSION_SETUP_ANDX *pSMB;
 	SESSION_SETUP_ANDX *pSMBr;
 	char *bcc_ptr;
-	char *user = ses->userName;
-	char *domain = ses->domainName;
+	char *user;
+	char *domain;
 	int rc = 0;
 	int remaining_words = 0;
 	int bytes_returned = 0;
 	int len;
 	int SecurityBlobLength = sizeof (AUTHENTICATE_MESSAGE);
 	PAUTHENTICATE_MESSAGE SecurityBlob;
+	__u32 negotiate_flags, capabilities;
+	__u16 count;
 
 	cFYI(1, ("In NTLMSSPSessSetup (Authenticate)"));
-
+	if(ses == NULL)
+		return -EINVAL;
+	user = ses->userName;
+	domain = ses->domainName;
 	smb_buffer = cifs_buf_get();
 	if (smb_buffer == 0) {
 		return -ENOMEM;
@@ -2352,36 +2401,35 @@
 	if(ses->server->secMode & (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
 		smb_buffer->Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
 
-	pSMB->req.Capabilities =
-	    CAP_LARGE_FILES | CAP_NT_SMBS | CAP_LEVEL_II_OPLOCKS |
+	capabilities = CAP_LARGE_FILES | CAP_NT_SMBS | CAP_LEVEL_II_OPLOCKS |
 	    CAP_EXTENDED_SECURITY;
 	if (ses->capabilities & CAP_UNICODE) {
 		smb_buffer->Flags2 |= SMBFLG2_UNICODE;
-		pSMB->req.Capabilities |= CAP_UNICODE;
+		capabilities |= CAP_UNICODE;
 	}
 	if (ses->capabilities & CAP_STATUS32) {
 		smb_buffer->Flags2 |= SMBFLG2_ERR_STATUS;
-		pSMB->req.Capabilities |= CAP_STATUS32;
+		capabilities |= CAP_STATUS32;
 	}
 	if (ses->capabilities & CAP_DFS) {
 		smb_buffer->Flags2 |= SMBFLG2_DFS;
-		pSMB->req.Capabilities |= CAP_DFS;
+		capabilities |= CAP_DFS;
 	}
-	pSMB->req.Capabilities = cpu_to_le32(pSMB->req.Capabilities);
+	pSMB->req.Capabilities = cpu_to_le32(capabilities);
 
 	bcc_ptr = (char *) &pSMB->req.SecurityBlob;
 	SecurityBlob = (PAUTHENTICATE_MESSAGE) bcc_ptr;
 	strncpy(SecurityBlob->Signature, NTLMSSP_SIGNATURE, 8);
 	SecurityBlob->MessageType = NtLmAuthenticate;
 	bcc_ptr += SecurityBlobLength;
-	SecurityBlob->NegotiateFlags =
+	negotiate_flags = 
 	    NTLMSSP_NEGOTIATE_UNICODE | NTLMSSP_REQUEST_TARGET |
 	    NTLMSSP_NEGOTIATE_NTLM | NTLMSSP_NEGOTIATE_TARGET_INFO |
 	    0x80000000 | NTLMSSP_NEGOTIATE_128;
 	if(sign_CIFS_PDUs)
-		SecurityBlob->NegotiateFlags |= /* NTLMSSP_NEGOTIATE_ALWAYS_SIGN |*/ NTLMSSP_NEGOTIATE_SIGN;
+		negotiate_flags |= /* NTLMSSP_NEGOTIATE_ALWAYS_SIGN |*/ NTLMSSP_NEGOTIATE_SIGN;
 	if(ntlmv2_flag)
-		SecurityBlob->NegotiateFlags |= NTLMSSP_NEGOTIATE_NTLMV2;
+		negotiate_flags |= NTLMSSP_NEGOTIATE_NTLMV2;
 
 /* setup pointers to domain name and workstation name */
 
@@ -2412,36 +2460,36 @@
 			SecurityBlob->DomainName.Length = 0;
 			SecurityBlob->DomainName.MaximumLength = 0;
 		} else {
-			SecurityBlob->DomainName.Length =
+			__u16 len =
 			    cifs_strtoUCS((wchar_t *) bcc_ptr, domain, 64,
 					  nls_codepage);
-			SecurityBlob->DomainName.Length *= 2;
+			len *= 2;
 			SecurityBlob->DomainName.MaximumLength =
-			    cpu_to_le16(SecurityBlob->DomainName.Length);
+			    cpu_to_le16(len);
 			SecurityBlob->DomainName.Buffer =
 			    cpu_to_le32(SecurityBlobLength);
-			bcc_ptr += SecurityBlob->DomainName.Length;
-			SecurityBlobLength += SecurityBlob->DomainName.Length;
+			bcc_ptr += len;
+			SecurityBlobLength += len;
 			SecurityBlob->DomainName.Length =
-			    cpu_to_le16(SecurityBlob->DomainName.Length);
+			    cpu_to_le16(len);
 		}
 		if (user == NULL) {
 			SecurityBlob->UserName.Buffer = 0;
 			SecurityBlob->UserName.Length = 0;
 			SecurityBlob->UserName.MaximumLength = 0;
 		} else {
-			SecurityBlob->UserName.Length =
+			__u16 len =
 			    cifs_strtoUCS((wchar_t *) bcc_ptr, user, 64,
 					  nls_codepage);
-			SecurityBlob->UserName.Length *= 2;
+			len *= 2;
 			SecurityBlob->UserName.MaximumLength =
-			    cpu_to_le16(SecurityBlob->UserName.Length);
+			    cpu_to_le16(len);
 			SecurityBlob->UserName.Buffer =
 			    cpu_to_le32(SecurityBlobLength);
-			bcc_ptr += SecurityBlob->UserName.Length;
-			SecurityBlobLength += SecurityBlob->UserName.Length;
+			bcc_ptr += len;
+			SecurityBlobLength += len;
 			SecurityBlob->UserName.Length =
-			    cpu_to_le16(SecurityBlob->UserName.Length);
+			    cpu_to_le16(len);
 		}
 
 		/* SecurityBlob->WorkstationName.Length = cifs_strtoUCS((wchar_t *) bcc_ptr, "AMACHINE",64, nls_codepage);
@@ -2481,34 +2529,33 @@
 			SecurityBlob->DomainName.Length = 0;
 			SecurityBlob->DomainName.MaximumLength = 0;
 		} else {
-			SecurityBlob->NegotiateFlags |=
-			    NTLMSSP_NEGOTIATE_DOMAIN_SUPPLIED;
+			__u16 len;
+			negotiate_flags |= NTLMSSP_NEGOTIATE_DOMAIN_SUPPLIED;
 			strncpy(bcc_ptr, domain, 63);
-			SecurityBlob->DomainName.Length = strnlen(domain, 64);
+			len = strnlen(domain, 64);
 			SecurityBlob->DomainName.MaximumLength =
-			    cpu_to_le16(SecurityBlob->DomainName.Length);
+			    cpu_to_le16(len);
 			SecurityBlob->DomainName.Buffer =
 			    cpu_to_le32(SecurityBlobLength);
-			bcc_ptr += SecurityBlob->DomainName.Length;
-			SecurityBlobLength += SecurityBlob->DomainName.Length;
-			SecurityBlob->DomainName.Length =
-			    cpu_to_le16(SecurityBlob->DomainName.Length);
+			bcc_ptr += len;
+			SecurityBlobLength += len;
+			SecurityBlob->DomainName.Length = cpu_to_le16(len);
 		}
 		if (user == NULL) {
 			SecurityBlob->UserName.Buffer = 0;
 			SecurityBlob->UserName.Length = 0;
 			SecurityBlob->UserName.MaximumLength = 0;
 		} else {
+			__u16 len;
 			strncpy(bcc_ptr, user, 63);
-			SecurityBlob->UserName.Length = strnlen(user, 64);
+			len = strnlen(user, 64);
 			SecurityBlob->UserName.MaximumLength =
-			    cpu_to_le16(SecurityBlob->UserName.Length);
+			    cpu_to_le16(len);
 			SecurityBlob->UserName.Buffer =
 			    cpu_to_le32(SecurityBlobLength);
-			bcc_ptr += SecurityBlob->UserName.Length;
-			SecurityBlobLength += SecurityBlob->UserName.Length;
-			SecurityBlob->UserName.Length =
-			    cpu_to_le16(SecurityBlob->UserName.Length);
+			bcc_ptr += len;
+			SecurityBlobLength += len;
+			SecurityBlob->UserName.Length = cpu_to_le16(len);
 		}
 		/* BB fill in our workstation name if known BB */
 
@@ -2521,12 +2568,11 @@
 		bcc_ptr++;	/* null domain */
 		*bcc_ptr = 0;
 	}
-	SecurityBlob->NegotiateFlags =
-	    cpu_to_le32(SecurityBlob->NegotiateFlags);
+	SecurityBlob->NegotiateFlags = cpu_to_le32(negotiate_flags);
 	pSMB->req.SecurityBlobLength = cpu_to_le16(SecurityBlobLength);
-	BCC(smb_buffer) = (long) bcc_ptr - (long) pByteArea(smb_buffer);
-	smb_buffer->smb_buf_length += BCC(smb_buffer);
-	BCC(smb_buffer) = cpu_to_le16(BCC(smb_buffer));
+	count = (long) bcc_ptr - (long) pByteArea(smb_buffer);
+	smb_buffer->smb_buf_length += count;
+	pSMB->req.ByteCount = cpu_to_le16(count);
 
 	rc = SendReceive(xid, ses, smb_buffer, smb_buffer_response,
 			 &bytes_returned, 1);
@@ -2534,10 +2580,10 @@
 /*    rc = map_smb_to_linux_error(smb_buffer_response);  *//* done in SendReceive now */
 	} else if ((smb_buffer_response->WordCount == 3)
 		   || (smb_buffer_response->WordCount == 4)) {
-		pSMBr->resp.Action = le16_to_cpu(pSMBr->resp.Action);
-		pSMBr->resp.SecurityBlobLength =
+		__u16 action = le16_to_cpu(pSMBr->resp.Action);
+		__u16 blob_len =
 		    le16_to_cpu(pSMBr->resp.SecurityBlobLength);
-		if (pSMBr->resp.Action & GUEST_LOGIN)
+		if (action & GUEST_LOGIN)
 			cFYI(1, (" Guest login"));	/* BB do we want to set anything in SesInfo struct ? */
 /*        if(SecurityBlob2->MessageType != NtLm??){                               
                  cFYI("Unexpected message type on auth response is %d ")); 
@@ -2551,14 +2597,14 @@
             /* response can have either 3 or 4 word count - Samba sends 3 */
 			if ((pSMBr->resp.hdr.WordCount == 3)
 			    || ((pSMBr->resp.hdr.WordCount == 4)
-				&& (pSMBr->resp.SecurityBlobLength <
+				&& (blob_len <
 				    pSMBr->resp.ByteCount))) {
 				if (pSMBr->resp.hdr.WordCount == 4) {
 					bcc_ptr +=
-					    pSMBr->resp.SecurityBlobLength;
+					    blob_len;
 					cFYI(1,
 					     ("Security Blob Length %d ",
-					      pSMBr->resp.SecurityBlobLength));
+					      blob_len));
 				}
 
 				cFYI(1,
@@ -2699,9 +2745,10 @@
 	struct smb_hdr *smb_buffer_response;
 	TCONX_REQ *pSMB;
 	TCONX_RSP *pSMBr;
-	char *bcc_ptr;
+	unsigned char *bcc_ptr;
 	int rc = 0;
 	int length;
+	__u16 count;
 
 	if (ses == NULL)
 		return -EIO;
@@ -2721,7 +2768,7 @@
 	pSMB->AndXCommand = 0xFF;
 	pSMB->Flags = cpu_to_le16(TCON_EXTENDED_SECINFO);
 	pSMB->PasswordLength = cpu_to_le16(1);	/* minimum */
-	bcc_ptr = &(pSMB->Password[0]);
+	bcc_ptr = &pSMB->Password[0];
 	bcc_ptr++;		/* skip password */
 
 	if(ses->server->secMode & (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
@@ -2747,16 +2794,16 @@
 	strcpy(bcc_ptr, "?????");
 	bcc_ptr += strlen("?????");
 	bcc_ptr += 1;
-	BCC(smb_buffer) = (long) bcc_ptr - (long) pByteArea(smb_buffer);
-	smb_buffer->smb_buf_length += BCC(smb_buffer);
-	BCC(smb_buffer) = cpu_to_le16(BCC(smb_buffer));
+	count = bcc_ptr - &pSMB->Password[0];
+	pSMB->hdr.smb_buf_length += count;
+	pSMB->ByteCount = cpu_to_le16(count);
 
 	rc = SendReceive(xid, ses, smb_buffer, smb_buffer_response, &length, 0);
 
 	/* if (rc) rc = map_smb_to_linux_error(smb_buffer_response); */
 	/* above now done in SendReceive */
 	if ((rc == 0) && (tcon != NULL)) {
-        tcon->tidStatus = CifsGood;
+		tcon->tidStatus = CifsGood;
 		tcon->tid = smb_buffer_response->Tid;
 		bcc_ptr = pByteArea(smb_buffer_response);
 		length = strnlen(bcc_ptr, BCC(smb_buffer_response) - 2);
@@ -2765,8 +2812,8 @@
 		strncpy(tcon->treeName, tree, MAX_TREE_SIZE);
 		if (smb_buffer->Flags2 & SMBFLG2_UNICODE) {
 			length = UniStrnlen((wchar_t *) bcc_ptr, 512);
-			if (((long) bcc_ptr + (2 * length)) -
-			    (long) pByteArea(smb_buffer_response) <=
+			if ((bcc_ptr + (2 * length)) -
+			     pByteArea(smb_buffer_response) <=
 			    BCC(smb_buffer_response)) {
 				if(tcon->nativeFileSystem)
 					kfree(tcon->nativeFileSystem);
@@ -2783,8 +2830,8 @@
 			/* else do not bother copying these informational fields */
 		} else {
 			length = strnlen(bcc_ptr, 1024);
-			if (((long) bcc_ptr + length) -
-			    (long) pByteArea(smb_buffer_response) <=
+			if ((bcc_ptr + length) -
+			    pByteArea(smb_buffer_response) <=
 			    BCC(smb_buffer_response)) {
 				if(tcon->nativeFileSystem)
 					kfree(tcon->nativeFileSystem);
diff -Nru a/fs/cifs/file.c b/fs/cifs/file.c
--- a/fs/cifs/file.c	2004-10-18 14:55:53 -07:00
+++ b/fs/cifs/file.c	2004-10-18 14:55:53 -07:00
@@ -148,7 +148,7 @@
 	and the first handle has writebehind data, we might be 
 	able to simply do a filemap_fdatawrite/filemap_fdatawait first */
 	buf = kmalloc(sizeof(FILE_ALL_INFO),GFP_KERNEL);
-	if(buf==0) {
+	if(buf== NULL) {
 		if (full_path)
 			kfree(full_path);
 		FreeXid(xid);
@@ -569,6 +569,8 @@
 			 netfid, length,
 			 pfLock->fl_start, numUnlock, numLock, lockType,
 			 wait_flag);
+	if (rc == 0 && (pfLock->fl_flags & FL_POSIX))
+		posix_lock_file(file, pfLock);
 	FreeXid(xid);
 	return rc;
 }
@@ -1346,12 +1348,11 @@
 {
 	struct cifsInodeInfo *cifsInfo = CIFS_I(tmp_inode);
 	struct cifs_sb_info *cifs_sb = CIFS_SB(tmp_inode->i_sb);
+	__u32 attr = le32_to_cpu(pfindData->ExtFileAttributes);
+	__u64 allocation_size = le64_to_cpu(pfindData->AllocationSize);
+	__u64 end_of_file = le64_to_cpu(pfindData->EndOfFile);
 
-	pfindData->ExtFileAttributes =
-	    le32_to_cpu(pfindData->ExtFileAttributes);
-	pfindData->AllocationSize = le64_to_cpu(pfindData->AllocationSize);
-	pfindData->EndOfFile = le64_to_cpu(pfindData->EndOfFile);
-	cifsInfo->cifsAttrs = pfindData->ExtFileAttributes;
+	cifsInfo->cifsAttrs = attr;
 	cifsInfo->time = jiffies;
 
 	/* Linux can not store file creation time unfortunately so ignore it */
@@ -1374,12 +1375,12 @@
 
 	cFYI(0,
 	     ("CIFS FFIRST: Attributes came in as 0x%x",
-	      pfindData->ExtFileAttributes));
-	if (pfindData->ExtFileAttributes & ATTR_REPARSE) {
+	      attr));
+	if (attr & ATTR_REPARSE) {
 		*pobject_type = DT_LNK;
 		/* BB can this and S_IFREG or S_IFDIR be set as in Windows? */
 		tmp_inode->i_mode |= S_IFLNK;
-	} else if (pfindData->ExtFileAttributes & ATTR_DIRECTORY) {
+	} else if (attr & ATTR_DIRECTORY) {
 		*pobject_type = DT_DIR;
 		/* override default perms since we do not lock dirs */
 		if(atomic_read(&cifsInfo->inUse) == 0) {
@@ -1389,7 +1390,7 @@
 	} else {
 		*pobject_type = DT_REG;
 		tmp_inode->i_mode |= S_IFREG;
-		if(pfindData->ExtFileAttributes & ATTR_READONLY)
+		if(attr & ATTR_READONLY)
 			tmp_inode->i_mode &= ~(S_IWUGO);
 
 	}/* could add code here - to validate if device or weird share type? */
@@ -1402,14 +1403,14 @@
 	if(is_size_safe_to_change(cifsInfo)) {
 		/* can not safely change the file size here if the 
 		client is writing to it due to potential races */
-		i_size_write(tmp_inode,pfindData->EndOfFile);
+		i_size_write(tmp_inode,end_of_file);
 
 	/* 512 bytes (2**9) is the fake blocksize that must be used */
 	/* for this calculation, even though the reported blocksize is larger */
-		tmp_inode->i_blocks = (512 - 1 + pfindData->AllocationSize) >> 9;
+		tmp_inode->i_blocks = (512 - 1 + allocation_size) >> 9;
 	}
 
-	if (pfindData->AllocationSize < pfindData->EndOfFile)
+	if (allocation_size < end_of_file)
 		cFYI(1, ("Possible sparse file: allocation size less than end of file "));
 	cFYI(1,
 	     ("File Size %ld and blocks %ld and blocksize %ld",
@@ -1439,6 +1440,9 @@
 		   FILE_UNIX_INFO * pfindData, int *pobject_type)
 {
 	struct cifsInodeInfo *cifsInfo = CIFS_I(tmp_inode);
+	__u32 type = le32_to_cpu(pfindData->Type);
+	__u64 num_of_bytes = le64_to_cpu(pfindData->NumOfBytes);
+	__u64 end_of_file = le64_to_cpu(pfindData->EndOfFile);
 	cifsInfo->time = jiffies;
 	atomic_inc(&cifsInfo->inUse);
 
@@ -1450,30 +1454,29 @@
 	    cifs_NTtimeToUnix(le64_to_cpu(pfindData->LastStatusChange));
 
 	tmp_inode->i_mode = le64_to_cpu(pfindData->Permissions);
-	pfindData->Type = le32_to_cpu(pfindData->Type);
-	if (pfindData->Type == UNIX_FILE) {
+	if (type == UNIX_FILE) {
 		*pobject_type = DT_REG;
 		tmp_inode->i_mode |= S_IFREG;
-	} else if (pfindData->Type == UNIX_SYMLINK) {
+	} else if (type == UNIX_SYMLINK) {
 		*pobject_type = DT_LNK;
 		tmp_inode->i_mode |= S_IFLNK;
-	} else if (pfindData->Type == UNIX_DIR) {
+	} else if (type == UNIX_DIR) {
 		*pobject_type = DT_DIR;
 		tmp_inode->i_mode |= S_IFDIR;
-	} else if (pfindData->Type == UNIX_CHARDEV) {
+	} else if (type == UNIX_CHARDEV) {
 		*pobject_type = DT_CHR;
 		tmp_inode->i_mode |= S_IFCHR;
 		tmp_inode->i_rdev = MKDEV(le64_to_cpu(pfindData->DevMajor),
 				le64_to_cpu(pfindData->DevMinor) & MINORMASK);
-	} else if (pfindData->Type == UNIX_BLOCKDEV) {
+	} else if (type == UNIX_BLOCKDEV) {
 		*pobject_type = DT_BLK;
 		tmp_inode->i_mode |= S_IFBLK;
 		tmp_inode->i_rdev = MKDEV(le64_to_cpu(pfindData->DevMajor),
 				le64_to_cpu(pfindData->DevMinor) & MINORMASK);
-	} else if (pfindData->Type == UNIX_FIFO) {
+	} else if (type == UNIX_FIFO) {
 		*pobject_type = DT_FIFO;
 		tmp_inode->i_mode |= S_IFIFO;
-	} else if (pfindData->Type == UNIX_SOCKET) {
+	} else if (type == UNIX_SOCKET) {
 		*pobject_type = DT_SOCK;
 		tmp_inode->i_mode |= S_IFSOCK;
 	}
@@ -1482,17 +1485,15 @@
 	tmp_inode->i_gid = le64_to_cpu(pfindData->Gid);
 	tmp_inode->i_nlink = le64_to_cpu(pfindData->Nlinks);
 
-	pfindData->NumOfBytes = le64_to_cpu(pfindData->NumOfBytes);
 
 	if(is_size_safe_to_change(cifsInfo)) {
 		/* can not safely change the file size here if the 
 		client is writing to it due to potential races */
-		pfindData->EndOfFile = le64_to_cpu(pfindData->EndOfFile);
-		i_size_write(tmp_inode,pfindData->EndOfFile);
+		i_size_write(tmp_inode,end_of_file);
 
 	/* 512 bytes (2**9) is the fake blocksize that must be used */
 	/* for this calculation, not the real blocksize */
-		tmp_inode->i_blocks = (512 - 1 + pfindData->NumOfBytes) >> 9;
+		tmp_inode->i_blocks = (512 - 1 + num_of_bytes) >> 9;
 	}
 
 	if (S_ISREG(tmp_inode->i_mode)) {
@@ -1606,7 +1607,7 @@
 	int object_type,rc;
 
 	pqstring->name = pfindData->FileName;
-	pqstring->len = pfindData->FileNameLength;
+	/* pqstring->len is already set by caller */
 
 	construct_dentry(pqstring, file, &tmp_inode, &tmp_dentry);
 	if((tmp_inode == NULL) || (tmp_dentry == NULL)) {
@@ -1685,8 +1686,12 @@
 	}
 	data = kmalloc(bufsize, GFP_KERNEL);
 	pfindData = (FILE_DIRECTORY_INFO *) data;
-
+	if(data == NULL) {
+		FreeXid(xid);
+		return -ENOMEM;
+	}
 	if(file->f_dentry == NULL) {
+		kfree(data);
 		FreeXid(xid);
 		return -EIO;
 	}
@@ -1694,7 +1699,11 @@
 	full_path = build_wildcard_path_from_dentry(file->f_dentry);
 	up(&file->f_dentry->d_sb->s_vfs_rename_sem);
 
-
+	if(full_path == NULL) {
+		kfree(data);
+		FreeXid(xid);
+		return -ENOMEM;
+	}
 	cFYI(1, ("Full path: %s start at: %lld ", full_path, file->f_pos));
 
 	switch ((int) file->f_pos) {
@@ -1736,10 +1745,12 @@
 		rc = CIFSFindFirst(xid, pTcon, full_path, pfindData,
 				&findParms, cifs_sb->local_nls,
 				&Unicode, &UnixSearch);
-		cFYI(1, ("Count: %d  End: %d ", findParms.SearchCount,
-			findParms.EndofSearch));
+		cFYI(1, ("Count: %d  End: %d ",
+			le16_to_cpu(findParms.SearchCount),
+			le16_to_cpu(findParms.EndofSearch)));
  
 		if (rc == 0) {
+			__u16 count = le16_to_cpu(findParms.SearchCount);
 			searchHandle = findParms.SearchHandle;
 			if(file->private_data == NULL)
 				file->private_data =
@@ -1760,7 +1771,7 @@
 			renew_parental_timestamps(file->f_dentry);
 			lastFindData = 
 				(FILE_DIRECTORY_INFO *) ((char *) pfindData + 
-					findParms.LastNameOffset);
+					le16_to_cpu(findParms.LastNameOffset));
 			if((char *)lastFindData > (char *)pfindData + bufsize) {
 				cFYI(1,("last search entry past end of packet"));
 				rc = -EIO;
@@ -1782,6 +1793,10 @@
 				cFYI(1,("Last file: %s with name %d bytes long",
 					lastFindData->FileName,
 					cifsFile->resume_name_length));
+				if(cifsFile->search_resume_name == NULL) {
+					rc = -ENOMEM;
+					break;
+				}
 				memcpy(cifsFile->search_resume_name,
 					lastFindData->FileName, 
 					cifsFile->resume_name_length);
@@ -1811,27 +1826,29 @@
 				cFYI(1,("Last file: %s with name %d bytes long",
 					pfindDataUnix->FileName,
 					cifsFile->resume_name_length));
+				if(cifsFile->search_resume_name == NULL) {
+					rc = -ENOMEM;
+					break;
+				}
 				memcpy(cifsFile->search_resume_name,
 					pfindDataUnix->FileName, 
 					cifsFile->resume_name_length);
 			}
-			for (i = 2; i < (unsigned int)findParms.SearchCount + 2; i++) {
+			for (i = 2; i < count + 2; i++) {
 				if (UnixSearch == FALSE) {
-					pfindData->FileNameLength =
-					  le32_to_cpu(pfindData->FileNameLength);
+					__u32 len = le32_to_cpu(pfindData->FileNameLength);
 					if (Unicode == TRUE)
-						pfindData->FileNameLength =
+						len =
 						    cifs_strfromUCS_le
 						    (pfindData->FileName,
 						     (wchar_t *)
 						     pfindData->FileName,
-						     (pfindData->
-						      FileNameLength) / 2,
+						     len / 2,
 						     cifs_sb->local_nls);
-					qstring.len = pfindData->FileNameLength;
-					if (((qstring.len != 1)
+					qstring.len = len;
+					if (((len != 1)
 					     || (pfindData->FileName[0] != '.'))
-					    && ((qstring.len != 2)
+					    && ((len != 2)
 						|| (pfindData->
 						    FileName[0] != '.')
 						|| (pfindData->
@@ -1899,7 +1916,7 @@
 			}	/* end for loop */
 			if ((findParms.EndofSearch != 0) && cifsFile) {
 				cifsFile->endOfSearch = TRUE;
-				if(findParms.SearchCount == 2)
+				if(findParms.SearchCount == cpu_to_le16(2))
 					cifsFile->emptyDir = TRUE;
 			}
 		} else {
@@ -1930,13 +1947,14 @@
 				cifsFile->resume_key,
 				&Unicode, &UnixSearch);
 			cFYI(1,("Count: %d  End: %d ",
-			      findNextParms.SearchCount,
-			      findNextParms.EndofSearch));
+			      le16_to_cpu(findNextParms.SearchCount),
+			      le16_to_cpu(findNextParms.EndofSearch)));
 			if ((rc == 0) && (findNextParms.SearchCount != 0)) {
 			/* BB save off resume key, key name and name length  */
+				__u16 count = le16_to_cpu(findNextParms.SearchCount);
 				lastFindData = 
 					(FILE_DIRECTORY_INFO *) ((char *) pfindData 
-						+ findNextParms.LastNameOffset);
+					+ le16_to_cpu(findNextParms.LastNameOffset));
 				if((char *)lastFindData > (char *)pfindData + bufsize) {
 					cFYI(1,("last search entry past end of packet"));
 					rc = -EIO;
@@ -1964,6 +1982,11 @@
 					cFYI(1,("Last file: %s with name %d bytes long",
 						lastFindData->FileName,
 						cifsFile->resume_name_length));
+					if(cifsFile->search_resume_name == NULL) {
+						rc = -ENOMEM;
+						break;
+					}
+					
 					memcpy(cifsFile->search_resume_name,
 						lastFindData->FileName, 
 						cifsFile->resume_name_length);
@@ -1999,29 +2022,31 @@
 					cFYI(1,("fnext last file: %s with name %d bytes long",
 						pfindDataUnix->FileName,
 						cifsFile->resume_name_length));
+					if(cifsFile->search_resume_name == NULL) {
+						rc = -ENOMEM;
+						break;
+					}
 					memcpy(cifsFile->search_resume_name,
 						pfindDataUnix->FileName, 
 						cifsFile->resume_name_length);
 				}
 
-				for (i = 0; i < findNextParms.SearchCount; i++) {
-					pfindData->FileNameLength =
-					    le32_to_cpu(pfindData->
+				for (i = 0; i < count; i++) {
+					__u32 len = le32_to_cpu(pfindData->
 							FileNameLength);
 					if (UnixSearch == FALSE) {
 						if (Unicode == TRUE)
-							pfindData->FileNameLength =
+							len =
 							  cifs_strfromUCS_le
 							  (pfindData->FileName,
 							  (wchar_t *)
 							  pfindData->FileName,
-							  (pfindData->FileNameLength)/ 2,
+							  len / 2,
 							  cifs_sb->local_nls);
-						qstring.len = 
-							pfindData->FileNameLength;
-						if (((qstring.len != 1)
+						qstring.len = len;
+						if (((len != 1)
 						    || (pfindData->FileName[0] != '.'))
-						    && ((qstring.len != 2)
+						    && ((len != 2)
 							|| (pfindData->FileName[0] != '.')
 							|| (pfindData->FileName[1] !=
 							    '.'))) {
diff -Nru a/fs/cifs/inode.c b/fs/cifs/inode.c
--- a/fs/cifs/inode.c	2004-10-18 14:55:54 -07:00
+++ b/fs/cifs/inode.c	2004-10-18 14:55:54 -07:00
@@ -76,6 +76,9 @@
 
 	} else {
 		struct cifsInodeInfo *cifsInfo;
+		__u32 type = le32_to_cpu(findData.Type);
+		__u64 num_of_bytes = le64_to_cpu(findData.NumOfBytes);
+		__u64 end_of_file = le64_to_cpu(findData.EndOfFile);
 
 		/* get new inode */
 		if (*pinode == NULL) {
@@ -101,37 +104,34 @@
 		inode->i_ctime =
 		    cifs_NTtimeToUnix(le64_to_cpu(findData.LastStatusChange));
 		inode->i_mode = le64_to_cpu(findData.Permissions);
-		findData.Type = le32_to_cpu(findData.Type);
-		if (findData.Type == UNIX_FILE) {
+		if (type == UNIX_FILE) {
 			inode->i_mode |= S_IFREG;
-		} else if (findData.Type == UNIX_SYMLINK) {
+		} else if (type == UNIX_SYMLINK) {
 			inode->i_mode |= S_IFLNK;
-		} else if (findData.Type == UNIX_DIR) {
+		} else if (type == UNIX_DIR) {
 			inode->i_mode |= S_IFDIR;
-		} else if (findData.Type == UNIX_CHARDEV) {
+		} else if (type == UNIX_CHARDEV) {
 			inode->i_mode |= S_IFCHR;
 			inode->i_rdev = MKDEV(le64_to_cpu(findData.DevMajor),
 				le64_to_cpu(findData.DevMinor) & MINORMASK);
-		} else if (findData.Type == UNIX_BLOCKDEV) {
+		} else if (type == UNIX_BLOCKDEV) {
 			inode->i_mode |= S_IFBLK;
 			inode->i_rdev = MKDEV(le64_to_cpu(findData.DevMajor),
 				le64_to_cpu(findData.DevMinor) & MINORMASK);
-		} else if (findData.Type == UNIX_FIFO) {
+		} else if (type == UNIX_FIFO) {
 			inode->i_mode |= S_IFIFO;
-		} else if (findData.Type == UNIX_SOCKET) {
+		} else if (type == UNIX_SOCKET) {
 			inode->i_mode |= S_IFSOCK;
 		}
 		inode->i_uid = le64_to_cpu(findData.Uid);
 		inode->i_gid = le64_to_cpu(findData.Gid);
 		inode->i_nlink = le64_to_cpu(findData.Nlinks);
-		findData.NumOfBytes = le64_to_cpu(findData.NumOfBytes);
-		findData.EndOfFile = le64_to_cpu(findData.EndOfFile);
 
 		if(is_size_safe_to_change(cifsInfo)) {
 		/* can not safely change the file size here if the 
 		   client is writing to it due to potential races */
 
-			i_size_write(inode,findData.EndOfFile);
+			i_size_write(inode, end_of_file);
 /* blksize needs to be multiple of two. So safer to default to blksize
 	and blkbits set in superblock so 2**blkbits and blksize will match */
 /*		inode->i_blksize =
@@ -143,14 +143,14 @@
 		 
 
 /*		inode->i_blocks = 
-	                (inode->i_blksize - 1 + findData.NumOfBytes) >> inode->i_blkbits;*/
+	                (inode->i_blksize - 1 + num_of_bytes) >> inode->i_blkbits;*/
 
 		/* 512 bytes (2**9) is the fake blocksize that must be used */
 		/* for this calculation */
-			inode->i_blocks = (512 - 1 + findData.NumOfBytes) >> 9;
+			inode->i_blocks = (512 - 1 + num_of_bytes) >> 9;
 		}
 
-		if (findData.NumOfBytes < findData.EndOfFile)
+		if (num_of_bytes < end_of_file)
 			cFYI(1, ("Server inconsistency Error: it says allocation size less than end of file "));
 		cFYI(1,
 		     ("Size %ld and blocks %ld ",
@@ -201,6 +201,8 @@
 	/* if file info not passed in then get it from server */
 	if(pfindData == NULL) {
 		buf = kmalloc(sizeof(FILE_ALL_INFO),GFP_KERNEL);
+		if(buf == NULL)
+			return -ENOMEM;
 		pfindData = (FILE_ALL_INFO *)buf;
 	/* could do find first instead but this returns more info */
 		rc = CIFSSMBQPathInfo(xid, pTcon, search_path, pfindData,
@@ -235,6 +237,7 @@
 		}
 	} else {
 		struct cifsInodeInfo *cifsInfo;
+		__u32 attr = le32_to_cpu(pfindData->Attributes);
 
 		/* get new inode */
 		if (*pinode == NULL) {
@@ -245,8 +248,7 @@
 		}
 		inode = *pinode;
 		cifsInfo = CIFS_I(inode);
-		pfindData->Attributes = le32_to_cpu(pfindData->Attributes);
-		cifsInfo->cifsAttrs = pfindData->Attributes;
+		cifsInfo->cifsAttrs = attr;
 		cFYI(1, (" Old time %ld ", cifsInfo->time));
 		cifsInfo->time = jiffies;
 		cFYI(1, (" New time %ld ", cifsInfo->time));
@@ -264,17 +266,17 @@
 		inode->i_ctime =
 		    cifs_NTtimeToUnix(le64_to_cpu(pfindData->ChangeTime));
 		cFYI(0,
-		     (" Attributes came in as 0x%x ", pfindData->Attributes));
+		     (" Attributes came in as 0x%x ", attr));
 
 		/* set default mode. will override for dirs below */
 		if(atomic_read(&cifsInfo->inUse) == 0)
 			/* new inode, can safely set these fields */
 			inode->i_mode = cifs_sb->mnt_file_mode;
 
-		if (pfindData->Attributes & ATTR_REPARSE) {
+		if (attr & ATTR_REPARSE) {
 	/* Can IFLNK be set as it basically is on windows with IFREG or IFDIR? */
 			inode->i_mode |= S_IFLNK;
-		} else if (pfindData->Attributes & ATTR_DIRECTORY) {
+		} else if (attr & ATTR_DIRECTORY) {
 	/* override default perms since we do not do byte range locking on dirs */
 			inode->i_mode = cifs_sb->mnt_dir_mode;
 			inode->i_mode |= S_IFDIR;
@@ -293,10 +295,9 @@
 
 		/* 512 bytes (2**9) is the fake blocksize that must be used */
 		/* for this calculation */
-			inode->i_blocks = (512 - 1 + pfindData->AllocationSize)
+			inode->i_blocks = (512 - 1 + le64_to_cpu(pfindData->AllocationSize))
 				 >> 9;
 		}
-		pfindData->AllocationSize = le64_to_cpu(pfindData->AllocationSize);
 
 		inode->i_nlink = le32_to_cpu(pfindData->NumberOfLinks);
 
@@ -949,7 +950,7 @@
 	} else
 		time_buf.ChangeTime = 0;
 
-	if (set_time | time_buf.Attributes) {
+	if (set_time || time_buf.Attributes) {
 		/* BB what if setting one attribute fails  
 			(such as size) but time setting works */
 		time_buf.CreationTime = 0;	/* do not change */
diff -Nru a/fs/cifs/link.c b/fs/cifs/link.c
--- a/fs/cifs/link.c	2004-10-18 14:56:27 -07:00
+++ b/fs/cifs/link.c	2004-10-18 14:56:27 -07:00
@@ -20,6 +20,7 @@
  */
 #include <linux/fs.h>
 #include <linux/stat.h>
+#include <linux/namei.h>
 #include "cifsfs.h"
 #include "cifspdu.h"
 #include "cifsglob.h"
@@ -94,7 +95,7 @@
 	int rc = -EACCES;
 	int xid;
 	char *full_path = NULL;
-	char * target_path;
+	char * target_path = ERR_PTR(-ENOMEM);
 	struct cifs_sb_info *cifs_sb;
 	struct cifsTconInfo *pTcon;
 
@@ -104,22 +105,17 @@
 	full_path = build_path_from_dentry(direntry);
 	up(&direntry->d_sb->s_vfs_rename_sem);
 
-	if(full_path == NULL) {
-		FreeXid(xid);
-		return -ENOMEM;
-	}
+	if (!full_path)
+		goto out_no_free;
+
 	cFYI(1, ("Full path: %s inode = 0x%p", full_path, inode));
 	cifs_sb = CIFS_SB(inode->i_sb);
 	pTcon = cifs_sb->tcon;
 	target_path = kmalloc(PATH_MAX, GFP_KERNEL);
-	if(target_path == NULL) {
-		if (full_path)
-			kfree(full_path);
-		FreeXid(xid);
-		return -ENOMEM;
+	if (!target_path) {
+		target_path = ERR_PTR(-ENOMEM);
+		goto out;
 	}
-	/* can not call the following line due to EFAULT in vfs_readlink which is presumably expecting a user space buffer */
-	/* length = cifs_readlink(direntry,target_path, sizeof(target_path) - 1);    */
 
 /* BB add read reparse point symlink code and Unix extensions symlink code here BB */
 	if (pTcon->ses->capabilities & CAP_UNIX)
@@ -130,25 +126,25 @@
 	else {
 		/* rc = CIFSSMBQueryReparseLinkInfo */
 		/* BB Add code to Query ReparsePoint info */
+		/* BB Add MAC style xsymlink check here if enabled */
 	}
-	/* BB Anything else to do to handle recursive links? */
-	/* BB Should we be using page symlink ops here? */
 
 	if (rc == 0) {
 
 /* BB Add special case check for Samba DFS symlinks */
 
 		target_path[PATH_MAX-1] = 0;
-		rc = vfs_follow_link(nd, target_path);
+	} else {
+		kfree(target_path);
+		target_path = ERR_PTR(rc);
 	}
-	/* else EACCESS */
 
-	if (target_path)
-		kfree(target_path);
-	if (full_path)
-		kfree(full_path);
+out:
+	kfree(full_path);
+out_no_free:
 	FreeXid(xid);
-	return rc;
+	nd_set_link(nd, target_path);
+	return 0;
 }
 
 int
@@ -297,10 +293,7 @@
 					if(referrals)
 						kfree(referrals);
 					kfree(tmp_path);
-					if(referrals) {
-						kfree(referrals);
-					}
-				}
+}
 				/* BB add code like else decode referrals then memcpy to
 				  tmpbuffer and free referrals string array BB */
 			}
@@ -325,4 +318,11 @@
 	}
 	FreeXid(xid);
 	return rc;
+}
+
+void cifs_put_link(struct dentry *direntry, struct nameidata *nd)
+{
+	char *p = nd_get_link(nd);
+	if (!IS_ERR(p))
+		kfree(p);
 }
diff -Nru a/fs/cifs/misc.c b/fs/cifs/misc.c
--- a/fs/cifs/misc.c	2004-10-18 14:57:04 -07:00
+++ b/fs/cifs/misc.c	2004-10-18 14:57:04 -07:00
@@ -189,7 +189,6 @@
     )
 {
 	int i;
-	__u32 tmp;
 	struct list_head* temp_item;
 	struct cifsSesInfo * ses;
 	char *temp = (char *) buffer;
@@ -211,10 +210,8 @@
 	buffer->Command = smb_command;
 	buffer->Flags = 0x00;	/* case sensitive */
 	buffer->Flags2 = SMBFLG2_KNOWS_LONG_NAMES;
-	tmp = cpu_to_le32(current->tgid);
-	buffer->Pid = tmp & 0xFFFF;
-	tmp >>= 16;
-	buffer->PidHigh = tmp & 0xFFFF;
+	buffer->Pid = cpu_to_le16((__u16)current->tgid);
+	buffer->PidHigh = cpu_to_le16((__u16)(current->tgid >> 16));
 	spin_lock(&GlobalMid_Lock);
 	GlobalMid++;
 	buffer->Mid = GlobalMid;
@@ -276,7 +273,7 @@
 		}
 		if (treeCon->Flags & SMB_SHARE_IS_IN_DFS)
 			buffer->Flags2 |= SMBFLG2_DFS;
-		if(treeCon->ses->server)
+		if((treeCon->ses) && (treeCon->ses->server))
 			if(treeCon->ses->server->secMode & 
 			  (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
 				buffer->Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
@@ -292,7 +289,7 @@
 {
 	/* Make sure that this really is an SMB, that it is a response, 
 	   and that the message ids match */
-	if ((*(unsigned int *) smb->Protocol == cpu_to_le32(0x424d53ff)) && 
+	if ((*(__le32 *) smb->Protocol == cpu_to_le32(0x424d53ff)) && 
 		(mid == smb->Mid)) {    
 		if(smb->Flags & SMBFLG_RESPONSE)
 			return 0;                    
@@ -304,7 +301,7 @@
 				cERROR(1, ("Rcvd Request not response "));         
 		}
 	} else { /* bad signature or mid */
-		if (*(unsigned int *) smb->Protocol != cpu_to_le32(0x424d53ff))
+		if (*(__le32 *) smb->Protocol != cpu_to_le32(0x424d53ff))
 			cERROR(1,
 			       ("Bad protocol string signature header %x ",
 				*(unsigned int *) smb->Protocol));
@@ -318,12 +315,12 @@
 int
 checkSMB(struct smb_hdr *smb, __u16 mid, int length)
 {
+	__u32 len = be32_to_cpu(smb->smb_buf_length);
 	cFYI(0,
 	     ("Entering checkSMB with Length: %x, smb_buf_length: %x ",
-	      length, ntohl(smb->smb_buf_length)));
-	if (((unsigned int)length < 2 + sizeof (struct smb_hdr))
-	    || (ntohl(smb->smb_buf_length) >
-		CIFS_MAX_MSGSIZE + MAX_CIFS_HDR_SIZE - 4)) {
+	      length, len));
+	if (((unsigned int)length < 2 + sizeof (struct smb_hdr)) ||
+	    (len > CIFS_MAX_MSGSIZE + MAX_CIFS_HDR_SIZE - 4)) {
 		if ((unsigned int)length < 2 + sizeof (struct smb_hdr)) {
 			cERROR(1, ("Length less than 2 + sizeof smb_hdr "));
 			if (((unsigned int)length >= sizeof (struct smb_hdr) - 1)
@@ -331,8 +328,7 @@
 				return 0;	/* some error cases do not return wct and bcc */
 
 		}
-		if (ntohl(smb->smb_buf_length) >
-		    CIFS_MAX_MSGSIZE + MAX_CIFS_HDR_SIZE - 4)
+		if (len > CIFS_MAX_MSGSIZE + MAX_CIFS_HDR_SIZE - 4)
 			cERROR(1,
 			       ("smb_buf_length greater than CIFS_MAX_MSGSIZE ... "));
 		cERROR(1,
@@ -344,8 +340,8 @@
 	if (checkSMBhdr(smb, mid))
 		return 1;
 
-	if ((4 + ntohl(smb->smb_buf_length) != smbCalcSize(smb))
-	    || (4 + ntohl(smb->smb_buf_length) != (unsigned int)length)) {
+	if ((4 + len != smbCalcSize(smb))
+	    || (4 + len != (unsigned int)length)) {
 		return 0;
 	} else {
 		cERROR(1, ("smbCalcSize %x ", smbCalcSize(smb)));
diff -Nru a/fs/cifs/netmisc.c b/fs/cifs/netmisc.c
--- a/fs/cifs/netmisc.c	2004-10-18 14:57:03 -07:00
+++ b/fs/cifs/netmisc.c	2004-10-18 14:57:03 -07:00
@@ -187,8 +187,8 @@
 	if (value > addr_class_max[end - bytes])
 		return 0;
 
-	address.s_addr = *((int *) bytes) | htonl(value);
-	*((int *)dst) = address.s_addr;
+	address.s_addr = *((__be32 *) bytes) | htonl(value);
+	*((__be32 *)dst) = address.s_addr;
 	return 1; /* success */
 }
 
@@ -810,16 +810,13 @@
 
 	if (smb->Flags2 & SMBFLG2_ERR_STATUS) {
 		/* translate the newer STATUS codes to old style errors and then to POSIX errors */
-		smb->Status.CifsError = le32_to_cpu(smb->Status.CifsError);
+		__u32 err = le32_to_cpu(smb->Status.CifsError);
 		if(cifsFYI)
-			cifs_print_status(smb->Status.CifsError);
-		ntstatus_to_dos(smb->Status.CifsError, &smberrclass,
-				&smberrcode);
+			cifs_print_status(err);
+		ntstatus_to_dos(err, &smberrclass, &smberrcode);
 	} else {
 		smberrclass = smb->Status.DosError.ErrorClass;
-		smb->Status.DosError.Error =
-		    le16_to_cpu(smb->Status.DosError.Error);
-		smberrcode = smb->Status.DosError.Error;
+		smberrcode = le16_to_cpu(smb->Status.DosError.Error);
 	}
 
 	/* old style errors */
diff -Nru a/fs/cifs/ntlmssp.h b/fs/cifs/ntlmssp.h
--- a/fs/cifs/ntlmssp.h	2004-10-18 14:55:54 -07:00
+++ b/fs/cifs/ntlmssp.h	2004-10-18 14:55:54 -07:00
@@ -23,10 +23,10 @@
 
 #define NTLMSSP_SIGNATURE "NTLMSSP"
 /* Message Types */
-#define NtLmNegotiate     1
-#define NtLmChallenge     2
-#define NtLmAuthenticate  3
-#define UnknownMessage    8
+#define NtLmNegotiate     cpu_to_le32(1)
+#define NtLmChallenge     cpu_to_le32(2)
+#define NtLmAuthenticate  cpu_to_le32(3)
+#define UnknownMessage    cpu_to_le32(8)
 
 /* Negotiate Flags */
 #define NTLMSSP_NEGOTIATE_UNICODE       0x01	// Text strings are in unicode
@@ -60,15 +60,15 @@
 /* appearance */
 
 typedef struct _SECURITY_BUFFER {
-	__u16 Length;
-	__u16 MaximumLength;
-	__u32 Buffer;		/* offset to buffer */
+	__le16 Length;
+	__le16 MaximumLength;
+	__le32 Buffer;		/* offset to buffer */
 } SECURITY_BUFFER;
 
 typedef struct _NEGOTIATE_MESSAGE {
 	__u8 Signature[sizeof (NTLMSSP_SIGNATURE)];
-	__u32 MessageType;     /* 1 */
-	__u32 NegotiateFlags;
+	__le32 MessageType;     /* 1 */
+	__le32 NegotiateFlags;
 	SECURITY_BUFFER DomainName;	/* RFC 1001 style and ASCII */
 	SECURITY_BUFFER WorkstationName;	/* RFC 1001 and ASCII */
 	char DomainString[0];
@@ -77,9 +77,9 @@
 
 typedef struct _CHALLENGE_MESSAGE {
 	__u8 Signature[sizeof (NTLMSSP_SIGNATURE)];
-	__u32 MessageType;   /* 2 */
+	__le32 MessageType;   /* 2 */
 	SECURITY_BUFFER TargetName;
-	__u32 NegotiateFlags;
+	__le32 NegotiateFlags;
 	__u8 Challenge[CIFS_CRYPTO_KEY_SIZE];
 	__u8 Reserved[8];
 	SECURITY_BUFFER TargetInfoArray;
@@ -87,14 +87,14 @@
 
 typedef struct _AUTHENTICATE_MESSAGE {
 	__u8 Signature[sizeof (NTLMSSP_SIGNATURE)];
-	__u32 MessageType;  /* 3 */
+	__le32 MessageType;  /* 3 */
 	SECURITY_BUFFER LmChallengeResponse;
 	SECURITY_BUFFER NtChallengeResponse;
 	SECURITY_BUFFER DomainName;
 	SECURITY_BUFFER UserName;
 	SECURITY_BUFFER WorkstationName;
 	SECURITY_BUFFER SessionKey;
-	__u32 NegotiateFlags;
+	__le32 NegotiateFlags;
 	char UserString[0];
 } AUTHENTICATE_MESSAGE, *PAUTHENTICATE_MESSAGE;
 
diff -Nru a/fs/cifs/transport.c b/fs/cifs/transport.c
--- a/fs/cifs/transport.c	2004-10-18 14:56:27 -07:00
+++ b/fs/cifs/transport.c	2004-10-18 14:56:27 -07:00
@@ -123,11 +123,12 @@
 	int i = 0;
 	struct msghdr smb_msg;
 	struct kvec iov;
+	unsigned len = smb_buf_length + 4;
 
 	if(ssocket == NULL)
 		return -ENOTSOCK; /* BB eventually add reconnect code here */
 	iov.iov_base = smb_buffer;
-	iov.iov_len = smb_buf_length + 4;
+	iov.iov_len = len;
 
 	smb_msg.msg_name = sin;
 	smb_msg.msg_namelen = sizeof (struct sockaddr);
@@ -142,10 +143,10 @@
 
 	smb_buffer->smb_buf_length = cpu_to_be32(smb_buffer->smb_buf_length);
 	cFYI(1, ("Sending smb of length %d ", smb_buf_length));
-	dump_smb(smb_buffer, smb_buf_length + 4);
+	dump_smb(smb_buffer, len);
 
-	while(iov.iov_len > 0) {
-		rc = kernel_sendmsg(ssocket, &smb_msg, &iov, 1, smb_buf_length + 4);
+	while (len > 0) {
+		rc = kernel_sendmsg(ssocket, &smb_msg, &iov, 1, len);
 		if ((rc == -ENOSPC) || (rc == -EAGAIN)) {
 			i++;
 			if(i > 60) {
@@ -163,6 +164,7 @@
 			break;
 		iov.iov_base += rc;
 		iov.iov_len -= rc;
+		len -= rc;
 	}
 
 	if (rc < 0) {
@@ -181,7 +183,7 @@
 {
 	int rc = 0;
 	unsigned int receive_len;
-	long timeout;
+	unsigned long timeout;
 	struct mid_q_entry *midQ;
 
 	if (ses == NULL) {
@@ -272,9 +274,6 @@
 		return -EIO;
 	}
 
-	if (in_buf->smb_buf_length > 12)
-		in_buf->Flags2 = cpu_to_le16(in_buf->Flags2);
-	
 	rc = cifs_sign_smb(in_buf, ses, &midQ->sequence_number);
 
 	midQ->midState = MID_REQUEST_SUBMITTED;
@@ -307,27 +306,29 @@
 	if (signal_pending(current)) {
 		/* if signal pending do not hold up user for full smb timeout
 		but we still give response a change to complete */
-		if(midQ->midState & MID_REQUEST_SUBMITTED) {
-			set_current_state(TASK_UNINTERRUPTIBLE);
-			timeout = sleep_on_timeout(&ses->server->response_q,2 * HZ);
-		}
-	} else { /* using normal timeout */
-		/* timeout = wait_event_interruptible_timeout(ses->server->response_q,
+		timeout = 2 * HZ;
+		
+	}   
+
+	/* No user interrupts in wait - wreaks havoc with performance */
+	if(timeout != MAX_SCHEDULE_TIMEOUT) {
+		timeout += jiffies;
+		wait_event(ses->server->response_q,
 			(midQ->midState & MID_RESPONSE_RECEIVED) || 
+			time_after(jiffies, timeout) || 
 			((ses->server->tcpStatus != CifsGood) &&
-			 (ses->server->tcpStatus != CifsNew)),
-			timeout); */ 
-		/* Can not allow user interrupts- wreaks havoc with performance */
-		if(midQ->midState & MID_REQUEST_SUBMITTED) {
-			set_current_state(TASK_UNINTERRUPTIBLE);
-			timeout = sleep_on_timeout(&ses->server->response_q,timeout);
-		}
+			 (ses->server->tcpStatus != CifsNew)));
+	} else {
+		wait_event(ses->server->response_q,
+			(midQ->midState & MID_RESPONSE_RECEIVED) || 
+			((ses->server->tcpStatus != CifsGood) &&
+			 (ses->server->tcpStatus != CifsNew)));
 	}
-    
+
 	spin_lock(&GlobalMid_Lock);
 	if (midQ->resp_buf) {
 		spin_unlock(&GlobalMid_Lock);
-		receive_len = be32_to_cpu(midQ->resp_buf->smb_buf_length);
+		receive_len = be32_to_cpu(*(__be32 *)midQ->resp_buf);
 	} else {
 		cERROR(1,("No response buffer"));
 		if(midQ->midState == MID_REQUEST_SUBMITTED) {
@@ -366,28 +367,19 @@
 
 		if (midQ->resp_buf && out_buf
 		    && (midQ->midState == MID_RESPONSE_RECEIVED)) {
-			memcpy(out_buf, midQ->resp_buf,
-			       receive_len +
-			       4 /* include 4 byte RFC1001 header */ );
+			out_buf->smb_buf_length = receive_len;
+			memcpy((char *)out_buf + 4,
+			       (char *)midQ->resp_buf + 4,
+			       receive_len);
 
 			dump_smb(out_buf, 92);
 			/* convert the length into a more usable form */
-			out_buf->smb_buf_length =
-			    be32_to_cpu(out_buf->smb_buf_length);
-			if((out_buf->smb_buf_length > 24) &&
+			if((receive_len > 24) &&
 			   (ses->server->secMode & (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))) {
 				rc = cifs_verify_signature(out_buf, ses->mac_signing_key,midQ->sequence_number); /* BB fix BB */
 				if(rc)
 					cFYI(1,("Unexpected signature received from server"));
 			}
-
-			if (out_buf->smb_buf_length > 12)
-				out_buf->Flags2 = le16_to_cpu(out_buf->Flags2);
-			if (out_buf->smb_buf_length > 28)
-				out_buf->Pid = le16_to_cpu(out_buf->Pid);
-			if (out_buf->smb_buf_length > 28)
-				out_buf->PidHigh =
-				    le16_to_cpu(out_buf->PidHigh);
 
 			*pbytes_returned = out_buf->smb_buf_length;
 
diff -Nru a/fs/coda/coda_linux.c b/fs/coda/coda_linux.c
--- a/fs/coda/coda_linux.c	2004-10-18 14:55:53 -07:00
+++ b/fs/coda/coda_linux.c	2004-10-18 14:55:53 -07:00
@@ -28,7 +28,7 @@
 char * coda_f2s(struct CodaFid *f)
 {
 	static char s[60];
-#ifdef CODA_FS_OLD_API
+#ifdef CONFIG_CODA_FS_OLD_API
  	sprintf(s, "(%08x.%08x.%08x)", f->opaque[0], f->opaque[1], f->opaque[2]);
 #else
  	sprintf(s, "(%08x.%08x.%08x.%08x)", f->opaque[0], f->opaque[1], f->opaque[2], f->opaque[3]);
diff -Nru a/fs/coda/file.c b/fs/coda/file.c
--- a/fs/coda/file.c	2004-10-18 14:56:28 -07:00
+++ b/fs/coda/file.c	2004-10-18 14:56:28 -07:00
@@ -45,6 +45,23 @@
 }
 
 static ssize_t
+coda_file_sendfile(struct file *coda_file, loff_t *ppos, size_t count,
+		   read_actor_t actor, void *target)
+{
+	struct coda_file_info *cfi;
+	struct file *host_file;
+
+	cfi = CODA_FTOC(coda_file);
+	BUG_ON(!cfi || cfi->cfi_magic != CODA_MAGIC);
+	host_file = cfi->cfi_container;
+
+	if (!host_file->f_op || !host_file->f_op->sendfile)
+		return -EINVAL;
+
+	return host_file->f_op->sendfile(host_file, ppos, count, actor, target);
+}
+
+static ssize_t
 coda_file_write(struct file *coda_file, const char __user *buf, size_t count, loff_t *ppos)
 {
 	struct inode *host_inode, *coda_inode = coda_file->f_dentry->d_inode;
@@ -278,5 +295,6 @@
 	.flush		= coda_flush,
 	.release	= coda_release,
 	.fsync		= coda_fsync,
+	.sendfile	= coda_file_sendfile,
 };
 
diff -Nru a/fs/coda/inode.c b/fs/coda/inode.c
--- a/fs/coda/inode.c	2004-10-18 14:56:32 -07:00
+++ b/fs/coda/inode.c	2004-10-18 14:56:32 -07:00
@@ -69,7 +69,7 @@
 {
 	coda_inode_cachep = kmem_cache_create("coda_inode_cache",
 				sizeof(struct coda_inode_info),
-				0, SLAB_HWCACHE_ALIGN|SLAB_RECLAIM_ACCOUNT,
+				0, SLAB_RECLAIM_ACCOUNT,
 				init_once, NULL);
 	if (coda_inode_cachep == NULL)
 		return -ENOMEM;
diff -Nru a/fs/coda/psdev.c b/fs/coda/psdev.c
--- a/fs/coda/psdev.c	2004-10-18 14:56:33 -07:00
+++ b/fs/coda/psdev.c	2004-10-18 14:56:33 -07:00
@@ -405,7 +405,7 @@
 	int status;
 	int i;
 	printk(KERN_INFO "Coda Kernel/Venus communications, "
-#ifdef CODA_FS_OLD_API
+#ifdef CONFIG_CODA_FS_OLD_API
 	       "v5.3.20"
 #else
 	       "v6.0.0"
diff -Nru a/fs/coda/upcall.c b/fs/coda/upcall.c
--- a/fs/coda/upcall.c	2004-10-18 14:56:49 -07:00
+++ b/fs/coda/upcall.c	2004-10-18 14:56:49 -07:00
@@ -55,7 +55,7 @@
         inp->ih.opcode = opcode;
 	inp->ih.pid = current->pid;
 	inp->ih.pgid = process_group(current);
-#ifdef CODA_FS_OLD_API
+#ifdef CONFIG_CODA_FS_OLD_API
 	memset(&inp->ih.cred, 0, sizeof(struct coda_cred));
 	inp->ih.cred.cr_fsuid = current->fsuid;
 #else
@@ -172,7 +172,7 @@
         union inputArgs *inp;
         union outputArgs *outp;
         int insize, outsize, error;
-#ifdef CODA_FS_OLD_API
+#ifdef CONFIG_CODA_FS_OLD_API
 	struct coda_cred cred = { 0, };
 	cred.cr_fsuid = uid;
 #endif
@@ -180,7 +180,7 @@
 	insize = SIZE(store);
 	UPARG(CODA_STORE);
 	
-#ifdef CODA_FS_OLD_API
+#ifdef CONFIG_CODA_FS_OLD_API
 	memcpy(&(inp->ih.cred), &cred, sizeof(cred));
 #else
 	inp->ih.uid = uid;
@@ -219,7 +219,7 @@
 	union inputArgs *inp;
 	union outputArgs *outp;
 	int insize, outsize, error;
-#ifdef CODA_FS_OLD_API
+#ifdef CONFIG_CODA_FS_OLD_API
 	struct coda_cred cred = { 0, };
 	cred.cr_fsuid = uid;
 #endif
@@ -227,7 +227,7 @@
 	insize = SIZE(release);
 	UPARG(CODA_CLOSE);
 	
-#ifdef CODA_FS_OLD_API
+#ifdef CONFIG_CODA_FS_OLD_API
 	memcpy(&(inp->ih.cred), &cred, sizeof(cred));
 #else
 	inp->ih.uid = uid;
diff -Nru a/fs/compat.c b/fs/compat.c
--- a/fs/compat.c	2004-10-18 14:56:29 -07:00
+++ b/fs/compat.c	2004-10-18 14:56:29 -07:00
@@ -41,6 +41,7 @@
 #include <linux/nfsd/nfsd.h>
 #include <linux/nfsd/syscall.h>
 #include <linux/personality.h>
+#include <linux/rwsem.h>
 
 #include <net/sock.h>		/* siocdevprivate_ioctl */
 
@@ -247,7 +248,8 @@
 /* ioctl32 stuff, used by sparc64, parisc, s390x, ppc64, x86_64, MIPS */
 
 #define IOCTL_HASHSIZE 256
-struct ioctl_trans *ioctl32_hash_table[IOCTL_HASHSIZE];
+static struct ioctl_trans *ioctl32_hash_table[IOCTL_HASHSIZE];
+static DECLARE_RWSEM(ioctl32_sem);
 
 extern struct ioctl_trans ioctl_start[];
 extern int ioctl_table_size;
@@ -291,8 +293,8 @@
 
 __initcall(init_sys32_ioctl);
 
-int register_ioctl32_conversion(unsigned int cmd, int (*handler)(unsigned int,
-				unsigned int, unsigned long, struct file *))
+int register_ioctl32_conversion(unsigned int cmd,
+				ioctl_trans_handler_t handler)
 {
 	struct ioctl_trans *t;
 	struct ioctl_trans *new_t;
@@ -302,12 +304,12 @@
 	if (!new_t)
 		return -ENOMEM;
 
-	lock_kernel(); 
+	down_write(&ioctl32_sem);
 	for (t = ioctl32_hash_table[hash]; t; t = t->next) {
 		if (t->cmd == cmd) {
 			printk(KERN_ERR "Trying to register duplicated ioctl32 "
 					"handler %x\n", cmd);
-			unlock_kernel();
+			up_write(&ioctl32_sem);
 			kfree(new_t);
 			return -EINVAL; 
 		}
@@ -317,7 +319,7 @@
 	new_t->handler = handler;
 	ioctl32_insert_translation(new_t);
 
-	unlock_kernel();
+	up_write(&ioctl32_sem);
 	return 0;
 }
 EXPORT_SYMBOL(register_ioctl32_conversion);
@@ -337,11 +339,11 @@
 	unsigned long hash = ioctl32_hash(cmd);
 	struct ioctl_trans *t, *t1;
 
-	lock_kernel(); 
+	down_write(&ioctl32_sem);
 
 	t = ioctl32_hash_table[hash];
 	if (!t) { 
-		unlock_kernel();
+		up_write(&ioctl32_sem);
 		return -EINVAL;
 	} 
 
@@ -351,7 +353,7 @@
 			       __builtin_return_address(0), cmd);
 		} else { 
 			ioctl32_hash_table[hash] = t->next;
-			unlock_kernel();
+			up_write(&ioctl32_sem);
 			kfree(t);
 			return 0;
 		}
@@ -366,7 +368,7 @@
 				goto out;
 			} else { 
 				t->next = t1->next;
-				unlock_kernel();
+				up_write(&ioctl32_sem);
 				kfree(t1);
 				return 0;
 			}
@@ -376,7 +378,7 @@
 	printk(KERN_ERR "Trying to free unknown 32bit ioctl handler %x\n",
 				cmd);
 out:
-	unlock_kernel();
+	up_write(&ioctl32_sem);
 	return -EINVAL;
 }
 EXPORT_SYMBOL(unregister_ioctl32_conversion); 
@@ -397,7 +399,7 @@
 		goto out;
 	}
 
-	lock_kernel();
+	down_read(&ioctl32_sem);
 
 	t = ioctl32_hash_table[ioctl32_hash (cmd)];
 
@@ -405,14 +407,16 @@
 		t = t->next;
 	if (t) {
 		if (t->handler) { 
+			lock_kernel();
 			error = t->handler(fd, cmd, arg, filp);
 			unlock_kernel();
+			up_read(&ioctl32_sem);
 		} else {
-			unlock_kernel();
+			up_read(&ioctl32_sem);
 			error = sys_ioctl(fd, cmd, arg);
 		}
 	} else {
-		unlock_kernel();
+		up_read(&ioctl32_sem);
 		if (cmd >= SIOCDEVPRIVATE && cmd <= (SIOCDEVPRIVATE + 15)) {
 			error = siocdevprivate_ioctl(fd, cmd, arg);
 		} else {
@@ -429,6 +433,8 @@
 			       		fn = d_path(filp->f_dentry,
 						filp->f_vfsmnt, path,
 						PAGE_SIZE);
+					if (IS_ERR(fn))
+						fn = "?";
 				}
 
 				sprintf(buf,"'%c'", (cmd>>24) & 0x3f);
@@ -522,8 +528,15 @@
 		ret = sys_fcntl(fd, cmd, (unsigned long)&f);
 		set_fs(old_fs);
 		if ((cmd == F_GETLK) && (ret == 0)) {
+			/* POSIX-2001 now defines negative l_len */
+			if (f.l_len < 0) {
+				f.l_start += f.l_len;
+				f.l_len = -f.l_len;
+			}
+			if (f.l_start < 0)
+				return -EINVAL;
 			if ((f.l_start >= COMPAT_OFF_T_MAX) ||
-			    ((f.l_start + f.l_len) >= COMPAT_OFF_T_MAX))
+			    ((f.l_start + f.l_len) > COMPAT_OFF_T_MAX))
 				ret = -EOVERFLOW;
 			if (ret == 0)
 				ret = put_compat_flock(&f, compat_ptr(arg));
@@ -543,8 +556,15 @@
 				(unsigned long)&f);
 		set_fs(old_fs);
 		if ((cmd == F_GETLK64) && (ret == 0)) {
+			/* POSIX-2001 now defines negative l_len */
+			if (f.l_len < 0) {
+				f.l_start += f.l_len;
+				f.l_len = -f.l_len;
+			}
+			if (f.l_start < 0)
+				return -EINVAL;
 			if ((f.l_start >= COMPAT_LOFF_T_MAX) ||
-			    ((f.l_start + f.l_len) >= COMPAT_LOFF_T_MAX))
+			    ((f.l_start + f.l_len) > COMPAT_LOFF_T_MAX))
 				ret = -EOVERFLOW;
 			if (ret == 0)
 				ret = put_compat_flock64(&f, compat_ptr(arg));
@@ -979,19 +999,14 @@
 	dirent = buf->previous;
 
 	if (dirent) {
-		if (__put_user(offset, (u32 __user *)&dirent->d_off))
-			goto efault;
-		if (__put_user(offset >> 32,
-				((u32 __user *)&dirent->d_off) + 1))
+		if (__put_user_unaligned(offset, &dirent->d_off))
 			goto efault;
 	}
 	dirent = buf->current_dir;
-	if ((__put_user(ino, (u32 __user *)&dirent->d_ino))
-	 || (__put_user(ino >> 32, ((u32 __user *)&dirent->d_ino) + 1)))
+	if (__put_user_unaligned(ino, &dirent->d_ino))
 		goto efault;
 	off = 0;
-	if ((__put_user(off, (u32 __user *)&dirent->d_off))
-	 || (__put_user(off >> 32, ((u32 __user *)&dirent->d_off) + 1)))
+	if (__put_user_unaligned(off, &dirent->d_off))
 		goto efault;
 	if (__put_user(reclen, &dirent->d_reclen))
 		goto efault;
@@ -1040,8 +1055,7 @@
 	lastdirent = buf.previous;
 	if (lastdirent) {
 		typeof(lastdirent->d_off) d_off = file->f_pos;
-		__put_user(d_off, (u32 __user *)&lastdirent->d_off);
-		__put_user(d_off >> 32, ((u32 __user *)&lastdirent->d_off) + 1);
+		__put_user_unaligned(d_off, &lastdirent->d_off);
 		error = count - buf.count;
 	}
 
@@ -1368,97 +1382,99 @@
 	compat_uptr_t __user *envp,
 	struct pt_regs * regs)
 {
-	struct linux_binprm bprm;
+	struct linux_binprm *bprm;
 	struct file *file;
 	int retval;
 	int i;
 
-	sched_balance_exec();
-
 	file = open_exec(filename);
 
 	retval = PTR_ERR(file);
 	if (IS_ERR(file))
 		return retval;
 
-	bprm.p = PAGE_SIZE*MAX_ARG_PAGES-sizeof(void *);
-	memset(bprm.page, 0, MAX_ARG_PAGES*sizeof(bprm.page[0]));
+	sched_exec();
 
-	bprm.file = file;
-	bprm.filename = filename;
-	bprm.interp = filename;
-	bprm.sh_bang = 0;
-	bprm.loader = 0;
-	bprm.exec = 0;
-	bprm.security = NULL;
-	bprm.mm = mm_alloc();
 	retval = -ENOMEM;
-	if (!bprm.mm)
+	bprm = kmalloc(sizeof(*bprm), GFP_KERNEL);
+	if (!bprm)
+		goto out_ret;
+	memset(bprm, 0, sizeof(*bprm));
+
+	bprm->p = PAGE_SIZE*MAX_ARG_PAGES-sizeof(void *);
+	bprm->file = file;
+	bprm->filename = filename;
+	bprm->interp = filename;
+	bprm->mm = mm_alloc();
+	if (!bprm->mm)
 		goto out_file;
 
-	retval = init_new_context(current, bprm.mm);
+	retval = init_new_context(current, bprm->mm);
 	if (retval < 0)
 		goto out_mm;
 
-	bprm.argc = compat_count(argv, bprm.p / sizeof(compat_uptr_t));
-	if ((retval = bprm.argc) < 0)
+	bprm->argc = compat_count(argv, bprm->p / sizeof(compat_uptr_t));
+	if ((retval = bprm->argc) < 0)
 		goto out_mm;
 
-	bprm.envc = compat_count(envp, bprm.p / sizeof(compat_uptr_t));
-	if ((retval = bprm.envc) < 0)
+	bprm->envc = compat_count(envp, bprm->p / sizeof(compat_uptr_t));
+	if ((retval = bprm->envc) < 0)
 		goto out_mm;
 
-	retval = security_bprm_alloc(&bprm);
+	retval = security_bprm_alloc(bprm);
 	if (retval)
 		goto out;
 
-	retval = prepare_binprm(&bprm);
+	retval = prepare_binprm(bprm);
 	if (retval < 0)
 		goto out;
 
-	retval = copy_strings_kernel(1, &bprm.filename, &bprm);
+	retval = copy_strings_kernel(1, &bprm->filename, bprm);
 	if (retval < 0)
 		goto out;
 
-	bprm.exec = bprm.p;
-	retval = compat_copy_strings(bprm.envc, envp, &bprm);
+	bprm->exec = bprm->p;
+	retval = compat_copy_strings(bprm->envc, envp, bprm);
 	if (retval < 0)
 		goto out;
 
-	retval = compat_copy_strings(bprm.argc, argv, &bprm);
+	retval = compat_copy_strings(bprm->argc, argv, bprm);
 	if (retval < 0)
 		goto out;
 
-	retval = search_binary_handler(&bprm,regs);
+	retval = search_binary_handler(bprm, regs);
 	if (retval >= 0) {
-		free_arg_pages(&bprm);
+		free_arg_pages(bprm);
 
 		/* execve success */
-		security_bprm_free(&bprm);
+		security_bprm_free(bprm);
+		kfree(bprm);
 		return retval;
 	}
 
 out:
 	/* Something went wrong, return the inode and free the argument pages*/
 	for (i = 0 ; i < MAX_ARG_PAGES ; i++) {
-		struct page * page = bprm.page[i];
+		struct page * page = bprm->page[i];
 		if (page)
 			__free_page(page);
 	}
 
-	if (bprm.security)
-		security_bprm_free(&bprm);
+	if (bprm->security)
+		security_bprm_free(bprm);
 
 out_mm:
-	if (bprm.mm)
-		mmdrop(bprm.mm);
+	if (bprm->mm)
+		mmdrop(bprm->mm);
 
 out_file:
-	if (bprm.file) {
-		allow_write_access(bprm.file);
-		fput(bprm.file);
+	if (bprm->file) {
+		allow_write_access(bprm->file);
+		fput(bprm->file);
 	}
+	kfree(bprm);
 
+out_ret:
 	return retval;
 }
 
diff -Nru a/fs/compat_ioctl.c b/fs/compat_ioctl.c
--- a/fs/compat_ioctl.c	2004-10-18 14:57:04 -07:00
+++ b/fs/compat_ioctl.c	2004-10-18 14:57:04 -07:00
@@ -15,6 +15,7 @@
 #include <linux/types.h>
 #include <linux/compat.h>
 #include <linux/kernel.h>
+#include <linux/compiler.h>
 #include <linux/sched.h>
 #include <linux/smp.h>
 #include <linux/smp_lock.h>
@@ -115,6 +116,8 @@
 #include <linux/filter.h>
 #include <linux/msdos_fs.h>
 
+#include <linux/hiddev.h>
+
 #undef INCLUDES
 #endif
 
@@ -407,6 +410,7 @@
 	return err;
 }
 
+#ifdef CONFIG_NET
 static int do_siocgstamp(unsigned int fd, unsigned int cmd, unsigned long arg)
 {
 	struct compat_timeval __user *up = compat_ptr(arg);
@@ -461,7 +465,6 @@
         compat_caddr_t  ifcbuf;
 };
 
-#ifdef CONFIG_NET
 static int dev_ifname32(unsigned int fd, unsigned int cmd, unsigned long arg)
 {
 	struct net_device *dev;
@@ -481,7 +484,6 @@
 	err = copy_to_user(compat_ptr(arg), &ifr32, sizeof(ifr32));
 	return (err ? -EFAULT : 0);
 }
-#endif
 
 static int dev_ifconf(unsigned int fd, unsigned int cmd, unsigned long arg)
 {
@@ -797,6 +799,7 @@
 
 	return ret;
 }
+#endif
 
 struct hd_geometry32 {
 	unsigned char heads;
@@ -1872,7 +1875,8 @@
         return -EINVAL;
 }
 
-static int ret_einval(unsigned int fd, unsigned int cmd, unsigned long arg)
+static __attribute_used__ int 
+ret_einval(unsigned int fd, unsigned int cmd, unsigned long arg)
 {
 	return -EINVAL;
 }
@@ -3162,7 +3166,6 @@
 HANDLE_IOCTL(MEMWRITEOOB32, mtd_rw_oob)
 #ifdef CONFIG_NET
 HANDLE_IOCTL(SIOCGIFNAME, dev_ifname32)
-#endif
 HANDLE_IOCTL(SIOCGIFCONF, dev_ifconf)
 HANDLE_IOCTL(SIOCGIFFLAGS, dev_ifsioc)
 HANDLE_IOCTL(SIOCSIFFLAGS, dev_ifsioc)
@@ -3206,6 +3209,7 @@
 /* Note SIOCRTMSG is no longer, so this is safe and * the user would have seen just an -EINVAL anyways. */
 HANDLE_IOCTL(SIOCRTMSG, ret_einval)
 HANDLE_IOCTL(SIOCGSTAMP, do_siocgstamp)
+#endif
 HANDLE_IOCTL(HDIO_GETGEO, hdio_getgeo)
 HANDLE_IOCTL(BLKRAGET, w_long)
 HANDLE_IOCTL(BLKGETSIZE, w_long)
diff -Nru a/fs/dcache.c b/fs/dcache.c
--- a/fs/dcache.c	2004-10-18 14:55:55 -07:00
+++ b/fs/dcache.c	2004-10-18 14:55:55 -07:00
@@ -144,6 +144,8 @@
 		return;
 
 repeat:
+	if (atomic_read(&dentry->d_count) == 1)
+		might_sleep();
 	if (!atomic_dec_and_lock(&dentry->d_count, &dcache_lock))
 		return;
 
@@ -286,12 +288,11 @@
  * any other hashed alias over that one.
  */
 
-struct dentry * d_find_alias(struct inode *inode)
+static struct dentry * __d_find_alias(struct inode *inode, int want_discon)
 {
 	struct list_head *head, *next, *tmp;
 	struct dentry *alias, *discon_alias=NULL;
 
-	spin_lock(&dcache_lock);
 	head = &inode->i_dentry;
 	next = inode->i_dentry.next;
 	while (next != head) {
@@ -302,19 +303,26 @@
  		if (!d_unhashed(alias)) {
 			if (alias->d_flags & DCACHE_DISCONNECTED)
 				discon_alias = alias;
-			else {
+			else if (!want_discon) {
 				__dget_locked(alias);
-				spin_unlock(&dcache_lock);
 				return alias;
 			}
 		}
 	}
 	if (discon_alias)
 		__dget_locked(discon_alias);
-	spin_unlock(&dcache_lock);
 	return discon_alias;
 }
 
+struct dentry * d_find_alias(struct inode *inode)
+{
+	struct dentry *de;
+	spin_lock(&dcache_lock);
+	de = __d_find_alias(inode, 0);
+	spin_unlock(&dcache_lock);
+	return de;
+}
+
 /*
  *	Try to kill dentries associated with this inode.
  * WARNING: you must own a reference to inode.
@@ -613,7 +621,7 @@
  *
  * Prune the dentries that are anonymous
  *
- * parsing d_hash list does not read_barrier_depends() as it
+ * parsing d_hash list does not hlist_for_each_rcu() as it
  * done under dcache_lock.
  *
  */
@@ -833,33 +841,27 @@
 	tmp->d_parent = tmp; /* make sure dput doesn't croak */
 	
 	spin_lock(&dcache_lock);
-	if (S_ISDIR(inode->i_mode) && !list_empty(&inode->i_dentry)) {
-		/* A directory can only have one dentry.
-		 * This (now) has one, so use it.
-		 */
-		res = list_entry(inode->i_dentry.next, struct dentry, d_alias);
-		__dget_locked(res);
-	} else {
+	res = __d_find_alias(inode, 0);
+	if (!res) {
 		/* attach a disconnected dentry */
 		res = tmp;
 		tmp = NULL;
-		if (res) {
-			spin_lock(&res->d_lock);
-			res->d_sb = inode->i_sb;
-			res->d_parent = res;
-			res->d_inode = inode;
+		spin_lock(&res->d_lock);
+		res->d_sb = inode->i_sb;
+		res->d_parent = res;
+		res->d_inode = inode;
+
+		/*
+		 * Set d_bucket to an "impossible" bucket address so
+		 * that d_move() doesn't get a false positive
+		 */
+		res->d_bucket = NULL;
+		res->d_flags |= DCACHE_DISCONNECTED;
+		res->d_flags &= ~DCACHE_UNHASHED;
+		list_add(&res->d_alias, &inode->i_dentry);
+		hlist_add_head(&res->d_hash, &inode->i_sb->s_anon);
+		spin_unlock(&res->d_lock);
 
-			/*
-			 * Set d_bucket to an "impossible" bucket address so
-			 * that d_move() doesn't get a false positive
-			 */
-			res->d_bucket = NULL;
-			res->d_flags |= DCACHE_DISCONNECTED;
-			res->d_flags &= ~DCACHE_UNHASHED;
-			list_add(&res->d_alias, &inode->i_dentry);
-			hlist_add_head(&res->d_hash, &inode->i_sb->s_anon);
-			spin_unlock(&res->d_lock);
-		}
 		inode = NULL; /* don't drop reference */
 	}
 	spin_unlock(&dcache_lock);
@@ -881,7 +883,7 @@
  * DCACHE_DISCONNECTED), then d_move that in place of the given dentry
  * and return it, else simply d_add the inode to the dentry and return NULL.
  *
- * This is (will be) needed in the lookup routine of any filesystem that is exportable
+ * This is needed in the lookup routine of any filesystem that is exportable
  * (via knfsd) so that we can build dcache paths to directories effectively.
  *
  * If a dentry was found and moved, then it is returned.  Otherwise NULL
@@ -892,11 +894,11 @@
 {
 	struct dentry *new = NULL;
 
-	if (inode && S_ISDIR(inode->i_mode)) {
+	if (inode) {
 		spin_lock(&dcache_lock);
-		if (!list_empty(&inode->i_dentry)) {
-			new = list_entry(inode->i_dentry.next, struct dentry, d_alias);
-			__dget_locked(new);
+		new = __d_find_alias(inode, 1);
+		if (new) {
+			BUG_ON(!(new->d_flags & DCACHE_DISCONNECTED));
 			spin_unlock(&dcache_lock);
 			security_d_instantiate(new, inode);
 			d_rehash(dentry);
@@ -970,11 +972,10 @@
 
 	rcu_read_lock();
 	
-	hlist_for_each (node, head) { 
+	hlist_for_each_rcu(node, head) {
 		struct dentry *dentry; 
 		struct qstr *qstr;
 
-		smp_read_barrier_depends();
 		dentry = hlist_entry(node, struct dentry, d_hash);
 
 		smp_rmb();
@@ -1001,8 +1002,7 @@
 		if (dentry->d_parent != parent)
 			goto next;
 
-		qstr = &dentry->d_name;
-		smp_read_barrier_depends();
+		qstr = rcu_dereference(&dentry->d_name);
 		if (parent->d_op && parent->d_op->d_compare) {
 			if (parent->d_op->d_compare(parent, qstr, name))
 				goto next;
@@ -1055,7 +1055,7 @@
 	spin_lock(&dcache_lock);
 	base = d_hash(dparent, dentry->d_name.hash);
 	hlist_for_each(lhp,base) { 
-		/* read_barrier_depends() not required for d_hash list
+		/* hlist_for_each_rcu() not required for d_hash list
 		 * as it is parsed under dcache_lock
 		 */
 		if (dentry == hlist_entry(lhp, struct dentry, d_hash)) {
diff -Nru a/fs/devpts/inode.c b/fs/devpts/inode.c
--- a/fs/devpts/inode.c	2004-10-18 14:56:18 -07:00
+++ b/fs/devpts/inode.c	2004-10-18 14:56:18 -07:00
@@ -179,8 +179,12 @@
 	struct dentry *dentry = get_node(number);
 	struct tty_struct *tty;
 
-	tty = (IS_ERR(dentry) || !dentry->d_inode) ? NULL :
-			dentry->d_inode->u.generic_ip;
+	tty = NULL;
+	if (!IS_ERR(dentry)) {
+		if (dentry->d_inode)
+			tty = dentry->d_inode->u.generic_ip;
+		dput(dentry);
+	}
 
 	up(&devpts_root->d_inode->i_sem);
 
diff -Nru a/fs/direct-io.c b/fs/direct-io.c
--- a/fs/direct-io.c	2004-10-18 14:56:33 -07:00
+++ b/fs/direct-io.c	2004-10-18 14:56:33 -07:00
@@ -53,9 +53,12 @@
  * If blkfactor is zero then the user's request was aligned to the filesystem's
  * blocksize.
  *
- * needs_locking is set for regular files on direct-IO-naive filesystems.  It
- * determines whether we need to do the fancy locking which prevents direct-IO
- * from being able to read uninitialised disk blocks.
+ * lock_type is DIO_LOCKING for regular files on direct-IO-naive filesystems.
+ * This determines whether we need to do the fancy locking which prevents
+ * direct-IO from being able to read uninitialised disk blocks.  If its zero
+ * (blockdev) this locking is not done, and if it is DIO_OWN_LOCKING i_sem is
+ * not held for the entire direct write (taken briefly, initially, during a
+ * direct read though, but its never held for the duration of a direct-IO).
  */
 
 struct dio {
@@ -63,7 +66,7 @@
 	struct bio *bio;		/* bio under assembly */
 	struct inode *inode;
 	int rw;
-	int needs_locking;		/* doesn't change */
+	int lock_type;			/* doesn't change */
 	unsigned blkbits;		/* doesn't change */
 	unsigned blkfactor;		/* When we're using an alignment which
 					   is finer than the filesystem's soft
@@ -212,7 +215,7 @@
 {
 	if (dio->end_io && dio->result)
 		dio->end_io(dio->inode, offset, bytes, dio->map_bh.b_private);
-	if (dio->needs_locking)
+	if (dio->lock_type != DIO_NO_LOCKING)
 		up_read(&dio->inode->i_alloc_sem);
 }
 
@@ -235,7 +238,8 @@
 			dio_complete(dio, dio->block_in_file << dio->blkbits,
 					dio->result);
 			/* Complete AIO later if falling back to buffered i/o */
-			if (dio->result == dio->size || dio->rw == READ) {
+			if (dio->result == dio->size ||
+				((dio->rw == READ) && dio->result)) {
 				aio_complete(dio->iocb, dio->result, 0);
 				kfree(dio);
 				return;
@@ -492,7 +496,7 @@
 	unsigned long fs_count;	/* Number of filesystem-sized blocks */
 	unsigned long dio_count;/* Number of dio_block-sized blocks */
 	unsigned long blkmask;
-	int beyond_eof = 0;
+	int create;
 
 	/*
 	 * If there was a memory error and we've overwritten all the
@@ -510,10 +514,13 @@
 		if (dio_count & blkmask)	
 			fs_count++;
 
-		if (dio->needs_locking) {
-			if (dio->block_in_file >= (i_size_read(dio->inode) >>
+		create = dio->rw == WRITE;
+		if (dio->lock_type == DIO_LOCKING) {
+			if (dio->block_in_file < (i_size_read(dio->inode) >>
 							dio->blkbits))
-				beyond_eof = 1;
+				create = 0;
+		} else if (dio->lock_type == DIO_NO_LOCKING) {
+			create = 0;
 		}
 		/*
 		 * For writes inside i_size we forbid block creations: only
@@ -522,7 +529,7 @@
 		 * writes.
 		 */
 		ret = (*dio->get_blocks)(dio->inode, fs_startblk, fs_count,
-				map_bh, (dio->rw == WRITE) && beyond_eof);
+						map_bh, create);
 	}
 	return ret;
 }
@@ -561,7 +568,11 @@
 	ret = bio_add_page(dio->bio, dio->cur_page,
 			dio->cur_page_len, dio->cur_page_offset);
 	if (ret == dio->cur_page_len) {
-		dio->pages_in_io--;
+		/*
+		 * Decrement count only, if we are done with this page
+		 */
+		if ((dio->cur_page_len + dio->cur_page_offset) == PAGE_SIZE)
+			dio->pages_in_io--;
 		page_cache_get(dio->cur_page);
 		dio->final_block_in_bio = dio->cur_page_block +
 			(dio->cur_page_len >> dio->blkbits);
@@ -953,9 +964,21 @@
 	dio->bio_list = NULL;
 	dio->waiter = NULL;
 
-	dio->pages_in_io = 0;
-	for (seg = 0; seg < nr_segs; seg++) 
-		dio->pages_in_io += (iov[seg].iov_len >> blkbits) + 2; 
+	/*
+	 * In case of non-aligned buffers, we may need 2 more
+	 * pages since we need to zero out first and last block.
+	 */
+	if (unlikely(dio->blkfactor))
+		dio->pages_in_io = 2;
+	else
+		dio->pages_in_io = 0;
+
+	for (seg = 0; seg < nr_segs; seg++) {
+		user_addr = (unsigned long)iov[seg].iov_base;
+		dio->pages_in_io +=
+			((user_addr+iov[seg].iov_len +PAGE_SIZE-1)/PAGE_SIZE
+				- user_addr/PAGE_SIZE);
+	}
 
 	for (seg = 0; seg < nr_segs; seg++) {
 		user_addr = (unsigned long)iov[seg].iov_base;
@@ -1024,7 +1047,7 @@
 	 * we can let i_sem go now that its achieved its purpose
 	 * of protecting us from looking up uninitialized blocks.
 	 */
-	if ((rw == READ) && dio->needs_locking)
+	if ((rw == READ) && (dio->lock_type == DIO_LOCKING))
 		up(&dio->inode->i_sem);
 
 	/*
@@ -1111,7 +1134,7 @@
 __blockdev_direct_IO(int rw, struct kiocb *iocb, struct inode *inode,
 	struct block_device *bdev, const struct iovec *iov, loff_t offset, 
 	unsigned long nr_segs, get_blocks_t get_blocks, dio_iodone_t end_io,
-	int needs_special_locking)
+	int dio_lock_type)
 {
 	int seg;
 	size_t size;
@@ -1122,7 +1145,6 @@
 	ssize_t retval = -EINVAL;
 	loff_t end = offset;
 	struct dio *dio;
-	int needs_locking;
 
 	if (bdev)
 		bdev_blkbits = blksize_bits(bdev_hardsect_size(bdev));
@@ -1155,13 +1177,15 @@
 		goto out;
 
 	/*
-	 * For regular files,
+	 * For regular files using DIO_LOCKING,
 	 *	readers need to grab i_sem and i_alloc_sem
 	 *	writers need to grab i_alloc_sem only (i_sem is already held)
+	 * For regular files using DIO_OWN_LOCKING,
+	 *	both readers and writers need to grab i_alloc_sem
+	 *	neither readers nor writers hold i_sem on entry (nor exit)
 	 */
-	needs_locking = 0;
-	if (S_ISREG(inode->i_mode) && needs_special_locking) {
-		needs_locking = 1;
+	dio->lock_type = dio_lock_type;
+	if (dio_lock_type != DIO_NO_LOCKING) {
 		if (rw == READ) {
 			struct address_space *mapping;
 
@@ -1173,10 +1197,13 @@
 				kfree(dio);
 				goto out;
 			}
+			down_read(&inode->i_alloc_sem);
+			if (dio_lock_type == DIO_OWN_LOCKING)
+				up(&inode->i_sem);
+		} else {
+			down_read(&inode->i_alloc_sem);
 		}
-		down_read(&inode->i_alloc_sem);
 	}
-	dio->needs_locking = needs_locking;
 	/*
 	 * For file extending writes updating i_size before data
 	 * writeouts complete can expose uninitialized blocks. So
diff -Nru a/fs/dquot.c b/fs/dquot.c
--- a/fs/dquot.c	2004-10-18 14:56:48 -07:00
+++ b/fs/dquot.c	2004-10-18 14:56:48 -07:00
@@ -120,7 +120,7 @@
  * i_sem on quota files is special (it's below dqio_sem)
  */
 
-spinlock_t dq_list_lock = SPIN_LOCK_UNLOCKED;
+static spinlock_t dq_list_lock = SPIN_LOCK_UNLOCKED;
 spinlock_t dq_data_lock = SPIN_LOCK_UNLOCKED;
 
 static char *quotatypes[] = INITQFNAMES;
@@ -1792,7 +1792,6 @@
 EXPORT_SYMBOL(register_quota_format);
 EXPORT_SYMBOL(unregister_quota_format);
 EXPORT_SYMBOL(dqstats);
-EXPORT_SYMBOL(dq_list_lock);
 EXPORT_SYMBOL(dq_data_lock);
 EXPORT_SYMBOL(vfs_quota_on);
 EXPORT_SYMBOL(vfs_quota_on_mount);
diff -Nru a/fs/efs/inode.c b/fs/efs/inode.c
--- a/fs/efs/inode.c	2004-10-18 14:56:29 -07:00
+++ b/fs/efs/inode.c	2004-10-18 14:56:29 -07:00
@@ -13,8 +13,6 @@
 #include <linux/module.h>
 #include <linux/fs.h>
 
-
-extern int efs_get_block(struct inode *, sector_t, struct buffer_head *, int);
 static int efs_readpage(struct file *file, struct page *page)
 {
 	return block_read_full_page(page,efs_get_block);
@@ -23,7 +21,7 @@
 {
 	return generic_block_bmap(mapping,block,efs_get_block);
 }
-struct address_space_operations efs_aops = {
+static struct address_space_operations efs_aops = {
 	.readpage = efs_readpage,
 	.sync_page = block_sync_page,
 	.bmap = _efs_bmap
diff -Nru a/fs/efs/super.c b/fs/efs/super.c
--- a/fs/efs/super.c	2004-10-18 14:56:49 -07:00
+++ b/fs/efs/super.c	2004-10-18 14:56:49 -07:00
@@ -15,6 +15,9 @@
 #include <linux/buffer_head.h>
 #include <linux/vfs.h>
 
+static int efs_statfs(struct super_block *s, struct kstatfs *buf);
+static int efs_fill_super(struct super_block *s, void *d, int silent);
+
 static struct super_block *efs_get_sb(struct file_system_type *fs_type,
 	int flags, const char *dev_name, void *data)
 {
@@ -58,7 +61,7 @@
 {
 	efs_inode_cachep = kmem_cache_create("efs_inode_cache",
 				sizeof(struct efs_inode_info),
-				0, SLAB_HWCACHE_ALIGN|SLAB_RECLAIM_ACCOUNT,
+				0, SLAB_RECLAIM_ACCOUNT,
 				init_once, NULL);
 	if (efs_inode_cachep == NULL)
 		return -ENOMEM;
@@ -71,7 +74,7 @@
 		printk(KERN_INFO "efs_inode_cache: not all structures were freed\n");
 }
 
-void efs_put_super(struct super_block *s)
+static void efs_put_super(struct super_block *s)
 {
 	kfree(s->s_fs_info);
 	s->s_fs_info = NULL;
@@ -118,7 +121,8 @@
 
 static efs_block_t efs_validate_vh(struct volume_header *vh) {
 	int		i;
-	unsigned int	cs, csum, *ui;
+	__be32		cs, *ui;
+	int		csum;
 	efs_block_t	sblock = 0; /* shuts up gcc */
 	struct pt_types	*pt_entry;
 	int		pt_type, slice = -1;
@@ -132,8 +136,8 @@
 		return 0;
 	}
 
-	ui = ((unsigned int *) (vh + 1)) - 1;
-	for(csum = 0; ui >= ((unsigned int *) vh);) {
+	ui = ((__be32 *) (vh + 1)) - 1;
+	for(csum = 0; ui >= ((__be32 *) vh);) {
 		cs = *ui--;
 		csum += be32_to_cpu(cs);
 	}
@@ -213,7 +217,7 @@
 	return 0;    
 }
 
-int efs_fill_super(struct super_block *s, void *d, int silent)
+static int efs_fill_super(struct super_block *s, void *d, int silent)
 {
 	struct efs_sb_info *sb;
 	struct buffer_head *bh;
@@ -292,7 +296,7 @@
 	return -EINVAL;
 }
 
-int efs_statfs(struct super_block *s, struct kstatfs *buf) {
+static int efs_statfs(struct super_block *s, struct kstatfs *buf) {
 	struct efs_sb_info *sb = SUPER_INFO(s);
 
 	buf->f_type    = EFS_SUPER_MAGIC;	/* efs magic number */
diff -Nru a/fs/eventpoll.c b/fs/eventpoll.c
--- a/fs/eventpoll.c	2004-10-18 14:56:28 -07:00
+++ b/fs/eventpoll.c	2004-10-18 14:56:28 -07:00
@@ -148,6 +148,9 @@
 /* Get the "struct epitem" from an epoll queue wrapper */
 #define EP_ITEM_FROM_EPQUEUE(p) (container_of(p, struct ep_pqueue, pt)->epi)
 
+/* Tells if the epoll_ctl(2) operation needs an event copy from userspace */
+#define EP_OP_HASH_EVENT(op) ((op) != EPOLL_CTL_DEL)
+
 
 struct epoll_filefd {
 	struct file *file;
@@ -531,7 +534,8 @@
 		     current, epfd, op, fd, event));
 
 	error = -EFAULT;
-	if (copy_from_user(&epds, event, sizeof(struct epoll_event)))
+	if (EP_OP_HASH_EVENT(op) &&
+	    copy_from_user(&epds, event, sizeof(struct epoll_event)))
 		goto eexit_1;
 
 	/* Get the "struct file *" for the eventpoll file */
diff -Nru a/fs/exec.c b/fs/exec.c
--- a/fs/exec.c	2004-10-18 14:56:28 -07:00
+++ b/fs/exec.c	2004-10-18 14:56:28 -07:00
@@ -433,7 +433,7 @@
 		mpnt->vm_flags |= mm->def_flags;
 		mpnt->vm_page_prot = protection_map[mpnt->vm_flags & 0x7];
 		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++) {
@@ -546,6 +546,7 @@
 	tsk->active_mm = mm;
 	activate_mm(active_mm, mm);
 	task_unlock(tsk);
+	arch_pick_mmap_layout(mm);
 	if (old_mm) {
 		if (active_mm != old_mm) BUG();
 		mmput(old_mm);
@@ -740,8 +741,10 @@
 	spin_unlock(&oldsighand->siglock);
 	write_unlock_irq(&tasklist_lock);
 
-	if (newsig && atomic_dec_and_test(&oldsig->count))
+	if (newsig && atomic_dec_and_test(&oldsig->count)) {
+		exit_itimers(oldsig);
 		kmem_cache_free(signal_cachep, oldsig);
+	}
 
 	if (atomic_dec_and_test(&oldsighand->count))
 		kmem_cache_free(sighand_cachep, oldsighand);
@@ -786,11 +789,27 @@
 	spin_unlock(&files->file_lock);
 }
 
+void get_task_comm(char *buf, struct task_struct *tsk)
+{
+	/* buf must be at least sizeof(tsk->comm) in size */
+	task_lock(tsk);
+	memcpy(buf, tsk->comm, sizeof(tsk->comm));
+	task_unlock(tsk);
+}
+
+void set_task_comm(struct task_struct *tsk, char *buf)
+{
+	task_lock(tsk);
+	strlcpy(tsk->comm, buf, sizeof(tsk->comm));
+	task_unlock(tsk);
+}
+
 int flush_old_exec(struct linux_binprm * bprm)
 {
 	char * name;
 	int i, ch, retval;
 	struct files_struct *files;
+	char tcomm[sizeof(current->comm)];
 
 	/*
 	 * Make sure we have a private signal table and that
@@ -831,10 +850,11 @@
 		if (ch == '/')
 			i = 0;
 		else
-			if (i < 15)
-				current->comm[i++] = ch;
+			if (i < (sizeof(tcomm) - 1))
+				tcomm[i++] = ch;
 	}
-	current->comm[i] = '\0';
+	tcomm[i] = '\0';
+	set_task_comm(current, tcomm);
 
 	flush_thread();
 
@@ -1074,7 +1094,7 @@
 	char __user *__user *envp,
 	struct pt_regs * regs)
 {
-	struct linux_binprm bprm;
+	struct linux_binprm *bprm;
 	struct file *file;
 	int retval;
 	int i;
@@ -1085,87 +1105,89 @@
 	if (IS_ERR(file))
 		return retval;
 
-	sched_balance_exec();
-
-	bprm.p = PAGE_SIZE*MAX_ARG_PAGES-sizeof(void *);
-	memset(bprm.page, 0, MAX_ARG_PAGES*sizeof(bprm.page[0]));
+	sched_exec();
 
-	bprm.file = file;
-	bprm.filename = filename;
-	bprm.interp = filename;
-	bprm.interp_flags = 0;
-	bprm.interp_data = 0;
-	bprm.sh_bang = 0;
-	bprm.loader = 0;
-	bprm.exec = 0;
-	bprm.security = NULL;
-	bprm.mm = mm_alloc();
 	retval = -ENOMEM;
-	if (!bprm.mm)
+	bprm = kmalloc(sizeof(*bprm), GFP_KERNEL);
+	if (!bprm)
+		goto out_ret;
+	memset(bprm, 0, sizeof(*bprm));
+
+	bprm->p = PAGE_SIZE*MAX_ARG_PAGES-sizeof(void *);
+
+	bprm->file = file;
+	bprm->filename = filename;
+	bprm->interp = filename;
+	bprm->mm = mm_alloc();
+	if (!bprm->mm)
 		goto out_file;
 
-	retval = init_new_context(current, bprm.mm);
+	retval = init_new_context(current, bprm->mm);
 	if (retval < 0)
 		goto out_mm;
 
-	bprm.argc = count(argv, bprm.p / sizeof(void *));
-	if ((retval = bprm.argc) < 0)
+	bprm->argc = count(argv, bprm->p / sizeof(void *));
+	if ((retval = bprm->argc) < 0)
 		goto out_mm;
 
-	bprm.envc = count(envp, bprm.p / sizeof(void *));
-	if ((retval = bprm.envc) < 0)
+	bprm->envc = count(envp, bprm->p / sizeof(void *));
+	if ((retval = bprm->envc) < 0)
 		goto out_mm;
 
-	retval = security_bprm_alloc(&bprm);
+	retval = security_bprm_alloc(bprm);
 	if (retval)
 		goto out;
 
-	retval = prepare_binprm(&bprm);
+	retval = prepare_binprm(bprm);
 	if (retval < 0)
 		goto out;
 
-	retval = copy_strings_kernel(1, &bprm.filename, &bprm);
+	retval = copy_strings_kernel(1, &bprm->filename, bprm);
 	if (retval < 0)
 		goto out;
 
-	bprm.exec = bprm.p;
-	retval = copy_strings(bprm.envc, envp, &bprm);
+	bprm->exec = bprm->p;
+	retval = copy_strings(bprm->envc, envp, bprm);
 	if (retval < 0)
 		goto out;
 
-	retval = copy_strings(bprm.argc, argv, &bprm);
+	retval = copy_strings(bprm->argc, argv, bprm);
 	if (retval < 0)
 		goto out;
 
-	retval = search_binary_handler(&bprm,regs);
+	retval = search_binary_handler(bprm,regs);
 	if (retval >= 0) {
-		free_arg_pages(&bprm);
+		free_arg_pages(bprm);
 
 		/* execve success */
-		security_bprm_free(&bprm);
+		security_bprm_free(bprm);
+		kfree(bprm);
 		return retval;
 	}
 
 out:
 	/* Something went wrong, return the inode and free the argument pages*/
 	for (i = 0 ; i < MAX_ARG_PAGES ; i++) {
-		struct page * page = bprm.page[i];
+		struct page * page = bprm->page[i];
 		if (page)
 			__free_page(page);
 	}
 
-	if (bprm.security)
-		security_bprm_free(&bprm);
+	if (bprm->security)
+		security_bprm_free(bprm);
 
 out_mm:
-	if (bprm.mm)
-		mmdrop(bprm.mm);
+	if (bprm->mm)
+		mmdrop(bprm->mm);
 
 out_file:
-	if (bprm.file) {
-		allow_write_access(bprm.file);
-		fput(bprm.file);
+	if (bprm->file) {
+		allow_write_access(bprm->file);
+		fput(bprm->file);
 	}
+	kfree(bprm);
+
+out_ret:
 	return retval;
 }
 
@@ -1193,7 +1215,7 @@
  * name into corename, which must have space for at least
  * CORENAME_MAX_SIZE bytes plus one byte for the zero terminator.
  */
-void format_corename(char *corename, const char *pattern, long signr)
+static void format_corename(char *corename, const char *pattern, long signr)
 {
 	const char *pat_ptr = pattern;
 	char *out_ptr = corename;
@@ -1357,7 +1379,6 @@
 	struct file * file;
 	int retval = 0;
 
-	lock_kernel();
 	binfmt = current->binfmt;
 	if (!binfmt || !binfmt->core_dump)
 		goto fail;
@@ -1375,7 +1396,13 @@
 	if (current->rlim[RLIMIT_CORE].rlim_cur < binfmt->min_coredump)
 		goto fail_unlock;
 
- 	format_corename(corename, core_pattern, signr);
+	/*
+	 * lock_kernel() because format_corename() is controlled by sysctl, which
+	 * uses lock_kernel()
+	 */
+ 	lock_kernel();
+	format_corename(corename, core_pattern, signr);
+	unlock_kernel();
 	file = filp_open(corename, O_CREAT | 2 | O_NOFOLLOW | O_LARGEFILE, 0600);
 	if (IS_ERR(file))
 		goto fail_unlock;
@@ -1402,6 +1429,5 @@
 fail_unlock:
 	complete_all(&mm->core_done);
 fail:
-	unlock_kernel();
 	return retval;
 }
diff -Nru a/fs/exportfs/expfs.c b/fs/exportfs/expfs.c
--- a/fs/exportfs/expfs.c	2004-10-18 14:56:49 -07:00
+++ b/fs/exportfs/expfs.c	2004-10-18 14:56:49 -07:00
@@ -1,5 +1,6 @@
 
 #include <linux/fs.h>
+#include <linux/file.h>
 #include <linux/module.h>
 #include <linux/smp_lock.h>
 #include <linux/namei.h>
@@ -282,7 +283,12 @@
 
 	/* drat - I just cannot find anything acceptable */
 	dput(result);
-	return ERR_PTR(-ESTALE);
+	/* It might be justifiable to return ESTALE here,
+	 * but the filehandle at-least looks reasonable good
+	 * and it just be a permission problem, so returning
+	 * -EACCESS is safer
+	 */
+	return ERR_PTR(-EACCES);
 
  err_target:
 	dput(target_dir);
@@ -347,7 +353,7 @@
 {
 	struct inode *dir = dentry->d_inode;
 	int error;
-	struct file file;
+	struct file *file;
 	struct getdents_callback buffer;
 
 	error = -ENOTDIR;
@@ -359,11 +365,13 @@
 	/*
 	 * Open the directory ...
 	 */
-	error = open_private_file(&file, dentry, O_RDONLY);
-	if (error)
+	file = dentry_open(dget(dentry), NULL, O_RDONLY);
+	error = PTR_ERR(file);
+	if (IS_ERR(file))
 		goto out;
+
 	error = -EINVAL;
-	if (!file.f_op->readdir)
+	if (!file->f_op->readdir)
 		goto out_close;
 
 	buffer.name = name;
@@ -373,7 +381,7 @@
 	while (1) {
 		int old_seq = buffer.sequence;
 
-		error = vfs_readdir(&file, filldir_one, &buffer);
+		error = vfs_readdir(file, filldir_one, &buffer);
 
 		if (error < 0)
 			break;
@@ -387,7 +395,7 @@
 	}
 
 out_close:
-	close_private_file(&file);
+	fput(file);
 out:
 	return error;
 }
diff -Nru a/fs/ext2/acl.h b/fs/ext2/acl.h
--- a/fs/ext2/acl.h	2004-10-18 14:56:48 -07:00
+++ b/fs/ext2/acl.h	2004-10-18 14:56:48 -07:00
@@ -10,18 +10,18 @@
 #define EXT2_ACL_MAX_ENTRIES	32
 
 typedef struct {
-	__u16		e_tag;
-	__u16		e_perm;
-	__u32		e_id;
+	__le16		e_tag;
+	__le16		e_perm;
+	__le32		e_id;
 } ext2_acl_entry;
 
 typedef struct {
-	__u16		e_tag;
-	__u16		e_perm;
+	__le16		e_tag;
+	__le16		e_perm;
 } ext2_acl_entry_short;
 
 typedef struct {
-	__u32		a_version;
+	__le32		a_version;
 } ext2_acl_header;
 
 static inline size_t ext2_acl_size(int count)
diff -Nru a/fs/ext2/balloc.c b/fs/ext2/balloc.c
--- a/fs/ext2/balloc.c	2004-10-18 14:56:28 -07:00
+++ b/fs/ext2/balloc.c	2004-10-18 14:56:28 -07:00
@@ -88,8 +88,8 @@
 	if (!bh)
 		ext2_error (sb, "read_block_bitmap",
 			    "Cannot read block bitmap - "
-			    "block_group = %d, block_bitmap = %lu",
-			    block_group, (unsigned long) desc->bg_block_bitmap);
+			    "block_group = %d, block_bitmap = %u",
+			    block_group, le32_to_cpu(desc->bg_block_bitmap));
 error_out:
 	return bh;
 }
diff -Nru a/fs/ext2/dir.c b/fs/ext2/dir.c
--- a/fs/ext2/dir.c	2004-10-18 14:56:32 -07:00
+++ b/fs/ext2/dir.c	2004-10-18 14:56:32 -07:00
@@ -251,7 +251,7 @@
 	loff_t pos = filp->f_pos;
 	struct inode *inode = filp->f_dentry->d_inode;
 	struct super_block *sb = inode->i_sb;
-	unsigned offset = pos & ~PAGE_CACHE_MASK;
+	unsigned int offset = pos & ~PAGE_CACHE_MASK;
 	unsigned long n = pos >> PAGE_CACHE_SHIFT;
 	unsigned long npages = dir_pages(inode);
 	unsigned chunk_mask = ~(ext2_chunk_size(inode)-1);
@@ -270,8 +270,13 @@
 		ext2_dirent *de;
 		struct page *page = ext2_get_page(inode, n);
 
-		if (IS_ERR(page))
+		if (IS_ERR(page)) {
+			ext2_error(sb, __FUNCTION__,
+				   "bad page in #%lu",
+				   inode->i_ino);
+			filp->f_pos += PAGE_CACHE_SIZE - offset;
 			continue;
+		}
 		kaddr = page_address(page);
 		if (need_revalidate) {
 			offset = ext2_validate_entry(kaddr, offset, chunk_mask);
@@ -303,6 +308,7 @@
 					goto success;
 				}
 			}
+			filp->f_pos += le16_to_cpu(de->rec_len);
 		}
 		ext2_put_page(page);
 	}
@@ -310,7 +316,6 @@
 success:
 	ret = 0;
 done:
-	filp->f_pos = (n << PAGE_CACHE_SHIFT) | offset;
 	filp->f_version = inode->i_version;
 	return ret;
 }
diff -Nru a/fs/ext2/ext2.h b/fs/ext2/ext2.h
--- a/fs/ext2/ext2.h	2004-10-18 14:57:04 -07:00
+++ b/fs/ext2/ext2.h	2004-10-18 14:57:04 -07:00
@@ -5,7 +5,7 @@
  * second extended file system inode data in memory
  */
 struct ext2_inode_info {
-	__u32	i_data[15];
+	__le32	i_data[15];
 	__u32	i_flags;
 	__u32	i_faddr;
 	__u8	i_frag_no;
@@ -115,7 +115,7 @@
 
 /* inode.c */
 extern void ext2_read_inode (struct inode *);
-extern void ext2_write_inode (struct inode *, int);
+extern int ext2_write_inode (struct inode *, int);
 extern void ext2_put_inode (struct inode *);
 extern void ext2_delete_inode (struct inode *);
 extern int ext2_sync_inode (struct inode *);
@@ -131,9 +131,6 @@
 /* super.c */
 extern void ext2_error (struct super_block *, const char *, const char *, ...)
 	__attribute__ ((format (printf, 3, 4)));
-extern NORET_TYPE void ext2_panic (struct super_block *, const char *,
-				   const char *, ...)
-	__attribute__ ((NORET_AND format (printf, 3, 4)));
 extern void ext2_warning (struct super_block *, const char *, const char *, ...)
 	__attribute__ ((format (printf, 3, 4)));
 extern void ext2_update_dynamic_rev (struct super_block *sb);
diff -Nru a/fs/ext2/ialloc.c b/fs/ext2/ialloc.c
--- a/fs/ext2/ialloc.c	2004-10-18 14:56:32 -07:00
+++ b/fs/ext2/ialloc.c	2004-10-18 14:56:32 -07:00
@@ -57,8 +57,8 @@
 	if (!bh)
 		ext2_error(sb, "read_inode_bitmap",
 			    "Cannot read inode bitmap - "
-			    "block_group = %lu, inode_bitmap = %lu",
-			    block_group, (unsigned long) desc->bg_inode_bitmap);
+			    "block_group = %lu, inode_bitmap = %u",
+			    block_group, le32_to_cpu(desc->bg_inode_bitmap));
 error_out:
 	return bh;
 }
diff -Nru a/fs/ext2/inode.c b/fs/ext2/inode.c
--- a/fs/ext2/inode.c	2004-10-18 14:55:54 -07:00
+++ b/fs/ext2/inode.c	2004-10-18 14:55:54 -07:00
@@ -142,12 +142,12 @@
 }
 
 typedef struct {
-	u32	*p;
-	u32	key;
+	__le32	*p;
+	__le32	key;
 	struct buffer_head *bh;
 } Indirect;
 
-static inline void add_chain(Indirect *p, struct buffer_head *bh, u32 *v)
+static inline void add_chain(Indirect *p, struct buffer_head *bh, __le32 *v)
 {
 	p->key = *(p->p = v);
 	p->bh = bh;
@@ -280,7 +280,7 @@
 		read_lock(&EXT2_I(inode)->i_meta_lock);
 		if (!verify_chain(chain, p))
 			goto changed;
-		add_chain(++p, bh, (u32*)bh->b_data + *++offsets);
+		add_chain(++p, bh, (__le32*)bh->b_data + *++offsets);
 		read_unlock(&EXT2_I(inode)->i_meta_lock);
 		if (!p->key)
 			goto no_block;
@@ -321,8 +321,8 @@
 static unsigned long ext2_find_near(struct inode *inode, Indirect *ind)
 {
 	struct ext2_inode_info *ei = EXT2_I(inode);
-	u32 *start = ind->bh ? (u32*) ind->bh->b_data : ei->i_data;
-	u32 *p;
+	__le32 *start = ind->bh ? (__le32 *) ind->bh->b_data : ei->i_data;
+	__le32 *p;
 	unsigned long bg_start;
 	unsigned long colour;
 
@@ -440,7 +440,7 @@
 		lock_buffer(bh);
 		memset(bh->b_data, 0, blocksize);
 		branch[n].bh = bh;
-		branch[n].p = (u32*) bh->b_data + offsets[n];
+		branch[n].p = (__le32 *) bh->b_data + offsets[n];
 		*branch[n].p = branch[n].key;
 		set_buffer_uptodate(bh);
 		unlock_buffer(bh);
@@ -702,7 +702,7 @@
  * or memcmp with zero_page, whatever is better for particular architecture.
  * Linus?
  */
-static inline int all_zeroes(u32 *p, u32 *q)
+static inline int all_zeroes(__le32 *p, __le32 *q)
 {
 	while (p < q)
 		if (*p++)
@@ -748,7 +748,7 @@
 				int depth,
 				int offsets[4],
 				Indirect chain[4],
-				u32 *top)
+				__le32 *top)
 {
 	Indirect *partial, *p;
 	int k, err;
@@ -768,7 +768,7 @@
 		write_unlock(&EXT2_I(inode)->i_meta_lock);
 		goto no_top;
 	}
-	for (p=partial; p>chain && all_zeroes((u32*)p->bh->b_data,p->p); p--)
+	for (p=partial; p>chain && all_zeroes((__le32*)p->bh->b_data,p->p); p--)
 		;
 	/*
 	 * OK, we've found the last block that must survive. The rest of our
@@ -803,7 +803,7 @@
  *	stored as little-endian 32-bit) and updating @inode->i_blocks
  *	appropriately.
  */
-static inline void ext2_free_data(struct inode *inode, u32 *p, u32 *q)
+static inline void ext2_free_data(struct inode *inode, __le32 *p, __le32 *q)
 {
 	unsigned long block_to_free = 0, count = 0;
 	unsigned long nr;
@@ -843,7 +843,7 @@
  *	stored as little-endian 32-bit) and updating @inode->i_blocks
  *	appropriately.
  */
-static void ext2_free_branches(struct inode *inode, u32 *p, u32 *q, int depth)
+static void ext2_free_branches(struct inode *inode, __le32 *p, __le32 *q, int depth)
 {
 	struct buffer_head * bh;
 	unsigned long nr;
@@ -867,8 +867,8 @@
 				continue;
 			}
 			ext2_free_branches(inode,
-					   (u32*)bh->b_data,
-					   (u32*)bh->b_data + addr_per_block,
+					   (__le32*)bh->b_data,
+					   (__le32*)bh->b_data + addr_per_block,
 					   depth);
 			bforget(bh);
 			ext2_free_blocks(inode, nr, 1);
@@ -880,12 +880,12 @@
 
 void ext2_truncate (struct inode * inode)
 {
-	u32 *i_data = EXT2_I(inode)->i_data;
+	__le32 *i_data = EXT2_I(inode)->i_data;
 	int addr_per_block = EXT2_ADDR_PER_BLOCK(inode->i_sb);
 	int offsets[4];
 	Indirect chain[4];
 	Indirect *partial;
-	int nr = 0;
+	__le32 nr = 0;
 	int n;
 	long iblock;
 	unsigned blocksize;
@@ -933,7 +933,7 @@
 	while (partial > chain) {
 		ext2_free_branches(inode,
 				   partial->p + 1,
-				   (u32*)partial->bh->b_data + addr_per_block,
+				   (__le32*)partial->bh->b_data+addr_per_block,
 				   (chain+n-1) - partial);
 		mark_buffer_dirty_inode(partial->bh, inode);
 		brelse (partial->bh);
@@ -1248,9 +1248,9 @@
 	return err;
 }
 
-void ext2_write_inode(struct inode *inode, int wait)
+int ext2_write_inode(struct inode *inode, int wait)
 {
-	ext2_update_inode(inode, wait);
+	return ext2_update_inode(inode, wait);
 }
 
 int ext2_sync_inode(struct inode *inode)
diff -Nru a/fs/ext2/super.c b/fs/ext2/super.c
--- a/fs/ext2/super.c	2004-10-18 14:56:33 -07:00
+++ b/fs/ext2/super.c	2004-10-18 14:56:33 -07:00
@@ -37,8 +37,6 @@
 static int ext2_remount (struct super_block * sb, int * flags, char * data);
 static int ext2_statfs (struct super_block * sb, struct kstatfs * buf);
 
-static char error_buf[1024];
-
 void ext2_error (struct super_block * sb, const char * function,
 		 const char * fmt, ...)
 {
@@ -52,51 +50,32 @@
 			cpu_to_le16(le16_to_cpu(es->s_state) | EXT2_ERROR_FS);
 		ext2_sync_super(sb, es);
 	}
-	va_start (args, fmt);
-	vsprintf (error_buf, fmt, args);
-	va_end (args);
-	if (test_opt (sb, ERRORS_PANIC))
-		panic ("EXT2-fs panic (device %s): %s: %s\n",
-		       sb->s_id, function, error_buf);
-	printk (KERN_CRIT "EXT2-fs error (device %s): %s: %s\n",
-		sb->s_id, function, error_buf);
-	if (test_opt (sb, ERRORS_RO)) {
-		printk ("Remounting filesystem read-only\n");
+
+	va_start(args, fmt);
+	printk(KERN_CRIT "EXT2-fs error (device %s): %s: ",sb->s_id, function);
+	vprintk(fmt, args);
+	printk("\n");
+	va_end(args);
+
+	if (test_opt(sb, ERRORS_PANIC))
+		panic("EXT2-fs panic from previous error\n");
+	if (test_opt(sb, ERRORS_RO)) {
+		printk("Remounting filesystem read-only\n");
 		sb->s_flags |= MS_RDONLY;
 	}
 }
 
-NORET_TYPE void ext2_panic (struct super_block * sb, const char * function,
-			    const char * fmt, ...)
-{
-	va_list args;
-	struct ext2_sb_info *sbi = EXT2_SB(sb);
-
-	if (!(sb->s_flags & MS_RDONLY)) {
-		sbi->s_mount_state |= EXT2_ERROR_FS;
-		sbi->s_es->s_state =
-			cpu_to_le16(le16_to_cpu(sbi->s_es->s_state) | EXT2_ERROR_FS);
-		mark_buffer_dirty(sbi->s_sbh);
-		sb->s_dirt = 1;
-	}
-	va_start (args, fmt);
-	vsprintf (error_buf, fmt, args);
-	va_end (args);
-	sb->s_flags |= MS_RDONLY;
-	panic ("EXT2-fs panic (device %s): %s: %s\n",
-	       sb->s_id, function, error_buf);
-}
-
 void ext2_warning (struct super_block * sb, const char * function,
 		   const char * fmt, ...)
 {
 	va_list args;
 
-	va_start (args, fmt);
-	vsprintf (error_buf, fmt, args);
-	va_end (args);
-	printk (KERN_WARNING "EXT2-fs warning (device %s): %s: %s\n",
-		sb->s_id, function, error_buf);
+	va_start(args, fmt);
+	printk(KERN_WARNING "EXT2-fs warning (device %s): %s: ",
+	       sb->s_id, function);
+	vprintk(fmt, args);
+	printk("\n");
+	va_end(args);
 }
 
 void ext2_update_dynamic_rev(struct super_block *sb)
@@ -134,7 +113,7 @@
 	if (!(sb->s_flags & MS_RDONLY)) {
 		struct ext2_super_block *es = sbi->s_es;
 
-		es->s_state = le16_to_cpu(sbi->s_mount_state);
+		es->s_state = cpu_to_le16(sbi->s_mount_state);
 		ext2_sync_super(sb, es);
 	}
 	db_count = sbi->s_gdb_count;
@@ -189,7 +168,7 @@
 {
 	ext2_inode_cachep = kmem_cache_create("ext2_inode_cache",
 					     sizeof(struct ext2_inode_info),
-					     0, SLAB_HWCACHE_ALIGN|SLAB_RECLAIM_ACCOUNT,
+					     0, SLAB_RECLAIM_ACCOUNT,
 					     init_once, NULL);
 	if (ext2_inode_cachep == NULL)
 		return -ENOMEM;
@@ -449,8 +428,8 @@
 		(le32_to_cpu(es->s_lastcheck) + le32_to_cpu(es->s_checkinterval) <= get_seconds()))
 		printk ("EXT2-fs warning: checktime reached, "
 			"running e2fsck is recommended\n");
-	if (!(__s16) le16_to_cpu(es->s_max_mnt_count))
-		es->s_max_mnt_count = (__s16) cpu_to_le16(EXT2_DFL_MAX_MNT_COUNT);
+	if (!le16_to_cpu(es->s_max_mnt_count))
+		es->s_max_mnt_count = cpu_to_le16(EXT2_DFL_MAX_MNT_COUNT);
 	es->s_mnt_count=cpu_to_le16(le16_to_cpu(es->s_mnt_count) + 1);
 	ext2_write_super(sb);
 	if (test_opt (sb, DEBUG))
@@ -572,6 +551,7 @@
 	int blocksize = BLOCK_SIZE;
 	int db_count;
 	int i, j;
+	__le32 features;
 
 	sbi = kmalloc(sizeof(*sbi), GFP_KERNEL);
 	if (!sbi)
@@ -661,17 +641,18 @@
 	 * previously didn't change the revision level when setting the flags,
 	 * so there is a chance incompat flags are set on a rev 0 filesystem.
 	 */
-	if ((i = EXT2_HAS_INCOMPAT_FEATURE(sb, ~EXT2_FEATURE_INCOMPAT_SUPP))) {
+	features = EXT2_HAS_INCOMPAT_FEATURE(sb, ~EXT2_FEATURE_INCOMPAT_SUPP);
+	if (features) {
 		printk("EXT2-fs: %s: couldn't mount because of "
 		       "unsupported optional features (%x).\n",
-		       sb->s_id, i);
+		       sb->s_id, le32_to_cpu(features));
 		goto failed_mount;
 	}
 	if (!(sb->s_flags & MS_RDONLY) &&
-	    (i = EXT2_HAS_RO_COMPAT_FEATURE(sb, ~EXT2_FEATURE_RO_COMPAT_SUPP))){
+	    (features = EXT2_HAS_RO_COMPAT_FEATURE(sb, ~EXT2_FEATURE_RO_COMPAT_SUPP))){
 		printk("EXT2-fs: %s: couldn't mount RDWR because of "
 		       "unsupported optional features (%x).\n",
-		       sb->s_id, i);
+		       sb->s_id, le32_to_cpu(features));
 		goto failed_mount;
 	}
 	blocksize = BLOCK_SIZE << le32_to_cpu(sbi->s_es->s_log_block_size);
@@ -694,7 +675,7 @@
 		}
 		es = (struct ext2_super_block *) (((char *)bh->b_data) + offset);
 		sbi->s_es = es;
-		if (es->s_magic != le16_to_cpu(EXT2_SUPER_MAGIC)) {
+		if (es->s_magic != cpu_to_le16(EXT2_SUPER_MAGIC)) {
 			printk ("EXT2-fs: Magic mismatch, very weird !\n");
 			goto failed_mount;
 		}
@@ -937,12 +918,12 @@
 		es->s_state = cpu_to_le16(sbi->s_mount_state);
 		es->s_mtime = cpu_to_le32(get_seconds());
 	} else {
-		int ret;
-		if ((ret = EXT2_HAS_RO_COMPAT_FEATURE(sb,
-					       ~EXT2_FEATURE_RO_COMPAT_SUPP))) {
+		__le32 ret = EXT2_HAS_RO_COMPAT_FEATURE(sb,
+					       ~EXT2_FEATURE_RO_COMPAT_SUPP);
+		if (ret) {
 			printk("EXT2-fs: %s: couldn't remount RDWR because of "
 			       "unsupported optional features (%x).\n",
-			       sb->s_id, ret);
+			       sb->s_id, le32_to_cpu(ret));
 			return -EROFS;
 		}
 		/*
diff -Nru a/fs/ext2/xattr.c b/fs/ext2/xattr.c
--- a/fs/ext2/xattr.c	2004-10-18 14:56:33 -07:00
+++ b/fs/ext2/xattr.c	2004-10-18 14:56:33 -07:00
@@ -1071,7 +1071,7 @@
 	}
 
 	if (entry->e_value_block == 0 && entry->e_value_size != 0) {
-		__u32 *value = (__u32 *)((char *)header +
+		__le32 *value = (__le32 *)((char *)header +
 			le16_to_cpu(entry->e_value_offs));
 		for (n = (le32_to_cpu(entry->e_value_size) +
 		     EXT2_XATTR_ROUND) >> EXT2_XATTR_PAD_BITS; n; n--) {
diff -Nru a/fs/ext2/xattr.h b/fs/ext2/xattr.h
--- a/fs/ext2/xattr.h	2004-10-18 14:56:48 -07:00
+++ b/fs/ext2/xattr.h	2004-10-18 14:56:48 -07:00
@@ -26,20 +26,20 @@
 #define EXT2_XATTR_INDEX_SECURITY	        6
 
 struct ext2_xattr_header {
-	__u32	h_magic;	/* magic number for identification */
-	__u32	h_refcount;	/* reference count */
-	__u32	h_blocks;	/* number of disk blocks used */
-	__u32	h_hash;		/* hash value of all attributes */
+	__le32	h_magic;	/* magic number for identification */
+	__le32	h_refcount;	/* reference count */
+	__le32	h_blocks;	/* number of disk blocks used */
+	__le32	h_hash;		/* hash value of all attributes */
 	__u32	h_reserved[4];	/* zero right now */
 };
 
 struct ext2_xattr_entry {
 	__u8	e_name_len;	/* length of name */
 	__u8	e_name_index;	/* attribute name index */
-	__u16	e_value_offs;	/* offset in disk block of value */
-	__u32	e_value_block;	/* disk block attribute is stored on (n/i) */
-	__u32	e_value_size;	/* size of attribute value */
-	__u32	e_hash;		/* hash value of name and value */
+	__le16	e_value_offs;	/* offset in disk block of value */
+	__le32	e_value_block;	/* disk block attribute is stored on (n/i) */
+	__le32	e_value_size;	/* size of attribute value */
+	__le32	e_hash;		/* hash value of name and value */
 	char	e_name[0];	/* attribute name */
 };
 
diff -Nru a/fs/ext3/acl.h b/fs/ext3/acl.h
--- a/fs/ext3/acl.h	2004-10-18 14:57:04 -07:00
+++ b/fs/ext3/acl.h	2004-10-18 14:57:04 -07:00
@@ -10,18 +10,18 @@
 #define EXT3_ACL_MAX_ENTRIES	32
 
 typedef struct {
-	__u16		e_tag;
-	__u16		e_perm;
-	__u32		e_id;
+	__le16		e_tag;
+	__le16		e_perm;
+	__le32		e_id;
 } ext3_acl_entry;
 
 typedef struct {
-	__u16		e_tag;
-	__u16		e_perm;
+	__le16		e_tag;
+	__le16		e_perm;
 } ext3_acl_entry_short;
 
 typedef struct {
-	__u32		a_version;
+	__le32		a_version;
 } ext3_acl_header;
 
 static inline size_t ext3_acl_size(int count)
diff -Nru a/fs/ext3/balloc.c b/fs/ext3/balloc.c
--- a/fs/ext3/balloc.c	2004-10-18 14:55:54 -07:00
+++ b/fs/ext3/balloc.c	2004-10-18 14:55:54 -07:00
@@ -91,8 +91,8 @@
 	if (!bh)
 		ext3_error (sb, "read_block_bitmap",
 			    "Cannot read block bitmap - "
-			    "block_group = %d, block_bitmap = %lu",
-			    block_group, (unsigned long) desc->bg_block_bitmap);
+			    "block_group = %d, block_bitmap = %u",
+			    block_group, le32_to_cpu(desc->bg_block_bitmap));
 error_out:
 	return bh;
 }
diff -Nru a/fs/ext3/fsync.c b/fs/ext3/fsync.c
--- a/fs/ext3/fsync.c	2004-10-18 14:57:04 -07:00
+++ b/fs/ext3/fsync.c	2004-10-18 14:57:04 -07:00
@@ -49,10 +49,6 @@
 
 	J_ASSERT(ext3_journal_current_handle() == 0);
 
-	smp_mb();		/* prepare for lockless i_state read */
-	if (!(inode->i_state & I_DIRTY))
-		goto out;
-
 	/*
 	 * data=writeback:
 	 *  The caller's filemap_fdatawrite()/wait will sync the data.
diff -Nru a/fs/ext3/ialloc.c b/fs/ext3/ialloc.c
--- a/fs/ext3/ialloc.c	2004-10-18 14:56:32 -07:00
+++ b/fs/ext3/ialloc.c	2004-10-18 14:56:32 -07:00
@@ -64,8 +64,8 @@
 	if (!bh)
 		ext3_error(sb, "read_inode_bitmap",
 			    "Cannot read inode bitmap - "
-			    "block_group = %lu, inode_bitmap = %lu",
-			    block_group, (unsigned long) desc->bg_inode_bitmap);
+			    "block_group = %lu, inode_bitmap = %u",
+			    block_group, le32_to_cpu(desc->bg_inode_bitmap));
 error_out:
 	return bh;
 }
@@ -97,7 +97,7 @@
 	unsigned long bit;
 	struct ext3_group_desc * gdp;
 	struct ext3_super_block * es;
-	struct ext3_sb_info *sbi = EXT3_SB(sb);
+	struct ext3_sb_info *sbi;
 	int fatal = 0, err;
 
 	if (atomic_read(&inode->i_count) > 1) {
@@ -114,6 +114,7 @@
 		printk("ext3_free_inode: inode on nonexistent device\n");
 		return;
 	}
+	sbi = EXT3_SB(sb);
 
 	ino = inode->i_ino;
 	ext3_debug ("freeing inode %lu\n", ino);
diff -Nru a/fs/ext3/inode.c b/fs/ext3/inode.c
--- a/fs/ext3/inode.c	2004-10-18 14:56:48 -07:00
+++ b/fs/ext3/inode.c	2004-10-18 14:56:48 -07:00
@@ -66,6 +66,8 @@
 {
 	int err;
 
+	might_sleep();
+
 	BUFFER_TRACE(bh, "enter");
 
 	jbd_debug(4, "forgetting bh %p: is_metadata = %d, mode %o, "
@@ -303,12 +305,12 @@
 
 
 typedef struct {
-	u32	*p;
-	u32	key;
+	__le32	*p;
+	__le32	key;
 	struct buffer_head *bh;
 } Indirect;
 
-static inline void add_chain(Indirect *p, struct buffer_head *bh, u32 *v)
+static inline void add_chain(Indirect *p, struct buffer_head *bh, __le32 *v)
 {
 	p->key = *(p->p = v);
 	p->bh = bh;
@@ -439,7 +441,7 @@
 		/* Reader: pointers */
 		if (!verify_chain(chain, p))
 			goto changed;
-		add_chain(++p, bh, (u32*)bh->b_data + *++offsets);
+		add_chain(++p, bh, (__le32*)bh->b_data + *++offsets);
 		/* Reader: end */
 		if (!p->key)
 			goto no_block;
@@ -480,8 +482,8 @@
 static unsigned long ext3_find_near(struct inode *inode, Indirect *ind)
 {
 	struct ext3_inode_info *ei = EXT3_I(inode);
-	u32 *start = ind->bh ? (u32*) ind->bh->b_data : ei->i_data;
-	u32 *p;
+	__le32 *start = ind->bh ? (__le32*) ind->bh->b_data : ei->i_data;
+	__le32 *p;
 	unsigned long bg_start;
 	unsigned long colour;
 
@@ -609,7 +611,7 @@
 			}
 
 			memset(bh->b_data, 0, blocksize);
-			branch[n].p = (u32*) bh->b_data + offsets[n];
+			branch[n].p = (__le32*) bh->b_data + offsets[n];
 			*branch[n].p = branch[n].key;
 			BUFFER_TRACE(bh, "marking uptodate");
 			set_buffer_uptodate(bh);
@@ -1577,6 +1579,12 @@
 				 offset, nr_segs,
 				 ext3_direct_io_get_blocks, NULL);
 
+	/*
+	 * Reacquire the handle: ext3_direct_io_get_block() can restart the
+	 * transaction
+	 */
+	handle = journal_current_handle();
+
 out_stop:
 	if (handle) {
 		int err;
@@ -1765,7 +1773,7 @@
  * or memcmp with zero_page, whatever is better for particular architecture.
  * Linus?
  */
-static inline int all_zeroes(u32 *p, u32 *q)
+static inline int all_zeroes(__le32 *p, __le32 *q)
 {
 	while (p < q)
 		if (*p++)
@@ -1812,7 +1820,7 @@
 				int depth,
 				int offsets[4],
 				Indirect chain[4],
-				u32 *top)
+				__le32 *top)
 {
 	Indirect *partial, *p;
 	int k, err;
@@ -1832,7 +1840,7 @@
 	if (!partial->key && *partial->p)
 		/* Writer: end */
 		goto no_top;
-	for (p=partial; p>chain && all_zeroes((u32*)p->bh->b_data,p->p); p--)
+	for (p=partial; p>chain && all_zeroes((__le32*)p->bh->b_data,p->p); p--)
 		;
 	/*
 	 * OK, we've found the last block that must survive. The rest of our
@@ -1871,9 +1879,9 @@
 static void
 ext3_clear_blocks(handle_t *handle, struct inode *inode, struct buffer_head *bh,
 		unsigned long block_to_free, unsigned long count,
-		u32 *first, u32 *last)
+		__le32 *first, __le32 *last)
 {
-	u32 *p;
+	__le32 *p;
 	if (try_to_extend_transaction(handle, inode)) {
 		if (bh) {
 			BUFFER_TRACE(bh, "call ext3_journal_dirty_metadata");
@@ -1929,15 +1937,16 @@
  * block pointers.
  */
 static void ext3_free_data(handle_t *handle, struct inode *inode,
-			   struct buffer_head *this_bh, u32 *first, u32 *last)
+			   struct buffer_head *this_bh,
+			   __le32 *first, __le32 *last)
 {
 	unsigned long block_to_free = 0;    /* Starting block # of a run */
 	unsigned long count = 0;	    /* Number of blocks in the run */ 
-	u32 *block_to_free_p = NULL;	    /* Pointer into inode/ind
+	__le32 *block_to_free_p = NULL;	    /* Pointer into inode/ind
 					       corresponding to
 					       block_to_free */
 	unsigned long nr;		    /* Current block # */
-	u32 *p;				    /* Pointer into inode/ind
+	__le32 *p;			    /* Pointer into inode/ind
 					       for current block */
 	int err;
 
@@ -1996,10 +2005,10 @@
  */
 static void ext3_free_branches(handle_t *handle, struct inode *inode,
 			       struct buffer_head *parent_bh,
-			       u32 *first, u32 *last, int depth)
+			       __le32 *first, __le32 *last, int depth)
 {
 	unsigned long nr;
-	u32 *p;
+	__le32 *p;
 
 	if (is_handle_aborted(handle))
 		return;
@@ -2029,8 +2038,9 @@
 
 			/* This zaps the entire block.  Bottom up. */
 			BUFFER_TRACE(bh, "free child branches");
-			ext3_free_branches(handle, inode, bh, (u32*)bh->b_data,
-					   (u32*)bh->b_data + addr_per_block,
+			ext3_free_branches(handle, inode, bh,
+					   (__le32*)bh->b_data,
+					   (__le32*)bh->b_data + addr_per_block,
 					   depth);
 
 			/*
@@ -2135,13 +2145,13 @@
 {
 	handle_t *handle;
 	struct ext3_inode_info *ei = EXT3_I(inode);
-	u32 *i_data = ei->i_data;
+	__le32 *i_data = ei->i_data;
 	int addr_per_block = EXT3_ADDR_PER_BLOCK(inode->i_sb);
 	struct address_space *mapping = inode->i_mapping;
 	int offsets[4];
 	Indirect chain[4];
 	Indirect *partial;
-	int nr = 0;
+	__le32 nr = 0;
 	int n;
 	long last_block;
 	unsigned blocksize = inode->i_sb->s_blocksize;
@@ -2248,7 +2258,7 @@
 	/* Clear the ends of indirect blocks on the shared branch */
 	while (partial > chain) {
 		ext3_free_branches(handle, inode, partial->bh, partial->p + 1,
-				   (u32*)partial->bh->b_data + addr_per_block,
+				   (__le32*)partial->bh->b_data+addr_per_block,
 				   (chain+n-1) - partial);
 		BUFFER_TRACE(partial->bh, "call brelse");
 		brelse (partial->bh);
@@ -2743,21 +2753,21 @@
  * `stuff()' is running, and the new i_size will be lost.  Plus the inode
  * will no longer be on the superblock's dirty inode list.
  */
-void ext3_write_inode(struct inode *inode, int wait)
+int ext3_write_inode(struct inode *inode, int wait)
 {
 	if (current->flags & PF_MEMALLOC)
-		return;
+		return 0;
 
 	if (ext3_journal_current_handle()) {
 		jbd_debug(0, "called recursively, non-PF_MEMALLOC!\n");
 		dump_stack();
-		return;
+		return -EIO;
 	}
 
 	if (!wait)
-		return;
+		return 0;
 
-	ext3_force_commit(inode->i_sb);
+	return ext3_force_commit(inode->i_sb);
 }
 
 /*
@@ -2966,6 +2976,7 @@
 	struct ext3_iloc iloc;
 	int err;
 
+	might_sleep();
 	err = ext3_reserve_inode_write(handle, inode, &iloc);
 	if (!err)
 		err = ext3_mark_iloc_dirty(handle, inode, &iloc);
diff -Nru a/fs/ext3/namei.c b/fs/ext3/namei.c
--- a/fs/ext3/namei.c	2004-10-18 14:56:33 -07:00
+++ b/fs/ext3/namei.c	2004-10-18 14:56:33 -07:00
@@ -71,9 +71,6 @@
 #define swap(x, y) do { typeof(x) z = x; x = y; y = z; } while (0)
 #endif
 
-typedef struct { u32 v; } le_u32;
-typedef struct { u16 v; } le_u16;
-
 #ifdef DX_DEBUG
 #define dxtrace(command) command
 #else
@@ -82,22 +79,22 @@
 
 struct fake_dirent
 {
-	/*le*/u32 inode;
-	/*le*/u16 rec_len;
+	__le32 inode;
+	__le16 rec_len;
 	u8 name_len;
 	u8 file_type;
 };
 
 struct dx_countlimit
 {
-	le_u16 limit;
-	le_u16 count;
+	__le16 limit;
+	__le16 count;
 };
 
 struct dx_entry
 {
-	le_u32 hash;
-	le_u32 block;
+	__le32 hash;
+	__le32 block;
 };
 
 /*
@@ -114,7 +111,7 @@
 	char dotdot_name[4];
 	struct dx_root_info
 	{
-		le_u32 reserved_zero;
+		__le32 reserved_zero;
 		u8 hash_version;
 		u8 info_length; /* 8 */
 		u8 indirect_levels;
@@ -184,42 +181,42 @@
 
 static inline unsigned dx_get_block (struct dx_entry *entry)
 {
-	return le32_to_cpu(entry->block.v) & 0x00ffffff;
+	return le32_to_cpu(entry->block) & 0x00ffffff;
 }
 
 static inline void dx_set_block (struct dx_entry *entry, unsigned value)
 {
-	entry->block.v = cpu_to_le32(value);
+	entry->block = cpu_to_le32(value);
 }
 
 static inline unsigned dx_get_hash (struct dx_entry *entry)
 {
-	return le32_to_cpu(entry->hash.v);
+	return le32_to_cpu(entry->hash);
 }
 
 static inline void dx_set_hash (struct dx_entry *entry, unsigned value)
 {
-	entry->hash.v = cpu_to_le32(value);
+	entry->hash = cpu_to_le32(value);
 }
 
 static inline unsigned dx_get_count (struct dx_entry *entries)
 {
-	return le16_to_cpu(((struct dx_countlimit *) entries)->count.v);
+	return le16_to_cpu(((struct dx_countlimit *) entries)->count);
 }
 
 static inline unsigned dx_get_limit (struct dx_entry *entries)
 {
-	return le16_to_cpu(((struct dx_countlimit *) entries)->limit.v);
+	return le16_to_cpu(((struct dx_countlimit *) entries)->limit);
 }
 
 static inline void dx_set_count (struct dx_entry *entries, unsigned value)
 {
-	((struct dx_countlimit *) entries)->count.v = cpu_to_le16(value);
+	((struct dx_countlimit *) entries)->count = cpu_to_le16(value);
 }
 
 static inline void dx_set_limit (struct dx_entry *entries, unsigned value)
 {
-	((struct dx_countlimit *) entries)->limit.v = cpu_to_le16(value);
+	((struct dx_countlimit *) entries)->limit = cpu_to_le16(value);
 }
 
 static inline unsigned dx_root_limit (struct inode *dir, unsigned infosize)
@@ -2258,7 +2255,7 @@
 	} else {
 		BUFFER_TRACE(new_bh, "get write access");
 		ext3_journal_get_write_access(handle, new_bh);
-		new_de->inode = le32_to_cpu(old_inode->i_ino);
+		new_de->inode = cpu_to_le32(old_inode->i_ino);
 		if (EXT3_HAS_INCOMPAT_FEATURE(new_dir->i_sb,
 					      EXT3_FEATURE_INCOMPAT_FILETYPE))
 			new_de->file_type = old_de->file_type;
@@ -2313,7 +2310,7 @@
 	if (dir_bh) {
 		BUFFER_TRACE(dir_bh, "get_write_access");
 		ext3_journal_get_write_access(handle, dir_bh);
-		PARENT_INO(dir_bh->b_data) = le32_to_cpu(new_dir->i_ino);
+		PARENT_INO(dir_bh->b_data) = cpu_to_le32(new_dir->i_ino);
 		BUFFER_TRACE(dir_bh, "call ext3_journal_dirty_metadata");
 		ext3_journal_dirty_metadata(handle, dir_bh);
 		old_dir->i_nlink--;
diff -Nru a/fs/ext3/super.c b/fs/ext3/super.c
--- a/fs/ext3/super.c	2004-10-18 14:57:03 -07:00
+++ b/fs/ext3/super.c	2004-10-18 14:57:03 -07:00
@@ -118,8 +118,6 @@
 		handle->h_err = err;
 }
 
-static char error_buf[1024];
-
 /* Deal with the reporting of failure conditions on a filesystem such as
  * inconsistencies detected or read IO failures.
  *
@@ -140,7 +138,7 @@
 	struct ext3_super_block *es = EXT3_SB(sb)->s_es;
 
 	EXT3_SB(sb)->s_mount_state |= EXT3_ERROR_FS;
-	es->s_state |= cpu_to_le32(EXT3_ERROR_FS);
+	es->s_state |= cpu_to_le16(EXT3_ERROR_FS);
 
 	if (sb->s_flags & MS_RDONLY)
 		return;
@@ -166,12 +164,11 @@
 {
 	va_list args;
 
-	va_start (args, fmt);
-	vsprintf (error_buf, fmt, args);
-	va_end (args);
-
-	printk (KERN_CRIT "EXT3-fs error (device %s): %s: %s\n",
-		sb->s_id, function, error_buf);
+	va_start(args, fmt);
+	printk(KERN_CRIT "EXT3-fs error (device %s): %s: ",sb->s_id, function);
+	vprintk(fmt, args);
+	printk("\n");
+	va_end(args);
 
 	ext3_handle_error(sb);
 }
@@ -240,21 +237,19 @@
 
 	printk (KERN_CRIT "ext3_abort called.\n");
 
-	va_start (args, fmt);
-	vsprintf (error_buf, fmt, args);
-	va_end (args);
-
-	if (test_opt (sb, ERRORS_PANIC))
-		panic ("EXT3-fs panic (device %s): %s: %s\n",
-		       sb->s_id, function, error_buf);
+	va_start(args, fmt);
+	printk(KERN_CRIT "EXT3-fs error (device %s): %s: ",sb->s_id, function);
+	vprintk(fmt, args);
+	printk("\n");
+	va_end(args);
 
-	printk (KERN_CRIT "EXT3-fs abort (device %s): %s: %s\n",
-		sb->s_id, function, error_buf);
+	if (test_opt(sb, ERRORS_PANIC))
+		panic("EXT3-fs panic from previous error\n");
 
 	if (sb->s_flags & MS_RDONLY)
 		return;
 
-	printk (KERN_CRIT "Remounting filesystem read-only\n");
+	printk(KERN_CRIT "Remounting filesystem read-only\n");
 	EXT3_SB(sb)->s_mount_state |= EXT3_ERROR_FS;
 	sb->s_flags |= MS_RDONLY;
 	EXT3_SB(sb)->s_mount_opt |= EXT3_MOUNT_ABORT;
@@ -272,15 +267,16 @@
 {
 	va_list args;
 
-	va_start (args, fmt);
-	vsprintf (error_buf, fmt, args);
-	va_end (args);
+	va_start(args, fmt);
+	printk(KERN_CRIT "EXT3-fs error (device %s): %s: ",sb->s_id, function);
+	vprintk(fmt, args);
+	printk("\n");
+	va_end(args);
 
 	/* this is to prevent panic from syncing this filesystem */
 	/* AKPM: is this sufficient? */
 	sb->s_flags |= MS_RDONLY;
-	panic ("EXT3-fs panic (device %s): %s: %s\n",
-	       sb->s_id, function, error_buf);
+	panic ("EXT3-fs panic forced\n");
 }
 
 void ext3_warning (struct super_block * sb, const char * function,
@@ -288,11 +284,12 @@
 {
 	va_list args;
 
-	va_start (args, fmt);
-	vsprintf (error_buf, fmt, args);
-	va_end (args);
-	printk (KERN_WARNING "EXT3-fs warning (device %s): %s: %s\n",
-		sb->s_id, function, error_buf);
+	va_start(args, fmt);
+	printk(KERN_WARNING "EXT3-fs warning (device %s): %s: ",
+	       sb->s_id, function);
+	vprintk(fmt, args);
+	printk("\n");
+	va_end(args);
 }
 
 void ext3_update_dynamic_rev(struct super_block *sb)
@@ -380,7 +377,7 @@
 		       "inode %s:%ld at %p: mode %o, nlink %d, next %d\n",
 		       inode->i_sb->s_id, inode->i_ino, inode,
 		       inode->i_mode, inode->i_nlink, 
-		       le32_to_cpu(NEXT_ORPHAN(inode)));
+		       NEXT_ORPHAN(inode));
 	}
 }
 
@@ -394,7 +391,7 @@
 	journal_destroy(sbi->s_journal);
 	if (!(sb->s_flags & MS_RDONLY)) {
 		EXT3_CLEAR_INCOMPAT_FEATURE(sb, EXT3_FEATURE_INCOMPAT_RECOVER);
-		es->s_state = le16_to_cpu(sbi->s_mount_state);
+		es->s_state = cpu_to_le16(sbi->s_mount_state);
 		BUFFER_TRACE(sbi->s_sbh, "marking dirty");
 		mark_buffer_dirty(sbi->s_sbh);
 		ext3_commit_super(sb, es, 1);
@@ -480,7 +477,7 @@
 {
 	ext3_inode_cachep = kmem_cache_create("ext3_inode_cache",
 					     sizeof(struct ext3_inode_info),
-					     0, SLAB_HWCACHE_ALIGN|SLAB_RECLAIM_ACCOUNT,
+					     0, SLAB_RECLAIM_ACCOUNT,
 					     init_once, NULL);
 	if (ext3_inode_cachep == NULL)
 		return -ENOMEM;
@@ -587,7 +584,7 @@
 	Opt_abort, Opt_data_journal, Opt_data_ordered, Opt_data_writeback,
 	Opt_usrjquota, Opt_grpjquota, Opt_offusrjquota, Opt_offgrpjquota,
 	Opt_jqfmt_vfsold, Opt_jqfmt_vfsv0,
-	Opt_ignore, Opt_err,
+	Opt_ignore, Opt_barrier, Opt_err,
 };
 
 static match_table_t tokens = {
@@ -632,6 +629,7 @@
 	{Opt_ignore, "noquota"},
 	{Opt_ignore, "quota"},
 	{Opt_ignore, "usrquota"},
+	{Opt_barrier, "barrier=%u"},
 	{Opt_err, NULL}
 };
 
@@ -897,6 +895,14 @@
 		case Opt_abort:
 			set_opt(sbi->s_mount_opt, ABORT);
 			break;
+		case Opt_barrier:
+			if (match_int(&args[0], &option))
+				return 0;
+			if (option)
+				set_opt(sbi->s_mount_opt, BARRIER);
+			else
+				clear_opt(sbi->s_mount_opt, BARRIER);
+			break;
 		case Opt_ignore:
 			break;
 		default:
@@ -958,8 +964,7 @@
 	es->s_state = cpu_to_le16(le16_to_cpu(es->s_state) & ~EXT3_VALID_FS);
 #endif
 	if (!(__s16) le16_to_cpu(es->s_max_mnt_count))
-		es->s_max_mnt_count =
-			(__s16) cpu_to_le16(EXT3_DFL_MAX_MNT_COUNT);
+		es->s_max_mnt_count = cpu_to_le16(EXT3_DFL_MAX_MNT_COUNT);
 	es->s_mnt_count=cpu_to_le16(le16_to_cpu(es->s_mnt_count) + 1);
 	es->s_mtime = cpu_to_le32(get_seconds());
 	ext3_update_dynamic_rev(sb);
@@ -1215,6 +1220,7 @@
 	int db_count;
 	int i;
 	int needs_recovery;
+	__le32 features;
 
 	sbi = kmalloc(sizeof(*sbi), GFP_KERNEL);
 	if (!sbi)
@@ -1307,17 +1313,18 @@
 	 * previously didn't change the revision level when setting the flags,
 	 * so there is a chance incompat flags are set on a rev 0 filesystem.
 	 */
-	if ((i = EXT3_HAS_INCOMPAT_FEATURE(sb, ~EXT3_FEATURE_INCOMPAT_SUPP))) {
+	features = EXT3_HAS_INCOMPAT_FEATURE(sb, ~EXT3_FEATURE_INCOMPAT_SUPP);
+	if (features) {
 		printk(KERN_ERR "EXT3-fs: %s: couldn't mount because of "
 		       "unsupported optional features (%x).\n",
-		       sb->s_id, i);
+		       sb->s_id, le32_to_cpu(features));
 		goto failed_mount;
 	}
-	if (!(sb->s_flags & MS_RDONLY) &&
-	    (i = EXT3_HAS_RO_COMPAT_FEATURE(sb, ~EXT3_FEATURE_RO_COMPAT_SUPP))){
+	features = EXT3_HAS_RO_COMPAT_FEATURE(sb, ~EXT3_FEATURE_RO_COMPAT_SUPP);
+	if (!(sb->s_flags & MS_RDONLY) && features) {
 		printk(KERN_ERR "EXT3-fs: %s: couldn't mount RDWR because of "
 		       "unsupported optional features (%x).\n",
-		       sb->s_id, i);
+		       sb->s_id, le32_to_cpu(features));
 		goto failed_mount;
 	}
 	blocksize = BLOCK_SIZE << le32_to_cpu(es->s_log_block_size);
@@ -1354,7 +1361,7 @@
 		}
 		es = (struct ext3_super_block *)(((char *)bh->b_data) + offset);
 		sbi->s_es = es;
-		if (es->s_magic != le16_to_cpu(EXT3_SUPER_MAGIC)) {
+		if (es->s_magic != cpu_to_le16(EXT3_SUPER_MAGIC)) {
 			printk (KERN_ERR 
 				"EXT3-fs: Magic mismatch, very weird !\n");
 			goto failed_mount;
@@ -1599,16 +1606,23 @@
  * initial mount, once the journal has been initialised but before we've
  * done any recovery; and again on any subsequent remount. 
  */
-static void ext3_init_journal_params(struct ext3_sb_info *sbi, 
-				     journal_t *journal)
+static void ext3_init_journal_params(struct super_block *sb, journal_t *journal)
 {
+	struct ext3_sb_info *sbi = EXT3_SB(sb);
+
 	if (sbi->s_commit_interval)
 		journal->j_commit_interval = sbi->s_commit_interval;
 	/* We could also set up an ext3-specific default for the commit
 	 * interval here, but for now we'll just fall back to the jbd
 	 * default. */
-}
 
+	spin_lock(&journal->j_state_lock);
+	if (test_opt(sb, BARRIER))
+		journal->j_flags |= JFS_BARRIER;
+	else
+		journal->j_flags &= ~JFS_BARRIER;
+	spin_unlock(&journal->j_state_lock);
+}
 
 static journal_t *ext3_get_journal(struct super_block *sb, int journal_inum)
 {
@@ -1646,7 +1660,7 @@
 		return NULL;
 	}
 	journal->j_private = sb;
-	ext3_init_journal_params(EXT3_SB(sb), journal);
+	ext3_init_journal_params(sb, journal);
 	return journal;
 }
 
@@ -1724,14 +1738,14 @@
 		printk(KERN_ERR "EXT3-fs: I/O error on journal device\n");
 		goto out_journal;
 	}
-	if (ntohl(journal->j_superblock->s_nr_users) != 1) {
+	if (be32_to_cpu(journal->j_superblock->s_nr_users) != 1) {
 		printk(KERN_ERR "EXT3-fs: External journal has more than one "
 					"user (unsupported) - %d\n",
-			ntohl(journal->j_superblock->s_nr_users));
+			be32_to_cpu(journal->j_superblock->s_nr_users));
 		goto out_journal;
 	}
 	EXT3_SB(sb)->journal_bdev = bdev;
-	ext3_init_journal_params(EXT3_SB(sb), journal);
+	ext3_init_journal_params(sb, journal);
 	return journal;
 out_journal:
 	journal_destroy(journal);
@@ -2028,7 +2042,7 @@
 
 	es = sbi->s_es;
 
-	ext3_init_journal_params(sbi, sbi->s_journal);
+	ext3_init_journal_params(sb, sbi->s_journal);
 
 	if ((*flags & MS_RDONLY) != (sb->s_flags & MS_RDONLY)) {
 		if (sbi->s_mount_opt & EXT3_MOUNT_ABORT)
@@ -2052,13 +2066,13 @@
 
 			ext3_mark_recovery_complete(sb, es);
 		} else {
-			int ret;
+			__le32 ret;
 			if ((ret = EXT3_HAS_RO_COMPAT_FEATURE(sb,
 					~EXT3_FEATURE_RO_COMPAT_SUPP))) {
 				printk(KERN_WARNING "EXT3-fs: %s: couldn't "
 				       "remount RDWR because of unsupported "
 				       "optional features (%x).\n",
-				       sb->s_id, ret);
+				       sb->s_id, le32_to_cpu(ret));
 				return -EROFS;
 			}
 			/*
diff -Nru a/fs/ext3/xattr.c b/fs/ext3/xattr.c
--- a/fs/ext3/xattr.c	2004-10-18 14:56:33 -07:00
+++ b/fs/ext3/xattr.c	2004-10-18 14:56:33 -07:00
@@ -1130,7 +1130,7 @@
 	}
 
 	if (entry->e_value_block == 0 && entry->e_value_size != 0) {
-		__u32 *value = (__u32 *)((char *)header +
+		__le32 *value = (__le32 *)((char *)header +
 			le16_to_cpu(entry->e_value_offs));
 		for (n = (le32_to_cpu(entry->e_value_size) +
 		     EXT3_XATTR_ROUND) >> EXT3_XATTR_PAD_BITS; n; n--) {
diff -Nru a/fs/ext3/xattr.h b/fs/ext3/xattr.h
--- a/fs/ext3/xattr.h	2004-10-18 14:57:04 -07:00
+++ b/fs/ext3/xattr.h	2004-10-18 14:57:04 -07:00
@@ -25,20 +25,20 @@
 #define EXT3_XATTR_INDEX_SECURITY	        6
 
 struct ext3_xattr_header {
-	__u32	h_magic;	/* magic number for identification */
-	__u32	h_refcount;	/* reference count */
-	__u32	h_blocks;	/* number of disk blocks used */
-	__u32	h_hash;		/* hash value of all attributes */
+	__le32	h_magic;	/* magic number for identification */
+	__le32	h_refcount;	/* reference count */
+	__le32	h_blocks;	/* number of disk blocks used */
+	__le32	h_hash;		/* hash value of all attributes */
 	__u32	h_reserved[4];	/* zero right now */
 };
 
 struct ext3_xattr_entry {
 	__u8	e_name_len;	/* length of name */
 	__u8	e_name_index;	/* attribute name index */
-	__u16	e_value_offs;	/* offset in disk block of value */
-	__u32	e_value_block;	/* disk block attribute is stored on (n/i) */
-	__u32	e_value_size;	/* size of attribute value */
-	__u32	e_hash;		/* hash value of name and value */
+	__le16	e_value_offs;	/* offset in disk block of value */
+	__le32	e_value_block;	/* disk block attribute is stored on (n/i) */
+	__le32	e_value_size;	/* size of attribute value */
+	__le32	e_hash;		/* hash value of name and value */
 	char	e_name[0];	/* attribute name */
 };
 
diff -Nru a/fs/fat/cache.c b/fs/fat/cache.c
--- a/fs/fat/cache.c	2004-10-18 14:56:49 -07:00
+++ b/fs/fat/cache.c	2004-10-18 14:56:49 -07:00
@@ -45,13 +45,13 @@
 	}
 	if (sbi->fat_bits == 32) {
 		p_first = p_last = NULL; /* GCC needs that stuff */
-		next = CF_LE_L(((__u32 *) bh->b_data)[(first &
+		next = CF_LE_L(((__le32 *) bh->b_data)[(first &
 		    (sb->s_blocksize - 1)) >> 2]);
 		/* Fscking Microsoft marketing department. Their "32" is 28. */
 		next &= 0x0fffffff;
 	} else if (sbi->fat_bits == 16) {
 		p_first = p_last = NULL; /* GCC needs that stuff */
-		next = CF_LE_W(((__u16 *) bh->b_data)[(first &
+		next = CF_LE_W(((__le16 *) bh->b_data)[(first &
 		    (sb->s_blocksize - 1)) >> 1]);
 	} else {
 		p_first = &((__u8 *)bh->b_data)[first & (sb->s_blocksize - 1)];
@@ -63,10 +63,10 @@
 	}
 	if (new_value != -1) {
 		if (sbi->fat_bits == 32) {
-			((__u32 *)bh->b_data)[(first & (sb->s_blocksize - 1)) >> 2]
+			((__le32 *)bh->b_data)[(first & (sb->s_blocksize - 1)) >> 2]
 				= CT_LE_L(new_value);
 		} else if (sbi->fat_bits == 16) {
-			((__u16 *)bh->b_data)[(first & (sb->s_blocksize - 1)) >> 1]
+			((__le16 *)bh->b_data)[(first & (sb->s_blocksize - 1)) >> 1]
 				= CT_LE_W(new_value);
 		} else {
 			if (nr & 1) {
@@ -146,7 +146,8 @@
 	sbi->cache = sbi->cache_array;
 }
 
-void fat_cache_lookup(struct inode *inode, int cluster, int *f_clu, int *d_clu)
+static void
+fat_cache_lookup(struct inode *inode, int cluster, int *f_clu, int *d_clu)
 {
 	struct msdos_sb_info *sbi = MSDOS_SB(inode->i_sb);
 	struct fat_cache *walk;
diff -Nru a/fs/fat/dir.c b/fs/fat/dir.c
--- a/fs/fat/dir.c	2004-10-18 14:55:54 -07:00
+++ b/fs/fat/dir.c	2004-10-18 14:55:54 -07:00
@@ -93,14 +93,6 @@
 }
 #endif
 
-static inline unsigned char
-fat_tolower(struct nls_table *t, unsigned char c)
-{
-	unsigned char nc = t->charset2lower[c];
-
-	return nc ? nc : c;
-}
-
 static inline int
 fat_short2uni(struct nls_table *t, unsigned char *c, int clen, wchar_t *uni)
 {
@@ -140,17 +132,6 @@
 	return charlen;
 }
 
-static int
-fat_strnicmp(struct nls_table *t, const unsigned char *s1,
-					const unsigned char *s2, int len)
-{
-	while(len--)
-		if (fat_tolower(t, *s1++) != fat_tolower(t, *s2++))
-			return 1;
-
-	return 0;
-}
-
 static inline int
 fat_shortname2uni(struct nls_table *nls, unsigned char *buf, int buf_size,
 		  wchar_t *uni_buf, unsigned short opt, int lower)
@@ -311,7 +292,7 @@
 			:uni16_to_x8(bufname, bufuname, uni_xlate, nls_io);
 		if (xlate_len == name_len)
 			if ((!anycase && !memcmp(name, bufname, xlate_len)) ||
-			    (anycase && !fat_strnicmp(nls_io, name, bufname,
+			    (anycase && !nls_strnicmp(nls_io, name, bufname,
 								xlate_len)))
 				goto Found;
 
@@ -322,7 +303,7 @@
 			if (xlate_len != name_len)
 				continue;
 			if ((!anycase && !memcmp(name, bufname, xlate_len)) ||
-			    (anycase && !fat_strnicmp(nls_io, name, bufname,
+			    (anycase && !nls_strnicmp(nls_io, name, bufname,
 								xlate_len)))
 				goto Found;
 		}
@@ -733,7 +714,7 @@
 {
 	struct buffer_head *bh;
 	struct msdos_dir_entry *de;
-	__u16 date, time;
+	__le16 date, time;
 
 	bh = fat_extend_dir(dir);
 	if (IS_ERR(bh))
@@ -745,12 +726,12 @@
 	memcpy(de[0].name,MSDOS_DOT,MSDOS_NAME);
 	memcpy(de[1].name,MSDOS_DOTDOT,MSDOS_NAME);
 	de[0].attr = de[1].attr = ATTR_DIR;
-	de[0].time = de[1].time = CT_LE_W(time);
-	de[0].date = de[1].date = CT_LE_W(date);
+	de[0].time = de[1].time = time;
+	de[0].date = de[1].date = date;
 	if (is_vfat) {	/* extra timestamps */
-		de[0].ctime = de[1].ctime = CT_LE_W(time);
+		de[0].ctime = de[1].ctime = time;
 		de[0].adate = de[0].cdate =
-			de[1].adate = de[1].cdate = CT_LE_W(date);
+			de[1].adate = de[1].cdate = date;
 	}
 	de[0].start = CT_LE_W(MSDOS_I(dir)->i_logstart);
 	de[0].starthi = CT_LE_W(MSDOS_I(dir)->i_logstart>>16);
diff -Nru a/fs/fat/file.c b/fs/fat/file.c
--- a/fs/fat/file.c	2004-10-18 14:56:27 -07:00
+++ b/fs/fat/file.c	2004-10-18 14:56:27 -07:00
@@ -90,12 +90,6 @@
 	const unsigned int cluster_size = sbi->cluster_size;
 	int nr_clusters;
 
-	/* Why no return value?  Surely the disk could fail... */
-	if (IS_RDONLY (inode))
-		return /* -EPERM */;
-	if (IS_IMMUTABLE(inode))
-		return /* -EPERM */;
-
 	/* 
 	 * This protects against truncating a file bigger than it was then
 	 * trying to write into the hole.
diff -Nru a/fs/fat/inode.c b/fs/fat/inode.c
--- a/fs/fat/inode.c	2004-10-18 14:56:29 -07:00
+++ b/fs/fat/inode.c	2004-10-18 14:56:29 -07:00
@@ -59,7 +59,7 @@
 #define FAT_HASH_SIZE	(1UL << FAT_HASH_BITS)
 #define FAT_HASH_MASK	(FAT_HASH_SIZE-1)
 static struct list_head fat_inode_hashtable[FAT_HASH_SIZE];
-spinlock_t fat_inode_lock = SPIN_LOCK_UNLOCKED;
+static spinlock_t fat_inode_lock = SPIN_LOCK_UNLOCKED;
 
 void fat_hash_init(void)
 {
@@ -579,12 +579,11 @@
  * of i_logstart is used to store the directory entry offset.
  */
 
-struct dentry *fat_decode_fh(struct super_block *sb, __u32 *fh,
-			     int len, int fhtype, 
-			     int (*acceptable)(void *context, struct dentry *de),
-			     void *context)
+static struct dentry *
+fat_decode_fh(struct super_block *sb, __u32 *fh, int len, int fhtype, 
+	      int (*acceptable)(void *context, struct dentry *de),
+	      void *context)
 {
-
 	if (fhtype != 3)
 		return ERR_PTR(-ESTALE);
 	if (len < 5)
@@ -593,7 +592,7 @@
 	return sb->s_export_op->find_exported_dentry(sb, fh, NULL, acceptable, context);
 }
 
-struct dentry *fat_get_dentry(struct super_block *sb, void *inump)
+static struct dentry *fat_get_dentry(struct super_block *sb, void *inump)
 {
 	struct inode *inode = NULL;
 	struct dentry *result;
@@ -653,7 +652,8 @@
 	return result;
 }
 
-int fat_encode_fh(struct dentry *de, __u32 *fh, int *lenp, int connectable)
+static int
+fat_encode_fh(struct dentry *de, __u32 *fh, int *lenp, int connectable)
 {
 	int len = *lenp;
 	struct inode *inode =  de->d_inode;
@@ -676,7 +676,7 @@
 	return 3;
 }
 
-struct dentry *fat_get_parent(struct dentry *child)
+static struct dentry *fat_get_parent(struct dentry *child)
 {
 	struct buffer_head *bh=NULL;
 	struct msdos_dir_entry *de = NULL;
@@ -744,7 +744,7 @@
 {
 	fat_inode_cachep = kmem_cache_create("fat_inode_cache",
 					     sizeof(struct msdos_inode_info),
-					     0, SLAB_HWCACHE_ALIGN|SLAB_RECLAIM_ACCOUNT,
+					     0, SLAB_RECLAIM_ACCOUNT,
 					     init_once, NULL);
 	if (fat_inode_cachep == NULL)
 		return -ENOMEM;
@@ -857,7 +857,7 @@
 		brelse(bh);
 		goto out_invalid;
 	}
-	logical_sector_size = CF_LE_W(get_unaligned((u16 *)&b->sector_size));
+	logical_sector_size = CF_LE_W(get_unaligned((__le16 *)&b->sector_size));
 	if (!logical_sector_size
 	    || (logical_sector_size & (logical_sector_size - 1))
 	    || (logical_sector_size < 512)
@@ -957,7 +957,7 @@
 	sbi->dir_per_block_bits = ffs(sbi->dir_per_block) - 1;
 
 	sbi->dir_start = sbi->fat_start + sbi->fats * sbi->fat_length;
-	sbi->dir_entries = CF_LE_W(get_unaligned((u16 *)&b->dir_entries));
+	sbi->dir_entries = CF_LE_W(get_unaligned((__le16 *)&b->dir_entries));
 	if (sbi->dir_entries & (sbi->dir_per_block - 1)) {
 		if (!silent)
 			printk(KERN_ERR "FAT: bogus directroy-entries per block"
@@ -969,7 +969,7 @@
 	rootdir_sectors = sbi->dir_entries
 		* sizeof(struct msdos_dir_entry) / sb->s_blocksize;
 	sbi->data_start = sbi->dir_start + rootdir_sectors;
-	total_sectors = CF_LE_W(get_unaligned((u16 *)&b->sectors));
+	total_sectors = CF_LE_W(get_unaligned((__le16 *)&b->sectors));
 	if (total_sectors == 0)
 		total_sectors = CF_LE_L(b->total_sect);
 
@@ -1227,7 +1227,7 @@
 	return 0;
 }
 
-void fat_write_inode(struct inode *inode, int wait)
+int fat_write_inode(struct inode *inode, int wait)
 {
 	struct super_block *sb = inode->i_sb;
 	struct buffer_head *bh;
@@ -1237,14 +1237,14 @@
 retry:
 	i_pos = MSDOS_I(inode)->i_pos;
 	if (inode->i_ino == MSDOS_ROOT_INO || !i_pos) {
-		return;
+		return 0;
 	}
 	lock_kernel();
 	if (!(bh = sb_bread(sb, i_pos >> MSDOS_SB(sb)->dir_per_block_bits))) {
 		printk(KERN_ERR "FAT: unable to read inode block "
 		       "for updating (i_pos %lld)\n", i_pos);
 		unlock_kernel();
-		return /* -EIO */;
+		return -EIO;
 	}
 	spin_lock(&fat_inode_lock);
 	if (i_pos != MSDOS_I(inode)->i_pos) {
@@ -1268,19 +1268,16 @@
 	    MSDOS_I(inode)->i_attrs;
 	raw_entry->start = CT_LE_W(MSDOS_I(inode)->i_logstart);
 	raw_entry->starthi = CT_LE_W(MSDOS_I(inode)->i_logstart >> 16);
-	fat_date_unix2dos(inode->i_mtime.tv_sec,&raw_entry->time,&raw_entry->date);
-	raw_entry->time = CT_LE_W(raw_entry->time);
-	raw_entry->date = CT_LE_W(raw_entry->date);
+	fat_date_unix2dos(inode->i_mtime.tv_sec, &raw_entry->time, &raw_entry->date);
 	if (MSDOS_SB(sb)->options.isvfat) {
 		fat_date_unix2dos(inode->i_ctime.tv_sec,&raw_entry->ctime,&raw_entry->cdate);
 		raw_entry->ctime_ms = MSDOS_I(inode)->i_ctime_ms; /* use i_ctime.tv_nsec? */
-		raw_entry->ctime = CT_LE_W(raw_entry->ctime);
-		raw_entry->cdate = CT_LE_W(raw_entry->cdate);
 	}
 	spin_unlock(&fat_inode_lock);
 	mark_buffer_dirty(bh);
 	brelse(bh);
 	unlock_kernel();
+	return 0;
 }
 
 
diff -Nru a/fs/fat/misc.c b/fs/fat/misc.c
--- a/fs/fat/misc.c	2004-10-18 14:56:50 -07:00
+++ b/fs/fat/misc.c	2004-10-18 14:56:50 -07:00
@@ -73,9 +73,9 @@
 		       sbi->fsinfo_sector);
 	} else {
 		if (sbi->free_clusters != -1)
-			fsinfo->free_clusters = CF_LE_L(sbi->free_clusters);
+			fsinfo->free_clusters = cpu_to_le32(sbi->free_clusters);
 		if (sbi->prev_free != -1)
-			fsinfo->next_cluster = CF_LE_L(sbi->prev_free);
+			fsinfo->next_cluster = cpu_to_le32(sbi->prev_free);
 		mark_buffer_dirty(bh);
 	}
 	brelse(bh);
@@ -243,8 +243,7 @@
 
 /* Convert linear UNIX date to a MS-DOS time/date pair. */
 
-void fat_date_unix2dos(int unix_date,unsigned short *time,
-    unsigned short *date)
+void fat_date_unix2dos(int unix_date,__le16 *time, __le16 *date)
 {
 	int day,year,nl_day,month;
 
@@ -254,8 +253,8 @@
 	if (unix_date < 315532800)
 		unix_date = 315532800;
 
-	*time = (unix_date % 60)/2+(((unix_date/60) % 60) << 5)+
-	    (((unix_date/3600) % 24) << 11);
+	*time = cpu_to_le16((unix_date % 60)/2+(((unix_date/60) % 60) << 5)+
+	    (((unix_date/3600) % 24) << 11));
 	day = unix_date/86400-3652;
 	year = day/365;
 	if ((year+3)/4+365*year > day) year--;
@@ -269,7 +268,7 @@
 		for (month = 0; month < 12; month++)
 			if (day_n[month] > nl_day) break;
 	}
-	*date = nl_day-day_n[month-1]+1+(month << 5)+(year << 9);
+	*date = cpu_to_le16(nl_day-day_n[month-1]+1+(month << 5)+(year << 9));
 }
 
 
diff -Nru a/fs/fcntl.c b/fs/fcntl.c
--- a/fs/fcntl.c	2004-10-18 14:56:34 -07:00
+++ b/fs/fcntl.c	2004-10-18 14:56:34 -07:00
@@ -497,11 +497,9 @@
 			send_sigio_to_task(p, fown, fd, band);
 		}
 	} else {
-		struct list_head *l;
-		struct pid *pidptr;
-		for_each_task_pid(-pid, PIDTYPE_PGID, p, l, pidptr) {
+		do_each_task_pid(-pid, PIDTYPE_PGID, p) {
 			send_sigio_to_task(p, fown, fd, band);
-		}
+		} while_each_task_pid(-pid, PIDTYPE_PGID, p);
 	}
 	read_unlock(&tasklist_lock);
  out_unlock_fown:
@@ -534,11 +532,9 @@
 			send_sigurg_to_task(p, fown);
 		}
 	} else {
-		struct list_head *l;
-		struct pid *pidptr;
-		for_each_task_pid(-pid, PIDTYPE_PGID, p, l, pidptr) {
+		do_each_task_pid(-pid, PIDTYPE_PGID, p) {
 			send_sigurg_to_task(p, fown);
-		}
+		} while_each_task_pid(-pid, PIDTYPE_PGID, p);
 	}
 	read_unlock(&tasklist_lock);
  out_unlock_fown:
diff -Nru a/fs/file_table.c b/fs/file_table.c
--- a/fs/file_table.c	2004-10-18 14:55:54 -07:00
+++ b/fs/file_table.c	2004-10-18 14:55:54 -07:00
@@ -106,52 +106,6 @@
 
 EXPORT_SYMBOL(get_empty_filp);
 
-/*
- * Clear and initialize a (private) struct file for the given dentry,
- * allocate the security structure, and call the open function (if any).  
- * The file should be released using close_private_file.
- */
-int open_private_file(struct file *filp, struct dentry *dentry, int flags)
-{
-	int error;
-	memset(filp, 0, sizeof(*filp));
-	eventpoll_init_file(filp);
-	filp->f_flags  = flags;
-	filp->f_mode   = ((flags+1) & O_ACCMODE) | FMODE_LSEEK | FMODE_PREAD | FMODE_PWRITE;
-	atomic_set(&filp->f_count, 1);
-	filp->f_dentry = dentry;
-	filp->f_mapping = dentry->d_inode->i_mapping;
-	filp->f_uid    = current->fsuid;
-	filp->f_gid    = current->fsgid;
-	filp->f_op     = dentry->d_inode->i_fop;
-	INIT_LIST_HEAD(&filp->f_list);
-	error = security_file_alloc(filp);
-	if (!error)
-		if (filp->f_op && filp->f_op->open) {
-			error = filp->f_op->open(dentry->d_inode, filp);
-			if (error)
-				security_file_free(filp);
-		}
-	return error;
-}
-
-EXPORT_SYMBOL(open_private_file);
-
-/*
- * Release a private file by calling the release function (if any) and
- * freeing the security structure.
- */
-void close_private_file(struct file *file)
-{
-	struct inode * inode = file->f_dentry->d_inode;
-
-	if (file->f_op && file->f_op->release)
-		file->f_op->release(inode, file);
-	security_file_free(file);
-}
-
-EXPORT_SYMBOL(close_private_file);
-
 void fastcall fput(struct file *file)
 {
 	if (atomic_dec_and_test(&file->f_count))
@@ -169,6 +123,7 @@
 	struct vfsmount *mnt = file->f_vfsmnt;
 	struct inode *inode = dentry->d_inode;
 
+	might_sleep();
 	/*
 	 * The function eventpoll_release() should be the first called
 	 * in the file cleanup chain.
diff -Nru a/fs/freevxfs/vxfs_extern.h b/fs/freevxfs/vxfs_extern.h
--- a/fs/freevxfs/vxfs_extern.h	2004-10-18 14:57:04 -07:00
+++ b/fs/freevxfs/vxfs_extern.h	2004-10-18 14:57:04 -07:00
@@ -59,7 +59,7 @@
 extern struct vxfs_inode_info *	vxfs_blkiget(struct super_block *, u_long, ino_t);
 extern struct vxfs_inode_info *	vxfs_stiget(struct super_block *, ino_t);
 extern void			vxfs_read_inode(struct inode *);
-extern void			vxfs_put_inode(struct inode *);
+extern void			vxfs_clear_inode(struct inode *);
 
 /* vxfs_lookup.c */
 extern struct inode_operations	vxfs_dir_inode_ops;
diff -Nru a/fs/freevxfs/vxfs_inode.c b/fs/freevxfs/vxfs_inode.c
--- a/fs/freevxfs/vxfs_inode.c	2004-10-18 14:56:17 -07:00
+++ b/fs/freevxfs/vxfs_inode.c	2004-10-18 14:56:17 -07:00
@@ -337,16 +337,15 @@
 }
 
 /**
- * vxfs_put_inode - remove inode from main memory
+ * vxfs_clear_inode - remove inode from main memory
  * @ip:		inode to discard.
  *
  * Description:
- *  vxfs_put_inode() is called on each iput.  If we are the last
- *  link in memory, free the fspriv inode area.
+ *  vxfs_clear_inode() is called on the final iput and frees the private
+ *  inode area.
  */
 void
-vxfs_put_inode(struct inode *ip)
+vxfs_clear_inode(struct inode *ip)
 {
-	if (atomic_read(&ip->i_count) == 1)
-		kmem_cache_free(vxfs_inode_cachep, ip->u.generic_ip);
+	kmem_cache_free(vxfs_inode_cachep, ip->u.generic_ip);
 }
diff -Nru a/fs/freevxfs/vxfs_super.c b/fs/freevxfs/vxfs_super.c
--- a/fs/freevxfs/vxfs_super.c	2004-10-18 14:56:50 -07:00
+++ b/fs/freevxfs/vxfs_super.c	2004-10-18 14:56:50 -07:00
@@ -60,7 +60,7 @@
 
 static struct super_operations vxfs_super_ops = {
 	.read_inode =		vxfs_read_inode,
-	.put_inode =		vxfs_put_inode,
+	.clear_inode =		vxfs_clear_inode,
 	.put_super =		vxfs_put_super,
 	.statfs =		vxfs_statfs,
 	.remount_fs =		vxfs_remount,
diff -Nru a/fs/fs-writeback.c b/fs/fs-writeback.c
--- a/fs/fs-writeback.c	2004-10-18 14:57:05 -07:00
+++ b/fs/fs-writeback.c	2004-10-18 14:57:05 -07:00
@@ -133,10 +133,11 @@
 
 EXPORT_SYMBOL(__mark_inode_dirty);
 
-static void write_inode(struct inode *inode, int sync)
+static int write_inode(struct inode *inode, int sync)
 {
 	if (inode->i_sb->s_op->write_inode && !is_bad_inode(inode))
-		inode->i_sb->s_op->write_inode(inode, sync);
+		return inode->i_sb->s_op->write_inode(inode, sync);
+	return 0;
 }
 
 /*
@@ -170,8 +171,11 @@
 	ret = do_writepages(mapping, wbc);
 
 	/* Don't write the inode if only I_DIRTY_PAGES was set */
-	if (dirty & (I_DIRTY_SYNC | I_DIRTY_DATASYNC))
-		write_inode(inode, wait);
+	if (dirty & (I_DIRTY_SYNC | I_DIRTY_DATASYNC)) {
+		int err = write_inode(inode, wait);
+		if (ret == 0)
+			ret = err;
+	}
 
 	if (wait) {
 		int err = filemap_fdatawait(mapping);
@@ -304,14 +308,20 @@
 		long pages_skipped;
 
 		if (bdi->memory_backed) {
+			list_move(&inode->i_list, &sb->s_dirty);
 			if (sb == blockdev_superblock) {
 				/*
 				 * Dirty memory-backed blockdev: the ramdisk
-				 * driver does this.
+				 * driver does this.  Skip just this inode
 				 */
-				list_move(&inode->i_list, &sb->s_dirty);
 				continue;
 			}
+			/*
+			 * Dirty memory-backed inode against a filesystem other
+			 * than the kernel-internal bdev filesystem.  Skip the
+			 * entire superblock.
+			 */
+			break;
 		}
 
 		if (wbc->nonblocking && bdi_write_congested(bdi)) {
@@ -392,7 +402,7 @@
 {
 	struct super_block *sb;
 
-	spin_lock(&inode_lock);
+	might_sleep();
 	spin_lock(&sb_lock);
 restart:
 	sb = sb_entry(super_blocks.prev);
@@ -407,19 +417,21 @@
 			 * be unmounted by the time it is released.
 			 */
 			if (down_read_trylock(&sb->s_umount)) {
-				if (sb->s_root)
+				if (sb->s_root) {
+					spin_lock(&inode_lock);
 					sync_sb_inodes(sb, wbc);
+					spin_unlock(&inode_lock);
+				}
 				up_read(&sb->s_umount);
 			}
 			spin_lock(&sb_lock);
-			if (__put_super(sb))
+			if (__put_super_and_need_restart(sb))
 				goto restart;
 		}
 		if (wbc->nr_to_write <= 0)
 			break;
 	}
 	spin_unlock(&sb_lock);
-	spin_unlock(&inode_lock);
 }
 
 /*
@@ -547,6 +559,7 @@
 	if (inode->i_mapping->backing_dev_info->memory_backed)
 		return;
 
+	might_sleep();
 	spin_lock(&inode_lock);
 	__writeback_single_inode(inode, &wbc);
 	spin_unlock(&inode_lock);
diff -Nru a/fs/hfs/bfind.c b/fs/hfs/bfind.c
--- a/fs/hfs/bfind.c	2004-10-18 14:56:49 -07:00
+++ b/fs/hfs/bfind.c	2004-10-18 14:56:49 -07:00
@@ -85,7 +85,8 @@
 {
 	struct hfs_btree *tree;
 	struct hfs_bnode *bnode;
-	u32 data, nidx, parent;
+	u32 nidx, parent;
+	__be32 data;
 	int height, res;
 
 	tree = fd->tree;
diff -Nru a/fs/hfs/bitmap.c b/fs/hfs/bitmap.c
--- a/fs/hfs/bitmap.c	2004-10-18 14:57:04 -07:00
+++ b/fs/hfs/bitmap.c	2004-10-18 14:57:04 -07:00
@@ -26,10 +26,11 @@
  *  Accesses memory in 32-bit aligned chunks of 32-bits and thus
  *  may read beyond the 'size'th bit.
  */
-static u32 hfs_find_set_zero_bits(u32 *bitmap, u32 size, u32 offset, u32 *max)
+static u32 hfs_find_set_zero_bits(__be32 *bitmap, u32 size, u32 offset, u32 *max)
 {
-	u32 *curr, *end;
-	u32 val, mask, start, len;
+	__be32 *curr, *end;
+	u32 mask, start, len, n;
+	__be32 val;
 	int i;
 
 	len = *max;
@@ -42,11 +43,11 @@
 	/* scan the first partial u32 for zero bits */
 	val = *curr;
 	if (~val) {
-		val = be32_to_cpu(val);
+		n = be32_to_cpu(val);
 		i = offset % 32;
 		mask = (1U << 31) >> i;
 		for (; i < 32; mask >>= 1, i++) {
-			if (!(val & mask))
+			if (!(n & mask))
 				goto found;
 		}
 	}
@@ -55,10 +56,10 @@
 	while (++curr < end) {
 		val = *curr;
 		if (~val) {
-			val = be32_to_cpu(val);
+			n = be32_to_cpu(val);
 			mask = 1 << 31;
 			for (i = 0; i < 32; mask >>= 1, i++) {
-				if (!(val & mask))
+				if (!(n & mask))
 					goto found;
 			}
 		}
@@ -72,38 +73,38 @@
 	/* do any partial u32 at the start */
 	len = min(size - start, len);
 	while (1) {
-		val |= mask;
+		n |= mask;
 		if (++i >= 32)
 			break;
 		mask >>= 1;
-		if (!--len || val & mask)
+		if (!--len || n & mask)
 			goto done;
 	}
 	if (!--len)
 		goto done;
-	*curr++ = cpu_to_be32(val);
+	*curr++ = cpu_to_be32(n);
 	/* do full u32s */
 	while (1) {
-		val = be32_to_cpu(*curr);
+		n = be32_to_cpu(*curr);
 		if (len < 32)
 			break;
-		if (val) {
+		if (n) {
 			len = 32;
 			break;
 		}
-		*curr++ = 0xffffffffU;
+		*curr++ = cpu_to_be32(0xffffffff);
 		len -= 32;
 	}
 	/* do any partial u32 at end */
 	mask = 1U << 31;
 	for (i = 0; i < len; i++) {
-		if (val & mask)
+		if (n & mask)
 			break;
-		val |= mask;
+		n |= mask;
 		mask >>= 1;
 	}
 done:
-	*curr = cpu_to_be32(val);
+	*curr = cpu_to_be32(n);
 	*max = (curr - bitmap) * 32 + i - start;
 	return start;
 }
@@ -191,7 +192,7 @@
  */
 int hfs_clear_vbm_bits(struct super_block *sb, u16 start, u16 count)
 {
-	u32 *curr;
+	__be32 *curr;
 	u32 mask;
 	int i, len;
 
diff -Nru a/fs/hfs/bnode.c b/fs/hfs/bnode.c
--- a/fs/hfs/bnode.c	2004-10-18 14:56:28 -07:00
+++ b/fs/hfs/bnode.c	2004-10-18 14:56:28 -07:00
@@ -29,7 +29,7 @@
 
 u16 hfs_bnode_read_u16(struct hfs_bnode *node, int off)
 {
-	u16 data;
+	__be16 data;
 	// optimize later...
 	hfs_bnode_read(node, &data, off, 2);
 	return be16_to_cpu(data);
@@ -72,9 +72,9 @@
 
 void hfs_bnode_write_u16(struct hfs_bnode *node, int off, u16 data)
 {
-	data = cpu_to_be16(data);
+	__be16 v = cpu_to_be16(data);
 	// optimize later...
-	hfs_bnode_write(node, &data, off, 2);
+	hfs_bnode_write(node, &v, off, 2);
 }
 
 void hfs_bnode_write_u8(struct hfs_bnode *node, int off, u8 data)
@@ -136,7 +136,7 @@
 void hfs_bnode_dump(struct hfs_bnode *node)
 {
 	struct hfs_bnode_desc desc;
-	u32 cnid;
+	__be32 cnid;
 	int i, off, key_off;
 
 	dprint(DBG_BNODE_MOD, "bnode: %d\n", node->this);
@@ -173,7 +173,7 @@
 {
 	struct hfs_btree *tree;
 	struct hfs_bnode *tmp;
-	u32 cnid;
+	__be32 cnid;
 
 	tree = node->tree;
 	if (node->prev) {
diff -Nru a/fs/hfs/brec.c b/fs/hfs/brec.c
--- a/fs/hfs/brec.c	2004-10-18 14:56:32 -07:00
+++ b/fs/hfs/brec.c	2004-10-18 14:56:32 -07:00
@@ -13,7 +13,7 @@
 /* Get the length and offset of the given record in the given node */
 u16 hfs_brec_lenoff(struct hfs_bnode *node, u16 rec, u16 *off)
 {
-	u16 retval[2];
+	__be16 retval[2];
 	u16 dataoff;
 
 	dataoff = node->tree->node_size - (rec + 2) * 2;
@@ -55,7 +55,7 @@
 	int size, key_len, rec;
 	int data_off, end_off;
 	int idx_rec_off, data_rec_off, end_rec_off;
-	u32 cnid;
+	__be32 cnid;
 
 	tree = fd->tree;
 	if (!fd->bnode) {
@@ -391,7 +391,7 @@
 	node = parent;
 
 	if (new_node) {
-		u32 cnid;
+		__be32 cnid;
 
 		fd->bnode = hfs_bnode_find(tree, new_node->parent);
 		/* create index key and entry */
@@ -423,7 +423,7 @@
 	struct hfs_bnode *node, *new_node;
 	struct hfs_bnode_desc node_desc;
 	int key_size, rec;
-	u32 cnid;
+	__be32 cnid;
 
 	node = NULL;
 	if (tree->root) {
diff -Nru a/fs/hfs/btree.c b/fs/hfs/btree.c
--- a/fs/hfs/btree.c	2004-10-18 14:56:28 -07:00
+++ b/fs/hfs/btree.c	2004-10-18 14:56:28 -07:00
@@ -154,7 +154,7 @@
 	struct hfs_btree *tree = prev->tree;
 	struct hfs_bnode *node;
 	struct hfs_bnode_desc desc;
-	u32 cnid;
+	__be32 cnid;
 
 	node = hfs_bnode_create(tree, idx);
 	if (IS_ERR(node))
diff -Nru a/fs/hfs/btree.h b/fs/hfs/btree.h
--- a/fs/hfs/btree.h	2004-10-18 14:57:04 -07:00
+++ b/fs/hfs/btree.h	2004-10-18 14:57:04 -07:00
@@ -125,11 +125,11 @@
 
 
 struct hfs_bnode_desc {
-	u32 next;		/* (V) Number of the next node at this level */
-	u32 prev;		/* (V) Number of the prev node at this level */
+	__be32 next;		/* (V) Number of the next node at this level */
+	__be32 prev;		/* (V) Number of the prev node at this level */
 	u8 type;		/* (F) The type of node */
 	u8 height;		/* (F) The level of this node (leaves=1) */
-	u16 num_recs;		/* (V) The number of records in this node */
+	__be16 num_recs;	/* (V) The number of records in this node */
 	u16 reserved;
 } __packed;
 
@@ -139,20 +139,20 @@
 #define HFS_NODE_LEAF	0xFF	/* A leaf (ndNHeight==1) node */
 
 struct hfs_btree_header_rec {
-	u16 depth;		/* (V) The number of levels in this B-tree */
-	u32 root;		/* (V) The node number of the root node */
-	u32 leaf_count;		/* (V) The number of leaf records */
-	u32 leaf_head;		/* (V) The number of the first leaf node */
-	u32 leaf_tail;		/* (V) The number of the last leaf node */
-	u16 node_size;		/* (F) The number of bytes in a node (=512) */
-	u16 max_key_len;	/* (F) The length of a key in an index node */
-	u32 node_count;		/* (V) The total number of nodes */
-	u32 free_nodes;		/* (V) The number of unused nodes */
+	__be16 depth;		/* (V) The number of levels in this B-tree */
+	__be32 root;		/* (V) The node number of the root node */
+	__be32 leaf_count;	/* (V) The number of leaf records */
+	__be32 leaf_head;	/* (V) The number of the first leaf node */
+	__be32 leaf_tail;	/* (V) The number of the last leaf node */
+	__be16 node_size;	/* (F) The number of bytes in a node (=512) */
+	__be16 max_key_len;	/* (F) The length of a key in an index node */
+	__be32 node_count;	/* (V) The total number of nodes */
+	__be32 free_nodes;	/* (V) The number of unused nodes */
 	u16 reserved1;
-	u32 clump_size;		/* (F) clump size. not usually used. */
+	__be32 clump_size;	/* (F) clump size. not usually used. */
 	u8 btree_type;		/* (F) BTree type */
 	u8 reserved2;
-	u32 attributes;		/* (F) attributes */
+	__be32 attributes;	/* (F) attributes */
 	u32 reserved3[16];
 } __packed;
 
diff -Nru a/fs/hfs/catalog.c b/fs/hfs/catalog.c
--- a/fs/hfs/catalog.c	2004-10-18 14:56:49 -07:00
+++ b/fs/hfs/catalog.c	2004-10-18 14:56:49 -07:00
@@ -35,7 +35,7 @@
 
 int hfs_cat_build_record(hfs_cat_rec *rec, u32 cnid, struct inode *inode)
 {
-	u32 mtime = hfs_mtime();
+	__be32 mtime = hfs_mtime();
 
 	memset(rec, 0, sizeof(*rec));
 	if (S_ISDIR(inode->i_mode)) {
diff -Nru a/fs/hfs/extent.c b/fs/hfs/extent.c
--- a/fs/hfs/extent.c	2004-10-18 14:56:32 -07:00
+++ b/fs/hfs/extent.c	2004-10-18 14:56:32 -07:00
@@ -279,13 +279,13 @@
 	int res, i;
 
 	if (type == HFS_FK_DATA) {
-		total_blocks = file->PyLen;
+		total_blocks = be32_to_cpu(file->PyLen);
 		extent = file->ExtRec;
 	} else {
-		total_blocks = file->RPyLen;
+		total_blocks = be32_to_cpu(file->RPyLen);
 		extent = file->RExtRec;
 	}
-	total_blocks = be32_to_cpu(total_blocks) / HFS_SB(sb)->alloc_blksz;
+	total_blocks /= HFS_SB(sb)->alloc_blksz;
 	if (!total_blocks)
 		return 0;
 
diff -Nru a/fs/hfs/hfs.h b/fs/hfs/hfs.h
--- a/fs/hfs/hfs.h	2004-10-18 14:56:29 -07:00
+++ b/fs/hfs/hfs.h	2004-10-18 14:56:29 -07:00
@@ -91,45 +91,45 @@
 } __packed;
 
 struct hfs_point {
-	u16 v;
-	u16 h;
+	__be16 v;
+	__be16 h;
 } __packed;
 
 struct hfs_rect {
-	u16 top;
-	u16 left;
-	u16 bottom;
-	u16 right;
+	__be16 top;
+	__be16 left;
+	__be16 bottom;
+	__be16 right;
 } __packed;
 
 struct hfs_finfo {
-	u32 fdType;
-	u32 fdCreator;
-	u16 fdFlags;
+	__be32 fdType;
+	__be32 fdCreator;
+	__be16 fdFlags;
 	struct hfs_point fdLocation;
-	u16 fdFldr;
+	__be16 fdFldr;
 } __packed;
 
 struct hfs_fxinfo {
-	u16 fdIconID;
+	__be16 fdIconID;
 	u8 fdUnused[8];
-	u16 fdComment;
-	u32 fdPutAway;
+	__be16 fdComment;
+	__be32 fdPutAway;
 } __packed;
 
 struct hfs_dinfo {
 	struct hfs_rect frRect;
-	u16 frFlags;
+	__be16 frFlags;
 	struct hfs_point frLocation;
-	u16 frView;
+	__be16 frView;
 } __packed;
 
 struct hfs_dxinfo {
 	struct hfs_point frScroll;
-	u32 frOpenChain;
-	u16 frUnused;
-	u16 frComment;
-	u32 frPutAway;
+	__be32 frOpenChain;
+	__be16 frUnused;
+	__be16 frComment;
+	__be32 frPutAway;
 } __packed;
 
 union hfs_finder_info {
@@ -150,7 +150,7 @@
 struct hfs_cat_key {
 	u8 key_len;		/* number of bytes in the key */
 	u8 reserved;		/* padding */
-	u32 ParID;		/* CNID of the parent dir */
+	__be32 ParID;		/* CNID of the parent dir */
 	struct hfs_name	CName;	/* The filename of the entry */
 } __packed;
 
@@ -158,8 +158,8 @@
 struct hfs_ext_key {
 	u8 key_len;		/* number of bytes in the key */
 	u8 FkType;		/* HFS_FK_{DATA,RSRC} */
-	u32 FNum;		/* The File ID of the file */
-	u16 FABN;		/* allocation blocks number*/
+	__be32 FNum;		/* The File ID of the file */
+	__be16 FABN;		/* allocation blocks number*/
 } __packed;
 
 typedef union hfs_btree_key {
@@ -171,8 +171,8 @@
 typedef union hfs_btree_key btree_key;
 
 struct hfs_extent {
-	u16 block;
-	u16 count;
+	__be16 block;
+	__be16 count;
 };
 typedef struct hfs_extent hfs_extent_rec[3];
 
@@ -183,18 +183,18 @@
 	u8 Flags;			/* Flags such as read-only */
 	s8 Typ;				/* file version number = 0 */
 	struct hfs_finfo UsrWds;	/* data used by the Finder */
-	u32 FlNum;			/* The CNID */
-	u16 StBlk;			/* obsolete */
-	u32 LgLen;			/* The logical EOF of the data fork*/
-	u32 PyLen;			/* The physical EOF of the data fork */
-	u16 RStBlk;			/* obsolete */
-	u32 RLgLen;			/* The logical EOF of the rsrc fork */
-	u32 RPyLen;			/* The physical EOF of the rsrc fork */
-	u32 CrDat;			/* The creation date */
-	u32 MdDat;			/* The modified date */
-	u32 BkDat;			/* The last backup date */
+	__be32 FlNum;			/* The CNID */
+	__be16 StBlk;			/* obsolete */
+	__be32 LgLen;			/* The logical EOF of the data fork*/
+	__be32 PyLen;			/* The physical EOF of the data fork */
+	__be16 RStBlk;			/* obsolete */
+	__be32 RLgLen;			/* The logical EOF of the rsrc fork */
+	__be32 RPyLen;			/* The physical EOF of the rsrc fork */
+	__be32 CrDat;			/* The creation date */
+	__be32 MdDat;			/* The modified date */
+	__be32 BkDat;			/* The last backup date */
 	struct hfs_fxinfo FndrInfo;	/* more data for the Finder */
-	u16 ClpSize;			/* number of bytes to allocate
+	__be16 ClpSize;			/* number of bytes to allocate
 					   when extending files */
 	hfs_extent_rec ExtRec;		/* first extent record
 					   for the data fork */
@@ -207,13 +207,13 @@
 struct hfs_cat_dir {
 	s8 type;			/* The type of entry */
 	u8 reserved;
-	u16 Flags;			/* flags */
-	u16 Val;			/* Valence: number of files and
+	__be16 Flags;			/* flags */
+	__be16 Val;			/* Valence: number of files and
 					   dirs in the directory */
-	u32 DirID;			/* The CNID */
-	u32 CrDat;			/* The creation date */
-	u32 MdDat;			/* The modification date */
-	u32 BkDat;			/* The last backup date */
+	__be32 DirID;			/* The CNID */
+	__be32 CrDat;			/* The creation date */
+	__be32 MdDat;			/* The modification date */
+	__be32 BkDat;			/* The last backup date */
 	struct hfs_dinfo UsrInfo;	/* data used by the Finder */
 	struct hfs_dxinfo FndrInfo;	/* more data used by Finder */
 	u8 Resrv[16];			/* reserved by Apple */
@@ -223,7 +223,7 @@
 struct hfs_cat_thread {
 	s8 type;			/* The type of entry */
 	u8 reserved[9];			/* reserved by Apple */
-	u32 ParID;			/* CNID of parent directory */
+	__be32 ParID;			/* CNID of parent directory */
 	struct hfs_name CName;		/* The name of this entry */
 }  __packed;
 
@@ -236,43 +236,43 @@
 } hfs_cat_rec;
 
 struct hfs_mdb {
-	u16 drSigWord;			/* Signature word indicating fs type */
-	u32 drCrDate;			/* fs creation date/time */
-	u32 drLsMod;			/* fs modification date/time */
-	u16 drAtrb;			/* fs attributes */
-	u16 drNmFls;			/* number of files in root directory */
-	u16 drVBMSt;			/* location (in 512-byte blocks)
+	__be16 drSigWord;		/* Signature word indicating fs type */
+	__be32 drCrDate;		/* fs creation date/time */
+	__be32 drLsMod;			/* fs modification date/time */
+	__be16 drAtrb;			/* fs attributes */
+	__be16 drNmFls;			/* number of files in root directory */
+	__be16 drVBMSt;			/* location (in 512-byte blocks)
 					   of the volume bitmap */
-	u16 drAllocPtr;			/* location (in allocation blocks)
+	__be16 drAllocPtr;		/* location (in allocation blocks)
 					   to begin next allocation search */
-	u16 drNmAlBlks;			/* number of allocation blocks */
-	u32 drAlBlkSiz;			/* bytes in an allocation block */
-	u32 drClpSiz;			/* clumpsize, the number of bytes to
+	__be16 drNmAlBlks;		/* number of allocation blocks */
+	__be32 drAlBlkSiz;		/* bytes in an allocation block */
+	__be32 drClpSiz;		/* clumpsize, the number of bytes to
 					   allocate when extending a file */
-	u16 drAlBlSt;			/* location (in 512-byte blocks)
+	__be16 drAlBlSt;		/* location (in 512-byte blocks)
 					   of the first allocation block */
-	u32 drNxtCNID;			/* CNID to assign to the next
+	__be32 drNxtCNID;		/* CNID to assign to the next
 					   file or directory created */
-	u16 drFreeBks;			/* number of free allocation blocks */
+	__be16 drFreeBks;		/* number of free allocation blocks */
 	u8 drVN[28];			/* the volume label */
-	u32 drVolBkUp;			/* fs backup date/time */
-	u16 drVSeqNum;			/* backup sequence number */
-	u32 drWrCnt;			/* fs write count */
-	u32 drXTClpSiz;			/* clumpsize for the extents B-tree */
-	u32 drCTClpSiz;			/* clumpsize for the catalog B-tree */
-	u16 drNmRtDirs;			/* number of directories in
+	__be32 drVolBkUp;		/* fs backup date/time */
+	__be16 drVSeqNum;		/* backup sequence number */
+	__be32 drWrCnt;			/* fs write count */
+	__be32 drXTClpSiz;		/* clumpsize for the extents B-tree */
+	__be32 drCTClpSiz;		/* clumpsize for the catalog B-tree */
+	__be16 drNmRtDirs;		/* number of directories in
 					   the root directory */
-	u32 drFilCnt;			/* number of files in the fs */
-	u32 drDirCnt;			/* number of directories in the fs */
+	__be32 drFilCnt;		/* number of files in the fs */
+	__be32 drDirCnt;		/* number of directories in the fs */
 	u8 drFndrInfo[32];		/* data used by the Finder */
-	u16 drEmbedSigWord;		/* embedded volume signature */
-	u32 drEmbedExtent;		/* starting block number (xdrStABN)
+	__be16 drEmbedSigWord;		/* embedded volume signature */
+	__be32 drEmbedExtent;		/* starting block number (xdrStABN)
 					   and number of allocation blocks
 					   (xdrNumABlks) occupied by embedded
 					   volume */
-	u32 drXTFlSize;			/* bytes in the extents B-tree */
+	__be32 drXTFlSize;		/* bytes in the extents B-tree */
 	hfs_extent_rec drXTExtRec;	/* extents B-tree's first 3 extents */
-	u32 drCTFlSize;			/* bytes in the catalog B-tree */
+	__be32 drCTFlSize;		/* bytes in the catalog B-tree */
 	hfs_extent_rec drCTExtRec;	/* catalog B-tree's first 3 extents */
 } __packed;
 
diff -Nru a/fs/hfs/hfs_fs.h b/fs/hfs/hfs_fs.h
--- a/fs/hfs/hfs_fs.h	2004-10-18 14:56:48 -07:00
+++ b/fs/hfs/hfs_fs.h	2004-10-18 14:56:48 -07:00
@@ -90,7 +90,7 @@
 	struct buffer_head *alt_mdb_bh;		/* The hfs_buffer holding
 						   the alternate superblock */
 	struct hfs_mdb *alt_mdb;
-	u32 *bitmap;				/* The page holding the
+	__be32 *bitmap;				/* The page holding the
 						   allocation bitmap */
 	struct hfs_btree *ext_tree;			/* Information about
 						   the extents b-tree */
@@ -129,8 +129,8 @@
 						   "allocation block" */
 	int s_quiet;				/* Silent failure when
 						   changing owner or mode? */
-	u32 s_type;				/* Type for new files */
-	u32 s_creator;				/* Creator for new files */
+	__be32 s_type;				/* Type for new files */
+	__be32 s_creator;			/* Creator for new files */
 	umode_t s_file_umask;			/* The umask applied to the
 						   permissions on all files */
 	umode_t s_dir_umask;			/* The umask applied to the
@@ -197,11 +197,11 @@
 extern struct address_space_operations hfs_btree_aops;
 
 extern struct inode *hfs_new_inode(struct inode *, struct qstr *, int);
-extern void hfs_inode_write_fork(struct inode *, struct hfs_extent *, u32 *, u32 *);
-extern void hfs_write_inode(struct inode *, int);
+extern void hfs_inode_write_fork(struct inode *, struct hfs_extent *, __be32 *, __be32 *);
+extern int hfs_write_inode(struct inode *, int);
 extern int hfs_inode_setattr(struct dentry *, struct iattr *);
 extern void hfs_inode_read_fork(struct inode *inode, struct hfs_extent *ext,
-				u32 log_size, u32 phys_size, u32 clump_size);
+			__be32 log_size, __be32 phys_size, u32 clump_size);
 extern struct inode *hfs_iget(struct super_block *, struct hfs_cat_key *, hfs_cat_rec *);
 extern void hfs_clear_inode(struct inode *);
 extern void hfs_delete_inode(struct inode *);
@@ -222,9 +222,6 @@
 extern int hfs_strcmp(const unsigned char *, unsigned int,
 		      const unsigned char *, unsigned int);
 extern int hfs_compare_dentry(struct dentry *, struct qstr *, struct qstr *);
-
-/* super.c */
-extern struct super_block *hfs_read_super(struct super_block *,void *,int);
 
 /* trans.c */
 extern void hfs_triv2mac(struct hfs_name *, struct qstr *);
diff -Nru a/fs/hfs/inode.c b/fs/hfs/inode.c
--- a/fs/hfs/inode.c	2004-10-18 14:57:04 -07:00
+++ b/fs/hfs/inode.c	2004-10-18 14:57:04 -07:00
@@ -210,14 +210,14 @@
 	dprint(DBG_INODE, "delete_inode: %lu\n", inode->i_ino);
 	if (S_ISDIR(inode->i_mode)) {
 		HFS_SB(sb)->folder_count--;
-		if (HFS_I(inode)->cat_key.ParID == be32_to_cpu(HFS_ROOT_CNID))
+		if (HFS_I(inode)->cat_key.ParID == cpu_to_be32(HFS_ROOT_CNID))
 			HFS_SB(sb)->root_dirs--;
 		set_bit(HFS_FLG_MDB_DIRTY, &HFS_SB(sb)->flags);
 		sb->s_dirt = 1;
 		return;
 	}
 	HFS_SB(sb)->file_count--;
-	if (HFS_I(inode)->cat_key.ParID == be32_to_cpu(HFS_ROOT_CNID))
+	if (HFS_I(inode)->cat_key.ParID == cpu_to_be32(HFS_ROOT_CNID))
 		HFS_SB(sb)->root_files--;
 	if (S_ISREG(inode->i_mode)) {
 		if (!inode->i_nlink) {
@@ -230,9 +230,10 @@
 }
 
 void hfs_inode_read_fork(struct inode *inode, struct hfs_extent *ext,
-			 u32 log_size, u32 phys_size, u32 clump_size)
+			 __be32 __log_size, __be32 phys_size, u32 clump_size)
 {
 	struct super_block *sb = inode->i_sb;
+	u32 log_size = be32_to_cpu(__log_size);
 	u16 count;
 	int i;
 
@@ -241,7 +242,6 @@
 		count += be16_to_cpu(ext[i].count);
 	HFS_I(inode)->first_blocks = count;
 
-	log_size = be32_to_cpu(log_size);
 	inode->i_size = HFS_I(inode)->phys_size = log_size;
 	inode->i_blocks = (log_size + sb->s_blocksize - 1) >> sb->s_blocksize_bits;
 	HFS_I(inode)->alloc_blocks = be32_to_cpu(phys_size) /
@@ -370,7 +370,7 @@
 }
 
 void hfs_inode_write_fork(struct inode *inode, struct hfs_extent *ext,
-			  u32 *log_size, u32 *phys_size)
+			  __be32 *log_size, __be32 *phys_size)
 {
 	memcpy(ext, HFS_I(inode)->first_extents, sizeof(hfs_extent_rec));
 
@@ -381,7 +381,7 @@
 					 HFS_SB(inode->i_sb)->alloc_blksz);
 }
 
-void hfs_write_inode(struct inode *inode, int unused)
+int hfs_write_inode(struct inode *inode, int unused)
 {
 	struct hfs_find_data fd;
 	hfs_cat_rec rec;
@@ -395,27 +395,27 @@
 			break;
 		case HFS_EXT_CNID:
 			hfs_btree_write(HFS_SB(inode->i_sb)->ext_tree);
-			return;
+			return 0;
 		case HFS_CAT_CNID:
 			hfs_btree_write(HFS_SB(inode->i_sb)->cat_tree);
-			return;
+			return 0;
 		default:
 			BUG();
-			return;
+			return -EIO;
 		}
 	}
 
 	if (HFS_IS_RSRC(inode)) {
 		mark_inode_dirty(HFS_I(inode)->rsrc_inode);
-		return;
+		return 0;
 	}
 
 	if (!inode->i_nlink)
-		return;
+		return 0;
 
 	if (hfs_find_init(HFS_SB(inode->i_sb)->cat_tree, &fd))
 		/* panic? */
-		return;
+		return -EIO;
 
 	fd.search_key->cat = HFS_I(inode)->cat_key;
 	if (hfs_brec_find(&fd))
@@ -460,6 +460,7 @@
 	}
 out:
 	hfs_find_exit(&fd);
+	return 0;
 }
 
 static struct dentry *hfs_file_lookup(struct inode *dir, struct dentry *dentry,
@@ -609,6 +610,7 @@
 	.read		= generic_file_read,
 	.write		= generic_file_write,
 	.mmap		= generic_file_mmap,
+	.sendfile	= generic_file_sendfile,
 	.fsync		= file_fsync,
 	.open		= hfs_file_open,
 	.release	= hfs_file_release,
diff -Nru a/fs/hfs/mdb.c b/fs/hfs/mdb.c
--- a/fs/hfs/mdb.c	2004-10-18 14:56:28 -07:00
+++ b/fs/hfs/mdb.c	2004-10-18 14:56:28 -07:00
@@ -71,7 +71,7 @@
 	int off2, len, size, sect;
 	sector_t part_start, part_size;
 	loff_t off;
-	u16 attrib;
+	__be16 attrib;
 
 	/* set the device driver to 512-byte blocks */
 	size = sb_min_blocksize(sb, HFS_SECTOR_SIZE);
@@ -164,7 +164,7 @@
 		hfs_warn("hfs_fs: continuing without an alternate MDB\n");
 	}
 
-	HFS_SB(sb)->bitmap = (u32 *)__get_free_pages(GFP_KERNEL, PAGE_SIZE < 8192 ? 1 : 0);
+	HFS_SB(sb)->bitmap = (__be32 *)__get_free_pages(GFP_KERNEL, PAGE_SIZE < 8192 ? 1 : 0);
 	if (!HFS_SB(sb)->bitmap)
 		goto out;
 
diff -Nru a/fs/hfs/part_tbl.c b/fs/hfs/part_tbl.c
--- a/fs/hfs/part_tbl.c	2004-10-18 14:56:33 -07:00
+++ b/fs/hfs/part_tbl.c	2004-10-18 14:56:33 -07:00
@@ -19,11 +19,11 @@
  * contiguous starting at block 1.
  */
 struct new_pmap {
-	u16	pmSig;		/* signature */
-	u16	reSigPad;	/* padding */
-	u32	pmMapBlkCnt;	/* partition blocks count */
-	u32	pmPyPartStart;	/* physical block start of partition */
-	u32	pmPartBlkCnt;	/* physical block count of partition */
+	__be16	pmSig;		/* signature */
+	__be16	reSigPad;	/* padding */
+	__be32	pmMapBlkCnt;	/* partition blocks count */
+	__be32	pmPyPartStart;	/* physical block start of partition */
+	__be32	pmPartBlkCnt;	/* physical block count of partition */
 	u8	pmPartName[32];	/* (null terminated?) string
 				   giving the name of this
 				   partition */
@@ -41,11 +41,11 @@
  * one of these.
  */
 struct old_pmap {
-	u16		pdSig;	/* Signature bytes */
+	__be16		pdSig;	/* Signature bytes */
 	struct 	old_pmap_entry {
-		u32	pdStart;
-		u32	pdSize;
-		u32	pdFSID;
+		__be32	pdStart;
+		__be32	pdSize;
+		__be32	pdFSID;
 	}	pdEntry[42];
 } __packed;
 
@@ -59,7 +59,7 @@
 		  sector_t *part_start, sector_t *part_size)
 {
 	struct buffer_head *bh;
-	u16 *data;
+	__be16 *data;
 	int i, size, res;
 
 	res = -ENOENT;
diff -Nru a/fs/hfs/super.c b/fs/hfs/super.c
--- a/fs/hfs/super.c	2004-10-18 14:56:28 -07:00
+++ b/fs/hfs/super.c	2004-10-18 14:56:28 -07:00
@@ -152,8 +152,7 @@
 	hsb->s_gid = current->gid;
 	hsb->s_file_umask = 0644;
 	hsb->s_dir_umask = 0755;
-	hsb->s_type = 0x3f3f3f3f;	/* == '????' */
-	hsb->s_creator = 0x3f3f3f3f;	/* == '????' */
+	hsb->s_type = hsb->s_creator = cpu_to_be32(0x3f3f3f3f);	/* == '????' */
 	hsb->s_quiet = 0;
 	hsb->part = -1;
 	hsb->session = -1;
@@ -216,11 +215,11 @@
 		} else if (!strcmp(this_char, "type") && value) {
 			if (strlen(value) != 4)
 				return 0;
-			hsb->s_type = *(u32 *)value;
+			memcpy(&hsb->s_type, value, 4);
 		} else if (!strcmp(this_char, "creator") && value) {
 			if (strlen(value) != 4)
 				return 0;
-			hsb->s_creator = *(u32 *)value;
+			memcpy(&hsb->s_creator, value, 4);
 	/* Boolean-valued options */
 		} else if (!strcmp(this_char, "quiet")) {
 			if (value)
diff -Nru a/fs/hfsplus/bfind.c b/fs/hfsplus/bfind.c
--- a/fs/hfsplus/bfind.c	2004-10-18 14:56:49 -07:00
+++ b/fs/hfsplus/bfind.c	2004-10-18 14:56:49 -07:00
@@ -85,7 +85,8 @@
 {
 	struct hfs_btree *tree;
 	struct hfs_bnode *bnode;
-	u32 data, nidx, parent;
+	u32 nidx, parent;
+	__be32 data;
 	int height, res;
 
 	tree = fd->tree;
diff -Nru a/fs/hfsplus/bitmap.c b/fs/hfsplus/bitmap.c
--- a/fs/hfsplus/bitmap.c	2004-10-18 14:56:48 -07:00
+++ b/fs/hfsplus/bitmap.c	2004-10-18 14:56:48 -07:00
@@ -19,8 +19,9 @@
 {
 	struct page *page;
 	struct address_space *mapping;
-	u32 *pptr, *curr, *end;
-	u32 val, mask, start, len;
+	__be32 *pptr, *curr, *end;
+	u32 mask, start, len, n;
+	__be32 val;
 	int i;
 
 	len = *max;
@@ -44,10 +45,10 @@
 	/* scan the first partial u32 for zero bits */
 	val = *curr;
 	if (~val) {
-		val = be32_to_cpu(val);
+		n = be32_to_cpu(val);
 		mask = (1U << 31) >> i;
 		for (; i < 32; mask >>= 1, i++) {
-			if (!(val & mask))
+			if (!(n & mask))
 				goto found;
 		}
 	}
@@ -58,10 +59,10 @@
 		while (curr < end) {
 			val = *curr;
 			if (~val) {
-				val = be32_to_cpu(val);
+				n = be32_to_cpu(val);
 				mask = 1 << 31;
 				for (i = 0; i < 32; mask >>= 1, i++) {
-					if (!(val & mask))
+					if (!(n & mask))
 						goto found;
 				}
 			}
@@ -92,27 +93,27 @@
 	/* do any partial u32 at the start */
 	len = min(size - start, len);
 	while (1) {
-		val |= mask;
+		n |= mask;
 		if (++i >= 32)
 			break;
 		mask >>= 1;
-		if (!--len || val & mask)
+		if (!--len || n & mask)
 			goto done;
 	}
 	if (!--len)
 		goto done;
-	*curr++ = cpu_to_be32(val);
+	*curr++ = cpu_to_be32(n);
 	/* do full u32s */
 	while (1) {
 		while (curr < end) {
-			val = be32_to_cpu(*curr);
+			n = be32_to_cpu(*curr);
 			if (len < 32)
 				goto last;
-			if (val) {
+			if (n) {
 				len = 32;
 				goto last;
 			}
-			*curr++ = 0xffffffffU;
+			*curr++ = cpu_to_be32(0xffffffff);
 			len -= 32;
 		}
 		set_page_dirty(page);
@@ -128,13 +129,13 @@
 	/* do any partial u32 at end */
 	mask = 1U << 31;
 	for (i = 0; i < len; i++) {
-		if (val & mask)
+		if (n & mask)
 			break;
-		val |= mask;
+		n |= mask;
 		mask >>= 1;
 	}
 done:
-	*curr = cpu_to_be32(val);
+	*curr = cpu_to_be32(n);
 	set_page_dirty(page);
 	kunmap(page);
 	*max = offset + (curr - pptr) * 32 + i - start;
@@ -150,7 +151,7 @@
 {
 	struct page *page;
 	struct address_space *mapping;
-	u32 *pptr, *curr, *end;
+	__be32 *pptr, *curr, *end;
 	u32 mask, len, pnr;
 	int i;
 
diff -Nru a/fs/hfsplus/bnode.c b/fs/hfsplus/bnode.c
--- a/fs/hfsplus/bnode.c	2004-10-18 14:56:32 -07:00
+++ b/fs/hfsplus/bnode.c	2004-10-18 14:56:32 -07:00
@@ -44,7 +44,7 @@
 
 u16 hfs_bnode_read_u16(struct hfs_bnode *node, int off)
 {
-	u16 data;
+	__be16 data;
 	// optimize later...
 	hfs_bnode_read(node, &data, off, 2);
 	return be16_to_cpu(data);
@@ -55,7 +55,7 @@
 	u8 data;
 	// optimize later...
 	hfs_bnode_read(node, &data, off, 1);
-	return be16_to_cpu(data);
+	return data;
 }
 
 void hfs_bnode_read_key(struct hfs_bnode *node, void *key, int off)
@@ -98,9 +98,9 @@
 
 void hfs_bnode_write_u16(struct hfs_bnode *node, int off, u16 data)
 {
-	data = cpu_to_be16(data);
+	__be16 v = cpu_to_be16(data);
 	// optimize later...
-	hfs_bnode_write(node, &data, off, 2);
+	hfs_bnode_write(node, &v, off, 2);
 }
 
 void hfs_bnode_clear(struct hfs_bnode *node, int off, int len)
@@ -297,7 +297,7 @@
 void hfs_bnode_dump(struct hfs_bnode *node)
 {
 	struct hfs_bnode_desc desc;
-	u32 cnid;
+	__be32 cnid;
 	int i, off, key_off;
 
 	dprint(DBG_BNODE_MOD, "bnode: %d\n", node->this);
@@ -334,7 +334,7 @@
 {
 	struct hfs_btree *tree;
 	struct hfs_bnode *tmp;
-	u32 cnid;
+	__be32 cnid;
 
 	tree = node->tree;
 	if (node->prev) {
diff -Nru a/fs/hfsplus/brec.c b/fs/hfsplus/brec.c
--- a/fs/hfsplus/brec.c	2004-10-18 14:57:03 -07:00
+++ b/fs/hfsplus/brec.c	2004-10-18 14:57:03 -07:00
@@ -14,7 +14,7 @@
 /* Get the length and offset of the given record in the given node */
 u16 hfs_brec_lenoff(struct hfs_bnode *node, u16 rec, u16 *off)
 {
-	u16 retval[2];
+	__be16 retval[2];
 	u16 dataoff;
 
 	dataoff = node->tree->node_size - (rec + 2) * 2;
@@ -53,7 +53,7 @@
 	int size, key_len, rec;
 	int data_off, end_off;
 	int idx_rec_off, data_rec_off, end_rec_off;
-	u32 cnid;
+	__be32 cnid;
 
 	tree = fd->tree;
 	if (!fd->bnode) {
@@ -387,7 +387,7 @@
 	node = parent;
 
 	if (new_node) {
-		u32 cnid;
+		__be32 cnid;
 
 		fd->bnode = hfs_bnode_find(tree, new_node->parent);
 		/* create index key and entry */
@@ -419,7 +419,7 @@
 	struct hfs_bnode *node, *new_node;
 	struct hfs_bnode_desc node_desc;
 	int key_size, rec;
-	u32 cnid;
+	__be32 cnid;
 
 	node = NULL;
 	if (tree->root) {
diff -Nru a/fs/hfsplus/btree.c b/fs/hfsplus/btree.c
--- a/fs/hfsplus/btree.c	2004-10-18 14:56:19 -07:00
+++ b/fs/hfsplus/btree.c	2004-10-18 14:56:19 -07:00
@@ -142,7 +142,7 @@
 	struct hfs_btree *tree = prev->tree;
 	struct hfs_bnode *node;
 	struct hfs_bnode_desc desc;
-	u32 cnid;
+	__be32 cnid;
 
 	node = hfs_bnode_create(tree, idx);
 	if (IS_ERR(node))
diff -Nru a/fs/hfsplus/catalog.c b/fs/hfsplus/catalog.c
--- a/fs/hfsplus/catalog.c	2004-10-18 14:56:32 -07:00
+++ b/fs/hfsplus/catalog.c	2004-10-18 14:56:32 -07:00
@@ -15,7 +15,7 @@
 
 int hfsplus_cat_cmp_key(hfsplus_btree_key *k1, hfsplus_btree_key *k2)
 {
-	u32 k1p, k2p;
+	__be32 k1p, k2p;
 
 	k1p = k1->cat.parent;
 	k2p = k2->cat.parent;
@@ -34,8 +34,10 @@
 	if (str) {
 		hfsplus_asc2uni(&key->cat.name, str->name, str->len);
 		len = be16_to_cpu(key->cat.name.length);
-	} else
-		len = key->cat.name.length = 0;
+	} else {
+		key->cat.name.length = 0;
+		len = 0;
+	}
 	key->key_len = cpu_to_be16(6 + 2 * len);
 }
 
diff -Nru a/fs/hfsplus/extents.c b/fs/hfsplus/extents.c
--- a/fs/hfsplus/extents.c	2004-10-18 14:55:54 -07:00
+++ b/fs/hfsplus/extents.c	2004-10-18 14:55:54 -07:00
@@ -19,8 +19,8 @@
 /* Compare two extents keys, returns 0 on same, pos/neg for difference */
 int hfsplus_ext_cmp_key(hfsplus_btree_key *k1, hfsplus_btree_key *k2)
 {
-	u32 k1id, k2id;
-	u32 k1s, k2s;
+	__be32 k1id, k2id;
+	__be32 k1s, k2s;
 
 	k1id = k1->ext.cnid;
 	k2id = k2->ext.cnid;
diff -Nru a/fs/hfsplus/hfsplus_fs.h b/fs/hfsplus/hfsplus_fs.h
--- a/fs/hfsplus/hfsplus_fs.h	2004-10-18 14:56:50 -07:00
+++ b/fs/hfsplus/hfsplus_fs.h	2004-10-18 14:56:50 -07:00
@@ -333,7 +333,7 @@
 void hfsplus_inode_read_fork(struct inode *, struct hfsplus_fork_raw *);
 void hfsplus_inode_write_fork(struct inode *, struct hfsplus_fork_raw *);
 int hfsplus_cat_read_inode(struct inode *, struct hfs_find_data *);
-void hfsplus_cat_write_inode(struct inode *);
+int hfsplus_cat_write_inode(struct inode *);
 struct inode *hfsplus_new_inode(struct super_block *, int);
 void hfsplus_delete_inode(struct inode *);
 
@@ -344,7 +344,6 @@
 /* options.c */
 int parse_options(char *, struct hfsplus_sb_info *);
 void fill_defaults(struct hfsplus_sb_info *);
-void fill_current(struct hfsplus_sb_info *, struct hfsplus_sb_info *);
 
 /* tables.c */
 extern u16 case_fold_table[];
diff -Nru a/fs/hfsplus/hfsplus_raw.h b/fs/hfsplus/hfsplus_raw.h
--- a/fs/hfsplus/hfsplus_raw.h	2004-10-18 14:56:27 -07:00
+++ b/fs/hfsplus/hfsplus_raw.h	2004-10-18 14:56:27 -07:00
@@ -45,12 +45,12 @@
 
 /* Structures used on disk */
 
-typedef u32 hfsplus_cnid;
-typedef u16 hfsplus_unichr;
+typedef __be32 hfsplus_cnid;
+typedef __be16 hfsplus_unichr;
 
 /* A "string" as used in filenames, etc. */
 struct hfsplus_unistr {
-	u16 length;
+	__be16 length;
 	hfsplus_unichr unicode[255];
 } __packed;
 
@@ -58,12 +58,12 @@
 
 /* POSIX permissions */
 struct hfsplus_perm {
-	u32 owner;
-	u32 group;
+	__be32 owner;
+	__be32 group;
 	u8  rootflags;
 	u8  userflags;
-	u16 mode;
-	u32 dev;
+	__be16 mode;
+	__be32 dev;
 } __packed;
 
 #define HFSPLUS_FLG_NODUMP	0x01
@@ -72,46 +72,46 @@
 
 /* A single contiguous area of a file */
 struct hfsplus_extent {
-	u32 start_block;
-	u32 block_count;
+	__be32 start_block;
+	__be32 block_count;
 } __packed;
 typedef struct hfsplus_extent hfsplus_extent_rec[8];
 
 /* Information for a "Fork" in a file */
 struct hfsplus_fork_raw {
-	u64 total_size;
-	u32 clump_size;
-	u32 total_blocks;
+	__be64 total_size;
+	__be32 clump_size;
+	__be32 total_blocks;
 	hfsplus_extent_rec extents;
 } __packed;
 
 /* HFS+ Volume Header */
 struct hfsplus_vh {
-	u16 signature;
-	u16 version;
-	u32 attributes;
-	u32 last_mount_vers;
+	__be16 signature;
+	__be16 version;
+	__be32 attributes;
+	__be32 last_mount_vers;
 	u32 reserved;
 
-	u32 create_date;
-	u32 modify_date;
-	u32 backup_date;
-	u32 checked_date;
-
-	u32 file_count;
-	u32 folder_count;
-
-	u32 blocksize;
-	u32 total_blocks;
-	u32 free_blocks;
-
-	u32 next_alloc;
-	u32 rsrc_clump_sz;
-	u32 data_clump_sz;
+	__be32 create_date;
+	__be32 modify_date;
+	__be32 backup_date;
+	__be32 checked_date;
+
+	__be32 file_count;
+	__be32 folder_count;
+
+	__be32 blocksize;
+	__be32 total_blocks;
+	__be32 free_blocks;
+
+	__be32 next_alloc;
+	__be32 rsrc_clump_sz;
+	__be32 data_clump_sz;
 	hfsplus_cnid next_cnid;
 
-	u32 write_count;
-	u64 encodings_bmp;
+	__be32 write_count;
+	__be64 encodings_bmp;
 
 	u8 finder_info[32];
 
@@ -131,11 +131,11 @@
 
 /* HFS+ BTree node descriptor */
 struct hfs_bnode_desc {
-	u32 next;
-	u32 prev;
+	__be32 next;
+	__be32 prev;
 	s8 type;
 	u8 height;
-	u16 num_recs;
+	__be16 num_recs;
 	u16 reserved;
 } __packed;
 
@@ -147,20 +147,20 @@
 
 /* HFS+ BTree header */
 struct hfs_btree_header_rec {
-	u16 depth;
-	u32 root;
-	u32 leaf_count;
-	u32 leaf_head;
-	u32 leaf_tail;
-	u16 node_size;
-	u16 max_key_len;
-	u32 node_count;
-	u32 free_nodes;
+	__be16 depth;
+	__be32 root;
+	__be32 leaf_count;
+	__be32 leaf_head;
+	__be32 leaf_tail;
+	__be16 node_size;
+	__be16 max_key_len;
+	__be32 node_count;
+	__be32 free_nodes;
 	u16 reserved1;
-	u32 clump_size;
+	__be32 clump_size;
 	u8 btree_type;
 	u8 reserved2;
-	u32 attributes;
+	__be32 attributes;
 	u32 reserved3[16];
 } __packed;
 
@@ -186,7 +186,7 @@
 
 /* HFS+ catalog entry key */
 struct hfsplus_cat_key {
-	u16 key_len;
+	__be16 key_len;
 	hfsplus_cnid parent;
 	struct hfsplus_unistr name;
 } __packed;
@@ -194,83 +194,83 @@
 
 /* Structs from hfs.h */
 struct hfsp_point {
-	u16 v;
-	u16 h;
+	__be16 v;
+	__be16 h;
 } __packed;
 
 struct hfsp_rect {
-	u16 top;
-	u16 left;
-	u16 bottom;
-	u16 right;
+	__be16 top;
+	__be16 left;
+	__be16 bottom;
+	__be16 right;
 } __packed;
 
 
 /* HFS directory info (stolen from hfs.h */
 struct DInfo {
 	struct hfsp_rect frRect;
-	u16 frFlags;
+	__be16 frFlags;
 	struct hfsp_point frLocation;
-	u16 frView;
+	__be16 frView;
 } __packed;
 
 struct DXInfo {
 	struct hfsp_point frScroll;
-	u32 frOpenChain;
-	u16 frUnused;
-	u16 frComment;
-	u32 frPutAway;
+	__be32 frOpenChain;
+	__be16 frUnused;
+	__be16 frComment;
+	__be32 frPutAway;
 } __packed;
 
 /* HFS+ folder data (part of an hfsplus_cat_entry) */
 struct hfsplus_cat_folder {
-	s16 type;
-	u16 flags;
-	u32 valence;
+	__be16 type;
+	__be16 flags;
+	__be32 valence;
 	hfsplus_cnid id;
-	u32 create_date;
-	u32 content_mod_date;
-	u32 attribute_mod_date;
-	u32 access_date;
-	u32 backup_date;
+	__be32 create_date;
+	__be32 content_mod_date;
+	__be32 attribute_mod_date;
+	__be32 access_date;
+	__be32 backup_date;
 	struct hfsplus_perm permissions;
 	struct DInfo user_info;
 	struct DXInfo finder_info;
-	u32 text_encoding;
+	__be32 text_encoding;
 	u32 reserved;
 } __packed;
 
 /* HFS file info (stolen from hfs.h) */
 struct FInfo {
-	u32 fdType;
-	u32 fdCreator;
-	u16 fdFlags;
+	__be32 fdType;
+	__be32 fdCreator;
+	__be16 fdFlags;
 	struct hfsp_point fdLocation;
-	u16 fdFldr;
+	__be16 fdFldr;
 } __packed;
 
 struct FXInfo {
-	u16 fdIconID;
+	__be16 fdIconID;
 	u8 fdUnused[8];
-	u16 fdComment;
-	u32 fdPutAway;
+	__be16 fdComment;
+	__be32 fdPutAway;
 } __packed;
 
 /* HFS+ file data (part of a cat_entry) */
 struct hfsplus_cat_file {
-	s16 type;
-	u16 flags;
+	__be16 type;
+	__be16 flags;
 	u32 reserved1;
 	hfsplus_cnid id;
-	u32 create_date;
-	u32 content_mod_date;
-	u32 attribute_mod_date;
-	u32 access_date;
-	u32 backup_date;
+	__be32 create_date;
+	__be32 content_mod_date;
+	__be32 attribute_mod_date;
+	__be32 access_date;
+	__be32 backup_date;
 	struct hfsplus_perm permissions;
 	struct FInfo user_info;
 	struct FXInfo finder_info;
-	u32 text_encoding;
+	__be32 text_encoding;
 	u32 reserved2;
 
 	struct hfsplus_fork_raw data_fork;
@@ -283,7 +283,7 @@
 
 /* HFS+ catalog thread (part of a cat_entry) */
 struct hfsplus_cat_thread {
-	s16 type;
+	__be16 type;
 	s16 reserved;
 	hfsplus_cnid parentID;
 	struct hfsplus_unistr nodeName;
@@ -293,7 +293,7 @@
 
 /* A data record in the catalog tree */
 typedef union {
-	s16 type;
+	__be16 type;
 	struct hfsplus_cat_folder folder;
 	struct hfsplus_cat_file file;
 	struct hfsplus_cat_thread thread;
@@ -307,18 +307,18 @@
 
 /* HFS+ extents tree key */
 struct hfsplus_ext_key {
-	u16 key_len;
+	__be16 key_len;
 	u8 fork_type;
 	u8 pad;
 	hfsplus_cnid cnid;
-	u32 start_block;
+	__be32 start_block;
 } __packed;
 
 #define HFSPLUS_EXT_KEYLEN 12
 
 /* HFS+ generic BTree key */
 typedef union {
-	u16 key_len;
+	__be16 key_len;
 	struct hfsplus_cat_key cat;
 	struct hfsplus_ext_key ext;
 } __packed hfsplus_btree_key;
diff -Nru a/fs/hfsplus/inode.c b/fs/hfsplus/inode.c
--- a/fs/hfsplus/inode.c	2004-10-18 14:56:20 -07:00
+++ b/fs/hfsplus/inode.c	2004-10-18 14:56:20 -07:00
@@ -308,6 +308,7 @@
 	.read		= generic_file_read,
 	.write		= generic_file_write,
 	.mmap		= generic_file_mmap,
+	.sendfile	= generic_file_sendfile,
 	.fsync		= file_fsync,
 	.open		= hfsplus_file_open,
 	.release	= hfsplus_file_release,
@@ -483,22 +484,22 @@
 	return res;
 }
 
-void hfsplus_cat_write_inode(struct inode *inode)
+int hfsplus_cat_write_inode(struct inode *inode)
 {
 	struct hfs_find_data fd;
 	hfsplus_cat_entry entry;
 
 	if (HFSPLUS_IS_RSRC(inode)) {
 		mark_inode_dirty(HFSPLUS_I(inode).rsrc_inode);
-		return;
+		return 0;
 	}
 
 	if (!inode->i_nlink)
-		return;
+		return 0;
 
 	if (hfs_find_init(HFSPLUS_SB(inode->i_sb).cat_tree, &fd))
 		/* panic? */
-		return;
+		return -EIO;
 
 	if (hfsplus_find_cat(inode->i_sb, inode->i_ino, &fd))
 		/* panic? */
@@ -546,4 +547,5 @@
 	}
 out:
 	hfs_find_exit(&fd);
+	return 0;
 }
diff -Nru a/fs/hfsplus/part_tbl.c b/fs/hfsplus/part_tbl.c
--- a/fs/hfsplus/part_tbl.c	2004-10-18 14:56:20 -07:00
+++ b/fs/hfsplus/part_tbl.c	2004-10-18 14:56:20 -07:00
@@ -35,11 +35,11 @@
  * contiguous starting at block 1.
  */
 struct new_pmap {
-	u16	pmSig;		/* signature */
-	u16	reSigPad;	/* padding */
-	u32	pmMapBlkCnt;	/* partition blocks count */
-	u32	pmPyPartStart;	/* physical block start of partition */
-	u32	pmPartBlkCnt;	/* physical block count of partition */
+	__be16	pmSig;		/* signature */
+	__be16	reSigPad;	/* padding */
+	__be32	pmMapBlkCnt;	/* partition blocks count */
+	__be32	pmPyPartStart;	/* physical block start of partition */
+	__be32	pmPartBlkCnt;	/* physical block count of partition */
 	u8	pmPartName[32];	/* (null terminated?) string
 				   giving the name of this
 				   partition */
@@ -57,11 +57,11 @@
  * one of these.
  */
 struct old_pmap {
-	u16		pdSig;	/* Signature bytes */
+	__be16		pdSig;	/* Signature bytes */
 	struct 	old_pmap_entry {
-		u32	pdStart;
-		u32	pdSize;
-		u32	pdFSID;
+		__be32	pdStart;
+		__be32	pdSize;
+		__be32	pdFSID;
 	}	pdEntry[42];
 } __packed;
 
@@ -75,7 +75,7 @@
 		  sector_t *part_start, sector_t *part_size)
 {
 	struct buffer_head *bh;
-	u16 *data;
+	__be16 *data;
 	int i, size, res;
 
 	res = -ENOENT;
diff -Nru a/fs/hfsplus/super.c b/fs/hfsplus/super.c
--- a/fs/hfsplus/super.c	2004-10-18 14:56:17 -07:00
+++ b/fs/hfsplus/super.c	2004-10-18 14:56:17 -07:00
@@ -94,20 +94,20 @@
 	make_bad_inode(inode);
 }
 
-void hfsplus_write_inode(struct inode *inode, int unused)
+int hfsplus_write_inode(struct inode *inode, int unused)
 {
 	struct hfsplus_vh *vhdr;
+	int ret = 0;
 
 	dprint(DBG_INODE, "hfsplus_write_inode: %lu\n", inode->i_ino);
 	hfsplus_ext_write_extent(inode);
 	if (inode->i_ino >= HFSPLUS_FIRSTUSER_CNID) {
-		hfsplus_cat_write_inode(inode);
-		return;
+		return hfsplus_cat_write_inode(inode);
 	}
 	vhdr = HFSPLUS_SB(inode->i_sb).s_vhdr;
 	switch (inode->i_ino) {
 	case HFSPLUS_ROOT_CNID:
-		hfsplus_cat_write_inode(inode);
+		ret = hfsplus_cat_write_inode(inode);
 		break;
 	case HFSPLUS_EXT_CNID:
 		if (vhdr->ext_file.total_size != cpu_to_be64(inode->i_size)) {
@@ -148,6 +148,7 @@
 		hfs_btree_write(HFSPLUS_SB(inode->i_sb).attr_tree);
 		break;
 	}
+	return ret;
 }
 
 static void hfsplus_clear_inode(struct inode *inode)
diff -Nru a/fs/hfsplus/wrapper.c b/fs/hfsplus/wrapper.c
--- a/fs/hfsplus/wrapper.c	2004-10-18 14:56:49 -07:00
+++ b/fs/hfsplus/wrapper.c	2004-10-18 14:56:49 -07:00
@@ -30,22 +30,22 @@
 	u32 extent;
 	u16 attrib;
 
-	if (be16_to_cpu(*(u16 *)(bufptr + HFSP_WRAPOFF_EMBEDSIG)) != HFSPLUS_VOLHEAD_SIG)
+	if (be16_to_cpu(*(__be16 *)(bufptr + HFSP_WRAPOFF_EMBEDSIG)) != HFSPLUS_VOLHEAD_SIG)
 		return 0;
 
-	attrib = be16_to_cpu(*(u16 *)(bufptr + HFSP_WRAPOFF_ATTRIB));
+	attrib = be16_to_cpu(*(__be16 *)(bufptr + HFSP_WRAPOFF_ATTRIB));
 	if (!(attrib & HFSP_WRAP_ATTRIB_SLOCK) ||
 	   !(attrib & HFSP_WRAP_ATTRIB_SPARED))
 		return 0;
 
-	wd->ablk_size = be32_to_cpu(*(u32 *)(bufptr + HFSP_WRAPOFF_ABLKSIZE));
+	wd->ablk_size = be32_to_cpu(*(__be32 *)(bufptr + HFSP_WRAPOFF_ABLKSIZE));
 	if (wd->ablk_size < HFSPLUS_SECTOR_SIZE)
 		return 0;
 	if (wd->ablk_size % HFSPLUS_SECTOR_SIZE)
 		return 0;
-	wd->ablk_start = be16_to_cpu(*(u16 *)(bufptr + HFSP_WRAPOFF_ABLKSTART));
+	wd->ablk_start = be16_to_cpu(*(__be16 *)(bufptr + HFSP_WRAPOFF_ABLKSTART));
 
-	extent = be32_to_cpu(get_unaligned((u32 *)(bufptr + HFSP_WRAPOFF_EMBEDEXT)));
+	extent = be32_to_cpu(get_unaligned((__be32 *)(bufptr + HFSP_WRAPOFF_EMBEDEXT)));
 	wd->embed_start = (extent >> 16) & 0xFFFF;
 	wd->embed_count = extent & 0xFFFF;
 
diff -Nru a/fs/hostfs/Makefile b/fs/hostfs/Makefile
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/fs/hostfs/Makefile	2004-10-18 14:57:22 -07:00
@@ -0,0 +1,26 @@
+#
+# Copyright (C) 2000 Jeff Dike (jdike@karaya.com)
+# Licensed under the GPL
+#
+
+# struct stat64 changed the inode field name between 2.2 and 2.4 from st_ino
+# to __st_ino.  It stayed in the same place, so as long as the correct name
+# is used, hostfs compiled on 2.2 should work on 2.4 and vice versa.
+
+STAT64_INO_FIELD := $(shell grep -q __st_ino /usr/include/bits/stat.h && \
+				echo __)st_ino
+
+hostfs-objs := hostfs_kern.o hostfs_user.o
+
+obj-y =
+obj-$(CONFIG_HOSTFS) += hostfs.o
+
+SINGLE_OBJS = $(foreach f,$(patsubst %.o,%,$(obj-y) $(obj-m)),$($(f)-objs))
+
+USER_OBJS := $(filter %_user.o,$(obj-y) $(obj-m) $(SINGLE_OBJS))
+USER_OBJS := $(foreach file,$(USER_OBJS),$(obj)/$(file))
+
+USER_CFLAGS += -DSTAT64_INO_FIELD=$(STAT64_INO_FIELD)
+
+$(USER_OBJS) : %.o: %.c
+	$(CC) $(CFLAGS_$(notdir $@)) $(USER_CFLAGS) -c -o $@ $<
diff -Nru a/fs/hostfs/hostfs.h b/fs/hostfs/hostfs.h
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/fs/hostfs/hostfs.h	2004-10-18 14:57:24 -07:00
@@ -0,0 +1,79 @@
+#ifndef __UM_FS_HOSTFS
+#define __UM_FS_HOSTFS
+
+#include "os.h"
+
+/* These are exactly the same definitions as in fs.h, but the names are
+ * changed so that this file can be included in both kernel and user files.
+ */
+
+#define HOSTFS_ATTR_MODE	1
+#define HOSTFS_ATTR_UID 	2
+#define HOSTFS_ATTR_GID 	4
+#define HOSTFS_ATTR_SIZE	8
+#define HOSTFS_ATTR_ATIME	16
+#define HOSTFS_ATTR_MTIME	32
+#define HOSTFS_ATTR_CTIME	64
+#define HOSTFS_ATTR_ATIME_SET	128
+#define HOSTFS_ATTR_MTIME_SET	256
+#define HOSTFS_ATTR_FORCE	512	/* Not a change, but a change it */
+#define HOSTFS_ATTR_ATTR_FLAG	1024
+
+struct hostfs_iattr {
+	unsigned int	ia_valid;
+	mode_t		ia_mode;
+	uid_t		ia_uid;
+	gid_t		ia_gid;
+	loff_t		ia_size;
+	struct timespec	ia_atime;
+	struct timespec	ia_mtime;
+	struct timespec	ia_ctime;
+	unsigned int	ia_attr_flags;
+};
+
+extern int stat_file(const char *path, unsigned long long *inode_out,
+		     int *mode_out, int *nlink_out, int *uid_out, int *gid_out,
+		     unsigned long long *size_out, struct timespec *atime_out,
+		     struct timespec *mtime_out, struct timespec *ctime_out,
+		     int *blksize_out, unsigned long long *blocks_out);
+extern int access_file(char *path, int r, int w, int x);
+extern int open_file(char *path, int r, int w, int append);
+extern int file_type(const char *path, int *maj, int *min);
+extern void *open_dir(char *path, int *err_out);
+extern char *read_dir(void *stream, unsigned long long *pos,
+		      unsigned long long *ino_out, int *len_out);
+extern void close_file(void *stream);
+extern void close_dir(void *stream);
+extern int read_file(int fd, unsigned long long *offset, char *buf, int len);
+extern int write_file(int fd, unsigned long long *offset, const char *buf,
+		      int len);
+extern int lseek_file(int fd, long long offset, int whence);
+extern int file_create(char *name, int ur, int uw, int ux, int gr,
+		       int gw, int gx, int or, int ow, int ox);
+extern int set_attr(const char *file, struct hostfs_iattr *attrs);
+extern int make_symlink(const char *from, const char *to);
+extern int unlink_file(const char *file);
+extern int do_mkdir(const char *file, int mode);
+extern int do_rmdir(const char *file);
+extern int do_mknod(const char *file, int mode, int dev);
+extern int link_file(const char *from, const char *to);
+extern int do_readlink(char *file, char *buf, int size);
+extern int rename_file(char *from, char *to);
+extern int do_statfs(char *root, long *bsize_out, long long *blocks_out,
+		     long long *bfree_out, long long *bavail_out,
+		     long long *files_out, long long *ffree_out,
+		     void *fsid_out, int fsid_size, long *namelen_out,
+		     long *spare_out);
+
+#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/fs/hostfs/hostfs_kern.c b/fs/hostfs/hostfs_kern.c
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/fs/hostfs/hostfs_kern.c	2004-10-18 14:57:21 -07:00
@@ -0,0 +1,1030 @@
+/*
+ * Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com)
+ * Licensed under the GPL
+ *
+ * Ported the filesystem routines to 2.5.
+ * 2003-02-10 Petr Baudis <pasky@ucw.cz>
+ */
+
+#include <linux/stddef.h>
+#include <linux/fs.h>
+#include <linux/version.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/pagemap.h>
+#include <linux/blkdev.h>
+#include <linux/list.h>
+#include <linux/buffer_head.h>
+#include <linux/root_dev.h>
+#include <linux/statfs.h>
+#include <linux/kdev_t.h>
+#include <asm/uaccess.h>
+#include "hostfs.h"
+#include "kern_util.h"
+#include "kern.h"
+#include "user_util.h"
+#include "2_5compat.h"
+#include "init.h"
+
+struct hostfs_inode_info {
+	char *host_filename;
+	int fd;
+	int mode;
+	struct inode vfs_inode;
+};
+
+static inline struct hostfs_inode_info *HOSTFS_I(struct inode *inode)
+{
+	return(list_entry(inode, struct hostfs_inode_info, vfs_inode));
+}
+
+#define FILE_HOSTFS_I(file) HOSTFS_I((file)->f_dentry->d_inode)
+
+int hostfs_d_delete(struct dentry *dentry)
+{
+	return(1);
+}
+
+struct dentry_operations hostfs_dentry_ops = {
+	.d_delete		= hostfs_d_delete,
+};
+
+/* Changed in hostfs_args before the kernel starts running */
+static char *root_ino = "/";
+static int append = 0;
+
+#define HOSTFS_SUPER_MAGIC 0x00c0ffee
+
+static struct inode_operations hostfs_iops;
+static struct inode_operations hostfs_dir_iops;
+static struct address_space_operations hostfs_link_aops;
+
+#ifndef MODULE
+static int __init hostfs_args(char *options, int *add)
+{
+	char *ptr;
+
+	ptr = strchr(options, ',');
+	if(ptr != NULL)
+		*ptr++ = '\0';
+	if(*options != '\0')
+		root_ino = options;
+
+	options = ptr;
+	while(options){
+		ptr = strchr(options, ',');
+		if(ptr != NULL)
+			*ptr++ = '\0';
+		if(*options != '\0'){
+			if(!strcmp(options, "append"))
+				append = 1;
+			else printf("hostfs_args - unsupported option - %s\n",
+				    options);
+		}
+		options = ptr;
+	}
+	return(0);
+}
+
+__uml_setup("hostfs=", hostfs_args,
+"hostfs=<root dir>,<flags>,...\n"
+"    This is used to set hostfs parameters.  The root directory argument\n"
+"    is used to confine all hostfs mounts to within the specified directory\n"
+"    tree on the host.  If this isn't specified, then a user inside UML can\n"
+"    mount anything on the host that's accessible to the user that's running\n"
+"    it.\n"
+"    The only flag currently supported is 'append', which specifies that all\n"
+"    files opened by hostfs will be opened in append mode.\n\n"
+);
+#endif
+
+static char *dentry_name(struct dentry *dentry, int extra)
+{
+	struct dentry *parent;
+	char *root, *name;
+	int len;
+
+	len = 0;
+	parent = dentry;
+	while(parent->d_parent != parent){
+		len += parent->d_name.len + 1;
+		parent = parent->d_parent;
+	}
+
+	root = HOSTFS_I(parent->d_inode)->host_filename;
+	len += strlen(root);
+	name = kmalloc(len + extra + 1, GFP_KERNEL);
+	if(name == NULL) return(NULL);
+
+	name[len] = '\0';
+	parent = dentry;
+	while(parent->d_parent != parent){
+		len -= parent->d_name.len + 1;
+		name[len] = '/';
+		strncpy(&name[len + 1], parent->d_name.name,
+			parent->d_name.len);
+		parent = parent->d_parent;
+	}
+	strncpy(name, root, strlen(root));
+	return(name);
+}
+
+static char *inode_name(struct inode *ino, int extra)
+{
+	struct dentry *dentry;
+
+	dentry = list_entry(ino->i_dentry.next, struct dentry, d_alias);
+	return(dentry_name(dentry, extra));
+}
+
+static int read_name(struct inode *ino, char *name)
+{
+	/* The non-int inode fields are copied into ints by stat_file and
+	 * then copied into the inode because passing the actual pointers
+	 * in and having them treated as int * breaks on big-endian machines
+	 */
+	int err;
+	int i_mode, i_nlink, i_blksize;
+	unsigned long long i_size;
+	unsigned long long i_ino;
+	unsigned long long i_blocks;
+
+	err = stat_file(name, &i_ino, &i_mode, &i_nlink, &ino->i_uid,
+			&ino->i_gid, &i_size, &ino->i_atime, &ino->i_mtime,
+			&ino->i_ctime, &i_blksize, &i_blocks);
+	if(err)
+		return(err);
+
+	ino->i_ino = i_ino;
+	ino->i_mode = i_mode;
+	ino->i_nlink = i_nlink;
+	ino->i_size = i_size;
+	ino->i_blksize = i_blksize;
+	ino->i_blocks = i_blocks;
+	if((ino->i_sb->s_dev == ROOT_DEV) && (ino->i_uid == getuid()))
+		ino->i_uid = 0;
+	return(0);
+}
+
+static char *follow_link(char *link)
+{
+	int len, n;
+	char *name, *resolved, *end;
+
+	len = 64;
+	while(1){
+		n = -ENOMEM;
+		name = kmalloc(len, GFP_KERNEL);
+		if(name == NULL)
+			goto out;
+
+		n = do_readlink(link, name, len);
+		if(n < len)
+			break;
+		len *= 2;
+		kfree(name);
+	}
+	if(n < 0)
+		goto out_free;
+
+	if(*name == '/')
+		return(name);
+
+	end = strrchr(link, '/');
+	if(end == NULL)
+		return(name);
+
+	*(end + 1) = '\0';
+	len = strlen(link) + strlen(name) + 1;
+
+	resolved = kmalloc(len, GFP_KERNEL);
+	if(resolved == NULL){
+		n = -ENOMEM;
+		goto out_free;
+	}
+
+	sprintf(resolved, "%s%s", link, name);
+	kfree(name);
+	kfree(link);
+	return(resolved);
+
+ out_free:
+	kfree(name);
+ out:
+	return(ERR_PTR(n));
+}
+
+static int read_inode(struct inode *ino)
+{
+	char *name;
+	int err = 0;
+
+	/* Unfortunately, we are called from iget() when we don't have a dentry
+	 * allocated yet.
+	 */
+	if(list_empty(&ino->i_dentry))
+		goto out;
+
+	err = -ENOMEM;
+	name = inode_name(ino, 0);
+	if(name == NULL)
+		goto out;
+
+	if(file_type(name, NULL, NULL) == OS_TYPE_SYMLINK){
+		name = follow_link(name);
+		if(IS_ERR(name)){
+			err = PTR_ERR(name);
+			goto out;
+		}
+	}
+
+	err = read_name(ino, name);
+	kfree(name);
+ out:
+	return(err);
+}
+
+int hostfs_statfs(struct super_block *sb, struct kstatfs *sf)
+{
+	/* do_statfs uses struct statfs64 internally, but the linux kernel
+	 * struct statfs still has 32-bit versions for most of these fields,
+	 * so we convert them here
+	 */
+	int err;
+	long long f_blocks;
+	long long f_bfree;
+	long long f_bavail;
+	long long f_files;
+	long long f_ffree;
+
+	err = do_statfs(HOSTFS_I(sb->s_root->d_inode)->host_filename,
+			&sf->f_bsize, &f_blocks, &f_bfree, &f_bavail, &f_files,
+			&f_ffree, &sf->f_fsid, sizeof(sf->f_fsid),
+			&sf->f_namelen, sf->f_spare);
+	if(err) return(err);
+	sf->f_blocks = f_blocks;
+	sf->f_bfree = f_bfree;
+	sf->f_bavail = f_bavail;
+	sf->f_files = f_files;
+	sf->f_ffree = f_ffree;
+	sf->f_type = HOSTFS_SUPER_MAGIC;
+	return(0);
+}
+
+static struct inode *hostfs_alloc_inode(struct super_block *sb)
+{
+	struct hostfs_inode_info *hi;
+
+	hi = kmalloc(sizeof(*hi), GFP_KERNEL);
+	if(hi == NULL)
+		return(NULL);
+
+	*hi = ((struct hostfs_inode_info) { .host_filename	= NULL,
+					    .fd			= -1,
+					    .mode		= 0 });
+	inode_init_once(&hi->vfs_inode);
+	return(&hi->vfs_inode);
+}
+
+static void hostfs_delete_inode(struct inode *inode)
+{
+	if(HOSTFS_I(inode)->fd != -1) {
+		close_file(&HOSTFS_I(inode)->fd);
+		HOSTFS_I(inode)->fd = -1;
+	}
+	clear_inode(inode);
+}
+
+static void hostfs_destroy_inode(struct inode *inode)
+{
+	if(HOSTFS_I(inode)->host_filename)
+		kfree(HOSTFS_I(inode)->host_filename);
+
+	/*XXX: This should not happen, probably. The check is here for
+	 * additional safety.*/
+	if(HOSTFS_I(inode)->fd != -1) {
+		close_file(&HOSTFS_I(inode)->fd);
+		printk(KERN_DEBUG "Closing host fd in .destroy_inode\n");
+	}
+
+	kfree(HOSTFS_I(inode));
+}
+
+static void hostfs_read_inode(struct inode *inode)
+{
+	read_inode(inode);
+}
+
+static struct super_operations hostfs_sbops = {
+	.alloc_inode	= hostfs_alloc_inode,
+	.drop_inode	= generic_delete_inode,
+	.delete_inode   = hostfs_delete_inode,
+	.destroy_inode	= hostfs_destroy_inode,
+	.read_inode	= hostfs_read_inode,
+	.statfs		= hostfs_statfs,
+};
+
+int hostfs_readdir(struct file *file, void *ent, filldir_t filldir)
+{
+	void *dir;
+	char *name;
+	unsigned long long next, ino;
+	int error, len;
+
+	name = dentry_name(file->f_dentry, 0);
+	if(name == NULL) return(-ENOMEM);
+	dir = open_dir(name, &error);
+	kfree(name);
+	if(dir == NULL) return(-error);
+	next = file->f_pos;
+	while((name = read_dir(dir, &next, &ino, &len)) != NULL){
+		error = (*filldir)(ent, name, len, file->f_pos,
+				   ino, DT_UNKNOWN);
+		if(error) break;
+		file->f_pos = next;
+	}
+	close_dir(dir);
+	return(0);
+}
+
+int hostfs_file_open(struct inode *ino, struct file *file)
+{
+	char *name;
+	int mode = 0, r = 0, w = 0, fd;
+
+	mode = file->f_mode & (FMODE_READ | FMODE_WRITE);
+	if((mode & HOSTFS_I(ino)->mode) == mode)
+		return(0);
+
+	/* The file may already have been opened, but with the wrong access,
+	 * so this resets things and reopens the file with the new access.
+	 */
+	if(HOSTFS_I(ino)->fd != -1){
+		close_file(&HOSTFS_I(ino)->fd);
+		HOSTFS_I(ino)->fd = -1;
+	}
+
+	HOSTFS_I(ino)->mode |= mode;
+	if(HOSTFS_I(ino)->mode & FMODE_READ)
+		r = 1;
+	if(HOSTFS_I(ino)->mode & FMODE_WRITE)
+		w = 1;
+	if(w)
+		r = 1;
+
+	name = dentry_name(file->f_dentry, 0);
+	if(name == NULL)
+		return(-ENOMEM);
+
+	fd = open_file(name, r, w, append);
+	kfree(name);
+	if(fd < 0) return(fd);
+	FILE_HOSTFS_I(file)->fd = fd;
+
+	return(0);
+}
+
+int hostfs_fsync(struct file *file, struct dentry *dentry, int datasync)
+{
+	return(0);
+}
+
+static struct file_operations hostfs_file_fops = {
+	.llseek		= generic_file_llseek,
+	.read		= generic_file_read,
+	.write		= generic_file_write,
+	.mmap		= generic_file_mmap,
+	.open		= hostfs_file_open,
+	.release	= NULL,
+	.fsync		= hostfs_fsync,
+};
+
+static struct file_operations hostfs_dir_fops = {
+	.readdir	= hostfs_readdir,
+	.read		= generic_read_dir,
+};
+
+int hostfs_writepage(struct page *page, struct writeback_control *wbc)
+{
+	struct address_space *mapping = page->mapping;
+	struct inode *inode = mapping->host;
+	char *buffer;
+	unsigned long long base;
+	int count = PAGE_CACHE_SIZE;
+	int end_index = inode->i_size >> PAGE_CACHE_SHIFT;
+	int err;
+
+	if (page->index >= end_index)
+		count = inode->i_size & (PAGE_CACHE_SIZE-1);
+
+	buffer = kmap(page);
+	base = ((unsigned long long) page->index) << PAGE_CACHE_SHIFT;
+
+	err = write_file(HOSTFS_I(inode)->fd, &base, buffer, count);
+	if(err != count){
+		ClearPageUptodate(page);
+		goto out;
+	}
+
+	if (base > inode->i_size)
+		inode->i_size = base;
+
+	if (PageError(page))
+		ClearPageError(page);
+	err = 0;
+
+ out:
+	kunmap(page);
+
+	unlock_page(page);
+	return err;
+}
+
+int hostfs_readpage(struct file *file, struct page *page)
+{
+	char *buffer;
+	long long start;
+	int err = 0;
+
+	start = (long long) page->index << PAGE_CACHE_SHIFT;
+	buffer = kmap(page);
+	err = read_file(FILE_HOSTFS_I(file)->fd, &start, buffer,
+			PAGE_CACHE_SIZE);
+	if(err < 0) goto out;
+
+	memset(&buffer[err], 0, PAGE_CACHE_SIZE - err);
+
+	flush_dcache_page(page);
+	SetPageUptodate(page);
+	if (PageError(page)) ClearPageError(page);
+	err = 0;
+ out:
+	kunmap(page);
+	unlock_page(page);
+	return(err);
+}
+
+int hostfs_prepare_write(struct file *file, struct page *page,
+			 unsigned int from, unsigned int to)
+{
+	char *buffer;
+	long long start, tmp;
+	int err;
+
+	start = (long long) page->index << PAGE_CACHE_SHIFT;
+	buffer = kmap(page);
+	if(from != 0){
+		tmp = start;
+		err = read_file(FILE_HOSTFS_I(file)->fd, &tmp, buffer,
+				from);
+		if(err < 0) goto out;
+	}
+	if(to != PAGE_CACHE_SIZE){
+		start += to;
+		err = read_file(FILE_HOSTFS_I(file)->fd, &start, buffer + to,
+				PAGE_CACHE_SIZE - to);
+		if(err < 0) goto out;
+	}
+	err = 0;
+ out:
+	kunmap(page);
+	return(err);
+}
+
+int hostfs_commit_write(struct file *file, struct page *page, unsigned from,
+		 unsigned to)
+{
+	struct address_space *mapping = page->mapping;
+	struct inode *inode = mapping->host;
+	char *buffer;
+	long long start;
+	int err = 0;
+
+	start = (long long) (page->index << PAGE_CACHE_SHIFT) + from;
+	buffer = kmap(page);
+	err = write_file(FILE_HOSTFS_I(file)->fd, &start, buffer + from,
+			 to - from);
+	if(err > 0) err = 0;
+	if(!err && (start > inode->i_size))
+		inode->i_size = start;
+
+	kunmap(page);
+	return(err);
+}
+
+static struct address_space_operations hostfs_aops = {
+	.writepage 	= hostfs_writepage,
+	.readpage	= hostfs_readpage,
+/* 	.set_page_dirty = __set_page_dirty_nobuffers, */
+	.prepare_write	= hostfs_prepare_write,
+	.commit_write	= hostfs_commit_write
+};
+
+static int init_inode(struct inode *inode, struct dentry *dentry)
+{
+	char *name;
+	int type, err = -ENOMEM;
+	int maj, min;
+	dev_t rdev = 0;
+
+	if(dentry){
+		name = dentry_name(dentry, 0);
+		if(name == NULL)
+			goto out;
+		type = file_type(name, &maj, &min);
+		/*Reencode maj and min with the kernel encoding.*/
+		rdev = MKDEV(maj, min);
+		kfree(name);
+	}
+	else type = OS_TYPE_DIR;
+
+	err = 0;
+	if(type == OS_TYPE_SYMLINK)
+		inode->i_op = &page_symlink_inode_operations;
+	else if(type == OS_TYPE_DIR)
+		inode->i_op = &hostfs_dir_iops;
+	else inode->i_op = &hostfs_iops;
+
+	if(type == OS_TYPE_DIR) inode->i_fop = &hostfs_dir_fops;
+	else inode->i_fop = &hostfs_file_fops;
+
+	if(type == OS_TYPE_SYMLINK)
+		inode->i_mapping->a_ops = &hostfs_link_aops;
+	else inode->i_mapping->a_ops = &hostfs_aops;
+
+	switch (type) {
+	case OS_TYPE_CHARDEV:
+		init_special_inode(inode, S_IFCHR, rdev);
+		break;
+	case OS_TYPE_BLOCKDEV:
+		init_special_inode(inode, S_IFBLK, rdev);
+		break;
+	case OS_TYPE_FIFO:
+		init_special_inode(inode, S_IFIFO, 0);
+		break;
+	case OS_TYPE_SOCK:
+		init_special_inode(inode, S_IFSOCK, 0);
+		break;
+	}
+ out:
+	return(err);
+}
+
+int hostfs_create(struct inode *dir, struct dentry *dentry, int mode,
+                 struct nameidata *nd)
+{
+	struct inode *inode;
+	char *name;
+	int error, fd;
+
+	error = -ENOMEM;
+	inode = iget(dir->i_sb, 0);
+	if(inode == NULL) goto out;
+
+	error = init_inode(inode, dentry);
+	if(error)
+		goto out_put;
+
+	error = -ENOMEM;
+	name = dentry_name(dentry, 0);
+	if(name == NULL)
+		goto out_put;
+
+	fd = file_create(name,
+			 mode & S_IRUSR, mode & S_IWUSR, mode & S_IXUSR,
+			 mode & S_IRGRP, mode & S_IWGRP, mode & S_IXGRP,
+			 mode & S_IROTH, mode & S_IWOTH, mode & S_IXOTH);
+	if(fd < 0)
+		error = fd;
+	else error = read_name(inode, name);
+
+	kfree(name);
+	if(error)
+		goto out_put;
+
+	HOSTFS_I(inode)->fd = fd;
+	HOSTFS_I(inode)->mode = FMODE_READ | FMODE_WRITE;
+	d_instantiate(dentry, inode);
+	return(0);
+
+ out_put:
+	iput(inode);
+ out:
+	return(error);
+}
+
+struct dentry *hostfs_lookup(struct inode *ino, struct dentry *dentry,
+                            struct nameidata *nd)
+{
+	struct inode *inode;
+	char *name;
+	int err;
+
+	err = -ENOMEM;
+	inode = iget(ino->i_sb, 0);
+	if(inode == NULL)
+		goto out;
+
+	err = init_inode(inode, dentry);
+	if(err)
+		goto out_put;
+
+	err = -ENOMEM;
+	name = dentry_name(dentry, 0);
+	if(name == NULL)
+		goto out_put;
+
+	err = read_name(inode, name);
+	kfree(name);
+	if(err == -ENOENT){
+		iput(inode);
+		inode = NULL;
+	}
+	else if(err)
+		goto out_put;
+
+	d_add(dentry, inode);
+	dentry->d_op = &hostfs_dentry_ops;
+	return(NULL);
+
+ out_put:
+	iput(inode);
+ out:
+	return(ERR_PTR(err));
+}
+
+static char *inode_dentry_name(struct inode *ino, struct dentry *dentry)
+{
+        char *file;
+	int len;
+
+	file = inode_name(ino, dentry->d_name.len + 1);
+	if(file == NULL) return(NULL);
+        strcat(file, "/");
+	len = strlen(file);
+        strncat(file, dentry->d_name.name, dentry->d_name.len);
+	file[len + dentry->d_name.len] = '\0';
+        return(file);
+}
+
+int hostfs_link(struct dentry *to, struct inode *ino, struct dentry *from)
+{
+        char *from_name, *to_name;
+        int err;
+
+        if((from_name = inode_dentry_name(ino, from)) == NULL)
+                return(-ENOMEM);
+        to_name = dentry_name(to, 0);
+	if(to_name == NULL){
+		kfree(from_name);
+		return(-ENOMEM);
+	}
+        err = link_file(to_name, from_name);
+        kfree(from_name);
+        kfree(to_name);
+        return(err);
+}
+
+int hostfs_unlink(struct inode *ino, struct dentry *dentry)
+{
+	char *file;
+	int err;
+
+	if((file = inode_dentry_name(ino, dentry)) == NULL) return(-ENOMEM);
+	if(append)
+		return(-EPERM);
+
+	err = unlink_file(file);
+	kfree(file);
+	return(err);
+}
+
+int hostfs_symlink(struct inode *ino, struct dentry *dentry, const char *to)
+{
+	char *file;
+	int err;
+
+	if((file = inode_dentry_name(ino, dentry)) == NULL) return(-ENOMEM);
+	err = make_symlink(file, to);
+	kfree(file);
+	return(err);
+}
+
+int hostfs_mkdir(struct inode *ino, struct dentry *dentry, int mode)
+{
+	char *file;
+	int err;
+
+	if((file = inode_dentry_name(ino, dentry)) == NULL) return(-ENOMEM);
+	err = do_mkdir(file, mode);
+	kfree(file);
+	return(err);
+}
+
+int hostfs_rmdir(struct inode *ino, struct dentry *dentry)
+{
+	char *file;
+	int err;
+
+	if((file = inode_dentry_name(ino, dentry)) == NULL) return(-ENOMEM);
+	err = do_rmdir(file);
+	kfree(file);
+	return(err);
+}
+
+int hostfs_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t dev)
+{
+	struct inode *inode;
+	char *name;
+	int err = -ENOMEM;
+
+	inode = iget(dir->i_sb, 0);
+	if(inode == NULL)
+		goto out;
+
+	err = init_inode(inode, dentry);
+	if(err)
+		goto out_put;
+
+	err = -ENOMEM;
+	name = dentry_name(dentry, 0);
+	if(name == NULL)
+		goto out_put;
+
+	init_special_inode(inode, mode, dev);
+	err = do_mknod(name, mode, dev);
+	if(err)
+		goto out_free;
+
+	err = read_name(inode, name);
+	kfree(name);
+	if(err)
+		goto out_put;
+
+	d_instantiate(dentry, inode);
+	return(0);
+
+ out_free:
+	kfree(name);
+ out_put:
+	iput(inode);
+ out:
+	return(err);
+}
+
+int hostfs_rename(struct inode *from_ino, struct dentry *from,
+		  struct inode *to_ino, struct dentry *to)
+{
+	char *from_name, *to_name;
+	int err;
+
+	if((from_name = inode_dentry_name(from_ino, from)) == NULL)
+		return(-ENOMEM);
+	if((to_name = inode_dentry_name(to_ino, to)) == NULL){
+		kfree(from_name);
+		return(-ENOMEM);
+	}
+	err = rename_file(from_name, to_name);
+	kfree(from_name);
+	kfree(to_name);
+	return(err);
+}
+
+void hostfs_truncate(struct inode *ino)
+{
+	not_implemented();
+}
+
+int hostfs_permission(struct inode *ino, int desired, struct nameidata *nd)
+{
+	char *name;
+	int r = 0, w = 0, x = 0, err;
+
+	if(desired & MAY_READ) r = 1;
+	if(desired & MAY_WRITE) w = 1;
+	if(desired & MAY_EXEC) x = 1;
+	name = inode_name(ino, 0);
+	if(name == NULL) return(-ENOMEM);
+	err = access_file(name, r, w, x);
+	kfree(name);
+	if(!err) err = vfs_permission(ino, desired);
+	return(err);
+}
+
+int hostfs_setattr(struct dentry *dentry, struct iattr *attr)
+{
+	struct hostfs_iattr attrs;
+	char *name;
+	int err;
+
+	if(append)
+		attr->ia_valid &= ~ATTR_SIZE;
+
+	attrs.ia_valid = 0;
+	if(attr->ia_valid & ATTR_MODE){
+		attrs.ia_valid |= HOSTFS_ATTR_MODE;
+		attrs.ia_mode = attr->ia_mode;
+	}
+	if(attr->ia_valid & ATTR_UID){
+		if((dentry->d_inode->i_sb->s_dev == ROOT_DEV) &&
+		   (attr->ia_uid == 0))
+			attr->ia_uid = getuid();
+		attrs.ia_valid |= HOSTFS_ATTR_UID;
+		attrs.ia_uid = attr->ia_uid;
+	}
+	if(attr->ia_valid & ATTR_GID){
+		if((dentry->d_inode->i_sb->s_dev == ROOT_DEV) &&
+		   (attr->ia_gid == 0))
+			attr->ia_gid = getuid();
+		attrs.ia_valid |= HOSTFS_ATTR_GID;
+		attrs.ia_gid = attr->ia_gid;
+	}
+	if(attr->ia_valid & ATTR_SIZE){
+		attrs.ia_valid |= HOSTFS_ATTR_SIZE;
+		attrs.ia_size = attr->ia_size;
+	}
+	if(attr->ia_valid & ATTR_ATIME){
+		attrs.ia_valid |= HOSTFS_ATTR_ATIME;
+		attrs.ia_atime = attr->ia_atime;
+	}
+	if(attr->ia_valid & ATTR_MTIME){
+		attrs.ia_valid |= HOSTFS_ATTR_MTIME;
+		attrs.ia_mtime = attr->ia_mtime;
+	}
+	if(attr->ia_valid & ATTR_CTIME){
+		attrs.ia_valid |= HOSTFS_ATTR_CTIME;
+		attrs.ia_ctime = attr->ia_ctime;
+	}
+	if(attr->ia_valid & ATTR_ATIME_SET){
+		attrs.ia_valid |= HOSTFS_ATTR_ATIME_SET;
+	}
+	if(attr->ia_valid & ATTR_MTIME_SET){
+		attrs.ia_valid |= HOSTFS_ATTR_MTIME_SET;
+	}
+	name = dentry_name(dentry, 0);
+	if(name == NULL) return(-ENOMEM);
+	err = set_attr(name, &attrs);
+	kfree(name);
+	if(err)
+		return(err);
+
+	return(inode_setattr(dentry->d_inode, attr));
+}
+
+int hostfs_getattr(struct vfsmount *mnt, struct dentry *dentry,
+	   struct kstat *stat)
+{
+	generic_fillattr(dentry->d_inode, stat);
+	return(0);
+}
+
+static struct inode_operations hostfs_iops = {
+	.create		= hostfs_create,
+	.link		= hostfs_link,
+	.unlink		= hostfs_unlink,
+	.symlink	= hostfs_symlink,
+	.mkdir		= hostfs_mkdir,
+	.rmdir		= hostfs_rmdir,
+	.mknod		= hostfs_mknod,
+	.rename		= hostfs_rename,
+	.truncate	= hostfs_truncate,
+	.permission	= hostfs_permission,
+	.setattr	= hostfs_setattr,
+	.getattr	= hostfs_getattr,
+};
+
+static struct inode_operations hostfs_dir_iops = {
+	.create		= hostfs_create,
+	.lookup		= hostfs_lookup,
+	.link		= hostfs_link,
+	.unlink		= hostfs_unlink,
+	.symlink	= hostfs_symlink,
+	.mkdir		= hostfs_mkdir,
+	.rmdir		= hostfs_rmdir,
+	.mknod		= hostfs_mknod,
+	.rename		= hostfs_rename,
+	.truncate	= hostfs_truncate,
+	.permission	= hostfs_permission,
+	.setattr	= hostfs_setattr,
+	.getattr	= hostfs_getattr,
+};
+
+int hostfs_link_readpage(struct file *file, struct page *page)
+{
+	char *buffer, *name;
+	long long start;
+	int err;
+
+	start = page->index << PAGE_CACHE_SHIFT;
+	buffer = kmap(page);
+	name = inode_name(page->mapping->host, 0);
+	if(name == NULL) return(-ENOMEM);
+	err = do_readlink(name, buffer, PAGE_CACHE_SIZE);
+	kfree(name);
+	if(err == PAGE_CACHE_SIZE)
+		err = -E2BIG;
+	else if(err > 0){
+		flush_dcache_page(page);
+		SetPageUptodate(page);
+		if (PageError(page)) ClearPageError(page);
+		err = 0;
+	}
+	kunmap(page);
+	unlock_page(page);
+	return(err);
+}
+
+static struct address_space_operations hostfs_link_aops = {
+	.readpage	= hostfs_link_readpage,
+};
+
+static int hostfs_fill_sb_common(struct super_block *sb, void *d, int silent)
+{
+	struct inode *root_inode;
+	char *name, *data = d;
+	int err;
+
+	sb->s_blocksize = 1024;
+	sb->s_blocksize_bits = 10;
+	sb->s_magic = HOSTFS_SUPER_MAGIC;
+	sb->s_op = &hostfs_sbops;
+
+	if((data == NULL) || (*data == '\0'))
+		data = root_ino;
+
+	err = -ENOMEM;
+	name = kmalloc(strlen(data) + 1, GFP_KERNEL);
+	if(name == NULL)
+		goto out;
+
+	strcpy(name, data);
+
+	root_inode = iget(sb, 0);
+	if(root_inode == NULL)
+		goto out_free;
+
+	err = init_inode(root_inode, NULL);
+	if(err)
+		goto out_put;
+
+	HOSTFS_I(root_inode)->host_filename = name;
+
+	err = -ENOMEM;
+	sb->s_root = d_alloc_root(root_inode);
+	if(sb->s_root == NULL)
+		goto out_put;
+
+	err = read_inode(root_inode);
+	if(err)
+		goto out_put;
+
+	return(0);
+
+ out_put:
+	iput(root_inode);
+ out_free:
+	kfree(name);
+ out:
+	return(err);
+}
+
+static struct super_block *hostfs_read_sb(struct file_system_type *type,
+					     int flags, const char *dev_name,
+					     void *data)
+{
+	return(get_sb_nodev(type, flags, data, hostfs_fill_sb_common));
+}
+
+static struct file_system_type hostfs_type = {
+	.owner 		= THIS_MODULE,
+	.name 		= "hostfs",
+	.get_sb 	= hostfs_read_sb,
+	.kill_sb	= kill_anon_super,
+	.fs_flags 	= 0,
+};
+
+static int __init init_hostfs(void)
+{
+	return(register_filesystem(&hostfs_type));
+}
+
+static void __exit exit_hostfs(void)
+{
+	unregister_filesystem(&hostfs_type);
+}
+
+module_init(init_hostfs)
+module_exit(exit_hostfs)
+MODULE_LICENSE("GPL");
+
+/*
+ * 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/fs/hostfs/hostfs_user.c b/fs/hostfs/hostfs_user.c
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/fs/hostfs/hostfs_user.c	2004-10-18 14:57:23 -07:00
@@ -0,0 +1,365 @@
+/*
+ * Copyright (C) 2000 Jeff Dike (jdike@karaya.com)
+ * Licensed under the GPL
+ */
+
+#include <unistd.h>
+#include <stdio.h>
+#include <fcntl.h>
+#include <dirent.h>
+#include <errno.h>
+#include <utime.h>
+#include <string.h>
+#include <sys/stat.h>
+#include <sys/time.h>
+#include <sys/vfs.h>
+#include "hostfs.h"
+#include "kern_util.h"
+#include "user.h"
+
+int stat_file(const char *path, unsigned long long *inode_out, int *mode_out,
+	      int *nlink_out, int *uid_out, int *gid_out,
+	      unsigned long long *size_out, struct timespec *atime_out,
+	      struct timespec *mtime_out, struct timespec *ctime_out,
+	      int *blksize_out, unsigned long long *blocks_out)
+{
+	struct stat64 buf;
+
+	if(lstat64(path, &buf) < 0)
+		return(-errno);
+
+	/* See the Makefile for why STAT64_INO_FIELD is passed in
+	 * by the build
+	 */
+	if(inode_out != NULL) *inode_out = buf.STAT64_INO_FIELD;
+	if(mode_out != NULL) *mode_out = buf.st_mode;
+	if(nlink_out != NULL) *nlink_out = buf.st_nlink;
+	if(uid_out != NULL) *uid_out = buf.st_uid;
+	if(gid_out != NULL) *gid_out = buf.st_gid;
+	if(size_out != NULL) *size_out = buf.st_size;
+	if(atime_out != NULL) {
+		atime_out->tv_sec = buf.st_atime;
+		atime_out->tv_nsec = 0;
+	}
+	if(mtime_out != NULL) {
+		mtime_out->tv_sec = buf.st_mtime;
+		mtime_out->tv_nsec = 0;
+	}
+	if(ctime_out != NULL) {
+		ctime_out->tv_sec = buf.st_ctime;
+		ctime_out->tv_nsec = 0;
+	}
+	if(blksize_out != NULL) *blksize_out = buf.st_blksize;
+	if(blocks_out != NULL) *blocks_out = buf.st_blocks;
+	return(0);
+}
+
+int file_type(const char *path, int *maj, int *min)
+{
+ 	struct stat64 buf;
+
+	if(lstat64(path, &buf) < 0)
+		return(-errno);
+	/*We cannot pass rdev as is because glibc and the kernel disagree
+	 *about its definition.*/
+	if(maj != NULL)
+		*maj = major(buf.st_rdev);
+	if(min != NULL)
+		*min = minor(buf.st_rdev);
+
+	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);
+	else return(OS_TYPE_FILE);
+}
+
+int access_file(char *path, int r, int w, int x)
+{
+	int mode = 0;
+
+	if(r) mode = R_OK;
+	if(w) mode |= W_OK;
+	if(x) mode |= X_OK;
+	if(access(path, mode) != 0) return(-errno);
+	else return(0);
+}
+
+int open_file(char *path, int r, int w, int append)
+{
+	int mode = 0, fd;
+
+	if(r && !w)
+		mode = O_RDONLY;
+	else if(!r && w)
+		mode = O_WRONLY;
+	else if(r && w)
+		mode = O_RDWR;
+	else panic("Impossible mode in open_file");
+
+	if(append)
+		mode |= O_APPEND;
+	fd = open64(path, mode);
+	if(fd < 0) return(-errno);
+	else return(fd);
+}
+
+void *open_dir(char *path, int *err_out)
+{
+	DIR *dir;
+
+	dir = opendir(path);
+	*err_out = errno;
+	if(dir == NULL) return(NULL);
+	return(dir);
+}
+
+char *read_dir(void *stream, unsigned long long *pos,
+	       unsigned long long *ino_out, int *len_out)
+{
+	DIR *dir = stream;
+	struct dirent *ent;
+
+	seekdir(dir, *pos);
+	ent = readdir(dir);
+	if(ent == NULL) return(NULL);
+	*len_out = strlen(ent->d_name);
+	*ino_out = ent->d_ino;
+	*pos = telldir(dir);
+	return(ent->d_name);
+}
+
+int read_file(int fd, unsigned long long *offset, char *buf, int len)
+{
+	int n;
+
+	n = pread64(fd, buf, len, *offset);
+	if(n < 0) return(-errno);
+	*offset += n;
+	return(n);
+}
+
+int write_file(int fd, unsigned long long *offset, const char *buf, int len)
+{
+	int n;
+
+	n = pwrite64(fd, buf, len, *offset);
+	if(n < 0) return(-errno);
+	*offset += n;
+	return(n);
+}
+
+int lseek_file(int fd, long long offset, int whence)
+{
+	int ret;
+
+	ret = lseek64(fd, offset, whence);
+	if(ret < 0) return(-errno);
+	return(0);
+}
+
+void close_file(void *stream)
+{
+	close(*((int *) stream));
+}
+
+void close_dir(void *stream)
+{
+	closedir(stream);
+}
+
+int file_create(char *name, int ur, int uw, int ux, int gr,
+		int gw, int gx, int or, int ow, int ox)
+{
+	int mode, fd;
+
+	mode = 0;
+	mode |= ur ? S_IRUSR : 0;
+	mode |= uw ? S_IWUSR : 0;
+	mode |= ux ? S_IXUSR : 0;
+	mode |= gr ? S_IRGRP : 0;
+	mode |= gw ? S_IWGRP : 0;
+	mode |= gx ? S_IXGRP : 0;
+	mode |= or ? S_IROTH : 0;
+	mode |= ow ? S_IWOTH : 0;
+	mode |= ox ? S_IXOTH : 0;
+	fd = open64(name, O_CREAT | O_RDWR, mode);
+	if(fd < 0)
+		return(-errno);
+	return(fd);
+}
+
+int set_attr(const char *file, struct hostfs_iattr *attrs)
+{
+	struct utimbuf buf;
+	int err, ma;
+
+	if(attrs->ia_valid & HOSTFS_ATTR_MODE){
+		if(chmod(file, attrs->ia_mode) != 0) return(-errno);
+	}
+	if(attrs->ia_valid & HOSTFS_ATTR_UID){
+		if(chown(file, attrs->ia_uid, -1)) return(-errno);
+	}
+	if(attrs->ia_valid & HOSTFS_ATTR_GID){
+		if(chown(file, -1, attrs->ia_gid)) return(-errno);
+	}
+	if(attrs->ia_valid & HOSTFS_ATTR_SIZE){
+		if(truncate(file, attrs->ia_size)) return(-errno);
+	}
+	ma = HOSTFS_ATTR_ATIME_SET | HOSTFS_ATTR_MTIME_SET;
+	if((attrs->ia_valid & ma) == ma){
+		buf.actime = attrs->ia_atime.tv_sec;
+		buf.modtime = attrs->ia_mtime.tv_sec;
+		if(utime(file, &buf) != 0) return(-errno);
+	}
+	else {
+		struct timespec ts;
+
+		if(attrs->ia_valid & HOSTFS_ATTR_ATIME_SET){
+			err = stat_file(file, NULL, NULL, NULL, NULL, NULL,
+					NULL, NULL, &ts, NULL, NULL, NULL);
+			if(err != 0)
+				return(err);
+			buf.actime = attrs->ia_atime.tv_sec;
+			buf.modtime = ts.tv_sec;
+			if(utime(file, &buf) != 0)
+				return(-errno);
+		}
+		if(attrs->ia_valid & HOSTFS_ATTR_MTIME_SET){
+			err = stat_file(file, NULL, NULL, NULL, NULL, NULL,
+					NULL, &ts, NULL, NULL, NULL, NULL);
+			if(err != 0)
+				return(err);
+			buf.actime = ts.tv_sec;
+			buf.modtime = attrs->ia_mtime.tv_sec;
+			if(utime(file, &buf) != 0)
+				return(-errno);
+		}
+	}
+	if(attrs->ia_valid & HOSTFS_ATTR_CTIME) ;
+	if(attrs->ia_valid & (HOSTFS_ATTR_ATIME | HOSTFS_ATTR_MTIME)){
+		err = stat_file(file, NULL, NULL, NULL, NULL, NULL, NULL,
+				&attrs->ia_atime, &attrs->ia_mtime, NULL,
+				NULL, NULL);
+		if(err != 0) return(err);
+	}
+	return(0);
+}
+
+int make_symlink(const char *from, const char *to)
+{
+	int err;
+
+	err = symlink(to, from);
+	if(err) return(-errno);
+	return(0);
+}
+
+int unlink_file(const char *file)
+{
+	int err;
+
+	err = unlink(file);
+	if(err) return(-errno);
+	return(0);
+}
+
+int do_mkdir(const char *file, int mode)
+{
+	int err;
+
+	err = mkdir(file, mode);
+	if(err) return(-errno);
+	return(0);
+}
+
+int do_rmdir(const char *file)
+{
+	int err;
+
+	err = rmdir(file);
+	if(err) return(-errno);
+	return(0);
+}
+
+int do_mknod(const char *file, int mode, int dev)
+{
+	int err;
+
+	err = mknod(file, mode, dev);
+	if(err) return(-errno);
+	return(0);
+}
+
+int link_file(const char *to, const char *from)
+{
+	int err;
+
+	err = link(to, from);
+	if(err) return(-errno);
+	return(0);
+}
+
+int do_readlink(char *file, char *buf, int size)
+{
+	int n;
+
+	n = readlink(file, buf, size);
+	if(n < 0)
+		return(-errno);
+	if(n < size)
+		buf[n] = '\0';
+	return(n);
+}
+
+int rename_file(char *from, char *to)
+{
+	int err;
+
+	err = rename(from, to);
+	if(err < 0) return(-errno);
+	return(0);
+}
+
+int do_statfs(char *root, long *bsize_out, long long *blocks_out,
+	      long long *bfree_out, long long *bavail_out,
+	      long long *files_out, long long *ffree_out,
+	      void *fsid_out, int fsid_size, long *namelen_out,
+	      long *spare_out)
+{
+	struct statfs64 buf;
+	int err;
+
+	err = statfs64(root, &buf);
+	if(err < 0) return(-errno);
+	*bsize_out = buf.f_bsize;
+	*blocks_out = buf.f_blocks;
+	*bfree_out = buf.f_bfree;
+	*bavail_out = buf.f_bavail;
+	*files_out = buf.f_files;
+	*ffree_out = buf.f_ffree;
+	memcpy(fsid_out, &buf.f_fsid,
+	       sizeof(buf.f_fsid) > fsid_size ? fsid_size :
+	       sizeof(buf.f_fsid));
+	*namelen_out = buf.f_namelen;
+	spare_out[0] = buf.f_spare[0];
+	spare_out[1] = buf.f_spare[1];
+	spare_out[2] = buf.f_spare[2];
+	spare_out[3] = buf.f_spare[3];
+	spare_out[4] = buf.f_spare[4];
+	spare_out[5] = buf.f_spare[5];
+	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/fs/hpfs/super.c b/fs/hpfs/super.c
--- a/fs/hpfs/super.c	2004-10-18 14:56:33 -07:00
+++ b/fs/hpfs/super.c	2004-10-18 14:56:33 -07:00
@@ -191,7 +191,7 @@
 {
 	hpfs_inode_cachep = kmem_cache_create("hpfs_inode_cache",
 					     sizeof(struct hpfs_inode_info),
-					     0, SLAB_HWCACHE_ALIGN|SLAB_RECLAIM_ACCOUNT,
+					     0, SLAB_RECLAIM_ACCOUNT,
 					     init_once, NULL);
 	if (hpfs_inode_cachep == NULL)
 		return -ENOMEM;
diff -Nru a/fs/hppfs/Makefile b/fs/hppfs/Makefile
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/fs/hppfs/Makefile	2004-10-18 14:57:21 -07:00
@@ -0,0 +1,19 @@
+#
+# Copyright (C) 2002, 2003 Jeff Dike (jdike@karaya.com)
+# Licensed under the GPL
+#
+
+hppfs-objs := hppfs_kern.o
+
+obj-y =
+obj-$(CONFIG_HPPFS) += hppfs.o
+
+clean:
+
+modules:
+
+fastdep:
+
+dep:
+
+archmrproper: clean
diff -Nru a/fs/hppfs/hppfs_kern.c b/fs/hppfs/hppfs_kern.c
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/fs/hppfs/hppfs_kern.c	2004-10-18 14:57:24 -07:00
@@ -0,0 +1,815 @@
+/*
+ * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
+ * Licensed under the GPL
+ */
+
+#include <linux/fs.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/list.h>
+#include <linux/kernel.h>
+#include <linux/ctype.h>
+#include <linux/dcache.h>
+#include <linux/statfs.h>
+#include <asm/uaccess.h>
+#include <asm/fcntl.h>
+#include "os.h"
+
+static int init_inode(struct inode *inode, struct dentry *dentry);
+
+struct hppfs_data {
+	struct list_head list;
+	char contents[PAGE_SIZE - sizeof(struct list_head)];
+};
+
+struct hppfs_private {
+	struct file *proc_file;
+	int host_fd;
+	loff_t len;
+	struct hppfs_data *contents;
+};
+
+struct hppfs_inode_info {
+        struct dentry *proc_dentry;
+	struct inode vfs_inode;
+};
+
+static inline struct hppfs_inode_info *HPPFS_I(struct inode *inode)
+{
+	return(list_entry(inode, struct hppfs_inode_info, vfs_inode));
+}
+
+#define HPPFS_SUPER_MAGIC 0xb00000ee
+
+static struct super_operations hppfs_sbops;
+
+static int is_pid(struct dentry *dentry)
+{
+	struct super_block *sb;
+	int i;
+
+	sb = dentry->d_sb;
+	if((sb->s_op != &hppfs_sbops) || (dentry->d_parent != sb->s_root))
+		return(0);
+
+	for(i = 0; i < dentry->d_name.len; i++){
+		if(!isdigit(dentry->d_name.name[i]))
+			return(0);
+	}
+	return(1);
+}
+
+static char *dentry_name(struct dentry *dentry, int extra)
+{
+	struct dentry *parent;
+	char *root, *name;
+	const char *seg_name;
+	int len, seg_len;
+
+	len = 0;
+	parent = dentry;
+	while(parent->d_parent != parent){
+		if(is_pid(parent))
+			len += strlen("pid") + 1;
+		else len += parent->d_name.len + 1;
+		parent = parent->d_parent;
+	}
+
+	root = "proc";
+	len += strlen(root);
+	name = kmalloc(len + extra + 1, GFP_KERNEL);
+	if(name == NULL) return(NULL);
+
+	name[len] = '\0';
+	parent = dentry;
+	while(parent->d_parent != parent){
+		if(is_pid(parent)){
+			seg_name = "pid";
+			seg_len = strlen("pid");
+		}
+		else {
+			seg_name = parent->d_name.name;
+			seg_len = parent->d_name.len;
+		}
+
+		len -= seg_len + 1;
+		name[len] = '/';
+		strncpy(&name[len + 1], seg_name, seg_len);
+		parent = parent->d_parent;
+	}
+	strncpy(name, root, strlen(root));
+	return(name);
+}
+
+struct dentry_operations hppfs_dentry_ops = {
+};
+
+static int file_removed(struct dentry *dentry, const char *file)
+{
+	char *host_file;
+	int extra, fd;
+
+	extra = 0;
+	if(file != NULL) extra += strlen(file) + 1;
+
+	host_file = dentry_name(dentry, extra + strlen("/remove"));
+	if(host_file == NULL){
+		printk("file_removed : allocation failed\n");
+		return(-ENOMEM);
+	}
+
+	if(file != NULL){
+		strcat(host_file, "/");
+		strcat(host_file, file);
+	}
+	strcat(host_file, "/remove");
+
+	fd = os_open_file(host_file, of_read(OPENFLAGS()), 0);
+	kfree(host_file);
+	if(fd > 0){
+		os_close_file(fd);
+		return(1);
+	}
+	return(0);
+}
+
+static void hppfs_read_inode(struct inode *ino)
+{
+	struct inode *proc_ino;
+
+	if(HPPFS_I(ino)->proc_dentry == NULL)
+		return;
+
+	proc_ino = HPPFS_I(ino)->proc_dentry->d_inode;
+	ino->i_uid = proc_ino->i_uid;
+	ino->i_gid = proc_ino->i_gid;
+	ino->i_atime = proc_ino->i_atime;
+	ino->i_mtime = proc_ino->i_mtime;
+	ino->i_ctime = proc_ino->i_ctime;
+	ino->i_ino = proc_ino->i_ino;
+	ino->i_mode = proc_ino->i_mode;
+	ino->i_nlink = proc_ino->i_nlink;
+	ino->i_size = proc_ino->i_size;
+	ino->i_blksize = proc_ino->i_blksize;
+	ino->i_blocks = proc_ino->i_blocks;
+}
+
+static struct dentry *hppfs_lookup(struct inode *ino, struct dentry *dentry,
+                                  struct nameidata *nd)
+{
+	struct dentry *proc_dentry, *new, *parent;
+	struct inode *inode;
+	int err, deleted;
+
+	deleted = file_removed(dentry, NULL);
+	if(deleted < 0)
+		return(ERR_PTR(deleted));
+	else if(deleted)
+		return(ERR_PTR(-ENOENT));
+
+	err = -ENOMEM;
+	parent = HPPFS_I(ino)->proc_dentry;
+	down(&parent->d_inode->i_sem);
+	proc_dentry = d_lookup(parent, &dentry->d_name);
+	if(proc_dentry == NULL){
+		proc_dentry = d_alloc(parent, &dentry->d_name);
+		if(proc_dentry == NULL){
+			up(&parent->d_inode->i_sem);
+			goto out;
+		}
+		new = (*parent->d_inode->i_op->lookup)(parent->d_inode,
+						       proc_dentry, NULL);
+		if(new){
+			dput(proc_dentry);
+			proc_dentry = new;
+		}
+	}
+	up(&parent->d_inode->i_sem);
+
+	if(IS_ERR(proc_dentry))
+		return(proc_dentry);
+
+	inode = iget(ino->i_sb, 0);
+	if(inode == NULL)
+		goto out_dput;
+
+	err = init_inode(inode, proc_dentry);
+	if(err)
+		goto out_put;
+
+	hppfs_read_inode(inode);
+
+ 	d_add(dentry, inode);
+	dentry->d_op = &hppfs_dentry_ops;
+	return(NULL);
+
+ out_put:
+	iput(inode);
+ out_dput:
+	dput(proc_dentry);
+ out:
+	return(ERR_PTR(err));
+}
+
+static struct inode_operations hppfs_file_iops = {
+};
+
+static ssize_t read_proc(struct file *file, char *buf, ssize_t count,
+			 loff_t *ppos, int is_user)
+{
+	ssize_t (*read)(struct file *, char *, size_t, loff_t *);
+	ssize_t n;
+
+	read = file->f_dentry->d_inode->i_fop->read;
+
+	if(!is_user)
+		set_fs(KERNEL_DS);
+
+	n = (*read)(file, buf, count, &file->f_pos);
+
+	if(!is_user)
+		set_fs(USER_DS);
+
+	if(ppos) *ppos = file->f_pos;
+	return(n);
+}
+
+static ssize_t hppfs_read_file(int fd, char *buf, ssize_t count)
+{
+	ssize_t n;
+	int cur, err;
+	char *new_buf;
+
+	n = -ENOMEM;
+	new_buf = kmalloc(PAGE_SIZE, GFP_KERNEL);
+	if(new_buf == NULL){
+		printk("hppfs_read_file : kmalloc failed\n");
+		goto out;
+	}
+	n = 0;
+	while(count > 0){
+		cur = min_t(ssize_t, count, PAGE_SIZE);
+		err = os_read_file(fd, new_buf, cur);
+		if(err < 0){
+			printk("hppfs_read : read failed, errno = %d\n",
+			       count);
+			n = err;
+			goto out_free;
+		}
+		else if(err == 0)
+			break;
+
+		if(copy_to_user(buf, new_buf, err)){
+			n = -EFAULT;
+			goto out_free;
+		}
+		n += err;
+		count -= err;
+	}
+ out_free:
+	kfree(new_buf);
+ out:
+	return(n);
+}
+
+static ssize_t hppfs_read(struct file *file, char *buf, size_t count,
+			  loff_t *ppos)
+{
+	struct hppfs_private *hppfs = file->private_data;
+	struct hppfs_data *data;
+	loff_t off;
+	int err;
+
+	if(hppfs->contents != NULL){
+		if(*ppos >= hppfs->len) return(0);
+
+		data = hppfs->contents;
+		off = *ppos;
+		while(off >= sizeof(data->contents)){
+			data = list_entry(data->list.next, struct hppfs_data,
+					  list);
+			off -= sizeof(data->contents);
+		}
+
+		if(off + count > hppfs->len)
+			count = hppfs->len - off;
+		copy_to_user(buf, &data->contents[off], count);
+		*ppos += count;
+	}
+	else if(hppfs->host_fd != -1){
+		err = os_seek_file(hppfs->host_fd, *ppos);
+		if(err){
+			printk("hppfs_read : seek failed, errno = %d\n", err);
+			return(err);
+		}
+		count = hppfs_read_file(hppfs->host_fd, buf, count);
+		if(count > 0)
+			*ppos += count;
+	}
+	else count = read_proc(hppfs->proc_file, buf, count, ppos, 1);
+
+	return(count);
+}
+
+static ssize_t hppfs_write(struct file *file, const char *buf, size_t len,
+			   loff_t *ppos)
+{
+	struct hppfs_private *data = file->private_data;
+	struct file *proc_file = data->proc_file;
+	ssize_t (*write)(struct file *, const char *, size_t, loff_t *);
+	int err;
+
+	write = proc_file->f_dentry->d_inode->i_fop->write;
+
+	proc_file->f_pos = file->f_pos;
+	err = (*write)(proc_file, buf, len, &proc_file->f_pos);
+	file->f_pos = proc_file->f_pos;
+
+	return(err);
+}
+
+static int open_host_sock(char *host_file, int *filter_out)
+{
+	char *end;
+	int fd;
+
+	end = &host_file[strlen(host_file)];
+	strcpy(end, "/rw");
+	*filter_out = 1;
+	fd = os_connect_socket(host_file);
+	if(fd > 0)
+		return(fd);
+
+	strcpy(end, "/r");
+	*filter_out = 0;
+	fd = os_connect_socket(host_file);
+	return(fd);
+}
+
+static void free_contents(struct hppfs_data *head)
+{
+	struct hppfs_data *data;
+	struct list_head *ele, *next;
+
+	if(head == NULL) return;
+
+	list_for_each_safe(ele, next, &head->list){
+		data = list_entry(ele, struct hppfs_data, list);
+		kfree(data);
+	}
+	kfree(head);
+}
+
+static struct hppfs_data *hppfs_get_data(int fd, int filter,
+					 struct file *proc_file,
+					 struct file *hppfs_file,
+					 loff_t *size_out)
+{
+	struct hppfs_data *data, *new, *head;
+	int n, err;
+
+	err = -ENOMEM;
+	data = kmalloc(sizeof(*data), GFP_KERNEL);
+	if(data == NULL){
+		printk("hppfs_get_data : head allocation failed\n");
+		goto failed;
+	}
+
+	INIT_LIST_HEAD(&data->list);
+
+	head = data;
+	*size_out = 0;
+
+	if(filter){
+		while((n = read_proc(proc_file, data->contents,
+				     sizeof(data->contents), NULL, 0)) > 0)
+			os_write_file(fd, data->contents, n);
+		err = os_shutdown_socket(fd, 0, 1);
+		if(err){
+			printk("hppfs_get_data : failed to shut down "
+			       "socket\n");
+			goto failed_free;
+		}
+	}
+	while(1){
+		n = os_read_file(fd, data->contents, sizeof(data->contents));
+		if(n < 0){
+			err = n;
+			printk("hppfs_get_data : read failed, errno = %d\n",
+			       err);
+			goto failed_free;
+		}
+		else if(n == 0)
+			break;
+
+		*size_out += n;
+
+		if(n < sizeof(data->contents))
+			break;
+
+		new = kmalloc(sizeof(*data), GFP_KERNEL);
+		if(new == 0){
+			printk("hppfs_get_data : data allocation failed\n");
+			err = -ENOMEM;
+			goto failed_free;
+		}
+
+		INIT_LIST_HEAD(&new->list);
+		list_add(&new->list, &data->list);
+		data = new;
+	}
+	return(head);
+
+ failed_free:
+	free_contents(head);
+ failed:
+	return(ERR_PTR(err));
+}
+
+static struct hppfs_private *hppfs_data(void)
+{
+	struct hppfs_private *data;
+
+	data = kmalloc(sizeof(*data), GFP_KERNEL);
+	if(data == NULL)
+		return(data);
+
+	*data = ((struct hppfs_private ) { .host_fd  		= -1,
+					   .len  		= -1,
+					   .contents 		= NULL } );
+	return(data);
+}
+
+static int file_mode(int fmode)
+{
+	if(fmode == (FMODE_READ | FMODE_WRITE))
+		return(O_RDWR);
+	if(fmode == FMODE_READ)
+		return(O_RDONLY);
+	if(fmode == FMODE_WRITE)
+		return(O_WRONLY);
+	return(0);
+}
+
+static int hppfs_open(struct inode *inode, struct file *file)
+{
+	struct hppfs_private *data;
+	struct dentry *proc_dentry;
+	char *host_file;
+	int err, fd, type, filter;
+
+	err = -ENOMEM;
+	data = hppfs_data();
+	if(data == NULL)
+		goto out;
+
+	host_file = dentry_name(file->f_dentry, strlen("/rw"));
+	if(host_file == NULL)
+		goto out_free2;
+
+	proc_dentry = HPPFS_I(inode)->proc_dentry;
+
+	/* XXX This isn't closed anywhere */
+	data->proc_file = dentry_open(dget(proc_dentry), NULL,
+				      file_mode(file->f_mode));
+	err = PTR_ERR(data->proc_file);
+	if(IS_ERR(data->proc_file))
+		goto out_free1;
+
+	type = os_file_type(host_file);
+	if(type == OS_TYPE_FILE){
+		fd = os_open_file(host_file, of_read(OPENFLAGS()), 0);
+		if(fd >= 0)
+			data->host_fd = fd;
+		else printk("hppfs_open : failed to open '%s', errno = %d\n",
+			    host_file, -fd);
+
+		data->contents = NULL;
+	}
+	else if(type == OS_TYPE_DIR){
+		fd = open_host_sock(host_file, &filter);
+		if(fd > 0){
+			data->contents = hppfs_get_data(fd, filter,
+							&data->proc_file,
+							file, &data->len);
+			if(!IS_ERR(data->contents))
+				data->host_fd = fd;
+		}
+		else printk("hppfs_open : failed to open a socket in "
+			    "'%s', errno = %d\n", host_file, -fd);
+	}
+	kfree(host_file);
+
+	file->private_data = data;
+	return(0);
+
+ out_free1:
+	kfree(host_file);
+ out_free2:
+	free_contents(data->contents);
+	kfree(data);
+ out:
+	return(err);
+}
+
+static int hppfs_dir_open(struct inode *inode, struct file *file)
+{
+	struct hppfs_private *data;
+	struct dentry *proc_dentry;
+	int err;
+
+	err = -ENOMEM;
+	data = hppfs_data();
+	if(data == NULL)
+		goto out;
+
+	proc_dentry = HPPFS_I(inode)->proc_dentry;
+	data->proc_file = dentry_open(dget(proc_dentry), NULL,
+				      file_mode(file->f_mode));
+	err = PTR_ERR(data->proc_file);
+	if(IS_ERR(data->proc_file))
+		goto out_free;
+
+	file->private_data = data;
+	return(0);
+
+ out_free:
+	kfree(data);
+ out:
+	return(err);
+}
+
+static loff_t hppfs_llseek(struct file *file, loff_t off, int where)
+{
+	struct hppfs_private *data = file->private_data;
+	struct file *proc_file = &data->proc_file;
+	loff_t (*llseek)(struct file *, loff_t, int);
+	loff_t ret;
+
+	llseek = proc_file->f_dentry->d_inode->i_fop->llseek;
+	if(llseek != NULL){
+		ret = (*llseek)(proc_file, off, where);
+		if(ret < 0)
+			return(ret);
+	}
+
+	return(default_llseek(file, off, where));
+}
+
+static struct file_operations hppfs_file_fops = {
+	.owner		= NULL,
+	.llseek		= hppfs_llseek,
+	.read		= hppfs_read,
+	.write		= hppfs_write,
+	.open		= hppfs_open,
+};
+
+struct hppfs_dirent {
+	void *vfs_dirent;
+	filldir_t filldir;
+	struct dentry *dentry;
+};
+
+static int hppfs_filldir(void *d, const char *name, int size,
+			 loff_t offset, ino_t inode, unsigned int type)
+{
+	struct hppfs_dirent *dirent = d;
+
+	if(file_removed(dirent->dentry, name))
+		return(0);
+
+	return((*dirent->filldir)(dirent->vfs_dirent, name, size, offset,
+				  inode, type));
+}
+
+static int hppfs_readdir(struct file *file, void *ent, filldir_t filldir)
+{
+	struct hppfs_private *data = file->private_data;
+	struct file *proc_file = &data->proc_file;
+	int (*readdir)(struct file *, void *, filldir_t);
+	struct hppfs_dirent dirent = ((struct hppfs_dirent)
+		                      { .vfs_dirent  	= ent,
+					.filldir 	= filldir,
+					.dentry  	= file->f_dentry } );
+	int err;
+
+	readdir = proc_file->f_dentry->d_inode->i_fop->readdir;
+
+	proc_file->f_pos = file->f_pos;
+	err = (*readdir)(proc_file, &dirent, hppfs_filldir);
+	file->f_pos = proc_file->f_pos;
+
+	return(err);
+}
+
+static int hppfs_fsync(struct file *file, struct dentry *dentry, int datasync)
+{
+	return(0);
+}
+
+static struct file_operations hppfs_dir_fops = {
+	.owner		= NULL,
+	.readdir	= hppfs_readdir,
+	.open		= hppfs_dir_open,
+	.fsync		= hppfs_fsync,
+};
+
+static int hppfs_statfs(struct super_block *sb, struct kstatfs *sf)
+{
+	sf->f_blocks = 0;
+	sf->f_bfree = 0;
+	sf->f_bavail = 0;
+	sf->f_files = 0;
+	sf->f_ffree = 0;
+	sf->f_type = HPPFS_SUPER_MAGIC;
+	return(0);
+}
+
+static struct inode *hppfs_alloc_inode(struct super_block *sb)
+{
+	struct hppfs_inode_info *hi;
+
+	hi = kmalloc(sizeof(*hi), GFP_KERNEL);
+	if(hi == NULL)
+		return(NULL);
+
+	*hi = ((struct hppfs_inode_info) { .proc_dentry	= NULL });
+	inode_init_once(&hi->vfs_inode);
+	return(&hi->vfs_inode);
+}
+
+void hppfs_delete_inode(struct inode *ino)
+{
+	clear_inode(ino);
+}
+
+static void hppfs_destroy_inode(struct inode *inode)
+{
+	kfree(HPPFS_I(inode));
+}
+
+static struct super_operations hppfs_sbops = {
+	.alloc_inode	= hppfs_alloc_inode,
+	.destroy_inode	= hppfs_destroy_inode,
+	.read_inode	= hppfs_read_inode,
+	.delete_inode	= hppfs_delete_inode,
+	.statfs		= hppfs_statfs,
+};
+
+static int hppfs_readlink(struct dentry *dentry, char *buffer, int buflen)
+{
+	struct file *proc_file;
+	struct dentry *proc_dentry;
+	int (*readlink)(struct dentry *, char *, int);
+	int err, n;
+
+	proc_dentry = HPPFS_I(dentry->d_inode)->proc_dentry;
+	proc_file = dentry_open(dget(proc_dentry), NULL, O_RDONLY);
+	err = PTR_ERR(proc_dentry);
+	if(IS_ERR(proc_dentry))
+		return(err);
+
+	readlink = proc_dentry->d_inode->i_op->readlink;
+	n = (*readlink)(proc_dentry, buffer, buflen);
+
+	fput(proc_file);
+
+	return(n);
+}
+
+static int hppfs_follow_link(struct dentry *dentry, struct nameidata *nd)
+{
+	struct file *proc_file;
+	struct dentry *proc_dentry;
+	int (*follow_link)(struct dentry *, struct nameidata *);
+	int err, n;
+
+	proc_dentry = HPPFS_I(dentry->d_inode)->proc_dentry;
+	proc_file = dentry_open(dget(proc_dentry), NULL, O_RDONLY);
+	err = PTR_ERR(proc_dentry);
+	if(IS_ERR(proc_dentry))
+		return(err);
+
+	follow_link = proc_dentry->d_inode->i_op->follow_link;
+	n = (*follow_link)(proc_dentry, nd);
+
+	fput(proc_file);
+
+	return(n);
+}
+
+static struct inode_operations hppfs_dir_iops = {
+	.lookup		= hppfs_lookup,
+};
+
+static struct inode_operations hppfs_link_iops = {
+	.readlink	= hppfs_readlink,
+	.follow_link	= hppfs_follow_link,
+};
+
+static int init_inode(struct inode *inode, struct dentry *dentry)
+{
+	if(S_ISDIR(dentry->d_inode->i_mode)){
+		inode->i_op = &hppfs_dir_iops;
+		inode->i_fop = &hppfs_dir_fops;
+	}
+	else if(S_ISLNK(dentry->d_inode->i_mode)){
+		inode->i_op = &hppfs_link_iops;
+		inode->i_fop = &hppfs_file_fops;
+	}
+	else {
+		inode->i_op = &hppfs_file_iops;
+		inode->i_fop = &hppfs_file_fops;
+	}
+
+	HPPFS_I(inode)->proc_dentry = dentry;
+
+	return(0);
+}
+
+static int hppfs_fill_super(struct super_block *sb, void *d, int silent)
+{
+	struct inode *root_inode;
+	struct file_system_type *procfs;
+	struct super_block *proc_sb;
+	int err;
+
+	err = -ENOENT;
+	procfs = get_fs_type("proc");
+	if(procfs == NULL)
+		goto out;
+
+	if(list_empty(&procfs->fs_supers))
+		goto out;
+
+	proc_sb = list_entry(procfs->fs_supers.next, struct super_block,
+			     s_instances);
+
+	sb->s_blocksize = 1024;
+	sb->s_blocksize_bits = 10;
+	sb->s_magic = HPPFS_SUPER_MAGIC;
+	sb->s_op = &hppfs_sbops;
+
+	root_inode = iget(sb, 0);
+	if(root_inode == NULL)
+		goto out;
+
+	err = init_inode(root_inode, proc_sb->s_root);
+	if(err)
+		goto out_put;
+
+	err = -ENOMEM;
+	sb->s_root = d_alloc_root(root_inode);
+	if(sb->s_root == NULL)
+		goto out_put;
+
+	hppfs_read_inode(root_inode);
+
+	return(0);
+
+ out_put:
+	iput(root_inode);
+ out:
+	return(err);
+}
+
+static struct super_block *hppfs_read_super(struct file_system_type *type,
+					     int flags, const char *dev_name,
+					     void *data)
+{
+	return(get_sb_nodev(type, flags, data, hppfs_fill_super));
+}
+
+static struct file_system_type hppfs_type = {
+	.owner 		= THIS_MODULE,
+	.name 		= "hppfs",
+	.get_sb 	= hppfs_read_super,
+	.kill_sb	= kill_anon_super,
+	.fs_flags 	= 0,
+};
+
+static int __init init_hppfs(void)
+{
+	return(register_filesystem(&hppfs_type));
+}
+
+static void __exit exit_hppfs(void)
+{
+	unregister_filesystem(&hppfs_type);
+}
+
+module_init(init_hppfs)
+module_exit(exit_hppfs)
+MODULE_LICENSE("GPL");
+
+/*
+ * 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/fs/hugetlbfs/inode.c b/fs/hugetlbfs/inode.c
--- a/fs/hugetlbfs/inode.c	2004-10-18 14:57:03 -07:00
+++ b/fs/hugetlbfs/inode.c	2004-10-18 14:57:03 -07:00
@@ -52,6 +52,9 @@
 	loff_t len, vma_len;
 	int ret;
 
+	if ((vma->vm_flags & (VM_MAYSHARE | VM_WRITE)) == VM_WRITE)
+		return -EINVAL;
+
 	if (vma->vm_pgoff & (HPAGE_SIZE / PAGE_SIZE - 1))
 		return -EINVAL;
 
@@ -70,10 +73,19 @@
 	file_accessed(file);
 	vma->vm_flags |= VM_HUGETLB | VM_RESERVED;
 	vma->vm_ops = &hugetlb_vm_ops;
+
+	ret = -ENOMEM;
+	len = vma_len + ((loff_t)vma->vm_pgoff << PAGE_SHIFT);
+	if (!(vma->vm_flags & VM_WRITE) && len > inode->i_size)
+		goto out;
+
 	ret = hugetlb_prefault(mapping, vma);
-	len = vma_len +	((loff_t)vma->vm_pgoff << PAGE_SHIFT);
-	if (ret == 0 && inode->i_size < len)
+	if (ret)
+		goto out;
+
+	if (inode->i_size < len)
 		inode->i_size = len;
+out:
 	up(&inode->i_sem);
 
 	return ret;
@@ -272,11 +284,10 @@
 static inline void
 hugetlb_vmtruncate_list(struct prio_tree_root *root, unsigned long h_pgoff)
 {
-	struct vm_area_struct *vma = NULL;
+	struct vm_area_struct *vma;
 	struct prio_tree_iter iter;
 
-	while ((vma = vma_prio_tree_next(vma, root, &iter,
-					h_pgoff, ULONG_MAX)) != NULL) {
+	vma_prio_tree_foreach(vma, &iter, root, h_pgoff, ULONG_MAX) {
 		unsigned long h_vm_pgoff;
 		unsigned long v_length;
 		unsigned long v_offset;
@@ -640,6 +651,7 @@
 	sbinfo->free_blocks = config.nr_blocks;
 	sbinfo->max_inodes = config.nr_inodes;
 	sbinfo->free_inodes = config.nr_inodes;
+	sb->s_maxbytes = MAX_LFS_FILESIZE;
 	sb->s_blocksize = HPAGE_SIZE;
 	sb->s_blocksize_bits = HPAGE_SHIFT;
 	sb->s_magic = HUGETLBFS_MAGIC;
@@ -721,12 +733,13 @@
 static int can_do_hugetlb_shm(void)
 {
 	return likely(capable(CAP_IPC_LOCK) ||
-			in_group_p(sysctl_hugetlb_shm_group));
+			in_group_p(sysctl_hugetlb_shm_group) ||
+			can_do_mlock());
 }
 
 struct file *hugetlb_zero_setup(size_t size)
 {
-	int error;
+	int error = -ENOMEM;
 	struct file *file;
 	struct inode *inode;
 	struct dentry *dentry, *root;
@@ -739,6 +752,9 @@
 	if (!is_hugepage_mem_enough(size))
 		return ERR_PTR(-ENOMEM);
 
+	if (!user_shm_lock(size, current->user))
+		return ERR_PTR(-ENOMEM);
+
 	root = hugetlbfs_vfsmount->mnt_root;
 	snprintf(buf, 16, "%lu", hugetlbfs_counter());
 	quick_string.name = buf;
@@ -746,7 +762,7 @@
 	quick_string.hash = 0;
 	dentry = d_alloc(root, &quick_string);
 	if (!dentry)
-		return ERR_PTR(-ENOMEM);
+		goto out_shm_unlock;
 
 	error = -ENFILE;
 	file = get_empty_filp();
@@ -773,6 +789,8 @@
 	put_filp(file);
 out_dentry:
 	dput(dentry);
+out_shm_unlock:
+	user_shm_unlock(size, current->user);
 	return ERR_PTR(error);
 }
 
@@ -783,8 +801,7 @@
 
 	hugetlbfs_inode_cachep = kmem_cache_create("hugetlbfs_inode_cache",
 					sizeof(struct hugetlbfs_inode_info),
-					0, SLAB_RECLAIM_ACCOUNT,
-					init_once, NULL);
+					0, 0, init_once, NULL);
 	if (hugetlbfs_inode_cachep == NULL)
 		return -ENOMEM;
 
diff -Nru a/fs/inode.c b/fs/inode.c
--- a/fs/inode.c	2004-10-18 14:57:04 -07:00
+++ b/fs/inode.c	2004-10-18 14:57:04 -07:00
@@ -243,6 +243,7 @@
  */
 void clear_inode(struct inode *inode)
 {
+	might_sleep();
 	invalidate_inode_buffers(inode);
        
 	if (inode->i_data.nrpages)
@@ -485,8 +486,9 @@
 		 * and we don't want to recurse into the FS that called us
 		 * in clear_inode() and friends..
 	 	 */
-		if (gfp_mask & __GFP_FS)
-			prune_icache(nr);
+		if (!(gfp_mask & __GFP_FS))
+			return -1;
+		prune_icache(nr);
 	}
 	return (inodes_stat.nr_unused / 100) * sysctl_vfs_cache_pressure;
 }
@@ -1372,8 +1374,7 @@
 
 	/* inode slab cache */
 	inode_cachep = kmem_cache_create("inode_cache", sizeof(struct inode),
-				0, SLAB_HWCACHE_ALIGN|SLAB_PANIC, init_once,
-				NULL);
+				0, SLAB_PANIC, init_once, NULL);
 	set_shrinker(DEFAULT_SEEKS, shrink_icache_memory);
 }
 
diff -Nru a/fs/isofs/compress.c b/fs/isofs/compress.c
--- a/fs/isofs/compress.c	2004-10-18 14:55:55 -07:00
+++ b/fs/isofs/compress.c	2004-10-18 14:55:55 -07:00
@@ -132,7 +132,7 @@
 			brelse(ptrbh[1]);
 		goto eio;
 	}
-	cstart = le32_to_cpu(*(u32 *)(bh->b_data + (blockptr & bufmask)));
+	cstart = le32_to_cpu(*(__le32 *)(bh->b_data + (blockptr & bufmask)));
 
 	if ( indexblocks == 2 ) {
 		/* We just crossed a block boundary.  Switch to the next block */
@@ -144,7 +144,7 @@
 			goto eio;
 		}
 	}
-	cend = le32_to_cpu(*(u32 *)(bh->b_data + (blockendptr & bufmask)));
+	cend = le32_to_cpu(*(__le32 *)(bh->b_data + (blockendptr & bufmask)));
 	brelse(bh);
 
 	csize = cend-cstart;
diff -Nru a/fs/isofs/inode.c b/fs/isofs/inode.c
--- a/fs/isofs/inode.c	2004-10-18 14:57:04 -07:00
+++ b/fs/isofs/inode.c	2004-10-18 14:57:04 -07:00
@@ -108,7 +108,7 @@
 {
 	isofs_inode_cachep = kmem_cache_create("isofs_inode_cache",
 					     sizeof(struct iso_inode_info),
-					     0, SLAB_HWCACHE_ALIGN|SLAB_RECLAIM_ACCOUNT,
+					     0, SLAB_RECLAIM_ACCOUNT,
 					     init_once, NULL);
 	if (isofs_inode_cachep == NULL)
 		return -ENOMEM;
@@ -715,6 +715,7 @@
 	  }
 
 	s->s_magic = ISOFS_SUPER_MAGIC;
+	s->s_maxbytes = 0xffffffff; /* We can handle files up to 4 GB */
 
 	/* The CDROM is read-only, has no nodes (devices) on it, and since
 	   all of the files appear to be owned by root, we really do not want
diff -Nru a/fs/isofs/rock.c b/fs/isofs/rock.c
--- a/fs/isofs/rock.c	2004-10-18 14:56:32 -07:00
+++ b/fs/isofs/rock.c	2004-10-18 14:56:32 -07:00
@@ -62,7 +62,7 @@
 }                                     
 
 #define MAYBE_CONTINUE(LABEL,DEV) \
-  {if (buffer) kfree(buffer); \
+  {if (buffer) { kfree(buffer); buffer = NULL; } \
   if (cont_extent){ \
     int block, offset, offset1; \
     struct buffer_head * pbh; \
@@ -153,14 +153,17 @@
     }
   }
   MAYBE_CONTINUE(repeat,inode);
+  if (buffer) kfree(buffer);
   return retnamlen; /* If 0, this file did not have a NM field */
  out:
   if(buffer) kfree(buffer);
   return 0;
 }
 
-int parse_rock_ridge_inode_internal(struct iso_directory_record * de,
-			            struct inode * inode,int regard_xa){
+static int
+parse_rock_ridge_inode_internal(struct iso_directory_record *de,
+				struct inode *inode, int regard_xa)
+{
   int len;
   unsigned char * chr;
   int symlink_len = 0;
@@ -174,7 +177,7 @@
      chr+=14;
      len-=14;
      if (len<0) len=0;
-   };
+   }
    
  repeat:
   {
@@ -351,7 +354,6 @@
     }
   }
   MAYBE_CONTINUE(repeat,inode);
-  return 0;
  out:
   if(buffer) kfree(buffer);
   return 0;
@@ -435,9 +437,9 @@
        &&(ISOFS_SB(inode->i_sb)->s_rock==2))
      {
 	result=parse_rock_ridge_inode_internal(de,inode,14);
-     };
+     }
    return result;
-};
+}
 
 /* readpage() for symlinks: reads symlink contents into the page and either
    makes it uptodate and returns 0 or returns error (-EIO) */
@@ -515,6 +517,8 @@
 		}
 	}
 	MAYBE_CONTINUE(repeat, inode);
+	if (buffer)
+		kfree(buffer);
 
 	if (rpnt == link)
 		goto fail;
diff -Nru a/fs/jbd/commit.c b/fs/jbd/commit.c
--- a/fs/jbd/commit.c	2004-10-18 14:57:03 -07:00
+++ b/fs/jbd/commit.c	2004-10-18 14:57:03 -07:00
@@ -405,9 +405,9 @@
 			jbd_debug(4, "JBD: got buffer %llu (%p)\n",
 				(unsigned long long)bh->b_blocknr, bh->b_data);
 			header = (journal_header_t *)&bh->b_data[0];
-			header->h_magic     = htonl(JFS_MAGIC_NUMBER);
-			header->h_blocktype = htonl(JFS_DESCRIPTOR_BLOCK);
-			header->h_sequence  = htonl(commit_transaction->t_tid);
+			header->h_magic     = cpu_to_be32(JFS_MAGIC_NUMBER);
+			header->h_blocktype = cpu_to_be32(JFS_DESCRIPTOR_BLOCK);
+			header->h_sequence  = cpu_to_be32(commit_transaction->t_tid);
 
 			tagp = &bh->b_data[sizeof(journal_header_t)];
 			space_left = bh->b_size - sizeof(journal_header_t);
@@ -473,8 +473,8 @@
 			tag_flag |= JFS_FLAG_SAME_UUID;
 
 		tag = (journal_block_tag_t *) tagp;
-		tag->t_blocknr = htonl(jh2bh(jh)->b_blocknr);
-		tag->t_flags = htonl(tag_flag);
+		tag->t_blocknr = cpu_to_be32(jh2bh(jh)->b_blocknr);
+		tag->t_flags = cpu_to_be32(tag_flag);
 		tagp += sizeof(journal_block_tag_t);
 		space_left -= sizeof(journal_block_tag_t);
 
@@ -498,7 +498,7 @@
                            submitting the IOs.  "tag" still points to
                            the last tag we set up. */
 
-			tag->t_flags |= htonl(JFS_FLAG_LAST_TAG);
+			tag->t_flags |= cpu_to_be32(JFS_FLAG_LAST_TAG);
 
 start_journal_io:
 			for (i = 0; i < bufs; i++) {
@@ -631,18 +631,46 @@
 	for (i = 0; i < jh2bh(descriptor)->b_size; i += 512) {
 		journal_header_t *tmp =
 			(journal_header_t*)jh2bh(descriptor)->b_data;
-		tmp->h_magic = htonl(JFS_MAGIC_NUMBER);
-		tmp->h_blocktype = htonl(JFS_COMMIT_BLOCK);
-		tmp->h_sequence = htonl(commit_transaction->t_tid);
+		tmp->h_magic = cpu_to_be32(JFS_MAGIC_NUMBER);
+		tmp->h_blocktype = cpu_to_be32(JFS_COMMIT_BLOCK);
+		tmp->h_sequence = cpu_to_be32(commit_transaction->t_tid);
 	}
 
 	JBUFFER_TRACE(descriptor, "write commit block");
 	{
 		struct buffer_head *bh = jh2bh(descriptor);
+		int ret;
+		int barrier_done = 0;
 
 		set_buffer_dirty(bh);
-		sync_dirty_buffer(bh);
-		if (unlikely(!buffer_uptodate(bh)))
+		if (journal->j_flags & JFS_BARRIER) {
+			set_buffer_ordered(bh);
+			barrier_done = 1;
+		}
+		ret = sync_dirty_buffer(bh);
+		/* is it possible for another commit to fail at roughly
+		 * the same time as this one?  If so, we don't want to
+		 * trust the barrier flag in the super, but instead want
+		 * to remember if we sent a barrier request
+		 */
+		if (ret == -EOPNOTSUPP && barrier_done) {
+			char b[BDEVNAME_SIZE];
+
+			printk(KERN_WARNING
+				"JBD: barrier-based sync failed on %s - "
+				"disabling barriers\n",
+				bdevname(journal->j_dev, b));
+			spin_lock(&journal->j_state_lock);
+			journal->j_flags &= ~JFS_BARRIER;
+			spin_unlock(&journal->j_state_lock);
+
+			/* And try again, without the barrier */
+			clear_buffer_ordered(bh);
+			set_buffer_uptodate(bh);
+			set_buffer_dirty(bh);
+			ret = sync_dirty_buffer(bh);
+		}
+		if (unlikely(ret == -EIO))
 			err = -EIO;
 		put_bh(bh);		/* One for getblk() */
 		journal_put_journal_head(descriptor);
diff -Nru a/fs/jbd/journal.c b/fs/jbd/journal.c
--- a/fs/jbd/journal.c	2004-10-18 14:56:14 -07:00
+++ b/fs/jbd/journal.c	2004-10-18 14:56:14 -07:00
@@ -34,6 +34,7 @@
 #include <linux/suspend.h>
 #include <linux/pagemap.h>
 #include <asm/uaccess.h>
+#include <asm/page.h>
 #include <linux/proc_fs.h>
 
 EXPORT_SYMBOL(journal_start);
@@ -325,8 +326,8 @@
 	/*
 	 * Check for escaping
 	 */
-	if (*((unsigned int *)(mapped_data + new_offset)) ==
-				htonl(JFS_MAGIC_NUMBER)) {
+	if (*((__be32 *)(mapped_data + new_offset)) ==
+				cpu_to_be32(JFS_MAGIC_NUMBER)) {
 		need_copy_out = 1;
 		do_escape = 1;
 	}
@@ -808,8 +809,8 @@
 	journal_superblock_t *sb = journal->j_superblock;
 	unsigned int first, last;
 
-	first = ntohl(sb->s_first);
-	last = ntohl(sb->s_maxlen);
+	first = be32_to_cpu(sb->s_first);
+	last = be32_to_cpu(sb->s_maxlen);
 
 	journal->j_first = first;
 	journal->j_last = last;
@@ -886,12 +887,12 @@
 	/* OK, fill in the initial static fields in the new superblock */
 	sb = journal->j_superblock;
 
-	sb->s_header.h_magic	 = htonl(JFS_MAGIC_NUMBER);
-	sb->s_header.h_blocktype = htonl(JFS_SUPERBLOCK_V2);
+	sb->s_header.h_magic	 = cpu_to_be32(JFS_MAGIC_NUMBER);
+	sb->s_header.h_blocktype = cpu_to_be32(JFS_SUPERBLOCK_V2);
 
-	sb->s_blocksize	= htonl(journal->j_blocksize);
-	sb->s_maxlen	= htonl(journal->j_maxlen);
-	sb->s_first	= htonl(1);
+	sb->s_blocksize	= cpu_to_be32(journal->j_blocksize);
+	sb->s_maxlen	= cpu_to_be32(journal->j_maxlen);
+	sb->s_first	= cpu_to_be32(1);
 
 	journal->j_transaction_sequence = 1;
 
@@ -934,9 +935,9 @@
 	jbd_debug(1,"JBD: updating superblock (start %ld, seq %d, errno %d)\n",
 		  journal->j_tail, journal->j_tail_sequence, journal->j_errno);
 
-	sb->s_sequence = htonl(journal->j_tail_sequence);
-	sb->s_start    = htonl(journal->j_tail);
-	sb->s_errno    = htonl(journal->j_errno);
+	sb->s_sequence = cpu_to_be32(journal->j_tail_sequence);
+	sb->s_start    = cpu_to_be32(journal->j_tail);
+	sb->s_errno    = cpu_to_be32(journal->j_errno);
 	spin_unlock(&journal->j_state_lock);
 
 	BUFFER_TRACE(bh, "marking dirty");
@@ -987,13 +988,13 @@
 
 	err = -EINVAL;
 
-	if (sb->s_header.h_magic != htonl(JFS_MAGIC_NUMBER) ||
-	    sb->s_blocksize != htonl(journal->j_blocksize)) {
+	if (sb->s_header.h_magic != cpu_to_be32(JFS_MAGIC_NUMBER) ||
+	    sb->s_blocksize != cpu_to_be32(journal->j_blocksize)) {
 		printk(KERN_WARNING "JBD: no valid journal superblock found\n");
 		goto out;
 	}
 
-	switch(ntohl(sb->s_header.h_blocktype)) {
+	switch(be32_to_cpu(sb->s_header.h_blocktype)) {
 	case JFS_SUPERBLOCK_V1:
 		journal->j_format_version = 1;
 		break;
@@ -1005,9 +1006,9 @@
 		goto out;
 	}
 
-	if (ntohl(sb->s_maxlen) < journal->j_maxlen)
-		journal->j_maxlen = ntohl(sb->s_maxlen);
-	else if (ntohl(sb->s_maxlen) > journal->j_maxlen) {
+	if (be32_to_cpu(sb->s_maxlen) < journal->j_maxlen)
+		journal->j_maxlen = be32_to_cpu(sb->s_maxlen);
+	else if (be32_to_cpu(sb->s_maxlen) > journal->j_maxlen) {
 		printk (KERN_WARNING "JBD: journal file too short\n");
 		goto out;
 	}
@@ -1035,11 +1036,11 @@
 
 	sb = journal->j_superblock;
 
-	journal->j_tail_sequence = ntohl(sb->s_sequence);
-	journal->j_tail = ntohl(sb->s_start);
-	journal->j_first = ntohl(sb->s_first);
-	journal->j_last = ntohl(sb->s_maxlen);
-	journal->j_errno = ntohl(sb->s_errno);
+	journal->j_tail_sequence = be32_to_cpu(sb->s_sequence);
+	journal->j_tail = be32_to_cpu(sb->s_start);
+	journal->j_first = be32_to_cpu(sb->s_first);
+	journal->j_last = be32_to_cpu(sb->s_maxlen);
+	journal->j_errno = be32_to_cpu(sb->s_errno);
 
 	return 0;
 }
@@ -1252,7 +1253,7 @@
 
 	sb = journal->j_superblock;
 
-	switch (ntohl(sb->s_header.h_blocktype)) {
+	switch (be32_to_cpu(sb->s_header.h_blocktype)) {
 	case JFS_SUPERBLOCK_V2:
 		return 0;
 	case JFS_SUPERBLOCK_V1:
@@ -1274,7 +1275,7 @@
 
 	/* Pre-initialise new fields to zero */
 	offset = ((char *) &(sb->s_feature_compat)) - ((char *) sb);
-	blocksize = ntohl(sb->s_blocksize);
+	blocksize = be32_to_cpu(sb->s_blocksize);
 	memset(&sb->s_feature_compat, 0, blocksize-offset);
 
 	sb->s_nr_users = cpu_to_be32(1);
diff -Nru a/fs/jbd/recovery.c b/fs/jbd/recovery.c
--- a/fs/jbd/recovery.c	2004-10-18 14:56:49 -07:00
+++ b/fs/jbd/recovery.c	2004-10-18 14:56:49 -07:00
@@ -191,10 +191,10 @@
 
 		nr++;
 		tagp += sizeof(journal_block_tag_t);
-		if (!(tag->t_flags & htonl(JFS_FLAG_SAME_UUID)))
+		if (!(tag->t_flags & cpu_to_be32(JFS_FLAG_SAME_UUID)))
 			tagp += 16;
 
-		if (tag->t_flags & htonl(JFS_FLAG_LAST_TAG))
+		if (tag->t_flags & cpu_to_be32(JFS_FLAG_LAST_TAG))
 			break;
 	}
 
@@ -239,8 +239,8 @@
 
 	if (!sb->s_start) {
 		jbd_debug(1, "No recovery required, last transaction %d\n",
-			  ntohl(sb->s_sequence));
-		journal->j_transaction_sequence = ntohl(sb->s_sequence) + 1;
+			  be32_to_cpu(sb->s_sequence));
+		journal->j_transaction_sequence = be32_to_cpu(sb->s_sequence) + 1;
 		return 0;
 	}
 
@@ -295,7 +295,7 @@
 		++journal->j_transaction_sequence;
 	} else {
 #ifdef CONFIG_JBD_DEBUG
-		int dropped = info.end_transaction - ntohl(sb->s_sequence);
+		int dropped = info.end_transaction - be32_to_cpu(sb->s_sequence);
 #endif
 		jbd_debug(0, 
 			  "JBD: ignoring %d transaction%s from the journal.\n",
@@ -331,8 +331,8 @@
 	 */
 
 	sb = journal->j_superblock;
-	next_commit_ID = ntohl(sb->s_sequence);
-	next_log_block = ntohl(sb->s_start);
+	next_commit_ID = be32_to_cpu(sb->s_sequence);
+	next_log_block = be32_to_cpu(sb->s_start);
 
 	first_commit_ID = next_commit_ID;
 	if (pass == PASS_SCAN)
@@ -385,13 +385,13 @@
 
 		tmp = (journal_header_t *)bh->b_data;
 
-		if (tmp->h_magic != htonl(JFS_MAGIC_NUMBER)) {
+		if (tmp->h_magic != cpu_to_be32(JFS_MAGIC_NUMBER)) {
 			brelse(bh);
 			break;
 		}
 
-		blocktype = ntohl(tmp->h_blocktype);
-		sequence = ntohl(tmp->h_sequence);
+		blocktype = be32_to_cpu(tmp->h_blocktype);
+		sequence = be32_to_cpu(tmp->h_sequence);
 		jbd_debug(3, "Found magic %d, sequence %d\n", 
 			  blocktype, sequence);
 
@@ -427,7 +427,7 @@
 				unsigned long io_block;
 
 				tag = (journal_block_tag_t *) tagp;
-				flags = ntohl(tag->t_flags);
+				flags = be32_to_cpu(tag->t_flags);
 
 				io_block = next_log_block++;
 				wrap(journal, next_log_block);
@@ -444,7 +444,7 @@
 					unsigned long blocknr;
 
 					J_ASSERT(obh != NULL);
-					blocknr = ntohl(tag->t_blocknr);
+					blocknr = be32_to_cpu(tag->t_blocknr);
 
 					/* If the block has been
 					 * revoked, then we're all done
@@ -476,8 +476,8 @@
 					memcpy(nbh->b_data, obh->b_data,
 							journal->j_blocksize);
 					if (flags & JFS_FLAG_ESCAPE) {
-						*((unsigned int *)bh->b_data) =
-							htonl(JFS_MAGIC_NUMBER);
+						*((__be32 *)bh->b_data) =
+						cpu_to_be32(JFS_MAGIC_NUMBER);
 					}
 
 					BUFFER_TRACE(nbh, "marking dirty");
@@ -572,13 +572,13 @@
 
 	header = (journal_revoke_header_t *) bh->b_data;
 	offset = sizeof(journal_revoke_header_t);
-	max = ntohl(header->r_count);
+	max = be32_to_cpu(header->r_count);
 
 	while (offset < max) {
 		unsigned long blocknr;
 		int err;
 
-		blocknr = ntohl(* ((unsigned int *) (bh->b_data+offset)));
+		blocknr = be32_to_cpu(* ((__be32 *) (bh->b_data+offset)));
 		offset += 4;
 		err = journal_set_revoke(journal, blocknr, sequence);
 		if (err)
diff -Nru a/fs/jbd/revoke.c b/fs/jbd/revoke.c
--- a/fs/jbd/revoke.c	2004-10-18 14:55:54 -07:00
+++ b/fs/jbd/revoke.c	2004-10-18 14:55:54 -07:00
@@ -332,6 +332,7 @@
 	struct block_device *bdev;
 	int err;
 
+	might_sleep();
 	if (bh_in)
 		BUFFER_TRACE(bh_in, "enter");
 
@@ -565,9 +566,9 @@
 		if (!descriptor)
 			return;
 		header = (journal_header_t *) &jh2bh(descriptor)->b_data[0];
-		header->h_magic     = htonl(JFS_MAGIC_NUMBER);
-		header->h_blocktype = htonl(JFS_REVOKE_BLOCK);
-		header->h_sequence  = htonl(transaction->t_tid);
+		header->h_magic     = cpu_to_be32(JFS_MAGIC_NUMBER);
+		header->h_blocktype = cpu_to_be32(JFS_REVOKE_BLOCK);
+		header->h_sequence  = cpu_to_be32(transaction->t_tid);
 
 		/* Record it so that we can wait for IO completion later */
 		JBUFFER_TRACE(descriptor, "file as BJ_LogCtl");
@@ -577,8 +578,8 @@
 		*descriptorp = descriptor;
 	}
 
-	* ((unsigned int *)(&jh2bh(descriptor)->b_data[offset])) = 
-		htonl(record->blocknr);
+	* ((__be32 *)(&jh2bh(descriptor)->b_data[offset])) = 
+		cpu_to_be32(record->blocknr);
 	offset += 4;
 	*offsetp = offset;
 }
@@ -603,7 +604,7 @@
 	}
 
 	header = (journal_revoke_header_t *) jh2bh(descriptor)->b_data;
-	header->r_count = htonl(offset);
+	header->r_count = cpu_to_be32(offset);
 	set_buffer_jwrite(bh);
 	BUFFER_TRACE(bh, "write");
 	set_buffer_dirty(bh);
diff -Nru a/fs/jffs2/super.c b/fs/jffs2/super.c
--- a/fs/jffs2/super.c	2004-10-18 14:56:28 -07:00
+++ b/fs/jffs2/super.c	2004-10-18 14:56:28 -07:00
@@ -7,7 +7,7 @@
  *
  * For licensing information, see the file 'LICENCE' in this directory.
  *
- * $Id: super.c,v 1.97 2004/07/16 15:17:57 dwmw2 Exp $
+ * $Id: super.c,v 1.99 2004/08/24 07:59:57 dwmw2 Exp $
  *
  */
 
@@ -130,7 +130,7 @@
 		  mtd->index, mtd->name));
 
 	sb->s_op = &jffs2_super_operations;
-	sb->s_flags |= MS_NOATIME;
+	sb->s_flags = flags | MS_NOATIME;
 
 	ret = jffs2_do_fill_super(sb, data, (flags&MS_VERBOSE)?1:0);
 
@@ -302,7 +302,7 @@
 
 	jffs2_inode_cachep = kmem_cache_create("jffs2_i",
 					     sizeof(struct jffs2_inode_info),
-					     0, SLAB_HWCACHE_ALIGN|SLAB_RECLAIM_ACCOUNT,
+					     0, SLAB_RECLAIM_ACCOUNT,
 					     jffs2_i_init_once, NULL);
 	if (!jffs2_inode_cachep) {
 		printk(KERN_ERR "JFFS2 error: Failed to initialise inode cache\n");
@@ -330,6 +330,7 @@
  out_compressors:
 	jffs2_compressors_exit();
  out:
+	kmem_cache_destroy(jffs2_inode_cachep);
 	return ret;
 }
 
diff -Nru a/fs/jfs/acl.c b/fs/jfs/acl.c
--- a/fs/jfs/acl.c	2004-10-18 14:55:54 -07:00
+++ b/fs/jfs/acl.c	2004-10-18 14:55:54 -07:00
@@ -1,7 +1,7 @@
 /*
- *   Copyright (c) International Business Machines  Corp., 2002
- *   Copyright (c) Andreas Gruenbacher, 2001
- *   Copyright (c) Linus Torvalds, 1991, 1992
+ *   Copyright (C) International Business Machines  Corp., 2002-2004
+ *   Copyright (C) Andreas Gruenbacher, 2001
+ *   Copyright (C) Linus Torvalds, 1991, 1992
  *
  *   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
@@ -20,6 +20,7 @@
 
 #include <linux/sched.h>
 #include <linux/fs.h>
+#include <linux/quotaops.h>
 #include "jfs_incore.h"
 #include "jfs_xattr.h"
 #include "jfs_acl.h"
@@ -280,6 +281,12 @@
 	rc = inode_change_ok(inode, iattr);
 	if (rc)
 		return rc;
+
+	if ((iattr->ia_valid & ATTR_UID && iattr->ia_uid != inode->i_uid) ||
+	    (iattr->ia_valid & ATTR_GID && iattr->ia_gid != inode->i_gid)) {
+		if (DQUOT_TRANSFER(inode, iattr))
+			return -EDQUOT;
+	}
 
 	rc = inode_setattr(inode, iattr);
 
diff -Nru a/fs/jfs/inode.c b/fs/jfs/inode.c
--- a/fs/jfs/inode.c	2004-10-18 14:55:46 -07:00
+++ b/fs/jfs/inode.c	2004-10-18 14:55:46 -07:00
@@ -1,6 +1,6 @@
 /*
- *   Copyright (c) International Business Machines Corp., 2000-2002
- *   Portions Copyright (c) Christoph Hellwig, 2001-2002
+ *   Copyright (C) International Business Machines Corp., 2000-2004
+ *   Portions Copyright (C) Christoph Hellwig, 2001-2002
  *
  *   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
@@ -21,6 +21,7 @@
 #include <linux/mpage.h>
 #include <linux/buffer_head.h>
 #include <linux/pagemap.h>
+#include <linux/quotaops.h>
 #include "jfs_incore.h"
 #include "jfs_filsys.h"
 #include "jfs_imap.h"
@@ -105,10 +106,10 @@
 	return rc;
 }
 
-void jfs_write_inode(struct inode *inode, int wait)
+int jfs_write_inode(struct inode *inode, int wait)
 {
 	if (test_cflag(COMMIT_Nolink, inode))
-		return;
+		return 0;
 	/*
 	 * If COMMIT_DIRTY is not set, the inode isn't really dirty.
 	 * It has been committed since the last change, but was still
@@ -117,12 +118,14 @@
 	 if (!test_cflag(COMMIT_Dirty, inode)) {
 		/* Make sure committed changes hit the disk */
 		jfs_flush_journal(JFS_SBI(inode->i_sb)->log, wait);
-		return;
+		return 0;
 	 }
 
 	if (jfs_commit_inode(inode, wait)) {
 		jfs_err("jfs_write_inode: jfs_commit_inode failed!");
-	}
+		return -EIO;
+	} else
+		return 0;
 }
 
 void jfs_delete_inode(struct inode *inode)
@@ -133,6 +136,13 @@
 		freeZeroLink(inode);
 
 	diFree(inode);
+
+	/*
+	 * Free the inode from the quota allocation.
+	 */
+	DQUOT_INIT(inode);
+	DQUOT_FREE_INODE(inode);
+	DQUOT_DROP(inode);
 
 	clear_inode(inode);
 }
diff -Nru a/fs/jfs/jfs_dtree.c b/fs/jfs/jfs_dtree.c
--- a/fs/jfs/jfs_dtree.c	2004-10-18 14:56:48 -07:00
+++ b/fs/jfs/jfs_dtree.c	2004-10-18 14:56:48 -07:00
@@ -101,6 +101,7 @@
  */
 
 #include <linux/fs.h>
+#include <linux/quotaops.h>
 #include "jfs_incore.h"
 #include "jfs_superblock.h"
 #include "jfs_filsys.h"
@@ -380,7 +381,8 @@
 		 * It's time to move the inline table to an external
 		 * page and begin to build the xtree
 		 */
-		if (dbAlloc(ip, 0, sbi->nbperpage, &xaddr))
+		if (DQUOT_ALLOC_BLOCK(ip, sbi->nbperpage) ||
+		    dbAlloc(ip, 0, sbi->nbperpage, &xaddr))
 			goto clean_up;	/* No space */
 
 		/*
@@ -405,7 +407,6 @@
 			goto clean_up;
 		}
 		ip->i_size = PSIZE;
-		ip->i_blocks += LBLK2PBLK(sb, sbi->nbperpage);
 
 		if ((mp = get_index_page(ip, 0)) == 0) {
 			jfs_err("add_index: get_metapage failed!");
@@ -447,7 +448,6 @@
 			goto clean_up;
 		}
 		ip->i_size += PSIZE;
-		ip->i_blocks += LBLK2PBLK(sb, sbi->nbperpage);
 
 		if ((mp = get_index_page(ip, blkno)))
 			memset(mp->data, 0, PSIZE);	/* Just looks better */
@@ -946,6 +946,7 @@
 	struct dt_lock *dtlck;
 	struct tlock *tlck;
 	struct lv *lv;
+	int quota_allocation = 0;
 
 	/* get split page */
 	smp = split->mp;
@@ -992,7 +993,9 @@
 		split->pxdlist = &pxdlist;
 		rc = dtSplitRoot(tid, ip, split, &rmp);
 
-		if (!rc)
+		if (rc)
+			dbFree(ip, xaddr, xlen);
+		else
 			DT_PUTPAGE(rmp);
 
 		DT_PUTPAGE(smp);
@@ -1017,6 +1020,14 @@
 			n = xlen + (xlen << 1);
 		else
 			n = xlen;
+
+		/* Allocate blocks to quota. */
+		if (DQUOT_ALLOC_BLOCK(ip, n)) {
+			rc = -EDQUOT;
+			goto extendOut;
+		}
+		quota_allocation += n;
+
 		if ((rc = dbReAlloc(sbi->ipbmap, xaddr, (s64) xlen,
 				    (s64) n, &nxaddr)))
 			goto extendOut;
@@ -1285,6 +1296,10 @@
       freeKeyName:
 	kfree(key.name);
 
+	/* Rollback quota allocation */
+	if (rc && quota_allocation)
+		DQUOT_FREE_BLOCK(ip, quota_allocation);
+
       dtSplitUp_Exit:
 
 	return rc;
@@ -1305,7 +1320,6 @@
 static int dtSplitPage(tid_t tid, struct inode *ip, struct dtsplit * split,
 	    struct metapage ** rmpp, dtpage_t ** rpp, pxd_t * rpxdp)
 {
-	struct super_block *sb = ip->i_sb;
 	int rc = 0;
 	struct metapage *smp;
 	dtpage_t *sp;
@@ -1344,6 +1358,12 @@
 	if (rmp == NULL)
 		return -EIO;
 
+	/* Allocate blocks to quota. */
+	if (DQUOT_ALLOC_BLOCK(ip, lengthPXD(pxd))) {
+		release_metapage(rmp);
+		return -EDQUOT;
+	}
+
 	jfs_info("dtSplitPage: ip:0x%p smp:0x%p rmp:0x%p", ip, smp, rmp);
 
 	BT_MARK_DIRTY(rmp, ip);
@@ -1593,8 +1613,6 @@
 	*rmpp = rmp;
 	*rpxdp = *pxd;
 
-	ip->i_blocks += LBLK2PBLK(sb, lengthPXD(pxd));
-
 	return rc;
 }
 
@@ -1823,16 +1841,6 @@
 	tpxd = (pxd_t *) & pp->slot[1];
 	*tpxd = *pxd;
 
-	/* Since the directory might have an EA and/or ACL associated with it
-	 * we need to make sure we take that into account when setting the
-	 * i_nblocks
-	 */
-	ip->i_blocks = LBLK2PBLK(ip->i_sb, xlen +
-				 ((JFS_IP(ip)->ea.flag & DXD_EXTENT) ?
-				  lengthDXD(&JFS_IP(ip)->ea) : 0) +
-				 ((JFS_IP(ip)->acl.flag & DXD_EXTENT) ?
-				  lengthDXD(&JFS_IP(ip)->acl) : 0));
-
 	DT_PUTPAGE(pmp);
 	return 0;
 }
@@ -1900,6 +1908,12 @@
 
 	rp = rmp->data;
 
+	/* Allocate blocks to quota. */
+	if (DQUOT_ALLOC_BLOCK(ip, lengthPXD(pxd))) {
+		release_metapage(rmp);
+		return -EDQUOT;
+	}
+
 	BT_MARK_DIRTY(rmp, ip);
 	/*
 	 * acquire a transaction lock on the new right page
@@ -2042,7 +2056,6 @@
 
 	*rmpp = rmp;
 
-	ip->i_blocks += LBLK2PBLK(ip->i_sb, lengthPXD(pxd));
 	return 0;
 }
 
@@ -2265,7 +2278,9 @@
 	}
 
 	xlen = lengthPXD(&fp->header.self);
-	ip->i_blocks -= LBLK2PBLK(ip->i_sb, xlen);
+
+	/* Free quota allocation. */
+	DQUOT_FREE_BLOCK(ip, xlen);
 
 	/* free/invalidate its buffer page */
 	discard_metapage(fmp);
@@ -2339,7 +2354,9 @@
 				}
 
 				xlen = lengthPXD(&p->header.self);
-				ip->i_blocks -= LBLK2PBLK(ip->i_sb, xlen);
+
+				/* Free quota allocation */
+				DQUOT_FREE_BLOCK(ip, xlen);
 
 				/* free/invalidate its buffer page */
 				discard_metapage(mp);
@@ -2876,14 +2893,6 @@
 
 	/* init '..' entry */
 	p->header.idotdot = cpu_to_le32(idotdot);
-
-#if 0
-	ip->i_blocks = LBLK2PBLK(ip->i_sb,
-				 ((jfs_ip->ea.flag & DXD_EXTENT) ?
-				  lengthDXD(&jfs_ip->ea) : 0) +
-				 ((jfs_ip->acl.flag & DXD_EXTENT) ?
-				  lengthDXD(&jfs_ip->acl) : 0));
-#endif
 
 	return;
 }
diff -Nru a/fs/jfs/jfs_extent.c b/fs/jfs/jfs_extent.c
--- a/fs/jfs/jfs_extent.c	2004-10-18 14:56:32 -07:00
+++ b/fs/jfs/jfs_extent.c	2004-10-18 14:56:32 -07:00
@@ -1,5 +1,5 @@
 /*
- *   Copyright (C) International Business Machines Corp., 2000-2003
+ *   Copyright (C) International Business Machines Corp., 2000-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
@@ -17,6 +17,7 @@
  */
 
 #include <linux/fs.h>
+#include <linux/quotaops.h>
 #include "jfs_incore.h"
 #include "jfs_superblock.h"
 #include "jfs_dmap.h"
@@ -144,6 +145,13 @@
 		return (rc);
 	}
 
+	/* Allocate blocks to quota. */
+	if (DQUOT_ALLOC_BLOCK(ip, nxlen)) {
+		dbFree(ip, nxaddr, (s64) nxlen);
+		up(&JFS_IP(ip)->commit_sem);
+		return -EDQUOT;
+	}
+
 	/* determine the value of the extent flag */
 	xflag = (abnr == TRUE) ? XAD_NOTRECORDED : 0;
 
@@ -161,13 +169,11 @@
 	 */
 	if (rc) {
 		dbFree(ip, nxaddr, nxlen);
+		DQUOT_FREE_BLOCK(ip, nxlen);
 		up(&JFS_IP(ip)->commit_sem);
 		return (rc);
 	}
 
-	/* update the number of blocks allocated to the file */
-	ip->i_blocks += LBLK2PBLK(ip->i_sb, nxlen);
-
 	/* set the results of the extent allocation */
 	XADaddress(xp, nxaddr);
 	XADlength(xp, nxlen);
@@ -254,6 +260,13 @@
 	if ((rc = extBrealloc(ip, xaddr, xlen, &nxlen, &nxaddr)))
 		goto exit;
 
+	/* Allocat blocks to quota. */
+	if (DQUOT_ALLOC_BLOCK(ip, nxlen)) {
+		dbFree(ip, nxaddr, (s64) nxlen);
+		up(&JFS_IP(ip)->commit_sem);
+		return -EDQUOT;
+	}
+
 	delta = nxlen - xlen;
 
 	/* check if the extend page is not abnr but the request is abnr
@@ -289,6 +302,7 @@
 		/* extend the extent */
 		if ((rc = xtExtend(0, ip, xoff + xlen, (int) nextend, 0))) {
 			dbFree(ip, xaddr + xlen, delta);
+			DQUOT_FREE_BLOCK(ip, nxlen);
 			goto exit;
 		}
 	} else {
@@ -299,6 +313,7 @@
 		 */
 		if ((rc = xtTailgate(0, ip, xoff, (int) ntail, nxaddr, 0))) {
 			dbFree(ip, nxaddr, nxlen);
+			DQUOT_FREE_BLOCK(ip, nxlen);
 			goto exit;
 		}
 	}
@@ -319,9 +334,6 @@
 			xflag = 0;
 		}
 	}
-
-	/* update the inode with the number of blocks allocated */
-	ip->i_blocks += LBLK2PBLK(sb, delta);
 
 	/* set the return results */
 	XADaddress(xp, nxaddr);
diff -Nru a/fs/jfs/jfs_imap.c b/fs/jfs/jfs_imap.c
--- a/fs/jfs/jfs_imap.c	2004-10-18 14:56:13 -07:00
+++ b/fs/jfs/jfs_imap.c	2004-10-18 14:56:13 -07:00
@@ -1,5 +1,5 @@
 /*
- *   Copyright (C) International Business Machines Corp., 2000-2003
+ *   Copyright (C) International Business Machines Corp., 2000-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
@@ -44,6 +44,7 @@
 #include <linux/fs.h>
 #include <linux/buffer_head.h>
 #include <linux/pagemap.h>
+#include <linux/quotaops.h>
 
 #include "jfs_incore.h"
 #include "jfs_filsys.h"
@@ -504,6 +505,9 @@
 	ip->i_mapping->a_ops = &jfs_aops;
 	mapping_set_gfp_mask(ip->i_mapping, GFP_NOFS);
 
+	/* Allocations to metadata inodes should not affect quotas */
+	ip->i_flags |= S_NOQUOTA;
+
 	if ((inum == FILESYSTEM_I) && (JFS_IP(ip)->ipimap == sbi->ipaimap)) {
 		sbi->gengen = le32_to_cpu(dp->di_gengen);
 		sbi->inostamp = le32_to_cpu(dp->di_inostamp);
@@ -2601,28 +2605,11 @@
 			iagp->inosmap[i] = ONES;
 
 		flush_metapage(mp);
-#ifdef _STILL_TO_PORT
-		/* synchronously write the iag page */
-		if (bmWrite(bp)) {
-			/* Free the blocks allocated for the iag since it was
-			 * not successfully added to the inode map
-			 */
-			dbFree(ipimap, xaddr, (s64) xlen);
-
-			/* release the inode map lock */
-			IWRITE_UNLOCK(ipimap);
-
-			rc = -EIO;
-			goto out;
-		}
-
-		/* Now the iag is on disk */
 
 		/*
 		 * start tyransaction of update of the inode map
 		 * addressing structure pointing to the new iag page;
 		 */
-#endif				/*  _STILL_TO_PORT */
 		tid = txBegin(sb, COMMIT_FORCE);
 		down(&JFS_IP(ipimap)->commit_sem);
 
@@ -2644,7 +2631,7 @@
 
 		/* update the inode map's inode to reflect the extension */
 		ipimap->i_size += PSIZE;
-		ipimap->i_blocks += LBLK2PBLK(sb, xlen);
+		inode_add_bytes(ipimap, PSIZE);
 
 		/*
 		 * txCommit(COMMIT_FORCE) will synchronously write address 
@@ -3085,7 +3072,7 @@
 	}
 	/* update the inode map's inode to reflect the extension */
 	ip->i_size += PSIZE;
-	ip->i_blocks += LBLK2PBLK(sb, xlen);
+	inode_add_bytes(ip, PSIZE);
 	txCommit(tid, 1, &ip, COMMIT_FORCE);
       cleanup:
 	txEnd(tid);
diff -Nru a/fs/jfs/jfs_inode.c b/fs/jfs/jfs_inode.c
--- a/fs/jfs/jfs_inode.c	2004-10-18 14:55:54 -07:00
+++ b/fs/jfs/jfs_inode.c	2004-10-18 14:55:54 -07:00
@@ -1,5 +1,5 @@
 /*
- *   Copyright (c) International Business Machines Corp., 2000-2002
+ *   Copyright (C) International Business Machines Corp., 2000-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
@@ -17,6 +17,7 @@
  */
 
 #include <linux/fs.h>
+#include <linux/quotaops.h>
 #include "jfs_incore.h"
 #include "jfs_filsys.h"
 #include "jfs_imap.h"
@@ -59,6 +60,17 @@
 			mode |= S_ISGID;
 	} else
 		inode->i_gid = current->fsgid;
+
+	/*
+	 * Allocate inode to quota.
+	 */
+	if (DQUOT_ALLOC_INODE(inode)) {
+		DQUOT_DROP(inode);
+		inode->i_flags |= S_NOQUOTA;
+		inode->i_nlink = 0;
+		iput(inode);
+		return NULL;
+	}
 
 	inode->i_mode = mode;
 	if (S_ISDIR(mode))
diff -Nru a/fs/jfs/jfs_metapage.c b/fs/jfs/jfs_metapage.c
--- a/fs/jfs/jfs_metapage.c	2004-10-18 14:56:21 -07:00
+++ b/fs/jfs/jfs_metapage.c	2004-10-18 14:56:21 -07:00
@@ -557,6 +557,7 @@
 			if (page) {
 				block_invalidatepage(page, 0);
 				unlock_page(page);
+				page_cache_release(page);
 			}
 		}
 	}
diff -Nru a/fs/jfs/jfs_mount.c b/fs/jfs/jfs_mount.c
--- a/fs/jfs/jfs_mount.c	2004-10-18 14:56:27 -07:00
+++ b/fs/jfs/jfs_mount.c	2004-10-18 14:56:27 -07:00
@@ -197,9 +197,6 @@
 	/*
 	 *      unwind on error
 	 */
-//errout42: /* close fileset inode allocation map */
-	diUnmount(ipimap, 1);
-
       errout41:		/* close fileset inode allocation map inode */
 	diFreeSpecial(ipimap);
 
diff -Nru a/fs/jfs/jfs_txnmgr.c b/fs/jfs/jfs_txnmgr.c
--- a/fs/jfs/jfs_txnmgr.c	2004-10-18 14:56:33 -07:00
+++ b/fs/jfs/jfs_txnmgr.c	2004-10-18 14:56:33 -07:00
@@ -165,7 +165,6 @@
  * external references
  */
 extern int lmGroupCommit(struct jfs_log *, struct tblock *);
-extern void lmSync(struct jfs_log *);
 extern int jfs_commit_inode(struct inode *, int);
 extern int jfs_stop_threads;
 
@@ -2621,8 +2620,6 @@
 	struct metapage *mp;
 	struct tblock *tblk = tid_to_tblock(tid);
 	struct tlock *tlck;
-
-	jfs_warn("txAbort: tid:%d dirty:0x%x", tid, dirty);
 
 	/*
 	 * free tlocks of the transaction
diff -Nru a/fs/jfs/jfs_xtree.c b/fs/jfs/jfs_xtree.c
--- a/fs/jfs/jfs_xtree.c	2004-10-18 14:56:31 -07:00
+++ b/fs/jfs/jfs_xtree.c	2004-10-18 14:56:31 -07:00
@@ -1,5 +1,5 @@
 /*
- *   Copyright (C) International Business Machines Corp., 2000-2003
+ *   Copyright (C) International Business Machines Corp., 2000-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
@@ -20,6 +20,7 @@
  */
 
 #include <linux/fs.h>
+#include <linux/quotaops.h>
 #include "jfs_incore.h"
 #include "jfs_filsys.h"
 #include "jfs_metapage.h"
@@ -829,8 +830,12 @@
 			hint = addressXAD(xad) + lengthXAD(xad) - 1;
 		} else
 			hint = 0;
-		if ((rc = dbAlloc(ip, hint, (s64) xlen, &xaddr)))
+		if ((rc = DQUOT_ALLOC_BLOCK(ip, xlen)))
 			goto out;
+		if ((rc = dbAlloc(ip, hint, (s64) xlen, &xaddr))) {
+			DQUOT_FREE_BLOCK(ip, xlen);
+			goto out;
+		}
 	}
 
 	/*
@@ -855,8 +860,10 @@
 		split.pxdlist = NULL;
 		if ((rc = xtSplitUp(tid, ip, &split, &btstack))) {
 			/* undo data extent allocation */
-			if (*xaddrp == 0)
+			if (*xaddrp == 0) {
 				dbFree(ip, xaddr, (s64) xlen);
+				DQUOT_FREE_BLOCK(ip, xlen);
+			}
 			return rc;
 		}
 
@@ -1214,22 +1221,34 @@
 	pxd_t *pxd;
 	struct tlock *tlck;
 	struct xtlock *sxtlck = NULL, *rxtlck = NULL;
+	int quota_allocation = 0;
 
 	smp = split->mp;
 	sp = XT_PAGE(ip, smp);
 
 	INCREMENT(xtStat.split);
 
-	/*
-	 * allocate the new right page for the split
-	 */
 	pxdlist = split->pxdlist;
 	pxd = &pxdlist->pxd[pxdlist->npxd];
 	pxdlist->npxd++;
 	rbn = addressPXD(pxd);
+
+	/* Allocate blocks to quota. */
+       if (DQUOT_ALLOC_BLOCK(ip, lengthPXD(pxd))) {
+	       rc = -EDQUOT;
+	       goto clean_up;
+	}
+
+	quota_allocation += lengthPXD(pxd);
+
+	/*
+	 * allocate the new right page for the split
+	 */
 	rmp = get_metapage(ip, rbn, PSIZE, 1);
-	if (rmp == NULL)
-		return -EIO;
+	if (rmp == NULL) {
+		rc = -EIO;
+		goto clean_up;
+	}
 
 	jfs_info("xtSplitPage: ip:0x%p smp:0x%p rmp:0x%p", ip, smp, rmp);
 
@@ -1304,8 +1323,6 @@
 		*rmpp = rmp;
 		*rbnp = rbn;
 
-		ip->i_blocks += LBLK2PBLK(ip->i_sb, lengthPXD(pxd));
-
 		jfs_info("xtSplitPage: sp:0x%p rp:0x%p", sp, rp);
 		return 0;
 	}
@@ -1321,7 +1338,7 @@
 		XT_GETPAGE(ip, nextbn, mp, PSIZE, p, rc);
 		if (rc) {
 			XT_PUTPAGE(rmp);
-			return rc;
+			goto clean_up;
 		}
 
 		BT_MARK_DIRTY(mp, ip);
@@ -1420,10 +1437,16 @@
 	*rmpp = rmp;
 	*rbnp = rbn;
 
-	ip->i_blocks += LBLK2PBLK(ip->i_sb, lengthPXD(pxd));
-
 	jfs_info("xtSplitPage: sp:0x%p rp:0x%p", sp, rp);
 	return rc;
+
+      clean_up:
+
+	/* Rollback quota allocation. */
+	if (quota_allocation)
+		DQUOT_FREE_BLOCK(ip, quota_allocation);
+
+	return (rc);
 }
 
 
@@ -1478,6 +1501,12 @@
 	if (rmp == NULL)
 		return -EIO;
 
+	/* Allocate blocks to quota. */
+	if (DQUOT_ALLOC_BLOCK(ip, lengthPXD(pxd))) {
+		release_metapage(rmp);
+		return -EDQUOT;
+	}
+
 	jfs_info("xtSplitRoot: ip:0x%p rmp:0x%p", ip, rmp);
 
 	/*
@@ -1561,8 +1590,6 @@
 
 	*rmpp = rmp;
 
-	ip->i_blocks += LBLK2PBLK(ip->i_sb, lengthPXD(pxd));
-
 	jfs_info("xtSplitRoot: sp:0x%p rp:0x%p", sp, rp);
 	return 0;
 }
@@ -3909,8 +3936,8 @@
 	else
 		ip->i_size = newsize;
 
-	/* update nblocks to reflect freed blocks */
-	ip->i_blocks -= LBLK2PBLK(ip->i_sb, nfreed);
+	/* update quota allocation to reflect freed blocks */
+	DQUOT_FREE_BLOCK(ip, nfreed);
 
 	/*
 	 * free tlock of invalidated pages
diff -Nru a/fs/jfs/namei.c b/fs/jfs/namei.c
--- a/fs/jfs/namei.c	2004-10-18 14:56:49 -07:00
+++ b/fs/jfs/namei.c	2004-10-18 14:56:49 -07:00
@@ -19,6 +19,7 @@
 
 #include <linux/fs.h>
 #include <linux/ctype.h>
+#include <linux/quotaops.h>
 #include "jfs_incore.h"
 #include "jfs_superblock.h"
 #include "jfs_inode.h"
@@ -123,10 +124,10 @@
 	 */
 	ino = ip->i_ino;
 	if ((rc = dtInsert(tid, dip, &dname, &ino, &btstack))) {
-		jfs_err("jfs_create: dtInsert returned %d", rc);
-		if (rc == -EIO)
+		if (rc == -EIO) {
+			jfs_err("jfs_create: dtInsert returned -EIO");
 			txAbort(tid, 1);	/* Marks Filesystem dirty */
-		else
+		} else
 			txAbort(tid, 0);	/* Filesystem full */
 		goto out3;
 	}
@@ -250,11 +251,10 @@
 	 */
 	ino = ip->i_ino;
 	if ((rc = dtInsert(tid, dip, &dname, &ino, &btstack))) {
-		jfs_err("jfs_mkdir: dtInsert returned %d", rc);
-
-		if (rc == -EIO)
+		if (rc == -EIO) {
+			jfs_err("jfs_mkdir: dtInsert returned -EIO");
 			txAbort(tid, 1);	/* Marks Filesystem dirty */
-		else
+		} else
 			txAbort(tid, 0);	/* Filesystem full */
 		goto out3;
 	}
@@ -330,6 +330,9 @@
 
 	jfs_info("jfs_rmdir: dip:0x%p name:%s", dip, dentry->d_name.name);
 
+	/* Init inode for quota operations. */
+	DQUOT_INIT(ip);
+
 	/* directory must be empty to be removed */
 	if (!dtEmpty(ip)) {
 		rc = -ENOTEMPTY;
@@ -455,6 +458,9 @@
 
 	jfs_info("jfs_unlink: dip:0x%p name:%s", dip, dentry->d_name.name);
 
+	/* Init inode for quota operations. */
+	DQUOT_INIT(ip);
+
 	if ((rc = get_UCSname(&dname, dentry)))
 		goto out;
 
@@ -813,7 +819,10 @@
 	iplist[1] = dir;
 	rc = txCommit(tid, 2, &iplist[0], 0);
 
-	if (!rc)
+	if (rc) {
+		ip->i_nlink--;
+		iput(ip);
+	} else
 		d_instantiate(dentry, ip);
 
       free_dname:
@@ -964,7 +973,7 @@
 			mp = get_metapage(ip, xaddr, PSIZE, 1);
 
 			if (mp == NULL) {
-				dbFree(ip, extent, xlen);
+				xtTruncate(tid, ip, 0, COMMIT_PWMAP);
 				rc = -EIO;
 				txAbort(tid, 0);
 				goto out3;
@@ -975,7 +984,6 @@
 			name += copy_size;
 			xaddr += JFS_SBI(sb)->nbperpage;
 		}
-		ip->i_blocks = LBLK2PBLK(sb, xlen);
 	}
 
 	/*
@@ -988,7 +996,7 @@
 	}
 	if (rc) {
 		if (xlen)
-			dbFree(ip, extent, xlen);
+			xtTruncate(tid, ip, 0, COMMIT_PWMAP);
 		txAbort(tid, 0);
 		/* discard new inode */
 		goto out3;
@@ -1104,8 +1112,11 @@
 			rc = -EMLINK;
 			goto out3;
 		}
-	} else if (new_ip)
+	} else if (new_ip) {
 		IWRITE_LOCK(new_ip);
+		/* Init inode for quota operations. */
+		DQUOT_INIT(new_ip);
+	}
 
 	/*
 	 * The real work starts here
@@ -1174,8 +1185,8 @@
 		ino = old_ip->i_ino;
 		rc = dtInsert(tid, new_dir, &new_dname, &ino, &btstack);
 		if (rc) {
-			jfs_err("jfs_rename: dtInsert failed w/rc = %d",
-				rc);
+			if (rc == -EIO)
+				jfs_err("jfs_rename: dtInsert returned -EIO");
 			goto out4;
 		}
 		if (S_ISDIR(old_ip->i_mode))
diff -Nru a/fs/jfs/resize.c b/fs/jfs/resize.c
--- a/fs/jfs/resize.c	2004-10-18 14:56:33 -07:00
+++ b/fs/jfs/resize.c	2004-10-18 14:56:33 -07:00
@@ -1,5 +1,5 @@
 /*
- *   Copyright (C) International Business Machines  Corp., 2000-2003
+ *   Copyright (C) International Business Machines  Corp., 2000-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
@@ -18,6 +18,7 @@
 
 #include <linux/fs.h>
 #include <linux/buffer_head.h>
+#include <linux/quotaops.h>
 #include "jfs_incore.h"
 #include "jfs_filsys.h"
 #include "jfs_metapage.h"
@@ -390,7 +391,7 @@
 	}
 	/* update bmap file size */
 	ipbmap->i_size += xlen << sbi->l2bsize;
-	ipbmap->i_blocks += LBLK2PBLK(sb, xlen);
+	inode_add_bytes(ipbmap, xlen << sbi->l2bsize);
 
 	iplist[0] = ipbmap;
 	rc = txCommit(tid, 1, &iplist[0], COMMIT_FORCE);
diff -Nru a/fs/jfs/super.c b/fs/jfs/super.c
--- a/fs/jfs/super.c	2004-10-18 14:56:29 -07:00
+++ b/fs/jfs/super.c	2004-10-18 14:56:29 -07:00
@@ -58,7 +58,7 @@
 
 #ifdef CONFIG_JFS_DEBUG
 int jfsloglevel = JFS_LOGLEVEL_WARN;
-module_param(jfsloglevel, int, 644);
+module_param(jfsloglevel, int, 0644);
 MODULE_PARM_DESC(jfsloglevel, "Specify JFS loglevel (0, 1 or 2)");
 #endif
 
@@ -77,7 +77,7 @@
 extern void jfs_read_inode(struct inode *inode);
 extern void jfs_dirty_inode(struct inode *inode);
 extern void jfs_delete_inode(struct inode *inode);
-extern void jfs_write_inode(struct inode *inode, int wait);
+extern int jfs_write_inode(struct inode *inode, int wait);
 
 extern struct dentry *jfs_get_parent(struct dentry *dentry);
 extern int jfs_extendfs(struct super_block *, s64, int);
diff -Nru a/fs/jfs/xattr.c b/fs/jfs/xattr.c
--- a/fs/jfs/xattr.c	2004-10-18 14:56:28 -07:00
+++ b/fs/jfs/xattr.c	2004-10-18 14:56:28 -07:00
@@ -1,5 +1,5 @@
 /*
- *   Copyright (C) International Business Machines  Corp., 2000-2003
+ *   Copyright (C) International Business Machines  Corp., 2000-2004
  *   Copyright (C) Christoph Hellwig, 2002
  *
  *   This program is free software;  you can redistribute it and/or modify
@@ -19,6 +19,7 @@
 
 #include <linux/fs.h>
 #include <linux/xattr.h>
+#include <linux/quotaops.h>
 #include "jfs_incore.h"
 #include "jfs_superblock.h"
 #include "jfs_dmap.h"
@@ -251,9 +252,17 @@
 	/* figure out how many blocks we need */
 	nblocks = (size + (sb->s_blocksize - 1)) >> sb->s_blocksize_bits;
 
+	/* Allocate new blocks to quota. */
+	if (DQUOT_ALLOC_BLOCK(ip, nblocks)) {
+		return -EDQUOT;
+	}
+
 	rc = dbAlloc(ip, INOHINT(ip), nblocks, &blkno);
-	if (rc)
+	if (rc) {
+		/*Rollback quota allocation. */
+		DQUOT_FREE_BLOCK(ip, nblocks);
 		return rc;
+	}
 
 	/*
 	 * Now have nblocks worth of storage to stuff into the FEALIST.
@@ -315,6 +324,9 @@
 	return 0;
 
       failed:
+	/* Rollback quota allocation. */
+	DQUOT_FREE_BLOCK(ip, nblocks);
+
 	dbFree(ip, blkno, nblocks);
 	return rc;
 }
@@ -448,6 +460,7 @@
 	int blocks_needed, current_blocks;
 	s64 blkno;
 	int rc;
+	int quota_allocation = 0;
 
 	/* When fsck.jfs clears a bad ea, it doesn't clear the size */
 	if (ji->ea.flag == 0)
@@ -517,10 +530,16 @@
 	    sb->s_blocksize_bits;
 
 	if (blocks_needed > current_blocks) {
+		/* Allocate new blocks to quota. */
+		if (DQUOT_ALLOC_BLOCK(inode, blocks_needed))
+			return -EDQUOT;
+
+		quota_allocation = blocks_needed;
+
 		rc = dbAlloc(inode, INOHINT(inode), (s64) blocks_needed,
 			     &blkno);
 		if (rc)
-			return rc;
+			goto clean_up;
 
 		DXDlength(&ea_buf->new_ea, blocks_needed);
 		DXDaddress(&ea_buf->new_ea, blkno);
@@ -534,7 +553,8 @@
 					  1);
 		if (ea_buf->mp == NULL) {
 			dbFree(inode, blkno, (s64) blocks_needed);
-			return -EIO;
+			rc = -EIO;
+			goto clean_up;
 		}
 		ea_buf->xattr = ea_buf->mp->data;
 		ea_buf->max_size = (min_size + sb->s_blocksize - 1) &
@@ -544,7 +564,7 @@
 		if ((rc = ea_read(inode, ea_buf->xattr))) {
 			discard_metapage(ea_buf->mp);
 			dbFree(inode, blkno, (s64) blocks_needed);
-			return rc;
+			goto clean_up;
 		}
 		goto size_check;
 	}
@@ -552,8 +572,10 @@
 	ea_buf->mp = read_metapage(inode, addressDXD(&ji->ea),
 				   lengthDXD(&ji->ea) << sb->s_blocksize_bits,
 				   1);
-	if (ea_buf->mp == NULL)
-		return -EIO;
+	if (ea_buf->mp == NULL) {
+		rc = -EIO;
+		goto clean_up;
+	}
 	ea_buf->xattr = ea_buf->mp->data;
 	ea_buf->max_size = (ea_size + sb->s_blocksize - 1) &
 	    ~(sb->s_blocksize - 1);
@@ -563,10 +585,18 @@
 		printk(KERN_ERR "ea_get: invalid extended attribute\n");
 		dump_mem("xattr", ea_buf->xattr, ea_size);
 		ea_release(inode, ea_buf);
-		return -EIO;
+		rc = -EIO;
+		goto clean_up;
 	}
 
 	return ea_size;
+
+      clean_up:
+	/* Rollback quota allocation */
+	if (quota_allocation)
+		DQUOT_FREE_BLOCK(inode, quota_allocation);
+
+	return (rc);
 }
 
 static void ea_release(struct inode *inode, struct ea_buffer *ea_buf)
@@ -640,7 +670,10 @@
 		ji->ea.size = 0;
 	}
 
-	inode->i_blocks += LBLK2PBLK(inode->i_sb, new_blocks - old_blocks);
+	/* If old blocks exist, they must be removed from quota allocation. */
+	if (old_blocks)
+		DQUOT_FREE_BLOCK(inode, old_blocks);
+
 	inode->i_ctime = CURRENT_TIME;
 	rc = txCommit(tid, 1, &inode, 0);
 	txEnd(tid);
diff -Nru a/fs/libfs.c b/fs/libfs.c
--- a/fs/libfs.c	2004-10-18 14:55:54 -07:00
+++ b/fs/libfs.c	2004-10-18 14:55:54 -07:00
@@ -27,14 +27,27 @@
 }
 
 /*
- * Lookup the data. This is trivial - if the dentry didn't already
- * exist, we know it is negative.
+ * Retaining negative dentries for an in-memory filesystem just wastes
+ * memory and lookup time: arrange for them to be deleted immediately.
  */
+static int simple_delete_dentry(struct dentry *dentry)
+{
+	return 1;
+}
 
+/*
+ * Lookup the data. This is trivial - if the dentry didn't already
+ * exist, we know it is negative.  Set d_op to delete negative dentries.
+ */
 struct dentry *simple_lookup(struct inode *dir, struct dentry *dentry, struct nameidata *nd)
 {
+	static struct dentry_operations simple_dentry_operations = {
+		.d_delete = simple_delete_dentry,
+	};
+
 	if (dentry->d_name.len > NAME_MAX)
 		return ERR_PTR(-ENAMETOOLONG);
+	dentry->d_op = &simple_dentry_operations;
 	d_add(dentry, NULL);
 	return NULL;
 }
@@ -456,6 +469,58 @@
 	return count;
 }
 
+/*
+ * Transaction based IO.
+ * The file expects a single write which triggers the transaction, and then
+ * possibly a read which collects the result - which is stored in a
+ * file-local buffer.
+ */
+char *simple_transaction_get(struct file *file, const char __user *buf, size_t size)
+{
+	struct simple_transaction_argresp *ar;
+	static spinlock_t simple_transaction_lock = SPIN_LOCK_UNLOCKED;
+
+	if (size > SIMPLE_TRANSACTION_LIMIT - 1)
+		return ERR_PTR(-EFBIG);
+
+	ar = (struct simple_transaction_argresp *)get_zeroed_page(GFP_KERNEL);
+	if (!ar)
+		return ERR_PTR(-ENOMEM);
+
+	spin_lock(&simple_transaction_lock);
+
+	/* only one write allowed per open */
+	if (file->private_data) {
+		spin_unlock(&simple_transaction_lock);
+		free_page((unsigned long)ar);
+		return ERR_PTR(-EBUSY);
+	}
+
+	file->private_data = ar;
+
+	spin_unlock(&simple_transaction_lock);
+
+	if (copy_from_user(ar->data, buf, size))
+		return ERR_PTR(-EFAULT);
+
+	return ar->data;
+}
+
+ssize_t simple_transaction_read(struct file *file, char __user *buf, size_t size, loff_t *pos)
+{
+	struct simple_transaction_argresp *ar = file->private_data;
+
+	if (!ar)
+		return 0;
+	return simple_read_from_buffer(buf, size, pos, ar->data, ar->size);
+}
+
+int simple_transaction_release(struct inode *inode, struct file *file)
+{
+	free_page((unsigned long)file->private_data);
+	return 0;
+}
+
 EXPORT_SYMBOL(dcache_dir_close);
 EXPORT_SYMBOL(dcache_dir_lseek);
 EXPORT_SYMBOL(dcache_dir_open);
@@ -479,3 +544,6 @@
 EXPORT_SYMBOL(simple_sync_file);
 EXPORT_SYMBOL(simple_unlink);
 EXPORT_SYMBOL(simple_read_from_buffer);
+EXPORT_SYMBOL(simple_transaction_get);
+EXPORT_SYMBOL(simple_transaction_read);
+EXPORT_SYMBOL(simple_transaction_release);
diff -Nru a/fs/lockd/clntlock.c b/fs/lockd/clntlock.c
--- a/fs/lockd/clntlock.c	2004-10-18 14:57:04 -07:00
+++ b/fs/lockd/clntlock.c	2004-10-18 14:57:04 -07:00
@@ -146,7 +146,7 @@
 		inode = fl->fl_file->f_dentry->d_inode;
 		if (inode->i_sb->s_magic != NFS_SUPER_MAGIC)
 			continue;
-		if (fl->fl_u.nfs_fl.host != host)
+		if (fl->fl_u.nfs_fl.owner->host != host)
 			continue;
 		if (!(fl->fl_u.nfs_fl.flags & NFS_LCK_GRANTED))
 			continue;
@@ -215,7 +215,7 @@
 		inode = fl->fl_file->f_dentry->d_inode;
 		if (inode->i_sb->s_magic != NFS_SUPER_MAGIC)
 			continue;
-		if (fl->fl_u.nfs_fl.host != host)
+		if (fl->fl_u.nfs_fl.owner->host != host)
 			continue;
 		if (!(fl->fl_u.nfs_fl.flags & NFS_LCK_RECLAIM))
 			continue;
diff -Nru a/fs/lockd/clntproc.c b/fs/lockd/clntproc.c
--- a/fs/lockd/clntproc.c	2004-10-18 14:55:54 -07:00
+++ b/fs/lockd/clntproc.c	2004-10-18 14:55:54 -07:00
@@ -27,6 +27,7 @@
 static void	nlmclnt_unlock_callback(struct rpc_task *);
 static void	nlmclnt_cancel_callback(struct rpc_task *);
 static int	nlm_stat_to_errno(u32 stat);
+static void	nlmclnt_locks_init_private(struct file_lock *fl, struct nlm_host *host);
 
 /*
  * Cookie counter for NLM requests
@@ -41,11 +42,83 @@
 	nlm_cookie++;
 }
 
+static struct nlm_lockowner *nlm_get_lockowner(struct nlm_lockowner *lockowner)
+{
+	atomic_inc(&lockowner->count);
+	return lockowner;
+}
+
+static void nlm_put_lockowner(struct nlm_lockowner *lockowner)
+{
+	if (!atomic_dec_and_lock(&lockowner->count, &lockowner->host->h_lock))
+		return;
+	list_del(&lockowner->list);
+	spin_unlock(&lockowner->host->h_lock);
+	nlm_release_host(lockowner->host);
+	kfree(lockowner);
+}
+
+static inline int nlm_pidbusy(struct nlm_host *host, uint32_t pid)
+{
+	struct nlm_lockowner *lockowner;
+	list_for_each_entry(lockowner, &host->h_lockowners, list) {
+		if (lockowner->pid == pid)
+			return -EBUSY;
+	}
+	return 0;
+}
+
+static inline uint32_t __nlm_alloc_pid(struct nlm_host *host)
+{
+	uint32_t res;
+	do {
+		res = host->h_pidcount++;
+	} while (nlm_pidbusy(host, res) < 0);
+	return res;
+}
+
+static struct nlm_lockowner *__nlm_find_lockowner(struct nlm_host *host, fl_owner_t owner)
+{
+	struct nlm_lockowner *lockowner;
+	list_for_each_entry(lockowner, &host->h_lockowners, list) {
+		if (lockowner->owner != owner)
+			continue;
+		return nlm_get_lockowner(lockowner);
+	}
+	return NULL;
+}
+
+static struct nlm_lockowner *nlm_find_lockowner(struct nlm_host *host, fl_owner_t owner)
+{
+	struct nlm_lockowner *res, *new = NULL;
+
+	spin_lock(&host->h_lock);
+	res = __nlm_find_lockowner(host, owner);
+	if (res == NULL) {
+		spin_unlock(&host->h_lock);
+		new = (struct nlm_lockowner *)kmalloc(sizeof(*new), GFP_KERNEL);
+		spin_lock(&host->h_lock);
+		res = __nlm_find_lockowner(host, owner);
+		if (res == NULL && new != NULL) {
+			res = new;
+			atomic_set(&new->count, 1);
+			new->owner = owner;
+			new->pid = __nlm_alloc_pid(host);
+			new->host = nlm_get_host(host);
+			list_add(&new->list, &host->h_lockowners);
+			new = NULL;
+		}
+	}
+	spin_unlock(&host->h_lock);
+	if (new != NULL)
+		kfree(new);
+	return res;
+}
+
 /*
  * Initialize arguments for TEST/LOCK/UNLOCK/CANCEL calls
  */
-static inline void
-nlmclnt_setlockargs(struct nlm_rqst *req, struct file_lock *fl)
+static void nlmclnt_setlockargs(struct nlm_rqst *req, struct file_lock *fl)
 {
 	struct nlm_args	*argp = &req->a_args;
 	struct nlm_lock	*lock = &argp->lock;
@@ -60,6 +133,14 @@
 	locks_copy_lock(&lock->fl, fl);
 }
 
+static void nlmclnt_release_lockargs(struct nlm_rqst *req)
+{
+	struct file_lock *fl = &req->a_args.lock.fl;
+
+	if (fl->fl_ops && fl->fl_ops->fl_release_private)
+		fl->fl_ops->fl_release_private(fl);
+}
+
 /*
  * Initialize arguments for GRANTED call. The nlm_rqst structure
  * has been cleared already.
@@ -77,8 +158,10 @@
 
 	if (lock->oh.len > NLMCLNT_OHSIZE) {
 		void *data = kmalloc(lock->oh.len, GFP_KERNEL);
-		if (!data)
+		if (!data) {
+			nlmclnt_freegrantargs(call);
 			return 0;
+		}
 		call->a_args.lock.oh.data = (u8 *) data;
 	}
 
@@ -89,12 +172,15 @@
 void
 nlmclnt_freegrantargs(struct nlm_rqst *call)
 {
+	struct file_lock *fl = &call->a_args.lock.fl;
 	/*
 	 * Check whether we allocated memory for the owner.
 	 */
 	if (call->a_args.lock.oh.data != (u8 *) call->a_owner) {
 		kfree(call->a_args.lock.oh.data);
 	}
+	if (fl->fl_ops && fl->fl_ops->fl_release_private)
+		fl->fl_ops->fl_release_private(fl);
 }
 
 /*
@@ -165,6 +251,8 @@
 	}
 	call->a_host = host;
 
+	nlmclnt_locks_init_private(fl, host);
+
 	/* Set up the argument struct */
 	nlmclnt_setlockargs(call, fl);
 
@@ -179,9 +267,6 @@
 	else
 		status = -EINVAL;
 
-	if (status < 0 && (call->a_flags & RPC_TASK_ASYNC))
-		kfree(call);
-
  out_restore:
 	spin_lock_irqsave(&current->sighand->siglock, flags);
 	current->blocked = oldset;
@@ -382,7 +467,9 @@
 {
 	int	status;
 
-	if ((status = nlmclnt_call(req, NLMPROC_TEST)) < 0)
+	status = nlmclnt_call(req, NLMPROC_TEST);
+	nlmclnt_release_lockargs(req);
+	if (status < 0)
 		return status;
 
 	status = req->a_res.status;
@@ -391,10 +478,9 @@
 	} if (status == NLM_LCK_DENIED) {
 		/*
 		 * Report the conflicting lock back to the application.
-		 * FIXME: Is it OK to report the pid back as well?
 		 */
 		locks_copy_lock(fl, &req->a_res.lock.fl);
-		/* fl->fl_pid = 0; */
+		fl->fl_pid = 0;
 	} else {
 		return nlm_stat_to_errno(req->a_res.status);
 	}
@@ -402,18 +488,30 @@
 	return 0;
 }
 
-static
-void nlmclnt_insert_lock_callback(struct file_lock *fl)
+static void nlmclnt_locks_copy_lock(struct file_lock *new, struct file_lock *fl)
 {
-	nlm_get_host(fl->fl_u.nfs_fl.host);
+	memcpy(&new->fl_u.nfs_fl, &fl->fl_u.nfs_fl, sizeof(new->fl_u.nfs_fl));
+	nlm_get_lockowner(new->fl_u.nfs_fl.owner);
 }
-static
-void nlmclnt_remove_lock_callback(struct file_lock *fl)
+
+static void nlmclnt_locks_release_private(struct file_lock *fl)
 {
-	if (fl->fl_u.nfs_fl.host) {
-		nlm_release_host(fl->fl_u.nfs_fl.host);
-		fl->fl_u.nfs_fl.host = NULL;
-	}
+	nlm_put_lockowner(fl->fl_u.nfs_fl.owner);
+	fl->fl_ops = NULL;
+}
+
+static struct file_lock_operations nlmclnt_lock_ops = {
+	.fl_copy_lock = nlmclnt_locks_copy_lock,
+	.fl_release_private = nlmclnt_locks_release_private,
+};
+
+static void nlmclnt_locks_init_private(struct file_lock *fl, struct nlm_host *host)
+{
+	BUG_ON(fl->fl_ops != NULL);
+	fl->fl_u.nfs_fl.state = 0;
+	fl->fl_u.nfs_fl.flags = 0;
+	fl->fl_u.nfs_fl.owner = nlm_find_lockowner(host, fl->fl_owner);
+	fl->fl_ops = &nlmclnt_lock_ops;
 }
 
 /*
@@ -446,7 +544,8 @@
 	if (!host->h_monitored && nsm_monitor(host) < 0) {
 		printk(KERN_NOTICE "lockd: failed to monitor %s\n",
 					host->h_name);
-		return -ENOLCK;
+		status = -ENOLCK;
+		goto out;
 	}
 
 	do {
@@ -456,18 +555,21 @@
 			status = nlmclnt_block(host, fl, &resp->status);
 		}
 		if (status < 0)
-			return status;
+			goto out;
 	} while (resp->status == NLM_LCK_BLOCKED && req->a_args.block);
 
 	if (resp->status == NLM_LCK_GRANTED) {
 		fl->fl_u.nfs_fl.state = host->h_state;
 		fl->fl_u.nfs_fl.flags |= NFS_LCK_GRANTED;
-		fl->fl_u.nfs_fl.host = host;
-		fl->fl_insert = nlmclnt_insert_lock_callback;
-		fl->fl_remove = nlmclnt_remove_lock_callback;
-	}
-
-	return nlm_stat_to_errno(resp->status);
+		fl->fl_flags |= FL_SLEEP;
+		if (posix_lock_file_wait(fl->fl_file, fl) < 0)
+				printk(KERN_WARNING "%s: VFS is out of sync with lock manager!\n",
+						__FUNCTION__);
+	}
+	status = nlm_stat_to_errno(resp->status);
+out:
+	nlmclnt_release_lockargs(req);
+	return status;
 }
 
 /*
@@ -527,13 +629,24 @@
 	fl->fl_u.nfs_fl.flags &= ~NFS_LCK_GRANTED;
 
 	if (req->a_flags & RPC_TASK_ASYNC) {
-		return nlmclnt_async_call(req, NLMPROC_UNLOCK,
+		status = nlmclnt_async_call(req, NLMPROC_UNLOCK,
 					nlmclnt_unlock_callback);
+		/* Hrmf... Do the unlock early since locks_remove_posix()
+		 * really expects us to free the lock synchronously */
+		posix_lock_file(fl->fl_file, fl);
+		if (status < 0) {
+			nlmclnt_release_lockargs(req);
+			kfree(req);
+		}
+		return status;
 	}
 
-	if ((status = nlmclnt_call(req, NLMPROC_UNLOCK)) < 0)
+	status = nlmclnt_call(req, NLMPROC_UNLOCK);
+	nlmclnt_release_lockargs(req);
+	if (status < 0)
 		return status;
 
+	posix_lock_file(fl->fl_file, fl);
 	if (resp->status == NLM_LCK_GRANTED)
 		return 0;
 
@@ -564,9 +677,9 @@
 	}
 	if (status != NLM_LCK_GRANTED)
 		printk(KERN_WARNING "lockd: unexpected unlock status: %d\n", status);
-
 die:
 	nlm_release_host(req->a_host);
+	nlmclnt_release_lockargs(req);
 	kfree(req);
 	return;
  retry_rebind:
@@ -605,8 +718,10 @@
 
 	status = nlmclnt_async_call(req, NLMPROC_CANCEL,
 					nlmclnt_cancel_callback);
-	if (status < 0)
+	if (status < 0) {
+		nlmclnt_release_lockargs(req);
 		kfree(req);
+	}
 
 	spin_lock_irqsave(&current->sighand->siglock, flags);
 	current->blocked = oldset;
@@ -648,6 +763,7 @@
 
 die:
 	nlm_release_host(req->a_host);
+	nlmclnt_release_lockargs(req);
 	kfree(req);
 	return;
 
diff -Nru a/fs/lockd/host.c b/fs/lockd/host.c
--- a/fs/lockd/host.c	2004-10-18 14:56:32 -07:00
+++ b/fs/lockd/host.c	2004-10-18 14:56:32 -07:00
@@ -119,13 +119,15 @@
 	init_MUTEX(&host->h_sema);
 	host->h_nextrebind = jiffies + NLM_HOST_REBIND;
 	host->h_expires    = jiffies + NLM_HOST_EXPIRE;
-	host->h_count      = 1;
+	atomic_set(&host->h_count, 1);
 	init_waitqueue_head(&host->h_gracewait);
 	host->h_state      = 0;			/* pseudo NSM state */
 	host->h_nsmstate   = 0;			/* real NSM state */
 	host->h_server	   = server;
 	host->h_next       = nlm_hosts[hash];
 	nlm_hosts[hash]    = host;
+	INIT_LIST_HEAD(&host->h_lockowners);
+	spin_lock_init(&host->h_lock);
 
 	if (++nrhosts > NLM_HOST_MAX)
 		next_gc = 0;
@@ -235,7 +237,7 @@
 {
 	if (host) {
 		dprintk("lockd: get host %s\n", host->h_name);
-		host->h_count ++;
+		atomic_inc(&host->h_count);
 		host->h_expires = jiffies + NLM_HOST_EXPIRE;
 	}
 	return host;
@@ -246,9 +248,10 @@
  */
 void nlm_release_host(struct nlm_host *host)
 {
-	if (host && host->h_count) {
+	if (host != NULL) {
 		dprintk("lockd: release host %s\n", host->h_name);
-		host->h_count --;
+		atomic_dec(&host->h_count);
+		BUG_ON(atomic_read(&host->h_count) < 0);
 	}
 }
 
@@ -283,7 +286,7 @@
 		for (i = 0; i < NLM_HOST_NRHASH; i++) {
 			for (host = nlm_hosts[i]; host; host = host->h_next) {
 				dprintk("       %s (cnt %d use %d exp %ld)\n",
-					host->h_name, host->h_count,
+					host->h_name, atomic_read(&host->h_count),
 					host->h_inuse, host->h_expires);
 			}
 		}
@@ -314,10 +317,10 @@
 	for (i = 0; i < NLM_HOST_NRHASH; i++) {
 		q = &nlm_hosts[i];
 		while ((host = *q) != NULL) {
-			if (host->h_count || host->h_inuse
+			if (atomic_read(&host->h_count) || host->h_inuse
 			 || time_before(jiffies, host->h_expires)) {
 				dprintk("nlm_gc_hosts skipping %s (cnt %d use %d exp %ld)\n",
-					host->h_name, host->h_count,
+					host->h_name, atomic_read(&host->h_count),
 					host->h_inuse, host->h_expires);
 				q = &host->h_next;
 				continue;
@@ -336,6 +339,7 @@
 					rpc_destroy_client(host->h_rpcclnt);
 				}
 			}
+			BUG_ON(!list_empty(&host->h_lockowners));
 			kfree(host);
 			nrhosts--;
 		}
diff -Nru a/fs/lockd/svc.c b/fs/lockd/svc.c
--- a/fs/lockd/svc.c	2004-10-18 14:56:33 -07:00
+++ b/fs/lockd/svc.c	2004-10-18 14:56:33 -07:00
@@ -409,13 +409,13 @@
 MODULE_LICENSE("GPL");
 
 module_param_call(nlm_grace_period, param_set_grace_period, param_get_ulong,
-		  &nlm_grace_period, 644);
+		  &nlm_grace_period, 0644);
 module_param_call(nlm_timeout, param_set_timeout, param_get_ulong,
-		  &nlm_timeout, 644);
+		  &nlm_timeout, 0644);
 module_param_call(nlm_udpport, param_set_port, param_get_int,
-		  &nlm_udpport, 644);
+		  &nlm_udpport, 0644);
 module_param_call(nlm_tcpport, param_set_port, param_get_int,
-		  &nlm_tcpport, 644);
+		  &nlm_tcpport, 0644);
 
 /*
  * Initialising and terminating the module.
diff -Nru a/fs/lockd/svc4proc.c b/fs/lockd/svc4proc.c
--- a/fs/lockd/svc4proc.c	2004-10-18 14:56:28 -07:00
+++ b/fs/lockd/svc4proc.c	2004-10-18 14:56:28 -07:00
@@ -53,8 +53,9 @@
 		*filp = file;
 
 		/* Set up the missing parts of the file_lock structure */
-		lock->fl.fl_file  = &file->f_file;
+		lock->fl.fl_file  = file->f_file;
 		lock->fl.fl_owner = (fl_owner_t) host;
+		lock->fl.fl_lmops = &nlmsvc_lock_operations;
 	}
 
 	return 0;
diff -Nru a/fs/lockd/svclock.c b/fs/lockd/svclock.c
--- a/fs/lockd/svclock.c	2004-10-18 14:56:27 -07:00
+++ b/fs/lockd/svclock.c	2004-10-18 14:56:27 -07:00
@@ -42,7 +42,6 @@
 static void	nlmsvc_insert_block(struct nlm_block *block, unsigned long);
 static int	nlmsvc_remove_block(struct nlm_block *block);
 static void	nlmsvc_grant_callback(struct rpc_task *task);
-static void	nlmsvc_notify_blocked(struct file_lock *);
 
 /*
  * The list of blocked locks to retry
@@ -193,7 +192,7 @@
 		goto failed_free;
 
 	/* Set notifier function for VFS, and init args */
-	block->b_call.a_args.lock.fl.fl_notify = nlmsvc_notify_blocked;
+	block->b_call.a_args.lock.fl.fl_lmops = &nlmsvc_lock_operations;
 	block->b_call.a_args.cookie = *cookie;	/* see above */
 
 	dprintk("lockd: created block %p...\n", block);
@@ -238,8 +237,13 @@
 
 	/* Remove block from list */
 	nlmsvc_remove_block(block);
-	posix_unblock_lock(&file->f_file, fl);
-	block->b_granted = 0;
+	if (fl->fl_next)
+		posix_unblock_lock(file->f_file, fl);
+	if (unlock) {
+		fl->fl_type = F_UNLCK;
+		posix_lock_file(file->f_file, fl);
+		block->b_granted = 0;
+	}
 
 	/* If the block is in the middle of a GRANT callback,
 	 * don't kill it yet. */
@@ -299,8 +303,8 @@
 	int			error;
 
 	dprintk("lockd: nlmsvc_lock(%s/%ld, ty=%d, pi=%d, %Ld-%Ld, bl=%d)\n",
-				file->f_file.f_dentry->d_inode->i_sb->s_id,
-				file->f_file.f_dentry->d_inode->i_ino,
+				file->f_file->f_dentry->d_inode->i_sb->s_id,
+				file->f_file->f_dentry->d_inode->i_ino,
 				lock->fl.fl_type, lock->fl.fl_pid,
 				(long long)lock->fl.fl_start,
 				(long long)lock->fl.fl_end,
@@ -316,8 +320,8 @@
 	/* Lock file against concurrent access */
 	down(&file->f_sema);
 
-	if (!(conflock = posix_test_lock(&file->f_file, &lock->fl))) {
-		error = posix_lock_file(&file->f_file, &lock->fl);
+	if (!(conflock = posix_test_lock(file->f_file, &lock->fl))) {
+		error = posix_lock_file(file->f_file, &lock->fl);
 
 		if (block)
 			nlmsvc_delete_block(block, 0);
@@ -382,13 +386,13 @@
 	struct file_lock	*fl;
 
 	dprintk("lockd: nlmsvc_testlock(%s/%ld, ty=%d, %Ld-%Ld)\n",
-				file->f_file.f_dentry->d_inode->i_sb->s_id,
-				file->f_file.f_dentry->d_inode->i_ino,
+				file->f_file->f_dentry->d_inode->i_sb->s_id,
+				file->f_file->f_dentry->d_inode->i_ino,
 				lock->fl.fl_type,
 				(long long)lock->fl.fl_start,
 				(long long)lock->fl.fl_end);
 
-	if ((fl = posix_test_lock(&file->f_file, &lock->fl)) != NULL) {
+	if ((fl = posix_test_lock(file->f_file, &lock->fl)) != NULL) {
 		dprintk("lockd: conflicting lock(ty=%d, %Ld-%Ld)\n",
 				fl->fl_type, (long long)fl->fl_start,
 				(long long)fl->fl_end);
@@ -414,8 +418,8 @@
 	int	error;
 
 	dprintk("lockd: nlmsvc_unlock(%s/%ld, pi=%d, %Ld-%Ld)\n",
-				file->f_file.f_dentry->d_inode->i_sb->s_id,
-				file->f_file.f_dentry->d_inode->i_ino,
+				file->f_file->f_dentry->d_inode->i_sb->s_id,
+				file->f_file->f_dentry->d_inode->i_ino,
 				lock->fl.fl_pid,
 				(long long)lock->fl.fl_start,
 				(long long)lock->fl.fl_end);
@@ -424,7 +428,7 @@
 	nlmsvc_cancel_blocked(file, lock);
 
 	lock->fl.fl_type = F_UNLCK;
-	error = posix_lock_file(&file->f_file, &lock->fl);
+	error = posix_lock_file(file->f_file, &lock->fl);
 
 	return (error < 0)? nlm_lck_denied_nolocks : nlm_granted;
 }
@@ -442,8 +446,8 @@
 	struct nlm_block	*block;
 
 	dprintk("lockd: nlmsvc_cancel(%s/%ld, pi=%d, %Ld-%Ld)\n",
-				file->f_file.f_dentry->d_inode->i_sb->s_id,
-				file->f_file.f_dentry->d_inode->i_ino,
+				file->f_file->f_dentry->d_inode->i_sb->s_id,
+				file->f_file->f_dentry->d_inode->i_ino,
 				lock->fl.fl_pid,
 				(long long)lock->fl.fl_start,
 				(long long)lock->fl.fl_end);
@@ -479,6 +483,16 @@
 	printk(KERN_WARNING "lockd: notification for unknown block!\n");
 }
 
+static int nlmsvc_same_owner(struct file_lock *fl1, struct file_lock *fl2)
+{
+	return fl1->fl_owner == fl2->fl_owner && fl1->fl_pid == fl2->fl_pid;
+}
+
+struct lock_manager_operations nlmsvc_lock_operations = {
+	.fl_compare_owner = nlmsvc_same_owner,
+	.fl_notify = nlmsvc_notify_blocked,
+};
+
 /*
  * Try to claim a lock that was previously blocked.
  *
@@ -515,7 +529,7 @@
 	}
 
 	/* Try the lock operation again */
-	if ((conflock = posix_test_lock(&file->f_file, &lock->fl)) != NULL) {
+	if ((conflock = posix_test_lock(file->f_file, &lock->fl)) != NULL) {
 		/* Bummer, we blocked again */
 		dprintk("lockd: lock still blocked\n");
 		nlmsvc_insert_block(block, NLM_NEVER);
@@ -528,7 +542,7 @@
 	 * following yields an error, this is most probably due to low
 	 * memory. Retry the lock in a few seconds.
 	 */
-	if ((error = posix_lock_file(&file->f_file, &lock->fl)) < 0) {
+	if ((error = posix_lock_file(file->f_file, &lock->fl)) < 0) {
 		printk(KERN_WARNING "lockd: unexpected error %d in %s!\n",
 				-error, __FUNCTION__);
 		nlmsvc_insert_block(block, 10 * HZ);
diff -Nru a/fs/lockd/svcproc.c b/fs/lockd/svcproc.c
--- a/fs/lockd/svcproc.c	2004-10-18 14:56:48 -07:00
+++ b/fs/lockd/svcproc.c	2004-10-18 14:56:48 -07:00
@@ -82,8 +82,9 @@
 		*filp = file;
 
 		/* Set up the missing parts of the file_lock structure */
-		lock->fl.fl_file  = &file->f_file;
+		lock->fl.fl_file  = file->f_file;
 		lock->fl.fl_owner = (fl_owner_t) host;
+		lock->fl.fl_lmops = &nlmsvc_lock_operations;
 	}
 
 	return 0;
diff -Nru a/fs/lockd/svcsubs.c b/fs/lockd/svcsubs.c
--- a/fs/lockd/svcsubs.c	2004-10-18 14:56:33 -07:00
+++ b/fs/lockd/svcsubs.c	2004-10-18 14:56:33 -07:00
@@ -67,7 +67,7 @@
 	down(&nlm_file_sema);
 
 	for (file = nlm_files[hash]; file; file = file->f_next)
-		if (!memcmp(&file->f_handle, f, sizeof(*f)))
+		if (!nfs_compare_fh(&file->f_handle, f))
 			goto found;
 
 	dprintk("lockd: creating file for (%08x %08x %08x %08x %08x %08x)\n",
@@ -124,7 +124,7 @@
 static inline void
 nlm_delete_file(struct nlm_file *file)
 {
-	struct inode *inode = file->f_file.f_dentry->d_inode;
+	struct inode *inode = file->f_file->f_dentry->d_inode;
 	struct nlm_file	**fp, *f;
 
 	dprintk("lockd: closing file %s/%ld\n",
@@ -133,7 +133,7 @@
 	while ((f = *fp) != NULL) {
 		if (f == file) {
 			*fp = file->f_next;
-			nlmsvc_ops->fclose(&file->f_file);
+			nlmsvc_ops->fclose(file->f_file);
 			kfree(file);
 			return;
 		}
@@ -176,7 +176,7 @@
 			lock.fl_type  = F_UNLCK;
 			lock.fl_start = 0;
 			lock.fl_end   = OFFSET_MAX;
-			if (posix_lock_file(&file->f_file, &lock) < 0) {
+			if (posix_lock_file(file->f_file, &lock) < 0) {
 				printk("lockd: unlock failure in %s:%d\n",
 						__FILE__, __LINE__);
 				return 1;
@@ -230,7 +230,7 @@
 			if (!file->f_blocks && !file->f_locks
 			 && !file->f_shares && !file->f_count) {
 				*fp = file->f_next;
-				nlmsvc_ops->fclose(&file->f_file);
+				nlmsvc_ops->fclose(file->f_file);
 				kfree(file);
 			} else {
 				fp = &file->f_next;
diff -Nru a/fs/locks.c b/fs/locks.c
--- a/fs/locks.c	2004-10-18 14:57:04 -07:00
+++ b/fs/locks.c	2004-10-18 14:57:04 -07:00
@@ -167,6 +167,13 @@
 	if (!list_empty(&fl->fl_link))
 		panic("Attempting to free lock on active lock list");
 
+	if (fl->fl_ops) {
+		if (fl->fl_ops->fl_release_private)
+			fl->fl_ops->fl_release_private(fl);
+		fl->fl_ops = NULL;
+	}
+	fl->fl_lmops = NULL;
+
 	kmem_cache_free(filelock_cache, fl);
 }
 
@@ -183,9 +190,8 @@
 	fl->fl_flags = 0;
 	fl->fl_type = 0;
 	fl->fl_start = fl->fl_end = 0;
-	fl->fl_notify = NULL;
-	fl->fl_insert = NULL;
-	fl->fl_remove = NULL;
+	fl->fl_ops = NULL;
+	fl->fl_lmops = NULL;
 }
 
 EXPORT_SYMBOL(locks_init_lock);
@@ -217,10 +223,10 @@
 	new->fl_type = fl->fl_type;
 	new->fl_start = fl->fl_start;
 	new->fl_end = fl->fl_end;
-	new->fl_notify = fl->fl_notify;
-	new->fl_insert = fl->fl_insert;
-	new->fl_remove = fl->fl_remove;
-	new->fl_u = fl->fl_u;
+	new->fl_ops = fl->fl_ops;
+	new->fl_lmops = fl->fl_lmops;
+	if (fl->fl_ops && fl->fl_ops->fl_copy_lock)
+		fl->fl_ops->fl_copy_lock(new, fl);
 }
 
 EXPORT_SYMBOL(locks_copy_lock);
@@ -321,9 +327,8 @@
 	fl->fl_pid = current->tgid;
 	fl->fl_file = filp;
 	fl->fl_flags = FL_POSIX;
-	fl->fl_notify = NULL;
-	fl->fl_insert = NULL;
-	fl->fl_remove = NULL;
+	fl->fl_ops = NULL;
+	fl->fl_lmops = NULL;
 
 	return assign_type(fl, l->l_type);
 }
@@ -361,9 +366,8 @@
 	fl->fl_pid = current->tgid;
 	fl->fl_file = filp;
 	fl->fl_flags = FL_POSIX;
-	fl->fl_notify = NULL;
-	fl->fl_insert = NULL;
-	fl->fl_remove = NULL;
+	fl->fl_ops = NULL;
+	fl->fl_lmops = NULL;
 
 	switch (l->l_type) {
 	case F_RDLCK:
@@ -397,9 +401,8 @@
 	}
 	fl->fl_start = 0;
 	fl->fl_end = OFFSET_MAX;
-	fl->fl_notify = NULL;
-	fl->fl_insert = NULL;
-	fl->fl_remove = NULL;
+	fl->fl_ops = NULL;
+	fl->fl_lmops = NULL;
 
 	*flp = fl;
 	return 0;
@@ -414,14 +417,15 @@
 }
 
 /*
- * Check whether two locks have the same owner.  The apparently superfluous
- * check for fl_pid enables us to distinguish between locks set by lockd.
+ * Check whether two locks have the same owner.
  */
 static inline int
 posix_same_owner(struct file_lock *fl1, struct file_lock *fl2)
 {
-	return (fl1->fl_owner == fl2->fl_owner) &&
-		(fl1->fl_pid == fl2->fl_pid);
+	if (fl1->fl_lmops && fl1->fl_lmops->fl_compare_owner)
+		return fl2->fl_lmops == fl1->fl_lmops &&
+			fl1->fl_lmops->fl_compare_owner(fl1, fl2);
+	return fl1->fl_owner == fl2->fl_owner;
 }
 
 /* Remove waiter from blocker's block list.
@@ -459,7 +463,8 @@
 	}
 	list_add_tail(&waiter->fl_block, &blocker->fl_block);
 	waiter->fl_next = blocker;
-	list_add(&waiter->fl_link, &blocked_list);
+	if (IS_POSIX(blocker))
+		list_add(&waiter->fl_link, &blocked_list);
 }
 
 /* Wake up processes blocked waiting for blocker.
@@ -472,8 +477,8 @@
 		struct file_lock *waiter = list_entry(blocker->fl_block.next,
 				struct file_lock, fl_block);
 		__locks_delete_block(waiter);
-		if (waiter->fl_notify)
-			waiter->fl_notify(waiter);
+		if (waiter->fl_lmops && waiter->fl_lmops->fl_notify)
+			waiter->fl_lmops->fl_notify(waiter);
 		else
 			wake_up(&waiter->fl_wait);
 	}
@@ -490,8 +495,8 @@
 	fl->fl_next = *pos;
 	*pos = fl;
 
-	if (fl->fl_insert)
-		fl->fl_insert(fl);
+	if (fl->fl_ops && fl->fl_ops->fl_insert)
+		fl->fl_ops->fl_insert(fl);
 }
 
 /*
@@ -514,8 +519,8 @@
 		fl->fl_fasync = NULL;
 	}
 
-	if (fl->fl_remove)
-		fl->fl_remove(fl);
+	if (fl->fl_ops && fl->fl_ops->fl_remove)
+		fl->fl_ops->fl_remove(fl);
 
 	locks_wake_up_blocks(fl);
 	locks_free_lock(fl);
@@ -631,24 +636,15 @@
 				struct file_lock *block_fl)
 {
 	struct list_head *tmp;
-	fl_owner_t caller_owner, blocked_owner;
-	unsigned int	 caller_pid, blocked_pid;
-
-	caller_owner = caller_fl->fl_owner;
-	caller_pid = caller_fl->fl_pid;
-	blocked_owner = block_fl->fl_owner;
-	blocked_pid = block_fl->fl_pid;
 
 next_task:
-	if (caller_owner == blocked_owner && caller_pid == blocked_pid)
+	if (posix_same_owner(caller_fl, block_fl))
 		return 1;
 	list_for_each(tmp, &blocked_list) {
 		struct file_lock *fl = list_entry(tmp, struct file_lock, fl_link);
-		if ((fl->fl_owner == blocked_owner)
-		    && (fl->fl_pid == blocked_pid)) {
+		if (posix_same_owner(fl, block_fl)) {
 			fl = fl->fl_next;
-			blocked_owner = fl->fl_owner;
-			blocked_pid = fl->fl_pid;
+			block_fl = fl;
 			goto next_task;
 		}
 	}
@@ -912,6 +908,34 @@
 }
 
 /**
+ * posix_lock_file_wait - Apply a POSIX-style lock to a file
+ * @filp: The file to apply the lock to
+ * @fl: The lock to be applied
+ *
+ * Add a POSIX style lock to a file.
+ * We merge adjacent & overlapping locks whenever possible.
+ * POSIX locks are sorted by owner task, then by starting address
+ */
+int posix_lock_file_wait(struct file *filp, struct file_lock *fl)
+{
+	int error;
+	might_sleep ();
+	for (;;) {
+		error = __posix_lock_file(filp->f_dentry->d_inode, fl);
+		if ((error != -EAGAIN) || !(fl->fl_flags & FL_SLEEP))
+			break;
+		error = wait_event_interruptible(fl->fl_wait, !fl->fl_next);
+		if (!error)
+			continue;
+
+		locks_delete_block(fl);
+		break;
+	}
+	return error;
+}
+EXPORT_SYMBOL(posix_lock_file_wait);
+
+/**
  * locks_mandatory_locked - Check for an active lock
  * @inode: the file to check
  *
@@ -1295,6 +1319,33 @@
 }
 
 /**
+ * flock_lock_file_wait - Apply a FLOCK-style lock to a file
+ * @filp: The file to apply the lock to
+ * @fl: The lock to be applied
+ *
+ * Add a FLOCK style lock to a file.
+ */
+int flock_lock_file_wait(struct file *filp, struct file_lock *fl)
+{
+	int error;
+	might_sleep();
+	for (;;) {
+		error = flock_lock_file(filp, fl);
+		if ((error != -EAGAIN) || !(fl->fl_flags & FL_SLEEP))
+			break;
+		error = wait_event_interruptible(fl->fl_wait, !fl->fl_next);
+		if (!error)
+			continue;
+
+		locks_delete_block(fl);
+		break;
+	}
+	return error;
+}
+
+EXPORT_SYMBOL(flock_lock_file_wait);
+
+/**
  *	sys_flock: - flock() system call.
  *	@fd: the file descriptor to lock.
  *	@cmd: the type of lock to apply.
@@ -1342,17 +1393,12 @@
 	if (error)
 		goto out_free;
 
-	for (;;) {
-		error = flock_lock_file(filp, lock);
-		if ((error != -EAGAIN) || !can_sleep)
-			break;
-		error = wait_event_interruptible(lock->fl_wait, !lock->fl_next);
-		if (!error)
-			continue;
-
-		locks_delete_block(lock);
-		break;
-	}
+	if (filp->f_op && filp->f_op->flock)
+		error = filp->f_op->flock(filp,
+					  (can_sleep) ? F_SETLKW : F_SETLK,
+					  lock);
+	else
+		error = flock_lock_file_wait(filp, lock);
 
  out_free:
 	if (list_empty(&lock->fl_link)) {
@@ -1422,7 +1468,6 @@
 	error = -EFAULT;
 	if (!copy_to_user(l, &flock, sizeof(flock)))
 		error = 0;
-  
 out:
 	return error;
 }
@@ -1489,8 +1534,7 @@
 
 	if (filp->f_op && filp->f_op->lock != NULL) {
 		error = filp->f_op->lock(filp, cmd, file_lock);
-		if (error < 0)
-			goto out;
+		goto out;
 	}
 
 	for (;;) {
@@ -1624,8 +1668,7 @@
 
 	if (filp->f_op && filp->f_op->lock != NULL) {
 		error = filp->f_op->lock(filp, cmd, file_lock);
-		if (error < 0)
-			goto out;
+		goto out;
 	}
 
 	for (;;) {
@@ -1672,10 +1715,12 @@
 	lock.fl_owner = owner;
 	lock.fl_pid = current->tgid;
 	lock.fl_file = filp;
+	lock.fl_ops = NULL;
+	lock.fl_lmops = NULL;
 
 	if (filp->f_op && filp->f_op->lock != NULL) {
 		filp->f_op->lock(filp, F_SETLK, &lock);
-		/* Ignore any error -- we must remove the locks anyway */
+		goto out;
 	}
 
 	/* Can't use posix_lock_file here; we need to remove it no matter
@@ -1684,13 +1729,16 @@
 	lock_kernel();
 	while (*before != NULL) {
 		struct file_lock *fl = *before;
-		if (IS_POSIX(fl) && (fl->fl_owner == owner)) {
+		if (IS_POSIX(fl) && posix_same_owner(fl, &lock)) {
 			locks_delete_lock(before);
 			continue;
 		}
 		before = &fl->fl_next;
 	}
 	unlock_kernel();
+out:
+	if (lock.fl_ops && lock.fl_ops->fl_release_private)
+		lock.fl_ops->fl_release_private(&lock);
 }
 
 EXPORT_SYMBOL(locks_remove_posix);
@@ -1707,12 +1755,23 @@
 	if (!inode->i_flock)
 		return;
 
+	if (filp->f_op && filp->f_op->flock) {
+		struct file_lock fl = { .fl_flags = FL_FLOCK,
+					.fl_type = F_UNLCK };
+		filp->f_op->flock(filp, F_SETLKW, &fl);
+	}
+
 	lock_kernel();
 	before = &inode->i_flock;
 
 	while ((fl = *before) != NULL) {
 		if (fl->fl_file == filp) {
-			if (IS_FLOCK(fl)) {
+			/*
+			 * We might have a POSIX lock that was created at the same time
+			 * the filp was closed for the last time. Just remove that too,
+			 * regardless of ownership, since nobody can own it.
+			 */
+			if (IS_FLOCK(fl) || IS_POSIX(fl)) {
 				locks_delete_lock(before);
 				continue;
 			}
@@ -1720,9 +1779,7 @@
 				lease_modify(before, F_UNLCK);
 				continue;
 			}
-			/* FL_POSIX locks of this process have already been
-			 * removed in filp_close->locks_remove_posix.
-			 */
+			/* What? */
 			BUG();
  		}
 		before = &fl->fl_next;
@@ -2038,4 +2095,4 @@
 	return 0;
 }
 
-module_init(filelock_init)
+core_initcall(filelock_init);
diff -Nru a/fs/minix/inode.c b/fs/minix/inode.c
--- a/fs/minix/inode.c	2004-10-18 14:56:32 -07:00
+++ b/fs/minix/inode.c	2004-10-18 14:56:32 -07:00
@@ -18,7 +18,7 @@
 #include <linux/vfs.h>
 
 static void minix_read_inode(struct inode * inode);
-static void minix_write_inode(struct inode * inode, int wait);
+static int minix_write_inode(struct inode * inode, int wait);
 static int minix_statfs(struct super_block *sb, struct kstatfs *buf);
 static int minix_remount (struct super_block * sb, int * flags, char * data);
 
@@ -79,7 +79,7 @@
 {
 	minix_inode_cachep = kmem_cache_create("minix_inode_cache",
 					     sizeof(struct minix_inode_info),
-					     0, SLAB_HWCACHE_ALIGN|SLAB_RECLAIM_ACCOUNT,
+					     0, SLAB_RECLAIM_ACCOUNT,
 					     init_once, NULL);
 	if (minix_inode_cachep == NULL)
 		return -ENOMEM;
@@ -505,9 +505,10 @@
 		return V2_minix_update_inode(inode);
 }
 
-static void minix_write_inode(struct inode * inode, int wait)
+static int minix_write_inode(struct inode * inode, int wait)
 {
 	brelse(minix_update_inode(inode));
+	return 0;
 }
 
 int minix_sync_inode(struct inode * inode)
diff -Nru a/fs/minix/itree_common.c b/fs/minix/itree_common.c
--- a/fs/minix/itree_common.c	2004-10-18 14:56:33 -07:00
+++ b/fs/minix/itree_common.c	2004-10-18 14:56:33 -07:00
@@ -358,5 +358,5 @@
 		res += blocks;
 		direct = 1;
 	}
-	return blocks;
+	return res;
 }
diff -Nru a/fs/mpage.c b/fs/mpage.c
--- a/fs/mpage.c	2004-10-18 14:56:20 -07:00
+++ b/fs/mpage.c	2004-10-18 14:56:20 -07:00
@@ -290,7 +290,8 @@
 alloc_new:
 	if (bio == NULL) {
 		bio = mpage_alloc(bdev, blocks[0] << (blkbits - 9),
-					nr_pages, GFP_KERNEL);
+			  	min_t(int, nr_pages, bio_get_nr_vecs(bdev)),
+				GFP_KERNEL);
 		if (bio == NULL)
 			goto confused;
 	}
@@ -627,7 +628,9 @@
 	struct pagevec pvec;
 	int nr_pages;
 	pgoff_t index;
+	pgoff_t end = -1;		/* Inclusive */
 	int scanned = 0;
+	int is_range = 0;
 
 	if (wbc->nonblocking && bdi_write_congested(bdi)) {
 		wbc->encountered_congestion = 1;
@@ -645,9 +648,17 @@
 		index = 0;			  /* whole-file sweep */
 		scanned = 1;
 	}
+	if (wbc->start || wbc->end) {
+		index = wbc->start >> PAGE_CACHE_SHIFT;
+		end = wbc->end >> PAGE_CACHE_SHIFT;
+		is_range = 1;
+		scanned = 1;
+	}
 retry:
-	while (!done && (nr_pages = pagevec_lookup_tag(&pvec, mapping, &index,
-					PAGECACHE_TAG_DIRTY, PAGEVEC_SIZE))) {
+	while (!done && (index <= end) &&
+			(nr_pages = pagevec_lookup_tag(&pvec, mapping, &index,
+			PAGECACHE_TAG_DIRTY,
+			min(end - index, (pgoff_t)PAGEVEC_SIZE-1) + 1))) {
 		unsigned i;
 
 		scanned = 1;
@@ -664,10 +675,21 @@
 
 			lock_page(page);
 
+			if (unlikely(page->mapping != mapping)) {
+				unlock_page(page);
+				continue;
+			}
+
+			if (unlikely(is_range) && page->index > end) {
+				done = 1;
+				unlock_page(page);
+				continue;
+			}
+
 			if (wbc->sync_mode != WB_SYNC_NONE)
 				wait_on_page_writeback(page);
 
-			if (page->mapping != mapping || PageWriteback(page) ||
+			if (PageWriteback(page) ||
 					!clear_page_dirty_for_io(page)) {
 				unlock_page(page);
 				continue;
@@ -706,7 +728,8 @@
 		index = 0;
 		goto retry;
 	}
-	mapping->writeback_index = index;
+	if (!is_range)
+		mapping->writeback_index = index;
 	if (bio)
 		mpage_bio_submit(WRITE, bio);
 	return ret;
diff -Nru a/fs/namei.c b/fs/namei.c
--- a/fs/namei.c	2004-10-18 14:56:28 -07:00
+++ b/fs/namei.c	2004-10-18 14:56:28 -07:00
@@ -868,29 +868,31 @@
 		return 0;		/* something went wrong... */
 
 	if (!nd->dentry->d_inode || S_ISDIR(nd->dentry->d_inode->i_mode)) {
-		struct nameidata nd_root;
+		struct dentry *old_dentry = nd->dentry;
+		struct vfsmount *old_mnt = nd->mnt;
+		struct qstr last = nd->last;
+		int last_type = nd->last_type;
 		/*
 		 * NAME was not found in alternate root or it's a directory.  Try to find
 		 * it in the normal root:
 		 */
-		nd_root.last_type = LAST_ROOT;
-		nd_root.flags = nd->flags;
-		nd_root.depth = 0;
-		memcpy(&nd_root.intent, &nd->intent, sizeof(nd_root.intent));
+		nd->last_type = LAST_ROOT;
 		read_lock(&current->fs->lock);
-		nd_root.mnt = mntget(current->fs->rootmnt);
-		nd_root.dentry = dget(current->fs->root);
+		nd->mnt = mntget(current->fs->rootmnt);
+		nd->dentry = dget(current->fs->root);
 		read_unlock(&current->fs->lock);
-		if (path_walk(name, &nd_root))
-			return 1;
-		if (nd_root.dentry->d_inode) {
+		if (path_walk(name, nd) == 0) {
+			if (nd->dentry->d_inode) {
+				dput(old_dentry);
+				mntput(old_mnt);
+				return 1;
+			}
 			path_release(nd);
-			nd->dentry = nd_root.dentry;
-			nd->mnt = nd_root.mnt;
-			nd->last = nd_root.last;
-			return 1;
 		}
-		path_release(&nd_root);
+		nd->dentry = old_dentry;
+		nd->mnt = old_mnt;
+		nd->last = last;
+		nd->last_type = last_type;
 	}
 	return 1;
 }
@@ -943,8 +945,7 @@
 		}
 		nd->mnt = mntget(current->fs->rootmnt);
 		nd->dentry = dget(current->fs->root);
-	}
-	else{
+	} else {
 		nd->mnt = mntget(current->fs->pwdmnt);
 		nd->dentry = dget(current->fs->pwd);
 	}
@@ -1094,8 +1095,12 @@
 static inline int may_delete(struct inode *dir,struct dentry *victim,int isdir)
 {
 	int error;
-	if (!victim->d_inode || victim->d_parent->d_inode != dir)
+
+	if (!victim->d_inode)
 		return -ENOENT;
+
+	BUG_ON(victim->d_parent->d_inode != dir);
+
 	error = permission(dir,MAY_WRITE | MAY_EXEC, NULL);
 	if (error)
 		return error;
@@ -1659,7 +1664,7 @@
  * if it cannot handle the case of removing a directory
  * that is still in use by something else..
  */
-static void d_unhash(struct dentry *dentry)
+void dentry_unhash(struct dentry *dentry)
 {
 	dget(dentry);
 	spin_lock(&dcache_lock);
@@ -1689,7 +1694,7 @@
 	DQUOT_INIT(dir);
 
 	down(&dentry->d_inode->i_sem);
-	d_unhash(dentry);
+	dentry_unhash(dentry);
 	if (d_mountpoint(dentry))
 		error = -EBUSY;
 	else {
@@ -1820,13 +1825,12 @@
 		dput(dentry);
 	}
 	up(&nd.dentry->d_inode->i_sem);
+	if (inode)
+		iput(inode);	/* truncate the inode here */
 exit1:
 	path_release(&nd);
 exit:
 	putname(name);
-
-	if (inode)
-		iput(inode);	/* truncate the inode here */
 	return error;
 
 slashes:
@@ -2032,7 +2036,7 @@
 	target = new_dentry->d_inode;
 	if (target) {
 		down(&target->i_sem);
-		d_unhash(new_dentry);
+		dentry_unhash(new_dentry);
 	}
 	if (d_mountpoint(old_dentry)||d_mountpoint(new_dentry))
 		error = -EBUSY;
@@ -2299,12 +2303,8 @@
 int page_follow_link_light(struct dentry *dentry, struct nameidata *nd)
 {
 	struct page *page;
-	char *s = page_getlink(dentry, &page);
-	if (!IS_ERR(s)) {
-		nd_set_link(nd, s);
-		s = NULL;
-	}
-	return PTR_ERR(s);
+	nd_set_link(nd, page_getlink(dentry, &page));
+	return 0;
 }
 
 void page_put_link(struct dentry *dentry, struct nameidata *nd)
@@ -2410,4 +2410,5 @@
 EXPORT_SYMBOL(vfs_rmdir);
 EXPORT_SYMBOL(vfs_symlink);
 EXPORT_SYMBOL(vfs_unlink);
+EXPORT_SYMBOL(dentry_unhash);
 EXPORT_SYMBOL(generic_readlink);
diff -Nru a/fs/namespace.c b/fs/namespace.c
--- a/fs/namespace.c	2004-10-18 14:56:33 -07:00
+++ b/fs/namespace.c	2004-10-18 14:56:33 -07:00
@@ -930,7 +930,35 @@
 
 EXPORT_SYMBOL_GPL(mark_mounts_for_expiry);
 
-int copy_mount_options (const void __user *data, unsigned long *where)
+/*
+ * Some copy_from_user() implementations do not return the exact number of
+ * bytes remaining to copy on a fault.  But copy_mount_options() requires that.
+ * Note that this function differs from copy_from_user() in that it will oops
+ * on bad values of `to', rather than returning a short copy.
+ */
+static long
+exact_copy_from_user(void *to, const void __user *from, unsigned long n)
+{
+	char *t = to;
+	const char __user *f = from;
+	char c;
+
+	if (!access_ok(VERIFY_READ, from, n))
+		return n;
+
+	while (n) {
+		if (__get_user(c, f)) {
+			memset(t, 0, n);
+			break;
+		}
+		*t++ = c;
+		f++;
+		n--;
+	}
+	return n;
+}
+
+int copy_mount_options(const void __user *data, unsigned long *where)
 {
 	int i;
 	unsigned long page;
@@ -952,7 +980,7 @@
 	if (size > PAGE_SIZE)
 		size = PAGE_SIZE;
 
-	i = size - copy_from_user((void *)page, data, size);
+	i = size - exact_copy_from_user((void *)page, data, size);
 	if (!i) {
 		free_page(page); 
 		return -EFAULT;
diff -Nru a/fs/ncpfs/dir.c b/fs/ncpfs/dir.c
--- a/fs/ncpfs/dir.c	2004-10-18 14:56:32 -07:00
+++ b/fs/ncpfs/dir.c	2004-10-18 14:56:32 -07:00
@@ -174,7 +174,7 @@
 {
         int res=0x9c,res2;
 	struct nw_modify_dos_info info;
-	__u32 old_nwattr;
+	__le32 old_nwattr;
 	struct inode *inode;
 
 	memset(&info, 0, sizeof(info));
@@ -211,8 +211,8 @@
 	struct nw_modify_dos_info info;
         int res=0x90,res2;
 	struct inode *old_inode = old_dentry->d_inode;
-	__u32 old_nwattr = NCP_FINFO(old_inode)->nwattr;
-	__u32 new_nwattr = 0; /* shut compiler warning */
+	__le32 old_nwattr = NCP_FINFO(old_inode)->nwattr;
+	__le32 new_nwattr = 0; /* shut compiler warning */
 	int old_nwattr_changed = 0;
 	int new_nwattr_changed = 0;
 
@@ -395,8 +395,7 @@
 	if (ncp_obtain_info(server, inode, NULL, &i))
 		return 0;
 
-	return ncp_date_dos2unix(le16_to_cpu(i.modifyTime),
-						le16_to_cpu(i.modifyDate));
+	return ncp_date_dos2unix(i.modifyTime, i.modifyDate);
 }
 
 static int ncp_readdir(struct file *filp, void *dirent, filldir_t filldir)
@@ -767,7 +766,9 @@
 	if (ncp_single_volume(server)) {
 		int len;
 		struct dentry* dent;
-		__u32 volNumber, dirEntNum, DosDirNum;
+		__u32 volNumber;
+		__le32 dirEntNum;
+		__le32 DosDirNum;
 		__u8 __name[NCP_MAXPATHLEN + 1];
 
 		len = sizeof(__name);
@@ -886,7 +887,7 @@
 }
 
 int ncp_create_new(struct inode *dir, struct dentry *dentry, int mode,
-		   dev_t rdev, int attributes)
+		   dev_t rdev, __le32 attributes)
 {
 	struct ncp_server *server = NCP_SERVER(dir);
 	struct ncp_entry_info finfo;
@@ -979,7 +980,8 @@
 
 	error = -EACCES;
 	if (ncp_open_create_file_or_subdir(server, dir, __name,
-					   OC_MODE_CREATE, aDIR, 0xffff,
+					   OC_MODE_CREATE, aDIR,
+					   cpu_to_le16(0xffff),
 					   &finfo) == 0)
 	{
 		if (ncp_is_nfs_extras(server, finfo.volume)) {
@@ -1213,8 +1215,9 @@
 
 /* Convert a MS-DOS time/date pair to a UNIX date (seconds since 1 1 70). */
 int
-ncp_date_dos2unix(unsigned short time, unsigned short date)
+ncp_date_dos2unix(__le16 t, __le16 d)
 {
+	unsigned short time = le16_to_cpu(t), date = le16_to_cpu(d);
 	int month, year, secs;
 
 	/* first subtract and mask after that... Otherwise, if
@@ -1231,13 +1234,14 @@
 
 /* Convert linear UNIX date to a MS-DOS time/date pair. */
 void
-ncp_date_unix2dos(int unix_date, unsigned short *time, unsigned short *date)
+ncp_date_unix2dos(int unix_date, __le16 *time, __le16 *date)
 {
 	int day, year, nl_day, month;
 
 	unix_date = utc2local(unix_date);
-	*time = (unix_date % 60) / 2 + (((unix_date / 60) % 60) << 5) +
-	    (((unix_date / 3600) % 24) << 11);
+	*time = cpu_to_le16(
+		(unix_date % 60) / 2 + (((unix_date / 60) % 60) << 5) +
+		(((unix_date / 3600) % 24) << 11));
 	day = unix_date / 86400 - 3652;
 	year = day / 365;
 	if ((year + 3) / 4 + 365 * year > day)
@@ -1252,5 +1256,5 @@
 			if (day_n[month] > nl_day)
 				break;
 	}
-	*date = nl_day - day_n[month - 1] + 1 + (month << 5) + (year << 9);
+	*date = cpu_to_le16(nl_day - day_n[month - 1] + 1 + (month << 5) + (year << 9));
 }
diff -Nru a/fs/ncpfs/file.c b/fs/ncpfs/file.c
--- a/fs/ncpfs/file.c	2004-10-18 14:55:54 -07:00
+++ b/fs/ncpfs/file.c	2004-10-18 14:55:54 -07:00
@@ -115,11 +115,6 @@
 
 	if (!ncp_conn_valid(NCP_SERVER(inode)))
 		return -EIO;
-	if (!S_ISREG(inode->i_mode)) {
-		DPRINTK("ncp_file_read: read from non-file, mode %07o\n",
-			inode->i_mode);
-		return -EINVAL;
-	}
 
 	pos = *ppos;
 
@@ -175,10 +170,8 @@
 
 	*ppos = pos;
 
-	if (!IS_RDONLY(inode)) {
-		inode->i_atime = CURRENT_TIME;
-	}
-	
+	file_accessed(file);
+
 	DPRINTK("ncp_file_read: exit %s/%s\n",
 		dentry->d_parent->d_name.name, dentry->d_name.name);
 outrel:
@@ -201,11 +194,6 @@
 		dentry->d_parent->d_name.name, dentry->d_name.name);
 	if (!ncp_conn_valid(NCP_SERVER(inode)))
 		return -EIO;
-	if (!S_ISREG(inode->i_mode)) {
-		DPRINTK("ncp_file_write: write to non-file, mode %07o\n",
-			inode->i_mode);
-		return -EINVAL;
-	}
 	if ((ssize_t) count < 0)
 		return -EINVAL;
 	pos = *ppos;
@@ -273,8 +261,9 @@
 		}
 	}
 	vfree(bouncebuffer);
-	inode->i_mtime = inode->i_atime = CURRENT_TIME;
-	
+
+	inode_update_time(inode, 1);
+
 	*ppos = pos;
 
 	if (pos > inode->i_size) {
diff -Nru a/fs/ncpfs/inode.c b/fs/ncpfs/inode.c
--- a/fs/ncpfs/inode.c	2004-10-18 14:56:32 -07:00
+++ b/fs/ncpfs/inode.c	2004-10-18 14:56:32 -07:00
@@ -72,7 +72,7 @@
 {
 	ncp_inode_cachep = kmem_cache_create("ncp_inode_cache",
 					     sizeof(struct ncp_inode_info),
-					     0, SLAB_HWCACHE_ALIGN|SLAB_RECLAIM_ACCOUNT,
+					     0, SLAB_RECLAIM_ACCOUNT,
 					     init_once, NULL);
 	if (ncp_inode_cachep == NULL)
 		return -ENOMEM;
@@ -142,12 +142,9 @@
 
 	inode->i_blocks = (inode->i_size + NCP_BLOCK_SIZE - 1) >> NCP_BLOCK_SHIFT;
 
-	inode->i_mtime.tv_sec = ncp_date_dos2unix(le16_to_cpu(nwi->modifyTime),
-					   le16_to_cpu(nwi->modifyDate));
-	inode->i_ctime.tv_sec = ncp_date_dos2unix(le16_to_cpu(nwi->creationTime),
-					   le16_to_cpu(nwi->creationDate));
-	inode->i_atime.tv_sec = ncp_date_dos2unix(0,
-					   le16_to_cpu(nwi->lastAccessDate));
+	inode->i_mtime.tv_sec = ncp_date_dos2unix(nwi->modifyTime, nwi->modifyDate);
+	inode->i_ctime.tv_sec = ncp_date_dos2unix(nwi->creationTime, nwi->creationDate);
+	inode->i_atime.tv_sec = ncp_date_dos2unix(0, nwi->lastAccessDate);
 	inode->i_atime.tv_nsec = 0;
 	inode->i_mtime.tv_nsec = 0;
 	inode->i_ctime.tv_nsec = 0;
@@ -235,8 +232,9 @@
 
 #if defined(CONFIG_NCPFS_EXTRAS) || defined(CONFIG_NCPFS_NFS_NS)
 static struct inode_operations ncp_symlink_inode_operations = {
-	.readlink	= page_readlink,
-	.follow_link	= page_follow_link,
+	.readlink	= generic_readlink,
+	.follow_link	= page_follow_link_light,
+	.put_link	= page_put_link,
 	.setattr	= ncp_notify_change,
 };
 #endif
@@ -462,7 +460,7 @@
 			break;
 		default:
 			error = -ECHRNG;
-			if (*(__u32*)raw_data == cpu_to_be32(0x76657273)) {
+			if (memcmp(raw_data, "vers", 4) == 0) {
 				error = ncp_parse_options(&data, raw_data);
 			}
 			if (error)
@@ -625,7 +623,7 @@
 
 	memset(&finfo, 0, sizeof(finfo));
 	finfo.i.attributes	= aDIR;
-	finfo.i.dataStreamSize	= NCP_BLOCK_SIZE;
+	finfo.i.dataStreamSize	= 0;	/* ignored */
 	finfo.i.dirEntNum	= 0;
 	finfo.i.DosDirNum	= 0;
 #ifdef CONFIG_NCPFS_SMALLDOS
@@ -794,7 +792,7 @@
 {
 	struct inode *inode = dentry->d_inode;
 	int result = 0;
-	int info_mask;
+	__le32 info_mask;
 	struct nw_modify_dos_info info;
 	struct ncp_server *server;
 
@@ -917,23 +915,18 @@
 	if ((attr->ia_valid & ATTR_CTIME) != 0) {
 		info_mask |= (DM_CREATE_TIME | DM_CREATE_DATE);
 		ncp_date_unix2dos(attr->ia_ctime.tv_sec,
-			     &(info.creationTime), &(info.creationDate));
-		info.creationTime = le16_to_cpu(info.creationTime);
-		info.creationDate = le16_to_cpu(info.creationDate);
+			     &info.creationTime, &info.creationDate);
 	}
 	if ((attr->ia_valid & ATTR_MTIME) != 0) {
 		info_mask |= (DM_MODIFY_TIME | DM_MODIFY_DATE);
 		ncp_date_unix2dos(attr->ia_mtime.tv_sec,
-				  &(info.modifyTime), &(info.modifyDate));
-		info.modifyTime = le16_to_cpu(info.modifyTime);
-		info.modifyDate = le16_to_cpu(info.modifyDate);
+				  &info.modifyTime, &info.modifyDate);
 	}
 	if ((attr->ia_valid & ATTR_ATIME) != 0) {
-		__u16 dummy;
+		__le16 dummy;
 		info_mask |= (DM_LAST_ACCESS_DATE);
 		ncp_date_unix2dos(attr->ia_atime.tv_sec,
-				  &(dummy), &(info.lastAccessDate));
-		info.lastAccessDate = le16_to_cpu(info.lastAccessDate);
+				  &dummy, &info.lastAccessDate);
 	}
 	if (info_mask != 0) {
 		result = ncp_modify_file_or_subdir_dos_info(NCP_SERVER(inode),
diff -Nru a/fs/ncpfs/ioctl.c b/fs/ncpfs/ioctl.c
--- a/fs/ncpfs/ioctl.c	2004-10-18 14:56:32 -07:00
+++ b/fs/ncpfs/ioctl.c	2004-10-18 14:56:32 -07:00
@@ -299,7 +299,9 @@
 	case NCP_IOC_SETROOT:
 		{
 			struct ncp_setroot_ioctl sr;
-			__u32 vnum, de, dosde;
+			__u32 vnum;
+			__le32 de;
+			__le32 dosde;
 			struct dentry* dentry;
 
 			if (!capable(CAP_SYS_ADMIN))
diff -Nru a/fs/ncpfs/mmap.c b/fs/ncpfs/mmap.c
--- a/fs/ncpfs/mmap.c	2004-10-18 14:56:48 -07:00
+++ b/fs/ncpfs/mmap.c	2004-10-18 14:56:48 -07:00
@@ -110,23 +110,19 @@
 	
 	DPRINTK("ncp_mmap: called\n");
 
-	if (!ncp_conn_valid(NCP_SERVER(inode))) {
+	if (!ncp_conn_valid(NCP_SERVER(inode)))
 		return -EIO;
-	}
+
 	/* only PAGE_COW or read-only supported now */
 	if (vma->vm_flags & VM_SHARED)
 		return -EINVAL;
-	if (!inode->i_sb || !S_ISREG(inode->i_mode))
-		return -EACCES;
 	/* we do not support files bigger than 4GB... We eventually 
 	   supports just 4GB... */
 	if (((vma->vm_end - vma->vm_start) >> PAGE_SHIFT) + vma->vm_pgoff 
 	   > (1U << (32 - PAGE_SHIFT)))
 		return -EFBIG;
-	if (!IS_RDONLY(inode)) {
-		inode->i_atime = CURRENT_TIME;
-	}
 
 	vma->vm_ops = &ncp_file_mmap;
+	file_accessed(file);
 	return 0;
 }
diff -Nru a/fs/ncpfs/ncplib_kernel.c b/fs/ncpfs/ncplib_kernel.c
--- a/fs/ncpfs/ncplib_kernel.c	2004-10-18 14:56:29 -07:00
+++ b/fs/ncpfs/ncplib_kernel.c	2004-10-18 14:56:29 -07:00
@@ -29,22 +29,36 @@
 	return;
 }
 
-static void ncp_add_word(struct ncp_server *server, __u16 x)
+static void ncp_add_word(struct ncp_server *server, __le16 x)
 {
 	assert_server_locked(server);
-	put_unaligned(x, (__u16 *) (&(server->packet[server->current_size])));
+	put_unaligned(x, (__le16 *) (&(server->packet[server->current_size])));
 	server->current_size += 2;
 	return;
 }
 
-static void ncp_add_dword(struct ncp_server *server, __u32 x)
+static void ncp_add_be16(struct ncp_server *server, __u16 x)
 {
 	assert_server_locked(server);
-	put_unaligned(x, (__u32 *) (&(server->packet[server->current_size])));
+	put_unaligned(cpu_to_be16(x), (__be16 *) (&(server->packet[server->current_size])));
+	server->current_size += 2;
+}
+
+static void ncp_add_dword(struct ncp_server *server, __le32 x)
+{
+	assert_server_locked(server);
+	put_unaligned(x, (__le32 *) (&(server->packet[server->current_size])));
 	server->current_size += 4;
 	return;
 }
 
+static void ncp_add_be32(struct ncp_server *server, __u32 x)
+{
+	assert_server_locked(server);
+	put_unaligned(cpu_to_be32(x), (__be32 *)(&(server->packet[server->current_size])));
+	server->current_size += 4;
+}
+
 static inline void ncp_add_dword_lh(struct ncp_server *server, __u32 x) {
 	ncp_add_dword(server, cpu_to_le32(x));
 }
@@ -107,24 +121,30 @@
 
 static inline __u16 WVAL_LH(void* data)
 {
-	return le16_to_cpu(get_unaligned((__u16*)data));
+	return le16_to_cpu(get_unaligned((__le16*)data));
 }
 
 static __u16
- ncp_reply_word(struct ncp_server *server, int offset)
+ ncp_reply_le16(struct ncp_server *server, int offset)
 {
-	return get_unaligned((__u16 *) ncp_reply_data(server, offset));
+	return le16_to_cpu(get_unaligned((__le16 *) ncp_reply_data(server, offset)));
+}
+
+static __u16
+ ncp_reply_be16(struct ncp_server *server, int offset)
+{
+	return be16_to_cpu(get_unaligned((__be16 *) ncp_reply_data(server, offset)));
 }
 
 static inline __u32 DVAL_LH(void* data)
 {
-	return le32_to_cpu(get_unaligned((__u32*)data));
+	return le32_to_cpu(get_unaligned((__le32*)data));
 }
 
-static __u32
+static __le32
  ncp_reply_dword(struct ncp_server *server, int offset)
 {
-	return get_unaligned((__u32 *) ncp_reply_data(server, offset));
+	return get_unaligned((__le32 *) ncp_reply_data(server, offset));
 }
 
 static inline __u32 ncp_reply_dword_lh(struct ncp_server* server, int offset) {
@@ -137,13 +157,13 @@
 	int result;
 
 	ncp_init_request(server);
-	ncp_add_word(server, htons(size));
+	ncp_add_be16(server, size);
 
 	if ((result = ncp_request(server, 33)) != 0) {
 		ncp_unlock_server(server);
 		return result;
 	}
-	*target = min_t(unsigned int, ntohs(ncp_reply_word(server, 0)), size);
+	*target = min_t(unsigned int, ncp_reply_be16(server, 0), size);
 
 	ncp_unlock_server(server);
 	return 0;
@@ -163,7 +183,7 @@
 	if (size < NCP_BLOCK_SIZE) size = NCP_BLOCK_SIZE;
 
 	ncp_init_request(server);
-	ncp_add_word(server, htons(size));
+	ncp_add_be16(server, size);
 	ncp_add_byte(server, options);
 	
 	if ((result = ncp_request(server, 0x61)) != 0)
@@ -173,7 +193,7 @@
 	}
 
 	/* NCP over UDP returns 0 (!!!) */
-	result = ntohs(ncp_reply_word(server, 0));
+	result = ncp_reply_be16(server, 0);
 	if (result >= NCP_BLOCK_SIZE)
 		size = min(result, size);
 	*ret_size = size;
@@ -286,7 +306,7 @@
 }
 
 static void ncp_add_handle_path(struct ncp_server *server, __u8 vol_num,
-				__u32 dir_base, int have_dir_base, 
+				__le32 dir_base, int have_dir_base, 
 				const char *path)
 {
 	ncp_add_byte(server, vol_num);
@@ -304,7 +324,7 @@
 	}
 }
 
-int ncp_dirhandle_alloc(struct ncp_server* server, __u8 volnum, __u32 dirent,
+int ncp_dirhandle_alloc(struct ncp_server* server, __u8 volnum, __le32 dirent,
 			__u8* dirhandle) {
 	int result;
 
@@ -403,7 +423,7 @@
 			struct nw_info_struct *target)
 {
 	__u8  volnum = NCP_FINFO(dir)->volNumber;
-	__u32 dirent = NCP_FINFO(dir)->dirEntNum;
+	__le32 dirent = NCP_FINFO(dir)->dirEntNum;
 	int result;
 
 	if (target == NULL) {
@@ -414,7 +434,7 @@
 	ncp_add_byte(server, 6);	/* subfunction */
 	ncp_add_byte(server, server->name_space[volnum]);
 	ncp_add_byte(server, server->name_space[volnum]); /* N.B. twice ?? */
-	ncp_add_word(server, htons(0x0680));	/* get all */
+	ncp_add_word(server, cpu_to_le16(0x8006));	/* get all */
 	ncp_add_dword(server, RIM_ALL);
 	ncp_add_handle_path(server, volnum, dirent, 1, path);
 
@@ -434,9 +454,9 @@
 #ifdef CONFIG_NCPFS_NFS_NS
 static int
 ncp_obtain_DOS_dir_base(struct ncp_server *server,
-		__u8 volnum, __u32 dirent,
+		__u8 volnum, __le32 dirent,
 		char *path, /* At most 1 component */
-		__u32 *DOS_dir_base)
+		__le32 *DOS_dir_base)
 {
 	int result;
 
@@ -444,7 +464,7 @@
 	ncp_add_byte(server, 6); /* subfunction */
 	ncp_add_byte(server, server->name_space[volnum]);
 	ncp_add_byte(server, server->name_space[volnum]);
-	ncp_add_word(server, htons(0x0680)); /* get all */
+	ncp_add_word(server, cpu_to_le16(0x8006)); /* get all */
 	ncp_add_dword(server, RIM_DIRECTORY);
 	ncp_add_handle_path(server, volnum, dirent, 1, path);
 
@@ -476,7 +496,7 @@
 	}
 
 	result = NW_NS_DOS;
-	no_namespaces = le16_to_cpu(ncp_reply_word(server, 0));
+	no_namespaces = ncp_reply_le16(server, 0);
 	namespace = ncp_reply_data(server, 2);
 
 	while (no_namespaces > 0) {
@@ -507,9 +527,9 @@
 
 static int
 ncp_ObtainSpecificDirBase(struct ncp_server *server,
-		__u8 nsSrc, __u8 nsDst, __u8 vol_num, __u32 dir_base,
+		__u8 nsSrc, __u8 nsDst, __u8 vol_num, __le32 dir_base,
 		char *path, /* At most 1 component */
-		__u32 *dirEntNum, __u32 *DosDirNum)
+		__le32 *dirEntNum, __le32 *DosDirNum)
 {
 	int result;
 
@@ -517,7 +537,7 @@
 	ncp_add_byte(server, 6); /* subfunction */
 	ncp_add_byte(server, nsSrc);
 	ncp_add_byte(server, nsDst);
-	ncp_add_word(server, htons(0x0680)); /* get all */
+	ncp_add_word(server, cpu_to_le16(0x8006)); /* get all */
 	ncp_add_dword(server, RIM_ALL);
 	ncp_add_handle_path(server, vol_num, dir_base, 1, path);
 
@@ -537,8 +557,8 @@
 
 int
 ncp_mount_subdir(struct ncp_server *server,
-		 __u8 volNumber, __u8 srcNS, __u32 dirEntNum,
-		 __u32* volume, __u32* newDirEnt, __u32* newDosEnt)
+		 __u8 volNumber, __u8 srcNS, __le32 dirEntNum,
+		 __u32* volume, __le32* newDirEnt, __le32* newDosEnt)
 {
 	int dstNS;
 	int result;
@@ -558,7 +578,7 @@
 
 int 
 ncp_get_volume_root(struct ncp_server *server, const char *volname,
-		    __u32* volume, __u32* dirent, __u32* dosdirent)
+		    __u32* volume, __le32* dirent, __le32* dosdirent)
 {
 	int result;
 	__u8 volnum;
@@ -620,18 +640,18 @@
 int ncp_modify_file_or_subdir_dos_info_path(struct ncp_server *server,
 					    struct inode *dir,
 					    const char *path,
-					    __u32 info_mask,
+					    __le32 info_mask,
 					    const struct nw_modify_dos_info *info)
 {
 	__u8  volnum = NCP_FINFO(dir)->volNumber;
-	__u32 dirent = NCP_FINFO(dir)->dirEntNum;
+	__le32 dirent = NCP_FINFO(dir)->dirEntNum;
 	int result;
 
 	ncp_init_request(server);
 	ncp_add_byte(server, 7);	/* subfunction */
 	ncp_add_byte(server, server->name_space[volnum]);
 	ncp_add_byte(server, 0);	/* reserved */
-	ncp_add_word(server, htons(0x0680));	/* search attribs: all */
+	ncp_add_word(server, cpu_to_le16(0x8006));	/* search attribs: all */
 
 	ncp_add_dword(server, info_mask);
 	ncp_add_mem(server, info, sizeof(*info));
@@ -644,7 +664,7 @@
 
 int ncp_modify_file_or_subdir_dos_info(struct ncp_server *server,
 				       struct inode *dir,
-				       __u32 info_mask,
+				       __le32 info_mask,
 				       const struct nw_modify_dos_info *info)
 {
 	return ncp_modify_file_or_subdir_dos_info_path(server, dir, NULL,
@@ -652,7 +672,7 @@
 }
 
 #ifdef CONFIG_NCPFS_NFS_NS
-int ncp_modify_nfs_info(struct ncp_server *server, __u8 volnum, __u32 dirent,
+int ncp_modify_nfs_info(struct ncp_server *server, __u8 volnum, __le32 dirent,
 			       __u32 mode, __u32 rdev)
 
 {
@@ -681,8 +701,8 @@
 
 static int
 ncp_DeleteNSEntry(struct ncp_server *server,
-		  __u8 have_dir_base, __u8 volnum, __u32 dirent,
-		  char* name, __u8 ns, int attr)
+		  __u8 have_dir_base, __u8 volnum, __le32 dirent,
+		  char* name, __u8 ns, __le16 attr)
 {
 	int result;
 
@@ -704,7 +724,7 @@
 {
 	struct inode *inode = dentry->d_inode;
 	__u8  volnum;
-	__u32 dirent;
+	__le32 dirent;
 
 	if (!inode) {
 #ifdef CONFIG_NCPFS_DEBUGDENTRY
@@ -714,7 +734,7 @@
 	}
 	volnum = NCP_FINFO(inode)->volNumber;
 	dirent = NCP_FINFO(inode)->DosDirNum;
-	return ncp_DeleteNSEntry(server, 1, volnum, dirent, NULL, NW_NS_DOS, htons(0x0680));
+	return ncp_DeleteNSEntry(server, 1, volnum, dirent, NULL, NW_NS_DOS, cpu_to_le16(0x8006));
 }
 
 int
@@ -722,7 +742,7 @@
 		       struct inode *dir, char *name)
 {
 	__u8  volnum = NCP_FINFO(dir)->volNumber;
-	__u32 dirent = NCP_FINFO(dir)->dirEntNum;
+	__le32 dirent = NCP_FINFO(dir)->dirEntNum;
 
 #ifdef CONFIG_NCPFS_NFS_NS
 	if (server->name_space[volnum]==NW_NS_NFS)
@@ -731,18 +751,19 @@
  
  		result=ncp_obtain_DOS_dir_base(server, volnum, dirent, name, &dirent);
  		if (result) return result;
- 		return ncp_DeleteNSEntry(server, 1, volnum, dirent, NULL, NW_NS_DOS, htons(0x0680));
+ 		return ncp_DeleteNSEntry(server, 1, volnum, dirent, NULL, NW_NS_DOS, cpu_to_le16(0x8006));
  	}
  	else
 #endif	/* CONFIG_NCPFS_NFS_NS */
- 		return ncp_DeleteNSEntry(server, 1, volnum, dirent, name, server->name_space[volnum], htons(0x0680));
+ 		return ncp_DeleteNSEntry(server, 1, volnum, dirent, name, server->name_space[volnum], cpu_to_le16(0x8006));
 }
 
-static inline void ConvertToNWfromDWORD(__u32 sfd, __u8 ret[6])
+static inline void ConvertToNWfromDWORD(__u16 v0, __u16 v1, __u8 ret[6])
 {
-	__u16 *dest = (__u16 *) ret;
-	memcpy(ret + 2, &sfd, 4);
-	dest[0] = cpu_to_le16((le16_to_cpu(dest[1]) + le16_to_cpu(1)));
+	__le16 *dest = (__le16 *) ret;
+	dest[1] = cpu_to_le16(v0);
+	dest[2] = cpu_to_le16(v1);
+	dest[0] = cpu_to_le16(v0 + 1);
 	return;
 }
 
@@ -751,20 +772,20 @@
 int ncp_open_create_file_or_subdir(struct ncp_server *server,
 				   struct inode *dir, char *name,
 				   int open_create_mode,
-				   __u32 create_attributes,
-				   int desired_acc_rights,
+				   __le32 create_attributes,
+				   __le16 desired_acc_rights,
 				   struct ncp_entry_info *target)
 {
-	__u16 search_attribs = ntohs(0x0600);
+	__le16 search_attribs = cpu_to_le16(0x0006);
 	__u8  volnum;
-	__u32 dirent;
+	__le32 dirent;
 	int result;
 
 	volnum = NCP_FINFO(dir)->volNumber;
 	dirent = NCP_FINFO(dir)->dirEntNum;
 
 	if ((create_attributes & aDIR) != 0) {
-		search_attribs |= ntohs(0x0080);
+		search_attribs |= cpu_to_le16(0x8000);
 	}
 	ncp_init_request(server);
 	ncp_add_byte(server, 1);	/* subfunction */
@@ -786,7 +807,9 @@
 	/* in target there's a new finfo to fill */
 	ncp_extract_file_info(ncp_reply_data(server, 6), &(target->i));
 	target->volume = target->i.volNumber;
-	ConvertToNWfromDWORD(ncp_reply_dword(server, 0), target->file_handle);
+	ConvertToNWfromDWORD(ncp_reply_le16(server, 0),
+			     ncp_reply_le16(server, 2),
+			     target->file_handle);
 	
 	ncp_unlock_server(server);
 
@@ -803,7 +826,7 @@
 			struct nw_search_sequence *target)
 {
 	__u8  volnum = NCP_FINFO(dir)->volNumber;
-	__u32 dirent = NCP_FINFO(dir)->dirEntNum;
+	__le32 dirent = NCP_FINFO(dir)->dirEntNum;
 	int result;
 
 	ncp_init_request(server);
@@ -833,7 +856,7 @@
 	ncp_add_byte(server, 3);	/* subfunction */
 	ncp_add_byte(server, server->name_space[seq->volNumber]);
 	ncp_add_byte(server, 0);	/* data stream (???) */
-	ncp_add_word(server, htons(0x0680));	/* Search attribs */
+	ncp_add_word(server, cpu_to_le16(0x8006));	/* Search attribs */
 	ncp_add_dword(server, RIM_ALL);		/* return info mask */
 	ncp_add_mem(server, seq, 9);
 #ifdef CONFIG_NCPFS_NFS_NS
@@ -877,9 +900,9 @@
 	ncp_add_byte(server, 20);
 	ncp_add_byte(server, server->name_space[seq->volNumber]);
 	ncp_add_byte(server, 0);		/* datastream */
-	ncp_add_word(server, htons(0x0680));
+	ncp_add_word(server, cpu_to_le16(0x8006));
 	ncp_add_dword(server, RIM_ALL);
-	ncp_add_word(server, 32767);		/* max returned items */
+	ncp_add_word(server, cpu_to_le16(32767));	/* max returned items */
 	ncp_add_mem(server, seq, 9);
 #ifdef CONFIG_NCPFS_NFS_NS
 	if (server->name_space[seq->volNumber] == NW_NS_NFS) {
@@ -912,7 +935,7 @@
 
 int
 ncp_RenameNSEntry(struct ncp_server *server,
-		  struct inode *old_dir, char *old_name, int old_type,
+		  struct inode *old_dir, char *old_name, __le16 old_type,
 		  struct inode *new_dir, char *new_name)
 {
 	int result = -EINVAL;
@@ -955,14 +978,14 @@
 				struct inode *new_dir, char *new_name)
 {
         int result;
-        int old_type = htons(0x0600);
+        __le16 old_type = cpu_to_le16(0x06);
 
 /* If somebody can do it atomic, call me... vandrove@vc.cvut.cz */
 	result = ncp_RenameNSEntry(server, old_dir, old_name, old_type,
 	                                   new_dir, new_name);
         if (result == 0xFF)	/* File Not Found, try directory */
 	{
-		old_type = htons(0x1600);
+		old_type = cpu_to_le16(0x16);
 		result = ncp_RenameNSEntry(server, old_dir, old_name, old_type,
 						   new_dir, new_name);
 	}
@@ -986,13 +1009,13 @@
 	ncp_init_request(server);
 	ncp_add_byte(server, 0);
 	ncp_add_mem(server, file_id, 6);
-	ncp_add_dword(server, htonl(offset));
-	ncp_add_word(server, htons(to_read));
+	ncp_add_be32(server, offset);
+	ncp_add_be16(server, to_read);
 
 	if ((result = ncp_request(server, 72)) != 0) {
 		goto out;
 	}
-	*bytes_read = ntohs(ncp_reply_word(server, 0));
+	*bytes_read = ncp_reply_be16(server, 0);
 	source = ncp_reply_data(server, 2 + (offset & 1));
 
 	memcpy(target, source, *bytes_read);
@@ -1022,12 +1045,12 @@
 	ncp_init_request(server);
 	ncp_add_byte(server, 0);
 	ncp_add_mem(server, file_id, 6);
-	ncp_add_dword(server, htonl(offset));
-	ncp_add_word(server, htons(to_read));
+	ncp_add_be32(server, offset);
+	ncp_add_be16(server, to_read);
 	result = ncp_request2(server, 72, bounce, bufsize);
 	ncp_unlock_server(server);
 	if (!result) {
-		int len = be16_to_cpu(get_unaligned((__u16*)((char*)bounce + 
+		int len = be16_to_cpu(get_unaligned((__be16*)((char*)bounce + 
 			  sizeof(struct ncp_reply_header))));
 		result = -EIO;
 		if (len <= to_read) {
@@ -1055,8 +1078,8 @@
 	ncp_init_request(server);
 	ncp_add_byte(server, 0);
 	ncp_add_mem(server, file_id, 6);
-	ncp_add_dword(server, htonl(offset));
-	ncp_add_word(server, htons(to_write));
+	ncp_add_be32(server, offset);
+	ncp_add_be16(server, to_write);
 	ncp_add_mem(server, source, to_write);
 	
 	if ((result = ncp_request(server, 73)) == 0)
@@ -1075,9 +1098,9 @@
 	ncp_init_request(server);
 	ncp_add_byte(server, locktype);
 	ncp_add_mem(server, file_id, 6);
-	ncp_add_dword(server, htonl(offset));
-	ncp_add_dword(server, htonl(length));
-	ncp_add_word(server, htons(timeout));
+	ncp_add_be32(server, offset);
+	ncp_add_be32(server, length);
+	ncp_add_be16(server, timeout);
 
 	if ((result = ncp_request(server, 0x1A)) != 0)
 	{
@@ -1097,8 +1120,8 @@
 	ncp_init_request(server);
 	ncp_add_byte(server, 0);	/* who knows... lanalyzer says that */
 	ncp_add_mem(server, file_id, 6);
-	ncp_add_dword(server, htonl(offset));
-	ncp_add_dword(server, htonl(length));
+	ncp_add_be32(server, offset);
+	ncp_add_be32(server, length);
 
 	if ((result = ncp_request(server, 0x1E)) != 0)
 	{
@@ -1115,22 +1138,6 @@
  * from the vfat file system and hints from Petr Vandrovec.
  */
 
-inline unsigned char
-ncp__tolower(struct nls_table *t, unsigned char c)
-{
-	unsigned char nc = t->charset2lower[c];
-
-	return nc ? nc : c;
-}
-
-inline unsigned char
-ncp__toupper(struct nls_table *t, unsigned char c)
-{
-	unsigned char nc = t->charset2upper[c];
-
-	return nc ? nc : c;
-}
-
 int
 ncp__io2vol(struct ncp_server *server, unsigned char *vname, unsigned int *vlen,
 		const unsigned char *iname, unsigned int ilen, int cc)
@@ -1346,16 +1353,3 @@
 }
 
 #endif
-
-inline int
-ncp_strnicmp(struct nls_table *t, const unsigned char *s1,
-					const unsigned char *s2, int n)
-{
-	int i;
-
-	for (i=0; i<n; i++)
-		if (ncp_tolower(t, s1[i]) != ncp_tolower(t, s2[i]))
-			return 1;
-
-	return 0;
-}
diff -Nru a/fs/ncpfs/ncplib_kernel.h b/fs/ncpfs/ncplib_kernel.h
--- a/fs/ncpfs/ncplib_kernel.h	2004-10-18 14:56:27 -07:00
+++ b/fs/ncpfs/ncplib_kernel.h	2004-10-18 14:56:27 -07:00
@@ -71,19 +71,19 @@
 		struct nw_info_struct *target);
 int ncp_obtain_nfs_info(struct ncp_server *server, struct nw_info_struct *target);
 int ncp_get_volume_root(struct ncp_server *server, const char *volname,
-			__u32 *volume, __u32 *dirent, __u32 *dosdirent);
+			__u32 *volume, __le32 *dirent, __le32 *dosdirent);
 int ncp_lookup_volume(struct ncp_server *, const char *, struct nw_info_struct *);
 int ncp_modify_file_or_subdir_dos_info(struct ncp_server *, struct inode *,
-	 __u32, const struct nw_modify_dos_info *info);
+	 __le32, const struct nw_modify_dos_info *info);
 int ncp_modify_file_or_subdir_dos_info_path(struct ncp_server *, struct inode *,
-	 const char* path, __u32, const struct nw_modify_dos_info *info);
-int ncp_modify_nfs_info(struct ncp_server *, __u8 volnum, __u32 dirent,
+	 const char* path, __le32, const struct nw_modify_dos_info *info);
+int ncp_modify_nfs_info(struct ncp_server *, __u8 volnum, __le32 dirent,
 			__u32 mode, __u32 rdev);
 
 int ncp_del_file_or_subdir2(struct ncp_server *, struct dentry*);
 int ncp_del_file_or_subdir(struct ncp_server *, struct inode *, char *);
 int ncp_open_create_file_or_subdir(struct ncp_server *, struct inode *, char *,
-				int, __u32, int, struct ncp_entry_info *);
+				int, __le32, __le16, struct ncp_entry_info *);
 
 int ncp_initialize_search(struct ncp_server *, struct inode *,
 		      struct nw_search_sequence *target);
@@ -113,13 +113,13 @@
 #endif	/* CONFIG_NCPFS_IOCTL_LOCKING */
 
 int
-ncp_mount_subdir(struct ncp_server *, __u8, __u8, __u32,
-		 __u32* volume, __u32* dirent, __u32* dosdirent);
-int ncp_dirhandle_alloc(struct ncp_server *, __u8 vol, __u32 dirent, __u8 *dirhandle);
+ncp_mount_subdir(struct ncp_server *, __u8, __u8, __le32,
+		 __u32* volume, __le32* dirent, __le32* dosdirent);
+int ncp_dirhandle_alloc(struct ncp_server *, __u8 vol, __le32 dirent, __u8 *dirhandle);
 int ncp_dirhandle_free(struct ncp_server *, __u8 dirhandle);
 
 int ncp_create_new(struct inode *dir, struct dentry *dentry,
-                          int mode, dev_t rdev, int attributes);
+                          int mode, dev_t rdev, __le32 attributes);
 
 static inline int ncp_is_nfs_extras(struct ncp_server* server, unsigned int volnum) {
 #ifdef CONFIG_NCPFS_NFS_NS
@@ -132,8 +132,6 @@
 
 #ifdef CONFIG_NCPFS_NLS
 
-unsigned char ncp__tolower(struct nls_table *, unsigned char);
-unsigned char ncp__toupper(struct nls_table *, unsigned char);
 int ncp__io2vol(struct ncp_server *, unsigned char *, unsigned int *,
 				const unsigned char *, unsigned int, int);
 int ncp__vol2io(struct ncp_server *, unsigned char *, unsigned int *,
@@ -141,8 +139,10 @@
 
 #define NCP_ESC			':'
 #define NCP_IO_TABLE(dentry)	(NCP_SERVER((dentry)->d_inode)->nls_io)
-#define ncp_tolower(t, c)	ncp__tolower(t, c)
-#define ncp_toupper(t, c)	ncp__toupper(t, c)
+#define ncp_tolower(t, c)	nls_tolower(t, c)
+#define ncp_toupper(t, c)	nls_toupper(t, c)
+#define ncp_strnicmp(t, s1, s2, len) \
+	nls_strnicmp(t, s1, s2, len)
 #define ncp_io2vol(S,m,i,n,k,U)	ncp__io2vol(S,m,i,n,k,U)
 #define ncp_vol2io(S,m,i,n,k,U)	ncp__vol2io(S,m,i,n,k,U)
 
@@ -159,11 +159,19 @@
 #define ncp_io2vol(S,m,i,n,k,U)	ncp__io2vol(m,i,n,k,U)
 #define ncp_vol2io(S,m,i,n,k,U)	ncp__vol2io(m,i,n,k,U)
 
-#endif /* CONFIG_NCPFS_NLS */
 
-int
-ncp_strnicmp(struct nls_table *,
-		const unsigned char *, const unsigned char *, int);
+static inline int ncp_strnicmp(struct nls_table *t, const unsigned char *s1,
+		const unsigned char *s2, int len)
+{
+	while (len--) {
+		if (tolower(*s1++) != tolower(*s2++))
+			return 1;
+	}
+
+	return 0;
+}
+
+#endif /* CONFIG_NCPFS_NLS */
 
 #define NCP_GET_AGE(dentry)	(jiffies - (dentry)->d_time)
 #define NCP_MAX_AGE(server)	((server)->dentry_ttl)
diff -Nru a/fs/ncpfs/sock.c b/fs/ncpfs/sock.c
--- a/fs/ncpfs/sock.c	2004-10-18 14:56:28 -07:00
+++ b/fs/ncpfs/sock.c	2004-10-18 14:56:28 -07:00
@@ -337,7 +337,7 @@
 {
 	if (server->info_sock) {
 		struct kvec iov[2];
-		__u32 hdr[2];
+		__be32 hdr[2];
 	
 		hdr[0] = cpu_to_be32(len + 8);
 		hdr[1] = cpu_to_be32(id);
diff -Nru a/fs/ncpfs/symlink.c b/fs/ncpfs/symlink.c
--- a/fs/ncpfs/symlink.c	2004-10-18 14:57:04 -07:00
+++ b/fs/ncpfs/symlink.c	2004-10-18 14:57:04 -07:00
@@ -36,8 +36,8 @@
 /* these magic numbers must appear in the symlink file -- this makes it a bit
    more resilient against the magic attributes being set on random files. */
 
-#define NCP_SYMLINK_MAGIC0	le32_to_cpu(0x6c6d7973)     /* "symlnk->" */
-#define NCP_SYMLINK_MAGIC1	le32_to_cpu(0x3e2d6b6e)
+#define NCP_SYMLINK_MAGIC0	cpu_to_le32(0x6c6d7973)     /* "symlnk->" */
+#define NCP_SYMLINK_MAGIC1	cpu_to_le32(0x3e2d6b6e)
 
 /* ----- read a symbolic link ------------------------------------------ */
 
@@ -67,8 +67,8 @@
 
 	if (NCP_FINFO(inode)->flags & NCPI_KLUDGE_SYMLINK) {
 		if (length<NCP_MIN_SYMLINK_SIZE || 
-		    ((__u32 *)rawlink)[0]!=NCP_SYMLINK_MAGIC0 ||
-		    ((__u32 *)rawlink)[1]!=NCP_SYMLINK_MAGIC1)
+		    ((__le32 *)rawlink)[0]!=NCP_SYMLINK_MAGIC0 ||
+		    ((__le32 *)rawlink)[1]!=NCP_SYMLINK_MAGIC1)
 		    	goto failEIO;
 		link = rawlink + 8;
 		length -= 8;
@@ -110,7 +110,8 @@
 	char *rawlink;
 	int length, err, i, outlen;
 	int kludge;
-	int mode, attr;
+	int mode;
+	__le32 attr;
 	unsigned int hdr;
 
 	DPRINTK("ncp_symlink(dir=%p,dentry=%p,symname=%s)\n",dir,dentry,symname);
@@ -133,8 +134,8 @@
 	if (kludge) {
 		mode = 0;
 		attr = aSHARED | aHIDDEN;
-		((__u32 *)rawlink)[0]=NCP_SYMLINK_MAGIC0;
-		((__u32 *)rawlink)[1]=NCP_SYMLINK_MAGIC1;
+		((__le32 *)rawlink)[0]=NCP_SYMLINK_MAGIC0;
+		((__le32 *)rawlink)[1]=NCP_SYMLINK_MAGIC1;
 		hdr = 8;
 	} else {
 		mode = S_IFLNK | S_IRWXUGO;
diff -Nru a/fs/nfs/Makefile b/fs/nfs/Makefile
--- a/fs/nfs/Makefile	2004-10-18 14:56:17 -07:00
+++ b/fs/nfs/Makefile	2004-10-18 14:56:17 -07:00
@@ -9,6 +9,7 @@
 nfs-$(CONFIG_ROOT_NFS)	+= nfsroot.o mount_clnt.o      
 nfs-$(CONFIG_NFS_V3)	+= nfs3proc.o nfs3xdr.o
 nfs-$(CONFIG_NFS_V4)	+= nfs4proc.o nfs4xdr.o nfs4state.o nfs4renewd.o \
-			   idmap.o
+			   delegation.o idmap.o \
+			   callback.o callback_xdr.o callback_proc.o
 nfs-$(CONFIG_NFS_DIRECTIO) += direct.o
 nfs-objs		:= $(nfs-y)
diff -Nru a/fs/nfs/callback.c b/fs/nfs/callback.c
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/fs/nfs/callback.c	2004-10-18 14:57:23 -07:00
@@ -0,0 +1,325 @@
+/*
+ * linux/fs/nfs/callback.c
+ *
+ * Copyright (C) 2004 Trond Myklebust
+ *
+ * NFSv4 callback handling
+ */
+
+#include <linux/config.h>
+#include <linux/completion.h>
+#include <linux/ip.h>
+#include <linux/module.h>
+#include <linux/smp_lock.h>
+#include <linux/sunrpc/svc.h>
+#include <linux/sunrpc/svcsock.h>
+#include <linux/nfs_fs.h>
+#include "callback.h"
+
+#define NFSDBG_FACILITY NFSDBG_CALLBACK
+
+struct nfs_callback_data {
+	unsigned int users;
+	struct svc_serv *serv;
+	pid_t pid;
+	struct completion started;
+	struct completion stopped;
+};
+
+static struct nfs_callback_data nfs_callback_info;
+static DECLARE_MUTEX(nfs_callback_sema);
+static struct svc_program nfs4_callback_program;
+
+unsigned short nfs_callback_tcpport;
+
+/*
+ * This is the callback kernel thread.
+ */
+static void nfs_callback_svc(struct svc_rqst *rqstp)
+{
+	struct svc_serv *serv = rqstp->rq_server;
+	int err;
+
+	__module_get(THIS_MODULE);
+	lock_kernel();
+
+	nfs_callback_info.pid = current->pid;
+	daemonize("nfsv4-svc");
+	/* Process request with signals blocked, but allow SIGKILL.  */
+	allow_signal(SIGKILL);
+
+	complete(&nfs_callback_info.started);
+
+	while (nfs_callback_info.users != 0 || !signalled()) {
+		/*
+		 * Listen for a request on the socket
+		 */
+		err = svc_recv(serv, rqstp, MAX_SCHEDULE_TIMEOUT);
+		if (err == -EAGAIN || err == -EINTR)
+			continue;
+		if (err < 0) {
+			printk(KERN_WARNING
+					"%s: terminating on error %d\n",
+					__FUNCTION__, -err);
+			break;
+		}
+		dprintk("%s: request from %u.%u.%u.%u\n", __FUNCTION__,
+				NIPQUAD(rqstp->rq_addr.sin_addr.s_addr));
+		svc_process(serv, rqstp);
+	}
+
+	nfs_callback_info.pid = 0;
+	complete(&nfs_callback_info.stopped);
+	unlock_kernel();
+	module_put_and_exit(0);
+}
+
+/*
+ * Bring up the server process if it is not already up.
+ */
+int nfs_callback_up(void)
+{
+	struct svc_serv *serv;
+	struct svc_sock *svsk;
+	int ret = 0;
+
+	lock_kernel();
+	down(&nfs_callback_sema);
+	if (nfs_callback_info.users++ || nfs_callback_info.pid != 0)
+		goto out;
+	init_completion(&nfs_callback_info.started);
+	init_completion(&nfs_callback_info.stopped);
+	serv = svc_create(&nfs4_callback_program, NFS4_CALLBACK_BUFSIZE);
+	ret = -ENOMEM;
+	if (!serv)
+		goto out_err;
+	/* FIXME: We don't want to register this socket with the portmapper */
+	ret = svc_makesock(serv, IPPROTO_TCP, 0);
+	if (ret < 0)
+		goto out_destroy;
+	if (!list_empty(&serv->sv_permsocks)) {
+		svsk = list_entry(serv->sv_permsocks.next,
+				struct svc_sock, sk_list);
+		nfs_callback_tcpport = ntohs(inet_sk(svsk->sk_sk)->sport);
+		dprintk ("Callback port = 0x%x\n", nfs_callback_tcpport);
+	} else
+		BUG();
+	ret = svc_create_thread(nfs_callback_svc, serv);
+	if (ret < 0)
+		goto out_destroy;
+	nfs_callback_info.serv = serv;
+	wait_for_completion(&nfs_callback_info.started);
+out:
+	up(&nfs_callback_sema);
+	unlock_kernel();
+	return ret;
+out_destroy:
+	svc_destroy(serv);
+out_err:
+	nfs_callback_info.users--;
+	goto out;
+}
+
+/*
+ * Kill the server process if it is not already up.
+ */
+int nfs_callback_down(void)
+{
+	int ret = 0;
+
+	lock_kernel();
+	down(&nfs_callback_sema);
+	if (--nfs_callback_info.users || nfs_callback_info.pid == 0)
+		goto out;
+	kill_proc(nfs_callback_info.pid, SIGKILL, 1);
+	wait_for_completion(&nfs_callback_info.stopped);
+out:
+	up(&nfs_callback_sema);
+	unlock_kernel();
+	return ret;
+}
+
+/*
+ * AUTH_NULL authentication
+ */
+static int nfs_callback_null_accept(struct svc_rqst *rqstp, u32 *authp)
+{
+	struct kvec    *argv = &rqstp->rq_arg.head[0];
+	struct kvec    *resv = &rqstp->rq_res.head[0];
+
+	if (argv->iov_len < 3*4)
+		return SVC_GARBAGE;
+
+	if (svc_getu32(argv) != 0) {
+		dprintk("svc: bad null cred\n");
+		*authp = rpc_autherr_badcred;
+		return SVC_DENIED;
+	}
+	if (svc_getu32(argv) != RPC_AUTH_NULL || svc_getu32(argv) != 0) {
+		dprintk("svc: bad null verf\n");
+		 *authp = rpc_autherr_badverf;
+		 return SVC_DENIED;
+	}
+
+	/* Signal that mapping to nobody uid/gid is required */
+	rqstp->rq_cred.cr_uid = (uid_t) -1;
+	rqstp->rq_cred.cr_gid = (gid_t) -1;
+	rqstp->rq_cred.cr_group_info = groups_alloc(0);
+	if (rqstp->rq_cred.cr_group_info == NULL)
+		return SVC_DROP; /* kmalloc failure - client must retry */
+
+	/* Put NULL verifier */
+	svc_putu32(resv, RPC_AUTH_NULL);
+	svc_putu32(resv, 0);
+	dprintk("%s: success, returning %d!\n", __FUNCTION__, SVC_OK);
+	return SVC_OK;
+}
+
+static int nfs_callback_null_release(struct svc_rqst *rqstp)
+{
+	if (rqstp->rq_cred.cr_group_info)
+		put_group_info(rqstp->rq_cred.cr_group_info);
+	rqstp->rq_cred.cr_group_info = NULL;
+	return 0; /* don't drop */
+}
+
+static struct auth_ops nfs_callback_auth_null = {
+	.name = "null",
+	.flavour = RPC_AUTH_NULL,
+	.accept = nfs_callback_null_accept,
+	.release = nfs_callback_null_release,
+};
+
+/*
+ * AUTH_SYS authentication
+ */
+static int nfs_callback_unix_accept(struct svc_rqst *rqstp, u32 *authp)
+{
+	struct kvec    *argv = &rqstp->rq_arg.head[0];
+	struct kvec    *resv = &rqstp->rq_res.head[0];
+	struct svc_cred *cred = &rqstp->rq_cred;
+	u32 slen, i;
+	int len = argv->iov_len;
+
+	dprintk("%s: start\n", __FUNCTION__);
+	cred->cr_group_info = NULL;
+	rqstp->rq_client = NULL;
+	if ((len -= 3*4) < 0)
+		return SVC_GARBAGE;
+
+	/* Get length, time stamp and machine name */
+	svc_getu32(argv);
+	svc_getu32(argv);
+	slen = XDR_QUADLEN(ntohl(svc_getu32(argv)));
+	if (slen > 64 || (len -= (slen + 3)*4) < 0)
+		goto badcred;
+	argv->iov_base = (void*)((u32*)argv->iov_base + slen);
+	argv->iov_len -= slen*4;
+
+	cred->cr_uid = ntohl(svc_getu32(argv));
+	cred->cr_gid = ntohl(svc_getu32(argv));
+	slen = ntohl(svc_getu32(argv));
+	if (slen > 16 || (len -= (slen + 2)*4) < 0)
+		goto badcred;
+	cred->cr_group_info = groups_alloc(slen);
+	if (cred->cr_group_info == NULL)
+		return SVC_DROP;
+	for (i = 0; i < slen; i++)
+		GROUP_AT(cred->cr_group_info, i) = ntohl(svc_getu32(argv));
+
+	if (svc_getu32(argv) != RPC_AUTH_NULL || svc_getu32(argv) != 0) {
+		*authp = rpc_autherr_badverf;
+		return SVC_DENIED;
+	}
+	/* Put NULL verifier */
+	svc_putu32(resv, RPC_AUTH_NULL);
+	svc_putu32(resv, 0);
+	dprintk("%s: success, returning %d!\n", __FUNCTION__, SVC_OK);
+	return SVC_OK;
+badcred:
+	*authp = rpc_autherr_badcred;
+	return SVC_DENIED;
+}
+
+static int nfs_callback_unix_release(struct svc_rqst *rqstp)
+{
+	if (rqstp->rq_cred.cr_group_info)
+		put_group_info(rqstp->rq_cred.cr_group_info);
+	rqstp->rq_cred.cr_group_info = NULL;
+	return 0;
+}
+
+static struct auth_ops nfs_callback_auth_unix = {
+	.name = "unix",
+	.flavour = RPC_AUTH_UNIX,
+	.accept = nfs_callback_unix_accept,
+	.release = nfs_callback_unix_release,
+};
+
+/*
+ * Hook the authentication protocol
+ */
+static int nfs_callback_auth(struct svc_rqst *rqstp, u32 *authp)
+{
+	struct in_addr *addr = &rqstp->rq_addr.sin_addr;
+	struct nfs4_client *clp;
+	struct kvec *argv = &rqstp->rq_arg.head[0];
+	int flavour;
+	int retval;
+
+	/* Don't talk to strangers */
+	clp = nfs4_find_client(addr);
+	if (clp == NULL)
+		return SVC_DROP;
+	dprintk("%s: %u.%u.%u.%u NFSv4 callback!\n", __FUNCTION__, NIPQUAD(addr));
+	nfs4_put_client(clp);
+	flavour = ntohl(svc_getu32(argv));
+	switch(flavour) {
+		case RPC_AUTH_NULL:
+			if (rqstp->rq_proc != CB_NULL) {
+				*authp = rpc_autherr_tooweak;
+				retval = SVC_DENIED;
+				break;
+			}
+			rqstp->rq_authop = &nfs_callback_auth_null;
+			retval = nfs_callback_null_accept(rqstp, authp);
+			break;
+		case RPC_AUTH_UNIX:
+			/* Eat the authentication flavour */
+			rqstp->rq_authop = &nfs_callback_auth_unix;
+			retval = nfs_callback_unix_accept(rqstp, authp);
+			break;
+		default:
+			/* FIXME: need to add RPCSEC_GSS upcalls */
+#if 0
+			svc_ungetu32(argv);
+			retval = svc_authenticate(rqstp, authp);
+#else
+			*authp = rpc_autherr_rejectedcred;
+			retval = SVC_DENIED;
+#endif
+	}
+	dprintk("%s: flavour %d returning error %d\n", __FUNCTION__, flavour, retval);
+	return retval;
+}
+
+/*
+ * Define NFS4 callback program
+ */
+extern struct svc_version nfs4_callback_version1;
+
+static struct svc_version *nfs4_callback_version[] = {
+	[1] = &nfs4_callback_version1,
+};
+
+static struct svc_stat nfs4_callback_stats;
+
+static struct svc_program nfs4_callback_program = {
+	.pg_prog = NFS4_CALLBACK,			/* RPC service number */
+	.pg_nvers = ARRAY_SIZE(nfs4_callback_version),	/* Number of entries */
+	.pg_vers = nfs4_callback_version,		/* version table */
+	.pg_name = "NFSv4 callback",			/* service name */
+	.pg_class = "nfs",				/* authentication class */
+	.pg_stats = &nfs4_callback_stats,
+	.pg_authenticate = nfs_callback_auth,
+};
diff -Nru a/fs/nfs/callback.h b/fs/nfs/callback.h
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/fs/nfs/callback.h	2004-10-18 14:57:24 -07:00
@@ -0,0 +1,70 @@
+/*
+ * linux/fs/nfs/callback.h
+ *
+ * Copyright (C) 2004 Trond Myklebust
+ *
+ * NFSv4 callback definitions
+ */
+#ifndef __LINUX_FS_NFS_CALLBACK_H
+#define __LINUX_FS_NFS_CALLBACK_H
+
+#define NFS4_CALLBACK 0x40000000
+#define NFS4_CALLBACK_XDRSIZE 2048
+#define NFS4_CALLBACK_BUFSIZE (1024 + NFS4_CALLBACK_XDRSIZE)
+
+enum nfs4_callback_procnum {
+	CB_NULL = 0,
+	CB_COMPOUND = 1,
+};
+
+enum nfs4_callback_opnum {
+	OP_CB_GETATTR = 3,
+	OP_CB_RECALL  = 4,
+	OP_CB_ILLEGAL = 10044,
+};
+
+struct cb_compound_hdr_arg {
+	int taglen;
+	const char *tag;
+	unsigned int callback_ident;
+	unsigned nops;
+};
+
+struct cb_compound_hdr_res {
+	uint32_t *status;
+	int taglen;
+	const char *tag;
+	uint32_t *nops;
+};
+
+struct cb_getattrargs {
+	struct sockaddr_in *addr;
+	struct nfs_fh fh;
+	uint32_t bitmap[2];
+};
+
+struct cb_getattrres {
+	uint32_t status;
+	uint32_t bitmap[2];
+	uint64_t size;
+	uint64_t change_attr;
+	struct timespec ctime;
+	struct timespec mtime;
+};
+
+struct cb_recallargs {
+	struct sockaddr_in *addr;
+	struct nfs_fh fh;
+	nfs4_stateid stateid;
+	uint32_t truncate;
+};
+
+extern unsigned nfs4_callback_getattr(struct cb_getattrargs *args, struct cb_getattrres *res);
+extern unsigned nfs4_callback_recall(struct cb_recallargs *args, void *dummy);
+
+extern int nfs_callback_up(void);
+extern int nfs_callback_down(void);
+
+extern unsigned short nfs_callback_tcpport;
+
+#endif /* __LINUX_FS_NFS_CALLBACK_H */
diff -Nru a/fs/nfs/callback_proc.c b/fs/nfs/callback_proc.c
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/fs/nfs/callback_proc.c	2004-10-18 14:57:24 -07:00
@@ -0,0 +1,85 @@
+/*
+ * linux/fs/nfs/callback_proc.c
+ *
+ * Copyright (C) 2004 Trond Myklebust
+ *
+ * NFSv4 callback procedures
+ */
+#include <linux/config.h>
+#include <linux/nfs4.h>
+#include <linux/nfs_fs.h>
+#include "callback.h"
+#include "delegation.h"
+
+#define NFSDBG_FACILITY NFSDBG_CALLBACK
+ 
+unsigned nfs4_callback_getattr(struct cb_getattrargs *args, struct cb_getattrres *res)
+{
+	struct nfs4_client *clp;
+	struct nfs_delegation *delegation;
+	struct nfs_inode *nfsi;
+	struct inode *inode;
+	
+	res->bitmap[0] = res->bitmap[1] = 0;
+	res->status = htonl(NFS4ERR_BADHANDLE);
+	clp = nfs4_find_client(&args->addr->sin_addr);
+	if (clp == NULL)
+		goto out;
+	inode = nfs_delegation_find_inode(clp, &args->fh);
+	if (inode == NULL)
+		goto out_putclient;
+	nfsi = NFS_I(inode);
+	down_read(&nfsi->rwsem);
+	delegation = nfsi->delegation;
+	if (delegation == NULL || (delegation->type & FMODE_WRITE) == 0)
+		goto out_iput;
+	res->size = i_size_read(inode);
+	res->change_attr = NFS_CHANGE_ATTR(inode);
+	res->ctime = inode->i_ctime;
+	res->mtime = inode->i_mtime;
+	res->bitmap[0] = (FATTR4_WORD0_CHANGE|FATTR4_WORD0_SIZE) &
+		args->bitmap[0];
+	res->bitmap[1] = (FATTR4_WORD1_TIME_METADATA|FATTR4_WORD1_TIME_MODIFY) &
+		args->bitmap[1];
+	res->status = 0;
+out_iput:
+	up_read(&nfsi->rwsem);
+	iput(inode);
+out_putclient:
+	nfs4_put_client(clp);
+out:
+	dprintk("%s: exit with status = %d\n", __FUNCTION__, ntohl(res->status));
+	return res->status;
+}
+
+unsigned nfs4_callback_recall(struct cb_recallargs *args, void *dummy)
+{
+	struct nfs4_client *clp;
+	struct inode *inode;
+	unsigned res;
+	
+	res = htonl(NFS4ERR_BADHANDLE);
+	clp = nfs4_find_client(&args->addr->sin_addr);
+	if (clp == NULL)
+		goto out;
+	inode = nfs_delegation_find_inode(clp, &args->fh);
+	if (inode == NULL)
+		goto out_putclient;
+	/* Set up a helper thread to actually return the delegation */
+	switch(nfs_async_inode_return_delegation(inode, &args->stateid)) {
+		case 0:
+			res = 0;
+			break;
+		case -ENOENT:
+			res = htonl(NFS4ERR_BAD_STATEID);
+			break;
+		default:
+			res = htonl(NFS4ERR_RESOURCE);
+	}
+	iput(inode);
+out_putclient:
+	nfs4_put_client(clp);
+out:
+	dprintk("%s: exit with status = %d\n", __FUNCTION__, ntohl(res));
+	return res;
+}
diff -Nru a/fs/nfs/callback_xdr.c b/fs/nfs/callback_xdr.c
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/fs/nfs/callback_xdr.c	2004-10-18 14:57:21 -07:00
@@ -0,0 +1,481 @@
+/*
+ * linux/fs/nfs/callback_xdr.c
+ *
+ * Copyright (C) 2004 Trond Myklebust
+ *
+ * NFSv4 callback encode/decode procedures
+ */
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/sunrpc/svc.h>
+#include <linux/nfs4.h>
+#include <linux/nfs_fs.h>
+#include "callback.h"
+
+#define CB_OP_TAGLEN_MAXSZ	(512)
+#define CB_OP_HDR_RES_MAXSZ	(2 + CB_OP_TAGLEN_MAXSZ)
+#define CB_OP_GETATTR_BITMAP_MAXSZ	(4)
+#define CB_OP_GETATTR_RES_MAXSZ	(CB_OP_HDR_RES_MAXSZ + \
+				CB_OP_GETATTR_BITMAP_MAXSZ + \
+				2 + 2 + 3 + 3)
+#define CB_OP_RECALL_RES_MAXSZ	(CB_OP_HDR_RES_MAXSZ)
+
+#define NFSDBG_FACILITY NFSDBG_CALLBACK
+
+typedef unsigned (*callback_process_op_t)(void *, void *);
+typedef unsigned (*callback_decode_arg_t)(struct svc_rqst *, struct xdr_stream *, void *);
+typedef unsigned (*callback_encode_res_t)(struct svc_rqst *, struct xdr_stream *, void *);
+
+
+struct callback_op {
+	callback_process_op_t process_op;
+	callback_decode_arg_t decode_args;
+	callback_encode_res_t encode_res;
+	long res_maxsize;
+};
+
+static struct callback_op callback_ops[];
+
+static int nfs4_callback_null(struct svc_rqst *rqstp, void *argp, void *resp)
+{
+	return htonl(NFS4_OK);
+}
+
+static int nfs4_decode_void(struct svc_rqst *rqstp, uint32_t *p, void *dummy)
+{
+	return xdr_argsize_check(rqstp, p);
+}
+
+static int nfs4_encode_void(struct svc_rqst *rqstp, uint32_t *p, void *dummy)
+{
+	return xdr_ressize_check(rqstp, p);
+}
+
+static uint32_t *read_buf(struct xdr_stream *xdr, int nbytes)
+{
+	uint32_t *p;
+
+	p = xdr_inline_decode(xdr, nbytes);
+	if (unlikely(p == NULL))
+		printk(KERN_WARNING "NFSv4 callback reply buffer overflowed!\n");
+	return p;
+}
+
+static unsigned decode_string(struct xdr_stream *xdr, unsigned int *len, const char **str)
+{
+	uint32_t *p;
+
+	p = read_buf(xdr, 4);
+	if (unlikely(p == NULL))
+		return htonl(NFS4ERR_RESOURCE);
+	*len = ntohl(*p);
+
+	if (*len != 0) {
+		p = read_buf(xdr, *len);
+		if (unlikely(p == NULL))
+			return htonl(NFS4ERR_RESOURCE);
+		*str = (const char *)p;
+	} else
+		*str = NULL;
+
+	return 0;
+}
+
+static unsigned decode_fh(struct xdr_stream *xdr, struct nfs_fh *fh)
+{
+	uint32_t *p;
+
+	p = read_buf(xdr, 4);
+	if (unlikely(p == NULL))
+		return htonl(NFS4ERR_RESOURCE);
+	fh->size = ntohl(*p);
+	if (fh->size > NFS4_FHSIZE)
+		return htonl(NFS4ERR_BADHANDLE);
+	p = read_buf(xdr, fh->size);
+	if (unlikely(p == NULL))
+		return htonl(NFS4ERR_RESOURCE);
+	memcpy(&fh->data[0], p, fh->size);
+	memset(&fh->data[fh->size], 0, sizeof(fh->data) - fh->size);
+	return 0;
+}
+
+static unsigned decode_bitmap(struct xdr_stream *xdr, uint32_t *bitmap)
+{
+	uint32_t *p;
+	unsigned int attrlen;
+
+	p = read_buf(xdr, 4);
+	if (unlikely(p == NULL))
+		return htonl(NFS4ERR_RESOURCE);
+	attrlen = ntohl(*p);
+	p = read_buf(xdr, attrlen << 2);
+	if (unlikely(p == NULL))
+		return htonl(NFS4ERR_RESOURCE);
+	if (likely(attrlen > 0))
+		bitmap[0] = ntohl(*p++);
+	if (attrlen > 1)
+		bitmap[1] = ntohl(*p);
+	return 0;
+}
+
+static unsigned decode_stateid(struct xdr_stream *xdr, nfs4_stateid *stateid)
+{
+	uint32_t *p;
+
+	p = read_buf(xdr, 16);
+	if (unlikely(p == NULL))
+		return htonl(NFS4ERR_RESOURCE);
+	memcpy(stateid->data, p, 16);
+	return 0;
+}
+
+static unsigned decode_compound_hdr_arg(struct xdr_stream *xdr, struct cb_compound_hdr_arg *hdr)
+{
+	uint32_t *p;
+	unsigned int minor_version;
+	unsigned status;
+
+	status = decode_string(xdr, &hdr->taglen, &hdr->tag);
+	if (unlikely(status != 0))
+		return status;
+	/* We do not like overly long tags! */
+	if (hdr->taglen > CB_OP_TAGLEN_MAXSZ-12 || hdr->taglen < 0) {
+		printk("NFSv4 CALLBACK %s: client sent tag of length %u\n",
+				__FUNCTION__, hdr->taglen);
+		return htonl(NFS4ERR_RESOURCE);
+	}
+	p = read_buf(xdr, 12);
+	if (unlikely(p == NULL))
+		return htonl(NFS4ERR_RESOURCE);
+	minor_version = ntohl(*p++);
+	/* Check minor version is zero. */
+	if (minor_version != 0) {
+		printk(KERN_WARNING "%s: NFSv4 server callback with illegal minor version %u!\n",
+				__FUNCTION__, minor_version);
+		return htonl(NFS4ERR_MINOR_VERS_MISMATCH);
+	}
+	hdr->callback_ident = ntohl(*p++);
+	hdr->nops = ntohl(*p);
+	return 0;
+}
+
+static unsigned decode_op_hdr(struct xdr_stream *xdr, unsigned int *op)
+{
+	uint32_t *p;
+	p = read_buf(xdr, 4);
+	if (unlikely(p == NULL))
+		return htonl(NFS4ERR_RESOURCE);
+	*op = ntohl(*p);
+	return 0;
+}
+
+static unsigned decode_getattr_args(struct svc_rqst *rqstp, struct xdr_stream *xdr, struct cb_getattrargs *args)
+{
+	unsigned status;
+
+	status = decode_fh(xdr, &args->fh);
+	if (unlikely(status != 0))
+		goto out;
+	args->addr = &rqstp->rq_addr;
+	status = decode_bitmap(xdr, args->bitmap);
+out:
+	dprintk("%s: exit with status = %d\n", __FUNCTION__, status);
+	return status;
+}
+
+static unsigned decode_recall_args(struct svc_rqst *rqstp, struct xdr_stream *xdr, struct cb_recallargs *args)
+{
+	uint32_t *p;
+	unsigned status;
+
+	args->addr = &rqstp->rq_addr;
+	status = decode_stateid(xdr, &args->stateid);
+	if (unlikely(status != 0))
+		goto out;
+	p = read_buf(xdr, 4);
+	if (unlikely(p == NULL)) {
+		status = htonl(NFS4ERR_RESOURCE);
+		goto out;
+	}
+	args->truncate = ntohl(*p);
+	status = decode_fh(xdr, &args->fh);
+out:
+	dprintk("%s: exit with status = %d\n", __FUNCTION__, status);
+	return 0;
+}
+
+static unsigned encode_string(struct xdr_stream *xdr, unsigned int len, const char *str)
+{
+	uint32_t *p;
+
+	p = xdr_reserve_space(xdr, 4 + len);
+	if (unlikely(p == NULL))
+		return htonl(NFS4ERR_RESOURCE);
+	xdr_encode_opaque(p, str, len);
+	return 0;
+}
+
+#define CB_SUPPORTED_ATTR0 (FATTR4_WORD0_CHANGE|FATTR4_WORD0_SIZE)
+#define CB_SUPPORTED_ATTR1 (FATTR4_WORD1_TIME_METADATA|FATTR4_WORD1_TIME_MODIFY)
+static unsigned encode_attr_bitmap(struct xdr_stream *xdr, const uint32_t *bitmap, uint32_t **savep)
+{
+	uint32_t bm[2];
+	uint32_t *p;
+
+	bm[0] = htonl(bitmap[0] & CB_SUPPORTED_ATTR0);
+	bm[1] = htonl(bitmap[1] & CB_SUPPORTED_ATTR1);
+	if (bm[1] != 0) {
+		p = xdr_reserve_space(xdr, 16);
+		if (unlikely(p == NULL))
+			return htonl(NFS4ERR_RESOURCE);
+		*p++ = htonl(2);
+		*p++ = bm[0];
+		*p++ = bm[1];
+	} else if (bm[0] != 0) {
+		p = xdr_reserve_space(xdr, 12);
+		if (unlikely(p == NULL))
+			return htonl(NFS4ERR_RESOURCE);
+		*p++ = htonl(1);
+		*p++ = bm[0];
+	} else {
+		p = xdr_reserve_space(xdr, 8);
+		if (unlikely(p == NULL))
+			return htonl(NFS4ERR_RESOURCE);
+		*p++ = htonl(0);
+	}
+	*savep = p;
+	return 0;
+}
+
+static unsigned encode_attr_change(struct xdr_stream *xdr, const uint32_t *bitmap, uint64_t change)
+{
+	uint32_t *p;
+
+	if (!(bitmap[0] & FATTR4_WORD0_CHANGE))
+		return 0;
+	p = xdr_reserve_space(xdr, 8);
+	if (unlikely(p == 0))
+		return htonl(NFS4ERR_RESOURCE);
+	p = xdr_encode_hyper(p, change);
+	return 0;
+}
+
+static unsigned encode_attr_size(struct xdr_stream *xdr, const uint32_t *bitmap, uint64_t size)
+{
+	uint32_t *p;
+
+	if (!(bitmap[0] & FATTR4_WORD0_SIZE))
+		return 0;
+	p = xdr_reserve_space(xdr, 8);
+	if (unlikely(p == 0))
+		return htonl(NFS4ERR_RESOURCE);
+	p = xdr_encode_hyper(p, size);
+	return 0;
+}
+
+static unsigned encode_attr_time(struct xdr_stream *xdr, const struct timespec *time)
+{
+	uint32_t *p;
+
+	p = xdr_reserve_space(xdr, 12);
+	if (unlikely(p == 0))
+		return htonl(NFS4ERR_RESOURCE);
+	p = xdr_encode_hyper(p, time->tv_sec);
+	*p = htonl(time->tv_nsec);
+	return 0;
+}
+
+static unsigned encode_attr_ctime(struct xdr_stream *xdr, const uint32_t *bitmap, const struct timespec *time)
+{
+	if (!(bitmap[1] & FATTR4_WORD1_TIME_METADATA))
+		return 0;
+	return encode_attr_time(xdr,time);
+}
+
+static unsigned encode_attr_mtime(struct xdr_stream *xdr, const uint32_t *bitmap, const struct timespec *time)
+{
+	if (!(bitmap[1] & FATTR4_WORD1_TIME_MODIFY))
+		return 0;
+	return encode_attr_time(xdr,time);
+}
+
+static unsigned encode_compound_hdr_res(struct xdr_stream *xdr, struct cb_compound_hdr_res *hdr)
+{
+	unsigned status;
+
+	hdr->status = xdr_reserve_space(xdr, 4);
+	if (unlikely(hdr->status == NULL))
+		return htonl(NFS4ERR_RESOURCE);
+	status = encode_string(xdr, hdr->taglen, hdr->tag);
+	if (unlikely(status != 0))
+		return status;
+	hdr->nops = xdr_reserve_space(xdr, 4);
+	if (unlikely(hdr->nops == NULL))
+		return htonl(NFS4ERR_RESOURCE);
+	return 0;
+}
+
+static unsigned encode_op_hdr(struct xdr_stream *xdr, uint32_t op, uint32_t res)
+{
+	uint32_t *p;
+	
+	p = xdr_reserve_space(xdr, 8);
+	if (unlikely(p == NULL))
+		return htonl(NFS4ERR_RESOURCE);
+	*p++ = htonl(op);
+	*p = res;
+	return 0;
+}
+
+static unsigned encode_getattr_res(struct svc_rqst *rqstp, struct xdr_stream *xdr, const struct cb_getattrres *res)
+{
+	uint32_t *savep;
+	unsigned status = res->status;
+	
+	if (unlikely(status != 0))
+		goto out;
+	status = encode_attr_bitmap(xdr, res->bitmap, &savep);
+	if (unlikely(status != 0))
+		goto out;
+	status = encode_attr_change(xdr, res->bitmap, res->change_attr);
+	if (unlikely(status != 0))
+		goto out;
+	status = encode_attr_size(xdr, res->bitmap, res->size);
+	if (unlikely(status != 0))
+		goto out;
+	status = encode_attr_ctime(xdr, res->bitmap, &res->ctime);
+	if (unlikely(status != 0))
+		goto out;
+	status = encode_attr_mtime(xdr, res->bitmap, &res->mtime);
+	*savep = htonl((unsigned int)((char *)xdr->p - (char *)(savep+1)));
+out:
+	dprintk("%s: exit with status = %d\n", __FUNCTION__, status);
+	return status;
+}
+
+static unsigned process_op(struct svc_rqst *rqstp,
+		struct xdr_stream *xdr_in, void *argp,
+		struct xdr_stream *xdr_out, void *resp)
+{
+	struct callback_op *op;
+	unsigned int op_nr;
+	unsigned int status = 0;
+	long maxlen;
+	unsigned res;
+
+	dprintk("%s: start\n", __FUNCTION__);
+	status = decode_op_hdr(xdr_in, &op_nr);
+	if (unlikely(status != 0)) {
+		op_nr = OP_CB_ILLEGAL;
+		op = &callback_ops[0];
+	} else if (unlikely(op_nr != OP_CB_GETATTR && op_nr != OP_CB_RECALL)) {
+		op_nr = OP_CB_ILLEGAL;
+		op = &callback_ops[0];
+		status = htonl(NFS4ERR_OP_ILLEGAL);
+	} else
+		op = &callback_ops[op_nr];
+
+	maxlen = xdr_out->end - xdr_out->p;
+	if (maxlen > 0 && maxlen < PAGE_SIZE) {
+		if (likely(status == 0 && op->decode_args != NULL))
+			status = op->decode_args(rqstp, xdr_in, argp);
+		if (likely(status == 0 && op->process_op != NULL))
+			status = op->process_op(argp, resp);
+	} else
+		status = htonl(NFS4ERR_RESOURCE);
+
+	res = encode_op_hdr(xdr_out, op_nr, status);
+	if (status == 0)
+		status = res;
+	if (op->encode_res != NULL && status == 0)
+		status = op->encode_res(rqstp, xdr_out, resp);
+	dprintk("%s: done, status = %d\n", __FUNCTION__, status);
+	return status;
+}
+
+/*
+ * Decode, process and encode a COMPOUND
+ */
+static int nfs4_callback_compound(struct svc_rqst *rqstp, void *argp, void *resp)
+{
+	struct cb_compound_hdr_arg hdr_arg;
+	struct cb_compound_hdr_res hdr_res;
+	struct xdr_stream xdr_in, xdr_out;
+	uint32_t *p;
+	unsigned int status;
+	unsigned int nops = 1;
+
+	dprintk("%s: start\n", __FUNCTION__);
+
+	xdr_init_decode(&xdr_in, &rqstp->rq_arg, rqstp->rq_arg.head[0].iov_base);
+
+	p = (uint32_t*)((char *)rqstp->rq_res.head[0].iov_base + rqstp->rq_res.head[0].iov_len);
+	rqstp->rq_res.head[0].iov_len = PAGE_SIZE;
+	xdr_init_encode(&xdr_out, &rqstp->rq_res, p);
+
+	decode_compound_hdr_arg(&xdr_in, &hdr_arg);
+	hdr_res.taglen = hdr_arg.taglen;
+	hdr_res.tag = hdr_arg.tag;
+	encode_compound_hdr_res(&xdr_out, &hdr_res);
+
+	for (;;) {
+		status = process_op(rqstp, &xdr_in, argp, &xdr_out, resp);
+		if (status != 0)
+			break;
+		if (nops == hdr_arg.nops)
+			break;
+		nops++;
+	}
+	*hdr_res.status = status;
+	*hdr_res.nops = htonl(nops);
+	dprintk("%s: done, status = %u\n", __FUNCTION__, status);
+	return rpc_success;
+}
+
+/*
+ * Define NFS4 callback COMPOUND ops.
+ */
+static struct callback_op callback_ops[] = {
+	[0] = {
+		.res_maxsize = CB_OP_HDR_RES_MAXSZ,
+	},
+	[OP_CB_GETATTR] = {
+		.process_op = (callback_process_op_t)nfs4_callback_getattr,
+		.decode_args = (callback_decode_arg_t)decode_getattr_args,
+		.encode_res = (callback_encode_res_t)encode_getattr_res,
+		.res_maxsize = CB_OP_GETATTR_RES_MAXSZ,
+	},
+	[OP_CB_RECALL] = {
+		.process_op = (callback_process_op_t)nfs4_callback_recall,
+		.decode_args = (callback_decode_arg_t)decode_recall_args,
+		.res_maxsize = CB_OP_RECALL_RES_MAXSZ,
+	}
+};
+
+/*
+ * Define NFS4 callback procedures
+ */
+static struct svc_procedure nfs4_callback_procedures1[] = {
+	[CB_NULL] = {
+		.pc_func = nfs4_callback_null,
+		.pc_decode = (kxdrproc_t)nfs4_decode_void,
+		.pc_encode = (kxdrproc_t)nfs4_encode_void,
+		.pc_xdrressize = 1,
+	},
+	[CB_COMPOUND] = {
+		.pc_func = nfs4_callback_compound,
+		.pc_encode = (kxdrproc_t)nfs4_encode_void,
+		.pc_argsize = 256,
+		.pc_ressize = 256,
+		.pc_xdrressize = NFS4_CALLBACK_BUFSIZE,
+	}
+};
+
+struct svc_version nfs4_callback_version1 = {
+	.vs_vers = 1,
+	.vs_nproc = ARRAY_SIZE(nfs4_callback_procedures1),
+	.vs_proc = nfs4_callback_procedures1,
+	.vs_xdrsize = NFS4_CALLBACK_XDRSIZE,
+	.vs_dispatch = NULL,
+};
+
diff -Nru a/fs/nfs/delegation.c b/fs/nfs/delegation.c
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/fs/nfs/delegation.c	2004-10-18 14:57:24 -07:00
@@ -0,0 +1,342 @@
+/*
+ * linux/fs/nfs/delegation.c
+ *
+ * Copyright (C) 2004 Trond Myklebust
+ *
+ * NFS file delegation management
+ *
+ */
+#include <linux/config.h>
+#include <linux/completion.h>
+#include <linux/module.h>
+#include <linux/sched.h>
+#include <linux/spinlock.h>
+
+#include <linux/nfs4.h>
+#include <linux/nfs_fs.h>
+#include <linux/nfs_xdr.h>
+
+#include "delegation.h"
+
+static struct nfs_delegation *nfs_alloc_delegation(void)
+{
+	return (struct nfs_delegation *)kmalloc(sizeof(struct nfs_delegation), GFP_KERNEL);
+}
+
+static void nfs_free_delegation(struct nfs_delegation *delegation)
+{
+	if (delegation->cred)
+		put_rpccred(delegation->cred);
+	kfree(delegation);
+}
+
+static void nfs_delegation_claim_opens(struct inode *inode)
+{
+	struct nfs_inode *nfsi = NFS_I(inode);
+	struct nfs_open_context *ctx;
+	struct nfs4_state *state;
+
+again:
+	spin_lock(&inode->i_lock);
+	list_for_each_entry(ctx, &nfsi->open_files, list) {
+		state = ctx->state;
+		if (state == NULL)
+			continue;
+		if (!test_bit(NFS_DELEGATED_STATE, &state->flags))
+			continue;
+		get_nfs_open_context(ctx);
+		spin_unlock(&inode->i_lock);
+		if (nfs4_open_delegation_recall(ctx->dentry, state) < 0)
+			return;
+		put_nfs_open_context(ctx);
+		goto again;
+	}
+	spin_unlock(&inode->i_lock);
+}
+
+/*
+ * Set up a delegation on an inode
+ */
+void nfs_inode_reclaim_delegation(struct inode *inode, struct rpc_cred *cred, struct nfs_openres *res)
+{
+	struct nfs_delegation *delegation = NFS_I(inode)->delegation;
+
+	if (delegation == NULL)
+		return;
+	memcpy(delegation->stateid.data, res->delegation.data,
+			sizeof(delegation->stateid.data));
+	delegation->type = res->delegation_type;
+	delegation->maxsize = res->maxsize;
+	put_rpccred(cred);
+	delegation->cred = get_rpccred(cred);
+	delegation->flags &= ~NFS_DELEGATION_NEED_RECLAIM;
+	NFS_I(inode)->delegation_state = delegation->type;
+	smp_wmb();
+}
+
+/*
+ * Set up a delegation on an inode
+ */
+int nfs_inode_set_delegation(struct inode *inode, struct rpc_cred *cred, struct nfs_openres *res)
+{
+	struct nfs4_client *clp = NFS_SERVER(inode)->nfs4_state;
+	struct nfs_inode *nfsi = NFS_I(inode);
+	struct nfs_delegation *delegation;
+	int status = 0;
+
+	delegation = nfs_alloc_delegation();
+	if (delegation == NULL)
+		return -ENOMEM;
+	memcpy(delegation->stateid.data, res->delegation.data,
+			sizeof(delegation->stateid.data));
+	delegation->type = res->delegation_type;
+	delegation->maxsize = res->maxsize;
+	delegation->cred = get_rpccred(cred);
+	delegation->inode = inode;
+
+	spin_lock(&clp->cl_lock);
+	if (nfsi->delegation == NULL) {
+		list_add(&delegation->super_list, &clp->cl_delegations);
+		nfsi->delegation = delegation;
+		nfsi->delegation_state = delegation->type;
+		delegation = NULL;
+	} else {
+		if (memcmp(&delegation->stateid, &nfsi->delegation->stateid,
+					sizeof(delegation->stateid)) != 0 ||
+				delegation->type != nfsi->delegation->type) {
+			printk("%s: server %u.%u.%u.%u, handed out a duplicate delegation!\n",
+					__FUNCTION__, NIPQUAD(clp->cl_addr));
+			status = -EIO;
+		}
+	}
+	spin_unlock(&clp->cl_lock);
+	if (delegation != NULL)
+		kfree(delegation);
+	return status;
+}
+
+static int nfs_do_return_delegation(struct inode *inode, struct nfs_delegation *delegation)
+{
+	int res = 0;
+
+	__nfs_revalidate_inode(NFS_SERVER(inode), inode);
+
+	res = nfs4_proc_delegreturn(inode, delegation->cred, &delegation->stateid);
+	nfs_free_delegation(delegation);
+	return res;
+}
+
+/* Sync all data to disk upon delegation return */
+static void nfs_msync_inode(struct inode *inode)
+{
+	filemap_fdatawrite(inode->i_mapping);
+	nfs_wb_all(inode);
+	filemap_fdatawait(inode->i_mapping);
+}
+
+/*
+ * Basic procedure for returning a delegation to the server
+ */
+int nfs_inode_return_delegation(struct inode *inode)
+{
+	struct nfs4_client *clp = NFS_SERVER(inode)->nfs4_state;
+	struct nfs_inode *nfsi = NFS_I(inode);
+	struct nfs_delegation *delegation;
+	int res = 0;
+
+	nfs_msync_inode(inode);
+	down_read(&clp->cl_sem);
+	/* Guard against new delegated open calls */
+	down_write(&nfsi->rwsem);
+	spin_lock(&clp->cl_lock);
+	delegation = nfsi->delegation;
+	if (delegation != NULL) {
+		list_del_init(&delegation->super_list);
+		nfsi->delegation = NULL;
+		nfsi->delegation_state = 0;
+	}
+	spin_unlock(&clp->cl_lock);
+	nfs_delegation_claim_opens(inode);
+	up_write(&nfsi->rwsem);
+	up_read(&clp->cl_sem);
+	nfs_msync_inode(inode);
+
+	if (delegation != NULL)
+		res = nfs_do_return_delegation(inode, delegation);
+	return res;
+}
+
+/*
+ * Return all delegations associated to a super block
+ */
+void nfs_return_all_delegations(struct super_block *sb)
+{
+	struct nfs4_client *clp = NFS_SB(sb)->nfs4_state;
+	struct nfs_delegation *delegation;
+	struct inode *inode;
+
+	if (clp == NULL)
+		return;
+restart:
+	spin_lock(&clp->cl_lock);
+	list_for_each_entry(delegation, &clp->cl_delegations, super_list) {
+		if (delegation->inode->i_sb != sb)
+			continue;
+		inode = igrab(delegation->inode);
+		if (inode == NULL)
+			continue;
+		spin_unlock(&clp->cl_lock);
+		nfs_inode_return_delegation(inode);
+		iput(inode);
+		goto restart;
+	}
+	spin_unlock(&clp->cl_lock);
+}
+
+/*
+ * Return all delegations following an NFS4ERR_CB_PATH_DOWN error.
+ */
+void nfs_handle_cb_pathdown(struct nfs4_client *clp)
+{
+	struct nfs_delegation *delegation;
+	struct inode *inode;
+
+	if (clp == NULL)
+		return;
+restart:
+	spin_lock(&clp->cl_lock);
+	list_for_each_entry(delegation, &clp->cl_delegations, super_list) {
+		inode = igrab(delegation->inode);
+		if (inode == NULL)
+			continue;
+		spin_unlock(&clp->cl_lock);
+		nfs_inode_return_delegation(inode);
+		iput(inode);
+		goto restart;
+	}
+	spin_unlock(&clp->cl_lock);
+}
+
+struct recall_threadargs {
+	struct inode *inode;
+	struct nfs4_client *clp;
+	const nfs4_stateid *stateid;
+
+	struct completion started;
+	int result;
+};
+
+static int recall_thread(void *data)
+{
+	struct recall_threadargs *args = (struct recall_threadargs *)data;
+	struct inode *inode = igrab(args->inode);
+	struct nfs4_client *clp = NFS_SERVER(inode)->nfs4_state;
+	struct nfs_inode *nfsi = NFS_I(inode);
+	struct nfs_delegation *delegation;
+
+	daemonize("nfsv4-delegreturn");
+
+	nfs_msync_inode(inode);
+	down_read(&clp->cl_sem);
+	down_write(&nfsi->rwsem);
+	spin_lock(&clp->cl_lock);
+	delegation = nfsi->delegation;
+	if (delegation != NULL && memcmp(delegation->stateid.data,
+				args->stateid->data,
+				sizeof(delegation->stateid.data)) == 0) {
+		list_del_init(&delegation->super_list);
+		nfsi->delegation = NULL;
+		nfsi->delegation_state = 0;
+		args->result = 0;
+	} else {
+		delegation = NULL;
+		args->result = -ENOENT;
+	}
+	spin_unlock(&clp->cl_lock);
+	complete(&args->started);
+	nfs_delegation_claim_opens(inode);
+	up_write(&nfsi->rwsem);
+	up_read(&clp->cl_sem);
+	nfs_msync_inode(inode);
+
+	if (delegation != NULL)
+		nfs_do_return_delegation(inode, delegation);
+	iput(inode);
+	module_put_and_exit(0);
+}
+
+/*
+ * Asynchronous delegation recall!
+ */
+int nfs_async_inode_return_delegation(struct inode *inode, const nfs4_stateid *stateid)
+{
+	struct recall_threadargs data = {
+		.inode = inode,
+		.stateid = stateid,
+	};
+	int status;
+
+	init_completion(&data.started);
+	__module_get(THIS_MODULE);
+	status = kernel_thread(recall_thread, &data, CLONE_KERNEL);
+	if (status < 0)
+		goto out_module_put;
+	wait_for_completion(&data.started);
+	return data.result;
+out_module_put:
+	module_put(THIS_MODULE);
+	return status;
+}
+
+/*
+ * Retrieve the inode associated with a delegation
+ */
+struct inode *nfs_delegation_find_inode(struct nfs4_client *clp, const struct nfs_fh *fhandle)
+{
+	struct nfs_delegation *delegation;
+	struct inode *res = NULL;
+	spin_lock(&clp->cl_lock);
+	list_for_each_entry(delegation, &clp->cl_delegations, super_list) {
+		if (nfs_compare_fh(fhandle, &NFS_I(delegation->inode)->fh) == 0) {
+			res = igrab(delegation->inode);
+			break;
+		}
+	}
+	spin_unlock(&clp->cl_lock);
+	return res;
+}
+
+/*
+ * Mark all delegations as needing to be reclaimed
+ */
+void nfs_delegation_mark_reclaim(struct nfs4_client *clp)
+{
+	struct nfs_delegation *delegation;
+	spin_lock(&clp->cl_lock);
+	list_for_each_entry(delegation, &clp->cl_delegations, super_list)
+		delegation->flags |= NFS_DELEGATION_NEED_RECLAIM;
+	spin_unlock(&clp->cl_lock);
+}
+
+/*
+ * Reap all unclaimed delegations after reboot recovery is done
+ */
+void nfs_delegation_reap_unclaimed(struct nfs4_client *clp)
+{
+	struct nfs_delegation *delegation, *n;
+	LIST_HEAD(head);
+	spin_lock(&clp->cl_lock);
+	list_for_each_entry_safe(delegation, n, &clp->cl_delegations, super_list) {
+		if ((delegation->flags & NFS_DELEGATION_NEED_RECLAIM) == 0)
+			continue;
+		list_move(&delegation->super_list, &head);
+		NFS_I(delegation->inode)->delegation = NULL;
+		NFS_I(delegation->inode)->delegation_state = 0;
+	}
+	spin_unlock(&clp->cl_lock);
+	while(!list_empty(&head)) {
+		delegation = list_entry(head.next, struct nfs_delegation, super_list);
+		list_del(&delegation->super_list);
+		nfs_free_delegation(delegation);
+	}
+}
diff -Nru a/fs/nfs/delegation.h b/fs/nfs/delegation.h
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/fs/nfs/delegation.h	2004-10-18 14:57:21 -07:00
@@ -0,0 +1,57 @@
+/*
+ * linux/fs/nfs/delegation.h
+ *
+ * Copyright (c) Trond Myklebust
+ *
+ * Definitions pertaining to NFS delegated files
+ */
+#ifndef FS_NFS_DELEGATION_H
+#define FS_NFS_DELEGATION_H
+
+#if defined(CONFIG_NFS_V4)
+/*
+ * NFSv4 delegation
+ */
+struct nfs_delegation {
+	struct list_head super_list;
+	struct rpc_cred *cred;
+	struct inode *inode;
+	nfs4_stateid stateid;
+	int type;
+#define NFS_DELEGATION_NEED_RECLAIM 1
+	long flags;
+	loff_t maxsize;
+};
+
+int nfs_inode_set_delegation(struct inode *inode, struct rpc_cred *cred, struct nfs_openres *res);
+void nfs_inode_reclaim_delegation(struct inode *inode, struct rpc_cred *cred, struct nfs_openres *res);
+int nfs_inode_return_delegation(struct inode *inode);
+int nfs_async_inode_return_delegation(struct inode *inode, const nfs4_stateid *stateid);
+
+struct inode *nfs_delegation_find_inode(struct nfs4_client *clp, const struct nfs_fh *fhandle);
+void nfs_return_all_delegations(struct super_block *sb);
+void nfs_handle_cb_pathdown(struct nfs4_client *clp);
+
+void nfs_delegation_mark_reclaim(struct nfs4_client *clp);
+void nfs_delegation_reap_unclaimed(struct nfs4_client *clp);
+
+/* NFSv4 delegation-related procedures */
+int nfs4_proc_delegreturn(struct inode *inode, struct rpc_cred *cred, const nfs4_stateid *stateid);
+int nfs4_open_delegation_recall(struct dentry *dentry, struct nfs4_state *state);
+
+static inline int nfs_have_delegation(struct inode *inode, int flags)
+{
+	flags &= FMODE_READ|FMODE_WRITE;
+	smp_rmb();
+	if ((NFS_I(inode)->delegation_state & flags) == flags)
+		return 1;
+	return 0;
+}
+#else
+static inline int nfs_have_delegation(struct inode *inode, int flags)
+{
+	return 0;
+}
+#endif
+
+#endif
diff -Nru a/fs/nfs/dir.c b/fs/nfs/dir.c
--- a/fs/nfs/dir.c	2004-10-18 14:56:31 -07:00
+++ b/fs/nfs/dir.c	2004-10-18 14:56:31 -07:00
@@ -32,6 +32,8 @@
 #include <linux/smp_lock.h>
 #include <linux/namei.h>
 
+#include "delegation.h"
+
 #define NFS_PARANOIA 1
 /* #define NFS_DEBUG_VERBOSE 1 */
 
@@ -49,12 +51,14 @@
 static int nfs_mknod(struct inode *, struct dentry *, int, dev_t);
 static int nfs_rename(struct inode *, struct dentry *,
 		      struct inode *, struct dentry *);
+static int nfs_fsync_dir(struct file *, struct dentry *, int);
 
 struct file_operations nfs_dir_operations = {
 	.read		= generic_read_dir,
 	.readdir	= nfs_readdir,
 	.open		= nfs_opendir,
 	.release	= nfs_release,
+	.fsync		= nfs_fsync_dir,
 };
 
 struct inode_operations nfs_dir_inode_operations = {
@@ -491,6 +495,15 @@
 }
 
 /*
+ * All directory operations under NFS are synchronous, so fsync()
+ * is a dummy operation.
+ */
+int nfs_fsync_dir(struct file *filp, struct dentry *dentry, int datasync)
+{
+	return 0;
+}
+
+/*
  * A check for whether or not the parent directory has changed.
  * In the case it has, we assume that the dentries are untrustworthy
  * and may need to be looked up again.
@@ -610,7 +623,7 @@
 	verifier = nfs_save_change_attribute(dir);
 	error = nfs_cached_lookup(dir, dentry, &fhandle, &fattr);
 	if (!error) {
-		if (memcmp(NFS_FH(inode), &fhandle, sizeof(struct nfs_fh))!= 0)
+		if (nfs_compare_fh(NFS_FH(inode), &fhandle))
 			goto out_bad;
 		if (nfs_lookup_verify_inode(inode, isopen))
 			goto out_zap_parent;
@@ -623,7 +636,7 @@
 	error = NFS_PROTO(dir)->lookup(dir, &dentry->d_name, &fhandle, &fattr);
 	if (error)
 		goto out_bad;
-	if (memcmp(NFS_FH(inode), &fhandle, sizeof(struct nfs_fh))!= 0)
+	if (nfs_compare_fh(NFS_FH(inode), &fhandle))
 		goto out_bad;
 	if ((error = nfs_refresh_inode(inode, &fattr)) != 0)
 		goto out_bad;
@@ -850,22 +863,22 @@
 	unsigned long verifier;
 	int openflags, ret = 0;
 
-	/* NFS only supports OPEN for regular files */
-	if (inode && !S_ISREG(inode->i_mode))
-		goto no_open;
 	parent = dget_parent(dentry);
 	dir = parent->d_inode;
 	if (!is_atomic_open(dir, nd))
 		goto no_open;
+	/* We can't create new files in nfs_open_revalidate(), so we
+	 * optimize away revalidation of negative dentries.
+	 */
+	if (inode == NULL)
+		goto out;
+	/* NFS only supports OPEN on regular files */
+	if (!S_ISREG(inode->i_mode))
+		goto no_open;
 	openflags = nd->intent.open.flags;
-	if (openflags & O_CREAT) {
-		/* If this is a negative dentry, just drop it */
-		if (!inode)
-			goto out;
-		/* If this is exclusive open, just revalidate */
-		if (openflags & O_EXCL)
-			goto no_open;
-	}
+	/* We cannot do exclusive creation on a positive dentry */
+	if ((openflags & (O_CREAT|O_EXCL)) == (O_CREAT|O_EXCL))
+		goto no_open;
 	/* We can't create new files, or truncate existing ones here */
 	openflags &= ~(O_CREAT|O_TRUNC);
 
@@ -887,6 +900,8 @@
 	return ret;
 no_open:
 	dput(parent);
+	if (inode != NULL && nfs_have_delegation(inode, FMODE_READ))
+		return 1;
 	return nfs_lookup_revalidate(dentry, nd);
 }
 #endif /* CONFIG_NFSV4 */
@@ -982,12 +997,18 @@
 	/* We may have been initialized further down */
 	if (dentry->d_inode)
 		return 0;
-	if (fhandle->size == 0 || !(fattr->valid & NFS_ATTR_FATTR)) {
+	if (fhandle->size == 0) {
 		struct inode *dir = dentry->d_parent->d_inode;
 		error = NFS_PROTO(dir)->lookup(dir, &dentry->d_name, fhandle, fattr);
 		if (error)
 			goto out_err;
 	}
+	if (!(fattr->valid & NFS_ATTR_FATTR)) {
+		struct nfs_server *server = NFS_SB(dentry->d_sb);
+		error = server->rpc_ops->getattr(server, fhandle, fattr);
+		if (error < 0)
+			goto out_err;
+	}
 	inode = nfs_fhget(dentry->d_sb, fhandle, fattr);
 	if (inode) {
 		d_instantiate(dentry, inode);
@@ -1299,19 +1320,6 @@
 	dfprintk(VFS, "NFS: symlink(%s/%ld, %s, %s)\n", dir->i_sb->s_id,
 		dir->i_ino, dentry->d_name.name, symname);
 
-	error = -ENAMETOOLONG;
-	switch (NFS_PROTO(dir)->version) {
-		case 2:
-			if (strlen(symname) > NFS2_MAXPATHLEN)
-				goto out;
-			break;
-		case 3:
-			if (strlen(symname) > NFS3_MAXPATHLEN)
-				goto out;
-		default:
-			break;
-	}
-
 #ifdef NFS_PARANOIA
 if (dentry->d_inode)
 printk("nfs_proc_symlink: %s/%s not negative!\n",
@@ -1341,8 +1349,6 @@
 		d_drop(dentry);
 	}
 	unlock_kernel();
-
-out:
 	return error;
 }
 
@@ -1498,10 +1504,56 @@
 	return error;
 }
 
-int
-nfs_permission(struct inode *inode, int mask, struct nameidata *nd)
+int nfs_access_get_cached(struct inode *inode, struct rpc_cred *cred, struct nfs_access_entry *res)
+{
+	struct nfs_access_entry *cache = &NFS_I(inode)->cache_access;
+
+	if (cache->cred != cred
+			|| time_after(jiffies, cache->jiffies + NFS_ATTRTIMEO(inode))
+			|| (NFS_FLAGS(inode) & NFS_INO_INVALID_ATTR))
+		return -ENOENT;
+	memcpy(res, cache, sizeof(*res));
+	return 0;
+}
+
+void nfs_access_add_cache(struct inode *inode, struct nfs_access_entry *set)
+{
+	struct nfs_access_entry *cache = &NFS_I(inode)->cache_access;
+
+	if (cache->cred != set->cred) {
+		if (cache->cred)
+			put_rpccred(cache->cred);
+		cache->cred = get_rpccred(set->cred);
+	}
+	cache->jiffies = set->jiffies;
+	cache->mask = set->mask;
+}
+
+static int nfs_do_access(struct inode *inode, struct rpc_cred *cred, int mask)
+{
+	struct nfs_access_entry cache;
+	int status;
+
+	status = nfs_access_get_cached(inode, cred, &cache);
+	if (status == 0)
+		goto out;
+
+	/* Be clever: ask server to check for all possible rights */
+	cache.mask = MAY_EXEC | MAY_WRITE | MAY_READ;
+	cache.cred = cred;
+	cache.jiffies = jiffies;
+	status = NFS_PROTO(inode)->access(inode, &cache);
+	if (status != 0)
+		return status;
+	nfs_access_add_cache(inode, &cache);
+out:
+	if ((cache.mask & mask) == mask)
+		return 0;
+	return -EACCES;
+}
+
+int nfs_permission(struct inode *inode, int mask, struct nameidata *nd)
 {
-	struct nfs_access_cache *cache = &NFS_I(inode)->cache_access;
 	struct rpc_cred *cred;
 	int mode = inode->i_mode;
 	int res;
@@ -1542,39 +1594,13 @@
 		goto out_notsup;
 
 	cred = rpcauth_lookupcred(NFS_CLIENT(inode)->cl_auth, 0);
-	if (cache->cred == cred
-	    && time_before(jiffies, cache->jiffies + NFS_ATTRTIMEO(inode))
-	    && !(NFS_FLAGS(inode) & NFS_INO_INVALID_ATTR)) {
-		if (!(res = cache->err)) {
-			/* Is the mask a subset of an accepted mask? */
-			if ((cache->mask & mask) == mask)
-				goto out;
-		} else {
-			/* ...or is it a superset of a rejected mask? */
-			if ((cache->mask & mask) == cache->mask)
-				goto out;
-		}
-	}
-
-	res = NFS_PROTO(inode)->access(inode, cred, mask);
-	if (!res || res == -EACCES)
-		goto add_cache;
-out:
+	res = nfs_do_access(inode, cred, mask);
 	put_rpccred(cred);
 	unlock_kernel();
 	return res;
 out_notsup:
 	nfs_revalidate_inode(NFS_SERVER(inode), inode);
 	res = vfs_permission(inode, mask);
-	unlock_kernel();
-	return res;
-add_cache:
-	cache->jiffies = jiffies;
-	if (cache->cred)
-		put_rpccred(cache->cred);
-	cache->cred = cred;
-	cache->mask = mask;
-	cache->err = res;
 	unlock_kernel();
 	return res;
 }
diff -Nru a/fs/nfs/direct.c b/fs/nfs/direct.c
--- a/fs/nfs/direct.c	2004-10-18 14:57:03 -07:00
+++ b/fs/nfs/direct.c	2004-10-18 14:57:03 -07:00
@@ -110,7 +110,7 @@
  * nfs_direct_read_seg - Read in one iov segment.  Generate separate
  *                        read RPCs for each "rsize" bytes.
  * @inode: target inode
- * @file: target file (may be NULL)
+ * @ctx: target file open context
  * user_addr: starting address of this segment of user's buffer
  * count: size of this segment
  * file_offset: offset in file to begin the operation
@@ -118,7 +118,7 @@
  * nr_pages: size of pages array
  */
 static int
-nfs_direct_read_seg(struct inode *inode, struct file *file,
+nfs_direct_read_seg(struct inode *inode, struct nfs_open_context *ctx,
 		unsigned long user_addr, size_t count, loff_t file_offset,
 		struct page **pages, int nr_pages)
 {
@@ -127,9 +127,10 @@
 	int curpage = 0;
 	struct nfs_read_data	rdata = {
 		.inode		= inode,
+		.cred		= ctx->cred,
 		.args		= {
 			.fh		= NFS_FH(inode),
-			.lockowner	= current->files,
+			.context	= ctx,
 		},
 		.res		= {
 			.fattr		= &rdata.fattr,
@@ -151,7 +152,7 @@
 			user_addr + tot_bytes, rdata.args.pgbase, curpage);
 
 		lock_kernel();
-		result = NFS_PROTO(inode)->read(&rdata, file);
+		result = NFS_PROTO(inode)->read(&rdata);
 		unlock_kernel();
 
 		if (result <= 0) {
@@ -183,7 +184,7 @@
  * nfs_direct_read - For each iov segment, map the user's buffer
  *                   then generate read RPCs.
  * @inode: target inode
- * @file: target file (may be NULL)
+ * @ctx: target file open context
  * @iov: array of vectors that define I/O buffer
  * file_offset: offset in file to begin the operation
  * nr_segs: size of iovec array
@@ -193,7 +194,7 @@
  * server.
  */
 static ssize_t
-nfs_direct_read(struct inode *inode, struct file *file,
+nfs_direct_read(struct inode *inode, struct nfs_open_context *ctx,
 		const struct iovec *iov, loff_t file_offset,
 		unsigned long nr_segs)
 {
@@ -216,7 +217,7 @@
                         return page_count;
                 }
 
-		result = nfs_direct_read_seg(inode, file, user_addr, size,
+		result = nfs_direct_read_seg(inode, ctx, user_addr, size,
 				file_offset, pages, page_count);
 
 		nfs_free_user_pages(pages, page_count, 1);
@@ -239,7 +240,7 @@
  * nfs_direct_write_seg - Write out one iov segment.  Generate separate
  *                        write RPCs for each "wsize" bytes, then commit.
  * @inode: target inode
- * @file: target file (may be NULL)
+ * @ctx: target file open context
  * user_addr: starting address of this segment of user's buffer
  * count: size of this segment
  * file_offset: offset in file to begin the operation
@@ -247,7 +248,7 @@
  * nr_pages: size of pages array
  */
 static int
-nfs_direct_write_seg(struct inode *inode, struct file *file,
+nfs_direct_write_seg(struct inode *inode, struct nfs_open_context *ctx,
 		unsigned long user_addr, size_t count, loff_t file_offset,
 		struct page **pages, int nr_pages)
 {
@@ -257,9 +258,10 @@
 	struct nfs_writeverf first_verf;
 	struct nfs_write_data	wdata = {
 		.inode		= inode,
+		.cred		= ctx->cred,
 		.args		= {
 			.fh		= NFS_FH(inode),
-			.lockowner	= current->files,
+			.context	= ctx,
 		},
 		.res		= {
 			.fattr		= &wdata.fattr,
@@ -290,7 +292,7 @@
 			user_addr + tot_bytes, wdata.args.pgbase, curpage);
 
 		lock_kernel();
-		result = NFS_PROTO(inode)->write(&wdata, file);
+		result = NFS_PROTO(inode)->write(&wdata);
 		unlock_kernel();
 
 		if (result <= 0) {
@@ -325,7 +327,7 @@
 		wdata.args.offset = file_offset;
 
 		lock_kernel();
-		result = NFS_PROTO(inode)->commit(&wdata, file);
+		result = NFS_PROTO(inode)->commit(&wdata);
 		unlock_kernel();
 
 		if (result < 0 || memcmp(&first_verf.verifier,
@@ -349,7 +351,7 @@
  * nfs_direct_write - For each iov segment, map the user's buffer
  *                    then generate write and commit RPCs.
  * @inode: target inode
- * @file: target file (may be NULL)
+ * @ctx: target file open context
  * @iov: array of vectors that define I/O buffer
  * file_offset: offset in file to begin the operation
  * nr_segs: size of iovec array
@@ -358,8 +360,7 @@
  * that non-direct readers might access, so they will pick up these
  * writes immediately.
  */
-static ssize_t
-nfs_direct_write(struct inode *inode, struct file *file,
+static int nfs_direct_write(struct inode *inode, struct nfs_open_context *ctx,
 		const struct iovec *iov, loff_t file_offset,
 		unsigned long nr_segs)
 {
@@ -382,7 +383,7 @@
                         return page_count;
                 }
 
-		result = nfs_direct_write_seg(inode, file, user_addr, size,
+		result = nfs_direct_write_seg(inode, ctx, user_addr, size,
 				file_offset, pages, page_count);
 		nfs_free_user_pages(pages, page_count, 0);
 
@@ -414,6 +415,7 @@
 {
 	ssize_t result = -EINVAL;
 	struct file *file = iocb->ki_filp;
+	struct nfs_open_context *ctx;
 	struct dentry *dentry = file->f_dentry;
 	struct inode *inode = dentry->d_inode;
 
@@ -423,19 +425,20 @@
 	if (!is_sync_kiocb(iocb))
 		return result;
 
+	ctx = (struct nfs_open_context *)file->private_data;
 	switch (rw) {
 	case READ:
 		dprintk("NFS: direct_IO(read) (%s) off/no(%Lu/%lu)\n",
 				dentry->d_name.name, file_offset, nr_segs);
 
-		result = nfs_direct_read(inode, file, iov,
+		result = nfs_direct_read(inode, ctx, iov,
 						file_offset, nr_segs);
 		break;
 	case WRITE:
 		dprintk("NFS: direct_IO(write) (%s) off/no(%Lu/%lu)\n",
 				dentry->d_name.name, file_offset, nr_segs);
 
-		result = nfs_direct_write(inode, file, iov,
+		result = nfs_direct_write(inode, ctx, iov,
 						file_offset, nr_segs);
 		break;
 	default:
@@ -471,6 +474,8 @@
 	ssize_t retval = -EINVAL;
 	loff_t *ppos = &iocb->ki_pos;
 	struct file *file = iocb->ki_filp;
+	struct nfs_open_context *ctx =
+			(struct nfs_open_context *) file->private_data;
 	struct dentry *dentry = file->f_dentry;
 	struct address_space *mapping = file->f_mapping;
 	struct inode *inode = mapping->host;
@@ -502,7 +507,7 @@
 			goto out;
 	}
 
-	retval = nfs_direct_read(inode, file, &iov, pos, 1);
+	retval = nfs_direct_read(inode, ctx, &iov, pos, 1);
 	if (retval > 0)
 		*ppos = pos + retval;
 
@@ -542,6 +547,8 @@
 	loff_t *ppos = &iocb->ki_pos;
 	unsigned long limit = current->rlim[RLIMIT_FSIZE].rlim_cur;
 	struct file *file = iocb->ki_filp;
+	struct nfs_open_context *ctx =
+			(struct nfs_open_context *) file->private_data;
 	struct dentry *dentry = file->f_dentry;
 	struct address_space *mapping = file->f_mapping;
 	struct inode *inode = mapping->host;
@@ -589,7 +596,7 @@
 			goto out;
 	}
 
-	retval = nfs_direct_write(inode, file, &iov, pos, 1);
+	retval = nfs_direct_write(inode, ctx, &iov, pos, 1);
 	if (mapping->nrpages)
 		invalidate_inode_pages2(mapping);
 	if (retval > 0)
diff -Nru a/fs/nfs/file.c b/fs/nfs/file.c
--- a/fs/nfs/file.c	2004-10-18 14:56:33 -07:00
+++ b/fs/nfs/file.c	2004-10-18 14:56:33 -07:00
@@ -31,6 +31,8 @@
 #include <asm/uaccess.h>
 #include <asm/system.h>
 
+#include "delegation.h"
+
 #define NFSDBG_FACILITY		NFSDBG_FILE
 
 static int nfs_file_open(struct inode *, struct file *);
@@ -72,7 +74,7 @@
 
 static int nfs_check_flags(int flags)
 {
-	if (flags & (O_APPEND | O_DIRECT))
+	if ((flags & (O_APPEND | O_DIRECT)) == (O_APPEND | O_DIRECT))
 		return -EINVAL;
 
 	return 0;
@@ -89,7 +91,7 @@
 	int res;
 
 	res = nfs_check_flags(filp->f_flags);
-	if (!res)
+	if (res)
 		return res;
 
 	lock_kernel();
@@ -113,6 +115,7 @@
 static int
 nfs_file_flush(struct file *file)
 {
+	struct nfs_open_context *ctx = (struct nfs_open_context *)file->private_data;
 	struct inode	*inode = file->f_dentry->d_inode;
 	int		status;
 
@@ -124,9 +127,9 @@
 	/* Ensure that data+attribute caches are up to date after close() */
 	status = nfs_wb_all(inode);
 	if (!status) {
-		status = file->f_error;
-		file->f_error = 0;
-		if (!status)
+		status = ctx->error;
+		ctx->error = 0;
+		if (!status && !nfs_have_delegation(inode, FMODE_READ))
 			__nfs_revalidate_inode(NFS_SERVER(inode), inode);
 	}
 	unlock_kernel();
@@ -197,6 +200,7 @@
 static int
 nfs_fsync(struct file *file, struct dentry *dentry, int datasync)
 {
+	struct nfs_open_context *ctx = (struct nfs_open_context *)file->private_data;
 	struct inode *inode = dentry->d_inode;
 	int status;
 
@@ -205,8 +209,8 @@
 	lock_kernel();
 	status = nfs_wb_all(inode);
 	if (!status) {
-		status = file->f_error;
-		file->f_error = 0;
+		status = ctx->error;
+		ctx->error = 0;
 	}
 	unlock_kernel();
 	return status;
@@ -288,6 +292,90 @@
 	goto out;
 }
 
+static int do_getlk(struct file *filp, int cmd, struct file_lock *fl)
+{
+	struct inode *inode = filp->f_mapping->host;
+	int status;
+
+	lock_kernel();
+	status = NFS_PROTO(inode)->lock(filp, cmd, fl);
+	unlock_kernel();
+	return status;
+}
+
+static int do_unlk(struct file *filp, int cmd, struct file_lock *fl)
+{
+	struct inode *inode = filp->f_mapping->host;
+	sigset_t oldset;
+	int status;
+
+	rpc_clnt_sigmask(NFS_CLIENT(inode), &oldset);
+	/*
+	 * Flush all pending writes before doing anything
+	 * with locks..
+	 */
+	filemap_fdatawrite(filp->f_mapping);
+	down(&inode->i_sem);
+	nfs_wb_all(inode);
+	up(&inode->i_sem);
+	filemap_fdatawait(filp->f_mapping);
+
+	/* NOTE: special case
+	 * 	If we're signalled while cleaning up locks on process exit, we
+	 * 	still need to complete the unlock.
+	 */
+	lock_kernel();
+	status = NFS_PROTO(inode)->lock(filp, cmd, fl);
+	rpc_clnt_sigunmask(NFS_CLIENT(inode), &oldset);
+	return status;
+}
+
+static int do_setlk(struct file *filp, int cmd, struct file_lock *fl)
+{
+	struct inode *inode = filp->f_mapping->host;
+	int status;
+
+	/*
+	 * Flush all pending writes before doing anything
+	 * with locks..
+	 */
+	status = filemap_fdatawrite(filp->f_mapping);
+	if (status == 0) {
+		down(&inode->i_sem);
+		status = nfs_wb_all(inode);
+		up(&inode->i_sem);
+		if (status == 0)
+			status = filemap_fdatawait(filp->f_mapping);
+	}
+	if (status < 0)
+		return status;
+
+	lock_kernel();
+	status = NFS_PROTO(inode)->lock(filp, cmd, fl);
+	/* If we were signalled we still need to ensure that
+	 * we clean up any state on the server. We therefore
+	 * record the lock call as having succeeded in order to
+	 * ensure that locks_remove_posix() cleans it out when
+	 * the process exits.
+	 */
+	if (status == -EINTR || status == -ERESTARTSYS)
+		posix_lock_file(filp, fl);
+	unlock_kernel();
+	if (status < 0)
+		return status;
+	/*
+	 * Make sure we clear the cache whenever we try to get the lock.
+	 * This makes locking act as a cache coherency point.
+	 */
+	filemap_fdatawrite(filp->f_mapping);
+	down(&inode->i_sem);
+	nfs_wb_all(inode);	/* we may have slept */
+	up(&inode->i_sem);
+	filemap_fdatawait(filp->f_mapping);
+	nfs_zap_caches(inode);
+	return 0;
+}
+
 /*
  * Lock a (portion of) a file
  */
@@ -295,8 +383,6 @@
 nfs_lock(struct file *filp, int cmd, struct file_lock *fl)
 {
 	struct inode * inode = filp->f_mapping->host;
-	int	status = 0;
-	int	status2;
 
 	dprintk("NFS: nfs_lock(f=%s/%ld, t=%x, fl=%x, r=%Ld:%Ld)\n",
 			inode->i_sb->s_id, inode->i_ino,
@@ -314,8 +400,8 @@
 		/* Fake OK code if mounted without NLM support */
 		if (NFS_SERVER(inode)->flags & NFS_MOUNT_NONLM) {
 			if (IS_GETLK(cmd))
-				status = LOCK_USE_CLNT;
-			goto out_ok;
+				return LOCK_USE_CLNT;
+			return 0;
 		}
 	}
 
@@ -329,42 +415,9 @@
 	if (!fl->fl_owner || !(fl->fl_flags & FL_POSIX))
 		return -ENOLCK;
 
-	/*
-	 * Flush all pending writes before doing anything
-	 * with locks..
-	 */
-	status = filemap_fdatawrite(filp->f_mapping);
-	down(&inode->i_sem);
-	status2 = nfs_wb_all(inode);
-	if (!status)
-		status = status2;
-	up(&inode->i_sem);
-	status2 = filemap_fdatawait(filp->f_mapping);
-	if (!status)
-		status = status2;
-	if (status < 0)
-		return status;
-
-	lock_kernel();
-	status = NFS_PROTO(inode)->lock(filp, cmd, fl);
-	unlock_kernel();
-	if (status < 0)
-		return status;
-	
-	status = 0;
-
-	/*
-	 * Make sure we clear the cache whenever we try to get the lock.
-	 * This makes locking act as a cache coherency point.
-	 */
- out_ok:
-	if ((IS_SETLK(cmd) || IS_SETLKW(cmd)) && fl->fl_type != F_UNLCK) {
-		filemap_fdatawrite(filp->f_mapping);
-		down(&inode->i_sem);
-		nfs_wb_all(inode);      /* we may have slept */
-		up(&inode->i_sem);
-		filemap_fdatawait(filp->f_mapping);
-		nfs_zap_caches(inode);
-	}
-	return status;
+	if (IS_GETLK(cmd))
+		return do_getlk(filp, cmd, fl);
+	if (fl->fl_type == F_UNLCK)
+		return do_unlk(filp, cmd, fl);
+	return do_setlk(filp, cmd, fl);
 }
diff -Nru a/fs/nfs/inode.c b/fs/nfs/inode.c
--- a/fs/nfs/inode.c	2004-10-18 14:56:49 -07:00
+++ b/fs/nfs/inode.c	2004-10-18 14:56:49 -07:00
@@ -39,6 +39,8 @@
 #include <asm/system.h>
 #include <asm/uaccess.h>
 
+#include "delegation.h"
+
 #define NFSDBG_FACILITY		NFSDBG_VFS
 #define NFS_PARANOIA 1
 
@@ -55,9 +57,8 @@
 
 static struct inode *nfs_alloc_inode(struct super_block *sb);
 static void nfs_destroy_inode(struct inode *);
-static void nfs_write_inode(struct inode *,int);
+static int nfs_write_inode(struct inode *,int);
 static void nfs_delete_inode(struct inode *);
-static void nfs_put_super(struct super_block *);
 static void nfs_clear_inode(struct inode *);
 static void nfs_umount_begin(struct super_block *);
 static int  nfs_statfs(struct super_block *, struct kstatfs *);
@@ -68,7 +69,6 @@
 	.destroy_inode	= nfs_destroy_inode,
 	.write_inode	= nfs_write_inode,
 	.delete_inode	= nfs_delete_inode,
-	.put_super	= nfs_put_super,
 	.statfs		= nfs_statfs,
 	.clear_inode	= nfs_clear_inode,
 	.umount_begin	= nfs_umount_begin,
@@ -110,12 +110,16 @@
 	return nfs_fileid_to_ino_t(fattr->fileid);
 }
 
-static void
+static int
 nfs_write_inode(struct inode *inode, int sync)
 {
 	int flags = sync ? FLUSH_WAIT : 0;
+	int ret;
 
-	nfs_commit_inode(inode, 0, 0, flags);
+	ret = nfs_commit_inode(inode, 0, 0, flags);
+	if (ret < 0)
+		return ret;
+	return 0;
 }
 
 static void
@@ -123,8 +127,9 @@
 {
 	dprintk("NFS: delete_inode(%s/%ld)\n", inode->i_sb->s_id, inode->i_ino);
 
+	nfs_wb_all(inode);
 	/*
-	 * The following can never actually happen...
+	 * The following should never happen...
 	 */
 	if (nfs_have_writebacks(inode)) {
 		printk(KERN_ERR "nfs_delete_inode: inode %ld has pending RPC requests\n", inode->i_ino);
@@ -141,10 +146,10 @@
 nfs_clear_inode(struct inode *inode)
 {
 	struct nfs_inode *nfsi = NFS_I(inode);
-	struct rpc_cred *cred = nfsi->mm_cred;
+	struct rpc_cred *cred;
 
-	if (cred)
-		put_rpccred(cred);
+	nfs_wb_all(inode);
+	BUG_ON (!list_empty(&nfsi->open_files));
 	cred = nfsi->cache_access.cred;
 	if (cred)
 		put_rpccred(cred);
@@ -152,27 +157,6 @@
 }
 
 void
-nfs_put_super(struct super_block *sb)
-{
-	struct nfs_server *server = NFS_SB(sb);
-
-	nfs4_renewd_prepare_shutdown(server);
-
-	if (server->client != NULL)
-		rpc_shutdown_client(server->client);
-	if (server->client_sys != NULL)
-		rpc_shutdown_client(server->client_sys);
-
-	if (!(server->flags & NFS_MOUNT_NONLM))
-		lockd_down();	/* release rpc.lockd */
-	rpciod_down();		/* release rpciod */
-
-	destroy_nfsv4_state(server);
-
-	kfree(server->hostname);
-}
-
-void
 nfs_umount_begin(struct super_block *sb)
 {
 	struct nfs_server *server = NFS_SB(sb);
@@ -293,14 +277,6 @@
 		server->rsize = nfs_block_size(fsinfo.rtpref, NULL);
 	if (server->wsize == 0)
 		server->wsize = nfs_block_size(fsinfo.wtpref, NULL);
-	if (sb->s_blocksize == 0) {
-		if (fsinfo.wtmult == 0) {
-			sb->s_blocksize = 512;
-			sb->s_blocksize_bits = 9;
-		} else
-			sb->s_blocksize = nfs_block_bits(fsinfo.wtmult,
-							 &sb->s_blocksize_bits);
-	}
 
 	if (fsinfo.rtmax >= 512 && server->rsize > fsinfo.rtmax)
 		server->rsize = nfs_block_size(fsinfo.rtmax, NULL);
@@ -319,6 +295,11 @@
                 server->wsize = server->wpages << PAGE_CACHE_SHIFT;
 	}
 
+	if (sb->s_blocksize == 0)
+		sb->s_blocksize = nfs_block_bits(server->wsize,
+							 &sb->s_blocksize_bits);
+	server->wtmult = nfs_block_bits(fsinfo.wtmult, NULL);
+
 	server->dtsize = nfs_block_size(fsinfo.dtpref, NULL);
 	if (server->dtsize > PAGE_CACHE_SIZE)
 		server->dtsize = PAGE_CACHE_SIZE;
@@ -405,7 +386,6 @@
 nfs_fill_super(struct super_block *sb, struct nfs_mount_data *data, int silent)
 {
 	struct nfs_server	*server;
-	int			err = -EIO;
 	rpc_authflavor_t	authflavor;
 
 	server           = NFS_SB(sb);
@@ -424,10 +404,14 @@
 	server->acdirmin = data->acdirmin*HZ;
 	server->acdirmax = data->acdirmax*HZ;
 
+	/* Start lockd here, before we might error out */
+	if (!(server->flags & NFS_MOUNT_NONLM))
+		lockd_up();
+
 	server->namelen  = data->namlen;
 	server->hostname = kmalloc(strlen(data->hostname) + 1, GFP_KERNEL);
 	if (!server->hostname)
-		goto out_fail;
+		return -ENOMEM;
 	strcpy(server->hostname, data->hostname);
 
 	/* Check NFS protocol revision and initialize RPC op vector
@@ -438,11 +422,11 @@
 		server->caps |= NFS_CAP_READDIRPLUS;
 		if (data->version < 4) {
 			printk(KERN_NOTICE "NFS: NFSv3 not supported by mount program.\n");
-			goto out_fail;
+			return -EIO;
 		}
 #else
 		printk(KERN_NOTICE "NFS: NFSv3 not supported.\n");
-		goto out_fail;
+		return -EIO;
 #endif
 	} else {
 		server->rpc_ops = &nfs_v2_clientops;
@@ -457,30 +441,19 @@
 	/* Create RPC client handles */
 	server->client = nfs_create_client(server, data);
 	if (IS_ERR(server->client))
-		goto out_fail;
+		return PTR_ERR(server->client);
 	/* RFC 2623, sec 2.3.2 */
 	if (authflavor != RPC_AUTH_UNIX) {
 		server->client_sys = rpc_clone_client(server->client);
-		if (server->client_sys == NULL)
-			goto out_shutdown;
+		if (IS_ERR(server->client_sys))
+			return PTR_ERR(server->client_sys);
 		if (!rpcauth_create(RPC_AUTH_UNIX, server->client_sys))
-			goto out_shutdown;
+			return -ENOMEM;
 	} else {
 		atomic_inc(&server->client->cl_count);
 		server->client_sys = server->client;
 	}
 
-	/* Fire up rpciod if not yet running */
-	if (rpciod_up() != 0) {
-		printk(KERN_WARNING "NFS: couldn't start rpciod!\n");
-		goto out_shutdown;
-	}
-
-	sb->s_op = &nfs_sops;
-	err = nfs_sb_init(sb, authflavor);
-	if (err != 0)
-		goto out_noinit;
-
 	if (server->flags & NFS_MOUNT_VER3) {
 		if (server->namelen == 0 || server->namelen > NFS3_MAXNAMLEN)
 			server->namelen = NFS3_MAXNAMLEN;
@@ -489,21 +462,8 @@
 			server->namelen = NFS2_MAXNAMLEN;
 	}
 
-	/* Check whether to start the lockd process */
-	if (!(server->flags & NFS_MOUNT_NONLM))
-		lockd_up();
-	return 0;
-out_noinit:
-	rpciod_down();
-out_shutdown:
-	if (server->client)
-		rpc_shutdown_client(server->client);
-	if (server->client_sys)
-		rpc_shutdown_client(server->client_sys);
-out_fail:
-	if (server->hostname)
-		kfree(server->hostname);
-	return err;
+	sb->s_op = &nfs_sops;
+	return nfs_sb_init(sb, authflavor);
 }
 
 static int
@@ -526,6 +486,7 @@
 	if (error < 0)
 		goto out_err;
 
+	buf->f_frsize = server->wtmult;
 	buf->f_bsize = sb->s_blocksize;
 	blockbits = sb->s_blocksize_bits;
 	blockres = (1 << blockbits) - 1;
@@ -642,7 +603,7 @@
 
 	if (NFS_FILEID(inode) != fattr->fileid)
 		return 0;
-	if (memcmp(NFS_FH(inode), fh, sizeof(struct nfs_fh)) != 0)
+	if (nfs_compare_fh(NFS_FH(inode), fh))
 		return 0;
 	if (is_bad_inode(inode))
 		return 0;
@@ -653,11 +614,10 @@
 nfs_init_locked(struct inode *inode, void *opaque)
 {
 	struct nfs_find_desc	*desc = (struct nfs_find_desc *)opaque;
-	struct nfs_fh		*fh = desc->fh;
 	struct nfs_fattr	*fattr = desc->fattr;
 
 	NFS_FILEID(inode) = fattr->fileid;
-	memcpy(NFS_FH(inode), fh, sizeof(struct nfs_fh));
+	nfs_copy_fh(NFS_FH(inode), desc->fh);
 	return 0;
 }
 
@@ -859,53 +819,114 @@
 	return err;
 }
 
+struct nfs_open_context *alloc_nfs_open_context(struct dentry *dentry, struct rpc_cred *cred)
+{
+	struct nfs_open_context *ctx;
+
+	ctx = (struct nfs_open_context *)kmalloc(sizeof(*ctx), GFP_KERNEL);
+	if (ctx != NULL) {
+		atomic_set(&ctx->count, 1);
+		ctx->dentry = dget(dentry);
+		ctx->cred = get_rpccred(cred);
+		ctx->state = NULL;
+		ctx->lockowner = current->files;
+		ctx->error = 0;
+		init_waitqueue_head(&ctx->waitq);
+	}
+	return ctx;
+}
+
+struct nfs_open_context *get_nfs_open_context(struct nfs_open_context *ctx)
+{
+	if (ctx != NULL)
+		atomic_inc(&ctx->count);
+	return ctx;
+}
+
+void put_nfs_open_context(struct nfs_open_context *ctx)
+{
+	if (atomic_dec_and_test(&ctx->count)) {
+		if (ctx->state != NULL)
+			nfs4_close_state(ctx->state, ctx->mode);
+		if (ctx->cred != NULL)
+			put_rpccred(ctx->cred);
+		dput(ctx->dentry);
+		kfree(ctx);
+	}
+}
+
 /*
  * Ensure that mmap has a recent RPC credential for use when writing out
  * shared pages
  */
-void
-nfs_set_mmcred(struct inode *inode, struct rpc_cred *cred)
+void nfs_file_set_open_context(struct file *filp, struct nfs_open_context *ctx)
+{
+	struct inode *inode = filp->f_dentry->d_inode;
+	struct nfs_inode *nfsi = NFS_I(inode);
+
+	filp->private_data = get_nfs_open_context(ctx);
+	spin_lock(&inode->i_lock);
+	list_add(&ctx->list, &nfsi->open_files);
+	spin_unlock(&inode->i_lock);
+}
+
+struct nfs_open_context *nfs_find_open_context(struct inode *inode, int mode)
+{
+	struct nfs_inode *nfsi = NFS_I(inode);
+	struct nfs_open_context *pos, *ctx = NULL;
+
+	spin_lock(&inode->i_lock);
+	list_for_each_entry(pos, &nfsi->open_files, list) {
+		if ((pos->mode & mode) == mode) {
+			ctx = get_nfs_open_context(pos);
+			break;
+		}
+	}
+	spin_unlock(&inode->i_lock);
+	return ctx;
+}
+
+void nfs_file_clear_open_context(struct file *filp)
 {
-	struct rpc_cred **p = &NFS_I(inode)->mm_cred,
-			*oldcred = *p;
+	struct inode *inode = filp->f_dentry->d_inode;
+	struct nfs_open_context *ctx = (struct nfs_open_context *)filp->private_data;
 
-	*p = get_rpccred(cred);
-	if (oldcred)
-		put_rpccred(oldcred);
+	if (ctx) {
+		filp->private_data = NULL;
+		spin_lock(&inode->i_lock);
+		list_del(&ctx->list);
+		spin_unlock(&inode->i_lock);
+		put_nfs_open_context(ctx);
+	}
 }
 
 /*
- * These are probably going to contain hooks for
- * allocating and releasing RPC credentials for
- * the file. I'll have to think about Tronds patch
- * a bit more..
+ * These allocate and release file read/write context information.
  */
 int nfs_open(struct inode *inode, struct file *filp)
 {
-	struct rpc_auth *auth;
+	struct nfs_open_context *ctx;
 	struct rpc_cred *cred;
 
-	auth = NFS_CLIENT(inode)->cl_auth;
-	cred = rpcauth_lookupcred(auth, 0);
-	filp->private_data = cred;
-	if ((filp->f_mode & FMODE_WRITE) != 0) {
-		nfs_set_mmcred(inode, cred);
+	if ((cred = rpcauth_lookupcred(NFS_CLIENT(inode)->cl_auth, 0)) == NULL)
+		return -ENOMEM;
+	ctx = alloc_nfs_open_context(filp->f_dentry, cred);
+	put_rpccred(cred);
+	if (ctx == NULL)
+		return -ENOMEM;
+	ctx->mode = filp->f_mode;
+	nfs_file_set_open_context(filp, ctx);
+	put_nfs_open_context(ctx);
+	if ((filp->f_mode & FMODE_WRITE) != 0)
 		nfs_begin_data_update(inode);
-	}
 	return 0;
 }
 
 int nfs_release(struct inode *inode, struct file *filp)
 {
-	struct rpc_cred *cred;
-
-	lock_kernel();
 	if ((filp->f_mode & FMODE_WRITE) != 0)
 		nfs_end_data_update(inode);
-	cred = nfs_file_cred(filp);
-	if (cred)
-		put_rpccred(cred);
-	unlock_kernel();
+	nfs_file_clear_open_context(filp);
 	return 0;
 }
 
@@ -946,7 +967,7 @@
 
 	/* Protect against RPC races by saving the change attribute */
 	verifier = nfs_save_change_attribute(inode);
-	status = NFS_PROTO(inode)->getattr(inode, &fattr);
+	status = NFS_PROTO(inode)->getattr(server, NFS_FH(inode), &fattr);
 	if (status) {
 		dfprintk(PAGECACHE, "nfs_revalidate_inode: (%s/%Ld) getattr failed, error=%d\n",
 			 inode->i_sb->s_id,
@@ -1002,6 +1023,30 @@
 	return status;
 }
 
+int nfs_attribute_timeout(struct inode *inode)
+{
+	struct nfs_inode *nfsi = NFS_I(inode);
+
+	if (nfs_have_delegation(inode, FMODE_READ))
+		return 0;
+	return time_after(jiffies, nfsi->read_cache_jiffies+nfsi->attrtimeo);
+}
+
+/**
+ * nfs_revalidate_inode - Revalidate the inode attributes
+ * @server - pointer to nfs_server struct
+ * @inode - pointer to inode struct
+ *
+ * Updates inode attribute information by retrieving the data from the server.
+ */
+int nfs_revalidate_inode(struct nfs_server *server, struct inode *inode)
+{
+	if (!(NFS_FLAGS(inode) & (NFS_INO_INVALID_ATTR|NFS_INO_INVALID_DATA))
+			&& !nfs_attribute_timeout(inode))
+		return NFS_STALE(inode) ? -ESTALE : 0;
+	return __nfs_revalidate_inode(server, inode);
+}
+
 /**
  * nfs_begin_data_update
  * @inode - pointer to inode
@@ -1023,11 +1068,13 @@
 {
 	struct nfs_inode *nfsi = NFS_I(inode);
 
-	/* Mark the attribute cache for revalidation */
-	nfsi->flags |= NFS_INO_INVALID_ATTR;
-	/* Directories and symlinks: invalidate page cache too */
-	if (S_ISDIR(inode->i_mode) || S_ISLNK(inode->i_mode))
-		nfsi->flags |= NFS_INO_INVALID_DATA;
+	if (!nfs_have_delegation(inode, FMODE_READ)) {
+		/* Mark the attribute cache for revalidation */
+		nfsi->flags |= NFS_INO_INVALID_ATTR;
+		/* Directories and symlinks: invalidate page cache too */
+		if (S_ISDIR(inode->i_mode) || S_ISLNK(inode->i_mode))
+			nfsi->flags |= NFS_INO_INVALID_DATA;
+	}
 	nfsi->cache_change_attribute ++;
 	atomic_dec(&nfsi->data_updates);
 }
@@ -1068,6 +1115,10 @@
 	loff_t cur_size, new_isize;
 	int data_unstable;
 
+	/* Do we hold a delegation? */
+	if (nfs_have_delegation(inode, FMODE_READ))
+		return 0;
+
 	/* Are we in the process of updating data on the server? */
 	data_unstable = nfs_caches_unstable(inode);
 
@@ -1265,7 +1316,8 @@
 	if (!(S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode)
 				|| S_ISLNK(inode->i_mode)))
 		invalid &= ~NFS_INO_INVALID_DATA;
-	nfsi->flags |= invalid;
+	if (!nfs_have_delegation(inode, FMODE_READ))
+		nfsi->flags |= invalid;
 
 	return 0;
  out_changed:
@@ -1305,7 +1357,7 @@
 		return 0;
 	if (old->addr.sin_port != server->addr.sin_port)
 		return 0;
-	return !memcmp(&old->fh, &server->fh, sizeof(struct nfs_fh));
+	return !nfs_compare_fh(&old->fh, &server->fh);
 }
 
 static struct super_block *nfs_get_sb(struct file_system_type *fs_type,
@@ -1329,11 +1381,6 @@
 	/* Zero out the NFS state stuff */
 	init_nfsv4_state(server);
 
-	root = &server->fh;
-	memcpy(root, &data->root, sizeof(*root));
-	if (root->size < sizeof(root->data))
-		memset(root->data+root->size, 0, sizeof(root->data)-root->size);
-
 	if (data->version != NFS_MOUNT_VERSION) {
 		printk("nfs warning: mount version %s than kernel\n",
 			data->version < NFS_MOUNT_VERSION ? "older" : "newer");
@@ -1343,19 +1390,25 @@
 			data->bsize  = 0;
 		if (data->version < 4) {
 			data->flags &= ~NFS_MOUNT_VER3;
-			memset(root, 0, sizeof(*root));
-			root->size = NFS2_FHSIZE;
-			memcpy(root->data, data->old_root.data, NFS2_FHSIZE);
+			data->root.size = NFS2_FHSIZE;
+			memcpy(data->root.data, data->old_root.data, NFS2_FHSIZE);
 		}
 		if (data->version < 5)
 			data->flags &= ~NFS_MOUNT_SECFLAVOUR;
 	}
 
+	root = &server->fh;
+	if (data->flags & NFS_MOUNT_VER3)
+		root->size = data->root.size;
+	else
+		root->size = NFS2_FHSIZE;
 	if (root->size > sizeof(root->data)) {
 		printk("nfs_get_sb: invalid root filehandle\n");
 		kfree(server);
 		return ERR_PTR(-EINVAL);
 	}
+	memcpy(root->data, data->root.data, root->size);
+
 	/* We now require that the mount process passes the remote address */
 	memcpy(&server->addr, &data->addr, sizeof(server->addr));
 	if (server->addr.sin_addr.s_addr == INADDR_ANY) {
@@ -1373,6 +1426,13 @@
 
 	s->s_flags = flags;
 
+	/* Fire up rpciod if not yet running */
+	if (rpciod_up() != 0) {
+		printk(KERN_WARNING "NFS: couldn't start rpciod!\n");
+		kfree(server);
+		return ERR_PTR(-EIO);
+	}
+
 	error = nfs_fill_super(s, data, flags & MS_VERBOSE ? 1 : 0);
 	if (error) {
 		up_write(&s->s_umount);
@@ -1386,7 +1446,25 @@
 static void nfs_kill_super(struct super_block *s)
 {
 	struct nfs_server *server = NFS_SB(s);
+
 	kill_anon_super(s);
+
+	nfs4_renewd_prepare_shutdown(server);
+
+	if (server->client != NULL && !IS_ERR(server->client))
+		rpc_shutdown_client(server->client);
+	if (server->client_sys != NULL && !IS_ERR(server->client_sys))
+		rpc_shutdown_client(server->client_sys);
+
+	if (!(server->flags & NFS_MOUNT_NONLM))
+		lockd_down();	/* release rpc.lockd */
+
+	rpciod_down();		/* release rpciod */
+
+	destroy_nfsv4_state(server);
+
+	if (server->hostname != NULL)
+		kfree(server->hostname);
 	kfree(server);
 }
 
@@ -1402,12 +1480,12 @@
 
 static void nfs4_clear_inode(struct inode *);
 
+
 static struct super_operations nfs4_sops = { 
 	.alloc_inode	= nfs_alloc_inode,
 	.destroy_inode	= nfs_destroy_inode,
 	.write_inode	= nfs_write_inode,
 	.delete_inode	= nfs_delete_inode,
-	.put_super	= nfs_put_super,
 	.statfs		= nfs_statfs,
 	.clear_inode	= nfs4_clear_inode,
 	.umount_begin	= nfs_umount_begin,
@@ -1423,6 +1501,12 @@
 {
 	struct nfs_inode *nfsi = NFS_I(inode);
 
+	/* If we are holding a delegation, return it! */
+	if (nfsi->delegation != NULL)
+		nfs_inode_return_delegation(inode);
+	/* First call standard NFS clear_inode() code */
+	nfs_clear_inode(inode);
+	/* Now clear out any remaining state */
 	while (!list_empty(&nfsi->open_states)) {
 		struct nfs4_state *state;
 		
@@ -1437,8 +1521,6 @@
 		BUG_ON(atomic_read(&state->count) != 1);
 		nfs4_close_state(state, state->state);
 	}
-	/* Now call standard NFS clear_inode() code */
-	nfs_clear_inode(inode);
 }
 
 
@@ -1498,7 +1580,7 @@
 	clp = nfs4_get_client(&server->addr.sin_addr);
 	if (!clp) {
 		printk(KERN_WARNING "NFS: failed to create NFS4 client.\n");
-		goto out_fail;
+		return -EIO;
 	}
 
 	/* Now create transport and client */
@@ -1536,8 +1618,13 @@
 		memcpy(clp->cl_ipaddr, server->ip_addr, sizeof(clp->cl_ipaddr));
 		nfs_idmap_new(clp);
 	}
-	if (list_empty(&clp->cl_superblocks))
-		clear_bit(NFS4CLNT_OK, &clp->cl_state);
+	if (list_empty(&clp->cl_superblocks)) {
+		err = nfs4_init_client(clp);
+		if (err != 0) {
+			up_write(&clp->cl_sem);
+			goto out_fail;
+		}
+	}
 	list_add_tail(&server->nfs4_siblings, &clp->cl_superblocks);
 	clnt = rpc_clone_client(clp->cl_rpcclient);
 	if (!IS_ERR(clnt))
@@ -1547,45 +1634,29 @@
 
 	if (IS_ERR(clnt)) {
 		printk(KERN_WARNING "NFS: cannot create RPC client.\n");
-		err = PTR_ERR(clnt);
-		goto out_remove_list;
+		return PTR_ERR(clnt);
 	}
 
 	clnt->cl_intr     = (server->flags & NFS4_MOUNT_INTR) ? 1 : 0;
 	clnt->cl_softrtry = (server->flags & NFS4_MOUNT_SOFT) ? 1 : 0;
 	server->client    = clnt;
 
-	err = -ENOMEM;
 	if (server->nfs4_state->cl_idmap == NULL) {
 		printk(KERN_WARNING "NFS: failed to create idmapper.\n");
-		goto out_shutdown;
+		return -ENOMEM;
 	}
 
 	if (clnt->cl_auth->au_flavor != authflavour) {
 		if (rpcauth_create(authflavour, clnt) == NULL) {
 			printk(KERN_WARNING "NFS: couldn't create credcache!\n");
-			goto out_shutdown;
+			return -ENOMEM;
 		}
 	}
 
-	/* Fire up rpciod if not yet running */
-	if (rpciod_up() != 0) {
-		printk(KERN_WARNING "NFS: couldn't start rpciod!\n");
-		goto out_shutdown;
-	}
-
 	sb->s_op = &nfs4_sops;
 	err = nfs_sb_init(sb, authflavour);
 	if (err == 0)
 		return 0;
-	rpciod_down();
-out_shutdown:
-	rpc_shutdown_client(server->client);
-out_remove_list:
-	down_write(&server->nfs4_state->cl_sem);
-	list_del_init(&server->nfs4_siblings);
-	up_write(&server->nfs4_state->cl_sem);
-	destroy_nfsv4_state(server);
 out_fail:
 	if (clp)
 		nfs4_put_client(clp);
@@ -1691,6 +1762,13 @@
 
 	s->s_flags = flags;
 
+	/* Fire up rpciod if not yet running */
+	if (rpciod_up() != 0) {
+		printk(KERN_WARNING "NFS: couldn't start rpciod!\n");
+		s = ERR_PTR(-EIO);
+		goto out_free;
+	}
+
 	error = nfs4_fill_super(s, data, flags & MS_VERBOSE ? 1 : 0);
 	if (error) {
 		up_write(&s->s_umount);
@@ -1710,22 +1788,31 @@
 	return s;
 }
 
+static void nfs4_kill_super(struct super_block *sb)
+{
+	nfs_return_all_delegations(sb);
+	nfs_kill_super(sb);
+}
+
 static struct file_system_type nfs4_fs_type = {
 	.owner		= THIS_MODULE,
 	.name		= "nfs4",
 	.get_sb		= nfs4_get_sb,
-	.kill_sb	= nfs_kill_super,
+	.kill_sb	= nfs4_kill_super,
 	.fs_flags	= FS_ODD_RENAME|FS_REVAL_DOT|FS_BINARY_MOUNTDATA,
 };
 
-#define nfs4_zero_state(nfsi) \
+#define nfs4_init_once(nfsi) \
 	do { \
 		INIT_LIST_HEAD(&(nfsi)->open_states); \
+		nfsi->delegation = NULL; \
+		nfsi->delegation_state = 0; \
+		init_rwsem(&nfsi->rwsem); \
 	} while(0)
 #define register_nfs4fs() register_filesystem(&nfs4_fs_type)
 #define unregister_nfs4fs() unregister_filesystem(&nfs4_fs_type)
 #else
-#define nfs4_zero_state(nfsi) \
+#define nfs4_init_once(nfsi) \
 	do { } while (0)
 #define register_nfs4fs() (0)
 #define unregister_nfs4fs()
@@ -1747,8 +1834,6 @@
 	if (!nfsi)
 		return NULL;
 	nfsi->flags = 0;
-	nfsi->mm_cred = NULL;
-	nfs4_zero_state(nfsi);
 	return &nfsi->vfs_inode;
 }
 
@@ -1764,14 +1849,17 @@
 	if ((flags & (SLAB_CTOR_VERIFY|SLAB_CTOR_CONSTRUCTOR)) ==
 	    SLAB_CTOR_CONSTRUCTOR) {
 		inode_init_once(&nfsi->vfs_inode);
+		spin_lock_init(&nfsi->req_lock);
 		INIT_LIST_HEAD(&nfsi->dirty);
 		INIT_LIST_HEAD(&nfsi->commit);
+		INIT_LIST_HEAD(&nfsi->open_files);
 		INIT_RADIX_TREE(&nfsi->nfs_page_tree, GFP_ATOMIC);
 		atomic_set(&nfsi->data_updates, 0);
 		nfsi->ndirty = 0;
 		nfsi->ncommit = 0;
 		nfsi->npages = 0;
 		init_waitqueue_head(&nfsi->nfs_i_wait);
+		nfs4_init_once(nfsi);
 	}
 }
  
@@ -1779,7 +1867,7 @@
 {
 	nfs_inode_cachep = kmem_cache_create("nfs_inode_cache",
 					     sizeof(struct nfs_inode),
-					     0, SLAB_HWCACHE_ALIGN|SLAB_RECLAIM_ACCOUNT,
+					     0, SLAB_RECLAIM_ACCOUNT,
 					     init_once, NULL);
 	if (nfs_inode_cachep == NULL)
 		return -ENOMEM;
diff -Nru a/fs/nfs/mount_clnt.c b/fs/nfs/mount_clnt.c
--- a/fs/nfs/mount_clnt.c	2004-10-18 14:55:54 -07:00
+++ b/fs/nfs/mount_clnt.c	2004-10-18 14:55:54 -07:00
@@ -108,7 +108,6 @@
 {
 	struct nfs_fh *fh = res->fh;
 
-	memset((void *)fh, 0, sizeof(*fh));
 	if ((res->status = ntohl(*p++)) == 0) {
 		fh->size = NFS2_FHSIZE;
 		memcpy(fh->data, p, NFS2_FHSIZE);
@@ -121,7 +120,6 @@
 {
 	struct nfs_fh *fh = res->fh;
 
-	memset((void *)fh, 0, sizeof(*fh));
 	if ((res->status = ntohl(*p++)) == 0) {
 		int size = ntohl(*p++);
 		if (size <= NFS3_FHSIZE) {
diff -Nru a/fs/nfs/nfs2xdr.c b/fs/nfs/nfs2xdr.c
--- a/fs/nfs/nfs2xdr.c	2004-10-18 14:56:28 -07:00
+++ b/fs/nfs/nfs2xdr.c	2004-10-18 14:56:28 -07:00
@@ -57,7 +57,7 @@
 
 #define NFS_attrstat_sz		(1+NFS_fattr_sz)
 #define NFS_diropres_sz		(1+NFS_fhandle_sz+NFS_fattr_sz)
-#define NFS_readlinkres_sz	(1)
+#define NFS_readlinkres_sz	(2)
 #define NFS_readres_sz		(1+NFS_fattr_sz+1)
 #define NFS_writeres_sz         (NFS_attrstat_sz)
 #define NFS_stat_sz		(1)
@@ -77,8 +77,6 @@
 static inline u32 *
 xdr_decode_fhandle(u32 *p, struct nfs_fh *fhandle)
 {
-	/* Zero handle first to allow comparisons */
-	memset(fhandle, 0, sizeof(*fhandle));
 	/* NFSv2 handles have a fixed length */
 	fhandle->size = NFS2_FHSIZE;
 	memcpy(fhandle->data, p, NFS2_FHSIZE);
@@ -95,6 +93,23 @@
 }
 
 static inline u32*
+xdr_encode_current_server_time(u32 *p, struct timespec *timep)
+{
+	/*
+	 * Passing the invalid value useconds=1000000 is a
+	 * Sun convention for "set to current server time".
+	 * It's needed to make permissions checks for the
+	 * "touch" program across v2 mounts to Solaris and
+	 * Irix boxes work correctly. See description of
+	 * sattr in section 6.1 of "NFS Illustrated" by
+	 * Brent Callaghan, Addison-Wesley, ISBN 0-201-32750-5
+	 */
+	*p++ = htonl(timep->tv_sec);
+	*p++ = htonl(1000000);
+	return p;
+}
+
+static inline u32*
 xdr_decode_time(u32 *p, struct timespec *timep)
 {
 	timep->tv_sec = ntohl(*p++);
@@ -142,15 +157,19 @@
 	SATTR(p, attr, ATTR_GID, ia_gid);
 	SATTR(p, attr, ATTR_SIZE, ia_size);
 
-	if (attr->ia_valid & (ATTR_ATIME|ATTR_ATIME_SET)) {
+	if (attr->ia_valid & ATTR_ATIME_SET) {
 		p = xdr_encode_time(p, &attr->ia_atime);
+	} else if (attr->ia_valid & ATTR_ATIME) {
+		p = xdr_encode_current_server_time(p, &attr->ia_atime);
 	} else {
 		*p++ = ~(u32) 0;
 		*p++ = ~(u32) 0;
 	}
 
-	if (attr->ia_valid & (ATTR_MTIME|ATTR_MTIME_SET)) {
+	if (attr->ia_valid & ATTR_MTIME_SET) {
 		p = xdr_encode_time(p, &attr->ia_mtime);
+	} else if (attr->ia_valid & ATTR_MTIME) {
+		p = xdr_encode_current_server_time(p, &attr->ia_mtime);
 	} else {
 		*p++ = ~(u32) 0;	
 		*p++ = ~(u32) 0;
@@ -511,7 +530,6 @@
 nfs_xdr_readlinkargs(struct rpc_rqst *req, u32 *p, struct nfs_readlinkargs *args)
 {
 	struct rpc_auth *auth = req->rq_task->tk_auth;
-	unsigned int count = args->count - 5;
 	unsigned int replen;
 
 	p = xdr_encode_fhandle(p, args->fh);
@@ -519,7 +537,7 @@
 
 	/* Inline the page array */
 	replen = (RPC_REPHDRSIZE + auth->au_rslack + NFS_readlinkres_sz) << 2;
-	xdr_inline_pages(&req->rq_rcv_buf, replen, args->pages, 0, count);
+	xdr_inline_pages(&req->rq_rcv_buf, replen, args->pages, args->pgbase, args->pglen);
 	return 0;
 }
 
@@ -531,32 +549,38 @@
 {
 	struct xdr_buf *rcvbuf = &req->rq_rcv_buf;
 	struct kvec *iov = rcvbuf->head;
-	unsigned int hdrlen;
-	u32	*strlen, len;
-	char	*string;
+	int hdrlen, len, recvd;
+	char	*kaddr;
 	int	status;
 
 	if ((status = ntohl(*p++)))
 		return -nfs_stat_to_errno(status);
+	/* Convert length of symlink */
+	len = ntohl(*p++);
+	if (len >= rcvbuf->page_len || len <= 0) {
+		dprintk(KERN_WARNING "nfs: server returned giant symlink!\n");
+		return -ENAMETOOLONG;
+	}
 	hdrlen = (u8 *) p - (u8 *) iov->iov_base;
-	if (iov->iov_len > hdrlen) {
+	if (iov->iov_len < hdrlen) {
+		printk(KERN_WARNING "NFS: READLINK reply header overflowed:"
+				"length %d > %Zu\n", hdrlen, iov->iov_len);
+		return -errno_NFSERR_IO;
+	} else if (iov->iov_len != hdrlen) {
 		dprintk("NFS: READLINK header is short. iovec will be shifted.\n");
 		xdr_shift_buf(rcvbuf, iov->iov_len - hdrlen);
 	}
-
-	strlen = (u32*)kmap_atomic(rcvbuf->pages[0], KM_USER0);
-	/* Convert length of symlink */
-	len = ntohl(*strlen);
-	if (len > rcvbuf->page_len) {
-		dprintk(KERN_WARNING "nfs: server returned giant symlink!\n");
-		kunmap_atomic(strlen, KM_USER0);
-		return -ENAMETOOLONG;
+	recvd = req->rq_rcv_buf.len - hdrlen;
+	if (recvd < len) {
+		printk(KERN_WARNING "NFS: server cheating in readlink reply: "
+				"count %u > recvd %u\n", len, recvd);
+		return -EIO;
 	}
-	*strlen = len;
+
 	/* NULL terminate the string we got */
-	string = (char *)(strlen + 1);
-	string[len] = '\0';
-	kunmap_atomic(strlen, KM_USER0);
+	kaddr = (char *)kmap_atomic(rcvbuf->pages[0], KM_USER0);
+	kaddr[len+rcvbuf->page_base] = '\0';
+	kunmap_atomic(kaddr, KM_USER0);
 	return 0;
 }
 
diff -Nru a/fs/nfs/nfs3proc.c b/fs/nfs/nfs3proc.c
--- a/fs/nfs/nfs3proc.c	2004-10-18 14:56:31 -07:00
+++ b/fs/nfs/nfs3proc.c	2004-10-18 14:56:31 -07:00
@@ -68,18 +68,6 @@
 	return 1;
 }
 
-static struct rpc_cred *
-nfs_cred(struct inode *inode, struct file *filp)
-{
-	struct rpc_cred *cred = NULL;
-
-	if (filp)
-		cred = (struct rpc_cred *)filp->private_data;
-	if (!cred)
-		cred = NFS_I(inode)->mm_cred;
-	return cred;
-}
-
 /*
  * Bare-bones access to getattr: this is for nfs_read_super.
  */
@@ -104,14 +92,15 @@
  * One function for each procedure in the NFS protocol.
  */
 static int
-nfs3_proc_getattr(struct inode *inode, struct nfs_fattr *fattr)
+nfs3_proc_getattr(struct nfs_server *server, struct nfs_fh *fhandle,
+		struct nfs_fattr *fattr)
 {
 	int	status;
 
 	dprintk("NFS call  getattr\n");
 	fattr->valid = 0;
-	status = rpc_call(NFS_CLIENT(inode), NFS3PROC_GETATTR,
-			  NFS_FH(inode), fattr, 0);
+	status = rpc_call(server->client, NFS3PROC_GETATTR,
+			  fhandle, fattr, 0);
 	dprintk("NFS reply getattr\n");
 	return status;
 }
@@ -164,8 +153,7 @@
 	return status;
 }
 
-static int
-nfs3_proc_access(struct inode *inode, struct rpc_cred *cred, int mode)
+static int nfs3_proc_access(struct inode *inode, struct nfs_access_entry *entry)
 {
 	struct nfs_fattr	fattr;
 	struct nfs3_accessargs	arg = {
@@ -178,9 +166,10 @@
 		.rpc_proc	= &nfs3_procedures[NFS3PROC_ACCESS],
 		.rpc_argp	= &arg,
 		.rpc_resp	= &res,
-		.rpc_cred	= cred
+		.rpc_cred	= entry->cred
 	};
-	int	status;
+	int mode = entry->mask;
+	int status;
 
 	dprintk("NFS call  access\n");
 	fattr.valid = 0;
@@ -200,20 +189,27 @@
 	}
 	status = rpc_call_sync(NFS_CLIENT(inode), &msg, 0);
 	nfs_refresh_inode(inode, &fattr);
-	dprintk("NFS reply access\n");
-
-	if (status == 0 && (arg.access & res.access) != arg.access)
-		status = -EACCES;
+	if (status == 0) {
+		entry->mask = 0;
+		if (res.access & NFS3_ACCESS_READ)
+			entry->mask |= MAY_READ;
+		if (res.access & (NFS3_ACCESS_MODIFY | NFS3_ACCESS_EXTEND | NFS3_ACCESS_DELETE))
+			entry->mask |= MAY_WRITE;
+		if (res.access & (NFS3_ACCESS_LOOKUP|NFS3_ACCESS_EXECUTE))
+			entry->mask |= MAY_EXEC;
+	}
+	dprintk("NFS reply access, status = %d\n", status);
 	return status;
 }
 
-static int
-nfs3_proc_readlink(struct inode *inode, struct page *page)
+static int nfs3_proc_readlink(struct inode *inode, struct page *page,
+		unsigned int pgbase, unsigned int pglen)
 {
 	struct nfs_fattr	fattr;
 	struct nfs3_readlinkargs args = {
 		.fh		= NFS_FH(inode),
-		.count		= PAGE_CACHE_SIZE,
+		.pgbase		= pgbase,
+		.pglen		= pglen,
 		.pages		= &page
 	};
 	int			status;
@@ -227,8 +223,7 @@
 	return status;
 }
 
-static int
-nfs3_proc_read(struct nfs_read_data *rdata, struct file *filp)
+static int nfs3_proc_read(struct nfs_read_data *rdata)
 {
 	int			flags = rdata->flags;
 	struct inode *		inode = rdata->inode;
@@ -237,13 +232,13 @@
 		.rpc_proc	= &nfs3_procedures[NFS3PROC_READ],
 		.rpc_argp	= &rdata->args,
 		.rpc_resp	= &rdata->res,
+		.rpc_cred	= rdata->cred,
 	};
 	int			status;
 
 	dprintk("NFS call  read %d @ %Ld\n", rdata->args.count,
 			(long long) rdata->args.offset);
 	fattr->valid = 0;
-	msg.rpc_cred = nfs_cred(inode, filp);
 	status = rpc_call_sync(NFS_CLIENT(inode), &msg, flags);
 	if (status >= 0)
 		nfs_refresh_inode(inode, fattr);
@@ -251,8 +246,7 @@
 	return status;
 }
 
-static int
-nfs3_proc_write(struct nfs_write_data *wdata, struct file *filp)
+static int nfs3_proc_write(struct nfs_write_data *wdata)
 {
 	int			rpcflags = wdata->flags;
 	struct inode *		inode = wdata->inode;
@@ -261,13 +255,13 @@
 		.rpc_proc	= &nfs3_procedures[NFS3PROC_WRITE],
 		.rpc_argp	= &wdata->args,
 		.rpc_resp	= &wdata->res,
+		.rpc_cred	= wdata->cred,
 	};
 	int			status;
 
 	dprintk("NFS call  write %d @ %Ld\n", wdata->args.count,
 			(long long) wdata->args.offset);
 	fattr->valid = 0;
-	msg.rpc_cred = nfs_cred(inode, filp);
 	status = rpc_call_sync(NFS_CLIENT(inode), &msg, rpcflags);
 	if (status >= 0)
 		nfs_refresh_inode(inode, fattr);
@@ -275,8 +269,7 @@
 	return status < 0? status : wdata->res.count;
 }
 
-static int
-nfs3_proc_commit(struct nfs_write_data *cdata, struct file *filp)
+static int nfs3_proc_commit(struct nfs_write_data *cdata)
 {
 	struct inode *		inode = cdata->inode;
 	struct nfs_fattr *	fattr = cdata->res.fattr;
@@ -284,13 +277,13 @@
 		.rpc_proc	= &nfs3_procedures[NFS3PROC_COMMIT],
 		.rpc_argp	= &cdata->args,
 		.rpc_resp	= &cdata->res,
+		.rpc_cred	= cdata->cred,
 	};
 	int			status;
 
 	dprintk("NFS call  commit %d @ %Ld\n", cdata->args.count,
 			(long long) cdata->args.offset);
 	fattr->valid = 0;
-	msg.rpc_cred = nfs_cred(inode, filp);
 	status = rpc_call_sync(NFS_CLIENT(inode), &msg, 0);
 	if (status >= 0)
 		nfs_refresh_inode(inode, fattr);
@@ -425,20 +418,21 @@
 static int
 nfs3_proc_unlink_setup(struct rpc_message *msg, struct dentry *dir, struct qstr *name)
 {
-	struct nfs3_diropargs	*arg;
-	struct nfs_fattr	*res;
+	struct unlinkxdr {
+		struct nfs3_diropargs arg;
+		struct nfs_fattr res;
+	} *ptr;
 
-	arg = (struct nfs3_diropargs *)kmalloc(sizeof(*arg)+sizeof(*res), GFP_KERNEL);
-	if (!arg)
+	ptr = (struct unlinkxdr *)kmalloc(sizeof(*ptr), GFP_KERNEL);
+	if (!ptr)
 		return -ENOMEM;
-	res = (struct nfs_fattr*)(arg + 1);
-	arg->fh = NFS_FH(dir->d_inode);
-	arg->name = name->name;
-	arg->len = name->len;
-	res->valid = 0;
+	ptr->arg.fh = NFS_FH(dir->d_inode);
+	ptr->arg.name = name->name;
+	ptr->arg.len = name->len;
+	ptr->res.valid = 0;
 	msg->rpc_proc = &nfs3_procedures[NFS3PROC_REMOVE];
-	msg->rpc_argp = arg;
-	msg->rpc_resp = res;
+	msg->rpc_argp = &ptr->arg;
+	msg->rpc_resp = &ptr->res;
 	return 0;
 }
 
@@ -534,6 +528,8 @@
 	};
 	int			status;
 
+	if (path->len > NFS3_MAXPATHLEN)
+		return -ENAMETOOLONG;
 	dprintk("NFS call  symlink %s -> %s\n", name->name, path->name);
 	dir_attr.valid = 0;
 	fattr->valid = 0;
@@ -832,27 +828,6 @@
 	rpc_call_setup(task, &msg, 0);
 }
 
-/*
- * Set up the nfspage struct with the right credentials
- */
-void
-nfs3_request_init(struct nfs_page *req, struct file *filp)
-{
-	req->wb_cred = get_rpccred(nfs_cred(req->wb_inode, filp));
-}
-
-static int
-nfs3_request_compatible(struct nfs_page *req, struct file *filp, struct page *page)
-{
-	if (req->wb_file != filp)
-		return 0;
-	if (req->wb_page != page)
-		return 0;
-	if (req->wb_cred != nfs_file_cred(filp))
-		return 0;
-	return 1;
-}
-
 static int
 nfs3_proc_lock(struct file *filp, int cmd, struct file_lock *fl)
 {
@@ -892,7 +867,5 @@
 	.commit_setup	= nfs3_proc_commit_setup,
 	.file_open	= nfs_open,
 	.file_release	= nfs_release,
-	.request_init	= nfs3_request_init,
-	.request_compatible = nfs3_request_compatible,
 	.lock		= nfs3_proc_lock,
 };
diff -Nru a/fs/nfs/nfs3xdr.c b/fs/nfs/nfs3xdr.c
--- a/fs/nfs/nfs3xdr.c	2004-10-18 14:57:05 -07:00
+++ b/fs/nfs/nfs3xdr.c	2004-10-18 14:57:05 -07:00
@@ -67,7 +67,7 @@
 #define NFS3_wccstat_sz		(1+NFS3_wcc_data_sz)
 #define NFS3_lookupres_sz	(1+NFS3_fh_sz+(2 * NFS3_post_op_attr_sz))
 #define NFS3_accessres_sz	(1+NFS3_post_op_attr_sz+1)
-#define NFS3_readlinkres_sz	(1+NFS3_post_op_attr_sz)
+#define NFS3_readlinkres_sz	(1+NFS3_post_op_attr_sz+1)
 #define NFS3_readres_sz		(1+NFS3_post_op_attr_sz+3)
 #define NFS3_writeres_sz	(1+NFS3_wcc_data_sz+4)
 #define NFS3_createres_sz	(1+NFS3_fh_sz+NFS3_post_op_attr_sz+NFS3_wcc_data_sz)
@@ -109,10 +109,6 @@
 static inline u32 *
 xdr_decode_fhandle(u32 *p, struct nfs_fh *fh)
 {
-	/*
-	 * Zero all nonused bytes
-	 */
-	memset((u8 *)fh, 0, sizeof(*fh));
 	if ((fh->size = ntohl(*p++)) <= NFS3_FHSIZE) {
 		memcpy(fh->data, p, fh->size);
 		return p + XDR_QUADLEN(fh->size);
@@ -702,7 +698,6 @@
 nfs3_xdr_readlinkargs(struct rpc_rqst *req, u32 *p, struct nfs3_readlinkargs *args)
 {
 	struct rpc_auth *auth = req->rq_task->tk_auth;
-	unsigned int count = args->count - 5;
 	unsigned int replen;
 
 	p = xdr_encode_fhandle(p, args->fh);
@@ -710,7 +705,7 @@
 
 	/* Inline the page array */
 	replen = (RPC_REPHDRSIZE + auth->au_rslack + NFS3_readlinkres_sz) << 2;
-	xdr_inline_pages(&req->rq_rcv_buf, replen, args->pages, 0, count);
+	xdr_inline_pages(&req->rq_rcv_buf, replen, args->pages, args->pgbase, args->pglen);
 	return 0;
 }
 
@@ -722,9 +717,8 @@
 {
 	struct xdr_buf *rcvbuf = &req->rq_rcv_buf;
 	struct kvec *iov = rcvbuf->head;
-	unsigned int hdrlen;
-	u32	*strlen, len;
-	char	*string;
+	int hdrlen, len, recvd;
+	char	*kaddr;
 	int	status;
 
 	status = ntohl(*p++);
@@ -733,25 +727,33 @@
 	if (status != 0)
 		return -nfs_stat_to_errno(status);
 
+	/* Convert length of symlink */
+	len = ntohl(*p++);
+	if (len >= rcvbuf->page_len || len <= 0) {
+		dprintk(KERN_WARNING "nfs: server returned giant symlink!\n");
+		return -ENAMETOOLONG;
+	}
+
 	hdrlen = (u8 *) p - (u8 *) iov->iov_base;
-	if (iov->iov_len > hdrlen) {
+	if (iov->iov_len < hdrlen) {
+		printk(KERN_WARNING "NFS: READLINK reply header overflowed:"
+				"length %d > %Zu\n", hdrlen, iov->iov_len);
+		return -errno_NFSERR_IO;
+	} else if (iov->iov_len != hdrlen) {
 		dprintk("NFS: READLINK header is short. iovec will be shifted.\n");
 		xdr_shift_buf(rcvbuf, iov->iov_len - hdrlen);
 	}
-
-	strlen = (u32*)kmap_atomic(rcvbuf->pages[0], KM_USER0);
-	/* Convert length of symlink */
-	len = ntohl(*strlen);
-	if (len > rcvbuf->page_len) {
-		dprintk(KERN_WARNING "nfs: server returned giant symlink!\n");
-		kunmap_atomic(strlen, KM_USER0);
-		return -ENAMETOOLONG;
+	recvd = req->rq_rcv_buf.len - hdrlen;
+	if (recvd < len) {
+		printk(KERN_WARNING "NFS: server cheating in readlink reply: "
+				"count %u > recvd %u\n", len, recvd);
+		return -EIO;
 	}
-	*strlen = len;
+
 	/* NULL terminate the string we got */
-	string = (char *)(strlen + 1);
-	string[len] = '\0';
-	kunmap_atomic(strlen, KM_USER0);
+	kaddr = (char*)kmap_atomic(rcvbuf->pages[0], KM_USER0);
+	kaddr[len+rcvbuf->page_base] = '\0';
+	kunmap_atomic(kaddr, KM_USER0);
 	return 0;
 }
 
diff -Nru a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c
--- a/fs/nfs/nfs4proc.c	2004-10-18 14:56:49 -07:00
+++ b/fs/nfs/nfs4proc.c	2004-10-18 14:56:49 -07:00
@@ -47,12 +47,16 @@
 #include <linux/smp_lock.h>
 #include <linux/namei.h>
 
+#include "delegation.h"
+
 #define NFSDBG_FACILITY		NFSDBG_PROC
 
-#define NFS4_POLL_RETRY_TIME	(15*HZ)
+#define NFS4_POLL_RETRY_MIN	(1*HZ)
+#define NFS4_POLL_RETRY_MAX	(15*HZ)
 
 static int nfs4_do_fsinfo(struct nfs_server *, struct nfs_fh *, struct nfs_fsinfo *);
 static int nfs4_async_handle_error(struct rpc_task *, struct nfs_server *);
+static int _nfs4_proc_access(struct inode *inode, struct nfs_access_entry *entry);
 extern u32 *nfs4_decode_dirent(u32 *p, struct nfs_entry *entry, int plus);
 extern struct rpc_procinfo nfs4_procedures[];
 
@@ -189,53 +193,296 @@
  * 	reclaim state on the server after a reboot.
  * 	Assumes caller is holding the sp->so_sem
  */
-int
-nfs4_open_reclaim(struct nfs4_state_owner *sp, struct nfs4_state *state)
+static int _nfs4_open_reclaim(struct nfs4_state_owner *sp, struct nfs4_state *state)
 {
 	struct inode *inode = state->inode;
 	struct nfs_server *server = NFS_SERVER(inode);
-	struct nfs_fattr fattr = {
-		.valid = 0,
-	};
-	struct nfs_open_reclaimargs o_arg = {
+	struct nfs_delegation *delegation = NFS_I(inode)->delegation;
+	struct nfs_openargs o_arg = {
 		.fh = NFS_FH(inode),
 		.seqid = sp->so_seqid,
 		.id = sp->so_id,
-		.share_access = state->state,
+		.open_flags = state->state,
 		.clientid = server->nfs4_state->cl_clientid,
 		.claim = NFS4_OPEN_CLAIM_PREVIOUS,
 		.bitmask = server->attr_bitmask,
 	};
 	struct nfs_openres o_res = {
-		.f_attr = &fattr,
 		.server = server,	/* Grrr */
 	};
 	struct rpc_message msg = {
-		.rpc_proc       = &nfs4_procedures[NFSPROC4_CLNT_OPEN_RECLAIM],
+		.rpc_proc       = &nfs4_procedures[NFSPROC4_CLNT_OPEN_NOATTR],
 		.rpc_argp       = &o_arg,
 		.rpc_resp	= &o_res,
 		.rpc_cred	= sp->so_cred,
 	};
 	int status;
 
-	status = rpc_call_sync(server->client, &msg, 0);
+	if (delegation != NULL) {
+		if (!(delegation->flags & NFS_DELEGATION_NEED_RECLAIM)) {
+			memcpy(&state->stateid, &delegation->stateid,
+					sizeof(state->stateid));
+			set_bit(NFS_DELEGATED_STATE, &state->flags);
+			return 0;
+		}
+		o_arg.u.delegation_type = delegation->type;
+	}
+	status = rpc_call_sync(server->client, &msg, RPC_TASK_NOINTR);
 	nfs4_increment_seqid(status, sp);
-	if (status == 0)
+	if (status == 0) {
 		memcpy(&state->stateid, &o_res.stateid, sizeof(state->stateid));
-	/* Update the inode attributes */
-	nfs_refresh_inode(inode, &fattr);
+		if (o_res.delegation_type != 0) {
+			nfs_inode_reclaim_delegation(inode, sp->so_cred, &o_res);
+			/* Did the server issue an immediate delegation recall? */
+			if (o_res.do_recall)
+				nfs_async_inode_return_delegation(inode, &o_res.stateid);
+		}
+	}
+	clear_bit(NFS_DELEGATED_STATE, &state->flags);
+	/* Ensure we update the inode attributes */
+	NFS_CACHEINV(inode);
 	return status;
 }
 
+int nfs4_open_reclaim(struct nfs4_state_owner *sp, struct nfs4_state *state)
+{
+	struct nfs_server *server = NFS_SERVER(state->inode);
+	struct nfs4_exception exception = { };
+	int err;
+	do {
+		err = _nfs4_open_reclaim(sp, state);
+		switch (err) {
+			case 0:
+			case -NFS4ERR_STALE_CLIENTID:
+			case -NFS4ERR_STALE_STATEID:
+			case -NFS4ERR_EXPIRED:
+				return err;
+		}
+		err = nfs4_handle_exception(server, err, &exception);
+	} while (exception.retry);
+	return err;
+}
+
+static int _nfs4_open_delegation_recall(struct dentry *dentry, struct nfs4_state *state)
+{
+	struct nfs4_state_owner  *sp  = state->owner;
+	struct inode *inode = dentry->d_inode;
+	struct nfs_server *server = NFS_SERVER(inode);
+	struct dentry *parent = dget_parent(dentry);
+	struct nfs_openargs arg = {
+		.fh = NFS_FH(parent->d_inode),
+		.clientid = server->nfs4_state->cl_clientid,
+		.name = &dentry->d_name,
+		.id = sp->so_id,
+		.server = server,
+		.bitmask = server->attr_bitmask,
+		.claim = NFS4_OPEN_CLAIM_DELEGATE_CUR,
+	};
+	struct nfs_openres res = {
+		.server = server,
+	};
+	struct 	rpc_message msg = {
+		.rpc_proc       = &nfs4_procedures[NFSPROC4_CLNT_OPEN_NOATTR],
+		.rpc_argp       = &arg,
+		.rpc_resp       = &res,
+		.rpc_cred	= sp->so_cred,
+	};
+	int status = 0;
+
+	down(&sp->so_sema);
+	if (!test_bit(NFS_DELEGATED_STATE, &state->flags))
+		goto out;
+	if (state->state == 0)
+		goto out;
+	arg.seqid = sp->so_seqid;
+	arg.open_flags = state->state;
+	memcpy(arg.u.delegation.data, state->stateid.data, sizeof(arg.u.delegation.data));
+	status = rpc_call_sync(server->client, &msg, RPC_TASK_NOINTR);
+	nfs4_increment_seqid(status, sp);
+	if (status >= 0) {
+		memcpy(state->stateid.data, res.stateid.data,
+				sizeof(state->stateid.data));
+		clear_bit(NFS_DELEGATED_STATE, &state->flags);
+	}
+out:
+	up(&sp->so_sema);
+	dput(parent);
+	return status;
+}
+
+int nfs4_open_delegation_recall(struct dentry *dentry, struct nfs4_state *state)
+{
+	struct nfs4_exception exception = { };
+	struct nfs_server *server = NFS_SERVER(dentry->d_inode);
+	int err;
+	do {
+		err = _nfs4_open_delegation_recall(dentry, state);
+		switch (err) {
+			case 0:
+				return err;
+			case -NFS4ERR_STALE_CLIENTID:
+			case -NFS4ERR_STALE_STATEID:
+			case -NFS4ERR_EXPIRED:
+				/* Don't recall a delegation if it was lost */
+				nfs4_schedule_state_recovery(server->nfs4_state);
+				return err;
+		}
+		err = nfs4_handle_exception(server, err, &exception);
+	} while (exception.retry);
+	return err;
+}
+
+static int _nfs4_proc_open_confirm(struct rpc_clnt *clnt, const struct nfs_fh *fh, struct nfs4_state_owner *sp, nfs4_stateid *stateid)
+{
+	struct nfs_open_confirmargs arg = {
+		.fh             = fh,
+		.seqid          = sp->so_seqid,
+		.stateid	= *stateid,
+	};
+	struct nfs_open_confirmres res;
+	struct 	rpc_message msg = {
+		.rpc_proc       = &nfs4_procedures[NFSPROC4_CLNT_OPEN_CONFIRM],
+		.rpc_argp       = &arg,
+		.rpc_resp       = &res,
+		.rpc_cred	= sp->so_cred,
+	};
+	int status;
+
+	status = rpc_call_sync(clnt, &msg, RPC_TASK_NOINTR);
+	nfs4_increment_seqid(status, sp);
+	if (status >= 0)
+		memcpy(stateid, &res.stateid, sizeof(*stateid));
+	return status;
+}
+
+static int _nfs4_do_access(struct inode *inode, struct rpc_cred *cred, int mask)
+{
+	struct nfs_access_entry cache;
+	int status;
+
+	status = nfs_access_get_cached(inode, cred, &cache);
+	if (status == 0)
+		goto out;
+
+	/* Be clever: ask server to check for all possible rights */
+	cache.mask = MAY_EXEC | MAY_WRITE | MAY_READ;
+	cache.cred = cred;
+	cache.jiffies = jiffies;
+	status = _nfs4_proc_access(inode, &cache);
+	if (status != 0)
+		return status;
+	nfs_access_add_cache(inode, &cache);
+out:
+	if ((cache.mask & mask) == mask)
+		return 0;
+	return -EACCES;
+}
+
+/*
+ * Returns an nfs4_state + an extra reference to the inode
+ */
+int _nfs4_open_delegated(struct inode *inode, int flags, struct rpc_cred *cred, struct nfs4_state **res)
+{
+	struct nfs_delegation *delegation;
+	struct nfs_server *server = NFS_SERVER(inode);
+	struct nfs4_client *clp = server->nfs4_state;
+	struct nfs_inode *nfsi = NFS_I(inode);
+	struct nfs4_state_owner *sp = NULL;
+	struct nfs4_state *state = NULL;
+	int open_flags = flags & (FMODE_READ|FMODE_WRITE);
+	int mask = 0;
+	int err;
+
+	/* Protect against reboot recovery - NOTE ORDER! */
+	down_read(&clp->cl_sem);
+	/* Protect against delegation recall */
+	down_read(&nfsi->rwsem);
+	delegation = NFS_I(inode)->delegation;
+	err = -ENOENT;
+	if (delegation == NULL || (delegation->type & open_flags) != open_flags)
+		goto out_err;
+	err = -ENOMEM;
+	if (!(sp = nfs4_get_state_owner(server, cred))) {
+		dprintk("%s: nfs4_get_state_owner failed!\n", __FUNCTION__);
+		goto out_err;
+	}
+	down(&sp->so_sema);
+	state = nfs4_get_open_state(inode, sp);
+	if (state == NULL)
+		goto out_err;
+
+	err = -ENOENT;
+	if ((state->state & open_flags) == open_flags) {
+		spin_lock(&inode->i_lock);
+		if (open_flags & FMODE_READ)
+			state->nreaders++;
+		if (open_flags & FMODE_WRITE)
+			state->nwriters++;
+		spin_unlock(&inode->i_lock);
+		goto out_ok;
+	} else if (state->state != 0)
+		goto out_err;
+
+	lock_kernel();
+	err = _nfs4_do_access(inode, cred, mask);
+	unlock_kernel();
+	if (err != 0)
+		goto out_err;
+	spin_lock(&inode->i_lock);
+	memcpy(state->stateid.data, delegation->stateid.data,
+			sizeof(state->stateid.data));
+	state->state |= open_flags;
+	if (open_flags & FMODE_READ)
+		state->nreaders++;
+	if (open_flags & FMODE_WRITE)
+		state->nwriters++;
+	set_bit(NFS_DELEGATED_STATE, &state->flags);
+	spin_unlock(&inode->i_lock);
+out_ok:
+	up(&sp->so_sema);
+	nfs4_put_state_owner(sp);
+	up_read(&nfsi->rwsem);
+	up_read(&clp->cl_sem);
+	igrab(inode);
+	*res = state;
+	return 0; 
+out_err:
+	if (sp != NULL) {
+		if (state != NULL)
+			nfs4_put_open_state(state);
+		up(&sp->so_sema);
+		nfs4_put_state_owner(sp);
+	}
+	up_read(&nfsi->rwsem);
+	up_read(&clp->cl_sem);
+	return err;
+}
+
+static struct nfs4_state *nfs4_open_delegated(struct inode *inode, int flags, struct rpc_cred *cred)
+{
+	struct nfs4_exception exception = { };
+	struct nfs4_state *res;
+	int err;
+
+	do {
+		err = _nfs4_open_delegated(inode, flags, cred, &res);
+		if (err == 0)
+			break;
+		res = ERR_PTR(nfs4_handle_exception(NFS_SERVER(inode),
+					err, &exception));
+	} while (exception.retry);
+	return res;
+}
+
 /*
  * Returns an nfs4_state + an referenced inode
  */
-struct nfs4_state *
-nfs4_do_open(struct inode *dir, struct qstr *name, int flags, struct iattr *sattr, struct rpc_cred *cred)
+static int _nfs4_do_open(struct inode *dir, struct qstr *name, int flags, struct iattr *sattr, struct rpc_cred *cred, struct nfs4_state **res)
 {
 	struct nfs4_state_owner  *sp;
 	struct nfs4_state     *state = NULL;
 	struct nfs_server       *server = NFS_SERVER(dir);
+	struct nfs4_client *clp = server->nfs4_state;
 	struct inode *inode = NULL;
 	int                     status;
 	struct nfs_fattr        f_attr = {
@@ -243,12 +490,11 @@
 	};
 	struct nfs_openargs o_arg = {
 		.fh             = NFS_FH(dir),
-		.share_access   = flags & (FMODE_READ|FMODE_WRITE),
-		.opentype       = (flags & O_CREAT) ? NFS4_OPEN_CREATE : NFS4_OPEN_NOCREATE,
-		.createmode     = (flags & O_EXCL) ? NFS4_CREATE_EXCLUSIVE : NFS4_CREATE_UNCHECKED,
+		.open_flags	= flags,
 		.name           = name,
 		.server         = server,
 		.bitmask = server->attr_bitmask,
+		.claim = NFS4_OPEN_CLAIM_NULL,
 	};
 	struct nfs_openres o_res = {
 		.f_attr         = &f_attr,
@@ -261,60 +507,50 @@
 		.rpc_cred	= cred,
 	};
 
-retry:
+	/* Protect against reboot recovery conflicts */
+	down_read(&clp->cl_sem);
 	status = -ENOMEM;
-	if (!(sp = nfs4_get_state_owner(NFS_SERVER(dir), cred))) {
+	if (!(sp = nfs4_get_state_owner(server, cred))) {
 		dprintk("nfs4_do_open: nfs4_get_state_owner failed!\n");
-		goto out;
+		goto out_err;
 	}
-	if (o_arg.createmode & NFS4_CREATE_EXCLUSIVE){
+	if (flags & O_EXCL) {
 		u32 *p = (u32 *) o_arg.u.verifier.data;
 		p[0] = jiffies;
 		p[1] = current->pid;
-	} else if (o_arg.createmode == NFS4_CREATE_UNCHECKED) {
+	} else
 		o_arg.u.attrs = sattr;
-	}
 	/* Serialization for the sequence id */
 	down(&sp->so_sema);
 	o_arg.seqid = sp->so_seqid;
 	o_arg.id = sp->so_id;
-	o_arg.clientid = NFS_SERVER(dir)->nfs4_state->cl_clientid,
+	o_arg.clientid = clp->cl_clientid,
 
-	status = rpc_call_sync(server->client, &msg, 0);
+	status = rpc_call_sync(server->client, &msg, RPC_TASK_NOINTR);
 	nfs4_increment_seqid(status, sp);
 	if (status)
-		goto out_up;
+		goto out_err;
 	update_changeattr(dir, &o_res.cinfo);
+	if(o_res.rflags & NFS4_OPEN_RESULT_CONFIRM) {
+		status = _nfs4_proc_open_confirm(server->client, &o_res.fh,
+				sp, &o_res.stateid);
+		if (status != 0)
+			goto out_err;
+	}
+	if (!(f_attr.valid & NFS_ATTR_FATTR)) {
+		status = server->rpc_ops->getattr(server, &o_res.fh, &f_attr);
+		if (status < 0)
+			goto out_err;
+	}
 
 	status = -ENOMEM;
 	inode = nfs_fhget(dir->i_sb, &o_res.fh, &f_attr);
 	if (!inode)
-		goto out_up;
+		goto out_err;
 	state = nfs4_get_open_state(inode, sp);
 	if (!state)
-		goto out_up;
-
-	if(o_res.rflags & NFS4_OPEN_RESULT_CONFIRM) {
-		struct nfs_open_confirmargs oc_arg = {
-			.fh             = &o_res.fh,
-			.seqid          = sp->so_seqid,
-		};
-		struct nfs_open_confirmres oc_res;
-		struct 	rpc_message msg = {
-			.rpc_proc       = &nfs4_procedures[NFSPROC4_CLNT_OPEN_CONFIRM],
-			.rpc_argp       = &oc_arg,
-			.rpc_resp       = &oc_res,
-			.rpc_cred	= cred,
-		};
-
-		memcpy(&oc_arg.stateid, &o_res.stateid, sizeof(oc_arg.stateid));
-		status = rpc_call_sync(server->client, &msg, 0);
-		nfs4_increment_seqid(status, sp);
-		if (status)
-			goto out_up;
-		memcpy(&state->stateid, &oc_res.stateid, sizeof(state->stateid));
-	} else
-		memcpy(&state->stateid, &o_res.stateid, sizeof(state->stateid));
+		goto out_err;
+	memcpy(&state->stateid, &o_res.stateid, sizeof(state->stateid));
 	spin_lock(&inode->i_lock);
 	if (flags & FMODE_READ)
 		state->nreaders++;
@@ -322,47 +558,62 @@
 		state->nwriters++;
 	state->state |= flags & (FMODE_READ|FMODE_WRITE);
 	spin_unlock(&inode->i_lock);
-
+	if (o_res.delegation_type != 0)
+		nfs_inode_set_delegation(inode, cred, &o_res);
 	up(&sp->so_sema);
 	nfs4_put_state_owner(sp);
-	return state;
-
-out_up:
-	up(&sp->so_sema);
-	nfs4_put_state_owner(sp);
-	if (state) {
-		nfs4_put_open_state(state);
-		state = NULL;
-	}
-	if (inode) {
+	up_read(&clp->cl_sem);
+	*res = state;
+	return 0;
+out_err:
+	if (sp != NULL) {
+		if (state != NULL)
+			nfs4_put_open_state(state);
+		up(&sp->so_sema);
+		nfs4_put_state_owner(sp);
+	}
+	/* Note: clp->cl_sem must be released before nfs4_put_open_state()! */
+	up_read(&clp->cl_sem);
+	if (inode != NULL)
 		iput(inode);
-		inode = NULL;
-	}
-	/* NOTE: BAD_SEQID means the server and client disagree about the
-	 * book-keeping w.r.t. state-changing operations
-	 * (OPEN/CLOSE/LOCK/LOCKU...)
-	 * It is actually a sign of a bug on the client or on the server.
-	 *
-	 * If we receive a BAD_SEQID error in the particular case of
-	 * doing an OPEN, we assume that nfs4_increment_seqid() will
-	 * have unhashed the old state_owner for us, and that we can
-	 * therefore safely retry using a new one. We should still warn
-	 * the user though...
-	 */
-	if (status == -NFS4ERR_BAD_SEQID) {
-		printk(KERN_WARNING "NFS: v4 server returned a bad sequence-id error!\n");
-		goto retry;
-	}
-	status = nfs4_handle_error(server, status);
-	if (!status)
-		goto retry;
-	BUG_ON(status < -1000 || status > 0);
-out:
-	return ERR_PTR(status);
+	*res = NULL;
+	return status;
 }
 
-int
-nfs4_do_setattr(struct nfs_server *server, struct nfs_fattr *fattr,
+
+struct nfs4_state *nfs4_do_open(struct inode *dir, struct qstr *name, int flags, struct iattr *sattr, struct rpc_cred *cred)
+{
+	struct nfs4_exception exception = { };
+	struct nfs4_state *res;
+	int status;
+
+	do {
+		status = _nfs4_do_open(dir, name, flags, sattr, cred, &res);
+		if (status == 0)
+			break;
+		/* NOTE: BAD_SEQID means the server and client disagree about the
+		 * book-keeping w.r.t. state-changing operations
+		 * (OPEN/CLOSE/LOCK/LOCKU...)
+		 * It is actually a sign of a bug on the client or on the server.
+		 *
+		 * If we receive a BAD_SEQID error in the particular case of
+		 * doing an OPEN, we assume that nfs4_increment_seqid() will
+		 * have unhashed the old state_owner for us, and that we can
+		 * therefore safely retry using a new one. We should still warn
+		 * the user though...
+		 */
+		if (status == -NFS4ERR_BAD_SEQID) {
+			printk(KERN_WARNING "NFS: v4 server returned a bad sequence-id error!\n");
+			exception.retry = 1;
+			continue;
+		}
+		res = ERR_PTR(nfs4_handle_exception(NFS_SERVER(dir),
+					status, &exception));
+	} while (exception.retry);
+	return res;
+}
+
+static int _nfs4_do_setattr(struct nfs_server *server, struct nfs_fattr *fattr,
                 struct nfs_fh *fhandle, struct iattr *sattr,
                 struct nfs4_state *state)
 {
@@ -381,9 +632,7 @@
                 .rpc_argp       = &arg,
                 .rpc_resp       = &res,
         };
-	int status;
 
-retry:
         fattr->valid = 0;
 
 	if (sattr->ia_valid & ATTR_SIZE)
@@ -391,13 +640,22 @@
 	else
 		memcpy(&arg.stateid, &zero_stateid, sizeof(arg.stateid));
 
-	status = rpc_call_sync(server->client, &msg, 0);
-	if (status) {
-		status = nfs4_handle_error(server, status);
-		if (!status)
-			goto retry;
-	}
-	return status;
+	return rpc_call_sync(server->client, &msg, 0);
+}
+
+int nfs4_do_setattr(struct nfs_server *server, struct nfs_fattr *fattr,
+                struct nfs_fh *fhandle, struct iattr *sattr,
+                struct nfs4_state *state)
+{
+	struct nfs4_exception exception = { };
+	int err;
+	do {
+		err = nfs4_handle_exception(server,
+				_nfs4_do_setattr(server, fattr, fhandle, sattr,
+					state),
+				&exception);
+	} while (exception.retry);
+	return err;
 }
 
 /* 
@@ -411,8 +669,7 @@
  *
  * NOTE: Caller must be holding the sp->so_owner semaphore!
  */
-int
-nfs4_do_close(struct inode *inode, struct nfs4_state *state) 
+static int _nfs4_do_close(struct inode *inode, struct nfs4_state *state) 
 {
 	struct nfs4_state_owner *sp = state->owner;
 	int status = 0;
@@ -426,10 +683,12 @@
 		.rpc_resp	= &res,
 	};
 
+	if (test_bit(NFS_DELEGATED_STATE, &state->flags))
+		return 0;
 	memcpy(&arg.stateid, &state->stateid, sizeof(arg.stateid));
 	/* Serialization for the sequence id */
 	arg.seqid = sp->so_seqid,
-	status = rpc_call_sync(NFS_SERVER(inode)->client, &msg, 0);
+	status = rpc_call_sync(NFS_SERVER(inode)->client, &msg, RPC_TASK_NOINTR);
 
         /* hmm. we are done with the inode, and in the process of freeing
 	 * the state_owner. we keep this around to process errors
@@ -441,15 +700,34 @@
 	return status;
 }
 
-int
-nfs4_do_downgrade(struct inode *inode, struct nfs4_state *state, mode_t mode) 
+int nfs4_do_close(struct inode *inode, struct nfs4_state *state) 
+{
+	struct nfs_server *server = NFS_SERVER(state->inode);
+	struct nfs4_exception exception = { };
+	int err;
+	do {
+		err = _nfs4_do_close(inode, state);
+		switch (err) {
+			case -NFS4ERR_STALE_STATEID:
+			case -NFS4ERR_EXPIRED:
+				nfs4_schedule_state_recovery(server->nfs4_state);
+				err = 0;
+			default:
+				state->state = 0;
+		}
+		err = nfs4_handle_exception(server, err, &exception);
+	} while (exception.retry);
+	return err;
+}
+
+static int _nfs4_do_downgrade(struct inode *inode, struct nfs4_state *state, mode_t mode) 
 {
 	struct nfs4_state_owner *sp = state->owner;
 	int status = 0;
 	struct nfs_closeargs arg = {
 		.fh		= NFS_FH(inode),
 		.seqid		= sp->so_seqid,
-		.share_access	= mode,
+		.open_flags	= mode,
 	};
 	struct nfs_closeres res;
 	struct rpc_message msg = {
@@ -458,8 +736,10 @@
 		.rpc_resp	= &res,
 	};
 
+	if (test_bit(NFS_DELEGATED_STATE, &state->flags))
+		return 0;
 	memcpy(&arg.stateid, &state->stateid, sizeof(arg.stateid));
-	status = rpc_call_sync(NFS_SERVER(inode)->client, &msg, 0);
+	status = rpc_call_sync(NFS_SERVER(inode)->client, &msg, RPC_TASK_NOINTR);
 	nfs4_increment_seqid(status, sp);
 	if (!status)
 		memcpy(&state->stateid, &res.stateid, sizeof(state->stateid));
@@ -467,6 +747,26 @@
 	return status;
 }
 
+int nfs4_do_downgrade(struct inode *inode, struct nfs4_state *state, mode_t mode) 
+{
+	struct nfs_server *server = NFS_SERVER(state->inode);
+	struct nfs4_exception exception = { };
+	int err;
+	do {
+		err = _nfs4_do_downgrade(inode, state, mode);
+		switch (err) {
+			case -NFS4ERR_STALE_STATEID:
+			case -NFS4ERR_EXPIRED:
+				nfs4_schedule_state_recovery(server->nfs4_state);
+				err = 0;
+			default:
+				state->state = mode;
+		}
+		err = nfs4_handle_exception(server, err, &exception);
+	} while (exception.retry);
+	return err;
+}
+
 struct inode *
 nfs4_atomic_open(struct inode *dir, struct dentry *dentry, struct nameidata *nd)
 {
@@ -500,7 +800,9 @@
 	struct inode *inode;
 
 	cred = rpcauth_lookupcred(NFS_SERVER(dir)->client->cl_auth, 0);
-	state = nfs4_do_open(dir, &dentry->d_name, openflags, NULL, cred);
+	state = nfs4_open_delegated(dentry->d_inode, openflags, cred);
+	if (IS_ERR(state))
+		state = nfs4_do_open(dir, &dentry->d_name, openflags, NULL, cred);
 	put_rpccred(cred);
 	if (state == ERR_PTR(-ENOENT) && dentry->d_inode == 0)
 		return 1;
@@ -518,7 +820,7 @@
 }
 
 
-static int nfs4_server_capabilities(struct nfs_server *server, struct nfs_fh *fhandle)
+static int _nfs4_server_capabilities(struct nfs_server *server, struct nfs_fh *fhandle)
 {
 	struct nfs4_server_caps_res res = {};
 	struct rpc_message msg = {
@@ -542,7 +844,19 @@
 	return status;
 }
 
-static int nfs4_lookup_root(struct nfs_server *server, struct nfs_fh *fhandle,
+static int nfs4_server_capabilities(struct nfs_server *server, struct nfs_fh *fhandle)
+{
+	struct nfs4_exception exception = { };
+	int err;
+	do {
+		err = nfs4_handle_exception(server,
+				_nfs4_server_capabilities(server, fhandle),
+				&exception);
+	} while (exception.retry);
+	return err;
+}
+
+static int _nfs4_lookup_root(struct nfs_server *server, struct nfs_fh *fhandle,
 		struct nfs_fsinfo *info)
 {
 	struct nfs_fattr *	fattr = info->fattr;
@@ -563,6 +877,19 @@
 	return rpc_call_sync(server->client, &msg, 0);
 }
 
+static int nfs4_lookup_root(struct nfs_server *server, struct nfs_fh *fhandle,
+		struct nfs_fsinfo *info)
+{
+	struct nfs4_exception exception = { };
+	int err;
+	do {
+		err = nfs4_handle_exception(server,
+				_nfs4_lookup_root(server, fhandle, info),
+				&exception);
+	} while (exception.retry);
+	return err;
+}
+
 static int nfs4_proc_get_root(struct nfs_server *server, struct nfs_fh *fhandle,
 		struct nfs_fsinfo *info)
 {
@@ -597,6 +924,8 @@
 
 	p = server->mnt_path;
 	for (;;) {
+		struct nfs4_exception exception = { };
+
 		while (*p == '/')
 			p++;
 		if (!*p)
@@ -606,9 +935,13 @@
 			p++;
 		q.len = p - q.name;
 
-		fattr->valid = 0;
-		status = rpc_call_sync(server->client, &msg, 0);
-		if (!status)
+		do {
+			fattr->valid = 0;
+			status = nfs4_handle_exception(server,
+					rpc_call_sync(server->client, &msg, 0),
+					&exception);
+		} while (exception.retry);
+		if (status == 0)
 			continue;
 		if (status == -ENOENT) {
 			printk(KERN_NOTICE "NFS: mount path %s does not exist!\n", server->mnt_path);
@@ -621,14 +954,13 @@
 	if (status == 0)
 		status = nfs4_do_fsinfo(server, fhandle, info);
 out:
-	return nfs4_map_errors(status);
+	return status;
 }
 
-static int nfs4_proc_getattr(struct inode *inode, struct nfs_fattr *fattr)
+static int _nfs4_proc_getattr(struct nfs_server *server, struct nfs_fh *fhandle, struct nfs_fattr *fattr)
 {
-	struct nfs_server *server = NFS_SERVER(inode);
 	struct nfs4_getattr_arg args = {
-		.fh = NFS_FH(inode),
+		.fh = fhandle,
 		.bitmask = server->attr_bitmask,
 	};
 	struct nfs4_getattr_res res = {
@@ -642,8 +974,19 @@
 	};
 	
 	fattr->valid = 0;
+	return rpc_call_sync(server->client, &msg, 0);
+}
 
-	return nfs4_map_errors(rpc_call_sync(NFS_CLIENT(inode), &msg, 0));
+static int nfs4_proc_getattr(struct nfs_server *server, struct nfs_fh *fhandle, struct nfs_fattr *fattr)
+{
+	struct nfs4_exception exception = { };
+	int err;
+	do {
+		err = nfs4_handle_exception(server,
+				_nfs4_proc_getattr(server, fhandle, fattr),
+				&exception);
+	} while (exception.retry);
+	return err;
 }
 
 /* 
@@ -678,9 +1021,13 @@
 	if (size_change) {
 		struct rpc_cred *cred = rpcauth_lookupcred(NFS_SERVER(inode)->client->cl_auth, 0);
 		state = nfs4_find_state(inode, cred, FMODE_WRITE);
-		if (!state) {
-			state = nfs4_do_open(dentry->d_parent->d_inode, 
-				&dentry->d_name, FMODE_WRITE, NULL, cred);
+		if (state == NULL) {
+			state = nfs4_open_delegated(dentry->d_inode,
+					FMODE_WRITE, cred);
+			if (IS_ERR(state))
+				state = nfs4_do_open(dentry->d_parent->d_inode,
+						&dentry->d_name, FMODE_WRITE,
+						NULL, cred);
 			need_iput = 1;
 		}
 		put_rpccred(cred);
@@ -705,7 +1052,7 @@
 	return status;
 }
 
-static int nfs4_proc_lookup(struct inode *dir, struct qstr *name,
+static int _nfs4_proc_lookup(struct inode *dir, struct qstr *name,
 		struct nfs_fh *fhandle, struct nfs_fattr *fattr)
 {
 	int		       status;
@@ -731,12 +1078,23 @@
 	dprintk("NFS call  lookup %s\n", name->name);
 	status = rpc_call_sync(NFS_CLIENT(dir), &msg, 0);
 	dprintk("NFS reply lookup: %d\n", status);
-	return nfs4_map_errors(status);
+	return status;
 }
 
-static int nfs4_proc_access(struct inode *inode, struct rpc_cred *cred, int mode)
+static int nfs4_proc_lookup(struct inode *dir, struct qstr *name, struct nfs_fh *fhandle, struct nfs_fattr *fattr)
+{
+	struct nfs4_exception exception = { };
+	int err;
+	do {
+		err = nfs4_handle_exception(NFS_SERVER(dir),
+				_nfs4_proc_lookup(dir, name, fhandle, fattr),
+				&exception);
+	} while (exception.retry);
+	return err;
+}
+
+static int _nfs4_proc_access(struct inode *inode, struct nfs_access_entry *entry)
 {
-	int			status;
 	struct nfs4_accessargs args = {
 		.fh = NFS_FH(inode),
 	};
@@ -745,8 +1103,10 @@
 		.rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_ACCESS],
 		.rpc_argp = &args,
 		.rpc_resp = &res,
-		.rpc_cred = cred,
+		.rpc_cred = entry->cred,
 	};
+	int mode = entry->mask;
+	int status;
 
 	/*
 	 * Determine which access bits we want to ask for...
@@ -758,8 +1118,7 @@
 			args.access |= NFS4_ACCESS_MODIFY | NFS4_ACCESS_EXTEND | NFS4_ACCESS_DELETE;
 		if (mode & MAY_EXEC)
 			args.access |= NFS4_ACCESS_LOOKUP;
-	}
-	else {
+	} else {
 		if (mode & MAY_WRITE)
 			args.access |= NFS4_ACCESS_MODIFY | NFS4_ACCESS_EXTEND;
 		if (mode & MAY_EXEC)
@@ -767,13 +1126,27 @@
 	}
 	status = rpc_call_sync(NFS_CLIENT(inode), &msg, 0);
 	if (!status) {
-		if (args.access != res.supported) {
-			printk(KERN_NOTICE "NFS: server didn't support all access bits!\n");
-			status = -ENOTSUPP;
-		} else if ((args.access & res.access) != args.access)
-			status = -EACCES;
+		entry->mask = 0;
+		if (res.access & NFS4_ACCESS_READ)
+			entry->mask |= MAY_READ;
+		if (res.access & (NFS4_ACCESS_MODIFY | NFS4_ACCESS_EXTEND | NFS4_ACCESS_DELETE))
+			entry->mask |= MAY_WRITE;
+		if (res.access & (NFS4_ACCESS_LOOKUP|NFS4_ACCESS_EXECUTE))
+			entry->mask |= MAY_EXEC;
 	}
-	return nfs4_map_errors(status);
+	return status;
+}
+
+static int nfs4_proc_access(struct inode *inode, struct nfs_access_entry *entry)
+{
+	struct nfs4_exception exception = { };
+	int err;
+	do {
+		err = nfs4_handle_exception(NFS_SERVER(inode),
+				_nfs4_proc_access(inode, entry),
+				&exception);
+	} while (exception.retry);
+	return err;
 }
 
 /*
@@ -800,11 +1173,13 @@
  * Both of these changes to the XDR layer would in fact be quite
  * minor, but I decided to leave them for a subsequent patch.
  */
-static int nfs4_proc_readlink(struct inode *inode, struct page *page)
+static int _nfs4_proc_readlink(struct inode *inode, struct page *page,
+		unsigned int pgbase, unsigned int pglen)
 {
 	struct nfs4_readlink args = {
 		.fh       = NFS_FH(inode),
-		.count    = PAGE_CACHE_SIZE,
+		.pgbase	  = pgbase,
+		.pglen    = pglen,
 		.pages    = &page,
 	};
 	struct rpc_message msg = {
@@ -813,11 +1188,23 @@
 		.rpc_resp = NULL,
 	};
 
-	return nfs4_map_errors(rpc_call_sync(NFS_CLIENT(inode), &msg, 0));
+	return rpc_call_sync(NFS_CLIENT(inode), &msg, 0);
 }
 
-static int
-nfs4_proc_read(struct nfs_read_data *rdata, struct file *filp)
+static int nfs4_proc_readlink(struct inode *inode, struct page *page,
+		unsigned int pgbase, unsigned int pglen)
+{
+	struct nfs4_exception exception = { };
+	int err;
+	do {
+		err = nfs4_handle_exception(NFS_SERVER(inode),
+				_nfs4_proc_readlink(inode, page, pgbase, pglen),
+				&exception);
+	} while (exception.retry);
+	return err;
+}
+
+static int _nfs4_proc_read(struct nfs_read_data *rdata)
 {
 	int flags = rdata->flags;
 	struct inode *inode = rdata->inode;
@@ -827,6 +1214,7 @@
 		.rpc_proc	= &nfs4_procedures[NFSPROC4_CLNT_READ],
 		.rpc_argp	= &rdata->args,
 		.rpc_resp	= &rdata->res,
+		.rpc_cred	= rdata->cred,
 	};
 	unsigned long timestamp = jiffies;
 	int status;
@@ -834,29 +1222,27 @@
 	dprintk("NFS call  read %d @ %Ld\n", rdata->args.count,
 			(long long) rdata->args.offset);
 
-	/*
-	 * Try first to use O_RDONLY, then O_RDWR stateid.
-	 */
-	if (filp) {
-		struct nfs4_state *state;
-		state = (struct nfs4_state *)filp->private_data;
-		rdata->args.state = state;
-		msg.rpc_cred = state->owner->so_cred;
-	} else {
-		rdata->args.state = NULL;
-		msg.rpc_cred = NFS_I(inode)->mm_cred;
-	}
-
 	fattr->valid = 0;
 	status = rpc_call_sync(server->client, &msg, flags);
 	if (!status)
 		renew_lease(server, timestamp);
 	dprintk("NFS reply read: %d\n", status);
-	return nfs4_map_errors(status);
+	return status;
 }
 
-static int
-nfs4_proc_write(struct nfs_write_data *wdata, struct file *filp)
+static int nfs4_proc_read(struct nfs_read_data *rdata)
+{
+	struct nfs4_exception exception = { };
+	int err;
+	do {
+		err = nfs4_handle_exception(NFS_SERVER(rdata->inode),
+				_nfs4_proc_read(rdata),
+				&exception);
+	} while (exception.retry);
+	return err;
+}
+
+static int _nfs4_proc_write(struct nfs_write_data *wdata)
 {
 	int rpcflags = wdata->flags;
 	struct inode *inode = wdata->inode;
@@ -866,33 +1252,32 @@
 		.rpc_proc	= &nfs4_procedures[NFSPROC4_CLNT_WRITE],
 		.rpc_argp	= &wdata->args,
 		.rpc_resp	= &wdata->res,
+		.rpc_cred	= wdata->cred,
 	};
 	int status;
 
 	dprintk("NFS call  write %d @ %Ld\n", wdata->args.count,
 			(long long) wdata->args.offset);
 
-	/*
-	 * Try first to use O_WRONLY, then O_RDWR stateid.
-	 */
-	if (filp) {
-		struct nfs4_state *state;
-		state = (struct nfs4_state *)filp->private_data;
-		wdata->args.state = state;
-		msg.rpc_cred = state->owner->so_cred;
-	} else {
-		wdata->args.state = NULL;
-		msg.rpc_cred = NFS_I(inode)->mm_cred;
-	}
-
 	fattr->valid = 0;
 	status = rpc_call_sync(server->client, &msg, rpcflags);
 	dprintk("NFS reply write: %d\n", status);
-	return nfs4_map_errors(status);
+	return status;
 }
 
-static int
-nfs4_proc_commit(struct nfs_write_data *cdata, struct file *filp)
+static int nfs4_proc_write(struct nfs_write_data *wdata)
+{
+	struct nfs4_exception exception = { };
+	int err;
+	do {
+		err = nfs4_handle_exception(NFS_SERVER(wdata->inode),
+				_nfs4_proc_write(wdata),
+				&exception);
+	} while (exception.retry);
+	return err;
+}
+
+static int _nfs4_proc_commit(struct nfs_write_data *cdata)
 {
 	struct inode *inode = cdata->inode;
 	struct nfs_fattr *fattr = cdata->res.fattr;
@@ -901,24 +1286,29 @@
 		.rpc_proc	= &nfs4_procedures[NFSPROC4_CLNT_COMMIT],
 		.rpc_argp	= &cdata->args,
 		.rpc_resp	= &cdata->res,
+		.rpc_cred	= cdata->cred,
 	};
 	int status;
 
 	dprintk("NFS call  commit %d @ %Ld\n", cdata->args.count,
 			(long long) cdata->args.offset);
 
-	/*
-	 * Try first to use O_WRONLY, then O_RDWR stateid.
-	 */
-	if (filp)
-		msg.rpc_cred = ((struct nfs4_state *)filp->private_data)->owner->so_cred;
-	else
-		msg.rpc_cred = NFS_I(inode)->mm_cred;
-
 	fattr->valid = 0;
 	status = rpc_call_sync(server->client, &msg, 0);
 	dprintk("NFS reply commit: %d\n", status);
-	return nfs4_map_errors(status);
+	return status;
+}
+
+static int nfs4_proc_commit(struct nfs_write_data *cdata)
+{
+	struct nfs4_exception exception = { };
+	int err;
+	do {
+		err = nfs4_handle_exception(NFS_SERVER(cdata->inode),
+				_nfs4_proc_commit(cdata),
+				&exception);
+	} while (exception.retry);
+	return err;
 }
 
 /*
@@ -965,7 +1355,7 @@
 	return inode;
 }
 
-static int nfs4_proc_remove(struct inode *dir, struct qstr *name)
+static int _nfs4_proc_remove(struct inode *dir, struct qstr *name)
 {
 	struct nfs4_remove_arg args = {
 		.fh = NFS_FH(dir),
@@ -982,7 +1372,19 @@
 	status = rpc_call_sync(NFS_CLIENT(dir), &msg, 0);
 	if (status == 0)
 		update_changeattr(dir, &res);
-	return nfs4_map_errors(status);
+	return status;
+}
+
+static int nfs4_proc_remove(struct inode *dir, struct qstr *name)
+{
+	struct nfs4_exception exception = { };
+	int err;
+	do {
+		err = nfs4_handle_exception(NFS_SERVER(dir),
+				_nfs4_proc_remove(dir, name),
+				&exception);
+	} while (exception.retry);
+	return err;
 }
 
 struct unlink_desc {
@@ -1023,7 +1425,7 @@
 	return 0;
 }
 
-static int nfs4_proc_rename(struct inode *old_dir, struct qstr *old_name,
+static int _nfs4_proc_rename(struct inode *old_dir, struct qstr *old_name,
 		struct inode *new_dir, struct qstr *new_name)
 {
 	struct nfs4_rename_arg arg = {
@@ -1046,10 +1448,24 @@
 		update_changeattr(old_dir, &res.old_cinfo);
 		update_changeattr(new_dir, &res.new_cinfo);
 	}
-	return nfs4_map_errors(status);
+	return status;
 }
 
-static int nfs4_proc_link(struct inode *inode, struct inode *dir, struct qstr *name)
+static int nfs4_proc_rename(struct inode *old_dir, struct qstr *old_name,
+		struct inode *new_dir, struct qstr *new_name)
+{
+	struct nfs4_exception exception = { };
+	int err;
+	do {
+		err = nfs4_handle_exception(NFS_SERVER(old_dir),
+				_nfs4_proc_rename(old_dir, old_name,
+					new_dir, new_name),
+				&exception);
+	} while (exception.retry);
+	return err;
+}
+
+static int _nfs4_proc_link(struct inode *inode, struct inode *dir, struct qstr *name)
 {
 	struct nfs4_link_arg arg = {
 		.fh     = NFS_FH(inode),
@@ -1068,10 +1484,22 @@
 	if (!status)
 		update_changeattr(dir, &cinfo);
 
-	return nfs4_map_errors(status);
+	return status;
 }
 
-static int nfs4_proc_symlink(struct inode *dir, struct qstr *name,
+static int nfs4_proc_link(struct inode *inode, struct inode *dir, struct qstr *name)
+{
+	struct nfs4_exception exception = { };
+	int err;
+	do {
+		err = nfs4_handle_exception(NFS_SERVER(inode),
+				_nfs4_proc_link(inode, dir, name),
+				&exception);
+	} while (exception.retry);
+	return err;
+}
+
+static int _nfs4_proc_symlink(struct inode *dir, struct qstr *name,
 		struct qstr *path, struct iattr *sattr, struct nfs_fh *fhandle,
 		struct nfs_fattr *fattr)
 {
@@ -1090,22 +1518,39 @@
 		.fattr = fattr,
 	};
 	struct rpc_message msg = {
-		.rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_CREATE],
+		.rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_SYMLINK],
 		.rpc_argp = &arg,
 		.rpc_resp = &res,
 	};
 	int			status;
 
+	if (path->len > NFS4_MAXPATHLEN)
+		return -ENAMETOOLONG;
 	arg.u.symlink = path;
 	fattr->valid = 0;
 	
 	status = rpc_call_sync(NFS_CLIENT(dir), &msg, 0);
 	if (!status)
 		update_changeattr(dir, &res.dir_cinfo);
-	return nfs4_map_errors(status);
+	return status;
 }
 
-static int nfs4_proc_mkdir(struct inode *dir, struct qstr *name,
+static int nfs4_proc_symlink(struct inode *dir, struct qstr *name,
+		struct qstr *path, struct iattr *sattr, struct nfs_fh *fhandle,
+		struct nfs_fattr *fattr)
+{
+	struct nfs4_exception exception = { };
+	int err;
+	do {
+		err = nfs4_handle_exception(NFS_SERVER(dir),
+				_nfs4_proc_symlink(dir, name, path, sattr,
+					fhandle, fattr),
+				&exception);
+	} while (exception.retry);
+	return err;
+}
+
+static int _nfs4_proc_mkdir(struct inode *dir, struct qstr *name,
 		struct iattr *sattr, struct nfs_fh *fhandle,
 		struct nfs_fattr *fattr)
 {
@@ -1135,10 +1580,25 @@
 	status = rpc_call_sync(NFS_CLIENT(dir), &msg, 0);
 	if (!status)
 		update_changeattr(dir, &res.dir_cinfo);
-	return nfs4_map_errors(status);
+	return status;
 }
 
-static int nfs4_proc_readdir(struct dentry *dentry, struct rpc_cred *cred,
+static int nfs4_proc_mkdir(struct inode *dir, struct qstr *name,
+		struct iattr *sattr, struct nfs_fh *fhandle,
+		struct nfs_fattr *fattr)
+{
+	struct nfs4_exception exception = { };
+	int err;
+	do {
+		err = nfs4_handle_exception(NFS_SERVER(dir),
+				_nfs4_proc_mkdir(dir, name, sattr,
+					fhandle, fattr),
+				&exception);
+	} while (exception.retry);
+	return err;
+}
+
+static int _nfs4_proc_readdir(struct dentry *dentry, struct rpc_cred *cred,
                   u64 cookie, struct page *page, unsigned int count, int plus)
 {
 	struct inode		*dir = dentry->d_inode;
@@ -1164,10 +1624,24 @@
 	if (status == 0)
 		memcpy(NFS_COOKIEVERF(dir), res.verifier.data, NFS4_VERIFIER_SIZE);
 	unlock_kernel();
-	return nfs4_map_errors(status);
+	return status;
 }
 
-static int nfs4_proc_mknod(struct inode *dir, struct qstr *name,
+static int nfs4_proc_readdir(struct dentry *dentry, struct rpc_cred *cred,
+                  u64 cookie, struct page *page, unsigned int count, int plus)
+{
+	struct nfs4_exception exception = { };
+	int err;
+	do {
+		err = nfs4_handle_exception(NFS_SERVER(dentry->d_inode),
+				_nfs4_proc_readdir(dentry, cred, cookie,
+					page, count, plus),
+				&exception);
+	} while (exception.retry);
+	return err;
+}
+
+static int _nfs4_proc_mknod(struct inode *dir, struct qstr *name,
 		struct iattr *sattr, dev_t rdev, struct nfs_fh *fh,
 		struct nfs_fattr *fattr)
 {
@@ -1214,10 +1688,25 @@
 	status = rpc_call_sync(NFS_CLIENT(dir), &msg, 0);
 	if (!status)
 		update_changeattr(dir, &res.dir_cinfo);
-	return nfs4_map_errors(status);
+	return status;
+}
+
+static int nfs4_proc_mknod(struct inode *dir, struct qstr *name,
+		struct iattr *sattr, dev_t rdev, struct nfs_fh *fh,
+		struct nfs_fattr *fattr)
+{
+	struct nfs4_exception exception = { };
+	int err;
+	do {
+		err = nfs4_handle_exception(NFS_SERVER(dir),
+				_nfs4_proc_mknod(dir, name, sattr, rdev,
+					fh, fattr),
+				&exception);
+	} while (exception.retry);
+	return err;
 }
 
-static int nfs4_proc_statfs(struct nfs_server *server, struct nfs_fh *fhandle,
+static int _nfs4_proc_statfs(struct nfs_server *server, struct nfs_fh *fhandle,
 		 struct nfs_fsstat *fsstat)
 {
 	struct nfs4_statfs_arg args = {
@@ -1231,10 +1720,22 @@
 	};
 
 	fsstat->fattr->valid = 0;
-	return nfs4_map_errors(rpc_call_sync(server->client, &msg, 0));
+	return rpc_call_sync(server->client, &msg, 0);
 }
 
-static int nfs4_do_fsinfo(struct nfs_server *server, struct nfs_fh *fhandle,
+static int nfs4_proc_statfs(struct nfs_server *server, struct nfs_fh *fhandle, struct nfs_fsstat *fsstat)
+{
+	struct nfs4_exception exception = { };
+	int err;
+	do {
+		err = nfs4_handle_exception(server,
+				_nfs4_proc_statfs(server, fhandle, fsstat),
+				&exception);
+	} while (exception.retry);
+	return err;
+}
+
+static int _nfs4_do_fsinfo(struct nfs_server *server, struct nfs_fh *fhandle,
 		struct nfs_fsinfo *fsinfo)
 {
 	struct nfs4_fsinfo_arg args = {
@@ -1247,16 +1748,29 @@
 		.rpc_resp = fsinfo,
 	};
 
-	return nfs4_map_errors(rpc_call_sync(server->client, &msg, 0));
+	return rpc_call_sync(server->client, &msg, 0);
+}
+
+static int nfs4_do_fsinfo(struct nfs_server *server, struct nfs_fh *fhandle, struct nfs_fsinfo *fsinfo)
+{
+	struct nfs4_exception exception = { };
+	int err;
+
+	do {
+		err = nfs4_handle_exception(server,
+				_nfs4_do_fsinfo(server, fhandle, fsinfo),
+				&exception);
+	} while (exception.retry);
+	return err;
 }
 
 static int nfs4_proc_fsinfo(struct nfs_server *server, struct nfs_fh *fhandle, struct nfs_fsinfo *fsinfo)
 {
 	fsinfo->fattr->valid = 0;
-	return nfs4_map_errors(nfs4_do_fsinfo(server, fhandle, fsinfo));
+	return nfs4_do_fsinfo(server, fhandle, fsinfo);
 }
 
-static int nfs4_proc_pathconf(struct nfs_server *server, struct nfs_fh *fhandle,
+static int _nfs4_proc_pathconf(struct nfs_server *server, struct nfs_fh *fhandle,
 		struct nfs_pathconf *pathconf)
 {
 	struct nfs4_pathconf_arg args = {
@@ -1276,7 +1790,21 @@
 	}
 
 	pathconf->fattr->valid = 0;
-	return nfs4_map_errors(rpc_call_sync(server->client, &msg, 0));
+	return rpc_call_sync(server->client, &msg, 0);
+}
+
+static int nfs4_proc_pathconf(struct nfs_server *server, struct nfs_fh *fhandle,
+		struct nfs_pathconf *pathconf)
+{
+	struct nfs4_exception exception = { };
+	int err;
+
+	do {
+		err = nfs4_handle_exception(server,
+				_nfs4_proc_pathconf(server, fhandle, pathconf),
+				&exception);
+	} while (exception.retry);
+	return err;
 }
 
 static void
@@ -1415,9 +1943,11 @@
 	if (task->tk_status < 0) {
 		switch (task->tk_status) {
 			case -NFS4ERR_STALE_CLIENTID:
+			case -NFS4ERR_EXPIRED:
+			case -NFS4ERR_CB_PATH_DOWN:
 				nfs4_schedule_state_recovery(clp);
-				return;
 		}
+		return;
 	}
 	spin_lock(&clp->cl_lock);
 	if (time_before(clp->cl_last_renewal,timestamp))
@@ -1450,11 +1980,13 @@
 	int status;
 
 	status = rpc_call_sync(clp->cl_rpcclient, &msg, 0);
+	if (status < 0)
+		return status;
 	spin_lock(&clp->cl_lock);
 	if (time_before(clp->cl_last_renewal,now))
 		clp->cl_last_renewal = now;
 	spin_unlock(&clp->cl_lock);
-	return status;
+	return 0;
 }
 
 /*
@@ -1467,8 +1999,10 @@
 nfs4_proc_file_open(struct inode *inode, struct file *filp)
 {
 	struct dentry *dentry = filp->f_dentry;
-	struct nfs4_state *state;
+	struct nfs_open_context *ctx;
+	struct nfs4_state *state = NULL;
 	struct rpc_cred *cred;
+	int status = -ENOMEM;
 
 	dprintk("nfs4_proc_file_open: starting on (%.*s/%.*s)\n",
 	                       (int)dentry->d_parent->d_name.len,
@@ -1478,21 +2012,28 @@
 
 	/* Find our open stateid */
 	cred = rpcauth_lookupcred(NFS_SERVER(inode)->client->cl_auth, 0);
-	state = nfs4_find_state(inode, cred, filp->f_mode);
+	if (unlikely(cred == NULL))
+		return -ENOMEM;
+	ctx = alloc_nfs_open_context(dentry, cred);
 	put_rpccred(cred);
-	if (state == NULL) {
-		printk(KERN_WARNING "NFS: v4 raced in function %s\n", __FUNCTION__);
-		return -EIO; /* ERACE actually */
-	}
+	if (unlikely(ctx == NULL))
+		return -ENOMEM;
+	status = -EIO; /* ERACE actually */
+	state = nfs4_find_state(inode, cred, filp->f_mode);
+	if (unlikely(state == NULL))
+		goto no_state;
+	ctx->state = state;
 	nfs4_close_state(state, filp->f_mode);
-	if (filp->f_mode & FMODE_WRITE) {
-		lock_kernel();
-		nfs_set_mmcred(inode, state->owner->so_cred);
+	ctx->mode = filp->f_mode;
+	nfs_file_set_open_context(filp, ctx);
+	put_nfs_open_context(ctx);
+	if (filp->f_mode & FMODE_WRITE)
 		nfs_begin_data_update(inode);
-		unlock_kernel();
-	}
-	filp->private_data = state;
 	return 0;
+no_state:
+	printk(KERN_WARNING "NFS: v4 raced in function %s\n", __FUNCTION__);
+	put_nfs_open_context(ctx);
+	return status;
 }
 
 /*
@@ -1501,37 +2042,12 @@
 static int
 nfs4_proc_file_release(struct inode *inode, struct file *filp)
 {
-	struct nfs4_state *state = (struct nfs4_state *)filp->private_data;
-
-	if (state)
-		nfs4_close_state(state, filp->f_mode);
-	if (filp->f_mode & FMODE_WRITE) {
-		lock_kernel();
+	if (filp->f_mode & FMODE_WRITE)
 		nfs_end_data_update(inode);
-		unlock_kernel();
-	}
+	nfs_file_clear_open_context(filp);
 	return 0;
 }
 
-/*
- * Set up the nfspage struct with the right state info and credentials
- */
-static void
-nfs4_request_init(struct nfs_page *req, struct file *filp)
-{
-	struct nfs4_state *state;
-
-	if (!filp) {
-		req->wb_cred = get_rpccred(NFS_I(req->wb_inode)->mm_cred);
-		req->wb_state = NULL;
-		return;
-	}
-	state = (struct nfs4_state *)filp->private_data;
-	req->wb_state = state;
-	req->wb_cred = get_rpccred(state->owner->so_cred);
-	req->wb_lockowner = current->files;
-}
-
 static int
 nfs4_async_handle_error(struct rpc_task *task, struct nfs_server *server)
 {
@@ -1545,11 +2061,13 @@
 		case -NFS4ERR_EXPIRED:
 			rpc_sleep_on(&clp->cl_rpcwaitq, task, NULL, NULL);
 			nfs4_schedule_state_recovery(clp);
+			if (test_bit(NFS4CLNT_OK, &clp->cl_state))
+				rpc_wake_up_task(task);
 			task->tk_status = 0;
 			return -EAGAIN;
 		case -NFS4ERR_GRACE:
 		case -NFS4ERR_DELAY:
-			rpc_delay(task, NFS4_POLL_RETRY_TIME);
+			rpc_delay(task, NFS4_POLL_RETRY_MAX);
 			task->tk_status = 0;
 			return -EAGAIN;
 		case -NFS4ERR_OLD_STATEID:
@@ -1560,12 +2078,11 @@
 	return 0;
 }
 
-int
-nfs4_wait_clnt_recover(struct rpc_clnt *clnt, struct nfs4_client *clp)
+int nfs4_wait_clnt_recover(struct rpc_clnt *clnt, struct nfs4_client *clp)
 {
 	DEFINE_WAIT(wait);
 	sigset_t oldset;
-	int interruptible, res;
+	int interruptible, res = 0;
 
 	might_sleep();
 
@@ -1573,101 +2090,85 @@
 	interruptible = TASK_UNINTERRUPTIBLE;
 	if (clnt->cl_intr)
 		interruptible = TASK_INTERRUPTIBLE;
-	do {
-		res = 0;
-		prepare_to_wait(&clp->cl_waitq, &wait, interruptible);
-		nfs4_schedule_state_recovery(clp);
-		if (test_bit(NFS4CLNT_OK, &clp->cl_state) &&
-				!test_bit(NFS4CLNT_SETUP_STATE, &clp->cl_state))
-			break;
-		if (clnt->cl_intr && signalled()) {
-			res = -ERESTARTSYS;
-			break;
-		}
+	prepare_to_wait(&clp->cl_waitq, &wait, interruptible);
+	nfs4_schedule_state_recovery(clp);
+	if (clnt->cl_intr && signalled())
+		res = -ERESTARTSYS;
+	else if (!test_bit(NFS4CLNT_OK, &clp->cl_state))
 		schedule();
-	} while(!test_bit(NFS4CLNT_OK, &clp->cl_state));
 	finish_wait(&clp->cl_waitq, &wait);
 	rpc_clnt_sigunmask(clnt, &oldset);
 	return res;
 }
 
-static int
-nfs4_delay(struct rpc_clnt *clnt)
+static int nfs4_delay(struct rpc_clnt *clnt, long *timeout)
 {
 	sigset_t oldset;
 	int res = 0;
 
 	might_sleep();
 
+	if (*timeout <= 0)
+		*timeout = NFS4_POLL_RETRY_MIN;
+	if (*timeout > NFS4_POLL_RETRY_MAX)
+		*timeout = NFS4_POLL_RETRY_MAX;
 	rpc_clnt_sigmask(clnt, &oldset);
 	if (clnt->cl_intr) {
 		set_current_state(TASK_INTERRUPTIBLE);
-		schedule_timeout(NFS4_POLL_RETRY_TIME);
+		schedule_timeout(*timeout);
 		if (signalled())
 			res = -ERESTARTSYS;
 	} else {
 		set_current_state(TASK_UNINTERRUPTIBLE);
-		schedule_timeout(NFS4_POLL_RETRY_TIME);
+		schedule_timeout(*timeout);
 	}
 	rpc_clnt_sigunmask(clnt, &oldset);
+	*timeout <<= 1;
 	return res;
 }
 
 /* This is the error handling routine for processes that are allowed
  * to sleep.
  */
-int
-nfs4_handle_error(struct nfs_server *server, int errorcode)
+int nfs4_handle_exception(struct nfs_server *server, int errorcode, struct nfs4_exception *exception)
 {
 	struct nfs4_client *clp = server->nfs4_state;
 	int ret = errorcode;
 
+	exception->retry = 0;
 	switch(errorcode) {
+		case 0:
+			return 0;
 		case -NFS4ERR_STALE_CLIENTID:
 		case -NFS4ERR_STALE_STATEID:
 		case -NFS4ERR_EXPIRED:
 			ret = nfs4_wait_clnt_recover(server->client, clp);
+			if (ret == 0)
+				exception->retry = 1;
 			break;
 		case -NFS4ERR_GRACE:
 		case -NFS4ERR_DELAY:
-			ret = nfs4_delay(server->client);
+			ret = nfs4_delay(server->client, &exception->timeout);
+			if (ret == 0)
+				exception->retry = 1;
 			break;
 		case -NFS4ERR_OLD_STATEID:
-			ret = 0;
+			if (ret == 0)
+				exception->retry = 1;
 	}
 	/* We failed to handle the error */
 	return nfs4_map_errors(ret);
 }
 
-
-static int
-nfs4_request_compatible(struct nfs_page *req, struct file *filp, struct page *page)
-{
-	struct nfs4_state *state = NULL;
-	struct rpc_cred *cred = NULL;
-
-	if (req->wb_file != filp)
-		return 0;
-	if (req->wb_page != page)
-		return 0;
-	state = (struct nfs4_state *)filp->private_data;
-	if (req->wb_state != state)
-		return 0;
-	if (req->wb_lockowner != current->files)
-		return 0;
-	cred = state->owner->so_cred;
-	if (req->wb_cred != cred)
-		return 0;
-	return 1;
-}
-
-int
-nfs4_proc_setclientid(struct nfs4_client *clp,
-		u32 program, unsigned short port)
+int nfs4_proc_setclientid(struct nfs4_client *clp, u32 program, unsigned short port)
 {
-	u32 *p;
-	struct nfs4_setclientid setclientid;
-	struct timespec tv;
+	static nfs4_verifier sc_verifier;
+	static int initialized;
+	
+	struct nfs4_setclientid setclientid = {
+		.sc_verifier = &sc_verifier,
+		.sc_prog = program,
+	};
 	struct rpc_message msg = {
 		.rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_SETCLIENTID],
 		.rpc_argp = &setclientid,
@@ -1675,15 +2176,24 @@
 		.rpc_cred = clp->cl_cred,
 	};
 
-	tv = CURRENT_TIME;
-	p = (u32*)setclientid.sc_verifier.data;
-	*p++ = (u32)tv.tv_sec;
-	*p = (u32)tv.tv_nsec;
-	setclientid.sc_name = clp->cl_ipaddr;
-	sprintf(setclientid.sc_netid, "tcp");
-	sprintf(setclientid.sc_uaddr, "%s.%d.%d", clp->cl_ipaddr, port >> 8, port & 255);
-	setclientid.sc_prog = htonl(program);
-	setclientid.sc_cb_ident = 0;
+	if (!initialized) {
+		struct timespec boot_time;
+		u32 *p;
+
+		initialized = 1;
+		boot_time = CURRENT_TIME;
+		p = (u32*)sc_verifier.data;
+		*p++ = htonl((u32)boot_time.tv_sec);
+		*p = htonl((u32)boot_time.tv_nsec);
+	}
+	setclientid.sc_name_len = scnprintf(setclientid.sc_name,
+			sizeof(setclientid.sc_name), "%s/%u.%u.%u.%u",
+			clp->cl_ipaddr, NIPQUAD(clp->cl_addr.s_addr));
+	setclientid.sc_netid_len = scnprintf(setclientid.sc_netid,
+			sizeof(setclientid.sc_netid), "tcp");
+	setclientid.sc_uaddr_len = scnprintf(setclientid.sc_uaddr,
+			sizeof(setclientid.sc_uaddr), "%s.%d.%d",
+			clp->cl_ipaddr, port >> 8, port & 255);
 
 	return rpc_call_sync(clp->cl_rpcclient, &msg, 0);
 }
@@ -1712,6 +2222,40 @@
 	return status;
 }
 
+static int _nfs4_proc_delegreturn(struct inode *inode, struct rpc_cred *cred, const nfs4_stateid *stateid)
+{
+	struct nfs4_delegreturnargs args = {
+		.fhandle = NFS_FH(inode),
+		.stateid = stateid,
+	};
+	struct rpc_message msg = {
+		.rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_DELEGRETURN],
+		.rpc_argp = &args,
+		.rpc_cred = cred,
+	};
+
+	return rpc_call_sync(NFS_CLIENT(inode), &msg, 0);
+}
+
+int nfs4_proc_delegreturn(struct inode *inode, struct rpc_cred *cred, const nfs4_stateid *stateid)
+{
+	struct nfs_server *server = NFS_SERVER(inode);
+	struct nfs4_exception exception = { };
+	int err;
+	do {
+		err = _nfs4_proc_delegreturn(inode, cred, stateid);
+		switch (err) {
+			case -NFS4ERR_STALE_STATEID:
+			case -NFS4ERR_EXPIRED:
+				nfs4_schedule_state_recovery(server->nfs4_state);
+			case 0:
+				return 0;
+		}
+		err = nfs4_handle_exception(server, err, &exception);
+	} while (exception.retry);
+	return err;
+}
+
 #define NFS4_LOCK_MINTIMEOUT (1 * HZ)
 #define NFS4_LOCK_MAXTIMEOUT (30 * HZ)
 
@@ -1753,8 +2297,7 @@
 	return request->fl_end - request->fl_start + 1;
 }
 
-int
-nfs4_proc_getlk(struct nfs4_state *state, int cmd, struct file_lock *request)
+static int _nfs4_proc_getlk(struct nfs4_state *state, int cmd, struct file_lock *request)
 {
 	struct inode *inode = state->inode;
 	struct nfs_server *server = NFS_SERVER(inode);
@@ -1778,6 +2321,7 @@
 	struct nfs4_lock_state *lsp;
 	int status;
 
+	down_read(&clp->cl_sem);
 	nlo.clientid = clp->cl_clientid;
 	down(&state->lock_sema);
 	lsp = nfs4_find_lock_state(state, request->fl_owner);
@@ -1811,14 +2355,28 @@
 	if (lsp)
 		nfs4_put_lock_state(lsp);
 	up(&state->lock_sema);
-	return nfs4_map_errors(status);
+	up_read(&clp->cl_sem);
+	return status;
 }
 
-int
-nfs4_proc_unlck(struct nfs4_state *state, int cmd, struct file_lock *request)
+static int nfs4_proc_getlk(struct nfs4_state *state, int cmd, struct file_lock *request)
+{
+	struct nfs4_exception exception = { };
+	int err;
+
+	do {
+		err = nfs4_handle_exception(NFS_SERVER(state->inode),
+				_nfs4_proc_getlk(state, cmd, request),
+				&exception);
+	} while (exception.retry);
+	return err;
+}
+
+static int _nfs4_proc_unlck(struct nfs4_state *state, int cmd, struct file_lock *request)
 {
 	struct inode *inode = state->inode;
 	struct nfs_server *server = NFS_SERVER(inode);
+	struct nfs4_client *clp = server->nfs4_state;
 	struct nfs_lockargs arg = {
 		.fh = NFS_FH(inode),
 		.type = nfs4_lck_type(cmd, request),
@@ -1838,29 +2396,48 @@
 	struct nfs_locku_opargs luargs;
 	int status = 0;
 			
+	down_read(&clp->cl_sem);
 	down(&state->lock_sema);
 	lsp = nfs4_find_lock_state(state, request->fl_owner);
 	if (!lsp)
 		goto out;
-	luargs.seqid = lsp->ls_seqid;
-	memcpy(&luargs.stateid, &lsp->ls_stateid, sizeof(luargs.stateid));
-	arg.u.locku = &luargs;
-	status = rpc_call_sync(server->client, &msg, 0);
-	nfs4_increment_lock_seqid(status, lsp);
+	/* We might have lost the locks! */
+	if ((lsp->ls_flags & NFS_LOCK_INITIALIZED) != 0) {
+		luargs.seqid = lsp->ls_seqid;
+		memcpy(&luargs.stateid, &lsp->ls_stateid, sizeof(luargs.stateid));
+		arg.u.locku = &luargs;
+		status = rpc_call_sync(server->client, &msg, RPC_TASK_NOINTR);
+		nfs4_increment_lock_seqid(status, lsp);
+	}
 
 	if (status == 0) {
 		memcpy(&lsp->ls_stateid,  &res.u.stateid, 
 				sizeof(lsp->ls_stateid));
-		nfs4_notify_unlck(inode, request, lsp);
+		nfs4_notify_unlck(state, request, lsp);
 	}
 	nfs4_put_lock_state(lsp);
 out:
 	up(&state->lock_sema);
-	return nfs4_map_errors(status);
+	if (status == 0)
+		posix_lock_file(request->fl_file, request);
+	up_read(&clp->cl_sem);
+	return status;
 }
 
-static int
-nfs4_proc_setlk(struct nfs4_state *state, int cmd, struct file_lock *request)
+static int nfs4_proc_unlck(struct nfs4_state *state, int cmd, struct file_lock *request)
+{
+	struct nfs4_exception exception = { };
+	int err;
+
+	do {
+		err = nfs4_handle_exception(NFS_SERVER(state->inode),
+				_nfs4_proc_unlck(state, cmd, request),
+				&exception);
+	} while (exception.retry);
+	return err;
+}
+
+static int _nfs4_do_setlk(struct nfs4_state *state, int cmd, struct file_lock *request, int reclaim)
 {
 	struct inode *inode = state->inode;
 	struct nfs_server *server = NFS_SERVER(inode);
@@ -1881,23 +2458,22 @@
 		.rpc_cred	= state->owner->so_cred,
 	};
 	struct nfs_lock_opargs largs = {
+		.reclaim = reclaim,
 		.new_lock_owner = 0,
 	};
 	int status;
 
-	down(&state->lock_sema);
-	lsp = nfs4_find_lock_state(state, request->fl_owner);
-	if (lsp == NULL) {
+	lsp = nfs4_get_lock_state(state, request->fl_owner);
+	if (lsp == NULL)
+		return -ENOMEM;
+	if (!(lsp->ls_flags & NFS_LOCK_INITIALIZED)) {
 		struct nfs4_state_owner *owner = state->owner;
 		struct nfs_open_to_lock otl = {
 			.lock_owner = {
 				.clientid = server->nfs4_state->cl_clientid,
 			},
 		};
-		status = -ENOMEM;
-		lsp = nfs4_alloc_lock_state(state, request->fl_owner);
-		if (!lsp)
-			goto out;
+
 		otl.lock_seqid = lsp->ls_seqid;
 		otl.lock_owner.id = lsp->ls_id;
 		memcpy(&otl.open_stateid, &state->stateid, sizeof(otl.open_stateid));
@@ -1906,7 +2482,7 @@
 		arg.u.lock = &largs;
 		down(&owner->so_sema);
 		otl.open_seqid = owner->so_seqid;
-		status = rpc_call_sync(server->client, &msg, 0);
+		status = rpc_call_sync(server->client, &msg, RPC_TASK_NOINTR);
 		/* increment open_owner seqid on success, and 
 		* seqid mutating errors */
 		nfs4_increment_seqid(status, owner);
@@ -1919,32 +2495,70 @@
 		largs.u.exist_lock = &el;
 		largs.new_lock_owner = 0;
 		arg.u.lock = &largs;
-		status = rpc_call_sync(server->client, &msg, 0);
+		status = rpc_call_sync(server->client, &msg, RPC_TASK_NOINTR);
 	}
 	/* increment seqid on success, and * seqid mutating errors*/
 	nfs4_increment_lock_seqid(status, lsp);
 	/* save the returned stateid. */
 	if (status == 0) {
 		memcpy(&lsp->ls_stateid, &res.u.stateid, sizeof(nfs4_stateid));
-		nfs4_notify_setlk(inode, request, lsp);
+		lsp->ls_flags |= NFS_LOCK_INITIALIZED;
+		if (!reclaim)
+			nfs4_notify_setlk(state, request, lsp);
 	} else if (status == -NFS4ERR_DENIED)
 		status = -EAGAIN;
 	nfs4_put_lock_state(lsp);
-out:
+	return status;
+}
+
+int nfs4_lock_reclaim(struct nfs4_state *state, struct file_lock *request)
+{
+	return _nfs4_do_setlk(state, F_SETLK, request, 1);
+}
+
+static int _nfs4_proc_setlk(struct nfs4_state *state, int cmd, struct file_lock *request)
+{
+	struct nfs4_client *clp = state->owner->so_client;
+	int status;
+
+	down_read(&clp->cl_sem);
+	down(&state->lock_sema);
+	status = _nfs4_do_setlk(state, cmd, request, 0);
 	up(&state->lock_sema);
-	return nfs4_map_errors(status);
+	if (status == 0) {
+		/* Note: we always want to sleep here! */
+		request->fl_flags |= FL_SLEEP;
+		if (posix_lock_file_wait(request->fl_file, request) < 0)
+			printk(KERN_WARNING "%s: VFS is out of sync with lock manager!\n", __FUNCTION__);
+	}
+	up_read(&clp->cl_sem);
+	return status;
+}
+
+static int nfs4_proc_setlk(struct nfs4_state *state, int cmd, struct file_lock *request)
+{
+	struct nfs4_exception exception = { };
+	int err;
+
+	do {
+		err = nfs4_handle_exception(NFS_SERVER(state->inode),
+				_nfs4_proc_setlk(state, cmd, request),
+				&exception);
+	} while (exception.retry);
+	return err;
 }
 
 static int
 nfs4_proc_lock(struct file *filp, int cmd, struct file_lock *request)
 {
+	struct nfs_open_context *ctx;
 	struct nfs4_state *state;
 	unsigned long timeout = NFS4_LOCK_MINTIMEOUT;
 	int status;
 
 	/* verify open state */
-	state = (struct nfs4_state *)filp->private_data;
-	BUG_ON(!state);
+	ctx = (struct nfs_open_context *)filp->private_data;
+	state = ctx->state;
 
 	if (request->fl_start < 0 || request->fl_end < 0)
 		return -EINVAL;
@@ -2004,8 +2618,6 @@
 	.commit_setup	= nfs4_proc_commit_setup,
 	.file_open      = nfs4_proc_file_open,
 	.file_release   = nfs4_proc_file_release,
-	.request_init	= nfs4_request_init,
-	.request_compatible = nfs4_request_compatible,
 	.lock		= nfs4_proc_lock,
 };
 
diff -Nru a/fs/nfs/nfs4state.c b/fs/nfs/nfs4state.c
--- a/fs/nfs/nfs4state.c	2004-10-18 14:55:54 -07:00
+++ b/fs/nfs/nfs4state.c	2004-10-18 14:55:54 -07:00
@@ -40,11 +40,15 @@
 
 #include <linux/config.h>
 #include <linux/slab.h>
+#include <linux/smp_lock.h>
 #include <linux/nfs_fs.h>
 #include <linux/nfs_idmap.h>
 #include <linux/workqueue.h>
 #include <linux/bitops.h>
 
+#include "callback.h"
+#include "delegation.h"
+
 #define OPENOWNER_POOL_SIZE	8
 
 static spinlock_t		state_spinlock = SPIN_LOCK_UNLOCKED;
@@ -93,21 +97,26 @@
 {
 	struct nfs4_client *clp;
 
-	if ((clp = kmalloc(sizeof(*clp), GFP_KERNEL))) {
-		memset(clp, 0, sizeof(*clp));
-		memcpy(&clp->cl_addr, addr, sizeof(clp->cl_addr));
-		init_rwsem(&clp->cl_sem);
-		INIT_LIST_HEAD(&clp->cl_state_owners);
-		INIT_LIST_HEAD(&clp->cl_unused);
-		spin_lock_init(&clp->cl_lock);
-		atomic_set(&clp->cl_count, 1);
-		INIT_WORK(&clp->cl_recoverd, nfs4_recover_state, clp);
-		INIT_WORK(&clp->cl_renewd, nfs4_renew_state, clp);
-		INIT_LIST_HEAD(&clp->cl_superblocks);
-		init_waitqueue_head(&clp->cl_waitq);
-		rpc_init_wait_queue(&clp->cl_rpcwaitq, "NFS4 client");
-		clp->cl_state = 1 << NFS4CLNT_NEW;
+	if (nfs_callback_up() < 0)
+		return NULL;
+	if ((clp = kmalloc(sizeof(*clp), GFP_KERNEL)) == NULL) {
+		nfs_callback_down();
+		return NULL;
 	}
+	memset(clp, 0, sizeof(*clp));
+	memcpy(&clp->cl_addr, addr, sizeof(clp->cl_addr));
+	init_rwsem(&clp->cl_sem);
+	INIT_LIST_HEAD(&clp->cl_delegations);
+	INIT_LIST_HEAD(&clp->cl_state_owners);
+	INIT_LIST_HEAD(&clp->cl_unused);
+	spin_lock_init(&clp->cl_lock);
+	atomic_set(&clp->cl_count, 1);
+	INIT_WORK(&clp->cl_recoverd, nfs4_recover_state, clp);
+	INIT_WORK(&clp->cl_renewd, nfs4_renew_state, clp);
+	INIT_LIST_HEAD(&clp->cl_superblocks);
+	init_waitqueue_head(&clp->cl_waitq);
+	rpc_init_wait_queue(&clp->cl_rpcwaitq, "NFS4 client");
+	clp->cl_state = 1 << NFS4CLNT_OK;
 	return clp;
 }
 
@@ -130,25 +139,52 @@
 	if (clp->cl_rpcclient)
 		rpc_shutdown_client(clp->cl_rpcclient);
 	kfree(clp);
+	nfs_callback_down();
+}
+
+static struct nfs4_client *__nfs4_find_client(struct in_addr *addr)
+{
+	struct nfs4_client *clp;
+	list_for_each_entry(clp, &nfs4_clientid_list, cl_servers) {
+		if (memcmp(&clp->cl_addr, addr, sizeof(clp->cl_addr)) == 0) {
+			atomic_inc(&clp->cl_count);
+			return clp;
+		}
+	}
+	return NULL;
+}
+
+struct nfs4_client *nfs4_find_client(struct in_addr *addr)
+{
+	struct nfs4_client *clp;
+	spin_lock(&state_spinlock);
+	clp = __nfs4_find_client(addr);
+	spin_unlock(&state_spinlock);
+	return clp;
 }
 
 struct nfs4_client *
 nfs4_get_client(struct in_addr *addr)
 {
-	struct nfs4_client *new, *clp = NULL;
+	struct nfs4_client *clp, *new = NULL;
 
-	new = nfs4_alloc_client(addr);
 	spin_lock(&state_spinlock);
-	list_for_each_entry(clp, &nfs4_clientid_list, cl_servers) {
-		if (memcmp(&clp->cl_addr, addr, sizeof(clp->cl_addr)) == 0)
-			goto found;
+	for (;;) {
+		clp = __nfs4_find_client(addr);
+		if (clp != NULL)
+			break;
+		clp = new;
+		if (clp != NULL) {
+			list_add(&clp->cl_servers, &nfs4_clientid_list);
+			new = NULL;
+			break;
+		}
+		spin_unlock(&state_spinlock);
+		new = nfs4_alloc_client(addr);
+		spin_lock(&state_spinlock);
+		if (new == NULL)
+			break;
 	}
-	if (new)
-		list_add(&new->cl_servers, &nfs4_clientid_list);
-	spin_unlock(&state_spinlock);
-	return new;
-found:
-	atomic_inc(&clp->cl_count);
 	spin_unlock(&state_spinlock);
 	if (new)
 		nfs4_free_client(new);
@@ -169,6 +205,16 @@
 	nfs4_free_client(clp);
 }
 
+int nfs4_init_client(struct nfs4_client *clp)
+{
+	int status = nfs4_proc_setclientid(clp, NFS4_CALLBACK, nfs_callback_tcpport);
+	if (status == 0)
+		status = nfs4_proc_setclientid_confirm(clp);
+	if (status == 0)
+		nfs4_schedule_state_renewal(clp);
+	return status;
+}
+
 u32
 nfs4_alloc_lockowner_id(struct nfs4_client *clp)
 {
@@ -185,7 +231,6 @@
 		atomic_inc(&sp->so_count);
 		sp->so_cred = cred;
 		list_move(&sp->so_list, &clp->cl_state_owners);
-		sp->so_generation = clp->cl_generation;
 		clp->cl_nunused--;
 	}
 	return sp;
@@ -224,6 +269,7 @@
 	init_MUTEX(&sp->so_sema);
 	sp->so_seqid = 0;                 /* arbitrary */
 	INIT_LIST_HEAD(&sp->so_states);
+	INIT_LIST_HEAD(&sp->so_delegations);
 	atomic_set(&sp->so_count, 1);
 	return sp;
 }
@@ -237,8 +283,11 @@
 	spin_unlock(&clp->cl_lock);
 }
 
-struct nfs4_state_owner *
-nfs4_get_state_owner(struct nfs_server *server, struct rpc_cred *cred)
+/*
+ * Note: must be called with clp->cl_sem held in order to prevent races
+ *       with reboot recovery!
+ */
+struct nfs4_state_owner *nfs4_get_state_owner(struct nfs_server *server, struct rpc_cred *cred)
 {
 	struct nfs4_client *clp = server->nfs4_state;
 	struct nfs4_state_owner *sp, *new;
@@ -254,23 +303,23 @@
 		new->so_client = clp;
 		new->so_id = nfs4_alloc_lockowner_id(clp);
 		new->so_cred = cred;
-		new->so_generation = clp->cl_generation;
 		sp = new;
 		new = NULL;
 	}
 	spin_unlock(&clp->cl_lock);
 	if (new)
 		kfree(new);
-	if (sp) {
-		if (!test_bit(NFS4CLNT_OK, &clp->cl_state))
-			nfs4_wait_clnt_recover(server->client, clp);
-	} else
-		put_rpccred(cred);
-	return sp;
+	if (sp != NULL)
+		return sp;
+	put_rpccred(cred);
+	return NULL;
 }
 
-void
-nfs4_put_state_owner(struct nfs4_state_owner *sp)
+/*
+ * Must be called with clp->cl_sem held in order to avoid races
+ * with state recovery...
+ */
+void nfs4_put_state_owner(struct nfs4_state_owner *sp)
 {
 	struct nfs4_client *clp = sp->so_client;
 	struct rpc_cred *cred = sp->so_cred;
@@ -330,8 +379,6 @@
 			continue;
 		if ((state->state & mode) != mode)
 			continue;
-		/* Add the state to the head of the inode's list */
-		list_move(&state->inode_states, &nfsi->open_states);
 		atomic_inc(&state->count);
 		if (mode & FMODE_READ)
 			state->nreaders++;
@@ -353,8 +400,6 @@
 		if (state->nreaders == 0 && state->nwriters == 0)
 			continue;
 		if (state->owner == owner) {
-			/* Add the state to the head of the inode's list */
-			list_move(&state->inode_states, &nfsi->open_states);
 			atomic_inc(&state->count);
 			return state;
 		}
@@ -411,51 +456,40 @@
 	return state;
 }
 
-static void
-__nfs4_put_open_state(struct nfs4_state *state)
+/*
+ * Beware! Caller must be holding exactly one
+ * reference to clp->cl_sem and owner->so_sema!
+ */
+void nfs4_put_open_state(struct nfs4_state *state)
 {
 	struct inode *inode = state->inode;
 	struct nfs4_state_owner *owner = state->owner;
-	int status = 0;
 
-	if (!atomic_dec_and_lock(&state->count, &inode->i_lock)) {
-		up(&owner->so_sema);
+	if (!atomic_dec_and_lock(&state->count, &inode->i_lock))
 		return;
-	}
 	if (!list_empty(&state->inode_states))
 		list_del(&state->inode_states);
 	spin_unlock(&inode->i_lock);
 	list_del(&state->open_states);
-	if (state->state != 0) {
-		do {
-			status = nfs4_do_close(inode, state);
-			if (!status)
-				break;
-			up(&owner->so_sema);
-			status = nfs4_handle_error(NFS_SERVER(inode), status);
-			down(&owner->so_sema);
-		} while (!status);
-	}
-	up(&owner->so_sema);
+	BUG_ON (state->state != 0);
 	nfs4_free_open_state(state);
 	nfs4_put_state_owner(owner);
 }
 
-void
-nfs4_put_open_state(struct nfs4_state *state)
-{
-	down(&state->owner->so_sema);
-	__nfs4_put_open_state(state);
-}
-
-void
-nfs4_close_state(struct nfs4_state *state, mode_t mode)
+/*
+ * Beware! Caller must be holding no references to clp->cl_sem!
+ * of owner->so_sema!
+ */
+void nfs4_close_state(struct nfs4_state *state, mode_t mode)
 {
 	struct inode *inode = state->inode;
 	struct nfs4_state_owner *owner = state->owner;
+	struct nfs4_client *clp = owner->so_client;
 	int newstate;
 	int status = 0;
 
+	atomic_inc(&owner->so_count);
+	down_read(&clp->cl_sem);
 	down(&owner->so_sema);
 	/* Protect against nfs4_find_state() */
 	spin_lock(&inode->i_lock);
@@ -466,29 +500,24 @@
 	if (state->nwriters == 0 && state->nreaders == 0)
 		list_del_init(&state->inode_states);
 	spin_unlock(&inode->i_lock);
-	do {
-		newstate = 0;
-		if (state->state == 0)
-			break;
+	newstate = 0;
+	if (state->state != 0) {
 		if (state->nreaders)
 			newstate |= FMODE_READ;
 		if (state->nwriters)
 			newstate |= FMODE_WRITE;
 		if (state->state == newstate)
-			break;
+			goto out;
 		if (newstate != 0)
 			status = nfs4_do_downgrade(inode, state, newstate);
 		else
 			status = nfs4_do_close(inode, state);
-		if (!status) {
-			state->state = newstate;
-			break;
-		}
-		up(&owner->so_sema);
-		status = nfs4_handle_error(NFS_SERVER(inode), status);
-		down(&owner->so_sema);
-	} while (!status);
-	__nfs4_put_open_state(state);
+	}
+out:
+	nfs4_put_open_state(state);
+	up(&owner->so_sema);
+	nfs4_put_state_owner(owner);
+	up_read(&clp->cl_sem);
 }
 
 /*
@@ -524,8 +553,7 @@
  *
  * The caller must be holding state->lock_sema
  */
-struct nfs4_lock_state *
-nfs4_alloc_lock_state(struct nfs4_state *state, fl_owner_t fl_owner)
+static struct nfs4_lock_state *nfs4_alloc_lock_state(struct nfs4_state *state, fl_owner_t fl_owner)
 {
 	struct nfs4_lock_state *lsp;
 	struct nfs4_client *clp = state->owner->so_client;
@@ -533,12 +561,12 @@
 	lsp = kmalloc(sizeof(*lsp), GFP_KERNEL);
 	if (lsp == NULL)
 		return NULL;
+	lsp->ls_flags = 0;
 	lsp->ls_seqid = 0;	/* arbitrary */
 	lsp->ls_id = -1; 
 	memset(lsp->ls_stateid.data, 0, sizeof(lsp->ls_stateid.data));
 	atomic_set(&lsp->ls_count, 1);
 	lsp->ls_owner = fl_owner;
-	lsp->ls_parent = state;
 	INIT_LIST_HEAD(&lsp->ls_locks);
 	spin_lock(&clp->cl_lock);
 	lsp->ls_id = nfs4_alloc_lockowner_id(clp);
@@ -547,6 +575,22 @@
 }
 
 /*
+ * Return a compatible lock_state. If no initialized lock_state structure
+ * exists, return an uninitialized one.
+ *
+ * The caller must be holding state->lock_sema and clp->cl_sem
+ */
+struct nfs4_lock_state *nfs4_get_lock_state(struct nfs4_state *state, fl_owner_t owner)
+{
+	struct nfs4_lock_state * lsp;
+	
+	lsp = nfs4_find_lock_state(state, owner);
+	if (lsp == NULL)
+		lsp = nfs4_alloc_lock_state(state, owner);
+	return lsp;
+}
+
+/*
  * Byte-range lock aware utility to initialize the stateid of read/write
  * requests.
  */
@@ -567,10 +611,9 @@
 }
 
 /*
-* Called with state->lock_sema held.
+* Called with state->lock_sema and clp->cl_sem held.
 */
-void
-nfs4_increment_lock_seqid(int status, struct nfs4_lock_state *lsp)
+void nfs4_increment_lock_seqid(int status, struct nfs4_lock_state *lsp)
 {
 	if (status == NFS_OK || seqid_mutating_err(-status))
 		lsp->ls_seqid++;
@@ -597,13 +640,11 @@
 /*
  * Post an initialized lock_state on the state->lock_states list.
  */
-void
-nfs4_notify_setlk(struct inode *inode, struct file_lock *request, struct nfs4_lock_state *lsp)
+void nfs4_notify_setlk(struct nfs4_state *state, struct file_lock *request, struct nfs4_lock_state *lsp)
 {
-	struct nfs4_state *state = lsp->ls_parent;
-
 	if (!list_empty(&lsp->ls_locks))
 		return;
+	atomic_inc(&lsp->ls_count);
 	write_lock(&state->state_lock);
 	list_add(&lsp->ls_locks, &state->lock_states);
 	set_bit(LK_STATE_IN_USE, &state->flags);
@@ -620,9 +661,9 @@
  *
  */
 void
-nfs4_notify_unlck(struct inode *inode, struct file_lock *request, struct nfs4_lock_state *lsp)
+nfs4_notify_unlck(struct nfs4_state *state, struct file_lock *request, struct nfs4_lock_state *lsp)
 {
-	struct nfs4_state *state = lsp->ls_parent;
+	struct inode *inode = state->inode;
 	struct file_lock *fl;
 
 	for (fl = inode->i_flock; fl != NULL; fl = fl->fl_next) {
@@ -640,6 +681,7 @@
 	if (list_empty(&state->lock_states))
 		clear_bit(LK_STATE_IN_USE, &state->flags);
 	write_unlock(&state->state_lock);
+	nfs4_put_lock_state(lsp);
 }
 
 /*
@@ -651,20 +693,18 @@
 {
 	if (!atomic_dec_and_test(&lsp->ls_count))
 		return;
-	if (!list_empty(&lsp->ls_locks))
-		return;
+	BUG_ON (!list_empty(&lsp->ls_locks));
 	kfree(lsp);
 }
 
 /*
-* Called with sp->so_sema held.
+* Called with sp->so_sema and clp->cl_sem held.
 *
 * Increment the seqid if the OPEN/OPEN_DOWNGRADE/CLOSE succeeded, or
 * failed with a seqid incrementing error -
 * see comments nfs_fs.h:seqid_mutating_error()
 */
-void
-nfs4_increment_seqid(int status, struct nfs4_state_owner *sp)
+void nfs4_increment_seqid(int status, struct nfs4_state_owner *sp)
 {
 	if (status == NFS_OK || seqid_mutating_err(-status))
 		sp->so_seqid++;
@@ -693,21 +733,14 @@
 
 	init_completion(&args.complete);
 
-	down_read(&clp->cl_sem);
-	if (test_and_set_bit(NFS4CLNT_SETUP_STATE, &clp->cl_state))
-		goto out_failed;
 	if (kernel_thread(reclaimer, &args, CLONE_KERNEL) < 0)
 		goto out_failed_clear;
 	wait_for_completion(&args.complete);
 	return;
 out_failed_clear:
-	smp_mb__before_clear_bit();
-	clear_bit(NFS4CLNT_SETUP_STATE, &clp->cl_state);
-	smp_mb__after_clear_bit();
+	set_bit(NFS4CLNT_OK, &clp->cl_state);
 	wake_up_all(&clp->cl_waitq);
 	rpc_wake_up(&clp->cl_rpcwaitq);
-out_failed:
-	up_read(&clp->cl_sem);
 }
 
 /*
@@ -718,24 +751,66 @@
 {
 	if (!clp)
 		return;
-	smp_mb__before_clear_bit();
-	clear_bit(NFS4CLNT_OK, &clp->cl_state);
-	smp_mb__after_clear_bit();
-	schedule_work(&clp->cl_recoverd);
+	if (test_and_clear_bit(NFS4CLNT_OK, &clp->cl_state))
+		schedule_work(&clp->cl_recoverd);
 }
 
-static int
-nfs4_reclaim_open_state(struct nfs4_state_owner *sp)
+static int nfs4_reclaim_locks(struct nfs4_state *state)
+{
+	struct inode *inode = state->inode;
+	struct file_lock *fl;
+	int status = 0;
+
+	for (fl = inode->i_flock; fl != 0; fl = fl->fl_next) {
+		if (!(fl->fl_flags & FL_POSIX))
+			continue;
+		if (((struct nfs_open_context *)fl->fl_file->private_data)->state != state)
+			continue;
+		status = nfs4_lock_reclaim(state, fl);
+		if (status >= 0)
+			continue;
+		switch (status) {
+			default:
+				printk(KERN_ERR "%s: unhandled error %d. Zeroing state\n",
+						__FUNCTION__, status);
+			case -NFS4ERR_EXPIRED:
+			case -NFS4ERR_NO_GRACE:
+			case -NFS4ERR_RECLAIM_BAD:
+			case -NFS4ERR_RECLAIM_CONFLICT:
+				/* kill_proc(fl->fl_owner, SIGLOST, 1); */
+				break;
+			case -NFS4ERR_STALE_CLIENTID:
+				goto out_err;
+		}
+	}
+	return 0;
+out_err:
+	return status;
+}
+
+static int nfs4_reclaim_open_state(struct nfs4_state_owner *sp)
 {
 	struct nfs4_state *state;
+	struct nfs4_lock_state *lock;
 	int status = 0;
 
 	list_for_each_entry(state, &sp->so_states, open_states) {
 		if (state->state == 0)
 			continue;
 		status = nfs4_open_reclaim(sp, state);
-		if (status >= 0)
+		list_for_each_entry(lock, &state->lock_states, ls_locks)
+			lock->ls_flags &= ~NFS_LOCK_INITIALIZED;
+		if (status >= 0) {
+			status = nfs4_reclaim_locks(state);
+			if (status < 0)
+				goto out_err;
+			list_for_each_entry(lock, &state->lock_states, ls_locks) {
+				if (!(lock->ls_flags & NFS_LOCK_INITIALIZED))
+					printk("%s: Lock reclaim failed!\n",
+							__FUNCTION__);
+			}
 			continue;
+		}
 		switch (status) {
 			default:
 				printk(KERN_ERR "%s: unhandled error %d. Zeroing state\n",
@@ -762,75 +837,57 @@
 	return status;
 }
 
-static int
-reclaimer(void *ptr)
+static int reclaimer(void *ptr)
 {
 	struct reclaimer_args *args = (struct reclaimer_args *)ptr;
 	struct nfs4_client *clp = args->clp;
 	struct nfs4_state_owner *sp;
-	int generation;
-	int status;
+	int status = 0;
 
 	daemonize("%u.%u.%u.%u-reclaim", NIPQUAD(clp->cl_addr));
 	allow_signal(SIGKILL);
 
+	atomic_inc(&clp->cl_count);
 	complete(&args->complete);
 
+	/* Ensure exclusive access to NFSv4 state */
+	lock_kernel();
+	down_write(&clp->cl_sem);
 	/* Are there any NFS mounts out there? */
 	if (list_empty(&clp->cl_superblocks))
 		goto out;
-	if (!test_bit(NFS4CLNT_NEW, &clp->cl_state)) {
-		status = nfs4_proc_renew(clp);
-		if (status == 0) {
-			set_bit(NFS4CLNT_OK, &clp->cl_state);
-			goto out;
-		}
-	}
-	status = nfs4_proc_setclientid(clp, 0, 0);
-	if (status)
-		goto out_error;
-	status = nfs4_proc_setclientid_confirm(clp);
+restart_loop:
+	status = nfs4_proc_renew(clp);
+	if (status == 0 || status == -NFS4ERR_CB_PATH_DOWN)
+		goto out;
+	status = nfs4_init_client(clp);
 	if (status)
 		goto out_error;
-	generation = ++(clp->cl_generation);
-	clear_bit(NFS4CLNT_NEW, &clp->cl_state);
-	set_bit(NFS4CLNT_OK, &clp->cl_state);
-	up_read(&clp->cl_sem);
-	nfs4_schedule_state_renewal(clp);
-restart_loop:
-	spin_lock(&clp->cl_lock);
+	/* Mark all delagations for reclaim */
+	nfs_delegation_mark_reclaim(clp);
+	/* Note: list is protected by exclusive lock on cl->cl_sem */
 	list_for_each_entry(sp, &clp->cl_state_owners, so_list) {
-		if (sp->so_generation - generation >= 0)
-			continue;
-		atomic_inc(&sp->so_count);
-		spin_unlock(&clp->cl_lock);
-		down(&sp->so_sema);
-		if (sp->so_generation - generation < 0) {
-			smp_rmb();
-			sp->so_generation = clp->cl_generation;
-			status = nfs4_reclaim_open_state(sp);
-		}
-		up(&sp->so_sema);
-		nfs4_put_state_owner(sp);
+		status = nfs4_reclaim_open_state(sp);
 		if (status < 0) {
 			if (status == -NFS4ERR_STALE_CLIENTID)
-				nfs4_schedule_state_recovery(clp);
-			goto out;
+				goto restart_loop;
+			goto out_error;
 		}
-		goto restart_loop;
 	}
-	spin_unlock(&clp->cl_lock);
+	nfs_delegation_reap_unclaimed(clp);
 out:
-	smp_mb__before_clear_bit();
-	clear_bit(NFS4CLNT_SETUP_STATE, &clp->cl_state);
-	smp_mb__after_clear_bit();
+	set_bit(NFS4CLNT_OK, &clp->cl_state);
+	up_write(&clp->cl_sem);
+	unlock_kernel();
 	wake_up_all(&clp->cl_waitq);
 	rpc_wake_up(&clp->cl_rpcwaitq);
+	if (status == -NFS4ERR_CB_PATH_DOWN)
+		nfs_handle_cb_pathdown(clp);
+	nfs4_put_client(clp);
 	return 0;
 out_error:
-	printk(KERN_WARNING "Error: state recovery failed on NFSv4 server %u.%u.%u.%u\n",
-				NIPQUAD(clp->cl_addr.s_addr));
-	up_read(&clp->cl_sem);
+	printk(KERN_WARNING "Error: state recovery failed on NFSv4 server %u.%u.%u.%u with error %d\n",
+				NIPQUAD(clp->cl_addr.s_addr), -status);
 	goto out;
 }
 
diff -Nru a/fs/nfs/nfs4xdr.c b/fs/nfs/nfs4xdr.c
--- a/fs/nfs/nfs4xdr.c	2004-10-18 14:57:04 -07:00
+++ b/fs/nfs/nfs4xdr.c	2004-10-18 14:57:04 -07:00
@@ -84,6 +84,7 @@
 				((3+NFS4_FHSIZE) >> 2))
 #define encode_getattr_maxsz    (op_encode_hdr_maxsz + 3)
 #define nfs4_name_maxsz		(1 + ((3 + NFS4_MAXNAMLEN) >> 2))
+#define nfs4_path_maxsz		(1 + ((3 + NFS4_MAXPATHLEN) >> 2))
 #define nfs4_fattr_bitmap_maxsz (36 + 2 * nfs4_name_maxsz)
 #define decode_getattr_maxsz    (op_decode_hdr_maxsz + 3 + \
                                 nfs4_fattr_bitmap_maxsz)
@@ -118,10 +119,17 @@
 #define encode_link_maxsz	(op_encode_hdr_maxsz + \
 				nfs4_name_maxsz)
 #define decode_link_maxsz	(op_decode_hdr_maxsz + 5)
+#define encode_symlink_maxsz	(op_encode_hdr_maxsz + \
+				1 + nfs4_name_maxsz + \
+				nfs4_path_maxsz + \
+				nfs4_fattr_bitmap_maxsz)
+#define decode_symlink_maxsz	(op_decode_hdr_maxsz + 8)
 #define encode_create_maxsz	(op_encode_hdr_maxsz + \
-				2 + 2 * nfs4_name_maxsz + \
+				2 + nfs4_name_maxsz + \
 				nfs4_fattr_bitmap_maxsz)
 #define decode_create_maxsz	(op_decode_hdr_maxsz + 8)
+#define encode_delegreturn_maxsz (op_encode_hdr_maxsz + 4)
+#define decode_delegreturn_maxsz (op_decode_hdr_maxsz)
 #define NFS4_enc_compound_sz	(1024)  /* XXX: large enough? */
 #define NFS4_dec_compound_sz	(1024)  /* XXX: large enough? */
 #define NFS4_enc_read_sz	(compound_encode_hdr_maxsz + \
@@ -172,16 +180,14 @@
 #define NFS4_dec_open_confirm_sz        (compound_decode_hdr_maxsz + \
                                         decode_putfh_maxsz + \
                                         op_decode_hdr_maxsz + 4)
-#define NFS4_enc_open_reclaim_sz	(compound_encode_hdr_maxsz + \
+#define NFS4_enc_open_noattr_sz	(compound_encode_hdr_maxsz + \
 					encode_putfh_maxsz + \
 					op_encode_hdr_maxsz + \
-					11 + \
-					encode_getattr_maxsz)
-#define NFS4_dec_open_reclaim_sz	(compound_decode_hdr_maxsz + \
+					11)
+#define NFS4_dec_open_noattr_sz	(compound_decode_hdr_maxsz + \
 					decode_putfh_maxsz + \
 					op_decode_hdr_maxsz + \
-					4 + 5 + 2 + 3 + \
-					decode_getattr_maxsz)
+					4 + 5 + 2 + 3)
 #define NFS4_enc_open_downgrade_sz \
 				(compound_encode_hdr_maxsz + \
                                 encode_putfh_maxsz + \
@@ -313,6 +319,16 @@
 				decode_savefh_maxsz + \
 				decode_putfh_maxsz + \
 				decode_link_maxsz)
+#define NFS4_enc_symlink_sz	(compound_encode_hdr_maxsz + \
+				encode_putfh_maxsz + \
+				encode_symlink_maxsz + \
+				encode_getattr_maxsz + \
+				encode_getfh_maxsz)
+#define NFS4_dec_symlink_sz	(compound_decode_hdr_maxsz + \
+				decode_putfh_maxsz + \
+				decode_symlink_maxsz + \
+				decode_getattr_maxsz + \
+				decode_getfh_maxsz)
 #define NFS4_enc_create_sz	(compound_encode_hdr_maxsz + \
 				encode_putfh_maxsz + \
 				encode_create_maxsz + \
@@ -339,6 +355,11 @@
 				encode_getattr_maxsz)
 #define NFS4_dec_server_caps_sz (compound_decode_hdr_maxsz + \
 				decode_getattr_maxsz)
+#define NFS4_enc_delegreturn_sz	(compound_encode_hdr_maxsz + \
+				encode_putfh_maxsz + \
+				encode_delegreturn_maxsz)
+#define NFS4_dec_delegreturn_sz (compound_decode_hdr_maxsz + \
+				decode_delegreturn_maxsz)
 
 static struct {
 	unsigned int	mode;
@@ -388,6 +409,15 @@
 	BUG_ON(!p);						\
 } while (0)
 
+static void encode_string(struct xdr_stream *xdr, unsigned int len, const char *str)
+{
+	uint32_t *p;
+
+	p = xdr_reserve_space(xdr, 4 + len);
+	BUG_ON(p == NULL);
+	xdr_encode_opaque(p, str, len);
+}
+
 static int encode_compound_hdr(struct xdr_stream *xdr, struct compound_hdr *hdr)
 {
 	uint32_t *p;
@@ -402,6 +432,15 @@
 	return 0;
 }
 
+static void encode_nfs4_verifier(struct xdr_stream *xdr, const nfs4_verifier *verf)
+{
+	uint32_t *p;
+
+	p = xdr_reserve_space(xdr, NFS4_VERIFIER_SIZE);
+	BUG_ON(p == NULL);
+	xdr_encode_opaque_fixed(p, verf->data, NFS4_VERIFIER_SIZE);
+}
+
 static int encode_attrs(struct xdr_stream *xdr, const struct iattr *iap, const struct nfs_server *server)
 {
 	char owner_name[IDMAP_NAMESZ];
@@ -742,19 +781,12 @@
 	return 0;
 }
 
-static int encode_open(struct xdr_stream *xdr, const struct nfs_openargs *arg)
+static void encode_share_access(struct xdr_stream *xdr, int open_flags)
 {
-	int status;
 	uint32_t *p;
 
- /*
- * opcode 4, seqid 4, share_access 4, share_deny 4, clientid 8, ownerlen 4,
- * owner 4, opentype 4 = 36
- */
-	RESERVE_SPACE(36);
-	WRITE32(OP_OPEN);
-	WRITE32(arg->seqid);
-	switch (arg->share_access) {
+	RESERVE_SPACE(8);
+	switch (open_flags & (FMODE_READ|FMODE_WRITE)) {
 		case FMODE_READ:
 			WRITE32(NFS4_SHARE_ACCESS_READ);
 			break;
@@ -767,84 +799,135 @@
 		default:
 			BUG();
 	}
-	WRITE32(0);                  /* for linux, share_deny = 0 always */
+	WRITE32(0);		/* for linux, share_deny = 0 always */
+}
+
+static inline void encode_openhdr(struct xdr_stream *xdr, const struct nfs_openargs *arg)
+{
+	uint32_t *p;
+ /*
+ * opcode 4, seqid 4, share_access 4, share_deny 4, clientid 8, ownerlen 4,
+ * owner 4 = 32
+ */
+	RESERVE_SPACE(8);
+	WRITE32(OP_OPEN);
+	WRITE32(arg->seqid);
+	encode_share_access(xdr, arg->open_flags);
+	RESERVE_SPACE(16);
 	WRITE64(arg->clientid);
 	WRITE32(4);
 	WRITE32(arg->id);
-	WRITE32(arg->opentype);
+}
 
-	if (arg->opentype == NFS4_OPEN_CREATE) {
-		if (arg->createmode == NFS4_CREATE_EXCLUSIVE) {
-			RESERVE_SPACE(12);
-			WRITE32(arg->createmode);
-			WRITEMEM(arg->u.verifier.data, sizeof(arg->u.verifier.data));
-		}
-		else if (arg->u.attrs) {
-			RESERVE_SPACE(4);
-			WRITE32(arg->createmode);
-			if ((status = encode_attrs(xdr, arg->u.attrs, arg->server)))
-				return status;
-		}
-		else {
-			RESERVE_SPACE(12);
-			WRITE32(arg->createmode);
-			WRITE32(0);
-			WRITE32(0);
-		}
+static inline void encode_createmode(struct xdr_stream *xdr, const struct nfs_openargs *arg)
+{
+	uint32_t *p;
+
+	RESERVE_SPACE(4);
+	switch(arg->open_flags & O_EXCL) {
+		case 0:
+			WRITE32(NFS4_CREATE_UNCHECKED);
+			encode_attrs(xdr, arg->u.attrs, arg->server);
+			break;
+		default:
+			WRITE32(NFS4_CREATE_EXCLUSIVE);
+			encode_nfs4_verifier(xdr, &arg->u.verifier);
 	}
+}
 
-	RESERVE_SPACE(8 + arg->name->len);
-	WRITE32(NFS4_OPEN_CLAIM_NULL);
-	WRITE32(arg->name->len);
-	WRITEMEM(arg->name->name, arg->name->len);
+static void encode_opentype(struct xdr_stream *xdr, const struct nfs_openargs *arg)
+{
+	uint32_t *p;
 
-	return 0;
+	RESERVE_SPACE(4);
+	switch (arg->open_flags & O_CREAT) {
+		case 0:
+			WRITE32(NFS4_OPEN_NOCREATE);
+			break;
+		default:
+			BUG_ON(arg->claim != NFS4_OPEN_CLAIM_NULL);
+			WRITE32(NFS4_OPEN_CREATE);
+			encode_createmode(xdr, arg);
+	}
 }
 
-static int encode_open_confirm(struct xdr_stream *xdr, const struct nfs_open_confirmargs *arg)
+static inline void encode_delegation_type(struct xdr_stream *xdr, int delegation_type)
 {
 	uint32_t *p;
 
-	RESERVE_SPACE(8+sizeof(arg->stateid.data));
-	WRITE32(OP_OPEN_CONFIRM);
-	WRITEMEM(arg->stateid.data, sizeof(arg->stateid.data));
-	WRITE32(arg->seqid);
+	RESERVE_SPACE(4);
+	switch (delegation_type) {
+		case 0:
+			WRITE32(NFS4_OPEN_DELEGATE_NONE);
+			break;
+		case FMODE_READ:
+			WRITE32(NFS4_OPEN_DELEGATE_READ);
+			break;
+		case FMODE_WRITE|FMODE_READ:
+			WRITE32(NFS4_OPEN_DELEGATE_WRITE);
+			break;
+		default:
+			BUG();
+	}
+}
 
-	return 0;
+static inline void encode_claim_null(struct xdr_stream *xdr, const struct qstr *name)
+{
+	uint32_t *p;
+
+	RESERVE_SPACE(4);
+	WRITE32(NFS4_OPEN_CLAIM_NULL);
+	encode_string(xdr, name->len, name->name);
 }
 
+static inline void encode_claim_previous(struct xdr_stream *xdr, int type)
+{
+	uint32_t *p;
+
+	RESERVE_SPACE(4);
+	WRITE32(NFS4_OPEN_CLAIM_PREVIOUS);
+	encode_delegation_type(xdr, type);
+}
 
-static int encode_open_reclaim(struct xdr_stream *xdr, const struct nfs_open_reclaimargs *arg)
+static inline void encode_claim_delegate_cur(struct xdr_stream *xdr, const struct qstr *name, const nfs4_stateid *stateid)
 {
 	uint32_t *p;
 
- /*
- * opcode 4, seqid 4, share_access 4, share_deny 4, clientid 8, ownerlen 4,
- * owner 4, opentype 4, claim 4, delegation_type 4 = 44
- */
-	RESERVE_SPACE(44);
-	WRITE32(OP_OPEN);
-	WRITE32(arg->seqid);
-	switch (arg->share_access) {
-		case FMODE_READ:
-			WRITE32(NFS4_SHARE_ACCESS_READ);
+	RESERVE_SPACE(4+sizeof(stateid->data));
+	WRITE32(NFS4_OPEN_CLAIM_DELEGATE_CUR);
+	WRITEMEM(stateid->data, sizeof(stateid->data));
+	encode_string(xdr, name->len, name->name);
+}
+
+static int encode_open(struct xdr_stream *xdr, const struct nfs_openargs *arg)
+{
+	encode_openhdr(xdr, arg);
+	encode_opentype(xdr, arg);
+	switch (arg->claim) {
+		case NFS4_OPEN_CLAIM_NULL:
+			encode_claim_null(xdr, arg->name);
 			break;
-		case FMODE_WRITE:
-			WRITE32(NFS4_SHARE_ACCESS_WRITE);
+		case NFS4_OPEN_CLAIM_PREVIOUS:
+			encode_claim_previous(xdr, arg->u.delegation_type);
 			break;
-		case FMODE_READ|FMODE_WRITE:
-			WRITE32(NFS4_SHARE_ACCESS_BOTH);
+		case NFS4_OPEN_CLAIM_DELEGATE_CUR:
+			encode_claim_delegate_cur(xdr, arg->name, &arg->u.delegation);
 			break;
 		default:
 			BUG();
 	}
-	WRITE32(0);                  /* for linux, share_deny = 0 always */
-	WRITE64(arg->clientid);
-	WRITE32(4);
-	WRITE32(arg->id);
-	WRITE32(NFS4_OPEN_NOCREATE);
-	WRITE32(NFS4_OPEN_CLAIM_PREVIOUS);
-	WRITE32(NFS4_OPEN_DELEGATE_NONE);
+	return 0;
+}
+
+static int encode_open_confirm(struct xdr_stream *xdr, const struct nfs_open_confirmargs *arg)
+{
+	uint32_t *p;
+
+	RESERVE_SPACE(8+sizeof(arg->stateid.data));
+	WRITE32(OP_OPEN_CONFIRM);
+	WRITEMEM(arg->stateid.data, sizeof(arg->stateid.data));
+	WRITE32(arg->seqid);
+
 	return 0;
 }
 
@@ -852,14 +935,11 @@
 {
 	uint32_t *p;
 
-	RESERVE_SPACE(16+sizeof(arg->stateid.data));
+	RESERVE_SPACE(8+sizeof(arg->stateid.data));
 	WRITE32(OP_OPEN_DOWNGRADE);
 	WRITEMEM(arg->stateid.data, sizeof(arg->stateid.data));
 	WRITE32(arg->seqid);
-	WRITE32(arg->share_access);
-	/* No deny modes */
-	WRITE32(0);
-
+	encode_share_access(xdr, arg->open_flags);
 	return 0;
 }
 
@@ -887,15 +967,15 @@
         return 0;
 }
 
-static void encode_stateid(struct xdr_stream *xdr, struct nfs4_state *state, fl_owner_t lockowner)
+static void encode_stateid(struct xdr_stream *xdr, const struct nfs_open_context *ctx)
 {
 	extern nfs4_stateid zero_stateid;
 	nfs4_stateid stateid;
 	uint32_t *p;
 
 	RESERVE_SPACE(16);
-	if (state != NULL) {
-		nfs4_copy_stateid(&stateid, state, lockowner);
+	if (ctx->state != NULL) {
+		nfs4_copy_stateid(&stateid, ctx->state, ctx->lockowner);
 		WRITEMEM(stateid.data, sizeof(stateid.data));
 	} else
 		WRITEMEM(zero_stateid.data, sizeof(zero_stateid.data));
@@ -908,7 +988,7 @@
 	RESERVE_SPACE(4);
 	WRITE32(OP_READ);
 
-	encode_stateid(xdr, args->state, args->lockowner);
+	encode_stateid(xdr, args->context);
 
 	RESERVE_SPACE(12);
 	WRITE64(args->offset);
@@ -927,7 +1007,7 @@
 	WRITE32(OP_READDIR);
 	WRITE64(readdir->cookie);
 	WRITEMEM(readdir->verifier.data, sizeof(readdir->verifier.data));
-	WRITE32(readdir->count >> 5);  /* meaningless "dircount" field */
+	WRITE32(readdir->count >> 1);  /* We're not doing readdirplus */
 	WRITE32(readdir->count);
 	WRITE32(2);
 	WRITE32(FATTR4_WORD0_FILEID);
@@ -947,7 +1027,6 @@
 static int encode_readlink(struct xdr_stream *xdr, const struct nfs4_readlink *readlink, struct rpc_rqst *req)
 {
 	struct rpc_auth *auth = req->rq_task->tk_auth;
-	unsigned int count = readlink->count - 5;
 	unsigned int replen;
 	uint32_t *p;
 
@@ -956,10 +1035,11 @@
 
 	/* set up reply kvec
 	 *    toplevel_status + taglen + rescount + OP_PUTFH + status
-	 *      + OP_READLINK + status  = 7
+	 *      + OP_READLINK + status + string length = 8
 	 */
-	replen = (RPC_REPHDRSIZE + auth->au_rslack + 7) << 2;
-	xdr_inline_pages(&req->rq_rcv_buf, replen, readlink->pages, 0, count);
+	replen = (RPC_REPHDRSIZE + auth->au_rslack + 8) << 2;
+	xdr_inline_pages(&req->rq_rcv_buf, replen, readlink->pages,
+			readlink->pgbase, readlink->pglen);
 	
 	return 0;
 }
@@ -1031,26 +1111,18 @@
 
 static int encode_setclientid(struct xdr_stream *xdr, const struct nfs4_setclientid *setclientid)
 {
-	uint32_t total_len;
-	uint32_t len1, len2, len3;
 	uint32_t *p;
 
-	len1 = strlen(setclientid->sc_name);
-	len2 = strlen(setclientid->sc_netid);
-	len3 = strlen(setclientid->sc_uaddr);
-	total_len = XDR_QUADLEN(len1) + XDR_QUADLEN(len2) + XDR_QUADLEN(len3);
-	total_len = (total_len << 2) + 24 + sizeof(setclientid->sc_verifier.data);
-
-	RESERVE_SPACE(total_len);
+	RESERVE_SPACE(4 + sizeof(setclientid->sc_verifier->data));
 	WRITE32(OP_SETCLIENTID);
-	WRITEMEM(setclientid->sc_verifier.data, sizeof(setclientid->sc_verifier.data));
-	WRITE32(len1);
-	WRITEMEM(setclientid->sc_name, len1);
+	WRITEMEM(setclientid->sc_verifier->data, sizeof(setclientid->sc_verifier->data));
+
+	encode_string(xdr, setclientid->sc_name_len, setclientid->sc_name);
+	RESERVE_SPACE(4);
 	WRITE32(setclientid->sc_prog);
-	WRITE32(len2);
-	WRITEMEM(setclientid->sc_netid, len2);
-	WRITE32(len3);
-	WRITEMEM(setclientid->sc_uaddr, len3);
+	encode_string(xdr, setclientid->sc_netid_len, setclientid->sc_netid);
+	encode_string(xdr, setclientid->sc_uaddr_len, setclientid->sc_uaddr);
+	RESERVE_SPACE(4);
 	WRITE32(setclientid->sc_cb_ident);
 
 	return 0;
@@ -1075,7 +1147,7 @@
 	RESERVE_SPACE(4);
 	WRITE32(OP_WRITE);
 
-	encode_stateid(xdr, args->state, args->lockowner);
+	encode_stateid(xdr, args->context);
 
 	RESERVE_SPACE(16);
 	WRITE64(args->offset);
@@ -1086,6 +1158,18 @@
 
 	return 0;
 }
+
+static int encode_delegreturn(struct xdr_stream *xdr, const nfs4_stateid *stateid)
+{
+	uint32_t *p;
+
+	RESERVE_SPACE(20);
+
+	WRITE32(OP_DELEGRETURN);
+	WRITEMEM(stateid->data, sizeof(stateid->data));
+	return 0;
+
+}
 /*
  * END OF "GENERIC" ENCODE ROUTINES.
  */
@@ -1236,14 +1320,22 @@
 		goto out;
 	if ((status = encode_create(&xdr, args)) != 0)
 		goto out;
-	if ((status = encode_getfattr(&xdr, args->bitmask)) != 0)
+	if ((status = encode_getfh(&xdr)) != 0)
 		goto out;
-	status = encode_getfh(&xdr);
+	status = encode_getfattr(&xdr, args->bitmask);
 out:
 	return status;
 }
 
 /*
+ * Encode SYMLINK request
+ */
+static int nfs4_xdr_enc_symlink(struct rpc_rqst *req, uint32_t *p, const struct nfs4_create_arg *args)
+{
+	return nfs4_xdr_enc_create(req, p, args);
+}
+
+/*
  * Encode GETATTR request
  */
 static int nfs4_xdr_enc_getattr(struct rpc_rqst *req, uint32_t *p, const struct nfs4_getattr_arg *args)
@@ -1301,10 +1393,10 @@
 	status = encode_open(&xdr, args);
 	if (status)
 		goto out;
-	status = encode_getfattr(&xdr, args->bitmask);
+	status = encode_getfh(&xdr);
 	if (status)
 		goto out;
-	status = encode_getfh(&xdr);
+	status = encode_getfattr(&xdr, args->bitmask);
 out:
 	return status;
 }
@@ -1331,13 +1423,13 @@
 }
 
 /*
- * Encode an OPEN request
+ * Encode an OPEN request with no attributes.
  */
-static int nfs4_xdr_enc_open_reclaim(struct rpc_rqst *req, uint32_t *p, struct nfs_open_reclaimargs *args)
+static int nfs4_xdr_enc_open_noattr(struct rpc_rqst *req, uint32_t *p, struct nfs_openargs *args)
 {
 	struct xdr_stream xdr;
 	struct compound_hdr hdr = {
-		.nops   = 3,
+		.nops   = 2,
 	};
 	int status;
 
@@ -1346,10 +1438,7 @@
 	status = encode_putfh(&xdr, args->fh);
 	if (status)
 		goto out;
-	status = encode_open_reclaim(&xdr, args);
-	if (status)
-		goto out;
-	status = encode_getfattr(&xdr, args->bitmask);
+	status = encode_open(&xdr, args);
 out:
 	return status;
 }
@@ -1716,6 +1805,24 @@
 }
 
 /*
+ * DELEGRETURN request
+ */
+static int nfs4_xdr_enc_delegreturn(struct rpc_rqst *req, uint32_t *p, const struct nfs4_delegreturnargs *args)
+{
+	struct xdr_stream xdr;
+	struct compound_hdr hdr = {
+		.nops = 2,
+	};
+	int status;
+
+	xdr_init_encode(&xdr, &req->rq_snd_buf, p);
+	encode_compound_hdr(&xdr, &hdr);
+	if ((status = encode_putfh(&xdr, args->fhandle)) == 0)
+		status = encode_delegreturn(&xdr, args->stateid);
+	return status;
+}
+
+/*
  * START OF "GENERIC" DECODE ROUTINES.
  *   These may look a little ugly since they are imported from a "generic"
  * set of XDR encode/decode routines which are intended to be shared by
@@ -1749,6 +1856,17 @@
 	} \
 } while (0)
 
+static int decode_opaque_inline(struct xdr_stream *xdr, uint32_t *len, char **string)
+{
+	uint32_t *p;
+
+	READ_BUF(4);
+	READ32(*len);
+	READ_BUF(*len);
+	*string = (char *)p;
+	return 0;
+}
+
 static int decode_compound_hdr(struct xdr_stream *xdr, struct compound_hdr *hdr)
 {
 	uint32_t *p;
@@ -1785,6 +1903,17 @@
 	return 0;
 }
 
+/* Dummy routine */
+static int decode_ace(struct xdr_stream *xdr, void *ace, struct nfs4_client *clp)
+{
+	uint32_t *p;
+	uint32_t strlen;
+	char *str;
+
+	READ_BUF(12);
+	return decode_opaque_inline(xdr, &strlen, &str);
+}
+
 static int decode_attr_bitmap(struct xdr_stream *xdr, uint32_t *bitmap)
 {
 	uint32_t bmlen, *p;
@@ -2717,10 +2846,56 @@
 	return decode_op_hdr(xdr, OP_LOOKUP);
 }
 
+/* This is too sick! */
+static int decode_space_limit(struct xdr_stream *xdr, u64 *maxsize)
+{
+        uint32_t *p;
+	uint32_t limit_type, nblocks, blocksize;
+
+	READ_BUF(12);
+	READ32(limit_type);
+	switch (limit_type) {
+		case 1:
+			READ64(*maxsize);
+			break;
+		case 2:
+			READ32(nblocks);
+			READ32(blocksize);
+			*maxsize = (uint64_t)nblocks * (uint64_t)blocksize;
+	}
+	return 0;
+}
+
+static int decode_delegation(struct xdr_stream *xdr, struct nfs_openres *res)
+{
+        uint32_t *p;
+        uint32_t delegation_type;
+
+	READ_BUF(4);
+	READ32(delegation_type);
+	if (delegation_type == NFS4_OPEN_DELEGATE_NONE) {
+		res->delegation_type = 0;
+		return 0;
+	}
+	READ_BUF(20);
+	COPYMEM(res->delegation.data, sizeof(res->delegation.data));
+	READ32(res->do_recall);
+	switch (delegation_type) {
+		case NFS4_OPEN_DELEGATE_READ:
+			res->delegation_type = FMODE_READ;
+			break;
+		case NFS4_OPEN_DELEGATE_WRITE:
+			res->delegation_type = FMODE_WRITE|FMODE_READ;
+			if (decode_space_limit(xdr, &res->maxsize) < 0)
+				return -EIO;
+	}
+	return decode_ace(xdr, NULL, res->server->nfs4_state);
+}
+
 static int decode_open(struct xdr_stream *xdr, struct nfs_openres *res)
 {
         uint32_t *p;
-        uint32_t bmlen, delegation_type;
+        uint32_t bmlen;
         int status;
 
         status = decode_op_hdr(xdr, OP_OPEN);
@@ -2737,11 +2912,9 @@
         if (bmlen > 10)
                 goto xdr_error;
 
-        READ_BUF((bmlen << 2) + 4);
+        READ_BUF(bmlen << 2);
         p += bmlen;
-        READ32(delegation_type);
-        if (delegation_type == NFS4_OPEN_DELEGATE_NONE)
-		return 0;
+	return decode_delegation(xdr, res);
 xdr_error:
 	printk(KERN_NOTICE "%s: xdr error!\n", __FUNCTION__);
 	return -EIO;
@@ -2817,8 +2990,8 @@
 	struct kvec	*iov = rcvbuf->head;
 	unsigned int	nr, pglen = rcvbuf->page_len;
 	uint32_t	*end, *entry, *p, *kaddr;
-	uint32_t	len, attrlen, word;
-	int 		i, hdrlen, recvd, status;
+	uint32_t	len, attrlen;
+	int 		hdrlen, recvd, status;
 
 	status = decode_op_hdr(xdr, OP_READDIR);
 	if (status)
@@ -2839,42 +3012,24 @@
 	for (nr = 0; *p++; nr++) {
 		if (p + 3 > end)
 			goto short_pkt;
-		p += 2;     /* cookie */
-		len = ntohl(*p++);  /* filename length */
+		p += 2;			/* cookie */
+		len = ntohl(*p++);	/* filename length */
 		if (len > NFS4_MAXNAMLEN) {
 			printk(KERN_WARNING "NFS: giant filename in readdir (len 0x%x)\n", len);
 			goto err_unmap;
 		}
-			
 		p += XDR_QUADLEN(len);
 		if (p + 1 > end)
 			goto short_pkt;
-		len = ntohl(*p++);  /* bitmap length */
-		if (len > 10) {
-			printk(KERN_WARNING "NFS: giant bitmap in readdir (len 0x%x)\n", len);
-			goto err_unmap;
-		}
-		if (p + len + 1 > end)
-			goto short_pkt;
-		attrlen = 0;
-		for (i = 0; i < len; i++) {
-			word = ntohl(*p++);
-			if (!word)
-				continue;
-			else if (i == 0 && word == FATTR4_WORD0_FILEID) {
-				attrlen = 8;
-				continue;
-			}
-			printk(KERN_WARNING "NFS: unexpected bitmap word in readdir (0x%x)\n", word);
-			goto err_unmap;
-		}
-		if (ntohl(*p++) != attrlen) {
-			printk(KERN_WARNING "NFS: unexpected attrlen in readdir\n");
-			goto err_unmap;
-		}
-		p += XDR_QUADLEN(attrlen);
+		len = ntohl(*p++);	/* bitmap length */
+		p += len;
 		if (p + 1 > end)
 			goto short_pkt;
+		attrlen = XDR_QUADLEN(ntohl(*p++));
+		p += attrlen;		/* attributes */
+		if (p + 2 > end)
+			goto short_pkt;
+		entry = p;
 	}
 	if (!nr && (entry[0] != 0 || entry[1] == 0))
 		goto short_pkt;
@@ -2898,21 +3053,30 @@
 {
 	struct xdr_buf *rcvbuf = &req->rq_rcv_buf;
 	struct kvec *iov = rcvbuf->head;
-	uint32_t *strlen;
-	unsigned int hdrlen, len;
-	char *string;
+	int hdrlen, len, recvd;
+	uint32_t *p;
+	char *kaddr;
 	int status;
 
 	status = decode_op_hdr(xdr, OP_READLINK);
 	if (status)
 		return status;
 
+	/* Convert length of symlink */
+	READ_BUF(4);
+	READ32(len);
+	if (len >= rcvbuf->page_len || len <= 0) {
+		dprintk(KERN_WARNING "nfs: server returned giant symlink!\n");
+		return -ENAMETOOLONG;
+	}
 	hdrlen = (char *) xdr->p - (char *) iov->iov_base;
-	if (iov->iov_len > hdrlen) {
-		dprintk("NFS: READLINK header is short. iovec will be shifted.\n");
-		xdr_shift_buf(rcvbuf, iov->iov_len - hdrlen);
-
+	recvd = req->rq_rcv_buf.len - hdrlen;
+	if (recvd < len) {
+		printk(KERN_WARNING "NFS: server cheating in readlink reply: "
+				"count %u > recvd %u\n", len, recvd);
+		return -EIO;
 	}
+	xdr_read_pages(xdr, len);
 	/*
 	 * The XDR encode routine has set things up so that
 	 * the link text will be copied directly into the
@@ -2920,18 +3084,9 @@
 	 * and and null-terminate the text (the VFS expects
 	 * null-termination).
 	 */
-	strlen = (uint32_t *) kmap_atomic(rcvbuf->pages[0], KM_USER0);
-	len = ntohl(*strlen);
-	if (len > rcvbuf->page_len) {
-		dprintk(KERN_WARNING "nfs: server returned giant symlink!\n");
-		kunmap_atomic(strlen, KM_USER0);
-		return -ENAMETOOLONG;
-	}
-	*strlen = len;
-
-	string = (char *)(strlen + 1);
-	string[len] = '\0';
-	kunmap_atomic(strlen, KM_USER0);
+	kaddr = (char *)kmap_atomic(rcvbuf->pages[0], KM_USER0);
+	kaddr[len+rcvbuf->page_base] = '\0';
+	kunmap_atomic(kaddr, KM_USER0);
 	return 0;
 }
 
@@ -3048,6 +3203,11 @@
 	return 0;
 }
 
+static int decode_delegreturn(struct xdr_stream *xdr)
+{
+	return decode_op_hdr(xdr, OP_DELEGRETURN);
+}
+
 /*
  * Decode OPEN_DOWNGRADE response
  */
@@ -3214,14 +3374,24 @@
 		goto out;
 	if ((status = decode_create(&xdr,&res->dir_cinfo)) != 0)
 		goto out;
-	if ((status = decode_getfattr(&xdr, res->fattr, res->server)) != 0)
+	if ((status = decode_getfh(&xdr, res->fh)) != 0)
 		goto out;
-	status = decode_getfh(&xdr, res->fh);
+	status = decode_getfattr(&xdr, res->fattr, res->server);
+	if (status == NFS4ERR_DELAY)
+		status = 0;
 out:
 	return status;
 }
 
 /*
+ * Decode SYMLINK response
+ */
+static int nfs4_xdr_dec_symlink(struct rpc_rqst *rqstp, uint32_t *p, struct nfs4_create_res *res)
+{
+	return nfs4_xdr_dec_create(rqstp, p, res);
+}
+
+/*
  * Decode GETATTR response
  */
 static int nfs4_xdr_dec_getattr(struct rpc_rqst *rqstp, uint32_t *p, struct nfs4_getattr_res *res)
@@ -3284,10 +3454,12 @@
         status = decode_open(&xdr, res);
         if (status)
                 goto out;
-	status = decode_getfattr(&xdr, res->f_attr, res->server);
-        if (status)
-                goto out;
 	status = decode_getfh(&xdr, &res->fh);
+        if (status)
+		goto out;
+	status = decode_getfattr(&xdr, res->f_attr, res->server);
+	if (status == NFS4ERR_DELAY)
+		status = 0;
 out:
         return status;
 }
@@ -3314,9 +3486,9 @@
 }
 
 /*
- * Decode OPEN_RECLAIM response
+ * Decode OPEN response
  */
-static int nfs4_xdr_dec_open_reclaim(struct rpc_rqst *rqstp, uint32_t *p, struct nfs_openres *res)
+static int nfs4_xdr_dec_open_noattr(struct rpc_rqst *rqstp, uint32_t *p, struct nfs_openres *res)
 {
         struct xdr_stream xdr;
         struct compound_hdr hdr;
@@ -3330,9 +3502,6 @@
         if (status)
                 goto out;
         status = decode_open(&xdr, res);
-        if (status)
-                goto out;
-	status = decode_getfattr(&xdr, res->f_attr, res->server);
 out:
         return status;
 }
@@ -3357,6 +3526,8 @@
         if (status)
                 goto out;
 	status = decode_getfattr(&xdr, res->fattr, res->server);
+	if (status == NFS4ERR_DELAY)
+		status = 0;
 out:
         return status;
 }
@@ -3665,8 +3836,28 @@
 	return status;
 }
 
+/*
+ * DELEGRETURN request
+ */
+static int nfs4_xdr_dec_delegreturn(struct rpc_rqst *rqstp, uint32_t *p, void *dummy)
+{
+	struct xdr_stream xdr;
+	struct compound_hdr hdr;
+	int status;
+
+	xdr_init_decode(&xdr, &rqstp->rq_rcv_buf, p);
+	status = decode_compound_hdr(&xdr, &hdr);
+	if (status == 0) {
+		status = decode_putfh(&xdr);
+		if (status == 0)
+			status = decode_delegreturn(&xdr);
+	}
+	return status;
+}
+
 uint32_t *nfs4_decode_dirent(uint32_t *p, struct nfs_entry *entry, int plus)
 {
+	uint32_t bitmap[1] = {0};
 	uint32_t len;
 
 	if (!*p++) {
@@ -3689,11 +3880,17 @@
 	 */
 	entry->ino = 1;
 
-	len = ntohl(*p++);             /* bitmap length */
-	p += len;
-	len = ntohl(*p++);             /* attribute buffer length */
-	if (len)
-		p = xdr_decode_hyper(p, &entry->ino);
+	len = ntohl(*p++);		/* bitmap length */
+	if (len > 0) {
+		bitmap[0] = ntohl(*p);
+		p += len;
+	}
+	len = XDR_QUADLEN(ntohl(*p++));	/* attribute buffer length */
+	if (len > 0) {
+		if (bitmap[0] == FATTR4_WORD0_FILEID)
+			xdr_decode_hyper(p, &entry->ino);
+		p += len;
+	}
 
 	entry->eof = !p[0] && p[1];
 	return p;
@@ -3756,7 +3953,7 @@
 		if (nfs_errtbl[i].stat == stat)
 			return nfs_errtbl[i].errno;
 	}
-	if (stat < 0) {
+	if (stat <= 10000 || stat > 10100) {
 		/* The server is looney tunes. */
 		return ESERVERFAULT;
 	}
@@ -3786,7 +3983,7 @@
   PROC(COMMIT,		enc_commit,	dec_commit),
   PROC(OPEN,		enc_open,	dec_open),
   PROC(OPEN_CONFIRM,	enc_open_confirm,	dec_open_confirm),
-  PROC(OPEN_RECLAIM,	enc_open_reclaim,	dec_open_reclaim),
+  PROC(OPEN_NOATTR,	enc_open_noattr,	dec_open_noattr),
   PROC(OPEN_DOWNGRADE,	enc_open_downgrade,	dec_open_downgrade),
   PROC(CLOSE,		enc_close,	dec_close),
   PROC(SETATTR,		enc_setattr,	dec_setattr),
@@ -3804,12 +4001,14 @@
   PROC(REMOVE,		enc_remove,	dec_remove),
   PROC(RENAME,		enc_rename,	dec_rename),
   PROC(LINK,		enc_link,	dec_link),
+  PROC(SYMLINK,		enc_symlink,	dec_symlink),
   PROC(CREATE,		enc_create,	dec_create),
   PROC(PATHCONF,	enc_pathconf,	dec_pathconf),
   PROC(STATFS,		enc_statfs,	dec_statfs),
   PROC(READLINK,	enc_readlink,	dec_readlink),
   PROC(READDIR,		enc_readdir,	dec_readdir),
   PROC(SERVER_CAPS,	enc_server_caps, dec_server_caps),
+  PROC(DELEGRETURN,	enc_delegreturn, dec_delegreturn),
 };
 
 struct rpc_version		nfs_version4 = {
diff -Nru a/fs/nfs/pagelist.c b/fs/nfs/pagelist.c
--- a/fs/nfs/pagelist.c	2004-10-18 14:57:03 -07:00
+++ b/fs/nfs/pagelist.c	2004-10-18 14:57:03 -07:00
@@ -21,11 +21,6 @@
 
 #define NFS_PARANOIA 1
 
-/*
- * Spinlock
- */
-spinlock_t nfs_wreq_lock = SPIN_LOCK_UNLOCKED;
-
 static kmem_cache_t *nfs_page_cachep;
 
 static inline struct nfs_page *
@@ -36,7 +31,6 @@
 	if (p) {
 		memset(p, 0, sizeof(*p));
 		INIT_LIST_HEAD(&p->wb_list);
-		init_waitqueue_head(&p->wb_wait);
 	}
 	return p;
 }
@@ -62,7 +56,7 @@
  * User should ensure it is safe to sleep in this function.
  */
 struct nfs_page *
-nfs_create_request(struct file *file, struct inode *inode,
+nfs_create_request(struct nfs_open_context *ctx, struct inode *inode,
 		   struct page *page,
 		   unsigned int offset, unsigned int count)
 {
@@ -94,33 +88,38 @@
 	req->wb_offset  = offset;
 	req->wb_pgbase	= offset;
 	req->wb_bytes   = count;
-	req->wb_inode   = inode;
-	req->wb_count   = 1;
-	server->rpc_ops->request_init(req, file);
+	atomic_set(&req->wb_count, 1);
+	req->wb_context = get_nfs_open_context(ctx);
 
 	return req;
 }
 
 /**
+ * nfs_unlock_request - Unlock request and wake up sleepers.
+ * @req:
+ */
+void nfs_unlock_request(struct nfs_page *req)
+{
+	if (!NFS_WBACK_BUSY(req)) {
+		printk(KERN_ERR "NFS: Invalid unlock attempted\n");
+		BUG();
+	}
+	smp_mb__before_clear_bit();
+	clear_bit(PG_BUSY, &req->wb_flags);
+	smp_mb__after_clear_bit();
+	wake_up_all(&req->wb_context->waitq);
+	nfs_release_request(req);
+}
+
+/**
  * nfs_clear_request - Free up all resources allocated to the request
  * @req:
  *
- * Release all resources associated with a write request after it
+ * Release page resources associated with a write request after it
  * has completed.
  */
 void nfs_clear_request(struct nfs_page *req)
 {
-	if (req->wb_state)
-		req->wb_state = NULL;
-	/* Release struct file or cached credential */
-	if (req->wb_file) {
-		fput(req->wb_file);
-		req->wb_file = NULL;
-	}
-	if (req->wb_cred) {
-		put_rpccred(req->wb_cred);
-		req->wb_cred = NULL;
-	}
 	if (req->wb_page) {
 		page_cache_release(req->wb_page);
 		req->wb_page = NULL;
@@ -137,12 +136,8 @@
 void
 nfs_release_request(struct nfs_page *req)
 {
-	spin_lock(&nfs_wreq_lock);
-	if (--req->wb_count) {
-		spin_unlock(&nfs_wreq_lock);
+	if (!atomic_dec_and_test(&req->wb_count))
 		return;
-	}
-	spin_unlock(&nfs_wreq_lock);
 
 #ifdef NFS_PARANOIA
 	BUG_ON (!list_empty(&req->wb_list));
@@ -151,6 +146,7 @@
 
 	/* Release struct file or cached credential */
 	nfs_clear_request(req);
+	put_nfs_open_context(req->wb_context);
 	nfs_page_free(req);
 }
 
@@ -194,12 +190,12 @@
 int
 nfs_wait_on_request(struct nfs_page *req)
 {
-	struct inode	*inode = req->wb_inode;
+	struct inode	*inode = req->wb_context->dentry->d_inode;
         struct rpc_clnt	*clnt = NFS_CLIENT(inode);
 
 	if (!NFS_WBACK_BUSY(req))
 		return 0;
-	return nfs_wait_event(clnt, req->wb_wait, !NFS_WBACK_BUSY(req));
+	return nfs_wait_event(clnt, req->wb_context->waitq, !NFS_WBACK_BUSY(req));
 }
 
 /**
@@ -224,7 +220,11 @@
 
 		req = nfs_list_entry(head->next);
 		if (prev) {
-			if (req->wb_cred != prev->wb_cred)
+			if (req->wb_context->cred != prev->wb_context->cred)
+				break;
+			if (req->wb_context->lockowner != prev->wb_context->lockowner)
+				break;
+			if (req->wb_context->state != prev->wb_context->state)
 				break;
 			if (req->wb_index != (prev->wb_index + 1))
 				break;
@@ -254,7 +254,7 @@
  * If the number of requests is set to 0, the entire address_space
  * starting at index idx_start, is scanned.
  * The requests are *not* checked to ensure that they form a contiguous set.
- * You must be holding the nfs_wreq_lock when calling this function
+ * You must be holding the inode's req_lock when calling this function
  */
 int
 nfs_scan_list(struct list_head *head, struct list_head *dst,
diff -Nru a/fs/nfs/proc.c b/fs/nfs/proc.c
--- a/fs/nfs/proc.c	2004-10-18 14:57:03 -07:00
+++ b/fs/nfs/proc.c	2004-10-18 14:57:03 -07:00
@@ -49,18 +49,6 @@
 
 extern struct rpc_procinfo nfs_procedures[];
 
-static struct rpc_cred *
-nfs_cred(struct inode *inode, struct file *filp)
-{
-	struct rpc_cred *cred = NULL;
-
-	if (filp)
-		cred = (struct rpc_cred *)filp->private_data;
-	if (!cred)
-		cred = NFS_I(inode)->mm_cred;
-	return cred;
-}
-
 /*
  * Bare-bones access to getattr: this is for nfs_read_super.
  */
@@ -99,14 +87,15 @@
  * One function for each procedure in the NFS protocol.
  */
 static int
-nfs_proc_getattr(struct inode *inode, struct nfs_fattr *fattr)
+nfs_proc_getattr(struct nfs_server *server, struct nfs_fh *fhandle,
+		struct nfs_fattr *fattr)
 {
 	int	status;
 
 	dprintk("NFS call  getattr\n");
 	fattr->valid = 0;
-	status = rpc_call(NFS_CLIENT(inode), NFSPROC_GETATTR,
-				NFS_FH(inode), fattr, 0);
+	status = rpc_call(server->client, NFSPROC_GETATTR,
+				fhandle, fattr, 0);
 	dprintk("NFS reply getattr\n");
 	return status;
 }
@@ -151,12 +140,13 @@
 	return status;
 }
 
-static int
-nfs_proc_readlink(struct inode *inode, struct page *page)
+static int nfs_proc_readlink(struct inode *inode, struct page *page,
+		unsigned int pgbase, unsigned int pglen)
 {
 	struct nfs_readlinkargs	args = {
 		.fh		= NFS_FH(inode),
-		.count		= PAGE_CACHE_SIZE,
+		.pgbase		= pgbase,
+		.pglen		= pglen,
 		.pages		= &page
 	};
 	int			status;
@@ -167,8 +157,7 @@
 	return status;
 }
 
-static int
-nfs_proc_read(struct nfs_read_data *rdata, struct file *filp)
+static int nfs_proc_read(struct nfs_read_data *rdata)
 {
 	int			flags = rdata->flags;
 	struct inode *		inode = rdata->inode;
@@ -177,15 +166,14 @@
 		.rpc_proc	= &nfs_procedures[NFSPROC_READ],
 		.rpc_argp	= &rdata->args,
 		.rpc_resp	= &rdata->res,
+		.rpc_cred	= rdata->cred,
 	};
 	int			status;
 
 	dprintk("NFS call  read %d @ %Ld\n", rdata->args.count,
 			(long long) rdata->args.offset);
 	fattr->valid = 0;
-	msg.rpc_cred = nfs_cred(inode, filp);
 	status = rpc_call_sync(NFS_CLIENT(inode), &msg, flags);
-
 	if (status >= 0) {
 		nfs_refresh_inode(inode, fattr);
 		/* Emulate the eof flag, which isn't normally needed in NFSv2
@@ -198,8 +186,7 @@
 	return status;
 }
 
-static int
-nfs_proc_write(struct nfs_write_data *wdata, struct file *filp)
+static int nfs_proc_write(struct nfs_write_data *wdata)
 {
 	int			flags = wdata->flags;
 	struct inode *		inode = wdata->inode;
@@ -208,13 +195,13 @@
 		.rpc_proc	= &nfs_procedures[NFSPROC_WRITE],
 		.rpc_argp	= &wdata->args,
 		.rpc_resp	= &wdata->res,
+		.rpc_cred	= wdata->cred,
 	};
 	int			status;
 
 	dprintk("NFS call  write %d @ %Ld\n", wdata->args.count,
 			(long long) wdata->args.offset);
 	fattr->valid = 0;
-	msg.rpc_cred = nfs_cred(inode, filp);
 	status = rpc_call_sync(NFS_CLIENT(inode), &msg, flags);
 	if (status >= 0) {
 		nfs_refresh_inode(inode, fattr);
@@ -400,8 +387,11 @@
 	};
 	int			status;
 
+	if (path->len > NFS2_MAXPATHLEN)
+		return -ENAMETOOLONG;
 	dprintk("NFS call  symlink %s -> %s\n", name->name, path->name);
 	fattr->valid = 0;
+	fhandle->size = 0;
 	status = rpc_call(NFS_CLIENT(dir), NFSPROC_SYMLINK, &arg, NULL, 0);
 	dprintk("NFS reply symlink: %d\n", status);
 	return status;
@@ -619,27 +609,6 @@
 	BUG();
 }
 
-/*
- * Set up the nfspage struct with the right credentials
- */
-static void
-nfs_request_init(struct nfs_page *req, struct file *filp)
-{
-	req->wb_cred = get_rpccred(nfs_cred(req->wb_inode, filp));
-}
-
-static int
-nfs_request_compatible(struct nfs_page *req, struct file *filp, struct page *page)
-{
-	if (req->wb_file != filp)
-		return 0;
-	if (req->wb_page != page)
-		return 0;
-	if (req->wb_cred != nfs_file_cred(filp))
-		return 0;
-	return 1;
-}
-
 static int
 nfs_proc_lock(struct file *filp, int cmd, struct file_lock *fl)
 {
@@ -680,7 +649,5 @@
 	.commit_setup	= nfs_proc_commit_setup,
 	.file_open	= nfs_open,
 	.file_release	= nfs_release,
-	.request_init	= nfs_request_init,
-	.request_compatible = nfs_request_compatible,
 	.lock		= nfs_proc_lock,
 };
diff -Nru a/fs/nfs/read.c b/fs/nfs/read.c
--- a/fs/nfs/read.c	2004-10-18 14:55:46 -07:00
+++ b/fs/nfs/read.c	2004-10-18 14:55:46 -07:00
@@ -91,8 +91,8 @@
 /*
  * Read a page synchronously.
  */
-static int
-nfs_readpage_sync(struct file *file, struct inode *inode, struct page *page)
+static int nfs_readpage_sync(struct nfs_open_context *ctx, struct inode *inode,
+		struct page *page)
 {
 	unsigned int	rsize = NFS_SERVER(inode)->rsize;
 	unsigned int	count = PAGE_CACHE_SIZE;
@@ -105,10 +105,11 @@
 
 	memset(rdata, 0, sizeof(*rdata));
 	rdata->flags = (IS_SWAPFILE(inode)? NFS_RPC_SWAPFLAGS : 0);
+	rdata->cred = ctx->cred;
 	rdata->inode = inode;
 	INIT_LIST_HEAD(&rdata->pages);
 	rdata->args.fh = NFS_FH(inode);
-	rdata->args.lockowner = current->files;
+	rdata->args.context = ctx;
 	rdata->args.pages = &page;
 	rdata->args.pgbase = 0UL;
 	rdata->args.count = rsize;
@@ -134,7 +135,7 @@
 			rdata->args.count);
 
 		lock_kernel();
-		result = NFS_PROTO(inode)->read(rdata, file);
+		result = NFS_PROTO(inode)->read(rdata);
 		unlock_kernel();
 
 		/*
@@ -169,8 +170,8 @@
 	return result;
 }
 
-static int
-nfs_readpage_async(struct file *file, struct inode *inode, struct page *page)
+static int nfs_readpage_async(struct nfs_open_context *ctx, struct inode *inode,
+		struct page *page)
 {
 	LIST_HEAD(one_request);
 	struct nfs_page	*new;
@@ -179,7 +180,7 @@
 	len = nfs_page_length(inode, page);
 	if (len == 0)
 		return nfs_return_empty_page(page);
-	new = nfs_create_request(file, inode, page, 0, len);
+	new = nfs_create_request(ctx, inode, page, 0, len);
 	if (IS_ERR(new)) {
 		unlock_page(page);
 		return PTR_ERR(new);
@@ -202,8 +203,8 @@
 	nfs_unlock_request(req);
 
 	dprintk("NFS: read done (%s/%Ld %d@%Ld)\n",
-			req->wb_inode->i_sb->s_id,
-			(long long)NFS_FILEID(req->wb_inode),
+			req->wb_context->dentry->d_inode->i_sb->s_id,
+			(long long)NFS_FILEID(req->wb_context->dentry->d_inode),
 			req->wb_bytes,
 			(long long)req_offset(req));
 }
@@ -217,16 +218,15 @@
 	struct inode		*inode;
 
 	data->req	  = req;
-	data->inode	  = inode = req->wb_inode;
-	data->cred	  = req->wb_cred;
+	data->inode	  = inode = req->wb_context->dentry->d_inode;
+	data->cred	  = req->wb_context->cred;
 
 	data->args.fh     = NFS_FH(inode);
 	data->args.offset = req_offset(req) + offset;
 	data->args.pgbase = req->wb_pgbase + offset;
 	data->args.pages  = data->pagevec;
 	data->args.count  = count;
-	data->args.lockowner = req->wb_lockowner;
-	data->args.state  = req->wb_state;
+	data->args.context = req->wb_context;
 
 	data->res.fattr   = &data->fattr;
 	data->res.count   = count;
@@ -396,7 +396,7 @@
 	while (!list_empty(head)) {
 		pages += nfs_coalesce_requests(head, &one_request, rpages);
 		req = nfs_list_entry(one_request.next);
-		error = nfs_pagein_one(&one_request, req->wb_inode);
+		error = nfs_pagein_one(&one_request, req->wb_context->dentry->d_inode);
 		if (error < 0)
 			break;
 	}
@@ -500,9 +500,9 @@
  *  -	The error flag is set for this page. This happens only when a
  *	previous async read operation failed.
  */
-int
-nfs_readpage(struct file *file, struct page *page)
+int nfs_readpage(struct file *file, struct page *page)
 {
+	struct nfs_open_context *ctx;
 	struct inode *inode = page->mapping->host;
 	int		error;
 
@@ -519,25 +519,33 @@
 	if (error)
 		goto out_error;
 
+	if (file == NULL) {
+		ctx = nfs_find_open_context(inode, FMODE_READ);
+		if (ctx == NULL)
+			return -EBADF;
+	} else
+		ctx = get_nfs_open_context((struct nfs_open_context *)
+				file->private_data);
 	if (!IS_SYNC(inode)) {
-		error = nfs_readpage_async(file, inode, page);
+		error = nfs_readpage_async(ctx, inode, page);
 		goto out;
 	}
 
-	error = nfs_readpage_sync(file, inode, page);
+	error = nfs_readpage_sync(ctx, inode, page);
 	if (error < 0 && IS_SWAPFILE(inode))
 		printk("Aiee.. nfs swap-in of page failed!\n");
 out:
+	put_nfs_open_context(ctx);
 	return error;
 
 out_error:
 	unlock_page(page);
-	goto out;
+	return error;
 }
 
 struct nfs_readdesc {
 	struct list_head *head;
-	struct file *filp;
+	struct nfs_open_context *ctx;
 };
 
 static int
@@ -552,7 +560,7 @@
 	len = nfs_page_length(inode, page);
 	if (len == 0)
 		return nfs_return_empty_page(page);
-	new = nfs_create_request(desc->filp, inode, page, 0, len);
+	new = nfs_create_request(desc->ctx, inode, page, 0, len);
 	if (IS_ERR(new)) {
 			SetPageError(page);
 			unlock_page(page);
@@ -565,13 +573,11 @@
 	return 0;
 }
 
-int
-nfs_readpages(struct file *filp, struct address_space *mapping,
+int nfs_readpages(struct file *filp, struct address_space *mapping,
 		struct list_head *pages, unsigned nr_pages)
 {
 	LIST_HEAD(head);
 	struct nfs_readdesc desc = {
-		.filp		= filp,
 		.head		= &head,
 	};
 	struct inode *inode = mapping->host;
@@ -583,12 +589,20 @@
 			(long long)NFS_FILEID(inode),
 			nr_pages);
 
+	if (filp == NULL) {
+		desc.ctx = nfs_find_open_context(inode, FMODE_READ);
+		if (desc.ctx == NULL)
+			return -EBADF;
+	} else
+		desc.ctx = get_nfs_open_context((struct nfs_open_context *)
+				filp->private_data);
 	ret = read_cache_pages(mapping, pages, readpage_async_filler, &desc);
 	if (!list_empty(&head)) {
 		int err = nfs_pagein_list(&head, server->rpages);
 		if (!ret)
 			ret = err;
 	}
+	put_nfs_open_context(desc.ctx);
 	return ret;
 }
 
diff -Nru a/fs/nfs/symlink.c b/fs/nfs/symlink.c
--- a/fs/nfs/symlink.c	2004-10-18 14:56:32 -07:00
+++ b/fs/nfs/symlink.c	2004-10-18 14:56:32 -07:00
@@ -23,20 +23,30 @@
 #include <linux/slab.h>
 #include <linux/string.h>
 #include <linux/smp_lock.h>
+#include <linux/namei.h>
 
 /* Symlink caching in the page cache is even more simplistic
  * and straight-forward than readdir caching.
+ *
+ * At the beginning of the page we store pointer to struct page in question,
+ * simplifying nfs_put_link() (if inode got invalidated we can't find the page
+ * to be freed via pagecache lookup).
+ * The NUL-terminated string follows immediately thereafter.
  */
+
+struct nfs_symlink {
+	struct page *page;
+	char body[0];
+};
+
 static int nfs_symlink_filler(struct inode *inode, struct page *page)
 {
+	const unsigned int pgbase = offsetof(struct nfs_symlink, body);
+	const unsigned int pglen = PAGE_SIZE - pgbase;
 	int error;
 
-	/* We place the length at the beginning of the page,
-	 * in host byte order, followed by the string.  The
-	 * XDR response verification will NULL terminate it.
-	 */
 	lock_kernel();
-	error = NFS_PROTO(inode)->readlink(inode, page);
+	error = NFS_PROTO(inode)->readlink(inode, page, pgbase, pglen);
 	unlock_kernel();
 	if (error < 0)
 		goto error;
@@ -50,61 +60,58 @@
 	return -EIO;
 }
 
-static char *nfs_getlink(struct inode *inode, struct page **ppage)
+static int nfs_follow_link(struct dentry *dentry, struct nameidata *nd)
 {
+	struct inode *inode = dentry->d_inode;
 	struct page *page;
-	u32 *p;
-
-	page = ERR_PTR(nfs_revalidate_inode(NFS_SERVER(inode), inode));
-	if (page)
+	struct nfs_symlink *p;
+	void *err = ERR_PTR(nfs_revalidate_inode(NFS_SERVER(inode), inode));
+	if (err)
 		goto read_failed;
 	page = read_cache_page(&inode->i_data, 0,
 				(filler_t *)nfs_symlink_filler, inode);
-	if (IS_ERR(page))
+	if (IS_ERR(page)) {
+		err = page;
 		goto read_failed;
-	if (!PageUptodate(page))
+	}
+	if (!PageUptodate(page)) {
+		err = ERR_PTR(-EIO);
 		goto getlink_read_error;
-	*ppage = page;
+	}
 	p = kmap(page);
-	return (char*)(p+1);
+	p->page = page;
+	nd_set_link(nd, p->body);
+	return 0;
 
 getlink_read_error:
 	page_cache_release(page);
-	page = ERR_PTR(-EIO);
 read_failed:
-	return (char*)page;
+	nd_set_link(nd, err);
+	return 0;
 }
 
-static int nfs_readlink(struct dentry *dentry, char __user *buffer, int buflen)
+static void nfs_put_link(struct dentry *dentry, struct nameidata *nd)
 {
-	struct inode *inode = dentry->d_inode;
-	struct page *page = NULL;
-	int res = vfs_readlink(dentry,buffer,buflen,nfs_getlink(inode,&page));
-	if (page) {
-		kunmap(page);
-		page_cache_release(page);
-	}
-	return res;
-}
+	char *s = nd_get_link(nd);
+	if (!IS_ERR(s)) {
+		struct nfs_symlink *p;
+		struct page *page;
+
+		p = container_of(s, struct nfs_symlink, body[0]);
+		page = p->page;
 
-static int nfs_follow_link(struct dentry *dentry, struct nameidata *nd)
-{
-	struct inode *inode = dentry->d_inode;
-	struct page *page = NULL;
-	int res = vfs_follow_link(nd, nfs_getlink(inode,&page));
-	if (page) {
 		kunmap(page);
 		page_cache_release(page);
 	}
-	return res;
 }
 
 /*
  * symlinks can't do much...
  */
 struct inode_operations nfs_symlink_inode_operations = {
-	.readlink	= nfs_readlink,
+	.readlink	= generic_readlink,
 	.follow_link	= nfs_follow_link,
+	.put_link	= nfs_put_link,
 	.getattr	= nfs_getattr,
 	.setattr	= nfs_setattr,
 };
diff -Nru a/fs/nfs/write.c b/fs/nfs/write.c
--- a/fs/nfs/write.c	2004-10-18 14:56:49 -07:00
+++ b/fs/nfs/write.c	2004-10-18 14:56:49 -07:00
@@ -63,6 +63,8 @@
 #include <linux/smp_lock.h>
 #include <linux/mempool.h>
 
+#include "delegation.h"
+
 #define NFSDBG_FACILITY		NFSDBG_PAGECACHE
 
 #define MIN_POOL_WRITE		(32)
@@ -71,7 +73,8 @@
 /*
  * Local function declarations
  */
-static struct nfs_page * nfs_update_request(struct file*, struct inode *,
+static struct nfs_page * nfs_update_request(struct nfs_open_context*,
+					    struct inode *,
 					    struct page *,
 					    unsigned int, unsigned int);
 static void nfs_writeback_done_partial(struct nfs_write_data *, int);
@@ -173,7 +176,7 @@
  * Write a page synchronously.
  * Offset is the data offset within the page.
  */
-static int nfs_writepage_sync(struct file *file, struct inode *inode,
+static int nfs_writepage_sync(struct nfs_open_context *ctx, struct inode *inode,
 		struct page *page, unsigned int offset, unsigned int count,
 		int how)
 {
@@ -187,9 +190,10 @@
 
 	memset(wdata, 0, sizeof(*wdata));
 	wdata->flags = how;
+	wdata->cred = ctx->cred;
 	wdata->inode = inode;
 	wdata->args.fh = NFS_FH(inode);
-	wdata->args.lockowner = current->files;
+	wdata->args.context = ctx;
 	wdata->args.pages = &page;
 	wdata->args.stable = NFS_FILE_SYNC;
 	wdata->args.pgbase = offset;
@@ -208,7 +212,7 @@
 			wdata->args.count = count;
 		wdata->args.offset = page_offset(page) + wdata->args.pgbase;
 
-		result = NFS_PROTO(inode)->write(wdata, file);
+		result = NFS_PROTO(inode)->write(wdata);
 
 		if (result < 0) {
 			/* Must mark the page invalid after I/O error */
@@ -234,20 +238,19 @@
 
 io_error:
 	nfs_end_data_update_defer(inode);
-	if (wdata->cred)
-		put_rpccred(wdata->cred);
 
 	kfree(wdata);
 	return written ? written : result;
 }
 
-static int nfs_writepage_async(struct file *file, struct inode *inode,
-		struct page *page, unsigned int offset, unsigned int count)
+static int nfs_writepage_async(struct nfs_open_context *ctx,
+		struct inode *inode, struct page *page,
+		unsigned int offset, unsigned int count)
 {
 	struct nfs_page	*req;
 	int		status;
 
-	req = nfs_update_request(file, inode, page, offset, count);
+	req = nfs_update_request(ctx, inode, page, offset, count);
 	status = (IS_ERR(req)) ? PTR_ERR(req) : 0;
 	if (status < 0)
 		goto out;
@@ -274,6 +277,7 @@
  */
 int nfs_writepage(struct page *page, struct writeback_control *wbc)
 {
+	struct nfs_open_context *ctx;
 	struct inode *inode = page->mapping->host;
 	unsigned long end_index;
 	unsigned offset = PAGE_CACHE_SIZE;
@@ -308,16 +312,21 @@
 	if (page->index >= end_index+1 || !offset)
 		goto out;
 do_it:
+	ctx = nfs_find_open_context(inode, FMODE_WRITE);
+	if (ctx == NULL) {
+		err = -EBADF;
+		goto out;
+	}
 	lock_kernel();
 	if (!IS_SYNC(inode) && inode_referenced) {
-		err = nfs_writepage_async(NULL, inode, page, 0, offset);
+		err = nfs_writepage_async(ctx, inode, page, 0, offset);
 		if (err >= 0) {
 			err = 0;
 			if (wbc->for_reclaim)
 				nfs_flush_inode(inode, 0, 0, FLUSH_STABLE);
 		}
 	} else {
-		err = nfs_writepage_sync(NULL, inode, page, 0,
+		err = nfs_writepage_sync(ctx, inode, page, 0,
 						offset, priority);
 		if (err >= 0) {
 			if (err != offset)
@@ -326,6 +335,7 @@
 		}
 	}
 	unlock_kernel();
+	put_nfs_open_context(ctx);
 out:
 	unlock_page(page);
 	if (inode_referenced)
@@ -374,8 +384,7 @@
 /*
  * Insert a write request into an inode
  */
-static inline int
-nfs_inode_add_request(struct inode *inode, struct nfs_page *req)
+static int nfs_inode_add_request(struct inode *inode, struct nfs_page *req)
 {
 	struct nfs_inode *nfsi = NFS_I(inode);
 	int error;
@@ -387,33 +396,33 @@
 	if (!nfsi->npages) {
 		igrab(inode);
 		nfs_begin_data_update(inode);
+		if (nfs_have_delegation(inode, FMODE_WRITE))
+			nfsi->change_attr++;
 	}
 	nfsi->npages++;
-	req->wb_count++;
+	atomic_inc(&req->wb_count);
 	return 0;
 }
 
 /*
  * Insert a write request into an inode
  */
-static void
-nfs_inode_remove_request(struct nfs_page *req)
+static void nfs_inode_remove_request(struct nfs_page *req)
 {
-	struct nfs_inode *nfsi;
-	struct inode *inode;
+	struct inode *inode = req->wb_context->dentry->d_inode;
+	struct nfs_inode *nfsi = NFS_I(inode);
 
 	BUG_ON (!NFS_WBACK_BUSY(req));
-	spin_lock(&nfs_wreq_lock);
-	inode = req->wb_inode;
-	nfsi = NFS_I(inode);
+
+	spin_lock(&nfsi->req_lock);
 	radix_tree_delete(&nfsi->nfs_page_tree, req->wb_index);
 	nfsi->npages--;
 	if (!nfsi->npages) {
-		spin_unlock(&nfs_wreq_lock);
+		spin_unlock(&nfsi->req_lock);
 		nfs_end_data_update_defer(inode);
 		iput(inode);
 	} else
-		spin_unlock(&nfs_wreq_lock);
+		spin_unlock(&nfsi->req_lock);
 	nfs_clear_request(req);
 	nfs_release_request(req);
 }
@@ -429,7 +438,7 @@
 
 	req = (struct nfs_page*)radix_tree_lookup(&nfsi->nfs_page_tree, index);
 	if (req)
-		req->wb_count++;
+		atomic_inc(&req->wb_count);
 	return req;
 }
 
@@ -437,10 +446,11 @@
 nfs_find_request(struct inode *inode, unsigned long index)
 {
 	struct nfs_page		*req;
+	struct nfs_inode	*nfsi = NFS_I(inode);
 
-	spin_lock(&nfs_wreq_lock);
+	spin_lock(&nfsi->req_lock);
 	req = _nfs_find_request(inode, index);
-	spin_unlock(&nfs_wreq_lock);
+	spin_unlock(&nfsi->req_lock);
 	return req;
 }
 
@@ -450,13 +460,13 @@
 static void
 nfs_mark_request_dirty(struct nfs_page *req)
 {
-	struct inode *inode = req->wb_inode;
+	struct inode *inode = req->wb_context->dentry->d_inode;
 	struct nfs_inode *nfsi = NFS_I(inode);
 
-	spin_lock(&nfs_wreq_lock);
+	spin_lock(&nfsi->req_lock);
 	nfs_list_add_request(req, &nfsi->dirty);
 	nfsi->ndirty++;
-	spin_unlock(&nfs_wreq_lock);
+	spin_unlock(&nfsi->req_lock);
 	inc_page_state(nr_dirty);
 	mark_inode_dirty(inode);
 }
@@ -467,7 +477,7 @@
 static inline int
 nfs_dirty_request(struct nfs_page *req)
 {
-	struct nfs_inode *nfsi = NFS_I(req->wb_inode);
+	struct nfs_inode *nfsi = NFS_I(req->wb_context->dentry->d_inode);
 	return !list_empty(&req->wb_list) && req->wb_list_head == &nfsi->dirty;
 }
 
@@ -478,13 +488,13 @@
 static void
 nfs_mark_request_commit(struct nfs_page *req)
 {
-	struct inode *inode = req->wb_inode;
+	struct inode *inode = req->wb_context->dentry->d_inode;
 	struct nfs_inode *nfsi = NFS_I(inode);
 
-	spin_lock(&nfs_wreq_lock);
+	spin_lock(&nfsi->req_lock);
 	nfs_list_add_request(req, &nfsi->commit);
 	nfsi->ncommit++;
-	spin_unlock(&nfs_wreq_lock);
+	spin_unlock(&nfsi->req_lock);
 	inc_page_state(nr_unstable);
 	mark_inode_dirty(inode);
 }
@@ -509,7 +519,7 @@
 	else
 		idx_end = idx_start + npages - 1;
 
-	spin_lock(&nfs_wreq_lock);
+	spin_lock(&nfsi->req_lock);
 	next = idx_start;
 	while (radix_tree_gang_lookup(&nfsi->nfs_page_tree, (void **)&req, next, 1)) {
 		if (req->wb_index > idx_end)
@@ -519,16 +529,16 @@
 		if (!NFS_WBACK_BUSY(req))
 			continue;
 
-		req->wb_count++;
-		spin_unlock(&nfs_wreq_lock);
+		atomic_inc(&req->wb_count);
+		spin_unlock(&nfsi->req_lock);
 		error = nfs_wait_on_request(req);
 		nfs_release_request(req);
 		if (error < 0)
 			return error;
-		spin_lock(&nfs_wreq_lock);
+		spin_lock(&nfsi->req_lock);
 		res++;
 	}
-	spin_unlock(&nfs_wreq_lock);
+	spin_unlock(&nfsi->req_lock);
 	return res;
 }
 
@@ -619,11 +629,12 @@
  *
  * Note: Should always be called with the Page Lock held!
  */
-static struct nfs_page *
-nfs_update_request(struct file* file, struct inode *inode, struct page *page,
-		   unsigned int offset, unsigned int bytes)
+static struct nfs_page * nfs_update_request(struct nfs_open_context* ctx,
+		struct inode *inode, struct page *page,
+		unsigned int offset, unsigned int bytes)
 {
 	struct nfs_server *server = NFS_SERVER(inode);
+	struct nfs_inode *nfsi = NFS_I(inode);
 	struct nfs_page		*req, *new = NULL;
 	unsigned long		rqend, end;
 
@@ -635,19 +646,19 @@
 		/* Loop over all inode entries and see if we find
 		 * A request for the page we wish to update
 		 */
-		spin_lock(&nfs_wreq_lock);
+		spin_lock(&nfsi->req_lock);
 		req = _nfs_find_request(inode, page->index);
 		if (req) {
 			if (!nfs_lock_request_dontget(req)) {
 				int error;
-				spin_unlock(&nfs_wreq_lock);
+				spin_unlock(&nfsi->req_lock);
 				error = nfs_wait_on_request(req);
 				nfs_release_request(req);
 				if (error < 0)
 					return ERR_PTR(error);
 				continue;
 			}
-			spin_unlock(&nfs_wreq_lock);
+			spin_unlock(&nfsi->req_lock);
 			if (new)
 				nfs_release_request(new);
 			break;
@@ -658,23 +669,19 @@
 			nfs_lock_request_dontget(new);
 			error = nfs_inode_add_request(inode, new);
 			if (error) {
-				spin_unlock(&nfs_wreq_lock);
+				spin_unlock(&nfsi->req_lock);
 				nfs_unlock_request(new);
 				return ERR_PTR(error);
 			}
-			spin_unlock(&nfs_wreq_lock);
+			spin_unlock(&nfsi->req_lock);
 			nfs_mark_request_dirty(new);
 			return new;
 		}
-		spin_unlock(&nfs_wreq_lock);
+		spin_unlock(&nfsi->req_lock);
 
-		new = nfs_create_request(file, inode, page, offset, bytes);
+		new = nfs_create_request(ctx, inode, page, offset, bytes);
 		if (IS_ERR(new))
 			return new;
-		if (file) {
-			new->wb_file = file;
-			get_file(file);
-		}
 	}
 
 	/* We have a request for our page.
@@ -684,7 +691,7 @@
 	 * request.
 	 */
 	rqend = req->wb_offset + req->wb_bytes;
-	if (req->wb_file != file
+	if (req->wb_context != ctx
 	    || req->wb_page != page
 	    || !nfs_dirty_request(req)
 	    || offset > rqend || end < req->wb_offset) {
@@ -705,9 +712,9 @@
 	return req;
 }
 
-int
-nfs_flush_incompatible(struct file *file, struct page *page)
+int nfs_flush_incompatible(struct file *file, struct page *page)
 {
+	struct nfs_open_context *ctx = (struct nfs_open_context *)file->private_data;
 	struct inode	*inode = page->mapping->host;
 	struct nfs_page	*req;
 	int		status = 0;
@@ -721,7 +728,7 @@
 	 */
 	req = nfs_find_request(inode, page->index);
 	if (req) {
-		if (!NFS_PROTO(inode)->request_compatible(req, file, page))
+		if (req->wb_page != page || ctx != req->wb_context)
 			status = nfs_wb_page(inode, page);
 		nfs_release_request(req);
 	}
@@ -737,6 +744,7 @@
 int nfs_updatepage(struct file *file, struct page *page,
 		unsigned int offset, unsigned int count)
 {
+	struct nfs_open_context *ctx = (struct nfs_open_context *)file->private_data;
 	struct dentry	*dentry = file->f_dentry;
 	struct inode	*inode = page->mapping->host;
 	struct nfs_page	*req;
@@ -747,7 +755,7 @@
 		count, (long long)(page_offset(page) +offset));
 
 	if (IS_SYNC(inode)) {
-		status = nfs_writepage_sync(file, inode, page, offset, count, 0);
+		status = nfs_writepage_sync(ctx, inode, page, offset, count, 0);
 		if (status > 0) {
 			if (offset == 0 && status == PAGE_CACHE_SIZE)
 				SetPageUptodate(page);
@@ -784,7 +792,7 @@
 	 * it out now.
 	 */
 	do {
-		req = nfs_update_request(file, inode, page, offset, count);
+		req = nfs_update_request(ctx, inode, page, offset, count);
 		status = (IS_ERR(req)) ? PTR_ERR(req) : 0;
 		if (status != -EBUSY)
 			break;
@@ -860,16 +868,15 @@
 	 * NB: take care not to mess about with data->commit et al. */
 
 	data->req = req;
-	data->inode = inode = req->wb_inode;
-	data->cred = req->wb_cred;
+	data->inode = inode = req->wb_context->dentry->d_inode;
+	data->cred = req->wb_context->cred;
 
 	data->args.fh     = NFS_FH(inode);
 	data->args.offset = req_offset(req) + offset;
 	data->args.pgbase = req->wb_pgbase + offset;
 	data->args.pages  = data->pagevec;
 	data->args.count  = count;
-	data->args.lockowner = req->wb_lockowner;
-	data->args.state  = req->wb_state;
+	data->args.context = req->wb_context;
 
 	data->res.fattr   = &data->fattr;
 	data->res.count   = count;
@@ -1029,7 +1036,7 @@
 	while (!list_empty(head)) {
 		pages += nfs_coalesce_requests(head, &one_request, wpages);
 		req = nfs_list_entry(one_request.next);
-		error = nfs_flush_one(&one_request, req->wb_inode, how);
+		error = nfs_flush_one(&one_request, req->wb_context->dentry->d_inode, how);
 		if (error < 0)
 			break;
 	}
@@ -1054,16 +1061,15 @@
 	struct page		*page = req->wb_page;
 
 	dprintk("NFS: write (%s/%Ld %d@%Ld)",
-		req->wb_inode->i_sb->s_id,
-		(long long)NFS_FILEID(req->wb_inode),
+		req->wb_context->dentry->d_inode->i_sb->s_id,
+		(long long)NFS_FILEID(req->wb_context->dentry->d_inode),
 		req->wb_bytes,
 		(long long)req_offset(req));
 
 	if (status < 0) {
 		ClearPageUptodate(page);
 		SetPageError(page);
-		if (req->wb_file)
-			req->wb_file->f_error = status;
+		req->wb_context->error = status;
 		dprintk(", error = %d\n", status);
 	} else {
 #if defined(CONFIG_NFS_V3) || defined(CONFIG_NFS_V4)
@@ -1104,16 +1110,15 @@
 		page = req->wb_page;
 
 		dprintk("NFS: write (%s/%Ld %d@%Ld)",
-			req->wb_inode->i_sb->s_id,
-			(long long)NFS_FILEID(req->wb_inode),
+			req->wb_context->dentry->d_inode->i_sb->s_id,
+			(long long)NFS_FILEID(req->wb_context->dentry->d_inode),
 			req->wb_bytes,
 			(long long)req_offset(req));
 
 		if (status < 0) {
 			ClearPageUptodate(page);
 			SetPageError(page);
-			if (req->wb_file)
-				req->wb_file->f_error = status;
+			req->wb_context->error = status;
 			end_page_writeback(page);
 			nfs_inode_remove_request(req);
 			dprintk(", error = %d\n", status);
@@ -1232,7 +1237,7 @@
 	list_splice_init(head, &data->pages);
 	first = nfs_list_entry(data->pages.next);
 	last = nfs_list_entry(data->pages.prev);
-	inode = first->wb_inode;
+	inode = first->wb_context->dentry->d_inode;
 
 	/*
 	 * Determine the offset range of requests in the COMMIT call.
@@ -1246,7 +1251,7 @@
 		len = 0;
 
 	data->inode	  = inode;
-	data->cred	  = first->wb_cred;
+	data->cred	  = first->wb_context->cred;
 
 	data->args.fh     = NFS_FH(data->inode);
 	data->args.offset = start;
@@ -1313,13 +1318,12 @@
 		nfs_list_remove_request(req);
 
 		dprintk("NFS: commit (%s/%Ld %d@%Ld)",
-			req->wb_inode->i_sb->s_id,
-			(long long)NFS_FILEID(req->wb_inode),
+			req->wb_context->dentry->d_inode->i_sb->s_id,
+			(long long)NFS_FILEID(req->wb_context->dentry->d_inode),
 			req->wb_bytes,
 			(long long)req_offset(req));
 		if (task->tk_status < 0) {
-			if (req->wb_file)
-				req->wb_file->f_error = task->tk_status;
+			req->wb_context->error = task->tk_status;
 			nfs_inode_remove_request(req);
 			dprintk(", error = %d\n", task->tk_status);
 			goto next;
@@ -1347,13 +1351,14 @@
 int nfs_flush_inode(struct inode *inode, unsigned long idx_start,
 		   unsigned int npages, int how)
 {
+	struct nfs_inode *nfsi = NFS_I(inode);
 	LIST_HEAD(head);
 	int			res,
 				error = 0;
 
-	spin_lock(&nfs_wreq_lock);
+	spin_lock(&nfsi->req_lock);
 	res = nfs_scan_dirty(inode, &head, idx_start, npages);
-	spin_unlock(&nfs_wreq_lock);
+	spin_unlock(&nfsi->req_lock);
 	if (res)
 		error = nfs_flush_list(&head, NFS_SERVER(inode)->wpages, how);
 	if (error < 0)
@@ -1365,18 +1370,19 @@
 int nfs_commit_inode(struct inode *inode, unsigned long idx_start,
 		    unsigned int npages, int how)
 {
+	struct nfs_inode *nfsi = NFS_I(inode);
 	LIST_HEAD(head);
 	int			res,
 				error = 0;
 
-	spin_lock(&nfs_wreq_lock);
+	spin_lock(&nfsi->req_lock);
 	res = nfs_scan_commit(inode, &head, idx_start, npages);
 	if (res) {
 		res += nfs_scan_commit(inode, &head, 0, 0);
-		spin_unlock(&nfs_wreq_lock);
+		spin_unlock(&nfsi->req_lock);
 		error = nfs_commit_list(&head, how);
 	} else
-		spin_unlock(&nfs_wreq_lock);
+		spin_unlock(&nfsi->req_lock);
 	if (error < 0)
 		return error;
 	return res;
diff -Nru a/fs/nfsd/Makefile b/fs/nfsd/Makefile
--- a/fs/nfsd/Makefile	2004-10-18 14:56:28 -07:00
+++ b/fs/nfsd/Makefile	2004-10-18 14:56:28 -07:00
@@ -7,5 +7,6 @@
 nfsd-y 			:= nfssvc.o nfsctl.o nfsproc.o nfsfh.o vfs.o \
 			   export.o auth.o lockd.o nfscache.o nfsxdr.o stats.o
 nfsd-$(CONFIG_NFSD_V3)	+= nfs3proc.o nfs3xdr.o
-nfsd-$(CONFIG_NFSD_V4)	+= nfs4proc.o nfs4xdr.o nfs4state.o nfs4idmap.o
+nfsd-$(CONFIG_NFSD_V4)	+= nfs4proc.o nfs4xdr.o nfs4state.o nfs4idmap.o \
+			   nfs4acl.o
 nfsd-objs		:= $(nfsd-y)
diff -Nru a/fs/nfsd/export.c b/fs/nfsd/export.c
--- a/fs/nfsd/export.c	2004-10-18 14:56:33 -07:00
+++ b/fs/nfsd/export.c	2004-10-18 14:56:33 -07:00
@@ -294,6 +294,11 @@
 
 	qword_add(bpp, blen, exp->ex_client->name);
 	pth = d_path(exp->ex_dentry, exp->ex_mnt, *bpp, *blen);
+	if (IS_ERR(pth)) {
+		/* is this correct? */
+		(*bpp)[0] = '\n';
+		return;
+	}
 	qword_add(bpp, blen, pth);
 	(*bpp)[-1] = '\n';
 }
diff -Nru a/fs/nfsd/lockd.c b/fs/nfsd/lockd.c
--- a/fs/nfsd/lockd.c	2004-10-18 14:56:49 -07:00
+++ b/fs/nfsd/lockd.c	2004-10-18 14:56:49 -07:00
@@ -10,6 +10,7 @@
 
 #include <linux/types.h>
 #include <linux/fs.h>
+#include <linux/file.h>
 #include <linux/mount.h>
 #include <linux/sunrpc/clnt.h>
 #include <linux/sunrpc/svc.h>
@@ -22,7 +23,7 @@
  * Note: we hold the dentry use count while the file is open.
  */
 static u32
-nlm_fopen(struct svc_rqst *rqstp, struct nfs_fh *f, struct file *filp)
+nlm_fopen(struct svc_rqst *rqstp, struct nfs_fh *f, struct file **filp)
 {
 	u32		nfserr;
 	struct svc_fh	fh;
@@ -35,10 +36,6 @@
 
 	exp_readlock();
 	nfserr = nfsd_open(rqstp, &fh, S_IFREG, MAY_LOCK, filp);
-	if (!nfserr) {
-		dget(filp->f_dentry);
-		mntget(filp->f_vfsmnt);
-	}
 	fh_put(&fh);
 	rqstp->rq_client = NULL;
 	exp_readunlock();
@@ -60,9 +57,7 @@
 static void
 nlm_fclose(struct file *filp)
 {
-	nfsd_close(filp);
-	dput(filp->f_dentry);
-	mntput(filp->f_vfsmnt);
+	fput(filp);
 }
 
 struct nlmsvc_binding		nfsd_nlm_ops = {
diff -Nru a/fs/nfsd/nfs3proc.c b/fs/nfsd/nfs3proc.c
--- a/fs/nfsd/nfs3proc.c	2004-10-18 14:56:28 -07:00
+++ b/fs/nfsd/nfs3proc.c	2004-10-18 14:56:28 -07:00
@@ -492,8 +492,16 @@
 		count += PAGE_SIZE;
 	}
 	resp->count = count >> 2;
-	if (resp->offset)
-		xdr_encode_hyper(resp->offset, offset);
+	if (resp->offset) {
+		if (unlikely(resp->offset1)) {
+			/* we ended up with offset on a page boundary */
+			*resp->offset = htonl(offset >> 32);
+			*resp->offset1 = htonl(offset & 0xffffffff);
+			resp->offset1 = NULL;
+		} else {
+			xdr_encode_hyper(resp->offset, offset);
+		}
+	}
 
 	RETURN_STATUS(nfserr);
 }
diff -Nru a/fs/nfsd/nfs3xdr.c b/fs/nfsd/nfs3xdr.c
--- a/fs/nfsd/nfs3xdr.c	2004-10-18 14:55:46 -07:00
+++ b/fs/nfsd/nfs3xdr.c	2004-10-18 14:55:46 -07:00
@@ -762,10 +762,16 @@
 		/* stupid readdir cookie */
 		memcpy(p, resp->verf, 8); p += 2;
 		xdr_ressize_check(rqstp, p);
-		p = resp->buffer;
+		if (rqstp->rq_res.head[0].iov_len + (2<<2) > PAGE_SIZE)
+			return 1; /*No room for trailer */
+		rqstp->rq_res.page_len = (resp->count) << 2;
+
+		/* add the 'tail' to the end of the 'head' page - page 0. */
+		rqstp->rq_restailpage = 0;
+		rqstp->rq_res.tail[0].iov_base = p;
 		*p++ = 0;		/* no more entries */
 		*p++ = htonl(resp->common.err == nfserr_eof);
-		rqstp->rq_res.page_len = (resp->count + 2) << 2;
+		rqstp->rq_res.tail[0].iov_len = 2<<2;
 		return 1;
 	} else
 		return xdr_ressize_check(rqstp, p);
diff -Nru a/fs/nfsd/nfs4acl.c b/fs/nfsd/nfs4acl.c
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/fs/nfsd/nfs4acl.c	2004-10-18 14:57:22 -07:00
@@ -0,0 +1,974 @@
+/*
+ *  fs/nfs4acl/acl.c
+ *
+ *  Common NFSv4 ACL handling code.
+ *
+ *  Copyright (c) 2002, 2003 The Regents of the University of Michigan.
+ *  All rights reserved.
+ *
+ *  Marius Aamodt Eriksen <marius@umich.edu>
+ *  Jeff Sedlak <jsedlak@umich.edu>
+ *  J. Bruce Fields <bfields@umich.edu>
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions
+ *  are met:
+ *
+ *  1. Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ *  2. Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in the
+ *     documentation and/or other materials provided with the distribution.
+ *  3. Neither the name of the University nor the names of its
+ *     contributors may be used to endorse or promote products derived
+ *     from this software without specific prior written permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ *  WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ *  DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ *  FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ *  CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ *  SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ *  BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ *  LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ *  NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ *  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <linux/string.h>
+#include <linux/slab.h>
+#include <linux/list.h>
+#include <linux/types.h>
+#include <linux/fs.h>
+#include <linux/module.h>
+#include <linux/nfs_fs.h>
+#include <linux/posix_acl.h>
+#include <linux/nfs4.h>
+#include <linux/nfs4_acl.h>
+
+
+/* mode bit translations: */
+#define NFS4_READ_MODE (NFS4_ACE_READ_DATA | NFS4_ACE_READ_NAMED_ATTRS)
+#define NFS4_WRITE_MODE (NFS4_ACE_WRITE_DATA | NFS4_ACE_WRITE_NAMED_ATTRS | NFS4_ACE_APPEND_DATA)
+#define NFS4_EXECUTE_MODE NFS4_ACE_EXECUTE
+#define NFS4_ANYONE_MODE (NFS4_ACE_READ_ATTRIBUTES | NFS4_ACE_READ_ACL | NFS4_ACE_SYNCHRONIZE)
+#define NFS4_OWNER_MODE (NFS4_ACE_WRITE_ATTRIBUTES | NFS4_ACE_WRITE_ACL)
+
+/* flags used to simulate posix default ACLs */
+#define NFS4_INHERITANCE_FLAGS (NFS4_ACE_FILE_INHERIT_ACE \
+		| NFS4_ACE_DIRECTORY_INHERIT_ACE | NFS4_ACE_INHERIT_ONLY_ACE)
+
+#define MASK_EQUAL(mask1, mask2) \
+	( ((mask1) & NFS4_ACE_MASK_ALL) == ((mask2) & NFS4_ACE_MASK_ALL) )
+
+static u32
+mask_from_posix(unsigned short perm, unsigned int flags)
+{
+	int mask = NFS4_ANYONE_MODE;
+
+	if (flags & NFS4_ACL_OWNER)
+		mask |= NFS4_OWNER_MODE;
+	if (perm & ACL_READ)
+		mask |= NFS4_READ_MODE;
+	if (perm & ACL_WRITE)
+		mask |= NFS4_WRITE_MODE;
+	if ((perm & ACL_WRITE) && (flags & NFS4_ACL_DIR))
+		mask |= NFS4_ACE_DELETE_CHILD;
+	if (perm & ACL_EXECUTE)
+		mask |= NFS4_EXECUTE_MODE;
+	return mask;
+}
+
+static u32
+deny_mask(u32 allow_mask, unsigned int flags)
+{
+	u32 ret = ~allow_mask & ~NFS4_ACE_DELETE;
+	if (!(flags & NFS4_ACL_DIR))
+		ret &= ~NFS4_ACE_DELETE_CHILD;
+	return ret;
+}
+
+static int
+mode_from_nfs4(u32 perm, unsigned short *mode, unsigned int flags)
+{
+	u32 ignore = 0;
+
+	if (!(flags & NFS4_ACL_DIR))
+		ignore |= NFS4_ACE_DELETE_CHILD; /* ignore it */
+	perm |= ignore;
+	*mode = 0;
+	if ((perm & NFS4_READ_MODE) == NFS4_READ_MODE)
+		*mode |= ACL_READ;
+	if ((perm & NFS4_WRITE_MODE) == NFS4_WRITE_MODE)
+		*mode |= ACL_WRITE;
+	if ((perm & NFS4_EXECUTE_MODE) == NFS4_EXECUTE_MODE)
+		*mode |= ACL_EXECUTE;
+	if (!MASK_EQUAL(perm, ignore|mask_from_posix(*mode, flags)))
+		return -EINVAL;
+	return 0;
+}
+
+struct ace_container {
+	struct nfs4_ace  *ace;
+	struct list_head  ace_l;
+};
+
+static short ace2type(struct nfs4_ace *);
+static int _posix_to_nfsv4_one(struct posix_acl *, struct nfs4_acl *, unsigned int);
+static struct posix_acl *_nfsv4_to_posix_one(struct nfs4_acl *, unsigned int);
+int nfs4_acl_add_ace(struct nfs4_acl *, u32, u32, u32, int, uid_t);
+int nfs4_acl_split(struct nfs4_acl *, struct nfs4_acl *);
+
+struct nfs4_acl *
+nfs4_acl_posix_to_nfsv4(struct posix_acl *pacl, struct posix_acl *dpacl,
+			unsigned int flags)
+{
+	struct nfs4_acl *acl;
+	int error = -EINVAL;
+
+	if ((pacl != NULL &&
+		(posix_acl_valid(pacl) < 0 || pacl->a_count == 0)) ||
+	    (dpacl != NULL &&
+		(posix_acl_valid(dpacl) < 0 || dpacl->a_count == 0)))
+		goto out_err;
+
+	acl = nfs4_acl_new();
+	if (acl == NULL) {
+		error = -ENOMEM;
+		goto out_err;
+	}
+
+	if (pacl != NULL) {
+		error = _posix_to_nfsv4_one(pacl, acl,
+						flags & ~NFS4_ACL_TYPE_DEFAULT);
+		if (error < 0)
+			goto out_acl;
+	}
+
+	if (dpacl != NULL) {
+		error = _posix_to_nfsv4_one(dpacl, acl,
+						flags | NFS4_ACL_TYPE_DEFAULT);
+		if (error < 0)
+			goto out_acl;
+	}
+
+	return acl;
+
+out_acl:
+	nfs4_acl_free(acl);
+out_err:
+	acl = ERR_PTR(error);
+
+	return acl;
+}
+
+static int
+nfs4_acl_add_pair(struct nfs4_acl *acl, int eflag, u32 mask, int whotype,
+		uid_t owner, unsigned int flags)
+{
+	int error;
+
+	error = nfs4_acl_add_ace(acl, NFS4_ACE_ACCESS_ALLOWED_ACE_TYPE,
+				 eflag, mask, whotype, owner);
+	if (error < 0)
+		return error;
+	error = nfs4_acl_add_ace(acl, NFS4_ACE_ACCESS_DENIED_ACE_TYPE,
+				eflag, deny_mask(mask, flags), whotype, owner);
+	return error;
+}
+
+/* We assume the acl has been verified with posix_acl_valid. */
+static int
+_posix_to_nfsv4_one(struct posix_acl *pacl, struct nfs4_acl *acl,
+						unsigned int flags)
+{
+	struct posix_acl_entry *pa, *pe, *group_owner_entry;
+	int error = -EINVAL;
+	u32 mask, mask_mask;
+	int eflag = ((flags & NFS4_ACL_TYPE_DEFAULT) ?
+					NFS4_INHERITANCE_FLAGS : 0);
+
+	BUG_ON(pacl->a_count < 3);
+	pe = pacl->a_entries + pacl->a_count;
+	pa = pe - 2; /* if mask entry exists, it's second from the last. */
+	if (pa->e_tag == ACL_MASK)
+		mask_mask = deny_mask(mask_from_posix(pa->e_perm, flags), flags);
+	else
+		mask_mask = 0;
+
+	pa = pacl->a_entries;
+	BUG_ON(pa->e_tag != ACL_USER_OBJ);
+	mask = mask_from_posix(pa->e_perm, flags | NFS4_ACL_OWNER);
+	error = nfs4_acl_add_pair(acl, eflag, mask, NFS4_ACL_WHO_OWNER, 0, flags);
+	if (error < 0)
+		goto out;
+	pa++;
+
+	while (pa->e_tag == ACL_USER) {
+		mask = mask_from_posix(pa->e_perm, flags);
+		error = nfs4_acl_add_ace(acl, NFS4_ACE_ACCESS_DENIED_ACE_TYPE,
+				eflag,  mask_mask, NFS4_ACL_WHO_NAMED, pa->e_id);
+		if (error < 0)
+			goto out;
+
+
+		error = nfs4_acl_add_pair(acl, eflag, mask,
+				NFS4_ACL_WHO_NAMED, pa->e_id, flags);
+		if (error < 0)
+			goto out;
+		pa++;
+	}
+
+	/* In the case of groups, we apply allow ACEs first, then deny ACEs,
+	 * since a user can be in more than one group.  */
+
+	/* allow ACEs */
+
+	if (pacl->a_count > 3) {
+		BUG_ON(pa->e_tag != ACL_GROUP_OBJ);
+		error = nfs4_acl_add_ace(acl, NFS4_ACE_ACCESS_DENIED_ACE_TYPE,
+				NFS4_ACE_IDENTIFIER_GROUP | eflag, mask_mask,
+				NFS4_ACL_WHO_GROUP, 0);
+		if (error < 0)
+			goto out;
+	}
+	group_owner_entry = pa;
+	mask = mask_from_posix(pa->e_perm, flags);
+	error = nfs4_acl_add_ace(acl, NFS4_ACE_ACCESS_ALLOWED_ACE_TYPE,
+			NFS4_ACE_IDENTIFIER_GROUP | eflag, mask,
+			NFS4_ACL_WHO_GROUP, 0);
+	if (error < 0)
+		goto out;
+	pa++;
+
+	while (pa->e_tag == ACL_GROUP) {
+		mask = mask_from_posix(pa->e_perm, flags);
+		error = nfs4_acl_add_ace(acl, NFS4_ACE_ACCESS_DENIED_ACE_TYPE,
+				NFS4_ACE_IDENTIFIER_GROUP | eflag, mask_mask,
+				NFS4_ACL_WHO_NAMED, pa->e_id);
+		if (error < 0)
+			goto out;
+
+		error = nfs4_acl_add_ace(acl, NFS4_ACE_ACCESS_ALLOWED_ACE_TYPE,
+		    		NFS4_ACE_IDENTIFIER_GROUP | eflag, mask,
+		    		NFS4_ACL_WHO_NAMED, pa->e_id);
+		if (error < 0)
+			goto out;
+		pa++;
+	}
+
+	/* deny ACEs */
+
+	pa = group_owner_entry;
+	mask = mask_from_posix(pa->e_perm, flags);
+	error = nfs4_acl_add_ace(acl, NFS4_ACE_ACCESS_DENIED_ACE_TYPE,
+			NFS4_ACE_IDENTIFIER_GROUP | eflag,
+			deny_mask(mask, flags), NFS4_ACL_WHO_GROUP, 0);
+	if (error < 0)
+		goto out;
+	pa++;
+	while (pa->e_tag == ACL_GROUP) {
+		mask = mask_from_posix(pa->e_perm, flags);
+		error = nfs4_acl_add_ace(acl, NFS4_ACE_ACCESS_DENIED_ACE_TYPE,
+		    		NFS4_ACE_IDENTIFIER_GROUP | eflag,
+		    		deny_mask(mask, flags), NFS4_ACL_WHO_NAMED, pa->e_id);
+		if (error < 0)
+			goto out;
+		pa++;
+	}
+
+	if (pa->e_tag == ACL_MASK)
+		pa++;
+	BUG_ON(pa->e_tag != ACL_OTHER);
+	mask = mask_from_posix(pa->e_perm, flags);
+	error = nfs4_acl_add_pair(acl, eflag, mask, NFS4_ACL_WHO_EVERYONE, 0, flags);
+
+out:
+	return error;
+}
+
+static void
+sort_pacl_range(struct posix_acl *pacl, int start, int end) {
+	int sorted = 0, i;
+	struct posix_acl_entry tmp;
+
+	/* We just do a bubble sort; easy to do in place, and we're not
+	 * expecting acl's to be long enough to justify anything more. */
+	while (!sorted) {
+		sorted = 1;
+		for (i = start; i < end; i++) {
+			if (pacl->a_entries[i].e_id
+					> pacl->a_entries[i+1].e_id) {
+				sorted = 0;
+				tmp = pacl->a_entries[i];
+				pacl->a_entries[i] = pacl->a_entries[i+1];
+				pacl->a_entries[i+1] = tmp;
+			}
+		}
+	}
+}
+
+static void
+sort_pacl(struct posix_acl *pacl)
+{
+	/* posix_acl_valid requires that users and groups be in order
+	 * by uid/gid. */
+	int i, j;
+
+	if (pacl->a_count <= 4)
+		return; /* no users or groups */
+	i = 1;
+	while (pacl->a_entries[i].e_tag == ACL_USER)
+		i++;
+	sort_pacl_range(pacl, 1, i-1);
+
+	BUG_ON(pacl->a_entries[i].e_tag != ACL_GROUP_OBJ);
+	j = i++;
+	while (pacl->a_entries[j].e_tag == ACL_GROUP)
+		j++;
+	sort_pacl_range(pacl, i, j-1);
+	return;
+}
+
+static int
+write_pace(struct nfs4_ace *ace, struct posix_acl *pacl,
+		struct posix_acl_entry **pace, short tag, unsigned int flags)
+{
+	struct posix_acl_entry *this = *pace;
+
+	if (*pace == pacl->a_entries + pacl->a_count)
+		return -EINVAL; /* fell off the end */
+	(*pace)++;
+	this->e_tag = tag;
+	if (tag == ACL_USER_OBJ)
+		flags |= NFS4_ACL_OWNER;
+	if (mode_from_nfs4(ace->access_mask, &this->e_perm, flags))
+		return -EINVAL;
+	this->e_id = (tag == ACL_USER || tag == ACL_GROUP ?
+			ace->who : ACL_UNDEFINED_ID);
+	return 0;
+}
+
+static struct nfs4_ace *
+get_next_v4_ace(struct list_head **p, struct list_head *head)
+{
+	struct nfs4_ace *ace;
+
+	*p = (*p)->next;
+	if (*p == head)
+		return NULL;
+	ace = list_entry(*p, struct nfs4_ace, l_ace);
+
+	return ace;
+}
+
+int
+nfs4_acl_nfsv4_to_posix(struct nfs4_acl *acl, struct posix_acl **pacl,
+		struct posix_acl **dpacl, unsigned int flags)
+{
+	struct nfs4_acl *dacl;
+	int error = -ENOMEM;
+
+	*pacl = NULL;
+	*dpacl = NULL;
+
+	dacl = nfs4_acl_new();
+	if (dacl == NULL)
+		goto out;
+
+	error = nfs4_acl_split(acl, dacl);
+	if (error < 0)
+		goto out_acl;
+
+	if (pacl != NULL) {
+		if (acl->naces == 0) {
+			error = -ENODATA;
+			goto try_dpacl;
+		}
+
+		*pacl = _nfsv4_to_posix_one(acl, flags);
+		if (IS_ERR(*pacl)) {
+			error = PTR_ERR(*pacl);
+			*pacl = NULL;
+			goto out_acl;
+		}
+	}
+
+try_dpacl:
+	if (dpacl != NULL) {
+		if (dacl->naces == 0) {
+			if (pacl == NULL || *pacl == NULL)
+				error = -ENODATA;
+			goto out_acl;
+		}
+
+		error = 0;
+		*dpacl = _nfsv4_to_posix_one(dacl, flags);
+		if (IS_ERR(*dpacl)) {
+			error = PTR_ERR(*dpacl);
+			*dpacl = NULL;
+			goto out_acl;
+		}
+	}
+
+out_acl:
+	if (error && pacl) {
+		posix_acl_release(*pacl);
+		*pacl = NULL;
+	}
+	nfs4_acl_free(dacl);
+out:
+	return error;
+}
+
+static int
+same_who(struct nfs4_ace *a, struct nfs4_ace *b)
+{
+	return a->whotype == b->whotype &&
+		(a->whotype != NFS4_ACL_WHO_NAMED || a->who == b->who);
+}
+
+static int
+complementary_ace_pair(struct nfs4_ace *allow, struct nfs4_ace *deny,
+		unsigned int flags)
+{
+	int ignore = 0;
+	if (!(flags & NFS4_ACL_DIR))
+		ignore |= NFS4_ACE_DELETE_CHILD;
+	return MASK_EQUAL(ignore|deny_mask(allow->access_mask, flags),
+			  ignore|deny->access_mask) &&
+		allow->type == NFS4_ACE_ACCESS_ALLOWED_ACE_TYPE &&
+		deny->type == NFS4_ACE_ACCESS_DENIED_ACE_TYPE &&
+		allow->flag == deny->flag &&
+		same_who(allow, deny);
+}
+
+static inline int
+user_obj_from_v4(struct nfs4_acl *n4acl, struct list_head **p,
+		struct posix_acl *pacl, struct posix_acl_entry **pace,
+		unsigned int flags)
+{
+	int error = -EINVAL;
+	struct nfs4_ace *ace, *ace2;
+
+	ace = get_next_v4_ace(p, &n4acl->ace_head);
+	if (ace == NULL)
+		goto out;
+	if (ace2type(ace) != ACL_USER_OBJ)
+		goto out;
+	error = write_pace(ace, pacl, pace, ACL_USER_OBJ, flags);
+	if (error < 0)
+		goto out;
+	error = -EINVAL;
+	ace2 = get_next_v4_ace(p, &n4acl->ace_head);
+	if (ace2 == NULL)
+		goto out;
+	if (!complementary_ace_pair(ace, ace2, flags))
+		goto out;
+	error = 0;
+out:
+	return error;
+}
+
+static inline int
+users_from_v4(struct nfs4_acl *n4acl, struct list_head **p,
+		struct nfs4_ace **mask_ace,
+		struct posix_acl *pacl, struct posix_acl_entry **pace,
+		unsigned int flags)
+{
+	int error = -EINVAL;
+	struct nfs4_ace *ace, *ace2;
+
+	ace = get_next_v4_ace(p, &n4acl->ace_head);
+	if (ace == NULL)
+		goto out;
+	while (ace2type(ace) == ACL_USER) {
+		if (ace->type != NFS4_ACE_ACCESS_DENIED_ACE_TYPE)
+			goto out;
+		if (*mask_ace &&
+			!MASK_EQUAL(ace->access_mask, (*mask_ace)->access_mask))
+			goto out;
+		*mask_ace = ace;
+		ace = get_next_v4_ace(p, &n4acl->ace_head);
+		if (ace == NULL)
+			goto out;
+		if (ace->type != NFS4_ACE_ACCESS_ALLOWED_ACE_TYPE)
+			goto out;
+		error = write_pace(ace, pacl, pace, ACL_USER, flags);
+		if (error < 0)
+			goto out;
+		error = -EINVAL;
+		ace2 = get_next_v4_ace(p, &n4acl->ace_head);
+		if (ace2 == NULL)
+			goto out;
+		if (!complementary_ace_pair(ace, ace2, flags))
+			goto out;
+		if ((*mask_ace)->flag != ace2->flag ||
+				!same_who(*mask_ace, ace2))
+			goto out;
+		ace = get_next_v4_ace(p, &n4acl->ace_head);
+		if (ace == NULL)
+			goto out;
+	}
+	error = 0;
+out:
+	return error;
+}
+
+static inline int
+group_obj_and_groups_from_v4(struct nfs4_acl *n4acl, struct list_head **p,
+		struct nfs4_ace **mask_ace,
+		struct posix_acl *pacl, struct posix_acl_entry **pace,
+		unsigned int flags)
+{
+	int error = -EINVAL;
+	struct nfs4_ace *ace, *ace2;
+	struct ace_container *ac;
+	struct list_head group_l;
+
+	INIT_LIST_HEAD(&group_l);
+	ace = list_entry(*p, struct nfs4_ace, l_ace);
+
+	/* group owner (mask and allow aces) */
+
+	if (pacl->a_count != 3) {
+		/* then the group owner should be preceded by mask */
+		if (ace->type != NFS4_ACE_ACCESS_DENIED_ACE_TYPE)
+			goto out;
+		if (*mask_ace &&
+			!MASK_EQUAL(ace->access_mask, (*mask_ace)->access_mask))
+			goto out;
+		*mask_ace = ace;
+		ace = get_next_v4_ace(p, &n4acl->ace_head);
+		if (ace == NULL)
+			goto out;
+
+		if ((*mask_ace)->flag != ace->flag || !same_who(*mask_ace, ace))
+			goto out;
+	}
+
+	if (ace2type(ace) != ACL_GROUP_OBJ)
+		goto out;
+
+	ac = kmalloc(sizeof(*ac), GFP_KERNEL);
+	error = -ENOMEM;
+	if (ac == NULL)
+		goto out;
+	ac->ace = ace;
+	list_add_tail(&ac->ace_l, &group_l);
+
+	error = -EINVAL;
+	if (ace->type != NFS4_ACE_ACCESS_ALLOWED_ACE_TYPE)
+		goto out;
+
+	error = write_pace(ace, pacl, pace, ACL_GROUP_OBJ, flags);
+	if (error < 0)
+		goto out;
+
+	error = -EINVAL;
+	ace = get_next_v4_ace(p, &n4acl->ace_head);
+	if (ace == NULL)
+		goto out;
+
+	/* groups (mask and allow aces) */
+
+	while (ace2type(ace) == ACL_GROUP) {
+		if (*mask_ace == NULL)
+			goto out;
+
+		if (ace->type != NFS4_ACE_ACCESS_DENIED_ACE_TYPE ||
+			!MASK_EQUAL(ace->access_mask, (*mask_ace)->access_mask))
+			goto out;
+		*mask_ace = ace;
+
+		ace = get_next_v4_ace(p, &n4acl->ace_head);
+		if (ace == NULL)
+			goto out;
+		ac = kmalloc(sizeof(*ac), GFP_KERNEL);
+		error = -ENOMEM;
+		if (ac == NULL)
+			goto out;
+		error = -EINVAL;
+		if (ace->type != NFS4_ACE_ACCESS_ALLOWED_ACE_TYPE ||
+				!same_who(ace, *mask_ace))
+			goto out;
+
+		ac->ace = ace;
+		list_add_tail(&ac->ace_l, &group_l);
+
+		error = write_pace(ace, pacl, pace, ACL_GROUP, flags);
+		if (error < 0)
+			goto out;
+		error = -EINVAL;
+		ace = get_next_v4_ace(p, &n4acl->ace_head);
+		if (ace == NULL)
+			goto out;
+	}
+
+	/* group owner (deny ace) */
+
+	if (ace2type(ace) != ACL_GROUP_OBJ)
+		goto out;
+	ac = list_entry(group_l.next, struct ace_container, ace_l);
+	ace2 = ac->ace;
+	if (!complementary_ace_pair(ace2, ace, flags))
+		goto out;
+	list_del(group_l.next);
+	kfree(ac);
+
+	/* groups (deny aces) */
+
+	while (!list_empty(&group_l)) {
+		ace = get_next_v4_ace(p, &n4acl->ace_head);
+		if (ace == NULL)
+			goto out;
+		if (ace2type(ace) != ACL_GROUP)
+			goto out;
+		ac = list_entry(group_l.next, struct ace_container, ace_l);
+		ace2 = ac->ace;
+		if (!complementary_ace_pair(ace2, ace, flags))
+			goto out;
+		list_del(group_l.next);
+		kfree(ac);
+	}
+
+	ace = get_next_v4_ace(p, &n4acl->ace_head);
+	if (ace == NULL)
+		goto out;
+	if (ace2type(ace) != ACL_OTHER)
+		goto out;
+	error = 0;
+out:
+	while (!list_empty(&group_l)) {
+		ac = list_entry(group_l.next, struct ace_container, ace_l);
+		list_del(group_l.next);
+		kfree(ac);
+	}
+	return error;
+}
+
+static inline int
+mask_from_v4(struct nfs4_acl *n4acl, struct list_head **p,
+		struct nfs4_ace **mask_ace,
+		struct posix_acl *pacl, struct posix_acl_entry **pace,
+		unsigned int flags)
+{
+	int error = -EINVAL;
+	struct nfs4_ace *ace;
+
+	ace = list_entry(*p, struct nfs4_ace, l_ace);
+	if (pacl->a_count != 3) {
+		if (*mask_ace == NULL)
+			goto out;
+		(*mask_ace)->access_mask = deny_mask((*mask_ace)->access_mask, flags);
+		write_pace(*mask_ace, pacl, pace, ACL_MASK, flags);
+	}
+	error = 0;
+out:
+	return error;
+}
+
+static inline int
+other_from_v4(struct nfs4_acl *n4acl, struct list_head **p,
+		struct posix_acl *pacl, struct posix_acl_entry **pace,
+		unsigned int flags)
+{
+	int error = -EINVAL;
+	struct nfs4_ace *ace, *ace2;
+
+	ace = list_entry(*p, struct nfs4_ace, l_ace);
+	if (ace->type != NFS4_ACE_ACCESS_ALLOWED_ACE_TYPE)
+		goto out;
+	error = write_pace(ace, pacl, pace, ACL_OTHER, flags);
+	if (error < 0)
+		goto out;
+	error = -EINVAL;
+	ace2 = get_next_v4_ace(p, &n4acl->ace_head);
+	if (ace2 == NULL)
+		goto out;
+	if (!complementary_ace_pair(ace, ace2, flags))
+		goto out;
+	error = 0;
+out:
+	return error;
+}
+
+static int
+calculate_posix_ace_count(struct nfs4_acl *n4acl)
+{
+	if (n4acl->naces == 6) /* owner, owner group, and other only */
+		return 3;
+	else { /* Otherwise there must be a mask entry. */
+		/* Also, the remaining entries are for named users and
+		 * groups, and come in threes (mask, allow, deny): */
+		if (n4acl->naces < 7)
+			return -1;
+		if ((n4acl->naces - 7) % 3)
+			return -1;
+		return 4 + (n4acl->naces - 7)/3;
+	}
+}
+
+
+static struct posix_acl *
+_nfsv4_to_posix_one(struct nfs4_acl *n4acl, unsigned int flags)
+{
+	struct posix_acl *pacl;
+	int error = -EINVAL, nace = 0;
+	struct list_head *p;
+	struct nfs4_ace *mask_ace = NULL;
+	struct posix_acl_entry *pace;
+
+	nace = calculate_posix_ace_count(n4acl);
+	if (nace < 0)
+		goto out_err;
+
+	pacl = posix_acl_alloc(nace, GFP_KERNEL);
+	error = -ENOMEM;
+	if (pacl == NULL)
+		goto out_err;
+
+	pace = &pacl->a_entries[0];
+	p = &n4acl->ace_head;
+
+	error = user_obj_from_v4(n4acl, &p, pacl, &pace, flags);
+	if (error)
+		goto out_acl;
+
+	error = users_from_v4(n4acl, &p, &mask_ace, pacl, &pace, flags);
+	if (error)
+		goto out_acl;
+
+	error = group_obj_and_groups_from_v4(n4acl, &p, &mask_ace, pacl, &pace,
+						flags);
+	if (error)
+		goto out_acl;
+
+	error = mask_from_v4(n4acl, &p, &mask_ace, pacl, &pace, flags);
+	if (error)
+		goto out_acl;
+	error = other_from_v4(n4acl, &p, pacl, &pace, flags);
+	if (error)
+		goto out_acl;
+
+	error = -EINVAL;
+	if (p->next != &n4acl->ace_head)
+		goto out_acl;
+	if (pace != pacl->a_entries + pacl->a_count)
+		goto out_acl;
+
+	sort_pacl(pacl);
+
+	return pacl;
+out_acl:
+	posix_acl_release(pacl);
+out_err:
+	pacl = ERR_PTR(error);
+	return pacl;
+}
+
+int
+nfs4_acl_split(struct nfs4_acl *acl, struct nfs4_acl *dacl)
+{
+	struct list_head *h, *n;
+	struct nfs4_ace *ace;
+	int error = 0;
+
+	list_for_each_safe(h, n, &acl->ace_head) {
+		ace = list_entry(h, struct nfs4_ace, l_ace);
+
+		if ((ace->flag & NFS4_INHERITANCE_FLAGS)
+				!= NFS4_INHERITANCE_FLAGS)
+			continue;
+
+		error = nfs4_acl_add_ace(dacl, ace->type, ace->flag,
+				ace->access_mask, ace->whotype, ace->who) == -1;
+		if (error < 0)
+			goto out;
+
+		list_del(h);
+		kfree(ace);
+		acl->naces--;
+	}
+
+out:
+	return error;
+}
+
+static short
+ace2type(struct nfs4_ace *ace)
+{
+	switch (ace->whotype) {
+		case NFS4_ACL_WHO_NAMED:
+			return (ace->flag & NFS4_ACE_IDENTIFIER_GROUP ?
+					ACL_GROUP : ACL_USER);
+		case NFS4_ACL_WHO_OWNER:
+			return ACL_USER_OBJ;
+		case NFS4_ACL_WHO_GROUP:
+			return ACL_GROUP_OBJ;
+		case NFS4_ACL_WHO_EVERYONE:
+			return ACL_OTHER;
+	}
+	BUG();
+	return -1;
+}
+
+EXPORT_SYMBOL(nfs4_acl_posix_to_nfsv4);
+EXPORT_SYMBOL(nfs4_acl_nfsv4_to_posix);
+
+struct nfs4_acl *
+nfs4_acl_new(void)
+{
+	struct nfs4_acl *acl;
+
+	if ((acl = kmalloc(sizeof(*acl), GFP_KERNEL)) == NULL)
+		return NULL;
+
+	acl->naces = 0;
+	INIT_LIST_HEAD(&acl->ace_head);
+
+	return acl;
+}
+
+void
+nfs4_acl_free(struct nfs4_acl *acl)
+{
+	struct list_head *h;
+	struct nfs4_ace *ace;
+
+	if (!acl)
+		return;
+
+	while (!list_empty(&acl->ace_head)) {
+		h = acl->ace_head.next;
+		list_del(h);
+		ace = list_entry(h, struct nfs4_ace, l_ace);
+		kfree(ace);
+	}
+
+	kfree(acl);
+
+	return;
+}
+
+int
+nfs4_acl_add_ace(struct nfs4_acl *acl, u32 type, u32 flag, u32 access_mask,
+		int whotype, uid_t who)
+{
+	struct nfs4_ace *ace;
+
+	if ((ace = kmalloc(sizeof(*ace), GFP_KERNEL)) == NULL)
+		return -1;
+
+	ace->type = type;
+	ace->flag = flag;
+	ace->access_mask = access_mask;
+	ace->whotype = whotype;
+	ace->who = who;
+
+	list_add_tail(&ace->l_ace, &acl->ace_head);
+	acl->naces++;
+
+	return 0;
+}
+
+static struct {
+	char *string;
+	int   stringlen;
+	int type;
+} s2t_map[] = {
+	{
+		.string    = "OWNER@",
+		.stringlen = sizeof("OWNER@") - 1,
+		.type      = NFS4_ACL_WHO_OWNER,
+	},
+	{
+		.string    = "GROUP@",
+		.stringlen = sizeof("GROUP@") - 1,
+		.type      = NFS4_ACL_WHO_GROUP,
+	},
+	{
+		.string    = "EVERYONE@",
+		.stringlen = sizeof("EVERYONE@") - 1,
+		.type      = NFS4_ACL_WHO_EVERYONE,
+	},
+};
+
+int
+nfs4_acl_get_whotype(char *p, u32 len)
+{
+	int i;
+
+	for (i=0; i < sizeof(s2t_map) / sizeof(*s2t_map); i++) {
+		if (s2t_map[i].stringlen == len &&
+				0 == memcmp(s2t_map[i].string, p, len))
+			return s2t_map[i].type;
+	}
+	return NFS4_ACL_WHO_NAMED;
+}
+
+int
+nfs4_acl_write_who(int who, char *p)
+{
+	int i;
+
+	for (i=0; i < sizeof(s2t_map) / sizeof(*s2t_map); i++) {
+		if (s2t_map[i].type == who) {
+			memcpy(p, s2t_map[i].string, s2t_map[i].stringlen);
+			return s2t_map[i].stringlen;
+		}
+	}
+	BUG();
+	return -1;
+}
+
+static inline int
+match_who(struct nfs4_ace *ace, uid_t owner, gid_t group, uid_t who)
+{
+	switch (ace->whotype) {
+		case NFS4_ACL_WHO_NAMED:
+			return who == ace->who;
+		case NFS4_ACL_WHO_OWNER:
+			return who == owner;
+		case NFS4_ACL_WHO_GROUP:
+			return who == group;
+		case NFS4_ACL_WHO_EVERYONE:
+			return 1;
+		default:
+			return 0;
+	}
+}
+
+/* 0 = granted, -EACCES = denied; mask is an nfsv4 mask, not mode bits */
+int
+nfs4_acl_permission(struct nfs4_acl *acl, uid_t owner, gid_t group,
+			uid_t who, u32 mask)
+{
+	struct nfs4_ace *ace;
+	u32 allowed = 0;
+
+	list_for_each_entry(ace, &acl->ace_head, l_ace) {
+		if (!match_who(ace, group, owner, who))
+			continue;
+		switch (ace->type) {
+			case NFS4_ACE_ACCESS_ALLOWED_ACE_TYPE:
+				allowed |= ace->access_mask;
+				if ((allowed & mask) == mask)
+					return 0;
+				break;
+			case NFS4_ACE_ACCESS_DENIED_ACE_TYPE:
+				if (ace->access_mask & mask)
+					return -EACCES;
+				break;
+		}
+	}
+	return -EACCES;
+}
+
+EXPORT_SYMBOL(nfs4_acl_new);
+EXPORT_SYMBOL(nfs4_acl_free);
+EXPORT_SYMBOL(nfs4_acl_add_ace);
+EXPORT_SYMBOL(nfs4_acl_get_whotype);
+EXPORT_SYMBOL(nfs4_acl_write_who);
+EXPORT_SYMBOL(nfs4_acl_permission);
diff -Nru a/fs/nfsd/nfs4proc.c b/fs/nfsd/nfs4proc.c
--- a/fs/nfsd/nfs4proc.c	2004-10-18 14:57:05 -07:00
+++ b/fs/nfsd/nfs4proc.c	2004-10-18 14:57:05 -07:00
@@ -52,6 +52,7 @@
 #include <linux/nfs4.h>
 #include <linux/nfsd/state.h>
 #include <linux/nfsd/xdr4.h>
+#include <linux/nfs4_acl.h>
 
 #define NFSDDBG_FACILITY		NFSDDBG_PROC
 
@@ -620,7 +621,7 @@
 		status = nfserr_bad_stateid;
 		if (ZERO_STATEID(&setattr->sa_stateid) || ONE_STATEID(&setattr->sa_stateid)) {
 			dprintk("NFSD: nfsd4_setattr: magic stateid!\n");
-			return status;
+			goto out;
 		}
 
 		nfs4_lock_state();
@@ -628,17 +629,25 @@
 						&setattr->sa_stateid, 
 						CHECK_FH | RDWR_STATE, &stp))) {
 			dprintk("NFSD: nfsd4_setattr: couldn't process stateid!\n");
-			goto out;
+			goto out_unlock;
 		}
 		status = nfserr_openmode;
 		if (!access_bits_permit_write(stp->st_access_bmap)) {
 			dprintk("NFSD: nfsd4_setattr: not opened for write!\n");
-			goto out;
+			goto out_unlock;
 		}
 		nfs4_unlock_state();
 	}
-	return (nfsd_setattr(rqstp, current_fh, &setattr->sa_iattr, 0, (time_t)0));
+	status = nfs_ok;
+	if (setattr->sa_acl != NULL)
+		status = nfsd4_set_nfs4_acl(rqstp, current_fh, setattr->sa_acl);
+	if (status)
+		goto out;
+	status = nfsd_setattr(rqstp, current_fh, &setattr->sa_iattr,
+				0, (time_t)0);
 out:
+	return status;
+out_unlock:
 	nfs4_unlock_state();
 	return status;
 }
diff -Nru a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c
--- a/fs/nfsd/nfs4state.c	2004-10-18 14:56:48 -07:00
+++ b/fs/nfsd/nfs4state.c	2004-10-18 14:56:48 -07:00
@@ -236,7 +236,7 @@
 create_client(struct xdr_netobj name) {
 	struct nfs4_client *clp;
 
-	if(!(clp = alloc_client(name)))
+	if (!(clp = alloc_client(name)))
 		goto out;
 	INIT_LIST_HEAD(&clp->cl_idhash);
 	INIT_LIST_HEAD(&clp->cl_strhash);
@@ -268,7 +268,7 @@
 
 static int
 cmp_name(struct xdr_netobj *n1, struct xdr_netobj *n2) {
-	if(!n1 || !n2)
+	if (!n1 || !n2)
 		return 0;
 	return((n1->len == n2->len) && !memcmp(n1->data, n2->data, n2->len));
 }
@@ -399,7 +399,7 @@
 			return 0;
 		}
 		cbaddr |= (temp << shift);
-		if(shift > 0)
+		if (shift > 0)
 		shift -= 8;
 	}
 	*cbaddrp = cbaddr;
@@ -411,7 +411,7 @@
 			return 0;
 		}
 		cbport |= (temp << shift);
-		if(shift > 0)
+		if (shift > 0)
 			shift -= 8;
 	}
 	*cbportp = cbport;
@@ -423,7 +423,7 @@
 {
 	struct nfs4_callback *cb = &clp->cl_callback;
 
-	if( !(parse_ipv4(se->se_callback_addr_len, se->se_callback_addr_val,
+	if ( !(parse_ipv4(se->se_callback_addr_len, se->se_callback_addr_val,
 		         &cb->cb_addr, &cb->cb_port))) {
 		printk(KERN_INFO "NFSD: BAD callback address. client will not receive delegations\n");
 		cb->cb_parsed = 0;
@@ -431,9 +431,9 @@
 	}
 	cb->cb_netid.len = se->se_callback_netid_len;
 	cb->cb_netid.data = se->se_callback_netid_val;
-        cb->cb_prog = se->se_callback_prog;
-        cb->cb_ident = se->se_callback_ident;
-        cb->cb_parsed = 1;
+	cb->cb_prog = se->se_callback_prog;
+	cb->cb_ident = se->se_callback_ident;
+	cb->cb_parsed = 1;
 }
 
 /*
@@ -812,7 +812,7 @@
 		alloc_file++;
 		return fp;
 	}
-	return (struct nfs4_file *)NULL;
+	return NULL;
 }
 
 static void
@@ -825,7 +825,7 @@
 		while (!list_empty(&file_hashtbl[i])) {
 			fp = list_entry(file_hashtbl[i].next, struct nfs4_file, fi_hash);
 			/* this should never be more than once... */
-			if(!list_empty(&fp->fi_perfile)) {
+			if (!list_empty(&fp->fi_perfile)) {
 				printk("ERROR: release_all_files: file %p is open, creating dangling state !!!\n",fp);
 			}
 			release_file(fp);
@@ -839,20 +839,20 @@
 	struct nfs4_stateowner *sop;
 
 	if ((sop = kmalloc(sizeof(struct nfs4_stateowner),GFP_KERNEL))) {
-		if((sop->so_owner.data = kmalloc(owner->len, GFP_KERNEL))) {
+		if ((sop->so_owner.data = kmalloc(owner->len, GFP_KERNEL))) {
 			memcpy(sop->so_owner.data, owner->data, owner->len);
 			sop->so_owner.len = owner->len;
 			return sop;
 		} 
 		kfree(sop);
 	}
-	return (struct nfs4_stateowner *)NULL;
+	return NULL;
 }
 
 /* should use a slab cache */
 static void
 free_stateowner(struct nfs4_stateowner *sop) {
-	if(sop) {
+	if (sop) {
 		kfree(sop->so_owner.data);
 		kfree(sop);
 		sop = NULL;
@@ -867,7 +867,7 @@
 	unsigned int idhashval;
 
 	if (!(sop = alloc_stateowner(&open->op_owner)))
-		return (struct nfs4_stateowner *)NULL;
+		return NULL;
 	idhashval = ownerid_hashval(current_ownerid);
 	INIT_LIST_HEAD(&sop->so_idhash);
 	INIT_LIST_HEAD(&sop->so_strhash);
@@ -908,7 +908,7 @@
 }
 
 static void
-release_stateowner(struct nfs4_stateowner *sop)
+unhash_stateowner(struct nfs4_stateowner *sop)
 {
 	struct nfs4_stateid *stp;
 
@@ -916,16 +916,22 @@
 	list_del(&sop->so_strhash);
 	list_del(&sop->so_perclient);
 	list_del(&sop->so_perlockowner);
-	list_del(&sop->so_close_lru);
 	del_perclient++;
 	while (!list_empty(&sop->so_perfilestate)) {
 		stp = list_entry(sop->so_perfilestate.next, 
 			struct nfs4_stateid, st_perfilestate);
-		if(sop->so_is_open_owner)
+		if (sop->so_is_open_owner)
 			release_stateid(stp, OPEN_STATE);
 		else
 			release_stateid(stp, LOCK_STATE);
 	}
+}
+
+static void
+release_stateowner(struct nfs4_stateowner *sop)
+{
+	unhash_stateowner(sop);
+	list_del(&sop->so_close_lru);
 	free_stateowner(sop);
 }
 
@@ -960,14 +966,12 @@
 	list_del_perfile++;
 	list_del(&stp->st_perfile);
 	list_del(&stp->st_perfilestate);
-	if((stp->st_vfs_set) && (flags & OPEN_STATE)) {
+	if ((stp->st_vfs_set) && (flags & OPEN_STATE)) {
 		release_stateid_lockowner(stp);
-		nfsd_close(&stp->st_vfs_file);
+		nfsd_close(stp->st_vfs_file);
 		vfsclose++;
-		dput(stp->st_vfs_file.f_dentry);
-		mntput(stp->st_vfs_file.f_vfsmnt);
 	} else if ((stp->st_vfs_set) && (flags & LOCK_STATE)) {
-		struct file *filp = &stp->st_vfs_file;
+		struct file *filp = stp->st_vfs_file;
 
 		locks_remove_posix(filp, (fl_owner_t) stp->st_stateowner);
 	}
@@ -988,13 +992,10 @@
 move_to_close_lru(struct nfs4_stateowner *sop)
 {
 	dprintk("NFSD: move_to_close_lru nfs4_stateowner %p\n", sop);
-	/* remove stateowner from all other hash lists except perclient */
-	list_del_init(&sop->so_idhash);
-	list_del_init(&sop->so_strhash);
-	list_del_init(&sop->so_perlockowner);
 
-        list_add_tail(&sop->so_close_lru, &close_lru);
-        sop->so_time = get_seconds();
+	unhash_stateowner(sop);
+	list_add_tail(&sop->so_close_lru, &close_lru);
+	sop->so_time = get_seconds();
 }
 
 void
@@ -1032,7 +1033,7 @@
 	struct nfs4_stateowner *local = NULL;
 
 	list_for_each_entry(local, &ownerstr_hashtbl[hashval], so_strhash) {
-		if(!cmp_owner_str(local, &open->op_owner, &open->op_clientid)) 
+		if (!cmp_owner_str(local, &open->op_owner, &open->op_clientid))
 			continue;
 		*op = local;
 		return(1);
@@ -1080,7 +1081,7 @@
 
 	*access = 0;
 	for (i = 1; i < 4; i++) {
-		if(test_bit(i, &bmap))
+		if (test_bit(i, &bmap))
 			*access |= i;
 	}
 }
@@ -1091,7 +1092,7 @@
 
 	*deny = 0;
 	for (i = 0; i < 4; i++) {
-		if(test_bit(i, &bmap))
+		if (test_bit(i, &bmap))
 			*deny |= i ;
 	}
 }
@@ -1280,7 +1281,7 @@
 		/* Search for conflicting share reservations */
 		status = nfserr_share_denied;
 		list_for_each_entry(stq, &fp->fi_perfile, st_perfile) {
-			if(stq->st_stateowner == sop) {
+			if (stq->st_stateowner == sop) {
 				stp = stq;
 				continue;
 			}
@@ -1315,8 +1316,6 @@
 			goto out_free;
 
 		vfsopen++;
-		dget(stp->st_vfs_file.f_dentry);
-		mntget(stp->st_vfs_file.f_vfsmnt);
 
 		init_stateid(stp, fp, sop, open);
 		stp->st_vfs_set = 1;
@@ -1331,7 +1330,7 @@
 		share_access &= open->op_share_access;
 
 		/* update the struct file */
-		if ((status = nfs4_file_upgrade(&stp->st_vfs_file, share_access)))
+		if ((status = nfs4_file_upgrade(stp->st_vfs_file, share_access)))
 			goto out;
 		/* remember the open */
 		set_bit(open->op_share_access, &stp->st_access_bmap);
@@ -1460,7 +1459,8 @@
 		}
 		dprintk("NFSD: purging unused open stateowner (so_id %d)\n",
 			sop->so_id);
-		release_stateowner(sop);
+		list_del(&sop->so_close_lru);
+		free_stateowner(sop);
 	}
 	if (clientid_val < NFSD_LAUNDROMAT_MINTIMEOUT)
 		clientid_val = NFSD_LAUNDROMAT_MINTIMEOUT;
@@ -1488,7 +1488,7 @@
 	dprintk("NFSD: find_openstateowner_id %d\n", st_id);
 	if (flags & CLOSE_STATE) {
 		list_for_each_entry(local, &close_lru, so_close_lru) {
-			if(local->so_id == st_id)
+			if (local->so_id == st_id)
 				return local;
 		}
 	}
@@ -1499,7 +1499,7 @@
 nfs4_check_fh(struct svc_fh *fhp, struct nfs4_stateid *stp)
 {
 	return (stp->st_vfs_set == 0 ||
-		fhp->fh_dentry->d_inode != stp->st_vfs_file.f_dentry->d_inode);
+		fhp->fh_dentry->d_inode != stp->st_vfs_file->f_dentry->d_inode);
 }
 
 static int
@@ -1816,7 +1816,7 @@
 		goto out;
 	}
 	set_access(&share_access, stp->st_access_bmap);
-	nfs4_file_downgrade(&stp->st_vfs_file, 
+	nfs4_file_downgrade(stp->st_vfs_file,
 	                    share_access & ~od->od_share_access);
 
 	reset_union_bmap_access(od->od_share_access, &stp->st_access_bmap);
@@ -1892,16 +1892,16 @@
 	if ((flags & LOCK_STATE) || (flags & RDWR_STATE)) {
 		hashval = stateid_hashval(st_id, f_id);
 		list_for_each_entry(local, &lockstateid_hashtbl[hashval], st_hash) {
-			if((local->st_stateid.si_stateownerid == st_id) &&
-			   (local->st_stateid.si_fileid == f_id))
+			if ((local->st_stateid.si_stateownerid == st_id) &&
+			    (local->st_stateid.si_fileid == f_id))
 				return local;
 		}
 	} 
 	if ((flags & OPEN_STATE) || (flags & RDWR_STATE)) {
 		hashval = stateid_hashval(st_id, f_id);
 		list_for_each_entry(local, &stateid_hashtbl[hashval], st_hash) {
-			if((local->st_stateid.si_stateownerid == st_id) &&
-			   (local->st_stateid.si_fileid == f_id))
+			if ((local->st_stateid.si_stateownerid == st_id) &&
+			    (local->st_stateid.si_fileid == f_id))
 				return local;
 		}
 	} else
@@ -1950,9 +1950,10 @@
 nfs4_set_lock_denied(struct file_lock *fl, struct nfsd4_lock_denied *deny)
 {
 	struct nfs4_stateowner *sop = (struct nfs4_stateowner *) fl->fl_owner;
+	unsigned int hval = lockownerid_hashval(sop->so_id);
 
 	deny->ld_sop = NULL;
-	if (nfs4_verify_lock_stateowner(sop, fl->fl_pid))
+	if (nfs4_verify_lock_stateowner(sop, hval))
 		deny->ld_sop = sop;
 	deny->ld_start = fl->fl_start;
 	deny->ld_length = ~(u64)0;
@@ -1971,7 +1972,7 @@
 
 	for (i = 0; i < LOCK_HASH_SIZE; i++) {
 		list_for_each_entry(local, &lock_ownerid_hashtbl[i], so_idhash) {
-			if(!cmp_owner_str(local, owner, clid))
+			if (!cmp_owner_str(local, owner, clid))
 				continue;
 			return local;
 		}
@@ -1984,7 +1985,7 @@
 	struct nfs4_stateowner *local = NULL;
 
 	list_for_each_entry(local, &lock_ownerstr_hashtbl[hashval], so_strhash) {
-		if(!cmp_owner_str(local, owner, clid)) 
+		if (!cmp_owner_str(local, owner, clid))
 			continue;
 		*op = local;
 		return(1);
@@ -2009,7 +2010,7 @@
 	unsigned int idhashval;
 
 	if (!(sop = alloc_stateowner(&lock->lk_new_owner)))
-		return (struct nfs4_stateowner *)NULL;
+		return NULL;
 	idhashval = lockownerid_hashval(current_ownerid);
 	INIT_LIST_HEAD(&sop->so_idhash);
 	INIT_LIST_HEAD(&sop->so_strhash);
@@ -2059,7 +2060,7 @@
 	stp->st_stateid.si_stateownerid = sop->so_id;
 	stp->st_stateid.si_fileid = fp->fi_id;
 	stp->st_stateid.si_generation = 0;
-	stp->st_vfs_file = open_stp->st_vfs_file;
+	stp->st_vfs_file = open_stp->st_vfs_file; /* FIXME refcount?? */
 	stp->st_vfs_set = open_stp->st_vfs_set;
 	stp->st_access_bmap = open_stp->st_access_bmap;
 	stp->st_deny_bmap = open_stp->st_deny_bmap;
@@ -2072,7 +2073,7 @@
 check_lock_length(u64 offset, u64 length)
 {
 	return ((length == 0)  || ((length != ~(u64)0) &&
- 	     LOFF_OVERFLOW(offset, length)));
+	     LOFF_OVERFLOW(offset, length)));
 }
 
 /*
@@ -2157,8 +2158,10 @@
 		if (!(lock->lk_stateowner = alloc_init_lock_stateowner(strhashval, open_sop->so_client, open_stp, lock)))
 			goto out;
 		if ((lock_stp = alloc_init_lock_stateid(lock->lk_stateowner, 
-						fp, open_stp)) == NULL)
+						fp, open_stp)) == NULL) {
+			release_stateowner(lock->lk_stateowner);
 			goto out;
+		}
 		/* bump the open seqid used to create the lock */
 		open_sop->so_seqid++;
 	} else {
@@ -2172,13 +2175,14 @@
 			goto out;
 	}
 	/* lock->lk_stateowner and lock_stp have been created or found */
-	filp = &lock_stp->st_vfs_file;
+	filp = lock_stp->st_vfs_file;
 
 	if ((status = fh_verify(rqstp, current_fh, S_IFREG, MAY_LOCK))) {
 		printk("NFSD: nfsd4_lock: permission denied!\n");
 		goto out;
 	}
 
+	locks_init_lock(&file_lock);
 	switch (lock->lk_type) {
 		case NFS4_READ_LT:
 		case NFS4_READW_LT:
@@ -2193,12 +2197,9 @@
 		goto out;
 	}
 	file_lock.fl_owner = (fl_owner_t) lock->lk_stateowner;
-	file_lock.fl_pid = lockownerid_hashval(lock->lk_stateowner->so_id);
+	file_lock.fl_pid = current->tgid;
 	file_lock.fl_file = filp;
 	file_lock.fl_flags = FL_POSIX;
-	file_lock.fl_notify = NULL;
-	file_lock.fl_insert = NULL;
-	file_lock.fl_remove = NULL;
 
 	file_lock.fl_start = lock->lk_offset;
 	if ((lock->lk_length == ~(u64)0) || 
@@ -2214,7 +2215,9 @@
 	*/
 
 	status = posix_lock_file(filp, &file_lock);
-	dprintk("NFSD: nfsd4_lock: posix_test_lock passed. posix_lock_file status %d\n",status);
+	if (file_lock.fl_ops && file_lock.fl_ops->fl_release_private)
+		file_lock.fl_ops->fl_release_private(&file_lock);
+	dprintk("NFSD: nfsd4_lock: posix_lock_file status %d\n",status);
 	switch (-status) {
 	case 0: /* success! */
 		update_stateid(&lock_stp->st_stateid);
@@ -2265,7 +2268,6 @@
 nfsd4_lockt(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_lockt *lockt)
 {
 	struct inode *inode;
-	struct nfs4_stateowner *sop;
 	struct file file;
 	struct file_lock file_lock;
 	struct file_lock *conflicting_lock;
@@ -2295,6 +2297,7 @@
 	}
 
 	inode = current_fh->fh_dentry->d_inode;
+	locks_init_lock(&file_lock);
 	switch (lockt->lt_type) {
 		case NFS4_READ_LT:
 		case NFS4_READW_LT:
@@ -2316,14 +2319,9 @@
 	find_lockstateowner_str(strhashval, &lockt->lt_owner,
 					&lockt->lt_clientid, 
 					&lockt->lt_stateowner);
-	sop = lockt->lt_stateowner;
-	if (sop) {
-		file_lock.fl_owner = (fl_owner_t) sop;
-		file_lock.fl_pid = lockownerid_hashval(sop->so_id);
-	} else {
-		file_lock.fl_owner = NULL;
-		file_lock.fl_pid = 0;
-	}
+	if (lockt->lt_stateowner)
+		file_lock.fl_owner = (fl_owner_t)lockt->lt_stateowner;
+	file_lock.fl_pid = current->tgid;
 	file_lock.fl_flags = FL_POSIX;
 
 	file_lock.fl_start = lockt->lt_offset;
@@ -2378,16 +2376,14 @@
 					&locku->lu_stateowner, &stp, NULL)))
 		goto out;
 
-	filp = &stp->st_vfs_file;
+	filp = stp->st_vfs_file;
 	BUG_ON(!filp);
+	locks_init_lock(&file_lock);
 	file_lock.fl_type = F_UNLCK;
 	file_lock.fl_owner = (fl_owner_t) locku->lu_stateowner;
-	file_lock.fl_pid = lockownerid_hashval(locku->lu_stateowner->so_id);
+	file_lock.fl_pid = current->tgid;
 	file_lock.fl_file = filp;
 	file_lock.fl_flags = FL_POSIX; 
-	file_lock.fl_notify = NULL;
-	file_lock.fl_insert = NULL;
-	file_lock.fl_remove = NULL;
 	file_lock.fl_start = locku->lu_offset;
 
 	if ((locku->lu_length == ~(u64)0) || LOFF_OVERFLOW(locku->lu_offset, locku->lu_length))
@@ -2400,6 +2396,8 @@
 	*  Try to unlock the file in the VFS.
 	*/
 	status = posix_lock_file(filp, &file_lock); 
+	if (file_lock.fl_ops && file_lock.fl_ops->fl_release_private)
+		file_lock.fl_ops->fl_release_private(&file_lock);
 	if (status) {
 		printk("NFSD: nfs4_locku: posix_lock_file failed!\n");
 		goto out_nfserr;
@@ -2462,7 +2460,7 @@
 
 	nfs4_lock_state();
 
-        status = nfs_ok;
+	status = nfs_ok;
 	local = find_lockstateowner(owner, clid);
 	if (local) {
 		struct nfs4_stateid *stp;
@@ -2472,8 +2470,8 @@
 		status = nfserr_locks_held;
 		list_for_each_entry(stp, &local->so_perfilestate,
 				st_perfilestate) {
-			if(stp->st_vfs_set) {
-				if (check_for_locks(&stp->st_vfs_file, local))
+			if (stp->st_vfs_set) {
+				if (check_for_locks(stp->st_vfs_file, local))
 					goto out;
 			}
 		}
@@ -2499,7 +2497,7 @@
 		kfree(crp);
 		return NULL;
 	}
-       	return crp;
+	return crp;
 }
 
 /*
@@ -2569,7 +2567,7 @@
 	strhashval = clientstr_hashval(client->cl_name.data,
 	                              client->cl_name.len);
 	list_for_each_entry(crp, &reclaim_str_hashtbl[strhashval], cr_strhash) {
-		if(cmp_name(&crp->cr_name, &client->cl_name)) {
+		if (cmp_name(&crp->cr_name, &client->cl_name)) {
 			return crp;
 		}
 	}
diff -Nru a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c
--- a/fs/nfsd/nfs4xdr.c	2004-10-18 14:56:50 -07:00
+++ b/fs/nfsd/nfs4xdr.c	2004-10-18 14:56:50 -07:00
@@ -55,6 +55,8 @@
 #include <linux/nfsd/state.h>
 #include <linux/nfsd/xdr4.h>
 #include <linux/nfsd_idmap.h>
+#include <linux/nfs4.h>
+#include <linux/nfs4_acl.h>
 
 #define NFSDDBG_FACILITY		NFSDDBG_XDR
 
@@ -348,7 +350,8 @@
 }
 
 static int
-nfsd4_decode_fattr(struct nfsd4_compoundargs *argp, u32 *bmval, struct iattr *iattr)
+nfsd4_decode_fattr(struct nfsd4_compoundargs *argp, u32 *bmval, struct iattr *iattr,
+    struct nfs4_acl **acl)
 {
 	int expected_len, len = 0;
 	u32 dummy32;
@@ -377,6 +380,51 @@
 		READ64(iattr->ia_size);
 		iattr->ia_valid |= ATTR_SIZE;
 	}
+	if (bmval[0] & FATTR4_WORD0_ACL) {
+		int nace, i;
+		struct nfs4_ace ace;
+
+		READ_BUF(4); len += 4;
+		READ32(nace);
+
+		*acl = nfs4_acl_new();
+		if (*acl == NULL) {
+			status = -ENOMEM;
+			goto out_nfserr;
+		}
+		defer_free(argp, (void (*)(const void *))nfs4_acl_free, *acl);
+
+		for (i = 0; i < nace; i++) {
+			READ_BUF(16); len += 16;
+			READ32(ace.type);
+			READ32(ace.flag);
+			READ32(ace.access_mask);
+			READ32(dummy32);
+			READ_BUF(dummy32);
+			len += XDR_QUADLEN(dummy32) << 2;
+			READMEM(buf, dummy32);
+			if (check_utf8(buf, dummy32))
+				return nfserr_inval;
+			ace.whotype = nfs4_acl_get_whotype(buf, dummy32);
+			status = 0;
+			if (ace.whotype != NFS4_ACL_WHO_NAMED)
+				ace.who = 0;
+			else if (ace.flag & NFS4_ACE_IDENTIFIER_GROUP)
+				status = nfsd_map_name_to_gid(argp->rqstp,
+						buf, dummy32, &ace.who);
+			else
+				status = nfsd_map_name_to_uid(argp->rqstp,
+						buf, dummy32, &ace.who);
+			if (status)
+				goto out_nfserr;
+			if (nfs4_acl_add_ace(*acl, ace.type, ace.flag,
+				 ace.access_mask, ace.whotype, ace.who) != 0) {
+				status = -ENOMEM;
+				goto out_nfserr;
+			}
+		}
+	} else
+		*acl = NULL;
 	if (bmval[1] & FATTR4_WORD1_MODE) {
 		READ_BUF(4);
 		len += 4;
@@ -562,7 +610,7 @@
 	if ((status = check_filename(create->cr_name, create->cr_namelen, nfserr_inval)))
 		return status;
 
-	if ((status = nfsd4_decode_fattr(argp, create->cr_bmval, &create->cr_iattr)))
+	if ((status = nfsd4_decode_fattr(argp, create->cr_bmval, &create->cr_iattr, &create->cr_acl)))
 		goto out;
 
 	DECODE_TAIL;
@@ -711,7 +759,7 @@
 		switch (open->op_createmode) {
 		case NFS4_CREATE_UNCHECKED:
 		case NFS4_CREATE_GUARDED:
-			if ((status = nfsd4_decode_fattr(argp, open->op_bmval, &open->op_iattr)))
+			if ((status = nfsd4_decode_fattr(argp, open->op_bmval, &open->op_iattr, &open->op_acl)))
 				goto out;
 			break;
 		case NFS4_CREATE_EXCLUSIVE:
@@ -888,7 +936,7 @@
 	READ_BUF(sizeof(stateid_t));
 	READ32(setattr->sa_stateid.si_generation);
 	COPYMEM(&setattr->sa_stateid.si_opaque, sizeof(stateid_opaque_t));
-	if ((status = nfsd4_decode_fattr(argp, setattr->sa_bmval, &setattr->sa_iattr)))
+	if ((status = nfsd4_decode_fattr(argp, setattr->sa_bmval, &setattr->sa_iattr, &setattr->sa_acl)))
 		goto out;
 
 	DECODE_TAIL;
@@ -1302,14 +1350,16 @@
 };
 
 static int
-nfsd4_encode_name(struct svc_rqst *rqstp, int group, uid_t id,
+nfsd4_encode_name(struct svc_rqst *rqstp, int whotype, uid_t id, int group,
 			u32 **p, int *buflen)
 {
 	int status;
 
 	if (*buflen < (XDR_QUADLEN(IDMAP_NAMESZ) << 2) + 4)
 		return nfserr_resource;
-	if (group)
+	if (whotype != NFS4_ACL_WHO_NAMED)
+		status = nfs4_acl_write_who(whotype, (u8 *)(*p + 1));
+	else if (group)
 		status = nfsd_map_gid_to_name(rqstp, id, (u8 *)(*p + 1));
 	else
 		status = nfsd_map_uid_to_name(rqstp, id, (u8 *)(*p + 1));
@@ -1324,13 +1374,20 @@
 static inline int
 nfsd4_encode_user(struct svc_rqst *rqstp, uid_t uid, u32 **p, int *buflen)
 {
-	return nfsd4_encode_name(rqstp, uid, 0, p, buflen);
+	return nfsd4_encode_name(rqstp, NFS4_ACL_WHO_NAMED, uid, 0, p, buflen);
 }
 
 static inline int
 nfsd4_encode_group(struct svc_rqst *rqstp, uid_t gid, u32 **p, int *buflen)
 {
-	return nfsd4_encode_name(rqstp, gid, 1, p, buflen);
+	return nfsd4_encode_name(rqstp, NFS4_ACL_WHO_NAMED, gid, 1, p, buflen);
+}
+
+static inline int
+nfsd4_encode_aclname(struct svc_rqst *rqstp, int whotype, uid_t id, int group,
+		u32 **p, int *buflen)
+{
+	return nfsd4_encode_name(rqstp, whotype, id, group, p, buflen);
 }
 
 
@@ -1357,6 +1414,8 @@
 	u64 dummy64;
 	u32 *p = buffer;
 	int status;
+	int aclsupport = 0;
+	struct nfs4_acl *acl = NULL;
 
 	BUG_ON(bmval1 & NFSD_WRITEONLY_ATTRS_WORD1);
 	BUG_ON(bmval0 & ~NFSD_SUPPORTED_ATTRS_WORD0);
@@ -1379,6 +1438,17 @@
 			goto out;
 		fhp = &tempfh;
 	}
+	if (bmval0 & (FATTR4_WORD0_ACL | FATTR4_WORD0_ACLSUPPORT
+			| FATTR4_WORD0_SUPPORTED_ATTRS)) {
+		status = nfsd4_get_nfs4_acl(rqstp, dentry, &acl);
+		aclsupport = (status == 0);
+		if (bmval0 & FATTR4_WORD0_ACL) {
+			if (status == -EOPNOTSUPP)
+				bmval0 &= ~FATTR4_WORD0_ACL;
+			else if (status != 0)
+				goto out_nfserr;
+		}
+	}
 	if ((buflen -= 16) < 0)
 		goto out_resource;
 
@@ -1391,7 +1461,9 @@
 		if ((buflen -= 12) < 0)
 			goto out_resource;
 		WRITE32(2);
-		WRITE32(NFSD_SUPPORTED_ATTRS_WORD0);
+		WRITE32(aclsupport ?
+			NFSD_SUPPORTED_ATTRS_WORD0 :
+			NFSD_SUPPORTED_ATTRS_WORD0 & ~FATTR4_WORD0_ACL);
 		WRITE32(NFSD_SUPPORTED_ATTRS_WORD1);
 	}
 	if (bmval0 & FATTR4_WORD0_TYPE) {
@@ -1462,10 +1534,44 @@
 			goto out_resource;
 		WRITE32(0);
 	}
+	if (bmval0 & FATTR4_WORD0_ACL) {
+		struct nfs4_ace *ace;
+		struct list_head *h;
+
+		if (acl == NULL) {
+			if ((buflen -= 4) < 0)
+				goto out_resource;
+
+			WRITE32(0);
+			goto out_acl;
+		}
+		if ((buflen -= 4) < 0)
+			goto out_resource;
+		WRITE32(acl->naces);
+
+		list_for_each(h, &acl->ace_head) {
+			ace = list_entry(h, struct nfs4_ace, l_ace);
+
+			if ((buflen -= 4*3) < 0)
+				goto out_resource;
+			WRITE32(ace->type);
+			WRITE32(ace->flag);
+			WRITE32(ace->access_mask & NFS4_ACE_MASK_ALL);
+			status = nfsd4_encode_aclname(rqstp, ace->whotype,
+				ace->who, ace->flag & NFS4_ACE_IDENTIFIER_GROUP,
+				&p, &buflen);
+			if (status == nfserr_resource)
+				goto out_resource;
+			if (status)
+				goto out;
+		}
+	}
+out_acl:
 	if (bmval0 & FATTR4_WORD0_ACLSUPPORT) {
 		if ((buflen -= 4) < 0)
 			goto out_resource;
-		WRITE32(0);
+		WRITE32(aclsupport ?
+			ACL4_SUPPORT_ALLOW_ACL|ACL4_SUPPORT_DENY_ACL : 0);
 	}
 	if (bmval0 & FATTR4_WORD0_CANSETTIME) {
 		if ((buflen -= 4) < 0)
@@ -1648,6 +1754,7 @@
 	status = nfs_ok;
 
 out:
+	nfs4_acl_free(acl);
 	if (fhp == &tempfh)
 		fh_put(&tempfh);
 	return status;
diff -Nru a/fs/nfsd/nfsctl.c b/fs/nfsd/nfsctl.c
--- a/fs/nfsd/nfsctl.c	2004-10-18 14:56:17 -07:00
+++ b/fs/nfsd/nfsctl.c	2004-10-18 14:56:17 -07:00
@@ -80,101 +80,31 @@
 	[NFSD_Leasetime] = write_leasetime,
 };
 
-/* an argresp is stored in an allocated page and holds the 
- * size of the argument or response, along with its content
- */
-struct argresp {
-	ssize_t size;
-	char data[0];
-};
-
-/*
- * transaction based IO methods.
- * The file expects a single write which triggers the transaction, and then
- * possibly a read which collects the result - which is stored in a 
- * file-local buffer.
- */
-static ssize_t TA_write(struct file *file, const char __user *buf, size_t size, loff_t *pos)
+static ssize_t nfsctl_transaction_write(struct file *file, const char __user *buf, size_t size, loff_t *pos)
 {
 	ino_t ino =  file->f_dentry->d_inode->i_ino;
-	struct argresp *ar;
-	ssize_t rv = 0;
+	char *data;
+	ssize_t rv;
 
 	if (ino >= sizeof(write_op)/sizeof(write_op[0]) || !write_op[ino])
 		return -EINVAL;
-	if (file->private_data) 
-		return -EINVAL; /* only one write allowed per open */
-	if (size > PAGE_SIZE - sizeof(struct argresp))
-		return -EFBIG;
 
-	ar = kmalloc(PAGE_SIZE, GFP_KERNEL);
-	if (!ar)
-		return -ENOMEM;
-	ar->size = 0;
-	down(&file->f_dentry->d_inode->i_sem);
-	if (file->private_data)
-		rv = -EINVAL;
-	else
-		file->private_data = ar;
-	up(&file->f_dentry->d_inode->i_sem);
-	if (rv) {
-		kfree(ar);
-		return rv;
-	}
-	if (copy_from_user(ar->data, buf, size))
-		return -EFAULT;
-	
-	rv =  write_op[ino](file, ar->data, size);
+	data = simple_transaction_get(file, buf, size);
+	if (IS_ERR(data))
+		return PTR_ERR(data);
+
+	rv =  write_op[ino](file, data, size);
 	if (rv>0) {
-		ar->size = rv;
+		simple_transaction_set(file, rv);
 		rv = size;
 	}
 	return rv;
 }
 
-
-static ssize_t TA_read(struct file *file, char __user *buf, size_t size, loff_t *pos)
-{
-	struct argresp *ar;
-	ssize_t rv = 0;
-	
-	if (file->private_data == NULL)
-		rv = TA_write(file, buf, 0, pos);
-	if (rv < 0)
-		return rv;
-
-	ar = file->private_data;
-	if (!ar)
-		return 0;
-	if (*pos >= ar->size)
-		return 0;
-	if (*pos + size > ar->size)
-		size = ar->size - *pos;
-	if (copy_to_user(buf, ar->data + *pos, size))
-		return -EFAULT;
-	*pos += size;
-	return size;
-}
-
-static int TA_open(struct inode *inode, struct file *file)
-{
-	file->private_data = NULL;
-	return 0;
-}
-
-static int TA_release(struct inode *inode, struct file *file)
-{
-	void *p = file->private_data;
-	file->private_data = NULL;
-	kfree(p);
-	return 0;
-}
-
 static struct file_operations transaction_ops = {
-	.write		= TA_write,
-	.read		= TA_read,
-	.open		= TA_open,
-	.release	= TA_release,
+	.write		= nfsctl_transaction_write,
+	.read		= simple_transaction_read,
+	.release	= simple_transaction_release,
 };
 
 extern struct seq_operations nfs_exports_op;
@@ -366,7 +296,7 @@
 	if (len)
 		return len;
 	
-	mesg = buf; len = PAGE_SIZE-sizeof(struct argresp);
+	mesg = buf; len = SIMPLE_TRANSACTION_LIMIT;
 	qword_addhex(&mesg, &len, (char*)&fh.fh_base, fh.fh_size);
 	mesg[-1] = '\n';
 	return mesg - buf;	
diff -Nru a/fs/nfsd/nfsfh.c b/fs/nfsd/nfsfh.c
--- a/fs/nfsd/nfsfh.c	2004-10-18 14:56:28 -07:00
+++ b/fs/nfsd/nfsfh.c	2004-10-18 14:56:28 -07:00
@@ -190,10 +190,10 @@
 			dentry = dget(exp->ex_dentry);
 		else {
 			struct export_operations *nop = exp->ex_mnt->mnt_sb->s_export_op;
-				dentry = CALL(nop,decode_fh)(exp->ex_mnt->mnt_sb,
-							     datap, data_left,
-							     fileid_type,
-							     nfsd_acceptable, exp);
+			dentry = CALL(nop,decode_fh)(exp->ex_mnt->mnt_sb,
+						     datap, data_left,
+						     fileid_type,
+						     nfsd_acceptable, exp);
 		}
 		if (dentry == NULL)
 			goto out;
@@ -339,13 +339,16 @@
 			ref_fh_fsid_type = ref_fh->fh_handle.fh_fsid_type;
 		if (ref_fh_fsid_type > 3)
 			ref_fh_fsid_type = 0;
-	}
-	/* make sure ref_fh type works for given export */
-	if (ref_fh_fsid_type == 1 &&
-	    !(exp->ex_flags & NFSEXP_FSID)) {
-		/* if we don't have an fsid, we cannot provide one... */
-		ref_fh_fsid_type = 0;
-	}
+
+		/* make sure ref_fh type works for given export */
+		if (ref_fh_fsid_type == 1 &&
+		    !(exp->ex_flags & NFSEXP_FSID)) {
+			/* if we don't have an fsid, we cannot provide one... */
+			ref_fh_fsid_type = 0;
+		}
+	} else if (exp->ex_flags & NFSEXP_FSID)
+		ref_fh_fsid_type = 1;
+
 	if (!old_valid_dev(ex_dev) && ref_fh_fsid_type == 0) {
 		/* for newer device numbers, we must use a newer fsid format */
 		ref_fh_version = 1;
diff -Nru a/fs/nfsd/nfsproc.c b/fs/nfsd/nfsproc.c
--- a/fs/nfsd/nfsproc.c	2004-10-18 14:56:28 -07:00
+++ b/fs/nfsd/nfsproc.c	2004-10-18 14:56:28 -07:00
@@ -586,6 +586,7 @@
 		{ nfserr_dquot, -EDQUOT },
 #endif
 		{ nfserr_stale, -ESTALE },
+		{ nfserr_jukebox, -EWOULDBLOCK },
 		{ nfserr_jukebox, -ETIMEDOUT },
 		{ nfserr_dropit, -EAGAIN },
 		{ nfserr_dropit, -ENOMEM },
diff -Nru a/fs/nfsd/nfssvc.c b/fs/nfsd/nfssvc.c
--- a/fs/nfsd/nfssvc.c	2004-10-18 14:56:32 -07:00
+++ b/fs/nfsd/nfssvc.c	2004-10-18 14:56:32 -07:00
@@ -328,6 +328,8 @@
 
 	/* Now call the procedure handler, and encode NFS status. */
 	nfserr = proc->pc_func(rqstp, rqstp->rq_argp, rqstp->rq_resp);
+	if (nfserr == nfserr_jukebox && rqstp->rq_vers == 2)
+		nfserr = nfserr_dropit;
 	if (nfserr == nfserr_dropit) {
 		dprintk("nfsd: Dropping request due to malloc failure!\n");
 		nfsd_cache_update(rqstp, RC_NOCACHE, NULL);
diff -Nru a/fs/nfsd/vfs.c b/fs/nfsd/vfs.c
--- a/fs/nfsd/vfs.c	2004-10-18 14:56:28 -07:00
+++ b/fs/nfsd/vfs.c	2004-10-18 14:56:28 -07:00
@@ -21,6 +21,7 @@
 #include <linux/time.h>
 #include <linux/errno.h>
 #include <linux/fs.h>
+#include <linux/file.h>
 #include <linux/mount.h>
 #include <linux/major.h>
 #include <linux/ext2_fs.h>
@@ -44,6 +45,16 @@
 #include <linux/nfsd/nfsfh.h>
 #include <linux/quotaops.h>
 #include <linux/dnotify.h>
+#ifdef CONFIG_NFSD_V4
+#include <linux/posix_acl.h>
+#include <linux/posix_acl_xattr.h>
+#include <linux/xattr_acl.h>
+#include <linux/xattr.h>
+#include <linux/nfs4.h>
+#include <linux/nfs4_acl.h>
+#include <linux/nfsd_idmap.h>
+#include <linux/security.h>
+#endif /* CONFIG_NFSD_V4 */
 
 #include <asm/uaccess.h>
 
@@ -69,6 +80,7 @@
 	unsigned int		p_count;
 	ino_t			p_ino;
 	dev_t			p_dev;
+	int			p_set;
 	struct file_ra_state	p_ra;
 };
 
@@ -291,8 +303,8 @@
 		 * If we are changing the size of the file, then
 		 * we need to break all leases.
 		 */
-		err = break_lease(inode, FMODE_WRITE);
-		if (err)
+		err = break_lease(inode, FMODE_WRITE | O_NONBLOCK);
+		if (err) /* ENOMEM or EWOULDBLOCK */
 			goto out_nfserr;
 
 		err = get_write_access(inode);
@@ -344,6 +356,177 @@
 	goto out;
 }
 
+#if defined(CONFIG_NFSD_V4)
+
+static int
+set_nfsv4_acl_one(struct dentry *dentry, struct posix_acl *pacl, char *key)
+{
+	int len;
+	size_t buflen;
+	char *buf = NULL;
+	int error = 0;
+	struct inode *inode = dentry->d_inode;
+
+	buflen = posix_acl_xattr_size(pacl->a_count);
+	buf = kmalloc(buflen, GFP_KERNEL);
+	error = -ENOMEM;
+	if (buf == NULL)
+		goto out;
+
+	len = posix_acl_to_xattr(pacl, buf, buflen);
+	if (len < 0) {
+		error = len;
+		goto out;
+	}
+
+	error = -EOPNOTSUPP;
+	if (inode->i_op && inode->i_op->setxattr) {
+		down(&inode->i_sem);
+		security_inode_setxattr(dentry, key, buf, len, 0);
+		error = inode->i_op->setxattr(dentry, key, buf, len, 0);
+		if (!error)
+			security_inode_post_setxattr(dentry, key, buf, len, 0);
+		up(&inode->i_sem);
+	}
+out:
+	kfree(buf);
+	return (error);
+}
+
+int
+nfsd4_set_nfs4_acl(struct svc_rqst *rqstp, struct svc_fh *fhp,
+    struct nfs4_acl *acl)
+{
+	int error;
+	struct dentry *dentry;
+	struct inode *inode;
+	struct posix_acl *pacl = NULL, *dpacl = NULL;
+	unsigned int flags = 0;
+
+	/* Get inode */
+	error = fh_verify(rqstp, fhp, 0 /* S_IFREG */, MAY_SATTR);
+	if (error)
+		goto out;
+
+	dentry = fhp->fh_dentry;
+	inode = dentry->d_inode;
+	if (S_ISDIR(inode->i_mode))
+		flags = NFS4_ACL_DIR;
+
+	error = nfs4_acl_nfsv4_to_posix(acl, &pacl, &dpacl, flags);
+	if (error < 0)
+		goto out_nfserr;
+
+	if (pacl) {
+		error = set_nfsv4_acl_one(dentry, pacl, XATTR_NAME_ACL_ACCESS);
+		if (error < 0)
+			goto out_nfserr;
+	}
+
+	if (dpacl) {
+		error = set_nfsv4_acl_one(dentry, dpacl, XATTR_NAME_ACL_DEFAULT);
+		if (error < 0)
+			goto out_nfserr;
+	}
+
+	error = nfs_ok;
+
+out:
+	posix_acl_release(pacl);
+	posix_acl_release(dpacl);
+	return (error);
+out_nfserr:
+	error = nfserrno(error);
+	goto out;
+}
+
+static struct posix_acl *
+_get_posix_acl(struct dentry *dentry, char *key)
+{
+	struct inode *inode = dentry->d_inode;
+	char *buf = NULL;
+	int buflen, error = 0;
+	struct posix_acl *pacl = NULL;
+
+	down(&inode->i_sem);
+
+	buflen = inode->i_op->getxattr(dentry, key, NULL, 0);
+	if (buflen <= 0) {
+		error = buflen < 0 ? buflen : -ENODATA;
+		goto out_sem;
+	}
+
+	buf = kmalloc(buflen, GFP_KERNEL);
+	if (buf == NULL) {
+		error = -ENOMEM;
+		goto out_sem;
+	}
+
+	error = -EOPNOTSUPP;
+	if (inode->i_op && inode->i_op->getxattr) {
+		error = security_inode_getxattr(dentry, key);
+		if (error)
+			goto out_sem;
+		error = inode->i_op->getxattr(dentry, key, buf, buflen);
+	}
+	if (error < 0)
+		goto out_sem;
+
+	error = 0;
+	up(&inode->i_sem);
+
+	pacl = posix_acl_from_xattr(buf, buflen);
+ out:
+	kfree(buf);
+	return pacl;
+ out_sem:
+	up(&inode->i_sem);
+	pacl = ERR_PTR(error);
+	goto out;
+}
+
+int
+nfsd4_get_nfs4_acl(struct svc_rqst *rqstp, struct dentry *dentry, struct nfs4_acl **acl)
+{
+	struct inode *inode = dentry->d_inode;
+	int error = 0;
+	struct posix_acl *pacl = NULL, *dpacl = NULL;
+	unsigned int flags = 0;
+
+	pacl = _get_posix_acl(dentry, XATTR_NAME_ACL_ACCESS);
+	if (IS_ERR(pacl) && PTR_ERR(pacl) == -ENODATA)
+		pacl = posix_acl_from_mode(inode->i_mode, GFP_KERNEL);
+	if (IS_ERR(pacl)) {
+		error = PTR_ERR(pacl);
+		pacl = NULL;
+		goto out;
+	}
+
+	if (S_ISDIR(inode->i_mode)) {
+		dpacl = _get_posix_acl(dentry, XATTR_NAME_ACL_DEFAULT);
+		if (IS_ERR(dpacl) && PTR_ERR(dpacl) == -ENODATA)
+			dpacl = NULL;
+		else if (IS_ERR(dpacl)) {
+			error = PTR_ERR(dpacl);
+			dpacl = NULL;
+			goto out;
+		}
+		flags = NFS4_ACL_DIR;
+	}
+
+	*acl = nfs4_acl_posix_to_nfsv4(pacl, dpacl, flags);
+	if (IS_ERR(*acl)) {
+		error = PTR_ERR(*acl);
+		*acl = NULL;
+	}
+ out:
+	posix_acl_release(pacl);
+	posix_acl_release(dpacl);
+	return error;
+}
+
+#endif /* defined(CONFIG_NFS_V4) */
+
 #ifdef CONFIG_NFSD_V3
 /*
  * Check server access rights to a file system object
@@ -376,12 +559,13 @@
 	 * to the server to check for access for things like /dev/null
 	 * (which really, the server doesn't care about).  So
 	 * We provide simple access checking for them, looking
-	 * mainly at mode bits
+	 * mainly at mode bits, and we make sure to ignore read-only
+	 * filesystem checks
 	 */
     {	NFS3_ACCESS_READ,	MAY_READ			},
     {	NFS3_ACCESS_EXECUTE,	MAY_EXEC			},
-    {	NFS3_ACCESS_MODIFY,	MAY_WRITE			},
-    {	NFS3_ACCESS_EXTEND,	MAY_WRITE			},
+    {	NFS3_ACCESS_MODIFY,	MAY_WRITE|MAY_LOCAL_ACCESS	},
+    {	NFS3_ACCESS_EXTEND,	MAY_WRITE|MAY_LOCAL_ACCESS	},
 
     {	0,			0				}
 };
@@ -454,7 +638,7 @@
  */
 int
 nfsd_open(struct svc_rqst *rqstp, struct svc_fh *fhp, int type,
-			int access, struct file *filp)
+			int access, struct file **filp)
 {
 	struct dentry	*dentry;
 	struct inode	*inode;
@@ -485,26 +669,18 @@
 	 * Check to see if there are any leases on this file.
 	 * This may block while leases are broken.
 	 */
-	err = break_lease(inode, (access & MAY_WRITE) ? FMODE_WRITE : 0);
-	if (err)
+	err = break_lease(inode, O_NONBLOCK | ((access & MAY_WRITE) ? FMODE_WRITE : 0));
+	if (err) /* NOMEM or WOULDBLOCK */
 		goto out_nfserr;
 
 	if (access & MAY_WRITE) {
-		err = get_write_access(inode);
-		if (err)
-			goto out_nfserr;
-
 		flags = O_WRONLY|O_LARGEFILE;
 
 		DQUOT_INIT(inode);
 	}
-
-	err = open_private_file(filp, dentry, flags);
-	if (!err) {
-		filp->f_vfsmnt = fhp->fh_export->ex_mnt;
-	} else if (access & MAY_WRITE)
-		put_write_access(inode);
-
+	*filp = dentry_open(dget(dentry), mntget(fhp->fh_export->ex_mnt), flags);
+	if (IS_ERR(*filp))
+		err = PTR_ERR(*filp);
 out_nfserr:
 	if (err)
 		err = nfserrno(err);
@@ -518,12 +694,7 @@
 void
 nfsd_close(struct file *filp)
 {
-	struct dentry	*dentry = filp->f_dentry;
-	struct inode	*inode = dentry->d_inode;
-
-	close_private_file(filp);
-	if (filp->f_mode & FMODE_WRITE)
-		put_write_access(inode);
+	fput(filp);
 }
 
 /*
@@ -567,7 +738,7 @@
 static spinlock_t ra_lock = SPIN_LOCK_UNLOCKED;
 
 static inline struct raparms *
-nfsd_get_raparms(dev_t dev, ino_t ino, struct address_space *mapping)
+nfsd_get_raparms(dev_t dev, ino_t ino)
 {
 	struct raparms	*ra, **rap, **frap = NULL;
 	int depth = 0;
@@ -589,7 +760,7 @@
 	ra = *frap;
 	ra->p_dev = dev;
 	ra->p_ino = ino;
-	file_ra_state_init(&ra->p_ra, mapping);
+	ra->p_set = 0;
 found:
 	if (rap != &raparm_cache) {
 		*rap = ra->p_next;
@@ -646,14 +817,14 @@
 	struct raparms	*ra;
 	mm_segment_t	oldfs;
 	int		err;
-	struct file	file;
+	struct file	*file;
 	struct inode	*inode;
 
 	err = nfsd_open(rqstp, fhp, S_IFREG, MAY_READ, &file);
 	if (err)
 		goto out;
 	err = nfserr_perm;
-	inode = file.f_dentry->d_inode;
+	inode = file->f_dentry->d_inode;
 #ifdef MSNFS
 	if ((fhp->fh_export->ex_flags & NFSEXP_MSNFS) &&
 		(!lock_may_read(inode, offset, *count)))
@@ -661,38 +832,40 @@
 #endif
 
 	/* Get readahead parameters */
-	ra = nfsd_get_raparms(inode->i_sb->s_dev, inode->i_ino,
-			      inode->i_mapping->host->i_mapping);
-	if (ra)
-		file.f_ra = ra->p_ra;
+	ra = nfsd_get_raparms(inode->i_sb->s_dev, inode->i_ino);
 
-	if (file.f_op->sendfile) {
+	if (ra && ra->p_set)
+		file->f_ra = ra->p_ra;
+
+	if (file->f_op->sendfile) {
 		svc_pushback_unused_pages(rqstp);
-		err = file.f_op->sendfile(&file, &offset, *count,
+		err = file->f_op->sendfile(file, &offset, *count,
 						 nfsd_read_actor, rqstp);
 	} else {
 		oldfs = get_fs();
 		set_fs(KERNEL_DS);
-		err = vfs_readv(&file, (struct iovec __user *)vec, vlen, &offset);
+		err = vfs_readv(file, (struct iovec __user *)vec, vlen, &offset);
 		set_fs(oldfs);
 	}
 
 	/* Write back readahead params */
 	if (ra) {
 		spin_lock(&ra_lock);
-		ra->p_ra = file.f_ra;
+		ra->p_ra = file->f_ra;
+		ra->p_set = 1;
 		ra->p_count--;
 		spin_unlock(&ra_lock);
 	}
+
 	if (err >= 0) {
 		nfsdstats.io_read += err;
 		*count = err;
 		err = 0;
-		dnotify_parent(file.f_dentry, DN_ACCESS);
+		dnotify_parent(file->f_dentry, DN_ACCESS);
 	} else 
 		err = nfserrno(err);
 out_close:
-	nfsd_close(&file);
+	nfsd_close(file);
 out:
 	return err;
 }
@@ -708,7 +881,7 @@
 	   			unsigned long cnt, int *stablep)
 {
 	struct svc_export	*exp;
-	struct file		file;
+	struct file		*file;
 	struct dentry		*dentry;
 	struct inode		*inode;
 	mm_segment_t		oldfs;
@@ -724,11 +897,11 @@
 
 #ifdef MSNFS
 	if ((fhp->fh_export->ex_flags & NFSEXP_MSNFS) &&
-		(!lock_may_write(file.f_dentry->d_inode, offset, cnt)))
+		(!lock_may_write(file->f_dentry->d_inode, offset, cnt)))
 		goto out_close;
 #endif
 
-	dentry = file.f_dentry;
+	dentry = file->f_dentry;
 	inode = dentry->d_inode;
 	exp   = fhp->fh_export;
 
@@ -741,7 +914,7 @@
 	 * flushing the data to disk is handled separately below.
 	 */
 
-	if (file.f_op->fsync == 0) {/* COMMIT3 cannot work */
+	if (file->f_op->fsync == 0) {/* COMMIT3 cannot work */
 	       stable = 2;
 	       *stablep = 2; /* FILE_SYNC */
 	}
@@ -749,15 +922,15 @@
 	if (!EX_ISSYNC(exp))
 		stable = 0;
 	if (stable && !EX_WGATHER(exp))
-		file.f_flags |= O_SYNC;
+		file->f_flags |= O_SYNC;
 
 	/* Write the data. */
 	oldfs = get_fs(); set_fs(KERNEL_DS);
-	err = vfs_writev(&file, (struct iovec __user *)vec, vlen, &offset);
+	err = vfs_writev(file, (struct iovec __user *)vec, vlen, &offset);
 	set_fs(oldfs);
 	if (err >= 0) {
 		nfsdstats.io_write += cnt;
-		dnotify_parent(file.f_dentry, DN_MODIFY);
+		dnotify_parent(file->f_dentry, DN_MODIFY);
 	}
 
 	/* clear setuid/setgid flag after write */
@@ -797,7 +970,7 @@
 
 			if (inode->i_state & I_DIRTY) {
 				dprintk("nfsd: write sync %d\n", current->pid);
-				nfsd_sync(&file);
+				nfsd_sync(file);
 			}
 #if 0
 			wake_up(&inode->i_wait);
@@ -813,7 +986,7 @@
 	else 
 		err = nfserrno(err);
 out_close:
-	nfsd_close(&file);
+	nfsd_close(file);
 out:
 	return err;
 }
@@ -832,7 +1005,7 @@
 nfsd_commit(struct svc_rqst *rqstp, struct svc_fh *fhp,
                loff_t offset, unsigned long count)
 {
-	struct file	file;
+	struct file	*file;
 	int		err;
 
 	if ((u64)count > ~(u64)offset)
@@ -841,14 +1014,14 @@
 	if ((err = nfsd_open(rqstp, fhp, S_IFREG, MAY_WRITE, &file)) != 0)
 		return err;
 	if (EX_ISSYNC(fhp->fh_export)) {
-		if (file.f_op && file.f_op->fsync) {
-			nfsd_sync(&file);
+		if (file->f_op && file->f_op->fsync) {
+			nfsd_sync(file);
 		} else {
 			err = nfserr_notsupp;
 		}
 	}
 
-	nfsd_close(&file);
+	nfsd_close(file);
 	return err;
 }
 #endif /* CONFIG_NFSD_V3 */
@@ -1471,14 +1644,14 @@
 	     struct readdir_cd *cdp, encode_dent_fn func)
 {
 	int		err;
-	struct file	file;
+	struct file	*file;
 	loff_t		offset = *offsetp;
 
 	err = nfsd_open(rqstp, fhp, S_IFDIR, MAY_READ, &file);
 	if (err)
 		goto out;
 
-	offset = vfs_llseek(&file, offset, 0);
+	offset = vfs_llseek(file, offset, 0);
 	if (offset < 0) {
 		err = nfserrno((int)offset);
 		goto out_close;
@@ -1492,18 +1665,18 @@
 
 	do {
 		cdp->err = nfserr_eof; /* will be cleared on successful read */
-		err = vfs_readdir(&file, (filldir_t) func, cdp);
+		err = vfs_readdir(file, (filldir_t) func, cdp);
 	} while (err >=0 && cdp->err == nfs_ok);
 	if (err)
 		err = nfserrno(err);
 	else
 		err = cdp->err;
-	*offsetp = vfs_llseek(&file, 0, 1);
+	*offsetp = vfs_llseek(file, 0, 1);
 
 	if (err == nfserr_eof || err == nfserr_toosmall)
 		err = nfs_ok; /* can still be found in ->err */
 out_close:
-	nfsd_close(&file);
+	nfsd_close(file);
 out:
 	return err;
 }
diff -Nru a/fs/nls/nls_cp932.c b/fs/nls/nls_cp932.c
--- a/fs/nls/nls_cp932.c	2004-10-18 14:56:27 -07:00
+++ b/fs/nls/nls_cp932.c	2004-10-18 14:56:27 -07:00
@@ -1619,6 +1619,33 @@
 	NULL,   NULL,   c2u_FA, c2u_FB, c2u_FC, NULL,   NULL,   NULL,   
 };
 
+static unsigned char u2c_00hi[256 - 0xA0][2] = {
+	{0x00, 0x00}, {0x00, 0x00}, {0x81, 0x91}, {0x81, 0x92},/* 0xA0-0xA3 */
+	{0x00, 0x00}, {0x00, 0x00}, {0x00, 0x00}, {0x81, 0x98},/* 0xA4-0xA7 */
+	{0x81, 0x4E}, {0x00, 0x00}, {0x00, 0x00}, {0x00, 0x00},/* 0xA8-0xAB */
+	{0x81, 0xCA}, {0x00, 0x00}, {0x00, 0x00}, {0x00, 0x00},/* 0xAC-0xAF */
+	{0x81, 0x8B}, {0x81, 0x7D}, {0x00, 0x00}, {0x00, 0x00},/* 0xB0-0xB3 */
+	{0x81, 0x4C}, {0x00, 0x00}, {0x81, 0xF7}, {0x00, 0x00},/* 0xB4-0xB7 */
+	{0x00, 0x00}, {0x00, 0x00}, {0x00, 0x00}, {0x00, 0x00},/* 0xB8-0xBB */
+	{0x00, 0x00}, {0x00, 0x00}, {0x00, 0x00}, {0x00, 0x00},/* 0xBC-0xBF */
+	{0x00, 0x00}, {0x00, 0x00}, {0x00, 0x00}, {0x00, 0x00},/* 0xC0-0xC3 */
+	{0x00, 0x00}, {0x00, 0x00}, {0x00, 0x00}, {0x00, 0x00},/* 0xC4-0xC7 */
+	{0x00, 0x00}, {0x00, 0x00}, {0x00, 0x00}, {0x00, 0x00},/* 0xC8-0xCB */
+	{0x00, 0x00}, {0x00, 0x00}, {0x00, 0x00}, {0x00, 0x00},/* 0xCC-0xCF */
+	{0x00, 0x00}, {0x00, 0x00}, {0x00, 0x00}, {0x00, 0x00},/* 0xD0-0xD3 */
+	{0x00, 0x00}, {0x00, 0x00}, {0x00, 0x00}, {0x81, 0x7E},/* 0xD4-0xD7 */
+	{0x00, 0x00}, {0x00, 0x00}, {0x00, 0x00}, {0x00, 0x00},/* 0xD8-0xDB */
+	{0x00, 0x00}, {0x00, 0x00}, {0x00, 0x00}, {0x00, 0x00},/* 0xDC-0xDF */
+	{0x00, 0x00}, {0x00, 0x00}, {0x00, 0x00}, {0x00, 0x00},/* 0xE0-0xE3 */
+	{0x00, 0x00}, {0x00, 0x00}, {0x00, 0x00}, {0x00, 0x00},/* 0xE4-0xE7 */
+	{0x00, 0x00}, {0x00, 0x00}, {0x00, 0x00}, {0x00, 0x00},/* 0xE8-0xEB */
+	{0x00, 0x00}, {0x00, 0x00}, {0x00, 0x00}, {0x00, 0x00},/* 0xEC-0xEF */
+	{0x00, 0x00}, {0x00, 0x00}, {0x00, 0x00}, {0x00, 0x00},/* 0xF0-0xF3 */
+	{0x00, 0x00}, {0x00, 0x00}, {0x00, 0x00}, {0x81, 0x80},/* 0xF4-0xF7 */
+	{0x00, 0x00}, {0x00, 0x00}, {0x00, 0x00}, {0x00, 0x00},/* 0xF8-0xFB */
+	{0x00, 0x00}, {0x00, 0x00}, {0x00, 0x00}, {0x00, 0x00},/* 0xFC-0xFF */
+};
+
 static unsigned char u2c_03[512] = {
 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x00-0x03 */
 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x04-0x07 */
@@ -7708,7 +7735,7 @@
 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xD4-0xD7 */
 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xD8-0xDB */
 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xDC-0xDF */
-	0x81, 0x91, 0x81, 0x92, 0xEE, 0xF9, 0x81, 0x50, /* 0xE0-0xE3 */
+	0x81, 0x91, 0x81, 0x92, 0x81, 0xCA, 0x81, 0x50, /* 0xE0-0xE3 */
 	0xEE, 0xFA, 0x81, 0x8F, 0x00, 0x00, 0x00, 0x00, /* 0xE4-0xE7 */
 };
 
@@ -7842,9 +7869,17 @@
 		if (out[0] == 0x00 && out[1] == 0x00)
 			return -EINVAL;
 		return 2;
-	} else if ((ch == 0) && (cl <= 0x7F)) {
-		out[0] = cl;
-		return 1;
+	} else if (ch == 0) {
+		if (cl <= 0x7F) {
+			out[0] = cl;
+			return 1;
+		} else if (0xA0 <= cl) {
+			out[0] = u2c_00hi[cl - 0xA0][0];
+			out[1] = u2c_00hi[cl - 0xA0][1];
+			if (out[0] && out[1])
+				return 2;
+		}
+		return -EINVAL;
 	}
 	else
 		return -EINVAL;
diff -Nru a/fs/ntfs/ChangeLog b/fs/ntfs/ChangeLog
--- a/fs/ntfs/ChangeLog	2004-10-18 14:56:27 -07:00
+++ b/fs/ntfs/ChangeLog	2004-10-18 14:56:27 -07:00
@@ -1,11 +1,6 @@
 ToDo/Notes:
 	- Find and fix bugs.
 	- Checkpoint or disable the user space journal ($UsnJrnl).
-	- Implement sops->dirty_inode() to implement {a,m,c}time updates and
-	  such things.  This should probably just flag the ntfs inode such that
-	  sops->write_inode(), i.e. ntfs_write_inode(), will copy the times
-	  when it is invoked rather than having to update the mft record
-	  every time.
 	- In between ntfs_prepare/commit_write, need exclusion between
 	  simultaneous file extensions. Need perhaps an NInoResizeUnderway()
 	  flag which we can set in ntfs_prepare_write() and clear again in
@@ -26,6 +21,114 @@
 	- Enable the code for setting the NT4 compatibility flag when we start
 	  making NTFS 1.2 specific modifications.
 
+2.1.20 - Fix a stupid bug in ntfs_attr_reinit_search_ctx().
+
+	- Fix stupid bug in fs/ntfs/attrib.c::ntfs_attr_reinit_search_ctx()
+	  where we did not clear ctx->al_entry but it was still set due to
+	  changes in ntfs_attr_lookup() and ntfs_external_attr_find() in
+	  particular.
+	- Fix another stupid bug in fs/ntfs/attrib.c::ntfs_external_attr_find()
+	  where we forgot to unmap the extent mft record when we had finished
+	  enumerating an attribute which caused a bug check to trigger when the
+	  VFS calls ->clear_inode.
+
+2.1.19 - Many cleanups, improvements, and a minor bug fix.
+
+	- Update ->setattr (fs/ntfs/inode.c::ntfs_setattr()) to refuse to
+	  change the uid, gid, and mode of an inode as we do not support NTFS
+	  ACLs yet.
+	- Remove BKL use from ntfs_setattr() syncing up with the rest of the
+	  kernel.
+	- Get rid of the ugly transparent union in fs/ntfs/dir.c::ntfs_readdir()
+	  and ntfs_filldir() as per suggestion from Al Viro.
+	- Change '\0' and L'\0' to simply 0 as per advice from Linus Torvalds.
+	- Update ->truncate (fs/ntfs/inode.c::ntfs_truncate()) to check if the
+	  inode size has changed and to only output an error if so.
+	- Rename fs/ntfs/attrib.h::attribute_value_length() to ntfs_attr_size().
+	- Add le{16,32,64} as well as sle{16,32,64} data types to
+	  fs/ntfs/types.h.
+	- Change ntfschar to be le16 instead of u16 in fs/ntfs/types.h.
+	- Add le versions of VCN, LCN, and LSN called leVCN, leLCN, and leLSN,
+	  respectively, to fs/ntfs/types.h.
+	- Update endianness conversion macros in fs/ntfs/endian.h to use the
+	  new types as appropriate.
+	- Do proper type casting when using sle64_to_cpup() in fs/ntfs/dir.c
+	  and index.c.
+	- Add leMFT_REF data type to fs/ntfs/layout.h.
+	- Update all NTFS header files with the new little endian data types.
+	  Affected files are fs/ntfs/layout.h, logfile.h, and time.h.
+	- Do proper type casting when using ntfs_is_*_recordp() in
+	  fs/ntfs/logfile.c, mft.c, and super.c. 
+	- Fix all the sparse bitwise warnings.  Had to change all the typedef
+	  enums storing little endian values to simple enums plus a typedef for
+	  the datatype to make sparse happy.
+	- Fix a bug found by the new sparse bitwise warnings where the default
+	  upcase table was defined as a pointer to wchar_t rather than ntfschar
+	  in fs/ntfs/ntfs.h and super.c.
+	- Change {const_,}cpu_to_le{16,32}(0) to just 0 as suggested by Al Viro.
+
+2.1.18 - Fix scheduling latencies at mount time as well as an endianness bug.
+
+	- Remove vol->nr_mft_records as it was pretty meaningless and optimize
+	  the calculation of total/free inodes as used by statfs().
+	- Fix scheduling latencies in ntfs_fill_super() by dropping the BKL
+	  because the code itself is using the ntfs_lock semaphore which
+	  provides safe locking.  (Ingo Molnar)
+	- Fix a potential bug in fs/ntfs/mft.c::map_extent_mft_record() that
+	  could occur in the future for when we start closing/freeing extent
+	  inodes if we don't set base_ni->ext.extent_ntfs_inos to NULL after
+	  we free it.
+	- Rename {find,lookup}_attr() to ntfs_attr_{find,lookup}() as well as
+	  find_external_attr() to ntfs_external_attr_find() to cleanup the
+	  namespace a bit and to be more consistent with libntfs.
+	- Rename {{re,}init,get,put}_attr_search_ctx() to
+	  ntfs_attr_{{re,}init,get,put}_search_ctx() as well as the type
+	  attr_search_context to ntfs_attr_search_ctx.
+	- Force use of ntfs_attr_find() in ntfs_attr_lookup() when searching
+	  for the attribute list attribute itself.
+	- Fix endianness bug in ntfs_external_attr_find().
+	- Change ntfs_{external_,}attr_find() to return 0 on success, -ENOENT
+	  if the attribute is not found, and -EIO on real error.  In the case
+	  of -ENOENT, the search context is updated to describe the attribute
+	  before which the attribute being searched for would need to be
+	  inserted if such an action were to be desired and in the case of
+	  ntfs_external_attr_find() the search context is also updated to
+	  indicate the attribute list entry before which the attribute list
+	  entry of the attribute being searched for would need to be inserted
+	  if such an action were to be desired.  Also make ntfs_find_attr()
+	  static and remove its prototype from attrib.h as it is not used
+	  anywhere other than attrib.c.  Update ntfs_attr_lookup() and all
+	  callers of ntfs_{external,}attr_{find,lookup}() for the new return
+	  values.
+	- Minor cleanup of fs/ntfs/inode.c::ntfs_init_locked_inode().
+
+2.1.17 - Fix bugs in mount time error code paths and other updates.
+
+	- Implement bitmap modification code (fs/ntfs/bitmap.[hc]).  This
+	  includes functions to set/clear a single bit or a run of bits.
+	- Add fs/ntfs/attrib.[hc]::ntfs_find_vcn() which returns the locked
+	  runlist element containing a particular vcn.  It also takes care of
+	  mapping any needed runlist fragments.
+	- Implement cluster (de-)allocation code (fs/ntfs/lcnalloc.[hc]).
+	- Load attribute definition table from $AttrDef at mount time.
+	- Fix bugs in mount time error code paths involving (de)allocation of
+	  the default and volume upcase tables.
+	- Remove ntfs_nr_mounts as it is no longer used.
+
+2.1.16 - Implement access time updates, file sync, async io, and read/writev.
+
+	- Add support for readv/writev and aio_read/aio_write (fs/ntfs/file.c).
+	  This is done by setting the appropriate file operations pointers to
+	  the generic helper functions provided by mm/filemap.c.
+	- Implement fsync, fdatasync, and msync both for files (fs/ntfs/file.c)
+	  and directories (fs/ntfs/dir.c).
+	- Add support for {a,m,c}time updates to inode.c::ntfs_write_inode().
+	  Note, except for the root directory and any other system files opened
+	  by the user, the system files will not have their access times
+	  updated as they are only accessed at the inode level an hence the
+	  file level functions which cause the times to be updated are never
+	  invoked.
+
 2.1.15 - Invalidate quotas when (re)mounting read-write.
 
 	- Add new element itype.index.collation_rule to the ntfs inode
@@ -434,7 +537,7 @@
 	  cannot set any write related options when the driver is compiled
 	  read-only.
 	- Optimize block resolution in fs/ntfs/aops.c::ntfs_read_block() to
-	  cache the current run list element. This should improve performance
+	  cache the current runlist element. This should improve performance
 	  when reading very large and/or very fragmented data.
 
 2.0.16 - Convert access to $MFT/$BITMAP to attribute inode API.
@@ -482,9 +585,9 @@
 	- Change fs/ntfs/super.c::ntfs_statfs() to not rely on BKL by moving
 	  the locking out of super.c::get_nr_free_mft_records() and taking and
 	  dropping the mftbmp_lock rw_semaphore in ntfs_statfs() itself.
-	- Bring attribute run list merging code (fs/ntfs/attrib.c) in sync with
+	- Bring attribute runlist merging code (fs/ntfs/attrib.c) in sync with
 	  current userspace ntfs library code. This means that if a merge
-	  fails the original run lists are always left unmodified instead of
+	  fails the original runlists are always left unmodified instead of
 	  being silently corrupted.
 	- Misc typo fixes.
 
@@ -676,7 +779,7 @@
 	  appropriately.
 	- Update to 2.5.9 kernel (preserving backwards compatibility) by
 	  replacing all occurences of page->buffers with page_buffers(page).
-	- Fix minor bugs in run list merging, also minor cleanup.
+	- Fix minor bugs in runlist merging, also minor cleanup.
 	- Updates to bootsector layout and mft mirror contents descriptions.
 	- Small bug fix in error detection in unistr.c and some cleanups.
 	- Grow name buffer allocations in unistr.c in aligned mutlipled of 64
@@ -699,12 +802,12 @@
 	  initialized_size vs data_size (i.e. i_size). Done are
 	  mft.c::ntfs_mft_readpage(), aops.c::end_buffer_read_index_async(),
 	  and attrib.c::load_attribute_list().
-	- Lock the run list in attrib.c::load_attribute_list() while using it.
+	- Lock the runlist in attrib.c::load_attribute_list() while using it.
 	- Fix memory leak in ntfs_file_read_compressed_block() and generally
 	  clean up compress.c a little, removing some uncommented/unused debug
 	  code.
 	- Tidy up dir.c a little bit.
-	- Don't bother getting the run list in inode.c::ntfs_read_inode().
+	- Don't bother getting the runlist in inode.c::ntfs_read_inode().
 	- Merge mft.c::ntfs_mft_readpage() and aops.c::ntfs_index_readpage()
 	  creating aops.c::ntfs_mst_readpage(), improving the handling of
 	  holes and overflow in the process and implementing the correct
@@ -734,7 +837,7 @@
 	- Apply kludge in ntfs_read_inode(), setting i_nlink to 1 for
 	  directories. Without this the "find" utility gets very upset which is
 	  fair enough as Linux/Unix do not support directory hard links.
-	- Further run list merging work. (Richard Russon)
+	- Further runlist merging work. (Richard Russon)
 	- Backwards compatibility for gcc-2.95. (Richard Russon)
 	- Update to kernel 2.5.5-pre1 and rediff the now tiny patch.
 	- Convert to new file system declaration using ->ntfs_get_sb() and
@@ -789,7 +892,7 @@
 	  which is then referenced but not copied.
 	- Rename run_list structure to run_list_element and create a new
 	  run_list structure containing a pointer to a run_list_element
-	  structure and a read/write semaphore. Adapt all users of run lists
+	  structure and a read/write semaphore. Adapt all users of runlists
 	  to new scheme and take and release the lock as needed. This fixes a
 	  nasty race as the run_list changes even when inodes are locked for
 	  reading and even when the inode isn't locked at all, so we really
@@ -820,7 +923,7 @@
 	- Cleanup mft.c and it's debug/error output in particular. Fix a minor
 	  bug in mapping of extent inodes. Update all the comments to fit all
 	  the recent code changes.
-	- Modify vcn_to_lcn() to cope with entirely unmapped run lists.
+	- Modify vcn_to_lcn() to cope with entirely unmapped runlists.
 	- Cleanups in compress.c, mostly comments and folding help.
 	- Implement attrib.c::map_run_list() as a generic helper.
 	- Make compress.c::ntfs_file_read_compressed_block() use map_run_list()
@@ -846,11 +949,11 @@
 	  pass in the upcase table and its length. These can be gotten from
 	  ctx->ntfs_ino->vol->upcase{_len}. Update all callers.
 	- Cleanups in attrib.c.
-	- Implement merging of run lists, attrib.c::merge_run_lists() and its
+	- Implement merging of runlists, attrib.c::merge_run_lists() and its
 	  helpers. (Richard Russon)
-	- Attribute lists part 2, attribute extents and multi part run lists:
+	- Attribute lists part 2, attribute extents and multi part runlists:
 	  enable proper support for LCN_RL_NOT_MAPPED and automatic mapping of
-	  further run list parts via attrib.c::map_run_list().
+	  further runlist parts via attrib.c::map_run_list().
 	- Tiny endianness bug fix in decompress_mapping_pairs().
 
 tng-0.0.6 - Encrypted directories, bug fixes, cleanups, debugging enhancements.
@@ -882,7 +985,7 @@
 	  support dollar signs in the names of variables/constants. Attribute
 	  types now start with AT_ instead of $ and $I30 is now just I30.
 	- Cleanup ntfs_lookup() and add consistency check of sequence numbers.
-	- Load complete run list for $MFT/$BITMAP during mount and cleanup
+	- Load complete runlist for $MFT/$BITMAP during mount and cleanup
 	  access functions. This means we now cope with $MFT/$BITMAP being
 	  spread accross several mft records.
 	- Disable modification of mft_zone_multiplier on remount. We can always
@@ -915,11 +1018,11 @@
 	  parameter list. Pass either READ or WRITE to this, each has the
 	  obvious meaning.
 	- General cleanups to allow for easier folding in vi.
-	- attrib.c::decompress_mapping_pairs() now accepts the old run list
+	- attrib.c::decompress_mapping_pairs() now accepts the old runlist
 	  argument, and invokes attrib.c::merge_run_lists() to merge the old
-	  and the new run lists.
+	  and the new runlists.
 	- Removed attrib.c::find_first_attr().
-	- Implemented loading of attribute list and complete run list for $MFT.
+	- Implemented loading of attribute list and complete runlist for $MFT.
 	  This means we now cope with $MFT being spread across several mft
 	  records.
 	- Adapt to 2.5.2-pre9 and the changed create_empty_buffers() syntax.
@@ -957,7 +1060,7 @@
 tng-0.0.3 - Cleanups, enhancements, bug fixes.
 
 	- Work on attrib.c::decompress_mapping_pairs() to detect base extents
-	  and setup the run list appropriately using knowledge provided by the
+	  and setup the runlist appropriately using knowledge provided by the
 	  sizes in the base attribute record.
 	- Balance the get_/put_attr_search_ctx() calls so we don't leak memory
 	  any more.
diff -Nru a/fs/ntfs/Makefile b/fs/ntfs/Makefile
--- a/fs/ntfs/Makefile	2004-10-18 14:56:32 -07:00
+++ b/fs/ntfs/Makefile	2004-10-18 14:56:32 -07:00
@@ -6,7 +6,7 @@
 	     index.o inode.o mft.o mst.o namei.o super.o sysctl.o unistr.o \
 	     upcase.o
 
-EXTRA_CFLAGS = -DNTFS_VERSION=\"2.1.15\"
+EXTRA_CFLAGS = -DNTFS_VERSION=\"2.1.20\"
 
 ifeq ($(CONFIG_NTFS_DEBUG),y)
 EXTRA_CFLAGS += -DDEBUG
@@ -15,5 +15,5 @@
 ifeq ($(CONFIG_NTFS_RW),y)
 EXTRA_CFLAGS += -DNTFS_RW
 
-ntfs-objs += logfile.o quota.o
+ntfs-objs += bitmap.o lcnalloc.o logfile.o quota.o
 endif
diff -Nru a/fs/ntfs/aops.c b/fs/ntfs/aops.c
--- a/fs/ntfs/aops.c	2004-10-18 14:56:49 -07:00
+++ b/fs/ntfs/aops.c	2004-10-18 14:56:49 -07:00
@@ -170,7 +170,7 @@
 	LCN lcn;
 	ntfs_inode *ni;
 	ntfs_volume *vol;
-	run_list_element *rl;
+	runlist_element *rl;
 	struct buffer_head *bh, *head, *arr[MAX_BUF_PER_PAGE];
 	sector_t iblock, lblock, zblock;
 	unsigned int blocksize, vcn_ofs;
@@ -196,8 +196,8 @@
 	zblock = (ni->initialized_size + blocksize - 1) >> blocksize_bits;
 
 #ifdef DEBUG
-	if (unlikely(!ni->run_list.rl && !ni->mft_no && !NInoAttr(ni)))
-		panic("NTFS: $MFT/$DATA run list has been unmapped! This is a "
+	if (unlikely(!ni->runlist.rl && !ni->mft_no && !NInoAttr(ni)))
+		panic("NTFS: $MFT/$DATA runlist has been unmapped! This is a "
 				"very serious bug! Cannot continue...");
 #endif
 
@@ -225,14 +225,14 @@
 					vol->cluster_size_mask;
 			if (!rl) {
 lock_retry_remap:
-				down_read(&ni->run_list.lock);
-				rl = ni->run_list.rl;
+				down_read(&ni->runlist.lock);
+				rl = ni->runlist.rl;
 			}
 			if (likely(rl != NULL)) {
 				/* Seek to element containing target vcn. */
 				while (rl->length && rl[1].vcn <= vcn)
 					rl++;
-				lcn = vcn_to_lcn(rl, vcn);
+				lcn = ntfs_vcn_to_lcn(rl, vcn);
 			} else
 				lcn = (LCN)LCN_RL_NOT_MAPPED;
 			/* Successful remap. */
@@ -252,29 +252,29 @@
 			/* It is a hole, need to zero it. */
 			if (lcn == LCN_HOLE)
 				goto handle_hole;
-			/* If first try and run list unmapped, map and retry. */
+			/* If first try and runlist unmapped, map and retry. */
 			if (!is_retry && lcn == LCN_RL_NOT_MAPPED) {
 				is_retry = TRUE;
 				/*
-				 * Attempt to map run list, dropping lock for
+				 * Attempt to map runlist, dropping lock for
 				 * the duration.
 				 */
-				up_read(&ni->run_list.lock);
-				if (!map_run_list(ni, vcn))
+				up_read(&ni->runlist.lock);
+				if (!ntfs_map_runlist(ni, vcn))
 					goto lock_retry_remap;
 				rl = NULL;
 			}
 			/* Hard error, zero out region. */
 			SetPageError(page);
-			ntfs_error(vol->sb, "vcn_to_lcn(vcn = 0x%llx) failed "
-					"with error code 0x%llx%s.",
+			ntfs_error(vol->sb, "ntfs_vcn_to_lcn(vcn = 0x%llx) "
+					"failed with error code 0x%llx%s.",
 					(unsigned long long)vcn,
 					(unsigned long long)-lcn,
 					is_retry ? " even after retrying" : "");
 			// FIXME: Depending on vol->on_errors, do something.
 		}
 		/*
-		 * Either iblock was outside lblock limits or vcn_to_lcn()
+		 * Either iblock was outside lblock limits or ntfs_vcn_to_lcn()
 		 * returned error. Just zero that portion of the page and set
 		 * the buffer uptodate.
 		 */
@@ -291,7 +291,7 @@
 
 	/* Release the lock if we took it. */
 	if (rl)
-		up_read(&ni->run_list.lock);
+		up_read(&ni->runlist.lock);
 
 	/* Check we have at least one buffer ready for i/o. */
 	if (nr) {
@@ -348,7 +348,7 @@
 	s64 attr_pos;
 	ntfs_inode *ni, *base_ni;
 	u8 *kaddr;
-	attr_search_context *ctx;
+	ntfs_attr_search_ctx *ctx;
 	MFT_RECORD *mrec;
 	u32 attr_len;
 	int err = 0;
@@ -393,20 +393,19 @@
 
 	/* Map, pin, and lock the mft record. */
 	mrec = map_mft_record(base_ni);
-	if (unlikely(IS_ERR(mrec))) {
+	if (IS_ERR(mrec)) {
 		err = PTR_ERR(mrec);
 		goto err_out;
 	}
-	ctx = get_attr_search_ctx(base_ni, mrec);
+	ctx = ntfs_attr_get_search_ctx(base_ni, mrec);
 	if (unlikely(!ctx)) {
 		err = -ENOMEM;
 		goto unm_err_out;
 	}
-	if (unlikely(!lookup_attr(ni->type, ni->name, ni->name_len,
-			CASE_SENSITIVE, 0, NULL, 0, ctx))) {
-		err = -ENOENT;
+	err = ntfs_attr_lookup(ni->type, ni->name, ni->name_len,
+			CASE_SENSITIVE, 0, NULL, 0, ctx);
+	if (unlikely(err))
 		goto put_unm_err_out;
-	}
 
 	/* Starting position of the page within the attribute value. */
 	attr_pos = page->index << PAGE_CACHE_SHIFT;
@@ -433,7 +432,7 @@
 
 	SetPageUptodate(page);
 put_unm_err_out:
-	put_attr_search_ctx(ctx);
+	ntfs_attr_put_search_ctx(ctx);
 unm_err_out:
 	unmap_mft_record(base_ni);
 err_out:
@@ -473,7 +472,7 @@
 	struct inode *vi;
 	ntfs_inode *ni;
 	ntfs_volume *vol;
-	run_list_element *rl;
+	runlist_element *rl;
 	struct buffer_head *bh, *head;
 	unsigned int blocksize, vcn_ofs;
 	int err;
@@ -631,14 +630,14 @@
 				vol->cluster_size_mask;
 		if (!rl) {
 lock_retry_remap:
-			down_read(&ni->run_list.lock);
-			rl = ni->run_list.rl;
+			down_read(&ni->runlist.lock);
+			rl = ni->runlist.rl;
 		}
 		if (likely(rl != NULL)) {
 			/* Seek to element containing target vcn. */
 			while (rl->length && rl[1].vcn <= vcn)
 				rl++;
-			lcn = vcn_to_lcn(rl, vcn);
+			lcn = ntfs_vcn_to_lcn(rl, vcn);
 		} else
 			lcn = (LCN)LCN_RL_NOT_MAPPED;
 		/* Successful remap. */
@@ -659,22 +658,22 @@
 			err = -EOPNOTSUPP;
 			break;
 		}
-		/* If first try and run list unmapped, map and retry. */
+		/* If first try and runlist unmapped, map and retry. */
 		if (!is_retry && lcn == LCN_RL_NOT_MAPPED) {
 			is_retry = TRUE;
 			/*
-			 * Attempt to map run list, dropping lock for
+			 * Attempt to map runlist, dropping lock for
 			 * the duration.
 			 */
-			up_read(&ni->run_list.lock);
-			err = map_run_list(ni, vcn);
+			up_read(&ni->runlist.lock);
+			err = ntfs_map_runlist(ni, vcn);
 			if (likely(!err))
 				goto lock_retry_remap;
 			rl = NULL;
 		}
 		/* Failed to map the buffer, even after retrying. */
 		bh->b_blocknr = -1UL;
-		ntfs_error(vol->sb, "vcn_to_lcn(vcn = 0x%llx) failed "
+		ntfs_error(vol->sb, "ntfs_vcn_to_lcn(vcn = 0x%llx) failed "
 				"with error code 0x%llx%s.",
 				(unsigned long long)vcn,
 				(unsigned long long)-lcn,
@@ -687,7 +686,7 @@
 
 	/* Release the lock if we took it. */
 	if (rl)
-		up_read(&ni->run_list.lock);
+		up_read(&ni->runlist.lock);
 
 	/* For the error case, need to reset bh to the beginning. */
 	bh = head;
@@ -1030,7 +1029,7 @@
 	struct inode *vi;
 	ntfs_inode *ni, *base_ni;
 	char *kaddr;
-	attr_search_context *ctx;
+	ntfs_attr_search_ctx *ctx;
 	MFT_RECORD *m;
 	u32 attr_len, bytes;
 	int err;
@@ -1111,22 +1110,21 @@
 
 	/* Map, pin, and lock the mft record. */
 	m = map_mft_record(base_ni);
-	if (unlikely(IS_ERR(m))) {
+	if (IS_ERR(m)) {
 		err = PTR_ERR(m);
 		m = NULL;
 		ctx = NULL;
 		goto err_out;
 	}
-	ctx = get_attr_search_ctx(base_ni, m);
+	ctx = ntfs_attr_get_search_ctx(base_ni, m);
 	if (unlikely(!ctx)) {
 		err = -ENOMEM;
 		goto err_out;
 	}
-	if (unlikely(!lookup_attr(ni->type, ni->name, ni->name_len,
-			CASE_SENSITIVE, 0, NULL, 0, ctx))) {
-		err = -ENOENT;
+	err = ntfs_attr_lookup(ni->type, ni->name, ni->name_len,
+			CASE_SENSITIVE, 0, NULL, 0, ctx);
+	if (unlikely(err))
 		goto err_out;
-	}
 
 	/* Starting position of the page within the attribute value. */
 	attr_pos = page->index << PAGE_CACHE_SHIFT;
@@ -1201,7 +1199,7 @@
 	/* Mark the mft record dirty, so it gets written back. */
 	mark_mft_record_dirty(ctx->ntfs_ino);
 
-	put_attr_search_ctx(ctx);
+	ntfs_attr_put_search_ctx(ctx);
 	unmap_mft_record(base_ni);
 	return 0;
 err_out:
@@ -1221,7 +1219,7 @@
 	}
 	unlock_page(page);
 	if (ctx)
-		put_attr_search_ctx(ctx);
+		ntfs_attr_put_search_ctx(ctx);
 	if (m)
 		unmap_mft_record(base_ni);
 	return err;
@@ -1240,7 +1238,7 @@
 	struct inode *vi;
 	ntfs_inode *ni;
 	ntfs_volume *vol;
-	run_list_element *rl;
+	runlist_element *rl;
 	struct buffer_head *bh, *head, *wait[2], **wait_bh = wait;
 	unsigned int vcn_ofs, block_start, block_end, blocksize;
 	int err;
@@ -1397,14 +1395,14 @@
 			is_retry = FALSE;
 			if (!rl) {
 lock_retry_remap:
-				down_read(&ni->run_list.lock);
-				rl = ni->run_list.rl;
+				down_read(&ni->runlist.lock);
+				rl = ni->runlist.rl;
 			}
 			if (likely(rl != NULL)) {
 				/* Seek to element containing target vcn. */
 				while (rl->length && rl[1].vcn <= vcn)
 					rl++;
-				lcn = vcn_to_lcn(rl, vcn);
+				lcn = ntfs_vcn_to_lcn(rl, vcn);
 			} else
 				lcn = (LCN)LCN_RL_NOT_MAPPED;
 			if (unlikely(lcn < 0)) {
@@ -1439,11 +1437,11 @@
 						lcn == LCN_RL_NOT_MAPPED) {
 					is_retry = TRUE;
 					/*
-					 * Attempt to map run list, dropping
+					 * Attempt to map runlist, dropping
 					 * lock for the duration.
 					 */
-					up_read(&ni->run_list.lock);
-					err = map_run_list(ni, vcn);
+					up_read(&ni->runlist.lock);
+					err = ntfs_map_runlist(ni, vcn);
 					if (likely(!err))
 						goto lock_retry_remap;
 					rl = NULL;
@@ -1453,9 +1451,9 @@
 				 * retrying.
 				 */
 				bh->b_blocknr = -1UL;
-				ntfs_error(vol->sb, "vcn_to_lcn(vcn = 0x%llx) "
-						"failed with error code "
-						"0x%llx%s.",
+				ntfs_error(vol->sb, "ntfs_vcn_to_lcn(vcn = "
+						"0x%llx) failed with error "
+						"code 0x%llx%s.",
 						(unsigned long long)vcn,
 						(unsigned long long)-lcn,
 						is_retry ? " even after "
@@ -1530,7 +1528,7 @@
 
 	/* Release the lock if we took it. */
 	if (rl) {
-		up_read(&ni->run_list.lock);
+		up_read(&ni->runlist.lock);
 		rl = NULL;
 	}
 
@@ -1576,7 +1574,7 @@
 	if (is_retry)
 		flush_dcache_page(page);
 	if (rl)
-		up_read(&ni->run_list.lock);
+		up_read(&ni->runlist.lock);
 	return err;
 }
 
@@ -1683,9 +1681,9 @@
 	 * We thus defer the uptodate bringing of the page region outside the
 	 * region written to to ntfs_commit_write(). The reason for doing this
 	 * is that we save one round of:
-	 *	map_mft_record(), get_attr_search_ctx(), lookup_attr(),
-	 *	kmap_atomic(), kunmap_atomic(), put_attr_search_ctx(),
-	 *	unmap_mft_record().
+	 *	map_mft_record(), ntfs_attr_get_search_ctx(),
+	 *	ntfs_attr_lookup(), kmap_atomic(), kunmap_atomic(),
+	 *	ntfs_attr_put_search_ctx(), unmap_mft_record().
 	 * Which is obviously a very worthwhile save.
 	 *
 	 * Thus we just return success now...
@@ -1804,7 +1802,7 @@
 	struct inode *vi;
 	ntfs_inode *ni, *base_ni;
 	char *kaddr, *kattr;
-	attr_search_context *ctx;
+	ntfs_attr_search_ctx *ctx;
 	MFT_RECORD *m;
 	u32 attr_len, bytes;
 	int err;
@@ -1885,22 +1883,21 @@
 
 	/* Map, pin, and lock the mft record. */
 	m = map_mft_record(base_ni);
-	if (unlikely(IS_ERR(m))) {
+	if (IS_ERR(m)) {
 		err = PTR_ERR(m);
 		m = NULL;
 		ctx = NULL;
 		goto err_out;
 	}
-	ctx = get_attr_search_ctx(base_ni, m);
+	ctx = ntfs_attr_get_search_ctx(base_ni, m);
 	if (unlikely(!ctx)) {
 		err = -ENOMEM;
 		goto err_out;
 	}
-	if (unlikely(!lookup_attr(ni->type, ni->name, ni->name_len,
-			CASE_SENSITIVE, 0, NULL, 0, ctx))) {
-		err = -ENOENT;
+	err = ntfs_attr_lookup(ni->type, ni->name, ni->name_len,
+			CASE_SENSITIVE, 0, NULL, 0, ctx);
+	if (unlikely(err))
 		goto err_out;
-	}
 
 	/* Starting position of the page within the attribute value. */
 	attr_pos = page->index << PAGE_CACHE_SHIFT;
@@ -1966,7 +1963,7 @@
 	/* Mark the mft record dirty, so it gets written back. */
 	mark_mft_record_dirty(ctx->ntfs_ino);
 
-	put_attr_search_ctx(ctx);
+	ntfs_attr_put_search_ctx(ctx);
 	unmap_mft_record(base_ni);
 	ntfs_debug("Done.");
 	return 0;
@@ -1993,7 +1990,7 @@
 		SetPageError(page);
 	}
 	if (ctx)
-		put_attr_search_ctx(ctx);
+		ntfs_attr_put_search_ctx(ctx);
 	if (m)
 		unmap_mft_record(base_ni);
 	return err;
diff -Nru a/fs/ntfs/attrib.c b/fs/ntfs/attrib.c
--- a/fs/ntfs/attrib.c	2004-10-18 14:57:05 -07:00
+++ b/fs/ntfs/attrib.c	2004-10-18 14:57:05 -07:00
@@ -27,11 +27,11 @@
 /* Temporary helper functions -- might become macros */
 
 /**
- * ntfs_rl_mm - run_list memmove
+ * ntfs_rl_mm - runlist memmove
  *
- * It is up to the caller to serialize access to the run list @base.
+ * It is up to the caller to serialize access to the runlist @base.
  */
-static inline void ntfs_rl_mm(run_list_element *base, int dst, int src,
+static inline void ntfs_rl_mm(runlist_element *base, int dst, int src,
 		int size)
 {
 	if (likely((dst != src) && (size > 0)))
@@ -39,42 +39,42 @@
 }
 
 /**
- * ntfs_rl_mc - run_list memory copy
+ * ntfs_rl_mc - runlist memory copy
  *
- * It is up to the caller to serialize access to the run lists @dstbase and
+ * It is up to the caller to serialize access to the runlists @dstbase and
  * @srcbase.
  */
-static inline void ntfs_rl_mc(run_list_element *dstbase, int dst,
-		run_list_element *srcbase, int src, int size)
+static inline void ntfs_rl_mc(runlist_element *dstbase, int dst,
+		runlist_element *srcbase, int src, int size)
 {
 	if (likely(size > 0))
 		memcpy(dstbase + dst, srcbase + src, size * sizeof(*dstbase));
 }
 
 /**
- * ntfs_rl_realloc - Reallocate memory for run_lists
- * @rl:		original run list
- * @old_size:	number of run list elements in the original run list @rl
- * @new_size:	number of run list elements we need space for
+ * ntfs_rl_realloc - Reallocate memory for runlists
+ * @rl:		original runlist
+ * @old_size:	number of runlist elements in the original runlist @rl
+ * @new_size:	number of runlist elements we need space for
  *
- * As the run_lists grow, more memory will be required.  To prevent the
+ * As the runlists grow, more memory will be required.  To prevent the
  * kernel having to allocate and reallocate large numbers of small bits of
  * memory, this function returns and entire page of memory.
  *
- * It is up to the caller to serialize access to the run list @rl.
+ * It is up to the caller to serialize access to the runlist @rl.
  *
  * N.B.  If the new allocation doesn't require a different number of pages in
  *       memory, the function will return the original pointer.
  *
  * On success, return a pointer to the newly allocated, or recycled, memory.
  * On error, return -errno. The following error codes are defined:
- *	-ENOMEM	- Not enough memory to allocate run list array.
+ *	-ENOMEM	- Not enough memory to allocate runlist array.
  *	-EINVAL	- Invalid parameters were passed in.
  */
-static inline run_list_element *ntfs_rl_realloc(run_list_element *rl,
+static inline runlist_element *ntfs_rl_realloc(runlist_element *rl,
 		int old_size, int new_size)
 {
-	run_list_element *new_rl;
+	runlist_element *new_rl;
 
 	old_size = PAGE_ALIGN(old_size * sizeof(*rl));
 	new_size = PAGE_ALIGN(new_size * sizeof(*rl));
@@ -95,20 +95,20 @@
 }
 
 /**
- * ntfs_are_rl_mergeable - test if two run lists can be joined together
- * @dst:	original run list
- * @src:	new run list to test for mergeability with @dst
+ * ntfs_are_rl_mergeable - test if two runlists can be joined together
+ * @dst:	original runlist
+ * @src:	new runlist to test for mergeability with @dst
  *
- * Test if two run lists can be joined together. For this, their VCNs and LCNs
+ * Test if two runlists can be joined together. For this, their VCNs and LCNs
  * must be adjacent.
  *
- * It is up to the caller to serialize access to the run lists @dst and @src.
+ * It is up to the caller to serialize access to the runlists @dst and @src.
  *
- * Return: TRUE   Success, the run lists can be merged.
- *	   FALSE  Failure, the run lists cannot be merged.
+ * Return: TRUE   Success, the runlists can be merged.
+ *	   FALSE  Failure, the runlists cannot be merged.
  */
-static inline BOOL ntfs_are_rl_mergeable(run_list_element *dst,
-		run_list_element *src)
+static inline BOOL ntfs_are_rl_mergeable(runlist_element *dst,
+		runlist_element *src)
 {
 	BUG_ON(!dst);
 	BUG_ON(!src);
@@ -124,37 +124,37 @@
 }
 
 /**
- * __ntfs_rl_merge - merge two run lists without testing if they can be merged
- * @dst:	original, destination run list
- * @src:	new run list to merge with @dst
+ * __ntfs_rl_merge - merge two runlists without testing if they can be merged
+ * @dst:	original, destination runlist
+ * @src:	new runlist to merge with @dst
  *
- * Merge the two run lists, writing into the destination run list @dst. The
- * caller must make sure the run lists can be merged or this will corrupt the
- * destination run list.
+ * Merge the two runlists, writing into the destination runlist @dst. The
+ * caller must make sure the runlists can be merged or this will corrupt the
+ * destination runlist.
  *
- * It is up to the caller to serialize access to the run lists @dst and @src.
+ * It is up to the caller to serialize access to the runlists @dst and @src.
  */
-static inline void __ntfs_rl_merge(run_list_element *dst, run_list_element *src)
+static inline void __ntfs_rl_merge(runlist_element *dst, runlist_element *src)
 {
 	dst->length += src->length;
 }
 
 /**
- * ntfs_rl_merge - test if two run lists can be joined together and merge them
- * @dst:	original, destination run list
- * @src:	new run list to merge with @dst
+ * ntfs_rl_merge - test if two runlists can be joined together and merge them
+ * @dst:	original, destination runlist
+ * @src:	new runlist to merge with @dst
  *
- * Test if two run lists can be joined together. For this, their VCNs and LCNs
+ * Test if two runlists can be joined together. For this, their VCNs and LCNs
  * must be adjacent. If they can be merged, perform the merge, writing into
- * the destination run list @dst.
+ * the destination runlist @dst.
  *
- * It is up to the caller to serialize access to the run lists @dst and @src.
+ * It is up to the caller to serialize access to the runlists @dst and @src.
  *
- * Return: TRUE   Success, the run lists have been merged.
- *	   FALSE  Failure, the run lists cannot be merged and have not been
+ * Return: TRUE   Success, the runlists have been merged.
+ *	   FALSE  Failure, the runlists cannot be merged and have not been
  *		  modified.
  */
-static inline BOOL ntfs_rl_merge(run_list_element *dst, run_list_element *src)
+static inline BOOL ntfs_rl_merge(runlist_element *dst, runlist_element *src)
 {
 	BOOL merge = ntfs_are_rl_mergeable(dst, src);
 
@@ -164,31 +164,31 @@
 }
 
 /**
- * ntfs_rl_append - append a run list after a given element
- * @dst:	original run list to be worked on
+ * ntfs_rl_append - append a runlist after a given element
+ * @dst:	original runlist to be worked on
  * @dsize:	number of elements in @dst (including end marker)
- * @src:	run list to be inserted into @dst
+ * @src:	runlist to be inserted into @dst
  * @ssize:	number of elements in @src (excluding end marker)
- * @loc:	append the new run list @src after this element in @dst
+ * @loc:	append the new runlist @src after this element in @dst
  *
- * Append the run list @src after element @loc in @dst.  Merge the right end of
- * the new run list, if necessary. Adjust the size of the hole before the
- * appended run list.
+ * Append the runlist @src after element @loc in @dst.  Merge the right end of
+ * the new runlist, if necessary. Adjust the size of the hole before the
+ * appended runlist.
  *
- * It is up to the caller to serialize access to the run lists @dst and @src.
+ * It is up to the caller to serialize access to the runlists @dst and @src.
  *
- * On success, return a pointer to the new, combined, run list. Note, both
- * run lists @dst and @src are deallocated before returning so you cannot use
- * the pointers for anything any more. (Strictly speaking the returned run list
+ * On success, return a pointer to the new, combined, runlist. Note, both
+ * runlists @dst and @src are deallocated before returning so you cannot use
+ * the pointers for anything any more. (Strictly speaking the returned runlist
  * may be the same as @dst but this is irrelevant.)
  *
- * On error, return -errno. Both run lists are left unmodified. The following
+ * On error, return -errno. Both runlists are left unmodified. The following
  * error codes are defined:
- *	-ENOMEM	- Not enough memory to allocate run list array.
+ *	-ENOMEM	- Not enough memory to allocate runlist array.
  *	-EINVAL	- Invalid parameters were passed in.
  */
-static inline run_list_element *ntfs_rl_append(run_list_element *dst,
-		int dsize, run_list_element *src, int ssize, int loc)
+static inline runlist_element *ntfs_rl_append(runlist_element *dst,
+		int dsize, runlist_element *src, int ssize, int loc)
 {
 	BOOL right;
 	int magic;
@@ -205,7 +205,7 @@
 		return dst;
 	/*
 	 * We are guaranteed to succeed from here so can start modifying the
-	 * original run lists.
+	 * original runlists.
 	 */
 
 	/* First, merge the right hand end, if necessary. */
@@ -229,31 +229,31 @@
 }
 
 /**
- * ntfs_rl_insert - insert a run list into another
- * @dst:	original run list to be worked on
+ * ntfs_rl_insert - insert a runlist into another
+ * @dst:	original runlist to be worked on
  * @dsize:	number of elements in @dst (including end marker)
- * @src:	new run list to be inserted
+ * @src:	new runlist to be inserted
  * @ssize:	number of elements in @src (excluding end marker)
- * @loc:	insert the new run list @src before this element in @dst
+ * @loc:	insert the new runlist @src before this element in @dst
  *
- * Insert the run list @src before element @loc in the run list @dst. Merge the
- * left end of the new run list, if necessary. Adjust the size of the hole
- * after the inserted run list.
+ * Insert the runlist @src before element @loc in the runlist @dst. Merge the
+ * left end of the new runlist, if necessary. Adjust the size of the hole
+ * after the inserted runlist.
  *
- * It is up to the caller to serialize access to the run lists @dst and @src.
+ * It is up to the caller to serialize access to the runlists @dst and @src.
  *
- * On success, return a pointer to the new, combined, run list. Note, both
- * run lists @dst and @src are deallocated before returning so you cannot use
- * the pointers for anything any more. (Strictly speaking the returned run list
+ * On success, return a pointer to the new, combined, runlist. Note, both
+ * runlists @dst and @src are deallocated before returning so you cannot use
+ * the pointers for anything any more. (Strictly speaking the returned runlist
  * may be the same as @dst but this is irrelevant.)
  *
- * On error, return -errno. Both run lists are left unmodified. The following
+ * On error, return -errno. Both runlists are left unmodified. The following
  * error codes are defined:
- *	-ENOMEM	- Not enough memory to allocate run list array.
+ *	-ENOMEM	- Not enough memory to allocate runlist array.
  *	-EINVAL	- Invalid parameters were passed in.
  */
-static inline run_list_element *ntfs_rl_insert(run_list_element *dst,
-		int dsize, run_list_element *src, int ssize, int loc)
+static inline runlist_element *ntfs_rl_insert(runlist_element *dst,
+		int dsize, runlist_element *src, int ssize, int loc)
 {
 	BOOL left = FALSE;
 	BOOL disc = FALSE;	/* Discontinuity */
@@ -290,7 +290,7 @@
 		return dst;
 	/*
 	 * We are guaranteed to succeed from here so can start modifying the
-	 * original run list.
+	 * original runlist.
 	 */
 
 	if (left)
@@ -336,30 +336,30 @@
 }
 
 /**
- * ntfs_rl_replace - overwrite a run_list element with another run list
- * @dst:	original run list to be worked on
+ * ntfs_rl_replace - overwrite a runlist element with another runlist
+ * @dst:	original runlist to be worked on
  * @dsize:	number of elements in @dst (including end marker)
- * @src:	new run list to be inserted
+ * @src:	new runlist to be inserted
  * @ssize:	number of elements in @src (excluding end marker)
- * @loc:	index in run list @dst to overwrite with @src
+ * @loc:	index in runlist @dst to overwrite with @src
  *
- * Replace the run list element @dst at @loc with @src. Merge the left and
- * right ends of the inserted run list, if necessary.
+ * Replace the runlist element @dst at @loc with @src. Merge the left and
+ * right ends of the inserted runlist, if necessary.
  *
- * It is up to the caller to serialize access to the run lists @dst and @src.
+ * It is up to the caller to serialize access to the runlists @dst and @src.
  *
- * On success, return a pointer to the new, combined, run list. Note, both
- * run lists @dst and @src are deallocated before returning so you cannot use
- * the pointers for anything any more. (Strictly speaking the returned run list
+ * On success, return a pointer to the new, combined, runlist. Note, both
+ * runlists @dst and @src are deallocated before returning so you cannot use
+ * the pointers for anything any more. (Strictly speaking the returned runlist
  * may be the same as @dst but this is irrelevant.)
  *
- * On error, return -errno. Both run lists are left unmodified. The following
+ * On error, return -errno. Both runlists are left unmodified. The following
  * error codes are defined:
- *	-ENOMEM	- Not enough memory to allocate run list array.
+ *	-ENOMEM	- Not enough memory to allocate runlist array.
  *	-EINVAL	- Invalid parameters were passed in.
  */
-static inline run_list_element *ntfs_rl_replace(run_list_element *dst,
-		int dsize, run_list_element *src, int ssize, int loc)
+static inline runlist_element *ntfs_rl_replace(runlist_element *dst,
+		int dsize, runlist_element *src, int ssize, int loc)
 {
 	BOOL left = FALSE;
 	BOOL right;
@@ -380,7 +380,7 @@
 		return dst;
 	/*
 	 * We are guaranteed to succeed from here so can start modifying the
-	 * original run lists.
+	 * original runlists.
 	 */
 	if (right)
 		__ntfs_rl_merge(src + ssize - 1, dst + loc + 1);
@@ -401,31 +401,31 @@
 }
 
 /**
- * ntfs_rl_split - insert a run list into the centre of a hole
- * @dst:	original run list to be worked on
+ * ntfs_rl_split - insert a runlist into the centre of a hole
+ * @dst:	original runlist to be worked on
  * @dsize:	number of elements in @dst (including end marker)
- * @src:	new run list to be inserted
+ * @src:	new runlist to be inserted
  * @ssize:	number of elements in @src (excluding end marker)
- * @loc:	index in run list @dst at which to split and insert @src
+ * @loc:	index in runlist @dst at which to split and insert @src
  *
- * Split the run list @dst at @loc into two and insert @new in between the two
- * fragments. No merging of run lists is necessary. Adjust the size of the
+ * Split the runlist @dst at @loc into two and insert @new in between the two
+ * fragments. No merging of runlists is necessary. Adjust the size of the
  * holes either side.
  *
- * It is up to the caller to serialize access to the run lists @dst and @src.
+ * It is up to the caller to serialize access to the runlists @dst and @src.
  *
- * On success, return a pointer to the new, combined, run list. Note, both
- * run lists @dst and @src are deallocated before returning so you cannot use
- * the pointers for anything any more. (Strictly speaking the returned run list
+ * On success, return a pointer to the new, combined, runlist. Note, both
+ * runlists @dst and @src are deallocated before returning so you cannot use
+ * the pointers for anything any more. (Strictly speaking the returned runlist
  * may be the same as @dst but this is irrelevant.)
  *
- * On error, return -errno. Both run lists are left unmodified. The following
+ * On error, return -errno. Both runlists are left unmodified. The following
  * error codes are defined:
- *	-ENOMEM	- Not enough memory to allocate run list array.
+ *	-ENOMEM	- Not enough memory to allocate runlist array.
  *	-EINVAL	- Invalid parameters were passed in.
  */
-static inline run_list_element *ntfs_rl_split(run_list_element *dst, int dsize,
-		run_list_element *src, int ssize, int loc)
+static inline runlist_element *ntfs_rl_split(runlist_element *dst, int dsize,
+		runlist_element *src, int ssize, int loc)
 {
 	BUG_ON(!dst);
 	BUG_ON(!src);
@@ -436,7 +436,7 @@
 		return dst;
 	/*
 	 * We are guaranteed to succeed from here so can start modifying the
-	 * original run lists.
+	 * original runlists.
 	 */
 
 	/* Move the tail of @dst out of the way, then copy in @src. */
@@ -452,17 +452,17 @@
 }
 
 /**
- * ntfs_merge_run_lists - merge two run_lists into one
- * @drl:	original run list to be worked on
- * @srl:	new run list to be merged into @drl
+ * ntfs_merge_runlists - merge two runlists into one
+ * @drl:	original runlist to be worked on
+ * @srl:	new runlist to be merged into @drl
  *
- * First we sanity check the two run lists @srl and @drl to make sure that they
- * are sensible and can be merged. The run list @srl must be either after the
- * run list @drl or completely within a hole (or unmapped region) in @drl.
+ * First we sanity check the two runlists @srl and @drl to make sure that they
+ * are sensible and can be merged. The runlist @srl must be either after the
+ * runlist @drl or completely within a hole (or unmapped region) in @drl.
  *
- * It is up to the caller to serialize access to the run lists @drl and @srl.
+ * It is up to the caller to serialize access to the runlists @drl and @srl.
  *
- * Merging of run lists is necessary in two cases:
+ * Merging of runlists is necessary in two cases:
  *   1. When attribute lists are used and a further extent is being mapped.
  *   2. When new clusters are allocated to fill a hole or extend a file.
  *
@@ -471,22 +471,22 @@
  *	- split the hole in two and be inserted between the two fragments,
  *	- be appended at the end of a hole, or it can
  *	- replace the whole hole.
- * It can also be appended to the end of the run list, which is just a variant
+ * It can also be appended to the end of the runlist, which is just a variant
  * of the insert case.
  *
- * On success, return a pointer to the new, combined, run list. Note, both
- * run lists @drl and @srl are deallocated before returning so you cannot use
- * the pointers for anything any more. (Strictly speaking the returned run list
+ * On success, return a pointer to the new, combined, runlist. Note, both
+ * runlists @drl and @srl are deallocated before returning so you cannot use
+ * the pointers for anything any more. (Strictly speaking the returned runlist
  * may be the same as @dst but this is irrelevant.)
  *
- * On error, return -errno. Both run lists are left unmodified. The following
+ * On error, return -errno. Both runlists are left unmodified. The following
  * error codes are defined:
- *	-ENOMEM	- Not enough memory to allocate run list array.
+ *	-ENOMEM	- Not enough memory to allocate runlist array.
  *	-EINVAL	- Invalid parameters were passed in.
- *	-ERANGE	- The run lists overlap and cannot be merged.
+ *	-ERANGE	- The runlists overlap and cannot be merged.
  */
-run_list_element *ntfs_merge_run_lists(run_list_element *drl,
-		run_list_element *srl)
+runlist_element *ntfs_merge_runlists(runlist_element *drl,
+		runlist_element *srl)
 {
 	int di, si;		/* Current index into @[ds]rl. */
 	int sstart;		/* First index with lcn > LCN_RL_NOT_MAPPED. */
@@ -507,21 +507,21 @@
 	/* Check for silly calling... */
 	if (unlikely(!srl))
 		return drl;
-	if (unlikely(IS_ERR(srl) || IS_ERR(drl)))
+	if (IS_ERR(srl) || IS_ERR(drl))
 		return ERR_PTR(-EINVAL);
 
 	/* Check for the case where the first mapping is being done now. */
 	if (unlikely(!drl)) {
 		drl = srl;
-		/* Complete the source run list if necessary. */
+		/* Complete the source runlist if necessary. */
 		if (unlikely(drl[0].vcn)) {
-			/* Scan to the end of the source run list. */
+			/* Scan to the end of the source runlist. */
 			for (dend = 0; likely(drl[dend].length); dend++)
 				;
 			drl = ntfs_rl_realloc(drl, dend, dend + 1);
 			if (IS_ERR(drl))
 				return drl;
-			/* Insert start element at the front of the run list. */
+			/* Insert start element at the front of the runlist. */
 			ntfs_rl_mm(drl, 1, 0, dend);
 			drl[0].vcn = 0;
 			drl[0].lcn = LCN_RL_NOT_MAPPED;
@@ -532,11 +532,11 @@
 
 	si = di = 0;
 
-	/* Skip any unmapped start element(s) in the source run_list. */
+	/* Skip any unmapped start element(s) in the source runlist. */
 	while (srl[si].length && srl[si].lcn < (LCN)LCN_HOLE)
 		si++;
 
-	/* Can't have an entirely unmapped source run list. */
+	/* Can't have an entirely unmapped source runlist. */
 	BUG_ON(!srl[si].length);
 
 	/* Record the starting points. */
@@ -560,7 +560,7 @@
 		return ERR_PTR(-ERANGE);
 	}
 
-	/* Scan to the end of both run lists in order to know their sizes. */
+	/* Scan to the end of both runlists in order to know their sizes. */
 	for (send = si; srl[send].length; send++)
 		;
 	for (dend = di; drl[dend].length; dend++)
@@ -631,7 +631,7 @@
 				goto finished;
 			}
 			/*
-			 * We need to create an unmapped run list element in
+			 * We need to create an unmapped runlist element in
 			 * @drl or extend an existing one before adding the
 			 * ENOENT terminator.
 			 */
@@ -640,7 +640,7 @@
 				slots = 1;
 			}
 			if (drl[ds].lcn != (LCN)LCN_RL_NOT_MAPPED) {
-				/* Add an unmapped run list element. */
+				/* Add an unmapped runlist element. */
 				if (!slots) {
 					/* FIXME/TODO: We need to have the
 					 * extra memory already! (AIA) */
@@ -677,7 +677,7 @@
 
 finished:
 	/* The merge was completed successfully. */
-	ntfs_debug("Merged run list:");
+	ntfs_debug("Merged runlist:");
 	ntfs_debug_dump_runlist(drl);
 	return drl;
 
@@ -688,45 +688,45 @@
 }
 
 /**
- * decompress_mapping_pairs - convert mapping pairs array to run list
+ * decompress_mapping_pairs - convert mapping pairs array to runlist
  * @vol:	ntfs volume on which the attribute resides
  * @attr:	attribute record whose mapping pairs array to decompress
- * @old_rl:	optional run list in which to insert @attr's run list
+ * @old_rl:	optional runlist in which to insert @attr's runlist
  *
- * It is up to the caller to serialize access to the run list @old_rl.
+ * It is up to the caller to serialize access to the runlist @old_rl.
  *
- * Decompress the attribute @attr's mapping pairs array into a run list. On
- * success, return the decompressed run list.
+ * Decompress the attribute @attr's mapping pairs array into a runlist. On
+ * success, return the decompressed runlist.
  *
- * If @old_rl is not NULL, decompressed run list is inserted into the
- * appropriate place in @old_rl and the resultant, combined run list is
+ * If @old_rl is not NULL, decompressed runlist is inserted into the
+ * appropriate place in @old_rl and the resultant, combined runlist is
  * returned. The original @old_rl is deallocated.
  *
  * On error, return -errno. @old_rl is left unmodified in that case.
  *
  * The following error codes are defined:
- *	-ENOMEM	- Not enough memory to allocate run list array.
- *	-EIO	- Corrupt run list.
+ *	-ENOMEM	- Not enough memory to allocate runlist array.
+ *	-EIO	- Corrupt runlist.
  *	-EINVAL	- Invalid parameters were passed in.
- *	-ERANGE	- The two run lists overlap.
+ *	-ERANGE	- The two runlists overlap.
  *
  * FIXME: For now we take the conceptionally simplest approach of creating the
- * new run list disregarding the already existing one and then splicing the
+ * new runlist disregarding the already existing one and then splicing the
  * two into one, if that is possible (we check for overlap and discard the new
- * run list if overlap present before returning ERR_PTR(-ERANGE)).
+ * runlist if overlap present before returning ERR_PTR(-ERANGE)).
  */
-run_list_element *decompress_mapping_pairs(const ntfs_volume *vol,
-		const ATTR_RECORD *attr, run_list_element *old_rl)
+runlist_element *decompress_mapping_pairs(const ntfs_volume *vol,
+		const ATTR_RECORD *attr, runlist_element *old_rl)
 {
 	VCN vcn;		/* Current vcn. */
 	LCN lcn;		/* Current lcn. */
 	s64 deltaxcn;		/* Change in [vl]cn. */
-	run_list_element *rl;	/* The output run list. */
+	runlist_element *rl;	/* The output runlist. */
 	u8 *buf;		/* Current position in mapping pairs array. */
 	u8 *attr_end;		/* End of attribute. */
-	int rlsize;		/* Size of run list buffer. */
-	u16 rlpos;		/* Current run list position in units of
-				   run_list_elements. */
+	int rlsize;		/* Size of runlist buffer. */
+	u16 rlpos;		/* Current runlist position in units of
+				   runlist_elements. */
 	u8 b;			/* Current byte offset in buf. */
 
 #ifdef DEBUG
@@ -748,9 +748,9 @@
 		ntfs_error(vol->sb, "Corrupt attribute.");
 		return ERR_PTR(-EIO);
 	}
-	/* Current position in run list array. */
+	/* Current position in runlist array. */
 	rlpos = 0;
-	/* Allocate first page and set current run list size to one page. */
+	/* Allocate first page and set current runlist size to one page. */
 	rl = ntfs_malloc_nofs(rlsize = PAGE_SIZE);
 	if (unlikely(!rl))
 		return ERR_PTR(-ENOMEM);
@@ -768,7 +768,7 @@
 		 * operates on whole pages only.
 		 */
 		if (((rlpos + 3) * sizeof(*old_rl)) > rlsize) {
-			run_list_element *rl2;
+			runlist_element *rl2;
 
 			rl2 = ntfs_malloc_nofs(rlsize + (int)PAGE_SIZE);
 			if (unlikely(!rl2)) {
@@ -780,7 +780,7 @@
 			rl = rl2;
 			rlsize += PAGE_SIZE;
 		}
-		/* Enter the current vcn into the current run_list element. */
+		/* Enter the current vcn into the current runlist element. */
 		rl[rlpos].vcn = vcn;
 		/*
 		 * Get the change in vcn, i.e. the run length in clusters.
@@ -810,7 +810,7 @@
 			goto err_out;
 		}
 		/*
-		 * Enter the current run length into the current run list
+		 * Enter the current run length into the current runlist
 		 * element.
 		 */
 		rl[rlpos].length = deltaxcn;
@@ -854,10 +854,10 @@
 						"mapping pairs array.");
 				goto err_out;
 			}
-			/* Enter the current lcn into the run_list element. */
+			/* Enter the current lcn into the runlist element. */
 			rl[rlpos].lcn = lcn;
 		}
-		/* Get to the next run_list element. */
+		/* Get to the next runlist element. */
 		rlpos++;
 		/* Increment the buffer position to the next mapping pair. */
 		buf += (*buf & 0xf) + ((*buf >> 4) & 0xf) + 1;
@@ -866,7 +866,7 @@
 		goto io_error;
 	/*
 	 * If there is a highest_vcn specified, it must be equal to the final
-	 * vcn in the run list - 1, or something has gone badly wrong.
+	 * vcn in the runlist - 1, or something has gone badly wrong.
 	 */
 	deltaxcn = sle64_to_cpu(attr->data.non_resident.highest_vcn);
 	if (unlikely(deltaxcn && vcn - 1 != deltaxcn)) {
@@ -875,7 +875,7 @@
 				"non-resident attribute.");
 		goto err_out;
 	}
-	/* Setup not mapped run list element if this is the base extent. */
+	/* Setup not mapped runlist element if this is the base extent. */
 	if (!attr->data.non_resident.lowest_vcn) {
 		VCN max_cluster;
 
@@ -885,7 +885,7 @@
 				vol->cluster_size_bits;
 		/*
 		 * If there is a difference between the highest_vcn and the
-		 * highest cluster, the run list is either corrupt or, more
+		 * highest cluster, the runlist is either corrupt or, more
 		 * likely, there are more extents following this one.
 		 */
 		if (deltaxcn < --max_cluster) {
@@ -908,21 +908,21 @@
 	} else /* Not the base extent. There may be more extents to follow. */
 		rl[rlpos].lcn = (LCN)LCN_RL_NOT_MAPPED;
 
-	/* Setup terminating run_list element. */
+	/* Setup terminating runlist element. */
 	rl[rlpos].vcn = vcn;
 	rl[rlpos].length = (s64)0;
-	/* If no existing run list was specified, we are done. */
+	/* If no existing runlist was specified, we are done. */
 	if (!old_rl) {
 		ntfs_debug("Mapping pairs array successfully decompressed:");
 		ntfs_debug_dump_runlist(rl);
 		return rl;
 	}
-	/* Now combine the new and old run lists checking for overlaps. */
-	old_rl = ntfs_merge_run_lists(old_rl, rl);
+	/* Now combine the new and old runlists checking for overlaps. */
+	old_rl = ntfs_merge_runlists(old_rl, rl);
 	if (likely(!IS_ERR(old_rl)))
 		return old_rl;
 	ntfs_free(rl);
-	ntfs_error(vol->sb, "Failed to merge run lists.");
+	ntfs_error(vol->sb, "Failed to merge runlists.");
 	return old_rl;
 io_error:
 	ntfs_error(vol->sb, "Corrupt attribute.");
@@ -932,22 +932,25 @@
 }
 
 /**
- * map_run_list - map (a part of) a run list of an ntfs inode
- * @ni:		ntfs inode for which to map (part of) a run list
- * @vcn:	map run list part containing this vcn
+ * ntfs_map_runlist - map (a part of) a runlist of an ntfs inode
+ * @ni:		ntfs inode for which to map (part of) a runlist
+ * @vcn:	map runlist part containing this vcn
  *
- * Map the part of a run list containing the @vcn of an the ntfs inode @ni.
+ * Map the part of a runlist containing the @vcn of the ntfs inode @ni.
  *
  * Return 0 on success and -errno on error.
+ *
+ * Locking: - The runlist must be unlocked on entry and is unlocked on return.
+ *	    - This function takes the lock for writing and modifies the runlist.
  */
-int map_run_list(ntfs_inode *ni, VCN vcn)
+int ntfs_map_runlist(ntfs_inode *ni, VCN vcn)
 {
 	ntfs_inode *base_ni;
-	attr_search_context *ctx;
+	ntfs_attr_search_ctx *ctx;
 	MFT_RECORD *mrec;
 	int err = 0;
 
-	ntfs_debug("Mapping run list part containing vcn 0x%llx.",
+	ntfs_debug("Mapping runlist part containing vcn 0x%llx.",
 			(unsigned long long)vcn);
 
 	if (!NInoAttr(ni))
@@ -958,69 +961,67 @@
 	mrec = map_mft_record(base_ni);
 	if (IS_ERR(mrec))
 		return PTR_ERR(mrec);
-	ctx = get_attr_search_ctx(base_ni, mrec);
-	if (!ctx) {
+	ctx = ntfs_attr_get_search_ctx(base_ni, mrec);
+	if (unlikely(!ctx)) {
 		err = -ENOMEM;
 		goto err_out;
 	}
-	if (!lookup_attr(ni->type, ni->name, ni->name_len, CASE_SENSITIVE, vcn,
-			NULL, 0, ctx)) {
-		put_attr_search_ctx(ctx);
-		err = -ENOENT;
-		goto err_out;
-	}
+	err = ntfs_attr_lookup(ni->type, ni->name, ni->name_len,
+			CASE_SENSITIVE, vcn, NULL, 0, ctx);
+	if (unlikely(err))
+		goto put_err_out;
 
-	down_write(&ni->run_list.lock);
+	down_write(&ni->runlist.lock);
 	/* Make sure someone else didn't do the work while we were sleeping. */
-	if (likely(vcn_to_lcn(ni->run_list.rl, vcn) <= LCN_RL_NOT_MAPPED)) {
-		run_list_element *rl;
+	if (likely(ntfs_vcn_to_lcn(ni->runlist.rl, vcn) <= LCN_RL_NOT_MAPPED)) {
+		runlist_element *rl;
 
 		rl = decompress_mapping_pairs(ni->vol, ctx->attr,
-				ni->run_list.rl);
-		if (unlikely(IS_ERR(rl)))
+				ni->runlist.rl);
+		if (IS_ERR(rl))
 			err = PTR_ERR(rl);
 		else
-			ni->run_list.rl = rl;
+			ni->runlist.rl = rl;
 	}
-	up_write(&ni->run_list.lock);
+	up_write(&ni->runlist.lock);
 
-	put_attr_search_ctx(ctx);
+put_err_out:
+	ntfs_attr_put_search_ctx(ctx);
 err_out:
 	unmap_mft_record(base_ni);
 	return err;
 }
 
 /**
- * vcn_to_lcn - convert a vcn into a lcn given a run list
- * @rl:		run list to use for conversion
+ * ntfs_vcn_to_lcn - convert a vcn into a lcn given a runlist
+ * @rl:		runlist to use for conversion
  * @vcn:	vcn to convert
  *
  * Convert the virtual cluster number @vcn of an attribute into a logical
- * cluster number (lcn) of a device using the run list @rl to map vcns to their
+ * cluster number (lcn) of a device using the runlist @rl to map vcns to their
  * corresponding lcns.
  *
- * It is up to the caller to serialize access to the run list @rl.
+ * It is up to the caller to serialize access to the runlist @rl.
  *
  * Since lcns must be >= 0, we use negative return values with special meaning:
  *
  * Return value			Meaning / Description
  * ==================================================
  *  -1 = LCN_HOLE		Hole / not allocated on disk.
- *  -2 = LCN_RL_NOT_MAPPED	This is part of the run list which has not been
- *				inserted into the run list yet.
+ *  -2 = LCN_RL_NOT_MAPPED	This is part of the runlist which has not been
+ *				inserted into the runlist yet.
  *  -3 = LCN_ENOENT		There is no such vcn in the attribute.
- *  -4 = LCN_EINVAL		Input parameter error (if debug enabled).
+ *
+ * Locking: - The caller must have locked the runlist (for reading or writing).
+ *	    - This function does not touch the lock.
  */
-LCN vcn_to_lcn(const run_list_element *rl, const VCN vcn)
+LCN ntfs_vcn_to_lcn(const runlist_element *rl, const VCN vcn)
 {
 	int i;
 
-#ifdef DEBUG
-	if (vcn < (VCN)0)
-		return (LCN)LCN_EINVAL;
-#endif
+	BUG_ON(vcn < 0);
 	/*
-	 * If rl is NULL, assume that we have found an unmapped run list. The
+	 * If rl is NULL, assume that we have found an unmapped runlist. The
 	 * caller can then attempt to map it and fail appropriately if
 	 * necessary.
 	 */
@@ -1049,7 +1050,104 @@
 }
 
 /**
- * find_attr - find (next) attribute in mft record
+ * ntfs_find_vcn - find a vcn in the runlist described by an ntfs inode
+ * @ni:		ntfs inode describing the runlist to search
+ * @vcn:	vcn to find
+ * @need_write:	if false, lock for reading and if true, lock for writing
+ *
+ * Find the virtual cluster number @vcn in the runlist described by the ntfs
+ * inode @ni and return the address of the runlist element containing the @vcn.
+ * The runlist is left locked and the caller has to unlock it.  If @need_write
+ * is true, the runlist is locked for writing and if @need_write is false, the
+ * runlist is locked for reading.  In the error case, the runlist is not left
+ * locked.
+ *
+ * Note you need to distinguish between the lcn of the returned runlist element
+ * being >= 0 and LCN_HOLE.  In the later case you have to return zeroes on
+ * read and allocate clusters on write.
+ *
+ * Return the runlist element containing the @vcn on success and
+ * ERR_PTR(-errno) on error.  You need to test the return value with IS_ERR()
+ * to decide if the return is success or failure and PTR_ERR() to get to the
+ * error code if IS_ERR() is true.
+ *
+ * The possible error return codes are:
+ *	-ENOENT - No such vcn in the runlist, i.e. @vcn is out of bounds.
+ *	-ENOMEM - Not enough memory to map runlist.
+ *	-EIO	- Critical error (runlist/file is corrupt, i/o error, etc).
+ *
+ * Locking: - The runlist must be unlocked on entry.
+ *	    - On failing return, the runlist is unlocked.
+ *	    - On successful return, the runlist is locked.  If @need_write us
+ *	      true, it is locked for writing.  Otherwise is is locked for
+ *	      reading.
+ */
+runlist_element *ntfs_find_vcn(ntfs_inode *ni, const VCN vcn,
+		const BOOL need_write)
+{
+	runlist_element *rl;
+	int err = 0;
+	BOOL is_retry = FALSE;
+
+	ntfs_debug("Entering for i_ino 0x%lx, vcn 0x%llx, lock for %sing.",
+			ni->mft_no, (unsigned long long)vcn,
+			!need_write ? "read" : "writ");
+	BUG_ON(!ni);
+	BUG_ON(!NInoNonResident(ni));
+	BUG_ON(vcn < 0);
+lock_retry_remap:
+	if (!need_write)
+		down_read(&ni->runlist.lock);
+	else
+		down_write(&ni->runlist.lock);
+	rl = ni->runlist.rl;
+	if (likely(rl && vcn >= rl[0].vcn)) {
+		while (likely(rl->length)) {
+			if (likely(vcn < rl[1].vcn)) {
+				if (likely(rl->lcn >= (LCN)LCN_HOLE)) {
+					ntfs_debug("Done.");
+					return rl;
+				}
+				break;
+			}
+			rl++;
+		}
+		if (likely(rl->lcn != (LCN)LCN_RL_NOT_MAPPED)) {
+			if (likely(rl->lcn == (LCN)LCN_ENOENT))
+				err = -ENOENT;
+			else
+				err = -EIO;
+		}
+	}
+	if (!need_write)
+		up_read(&ni->runlist.lock);
+	else
+		up_write(&ni->runlist.lock);
+	if (!err && !is_retry) {
+		/*
+		 * The @vcn is in an unmapped region, map the runlist and
+		 * retry.
+		 */
+		err = ntfs_map_runlist(ni, vcn);
+		if (likely(!err)) {
+			is_retry = TRUE;
+			goto lock_retry_remap;
+		}
+		/*
+		 * -EINVAL and -ENOENT coming from a failed mapping attempt are
+		 * equivalent to i/o errors for us as they should not happen in
+		 * our code paths.
+		 */
+		if (err == -EINVAL || err == -ENOENT)
+			err = -EIO;
+	} else if (!err)
+		err = -EIO;
+	ntfs_error(ni->vol->sb, "Failed with error code %i.", err);
+	return ERR_PTR(err);
+}
+
+/**
+ * ntfs_attr_find - find (next) attribute in mft record
  * @type:	attribute type to find
  * @name:	attribute name to find (optional, i.e. NULL means don't care)
  * @name_len:	attribute name length (only needed if @name present)
@@ -1058,47 +1156,56 @@
  * @val_len:	attribute value length
  * @ctx:	search context with mft record and attribute to search from
  *
- * You shouldn't need to call this function directly. Use lookup_attr() instead.
+ * You should not need to call this function directly.  Use ntfs_attr_lookup()
+ * instead.
+ *
+ * ntfs_attr_find() takes a search context @ctx as parameter and searches the
+ * mft record specified by @ctx->mrec, beginning at @ctx->attr, for an
+ * attribute of @type, optionally @name and @val.
+ *
+ * If the attribute is found, ntfs_attr_find() returns 0 and @ctx->attr will
+ * point to the found attribute.
+ *
+ * If the attribute is not found, ntfs_attr_find() returns -ENOENT and
+ * @ctx->attr will point to the attribute before which the attribute being
+ * searched for would need to be inserted if such an action were to be desired.
  *
- * find_attr() takes a search context @ctx as parameter and searches the mft
- * record specified by @ctx->mrec, beginning at @ctx->attr, for an attribute of
- * @type, optionally @name and @val. If found, find_attr() returns TRUE and
- * @ctx->attr will point to the found attribute. If not found, find_attr()
- * returns FALSE and @ctx->attr is undefined (i.e. do not rely on it not
- * changing).
+ * On actual error, ntfs_attr_find() returns -EIO.  In this case @ctx->attr is
+ * undefined and in particular do not rely on it not changing.
  *
- * If @ctx->is_first is TRUE, the search begins with @ctx->attr itself. If it
+ * If @ctx->is_first is TRUE, the search begins with @ctx->attr itself.  If it
  * is FALSE, the search begins after @ctx->attr.
  *
  * If @ic is IGNORE_CASE, the @name comparisson is not case sensitive and
  * @ctx->ntfs_ino must be set to the ntfs inode to which the mft record
- * @ctx->mrec belongs. This is so we can get at the ntfs volume and hence at
- * the upcase table. If @ic is CASE_SENSITIVE, the comparison is case
- * sensitive. When @name is present, @name_len is the @name length in Unicode
+ * @ctx->mrec belongs.  This is so we can get at the ntfs volume and hence at
+ * the upcase table.  If @ic is CASE_SENSITIVE, the comparison is case
+ * sensitive.  When @name is present, @name_len is the @name length in Unicode
  * characters.
  *
  * If @name is not present (NULL), we assume that the unnamed attribute is
  * being searched for.
  *
- * Finally, the resident attribute value @val is looked for, if present. If @val
- * is not present (NULL), @val_len is ignored.
+ * Finally, the resident attribute value @val is looked for, if present.  If
+ * @val is not present (NULL), @val_len is ignored.
  *
- * find_attr() only searches the specified mft record and it ignores the
+ * ntfs_attr_find() only searches the specified mft record and it ignores the
  * presence of an attribute list attribute (unless it is the one being searched
- * for, obviously). If you need to take attribute lists into consideration, use
- * lookup_attr() instead (see below). This also means that you cannot use
- * find_attr() to search for extent records of non-resident attributes, as
- * extents with lowest_vcn != 0 are usually described by the attribute list
- * attribute only. - Note that it is possible that the first extent is only in
- * the attribute list while the last extent is in the base mft record, so don't
- * rely on being able to find the first extent in the base mft record.
+ * for, obviously).  If you need to take attribute lists into consideration,
+ * use ntfs_attr_lookup() instead (see below).  This also means that you cannot
+ * use ntfs_attr_find() to search for extent records of non-resident
+ * attributes, as extents with lowest_vcn != 0 are usually described by the
+ * attribute list attribute only. - Note that it is possible that the first
+ * extent is only in the attribute list while the last extent is in the base
+ * mft record, so do not rely on being able to find the first extent in the
+ * base mft record.
  *
  * Warning: Never use @val when looking for attribute types which can be
  *	    non-resident as this most likely will result in a crash!
  */
-BOOL find_attr(const ATTR_TYPES type, const ntfschar *name, const u32 name_len,
-		const IGNORE_CASE_BOOL ic, const u8 *val, const u32 val_len,
-		attr_search_context *ctx)
+static int ntfs_attr_find(const ATTR_TYPE type, const ntfschar *name,
+		const u32 name_len, const IGNORE_CASE_BOOL ic,
+		const u8 *val, const u32 val_len, ntfs_attr_search_ctx *ctx)
 {
 	ATTR_RECORD *a;
 	ntfs_volume *vol;
@@ -1129,21 +1236,21 @@
 				le32_to_cpu(ctx->mrec->bytes_allocated))
 			break;
 		ctx->attr = a;
-		/* We catch $END with this more general check, too... */
-		if (le32_to_cpu(a->type) > le32_to_cpu(type))
-			return FALSE;
+		if (unlikely(le32_to_cpu(a->type) > le32_to_cpu(type) ||
+				a->type == AT_END))
+			return -ENOENT;
 		if (unlikely(!a->length))
 			break;
 		if (a->type != type)
 			continue;
 		/*
-		 * If @name is present, compare the two names. If @name is
+		 * If @name is present, compare the two names.  If @name is
 		 * missing, assume we want an unnamed attribute.
 		 */
 		if (!name) {
 			/* The search failed if the found attribute is named. */
 			if (a->name_length)
-				return FALSE;
+				return -ENOENT;
 		} else if (!ntfs_are_names_equal(name, name_len,
 			    (ntfschar*)((u8*)a + le16_to_cpu(a->name_offset)),
 			    a->name_length, ic, upcase, upcase_len)) {
@@ -1151,7 +1258,7 @@
 
 			rc = ntfs_collate_names(name, name_len,
 					(ntfschar*)((u8*)a +
-						le16_to_cpu(a->name_offset)),
+					le16_to_cpu(a->name_offset)),
 					a->name_length, 1, IGNORE_CASE,
 					upcase, upcase_len);
 			/*
@@ -1159,67 +1266,66 @@
 			 * matching attribute.
 			 */
 			if (rc == -1)
-				return FALSE;
+				return -ENOENT;
 			/* If the strings are not equal, continue search. */
 			if (rc)
 				continue;
 			rc = ntfs_collate_names(name, name_len,
 					(ntfschar*)((u8*)a +
-						le16_to_cpu(a->name_offset)),
+					le16_to_cpu(a->name_offset)),
 					a->name_length, 1, CASE_SENSITIVE,
 					upcase, upcase_len);
 			if (rc == -1)
-				return FALSE;
+				return -ENOENT;
 			if (rc)
 				continue;
 		}
 		/*
 		 * The names match or @name not present and attribute is
-		 * unnamed. If no @val specified, we have found the attribute
+		 * unnamed.  If no @val specified, we have found the attribute
 		 * and are done.
 		 */
 		if (!val)
-			return TRUE;
+			return 0;
 		/* @val is present; compare values. */
 		else {
-			u32 vl;
 			register int rc;
 
-			vl = le32_to_cpu(a->data.resident.value_length);
-			if (vl > val_len)
-				vl = val_len;
-
 			rc = memcmp(val, (u8*)a + le16_to_cpu(
-					a->data.resident.value_offset), vl);
+					a->data.resident.value_offset),
+					min_t(u32, val_len, le32_to_cpu(
+					a->data.resident.value_length)));
 			/*
 			 * If @val collates before the current attribute's
 			 * value, there is no matching attribute.
 			 */
 			if (!rc) {
 				register u32 avl;
+
 				avl = le32_to_cpu(
 						a->data.resident.value_length);
 				if (val_len == avl)
-					return TRUE;
+					return 0;
 				if (val_len < avl)
-					return FALSE;
+					return -ENOENT;
 			} else if (rc < 0)
-				return FALSE;
+				return -ENOENT;
 		}
 	}
-	ntfs_error(NULL, "Inode is corrupt. Run chkdsk.");
-	return FALSE;
+	ntfs_error(NULL, "Inode is corrupt.  Run chkdsk.");
+	NVolSetErrors(vol);
+	return -EIO;
 }
 
 /**
  * load_attribute_list - load an attribute list into memory
  * @vol:		ntfs volume from which to read
- * @run_list:		run list of the attribute list
+ * @runlist:		runlist of the attribute list
  * @al_start:		destination buffer
  * @size:		size of the destination buffer in bytes
  * @initialized_size:	initialized size of the attribute list
  *
- * Walk the run list @run_list and load all clusters from it copying them into
+ * Walk the runlist @runlist and load all clusters from it copying them into
  * the linear buffer @al. The maximum number of bytes copied to @al is @size
  * bytes. Note, @size does not need to be a multiple of the cluster size. If
  * @initialized_size is less than @size, the region in @al between
@@ -1227,13 +1333,13 @@
  *
  * Return 0 on success or -errno on error.
  */
-int load_attribute_list(ntfs_volume *vol, run_list *run_list, u8 *al_start,
+int load_attribute_list(ntfs_volume *vol, runlist *runlist, u8 *al_start,
 		const s64 size, const s64 initialized_size)
 {
 	LCN lcn;
 	u8 *al = al_start;
 	u8 *al_end = al + initialized_size;
-	run_list_element *rl;
+	runlist_element *rl;
 	struct buffer_head *bh;
 	struct super_block *sb;
 	unsigned long block_size;
@@ -1242,7 +1348,7 @@
 	unsigned char block_size_bits;
 
 	ntfs_debug("Entering.");
-	if (!vol || !run_list || !al || size <= 0 || initialized_size < 0 ||
+	if (!vol || !runlist || !al || size <= 0 || initialized_size < 0 ||
 			initialized_size > size)
 		return -EINVAL;
 	if (!initialized_size) {
@@ -1252,17 +1358,17 @@
 	sb = vol->sb;
 	block_size = sb->s_blocksize;
 	block_size_bits = sb->s_blocksize_bits;
-	down_read(&run_list->lock);
-	rl = run_list->rl;
-	/* Read all clusters specified by the run list one run at a time. */
+	down_read(&runlist->lock);
+	rl = runlist->rl;
+	/* Read all clusters specified by the runlist one run at a time. */
 	while (rl->length) {
-		lcn = vcn_to_lcn(rl, rl->vcn);
+		lcn = ntfs_vcn_to_lcn(rl, rl->vcn);
 		ntfs_debug("Reading vcn = 0x%llx, lcn = 0x%llx.",
 				(unsigned long long)rl->vcn,
 				(unsigned long long)lcn);
 		/* The attribute list cannot be sparse. */
 		if (lcn < 0) {
-			ntfs_error(sb, "vcn_to_lcn() failed. Cannot read "
+			ntfs_error(sb, "ntfs_vcn_to_lcn() failed. Cannot read "
 					"attribute list.");
 			goto err_out;
 		}
@@ -1292,7 +1398,7 @@
 		memset(al_start + initialized_size, 0, size - initialized_size);
 	}
 done:
-	up_read(&run_list->lock);
+	up_read(&runlist->lock);
 	return err;
 do_final:
 	if (al < al_end) {
@@ -1320,7 +1426,7 @@
 }
 
 /**
- * find_external_attr - find an attribute in the attribute list of an ntfs inode
+ * ntfs_external_attr_find - find an attribute in the attribute list of an inode
  * @type:	attribute type to find
  * @name:	attribute name to find (optional, i.e. NULL means don't care)
  * @name_len:	attribute name length (only needed if @name present)
@@ -1330,34 +1436,49 @@
  * @val_len:	attribute value length
  * @ctx:	search context with mft record and attribute to search from
  *
- * You shouldn't need to call this function directly. Use lookup_attr() instead.
+ * You should not need to call this function directly.  Use ntfs_attr_lookup()
+ * instead.
  *
  * Find an attribute by searching the attribute list for the corresponding
- * attribute list entry. Having found the entry, map the mft record for read
- * if the attribute is in a different mft record/inode, find_attr the attribute
+ * attribute list entry.  Having found the entry, map the mft record if the
+ * attribute is in a different mft record/inode, ntfs_attr_find() the attribute
  * in there and return it.
  *
  * On first search @ctx->ntfs_ino must be the base mft record and @ctx must
- * have been obtained from a call to get_attr_search_ctx(). On subsequent calls
- * @ctx->ntfs_ino can be any extent inode, too (@ctx->base_ntfs_ino is then the
- * base inode).
+ * have been obtained from a call to ntfs_attr_get_search_ctx().  On subsequent
+ * calls @ctx->ntfs_ino can be any extent inode, too (@ctx->base_ntfs_ino is
+ * then the base inode).
  *
  * After finishing with the attribute/mft record you need to call
- * put_attr_search_ctx() to cleanup the search context (unmapping any mapped
- * inodes, etc).
+ * ntfs_attr_put_search_ctx() to cleanup the search context (unmapping any
+ * mapped inodes, etc).
  *
- * Return TRUE if the search was successful and FALSE if not. When TRUE,
- * @ctx->attr is the found attribute and it is in mft record @ctx->mrec. When
- * FALSE, @ctx->attr is the attribute which collates just after the attribute
- * being searched for in the base ntfs inode, i.e. if one wants to add the
- * attribute to the mft record this is the correct place to insert it into
- * and if there is not enough space, the attribute should be placed in an
- * extent mft record.
- */
-static BOOL find_external_attr(const ATTR_TYPES type, const ntfschar *name,
-		const u32 name_len, const IGNORE_CASE_BOOL ic,
-		const VCN lowest_vcn, const u8 *val, const u32 val_len,
-		attr_search_context *ctx)
+ * If the attribute is found, ntfs_external_attr_find() returns 0 and
+ * @ctx->attr will point to the found attribute.  @ctx->mrec will point to the
+ * mft record in which @ctx->attr is located and @ctx->al_entry will point to
+ * the attribute list entry for the attribute.
+ *
+ * If the attribute is not found, ntfs_external_attr_find() returns -ENOENT and
+ * @ctx->attr will point to the attribute in the base mft record before which
+ * the attribute being searched for would need to be inserted if such an action
+ * were to be desired.  @ctx->mrec will point to the mft record in which
+ * @ctx->attr is located and @ctx->al_entry will point to the attribute list
+ * entry of the attribute before which the attribute being searched for would
+ * need to be inserted if such an action were to be desired.
+ *
+ * Thus to insert the not found attribute, one wants to add the attribute to
+ * @ctx->mrec (the base mft record) and if there is not enough space, the
+ * attribute should be placed in a newly allocated extent mft record.  The
+ * attribute list entry for the inserted attribute should be inserted in the
+ * attribute list attribute at @ctx->al_entry.
+ *
+ * On actual error, ntfs_external_attr_find() returns -EIO.  In this case
+ * @ctx->attr is undefined and in particular do not rely on it not changing.
+ */
+static int ntfs_external_attr_find(const ATTR_TYPE type,
+		const ntfschar *name, const u32 name_len,
+		const IGNORE_CASE_BOOL ic, const VCN lowest_vcn,
+		const u8 *val, const u32 val_len, ntfs_attr_search_ctx *ctx)
 {
 	ntfs_inode *base_ni, *ni;
 	ntfs_volume *vol;
@@ -1366,6 +1487,8 @@
 	ATTR_RECORD *a;
 	ntfschar *al_name;
 	u32 al_name_len;
+	int err = 0;
+	static const char *es = " Unmount and run chkdsk.";
 
 	ni = ctx->ntfs_ino;
 	base_ni = ctx->base_ntfs_ino;
@@ -1377,6 +1500,8 @@
 	}
 	if (ni == base_ni)
 		ctx->base_attr = ctx->attr;
+	if (type == AT_END)
+		goto not_found;
 	vol = base_ni->vol;
 	al_start = base_ni->attr_list;
 	al_end = al_start + base_ni->attr_list_size;
@@ -1413,7 +1538,7 @@
 		if (type != al_entry->type)
 			continue;
 		/*
-		 * If @name is present, compare the two names. If @name is
+		 * If @name is present, compare the two names.  If @name is
 		 * missing, assume we want an unnamed attribute.
 		 */
 		al_name_len = al_entry->name_length;
@@ -1439,10 +1564,11 @@
 				continue;
 			/*
 			 * FIXME: Reverse engineering showed 0, IGNORE_CASE but
-			 * that is inconsistent with find_attr(). The subsequent
-			 * rc checks were also different. Perhaps I made a
-			 * mistake in one of the two. Need to recheck which is
-			 * correct or at least see what is going on... (AIA)
+			 * that is inconsistent with ntfs_attr_find().  The
+			 * subsequent rc checks were also different.  Perhaps I
+			 * made a mistake in one of the two.  Need to recheck
+			 * which is correct or at least see what is going on...
+			 * (AIA)
 			 */
 			rc = ntfs_collate_names(name, name_len, al_name,
 					al_name_len, 1, CASE_SENSITIVE,
@@ -1454,8 +1580,8 @@
 		}
 		/*
 		 * The names match or @name not present and attribute is
-		 * unnamed. Now check @lowest_vcn. Continue search if the
-		 * next attribute list entry still fits @lowest_vcn. Otherwise
+		 * unnamed.  Now check @lowest_vcn.  Continue search if the
+		 * next attribute list entry still fits @lowest_vcn.  Otherwise
 		 * we have reached the right one or the search has failed.
 		 */
 		if (lowest_vcn && (u8*)next_al_entry >= al_start	    &&
@@ -1463,7 +1589,7 @@
 				(u8*)next_al_entry + le16_to_cpu(
 					next_al_entry->length) <= al_end    &&
 				sle64_to_cpu(next_al_entry->lowest_vcn) <=
-					sle64_to_cpu(lowest_vcn)	    &&
+					lowest_vcn			    &&
 				next_al_entry->type == al_entry->type	    &&
 				next_al_entry->name_length == al_name_len   &&
 				ntfs_are_names_equal((ntfschar*)((u8*)
@@ -1476,7 +1602,10 @@
 		if (MREF_LE(al_entry->mft_reference) == ni->mft_no) {
 			if (MSEQNO_LE(al_entry->mft_reference) != ni->seq_no) {
 				ntfs_error(vol->sb, "Found stale mft "
-						"reference in attribute list!");
+						"reference in attribute list "
+						"of base inode 0x%lx.%s",
+						base_ni->mft_no, es);
+				err = -EIO;
 				break;
 			}
 		} else { /* Mft references do not match. */
@@ -1491,13 +1620,20 @@
 			} else {
 				/* We want an extent record. */
 				ctx->mrec = map_extent_mft_record(base_ni,
-						al_entry->mft_reference, &ni);
+						le64_to_cpu(
+						al_entry->mft_reference), &ni);
 				ctx->ntfs_ino = ni;
 				if (IS_ERR(ctx->mrec)) {
-					ntfs_error(vol->sb, "Failed to map mft "
-							"record, error code "
-							"%ld.",
-							-PTR_ERR(ctx->mrec));
+					ntfs_error(vol->sb, "Failed to map "
+							"extent mft record "
+							"0x%lx of base inode "
+							"0x%lx.%s",
+							MREF_LE(al_entry->
+							mft_reference),
+							base_ni->mft_no, es);
+					err = PTR_ERR(ctx->mrec);
+					if (err == -ENOENT)
+						err = -EIO;
 					break;
 				}
 			}
@@ -1510,14 +1646,14 @@
 		 * current al_entry.
 		 */
 		/*
-		 * We could call into find_attr() to find the right attribute
-		 * in this mft record but this would be less efficient and not
-		 * quite accurate as find_attr() ignores the attribute instance
-		 * numbers for example which become important when one plays
-		 * with attribute lists. Also, because a proper match has been
-		 * found in the attribute list entry above, the comparison can
-		 * now be optimized. So it is worth re-implementing a
-		 * simplified find_attr() here.
+		 * We could call into ntfs_attr_find() to find the right
+		 * attribute in this mft record but this would be less
+		 * efficient and not quite accurate as ntfs_attr_find() ignores
+		 * the attribute instance numbers for example which become
+		 * important when one plays with attribute lists.  Also,
+		 * because a proper match has been found in the attribute list
+		 * entry above, the comparison can now be optimized.  So it is
+		 * worth re-implementing a simplified ntfs_attr_find() here.
 		 */
 		a = ctx->attr;
 		/*
@@ -1534,18 +1670,18 @@
 			break;
 		if (al_entry->instance != a->instance)
 			goto do_next_attr;
+		/*
+		 * If the type and/or the name are mismatched between the
+		 * attribute list entry and the attribute record, there is
+		 * corruption so we break and return error EIO.
+		 */
 		if (al_entry->type != a->type)
-			continue;
-		if (name) {
-			if (a->name_length != al_name_len)
-				continue;
-			if (!ntfs_are_names_equal((ntfschar*)((u8*)a +
-					le16_to_cpu(a->name_offset)),
-					a->name_length, al_name, al_name_len,
-					CASE_SENSITIVE, vol->upcase,
-					vol->upcase_len))
-				continue;
-		}
+			break;
+		if (!ntfs_are_names_equal((ntfschar*)((u8*)a +
+				le16_to_cpu(a->name_offset)), a->name_length,
+				al_name, al_name_len, CASE_SENSITIVE,
+				vol->upcase, vol->upcase_len))
+			break;
 		ctx->attr = a;
 		/*
 		 * If no @val specified or @val specified and it matches, we
@@ -1557,46 +1693,78 @@
 				le16_to_cpu(a->data.resident.value_offset),
 				val, val_len))) {
 			ntfs_debug("Done, found.");
-			return TRUE;
+			return 0;
 		}
 do_next_attr:
 		/* Proceed to the next attribute in the current mft record. */
 		a = (ATTR_RECORD*)((u8*)a + le32_to_cpu(a->length));
 		goto do_next_attr_loop;
 	}
-	ntfs_error(base_ni->vol->sb, "Inode contains corrupt attribute list "
-			"attribute.");
+	if (!err) {
+		ntfs_error(vol->sb, "Base inode 0x%lx contains corrupt "
+				"attribute list attribute.%s", base_ni->mft_no,
+				es);
+		err = -EIO;
+	}
 	if (ni != base_ni) {
 		unmap_extent_mft_record(ni);
 		ctx->ntfs_ino = base_ni;
 		ctx->mrec = ctx->base_mrec;
 		ctx->attr = ctx->base_attr;
 	}
+	if (err != -ENOMEM)
+		NVolSetErrors(vol);
+	return err;
+not_found:
+	/*
+	 * If we were looking for AT_END, we reset the search context @ctx and
+	 * use ntfs_attr_find() to seek to the end of the base mft record.
+	 */
+	if (type == AT_END) {
+		ntfs_attr_reinit_search_ctx(ctx);
+		return ntfs_attr_find(AT_END, name, name_len, ic, val, val_len,
+				ctx);
+	}
 	/*
-	 * FIXME: We absolutely have to return ERROR status instead of just
-	 * false or we will blow up or even worse cause corruption when we add
-	 * write support and we reach this code path!
+	 * The attribute was not found.  Before we return, we want to ensure
+	 * @ctx->mrec and @ctx->attr indicate the position at which the
+	 * attribute should be inserted in the base mft record.  Since we also
+	 * want to preserve @ctx->al_entry we cannot reinitialize the search
+	 * context using ntfs_attr_reinit_search_ctx() as this would set
+	 * @ctx->al_entry to NULL.  Thus we do the necessary bits manually (see
+	 * ntfs_attr_init_search_ctx() below).  Note, we _only_ preserve
+	 * @ctx->al_entry as the remaining fields (base_*) are identical to
+	 * their non base_ counterparts and we cannot set @ctx->base_attr
+	 * correctly yet as we do not know what @ctx->attr will be set to by
+	 * the call to ntfs_attr_find() below.
 	 */
-	printk(KERN_CRIT "NTFS: FIXME: Hit unfinished error code path!!!\n");
-	return FALSE;
-not_found:
+	if (ni != base_ni)
+		unmap_extent_mft_record(ni);
+	ctx->mrec = ctx->base_mrec;
+	ctx->attr = (ATTR_RECORD*)((u8*)ctx->mrec +
+			le16_to_cpu(ctx->mrec->attrs_offset));
+	ctx->is_first = TRUE;
+	ctx->ntfs_ino = base_ni;
+	ctx->base_ntfs_ino = NULL;
+	ctx->base_mrec = NULL;
+	ctx->base_attr = NULL;
 	/*
-	 * Seek to the end of the base mft record, i.e. when we return false,
-	 * ctx->mrec and ctx->attr indicate where the attribute should be
-	 * inserted into the attribute record.
-	 * And of course ctx->al_entry points to the end of the attribute
-	 * list inside NTFS_I(ctx->base_vfs_ino)->attr_list.
-	 *
-	 * FIXME: Do we really want to do this here? Think about it... (AIA)
+	 * In case there are multiple matches in the base mft record, need to
+	 * keep enumerating until we get an attribute not found response (or
+	 * another error), otherwise we would keep returning the same attribute
+	 * over and over again and all programs using us for enumeration would
+	 * lock up in a tight loop.
 	 */
-	reinit_attr_search_ctx(ctx);
-	find_attr(type, name, name_len, ic, val, val_len, ctx);
+	do {
+		err = ntfs_attr_find(type, name, name_len, ic, val, val_len,
+				ctx);
+	} while (!err);
 	ntfs_debug("Done, not found.");
-	return FALSE;
+	return err;
 }
 
 /**
- * lookup_attr - find an attribute in an ntfs inode
+ * ntfs_attr_lookup - find an attribute in an ntfs inode
  * @type:	attribute type to find
  * @name:	attribute name to find (optional, i.e. NULL means don't care)
  * @name_len:	attribute name length (only needed if @name present)
@@ -1606,27 +1774,38 @@
  * @val_len:	attribute value length
  * @ctx:	search context with mft record and attribute to search from
  *
- * Find an attribute in an ntfs inode. On first search @ctx->ntfs_ino must
+ * Find an attribute in an ntfs inode.  On first search @ctx->ntfs_ino must
  * be the base mft record and @ctx must have been obtained from a call to
- * get_attr_search_ctx().
+ * ntfs_attr_get_search_ctx().
  *
  * This function transparently handles attribute lists and @ctx is used to
  * continue searches where they were left off at.
  *
  * After finishing with the attribute/mft record you need to call
- * put_attr_search_ctx() to cleanup the search context (unmapping any mapped
- * inodes, etc).
+ * ntfs_attr_put_search_ctx() to cleanup the search context (unmapping any
+ * mapped inodes, etc).
+ *
+ * Return 0 if the search was successful and -errno if not.
  *
- * Return TRUE if the search was successful and FALSE if not. When TRUE,
- * @ctx->attr is the found attribute and it is in mft record @ctx->mrec. When
- * FALSE, @ctx->attr is the attribute which collates just after the attribute
- * being searched for, i.e. if one wants to add the attribute to the mft
- * record this is the correct place to insert it into.
+ * When 0, @ctx->attr is the found attribute and it is in mft record
+ * @ctx->mrec.  If an attribute list attribute is present, @ctx->al_entry is
+ * the attribute list entry of the found attribute.
+ *
+ * When -ENOENT, @ctx->attr is the attribute which collates just after the
+ * attribute being searched for, i.e. if one wants to add the attribute to the
+ * mft record this is the correct place to insert it into.  If an attribute
+ * list attribute is present, @ctx->al_entry is the attribute list entry which
+ * collates just after the attribute list entry of the attribute being searched
+ * for, i.e. if one wants to add the attribute to the mft record this is the
+ * correct place to insert its attribute list entry into.
+ *
+ * When -errno != -ENOENT, an error occured during the lookup.  @ctx->attr is
+ * then undefined and in particular you should not rely on it not changing.
  */
-BOOL lookup_attr(const ATTR_TYPES type, const ntfschar *name,
+int ntfs_attr_lookup(const ATTR_TYPE type, const ntfschar *name,
 		const u32 name_len, const IGNORE_CASE_BOOL ic,
 		const VCN lowest_vcn, const u8 *val, const u32 val_len,
-		attr_search_context *ctx)
+		ntfs_attr_search_ctx *ctx)
 {
 	ntfs_inode *base_ni;
 
@@ -1637,21 +1816,22 @@
 		base_ni = ctx->ntfs_ino;
 	/* Sanity check, just for debugging really. */
 	BUG_ON(!base_ni);
-	if (!NInoAttrList(base_ni))
-		return find_attr(type, name, name_len, ic, val, val_len, ctx);
-	return find_external_attr(type, name, name_len, ic, lowest_vcn, val,
-			val_len, ctx);
+	if (!NInoAttrList(base_ni) || type == AT_ATTRIBUTE_LIST)
+		return ntfs_attr_find(type, name, name_len, ic, val, val_len,
+				ctx);
+	return ntfs_external_attr_find(type, name, name_len, ic, lowest_vcn,
+			val, val_len, ctx);
 }
 
 /**
- * init_attr_search_ctx - initialize an attribute search context
+ * ntfs_attr_init_search_ctx - initialize an attribute search context
  * @ctx:	attribute search context to initialize
  * @ni:		ntfs inode with which to initialize the search context
  * @mrec:	mft record with which to initialize the search context
  *
  * Initialize the attribute search context @ctx with @ni and @mrec.
  */
-static inline void init_attr_search_ctx(attr_search_context *ctx,
+static inline void ntfs_attr_init_search_ctx(ntfs_attr_search_ctx *ctx,
 		ntfs_inode *ni, MFT_RECORD *mrec)
 {
 	ctx->mrec = mrec;
@@ -1666,7 +1846,7 @@
 }
 
 /**
- * reinit_attr_search_ctx - reinitialize an attribute search context
+ * ntfs_attr_reinit_search_ctx - reinitialize an attribute search context
  * @ctx:	attribute search context to reinitialize
  *
  * Reinitialize the attribute search context @ctx, unmapping an associated
@@ -1675,7 +1855,7 @@
  * This is used when a search for a new attribute is being started to reset
  * the search context to the beginning.
  */
-void reinit_attr_search_ctx(attr_search_context *ctx)
+void ntfs_attr_reinit_search_ctx(ntfs_attr_search_ctx *ctx)
 {
 	if (likely(!ctx->base_ntfs_ino)) {
 		/* No attribute list. */
@@ -1683,44 +1863,48 @@
 		/* Sanity checks are performed elsewhere. */
 		ctx->attr = (ATTR_RECORD*)((u8*)ctx->mrec +
 				le16_to_cpu(ctx->mrec->attrs_offset));
+		/*
+		 * This needs resetting due to ntfs_external_attr_find() which
+		 * can leave it set despite having zeroed ctx->base_ntfs_ino.
+		 */
+		ctx->al_entry = NULL;
 		return;
 	} /* Attribute list. */
 	if (ctx->ntfs_ino != ctx->base_ntfs_ino)
 		unmap_extent_mft_record(ctx->ntfs_ino);
-	init_attr_search_ctx(ctx, ctx->base_ntfs_ino, ctx->base_mrec);
+	ntfs_attr_init_search_ctx(ctx, ctx->base_ntfs_ino, ctx->base_mrec);
 	return;
 }
 
 /**
- * get_attr_search_ctx - allocate and initialize a new attribute search context
+ * ntfs_attr_get_search_ctx - allocate/initialize a new attribute search context
  * @ni:		ntfs inode with which to initialize the search context
  * @mrec:	mft record with which to initialize the search context
  *
  * Allocate a new attribute search context, initialize it with @ni and @mrec,
  * and return it. Return NULL if allocation failed.
  */
-attr_search_context *get_attr_search_ctx(ntfs_inode *ni, MFT_RECORD *mrec)
+ntfs_attr_search_ctx *ntfs_attr_get_search_ctx(ntfs_inode *ni, MFT_RECORD *mrec)
 {
-	attr_search_context *ctx;
+	ntfs_attr_search_ctx *ctx;
 
 	ctx = kmem_cache_alloc(ntfs_attr_ctx_cache, SLAB_NOFS);
 	if (ctx)
-		init_attr_search_ctx(ctx, ni, mrec);
+		ntfs_attr_init_search_ctx(ctx, ni, mrec);
 	return ctx;
 }
 
 /**
- * put_attr_search_ctx - release an attribute search context
+ * ntfs_attr_put_search_ctx - release an attribute search context
  * @ctx:	attribute search context to free
  *
  * Release the attribute search context @ctx, unmapping an associated extent
  * mft record if present.
  */
-void put_attr_search_ctx(attr_search_context *ctx)
+void ntfs_attr_put_search_ctx(ntfs_attr_search_ctx *ctx)
 {
 	if (ctx->base_ntfs_ino && ctx->ntfs_ino != ctx->base_ntfs_ino)
 		unmap_extent_mft_record(ctx->ntfs_ino);
 	kmem_cache_free(ntfs_attr_ctx_cache, ctx);
 	return;
 }
-
diff -Nru a/fs/ntfs/attrib.h b/fs/ntfs/attrib.h
--- a/fs/ntfs/attrib.h	2004-10-18 14:56:29 -07:00
+++ b/fs/ntfs/attrib.h	2004-10-18 14:56:29 -07:00
@@ -30,7 +30,7 @@
 #include "types.h"
 #include "layout.h"
 
-static inline void init_run_list(run_list *rl)
+static inline void init_runlist(runlist *rl)
 {
 	rl->rl = NULL;
 	init_rwsem(&rl->lock);
@@ -40,14 +40,13 @@
 	LCN_HOLE		= -1,	/* Keep this as highest value or die! */
 	LCN_RL_NOT_MAPPED	= -2,
 	LCN_ENOENT		= -3,
-	LCN_EINVAL		= -4,
 } LCN_SPECIAL_VALUES;
 
 /**
- * attr_search_context - used in attribute search functions
+ * ntfs_attr_search_ctx - used in attribute search functions
  * @mrec:	buffer containing mft record to search
  * @attr:	attribute record in @mrec where to begin/continue search
- * @is_first:	if true lookup_attr() begins search with @attr, else after @attr
+ * @is_first:	if true ntfs_attr_lookup() begins search with @attr, else after
  *
  * Structure must be initialized to zero before the first call to one of the
  * attribute search functions. Initialize @mrec to point to the mft record to
@@ -70,37 +69,36 @@
 	ntfs_inode *base_ntfs_ino;
 	MFT_RECORD *base_mrec;
 	ATTR_RECORD *base_attr;
-} attr_search_context;
+} ntfs_attr_search_ctx;
 
-extern run_list_element *decompress_mapping_pairs(const ntfs_volume *vol,
-		const ATTR_RECORD *attr, run_list_element *old_rl);
+extern runlist_element *decompress_mapping_pairs(const ntfs_volume *vol,
+		const ATTR_RECORD *attr, runlist_element *old_rl);
 
-extern int map_run_list(ntfs_inode *ni, VCN vcn);
+extern int ntfs_map_runlist(ntfs_inode *ni, VCN vcn);
 
-extern LCN vcn_to_lcn(const run_list_element *rl, const VCN vcn);
+extern LCN ntfs_vcn_to_lcn(const runlist_element *rl, const VCN vcn);
 
-extern BOOL find_attr(const ATTR_TYPES type, const ntfschar *name,
-		const u32 name_len, const IGNORE_CASE_BOOL ic, const u8 *val,
-		const u32 val_len, attr_search_context *ctx);
+extern runlist_element *ntfs_find_vcn(ntfs_inode *ni, const VCN vcn,
+		const BOOL need_write);
 
-BOOL lookup_attr(const ATTR_TYPES type, const ntfschar *name,
+int ntfs_attr_lookup(const ATTR_TYPE type, const ntfschar *name,
 		const u32 name_len, const IGNORE_CASE_BOOL ic,
 		const VCN lowest_vcn, const u8 *val, const u32 val_len,
-		attr_search_context *ctx);
+		ntfs_attr_search_ctx *ctx);
 
-extern int load_attribute_list(ntfs_volume *vol, run_list *rl, u8 *al_start,
+extern int load_attribute_list(ntfs_volume *vol, runlist *rl, u8 *al_start,
 		const s64 size, const s64 initialized_size);
 
-static inline s64 attribute_value_length(const ATTR_RECORD *a)
+static inline s64 ntfs_attr_size(const ATTR_RECORD *a)
 {
 	if (!a->non_resident)
 		return (s64)le32_to_cpu(a->data.resident.value_length);
 	return sle64_to_cpu(a->data.non_resident.data_size);
 }
 
-extern void reinit_attr_search_ctx(attr_search_context *ctx);
-extern attr_search_context *get_attr_search_ctx(ntfs_inode *ni,
+extern void ntfs_attr_reinit_search_ctx(ntfs_attr_search_ctx *ctx);
+extern ntfs_attr_search_ctx *ntfs_attr_get_search_ctx(ntfs_inode *ni,
 		MFT_RECORD *mrec);
-extern void put_attr_search_ctx(attr_search_context *ctx);
+extern void ntfs_attr_put_search_ctx(ntfs_attr_search_ctx *ctx);
 
 #endif /* _LINUX_NTFS_ATTRIB_H */
diff -Nru a/fs/ntfs/bitmap.c b/fs/ntfs/bitmap.c
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/fs/ntfs/bitmap.c	2004-10-18 14:57:23 -07:00
@@ -0,0 +1,191 @@
+/*
+ * bitmap.c - NTFS kernel bitmap handling.  Part of the Linux-NTFS project.
+ *
+ * Copyright (c) 2004 Anton Altaparmakov
+ *
+ * This program/include file 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/include file 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 (in the main directory of the Linux-NTFS
+ * distribution in the file COPYING); if not, write to the Free Software
+ * Foundation,Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#ifdef NTFS_RW
+
+#include <linux/pagemap.h>
+
+#include "bitmap.h"
+#include "debug.h"
+#include "ntfs.h"
+
+/**
+ * __ntfs_bitmap_set_bits_in_run - set a run of bits in a bitmap to a value
+ * @vi:			vfs inode describing the bitmap
+ * @start_bit:		first bit to set
+ * @count:		number of bits to set
+ * @value:		value to set the bits to (i.e. 0 or 1)
+ * @is_rollback:	if TRUE this is a rollback operation
+ *
+ * Set @count bits starting at bit @start_bit in the bitmap described by the
+ * vfs inode @vi to @value, where @value is either 0 or 1.
+ *
+ * @is_rollback should always be FALSE, it is for internal use to rollback
+ * errors.  You probably want to use ntfs_bitmap_set_bits_in_run() instead.
+ *
+ * Return 0 on success and -errno on error.
+ */
+int __ntfs_bitmap_set_bits_in_run(struct inode *vi, const s64 start_bit,
+		const s64 count, const u8 value, const BOOL is_rollback)
+{
+	s64 cnt = count;
+	pgoff_t index, end_index;
+	struct address_space *mapping;
+	struct page *page;
+	u8 *kaddr;
+	int pos, len;
+	u8 bit;
+
+	BUG_ON(!vi);
+	ntfs_debug("Entering for i_ino 0x%lx, start_bit 0x%llx, count 0x%llx, "
+			"value %u.%s", vi->i_ino, (unsigned long long)start_bit,
+			(unsigned long long)cnt, (unsigned int)value,
+			is_rollback ? " (rollback)" : "");
+	BUG_ON(start_bit < 0);
+	BUG_ON(cnt < 0);
+	BUG_ON(value > 1);
+	/*
+	 * Calculate the indices for the pages containing the first and last
+	 * bits, i.e. @start_bit and @start_bit + @cnt - 1, respectively.
+	 */
+	index = start_bit >> (3 + PAGE_CACHE_SHIFT);
+	end_index = (start_bit + cnt - 1) >> (3 + PAGE_CACHE_SHIFT);
+
+	/* Get the page containing the first bit (@start_bit). */
+	mapping = vi->i_mapping;
+	page = ntfs_map_page(mapping, index);
+	if (IS_ERR(page)) {
+		if (!is_rollback)
+			ntfs_error(vi->i_sb, "Failed to map first page (error "
+					"%li), aborting.", PTR_ERR(page));
+		return PTR_ERR(page);
+	}
+	kaddr = page_address(page);
+
+	/* Set @pos to the position of the byte containing @start_bit. */
+	pos = (start_bit >> 3) & ~PAGE_CACHE_MASK;
+
+	/* Calculate the position of @start_bit in the first byte. */
+	bit = start_bit & 7;
+
+	/* If the first byte is partial, modify the appropriate bits in it. */
+	if (bit) {
+		u8 *byte = kaddr + pos;
+		while ((bit & 7) && cnt--) {
+			if (value)
+				*byte |= 1 << bit++;
+			else
+				*byte &= ~(1 << bit++);
+		}
+		/* If we are done, unmap the page and return success. */
+		if (!cnt)
+			goto done;
+
+		/* Update @pos to the new position. */
+		pos++;
+	}
+	/*
+	 * Depending on @value, modify all remaining whole bytes in the page up
+	 * to @cnt.
+	 */
+	len = min_t(s64, cnt >> 3, PAGE_CACHE_SIZE - pos);
+	memset(kaddr + pos, value ? 0xff : 0, len);
+	cnt -= len << 3;
+
+	/* Update @len to point to the first not-done byte in the page. */
+	if (cnt < 8)
+		len += pos;
+
+	/* If we are not in the last page, deal with all subsequent pages. */
+	while (index < end_index) {
+		BUG_ON(cnt <= 0);
+
+		/* Update @index and get the next page. */
+		flush_dcache_page(page);
+		set_page_dirty(page);
+		ntfs_unmap_page(page);
+		page = ntfs_map_page(mapping, ++index);
+		if (IS_ERR(page))
+			goto rollback;
+		kaddr = page_address(page);
+		/*
+		 * Depending on @value, modify all remaining whole bytes in the
+		 * page up to @cnt.
+		 */
+		len = min_t(s64, cnt >> 3, PAGE_CACHE_SIZE);
+		memset(kaddr, value ? 0xff : 0, len);
+		cnt -= len << 3;
+	}
+	/*
+	 * The currently mapped page is the last one.  If the last byte is
+	 * partial, modify the appropriate bits in it.  Note, @len is the
+	 * position of the last byte inside the page.
+	 */
+	if (cnt) {
+		u8 *byte;
+
+		BUG_ON(cnt > 7);
+
+		bit = cnt;
+		byte = kaddr + len;
+		while (bit--) {
+			if (value)
+				*byte |= 1 << bit;
+			else
+				*byte &= ~(1 << bit);
+		}
+	}
+done:
+	/* We are done.  Unmap the page and return success. */
+	flush_dcache_page(page);
+	set_page_dirty(page);
+	ntfs_unmap_page(page);
+	ntfs_debug("Done.");
+	return 0;
+rollback:
+	/*
+	 * Current state:
+	 *	- no pages are mapped
+	 *	- @count - @cnt is the number of bits that have been modified
+	 */
+	if (is_rollback)
+		return PTR_ERR(page);
+	if (count != cnt)
+		pos = __ntfs_bitmap_set_bits_in_run(vi, start_bit, count - cnt,
+				value ? 0 : 1, TRUE);
+	else
+		pos = 0;
+	if (!pos) {
+		/* Rollback was successful. */
+		ntfs_error(vi->i_sb, "Failed to map subsequent page (error "
+				"%li), aborting.", PTR_ERR(page));
+	} else {
+		/* Rollback failed. */
+		ntfs_error(vi->i_sb, "Failed to map subsequent page (error "
+				"%li) and rollback failed (error %i).  "
+				"Aborting and leaving inconsistent metadata.  "
+				"Unmount and run chkdsk.", PTR_ERR(page), pos);
+		NVolSetErrors(NTFS_SB(vi->i_sb));
+	}
+	return PTR_ERR(page);
+}
+
+#endif /* NTFS_RW */
diff -Nru a/fs/ntfs/bitmap.h b/fs/ntfs/bitmap.h
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/fs/ntfs/bitmap.h	2004-10-18 14:57:23 -07:00
@@ -0,0 +1,118 @@
+/*
+ * bitmap.h - Defines for NTFS kernel bitmap handling.  Part of the Linux-NTFS
+ *	      project.
+ *
+ * Copyright (c) 2004 Anton Altaparmakov
+ *
+ * This program/include file 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/include file 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 (in the main directory of the Linux-NTFS
+ * distribution in the file COPYING); if not, write to the Free Software
+ * Foundation,Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#ifndef _LINUX_NTFS_BITMAP_H
+#define _LINUX_NTFS_BITMAP_H
+
+#ifdef NTFS_RW
+
+#include <linux/fs.h>
+
+#include "types.h"
+
+extern int __ntfs_bitmap_set_bits_in_run(struct inode *vi, const s64 start_bit,
+		const s64 count, const u8 value, const BOOL is_rollback);
+
+/**
+ * ntfs_bitmap_set_bits_in_run - set a run of bits in a bitmap to a value
+ * @vi:			vfs inode describing the bitmap
+ * @start_bit:		first bit to set
+ * @count:		number of bits to set
+ * @value:		value to set the bits to (i.e. 0 or 1)
+ *
+ * Set @count bits starting at bit @start_bit in the bitmap described by the
+ * vfs inode @vi to @value, where @value is either 0 or 1.
+ *
+ * Return 0 on success and -errno on error.
+ */
+static inline int ntfs_bitmap_set_bits_in_run(struct inode *vi,
+		const s64 start_bit, const s64 count, const u8 value)
+{
+	return __ntfs_bitmap_set_bits_in_run(vi, start_bit, count, value,
+			FALSE);
+}
+
+/**
+ * ntfs_bitmap_set_run - set a run of bits in a bitmap
+ * @vi:		vfs inode describing the bitmap
+ * @start_bit:	first bit to set
+ * @count:	number of bits to set
+ *
+ * Set @count bits starting at bit @start_bit in the bitmap described by the
+ * vfs inode @vi.
+ *
+ * Return 0 on success and -errno on error.
+ */
+static inline int ntfs_bitmap_set_run(struct inode *vi, const s64 start_bit,
+		const s64 count)
+{
+	return ntfs_bitmap_set_bits_in_run(vi, start_bit, count, 1);
+}
+
+/**
+ * ntfs_bitmap_clear_run - clear a run of bits in a bitmap
+ * @vi:		vfs inode describing the bitmap
+ * @start_bit:	first bit to clear
+ * @count:	number of bits to clear
+ *
+ * Clear @count bits starting at bit @start_bit in the bitmap described by the
+ * vfs inode @vi.
+ *
+ * Return 0 on success and -errno on error.
+ */
+static inline int ntfs_bitmap_clear_run(struct inode *vi, const s64 start_bit,
+		const s64 count)
+{
+	return ntfs_bitmap_set_bits_in_run(vi, start_bit, count, 0);
+}
+
+/**
+ * ntfs_bitmap_set_bit - set a bit in a bitmap
+ * @vi:		vfs inode describing the bitmap
+ * @bit:	bit to set
+ *
+ * Set bit @bit in the bitmap described by the vfs inode @vi.
+ *
+ * Return 0 on success and -errno on error.
+ */
+static inline int ntfs_bitmap_set_bit(struct inode *vi, const s64 bit)
+{
+	return ntfs_bitmap_set_run(vi, bit, 1);
+}
+
+/**
+ * ntfs_bitmap_clear_bit - clear a bit in a bitmap
+ * @vi:		vfs inode describing the bitmap
+ * @bit:	bit to clear
+ *
+ * Clear bit @bit in the bitmap described by the vfs inode @vi.
+ *
+ * Return 0 on success and -errno on error.
+ */
+static inline int ntfs_bitmap_clear_bit(struct inode *vi, const s64 bit)
+{
+	return ntfs_bitmap_clear_run(vi, bit, 1);
+}
+
+#endif /* NTFS_RW */
+
+#endif /* defined _LINUX_NTFS_BITMAP_H */
diff -Nru a/fs/ntfs/collate.c b/fs/ntfs/collate.c
--- a/fs/ntfs/collate.c	2004-10-18 14:56:50 -07:00
+++ b/fs/ntfs/collate.c	2004-10-18 14:56:50 -07:00
@@ -97,24 +97,26 @@
  * For speed we use the collation rule @cr as an index into two tables of
  * function pointers to call the appropriate collation function.
  */
-int ntfs_collate(ntfs_volume *vol, COLLATION_RULES cr,
+int ntfs_collate(ntfs_volume *vol, COLLATION_RULE cr,
 		const void *data1, const int data1_len,
 		const void *data2, const int data2_len) {
+	int i;
+
 	ntfs_debug("Entering.");
 	/*
 	 * FIXME:  At the moment we only support COLLATION_BINARY and
 	 * COLLATION_NTOFS_ULONG, so we BUG() for everything else for now.
 	 */
 	BUG_ON(cr != COLLATION_BINARY && cr != COLLATION_NTOFS_ULONG);
-	cr = le32_to_cpu(cr);
-	BUG_ON(cr < 0);
-	if (cr <= 0x02)
-		return ntfs_do_collate0x0[cr](vol, data1, data1_len,
+	i = le32_to_cpu(cr);
+	BUG_ON(i < 0);
+	if (i <= 0x02)
+		return ntfs_do_collate0x0[i](vol, data1, data1_len,
 				data2, data2_len);
-	BUG_ON(cr < 0x10);
-	cr -= 0x10;
-	if (likely(cr <= 3))
-		return ntfs_do_collate0x1[cr](vol, data1, data1_len,
+	BUG_ON(i < 0x10);
+	i -= 0x10;
+	if (likely(i <= 3))
+		return ntfs_do_collate0x1[i](vol, data1, data1_len,
 				data2, data2_len);
 	BUG();
 	return 0;
diff -Nru a/fs/ntfs/collate.h b/fs/ntfs/collate.h
--- a/fs/ntfs/collate.h	2004-10-18 14:55:54 -07:00
+++ b/fs/ntfs/collate.h	2004-10-18 14:55:54 -07:00
@@ -26,7 +26,9 @@
 #include "types.h"
 #include "volume.h"
 
-static inline BOOL ntfs_is_collation_rule_supported(COLLATION_RULES cr) {
+static inline BOOL ntfs_is_collation_rule_supported(COLLATION_RULE cr) {
+	int i;
+
 	/*
 	 * FIXME:  At the moment we only support COLLATION_BINARY and
 	 * COLLATION_NTOFS_ULONG, so we return false for everything else for
@@ -34,14 +36,14 @@
 	 */
 	if (unlikely(cr != COLLATION_BINARY && cr != COLLATION_NTOFS_ULONG))
 		return FALSE;
-	cr = le32_to_cpu(cr);
-	if (likely(((cr >= 0) && (cr <= 0x02)) ||
-			((cr >= 0x10) && (cr <= 0x13))))
+	i = le32_to_cpu(cr);
+	if (likely(((i >= 0) && (i <= 0x02)) ||
+			((i >= 0x10) && (i <= 0x13))))
 		return TRUE;
 	return FALSE;
 }
 
-extern int ntfs_collate(ntfs_volume *vol, COLLATION_RULES cr,
+extern int ntfs_collate(ntfs_volume *vol, COLLATION_RULE cr,
 		const void *data1, const int data1_len,
 		const void *data2, const int data2_len);
 
diff -Nru a/fs/ntfs/compress.c b/fs/ntfs/compress.c
--- a/fs/ntfs/compress.c	2004-10-18 14:56:32 -07:00
+++ b/fs/ntfs/compress.c	2004-10-18 14:56:32 -07:00
@@ -203,7 +203,7 @@
 	 * position in the compression block is one byte before its end so the
 	 * first two checks do not detect it.
 	 */
-	if (cb == cb_end || !le16_to_cpup((u16*)cb) ||
+	if (cb == cb_end || !le16_to_cpup((le16*)cb) ||
 			(*dest_index == dest_max_index &&
 			*dest_ofs == dest_max_ofs)) {
 		int i;
@@ -255,7 +255,7 @@
 
 	/* Setup the current sub-block source pointers and validate range. */
 	cb_sb_start = cb;
-	cb_sb_end = cb_sb_start + (le16_to_cpup((u16*)cb) & NTFS_SB_SIZE_MASK)
+	cb_sb_end = cb_sb_start + (le16_to_cpup((le16*)cb) & NTFS_SB_SIZE_MASK)
 			+ 3;
 	if (cb_sb_end > cb_end)
 		goto return_overflow;
@@ -277,7 +277,7 @@
 	dp_addr = (u8*)page_address(dp) + do_sb_start;
 
 	/* Now, we are ready to process the current sub-block (sb). */
-	if (!(le16_to_cpup((u16*)cb) & NTFS_SB_IS_COMPRESSED)) {
+	if (!(le16_to_cpup((le16*)cb) & NTFS_SB_IS_COMPRESSED)) {
 		ntfs_debug("Found uncompressed sub-block.");
 		/* This sb is not compressed, just copy it into destination. */
 
@@ -382,7 +382,7 @@
 			lg++;
 
 		/* Get the phrase token into i. */
-		pt = le16_to_cpup((u16*)cb);
+		pt = le16_to_cpup((le16*)cb);
 
 		/*
 		 * Calculate starting position of the byte sequence in
@@ -478,7 +478,7 @@
 	ntfs_inode *ni = NTFS_I(mapping->host);
 	ntfs_volume *vol = ni->vol;
 	struct super_block *sb = vol->sb;
-	run_list_element *rl;
+	runlist_element *rl;
 	unsigned long block_size = sb->s_blocksize;
 	unsigned char block_size_bits = sb->s_blocksize_bits;
 	u8 *cb, *cb_pos, *cb_end;
@@ -575,7 +575,7 @@
 	}
 
 	/*
-	 * We have the run list, and all the destination pages we need to fill.
+	 * We have the runlist, and all the destination pages we need to fill.
 	 * Now read the first compression block.
 	 */
 	cur_page = 0;
@@ -593,14 +593,14 @@
 
 		if (!rl) {
 lock_retry_remap:
-			down_read(&ni->run_list.lock);
-			rl = ni->run_list.rl;
+			down_read(&ni->runlist.lock);
+			rl = ni->runlist.rl;
 		}
 		if (likely(rl != NULL)) {
 			/* Seek to element containing target vcn. */
 			while (rl->length && rl[1].vcn <= vcn)
 				rl++;
-			lcn = vcn_to_lcn(rl, vcn);
+			lcn = ntfs_vcn_to_lcn(rl, vcn);
 		} else
 			lcn = (LCN)LCN_RL_NOT_MAPPED;
 		ntfs_debug("Reading vcn = 0x%llx, lcn = 0x%llx.",
@@ -617,11 +617,11 @@
 				goto rl_err;
 			is_retry = TRUE;
 			/*
-			 * Attempt to map run list, dropping lock for the
+			 * Attempt to map runlist, dropping lock for the
 			 * duration.
 			 */
-			up_read(&ni->run_list.lock);
-			if (!map_run_list(ni, vcn))
+			up_read(&ni->runlist.lock);
+			if (!ntfs_map_runlist(ni, vcn))
 				goto lock_retry_remap;
 			goto map_rl_err;
 		}
@@ -638,7 +638,7 @@
 
 	/* Release the lock if we took it. */
 	if (rl)
-		up_read(&ni->run_list.lock);
+		up_read(&ni->runlist.lock);
 
 	/* Setup and initiate io on all buffer heads. */
 	for (i = 0; i < nr_bhs; i++) {
@@ -920,18 +920,18 @@
 	goto err_out;
 
 map_rl_err:
-	ntfs_error(vol->sb, "map_run_list() failed. Cannot read compression "
-			"block.");
+	ntfs_error(vol->sb, "ntfs_map_runlist() failed. Cannot read "
+			"compression block.");
 	goto err_out;
 
 rl_err:
-	up_read(&ni->run_list.lock);
-	ntfs_error(vol->sb, "vcn_to_lcn() failed. Cannot read compression "
-			"block.");
+	up_read(&ni->runlist.lock);
+	ntfs_error(vol->sb, "ntfs_vcn_to_lcn() failed. Cannot read "
+			"compression block.");
 	goto err_out;
 
 getblk_err:
-	up_read(&ni->run_list.lock);
+	up_read(&ni->runlist.lock);
 	ntfs_error(vol->sb, "getblk() failed. Cannot read compression block.");
 
 err_out:
diff -Nru a/fs/ntfs/debug.c b/fs/ntfs/debug.c
--- a/fs/ntfs/debug.c	2004-10-18 14:57:19 -07:00
+++ b/fs/ntfs/debug.c	2004-10-18 14:57:19 -07:00
@@ -127,22 +127,21 @@
 	va_start(args, fmt);
 	vsnprintf(err_buf, sizeof(err_buf), fmt, args);
 	va_end(args);
-	printk(KERN_DEBUG "NTFS-fs DEBUG (%s, %d): %s: %s\n",
+	printk(KERN_DEBUG "NTFS-fs DEBUG (%s, %d): %s(): %s\n",
 		file, line, flen ? function : "", err_buf);
 	spin_unlock(&err_buf_lock);
 }
 
-/* Dump a run list. Caller has to provide synchronisation for @rl. */
-void ntfs_debug_dump_runlist(const run_list_element *rl)
+/* Dump a runlist. Caller has to provide synchronisation for @rl. */
+void ntfs_debug_dump_runlist(const runlist_element *rl)
 {
 	int i;
 	const char *lcn_str[5] = { "LCN_HOLE         ", "LCN_RL_NOT_MAPPED",
-				   "LCN_ENOENT       ", "LCN_EINVAL       ",
-				   "LCN_unknown      " };
+				   "LCN_ENOENT       ", "LCN_unknown      " };
 
 	if (!debug_msgs)
 		return;
-	printk(KERN_DEBUG "NTFS-fs DEBUG: Dumping run list (values "
+	printk(KERN_DEBUG "NTFS-fs DEBUG: Dumping runlist (values "
 			"in hex):\n");
 	if (!rl) {
 		printk(KERN_DEBUG "Run list not present.\n");
@@ -155,17 +154,17 @@
 		if (lcn < (LCN)0) {
 			int index = -lcn - 1;
 
-			if (index > -LCN_EINVAL - 1)
-				index = 4;
+			if (index > -LCN_ENOENT - 1)
+				index = 3;
 			printk(KERN_DEBUG "%-16Lx %s %-16Lx%s\n",
 				(rl + i)->vcn, lcn_str[index],
 				(rl + i)->length, (rl + i)->length ?
-				"" : " (run list end)");
+				"" : " (runlist end)");
 		} else
 			printk(KERN_DEBUG "%-16Lx %-16Lx  %-16Lx%s\n",
 				(rl + i)->vcn, (rl + i)->lcn,
 				(rl + i)->length, (rl + i)->length ?
-				"" : " (run list end)");
+				"" : " (runlist end)");
 		if (!(rl + i)->length)
 			break;
 	}
diff -Nru a/fs/ntfs/debug.h b/fs/ntfs/debug.h
--- a/fs/ntfs/debug.h	2004-10-18 14:56:48 -07:00
+++ b/fs/ntfs/debug.h	2004-10-18 14:56:48 -07:00
@@ -51,7 +51,7 @@
 #define ntfs_debug(f, a...)						\
 	__ntfs_debug(__FILE__, __LINE__, __FUNCTION__, f, ##a)
 
-extern void ntfs_debug_dump_runlist(const run_list_element *rl);
+extern void ntfs_debug_dump_runlist(const runlist_element *rl);
 
 #else	/* !DEBUG */
 
diff -Nru a/fs/ntfs/dir.c b/fs/ntfs/dir.c
--- a/fs/ntfs/dir.c	2004-10-18 14:56:28 -07:00
+++ b/fs/ntfs/dir.c	2004-10-18 14:56:28 -07:00
@@ -28,8 +28,7 @@
  * The little endian Unicode string $I30 as a global constant.
  */
 ntfschar I30[5] = { const_cpu_to_le16('$'), const_cpu_to_le16('I'),
-		const_cpu_to_le16('3'),	const_cpu_to_le16('0'),
-		const_cpu_to_le16(0) };
+		const_cpu_to_le16('3'),	const_cpu_to_le16('0'), 0 };
 
 /**
  * ntfs_lookup_inode_by_name - find an inode in a directory given its name
@@ -83,7 +82,7 @@
 	INDEX_ALLOCATION *ia;
 	u8 *index_end;
 	u64 mref;
-	attr_search_context *ctx;
+	ntfs_attr_search_ctx *ctx;
 	int err, rc;
 	VCN vcn, old_vcn;
 	struct address_space *ia_mapping;
@@ -95,22 +94,26 @@
 	BUG_ON(NInoAttr(dir_ni));
 	/* Get hold of the mft record for the directory. */
 	m = map_mft_record(dir_ni);
-	if (unlikely(IS_ERR(m))) {
+	if (IS_ERR(m)) {
 		ntfs_error(sb, "map_mft_record() failed with error code %ld.",
 				-PTR_ERR(m));
 		return ERR_MREF(PTR_ERR(m));
 	}
-	ctx = get_attr_search_ctx(dir_ni, m);
+	ctx = ntfs_attr_get_search_ctx(dir_ni, m);
 	if (unlikely(!ctx)) {
 		err = -ENOMEM;
 		goto err_out;
 	}
 	/* Find the index root attribute in the mft record. */
-	if (!lookup_attr(AT_INDEX_ROOT, I30, 4, CASE_SENSITIVE, 0, NULL, 0,
-			ctx)) {
-		ntfs_error(sb, "Index root attribute missing in directory "
-				"inode 0x%lx.", dir_ni->mft_no);
-		err = -EIO;
+	err = ntfs_attr_lookup(AT_INDEX_ROOT, I30, 4, CASE_SENSITIVE, 0, NULL,
+			0, ctx);
+	if (unlikely(err)) {
+		if (err == -ENOENT) {
+			ntfs_error(sb, "Index root attribute missing in "
+					"directory inode 0x%lx.",
+					dir_ni->mft_no);
+			err = -EIO;
+		}
 		goto err_out;
 	}
 	/* Get to the index root value (it's been verified in read_inode). */
@@ -179,7 +182,7 @@
 				*res = NULL;
 			}
 			mref = le64_to_cpu(ie->data.dir.indexed_file);
-			put_attr_search_ctx(ctx);
+			ntfs_attr_put_search_ctx(ctx);
 			unmap_mft_record(dir_ni);
 			return mref;
 		}
@@ -278,7 +281,7 @@
 	 */
 	if (!(ie->flags & INDEX_ENTRY_NODE)) {
 		if (name) {
-			put_attr_search_ctx(ctx);
+			ntfs_attr_put_search_ctx(ctx);
 			unmap_mft_record(dir_ni);
 			return name->mref;
 		}
@@ -295,13 +298,13 @@
 		goto err_out;
 	}
 	/* Get the starting vcn of the index_block holding the child node. */
-	vcn = sle64_to_cpup((u8*)ie + le16_to_cpu(ie->length) - 8);
+	vcn = sle64_to_cpup((sle64*)((u8*)ie + le16_to_cpu(ie->length) - 8));
 	ia_mapping = VFS_I(dir_ni)->i_mapping;
 	/*
 	 * We are done with the index root and the mft record. Release them,
 	 * otherwise we deadlock with ntfs_map_page().
 	 */
-	put_attr_search_ctx(ctx);
+	ntfs_attr_put_search_ctx(ctx);
 	unmap_mft_record(dir_ni);
 	m = NULL;
 	ctx = NULL;
@@ -547,7 +550,8 @@
 		}
 		/* Child node present, descend into it. */
 		old_vcn = vcn;
-		vcn = sle64_to_cpup((u8*)ie + le16_to_cpu(ie->length) - 8);
+		vcn = sle64_to_cpup((sle64*)((u8*)ie +
+				le16_to_cpu(ie->length) - 8));
 		if (vcn >= 0) {
 			/* If vcn is in the same page cache page as old_vcn we
 			 * recycle the mapped page. */
@@ -582,7 +586,7 @@
 	ntfs_unmap_page(page);
 err_out:
 	if (ctx)
-		put_attr_search_ctx(ctx);
+		ntfs_attr_put_search_ctx(ctx);
 	if (m)
 		unmap_mft_record(dir_ni);
 	if (name) {
@@ -634,7 +638,7 @@
 	INDEX_ALLOCATION *ia;
 	u8 *index_end;
 	u64 mref;
-	attr_search_context *ctx;
+	ntfs_attr_search_ctx *ctx;
 	int err, rc;
 	IGNORE_CASE_BOOL ic;
 	VCN vcn, old_vcn;
@@ -649,17 +653,21 @@
 				-PTR_ERR(m));
 		return ERR_MREF(PTR_ERR(m));
 	}
-	ctx = get_attr_search_ctx(dir_ni, m);
+	ctx = ntfs_attr_get_search_ctx(dir_ni, m);
 	if (!ctx) {
 		err = -ENOMEM;
 		goto err_out;
 	}
 	/* Find the index root attribute in the mft record. */
-	if (!lookup_attr(AT_INDEX_ROOT, I30, 4, CASE_SENSITIVE, 0, NULL, 0,
-			ctx)) {
-		ntfs_error(sb, "Index root attribute missing in directory "
-				"inode 0x%lx.", dir_ni->mft_no);
-		err = -EIO;
+	err = ntfs_attr_lookup(AT_INDEX_ROOT, I30, 4, CASE_SENSITIVE, 0, NULL,
+			0, ctx);
+	if (unlikely(err)) {
+		if (err == -ENOENT) {
+			ntfs_error(sb, "Index root attribute missing in "
+					"directory inode 0x%lx.",
+					dir_ni->mft_no);
+			err = -EIO;
+		}
 		goto err_out;
 	}
 	/* Get to the index root value (it's been verified in read_inode). */
@@ -710,7 +718,7 @@
 				vol->upcase, vol->upcase_len)) {
 found_it:
 			mref = le64_to_cpu(ie->data.dir.indexed_file);
-			put_attr_search_ctx(ctx);
+			ntfs_attr_put_search_ctx(ctx);
 			unmap_mft_record(dir_ni);
 			return mref;
 		}
@@ -776,7 +784,7 @@
 	 * We are done with the index root and the mft record. Release them,
 	 * otherwise we deadlock with ntfs_map_page().
 	 */
-	put_attr_search_ctx(ctx);
+	ntfs_attr_put_search_ctx(ctx);
 	unmap_mft_record(dir_ni);
 	m = NULL;
 	ctx = NULL;
@@ -979,7 +987,7 @@
 	ntfs_unmap_page(page);
 err_out:
 	if (ctx)
-		put_attr_search_ctx(ctx);
+		ntfs_attr_put_search_ctx(ctx);
 	if (m)
 		unmap_mft_record(dir_ni);
 	return ERR_MREF(err);
@@ -991,23 +999,11 @@
 
 #endif
 
-typedef union {
-	INDEX_ROOT *ir;
-	INDEX_ALLOCATION *ia;
-} index_union __attribute__ ((__transparent_union__));
-
-typedef enum {
-	INDEX_TYPE_ROOT,	/* index root */
-	INDEX_TYPE_ALLOCATION,	/* index allocation */
-} INDEX_TYPE;
-
 /**
  * ntfs_filldir - ntfs specific filldir method
  * @vol:	current ntfs volume
  * @fpos:	position in the directory
  * @ndir:	ntfs inode of current directory
- * @index_type:	specifies whether @iu is an index root or an index allocation
- * @iu:		index root or index allocation attribute to which @ie belongs
  * @ia_page:	page in which the index allocation buffer @ie is in resides
  * @ie:		current index entry
  * @name:	buffer to use for the converted name
@@ -1017,9 +1013,8 @@
  * Convert the Unicode @name to the loaded NLS and pass it to the @filldir
  * callback.
  *
- * If @index_type is INDEX_TYPE_ALLOCATION, @ia_page is the locked page
- * containing the index allocation block containing the index entry @ie.
- * Otherwise, @ia_page is NULL.
+ * If @ia_page is not NULL it is the locked page containing the index
+ * allocation block containing the index entry @ie.
  *
  * Note, we drop (and then reacquire) the page lock on @ia_page across the
  * @filldir() call otherwise we would deadlock with NFSd when it calls ->lookup
@@ -1027,9 +1022,8 @@
  * retake the lock if we are returning a non-zero value as ntfs_readdir()
  * would need to drop the lock immediately anyway.
  */
-static inline int ntfs_filldir(ntfs_volume *vol, loff_t *fpos,
-		ntfs_inode *ndir, const INDEX_TYPE index_type,
-		index_union iu, struct page *ia_page, INDEX_ENTRY *ie,
+static inline int ntfs_filldir(ntfs_volume *vol, loff_t fpos,
+		ntfs_inode *ndir, struct page *ia_page, INDEX_ENTRY *ie,
 		u8 *name, void *dirent, filldir_t filldir)
 {
 	unsigned long mref;
@@ -1037,14 +1031,6 @@
 	unsigned dt_type;
 	FILE_NAME_TYPE_FLAGS name_type;
 
-	/* Advance the position even if going to skip the entry. */
-	if (index_type == INDEX_TYPE_ALLOCATION)
-		*fpos = (u8*)ie - (u8*)iu.ia +
-				(sle64_to_cpu(iu.ia->index_block_vcn) <<
-				ndir->itype.index.vcn_size_bits) +
-				vol->mft_record_size;
-	else /* if (index_type == INDEX_TYPE_ROOT) */
-		*fpos = (u8*)ie - (u8*)iu.ir;
 	name_type = ie->key.file_name.file_name_type;
 	if (name_type == FILE_NAME_DOS) {
 		ntfs_debug("Skipping DOS name space entry.");
@@ -1076,14 +1062,14 @@
 	 * Drop the page lock otherwise we deadlock with NFS when it calls
 	 * ->lookup since ntfs_lookup() will lock the same page.
 	 */
-	if (index_type == INDEX_TYPE_ALLOCATION)
+	if (ia_page)
 		unlock_page(ia_page);
 	ntfs_debug("Calling filldir for %s with len %i, fpos 0x%llx, inode "
-			"0x%lx, DT_%s.", name, name_len, *fpos, mref,
+			"0x%lx, DT_%s.", name, name_len, fpos, mref,
 			dt_type == DT_DIR ? "DIR" : "REG");
-	rc = filldir(dirent, name, name_len, *fpos, mref, dt_type);
+	rc = filldir(dirent, name, name_len, fpos, mref, dt_type);
 	/* Relock the page but not if we are aborting ->readdir. */
-	if (!rc && index_type == INDEX_TYPE_ALLOCATION)
+	if (!rc && ia_page)
 		lock_page(ia_page);
 	return rc;
 }
@@ -1125,7 +1111,7 @@
 	struct address_space *ia_mapping, *bmp_mapping;
 	struct page *bmp_page = NULL, *ia_page = NULL;
 	u8 *kaddr, *bmp, *index_end;
-	attr_search_context *ctx;
+	ntfs_attr_search_ctx *ctx;
 
 	fpos = filp->f_pos;
 	ntfs_debug("Entering for inode 0x%lx, fpos 0x%llx.",
@@ -1170,12 +1156,12 @@
 		goto skip_index_root;
 	/* Get hold of the mft record for the directory. */
 	m = map_mft_record(ndir);
-	if (unlikely(IS_ERR(m))) {
+	if (IS_ERR(m)) {
 		err = PTR_ERR(m);
 		m = NULL;
 		goto err_out;
 	}
-	ctx = get_attr_search_ctx(ndir, m);
+	ctx = ntfs_attr_get_search_ctx(ndir, m);
 	if (unlikely(!ctx)) {
 		err = -ENOMEM;
 		goto err_out;
@@ -1183,8 +1169,9 @@
 	/* Get the offset into the index root attribute. */
 	ir_pos = (s64)fpos;
 	/* Find the index root attribute in the mft record. */
-	if (unlikely(!lookup_attr(AT_INDEX_ROOT, I30, 4, CASE_SENSITIVE, 0,
-			NULL, 0, ctx))) {
+	err = ntfs_attr_lookup(AT_INDEX_ROOT, I30, 4, CASE_SENSITIVE, 0, NULL,
+			0, ctx);
+	if (unlikely(err)) {
 		ntfs_error(sb, "Index root attribute missing in directory "
 				"inode 0x%lx.", vdir->i_ino);
 		goto err_out;
@@ -1208,7 +1195,7 @@
 	/* Copy the index root value (it has been verified in read_inode). */
 	memcpy(ir, (u8*)ctx->attr +
 			le16_to_cpu(ctx->attr->data.resident.value_offset), rc);
-	put_attr_search_ctx(ctx);
+	ntfs_attr_put_search_ctx(ctx);
 	unmap_mft_record(ndir);
 	ctx = NULL;
 	m = NULL;
@@ -1235,9 +1222,11 @@
 		/* Skip index root entry if continuing previous readdir. */
 		if (ir_pos > (u8*)ie - (u8*)ir)
 			continue;
+		/* Advance the position even if going to skip the entry. */
+		fpos = (u8*)ie - (u8*)ir;
 		/* Submit the name to the filldir callback. */
-		rc = ntfs_filldir(vol, &fpos, ndir, INDEX_TYPE_ROOT, ir, NULL,
-				ie, name, dirent, filldir);
+		rc = ntfs_filldir(vol, fpos, ndir, NULL, ie, name, dirent,
+				filldir);
 		if (rc) {
 			kfree(ir);
 			goto abort;
@@ -1261,7 +1250,7 @@
 	if (unlikely(!bmp_vi)) {
 		ntfs_debug("Inode 0x%lx, regetting index bitmap.", vdir->i_ino);
 		bmp_vi = ntfs_attr_iget(vdir, AT_BITMAP, I30, 4);
-		if (unlikely(IS_ERR(bmp_vi))) {
+		if (IS_ERR(bmp_vi)) {
 			ntfs_error(sb, "Failed to get bitmap attribute.");
 			err = PTR_ERR(bmp_vi);
 			goto err_out;
@@ -1286,7 +1275,7 @@
 			((PAGE_CACHE_SIZE * 8) - 1));
 	bmp_page = ntfs_map_page(bmp_mapping,
 			bmp_pos >> (3 + PAGE_CACHE_SHIFT));
-	if (unlikely(IS_ERR(bmp_page))) {
+	if (IS_ERR(bmp_page)) {
 		ntfs_error(sb, "Reading index bitmap failed.");
 		err = PTR_ERR(bmp_page);
 		bmp_page = NULL;
@@ -1327,7 +1316,7 @@
 		 * reading it from disk if necessary.
 		 */
 		ia_page = ntfs_map_page(ia_mapping, ia_pos >> PAGE_CACHE_SHIFT);
-		if (unlikely(IS_ERR(ia_page))) {
+		if (IS_ERR(ia_page)) {
 			ntfs_error(sb, "Reading index allocation data failed.");
 			err = PTR_ERR(ia_page);
 			ia_page = NULL;
@@ -1411,14 +1400,19 @@
 		/* Skip index block entry if continuing previous readdir. */
 		if (ia_pos - ia_start > (u8*)ie - (u8*)ia)
 			continue;
+		/* Advance the position even if going to skip the entry. */
+		fpos = (u8*)ie - (u8*)ia +
+				(sle64_to_cpu(ia->index_block_vcn) <<
+				ndir->itype.index.vcn_size_bits) +
+				vol->mft_record_size;
 		/*
 		 * Submit the name to the @filldir callback.  Note,
 		 * ntfs_filldir() drops the lock on @ia_page but it retakes it
 		 * before returning, unless a non-zero value is returned in
 		 * which case the page is left unlocked.
 		 */
-		rc = ntfs_filldir(vol, &fpos, ndir, INDEX_TYPE_ALLOCATION, ia,
-				ia_page, ie, name, dirent, filldir);
+		rc = ntfs_filldir(vol, fpos, ndir, ia_page, ie, name, dirent,
+				filldir);
 		if (rc) {
 			/* @ia_page is already unlocked in this case. */
 			ntfs_unmap_page(ia_page);
@@ -1460,7 +1454,7 @@
 	if (name)
 		kfree(name);
 	if (ctx)
-		put_attr_search_ctx(ctx);
+		ntfs_attr_put_search_ctx(ctx);
 	if (m)
 		unmap_mft_record(ndir);
 	if (!err)
@@ -1495,10 +1489,69 @@
 	return 0;
 }
 
+#ifdef NTFS_RW
+
+/**
+ * ntfs_dir_fsync - sync a directory to disk
+ * @filp:	directory to be synced
+ * @dentry:	dentry describing the directory to sync
+ * @datasync:	if non-zero only flush user data and not metadata
+ *
+ * Data integrity sync of a directory to disk.  Used for fsync, fdatasync, and
+ * msync system calls.  This function is based on file.c::ntfs_file_fsync().
+ *
+ * Write the mft record and all associated extent mft records as well as the
+ * $INDEX_ALLOCATION and $BITMAP attributes and then sync the block device.
+ *
+ * If @datasync is true, we do not wait on the inode(s) to be written out
+ * but we always wait on the page cache pages to be written out.
+ *
+ * Note: In the past @filp could be NULL so we ignore it as we don't need it
+ * anyway.
+ *
+ * Locking: Caller must hold i_sem on the inode.
+ *
+ * TODO: We should probably also write all attribute/index inodes associated
+ * with this inode but since we have no simple way of getting to them we ignore
+ * this problem for now.  We do write the $BITMAP attribute if it is present
+ * which is the important one for a directory so things are not too bad.
+ */
+static int ntfs_dir_fsync(struct file *filp, struct dentry *dentry,
+		int datasync)
+{
+	struct inode *vi = dentry->d_inode;
+	ntfs_inode *ni = NTFS_I(vi);
+	int err, ret;
+
+	ntfs_debug("Entering for inode 0x%lx.", vi->i_ino);
+	BUG_ON(!S_ISDIR(vi->i_mode));
+	if (NInoIndexAllocPresent(ni) && ni->itype.index.bmp_ino)
+		write_inode_now(ni->itype.index.bmp_ino, !datasync);
+	ret = ntfs_write_inode(vi, 1);
+	write_inode_now(vi, !datasync);
+	err = sync_blockdev(vi->i_sb->s_bdev);
+	if (unlikely(err && !ret))
+		ret = err;
+	if (likely(!ret))
+		ntfs_debug("Done.");
+	else
+		ntfs_warning(vi->i_sb, "Failed to f%ssync inode 0x%lx.  Error "
+				"%u.", datasync ? "data" : "", vi->i_ino, -ret);
+	return ret;
+}
+
+#endif /* NTFS_RW */
+
 struct file_operations ntfs_dir_ops = {
 	.llseek		= generic_file_llseek,	/* Seek inside directory. */
 	.read		= generic_read_dir,	/* Return -EISDIR. */
 	.readdir	= ntfs_readdir,		/* Read directory contents. */
+#ifdef NTFS_RW
+	.fsync		= ntfs_dir_fsync,	/* Sync a directory to disk. */
+	/*.aio_fsync	= ,*/			/* Sync all outstanding async
+						   i/o operations on a kiocb. */
+#endif /* NTFS_RW */
+	/*.ioctl	= ,*/			/* Perform function on the
+						   mounted filesystem. */
 	.open		= ntfs_dir_open,	/* Open directory. */
 };
-
diff -Nru a/fs/ntfs/endian.h b/fs/ntfs/endian.h
--- a/fs/ntfs/endian.h	2004-10-18 14:56:49 -07:00
+++ b/fs/ntfs/endian.h	2004-10-18 14:56:49 -07:00
@@ -24,24 +24,70 @@
 #define _LINUX_NTFS_ENDIAN_H
 
 #include <asm/byteorder.h>
+#include "types.h"
 
 /*
- * Signed endianness conversion defines.
+ * Signed endianness conversion functions.
  */
-#define sle16_to_cpu(x)		((s16)__le16_to_cpu((s16)(x)))
-#define sle32_to_cpu(x)		((s32)__le32_to_cpu((s32)(x)))
-#define sle64_to_cpu(x)		((s64)__le64_to_cpu((s64)(x)))
-
-#define sle16_to_cpup(x)	((s16)__le16_to_cpu(*(s16*)(x)))
-#define sle32_to_cpup(x)	((s32)__le32_to_cpu(*(s32*)(x)))
-#define sle64_to_cpup(x)	((s64)__le64_to_cpu(*(s64*)(x)))
-
-#define cpu_to_sle16(x)		((s16)__cpu_to_le16((s16)(x)))
-#define cpu_to_sle32(x)		((s32)__cpu_to_le32((s32)(x)))
-#define cpu_to_sle64(x)		((s64)__cpu_to_le64((s64)(x)))
-
-#define cpu_to_sle16p(x)	((s16)__cpu_to_le16(*(s16*)(x)))
-#define cpu_to_sle32p(x)	((s32)__cpu_to_le32(*(s32*)(x)))
-#define cpu_to_sle64p(x)	((s64)__cpu_to_le64(*(s64*)(x)))
+
+static inline s16 sle16_to_cpu(sle16 x)
+{
+	return le16_to_cpu((__force le16)x);
+}
+
+static inline s32 sle32_to_cpu(sle32 x)
+{
+	return le32_to_cpu((__force le32)x);
+}
+
+static inline s64 sle64_to_cpu(sle64 x)
+{
+	return le64_to_cpu((__force le64)x);
+}
+
+static inline s16 sle16_to_cpup(sle16 *x)
+{
+	return le16_to_cpu(*(__force le16*)x);
+}
+
+static inline s32 sle32_to_cpup(sle32 *x)
+{
+	return le32_to_cpu(*(__force le32*)x);
+}
+
+static inline s64 sle64_to_cpup(sle64 *x)
+{
+	return le64_to_cpu(*(__force le64*)x);
+}
+
+static inline sle16 cpu_to_sle16(s16 x)
+{
+	return (__force sle16)cpu_to_le16(x);
+}
+
+static inline sle32 cpu_to_sle32(s32 x)
+{
+	return (__force sle32)cpu_to_le32(x);
+}
+
+static inline sle64 cpu_to_sle64(s64 x)
+{
+	return (__force sle64)cpu_to_le64(x);
+}
+
+static inline sle16 cpu_to_sle16p(s16 *x)
+{
+	return (__force sle16)cpu_to_le16(*x);
+}
+
+static inline sle32 cpu_to_sle32p(s32 *x)
+{
+	return (__force sle32)cpu_to_le32(*x);
+}
+
+static inline sle64 cpu_to_sle64p(s64 *x)
+{
+	return (__force sle64)cpu_to_le64(*x);
+}
 
 #endif /* _LINUX_NTFS_ENDIAN_H */
diff -Nru a/fs/ntfs/file.c b/fs/ntfs/file.c
--- a/fs/ntfs/file.c	2004-10-18 14:56:50 -07:00
+++ b/fs/ntfs/file.c	2004-10-18 14:56:50 -07:00
@@ -48,26 +48,101 @@
 	return generic_file_open(vi, filp);
 }
 
+#ifdef NTFS_RW
+
+/**
+ * ntfs_file_fsync - sync a file to disk
+ * @filp:	file to be synced
+ * @dentry:	dentry describing the file to sync
+ * @datasync:	if non-zero only flush user data and not metadata
+ *
+ * Data integrity sync of a file to disk.  Used for fsync, fdatasync, and msync
+ * system calls.  This function is inspired by fs/buffer.c::file_fsync().
+ *
+ * If @datasync is false, write the mft record and all associated extent mft
+ * records as well as the $DATA attribute and then sync the block device.
+ *
+ * If @datasync is true and the attribute is non-resident, we skip the writing
+ * of the mft record and all associated extent mft records (this might still
+ * happen due to the write_inode_now() call).
+ *
+ * Also, if @datasync is true, we do not wait on the inode to be written out
+ * but we always wait on the page cache pages to be written out.
+ *
+ * Note: In the past @filp could be NULL so we ignore it as we don't need it
+ * anyway.
+ *
+ * Locking: Caller must hold i_sem on the inode.
+ *
+ * TODO: We should probably also write all attribute/index inodes associated
+ * with this inode but since we have no simple way of getting to them we ignore
+ * this problem for now.
+ */
+static int ntfs_file_fsync(struct file *filp, struct dentry *dentry,
+		int datasync)
+{
+	struct inode *vi = dentry->d_inode;
+	int err, ret = 0;
+
+	ntfs_debug("Entering for inode 0x%lx.", vi->i_ino);
+	BUG_ON(S_ISDIR(vi->i_mode));
+	if (!datasync || !NInoNonResident(NTFS_I(vi)))
+		ret = ntfs_write_inode(vi, 1);
+	write_inode_now(vi, !datasync);
+	err = sync_blockdev(vi->i_sb->s_bdev);
+	if (unlikely(err && !ret))
+		ret = err;
+	if (likely(!ret))
+		ntfs_debug("Done.");
+	else
+		ntfs_warning(vi->i_sb, "Failed to f%ssync inode 0x%lx.  Error "
+				"%u.", datasync ? "data" : "", vi->i_ino, -ret);
+	return ret;
+}
+
+#endif /* NTFS_RW */
+
 struct file_operations ntfs_file_ops = {
-	.llseek		= generic_file_llseek,	/* Seek inside file. */
-	.read		= generic_file_read,	/* Read from file. */
+	.llseek		= generic_file_llseek,	  /* Seek inside file. */
+	.read		= generic_file_read,	  /* Read from file. */
+	.aio_read	= generic_file_aio_read,  /* Async read from file. */
+	.readv		= generic_file_readv,	  /* Read from file. */
 #ifdef NTFS_RW
-	.write		= generic_file_write,	/* Write to a file. */
-#endif
-	.mmap		= generic_file_mmap,	/* Mmap file. */
-	.sendfile	= generic_file_sendfile,/* Zero-copy data send with the
-						   data source being on the
-						   ntfs partition. We don't
-						   need to care about the data
-						   destination. */
-	.open		= ntfs_file_open,	/* Open file. */
+	.write		= generic_file_write,	  /* Write to file. */
+	.aio_write	= generic_file_aio_write, /* Async write to file. */
+	.writev		= generic_file_writev,	  /* Write to file. */
+	/*.release	= ,*/			  /* Last file is closed.  See
+						     fs/ext2/file.c::
+						     ext2_release_file() for
+						     how to use this to discard
+						     preallocated space for
+						     write opened files. */
+	.fsync		= ntfs_file_fsync,	  /* Sync a file to disk. */
+	/*.aio_fsync	= ,*/			  /* Sync all outstanding async
+						     i/o operations on a
+						     kiocb. */
+#endif /* NTFS_RW */
+	/*.ioctl	= ,*/			  /* Perform function on the
+						     mounted filesystem. */
+	.mmap		= generic_file_mmap,	  /* Mmap file. */
+	.open		= ntfs_file_open,	  /* Open file. */
+	.sendfile	= generic_file_sendfile,  /* Zero-copy data send with
+						     the data source being on
+						     the ntfs partition.  We
+						     do not need to care about
+						     the data destination. */
+	/*.sendpage	= ,*/			  /* Zero-copy data send with
+						     the data destination being
+						     on the ntfs partition.  We
+						     do not need to care about
+						     the data source. */
 };
 
 struct inode_operations ntfs_file_inode_ops = {
 #ifdef NTFS_RW
 	.truncate	= ntfs_truncate,
 	.setattr	= ntfs_setattr,
-#endif
+#endif /* NTFS_RW */
 };
 
 struct file_operations ntfs_empty_file_ops = {};
diff -Nru a/fs/ntfs/index.c b/fs/ntfs/index.c
--- a/fs/ntfs/index.c	2004-10-18 14:56:49 -07:00
+++ b/fs/ntfs/index.c	2004-10-18 14:56:49 -07:00
@@ -65,7 +65,7 @@
 	if (ictx->entry) {
 		if (ictx->is_in_root) {
 			if (ictx->actx)
-				put_attr_search_ctx(ictx->actx);
+				ntfs_attr_put_search_ctx(ictx->actx);
 			if (ictx->base_ni)
 				unmap_mft_record(ictx->base_ni);
 		} else {
@@ -125,6 +125,7 @@
 int ntfs_index_lookup(const void *key, const int key_len,
 		ntfs_index_context *ictx)
 {
+	VCN vcn, old_vcn;
 	ntfs_inode *idx_ni = ictx->idx_ni;
 	ntfs_volume *vol = idx_ni->vol;
 	struct super_block *sb = vol->sb;
@@ -133,13 +134,11 @@
 	INDEX_ROOT *ir;
 	INDEX_ENTRY *ie;
 	INDEX_ALLOCATION *ia;
-	u8 *index_end;
-	attr_search_context *actx;
-	int rc, err = 0;
-	VCN vcn, old_vcn;
+	u8 *index_end, *kaddr;
+	ntfs_attr_search_ctx *actx;
 	struct address_space *ia_mapping;
 	struct page *page;
-	u8 *kaddr;
+	int rc, err = 0;
 
 	ntfs_debug("Entering.");
 	BUG_ON(!NInoAttr(idx_ni));
@@ -157,22 +156,25 @@
 	}
 	/* Get hold of the mft record for the index inode. */
 	m = map_mft_record(base_ni);
-	if (unlikely(IS_ERR(m))) {
+	if (IS_ERR(m)) {
 		ntfs_error(sb, "map_mft_record() failed with error code %ld.",
 				-PTR_ERR(m));
 		return PTR_ERR(m);
 	}
-	actx = get_attr_search_ctx(base_ni, m);
+	actx = ntfs_attr_get_search_ctx(base_ni, m);
 	if (unlikely(!actx)) {
 		err = -ENOMEM;
 		goto err_out;
 	}
 	/* Find the index root attribute in the mft record. */
-	if (!lookup_attr(AT_INDEX_ROOT, idx_ni->name, idx_ni->name_len,
-			CASE_SENSITIVE, 0, NULL, 0, actx)) {
-		ntfs_error(sb, "Index root attribute missing in inode 0x%lx.",
-				idx_ni->mft_no);
-		err = -EIO;
+	err = ntfs_attr_lookup(AT_INDEX_ROOT, idx_ni->name, idx_ni->name_len,
+			CASE_SENSITIVE, 0, NULL, 0, actx);
+	if (unlikely(err)) {
+		if (err == -ENOENT) {
+			ntfs_error(sb, "Index root attribute missing in inode "
+					"0x%lx.", idx_ni->mft_no);
+			err = -EIO;
+		}
 		goto err_out;
 	}
 	/* Get to the index root value (it has been verified in read_inode). */
@@ -263,13 +265,13 @@
 		goto err_out;
 	}
 	/* Get the starting vcn of the index_block holding the child node. */
-	vcn = sle64_to_cpup((u8*)ie + le16_to_cpu(ie->length) - 8);
+	vcn = sle64_to_cpup((sle64*)((u8*)ie + le16_to_cpu(ie->length) - 8));
 	ia_mapping = VFS_I(idx_ni)->i_mapping;
 	/*
 	 * We are done with the index root and the mft record.  Release them,
 	 * otherwise we deadlock with ntfs_map_page().
 	 */
-	put_attr_search_ctx(actx);
+	ntfs_attr_put_search_ctx(actx);
 	unmap_mft_record(base_ni);
 	m = NULL;
 	actx = NULL;
@@ -425,7 +427,7 @@
 	}
 	/* Child node present, descend into it. */
 	old_vcn = vcn;
-	vcn = sle64_to_cpup((u8*)ie + le16_to_cpu(ie->length) - 8);
+	vcn = sle64_to_cpup((sle64*)((u8*)ie + le16_to_cpu(ie->length) - 8));
 	if (vcn >= 0) {
 		/*
 		 * If vcn is in the same page cache page as old_vcn we recycle
@@ -448,7 +450,7 @@
 	ntfs_unmap_page(page);
 err_out:
 	if (actx)
-		put_attr_search_ctx(actx);
+		ntfs_attr_put_search_ctx(actx);
 	if (m)
 		unmap_mft_record(base_ni);
 	return err;
diff -Nru a/fs/ntfs/index.h b/fs/ntfs/index.h
--- a/fs/ntfs/index.h	2004-10-18 14:57:03 -07:00
+++ b/fs/ntfs/index.h	2004-10-18 14:57:03 -07:00
@@ -78,7 +78,7 @@
 	u16 data_len;
 	BOOL is_in_root;
 	INDEX_ROOT *ir;
-	attr_search_context *actx;
+	ntfs_attr_search_ctx *actx;
 	ntfs_inode *base_ni;
 	INDEX_ALLOCATION *ia;
 	struct page *page;
diff -Nru a/fs/ntfs/inode.c b/fs/ntfs/inode.c
--- a/fs/ntfs/inode.c	2004-10-18 14:57:03 -07:00
+++ b/fs/ntfs/inode.c	2004-10-18 14:57:03 -07:00
@@ -105,8 +105,11 @@
 	ni->name_len = na->name_len;
 
 	/* If initializing a normal inode, we are done. */
-	if (likely(na->type == AT_UNUSED))
+	if (likely(na->type == AT_UNUSED)) {
+		BUG_ON(na->name);
+		BUG_ON(na->name_len);
 		return 0;
+	}
 
 	/* It is a fake inode. */
 	NInoSetAttr(ni);
@@ -118,15 +121,16 @@
 	 * thus the fraction of named attributes with name != I30 is actually
 	 * absolutely tiny.
 	 */
-	if (na->name && na->name_len && na->name != I30) {
+	if (na->name_len && na->name != I30) {
 		unsigned int i;
 
+		BUG_ON(!na->name);
 		i = na->name_len * sizeof(ntfschar);
 		ni->name = (ntfschar*)kmalloc(i + sizeof(ntfschar), GFP_ATOMIC);
 		if (!ni->name)
 			return -ENOMEM;
 		memcpy(ni->name, na->name, i);
-		ni->name[i] = cpu_to_le16('\0');
+		ni->name[i] = 0;
 	}
 	return 0;
 }
@@ -210,7 +214,7 @@
  * value with IS_ERR() and if true, the function failed and the error code is
  * obtained from PTR_ERR().
  */
-struct inode *ntfs_attr_iget(struct inode *base_vi, ATTR_TYPES type,
+struct inode *ntfs_attr_iget(struct inode *base_vi, ATTR_TYPE type,
 		ntfschar *name, u32 name_len)
 {
 	struct inode *vi;
@@ -372,13 +376,13 @@
 	ni->seq_no = 0;
 	atomic_set(&ni->count, 1);
 	ni->vol = NTFS_SB(sb);
-	init_run_list(&ni->run_list);
+	init_runlist(&ni->runlist);
 	init_MUTEX(&ni->mrec_lock);
 	ni->page = NULL;
 	ni->page_ofs = 0;
 	ni->attr_list_size = 0;
 	ni->attr_list = NULL;
-	init_run_list(&ni->attr_list_rl);
+	init_runlist(&ni->attr_list_rl);
 	ni->itype.index.bmp_ino = NULL;
 	ni->itype.index.block_size = 0;
 	ni->itype.index.vcn_size = 0;
@@ -428,20 +432,21 @@
  * Return values:
  *	   1: file is in $Extend directory
  *	   0: file is not in $Extend directory
- *	-EIO: file is corrupt
+ *    -errno: failed to determine if the file is in the $Extend directory
  */
-static int ntfs_is_extended_system_file(attr_search_context *ctx)
+static int ntfs_is_extended_system_file(ntfs_attr_search_ctx *ctx)
 {
-	int nr_links;
+	int nr_links, err;
 
 	/* Restart search. */
-	reinit_attr_search_ctx(ctx);
+	ntfs_attr_reinit_search_ctx(ctx);
 
 	/* Get number of hard links. */
 	nr_links = le16_to_cpu(ctx->mrec->link_count);
 
 	/* Loop through all hard links. */
-	while (lookup_attr(AT_FILE_NAME, NULL, 0, 0, 0, NULL, 0, ctx)) {
+	while (!(err = ntfs_attr_lookup(AT_FILE_NAME, NULL, 0, 0, 0, NULL, 0,
+			ctx))) {
 		FILE_NAME_ATTR *file_name_attr;
 		ATTR_RECORD *attr = ctx->attr;
 		u8 *p, *p2;
@@ -484,7 +489,9 @@
 		if (MREF_LE(file_name_attr->parent_directory) == FILE_Extend)
 			return 1;	/* YES, it's an extended system file. */
 	}
-	if (nr_links) {
+	if (unlikely(err != -ENOENT))
+		return err;
+	if (unlikely(nr_links)) {
 		ntfs_error(ctx->ntfs_ino->vol->sb, "Inode hard link count "
 				"doesn't match number of name attributes. You "
 				"should run chkdsk.");
@@ -525,7 +532,7 @@
 	ntfs_inode *ni;
 	MFT_RECORD *m;
 	STANDARD_INFORMATION *si;
-	attr_search_context *ctx;
+	ntfs_attr_search_ctx *ctx;
 	int err = 0;
 
 	ntfs_debug("Entering for i_ino 0x%lx.", vi->i_ino);
@@ -557,7 +564,7 @@
 		err = PTR_ERR(m);
 		goto err_out;
 	}
-	ctx = get_attr_search_ctx(ni, m);
+	ctx = ntfs_attr_get_search_ctx(ni, m);
 	if (!ctx) {
 		err = -ENOMEM;
 		goto unm_err_out;
@@ -608,21 +615,25 @@
 	 * in fact fail if the standard information is in an extent record, but
 	 * I don't think this actually ever happens.
 	 */
-	if (!lookup_attr(AT_STANDARD_INFORMATION, NULL, 0, 0, 0, NULL, 0,
-			ctx)) {
-		/*
-		 * TODO: We should be performing a hot fix here (if the recover
-		 * mount option is set) by creating a new attribute.
-		 */
-		ntfs_error(vi->i_sb, "$STANDARD_INFORMATION attribute is "
-				"missing.");
+	err = ntfs_attr_lookup(AT_STANDARD_INFORMATION, NULL, 0, 0, 0, NULL, 0,
+			ctx);
+	if (unlikely(err)) {
+		if (err == -ENOENT) {
+			/*
+			 * TODO: We should be performing a hot fix here (if the
+			 * recover mount option is set) by creating a new
+			 * attribute.
+			 */
+			ntfs_error(vi->i_sb, "$STANDARD_INFORMATION attribute "
+					"is missing.");
+		}
 		goto unm_err_out;
 	}
 	/* Get the standard information attribute value. */
 	si = (STANDARD_INFORMATION*)((char*)ctx->attr +
 			le16_to_cpu(ctx->attr->data.resident.value_offset));
 
-	/* Transfer information from the standard information into vfs_ino. */
+	/* Transfer information from the standard information into vi. */
 	/*
 	 * Note: The i_?times do not quite map perfectly onto the NTFS times,
 	 * but they are close enough, and in the end it doesn't really matter
@@ -646,8 +657,15 @@
 	vi->i_atime = ntfs2utc(si->last_access_time);
 
 	/* Find the attribute list attribute if present. */
-	reinit_attr_search_ctx(ctx);
-	if (lookup_attr(AT_ATTRIBUTE_LIST, NULL, 0, 0, 0, NULL, 0, ctx)) {
+	ntfs_attr_reinit_search_ctx(ctx);
+	err = ntfs_attr_lookup(AT_ATTRIBUTE_LIST, NULL, 0, 0, 0, NULL, 0, ctx);
+	if (err) {
+		if (unlikely(err != -ENOENT)) {
+			ntfs_error(vi->i_sb, "Failed to lookup attribute list "
+					"attribute. You should run chkdsk.");
+			goto unm_err_out;
+		}
+	} else /* if (!err) */ {
 		if (vi->i_ino == FILE_MFT)
 			goto skip_attr_list_load;
 		ntfs_debug("Attribute list found in inode 0x%lx.", vi->i_ino);
@@ -662,7 +680,7 @@
 			goto unm_err_out;
 		}
 		/* Now allocate memory for the attribute list. */
-		ni->attr_list_size = (u32)attribute_value_length(ctx->attr);
+		ni->attr_list_size = (u32)ntfs_attr_size(ctx->attr);
 		ni->attr_list = ntfs_malloc_nofs(ni->attr_list_size);
 		if (!ni->attr_list) {
 			ntfs_error(vi->i_sb, "Not enough memory to allocate "
@@ -680,7 +698,7 @@
 				goto unm_err_out;
 			}
 			/*
-			 * Setup the run list. No need for locking as we have
+			 * Setup the runlist. No need for locking as we have
 			 * exclusive access to the inode at this time.
 			 */
 			ni->attr_list_rl.rl = decompress_mapping_pairs(vol,
@@ -733,13 +751,17 @@
 		char *ir_end, *index_end;
 
 		/* It is a directory, find index root attribute. */
-		reinit_attr_search_ctx(ctx);
-		if (!lookup_attr(AT_INDEX_ROOT, I30, 4, CASE_SENSITIVE, 0,
-				NULL, 0, ctx)) {
-			// FIXME: File is corrupt! Hot-fix with empty index
-			// root attribute if recovery option is set.
-			ntfs_error(vi->i_sb, "$INDEX_ROOT attribute is "
-					"missing.");
+		ntfs_attr_reinit_search_ctx(ctx);
+		err = ntfs_attr_lookup(AT_INDEX_ROOT, I30, 4, CASE_SENSITIVE,
+				0, NULL, 0, ctx);
+		if (unlikely(err)) {
+			if (err == -ENOENT) {
+				// FIXME: File is corrupt! Hot-fix with empty
+				// index root attribute if recovery option is
+				// set.
+				ntfs_error(vi->i_sb, "$INDEX_ROOT attribute "
+						"is missing.");
+			}
 			goto unm_err_out;
 		}
 		/* Set up the state. */
@@ -841,7 +863,7 @@
 			vi->i_size = ni->initialized_size =
 					ni->allocated_size = 0;
 			/* We are done with the mft record, so we release it. */
-			put_attr_search_ctx(ctx);
+			ntfs_attr_put_search_ctx(ctx);
 			unmap_mft_record(ni);
 			m = NULL;
 			ctx = NULL;
@@ -849,12 +871,19 @@
 		} /* LARGE_INDEX: Index allocation present. Setup state. */
 		NInoSetIndexAllocPresent(ni);
 		/* Find index allocation attribute. */
-		reinit_attr_search_ctx(ctx);
-		if (!lookup_attr(AT_INDEX_ALLOCATION, I30, 4, CASE_SENSITIVE,
-				0, NULL, 0, ctx)) {
-			ntfs_error(vi->i_sb, "$INDEX_ALLOCATION attribute "
-					"is not present but $INDEX_ROOT "
-					"indicated it is.");
+		ntfs_attr_reinit_search_ctx(ctx);
+		err = ntfs_attr_lookup(AT_INDEX_ALLOCATION, I30, 4,
+				CASE_SENSITIVE, 0, NULL, 0, ctx);
+		if (unlikely(err)) {
+			if (err == -ENOENT)
+				ntfs_error(vi->i_sb, "$INDEX_ALLOCATION "
+						"attribute is not present but "
+						"$INDEX_ROOT indicated it "
+						"is.");
+			else
+				ntfs_error(vi->i_sb, "Failed to lookup "
+						"$INDEX_ALLOCATION "
+						"attribute.");
 			goto unm_err_out;
 		}
 		if (!ctx->attr->non_resident) {
@@ -894,13 +923,13 @@
 		 * We are done with the mft record, so we release it. Otherwise
 		 * we would deadlock in ntfs_attr_iget().
 		 */
-		put_attr_search_ctx(ctx);
+		ntfs_attr_put_search_ctx(ctx);
 		unmap_mft_record(ni);
 		m = NULL;
 		ctx = NULL;
 		/* Get the index bitmap attribute inode. */
 		bvi = ntfs_attr_iget(vi, AT_BITMAP, I30, 4);
-		if (unlikely(IS_ERR(bvi))) {
+		if (IS_ERR(bvi)) {
 			ntfs_error(vi->i_sb, "Failed to get bitmap attribute.");
 			err = PTR_ERR(bvi);
 			goto unm_err_out;
@@ -938,7 +967,7 @@
 		vi->i_mapping->a_ops = &ntfs_mst_aops;
 	} else {
 		/* It is a file. */
-		reinit_attr_search_ctx(ctx);
+		ntfs_attr_reinit_search_ctx(ctx);
 
 		/* Setup the data attribute, even if not present. */
 		ni->type = AT_DATA;
@@ -946,9 +975,15 @@
 		ni->name_len = 0;
 
 		/* Find first extent of the unnamed data attribute. */
-		if (!lookup_attr(AT_DATA, NULL, 0, 0, 0, NULL, 0, ctx)) {
+		err = ntfs_attr_lookup(AT_DATA, NULL, 0, 0, 0, NULL, 0, ctx);
+		if (unlikely(err)) {
 			vi->i_size = ni->initialized_size =
-					ni->allocated_size = 0LL;
+					ni->allocated_size = 0;
+			if (err != -ENOENT) {
+				ntfs_error(vi->i_sb, "Failed to lookup $DATA "
+						"attribute.");
+				goto unm_err_out;
+			}
 			/*
 			 * FILE_Secure does not have an unnamed $DATA
 			 * attribute, so we special case it here.
@@ -1059,7 +1094,7 @@
 		}
 no_data_attr_special_case:
 		/* We are done with the mft record, so we release it. */
-		put_attr_search_ctx(ctx);
+		ntfs_attr_put_search_ctx(ctx);
 		unmap_mft_record(ni);
 		m = NULL;
 		ctx = NULL;
@@ -1098,7 +1133,7 @@
 	if (!err)
 		err = -EIO;
 	if (ctx)
-		put_attr_search_ctx(ctx);
+		ntfs_attr_put_search_ctx(ctx);
 	if (m)
 		unmap_mft_record(ni);
 err_out:
@@ -1133,7 +1168,7 @@
 	ntfs_volume *vol = NTFS_SB(vi->i_sb);
 	ntfs_inode *ni, *base_ni;
 	MFT_RECORD *m;
-	attr_search_context *ctx;
+	ntfs_attr_search_ctx *ctx;
 	int err = 0;
 
 	ntfs_debug("Entering for i_ino 0x%lx.", vi->i_ino);
@@ -1162,15 +1197,16 @@
 		err = PTR_ERR(m);
 		goto err_out;
 	}
-	ctx = get_attr_search_ctx(base_ni, m);
+	ctx = ntfs_attr_get_search_ctx(base_ni, m);
 	if (!ctx) {
 		err = -ENOMEM;
 		goto unm_err_out;
 	}
 
 	/* Find the attribute. */
-	if (!lookup_attr(ni->type, ni->name, ni->name_len, CASE_SENSITIVE, 0,
-			NULL, 0, ctx))
+	err = ntfs_attr_lookup(ni->type, ni->name, ni->name_len,
+			CASE_SENSITIVE, 0, NULL, 0, ctx);
+	if (unlikely(err))
 		goto unm_err_out;
 
 	if (!ctx->attr->non_resident) {
@@ -1333,7 +1369,7 @@
 	ni->ext.base_ntfs_ino = base_ni;
 	ni->nr_extents = -1;
 
-	put_attr_search_ctx(ctx);
+	ntfs_attr_put_search_ctx(ctx);
 	unmap_mft_record(base_ni);
 
 	ntfs_debug("Done.");
@@ -1343,7 +1379,7 @@
 	if (!err)
 		err = -EIO;
 	if (ctx)
-		put_attr_search_ctx(ctx);
+		ntfs_attr_put_search_ctx(ctx);
 	unmap_mft_record(base_ni);
 err_out:
 	ntfs_error(vi->i_sb, "Failed with error code %i while reading "
@@ -1392,7 +1428,7 @@
 	ntfs_inode *ni, *base_ni, *bni;
 	struct inode *bvi;
 	MFT_RECORD *m;
-	attr_search_context *ctx;
+	ntfs_attr_search_ctx *ctx;
 	INDEX_ROOT *ir;
 	u8 *ir_end, *index_end;
 	int err = 0;
@@ -1419,15 +1455,18 @@
 		err = PTR_ERR(m);
 		goto err_out;
 	}
-	ctx = get_attr_search_ctx(base_ni, m);
+	ctx = ntfs_attr_get_search_ctx(base_ni, m);
 	if (!ctx) {
 		err = -ENOMEM;
 		goto unm_err_out;
 	}
 	/* Find the index root attribute. */
-	if (!lookup_attr(AT_INDEX_ROOT, ni->name, ni->name_len, CASE_SENSITIVE,
-			0, NULL, 0, ctx)) {
-		ntfs_error(vi->i_sb, "$INDEX_ROOT attribute is missing.");
+	err = ntfs_attr_lookup(AT_INDEX_ROOT, ni->name, ni->name_len,
+			CASE_SENSITIVE, 0, NULL, 0, ctx);
+	if (unlikely(err)) {
+		if (err == -ENOENT)
+			ntfs_error(vi->i_sb, "$INDEX_ROOT attribute is "
+					"missing.");
 		goto unm_err_out;
 	}
 	/* Set up the state. */
@@ -1497,7 +1536,7 @@
 		/* No index allocation. */
 		vi->i_size = ni->initialized_size = ni->allocated_size = 0;
 		/* We are done with the mft record, so we release it. */
-		put_attr_search_ctx(ctx);
+		ntfs_attr_put_search_ctx(ctx);
 		unmap_mft_record(base_ni);
 		m = NULL;
 		ctx = NULL;
@@ -1505,11 +1544,17 @@
 	} /* LARGE_INDEX:  Index allocation present.  Setup state. */
 	NInoSetIndexAllocPresent(ni);
 	/* Find index allocation attribute. */
-	reinit_attr_search_ctx(ctx);
-	if (!lookup_attr(AT_INDEX_ALLOCATION, ni->name, ni->name_len,
-			CASE_SENSITIVE, 0, NULL, 0, ctx)) {
-		ntfs_error(vi->i_sb, "$INDEX_ALLOCATION attribute is not "
-				"present but $INDEX_ROOT indicated it is.");
+	ntfs_attr_reinit_search_ctx(ctx);
+	err = ntfs_attr_lookup(AT_INDEX_ALLOCATION, ni->name, ni->name_len,
+			CASE_SENSITIVE, 0, NULL, 0, ctx);
+	if (unlikely(err)) {
+		if (err == -ENOENT)
+			ntfs_error(vi->i_sb, "$INDEX_ALLOCATION attribute is "
+					"not present but $INDEX_ROOT "
+					"indicated it is.");
+		else
+			ntfs_error(vi->i_sb, "Failed to lookup "
+					"$INDEX_ALLOCATION attribute.");
 		goto unm_err_out;
 	}
 	if (!ctx->attr->non_resident) {
@@ -1546,13 +1591,13 @@
 	 * We are done with the mft record, so we release it.  Otherwise
 	 * we would deadlock in ntfs_attr_iget().
 	 */
-	put_attr_search_ctx(ctx);
+	ntfs_attr_put_search_ctx(ctx);
 	unmap_mft_record(base_ni);
 	m = NULL;
 	ctx = NULL;
 	/* Get the index bitmap attribute inode. */
 	bvi = ntfs_attr_iget(base_vi, AT_BITMAP, ni->name, ni->name_len);
-	if (unlikely(IS_ERR(bvi))) {
+	if (IS_ERR(bvi)) {
 		ntfs_error(vi->i_sb, "Failed to get bitmap attribute.");
 		err = PTR_ERR(bvi);
 		goto unm_err_out;
@@ -1597,7 +1642,7 @@
 	if (!err)
 		err = -EIO;
 	if (ctx)
-		put_attr_search_ctx(ctx);
+		ntfs_attr_put_search_ctx(ctx);
 	if (m)
 		unmap_mft_record(base_ni);
 err_out:
@@ -1619,16 +1664,16 @@
  * is not initialized and hence we cannot get at the contents of mft records
  * by calling map_mft_record*().
  *
- * Further it needs to cope with the circular references problem, i.e. can't
+ * Further it needs to cope with the circular references problem, i.e. cannot
  * load any attributes other than $ATTRIBUTE_LIST until $DATA is loaded, because
- * we don't know where the other extent mft records are yet and again, because
- * we cannot call map_mft_record*() yet. Obviously this applies only when an
+ * we do not know where the other extent mft records are yet and again, because
+ * we cannot call map_mft_record*() yet.  Obviously this applies only when an
  * attribute list is actually present in $MFT inode.
  *
  * We solve these problems by starting with the $DATA attribute before anything
- * else and iterating using lookup_attr($DATA) over all extents. As each extent
- * is found, we decompress_mapping_pairs() including the implied
- * merge_run_lists(). Each step of the iteration necessarily provides
+ * else and iterating using ntfs_attr_lookup($DATA) over all extents.  As each
+ * extent is found, we decompress_mapping_pairs() including the implied
+ * ntfs_merge_runlists().  Each step of the iteration necessarily provides
  * sufficient information for the next step to complete.
  *
  * This should work but there are two possible pit falls (see inline comments
@@ -1644,7 +1689,7 @@
 	ntfs_inode *ni;
 	MFT_RECORD *m = NULL;
 	ATTR_RECORD *attr;
-	attr_search_context *ctx;
+	ntfs_attr_search_ctx *ctx;
 	unsigned int i, nr_blocks;
 	int err;
 
@@ -1719,14 +1764,21 @@
 	/* Provides readpage() and sync_page() for map_mft_record(). */
 	vi->i_mapping->a_ops = &ntfs_mft_aops;
 
-	ctx = get_attr_search_ctx(ni, m);
+	ctx = ntfs_attr_get_search_ctx(ni, m);
 	if (!ctx) {
 		err = -ENOMEM;
 		goto err_out;
 	}
 
 	/* Find the attribute list attribute if present. */
-	if (lookup_attr(AT_ATTRIBUTE_LIST, NULL, 0, 0, 0, NULL, 0, ctx)) {
+	err = ntfs_attr_lookup(AT_ATTRIBUTE_LIST, NULL, 0, 0, 0, NULL, 0, ctx);
+	if (err) {
+		if (unlikely(err != -ENOENT)) {
+			ntfs_error(sb, "Failed to lookup attribute list "
+					"attribute. You should run chkdsk.");
+			goto put_err_out;
+		}
+	} else /* if (!err) */ {
 		ATTR_LIST_ENTRY *al_entry, *next_al_entry;
 		u8 *al_end;
 
@@ -1742,7 +1794,7 @@
 			goto put_err_out;
 		}
 		/* Now allocate memory for the attribute list. */
-		ni->attr_list_size = (u32)attribute_value_length(ctx->attr);
+		ni->attr_list_size = (u32)ntfs_attr_size(ctx->attr);
 		ni->attr_list = ntfs_malloc_nofs(ni->attr_list_size);
 		if (!ni->attr_list) {
 			ntfs_error(sb, "Not enough memory to allocate buffer "
@@ -1757,7 +1809,7 @@
 						"You should run chkdsk.");
 				goto put_err_out;
 			}
-			/* Setup the run list. */
+			/* Setup the runlist. */
 			ni->attr_list_rl.rl = decompress_mapping_pairs(vol,
 					ctx->attr, NULL);
 			if (IS_ERR(ni->attr_list_rl.rl)) {
@@ -1855,13 +1907,14 @@
 		}
 	}
 
-	reinit_attr_search_ctx(ctx);
+	ntfs_attr_reinit_search_ctx(ctx);
 
 	/* Now load all attribute extents. */
 	attr = NULL;
 	next_vcn = last_vcn = highest_vcn = 0;
-	while (lookup_attr(AT_DATA, NULL, 0, 0, next_vcn, NULL, 0, ctx)) {
-		run_list_element *nrl;
+	while (!(err = ntfs_attr_lookup(AT_DATA, NULL, 0, 0, next_vcn, NULL, 0,
+			ctx))) {
+		runlist_element *nrl;
 
 		/* Cache the current attribute. */
 		attr = ctx->attr;
@@ -1885,23 +1938,21 @@
 		}
 		/*
 		 * Decompress the mapping pairs array of this extent and merge
-		 * the result into the existing run list. No need for locking
+		 * the result into the existing runlist. No need for locking
 		 * as we have exclusive access to the inode at this time and we
 		 * are a mount in progress task, too.
 		 */
-		nrl = decompress_mapping_pairs(vol, attr, ni->run_list.rl);
+		nrl = decompress_mapping_pairs(vol, attr, ni->runlist.rl);
 		if (IS_ERR(nrl)) {
 			ntfs_error(sb, "decompress_mapping_pairs() failed with "
 					"error code %ld. $MFT is corrupt.",
 					PTR_ERR(nrl));
 			goto put_err_out;
 		}
-		ni->run_list.rl = nrl;
+		ni->runlist.rl = nrl;
 
 		/* Are we in the first extent? */
 		if (!next_vcn) {
-			u64 ll;
-
 			if (attr->data.non_resident.lowest_vcn) {
 				ntfs_error(sb, "First extent of $DATA "
 						"attribute has non zero "
@@ -1920,19 +1971,17 @@
 					non_resident.initialized_size);
 			ni->allocated_size = sle64_to_cpu(
 					attr->data.non_resident.allocated_size);
-			/* Set the number of mft records. */
-			ll = vi->i_size >> vol->mft_record_size_bits;
 			/*
 			 * Verify the number of mft records does not exceed
 			 * 2^32 - 1.
 			 */
-			if (ll >= (1ULL << 32)) {
+			if ((vi->i_size >> vol->mft_record_size_bits) >=
+					(1ULL << 32)) {
 				ntfs_error(sb, "$MFT is too big! Aborting.");
 				goto put_err_out;
 			}
-			vol->nr_mft_records = ll;
 			/*
-			 * We have got the first extent of the run_list for
+			 * We have got the first extent of the runlist for
 			 * $MFT which means it is now relatively safe to call
 			 * the normal ntfs_read_inode() function.
 			 * Complete reading the inode, this will actually
@@ -1959,7 +2008,7 @@
 						"saw this message to "
 						"linux-ntfs-dev@lists."
 						"sourceforge.net");
-				put_attr_search_ctx(ctx);
+				ntfs_attr_put_search_ctx(ctx);
 				/* Revert to the safe super operations. */
 				ntfs_free(m);
 				return -1;
@@ -1995,21 +2044,26 @@
 			goto put_err_out;
 		}
 	}
+	if (err != -ENOENT) {
+		ntfs_error(sb, "Failed to lookup $MFT/$DATA attribute extent. "
+				"$MFT is corrupt. Run chkdsk.");
+		goto put_err_out;
+	}
 	if (!attr) {
 		ntfs_error(sb, "$MFT/$DATA attribute not found. $MFT is "
 				"corrupt. Run chkdsk.");
 		goto put_err_out;
 	}
 	if (highest_vcn && highest_vcn != last_vcn - 1) {
-		ntfs_error(sb, "Failed to load the complete run list "
-				"for $MFT/$DATA. Driver bug or "
-				"corrupt $MFT. Run chkdsk.");
+		ntfs_error(sb, "Failed to load the complete runlist for "
+				"$MFT/$DATA. Driver bug or corrupt $MFT. "
+				"Run chkdsk.");
 		ntfs_debug("highest_vcn = 0x%llx, last_vcn - 1 = 0x%llx",
 				(unsigned long long)highest_vcn,
 				(unsigned long long)last_vcn - 1);
 		goto put_err_out;
 	}
-	put_attr_search_ctx(ctx);
+	ntfs_attr_put_search_ctx(ctx);
 	ntfs_debug("Done.");
 	ntfs_free(m);
 	return 0;
@@ -2018,7 +2072,7 @@
 	ntfs_error(sb, "Couldn't find first extent of $DATA attribute in "
 			"attribute list. $MFT is corrupt. Run chkdsk.");
 put_err_out:
-	put_attr_search_ctx(ctx);
+	ntfs_attr_put_search_ctx(ctx);
 err_out:
 	ntfs_error(sb, "Failed. Marking inode as bad.");
 	make_bad_inode(vi);
@@ -2073,12 +2127,12 @@
 void __ntfs_clear_inode(ntfs_inode *ni)
 {
 	/* Free all alocated memory. */
-	down_write(&ni->run_list.lock);
-	if (ni->run_list.rl) {
-		ntfs_free(ni->run_list.rl);
-		ni->run_list.rl = NULL;
+	down_write(&ni->runlist.lock);
+	if (ni->runlist.rl) {
+		ntfs_free(ni->runlist.rl);
+		ni->runlist.rl = NULL;
 	}
-	up_write(&ni->run_list.lock);
+	up_write(&ni->runlist.lock);
 
 	if (ni->attr_list) {
 		ntfs_free(ni->attr_list);
@@ -2216,16 +2270,71 @@
  *
  * We don't support i_size changes yet.
  *
- * Called with ->i_sem held.
+ * The kernel guarantees that @vi is a regular file (S_ISREG() is true) and
+ * that the change is allowed.
+ *
+ * This implies for us that @vi is a file inode rather than a directory, index,
+ * or attribute inode as well as that @vi is a base inode.
+ *
+ * Called with ->i_sem held.  In all but one case ->i_alloc_sem is held for
+ * writing.  The only case where ->i_alloc_sem is not held is
+ * mm/filemap.c::generic_file_buffered_write() where vmtruncate() is called
+ * with the current i_size as the offset which means that it is a noop as far
+ * as ntfs_truncate() is concerned.
  */
 void ntfs_truncate(struct inode *vi)
 {
-	// TODO: Implement...
-	ntfs_warning(vi->i_sb, "Eeek: i_size may have changed! If you see "
-			"this right after a message from "
-			"ntfs_{prepare,commit}_{,nonresident_}write() then "
-			"just ignore it. Otherwise it is bad news.");
-	// TODO: reset i_size now!
+	ntfs_inode *ni = NTFS_I(vi);
+	ntfs_attr_search_ctx *ctx;
+	MFT_RECORD *m;
+	int err;
+
+	m = map_mft_record(ni);
+	if (IS_ERR(m)) {
+		ntfs_error(vi->i_sb, "Failed to map mft record for inode 0x%lx "
+				"(error code %ld).", vi->i_ino, PTR_ERR(m));
+		if (PTR_ERR(m) != ENOMEM)
+			make_bad_inode(vi);
+		return;
+	}
+	ctx = ntfs_attr_get_search_ctx(ni, m);
+	if (unlikely(!ctx)) {
+		ntfs_error(vi->i_sb, "Failed to allocate a search context: "
+				"Not enough memory");
+		// FIXME: We can't report an error code upstream.  So what do
+		// we do?!?  make_bad_inode() seems a bit harsh...
+		unmap_mft_record(ni);
+		return;
+	}
+	err = ntfs_attr_lookup(ni->type, ni->name, ni->name_len,
+			CASE_SENSITIVE, 0, NULL, 0, ctx);
+	if (unlikely(err)) {
+		if (err == -ENOENT) {
+			ntfs_error(vi->i_sb, "Open attribute is missing from "
+					"mft record.  Inode 0x%lx is corrupt.  "
+					"Run chkdsk.", vi->i_ino);
+			make_bad_inode(vi);
+		} else {
+			ntfs_error(vi->i_sb, "Failed to lookup attribute in "
+					"inode 0x%lx (error code %d).",
+					vi->i_ino, err);
+			// FIXME: We can't report an error code upstream.  So
+			// what do we do?!?  make_bad_inode() seems a bit
+			// harsh...
+		}
+		goto out;
+	}
+	/* If the size has not changed there is nothing to do. */
+	if (ntfs_attr_size(ctx->attr) == i_size_read(vi))
+		goto out;
+	// TODO: Implement the truncate...
+	ntfs_error(vi->i_sb, "Inode size has changed but this is not "
+			"implemented yet.  Resetting inode size to old value. "
+			" This is most likely a bug in the ntfs driver!");
+	i_size_write(vi, ntfs_attr_size(ctx->attr)); 
+out:
+	ntfs_attr_put_search_ctx(ctx);
+	unmap_mft_record(ni);
 	return;
 }
 
@@ -2235,67 +2344,62 @@
  * @attr:	structure describing the attributes and the changes
  *
  * We have to trap VFS attempts to truncate the file described by @dentry as
- * soon as possible, because we do not implement changes in i_size yet. So we
+ * soon as possible, because we do not implement changes in i_size yet.  So we
  * abort all i_size changes here.
  *
- * Called with ->i_sem held.
+ * We also abort all changes of user, group, and mode as we do not implement
+ * the NTFS ACLs yet.
+ *
+ * Called with ->i_sem held.  For the ATTR_SIZE (i.e. ->truncate) case, also
+ * called with ->i_alloc_sem held for writing.
  *
  * Basically this is a copy of generic notify_change() and inode_setattr()
  * functionality, except we intercept and abort changes in i_size.
  */
 int ntfs_setattr(struct dentry *dentry, struct iattr *attr)
 {
-	struct inode *vi;
+	struct inode *vi = dentry->d_inode;
 	int err;
 	unsigned int ia_valid = attr->ia_valid;
 
-	vi = dentry->d_inode;
-
 	err = inode_change_ok(vi, attr);
 	if (err)
 		return err;
 
-	if ((ia_valid & ATTR_UID && attr->ia_uid != vi->i_uid) ||
-			(ia_valid & ATTR_GID && attr->ia_gid != vi->i_gid)) {
-		err = DQUOT_TRANSFER(vi, attr) ? -EDQUOT : 0;
-		if (err)
-			return err;
+	/* We do not support NTFS ACLs yet. */
+	if (ia_valid & (ATTR_UID | ATTR_GID | ATTR_MODE)) {
+		ntfs_warning(vi->i_sb, "Changes in user/group/mode are not "
+				"supported yet, ignoring.");
+		err = -EOPNOTSUPP;
+		goto out;
 	}
 
-	lock_kernel();
-
 	if (ia_valid & ATTR_SIZE) {
-		ntfs_error(vi->i_sb, "Changes in i_size are not supported "
-				"yet. Sorry.");
-		// TODO: Implement...
-		// err = vmtruncate(vi, attr->ia_size);
-		err = -EOPNOTSUPP;
-		if (err)
-			goto trunc_err;
+		if (attr->ia_size != i_size_read(vi)) {
+			ntfs_warning(vi->i_sb, "Changes in inode size are not "
+					"supported yet, ignoring.");
+			err = -EOPNOTSUPP;
+			// TODO: Implement...
+			// err = vmtruncate(vi, attr->ia_size);
+			if (err || ia_valid == ATTR_SIZE)
+				goto out;
+		} else {
+			/*
+			 * We skipped the truncate but must still update
+			 * timestamps.
+			 */
+			ia_valid |= ATTR_MTIME|ATTR_CTIME;
+		}
 	}
 
-	if (ia_valid & ATTR_UID)
-		vi->i_uid = attr->ia_uid;
-	if (ia_valid & ATTR_GID)
-		vi->i_gid = attr->ia_gid;
 	if (ia_valid & ATTR_ATIME)
 		vi->i_atime = attr->ia_atime;
 	if (ia_valid & ATTR_MTIME)
 		vi->i_mtime = attr->ia_mtime;
 	if (ia_valid & ATTR_CTIME)
 		vi->i_ctime = attr->ia_ctime;
-	if (ia_valid & ATTR_MODE) {
-		vi->i_mode = attr->ia_mode;
-		if (!in_group_p(vi->i_gid) &&
-				!capable(CAP_FSETID))
-			vi->i_mode &= ~S_ISGID;
-	}
 	mark_inode_dirty(vi);
-
-trunc_err:
-
-	unlock_kernel();
-
+out:
 	return err;
 }
 
@@ -2314,67 +2418,93 @@
  * marking the page (and in this case mft record) dirty but we do not implement
  * this yet as write_mft_record() largely ignores the @sync parameter and
  * always performs synchronous writes.
+ *
+ * Return 0 on success and -errno on error.
  */
-void ntfs_write_inode(struct inode *vi, int sync)
+int ntfs_write_inode(struct inode *vi, int sync)
 {
+	sle64 nt;
 	ntfs_inode *ni = NTFS_I(vi);
-#if 0
-	attr_search_context *ctx;
-#endif
+	ntfs_attr_search_ctx *ctx;
 	MFT_RECORD *m;
+	STANDARD_INFORMATION *si;
 	int err = 0;
+	BOOL modified = FALSE;
 
 	ntfs_debug("Entering for %sinode 0x%lx.", NInoAttr(ni) ? "attr " : "",
 			vi->i_ino);
 	/*
 	 * Dirty attribute inodes are written via their real inodes so just
-	 * clean them here.  TODO:  Take care of access time updates.
+	 * clean them here.  Access time updates are taken care off when the
+	 * real inode is written.
 	 */
 	if (NInoAttr(ni)) {
 		NInoClearDirty(ni);
-		return;
+		ntfs_debug("Done.");
+		return 0;
 	}
 	/* Map, pin, and lock the mft record belonging to the inode. */
 	m = map_mft_record(ni);
-	if (unlikely(IS_ERR(m))) {
+	if (IS_ERR(m)) {
 		err = PTR_ERR(m);
 		goto err_out;
 	}
-#if 0
-	/* Obtain the standard information attribute. */
-	ctx = get_attr_search_ctx(ni, m);
+	/* Update the access times in the standard information attribute. */
+	ctx = ntfs_attr_get_search_ctx(ni, m);
 	if (unlikely(!ctx)) {
 		err = -ENOMEM;
 		goto unm_err_out;
 	}
-	if (unlikely(!lookup_attr(AT_STANDARD_INFORMATION, NULL, 0,
-			CASE_SENSITIVE, 0, NULL, 0, ctx))) {
-		put_attr_search_ctx(ctx);
-		err = -ENOENT;
-		goto unm_err_out;
-	}
-	// TODO:  Update the access times in the standard information attribute
-	// which is now in ctx->attr.
-	// - Probably want to have use sops->dirty_inode() to set a flag that
-	//   we need to update the times here rather than having to blindly do
-	//   it every time.  Or even don't do it here at all and do it in
-	//   sops->dirty_inode() instead.  Problem with this would be that
-	//   sops->dirty_inode() must be atomic under certain circumstances
-	//   and mapping mft records and such like is not atomic.
-	// - For atime updates also need to check whether they are enabled in
-	//   the superblock flags.
-	ntfs_warning(vi->i_sb, "Access time updates not implement yet.");
-	/*
-	 * We just modified the mft record containing the standard information
-	 * attribute.  So need to mark the mft record dirty, too, but we do it
-	 * manually so that mark_inode_dirty() is not called again.
-	 * TODO:  Only do this if there was a change in any of the times!
+	err = ntfs_attr_lookup(AT_STANDARD_INFORMATION, NULL, 0,
+			CASE_SENSITIVE, 0, NULL, 0, ctx);
+	if (unlikely(err)) {
+		ntfs_attr_put_search_ctx(ctx);
+		goto unm_err_out;
+	}
+	si = (STANDARD_INFORMATION*)((u8*)ctx->attr +
+			le16_to_cpu(ctx->attr->data.resident.value_offset));
+	/* Update the access times if they have changed. */
+	nt = utc2ntfs(vi->i_mtime);
+	if (si->last_data_change_time != nt) {
+		ntfs_debug("Updating mtime for inode 0x%lx: old = 0x%llx, "
+				"new = 0x%llx", vi->i_ino,
+				sle64_to_cpu(si->last_data_change_time),
+				sle64_to_cpu(nt));
+		si->last_data_change_time = nt;
+		modified = TRUE;
+	}
+	nt = utc2ntfs(vi->i_ctime);
+	if (si->last_mft_change_time != nt) {
+		ntfs_debug("Updating ctime for inode 0x%lx: old = 0x%llx, "
+				"new = 0x%llx", vi->i_ino,
+				sle64_to_cpu(si->last_mft_change_time),
+				sle64_to_cpu(nt));
+		si->last_mft_change_time = nt;
+		modified = TRUE;
+	}
+	nt = utc2ntfs(vi->i_atime);
+	if (si->last_access_time != nt) {
+		ntfs_debug("Updating atime for inode 0x%lx: old = 0x%llx, "
+				"new = 0x%llx", vi->i_ino,
+				sle64_to_cpu(si->last_access_time),
+				sle64_to_cpu(nt));
+		si->last_access_time = nt;
+		modified = TRUE;
+	}
+	/*
+	 * If we just modified the standard information attribute we need to
+	 * mark the mft record it is in dirty.  We do this manually so that
+	 * mark_inode_dirty() is not called which would redirty the inode and
+	 * hence result in an infinite loop of trying to write the inode.
+	 * There is no need to mark the base inode nor the base mft record
+	 * dirty, since we are going to write this mft record below in any case
+	 * and the base mft record may actually not have been modified so it
+	 * might not need to be written out.
 	 */
-	if (!NInoTestSetDirty(ctx->ntfs_ino))
+	if (modified && !NInoTestSetDirty(ctx->ntfs_ino))
 		__set_page_dirty_nobuffers(ctx->ntfs_ino->page);
-	put_attr_search_ctx(ctx);
-#endif
-	/* Write this base mft record. */
+	ntfs_attr_put_search_ctx(ctx);
+	/* Now the access times are updated, write the base mft record. */
 	if (NInoDirty(ni))
 		err = write_mft_record(ni, m, sync);
 	/* Write all attached extent mft records. */
@@ -2391,7 +2521,7 @@
 				MFT_RECORD *tm = map_mft_record(tni);
 				int ret;
 
-				if (unlikely(IS_ERR(tm))) {
+				if (IS_ERR(tm)) {
 					if (!err || err == -ENOMEM)
 						err = PTR_ERR(tm);
 					continue;
@@ -2410,11 +2540,9 @@
 	if (unlikely(err))
 		goto err_out;
 	ntfs_debug("Done.");
-	return;
-#if 0
+	return 0;
 unm_err_out:
 	unmap_mft_record(ni);
-#endif
 err_out:
 	if (err == -ENOMEM) {
 		ntfs_warning(vi->i_sb, "Not enough memory to write inode.  "
@@ -2426,7 +2554,7 @@
 				"as bad.  You should run chkdsk.", -err);
 		make_bad_inode(vi);
 	}
-	return;
+	return err;
 }
 
 #endif /* NTFS_RW */
diff -Nru a/fs/ntfs/inode.h b/fs/ntfs/inode.h
--- a/fs/ntfs/inode.h	2004-10-18 14:56:49 -07:00
+++ b/fs/ntfs/inode.h	2004-10-18 14:56:49 -07:00
@@ -53,21 +53,21 @@
 	 * name_len = 0 for files and name = I30 (global constant) and
 	 * name_len = 4 for directories.
 	 */
-	ATTR_TYPES type;	/* Attribute type of this fake inode. */
+	ATTR_TYPE type;	/* Attribute type of this fake inode. */
 	ntfschar *name;		/* Attribute name of this fake inode. */
 	u32 name_len;		/* Attribute name length of this fake inode. */
-	run_list run_list;	/* If state has the NI_NonResident bit set,
-				   the run list of the unnamed data attribute
+	runlist runlist;	/* If state has the NI_NonResident bit set,
+				   the runlist of the unnamed data attribute
 				   (if a file) or of the index allocation
 				   attribute (directory) or of the attribute
 				   described by the fake inode (if NInoAttr()).
-				   If run_list.rl is NULL, the run list has not
+				   If runlist.rl is NULL, the runlist has not
 				   been read in yet or has been unmapped. If
 				   NI_NonResident is clear, the attribute is
 				   resident (file and fake inode) or there is
 				   no $I30 index allocation attribute
 				   (small directory). In the latter case
-				   run_list.rl is always NULL.*/
+				   runlist.rl is always NULL.*/
 	/*
 	 * The following fields are only valid for real inodes and extent
 	 * inodes.
@@ -88,7 +88,7 @@
 	 */
 	u32 attr_list_size;	/* Length of attribute list value in bytes. */
 	u8 *attr_list;		/* Attribute list value itself. */
-	run_list attr_list_rl;	/* Run list for the attribute list value. */
+	runlist attr_list_rl;	/* Run list for the attribute list value. */
 	union {
 		struct { /* It is a directory, $MFT, or an index inode. */
 			struct inode *bmp_ino;	/* Attribute inode for the
@@ -96,7 +96,7 @@
 			u32 block_size;		/* Size of an index block. */
 			u32 vcn_size;		/* Size of a vcn in this
 						   index. */
-			COLLATION_RULES collation_rule; /* The collation rule
+			COLLATION_RULE collation_rule; /* The collation rule
 						   for the index. */
 			u8 block_size_bits; 	/* Log2 of the above. */
 			u8 vcn_size_bits;	/* Log2 of the above. */
@@ -252,7 +252,7 @@
 	unsigned long mft_no;
 	ntfschar *name;
 	u32 name_len;
-	ATTR_TYPES type;
+	ATTR_TYPE type;
 } ntfs_attr;
 
 typedef int (*test_t)(struct inode *, void *);
@@ -260,7 +260,7 @@
 extern int ntfs_test_inode(struct inode *vi, ntfs_attr *na);
 
 extern struct inode *ntfs_iget(struct super_block *sb, unsigned long mft_no);
-extern struct inode *ntfs_attr_iget(struct inode *base_vi, ATTR_TYPES type,
+extern struct inode *ntfs_attr_iget(struct inode *base_vi, ATTR_TYPE type,
 		ntfschar *name, u32 name_len);
 extern struct inode *ntfs_index_iget(struct inode *base_vi, ntfschar *name,
 		u32 name_len);
@@ -285,7 +285,7 @@
 
 extern int ntfs_setattr(struct dentry *dentry, struct iattr *attr);
 
-extern void ntfs_write_inode(struct inode *vi, int sync);
+extern int ntfs_write_inode(struct inode *vi, int sync);
 
 static inline void ntfs_commit_inode(struct inode *vi)
 {
diff -Nru a/fs/ntfs/layout.h b/fs/ntfs/layout.h
--- a/fs/ntfs/layout.h	2004-10-18 14:56:32 -07:00
+++ b/fs/ntfs/layout.h	2004-10-18 14:56:32 -07:00
@@ -60,18 +60,18 @@
  * BIOS parameter block (bpb) structure.
  */
 typedef struct {
-	u16 bytes_per_sector;		/* Size of a sector in bytes. */
+	le16 bytes_per_sector;		/* Size of a sector in bytes. */
 	u8  sectors_per_cluster;	/* Size of a cluster in sectors. */
-	u16 reserved_sectors;		/* zero */
+	le16 reserved_sectors;		/* zero */
 	u8  fats;			/* zero */
-	u16 root_entries;		/* zero */
-	u16 sectors;			/* zero */
+	le16 root_entries;		/* zero */
+	le16 sectors;			/* zero */
 	u8  media_type;			/* 0xf8 = hard disk */
-	u16 sectors_per_fat;		/* zero */
-	u16 sectors_per_track;		/* irrelevant */
-	u16 heads;			/* irrelevant */
-	u32 hidden_sectors;		/* zero */
-	u32 large_sectors;		/* zero */
+	le16 sectors_per_fat;		/* zero */
+	le16 sectors_per_track;		/* irrelevant */
+	le16 heads;			/* irrelevant */
+	le32 hidden_sectors;		/* zero */
+	le32 large_sectors;		/* zero */
 } __attribute__ ((__packed__)) BIOS_PARAMETER_BLOCK;
 
 /*
@@ -79,7 +79,7 @@
  */
 typedef struct {
 	u8  jump[3];			/* Irrelevant (jump to boot up code).*/
-	u64 oem_id;			/* Magic "NTFS    ". */
+	le64 oem_id;			/* Magic "NTFS    ". */
 	BIOS_PARAMETER_BLOCK bpb;	/* See BIOS_PARAMETER_BLOCK. */
 	u8  unused[4];			/* zero, NTFS diskedit.exe states that
 					   this is actually:
@@ -89,21 +89,21 @@
 									// 0x80
 						__u8 unused;		// zero
 					 */
-/*0x28*/s64 number_of_sectors;		/* Number of sectors in volume. Gives
+/*0x28*/sle64 number_of_sectors;	/* Number of sectors in volume. Gives
 					   maximum volume size of 2^63 sectors.
 					   Assuming standard sector size of 512
 					   bytes, the maximum byte size is
 					   approx. 4.7x10^21 bytes. (-; */
-	s64 mft_lcn;			/* Cluster location of mft data. */
-	s64 mftmirr_lcn;		/* Cluster location of copy of mft. */
+	sle64 mft_lcn;			/* Cluster location of mft data. */
+	sle64 mftmirr_lcn;		/* Cluster location of copy of mft. */
 	s8  clusters_per_mft_record;	/* Mft record size in clusters. */
 	u8  reserved0[3];		/* zero */
 	s8  clusters_per_index_record;	/* Index block size in clusters. */
 	u8  reserved1[3];		/* zero */
-	u64 volume_serial_number;	/* Irrelevant (serial number). */
-	u32 checksum;			/* Boot sector checksum. */
+	le64 volume_serial_number;	/* Irrelevant (serial number). */
+	le32 checksum;			/* Boot sector checksum. */
 /*0x54*/u8  bootstrap[426];		/* Irrelevant (boot up code). */
-	u16 end_of_sector_marker;	/* End of bootsector magic. Always is
+	le16 end_of_sector_marker;	/* End of bootsector magic. Always is
 					   0xaa55 in little endian. */
 /* sizeof() = 512 (0x200) bytes */
 } __attribute__ ((__packed__)) NTFS_BOOT_SECTOR;
@@ -112,7 +112,7 @@
  * Magic identifiers present at the beginning of all ntfs record containing
  * records (like mft records for example).
  */
-typedef enum {
+enum {
 	/* Found in $MFT/$DATA. */
 	magic_FILE = const_cpu_to_le32(0x454c4946), /* Mft entry. */
 	magic_INDX = const_cpu_to_le32(0x58444e49), /* Index buffer. */
@@ -128,72 +128,80 @@
 	/* Found in all ntfs record containing records. */
 	magic_BAAD = const_cpu_to_le32(0x44414142), /* Failed multi sector
 						       transfer was detected. */
-
 	/*
-	 * Found in $LogFile/$DATA when a page is full or 0xff bytes and is
-	 * thus not initialized.  User has to initialize the page before using
-	 * it.
+	 * Found in $LogFile/$DATA when a page is full of 0xff bytes and is
+	 * thus not initialized.  Page must be initialized before using it.
 	 */
-	magic_empty = const_cpu_to_le32(0xffffffff),/* Record is empty and has
-						       to be initialized before
-						       it can be used. */
-} NTFS_RECORD_TYPES;
+	magic_empty = const_cpu_to_le32(0xffffffff) /* Record is empty. */
+};
+
+typedef le32 NTFS_RECORD_TYPE;
 
 /*
  * Generic magic comparison macros. Finally found a use for the ## preprocessor
  * operator! (-8
  */
-#define ntfs_is_magic(x, m)	(   (u32)(x) == magic_##m )
-#define ntfs_is_magicp(p, m)	( *(u32*)(p) == magic_##m )
 
-/*
- * Specialised magic comparison macros for the NTFS_RECORD_TYPES defined above.
- */
-#define ntfs_is_file_record(x)	( ntfs_is_magic (x, FILE) )
-#define ntfs_is_file_recordp(p)	( ntfs_is_magicp(p, FILE) )
-#define ntfs_is_mft_record(x)	( ntfs_is_file_record(x) )
-#define ntfs_is_mft_recordp(p)	( ntfs_is_file_recordp(p) )
-#define ntfs_is_indx_record(x)	( ntfs_is_magic (x, INDX) )
-#define ntfs_is_indx_recordp(p)	( ntfs_is_magicp(p, INDX) )
-#define ntfs_is_hole_record(x)	( ntfs_is_magic (x, HOLE) )
-#define ntfs_is_hole_recordp(p)	( ntfs_is_magicp(p, HOLE) )
-
-#define ntfs_is_rstr_record(x)	( ntfs_is_magic (x, RSTR) )
-#define ntfs_is_rstr_recordp(p)	( ntfs_is_magicp(p, RSTR) )
-#define ntfs_is_rcrd_record(x)	( ntfs_is_magic (x, RCRD) )
-#define ntfs_is_rcrd_recordp(p)	( ntfs_is_magicp(p, RCRD) )
+static inline BOOL __ntfs_is_magic(le32 x, NTFS_RECORD_TYPE r)
+{
+	return (x == r);
+}
+#define ntfs_is_magic(x, m)	__ntfs_is_magic(x, magic_##m)
+
+static inline BOOL __ntfs_is_magicp(le32 *p, NTFS_RECORD_TYPE r)
+{
+	return (*p == r);
+}
+#define ntfs_is_magicp(p, m)	__ntfs_is_magicp(p, magic_##m)
+
+/*
+ * Specialised magic comparison macros for the NTFS_RECORD_TYPEs defined above.
+ */
+#define ntfs_is_file_record(x)		( ntfs_is_magic (x, FILE) )
+#define ntfs_is_file_recordp(p)		( ntfs_is_magicp(p, FILE) )
+#define ntfs_is_mft_record(x)		( ntfs_is_file_record (x) )
+#define ntfs_is_mft_recordp(p)		( ntfs_is_file_recordp(p) )
+#define ntfs_is_indx_record(x)		( ntfs_is_magic (x, INDX) )
+#define ntfs_is_indx_recordp(p)		( ntfs_is_magicp(p, INDX) )
+#define ntfs_is_hole_record(x)		( ntfs_is_magic (x, HOLE) )
+#define ntfs_is_hole_recordp(p)		( ntfs_is_magicp(p, HOLE) )
+
+#define ntfs_is_rstr_record(x)		( ntfs_is_magic (x, RSTR) )
+#define ntfs_is_rstr_recordp(p)		( ntfs_is_magicp(p, RSTR) )
+#define ntfs_is_rcrd_record(x)		( ntfs_is_magic (x, RCRD) )
+#define ntfs_is_rcrd_recordp(p)		( ntfs_is_magicp(p, RCRD) )
 
-#define ntfs_is_chkd_record(x)	( ntfs_is_magic (x, CHKD) )
-#define ntfs_is_chkd_recordp(p)	( ntfs_is_magicp(p, CHKD) )
+#define ntfs_is_chkd_record(x)		( ntfs_is_magic (x, CHKD) )
+#define ntfs_is_chkd_recordp(p)		( ntfs_is_magicp(p, CHKD) )
 
-#define ntfs_is_baad_record(x)	( ntfs_is_magic (x, BAAD) )
-#define ntfs_is_baad_recordp(p)	( ntfs_is_magicp(p, BAAD) )
+#define ntfs_is_baad_record(x)		( ntfs_is_magic (x, BAAD) )
+#define ntfs_is_baad_recordp(p)		( ntfs_is_magicp(p, BAAD) )
 
 #define ntfs_is_empty_record(x)		( ntfs_is_magic (x, empty) )
 #define ntfs_is_empty_recordp(p)	( ntfs_is_magicp(p, empty) )
 
 /*
- * The Update Sequence Array (usa) is an array of the u16 values which belong
+ * The Update Sequence Array (usa) is an array of the le16 values which belong
  * to the end of each sector protected by the update sequence record in which
  * this array is contained. Note that the first entry is the Update Sequence
  * Number (usn), a cyclic counter of how many times the protected record has
  * been written to disk. The values 0 and -1 (ie. 0xffff) are not used. All
- * last u16's of each sector have to be equal to the usn (during reading) or
+ * last le16's of each sector have to be equal to the usn (during reading) or
  * are set to it (during writing). If they are not, an incomplete multi sector
  * transfer has occurred when the data was written.
  * The maximum size for the update sequence array is fixed to:
  *	maximum size = usa_ofs + (usa_count * 2) = 510 bytes
- * The 510 bytes comes from the fact that the last u16 in the array has to
- * (obviously) finish before the last u16 of the first 512-byte sector.
+ * The 510 bytes comes from the fact that the last le16 in the array has to
+ * (obviously) finish before the last le16 of the first 512-byte sector.
  * This formula can be used as a consistency check in that usa_ofs +
  * (usa_count * 2) has to be less than or equal to 510.
  */
 typedef struct {
-	NTFS_RECORD_TYPES magic;	/* A four-byte magic identifying the
-					   record type and/or status. */
-	u16 usa_ofs;		/* Offset to the Update Sequence Array (usa)
+	NTFS_RECORD_TYPE magic;	/* A four-byte magic identifying the record
+				   type and/or status. */
+	le16 usa_ofs;		/* Offset to the Update Sequence Array (usa)
 				   from the start of the ntfs record. */
-	u16 usa_count;		/* Number of u16 sized entries in the usa
+	le16 usa_count;		/* Number of le16 sized entries in the usa
 				   including the Update Sequence Number (usn),
 				   thus the number of fixups is the usa_count
 				   minus 1. */
@@ -249,11 +257,12 @@
  * These are the so far known MFT_RECORD_* flags (16-bit) which contain
  * information about the mft record in which they are present.
  */
-typedef enum {
+enum {
 	MFT_RECORD_IN_USE	= const_cpu_to_le16(0x0001),
-	MFT_RECORD_IS_DIRECTORY	= const_cpu_to_le16(0x0002),
-	MFT_REC_SPACE_FILLER	= 0xffff	/* Just to make flags 16-bit. */
-} __attribute__ ((__packed__)) MFT_RECORD_FLAGS;
+	MFT_RECORD_IS_DIRECTORY = const_cpu_to_le16(0x0002),
+};
+
+typedef le16 MFT_RECORD_FLAGS;
 
 /*
  * mft references (aka file references or file record segment references) are
@@ -305,6 +314,7 @@
 } MFT_REF_CONSTS;
 
 typedef u64 MFT_REF;
+typedef le64 leMFT_REF;
 
 #define MREF(x)		((unsigned long)((x) & MFT_REF_MASK_CPU))
 #define MSEQNO(x)	((u16)(((x) >> 48) & 0xffff))
@@ -325,18 +335,18 @@
 typedef struct {
 /*Ofs*/
 /*  0	NTFS_RECORD; -- Unfolded here as gcc doesn't like unnamed structs. */
-	NTFS_RECORD_TYPES magic;/* Usually the magic is "FILE". */
-	u16 usa_ofs;		/* See NTFS_RECORD definition above. */
-	u16 usa_count;		/* See NTFS_RECORD definition above. */
+	NTFS_RECORD_TYPE magic;	/* Usually the magic is "FILE". */
+	le16 usa_ofs;		/* See NTFS_RECORD definition above. */
+	le16 usa_count;		/* See NTFS_RECORD definition above. */
 
-/*  8*/	u64 lsn;		/* $LogFile sequence number for this record.
+/*  8*/	le64 lsn;		/* $LogFile sequence number for this record.
 				   Changed every time the record is modified. */
-/* 16*/	u16 sequence_number;	/* Number of times this mft record has been
+/* 16*/	le16 sequence_number;	/* Number of times this mft record has been
 				   reused. (See description for MFT_REF
 				   above.) NOTE: The increment (skipping zero)
 				   is done when the file is deleted. NOTE: If
 				   this is zero it is left zero. */
-/* 18*/	u16 link_count;		/* Number of hard links, i.e. the number of
+/* 18*/	le16 link_count;	/* Number of hard links, i.e. the number of
 				   directory entries referencing this record.
 				   NOTE: Only used in mft base records.
 				   NOTE: When deleting a directory entry we
@@ -346,18 +356,18 @@
 				   directory entry from the mft record and
 				   decrement the link_count.
 				   FIXME: Careful with Win32 + DOS names! */
-/* 20*/	u16 attrs_offset;	/* Byte offset to the first attribute in this
+/* 20*/	le16 attrs_offset;	/* Byte offset to the first attribute in this
 				   mft record from the start of the mft record.
 				   NOTE: Must be aligned to 8-byte boundary. */
 /* 22*/	MFT_RECORD_FLAGS flags;	/* Bit array of MFT_RECORD_FLAGS. When a file
 				   is deleted, the MFT_RECORD_IN_USE flag is
 				   set to zero. */
-/* 24*/	u32 bytes_in_use;	/* Number of bytes used in this mft record.
+/* 24*/	le32 bytes_in_use;	/* Number of bytes used in this mft record.
 				   NOTE: Must be aligned to 8-byte boundary. */
-/* 28*/	u32 bytes_allocated;	/* Number of bytes allocated for this mft
+/* 28*/	le32 bytes_allocated;	/* Number of bytes allocated for this mft
 				   record. This should be equal to the mft
 				   record size. */
-/* 32*/	MFT_REF base_mft_record; /* This is zero for base mft records.
+/* 32*/	leMFT_REF base_mft_record;/* This is zero for base mft records.
 				   When it is not zero it is a mft reference
 				   pointing to the base mft record to which
 				   this record belongs (this is then used to
@@ -369,17 +379,16 @@
 				   attribute list also means finding the other
 				   potential extents, belonging to the non-base
 				   mft record). */
-/* 40*/	u16 next_attr_instance;	/* The instance number that will be
-				   assigned to the next attribute added to this
-				   mft record. NOTE: Incremented each time
-				   after it is used. NOTE: Every time the mft
-				   record is reused this number is set to zero.
-				   NOTE: The first instance number is always 0.
-				 */
+/* 40*/	le16 next_attr_instance;/* The instance number that will be assigned to
+				   the next attribute added to this mft record.
+				   NOTE: Incremented each time after it is used.
+				   NOTE: Every time the mft record is reused
+				   this number is set to zero.  NOTE: The first
+				   instance number is always 0. */
 /* sizeof() = 42 bytes */
 /* NTFS 3.1+ (Windows XP and above) introduce the following additions. */
-/* 42*/ //u16 reserved;		/* Reserved/alignment. */
-/* 44*/ //u32 mft_record_number;/* Number of this mft record. */
+/* 42*/ //le16 reserved;	/* Reserved/alignment. */
+/* 44*/ //le32 mft_record_number;/* Number of this mft record. */
 /* sizeof() = 48 bytes */
 /*
  * When (re)using the mft record, we place the update sequence array at this
@@ -393,15 +402,15 @@
 } __attribute__ ((__packed__)) MFT_RECORD;
 
 /*
- * System defined attributes (32-bit). Each attribute type has a corresponding
+ * System defined attributes (32-bit).  Each attribute type has a corresponding
  * attribute name (Unicode string of maximum 64 character length) as described
  * by the attribute definitions present in the data attribute of the $AttrDef
- * system file. On NTFS 3.0 volumes the names are just as the types are named
- * in the below enum exchanging AT_ for the dollar sign ($). If that isn't a
- * revealing choice of symbol... (-;
+ * system file.  On NTFS 3.0 volumes the names are just as the types are named
+ * in the below defines exchanging AT_ for the dollar sign ($).  If that is not
+ * a revealing choice of symbol I do not know what is... (-;
  */
-typedef enum {
-	AT_UNUSED			= const_cpu_to_le32(	     0),
+enum {
+	AT_UNUSED			= const_cpu_to_le32(         0),
 	AT_STANDARD_INFORMATION		= const_cpu_to_le32(      0x10),
 	AT_ATTRIBUTE_LIST		= const_cpu_to_le32(      0x20),
 	AT_FILE_NAME			= const_cpu_to_le32(      0x30),
@@ -419,12 +428,16 @@
 	AT_PROPERTY_SET			= const_cpu_to_le32(      0xf0),
 	AT_LOGGED_UTILITY_STREAM	= const_cpu_to_le32(     0x100),
 	AT_FIRST_USER_DEFINED_ATTRIBUTE	= const_cpu_to_le32(    0x1000),
-	AT_END				= const_cpu_to_le32(0xffffffff),
-} ATTR_TYPES;
+	AT_END				= const_cpu_to_le32(0xffffffff)
+};
+
+typedef le32 ATTR_TYPE;
 
 /*
  * The collation rules for sorting views/indexes/etc (32-bit).
  *
+ * COLLATION_BINARY - Collate by binary compare where the first byte is most
+ *	significant.
  * COLLATION_UNICODE_STRING - Collate Unicode strings by comparing their binary
  *	Unicode values, except that when a character can be uppercased, the
  *	upper case value collates before the lower case one.
@@ -435,63 +448,59 @@
  *	unistr.c::ntfs_collate_names() and unistr.c::legal_ansi_char_array[]
  *	for what I mean but COLLATION_UNICODE_STRING would not give any special
  *	treatment to any characters at all, but this is speculation.
- * COLLATION_NTOFS_ULONG - Sorting is done according to ascending u32 key
+ * COLLATION_NTOFS_ULONG - Sorting is done according to ascending le32 key
  *	values. E.g. used for $SII index in FILE_Secure, which sorts by
- *	security_id (u32).
+ *	security_id (le32).
  * COLLATION_NTOFS_SID - Sorting is done according to ascending SID values.
  *	E.g. used for $O index in FILE_Extend/$Quota.
  * COLLATION_NTOFS_SECURITY_HASH - Sorting is done first by ascending hash
  *	values and second by ascending security_id values. E.g. used for $SDH
  *	index in FILE_Secure.
  * COLLATION_NTOFS_ULONGS - Sorting is done according to a sequence of ascending
- *	u32 key values. E.g. used for $O index in FILE_Extend/$ObjId, which
+ *	le32 key values. E.g. used for $O index in FILE_Extend/$ObjId, which
  *	sorts by object_id (16-byte), by splitting up the object_id in four
- *	u32 values and using them as individual keys. E.g. take the following
+ *	le32 values and using them as individual keys. E.g. take the following
  *	two security_ids, stored as follows on disk:
  *		1st: a1 61 65 b7 65 7b d4 11 9e 3d 00 e0 81 10 42 59
  *		2nd: 38 14 37 d2 d2 f3 d4 11 a5 21 c8 6b 79 b1 97 45
- *	To compare them, they are split into four u32 values each, like so:
+ *	To compare them, they are split into four le32 values each, like so:
  *		1st: 0xb76561a1 0x11d47b65 0xe0003d9e 0x59421081
  *		2nd: 0xd2371438 0x11d4f3d2 0x6bc821a5 0x4597b179
  *	Now, it is apparent why the 2nd object_id collates after the 1st: the
- *	first u32 value of the 1st object_id is less than the first u32 of
- *	the 2nd object_id. If the first u32 values of both object_ids were
- *	equal then the second u32 values would be compared, etc.
- */
-typedef enum {
-	COLLATION_BINARY	 = const_cpu_to_le32(0x00), /* Collate by
-					binary compare where the first byte is
-					most significant. */
-	COLLATION_FILE_NAME	 = const_cpu_to_le32(0x01), /* Collate file
-					names as Unicode strings. */
-	COLLATION_UNICODE_STRING = const_cpu_to_le32(0x02), /* Collate Unicode
-					strings by comparing their binary
-					Unicode values, except that when a
-					character can be uppercased, the upper
-					case value collates before the lower
-					case one. */
+ *	first le32 value of the 1st object_id is less than the first le32 of
+ *	the 2nd object_id. If the first le32 values of both object_ids were
+ *	equal then the second le32 values would be compared, etc.
+ */
+enum {
+	COLLATION_BINARY		= const_cpu_to_le32(0x00),
+	COLLATION_FILE_NAME		= const_cpu_to_le32(0x01),
+	COLLATION_UNICODE_STRING	= const_cpu_to_le32(0x02),
 	COLLATION_NTOFS_ULONG		= const_cpu_to_le32(0x10),
 	COLLATION_NTOFS_SID		= const_cpu_to_le32(0x11),
 	COLLATION_NTOFS_SECURITY_HASH	= const_cpu_to_le32(0x12),
-	COLLATION_NTOFS_ULONGS		= const_cpu_to_le32(0x13),
-} COLLATION_RULES;
+	COLLATION_NTOFS_ULONGS		= const_cpu_to_le32(0x13)
+};
+
+typedef le32 COLLATION_RULE;
 
 /*
  * The flags (32-bit) describing attribute properties in the attribute
- * definition structure. FIXME: This information is from Regis's information
+ * definition structure.  FIXME: This information is from Regis's information
  * and, according to him, it is not certain and probably incomplete.
  * The INDEXABLE flag is fairly certainly correct as only the file name
  * attribute has this flag set and this is the only attribute indexed in NT4.
  */
-typedef enum {
-	INDEXABLE	    = const_cpu_to_le32(0x02),	/* Attribute can be
-							   indexed. */
-	NEED_TO_REGENERATE  = const_cpu_to_le32(0x40),	/* Need to regenerate
-							   during regeneration
-							   phase. */
-	CAN_BE_NON_RESIDENT = const_cpu_to_le32(0x80),	/* Attribute can be
-							   non-resident. */
-} ATTR_DEF_FLAGS;
+enum {
+	INDEXABLE	    = const_cpu_to_le32(0x02), /* Attribute can be
+							  indexed. */
+	NEED_TO_REGENERATE  = const_cpu_to_le32(0x40), /* Need to regenerate
+							  during regeneration
+							  phase. */
+	CAN_BE_NON_RESIDENT = const_cpu_to_le32(0x80), /* Attribute can be
+							  non-resident. */
+};
+
+typedef le32 ATTR_DEF_FLAGS;
 
 /*
  * The data attribute of FILE_AttrDef contains a sequence of attribute
@@ -506,27 +515,29 @@
 /*hex ofs*/
 /*  0*/	ntfschar name[0x40];		/* Unicode name of the attribute. Zero
 					   terminated. */
-/* 80*/	ATTR_TYPES type;		/* Type of the attribute. */
-/* 84*/	u32 display_rule;		/* Default display rule.
+/* 80*/	ATTR_TYPE type;			/* Type of the attribute. */
+/* 84*/	le32 display_rule;		/* Default display rule.
 					   FIXME: What does it mean? (AIA) */
-/* 88*/ COLLATION_RULES collation_rule;	/* Default collation rule. */
+/* 88*/ COLLATION_RULE collation_rule;	/* Default collation rule. */
 /* 8c*/	ATTR_DEF_FLAGS flags;		/* Flags describing the attribute. */
-/* 90*/	u64 min_size;			/* Optional minimum attribute size. */
-/* 98*/	u64 max_size;			/* Maximum size of attribute. */
+/* 90*/	le64 min_size;			/* Optional minimum attribute size. */
+/* 98*/	le64 max_size;			/* Maximum size of attribute. */
 /* sizeof() = 0xa0 or 160 bytes */
 } __attribute__ ((__packed__)) ATTR_DEF;
 
 /*
  * Attribute flags (16-bit).
  */
-typedef enum {
-	ATTR_IS_COMPRESSED	= const_cpu_to_le16(0x0001),
-	ATTR_COMPRESSION_MASK	= const_cpu_to_le16(0x00ff),  /* Compression
-						method mask. Also, first
-						illegal value. */
-	ATTR_IS_ENCRYPTED	= const_cpu_to_le16(0x4000),
-	ATTR_IS_SPARSE		= const_cpu_to_le16(0x8000),
-} __attribute__ ((__packed__)) ATTR_FLAGS;
+enum {
+	ATTR_IS_COMPRESSED    = const_cpu_to_le16(0x0001),
+	ATTR_COMPRESSION_MASK = const_cpu_to_le16(0x00ff), /* Compression method
+							      mask.  Also, first
+							      illegal value. */
+	ATTR_IS_ENCRYPTED     = const_cpu_to_le16(0x4000),
+	ATTR_IS_SPARSE	      = const_cpu_to_le16(0x8000),
+} __attribute__ ((__packed__));
+
+typedef le16 ATTR_FLAGS;
 
 /*
  * Attribute compression.
@@ -545,7 +556,7 @@
  * can be stored:
  *
  *   1) The data in the block is all zero (a sparse block):
- *	  This is stored as a sparse block in the run list, i.e. the run list
+ *	  This is stored as a sparse block in the runlist, i.e. the runlist
  *	  entry has length = X and lcn = -1. The mapping pairs array actually
  *	  uses a delta_lcn value length of 0, i.e. delta_lcn is not present at
  *	  all, which is then interpreted by the driver as lcn = -1.
@@ -558,7 +569,7 @@
  *	  in clusters. I.e. if compression has a small effect so that the
  *	  compressed data still occupies X clusters, then the uncompressed data
  *	  is stored in the block.
- *	  This case is recognised by the fact that the run list entry has
+ *	  This case is recognised by the fact that the runlist entry has
  *	  length = X and lcn >= 0. The mapping pairs array stores this as
  *	  normal with a run length of X and some specific delta_lcn, i.e.
  *	  delta_lcn has to be present.
@@ -567,7 +578,7 @@
  *	  The common case. This case is recognised by the fact that the run
  *	  list entry has length L < X and lcn >= 0. The mapping pairs array
  *	  stores this as normal with a run length of X and some specific
- *	  delta_lcn, i.e. delta_lcn has to be present. This run list entry is
+ *	  delta_lcn, i.e. delta_lcn has to be present. This runlist entry is
  *	  immediately followed by a sparse entry with length = X - L and
  *	  lcn = -1. The latter entry is to make up the vcn counting to the
  *	  full compression block size X.
@@ -575,15 +586,15 @@
  * In fact, life is more complicated because adjacent entries of the same type
  * can be coalesced. This means that one has to keep track of the number of
  * clusters handled and work on a basis of X clusters at a time being one
- * block. An example: if length L > X this means that this particular run list
+ * block. An example: if length L > X this means that this particular runlist
  * entry contains a block of length X and part of one or more blocks of length
  * L - X. Another example: if length L < X, this does not necessarily mean that
  * the block is compressed as it might be that the lcn changes inside the block
- * and hence the following run list entry describes the continuation of the
+ * and hence the following runlist entry describes the continuation of the
  * potentially compressed block. The block would be compressed if the
- * following run list entry describes at least X - L sparse clusters, thus
+ * following runlist entry describes at least X - L sparse clusters, thus
  * making up the compression block length as described in point 3 above. (Of
- * course, there can be several run list entries with small lengths so that the
+ * course, there can be several runlist entries with small lengths so that the
  * sparse entry does not follow the first data containing entry with
  * length < X.)
  *
@@ -598,26 +609,28 @@
 /*
  * Flags of resident attributes (8-bit).
  */
-typedef enum {
+enum {
 	RESIDENT_ATTR_IS_INDEXED = 0x01, /* Attribute is referenced in an index
 					    (has implications for deleting and
 					    modifying the attribute). */
-} __attribute__ ((__packed__)) RESIDENT_ATTR_FLAGS;
+} __attribute__ ((__packed__));
+
+typedef u8 RESIDENT_ATTR_FLAGS;
 
 /*
  * Attribute record header. Always aligned to 8-byte boundary.
  */
 typedef struct {
 /*Ofs*/
-/*  0*/	ATTR_TYPES type;	/* The (32-bit) type of the attribute. */
-/*  4*/	u32 length;		/* Byte size of the resident part of the
+/*  0*/	ATTR_TYPE type;		/* The (32-bit) type of the attribute. */
+/*  4*/	le32 length;		/* Byte size of the resident part of the
 				   attribute (aligned to 8-byte boundary).
 				   Used to get to the next attribute. */
 /*  8*/	u8 non_resident;	/* If 0, attribute is resident.
 				   If 1, attribute is non-resident. */
 /*  9*/	u8 name_length;		/* Unicode character size of name of attribute.
 				   0 if unnamed. */
-/* 10*/	u16 name_offset;	/* If name_length != 0, the byte offset to the
+/* 10*/	le16 name_offset;	/* If name_length != 0, the byte offset to the
 				   beginning of the name from the attribute
 				   record. Note that the name is stored as a
 				   Unicode string. When creating, place offset
@@ -627,15 +640,15 @@
 				   respectively, aligning to an 8-byte
 				   boundary. */
 /* 12*/	ATTR_FLAGS flags;	/* Flags describing the attribute. */
-/* 14*/	u16 instance;		/* The instance of this attribute record. This
+/* 14*/	le16 instance;		/* The instance of this attribute record. This
 				   number is unique within this mft record (see
 				   MFT_RECORD/next_attribute_instance notes in
 				   in mft.h for more details). */
 /* 16*/	union {
 		/* Resident attributes. */
 		struct {
-/* 16 */		u32 value_length; /* Byte size of attribute value. */
-/* 20 */		u16 value_offset; /* Byte offset of the attribute
+/* 16 */		le32 value_length;/* Byte size of attribute value. */
+/* 20 */		le16 value_offset;/* Byte offset of the attribute
 					     value from the start of the
 					     attribute record. When creating,
 					     align to 8-byte boundary if we
@@ -648,18 +661,18 @@
 		} __attribute__ ((__packed__)) resident;
 		/* Non-resident attributes. */
 		struct {
-/* 16*/			VCN lowest_vcn;	/* Lowest valid virtual cluster number
+/* 16*/			leVCN lowest_vcn;/* Lowest valid virtual cluster number
 				for this portion of the attribute value or
 				0 if this is the only extent (usually the
 				case). - Only when an attribute list is used
 				does lowest_vcn != 0 ever occur. */
-/* 24*/			VCN highest_vcn; /* Highest valid vcn of this extent of
+/* 24*/			leVCN highest_vcn;/* Highest valid vcn of this extent of
 				the attribute value. - Usually there is only one
 				portion, so this usually equals the attribute
 				value size in clusters minus 1. Can be -1 for
 				zero length files. Can be 0 for "single extent"
 				attributes. */
-/* 32*/			u16 mapping_pairs_offset; /* Byte offset from the
+/* 32*/			le16 mapping_pairs_offset; /* Byte offset from the
 				beginning of the structure to the mapping pairs
 				array which contains the mappings between the
 				vcns and the logical cluster numbers (lcns).
@@ -674,7 +687,7 @@
 /* 35*/			u8 reserved[5];		/* Align to 8-byte boundary. */
 /* The sizes below are only used when lowest_vcn is zero, as otherwise it would
    be difficult to keep them up-to-date.*/
-/* 40*/			s64 allocated_size;	/* Byte size of disk space
+/* 40*/			sle64 allocated_size;	/* Byte size of disk space
 				allocated to hold the attribute value. Always
 				is a multiple of the cluster size. When a file
 				is compressed, this field is a multiple of the
@@ -682,14 +695,14 @@
 				it represents the logically allocated space
 				rather than the actual on disk usage. For this
 				use the compressed_size (see below). */
-/* 48*/			s64 data_size;	/* Byte size of the attribute
+/* 48*/			sle64 data_size;	/* Byte size of the attribute
 				value. Can be larger than allocated_size if
 				attribute value is compressed or sparse. */
-/* 56*/			s64 initialized_size;	/* Byte size of initialized
+/* 56*/			sle64 initialized_size;	/* Byte size of initialized
 				portion of the attribute value. Usually equals
 				data_size. */
 /* sizeof(uncompressed attr) = 64*/
-/* 64*/			s64 compressed_size;	/* Byte size of the attribute
+/* 64*/			sle64 compressed_size;	/* Byte size of the attribute
 				value after compression. Only present when
 				compressed. Always is a multiple of the
 				cluster size. Represents the actual amount of
@@ -704,19 +717,19 @@
 /*
  * File attribute flags (32-bit).
  */
-typedef enum {
+enum {
 	/*
-	 * These flags are only present in the STANDARD_INFORMATION attribute
-	 * (in the field file_attributes).
+	 * The following flags are only present in the STANDARD_INFORMATION
+	 * attribute (in the field file_attributes).
 	 */
 	FILE_ATTR_READONLY		= const_cpu_to_le32(0x00000001),
 	FILE_ATTR_HIDDEN		= const_cpu_to_le32(0x00000002),
 	FILE_ATTR_SYSTEM		= const_cpu_to_le32(0x00000004),
-	/* Old DOS volid. Unused in NT.	= cpu_to_le32(0x00000008), */
+	/* Old DOS volid. Unused in NT.	= const_cpu_to_le32(0x00000008), */
 
 	FILE_ATTR_DIRECTORY		= const_cpu_to_le32(0x00000010),
-	/* FILE_ATTR_DIRECTORY is not considered valid in NT. It is reserved
-	   for the DOS SUBDIRECTORY flag. */
+	/* Note, FILE_ATTR_DIRECTORY is not considered valid in NT.  It is
+	   reserved for the DOS SUBDIRECTORY flag. */
 	FILE_ATTR_ARCHIVE		= const_cpu_to_le32(0x00000020),
 	FILE_ATTR_DEVICE		= const_cpu_to_le32(0x00000040),
 	FILE_ATTR_NORMAL		= const_cpu_to_le32(0x00000080),
@@ -731,29 +744,31 @@
 	FILE_ATTR_ENCRYPTED		= const_cpu_to_le32(0x00004000),
 
 	FILE_ATTR_VALID_FLAGS		= const_cpu_to_le32(0x00007fb7),
-	/* FILE_ATTR_VALID_FLAGS masks out the old DOS VolId and the
-	   FILE_ATTR_DEVICE and preserves everything else. This mask
-	   is used to obtain all flags that are valid for reading. */
+	/* Note, FILE_ATTR_VALID_FLAGS masks out the old DOS VolId and the
+	   FILE_ATTR_DEVICE and preserves everything else.  This mask is used
+	   to obtain all flags that are valid for reading. */
 	FILE_ATTR_VALID_SET_FLAGS	= const_cpu_to_le32(0x000031a7),
-	/* FILE_ATTR_VALID_SET_FLAGS masks out the old DOS VolId, the
+	/* Note, FILE_ATTR_VALID_SET_FLAGS masks out the old DOS VolId, the
 	   F_A_DEVICE, F_A_DIRECTORY, F_A_SPARSE_FILE, F_A_REPARSE_POINT,
-	   F_A_COMPRESSED and F_A_ENCRYPTED and preserves the rest. This mask
+	   F_A_COMPRESSED, and F_A_ENCRYPTED and preserves the rest.  This mask
 	   is used to to obtain all flags that are valid for setting. */
 
 	/*
-	 * These flags are only present in the FILE_NAME attribute (in the
-	 * field file_attributes).
+	 * The following flags are only present in the FILE_NAME attribute (in
+	 * the field file_attributes).
 	 */
 	FILE_ATTR_DUP_FILE_NAME_INDEX_PRESENT	= const_cpu_to_le32(0x10000000),
-	/* This is a copy of the corresponding bit from the mft record, telling
-	   us whether this is a directory or not, i.e. whether it has an
-	   index root attribute or not. */
+	/* Note, this is a copy of the corresponding bit from the mft record,
+	   telling us whether this is a directory or not, i.e. whether it has
+	   an index root attribute or not. */
 	FILE_ATTR_DUP_VIEW_INDEX_PRESENT	= const_cpu_to_le32(0x20000000),
-	/* This is a copy of the corresponding bit from the mft record, telling
-	   us whether this file has a view index present (eg. object id index,
-	   quota index, one of the security indexes or the encrypting file
-	   system related indexes). */
-} FILE_ATTR_FLAGS;
+	/* Note, this is a copy of the corresponding bit from the mft record,
+	   telling us whether this file has a view index present (eg. object id
+	   index, quota index, one of the security indexes or the encrypting
+	   file system related indexes). */
+};
+
+typedef le32 FILE_ATTR_FLAGS;
 
 /*
  * NOTE on times in NTFS: All times are in MS standard time format, i.e. they
@@ -774,13 +789,13 @@
  */
 typedef struct {
 /*Ofs*/
-/*  0*/	s64 creation_time;		/* Time file was created. Updated when
+/*  0*/	sle64 creation_time;		/* Time file was created. Updated when
 					   a filename is changed(?). */
-/*  8*/	s64 last_data_change_time;	/* Time the data attribute was last
+/*  8*/	sle64 last_data_change_time;	/* Time the data attribute was last
 					   modified. */
-/* 16*/	s64 last_mft_change_time;	/* Time this mft record was last
+/* 16*/	sle64 last_mft_change_time;	/* Time this mft record was last
 					   modified. */
-/* 24*/	s64 last_access_time;		/* Approximate time when the file was
+/* 24*/	sle64 last_access_time;		/* Approximate time when the file was
 					   last accessed (obviously this is not
 					   updated on read-only volumes). In
 					   Windows this is only updated when
@@ -817,23 +832,23 @@
  * views that as a corruption, assuming that it behaves like this for all
  * attributes.
  */
-		/* 36*/	u32 maximum_versions;	/* Maximum allowed versions for
+		/* 36*/	le32 maximum_versions;	/* Maximum allowed versions for
 				file. Zero if version numbering is disabled. */
-		/* 40*/	u32 version_number;	/* This file's version (if any).
+		/* 40*/	le32 version_number;	/* This file's version (if any).
 				Set to zero if maximum_versions is zero. */
-		/* 44*/	u32 class_id;		/* Class id from bidirectional
+		/* 44*/	le32 class_id;		/* Class id from bidirectional
 				class id index (?). */
-		/* 48*/	u32 owner_id;		/* Owner_id of the user owning
+		/* 48*/	le32 owner_id;		/* Owner_id of the user owning
 				the file. Translate via $Q index in FILE_Extend
 				/$Quota to the quota control entry for the user
 				owning the file. Zero if quotas are disabled. */
-		/* 52*/	u32 security_id;	/* Security_id for the file.
+		/* 52*/	le32 security_id;	/* Security_id for the file.
 				Translate via $SII index and $SDS data stream
 				in FILE_Secure to the security descriptor. */
-		/* 56*/	u64 quota_charged;	/* Byte size of the charge to
+		/* 56*/	le64 quota_charged;	/* Byte size of the charge to
 				the quota for all streams of the file. Note: Is
 				zero if quotas are disabled. */
-		/* 64*/	u64 usn;		/* Last update sequence number
+		/* 64*/	le64 usn;		/* Last update sequence number
 				of the file. This is a direct index into the
 				change (aka usn) journal file. It is zero if
 				the usn journal is disabled.
@@ -886,14 +901,14 @@
  */
 typedef struct {
 /*Ofs*/
-/*  0*/	ATTR_TYPES type;	/* Type of referenced attribute. */
-/*  4*/	u16 length;		/* Byte size of this entry (8-byte aligned). */
+/*  0*/	ATTR_TYPE type;		/* Type of referenced attribute. */
+/*  4*/	le16 length;		/* Byte size of this entry (8-byte aligned). */
 /*  6*/	u8 name_length;		/* Size in Unicode chars of the name of the
 				   attribute or 0 if unnamed. */
 /*  7*/	u8 name_offset;		/* Byte offset to beginning of attribute name
 				   (always set this to where the name would
 				   start even if unnamed). */
-/*  8*/	VCN lowest_vcn;		/* Lowest virtual cluster number of this portion
+/*  8*/	leVCN lowest_vcn;	/* Lowest virtual cluster number of this portion
 				   of the attribute value. This is usually 0. It
 				   is non-zero for the case where one attribute
 				   does not fit into one mft record and thus
@@ -905,10 +920,10 @@
 				   value! The windows driver uses cmp, followed
 				   by jg when comparing this, thus it treats it
 				   as signed. */
-/* 16*/	MFT_REF mft_reference;	/* The reference of the mft record holding
+/* 16*/	leMFT_REF mft_reference;/* The reference of the mft record holding
 				   the ATTR_RECORD for this portion of the
 				   attribute value. */
-/* 24*/	u16 instance;		/* If lowest_vcn = 0, the instance of the
+/* 24*/	le16 instance;		/* If lowest_vcn = 0, the instance of the
 				   attribute being referenced; otherwise 0. */
 /* 26*/	ntfschar name[0];	/* Use when creating only. When reading use
 				   name_offset to determine the location of the
@@ -924,28 +939,28 @@
 /*
  * Possible namespaces for filenames in ntfs (8-bit).
  */
-typedef enum {
-	FILE_NAME_POSIX			= 0x00,
-		/* This is the largest namespace. It is case sensitive and
-		   allows all Unicode characters except for: '\0' and '/'.
-		   Beware that in WinNT/2k files which eg have the same name
-		   except for their case will not be distinguished by the
-		   standard utilities and thus a "del filename" will delete
-		   both "filename" and "fileName" without warning. */
-	FILE_NAME_WIN32			= 0x01,
-		/* The standard WinNT/2k NTFS long filenames. Case insensitive.
-		   All Unicode chars except: '\0', '"', '*', '/', ':', '<',
-		   '>', '?', '\' and '|'. Further, names cannot end with a '.'
-		   or a space. */
-	FILE_NAME_DOS			= 0x02,
-		/* The standard DOS filenames (8.3 format). Uppercase only.
-		   All 8-bit characters greater space, except: '"', '*', '+',
-		   ',', '/', ':', ';', '<', '=', '>', '?' and '\'. */
-	FILE_NAME_WIN32_AND_DOS		= 0x03,
-		/* 3 means that both the Win32 and the DOS filenames are
-		   identical and hence have been saved in this single filename
-		   record. */
-} __attribute__ ((__packed__)) FILE_NAME_TYPE_FLAGS;
+enum {
+	FILE_NAME_POSIX		= 0x00,
+	/* This is the largest namespace. It is case sensitive and allows all
+	   Unicode characters except for: '\0' and '/'.  Beware that in
+	   WinNT/2k files which eg have the same name except for their case
+	   will not be distinguished by the standard utilities and thus a "del
+	   filename" will delete both "filename" and "fileName" without
+	   warning. */
+	FILE_NAME_WIN32		= 0x01,
+	/* The standard WinNT/2k NTFS long filenames. Case insensitive.  All
+	   Unicode chars except: '\0', '"', '*', '/', ':', '<', '>', '?', '\',
+	   and '|'.  Further, names cannot end with a '.' or a space. */
+	FILE_NAME_DOS		= 0x02,
+	/* The standard DOS filenames (8.3 format). Uppercase only.  All 8-bit
+	   characters greater space, except: '"', '*', '+', ',', '/', ':', ';',
+	   '<', '=', '>', '?', and '\'. */
+	FILE_NAME_WIN32_AND_DOS	= 0x03,
+	/* 3 means that both the Win32 and the DOS filenames are identical and
+	   hence have been saved in this single filename record. */
+} __attribute__ ((__packed__));
+
+typedef u8 FILE_NAME_TYPE_FLAGS;
 
 /*
  * Attribute: Filename (0x30).
@@ -962,30 +977,30 @@
  */
 typedef struct {
 /*hex ofs*/
-/*  0*/	MFT_REF parent_directory;	/* Directory this filename is
+/*  0*/	leMFT_REF parent_directory;	/* Directory this filename is
 					   referenced from. */
-/*  8*/	s64 creation_time;		/* Time file was created. */
-/* 10*/	s64 last_data_change_time;	/* Time the data attribute was last
+/*  8*/	sle64 creation_time;		/* Time file was created. */
+/* 10*/	sle64 last_data_change_time;	/* Time the data attribute was last
 					   modified. */
-/* 18*/	s64 last_mft_change_time;	/* Time this mft record was last
+/* 18*/	sle64 last_mft_change_time;	/* Time this mft record was last
 					   modified. */
-/* 20*/	s64 last_access_time;		/* Time this mft record was last
+/* 20*/	sle64 last_access_time;		/* Time this mft record was last
 					   accessed. */
-/* 28*/	s64 allocated_size;		/* Byte size of allocated space for the
+/* 28*/	sle64 allocated_size;		/* Byte size of allocated space for the
 					   data attribute. NOTE: Is a multiple
 					   of the cluster size. */
-/* 30*/	s64 data_size;			/* Byte size of actual data in data
+/* 30*/	sle64 data_size;		/* Byte size of actual data in data
 					   attribute. */
 /* 38*/	FILE_ATTR_FLAGS file_attributes;	/* Flags describing the file. */
 /* 3c*/	union {
 	/* 3c*/	struct {
-		/* 3c*/	u16 packed_ea_size;	/* Size of the buffer needed to
+		/* 3c*/	le16 packed_ea_size;	/* Size of the buffer needed to
 						   pack the extended attributes
 						   (EAs), if such are present.*/
-		/* 3e*/	u16 reserved;		/* Reserved for alignment. */
+		/* 3e*/	le16 reserved;		/* Reserved for alignment. */
 		} __attribute__ ((__packed__)) ea;
 	/* 3c*/	struct {
-		/* 3c*/	u32 reparse_point_tag;	/* Type of reparse point,
+		/* 3c*/	le32 reparse_point_tag;	/* Type of reparse point,
 						   present only in reparse
 						   points and only if there are
 						   no EAs. */
@@ -1007,9 +1022,9 @@
  *	1F010768-5A73-BC91-0010A52216A7
  */
 typedef struct {
-	u32 data1;	/* The first eight hexadecimal digits of the GUID. */
-	u16 data2;	/* The first group of four hexadecimal digits. */
-	u16 data3;	/* The second group of four hexadecimal digits. */
+	le32 data1;	/* The first eight hexadecimal digits of the GUID. */
+	le16 data2;	/* The first group of four hexadecimal digits. */
+	le16 data3;	/* The second group of four hexadecimal digits. */
 	u8 data4[8];	/* The first two bytes are the third group of four
 			   hexadecimal digits. The remaining six bytes are the
 			   final 12 hexadecimal digits. */
@@ -1027,7 +1042,7 @@
  *	domain_id	- Reserved (always zero).
  */
 typedef struct {
-	MFT_REF mft_reference;	/* Mft record containing the object_id in
+	leMFT_REF mft_reference;/* Mft record containing the object_id in
 				   the index entry key. */
 	union {
 		struct {
@@ -1195,13 +1210,16 @@
 
 /*
  * The SID_IDENTIFIER_AUTHORITY is a 48-bit value used in the SID structure.
+ *
+ * NOTE: This is stored as a big endian number, hence the high_part comes
+ * before the low_part.
  */
 typedef union {
 	struct {
-		u32 low;	/* Low 32-bits. */
-		u16 high;	/* High 16-bits. */
+		u16 high_part;	/* High 16-bits. */
+		u32 low_part;	/* Low 32-bits. */
 	} __attribute__ ((__packed__)) parts;
-	u8 value[6];			/* Value as individual bytes. */
+	u8 value[6];		/* Value as individual bytes. */
 } __attribute__ ((__packed__)) SID_IDENTIFIER_AUTHORITY;
 
 /*
@@ -1232,7 +1250,7 @@
 	u8 revision;
 	u8 sub_authority_count;
 	SID_IDENTIFIER_AUTHORITY identifier_authority;
-	u32 sub_authority[1];		/* At least one sub_authority. */
+	le32 sub_authority[1];		/* At least one sub_authority. */
 } __attribute__ ((__packed__)) SID;
 
 /*
@@ -1248,7 +1266,7 @@
 /*
  * The predefined ACE types (8-bit, see below).
  */
-typedef enum {
+enum {
 	ACCESS_MIN_MS_ACE_TYPE		= 0,
 	ACCESS_ALLOWED_ACE_TYPE		= 0,
 	ACCESS_DENIED_ACE_TYPE		= 1,
@@ -1269,9 +1287,11 @@
 
 	ACCESS_MAX_MS_V4_ACE_TYPE	= 8,
 
-	/* This one is for WinNT&2k. */
+	/* This one is for WinNT/2k. */
 	ACCESS_MAX_MS_ACE_TYPE		= 8,
-} __attribute__ ((__packed__)) ACE_TYPES;
+} __attribute__ ((__packed__));
+
+typedef u8 ACE_TYPES;
 
 /*
  * The ACE flags (8-bit) for audit and inheritance (see below).
@@ -1283,7 +1303,7 @@
  * FAILED_ACCESS_ACE_FLAG is only used with system audit and alarm ACE types
  * to indicate that a message is generated (in Windows!) for failed accesses.
  */
-typedef enum {
+enum {
 	/* The inheritance flags. */
 	OBJECT_INHERIT_ACE		= 0x01,
 	CONTAINER_INHERIT_ACE		= 0x02,
@@ -1295,7 +1315,9 @@
 	/* The audit flags. */
 	SUCCESSFUL_ACCESS_ACE_FLAG	= 0x40,
 	FAILED_ACCESS_ACE_FLAG		= 0x80,
-} __attribute__ ((__packed__)) ACE_FLAGS;
+} __attribute__ ((__packed__));
+
+typedef u8 ACE_FLAGS;
 
 /*
  * An ACE is an access-control entry in an access-control list (ACL).
@@ -1312,18 +1334,16 @@
 /*Ofs*/
 /*  0*/	ACE_TYPES type;		/* Type of the ACE. */
 /*  1*/	ACE_FLAGS flags;	/* Flags describing the ACE. */
-/*  2*/	u16 size;		/* Size in bytes of the ACE. */
+/*  2*/	le16 size;		/* Size in bytes of the ACE. */
 } __attribute__ ((__packed__)) ACE_HEADER;
 
 /*
  * The access mask (32-bit). Defines the access rights.
+ *
+ * The specific rights (bits 0 to 15).  These depend on the type of the object
+ * being secured by the ACE.
  */
-typedef enum {
-	/*
-	 * The specific rights (bits 0 to 15). Depend on the type of the
-	 * object being secured by the ACE.
-	 */
-
+enum {
 	/* Specific rights for files and directories are as follows: */
 
 	/* Right to read data from the file. (FILE) */
@@ -1365,8 +1385,8 @@
 	FILE_WRITE_ATTRIBUTES		= const_cpu_to_le32(0x00000100),
 
 	/*
-	 * The standard rights (bits 16 to 23). Are independent of the type of
-	 * object being secured.
+	 * The standard rights (bits 16 to 23).  These are independent of the
+	 * type of object being secured.
 	 */
 
 	/* Right to delete the object. */
@@ -1374,7 +1394,7 @@
 
 	/*
 	 * Right to read the information in the object's security descriptor,
-	 * not including the information in the SACL. I.e. right to read the
+	 * not including the information in the SACL, i.e. right to read the
 	 * security descriptor and owner.
 	 */
 	READ_CONTROL			= const_cpu_to_le32(0x00020000),
@@ -1386,8 +1406,8 @@
 	WRITE_OWNER			= const_cpu_to_le32(0x00080000),
 
 	/*
-	 * Right to use the object for synchronization. Enables a process to
-	 * wait until the object is in the signalled state. Some object types
+	 * Right to use the object for synchronization.  Enables a process to
+	 * wait until the object is in the signalled state.  Some object types
 	 * do not support this access right.
 	 */
 	SYNCHRONIZE			= const_cpu_to_le32(0x00100000),
@@ -1419,7 +1439,7 @@
 	MAXIMUM_ALLOWED			= const_cpu_to_le32(0x02000000),
 
 	/*
-	 * The generic rights (bits 28 to 31). These map onto the standard and
+	 * The generic rights (bits 28 to 31).  These map onto the standard and
 	 * specific rights.
 	 */
 
@@ -1430,23 +1450,25 @@
 	GENERIC_EXECUTE			= const_cpu_to_le32(0x20000000),
 
 	/*
-	 * Write access. For files, this maps onto:
+	 * Write access.  For files, this maps onto:
 	 *	FILE_APPEND_DATA | FILE_WRITE_ATTRIBUTES | FILE_WRITE_DATA |
 	 *	FILE_WRITE_EA | STANDARD_RIGHTS_WRITE | SYNCHRONIZE
-	 * For directories, the mapping has the same numberical value. See
+	 * For directories, the mapping has the same numerical value.  See
 	 * above for the descriptions of the rights granted.
 	 */
 	GENERIC_WRITE			= const_cpu_to_le32(0x40000000),
 
 	/*
-	 * Read access. For files, this maps onto:
+	 * Read access.  For files, this maps onto:
 	 *	FILE_READ_ATTRIBUTES | FILE_READ_DATA | FILE_READ_EA |
 	 *	STANDARD_RIGHTS_READ | SYNCHRONIZE
-	 * For directories, the mapping has the same numberical value. See
+	 * For directories, the mapping has the same numberical value.  See
 	 * above for the descriptions of the rights granted.
 	 */
 	GENERIC_READ			= const_cpu_to_le32(0x80000000),
-} ACCESS_MASK;
+};
+
+typedef le32 ACCESS_MASK;
 
 /*
  * The generic mapping array. Used to denote the mapping of each generic
@@ -1472,7 +1494,7 @@
 /*  0	ACE_HEADER; -- Unfolded here as gcc doesn't like unnamed structs. */
 	ACE_TYPES type;		/* Type of the ACE. */
 	ACE_FLAGS flags;	/* Flags describing the ACE. */
-	u16 size;		/* Size in bytes of the ACE. */
+	le16 size;		/* Size in bytes of the ACE. */
 /*  4*/	ACCESS_MASK mask;	/* Access mask associated with the ACE. */
 
 /*  8*/	SID sid;		/* The SID associated with the ACE. */
@@ -1482,16 +1504,18 @@
 /*
  * The object ACE flags (32-bit).
  */
-typedef enum {
+enum {
 	ACE_OBJECT_TYPE_PRESENT			= const_cpu_to_le32(1),
 	ACE_INHERITED_OBJECT_TYPE_PRESENT	= const_cpu_to_le32(2),
-} OBJECT_ACE_FLAGS;
+};
+
+typedef le32 OBJECT_ACE_FLAGS;
 
 typedef struct {
 /*  0	ACE_HEADER; -- Unfolded here as gcc doesn't like unnamed structs. */
 	ACE_TYPES type;		/* Type of the ACE. */
 	ACE_FLAGS flags;	/* Flags describing the ACE. */
-	u16 size;		/* Size in bytes of the ACE. */
+	le16 size;		/* Size in bytes of the ACE. */
 /*  4*/	ACCESS_MASK mask;	/* Access mask associated with the ACE. */
 
 /*  8*/	OBJECT_ACE_FLAGS object_flags;	/* Flags describing the object ACE. */
@@ -1514,10 +1538,10 @@
 typedef struct {
 	u8 revision;	/* Revision of this ACL. */
 	u8 alignment1;
-	u16 size;	/* Allocated space in bytes for ACL. Includes this
+	le16 size;	/* Allocated space in bytes for ACL. Includes this
 			   header, the ACEs and the remaining free space. */
-	u16 ace_count;	/* Number of ACEs in the ACL. */
-	u16 alignment2;
+	le16 ace_count;	/* Number of ACEs in the ACL. */
+	le16 alignment2;
 /* sizeof() = 8 bytes */
 } __attribute__ ((__packed__)) ACL;
 
@@ -1582,22 +1606,27 @@
  *	security descriptor are contiguous in memory and all pointer fields are
  *	expressed as offsets from the beginning of the security descriptor.
  */
-typedef enum {
+enum {
 	SE_OWNER_DEFAULTED		= const_cpu_to_le16(0x0001),
 	SE_GROUP_DEFAULTED		= const_cpu_to_le16(0x0002),
 	SE_DACL_PRESENT			= const_cpu_to_le16(0x0004),
 	SE_DACL_DEFAULTED		= const_cpu_to_le16(0x0008),
+
 	SE_SACL_PRESENT			= const_cpu_to_le16(0x0010),
 	SE_SACL_DEFAULTED		= const_cpu_to_le16(0x0020),
+
 	SE_DACL_AUTO_INHERIT_REQ	= const_cpu_to_le16(0x0100),
 	SE_SACL_AUTO_INHERIT_REQ	= const_cpu_to_le16(0x0200),
 	SE_DACL_AUTO_INHERITED		= const_cpu_to_le16(0x0400),
 	SE_SACL_AUTO_INHERITED		= const_cpu_to_le16(0x0800),
+
 	SE_DACL_PROTECTED		= const_cpu_to_le16(0x1000),
 	SE_SACL_PROTECTED		= const_cpu_to_le16(0x2000),
 	SE_RM_CONTROL_VALID		= const_cpu_to_le16(0x4000),
-	SE_SELF_RELATIVE		= const_cpu_to_le16(0x8000),
-} __attribute__ ((__packed__)) SECURITY_DESCRIPTOR_CONTROL;
+	SE_SELF_RELATIVE		= const_cpu_to_le16(0x8000)
+} __attribute__ ((__packed__));
+
+typedef le16 SECURITY_DESCRIPTOR_CONTROL;
 
 /*
  * Self-relative security descriptor. Contains the owner and group SIDs as well
@@ -1608,17 +1637,17 @@
 	u8 alignment;
 	SECURITY_DESCRIPTOR_CONTROL control; /* Flags qualifying the type of
 			   the descriptor as well as the following fields. */
-	u32 owner;	/* Byte offset to a SID representing an object's
+	le32 owner;	/* Byte offset to a SID representing an object's
 			   owner. If this is NULL, no owner SID is present in
 			   the descriptor. */
-	u32 group;	/* Byte offset to a SID representing an object's
+	le32 group;	/* Byte offset to a SID representing an object's
 			   primary group. If this is NULL, no primary group
 			   SID is present in the descriptor. */
-	u32 sacl;	/* Byte offset to a system ACL. Only valid, if
+	le32 sacl;	/* Byte offset to a system ACL. Only valid, if
 			   SE_SACL_PRESENT is set in the control field. If
 			   SE_SACL_PRESENT is set but sacl is NULL, a NULL ACL
 			   is specified. */
-	u32 dacl;	/* Byte offset to a discretionary ACL. Only valid, if
+	le32 dacl;	/* Byte offset to a discretionary ACL. Only valid, if
 			   SE_DACL_PRESENT is set in the control field. If
 			   SE_DACL_PRESENT is set but dacl is NULL, a NULL ACL
 			   (unconditionally granting access) is specified. */
@@ -1721,10 +1750,10 @@
  * This is also the index entry data part of both the $SII and $SDH indexes.
  */
 typedef struct {
-	u32 hash;	   /* Hash of the security descriptor. */
-	u32 security_id;   /* The security_id assigned to the descriptor. */
-	u64 offset;	   /* Byte offset of this entry in the $SDS stream. */
-	u32 length;	   /* Size in bytes of this entry in $SDS stream. */
+	le32 hash;	  /* Hash of the security descriptor. */
+	le32 security_id; /* The security_id assigned to the descriptor. */
+	le64 offset;	  /* Byte offset of this entry in the $SDS stream. */
+	le32 length;	  /* Size in bytes of this entry in $SDS stream. */
 } __attribute__ ((__packed__)) SECURITY_DESCRIPTOR_HEADER;
 
 /*
@@ -1742,10 +1771,10 @@
 /*Ofs*/
 /*  0	SECURITY_DESCRIPTOR_HEADER; -- Unfolded here as gcc doesn't like
 				       unnamed structs. */
-	u32 hash;	   /* Hash of the security descriptor. */
-	u32 security_id;   /* The security_id assigned to the descriptor. */
-	u64 offset;	   /* Byte offset of this entry in the $SDS stream. */
-	u32 length;	   /* Size in bytes of this entry in $SDS stream. */
+	le32 hash;	  /* Hash of the security descriptor. */
+	le32 security_id; /* The security_id assigned to the descriptor. */
+	le64 offset;	  /* Byte offset of this entry in the $SDS stream. */
+	le32 length;	  /* Size in bytes of this entry in $SDS stream. */
 /* 20*/	SECURITY_DESCRIPTOR_RELATIVE sid; /* The self-relative security
 					     descriptor. */
 } __attribute__ ((__packed__)) SDS_ENTRY;
@@ -1755,7 +1784,7 @@
  * COLLATION_NTOFS_ULONG.
  */
 typedef struct {
-	u32 security_id; /* The security_id assigned to the descriptor. */
+	le32 security_id; /* The security_id assigned to the descriptor. */
 } __attribute__ ((__packed__)) SII_INDEX_KEY;
 
 /*
@@ -1764,8 +1793,8 @@
  * COLLATION_NTOFS_SECURITY_HASH.
  */
 typedef struct {
-	u32 hash;	   /* Hash of the security descriptor. */
-	u32 security_id;   /* The security_id assigned to the descriptor. */
+	le32 hash;	  /* Hash of the security descriptor. */
+	le32 security_id; /* The security_id assigned to the descriptor. */
 } __attribute__ ((__packed__)) SDH_INDEX_KEY;
 
 /*
@@ -1781,19 +1810,24 @@
 /*
  * Possible flags for the volume (16-bit).
  */
-typedef enum {
+enum {
 	VOLUME_IS_DIRTY			= const_cpu_to_le16(0x0001),
 	VOLUME_RESIZE_LOG_FILE		= const_cpu_to_le16(0x0002),
 	VOLUME_UPGRADE_ON_MOUNT		= const_cpu_to_le16(0x0004),
 	VOLUME_MOUNTED_ON_NT4		= const_cpu_to_le16(0x0008),
+
 	VOLUME_DELETE_USN_UNDERWAY	= const_cpu_to_le16(0x0010),
 	VOLUME_REPAIR_OBJECT_ID		= const_cpu_to_le16(0x0020),
+
 	VOLUME_MODIFIED_BY_CHKDSK	= const_cpu_to_le16(0x8000),
+
 	VOLUME_FLAGS_MASK		= const_cpu_to_le16(0x803f),
 
 	/* To make our life easier when checking if we must mount read-only. */
 	VOLUME_MUST_MOUNT_RO_MASK	= const_cpu_to_le16(0x8037),
-} __attribute__ ((__packed__)) VOLUME_FLAGS;
+} __attribute__ ((__packed__));
+
+typedef le16 VOLUME_FLAGS;
 
 /*
  * Attribute: Volume information (0x70).
@@ -1804,7 +1838,7 @@
  *	 NTFS 1.2. I haven't personally seen other values yet.
  */
 typedef struct {
-	u64 reserved;		/* Not used (yet?). */
+	le64 reserved;		/* Not used (yet?). */
 	u8 major_ver;		/* Major version of the ntfs format. */
 	u8 minor_ver;		/* Minor version of the ntfs format. */
 	VOLUME_FLAGS flags;	/* Bit array of VOLUME_* flags. */
@@ -1824,24 +1858,28 @@
 /*
  * Index header flags (8-bit).
  */
-typedef enum {
-	/* When index header is in an index root attribute: */
-	SMALL_INDEX	= 0, /* The index is small enough to fit inside the
-				index root attribute and there is no index
-				allocation attribute present. */
-	LARGE_INDEX	= 1, /* The index is too large to fit in the index
-				root attribute and/or an index allocation
-				attribute is present. */
+enum {
+	/*
+	 * When index header is in an index root attribute:
+	 */
+	SMALL_INDEX = 0, /* The index is small enough to fit inside the index
+			    root attribute and there is no index allocation
+			    attribute present. */
+	LARGE_INDEX = 1, /* The index is too large to fit in the index root
+			    attribute and/or an index allocation attribute is
+			    present. */
 	/*
 	 * When index header is in an index block, i.e. is part of index
 	 * allocation attribute:
 	 */
-	LEAF_NODE	= 0, /* This is a leaf node, i.e. there are no more
-				nodes branching off it. */
-	INDEX_NODE	= 1, /* This node indexes other nodes, i.e. is not a
-				leaf node. */
-	NODE_MASK	= 1, /* Mask for accessing the *_NODE bits. */
-} __attribute__ ((__packed__)) INDEX_HEADER_FLAGS;
+	LEAF_NODE  = 0, /* This is a leaf node, i.e. there are no more nodes
+			   branching off it. */
+	INDEX_NODE = 1, /* This node indexes other nodes, i.e. it is not a leaf
+			   node. */
+	NODE_MASK  = 1, /* Mask for accessing the *_NODE bits. */
+} __attribute__ ((__packed__));
+
+typedef u8 INDEX_HEADER_FLAGS;
 
 /*
  * This is the header for indexes, describing the INDEX_ENTRY records, which
@@ -1853,12 +1891,12 @@
  * start of the index root or index allocation structures themselves.
  */
 typedef struct {
-	u32 entries_offset;		/* Byte offset to first INDEX_ENTRY
+	le32 entries_offset;		/* Byte offset to first INDEX_ENTRY
 					   aligned to 8-byte boundary. */
-	u32 index_length;		/* Data size of the index in bytes,
+	le32 index_length;		/* Data size of the index in bytes,
 					   i.e. bytes used from allocated
 					   size, aligned to 8-byte boundary. */
-	u32 allocated_size;		/* Byte size of this index (block),
+	le32 allocated_size;		/* Byte size of this index (block),
 					   multiple of 8 bytes. */
 	/* NOTE: For the index root attribute, the above two numbers are always
 	   equal, as the attribute is resident and it is resized as needed. In
@@ -1891,14 +1929,14 @@
  * dircetories do not contain entries for themselves, though.
  */
 typedef struct {
-	ATTR_TYPES type;		/* Type of the indexed attribute. Is
+	ATTR_TYPE type;			/* Type of the indexed attribute. Is
 					   $FILE_NAME for directories, zero
 					   for view indexes. No other values
 					   allowed. */
-	COLLATION_RULES collation_rule;	/* Collation rule used to sort the
+	COLLATION_RULE collation_rule;	/* Collation rule used to sort the
 					   index entries. If type is $FILE_NAME,
 					   this must be COLLATION_FILE_NAME. */
-	u32 index_block_size;		/* Size of each index block in bytes (in
+	le32 index_block_size;		/* Size of each index block in bytes (in
 					   the index allocation attribute). */
 	u8 clusters_per_index_block;	/* Cluster size of each index block (in
 					   the index allocation attribute), when
@@ -1924,13 +1962,13 @@
  */
 typedef struct {
 /*  0	NTFS_RECORD; -- Unfolded here as gcc doesn't like unnamed structs. */
-	NTFS_RECORD_TYPES magic;/* Magic is "INDX". */
-	u16 usa_ofs;		/* See NTFS_RECORD definition. */
-	u16 usa_count;		/* See NTFS_RECORD definition. */
+	NTFS_RECORD_TYPE magic;	/* Magic is "INDX". */
+	le16 usa_ofs;		/* See NTFS_RECORD definition. */
+	le16 usa_count;		/* See NTFS_RECORD definition. */
 
-/*  8*/	s64 lsn;		/* $LogFile sequence number of the last
+/*  8*/	sle64 lsn;		/* $LogFile sequence number of the last
 				   modification of this index block. */
-/* 16*/	VCN index_block_vcn;	/* Virtual cluster number of the index block.
+/* 16*/	leVCN index_block_vcn;	/* Virtual cluster number of the index block.
 				   If the cluster_size on the volume is <= the
 				   index_block_size of the directory,
 				   index_block_vcn counts in units of clusters,
@@ -1960,34 +1998,40 @@
  * primary key / is not a key at all. (AIA)
  */
 typedef struct {
-	u32 reparse_tag;	/* Reparse point type (inc. flags). */
-	MFT_REF file_id;	/* Mft record of the file containing the
+	le32 reparse_tag;	/* Reparse point type (inc. flags). */
+	leMFT_REF file_id;	/* Mft record of the file containing the
 				   reparse point attribute. */
 } __attribute__ ((__packed__)) REPARSE_INDEX_KEY;
 
 /*
  * Quota flags (32-bit).
+ *
+ * The user quota flags.  Names explain meaning.
  */
-typedef enum {
-	/* The user quota flags. Names explain meaning. */
+enum {
 	QUOTA_FLAG_DEFAULT_LIMITS	= const_cpu_to_le32(0x00000001),
 	QUOTA_FLAG_LIMIT_REACHED	= const_cpu_to_le32(0x00000002),
 	QUOTA_FLAG_ID_DELETED		= const_cpu_to_le32(0x00000004),
 
 	QUOTA_FLAG_USER_MASK		= const_cpu_to_le32(0x00000007),
-		/* Bit mask for user quota flags. */
+	/* This is a bit mask for the user quota flags. */
 
-	/* These flags are only present in the quota defaults index entry,
-	   i.e. in the entry where owner_id = QUOTA_DEFAULTS_ID. */
+	/*
+	 * These flags are only present in the quota defaults index entry, i.e.
+	 * in the entry where owner_id = QUOTA_DEFAULTS_ID.
+	 */
 	QUOTA_FLAG_TRACKING_ENABLED	= const_cpu_to_le32(0x00000010),
 	QUOTA_FLAG_ENFORCEMENT_ENABLED	= const_cpu_to_le32(0x00000020),
 	QUOTA_FLAG_TRACKING_REQUESTED	= const_cpu_to_le32(0x00000040),
 	QUOTA_FLAG_LOG_THRESHOLD	= const_cpu_to_le32(0x00000080),
+
 	QUOTA_FLAG_LOG_LIMIT		= const_cpu_to_le32(0x00000100),
 	QUOTA_FLAG_OUT_OF_DATE		= const_cpu_to_le32(0x00000200),
 	QUOTA_FLAG_CORRUPT		= const_cpu_to_le32(0x00000400),
 	QUOTA_FLAG_PENDING_DELETES	= const_cpu_to_le32(0x00000800),
-} QUOTA_FLAGS;
+};
+
+typedef le32 QUOTA_FLAGS;
 
 /*
  * The system file FILE_Extend/$Quota contains two indexes $O and $Q. Quotas
@@ -2011,13 +2055,13 @@
  * The $Q index entry data is the quota control entry and is defined below.
  */
 typedef struct {
-	u32 version;		/* Currently equals 2. */
+	le32 version;		/* Currently equals 2. */
 	QUOTA_FLAGS flags;	/* Flags describing this quota entry. */
-	u64 bytes_used;		/* How many bytes of the quota are in use. */
-	s64 change_time;	/* Last time this quota entry was changed. */
-	s64 threshold;		/* Soft quota (-1 if not limited). */
-	s64 limit;		/* Hard quota (-1 if not limited). */
-	s64 exceeded_time;	/* How long the soft quota has been exceeded. */
+	le64 bytes_used;	/* How many bytes of the quota are in use. */
+	sle64 change_time;	/* Last time this quota entry was changed. */
+	sle64 threshold;	/* Soft quota (-1 if not limited). */
+	sle64 limit;		/* Hard quota (-1 if not limited). */
+	sle64 exceeded_time;	/* How long the soft quota has been exceeded. */
 	SID sid;		/* The SID of the user/object associated with
 				   this quota entry.  Equals zero for the quota
 				   defaults entry (and in fact on a WinXP
@@ -2027,11 +2071,11 @@
 /*
  * Predefined owner_id values (32-bit).
  */
-typedef enum {
+enum {
 	QUOTA_INVALID_ID	= const_cpu_to_le32(0x00000000),
 	QUOTA_DEFAULTS_ID	= const_cpu_to_le32(0x00000001),
 	QUOTA_FIRST_USER_ID	= const_cpu_to_le32(0x00000100),
-} PREDEFINED_OWNER_IDS;
+};
 
 /*
  * Current constants for quota control entries.
@@ -2044,18 +2088,19 @@
 /*
  * Index entry flags (16-bit).
  */
-typedef enum {
+enum {
 	INDEX_ENTRY_NODE = const_cpu_to_le16(1), /* This entry contains a
-					      sub-node, i.e. a reference to an
-					      index block in form of a virtual
-					      cluster number (see below). */
+			sub-node, i.e. a reference to an index block in form of
+			a virtual cluster number (see below). */
 	INDEX_ENTRY_END  = const_cpu_to_le16(2), /* This signifies the last
-					      entry in an index block.  The
-					      index entry does not represent a
-					      file but it can point to a
-					      sub-node. */
-	INDEX_ENTRY_SPACE_FILLER = 0xffff, /* Just to force 16-bit width. */
-} __attribute__ ((__packed__)) INDEX_ENTRY_FLAGS;
+			entry in an index block.  The index entry does not
+			represent a file but it can point to a sub-node. */
+
+	INDEX_ENTRY_SPACE_FILLER = const_cpu_to_le16(0xffff), /* gcc: Force
+			enum bit width to 16-bit. */
+} __attribute__ ((__packed__));
+
+typedef le16 INDEX_ENTRY_FLAGS;
 
 /*
  * This the index entry header (see below).
@@ -2063,26 +2108,26 @@
 typedef struct {
 /*  0*/	union {
 		struct { /* Only valid when INDEX_ENTRY_END is not set. */
-			MFT_REF indexed_file;	/* The mft reference of the file
+			leMFT_REF indexed_file;	/* The mft reference of the file
 						   described by this index
 						   entry. Used for directory
 						   indexes. */
 		} __attribute__ ((__packed__)) dir;
 		struct { /* Used for views/indexes to find the entry's data. */
-			u16 data_offset;	/* Data byte offset from this
+			le16 data_offset;	/* Data byte offset from this
 						   INDEX_ENTRY. Follows the
 						   index key. */
-			u16 data_length;	/* Data length in bytes. */
-			u32 reservedV;		/* Reserved (zero). */
+			le16 data_length;	/* Data length in bytes. */
+			le32 reservedV;		/* Reserved (zero). */
 		} __attribute__ ((__packed__)) vi;
 	} __attribute__ ((__packed__)) data;
-/*  8*/	u16 length;		 /* Byte size of this index entry, multiple of
+/*  8*/	le16 length;		 /* Byte size of this index entry, multiple of
 				    8-bytes. */
-/* 10*/	u16 key_length;		 /* Byte size of the key value, which is in the
+/* 10*/	le16 key_length;	 /* Byte size of the key value, which is in the
 				    index entry. It follows field reserved. Not
 				    multiple of 8-bytes. */
 /* 12*/	INDEX_ENTRY_FLAGS flags; /* Bit field of INDEX_ENTRY_* flags. */
-/* 14*/	u16 reserved;		 /* Reserved/align to 8-byte boundary. */
+/* 14*/	le16 reserved;		 /* Reserved/align to 8-byte boundary. */
 /* sizeof() = 16 bytes */
 } __attribute__ ((__packed__)) INDEX_ENTRY_HEADER;
 
@@ -2098,26 +2143,26 @@
 /*  0	INDEX_ENTRY_HEADER; -- Unfolded here as gcc dislikes unnamed structs. */
 	union {
 		struct { /* Only valid when INDEX_ENTRY_END is not set. */
-			MFT_REF indexed_file;	/* The mft reference of the file
+			leMFT_REF indexed_file;	/* The mft reference of the file
 						   described by this index
 						   entry. Used for directory
 						   indexes. */
 		} __attribute__ ((__packed__)) dir;
 		struct { /* Used for views/indexes to find the entry's data. */
-			u16 data_offset;	/* Data byte offset from this
+			le16 data_offset;	/* Data byte offset from this
 						   INDEX_ENTRY. Follows the
 						   index key. */
-			u16 data_length;	/* Data length in bytes. */
-			u32 reservedV;		/* Reserved (zero). */
+			le16 data_length;	/* Data length in bytes. */
+			le32 reservedV;		/* Reserved (zero). */
 		} __attribute__ ((__packed__)) vi;
 	} __attribute__ ((__packed__)) data;
-	u16 length;		 /* Byte size of this index entry, multiple of
+	le16 length;		 /* Byte size of this index entry, multiple of
 				    8-bytes. */
-	u16 key_length;		 /* Byte size of the key value, which is in the
+	le16 key_length;	 /* Byte size of the key value, which is in the
 				    index entry. It follows field reserved. Not
 				    multiple of 8-bytes. */
 	INDEX_ENTRY_FLAGS flags; /* Bit field of INDEX_ENTRY_* flags. */
-	u16 reserved;		 /* Reserved/align to 8-byte boundary. */
+	le16 reserved;		 /* Reserved/align to 8-byte boundary. */
 
 /* 16*/	union {		/* The key of the indexed attribute. NOTE: Only present
 			   if INDEX_ENTRY_END bit in flags is not set. NOTE: On
@@ -2134,13 +2179,13 @@
 						   FILE_Extend/$Reparse. */
 		SID sid;		/* $O index in FILE_Extend/$Quota:
 					   SID of the owner of the user_id. */
-		u32 owner_id;		/* $Q index in FILE_Extend/$Quota:
+		le32 owner_id;		/* $Q index in FILE_Extend/$Quota:
 					   user_id of the owner of the quota
 					   control entry in the data part of
 					   the index. */
 	} __attribute__ ((__packed__)) key;
 	/* The (optional) index data is inserted here when creating. */
-	// VCN vcn;	/* If INDEX_ENTRY_NODE bit in flags is set, the last
+	// leVCN vcn;	/* If INDEX_ENTRY_NODE bit in flags is set, the last
 	//		   eight bytes of this index entry contain the virtual
 	//		   cluster number of the index block that holds the
 	//		   entries immediately preceding the current entry (the
@@ -2185,8 +2230,10 @@
  *		be slow. (E.g. the data is stored on a tape drive.)
  *	bit 31: Microsoft bit. If set, the tag is owned by Microsoft. User
  *		defined tags have to use zero here.
+ *
+ * These are the predefined reparse point tags:
  */
-typedef enum {
+enum {
 	IO_REPARSE_TAG_IS_ALIAS		= const_cpu_to_le32(0x20000000),
 	IO_REPARSE_TAG_IS_HIGH_LATENCY	= const_cpu_to_le32(0x40000000),
 	IO_REPARSE_TAG_IS_MICROSOFT	= const_cpu_to_le32(0x80000000),
@@ -2207,7 +2254,7 @@
 	IO_REPARSE_TAG_SYMBOLIC_LINK	= const_cpu_to_le32(0xe8000000),
 
 	IO_REPARSE_TAG_VALID_VALUES	= const_cpu_to_le32(0xe000ffff),
-} PREDEFINED_REPARSE_TAGS;
+};
 
 /*
  * Attribute: Reparse point (0xc0).
@@ -2215,9 +2262,9 @@
  * NOTE: Can be resident or non-resident.
  */
 typedef struct {
-	u32 reparse_tag;		/* Reparse point type (inc. flags). */
-	u16 reparse_data_length;	/* Byte size of reparse data. */
-	u16 reserved;			/* Align to 8-byte boundary. */
+	le32 reparse_tag;		/* Reparse point type (inc. flags). */
+	le16 reparse_data_length;	/* Byte size of reparse data. */
+	le16 reserved;			/* Align to 8-byte boundary. */
 	u8 reparse_data[0];		/* Meaning depends on reparse_tag. */
 } __attribute__ ((__packed__)) REPARSE_POINT;
 
@@ -2227,11 +2274,11 @@
  * NOTE: Always resident. (Is this true???)
  */
 typedef struct {
-	u16 ea_length;		/* Byte size of the packed extended
+	le16 ea_length;		/* Byte size of the packed extended
 				   attributes. */
-	u16 need_ea_count;	/* The number of extended attributes which have
+	le16 need_ea_count;	/* The number of extended attributes which have
 				   the NEED_EA bit set. */
-	u32 ea_query_length;	/* Byte size of the buffer required to query
+	le32 ea_query_length;	/* Byte size of the buffer required to query
 				   the extended attributes when calling
 				   ZwQueryEaFile() in Windows NT/2k. I.e. the
 				   byte size of the unpacked extended
@@ -2241,9 +2288,11 @@
 /*
  * Extended attribute flags (8-bit).
  */
-typedef enum {
-	NEED_EA	= 0x80,
-} __attribute__ ((__packed__)) EA_FLAGS;
+enum {
+	NEED_EA	= 0x80
+} __attribute__ ((__packed__));
+
+typedef u8 EA_FLAGS;
 
 /*
  * Attribute: Extended attribute (EA) (0xe0).
@@ -2256,10 +2305,10 @@
  * FIXME: It appears weird that the EA name is not unicode. Is it true?
  */
 typedef struct {
-	u32 next_entry_offset;	/* Offset to the next EA_ATTR. */
+	le32 next_entry_offset;	/* Offset to the next EA_ATTR. */
 	EA_FLAGS flags;		/* Flags describing the EA. */
 	u8 ea_name_length;	/* Length of the name of the EA in bytes. */
-	u16 ea_value_length;	/* Byte size of the EA's value. */
+	le16 ea_value_length;	/* Byte size of the EA's value. */
 	u8 ea_name[0];		/* Name of the EA. */
 	u8 ea_value[0];		/* The value of the EA. Immediately follows
 				   the name. */
diff -Nru a/fs/ntfs/lcnalloc.c b/fs/ntfs/lcnalloc.c
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/fs/ntfs/lcnalloc.c	2004-10-18 14:57:24 -07:00
@@ -0,0 +1,1001 @@
+/*
+ * lcnalloc.c - Cluster (de)allocation code.  Part of the Linux-NTFS project.
+ *
+ * Copyright (c) 2004 Anton Altaparmakov
+ *
+ * This program/include file 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/include file 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 (in the main directory of the Linux-NTFS
+ * distribution in the file COPYING); if not, write to the Free Software
+ * Foundation,Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#ifdef NTFS_RW
+
+#include <linux/pagemap.h>
+
+#include "lcnalloc.h"
+#include "debug.h"
+#include "bitmap.h"
+#include "inode.h"
+#include "volume.h"
+#include "attrib.h"
+#include "malloc.h"
+#include "ntfs.h"
+
+/**
+ * ntfs_cluster_free_from_rl_nolock - free clusters from runlist
+ * @vol:	mounted ntfs volume on which to free the clusters
+ * @rl:		runlist describing the clusters to free
+ *
+ * Free all the clusters described by the runlist @rl on the volume @vol.  In
+ * the case of an error being returned, at least some of the clusters were not
+ * freed.
+ *
+ * Return 0 on success and -errno on error.
+ *
+ * Locking: - The volume lcn bitmap must be locked for writing on entry and is
+ *	      left locked on return.
+ */
+static int ntfs_cluster_free_from_rl_nolock(ntfs_volume *vol,
+		const runlist_element *rl)
+{
+	struct inode *lcnbmp_vi = vol->lcnbmp_ino;
+	int ret = 0;
+
+	ntfs_debug("Entering.");
+	for (; rl->length; rl++) {
+		int err;
+
+		if (rl->lcn < 0)
+			continue;
+		err = ntfs_bitmap_clear_run(lcnbmp_vi, rl->lcn, rl->length);
+		if (unlikely(err && (!ret || ret == ENOMEM) && ret != err))
+			ret = err;
+	}
+	ntfs_debug("Done.");
+	return ret;
+}
+
+/**
+ * ntfs_cluster_alloc - allocate clusters on an ntfs volume
+ * @vol:	mounted ntfs volume on which to allocate the clusters
+ * @start_vcn:	vcn to use for the first allocated cluster
+ * @count:	number of clusters to allocate
+ * @start_lcn:	starting lcn at which to allocate the clusters (or -1 if none)
+ * @zone:	zone from which to allocate the clusters
+ *
+ * Allocate @count clusters preferably starting at cluster @start_lcn or at the
+ * current allocator position if @start_lcn is -1, on the mounted ntfs volume
+ * @vol. @zone is either DATA_ZONE for allocation of normal clusters or
+ * MFT_ZONE for allocation of clusters for the master file table, i.e. the
+ * $MFT/$DATA attribute.
+ *
+ * @start_vcn specifies the vcn of the first allocated cluster.  This makes
+ * merging the resulting runlist with the old runlist easier.
+ *
+ * You need to check the return value with IS_ERR().  If this is false, the
+ * function was successful and the return value is a runlist describing the
+ * allocated cluster(s).  If IS_ERR() is true, the function failed and
+ * PTR_ERR() gives you the error code.
+ *
+ * Notes on the allocation algorithm
+ * =================================
+ *
+ * There are two data zones.  First is the area between the end of the mft zone
+ * and the end of the volume, and second is the area between the start of the
+ * volume and the start of the mft zone.  On unmodified/standard NTFS 1.x
+ * volumes, the second data zone does not exist due to the mft zone being
+ * expanded to cover the start of the volume in order to reserve space for the
+ * mft bitmap attribute.
+ *
+ * This is not the prettiest function but the complexity stems from the need of
+ * implementing the mft vs data zoned approach and from the fact that we have
+ * access to the lcn bitmap in portions of up to 8192 bytes at a time, so we
+ * need to cope with crossing over boundaries of two buffers.  Further, the
+ * fact that the allocator allows for caller supplied hints as to the location
+ * of where allocation should begin and the fact that the allocator keeps track
+ * of where in the data zones the next natural allocation should occur,
+ * contribute to the complexity of the function.  But it should all be
+ * worthwhile, because this allocator should: 1) be a full implementation of
+ * the MFT zone approach used by Windows NT, 2) cause reduction in
+ * fragmentation, and 3) be speedy in allocations (the code is not optimized
+ * for speed, but the algorithm is, so further speed improvements are probably
+ * possible).
+ *
+ * FIXME: We should be monitoring cluster allocation and increment the MFT zone
+ * size dynamically but this is something for the future.  We will just cause
+ * heavier fragmentation by not doing it and I am not even sure Windows would
+ * grow the MFT zone dynamically, so it might even be correct not to do this.
+ * The overhead in doing dynamic MFT zone expansion would be very large and
+ * unlikely worth the effort. (AIA)
+ *
+ * TODO: I have added in double the required zone position pointer wrap around
+ * logic which can be optimized to having only one of the two logic sets.
+ * However, having the double logic will work fine, but if we have only one of
+ * the sets and we get it wrong somewhere, then we get into trouble, so
+ * removing the duplicate logic requires _very_ careful consideration of _all_
+ * possible code paths.  So at least for now, I am leaving the double logic -
+ * better safe than sorry... (AIA)
+ *
+ * Locking: - The volume lcn bitmap must be unlocked on entry and is unlocked
+ *	      on return.
+ *	    - This function takes the volume lcn bitmap lock for writing and
+ *	      modifies the bitmap contents.
+ */
+runlist_element *ntfs_cluster_alloc(ntfs_volume *vol, const VCN start_vcn,
+		const s64 count, const LCN start_lcn,
+		const NTFS_CLUSTER_ALLOCATION_ZONES zone)
+{
+	LCN zone_start, zone_end, bmp_pos, bmp_initial_pos, last_read_pos, lcn;
+	LCN prev_lcn = 0, prev_run_len = 0, mft_zone_size;
+	s64 clusters;
+	struct inode *lcnbmp_vi;
+	runlist_element *rl = NULL;
+	struct address_space *mapping;
+	struct page *page = NULL;
+	u8 *buf, *byte;
+	int err = 0, rlpos, rlsize, buf_size;
+	u8 pass, done_zones, search_zone, need_writeback = 0, bit;
+
+	ntfs_debug("Entering for start_vcn 0x%llx, count 0x%llx, start_lcn "
+			"0x%llx, zone %s_ZONE.", (unsigned long long)start_vcn,
+			(unsigned long long)count,
+			(unsigned long long)start_lcn,
+			zone == MFT_ZONE ? "MFT" : "DATA");
+	BUG_ON(!vol);
+	lcnbmp_vi = vol->lcnbmp_ino;
+	BUG_ON(!lcnbmp_vi);
+	BUG_ON(start_vcn < 0);
+	BUG_ON(count < 0);
+	BUG_ON(start_lcn < -1);
+	BUG_ON(zone < FIRST_ZONE);
+	BUG_ON(zone > LAST_ZONE);
+
+	/* Return empty runlist if @count == 0 */
+	// FIXME: Do we want to just return NULL instead? (AIA)
+	if (!count) {
+		rl = ntfs_malloc_nofs(PAGE_SIZE);
+		if (!rl)
+			return ERR_PTR(-ENOMEM);
+		rl[0].vcn = start_vcn;
+		rl[0].lcn = LCN_RL_NOT_MAPPED;
+		rl[0].length = 0;
+		return rl;
+	}
+	/* Take the lcnbmp lock for writing. */
+	down_write(&vol->lcnbmp_lock);
+	/*
+	 * If no specific @start_lcn was requested, use the current data zone
+	 * position, otherwise use the requested @start_lcn but make sure it
+	 * lies outside the mft zone.  Also set done_zones to 0 (no zones done)
+	 * and pass depending on whether we are starting inside a zone (1) or
+	 * at the beginning of a zone (2).  If requesting from the MFT_ZONE,
+	 * we either start at the current position within the mft zone or at
+	 * the specified position.  If the latter is out of bounds then we start
+	 * at the beginning of the MFT_ZONE.
+	 */
+	done_zones = 0;
+	pass = 1;
+	/*
+	 * zone_start and zone_end are the current search range.  search_zone
+	 * is 1 for mft zone, 2 for data zone 1 (end of mft zone till end of
+	 * volume) and 4 for data zone 2 (start of volume till start of mft
+	 * zone).
+	 */
+	zone_start = start_lcn;
+	if (zone_start < 0) {
+		if (zone == DATA_ZONE)
+			zone_start = vol->data1_zone_pos;
+		else
+			zone_start = vol->mft_zone_pos;
+		if (!zone_start) {
+			/*
+			 * Zone starts at beginning of volume which means a
+			 * single pass is sufficient.
+			 */
+			pass = 2;
+		}
+	} else if (zone == DATA_ZONE && zone_start >= vol->mft_zone_start &&
+			zone_start < vol->mft_zone_end) {
+		zone_start = vol->mft_zone_end;
+		/*
+		 * Starting at beginning of data1_zone which means a single
+		 * pass in this zone is sufficient.
+		 */
+		pass = 2;
+	} else if (zone == MFT_ZONE && (zone_start < vol->mft_zone_start ||
+			zone_start >= vol->mft_zone_end)) {
+		zone_start = vol->mft_lcn;
+		if (!vol->mft_zone_end)
+			zone_start = 0;
+		/*
+		 * Starting at beginning of volume which means a single pass
+		 * is sufficient.
+		 */
+		pass = 2;
+	}
+	if (zone == MFT_ZONE) {
+		zone_end = vol->mft_zone_end;
+		search_zone = 1;
+	} else /* if (zone == DATA_ZONE) */ {
+		/* Skip searching the mft zone. */
+		done_zones |= 1;
+		if (zone_start >= vol->mft_zone_end) {
+			zone_end = vol->nr_clusters;
+			search_zone = 2;
+		} else {
+			zone_end = vol->mft_zone_start;
+			search_zone = 4;
+		}
+	}
+	/*
+	 * bmp_pos is the current bit position inside the bitmap.  We use
+	 * bmp_initial_pos to determine whether or not to do a zone switch.
+	 */
+	bmp_pos = bmp_initial_pos = zone_start;
+
+	/* Loop until all clusters are allocated, i.e. clusters == 0. */
+	clusters = count;
+	rlpos = rlsize = 0;
+	mapping = lcnbmp_vi->i_mapping;
+	while (1) {
+		ntfs_debug("Start of outer while loop: done_zones 0x%x, "
+				"search_zone %i, pass %i, zone_start 0x%llx, "
+				"zone_end 0x%llx, bmp_initial_pos 0x%llx, "
+				"bmp_pos 0x%llx, rlpos %i, rlsize %i.",
+				done_zones, search_zone, pass,
+				(unsigned long long)zone_start,
+				(unsigned long long)zone_end,
+				(unsigned long long)bmp_initial_pos,
+				(unsigned long long)bmp_pos, rlpos, rlsize);
+		/* Loop until we run out of free clusters. */
+		last_read_pos = bmp_pos >> 3;
+		ntfs_debug("last_read_pos 0x%llx.",
+				(unsigned long long)last_read_pos);
+		if (last_read_pos > lcnbmp_vi->i_size) {
+			ntfs_debug("End of attribute reached.  "
+					"Skipping to zone_pass_done.");
+			goto zone_pass_done;
+		}
+		if (likely(page)) {
+			if (need_writeback) {
+				ntfs_debug("Marking page dirty.");
+				flush_dcache_page(page);
+				set_page_dirty(page);
+				need_writeback = 0;
+			}
+			ntfs_unmap_page(page);
+		}
+		page = ntfs_map_page(mapping, last_read_pos >>
+				PAGE_CACHE_SHIFT);
+		if (IS_ERR(page)) {
+			err = PTR_ERR(page);
+			ntfs_error(vol->sb, "Failed to map page.");
+			goto out;
+		}
+		buf_size = last_read_pos & ~PAGE_CACHE_MASK;
+		buf = page_address(page) + buf_size;
+		buf_size = PAGE_CACHE_SIZE - buf_size;
+		if (unlikely(last_read_pos + buf_size > lcnbmp_vi->i_size))
+			buf_size = lcnbmp_vi->i_size - last_read_pos;
+		buf_size <<= 3;
+		lcn = bmp_pos & 7;
+		bmp_pos &= ~7;
+		ntfs_debug("Before inner while loop: buf_size %i, lcn 0x%llx, "
+				"bmp_pos 0x%llx, need_writeback %i.", buf_size,
+				(unsigned long long)lcn,
+				(unsigned long long)bmp_pos, need_writeback);
+		while (lcn < buf_size && lcn + bmp_pos < zone_end) {
+			byte = buf + (lcn >> 3);
+			ntfs_debug("In inner while loop: buf_size %i, "
+					"lcn 0x%llx, bmp_pos 0x%llx, "
+					"need_writeback %i, byte ofs 0x%x, "
+					"*byte 0x%x.", buf_size,
+					(unsigned long long)lcn,
+					(unsigned long long)bmp_pos,
+					need_writeback,
+					(unsigned int)(lcn >> 3),
+					(unsigned int)*byte);
+			/* Skip full bytes. */
+			if (*byte == 0xff) {
+				lcn = (lcn + 8) & ~7;
+				ntfs_debug("Continuing while loop 1.");
+				continue;
+			}
+			bit = 1 << (lcn & 7);
+			ntfs_debug("bit %i.", bit);
+			/* If the bit is already set, go onto the next one. */
+			if (*byte & bit) {
+				lcn++;
+				ntfs_debug("Continuing while loop 2.");
+				continue;
+			}
+			/*
+			 * Allocate more memory if needed, including space for
+			 * the terminator element.
+			 * ntfs_malloc_nofs() operates on whole pages only.
+			 */
+			if ((rlpos + 2) * sizeof(*rl) > rlsize) {
+				runlist_element *rl2;
+
+				ntfs_debug("Reallocating memory.");
+				if (!rl)
+					ntfs_debug("First free bit is at LCN "
+							"0x%llx.",
+							(unsigned long long)
+							(lcn + bmp_pos));
+				rl2 = ntfs_malloc_nofs(rlsize + (int)PAGE_SIZE);
+				if (unlikely(!rl2)) {
+					err = -ENOMEM;
+					ntfs_error(vol->sb, "Failed to "
+							"allocate memory.");
+					goto out;
+				}
+				memcpy(rl2, rl, rlsize);
+				ntfs_free(rl);
+				rl = rl2;
+				rlsize += PAGE_SIZE;
+				ntfs_debug("Reallocated memory, rlsize 0x%x.",
+						rlsize);
+			}
+			/* Allocate the bitmap bit. */
+			*byte |= bit;
+			/* We need to write this bitmap page to disk. */
+			need_writeback = 1;
+			ntfs_debug("*byte 0x%x, need_writeback is set.",
+					(unsigned int)*byte);
+			/*
+			 * Coalesce with previous run if adjacent LCNs.
+			 * Otherwise, append a new run.
+			 */
+			ntfs_debug("Adding run (lcn 0x%llx, len 0x%llx), "
+					"prev_lcn 0x%llx, lcn 0x%llx, "
+					"bmp_pos 0x%llx, prev_run_len 0x%llx, "
+					"rlpos %i.",
+					(unsigned long long)(lcn + bmp_pos),
+					1ULL, (unsigned long long)prev_lcn,
+					(unsigned long long)lcn,
+					(unsigned long long)bmp_pos,
+					(unsigned long long)prev_run_len,
+					rlpos);
+			if (prev_lcn == lcn + bmp_pos - prev_run_len && rlpos) {
+				ntfs_debug("Coalescing to run (lcn 0x%llx, "
+						"len 0x%llx).",
+						(unsigned long long)
+						rl[rlpos - 1].lcn,
+						(unsigned long long)
+						rl[rlpos - 1].length);
+				rl[rlpos - 1].length = ++prev_run_len;
+				ntfs_debug("Run now (lcn 0x%llx, len 0x%llx), "
+						"prev_run_len 0x%llx.",
+						(unsigned long long)
+						rl[rlpos - 1].lcn,
+						(unsigned long long)
+						rl[rlpos - 1].length,
+						(unsigned long long)
+						prev_run_len);
+			} else {
+				if (likely(rlpos)) {
+					ntfs_debug("Adding new run, (previous "
+							"run lcn 0x%llx, "
+							"len 0x%llx).",
+							(unsigned long long)
+							rl[rlpos - 1].lcn,
+							(unsigned long long)
+							rl[rlpos - 1].length);
+					rl[rlpos].vcn = rl[rlpos - 1].vcn +
+							prev_run_len;
+				} else {
+					ntfs_debug("Adding new run, is first "
+							"run.");
+					rl[rlpos].vcn = start_vcn;
+				}
+				rl[rlpos].lcn = prev_lcn = lcn + bmp_pos;
+				rl[rlpos].length = prev_run_len = 1;
+				rlpos++;
+			}
+			/* Done? */
+			if (!--clusters) {
+				LCN tc;
+				/*
+				 * Update the current zone position.  Positions
+				 * of already scanned zones have been updated
+				 * during the respective zone switches.
+				 */
+				tc = lcn + bmp_pos + 1;
+				ntfs_debug("Done. Updating current zone "
+						"position, tc 0x%llx, "
+						"search_zone %i.",
+						(unsigned long long)tc,
+						search_zone);
+				switch (search_zone) {
+				case 1:
+					ntfs_debug("Before checks, "
+							"vol->mft_zone_pos "
+							"0x%llx.",
+							(unsigned long long)
+							vol->mft_zone_pos);
+					if (tc >= vol->mft_zone_end) {
+						vol->mft_zone_pos =
+								vol->mft_lcn;
+						if (!vol->mft_zone_end)
+							vol->mft_zone_pos = 0;
+					} else if ((bmp_initial_pos >=
+							vol->mft_zone_pos ||
+							tc > vol->mft_zone_pos)
+							&& tc >= vol->mft_lcn)
+						vol->mft_zone_pos = tc;
+					ntfs_debug("After checks, "
+							"vol->mft_zone_pos "
+							"0x%llx.",
+							(unsigned long long)
+							vol->mft_zone_pos);
+					break;
+				case 2:
+					ntfs_debug("Before checks, "
+							"vol->data1_zone_pos "
+							"0x%llx.",
+							(unsigned long long)
+							vol->data1_zone_pos);
+					if (tc >= vol->nr_clusters)
+						vol->data1_zone_pos =
+							     vol->mft_zone_end;
+					else if ((bmp_initial_pos >=
+						    vol->data1_zone_pos ||
+						    tc > vol->data1_zone_pos)
+						    && tc >= vol->mft_zone_end)
+						vol->data1_zone_pos = tc;
+					ntfs_debug("After checks, "
+							"vol->data1_zone_pos "
+							"0x%llx.",
+							(unsigned long long)
+							vol->data1_zone_pos);
+					break;
+				case 4:
+					ntfs_debug("Before checks, "
+							"vol->data2_zone_pos "
+							"0x%llx.",
+							(unsigned long long)
+							vol->data2_zone_pos);
+					if (tc >= vol->mft_zone_start)
+						vol->data2_zone_pos = 0;
+					else if (bmp_initial_pos >=
+						      vol->data2_zone_pos ||
+						      tc > vol->data2_zone_pos)
+						vol->data2_zone_pos = tc;
+					ntfs_debug("After checks, "
+							"vol->data2_zone_pos "
+							"0x%llx.",
+							(unsigned long long)
+							vol->data2_zone_pos);
+					break;
+				default:
+					BUG();
+				}
+				ntfs_debug("Finished.  Going to out.");
+				goto out;
+			}
+			lcn++;
+		}
+		bmp_pos += buf_size;
+		ntfs_debug("After inner while loop: buf_size 0x%x, lcn "
+				"0x%llx, bmp_pos 0x%llx, need_writeback %i.",
+				buf_size, (unsigned long long)lcn,
+				(unsigned long long)bmp_pos, need_writeback);
+		if (bmp_pos < zone_end) {
+			ntfs_debug("Continuing outer while loop, "
+					"bmp_pos 0x%llx, zone_end 0x%llx.",
+					(unsigned long long)bmp_pos,
+					(unsigned long long)zone_end);
+			continue;
+		}
+zone_pass_done:	/* Finished with the current zone pass. */
+		ntfs_debug("At zone_pass_done, pass %i.", pass);
+		if (pass == 1) {
+			/*
+			 * Now do pass 2, scanning the first part of the zone
+			 * we omitted in pass 1.
+			 */
+			pass = 2;
+			zone_end = zone_start;
+			switch (search_zone) {
+			case 1: /* mft_zone */
+				zone_start = vol->mft_zone_start;
+				break;
+			case 2: /* data1_zone */
+				zone_start = vol->mft_zone_end;
+				break;
+			case 4: /* data2_zone */
+				zone_start = 0;
+				break;
+			default:
+				BUG();
+			}
+			/* Sanity check. */
+			if (zone_end < zone_start)
+				zone_end = zone_start;
+			bmp_pos = zone_start;
+			ntfs_debug("Continuing outer while loop, pass 2, "
+					"zone_start 0x%llx, zone_end 0x%llx, "
+					"bmp_pos 0x%llx.",
+					(unsigned long long)zone_start,
+					(unsigned long long)zone_end,
+					(unsigned long long)bmp_pos);
+			continue;
+		} /* pass == 2 */
+done_zones_check:
+		ntfs_debug("At done_zones_check, search_zone %i, done_zones "
+				"before 0x%x, done_zones after 0x%x.",
+				search_zone, done_zones,
+				done_zones | search_zone);
+		done_zones |= search_zone;
+		if (done_zones < 7) {
+			ntfs_debug("Switching zone.");
+			/* Now switch to the next zone we haven't done yet. */
+			pass = 1;
+			switch (search_zone) {
+			case 1:
+				ntfs_debug("Switching from mft zone to data1 "
+						"zone.");
+				/* Update mft zone position. */
+				if (rlpos) {
+					LCN tc;
+
+					ntfs_debug("Before checks, "
+							"vol->mft_zone_pos "
+							"0x%llx.",
+							(unsigned long long)
+							vol->mft_zone_pos);
+					tc = rl[rlpos - 1].lcn +
+							rl[rlpos - 1].length;
+					if (tc >= vol->mft_zone_end) {
+						vol->mft_zone_pos =
+								vol->mft_lcn;
+						if (!vol->mft_zone_end)
+							vol->mft_zone_pos = 0;
+					} else if ((bmp_initial_pos >=
+							vol->mft_zone_pos ||
+							tc > vol->mft_zone_pos)
+							&& tc >= vol->mft_lcn)
+						vol->mft_zone_pos = tc;
+					ntfs_debug("After checks, "
+							"vol->mft_zone_pos "
+							"0x%llx.",
+							(unsigned long long)
+							vol->mft_zone_pos);
+				}
+				/* Switch from mft zone to data1 zone. */
+switch_to_data1_zone:		search_zone = 2;
+				zone_start = bmp_initial_pos =
+						vol->data1_zone_pos;
+				zone_end = vol->nr_clusters;
+				if (zone_start == vol->mft_zone_end)
+					pass = 2;
+				if (zone_start >= zone_end) {
+					vol->data1_zone_pos = zone_start =
+							vol->mft_zone_end;
+					pass = 2;
+				}
+				break;
+			case 2:
+				ntfs_debug("Switching from data1 zone to "
+						"data2 zone.");
+				/* Update data1 zone position. */
+				if (rlpos) {
+					LCN tc;
+
+					ntfs_debug("Before checks, "
+							"vol->data1_zone_pos "
+							"0x%llx.",
+							(unsigned long long)
+							vol->data1_zone_pos);
+					tc = rl[rlpos - 1].lcn +
+							rl[rlpos - 1].length;
+					if (tc >= vol->nr_clusters)
+						vol->data1_zone_pos =
+							     vol->mft_zone_end;
+					else if ((bmp_initial_pos >=
+						    vol->data1_zone_pos ||
+						    tc > vol->data1_zone_pos)
+						    && tc >= vol->mft_zone_end)
+						vol->data1_zone_pos = tc;
+					ntfs_debug("After checks, "
+							"vol->data1_zone_pos "
+							"0x%llx.",
+							(unsigned long long)
+							vol->data1_zone_pos);
+				}
+				/* Switch from data1 zone to data2 zone. */
+				search_zone = 4;
+				zone_start = bmp_initial_pos =
+						vol->data2_zone_pos;
+				zone_end = vol->mft_zone_start;
+				if (!zone_start)
+					pass = 2;
+				if (zone_start >= zone_end) {
+					vol->data2_zone_pos = zone_start =
+							bmp_initial_pos = 0;
+					pass = 2;
+				}
+				break;
+			case 4:
+				ntfs_debug("Switching from data2 zone to "
+						"data1 zone.");
+				/* Update data2 zone position. */
+				if (rlpos) {
+					LCN tc;
+
+					ntfs_debug("Before checks, "
+							"vol->data2_zone_pos "
+							"0x%llx.",
+							(unsigned long long)
+							vol->data2_zone_pos);
+					tc = rl[rlpos - 1].lcn +
+							rl[rlpos - 1].length;
+					if (tc >= vol->mft_zone_start)
+						vol->data2_zone_pos = 0;
+					else if (bmp_initial_pos >=
+						      vol->data2_zone_pos ||
+						      tc > vol->data2_zone_pos)
+						vol->data2_zone_pos = tc;
+					ntfs_debug("After checks, "
+							"vol->data2_zone_pos "
+							"0x%llx.",
+							(unsigned long long)
+							vol->data2_zone_pos);
+				}
+				/* Switch from data2 zone to data1 zone. */
+				goto switch_to_data1_zone;
+			default:
+				BUG();
+			}
+			ntfs_debug("After zone switch, search_zone %i, "
+					"pass %i, bmp_initial_pos 0x%llx, "
+					"zone_start 0x%llx, zone_end 0x%llx.",
+					search_zone, pass,
+					(unsigned long long)bmp_initial_pos,
+					(unsigned long long)zone_start,
+					(unsigned long long)zone_end);
+			bmp_pos = zone_start;
+			if (zone_start == zone_end) {
+				ntfs_debug("Empty zone, going to "
+						"done_zones_check.");
+				/* Empty zone. Don't bother searching it. */
+				goto done_zones_check;
+			}
+			ntfs_debug("Continuing outer while loop.");
+			continue;
+		} /* done_zones == 7 */
+		ntfs_debug("All zones are finished.");
+		/*
+		 * All zones are finished!  If DATA_ZONE, shrink mft zone.  If
+		 * MFT_ZONE, we have really run out of space.
+		 */
+		mft_zone_size = vol->mft_zone_end - vol->mft_zone_start;
+		ntfs_debug("vol->mft_zone_start 0x%llx, vol->mft_zone_end "
+				"0x%llx, mft_zone_size 0x%llx.",
+				(unsigned long long)vol->mft_zone_start,
+				(unsigned long long)vol->mft_zone_end,
+				(unsigned long long)mft_zone_size);
+		if (zone == MFT_ZONE || mft_zone_size <= 0) {
+			ntfs_debug("No free clusters left, going to out.");
+			/* Really no more space left on device. */
+			err = ENOSPC;
+			goto out;
+		} /* zone == DATA_ZONE && mft_zone_size > 0 */
+		ntfs_debug("Shrinking mft zone.");
+		zone_end = vol->mft_zone_end;
+		mft_zone_size >>= 1;
+		if (mft_zone_size > 0)
+			vol->mft_zone_end = vol->mft_zone_start + mft_zone_size;
+		else /* mft zone and data2 zone no longer exist. */
+			vol->data2_zone_pos = vol->mft_zone_start =
+					vol->mft_zone_end = 0;
+		if (vol->mft_zone_pos >= vol->mft_zone_end) {
+			vol->mft_zone_pos = vol->mft_lcn;
+			if (!vol->mft_zone_end)
+				vol->mft_zone_pos = 0;
+		}
+		bmp_pos = zone_start = bmp_initial_pos =
+				vol->data1_zone_pos = vol->mft_zone_end;
+		search_zone = 2;
+		pass = 2;
+		done_zones &= ~2;
+		ntfs_debug("After shrinking mft zone, mft_zone_size 0x%llx, "
+				"vol->mft_zone_start 0x%llx, "
+				"vol->mft_zone_end 0x%llx, "
+				"vol->mft_zone_pos 0x%llx, search_zone 2, "
+				"pass 2, dones_zones 0x%x, zone_start 0x%llx, "
+				"zone_end 0x%llx, vol->data1_zone_pos 0x%llx, "
+				"continuing outer while loop.",
+				(unsigned long long)mft_zone_size,
+				(unsigned long long)vol->mft_zone_start,
+				(unsigned long long)vol->mft_zone_end,
+				(unsigned long long)vol->mft_zone_pos,
+				done_zones, (unsigned long long)zone_start,
+				(unsigned long long)zone_end,
+				(unsigned long long)vol->data1_zone_pos);
+	}
+	ntfs_debug("After outer while loop.");
+out:
+	ntfs_debug("At out.");
+	/* Add runlist terminator element. */
+	if (likely(rl)) {
+		rl[rlpos].vcn = rl[rlpos - 1].vcn + rl[rlpos - 1].length;
+		rl[rlpos].lcn = LCN_RL_NOT_MAPPED;
+		rl[rlpos].length = 0;
+	}
+	if (likely(page && !IS_ERR(page))) {
+		if (need_writeback) {
+			ntfs_debug("Marking page dirty.");
+			flush_dcache_page(page);
+			set_page_dirty(page);
+			need_writeback = 0;
+		}
+		ntfs_unmap_page(page);
+	}
+	if (likely(!err)) {
+		up_write(&vol->lcnbmp_lock);
+		ntfs_debug("Done.");
+		return rl;
+	}
+	ntfs_error(vol->sb, "Failed to allocate clusters, aborting "
+			"(error %i).", err);
+	if (rl) {
+		int err2;
+
+		if (err == ENOSPC)
+			ntfs_debug("Not enough space to complete allocation, "
+					"err ENOSPC, first free lcn 0x%llx, "
+					"could allocate up to 0x%llx "
+					"clusters.",
+					(unsigned long long)rl[0].lcn,
+					(unsigned long long)count - clusters);
+		/* Deallocate all allocated clusters. */
+		ntfs_debug("Attempting rollback...");
+		err2 = ntfs_cluster_free_from_rl_nolock(vol, rl);
+		if (err2) {
+			ntfs_error(vol->sb, "Failed to rollback (error %i).  "
+					"Leaving inconsistent metadata!  "
+					"Unmount and run chkdsk.", err2);
+			NVolSetErrors(vol);
+		}
+		/* Free the runlist. */
+		ntfs_free(rl);
+	} else if (err == ENOSPC)
+		ntfs_debug("No space left at all, err = ENOSPC, "
+				"first free lcn = 0x%llx.",
+				(unsigned long long)vol->data1_zone_pos);
+	up_write(&vol->lcnbmp_lock);
+	return ERR_PTR(err);
+}
+
+/**
+ * __ntfs_cluster_free - free clusters on an ntfs volume
+ * @vi:		vfs inode whose runlist describes the clusters to free
+ * @start_vcn:	vcn in the runlist of @vi at which to start freeing clusters
+ * @count:	number of clusters to free or -1 for all clusters
+ * @is_rollback:	if TRUE this is a rollback operation
+ *
+ * Free @count clusters starting at the cluster @start_vcn in the runlist
+ * described by the vfs inode @vi.
+ *
+ * If @count is -1, all clusters from @start_vcn to the end of the runlist are
+ * deallocated.  Thus, to completely free all clusters in a runlist, use
+ * @start_vcn = 0 and @count = -1.
+ *
+ * @is_rollback should always be FALSE, it is for internal use to rollback
+ * errors.  You probably want to use ntfs_cluster_free() instead.
+ *
+ * Note, ntfs_cluster_free() does not modify the runlist at all, so the caller
+ * has to deal with it later.
+ *
+ * Return the number of deallocated clusters (not counting sparse ones) on
+ * success and -errno on error.
+ *
+ * Locking: - The runlist described by @vi must be unlocked on entry and is
+ *	      unlocked on return.
+ *	    - This function takes the runlist lock of @vi for reading and
+ *	      sometimes for writing and sometimes modifies the runlist.
+ *	    - The volume lcn bitmap must be unlocked on entry and is unlocked
+ *	      on return.
+ *	    - This function takes the volume lcn bitmap lock for writing and
+ *	      modifies the bitmap contents.
+ */
+s64 __ntfs_cluster_free(struct inode *vi, const VCN start_vcn, s64 count,
+		const BOOL is_rollback)
+{
+	s64 delta, to_free, total_freed, real_freed;
+	ntfs_inode *ni;
+	ntfs_volume *vol;
+	struct inode *lcnbmp_vi;
+	runlist_element *rl;
+	int err;
+
+	BUG_ON(!vi);
+	ntfs_debug("Entering for i_ino 0x%lx, start_vcn 0x%llx, count "
+			"0x%llx.%s", vi->i_ino, (unsigned long long)start_vcn,
+			(unsigned long long)count,
+			is_rollback ? " (rollback)" : "");
+	ni = NTFS_I(vi);
+	vol = ni->vol;
+	lcnbmp_vi = vol->lcnbmp_ino;
+	BUG_ON(!lcnbmp_vi);
+	BUG_ON(start_vcn < 0);
+	BUG_ON(count < -1);
+	/*
+	 * Lock the lcn bitmap for writing but only if not rolling back.  We
+	 * must hold the lock all the way including through rollback otherwise
+	 * rollback is not possible because once we have cleared a bit and
+	 * dropped the lock, anyone could have set the bit again, thus
+	 * allocating the cluster for another use.
+	 */
+	if (likely(!is_rollback))
+		down_write(&vol->lcnbmp_lock);
+
+	total_freed = real_freed = 0;
+
+	/* This returns with ni->runlist locked for reading on success. */
+	rl = ntfs_find_vcn(ni, start_vcn, FALSE);
+	if (IS_ERR(rl)) {
+		if (!is_rollback)
+			ntfs_error(vol->sb, "Failed to find first runlist "
+					"element (error %li), aborting.",
+					PTR_ERR(rl));
+		err = PTR_ERR(rl);
+		goto err_out;
+	}
+	if (unlikely(rl->lcn < (LCN)LCN_HOLE)) {
+		if (!is_rollback)
+			ntfs_error(vol->sb, "First runlist element has "
+					"invalid lcn, aborting.");
+		err = -EIO;
+		goto unl_err_out;
+	}
+	/* Find the starting cluster inside the run that needs freeing. */
+	delta = start_vcn - rl->vcn;
+
+	/* The number of clusters in this run that need freeing. */
+	to_free = rl->length - delta;
+	if (count >= 0 && to_free > count)
+		to_free = count;
+
+	if (likely(rl->lcn >= 0)) {
+		/* Do the actual freeing of the clusters in this run. */
+		err = ntfs_bitmap_set_bits_in_run(lcnbmp_vi, rl->lcn + delta,
+				to_free, likely(!is_rollback) ? 0 : 1);
+		if (unlikely(err)) {
+			if (!is_rollback)
+				ntfs_error(vol->sb, "Failed to clear first run "
+						"(error %i), aborting.", err);
+			goto unl_err_out;
+		}
+		/* We have freed @to_free real clusters. */
+		real_freed = to_free;
+	};
+	/* Go to the next run and adjust the number of clusters left to free. */
+	++rl;
+	if (count >= 0)
+		count -= to_free;
+
+	/* Keep track of the total "freed" clusters, including sparse ones. */
+	total_freed = to_free;
+	/*
+	 * Loop over the remaining runs, using @count as a capping value, and
+	 * free them.
+	 */
+	for (; rl->length && count != 0; ++rl) {
+		if (unlikely(rl->lcn < (LCN)LCN_HOLE)) {
+			VCN vcn;
+
+			/*
+			 * Attempt to map runlist, dropping runlist lock for
+			 * the duration.
+			 */
+			up_read(&ni->runlist.lock);
+			vcn = rl->vcn;
+			err = ntfs_map_runlist(ni, vcn);
+			if (err) {
+				if (!is_rollback)
+					ntfs_error(vol->sb, "Failed to map "
+							"runlist fragment.");
+				if (err == -EINVAL || err == -ENOENT)
+					err = -EIO;
+				goto err_out;
+			}
+			/*
+			 * This returns with ni->runlist locked for reading on
+			 * success.
+			 */
+			rl = ntfs_find_vcn(ni, vcn, FALSE);
+			if (IS_ERR(rl)) {
+				err = PTR_ERR(rl);
+				if (!is_rollback)
+					ntfs_error(vol->sb, "Failed to find "
+							"subsequent runlist "
+							"element.");
+				goto err_out;
+			}
+			if (unlikely(rl->lcn < (LCN)LCN_HOLE)) {
+				if (!is_rollback)
+					ntfs_error(vol->sb, "Runlist element "
+							"has invalid lcn "
+							"(0x%llx).",
+							(unsigned long long)
+							rl->lcn);
+				err = -EIO;
+				goto unl_err_out;
+			}
+		}
+		/* The number of clusters in this run that need freeing. */
+		to_free = rl->length;
+		if (count >= 0 && to_free > count)
+			to_free = count;
+
+		if (likely(rl->lcn >= 0)) {
+			/* Do the actual freeing of the clusters in the run. */
+			err = ntfs_bitmap_set_bits_in_run(lcnbmp_vi, rl->lcn,
+					to_free, likely(!is_rollback) ? 0 : 1);
+			if (unlikely(err)) {
+				if (!is_rollback)
+					ntfs_error(vol->sb, "Failed to clear "
+							"subsequent run.");
+				goto unl_err_out;
+			}
+			/* We have freed @to_free real clusters. */
+			real_freed += to_free;
+		}
+		/* Adjust the number of clusters left to free. */
+		if (count >= 0)
+			count -= to_free;
+	
+		/* Update the total done clusters. */
+		total_freed += to_free;
+	}
+	up_read(&ni->runlist.lock);
+	if (likely(!is_rollback))
+		up_write(&vol->lcnbmp_lock);
+
+	BUG_ON(count > 0);
+
+	/* We are done.  Return the number of actually freed clusters. */
+	ntfs_debug("Done.");
+	return real_freed;
+unl_err_out:
+	up_read(&ni->runlist.lock);
+err_out:
+	if (is_rollback)
+		return err;
+	/* If no real clusters were freed, no need to rollback. */
+	if (!real_freed) {
+		up_write(&vol->lcnbmp_lock);
+		return err;
+	}
+	/*
+	 * Attempt to rollback and if that succeeds just return the error code.
+	 * If rollback fails, set the volume errors flag, emit an error
+	 * message, and return the error code.
+	 */
+	delta = __ntfs_cluster_free(vi, start_vcn, total_freed, TRUE);
+	if (delta < 0) {
+		ntfs_error(vol->sb, "Failed to rollback (error %i).  Leaving "
+				"inconsistent metadata!  Unmount and run "
+				"chkdsk.", (int)delta);
+		NVolSetErrors(vol);
+	}
+	up_write(&vol->lcnbmp_lock);
+	ntfs_error(vol->sb, "Aborting (error %i).", err);
+	return err;
+}
+
+#endif /* NTFS_RW */
diff -Nru a/fs/ntfs/lcnalloc.h b/fs/ntfs/lcnalloc.h
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/fs/ntfs/lcnalloc.h	2004-10-18 14:57:24 -07:00
@@ -0,0 +1,83 @@
+/*
+ * lcnalloc.h - Exports for NTFS kernel cluster (de)allocation.  Part of the
+ *		Linux-NTFS project.
+ *
+ * Copyright (c) 2004 Anton Altaparmakov
+ *
+ * This program/include file 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/include file 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 (in the main directory of the Linux-NTFS
+ * distribution in the file COPYING); if not, write to the Free Software
+ * Foundation,Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#ifndef _LINUX_NTFS_LCNALLOC_H
+#define _LINUX_NTFS_LCNALLOC_H
+
+#ifdef NTFS_RW
+
+#include <linux/fs.h>
+
+#include "types.h"
+#include "volume.h"
+
+typedef enum {
+	FIRST_ZONE	= 0,	/* For sanity checking. */
+	MFT_ZONE	= 0,	/* Allocate from $MFT zone. */
+	DATA_ZONE	= 1,	/* Allocate from $DATA zone. */
+	LAST_ZONE	= 1,	/* For sanity checking. */
+} NTFS_CLUSTER_ALLOCATION_ZONES;
+
+extern runlist_element *ntfs_cluster_alloc(ntfs_volume *vol,
+		const VCN start_vcn, const s64 count, const LCN start_lcn,
+		const NTFS_CLUSTER_ALLOCATION_ZONES zone);
+
+extern s64 __ntfs_cluster_free(struct inode *vi, const VCN start_vcn,
+		s64 count, const BOOL is_rollback);
+
+/**
+ * ntfs_cluster_free - free clusters on an ntfs volume
+ * @vi:		vfs inode whose runlist describes the clusters to free
+ * @start_vcn:	vcn in the runlist of @vi at which to start freeing clusters
+ * @count:	number of clusters to free or -1 for all clusters
+ *
+ * Free @count clusters starting at the cluster @start_vcn in the runlist
+ * described by the vfs inode @vi.
+ *
+ * If @count is -1, all clusters from @start_vcn to the end of the runlist are
+ * deallocated.  Thus, to completely free all clusters in a runlist, use
+ * @start_vcn = 0 and @count = -1.
+ *
+ * Note, ntfs_cluster_free() does not modify the runlist at all, so the caller
+ * has to deal with it later.
+ *
+ * Return the number of deallocated clusters (not counting sparse ones) on
+ * success and -errno on error.
+ *
+ * Locking: - The runlist described by @vi must be unlocked on entry and is
+ *	      unlocked on return.
+ *	    - This function takes the runlist lock of @vi for reading and
+ *	      sometimes for writing and sometimes modifies the runlist.
+ *	    - The volume lcn bitmap must be unlocked on entry and is unlocked
+ *	      on return.
+ *	    - This function takes the volume lcn bitmap lock for writing and
+ *	      modifies the bitmap contents.
+ */
+static inline s64 ntfs_cluster_free(struct inode *vi, const VCN start_vcn,
+		s64 count)
+{
+	return __ntfs_cluster_free(vi, start_vcn, count, FALSE);
+}
+
+#endif /* NTFS_RW */
+
+#endif /* defined _LINUX_NTFS_LCNALLOC_H */
diff -Nru a/fs/ntfs/logfile.c b/fs/ntfs/logfile.c
--- a/fs/ntfs/logfile.c	2004-10-18 14:56:29 -07:00
+++ b/fs/ntfs/logfile.c	2004-10-18 14:56:29 -07:00
@@ -497,7 +497,7 @@
 		 * empty block after a non-empty block has been encountered
 		 * means we are done.
 		 */
-		if (!ntfs_is_empty_recordp(kaddr))
+		if (!ntfs_is_empty_recordp((le32*)kaddr))
 			logfile_is_empty = FALSE;
 		else if (!logfile_is_empty)
 			break;
@@ -505,20 +505,20 @@
 		 * A log record page means there cannot be a restart page after
 		 * this so no need to continue searching.
 		 */
-		if (ntfs_is_rcrd_recordp(kaddr))
+		if (ntfs_is_rcrd_recordp((le32*)kaddr))
 			break;
 		/*
 		 * A modified by chkdsk restart page means we cannot handle
 		 * this log file.
 		 */
-		if (ntfs_is_chkd_recordp(kaddr)) {
+		if (ntfs_is_chkd_recordp((le32*)kaddr)) {
 			ntfs_error(vol->sb, "$LogFile has been modified by "
 					"chkdsk.  Mount this volume in "
 					"Windows.");
 			goto err_out;
 		}
 		/* If not a restart page, continue. */
-		if (!ntfs_is_rstr_recordp(kaddr)) {
+		if (!ntfs_is_rstr_recordp((le32*)kaddr)) {
 			/* Skip to the minimum page size for the next one. */
 			if (!pos)
 				pos = NTFS_BLOCK_SIZE >> 1;
diff -Nru a/fs/ntfs/logfile.h b/fs/ntfs/logfile.h
--- a/fs/ntfs/logfile.h	2004-10-18 14:56:48 -07:00
+++ b/fs/ntfs/logfile.h	2004-10-18 14:56:48 -07:00
@@ -67,34 +67,34 @@
 typedef struct {
 /*Ofs*/
 /*  0	NTFS_RECORD; -- Unfolded here as gcc doesn't like unnamed structs. */
-/*  0*/	NTFS_RECORD_TYPES magic;/* The magic is "RSTR". */
-/*  4*/	u16 usa_ofs;		/* See NTFS_RECORD definition in layout.h.
+/*  0*/	NTFS_RECORD_TYPE magic;	/* The magic is "RSTR". */
+/*  4*/	le16 usa_ofs;		/* See NTFS_RECORD definition in layout.h.
 				   When creating, set this to be immediately
 				   after this header structure (without any
 				   alignment). */
-/*  6*/	u16 usa_count;		/* See NTFS_RECORD definition in layout.h. */
+/*  6*/	le16 usa_count;		/* See NTFS_RECORD definition in layout.h. */
 
-/*  8*/	LSN chkdsk_lsn;		/* The last log file sequence number found by
+/*  8*/	leLSN chkdsk_lsn;	/* The last log file sequence number found by
 				   chkdsk.  Only used when the magic is changed
 				   to "CHKD".  Otherwise this is zero. */
-/* 16*/	u32 system_page_size;	/* Byte size of system pages when the log file
+/* 16*/	le32 system_page_size;	/* Byte size of system pages when the log file
 				   was created, has to be >= 512 and a power of
 				   2.  Use this to calculate the required size
 				   of the usa (usa_count) and add it to usa_ofs.
 				   Then verify that the result is less than the
 				   value of the restart_area_offset. */
-/* 20*/	u32 log_page_size;	/* Byte size of log file pages, has to be >=
+/* 20*/	le32 log_page_size;	/* Byte size of log file pages, has to be >=
 				   512 and a power of 2.  The default is 4096
 				   and is used when the system page size is
 				   between 4096 and 8192.  Otherwise this is
 				   set to the system page size instead. */
-/* 24*/	u16 restart_area_offset;/* Byte offset from the start of this header to
+/* 24*/	le16 restart_area_offset;/* Byte offset from the start of this header to
 				   the RESTART_AREA.  Value has to be aligned
 				   to 8-byte boundary.  When creating, set this
 				   to be after the usa. */
-/* 26*/	s16 minor_ver;		/* Log file minor version.  Only check if major
+/* 26*/	sle16 minor_ver;	/* Log file minor version.  Only check if major
 				   version is 1. */
-/* 28*/	s16 major_ver;		/* Log file major version.  We only support
+/* 28*/	sle16 major_ver;	/* Log file major version.  We only support
 				   version 1.1. */
 /* sizeof() = 30 (0x1e) bytes */
 } __attribute__ ((__packed__)) RESTART_PAGE_HEADER;
@@ -111,10 +111,12 @@
  * These are the so far known RESTART_AREA_* flags (16-bit) which contain
  * information about the log file in which they are present.
  */
-typedef enum {
+enum {
 	RESTART_VOLUME_IS_CLEAN	= const_cpu_to_le16(0x0002),
-	REST_AREA_SPACE_FILLER	= 0xffff	/* Just to make flags 16-bit. */
-} __attribute__ ((__packed__)) RESTART_AREA_FLAGS;
+	RESTART_SPACE_FILLER	= 0xffff, /* gcc: Force enum bit width to 16. */
+} __attribute__ ((__packed__));
+
+typedef le16 RESTART_AREA_FLAGS;
 
 /*
  * Log file restart area record.  The offset of this record is found by adding
@@ -123,16 +125,16 @@
  */
 typedef struct {
 /*Ofs*/
-/*  0*/	LSN current_lsn;	/* The current, i.e. last LSN inside the log
+/*  0*/	leLSN current_lsn;	/* The current, i.e. last LSN inside the log
 				   when the restart area was last written.
 				   This happens often but what is the interval?
 				   Is it just fixed time or is it every time a
 				   check point is written or somethine else?
 				   On create set to 0. */
-/*  8*/	u16 log_clients;	/* Number of log client records in the array of
+/*  8*/	le16 log_clients;	/* Number of log client records in the array of
 				   log client records which follows this
 				   restart area.  Must be 1.  */
-/* 10*/	u16 client_free_list;	/* The index of the first free log client record
+/* 10*/	le16 client_free_list;	/* The index of the first free log client record
 				   in the array of log client records.
 				   LOGFILE_NO_CLIENT means that there are no
 				   free log client records in the array.
@@ -148,7 +150,7 @@
 				   and presumably later, the logfile is always
 				   open, even on clean shutdown so this should
 				   always be LOGFILE_NO_CLIENT. */
-/* 12*/	u16 client_in_use_list;	/* The index of the first in-use log client
+/* 12*/	le16 client_in_use_list;/* The index of the first in-use log client
 				   record in the array of log client records.
 				   LOGFILE_NO_CLIENT means that there are no
 				   in-use log client records in the array.  If
@@ -181,13 +183,13 @@
 				   clean.  If on the other hand the logfile is
 				   open and this bit is clear, we can be almost
 				   certain that the logfile is dirty. */
-/* 16*/	u32 seq_number_bits;	/* How many bits to use for the sequence
+/* 16*/	le32 seq_number_bits;	/* How many bits to use for the sequence
 				   number.  This is calculated as 67 - the
 				   number of bits required to store the logfile
 				   size in bytes and this can be used in with
 				   the specified file_size as a consistency
 				   check. */
-/* 20*/	u16 restart_area_length;/* Length of the restart area including the
+/* 20*/	le16 restart_area_length;/* Length of the restart area including the
 				   client array.  Following checks required if
 				   version matches.  Otherwise, skip them.
 				   restart_area_offset + restart_area_length
@@ -195,7 +197,7 @@
 				   restart_area_length has to be >=
 				   client_array_offset + (log_clients *
 				   sizeof(log client record)). */
-/* 22*/	u16 client_array_offset;/* Offset from the start of this record to
+/* 22*/	le16 client_array_offset;/* Offset from the start of this record to
 				   the first log client record if versions are
 				   matched.  When creating, set this to be
 				   after this restart area structure, aligned
@@ -217,7 +219,7 @@
 				   the client array.  This probably means that
 				   the RESTART_AREA record is actually bigger
 				   in WinXP and later. */
-/* 24*/	s64 file_size;		/* Usable byte size of the log file.  If the
+/* 24*/	sle64 file_size;	/* Usable byte size of the log file.  If the
 				   restart_area_offset + the offset of the
 				   file_size are > 510 then corruption has
 				   occured.  This is the very first check when
@@ -230,28 +232,28 @@
 				   then it has to be at least big enough to
 				   store the two restart pages and 48 (0x30)
 				   log record pages. */
-/* 32*/	u32 last_lsn_data_length;/* Length of data of last LSN, not including
+/* 32*/	le32 last_lsn_data_length;/* Length of data of last LSN, not including
 				   the log record header.  On create set to
 				   0. */
-/* 36*/	u16 log_record_header_length;/* Byte size of the log record header.  If
-				   the version matches then check that the
+/* 36*/	le16 log_record_header_length;/* Byte size of the log record header.
+				   If the version matches then check that the
 				   value of log_record_header_length is a
 				   multiple of 8, i.e.
 				   (log_record_header_length + 7) & ~7 ==
 				   log_record_header_length.  When creating set
 				   it to sizeof(LOG_RECORD_HEADER), aligned to
 				   8 bytes. */
-/* 38*/	u16 log_page_data_offset;/* Offset to the start of data in a log record
+/* 38*/	le16 log_page_data_offset;/* Offset to the start of data in a log record
 				   page.  Must be a multiple of 8.  On create
 				   set it to immediately after the update
 				   sequence array of the log record page. */
-/* 40*/	u32 restart_log_open_count;/* A counter that gets incremented every time
-				   the logfile is restarted which happens at
-				   mount time when the logfile is opened.  When
-				   creating set to a random value.  Win2k sets
-				   it to the low 32 bits of the current system
-				   time in NTFS format (see time.h). */
-/* 44*/	u32 reserved;		/* Reserved/alignment to 8-byte boundary. */
+/* 40*/	le32 restart_log_open_count;/* A counter that gets incremented every
+				   time the logfile is restarted which happens
+				   at mount time when the logfile is opened.
+				   When creating set to a random value.  Win2k
+				   sets it to the low 32 bits of the current
+				   system time in NTFS format (see time.h). */
+/* 44*/	le32 reserved;		/* Reserved/alignment to 8-byte boundary. */
 /* sizeof() = 48 (0x30) bytes */
 } __attribute__ ((__packed__)) RESTART_AREA;
 
@@ -261,32 +263,32 @@
  */
 typedef struct {
 /*Ofs*/
-/*  0*/	LSN oldest_lsn;		/* Oldest LSN needed by this client.  On create
+/*  0*/	leLSN oldest_lsn;	/* Oldest LSN needed by this client.  On create
 				   set to 0. */
-/*  8*/	LSN client_restart_lsn;	/* LSN at which this client needs to restart
+/*  8*/	leLSN client_restart_lsn;/* LSN at which this client needs to restart
 				   the volume, i.e. the current position within
 				   the log file.  At present, if clean this
 				   should = current_lsn in restart area but it
 				   probably also = current_lsn when dirty most
 				   of the time.  At create set to 0. */
-/* 16*/	u16 prev_client;	/* The offset to the previous log client record
+/* 16*/	le16 prev_client;	/* The offset to the previous log client record
 				   in the array of log client records.
 				   LOGFILE_NO_CLIENT means there is no previous
 				   client record, i.e. this is the first one.
 				   This is always LOGFILE_NO_CLIENT. */
-/* 18*/	u16 next_client;	/* The offset to the next log client record in
+/* 18*/	le16 next_client;	/* The offset to the next log client record in
 				   the array of log client records.
 				   LOGFILE_NO_CLIENT means there are no next
 				   client records, i.e. this is the last one.
 				   This is always LOGFILE_NO_CLIENT. */
-/* 20*/	u16 seq_number;		/* On Win2k and presumably earlier, this is set
+/* 20*/	le16 seq_number;	/* On Win2k and presumably earlier, this is set
 				   to zero every time the logfile is restarted
 				   and it is incremented when the logfile is
 				   closed at dismount time.  Thus it is 0 when
 				   dirty and 1 when clean.  On WinXP and
 				   presumably later, this is always 0. */
 /* 22*/	u8 reserved[6];		/* Reserved/alignment. */
-/* 28*/	u32 client_name_length; /* Length of client name in bytes.  Should
+/* 28*/	le32 client_name_length;/* Length of client name in bytes.  Should
 				   always be 8. */
 /* 32*/	ntfschar client_name[64];/* Name of the client in Unicode.  Should
 				   always be "NTFS" with the remaining bytes
diff -Nru a/fs/ntfs/mft.c b/fs/ntfs/mft.c
--- a/fs/ntfs/mft.c	2004-10-18 14:56:48 -07:00
+++ b/fs/ntfs/mft.c	2004-10-18 14:56:48 -07:00
@@ -44,14 +44,14 @@
 	m->usa_ofs = cpu_to_le16((sizeof(MFT_RECORD) + 1) & ~1);
 	m->usa_count = cpu_to_le16(size / NTFS_BLOCK_SIZE + 1);
 	/* Set the update sequence number to 1. */
-	*(u16*)((char*)m + ((sizeof(MFT_RECORD) + 1) & ~1)) = cpu_to_le16(1);
+	*(le16*)((char*)m + ((sizeof(MFT_RECORD) + 1) & ~1)) = cpu_to_le16(1);
 	m->lsn = cpu_to_le64(0LL);
 	m->sequence_number = cpu_to_le16(1);
-	m->link_count = cpu_to_le16(0);
+	m->link_count = 0;
 	/* Aligned to 8-byte boundary. */
 	m->attrs_offset = cpu_to_le16((le16_to_cpu(m->usa_ofs) +
 			(le16_to_cpu(m->usa_count) << 1) + 7) & ~7);
-	m->flags = cpu_to_le16(0);
+	m->flags = 0;
 	/*
 	 * Using attrs_offset plus eight bytes (for the termination attribute),
 	 * aligned to 8-byte boundary.
@@ -60,10 +60,10 @@
 			~7);
 	m->bytes_allocated = cpu_to_le32(size);
 	m->base_mft_record = cpu_to_le64((MFT_REF)0);
-	m->next_attr_instance = cpu_to_le16(0);
+	m->next_attr_instance = 0;
 	a = (ATTR_RECORD*)((char*)m + le16_to_cpu(m->attrs_offset));
 	a->type = AT_END;
-	a->length = cpu_to_le32(0);
+	a->length = 0;
 }
 
 /**
@@ -311,11 +311,11 @@
 /**
  * map_extent_mft_record - load an extent inode and attach it to its base
  * @base_ni:	base ntfs inode
- * @mref:	mft reference of the extent inode to load (in little endian)
+ * @mref:	mft reference of the extent inode to load
  * @ntfs_ino:	on successful return, pointer to the ntfs_inode structure
  *
  * Load the extent mft record @mref and attach it to its base inode @base_ni.
- * Return the mapped extent mft record if IS_ERR(result) is false. Otherwise
+ * Return the mapped extent mft record if IS_ERR(result) is false.  Otherwise
  * PTR_ERR(result) gives the negative error code.
  *
  * On successful return, @ntfs_ino contains a pointer to the ntfs_inode
@@ -328,8 +328,8 @@
 	ntfs_inode *ni = NULL;
 	ntfs_inode **extent_nis = NULL;
 	int i;
-	unsigned long mft_no = MREF_LE(mref);
-	u16 seq_no = MSEQNO_LE(mref);
+	unsigned long mft_no = MREF(mref);
+	u16 seq_no = MSEQNO(mref);
 	BOOL destroy_ni = FALSE;
 
 	ntfs_debug("Mapping extent mft record 0x%lx (base mft record 0x%lx).",
@@ -391,7 +391,7 @@
 	ni->ext.base_ntfs_ino = base_ni;
 	/* Now map the record. */
 	m = map_mft_record(ni);
-	if (unlikely(IS_ERR(m))) {
+	if (IS_ERR(m)) {
 		up(&base_ni->extent_lock);
 		atomic_dec(&base_ni->count);
 		ntfs_clear_extent_inode(ni);
@@ -418,7 +418,8 @@
 			m = ERR_PTR(-ENOMEM);
 			goto unm_err_out;
 		}
-		if (base_ni->ext.extent_ntfs_inos) {
+		if (base_ni->nr_extents) {
+			BUG_ON(!base_ni->ext.extent_ntfs_inos);
 			memcpy(tmp, base_ni->ext.extent_ntfs_inos, new_size -
 					4 * sizeof(ntfs_inode *));
 			kfree(base_ni->ext.extent_ntfs_inos);
@@ -571,7 +572,7 @@
 	/* Get the page containing the mirror copy of the mft record @m. */
 	page = ntfs_map_page(vol->mftmirr_ino->i_mapping, ni->mft_no >>
 			(PAGE_CACHE_SHIFT - vol->mft_record_size_bits));
-	if (unlikely(IS_ERR(page))) {
+	if (IS_ERR(page)) {
 		ntfs_error(vol->sb, "Failed to map mft mirror page.");
 		err = PTR_ERR(page);
 		goto err_out;
@@ -979,7 +980,7 @@
 		ntfs_debug("Inode 0x%lx is not in icache.", mft_no);
 		/* The inode is not in icache. */
 		/* Skip the record if it is not a mft record (type "FILE"). */
-		if (!ntfs_is_mft_recordp(maddr)) {
+		if (!ntfs_is_mft_recordp((le32*)maddr)) {
 			ntfs_debug("Mft record 0x%lx is not a FILE record, "
 					"continuing search.", mft_no);
 			continue;
diff -Nru a/fs/ntfs/mst.c b/fs/ntfs/mst.c
--- a/fs/ntfs/mst.c	2004-10-18 14:56:33 -07:00
+++ b/fs/ntfs/mst.c	2004-10-18 14:56:33 -07:00
@@ -122,8 +122,9 @@
  */
 int pre_write_mst_fixup(NTFS_RECORD *b, const u32 size)
 {
+	le16 *usa_pos, *data_pos;
 	u16 usa_ofs, usa_count, usn;
-	u16 *usa_pos, *data_pos;
+	le16 le_usn;
 
 	/* Sanity check + only fixup if it makes sense. */
 	if (!b || ntfs_is_baad_record(b->magic) ||
@@ -140,7 +141,7 @@
 	     (size >> NTFS_BLOCK_SIZE_BITS) != usa_count)
 		return -EINVAL;
 	/* Position of usn in update sequence array. */
-	usa_pos = (u16*)((u8*)b + usa_ofs);
+	usa_pos = (le16*)((u8*)b + usa_ofs);
 	/*
 	 * Cyclically increment the update sequence number
 	 * (skipping 0 and -1, i.e. 0xffff).
@@ -148,10 +149,10 @@
 	usn = le16_to_cpup(usa_pos) + 1;
 	if (usn == 0xffff || !usn)
 		usn = 1;
-	usn = cpu_to_le16(usn);
-	*usa_pos = usn;
+	le_usn = cpu_to_le16(usn);
+	*usa_pos = le_usn;
 	/* Position in data of first u16 that needs fixing up. */
-	data_pos = (u16*)b + NTFS_BLOCK_SIZE/sizeof(u16) - 1;
+	data_pos = (le16*)b + NTFS_BLOCK_SIZE/sizeof(le16) - 1;
 	/* Fixup all sectors. */
 	while (usa_count--) {
 		/*
@@ -160,9 +161,9 @@
 		 */
 		*(++usa_pos) = *data_pos;
 		/* Apply fixup to data. */
-		*data_pos = usn;
+		*data_pos = le_usn;
 		/* Increment position in data as well. */
-		data_pos += NTFS_BLOCK_SIZE/sizeof(u16);
+		data_pos += NTFS_BLOCK_SIZE/sizeof(le16);
 	}
 	return 0;
 }
@@ -177,16 +178,16 @@
  */
 void post_write_mst_fixup(NTFS_RECORD *b)
 {
-	u16 *usa_pos, *data_pos;
+	le16 *usa_pos, *data_pos;
 
 	u16 usa_ofs = le16_to_cpu(b->usa_ofs);
 	u16 usa_count = le16_to_cpu(b->usa_count) - 1;
 
 	/* Position of usn in update sequence array. */
-	usa_pos = (u16*)b + usa_ofs/sizeof(u16);
+	usa_pos = (le16*)b + usa_ofs/sizeof(le16);
 
 	/* Position in protected data of first u16 that needs fixing up. */
-	data_pos = (u16*)b + NTFS_BLOCK_SIZE/sizeof(u16) - 1;
+	data_pos = (le16*)b + NTFS_BLOCK_SIZE/sizeof(le16) - 1;
 
 	/* Fixup all sectors. */
 	while (usa_count--) {
@@ -197,6 +198,6 @@
 		*data_pos = *(++usa_pos);
 
 		/* Increment position in data as well. */
-		data_pos += NTFS_BLOCK_SIZE/sizeof(u16);
+		data_pos += NTFS_BLOCK_SIZE/sizeof(le16);
 	}
 }
diff -Nru a/fs/ntfs/namei.c b/fs/ntfs/namei.c
--- a/fs/ntfs/namei.c	2004-10-18 14:56:49 -07:00
+++ b/fs/ntfs/namei.c	2004-10-18 14:56:49 -07:00
@@ -171,7 +171,7 @@
    {
 	struct dentry *real_dent, *new_dent;
 	MFT_RECORD *m;
-	attr_search_context *ctx;
+	ntfs_attr_search_ctx *ctx;
 	ntfs_inode *ni = NTFS_I(dent_inode);
 	int err;
 	struct qstr nls_name;
@@ -196,8 +196,8 @@
 			ctx = NULL;
 			goto err_out;
 		}
-		ctx = get_attr_search_ctx(ni, m);
-		if (!ctx) {
+		ctx = ntfs_attr_get_search_ctx(ni, m);
+		if (unlikely(!ctx)) {
 			err = -ENOMEM;
 			goto err_out;
 		}
@@ -205,12 +205,14 @@
 			ATTR_RECORD *a;
 			u32 val_len;
 
-			if (!lookup_attr(AT_FILE_NAME, NULL, 0, 0, 0, NULL, 0,
-					ctx)) {
+			err = ntfs_attr_lookup(AT_FILE_NAME, NULL, 0, 0, 0,
+					NULL, 0, ctx);
+			if (unlikely(err)) {
 				ntfs_error(vol->sb, "Inode corrupt: No WIN32 "
 						"namespace counterpart to DOS "
 						"file name. Run chkdsk.");
-				err = -EIO;
+				if (err == -ENOENT)
+					err = -EIO;
 				goto err_out;
 			}
 			/* Consistency checks. */
@@ -233,7 +235,7 @@
 				(ntfschar*)&fn->file_name, fn->file_name_length,
 				(unsigned char**)&nls_name.name, 0);
 
-		put_attr_search_ctx(ctx);
+		ntfs_attr_put_search_ctx(ctx);
 		unmap_mft_record(ni);
 	}
 	m = NULL;
@@ -329,7 +331,7 @@
 	err = -EIO;
 err_out:
 	if (ctx)
-		put_attr_search_ctx(ctx);
+		ntfs_attr_put_search_ctx(ctx);
 	if (m)
 		unmap_mft_record(ni);
 	iput(dent_inode);
@@ -366,32 +368,36 @@
 	struct inode *vi = child_dent->d_inode;
 	ntfs_inode *ni = NTFS_I(vi);
 	MFT_RECORD *mrec;
-	attr_search_context *ctx;
+	ntfs_attr_search_ctx *ctx;
 	ATTR_RECORD *attr;
 	FILE_NAME_ATTR *fn;
 	struct inode *parent_vi;
 	struct dentry *parent_dent;
 	unsigned long parent_ino;
+	int err;
 
 	ntfs_debug("Entering for inode 0x%lx.", vi->i_ino);
 	/* Get the mft record of the inode belonging to the child dentry. */
 	mrec = map_mft_record(ni);
-	if (unlikely(IS_ERR(mrec)))
+	if (IS_ERR(mrec))
 		return (struct dentry *)mrec;
 	/* Find the first file name attribute in the mft record. */
-	ctx = get_attr_search_ctx(ni, mrec);
+	ctx = ntfs_attr_get_search_ctx(ni, mrec);
 	if (unlikely(!ctx)) {
 		unmap_mft_record(ni);
 		return ERR_PTR(-ENOMEM);
 	}
 try_next:
-	if (unlikely(!lookup_attr(AT_FILE_NAME, NULL, 0, CASE_SENSITIVE, 0,
-			NULL, 0, ctx))) {
-		put_attr_search_ctx(ctx);
+	err = ntfs_attr_lookup(AT_FILE_NAME, NULL, 0, CASE_SENSITIVE, 0, NULL,
+			0, ctx);
+	if (unlikely(err)) {
+		ntfs_attr_put_search_ctx(ctx);
 		unmap_mft_record(ni);
-		ntfs_error(vi->i_sb, "Inode 0x%lx does not have a file name "
-				"attribute. Run chkdsk.", vi->i_ino);
-		return ERR_PTR(-ENOENT);
+		if (err == -ENOENT)
+			ntfs_error(vi->i_sb, "Inode 0x%lx does not have a "
+					"file name attribute.  Run chkdsk.",
+					vi->i_ino);
+		return ERR_PTR(err);
 	}
 	attr = ctx->attr;
 	if (unlikely(attr->non_resident))
@@ -404,11 +410,11 @@
 	/* Get the inode number of the parent directory. */
 	parent_ino = MREF_LE(fn->parent_directory);
 	/* Release the search context and the mft record of the child. */
-	put_attr_search_ctx(ctx);
+	ntfs_attr_put_search_ctx(ctx);
 	unmap_mft_record(ni);
 	/* Get the inode of the parent directory. */
 	parent_vi = ntfs_iget(vi->i_sb, parent_ino);
-	if (unlikely(IS_ERR(parent_vi) || is_bad_inode(parent_vi))) {
+	if (IS_ERR(parent_vi) || unlikely(is_bad_inode(parent_vi))) {
 		if (!IS_ERR(parent_vi))
 			iput(parent_vi);
 		ntfs_error(vi->i_sb, "Failed to get parent directory inode "
@@ -451,7 +457,7 @@
 
 	ntfs_debug("Entering for inode 0x%lx, generation 0x%x.", ino, gen);
 	vi = ntfs_iget(sb, ino);
-	if (unlikely(IS_ERR(vi))) {
+	if (IS_ERR(vi)) {
 		ntfs_error(sb, "Failed to get inode 0x%lx.", ino);
 		return (struct dentry *)vi;
 	}
diff -Nru a/fs/ntfs/ntfs.h b/fs/ntfs/ntfs.h
--- a/fs/ntfs/ntfs.h	2004-10-18 14:56:29 -07:00
+++ b/fs/ntfs/ntfs.h	2004-10-18 14:56:29 -07:00
@@ -156,9 +156,8 @@
 
 /* From fs/ntfs/super.c */
 #define default_upcase_len 0x10000
-extern wchar_t *default_upcase;
+extern ntfschar *default_upcase;
 extern unsigned long ntfs_nr_upcase_users;
-extern unsigned long ntfs_nr_mounts;
 extern struct semaphore ntfs_lock;
 
 typedef struct {
diff -Nru a/fs/ntfs/quota.c b/fs/ntfs/quota.c
--- a/fs/ntfs/quota.c	2004-10-18 14:56:49 -07:00
+++ b/fs/ntfs/quota.c	2004-10-18 14:56:49 -07:00
@@ -37,7 +37,7 @@
 {
 	ntfs_index_context *ictx;
 	QUOTA_CONTROL_ENTRY *qce;
-	const u32 qid = QUOTA_DEFAULTS_ID;
+	const le32 qid = QUOTA_DEFAULTS_ID;
 	int err;
 
 	ntfs_debug("Entering.");
diff -Nru a/fs/ntfs/super.c b/fs/ntfs/super.c
--- a/fs/ntfs/super.c	2004-10-18 14:56:48 -07:00
+++ b/fs/ntfs/super.c	2004-10-18 14:56:48 -07:00
@@ -28,6 +28,8 @@
 #include <linux/backing-dev.h>
 #include <linux/buffer_head.h>
 #include <linux/vfs.h>
+#include <linux/moduleparam.h>
+#include <linux/smp_lock.h>
 
 #include "ntfs.h"
 #include "sysctl.h"
@@ -143,7 +145,7 @@
 	ntfs_debug("Entering with mount options string: %s", opt);
 	while ((p = strsep(&opt, ","))) {
 		if ((v = strchr(p, '=')))
-			*v++ = '\0';
+			*v++ = 0;
 		NTFS_GETOPT("uid", uid)
 		else NTFS_GETOPT("gid", gid)
 		else NTFS_GETOPT("umask", fmask = dmask)
@@ -316,11 +318,11 @@
 	ntfs_inode *ni = NTFS_I(vol->vol_ino);
 	MFT_RECORD *m;
 	VOLUME_INFORMATION *vi;
-	attr_search_context *ctx;
+	ntfs_attr_search_ctx *ctx;
 	int err;
 
 	ntfs_debug("Entering, old flags = 0x%x, new flags = 0x%x.",
-			vol->vol_flags, flags);
+			le16_to_cpu(vol->vol_flags), le16_to_cpu(flags));
 	if (vol->vol_flags == flags)
 		goto done;
 	BUG_ON(!ni);
@@ -329,28 +331,28 @@
 		err = PTR_ERR(m);
 		goto err_out;
 	}
-	ctx = get_attr_search_ctx(ni, m);
+	ctx = ntfs_attr_get_search_ctx(ni, m);
 	if (!ctx) {
 		err = -ENOMEM;
 		goto put_unm_err_out;
 	}
-	if (!lookup_attr(AT_VOLUME_INFORMATION, NULL, 0, 0, 0, NULL, 0, ctx)) {
-		err = -EIO;
+	err = ntfs_attr_lookup(AT_VOLUME_INFORMATION, NULL, 0, 0, 0, NULL, 0,
+			ctx);
+	if (err)
 		goto put_unm_err_out;
-	}
 	vi = (VOLUME_INFORMATION*)((u8*)ctx->attr +
 			le16_to_cpu(ctx->attr->data.resident.value_offset));
 	vol->vol_flags = vi->flags = flags;
 	flush_dcache_mft_record_page(ctx->ntfs_ino);
 	mark_mft_record_dirty(ctx->ntfs_ino);
-	put_attr_search_ctx(ctx);
+	ntfs_attr_put_search_ctx(ctx);
 	unmap_mft_record(ni);
 done:
 	ntfs_debug("Done.");
 	return 0;
 put_unm_err_out:
 	if (ctx)
-		put_attr_search_ctx(ctx);
+		ntfs_attr_put_search_ctx(ctx);
 	unmap_mft_record(ni);
 err_out:
 	ntfs_error(vol->sb, "Failed with error code %i.", -err);
@@ -384,7 +386,8 @@
 static inline int ntfs_clear_volume_flags(ntfs_volume *vol, VOLUME_FLAGS flags)
 {
 	flags &= VOLUME_FLAGS_MASK;
-	return ntfs_write_volume_flags(vol, vol->vol_flags & ~flags);
+	flags = vol->vol_flags & cpu_to_le16(~le16_to_cpu(flags));
+	return ntfs_write_volume_flags(vol, flags);
 }
 
 #endif /* NTFS_RW */
@@ -409,7 +412,7 @@
 #ifndef NTFS_RW
 	/* For read-only compiled driver, enforce all read-only flags. */
 	*flags |= MS_RDONLY | MS_NOATIME | MS_NODIRATIME;
-#else /* ! NTFS_RW */
+#else /* NTFS_RW */
 	/*
 	 * For the read-write compiled driver, if we are remounting read-write,
 	 * make sure there are no volume errors and that no unsupported volume
@@ -479,28 +482,7 @@
 						"flags.  Run chkdsk.");
 		}
 	}
-	// TODO:  For now we enforce no atime and dir atime updates as they are
-	// not implemented.
-	if ((sb->s_flags & MS_NOATIME) && !(*flags & MS_NOATIME))
-		ntfs_warning(sb, "Atime updates are not implemented yet.  "
-				"Leaving them disabled.");
-	else if ((sb->s_flags & MS_NODIRATIME) && !(*flags & MS_NODIRATIME))
-		ntfs_warning(sb, "Directory atime updates are not implemented "
-				"yet.  Leaving them disabled.");
-	*flags |= MS_NOATIME | MS_NODIRATIME;
-#endif /* ! NTFS_RW */
-
-	// FIXME/TODO: If left like this we will have problems with rw->ro and
-	// ro->rw, as well as with sync->async and vice versa remounts.
-	// Note: The VFS already checks that there are no pending deletes and
-	// no open files for writing. So we only need to worry about dirty
-	// inode pages and dirty system files (which include dirty inodes).
-	// Either handle by flushing the whole volume NOW or by having the
-	// write routines work on MS_RDONLY fs and guarantee we don't mark
-	// anything as dirty if MS_RDONLY is set. That way the dirty data
-	// would get flushed but no new dirty data would appear. This is
-	// probably best but we need to be careful not to mark anything dirty
-	// or the MS_RDONLY will be leaking writes.
+#endif /* NTFS_RW */
 
 	// TODO: Deal with *flags.
 
@@ -530,8 +512,10 @@
 	 * field. If checksum is zero, no checking is done.
 	 */
 	if ((void*)b < (void*)&b->checksum && b->checksum) {
-		u32 i, *u;
-		for (i = 0, u = (u32*)b; u < (u32*)(&b->checksum); ++u)
+		le32 *u;
+		u32 i;
+
+		for (i = 0, u = (le32*)b; u < (le32*)(&b->checksum); ++u)
 			i += le32_to_cpup(u);
 		if (le32_to_cpu(b->checksum) != i)
 			goto not_ntfs;
@@ -540,7 +524,7 @@
 	if (b->oem_id != magicNTFS)
 		goto not_ntfs;
 	/* Check bytes per sector value is between 256 and 4096. */
-	if (le16_to_cpu(b->bpb.bytes_per_sector) <  0x100 ||
+	if (le16_to_cpu(b->bpb.bytes_per_sector) < 0x100 ||
 			le16_to_cpu(b->bpb.bytes_per_sector) > 0x1000)
 		goto not_ntfs;
 	/* Check sectors per cluster value is valid. */
@@ -839,37 +823,86 @@
 	vol->serial_no = le64_to_cpu(b->volume_serial_number);
 	ntfs_debug("vol->serial_no = 0x%llx",
 			(unsigned long long)vol->serial_no);
-	/*
-	 * Determine MFT zone size. This is not strictly the right place to do
-	 * this, but I am too lazy to create a function especially for it...
-	 */
-	vol->mft_zone_end = vol->nr_clusters;
+	return TRUE;
+}
+
+/**
+ * setup_lcn_allocator - initialize the cluster allocator
+ * @vol:	volume structure for which to setup the lcn allocator
+ *
+ * Setup the cluster (lcn) allocator to the starting values.
+ */
+static void setup_lcn_allocator(ntfs_volume *vol)
+{
+#ifdef NTFS_RW
+	LCN mft_zone_size, mft_lcn;
+#endif /* NTFS_RW */
+
+	ntfs_debug("vol->mft_zone_multiplier = 0x%x",
+			vol->mft_zone_multiplier);
+#ifdef NTFS_RW
+	/* Determine the size of the MFT zone. */
+	mft_zone_size = vol->nr_clusters;
 	switch (vol->mft_zone_multiplier) {  /* % of volume size in clusters */
 	case 4:
-		vol->mft_zone_end = vol->mft_zone_end >> 1;	/* 50%   */
+		mft_zone_size >>= 1;			/* 50%   */
 		break;
 	case 3:
-		vol->mft_zone_end = (vol->mft_zone_end +
-				(vol->mft_zone_end >> 1)) >> 2;	/* 37.5% */
+		mft_zone_size = (mft_zone_size +
+				(mft_zone_size >> 1)) >> 2;	/* 37.5% */
 		break;
 	case 2:
-		vol->mft_zone_end = vol->mft_zone_end >> 2;	/* 25%   */
+		mft_zone_size >>= 2;			/* 25%   */
 		break;
+	/* case 1: */
 	default:
-		vol->mft_zone_multiplier = 1;
-		/* Fall through into case 1. */
-	case 1:
-		vol->mft_zone_end = vol->mft_zone_end >> 3;	/* 12.5% */
+		mft_zone_size >>= 3;			/* 12.5% */
 		break;
 	}
-	ntfs_debug("vol->mft_zone_multiplier = 0x%x",
-			vol->mft_zone_multiplier);
-	vol->mft_zone_start = vol->mft_lcn;
-	vol->mft_zone_end += vol->mft_lcn;
+	/* Setup the mft zone. */
+	vol->mft_zone_start = vol->mft_zone_pos = vol->mft_lcn;
+	ntfs_debug("vol->mft_zone_pos = 0x%llx",
+			(unsigned long long)vol->mft_zone_pos);
+	/*
+	 * Calculate the mft_lcn for an unmodified NTFS volume (see mkntfs
+	 * source) and if the actual mft_lcn is in the expected place or even
+	 * further to the front of the volume, extend the mft_zone to cover the
+	 * beginning of the volume as well.  This is in order to protect the
+	 * area reserved for the mft bitmap as well within the mft_zone itself.
+	 * On non-standard volumes we do not protect it as the overhead would
+	 * be higher than the speed increase we would get by doing it.
+	 */
+	mft_lcn = (8192 + 2 * vol->cluster_size - 1) / vol->cluster_size;
+	if (mft_lcn * vol->cluster_size < 16 * 1024)
+		mft_lcn = (16 * 1024 + vol->cluster_size - 1) /
+				vol->cluster_size;
+	if (vol->mft_zone_start <= mft_lcn)
+		vol->mft_zone_start = 0;
 	ntfs_debug("vol->mft_zone_start = 0x%llx",
-			(long long)vol->mft_zone_start);
-	ntfs_debug("vol->mft_zone_end = 0x%llx", (long long)vol->mft_zone_end);
-	return TRUE;
+			(unsigned long long)vol->mft_zone_start);
+	/*
+	 * Need to cap the mft zone on non-standard volumes so that it does
+	 * not point outside the boundaries of the volume.  We do this by
+	 * halving the zone size until we are inside the volume.
+	 */
+	vol->mft_zone_end = vol->mft_lcn + mft_zone_size;
+	while (vol->mft_zone_end >= vol->nr_clusters) {
+		mft_zone_size >>= 1;
+		vol->mft_zone_end = vol->mft_lcn + mft_zone_size;
+	}
+	ntfs_debug("vol->mft_zone_end = 0x%llx",
+			(unsigned long long)vol->mft_zone_end);
+	/*
+	 * Set the current position within each data zone to the start of the
+	 * respective zone.
+	 */
+	vol->data1_zone_pos = vol->mft_zone_end;
+	ntfs_debug("vol->data1_zone_pos = 0x%llx",
+			(unsigned long long)vol->data1_zone_pos);
+	vol->data2_zone_pos = 0;
+	ntfs_debug("vol->data2_zone_pos = 0x%llx",
+			(unsigned long long)vol->data2_zone_pos);
+#endif /* NTFS_RW */
 }
 
 #ifdef NTFS_RW
@@ -934,7 +967,7 @@
 	ntfs_inode *mirr_ni;
 	struct page *mft_page, *mirr_page;
 	u8 *kmft, *kmirr;
-	run_list_element *rl, rl2[2];
+	runlist_element *rl, rl2[2];
 	int mrecs_per_page, i;
 
 	ntfs_debug("Entering.");
@@ -973,7 +1006,7 @@
 			++index;
 		}
 		/* Make sure the record is ok. */
-		if (ntfs_is_baad_recordp(kmft)) {
+		if (ntfs_is_baad_recordp((le32*)kmft)) {
 			ntfs_error(sb, "Incomplete multi sector transfer "
 					"detected in mft record %i.", i);
 mm_unmap_out:
@@ -982,7 +1015,7 @@
 			ntfs_unmap_page(mft_page);
 			return FALSE;
 		}
-		if (ntfs_is_baad_recordp(kmirr)) {
+		if (ntfs_is_baad_recordp((le32*)kmirr)) {
 			ntfs_error(sb, "Incomplete multi sector transfer "
 					"detected in mft mirror record %i.", i);
 			goto mm_unmap_out;
@@ -1007,7 +1040,7 @@
 	ntfs_unmap_page(mft_page);
 	ntfs_unmap_page(mirr_page);
 
-	/* Construct the mft mirror run list by hand. */
+	/* Construct the mft mirror runlist by hand. */
 	rl2[0].vcn = 0;
 	rl2[0].lcn = vol->mftmirr_lcn;
 	rl2[0].length = (vol->mftmirr_size * vol->mft_record_size +
@@ -1017,23 +1050,23 @@
 	rl2[1].length = 0;
 	/*
 	 * Because we have just read all of the mft mirror, we know we have
-	 * mapped the full run list for it.
+	 * mapped the full runlist for it.
 	 */
 	mirr_ni = NTFS_I(vol->mftmirr_ino);
-	down_read(&mirr_ni->run_list.lock);
-	rl = mirr_ni->run_list.rl;
-	/* Compare the two run lists.  They must be identical. */
+	down_read(&mirr_ni->runlist.lock);
+	rl = mirr_ni->runlist.rl;
+	/* Compare the two runlists.  They must be identical. */
 	i = 0;
 	do {
 		if (rl2[i].vcn != rl[i].vcn || rl2[i].lcn != rl[i].lcn ||
 				rl2[i].length != rl[i].length) {
 			ntfs_error(sb, "$MFTMirr location mismatch.  "
 					"Run chkdsk.");
-			up_read(&mirr_ni->run_list.lock);
+			up_read(&mirr_ni->runlist.lock);
 			return FALSE;
 		}
 	} while (rl2[i++].length);
-	up_read(&mirr_ni->run_list.lock);
+	up_read(&mirr_ni->runlist.lock);
 	ntfs_debug("Done.");
 	return TRUE;
 }
@@ -1081,9 +1114,9 @@
 	static const ntfschar Quota[7] = { const_cpu_to_le16('$'),
 			const_cpu_to_le16('Q'), const_cpu_to_le16('u'),
 			const_cpu_to_le16('o'), const_cpu_to_le16('t'),
-			const_cpu_to_le16('a'), const_cpu_to_le16(0) };
+			const_cpu_to_le16('a'), 0 };
 	static ntfschar Q[3] = { const_cpu_to_le16('$'),
-			const_cpu_to_le16('Q'), const_cpu_to_le16(0) };
+			const_cpu_to_le16('Q'), 0 };
 
 	ntfs_debug("Entering.");
 	/*
@@ -1136,6 +1169,66 @@
 	return TRUE;
 }
 
+/**
+ * load_and_init_attrdef - load the attribute definitions table for a volume
+ * @vol:	ntfs super block describing device whose attrdef to load
+ *
+ * Return TRUE on success or FALSE on error.
+ */
+static BOOL load_and_init_attrdef(ntfs_volume *vol)
+{
+	struct super_block *sb = vol->sb;
+	struct inode *ino;
+	struct page *page;
+	unsigned long index, max_index;
+	unsigned int size;
+
+	ntfs_debug("Entering.");
+	/* Read attrdef table and setup vol->attrdef and vol->attrdef_size. */
+	ino = ntfs_iget(sb, FILE_AttrDef);
+	if (IS_ERR(ino) || is_bad_inode(ino)) {
+		if (!IS_ERR(ino))
+			iput(ino);
+		goto failed;
+	}
+	/* The size of FILE_AttrDef must be above 0 and fit inside 31 bits. */
+	if (!ino->i_size || ino->i_size > 0x7fffffff)
+		goto iput_failed;
+	vol->attrdef = (ATTR_DEF*)ntfs_malloc_nofs(ino->i_size);
+	if (!vol->attrdef)
+		goto iput_failed;
+	index = 0;
+	max_index = ino->i_size >> PAGE_CACHE_SHIFT;
+	size = PAGE_CACHE_SIZE;
+	while (index < max_index) {
+		/* Read the attrdef table and copy it into the linear buffer. */
+read_partial_attrdef_page:
+		page = ntfs_map_page(ino->i_mapping, index);
+		if (IS_ERR(page))
+			goto free_iput_failed;
+		memcpy((u8*)vol->attrdef + (index++ << PAGE_CACHE_SHIFT),
+				page_address(page), size);
+		ntfs_unmap_page(page);
+	};
+	if (size == PAGE_CACHE_SIZE) {
+		size = ino->i_size & ~PAGE_CACHE_MASK;
+		if (size)
+			goto read_partial_attrdef_page;
+	}
+	vol->attrdef_size = ino->i_size;
+	ntfs_debug("Read %llu bytes from $AttrDef.", ino->i_size);
+	iput(ino);
+	return TRUE;
+free_iput_failed:
+	ntfs_free(vol->attrdef);
+	vol->attrdef = NULL;
+iput_failed:
+	iput(ino);
+failed:
+	ntfs_error(sb, "Failed to initialize attribute definition table.");
+	return FALSE;
+}
+
 #endif /* NTFS_RW */
 
 /**
@@ -1236,7 +1329,7 @@
 		return TRUE;
 	}
 	up(&ntfs_lock);
-	ntfs_error(sb, "Failed to initialized upcase table.");
+	ntfs_error(sb, "Failed to initialize upcase table.");
 	return FALSE;
 }
 
@@ -1252,10 +1345,9 @@
 static BOOL load_system_files(ntfs_volume *vol)
 {
 	struct super_block *sb = vol->sb;
-	struct inode *tmp_ino;
 	MFT_RECORD *m;
 	VOLUME_INFORMATION *vi;
-	attr_search_context *ctx;
+	ntfs_attr_search_ctx *ctx;
 
 	ntfs_debug("Entering.");
 #ifdef NTFS_RW
@@ -1296,6 +1388,14 @@
 	/* Read upcase table and setup @vol->upcase and @vol->upcase_len. */
 	if (!load_and_init_upcase(vol))
 		goto iput_mftbmp_err_out;
+#ifdef NTFS_RW
+	/*
+	 * Read attribute definitions table and setup @vol->attrdef and
+	 * @vol->attrdef_size.
+	 */
+	if (!load_and_init_attrdef(vol))
+		goto iput_upcase_err_out;
+#endif /* NTFS_RW */
 	/*
 	 * Get the cluster allocation bitmap inode and verify the size, no
 	 * need for any locking at this stage as we are already running
@@ -1311,7 +1411,7 @@
 		iput(vol->lcnbmp_ino);
 bitmap_failed:
 		ntfs_error(sb, "Failed to load $Bitmap.");
-		goto iput_mirr_err_out;
+		goto iput_attrdef_err_out;
 	}
 	/*
 	 * Get the volume inode and setup our cache of the volume flags and
@@ -1331,14 +1431,14 @@
 		iput(vol->vol_ino);
 		goto volume_failed;
 	}
-	if (!(ctx = get_attr_search_ctx(NTFS_I(vol->vol_ino), m))) {
+	if (!(ctx = ntfs_attr_get_search_ctx(NTFS_I(vol->vol_ino), m))) {
 		ntfs_error(sb, "Failed to get attribute search context.");
 		goto get_ctx_vol_failed;
 	}
-	if (!lookup_attr(AT_VOLUME_INFORMATION, NULL, 0, 0, 0, NULL, 0, ctx) ||
-			ctx->attr->non_resident || ctx->attr->flags) {
+	if (ntfs_attr_lookup(AT_VOLUME_INFORMATION, NULL, 0, 0, 0, NULL, 0,
+			ctx) || ctx->attr->non_resident || ctx->attr->flags) {
 err_put_vol:
-		put_attr_search_ctx(ctx);
+		ntfs_attr_put_search_ctx(ctx);
 get_ctx_vol_failed:
 		unmap_mft_record(NTFS_I(vol->vol_ino));
 		goto iput_volume_failed;
@@ -1354,7 +1454,7 @@
 	vol->vol_flags = vi->flags;
 	vol->major_ver = vi->major_ver;
 	vol->minor_ver = vi->minor_ver;
-	put_attr_search_ctx(ctx);
+	ntfs_attr_put_search_ctx(ctx);
 	unmap_mft_record(NTFS_I(vol->vol_ino));
 	printk(KERN_INFO "NTFS volume version %i.%i.\n", vol->major_ver,
 			vol->minor_ver);
@@ -1483,19 +1583,6 @@
 		NVolSetErrors(vol);
 	}
 #endif /* NTFS_RW */
-	/*
-	 * Get the inode for the attribute definitions file and parse the
-	 * attribute definitions.
-	 */
-	tmp_ino = ntfs_iget(sb, FILE_AttrDef);
-	if (IS_ERR(tmp_ino) || is_bad_inode(tmp_ino)) {
-		if (!IS_ERR(tmp_ino))
-			iput(tmp_ino);
-		ntfs_error(sb, "Failed to load $AttrDef.");
-		goto iput_logfile_err_out;
-	}
-	// FIXME: Parse the attribute definitions.
-	iput(tmp_ino);
 	/* Get the root directory inode. */
 	vol->root_ino = ntfs_iget(sb, FILE_root);
 	if (IS_ERR(vol->root_ino) || is_bad_inode(vol->root_ino)) {
@@ -1591,6 +1678,26 @@
 	iput(vol->vol_ino);
 iput_lcnbmp_err_out:
 	iput(vol->lcnbmp_ino);
+iput_attrdef_err_out:
+	vol->attrdef_size = 0;
+	if (vol->attrdef) {
+		ntfs_free(vol->attrdef);
+		vol->attrdef = NULL;
+	}
+#ifdef NTFS_RW
+iput_upcase_err_out:
+#endif /* NTFS_RW */
+	vol->upcase_len = 0;
+	down(&ntfs_lock);
+	if (vol->upcase == default_upcase) {
+		ntfs_nr_upcase_users--;
+		vol->upcase = NULL;
+	}
+	up(&ntfs_lock);
+	if (vol->upcase) {
+		ntfs_free(vol->upcase);
+		vol->upcase = NULL;
+	}
 iput_mftbmp_err_out:
 	iput(vol->mftbmp_ino);
 iput_mirr_err_out:
@@ -1762,14 +1869,18 @@
 	iput(vol->mft_ino);
 	vol->mft_ino = NULL;
 
+	/* Throw away the table of attribute definitions. */
+	vol->attrdef_size = 0;
+	if (vol->attrdef) {
+		ntfs_free(vol->attrdef);
+		vol->attrdef = NULL;
+	}
 	vol->upcase_len = 0;
 	/*
-	 * Decrease the number of mounts and destroy the global default upcase
-	 * table if necessary.  Also decrease the number of upcase users if we
-	 * are a user.
+	 * Destroy the global default upcase table if necessary.  Also decrease
+	 * the number of upcase users if we are a user.
 	 */
 	down(&ntfs_lock);
-	ntfs_nr_mounts--;
 	if (vol->upcase == default_upcase) {
 		ntfs_nr_upcase_users--;
 		vol->upcase = NULL;
@@ -1906,7 +2017,7 @@
  */
 static unsigned long __get_nr_free_mft_records(ntfs_volume *vol)
 {
-	s64 nr_free = vol->nr_mft_records;
+	s64 nr_free;
 	u32 *kaddr;
 	struct address_space *mapping = vol->mftbmp_ino->i_mapping;
 	filler_t *readpage = (filler_t*)mapping->a_ops->readpage;
@@ -1915,13 +2026,16 @@
 	unsigned int max_size;
 
 	ntfs_debug("Entering.");
+	/* Number of mft records in file system (at this point in time). */
+	nr_free = vol->mft_ino->i_size >> vol->mft_record_size_bits;
 	/*
-	 * Convert the number of bits into bytes rounded up, then convert into
-	 * multiples of PAGE_CACHE_SIZE, rounding up so that if we have one
-	 * full and one partial page max_index = 2.
-	 */
-	max_index = (((vol->nr_mft_records + 7) >> 3) + PAGE_CACHE_SIZE - 1) >>
-			PAGE_CACHE_SHIFT;
+	 * Convert the maximum number of set bits into bytes rounded up, then
+	 * convert into multiples of PAGE_CACHE_SIZE, rounding up so that if we
+	 * have one full and one partial page max_index = 2.
+	 */
+	max_index = ((((NTFS_I(vol->mft_ino)->initialized_size >>
+			vol->mft_record_size_bits) + 7) >> 3) +
+			PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT;
 	/* Use multiples of 4 bytes. */
 	max_size = PAGE_CACHE_SIZE >> 2;
 	ntfs_debug("Reading $MFT/$BITMAP, max_index = 0x%lx, max_size = "
@@ -2016,9 +2130,9 @@
 	sfs->f_bavail = sfs->f_bfree = size;
 	/* Serialize accesses to the inode bitmap. */
 	down_read(&vol->mftbmp_lock);
-	/* Total file nodes in file system (at this moment in time). */
-	sfs->f_files  = vol->mft_ino->i_size >> vol->mft_record_size_bits;
-	/* Free file nodes in fs (based on current total count). */
+	/* Number of inodes in file system (at this point in time). */
+	sfs->f_files = vol->mft_ino->i_size >> vol->mft_record_size_bits;
+	/* Free inodes in fs (based on current total count). */
 	sfs->f_ffree = __get_nr_free_mft_records(vol);
 	up_read(&vol->mftbmp_lock);
 	/*
@@ -2139,15 +2253,7 @@
 	ntfs_debug("Entering.");
 #ifndef NTFS_RW
 	sb->s_flags |= MS_RDONLY | MS_NOATIME | MS_NODIRATIME;
-#else
-	if (!(sb->s_flags & MS_NOATIME))
-		ntfs_warning(sb, "Atime updates are not implemented yet.  "
-				"Disabling them.");
-	else if (!(sb->s_flags & MS_NODIRATIME))
-		ntfs_warning(sb, "Directory atime updates are not implemented "
-				"yet.  Disabling them.");
-	sb->s_flags |= MS_NOATIME | MS_NODIRATIME;
-#endif
+#endif /* ! NTFS_RW */
 	/* Allocate a new ntfs_volume and place it in sb->s_fs_info. */
 	sb->s_fs_info = kmalloc(sizeof(ntfs_volume), GFP_NOFS);
 	vol = NTFS_SB(sb);
@@ -2161,6 +2267,7 @@
 	memset(vol, 0, sizeof(ntfs_volume));
 	vol->sb = sb;
 	vol->upcase = NULL;
+	vol->attrdef = NULL;
 	vol->mft_ino = NULL;
 	vol->mftbmp_ino = NULL;
 	init_rwsem(&vol->mftbmp_lock);
@@ -2188,6 +2295,8 @@
 	vol->fmask = 0177;
 	vol->dmask = 0077;
 
+	unlock_kernel();
+
 	/* Important to get the mount options dealt with now. */
 	if (!parse_options(vol, (char*)opt))
 		goto err_out_now;
@@ -2225,6 +2334,9 @@
 	 */
 	result = parse_ntfs_boot_sector(vol, (NTFS_BOOT_SECTOR*)bh->b_data);
 
+	/* Initialize the cluster allocator. */
+	setup_lcn_allocator(vol);
+
 	brelse(bh);
 
 	if (!result) {
@@ -2289,14 +2401,13 @@
 		}
 	}
 	/*
-	 * Increment the number of mounts and generate the global default
-	 * upcase table if necessary. Also temporarily increment the number of
-	 * upcase users to avoid race conditions with concurrent (u)mounts.
+	 * Generate the global default upcase table if necessary.  Also
+	 * temporarily increment the number of upcase users to avoid race
+	 * conditions with concurrent (u)mounts.
 	 */
-	if (!ntfs_nr_mounts++)
+	if (!default_upcase)
 		default_upcase = generate_default_upcase();
 	ntfs_nr_upcase_users++;
-
 	up(&ntfs_lock);
 	/*
 	 * From now on, ignore @silent parameter. If we fail below this line,
@@ -2322,6 +2433,7 @@
 		}
 		up(&ntfs_lock);
 		sb->s_export_op = &ntfs_export_ops;
+		lock_kernel();
 		return 0;
 	}
 	ntfs_error(sb, "Failed to allocate root directory.");
@@ -2368,10 +2480,23 @@
 		vol->mftmirr_ino = NULL;
 	}
 #endif /* NTFS_RW */
+	/* Throw away the table of attribute definitions. */
+	vol->attrdef_size = 0;
+	if (vol->attrdef) {
+		ntfs_free(vol->attrdef);
+		vol->attrdef = NULL;
+	}
 	vol->upcase_len = 0;
-	if (vol->upcase != default_upcase)
+	down(&ntfs_lock);
+	if (vol->upcase == default_upcase) {
+		ntfs_nr_upcase_users--;
+		vol->upcase = NULL;
+	}
+	up(&ntfs_lock);
+	if (vol->upcase) {
 		ntfs_free(vol->upcase);
-	vol->upcase = NULL;
+		vol->upcase = NULL;
+	}
 	if (vol->nls_map) {
 		unload_nls(vol->nls_map);
 		vol->nls_map = NULL;
@@ -2379,11 +2504,10 @@
 	/* Error exit code path. */
 unl_upcase_iput_tmp_ino_err_out_now:
 	/*
-	 * Decrease the number of mounts and destroy the global default upcase
-	 * table if necessary.
+	 * Decrease the number of upcase users and destroy the global default
+	 * upcase table if necessary.
 	 */
 	down(&ntfs_lock);
-	ntfs_nr_mounts--;
 	if (!--ntfs_nr_upcase_users && default_upcase) {
 		ntfs_free(default_upcase);
 		default_upcase = NULL;
@@ -2413,6 +2537,7 @@
 	}
 	/* Errors at this stage are irrelevant. */
 err_out_now:
+	lock_kernel();
 	sb->s_fs_info = NULL;
 	kfree(vol);
 	ntfs_debug("Failed, returning -EINVAL.");
@@ -2449,12 +2574,9 @@
 kmem_cache_t *ntfs_index_ctx_cache;
 
 /* A global default upcase table and a corresponding reference count. */
-wchar_t *default_upcase = NULL;
+ntfschar *default_upcase = NULL;
 unsigned long ntfs_nr_upcase_users = 0;
 
-/* The number of mounted filesystems. */
-unsigned long ntfs_nr_mounts = 0;
-
 /* Driver wide semaphore. */
 DECLARE_MUTEX(ntfs_lock);
 
@@ -2509,7 +2631,7 @@
 		goto ictx_err_out;
 	}
 	ntfs_attr_ctx_cache = kmem_cache_create(ntfs_attr_ctx_cache_name,
-			sizeof(attr_search_context), 0 /* offset */,
+			sizeof(ntfs_attr_search_ctx), 0 /* offset */,
 			SLAB_HWCACHE_ALIGN, NULL /* ctor */, NULL /* dtor */);
 	if (!ntfs_attr_ctx_cache) {
 		printk(KERN_CRIT "NTFS: Failed to create %s!\n",
@@ -2528,7 +2650,7 @@
 
 	ntfs_inode_cache = kmem_cache_create(ntfs_inode_cache_name,
 			sizeof(ntfs_inode), 0,
-			SLAB_HWCACHE_ALIGN|SLAB_RECLAIM_ACCOUNT, NULL, NULL);
+			SLAB_RECLAIM_ACCOUNT, NULL, NULL);
 	if (!ntfs_inode_cache) {
 		printk(KERN_CRIT "NTFS: Failed to create %s!\n",
 				ntfs_inode_cache_name);
@@ -2614,7 +2736,7 @@
 MODULE_DESCRIPTION("NTFS 1.2/3.x driver - Copyright (c) 2001-2004 Anton Altaparmakov");
 MODULE_LICENSE("GPL");
 #ifdef DEBUG
-MODULE_PARM(debug_msgs, "i");
+module_param(debug_msgs, bool, 0);
 MODULE_PARM_DESC(debug_msgs, "Enable debug messages.");
 #endif
 
diff -Nru a/fs/ntfs/time.h b/fs/ntfs/time.h
--- a/fs/ntfs/time.h	2004-10-18 14:56:48 -07:00
+++ b/fs/ntfs/time.h	2004-10-18 14:56:48 -07:00
@@ -45,7 +45,7 @@
  * measured as the number of 100-nano-second intervals since 1st January 1601,
  * 00:00:00 UTC.
  */
-static inline s64 utc2ntfs(const struct timespec ts)
+static inline sle64 utc2ntfs(const struct timespec ts)
 {
 	/*
 	 * Convert the seconds to 100ns intervals, add the nano-seconds
@@ -61,7 +61,7 @@
  * Get the current time from the Linux kernel, convert it to its corresponding
  * NTFS time and return that in little endian format.
  */
-static inline s64 get_current_ntfs_time(void)
+static inline sle64 get_current_ntfs_time(void)
 {
 	return utc2ntfs(current_kernel_time());
 }
@@ -82,7 +82,7 @@
  * measured as the number of 100 nano-second intervals since 1st January 1601,
  * 00:00:00 UTC.
  */
-static inline struct timespec ntfs2utc(const s64 time)
+static inline struct timespec ntfs2utc(const sle64 time)
 {
 	struct timespec ts;
 
diff -Nru a/fs/ntfs/types.h b/fs/ntfs/types.h
--- a/fs/ntfs/types.h	2004-10-18 14:56:49 -07:00
+++ b/fs/ntfs/types.h	2004-10-18 14:56:49 -07:00
@@ -23,8 +23,17 @@
 #ifndef _LINUX_NTFS_TYPES_H
 #define _LINUX_NTFS_TYPES_H
 
+#include <linux/types.h>
+
+typedef __le16 le16;
+typedef __le32 le32;
+typedef __le64 le64;
+typedef __u16 __bitwise sle16;
+typedef __u32 __bitwise sle32;
+typedef __u64 __bitwise sle64;
+
 /* 2-byte Unicode character type. */
-typedef u16 ntfschar;
+typedef le16 ntfschar;
 #define UCHAR_T_SIZE_BITS 1
 
 /*
@@ -32,7 +41,9 @@
  * and VCN, to allow for type checking and better code readability.
  */
 typedef s64 VCN;
+typedef sle64 leVCN;
 typedef s64 LCN;
+typedef sle64 leLCN;
 
 /*
  * The NTFS journal $LogFile uses log sequence numbers which are signed 64-bit
@@ -40,9 +51,10 @@
  * code readability.
  */
 typedef s64 LSN;
+typedef sle64 leLSN;
 
 /**
- * run_list_element - in memory vcn to lcn mapping array element
+ * runlist_element - in memory vcn to lcn mapping array element
  * @vcn:	starting vcn of the current array element
  * @lcn:	starting lcn of the current array element
  * @length:	length in clusters of the current array element
@@ -56,18 +68,18 @@
 	VCN vcn;	/* vcn = Starting virtual cluster number. */
 	LCN lcn;	/* lcn = Starting logical cluster number. */
 	s64 length;	/* Run length in clusters. */
-} run_list_element;
+} runlist_element;
 
 /**
- * run_list - in memory vcn to lcn mapping array including a read/write lock
- * @rl:		pointer to an array of run list elements
+ * runlist - in memory vcn to lcn mapping array including a read/write lock
+ * @rl:		pointer to an array of runlist elements
  * @lock:	read/write spinlock for serializing access to @rl
  *
  */
 typedef struct {
-	run_list_element *rl;
+	runlist_element *rl;
 	struct rw_semaphore lock;
-} run_list;
+} runlist;
 
 typedef enum {
 	FALSE = 0,
diff -Nru a/fs/ntfs/unistr.c b/fs/ntfs/unistr.c
--- a/fs/ntfs/unistr.c	2004-10-18 14:56:48 -07:00
+++ b/fs/ntfs/unistr.c	2004-10-18 14:56:48 -07:00
@@ -96,7 +96,7 @@
 		const ntfschar *upcase, const u32 upcase_len)
 {
 	u32 cnt, min_len;
-	ntfschar c1, c2;
+	u16 c1, c2;
 
 	min_len = name1_len;
 	if (name1_len > name2_len)
@@ -144,7 +144,7 @@
  */
 int ntfs_ucsncmp(const ntfschar *s1, const ntfschar *s2, size_t n)
 {
-	ntfschar c1, c2;
+	u16 c1, c2;
 	size_t i;
 
 	for (i = 0; i < n; ++i) {
@@ -181,8 +181,8 @@
 int ntfs_ucsncasecmp(const ntfschar *s1, const ntfschar *s2, size_t n,
 		const ntfschar *upcase, const u32 upcase_size)
 {
-	ntfschar c1, c2;
 	size_t i;
+	u16 c1, c2;
 
 	for (i = 0; i < n; ++i) {
 		if ((c1 = le16_to_cpu(s1[i])) < upcase_size)
@@ -203,7 +203,7 @@
 		const u32 upcase_len)
 {
 	u32 i;
-	ntfschar u;
+	u16 u;
 
 	for (i = 0; i < name_len; i++)
 		if ((u = le16_to_cpu(name[i])) < upcase_len)
@@ -276,7 +276,7 @@
 				} /* else (wc_len < 0) */
 				goto conversion_err;
 			}
-			ucs[o] = cpu_to_le16('\0');
+			ucs[o] = 0;
 			*outs = ucs;
 			return o;
 		} /* else (!ucs) */
@@ -362,7 +362,7 @@
 			} /* wc < 0, real error. */
 			goto conversion_err;
 		}
-		ns[o] = '\0';
+		ns[o] = 0;
 		*outs = ns;
 		return o;
 	} /* else (!ins) */
diff -Nru a/fs/ntfs/upcase.c b/fs/ntfs/upcase.c
--- a/fs/ntfs/upcase.c	2004-10-18 14:55:54 -07:00
+++ b/fs/ntfs/upcase.c	2004-10-18 14:55:54 -07:00
@@ -3,7 +3,7 @@
  *	      Part of the Linux-NTFS project.
  *
  * Copyright (c) 2001 Richard Russon <ntfs@flatcap.org>
- * Copyright (c) 2001-2003 Anton Altaparmakov
+ * Copyright (c) 2001-2004 Anton Altaparmakov
  *
  * Modified for mkntfs inclusion 9 June 2001 by Anton Altaparmakov.
  * Modified for kernel inclusion 10 September 2001 by Anton Altparmakov.
@@ -87,4 +87,3 @@
 		uc[uc_word_table[r][0]] = cpu_to_le16(uc_word_table[r][1]);
 	return uc;
 }
-
diff -Nru a/fs/ntfs/volume.h b/fs/ntfs/volume.h
--- a/fs/ntfs/volume.h	2004-10-18 14:55:55 -07:00
+++ b/fs/ntfs/volume.h	2004-10-18 14:55:55 -07:00
@@ -73,16 +73,28 @@
 	/* Mount specific NTFS information. */
 	u32 upcase_len;			/* Number of entries in upcase[]. */
 	ntfschar *upcase;		/* The upcase table. */
+
+	s32 attrdef_size;		/* Size of the attribute definition
+					   table in bytes. */
+	ATTR_DEF *attrdef;		/* Table of attribute definitions.
+					   Obtained from FILE_AttrDef. */
+
+#ifdef NTFS_RW
+	/* Variables used by the cluster and mft allocators. */
 	LCN mft_zone_start;		/* First cluster of the mft zone. */
 	LCN mft_zone_end;		/* First cluster beyond the mft zone. */
+	LCN mft_zone_pos;		/* Current position in the mft zone. */
+	LCN data1_zone_pos;		/* Current position in the first data
+					   zone. */
+	LCN data2_zone_pos;		/* Current position in the second data
+					   zone. */
+#endif /* NTFS_RW */
+
 	struct inode *mft_ino;		/* The VFS inode of $MFT. */
 
 	struct inode *mftbmp_ino;	/* Attribute inode for $MFT/$BITMAP. */
 	struct rw_semaphore mftbmp_lock; /* Lock for serializing accesses to the
 					    mft record bitmap ($MFT/$BITMAP). */
-	unsigned long nr_mft_records;	/* Number of mft records == number of
-					   bits in mft bitmap. */
-
 #ifdef NTFS_RW
 	struct inode *mftmirr_ino;	/* The VFS inode of $MFTMirr. */
 	int mftmirr_size;		/* Size of mft mirror in mft records. */
diff -Nru a/fs/openpromfs/inode.c b/fs/openpromfs/inode.c
--- a/fs/openpromfs/inode.c	2004-10-18 14:56:29 -07:00
+++ b/fs/openpromfs/inode.c	2004-10-18 14:56:29 -07:00
@@ -79,7 +79,7 @@
 		count = 9 - file->f_pos;
 	if (copy_to_user(buf, buffer + file->f_pos, count))
 		return -EFAULT;
-	file->f_pos += count;
+	*ppos += count;
 	return count;
 }
 
@@ -94,7 +94,7 @@
 	openprom_property *op;
 	char buffer[64];
 	
-	if (filp->f_pos >= 0xffffff || count >= 0xffffff)
+	if (*ppos >= 0xffffff || count >= 0xffffff)
 		return -EINVAL;
 	if (!filp->private_data) {
 		node = nodes[(u16)((long)inode->u.generic_ip)].node;
@@ -180,7 +180,7 @@
 	} else {
 		i = (op->len << 1) + 1;
 	}
-	k = filp->f_pos;
+	k = *ppos;
 	if (k >= i) return 0;
 	if (count > i - k) count = i - k;
 	if (op->flag & OPP_STRING) {
@@ -197,7 +197,7 @@
 			j = count;
 
 		if (j >= 0) {
-			if (copy_to_user(buf + k - filp->f_pos,
+			if (copy_to_user(buf + k - *ppos,
 					 op->value + k - 1, j))
 				return -EFAULT;
 			count -= j;
@@ -205,11 +205,11 @@
 		}
 
 		if (count) {
-			if (put_user('\'', &buf [k++ - filp->f_pos]))
+			if (put_user('\'', &buf [k++ - *ppos]))
 				return -EFAULT;
 		}
 		if (count > 1) {
-			if (put_user('\n', &buf [k++ - filp->f_pos]))
+			if (put_user('\n', &buf [k++ - *ppos]))
 				return -EFAULT;
 		}
 	} else if (op->flag & OPP_STRINGLIST) {
@@ -287,7 +287,7 @@
 		if ((k < i - 1) && (k & 1)) {
 			sprintf (buffer, "%02x",
 				 (unsigned char) *(op->value + (k >> 1)) & 0xff);
-			if (put_user(buffer[1], &buf[k++ - filp->f_pos]))
+			if (put_user(buffer[1], &buf[k++ - *ppos]))
 				return -EFAULT;
 			count--;
 		}
@@ -295,7 +295,7 @@
 		for (; (count > 1) && (k < i - 1); k += 2) {
 			sprintf (buffer, "%02x",
 				 (unsigned char) *(op->value + (k >> 1)) & 0xff);
-			if (copy_to_user(buf + k - filp->f_pos, buffer, 2))
+			if (copy_to_user(buf + k - *ppos, buffer, 2))
 				return -EFAULT;
 			count -= 2;
 		}
@@ -303,18 +303,18 @@
 		if (count && (k < i - 1)) {
 			sprintf (buffer, "%02x",
 				 (unsigned char) *(op->value + (k >> 1)) & 0xff);
-			if (put_user(buffer[0], &buf[k++ - filp->f_pos]))
+			if (put_user(buffer[0], &buf[k++ - *ppos]))
 				return -EFAULT;
 			count--;
 		}
 
 		if (count) {
-			if (put_user('\n', &buf [k++ - filp->f_pos]))
+			if (put_user('\n', &buf [k++ - *ppos]))
 				return -EFAULT;
 		}
 	}
-	count = k - filp->f_pos;
-	filp->f_pos = k;
+	count = k - *ppos;
+	*ppos = k;
 	return count;
 }
 
@@ -327,14 +327,14 @@
 	void *b;
 	openprom_property *op;
 	
-	if (filp->f_pos >= 0xffffff || count >= 0xffffff)
+	if (*ppos >= 0xffffff || count >= 0xffffff)
 		return -EINVAL;
 	if (!filp->private_data) {
 		i = property_read (filp, NULL, 0, NULL);
 		if (i)
 			return i;
 	}
-	k = filp->f_pos;
+	k = *ppos;
 	op = (openprom_property *)filp->private_data;
 	if (!(op->flag & OPP_STRING)) {
 		u32 *first, *last;
@@ -462,7 +462,7 @@
 				op->len = i;
 		} else
 			op->len = i;
-		filp->f_pos += count;
+		*ppos += count;
 	}
 write_try_string:
 	if (!(op->flag & OPP_BINARY)) {
@@ -480,7 +480,7 @@
 				op->flag |= OPP_QUOTED;
 				buf++;
 				count--;
-				filp->f_pos++;
+				(*ppos)++;
 				if (!count) {
 					op->flag |= OPP_STRING;
 					return 1;
@@ -489,9 +489,9 @@
 				op->flag |= OPP_NOTQUOTED;
 		}
 		op->flag |= OPP_STRING;
-		if (op->alloclen <= count + filp->f_pos) {
+		if (op->alloclen <= count + *ppos) {
 			b = kmalloc (sizeof (openprom_property)
-				     + 2 * (count + filp->f_pos), GFP_KERNEL);
+				     + 2 * (count + *ppos), GFP_KERNEL);
 			if (!b)
 				return -ENOMEM;
 			memcpy (b, filp->private_data,
@@ -499,14 +499,14 @@
 				+ strlen (op->name) + op->alloclen);
 			memset (((char *)b) + sizeof (openprom_property)
 				+ strlen (op->name) + op->alloclen, 
-				0, 2*(count - filp->f_pos) - op->alloclen);
+				0, 2*(count - *ppos) - op->alloclen);
 			op = (openprom_property *)b;
-			op->alloclen = 2*(count + filp->f_pos);
+			op->alloclen = 2*(count + *ppos);
 			b = filp->private_data;
 			filp->private_data = (void *)op;
 			kfree (b);
 		}
-		p = op->value + filp->f_pos - ((op->flag & OPP_QUOTED) ? 1 : 0);
+		p = op->value + *ppos - ((op->flag & OPP_QUOTED) ? 1 : 0);
 		if (copy_from_user(p, buf, count))
 			return -EFAULT;
 		op->flag |= OPP_DIRTY;
@@ -517,17 +517,17 @@
 			}
 		if (i < count) {
 			op->len = p - op->value;
-			filp->f_pos += i + 1;
+			*ppos += i + 1;
 			if ((p > op->value) && (op->flag & OPP_QUOTED)
 			    && (*(p - 1) == '\''))
 				op->len--;
 		} else {
 			if (p - op->value > op->len)
 				op->len = p - op->value;
-			filp->f_pos += count;
+			*ppos += count;
 		}
 	}
-	return filp->f_pos - k;
+	return *ppos - k;
 }
 
 int property_release (struct inode *inode, struct file *filp)
diff -Nru a/fs/partitions/acorn.c b/fs/partitions/acorn.c
--- a/fs/partitions/acorn.c	2004-10-18 14:56:33 -07:00
+++ b/fs/partitions/acorn.c	2004-10-18 14:56:33 -07:00
@@ -53,16 +53,16 @@
 #ifdef CONFIG_ACORN_PARTITION_RISCIX
 
 struct riscix_part {
-	__u32	start;
-	__u32	length;
-	__u32	one;
+	__le32	start;
+	__le32	length;
+	__le32	one;
 	char	name[16];
 };
 
 struct riscix_record {
-	__u32	magic;
-#define RISCIX_MAGIC	(0x4a657320)
-	__u32	date;
+	__le32	magic;
+#define RISCIX_MAGIC	cpu_to_le32(0x4a657320)
+	__le32	date;
 	struct riscix_part part[8];
 };
 
@@ -111,9 +111,9 @@
 #define LINUX_SWAP_MAGIC   0xdeafab1e
 
 struct linux_part {
-	__u32 magic;
-	__u32 start_sect;
-	__u32 nr_sects;
+	__le32 magic;
+	__le32 start_sect;
+	__le32 nr_sects;
 };
 
 static int
@@ -306,8 +306,8 @@
 #ifdef CONFIG_ACORN_PARTITION_ICS
 
 struct ics_part {
-	__u32 start;
-	__s32 size;
+	__le32 start;
+	__le32 size;
 };
 
 static int adfspart_check_ICSLinux(struct block_device *bdev, unsigned long block)
@@ -336,7 +336,7 @@
 	for (i = 0, sum = 0x50617274; i < 508; i++)
 		sum += data[i];
 
-	sum -= le32_to_cpu(*(__u32 *)(&data[508]));
+	sum -= le32_to_cpu(*(__le32 *)(&data[508]));
 
 	return sum == 0;
 }
@@ -412,11 +412,11 @@
 
 #ifdef CONFIG_ACORN_PARTITION_POWERTEC
 struct ptec_part {
-	__u32 unused1;
-	__u32 unused2;
-	__u32 start;
-	__u32 size;
-	__u32 unused5;
+	__le32 unused1;
+	__le32 unused2;
+	__le32 start;
+	__le32 size;
+	__le32 unused5;
 	char type[8];
 };
 
@@ -486,10 +486,10 @@
 struct eesox_part {
 	char	magic[6];
 	char	name[10];
-	u32	start;
-	u32	unused6;
-	u32	unused7;
-	u32	unused8;
+	__le32	start;
+	__le32	unused6;
+	__le32	unused7;
+	__le32	unused8;
 };
 
 /*
diff -Nru a/fs/partitions/amiga.c b/fs/partitions/amiga.c
--- a/fs/partitions/amiga.c	2004-10-18 14:56:29 -07:00
+++ b/fs/partitions/amiga.c	2004-10-18 14:56:29 -07:00
@@ -14,7 +14,7 @@
 #include "amiga.h"
 
 static __inline__ u32
-checksum_block(u32 *m, int size)
+checksum_block(__be32 *m, int size)
 {
 	u32 sum = 0;
 
@@ -31,6 +31,7 @@
 	struct RigidDiskBlock *rdb;
 	struct PartitionBlock *pb;
 	int start_sect, nr_sects, blk, part, res = 0;
+	int blksize = 1;	/* Multiplier for disk block size */
 	int slot = 1;
 	char b[BDEVNAME_SIZE];
 
@@ -44,17 +45,17 @@
 				       bdevname(bdev, b), blk);
 			goto rdb_done;
 		}
-		if (*(u32 *)data != cpu_to_be32(IDNAME_RIGIDDISK))
+		if (*(__be32 *)data != cpu_to_be32(IDNAME_RIGIDDISK))
 			continue;
 
 		rdb = (struct RigidDiskBlock *)data;
-		if (checksum_block((u32 *)data, be32_to_cpu(rdb->rdb_SummedLongs) & 0x7F) == 0)
+		if (checksum_block((__be32 *)data, be32_to_cpu(rdb->rdb_SummedLongs) & 0x7F) == 0)
 			break;
 		/* Try again with 0xdc..0xdf zeroed, Windows might have
 		 * trashed it.
 		 */
-		*(u32 *)(data+0xdc) = 0;
-		if (checksum_block((u32 *)data,
+		*(__be32 *)(data+0xdc) = 0;
+		if (checksum_block((__be32 *)data,
 				be32_to_cpu(rdb->rdb_SummedLongs) & 0x7F)==0) {
 			printk("Warning: Trashed word at 0xd0 in block %d "
 				"ignored in checksum calculation\n",blk);
@@ -65,10 +66,14 @@
 			       bdevname(bdev, b), blk);
 	}
 
-	printk(" RDSK");
+	/* blksize is blocks per 512 byte standard block */
+	blksize = be32_to_cpu( rdb->rdb_BlockBytes ) / 512;
+
+	printk(" RDSK (%d)", blksize * 512);	/* Be more informative */
 	blk = be32_to_cpu(rdb->rdb_PartitionList);
 	put_dev_sector(sect);
 	for (part = 1; blk>0 && part<=16; part++, put_dev_sector(sect)) {
+		blk *= blksize;	/* Read in terms partition table understands */
 		data = read_dev_sector(bdev, blk, &sect);
 		if (!data) {
 			if (warn_no_part)
@@ -80,7 +85,7 @@
 		blk = be32_to_cpu(pb->pb_Next);
 		if (pb->pb_ID != cpu_to_be32(IDNAME_PARTITION))
 			continue;
-		if (checksum_block((u32 *)pb, be32_to_cpu(pb->pb_SummedLongs) & 0x7F) != 0 )
+		if (checksum_block((__be32 *)pb, be32_to_cpu(pb->pb_SummedLongs) & 0x7F) != 0 )
 			continue;
 
 		/* Tell Kernel about it */
@@ -88,13 +93,32 @@
 		nr_sects = (be32_to_cpu(pb->pb_Environment[10]) + 1 -
 			    be32_to_cpu(pb->pb_Environment[9])) *
 			   be32_to_cpu(pb->pb_Environment[3]) *
-			   be32_to_cpu(pb->pb_Environment[5]);
+			   be32_to_cpu(pb->pb_Environment[5]) *
+			   blksize;
 		if (!nr_sects)
 			continue;
 		start_sect = be32_to_cpu(pb->pb_Environment[9]) *
 			     be32_to_cpu(pb->pb_Environment[3]) *
-			     be32_to_cpu(pb->pb_Environment[5]);
+			     be32_to_cpu(pb->pb_Environment[5]) *
+			     blksize;
 		put_partition(state,slot++,start_sect,nr_sects);
+		{
+			/* Be even more informative to aid mounting */
+			char dostype[4];
+			__be32 *dt = (__be32 *)dostype;
+			*dt = pb->pb_Environment[16];
+			if (dostype[3] < ' ')
+				printk(" (%c%c%c^%c)",
+					dostype[0], dostype[1],
+					dostype[2], dostype[3] + '@' );
+			else
+				printk(" (%c%c%c%c)",
+					dostype[0], dostype[1],
+					dostype[2], dostype[3]);
+			printk("(res %d spb %d)",
+				be32_to_cpu(pb->pb_Environment[6]),
+				be32_to_cpu(pb->pb_Environment[4]));
+		}
 		res = 1;
 	}
 	printk("\n");
diff -Nru a/fs/partitions/atari.h b/fs/partitions/atari.h
--- a/fs/partitions/atari.h	2004-10-18 14:56:32 -07:00
+++ b/fs/partitions/atari.h	2004-10-18 14:56:32 -07:00
@@ -15,8 +15,8 @@
 {
   u8 flg;			/* bit 0: active; bit 7: bootable */
   char id[3];			/* "GEM", "BGM", "XGM", or other */
-  u32 st;			/* start of partition */
-  u32 siz;			/* length of partition */
+  __be32 st;			/* start of partition */
+  __be32 siz;			/* length of partition */
 };
 
 struct rootsector
diff -Nru a/fs/partitions/efi.h b/fs/partitions/efi.h
--- a/fs/partitions/efi.h	2004-10-18 14:56:48 -07:00
+++ b/fs/partitions/efi.h	2004-10-18 14:56:48 -07:00
@@ -66,20 +66,20 @@
               0xa2, 0x3c, 0x23, 0x8f, 0x2a, 0x3d, 0xf9, 0x28)
 
 typedef struct _gpt_header {
-	u64 signature;
-	u32 revision;
-	u32 header_size;
-	u32 header_crc32;
-	u32 reserved1;
-	u64 my_lba;
-	u64 alternate_lba;
-	u64 first_usable_lba;
-	u64 last_usable_lba;
+	__le64 signature;
+	__le32 revision;
+	__le32 header_size;
+	__le32 header_crc32;
+	__le32 reserved1;
+	__le64 my_lba;
+	__le64 alternate_lba;
+	__le64 first_usable_lba;
+	__le64 last_usable_lba;
 	efi_guid_t disk_guid;
-	u64 partition_entry_lba;
-	u32 num_partition_entries;
-	u32 sizeof_partition_entry;
-	u32 partition_entry_array_crc32;
+	__le64 partition_entry_lba;
+	__le32 num_partition_entries;
+	__le32 sizeof_partition_entry;
+	__le32 partition_entry_array_crc32;
 	u8 reserved2[GPT_BLOCK_SIZE - 92];
 } __attribute__ ((packed)) gpt_header;
 
@@ -92,18 +92,18 @@
 typedef struct _gpt_entry {
 	efi_guid_t partition_type_guid;
 	efi_guid_t unique_partition_guid;
-	u64 starting_lba;
-	u64 ending_lba;
+	__le64 starting_lba;
+	__le64 ending_lba;
 	gpt_entry_attributes attributes;
 	efi_char16_t partition_name[72 / sizeof (efi_char16_t)];
 } __attribute__ ((packed)) gpt_entry;
 
 typedef struct _legacy_mbr {
 	u8 boot_code[440];
-	u32 unique_mbr_signature;
-	u16 unknown;
+	__le32 unique_mbr_signature;
+	__le16 unknown;
 	struct partition partition_record[4];
-	u16 signature;
+	__le16 signature;
 } __attribute__ ((packed)) legacy_mbr;
 
 /* Functions */
diff -Nru a/fs/partitions/ldm.c b/fs/partitions/ldm.c
--- a/fs/partitions/ldm.c	2004-10-18 14:56:28 -07:00
+++ b/fs/partitions/ldm.c	2004-10-18 14:56:28 -07:00
@@ -2,7 +2,7 @@
  * ldm - Support for Windows Logical Disk Manager (Dynamic Disks)
  *
  * Copyright (C) 2001,2002 Richard Russon <ldm@flatcap.org>
- * Copyright (C) 2001      Anton Altaparmakov <aia21@cantab.net>
+ * Copyright (c) 2001-2004 Anton Altaparmakov
  * Copyright (C) 2001,2002 Jakob Kemi <jakob.kemi@telia.com>
  *
  * Documentation is available at http://linux-ntfs.sf.net/ldm
@@ -517,9 +517,15 @@
 	if (vm->vblk_offset != 512)
 		ldm_info ("VBLKs start at offset 0x%04x.", vm->vblk_offset);
 
-	/* FIXME: How should we handle this situation? */
-	if ((vm->vblk_size * vm->last_vblk_seq) != (toc->bitmap1_size << 9))
-		ldm_info ("VMDB and TOCBLOCK don't agree on the database size.");
+	/*
+	 * The last_vblkd_seq can be before the end of the vmdb, just make sure
+	 * it is not out of bounds.
+	 */
+	if ((vm->vblk_size * vm->last_vblk_seq) > (toc->bitmap1_size << 9)) {
+		ldm_crit ("VMDB exceeds allowed size specified by TOCBLOCK.  "
+				"Database is corrupt.  Aborting.");
+		goto out;
+	}
 
 	result = TRUE;
 out:
@@ -560,7 +566,7 @@
 		return FALSE;
 	}
 
-	if (*(u16*) (data + 0x01FE) != cpu_to_le16 (MSDOS_LABEL_MAGIC))
+	if (*(__le16*) (data + 0x01FE) != cpu_to_le16 (MSDOS_LABEL_MAGIC))
 		goto out;
 
 	p = (struct partition*)(data + 0x01BE);
diff -Nru a/fs/partitions/ldm.h b/fs/partitions/ldm.h
--- a/fs/partitions/ldm.h	2004-10-18 14:56:28 -07:00
+++ b/fs/partitions/ldm.h	2004-10-18 14:56:28 -07:00
@@ -99,9 +99,9 @@
 #define TOC_BITMAP2		"log"		/* bitmaps in the TOCBLOCK. */
 
 /* Most numbers we deal with are big-endian and won't be aligned. */
-#define BE16(x)			((u16)be16_to_cpu(get_unaligned((u16*)(x))))
-#define BE32(x)			((u32)be32_to_cpu(get_unaligned((u32*)(x))))
-#define BE64(x)			((u64)be64_to_cpu(get_unaligned((u64*)(x))))
+#define BE16(x)			((u16)be16_to_cpu(get_unaligned((__be16*)(x))))
+#define BE32(x)			((u32)be32_to_cpu(get_unaligned((__be32*)(x))))
+#define BE64(x)			((u64)be64_to_cpu(get_unaligned((__be64*)(x))))
 
 /* Borrowed from msdos.c */
 #define SYS_IND(p)		(get_unaligned(&(p)->sys_ind))
diff -Nru a/fs/partitions/mac.h b/fs/partitions/mac.h
--- a/fs/partitions/mac.h	2004-10-18 14:56:49 -07:00
+++ b/fs/partitions/mac.h	2004-10-18 14:56:49 -07:00
@@ -8,23 +8,23 @@
 #define APPLE_AUX_TYPE	"Apple_UNIX_SVR2"
 
 struct mac_partition {
-	__u16	signature;	/* expected to be MAC_PARTITION_MAGIC */
-	__u16	res1;
-	__u32	map_count;	/* # blocks in partition map */
-	__u32	start_block;	/* absolute starting block # of partition */
-	__u32	block_count;	/* number of blocks in partition */
+	__be16	signature;	/* expected to be MAC_PARTITION_MAGIC */
+	__be16	res1;
+	__be32	map_count;	/* # blocks in partition map */
+	__be32	start_block;	/* absolute starting block # of partition */
+	__be32	block_count;	/* number of blocks in partition */
 	char	name[32];	/* partition name */
 	char	type[32];	/* string type description */
-	__u32	data_start;	/* rel block # of first data block */
-	__u32	data_count;	/* number of data blocks */
-	__u32	status;		/* partition status bits */
-	__u32	boot_start;
-	__u32	boot_size;
-	__u32	boot_load;
-	__u32	boot_load2;
-	__u32	boot_entry;
-	__u32	boot_entry2;
-	__u32	boot_cksum;
+	__be32	data_start;	/* rel block # of first data block */
+	__be32	data_count;	/* number of data blocks */
+	__be32	status;		/* partition status bits */
+	__be32	boot_start;
+	__be32	boot_size;
+	__be32	boot_load;
+	__be32	boot_load2;
+	__be32	boot_entry;
+	__be32	boot_entry2;
+	__be32	boot_cksum;
 	char	processor[16];	/* identifies ISA of boot */
 	/* there is more stuff after this that we don't need */
 };
@@ -35,9 +35,9 @@
 
 /* Driver descriptor structure, in block 0 */
 struct mac_driver_desc {
-	__u16	signature;	/* expected to be MAC_DRIVER_MAGIC */
-	__u16	block_size;
-	__u32	block_count;
+	__be16	signature;	/* expected to be MAC_DRIVER_MAGIC */
+	__be16	block_size;
+	__be32	block_count;
     /* ... more stuff */
 };
 
diff -Nru a/fs/partitions/msdos.c b/fs/partitions/msdos.c
--- a/fs/partitions/msdos.c	2004-10-18 14:56:33 -07:00
+++ b/fs/partitions/msdos.c	2004-10-18 14:56:33 -07:00
@@ -246,6 +246,9 @@
 		put_partition(state, state->next++, bsd_start, bsd_size);
 	}
 	put_dev_sector(sect);
+	if (le16_to_cpu(l->d_npartitions) > max_partitions)
+		printk(" (ignored %d more)",
+		       le16_to_cpu(l->d_npartitions) - max_partitions);
 	printk(" >\n");
 }
 #endif
diff -Nru a/fs/partitions/osf.c b/fs/partitions/osf.c
--- a/fs/partitions/osf.c	2004-10-18 14:56:49 -07:00
+++ b/fs/partitions/osf.c	2004-10-18 14:56:49 -07:00
@@ -17,34 +17,34 @@
 	Sector sect;
 	unsigned char *data;
 	struct disklabel {
-		u32 d_magic;
-		u16 d_type,d_subtype;
+		__le32 d_magic;
+		__le16 d_type,d_subtype;
 		u8 d_typename[16];
 		u8 d_packname[16];
-		u32 d_secsize;
-		u32 d_nsectors;
-		u32 d_ntracks;
-		u32 d_ncylinders;
-		u32 d_secpercyl;
-		u32 d_secprtunit;
-		u16 d_sparespertrack;
-		u16 d_sparespercyl;
-		u32 d_acylinders;
-		u16 d_rpm, d_interleave, d_trackskew, d_cylskew;
-		u32 d_headswitch, d_trkseek, d_flags;
-		u32 d_drivedata[5];
-		u32 d_spare[5];
-		u32 d_magic2;
-		u16 d_checksum;
-		u16 d_npartitions;
-		u32 d_bbsize, d_sbsize;
+		__le32 d_secsize;
+		__le32 d_nsectors;
+		__le32 d_ntracks;
+		__le32 d_ncylinders;
+		__le32 d_secpercyl;
+		__le32 d_secprtunit;
+		__le16 d_sparespertrack;
+		__le16 d_sparespercyl;
+		__le32 d_acylinders;
+		__le16 d_rpm, d_interleave, d_trackskew, d_cylskew;
+		__le32 d_headswitch, d_trkseek, d_flags;
+		__le32 d_drivedata[5];
+		__le32 d_spare[5];
+		__le32 d_magic2;
+		__le16 d_checksum;
+		__le16 d_npartitions;
+		__le32 d_bbsize, d_sbsize;
 		struct d_partition {
-			u32 p_size;
-			u32 p_offset;
-			u32 p_fsize;
+			__le32 p_size;
+			__le32 p_offset;
+			__le32 p_fsize;
 			u8  p_fstype;
 			u8  p_frag;
-			u16 p_cpg;
+			__le16 p_cpg;
 		} d_partitions[8];
 	} * label;
 	struct d_partition * partition;
diff -Nru a/fs/partitions/sgi.c b/fs/partitions/sgi.c
--- a/fs/partitions/sgi.c	2004-10-18 14:56:17 -07:00
+++ b/fs/partitions/sgi.c	2004-10-18 14:56:17 -07:00
@@ -8,30 +8,32 @@
 #include "sgi.h"
 
 struct sgi_disklabel {
-	s32 magic_mushroom;		/* Big fat spliff... */
-	s16 root_part_num;		/* Root partition number */
-	s16 swap_part_num;		/* Swap partition number */
+	__be32 magic_mushroom;		/* Big fat spliff... */
+	__be16 root_part_num;		/* Root partition number */
+	__be16 swap_part_num;		/* Swap partition number */
 	s8 boot_file[16];		/* Name of boot file for ARCS */
 	u8 _unused0[48];		/* Device parameter useless crapola.. */
 	struct sgi_volume {
 		s8 name[8];		/* Name of volume */
-		s32 block_num;		/* Logical block number */
-		s32 num_bytes;		/* How big, in bytes */
+		__be32 block_num;		/* Logical block number */
+		__be32 num_bytes;		/* How big, in bytes */
 	} volume[15];
 	struct sgi_partition {
-		u32 num_blocks;		/* Size in logical blocks */
-		u32 first_block;	/* First logical block */
-		s32 type;		/* Type of this partition */
+		__be32 num_blocks;		/* Size in logical blocks */
+		__be32 first_block;	/* First logical block */
+		__be32 type;		/* Type of this partition */
 	} partitions[16];
-	s32 csum;			/* Disk label checksum */
-	s32 _unused1;			/* Padding */
+	__be32 csum;			/* Disk label checksum */
+	__be32 _unused1;			/* Padding */
 };
 
 int sgi_partition(struct parsed_partitions *state, struct block_device *bdev)
 {
-	int i, csum, magic;
+	int i, csum;
+	__be32 magic;
 	int slot = 1;
-	unsigned int *ui, start, blocks, cs;
+	unsigned int start, blocks;
+	__be32 *ui, cs;
 	Sector sect;
 	struct sgi_disklabel *label;
 	struct sgi_partition *p;
@@ -44,12 +46,12 @@
 	magic = label->magic_mushroom;
 	if(be32_to_cpu(magic) != SGI_LABEL_MAGIC) {
 		/*printk("Dev %s SGI disklabel: bad magic %08x\n",
-		       bdevname(bdev, b), magic);*/
+		       bdevname(bdev, b), be32_to_cpu(magic));*/
 		put_dev_sector(sect);
 		return 0;
 	}
-	ui = ((unsigned int *) (label + 1)) - 1;
-	for(csum = 0; ui >= ((unsigned int *) label);) {
+	ui = ((__be32 *) (label + 1)) - 1;
+	for(csum = 0; ui >= ((__be32 *) label);) {
 		cs = *ui--;
 		csum += be32_to_cpu(cs);
 	}
diff -Nru a/fs/partitions/sun.c b/fs/partitions/sun.c
--- a/fs/partitions/sun.c	2004-10-18 14:57:03 -07:00
+++ b/fs/partitions/sun.c	2004-10-18 14:57:03 -07:00
@@ -12,9 +12,10 @@
 
 int sun_partition(struct parsed_partitions *state, struct block_device *bdev)
 {
-	int i, csum;
+	int i;
+	__be16 csum;
 	int slot = 1;
-	unsigned short *ush;
+	__be16 *ush;
 	Sector sect;
 	struct sun_disklabel {
 		unsigned char info[128];   /* Informative text string */
@@ -26,22 +27,22 @@
 			unsigned char flags;
 		} infos[8];
 		unsigned char spare[246];  /* Boot information etc. */
-		unsigned short rspeed;     /* Disk rotational speed */
-		unsigned short pcylcount;  /* Physical cylinder count */
-		unsigned short sparecyl;   /* extra sects per cylinder */
+		__be16 rspeed;     /* Disk rotational speed */
+		__be16 pcylcount;  /* Physical cylinder count */
+		__be16 sparecyl;   /* extra sects per cylinder */
 		unsigned char spare2[4];   /* More magic... */
-		unsigned short ilfact;     /* Interleave factor */
-		unsigned short ncyl;       /* Data cylinder count */
-		unsigned short nacyl;      /* Alt. cylinder count */
-		unsigned short ntrks;      /* Tracks per cylinder */
-		unsigned short nsect;      /* Sectors per track */
+		__be16 ilfact;     /* Interleave factor */
+		__be16 ncyl;       /* Data cylinder count */
+		__be16 nacyl;      /* Alt. cylinder count */
+		__be16 ntrks;      /* Tracks per cylinder */
+		__be16 nsect;      /* Sectors per track */
 		unsigned char spare3[4];   /* Even more magic... */
 		struct sun_partition {
-			__u32 start_cylinder;
-			__u32 num_sectors;
+			__be32 start_cylinder;
+			__be32 num_sectors;
 		} partitions[8];
-		unsigned short magic;      /* Magic number */
-		unsigned short csum;       /* Label xor'd checksum */
+		__be16 magic;      /* Magic number */
+		__be16 csum;       /* Label xor'd checksum */
 	} * label;		
 	struct sun_partition *p;
 	unsigned long spc;
@@ -59,8 +60,8 @@
 		return 0;
 	}
 	/* Look at the checksum */
-	ush = ((unsigned short *) (label+1)) - 1;
-	for (csum = 0; ush >= ((unsigned short *) label);)
+	ush = ((__be16 *) (label+1)) - 1;
+	for (csum = 0; ush >= ((__be16 *) label);)
 		csum ^= *ush--;
 	if (csum) {
 		printk("Dev %s Sun disklabel: Csum bad, label corrupted\n",
diff -Nru a/fs/proc/array.c b/fs/proc/array.c
--- a/fs/proc/array.c	2004-10-18 14:56:33 -07:00
+++ b/fs/proc/array.c	2004-10-18 14:56:33 -07:00
@@ -88,10 +88,13 @@
 {
 	int i;
 	char * name;
+	char tcomm[sizeof(p->comm)];
+
+	get_task_comm(tcomm, p);
 
 	ADDBUF(buf, "Name:\t");
-	name = p->comm;
-	i = sizeof(p->comm);
+	name = tcomm;
+	i = sizeof(tcomm);
 	do {
 		unsigned char c = *name;
 		name++;
@@ -127,8 +130,9 @@
 	"S (sleeping)",		/*  1 */
 	"D (disk sleep)",	/*  2 */
 	"T (stopped)",		/*  4 */
-	"Z (zombie)",		/*  8 */
-	"X (dead)"		/* 16 */
+	"T (tracing stop)",	/*  8 */
+	"Z (zombie)",		/* 16 */
+	"X (dead)"		/* 32 */
 };
 
 static inline const char * get_task_state(struct task_struct *tsk)
@@ -138,7 +142,8 @@
 					   TASK_UNINTERRUPTIBLE |
 					   TASK_ZOMBIE |
 					   TASK_DEAD |
-					   TASK_STOPPED);
+					   TASK_STOPPED |
+					   TASK_TRACED);
 	const char **p = &task_state_array[0];
 
 	while (state) {
@@ -275,7 +280,6 @@
 			    cap_t(p->cap_effective));
 }
 
-extern char *task_mem(struct mm_struct *, char *);
 int proc_pid_status(struct task_struct *task, char * buffer)
 {
 	char * orig = buffer;
@@ -296,7 +300,6 @@
 	return buffer - orig;
 }
 
-extern unsigned long task_vsize(struct mm_struct *);
 int proc_pid_stat(struct task_struct *task, char * buffer)
 {
 	unsigned long vsize, eip, esp, wchan;
@@ -309,22 +312,19 @@
 	int num_threads = 0;
 	struct mm_struct *mm;
 	unsigned long long start_time;
+	unsigned long cmin_flt = 0, cmaj_flt = 0, cutime = 0, cstime = 0;
+	char tcomm[sizeof(task->comm)];
 
 	state = *get_task_state(task);
 	vsize = eip = esp = 0;
-	task_lock(task);
-	mm = task->mm;
-	if(mm)
-		mm = mmgrab(mm);
-	task_unlock(task);
+	mm = get_task_mm(task);
 	if (mm) {
-		down_read(&mm->mmap_sem);
 		vsize = task_vsize(mm);
 		eip = KSTK_EIP(task);
 		esp = KSTK_ESP(task);
-		up_read(&mm->mmap_sem);
 	}
 
+	get_task_comm(tcomm, task);
 	wchan = get_wchan(task);
 
 	sigemptyset(&sigign);
@@ -343,6 +343,10 @@
 		}
 		pgid = process_group(task);
 		sid = task->signal->session;
+		cmin_flt = task->signal->cmin_flt;
+		cmaj_flt = task->signal->cmaj_flt;
+		cutime = task->signal->cutime;
+		cstime = task->signal->cstime;
 	}
 	read_unlock(&tasklist_lock);
 
@@ -356,13 +360,17 @@
 	read_unlock(&tasklist_lock);
 
 	/* Temporary variable needed for gcc-2.96 */
-	start_time = jiffies_64_to_clock_t(task->start_time - INITIAL_JIFFIES);
+	/* convert timespec -> nsec*/
+	start_time = (unsigned long long)task->start_time.tv_sec * NSEC_PER_SEC
+				+ task->start_time.tv_nsec;
+	/* convert nsec -> ticks */
+	start_time = nsec_to_clock_t(start_time);
 
 	res = sprintf(buffer,"%d (%s) %c %d %d %d %d %d %lu %lu \
 %lu %lu %lu %lu %lu %ld %ld %ld %ld %d %ld %llu %lu %ld %lu %lu %lu %lu %lu \
 %lu %lu %lu %lu %lu %lu %lu %lu %d %d %lu %lu\n",
 		task->pid,
-		task->comm,
+		tcomm,
 		state,
 		ppid,
 		pgid,
@@ -371,13 +379,13 @@
 		tty_pgrp,
 		task->flags,
 		task->min_flt,
-		task->cmin_flt,
+		cmin_flt,
 		task->maj_flt,
-		task->cmaj_flt,
+		cmaj_flt,
 		jiffies_to_clock_t(task->utime),
 		jiffies_to_clock_t(task->stime),
-		jiffies_to_clock_t(task->cutime),
-		jiffies_to_clock_t(task->cstime),
+		jiffies_to_clock_t(cutime),
+		jiffies_to_clock_t(cstime),
 		priority,
 		nice,
 		num_threads,
@@ -411,17 +419,13 @@
 	return res;
 }
 
-extern int task_statm(struct mm_struct *, int *, int *, int *, int *);
 int proc_pid_statm(struct task_struct *task, char *buffer)
 {
 	int size = 0, resident = 0, shared = 0, text = 0, lib = 0, data = 0;
 	struct mm_struct *mm = get_task_mm(task);
 	
 	if (mm) {
-		down_read(&mm->mmap_sem);
 		size = task_statm(mm, &shared, &text, &data, &resident);
-		up_read(&mm->mmap_sem);
-
 		mmput(mm);
 	}
 
diff -Nru a/fs/proc/base.c b/fs/proc/base.c
--- a/fs/proc/base.c	2004-10-18 14:56:33 -07:00
+++ b/fs/proc/base.c	2004-10-18 14:56:33 -07:00
@@ -60,6 +60,9 @@
 	PROC_TGID_MAPS,
 	PROC_TGID_MOUNTS,
 	PROC_TGID_WCHAN,
+#ifdef CONFIG_SCHEDSTATS
+	PROC_TGID_SCHEDSTAT,
+#endif
 #ifdef CONFIG_SECURITY
 	PROC_TGID_ATTR,
 	PROC_TGID_ATTR_CURRENT,
@@ -83,6 +86,9 @@
 	PROC_TID_MAPS,
 	PROC_TID_MOUNTS,
 	PROC_TID_WCHAN,
+#ifdef CONFIG_SCHEDSTATS
+	PROC_TID_SCHEDSTAT,
+#endif
 #ifdef CONFIG_SECURITY
 	PROC_TID_ATTR,
 	PROC_TID_ATTR_CURRENT,
@@ -123,6 +129,9 @@
 #ifdef CONFIG_KALLSYMS
 	E(PROC_TGID_WCHAN,     "wchan",   S_IFREG|S_IRUGO),
 #endif
+#ifdef CONFIG_SCHEDSTATS
+	E(PROC_TGID_SCHEDSTAT, "schedstat", S_IFREG|S_IRUGO),
+#endif
 	{0,0,NULL,0}
 };
 static struct pid_entry tid_base_stuff[] = {
@@ -145,6 +154,9 @@
 #ifdef CONFIG_KALLSYMS
 	E(PROC_TID_WCHAN,      "wchan",   S_IFREG|S_IRUGO),
 #endif
+#ifdef CONFIG_SCHEDSTATS
+	E(PROC_TID_SCHEDSTAT, "schedstat",S_IFREG|S_IRUGO),
+#endif
 	{0,0,NULL,0}
 };
 
@@ -180,7 +192,6 @@
 int proc_pid_stat(struct task_struct*,char*);
 int proc_pid_status(struct task_struct*,char*);
 int proc_pid_statm(struct task_struct*,char*);
-int proc_pid_cpu(struct task_struct*,char*);
 
 static int proc_fd_link(struct inode *inode, struct dentry **dentry, struct vfsmount **mnt)
 {
@@ -276,7 +287,8 @@
 #define MAY_PTRACE(task) \
 	(task == current || \
 	(task->parent == current && \
-	(task->ptrace & PT_PTRACED) &&  task->state == TASK_STOPPED && \
+	(task->ptrace & PT_PTRACED) && \
+	 (task->state == TASK_STOPPED || task->state == TASK_TRACED) && \
 	 security_ptrace(current,task) == 0))
 
 static int may_ptrace_attach(struct task_struct *task)
@@ -329,6 +341,8 @@
 	struct mm_struct *mm = get_task_mm(task);
 	if (!mm)
 		goto out;
+	if (!mm->arg_end)
+		goto out;	/* Shh! No looking before we're done */
 
  	len = mm->arg_end - mm->arg_start;
  
@@ -339,7 +353,7 @@
 
 	// If the nul at the end of args has been overwritten, then
 	// assume application is using setproctitle(3).
-	if (res > 0 && buffer[res-1] != '\0') {
+	if (res > 0 && buffer[res-1] != '\0' && len < PAGE_SIZE) {
 		len = strnlen(buffer, res);
 		if (len < res) {
 		    res = len;
@@ -397,6 +411,19 @@
 }
 #endif /* CONFIG_KALLSYMS */
 
+#ifdef CONFIG_SCHEDSTATS
+/*
+ * Provides /proc/PID/schedstat
+ */
+static int proc_pid_schedstat(struct task_struct *task, char *buffer)
+{
+	return sprintf(buffer, "%lu %lu %lu\n",
+			task->sched_info.cpu_time,
+			task->sched_info.run_delay,
+			task->sched_info.pcnt);
+}
+#endif
+
 /************************************************************************/
 /*                       Here the fs part begins                        */
 /************************************************************************/
@@ -517,7 +544,6 @@
 	struct inode * inode = file->f_dentry->d_inode;
 	unsigned long page;
 	ssize_t length;
-	ssize_t end;
 	struct task_struct *task = proc_task(inode);
 
 	if (count > PROC_BLOCK_SIZE)
@@ -527,24 +553,10 @@
 
 	length = PROC_I(inode)->op.proc_read(task, (char*)page);
 
-	if (length < 0) {
-		free_page(page);
-		return length;
-	}
-	/* Static 4kB (or whatever) block capacity */
-	if (*ppos >= length) {
-		free_page(page);
-		return 0;
-	}
-	if (count + *ppos > length)
-		count = length - *ppos;
-	end = count + *ppos;
-	if (copy_to_user(buf, (char *) page + *ppos, count))
-		count = -EFAULT;
-	else
-		*ppos = end;
+	if (length >= 0)
+		length = simple_read_from_buffer(buf, count, ppos, (char *)page, length);
 	free_page(page);
-	return count;
+	return length;
 }
 
 static struct file_operations proc_info_file_operations = {
@@ -767,10 +779,9 @@
 	.follow_link	= proc_pid_follow_link
 };
 
-static int pid_alive(struct task_struct *p)
+static inline int pid_alive(struct task_struct *p)
 {
-	BUG_ON(p->pids[PIDTYPE_PID].pidptr != &p->pids[PIDTYPE_PID].pid);
-	return atomic_read(&p->pids[PIDTYPE_PID].pid.count);
+	return p->pids[PIDTYPE_PID].nr != 0;
 }
 
 #define NUMBUF 10
@@ -1168,7 +1179,6 @@
 	struct inode * inode = file->f_dentry->d_inode;
 	unsigned long page;
 	ssize_t length;
-	ssize_t end;
 	struct task_struct *task = proc_task(inode);
 
 	if (count > PAGE_SIZE)
@@ -1179,24 +1189,10 @@
 	length = security_getprocattr(task, 
 				      (char*)file->f_dentry->d_name.name, 
 				      (void*)page, count);
-	if (length < 0) {
-		free_page(page);
-		return length;
-	}
-	/* Static 4kB (or whatever) block capacity */
-	if (*ppos >= length) {
-		free_page(page);
-		return 0;
-	}
-	if (count + *ppos > length)
-		count = length - *ppos;
-	end = count + *ppos;
-	if (copy_to_user(buf, (char *) page + *ppos, count))
-		count = -EFAULT;
-	else
-		*ppos = end;
+	if (length >= 0)
+		length = simple_read_from_buffer(buf, count, ppos, (char *)page, length);
 	free_page(page);
-	return count;
+	return length;
 }
 
 static ssize_t proc_pid_attr_write(struct file * file, const char __user * buf,
@@ -1375,6 +1371,13 @@
 			ei->op.proc_read = proc_pid_wchan;
 			break;
 #endif
+#ifdef CONFIG_SCHEDSTATS
+		case PROC_TID_SCHEDSTAT:
+		case PROC_TGID_SCHEDSTAT:
+			inode->i_fop = &proc_info_file_operations;
+			ei->op.proc_read = proc_pid_schedstat;
+			break;
+#endif
 		default:
 			printk("procfs: impossible type (%d)",p->type);
 			iput(inode);
@@ -1526,6 +1529,7 @@
 	
 void proc_pid_flush(struct dentry *proc_dentry)
 {
+	might_sleep();
 	if(proc_dentry != NULL) {
 		shrink_dcache_parent(proc_dentry);
 		dput(proc_dentry);
@@ -1666,7 +1670,7 @@
 	p = NULL;
 	if (version) {
 		p = find_task_by_pid(version);
-		if (!thread_group_leader(p))
+		if (p && !thread_group_leader(p))
 			p = NULL;
 	}
 
@@ -1729,6 +1733,7 @@
 	char buf[PROC_NUMBUF];
 	unsigned int nr = filp->f_pos - FIRST_PROCESS_ENTRY;
 	unsigned int nr_tgids, i;
+	int next_tgid;
 
 	if (!nr) {
 		ino_t ino = fake_ino(0,PROC_TGID_INO);
@@ -1738,26 +1743,45 @@
 		nr++;
 	}
 
-	/*
-	 * f_version caches the last tgid which was returned from readdir
+	/* f_version caches the tgid value that the last readdir call couldn't
+	 * return. lseek aka telldir automagically resets f_version to 0.
 	 */
-	nr_tgids = get_tgid_list(nr, filp->f_version, tgid_array);
-
-	for (i = 0; i < nr_tgids; i++) {
-		int tgid = tgid_array[i];
-		ino_t ino = fake_ino(tgid,PROC_TGID_INO);
-		unsigned long j = PROC_NUMBUF;
+	next_tgid = filp->f_version;
+	filp->f_version = 0;
+	for (;;) {
+		nr_tgids = get_tgid_list(nr, next_tgid, tgid_array);
+		if (!nr_tgids) {
+			/* no more entries ! */
+			break;
+		}
+		next_tgid = 0;
 
-		do
-			buf[--j] = '0' + (tgid % 10);
-		while ((tgid /= 10) != 0);
+		/* do not use the last found pid, reserve it for next_tgid */
+		if (nr_tgids == PROC_MAXPIDS) {
+			nr_tgids--;
+			next_tgid = tgid_array[nr_tgids];
+		}
 
-		if (filldir(dirent, buf+j, PROC_NUMBUF-j, filp->f_pos, ino, DT_DIR) < 0) {
-			filp->f_version = tgid;
-			break;
+		for (i=0;i<nr_tgids;i++) {
+			int tgid = tgid_array[i];
+			ino_t ino = fake_ino(tgid,PROC_TGID_INO);
+			unsigned long j = PROC_NUMBUF;
+
+			do
+				buf[--j] = '0' + (tgid % 10);
+			while ((tgid /= 10) != 0);
+
+			if (filldir(dirent, buf+j, PROC_NUMBUF-j, filp->f_pos, ino, DT_DIR) < 0) {
+				/* returning this tgid failed, save it as the first
+				 * pid for the next readir call */
+				filp->f_version = tgid_array[i];
+				goto out;
+			}
+			filp->f_pos++;
+			nr++;
 		}
-		filp->f_pos++;
 	}
+out:
 	return 0;
 }
 
diff -Nru a/fs/proc/inode.c b/fs/proc/inode.c
--- a/fs/proc/inode.c	2004-10-18 14:57:03 -07:00
+++ b/fs/proc/inode.c	2004-10-18 14:57:03 -07:00
@@ -120,7 +120,7 @@
 {
 	proc_inode_cachep = kmem_cache_create("proc_inode_cache",
 					     sizeof(struct proc_inode),
-					     0, SLAB_HWCACHE_ALIGN|SLAB_RECLAIM_ACCOUNT,
+					     0, SLAB_RECLAIM_ACCOUNT,
 					     init_once, NULL);
 	if (proc_inode_cachep == NULL)
 		return -ENOMEM;
diff -Nru a/fs/proc/proc_misc.c b/fs/proc/proc_misc.c
--- a/fs/proc/proc_misc.c	2004-10-18 14:55:55 -07:00
+++ b/fs/proc/proc_misc.c	2004-10-18 14:55:55 -07:00
@@ -541,70 +541,6 @@
 	return proc_calc_metrics(page, start, off, count, eof, len);
 }
 
-/*
- * This function accesses profiling information. The returned data is
- * binary: the sampling step and the actual contents of the profile
- * buffer. Use of the program readprofile is recommended in order to
- * get meaningful info out of these data.
- */
-static ssize_t
-read_profile(struct file *file, char __user *buf, size_t count, loff_t *ppos)
-{
-	unsigned long p = *ppos;
-	ssize_t read;
-	char * pnt;
-	unsigned int sample_step = 1 << prof_shift;
-
-	if (p >= (prof_len+1)*sizeof(unsigned int))
-		return 0;
-	if (count > (prof_len+1)*sizeof(unsigned int) - p)
-		count = (prof_len+1)*sizeof(unsigned int) - p;
-	read = 0;
-
-	while (p < sizeof(unsigned int) && count > 0) {
-		put_user(*((char *)(&sample_step)+p),buf);
-		buf++; p++; count--; read++;
-	}
-	pnt = (char *)prof_buffer + p - sizeof(unsigned int);
-	if (copy_to_user(buf,(void *)pnt,count))
-		return -EFAULT;
-	read += count;
-	*ppos += read;
-	return read;
-}
-
-/*
- * Writing to /proc/profile resets the counters
- *
- * Writing a 'profiling multiplier' value into it also re-sets the profiling
- * interrupt frequency, on architectures that support this.
- */
-static ssize_t write_profile(struct file *file, const char __user *buf,
-			     size_t count, loff_t *ppos)
-{
-#ifdef CONFIG_SMP
-	extern int setup_profiling_timer (unsigned int multiplier);
-
-	if (count == sizeof(int)) {
-		unsigned int multiplier;
-
-		if (copy_from_user(&multiplier, buf, sizeof(int)))
-			return -EFAULT;
-
-		if (setup_profiling_timer(multiplier))
-			return -EINVAL;
-	}
-#endif
-
-	memset(prof_buffer, 0, prof_len * sizeof(*prof_buffer));
-	return count;
-}
-
-static struct file_operations proc_profile_operations = {
-	.read		= read_profile,
-	.write		= write_profile,
-};
-
 #ifdef CONFIG_MAGIC_SYSRQ
 /*
  * writing 'C' to /proc/sysrq-trigger is like sysrq-C
@@ -681,6 +617,9 @@
 #ifdef CONFIG_MODULES
 	create_seq_entry("modules", 0, &proc_modules_operations);
 #endif
+#ifdef CONFIG_SCHEDSTATS
+	create_seq_entry("schedstat", 0, &proc_schedstat_operations);
+#endif
 #ifdef CONFIG_PROC_KCORE
 	proc_root_kcore = create_proc_entry("kcore", S_IRUSR, NULL);
 	if (proc_root_kcore) {
@@ -689,13 +628,6 @@
 				(size_t)high_memory - PAGE_OFFSET + PAGE_SIZE;
 	}
 #endif
-	if (prof_on) {
-		entry = create_proc_entry("profile", S_IWUSR | S_IRUGO, NULL);
-		if (entry) {
-			entry->proc_fops = &proc_profile_operations;
-			entry->size = (1+prof_len) * sizeof(unsigned int);
-		}
-	}
 #ifdef CONFIG_MAGIC_SYSRQ
 	entry = create_proc_entry("sysrq-trigger", S_IWUSR, NULL);
 	if (entry)
diff -Nru a/fs/proc/proc_tty.c b/fs/proc/proc_tty.c
--- a/fs/proc/proc_tty.c	2004-10-18 14:56:28 -07:00
+++ b/fs/proc/proc_tty.c	2004-10-18 14:56:28 -07:00
@@ -15,9 +15,6 @@
 #include <linux/seq_file.h>
 #include <asm/bitops.h>
 
-extern struct tty_ldisc ldiscs[];
-
-
 static int tty_ldiscs_read_proc(char *page, char **start, off_t off,
 				int count, int *eof, void *data);
 
@@ -159,12 +156,15 @@
 	int	i;
 	int	len = 0;
 	off_t	begin = 0;
-
+	struct tty_ldisc *ld;
+	
 	for (i=0; i < NR_LDISCS; i++) {
-		if (!(ldiscs[i].flags & LDISC_FLAG_DEFINED))
+		ld = tty_ldisc_get(i);
+		if (ld == NULL)
 			continue;
 		len += sprintf(page+len, "%-10s %2d\n",
-			       ldiscs[i].name ? ldiscs[i].name : "???", i);
+			       ld->name ? ld->name : "???", i);
+		tty_ldisc_put(i);
 		if (len+begin > off+count)
 			break;
 		if (len+begin < off) {
diff -Nru a/fs/proc/root.c b/fs/proc/root.c
--- a/fs/proc/root.c	2004-10-18 14:56:49 -07:00
+++ b/fs/proc/root.c	2004-10-18 14:56:49 -07:00
@@ -18,7 +18,7 @@
 #include <asm/bitops.h>
 #include <linux/smp_lock.h>
 
-struct proc_dir_entry *proc_net, *proc_bus, *proc_root_fs, *proc_root_driver;
+struct proc_dir_entry *proc_net, *proc_net_stat, *proc_bus, *proc_root_fs, *proc_root_driver;
 
 #ifdef CONFIG_SYSCTL
 struct proc_dir_entry *proc_sys_root;
@@ -53,6 +53,8 @@
 	}
 	proc_misc_init();
 	proc_net = proc_mkdir("net", NULL);
+	proc_net_stat = proc_mkdir("net/stat", NULL);
+
 #ifdef CONFIG_SYSVIPC
 	proc_mkdir("sysvipc", NULL);
 #endif
@@ -157,5 +159,6 @@
 EXPORT_SYMBOL(proc_root);
 EXPORT_SYMBOL(proc_root_fs);
 EXPORT_SYMBOL(proc_net);
+EXPORT_SYMBOL(proc_net_stat);
 EXPORT_SYMBOL(proc_bus);
 EXPORT_SYMBOL(proc_root_driver);
diff -Nru a/fs/proc/task_mmu.c b/fs/proc/task_mmu.c
--- a/fs/proc/task_mmu.c	2004-10-18 14:55:55 -07:00
+++ b/fs/proc/task_mmu.c	2004-10-18 14:55:55 -07:00
@@ -6,27 +6,11 @@
 
 char *task_mem(struct mm_struct *mm, char *buffer)
 {
-	unsigned long data = 0, stack = 0, exec = 0, lib = 0;
-	struct vm_area_struct *vma;
+	unsigned long data, text, lib;
 
-	down_read(&mm->mmap_sem);
-	for (vma = mm->mmap; vma; vma = vma->vm_next) {
-		unsigned long len = (vma->vm_end - vma->vm_start) >> 10;
-		if (!vma->vm_file) {
-			data += len;
-			if (vma->vm_flags & VM_GROWSDOWN)
-				stack += len;
-			continue;
-		}
-		if (vma->vm_flags & VM_WRITE)
-			continue;
-		if (vma->vm_flags & VM_EXEC) {
-			exec += len;
-			if (vma->vm_flags & VM_EXECUTABLE)
-				continue;
-			lib += len;
-		}
-	}
+	data = mm->total_vm - mm->shared_vm - mm->stack_vm;
+	text = (mm->end_code - mm->start_code) >> 10;
+	lib = (mm->exec_vm << (PAGE_SHIFT-10)) - text;
 	buffer += sprintf(buffer,
 		"VmSize:\t%8lu kB\n"
 		"VmLck:\t%8lu kB\n"
@@ -35,12 +19,11 @@
 		"VmStk:\t%8lu kB\n"
 		"VmExe:\t%8lu kB\n"
 		"VmLib:\t%8lu kB\n",
-		mm->total_vm << (PAGE_SHIFT-10),
+		(mm->total_vm - mm->reserved_vm) << (PAGE_SHIFT-10),
 		mm->locked_vm << (PAGE_SHIFT-10),
 		mm->rss << (PAGE_SHIFT-10),
-		data - stack, stack,
-		exec - lib, lib);
-	up_read(&mm->mmap_sem);
+		data << (PAGE_SHIFT-10),
+		mm->stack_vm << (PAGE_SHIFT-10), text, lib);
 	return buffer;
 }
 
@@ -52,28 +35,11 @@
 int task_statm(struct mm_struct *mm, int *shared, int *text,
 	       int *data, int *resident)
 {
-	struct vm_area_struct *vma;
-	int size = 0;
-
+	*shared = mm->shared_vm;
+	*text = (mm->end_code - mm->start_code) >> PAGE_SHIFT;
+	*data = mm->total_vm - mm->shared_vm - *text;
 	*resident = mm->rss;
-	for (vma = mm->mmap; vma; vma = vma->vm_next) {
-		int pages = (vma->vm_end - vma->vm_start) >> PAGE_SHIFT;
-
-		size += pages;
-		if (is_vm_hugetlb_page(vma)) {
-			if (!(vma->vm_flags & VM_DONTCOPY))
-				*shared += pages;
-			continue;
-		}
-		if (vma->vm_file)
-			*shared += pages;
-		if (vma->vm_flags & VM_EXECUTABLE)
-			*text += pages;
-		else
-			*data += pages;
-	}
-
-	return size;
+	return mm->total_vm;
 }
 
 static int show_map(struct seq_file *m, void *v)
diff -Nru a/fs/proc/task_nommu.c b/fs/proc/task_nommu.c
--- a/fs/proc/task_nommu.c	2004-10-18 14:56:33 -07:00
+++ b/fs/proc/task_nommu.c	2004-10-18 14:56:33 -07:00
@@ -68,11 +68,12 @@
 	struct mm_tblock_struct *tbp;
 	unsigned long vsize = 0;
 
+	down_read(&mm->mmap_sem);
 	for (tbp = &mm->context.tblock; tbp; tbp = tbp->next) {
 		if (tbp->rblock)
 			vsize += kobjsize(tbp->rblock->kblock);
 	}
-
+	up_read(&mm->mmap_sem);
 	return vsize;
 }
 
@@ -81,7 +82,8 @@
 {
 	struct mm_tblock_struct *tbp;
 	int size = kobjsize(mm);
-	
+
+	down_read(&mm->mmap_sem);
 	for (tbp = &mm->context.tblock; tbp; tbp = tbp->next) {
 		if (tbp->next)
 			size += kobjsize(tbp->next);
@@ -93,7 +95,7 @@
 
 	size += (*text = mm->end_code - mm->start_code);
 	size += (*data = mm->start_stack - mm->start_data);
-
+	up_read(&mm->mmap_sem);
 	*resident = size;
 	return size;
 }
diff -Nru a/fs/qnx4/inode.c b/fs/qnx4/inode.c
--- a/fs/qnx4/inode.c	2004-10-18 14:56:50 -07:00
+++ b/fs/qnx4/inode.c	2004-10-18 14:56:50 -07:00
@@ -78,7 +78,7 @@
 	unlock_kernel();
 }
 
-static void qnx4_write_inode(struct inode *inode, int unused)
+static int qnx4_write_inode(struct inode *inode, int unused)
 {
 	struct qnx4_inode_entry *raw_inode;
 	int block, ino;
@@ -87,12 +87,12 @@
 
 	QNX4DEBUG(("qnx4: write inode 1.\n"));
 	if (inode->i_nlink == 0) {
-		return;
+		return 0;
 	}
 	if (!ino) {
 		printk("qnx4: bad inode number on dev %s: %d is out of range\n",
 		       inode->i_sb->s_id, ino);
-		return;
+		return -EIO;
 	}
 	QNX4DEBUG(("qnx4: write inode 2.\n"));
 	block = ino / QNX4_INODES_PER_BLOCK;
@@ -101,7 +101,7 @@
 		printk("qnx4: major problem: unable to read inode from dev "
 		       "%s\n", inode->i_sb->s_id);
 		unlock_kernel();
-		return;
+		return -EIO;
 	}
 	raw_inode = ((struct qnx4_inode_entry *) bh->b_data) +
 	    (ino % QNX4_INODES_PER_BLOCK);
@@ -117,6 +117,7 @@
 	mark_buffer_dirty(bh);
 	brelse(bh);
 	unlock_kernel();
+	return 0;
 }
 
 #endif
@@ -544,7 +545,7 @@
 {
 	qnx4_inode_cachep = kmem_cache_create("qnx4_inode_cache",
 					     sizeof(struct qnx4_inode_info),
-					     0, SLAB_HWCACHE_ALIGN|SLAB_RECLAIM_ACCOUNT,
+					     0, SLAB_RECLAIM_ACCOUNT,
 					     init_once, NULL);
 	if (qnx4_inode_cachep == NULL)
 		return -ENOMEM;
diff -Nru a/fs/quota_v1.c b/fs/quota_v1.c
--- a/fs/quota_v1.c	2004-10-18 14:56:49 -07:00
+++ b/fs/quota_v1.c	2004-10-18 14:56:49 -07:00
@@ -115,8 +115,8 @@
 
 /* Header of new quota format */
 struct v2_disk_dqheader {
-	__u32 dqh_magic;        /* Magic number identifying file */
-	__u32 dqh_version;      /* File version */
+	__le32 dqh_magic;        /* Magic number identifying file */
+	__le32 dqh_version;      /* File version */
 };
 
 static int v1_check_quota_file(struct super_block *sb, int type)
diff -Nru a/fs/quota_v2.c b/fs/quota_v2.c
--- a/fs/quota_v2.c	2004-10-18 14:56:49 -07:00
+++ b/fs/quota_v2.c	2004-10-18 14:56:49 -07:00
@@ -357,7 +357,7 @@
 	struct file *filp = sb_dqopt(dquot->dq_sb)->files[dquot->dq_type];
 	dqbuf_t buf;
 	int ret = 0, newson = 0, newact = 0;
-	u32 *ref;
+	__le32 *ref;
 	uint newblk;
 
 	if (!(buf = getdqbuf()))
@@ -376,14 +376,14 @@
 			goto out_buf;
 		}
 	}
-	ref = (u32 *)buf;
+	ref = (__le32 *)buf;
 	newblk = le32_to_cpu(ref[GETIDINDEX(dquot->dq_id, depth)]);
 	if (!newblk)
 		newson = 1;
 	if (depth == V2_DQTREEDEPTH-1) {
 #ifdef __QUOTA_V2_PARANOIA
 		if (newblk) {
-			printk(KERN_ERR "VFS: Inserting already present quota entry (block %u).\n", ref[GETIDINDEX(dquot->dq_id, depth)]);
+			printk(KERN_ERR "VFS: Inserting already present quota entry (block %u).\n", le32_to_cpu(ref[GETIDINDEX(dquot->dq_id, depth)]));
 			ret = -EIO;
 			goto out_buf;
 		}
@@ -510,7 +510,7 @@
 	dqbuf_t buf = getdqbuf();
 	int ret = 0;
 	uint newblk;
-	u32 *ref = (u32 *)buf;
+	__le32 *ref = (__le32 *)buf;
 	
 	if (!buf)
 		return -ENOMEM;
@@ -595,7 +595,7 @@
 	struct file *filp = sb_dqopt(dquot->dq_sb)->files[dquot->dq_type];
 	dqbuf_t buf = getdqbuf();
 	loff_t ret = 0;
-	u32 *ref = (u32 *)buf;
+	__le32 *ref = (__le32 *)buf;
 
 	if (!buf)
 		return -ENOMEM;
diff -Nru a/fs/ramfs/inode.c b/fs/ramfs/inode.c
--- a/fs/ramfs/inode.c	2004-10-18 14:56:28 -07:00
+++ b/fs/ramfs/inode.c	2004-10-18 14:56:28 -07:00
@@ -31,6 +31,7 @@
 #include <linux/string.h>
 #include <linux/smp_lock.h>
 #include <linux/backing-dev.h>
+#include <linux/ramfs.h>
 
 #include <asm/uaccess.h>
 
@@ -39,7 +40,6 @@
 
 static struct super_operations ramfs_ops;
 static struct address_space_operations ramfs_aops;
-static struct file_operations ramfs_file_operations;
 static struct inode_operations ramfs_file_inode_operations;
 static struct inode_operations ramfs_dir_inode_operations;
 
@@ -48,7 +48,7 @@
 	.memory_backed	= 1,	/* Does not contribute to dirty memory */
 };
 
-static struct inode *ramfs_get_inode(struct super_block *sb, int mode, dev_t dev)
+struct inode *ramfs_get_inode(struct super_block *sb, int mode, dev_t dev)
 {
 	struct inode * inode = new_inode(sb);
 
@@ -146,7 +146,7 @@
 	.commit_write	= simple_commit_write
 };
 
-static struct file_operations ramfs_file_operations = {
+struct file_operations ramfs_file_operations = {
 	.read		= generic_file_read,
 	.write		= generic_file_write,
 	.mmap		= generic_file_mmap,
@@ -199,7 +199,7 @@
 	return 0;
 }
 
-static struct super_block *ramfs_get_sb(struct file_system_type *fs_type,
+struct super_block *ramfs_get_sb(struct file_system_type *fs_type,
 	int flags, const char *dev_name, void *data)
 {
 	return get_sb_nodev(fs_type, flags, data, ramfs_fill_super);
diff -Nru a/fs/reiserfs/file.c b/fs/reiserfs/file.c
--- a/fs/reiserfs/file.c	2004-10-18 14:55:54 -07:00
+++ b/fs/reiserfs/file.c	2004-10-18 14:55:54 -07:00
@@ -89,15 +89,16 @@
 			      ) {
   struct inode * p_s_inode = p_s_dentry->d_inode;
   int n_err;
-
-  reiserfs_write_lock(p_s_inode->i_sb);
+  int barrier_done;
 
   if (!S_ISREG(p_s_inode->i_mode))
       BUG ();
-
   n_err = sync_mapping_buffers(p_s_inode->i_mapping) ;
-  reiserfs_commit_for_inode(p_s_inode) ;
+  reiserfs_write_lock(p_s_inode->i_sb);
+  barrier_done = reiserfs_commit_for_inode(p_s_inode);
   reiserfs_write_unlock(p_s_inode->i_sb);
+  if (barrier_done != 1)
+      blkdev_issue_flush(p_s_inode->i_sb->s_bdev, NULL);
   return ( n_err < 0 ) ? -EIO : 0;
 }
 
@@ -1098,7 +1099,7 @@
 {
     size_t already_written = 0; // Number of bytes already written to the file.
     loff_t pos; // Current position in the file.
-    size_t res; // return value of various functions that we call.
+    ssize_t res; // return value of various functions that we call.
     struct inode *inode = file->f_dentry->d_inode; // Inode of the file that we are writing to.
 				/* To simplify coding at this time, we store
 				   locked pages in array for now */
@@ -1107,7 +1108,7 @@
     th.t_trans_id = 0;
 
     if ( file->f_flags & O_DIRECT) { // Direct IO needs treatment
-	int result, after_file_end = 0;
+	ssize_t result, after_file_end = 0;
 	if ( (*ppos + count >= inode->i_size) || (file->f_flags & O_APPEND) ) {
 	    /* If we are appending a file, we need to put this savelink in here.
 	       If we will crash while doing direct io, finish_unfinished will
diff -Nru a/fs/reiserfs/inode.c b/fs/reiserfs/inode.c
--- a/fs/reiserfs/inode.c	2004-10-18 14:56:28 -07:00
+++ b/fs/reiserfs/inode.c	2004-10-18 14:56:28 -07:00
@@ -1504,7 +1504,7 @@
 ** to properly mark inodes for datasync and such, but only actually
 ** does something when called for a synchronous update.
 */
-void reiserfs_write_inode (struct inode * inode, int do_sync) {
+int reiserfs_write_inode (struct inode * inode, int do_sync) {
     struct reiserfs_transaction_handle th ;
     int jbegin_count = 1 ;
 
@@ -1512,7 +1512,7 @@
         reiserfs_warning (inode->i_sb,
 			  "clm-6005: writing inode %lu on readonly FS",
 			  inode->i_ino) ;
-        return ;
+        return -EROFS;
     }
     /* memory pressure can sometimes initiate write_inode calls with sync == 1,
     ** these cases are just when the system needs ram, not when the 
@@ -1526,6 +1526,7 @@
 	journal_end_sync(&th, inode->i_sb, jbegin_count) ;
 	reiserfs_write_unlock(inode->i_sb);
     }
+    return 0;
 }
 
 /* FIXME: no need any more. right? */
diff -Nru a/fs/reiserfs/journal.c b/fs/reiserfs/journal.c
--- a/fs/reiserfs/journal.c	2004-10-18 14:56:33 -07:00
+++ b/fs/reiserfs/journal.c	2004-10-18 14:56:33 -07:00
@@ -127,6 +127,12 @@
   return 0 ;
 }
 
+static void disable_barrier(struct super_block *s)
+{
+    REISERFS_SB(s)->s_mount_opt &= ~(1 << REISERFS_BARRIER_FLUSH);
+    printk("reiserfs: disabling flush barriers on %s\n", reiserfs_bdevname(s));
+}
+
 static struct reiserfs_bitmap_node *
 allocate_bitmap_node(struct super_block *p_s_sb) {
   struct reiserfs_bitmap_node *bn ;
@@ -640,6 +646,26 @@
     submit_bh(WRITE, bh) ;
 }
 
+static int submit_barrier_buffer(struct buffer_head *bh) {
+    get_bh(bh) ;
+    bh->b_end_io = reiserfs_end_ordered_io;
+    clear_buffer_dirty(bh) ;
+    if (!buffer_uptodate(bh))
+        BUG();
+    return submit_bh(WRITE_BARRIER, bh) ;
+}
+
+static void check_barrier_completion(struct super_block *s,
+                                     struct buffer_head *bh) {
+    if (buffer_eopnotsupp(bh)) {
+	clear_buffer_eopnotsupp(bh);
+	disable_barrier(s);
+	set_buffer_uptodate(bh);
+	set_buffer_dirty(bh);
+	sync_dirty_buffer(bh);
+    }
+}
+
 #define CHUNK_SIZE 32
 struct buffer_chunk {
     struct buffer_head *bh[CHUNK_SIZE];
@@ -909,6 +935,7 @@
   int bn ;
   struct buffer_head *tbh = NULL ;
   unsigned long trans_id = jl->j_trans_id;
+  int barrier = 0;
 
   reiserfs_check_lock_depth(s, "flush_commit_list") ;
 
@@ -973,7 +1000,20 @@
   }
   atomic_dec(&SB_JOURNAL(s)->j_async_throttle);
 
-  /* wait on everything written so far before writing the commit */
+  /* wait on everything written so far before writing the commit
+   * if we are in barrier mode, send the commit down now
+   */
+  barrier = reiserfs_barrier_flush(s);
+  if (barrier) {
+      int ret;
+      lock_buffer(jl->j_commit_bh);
+      ret = submit_barrier_buffer(jl->j_commit_bh);
+      if (ret == -EOPNOTSUPP) {
+	  set_buffer_uptodate(jl->j_commit_bh);
+          disable_barrier(s);
+	  barrier = 0;
+      }
+  }
   for (i = 0 ;  i < (jl->j_len + 1) ; i++) {
     bn = SB_ONDISK_JOURNAL_1st_BLOCK(s) +
 	 (jl->j_start + i) % SB_ONDISK_JOURNAL_SIZE(s) ;
@@ -995,10 +1035,15 @@
   if (atomic_read(&(jl->j_commit_left)) != 1)
     BUG();
 
-  if (buffer_dirty(jl->j_commit_bh))
-    BUG();
-  mark_buffer_dirty(jl->j_commit_bh) ;
-  sync_dirty_buffer(jl->j_commit_bh) ;
+  if (!barrier) {
+      if (buffer_dirty(jl->j_commit_bh))
+	BUG();
+      mark_buffer_dirty(jl->j_commit_bh) ;
+      sync_dirty_buffer(jl->j_commit_bh) ;
+  } else
+      wait_on_buffer(jl->j_commit_bh);
+
+  check_barrier_completion(s, jl->j_commit_bh);
   if (!buffer_uptodate(jl->j_commit_bh)) {
     reiserfs_panic(s, "journal-615: buffer write failed\n") ;
   }
@@ -1098,8 +1143,23 @@
     jh->j_last_flush_trans_id = cpu_to_le32(trans_id) ;
     jh->j_first_unflushed_offset = cpu_to_le32(offset) ;
     jh->j_mount_id = cpu_to_le32(SB_JOURNAL(p_s_sb)->j_mount_id) ;
-    set_buffer_dirty(SB_JOURNAL(p_s_sb)->j_header_bh) ;
-    sync_dirty_buffer(SB_JOURNAL(p_s_sb)->j_header_bh) ;
+
+    if (reiserfs_barrier_flush(p_s_sb)) {
+	int ret;
+	lock_buffer(SB_JOURNAL(p_s_sb)->j_header_bh);
+	ret = submit_barrier_buffer(SB_JOURNAL(p_s_sb)->j_header_bh);
+	if (ret == -EOPNOTSUPP) {
+	    set_buffer_uptodate(SB_JOURNAL(p_s_sb)->j_header_bh);
+	    disable_barrier(p_s_sb);
+	    goto sync;
+	}
+	wait_on_buffer(SB_JOURNAL(p_s_sb)->j_header_bh);
+	check_barrier_completion(p_s_sb, SB_JOURNAL(p_s_sb)->j_header_bh);
+    } else {
+sync:
+	set_buffer_dirty(SB_JOURNAL(p_s_sb)->j_header_bh) ;
+	sync_dirty_buffer(SB_JOURNAL(p_s_sb)->j_header_bh) ;
+    }
     if (!buffer_uptodate(SB_JOURNAL(p_s_sb)->j_header_bh)) {
       reiserfs_warning (p_s_sb, "journal-837: IO error during journal replay");
       return -EIO ;
@@ -3184,11 +3244,16 @@
   REISERFS_I(inode)->i_trans_id = SB_JOURNAL(inode->i_sb)->j_trans_id ;
 }
 
-static void __commit_trans_jl(struct inode *inode, unsigned long id,
+/*
+ * returns -1 on error, 0 if no commits/barriers were done and 1
+ * if a transaction was actually committed and the barrier was done
+ */
+static int __commit_trans_jl(struct inode *inode, unsigned long id,
                                  struct reiserfs_journal_list *jl)
 {
     struct reiserfs_transaction_handle th ;
     struct super_block *sb = inode->i_sb ;
+    int ret = 0;
 
     /* is it from the current transaction, or from an unknown transaction? */
     if (id == SB_JOURNAL(sb)->j_trans_id) {
@@ -3210,6 +3275,7 @@
 	}
 
 	journal_end_sync(&th, sb, 1) ;
+	ret = 1;
 
     } else {
 	/* this gets tricky, we have to make sure the journal list in
@@ -3218,13 +3284,21 @@
 	 */
 flush_commit_only:
 	if (journal_list_still_alive(inode->i_sb, id)) {
+	    /*
+	     * we only set ret to 1 when we know for sure
+	     * the barrier hasn't been started yet on the commit
+	     * block.
+	     */
+	    if (atomic_read(&jl->j_commit_left) > 1)
+	        ret = 1;
 	    flush_commit_list(sb, jl, 1) ;
 	}
     }
     /* otherwise the list is gone, and long since committed */
+    return ret;
 }
 
-void reiserfs_commit_for_inode(struct inode *inode) {
+int reiserfs_commit_for_inode(struct inode *inode) {
     unsigned long id = REISERFS_I(inode)->i_trans_id;
     struct reiserfs_journal_list *jl = REISERFS_I(inode)->i_jl;
 
@@ -3237,7 +3311,7 @@
 	/* jl will be updated in __commit_trans_jl */
     }
 
-    __commit_trans_jl(inode, id, jl);
+   return __commit_trans_jl(inode, id, jl);
 }
 
 void reiserfs_restore_prepared_buffer(struct super_block *p_s_sb, 
diff -Nru a/fs/reiserfs/super.c b/fs/reiserfs/super.c
--- a/fs/reiserfs/super.c	2004-10-18 14:56:29 -07:00
+++ b/fs/reiserfs/super.c	2004-10-18 14:56:29 -07:00
@@ -444,7 +444,7 @@
 {
 	reiserfs_inode_cachep = kmem_cache_create("reiser_inode_cache",
 					     sizeof(struct reiserfs_inode_info),
-					     0, SLAB_HWCACHE_ALIGN|SLAB_RECLAIM_ACCOUNT,
+					     0, SLAB_RECLAIM_ACCOUNT,
 					     init_once, NULL);
 	if (reiserfs_inode_cachep == NULL)
 		return -ENOMEM;
@@ -549,6 +549,13 @@
     {NULL, 0}
 };
 
+/* possible values for -o barrier= */
+static const arg_desc_t barrier_mode[] = {
+    {"none", 1<<REISERFS_BARRIER_NONE, 1<<REISERFS_BARRIER_FLUSH},
+    {"flush", 1<<REISERFS_BARRIER_FLUSH, 1<<REISERFS_BARRIER_NONE},
+    {NULL, 0}
+};
+
 /* possible values for "-o block-allocator=" and bits which are to be set in
    s_mount_opt of reiserfs specific part of in-core super block */
 static const arg_desc_t balloc[] = {
@@ -711,6 +718,7 @@
 	{"replayonly",	.setmask = 1<<REPLAYONLY},
 	{"block-allocator", .arg_required = 'a', .values = balloc},
 	{"data",	.arg_required = 'd', .values = logging_mode},
+	{"barrier",	.arg_required = 'b', .values = barrier_mode},
 	{"resize",	.arg_required = 'r', .values = NULL},
 	{"jdev",	.arg_required = 'j', .values = NULL},
 	{"nolargeio",	.arg_required = 'w', .values = NULL},
@@ -810,6 +818,23 @@
     }
 }
 
+static void handle_barrier_mode(struct super_block *s, unsigned long bits) {
+    int flush = (1 << REISERFS_BARRIER_FLUSH);
+    int none = (1 << REISERFS_BARRIER_NONE);
+    int all_barrier = flush | none;
+
+    if (bits & all_barrier) {
+        REISERFS_SB(s)->s_mount_opt &= ~all_barrier;
+	if (bits & flush) {
+	    REISERFS_SB(s)->s_mount_opt |= flush;
+	    printk("reiserfs: enabling write barrier flush mode\n");
+	} else if (bits & none) {
+	    REISERFS_SB(s)->s_mount_opt |= none;
+	    printk("reiserfs: write barriers turned off\n");
+	}
+   }
+}
+
 static void handle_attrs( struct super_block *s )
 {
 	struct reiserfs_super_block * rs;
@@ -854,6 +879,8 @@
   safe_mask |= 1 << REISERFS_ATTRS;
   safe_mask |= 1 << REISERFS_XATTRS_USER;
   safe_mask |= 1 << REISERFS_POSIXACL;
+  safe_mask |= 1 << REISERFS_BARRIER_FLUSH;
+  safe_mask |= 1 << REISERFS_BARRIER_NONE;
 
   /* Update the bitmask, taking care to keep
    * the bits we're not allowed to change here */
@@ -900,6 +927,7 @@
     }
 
     handle_data_mode(s, mount_options);
+    handle_barrier_mode(s, mount_options);
     REISERFS_SB(s)->s_mount_state = sb_umount_state(rs) ;
     s->s_flags &= ~MS_RDONLY ; /* now it is safe to call journal_begin */
     journal_begin(&th, s, 10) ;
@@ -1412,6 +1440,9 @@
         reiserfs_info (s, "using ordered data mode\n");
     } else {
         reiserfs_info (s, "using writeback data mode\n");
+    }
+    if (reiserfs_barrier_flush(s)) {
+    	printk("reiserfs: using flush barriers\n");
     }
 
     // set_device_ro(s->s_dev, 1) ;
diff -Nru a/fs/reiserfs/xattr.c b/fs/reiserfs/xattr.c
--- a/fs/reiserfs/xattr.c	2004-10-18 14:57:04 -07:00
+++ b/fs/reiserfs/xattr.c	2004-10-18 14:57:04 -07:00
@@ -589,8 +589,14 @@
             break;
     }
 
-    inode->i_ctime = CURRENT_TIME;
-    mark_inode_dirty (inode);
+    /* We can't mark the inode dirty if it's not hashed. This is the case
+     * when we're inheriting the default ACL. If we dirty it, the inode
+     * gets marked dirty, but won't (ever) make it onto the dirty list until
+     * it's synced explicitly to clear I_DIRTY. This is bad. */
+    if (!hlist_unhashed(&inode->i_hash)) {
+        inode->i_ctime = CURRENT_TIME;
+        mark_inode_dirty (inode);
+    }
 
 out_filp:
     up (&xinode->i_sem);
@@ -761,6 +767,11 @@
     err = __reiserfs_xattr_del (dir, name, strlen (name));
     dput (dir);
 
+    if (!err) {
+        inode->i_ctime = CURRENT_TIME;
+        mark_inode_dirty (inode);
+    }
+
 out:
     return err;
 }
@@ -1240,8 +1251,10 @@
         name->hash == priv_root->d_name.hash &&
         !memcmp (name->name, priv_root->d_name.name, name->len)) {
             return -ENOENT;
-    }
-    return 0;
+    } else if (q1->len == name->len &&
+               !memcmp(q1->name, name->name, name->len))
+        return 0;
+    return 1;
 }
 
 static struct dentry_operations xattr_lookup_poison_ops = {
diff -Nru a/fs/reiserfs/xattr_acl.c b/fs/reiserfs/xattr_acl.c
--- a/fs/reiserfs/xattr_acl.c	2004-10-18 14:56:49 -07:00
+++ b/fs/reiserfs/xattr_acl.c	2004-10-18 14:56:49 -07:00
@@ -289,8 +289,14 @@
             error = reiserfs_xattr_set(inode, name, value, size, 0);
 	} else {
             error = reiserfs_xattr_del (inode, name);
-            if (error == -ENODATA)
+            if (error == -ENODATA) {
+                /* This may seem odd here, but it means that the ACL was set
+                 * with a value representable with mode bits. If there was
+                 * an ACL before, reiserfs_xattr_del already dirtied the inode.
+                 */
+                mark_inode_dirty (inode);
                 error = 0;
+            }
         }
 
 	if (value)
@@ -502,11 +508,11 @@
 }
 
 struct reiserfs_xattr_handler posix_acl_access_handler = {
-    prefix: XATTR_NAME_ACL_ACCESS,
-    get: posix_acl_access_get,
-    set: posix_acl_access_set,
-    del: posix_acl_access_del,
-    list: posix_acl_access_list,
+	.prefix = XATTR_NAME_ACL_ACCESS,
+	.get = posix_acl_access_get,
+	.set = posix_acl_access_set,
+	.del = posix_acl_access_del,
+	.list = posix_acl_access_list,
 };
 
 static int
@@ -555,9 +561,9 @@
 }
 
 struct reiserfs_xattr_handler posix_acl_default_handler = {
-    prefix: XATTR_NAME_ACL_DEFAULT,
-    get: posix_acl_default_get,
-    set: posix_acl_default_set,
-    del: posix_acl_default_del,
-    list: posix_acl_default_list,
+	.prefix = XATTR_NAME_ACL_DEFAULT,
+	.get = posix_acl_default_get,
+	.set = posix_acl_default_set,
+	.del = posix_acl_default_del,
+	.list = posix_acl_default_list,
 };
diff -Nru a/fs/reiserfs/xattr_security.c b/fs/reiserfs/xattr_security.c
--- a/fs/reiserfs/xattr_security.c	2004-10-18 14:56:28 -07:00
+++ b/fs/reiserfs/xattr_security.c	2004-10-18 14:56:28 -07:00
@@ -61,9 +61,9 @@
 
 
 struct reiserfs_xattr_handler security_handler = {
-    prefix: XATTR_SECURITY_PREFIX,
-    get: security_get,
-    set: security_set,
-    del: security_del,
-    list: security_list,
+	.prefix = XATTR_SECURITY_PREFIX,
+	.get = security_get,
+	.set = security_set,
+	.del = security_del,
+	.list = security_list,
 };
diff -Nru a/fs/reiserfs/xattr_trusted.c b/fs/reiserfs/xattr_trusted.c
--- a/fs/reiserfs/xattr_trusted.c	2004-10-18 14:56:17 -07:00
+++ b/fs/reiserfs/xattr_trusted.c	2004-10-18 14:56:17 -07:00
@@ -73,9 +73,9 @@
 
 
 struct reiserfs_xattr_handler trusted_handler = {
-    prefix: XATTR_TRUSTED_PREFIX,
-    get: trusted_get,
-    set: trusted_set,
-    del: trusted_del,
-    list: trusted_list,
+	.prefix = XATTR_TRUSTED_PREFIX,
+	.get = trusted_get,
+	.set = trusted_set,
+	.del = trusted_del,
+	.list = trusted_list,
 };
diff -Nru a/fs/reiserfs/xattr_user.c b/fs/reiserfs/xattr_user.c
--- a/fs/reiserfs/xattr_user.c	2004-10-18 14:56:49 -07:00
+++ b/fs/reiserfs/xattr_user.c	2004-10-18 14:56:49 -07:00
@@ -91,9 +91,9 @@
 }
 
 struct reiserfs_xattr_handler user_handler = {
-    prefix: XATTR_USER_PREFIX,
-    get: user_get,
-    set: user_set,
-    del: user_del,
-    list: user_list,
+	.prefix = XATTR_USER_PREFIX,
+	.get = user_get,
+	.set = user_set,
+	.del = user_del,
+	.list = user_list,
 };
diff -Nru a/fs/romfs/inode.c b/fs/romfs/inode.c
--- a/fs/romfs/inode.c	2004-10-18 14:56:48 -07:00
+++ b/fs/romfs/inode.c	2004-10-18 14:56:48 -07:00
@@ -95,15 +95,16 @@
 	return list_entry(inode, struct romfs_inode_info, vfs_inode);
 }
 
-static __s32
+static __u32
 romfs_checksum(void *data, int size)
 {
-	__s32 sum, *ptr;
+	__u32 sum;
+	__be32 *ptr;
 
 	sum = 0; ptr = data;
 	size>>=2;
 	while (size>0) {
-		sum += ntohl(*ptr++);
+		sum += be32_to_cpu(*ptr++);
 		size--;
 	}
 	return sum;
@@ -131,7 +132,7 @@
 	}
 
 	rsb = (struct romfs_super_block *)bh->b_data;
-	sz = ntohl(rsb->size);
+	sz = be32_to_cpu(rsb->size);
 	if (rsb->word0 != ROMSB_WORD0 || rsb->word1 != ROMSB_WORD1
 	   || sz < ROMFH_SIZE) {
 		if (!silent)
@@ -292,7 +293,7 @@
 		offset = i->i_ino & ROMFH_MASK;
 		if (romfs_copyfrom(i, &ri, offset, ROMFH_SIZE) <= 0)
 			goto out;
-		offset = ntohl(ri.spec) & ROMFH_MASK;
+		offset = be32_to_cpu(ri.spec) & ROMFH_MASK;
 	}
 
 	/* Not really failsafe, but we are read-only... */
@@ -316,9 +317,9 @@
 		romfs_copyfrom(i, fsname, offset+ROMFH_SIZE, j);
 
 		ino = offset;
-		nextfh = ntohl(ri.next);
+		nextfh = be32_to_cpu(ri.next);
 		if ((nextfh & ROMFH_TYPE) == ROMFH_HRD)
-			ino = ntohl(ri.spec);
+			ino = be32_to_cpu(ri.spec);
 		if (filldir(dirent, fsname, j, offset, ino,
 			    romfs_dtype_table[nextfh & ROMFH_TYPE]) < 0) {
 			goto out;
@@ -349,7 +350,7 @@
 		goto out;
 
 	maxoff = romfs_maxsize(dir->i_sb);
-	offset = ntohl(ri.spec) & ROMFH_MASK;
+	offset = be32_to_cpu(ri.spec) & ROMFH_MASK;
 
 	/* OK, now find the file whose name is in "dentry" in the
 	 * directory specified by "dir".  */
@@ -382,12 +383,12 @@
 			}
 		}
 		/* next entry */
-		offset = ntohl(ri.next) & ROMFH_MASK;
+		offset = be32_to_cpu(ri.next) & ROMFH_MASK;
 	}
 
 	/* Hard link handling */
-	if ((ntohl(ri.next) & ROMFH_TYPE) == ROMFH_HRD)
-		offset = ntohl(ri.spec) & ROMFH_MASK;
+	if ((be32_to_cpu(ri.next) & ROMFH_TYPE) == ROMFH_HRD)
+		offset = be32_to_cpu(ri.spec) & ROMFH_MASK;
 
 	if ((inode = iget(dir->i_sb, offset)))
 		goto outi;
@@ -495,15 +496,15 @@
 		}
 		/* XXX: do romfs_checksum here too (with name) */
 
-		nextfh = ntohl(ri.next);
+		nextfh = be32_to_cpu(ri.next);
 		if ((nextfh & ROMFH_TYPE) != ROMFH_HRD)
 			break;
 
-		ino = ntohl(ri.spec) & ROMFH_MASK;
+		ino = be32_to_cpu(ri.spec) & ROMFH_MASK;
 	}
 
 	i->i_nlink = 1;		/* Hard to decide.. */
-	i->i_size = ntohl(ri.size);
+	i->i_size = be32_to_cpu(ri.size);
 	i->i_mtime.tv_sec = i->i_atime.tv_sec = i->i_ctime.tv_sec = 0;
 	i->i_mtime.tv_nsec = i->i_atime.tv_nsec = i->i_ctime.tv_nsec = 0;
 	i->i_uid = i->i_gid = 0;
@@ -544,7 +545,7 @@
 			break;
 		default:
 			/* depending on MBZ for sock/fifos */
-			nextfh = ntohl(ri.spec);
+			nextfh = be32_to_cpu(ri.spec);
 			init_special_inode(i, ino,
 					MKDEV(nextfh>>16,nextfh&0xffff));
 	}
@@ -579,7 +580,7 @@
 {
 	romfs_inode_cachep = kmem_cache_create("romfs_inode_cache",
 					     sizeof(struct romfs_inode_info),
-					     0, SLAB_HWCACHE_ALIGN|SLAB_RECLAIM_ACCOUNT,
+					     0, SLAB_RECLAIM_ACCOUNT,
 					     init_once, NULL);
 	if (romfs_inode_cachep == NULL)
 		return -ENOMEM;
diff -Nru a/fs/select.c b/fs/select.c
--- a/fs/select.c	2004-10-18 14:55:54 -07:00
+++ b/fs/select.c	2004-10-18 14:55:54 -07:00
@@ -118,15 +118,11 @@
 	}
 }
 
+#define FDS_IN(fds, n)		(fds->in + n)
+#define FDS_OUT(fds, n)		(fds->out + n)
+#define FDS_EX(fds, n)		(fds->ex + n)
 
-#define __IN(fds, n)		(fds->in + n)
-#define __OUT(fds, n)		(fds->out + n)
-#define __EX(fds, n)		(fds->ex + n)
-#define __RES_IN(fds, n)	(fds->res_in + n)
-#define __RES_OUT(fds, n)	(fds->res_out + n)
-#define __RES_EX(fds, n)	(fds->res_ex + n)
-
-#define BITS(fds, n)		(*__IN(fds, n)|*__OUT(fds, n)|*__EX(fds, n))
+#define BITS(fds, n)	(*FDS_IN(fds, n)|*FDS_OUT(fds, n)|*FDS_EX(fds, n))
 
 static int max_select_fd(unsigned long n, fd_set_bits *fds)
 {
@@ -377,9 +373,10 @@
 		ret = 0;
 	}
 
-	set_fd_set(n, inp, fds.res_in);
-	set_fd_set(n, outp, fds.res_out);
-	set_fd_set(n, exp, fds.res_ex);
+	if (set_fd_set(n, inp, fds.res_in) ||
+	    set_fd_set(n, outp, fds.res_out) ||
+	    set_fd_set(n, exp, fds.res_ex))
+		ret = -EFAULT;
 
 out:
 	select_bits_free(bits, size);
diff -Nru a/fs/smbfs/inode.c b/fs/smbfs/inode.c
--- a/fs/smbfs/inode.c	2004-10-18 14:55:55 -07:00
+++ b/fs/smbfs/inode.c	2004-10-18 14:55:55 -07:00
@@ -80,7 +80,7 @@
 {
 	smb_inode_cachep = kmem_cache_create("smb_inode_cache",
 					     sizeof(struct smb_inode_info),
-					     0, SLAB_HWCACHE_ALIGN|SLAB_RECLAIM_ACCOUNT,
+					     0, SLAB_RECLAIM_ACCOUNT,
 					     init_once, NULL);
 	if (smb_inode_cachep == NULL)
 		return -ENOMEM;
diff -Nru a/fs/smbfs/proc.c b/fs/smbfs/proc.c
--- a/fs/smbfs/proc.c	2004-10-18 14:55:55 -07:00
+++ b/fs/smbfs/proc.c	2004-10-18 14:55:55 -07:00
@@ -2076,6 +2076,8 @@
 
 void smb_decode_unix_basic(struct smb_fattr *fattr, char *p)
 {
+	u64 size, disk_bytes;
+
 	/* FIXME: verify nls support. all is sent as utf8? */
 
 	fattr->f_unix = 1;
@@ -2093,8 +2095,19 @@
 	/* 84 L permissions */
 	/* 92 L link count */
 
-	fattr->f_size = LVAL(p, 0);
-	fattr->f_blocks = LVAL(p, 8);
+	size = LVAL(p, 0);
+	disk_bytes = LVAL(p, 8);
+
+	/*
+	 * Some samba versions round up on-disk byte usage
+	 * to 1MB boundaries, making it useless. When seeing
+	 * that, use the size instead.
+	 */
+	if (!(disk_bytes & 0xfffff))
+		disk_bytes = size+511;
+
+	fattr->f_size = size;
+	fattr->f_blocks = disk_bytes >> 9;
 	fattr->f_ctime = smb_ntutc2unixutc(LVAL(p, 16));
 	fattr->f_atime = smb_ntutc2unixutc(LVAL(p, 24));
 	fattr->f_mtime = smb_ntutc2unixutc(LVAL(p, 32));
diff -Nru a/fs/super.c b/fs/super.c
--- a/fs/super.c	2004-10-18 14:56:29 -07:00
+++ b/fs/super.c	2004-10-18 14:56:29 -07:00
@@ -116,6 +116,27 @@
 	return ret;
 }
 
+/*
+ * Drop a superblock's refcount.
+ * Returns non-zero if the superblock is about to be destroyed and
+ * at least is already removed from super_blocks list, so if we are
+ * making a loop through super blocks then we need to restart.
+ * The caller must hold sb_lock.
+ */
+int __put_super_and_need_restart(struct super_block *sb)
+{
+	/* check for race with generic_shutdown_super() */
+	if (list_empty(&sb->s_list)) {
+		/* super block is removed, need to restart... */
+		__put_super(sb);
+		return 1;
+	}
+	/* can't be the last, since s_list is still in use */
+	sb->s_count--;
+	BUG_ON(sb->s_count == 0);
+	return 0;
+}
+
 /**
  *	put_super	-	drop a temporary reference to superblock
  *	@s: superblock in question
@@ -229,7 +250,8 @@
 		unlock_super(sb);
 	}
 	spin_lock(&sb_lock);
-	list_del(&sb->s_list);
+	/* should be initialized for __put_super_and_need_restart() */
+	list_del_init(&sb->s_list);
 	list_del(&sb->s_instances);
 	spin_unlock(&sb_lock);
 	up_write(&sb->s_umount);
@@ -282,7 +304,7 @@
 	}
 	s->s_type = type;
 	strlcpy(s->s_id, type->name, sizeof(s->s_id));
-	list_add(&s->s_list, super_blocks.prev);
+	list_add_tail(&s->s_list, &super_blocks);
 	list_add(&s->s_instances, &type->fs_supers);
 	spin_unlock(&sb_lock);
 	get_filesystem(type);
diff -Nru a/fs/sysfs/symlink.c b/fs/sysfs/symlink.c
--- a/fs/sysfs/symlink.c	2004-10-18 14:56:29 -07:00
+++ b/fs/sysfs/symlink.c	2004-10-18 14:56:29 -07:00
@@ -5,12 +5,14 @@
 #include <linux/fs.h>
 #include <linux/module.h>
 #include <linux/kobject.h>
+#include <linux/namei.h>
 
 #include "sysfs.h"
 
 static struct inode_operations sysfs_symlink_inode_operations = {
-	.readlink = sysfs_readlink,
+	.readlink = generic_readlink,
 	.follow_link = sysfs_follow_link,
+	.put_link = sysfs_put_link,
 };
 
 static int init_symlink(struct inode * inode)
@@ -140,38 +142,21 @@
 
 }
 
-int sysfs_readlink(struct dentry *dentry, char __user *buffer, int buflen)
+int sysfs_follow_link(struct dentry *dentry, struct nameidata *nd)
 {
-	int error = 0;
+	int error = -ENOMEM;
 	unsigned long page = get_zeroed_page(GFP_KERNEL);
-
-	if (!page)
-		return -ENOMEM;
-
-	error = sysfs_getlink(dentry, (char *) page);
-	if (!error)
-	        error = vfs_readlink(dentry, buffer, buflen, (char *) page);
-
-	free_page(page);
-
-	return error;
+	if (page)
+		error = sysfs_getlink(dentry, (char *) page); 
+	nd_set_link(nd, error ? ERR_PTR(error) : (char *)page);
+	return 0;
 }
 
-int sysfs_follow_link(struct dentry *dentry, struct nameidata *nd)
+void sysfs_put_link(struct dentry *dentry, struct nameidata *nd)
 {
-	int error = 0;
-	unsigned long page = get_zeroed_page(GFP_KERNEL);
-
-	if (!page)
-		return -ENOMEM;
-
-	error = sysfs_getlink(dentry, (char *) page); 
-	if (!error)
-	        error = vfs_follow_link(nd, (char *) page);
-
-	free_page(page);
-
-	return error;
+	char *page = nd_get_link(nd);
+	if (!IS_ERR(page))
+		free_page((unsigned long)page);
 }
 
 EXPORT_SYMBOL(sysfs_create_link);
diff -Nru a/fs/sysfs/sysfs.h b/fs/sysfs/sysfs.h
--- a/fs/sysfs/sysfs.h	2004-10-18 14:56:49 -07:00
+++ b/fs/sysfs/sysfs.h	2004-10-18 14:56:49 -07:00
@@ -12,8 +12,8 @@
 extern int sysfs_create_subdir(struct kobject *, const char *, struct dentry **);
 extern void sysfs_remove_subdir(struct dentry *);
 
-extern int sysfs_readlink(struct dentry *, char __user *, int );
 extern int sysfs_follow_link(struct dentry *, struct nameidata *);
+extern void sysfs_put_link(struct dentry *, struct nameidata *);
 extern struct rw_semaphore sysfs_rename_sem;
 
 static inline struct kobject *sysfs_get_kobject(struct dentry *dentry)
diff -Nru a/fs/sysv/balloc.c b/fs/sysv/balloc.c
--- a/fs/sysv/balloc.c	2004-10-18 14:56:29 -07:00
+++ b/fs/sysv/balloc.c	2004-10-18 14:56:29 -07:00
@@ -27,23 +27,23 @@
    sb->sv_sbd2->s_tfree = *sb->sv_free_blocks
    but we nevertheless keep it up to date. */
 
-static inline u32 *get_chunk(struct super_block *sb, struct buffer_head *bh)
+static inline sysv_zone_t *get_chunk(struct super_block *sb, struct buffer_head *bh)
 {
 	char *bh_data = bh->b_data;
 
 	if (SYSV_SB(sb)->s_type == FSTYPE_SYSV4)
-		return (u32*)(bh_data+4);
+		return (sysv_zone_t*)(bh_data+4);
 	else
-		return (u32*)(bh_data+2);
+		return (sysv_zone_t*)(bh_data+2);
 }
 
 /* NOTE NOTE NOTE: nr is a block number _as_ _stored_ _on_ _disk_ */
 
-void sysv_free_block(struct super_block * sb, u32 nr)
+void sysv_free_block(struct super_block * sb, sysv_zone_t nr)
 {
 	struct sysv_sb_info * sbi = SYSV_SB(sb);
 	struct buffer_head * bh;
-	u32 *blocks = sbi->s_bcache;
+	sysv_zone_t *blocks = sbi->s_bcache;
 	unsigned count;
 	unsigned block = fs32_to_cpu(sbi, nr);
 
@@ -81,7 +81,7 @@
 			return;
 		}
 		memset(bh->b_data, 0, sb->s_blocksize);
-		*(u16*)bh->b_data = cpu_to_fs16(sbi, count);
+		*(__fs16*)bh->b_data = cpu_to_fs16(sbi, count);
 		memcpy(get_chunk(sb,bh), blocks, count * sizeof(sysv_zone_t));
 		mark_buffer_dirty(bh);
 		set_buffer_uptodate(bh);
@@ -96,11 +96,11 @@
 	unlock_super(sb);
 }
 
-u32 sysv_new_block(struct super_block * sb)
+sysv_zone_t sysv_new_block(struct super_block * sb)
 {
 	struct sysv_sb_info *sbi = SYSV_SB(sb);
 	unsigned int block;
-	u32 nr;
+	sysv_zone_t nr;
 	struct buffer_head * bh;
 	unsigned count;
 
@@ -133,7 +133,7 @@
 			*sbi->s_bcache_count = cpu_to_fs16(sbi, 1);
 			goto Enospc;
 		}
-		count = fs16_to_cpu(sbi, *(u16*)bh->b_data);
+		count = fs16_to_cpu(sbi, *(__fs16*)bh->b_data);
 		if (count > sbi->s_flc_size) {
 			printk("sysv_new_block: free-list block with >flc_size entries\n");
 			brelse(bh);
@@ -161,7 +161,7 @@
 	int sb_count;
 	int count;
 	struct buffer_head * bh = NULL;
-	u32 *blocks;
+	sysv_zone_t *blocks;
 	unsigned block;
 	int n;
 
@@ -184,15 +184,16 @@
 	n = fs16_to_cpu(sbi, *sbi->s_bcache_count);
 	blocks = sbi->s_bcache;
 	while (1) {
+		sysv_zone_t zone;
 		if (n > sbi->s_flc_size)
 			goto E2big;
-		block = 0;
-		while (n && (block = blocks[--n]) != 0)
+		zone = 0;
+		while (n && (zone = blocks[--n]) != 0)
 			count++;
-		if (block == 0)
+		if (zone == 0)
 			break;
 
-		block = fs32_to_cpu(sbi, block);
+		block = fs32_to_cpu(sbi, zone);
 		if (bh)
 			brelse(bh);
 
@@ -202,7 +203,7 @@
 		bh = sb_bread(sb, block);
 		if (!bh)
 			goto Eio;
-		n = fs16_to_cpu(sbi, *(u16*)bh->b_data);
+		n = fs16_to_cpu(sbi, *(__fs16*)bh->b_data);
 		blocks = get_chunk(sb, bh);
 	}
 	if (bh)
diff -Nru a/fs/sysv/ialloc.c b/fs/sysv/ialloc.c
--- a/fs/sysv/ialloc.c	2004-10-18 14:56:13 -07:00
+++ b/fs/sysv/ialloc.c	2004-10-18 14:56:13 -07:00
@@ -137,7 +137,7 @@
 	struct super_block *sb = dir->i_sb;
 	struct sysv_sb_info *sbi = SYSV_SB(sb);
 	struct inode *inode;
-	u16 ino;
+	sysv_ino_t ino;
 	unsigned count;
 
 	inode = new_inode(sb);
diff -Nru a/fs/sysv/inode.c b/fs/sysv/inode.c
--- a/fs/sysv/inode.c	2004-10-18 14:55:54 -07:00
+++ b/fs/sysv/inode.c	2004-10-18 14:55:54 -07:00
@@ -260,13 +260,14 @@
 	return bh;
 }
 
-void sysv_write_inode(struct inode * inode, int wait)
+int sysv_write_inode(struct inode * inode, int wait)
 {
 	struct buffer_head *bh;
 	lock_kernel();
 	bh = sysv_update_inode(inode);
 	brelse(bh);
 	unlock_kernel();
+	return 0;
 }
 
 int sysv_sync_inode(struct inode * inode)
@@ -340,7 +341,7 @@
 {
 	sysv_inode_cachep = kmem_cache_create("sysv_inode_cache",
 			sizeof(struct sysv_inode_info), 0,
-			SLAB_HWCACHE_ALIGN|SLAB_RECLAIM_ACCOUNT, 
+			SLAB_RECLAIM_ACCOUNT,
 			init_once, NULL);
 	if (!sysv_inode_cachep)
 		return -ENOMEM;
diff -Nru a/fs/sysv/itree.c b/fs/sysv/itree.c
--- a/fs/sysv/itree.c	2004-10-18 14:56:27 -07:00
+++ b/fs/sysv/itree.c	2004-10-18 14:56:27 -07:00
@@ -50,20 +50,20 @@
 	return n;
 }
 
-static inline int block_to_cpu(struct sysv_sb_info *sbi, u32 nr)
+static inline int block_to_cpu(struct sysv_sb_info *sbi, sysv_zone_t nr)
 {
 	return sbi->s_block_base + fs32_to_cpu(sbi, nr);
 }
 
 typedef struct {
-	u32     *p;
-	u32     key;
+	sysv_zone_t     *p;
+	sysv_zone_t     key;
 	struct buffer_head *bh;
 } Indirect;
 
 static rwlock_t pointers_lock = RW_LOCK_UNLOCKED;
 
-static inline void add_chain(Indirect *p, struct buffer_head *bh, u32 *v)
+static inline void add_chain(Indirect *p, struct buffer_head *bh, sysv_zone_t *v)
 {
 	p->key = *(p->p = v);
 	p->bh = bh;
@@ -76,9 +76,9 @@
 	return (from > to);
 }
 
-static inline u32 *block_end(struct buffer_head *bh)
+static inline sysv_zone_t *block_end(struct buffer_head *bh)
 {
-	return (u32*)((char*)bh->b_data + bh->b_size);
+	return (sysv_zone_t*)((char*)bh->b_data + bh->b_size);
 }
 
 /*
@@ -105,7 +105,7 @@
 			goto failure;
 		if (!verify_chain(chain, p))
 			goto changed;
-		add_chain(++p, bh, (u32*)bh->b_data + *++offsets);
+		add_chain(++p, bh, (sysv_zone_t*)bh->b_data + *++offsets);
 		if (!p->key)
 			goto no_block;
 	}
@@ -147,7 +147,7 @@
 		lock_buffer(bh);
 		memset(bh->b_data, 0, blocksize);
 		branch[n].bh = bh;
-		branch[n].p = (u32*) bh->b_data + offsets[n];
+		branch[n].p = (sysv_zone_t*) bh->b_data + offsets[n];
 		*branch[n].p = branch[n].key;
 		set_buffer_uptodate(bh);
 		unlock_buffer(bh);
@@ -265,7 +265,7 @@
 	goto reread;
 }
 
-static inline int all_zeroes(u32 *p, u32 *q)
+static inline int all_zeroes(sysv_zone_t *p, sysv_zone_t *q)
 {
 	while (p < q)
 		if (*p++)
@@ -277,7 +277,7 @@
 				int depth,
 				int offsets[],
 				Indirect chain[],
-				u32 *top)
+				sysv_zone_t *top)
 {
 	Indirect *partial, *p;
 	int k, err;
@@ -298,7 +298,7 @@
 		write_unlock(&pointers_lock);
 		goto no_top;
 	}
-	for (p=partial; p>chain && all_zeroes((u32*)p->bh->b_data,p->p); p--)
+	for (p=partial; p>chain && all_zeroes((sysv_zone_t*)p->bh->b_data,p->p); p--)
 		;
 	/*
 	 * OK, we've found the last block that must survive. The rest of our
@@ -322,10 +322,10 @@
 	return partial;
 }
 
-static inline void free_data(struct inode *inode, u32 *p, u32 *q)
+static inline void free_data(struct inode *inode, sysv_zone_t *p, sysv_zone_t *q)
 {
 	for ( ; p < q ; p++) {
-		u32 nr = *p;
+		sysv_zone_t nr = *p;
 		if (nr) {
 			*p = 0;
 			sysv_free_block(inode->i_sb, nr);
@@ -334,7 +334,7 @@
 	}
 }
 
-static void free_branches(struct inode *inode, u32 *p, u32 *q, int depth)
+static void free_branches(struct inode *inode, sysv_zone_t *p, sysv_zone_t *q, int depth)
 {
 	struct buffer_head * bh;
 	struct super_block *sb = inode->i_sb;
@@ -342,7 +342,7 @@
 	if (depth--) {
 		for ( ; p < q ; p++) {
 			int block;
-			u32 nr = *p;
+			sysv_zone_t nr = *p;
 			if (!nr)
 				continue;
 			*p = 0;
@@ -350,7 +350,7 @@
 			bh = sb_bread(sb, block);
 			if (!bh)
 				continue;
-			free_branches(inode, (u32*)bh->b_data,
+			free_branches(inode, (sysv_zone_t*)bh->b_data,
 					block_end(bh), depth);
 			bforget(bh);
 			sysv_free_block(sb, nr);
@@ -362,11 +362,11 @@
 
 void sysv_truncate (struct inode * inode)
 {
-	u32 *i_data = SYSV_I(inode)->i_data;
+	sysv_zone_t *i_data = SYSV_I(inode)->i_data;
 	int offsets[DEPTH];
 	Indirect chain[DEPTH];
 	Indirect *partial;
-	int nr = 0;
+	sysv_zone_t nr = 0;
 	int n;
 	long iblock;
 	unsigned blocksize;
diff -Nru a/fs/sysv/super.c b/fs/sysv/super.c
--- a/fs/sysv/super.c	2004-10-18 14:57:19 -07:00
+++ b/fs/sysv/super.c	2004-10-18 14:57:19 -07:00
@@ -178,16 +178,22 @@
 static int detect_xenix(struct sysv_sb_info *sbi, struct buffer_head *bh)
 {
 	struct xenix_super_block *sbd = (struct xenix_super_block *)bh->b_data;
-	if (sbd->s_magic == cpu_to_le32(0x2b5544))
+	if (*(__le32 *)&sbd->s_magic == cpu_to_le32(0x2b5544))
 		sbi->s_bytesex = BYTESEX_LE;
-	else if (sbd->s_magic == cpu_to_be32(0x2b5544))
+	else if (*(__be32 *)&sbd->s_magic == cpu_to_be32(0x2b5544))
 		sbi->s_bytesex = BYTESEX_BE;
 	else
 		return 0;
-	if (sbd->s_type > 2 || sbd->s_type < 1)
+	switch (fs32_to_cpu(sbi, sbd->s_type)) {
+	case 1:
+		sbi->s_type = FSTYPE_XENIX;
+		return 1;
+	case 2:
+		sbi->s_type = FSTYPE_XENIX;
+		return 2;
+	default:
 		return 0;
-	sbi->s_type = FSTYPE_XENIX;
-	return sbd->s_type;
+	}
 }
 
 static int detect_sysv(struct sysv_sb_info *sbi, struct buffer_head *bh)
@@ -195,14 +201,17 @@
 	struct super_block *sb = sbi->s_sb;
 	/* All relevant fields are at the same offsets in R2 and R4 */
 	struct sysv4_super_block * sbd;
+	u32 type;
 
 	sbd = (struct sysv4_super_block *) (bh->b_data + BLOCK_SIZE/2);
-	if (sbd->s_magic == cpu_to_le32(0xfd187e20))
+	if (*(__le32 *)&sbd->s_magic == cpu_to_le32(0xfd187e20))
 		sbi->s_bytesex = BYTESEX_LE;
-	else if (sbd->s_magic == cpu_to_be32(0xfd187e20))
+	else if (*(__be32 *)&sbd->s_magic == cpu_to_be32(0xfd187e20))
 		sbi->s_bytesex = BYTESEX_BE;
 	else
 		return 0;
+
+	type = fs32_to_cpu(sbi, sbd->s_type);
  
  	if (fs16_to_cpu(sbi, sbd->s_nfree) == 0xffff) {
  		sbi->s_type = FSTYPE_AFS;
@@ -212,18 +221,17 @@
  				"forcing read-only mode.\n", 
  				sb->s_id);
  		}
- 		return sbd->s_type;
+ 		return type;
  	}
  
 	if (fs32_to_cpu(sbi, sbd->s_time) < JAN_1_1980) {
 		/* this is likely to happen on SystemV2 FS */
-		if (sbd->s_type > 3 || sbd->s_type < 1)
+		if (type > 3 || type < 1)
 			return 0;
 		sbi->s_type = FSTYPE_SYSV2;
-		return sbd->s_type;
+		return type;
 	}
-	if ((sbd->s_type > 3 || sbd->s_type < 1) &&
-	    (sbd->s_type > 0x30 || sbd->s_type < 0x10))
+	if ((type > 3 || type < 1) && (type > 0x30 || type < 0x10))
 		return 0;
 
 	/* On Interactive Unix (ISC) Version 4.0/3.x s_type field = 0x10,
@@ -231,14 +239,14 @@
 	   filename limit is gone. Due to lack of information about this
            feature read-only mode seems to be a reasonable approach... -KGB */
 
-	if (sbd->s_type >= 0x10) {
+	if (type >= 0x10) {
 		printk("SysV FS: can't handle long file names on %s, "
 		       "forcing read-only mode.\n", sb->s_id);
 		sbi->s_forced_ro = 1;
 	}
 
 	sbi->s_type = FSTYPE_SYSV4;
-	return sbd->s_type >= 0x10 ? (sbd->s_type >> 4) : sbd->s_type;
+	return type >= 0x10 ? type >> 4 : type;
 }
 
 static int detect_coherent(struct sysv_sb_info *sbi, struct buffer_head *bh)
diff -Nru a/fs/sysv/sysv.h b/fs/sysv/sysv.h
--- a/fs/sysv/sysv.h	2004-10-18 14:56:32 -07:00
+++ b/fs/sysv/sysv.h	2004-10-18 14:56:32 -07:00
@@ -2,6 +2,10 @@
 #define _SYSV_H
 
 #include <linux/buffer_head.h>
+
+typedef __u16 __bitwise __fs16;
+typedef __u32 __bitwise __fs32;
+
 #include <linux/sysv_fs.h>
 
 /*
@@ -38,14 +42,14 @@
 	   different superblock layout. */
 	char *         s_sbd1;		/* entire superblock data, for part 1 */
 	char *         s_sbd2;		/* entire superblock data, for part 2 */
-	u16            *s_sb_fic_count;	/* pointer to s_sbd->s_ninode */
-        u16            *s_sb_fic_inodes; /* pointer to s_sbd->s_inode */
-	u16            *s_sb_total_free_inodes; /* pointer to s_sbd->s_tinode */
-	u16            *s_bcache_count;	/* pointer to s_sbd->s_nfree */
-	u32	       *s_bcache;	/* pointer to s_sbd->s_free */
-	u32            *s_free_blocks;	/* pointer to s_sbd->s_tfree */
-	u32            *s_sb_time;	/* pointer to s_sbd->s_time */
-	u32            *s_sb_state;	/* pointer to s_sbd->s_state, only FSTYPE_SYSV */
+	__fs16         *s_sb_fic_count;	/* pointer to s_sbd->s_ninode */
+        sysv_ino_t     *s_sb_fic_inodes; /* pointer to s_sbd->s_inode */
+	__fs16         *s_sb_total_free_inodes; /* pointer to s_sbd->s_tinode */
+	__fs16         *s_bcache_count;	/* pointer to s_sbd->s_nfree */
+	sysv_zone_t    *s_bcache;	/* pointer to s_sbd->s_free */
+	__fs32         *s_free_blocks;	/* pointer to s_sbd->s_tfree */
+	__fs32         *s_sb_time;	/* pointer to s_sbd->s_time */
+	__fs32         *s_sb_state;	/* pointer to s_sbd->s_state, only FSTYPE_SYSV */
 	/* We keep those superblock entities that don't change here;
 	   this saves us an indirection and perhaps a conversion. */
 	u32            s_firstinodezone; /* index of first inode zone */
@@ -61,7 +65,7 @@
  * SystemV/V7/Coherent FS inode data in memory
  */
 struct sysv_inode_info {
-	u32		i_data[13];
+	__fs32		i_data[13];
 	u32		i_dir_start_lookup;
 	struct inode	vfs_inode;
 };
@@ -126,15 +130,15 @@
 extern unsigned long sysv_count_free_inodes(struct super_block *);
 
 /* balloc.c */
-extern u32 sysv_new_block(struct super_block *);
-extern void sysv_free_block(struct super_block *, u32);
+extern sysv_zone_t sysv_new_block(struct super_block *);
+extern void sysv_free_block(struct super_block *, sysv_zone_t);
 extern unsigned long sysv_count_free_blocks(struct super_block *);
 
 /* itree.c */
 extern void sysv_truncate(struct inode *);
 
 /* inode.c */
-extern void sysv_write_inode(struct inode *, int);
+extern int sysv_write_inode(struct inode *, int);
 extern int sysv_sync_inode(struct inode *);
 extern int sysv_sync_file(struct file *, struct dentry *, int);
 extern void sysv_set_inode(struct inode *, dev_t);
@@ -181,58 +185,60 @@
 #endif
 }
 
-static inline u32 fs32_to_cpu(struct sysv_sb_info *sbi, u32 n)
+static inline __u32 fs32_to_cpu(struct sysv_sb_info *sbi, __fs32 n)
 {
 	if (sbi->s_bytesex == BYTESEX_PDP)
-		return PDP_swab(n);
+		return PDP_swab((__force __u32)n);
 	else if (sbi->s_bytesex == BYTESEX_LE)
-		return le32_to_cpu(n);
+		return le32_to_cpu((__force __le32)n);
 	else
-		return be32_to_cpu(n);
+		return be32_to_cpu((__force __be32)n);
 }
 
-static inline u32 cpu_to_fs32(struct sysv_sb_info *sbi, u32 n)
+static inline __fs32 cpu_to_fs32(struct sysv_sb_info *sbi, __u32 n)
 {
 	if (sbi->s_bytesex == BYTESEX_PDP)
-		return PDP_swab(n);
+		return (__force __fs32)PDP_swab(n);
 	else if (sbi->s_bytesex == BYTESEX_LE)
-		return cpu_to_le32(n);
+		return (__force __fs32)cpu_to_le32(n);
 	else
-		return cpu_to_be32(n);
+		return (__force __fs32)cpu_to_be32(n);
 }
 
-static inline u32 fs32_add(struct sysv_sb_info *sbi, u32 *n, int d)
+static inline __fs32 fs32_add(struct sysv_sb_info *sbi, __fs32 *n, int d)
 {
 	if (sbi->s_bytesex == BYTESEX_PDP)
-		return *n = PDP_swab(PDP_swab(*n)+d);
+		*(__u32*)n = PDP_swab(PDP_swab(*(__u32*)n)+d);
 	else if (sbi->s_bytesex == BYTESEX_LE)
-		return *n = cpu_to_le32(le32_to_cpu(*n)+d);
+		*(__le32*)n = cpu_to_le32(le32_to_cpu(*(__le32*)n)+d);
 	else
-		return *n = cpu_to_be32(be32_to_cpu(*n)+d);
+		*(__be32*)n = cpu_to_be32(be32_to_cpu(*(__be32*)n)+d);
+	return *n;
 }
 
-static inline u16 fs16_to_cpu(struct sysv_sb_info *sbi, u16 n)
+static inline __u16 fs16_to_cpu(struct sysv_sb_info *sbi, __fs16 n)
 {
 	if (sbi->s_bytesex != BYTESEX_BE)
-		return le16_to_cpu(n);
+		return le16_to_cpu((__force __le16)n);
 	else
-		return be16_to_cpu(n);
+		return be16_to_cpu((__force __be16)n);
 }
 
-static inline u16 cpu_to_fs16(struct sysv_sb_info *sbi, u16 n)
+static inline __fs16 cpu_to_fs16(struct sysv_sb_info *sbi, __u16 n)
 {
 	if (sbi->s_bytesex != BYTESEX_BE)
-		return cpu_to_le16(n);
+		return (__force __fs16)cpu_to_le16(n);
 	else
-		return cpu_to_be16(n);
+		return (__force __fs16)cpu_to_be16(n);
 }
 
-static inline u16 fs16_add(struct sysv_sb_info *sbi, u16 *n, int d)
+static inline __fs16 fs16_add(struct sysv_sb_info *sbi, __fs16 *n, int d)
 {
 	if (sbi->s_bytesex != BYTESEX_BE)
-		return *n = cpu_to_le16(le16_to_cpu(*n)+d);
+		*(__le16*)n = cpu_to_le16(le16_to_cpu(*(__le16 *)n)+d);
 	else
-		return *n = cpu_to_be16(be16_to_cpu(*n)+d);
+		*(__be16*)n = cpu_to_be16(be16_to_cpu(*(__be16 *)n)+d);
+	return *n;
 }
 
 #endif /* _SYSV_H */
diff -Nru a/fs/udf/balloc.c b/fs/udf/balloc.c
--- a/fs/udf/balloc.c	2004-10-18 14:56:27 -07:00
+++ b/fs/udf/balloc.c	2004-10-18 14:56:27 -07:00
@@ -44,13 +44,13 @@
 #define xleNUM_to_cpup(x,y) (le ## x ## _to_cpup(y))
 #define uintBPL_t uint(BITS_PER_LONG)
 #define uint(x) xuint(x)
-#define xuint(x) uint ## x ## _t
+#define xuint(x) __le ## x
 
 extern inline int find_next_one_bit (void * addr, int size, int offset)
 {
 	uintBPL_t * p = ((uintBPL_t *) addr) + (offset / BITS_PER_LONG);
-	uintBPL_t result = offset & ~(BITS_PER_LONG-1);
-	uintBPL_t tmp;
+	int result = offset & ~(BITS_PER_LONG-1);
+	unsigned long tmp;
 
 	if (offset >= size)
 		return size;
@@ -91,7 +91,7 @@
 {
 	struct buffer_head *bh = NULL;
 	int retval = 0;
-	lb_addr loc;
+	kernel_lb_addr loc;
 
 	loc.logicalBlockNum = bitmap->s_extPosition;
 	loc.partitionReferenceNum = UDF_SB_PARTITION(sb);
@@ -145,7 +145,8 @@
 
 static void udf_bitmap_free_blocks(struct super_block * sb,
 	struct inode * inode,
-	struct udf_bitmap *bitmap, lb_addr bloc, uint32_t offset, uint32_t count)
+	struct udf_bitmap *bitmap,
+	kernel_lb_addr bloc, uint32_t offset, uint32_t count)
 {
 	struct buffer_head * bh = NULL;
 	unsigned long block;
@@ -424,11 +425,12 @@
 
 static void udf_table_free_blocks(struct super_block * sb,
 	struct inode * inode,
-	struct inode * table, lb_addr bloc, uint32_t offset, uint32_t count)
+	struct inode * table,
+	kernel_lb_addr bloc, uint32_t offset, uint32_t count)
 {
 	uint32_t start, end;
 	uint32_t nextoffset, oextoffset, elen;
-	lb_addr nbloc, obloc, eloc;
+	kernel_lb_addr nbloc, obloc, eloc;
 	struct buffer_head *obh, *nbh;
 	int8_t etype;
 	int i;
@@ -678,7 +680,7 @@
 {
 	int alloc_count = 0;
 	uint32_t extoffset, elen, adsize;
-	lb_addr bloc, eloc;
+	kernel_lb_addr bloc, eloc;
 	struct buffer_head *bh;
 	int8_t etype = -1;
 
@@ -748,7 +750,7 @@
 	uint32_t spread = 0xFFFFFFFF, nspread = 0xFFFFFFFF;
 	uint32_t newblock = 0, adsize;
 	uint32_t extoffset, goal_extoffset, elen, goal_elen = 0;
-	lb_addr bloc, goal_bloc, eloc, goal_eloc;
+	kernel_lb_addr bloc, goal_bloc, eloc, goal_eloc;
 	struct buffer_head *bh, *goal_bh;
 	int8_t etype;
 
@@ -854,7 +856,7 @@
 
 inline void udf_free_blocks(struct super_block * sb,
 	struct inode * inode,
-	lb_addr bloc, uint32_t offset, uint32_t count)
+	kernel_lb_addr bloc, uint32_t offset, uint32_t count)
 {
 	uint16_t partition = bloc.partitionReferenceNum;
 
diff -Nru a/fs/udf/dir.c b/fs/udf/dir.c
--- a/fs/udf/dir.c	2004-10-18 14:56:27 -07:00
+++ b/fs/udf/dir.c	2004-10-18 14:56:27 -07:00
@@ -117,7 +117,7 @@
 	uint8_t lfi;
 	loff_t size = (udf_ext0_offset(dir) + dir->i_size) >> 2;
 	struct buffer_head * bh = NULL, * tmp, * bha[16];
-	lb_addr bloc, eloc;
+	kernel_lb_addr bloc, eloc;
 	uint32_t extoffset, elen, offset;
 	int i, num;
 	unsigned int dt_type;
@@ -237,7 +237,7 @@
 		}
 		else
 		{
-			lb_addr tloc = lelb_to_cpu(cfi.icb.extLocation);
+			kernel_lb_addr tloc = lelb_to_cpu(cfi.icb.extLocation);
 
 			iblock = udf_get_lb_pblock(dir->i_sb, tloc, 0);
 			flen = udf_get_filename(dir->i_sb, nameptr, fname, lfi);
diff -Nru a/fs/udf/directory.c b/fs/udf/directory.c
--- a/fs/udf/directory.c	2004-10-18 14:56:49 -07:00
+++ b/fs/udf/directory.c	2004-10-18 14:56:49 -07:00
@@ -23,8 +23,11 @@
 #include <linux/string.h>
 #include <linux/buffer_head.h>
 
-uint8_t * udf_filead_read(struct inode *dir, uint8_t *tmpad, uint8_t ad_size,
-	lb_addr fe_loc, int *pos, int *offset, struct buffer_head **bh, int *error)
+#if 0
+static uint8_t *
+udf_filead_read(struct inode *dir, uint8_t *tmpad, uint8_t ad_size,
+		kernel_lb_addr fe_loc, int *pos, int *offset,
+		struct buffer_head **bh, int *error)
 {
 	int loffset = *offset;
 	int block;
@@ -71,13 +74,14 @@
 	}
 	return ad;
 }
+#endif
 
 struct fileIdentDesc *
 udf_fileident_read(struct inode *dir, loff_t *nf_pos,
 	struct udf_fileident_bh *fibh,
 	struct fileIdentDesc *cfi,
-	lb_addr *bloc, uint32_t *extoffset, 
-	lb_addr *eloc, uint32_t *elen,
+	kernel_lb_addr *bloc, uint32_t *extoffset, 
+	kernel_lb_addr *eloc, uint32_t *elen,
 	uint32_t *offset, struct buffer_head **bh)
 {
 	struct fileIdentDesc *fi;
@@ -259,7 +263,8 @@
 	return fi;
 }
 
-extent_ad *
+#if 0
+static extent_ad *
 udf_get_fileextent(void * buffer, int bufsize, int * offset)
 {
 	extent_ad * ext;
@@ -293,6 +298,7 @@
 	*offset = *offset + sizeof(extent_ad);
 	return ext;
 }
+#endif
 
 short_ad *
 udf_get_fileshortad(uint8_t *ptr, int maxoffset, int *offset, int inc)
diff -Nru a/fs/udf/ecma_167.h b/fs/udf/ecma_167.h
--- a/fs/udf/ecma_167.h	2004-10-18 14:56:29 -07:00
+++ b/fs/udf/ecma_167.h	2004-10-18 14:56:29 -07:00
@@ -60,6 +60,20 @@
 /* Timestamp (ECMA 167r3 1/7.3) */
 typedef struct
 {
+	__le16		typeAndTimezone;
+	__le16		year;
+	uint8_t		month;
+	uint8_t		day;
+	uint8_t		hour;
+	uint8_t		minute;
+	uint8_t		second;
+	uint8_t		centiseconds;
+	uint8_t		hundredsOfMicroseconds;
+	uint8_t		microseconds;
+} __attribute__ ((packed)) timestamp;
+
+typedef struct
+{
 	uint16_t	typeAndTimezone;
 	int16_t		year;
 	uint8_t		month;
@@ -70,7 +84,7 @@
 	uint8_t		centiseconds;
 	uint8_t		hundredsOfMicroseconds;
 	uint8_t		microseconds;
-} __attribute__ ((packed)) timestamp;
+} __attribute__ ((packed)) kernel_timestamp;
 
 /* Type and Time Zone (ECMA 167r3 1/7.3.1) */
 #define TIMESTAMP_TYPE_MASK		0xF000
@@ -139,12 +153,12 @@
 	uint8_t		reserved1;
 	regid		archType;
 	regid		bootIdent;
-	uint32_t	bootExtLocation;
-	uint32_t	bootExtLength;
-	uint64_t	loadAddress;
-	uint64_t	startAddress;
+	__le32		bootExtLocation;
+	__le32		bootExtLength;
+	__le64		loadAddress;
+	__le64		startAddress;
 	timestamp	descCreationDateAndTime;
-	uint16_t	flags;
+	__le16		flags;
 	uint8_t		reserved2[32];
 	uint8_t		bootUse[1906];
 } __attribute__ ((packed));
@@ -155,21 +169,27 @@
 /* Extent Descriptor (ECMA 167r3 3/7.1) */
 typedef struct
 {
+	__le32		extLength;
+	__le32		extLocation;
+} __attribute__ ((packed)) extent_ad;
+
+typedef struct
+{
 	uint32_t	extLength;
 	uint32_t	extLocation;
-} __attribute__ ((packed)) extent_ad;
+} kernel_extent_ad;
 
 /* Descriptor Tag (ECMA 167r3 3/7.2) */
 typedef struct
 {
-	uint16_t	tagIdent;
-	uint16_t	descVersion;
+	__le16		tagIdent;
+	__le16		descVersion;
 	uint8_t		tagChecksum;
 	uint8_t		reserved;
-	uint16_t	tagSerialNum;
-	uint16_t	descCRC;
-	uint16_t	descCRCLength;
-	uint32_t	tagLocation;
+	__le16		tagSerialNum;
+	__le16		descCRC;
+	__le16		descCRCLength;
+	__le32		tagLocation;
 } __attribute__ ((packed)) tag;
 
 /* Tag Identifier (ECMA 167r3 3/7.2.1) */
@@ -197,15 +217,15 @@
 struct primaryVolDesc
 {
 	tag		descTag;
-	uint32_t	volDescSeqNum;
-	uint32_t	primaryVolDescNum;
+	__le32		volDescSeqNum;
+	__le32		primaryVolDescNum;
 	dstring		volIdent[32];
-	uint16_t	volSeqNum;
-	uint16_t	maxVolSeqNum;
-	uint16_t	interchangeLvl;
-	uint16_t	maxInterchangeLvl;
-	uint32_t	charSetList;
-	uint32_t	maxCharSetList;
+	__le16		volSeqNum;
+	__le16		maxVolSeqNum;
+	__le16		interchangeLvl;
+	__le16		maxInterchangeLvl;
+	__le32		charSetList;
+	__le32		maxCharSetList;
 	dstring		volSetIdent[128];
 	charspec	descCharSet;
 	charspec	explanatoryCharSet;
@@ -215,8 +235,8 @@
 	timestamp	recordingDateAndTime;
 	regid		impIdent;
 	uint8_t		impUse[64];
-	uint32_t	predecessorVolDescSeqLocation;
-	uint16_t	flags;
+	__le32		predecessorVolDescSeqLocation;
+	__le16		flags;
 	uint8_t		reserved[22];
 } __attribute__ ((packed));
 
@@ -236,7 +256,7 @@
 struct volDescPtr
 {
 	tag		descTag;
-	uint32_t	volDescSeqNum;
+	__le32		volDescSeqNum;
 	extent_ad	nextVolDescSeqExt;
 	uint8_t		reserved[484];
 } __attribute__ ((packed));
@@ -245,7 +265,7 @@
 struct impUseVolDesc
 {
 	tag		descTag;
-	uint32_t	volDescSeqNum;
+	__le32		volDescSeqNum;
 	regid		impIdent;
 	uint8_t		impUse[460];
 } __attribute__ ((packed));
@@ -254,14 +274,14 @@
 struct partitionDesc
 {
 	tag		descTag;
-	uint32_t	volDescSeqNum;
-	uint16_t	partitionFlags;
-	uint16_t	partitionNumber;
+	__le32		volDescSeqNum;
+	__le16		partitionFlags;
+	__le16		partitionNumber;
 	regid		partitionContents;
 	uint8_t		partitionContentsUse[128];
-	uint32_t	accessType;
-	uint32_t	partitionStartingLocation;
-	uint32_t	partitionLength;
+	__le32		accessType;
+	__le32		partitionStartingLocation;
+	__le32		partitionLength;
 	regid		impIdent;
 	uint8_t		impUse[128];
 	uint8_t		reserved[156];
@@ -290,14 +310,14 @@
 struct logicalVolDesc
 {
 	tag		descTag;
-	uint32_t	volDescSeqNum;
+	__le32		volDescSeqNum;
 	charspec	descCharSet;
 	dstring		logicalVolIdent[128];
-	uint32_t	logicalBlockSize;
+	__le32		logicalBlockSize;
 	regid		domainIdent;
 	uint8_t		logicalVolContentsUse[16];
-	uint32_t	mapTableLength;
-	uint32_t	numPartitionMaps;
+	__le32		mapTableLength;
+	__le32		numPartitionMaps;
 	regid		impIdent;
 	uint8_t		impUse[128];
 	extent_ad	integritySeqExt;
@@ -322,8 +342,8 @@
 {
 	uint8_t		partitionMapType;
 	uint8_t		partitionMapLength;
-	uint16_t	volSeqNum;
-	uint16_t	partitionNum;
+	__le16		volSeqNum;
+	__le16		partitionNum;
 } __attribute__ ((packed));
 
 /* Type 2 Partition Map (ECMA 167r3 3/10.7.3) */
@@ -338,8 +358,8 @@
 struct unallocSpaceDesc
 {
 	tag		descTag;
-	uint32_t	volDescSeqNum;
-	uint32_t	numAllocDescs;
+	__le32		volDescSeqNum;
+	__le32		numAllocDescs;
 	extent_ad	allocDescs[0];
 } __attribute__ ((packed));
 
@@ -355,13 +375,13 @@
 {
 	tag		descTag;
 	timestamp	recordingDateAndTime;
-	uint32_t	integrityType;
+	__le32		integrityType;
 	extent_ad	nextIntegrityExt;
 	uint8_t		logicalVolContentsUse[32];
-	uint32_t	numOfPartitions;
-	uint32_t	lengthOfImpUse;
-	uint32_t	freeSpaceTable[0];
-	uint32_t	sizeTable[0];
+	__le32		numOfPartitions;
+	__le32		lengthOfImpUse;
+	__le32		freeSpaceTable[0];
+	__le32		sizeTable[0];
 	uint8_t		impUse[0];
 } __attribute__ ((packed));
 
@@ -372,33 +392,55 @@
 /* Recorded Address (ECMA 167r3 4/7.1) */
 typedef struct 
 {
-	uint32_t	logicalBlockNum;
-	uint16_t	partitionReferenceNum;
+	__le32		logicalBlockNum;
+	__le16	 	partitionReferenceNum;
 } __attribute__ ((packed)) lb_addr;
 
+/* ... and its in-core analog */
+typedef struct 
+{
+	uint32_t		logicalBlockNum;
+	uint16_t	 	partitionReferenceNum;
+} kernel_lb_addr;
+
 /* Short Allocation Descriptor (ECMA 167r3 4/14.14.1) */
 typedef struct
 {
-        uint32_t	extLength;
-        uint32_t	extPosition;
+        __le32		extLength;
+        __le32		extPosition;
 } __attribute__ ((packed)) short_ad;
 
 /* Long Allocation Descriptor (ECMA 167r3 4/14.14.2) */
 typedef struct
 {
-	uint32_t	extLength;
+	__le32		extLength;
 	lb_addr		extLocation;
 	uint8_t		impUse[6];
 } __attribute__ ((packed)) long_ad;
 
+typedef struct
+{
+	uint32_t	extLength;
+	kernel_lb_addr	extLocation;
+	uint8_t		impUse[6];
+} kernel_long_ad;
+
 /* Extended Allocation Descriptor (ECMA 167r3 4/14.14.3) */
 typedef struct
 {
+	__le32		extLength;
+	__le32		recordedLength;
+	__le32		informationLength;
+	lb_addr		extLocation;
+} __attribute__ ((packed)) ext_ad;
+
+typedef struct
+{
 	uint32_t	extLength;
 	uint32_t	recordedLength;
 	uint32_t	informationLength;
-	lb_addr		extLocation;
-} __attribute__ ((packed)) ext_ad;
+	kernel_lb_addr	extLocation;
+} kernel_ext_ad;
 
 /* Descriptor Tag (ECMA 167r3 4/7.2 - See 3/7.2) */
 
@@ -420,12 +462,12 @@
 {
 	tag		descTag;
 	timestamp	recordingDateAndTime;
-	uint16_t	interchangeLvl;
-	uint16_t	maxInterchangeLvl;
-	uint32_t	charSetList;
-	uint32_t	maxCharSetList;
-	uint32_t	fileSetNum;
-	uint32_t	fileSetDescNum;
+	__le16		interchangeLvl;
+	__le16		maxInterchangeLvl;
+	__le32		charSetList;
+	__le32		maxCharSetList;
+	__le32		fileSetNum;
+	__le32		fileSetDescNum;
 	charspec	logicalVolIdentCharSet;
 	dstring		logicalVolIdent[128];
 	charspec	fileSetCharSet;
@@ -454,11 +496,11 @@
 struct fileIdentDesc
 {
 	tag		descTag;
-	uint16_t	fileVersionNum;
+	__le16		fileVersionNum;
 	uint8_t		fileCharacteristics;
 	uint8_t		lengthFileIdent;
 	long_ad		icb;
-	uint16_t	lengthOfImpUse;
+	__le16		lengthOfImpUse;
 	uint8_t		impUse[0];
 	uint8_t		fileIdent[0];
 	uint8_t		padding[0];
@@ -475,21 +517,21 @@
 struct allocExtDesc
 {
 	tag		descTag;
-	uint32_t	previousAllocExtLocation;
-	uint32_t	lengthAllocDescs;
+	__le32		previousAllocExtLocation;
+	__le32		lengthAllocDescs;
 } __attribute__ ((packed));
 
 /* ICB Tag (ECMA 167r3 4/14.6) */
 typedef struct
 {
-	uint32_t	priorRecordedNumDirectEntries;
-	uint16_t	strategyType;
-	uint16_t	strategyParameter;
-	uint16_t	numEntries;
+	__le32		priorRecordedNumDirectEntries;
+	__le16		strategyType;
+	__le16		strategyParameter;
+	__le16		numEntries;
 	uint8_t		reserved;
 	uint8_t		fileType;
 	lb_addr		parentICBLocation;
-	uint16_t	flags;
+	__le16		flags;
 } __attribute__ ((packed)) icbtag;
 
 /* Strategy Type (ECMA 167r3 4/14.6.2) */
@@ -553,24 +595,24 @@
 {
 	tag		descTag;
 	icbtag		icbTag;
-	uint32_t	uid;
-	uint32_t	gid;
-	uint32_t	permissions;
-	uint16_t	fileLinkCount;
+	__le32		uid;
+	__le32		gid;
+	__le32		permissions;
+	__le16		fileLinkCount;
 	uint8_t		recordFormat;
 	uint8_t		recordDisplayAttr;
-	uint32_t	recordLength;
-	uint64_t	informationLength;
-	uint64_t	logicalBlocksRecorded;
+	__le32		recordLength;
+	__le64		informationLength;
+	__le64		logicalBlocksRecorded;
 	timestamp	accessTime;
 	timestamp	modificationTime;
 	timestamp	attrTime;
-	uint32_t	checkpoint;
+	__le32		checkpoint;
 	long_ad		extendedAttrICB;
 	regid		impIdent;
-	uint64_t	uniqueID;
-	uint32_t	lengthExtendedAttr;
-	uint32_t	lengthAllocDescs;
+	__le64		uniqueID;
+	__le32		lengthExtendedAttr;
+	__le32		lengthAllocDescs;
 	uint8_t		extendedAttr[0];
 	uint8_t		allocDescs[0];
 } __attribute__ ((packed));
@@ -616,28 +658,28 @@
 struct extendedAttrHeaderDesc
 {
 	tag		descTag;
-	uint32_t	impAttrLocation;
-	uint32_t	appAttrLocation;
+	__le32		impAttrLocation;
+	__le32		appAttrLocation;
 } __attribute__ ((packed));
 
 /* Generic Format (ECMA 167r3 4/14.10.2) */
 struct genericFormat
 {
-	uint32_t	attrType;
+	__le32		attrType;
 	uint8_t		attrSubtype;
 	uint8_t		reserved[3];
-	uint32_t	attrLength;
+	__le32		attrLength;
 	uint8_t		attrData[0];
 } __attribute__ ((packed));
 
 /* Character Set Information (ECMA 167r3 4/14.10.3) */
 struct charSetInfo
 {
-	uint32_t	attrType;
+	__le32		attrType;
 	uint8_t		attrSubtype;
 	uint8_t		reserved[3];
-	uint32_t	attrLength;
-	uint32_t	escapeSeqLength;
+	__le32		attrLength;
+	__le32		escapeSeqLength;
 	uint8_t		charSetType;
 	uint8_t		escapeSeq[0];
 } __attribute__ ((packed));
@@ -645,24 +687,24 @@
 /* Alternate Permissions (ECMA 167r3 4/14.10.4) */
 struct altPerms
 {
-	uint32_t	attrType;
+	__le32		attrType;
 	uint8_t		attrSubtype;
 	uint8_t		reserved[3];
-	uint32_t	attrLength;
-	uint16_t	ownerIdent;
-	uint16_t	groupIdent;
-	uint16_t	permission;
+	__le32		attrLength;
+	__le16		ownerIdent;
+	__le16		groupIdent;
+	__le16		permission;
 } __attribute__ ((packed));
 
 /* File Times Extended Attribute (ECMA 167r3 4/14.10.5) */
 struct fileTimesExtAttr
 {
-	uint32_t	attrType;
+	__le32		attrType;
 	uint8_t		attrSubtype;
 	uint8_t		reserved[3];
-	uint32_t	attrLength;
-	uint32_t	dataLength;
-	uint32_t	fileTimeExistence;
+	__le32		attrLength;
+	__le32		dataLength;
+	__le32		fileTimeExistence;
 	uint8_t		fileTimes;
 } __attribute__ ((packed));
 
@@ -675,36 +717,36 @@
 /* Information Times Extended Attribute (ECMA 167r3 4/14.10.6) */
 struct infoTimesExtAttr
 {
-	uint32_t	attrType;
+	__le32		attrType;
 	uint8_t		attrSubtype;
 	uint8_t		reserved[3];
-	uint32_t	attrLength;
-	uint32_t	dataLength;
-	uint32_t	infoTimeExistence;
+	__le32		attrLength;
+	__le32		dataLength;
+	__le32		infoTimeExistence;
 	uint8_t		infoTimes[0];
 } __attribute__ ((packed));
 
 /* Device Specification (ECMA 167r3 4/14.10.7) */
 struct deviceSpec
 {
-	uint32_t	attrType;
+	__le32		attrType;
 	uint8_t		attrSubtype;
 	uint8_t		reserved[3];
-	uint32_t	attrLength;
-	uint32_t	impUseLength;
-	uint32_t	majorDeviceIdent;
-	uint32_t	minorDeviceIdent;
+	__le32		attrLength;
+	__le32		impUseLength;
+	__le32		majorDeviceIdent;
+	__le32		minorDeviceIdent;
 	uint8_t		impUse[0];
 } __attribute__ ((packed));
 
 /* Implementation Use Extended Attr (ECMA 167r3 4/14.10.8) */
 struct impUseExtAttr
 {
-	uint32_t	attrType;
+	__le32		attrType;
 	uint8_t		attrSubtype;
 	uint8_t		reserved[3];
-	uint32_t	attrLength;
-	uint32_t	impUseLength;
+	__le32		attrLength;
+	__le32		impUseLength;
 	regid		impIdent;
 	uint8_t		impUse[0];
 } __attribute__ ((packed));
@@ -712,11 +754,11 @@
 /* Application Use Extended Attribute (ECMA 167r3 4/14.10.9) */
 struct appUseExtAttr
 {
-	uint32_t	attrType;
+	__le32		attrType;
 	uint8_t		attrSubtype;
 	uint8_t		reserved[3];
-	uint32_t	attrLength;
-	uint32_t	appUseLength;
+	__le32		attrLength;
+	__le32		appUseLength;
 	regid		appIdent;
 	uint8_t		appUse[0];
 } __attribute__ ((packed));
@@ -735,7 +777,7 @@
 {
 	tag		descTag;
 	icbtag		icbTag;
-	uint32_t	lengthAllocDescs;
+	__le32		lengthAllocDescs;
 	uint8_t		allocDescs[0];
 } __attribute__ ((packed));
 
@@ -743,8 +785,8 @@
 struct spaceBitmapDesc
 {
 	tag		descTag;
-	uint32_t	numOfBits;
-	uint32_t	numOfBytes;
+	__le32		numOfBits;
+	__le32		numOfBytes;
 	uint8_t		bitmap[0];
 } __attribute__ ((packed));
 
@@ -775,7 +817,7 @@
 /* Logical Volume Header Descriptor (ECMA 167r3 4/14.15) */
 struct logicalVolHeaderDesc
 {
-	uint64_t	uniqueID;
+	__le64		uniqueID;
 	uint8_t		reserved[24];
 } __attribute__ ((packed));
 
@@ -784,7 +826,7 @@
 {
 	uint8_t		componentType;
 	uint8_t		lengthComponentIdent;
-	uint16_t	componentFileVersionNum;
+	__le16		componentFileVersionNum;
 	dstring		componentIdent[0];
 } __attribute__ ((packed));
 
@@ -793,28 +835,28 @@
 {
 	tag		descTag;
 	icbtag		icbTag;
-	uint32_t	uid;
-	uint32_t	gid;
-	uint32_t	permissions;
-	uint16_t	fileLinkCount;
+	__le32		uid;
+	__le32		gid;
+	__le32		permissions;
+	__le16		fileLinkCount;
 	uint8_t		recordFormat;
 	uint8_t		recordDisplayAttr;
-	uint32_t	recordLength;
-	uint64_t	informationLength;
-	uint64_t	objectSize;
-	uint64_t	logicalBlocksRecorded;
+	__le32		recordLength;
+	__le64		informationLength;
+	__le64		objectSize;
+	__le64		logicalBlocksRecorded;
 	timestamp	accessTime;
 	timestamp	modificationTime;
 	timestamp	createTime;
 	timestamp	attrTime;
-	uint32_t	checkpoint;
-	uint32_t	reserved;
+	__le32		checkpoint;
+	__le32		reserved;
 	long_ad		extendedAttrICB;
 	long_ad		streamDirectoryICB;
 	regid		impIdent;
-	uint64_t	uniqueID;
-	uint32_t	lengthExtendedAttr;
-	uint32_t	lengthAllocDescs;
+	__le64		uniqueID;
+	__le32		lengthExtendedAttr;
+	__le32		lengthAllocDescs;
 	uint8_t		extendedAttr[0];
 	uint8_t		allocDescs[0];
 } __attribute__ ((packed));
diff -Nru a/fs/udf/fsync.c b/fs/udf/fsync.c
--- a/fs/udf/fsync.c	2004-10-18 14:56:13 -07:00
+++ b/fs/udf/fsync.c	2004-10-18 14:56:13 -07:00
@@ -28,6 +28,8 @@
 #include <linux/fs.h>
 #include <linux/smp_lock.h>
 
+static int udf_fsync_inode(struct inode *, int);
+
 /*
  *	File may be NULL when we are called. Perhaps we shouldn't
  *	even pass file to fsync ?
@@ -39,7 +41,7 @@
 	return udf_fsync_inode(inode, datasync);
 }
 
-int udf_fsync_inode(struct inode *inode, int datasync)
+static int udf_fsync_inode(struct inode *inode, int datasync)
 {
 	int err;
 
diff -Nru a/fs/udf/inode.c b/fs/udf/inode.c
--- a/fs/udf/inode.c	2004-10-18 14:57:18 -07:00
+++ b/fs/udf/inode.c	2004-10-18 14:57:18 -07:00
@@ -54,16 +54,19 @@
 static mode_t udf_convert_permissions(struct fileEntry *);
 static int udf_update_inode(struct inode *, int);
 static void udf_fill_inode(struct inode *, struct buffer_head *);
-static struct buffer_head *inode_getblk(struct inode *, long, int *, long *, int *);
+static struct buffer_head *inode_getblk(struct inode *, long, int *,
+	long *, int *);
+static int8_t udf_insert_aext(struct inode *, kernel_lb_addr, int,
+	kernel_lb_addr, uint32_t, struct buffer_head *);
 static void udf_split_extents(struct inode *, int *, int, int,
-	long_ad [EXTENT_MERGE_SIZE], int *);
+	kernel_long_ad [EXTENT_MERGE_SIZE], int *);
 static void udf_prealloc_extents(struct inode *, int, int,
-	 long_ad [EXTENT_MERGE_SIZE], int *);
+	 kernel_long_ad [EXTENT_MERGE_SIZE], int *);
 static void udf_merge_extents(struct inode *,
-	 long_ad [EXTENT_MERGE_SIZE], int *);
+	 kernel_long_ad [EXTENT_MERGE_SIZE], int *);
 static void udf_update_extents(struct inode *,
-	long_ad [EXTENT_MERGE_SIZE], int, int,
-	lb_addr, uint32_t, struct buffer_head **);
+	kernel_long_ad [EXTENT_MERGE_SIZE], int, int,
+	kernel_lb_addr, uint32_t, struct buffer_head **);
 static int udf_get_block(struct inode *, sector_t, struct buffer_head *, int);
 
 /*
@@ -213,7 +216,7 @@
 {
 	int newblock;
 	struct buffer_head *sbh = NULL, *dbh = NULL;
-	lb_addr bloc, eloc;
+	kernel_lb_addr bloc, eloc;
 	uint32_t elen, extoffset;
 	uint8_t alloctype;
 
@@ -268,12 +271,12 @@
 			return NULL;
 		}
 		UDF_I_ALLOCTYPE(inode) = alloctype;
-		sfi->descTag.tagLocation = *block;
+		sfi->descTag.tagLocation = cpu_to_le32(*block);
 		dfibh.soffset = dfibh.eoffset;
 		dfibh.eoffset += (sfibh.eoffset - sfibh.soffset);
 		dfi = (struct fileIdentDesc *)(dbh->b_data + dfibh.soffset);
 		if (udf_write_fi(inode, sfi, dfi, &dfibh, sfi->impUse,
-			sfi->fileIdent + sfi->lengthOfImpUse))
+			sfi->fileIdent + le16_to_cpu(sfi->lengthOfImpUse)))
 		{
 			UDF_I_ALLOCTYPE(inode) = ICBTAG_FLAG_AD_IN_ICB;
 			udf_release_data(dbh);
@@ -349,8 +352,8 @@
 	goto abort;
 }
 
-struct buffer_head * udf_getblk(struct inode * inode, long block,
-	int create, int * err)
+static struct buffer_head *
+udf_getblk(struct inode *inode, long block, int create, int *err)
 {
 	struct buffer_head dummy;
 
@@ -378,11 +381,11 @@
 	int *err, long *phys, int *new)
 {
 	struct buffer_head *pbh = NULL, *cbh = NULL, *nbh = NULL, *result = NULL;
-	long_ad laarr[EXTENT_MERGE_SIZE];
+	kernel_long_ad laarr[EXTENT_MERGE_SIZE];
 	uint32_t pextoffset = 0, cextoffset = 0, nextoffset = 0;
 	int count = 0, startnum = 0, endnum = 0;
 	uint32_t elen = 0;
-	lb_addr eloc, pbloc, cbloc, nbloc;
+	kernel_lb_addr eloc, pbloc, cbloc, nbloc;
 	int c = 1;
 	uint64_t lbcount = 0, b_off = 0;
 	uint32_t newblocknum, newblock, offset = 0;
@@ -476,7 +479,7 @@
 		c = !c;
 		laarr[c].extLength = EXT_NOT_RECORDED_NOT_ALLOCATED |
 			((offset + 1) << inode->i_sb->s_blocksize_bits);
-		memset(&laarr[c].extLocation, 0x00, sizeof(lb_addr));
+		memset(&laarr[c].extLocation, 0x00, sizeof(kernel_lb_addr));
 		count ++;
 		endnum ++;
 		lastblock = 1;
@@ -575,7 +578,7 @@
 }
 
 static void udf_split_extents(struct inode *inode, int *c, int offset, int newblocknum,
-	long_ad laarr[EXTENT_MERGE_SIZE], int *endnum)
+	kernel_long_ad laarr[EXTENT_MERGE_SIZE], int *endnum)
 {
 	if ((laarr[*c].extLength >> 30) == (EXT_NOT_RECORDED_ALLOCATED >> 30) ||
 		(laarr[*c].extLength >> 30) == (EXT_NOT_RECORDED_NOT_ALLOCATED >> 30))
@@ -637,7 +640,7 @@
 }
 
 static void udf_prealloc_extents(struct inode *inode, int c, int lastblock,
-	 long_ad laarr[EXTENT_MERGE_SIZE], int *endnum)
+	 kernel_long_ad laarr[EXTENT_MERGE_SIZE], int *endnum)
 {
 	int start, length = 0, currlength = 0, i;
 
@@ -729,7 +732,7 @@
 }
 
 static void udf_merge_extents(struct inode *inode,
-	 long_ad laarr[EXTENT_MERGE_SIZE], int *endnum)
+	 kernel_long_ad laarr[EXTENT_MERGE_SIZE], int *endnum)
 {
 	int i;
 
@@ -814,11 +817,11 @@
 }
 
 static void udf_update_extents(struct inode *inode,
-	long_ad laarr[EXTENT_MERGE_SIZE], int startnum, int endnum,
-	lb_addr pbloc, uint32_t pextoffset, struct buffer_head **pbh)
+	kernel_long_ad laarr[EXTENT_MERGE_SIZE], int startnum, int endnum,
+	kernel_lb_addr pbloc, uint32_t pextoffset, struct buffer_head **pbh)
 {
 	int start = 0, i;
-	lb_addr tmploc;
+	kernel_lb_addr tmploc;
 	uint32_t tmplen;
 
 	if (startnum > endnum)
@@ -938,10 +941,10 @@
 void
 udf_read_inode(struct inode *inode)
 {
-	memset(&UDF_I_LOCATION(inode), 0xFF, sizeof(lb_addr));
+	memset(&UDF_I_LOCATION(inode), 0xFF, sizeof(kernel_lb_addr));
 }
 
-void
+static void
 __udf_read_inode(struct inode *inode)
 {
 	struct buffer_head *bh = NULL;
@@ -994,7 +997,7 @@
 		{
 			if (ibh)
 			{
-				lb_addr loc;
+				kernel_lb_addr loc;
 				ie = (struct indirectEntry *)ibh->b_data;
 	
 				loc = lelb_to_cpu(ie->indirectICB.extLocation);
@@ -1005,7 +1008,7 @@
 					if (ident == TAG_IDENT_FE ||
 						ident == TAG_IDENT_EFE)
 					{
-						memcpy(&UDF_I_LOCATION(inode), &loc, sizeof(lb_addr));
+						memcpy(&UDF_I_LOCATION(inode), &loc, sizeof(kernel_lb_addr));
 						udf_release_data(bh);
 						udf_release_data(ibh);
 						udf_release_data(nbh);
@@ -1313,11 +1316,13 @@
  *	Written, tested, and released.
  */
 
-void udf_write_inode(struct inode * inode, int sync)
+int udf_write_inode(struct inode * inode, int sync)
 {
+	int ret;
 	lock_kernel();
-	udf_update_inode(inode, sync);
+	ret = udf_update_inode(inode, sync);
 	unlock_kernel();
+	return ret;
 }
 
 int udf_sync_inode(struct inode * inode)
@@ -1335,7 +1340,7 @@
 	uint16_t icbflags;
 	uint16_t crclen;
 	int i;
-	timestamp cpu_time;
+	kernel_timestamp cpu_time;
 	int err = 0;
 
 	bh = udf_tread(inode->i_sb,
@@ -1411,11 +1416,11 @@
 				udf_add_extendedattr(inode,
 					sizeof(struct deviceSpec) +
 					sizeof(regid), 12, 0x3);
-			dsea->attrType = 12;
+			dsea->attrType = cpu_to_le32(12);
 			dsea->attrSubtype = 1;
-			dsea->attrLength = sizeof(struct deviceSpec) +
-				sizeof(regid);
-			dsea->impUseLength = sizeof(regid);
+			dsea->attrLength = cpu_to_le32(sizeof(struct deviceSpec) +
+				sizeof(regid));
+			dsea->impUseLength = cpu_to_le32(sizeof(regid));
 		}
 		eid = (regid *)dsea->impUse;
 		memset(eid, 0, sizeof(regid));
@@ -1446,7 +1451,7 @@
 		fe->uniqueID = cpu_to_le64(UDF_I_UNIQUE(inode));
 		fe->lengthExtendedAttr = cpu_to_le32(UDF_I_LENEATTR(inode));
 		fe->lengthAllocDescs = cpu_to_le32(UDF_I_LENALLOC(inode));
-		fe->descTag.tagIdent = le16_to_cpu(TAG_IDENT_FE);
+		fe->descTag.tagIdent = cpu_to_le16(TAG_IDENT_FE);
 		crclen = sizeof(struct fileEntry);
 	}
 	else
@@ -1492,7 +1497,7 @@
 		efe->uniqueID = cpu_to_le64(UDF_I_UNIQUE(inode));
 		efe->lengthExtendedAttr = cpu_to_le32(UDF_I_LENEATTR(inode));
 		efe->lengthAllocDescs = cpu_to_le32(UDF_I_LENALLOC(inode));
-		efe->descTag.tagIdent = le16_to_cpu(TAG_IDENT_EFE);
+		efe->descTag.tagIdent = cpu_to_le16(TAG_IDENT_EFE);
 		crclen = sizeof(struct extendedFileEntry);
 	}
 	if (UDF_I_STRAT4096(inode))
@@ -1578,7 +1583,7 @@
  * 12/19/98 dgb  Added semaphore and changed to be a wrapper of iget
  */
 struct inode *
-udf_iget(struct super_block *sb, lb_addr ino)
+udf_iget(struct super_block *sb, kernel_lb_addr ino)
 {
 	struct inode *inode;
 	unsigned long block;
@@ -1603,7 +1608,7 @@
 	else if (UDF_I_LOCATION(inode).logicalBlockNum == 0xFFFFFFFF &&
 		UDF_I_LOCATION(inode).partitionReferenceNum == 0xFFFF)
 	{
-		memcpy(&UDF_I_LOCATION(inode), &ino, sizeof(lb_addr));
+		memcpy(&UDF_I_LOCATION(inode), &ino, sizeof(kernel_lb_addr));
 		__udf_read_inode(inode);
 		if (is_bad_inode(inode))
 		{
@@ -1624,8 +1629,8 @@
 	return inode;
 }
 
-int8_t udf_add_aext(struct inode *inode, lb_addr *bloc, int *extoffset,
-	lb_addr eloc, uint32_t elen, struct buffer_head **bh, int inc)
+int8_t udf_add_aext(struct inode *inode, kernel_lb_addr *bloc, int *extoffset,
+	kernel_lb_addr eloc, uint32_t elen, struct buffer_head **bh, int inc)
 {
 	int adsize;
 	short_ad *sad = NULL;
@@ -1651,7 +1656,7 @@
 		char *sptr, *dptr;
 		struct buffer_head *nbh;
 		int err, loffset;
-		lb_addr obloc = *bloc;
+		kernel_lb_addr obloc = *bloc;
 
 		if (!(bloc->logicalBlockNum = udf_new_block(inode->i_sb, NULL,
 			obloc.partitionReferenceNum, obloc.logicalBlockNum, &err)))
@@ -1764,8 +1769,8 @@
 	return etype;
 }
 
-int8_t udf_write_aext(struct inode *inode, lb_addr bloc, int *extoffset,
-    lb_addr eloc, uint32_t elen, struct buffer_head *bh, int inc)
+int8_t udf_write_aext(struct inode *inode, kernel_lb_addr bloc, int *extoffset,
+    kernel_lb_addr eloc, uint32_t elen, struct buffer_head *bh, int inc)
 {
 	int adsize;
 	uint8_t *ptr;
@@ -1820,8 +1825,8 @@
 	return (elen >> 30);
 }
 
-int8_t udf_next_aext(struct inode *inode, lb_addr *bloc, int *extoffset,
-	lb_addr *eloc, uint32_t *elen, struct buffer_head **bh, int inc)
+int8_t udf_next_aext(struct inode *inode, kernel_lb_addr *bloc, int *extoffset,
+	kernel_lb_addr *eloc, uint32_t *elen, struct buffer_head **bh, int inc)
 {
 	int8_t etype;
 
@@ -1842,8 +1847,8 @@
 	return etype;
 }
 
-int8_t udf_current_aext(struct inode *inode, lb_addr *bloc, int *extoffset,
-	lb_addr *eloc, uint32_t *elen, struct buffer_head **bh, int inc)
+int8_t udf_current_aext(struct inode *inode, kernel_lb_addr *bloc, int *extoffset,
+	kernel_lb_addr *eloc, uint32_t *elen, struct buffer_head **bh, int inc)
 {
 	int alen;
 	int8_t etype;
@@ -1901,10 +1906,11 @@
 	return etype;
 }
 
-int8_t udf_insert_aext(struct inode *inode, lb_addr bloc, int extoffset,
-	lb_addr neloc, uint32_t nelen, struct buffer_head *bh)
+static int8_t
+udf_insert_aext(struct inode *inode, kernel_lb_addr bloc, int extoffset,
+		kernel_lb_addr neloc, uint32_t nelen, struct buffer_head *bh)
 {
-	lb_addr oeloc;
+	kernel_lb_addr oeloc;
 	uint32_t oelen;
 	int8_t etype;
 
@@ -1923,11 +1929,11 @@
 	return (nelen >> 30);
 }
 
-int8_t udf_delete_aext(struct inode *inode, lb_addr nbloc, int nextoffset,
-	lb_addr eloc, uint32_t elen, struct buffer_head *nbh)
+int8_t udf_delete_aext(struct inode *inode, kernel_lb_addr nbloc, int nextoffset,
+	kernel_lb_addr eloc, uint32_t elen, struct buffer_head *nbh)
 {
 	struct buffer_head *obh;
-	lb_addr obloc;
+	kernel_lb_addr obloc;
 	int oextoffset, adsize;
 	int8_t etype;
 	struct allocExtDesc *aed;
@@ -1964,7 +1970,7 @@
 			oextoffset = nextoffset - adsize;
 		}
 	}
-	memset(&eloc, 0x00, sizeof(lb_addr));
+	memset(&eloc, 0x00, sizeof(kernel_lb_addr));
 	elen = 0;
 
 	if (nbh != obh)
@@ -2015,8 +2021,8 @@
 	return (elen >> 30);
 }
 
-int8_t inode_bmap(struct inode *inode, int block, lb_addr *bloc, uint32_t *extoffset,
-	lb_addr *eloc, uint32_t *elen, uint32_t *offset, struct buffer_head **bh)
+int8_t inode_bmap(struct inode *inode, int block, kernel_lb_addr *bloc, uint32_t *extoffset,
+	kernel_lb_addr *eloc, uint32_t *elen, uint32_t *offset, struct buffer_head **bh)
 {
 	uint64_t lbcount = 0, bcount = (uint64_t)block << inode->i_sb->s_blocksize_bits;
 	int8_t etype;
@@ -2054,7 +2060,7 @@
 
 long udf_block_map(struct inode *inode, long block)
 {
-	lb_addr eloc, bloc;
+	kernel_lb_addr eloc, bloc;
 	uint32_t offset, extoffset, elen;
 	struct buffer_head *bh = NULL;
 	int ret;
diff -Nru a/fs/udf/misc.c b/fs/udf/misc.c
--- a/fs/udf/misc.c	2004-10-18 14:56:33 -07:00
+++ b/fs/udf/misc.c	2004-10-18 14:56:33 -07:00
@@ -273,7 +273,7 @@
 }
 
 struct buffer_head *
-udf_read_ptagged(struct super_block *sb, lb_addr loc, uint32_t offset, uint16_t *ident)
+udf_read_ptagged(struct super_block *sb, kernel_lb_addr loc, uint32_t offset, uint16_t *ident)
 {
 	return udf_read_tagged(sb, udf_get_lb_pblock(sb, loc, offset),
 		loc.logicalBlockNum + offset, ident);
@@ -293,8 +293,8 @@
 	length -= sizeof(tag);
 
 	tptr->tagChecksum = 0;
-	tptr->descCRCLength = le16_to_cpu(length);
-	tptr->descCRC = le16_to_cpu(udf_crc(data + sizeof(tag), length, 0));
+	tptr->descCRCLength = cpu_to_le16(length);
+	tptr->descCRC = cpu_to_le16(udf_crc(data + sizeof(tag), length, 0));
 
 	for (i=0; i<16; i++)
 		if (i != 4)
@@ -305,9 +305,9 @@
 	uint32_t loc, int length)
 {
 	tag *tptr = (tag *)data;
-	tptr->tagIdent = le16_to_cpu(ident);
-	tptr->descVersion = le16_to_cpu(version);
-	tptr->tagSerialNum = le16_to_cpu(snum);
-	tptr->tagLocation = le32_to_cpu(loc);
+	tptr->tagIdent = cpu_to_le16(ident);
+	tptr->descVersion = cpu_to_le16(version);
+	tptr->tagSerialNum = cpu_to_le16(snum);
+	tptr->tagLocation = cpu_to_le32(loc);
 	udf_update_tag(data, length);
 }
diff -Nru a/fs/udf/namei.c b/fs/udf/namei.c
--- a/fs/udf/namei.c	2004-10-18 14:56:50 -07:00
+++ b/fs/udf/namei.c	2004-10-18 14:56:50 -07:00
@@ -119,7 +119,7 @@
 		crc = udf_crc(fibh->ebh->b_data, fibh->eoffset, crc);
 	}
 
-	cfi->descTag.descCRC = cpu_to_le32(crc);
+	cfi->descTag.descCRC = cpu_to_le16(crc);
 	cfi->descTag.descCRCLength = cpu_to_le16(crclen);
 
 	for (i=0; i<16; i++)
@@ -160,7 +160,7 @@
 	uint8_t lfi;
 	uint16_t liu;
 	loff_t size = (udf_ext0_offset(dir) + dir->i_size) >> 2;
-	lb_addr bloc, eloc;
+	kernel_lb_addr bloc, eloc;
 	uint32_t extoffset, elen, offset;
 	struct buffer_head *bh = NULL;
 
@@ -314,7 +314,7 @@
 	/* temporary shorthand for specifying files by inode number */
 	if (!strncmp(dentry->d_name.name, ".B=", 3) )
 	{
-		lb_addr lb = { 0, simple_strtoul(dentry->d_name.name+3, NULL, 0) };
+		kernel_lb_addr lb = { 0, simple_strtoul(dentry->d_name.name+3, NULL, 0) };
 		inode = udf_iget(dir->i_sb, lb);
 		if (!inode)
 		{
@@ -360,7 +360,7 @@
 	uint8_t lfi;
 	uint16_t liu;
 	int block;
-	lb_addr bloc, eloc;
+	kernel_lb_addr bloc, eloc;
 	uint32_t extoffset, elen, offset;
 	struct buffer_head *bh = NULL;
 
@@ -655,7 +655,7 @@
 	}
 	cfi.icb.extLength = cpu_to_le32(inode->i_sb->s_blocksize);
 	cfi.icb.extLocation = cpu_to_lelb(UDF_I_LOCATION(inode));
-	*(uint32_t *)((struct allocDescImpUse *)cfi.icb.impUse)->impUse =
+	*(__le32 *)((struct allocDescImpUse *)cfi.icb.impUse)->impUse =
 		cpu_to_le32(UDF_I_UNIQUE(inode) & 0x00000000FFFFFFFFUL);
 	udf_write_fi(dir, &cfi, fi, &fibh, NULL, NULL);
 	if (UDF_I_ALLOCTYPE(dir) == ICBTAG_FLAG_AD_IN_ICB)
@@ -698,7 +698,7 @@
 	}
 	cfi.icb.extLength = cpu_to_le32(inode->i_sb->s_blocksize);
 	cfi.icb.extLocation = cpu_to_lelb(UDF_I_LOCATION(inode));
-	*(uint32_t *)((struct allocDescImpUse *)cfi.icb.impUse)->impUse =
+	*(__le32 *)((struct allocDescImpUse *)cfi.icb.impUse)->impUse =
 		cpu_to_le32(UDF_I_UNIQUE(inode) & 0x00000000FFFFFFFFUL);
 	udf_write_fi(dir, &cfi, fi, &fibh, NULL, NULL);
 	if (UDF_I_ALLOCTYPE(dir) == ICBTAG_FLAG_AD_IN_ICB)
@@ -746,7 +746,7 @@
 	inode->i_nlink = 2;
 	cfi.icb.extLength = cpu_to_le32(inode->i_sb->s_blocksize);
 	cfi.icb.extLocation = cpu_to_lelb(UDF_I_LOCATION(dir));
-	*(uint32_t *)((struct allocDescImpUse *)cfi.icb.impUse)->impUse =
+	*(__le32 *)((struct allocDescImpUse *)cfi.icb.impUse)->impUse =
 		cpu_to_le32(UDF_I_UNIQUE(dir) & 0x00000000FFFFFFFFUL);
 	cfi.fileCharacteristics = FID_FILE_CHAR_DIRECTORY | FID_FILE_CHAR_PARENT;
 	udf_write_fi(inode, &cfi, fi, &fibh, NULL, NULL);
@@ -765,7 +765,7 @@
 	}
 	cfi.icb.extLength = cpu_to_le32(inode->i_sb->s_blocksize);
 	cfi.icb.extLocation = cpu_to_lelb(UDF_I_LOCATION(inode));
-	*(uint32_t *)((struct allocDescImpUse *)cfi.icb.impUse)->impUse =
+	*(__le32 *)((struct allocDescImpUse *)cfi.icb.impUse)->impUse =
 		cpu_to_le32(UDF_I_UNIQUE(inode) & 0x00000000FFFFFFFFUL);
 	cfi.fileCharacteristics |= FID_FILE_CHAR_DIRECTORY;
 	udf_write_fi(dir, &cfi, fi, &fibh, NULL, NULL);
@@ -788,7 +788,7 @@
 	loff_t f_pos;
 	loff_t size = (udf_ext0_offset(dir) + dir->i_size) >> 2;
 	int block;
-	lb_addr bloc, eloc;
+	kernel_lb_addr bloc, eloc;
 	uint32_t extoffset, elen, offset;
 	struct buffer_head *bh = NULL;
 
@@ -861,7 +861,7 @@
 	struct inode * inode = dentry->d_inode;
 	struct udf_fileident_bh fibh;
 	struct fileIdentDesc *fi, cfi;
-	lb_addr tloc;
+	kernel_lb_addr tloc;
 
 	retval = -ENOENT;
 	lock_kernel();
@@ -906,7 +906,7 @@
 	struct udf_fileident_bh fibh;
 	struct fileIdentDesc *fi;
 	struct fileIdentDesc cfi;
-	lb_addr tloc;
+	kernel_lb_addr tloc;
 
 	retval = -ENOENT;
 	lock_kernel();
@@ -971,7 +971,7 @@
 	if (UDF_I_ALLOCTYPE(inode) != ICBTAG_FLAG_AD_IN_ICB)
 	{
 		struct buffer_head *bh = NULL;
-		lb_addr bloc, eloc;
+		kernel_lb_addr bloc, eloc;
 		uint32_t elen, extoffset;
 
 		block = udf_new_block(inode->i_sb, inode,
@@ -1085,7 +1085,7 @@
 		uint64_t uniqueID;
 		lvhd = (struct logicalVolHeaderDesc *)(UDF_SB_LVID(inode->i_sb)->logicalVolContentsUse);
 		uniqueID = le64_to_cpu(lvhd->uniqueID);
-		*(uint32_t *)((struct allocDescImpUse *)cfi.icb.impUse)->impUse =
+		*(__le32 *)((struct allocDescImpUse *)cfi.icb.impUse)->impUse =
 			cpu_to_le32(uniqueID & 0x00000000FFFFFFFFUL);
 		if (!(++uniqueID & 0x00000000FFFFFFFFUL))
 			uniqueID += 16;
@@ -1142,7 +1142,7 @@
 		uint64_t uniqueID;
 		lvhd = (struct logicalVolHeaderDesc *)(UDF_SB_LVID(inode->i_sb)->logicalVolContentsUse);
 		uniqueID = le64_to_cpu(lvhd->uniqueID);
-		*(uint32_t *)((struct allocDescImpUse *)cfi.icb.impUse)->impUse =
+		*(__le32 *)((struct allocDescImpUse *)cfi.icb.impUse)->impUse =
 			cpu_to_le32(uniqueID & 0x00000000FFFFFFFFUL);
 		if (!(++uniqueID & 0x00000000FFFFFFFFUL))
 			uniqueID += 16;
@@ -1178,7 +1178,7 @@
 	struct fileIdentDesc *ofi = NULL, *nfi = NULL, *dir_fi = NULL, ocfi, ncfi;
 	struct buffer_head *dir_bh = NULL;
 	int retval = -ENOENT;
-	lb_addr tloc;
+	kernel_lb_addr tloc;
 
 	lock_kernel();
 	if ((ofi = udf_find_entry(old_dir, old_dentry, &ofibh, &ocfi)))
@@ -1231,7 +1231,7 @@
 		}
 		if (!dir_fi)
 			goto end_rename;
-		tloc = cpu_to_lelb(dir_fi->icb.extLocation);
+		tloc = lelb_to_cpu(dir_fi->icb.extLocation);
 		if (udf_get_lb_pblock(old_inode->i_sb, tloc, 0)
 					!= old_dir->i_ino)
 			goto end_rename;
@@ -1277,9 +1277,9 @@
 
 	if (dir_fi)
 	{
-		dir_fi->icb.extLocation = lelb_to_cpu(UDF_I_LOCATION(new_dir));
+		dir_fi->icb.extLocation = cpu_to_lelb(UDF_I_LOCATION(new_dir));
 		udf_update_tag((char *)dir_fi, (sizeof(struct fileIdentDesc) +
-			cpu_to_le16(dir_fi->lengthOfImpUse) + 3) & ~3);
+			le16_to_cpu(dir_fi->lengthOfImpUse) + 3) & ~3);
 		if (UDF_I_ALLOCTYPE(old_inode) == ICBTAG_FLAG_AD_IN_ICB)
 		{
 			mark_inode_dirty(old_inode);
diff -Nru a/fs/udf/osta_udf.h b/fs/udf/osta_udf.h
--- a/fs/udf/osta_udf.h	2004-10-18 14:56:48 -07:00
+++ b/fs/udf/osta_udf.h	2004-10-18 14:56:48 -07:00
@@ -67,7 +67,7 @@
 
 struct UDFIdentSuffix
 {
-	uint16_t	UDFRevision;
+	__le16		UDFRevision;
 	uint8_t		OSClass;
 	uint8_t		OSIdentifier;
 	uint8_t		reserved[4];
@@ -90,11 +90,11 @@
 struct logicalVolIntegrityDescImpUse
 {
 	regid		impIdent;
-	uint32_t	numFiles;
-	uint32_t	numDirs;
-	uint16_t	minUDFReadRev;
-	uint16_t	minUDFWriteRev;
-	uint16_t	maxUDFWriteRev;
+	__le32		numFiles;
+	__le32		numDirs;
+	__le16		minUDFReadRev;
+	__le16		minUDFWriteRev;
+	__le16		maxUDFWriteRev;
 	uint8_t		impUse[0];
 } __attribute__ ((packed));
 
@@ -117,8 +117,8 @@
 	uint8_t		partitionMapLength;
 	uint8_t		reserved1[2];
 	regid		partIdent;
-	uint16_t	volSeqNum;
-	uint16_t	partitionNum;
+	__le16		volSeqNum;
+	__le16		partitionNum;
 } __attribute__ ((packed));
 
 /* Virtual Partition Map (UDF 2.50 2.2.8) */
@@ -128,8 +128,8 @@
 	uint8_t		partitionMapLength;
 	uint8_t		reserved1[2];
 	regid		partIdent;
-	uint16_t	volSeqNum;
-	uint16_t	partitionNum;
+	__le16		volSeqNum;
+	__le16		partitionNum;
 	uint8_t		reserved2[24];
 } __attribute__ ((packed));
 
@@ -140,13 +140,13 @@
 	uint8_t		partitionMapLength;
 	uint8_t		reserved1[2];
 	regid		partIdent;
-	uint16_t	volSeqNum;
-	uint16_t	partitionNum;
-	uint16_t	packetLength;
+	__le16		volSeqNum;
+	__le16		partitionNum;
+	__le16		packetLength;
 	uint8_t		numSparingTables;
 	uint8_t		reserved2[1];
-	uint32_t	sizeSparingTable;
-	uint32_t	locSparingTable[4];
+	__le32		sizeSparingTable;
+	__le32		locSparingTable[4];
 } __attribute__ ((packed));
 
 /* Metadata Partition Map (UDF 2.4.0 2.2.10) */
@@ -156,13 +156,13 @@
 	uint8_t		partitionMapLength;
 	uint8_t		reserved1[2];
 	regid		partIdent;
-	uint16_t	volSeqNum;
-	uint16_t	partitionNum;
-	uint32_t	metadataFileLoc;
-	uint32_t	metadataMirrorFileLoc;
-	uint32_t	metadataBitmapFileLoc;
-	uint32_t	allocUnitSize;
-	uint16_t	alignUnitSize;
+	__le16		volSeqNum;
+	__le16		partitionNum;
+	__le32		metadataFileLoc;
+	__le32		metadataMirrorFileLoc;
+	__le32		metadataBitmapFileLoc;
+	__le32		allocUnitSize;
+	__le16		alignUnitSize;
 	uint8_t		flags;
 	uint8_t		reserved2[5];
 } __attribute__ ((packed));
@@ -170,9 +170,9 @@
 /* Virtual Allocation Table (UDF 1.5 2.2.10) */
 struct virtualAllocationTable15
 {
-	uint32_t	VirtualSector[0];
+	__le32		VirtualSector[0];
 	regid		vatIdent;
-	uint32_t	previousVATICBLoc;
+	__le32		previousVATICBLoc;
 } __attribute__ ((packed));  
 
 #define ICBTAG_FILE_TYPE_VAT15		0x00U
@@ -180,18 +180,18 @@
 /* Virtual Allocation Table (UDF 2.50 2.2.11) */
 struct virtualAllocationTable20
 {
-	uint16_t	lengthHeader;
-	uint16_t	lengthImpUse;
+	__le16		lengthHeader;
+	__le16		lengthImpUse;
 	dstring		logicalVolIdent[128];
-	uint32_t	previousVATICBLoc;
-	uint32_t	numFiles;
-	uint32_t	numDirs;
-	uint16_t	minReadRevision;
-	uint16_t	minWriteRevision;
-	uint16_t	maxWriteRevision;
-	uint16_t	reserved;
+	__le32		previousVATICBLoc;
+	__le32		numFiles;
+	__le32		numDirs;
+	__le16		minReadRevision;
+	__le16		minWriteRevision;
+	__le16		maxWriteRevision;
+	__le16		reserved;
 	uint8_t		impUse[0];
-	uint32_t	vatEntry[0];
+	__le32		vatEntry[0];
 } __attribute__ ((packed));
 
 #define ICBTAG_FILE_TYPE_VAT20		0xF8U
@@ -199,17 +199,17 @@
 /* Sparing Table (UDF 2.50 2.2.12) */
 struct sparingEntry
 {
-	uint32_t	origLocation;
-	uint32_t	mappedLocation;
+	__le32		origLocation;
+	__le32		mappedLocation;
 } __attribute__ ((packed));
 
 struct sparingTable
 {
 	tag 		descTag;
 	regid		sparingIdent;
-	uint16_t	reallocationTableLen;
-	uint16_t	reserved;
-	uint32_t	sequenceNum;
+	__le16		reallocationTableLen;
+	__le16		reserved;
+	__le32		sequenceNum;
 	struct sparingEntry
 			mapEntry[0];
 } __attribute__ ((packed));
@@ -222,7 +222,7 @@
 /* struct long_ad ICB - ADImpUse (UDF 2.50 2.2.4.3) */
 struct allocDescImpUse
 {
-	uint16_t	flags;
+	__le16		flags;
 	uint8_t		impUse[4];
 } __attribute__ ((packed));
 
@@ -235,14 +235,14 @@
 /* FreeEASpace (UDF 2.50 3.3.4.5.1.1) */
 struct freeEaSpace
 {
-	uint16_t	headerChecksum;
+	__le16		headerChecksum;
 	uint8_t		freeEASpace[0];
 } __attribute__ ((packed));
 
 /* DVD Copyright Management Information (UDF 2.50 3.3.4.5.1.2) */
 struct DVDCopyrightImpUse 
 {
-	uint16_t	headerChecksum;
+	__le16		headerChecksum;
 	uint8_t		CGMSInfo;
 	uint8_t		dataType;
 	uint8_t		protectionSystemInfo[4];
@@ -252,7 +252,7 @@
 /* FreeAppEASpace (UDF 2.50 3.3.4.6.1) */
 struct freeAppEASpace
 {
-	uint16_t	headerChecksum;
+	__le16		headerChecksum;
 	uint8_t		freeEASpace[0];
 } __attribute__ ((packed));
 
diff -Nru a/fs/udf/partition.c b/fs/udf/partition.c
--- a/fs/udf/partition.c	2004-10-18 14:55:53 -07:00
+++ b/fs/udf/partition.c	2004-10-18 14:55:53 -07:00
@@ -84,7 +84,7 @@
 		return 0xFFFFFFFF;
 	}
 
-	loc = le32_to_cpu(((uint32_t *)bh->b_data)[index]);
+	loc = le32_to_cpu(((__le32 *)bh->b_data)[index]);
 
 	udf_release_data(bh);
 
@@ -119,7 +119,7 @@
 
 	if (st)
 	{
-		for (i=0; i<st->reallocationTableLen; i++)
+		for (i=0; i<le16_to_cpu(st->reallocationTableLen); i++)
 		{
 			if (le32_to_cpu(st->mapEntry[i].origLocation) >= 0xFFFFFFF0)
 				break;
@@ -163,7 +163,7 @@
 			if (!st)
 				return 1;
 
-			for (k=0; k<st->reallocationTableLen; k++)
+			for (k=0; k<le16_to_cpu(st->reallocationTableLen); k++)
 			{
 				if (le32_to_cpu(st->mapEntry[k].origLocation) == 0xFFFFFFFF)
 				{
@@ -173,7 +173,7 @@
 						{
 							st = (struct sparingTable *)sdata->s_spar_map[j]->b_data;
 							st->mapEntry[k].origLocation = cpu_to_le32(packet);
-							udf_update_tag((char *)st, sizeof(struct sparingTable) + st->reallocationTableLen * sizeof(struct sparingEntry));
+							udf_update_tag((char *)st, sizeof(struct sparingTable) + le16_to_cpu(st->reallocationTableLen) * sizeof(struct sparingEntry));
 							mark_buffer_dirty(sdata->s_spar_map[j]);
 						}
 					}
@@ -190,7 +190,7 @@
 				else if (le32_to_cpu(st->mapEntry[k].origLocation) > packet)
 					break;
 			}
-			for (l=k; l<st->reallocationTableLen; l++)
+			for (l=k; l<le16_to_cpu(st->reallocationTableLen); l++)
 			{
 				if (le32_to_cpu(st->mapEntry[l].origLocation) == 0xFFFFFFFF)
 				{
@@ -203,7 +203,7 @@
 							mapEntry.origLocation = cpu_to_le32(packet);
 							memmove(&st->mapEntry[k+1], &st->mapEntry[k], (l-k)*sizeof(struct sparingEntry));
 							st->mapEntry[k] = mapEntry;
-							udf_update_tag((char *)st, sizeof(struct sparingTable) + st->reallocationTableLen * sizeof(struct sparingEntry));
+							udf_update_tag((char *)st, sizeof(struct sparingTable) + le16_to_cpu(st->reallocationTableLen) * sizeof(struct sparingEntry));
 							mark_buffer_dirty(sdata->s_spar_map[j]);
 						}
 					}
diff -Nru a/fs/udf/super.c b/fs/udf/super.c
--- a/fs/udf/super.c	2004-10-18 14:56:33 -07:00
+++ b/fs/udf/super.c	2004-10-18 14:56:33 -07:00
@@ -85,13 +85,13 @@
 static int udf_remount_fs(struct super_block *, int *, char *);
 static int udf_check_valid(struct super_block *, int, int);
 static int udf_vrs(struct super_block *sb, int silent);
-static int udf_load_partition(struct super_block *, lb_addr *);
-static int udf_load_logicalvol(struct super_block *, struct buffer_head *, lb_addr *);
-static void udf_load_logicalvolint(struct super_block *, extent_ad);
+static int udf_load_partition(struct super_block *, kernel_lb_addr *);
+static int udf_load_logicalvol(struct super_block *, struct buffer_head *, kernel_lb_addr *);
+static void udf_load_logicalvolint(struct super_block *, kernel_extent_ad);
 static void udf_find_anchor(struct super_block *);
-static int udf_find_fileset(struct super_block *, lb_addr *, lb_addr *);
+static int udf_find_fileset(struct super_block *, kernel_lb_addr *, kernel_lb_addr *);
 static void udf_load_pvoldesc(struct super_block *, struct buffer_head *);
-static void udf_load_fileset(struct super_block *, struct buffer_head *, lb_addr *);
+static void udf_load_fileset(struct super_block *, struct buffer_head *, kernel_lb_addr *);
 static void udf_load_partdesc(struct super_block *, struct buffer_head *);
 static void udf_open_lvid(struct super_block *);
 static void udf_close_lvid(struct super_block *);
@@ -145,7 +145,7 @@
 {
 	udf_inode_cachep = kmem_cache_create("udf_inode_cache",
 					     sizeof(struct udf_inode_info),
-					     0, SLAB_HWCACHE_ALIGN|SLAB_RECLAIM_ACCOUNT,
+					     0, SLAB_RECLAIM_ACCOUNT,
 					     init_once, NULL);
 	if (udf_inode_cachep == NULL)
 		return -ENOMEM;
@@ -194,7 +194,6 @@
 static int __init init_udf_fs(void)
 {
 	int err;
-	printk(KERN_NOTICE "udf: registering filesystem\n");
 	err = init_inodecache();
 	if (err)
 		goto out1;
@@ -210,7 +209,6 @@
 
 static void __exit exit_udf_fs(void)
 {
-	printk(KERN_NOTICE "udf: unregistering filesystem\n");
 	unregister_filesystem(&udf_fstype);
 	destroy_inodecache();
 }
@@ -771,7 +769,7 @@
 }
 
 static int 
-udf_find_fileset(struct super_block *sb, lb_addr *fileset, lb_addr *root)
+udf_find_fileset(struct super_block *sb, kernel_lb_addr *fileset, kernel_lb_addr *root)
 {
 	struct buffer_head *bh = NULL;
 	long lastblock;
@@ -794,7 +792,7 @@
 
 	if (!bh) /* Search backwards through the partitions */
 	{
-		lb_addr newfileset;
+		kernel_lb_addr newfileset;
 
 		return 1;
 		
@@ -876,7 +874,7 @@
 	if ( udf_stamp_to_time(&recording, &recording_usec,
 		lets_to_cpu(pvoldesc->recordingDateAndTime)) )
 	{
-		timestamp ts;
+		kernel_timestamp ts;
 		ts = lets_to_cpu(pvoldesc->recordingDateAndTime);
 		udf_debug("recording time %ld/%ld, %04u/%02u/%02u %02u:%02u (%x)\n",
 			recording, recording_usec,
@@ -903,7 +901,7 @@
 }
 
 static void 
-udf_load_fileset(struct super_block *sb, struct buffer_head *bh, lb_addr *root)
+udf_load_fileset(struct super_block *sb, struct buffer_head *bh, kernel_lb_addr *root)
 {
 	struct fileSetDesc *fset;
 
@@ -950,7 +948,7 @@
 				phd = (struct partitionHeaderDesc *)(p->partitionContentsUse);
 				if (phd->unallocSpaceTable.extLength)
 				{
-					lb_addr loc = { le32_to_cpu(phd->unallocSpaceTable.extPosition), i };
+					kernel_lb_addr loc = { le32_to_cpu(phd->unallocSpaceTable.extPosition), i };
 
 					UDF_SB_PARTMAPS(sb)[i].s_uspace.s_table =
 						udf_iget(sb, loc);
@@ -976,7 +974,7 @@
 					udf_debug("partitionIntegrityTable (part %d)\n", i);
 				if (phd->freedSpaceTable.extLength)
 				{
-					lb_addr loc = { le32_to_cpu(phd->freedSpaceTable.extPosition), i };
+					kernel_lb_addr loc = { le32_to_cpu(phd->freedSpaceTable.extPosition), i };
 
 					UDF_SB_PARTMAPS(sb)[i].s_fspace.s_table =
 						udf_iget(sb, loc);
@@ -1015,7 +1013,7 @@
 }
 
 static int 
-udf_load_logicalvol(struct super_block *sb, struct buffer_head * bh, lb_addr *fileset)
+udf_load_logicalvol(struct super_block *sb, struct buffer_head * bh, kernel_lb_addr *fileset)
 {
 	struct logicalVolDesc *lvd;
 	int i, j, offset;
@@ -1043,12 +1041,12 @@
 			struct udfPartitionMap2 *upm2 = (struct udfPartitionMap2 *)&(lvd->partitionMaps[offset]);
 			if (!strncmp(upm2->partIdent.ident, UDF_ID_VIRTUAL, strlen(UDF_ID_VIRTUAL)))
 			{
-				if (le16_to_cpu(((uint16_t *)upm2->partIdent.identSuffix)[0]) == 0x0150)
+				if (le16_to_cpu(((__le16 *)upm2->partIdent.identSuffix)[0]) == 0x0150)
 				{
 					UDF_SB_PARTTYPE(sb,i) = UDF_VIRTUAL_MAP15;
 					UDF_SB_PARTFUNC(sb,i) = udf_get_pblock_virt15;
 				}
-				else if (le16_to_cpu(((uint16_t *)upm2->partIdent.identSuffix)[0]) == 0x0200)
+				else if (le16_to_cpu(((__le16 *)upm2->partIdent.identSuffix)[0]) == 0x0200)
 				{
 					UDF_SB_PARTTYPE(sb,i) = UDF_VIRTUAL_MAP20;
 					UDF_SB_PARTFUNC(sb,i) = udf_get_pblock_virt20;
@@ -1112,7 +1110,7 @@
  *
  */
 static void
-udf_load_logicalvolint(struct super_block *sb, extent_ad loc)
+udf_load_logicalvolint(struct super_block *sb, kernel_extent_ad loc)
 {
 	struct buffer_head *bh = NULL;
 	uint16_t ident;
@@ -1152,7 +1150,7 @@
  *	Written, tested, and released.
  */
 static  int
-udf_process_sequence(struct super_block *sb, long block, long lastblock, lb_addr *fileset)
+udf_process_sequence(struct super_block *sb, long block, long lastblock, kernel_lb_addr *fileset)
 {
 	struct buffer_head *bh = NULL;
 	struct udf_vds_record vds[VDS_POS_LENGTH];
@@ -1295,7 +1293,7 @@
 }
 
 static int
-udf_load_partition(struct super_block *sb, lb_addr *fileset)
+udf_load_partition(struct super_block *sb, kernel_lb_addr *fileset)
 {
 	struct anchorVolDescPtr *anchor;
 	uint16_t ident;
@@ -1352,7 +1350,7 @@
 			case UDF_VIRTUAL_MAP15:
 			case UDF_VIRTUAL_MAP20:
 			{
-				lb_addr ino;
+				kernel_lb_addr ino;
 
 				if (!UDF_SB_LASTBLOCK(sb))
 				{
@@ -1417,7 +1415,7 @@
 	if (UDF_SB_LVIDBH(sb))
 	{
 		int i;
-		timestamp cpu_time;
+		kernel_timestamp cpu_time;
 
 		UDF_SB_LVIDIU(sb)->impIdent.identSuffix[0] = UDF_OS_CLASS_UNIX;
 		UDF_SB_LVIDIU(sb)->impIdent.identSuffix[1] = UDF_OS_ID_LINUX;
@@ -1445,7 +1443,7 @@
 		UDF_SB_LVID(sb)->integrityType == LVID_INTEGRITY_TYPE_OPEN)
 	{
 		int i;
-		timestamp cpu_time;
+		kernel_timestamp cpu_time;
 
 		UDF_SB_LVIDIU(sb)->impIdent.identSuffix[0] = UDF_OS_CLASS_UNIX;
 		UDF_SB_LVIDIU(sb)->impIdent.identSuffix[1] = UDF_OS_ID_LINUX;
@@ -1457,7 +1455,7 @@
 			UDF_SB_LVIDIU(sb)->minUDFReadRev = cpu_to_le16(UDF_SB_UDFREV(sb));
 		if (UDF_SB_UDFREV(sb) > le16_to_cpu(UDF_SB_LVIDIU(sb)->minUDFWriteRev))
 			UDF_SB_LVIDIU(sb)->minUDFWriteRev = cpu_to_le16(UDF_SB_UDFREV(sb));
-		UDF_SB_LVID(sb)->integrityType = LVID_INTEGRITY_TYPE_CLOSE;
+		UDF_SB_LVID(sb)->integrityType = cpu_to_le32(LVID_INTEGRITY_TYPE_CLOSE);
 
 		UDF_SB_LVID(sb)->descTag.descCRC =
 			cpu_to_le16(udf_crc((char *)UDF_SB_LVID(sb) + sizeof(tag),
@@ -1494,7 +1492,7 @@
 	int i;
 	struct inode *inode=NULL;
 	struct udf_options uopt;
-	lb_addr rootdir, fileset;
+	kernel_lb_addr rootdir, fileset;
 	struct udf_sb_info *sbi;
 
 	uopt.flags = (1 << UDF_FLAG_USE_AD_IN_ICB) | (1 << UDF_FLAG_STRICT);
@@ -1587,7 +1585,8 @@
 		if (minUDFReadRev > UDF_MAX_READ_VERSION)
 		{
 			printk("UDF-fs: minUDFReadRev=%x (max is %x)\n",
-				UDF_SB_LVIDIU(sb)->minUDFReadRev, UDF_MAX_READ_VERSION);
+				le16_to_cpu(UDF_SB_LVIDIU(sb)->minUDFReadRev),
+				UDF_MAX_READ_VERSION);
 			goto error_out;
 		}
 		else if (minUDFWriteRev > UDF_MAX_WRITE_VERSION)
@@ -1617,7 +1616,7 @@
 
 	if (!silent)
 	{
-		timestamp ts;
+		kernel_timestamp ts;
 		udf_time_to_stamp(&ts, UDF_SB_RECORDTIME(sb));
 		udf_info("UDF %s (%s) Mounting volume '%s', timestamp %04u/%02u/%02u %02u:%02u (%x)\n",
 			UDFFS_VERSION, UDFFS_DATE,
@@ -1800,7 +1799,7 @@
 	unsigned int accum = 0;
 	int index;
 	int block = 0, newblock;
-	lb_addr loc;
+	kernel_lb_addr loc;
 	uint32_t bytes;
 	uint8_t value;
 	uint8_t *ptr;
@@ -1826,7 +1825,7 @@
 	}
 
 	bm = (struct spaceBitmapDesc *)bh->b_data;
-	bytes = bm->numOfBytes;
+	bytes = le32_to_cpu(bm->numOfBytes);
 	index = sizeof(struct spaceBitmapDesc); /* offset in first block only */
 	ptr = (uint8_t *)bh->b_data;
 
@@ -1867,7 +1866,7 @@
 {
 	unsigned int accum = 0;
 	uint32_t extoffset, elen;
-	lb_addr bloc, eloc;
+	kernel_lb_addr bloc, eloc;
 	int8_t etype;
 	struct buffer_head *bh = NULL;
 
diff -Nru a/fs/udf/truncate.c b/fs/udf/truncate.c
--- a/fs/udf/truncate.c	2004-10-18 14:56:28 -07:00
+++ b/fs/udf/truncate.c	2004-10-18 14:56:28 -07:00
@@ -33,10 +33,10 @@
 #include "udf_i.h"
 #include "udf_sb.h"
 
-static void extent_trunc(struct inode * inode, lb_addr bloc, int extoffset,
-	lb_addr eloc, int8_t etype, uint32_t elen, struct buffer_head *bh, uint32_t nelen)
+static void extent_trunc(struct inode * inode, kernel_lb_addr bloc, int extoffset,
+	kernel_lb_addr eloc, int8_t etype, uint32_t elen, struct buffer_head *bh, uint32_t nelen)
 {
-	lb_addr neloc = { 0, 0 };
+	kernel_lb_addr neloc = { 0, 0 };
 	int last_block = (elen + inode->i_sb->s_blocksize - 1) >> inode->i_sb->s_blocksize_bits;
 	int first_block = (nelen + inode->i_sb->s_blocksize - 1) >> inode->i_sb->s_blocksize_bits;
 
@@ -68,7 +68,7 @@
 
 void udf_discard_prealloc(struct inode * inode)
 {
-	lb_addr bloc, eloc;
+	kernel_lb_addr bloc, eloc;
 	uint32_t extoffset = 0, elen, nelen;
 	uint64_t lbcount = 0;
 	int8_t etype = -1, netype;
@@ -129,7 +129,7 @@
 
 void udf_truncate_extents(struct inode * inode)
 {
-	lb_addr bloc, eloc, neloc = { 0, 0 };
+	kernel_lb_addr bloc, eloc, neloc = { 0, 0 };
 	uint32_t extoffset, elen, offset, nelen = 0, lelen = 0, lenalloc;
 	int8_t etype;
 	int first_block = inode->i_size >> inode->i_sb->s_blocksize_bits;
@@ -254,7 +254,7 @@
 			}
 			else if (etype == (EXT_NOT_RECORDED_ALLOCATED >> 30))
 			{
-				lb_addr neloc = { 0, 0 };
+				kernel_lb_addr neloc = { 0, 0 };
 				extoffset -= adsize;
 				nelen = EXT_NOT_RECORDED_NOT_ALLOCATED |
 					((elen + offset + inode->i_sb->s_blocksize - 1) &
@@ -272,7 +272,7 @@
 						~(inode->i_sb->s_blocksize - 1));
 					udf_write_aext(inode, bloc, &extoffset, eloc, elen, bh, 1);
 				}
-				memset(&eloc, 0x00, sizeof(lb_addr));
+				memset(&eloc, 0x00, sizeof(kernel_lb_addr));
 				elen = EXT_NOT_RECORDED_NOT_ALLOCATED | offset;
 				udf_add_aext(inode, &bloc, &extoffset, eloc, elen, &bh, 1);
 			}
diff -Nru a/fs/udf/udfdecl.h b/fs/udf/udfdecl.h
--- a/fs/udf/udfdecl.h	2004-10-18 14:56:29 -07:00
+++ b/fs/udf/udfdecl.h	2004-10-18 14:56:29 -07:00
@@ -68,7 +68,7 @@
 struct generic_desc
 {
 	tag		descTag;
-	uint32_t	volDescSeqNum;
+	__le32		volDescSeqNum;
 };
 
 struct ustr
@@ -89,35 +89,32 @@
 extern int udf_ioctl(struct inode *, struct file *, unsigned int, unsigned long);
 
 /* inode.c */
-extern struct inode *udf_iget(struct super_block *, lb_addr);
+extern struct inode *udf_iget(struct super_block *, kernel_lb_addr);
 extern int udf_sync_inode(struct inode *);
 extern void udf_expand_file_adinicb(struct inode *, int, int *);
 extern struct buffer_head * udf_expand_dir_adinicb(struct inode *, int *, int *);
-extern struct buffer_head * udf_getblk(struct inode *, long, int, int *);
 extern struct buffer_head * udf_bread(struct inode *, int, int, int *);
 extern void udf_truncate(struct inode *);
 extern void udf_read_inode(struct inode *);
 extern void udf_put_inode(struct inode *);
 extern void udf_delete_inode(struct inode *);
 extern void udf_clear_inode(struct inode *);
-extern void udf_write_inode(struct inode *, int);
+extern int udf_write_inode(struct inode *, int);
 extern long udf_block_map(struct inode *, long);
-extern int8_t inode_bmap(struct inode *, int, lb_addr *, uint32_t *, lb_addr *, uint32_t *, uint32_t *, struct buffer_head **);
-extern int8_t udf_add_aext(struct inode *, lb_addr *, int *, lb_addr, uint32_t, struct buffer_head **, int);
-extern int8_t udf_write_aext(struct inode *, lb_addr, int *, lb_addr, uint32_t, struct buffer_head *, int);
-extern int8_t udf_insert_aext(struct inode *, lb_addr, int, lb_addr, uint32_t, struct buffer_head *);
-extern int8_t udf_delete_aext(struct inode *, lb_addr, int, lb_addr, uint32_t, struct buffer_head *);
-extern int8_t udf_next_aext(struct inode *, lb_addr *, int *, lb_addr *, uint32_t *, struct buffer_head **, int);
-extern int8_t udf_current_aext(struct inode *, lb_addr *, int *, lb_addr *, uint32_t *, struct buffer_head **, int);
+extern int8_t inode_bmap(struct inode *, int, kernel_lb_addr *, uint32_t *, kernel_lb_addr *, uint32_t *, uint32_t *, struct buffer_head **);
+extern int8_t udf_add_aext(struct inode *, kernel_lb_addr *, int *, kernel_lb_addr, uint32_t, struct buffer_head **, int);
+extern int8_t udf_write_aext(struct inode *, kernel_lb_addr, int *, kernel_lb_addr, uint32_t, struct buffer_head *, int);
+extern int8_t udf_delete_aext(struct inode *, kernel_lb_addr, int, kernel_lb_addr, uint32_t, struct buffer_head *);
+extern int8_t udf_next_aext(struct inode *, kernel_lb_addr *, int *, kernel_lb_addr *, uint32_t *, struct buffer_head **, int);
+extern int8_t udf_current_aext(struct inode *, kernel_lb_addr *, int *, kernel_lb_addr *, uint32_t *, struct buffer_head **, int);
 
 /* misc.c */
-extern int udf_read_tagged_data(char *, int size, int fd, int block, int partref);
 extern struct buffer_head *udf_tgetblk(struct super_block *, int);
 extern struct buffer_head *udf_tread(struct super_block *, int);
 extern struct genericFormat *udf_add_extendedattr(struct inode *, uint32_t, uint32_t, uint8_t);
 extern struct genericFormat *udf_get_extendedattr(struct inode *, uint32_t, uint8_t);
 extern struct buffer_head *udf_read_tagged(struct super_block *, uint32_t, uint32_t, uint16_t *);
-extern struct buffer_head *udf_read_ptagged(struct super_block *, lb_addr, uint32_t, uint16_t *);
+extern struct buffer_head *udf_read_ptagged(struct super_block *, kernel_lb_addr, uint32_t, uint16_t *);
 extern void udf_release_data(struct buffer_head *);
 extern void udf_update_tag(char *, int);
 extern void udf_new_tag(char *, uint16_t, uint16_t, uint16_t, uint32_t, int);
@@ -148,28 +145,24 @@
 extern void udf_truncate_extents(struct inode *);
 
 /* balloc.c */
-extern void udf_free_blocks(struct super_block *, struct inode *, lb_addr, uint32_t, uint32_t);
+extern void udf_free_blocks(struct super_block *, struct inode *, kernel_lb_addr, uint32_t, uint32_t);
 extern int udf_prealloc_blocks(struct super_block *, struct inode *, uint16_t, uint32_t, uint32_t);
 extern int udf_new_block(struct super_block *, struct inode *, uint16_t, uint32_t, int *);
 
 /* fsync.c */
 extern int udf_fsync_file(struct file *, struct dentry *, int);
-extern int udf_fsync_inode(struct inode *, int);
 
 /* directory.c */
-extern uint8_t * udf_filead_read(struct inode *, uint8_t *, uint8_t, lb_addr, int *, int *, struct buffer_head **, int *);
-extern struct fileIdentDesc * udf_fileident_read(struct inode *, loff_t *, struct udf_fileident_bh *, struct fileIdentDesc *, lb_addr *, uint32_t *, lb_addr *, uint32_t *, uint32_t *, struct buffer_head **);
+extern struct fileIdentDesc * udf_fileident_read(struct inode *, loff_t *, struct udf_fileident_bh *, struct fileIdentDesc *, kernel_lb_addr *, uint32_t *, kernel_lb_addr *, uint32_t *, uint32_t *, struct buffer_head **);
 extern struct fileIdentDesc * udf_get_fileident(void * buffer, int bufsize, int * offset);
-extern extent_ad * udf_get_fileextent(void * buffer, int bufsize, int * offset);
 extern long_ad * udf_get_filelongad(uint8_t *, int, int *, int);
 extern short_ad * udf_get_fileshortad(uint8_t *, int, int *, int);
-extern uint8_t * udf_get_filead(struct fileEntry *, uint8_t *, int, int, int, int *);
 
 /* crc.c */
 extern uint16_t udf_crc(uint8_t *, uint32_t, uint16_t);
 
 /* udftime.c */
-extern time_t *udf_stamp_to_time(time_t *, long *, timestamp);
-extern timestamp *udf_time_to_stamp(timestamp *, struct timespec);
+extern time_t *udf_stamp_to_time(time_t *, long *, kernel_timestamp);
+extern kernel_timestamp *udf_time_to_stamp(kernel_timestamp *, struct timespec);
 
 #endif /* __UDF_DECL_H */
diff -Nru a/fs/udf/udfend.h b/fs/udf/udfend.h
--- a/fs/udf/udfend.h	2004-10-18 14:56:17 -07:00
+++ b/fs/udf/udfend.h	2004-10-18 14:56:17 -07:00
@@ -4,15 +4,15 @@
 #include <asm/byteorder.h>
 #include <linux/string.h>
 
-static inline lb_addr lelb_to_cpu(lb_addr in)
+static inline kernel_lb_addr lelb_to_cpu(lb_addr in)
 {
-	lb_addr out;
+	kernel_lb_addr out;
 	out.logicalBlockNum = le32_to_cpu(in.logicalBlockNum);
 	out.partitionReferenceNum = le16_to_cpu(in.partitionReferenceNum);
 	return out;
 }
 
-static inline lb_addr cpu_to_lelb(lb_addr in)
+static inline lb_addr cpu_to_lelb(kernel_lb_addr in)
 {
 	lb_addr out;
 	out.logicalBlockNum = cpu_to_le32(in.logicalBlockNum);
@@ -20,9 +20,9 @@
 	return out;
 }
 
-static inline timestamp lets_to_cpu(timestamp in)
+static inline kernel_timestamp lets_to_cpu(timestamp in)
 {
-	timestamp out;
+	kernel_timestamp out;
 	memcpy(&out, &in, sizeof(timestamp));
 	out.typeAndTimezone = le16_to_cpu(in.typeAndTimezone);
 	out.year = le16_to_cpu(in.year);
@@ -45,15 +45,15 @@
 	return out;
 }
 
-static inline long_ad lela_to_cpu(long_ad in)
+static inline kernel_long_ad lela_to_cpu(long_ad in)
 {
-	long_ad out;
+	kernel_long_ad out;
 	out.extLength = le32_to_cpu(in.extLength);
 	out.extLocation = lelb_to_cpu(in.extLocation);
 	return out;
 }
 
-static inline long_ad cpu_to_lela(long_ad in)
+static inline long_ad cpu_to_lela(kernel_long_ad in)
 {
 	long_ad out;
 	out.extLength = cpu_to_le32(in.extLength);
@@ -61,15 +61,15 @@
 	return out;
 }
 
-static inline extent_ad leea_to_cpu(extent_ad in)
+static inline kernel_extent_ad leea_to_cpu(extent_ad in)
 {
-	extent_ad out;
+	kernel_extent_ad out;
 	out.extLength = le32_to_cpu(in.extLength);
 	out.extLocation = le32_to_cpu(in.extLocation);
 	return out;
 }
 
-static inline timestamp cpu_to_lets(timestamp in)
+static inline timestamp cpu_to_lets(kernel_timestamp in)
 {
 	timestamp out;
 	memcpy(&out, &in, sizeof(timestamp));
diff -Nru a/fs/udf/udftime.c b/fs/udf/udftime.c
--- a/fs/udf/udftime.c	2004-10-18 14:56:32 -07:00
+++ b/fs/udf/udftime.c	2004-10-18 14:56:32 -07:00
@@ -58,7 +58,7 @@
 #define SPD 0x15180 /*3600*24*/
 #define SPY(y,l,s) (SPD * (365*y+l)+s)
 
-time_t year_seconds[MAX_YEAR_SECONDS]= {
+static time_t year_seconds[MAX_YEAR_SECONDS]= {
 /*1970*/ SPY( 0, 0,0), SPY( 1, 0,0), SPY( 2, 0,0), SPY( 3, 1,0), 
 /*1974*/ SPY( 4, 1,0), SPY( 5, 1,0), SPY( 6, 1,0), SPY( 7, 2,0), 
 /*1978*/ SPY( 8, 2,0), SPY( 9, 2,0), SPY(10, 2,0), SPY(11, 3,0), 
@@ -85,7 +85,7 @@
 #define SECS_PER_DAY	(SECS_PER_HOUR * 24)
 
 time_t *
-udf_stamp_to_time(time_t *dest, long *dest_usec, timestamp src)
+udf_stamp_to_time(time_t *dest, long *dest_usec, kernel_timestamp src)
 {
 	int yday;
 	uint8_t type = src.typeAndTimezone >> 12;
@@ -120,8 +120,8 @@
 }
 
 
-timestamp *
-udf_time_to_stamp(timestamp *dest, struct timespec ts)
+kernel_timestamp *
+udf_time_to_stamp(kernel_timestamp *dest, struct timespec ts)
 {
 	long int days, rem, y;
 	const unsigned short int *ip;
diff -Nru a/fs/ufs/balloc.c b/fs/ufs/balloc.c
--- a/fs/ufs/balloc.c	2004-10-18 14:56:33 -07:00
+++ b/fs/ufs/balloc.c	2004-10-18 14:56:33 -07:00
@@ -28,12 +28,12 @@
 #define UFSD(x)
 #endif
 
-unsigned ufs_add_fragments (struct inode *, unsigned, unsigned, unsigned, int *);
-unsigned ufs_alloc_fragments (struct inode *, unsigned, unsigned, unsigned, int *);
-unsigned ufs_alloccg_block (struct inode *, struct ufs_cg_private_info *, unsigned, int *);
-unsigned ufs_bitmap_search (struct super_block *, struct ufs_cg_private_info *, unsigned, unsigned);
+static unsigned ufs_add_fragments (struct inode *, unsigned, unsigned, unsigned, int *);
+static unsigned ufs_alloc_fragments (struct inode *, unsigned, unsigned, unsigned, int *);
+static unsigned ufs_alloccg_block (struct inode *, struct ufs_cg_private_info *, unsigned, int *);
+static unsigned ufs_bitmap_search (struct super_block *, struct ufs_cg_private_info *, unsigned, unsigned);
 static unsigned char ufs_fragtable_8fpb[], ufs_fragtable_other[];
-void ufs_clusteracct(struct super_block *, struct ufs_cg_private_info *, unsigned, int);
+static void ufs_clusteracct(struct super_block *, struct ufs_cg_private_info *, unsigned, int);
 
 /*
  * Free 'count' fragments from fragment number 'fragment'
@@ -235,7 +235,7 @@
 		brelse (bh); \
 	}
 
-unsigned ufs_new_fragments (struct inode * inode, u32 * p, unsigned fragment,
+unsigned ufs_new_fragments (struct inode * inode, __fs32 * p, unsigned fragment,
 	unsigned goal, unsigned count, int * err )
 {
 	struct super_block * sb;
@@ -393,8 +393,9 @@
 	return 0;
 }		
 
-unsigned ufs_add_fragments (struct inode * inode, unsigned fragment,
-	unsigned oldcount, unsigned newcount, int * err)
+static unsigned
+ufs_add_fragments (struct inode * inode, unsigned fragment,
+		   unsigned oldcount, unsigned newcount, int * err)
 {
 	struct super_block * sb;
 	struct ufs_sb_private_info * uspi;
@@ -411,7 +412,7 @@
 	count = newcount - oldcount;
 	
 	cgno = ufs_dtog(fragment);
-	if (UFS_SB(sb)->fs_cs(cgno).cs_nffree < count)
+	if (fs32_to_cpu(sb, UFS_SB(sb)->fs_cs(cgno).cs_nffree) < count)
 		return 0;
 	if ((ufs_fragnum (fragment) + newcount) > uspi->s_fpb)
 		return 0;
@@ -477,7 +478,7 @@
 		if (fs32_to_cpu(sb, ucg->cg_frsum[k])) \
 			goto cg_found; 
 
-unsigned ufs_alloc_fragments (struct inode * inode, unsigned cgno,
+static unsigned ufs_alloc_fragments (struct inode * inode, unsigned cgno,
 	unsigned goal, unsigned count, int * err)
 {
 	struct super_block * sb;
@@ -595,7 +596,7 @@
 	return result;
 }
 
-unsigned ufs_alloccg_block (struct inode * inode,
+static unsigned ufs_alloccg_block (struct inode * inode,
 	struct ufs_cg_private_info * ucpi, unsigned goal, int * err)
 {
 	struct super_block * sb;
@@ -653,7 +654,7 @@
 	return result;
 }
 
-unsigned ufs_bitmap_search (struct super_block * sb,
+static unsigned ufs_bitmap_search (struct super_block * sb,
 	struct ufs_cg_private_info * ucpi, unsigned goal, unsigned count)
 {
 	struct ufs_sb_private_info * uspi;
@@ -724,7 +725,7 @@
 	return (unsigned)-1;
 }
 
-void ufs_clusteracct(struct super_block * sb, 
+static void ufs_clusteracct(struct super_block * sb,
 	struct ufs_cg_private_info * ucpi, unsigned blkno, int cnt)
 {
 	struct ufs_sb_private_info * uspi;
@@ -770,11 +771,11 @@
 	i = back + forw + 1;
 	if (i > uspi->s_contigsumsize)
 		i = uspi->s_contigsumsize;
-	fs32_add(sb, (u32*)ubh_get_addr(UCPI_UBH, ucpi->c_clustersumoff + (i << 2)), cnt);
+	fs32_add(sb, (__fs32*)ubh_get_addr(UCPI_UBH, ucpi->c_clustersumoff + (i << 2)), cnt);
 	if (back > 0)
-		fs32_sub(sb, (u32*)ubh_get_addr(UCPI_UBH, ucpi->c_clustersumoff + (back << 2)), cnt);
+		fs32_sub(sb, (__fs32*)ubh_get_addr(UCPI_UBH, ucpi->c_clustersumoff + (back << 2)), cnt);
 	if (forw > 0)
-		fs32_sub(sb, (u32*)ubh_get_addr(UCPI_UBH, ucpi->c_clustersumoff + (forw << 2)), cnt);
+		fs32_sub(sb, (__fs32*)ubh_get_addr(UCPI_UBH, ucpi->c_clustersumoff + (forw << 2)), cnt);
 }
 
 
diff -Nru a/fs/ufs/dir.c b/fs/ufs/dir.c
--- a/fs/ufs/dir.c	2004-10-18 14:56:49 -07:00
+++ b/fs/ufs/dir.c	2004-10-18 14:56:49 -07:00
@@ -31,6 +31,9 @@
 #define UFSD(x)
 #endif
 
+static int
+ufs_check_dir_entry (const char *, struct inode *, struct ufs_dir_entry *,
+		     struct buffer_head *, unsigned long);
 
 
 /*
@@ -292,9 +295,10 @@
 	return NULL;
 }
 
-int ufs_check_dir_entry (const char * function,	struct inode * dir,
-	struct ufs_dir_entry * de, struct buffer_head * bh, 
-	unsigned long offset)
+static int
+ufs_check_dir_entry (const char *function, struct inode *dir,
+		     struct ufs_dir_entry *de, struct buffer_head *bh,
+		     unsigned long offset)
 {
 	struct super_block *sb = dir->i_sb;
 	const char *error_msg = NULL;
diff -Nru a/fs/ufs/inode.c b/fs/ufs/inode.c
--- a/fs/ufs/inode.c	2004-10-18 14:56:17 -07:00
+++ b/fs/ufs/inode.c	2004-10-18 14:56:17 -07:00
@@ -99,8 +99,8 @@
 	sector_t offsets[4], *p;
 	int depth = ufs_block_to_path(inode, frag >> uspi->s_fpbshift, offsets);
 	u64  ret = 0L;
-	u32 block;
-	u64 u2_block = 0L;
+	__fs32 block;
+	__fs64 u2_block = 0L;
 	unsigned flags = UFS_SB(sb)->s_flags;
 	u64 temp = 0L;
 
@@ -126,7 +126,7 @@
 		bh = sb_bread(sb, uspi->s_sbbase + fs32_to_cpu(sb, block)+(n>>shift));
 		if (!bh)
 			goto out;
-		block = ((u32*) bh->b_data)[n & mask];
+		block = ((__fs32 *) bh->b_data)[n & mask];
 		brelse (bh);
 		if (!block)
 			goto out;
@@ -148,7 +148,7 @@
 		bh = sb_bread(sb, temp +(u64) (n>>shift));
 		if (!bh)
 			goto out;
-		u2_block = ((u64*)bh->b_data)[n & mask];
+		u2_block = ((__fs64 *)bh->b_data)[n & mask];
 		brelse(bh);
 		if (!u2_block)
 			goto out;
@@ -171,7 +171,7 @@
 	struct buffer_head * result;
 	unsigned block, blockoff, lastfrag, lastblock, lastblockoff;
 	unsigned tmp, goal;
-	u32 * p, * p2;
+	__fs32 * p, * p2;
 	unsigned flags = 0;
 
 	UFSD(("ENTER, ino %lu, fragment %u, new_fragment %u, required %u\n",
@@ -303,7 +303,7 @@
 	struct ufs_sb_private_info * uspi;
 	struct buffer_head * result;
 	unsigned tmp, goal, block, blockoff;
-	u32 * p;
+	__fs32 * p;
 
 	sb = inode->i_sb;
 	uspi = UFS_SB(sb)->s_uspi;
@@ -322,7 +322,7 @@
 			goto out;
 	}
 
-	p = (u32 *) bh->b_data + block;
+	p = (__fs32 *) bh->b_data + block;
 repeat:
 	tmp = fs32_to_cpu(sb, *p);
 	if (tmp) {
@@ -338,7 +338,7 @@
 		}
 	}
 
-	if (block && (tmp = fs32_to_cpu(sb, ((u32*)bh->b_data)[block-1]) + uspi->s_fpb))
+	if (block && (tmp = fs32_to_cpu(sb, ((__fs32*)bh->b_data)[block-1]) + uspi->s_fpb))
 		goal = tmp + uspi->s_fpb;
 	else
 		goal = bh->b_blocknr + uspi->s_fpb;
@@ -788,11 +788,13 @@
 	return 0;
 }
 
-void ufs_write_inode (struct inode * inode, int wait)
+int ufs_write_inode (struct inode * inode, int wait)
 {
+	int ret;
 	lock_kernel();
-	ufs_update_inode (inode, wait);
+	ret = ufs_update_inode (inode, wait);
 	unlock_kernel();
+	return ret;
 }
 
 int ufs_sync_inode (struct inode *inode)
diff -Nru a/fs/ufs/super.c b/fs/ufs/super.c
--- a/fs/ufs/super.c	2004-10-18 14:55:46 -07:00
+++ b/fs/ufs/super.c	2004-10-18 14:55:46 -07:00
@@ -388,7 +388,7 @@
 /*
  * Read on-disk structures associated with cylinder groups
  */
-int ufs_read_cylinder_structures (struct super_block * sb) {
+static int ufs_read_cylinder_structures (struct super_block *sb) {
 	struct ufs_sb_info * sbi = UFS_SB(sb);
 	struct ufs_sb_private_info * uspi;
 	struct ufs_super_block *usb;
@@ -488,7 +488,7 @@
  * Put on-disk structures associated with cylinder groups and 
  * write them back to disk
  */
-void ufs_put_cylinder_structures (struct super_block * sb) {
+static void ufs_put_cylinder_structures (struct super_block *sb) {
 	struct ufs_sb_info * sbi = UFS_SB(sb);
 	struct ufs_sb_private_info * uspi;
 	struct ufs_buffer_head * ubh;
@@ -743,22 +743,22 @@
 	/*
 	 * Check ufs magic number
 	 */
-	switch ((uspi->fs_magic = __constant_le32_to_cpu(usb3->fs_magic))) {
+	sbi->s_bytesex = BYTESEX_LE;
+	switch ((uspi->fs_magic = fs32_to_cpu(sb, usb3->fs_magic))) {
 		case UFS_MAGIC:
 		case UFS2_MAGIC:
 		case UFS_MAGIC_LFN:
 	        case UFS_MAGIC_FEA:
 	        case UFS_MAGIC_4GB:
-			sbi->s_bytesex = BYTESEX_LE;
 			goto magic_found;
 	}
-	switch ((uspi->fs_magic = __constant_be32_to_cpu(usb3->fs_magic))) {
+	sbi->s_bytesex = BYTESEX_BE;
+	switch ((uspi->fs_magic = fs32_to_cpu(sb, usb3->fs_magic))) {
 		case UFS_MAGIC:
 		case UFS2_MAGIC:
 		case UFS_MAGIC_LFN:
 	        case UFS_MAGIC_FEA:
 	        case UFS_MAGIC_4GB:
-			sbi->s_bytesex = BYTESEX_BE;
 			goto magic_found;
 	}
 
@@ -993,7 +993,7 @@
 	return -ENOMEM;
 }
 
-void ufs_write_super (struct super_block * sb) {
+static void ufs_write_super (struct super_block *sb) {
 	struct ufs_sb_private_info * uspi;
 	struct ufs_super_block_first * usb1;
 	struct ufs_super_block_third * usb3;
@@ -1020,7 +1020,7 @@
 	unlock_kernel();
 }
 
-void ufs_put_super (struct super_block * sb)
+static void ufs_put_super (struct super_block *sb)
 {
 	struct ufs_sb_info * sbi = UFS_SB(sb);
 		
@@ -1037,7 +1037,7 @@
 }
 
 
-int ufs_remount (struct super_block * sb, int * mount_flags, char * data)
+static int ufs_remount (struct super_block *sb, int *mount_flags, char *data)
 {
 	struct ufs_sb_private_info * uspi;
 	struct ufs_super_block_first * usb1;
@@ -1112,7 +1112,7 @@
 	return 0;
 }
 
-int ufs_statfs (struct super_block * sb, struct kstatfs * buf)
+static int ufs_statfs (struct super_block *sb, struct kstatfs *buf)
 {
 	struct ufs_sb_private_info * uspi;
 	struct ufs_super_block_first * usb1;
@@ -1129,7 +1129,7 @@
 	flags = UFS_SB(sb)->s_flags;
 	if ((flags & UFS_TYPE_MASK) == UFS_TYPE_UFS2) {
 		buf->f_type = UFS2_MAGIC;
-		buf->f_blocks = usb->fs_u11.fs_u2.fs_dsize;
+		buf->f_blocks = fs64_to_cpu(sb, usb->fs_u11.fs_u2.fs_dsize);
 		buf->f_bfree = ufs_blkstofrags(fs64_to_cpu(sb, usb->fs_u11.fs_u2.fs_cstotal.cs_nbfree)) +
 			fs64_to_cpu(sb, usb->fs_u11.fs_u2.fs_cstotal.cs_nffree);
 		buf->f_ffree = fs64_to_cpu(sb,
@@ -1183,7 +1183,7 @@
 {
 	ufs_inode_cachep = kmem_cache_create("ufs_inode_cache",
 					     sizeof(struct ufs_inode_info),
-					     0, SLAB_HWCACHE_ALIGN|SLAB_RECLAIM_ACCOUNT,
+					     0, SLAB_RECLAIM_ACCOUNT,
 					     init_once, NULL);
 	if (ufs_inode_cachep == NULL)
 		return -ENOMEM;
diff -Nru a/fs/ufs/swab.h b/fs/ufs/swab.h
--- a/fs/ufs/swab.h	2004-10-18 14:57:04 -07:00
+++ b/fs/ufs/swab.h	2004-10-18 14:57:04 -07:00
@@ -22,22 +22,22 @@
 	BYTESEX_BE
 };
 
-static __inline u64
-fs64_to_cpu(struct super_block *sbp, u64 n)
+static inline u64
+fs64_to_cpu(struct super_block *sbp, __fs64 n)
 {
 	if (UFS_SB(sbp)->s_bytesex == BYTESEX_LE)
-		return le64_to_cpu(n);
+		return le64_to_cpu((__force __le64)n);
 	else
-		return be64_to_cpu(n);
+		return be64_to_cpu((__force __be64)n);
 }
 
-static __inline u64
+static inline __fs64
 cpu_to_fs64(struct super_block *sbp, u64 n)
 {
 	if (UFS_SB(sbp)->s_bytesex == BYTESEX_LE)
-		return cpu_to_le64(n);
+		return (__force __fs64)cpu_to_le64(n);
 	else
-		return cpu_to_be64(n);
+		return (__force __fs64)cpu_to_be64(n);
 }
 
 static __inline u32
@@ -59,75 +59,75 @@
 }
 
 static __inline u32
-fs32_to_cpu(struct super_block *sbp, u32 n)
+fs32_to_cpu(struct super_block *sbp, __fs32 n)
 {
 	if (UFS_SB(sbp)->s_bytesex == BYTESEX_LE)
-		return le32_to_cpu(n);
+		return le32_to_cpu((__force __le32)n);
 	else
-		return be32_to_cpu(n);
+		return be32_to_cpu((__force __be32)n);
 }
 
-static __inline u32
+static inline __fs32
 cpu_to_fs32(struct super_block *sbp, u32 n)
 {
 	if (UFS_SB(sbp)->s_bytesex == BYTESEX_LE)
-		return cpu_to_le32(n);
+		return (__force __fs32)cpu_to_le32(n);
 	else
-		return cpu_to_be32(n);
+		return (__force __fs32)cpu_to_be32(n);
 }
 
-static __inline u32
-fs32_add(struct super_block *sbp, u32 *n, int d)
+static inline void
+fs32_add(struct super_block *sbp, __fs32 *n, int d)
 {
 	if (UFS_SB(sbp)->s_bytesex == BYTESEX_LE)
-		return *n = cpu_to_le32(le32_to_cpu(*n)+d);
+		*(__le32 *)n = cpu_to_le32(le32_to_cpu(*(__le32 *)n)+d);
 	else
-		return *n = cpu_to_be32(be32_to_cpu(*n)+d);
+		*(__be32 *)n = cpu_to_be32(be32_to_cpu(*(__be32 *)n)+d);
 }
 
-static __inline u32
-fs32_sub(struct super_block *sbp, u32 *n, int d)
+static inline void
+fs32_sub(struct super_block *sbp, __fs32 *n, int d)
 {
 	if (UFS_SB(sbp)->s_bytesex == BYTESEX_LE)
-		return *n = cpu_to_le32(le32_to_cpu(*n)-d);
+		*(__le32 *)n = cpu_to_le32(le32_to_cpu(*(__le32 *)n)-d);
 	else
-		return *n = cpu_to_be32(be32_to_cpu(*n)-d);
+		*(__be32 *)n = cpu_to_be32(be32_to_cpu(*(__be32 *)n)-d);
 }
 
-static __inline u16
-fs16_to_cpu(struct super_block *sbp, u16 n)
+static inline u16
+fs16_to_cpu(struct super_block *sbp, __fs16 n)
 {
 	if (UFS_SB(sbp)->s_bytesex == BYTESEX_LE)
-		return le16_to_cpu(n);
+		return le16_to_cpu((__force __le16)n);
 	else
-		return be16_to_cpu(n);
+		return be16_to_cpu((__force __be16)n);
 }
 
-static __inline u16
+static inline __fs16
 cpu_to_fs16(struct super_block *sbp, u16 n)
 {
 	if (UFS_SB(sbp)->s_bytesex == BYTESEX_LE)
-		return cpu_to_le16(n);
+		return (__force __fs16)cpu_to_le16(n);
 	else
-		return cpu_to_be16(n);
+		return (__force __fs16)cpu_to_be16(n);
 }
 
-static __inline u16
-fs16_add(struct super_block *sbp, u16 *n, int d)
+static inline void
+fs16_add(struct super_block *sbp, __fs16 *n, int d)
 {
 	if (UFS_SB(sbp)->s_bytesex == BYTESEX_LE)
-		return *n = cpu_to_le16(le16_to_cpu(*n)+d);
+		*(__le16 *)n = cpu_to_le16(le16_to_cpu(*(__le16 *)n)+d);
 	else
-		return *n = cpu_to_be16(be16_to_cpu(*n)+d);
+		*(__be16 *)n = cpu_to_be16(be16_to_cpu(*(__be16 *)n)+d);
 }
 
-static __inline u16
-fs16_sub(struct super_block *sbp, u16 *n, int d)
+static inline void
+fs16_sub(struct super_block *sbp, __fs16 *n, int d)
 {
 	if (UFS_SB(sbp)->s_bytesex == BYTESEX_LE)
-		return *n = cpu_to_le16(le16_to_cpu(*n)-d);
+		*(__le16 *)n = cpu_to_le16(le16_to_cpu(*(__le16 *)n)-d);
 	else
-		return *n = cpu_to_be16(be16_to_cpu(*n)-d);
+		*(__be16 *)n = cpu_to_be16(be16_to_cpu(*(__be16 *)n)-d);
 }
 
 #endif /* _UFS_SWAB_H */
diff -Nru a/fs/ufs/truncate.c b/fs/ufs/truncate.c
--- a/fs/ufs/truncate.c	2004-10-18 14:56:31 -07:00
+++ b/fs/ufs/truncate.c	2004-10-18 14:56:31 -07:00
@@ -74,7 +74,7 @@
 	struct super_block * sb;
 	struct ufs_sb_private_info * uspi;
 	struct buffer_head * bh;
-	u32 * p;
+	__fs32 * p;
 	unsigned frag1, frag2, frag3, frag4, block1, block2;
 	unsigned frag_to_free, free_count;
 	unsigned i, j, tmp;
@@ -199,13 +199,13 @@
 }
 
 
-static int ufs_trunc_indirect (struct inode * inode, unsigned offset, u32 * p)
+static int ufs_trunc_indirect (struct inode * inode, unsigned offset, __fs32 *p)
 {
 	struct super_block * sb;
 	struct ufs_sb_private_info * uspi;
 	struct ufs_buffer_head * ind_ubh;
 	struct buffer_head * bh;
-	u32 * ind;
+	__fs32 * ind;
 	unsigned indirect_block, i, j, tmp;
 	unsigned frag_to_free, free_count;
 	int retry;
@@ -296,13 +296,13 @@
 	return retry;
 }
 
-static int ufs_trunc_dindirect (struct inode * inode, unsigned offset, u32 * p)
+static int ufs_trunc_dindirect (struct inode *inode, unsigned offset, __fs32 *p)
 {
 	struct super_block * sb;
 	struct ufs_sb_private_info * uspi;
 	struct ufs_buffer_head * dind_bh;
 	unsigned i, tmp, dindirect_block;
-	u32 * dind;
+	__fs32 * dind;
 	int retry = 0;
 	
 	UFSD(("ENTER\n"))
@@ -371,7 +371,7 @@
 	struct ufs_sb_private_info * uspi;
 	struct ufs_buffer_head * tind_bh;
 	unsigned tindirect_block, tmp, i;
-	u32 * tind, * p;
+	__fs32 * tind, * p;
 	int retry;
 	
 	UFSD(("ENTER\n"))
@@ -449,9 +449,9 @@
 	while (1) {
 		retry = ufs_trunc_direct(inode);
 		retry |= ufs_trunc_indirect (inode, UFS_IND_BLOCK,
-			(u32 *) &ufsi->i_u1.i_data[UFS_IND_BLOCK]);
+			(__fs32 *) &ufsi->i_u1.i_data[UFS_IND_BLOCK]);
 		retry |= ufs_trunc_dindirect (inode, UFS_IND_BLOCK + uspi->s_apb,
-			(u32 *) &ufsi->i_u1.i_data[UFS_DIND_BLOCK]);
+			(__fs32 *) &ufsi->i_u1.i_data[UFS_DIND_BLOCK]);
 		retry |= ufs_trunc_tindirect (inode);
 		if (!retry)
 			break;
diff -Nru a/fs/ufs/util.h b/fs/ufs/util.h
--- a/fs/ufs/util.h	2004-10-18 14:56:32 -07:00
+++ b/fs/ufs/util.h	2004-10-18 14:56:32 -07:00
@@ -72,20 +72,20 @@
 static inline u64
 ufs_get_fs_qbmask(struct super_block *sb, struct ufs_super_block_third *usb3)
 {
-	u64 tmp;
+	__fs64 tmp;
 
 	switch (UFS_SB(sb)->s_flags & UFS_ST_MASK) {
 	case UFS_ST_SUN:
-		((u32 *)&tmp)[0] = usb3->fs_u2.fs_sun.fs_qbmask[0];
-		((u32 *)&tmp)[1] = usb3->fs_u2.fs_sun.fs_qbmask[1];
+		((__fs32 *)&tmp)[0] = usb3->fs_u2.fs_sun.fs_qbmask[0];
+		((__fs32 *)&tmp)[1] = usb3->fs_u2.fs_sun.fs_qbmask[1];
 		break;
 	case UFS_ST_SUNx86:
-		((u32 *)&tmp)[0] = usb3->fs_u2.fs_sunx86.fs_qbmask[0];
-		((u32 *)&tmp)[1] = usb3->fs_u2.fs_sunx86.fs_qbmask[1];
+		((__fs32 *)&tmp)[0] = usb3->fs_u2.fs_sunx86.fs_qbmask[0];
+		((__fs32 *)&tmp)[1] = usb3->fs_u2.fs_sunx86.fs_qbmask[1];
 		break;
 	case UFS_ST_44BSD:
-		((u32 *)&tmp)[0] = usb3->fs_u2.fs_44.fs_qbmask[0];
-		((u32 *)&tmp)[1] = usb3->fs_u2.fs_44.fs_qbmask[1];
+		((__fs32 *)&tmp)[0] = usb3->fs_u2.fs_44.fs_qbmask[0];
+		((__fs32 *)&tmp)[1] = usb3->fs_u2.fs_44.fs_qbmask[1];
 		break;
 	}
 
@@ -95,20 +95,20 @@
 static inline u64
 ufs_get_fs_qfmask(struct super_block *sb, struct ufs_super_block_third *usb3)
 {
-	u64 tmp;
+	__fs64 tmp;
 
 	switch (UFS_SB(sb)->s_flags & UFS_ST_MASK) {
 	case UFS_ST_SUN:
-		((u32 *)&tmp)[0] = usb3->fs_u2.fs_sun.fs_qfmask[0];
-		((u32 *)&tmp)[1] = usb3->fs_u2.fs_sun.fs_qfmask[1];
+		((__fs32 *)&tmp)[0] = usb3->fs_u2.fs_sun.fs_qfmask[0];
+		((__fs32 *)&tmp)[1] = usb3->fs_u2.fs_sun.fs_qfmask[1];
 		break;
 	case UFS_ST_SUNx86:
-		((u32 *)&tmp)[0] = usb3->fs_u2.fs_sunx86.fs_qfmask[0];
-		((u32 *)&tmp)[1] = usb3->fs_u2.fs_sunx86.fs_qfmask[1];
+		((__fs32 *)&tmp)[0] = usb3->fs_u2.fs_sunx86.fs_qfmask[0];
+		((__fs32 *)&tmp)[1] = usb3->fs_u2.fs_sunx86.fs_qfmask[1];
 		break;
 	case UFS_ST_44BSD:
-		((u32 *)&tmp)[0] = usb3->fs_u2.fs_44.fs_qfmask[0];
-		((u32 *)&tmp)[1] = usb3->fs_u2.fs_44.fs_qfmask[1];
+		((__fs32 *)&tmp)[0] = usb3->fs_u2.fs_44.fs_qfmask[0];
+		((__fs32 *)&tmp)[1] = usb3->fs_u2.fs_44.fs_qfmask[1];
 		break;
 	}
 
@@ -273,11 +273,11 @@
 	((begin) & ~uspi->s_fmask))
 
 #define ubh_get_addr16(ubh,begin) \
-	(((u16*)((ubh)->bh[(begin) >> (uspi->s_fshift-1)]->b_data)) + \
+	(((__fs16*)((ubh)->bh[(begin) >> (uspi->s_fshift-1)]->b_data)) + \
 	((begin) & (uspi->fsize>>1) - 1)))
 
 #define ubh_get_addr32(ubh,begin) \
-	(((u32*)((ubh)->bh[(begin) >> (uspi->s_fshift-2)]->b_data)) + \
+	(((__fs32*)((ubh)->bh[(begin) >> (uspi->s_fshift-2)]->b_data)) + \
 	((begin) & ((uspi->s_fsize>>2) - 1)))
 
 #define ubh_get_addr ubh_get_addr8
@@ -315,10 +315,10 @@
  * Macros to access cylinder group array structures
  */
 #define ubh_cg_blktot(ucpi,cylno) \
-	(*((__u32*)ubh_get_addr(UCPI_UBH, (ucpi)->c_btotoff + ((cylno) << 2))))
+	(*((__fs32*)ubh_get_addr(UCPI_UBH, (ucpi)->c_btotoff + ((cylno) << 2))))
 
 #define ubh_cg_blks(ucpi,cylno,rpos) \
-	(*((__u16*)ubh_get_addr(UCPI_UBH, \
+	(*((__fs16*)ubh_get_addr(UCPI_UBH, \
 	(ucpi)->c_boff + (((cylno) * uspi->s_nrpos + (rpos)) << 1 ))))
 
 /*
@@ -476,7 +476,7 @@
 }
 
 static inline void ufs_fragacct (struct super_block * sb, unsigned blockmap,
-	unsigned * fraglist, int cnt)
+	__fs32 * fraglist, int cnt)
 {
 	struct ufs_sb_private_info * uspi;
 	unsigned fragsize, pos;
diff -Nru a/fs/umsdos/inode.c b/fs/umsdos/inode.c
--- a/fs/umsdos/inode.c	2004-10-18 14:55:55 -07:00
+++ b/fs/umsdos/inode.c	2004-10-18 14:55:55 -07:00
@@ -312,11 +312,12 @@
 /*
  * Update the disk with the inode content
  */
-void UMSDOS_write_inode (struct inode *inode, int wait)
+int UMSDOS_write_inode (struct inode *inode, int wait)
 {
 	struct iattr newattrs;
+	int ret;
 
-	fat_write_inode (inode, wait);
+	ret = fat_write_inode (inode, wait);
 	newattrs.ia_mtime = inode->i_mtime;
 	newattrs.ia_atime = inode->i_atime;
 	newattrs.ia_ctime = inode->i_ctime;
@@ -330,6 +331,7 @@
  * UMSDOS_notify_change (inode, &newattrs);
 
  * inode->i_state &= ~I_DIRTY; / * FIXME: this doesn't work.  We need to remove ourselves from list on dirty inodes. /mn/ */
+	return ret;
 }
 
 
diff -Nru a/fs/vfat/namei.c b/fs/vfat/namei.c
--- a/fs/vfat/namei.c	2004-10-18 14:56:33 -07:00
+++ b/fs/vfat/namei.c	2004-10-18 14:56:33 -07:00
@@ -73,33 +73,6 @@
 	return ret;
 }
 
-static inline unsigned char
-vfat_tolower(struct nls_table *t, unsigned char c)
-{
-	unsigned char nc = t->charset2lower[c];
-
-	return nc ? nc : c;
-}
-
-static inline unsigned char
-vfat_toupper(struct nls_table *t, unsigned char c)
-{
-	unsigned char nc = t->charset2upper[c];
-
-	return nc ? nc : c;
-}
-
-static inline int
-vfat_strnicmp(struct nls_table *t, const unsigned char *s1,
-					const unsigned char *s2, int len)
-{
-	while(len--)
-		if (vfat_tolower(t, *s1++) != vfat_tolower(t, *s2++))
-			return 1;
-
-	return 0;
-}
-
 /* returns the length of a struct qstr, ignoring trailing dots */
 static unsigned int vfat_striptail_len(struct qstr *qstr)
 {
@@ -142,7 +115,7 @@
 
 	hash = init_name_hash();
 	while (len--)
-		hash = partial_name_hash(vfat_tolower(t, *name++), hash);
+		hash = partial_name_hash(nls_tolower(t, *name++), hash);
 	qstr->hash = end_name_hash(hash);
 
 	return 0;
@@ -160,7 +133,7 @@
 	alen = vfat_striptail_len(a);
 	blen = vfat_striptail_len(b);
 	if (alen == blen) {
-		if (vfat_strnicmp(t, a->name, b->name, alen) == 0)
+		if (nls_strnicmp(t, a->name, b->name, alen) == 0)
 			return 0;
 	}
 	return 1;
@@ -341,7 +314,7 @@
 			info->upper = 0;
 		}
 
-		buf[0] = vfat_toupper(nls, buf[0]);
+		buf[0] = nls_toupper(nls, buf[0]);
 		if (isalpha(buf[0])) {
 			if (buf[0] == prev)
 				info->lower = 0;
@@ -704,7 +677,8 @@
 	de->attr = is_dir ? ATTR_DIR : ATTR_ARCH;
 	de->lcase = lcase;
 	de->adate = de->cdate = de->date = 0;
-	de->ctime_ms = de->ctime = de->time = 0;
+	de->ctime = de->time = 0;
+	de->ctime_ms = 0;
 	de->start = 0;
 	de->starthi = 0;
 	de->size = 0;
@@ -1073,8 +1047,8 @@
 
 	if (is_dir) {
 		int start = MSDOS_I(new_dir)->i_logstart;
-		dotdot_de->start = CT_LE_W(start);
-		dotdot_de->starthi = CT_LE_W(start>>16);
+		dotdot_de->start = cpu_to_le16(start);
+		dotdot_de->starthi = cpu_to_le16(start>>16);
 		mark_buffer_dirty(dotdot_bh);
 		old_dir->i_nlink--;
 		if (new_inode) {
diff -Nru a/fs/xfs/Makefile b/fs/xfs/Makefile
--- a/fs/xfs/Makefile	2004-10-18 14:56:48 -07:00
+++ b/fs/xfs/Makefile	2004-10-18 14:56:48 -07:00
@@ -67,10 +67,9 @@
 
 xfs-$(CONFIG_XFS_RT)		+= xfs_rtalloc.o
 xfs-$(CONFIG_XFS_POSIX_ACL)	+= xfs_acl.o
-xfs-$(CONFIG_XFS_POSIX_CAP)	+= xfs_cap.o
-xfs-$(CONFIG_XFS_POSIX_MAC)	+= xfs_mac.o
 xfs-$(CONFIG_PROC_FS)		+= linux-2.6/xfs_stats.o
 xfs-$(CONFIG_SYSCTL)		+= linux-2.6/xfs_sysctl.o
+xfs-$(CONFIG_COMPAT)		+= linux-2.6/xfs_ioctl32.o
 
 
 xfs-y				+= xfs_alloc.o \
diff -Nru a/fs/xfs/linux-2.6/xfs_aops.c b/fs/xfs/linux-2.6/xfs_aops.c
--- a/fs/xfs/linux-2.6/xfs_aops.c	2004-10-18 14:57:03 -07:00
+++ b/fs/xfs/linux-2.6/xfs_aops.c	2004-10-18 14:57:03 -07:00
@@ -234,6 +234,7 @@
 	sector_shift = block_bits - BBSHIFT;
 	bn = iomapp->iomap_bn >> sector_shift;
 	bn += delta;
+	BUG_ON(!bn && !(iomapp->iomap_flags & IOMAP_REALTIME));
 	ASSERT((bn << sector_shift) >= iomapp->iomap_bn);
 
 	lock_buffer(bh);
@@ -264,7 +265,7 @@
 
 	page = find_trylock_page(mapping, index);
 	if (!page)
-		return 0;
+		return NULL;
 	if (PageWriteback(page))
 		goto out;
 
@@ -549,19 +550,23 @@
 STATIC void
 xfs_submit_page(
 	struct page		*page,
+	struct writeback_control *wbc,
 	struct buffer_head	*bh_arr[],
-	int			cnt)
+	int			bh_count,
+	int			probed_page,
+	int			clear_dirty)
 {
 	struct buffer_head	*bh;
 	int			i;
 
 	BUG_ON(PageWriteback(page));
 	set_page_writeback(page);
-	clear_page_dirty(page);
+	if (clear_dirty)
+		clear_page_dirty(page);
 	unlock_page(page);
 
-	if (cnt) {
-		for (i = 0; i < cnt; i++) {
+	if (bh_count) {
+		for (i = 0; i < bh_count; i++) {
 			bh = bh_arr[i];
 			mark_buffer_async_write(bh);
 			if (buffer_unwritten(bh))
@@ -570,10 +575,15 @@
 			clear_buffer_dirty(bh);
 		}
 
-		for (i = 0; i < cnt; i++)
+		for (i = 0; i < bh_count; i++)
 			submit_bh(WRITE, bh_arr[i]);
-	} else
+
+		if (probed_page && clear_dirty)
+			wbc->nr_to_write--;	/* Wrote an "extra" page */
+	} else {
 		end_page_writeback(page);
+		wbc->pages_skipped++;	/* We didn't write this page */
+	}
 }
 
 /*
@@ -608,11 +618,13 @@
 	bh = head = page_buffers(page);
 	do {
 		offset = i << bbits;
+		if (offset >= end)
+			break;
 		if (!(PageUptodate(page) || buffer_uptodate(bh)))
 			continue;
 		if (buffer_mapped(bh) && all_bh &&
-		    !buffer_unwritten(bh) && !buffer_delay(bh)) {
-			if (startio && (offset < end)) {
+		    !(buffer_unwritten(bh) || buffer_delay(bh))) {
+			if (startio) {
 				lock_buffer(bh);
 				bh_arr[index++] = bh;
 			}
@@ -640,7 +652,7 @@
 				ASSERT(private);
 			}
 		}
-		if (startio && (offset < end)) {
+		if (startio) {
 			bh_arr[index++] = bh;
 		} else {
 			set_buffer_dirty(bh);
@@ -650,8 +662,7 @@
 	} while (i++, (bh = bh->b_this_page) != head);
 
 	if (startio) {
-		wbc->nr_to_write--;
-		xfs_submit_page(page, bh_arr, index);
+		xfs_submit_page(page, wbc, bh_arr, index, 1, index == i);
 	} else {
 		unlock_page(page);
 	}
@@ -863,7 +874,7 @@
 		SetPageUptodate(page);
 
 	if (startio)
-		xfs_submit_page(page, bh_arr, cnt);
+		xfs_submit_page(page, wbc, bh_arr, cnt, 0, 1);
 
 	if (iomp) {
 		tlast = (iomp->iomap_offset + iomp->iomap_bsize - 1) >>
@@ -938,9 +949,8 @@
 
 			bn = iomap.iomap_bn >> (inode->i_blkbits - BBSHIFT);
 			bn += delta;
-
+			BUG_ON(!bn && !(iomap.iomap_flags & IOMAP_REALTIME));
 			bh_result->b_blocknr = bn;
-			bh_result->b_bdev = iomap.iomap_target->pbr_bdev;
 			set_buffer_mapped(bh_result);
 		}
 		if (create && (iomap.iomap_flags & IOMAP_UNWRITTEN)) {
@@ -965,21 +975,18 @@
 	}
 
 	if (iomap.iomap_flags & IOMAP_DELAY) {
-		if (unlikely(direct))
-			BUG();
+		BUG_ON(direct);
 		if (create) {
 			set_buffer_mapped(bh_result);
 			set_buffer_uptodate(bh_result);
 		}
-		bh_result->b_bdev = iomap.iomap_target->pbr_bdev;
 		set_buffer_delay(bh_result);
 	}
 
 	if (blocks) {
-		loff_t iosize;
-		iosize = (iomap.iomap_bsize - iomap.iomap_delta);
-		bh_result->b_size =
-		    (ssize_t)min(iosize, (loff_t)(blocks << inode->i_blkbits));
+		bh_result->b_size = (ssize_t)min(
+			(loff_t)(iomap.iomap_bsize - iomap.iomap_delta),
+			(loff_t)(blocks << inode->i_blkbits));
 	}
 
 	return 0;
@@ -997,17 +1004,6 @@
 }
 
 STATIC int
-linvfs_get_block_sync(
-	struct inode		*inode,
-	sector_t		iblock,
-	struct buffer_head	*bh_result,
-	int			create)
-{
-	return linvfs_get_block_core(inode, iblock, 0, bh_result,
-					create, 0, BMAPI_SYNC|BMAPI_WRITE);
-}
-
-STATIC int
 linvfs_get_blocks_direct(
 	struct inode		*inode,
 	sector_t		iblock,
@@ -1038,7 +1034,7 @@
 	if (error)
 		return -error;
 
-	return blockdev_direct_IO_no_locking(rw, iocb, inode,
+	return blockdev_direct_IO_own_locking(rw, iocb, inode,
 		iomap.iomap_target->pbr_bdev,
 		iov, offset, nr_segs,
 		linvfs_get_blocks_direct,
@@ -1185,7 +1181,7 @@
 	return 0;
 
 out_fail:
-	set_page_dirty(page);
+	redirty_page_for_writepage(wbc, page);
 	unlock_page(page);
 	return 0;
 out_unlock:
@@ -1261,13 +1257,7 @@
 	unsigned int		from,
 	unsigned int		to)
 {
-	if (file && (file->f_flags & O_SYNC)) {
-		return block_prepare_write(page, from, to,
-						linvfs_get_block_sync);
-	} else {
-		return block_prepare_write(page, from, to,
-						linvfs_get_block);
-	}
+	return block_prepare_write(page, from, to, linvfs_get_block);
 }
 
 struct address_space_operations linvfs_aops = {
diff -Nru a/fs/xfs/linux-2.6/xfs_buf.c b/fs/xfs/linux-2.6/xfs_buf.c
--- a/fs/xfs/linux-2.6/xfs_buf.c	2004-10-18 14:55:54 -07:00
+++ b/fs/xfs/linux-2.6/xfs_buf.c	2004-10-18 14:55:54 -07:00
@@ -626,11 +626,8 @@
 	pb = _pagebuf_find(target, ioff, isize, flags, new_pb);
 	if (pb == new_pb) {
 		error = _pagebuf_lookup_pages(pb, flags);
-		if (unlikely(error)) {
-			printk(KERN_WARNING
-			       "pagebuf_get: failed to lookup pages\n");
+		if (error)
 			goto no_buffer;
-		}
 	} else {
 		pagebuf_deallocate(new_pb);
 		if (unlikely(pb == NULL))
@@ -1484,6 +1481,7 @@
 	xfs_flush_buftarg(btp, 1);
 	if (external)
 		xfs_blkdev_put(btp->pbr_bdev);
+	iput(btp->pbr_mapping->host);
 	kmem_free(btp, sizeof(*btp));
 }
 
@@ -1497,7 +1495,7 @@
 	truncate_inode_pages(btp->pbr_mapping, 0LL);
 }
 
-void
+int
 xfs_setsize_buftarg(
 	xfs_buftarg_t		*btp,
 	unsigned int		blocksize,
@@ -1511,7 +1509,42 @@
 		printk(KERN_WARNING
 			"XFS: Cannot set_blocksize to %u on device %s\n",
 			sectorsize, XFS_BUFTARG_NAME(btp));
+		return EINVAL;
 	}
+	return 0;
+}
+
+STATIC int
+xfs_mapping_buftarg(
+	xfs_buftarg_t		*btp,
+	struct block_device	*bdev)
+{
+	struct backing_dev_info	*bdi;
+	struct inode		*inode;
+	struct address_space	*mapping;
+	static struct address_space_operations mapping_aops = {
+		.sync_page = block_sync_page,
+	};
+
+	inode = new_inode(bdev->bd_inode->i_sb);
+	if (!inode) {
+		printk(KERN_WARNING
+			"XFS: Cannot allocate mapping inode for device %s\n",
+			XFS_BUFTARG_NAME(btp));
+		return ENOMEM;
+	}
+	inode->i_mode = S_IFBLK;
+	inode->i_bdev = bdev;
+	inode->i_rdev = bdev->bd_dev;
+	bdi = blk_get_backing_dev_info(bdev);
+	if (!bdi)
+		bdi = &default_backing_dev_info;
+	mapping = &inode->i_data;
+	mapping->a_ops = &mapping_aops;
+	mapping->backing_dev_info = bdi;
+	mapping_set_gfp_mask(mapping, GFP_KERNEL);
+	btp->pbr_mapping = mapping;
+	return 0;
 }
 
 xfs_buftarg_t *
@@ -1524,10 +1557,15 @@
 
 	btp->pbr_dev =  bdev->bd_dev;
 	btp->pbr_bdev = bdev;
-	btp->pbr_mapping = bdev->bd_inode->i_mapping;
-	xfs_setsize_buftarg(btp, PAGE_CACHE_SIZE, bdev_hardsect_size(bdev));
-
+	if (xfs_setsize_buftarg(btp, PAGE_CACHE_SIZE, bdev_hardsect_size(bdev)))
+		goto error;
+	if (xfs_mapping_buftarg(btp, bdev))
+		goto error;
 	return btp;
+
+error:
+	kmem_free(btp, sizeof(*btp));
+	return NULL;
 }
 
 
diff -Nru a/fs/xfs/linux-2.6/xfs_buf.h b/fs/xfs/linux-2.6/xfs_buf.h
--- a/fs/xfs/linux-2.6/xfs_buf.h	2004-10-18 14:56:33 -07:00
+++ b/fs/xfs/linux-2.6/xfs_buf.h	2004-10-18 14:56:33 -07:00
@@ -566,7 +566,7 @@
 
 extern xfs_buftarg_t *xfs_alloc_buftarg(struct block_device *);
 extern void xfs_free_buftarg(xfs_buftarg_t *, int);
-extern void xfs_setsize_buftarg(xfs_buftarg_t *, unsigned int, unsigned int);
+extern int xfs_setsize_buftarg(xfs_buftarg_t *, unsigned int, unsigned int);
 extern void xfs_incore_relse(xfs_buftarg_t *, int, int);
 extern int xfs_flush_buftarg(xfs_buftarg_t *, int);
 
diff -Nru a/fs/xfs/linux-2.6/xfs_file.c b/fs/xfs/linux-2.6/xfs_file.c
--- a/fs/xfs/linux-2.6/xfs_file.c	2004-10-18 14:56:32 -07:00
+++ b/fs/xfs/linux-2.6/xfs_file.c	2004-10-18 14:56:32 -07:00
@@ -61,7 +61,7 @@
 STATIC inline ssize_t
 __linvfs_read(
 	struct kiocb		*iocb,
-	char __user		*buf,
+	char			__user *buf,
 	int			ioflags,
 	size_t			count,
 	loff_t			pos)
@@ -83,7 +83,7 @@
 STATIC ssize_t
 linvfs_read(
 	struct kiocb		*iocb,
-	char __user		*buf,
+	char			__user *buf,
 	size_t			count,
 	loff_t			pos)
 {
@@ -93,7 +93,7 @@
 STATIC ssize_t
 linvfs_read_invis(
 	struct kiocb		*iocb,
-	char __user		*buf,
+	char			__user *buf,
 	size_t			count,
 	loff_t			pos)
 {
@@ -104,29 +104,22 @@
 STATIC inline ssize_t
 __linvfs_write(
 	struct kiocb	*iocb,
-	const char 	*buf,
+	const char	__user *buf,
 	int		ioflags,
 	size_t		count,
 	loff_t		pos)
 {
-	struct iovec	iov = {(void *)buf, count};
+	struct iovec	iov = {(void __user *)buf, count};
 	struct file	*file = iocb->ki_filp;
 	struct inode	*inode = file->f_mapping->host;
 	vnode_t		*vp = LINVFS_GET_VP(inode);
 	ssize_t		rval;
 
 	BUG_ON(iocb->ki_pos != pos);
-	if (unlikely(file->f_flags & O_DIRECT)) {
+	if (unlikely(file->f_flags & O_DIRECT))
 		ioflags |= IO_ISDIRECT;
-		VOP_WRITE(vp, iocb, &iov, 1, &iocb->ki_pos,
-				ioflags, NULL, rval);
-	} else {
-		down(&inode->i_sem);
-		VOP_WRITE(vp, iocb, &iov, 1, &iocb->ki_pos,
-				ioflags, NULL, rval);
-		up(&inode->i_sem);
-	}
 
+	VOP_WRITE(vp, iocb, &iov, 1, &iocb->ki_pos, ioflags, NULL, rval);
 	return rval;
 }
 
@@ -134,7 +127,7 @@
 STATIC ssize_t
 linvfs_write(
 	struct kiocb		*iocb,
-	const char __user	*buf,
+	const char		__user *buf,
 	size_t			count,
 	loff_t			pos)
 {
@@ -144,7 +137,7 @@
 STATIC ssize_t
 linvfs_write_invis(
 	struct kiocb		*iocb,
-	const char __user	*buf,
+	const char		__user *buf,
 	size_t			count,
 	loff_t			pos)
 {
@@ -171,8 +164,6 @@
 	if (unlikely(file->f_flags & O_DIRECT))
 		ioflags |= IO_ISDIRECT;
 	VOP_READ(vp, &kiocb, iov, nr_segs, &kiocb.ki_pos, ioflags, NULL, rval);
-	if (rval == -EIOCBQUEUED)
-		rval = wait_on_sync_kiocb(&kiocb);
 
 	*ppos = kiocb.ki_pos;
 	return rval;
@@ -214,19 +205,10 @@
 
 	init_sync_kiocb(&kiocb, file);
 	kiocb.ki_pos = *ppos;
-	if (unlikely(file->f_flags & O_DIRECT)) {
+	if (unlikely(file->f_flags & O_DIRECT))
 		ioflags |= IO_ISDIRECT;
-		VOP_WRITE(vp, &kiocb, iov, nr_segs, &kiocb.ki_pos,
-				ioflags, NULL, rval);
-	} else {
-		down(&inode->i_sem);
-		VOP_WRITE(vp, &kiocb, iov, nr_segs, &kiocb.ki_pos,
-				ioflags, NULL, rval);
-		up(&inode->i_sem);
-	}
 
-	if (rval == -EIOCBQUEUED)
-		rval = wait_on_sync_kiocb(&kiocb);
+	VOP_WRITE(vp, &kiocb, iov, nr_segs, &kiocb.ki_pos, ioflags, NULL, rval);
 
 	*ppos = kiocb.ki_pos;
 	return rval;
@@ -427,6 +409,8 @@
 	vma->vm_ops = &linvfs_file_vm_ops;
 
 	VOP_SETATTR(vp, &va, XFS_AT_UPDATIME, NULL, error);
+	if (!error)
+		vn_revalidate(vp);	/* update Linux inode flags */
 	return 0;
 }
 
@@ -442,7 +426,7 @@
 	vnode_t		*vp = LINVFS_GET_VP(inode);
 
 	unlock_kernel();
-	VOP_IOCTL(vp, inode, filp, 0, cmd, arg, error);
+	VOP_IOCTL(vp, inode, filp, 0, cmd, (void __user *)arg, error);
 	VMODIFY(vp);
 	lock_kernel();
 
@@ -467,7 +451,7 @@
 
 	unlock_kernel();
 	ASSERT(vp);
-	VOP_IOCTL(vp, inode, filp, IO_INVIS, cmd, arg, error);
+	VOP_IOCTL(vp, inode, filp, IO_INVIS, cmd, (void __user *)arg, error);
 	VMODIFY(vp);
 	lock_kernel();
 
diff -Nru a/fs/xfs/linux-2.6/xfs_fs_subr.h b/fs/xfs/linux-2.6/xfs_fs_subr.h
--- a/fs/xfs/linux-2.6/xfs_fs_subr.h	2004-10-18 14:56:48 -07:00
+++ b/fs/xfs/linux-2.6/xfs_fs_subr.h	2004-10-18 14:56:48 -07:00
@@ -40,7 +40,6 @@
 
 extern int	fs_noerr(void);
 extern int	fs_nosys(void);
-extern int	fs_nodev(void);
 extern void	fs_noval(void);
 extern void	fs_tosspages(bhv_desc_t *, xfs_off_t, xfs_off_t, int);
 extern void	fs_flushinval_pages(bhv_desc_t *, xfs_off_t, xfs_off_t, int);
diff -Nru a/fs/xfs/linux-2.6/xfs_globals.c b/fs/xfs/linux-2.6/xfs_globals.c
--- a/fs/xfs/linux-2.6/xfs_globals.c	2004-10-18 14:56:33 -07:00
+++ b/fs/xfs/linux-2.6/xfs_globals.c	2004-10-18 14:56:33 -07:00
@@ -63,6 +63,7 @@
 	.inherit_noatim = {	0,		1,		1	},
 	.xfs_buf_timer	= {	100/2,		1*100,		30*100	},
 	.xfs_buf_age	= {	1*100,		15*100,		7200*100},
+	.inherit_nosym	= {	0,		0,		1	},
 };
 
 /*
diff -Nru a/fs/xfs/linux-2.6/xfs_ioctl.c b/fs/xfs/linux-2.6/xfs_ioctl.c
--- a/fs/xfs/linux-2.6/xfs_ioctl.c	2004-10-18 14:56:49 -07:00
+++ b/fs/xfs/linux-2.6/xfs_ioctl.c	2004-10-18 14:56:49 -07:00
@@ -73,14 +73,6 @@
 #include <linux/pagemap.h>
 
 /*
- * ioctl commands that are used by Linux filesystems
- */
-#define XFS_IOC_GETXFLAGS	_IOR('f', 1, long)
-#define XFS_IOC_SETXFLAGS	_IOW('f', 2, long)
-#define XFS_IOC_GETVERSION	_IOR('v', 1, long)
-
-
-/*
  * xfs_find_handle maps from userspace xfs_fsop_handlereq structure to
  * a file or fs handle.
  *
@@ -94,7 +86,7 @@
 STATIC int
 xfs_find_handle(
 	unsigned int		cmd,
-	unsigned long		arg)
+	void			__user *arg)
 {
 	int			hsize;
 	xfs_handle_t		handle;
@@ -102,7 +94,7 @@
 	struct inode		*inode;
 	struct vnode		*vp;
 
-	if (copy_from_user(&hreq, (xfs_fsop_handlereq_t *)arg, sizeof(hreq)))
+	if (copy_from_user(&hreq, arg, sizeof(hreq)))
 		return -XFS_ERROR(EFAULT);
 
 	memset((char *)&handle, 0, sizeof(handle));
@@ -113,7 +105,7 @@
 		struct nameidata	nd;
 		int			error;
 
-		error = user_path_walk_link(hreq.path, &nd);
+		error = user_path_walk_link((const char __user *)hreq.path, &nd);
 		if (error)
 			return error;
 
@@ -185,7 +177,7 @@
 	}
 
 	/* now copy our handle into the user buffer & write out the size */
-	if (copy_to_user((xfs_handle_t *)hreq.ohandle, &handle, hsize) ||
+	if (copy_to_user(hreq.ohandle, &handle, hsize) ||
 	    copy_to_user(hreq.ohandlen, &hsize, sizeof(__s32))) {
 		iput(inode);
 		return -XFS_ERROR(EFAULT);
@@ -211,14 +203,14 @@
 	xfs_mount_t		*mp,
 	struct inode		*parinode,	/* parent inode pointer    */
 	int			cap,		/* capability level for op */
-	unsigned long		arg,		/* userspace data pointer  */
+	void			__user *arg,	/* userspace data pointer  */
 	unsigned long		size,		/* size of expected struct */
 	/* output arguments */
 	xfs_fsop_handlereq_t	*hreq,
 	vnode_t			**vp,
 	struct inode		**inode)
 {
-	void			*hanp;
+	void			__user *hanp;
 	size_t			hlen;
 	xfs_fid_t		*xfid;
 	xfs_handle_t		*handlep;
@@ -243,7 +235,7 @@
 	 * Copy the handle down from the user and validate
 	 * that it looks to be in the correct format.
 	 */
-	if (copy_from_user(hreq, (struct xfs_fsop_handlereq *)arg, size))
+	if (copy_from_user(hreq, arg, size))
 		return XFS_ERROR(EFAULT);
 
 	hanp = hreq->ihandle;
@@ -300,7 +292,7 @@
 STATIC int
 xfs_open_by_handle(
 	xfs_mount_t		*mp,
-	unsigned long		arg,
+	void			__user *arg,
 	struct file		*parfilp,
 	struct inode		*parinode)
 {
@@ -383,7 +375,7 @@
 STATIC int
 xfs_readlink_by_handle(
 	xfs_mount_t		*mp,
-	unsigned long		arg,
+	void			__user *arg,
 	struct file		*parfilp,
 	struct inode		*parinode)
 {
@@ -429,7 +421,7 @@
 STATIC int
 xfs_fssetdm_by_handle(
 	xfs_mount_t		*mp,
-	unsigned long		arg,
+	void			__user *arg,
 	struct file		*parfilp,
 	struct inode		*parinode)
 {
@@ -469,7 +461,7 @@
 STATIC int
 xfs_attrlist_by_handle(
 	xfs_mount_t		*mp,
-	unsigned long		arg,
+	void			__user *arg,
 	struct file		*parfilp,
 	struct inode		*parinode)
 {
@@ -498,7 +490,7 @@
 STATIC int
 xfs_attrmulti_by_handle(
 	xfs_mount_t		*mp,
-	unsigned long		arg,
+	void			__user *arg,
 	struct file		*parfilp,
 	struct inode		*parinode)
 {
@@ -577,23 +569,23 @@
 	struct file		*filp,
 	int			flags,
 	unsigned int		cmd,
-	unsigned long		arg);
+	void			__user *arg);
 
 STATIC int
 xfs_ioc_bulkstat(
 	xfs_mount_t		*mp,
 	unsigned int		cmd,
-	unsigned long		arg);
+	void			__user *arg);
 
 STATIC int
 xfs_ioc_fsgeometry_v1(
 	xfs_mount_t		*mp,
-	unsigned long		arg);
+	void			__user *arg);
 
 STATIC int
 xfs_ioc_fsgeometry(
 	xfs_mount_t		*mp,
-	unsigned long		arg);
+	void			__user *arg);
 
 STATIC int
 xfs_ioc_xattr(
@@ -601,7 +593,7 @@
 	xfs_inode_t		*ip,
 	struct file		*filp,
 	unsigned int		cmd,
-	unsigned long		arg);
+	void			__user *arg);
 
 STATIC int
 xfs_ioc_getbmap(
@@ -609,12 +601,12 @@
 	struct file		*filp,
 	int			flags,
 	unsigned int		cmd,
-	unsigned long		arg);
+	void			__user *arg);
 
 STATIC int
 xfs_ioc_getbmapx(
 	bhv_desc_t		*bdp,
-	unsigned long		arg);
+	void			__user *arg);
 
 int
 xfs_ioctl(
@@ -623,7 +615,7 @@
 	struct file		*filp,
 	int			ioflags,
 	unsigned int		cmd,
-	unsigned long		arg)
+	void			__user *arg)
 {
 	int			error;
 	vnode_t			*vp;
@@ -667,7 +659,7 @@
 		/* The size dio will do in one go */
 		da.d_maxiosz = 64 * PAGE_CACHE_SIZE;
 
-		if (copy_to_user((struct dioattr *)arg, &da, sizeof(da)))
+		if (copy_to_user(arg, &da, sizeof(da)))
 			return -XFS_ERROR(EFAULT);
 		return 0;
 	}
@@ -694,7 +686,7 @@
 	case XFS_IOC_FSSETDM: {
 		struct fsdmidata	dmi;
 
-		if (copy_from_user(&dmi, (struct fsdmidata *)arg, sizeof(dmi)))
+		if (copy_from_user(&dmi, arg, sizeof(dmi)))
 			return -XFS_ERROR(EFAULT);
 
 		error = xfs_set_dmattrs(bdp, dmi.fsd_dmevmask, dmi.fsd_dmstate,
@@ -730,7 +722,7 @@
 		return xfs_attrmulti_by_handle(mp, arg, filp, inode);
 
 	case XFS_IOC_SWAPEXT: {
-		error = xfs_swapext((struct xfs_swapext *)arg);
+		error = xfs_swapext((struct xfs_swapext __user *)arg);
 		return -error;
 	}
 
@@ -741,7 +733,7 @@
 		if (error)
 			return -error;
 
-		if (copy_to_user((char *)arg, &out, sizeof(out)))
+		if (copy_to_user(arg, &out, sizeof(out)))
 			return -XFS_ERROR(EFAULT);
 		return 0;
 	}
@@ -753,7 +745,7 @@
 		if (!capable(CAP_SYS_ADMIN))
 			return -EPERM;
 
-		if (copy_from_user(&inout, (char *)arg, sizeof(inout)))
+		if (copy_from_user(&inout, arg, sizeof(inout)))
 			return -XFS_ERROR(EFAULT);
 
 		/* input parameter is passed in resblks field of structure */
@@ -762,7 +754,7 @@
 		if (error)
 			return -error;
 
-		if (copy_to_user((char *)arg, &inout, sizeof(inout)))
+		if (copy_to_user(arg, &inout, sizeof(inout)))
 			return -XFS_ERROR(EFAULT);
 		return 0;
 	}
@@ -777,7 +769,7 @@
 		if (error)
 			return -error;
 
-		if (copy_to_user((char *)arg, &out, sizeof(out)))
+		if (copy_to_user(arg, &out, sizeof(out)))
 			return -XFS_ERROR(EFAULT);
 
 		return 0;
@@ -789,7 +781,7 @@
 		if (!capable(CAP_SYS_ADMIN))
 			return -EPERM;
 
-		if (copy_from_user(&in, (char *)arg, sizeof(in)))
+		if (copy_from_user(&in, arg, sizeof(in)))
 			return -XFS_ERROR(EFAULT);
 
 		error = xfs_growfs_data(mp, &in);
@@ -802,7 +794,7 @@
 		if (!capable(CAP_SYS_ADMIN))
 			return -EPERM;
 
-		if (copy_from_user(&in, (char *)arg, sizeof(in)))
+		if (copy_from_user(&in, arg, sizeof(in)))
 			return -XFS_ERROR(EFAULT);
 
 		error = xfs_growfs_log(mp, &in);
@@ -815,7 +807,7 @@
 		if (!capable(CAP_SYS_ADMIN))
 			return -EPERM;
 
-		if (copy_from_user(&in, (char *)arg, sizeof(in)))
+		if (copy_from_user(&in, arg, sizeof(in)))
 			return -XFS_ERROR(EFAULT);
 
 		error = xfs_growfs_rt(mp, &in);
@@ -826,13 +818,15 @@
 		if (!capable(CAP_SYS_ADMIN))
 			return -EPERM;
 
-		freeze_bdev(inode->i_sb->s_bdev);
+		if (inode->i_sb->s_frozen == SB_UNFROZEN)
+			freeze_bdev(inode->i_sb->s_bdev);
 		return 0;
 
 	case XFS_IOC_THAW:
 		if (!capable(CAP_SYS_ADMIN))
 			return -EPERM;
-		thaw_bdev(inode->i_sb->s_bdev, inode->i_sb);
+		if (inode->i_sb->s_frozen != SB_UNFROZEN)
+			thaw_bdev(inode->i_sb->s_bdev, inode->i_sb);
 		return 0;
 
 	case XFS_IOC_GOINGDOWN: {
@@ -841,7 +835,7 @@
 		if (!capable(CAP_SYS_ADMIN))
 			return -EPERM;
 
-		if (get_user(in, (__uint32_t *)arg))
+		if (get_user(in, (__uint32_t __user *)arg))
 			return -XFS_ERROR(EFAULT);
 
 		error = xfs_fs_goingdown(mp, in);
@@ -854,7 +848,7 @@
 		if (!capable(CAP_SYS_ADMIN))
 			return -EPERM;
 
-		if (copy_from_user(&in, (char *)arg, sizeof(in)))
+		if (copy_from_user(&in, arg, sizeof(in)))
 			return -XFS_ERROR(EFAULT);
 
 		error = xfs_errortag_add(in.errtag, mp);
@@ -880,7 +874,7 @@
 	struct file		*filp,
 	int			ioflags,
 	unsigned int		cmd,
-	unsigned long		arg)
+	void			__user *arg)
 {
 	xfs_flock64_t		bf;
 	int			attr_flags = 0;
@@ -895,7 +889,7 @@
 	if (vp->v_type != VREG)
 		return -XFS_ERROR(EINVAL);
 
-	if (copy_from_user(&bf, (xfs_flock64_t *)arg, sizeof(bf)))
+	if (copy_from_user(&bf, arg, sizeof(bf)))
 		return -XFS_ERROR(EFAULT);
 
 	if (filp->f_flags & (O_NDELAY|O_NONBLOCK))
@@ -912,7 +906,7 @@
 xfs_ioc_bulkstat(
 	xfs_mount_t		*mp,
 	unsigned int		cmd,
-	unsigned long		arg)
+	void			__user *arg)
 {
 	xfs_fsop_bulkreq_t	bulkreq;
 	int			count;	/* # of records returned */
@@ -929,12 +923,10 @@
 	if (XFS_FORCED_SHUTDOWN(mp))
 		return -XFS_ERROR(EIO);
 
-	if (copy_from_user(&bulkreq, (xfs_fsop_bulkreq_t *)arg,
-					sizeof(xfs_fsop_bulkreq_t)))
+	if (copy_from_user(&bulkreq, arg, sizeof(xfs_fsop_bulkreq_t)))
 		return -XFS_ERROR(EFAULT);
 
-	if (copy_from_user(&inlast, (__s64 *)bulkreq.lastip,
-						sizeof(__s64)))
+	if (copy_from_user(&inlast, bulkreq.lastip, sizeof(__s64)))
 		return -XFS_ERROR(EFAULT);
 
 	if ((count = bulkreq.icount) <= 0)
@@ -963,12 +955,11 @@
 		return -error;
 
 	if (bulkreq.ocount != NULL) {
-		if (copy_to_user((xfs_ino_t *)bulkreq.lastip, &inlast,
+		if (copy_to_user(bulkreq.lastip, &inlast,
 						sizeof(xfs_ino_t)))
 			return -XFS_ERROR(EFAULT);
 
-		if (copy_to_user((__s32 *)bulkreq.ocount, &count,
-						sizeof(count)))
+		if (copy_to_user(bulkreq.ocount, &count, sizeof(count)))
 			return -XFS_ERROR(EFAULT);
 	}
 
@@ -978,7 +969,7 @@
 STATIC int
 xfs_ioc_fsgeometry_v1(
 	xfs_mount_t		*mp,
-	unsigned long		arg)
+	void			__user *arg)
 {
 	xfs_fsop_geom_v1_t	fsgeo;
 	int			error;
@@ -987,7 +978,7 @@
 	if (error)
 		return -error;
 
-	if (copy_to_user((xfs_fsop_geom_t *)arg, &fsgeo, sizeof(fsgeo)))
+	if (copy_to_user(arg, &fsgeo, sizeof(fsgeo)))
 		return -XFS_ERROR(EFAULT);
 	return 0;
 }
@@ -995,7 +986,7 @@
 STATIC int
 xfs_ioc_fsgeometry(
 	xfs_mount_t		*mp,
-	unsigned long		arg)
+	void			__user *arg)
 {
 	xfs_fsop_geom_t		fsgeo;
 	int			error;
@@ -1004,7 +995,7 @@
 	if (error)
 		return -error;
 
-	if (copy_to_user((xfs_fsop_geom_t *)arg, &fsgeo, sizeof(fsgeo)))
+	if (copy_to_user(arg, &fsgeo, sizeof(fsgeo)))
 		return -XFS_ERROR(EFAULT);
 	return 0;
 }
@@ -1074,7 +1065,7 @@
 	xfs_inode_t		*ip,
 	struct file		*filp,
 	unsigned int		cmd,
-	unsigned long		arg)
+	void			__user *arg)
 {
 	struct fsxattr		fa;
 	vattr_t			va;
@@ -1093,13 +1084,13 @@
 		fa.fsx_extsize	= va.va_extsize;
 		fa.fsx_nextents = va.va_nextents;
 
-		if (copy_to_user((struct fsxattr *)arg, &fa, sizeof(fa)))
+		if (copy_to_user(arg, &fa, sizeof(fa)))
 			return -XFS_ERROR(EFAULT);
 		return 0;
 	}
 
 	case XFS_IOC_FSSETXATTR: {
-		if (copy_from_user(&fa, (struct fsxattr *)arg, sizeof(fa)))
+		if (copy_from_user(&fa, arg, sizeof(fa)))
 			return -XFS_ERROR(EFAULT);
 
 		attr_flags = 0;
@@ -1126,20 +1117,20 @@
 		fa.fsx_extsize	= va.va_extsize;
 		fa.fsx_nextents = va.va_anextents;
 
-		if (copy_to_user((struct fsxattr *)arg, &fa, sizeof(fa)))
+		if (copy_to_user(arg, &fa, sizeof(fa)))
 			return -XFS_ERROR(EFAULT);
 		return 0;
 	}
 
 	case XFS_IOC_GETXFLAGS: {
 		flags = xfs_di2lxflags(ip->i_d.di_flags);
-		if (copy_to_user((unsigned int *)arg, &flags, sizeof(flags)))
+		if (copy_to_user(arg, &flags, sizeof(flags)))
 			return -XFS_ERROR(EFAULT);
 		return 0;
 	}
 
 	case XFS_IOC_SETXFLAGS: {
-		if (copy_from_user(&flags, (unsigned int *)arg, sizeof(flags)))
+		if (copy_from_user(&flags, arg, sizeof(flags)))
 			return -XFS_ERROR(EFAULT);
 
 		if (flags & ~(LINUX_XFLAG_IMMUTABLE | LINUX_XFLAG_APPEND | \
@@ -1163,7 +1154,7 @@
 
 	case XFS_IOC_GETVERSION: {
 		flags = LINVFS_GET_IP(vp)->i_generation;
-		if (copy_to_user((unsigned int *)arg, &flags, sizeof(flags)))
+		if (copy_to_user(arg, &flags, sizeof(flags)))
 			return -XFS_ERROR(EFAULT);
 		return 0;
 	}
@@ -1179,13 +1170,13 @@
 	struct file		*filp,
 	int			ioflags,
 	unsigned int		cmd,
-	unsigned long		arg)
+	void			__user *arg)
 {
 	struct getbmap		bm;
 	int			iflags;
 	int			error;
 
-	if (copy_from_user(&bm, (struct getbmap *)arg, sizeof(bm)))
+	if (copy_from_user(&bm, arg, sizeof(bm)))
 		return -XFS_ERROR(EFAULT);
 
 	if (bm.bmv_count < 2)
@@ -1195,11 +1186,11 @@
 	if (ioflags & IO_INVIS)
 		iflags |= BMV_IF_NO_DMAPI_READ;
 
-	error = xfs_getbmap(bdp, &bm, (struct getbmap *)arg+1, iflags);
+	error = xfs_getbmap(bdp, &bm, (struct getbmap __user *)arg+1, iflags);
 	if (error)
 		return -error;
 
-	if (copy_to_user((struct getbmap *)arg, &bm, sizeof(bm)))
+	if (copy_to_user(arg, &bm, sizeof(bm)))
 		return -XFS_ERROR(EFAULT);
 	return 0;
 }
@@ -1207,14 +1198,14 @@
 STATIC int
 xfs_ioc_getbmapx(
 	bhv_desc_t		*bdp,
-	unsigned long		arg)
+	void			__user *arg)
 {
 	struct getbmapx		bmx;
 	struct getbmap		bm;
 	int			iflags;
 	int			error;
 
-	if (copy_from_user(&bmx, (struct getbmapx *)arg, sizeof(bmx)))
+	if (copy_from_user(&bmx, arg, sizeof(bmx)))
 		return -XFS_ERROR(EFAULT);
 
 	if (bmx.bmv_count < 2)
@@ -1233,13 +1224,13 @@
 
 	iflags |= BMV_IF_EXTENDED;
 
-	error = xfs_getbmap(bdp, &bm, (struct getbmapx *)arg+1, iflags);
+	error = xfs_getbmap(bdp, &bm, (struct getbmapx __user *)arg+1, iflags);
 	if (error)
 		return -error;
 
 	GETBMAP_CONVERT(bm, bmx);
 
-	if (copy_to_user((struct getbmapx *)arg, &bmx, sizeof(bmx)))
+	if (copy_to_user(arg, &bmx, sizeof(bmx)))
 		return -XFS_ERROR(EFAULT);
 
 	return 0;
diff -Nru a/fs/xfs/linux-2.6/xfs_ioctl32.c b/fs/xfs/linux-2.6/xfs_ioctl32.c
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/fs/xfs/linux-2.6/xfs_ioctl32.c	2004-10-18 14:57:24 -07:00
@@ -0,0 +1,162 @@
+/*
+ * Copyright (c) 2004 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/SGIGPLNoticeExplan/
+ */
+
+#include <linux/config.h>
+#include <linux/compat.h>
+#include <linux/init.h>
+#include <linux/ioctl.h>
+#include <linux/ioctl32.h>
+#include <linux/syscalls.h>
+#include <linux/types.h>
+#include <asm/uaccess.h>
+
+#include "xfs_types.h"
+#include "xfs_fs.h"
+#include "xfs_dfrag.h"
+
+#if defined(CONFIG_IA64) || defined(CONFIG_X86_64)
+#define BROKEN_X86_ALIGNMENT
+#else
+
+typedef struct xfs_fsop_bulkreq32 {
+	compat_uptr_t	lastip;		/* last inode # pointer		*/
+	__s32		icount;		/* count of entries in buffer	*/
+	compat_uptr_t	ubuffer;	/* user buffer for inode desc.	*/
+	__s32		ocount;		/* output count pointer		*/
+} xfs_fsop_bulkreq32_t;
+
+static int
+xfs_ioctl32_bulkstat(
+	unsigned int		fd,
+	unsigned int		cmd,
+	unsigned long		arg,
+	struct file *		file)
+{
+	xfs_fsop_bulkreq32_t	__user *p32 = (void __user *)arg;
+	xfs_fsop_bulkreq_t	__user *p = compat_alloc_user_space(sizeof(*p));
+	u32			addr;
+
+	if (get_user(addr, &p32->lastip) ||
+	    put_user(compat_ptr(addr), &p->lastip) ||
+	    copy_in_user(&p->icount, &p32->icount, sizeof(s32)) ||
+	    get_user(addr, &p32->ubuffer) ||
+	    put_user(compat_ptr(addr), &p->ubuffer) ||
+	    get_user(addr, &p32->ocount) ||
+	    put_user(compat_ptr(addr), &p->ocount))
+		return -EFAULT;
+
+	return sys_ioctl(fd, cmd, (unsigned long)p);
+}
+#endif
+
+struct ioctl_trans xfs_ioctl32_trans[] = {
+	{ XFS_IOC_DIOINFO, },
+	{ XFS_IOC_FSGEOMETRY_V1, },
+	{ XFS_IOC_FSGEOMETRY, },
+	{ XFS_IOC_GETVERSION, },
+	{ XFS_IOC_GETXFLAGS, },
+	{ XFS_IOC_SETXFLAGS, },
+	{ XFS_IOC_FSGETXATTR, },
+	{ XFS_IOC_FSSETXATTR, },
+	{ XFS_IOC_FSGETXATTRA, },
+	{ XFS_IOC_FSSETDM, },
+	{ XFS_IOC_GETBMAP, },
+	{ XFS_IOC_GETBMAPA, },
+	{ XFS_IOC_GETBMAPX, },
+/* not handled
+	{ XFS_IOC_FD_TO_HANDLE, },
+	{ XFS_IOC_PATH_TO_HANDLE, },
+	{ XFS_IOC_PATH_TO_HANDLE, },
+	{ XFS_IOC_PATH_TO_FSHANDLE, },
+	{ XFS_IOC_OPEN_BY_HANDLE, },
+	{ XFS_IOC_FSSETDM_BY_HANDLE, },
+	{ XFS_IOC_READLINK_BY_HANDLE, },
+	{ XFS_IOC_ATTRLIST_BY_HANDLE, },
+	{ XFS_IOC_ATTRMULTI_BY_HANDLE, },
+*/
+	{ XFS_IOC_FSCOUNTS, NULL, },
+	{ XFS_IOC_SET_RESBLKS, NULL, },
+	{ XFS_IOC_GET_RESBLKS, NULL, },
+	{ XFS_IOC_FSGROWFSDATA, NULL, },
+	{ XFS_IOC_FSGROWFSLOG, NULL, },
+	{ XFS_IOC_FSGROWFSRT, NULL, },
+	{ XFS_IOC_FREEZE, NULL, },
+	{ XFS_IOC_THAW, NULL, },
+	{ XFS_IOC_GOINGDOWN, NULL, },
+	{ XFS_IOC_ERROR_INJECTION, NULL, },
+	{ XFS_IOC_ERROR_CLEARALL, NULL, },
+#ifndef BROKEN_X86_ALIGNMENT
+	/* xfs_flock_t and xfs_bstat_t have wrong u32 vs u64 alignment */
+	{ XFS_IOC_ALLOCSP, },
+	{ XFS_IOC_FREESP, },
+	{ XFS_IOC_RESVSP, },
+	{ XFS_IOC_UNRESVSP, },
+	{ XFS_IOC_ALLOCSP64, },
+	{ XFS_IOC_FREESP64, },
+	{ XFS_IOC_RESVSP64, },
+	{ XFS_IOC_UNRESVSP64, },
+	{ XFS_IOC_SWAPEXT, },
+	{ XFS_IOC_FSBULKSTAT_SINGLE, xfs_ioctl32_bulkstat },
+	{ XFS_IOC_FSBULKSTAT, xfs_ioctl32_bulkstat},
+	{ XFS_IOC_FSINUMBERS, xfs_ioctl32_bulkstat},
+#endif
+	{ 0, },
+};
+
+int __init
+xfs_ioctl32_init(void)
+{
+	int error, i;
+
+	for (i = 0; xfs_ioctl32_trans[i].cmd != 0; i++) {
+		error = register_ioctl32_conversion(xfs_ioctl32_trans[i].cmd,
+				xfs_ioctl32_trans[i].handler);
+		if (error)
+			goto fail;
+	}
+
+	return 0;
+
+ fail:
+	while (--i)
+		unregister_ioctl32_conversion(xfs_ioctl32_trans[i].cmd);
+	return error;
+}
+
+void
+xfs_ioctl32_exit(void)
+{
+	int i;
+
+	for (i = 0; xfs_ioctl32_trans[i].cmd != 0; i++)
+		unregister_ioctl32_conversion(xfs_ioctl32_trans[i].cmd);
+}
diff -Nru a/fs/xfs/linux-2.6/xfs_ioctl32.h b/fs/xfs/linux-2.6/xfs_ioctl32.h
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/fs/xfs/linux-2.6/xfs_ioctl32.h	2004-10-18 14:57:23 -07:00
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 2004 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/SGIGPLNoticeExplan/
+ */
+
+#include <linux/config.h>
+
+#ifdef CONFIG_COMPAT
+extern int xfs_ioctl32_init(void);
+extern void xfs_ioctl32_exit(void);
+#else
+static inline int xfs_ioctl32_init(void) { return 0; }
+static inline void xfs_ioctl32_exit(void) { }
+#endif
diff -Nru a/fs/xfs/linux-2.6/xfs_iops.c b/fs/xfs/linux-2.6/xfs_iops.c
--- a/fs/xfs/linux-2.6/xfs_iops.c	2004-10-18 14:56:28 -07:00
+++ b/fs/xfs/linux-2.6/xfs_iops.c	2004-10-18 14:56:28 -07:00
@@ -174,8 +174,9 @@
 				 */
 				teardown.d_inode = ip = LINVFS_GET_IP(vp);
 				teardown.d_name = dentry->d_name;
-				remove_inode_hash(ip);
-				make_bad_inode(ip);
+
+				vn_mark_bad(vp);
+				
 				if (S_ISDIR(mode))
 					VOP_RMDIR(dvp, &teardown, NULL, err2);
 				else
@@ -225,26 +226,21 @@
 	struct dentry	*dentry,
 	struct nameidata *nd)
 {
-	struct inode	*ip = NULL;
-	vnode_t		*vp, *cvp = NULL;
+	struct vnode	*vp = LINVFS_GET_VP(dir), *cvp;
 	int		error;
 
 	if (dentry->d_name.len >= MAXNAMELEN)
 		return ERR_PTR(-ENAMETOOLONG);
 
-	vp = LINVFS_GET_VP(dir);
 	VOP_LOOKUP(vp, dentry, &cvp, 0, NULL, NULL, error);
-	if (!error) {
-		ASSERT(cvp);
-		ip = LINVFS_GET_IP(cvp);
-		if (!ip) {
-			VN_RELE(cvp);
-			return ERR_PTR(-EACCES);
-		}
+	if (error) {
+		if (unlikely(error != ENOENT))
+			return ERR_PTR(-error);
+		d_add(dentry, NULL);
+		return NULL;
 	}
-	if (error && (error != ENOENT))
-		return ERR_PTR(-error);
-	return d_splice_alias(ip, dentry);
+
+	return d_splice_alias(LINVFS_GET_IP(cvp), dentry);
 }
 
 STATIC int
@@ -304,7 +300,7 @@
 {
 	struct inode	*ip;
 	vattr_t		va;
-	vnode_t		*dvp;	/* directory containing name to remove */
+	vnode_t		*dvp;	/* directory containing name of symlink */
 	vnode_t		*cvp;	/* used to lookup symlink to put in dentry */
 	int		error;
 
@@ -376,7 +372,7 @@
 STATIC int
 linvfs_readlink(
 	struct dentry	*dentry,
-	char		*buf,
+	char		__user *buf,
 	int		size)
 {
 	vnode_t		*vp = LINVFS_GET_VP(dentry->d_inode);
diff -Nru a/fs/xfs/linux-2.6/xfs_iops.h b/fs/xfs/linux-2.6/xfs_iops.h
--- a/fs/xfs/linux-2.6/xfs_iops.h	2004-10-18 14:56:32 -07:00
+++ b/fs/xfs/linux-2.6/xfs_iops.h	2004-10-18 14:56:32 -07:00
@@ -46,6 +46,6 @@
 extern void linvfs_unwritten_done(struct buffer_head *, int);
 
 extern int xfs_ioctl(struct bhv_desc *, struct inode *, struct file *,
-                        int, unsigned int, unsigned long);
+                        int, unsigned int, void __user *);
 
 #endif /* __XFS_IOPS_H__ */
diff -Nru a/fs/xfs/linux-2.6/xfs_linux.h b/fs/xfs/linux-2.6/xfs_linux.h
--- a/fs/xfs/linux-2.6/xfs_linux.h	2004-10-18 14:55:53 -07:00
+++ b/fs/xfs/linux-2.6/xfs_linux.h	2004-10-18 14:55:53 -07:00
@@ -85,6 +85,7 @@
 #include <linux/vfs.h>
 #include <linux/seq_file.h>
 #include <linux/init.h>
+#include <linux/list.h>
 #include <linux/proc_fs.h>
 #include <linux/version.h>
 
@@ -140,6 +141,7 @@
 #define xfs_inherit_noatime	xfs_params.inherit_noatim.val
 #define xfs_buf_timer_centisecs	xfs_params.xfs_buf_timer.val
 #define xfs_buf_age_centisecs	xfs_params.xfs_buf_age.val
+#define xfs_inherit_nosymlinks	xfs_params.inherit_nosym.val
 
 #define current_cpu()		smp_processor_id()
 #define current_pid()		(current->pid)
diff -Nru a/fs/xfs/linux-2.6/xfs_lrw.c b/fs/xfs/linux-2.6/xfs_lrw.c
--- a/fs/xfs/linux-2.6/xfs_lrw.c	2004-10-18 14:55:46 -07:00
+++ b/fs/xfs/linux-2.6/xfs_lrw.c	2004-10-18 14:55:46 -07:00
@@ -74,6 +74,7 @@
 #include "xfs_iomap.h"
 
 #include <linux/capability.h>
+#include <linux/writeback.h>
 
 
 #if defined(XFS_RW_TRACE)
@@ -81,7 +82,7 @@
 xfs_rw_enter_trace(
 	int			tag,
 	xfs_iocore_t		*io,
-	const struct iovec	*iovp,
+	void			*data,
 	size_t			segs,
 	loff_t			offset,
 	int			ioflags)
@@ -95,7 +96,7 @@
 		(void *)ip,
 		(void *)((unsigned long)((ip->i_d.di_size >> 32) & 0xffffffff)),
 		(void *)((unsigned long)(ip->i_d.di_size & 0xffffffff)),
-		(void *)(__psint_t)iovp,
+		(void *)data,
 		(void *)((unsigned long)segs),
 		(void *)((unsigned long)((offset >> 32) & 0xffffffff)),
 		(void *)((unsigned long)(offset & 0xffffffff)),
@@ -225,40 +226,11 @@
 	int		write,
 	int		relock)
 {
-	xfs_mount_t	*mp;
-
-	if (!VN_CACHED(vp)) {
-		return;
+	if (VN_CACHED(vp)) {
+		xfs_inval_cached_trace(io, offset, -1, ctooff(offtoct(offset)), -1);
+		VOP_FLUSHINVAL_PAGES(vp, ctooff(offtoct(offset)), -1, FI_REMAPF_LOCKED);
 	}
 
-	mp = io->io_mount;
-
-	/*
-	 * We need to get the I/O lock exclusively in order
-	 * to safely invalidate pages and mappings.
-	 */
-	if (relock) {
-		XFS_IUNLOCK(mp, io, XFS_IOLOCK_SHARED);
-		XFS_ILOCK(mp, io, XFS_IOLOCK_EXCL);
-	}
-
-	/* Writing beyond EOF creates a hole that must be zeroed */
-	if (write && (offset > XFS_SIZE(mp, io))) {
-		xfs_fsize_t	isize;
-
-		XFS_ILOCK(mp, io, XFS_ILOCK_EXCL|XFS_EXTSIZE_RD);
-		isize = XFS_SIZE(mp, io);
-		if (offset > isize) {
-			xfs_zero_eof(vp, io, offset, isize, offset);
-		}
-		XFS_IUNLOCK(mp, io, XFS_ILOCK_EXCL|XFS_EXTSIZE_RD);
-	}
-
-	xfs_inval_cached_trace(io, offset, -1, ctooff(offtoct(offset)), -1);
-	VOP_FLUSHINVAL_PAGES(vp, ctooff(offtoct(offset)), -1, FI_REMAPF_LOCKED);
-	if (relock) {
-		XFS_ILOCK_DEMOTE(mp, io, XFS_IOLOCK_EXCL);
-	}
 }
 
 ssize_t			/* bytes read, or (-)  error */
@@ -324,11 +296,6 @@
 		return -EIO;
 	}
 
-	/* OK so we are holding the I/O lock for the duration
-	 * of the submission, then what happens if the I/O
-	 * does not really happen here, but is scheduled 
-	 * later?
-	 */
 	xfs_ilock(ip, XFS_IOLOCK_SHARED);
 
 	if (DM_EVENT_ENABLED(vp->v_vfsp, ip, DM_EVENT_READ) &&
@@ -345,8 +312,11 @@
 	}
 
 	xfs_rw_enter_trace(XFS_READ_ENTER, &ip->i_iocore,
-				iovp, segs, *offset, ioflags);
+				(void *)iovp, segs, *offset, ioflags);
 	ret = __generic_file_aio_read(iocb, iovp, segs, offset);
+	if (ret == -EIOCBQUEUED)
+		ret = wait_on_sync_kiocb(iocb);
+
 	xfs_iunlock(ip, XFS_IOLOCK_SHARED);
 
 	if (ret > 0)
@@ -406,12 +376,17 @@
 		}
 	}
 	xfs_rw_enter_trace(XFS_SENDFILE_ENTER, &ip->i_iocore,
-				target, count, *offset, ioflags);
+		   (void *)(unsigned long)target, count, *offset, ioflags);
 	ret = generic_file_sendfile(filp, offset, count, actor, target);
+
 	xfs_iunlock(ip, XFS_IOLOCK_SHARED);
 
-	XFS_STATS_ADD(xs_read_bytes, ret);
-	xfs_ichgtime(ip, XFS_ICHGTIME_ACC);
+	if (ret > 0)
+		XFS_STATS_ADD(xs_read_bytes, ret);
+
+	if (likely(!(ioflags & IO_INVIS)))
+		xfs_ichgtime(ip, XFS_ICHGTIME_ACC);
+
 	return ret;
 }
 
@@ -637,32 +612,34 @@
 	bhv_desc_t		*bdp,
 	struct kiocb		*iocb,
 	const struct iovec	*iovp,
-	unsigned int		segs,
+	unsigned int		nsegs,
 	loff_t			*offset,
 	int			ioflags,
 	cred_t			*credp)
 {
 	struct file		*file = iocb->ki_filp;
-	size_t			size = 0;
+	struct address_space	*mapping = file->f_mapping;
+	struct inode		*inode = mapping->host;
+	unsigned long		segs = nsegs;
 	xfs_inode_t		*xip;
 	xfs_mount_t		*mp;
-	ssize_t			ret;
-	int			error = 0;
+	ssize_t			ret = 0, error = 0;
 	xfs_fsize_t		isize, new_size;
-	xfs_fsize_t		n, limit;
 	xfs_iocore_t		*io;
 	vnode_t			*vp;
 	unsigned long		seg;
 	int			iolock;
 	int			eventsent = 0;
 	vrwlock_t		locktype;
+	size_t			ocount = 0, count;
+	loff_t			pos;
+	int			need_isem = 1, need_flush = 0;
 
 	XFS_STATS_INC(xs_write_calls);
 
 	vp = BHV_TO_VNODE(bdp);
 	xip = XFS_BHVTOI(bdp);
 
-	/* START copy & waste from filemap.c */
 	for (seg = 0; seg < segs; seg++) {
 		const struct iovec *iv = &iovp[seg];
 
@@ -670,73 +647,90 @@
 		 * If any segment has a negative length, or the cumulative
 		 * length ever wraps negative then return -EINVAL.
 		 */
-		size += iv->iov_len;
-		if (unlikely((ssize_t)(size|iv->iov_len) < 0))
-			return XFS_ERROR(-EINVAL);
+		ocount += iv->iov_len;
+		if (unlikely((ssize_t)(ocount|iv->iov_len) < 0))
+			return -EINVAL;
+		if (access_ok(VERIFY_READ, iv->iov_base, iv->iov_len))
+			continue;
+		if (seg == 0)
+			return -EFAULT;
+		segs = seg;
+		ocount -= iv->iov_len;  /* This segment is no good */
+		break;
 	}
-	/* END copy & waste from filemap.c */
 
-	if (size == 0)
+	count = ocount;
+	pos = *offset;
+
+	if (count == 0)
 		return 0;
 
 	io = &xip->i_iocore;
 	mp = io->io_mount;
 
-	if (XFS_FORCED_SHUTDOWN(mp)) {
+	if (XFS_FORCED_SHUTDOWN(mp))
 		return -EIO;
-	}
 
 	if (ioflags & IO_ISDIRECT) {
 		xfs_buftarg_t	*target =
 			(xip->i_d.di_flags & XFS_DIFLAG_REALTIME) ?
 				mp->m_rtdev_targp : mp->m_ddev_targp;
 
-		if ((*offset & target->pbr_smask) ||
-		    (size & target->pbr_smask)) {
+		if ((pos & target->pbr_smask) || (count & target->pbr_smask))
 			return XFS_ERROR(-EINVAL);
-		}
-		iolock = XFS_IOLOCK_SHARED;
-		locktype = VRWLOCK_WRITE_DIRECT;
-	} else {
+
+		if (!VN_CACHED(vp) && pos < i_size_read(inode))
+			need_isem = 0;
+
+		if (VN_CACHED(vp))
+			need_flush = 1;
+	}
+
+relock:
+	if (need_isem) {
 		iolock = XFS_IOLOCK_EXCL;
 		locktype = VRWLOCK_WRITE;
+
+		down(&inode->i_sem);
+	} else {
+		iolock = XFS_IOLOCK_SHARED;
+		locktype = VRWLOCK_WRITE_DIRECT;
 	}
 
 	xfs_ilock(xip, XFS_ILOCK_EXCL|iolock);
 
-	isize = xip->i_d.di_size;
-	limit = XFS_MAXIOFFSET(mp);
+	isize = i_size_read(inode);
 
 	if (file->f_flags & O_APPEND)
 		*offset = isize;
 
 start:
-	n = limit - *offset;
-	if (n <= 0) {
+	error = -generic_write_checks(file, &pos, &count,
+					S_ISBLK(inode->i_mode));
+	if (error) {
 		xfs_iunlock(xip, XFS_ILOCK_EXCL|iolock);
-		return -EFBIG;
+		goto out_unlock_isem;
 	}
 
-	if (n < size)
-		size = n;
-
-	new_size = *offset + size;
-	if (new_size > isize) {
+	new_size = pos + count;
+	if (new_size > isize)
 		io->io_new_size = new_size;
-	}
 
 	if ((DM_EVENT_ENABLED(vp->v_vfsp, xip, DM_EVENT_WRITE) &&
 	    !(ioflags & IO_INVIS) && !eventsent)) {
-		loff_t		savedsize = *offset;
-		int dmflags = FILP_DELAY_FLAG(file) | DM_SEM_FLAG_RD(ioflags);
+		loff_t		savedsize = pos;
+		int		dmflags = FILP_DELAY_FLAG(file);
+
+		if (need_isem)
+			dmflags |= DM_FLAGS_ISEM;
 
 		xfs_iunlock(xip, XFS_ILOCK_EXCL);
 		error = XFS_SEND_DATA(xip->i_mount, DM_EVENT_WRITE, vp,
-				      *offset, size,
+				      pos, count,
 				      dmflags, &locktype);
 		if (error) {
 			xfs_iunlock(xip, iolock);
-			return -error;
+			goto out_unlock_isem;
 		}
 		xfs_ilock(xip, XFS_ILOCK_EXCL);
 		eventsent = 1;
@@ -748,9 +742,8 @@
 		 * event prevents another call to XFS_SEND_DATA, which is
 		 * what allows the size to change in the first place.
 		 */
-		if ((file->f_flags & O_APPEND) &&
-		    savedsize != xip->i_d.di_size) {
-			*offset = isize = xip->i_d.di_size;
+		if ((file->f_flags & O_APPEND) && savedsize != isize) {
+			pos = isize = xip->i_d.di_size;
 			goto start;
 		}
 	}
@@ -761,8 +754,10 @@
 	 *
 	 * We must update xfs' times since revalidate will overcopy xfs.
 	 */
-	if (size && !(ioflags & IO_INVIS))
+	if (!(ioflags & IO_INVIS)) {
 		xfs_ichgtime(xip, XFS_ICHGTIME_MOD | XFS_ICHGTIME_CHG);
+		inode_update_time(inode, 1);
+	}
 
 	/*
 	 * If the offset is beyond the size of the file, we have a couple
@@ -773,12 +768,12 @@
 	 * to zero it out up to the new size.
 	 */
 
-	if (!(ioflags & IO_ISDIRECT) && (*offset > isize && isize)) {
-		error = xfs_zero_eof(BHV_TO_VNODE(bdp), io, *offset,
-			isize, *offset + size);
+	if (pos > isize) {
+		error = xfs_zero_eof(BHV_TO_VNODE(bdp), io, pos,
+					isize, pos + count);
 		if (error) {
 			xfs_iunlock(xip, XFS_ILOCK_EXCL|iolock);
-			return(-error);
+			goto out_unlock_isem;
 		}
 	}
 	xfs_iunlock(xip, XFS_ILOCK_EXCL);
@@ -795,22 +790,67 @@
 		(S_ISGID | S_IXGRP))) &&
 	     !capable(CAP_FSETID)) {
 		error = xfs_write_clear_setuid(xip);
-		if (error) {
+		if (likely(!error))
+			error = -remove_suid(file->f_dentry);
+		if (unlikely(error)) {
 			xfs_iunlock(xip, iolock);
-			return -error;
+			goto out_unlock_isem;
 		}
 	}
 
 retry:
-	if (ioflags & IO_ISDIRECT) {
-		xfs_inval_cached_pages(vp, io, *offset, 1, 1);
-		xfs_rw_enter_trace(XFS_DIOWR_ENTER,
-				io, iovp, segs, *offset, ioflags);
+	/* We can write back this queue in page reclaim */
+	current->backing_dev_info = mapping->backing_dev_info;
+
+	if ((ioflags & IO_ISDIRECT)) {
+		if (need_flush) {
+			xfs_inval_cached_trace(io, pos, -1,
+					ctooff(offtoct(pos)), -1);
+			VOP_FLUSHINVAL_PAGES(vp, ctooff(offtoct(pos)),
+					-1, FI_REMAPF_LOCKED);
+		}
+
+		if (need_isem) {
+			/* demote the lock now the cached pages are gone */
+			XFS_ILOCK_DEMOTE(mp, io, XFS_IOLOCK_EXCL);
+			up(&inode->i_sem);
+
+			iolock = XFS_IOLOCK_SHARED;
+			locktype = VRWLOCK_WRITE_DIRECT;
+			need_isem = 0;
+		}
+
+ 		xfs_rw_enter_trace(XFS_DIOWR_ENTER, io, (void *)iovp, segs,
+				*offset, ioflags);
+		ret = generic_file_direct_write(iocb, iovp,
+				&segs, pos, offset, count, ocount);
+
+		/*
+		 * direct-io write to a hole: fall through to buffered I/O
+		 * for completing the rest of the request.
+		 */
+		if (ret >= 0 && ret != count) {
+			XFS_STATS_ADD(xs_write_bytes, ret);
+
+			pos += ret;
+			count -= ret;
+
+			need_isem = 1;
+			ioflags &= ~IO_ISDIRECT;
+			xfs_iunlock(xip, iolock);
+			goto relock;
+		}
 	} else {
-		xfs_rw_enter_trace(XFS_WRITE_ENTER,
-				io, iovp, segs, *offset, ioflags);
+		xfs_rw_enter_trace(XFS_WRITE_ENTER, io, (void *)iovp, segs,
+				*offset, ioflags);
+		ret = generic_file_buffered_write(iocb, iovp, segs,
+				pos, offset, count, ret);
 	}
-	ret = generic_file_aio_write_nolock(iocb, iovp, segs, offset);
+
+	current->backing_dev_info = NULL;
+
+	if (ret == -EIOCBQUEUED)
+		ret = wait_on_sync_kiocb(iocb);
 
 	if ((ret == -ENOSPC) &&
 	    DM_EVENT_ENABLED(vp->v_vfsp, xip, DM_EVENT_NOSPACE) &&
@@ -821,17 +861,15 @@
 				DM_RIGHT_NULL, vp, DM_RIGHT_NULL, NULL, NULL,
 				0, 0, 0); /* Delay flag intentionally  unused */
 		if (error)
-			return -error;
+			goto out_unlock_isem;
 		xfs_rwlock(bdp, locktype);
-		*offset = xip->i_d.di_size;
+		pos = xip->i_d.di_size;
 		goto retry;
 	}
 
 	if (*offset > xip->i_d.di_size) {
 		xfs_ilock(xip, XFS_ILOCK_EXCL);
 		if (*offset > xip->i_d.di_size) {
-			struct inode	*inode = LINVFS_GET_IP(vp);
-
 			xip->i_d.di_size = *offset;
 			i_size_write(inode, *offset);
 			xip->i_update_core = 1;
@@ -840,23 +878,22 @@
 		xfs_iunlock(xip, XFS_ILOCK_EXCL);
 	}
 
-	if (ret <= 0) {
-		xfs_rwunlock(bdp, locktype);
-		return ret;
-	}
+	error = -ret;
+	if (ret <= 0)
+		goto out_unlock_internal;
 
 	XFS_STATS_ADD(xs_write_bytes, ret);
 
 	/* Handle various SYNC-type writes */
-	if ((file->f_flags & O_SYNC) || IS_SYNC(file->f_dentry->d_inode)) {
-
+	if ((file->f_flags & O_SYNC) || IS_SYNC(inode)) {
 		/*
 		 * If we're treating this as O_DSYNC and we have not updated the
 		 * size, force the log.
 		 */
+		if (!(mp->m_flags & XFS_MOUNT_OSYNCISOSYNC) &&
+		    !(xip->i_update_size)) {
+			xfs_inode_log_item_t	*iip = xip->i_itemp;
 
-		if (!(mp->m_flags & XFS_MOUNT_OSYNCISOSYNC)
-			&& !(xip->i_update_size)) {
 			/*
 			 * If an allocation transaction occurred
 			 * without extending the size, then we have to force
@@ -876,14 +913,8 @@
 			 * all changes affecting the inode are permanent
 			 * when we return.
 			 */
-
-			xfs_inode_log_item_t *iip;
-			xfs_lsn_t lsn;
-
-			iip = xip->i_itemp;
 			if (iip && iip->ili_last_lsn) {
-				lsn = iip->ili_last_lsn;
-				xfs_log_force(mp, lsn,
+				xfs_log_force(mp, iip->ili_last_lsn,
 						XFS_LOG_FORCE | XFS_LOG_SYNC);
 			} else if (xfs_ipincount(xip) > 0) {
 				xfs_log_force(mp, (xfs_lsn_t)0,
@@ -924,12 +955,27 @@
 				xfs_trans_set_sync(tp);
 				error = xfs_trans_commit(tp, 0, NULL);
 				xfs_iunlock(xip, XFS_ILOCK_EXCL);
+				if (error)
+					goto out_unlock_internal;
 			}
 		}
-	} /* (ioflags & O_SYNC) */
+	
+		xfs_rwunlock(bdp, locktype);
+		if (need_isem)
+			up(&inode->i_sem);
+
+		error = sync_page_range(inode, mapping, pos, ret);
+		if (!error)
+			error = ret;
+		return error;
+	}
 
+ out_unlock_internal:
 	xfs_rwunlock(bdp, locktype);
-	return(ret);
+ out_unlock_isem:
+	if (need_isem)
+		up(&inode->i_sem);
+	return -error;
 }
 
 /*
diff -Nru a/fs/xfs/linux-2.6/xfs_lrw.h b/fs/xfs/linux-2.6/xfs_lrw.h
--- a/fs/xfs/linux-2.6/xfs_lrw.h	2004-10-18 14:55:54 -07:00
+++ b/fs/xfs/linux-2.6/xfs_lrw.h	2004-10-18 14:55:54 -07:00
@@ -74,11 +74,11 @@
 #define	XFS_IOMAP_ALLOC_MAP	25
 #define	XFS_IOMAP_UNWRITTEN	26
 extern void xfs_rw_enter_trace(int, struct xfs_iocore *,
-			const struct iovec *, size_t, loff_t, int);
+				void *, size_t, loff_t, int);
 extern void xfs_inval_cached_trace(struct xfs_iocore *,
-			xfs_off_t, xfs_off_t, xfs_off_t, xfs_off_t);
+				xfs_off_t, xfs_off_t, xfs_off_t, xfs_off_t);
 #else
-#define xfs_rw_enter_trace(tag, io, iovec, segs, offset, ioflags)
+#define xfs_rw_enter_trace(tag, io, data, size, offset, ioflags)
 #define xfs_inval_cached_trace(io, offset, len, first, last)
 #endif
 
diff -Nru a/fs/xfs/linux-2.6/xfs_stats.c b/fs/xfs/linux-2.6/xfs_stats.c
--- a/fs/xfs/linux-2.6/xfs_stats.c	2004-10-18 14:57:03 -07:00
+++ b/fs/xfs/linux-2.6/xfs_stats.c	2004-10-18 14:57:03 -07:00
@@ -119,9 +119,9 @@
 void
 xfs_init_procfs(void)
 {
-	if (!proc_mkdir("fs/xfs", 0))
+	if (!proc_mkdir("fs/xfs", NULL))
 		return;
-	create_proc_read_entry("fs/xfs/stat", 0, 0, xfs_read_xfsstats, NULL);
+	create_proc_read_entry("fs/xfs/stat", 0, NULL, xfs_read_xfsstats, NULL);
 }
 
 void
diff -Nru a/fs/xfs/linux-2.6/xfs_super.c b/fs/xfs/linux-2.6/xfs_super.c
--- a/fs/xfs/linux-2.6/xfs_super.c	2004-10-18 14:57:03 -07:00
+++ b/fs/xfs/linux-2.6/xfs_super.c	2004-10-18 14:57:03 -07:00
@@ -66,6 +66,7 @@
 #include "xfs_buf_item.h"
 #include "xfs_utils.h"
 #include "xfs_version.h"
+#include "xfs_ioctl32.h"
 
 #include <linux/namei.h>
 #include <linux/init.h>
@@ -140,7 +141,7 @@
 	vnode_t			*vp = LINVFS_GET_VP(inode);
 
 	if (vp->v_type == VNON) {
-		make_bad_inode(inode);
+		vn_mark_bad(vp);
 	} else if (S_ISREG(inode->i_mode)) {
 		inode->i_op = &linvfs_file_inode_operations;
 		inode->i_fop = &linvfs_file_operations;
@@ -222,42 +223,21 @@
 		bhv_insert(VN_BHV_HEAD(vp), inode_bhv);
 	}
 
-	vp->v_type = IFTOVT(ip->i_d.di_mode);
-
-	/* Have we been called during the new inode create process,
-	 * in which case we are too early to fill in the Linux inode.
-	 */
-	if (vp->v_type == VNON)
-		return;
-
-	xfs_revalidate_inode(XFS_BHVTOM(bdp), vp, ip);
-
-	/* For new inodes we need to set the ops vectors,
-	 * and unlock the inode.
+	/*
+	 * We need to set the ops vectors, and unlock the inode, but if
+	 * we have been called during the new inode create process, it is
+	 * too early to fill in the Linux inode.  We will get called a
+	 * second time once the inode is properly set up, and then we can
+	 * finish our work.
 	 */
-	if (unlock && (inode->i_state & I_NEW)) {
+	if (ip->i_d.di_mode != 0 && unlock && (inode->i_state & I_NEW)) {
+		vp->v_type = IFTOVT(ip->i_d.di_mode);
+		xfs_revalidate_inode(XFS_BHVTOM(bdp), vp, ip);
 		xfs_set_inodeops(inode);
 		unlock_new_inode(inode);
 	}
 }
 
-void
-xfs_flush_inode(
-	xfs_inode_t	*ip)
-{
-	struct inode	*inode = LINVFS_GET_IP(XFS_ITOV(ip));
-
-	filemap_flush(inode->i_mapping);
-}
-
-void
-xfs_flush_device(
-	xfs_inode_t	*ip)
-{
-	sync_blockdev(XFS_ITOV(ip)->v_vfsp->vfs_super->s_bdev);
-	xfs_log_force(ip->i_mount, (xfs_lsn_t)0, XFS_LOG_FORCE|XFS_LOG_SYNC);
-}
-
 int
 xfs_blkdev_get(
 	xfs_mount_t		*mp,
@@ -311,7 +291,6 @@
 {
 	int		pages;
 
-	
 	pages = kmem_zone_shrink(linvfs_inode_zone);
 	pages += kmem_zone_shrink(xfs_inode_zone);
 	return pages;
@@ -334,10 +313,8 @@
 init_inodecache( void )
 {
 	linvfs_inode_zone = kmem_cache_create("linvfs_icache",
-				sizeof(vnode_t), 0,
-				SLAB_HWCACHE_ALIGN|SLAB_RECLAIM_ACCOUNT,
+				sizeof(vnode_t), 0, SLAB_RECLAIM_ACCOUNT,
 				init_once, NULL);
-
 	if (linvfs_inode_zone == NULL)
 		return -ENOMEM;
 	return 0;
@@ -356,13 +333,13 @@
  * at the point when it is unpinned after a log write,
  * since this is when the inode itself becomes flushable. 
  */
-STATIC void
+STATIC int
 linvfs_write_inode(
 	struct inode		*inode,
 	int			sync)
 {
 	vnode_t			*vp = LINVFS_GET_VP(inode);
-	int			error, flags = FLUSH_INODE;
+	int			error = 0, flags = FLUSH_INODE;
 
 	if (vp) {
 		vn_trace_entry(vp, __FUNCTION__, (inst_t *)__return_address);
@@ -370,6 +347,8 @@
 			flags |= FLUSH_SYNC;
 		VOP_IFLUSH(vp, flags, error);
 	}
+
+	return -error;
 }
 
 STATIC void
@@ -389,36 +368,152 @@
 }
 
 
+/*
+ * Enqueue a work item to be picked up by the vfs xfssyncd thread.
+ * Doing this has two advantages:
+ * - It saves on stack space, which is tight in certain situations
+ * - It can be used (with care) as a mechanism to avoid deadlocks.
+ * Flushing while allocating in a full filesystem requires both.
+ */
+STATIC void
+xfs_syncd_queue_work(
+	struct vfs	*vfs,
+	void		*data,
+	void		(*syncer)(vfs_t *, void *))
+{
+	vfs_sync_work_t	*work;
+
+	work = kmem_alloc(sizeof(struct vfs_sync_work), KM_SLEEP);
+	INIT_LIST_HEAD(&work->w_list);
+	work->w_syncer = syncer;
+	work->w_data = data;
+	work->w_vfs = vfs;
+	spin_lock(&vfs->vfs_sync_lock);
+	list_add_tail(&work->w_list, &vfs->vfs_sync_list);
+	spin_unlock(&vfs->vfs_sync_lock);
+	wake_up_process(vfs->vfs_sync_task);
+}
+
+/*
+ * Flush delayed allocate data, attempting to free up reserved space
+ * from existing allocations.  At this point a new allocation attempt
+ * has failed with ENOSPC and we are in the process of scratching our
+ * heads, looking about for more room...
+ */
+STATIC void
+xfs_flush_inode_work(
+	vfs_t		*vfs,
+	void		*inode)
+{
+	filemap_flush(((struct inode *)inode)->i_mapping);
+	iput((struct inode *)inode);
+}
+
+void
+xfs_flush_inode(
+	xfs_inode_t	*ip)
+{
+	struct inode	*inode = LINVFS_GET_IP(XFS_ITOV(ip));
+	struct vfs	*vfs = XFS_MTOVFS(ip->i_mount);
+
+	igrab(inode);
+	xfs_syncd_queue_work(vfs, inode, xfs_flush_inode_work);
+	delay(HZ/2);
+}
+
+/*
+ * This is the "bigger hammer" version of xfs_flush_inode_work...
+ * (IOW, "If at first you don't succeed, use a Bigger Hammer").
+ */
+STATIC void
+xfs_flush_device_work(
+	vfs_t		*vfs,
+	void		*inode)
+{
+	sync_blockdev(vfs->vfs_super->s_bdev);
+	iput((struct inode *)inode);
+}
+
+void
+xfs_flush_device(
+	xfs_inode_t	*ip)
+{
+	struct inode	*inode = LINVFS_GET_IP(XFS_ITOV(ip));
+	struct vfs	*vfs = XFS_MTOVFS(ip->i_mount);
+
+	igrab(inode);
+	xfs_syncd_queue_work(vfs, inode, xfs_flush_device_work);
+	delay(HZ/2);
+	xfs_log_force(ip->i_mount, (xfs_lsn_t)0, XFS_LOG_FORCE|XFS_LOG_SYNC);
+}
+
 #define SYNCD_FLAGS	(SYNC_FSDATA|SYNC_BDFLUSH|SYNC_ATTR)
+STATIC void
+vfs_sync_worker(
+	vfs_t		*vfsp,
+	void		*unused)
+{
+	int		error;
+
+	if (!(vfsp->vfs_flag & VFS_RDONLY))
+		VFS_SYNC(vfsp, SYNCD_FLAGS, NULL, error);
+	vfsp->vfs_sync_seq++;
+	wmb();
+	wake_up(&vfsp->vfs_wait_single_sync_task);
+}
 
 STATIC int
 xfssyncd(
 	void			*arg)
 {
+	long			timeleft;
 	vfs_t			*vfsp = (vfs_t *) arg;
-	int			error;
+	struct list_head	tmp;
+	struct vfs_sync_work	*work, *n;
 
 	daemonize("xfssyncd");
 
+	vfsp->vfs_sync_work.w_vfs = vfsp;
+	vfsp->vfs_sync_work.w_syncer = vfs_sync_worker;
 	vfsp->vfs_sync_task = current;
 	wmb();
 	wake_up(&vfsp->vfs_wait_sync_task);
 
+	INIT_LIST_HEAD(&tmp);
+	timeleft = (xfs_syncd_centisecs * HZ) / 100;
 	for (;;) {
 		set_current_state(TASK_INTERRUPTIBLE);
-		schedule_timeout((xfs_syncd_centisecs * HZ) / 100);
+		timeleft = schedule_timeout(timeleft);
 		/* swsusp */
 		if (current->flags & PF_FREEZE)
 			refrigerator(PF_FREEZE);
 		if (vfsp->vfs_flag & VFS_UMOUNT)
 			break;
-		if (vfsp->vfs_flag & VFS_RDONLY)
-			continue;
-		VFS_SYNC(vfsp, SYNCD_FLAGS, NULL, error);
 
-		vfsp->vfs_sync_seq++;
-		wmb();
-		wake_up(&vfsp->vfs_wait_single_sync_task);
+		spin_lock(&vfsp->vfs_sync_lock);
+		/*
+		 * We can get woken by laptop mode, to do a sync -
+		 * that's the (only!) case where the list would be
+		 * empty with time remaining.
+		 */
+		if (!timeleft || list_empty(&vfsp->vfs_sync_list)) {
+			if (!timeleft)
+				timeleft = (xfs_syncd_centisecs * HZ) / 100;
+			INIT_LIST_HEAD(&vfsp->vfs_sync_work.w_list);
+			list_add_tail(&vfsp->vfs_sync_work.w_list,
+					&vfsp->vfs_sync_list);
+		}
+		list_for_each_entry_safe(work, n, &vfsp->vfs_sync_list, w_list)
+			list_move(&work->w_list, &tmp);
+		spin_unlock(&vfsp->vfs_sync_lock);
+
+		list_for_each_entry_safe(work, n, &tmp, w_list) {
+			(*work->w_syncer)(vfsp, work->w_data);
+			list_del(&work->w_list);
+			if (work == &vfsp->vfs_sync_work)
+				continue;
+			kmem_free(work, sizeof(struct vfs_sync_work));
+		}
 	}
 
 	vfsp->vfs_sync_task = NULL;
@@ -506,9 +601,10 @@
 
 	if (unlikely(laptop_mode)) {
 		int	prev_sync_seq = vfsp->vfs_sync_seq;
+
 		/*
 		 * The disk must be active because we're syncing.
-		 * We schedule syncd now (now that the disk is
+		 * We schedule xfssyncd now (now that the disk is
 		 * active) instead of later (when it might not be).
 		 */
 		wake_up_process(vfsp->vfs_sync_task);
@@ -568,31 +664,22 @@
 	int			error;
 	vnode_t			*vp, *cvp;
 	struct dentry		*parent;
-	struct inode		*ip = NULL;
 	struct dentry		dotdot;
 
 	dotdot.d_name.name = "..";
 	dotdot.d_name.len = 2;
-	dotdot.d_inode = 0;
+	dotdot.d_inode = NULL;
 
 	cvp = NULL;
 	vp = LINVFS_GET_VP(child->d_inode);
 	VOP_LOOKUP(vp, &dotdot, &cvp, 0, NULL, NULL, error);
-
-	if (!error) {
-		ASSERT(cvp);
-		ip = LINVFS_GET_IP(cvp);
-		if (!ip) {
-			VN_RELE(cvp);
-			return ERR_PTR(-EACCES);
-		}
-	}
-	if (error)
+	if (unlikely(error))
 		return ERR_PTR(-error);
-	parent = d_alloc_anon(ip);
-	if (!parent) {
+
+	parent = d_alloc_anon(LINVFS_GET_IP(cvp));
+	if (unlikely(!parent)) {
 		VN_RELE(cvp);
-		parent = ERR_PTR(-ENOMEM);
+		return ERR_PTR(-ENOMEM);
 	}
 	return parent;
 }
@@ -857,6 +944,10 @@
 		goto undo_shaker;
 	}
 
+	error = xfs_ioctl32_init();
+	if (error)
+		goto undo_ioctl32;
+
 	error = register_filesystem(&xfs_fs_type);
 	if (error)
 		goto undo_register;
@@ -864,6 +955,9 @@
 	return 0;
 
 undo_register:
+	xfs_ioctl32_exit();
+
+undo_ioctl32:
 	kmem_shake_deregister(xfs_inode_shaker);
 
 undo_shaker:
@@ -882,6 +976,7 @@
 	vfs_exitquota();
 	XFS_DM_EXIT(&xfs_fs_type);
 	unregister_filesystem(&xfs_fs_type);
+	xfs_ioctl32_exit();
 	kmem_shake_deregister(xfs_inode_shaker);
 	xfs_cleanup();
 	pagebuf_terminate();
diff -Nru a/fs/xfs/linux-2.6/xfs_sysctl.c b/fs/xfs/linux-2.6/xfs_sysctl.c
--- a/fs/xfs/linux-2.6/xfs_sysctl.c	2004-10-18 14:57:19 -07:00
+++ b/fs/xfs/linux-2.6/xfs_sysctl.c	2004-10-18 14:57:19 -07:00
@@ -45,7 +45,7 @@
 	ctl_table	*ctl,
 	int		write,
 	struct file	*filp,
-	void		*buffer,
+	void		__user *buffer,
 	size_t		*lenp,
 	loff_t		*ppos)
 {
@@ -128,6 +128,11 @@
 	sizeof(int), 0644, NULL, &proc_dointvec_minmax,
 	&sysctl_intvec, NULL,
 	&xfs_params.xfs_buf_age.min, &xfs_params.xfs_buf_age.max},
+
+	{XFS_INHERIT_NOSYM, "inherit_nosymlinks", &xfs_params.inherit_nosym.val,
+	sizeof(int), 0644, NULL, &proc_dointvec_minmax,
+	&sysctl_intvec, NULL,
+	&xfs_params.inherit_nosym.min, &xfs_params.inherit_nosym.max},
 
 	/* please keep this the last entry */
 #ifdef CONFIG_PROC_FS
diff -Nru a/fs/xfs/linux-2.6/xfs_sysctl.h b/fs/xfs/linux-2.6/xfs_sysctl.h
--- a/fs/xfs/linux-2.6/xfs_sysctl.h	2004-10-18 14:55:53 -07:00
+++ b/fs/xfs/linux-2.6/xfs_sysctl.h	2004-10-18 14:55:53 -07:00
@@ -59,6 +59,7 @@
 	xfs_sysctl_val_t inherit_noatim;/* Inherit the "noatime" inode flag. */
 	xfs_sysctl_val_t xfs_buf_timer;	/* Interval between xfsbufd wakeups. */
 	xfs_sysctl_val_t xfs_buf_age;	/* Metadata buffer age before flush. */
+	xfs_sysctl_val_t inherit_nosym;	/* Inherit the "nosymlinks" flag. */
 } xfs_param_t;
 
 /*
@@ -95,6 +96,7 @@
 	XFS_BUF_TIMER = 16,
 	XFS_BUF_AGE = 17,
 	/* XFS_IO_BYPASS = 18 */
+	XFS_INHERIT_NOSYM = 19,
 };
 
 extern xfs_param_t	xfs_params;
diff -Nru a/fs/xfs/linux-2.6/xfs_vfs.c b/fs/xfs/linux-2.6/xfs_vfs.c
--- a/fs/xfs/linux-2.6/xfs_vfs.c	2004-10-18 14:55:53 -07:00
+++ b/fs/xfs/linux-2.6/xfs_vfs.c	2004-10-18 14:55:53 -07:00
@@ -249,6 +249,8 @@
 
 	vfsp = kmem_zalloc(sizeof(vfs_t), KM_SLEEP);
 	bhv_head_init(VFS_BHVHEAD(vfsp), "vfs");
+	INIT_LIST_HEAD(&vfsp->vfs_sync_list);
+	vfsp->vfs_sync_lock = SPIN_LOCK_UNLOCKED;
 	init_waitqueue_head(&vfsp->vfs_wait_sync_task);
 	init_waitqueue_head(&vfsp->vfs_wait_single_sync_task);
 	return vfsp;
diff -Nru a/fs/xfs/linux-2.6/xfs_vfs.h b/fs/xfs/linux-2.6/xfs_vfs.h
--- a/fs/xfs/linux-2.6/xfs_vfs.h	2004-10-18 14:55:54 -07:00
+++ b/fs/xfs/linux-2.6/xfs_vfs.h	2004-10-18 14:55:54 -07:00
@@ -36,6 +36,7 @@
 #include "xfs_fs.h"
 
 struct fid;
+struct vfs;
 struct cred;
 struct vnode;
 struct kstatfs;
@@ -45,14 +46,24 @@
 
 typedef struct kstatfs xfs_statfs_t;
 
+typedef struct vfs_sync_work {
+	struct list_head	w_list;
+	struct vfs		*w_vfs;
+	void			*w_data;	/* syncer routine argument */
+	void			(*w_syncer)(struct vfs *, void *);
+} vfs_sync_work_t;
+
 typedef struct vfs {
 	u_int			vfs_flag;	/* flags */
 	xfs_fsid_t		vfs_fsid;	/* file system ID */
 	xfs_fsid_t		*vfs_altfsid;	/* An ID fixed for life of FS */
 	bhv_head_t		vfs_bh;		/* head of vfs behavior chain */
-	struct super_block	*vfs_super;	/* Linux superblock structure */
-	struct task_struct	*vfs_sync_task;	/* xfssyncd process */
-	int 			vfs_sync_seq;	/* xfssyncd generation number */
+	struct super_block	*vfs_super;	/* generic superblock pointer */
+	struct task_struct	*vfs_sync_task;	/* generalised sync thread */
+	vfs_sync_work_t		vfs_sync_work;	/* work item for VFS_SYNC */
+	struct list_head	vfs_sync_list;	/* sync thread work item list */
+	spinlock_t		vfs_sync_lock;	/* work item list lock */
+	int 			vfs_sync_seq;	/* sync thread generation no. */
 	wait_queue_head_t	vfs_wait_single_sync_task;
 	wait_queue_head_t	vfs_wait_sync_task;
 } vfs_t;
@@ -204,5 +215,9 @@
 extern void bhv_insert_all_vfsops(struct vfs *);
 extern void bhv_remove_all_vfsops(struct vfs *, int);
 extern void bhv_remove_vfsops(struct vfs *, int);
+
+#define fs_frozen(vfsp)		((vfsp)->vfs_super->s_frozen)
+#define fs_check_frozen(vfsp, level) \
+	vfs_check_frozen(vfsp->vfs_super, level);
 
 #endif	/* __XFS_VFS_H__ */
diff -Nru a/fs/xfs/linux-2.6/xfs_vnode.c b/fs/xfs/linux-2.6/xfs_vnode.c
--- a/fs/xfs/linux-2.6/xfs_vnode.c	2004-10-18 14:56:28 -07:00
+++ b/fs/xfs/linux-2.6/xfs_vnode.c	2004-10-18 14:56:28 -07:00
@@ -188,13 +188,51 @@
 }
 
 /*
+ * Revalidate the Linux inode from the vattr.
+ * Note: i_size _not_ updated; we must hold the inode
+ * semaphore when doing that - callers responsibility.
+ */
+void
+vn_revalidate_core(
+	struct vnode	*vp,
+	vattr_t		*vap)
+{
+	struct inode	*inode = LINVFS_GET_IP(vp);
+
+	inode = LINVFS_GET_IP(vp);
+	inode->i_mode	    = VTTOIF(vap->va_type) | vap->va_mode;
+	inode->i_nlink	    = vap->va_nlink;
+	inode->i_uid	    = vap->va_uid;
+	inode->i_gid	    = vap->va_gid;
+	inode->i_blocks	    = vap->va_nblocks;
+	inode->i_mtime	    = vap->va_mtime;
+	inode->i_ctime	    = vap->va_ctime;
+	inode->i_atime	    = vap->va_atime;
+	if (vap->va_xflags & XFS_XFLAG_IMMUTABLE)
+		inode->i_flags |= S_IMMUTABLE;
+	else
+		inode->i_flags &= ~S_IMMUTABLE;
+	if (vap->va_xflags & XFS_XFLAG_APPEND)
+		inode->i_flags |= S_APPEND;
+	else
+		inode->i_flags &= ~S_APPEND;
+	if (vap->va_xflags & XFS_XFLAG_SYNC)
+		inode->i_flags |= S_SYNC;
+	else
+		inode->i_flags &= ~S_SYNC;
+	if (vap->va_xflags & XFS_XFLAG_NOATIME)
+		inode->i_flags |= S_NOATIME;
+	else
+		inode->i_flags &= ~S_NOATIME;
+}
+
+/*
  * Revalidate the Linux inode from the vnode.
  */
 int
 vn_revalidate(
 	struct vnode	*vp)
 {
-	struct inode	*inode;
 	vattr_t		va;
 	int		error;
 
@@ -204,31 +242,7 @@
 	va.va_mask = XFS_AT_STAT|XFS_AT_XFLAGS;
 	VOP_GETATTR(vp, &va, 0, NULL, error);
 	if (!error) {
-		inode = LINVFS_GET_IP(vp);
-		inode->i_mode	    = VTTOIF(va.va_type) | va.va_mode;
-		inode->i_nlink	    = va.va_nlink;
-		inode->i_uid	    = va.va_uid;
-		inode->i_gid	    = va.va_gid;
-		inode->i_blocks	    = va.va_nblocks;
-		inode->i_mtime	    = va.va_mtime;
-		inode->i_ctime	    = va.va_ctime;
-		inode->i_atime	    = va.va_atime;
-		if (va.va_xflags & XFS_XFLAG_IMMUTABLE)
-			inode->i_flags |= S_IMMUTABLE;
-		else
-			inode->i_flags &= ~S_IMMUTABLE;
-		if (va.va_xflags & XFS_XFLAG_APPEND)
-			inode->i_flags |= S_APPEND;
-		else
-			inode->i_flags &= ~S_APPEND;
-		if (va.va_xflags & XFS_XFLAG_SYNC)
-			inode->i_flags |= S_SYNC;
-		else
-			inode->i_flags &= ~S_SYNC;
-		if (va.va_xflags & XFS_XFLAG_NOATIME)
-			inode->i_flags |= S_NOATIME;
-		else
-			inode->i_flags &= ~S_NOATIME;
+		vn_revalidate_core(vp, &va);
 		VUNMODIFY(vp);
 	}
 	return -error;
diff -Nru a/fs/xfs/linux-2.6/xfs_vnode.h b/fs/xfs/linux-2.6/xfs_vnode.h
--- a/fs/xfs/linux-2.6/xfs_vnode.h	2004-10-18 14:57:05 -07:00
+++ b/fs/xfs/linux-2.6/xfs_vnode.h	2004-10-18 14:57:05 -07:00
@@ -194,7 +194,7 @@
 				loff_t *, int, size_t, read_actor_t,
 				void *, struct cred *);
 typedef int	(*vop_ioctl_t)(bhv_desc_t *, struct inode *, struct file *,
-				int, unsigned int, unsigned long);
+				int, unsigned int, void __user *);
 typedef int	(*vop_getattr_t)(bhv_desc_t *, struct vattr *, int,
 				struct cred *);
 typedef int	(*vop_setattr_t)(bhv_desc_t *, struct vattr *, int,
@@ -532,6 +532,7 @@
 extern void	vn_purge(struct vnode *, vmap_t *);
 extern vnode_t	*vn_get(struct vnode *, vmap_t *);
 extern int	vn_revalidate(struct vnode *);
+extern void	vn_revalidate_core(struct vnode *, vattr_t *);
 extern void	vn_remove(struct vnode *);
 
 static inline int vn_count(struct vnode *vp)
@@ -592,6 +593,19 @@
 #define VN_MTIMESET(vp, tvp)	(LINVFS_GET_IP(vp)->i_mtime = *(tvp))
 #define VN_ATIMESET(vp, tvp)	(LINVFS_GET_IP(vp)->i_atime = *(tvp))
 #define VN_CTIMESET(vp, tvp)	(LINVFS_GET_IP(vp)->i_ctime = *(tvp))
+
+/*
+ * Dealing with bad inodes
+ */
+static inline void vn_mark_bad(struct vnode *vp)
+{
+	make_bad_inode(LINVFS_GET_IP(vp));
+}
+
+static inline int VN_BAD(struct vnode *vp)
+{
+	return is_bad_inode(LINVFS_GET_IP(vp));
+}
 
 /*
  * Some useful predicates.
diff -Nru a/fs/xfs/quota/xfs_dquot.c b/fs/xfs/quota/xfs_dquot.c
--- a/fs/xfs/quota/xfs_dquot.c	2004-10-18 14:56:29 -07:00
+++ b/fs/xfs/quota/xfs_dquot.c	2004-10-18 14:56:29 -07:00
@@ -145,7 +145,7 @@
 		 dqp->q_res_icount = 0;
 		 dqp->q_res_rtbcount = 0;
 		 dqp->q_pincount = 0;
-		 dqp->q_hash = 0;
+		 dqp->q_hash = NULL;
 		 ASSERT(dqp->dq_flnext == dqp->dq_flprev);
 
 #ifdef XFS_DQUOT_TRACE
@@ -187,9 +187,9 @@
  */
 STATIC void
 xfs_qm_dqinit_core(
-	xfs_dqid_t	 id,
-	uint		 type,
-	xfs_dqblk_t	 *d)
+	xfs_dqid_t	id,
+	uint		type,
+	xfs_dqblk_t	*d)
 {
 	/*
 	 * Caller has zero'd the entire dquot 'chunk' already.
@@ -250,6 +250,36 @@
 
 
 /*
+ * If default limits are in force, push them into the dquot now.
+ * We overwrite the dquot limits only if they are zero and this
+ * is not the root dquot.
+ */
+void
+xfs_qm_adjust_dqlimits(
+	xfs_mount_t		*mp,
+	xfs_disk_dquot_t	*d)
+{
+	xfs_quotainfo_t		*q = mp->m_quotainfo;
+
+	ASSERT(!INT_ISZERO(d->d_id, ARCH_CONVERT));
+
+	if (q->qi_bsoftlimit && INT_ISZERO(d->d_blk_softlimit, ARCH_CONVERT))
+		INT_SET(d->d_blk_softlimit, ARCH_CONVERT, q->qi_bsoftlimit);
+	if (q->qi_bhardlimit && INT_ISZERO(d->d_blk_hardlimit, ARCH_CONVERT))
+		INT_SET(d->d_blk_hardlimit, ARCH_CONVERT, q->qi_bhardlimit);
+	if (q->qi_isoftlimit && INT_ISZERO(d->d_ino_softlimit, ARCH_CONVERT))
+		INT_SET(d->d_ino_softlimit, ARCH_CONVERT, q->qi_isoftlimit);
+	if (q->qi_ihardlimit && INT_ISZERO(d->d_ino_hardlimit, ARCH_CONVERT))
+		INT_SET(d->d_ino_hardlimit, ARCH_CONVERT, q->qi_ihardlimit);
+	if (q->qi_rtbsoftlimit &&
+	    INT_ISZERO(d->d_rtb_softlimit, ARCH_CONVERT))
+		INT_SET(d->d_rtb_softlimit, ARCH_CONVERT, q->qi_rtbsoftlimit);
+	if (q->qi_rtbhardlimit &&
+	    INT_ISZERO(d->d_rtb_hardlimit, ARCH_CONVERT))
+		INT_SET(d->d_rtb_hardlimit, ARCH_CONVERT, q->qi_rtbhardlimit);
+}
+
+/*
  * Check the limits and timers of a dquot and start or reset timers
  * if necessary.
  * This gets called even when quota enforcement is OFF, which makes our
@@ -265,51 +295,79 @@
 	xfs_mount_t		*mp,
 	xfs_disk_dquot_t	*d)
 {
-	/*
-	 * The dquot had better be locked. We are modifying it here.
-	 */
-
-	/*
-	 * root's limits are not real limits.
-	 */
-	if (INT_ISZERO(d->d_id, ARCH_CONVERT))
-		return;
+	ASSERT(!INT_ISZERO(d->d_id, ARCH_CONVERT));
 
 #ifdef QUOTADEBUG
 	if (INT_GET(d->d_blk_hardlimit, ARCH_CONVERT))
-		ASSERT(INT_GET(d->d_blk_softlimit, ARCH_CONVERT) <= INT_GET(d->d_blk_hardlimit, ARCH_CONVERT));
+		ASSERT(INT_GET(d->d_blk_softlimit, ARCH_CONVERT) <=
+			INT_GET(d->d_blk_hardlimit, ARCH_CONVERT));
 	if (INT_GET(d->d_ino_hardlimit, ARCH_CONVERT))
-		ASSERT(INT_GET(d->d_ino_softlimit, ARCH_CONVERT) <= INT_GET(d->d_ino_hardlimit, ARCH_CONVERT));
+		ASSERT(INT_GET(d->d_ino_softlimit, ARCH_CONVERT) <=
+			INT_GET(d->d_ino_hardlimit, ARCH_CONVERT));
+	if (INT_GET(d->d_rtb_hardlimit, ARCH_CONVERT))
+		ASSERT(INT_GET(d->d_rtb_softlimit, ARCH_CONVERT) <=
+			INT_GET(d->d_rtb_hardlimit, ARCH_CONVERT));
 #endif
 	if (INT_ISZERO(d->d_btimer, ARCH_CONVERT)) {
 		if ((INT_GET(d->d_blk_softlimit, ARCH_CONVERT) &&
-		    (INT_GET(d->d_bcount, ARCH_CONVERT) >= INT_GET(d->d_blk_softlimit, ARCH_CONVERT))) ||
+		    (INT_GET(d->d_bcount, ARCH_CONVERT) >=
+				INT_GET(d->d_blk_softlimit, ARCH_CONVERT))) ||
 		    (INT_GET(d->d_blk_hardlimit, ARCH_CONVERT) &&
-		    (INT_GET(d->d_bcount, ARCH_CONVERT) >= INT_GET(d->d_blk_hardlimit, ARCH_CONVERT)))) {
-			INT_SET(d->d_btimer, ARCH_CONVERT, get_seconds() + XFS_QI_BTIMELIMIT(mp));
+		    (INT_GET(d->d_bcount, ARCH_CONVERT) >=
+				INT_GET(d->d_blk_hardlimit, ARCH_CONVERT)))) {
+			INT_SET(d->d_btimer, ARCH_CONVERT,
+				get_seconds() + XFS_QI_BTIMELIMIT(mp));
 		}
 	} else {
 		if ((INT_ISZERO(d->d_blk_softlimit, ARCH_CONVERT) ||
-		    (INT_GET(d->d_bcount, ARCH_CONVERT) < INT_GET(d->d_blk_softlimit, ARCH_CONVERT))) &&
+		    (INT_GET(d->d_bcount, ARCH_CONVERT) <
+				INT_GET(d->d_blk_softlimit, ARCH_CONVERT))) &&
 		    (INT_ISZERO(d->d_blk_hardlimit, ARCH_CONVERT) ||
-		    (INT_GET(d->d_bcount, ARCH_CONVERT) < INT_GET(d->d_blk_hardlimit, ARCH_CONVERT)))) {
+		    (INT_GET(d->d_bcount, ARCH_CONVERT) <
+				INT_GET(d->d_blk_hardlimit, ARCH_CONVERT)))) {
 			INT_ZERO(d->d_btimer, ARCH_CONVERT);
 		}
 	}
 
 	if (INT_ISZERO(d->d_itimer, ARCH_CONVERT)) {
 		if ((INT_GET(d->d_ino_softlimit, ARCH_CONVERT) &&
-		    (INT_GET(d->d_icount, ARCH_CONVERT) >= INT_GET(d->d_ino_softlimit, ARCH_CONVERT))) ||
+		    (INT_GET(d->d_icount, ARCH_CONVERT) >=
+				INT_GET(d->d_ino_softlimit, ARCH_CONVERT))) ||
 		    (INT_GET(d->d_ino_hardlimit, ARCH_CONVERT) &&
-		    (INT_GET(d->d_icount, ARCH_CONVERT) >= INT_GET(d->d_ino_hardlimit, ARCH_CONVERT)))) {
-			INT_SET(d->d_itimer, ARCH_CONVERT, get_seconds() + XFS_QI_ITIMELIMIT(mp));
+		    (INT_GET(d->d_icount, ARCH_CONVERT) >=
+				INT_GET(d->d_ino_hardlimit, ARCH_CONVERT)))) {
+			INT_SET(d->d_itimer, ARCH_CONVERT,
+				get_seconds() + XFS_QI_ITIMELIMIT(mp));
 		}
 	} else {
 		if ((INT_ISZERO(d->d_ino_softlimit, ARCH_CONVERT) ||
-		    (INT_GET(d->d_icount, ARCH_CONVERT) < INT_GET(d->d_ino_softlimit, ARCH_CONVERT)))  &&
+		    (INT_GET(d->d_icount, ARCH_CONVERT) <
+				INT_GET(d->d_ino_softlimit, ARCH_CONVERT)))  &&
 		    (INT_ISZERO(d->d_ino_hardlimit, ARCH_CONVERT) ||
-		    (INT_GET(d->d_icount, ARCH_CONVERT) < INT_GET(d->d_ino_hardlimit, ARCH_CONVERT)))) {
+		    (INT_GET(d->d_icount, ARCH_CONVERT) <
+				INT_GET(d->d_ino_hardlimit, ARCH_CONVERT)))) {
 			INT_ZERO(d->d_itimer, ARCH_CONVERT);
+		}
+	}
+
+	if (INT_ISZERO(d->d_rtbtimer, ARCH_CONVERT)) {
+		if ((INT_GET(d->d_rtb_softlimit, ARCH_CONVERT) &&
+		    (INT_GET(d->d_rtbcount, ARCH_CONVERT) >=
+				INT_GET(d->d_rtb_softlimit, ARCH_CONVERT))) ||
+		    (INT_GET(d->d_rtb_hardlimit, ARCH_CONVERT) &&
+		    (INT_GET(d->d_rtbcount, ARCH_CONVERT) >=
+				INT_GET(d->d_rtb_hardlimit, ARCH_CONVERT)))) {
+			INT_SET(d->d_rtbtimer, ARCH_CONVERT,
+				get_seconds() + XFS_QI_RTBTIMELIMIT(mp));
+		}
+	} else {
+		if ((INT_ISZERO(d->d_rtb_softlimit, ARCH_CONVERT) ||
+		    (INT_GET(d->d_rtbcount, ARCH_CONVERT) <
+				INT_GET(d->d_rtb_softlimit, ARCH_CONVERT))) &&
+		    (INT_ISZERO(d->d_rtb_hardlimit, ARCH_CONVERT) ||
+		    (INT_GET(d->d_rtbcount, ARCH_CONVERT) <
+				INT_GET(d->d_rtb_hardlimit, ARCH_CONVERT)))) {
+			INT_ZERO(d->d_rtbtimer, ARCH_CONVERT);
 		}
 	}
 }
diff -Nru a/fs/xfs/quota/xfs_dquot.h b/fs/xfs/quota/xfs_dquot.h
--- a/fs/xfs/quota/xfs_dquot.h	2004-10-18 14:57:04 -07:00
+++ b/fs/xfs/quota/xfs_dquot.h	2004-10-18 14:57:04 -07:00
@@ -209,6 +209,8 @@
 extern void		xfs_qm_dqflock_pushbuf_wait(xfs_dquot_t *dqp);
 extern void		xfs_qm_adjust_dqtimers(xfs_mount_t *,
 					xfs_disk_dquot_t *);
+extern void		xfs_qm_adjust_dqlimits(xfs_mount_t *,
+					xfs_disk_dquot_t *);
 extern int		xfs_qm_dqwarn(xfs_disk_dquot_t *, uint);
 extern int		xfs_qm_dqget(xfs_mount_t *, xfs_inode_t *,
 					xfs_dqid_t, uint, uint, xfs_dquot_t **);
diff -Nru a/fs/xfs/quota/xfs_qm.c b/fs/xfs/quota/xfs_qm.c
--- a/fs/xfs/quota/xfs_qm.c	2004-10-18 14:55:54 -07:00
+++ b/fs/xfs/quota/xfs_qm.c	2004-10-18 14:55:54 -07:00
@@ -229,11 +229,8 @@
 	 */
 	XFS_QM_LOCK(xfs_Gqm);
 
-	if (xfs_Gqm == NULL) {
-		if ((xfs_Gqm = xfs_Gqm_init()) == NULL) {
-			return (XFS_ERROR(EINVAL));
-		}
-	}
+	if (xfs_Gqm == NULL)
+		xfs_Gqm = xfs_Gqm_init();
 	/*
 	 * We can keep a list of all filesystems with quotas mounted for
 	 * debugging and statistical purposes, but ...
@@ -1216,22 +1213,46 @@
 			     XFS_QMOPT_DQSUSER|XFS_QMOPT_DOWARN,
 			     &dqp);
 	if (! error) {
+		xfs_disk_dquot_t	*ddqp = &dqp->q_core;
+
 		/*
 		 * The warnings and timers set the grace period given to
 		 * a user or group before he or she can not perform any
 		 * more writing. If it is zero, a default is used.
 		 */
-		qinf->qi_btimelimit = INT_GET(dqp->q_core.d_btimer, ARCH_CONVERT) ?
-			INT_GET(dqp->q_core.d_btimer, ARCH_CONVERT) : XFS_QM_BTIMELIMIT;
-		qinf->qi_itimelimit = INT_GET(dqp->q_core.d_itimer, ARCH_CONVERT) ?
-			INT_GET(dqp->q_core.d_itimer, ARCH_CONVERT) : XFS_QM_ITIMELIMIT;
-		qinf->qi_rtbtimelimit = INT_GET(dqp->q_core.d_rtbtimer, ARCH_CONVERT) ?
-			INT_GET(dqp->q_core.d_rtbtimer, ARCH_CONVERT) : XFS_QM_RTBTIMELIMIT;
-		qinf->qi_bwarnlimit = INT_GET(dqp->q_core.d_bwarns, ARCH_CONVERT) ?
-			INT_GET(dqp->q_core.d_bwarns, ARCH_CONVERT) : XFS_QM_BWARNLIMIT;
-		qinf->qi_iwarnlimit = INT_GET(dqp->q_core.d_iwarns, ARCH_CONVERT) ?
-			INT_GET(dqp->q_core.d_iwarns, ARCH_CONVERT) : XFS_QM_IWARNLIMIT;
-
+		qinf->qi_btimelimit =
+				INT_GET(ddqp->d_btimer, ARCH_CONVERT) ?
+				INT_GET(ddqp->d_btimer, ARCH_CONVERT) :
+				XFS_QM_BTIMELIMIT;
+		qinf->qi_itimelimit =
+				INT_GET(ddqp->d_itimer, ARCH_CONVERT) ?
+				INT_GET(ddqp->d_itimer, ARCH_CONVERT) :
+				XFS_QM_ITIMELIMIT;
+		qinf->qi_rtbtimelimit =
+				INT_GET(ddqp->d_rtbtimer, ARCH_CONVERT) ?
+				INT_GET(ddqp->d_rtbtimer, ARCH_CONVERT) :
+				XFS_QM_RTBTIMELIMIT;
+		qinf->qi_bwarnlimit =
+				INT_GET(ddqp->d_bwarns, ARCH_CONVERT) ?
+				INT_GET(ddqp->d_bwarns, ARCH_CONVERT) :
+				XFS_QM_BWARNLIMIT;
+		qinf->qi_iwarnlimit =
+				INT_GET(ddqp->d_iwarns, ARCH_CONVERT) ?
+				INT_GET(ddqp->d_iwarns, ARCH_CONVERT) :
+				XFS_QM_IWARNLIMIT;
+		qinf->qi_bhardlimit =
+				INT_GET(ddqp->d_blk_hardlimit, ARCH_CONVERT);
+		qinf->qi_bsoftlimit =
+				INT_GET(ddqp->d_blk_softlimit, ARCH_CONVERT);
+		qinf->qi_ihardlimit =
+				INT_GET(ddqp->d_ino_hardlimit, ARCH_CONVERT);
+		qinf->qi_isoftlimit =
+				INT_GET(ddqp->d_ino_softlimit, ARCH_CONVERT);
+		qinf->qi_rtbhardlimit =
+				INT_GET(ddqp->d_rtb_hardlimit, ARCH_CONVERT);
+		qinf->qi_rtbsoftlimit =
+				INT_GET(ddqp->d_rtb_softlimit, ARCH_CONVERT);
+ 
 		/*
 		 * We sent the XFS_QMOPT_DQSUSER flag to dqget because
 		 * we don't want this dquot cached. We haven't done a
@@ -1691,10 +1712,12 @@
 	}
 
 	/*
-	 * Adjust the timers since we just changed usages
+	 * Set default limits, adjust timers (since we changed usages)
 	 */
-	if (! XFS_IS_SUSER_DQUOT(dqp))
+	if (! XFS_IS_SUSER_DQUOT(dqp)) {
+		xfs_qm_adjust_dqlimits(dqp->q_mount, &dqp->q_core);
 		xfs_qm_adjust_dqtimers(dqp->q_mount, &dqp->q_core);
+	}
 
 	dqp->dq_flags |= XFS_DQ_DIRTY;
 }
@@ -1735,7 +1758,7 @@
 xfs_qm_dqusage_adjust(
 	xfs_mount_t	*mp,		/* mount point for filesystem */
 	xfs_ino_t	ino,		/* inode number to get data for */
-	void		*buffer,	/* not used */
+	void		__user *buffer,	/* not used */
 	int		ubsize,		/* not used */
 	void		*private_data,	/* not used */
 	xfs_daddr_t	bno,		/* starting block of inode cluster */
diff -Nru a/fs/xfs/quota/xfs_qm.h b/fs/xfs/quota/xfs_qm.h
--- a/fs/xfs/quota/xfs_qm.h	2004-10-18 14:56:27 -07:00
+++ b/fs/xfs/quota/xfs_qm.h	2004-10-18 14:56:27 -07:00
@@ -136,9 +136,14 @@
 	xfs_qwarncnt_t	 qi_bwarnlimit;	 /* limit for num warnings */
 	xfs_qwarncnt_t	 qi_iwarnlimit;	 /* limit for num warnings */
 	mutex_t		 qi_quotaofflock;/* to serialize quotaoff */
-	/* Some useful precalculated constants */
 	xfs_filblks_t	 qi_dqchunklen;	 /* # BBs in a chunk of dqs */
 	uint		 qi_dqperchunk;	 /* # ondisk dqs in above chunk */
+	xfs_qcnt_t	 qi_bhardlimit;	 /* default data blk hard limit */
+	xfs_qcnt_t	 qi_bsoftlimit;	 /* default data blk soft limit */
+	xfs_qcnt_t	 qi_ihardlimit;	 /* default inode count hard limit */
+	xfs_qcnt_t	 qi_isoftlimit;	 /* default inode count soft limit */
+	xfs_qcnt_t	 qi_rtbhardlimit;/* default realtime blk hard limit */
+	xfs_qcnt_t	 qi_rtbsoftlimit;/* default realtime blk soft limit */
 } xfs_quotainfo_t;
 
 
@@ -187,7 +192,6 @@
 extern int		xfs_qm_sync(xfs_mount_t *, short);
 
 /* dquot stuff */
-extern void		xfs_qm_dqunlink(xfs_dquot_t *);
 extern boolean_t	xfs_qm_dqalloc_incore(xfs_dquot_t **);
 extern int		xfs_qm_dqattach(xfs_inode_t *, uint);
 extern void		xfs_qm_dqdetach(xfs_inode_t *);
diff -Nru a/fs/xfs/quota/xfs_qm_stats.c b/fs/xfs/quota/xfs_qm_stats.c
--- a/fs/xfs/quota/xfs_qm_stats.c	2004-10-18 14:55:54 -07:00
+++ b/fs/xfs/quota/xfs_qm_stats.c	2004-10-18 14:55:54 -07:00
@@ -137,8 +137,8 @@
 void
 xfs_qm_init_procfs(void)
 {
-	create_proc_read_entry("fs/xfs/xqmstat", 0, 0, xfs_qm_read_stats, NULL);
-	create_proc_read_entry("fs/xfs/xqm", 0, 0, xfs_qm_read_xfsquota, NULL);
+	create_proc_read_entry("fs/xfs/xqmstat", 0, NULL, xfs_qm_read_stats, NULL);
+	create_proc_read_entry("fs/xfs/xqm", 0, NULL, xfs_qm_read_xfsquota, NULL);
 }
 
 void
diff -Nru a/fs/xfs/quota/xfs_qm_syscalls.c b/fs/xfs/quota/xfs_qm_syscalls.c
--- a/fs/xfs/quota/xfs_qm_syscalls.c	2004-10-18 14:56:33 -07:00
+++ b/fs/xfs/quota/xfs_qm_syscalls.c	2004-10-18 14:56:33 -07:00
@@ -648,8 +648,11 @@
 	if (hard == 0 || hard >= soft) {
 		INT_SET(ddq->d_blk_hardlimit, ARCH_CONVERT, hard);
 		INT_SET(ddq->d_blk_softlimit, ARCH_CONVERT, soft);
-	}
-	else {
+		if (id == 0) {
+			mp->m_quotainfo->qi_bhardlimit = hard;
+			mp->m_quotainfo->qi_bsoftlimit = soft;
+		}
+	} else {
 		qdprintk("blkhard %Ld < blksoft %Ld\n", hard, soft);
 	}
 	hard = (newlim->d_fieldmask & FS_DQ_RTBHARD) ?
@@ -661,40 +664,49 @@
 	if (hard == 0 || hard >= soft) {
 		INT_SET(ddq->d_rtb_hardlimit, ARCH_CONVERT, hard);
 		INT_SET(ddq->d_rtb_softlimit, ARCH_CONVERT, soft);
-	}
-	else
+		if (id == 0) {
+			mp->m_quotainfo->qi_rtbhardlimit = hard;
+			mp->m_quotainfo->qi_rtbsoftlimit = soft;
+		}
+	} else {
 		qdprintk("rtbhard %Ld < rtbsoft %Ld\n", hard, soft);
+	}
 
 	hard = (newlim->d_fieldmask & FS_DQ_IHARD) ?
 		(xfs_qcnt_t) newlim->d_ino_hardlimit :
-		INT_GET(ddq->d_ino_hardlimit, ARCH_CONVERT);
+			INT_GET(ddq->d_ino_hardlimit, ARCH_CONVERT);
 	soft = (newlim->d_fieldmask & FS_DQ_ISOFT) ?
 		(xfs_qcnt_t) newlim->d_ino_softlimit :
-		INT_GET(ddq->d_ino_softlimit, ARCH_CONVERT);
+			INT_GET(ddq->d_ino_softlimit, ARCH_CONVERT);
 	if (hard == 0 || hard >= soft) {
 		INT_SET(ddq->d_ino_hardlimit, ARCH_CONVERT, hard);
 		INT_SET(ddq->d_ino_softlimit, ARCH_CONVERT, soft);
-	}
-	else
+		if (id == 0) {
+			mp->m_quotainfo->qi_ihardlimit = hard;
+			mp->m_quotainfo->qi_isoftlimit = soft;
+		}
+	} else {
 		qdprintk("ihard %Ld < isoft %Ld\n", hard, soft);
+	}
 
 	if (id == 0) {
 		/*
 		 * Timelimits for the super user set the relative time
 		 * the other users can be over quota for this file system.
-		 * If it is zero a default is used.
+		 * If it is zero a default is used.  Ditto for the default
+		 * soft and hard limit values (already done, above).
 		 */
 		if (newlim->d_fieldmask & FS_DQ_BTIMER) {
 			mp->m_quotainfo->qi_btimelimit = newlim->d_btimer;
-			INT_SET(dqp->q_core.d_btimer, ARCH_CONVERT, newlim->d_btimer);
+			INT_SET(ddq->d_btimer, ARCH_CONVERT, newlim->d_btimer);
 		}
 		if (newlim->d_fieldmask & FS_DQ_ITIMER) {
 			mp->m_quotainfo->qi_itimelimit = newlim->d_itimer;
-			INT_SET(dqp->q_core.d_itimer, ARCH_CONVERT, newlim->d_itimer);
+			INT_SET(ddq->d_itimer, ARCH_CONVERT, newlim->d_itimer);
 		}
 		if (newlim->d_fieldmask & FS_DQ_RTBTIMER) {
 			mp->m_quotainfo->qi_rtbtimelimit = newlim->d_rtbtimer;
-			INT_SET(dqp->q_core.d_rtbtimer, ARCH_CONVERT, newlim->d_rtbtimer);
+			INT_SET(ddq->d_rtbtimer, ARCH_CONVERT, newlim->d_rtbtimer);
 		}
 	} else /* if (XFS_IS_QUOTA_ENFORCED(mp)) */ {
 		/*
@@ -1114,7 +1126,7 @@
 	  cmn_err(CE_DEBUG, "%s (#%d)", title, (int) (l)->qh_nelems); \
 	  for (dqp = (xfs_dqtest_t *)(l)->qh_next; dqp != NULL; \
 	       dqp = (xfs_dqtest_t *)dqp->NXT) { \
-		cmn_err(CE_DEBUG, "  %d\. \"%d (%s)\"  bcnt = %d, icnt = %d", \
+		cmn_err(CE_DEBUG, "  %d. \"%d (%s)\"  bcnt = %d, icnt = %d", \
 			 ++i, dqp->d_id, DQFLAGTO_TYPESTR(dqp),	     \
 			 dqp->d_bcount, dqp->d_icount); } \
 }
@@ -1299,7 +1311,7 @@
 xfs_qm_internalqcheck_adjust(
 	xfs_mount_t	*mp,		/* mount point for filesystem */
 	xfs_ino_t	ino,		/* inode number to get data for */
-	void		*buffer,	/* not used */
+	void		__user *buffer,	/* not used */
 	int		ubsize,		/* not used */
 	void		*private_data,	/* not used */
 	xfs_daddr_t	bno,		/* starting block of inode cluster */
diff -Nru a/fs/xfs/quota/xfs_trans_dquot.c b/fs/xfs/quota/xfs_trans_dquot.c
--- a/fs/xfs/quota/xfs_trans_dquot.c	2004-10-18 14:56:17 -07:00
+++ b/fs/xfs/quota/xfs_trans_dquot.c	2004-10-18 14:56:17 -07:00
@@ -452,9 +452,13 @@
 				INT_MOD(d->d_rtbcount, ARCH_CONVERT, (xfs_qcnt_t)totalrtbdelta);
 
 			/*
+			 * Get any default limits in use.
 			 * Start/reset the timer(s) if needed.
 			 */
-			xfs_qm_adjust_dqtimers(tp->t_mountp, d);
+			if (!INT_ISZERO(d->d_id, ARCH_CONVERT)) {
+				xfs_qm_adjust_dqlimits(tp->t_mountp, d);
+				xfs_qm_adjust_dqtimers(tp->t_mountp, d);
+			}
 
 			dqp->dq_flags |= XFS_DQ_DIRTY;
 			/*
@@ -625,6 +629,7 @@
 STATIC int
 xfs_trans_dqresv(
 	xfs_trans_t	*tp,
+	xfs_mount_t	*mp,
 	xfs_dquot_t	*dqp,
 	long		nblks,
 	long		ninos,
@@ -635,6 +640,7 @@
 	xfs_qcnt_t	softlimit;
 	time_t		btimer;
 	xfs_qcnt_t	*resbcountp;
+	xfs_quotainfo_t	*q = mp->m_quotainfo;
 
 	if (! (flags & XFS_QMOPT_DQLOCK)) {
 		xfs_dqlock(dqp);
@@ -642,13 +648,21 @@
 	ASSERT(XFS_DQ_IS_LOCKED(dqp));
 	if (flags & XFS_TRANS_DQ_RES_BLKS) {
 		hardlimit = INT_GET(dqp->q_core.d_blk_hardlimit, ARCH_CONVERT);
+		if (!hardlimit)
+			hardlimit = q->qi_bhardlimit;
 		softlimit = INT_GET(dqp->q_core.d_blk_softlimit, ARCH_CONVERT);
+		if (!softlimit)
+			softlimit = q->qi_bsoftlimit;
 		btimer = INT_GET(dqp->q_core.d_btimer, ARCH_CONVERT);
 		resbcountp = &dqp->q_res_bcount;
 	} else {
 		ASSERT(flags & XFS_TRANS_DQ_RES_RTBLKS);
 		hardlimit = INT_GET(dqp->q_core.d_rtb_hardlimit, ARCH_CONVERT);
+		if (!hardlimit)
+			hardlimit = q->qi_rtbhardlimit;
 		softlimit = INT_GET(dqp->q_core.d_rtb_softlimit, ARCH_CONVERT);
+		if (!softlimit)
+			softlimit = q->qi_rtbsoftlimit;
 		btimer = INT_GET(dqp->q_core.d_rtbtimer, ARCH_CONVERT);
 		resbcountp = &dqp->q_res_rtbcount;
 	}
@@ -689,14 +703,18 @@
 			}
 		}
 		if (ninos > 0) {
-			if (INT_GET(dqp->q_core.d_ino_hardlimit, ARCH_CONVERT) > 0ULL &&
-			    INT_GET(dqp->q_core.d_icount, ARCH_CONVERT) >=
-			    INT_GET(dqp->q_core.d_ino_hardlimit, ARCH_CONVERT)) {
+			hardlimit = INT_GET(dqp->q_core.d_ino_hardlimit, ARCH_CONVERT);
+			if (!hardlimit)
+				hardlimit = q->qi_ihardlimit;
+			softlimit = INT_GET(dqp->q_core.d_ino_softlimit, ARCH_CONVERT);
+			if (!softlimit)
+				softlimit = q->qi_isoftlimit;
+			if (hardlimit > 0ULL &&
+			    INT_GET(dqp->q_core.d_icount, ARCH_CONVERT) >= hardlimit) {
 				error = EDQUOT;
 				goto error_return;
-			} else if (INT_GET(dqp->q_core.d_ino_softlimit, ARCH_CONVERT) > 0ULL &&
-				   INT_GET(dqp->q_core.d_icount, ARCH_CONVERT) >=
-				   INT_GET(dqp->q_core.d_ino_softlimit, ARCH_CONVERT)) {
+			} else if (softlimit > 0ULL &&
+				   INT_GET(dqp->q_core.d_icount, ARCH_CONVERT) >= softlimit) {
 				/*
 				 * If timer or warnings has expired,
 				 * return EDQUOT
@@ -786,19 +804,20 @@
 	resvd = 0;
 
 	if (udqp) {
-		if (xfs_trans_dqresv(tp, udqp, nblks, ninos, flags))
+		if (xfs_trans_dqresv(tp, mp, udqp, nblks, ninos, flags))
 			return (EDQUOT);
 		resvd = 1;
 	}
 
 	if (gdqp) {
-		if (xfs_trans_dqresv(tp, gdqp, nblks, ninos, flags)) {
+		if (xfs_trans_dqresv(tp, mp, gdqp, nblks, ninos, flags)) {
 			/*
 			 * can't do it, so backout previous reservation
 			 */
 			if (resvd) {
-				xfs_trans_dqresv(tp, udqp,  -nblks, -ninos,
-						 flags);
+				flags |= XFS_QMOPT_FORCE_RES;
+				xfs_trans_dqresv(tp, mp, udqp,
+						 -nblks, -ninos, flags);
 			}
 			return (EDQUOT);
 		}
diff -Nru a/fs/xfs/support/ktrace.c b/fs/xfs/support/ktrace.c
--- a/fs/xfs/support/ktrace.c	2004-10-18 14:56:29 -07:00
+++ b/fs/xfs/support/ktrace.c	2004-10-18 14:56:29 -07:00
@@ -30,14 +30,7 @@
  * http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/
  */
 
-#include <linux/types.h>
-#include <linux/slab.h>
-
-#include <xfs_types.h>
-#include "kmem.h"
-#include "spin.h"
-#include "debug.h"
-#include "ktrace.h"
+#include <xfs.h>
 
 static kmem_zone_t *ktrace_hdr_zone;
 static kmem_zone_t *ktrace_ent_zone;
diff -Nru a/fs/xfs/support/move.c b/fs/xfs/support/move.c
--- a/fs/xfs/support/move.c	2004-10-18 14:56:32 -07:00
+++ b/fs/xfs/support/move.c	2004-10-18 14:56:32 -07:00
@@ -30,13 +30,7 @@
  * http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/
  */
 
-#include <linux/string.h>
-#include <linux/errno.h>
-#include <asm/uaccess.h>
-
-#include <xfs_types.h>
-#include "debug.h"
-#include "move.h"
+#include <xfs.h>
 
 /* Read from kernel buffer at src to user/kernel buffer defined
  * by the uio structure. Advance the pointer in the uio struct
diff -Nru a/fs/xfs/xfs_acl.h b/fs/xfs/xfs_acl.h
--- a/fs/xfs/xfs_acl.h	2004-10-18 14:56:28 -07:00
+++ b/fs/xfs/xfs_acl.h	2004-10-18 14:56:28 -07:00
@@ -74,8 +74,6 @@
 
 extern int xfs_acl_inherit(struct vnode *, struct vattr *, xfs_acl_t *);
 extern int xfs_acl_iaccess(struct xfs_inode *, mode_t, cred_t *);
-extern int xfs_acl_get(struct vnode *, xfs_acl_t *, xfs_acl_t *);
-extern int xfs_acl_set(struct vnode *, xfs_acl_t *, xfs_acl_t *);
 extern int xfs_acl_vtoacl(struct vnode *, xfs_acl_t *, xfs_acl_t *);
 extern int xfs_acl_vhasacl_access(struct vnode *);
 extern int xfs_acl_vhasacl_default(struct vnode *);
@@ -95,7 +93,7 @@
 #define _ACL_XFS_IACCESS(i,m,c) (XFS_IFORK_Q(i) ? xfs_acl_iaccess(i,m,c) : -1)
 
 #define _ACL_ALLOC(a)		((a) = kmem_zone_alloc(xfs_acl_zone, KM_SLEEP))
-#define _ACL_FREE(a)		((a)? kmem_zone_free(xfs_acl_zone, (a)) : 0)
+#define _ACL_FREE(a)		((a)? kmem_zone_free(xfs_acl_zone, (a)):(void)0)
 
 #else
 #define xfs_acl_zone_init(zone,name)
diff -Nru a/fs/xfs/xfs_alloc.c b/fs/xfs/xfs_alloc.c
--- a/fs/xfs/xfs_alloc.c	2004-10-18 14:56:27 -07:00
+++ b/fs/xfs/xfs_alloc.c	2004-10-18 14:56:27 -07:00
@@ -665,7 +665,7 @@
 	 * Allocate/initialize a cursor for the by-number freespace btree.
 	 */
 	bno_cur = xfs_btree_init_cursor(args->mp, args->tp, args->agbp,
-		args->agno, XFS_BTNUM_BNO, 0, 0);
+		args->agno, XFS_BTNUM_BNO, NULL, 0);
 	/*
 	 * Lookup bno and minlen in the btree (minlen is irrelevant, really).
 	 * Look for the closest free block <= bno, it must contain bno
@@ -721,7 +721,7 @@
 	 * Allocate/initialize a cursor for the by-size btree.
 	 */
 	cnt_cur = xfs_btree_init_cursor(args->mp, args->tp, args->agbp,
-		args->agno, XFS_BTNUM_CNT, 0, 0);
+		args->agno, XFS_BTNUM_CNT, NULL, 0);
 	ASSERT(args->agbno + args->len <=
 		INT_GET(XFS_BUF_TO_AGF(args->agbp)->agf_length,
 			ARCH_CONVERT));
@@ -788,7 +788,7 @@
 	 * Get a cursor for the by-size btree.
 	 */
 	cnt_cur = xfs_btree_init_cursor(args->mp, args->tp, args->agbp,
-		args->agno, XFS_BTNUM_CNT, 0, 0);
+		args->agno, XFS_BTNUM_CNT, NULL, 0);
 	ltlen = 0;
 	bno_cur_lt = bno_cur_gt = NULL;
 	/*
@@ -916,7 +916,7 @@
 		 * Set up a cursor for the by-bno tree.
 		 */
 		bno_cur_lt = xfs_btree_init_cursor(args->mp, args->tp,
-			args->agbp, args->agno, XFS_BTNUM_BNO, 0, 0);
+			args->agbp, args->agno, XFS_BTNUM_BNO, NULL, 0);
 		/*
 		 * Fix up the btree entries.
 		 */
@@ -944,7 +944,7 @@
 	 * Allocate and initialize the cursor for the leftward search.
 	 */
 	bno_cur_lt = xfs_btree_init_cursor(args->mp, args->tp, args->agbp,
-		args->agno, XFS_BTNUM_BNO, 0, 0);
+		args->agno, XFS_BTNUM_BNO, NULL, 0);
 	/*
 	 * Lookup <= bno to find the leftward search's starting point.
 	 */
@@ -956,7 +956,7 @@
 		 * search.
 		 */
 		bno_cur_gt = bno_cur_lt;
-		bno_cur_lt = 0;
+		bno_cur_lt = NULL;
 	}
 	/*
 	 * Found something.  Duplicate the cursor for the rightward search.
@@ -1301,7 +1301,7 @@
 	 * Allocate and initialize a cursor for the by-size btree.
 	 */
 	cnt_cur = xfs_btree_init_cursor(args->mp, args->tp, args->agbp,
-		args->agno, XFS_BTNUM_CNT, 0, 0);
+		args->agno, XFS_BTNUM_CNT, NULL, 0);
 	bno_cur = NULL;
 	/*
 	 * Look for an entry >= maxlen+alignment-1 blocks.
@@ -1406,7 +1406,7 @@
 	 * Allocate and initialize a cursor for the by-block tree.
 	 */
 	bno_cur = xfs_btree_init_cursor(args->mp, args->tp, args->agbp,
-		args->agno, XFS_BTNUM_BNO, 0, 0);
+		args->agno, XFS_BTNUM_BNO, NULL, 0);
 	if ((error = xfs_alloc_fixup_trees(cnt_cur, bno_cur, fbno, flen,
 			rbno, rlen, XFSA_FIXUP_CNT_OK)))
 		goto error0;
@@ -1553,7 +1553,7 @@
 	/*
 	 * Allocate and initialize a cursor for the by-block btree.
 	 */
-	bno_cur = xfs_btree_init_cursor(mp, tp, agbp, agno, XFS_BTNUM_BNO, 0,
+	bno_cur = xfs_btree_init_cursor(mp, tp, agbp, agno, XFS_BTNUM_BNO, NULL,
 		0);
 	cnt_cur = NULL;
 	/*
@@ -1613,7 +1613,7 @@
 	/*
 	 * Now allocate and initialize a cursor for the by-size tree.
 	 */
-	cnt_cur = xfs_btree_init_cursor(mp, tp, agbp, agno, XFS_BTNUM_CNT, 0,
+	cnt_cur = xfs_btree_init_cursor(mp, tp, agbp, agno, XFS_BTNUM_CNT, NULL,
 		0);
 	/*
 	 * Have both left and right contiguous neighbors.
diff -Nru a/fs/xfs/xfs_alloc_btree.c b/fs/xfs/xfs_alloc_btree.c
--- a/fs/xfs/xfs_alloc_btree.c	2004-10-18 14:56:33 -07:00
+++ b/fs/xfs/xfs_alloc_btree.c	2004-10-18 14:56:33 -07:00
@@ -263,7 +263,7 @@
 			/*
 			 * Update the cursor so there's one fewer level.
 			 */
-			xfs_btree_setbuf(cur, level, 0);
+			xfs_btree_setbuf(cur, level, NULL);
 			cur->bc_nlevels--;
 		} else if (level > 0 &&
 			   (error = xfs_alloc_decrement(cur, level, &i)))
diff -Nru a/fs/xfs/xfs_attr.c b/fs/xfs/xfs_attr.c
--- a/fs/xfs/xfs_attr.c	2004-10-18 14:56:33 -07:00
+++ b/fs/xfs/xfs_attr.c	2004-10-18 14:56:33 -07:00
@@ -104,7 +104,6 @@
 STATIC int xfs_attr_rmtval_remove(xfs_da_args_t *args);
 
 #define ATTR_RMTVALUE_MAPSIZE	1	/* # of map entries at once */
-#define ATTR_RMTVALUE_TRANSBLKS	8	/* max # of blks in a transaction */
 
 #if defined(XFS_ATTR_TRACE)
 ktrace_t *xfs_attr_trace_buf;
@@ -122,22 +121,14 @@
 	xfs_da_args_t   args;
 	int             error;
 
-	if (XFS_FORCED_SHUTDOWN(ip->i_mount))
-		return(EIO);
-
 	if ((XFS_IFORK_Q(ip) == 0) ||
 	    (ip->i_d.di_aformat == XFS_DINODE_FMT_EXTENTS &&
 	     ip->i_d.di_anextents == 0))
 		return(ENOATTR);
 
-	if (!(flags & ATTR_KERNACCESS)) {
-		xfs_ilock(ip, XFS_ILOCK_SHARED);
-
-		if (!(flags & ATTR_SECURE) &&
-		    ((error = xfs_iaccess(ip, S_IRUSR, cred)))) {
-			xfs_iunlock(ip, XFS_ILOCK_SHARED);
+	if (!(flags & (ATTR_KERNACCESS|ATTR_SECURE))) {
+		if ((error = xfs_iaccess(ip, S_IRUSR, cred)))
 			return(XFS_ERROR(error));
-		}
 	}
 
 	/*
@@ -168,9 +159,6 @@
 		error = xfs_attr_node_get(&args);
 	}
 
-	if (!(flags & ATTR_KERNACCESS))
-		xfs_iunlock(ip, XFS_ILOCK_SHARED);
-
 	/*
 	 * Return the number of bytes in the value to the caller.
 	 */
@@ -186,7 +174,7 @@
 	     int flags, struct cred *cred)
 {
 	xfs_inode_t	*ip = XFS_BHVTOI(bdp);
-	int		namelen;
+	int		error, namelen;
 
 	XFS_STATS_INC(xs_attr_get);
 
@@ -196,7 +184,13 @@
 	if (namelen >= MAXNAMELEN)
 		return(EFAULT);		/* match IRIX behaviour */
 
-	return xfs_attr_fetch(ip, name, namelen, value, valuelenp, flags, cred);
+	if (XFS_FORCED_SHUTDOWN(ip->i_mount))
+		return(EIO);
+
+	xfs_ilock(ip, XFS_ILOCK_SHARED);
+	error = xfs_attr_fetch(ip, name, namelen, value, valuelenp, flags, cred);
+	xfs_iunlock(ip, XFS_ILOCK_SHARED);
+	return(error);
 }
 
 /*ARGSUSED*/
@@ -719,16 +713,15 @@
 	mp = dp->i_mount;
 	ASSERT(! XFS_NOT_DQATTACHED(mp, dp));
 
-	/* XXXsup - why on earth are we taking ILOCK_EXCL here??? */
-	xfs_ilock(dp, XFS_ILOCK_EXCL);
+	xfs_ilock(dp, XFS_ILOCK_SHARED);
 	if ((XFS_IFORK_Q(dp) == 0) ||
 	    (dp->i_d.di_aformat == XFS_DINODE_FMT_LOCAL) ||
 	    (dp->i_d.di_aformat == XFS_DINODE_FMT_EXTENTS &&
 	     dp->i_d.di_anextents == 0)) {
-		xfs_iunlock(dp, XFS_ILOCK_EXCL);
+		xfs_iunlock(dp, XFS_ILOCK_SHARED);
 		return(0);
 	}
-	xfs_iunlock(dp, XFS_ILOCK_EXCL);
+	xfs_iunlock(dp, XFS_ILOCK_SHARED);
 
 	/*
 	 * Start our first transaction of the day.
diff -Nru a/fs/xfs/xfs_attr_leaf.h b/fs/xfs/xfs_attr_leaf.h
--- a/fs/xfs/xfs_attr_leaf.h	2004-10-18 14:55:46 -07:00
+++ b/fs/xfs/xfs_attr_leaf.h	2004-10-18 14:55:46 -07:00
@@ -246,7 +246,6 @@
 int	xfs_attr_shortform_to_leaf(struct xfs_da_args *args);
 int	xfs_attr_shortform_remove(struct xfs_da_args *remove);
 int	xfs_attr_shortform_list(struct xfs_attr_list_context *context);
-int	xfs_attr_shortform_replace(struct xfs_da_args *args);
 int	xfs_attr_shortform_allfit(struct xfs_dabuf *bp, struct xfs_inode *dp);
 
 /*
diff -Nru a/fs/xfs/xfs_bmap.c b/fs/xfs/xfs_bmap.c
--- a/fs/xfs/xfs_bmap.c	2004-10-18 14:57:03 -07:00
+++ b/fs/xfs/xfs_bmap.c	2004-10-18 14:57:03 -07:00
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2000-2003 Silicon Graphics, Inc.  All Rights Reserved.
+ * Copyright (c) 2000-2004 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
@@ -203,8 +203,6 @@
 xfs_bmap_check_extents(
 	xfs_inode_t		*ip,		/* incore inode pointer */
 	int			whichfork);	/* data or attr fork */
-#else
-#define	xfs_bmap_check_extents(ip,w)
 #endif
 
 /*
@@ -3429,6 +3427,20 @@
 	int		high;		/* high index of binary search */
 	int		low;		/* low index of binary search */
 
+	/*
+	 * Initialize the extent entry structure to catch access to
+	 * uninitialized br_startblock field.
+	 */
+	got.br_startoff = 0xffa5a5a5a5a5a5a5LL;
+	got.br_blockcount = 0xa55a5a5a5a5a5a5aLL;
+	got.br_state = XFS_EXT_INVALID;
+
+#if XFS_BIG_BLKNOS
+	got.br_startblock = 0xffffa5a5a5a5a5a5LL;
+#else
+	got.br_startblock = 0xffffa5a5;
+#endif
+
 	if (lastx != NULLEXTNUM && lastx < nextents)
 		ep = base + lastx;
 	else
@@ -3527,6 +3539,8 @@
 	xfs_bmbt_rec_t  *base;          /* base of extent list */
 	xfs_extnum_t    lastx;          /* last extent index used */
 	xfs_extnum_t    nextents;       /* extent list size */
+	xfs_bmbt_rec_t  *ep;            /* extent list entry pointer */
+	int		rt;		/* realtime flag    */
 
 	XFS_STATS_INC(xs_look_exlist);
 	ifp = XFS_IFORK_PTR(ip, whichfork);
@@ -3534,8 +3548,18 @@
 	nextents = ifp->if_bytes / (uint)sizeof(xfs_bmbt_rec_t);
 	base = &ifp->if_u1.if_extents[0];
 
-	return xfs_bmap_do_search_extents(base, lastx, nextents, bno, eofp,
+	ep = xfs_bmap_do_search_extents(base, lastx, nextents, bno, eofp,
 					  lastxp, gotp, prevp);
+	rt = ip->i_d.di_flags & XFS_DIFLAG_REALTIME;
+	if(!rt && !gotp->br_startblock && (*lastxp != NULLEXTNUM)) {
+                cmn_err(CE_PANIC,"Access to block zero: fs: <%s> inode: %lld "
+			"start_block : %llx start_off : %llx blkcnt : %llx "
+			"extent-state : %x \n",
+			(ip->i_mount)->m_fsname,(long long)ip->i_ino,
+			gotp->br_startblock, gotp->br_startoff,
+			gotp->br_blockcount,gotp->br_state);
+        }
+        return ep;
 }
 
 
@@ -4689,8 +4713,41 @@
 					}
 					break;
 				}
+
+				/*
+				 * Split changing sb for alen and indlen since
+				 * they could be coming from different places.
+				 */
+				if (ip->i_d.di_flags & XFS_DIFLAG_REALTIME) {
+					xfs_extlen_t	extsz;
+					xfs_extlen_t	ralen;
+					if (!(extsz = ip->i_d.di_extsize))
+						extsz = mp->m_sb.sb_rextsize;
+					ralen = roundup(alen, extsz);
+					ralen = ralen / mp->m_sb.sb_rextsize;
+					if (xfs_mod_incore_sb(mp,
+						XFS_SBS_FREXTENTS,
+						-(ralen), rsvd)) {
+						if (XFS_IS_QUOTA_ON(ip->i_mount))
+							XFS_TRANS_UNRESERVE_BLKQUOTA(
+						     		mp, NULL, ip,
+								(long)alen);
+						break;
+					}
+				} else {
+					if (xfs_mod_incore_sb(mp,
+							      XFS_SBS_FDBLOCKS,
+							      -(alen), rsvd)) {
+						if (XFS_IS_QUOTA_ON(ip->i_mount))
+							XFS_TRANS_UNRESERVE_BLKQUOTA(
+								mp, NULL, ip,
+								(long)alen);
+						break;
+					}
+				}
+
 				if (xfs_mod_incore_sb(mp, XFS_SBS_FDBLOCKS,
-						-(alen + indlen), rsvd)) {
+						-(indlen), rsvd)) {
 					XFS_TRANS_UNRESERVE_BLKQUOTA(
 						mp, NULL, ip, (long)alen);
 					break;
@@ -5445,7 +5502,7 @@
 xfs_getbmap(
 	bhv_desc_t		*bdp,		/* XFS behavior descriptor*/
 	struct getbmap		*bmv,		/* user bmap structure */
-	void			*ap,		/* pointer to user's array */
+	void			__user *ap,	/* pointer to user's array */
 	int			interface)	/* interface flags */
 {
 	__int64_t		bmvend;		/* last block requested */
@@ -5634,8 +5691,10 @@
 					(__int64_t)(bmvend - bmv->bmv_offset));
 				bmv->bmv_entries++;
 				ap = (interface & BMV_IF_EXTENDED) ?
-					(void *)((struct getbmapx *)ap + 1) :
-					(void *)((struct getbmap *)ap + 1);
+						(void __user *)
+					((struct getbmapx __user *)ap + 1) :
+						(void __user *)
+					((struct getbmap __user *)ap + 1);
 			}
 		}
 	} while (nmap && nexleft && bmv->bmv_length);
diff -Nru a/fs/xfs/xfs_bmap.h b/fs/xfs/xfs_bmap.h
--- a/fs/xfs/xfs_bmap.h	2004-10-18 14:56:21 -07:00
+++ b/fs/xfs/xfs_bmap.h	2004-10-18 14:56:21 -07:00
@@ -328,7 +328,7 @@
 xfs_getbmap(
 	bhv_desc_t		*bdp,		/* XFS behavior descriptor*/
 	struct getbmap		*bmv,		/* user bmap structure */
-	void			*ap,		/* pointer to user's array */
+	void			__user *ap,	/* pointer to user's array */
 	int			iflags);	/* interface flags */
 
 /*
diff -Nru a/fs/xfs/xfs_bmap_btree.c b/fs/xfs/xfs_bmap_btree.c
--- a/fs/xfs/xfs_bmap_btree.c	2004-10-18 14:56:32 -07:00
+++ b/fs/xfs/xfs_bmap_btree.c	2004-10-18 14:56:32 -07:00
@@ -1953,7 +1953,7 @@
 		*bpp = cur->bc_bufs[level];
 		rval = XFS_BUF_TO_BMBT_BLOCK(*bpp);
 	} else {
-		*bpp = 0;
+		*bpp = NULL;
 		ifp = XFS_IFORK_PTR(cur->bc_private.b.ip,
 			cur->bc_private.b.whichfork);
 		rval = ifp->if_broot;
diff -Nru a/fs/xfs/xfs_bmap_btree.h b/fs/xfs/xfs_bmap_btree.h
--- a/fs/xfs/xfs_bmap_btree.h	2004-10-18 14:56:32 -07:00
+++ b/fs/xfs/xfs_bmap_btree.h	2004-10-18 14:56:32 -07:00
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2000 Silicon Graphics, Inc.  All Rights Reserved.
+ * Copyright (c) 2000,2002-2004 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
@@ -153,7 +153,7 @@
  */
 typedef enum {
 	XFS_EXT_NORM, XFS_EXT_UNWRITTEN,
-	XFS_EXT_DMAPI_OFFLINE
+	XFS_EXT_DMAPI_OFFLINE, XFS_EXT_INVALID
 } xfs_exntst_t;
 
 /*
@@ -549,13 +549,6 @@
 int
 xfs_bmbt_insert(
 	struct xfs_btree_cur *,
-	int *);
-
-int
-xfs_bmbt_insert_many(
-	struct xfs_btree_cur *,
-	int,
-	xfs_bmbt_rec_t *,
 	int *);
 
 void
diff -Nru a/fs/xfs/xfs_buf_item.c b/fs/xfs/xfs_buf_item.c
--- a/fs/xfs/xfs_buf_item.c	2004-10-18 14:55:54 -07:00
+++ b/fs/xfs/xfs_buf_item.c	2004-10-18 14:55:54 -07:00
@@ -55,8 +55,6 @@
 #include "xfs_error.h"
 
 
-#define	ROUNDUPNBWORD(x)	(((x) + (NBWORD - 1)) & ~(NBWORD - 1))
-
 kmem_zone_t	*xfs_buf_item_zone;
 
 #ifdef XFS_TRANS_DEBUG
diff -Nru a/fs/xfs/xfs_cap.c b/fs/xfs/xfs_cap.c
--- a/fs/xfs/xfs_cap.c	2004-10-18 14:56:29 -07:00
+++ /dev/null	Wed Dec 31 16:00:00 196900
@@ -1,206 +0,0 @@
-/*
- * Copyright (c) 2002 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/SGIGPLNoticeExplan/
- */
-
-#include "xfs.h"
-
-STATIC int xfs_cap_allow_set(vnode_t *);
-
-
-/*
- * Test for existence of capability attribute as efficiently as possible.
- */
-int
-xfs_cap_vhascap(
-	vnode_t		*vp)
-{
-	int		error;
-	int		len = sizeof(xfs_cap_set_t);
-	int		flags = ATTR_KERNOVAL|ATTR_ROOT;
-
-	VOP_ATTR_GET(vp, SGI_CAP_LINUX, NULL, &len, flags, sys_cred, error);
-	return (error == 0);
-}
-
-/*
- * Convert from extended attribute representation to in-memory for XFS.
- */
-STATIC int
-posix_cap_xattr_to_xfs(
-	posix_cap_xattr		*src,
-	size_t			size,
-	xfs_cap_set_t		*dest)
-{
-	if (!src || !dest)
-		return EINVAL;
-
-	if (src->c_version != cpu_to_le32(POSIX_CAP_XATTR_VERSION))
-		return EINVAL;
-	if (src->c_abiversion != cpu_to_le32(_LINUX_CAPABILITY_VERSION))
-		return EINVAL;
-
-	if (size < sizeof(posix_cap_xattr))
-		return EINVAL;
-
-	ASSERT(sizeof(dest->cap_effective) == sizeof(src->c_effective));
-
-	dest->cap_effective	= src->c_effective;
-	dest->cap_permitted	= src->c_permitted;
-	dest->cap_inheritable	= src->c_inheritable;
-
-	return 0;
-}
-
-/*
- * Convert from in-memory XFS to extended attribute representation.
- */
-STATIC int
-posix_cap_xfs_to_xattr(
-	xfs_cap_set_t		*src,
-	posix_cap_xattr		*xattr_cap,
-	size_t			size)
-{
-	size_t			new_size = posix_cap_xattr_size();
-
-	if (size < new_size)
-		return -ERANGE;
-
-	ASSERT(sizeof(xattr_cap->c_effective) == sizeof(src->cap_effective));
-
-	xattr_cap->c_version	= cpu_to_le32(POSIX_CAP_XATTR_VERSION);
-	xattr_cap->c_abiversion	= cpu_to_le32(_LINUX_CAPABILITY_VERSION);
-	xattr_cap->c_effective	= src->cap_effective;
-	xattr_cap->c_permitted	= src->cap_permitted;
-	xattr_cap->c_inheritable= src->cap_inheritable;
-
-	return new_size;
-}
-
-int
-xfs_cap_vget(
-	vnode_t		*vp,
-	void		*cap,
-	size_t		size)
-{
-	int		error;
-	int		len = sizeof(xfs_cap_set_t);
-	int		flags = ATTR_ROOT;
-	xfs_cap_set_t	xfs_cap = { 0 };
-	posix_cap_xattr	*xattr_cap = cap;
-	char		*data = (char *)&xfs_cap;
-
-	VN_HOLD(vp);
-	if ((error = _MAC_VACCESS(vp, NULL, VREAD)))
-		goto out;
-
-	if (!size) {
-		flags |= ATTR_KERNOVAL;
-		data = NULL;
-	}
-	VOP_ATTR_GET(vp, SGI_CAP_LINUX, data, &len, flags, sys_cred, error);
-	if (error)
-		goto out;
-	ASSERT(len == sizeof(xfs_cap_set_t));
-
-	error = (size)? -posix_cap_xattr_size() :
-			-posix_cap_xfs_to_xattr(&xfs_cap, xattr_cap, size);
-out:
-	VN_RELE(vp);
-	return -error;
-}
-
-int
-xfs_cap_vremove(
-	vnode_t		*vp)
-{
-	int		error;
-
-	VN_HOLD(vp);
-	error = xfs_cap_allow_set(vp);
-	if (!error) {
-		VOP_ATTR_REMOVE(vp, SGI_CAP_LINUX, ATTR_ROOT, sys_cred, error);
-		if (error == ENOATTR)
-			error = 0;	/* 'scool */
-	}
-	VN_RELE(vp);
-	return -error;
-}
-
-int
-xfs_cap_vset(
-	vnode_t			*vp,
-	void			*cap,
-	size_t			size)
-{
-	posix_cap_xattr		*xattr_cap = cap;
-	xfs_cap_set_t		xfs_cap;
-	int			error;
-
-	if (!cap)
-		return -EINVAL;
-
-	error = posix_cap_xattr_to_xfs(xattr_cap, size, &xfs_cap);
-	if (error)
-		return -error;
-
-	VN_HOLD(vp);
-	error = xfs_cap_allow_set(vp);
-	if (error)
-		goto out;
-
-	VOP_ATTR_SET(vp, SGI_CAP_LINUX, (char *)&xfs_cap,
-			sizeof(xfs_cap_set_t), ATTR_ROOT, sys_cred, error);
-out:
-	VN_RELE(vp);
-	return -error;
-}
-
-STATIC int
-xfs_cap_allow_set(
-	vnode_t		*vp)
-{
-	vattr_t		va;
-	int		error;
-
-	if (vp->v_vfsp->vfs_flag & VFS_RDONLY)
-		return EROFS;
-	if (vp->v_inode.i_flags & (S_IMMUTABLE|S_APPEND))
-		return EPERM;
-	if ((error = _MAC_VACCESS(vp, NULL, VWRITE)))
-		return error;
-	va.va_mask = XFS_AT_UID;
-	VOP_GETATTR(vp, &va, 0, NULL, error);
-	if (error)
-		return error;
-	if (va.va_uid != current->fsuid && !capable(CAP_FOWNER))
-		return EPERM;
-	return error;
-}
diff -Nru a/fs/xfs/xfs_da_btree.c b/fs/xfs/xfs_da_btree.c
--- a/fs/xfs/xfs_da_btree.c	2004-10-18 14:56:49 -07:00
+++ b/fs/xfs/xfs_da_btree.c	2004-10-18 14:56:49 -07:00
@@ -2092,7 +2092,7 @@
 	int		caller,
 	inst_t		*ra)
 {
-	xfs_buf_t	*bp = 0;
+	xfs_buf_t	*bp = NULL;
 	xfs_buf_t	**bplist;
 	int		error=0;
 	int		i;
diff -Nru a/fs/xfs/xfs_dfrag.c b/fs/xfs/xfs_dfrag.c
--- a/fs/xfs/xfs_dfrag.c	2004-10-18 14:55:54 -07:00
+++ b/fs/xfs/xfs_dfrag.c	2004-10-18 14:55:54 -07:00
@@ -65,7 +65,7 @@
  */
 int
 xfs_swapext(
-	xfs_swapext_t   *sxp)
+	xfs_swapext_t	__user *sxp)
 {
 	xfs_swapext_t	sx;
 	xfs_inode_t     *ip=NULL, *tip=NULL, *ips[2];
diff -Nru a/fs/xfs/xfs_dfrag.h b/fs/xfs/xfs_dfrag.h
--- a/fs/xfs/xfs_dfrag.h	2004-10-18 14:56:32 -07:00
+++ b/fs/xfs/xfs_dfrag.h	2004-10-18 14:56:32 -07:00
@@ -60,7 +60,7 @@
 /*
  * Syscall interface for xfs_swapext
  */
-int	xfs_swapext(struct xfs_swapext *sx);
+int	xfs_swapext(struct xfs_swapext __user *sx);
 
 #endif	/* __KERNEL__ */
 
diff -Nru a/fs/xfs/xfs_dinode.h b/fs/xfs/xfs_dinode.h
--- a/fs/xfs/xfs_dinode.h	2004-10-18 14:56:33 -07:00
+++ b/fs/xfs/xfs_dinode.h	2004-10-18 14:56:33 -07:00
@@ -456,6 +456,9 @@
 #define XFS_DIFLAG_SYNC_BIT      5	/* inode is written synchronously */
 #define XFS_DIFLAG_NOATIME_BIT   6	/* do not update atime */
 #define XFS_DIFLAG_NODUMP_BIT    7	/* do not dump */
+#define XFS_DIFLAG_RTINHERIT_BIT 8	/* create with realtime bit set */
+#define XFS_DIFLAG_PROJINHERIT_BIT  9	/* create with parents projid */
+#define XFS_DIFLAG_NOSYMLINKS_BIT  10	/* disallow symlink creation */
 #define XFS_DIFLAG_REALTIME      (1 << XFS_DIFLAG_REALTIME_BIT)
 #define XFS_DIFLAG_PREALLOC      (1 << XFS_DIFLAG_PREALLOC_BIT)
 #define XFS_DIFLAG_NEWRTBM       (1 << XFS_DIFLAG_NEWRTBM_BIT)
@@ -464,5 +467,14 @@
 #define XFS_DIFLAG_SYNC          (1 << XFS_DIFLAG_SYNC_BIT)
 #define XFS_DIFLAG_NOATIME       (1 << XFS_DIFLAG_NOATIME_BIT)
 #define XFS_DIFLAG_NODUMP        (1 << XFS_DIFLAG_NODUMP_BIT)
+#define XFS_DIFLAG_RTINHERIT     (1 << XFS_DIFLAG_RTINHERIT_BIT)
+#define XFS_DIFLAG_PROJINHERIT   (1 << XFS_DIFLAG_PROJINHERIT_BIT)
+#define XFS_DIFLAG_NOSYMLINKS    (1 << XFS_DIFLAG_NOSYMLINKS_BIT)
+
+#define XFS_DIFLAG_ANY \
+	(XFS_DIFLAG_REALTIME | XFS_DIFLAG_PREALLOC | XFS_DIFLAG_NEWRTBM | \
+	 XFS_DIFLAG_IMMUTABLE | XFS_DIFLAG_APPEND | XFS_DIFLAG_SYNC | \
+	 XFS_DIFLAG_NOATIME | XFS_DIFLAG_NODUMP | XFS_DIFLAG_RTINHERIT | \
+	 XFS_DIFLAG_PROJINHERIT | XFS_DIFLAG_NOSYMLINKS)
 
 #endif	/* __XFS_DINODE_H__ */
diff -Nru a/fs/xfs/xfs_dir2_trace.c b/fs/xfs/xfs_dir2_trace.c
--- a/fs/xfs/xfs_dir2_trace.c	2004-10-18 14:56:49 -07:00
+++ b/fs/xfs/xfs_dir2_trace.c	2004-10-18 14:56:49 -07:00
@@ -211,7 +211,7 @@
 		(void *)((unsigned long)(args->inumber >> 32)),
 		(void *)((unsigned long)(args->inumber & 0xFFFFFFFF)),
 		(void *)args->dp, (void *)args->trans,
-		(void *)(unsigned long)args->justcheck, (void *)(long)s, 0);
+		(void *)(unsigned long)args->justcheck, (void *)(long)s, NULL);
 }
 
 void
diff -Nru a/fs/xfs/xfs_fs.h b/fs/xfs/xfs_fs.h
--- a/fs/xfs/xfs_fs.h	2004-10-18 14:56:20 -07:00
+++ b/fs/xfs/xfs_fs.h	2004-10-18 14:56:20 -07:00
@@ -76,6 +76,9 @@
 #define XFS_XFLAG_SYNC		0x00000020	/* all writes synchronous */
 #define XFS_XFLAG_NOATIME	0x00000040	/* do not update access time */
 #define XFS_XFLAG_NODUMP	0x00000080	/* do not include in backups */
+#define XFS_XFLAG_RTINHERIT	0x00000100	/* create with rt bit set */
+#define XFS_XFLAG_PROJINHERIT	0x00000200	/* create with parents projid */
+#define XFS_XFLAG_NOSYMLINKS	0x00000400	/* disallow symlink creation */
 #define XFS_XFLAG_HASATTR	0x80000000	/* no DIFLAG for this	*/
 
 /*
@@ -164,7 +167,7 @@
 	__s64		l_start;
 	__s64		l_len;		/* len == 0 means until end of file */
 	__s32		l_sysid;
-	pid_t		l_pid;
+	__u32		l_pid;
 	__s32		l_pad[4];	/* reserve area			    */
 } xfs_flock64_t;
 
@@ -313,10 +316,10 @@
  * The user-level BulkStat Request interface structure.
  */
 typedef struct xfs_fsop_bulkreq {
-	__u64		*lastip;	/* last inode # pointer		*/
+	__u64		__user *lastip;	/* last inode # pointer		*/
 	__s32		icount;		/* count of entries in buffer	*/
-	void		*ubuffer;	/* user buffer for inode desc.	*/
-	__s32		*ocount;	/* output count pointer		*/
+	void		__user *ubuffer;/* user buffer for inode desc.	*/
+	__s32		__user *ocount;	/* output count pointer		*/
 } xfs_fsop_bulkreq_t;
 
 
@@ -344,12 +347,12 @@
  */
 typedef struct xfs_fsop_handlereq {
 	__u32		fd;		/* fd for FD_TO_HANDLE		*/
-	void		*path;		/* user pathname		*/
+	void		__user *path;	/* user pathname		*/
 	__u32		oflags;		/* open flags			*/
-	void		*ihandle;	/* user supplied handle		*/
+	void		__user *ihandle;/* user supplied handle		*/
 	__u32		ihandlen;	/* user supplied length		*/
-	void		*ohandle;	/* user buffer for handle	*/
-	__u32		*ohandlen;	/* user buffer length		*/
+	void		__user *ohandle;/* user buffer for handle	*/
+	__u32		__user *ohandlen;/* user buffer length		*/
 } xfs_fsop_handlereq_t;
 
 /*
@@ -360,35 +363,35 @@
  */
 
 typedef struct xfs_fsop_setdm_handlereq {
-	struct xfs_fsop_handlereq hreq; /* handle interface structure */
-	struct fsdmidata *data;		/* DMAPI data to set	      */
+	struct xfs_fsop_handlereq	hreq;	/* handle information	*/
+	struct fsdmidata		__user *data;	/* DMAPI data	*/
 } xfs_fsop_setdm_handlereq_t;
 
 typedef struct xfs_attrlist_cursor {
-	__u32	opaque[4];
+	__u32		opaque[4];
 } xfs_attrlist_cursor_t;
 
 typedef struct xfs_fsop_attrlist_handlereq {
-	struct xfs_fsop_handlereq hreq; /* handle interface structure */
-	struct xfs_attrlist_cursor pos; /* opaque cookie, list offset */
-	__u32 flags;			/* flags, use ROOT/USER names */
-	__u32 buflen;			/* length of buffer supplied  */
-	void *buffer;			/* attrlist data to return    */
+	struct xfs_fsop_handlereq	hreq; /* handle interface structure */
+	struct xfs_attrlist_cursor	pos; /* opaque cookie, list offset */
+	__u32				flags;	/* which namespace to use */
+	__u32				buflen;	/* length of buffer supplied */
+	void				__user *buffer;	/* returned names */
 } xfs_fsop_attrlist_handlereq_t;
 
 typedef struct xfs_attr_multiop {
-	__u32	am_opcode;
-	__s32	am_error;
-	void	*am_attrname;
-	void	*am_attrvalue;
-	__u32	am_length;
-	__u32	am_flags;
+	__u32		am_opcode;
+	__s32		am_error;
+	void		__user *am_attrname;
+	void		__user *am_attrvalue;
+	__u32		am_length;
+	__u32		am_flags;
 } xfs_attr_multiop_t;
 
 typedef struct xfs_fsop_attrmulti_handlereq {
-	struct xfs_fsop_handlereq hreq; /* handle interface structure */
-	__u32 opcount;			/* count of following multiop */
-	struct xfs_attr_multiop *ops;	/* attr_multi data to get/set */
+	struct xfs_fsop_handlereq	hreq; /* handle interface structure */
+	__u32				opcount;/* count of following multiop */
+	struct xfs_attr_multiop		__user *ops; /* attr_multi data */
 } xfs_fsop_attrmulti_handlereq_t;
 
 /*
@@ -443,6 +446,13 @@
 #define XFS_FSOP_GOING_FLAGS_DEFAULT		0x0	/* going down */
 #define XFS_FSOP_GOING_FLAGS_LOGFLUSH		0x1	/* flush log but not data */
 #define XFS_FSOP_GOING_FLAGS_NOLOGFLUSH		0x2	/* don't flush log nor data */
+
+/*
+ * ioctl commands that are used by Linux filesystems
+ */
+#define XFS_IOC_GETXFLAGS	_IOR('f', 1, long)
+#define XFS_IOC_SETXFLAGS	_IOW('f', 2, long)
+#define XFS_IOC_GETVERSION	_IOR('v', 1, long)
 
 /*
  * ioctl commands that replace IRIX fcntl()'s
diff -Nru a/fs/xfs/xfs_fsops.c b/fs/xfs/xfs_fsops.c
--- a/fs/xfs/xfs_fsops.c	2004-10-18 14:57:03 -07:00
+++ b/fs/xfs/xfs_fsops.c	2004-10-18 14:57:03 -07:00
@@ -142,6 +142,7 @@
 	int			dpct;
 	int			error;
 	xfs_agnumber_t		nagcount;
+	xfs_agnumber_t		nagimax = 0;
 	xfs_rfsblock_t		nb, nb_mod;
 	xfs_rfsblock_t		new;
 	xfs_rfsblock_t		nfree;
@@ -183,7 +184,7 @@
 		memset(&mp->m_perag[oagcount], 0,
 			(nagcount - oagcount) * sizeof(xfs_perag_t));
 		mp->m_flags |= XFS_MOUNT_32BITINODES;
-		xfs_initialize_perag(mp, nagcount);
+		nagimax = xfs_initialize_perag(mp, nagcount);
 		up_write(&mp->m_peraglock);
 	}
 	tp = xfs_trans_alloc(mp, XFS_TRANS_GROWFS);
@@ -372,6 +373,9 @@
 	if (error) {
 		return error;
 	}
+	/* New allocation groups fully initialized, so update mount struct */
+	if (nagimax)
+		mp->m_maxagi = nagimax;
 	if (mp->m_sb.sb_imax_pct) {
 		__uint64_t icount = mp->m_sb.sb_dblocks * mp->m_sb.sb_imax_pct;
 		do_div(icount, 100);
@@ -507,9 +511,9 @@
 	__uint64_t              *inval,
 	xfs_fsop_resblks_t      *outval)
 {
-	__uint64_t              lcounter, delta;
-	__uint64_t              request;
-	unsigned long s;
+	__int64_t		lcounter, delta;
+	__uint64_t		request;
+	unsigned long		s;
 
 	/* If inval is null, report current values and return */
 
@@ -536,8 +540,7 @@
 		mp->m_resblks = request;
 	} else {
 		delta = request - mp->m_resblks;
-		lcounter = mp->m_sb.sb_fdblocks;
-		lcounter -= delta;
+		lcounter = mp->m_sb.sb_fdblocks - delta;
 		if (lcounter < 0) {
 			/* We can't satisfy the request, just get what we can */
 			mp->m_resblks += mp->m_sb.sb_fdblocks;
@@ -587,9 +590,6 @@
 	xfs_mount_t	*mp,
 	__uint32_t	inflags)
 {
-	if (!capable(CAP_SYS_ADMIN))
-		return -EPERM;
-
 	switch (inflags) {
 	case XFS_FSOP_GOING_FLAGS_DEFAULT: {
 		struct vfs *vfsp = XFS_MTOVFS(mp);
@@ -599,7 +599,7 @@
 			xfs_force_shutdown(mp, XFS_FORCE_UMOUNT);
 			thaw_bdev(sb->s_bdev, sb);
 		}
-
+	
 		break;
 	}
 	case XFS_FSOP_GOING_FLAGS_LOGFLUSH:
diff -Nru a/fs/xfs/xfs_iget.c b/fs/xfs/xfs_iget.c
--- a/fs/xfs/xfs_iget.c	2004-10-18 14:57:04 -07:00
+++ b/fs/xfs/xfs_iget.c	2004-10-18 14:57:04 -07:00
@@ -457,7 +457,7 @@
 			error = xfs_iget_core(vp, mp, tp, ino,
 						lock_flags, ipp, bno);
 			if (error) {
-				make_bad_inode(inode);
+				vn_mark_bad(vp);
 				if (inode->i_state & I_NEW)
 					unlock_new_inode(inode);
 				iput(inode);
@@ -576,11 +576,8 @@
 
 	vn_trace_entry(vp, "xfs_iput_new", (inst_t *)__return_address);
 
-	/* We shouldn't get here without this being true, but just in case */
-	if (inode->i_state & I_NEW) {
-		make_bad_inode(inode);
+	if (inode->i_state & I_NEW)
 		unlock_new_inode(inode);
-	}
 	if (lock_flags)
 		xfs_iunlock(ip, lock_flags);
 	VN_RELE(vp);
diff -Nru a/fs/xfs/xfs_inode.c b/fs/xfs/xfs_inode.c
--- a/fs/xfs/xfs_inode.c	2004-10-18 14:57:04 -07:00
+++ b/fs/xfs/xfs_inode.c	2004-10-18 14:57:04 -07:00
@@ -860,25 +860,32 @@
 	xfs_arch_t		arch)
 {
 	__uint16_t		di_flags;
-	uint			flags = 0;
+	uint			flags;
 
 	di_flags = INT_GET(dic->di_flags, arch);
-	if (di_flags & XFS_DIFLAG_REALTIME)
-		flags |= XFS_XFLAG_REALTIME;
-	if (di_flags & XFS_DIFLAG_PREALLOC)
-		flags |= XFS_XFLAG_PREALLOC;
-	if (di_flags & XFS_DIFLAG_IMMUTABLE)
-		flags |= XFS_XFLAG_IMMUTABLE;
-	if (di_flags & XFS_DIFLAG_APPEND)
-		flags |= XFS_XFLAG_APPEND;
-	if (di_flags & XFS_DIFLAG_SYNC)
-		flags |= XFS_XFLAG_SYNC;
-	if (di_flags & XFS_DIFLAG_NOATIME)
-		flags |= XFS_XFLAG_NOATIME;
-	if (di_flags & XFS_DIFLAG_NODUMP)
-		flags |= XFS_XFLAG_NODUMP;
-	if (XFS_CFORK_Q_ARCH(dic, arch))
-		flags |= XFS_XFLAG_HASATTR;
+	flags = XFS_CFORK_Q_ARCH(dic, arch) ? XFS_XFLAG_HASATTR : 0;
+	if (di_flags & XFS_DIFLAG_ANY) {
+		if (di_flags & XFS_DIFLAG_REALTIME)
+			flags |= XFS_XFLAG_REALTIME;
+		if (di_flags & XFS_DIFLAG_PREALLOC)
+			flags |= XFS_XFLAG_PREALLOC;
+		if (di_flags & XFS_DIFLAG_IMMUTABLE)
+			flags |= XFS_XFLAG_IMMUTABLE;
+		if (di_flags & XFS_DIFLAG_APPEND)
+			flags |= XFS_XFLAG_APPEND;
+		if (di_flags & XFS_DIFLAG_SYNC)
+			flags |= XFS_XFLAG_SYNC;
+		if (di_flags & XFS_DIFLAG_NOATIME)
+			flags |= XFS_XFLAG_NOATIME;
+		if (di_flags & XFS_DIFLAG_NODUMP)
+			flags |= XFS_XFLAG_NODUMP;
+		if (di_flags & XFS_DIFLAG_RTINHERIT)
+			flags |= XFS_XFLAG_RTINHERIT;
+		if (di_flags & XFS_DIFLAG_PROJINHERIT)
+			flags |= XFS_XFLAG_PROJINHERIT;
+		if (di_flags & XFS_DIFLAG_NOSYMLINKS)
+			flags |= XFS_XFLAG_NOSYMLINKS;
+	}
 	return flags;
 }
 
@@ -1236,8 +1243,15 @@
 		break;
 	case S_IFREG:
 	case S_IFDIR:
-		if (pip->i_d.di_flags &
-		    (XFS_DIFLAG_NOATIME|XFS_DIFLAG_NODUMP|XFS_DIFLAG_SYNC)) {
+		if (unlikely(pip->i_d.di_flags & XFS_DIFLAG_ANY)) {
+			if (pip->i_d.di_flags & XFS_DIFLAG_RTINHERIT) {
+				if ((mode & S_IFMT) == S_IFDIR) {
+					ip->i_d.di_flags |= XFS_DIFLAG_RTINHERIT;
+				} else {
+					ip->i_d.di_flags |= XFS_DIFLAG_REALTIME;
+					ip->i_iocore.io_flags |= XFS_IOCORE_RT;
+				}
+			}
 			if ((pip->i_d.di_flags & XFS_DIFLAG_NOATIME) &&
 			    xfs_inherit_noatime)
 				ip->i_d.di_flags |= XFS_DIFLAG_NOATIME;
@@ -1247,7 +1261,11 @@
 			if ((pip->i_d.di_flags & XFS_DIFLAG_SYNC) &&
 			    xfs_inherit_sync)
 				ip->i_d.di_flags |= XFS_DIFLAG_SYNC;
+			if ((pip->i_d.di_flags & XFS_DIFLAG_NOSYMLINKS) &&
+			    xfs_inherit_nosymlinks)
+				ip->i_d.di_flags |= XFS_DIFLAG_NOSYMLINKS;
 		}
+		/* FALLTHROUGH */
 	case S_IFLNK:
 		ip->i_d.di_format = XFS_DINODE_FMT_EXTENTS;
 		ip->i_df.if_flags = XFS_IFEXTENTS;
@@ -3579,6 +3597,7 @@
 	return XFS_ERROR(EFSCORRUPTED);
 }
 
+
 /*
  * Flush all inactive inodes in mp.  Return true if no user references
  * were found, false otherwise.
@@ -3634,7 +3653,6 @@
 					continue;
 				}
 				if (!(flag & XFS_FLUSH_ALL)) {
-					ASSERT(0);
 					busy = 1;
 					done = 1;
 					break;
@@ -3851,6 +3869,6 @@
 		     (void *)ra,		/* caller of ilock */
 		     (void *)(unsigned long)current_cpu(),
 		     (void *)(unsigned long)current_pid(),
-		     0,0,0,0,0,0,0,0,0,0);
+		     NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL);
 }
 #endif
diff -Nru a/fs/xfs/xfs_inode.h b/fs/xfs/xfs_inode.h
--- a/fs/xfs/xfs_inode.h	2004-10-18 14:56:49 -07:00
+++ b/fs/xfs/xfs_inode.h	2004-10-18 14:56:49 -07:00
@@ -508,7 +508,6 @@
 uint		xfs_dic2xflags(struct xfs_dinode_core *, xfs_arch_t);
 int		xfs_ifree(struct xfs_trans *, xfs_inode_t *,
 			   struct xfs_bmap_free *);
-int		xfs_atruncate_start(xfs_inode_t *);
 void		xfs_itruncate_start(xfs_inode_t *, uint, xfs_fsize_t);
 int		xfs_itruncate_finish(struct xfs_trans **, xfs_inode_t *,
 				     xfs_fsize_t, int, int);
diff -Nru a/fs/xfs/xfs_iomap.c b/fs/xfs/xfs_iomap.c
--- a/fs/xfs/xfs_iomap.c	2004-10-18 14:56:32 -07:00
+++ b/fs/xfs/xfs_iomap.c	2004-10-18 14:56:32 -07:00
@@ -165,20 +165,24 @@
 		nisize = io->io_new_size;
 
 	for (pbm = 0; imaps && pbm < iomaps; imaps--, iomapp++, imap++, pbm++) {
-		iomapp->iomap_target = io->io_flags & XFS_IOCORE_RT ?
-			mp->m_rtdev_targp : mp->m_ddev_targp;
 		iomapp->iomap_offset = XFS_FSB_TO_B(mp, imap->br_startoff);
 		iomapp->iomap_delta = offset - iomapp->iomap_offset;
 		iomapp->iomap_bsize = XFS_FSB_TO_B(mp, imap->br_blockcount);
 		iomapp->iomap_flags = flags;
 
+		if (io->io_flags & XFS_IOCORE_RT) {
+			iomapp->iomap_flags |= IOMAP_REALTIME;
+			iomapp->iomap_target = mp->m_rtdev_targp;
+		} else {
+			iomapp->iomap_target = mp->m_ddev_targp;
+		}
 		start_block = imap->br_startblock;
 		if (start_block == HOLESTARTBLOCK) {
 			iomapp->iomap_bn = IOMAP_DADDR_NULL;
-			iomapp->iomap_flags = IOMAP_HOLE;
+			iomapp->iomap_flags |= IOMAP_HOLE;
 		} else if (start_block == DELAYSTARTBLOCK) {
 			iomapp->iomap_bn = IOMAP_DADDR_NULL;
-			iomapp->iomap_flags = IOMAP_DELAY;
+			iomapp->iomap_flags |= IOMAP_DELAY;
 		} else {
 			iomapp->iomap_bn = XFS_FSB_TO_DB_IO(io, start_block);
 			if (ISUNWRITTEN(imap))
@@ -512,6 +516,15 @@
 
 	*ret_imap = imap[0];
 	*nmaps = 1;
+	if ( !(io->io_flags & XFS_IOCORE_RT)  && !ret_imap->br_startblock) {
+                cmn_err(CE_PANIC,"Access to block zero:  fs <%s> inode: %lld "
+                        "start_block : %llx start_off : %llx blkcnt : %llx "
+                        "extent-state : %x \n",
+                        (ip->i_mount)->m_fsname,
+                        (long long)ip->i_ino,
+                        ret_imap->br_startblock, ret_imap->br_startoff,
+                        ret_imap->br_blockcount,ret_imap->br_state);
+        }
 	return 0;
 
  error0:	/* Cancel bmap, unlock inode, and cancel trans */
@@ -572,8 +585,10 @@
 	 * out to the file system's write iosize.  We clean up any extra
 	 * space left over when the file is closed in xfs_inactive().
 	 *
-	 * We don't bother with this for sync writes, because we need
-	 * to minimize the amount we write for good performance.
+	 * For sync writes, we are flushing delayed allocate space to
+	 * try to make additional space available for allocation near
+	 * the filesystem full boundary - preallocation hurts in that
+	 * situation, of course.
 	 */
 	if (!(ioflag & BMAPI_SYNC) && ((offset + count) > ip->i_d.di_size)) {
 		xfs_off_t	aligned_offset;
@@ -598,6 +613,20 @@
 				return error;
 			}
 			for (n = 0; n < nimaps; n++) {
+				if ( !(io->io_flags & XFS_IOCORE_RT)  && 
+					!imap[n].br_startblock) {
+					cmn_err(CE_PANIC,"Access to block "
+						"zero:  fs <%s> inode: %lld "
+						"start_block : %llx start_off "
+						": %llx blkcnt : %llx "
+						"extent-state : %x \n",
+						(ip->i_mount)->m_fsname,
+						(long long)ip->i_ino,
+						imap[n].br_startblock,
+						imap[n].br_startoff,
+						imap[n].br_blockcount,
+						imap[n].br_state);
+        			}
 				if ((imap[n].br_startblock != HOLESTARTBLOCK) &&
 				    (imap[n].br_startblock != DELAYSTARTBLOCK)) {
 					goto write_map;
@@ -621,7 +650,8 @@
 	 * request to a stripe width boundary if the file size is >=
 	 * stripe width and we are allocating past the allocation eof.
 	 */
-	if (mp->m_swidth && (mp->m_flags & XFS_MOUNT_SWALLOC)
+	if (!(io->io_flags & XFS_IOCORE_RT) && mp->m_swidth 
+	    && (mp->m_flags & XFS_MOUNT_SWALLOC)
 	    && (isize >= XFS_FSB_TO_B(mp, mp->m_swidth)) && aeof) {
 		int eof;
 		xfs_fileoff_t new_last_fsb;
@@ -639,8 +669,8 @@
 	 * if the file size is >= stripe unit size, and we are allocating past
 	 * the allocation eof.
 	 */
-	} else if (mp->m_dalign && (isize >= XFS_FSB_TO_B(mp, mp->m_dalign))
-		   && aeof) {
+	} else if (!(io->io_flags & XFS_IOCORE_RT) && mp->m_dalign &&
+		   (isize >= XFS_FSB_TO_B(mp, mp->m_dalign)) && aeof) {
 		int eof;
 		xfs_fileoff_t new_last_fsb;
 		new_last_fsb = roundup_64(last_fsb, mp->m_dalign);
@@ -651,8 +681,22 @@
 		if (eof) {
 			last_fsb = new_last_fsb;
 		}
-	}
+	/*
+	 * Round up the allocation request to a real-time extent boundary
+	 * if the file is on the real-time subvolume.
+	 */
+	} else if (io->io_flags & XFS_IOCORE_RT && aeof) {
+		int eof;
+		xfs_fileoff_t new_last_fsb;
 
+		new_last_fsb = roundup_64(last_fsb, mp->m_sb.sb_rextsize);
+		error = XFS_BMAP_EOF(mp, io, new_last_fsb, XFS_DATA_FORK, &eof);
+		if (error) {
+			return error;
+		}
+		if (eof)
+			last_fsb = new_last_fsb;
+	}
 	error = xfs_bmapi(NULL, ip, offset_fsb,
 			  (xfs_filblks_t)(last_fsb - offset_fsb),
 			  XFS_BMAPI_DELAY | XFS_BMAPI_WRITE |
@@ -680,6 +724,15 @@
 
 	*ret_imap = imap[0];
 	*nmaps = 1;
+	if ( !(io->io_flags & XFS_IOCORE_RT)  && !ret_imap->br_startblock) {
+		cmn_err(CE_PANIC,"Access to block zero:  fs <%s> inode: %lld "
+                        "start_block : %llx start_off : %llx blkcnt : %llx "
+                        "extent-state : %x \n",
+                        (ip->i_mount)->m_fsname,
+                        (long long)ip->i_ino,
+                        ret_imap->br_startblock, ret_imap->br_startoff,
+                        ret_imap->br_blockcount,ret_imap->br_state);
+	}
 	return 0;
 }
 
@@ -697,6 +750,7 @@
 	int		*retmap)
 {
 	xfs_mount_t	*mp = ip->i_mount;
+	xfs_iocore_t    *io = &ip->i_iocore;
 	xfs_fileoff_t	offset_fsb, last_block;
 	xfs_fileoff_t	end_fsb, map_start_fsb;
 	xfs_fsblock_t	first_block;
@@ -802,6 +856,18 @@
 		 */
 
 		for (i = 0; i < nimaps; i++) {
+			if ( !(io->io_flags & XFS_IOCORE_RT)  && 
+				!imap[i].br_startblock) {
+				cmn_err(CE_PANIC,"Access to block zero:  "
+					"fs <%s> inode: %lld "
+					"start_block : %llx start_off : %llx " 
+					"blkcnt : %llx extent-state : %x \n",
+					(ip->i_mount)->m_fsname,
+					(long long)ip->i_ino,
+					imap[i].br_startblock,
+					imap[i].br_startoff,
+				        imap[i].br_blockcount,imap[i].br_state);
+                        }
 			if ((map->br_startoff >= imap[i].br_startoff) &&
 			    (map->br_startoff < (imap[i].br_startoff +
 						 imap[i].br_blockcount))) {
@@ -837,6 +903,7 @@
 	size_t		count)
 {
 	xfs_mount_t	*mp = ip->i_mount;
+	xfs_iocore_t    *io = &ip->i_iocore;
 	xfs_trans_t	*tp;
 	xfs_fileoff_t	offset_fsb;
 	xfs_filblks_t	count_fsb;
@@ -853,7 +920,8 @@
 				&ip->i_iocore, offset, count);
 
 	offset_fsb = XFS_B_TO_FSBT(mp, offset);
-	count_fsb = XFS_B_TO_FSB(mp, count);
+	count_fsb = XFS_B_TO_FSB(mp, (xfs_ufsize_t)offset + count);
+	count_fsb = (xfs_filblks_t)(count_fsb - offset_fsb);
 
 	do {
 		nres = XFS_DIOSTRAT_SPACE_RES(mp, 0);
@@ -898,6 +966,16 @@
 		xfs_iunlock(ip, XFS_ILOCK_EXCL);
 		if (error)
 			goto error0;
+		
+		if ( !(io->io_flags & XFS_IOCORE_RT)  && !imap.br_startblock) {
+			cmn_err(CE_PANIC,"Access to block zero:  fs <%s> "
+				"inode: %lld start_block : %llx start_off : "
+				"%llx blkcnt : %llx extent-state : %x \n",
+				(ip->i_mount)->m_fsname,
+				(long long)ip->i_ino,
+				imap.br_startblock,imap.br_startoff,
+				imap.br_blockcount,imap.br_state);
+        	}
 
 		if ((numblks_fsb = imap.br_blockcount) == 0) {
 			/*
diff -Nru a/fs/xfs/xfs_iomap.h b/fs/xfs/xfs_iomap.h
--- a/fs/xfs/xfs_iomap.h	2004-10-18 14:56:29 -07:00
+++ b/fs/xfs/xfs_iomap.h	2004-10-18 14:56:29 -07:00
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003 Silicon Graphics, Inc.  All Rights Reserved.
+ * Copyright (c) 2003,2004 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
@@ -42,6 +42,7 @@
 	IOMAP_EOF =		0x01,	/* mapping contains EOF   */
 	IOMAP_HOLE =		0x02,	/* mapping covers a hole  */
 	IOMAP_DELAY =		0x04,	/* mapping covers delalloc region  */
+	IOMAP_REALTIME =	0x10,	/* mapping on the realtime device  */
 	IOMAP_UNWRITTEN =	0x20,	/* mapping covers allocated */
 					/* but uninitialized file data  */
 	IOMAP_NEW =		0x40	/* just allocate */
@@ -57,7 +58,7 @@
 	BMAPI_IGNSTATE = (1 << 4),	/* ignore unwritten state on read */
 	BMAPI_DIRECT = (1 << 5),		/* direct instead of buffered write */
 	BMAPI_MMAP = (1 << 6),		/* allocate for mmap write */
-	BMAPI_SYNC = (1 << 7),		/* sync write */
+	BMAPI_SYNC = (1 << 7),		/* sync write to flush delalloc space */
 	BMAPI_TRYLOCK = (1 << 8),	/* non-blocking request */
 	BMAPI_DEVICE = (1 << 9),	/* we only want to know the device */
 } bmapi_flags_t;
diff -Nru a/fs/xfs/xfs_itable.c b/fs/xfs/xfs_itable.c
--- a/fs/xfs/xfs_itable.c	2004-10-18 14:55:54 -07:00
+++ b/fs/xfs/xfs_itable.c	2004-10-18 14:55:54 -07:00
@@ -68,7 +68,7 @@
 xfs_bulkstat_one(
 	xfs_mount_t	*mp,		/* mount point for filesystem */
 	xfs_ino_t	ino,		/* inode number to get data for */
-	void		*buffer,	/* buffer to place output in */
+	void		__user *buffer,	/* buffer to place output in */
 	int		ubsize,		/* size of buffer */
 	void		*private_data,	/* my private data */
 	xfs_daddr_t	bno,		/* starting bno of inode cluster */
@@ -231,7 +231,7 @@
 	bulkstat_one_pf		formatter, /* func that'd fill a single buf */
 	void			*private_data,/* private data for formatter */
 	size_t			statstruct_size, /* sizeof struct filling */
-	xfs_caddr_t		ubuffer, /* buffer with inode stats */
+	char			__user *ubuffer, /* buffer with inode stats */
 	int			flags,	/* defined in xfs_itable.h */
 	int			*done)	/* 1 if there're more stats to get */
 {
@@ -265,7 +265,7 @@
 	int			tmp;	/* result value from btree calls */
 	int			ubcount; /* size of user's buffer */
 	int			ubleft;	/* bytes left in user's buffer */
-	xfs_caddr_t		ubufp;	/* current pointer into user's buffer */
+	char			__user *ubufp;	/* pointer into user's buffer */
 	int			ubelem;	/* spaces used in user's buffer */
 	int			ubused;	/* bytes used by formatter */
 	xfs_buf_t		*bp;	/* ptr to on-disk inode cluster buf */
@@ -633,7 +633,7 @@
 xfs_bulkstat_single(
 	xfs_mount_t		*mp,	/* mount point for filesystem */
 	xfs_ino_t		*lastinop, /* inode to return */
-	xfs_caddr_t		buffer,	/* buffer with inode stats */
+	char			__user *buffer, /* buffer with inode stats */
 	int			*done)	/* 1 if there're more stats to get */
 {
 	int			count;	/* count value for bulkstat call */
@@ -682,7 +682,7 @@
 	xfs_mount_t	*mp,		/* mount point for filesystem */
 	xfs_ino_t	*lastino,	/* last inode returned */
 	int		*count,		/* size of buffer/count returned */
-	xfs_caddr_t	ubuffer)	/* buffer with inode descriptions */
+	xfs_inogrp_t	__user *ubuffer)/* buffer with inode descriptions */
 {
 	xfs_buf_t	*agbp;
 	xfs_agino_t	agino;
@@ -766,7 +766,7 @@
 				error = XFS_ERROR(EFAULT);
 				break;
 			}
-			ubuffer += bufidx * sizeof(*buffer);
+			ubuffer += bufidx;
 			*count += bufidx;
 			bufidx = 0;
 		}
diff -Nru a/fs/xfs/xfs_itable.h b/fs/xfs/xfs_itable.h
--- a/fs/xfs/xfs_itable.h	2004-10-18 14:57:04 -07:00
+++ b/fs/xfs/xfs_itable.h	2004-10-18 14:57:04 -07:00
@@ -40,7 +40,7 @@
  */
 typedef int (*bulkstat_one_pf)(struct xfs_mount	*mp,
 			       xfs_ino_t	ino,
-			       void		*buffer,
+			       void		__user *buffer,
 			       int		ubsize,
 			       void		*private_data,
 			       xfs_daddr_t	bno,
@@ -73,7 +73,7 @@
 	bulkstat_one_pf formatter,	/* func that'd fill a single buf */
 	void		*private_data,	/* private data for formatter */
 	size_t		statstruct_size,/* sizeof struct that we're filling */
-	xfs_caddr_t	ubuffer,	/* buffer with inode stats */
+	char		__user *ubuffer,/* buffer with inode stats */
 	int		flags,		/* flag to control access method */
 	int		*done);		/* 1 if there're more stats to get */
 
@@ -81,14 +81,14 @@
 xfs_bulkstat_single(
 	xfs_mount_t		*mp,
 	xfs_ino_t		*lastinop,
-	xfs_caddr_t		buffer,
+	char			__user *buffer,
 	int			*done);
 
 int
 xfs_bulkstat_one(
 	xfs_mount_t		*mp,
 	xfs_ino_t		ino,
-	void			*buffer,
+	void			__user *buffer,
 	int			ubsize,
 	void			*private_data,
 	xfs_daddr_t		bno,
@@ -101,6 +101,6 @@
 	xfs_mount_t		*mp,	/* mount point for filesystem */
 	xfs_ino_t		*last,	/* last inode returned */
 	int			*count,	/* size of buffer/count returned */
-	xfs_caddr_t		buffer);/* buffer with inode descriptions */
+	xfs_inogrp_t		__user *buffer);/* buffer with inode info */
 
 #endif	/* __XFS_ITABLE_H__ */
diff -Nru a/fs/xfs/xfs_log.c b/fs/xfs/xfs_log.c
--- a/fs/xfs/xfs_log.c	2004-10-18 14:57:05 -07:00
+++ b/fs/xfs/xfs_log.c	2004-10-18 14:57:05 -07:00
@@ -122,7 +122,6 @@
 /* local debug functions */
 #if defined(DEBUG) && !defined(XLOG_NOLOG)
 STATIC void	xlog_verify_dest_ptr(xlog_t *log, __psint_t ptr);
-STATIC void	xlog_verify_disk_cycle_no(xlog_t *log, xlog_in_core_t *iclog);
 STATIC void	xlog_verify_grant_head(xlog_t *log, int equals);
 STATIC void	xlog_verify_iclog(xlog_t *log, xlog_in_core_t *iclog,
 				  int count, boolean_t syncing);
@@ -130,7 +129,6 @@
 				     xfs_lsn_t tail_lsn);
 #else
 #define xlog_verify_dest_ptr(a,b)
-#define xlog_verify_disk_cycle_no(a,b)
 #define xlog_verify_grant_head(a,b)
 #define xlog_verify_iclog(a,b,c,d)
 #define xlog_verify_tail_lsn(a,b,c)
@@ -356,13 +354,13 @@
 	if (!xlog_debug && xlog_target == log->l_targ)
 		return 0;
 #endif
-	cb->cb_next = 0;
+	cb->cb_next = NULL;
 	spl = LOG_LOCK(log);
 	abortflg = (iclog->ic_state & XLOG_STATE_IOERROR);
 	if (!abortflg) {
 		ASSERT_ALWAYS((iclog->ic_state == XLOG_STATE_ACTIVE) ||
 			      (iclog->ic_state == XLOG_STATE_WANT_SYNC));
-		cb->cb_next = 0;
+		cb->cb_next = NULL;
 		*(iclog->ic_callback_tail) = cb;
 		iclog->ic_callback_tail = &(cb->cb_next);
 	}
@@ -564,7 +562,7 @@
 	xlog_in_core_t	 *first_iclog;
 #endif
 	xfs_log_iovec_t  reg[1];
-	xfs_log_ticket_t tic = 0;
+	xfs_log_ticket_t tic = NULL;
 	xfs_lsn_t	 lsn;
 	int		 error;
 	SPLDECL(s);
@@ -813,7 +811,7 @@
 	xlog_t		*log = mp->m_log;
 	vfs_t		*vfsp = XFS_MTOVFS(mp);
 
-	if (vfsp->vfs_super->s_frozen || XFS_FORCED_SHUTDOWN(mp) ||
+	if (fs_frozen(vfsp) || XFS_FORCED_SHUTDOWN(mp) ||
 	    (vfsp->vfs_flag & VFS_RDONLY))
 		return 0;
 
@@ -1277,7 +1275,7 @@
 	int		error;
 	xfs_log_iovec_t	reg[1];
 
-	reg[0].i_addr = 0;
+	reg[0].i_addr = NULL;
 	reg[0].i_len = 0;
 
 	ASSERT_ALWAYS(iclog);
@@ -1413,9 +1411,13 @@
 	xlog_pack_data(log, iclog);       /* put cycle number in every block */
 
 	/* real byte length */
-	INT_SET(iclog->ic_header.h_len, 
-		ARCH_CONVERT,
-		iclog->ic_offset + iclog->ic_roundoff);
+	if (XFS_SB_VERSION_HASLOGV2(&log->l_mp->m_sb)) {
+		INT_SET(iclog->ic_header.h_len, 
+			ARCH_CONVERT,
+			iclog->ic_offset + iclog->ic_roundoff);
+	} else {
+		INT_SET(iclog->ic_header.h_len, ARCH_CONVERT, iclog->ic_offset);
+	}
 
 	/* put ops count in correct order */
 	ops = iclog->ic_header.h_num_logops;
@@ -1857,7 +1859,7 @@
 		if (iclog->ic_state == XLOG_STATE_DIRTY) {
 			iclog->ic_state	= XLOG_STATE_ACTIVE;
 			iclog->ic_offset       = 0;
-			iclog->ic_callback	= 0;   /* don't need to free */
+			iclog->ic_callback	= NULL;   /* don't need to free */
 			/*
 			 * If the number of ops in this iclog indicate it just
 			 * contains the dummy transaction, we can
@@ -2080,7 +2082,7 @@
 
 			while (cb != 0) {
 				iclog->ic_callback_tail = &(iclog->ic_callback);
-				iclog->ic_callback = 0;
+				iclog->ic_callback = NULL;
 				LOG_UNLOCK(log, s);
 
 				/* perform callbacks in the order given */
@@ -3098,7 +3100,7 @@
 		log->l_ticket_cnt++;
 		log->l_ticket_tcnt++;
 	}
-	t_list->t_next = 0;
+	t_list->t_next = NULL;
 	log->l_tail = t_list;
 	LOG_UNLOCK(log, s);
 }	/* xlog_state_ticket_alloc */
@@ -3126,7 +3128,7 @@
 	/* no need to clear fields */
 #else
 	/* When we debug, it is easier if tickets are cycled */
-	ticket->t_next     = 0;
+	ticket->t_next     = NULL;
 	if (log->l_tail != 0) {
 		log->l_tail->t_next = ticket;
 	} else {
@@ -3241,33 +3243,6 @@
 	if (! good_ptr)
 		xlog_panic("xlog_verify_dest_ptr: invalid ptr");
 }	/* xlog_verify_dest_ptr */
-
-
-#ifdef DEBUG
-/* check split LR write */
-STATIC void
-xlog_verify_disk_cycle_no(xlog_t	 *log,
-			  xlog_in_core_t *iclog)
-{
-    xfs_buf_t	*bp;
-    uint	cycle_no;
-    xfs_caddr_t ptr;
-    xfs_daddr_t	i;
-
-    if (BLOCK_LSN(iclog->ic_header.h_lsn, ARCH_CONVERT) < 10) {
-	cycle_no = CYCLE_LSN(iclog->ic_header.h_lsn, ARCH_CONVERT);
-	bp = xlog_get_bp(log, 1);
-	ASSERT(bp);
-	for (i = 0; i < BLOCK_LSN(iclog->ic_header.h_lsn, ARCH_CONVERT); i++) {
-	    xlog_bread(log, i, 1, bp);
-	    ptr = xlog_align(log, i, 1, bp);
-	    if (GET_CYCLE(ptr, ARCH_CONVERT) != cycle_no)
-		xlog_warn("XFS: xlog_verify_disk_cycle_no: bad cycle no");
-	}
-	xlog_put_bp(bp);
-    }
-}	/* xlog_verify_disk_cycle_no */
-#endif
 
 STATIC void
 xlog_verify_grant_head(xlog_t *log, int equals)
diff -Nru a/fs/xfs/xfs_log_priv.h b/fs/xfs/xfs_log_priv.h
--- a/fs/xfs/xfs_log_priv.h	2004-10-18 14:55:55 -07:00
+++ b/fs/xfs/xfs_log_priv.h	2004-10-18 14:55:55 -07:00
@@ -543,7 +543,6 @@
 				xfs_daddr_t *head_blk,
 				xfs_daddr_t *tail_blk,
 				int readonly);
-extern int	 xlog_print_find_oldest(xlog_t *log, xfs_daddr_t *last_blk);
 extern int	 xlog_recover(xlog_t *log, int readonly);
 extern int	 xlog_recover_finish(xlog_t *log, int mfsi_flags);
 extern void	 xlog_pack_data(xlog_t *log, xlog_in_core_t *iclog);
diff -Nru a/fs/xfs/xfs_log_recover.c b/fs/xfs/xfs_log_recover.c
--- a/fs/xfs/xfs_log_recover.c	2004-10-18 14:56:32 -07:00
+++ b/fs/xfs/xfs_log_recover.c	2004-10-18 14:56:32 -07:00
@@ -2047,12 +2047,11 @@
 		errs++;
 	}
 
-	if (! errs) {
+	if (! errs && !INT_ISZERO(ddq->d_id, ARCH_CONVERT)) {
 		if (INT_GET(ddq->d_blk_softlimit, ARCH_CONVERT) &&
 		    INT_GET(ddq->d_bcount, ARCH_CONVERT) >=
 				INT_GET(ddq->d_blk_softlimit, ARCH_CONVERT)) {
-			if (INT_ISZERO(ddq->d_btimer, ARCH_CONVERT) &&
-			    !INT_ISZERO(ddq->d_id, ARCH_CONVERT)) {
+			if (INT_ISZERO(ddq->d_btimer, ARCH_CONVERT)) {
 				if (flags & XFS_QMOPT_DOWARN)
 					cmn_err(CE_ALERT,
 					"%s : Dquot ID 0x%x (0x%p) "
@@ -2065,8 +2064,7 @@
 		if (INT_GET(ddq->d_ino_softlimit, ARCH_CONVERT) &&
 		    INT_GET(ddq->d_icount, ARCH_CONVERT) >=
 				INT_GET(ddq->d_ino_softlimit, ARCH_CONVERT)) {
-			if (INT_ISZERO(ddq->d_itimer, ARCH_CONVERT) &&
-			    !INT_ISZERO(ddq->d_id, ARCH_CONVERT)) {
+			if (INT_ISZERO(ddq->d_itimer, ARCH_CONVERT)) {
 				if (flags & XFS_QMOPT_DOWARN)
 					cmn_err(CE_ALERT,
 					"%s : Dquot ID 0x%x (0x%p) "
@@ -2076,6 +2074,19 @@
 				errs++;
 			}
 		}
+		if (INT_GET(ddq->d_rtb_softlimit, ARCH_CONVERT) &&
+		    INT_GET(ddq->d_rtbcount, ARCH_CONVERT) >=
+				INT_GET(ddq->d_rtb_softlimit, ARCH_CONVERT)) {
+			if (INT_ISZERO(ddq->d_rtbtimer, ARCH_CONVERT)) {
+				if (flags & XFS_QMOPT_DOWARN)
+					cmn_err(CE_ALERT,
+					"%s : Dquot ID 0x%x (0x%p) "
+					"RTBLK TIMER NOT STARTED",
+					str, (int)
+					INT_GET(ddq->d_id, ARCH_CONVERT), ddq);
+				errs++;
+			}
+		}
 	}
 
 	if (!errs || !(flags & XFS_QMOPT_DQREPAIR))
@@ -2319,7 +2330,7 @@
 		 * invalidate the buffer when we write it out below.
 		 */
 		imap.im_blkno = 0;
-		xfs_imap(log->l_mp, 0, ino, &imap, 0);
+		xfs_imap(log->l_mp, NULL, ino, &imap, 0);
 	}
 
 	/*
diff -Nru a/fs/xfs/xfs_mac.c b/fs/xfs/xfs_mac.c
--- a/fs/xfs/xfs_mac.c	2004-10-18 14:56:32 -07:00
+++ /dev/null	Wed Dec 31 16:00:00 196900
@@ -1,72 +0,0 @@
-/*
- * Copyright (c) 2000-2002 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/SGIGPLNoticeExplan/
- */
-
-#include "xfs.h"
-
-static xfs_mac_label_t *mac_low_high_lp;
-static xfs_mac_label_t *mac_high_low_lp;
-static xfs_mac_label_t *mac_admin_high_lp;
-static xfs_mac_label_t *mac_equal_equal_lp;
-
-/*
- * Test for the existence of a MAC label as efficiently as possible.
- */
-int
-xfs_mac_vhaslabel(
-	vnode_t		*vp)
-{
-	int		error;
-	int		len = sizeof(xfs_mac_label_t);
-	int		flags = ATTR_KERNOVAL|ATTR_ROOT;
-
-	VOP_ATTR_GET(vp, SGI_MAC_FILE, NULL, &len, flags, sys_cred, error);
-	return (error == 0);
-}
-
-int
-xfs_mac_iaccess(xfs_inode_t *ip, mode_t mode, struct cred *cr)
-{
-	xfs_mac_label_t mac;
-	xfs_mac_label_t *mp = mac_high_low_lp;
-
-	if (cr == NULL || sys_cred == NULL ) {
-		return EACCES;
-	}
-
-	if (xfs_attr_fetch(ip, SGI_MAC_FILE, (char *)&mac, sizeof(mac)) == 0) {
-		if ((mp = mac_add_label(&mac)) == NULL) {
-			return mac_access(mac_high_low_lp, cr, mode);
-		}
-	}
-
-	return mac_access(mp, cr, mode);
-}
diff -Nru a/fs/xfs/xfs_mount.c b/fs/xfs/xfs_mount.c
--- a/fs/xfs/xfs_mount.c	2004-10-18 14:56:28 -07:00
+++ b/fs/xfs/xfs_mount.c	2004-10-18 14:56:28 -07:00
@@ -278,17 +278,22 @@
 		return XFS_ERROR(EFSCORRUPTED);
 	}
 
-#if !XFS_BIG_BLKNOS
+	ASSERT(PAGE_SHIFT >= sbp->sb_blocklog);
+	ASSERT(sbp->sb_blocklog >= BBSHIFT);
+
+#if XFS_BIG_BLKNOS     /* Limited by ULONG_MAX of page cache index */
+	if (unlikely(
+	    (sbp->sb_dblocks >> (PAGE_SHIFT - sbp->sb_blocklog)) > ULONG_MAX ||
+	    (sbp->sb_rblocks >> (PAGE_SHIFT - sbp->sb_blocklog)) > ULONG_MAX)) {
+#else                  /* Limited by UINT_MAX of sectors */
 	if (unlikely(
-	    (sbp->sb_dblocks << (__uint64_t)(sbp->sb_blocklog - BBSHIFT))
-		> UINT_MAX ||
-	    (sbp->sb_rblocks << (__uint64_t)(sbp->sb_blocklog - BBSHIFT))
-		> UINT_MAX)) {
+	    (sbp->sb_dblocks << (sbp->sb_blocklog - BBSHIFT)) > UINT_MAX ||
+	    (sbp->sb_rblocks << (sbp->sb_blocklog - BBSHIFT)) > UINT_MAX)) {
+#endif
 		cmn_err(CE_WARN,
 	"XFS: File system is too large to be mounted on this system.");
 		return XFS_ERROR(E2BIG);
 	}
-#endif
 
 	if (unlikely(sbp->sb_inprogress)) {
 		cmn_err(CE_WARN, "XFS: file system busy");
@@ -313,10 +318,10 @@
 	return 0;
 }
 
-void
-xfs_initialize_perag(xfs_mount_t *mp, int agcount)
+xfs_agnumber_t
+xfs_initialize_perag(xfs_mount_t *mp, xfs_agnumber_t agcount)
 {
-	int		index, max_metadata;
+	xfs_agnumber_t	index, max_metadata;
 	xfs_perag_t	*pag;
 	xfs_agino_t	agino;
 	xfs_ino_t	ino;
@@ -372,7 +377,7 @@
 			pag->pagi_inodeok = 1;
 		}
 	}
-	mp->m_maxagi = index;
+	return index;
 }
 
 /*
@@ -633,9 +638,8 @@
 	xfs_buf_t	*bp;
 	xfs_sb_t	*sbp = &(mp->m_sb);
 	xfs_inode_t	*rip;
-	vnode_t		*rvp = 0;
+	vnode_t		*rvp = NULL;
 	int		readio_log, writeio_log;
-	vmap_t		vmap;
 	xfs_daddr_t	d;
 	__uint64_t	ret64;
 	__int64_t	update_flags;
@@ -947,7 +951,7 @@
 	mp->m_perag =
 		kmem_zalloc(sbp->sb_agcount * sizeof(xfs_perag_t), KM_SLEEP);
 
-	xfs_initialize_perag(mp, sbp->sb_agcount);
+	mp->m_maxagi = xfs_initialize_perag(mp, sbp->sb_agcount);
 
 	/*
 	 * log's mount-time initialization. Perform 1st part recovery if needed
@@ -979,7 +983,6 @@
 
 	ASSERT(rip != NULL);
 	rvp = XFS_ITOV(rip);
-	VMAP(rvp, vmap);
 
 	if (unlikely((rip->i_d.di_mode & S_IFMT) != S_IFDIR)) {
 		cmn_err(CE_WARN, "XFS: corrupted root inode");
@@ -1043,7 +1046,6 @@
 	 * Free up the root inode.
 	 */
 	VN_RELE(rvp);
-	vn_purge(rvp, &vmap);
  error3:
 	xfs_log_unmount_dealloc(mp);
  error2:
diff -Nru a/fs/xfs/xfs_mount.h b/fs/xfs/xfs_mount.h
--- a/fs/xfs/xfs_mount.h	2004-10-18 14:55:53 -07:00
+++ b/fs/xfs/xfs_mount.h	2004-10-18 14:55:53 -07:00
@@ -551,7 +551,7 @@
 extern void	xfs_freesb(xfs_mount_t *);
 extern void	xfs_do_force_shutdown(bhv_desc_t *, int, char *, int);
 extern int	xfs_syncsub(xfs_mount_t *, int, int, int *);
-extern void	xfs_initialize_perag(xfs_mount_t *, int);
+extern xfs_agnumber_t	xfs_initialize_perag(xfs_mount_t *, xfs_agnumber_t);
 extern void	xfs_xlatesb(void *, struct xfs_sb *, int, xfs_arch_t,
 			__int64_t);
 
diff -Nru a/fs/xfs/xfs_quota.h b/fs/xfs/xfs_quota.h
--- a/fs/xfs/xfs_quota.h	2004-10-18 14:57:04 -07:00
+++ b/fs/xfs/xfs_quota.h	2004-10-18 14:57:04 -07:00
@@ -309,23 +309,27 @@
 } xfs_dqtrxops_t;
 
 #define XFS_DQTRXOP(mp, tp, op, args...) \
-			((mp)->m_qm_ops.xfs_dqtrxops ? \
-			((mp)->m_qm_ops.xfs_dqtrxops->op)(tp, ## args) : 0)
+		((mp)->m_qm_ops.xfs_dqtrxops ? \
+		((mp)->m_qm_ops.xfs_dqtrxops->op)(tp, ## args) : 0)
+
+#define XFS_DQTRXOP_VOID(mp, tp, op, args...) \
+		((mp)->m_qm_ops.xfs_dqtrxops ? \
+		((mp)->m_qm_ops.xfs_dqtrxops->op)(tp, ## args) : (void)0)
 
 #define XFS_TRANS_DUP_DQINFO(mp, otp, ntp) \
-	XFS_DQTRXOP(mp, otp, qo_dup_dqinfo, ntp)
+	XFS_DQTRXOP_VOID(mp, otp, qo_dup_dqinfo, ntp)
 #define XFS_TRANS_FREE_DQINFO(mp, tp) \
-	XFS_DQTRXOP(mp, tp, qo_free_dqinfo)
+	XFS_DQTRXOP_VOID(mp, tp, qo_free_dqinfo)
 #define XFS_TRANS_MOD_DQUOT_BYINO(mp, tp, ip, field, delta) \
-	XFS_DQTRXOP(mp, tp, qo_mod_dquot_byino, ip, field, delta)
+	XFS_DQTRXOP_VOID(mp, tp, qo_mod_dquot_byino, ip, field, delta)
 #define XFS_TRANS_APPLY_DQUOT_DELTAS(mp, tp) \
-	XFS_DQTRXOP(mp, tp, qo_apply_dquot_deltas)
+	XFS_DQTRXOP_VOID(mp, tp, qo_apply_dquot_deltas)
 #define XFS_TRANS_RESERVE_QUOTA_NBLKS(mp, tp, ip, nblks, ninos, fl) \
 	XFS_DQTRXOP(mp, tp, qo_reserve_quota_nblks, mp, ip, nblks, ninos, fl)
 #define XFS_TRANS_RESERVE_QUOTA_BYDQUOTS(mp, tp, ud, gd, nb, ni, fl) \
 	XFS_DQTRXOP(mp, tp, qo_reserve_quota_bydquots, mp, ud, gd, nb, ni, fl)
 #define XFS_TRANS_UNRESERVE_AND_MOD_DQUOTS(mp, tp) \
-	XFS_DQTRXOP(mp, tp, qo_unreserve_and_mod_dquots)
+	XFS_DQTRXOP_VOID(mp, tp, qo_unreserve_and_mod_dquots)
 
 #define XFS_TRANS_RESERVE_BLKQUOTA(mp, tp, ip, nblks) \
 	XFS_TRANS_RESERVE_QUOTA_NBLKS(mp, tp, ip, nblks, 0, \
diff -Nru a/fs/xfs/xfs_rtalloc.c b/fs/xfs/xfs_rtalloc.c
--- a/fs/xfs/xfs_rtalloc.c	2004-10-18 14:56:13 -07:00
+++ b/fs/xfs/xfs_rtalloc.c	2004-10-18 14:56:13 -07:00
@@ -1966,7 +1966,8 @@
 	/*
 	 * Calculate new parameters.  These are the final values to be reached.
 	 */
-	nrextents = do_div(nrblocks, in->extsize);
+	nrextents = nrblocks;
+	do_div(nrextents, in->extsize);
 	nrbmblocks = roundup_64(nrextents, NBBY * sbp->sb_blocksize);
 	nrextslog = xfs_highbit32(nrextents);
 	nrsumlevels = nrextslog + 1;
@@ -2021,7 +2022,8 @@
 			XFS_RTMIN(nrblocks,
 				  nsbp->sb_rbmblocks * NBBY *
 				  nsbp->sb_blocksize * nsbp->sb_rextsize);
-		nsbp->sb_rextents = do_div(nsbp->sb_rblocks, nsbp->sb_rextsize);
+		nsbp->sb_rextents = nsbp->sb_rblocks;
+		do_div(nsbp->sb_rextents, nsbp->sb_rextsize);
 		nsbp->sb_rextslog = xfs_highbit32(nsbp->sb_rextents);
 		nrsumlevels = nmp->m_rsumlevels = nsbp->sb_rextslog + 1;
 		nrsumsize =
@@ -2353,13 +2355,7 @@
 	ASSERT(sbp->sb_rsumino != NULLFSINO);
 	error = xfs_iget(mp, NULL, sbp->sb_rsumino, 0, &mp->m_rsumip, 0);
 	if (error) {
-		vnode_t		*rbmvp;		/* vnode for bitmap file */
-		vmap_t		vmap;		/* vmap to delete vnode */
-
-		rbmvp = XFS_ITOV(mp->m_rbmip);
-		VMAP(rbmvp, vmap);
-		VN_RELE(rbmvp);
-		vn_purge(rbmvp, &vmap);
+		VN_RELE(XFS_ITOV(mp->m_rbmip));
 		return error;
 	}
 	ASSERT(mp->m_rsumip != NULL);
diff -Nru a/fs/xfs/xfs_sb.h b/fs/xfs/xfs_sb.h
--- a/fs/xfs/xfs_sb.h	2004-10-18 14:56:29 -07:00
+++ b/fs/xfs/xfs_sb.h	2004-10-18 14:56:29 -07:00
@@ -250,9 +250,9 @@
 	((((sbp)->sb_versionnum >= XFS_SB_VERSION_1) && \
 	  ((sbp)->sb_versionnum <= XFS_SB_VERSION_3)) || \
 	   ((XFS_SB_VERSION_NUM(sbp) == XFS_SB_VERSION_4) && \
-	    !(((sbp)->sb_versionnum & ~XFS_SB_VERSION_OKREALBITS) && \
-	      ((sbp)->sb_versionnum & XFS_SB_VERSION_MOREBITSBIT) && \
-	      ((sbp)->sb_features2 & ~XFS_SB_VERSION2_OKREALBITS))
+	    !(((sbp)->sb_versionnum & ~XFS_SB_VERSION_OKREALBITS) || \
+	      (((sbp)->sb_versionnum & XFS_SB_VERSION_MOREBITSBIT) && \
+	       ((sbp)->sb_features2 & ~XFS_SB_VERSION2_OKREALBITS)))
 
 #ifdef __KERNEL__
 #define	XFS_SB_GOOD_VERSION(sbp)	\
diff -Nru a/fs/xfs/xfs_trans.c b/fs/xfs/xfs_trans.c
--- a/fs/xfs/xfs_trans.c	2004-10-18 14:56:29 -07:00
+++ b/fs/xfs/xfs_trans.c	2004-10-18 14:56:29 -07:00
@@ -131,7 +131,7 @@
 	xfs_mount_t	*mp,
 	uint		type)
 {
-	vfs_check_frozen(XFS_MTOVFS(mp)->vfs_super, SB_FREEZE_TRANS);
+	fs_check_frozen(XFS_MTOVFS(mp), SB_FREEZE_TRANS);
 	atomic_inc(&mp->m_active_trans);
 
 	return (_xfs_trans_alloc(mp, type));
@@ -490,6 +490,9 @@
 
 	if (tp->t_frextents_delta != 0) {
 		INT_MOD(sbp->sb_frextents, ARCH_CONVERT, tp->t_frextents_delta);
+	}
+	if (tp->t_res_frextents_delta != 0) {
+		INT_MOD(sbp->sb_frextents, ARCH_CONVERT, tp->t_res_frextents_delta);
 	}
 	if (tp->t_dblocks_delta != 0) {
 		INT_MOD(sbp->sb_dblocks, ARCH_CONVERT, tp->t_dblocks_delta);
diff -Nru a/fs/xfs/xfs_trans_item.c b/fs/xfs/xfs_trans_item.c
--- a/fs/xfs/xfs_trans_item.c	2004-10-18 14:55:55 -07:00
+++ b/fs/xfs/xfs_trans_item.c	2004-10-18 14:55:55 -07:00
@@ -290,7 +290,7 @@
 	}
 	ASSERT(0);
 	/* NOTREACHED */
-	return 0; /* keep gcc quite */
+	return NULL; /* keep gcc quite */
 }
 
 /*
diff -Nru a/fs/xfs/xfs_types.h b/fs/xfs/xfs_types.h
--- a/fs/xfs/xfs_types.h	2004-10-18 14:57:19 -07:00
+++ b/fs/xfs/xfs_types.h	2004-10-18 14:57:19 -07:00
@@ -58,7 +58,7 @@
 typedef __int64_t		prid_t;		/* project ID */
 typedef __uint32_t		inst_t;		/* an instruction */
 
-typedef __u64			xfs_off_t;
+typedef __s64			xfs_off_t;	/* <file offset> type */
 typedef __u64			xfs_ino_t;	/* <inode> type */
 typedef __s64			xfs_daddr_t;	/* <disk address> type */
 typedef char *			xfs_caddr_t;	/* <core address> type */
diff -Nru a/fs/xfs/xfs_vfsops.c b/fs/xfs/xfs_vfsops.c
--- a/fs/xfs/xfs_vfsops.c	2004-10-18 14:56:17 -07:00
+++ b/fs/xfs/xfs_vfsops.c	2004-10-18 14:56:17 -07:00
@@ -431,6 +431,16 @@
 	logdev = rtdev = NULL;
 
 	/*
+	 * Setup xfs_mount function vectors from available behaviors
+	 */
+	p = vfs_bhv_lookup(vfsp, VFS_POSITION_DM);
+	mp->m_dm_ops = p ? *(xfs_dmops_t *) vfs_bhv_custom(p) : xfs_dmcore_stub;
+	p = vfs_bhv_lookup(vfsp, VFS_POSITION_QM);
+	mp->m_qm_ops = p ? *(xfs_qmops_t *) vfs_bhv_custom(p) : xfs_qmcore_stub;
+	p = vfs_bhv_lookup(vfsp, VFS_POSITION_IO);
+	mp->m_io_ops = p ? *(xfs_ioops_t *) vfs_bhv_custom(p) : xfs_iocore_xfs;
+
+	/*
 	 * Open real time and log devices - order is important.
 	 */
 	if (args->logname[0]) {
@@ -455,68 +465,73 @@
 	}
 
 	/*
-	 * Setup xfs_mount function vectors from available behaviors
-	 */
-	p = vfs_bhv_lookup(vfsp, VFS_POSITION_DM);
-	mp->m_dm_ops = p ? *(xfs_dmops_t *) vfs_bhv_custom(p) : xfs_dmcore_stub;
-	p = vfs_bhv_lookup(vfsp, VFS_POSITION_QM);
-	mp->m_qm_ops = p ? *(xfs_qmops_t *) vfs_bhv_custom(p) : xfs_qmcore_stub;
-	p = vfs_bhv_lookup(vfsp, VFS_POSITION_IO);
-	mp->m_io_ops = p ? *(xfs_ioops_t *) vfs_bhv_custom(p) : xfs_iocore_xfs;
-
-	/*
 	 * Setup xfs_mount buffer target pointers
 	 */
+	error = ENOMEM;
 	mp->m_ddev_targp = xfs_alloc_buftarg(ddev);
-	if (rtdev)
+	if (!mp->m_ddev_targp) {
+		xfs_blkdev_put(logdev);
+		xfs_blkdev_put(rtdev);
+		return error;
+	}
+	if (rtdev) {
 		mp->m_rtdev_targp = xfs_alloc_buftarg(rtdev);
+		if (!mp->m_rtdev_targp)
+			goto error0;
+	}
 	mp->m_logdev_targp = (logdev && logdev != ddev) ?
 				xfs_alloc_buftarg(logdev) : mp->m_ddev_targp;
+	if (!mp->m_logdev_targp)
+		goto error0;
 
 	/*
 	 * Setup flags based on mount(2) options and then the superblock
 	 */
 	error = xfs_start_flags(vfsp, args, mp);
 	if (error)
-		goto error;
+		goto error1;
 	error = xfs_readsb(mp);
 	if (error)
-		goto error;
+		goto error1;
 	error = xfs_finish_flags(vfsp, args, mp);
-	if (error) {
-		xfs_freesb(mp);
-		goto error;
-	}
+	if (error)
+		goto error2;
 
 	/*
 	 * Setup xfs_mount buffer target pointers based on superblock
 	 */
-	xfs_setsize_buftarg(mp->m_ddev_targp, mp->m_sb.sb_blocksize,
-			    mp->m_sb.sb_sectsize);
-	if (logdev && logdev != ddev) {
+	error = xfs_setsize_buftarg(mp->m_ddev_targp, mp->m_sb.sb_blocksize,
+				    mp->m_sb.sb_sectsize);
+	if (!error && logdev && logdev != ddev) {
 		unsigned int	log_sector_size = BBSIZE;
 
 		if (XFS_SB_VERSION_HASSECTOR(&mp->m_sb))
 			log_sector_size = mp->m_sb.sb_logsectsize;
-		xfs_setsize_buftarg(mp->m_logdev_targp, mp->m_sb.sb_blocksize,
-				    log_sector_size);
-	}
-	if (rtdev)
-		xfs_setsize_buftarg(mp->m_rtdev_targp, mp->m_sb.sb_blocksize,
-				    mp->m_sb.sb_blocksize);
+		error = xfs_setsize_buftarg(mp->m_logdev_targp,
+					    mp->m_sb.sb_blocksize,
+					    log_sector_size);
+	}
+	if (!error && rtdev)
+		error = xfs_setsize_buftarg(mp->m_rtdev_targp,
+					    mp->m_sb.sb_blocksize,
+					    mp->m_sb.sb_sectsize);
+	if (error)
+		goto error2;
 
-	if (!(error = XFS_IOINIT(vfsp, args, flags)))
+	error = XFS_IOINIT(vfsp, args, flags);
+	if (!error)
 		return 0;
-
- error:
+error2:
+	if (mp->m_sb_bp)
+		xfs_freesb(mp);
+error1:
 	xfs_binval(mp->m_ddev_targp);
-	if (logdev != NULL && logdev != ddev) {
+	if (logdev && logdev != ddev)
 		xfs_binval(mp->m_logdev_targp);
-	}
-	if (rtdev != NULL) {
+	if (rtdev)
 		xfs_binval(mp->m_rtdev_targp);
-	}
-	xfs_unmountfs_close(mp, NULL);
+error0:
+	xfs_unmountfs_close(mp, credp);
 	return error;
 }
 
@@ -1040,6 +1055,11 @@
 			continue;
 		}
 
+		if (VN_BAD(vp)) {
+			ip = ip->i_mnext;
+			continue;
+		}
+
 		if (XFS_FORCED_SHUTDOWN(mp) && !(flags & SYNC_CLOSE)) {
 			XFS_MOUNT_IUNLOCK(mp);
 			kmem_free(ipointer, sizeof(xfs_iptr_t));
@@ -1567,31 +1587,35 @@
 	vnode_t		**vpp,
 	fid_t		*fidp)
 {
-	xfs_fid_t	*xfid;
+	xfs_mount_t	*mp = XFS_BHVTOM(bdp);
+	xfs_fid_t	*xfid = (struct xfs_fid *)fidp;
 	xfs_inode_t	*ip;
 	int		error;
 	xfs_ino_t	ino;
 	unsigned int	igen;
-	xfs_mount_t	*mp;
 
-	xfid  = (struct xfs_fid *)fidp;
-	if (xfid->xfs_fid_len == sizeof(*xfid) - sizeof(xfid->xfs_fid_len)) {
-		ino  = xfid->xfs_fid_ino;
-		igen = xfid->xfs_fid_gen;
-	} else {
-		/*
-		 * Invalid.  Since handles can be created in user space
-		 * and passed in via gethandle(), this is not cause for
-		 * a panic.
-		 */
+	/*
+	 * Invalid.  Since handles can be created in user space and passed in
+	 * via gethandle(), this is not cause for a panic.
+	 */
+	if (xfid->xfs_fid_len != sizeof(*xfid) - sizeof(xfid->xfs_fid_len))
 		return XFS_ERROR(EINVAL);
-	}
-	mp = XFS_BHVTOM(bdp);
+
+	ino  = xfid->xfs_fid_ino;
+	igen = xfid->xfs_fid_gen;
+
+	/*
+	 * NFS can sometimes send requests for ino 0.  Fail them gracefully.
+	 */
+	if (ino == 0)
+		return XFS_ERROR(ESTALE);
+
 	error = xfs_iget(mp, NULL, ino, XFS_ILOCK_SHARED, &ip, 0);
 	if (error) {
 		*vpp = NULL;
 		return error;
 	}
+
 	if (ip == NULL) {
 		*vpp = NULL;
 		return XFS_ERROR(EIO);
diff -Nru a/fs/xfs/xfs_vnodeops.c b/fs/xfs/xfs_vnodeops.c
--- a/fs/xfs/xfs_vnodeops.c	2004-10-18 14:57:05 -07:00
+++ b/fs/xfs/xfs_vnodeops.c	2004-10-18 14:57:05 -07:00
@@ -283,7 +283,7 @@
 /*
  * xfs_setattr
  */
-STATIC int
+int
 xfs_setattr(
 	bhv_desc_t		*bdp,
 	vattr_t			*vap,
@@ -305,6 +305,7 @@
 	int			mandlock_before, mandlock_after;
 	struct xfs_dquot	*udqp, *gdqp, *olddquot1, *olddquot2;
 	int			file_owner;
+	int			need_iolock = (flags & ATTR_DMI) == 0;
 
 	vp = BHV_TO_VNODE(bdp);
 	vn_trace_entry(vp, __FUNCTION__, (inst_t *)__return_address);
@@ -406,7 +407,8 @@
 				goto error_return;
 			}
 		}
-		lock_flags |= XFS_IOLOCK_EXCL;
+		if (need_iolock)
+			lock_flags |= XFS_IOLOCK_EXCL;
 	}
 
 	xfs_ilock(ip, lock_flags);
@@ -678,7 +680,8 @@
 					     XFS_TRANS_PERM_LOG_RES,
 					     XFS_ITRUNCATE_LOG_COUNT))) {
 			xfs_trans_cancel(tp, 0);
-			xfs_iunlock(ip, XFS_IOLOCK_EXCL);
+			if (need_iolock)
+				xfs_iunlock(ip, XFS_IOLOCK_EXCL);
 			return code;
 		}
 		commit_flags = XFS_TRANS_RELEASE_LOG_RES;
@@ -823,22 +826,34 @@
 				mp->m_sb.sb_blocklog;
 		}
 		if (mask & XFS_AT_XFLAGS) {
-			ip->i_d.di_flags = 0;
-			if (vap->va_xflags & XFS_XFLAG_REALTIME) {
-				ip->i_d.di_flags |= XFS_DIFLAG_REALTIME;
-				ip->i_iocore.io_flags |= XFS_IOCORE_RT;
-			}
+			uint	di_flags;
+
+			/* can't set PREALLOC this way, just preserve it */
+			di_flags = (ip->i_d.di_flags & XFS_DIFLAG_PREALLOC);
 			if (vap->va_xflags & XFS_XFLAG_IMMUTABLE)
-				ip->i_d.di_flags |= XFS_DIFLAG_IMMUTABLE;
+				di_flags |= XFS_DIFLAG_IMMUTABLE;
 			if (vap->va_xflags & XFS_XFLAG_APPEND)
-				ip->i_d.di_flags |= XFS_DIFLAG_APPEND;
+				di_flags |= XFS_DIFLAG_APPEND;
 			if (vap->va_xflags & XFS_XFLAG_SYNC)
-				ip->i_d.di_flags |= XFS_DIFLAG_SYNC;
+				di_flags |= XFS_DIFLAG_SYNC;
 			if (vap->va_xflags & XFS_XFLAG_NOATIME)
-				ip->i_d.di_flags |= XFS_DIFLAG_NOATIME;
+				di_flags |= XFS_DIFLAG_NOATIME;
 			if (vap->va_xflags & XFS_XFLAG_NODUMP)
-				ip->i_d.di_flags |= XFS_DIFLAG_NODUMP;
-			/* can't set PREALLOC this way, just ignore it */
+				di_flags |= XFS_DIFLAG_NODUMP;
+			if ((ip->i_d.di_mode & S_IFMT) == S_IFDIR) {
+				if (vap->va_xflags & XFS_XFLAG_RTINHERIT)
+					di_flags |= XFS_DIFLAG_RTINHERIT;
+				if (vap->va_xflags & XFS_XFLAG_NOSYMLINKS)
+					di_flags |= XFS_DIFLAG_NOSYMLINKS;
+			} else {
+				if (vap->va_xflags & XFS_XFLAG_REALTIME) {
+					di_flags |= XFS_DIFLAG_REALTIME;
+					ip->i_iocore.io_flags |= XFS_IOCORE_RT;
+				} else {
+					ip->i_iocore.io_flags &= ~XFS_IOCORE_RT;
+				}
+			}
+			ip->i_d.di_flags = di_flags;
 		}
 		xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE);
 		timeflags |= XFS_ICHGTIME_CHG;
@@ -1596,7 +1611,7 @@
 	 * If the inode is already free, then there can be nothing
 	 * to clean up here.
 	 */
-	if (ip->i_d.di_mode == 0) {
+	if (ip->i_d.di_mode == 0 || VN_BAD(vp)) {
 		ASSERT(ip->i_df.if_real_bytes == 0);
 		ASSERT(ip->i_df.if_broot_bytes == 0);
 		return VN_INACTIVE_CACHE;
@@ -1822,8 +1837,6 @@
 }
 
 
-#define	XFS_CREATE_NEW_MAXTRIES	10000
-
 /*
  * xfs_create (create a new file).
  */
@@ -3382,6 +3395,14 @@
 	xfs_ilock(dp, XFS_ILOCK_EXCL);
 
 	/*
+	 * Check whether the directory allows new symlinks or not.
+	 */
+	if (dp->i_d.di_flags & XFS_DIFLAG_NOSYMLINKS) {
+		error = XFS_ERROR(EPERM);
+		goto error_return;
+	}
+
+	/*
 	 * Reserve disk quota : blocks and inode.
 	 */
 	error = XFS_TRANS_RESERVE_QUOTA(mp, tp, udqp, gdqp, resblks, 1, 0);
@@ -3787,11 +3808,17 @@
 	vnode_t		*vp;
 
 	vp = BHV_TO_VNODE(bdp);
+	ip = XFS_BHVTOI(bdp);
 
 	vn_trace_entry(vp, __FUNCTION__, (inst_t *)__return_address);
 
 	ASSERT(!VN_MAPPED(vp));
-	ip = XFS_BHVTOI(bdp);
+
+	/* bad inode, get out here ASAP */
+	if (VN_BAD(vp)) {
+		xfs_ireclaim(ip);
+		return 0;
+	}
 
 	if ((ip->i_d.di_mode & S_IFMT) == S_IFREG) {
 		if (ip->i_d.di_size > 0) {
@@ -3869,8 +3896,12 @@
 	int		sync_mode)
 {
 	xfs_ihash_t	*ih = ip->i_hash;
+	vnode_t		*vp = XFS_ITOV_NULL(ip);
 	int		error;
 
+	if (vp && VN_BAD(vp))
+		return 0;
+
 	/* The hash lock here protects a thread in xfs_iget_core from
 	 * racing with us on linking the inode back with a vnode.
 	 * Once we have the XFS_IRECLAIM flag set it will not touch
@@ -3878,8 +3909,7 @@
 	 */
 	write_lock(&ih->ih_lock);
 	if ((ip->i_flags & XFS_IRECLAIM) ||
-	    (!(ip->i_flags & XFS_IRECLAIMABLE) &&
-	      (XFS_ITOV_NULL(ip) == NULL))) {
+	    (!(ip->i_flags & XFS_IRECLAIMABLE) && vp == NULL)) {
 		write_unlock(&ih->ih_lock);
 		if (locked) {
 			xfs_ifunlock(ip);
@@ -3946,15 +3976,13 @@
 xfs_finish_reclaim_all(xfs_mount_t *mp, int noblock)
 {
 	int		purged;
-	struct list_head	*curr, *next;
-	xfs_inode_t	*ip;
+	xfs_inode_t	*ip, *n;
 	int		done = 0;
 
 	while (!done) {
 		purged = 0;
 		XFS_MOUNT_ILOCK(mp);
-		list_for_each_safe(curr, next, &mp->m_del_inodes) {
-			ip = list_entry(curr, xfs_inode_t, i_reclaim);
+		list_for_each_entry_safe(ip, n, &mp->m_del_inodes, i_reclaim) {
 			if (noblock) {
 				if (xfs_ilock_nowait(ip, XFS_ILOCK_EXCL) == 0)
 					continue;
@@ -4292,6 +4320,7 @@
 	int			rt;
 	xfs_fileoff_t		startoffset_fsb;
 	xfs_trans_t		*tp;
+	int			need_iolock = (attr_flags & ATTR_DMI) == 0;
 
 	vn_trace_entry(XFS_ITOV(ip), __FUNCTION__, (inst_t *)__return_address);
 	mp = ip->i_mount;
@@ -4319,7 +4348,8 @@
 			return(error);
 	}
 
-	xfs_ilock(ip, XFS_IOLOCK_EXCL);
+	if (need_iolock)
+		xfs_ilock(ip, XFS_IOLOCK_EXCL);
 	rounding = MAX((__uint8_t)(1 << mp->m_sb.sb_blocklog),
 			(__uint8_t)NBPP);
 	ilen = len + (offset & (rounding - 1));
@@ -4338,7 +4368,7 @@
 		error = xfs_bmapi(NULL, ip, startoffset_fsb, 1, 0, NULL, 0,
 			&imap, &nimap, NULL);
 		if (error)
-			return error;
+			goto out_unlock_iolock;
 		ASSERT(nimap == 0 || nimap == 1);
 		if (nimap && imap.br_startblock != HOLESTARTBLOCK) {
 			xfs_daddr_t	block;
@@ -4353,7 +4383,7 @@
 		error = xfs_bmapi(NULL, ip, endoffset_fsb - 1, 1, 0, NULL, 0,
 			&imap, &nimap, NULL);
 		if (error)
-			return error;
+			goto out_unlock_iolock;
 		ASSERT(nimap == 0 || nimap == 1);
 		if (nimap && imap.br_startblock != HOLESTARTBLOCK) {
 			ASSERT(imap.br_startblock != DELAYSTARTBLOCK);
@@ -4442,14 +4472,17 @@
 		xfs_iunlock(ip, XFS_ILOCK_EXCL);
 	}
 
-	xfs_iunlock(ip, XFS_IOLOCK_EXCL);
+ out_unlock_iolock:
+	if (need_iolock)
+		xfs_iunlock(ip, XFS_IOLOCK_EXCL);
 	return error;
 
  error0:
 	xfs_bmap_cancel(&free_list);
  error1:
 	xfs_trans_cancel(tp, XFS_TRANS_RELEASE_LOG_RES | XFS_TRANS_ABORT);
-	xfs_iunlock(ip, XFS_ILOCK_EXCL | XFS_IOLOCK_EXCL);
+	xfs_iunlock(ip, need_iolock ? (XFS_ILOCK_EXCL | XFS_IOLOCK_EXCL) :
+		    XFS_ILOCK_EXCL);
 	return error;
 }
 
@@ -4606,20 +4639,21 @@
 	xfs_trans_ijoin(tp, ip, XFS_ILOCK_EXCL);
 	xfs_trans_ihold(tp, ip);
 
-	ip->i_d.di_mode &= ~S_ISUID;
-
-	/*
-	 * Note that we don't have to worry about mandatory
-	 * file locking being disabled here because we only
-	 * clear the S_ISGID bit if the Group execute bit is
-	 * on, but if it was on then mandatory locking wouldn't
-	 * have been enabled.
-	 */
-	if (ip->i_d.di_mode & S_IXGRP)
-		ip->i_d.di_mode &= ~S_ISGID;
+	if ((attr_flags & ATTR_DMI) == 0) {
+		ip->i_d.di_mode &= ~S_ISUID;
 
-	xfs_ichgtime(ip, XFS_ICHGTIME_MOD | XFS_ICHGTIME_CHG);
+		/*
+		 * Note that we don't have to worry about mandatory
+		 * file locking being disabled here because we only
+		 * clear the S_ISGID bit if the Group execute bit is
+		 * on, but if it was on then mandatory locking wouldn't
+		 * have been enabled.
+		 */
+		if (ip->i_d.di_mode & S_IXGRP)
+			ip->i_d.di_mode &= ~S_ISGID;
 
+		xfs_ichgtime(ip, XFS_ICHGTIME_MOD | XFS_ICHGTIME_CHG);
+	}
 	if (setprealloc)
 		ip->i_d.di_flags |= XFS_DIFLAG_PREALLOC;
 	else if (clrprealloc)
diff -Nru a/include/acpi/acconfig.h b/include/acpi/acconfig.h
--- a/include/acpi/acconfig.h	2004-10-18 14:56:49 -07:00
+++ b/include/acpi/acconfig.h	2004-10-18 14:56:49 -07:00
@@ -64,11 +64,21 @@
 
 /* Version string */
 
-#define ACPI_CA_VERSION                 0x20040326
+#define ACPI_CA_VERSION                 0x20040816
+
+/*
+ * OS name, used for the _OS object.  The _OS object is essentially obsolete,
+ * but there is a large base of ASL/AML code in existing machines that check
+ * for the string below.  The use of this string usually guarantees that
+ * the ASL will execute down the most tested code path.  Also, there is some
+ * code that will not execute the _OSI method unless _OS matches the string
+ * below.  Therefore, change this string at your own risk.
+ */
+#define ACPI_OS_NAME                    "Microsoft Windows NT"
 
 /* Maximum objects in the various object caches */
 
-#define ACPI_MAX_STATE_CACHE_DEPTH      64          /* State objects for stacks */
+#define ACPI_MAX_STATE_CACHE_DEPTH      64          /* State objects */
 #define ACPI_MAX_PARSE_CACHE_DEPTH      96          /* Parse tree objects */
 #define ACPI_MAX_EXTPARSE_CACHE_DEPTH   64          /* Parse tree objects */
 #define ACPI_MAX_OBJECT_CACHE_DEPTH     64          /* Interpreter operand objects */
@@ -152,10 +162,11 @@
 
 /* Constants used in searching for the RSDP in low memory */
 
-#define ACPI_LO_RSDP_WINDOW_BASE        0           /* Physical Address */
-#define ACPI_HI_RSDP_WINDOW_BASE        0xE0000     /* Physical Address */
-#define ACPI_LO_RSDP_WINDOW_SIZE        0x400
-#define ACPI_HI_RSDP_WINDOW_SIZE        0x20000
+#define ACPI_EBDA_PTR_LOCATION          0x0000040E     /* Physical Address */
+#define ACPI_EBDA_PTR_LENGTH            2
+#define ACPI_EBDA_WINDOW_SIZE           1024
+#define ACPI_HI_RSDP_WINDOW_BASE        0x000E0000     /* Physical Address */
+#define ACPI_HI_RSDP_WINDOW_SIZE        0x00020000
 #define ACPI_RSDP_SCAN_STEP             16
 
 /* Operation regions */
@@ -187,7 +198,7 @@
 
 /* Number of strings associated with the _OSI reserved method */
 
-#define ACPI_NUM_OSI_STRINGS            4
+#define ACPI_NUM_OSI_STRINGS            9
 
 
 /******************************************************************************
diff -Nru a/include/acpi/acdebug.h b/include/acpi/acdebug.h
--- a/include/acpi/acdebug.h	2004-10-18 14:56:13 -07:00
+++ b/include/acpi/acdebug.h	2004-10-18 14:56:13 -07:00
@@ -106,6 +106,10 @@
  * dbcmds - debug commands and output routines
  */
 
+acpi_status
+acpi_db_disassemble_method (
+	char                            *name);
+
 void
 acpi_db_display_table_info (
 	char                            *table_arg);
@@ -163,6 +167,10 @@
 void
 acpi_db_set_scope (
 	char                            *name);
+
+acpi_status
+acpi_db_sleep (
+	char                            *object_arg);
 
 void
 acpi_db_find_references (
diff -Nru a/include/acpi/acdisasm.h b/include/acpi/acdisasm.h
--- a/include/acpi/acdisasm.h	2004-10-18 14:56:32 -07:00
+++ b/include/acpi/acdisasm.h	2004-10-18 14:56:32 -07:00
@@ -52,6 +52,13 @@
 #define BLOCK_BRACE             2
 #define BLOCK_COMMA_LIST        4
 
+struct acpi_external_list
+{
+	char                                *path;
+	struct acpi_external_list           *next;
+};
+
+extern struct acpi_external_list        *acpi_gbl_external_list;
 extern const char                       *acpi_gbl_io_decode[2];
 extern const char                       *acpi_gbl_word_decode[4];
 extern const char                       *acpi_gbl_consume_decode[2];
@@ -398,5 +405,13 @@
 	u32                             length,
 	u32                             level);
 
+
+/*
+ * dmutils
+ */
+
+void
+acpi_dm_add_to_external_list (
+	char                            *path);
 
 #endif  /* __ACDISASM_H__ */
diff -Nru a/include/acpi/acdispat.h b/include/acpi/acdispat.h
--- a/include/acpi/acdispat.h	2004-10-18 14:56:49 -07:00
+++ b/include/acpi/acdispat.h	2004-10-18 14:56:49 -07:00
@@ -437,8 +437,7 @@
 	struct acpi_namespace_node      *method_node,
 	u8                              *aml_start,
 	u32                             aml_length,
-	union acpi_operand_object       **params,
-	union acpi_operand_object       **return_obj_desc,
+	struct acpi_parameter_info      *info,
 	u32                             pass_number);
 
 acpi_status
diff -Nru a/include/acpi/acevents.h b/include/acpi/acevents.h
--- a/include/acpi/acevents.h	2004-10-18 14:56:33 -07:00
+++ b/include/acpi/acevents.h	2004-10-18 14:56:33 -07:00
@@ -46,11 +46,11 @@
 
 
 acpi_status
-acpi_ev_initialize (
+acpi_ev_initialize_events (
 	void);
 
 acpi_status
-acpi_ev_handler_initialize (
+acpi_ev_install_xrupt_handlers (
 	void);
 
 
@@ -111,12 +111,27 @@
 
 acpi_status
 acpi_ev_walk_gpe_list (
-	ACPI_GPE_CALLBACK       gpe_walk_callback);
+	ACPI_GPE_CALLBACK       gpe_walk_callback,
+	u32                             flags);
 
 u8
 acpi_ev_valid_gpe_event (
 	struct acpi_gpe_event_info      *gpe_event_info);
 
+acpi_status
+acpi_ev_update_gpe_enable_masks (
+	struct acpi_gpe_event_info      *gpe_event_info,
+	u8                              type);
+
+acpi_status
+acpi_ev_enable_gpe (
+	struct acpi_gpe_event_info      *gpe_event_info,
+	u8                              write_to_hardware);
+
+acpi_status
+acpi_ev_disable_gpe (
+	struct acpi_gpe_event_info      *gpe_event_info);
+
 struct acpi_gpe_event_info *
 acpi_ev_get_gpe_event_info (
 	acpi_handle                     gpe_device,
@@ -139,6 +154,11 @@
 acpi_ev_delete_gpe_block (
 	struct acpi_gpe_block_info      *gpe_block);
 
+acpi_status
+acpi_ev_delete_gpe_handlers (
+	struct acpi_gpe_xrupt_info      *gpe_xrupt_info,
+	struct acpi_gpe_block_info      *gpe_block);
+
 u32
 acpi_ev_gpe_dispatch (
 	struct acpi_gpe_event_info      *gpe_event_info,
@@ -148,12 +168,25 @@
 acpi_ev_gpe_detect (
 	struct acpi_gpe_xrupt_info      *gpe_xrupt_list);
 
+acpi_status
+acpi_ev_set_gpe_type (
+	struct acpi_gpe_event_info      *gpe_event_info,
+	u8                              type);
+
+acpi_status
+acpi_ev_check_for_wake_only_gpe (
+	struct acpi_gpe_event_info      *gpe_event_info);
+
 /*
  * Evregion - Address Space handling
  */
 
 acpi_status
-acpi_ev_init_address_spaces (
+acpi_ev_install_region_handlers (
+	void);
+
+acpi_status
+acpi_ev_initialize_op_regions (
 	void);
 
 acpi_status
@@ -181,6 +214,19 @@
 acpi_ev_detach_region (
 	union acpi_operand_object      *region_obj,
 	u8                              acpi_ns_is_locked);
+
+acpi_status
+acpi_ev_install_space_handler (
+	struct acpi_namespace_node      *node,
+	acpi_adr_space_type             space_id,
+	acpi_adr_space_handler          handler,
+	acpi_adr_space_setup            setup,
+	void                            *context);
+
+acpi_status
+acpi_ev_execute_reg_methods (
+	struct acpi_namespace_node      *node,
+	acpi_adr_space_type             space_id);
 
 acpi_status
 acpi_ev_execute_reg_method (
diff -Nru a/include/acpi/acexcep.h b/include/acpi/acexcep.h
--- a/include/acpi/acexcep.h	2004-10-18 14:55:54 -07:00
+++ b/include/acpi/acexcep.h	2004-10-18 14:55:54 -07:00
@@ -95,8 +95,9 @@
 #define AE_LOGICAL_ADDRESS              (acpi_status) (0x001B | AE_CODE_ENVIRONMENTAL)
 #define AE_ABORT_METHOD                 (acpi_status) (0x001C | AE_CODE_ENVIRONMENTAL)
 #define AE_SAME_HANDLER                 (acpi_status) (0x001D | AE_CODE_ENVIRONMENTAL)
+#define AE_WAKE_ONLY_GPE                (acpi_status) (0x001E | AE_CODE_ENVIRONMENTAL)
 
-#define AE_CODE_ENV_MAX                 0x001D
+#define AE_CODE_ENV_MAX                 0x001E
 
 /*
  * Programmer exceptions
@@ -165,7 +166,7 @@
 #define AE_AML_CIRCULAR_REFERENCE       (acpi_status) (0x0020 | AE_CODE_AML)
 #define AE_AML_BAD_RESOURCE_LENGTH      (acpi_status) (0x0021 | AE_CODE_AML)
 
-#define AE_CODE_AML_MAX                 0x0020
+#define AE_CODE_AML_MAX                 0x0021
 
 /*
  * Internal exceptions used for control
@@ -222,7 +223,8 @@
 	"AE_NO_GLOBAL_LOCK",
 	"AE_LOGICAL_ADDRESS",
 	"AE_ABORT_METHOD",
-	"AE_SAME_HANDLER"
+	"AE_SAME_HANDLER",
+	"AE_WAKE_ONLY_GPE"
 };
 
 char const   *acpi_gbl_exception_names_pgm[] =
diff -Nru a/include/acpi/acglobal.h b/include/acpi/acglobal.h
--- a/include/acpi/acglobal.h	2004-10-18 14:55:46 -07:00
+++ b/include/acpi/acglobal.h	2004-10-18 14:55:46 -07:00
@@ -46,15 +46,17 @@
 
 
 /*
- * Ensure that the globals are actually defined only once.
+ * Ensure that the globals are actually defined and initialized only once.
  *
- * The use of these defines allows a single list of globals (here) in order
+ * The use of these macros allows a single list of globals (here) in order
  * to simplify maintenance of the code.
  */
 #ifdef DEFINE_ACPI_GLOBALS
 #define ACPI_EXTERN
+#define ACPI_INIT_GLOBAL(a,b) a=b
 #else
 #define ACPI_EXTERN extern
+#define ACPI_INIT_GLOBAL(a,b) a
 #endif
 
 /*
@@ -64,6 +66,7 @@
 ACPI_EXTERN struct acpi_generic_address         acpi_gbl_xpm1a_enable;
 ACPI_EXTERN struct acpi_generic_address         acpi_gbl_xpm1b_enable;
 
+
 /*****************************************************************************
  *
  * Debug support
@@ -79,15 +82,42 @@
 
 extern      u32                                 acpi_gbl_nesting_level;
 
+
 /*****************************************************************************
  *
- * Runtime configuration
+ * Runtime configuration (static defaults that can be overriden at runtime)
  *
  ****************************************************************************/
 
-ACPI_EXTERN u8                                  acpi_gbl_create_osi_method;
-ACPI_EXTERN u8                                  acpi_gbl_all_methods_serialized;
-ACPI_EXTERN u8                                  acpi_gbl_leave_wake_gpes_disabled;
+/*
+ * Enable "slack" in the AML interpreter?  Default is FALSE, and the
+ * interpreter strictly follows the ACPI specification.  Setting to TRUE
+ * allows the interpreter to forgive certain bad AML constructs.
+ */
+ACPI_EXTERN u8       ACPI_INIT_GLOBAL (acpi_gbl_enable_interpreter_slack, FALSE);
+
+/*
+ * Automatically serialize ALL control methods? Default is FALSE, meaning
+ * to use the Serialized/not_serialized method flags on a per method basis.
+ * Only change this if the ASL code is poorly written and cannot handle
+ * reentrancy even though methods are marked "not_serialized".
+ */
+ACPI_EXTERN u8       ACPI_INIT_GLOBAL (acpi_gbl_all_methods_serialized, FALSE);
+
+/*
+ * Create the predefined _OSI method in the namespace? Default is TRUE
+ * because ACPI CA is fully compatible with other ACPI implementations.
+ * Changing this will revert ACPI CA (and machine ASL) to pre-OSI behavior.
+ */
+ACPI_EXTERN u8       ACPI_INIT_GLOBAL (acpi_gbl_create_osi_method, TRUE);
+
+/*
+ * Disable wakeup GPEs during runtime? Default is TRUE because WAKE and
+ * RUNTIME GPEs should never be shared, and WAKE GPEs should typically only
+ * be enabled just before going to sleep.
+ */
+ACPI_EXTERN u8       ACPI_INIT_GLOBAL (acpi_gbl_leave_wake_gpes_disabled, TRUE);
+
 
 /*****************************************************************************
  *
@@ -102,7 +132,6 @@
  *
  * These tables are single-table only; meaning that there can be at most one
  * of each in the system.  Each global points to the actual table.
- *
  */
 ACPI_EXTERN u32                                 acpi_gbl_table_flags;
 ACPI_EXTERN u32                                 acpi_gbl_rsdt_table_count;
@@ -170,6 +199,7 @@
 ACPI_EXTERN u8                                  acpi_gbl_acpi_hardware_present;
 ACPI_EXTERN u8                                  acpi_gbl_global_lock_present;
 ACPI_EXTERN u8                                  acpi_gbl_events_initialized;
+ACPI_EXTERN u8                                  acpi_gbl_system_awake_and_running;
 
 extern u8                                       acpi_gbl_shutdown;
 extern u32                                      acpi_gbl_startup_flags;
diff -Nru a/include/acpi/achware.h b/include/acpi/achware.h
--- a/include/acpi/achware.h	2004-10-18 14:56:33 -07:00
+++ b/include/acpi/achware.h	2004-10-18 14:56:33 -07:00
@@ -114,15 +114,7 @@
 /* GPE support */
 
 acpi_status
-acpi_hw_enable_gpe (
-	struct acpi_gpe_event_info      *gpe_event_info);
-
-void
-acpi_hw_enable_gpe_for_wakeup (
-	struct acpi_gpe_event_info      *gpe_event_info);
-
-acpi_status
-acpi_hw_disable_gpe (
+acpi_hw_write_gpe_enable_reg (
 	struct acpi_gpe_event_info      *gpe_event_info);
 
 acpi_status
@@ -130,10 +122,6 @@
 	struct acpi_gpe_xrupt_info      *gpe_xrupt_info,
 	struct acpi_gpe_block_info      *gpe_block);
 
-void
-acpi_hw_disable_gpe_for_wakeup (
-	struct acpi_gpe_event_info      *gpe_event_info);
-
 acpi_status
 acpi_hw_clear_gpe (
 	struct acpi_gpe_event_info      *gpe_event_info);
@@ -149,12 +137,26 @@
 	acpi_event_status               *event_status);
 
 acpi_status
-acpi_hw_prepare_gpes_for_sleep (
-	void);
+acpi_hw_disable_all_gpes (
+	u32                             flags);
+
+acpi_status
+acpi_hw_enable_all_runtime_gpes (
+	u32                             flags);
 
 acpi_status
-acpi_hw_restore_gpes_on_wake (
-	void);
+acpi_hw_enable_all_wakeup_gpes (
+	u32                             flags);
+
+acpi_status
+acpi_hw_enable_runtime_gpe_block (
+	struct acpi_gpe_xrupt_info      *gpe_xrupt_info,
+	struct acpi_gpe_block_info      *gpe_block);
+
+acpi_status
+acpi_hw_enable_wakeup_gpe_block (
+	struct acpi_gpe_xrupt_info      *gpe_xrupt_info,
+	struct acpi_gpe_block_info      *gpe_block);
 
 
 /* ACPI Timer prototypes */
diff -Nru a/include/acpi/acinterp.h b/include/acpi/acinterp.h
--- a/include/acpi/acinterp.h	2004-10-18 14:57:03 -07:00
+++ b/include/acpi/acinterp.h	2004-10-18 14:57:03 -07:00
@@ -118,6 +118,12 @@
  */
 
 acpi_status
+acpi_ex_common_buffer_setup (
+	union acpi_operand_object       *obj_desc,
+	u32                             buffer_length,
+	u32                             *datum_count);
+
+acpi_status
 acpi_ex_extract_from_field (
 	union acpi_operand_object       *obj_desc,
 	void                            *buffer,
@@ -240,8 +246,8 @@
 u8
 acpi_ex_do_logical_op (
 	u16                             opcode,
-	acpi_integer                    operand0,
-	acpi_integer                    operand1);
+	union acpi_operand_object       *obj_desc,
+	union acpi_operand_object       *obj_desc2);
 
 acpi_integer
 acpi_ex_do_math_op (
@@ -563,8 +569,11 @@
 acpi_ex_store_object_to_node (
 	union acpi_operand_object       *source_desc,
 	struct acpi_namespace_node      *node,
-	struct acpi_walk_state          *walk_state);
+	struct acpi_walk_state          *walk_state,
+	u8                              implicit_conversion);
 
+#define ACPI_IMPLICIT_CONVERSION        TRUE
+#define ACPI_NO_IMPLICIT_CONVERSION     FALSE
 
 /*
  * exstoren
diff -Nru a/include/acpi/aclocal.h b/include/acpi/aclocal.h
--- a/include/acpi/aclocal.h	2004-10-18 14:56:33 -07:00
+++ b/include/acpi/aclocal.h	2004-10-18 14:56:33 -07:00
@@ -189,8 +189,6 @@
 	u8                                  type;           /* Type associated with this name */
 	u16                                 owner_id;
 	union acpi_name_union               name;           /* ACPI Name, always 4 chars per ACPI spec */
-
-
 	union acpi_operand_object           *object;        /* Pointer to attached ACPI object (optional) */
 	struct acpi_namespace_node          *child;         /* First child */
 	struct acpi_namespace_node          *peer;          /* Next peer*/
@@ -211,10 +209,8 @@
 #define ANOBJ_METHOD_LOCAL              0x10
 #define ANOBJ_METHOD_NO_RETVAL          0x20
 #define ANOBJ_METHOD_SOME_NO_RETVAL     0x40
-
 #define ANOBJ_IS_BIT_OFFSET             0x80
 
-
 /*
  * ACPI Table Descriptor.  One per ACPI table
  */
@@ -309,16 +305,31 @@
  *
  ****************************************************************************/
 
-/* Information about a GPE, one per each GPE in an array */
+/* Dispatch info for each GPE -- either a method or handler, cannot be both */
 
-struct acpi_gpe_event_info
+struct acpi_handler_info
 {
-	struct acpi_namespace_node              *method_node;   /* Method node for this GPE level */
-	acpi_gpe_handler                        handler;        /* Address of handler, if any */
+	acpi_event_handler                      address;        /* Address of handler, if any */
 	void                                    *context;       /* Context to be passed to handler */
+	struct acpi_namespace_node              *method_node;   /* Method node for this GPE level (saved) */
+};
+
+union acpi_gpe_dispatch_info
+{
+	struct acpi_namespace_node              *method_node;   /* Method node for this GPE level */
+	struct acpi_handler_info                *handler;
+};
+
+/*
+ * Information about a GPE, one per each GPE in an array.
+ * NOTE: Important to keep this struct as small as possible.
+ */
+struct acpi_gpe_event_info
+{
+	union acpi_gpe_dispatch_info    dispatch;       /* Either Method or Handler */
 	struct acpi_gpe_register_info           *register_info; /* Backpointer to register info */
-	u8                                      flags;          /* Level or Edge */
-	u8                                      bit_mask;       /* This GPE within the register */
+	u8                                      flags;          /* Misc info about this GPE */
+	u8                                      register_bit;   /* This GPE bit within the register */
 };
 
 /* Information about a GPE register pair, one per each status/enable pair in an array */
@@ -327,9 +338,8 @@
 {
 	struct acpi_generic_address             status_address; /* Address of status reg */
 	struct acpi_generic_address             enable_address; /* Address of enable reg */
-	u8                                      status;         /* Current value of status reg */
-	u8                                      enable;         /* Current value of enable reg */
-	u8                                      wake_enable;    /* Mask of bits to keep enabled when sleeping */
+	u8                                      enable_for_wake; /* GPEs to keep enabled when sleeping */
+	u8                                      enable_for_run; /* GPEs to keep enabled when running */
 	u8                                      base_gpe_number; /* Base GPE number for this register */
 };
 
@@ -339,6 +349,7 @@
  */
 struct acpi_gpe_block_info
 {
+	struct acpi_namespace_node              *node;
 	struct acpi_gpe_block_info              *previous;
 	struct acpi_gpe_block_info              *next;
 	struct acpi_gpe_xrupt_info              *xrupt_block;   /* Backpointer to interrupt block */
@@ -502,7 +513,7 @@
 	struct acpi_walk_state              *walk_state_list;       /* Head of list of walk_states for this thread */
 	union acpi_operand_object           *acquired_mutex_list;   /* List of all currently acquired mutexes */
 	u32                                 thread_id;              /* Running thread ID */
-	u16                                 current_sync_level;     /* Mutex Sync (nested acquire) level */
+	u8                                  current_sync_level;     /* Mutex Sync (nested acquire) level */
 };
 
 
diff -Nru a/include/acpi/acmacros.h b/include/acpi/acmacros.h
--- a/include/acpi/acmacros.h	2004-10-18 14:56:32 -07:00
+++ b/include/acpi/acmacros.h	2004-10-18 14:56:32 -07:00
@@ -53,6 +53,9 @@
 #define ACPI_LOBYTE(l)                  ((u8)(u16)(l))
 #define ACPI_HIBYTE(l)                  ((u8)((((u16)(l)) >> 8) & 0xFF))
 
+#define ACPI_SET_BIT(target,bit)        ((target) |= (bit))
+#define ACPI_CLEAR_BIT(target,bit)      ((target) &= ~(bit))
+
 
 #if ACPI_MACHINE_WIDTH == 16
 
@@ -97,7 +100,7 @@
  * printf() format helpers
  */
 
-/* Split 64-bit integer into two 32-bit values. use with %8,8_x%8.8X */
+/* Split 64-bit integer into two 32-bit values. Use with %8.8X%8.8X */
 
 #define ACPI_FORMAT_UINT64(i)           ACPI_HIDWORD(i),ACPI_LODWORD(i)
 
@@ -360,24 +363,6 @@
 #define ACPI_MASK_BITS_BELOW(position)       ((ACPI_INTEGER_MAX) << ((u32) (position)))
 
 #define ACPI_IS_OCTAL_DIGIT(d)               (((char)(d) >= '0') && ((char)(d) <= '7'))
-
-/* Macros for GAS addressing */
-
-#if ACPI_MACHINE_WIDTH != 16
-
-#define ACPI_PCI_DEVICE(a)              (u16) ((ACPI_HIDWORD ((a))) & 0x0000FFFF)
-#define ACPI_PCI_FUNCTION(a)            (u16) ((ACPI_LODWORD ((a))) >> 16)
-#define ACPI_PCI_REGISTER(a)            (u16) ((ACPI_LODWORD ((a))) & 0x0000FFFF)
-
-#else
-
-/* No support for GAS and PCI IDs in 16-bit mode  */
-
-#define ACPI_PCI_FUNCTION(a)            (u16) ((a) & 0xFFFF0000)
-#define ACPI_PCI_DEVICE(a)              (u16) ((a) & 0x0000FFFF)
-#define ACPI_PCI_REGISTER(a)            (u16) ((a) & 0x0000FFFF)
-
-#endif
 
 
 /* Bitfields within ACPI registers */
diff -Nru a/include/acpi/acnamesp.h b/include/acpi/acnamesp.h
--- a/include/acpi/acnamesp.h	2004-10-18 14:55:55 -07:00
+++ b/include/acpi/acnamesp.h	2004-10-18 14:55:55 -07:00
@@ -278,33 +278,25 @@
 
 acpi_status
 acpi_ns_evaluate_by_handle (
-	struct acpi_namespace_node      *prefix_node,
-	union acpi_operand_object       **params,
-	union acpi_operand_object       **return_object);
+	struct acpi_parameter_info      *info);
 
 acpi_status
 acpi_ns_evaluate_by_name (
 	char                            *pathname,
-	union acpi_operand_object       **params,
-	union acpi_operand_object       **return_object);
+	struct acpi_parameter_info      *info);
 
 acpi_status
 acpi_ns_evaluate_relative (
-	struct acpi_namespace_node      *prefix_node,
 	char                            *pathname,
-	union acpi_operand_object       **params,
-	union acpi_operand_object       **return_object);
+	struct acpi_parameter_info      *info);
 
 acpi_status
 acpi_ns_execute_control_method (
-	struct acpi_namespace_node      *method_node,
-	union acpi_operand_object       **params,
-	union acpi_operand_object       **return_obj_desc);
+	struct acpi_parameter_info      *info);
 
 acpi_status
 acpi_ns_get_object_value (
-	struct acpi_namespace_node      *object_node,
-	union acpi_operand_object       **return_obj_desc);
+	struct acpi_parameter_info      *info);
 
 
 /*
diff -Nru a/include/acpi/acobject.h b/include/acpi/acobject.h
--- a/include/acpi/acobject.h	2004-10-18 14:55:55 -07:00
+++ b/include/acpi/acobject.h	2004-10-18 14:55:55 -07:00
@@ -204,13 +204,14 @@
 struct acpi_object_mutex
 {
 	ACPI_OBJECT_COMMON_HEADER
-	u16                                     sync_level;
-	u16                                     acquisition_depth;
-	struct acpi_thread_state                *owner_thread;
-	void                                    *semaphore;
+	u8                                      sync_level;         /* 0-15, specified in Mutex() call */
+	u16                                     acquisition_depth;  /* Allow multiple Acquires, same thread */
+	struct acpi_thread_state                *owner_thread;      /* Current owner of the mutex */
+	void                                    *semaphore;         /* Actual OS synchronization object */
 	union acpi_operand_object               *prev;              /* Link for list of acquired mutexes */
 	union acpi_operand_object               *next;              /* Link for list of acquired mutexes */
-	struct acpi_namespace_node              *node;              /* containing object */
+	struct acpi_namespace_node              *node;              /* Containing namespace node */
+	u8                                      original_sync_level; /* Owner's original sync level (0-15) */
 };
 
 
@@ -220,7 +221,7 @@
 
 	u8                                      space_id;
 	union acpi_operand_object               *handler;           /* Handler for region access */
-	struct acpi_namespace_node              *node;              /* containing object */
+	struct acpi_namespace_node              *node;              /* Containing namespace node */
 	union acpi_operand_object               *next;
 	u32                                     length;
 	acpi_physical_address                   address;
diff -Nru a/include/acpi/acparser.h b/include/acpi/acparser.h
--- a/include/acpi/acparser.h	2004-10-18 14:56:33 -07:00
+++ b/include/acpi/acparser.h	2004-10-18 14:56:33 -07:00
@@ -73,9 +73,7 @@
 
 acpi_status
 acpi_psx_execute (
-	struct acpi_namespace_node      *method_node,
-	union acpi_operand_object       **params,
-	union acpi_operand_object       **return_obj_desc);
+	struct acpi_parameter_info      *info);
 
 
 /******************************************************************************
diff -Nru a/include/acpi/acpi_bus.h b/include/acpi/acpi_bus.h
--- a/include/acpi/acpi_bus.h	2004-10-18 14:57:19 -07:00
+++ b/include/acpi/acpi_bus.h	2004-10-18 14:57:19 -07:00
@@ -157,7 +157,8 @@
 	u32			suprise_removal_ok:1;
 	u32			power_manageable:1;
 	u32			performance_manageable:1;
-	u32			reserved:21;
+	u32			wake_capable:1; /* Wakeup(_PRW) supported? */
+	u32			reserved:20;
 };
 
 
@@ -203,10 +204,8 @@
 	u32			explicit_get:1;		     /* _PSC present? */
 	u32			power_resources:1;	   /* Power resources */
 	u32			inrush_current:1;	  /* Serialize Dx->D0 */
-	u32			wake_capable:1;		 /* Wakeup supported? */
-	u32			wake_enabled:1;		/* Enabled for wakeup */
 	u32			power_removed:1;	   /* Optimize Dx->D0 */
-	u32			reserved:26;
+	u32			reserved:28;
 };
 
 struct acpi_device_power_state {
@@ -250,6 +249,25 @@
 	struct acpi_device_perf_state *states;
 };
 
+/* Wakeup Management */
+struct acpi_device_wakeup_flags {
+	u8	valid:1; /* Can successfully enable wakeup? */
+	u8	run_wake:1; /* Run-Wake GPE devices */
+};
+
+struct acpi_device_wakeup_state {
+	u8	enabled:1;
+	u8	active:1;
+};
+
+struct acpi_device_wakeup {
+	acpi_handle		gpe_device;
+	acpi_integer		gpe_number;;
+	acpi_integer		sleep_state;
+	struct acpi_handle_list	resources;
+	struct acpi_device_wakeup_state	state;
+	struct acpi_device_wakeup_flags	flags;
+};
 
 /* Device */
 
@@ -258,11 +276,13 @@
 	struct acpi_device	*parent;
 	struct list_head	children;
 	struct list_head	node;
+	struct list_head	wakeup_list;
 	struct list_head	g_list;
 	struct acpi_device_status status;
 	struct acpi_device_flags flags;
 	struct acpi_device_pnp	pnp;
 	struct acpi_device_power power;
+	struct acpi_device_wakeup wakeup;
 	struct acpi_device_perf	performance;
 	struct acpi_device_dir	dir;
 	struct acpi_device_ops	ops;
diff -Nru a/include/acpi/acpi_drivers.h b/include/acpi/acpi_drivers.h
--- a/include/acpi/acpi_drivers.h	2004-10-18 14:56:48 -07:00
+++ b/include/acpi/acpi_drivers.h	2004-10-18 14:56:48 -07:00
@@ -81,7 +81,8 @@
    -------------------------------------------------------------------------- */
 
 #ifdef CONFIG_ACPI_POWER
-
+int acpi_enable_wakeup_device_power (struct acpi_device *dev);
+int acpi_disable_wakeup_device_power (struct acpi_device *dev);
 int acpi_power_get_inferred_state (struct acpi_device *device);
 int acpi_power_transition (struct acpi_device *device, int state);
 #endif
@@ -103,61 +104,6 @@
 #define ACPI_PROCESSOR_LIMIT_DECREMENT	0x02
 
 int acpi_processor_set_thermal_limit(acpi_handle handle, int type);
-
-
-/* --------------------------------------------------------------------------
-                                Debug Support
-   -------------------------------------------------------------------------- */
-
-#define ACPI_DEBUG_RESTORE	0
-#define ACPI_DEBUG_LOW		1
-#define ACPI_DEBUG_MEDIUM	2
-#define ACPI_DEBUG_HIGH		3
-#define ACPI_DEBUG_DRIVERS	4
-
-extern u32 acpi_dbg_level;
-extern u32 acpi_dbg_layer;
-
-static inline void
-acpi_set_debug (
-	u32			flag)
-{
-	static u32		layer_save;
-	static u32		level_save;
-
-	switch (flag) {
-	case ACPI_DEBUG_RESTORE:
-		acpi_dbg_layer = layer_save;
-		acpi_dbg_level = level_save;
-		break;
-	case ACPI_DEBUG_LOW:
-	case ACPI_DEBUG_MEDIUM:
-	case ACPI_DEBUG_HIGH:
-	case ACPI_DEBUG_DRIVERS:
-		layer_save = acpi_dbg_layer;
-		level_save = acpi_dbg_level;
-		break;
-	}
-
-	switch (flag) {
-	case ACPI_DEBUG_LOW:
-		acpi_dbg_layer = ACPI_COMPONENT_DEFAULT | ACPI_ALL_DRIVERS;
-		acpi_dbg_level = ACPI_DEBUG_DEFAULT;
-		break;
-	case ACPI_DEBUG_MEDIUM:
-		acpi_dbg_layer = ACPI_COMPONENT_DEFAULT | ACPI_ALL_DRIVERS;
-		acpi_dbg_level = ACPI_LV_FUNCTIONS | ACPI_LV_ALL_EXCEPTIONS;
-		break;
-	case ACPI_DEBUG_HIGH:
-		acpi_dbg_layer = 0xFFFFFFFF;
-		acpi_dbg_level = 0xFFFFFFFF;
-		break;
-	case ACPI_DEBUG_DRIVERS:
-		acpi_dbg_layer = ACPI_ALL_DRIVERS;
-		acpi_dbg_level = 0xFFFFFFFF;
-		break;
-	}
-}
 
 
 #endif /*__ACPI_DRIVERS_H__*/
diff -Nru a/include/acpi/acpiosxf.h b/include/acpi/acpiosxf.h
--- a/include/acpi/acpiosxf.h	2004-10-18 14:55:54 -07:00
+++ b/include/acpi/acpiosxf.h	2004-10-18 14:55:54 -07:00
@@ -169,11 +169,11 @@
 acpi_os_map_memory (
 	acpi_physical_address           physical_address,
 	acpi_size                       size,
-	void                            **logical_address);
+	void __iomem                  **logical_address);
 
 void
 acpi_os_unmap_memory (
-	void                            *logical_address,
+	void __iomem                  *logical_address,
 	acpi_size                       size);
 
 acpi_status
@@ -189,13 +189,13 @@
 acpi_status
 acpi_os_install_interrupt_handler (
 	u32                             gsi,
-	OSD_HANDLER                     service_routine,
+	acpi_osd_handler                service_routine,
 	void                            *context);
 
 acpi_status
 acpi_os_remove_interrupt_handler (
-	u32                             interrupt_number,
-	OSD_HANDLER                     service_routine);
+	u32                             gsi,
+	acpi_osd_handler                service_routine);
 
 
 /*
@@ -209,7 +209,7 @@
 acpi_status
 acpi_os_queue_for_execution (
 	u32                             priority,
-	OSD_EXECUTION_CALLBACK  function,
+	acpi_osd_exec_callback          function,
 	void                            *context);
 
 void
@@ -262,25 +262,28 @@
 
 /*
  * Platform and hardware-independent PCI configuration space access
+ * Note: Can't use "Register" as a parameter, changed to "Reg" --
+ * certain compilers complain.
  */
 
 acpi_status
 acpi_os_read_pci_configuration (
 	struct acpi_pci_id              *pci_id,
-	u32                             register,
+	u32                             reg,
 	void                            *value,
 	u32                             width);
 
 acpi_status
 acpi_os_write_pci_configuration (
 	struct acpi_pci_id              *pci_id,
-	u32                             register,
+	u32                             reg,
 	acpi_integer                    value,
 	u32                             width);
 
 /*
  * Interim function needed for PCI IRQ routing
  */
+
 void
 acpi_os_derive_pci_id(
 	acpi_handle                     rhandle,
diff -Nru a/include/acpi/acpixf.h b/include/acpi/acpixf.h
--- a/include/acpi/acpixf.h	2004-10-18 14:55:53 -07:00
+++ b/include/acpi/acpixf.h	2004-10-18 14:55:53 -07:00
@@ -296,7 +296,7 @@
 	acpi_handle                     gpe_device,
 	u32                             gpe_number,
 	u32                             type,
-	acpi_gpe_handler                handler,
+	acpi_event_handler              address,
 	void                            *context);
 
 acpi_status
@@ -312,7 +312,7 @@
 acpi_remove_gpe_handler (
 	acpi_handle                     gpe_device,
 	u32                             gpe_number,
-	acpi_gpe_handler                handler);
+	acpi_event_handler              address);
 
 acpi_status
 acpi_enable_event (
@@ -332,6 +332,12 @@
 acpi_get_event_status (
 	u32                             event,
 	acpi_event_status               *event_status);
+
+acpi_status
+acpi_set_gpe_type (
+	acpi_handle                     gpe_device,
+	u32                             gpe_number,
+	u8                              type);
 
 acpi_status
 acpi_enable_gpe (
diff -Nru a/include/acpi/acstruct.h b/include/acpi/acstruct.h
--- a/include/acpi/acstruct.h	2004-10-18 14:55:54 -07:00
+++ b/include/acpi/acstruct.h	2004-10-18 14:55:54 -07:00
@@ -69,13 +69,14 @@
 struct acpi_walk_state
 {
 	u8                                  data_type;                          /* To differentiate various internal objs MUST BE FIRST!*/\
+	u8                                  walk_type;
 	acpi_owner_id                       owner_id;                           /* Owner of objects created during the walk */
 	u8                                  last_predicate;                     /* Result of last predicate */
+	u8                                  reserved;                           /* For alignment */
 	u8                                  current_result;                     /* */
 	u8                                  next_op_info;                       /* Info about next_op */
 	u8                                  num_operands;                       /* Stack pointer for Operands[] array */
 	u8                                  return_used;
-	u8                                  walk_type;
 	u16                                 opcode;                             /* Current AML opcode */
 	u8                                  scope_depth;
 	u8                                  reserved1;
@@ -91,7 +92,8 @@
 	struct acpi_namespace_node          arguments[ACPI_METHOD_NUM_ARGS];    /* Control method arguments */
 	union acpi_operand_object           **caller_return_desc;
 	union acpi_generic_state            *control_state;                     /* List of control states (nested IFs) */
-	struct acpi_namespace_node          *deferred_node;                      /* Used when executing deferred opcodes */
+	struct acpi_namespace_node          *deferred_node;                     /* Used when executing deferred opcodes */
+	struct acpi_gpe_event_info          *gpe_event_info;                    /* Info for GPE (_Lxx/_Exx methods only */
 	struct acpi_namespace_node          local_variables[ACPI_METHOD_NUM_LOCALS];    /* Control method locals */
 	struct acpi_namespace_node          *method_call_node;                  /* Called method Node*/
 	union acpi_parse_object             *method_call_op;                    /* method_call Op if running a method */
@@ -198,6 +200,23 @@
 
 	} mid;
 };
+
+
+/* Internal method parameter list */
+
+struct acpi_parameter_info
+{
+	struct acpi_namespace_node      *node;
+	union acpi_operand_object       **parameters;
+	union acpi_operand_object       *return_object;
+	u8                              parameter_type;
+	u8                              return_object_type;
+};
+
+/* Types for parameter_type above */
+
+#define ACPI_PARAM_ARGS                 0
+#define ACPI_PARAM_GPE                  1
 
 
 #endif
diff -Nru a/include/acpi/actbl.h b/include/acpi/actbl.h
--- a/include/acpi/actbl.h	2004-10-18 14:56:32 -07:00
+++ b/include/acpi/actbl.h	2004-10-18 14:56:32 -07:00
@@ -288,19 +288,6 @@
 };
 
 
-/*
- * High performance timer
- */
-struct hpet_table
-{
-	ACPI_TABLE_HEADER_DEF
-	u32                             hardware_id;
-	u32                             base_address [3];
-	u8                              hpet_number;
-	u16                             clock_tick;
-	u8                              attributes;
-};
-
 #pragma pack()
 
 
@@ -343,5 +330,21 @@
 #include "actbl1.h"   /* Acpi 1.0 table definitions */
 #include "actbl2.h"   /* Acpi 2.0 table definitions */
 
+
+#pragma pack(1)
+/*
+ * High performance timer
+ */
+struct hpet_table
+{
+	ACPI_TABLE_HEADER_DEF
+	u32                             hardware_id;
+	struct acpi_generic_address     base_address;
+	u8                              hpet_number;
+	u16                             clock_tick;
+	u8                              attributes;
+};
+
+#pragma pack()
 
 #endif /* __ACTBL_H__ */
diff -Nru a/include/acpi/actypes.h b/include/acpi/actypes.h
--- a/include/acpi/actypes.h	2004-10-18 14:56:33 -07:00
+++ b/include/acpi/actypes.h	2004-10-18 14:56:33 -07:00
@@ -557,34 +557,56 @@
 #define ACPI_GPE_MAX                    0xFF
 #define ACPI_NUM_GPE                    256
 
+#define ACPI_GPE_ENABLE                 0
+#define ACPI_GPE_DISABLE                1
+
+
 /*
  * GPE info flags - Per GPE
- * +---------+-+-+-+
- * |Bits 8:3 |2|1|0|
- * +---------+-+-+-+
- *          | | | |
- *          | | | +- Edge or Level Triggered
- *          | | +--- Type: Wake or Runtime
- *          | +----- Enabled for wake?
- *          +--------<Reserved>
- */
-#define ACPI_GPE_XRUPT_TYPE_MASK        (u8) 1
-#define ACPI_GPE_LEVEL_TRIGGERED        (u8) 1
-#define ACPI_GPE_EDGE_TRIGGERED         (u8) 0
-
-#define ACPI_GPE_TYPE_MASK              (u8) 2
-#define ACPI_GPE_TYPE_WAKE              (u8) 2
-#define ACPI_GPE_TYPE_RUNTIME           (u8) 0       /* Default */
-
-#define ACPI_GPE_ENABLE_MASK            (u8) 4
-#define ACPI_GPE_ENABLED                (u8) 4
-#define ACPI_GPE_DISABLED               (u8) 0       /* Default */
+ * +-+-+-+---+---+-+
+ * |7|6|5|4:3|2:1|0|
+ * +-+-+-+---+---+-+
+ *  | | |  |   |  |
+ *  | | |  |   |  +--- Interrupt type: Edge or Level Triggered
+ *  | | |  |   +--- Type: Wake-only, Runtime-only, or wake/runtime
+ *  | | |  +--- Type of dispatch -- to method, handler, or none
+ *  | | +--- Enabled for runtime?
+ *  | +--- Enabled for wake?
+ *  +--- System state when GPE ocurred (running/waking)
+ */
+#define ACPI_GPE_XRUPT_TYPE_MASK        (u8) 0x01
+#define ACPI_GPE_LEVEL_TRIGGERED        (u8) 0x01
+#define ACPI_GPE_EDGE_TRIGGERED         (u8) 0x00
+
+#define ACPI_GPE_TYPE_MASK              (u8) 0x06
+#define ACPI_GPE_TYPE_WAKE_RUN          (u8) 0x06
+#define ACPI_GPE_TYPE_WAKE              (u8) 0x02
+#define ACPI_GPE_TYPE_RUNTIME           (u8) 0x04    /* Default */
+
+#define ACPI_GPE_DISPATCH_MASK          (u8) 0x18
+#define ACPI_GPE_DISPATCH_HANDLER       (u8) 0x08
+#define ACPI_GPE_DISPATCH_METHOD        (u8) 0x10
+#define ACPI_GPE_DISPATCH_NOT_USED      (u8) 0x00    /* Default */
+
+#define ACPI_GPE_RUN_ENABLE_MASK        (u8) 0x20
+#define ACPI_GPE_RUN_ENABLED            (u8) 0x20
+#define ACPI_GPE_RUN_DISABLED           (u8) 0x00    /* Default */
+
+#define ACPI_GPE_WAKE_ENABLE_MASK       (u8) 0x40
+#define ACPI_GPE_WAKE_ENABLED           (u8) 0x40
+#define ACPI_GPE_WAKE_DISABLED          (u8) 0x00    /* Default */
+
+#define ACPI_GPE_ENABLE_MASK            (u8) 0x60    /* Both run/wake */
+
+#define ACPI_GPE_SYSTEM_MASK            (u8) 0x80
+#define ACPI_GPE_SYSTEM_RUNNING         (u8) 0x80
+#define ACPI_GPE_SYSTEM_WAKING          (u8) 0x00
 
 /*
  * Flags for GPE and Lock interfaces
  */
-#define ACPI_EVENT_WAKE_ENABLE          0x2
-#define ACPI_EVENT_WAKE_DISABLE         0x2
+#define ACPI_EVENT_WAKE_ENABLE          0x2             /* acpi_gpe_enable */
+#define ACPI_EVENT_WAKE_DISABLE         0x2             /* acpi_gpe_disable */
 
 #define ACPI_NOT_ISR                    0x1
 #define ACPI_ISR                        0x0
@@ -592,9 +614,10 @@
 
 /* Notify types */
 
-#define ACPI_SYSTEM_NOTIFY              0
-#define ACPI_DEVICE_NOTIFY              1
-#define ACPI_MAX_NOTIFY_HANDLER_TYPE    1
+#define ACPI_SYSTEM_NOTIFY              0x1
+#define ACPI_DEVICE_NOTIFY              0x2
+#define ACPI_ALL_NOTIFY                 0x3
+#define ACPI_MAX_NOTIFY_HANDLER_TYPE    0x3
 
 #define ACPI_MAX_SYS_NOTIFY             0x7f
 
@@ -775,11 +798,11 @@
  */
 
 typedef u32
-(ACPI_SYSTEM_XFACE *OSD_HANDLER) (
+(ACPI_SYSTEM_XFACE *acpi_osd_handler) (
 	void                            *context);
 
 typedef void
-(ACPI_SYSTEM_XFACE *OSD_EXECUTION_CALLBACK) (
+(ACPI_SYSTEM_XFACE *acpi_osd_exec_callback) (
 	void                            *context);
 
 /*
@@ -790,10 +813,6 @@
 	void                                *context);
 
 typedef
-void (*acpi_gpe_handler) (
-	void                                *context);
-
-typedef
 void (*acpi_notify_handler) (
 	acpi_handle                         device,
 	u32                                 value,
@@ -880,6 +899,7 @@
 #define ACPI_VALID_HID                  0x0004
 #define ACPI_VALID_UID                  0x0008
 #define ACPI_VALID_CID                  0x0010
+#define ACPI_VALID_SXDS                 0x0020
 
 
 #define ACPI_COMMON_OBJ_INFO \
@@ -899,12 +919,12 @@
 {
 	ACPI_COMMON_OBJ_INFO;
 
-	u8                                  highest_dstates[4]; /* _sx_d values 0xFF indicates not valid */
 	u32                                 valid;              /* Indicates which fields below are valid */
 	u32                                 current_status;     /* _STA value */
 	acpi_integer                        address;            /* _ADR value if any */
 	struct acpi_device_id               hardware_id;        /* _HID value if any */
 	struct acpi_device_id               unique_id;          /* _UID value if any */
+	u8                                  highest_dstates[4]; /* _sx_d values: 0xFF indicates not valid */
 	struct acpi_compatible_id_list      compatibility_id;   /* List of _CIDs if any */
 };
 
diff -Nru a/include/acpi/platform/acenv.h b/include/acpi/platform/acenv.h
--- a/include/acpi/platform/acenv.h	2004-10-18 14:56:19 -07:00
+++ b/include/acpi/platform/acenv.h	2004-10-18 14:56:19 -07:00
@@ -152,12 +152,8 @@
 #define COMPILER_DEPENDENT_INT64   long long
 #define COMPILER_DEPENDENT_UINT64  unsigned long long
 
-
-/* Name of host operating system (returned by the _OS_ namespace object) */
-
-#define ACPI_OS_NAME         "Intel ACPI/CA Core Subsystem"
-
-/* This macro is used to tag functions as "printf-like" because
+/*
+ * This macro is used to tag functions as "printf-like" because
  * some compilers can catch printf format string problems. MSVC
  * doesn't, so this is proprocessed away.
  */
diff -Nru a/include/acpi/platform/aclinux.h b/include/acpi/platform/aclinux.h
--- a/include/acpi/platform/aclinux.h	2004-10-18 14:56:49 -07:00
+++ b/include/acpi/platform/aclinux.h	2004-10-18 14:56:49 -07:00
@@ -44,8 +44,6 @@
 #ifndef __ACLINUX_H__
 #define __ACLINUX_H__
 
-#define ACPI_OS_NAME                "Linux"
-
 #define ACPI_USE_SYSTEM_CLIBRARY
 #define ACPI_USE_DO_WHILE_0
 
diff -Nru a/include/asm-alpha/a.out.h b/include/asm-alpha/a.out.h
--- a/include/asm-alpha/a.out.h	2004-10-18 14:56:49 -07:00
+++ b/include/asm-alpha/a.out.h	2004-10-18 14:56:49 -07:00
@@ -95,7 +95,7 @@
    Worse, we have to notice the start address before swapping to use
    /sbin/loader, which of course is _not_ a TASO application.  */
 #define SET_AOUT_PERSONALITY(BFPM, EX) \
-	set_personality (((BFPM->sh_bang || EX.ah.entry < 0x100000000 \
+	set_personality (((BFPM->sh_bang || EX.ah.entry < 0x100000000L \
 			   ? ADDR_LIMIT_32BIT : 0) | PER_OSF4))
 
 #define STACK_TOP \
diff -Nru a/include/asm-alpha/bitops.h b/include/asm-alpha/bitops.h
--- a/include/asm-alpha/bitops.h	2004-10-18 14:56:32 -07:00
+++ b/include/asm-alpha/bitops.h	2004-10-18 14:56:32 -07:00
@@ -2,7 +2,6 @@
 #define _ALPHA_BITOPS_H
 
 #include <linux/config.h>
-#include <linux/kernel.h>
 #include <asm/compiler.h>
 
 /*
@@ -324,7 +323,7 @@
 #endif
 
 /* Compute powers of two for the given integer.  */
-static inline int floor_log2(unsigned long word)
+static inline long floor_log2(unsigned long word)
 {
 #if defined(__alpha_cix__) && defined(__alpha_fix__)
 	return 63 - __kernel_ctlz(word);
@@ -336,7 +335,7 @@
 #endif
 }
 
-static inline int ceil_log2(unsigned int word)
+static inline long ceil_log2(unsigned long word)
 {
 	long bit = floor_log2(word);
 	return bit + (word > (1UL << bit));
diff -Nru a/include/asm-alpha/bug.h b/include/asm-alpha/bug.h
--- a/include/asm-alpha/bug.h	2004-10-18 14:56:49 -07:00
+++ b/include/asm-alpha/bug.h	2004-10-18 14:56:49 -07:00
@@ -9,15 +9,7 @@
   __asm__ __volatile__("call_pal %0  # bugchk\n\t"".long %1\n\t.8byte %2" \
 		       : : "i" (PAL_bugchk), "i"(__LINE__), "i"(__FILE__))
 
-#define BUG_ON(condition) do { if (unlikely((condition)!=0)) BUG(); } while(0)
-
-#define PAGE_BUG(page)	BUG()
-
-#define WARN_ON(condition) do { \
-	if (unlikely((condition)!=0)) { \
-		printk("Badness in %s at %s:%d\n", __FUNCTION__, __FILE__, __LINE__); \
-		dump_stack(); \
-	} \
-} while (0)
+#define HAVE_ARCH_BUG
+#include <asm-generic/bug.h>
 
 #endif
diff -Nru a/include/asm-alpha/cache.h b/include/asm-alpha/cache.h
--- a/include/asm-alpha/cache.h	2004-10-18 14:56:29 -07:00
+++ b/include/asm-alpha/cache.h	2004-10-18 14:56:29 -07:00
@@ -20,6 +20,6 @@
 
 #define L1_CACHE_ALIGN(x)  (((x)+(L1_CACHE_BYTES-1))&~(L1_CACHE_BYTES-1))
 #define SMP_CACHE_BYTES    L1_CACHE_BYTES
-#define L1_CACHE_SHIFT_MAX 6	/* largest L1 which this arch supports */
+#define L1_CACHE_SHIFT_MAX L1_CACHE_SHIFT
 
 #endif
diff -Nru a/include/asm-alpha/compiler.h b/include/asm-alpha/compiler.h
--- a/include/asm-alpha/compiler.h	2004-10-18 14:56:33 -07:00
+++ b/include/asm-alpha/compiler.h	2004-10-18 14:56:33 -07:00
@@ -17,9 +17,9 @@
 # define __kernel_extbl(val, shift)	__builtin_alpha_extbl(val, shift)
 # define __kernel_extwl(val, shift)	__builtin_alpha_extwl(val, shift)
 # define __kernel_cmpbge(a, b)		__builtin_alpha_cmpbge(a, b)
-# define __kernel_cttz(x)		__builtin_ctz(x)
-# define __kernel_ctlz(x)		__builtin_clz(x)
-# define __kernel_ctpop(x)		__builtin_popcount(x)
+# define __kernel_cttz(x)		__builtin_ctzl(x)
+# define __kernel_ctlz(x)		__builtin_clzl(x)
+# define __kernel_ctpop(x)		__builtin_popcountl(x)
 #else
 # define __kernel_insbl(val, shift)					\
   ({ unsigned long __kir;						\
@@ -89,5 +89,15 @@
 #define __kernel_stw(val,mem) \
   __asm__("stw %1,%0" : "=m"(mem) : "r"(val))
 #endif
+
+/* Some idiots over in <linux/compiler.h> thought inline should imply
+   always_inline.  This breaks stuff.  We'll include this file whenever
+   we run into such problems.  */
+
+#include <linux/compiler.h>
+#undef inline
+#undef __inline__
+#undef __inline
+
 
 #endif /* __ALPHA_COMPILER_H */
diff -Nru a/include/asm-alpha/core_apecs.h b/include/asm-alpha/core_apecs.h
--- a/include/asm-alpha/core_apecs.h	2004-10-18 14:57:04 -07:00
+++ b/include/asm-alpha/core_apecs.h	2004-10-18 14:57:04 -07:00
@@ -370,178 +370,142 @@
  * data to/from the right byte-lanes.
  */
 
-#define vip	volatile int *
-#define vuip	volatile unsigned int *
-#define vulp	volatile unsigned long *
+#define vip	volatile int __force *
+#define vuip	volatile unsigned int __force *
+#define vulp	volatile unsigned long __force *
+
+#define APECS_SET_HAE						\
+	do {							\
+		if (addr >= (1UL << 24)) {			\
+			unsigned long msb = addr & 0xf8000000;	\
+			addr -= msb;				\
+			set_hae(msb);				\
+		}						\
+	} while (0)
+
+__EXTERN_INLINE unsigned int apecs_ioread8(void __iomem *xaddr)
+{
+	unsigned long addr = (unsigned long) xaddr;
+	unsigned long result, base_and_type;
+
+	if (addr >= APECS_DENSE_MEM) {
+		addr -= APECS_DENSE_MEM;
+		APECS_SET_HAE;
+		base_and_type = APECS_SPARSE_MEM + 0x00;
+	} else {
+		addr -= APECS_IO;
+		base_and_type = APECS_IO + 0x00;
+	}
 
-__EXTERN_INLINE u8 apecs_inb(unsigned long addr)
-{
-	long result = *(vip) ((addr << 5) + APECS_IO + 0x00);
+	result = *(vip) ((addr << 5) + base_and_type);
 	return __kernel_extbl(result, addr & 3);
 }
 
-__EXTERN_INLINE void apecs_outb(u8 b, unsigned long addr)
-{
-	unsigned long w;
-
-	w = __kernel_insbl(b, addr & 3);
-	*(vuip) ((addr << 5) + APECS_IO + 0x00) = w;
-	mb();
-}
-
-__EXTERN_INLINE u16 apecs_inw(unsigned long addr)
-{
-	long result = *(vip) ((addr << 5) + APECS_IO + 0x08);
-	return __kernel_extwl(result, addr & 3);
-}
-
-__EXTERN_INLINE void apecs_outw(u16 b, unsigned long addr)
+__EXTERN_INLINE void apecs_iowrite8(u8 b, void __iomem *xaddr)
 {
-	unsigned long w;
+	unsigned long addr = (unsigned long) xaddr;
+	unsigned long w, base_and_type;
 
-	w = __kernel_inswl(b, addr & 3);
-	*(vuip) ((addr << 5) + APECS_IO + 0x08) = w;
-	mb();
-}
-
-__EXTERN_INLINE u32 apecs_inl(unsigned long addr)
-{
-	return *(vuip) ((addr << 5) + APECS_IO + 0x18);
-}
+	if (addr >= APECS_DENSE_MEM) {
+		addr -= APECS_DENSE_MEM;
+		APECS_SET_HAE;
+		base_and_type = APECS_SPARSE_MEM + 0x00;
+	} else {
+		addr -= APECS_IO;
+		base_and_type = APECS_IO + 0x00;
+	}
 
-__EXTERN_INLINE void apecs_outl(u32 b, unsigned long addr)
-{
-	*(vuip) ((addr << 5) + APECS_IO + 0x18) = b;
-	mb();
+	w = __kernel_insbl(b, addr & 3);
+	*(vuip) ((addr << 5) + base_and_type) = w;
 }
 
-
-/*
- * Memory functions.  64-bit and 32-bit accesses are done through
- * dense memory space, everything else through sparse space.
- */
-
-__EXTERN_INLINE u8 apecs_readb(unsigned long addr)
+__EXTERN_INLINE unsigned int apecs_ioread16(void __iomem *xaddr)
 {
-	unsigned long result, msb;
+	unsigned long addr = (unsigned long) xaddr;
+	unsigned long result, base_and_type;
 
-	addr -= APECS_DENSE_MEM;
-	if (addr >= (1UL << 24)) {
-		msb = addr & 0xf8000000;
-		addr -= msb;
-		set_hae(msb);
+	if (addr >= APECS_DENSE_MEM) {
+		addr -= APECS_DENSE_MEM;
+		APECS_SET_HAE;
+		base_and_type = APECS_SPARSE_MEM + 0x08;
+	} else {
+		addr -= APECS_IO;
+		base_and_type = APECS_IO + 0x08;
 	}
-	result = *(vip) ((addr << 5) + APECS_SPARSE_MEM + 0x00);
-	return __kernel_extbl(result, addr & 3);
-}
-
-__EXTERN_INLINE u16 apecs_readw(unsigned long addr)
-{
-	unsigned long result, msb;
 
-	addr -= APECS_DENSE_MEM;
-	if (addr >= (1UL << 24)) {
-		msb = addr & 0xf8000000;
-		addr -= msb;
-		set_hae(msb);
-	}
-	result = *(vip) ((addr << 5) + APECS_SPARSE_MEM + 0x08);
+	result = *(vip) ((addr << 5) + base_and_type);
 	return __kernel_extwl(result, addr & 3);
 }
 
-__EXTERN_INLINE u32 apecs_readl(unsigned long addr)
+__EXTERN_INLINE void apecs_iowrite16(u16 b, void __iomem *xaddr)
 {
-	return (*(vuip)addr) & 0xffffffff;
-}
+	unsigned long addr = (unsigned long) xaddr;
+	unsigned long w, base_and_type;
 
-__EXTERN_INLINE u64 apecs_readq(unsigned long addr)
-{
-	return *(vulp)addr;
-}
-
-__EXTERN_INLINE void apecs_writeb(u8 b, unsigned long addr)
-{
-	unsigned long msb;
-
-	addr -= APECS_DENSE_MEM;
-	if (addr >= (1UL << 24)) {
-		msb = addr & 0xf8000000;
-		addr -= msb;
-		set_hae(msb);
+	if (addr >= APECS_DENSE_MEM) {
+		addr -= APECS_DENSE_MEM;
+		APECS_SET_HAE;
+		base_and_type = APECS_SPARSE_MEM + 0x08;
+	} else {
+		addr -= APECS_IO;
+		base_and_type = APECS_IO + 0x08;
 	}
-	*(vuip) ((addr << 5) + APECS_SPARSE_MEM + 0x00) = b * 0x01010101;
+
+	w = __kernel_inswl(b, addr & 3);
+	*(vuip) ((addr << 5) + base_and_type) = w;
 }
 
-__EXTERN_INLINE void apecs_writew(u16 b, unsigned long addr)
+__EXTERN_INLINE unsigned int apecs_ioread32(void __iomem *xaddr)
 {
-	unsigned long msb;
-
-	addr -= APECS_DENSE_MEM;
-	if (addr >= (1UL << 24)) {
-		msb = addr & 0xf8000000;
-		addr -= msb;
-		set_hae(msb);
-	}
-	*(vuip) ((addr << 5) + APECS_SPARSE_MEM + 0x08) = b * 0x00010001;
+	unsigned long addr = (unsigned long) xaddr;
+	if (addr < APECS_DENSE_MEM)
+		addr = ((addr - APECS_IO) << 5) + APECS_IO + 0x18;
+	return *(vuip)addr;
 }
 
-__EXTERN_INLINE void apecs_writel(u32 b, unsigned long addr)
+__EXTERN_INLINE void apecs_iowrite32(u32 b, void __iomem *xaddr)
 {
+	unsigned long addr = (unsigned long) xaddr;
+	if (addr < APECS_DENSE_MEM)
+		addr = ((addr - APECS_IO) << 5) + APECS_IO + 0x18;
 	*(vuip)addr = b;
 }
 
-__EXTERN_INLINE void apecs_writeq(u64 b, unsigned long addr)
+__EXTERN_INLINE void __iomem *apecs_ioportmap(unsigned long addr)
 {
-	*(vulp)addr = b;
+	return (void __iomem *)(addr + APECS_IO);
 }
 
-__EXTERN_INLINE unsigned long apecs_ioremap(unsigned long addr,
-					    unsigned long size
-					    __attribute__((unused)))
+__EXTERN_INLINE void __iomem *apecs_ioremap(unsigned long addr,
+					    unsigned long size)
 {
-	return addr + APECS_DENSE_MEM;
+	return (void __iomem *)(addr + APECS_DENSE_MEM);
 }
 
-__EXTERN_INLINE void apecs_iounmap(unsigned long addr)
+__EXTERN_INLINE int apecs_is_ioaddr(unsigned long addr)
 {
-	return;
+	return addr >= IDENT_ADDR + 0x180000000UL;
 }
 
-__EXTERN_INLINE int apecs_is_ioaddr(unsigned long addr)
+__EXTERN_INLINE int apecs_is_mmio(const volatile void __iomem *addr)
 {
-	return addr >= IDENT_ADDR + 0x180000000UL;
+	return (unsigned long)addr >= APECS_DENSE_MEM;
 }
 
+#undef APECS_SET_HAE
+
 #undef vip
 #undef vuip
 #undef vulp
 
-#ifdef __WANT_IO_DEF
-
-#define __inb(p)		apecs_inb((unsigned long)(p))
-#define __inw(p)		apecs_inw((unsigned long)(p))
-#define __inl(p)		apecs_inl((unsigned long)(p))
-#define __outb(x,p)		apecs_outb((x),(unsigned long)(p))
-#define __outw(x,p)		apecs_outw((x),(unsigned long)(p))
-#define __outl(x,p)		apecs_outl((x),(unsigned long)(p))
-#define __readb(a)		apecs_readb((unsigned long)(a))
-#define __readw(a)		apecs_readw((unsigned long)(a))
-#define __readl(a)		apecs_readl((unsigned long)(a))
-#define __readq(a)		apecs_readq((unsigned long)(a))
-#define __writeb(x,a)		apecs_writeb((x),(unsigned long)(a))
-#define __writew(x,a)		apecs_writew((x),(unsigned long)(a))
-#define __writel(x,a)		apecs_writel((x),(unsigned long)(a))
-#define __writeq(x,a)		apecs_writeq((x),(unsigned long)(a))
-#define __ioremap(a,s)		apecs_ioremap((unsigned long)(a),(s))
-#define __iounmap(a)		apecs_iounmap((unsigned long)(a))
-#define __is_ioaddr(a)		apecs_is_ioaddr((unsigned long)(a))
-
-#define __raw_readl(a)		__readl(a)
-#define __raw_readq(a)		__readq(a)
-#define __raw_writel(v,a)	__writel((v),(a))
-#define __raw_writeq(v,a)	__writeq((v),(a))
-
-#endif /* __WANT_IO_DEF */
+#undef __IO_PREFIX
+#define __IO_PREFIX		apecs
+#define apecs_trivial_io_bw	0
+#define apecs_trivial_io_lq	0
+#define apecs_trivial_rw_bw	2
+#define apecs_trivial_rw_lq	1
+#define apecs_trivial_iounmap	1
+#include <asm/io_trivial.h>
 
 #ifdef __IO_EXTERN_INLINE
 #undef __EXTERN_INLINE
diff -Nru a/include/asm-alpha/core_cia.h b/include/asm-alpha/core_cia.h
--- a/include/asm-alpha/core_cia.h	2004-10-18 14:56:32 -07:00
+++ b/include/asm-alpha/core_cia.h	2004-10-18 14:56:32 -07:00
@@ -306,90 +306,6 @@
  * get at PCI memory and I/O.
  */
 
-#define vucp	volatile unsigned char *
-#define vusp	volatile unsigned short *
-#define vip	volatile int *
-#define vuip	volatile unsigned int *
-#define vulp	volatile unsigned long *
-
-__EXTERN_INLINE u8 cia_inb(unsigned long addr)
-{
-	long result;
-	result = *(vip) ((addr << 5) + CIA_IO + 0x00);
-	return __kernel_extbl(result, addr & 3);
-}
-
-__EXTERN_INLINE void cia_outb(u8 b, unsigned long addr)
-{
-	unsigned long w = __kernel_insbl(b, addr & 3);
-	*(vuip) ((addr << 5) + CIA_IO + 0x00) = w;
-	mb();
-}
-
-__EXTERN_INLINE u16 cia_inw(unsigned long addr)
-{
-	long result;
-	result = *(vip) ((addr << 5) + CIA_IO + 0x08);
-	return __kernel_extwl(result, addr & 3);
-}
-
-__EXTERN_INLINE void cia_outw(u16 b, unsigned long addr)
-{
-	unsigned long w = __kernel_inswl(b, addr & 3);
-	*(vuip) ((addr << 5) + CIA_IO + 0x08) = w;
-	mb();
-}
-
-__EXTERN_INLINE u32 cia_inl(unsigned long addr)
-{
-	return *(vuip) ((addr << 5) + CIA_IO + 0x18);
-}
-
-__EXTERN_INLINE void cia_outl(u32 b, unsigned long addr)
-{
-	*(vuip) ((addr << 5) + CIA_IO + 0x18) = b;
-	mb();
-}
-
-__EXTERN_INLINE u8 cia_bwx_inb(unsigned long addr)
-{
-	/* ??? I wish I could get rid of this.  But there's no ioremap
-	   equivalent for I/O space.  PCI I/O can be forced into the
-	   CIA BWX I/O region, but that doesn't take care of legacy
-	   ISA crap.  */
-
-	return __kernel_ldbu(*(vucp)(addr+CIA_BW_IO));
-}
-
-__EXTERN_INLINE void cia_bwx_outb(u8 b, unsigned long addr)
-{
-	__kernel_stb(b, *(vucp)(addr+CIA_BW_IO));
-	mb();
-}
-
-__EXTERN_INLINE u16 cia_bwx_inw(unsigned long addr)
-{
-	return __kernel_ldwu(*(vusp)(addr+CIA_BW_IO));
-}
-
-__EXTERN_INLINE void cia_bwx_outw(u16 b, unsigned long addr)
-{
-	__kernel_stw(b, *(vusp)(addr+CIA_BW_IO));
-	mb();
-}
-
-__EXTERN_INLINE u32 cia_bwx_inl(unsigned long addr)
-{
-	return *(vuip)(addr+CIA_BW_IO);
-}
-
-__EXTERN_INLINE void cia_bwx_outl(u32 b, unsigned long addr)
-{
-	*(vuip)(addr+CIA_BW_IO) = b;
-	mb();
-}
-
-
 /*
  * Memory functions.  64-bit and 32-bit accesses are done through
  * dense memory space, everything else through sparse space.
@@ -422,195 +338,158 @@
  *
  */
 
-__EXTERN_INLINE u8 cia_readb(unsigned long addr)
+#define vip	volatile int __force *
+#define vuip	volatile unsigned int __force *
+#define vulp	volatile unsigned long __force *
+
+__EXTERN_INLINE unsigned int cia_ioread8(void __iomem *xaddr)
 {
-	unsigned long result;
+	unsigned long addr = (unsigned long) xaddr;
+	unsigned long result, base_and_type;
 
+	/* We can use CIA_MEM_R1_MASK for io ports too, since it is large
+	   enough to cover all io ports, and smaller than CIA_IO.  */
 	addr &= CIA_MEM_R1_MASK;
-	result = *(vip) ((addr << 5) + CIA_SPARSE_MEM + 0x00);
+	if (addr >= CIA_DENSE_MEM)
+		base_and_type = CIA_SPARSE_MEM + 0x00;
+	else
+		base_and_type = CIA_IO + 0x00;
+
+	result = *(vip) ((addr << 5) + base_and_type);
 	return __kernel_extbl(result, addr & 3);
 }
 
-__EXTERN_INLINE u16 cia_readw(unsigned long addr)
+__EXTERN_INLINE void cia_iowrite8(u8 b, void __iomem *xaddr)
 {
-	unsigned long result;
+	unsigned long addr = (unsigned long) xaddr;
+	unsigned long w, base_and_type;
 
 	addr &= CIA_MEM_R1_MASK;
-	result = *(vip) ((addr << 5) + CIA_SPARSE_MEM + 0x08);
-	return __kernel_extwl(result, addr & 3);
-}
+	if (addr >= CIA_DENSE_MEM)
+		base_and_type = CIA_SPARSE_MEM + 0x00;
+	else
+		base_and_type = CIA_IO + 0x00;
 
-__EXTERN_INLINE void cia_writeb(u8 b, unsigned long addr)
-{
-	unsigned long w;
-
-	addr &= CIA_MEM_R1_MASK;
 	w = __kernel_insbl(b, addr & 3);
-	*(vuip) ((addr << 5) + CIA_SPARSE_MEM + 0x00) = w;
+	*(vuip) ((addr << 5) + base_and_type) = w;
 }
 
-__EXTERN_INLINE void cia_writew(u16 b, unsigned long addr)
+__EXTERN_INLINE unsigned int cia_ioread16(void __iomem *xaddr)
 {
-	unsigned long w;
+	unsigned long addr = (unsigned long) xaddr;
+	unsigned long result, base_and_type;
 
 	addr &= CIA_MEM_R1_MASK;
-	w = __kernel_inswl(b, addr & 3);
-	*(vuip) ((addr << 5) + CIA_SPARSE_MEM + 0x08) = w;
-}
-
-__EXTERN_INLINE u32 cia_readl(unsigned long addr)
-{
-	return *(vuip)addr;
-}
-
-__EXTERN_INLINE u64 cia_readq(unsigned long addr)
-{
-	return *(vulp)addr;
-}
-
-__EXTERN_INLINE void cia_writel(u32 b, unsigned long addr)
-{
-	*(vuip)addr = b;
-}
+	if (addr >= CIA_DENSE_MEM)
+		base_and_type = CIA_SPARSE_MEM + 0x08;
+	else
+		base_and_type = CIA_IO + 0x08;
 
-__EXTERN_INLINE void cia_writeq(u64 b, unsigned long addr)
-{
-	*(vulp)addr = b;
+	result = *(vip) ((addr << 5) + base_and_type);
+	return __kernel_extwl(result, addr & 3);
 }
 
-__EXTERN_INLINE unsigned long cia_ioremap(unsigned long addr,
-					  unsigned long size
-					  __attribute__((unused)))
+__EXTERN_INLINE void cia_iowrite16(u16 b, void __iomem *xaddr)
 {
-	return addr + CIA_DENSE_MEM;
-}
+	unsigned long addr = (unsigned long) xaddr;
+	unsigned long w, base_and_type;
 
-__EXTERN_INLINE void cia_iounmap(unsigned long addr)
-{
-	return;
-}
+	addr &= CIA_MEM_R1_MASK;
+	if (addr >= CIA_DENSE_MEM)
+		base_and_type = CIA_SPARSE_MEM + 0x08;
+	else
+		base_and_type = CIA_IO + 0x08;
 
-__EXTERN_INLINE u8 cia_bwx_readb(unsigned long addr)
-{
-	return __kernel_ldbu(*(vucp)addr);
+	w = __kernel_inswl(b, addr & 3);
+	*(vuip) ((addr << 5) + base_and_type) = w;
 }
 
-__EXTERN_INLINE u16 cia_bwx_readw(unsigned long addr)
+__EXTERN_INLINE unsigned int cia_ioread32(void __iomem *xaddr)
 {
-	return __kernel_ldwu(*(vusp)addr);
+	unsigned long addr = (unsigned long) xaddr;
+	if (addr < CIA_DENSE_MEM)
+		addr = ((addr - CIA_IO) << 5) + CIA_IO + 0x18;
+	return *(vuip)addr;
 }
 
-__EXTERN_INLINE u32 cia_bwx_readl(unsigned long addr)
+__EXTERN_INLINE void cia_iowrite32(u32 b, void __iomem *xaddr)
 {
-	return *(vuip)addr;
+	unsigned long addr = (unsigned long) xaddr;
+	if (addr < CIA_DENSE_MEM)
+		addr = ((addr - CIA_IO) << 5) + CIA_IO + 0x18;
+	*(vuip)addr = b;
 }
 
-__EXTERN_INLINE u64 cia_bwx_readq(unsigned long addr)
+__EXTERN_INLINE void __iomem *cia_ioportmap(unsigned long addr)
 {
-	return *(vulp)addr;
+	return (void __iomem *)(addr + CIA_IO);
 }
 
-__EXTERN_INLINE void cia_bwx_writeb(u8 b, unsigned long addr)
+__EXTERN_INLINE void __iomem *cia_ioremap(unsigned long addr,
+					  unsigned long size)
 {
-	__kernel_stb(b, *(vucp)addr);
+	return (void __iomem *)(addr + CIA_DENSE_MEM);
 }
 
-__EXTERN_INLINE void cia_bwx_writew(u16 b, unsigned long addr)
+__EXTERN_INLINE int cia_is_ioaddr(unsigned long addr)
 {
-	__kernel_stw(b, *(vusp)addr);
+	return addr >= IDENT_ADDR + 0x8000000000UL;
 }
 
-__EXTERN_INLINE void cia_bwx_writel(u32 b, unsigned long addr)
+__EXTERN_INLINE int cia_is_mmio(const volatile void __iomem *addr)
 {
-	*(vuip)addr = b;
+	return (unsigned long)addr >= CIA_DENSE_MEM;
 }
 
-__EXTERN_INLINE void cia_bwx_writeq(u64 b, unsigned long addr)
+__EXTERN_INLINE void __iomem *cia_bwx_ioportmap(unsigned long addr)
 {
-	*(vulp)addr = b;
+	return (void __iomem *)(addr + CIA_BW_IO);
 }
 
-__EXTERN_INLINE unsigned long cia_bwx_ioremap(unsigned long addr,
+__EXTERN_INLINE void __iomem *cia_bwx_ioremap(unsigned long addr,
 					      unsigned long size)
 {
-	return addr + CIA_BW_MEM;
+	return (void __iomem *)(addr + CIA_BW_MEM);
 }
 
-__EXTERN_INLINE void cia_bwx_iounmap(unsigned long addr)
+__EXTERN_INLINE int cia_bwx_is_ioaddr(unsigned long addr)
 {
-	return;
+	return addr >= IDENT_ADDR + 0x8000000000UL;
 }
 
-__EXTERN_INLINE int cia_is_ioaddr(unsigned long addr)
+__EXTERN_INLINE int cia_bwx_is_mmio(const volatile void __iomem *addr)
 {
-	return addr >= IDENT_ADDR + 0x8000000000UL;
+	return (unsigned long)addr < CIA_BW_IO;
 }
 
-#undef vucp
-#undef vusp
 #undef vip
 #undef vuip
 #undef vulp
 
-#ifdef __WANT_IO_DEF
+#undef __IO_PREFIX
+#define __IO_PREFIX		cia
+#define cia_trivial_rw_bw	2
+#define cia_trivial_rw_lq	1
+#define cia_trivial_io_bw	0
+#define cia_trivial_io_lq	0
+#define cia_trivial_iounmap	1
+#include <asm/io_trivial.h>
+
+#undef __IO_PREFIX
+#define __IO_PREFIX		cia_bwx
+#define cia_bwx_trivial_rw_bw	1
+#define cia_bwx_trivial_rw_lq	1
+#define cia_bwx_trivial_io_bw	1
+#define cia_bwx_trivial_io_lq	1
+#define cia_bwx_trivial_iounmap	1
+#include <asm/io_trivial.h>
 
+#undef __IO_PREFIX
 #ifdef CONFIG_ALPHA_PYXIS
-# define __inb(p)		cia_bwx_inb((unsigned long)(p))
-# define __inw(p)		cia_bwx_inw((unsigned long)(p))
-# define __inl(p)		cia_bwx_inl((unsigned long)(p))
-# define __outb(x,p)		cia_bwx_outb((x),(unsigned long)(p))
-# define __outw(x,p)		cia_bwx_outw((x),(unsigned long)(p))
-# define __outl(x,p)		cia_bwx_outl((x),(unsigned long)(p))
-# define __readb(a)		cia_bwx_readb((unsigned long)(a))
-# define __readw(a)		cia_bwx_readw((unsigned long)(a))
-# define __readl(a)		cia_bwx_readl((unsigned long)(a))
-# define __readq(a)		cia_bwx_readq((unsigned long)(a))
-# define __writeb(x,a)		cia_bwx_writeb((x),(unsigned long)(a))
-# define __writew(x,a)		cia_bwx_writew((x),(unsigned long)(a))
-# define __writel(x,a)		cia_bwx_writel((x),(unsigned long)(a))
-# define __writeq(x,a)		cia_bwx_writeq((x),(unsigned long)(a))
-# define __ioremap(a,s)		cia_bwx_ioremap((unsigned long)(a),(s))
-# define __iounmap(a)           cia_bwx_iounmap((unsigned long)(a))
-# define inb(p)			__inb(p)
-# define inw(p)			__inw(p)
-# define inl(p)			__inl(p)
-# define outb(x,p)		__outb((x),(p))
-# define outw(x,p)		__outw((x),(p))
-# define outl(x,p)		__outl((x),(p))
-# define __raw_readb(a)		__readb(a)
-# define __raw_readw(a)		__readw(a)
-# define __raw_readl(a)		__readl(a)
-# define __raw_readq(a)		__readq(a)
-# define __raw_writeb(x,a)	__writeb((x),(a))
-# define __raw_writew(x,a)	__writew((x),(a))
-# define __raw_writel(x,a)	__writel((x),(a))
-# define __raw_writeq(x,a)	__writeq((x),(a))
+#define __IO_PREFIX		cia_bwx
 #else
-# define __inb(p)		cia_inb((unsigned long)(p))
-# define __inw(p)		cia_inw((unsigned long)(p))
-# define __inl(p)		cia_inl((unsigned long)(p))
-# define __outb(x,p)		cia_outb((x),(unsigned long)(p))
-# define __outw(x,p)		cia_outw((x),(unsigned long)(p))
-# define __outl(x,p)		cia_outl((x),(unsigned long)(p))
-# define __readb(a)		cia_readb((unsigned long)(a))
-# define __readw(a)		cia_readw((unsigned long)(a))
-# define __readl(a)		cia_readl((unsigned long)(a))
-# define __readq(a)		cia_readq((unsigned long)(a))
-# define __writeb(x,a)		cia_writeb((x),(unsigned long)(a))
-# define __writew(x,a)		cia_writew((x),(unsigned long)(a))
-# define __writel(x,a)		cia_writel((x),(unsigned long)(a))
-# define __writeq(x,a)		cia_writeq((x),(unsigned long)(a))
-# define __ioremap(a,s)		cia_ioremap((unsigned long)(a),(s))
-# define __iounmap(a)           cia_iounmap((unsigned long)(a))
-# define __raw_readl(a)		__readl(a)
-# define __raw_readq(a)		__readq(a)
-# define __raw_writel(v,a)	__writel((v),(a))
-# define __raw_writeq(v,a)	__writeq((v),(a))
-#endif /* PYXIS */
-
-#define __is_ioaddr(a)		cia_is_ioaddr((unsigned long)(a))
-
-#endif /* __WANT_IO_DEF */
+#define __IO_PREFIX		cia
+#endif
 
 #ifdef __IO_EXTERN_INLINE
 #undef __EXTERN_INLINE
diff -Nru a/include/asm-alpha/core_irongate.h b/include/asm-alpha/core_irongate.h
--- a/include/asm-alpha/core_irongate.h	2004-10-18 14:56:28 -07:00
+++ b/include/asm-alpha/core_irongate.h	2004-10-18 14:56:28 -07:00
@@ -190,137 +190,37 @@
  * K7 can only use linear accesses to get at PCI memory and I/O spaces.
  */
 
-#define vucp	volatile unsigned char *
-#define vusp	volatile unsigned short *
-#define vuip	volatile unsigned int *
-#define vulp	volatile unsigned long *
-
-__EXTERN_INLINE u8 irongate_inb(unsigned long addr)
-{
-	return __kernel_ldbu(*(vucp)(addr + IRONGATE_IO));
-}
-
-__EXTERN_INLINE void irongate_outb(u8 b, unsigned long addr)
-{
-        __kernel_stb(b, *(vucp)(addr + IRONGATE_IO));
-	mb();
-}
-
-__EXTERN_INLINE u16 irongate_inw(unsigned long addr)
-{
-	return __kernel_ldwu(*(vusp)(addr + IRONGATE_IO));
-}
-
-__EXTERN_INLINE void irongate_outw(u16 b, unsigned long addr)
-{
-        __kernel_stw(b, *(vusp)(addr + IRONGATE_IO));
-	mb();
-}
-
-__EXTERN_INLINE u32 irongate_inl(unsigned long addr)
-{
-	return *(vuip)(addr + IRONGATE_IO);
-}
-
-__EXTERN_INLINE void irongate_outl(u32 b, unsigned long addr)
-{
-        *(vuip)(addr + IRONGATE_IO) = b;
-	mb();
-}
-
 /*
  * Memory functions.  All accesses are done through linear space.
  */
 
-__EXTERN_INLINE u8 irongate_readb(unsigned long addr)
+__EXTERN_INLINE void __iomem *irongate_ioportmap(unsigned long addr)
 {
-	return __kernel_ldbu(*(vucp)addr);
+	return (void __iomem *)(addr + IRONGATE_IO);
 }
 
-__EXTERN_INLINE u16 irongate_readw(unsigned long addr)
-{
-	return __kernel_ldwu(*(vusp)addr);
-}
-
-__EXTERN_INLINE u32 irongate_readl(unsigned long addr)
-{
-	return (*(vuip)addr) & 0xffffffff;
-}
-
-__EXTERN_INLINE u64 irongate_readq(unsigned long addr)
-{
-	return *(vulp)addr;
-}
-
-__EXTERN_INLINE void irongate_writeb(u8 b, unsigned long addr)
-{
-	__kernel_stb(b, *(vucp)addr);
-}
-
-__EXTERN_INLINE void irongate_writew(u16 b, unsigned long addr)
-{
-	__kernel_stw(b, *(vusp)addr);
-}
-
-__EXTERN_INLINE void irongate_writel(u32 b, unsigned long addr)
-{
-	*(vuip)addr = b;
-}
-
-__EXTERN_INLINE void irongate_writeq(u64 b, unsigned long addr)
-{
-	*(vulp)addr = b;
-}
-
-extern unsigned long irongate_ioremap(unsigned long addr, unsigned long size);
-extern void irongate_iounmap(unsigned long addr);
+extern void __iomem *irongate_ioremap(unsigned long addr, unsigned long size);
+extern void irongate_iounmap(volatile void __iomem *addr);
 
 __EXTERN_INLINE int irongate_is_ioaddr(unsigned long addr)
 {
 	return addr >= IRONGATE_MEM;
 }
 
-#undef vucp
-#undef vusp
-#undef vuip
-#undef vulp
-
-#ifdef __WANT_IO_DEF
-
-#define __inb(p)		irongate_inb((unsigned long)(p))
-#define __inw(p)		irongate_inw((unsigned long)(p))
-#define __inl(p)		irongate_inl((unsigned long)(p))
-#define __outb(x,p)		irongate_outb((x),(unsigned long)(p))
-#define __outw(x,p)		irongate_outw((x),(unsigned long)(p))
-#define __outl(x,p)		irongate_outl((x),(unsigned long)(p))
-#define __readb(a)		irongate_readb((unsigned long)(a))
-#define __readw(a)		irongate_readw((unsigned long)(a))
-#define __readl(a)		irongate_readl((unsigned long)(a))
-#define __readq(a)		irongate_readq((unsigned long)(a))
-#define __writeb(x,a)		irongate_writeb((x),(unsigned long)(a))
-#define __writew(x,a)		irongate_writew((x),(unsigned long)(a))
-#define __writel(x,a)		irongate_writel((x),(unsigned long)(a))
-#define __writeq(x,a)		irongate_writeq((x),(unsigned long)(a))
-#define __ioremap(a,s)		irongate_ioremap((unsigned long)(a),(s))
-#define __iounmap(a)		irongate_iounmap((unsigned long)(a))
-#define __is_ioaddr(a)		irongate_is_ioaddr((unsigned long)(a))
-
-#define inb(p)			__inb(p)
-#define inw(p)			__inw(p)
-#define inl(p)			__inl(p)
-#define outb(x,p)		__outb((x),(p))
-#define outw(x,p)		__outw((x),(p))
-#define outl(x,p)		__outl((x),(p))
-#define __raw_readb(a)		__readb(a)
-#define __raw_readw(a)		__readw(a)
-#define __raw_readl(a)		__readl(a)
-#define __raw_readq(a)		__readq(a)
-#define __raw_writeb(v,a)	__writeb((v),(a))
-#define __raw_writew(v,a)	__writew((v),(a))
-#define __raw_writel(v,a)	__writel((v),(a))
-#define __raw_writeq(v,a)	__writeq((v),(a))
+__EXTERN_INLINE int irongate_is_mmio(const volatile void __iomem *xaddr)
+{
+	unsigned long addr = (unsigned long)xaddr;
+	return addr < IRONGATE_IO || addr >= IRONGATE_CONF;
+}
 
-#endif /* __WANT_IO_DEF */
+#undef __IO_PREFIX
+#define __IO_PREFIX			irongate
+#define irongate_trivial_rw_bw		1
+#define irongate_trivial_rw_lq		1
+#define irongate_trivial_io_bw		1
+#define irongate_trivial_io_lq		1
+#define irongate_trivial_iounmap	0
+#include <asm/io_trivial.h>
 
 #ifdef __IO_EXTERN_INLINE
 #undef __EXTERN_INLINE
diff -Nru a/include/asm-alpha/core_lca.h b/include/asm-alpha/core_lca.h
--- a/include/asm-alpha/core_lca.h	2004-10-18 14:57:04 -07:00
+++ b/include/asm-alpha/core_lca.h	2004-10-18 14:57:04 -07:00
@@ -215,145 +215,117 @@
  * data to/from the right byte-lanes.
  */
 
-#define vip	volatile int *
-#define vuip	volatile unsigned int *
-#define vulp	volatile unsigned long *
+#define vip	volatile int __force *
+#define vuip	volatile unsigned int __force *
+#define vulp	volatile unsigned long __force *
+
+#define LCA_SET_HAE						\
+	do {							\
+		if (addr >= (1UL << 24)) {			\
+			unsigned long msb = addr & 0xf8000000;	\
+			addr -= msb;				\
+			set_hae(msb);				\
+		}						\
+	} while (0)
+
+
+__EXTERN_INLINE unsigned int lca_ioread8(void __iomem *xaddr)
+{
+	unsigned long addr = (unsigned long) xaddr;
+	unsigned long result, base_and_type;
+
+	if (addr >= LCA_DENSE_MEM) {
+		addr -= LCA_DENSE_MEM;
+		LCA_SET_HAE;
+		base_and_type = LCA_SPARSE_MEM + 0x00;
+	} else {
+		addr -= LCA_IO;
+		base_and_type = LCA_IO + 0x00;
+	}
 
-__EXTERN_INLINE u8 lca_inb(unsigned long addr)
-{
-	long result = *(vip) ((addr << 5) + LCA_IO + 0x00);
+	result = *(vip) ((addr << 5) + base_and_type);
 	return __kernel_extbl(result, addr & 3);
 }
 
-__EXTERN_INLINE void lca_outb(u8 b, unsigned long addr)
-{
-	unsigned long w;
-
-	w = __kernel_insbl(b, addr & 3);
-	*(vuip) ((addr << 5) + LCA_IO + 0x00) = w;
-	mb();
-}
-
-__EXTERN_INLINE u16 lca_inw(unsigned long addr)
-{
-	long result = *(vip) ((addr << 5) + LCA_IO + 0x08);
-	return __kernel_extwl(result, addr & 3);
-}
-
-__EXTERN_INLINE void lca_outw(u16 b, unsigned long addr)
+__EXTERN_INLINE void lca_iowrite8(u8 b, void __iomem *xaddr)
 {
-	unsigned long w;
+	unsigned long addr = (unsigned long) xaddr;
+	unsigned long w, base_and_type;
 
-	w = __kernel_inswl(b, addr & 3);
-	*(vuip) ((addr << 5) + LCA_IO + 0x08) = w;
-	mb();
-}
-
-__EXTERN_INLINE u32 lca_inl(unsigned long addr)
-{
-	return *(vuip) ((addr << 5) + LCA_IO + 0x18);
-}
+	if (addr >= LCA_DENSE_MEM) {
+		addr -= LCA_DENSE_MEM;
+		LCA_SET_HAE;
+		base_and_type = LCA_SPARSE_MEM + 0x00;
+	} else {
+		addr -= LCA_IO;
+		base_and_type = LCA_IO + 0x00;
+	}
 
-__EXTERN_INLINE void lca_outl(u32 b, unsigned long addr)
-{
-	*(vuip) ((addr << 5) + LCA_IO + 0x18) = b;
-	mb();
+	w = __kernel_insbl(b, addr & 3);
+	*(vuip) ((addr << 5) + base_and_type) = w;
 }
 
-
-/*
- * Memory functions.  64-bit and 32-bit accesses are done through
- * dense memory space, everything else through sparse space.
- */
-
-__EXTERN_INLINE u8 lca_readb(unsigned long addr)
+__EXTERN_INLINE unsigned int lca_ioread16(void __iomem *xaddr)
 {
-	unsigned long result, msb;
+	unsigned long addr = (unsigned long) xaddr;
+	unsigned long result, base_and_type;
 
-	addr -= LCA_DENSE_MEM;
-	if (addr >= (1UL << 24)) {
-		msb = addr & 0xf8000000;
-		addr -= msb;
-		set_hae(msb);
+	if (addr >= LCA_DENSE_MEM) {
+		addr -= LCA_DENSE_MEM;
+		LCA_SET_HAE;
+		base_and_type = LCA_SPARSE_MEM + 0x08;
+	} else {
+		addr -= LCA_IO;
+		base_and_type = LCA_IO + 0x08;
 	}
-	result = *(vip) ((addr << 5) + LCA_SPARSE_MEM + 0x00);
-	return __kernel_extbl(result, addr & 3);
-}
-
-__EXTERN_INLINE u16 lca_readw(unsigned long addr)
-{
-	unsigned long result, msb;
 
-	addr -= LCA_DENSE_MEM;
-	if (addr >= (1UL << 24)) {
-		msb = addr & 0xf8000000;
-		addr -= msb;
-		set_hae(msb);
-	}
-	result = *(vip) ((addr << 5) + LCA_SPARSE_MEM + 0x08);
+	result = *(vip) ((addr << 5) + base_and_type);
 	return __kernel_extwl(result, addr & 3);
 }
 
-__EXTERN_INLINE u32 lca_readl(unsigned long addr)
+__EXTERN_INLINE void lca_iowrite16(u16 b, void __iomem *xaddr)
 {
-	return (*(vuip)addr) & 0xffffffff;
-}
+	unsigned long addr = (unsigned long) xaddr;
+	unsigned long w, base_and_type;
 
-__EXTERN_INLINE u64 lca_readq(unsigned long addr)
-{
-	return *(vulp)addr;
-}
-
-__EXTERN_INLINE void lca_writeb(u8 b, unsigned long addr)
-{
-	unsigned long msb;
-	unsigned long w;
-
-	addr -= LCA_DENSE_MEM;
-	if (addr >= (1UL << 24)) {
-		msb = addr & 0xf8000000;
-		addr -= msb;
-		set_hae(msb);
+	if (addr >= LCA_DENSE_MEM) {
+		addr -= LCA_DENSE_MEM;
+		LCA_SET_HAE;
+		base_and_type = LCA_SPARSE_MEM + 0x08;
+	} else {
+		addr -= LCA_IO;
+		base_and_type = LCA_IO + 0x08;
 	}
-	w = __kernel_insbl(b, addr & 3);
-	*(vuip) ((addr << 5) + LCA_SPARSE_MEM + 0x00) = w;
-}
-
-__EXTERN_INLINE void lca_writew(u16 b, unsigned long addr)
-{
-	unsigned long msb;
-	unsigned long w;
 
-	addr -= LCA_DENSE_MEM;
-	if (addr >= (1UL << 24)) {
-		msb = addr & 0xf8000000;
-		addr -= msb;
-		set_hae(msb);
-	}
 	w = __kernel_inswl(b, addr & 3);
-	*(vuip) ((addr << 5) + LCA_SPARSE_MEM + 0x08) = w;
+	*(vuip) ((addr << 5) + base_and_type) = w;
 }
 
-__EXTERN_INLINE void lca_writel(u32 b, unsigned long addr)
+__EXTERN_INLINE unsigned int lca_ioread32(void __iomem *xaddr)
 {
-	*(vuip)addr = b;
+	unsigned long addr = (unsigned long) xaddr;
+	if (addr < LCA_DENSE_MEM)
+		addr = ((addr - LCA_IO) << 5) + LCA_IO + 0x18;
+	return *(vuip)addr;
 }
 
-__EXTERN_INLINE void lca_writeq(u64 b, unsigned long addr)
+__EXTERN_INLINE void lca_iowrite32(u32 b, void __iomem *xaddr)
 {
-	*(vulp)addr = b;
+	unsigned long addr = (unsigned long) xaddr;
+	if (addr < LCA_DENSE_MEM)
+		addr = ((addr - LCA_IO) << 5) + LCA_IO + 0x18;
+	*(vuip)addr = b;
 }
 
-__EXTERN_INLINE unsigned long lca_ioremap(unsigned long addr,
-					  unsigned long size
-					  __attribute__((unused)))
+__EXTERN_INLINE void __iomem *lca_ioportmap(unsigned long addr)
 {
-	return addr + LCA_DENSE_MEM;
+	return (void __iomem *)(addr + LCA_IO);
 }
 
-__EXTERN_INLINE void lca_iounmap(unsigned long addr)
+__EXTERN_INLINE void __iomem *lca_ioremap(unsigned long addr,
+					  unsigned long size)
 {
-	return;
+	return (void __iomem *)(addr + LCA_DENSE_MEM);
 }
 
 __EXTERN_INLINE int lca_is_ioaddr(unsigned long addr)
@@ -361,36 +333,23 @@
 	return addr >= IDENT_ADDR + 0x120000000UL;
 }
 
+__EXTERN_INLINE int lca_is_mmio(const volatile void __iomem *addr)
+{
+	return (unsigned long)addr >= LCA_DENSE_MEM;
+}
+
 #undef vip
 #undef vuip
 #undef vulp
 
-#ifdef __WANT_IO_DEF
-
-#define __inb(p)		lca_inb((unsigned long)(p))
-#define __inw(p)		lca_inw((unsigned long)(p))
-#define __inl(p)		lca_inl((unsigned long)(p))
-#define __outb(x,p)		lca_outb((x),(unsigned long)(p))
-#define __outw(x,p)		lca_outw((x),(unsigned long)(p))
-#define __outl(x,p)		lca_outl((x),(unsigned long)(p))
-#define __readb(a)		lca_readb((unsigned long)(a))
-#define __readw(a)		lca_readw((unsigned long)(a))
-#define __readl(a)		lca_readl((unsigned long)(a))
-#define __readq(a)		lca_readq((unsigned long)(a))
-#define __writeb(x,a)		lca_writeb((x),(unsigned long)(a))
-#define __writew(x,a)		lca_writew((x),(unsigned long)(a))
-#define __writel(x,a)		lca_writel((x),(unsigned long)(a))
-#define __writeq(x,a)		lca_writeq((x),(unsigned long)(a))
-#define __ioremap(a,s)		lca_ioremap((unsigned long)(a),(s))
-#define __iounmap(a)		lca_iounmap((unsigned long)(a))
-#define __is_ioaddr(a)		lca_is_ioaddr((unsigned long)(a))
-
-#define __raw_readl(a)		__readl(a)
-#define __raw_readq(a)		__readq(a)
-#define __raw_writel(v,a)	__writel((v),(a))
-#define __raw_writeq(v,a)	__writeq((v),(a))
-
-#endif /* __WANT_IO_DEF */
+#undef __IO_PREFIX
+#define __IO_PREFIX		lca
+#define lca_trivial_rw_bw	2
+#define lca_trivial_rw_lq	1
+#define lca_trivial_io_bw	0
+#define lca_trivial_io_lq	0
+#define lca_trivial_iounmap	1
+#include <asm/io_trivial.h>
 
 #ifdef __IO_EXTERN_INLINE
 #undef __EXTERN_INLINE
diff -Nru a/include/asm-alpha/core_marvel.h b/include/asm-alpha/core_marvel.h
--- a/include/asm-alpha/core_marvel.h	2004-10-18 14:56:27 -07:00
+++ b/include/asm-alpha/core_marvel.h	2004-10-18 14:56:27 -07:00
@@ -325,249 +325,48 @@
  * I/O functions. All access through linear space.
  */
 
-#define vucp	volatile unsigned char *
-#define vusp	volatile unsigned short *
-#define vuip	volatile unsigned int *
-#define vulp	volatile unsigned long *
-
-#ifdef CONFIG_VGA_HOSE
-extern struct pci_controller *pci_vga_hose;
-
-# define __marvel_is_port_vga(a)	\
-        (((a) >= 0x3b0) && ((a) < 0x3e0) && ((a) != 0x3b3) && ((a) != 0x3d3))
-# define __marvel_is_mem_vga(a)	(((a) >= 0xa0000) && ((a) <= 0xc0000))
-# define FIXUP_IOADDR_VGA(a) do {			\
-	if (pci_vga_hose && __marvel_is_port_vga(a))	\
-		a += pci_vga_hose->io_space->start;	\
-    } while(0)
-#else
-# define FIXUP_IOADDR_VGA(a)
-#endif 
-
-#define __marvel_is_port_kbd(a)	(((a) == 0x60) || ((a) == 0x64))
-#define __marvel_is_port_rtc(a)	(((a) == 0x70) || ((a) == 0x71))
-
-#define FIXUP_IOADDR_LEGACY(a)
-
-#define FIXUP_IOADDR(a) do {				\
-	FIXUP_IOADDR_VGA(a);				\
-        FIXUP_IOADDR_LEGACY(a);				\
-    } while(0)
-
-#if 0
-# define IOBUG(x) printk x
-# define IOBUG_FILTER_IOADDR(a, x)	\
-    if (!__marvel_is_port_kbd(a) && !__marvel_is_port_rtc(a)) IOBUG(x)
-#else
-# define IOBUG(x)
-# define IOBUG_FILTER_IOADDR(a, x)
-#endif
-
-extern u8 __marvel_rtc_io(int write, u8 b, unsigned long addr);
-#define __marvel_rtc_inb(a)	__marvel_rtc_io(0, 0, (a))
-#define __marvel_rtc_outb(b, a)	__marvel_rtc_io(1, (b), (a))
-
-__EXTERN_INLINE int marvel_is_ioaddr(unsigned long addr)
-{
-	return (addr & (1UL << 40)) != 0; /*FIXME - hardwire*/
-}
-
-__EXTERN_INLINE u8 marvel_inb(unsigned long addr)
-{
-	FIXUP_IOADDR(addr);
-	if (!marvel_is_ioaddr(addr)) {
-		if (__marvel_is_port_kbd(addr))
-			return (u8)0;
-		if (__marvel_is_port_rtc(addr))
-			return __marvel_rtc_inb(addr);
-		IOBUG_FILTER_IOADDR(addr, 
-				    ("Bad IO addr %lx - reading -1\n", addr));
-		return (u8)-1;
-	}
-	return __kernel_ldbu(*(vucp)addr);
-}
-
-__EXTERN_INLINE void marvel_outb(u8 b, unsigned long addr)
-{
-	FIXUP_IOADDR(addr);
-	if (!marvel_is_ioaddr(addr)) {
-		if (__marvel_is_port_rtc(addr)) 
-			return (void)__marvel_rtc_outb(b, addr);
-		IOBUG_FILTER_IOADDR(addr, 
-				    ("Bad IO addr %lx - reading -1\n", addr));
-		return;
-	}
-	__kernel_stb(b, *(vucp)addr);
-	mb();
-}
-
-__EXTERN_INLINE u16 marvel_inw(unsigned long addr)
-{
-	FIXUP_IOADDR(addr);
-	if (!marvel_is_ioaddr(addr)) {
-		IOBUG_FILTER_IOADDR(addr, 
-				    ("Bad IO addr %lx - reading -1\n", addr));
-		return (u16)-1;
-	}
-	return __kernel_ldwu(*(vusp)addr);
-}
-
-__EXTERN_INLINE void marvel_outw(u16 w, unsigned long addr)
-{
-	FIXUP_IOADDR(addr);
-	if (!marvel_is_ioaddr(addr)) {
-		IOBUG_FILTER_IOADDR(addr, 
-				    ("Bad IO addr %lx - reading -1\n", addr));
-		return;
-	}
-	__kernel_stw(w, *(vusp)addr);
-	mb();
-}
-
-__EXTERN_INLINE u32 marvel_inl(unsigned long addr)
-{
-	FIXUP_IOADDR(addr);
-	if (!marvel_is_ioaddr(addr)) {
-		IOBUG_FILTER_IOADDR(addr, 
-				    ("Bad IO addr %lx - reading -1\n", addr));
-		return (u32)-1;
-	}
-	return *(vuip)addr;
-}
-
-__EXTERN_INLINE void marvel_outl(u32 l, unsigned long addr)
-{
-	FIXUP_IOADDR(addr);
-	if (!marvel_is_ioaddr(addr)) {
-		IOBUG_FILTER_IOADDR(addr, 
-				    ("Bad IO addr %lx - reading -1\n", addr));
-		return;
-	}
-	*(vuip)addr = l;
-	mb();
-}
-
 /*
  * Memory functions.  All accesses through linear space.
  */
 
-extern unsigned long marvel_ioremap(unsigned long addr, unsigned long size);
-extern void marvel_iounmap(unsigned long addr);
+#define vucp	volatile unsigned char __force *
+#define vusp	volatile unsigned short __force *
 
-__EXTERN_INLINE u8 marvel_readb(unsigned long addr)
-{
-	if (!marvel_is_ioaddr(addr)) {
-		IOBUG(("Bad MEM addr %lx - reading -1\n", addr));
-		return (u8)-1;
-	}
-	return __kernel_ldbu(*(vucp)addr);
-}
+extern unsigned int marvel_ioread8(void __iomem *);
+extern void marvel_iowrite8(u8 b, void __iomem *);
 
-__EXTERN_INLINE u16 marvel_readw(unsigned long addr)
+__EXTERN_INLINE unsigned int marvel_ioread16(void __iomem *addr)
 {
-	if (!marvel_is_ioaddr(addr)) {
-		IOBUG(("Bad MEM addr %lx - reading -1\n", addr));
-		return (u16)-1;
-	}
 	return __kernel_ldwu(*(vusp)addr);
 }
 
-__EXTERN_INLINE u32 marvel_readl(unsigned long addr)
-{
-	if (!marvel_is_ioaddr(addr)) {
-		IOBUG(("Bad MEM addr %lx - reading -1\n", addr));
-		return (u32)-1;
-	}
-	return *(vuip)addr;
-}
-
-__EXTERN_INLINE u64 marvel_readq(unsigned long addr)
-{
-	if (!marvel_is_ioaddr(addr)) {
-		IOBUG(("Bad MEM addr %lx - reading -1\n", addr));
-		return (u64)-1;
-	}
-	return *(vulp)addr;
-}
-
-__EXTERN_INLINE void marvel_writeb(u8 b, unsigned long addr)
-{
-	if (!marvel_is_ioaddr(addr)) {
-		IOBUG(("Bad MEM addr %lx - dropping store\n", addr));
-		return;
-	}
-	__kernel_stb(b, *(vucp)addr);
-}
-
-__EXTERN_INLINE void marvel_writew(u16 w, unsigned long addr)
+__EXTERN_INLINE void marvel_iowrite16(u16 b, void __iomem *addr)
 {
-	if (!marvel_is_ioaddr(addr)) {
-		IOBUG(("Bad MEM addr %lx - dropping store\n", addr));
-		return;
-	}
-	__kernel_stw(w, *(vusp)addr);
+	__kernel_stw(b, *(vusp)addr);
 }
 
-__EXTERN_INLINE void marvel_writel(u32 l, unsigned long addr)
-{
-	if (!marvel_is_ioaddr(addr)) {
-		IOBUG(("Bad MEM addr %lx - dropping store\n", addr));
-		return;
-	}
-	*(vuip)addr = l;
-}
+extern void __iomem *marvel_ioremap(unsigned long addr, unsigned long size);
+extern void marvel_iounmap(volatile void __iomem *addr);
+extern void __iomem *marvel_ioportmap (unsigned long addr);
 
-__EXTERN_INLINE void marvel_writeq(u64 q, unsigned long addr)
+__EXTERN_INLINE int marvel_is_ioaddr(unsigned long addr)
 {
-	if (!marvel_is_ioaddr(addr)) {
-		IOBUG(("Bad MEM addr %lx - dropping store\n", addr));
-		return;
-	}
-	*(vulp)addr = q;
+	return (addr >> 40) & 1;
 }
 
-#undef FIXUP_IOADDR
-#undef FIXUP_IOADDR_LEGACY
-#undef FIXUP_IOADDR_VGA
+extern int marvel_is_mmio(const volatile void __iomem *);
 
 #undef vucp
 #undef vusp
-#undef vuip
-#undef vulp
-
-#ifdef __WANT_IO_DEF
-
-#define __inb(p)		marvel_inb((unsigned long)(p))
-#define __inw(p)		marvel_inw((unsigned long)(p))
-#define __inl(p)		marvel_inl((unsigned long)(p))
-#define __outb(x,p)		marvel_outb((x),(unsigned long)(p))
-#define __outw(x,p)		marvel_outw((x),(unsigned long)(p))
-#define __outl(x,p)		marvel_outl((x),(unsigned long)(p))
-#define __readb(a)		marvel_readb((unsigned long)(a))
-#define __readw(a)		marvel_readw((unsigned long)(a))
-#define __readl(a)		marvel_readl((unsigned long)(a))
-#define __readq(a)		marvel_readq((unsigned long)(a))
-#define __writeb(x,a)		marvel_writeb((x),(unsigned long)(a))
-#define __writew(x,a)		marvel_writew((x),(unsigned long)(a))
-#define __writel(x,a)		marvel_writel((x),(unsigned long)(a))
-#define __writeq(x,a)		marvel_writeq((x),(unsigned long)(a))
-#define __ioremap(a,s)		marvel_ioremap((unsigned long)(a),(s))
-#define __iounmap(a)		marvel_iounmap((unsigned long)(a))
-#define __is_ioaddr(a)		marvel_is_ioaddr((unsigned long)(a))
-
-/* Disable direct inlining of these calls with the debug checks present.  */
-#if 0
-#define __raw_readb(a)		__readb(a)
-#define __raw_readw(a)		__readw(a)
-#define __raw_readl(a)		__readl(a)
-#define __raw_readq(a)		__readq(a)
-#define __raw_writeb(v,a)	__writeb(v,a)
-#define __raw_writew(v,a)	__writew(v,a)
-#define __raw_writel(v,a)	__writel(v,a)
-#define __raw_writeq(v,a)	__writeq(v,a)
-#endif
 
-#endif /* __WANT_IO_DEF */
+#undef __IO_PREFIX
+#define __IO_PREFIX		marvel
+#define marvel_trivial_rw_bw	1
+#define marvel_trivial_rw_lq	1
+#define marvel_trivial_io_bw	0
+#define marvel_trivial_io_lq	1
+#define marvel_trivial_iounmap	0
+#include <asm/io_trivial.h>
 
 #ifdef __IO_EXTERN_INLINE
 # undef __EXTERN_INLINE
diff -Nru a/include/asm-alpha/core_mcpcia.h b/include/asm-alpha/core_mcpcia.h
--- a/include/asm-alpha/core_mcpcia.h	2004-10-18 14:57:05 -07:00
+++ b/include/asm-alpha/core_mcpcia.h	2004-10-18 14:57:05 -07:00
@@ -211,91 +211,6 @@
  * Unfortunately, we can't use BWIO with EV5, so for now, we always use SPARSE.
  */
 
-#define vucp	volatile unsigned char *
-#define vusp	volatile unsigned short *
-#define vip	volatile int *
-#define vuip	volatile unsigned int *
-#define vulp	volatile unsigned long *
-
-__EXTERN_INLINE u8 mcpcia_inb(unsigned long in_addr)
-{
-	unsigned long addr, hose, result;
-
-	addr = in_addr & 0xffffUL;
-	hose = in_addr & ~0xffffUL;
-
-	/* ??? I wish I could get rid of this.  But there's no ioremap
-	   equivalent for I/O space.  PCI I/O can be forced into the
-	   correct hose's I/O region, but that doesn't take care of
-	   legacy ISA crap.  */
-	hose += MCPCIA_IO_BIAS;
-
-	result = *(vip) ((addr << 5) + hose + 0x00);
-	return __kernel_extbl(result, addr & 3);
-}
-
-__EXTERN_INLINE void mcpcia_outb(u8 b, unsigned long in_addr)
-{
-	unsigned long addr, hose, w;
-
-	addr = in_addr & 0xffffUL;
-	hose = in_addr & ~0xffffUL;
-	hose += MCPCIA_IO_BIAS;
-
-	w = __kernel_insbl(b, addr & 3);
-	*(vuip) ((addr << 5) + hose + 0x00) = w;
-	mb();
-}
-
-__EXTERN_INLINE u16 mcpcia_inw(unsigned long in_addr)
-{
-	unsigned long addr, hose, result;
-
-	addr = in_addr & 0xffffUL;
-	hose = in_addr & ~0xffffUL;
-	hose += MCPCIA_IO_BIAS;
-
-	result = *(vip) ((addr << 5) + hose + 0x08);
-	return __kernel_extwl(result, addr & 3);
-}
-
-__EXTERN_INLINE void mcpcia_outw(u16 b, unsigned long in_addr)
-{
-	unsigned long addr, hose, w;
-
-	addr = in_addr & 0xffffUL;
-	hose = in_addr & ~0xffffUL;
-	hose += MCPCIA_IO_BIAS;
-
-	w = __kernel_inswl(b, addr & 3);
-	*(vuip) ((addr << 5) + hose + 0x08) = w;
-	mb();
-}
-
-__EXTERN_INLINE u32 mcpcia_inl(unsigned long in_addr)
-{
-	unsigned long addr, hose;
-
-	addr = in_addr & 0xffffUL;
-	hose = in_addr & ~0xffffUL;
-	hose += MCPCIA_IO_BIAS;
-
-	return *(vuip) ((addr << 5) + hose + 0x18);
-}
-
-__EXTERN_INLINE void mcpcia_outl(u32 b, unsigned long in_addr)
-{
-	unsigned long addr, hose;
-
-	addr = in_addr & 0xffffUL;
-	hose = in_addr & ~0xffffUL;
-	hose += MCPCIA_IO_BIAS;
-
-	*(vuip) ((addr << 5) + hose + 0x18) = b;
-	mb();
-}
-
-
 /*
  * Memory functions.  64-bit and 32-bit accesses are done through
  * dense memory space, everything else through sparse space.
@@ -328,149 +243,131 @@
  *
  */
 
-__EXTERN_INLINE unsigned long mcpcia_ioremap(unsigned long addr,
-					     unsigned long size
-					     __attribute__((unused)))
-{
-	return addr + MCPCIA_MEM_BIAS;
-}
+#define vip	volatile int __force *
+#define vuip	volatile unsigned int __force *
+
+#ifdef MCPCIA_ONE_HAE_WINDOW
+#define MCPCIA_FROB_MMIO						\
+	if (__mcpcia_is_mmio(hose)) {					\
+		set_hae(hose & 0xffffffff);				\
+		hose = hose - MCPCIA_DENSE(4) + MCPCIA_SPARSE(4);	\
+	}
+#else
+#define MCPCIA_FROB_MMIO						\
+	if (__mcpcia_is_mmio(hose)) {					\
+		hose = hose - MCPCIA_DENSE(4) + MCPCIA_SPARSE(4);	\
+	}
+#endif
 
-__EXTERN_INLINE void mcpcia_iounmap(unsigned long addr)
+static inline int __mcpcia_is_mmio(unsigned long addr)
 {
-	return;
+	return (addr & 0x80000000UL) == 0;
 }
 
-__EXTERN_INLINE int mcpcia_is_ioaddr(unsigned long addr)
+__EXTERN_INLINE unsigned int mcpcia_ioread8(void __iomem *xaddr)
 {
-	return addr >= MCPCIA_SPARSE(0);
+	unsigned long addr = (unsigned long)xaddr & MCPCIA_MEM_MASK;
+	unsigned long hose = (unsigned long)xaddr & ~MCPCIA_MEM_MASK;
+	unsigned long result;
+
+	MCPCIA_FROB_MMIO;
+
+	result = *(vip) ((addr << 5) + hose + 0x00);
+	return __kernel_extbl(result, addr & 3);
 }
 
-__EXTERN_INLINE u8 mcpcia_readb(unsigned long in_addr)
+__EXTERN_INLINE void mcpcia_iowrite8(u8 b, void __iomem *xaddr)
 {
-	unsigned long addr = in_addr & 0xffffffffUL;
-	unsigned long hose = in_addr & ~0xffffffffUL;
-	unsigned long result, work;
-
-#ifndef MCPCIA_ONE_HAE_WINDOW
-	unsigned long msb;
-	msb = addr & ~MCPCIA_MEM_MASK;
-	set_hae(msb);
-#endif
-	addr = addr & MCPCIA_MEM_MASK;
+	unsigned long addr = (unsigned long)xaddr & MCPCIA_MEM_MASK;
+	unsigned long hose = (unsigned long)xaddr & ~MCPCIA_MEM_MASK;
+	unsigned long w;
 
-	hose = hose - MCPCIA_DENSE(4) + MCPCIA_SPARSE(4);
-	work = ((addr << 5) + hose + 0x00);
-	result = *(vip) work;
-	return __kernel_extbl(result, addr & 3);
+	MCPCIA_FROB_MMIO;
+
+	w = __kernel_insbl(b, addr & 3);
+	*(vuip) ((addr << 5) + hose + 0x00) = w;
 }
 
-__EXTERN_INLINE u16 mcpcia_readw(unsigned long in_addr)
+__EXTERN_INLINE unsigned int mcpcia_ioread16(void __iomem *xaddr)
 {
-	unsigned long addr = in_addr & 0xffffffffUL;
-	unsigned long hose = in_addr & ~0xffffffffUL;
-	unsigned long result, work;
-
-#ifndef MCPCIA_ONE_HAE_WINDOW
-	unsigned long msb;
-	msb = addr & ~MCPCIA_MEM_MASK;
-	set_hae(msb);
-#endif
-	addr = addr & MCPCIA_MEM_MASK;
+	unsigned long addr = (unsigned long)xaddr & MCPCIA_MEM_MASK;
+	unsigned long hose = (unsigned long)xaddr & ~MCPCIA_MEM_MASK;
+	unsigned long result;
+
+	MCPCIA_FROB_MMIO;
 
-	hose = hose - MCPCIA_DENSE(4) + MCPCIA_SPARSE(4);
-	work = ((addr << 5) + hose + 0x08);
-	result = *(vip) work;
+	result = *(vip) ((addr << 5) + hose + 0x08);
 	return __kernel_extwl(result, addr & 3);
 }
 
-__EXTERN_INLINE void mcpcia_writeb(u8 b, unsigned long in_addr)
+__EXTERN_INLINE void mcpcia_iowrite16(u16 b, void __iomem *xaddr)
 {
-	unsigned long addr = in_addr & 0xffffffffUL;
-	unsigned long hose = in_addr & ~0xffffffffUL;
+	unsigned long addr = (unsigned long)xaddr & MCPCIA_MEM_MASK;
+	unsigned long hose = (unsigned long)xaddr & ~MCPCIA_MEM_MASK;
 	unsigned long w;
 
-#ifndef MCPCIA_ONE_HAE_WINDOW
-	unsigned long msb;
-	msb = addr & ~MCPCIA_MEM_MASK;
-	set_hae(msb);
-#endif
-	addr = addr & MCPCIA_MEM_MASK;
+	MCPCIA_FROB_MMIO;
 
-	w = __kernel_insbl(b, in_addr & 3);
-	hose = hose - MCPCIA_DENSE(4) + MCPCIA_SPARSE(4);
-	*(vuip) ((addr << 5) + hose + 0x00) = w;
+	w = __kernel_inswl(b, addr & 3);
+	*(vuip) ((addr << 5) + hose + 0x08) = w;
 }
 
-__EXTERN_INLINE void mcpcia_writew(u16 b, unsigned long in_addr)
+__EXTERN_INLINE unsigned int mcpcia_ioread32(void __iomem *xaddr)
 {
-	unsigned long addr = in_addr & 0xffffffffUL;
-	unsigned long hose = in_addr & ~0xffffffffUL;
-	unsigned long w;
+	unsigned long addr = (unsigned long)xaddr;
 
-#ifndef MCPCIA_ONE_HAE_WINDOW
-	unsigned long msb;
-	msb = addr & ~MCPCIA_MEM_MASK;
-	set_hae(msb);
-#endif
-	addr = addr & MCPCIA_MEM_MASK;
+	if (!__mcpcia_is_mmio(addr))
+		addr = ((addr & 0xffff) << 5) + (addr & ~0xfffful) + 0x18;
 
-	w = __kernel_inswl(b, in_addr & 3);
-	hose = hose - MCPCIA_DENSE(4) + MCPCIA_SPARSE(4);
-	*(vuip) ((addr << 5) + hose + 0x08) = w;
+	return *(vuip)addr;
 }
 
-__EXTERN_INLINE u32 mcpcia_readl(unsigned long addr)
+__EXTERN_INLINE void mcpcia_iowrite32(u32 b, void __iomem *xaddr)
 {
-	return (*(vuip)addr) & 0xffffffff;
+	unsigned long addr = (unsigned long)xaddr;
+
+	if (!__mcpcia_is_mmio(addr))
+		addr = ((addr & 0xffff) << 5) + (addr & ~0xfffful) + 0x18;
+
+	*(vuip)addr = b;
 }
 
-__EXTERN_INLINE u64 mcpcia_readq(unsigned long addr)
+
+__EXTERN_INLINE void __iomem *mcpcia_ioportmap(unsigned long addr)
 {
-	return *(vulp)addr;
+	return (void __iomem *)(addr + MCPCIA_IO_BIAS);
 }
 
-__EXTERN_INLINE void mcpcia_writel(u32 b, unsigned long addr)
+__EXTERN_INLINE void __iomem *mcpcia_ioremap(unsigned long addr,
+					     unsigned long size)
 {
-	*(vuip)addr = b;
+	return (void __iomem *)(addr + MCPCIA_MEM_BIAS);
 }
 
-__EXTERN_INLINE void mcpcia_writeq(u64 b, unsigned long addr)
+__EXTERN_INLINE int mcpcia_is_ioaddr(unsigned long addr)
 {
-	*(vulp)addr = b;
+	return addr >= MCPCIA_SPARSE(0);
 }
 
-#undef vucp
-#undef vusp
-#undef vip
-#undef vuip
-#undef vulp
+__EXTERN_INLINE int mcpcia_is_mmio(const volatile void __iomem *xaddr)
+{
+	unsigned long addr = (unsigned long) xaddr;
+	return __mcpcia_is_mmio(addr);
+}
 
-#ifdef __WANT_IO_DEF
+#undef MCPCIA_FROB_MMIO
 
-#define __inb(p)		mcpcia_inb((unsigned long)(p))
-#define __inw(p)		mcpcia_inw((unsigned long)(p))
-#define __inl(p)		mcpcia_inl((unsigned long)(p))
-#define __outb(x,p)		mcpcia_outb((x),(unsigned long)(p))
-#define __outw(x,p)		mcpcia_outw((x),(unsigned long)(p))
-#define __outl(x,p)		mcpcia_outl((x),(unsigned long)(p))
-#define __readb(a)		mcpcia_readb((unsigned long)(a))
-#define __readw(a)		mcpcia_readw((unsigned long)(a))
-#define __readl(a)		mcpcia_readl((unsigned long)(a))
-#define __readq(a)		mcpcia_readq((unsigned long)(a))
-#define __writeb(x,a)		mcpcia_writeb((x),(unsigned long)(a))
-#define __writew(x,a)		mcpcia_writew((x),(unsigned long)(a))
-#define __writel(x,a)		mcpcia_writel((x),(unsigned long)(a))
-#define __writeq(x,a)		mcpcia_writeq((x),(unsigned long)(a))
-#define __ioremap(a,s)		mcpcia_ioremap((unsigned long)(a),(s))
-#define __iounmap(a)		mcpcia_iounmap((unsigned long)(a))
-#define __is_ioaddr(a)		mcpcia_is_ioaddr((unsigned long)(a))
-
-#define __raw_readl(a)		__readl(a)
-#define __raw_readq(a)		__readq(a)
-#define __raw_writel(v,a)	__writel((v),(a))
-#define __raw_writeq(v,a)	__writeq((v),(a))
+#undef vip
+#undef vuip
 
-#endif /* __WANT_IO_DEF */
+#undef __IO_PREFIX
+#define __IO_PREFIX		mcpcia
+#define mcpcia_trivial_rw_bw	2
+#define mcpcia_trivial_rw_lq	1
+#define mcpcia_trivial_io_bw	0
+#define mcpcia_trivial_io_lq	0
+#define mcpcia_trivial_iounmap	1
+#include <asm/io_trivial.h>
 
 #ifdef __IO_EXTERN_INLINE
 #undef __EXTERN_INLINE
diff -Nru a/include/asm-alpha/core_polaris.h b/include/asm-alpha/core_polaris.h
--- a/include/asm-alpha/core_polaris.h	2004-10-18 14:56:27 -07:00
+++ b/include/asm-alpha/core_polaris.h	2004-10-18 14:56:27 -07:00
@@ -63,49 +63,6 @@
  * However, we will support only the BWX form.
  */
 
-#define vucp	volatile unsigned char *
-#define vusp	volatile unsigned short *
-#define vuip	volatile unsigned int  *
-#define vulp	volatile unsigned long  *
-
-__EXTERN_INLINE u8 polaris_inb(unsigned long addr)
-{
-	/* ??? I wish I could get rid of this.  But there's no ioremap
-	   equivalent for I/O space.  PCI I/O can be forced into the
-	   POLARIS I/O region, but that doesn't take care of legacy
-	   ISA crap.  */
-
-	return __kernel_ldbu(*(vucp)(addr + POLARIS_DENSE_IO_BASE));
-}
-
-__EXTERN_INLINE void polaris_outb(u8 b, unsigned long addr)
-{
-	__kernel_stb(b, *(vucp)(addr + POLARIS_DENSE_IO_BASE));
-	mb();
-}
-
-__EXTERN_INLINE u16 polaris_inw(unsigned long addr)
-{
-	return __kernel_ldwu(*(vusp)(addr + POLARIS_DENSE_IO_BASE));
-}
-
-__EXTERN_INLINE void polaris_outw(u16 b, unsigned long addr)
-{
-	__kernel_stw(b, *(vusp)(addr + POLARIS_DENSE_IO_BASE));
-	mb();
-}
-
-__EXTERN_INLINE u32 polaris_inl(unsigned long addr)
-{
-	return *(vuip)(addr + POLARIS_DENSE_IO_BASE);
-}
-
-__EXTERN_INLINE void polaris_outl(u32 b, unsigned long addr)
-{
-	*(vuip)(addr + POLARIS_DENSE_IO_BASE) = b;
-	mb();
-}
-
 /*
  * Memory functions.  Polaris allows all accesses (byte/word
  * as well as long/quad) to be done through dense space.
@@ -113,56 +70,15 @@
  * We will only support DENSE access via BWX insns.
  */
 
-__EXTERN_INLINE u8 polaris_readb(unsigned long addr)
-{
-	return __kernel_ldbu(*(vucp)addr);
-}
-
-__EXTERN_INLINE u16 polaris_readw(unsigned long addr)
+__EXTERN_INLINE void __iomem *polaris_ioportmap(unsigned long addr)
 {
-	return __kernel_ldwu(*(vusp)addr);
+	return (void __iomem *)(addr + POLARIS_DENSE_IO_BASE);
 }
 
-__EXTERN_INLINE u32 polaris_readl(unsigned long addr)
+__EXTERN_INLINE void __iomem *polaris_ioremap(unsigned long addr,
+					      unsigned long size)
 {
-	return (*(vuip)addr) & 0xffffffff;
-}
-
-__EXTERN_INLINE u64 polaris_readq(unsigned long addr)
-{
-	return *(vulp)addr;
-}
-
-__EXTERN_INLINE void polaris_writeb(u8 b, unsigned long addr)
-{
-	__kernel_stb(b, *(vucp)addr);
-}
-
-__EXTERN_INLINE void polaris_writew(u16 b, unsigned long addr)
-{
-	__kernel_stw(b, *(vusp)addr);
-}
-
-__EXTERN_INLINE void polaris_writel(u32 b, unsigned long addr)
-{
-	*(vuip)addr = b;
-}
-
-__EXTERN_INLINE void polaris_writeq(u64 b, unsigned long addr)
-{
-	*(vulp)addr = b;
-}
-
-__EXTERN_INLINE unsigned long polaris_ioremap(unsigned long addr,
-					      unsigned long size
-					      __attribute__((unused)))
-{
-	return addr + POLARIS_DENSE_MEM_BASE;
-}
-
-__EXTERN_INLINE void polaris_iounmap(unsigned long addr)
-{
-	return;
+	return (void __iomem *)(addr + POLARIS_DENSE_MEM_BASE);
 }
 
 __EXTERN_INLINE int polaris_is_ioaddr(unsigned long addr)
@@ -170,47 +86,19 @@
 	return addr >= POLARIS_SPARSE_MEM_BASE;
 }
 
-#undef vucp
-#undef vusp
-#undef vuip
-#undef vulp
-
-#ifdef __WANT_IO_DEF
-
-#define __inb(p)		polaris_inb((unsigned long)(p))
-#define __inw(p)		polaris_inw((unsigned long)(p))
-#define __inl(p)		polaris_inl((unsigned long)(p))
-#define __outb(x,p)		polaris_outb((x),(unsigned long)(p))
-#define __outw(x,p)		polaris_outw((x),(unsigned long)(p))
-#define __outl(x,p)		polaris_outl((x),(unsigned long)(p))
-#define __readb(a)		polaris_readb((unsigned long)(a))
-#define __readw(a)		polaris_readw((unsigned long)(a))
-#define __readl(a)		polaris_readl((unsigned long)(a))
-#define __readq(a)		polaris_readq((unsigned long)(a))
-#define __writeb(x,a)		polaris_writeb((x),(unsigned long)(a))
-#define __writew(x,a)		polaris_writew((x),(unsigned long)(a))
-#define __writel(x,a)		polaris_writel((x),(unsigned long)(a))
-#define __writeq(x,a)		polaris_writeq((x),(unsigned long)(a))
-#define __ioremap(a,s)		polaris_ioremap((unsigned long)(a),(s))
-#define __iounmap(a)		polaris_iounmap((unsigned long)(a))
-#define __is_ioaddr(a)		polaris_is_ioaddr((unsigned long)(a))
-
-#define inb(p)			__inb(p)
-#define inw(p)			__inw(p)
-#define inl(p)			__inl(p)
-#define outb(x,p)		__outb((x),(p))
-#define outw(x,p)		__outw((x),(p))
-#define outl(x,p)		__outl((x),(p))
-#define __raw_readb(a)		__readb(a)
-#define __raw_readw(a)		__readw(a)
-#define __raw_readl(a)		__readl(a)
-#define __raw_readq(a)		__readq(a)
-#define __raw_writeb(v,a)	__writeb((v),(a))
-#define __raw_writew(v,a)	__writew((v),(a))
-#define __raw_writel(v,a)	__writel((v),(a))
-#define __raw_writeq(v,a)	__writeq((v),(a))
+__EXTERN_INLINE int polaris_is_mmio(const volatile void __iomem *addr)
+{
+	return (unsigned long)addr < POLARIS_SPARSE_IO_BASE;
+}
 
-#endif /* __WANT_IO_DEF */
+#undef __IO_PREFIX
+#define __IO_PREFIX		polaris
+#define polaris_trivial_rw_bw	1
+#define polaris_trivial_rw_lq	1
+#define polaris_trivial_io_bw	1
+#define polaris_trivial_io_lq	1
+#define polaris_trivial_iounmap	1
+#include <asm/io_trivial.h>
 
 #ifdef __IO_EXTERN_INLINE
 #undef __EXTERN_INLINE
diff -Nru a/include/asm-alpha/core_t2.h b/include/asm-alpha/core_t2.h
--- a/include/asm-alpha/core_t2.h	2004-10-18 14:56:32 -07:00
+++ b/include/asm-alpha/core_t2.h	2004-10-18 14:56:32 -07:00
@@ -199,8 +199,8 @@
 
 struct el_t2_logout_header {
 	unsigned int	elfl_size;	/* size in bytes of logout area. */
-	int		elfl_sbz1:31;	/* Should be zero. */
-	char		elfl_retry:1;	/* Retry flag. */
+	unsigned int	elfl_sbz1:31;	/* Should be zero. */
+	unsigned int	elfl_retry:1;	/* Retry flag. */
 	unsigned int	elfl_procoffset; /* Processor-specific offset. */
 	unsigned int	elfl_sysoffset;	 /* Offset of system-specific. */
 	unsigned int	elfl_error_type;	/* PAL error type code. */
@@ -357,13 +357,13 @@
 #define vip	volatile int *
 #define vuip	volatile unsigned int *
 
-__EXTERN_INLINE u8 t2_inb(unsigned long addr)
+static inline u8 t2_inb(unsigned long addr)
 {
 	long result = *(vip) ((addr << 5) + T2_IO + 0x00);
 	return __kernel_extbl(result, addr & 3);
 }
 
-__EXTERN_INLINE void t2_outb(u8 b, unsigned long addr)
+static inline void t2_outb(u8 b, unsigned long addr)
 {
 	unsigned long w;
 
@@ -372,13 +372,13 @@
 	mb();
 }
 
-__EXTERN_INLINE u16 t2_inw(unsigned long addr)
+static inline u16 t2_inw(unsigned long addr)
 {
 	long result = *(vip) ((addr << 5) + T2_IO + 0x08);
 	return __kernel_extwl(result, addr & 3);
 }
 
-__EXTERN_INLINE void t2_outw(u16 b, unsigned long addr)
+static inline void t2_outw(u16 b, unsigned long addr)
 {
 	unsigned long w;
 
@@ -387,12 +387,12 @@
 	mb();
 }
 
-__EXTERN_INLINE u32 t2_inl(unsigned long addr)
+static inline u32 t2_inl(unsigned long addr)
 {
 	return *(vuip) ((addr << 5) + T2_IO + 0x18);
 }
 
-__EXTERN_INLINE void t2_outl(u32 b, unsigned long addr)
+static inline void t2_outl(u32 b, unsigned long addr)
 {
 	*(vuip) ((addr << 5) + T2_IO + 0x18) = b;
 	mb();
@@ -438,8 +438,9 @@
 
 static spinlock_t t2_hae_lock = SPIN_LOCK_UNLOCKED;
 
-__EXTERN_INLINE u8 t2_readb(unsigned long addr)
+__EXTERN_INLINE u8 t2_readb(const volatile void __iomem *xaddr)
 {
+	unsigned long addr = (unsigned long) xaddr;
 	unsigned long result, msb;
 	unsigned long flags;
 	spin_lock_irqsave(&t2_hae_lock, flags);
@@ -451,8 +452,9 @@
 	return __kernel_extbl(result, addr & 3);
 }
 
-__EXTERN_INLINE u16 t2_readw(unsigned long addr)
+__EXTERN_INLINE u16 t2_readw(const volatile void __iomem *xaddr)
 {
+	unsigned long addr = (unsigned long) xaddr;
 	unsigned long result, msb;
 	unsigned long flags;
 	spin_lock_irqsave(&t2_hae_lock, flags);
@@ -468,8 +470,9 @@
  * On SABLE with T2, we must use SPARSE memory even for 32-bit access,
  * because we cannot access all of DENSE without changing its HAE.
  */
-__EXTERN_INLINE u32 t2_readl(unsigned long addr)
+__EXTERN_INLINE u32 t2_readl(const volatile void __iomem *xaddr)
 {
+	unsigned long addr = (unsigned long) xaddr;
 	unsigned long result, msb;
 	unsigned long flags;
 	spin_lock_irqsave(&t2_hae_lock, flags);
@@ -481,8 +484,9 @@
 	return result & 0xffffffffUL;
 }
 
-__EXTERN_INLINE u64 t2_readq(unsigned long addr)
+__EXTERN_INLINE u64 t2_readq(const volatile void __iomem *xaddr)
 {
+	unsigned long addr = (unsigned long) xaddr;
 	unsigned long r0, r1, work, msb;
 	unsigned long flags;
 	spin_lock_irqsave(&t2_hae_lock, flags);
@@ -496,8 +500,9 @@
 	return r1 << 32 | r0;
 }
 
-__EXTERN_INLINE void t2_writeb(u8 b, unsigned long addr)
+__EXTERN_INLINE void t2_writeb(u8 b, volatile void __iomem *xaddr)
 {
+	unsigned long addr = (unsigned long) xaddr;
 	unsigned long msb, w;
 	unsigned long flags;
 	spin_lock_irqsave(&t2_hae_lock, flags);
@@ -509,8 +514,9 @@
 	spin_unlock_irqrestore(&t2_hae_lock, flags);
 }
 
-__EXTERN_INLINE void t2_writew(u16 b, unsigned long addr)
+__EXTERN_INLINE void t2_writew(u16 b, volatile void __iomem *xaddr)
 {
+	unsigned long addr = (unsigned long) xaddr;
 	unsigned long msb, w;
 	unsigned long flags;
 	spin_lock_irqsave(&t2_hae_lock, flags);
@@ -526,8 +532,9 @@
  * On SABLE with T2, we must use SPARSE memory even for 32-bit access,
  * because we cannot access all of DENSE without changing its HAE.
  */
-__EXTERN_INLINE void t2_writel(u32 b, unsigned long addr)
+__EXTERN_INLINE void t2_writel(u32 b, volatile void __iomem *xaddr)
 {
+	unsigned long addr = (unsigned long) xaddr;
 	unsigned long msb;
 	unsigned long flags;
 	spin_lock_irqsave(&t2_hae_lock, flags);
@@ -538,8 +545,9 @@
 	spin_unlock_irqrestore(&t2_hae_lock, flags);
 }
 
-__EXTERN_INLINE void t2_writeq(u64 b, unsigned long addr)
+__EXTERN_INLINE void t2_writeq(u64 b, volatile void __iomem *xaddr)
 {
+	unsigned long addr = (unsigned long) xaddr;
 	unsigned long msb, work;
 	unsigned long flags;
 	spin_lock_irqsave(&t2_hae_lock, flags);
@@ -552,16 +560,15 @@
 	spin_unlock_irqrestore(&t2_hae_lock, flags);
 }
 
-__EXTERN_INLINE unsigned long t2_ioremap(unsigned long addr, 
-					 unsigned long size
-					 __attribute__((unused)))
+__EXTERN_INLINE void __iomem *t2_ioportmap(unsigned long addr)
 {
-	return addr;
+	return (void __iomem *)(addr + T2_IO);
 }
 
-__EXTERN_INLINE void t2_iounmap(unsigned long addr)
+__EXTERN_INLINE void __iomem *t2_ioremap(unsigned long addr, 
+					 unsigned long size)
 {
-	return;
+	return (void __iomem *)(addr + T2_DENSE_MEM);
 }
 
 __EXTERN_INLINE int t2_is_ioaddr(unsigned long addr)
@@ -569,30 +576,47 @@
 	return (long)addr >= 0;
 }
 
-#undef vip
-#undef vuip
+__EXTERN_INLINE int t2_is_mmio(const volatile void __iomem *addr)
+{
+	return (unsigned long)addr >= T2_DENSE_MEM;
+}
 
-#ifdef __WANT_IO_DEF
+/* New-style ioread interface.  The mmio routines are so ugly for T2 that
+   it doesn't make sense to merge the pio and mmio routines.  */
 
-#define __inb(p)		t2_inb((unsigned long)(p))
-#define __inw(p)		t2_inw((unsigned long)(p))
-#define __inl(p)		t2_inl((unsigned long)(p))
-#define __outb(x,p)		t2_outb((x),(unsigned long)(p))
-#define __outw(x,p)		t2_outw((x),(unsigned long)(p))
-#define __outl(x,p)		t2_outl((x),(unsigned long)(p))
-#define __readb(a)		t2_readb((unsigned long)(a))
-#define __readw(a)		t2_readw((unsigned long)(a))
-#define __readl(a)		t2_readl((unsigned long)(a))
-#define __readq(a)		t2_readq((unsigned long)(a))
-#define __writeb(x,a)		t2_writeb((x),(unsigned long)(a))
-#define __writew(x,a)		t2_writew((x),(unsigned long)(a))
-#define __writel(x,a)		t2_writel((x),(unsigned long)(a))
-#define __writeq(x,a)		t2_writeq((x),(unsigned long)(a))
-#define __ioremap(a,s)		t2_ioremap((unsigned long)(a),(s))
-#define __iounmap(a)		t2_iounmap((unsigned long)(a))
-#define __is_ioaddr(a)		t2_is_ioaddr((unsigned long)(a))
+#define IOPORT(OS, NS)							\
+__EXTERN_INLINE unsigned int t2_ioread##NS(void __iomem *xaddr)		\
+{									\
+	if (t2_is_mmio(xaddr))						\
+		return t2_read##OS(xaddr - T2_DENSE_MEM);		\
+	else								\
+		return t2_in##OS((unsigned long)xaddr - T2_IO);		\
+}									\
+__EXTERN_INLINE void t2_iowrite##NS(u##NS b, void __iomem *xaddr)	\
+{									\
+	if (t2_is_mmio(xaddr))						\
+		t2_write##OS(b, xaddr - T2_DENSE_MEM);			\
+	else								\
+		t2_out##OS(b, (unsigned long)xaddr - T2_IO);		\
+}
+
+IOPORT(b, 8)
+IOPORT(w, 16)
+IOPORT(l, 32)
+
+#undef IOPORT
+
+#undef vip
+#undef vuip
 
-#endif /* __WANT_IO_DEF */
+#undef __IO_PREFIX
+#define __IO_PREFIX		t2
+#define t2_trivial_rw_bw	0
+#define t2_trivial_rw_lq	0
+#define t2_trivial_io_bw	0
+#define t2_trivial_io_lq	0
+#define t2_trivial_iounmap	1
+#include <asm/io_trivial.h>
 
 #ifdef __IO_EXTERN_INLINE
 #undef __EXTERN_INLINE
diff -Nru a/include/asm-alpha/core_titan.h b/include/asm-alpha/core_titan.h
--- a/include/asm-alpha/core_titan.h	2004-10-18 14:57:03 -07:00
+++ b/include/asm-alpha/core_titan.h	2004-10-18 14:57:03 -07:00
@@ -377,149 +377,33 @@
  * can only use linear accesses to get at PCI/AGP memory and I/O spaces.
  */
 
-#define vucp	volatile unsigned char *
-#define vusp	volatile unsigned short *
-#define vuip	volatile unsigned int *
-#define vulp	volatile unsigned long *
-
-__EXTERN_INLINE u8 titan_inb(unsigned long addr)
-{
-	/* ??? I wish I could get rid of this.  But there's no ioremap
-	   equivalent for I/O space.  PCI I/O can be forced into the
-	   correct hose's I/O region, but that doesn't take care of
-	   legacy ISA crap.  */
-
-	addr += TITAN_IO_BIAS;
-	return __kernel_ldbu(*(vucp)addr);
-}
-
-__EXTERN_INLINE void titan_outb(u8 b, unsigned long addr)
-{
-	addr += TITAN_IO_BIAS;
-	__kernel_stb(b, *(vucp)addr);
-	mb();
-}
-
-__EXTERN_INLINE u16 titan_inw(unsigned long addr)
-{
-	addr += TITAN_IO_BIAS;
-	return __kernel_ldwu(*(vusp)addr);
-}
-
-__EXTERN_INLINE void titan_outw(u16 b, unsigned long addr)
-{
-	addr += TITAN_IO_BIAS;
-	__kernel_stw(b, *(vusp)addr);
-	mb();
-}
-
-__EXTERN_INLINE u32 titan_inl(unsigned long addr)
-{
-	addr += TITAN_IO_BIAS;
-	return *(vuip)addr;
-}
-
-__EXTERN_INLINE void titan_outl(u32 b, unsigned long addr)
-{
-	addr += TITAN_IO_BIAS;
-	*(vuip)addr = b;
-	mb();
-}
-
 /*
  * Memory functions.  all accesses are done through linear space.
  */
 
-extern unsigned long titan_ioremap(unsigned long addr, unsigned long size);
-extern void titan_iounmap(unsigned long addr);
-
-__EXTERN_INLINE int titan_is_ioaddr(unsigned long addr)
+__EXTERN_INLINE void __iomem *titan_ioportmap(unsigned long addr)
 {
-	return addr >= TITAN_BASE;
+	return (void __iomem *)(addr + TITAN_IO_BIAS);
 }
 
-__EXTERN_INLINE u8 titan_readb(unsigned long addr)
-{
-	return __kernel_ldbu(*(vucp)addr);
-}
+extern void __iomem *titan_ioremap(unsigned long addr, unsigned long size);
+extern void titan_iounmap(volatile void __iomem *addr);
 
-__EXTERN_INLINE u16 titan_readw(unsigned long addr)
-{
-	return __kernel_ldwu(*(vusp)addr);
-}
-
-__EXTERN_INLINE u32 titan_readl(unsigned long addr)
-{
-	return (*(vuip)addr) & 0xffffffff;
-}
-
-__EXTERN_INLINE u64 titan_readq(unsigned long addr)
-{
-	return *(vulp)addr;
-}
-
-__EXTERN_INLINE void titan_writeb(u8 b, unsigned long addr)
-{
-	__kernel_stb(b, *(vucp)addr);
-}
-
-__EXTERN_INLINE void titan_writew(u16 b, unsigned long addr)
-{
-	__kernel_stw(b, *(vusp)addr);
-}
-
-__EXTERN_INLINE void titan_writel(u32 b, unsigned long addr)
-{
-	*(vuip)addr = b;
-}
-
-__EXTERN_INLINE void titan_writeq(u64 b, unsigned long addr)
+__EXTERN_INLINE int titan_is_ioaddr(unsigned long addr)
 {
-	*(vulp)addr = b;
+	return addr >= TITAN_BASE;
 }
 
-#undef vucp
-#undef vusp
-#undef vuip
-#undef vulp
-
-#ifdef __WANT_IO_DEF
-
-#define __inb(p)		titan_inb((unsigned long)(p))
-#define __inw(p)		titan_inw((unsigned long)(p))
-#define __inl(p)		titan_inl((unsigned long)(p))
-#define __outb(x,p)		titan_outb((x),(unsigned long)(p))
-#define __outw(x,p)		titan_outw((x),(unsigned long)(p))
-#define __outl(x,p)		titan_outl((x),(unsigned long)(p))
-#define __readb(a)		titan_readb((unsigned long)(a))
-#define __readw(a)		titan_readw((unsigned long)(a))
-#define __readl(a)		titan_readl((unsigned long)(a))
-#define __readq(a)		titan_readq((unsigned long)(a))
-#define __writeb(x,a)		titan_writeb((x),(unsigned long)(a))
-#define __writew(x,a)		titan_writew((x),(unsigned long)(a))
-#define __writel(x,a)		titan_writel((x),(unsigned long)(a))
-#define __writeq(x,a)		titan_writeq((x),(unsigned long)(a))
-#define __ioremap(a,s)		titan_ioremap((unsigned long)(a),(s))
-#define __iounmap(a)		titan_iounmap((unsigned long)(a))
-#define __is_ioaddr(a)		titan_is_ioaddr((unsigned long)(a))
-
-#define inb(port) 		__inb((port))
-#define inw(port) 		__inw((port))
-#define inl(port) 		__inl((port))
-#define outb(v, port) 		__outb((v),(port))
-#define outw(v, port) 		__outw((v),(port))
-#define outl(v, port) 		__outl((v),(port))
-
-#define __raw_readb(a)		__readb((unsigned long)(a))
-#define __raw_readw(a)		__readw((unsigned long)(a))
-#define __raw_readl(a)		__readl((unsigned long)(a))
-#define __raw_readq(a)		__readq((unsigned long)(a))
-#define __raw_writeb(v,a)	__writeb((v),(unsigned long)(a))
-#define __raw_writew(v,a)	__writew((v),(unsigned long)(a))
-#define __raw_writel(v,a)	__writel((v),(unsigned long)(a))
-#define __raw_writeq(v,a)	__writeq((v),(unsigned long)(a))
+extern int titan_is_mmio(const volatile void __iomem *addr);
 
-#endif /* __WANT_IO_DEF */
+#undef __IO_PREFIX
+#define __IO_PREFIX		titan
+#define titan_trivial_rw_bw	1
+#define titan_trivial_rw_lq	1
+#define titan_trivial_io_bw	1
+#define titan_trivial_io_lq	1
+#define titan_trivial_iounmap	0
+#include <asm/io_trivial.h>
 
 #ifdef __IO_EXTERN_INLINE
 #undef __EXTERN_INLINE
diff -Nru a/include/asm-alpha/core_tsunami.h b/include/asm-alpha/core_tsunami.h
--- a/include/asm-alpha/core_tsunami.h	2004-10-18 14:56:48 -07:00
+++ b/include/asm-alpha/core_tsunami.h	2004-10-18 14:56:48 -07:00
@@ -299,69 +299,19 @@
  * can only use linear accesses to get at PCI memory and I/O spaces.
  */
 
-#define vucp	volatile unsigned char *
-#define vusp	volatile unsigned short *
-#define vuip	volatile unsigned int *
-#define vulp	volatile unsigned long *
-
-__EXTERN_INLINE u8 tsunami_inb(unsigned long addr)
-{
-	/* ??? I wish I could get rid of this.  But there's no ioremap
-	   equivalent for I/O space.  PCI I/O can be forced into the
-	   correct hose's I/O region, but that doesn't take care of
-	   legacy ISA crap.  */
-
-	addr += TSUNAMI_IO_BIAS;
-	return __kernel_ldbu(*(vucp)addr);
-}
-
-__EXTERN_INLINE void tsunami_outb(u8 b, unsigned long addr)
-{
-	addr += TSUNAMI_IO_BIAS;
-	__kernel_stb(b, *(vucp)addr);
-	mb();
-}
-
-__EXTERN_INLINE u16 tsunami_inw(unsigned long addr)
-{
-	addr += TSUNAMI_IO_BIAS;
-	return __kernel_ldwu(*(vusp)addr);
-}
-
-__EXTERN_INLINE void tsunami_outw(u16 b, unsigned long addr)
-{
-	addr += TSUNAMI_IO_BIAS;
-	__kernel_stw(b, *(vusp)addr);
-	mb();
-}
-
-__EXTERN_INLINE u32 tsunami_inl(unsigned long addr)
-{
-	addr += TSUNAMI_IO_BIAS;
-	return *(vuip)addr;
-}
-
-__EXTERN_INLINE void tsunami_outl(u32 b, unsigned long addr)
-{
-	addr += TSUNAMI_IO_BIAS;
-	*(vuip)addr = b;
-	mb();
-}
-
 /*
  * Memory functions.  all accesses are done through linear space.
  */
 
-__EXTERN_INLINE unsigned long tsunami_ioremap(unsigned long addr, 
-					      unsigned long size
-					      __attribute__((unused)))
+__EXTERN_INLINE void __iomem *tsunami_ioportmap(unsigned long addr)
 {
-	return addr + TSUNAMI_MEM_BIAS;
+	return (void __iomem *)(addr + TSUNAMI_IO_BIAS);
 }
 
-__EXTERN_INLINE void tsunami_iounmap(unsigned long addr)
+__EXTERN_INLINE void __iomem *tsunami_ioremap(unsigned long addr, 
+					      unsigned long size)
 {
-	return;
+	return (void __iomem *)(addr + TSUNAMI_MEM_BIAS);
 }
 
 __EXTERN_INLINE int tsunami_is_ioaddr(unsigned long addr)
@@ -369,87 +319,20 @@
 	return addr >= TSUNAMI_BASE;
 }
 
-__EXTERN_INLINE u8 tsunami_readb(unsigned long addr)
-{
-	return __kernel_ldbu(*(vucp)addr);
-}
-
-__EXTERN_INLINE u16 tsunami_readw(unsigned long addr)
+__EXTERN_INLINE int tsunami_is_mmio(const volatile void __iomem *xaddr)
 {
-	return __kernel_ldwu(*(vusp)addr);
+	unsigned long addr = (unsigned long) xaddr;
+	return (addr & 0x100000000UL) == 0;
 }
 
-__EXTERN_INLINE u32 tsunami_readl(unsigned long addr)
-{
-	return *(vuip)addr;
-}
-
-__EXTERN_INLINE u64 tsunami_readq(unsigned long addr)
-{
-	return *(vulp)addr;
-}
-
-__EXTERN_INLINE void tsunami_writeb(u8 b, unsigned long addr)
-{
-	__kernel_stb(b, *(vucp)addr);
-}
-
-__EXTERN_INLINE void tsunami_writew(u16 b, unsigned long addr)
-{
-	__kernel_stw(b, *(vusp)addr);
-}
-
-__EXTERN_INLINE void tsunami_writel(u32 b, unsigned long addr)
-{
-	*(vuip)addr = b;
-}
-
-__EXTERN_INLINE void tsunami_writeq(u64 b, unsigned long addr)
-{
-	*(vulp)addr = b;
-}
-
-#undef vucp
-#undef vusp
-#undef vuip
-#undef vulp
-
-#ifdef __WANT_IO_DEF
-
-#define __inb(p)		tsunami_inb((unsigned long)(p))
-#define __inw(p)		tsunami_inw((unsigned long)(p))
-#define __inl(p)		tsunami_inl((unsigned long)(p))
-#define __outb(x,p)		tsunami_outb((x),(unsigned long)(p))
-#define __outw(x,p)		tsunami_outw((x),(unsigned long)(p))
-#define __outl(x,p)		tsunami_outl((x),(unsigned long)(p))
-#define __readb(a)		tsunami_readb((unsigned long)(a))
-#define __readw(a)		tsunami_readw((unsigned long)(a))
-#define __readl(a)		tsunami_readl((unsigned long)(a))
-#define __readq(a)		tsunami_readq((unsigned long)(a))
-#define __writeb(x,a)		tsunami_writeb((x),(unsigned long)(a))
-#define __writew(x,a)		tsunami_writew((x),(unsigned long)(a))
-#define __writel(x,a)		tsunami_writel((x),(unsigned long)(a))
-#define __writeq(x,a)		tsunami_writeq((x),(unsigned long)(a))
-#define __ioremap(a,s)		tsunami_ioremap((unsigned long)(a),(s))
-#define __iounmap(a)		tsunami_iounmap((unsigned long)(a))
-#define __is_ioaddr(a)		tsunami_is_ioaddr((unsigned long)(a))
-
-#define inb(p)			__inb(p)
-#define inw(p)			__inw(p)
-#define inl(p)			__inl(p)
-#define outb(x,p)		__outb((x),(p))
-#define outw(x,p)		__outw((x),(p))
-#define outl(x,p)		__outl((x),(p))
-#define __raw_readb(a)		__readb(a)
-#define __raw_readw(a)		__readw(a)
-#define __raw_readl(a)		__readl(a)
-#define __raw_readq(a)		__readq(a)
-#define __raw_writeb(v,a)	__writeb((v),(a))
-#define __raw_writew(v,a)	__writew((v),(a))
-#define __raw_writel(v,a)	__writel((v),(a))
-#define __raw_writeq(v,a)	__writeq((v),(a))
-
-#endif /* __WANT_IO_DEF */
+#undef __IO_PREFIX
+#define __IO_PREFIX		tsunami
+#define tsunami_trivial_rw_bw	1
+#define tsunami_trivial_rw_lq	1
+#define tsunami_trivial_io_bw	1
+#define tsunami_trivial_io_lq	1
+#define tsunami_trivial_iounmap	1
+#include <asm/io_trivial.h>
 
 #ifdef __IO_EXTERN_INLINE
 #undef __EXTERN_INLINE
diff -Nru a/include/asm-alpha/core_wildfire.h b/include/asm-alpha/core_wildfire.h
--- a/include/asm-alpha/core_wildfire.h	2004-10-18 14:55:55 -07:00
+++ b/include/asm-alpha/core_wildfire.h	2004-10-18 14:55:55 -07:00
@@ -273,69 +273,19 @@
 #define __IO_EXTERN_INLINE
 #endif
 
-#define vucp	volatile unsigned char *
-#define vusp	volatile unsigned short *
-#define vuip	volatile unsigned int *
-#define vulp	volatile unsigned long *
-
-__EXTERN_INLINE u8 wildfire_inb(unsigned long addr)
-{
-	/* ??? I wish I could get rid of this.  But there's no ioremap
-	   equivalent for I/O space.  PCI I/O can be forced into the
-	   correct hose's I/O region, but that doesn't take care of
-	   legacy ISA crap.  */
-
-	addr += WILDFIRE_IO_BIAS;
-	return __kernel_ldbu(*(vucp)addr);
-}
-
-__EXTERN_INLINE void wildfire_outb(u8 b, unsigned long addr)
-{
-	addr += WILDFIRE_IO_BIAS;
-	__kernel_stb(b, *(vucp)addr);
-	mb();
-}
-
-__EXTERN_INLINE u16 wildfire_inw(unsigned long addr)
-{
-	addr += WILDFIRE_IO_BIAS;
-	return __kernel_ldwu(*(vusp)addr);
-}
-
-__EXTERN_INLINE void wildfire_outw(u16 b, unsigned long addr)
-{
-	addr += WILDFIRE_IO_BIAS;
-	__kernel_stw(b, *(vusp)addr);
-	mb();
-}
-
-__EXTERN_INLINE u32 wildfire_inl(unsigned long addr)
-{
-	addr += WILDFIRE_IO_BIAS;
-	return *(vuip)addr;
-}
-
-__EXTERN_INLINE void wildfire_outl(u32 b, unsigned long addr)
-{
-	addr += WILDFIRE_IO_BIAS;
-	*(vuip)addr = b;
-	mb();
-}
-
 /*
  * Memory functions.  all accesses are done through linear space.
  */
 
-__EXTERN_INLINE unsigned long wildfire_ioremap(unsigned long addr, 
-					       unsigned long size
-					       __attribute__((unused)))
+__EXTERN_INLINE void __iomem *wildfire_ioportmap(unsigned long addr)
 {
-	return addr + WILDFIRE_MEM_BIAS;
+	return (void __iomem *)(addr + WILDFIRE_IO_BIAS);
 }
 
-__EXTERN_INLINE void wildfire_iounmap(unsigned long addr)
+__EXTERN_INLINE void __iomem *wildfire_ioremap(unsigned long addr, 
+					       unsigned long size)
 {
-	return;
+	return (void __iomem *)(addr + WILDFIRE_MEM_BIAS);
 }
 
 __EXTERN_INLINE int wildfire_is_ioaddr(unsigned long addr)
@@ -343,87 +293,20 @@
 	return addr >= WILDFIRE_BASE;
 }
 
-__EXTERN_INLINE u8 wildfire_readb(unsigned long addr)
-{
-	return __kernel_ldbu(*(vucp)addr);
-}
-
-__EXTERN_INLINE u16 wildfire_readw(unsigned long addr)
+__EXTERN_INLINE int wildfire_is_mmio(const volatile void __iomem *xaddr)
 {
-	return __kernel_ldwu(*(vusp)addr);
+	unsigned long addr = (unsigned long)addr;
+	return (addr & 0x100000000UL) == 0;
 }
 
-__EXTERN_INLINE u32 wildfire_readl(unsigned long addr)
-{
-	return (*(vuip)addr) & 0xffffffff;
-}
-
-__EXTERN_INLINE u64 wildfire_readq(unsigned long addr)
-{
-	return *(vulp)addr;
-}
-
-__EXTERN_INLINE void wildfire_writeb(u8 b, unsigned long addr)
-{
-	__kernel_stb(b, *(vucp)addr);
-}
-
-__EXTERN_INLINE void wildfire_writew(u16 b, unsigned long addr)
-{
-	__kernel_stw(b, *(vusp)addr);
-}
-
-__EXTERN_INLINE void wildfire_writel(u32 b, unsigned long addr)
-{
-	*(vuip)addr = b;
-}
-
-__EXTERN_INLINE void wildfire_writeq(u64 b, unsigned long addr)
-{
-	*(vulp)addr = b;
-}
-
-#undef vucp
-#undef vusp
-#undef vuip
-#undef vulp
-
-#ifdef __WANT_IO_DEF
-
-#define __inb(p)		wildfire_inb((unsigned long)(p))
-#define __inw(p)		wildfire_inw((unsigned long)(p))
-#define __inl(p)		wildfire_inl((unsigned long)(p))
-#define __outb(x,p)		wildfire_outb((x),(unsigned long)(p))
-#define __outw(x,p)		wildfire_outw((x),(unsigned long)(p))
-#define __outl(x,p)		wildfire_outl((x),(unsigned long)(p))
-#define __readb(a)		wildfire_readb((unsigned long)(a))
-#define __readw(a)		wildfire_readw((unsigned long)(a))
-#define __readl(a)		wildfire_readl((unsigned long)(a))
-#define __readq(a)		wildfire_readq((unsigned long)(a))
-#define __writeb(x,a)		wildfire_writeb((x),(unsigned long)(a))
-#define __writew(x,a)		wildfire_writew((x),(unsigned long)(a))
-#define __writel(x,a)		wildfire_writel((x),(unsigned long)(a))
-#define __writeq(x,a)		wildfire_writeq((x),(unsigned long)(a))
-#define __ioremap(a,s)		wildfire_ioremap((unsigned long)(a),(s))
-#define __iounmap(a)		wildfire_iounmap((unsigned long)(a))
-#define __is_ioaddr(a)		wildfire_is_ioaddr((unsigned long)(a))
-
-#define inb(p)			__inb(p)
-#define inw(p)			__inw(p)
-#define inl(p)			__inl(p)
-#define outb(x,p)		__outb((x),(p))
-#define outw(x,p)		__outw((x),(p))
-#define outl(x,p)		__outl((x),(p))
-#define __raw_readb(a)		__readb(a)
-#define __raw_readw(a)		__readw(a)
-#define __raw_readl(a)		__readl(a)
-#define __raw_readq(a)		__readq(a)
-#define __raw_writeb(v,a)	__writeb((v),(a))
-#define __raw_writew(v,a)	__writew((v),(a))
-#define __raw_writel(v,a)	__writel((v),(a))
-#define __raw_writeq(v,a)	__writeq((v),(a))
-
-#endif /* __WANT_IO_DEF */
+#undef __IO_PREFIX
+#define __IO_PREFIX			wildfire
+#define wildfire_trivial_rw_bw		1
+#define wildfire_trivial_rw_lq		1
+#define wildfire_trivial_io_bw		1
+#define wildfire_trivial_io_lq		1
+#define wildfire_trivial_iounmap	1
+#include <asm/io_trivial.h>
 
 #ifdef __IO_EXTERN_INLINE
 #undef __EXTERN_INLINE
diff -Nru a/include/asm-alpha/dma-mapping.h b/include/asm-alpha/dma-mapping.h
--- a/include/asm-alpha/dma-mapping.h	2004-10-18 14:56:28 -07:00
+++ b/include/asm-alpha/dma-mapping.h	2004-10-18 14:56:28 -07:00
@@ -1 +1,63 @@
-#include <asm-generic/dma-mapping.h>
+#ifndef _ALPHA_DMA_MAPPING_H
+#define _ALPHA_DMA_MAPPING_H
+
+#include <linux/config.h>
+
+#ifdef CONFIG_PCI
+
+#include <linux/pci.h>
+
+#define dma_map_single(dev, va, size, dir)		\
+		pci_map_single(alpha_gendev_to_pci(dev), va, size, dir)
+#define dma_unmap_single(dev, addr, size, dir)		\
+		pci_unmap_single(alpha_gendev_to_pci(dev), addr, size, dir)
+#define dma_alloc_coherent(dev, size, addr, gfp)	\
+		pci_alloc_consistent(alpha_gendev_to_pci(dev), size, addr)
+#define dma_free_coherent(dev, size, va, addr)		\
+		pci_free_consistent(alpha_gendev_to_pci(dev), size, va, addr)
+#define dma_map_page(dev, page, off, size, dir)		\
+		pci_map_single(alpha_gendev_to_pci(dev), page, off, size, dir)
+#define dma_unmap_page(dev, addr, size, dir)		\
+		pci_unmap_page(alpha_gendev_to_pci(dev), addr, size, dir)
+#define dma_map_sg(dev, sg, nents, dir)			\
+		pci_map_sg(alpha_gendev_to_pci(dev), sg, nents, dir)
+#define dma_unmap_sg(dev, sg, nents, dir)		\
+		pci_unmap_sg(alpha_gendev_to_pci(dev), sg, nents, dir)
+#define dma_supported(dev, mask)			\
+		pci_dma_supported(alpha_gendev_to_pci(dev), mask)
+
+#else	/* no PCI - no IOMMU. */
+
+void *dma_alloc_coherent(struct device *dev, size_t size,
+			 dma_addr_t *dma_handle, int gfp);
+int dma_map_sg(struct device *dev, struct scatterlist *sg, int nents,
+	       enum dma_data_direction direction);
+
+#define dma_free_coherent(dev, size, va, addr)		\
+		free_pages((unsigned long)va, get_order(size))
+#define dma_supported(dev, mask)		(mask < 0x00ffffffUL ? 0 : 1)
+#define dma_map_single(dev, va, size, dir)	virt_to_phys(va)
+#define dma_map_page(dev, page, off, size, dir)	(page_to_pa(page) + off)
+
+#define dma_unmap_single(dev, addr, size, dir)	do { } while (0)
+#define dma_unmap_page(dev, addr, size, dir)	do { } while (0)
+#define dma_unmap_sg(dev, sg, nents, dir)	do { } while (0)
+
+#endif	/* !CONFIG_PCI */
+
+#define dma_alloc_noncoherent(d, s, h, f)	dma_alloc_coherent(d, s, h, f)
+#define dma_free_noncoherent(d, s, v, h)	dma_free_coherent(d, s, v, h)
+#define dma_is_consistent(dev)			(1)
+
+int dma_set_mask(struct device *dev, u64 mask);
+
+#define dma_sync_single_for_cpu(dev, addr, size, dir)	  do { } while (0)
+#define dma_sync_single_for_device(dev, addr, size, dir)  do { } while (0)
+#define dma_sync_single_range(dev, addr, off, size, dir)  do { } while (0)
+#define dma_sync_sg_for_cpu(dev, sg, nents, dir)	  do { } while (0)
+#define dma_sync_sg_for_device(dev, sg, nents, dir)	  do { } while (0)
+#define dma_cache_sync(va, size, dir)			  do { } while (0)
+
+#define dma_get_cache_alignment()			  L1_CACHE_BYTES
+
+#endif	/* _ALPHA_DMA_MAPPING_H */
diff -Nru a/include/asm-alpha/hardirq.h b/include/asm-alpha/hardirq.h
--- a/include/asm-alpha/hardirq.h	2004-10-18 14:56:33 -07:00
+++ b/include/asm-alpha/hardirq.h	2004-10-18 14:56:33 -07:00
@@ -39,20 +39,6 @@
 #define SOFTIRQ_SHIFT	(PREEMPT_SHIFT + PREEMPT_BITS)
 #define HARDIRQ_SHIFT	(SOFTIRQ_SHIFT + SOFTIRQ_BITS)
 
-#define __MASK(x)	((1UL << (x))-1)
-
-#define PREEMPT_MASK	(__MASK(PREEMPT_BITS) << PREEMPT_SHIFT)
-#define HARDIRQ_MASK	(__MASK(HARDIRQ_BITS) << HARDIRQ_SHIFT)
-#define SOFTIRQ_MASK	(__MASK(SOFTIRQ_BITS) << SOFTIRQ_SHIFT)
-
-#define hardirq_count()	(preempt_count() & HARDIRQ_MASK)
-#define softirq_count()	(preempt_count() & SOFTIRQ_MASK)
-#define irq_count()	(preempt_count() & (HARDIRQ_MASK | SOFTIRQ_MASK))
-
-#define PREEMPT_OFFSET	(1UL << PREEMPT_SHIFT)
-#define SOFTIRQ_OFFSET	(1UL << SOFTIRQ_SHIFT)
-#define HARDIRQ_OFFSET	(1UL << HARDIRQ_SHIFT)
-
 /*
  * The hardirq mask has to be large enough to have
  * space for potentially nestable IRQ sources in the system
@@ -64,28 +50,7 @@
 #error HARDIRQ_BITS is too low!
 #endif
 
-/*
- * Are we doing bottom half or hardware interrupt processing?
- * Are we in a softirq context? Interrupt context?
- */
-#define in_irq()		(hardirq_count())
-#define in_softirq()		(softirq_count())
-#define in_interrupt()		(irq_count())
-
-
-#define hardirq_trylock()	(!in_interrupt())
-#define hardirq_endlock()	do { } while (0)
-
 #define irq_enter()		(preempt_count() += HARDIRQ_OFFSET)
-
-
-#ifdef CONFIG_PREEMPT
-#define in_atomic()	(preempt_count() != kernel_locked())
-# define IRQ_EXIT_OFFSET (HARDIRQ_OFFSET-1)
-#else
-#define in_atomic()	(preempt_count() != 0)
-#define IRQ_EXIT_OFFSET HARDIRQ_OFFSET
-# endif
 #define irq_exit()						\
 do {								\
 		preempt_count() -= IRQ_EXIT_OFFSET;		\
@@ -94,11 +59,5 @@
 			do_softirq();				\
 		preempt_enable_no_resched();			\
 } while (0)
-
-#ifndef CONFIG_SMP
-# define synchronize_irq(irq)	barrier()
-#else
-  extern void synchronize_irq(unsigned int irq);
-#endif /* CONFIG_SMP */
 
 #endif /* _ALPHA_HARDIRQ_H */
diff -Nru a/include/asm-alpha/io.h b/include/asm-alpha/io.h
--- a/include/asm-alpha/io.h	2004-10-18 14:57:03 -07:00
+++ b/include/asm-alpha/io.h	2004-10-18 14:57:03 -07:00
@@ -1,6 +1,20 @@
 #ifndef __ALPHA_IO_H
 #define __ALPHA_IO_H
 
+#ifdef __KERNEL__
+
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <asm/compiler.h>
+#include <asm/system.h>
+#include <asm/pgtable.h>
+#include <asm/machvec.h>
+#include <asm/hwrpb.h>
+
+/* The generic header contains only prototypes.  Including it ensures that
+   the implementation we have here matches that interface.  */
+#include <asm-generic/iomap.h>
+
 /* We don't use IO slowdowns on the Alpha, but.. */
 #define __SLOW_DOWN_IO	do { } while (0)
 #define SLOW_DOWN_IO	do { } while (0)
@@ -14,14 +28,6 @@
 #define IDENT_ADDR     0xfffffc0000000000UL
 #endif
 
-#ifdef __KERNEL__
-#include <linux/config.h>
-#include <linux/kernel.h>
-#include <asm/system.h>
-#include <asm/pgtable.h>
-#include <asm/machvec.h>
-#include <asm/hwrpb.h>
-
 /*
  * We try to avoid hae updates (thus the cache), but when we
  * do need to update the hae, we need to do it atomically, so
@@ -88,6 +94,9 @@
 /* This depends on working iommu.  */
 #define BIO_VMERGE_BOUNDARY	(alpha_mv.mv_pci_tbi ? PAGE_SIZE : 0)
 
+/* Maximum PIO space address supported?  */
+#define IO_SPACE_LIMIT 0xffff
+
 /*
  * Change addresses as seen by the kernel (virtual) to addresses as
  * seen by a device (bus), and vice versa.
@@ -118,67 +127,81 @@
 	return (long)address <= 0 ? NULL : virt;
 }
 
-#else /* !__KERNEL__ */
-
-/*
- * Define actual functions in private name-space so it's easier to
- * accommodate things like XFree or svgalib that like to define their
- * own versions of inb etc.
- */
-extern void __sethae (unsigned long addr);	/* syscall */
-extern void _sethae (unsigned long addr);	/* cached version */
-
-#endif /* !__KERNEL__ */
-
 /*
  * There are different chipsets to interface the Alpha CPUs to the world.
  */
 
-#ifdef __KERNEL__
+#define IO_CONCAT(a,b)	_IO_CONCAT(a,b)
+#define _IO_CONCAT(a,b)	a ## _ ## b
+
 #ifdef CONFIG_ALPHA_GENERIC
 
 /* In a generic kernel, we always go through the machine vector.  */
 
-# define __inb(p)	alpha_mv.mv_inb((unsigned long)(p))
-# define __inw(p)	alpha_mv.mv_inw((unsigned long)(p))
-# define __inl(p)	alpha_mv.mv_inl((unsigned long)(p))
-# define __outb(x,p)	alpha_mv.mv_outb((x),(unsigned long)(p))
-# define __outw(x,p)	alpha_mv.mv_outw((x),(unsigned long)(p))
-# define __outl(x,p)	alpha_mv.mv_outl((x),(unsigned long)(p))
-
-# define __readb(a)	alpha_mv.mv_readb((unsigned long)(a))
-# define __readw(a)	alpha_mv.mv_readw((unsigned long)(a))
-# define __readl(a)	alpha_mv.mv_readl((unsigned long)(a))
-# define __readq(a)	alpha_mv.mv_readq((unsigned long)(a))
-# define __writeb(v,a)	alpha_mv.mv_writeb((v),(unsigned long)(a))
-# define __writew(v,a)	alpha_mv.mv_writew((v),(unsigned long)(a))
-# define __writel(v,a)	alpha_mv.mv_writel((v),(unsigned long)(a))
-# define __writeq(v,a)	alpha_mv.mv_writeq((v),(unsigned long)(a))
-
-# define __ioremap(a,s)	alpha_mv.mv_ioremap((unsigned long)(a),(s))
-# define __iounmap(a)   alpha_mv.mv_iounmap((unsigned long)(a))
-# define __is_ioaddr(a)	alpha_mv.mv_is_ioaddr((unsigned long)(a))
-
-# define inb		__inb
-# define inw		__inw
-# define inl		__inl
-# define outb		__outb
-# define outw		__outw
-# define outl		__outl
-
-# define __raw_readb	__readb
-# define __raw_readw	__readw
-# define __raw_readl	__readl
-# define __raw_readq	__readq
-# define __raw_writeb	__writeb
-# define __raw_writew	__writew
-# define __raw_writel	__writel
-# define __raw_writeq	__writeq
+#define REMAP1(TYPE, NAME, QUAL)					\
+static inline TYPE generic_##NAME(QUAL void __iomem *addr)		\
+{									\
+	return alpha_mv.mv_##NAME(addr);				\
+}
 
-#else
+#define REMAP2(TYPE, NAME, QUAL)					\
+static inline void generic_##NAME(TYPE b, QUAL void __iomem *addr)	\
+{									\
+	alpha_mv.mv_##NAME(b, addr);					\
+}
+
+REMAP1(unsigned int, ioread8, /**/)
+REMAP1(unsigned int, ioread16, /**/)
+REMAP1(unsigned int, ioread32, /**/)
+REMAP1(u8, readb, const volatile)
+REMAP1(u16, readw, const volatile)
+REMAP1(u32, readl, const volatile)
+REMAP1(u64, readq, const volatile)
+
+REMAP2(u8, iowrite8, /**/)
+REMAP2(u16, iowrite16, /**/)
+REMAP2(u32, iowrite32, /**/)
+REMAP2(u8, writeb, volatile)
+REMAP2(u16, writew, volatile)
+REMAP2(u32, writel, volatile)
+REMAP2(u64, writeq, volatile)
+
+#undef REMAP1
+#undef REMAP2
+
+static inline void __iomem *generic_ioportmap(unsigned long a)
+{
+	return alpha_mv.mv_ioportmap(a);
+}
+
+static inline void __iomem *generic_ioremap(unsigned long a, unsigned long s)
+{
+	return alpha_mv.mv_ioremap(a, s);
+}
+
+static inline void generic_iounmap(volatile void __iomem *a)
+{
+	return alpha_mv.mv_iounmap(a);
+}
+
+static inline int generic_is_ioaddr(unsigned long a)
+{
+	return alpha_mv.mv_is_ioaddr(a);
+}
+
+static inline int generic_is_mmio(const volatile void __iomem *a)
+{
+	return alpha_mv.mv_is_mmio(a);
+}
 
-/* Control how and what gets defined within the core logic headers.  */
-#define __WANT_IO_DEF
+#define __IO_PREFIX		generic
+#define generic_trivial_rw_bw	0
+#define generic_trivial_rw_lq	0
+#define generic_trivial_io_bw	0
+#define generic_trivial_io_lq	0
+#define generic_trivial_iounmap	0
+
+#else
 
 #if defined(CONFIG_ALPHA_APECS)
 # include <asm/core_apecs.h>
@@ -208,245 +231,281 @@
 #error "What system is this?"
 #endif
 
-#undef __WANT_IO_DEF
-
 #endif /* GENERIC */
-#endif /* __KERNEL__ */
 
 /*
- * The convention used for inb/outb etc. is that names starting with
- * two underscores are the inline versions, names starting with a
- * single underscore are proper functions, and names starting with a
- * letter are macros that map in some way to inline or proper function
- * versions.  Not all that pretty, but before you change it, be sure
- * to convince yourself that it won't break anything (in particular
- * module support).
- */
-extern u8		_inb (unsigned long port);
-extern u16		_inw (unsigned long port);
-extern u32		_inl (unsigned long port);
-extern void		_outb (u8 b,unsigned long port);
-extern void		_outw (u16 w,unsigned long port);
-extern void		_outl (u32 l,unsigned long port);
-extern u8		_readb(unsigned long addr);
-extern u16		_readw(unsigned long addr);
-extern u32		_readl(unsigned long addr);
-extern u64		_readq(unsigned long addr);
-extern void		_writeb(u8 b, unsigned long addr);
-extern void		_writew(u16 b, unsigned long addr);
-extern void		_writel(u32 b, unsigned long addr);
-extern void		_writeq(u64 b, unsigned long addr);
-
-#ifdef __KERNEL__
-/*
- * The platform header files may define some of these macros to use
- * the inlined versions where appropriate.  These macros may also be
- * redefined by userlevel programs.
+ * We always have external versions of these routines.
  */
-#ifndef inb
-# define inb(p)		_inb(p)
-#endif
-#ifndef inw
-# define inw(p)		_inw(p)
-#endif
-#ifndef inl
-# define inl(p)		_inl(p)
-#endif
-#ifndef outb
-# define outb(b,p)	_outb((b),(p))
-#endif
-#ifndef outw
-# define outw(w,p)	_outw((w),(p))
-#endif
-#ifndef outl
-# define outl(l,p)	_outl((l),(p))
-#endif
-
-#ifndef inb_p
-# define inb_p		inb
-#endif
-#ifndef inw_p
-# define inw_p		inw
-#endif
-#ifndef inl_p
-# define inl_p		inl
-#endif
+extern u8		inb(unsigned long port);
+extern u16		inw(unsigned long port);
+extern u32		inl(unsigned long port);
+extern void		outb(u8 b, unsigned long port);
+extern void		outw(u16 b, unsigned long port);
+extern void		outl(u32 b, unsigned long port);
+
+extern u8		readb(const volatile void __iomem *addr);
+extern u16		readw(const volatile void __iomem *addr);
+extern u32		readl(const volatile void __iomem *addr);
+extern u64		readq(const volatile void __iomem *addr);
+extern void		writeb(u8 b, volatile void __iomem *addr);
+extern void		writew(u16 b, volatile void __iomem *addr);
+extern void		writel(u32 b, volatile void __iomem *addr);
+extern void		writeq(u64 b, volatile void __iomem *addr);
+
+extern u8		__raw_readb(const volatile void __iomem *addr);
+extern u16		__raw_readw(const volatile void __iomem *addr);
+extern u32		__raw_readl(const volatile void __iomem *addr);
+extern u64		__raw_readq(const volatile void __iomem *addr);
+extern void		__raw_writeb(u8 b, volatile void __iomem *addr);
+extern void		__raw_writew(u16 b, volatile void __iomem *addr);
+extern void		__raw_writel(u32 b, volatile void __iomem *addr);
+extern void		__raw_writeq(u64 b, volatile void __iomem *addr);
+
+/*
+ * Mapping from port numbers to __iomem space is pretty easy.
+ */
+
+/* These two have to be extern inline because of the extern prototype from
+   <asm-generic/iomap.h>.  It is not legal to mix "extern" and "static" for
+   the same declaration.  */
+extern inline void __iomem *ioport_map(unsigned long port, unsigned int size)
+{
+	return IO_CONCAT(__IO_PREFIX,ioportmap) (port);
+}
 
-#ifndef outb_p
-# define outb_p		outb
-#endif
-#ifndef outw_p
-# define outw_p		outw
-#endif
-#ifndef outl_p
-# define outl_p		outl
-#endif
+extern inline void ioport_unmap(void __iomem *addr)
+{
+}
 
-#define IO_SPACE_LIMIT 0xffff
+static inline void __iomem *ioremap(unsigned long port, unsigned long size)
+{
+	return IO_CONCAT(__IO_PREFIX,ioremap) (port, size);
+}
 
-#else 
+static inline void __iomem * ioremap_nocache(unsigned long offset,
+					     unsigned long size)
+{
+	return ioremap(offset, size);
+} 
 
-/* Userspace declarations.  Kill in 2.5. */
+static inline void iounmap(volatile void __iomem *addr)
+{
+	IO_CONCAT(__IO_PREFIX,iounmap)(addr);
+}
 
-extern unsigned int	inb(unsigned long port);
-extern unsigned int	inw(unsigned long port);
-extern unsigned int	inl(unsigned long port);
-extern void		outb(unsigned char b,unsigned long port);
-extern void		outw(unsigned short w,unsigned long port);
-extern void		outl(unsigned int l,unsigned long port);
-extern unsigned long	readb(unsigned long addr);
-extern unsigned long	readw(unsigned long addr);
-extern unsigned long	readl(unsigned long addr);
-extern void		writeb(unsigned char b, unsigned long addr);
-extern void		writew(unsigned short b, unsigned long addr);
-extern void		writel(unsigned int b, unsigned long addr);
+static inline int __is_ioaddr(unsigned long addr)
+{
+	return IO_CONCAT(__IO_PREFIX,is_ioaddr)(addr);
+}
+#define __is_ioaddr(a)		__is_ioaddr((unsigned long)(a))
 
-#endif /* __KERNEL__ */
+static inline int __is_mmio(const volatile void __iomem *addr)
+{
+	return IO_CONCAT(__IO_PREFIX,is_mmio)(addr);
+}
 
-#ifdef __KERNEL__
 
 /*
- * On Alpha, we have the whole of I/O space mapped at all times, but
- * at odd and sometimes discontinuous addresses.  Note that the 
- * discontinuities are all across busses, so we need not care for that
- * for any one device.
- *
- * The DRM drivers need to be able to map contiguously a (potentially)
- * discontiguous set of I/O pages. This set of pages is scatter-gather
- * mapped contiguously from the perspective of the bus, but we can't
- * directly access DMA addresses from the CPU, these addresses need to
- * have a real ioremap. Therefore, iounmap and the size argument to
- * ioremap are needed to give the platforms the ability to fully implement
- * ioremap.
- *
- * Map the I/O space address into the kernel's virtual address space.
+ * If the actual I/O bits are sufficiently trivial, then expand inline.
  */
-static inline void * ioremap(unsigned long offset, unsigned long size)
+
+#if IO_CONCAT(__IO_PREFIX,trivial_io_bw)
+extern inline unsigned int ioread8(void __iomem *addr)
 {
-	return (void *) __ioremap(offset, size);
-} 
+	unsigned int ret = IO_CONCAT(__IO_PREFIX,ioread8)(addr);
+	mb();
+	return ret;
+}
 
-static inline void iounmap(void *addr)
+extern inline unsigned int ioread16(void __iomem *addr)
 {
-	__iounmap(addr);
+	unsigned int ret = IO_CONCAT(__IO_PREFIX,ioread16)(addr);
+	mb();
+	return ret;
 }
 
-static inline void * ioremap_nocache(unsigned long offset, unsigned long size)
+extern inline void iowrite8(u8 b, void __iomem *addr)
 {
-	return ioremap(offset, size);
-} 
+	IO_CONCAT(__IO_PREFIX,iowrite8)(b, addr);
+	mb();
+}
 
-/* Indirect back to the macros provided.  */
+extern inline void iowrite16(u16 b, void __iomem *addr)
+{
+	IO_CONCAT(__IO_PREFIX,iowrite16)(b, addr);
+	mb();
+}
 
-extern u8		___raw_readb(unsigned long addr);
-extern u16		___raw_readw(unsigned long addr);
-extern u32		___raw_readl(unsigned long addr);
-extern u64		___raw_readq(unsigned long addr);
-extern void		___raw_writeb(u8 b, unsigned long addr);
-extern void		___raw_writew(u16 b, unsigned long addr);
-extern void		___raw_writel(u32 b, unsigned long addr);
-extern void		___raw_writeq(u64 b, unsigned long addr);
+extern inline u8 inb(unsigned long port)
+{
+	return ioread8(ioport_map(port, 1));
+}
 
-#ifdef __raw_readb
-# define readb(a)	({ u8 r_ = __raw_readb(a); mb(); r_; })
-#endif
-#ifdef __raw_readw
-# define readw(a)	({ u16 r_ = __raw_readw(a); mb(); r_; })
-#endif
-#ifdef __raw_readl
-# define readl(a)	({ u32 r_ = __raw_readl(a); mb(); r_; })
-#endif
-#ifdef __raw_readq
-# define readq(a)	({ u64 r_ = __raw_readq(a); mb(); r_; })
-#endif
+extern inline u16 inw(unsigned long port)
+{
+	return ioread16(ioport_map(port, 2));
+}
 
-#ifdef __raw_writeb
-# define writeb(v,a)	({ __raw_writeb((v),(a)); mb(); })
-#endif
-#ifdef __raw_writew
-# define writew(v,a)	({ __raw_writew((v),(a)); mb(); })
-#endif
-#ifdef __raw_writel
-# define writel(v,a)	({ __raw_writel((v),(a)); mb(); })
-#endif
-#ifdef __raw_writeq
-# define writeq(v,a)	({ __raw_writeq((v),(a)); mb(); })
-#endif
+extern inline void outb(u8 b, unsigned long port)
+{
+	iowrite8(b, ioport_map(port, 1));
+}
 
-#ifndef __raw_readb
-# define __raw_readb(a)	___raw_readb((unsigned long)(a))
-#endif
-#ifndef __raw_readw
-# define __raw_readw(a)	___raw_readw((unsigned long)(a))
-#endif
-#ifndef __raw_readl
-# define __raw_readl(a)	___raw_readl((unsigned long)(a))
-#endif
-#ifndef __raw_readq
-# define __raw_readq(a)	___raw_readq((unsigned long)(a))
+extern inline void outw(u16 b, unsigned long port)
+{
+	iowrite16(b, ioport_map(port, 2));
+}
 #endif
 
-#ifndef __raw_writeb
-# define __raw_writeb(v,a)  ___raw_writeb((v),(unsigned long)(a))
-#endif
-#ifndef __raw_writew
-# define __raw_writew(v,a)  ___raw_writew((v),(unsigned long)(a))
-#endif
-#ifndef __raw_writel
-# define __raw_writel(v,a)  ___raw_writel((v),(unsigned long)(a))
-#endif
-#ifndef __raw_writeq
-# define __raw_writeq(v,a)  ___raw_writeq((v),(unsigned long)(a))
-#endif
+#if IO_CONCAT(__IO_PREFIX,trivial_io_lq)
+extern inline unsigned int ioread32(void __iomem *addr)
+{
+	unsigned int ret = IO_CONCAT(__IO_PREFIX,ioread32)(addr);
+	mb();
+	return ret;
+}
 
-#ifndef readb
-# define readb(a)	_readb((unsigned long)(a))
-#endif
-#ifndef readw
-# define readw(a)	_readw((unsigned long)(a))
-#endif
-#ifndef readl
-# define readl(a)	_readl((unsigned long)(a))
-#endif
-#ifndef readq
-# define readq(a)	_readq((unsigned long)(a))
-#endif
+extern inline void iowrite32(u32 b, void __iomem *addr)
+{
+	IO_CONCAT(__IO_PREFIX,iowrite32)(b, addr);
+	mb();
+}
 
-#define readb_relaxed(addr) readb(addr)
-#define readw_relaxed(addr) readw(addr)
-#define readl_relaxed(addr) readl(addr)
-#define readq_relaxed(addr) readq(addr)
+extern inline u32 inl(unsigned long port)
+{
+	return ioread32(ioport_map(port, 4));
+}
 
-#ifndef writeb
-# define writeb(v,a)	_writeb((v),(unsigned long)(a))
-#endif
-#ifndef writew
-# define writew(v,a)	_writew((v),(unsigned long)(a))
+extern inline void outl(u32 b, unsigned long port)
+{
+	iowrite32(b, ioport_map(port, 4));
+}
 #endif
-#ifndef writel
-# define writel(v,a)	_writel((v),(unsigned long)(a))
+
+#if IO_CONCAT(__IO_PREFIX,trivial_rw_bw) == 1
+extern inline u8 __raw_readb(const volatile void __iomem *addr)
+{
+	return IO_CONCAT(__IO_PREFIX,readb)(addr);
+}
+
+extern inline u16 __raw_readw(const volatile void __iomem *addr)
+{
+	return IO_CONCAT(__IO_PREFIX,readw)(addr);
+}
+
+extern inline void __raw_writeb(u8 b, volatile void __iomem *addr)
+{
+	IO_CONCAT(__IO_PREFIX,writeb)(b, addr);
+}
+
+extern inline void __raw_writew(u16 b, volatile void __iomem *addr)
+{
+	IO_CONCAT(__IO_PREFIX,writew)(b, addr);
+}
+
+extern inline u8 readb(const volatile void __iomem *addr)
+{
+	u8 ret = __raw_readb(addr);
+	mb();
+	return ret;
+}
+
+extern inline u16 readw(const volatile void __iomem *addr)
+{
+	u16 ret = __raw_readw(addr);
+	mb();
+	return ret;
+}
+
+extern inline void writeb(u8 b, volatile void __iomem *addr)
+{
+	__raw_writeb(b, addr);
+	mb();
+}
+
+extern inline void writew(u16 b, volatile void __iomem *addr)
+{
+	__raw_writew(b, addr);
+	mb();
+}
 #endif
-#ifndef writeq
-# define writeq(v,a)	_writeq((v),(unsigned long)(a))
+
+#if IO_CONCAT(__IO_PREFIX,trivial_rw_lq) == 1
+extern inline u32 __raw_readl(const volatile void __iomem *addr)
+{
+	return IO_CONCAT(__IO_PREFIX,readl)(addr);
+}
+
+extern inline u64 __raw_readq(const volatile void __iomem *addr)
+{
+	return IO_CONCAT(__IO_PREFIX,readq)(addr);
+}
+
+extern inline void __raw_writel(u32 b, volatile void __iomem *addr)
+{
+	IO_CONCAT(__IO_PREFIX,writel)(b, addr);
+}
+
+extern inline void __raw_writeq(u64 b, volatile void __iomem *addr)
+{
+	IO_CONCAT(__IO_PREFIX,writeq)(b, addr);
+}
+
+extern inline u32 readl(const volatile void __iomem *addr)
+{
+	u32 ret = __raw_readl(addr);
+	mb();
+	return ret;
+}
+
+extern inline u64 readq(const volatile void __iomem *addr)
+{
+	u64 ret = __raw_readq(addr);
+	mb();
+	return ret;
+}
+
+extern inline void writel(u32 b, volatile void __iomem *addr)
+{
+	__raw_writel(b, addr);
+	mb();
+}
+
+extern inline void writeq(u64 b, volatile void __iomem *addr)
+{
+	__raw_writeq(b, addr);
+	mb();
+}
 #endif
 
+#define inb_p		inb
+#define inw_p		inw
+#define inl_p		inl
+#define outb_p		outb
+#define outw_p		outw
+#define outl_p		outl
+#define readb_relaxed(addr) __raw_readb(addr)
+#define readw_relaxed(addr) __raw_readw(addr)
+#define readl_relaxed(addr) __raw_readl(addr)
+#define readq_relaxed(addr) __raw_readq(addr)
+
 /*
  * String version of IO memory access ops:
  */
-extern void _memcpy_fromio(void *, unsigned long, long);
-extern void _memcpy_toio(unsigned long, const void *, long);
-extern void _memset_c_io(unsigned long, unsigned long, long);
-
-#define memcpy_fromio(to,from,len) \
-  _memcpy_fromio((to),(unsigned long)(from),(len))
-#define memcpy_toio(to,from,len) \
-  _memcpy_toio((unsigned long)(to),(from),(len))
-#define memset_io(addr,c,len) \
-  _memset_c_io((unsigned long)(addr),0x0101010101010101UL*(u8)(c),(len))
+extern void memcpy_fromio(void *, const volatile void __iomem *, long);
+extern void memcpy_toio(volatile void __iomem *, const void *, long);
+extern void _memset_c_io(volatile void __iomem *, unsigned long, long);
+
+static inline void memset_io(volatile void __iomem *addr, u8 c, long len)
+{
+	_memset_c_io(addr, 0x0101010101010101UL * c, len);
+}
 
 #define __HAVE_ARCH_MEMSETW_IO
-#define memsetw_io(addr,c,len) \
-  _memset_c_io((unsigned long)(addr),0x0001000100010001UL*(u16)(c),(len))
+static inline void memsetw_io(volatile void __iomem *addr, u16 c, long len)
+{
+	_memset_c_io(addr, 0x0001000100010001UL * c, len);
+}
 
 /*
  * String versions of in/out ops:
@@ -465,26 +524,22 @@
  */
 
 #define eth_io_copy_and_sum(skb,src,len,unused) \
-  memcpy_fromio((skb)->data,(src),(len))
+  memcpy_fromio((skb)->data,src,len)
 
 #define isa_eth_io_copy_and_sum(skb,src,len,unused) \
-  isa_memcpy_fromio((skb)->data,(src),(len))
+  isa_memcpy_fromio((skb)->data,src,len)
 
 static inline int
-check_signature(unsigned long io_addr, const unsigned char *signature,
-		int length)
+check_signature(const volatile void __iomem *io_addr,
+		const unsigned char *signature, int length)
 {
-	int retval = 0;
 	do {
 		if (readb(io_addr) != *signature)
-			goto out;
+			return 0;
 		io_addr++;
 		signature++;
-		length--;
-	} while (length);
-	retval = 1;
-out:
-	return retval;
+	} while (--length);
+	return 1;
 }
 
 
@@ -492,31 +547,89 @@
  * ISA space is mapped to some machine-specific location on Alpha.
  * Call into the existing hooks to get the address translated.
  */
-#define isa_readb(a)			readb(__ioremap((a),1))
-#define isa_readw(a)			readw(__ioremap((a),2))
-#define isa_readl(a)			readl(__ioremap((a),4))
-#define isa_writeb(b,a)			writeb((b),__ioremap((a),1))
-#define isa_writew(w,a)			writew((w),__ioremap((a),2))
-#define isa_writel(l,a)			writel((l),__ioremap((a),4))
-#define isa_memset_io(a,b,c)		memset_io(__ioremap((a),(c)),(b),(c))
-#define isa_memcpy_fromio(a,b,c)	memcpy_fromio((a),__ioremap((b),(c)),(c))
-#define isa_memcpy_toio(a,b,c)		memcpy_toio(__ioremap((a),(c)),(b),(c))
+
+static inline u8
+isa_readb(unsigned long offset)
+{
+	void __iomem *addr = ioremap(offset, 1);
+	u8 ret = readb(addr);
+	iounmap(addr);
+	return ret;
+}
+
+static inline u16
+isa_readw(unsigned long offset)
+{
+	void __iomem *addr = ioremap(offset, 2);
+	u16 ret = readw(addr);
+	iounmap(addr);
+	return ret;
+}
+
+static inline u32
+isa_readl(unsigned long offset)
+{
+	void __iomem *addr = ioremap(offset, 2);
+	u32 ret = readl(addr);
+	iounmap(addr);
+	return ret;
+}
+
+static inline void
+isa_writeb(u8 b, unsigned long offset)
+{
+	void __iomem *addr = ioremap(offset, 2);
+	writeb(b, addr);
+	iounmap(addr);
+}
+
+static inline void
+isa_writew(u16 w, unsigned long offset)
+{
+	void __iomem *addr = ioremap(offset, 2);
+	writew(w, addr);
+	iounmap(addr);
+}
+
+static inline void
+isa_writel(u32 l, unsigned long offset)
+{
+	void __iomem *addr = ioremap(offset, 2);
+	writel(l, addr);
+	iounmap(addr);
+}
+
+static inline void
+isa_memset_io(unsigned long offset, u8 val, long n)
+{
+	void __iomem *addr = ioremap(offset, n);
+	memset_io(addr, val, n);
+	iounmap(addr);
+}
+
+static inline void
+isa_memcpy_fromio(void *dest, unsigned long offset, long n)
+{
+	void __iomem *addr = ioremap(offset, n);
+	memcpy_fromio(dest, addr, n);
+	iounmap(addr);
+}
+
+static inline void
+isa_memcpy_toio(unsigned long offset, const void *src, long n)
+{
+	void __iomem *addr = ioremap(offset, n);
+	memcpy_toio(addr, src, n);
+	iounmap(addr);
+}
 
 static inline int
-isa_check_signature(unsigned long io_addr, const unsigned char *signature,
-		int length)
+isa_check_signature(unsigned long offset, const unsigned char *sig, long len)
 {
-	int retval = 0;
-	do {
-		if (isa_readb(io_addr) != *signature)
-			goto out;
-		io_addr++;
-		signature++;
-		length--;
-	} while (length);
-	retval = 1;
-out:
-	return retval;
+	void __iomem *addr = ioremap(offset, len);
+	int ret = check_signature(addr, sig, len);
+	iounmap(addr);
+	return ret;
 }
 
 
diff -Nru a/include/asm-alpha/io_trivial.h b/include/asm-alpha/io_trivial.h
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/include/asm-alpha/io_trivial.h	2004-10-18 14:57:23 -07:00
@@ -0,0 +1,127 @@
+/* Trivial implementations of basic i/o routines.  Assumes that all
+   of the hard work has been done by ioremap and ioportmap, and that
+   access to i/o space is linear.  */
+
+/* This file may be included multiple times.  */
+
+#if IO_CONCAT(__IO_PREFIX,trivial_io_bw)
+__EXTERN_INLINE unsigned int
+IO_CONCAT(__IO_PREFIX,ioread8)(void __iomem *a)
+{
+	return __kernel_ldbu(*(volatile u8 __force *)a);
+}
+
+__EXTERN_INLINE unsigned int
+IO_CONCAT(__IO_PREFIX,ioread16)(void __iomem *a)
+{
+	return __kernel_ldwu(*(volatile u16 __force *)a);
+}
+
+__EXTERN_INLINE void
+IO_CONCAT(__IO_PREFIX,iowrite8)(u8 b, void __iomem *a)
+{
+	__kernel_stb(b, *(volatile u8 __force *)a);
+}
+
+__EXTERN_INLINE void
+IO_CONCAT(__IO_PREFIX,iowrite16)(u16 b, void __iomem *a)
+{
+	__kernel_stb(b, *(volatile u16 __force *)a);
+}
+#endif
+
+#if IO_CONCAT(__IO_PREFIX,trivial_io_lq)
+__EXTERN_INLINE unsigned int
+IO_CONCAT(__IO_PREFIX,ioread32)(void __iomem *a)
+{
+	return *(volatile u32 __force *)a;
+}
+
+__EXTERN_INLINE void
+IO_CONCAT(__IO_PREFIX,iowrite32)(u32 b, void __iomem *a)
+{
+	*(volatile u32 __force *)a = b;
+}
+#endif
+
+#if IO_CONCAT(__IO_PREFIX,trivial_rw_bw) == 1
+__EXTERN_INLINE u8
+IO_CONCAT(__IO_PREFIX,readb)(const volatile void __iomem *a)
+{
+	return __kernel_ldbu(*(const volatile u8 __force *)a);
+}
+
+__EXTERN_INLINE u16
+IO_CONCAT(__IO_PREFIX,readw)(const volatile void __iomem *a)
+{
+	return __kernel_ldwu(*(const volatile u16 __force *)a);
+}
+
+__EXTERN_INLINE void
+IO_CONCAT(__IO_PREFIX,writeb)(u8 b, volatile void __iomem *a)
+{
+	__kernel_stb(b, *(volatile u8 __force *)a);
+}
+
+__EXTERN_INLINE void
+IO_CONCAT(__IO_PREFIX,writew)(u16 b, volatile void __iomem *a)
+{
+	__kernel_stb(b, *(volatile u16 __force *)a);
+}
+#elif IO_CONCAT(__IO_PREFIX,trivial_rw_bw) == 2
+__EXTERN_INLINE u8
+IO_CONCAT(__IO_PREFIX,readb)(const volatile void __iomem *a)
+{
+	return IO_CONCAT(__IO_PREFIX,ioread8)((void __iomem *)a);
+}
+
+__EXTERN_INLINE u16
+IO_CONCAT(__IO_PREFIX,readw)(const volatile void __iomem *a)
+{
+	return IO_CONCAT(__IO_PREFIX,ioread16)((void __iomem *)a);
+}
+
+__EXTERN_INLINE void
+IO_CONCAT(__IO_PREFIX,writeb)(u8 b, volatile void __iomem *a)
+{
+	IO_CONCAT(__IO_PREFIX,iowrite8)(b, (void __iomem *)a);
+}
+
+__EXTERN_INLINE void
+IO_CONCAT(__IO_PREFIX,writew)(u16 b, volatile void __iomem *a)
+{
+	IO_CONCAT(__IO_PREFIX,iowrite16)(b, (void __iomem *)a);
+}
+#endif
+
+#if IO_CONCAT(__IO_PREFIX,trivial_rw_lq) == 1
+__EXTERN_INLINE u32
+IO_CONCAT(__IO_PREFIX,readl)(const volatile void __iomem *a)
+{
+	return *(const volatile u32 __force *)a;
+}
+
+__EXTERN_INLINE u64
+IO_CONCAT(__IO_PREFIX,readq)(const volatile void __iomem *a)
+{
+	return *(const volatile u64 __force *)a;
+}
+
+__EXTERN_INLINE void
+IO_CONCAT(__IO_PREFIX,writel)(u32 b, volatile void __iomem *a)
+{
+	*(volatile u32 __force *)a = b;
+}
+
+__EXTERN_INLINE void
+IO_CONCAT(__IO_PREFIX,writeq)(u64 b, volatile void __iomem *a)
+{
+	*(volatile u64 __force *)a = b;
+}
+#endif
+
+#if IO_CONCAT(__IO_PREFIX,trivial_iounmap)
+__EXTERN_INLINE void IO_CONCAT(__IO_PREFIX,iounmap)(volatile void __iomem *a)
+{
+}
+#endif
diff -Nru a/include/asm-alpha/jensen.h b/include/asm-alpha/jensen.h
--- a/include/asm-alpha/jensen.h	2004-10-18 14:56:33 -07:00
+++ b/include/asm-alpha/jensen.h	2004-10-18 14:56:33 -07:00
@@ -200,8 +200,9 @@
  * Memory functions.
  */
 
-__EXTERN_INLINE u8 jensen_readb(unsigned long addr)
+__EXTERN_INLINE u8 jensen_readb(const volatile void __iomem *xaddr)
 {
+	unsigned long addr = (unsigned long) xaddr;
 	long result;
 
 	jensen_set_hae(addr);
@@ -211,8 +212,9 @@
 	return 0xffUL & result;
 }
 
-__EXTERN_INLINE u16 jensen_readw(unsigned long addr)
+__EXTERN_INLINE u16 jensen_readw(const volatile void __iomem *xaddr)
 {
+	unsigned long addr = (unsigned long) xaddr;
 	long result;
 
 	jensen_set_hae(addr);
@@ -222,15 +224,17 @@
 	return 0xffffUL & result;
 }
 
-__EXTERN_INLINE u32 jensen_readl(unsigned long addr)
+__EXTERN_INLINE u32 jensen_readl(const volatile void __iomem *xaddr)
 {
+	unsigned long addr = (unsigned long) xaddr;
 	jensen_set_hae(addr);
 	addr &= JENSEN_HAE_MASK;
 	return *(vuip) ((addr << 7) + EISA_MEM + 0x60);
 }
 
-__EXTERN_INLINE u64 jensen_readq(unsigned long addr)
+__EXTERN_INLINE u64 jensen_readq(const volatile void __iomem *xaddr)
 {
+	unsigned long addr = (unsigned long) xaddr;
 	unsigned long r0, r1;
 
 	jensen_set_hae(addr);
@@ -241,29 +245,33 @@
 	return r1 << 32 | r0;
 }
 
-__EXTERN_INLINE void jensen_writeb(u8 b, unsigned long addr)
+__EXTERN_INLINE void jensen_writeb(u8 b, volatile void __iomem *xaddr)
 {
+	unsigned long addr = (unsigned long) xaddr;
 	jensen_set_hae(addr);
 	addr &= JENSEN_HAE_MASK;
 	*(vuip) ((addr << 7) + EISA_MEM + 0x00) = b * 0x01010101;
 }
 
-__EXTERN_INLINE void jensen_writew(u16 b, unsigned long addr)
+__EXTERN_INLINE void jensen_writew(u16 b, volatile void __iomem *xaddr)
 {
+	unsigned long addr = (unsigned long) xaddr;
 	jensen_set_hae(addr);
 	addr &= JENSEN_HAE_MASK;
 	*(vuip) ((addr << 7) + EISA_MEM + 0x20) = b * 0x00010001;
 }
 
-__EXTERN_INLINE void jensen_writel(u32 b, unsigned long addr)
+__EXTERN_INLINE void jensen_writel(u32 b, volatile void __iomem *xaddr)
 {
+	unsigned long addr = (unsigned long) xaddr;
 	jensen_set_hae(addr);
 	addr &= JENSEN_HAE_MASK;
 	*(vuip) ((addr << 7) + EISA_MEM + 0x60) = b;
 }
 
-__EXTERN_INLINE void jensen_writeq(u64 b, unsigned long addr)
+__EXTERN_INLINE void jensen_writeq(u64 b, volatile void __iomem *xaddr)
 {
+	unsigned long addr = (unsigned long) xaddr;
 	jensen_set_hae(addr);
 	addr &= JENSEN_HAE_MASK;
 	addr = (addr << 7) + EISA_MEM + 0x60;
@@ -271,15 +279,15 @@
 	*(vuip) (addr + (4 << 7)) = b >> 32;
 }
 
-__EXTERN_INLINE unsigned long jensen_ioremap(unsigned long addr, 
-					     unsigned long size)
+__EXTERN_INLINE void __iomem *jensen_ioportmap(unsigned long addr)
 {
-	return addr;
+	return (void __iomem *)addr;
 }
 
-__EXTERN_INLINE void jensen_iounmap(unsigned long addr)
+__EXTERN_INLINE void __iomem *jensen_ioremap(unsigned long addr,
+					     unsigned long size)
 {
-	return;
+	return (void __iomem *)(addr + 0x100000000ul);
 }
 
 __EXTERN_INLINE int jensen_is_ioaddr(unsigned long addr)
@@ -287,39 +295,46 @@
 	return (long)addr >= 0;
 }
 
-#undef vuip
+__EXTERN_INLINE int jensen_is_mmio(const volatile void __iomem *addr)
+{
+	return (unsigned long)addr >= 0x100000000ul;
+}
+
+/* New-style ioread interface.  All the routines are so ugly for Jensen
+   that it doesn't make sense to merge them.  */
 
-#ifdef __WANT_IO_DEF
+#define IOPORT(OS, NS)							\
+__EXTERN_INLINE unsigned int jensen_ioread##NS(void __iomem *xaddr)	\
+{									\
+	if (jensen_is_mmio(xaddr))					\
+		return jensen_read##OS(xaddr - 0x100000000ul);		\
+	else								\
+		return jensen_in##OS((unsigned long)xaddr);		\
+}									\
+__EXTERN_INLINE void jensen_iowrite##NS(u##NS b, void __iomem *xaddr)	\
+{									\
+	if (jensen_is_mmio(xaddr))					\
+		jensen_write##OS(b, xaddr - 0x100000000ul);		\
+	else								\
+		jensen_out##OS(b, (unsigned long)xaddr);		\
+}
+
+IOPORT(b, 8)
+IOPORT(w, 16)
+IOPORT(l, 32)
 
-#define __inb		jensen_inb
-#define __inw		jensen_inw
-#define __inl		jensen_inl
-#define __outb		jensen_outb
-#define __outw		jensen_outw
-#define __outl		jensen_outl
-#define __readb		jensen_readb
-#define __readw		jensen_readw
-#define __writeb	jensen_writeb
-#define __writew	jensen_writew
-#define __readl		jensen_readl
-#define __readq		jensen_readq
-#define __writel	jensen_writel
-#define __writeq	jensen_writeq
-#define __ioremap	jensen_ioremap
-#define __iounmap(a)	jensen_iounmap((unsigned long)a)
-#define __is_ioaddr	jensen_is_ioaddr
-
-/*
- * The above have so much overhead that it probably doesn't make
- * sense to have them inlined (better icache behaviour).
- */
-#define inb(port) \
-(__builtin_constant_p((port))?__inb(port):_inb(port))
+#undef IOPORT
 
-#define outb(x, port) \
-(__builtin_constant_p((port))?__outb((x),(port)):_outb((x),(port)))
+#undef vuip
 
-#endif /* __WANT_IO_DEF */
+#undef __IO_PREFIX
+#define __IO_PREFIX		jensen
+#define jensen_trivial_rw_bw	0
+#define jensen_trivial_rw_lq	0
+#define jensen_trivial_io_bw	0
+#define jensen_trivial_io_lq	0
+#define jensen_trivial_iounmap	1
+#include <asm/io_trivial.h>
 
 #ifdef __IO_EXTERN_INLINE
 #undef __EXTERN_INLINE
diff -Nru a/include/asm-alpha/machvec.h b/include/asm-alpha/machvec.h
--- a/include/asm-alpha/machvec.h	2004-10-18 14:55:55 -07:00
+++ b/include/asm-alpha/machvec.h	2004-10-18 14:55:55 -07:00
@@ -45,27 +45,29 @@
 	void (*mv_pci_tbi)(struct pci_controller *hose,
 			   dma_addr_t start, dma_addr_t end);
 
-	u8 (*mv_inb)(unsigned long);
-	u16 (*mv_inw)(unsigned long);
-	u32 (*mv_inl)(unsigned long);
+	unsigned int (*mv_ioread8)(void __iomem *);
+	unsigned int (*mv_ioread16)(void __iomem *);
+	unsigned int (*mv_ioread32)(void __iomem *);
 
-	void (*mv_outb)(u8, unsigned long);
-	void (*mv_outw)(u16, unsigned long);
-	void (*mv_outl)(u32, unsigned long);
-	
-	u8 (*mv_readb)(unsigned long);
-	u16 (*mv_readw)(unsigned long);
-	u32 (*mv_readl)(unsigned long);
-	u64 (*mv_readq)(unsigned long);
+	void (*mv_iowrite8)(u8, void __iomem *);
+	void (*mv_iowrite16)(u16, void __iomem *);
+	void (*mv_iowrite32)(u32, void __iomem *);
 
-	void (*mv_writeb)(u8, unsigned long);
-	void (*mv_writew)(u16, unsigned long);
-	void (*mv_writel)(u32, unsigned long);
-	void (*mv_writeq)(u64, unsigned long);
+	u8 (*mv_readb)(const volatile void __iomem *);
+	u16 (*mv_readw)(const volatile void __iomem *);
+	u32 (*mv_readl)(const volatile void __iomem *);
+	u64 (*mv_readq)(const volatile void __iomem *);
 
-	unsigned long (*mv_ioremap)(unsigned long, unsigned long);
-	void (*mv_iounmap)(unsigned long);
+	void (*mv_writeb)(u8, volatile void __iomem *);
+	void (*mv_writew)(u16, volatile void __iomem *);
+	void (*mv_writel)(u32, volatile void __iomem *);
+	void (*mv_writeq)(u64, volatile void __iomem *);
+
+	void __iomem *(*mv_ioportmap)(unsigned long);
+	void __iomem *(*mv_ioremap)(unsigned long, unsigned long);
+	void (*mv_iounmap)(volatile void __iomem *);
 	int (*mv_is_ioaddr)(unsigned long);
+	int (*mv_is_mmio)(const volatile void __iomem *);
 
 	void (*mv_switch_mm)(struct mm_struct *, struct mm_struct *,
 			     struct task_struct *);
diff -Nru a/include/asm-alpha/mmu_context.h b/include/asm-alpha/mmu_context.h
--- a/include/asm-alpha/mmu_context.h	2004-10-18 14:56:32 -07:00
+++ b/include/asm-alpha/mmu_context.h	2004-10-18 14:56:32 -07:00
@@ -10,6 +10,7 @@
 #include <linux/config.h>
 #include <asm/system.h>
 #include <asm/machvec.h>
+#include <asm/compiler.h>
 
 /*
  * Force a context reload. This is needed when we change the page
diff -Nru a/include/asm-alpha/page.h b/include/asm-alpha/page.h
--- a/include/asm-alpha/page.h	2004-10-18 14:56:49 -07:00
+++ b/include/asm-alpha/page.h	2004-10-18 14:56:49 -07:00
@@ -1,6 +1,7 @@
 #ifndef _ALPHA_PAGE_H
 #define _ALPHA_PAGE_H
 
+#include <linux/config.h>
 #include <asm/pal.h>
 
 /* PAGE_SHIFT determines the page size */
diff -Nru a/include/asm-alpha/pci.h b/include/asm-alpha/pci.h
--- a/include/asm-alpha/pci.h	2004-10-18 14:55:53 -07:00
+++ b/include/asm-alpha/pci.h	2004-10-18 14:55:53 -07:00
@@ -169,7 +169,7 @@
 
 static inline void
 pci_dma_sync_single_for_device(struct pci_dev *dev, dma_addr_t dma_addr,
-			       long size, int direction)
+			       size_t size, int direction)
 {
 	/* Nothing to do.  */
 }
@@ -245,6 +245,8 @@
 pcibios_add_platform_entries(struct pci_dev *dev)
 {
 }
+
+struct pci_dev *alpha_gendev_to_pci(struct device *dev);
 
 #endif /* __KERNEL__ */
 
diff -Nru a/include/asm-alpha/pgtable.h b/include/asm-alpha/pgtable.h
--- a/include/asm-alpha/pgtable.h	2004-10-18 14:56:27 -07:00
+++ b/include/asm-alpha/pgtable.h	2004-10-18 14:56:27 -07:00
@@ -328,7 +328,7 @@
 #endif
 
 #define io_remap_page_range(vma, start, busaddr, size, prot) \
-    remap_page_range(vma, start, virt_to_phys(__ioremap(busaddr, size)), size, prot)
+    remap_page_range(vma, start, virt_to_phys((void *)__ioremap(busaddr, size)), size, prot)
 
 #define pte_ERROR(e) \
 	printk("%s:%d: bad pte %016lx.\n", __FILE__, __LINE__, pte_val(e))
diff -Nru a/include/asm-alpha/ptrace.h b/include/asm-alpha/ptrace.h
--- a/include/asm-alpha/ptrace.h	2004-10-18 14:56:17 -07:00
+++ b/include/asm-alpha/ptrace.h	2004-10-18 14:56:17 -07:00
@@ -69,6 +69,7 @@
 #ifdef __KERNEL__
 #define user_mode(regs) (((regs)->ps & 8) != 0)
 #define instruction_pointer(regs) ((regs)->pc)
+#define profile_pc(regs) instruction_pointer(regs)
 extern void show_regs(struct pt_regs *);
 
 #define alpha_task_regs(task) \
diff -Nru a/include/asm-alpha/resource.h b/include/asm-alpha/resource.h
--- a/include/asm-alpha/resource.h	2004-10-18 14:55:54 -07:00
+++ b/include/asm-alpha/resource.h	2004-10-18 14:55:54 -07:00
@@ -41,7 +41,7 @@
     {INR_OPEN, INR_OPEN},			/* RLIMIT_NOFILE */	\
     {LONG_MAX, LONG_MAX},			/* RLIMIT_AS */		\
     {LONG_MAX, LONG_MAX},			/* RLIMIT_NPROC */	\
-    {LONG_MAX, LONG_MAX},			/* RLIMIT_MEMLOCK */	\
+    {MLOCK_LIMIT, MLOCK_LIMIT },		/* RLIMIT_MEMLOCK */	\
     {LONG_MAX, LONG_MAX},			/* RLIMIT_LOCKS */	\
     {MAX_SIGPENDING, MAX_SIGPENDING},		/* RLIMIT_SIGPENDING */ \
     {MQ_BYTES_MAX, MQ_BYTES_MAX},		/* RLIMIT_MSGQUEUE */	\
diff -Nru a/include/asm-alpha/semaphore.h b/include/asm-alpha/semaphore.h
--- a/include/asm-alpha/semaphore.h	2004-10-18 14:56:49 -07:00
+++ b/include/asm-alpha/semaphore.h	2004-10-18 14:56:49 -07:00
@@ -18,21 +18,13 @@
 struct semaphore {
 	atomic_t count;
 	wait_queue_head_t wait;
-#ifdef WAITQUEUE_DEBUG
-	long __magic;
-#endif
 };
 
-#ifdef WAITQUEUE_DEBUG
-# define __SEM_DEBUG_INIT(name)		, (long)&(name).__magic
-#else
-# define __SEM_DEBUG_INIT(name)
-#endif
-
-#define __SEMAPHORE_INITIALIZER(name,count)		\
-	{ ATOMIC_INIT(count),				\
-	  __WAIT_QUEUE_HEAD_INITIALIZER((name).wait)	\
-	  __SEM_DEBUG_INIT(name) }
+#define __SEMAPHORE_INITIALIZER(name, n)			\
+{								\
+	.count	= ATOMIC_INIT(n),				\
+  	.wait	= __WAIT_QUEUE_HEAD_INITIALIZER((name).wait),	\
+}
 
 #define __MUTEX_INITIALIZER(name)			\
 	__SEMAPHORE_INITIALIZER(name,1)
@@ -53,9 +45,6 @@
 
 	atomic_set(&sem->count, val);
 	init_waitqueue_head(&sem->wait);
-#ifdef WAITQUEUE_DEBUG
-	sem->__magic = (long)&sem->__magic;
-#endif
 }
 
 static inline void init_MUTEX (struct semaphore *sem)
@@ -142,7 +131,7 @@
 		__up_wakeup(sem);
 }
 
-#if !defined(WAITQUEUE_DEBUG) && !defined(CONFIG_DEBUG_SEMAPHORE)
+#if !defined(CONFIG_DEBUG_SEMAPHORE)
 extern inline void down(struct semaphore *sem)
 {
 	__down(sem);
diff -Nru a/include/asm-alpha/socket.h b/include/asm-alpha/socket.h
--- a/include/asm-alpha/socket.h	2004-10-18 14:57:04 -07:00
+++ b/include/asm-alpha/socket.h	2004-10-18 14:57:04 -07:00
@@ -55,20 +55,4 @@
 #define SO_SECURITY_ENCRYPTION_TRANSPORT	20
 #define SO_SECURITY_ENCRYPTION_NETWORK		21
 
-/* Nast libc5 fixup - bletch */
-#if defined(__KERNEL__)
-/* Socket types. */
-#define SOCK_STREAM	1		/* stream (connection) socket	*/
-#define SOCK_DGRAM	2		/* datagram (conn.less) socket	*/
-#define SOCK_RAW	3		/* raw socket			*/
-#define SOCK_RDM	4		/* reliably-delivered message	*/
-#define SOCK_SEQPACKET	5		/* sequential packet socket	*/
-#define SOCK_PACKET	10		/* linux specific way of	*/
-					/* getting packets at the dev	*/
-					/* level.  For writing rarp and	*/
-					/* other similar things on the	*/
-					/* user level.			*/
-#define	SOCK_MAX	(SOCK_PACKET+1)
-#endif
-
 #endif /* _ASM_SOCKET_H */
diff -Nru a/include/asm-alpha/spinlock.h b/include/asm-alpha/spinlock.h
--- a/include/asm-alpha/spinlock.h	2004-10-18 14:56:33 -07:00
+++ b/include/asm-alpha/spinlock.h	2004-10-18 14:56:33 -07:00
@@ -95,7 +95,7 @@
 /***********************************************************/
 
 typedef struct {
-	volatile int write_lock:1, read_counter:31;
+	volatile unsigned int write_lock:1, read_counter:31;
 } /*__attribute__((aligned(32)))*/ rwlock_t;
 
 #define RW_LOCK_UNLOCKED (rwlock_t) { 0, 0 }
@@ -124,7 +124,7 @@
 	"	br	1b\n"
 	".previous"
 	: "=m" (*lock), "=&r" (regx)
-	: "0" (*lock) : "memory");
+	: "m" (*lock) : "memory");
 }
 
 static inline void _raw_read_lock(rwlock_t * lock)
@@ -147,6 +147,29 @@
 	: "m" (*lock) : "memory");
 }
 #endif /* CONFIG_DEBUG_RWLOCK */
+
+static inline int _raw_write_trylock(rwlock_t * lock)
+{
+	long regx;
+	int success;
+
+	__asm__ __volatile__(
+	"1:	ldl_l	%1,%0\n"
+	"	lda	%2,0\n"
+	"	bne	%1,2f\n"
+	"	or	$31,1,%1\n"
+	"	stl_c	%1,%0\n"
+	"	beq	%1,6f\n"
+	"	lda	%2,1\n"
+	"2:	mb\n"
+	".subsection 2\n"
+	"6:	br	1b\n"
+	".previous"
+	: "=m" (*lock), "=&r" (regx), "=&r" (success)
+	: "m" (*lock) : "memory");
+
+	return success;
+}
 
 static inline void _raw_write_unlock(rwlock_t * lock)
 {
diff -Nru a/include/asm-alpha/sysinfo.h b/include/asm-alpha/sysinfo.h
--- a/include/asm-alpha/sysinfo.h	2004-10-18 14:55:55 -07:00
+++ b/include/asm-alpha/sysinfo.h	2004-10-18 14:55:55 -07:00
@@ -18,6 +18,7 @@
 #define SSI_IEEE_FP_CONTROL		14
 #define SSI_IEEE_STATE_AT_SIGNAL	15
 #define SSI_IEEE_IGNORE_STATE_AT_SIGNAL	16
+#define SSI_IEEE_RAISE_EXCEPTION	1001	/* linux specific */
 
 #define SSIN_UACPROC			6
 
diff -Nru a/include/asm-alpha/system.h b/include/asm-alpha/system.h
--- a/include/asm-alpha/system.h	2004-10-18 14:56:33 -07:00
+++ b/include/asm-alpha/system.h	2004-10-18 14:56:33 -07:00
@@ -55,9 +55,9 @@
  */
 struct el_common {
 	unsigned int	size;		/* size in bytes of logout area */
-	int		sbz1	: 30;	/* should be zero */
-	int		err2	:  1;	/* second error */
-	int		retry	:  1;	/* retry flag */
+	unsigned int	sbz1	: 30;	/* should be zero */
+	unsigned int	err2	:  1;	/* second error */
+	unsigned int	retry	:  1;	/* retry flag */
 	unsigned int	proc_offset;	/* processor-specific offset */
 	unsigned int	sys_offset;	/* system-specific offset */
 	unsigned int	code;		/* machine check code */
diff -Nru a/include/asm-alpha/thread_info.h b/include/asm-alpha/thread_info.h
--- a/include/asm-alpha/thread_info.h	2004-10-18 14:57:03 -07:00
+++ b/include/asm-alpha/thread_info.h	2004-10-18 14:57:03 -07:00
@@ -19,7 +19,7 @@
 
 	struct exec_domain	*exec_domain;	/* execution domain */
 	mm_segment_t		addr_limit;	/* thread address space */
-	long			cpu;		/* current CPU */
+	unsigned		cpu;		/* current CPU */
 	int			preempt_count; /* 0 => preemptable, <0 => BUG */
 
 	int bpt_nsaved;
diff -Nru a/include/asm-alpha/tlbflush.h b/include/asm-alpha/tlbflush.h
--- a/include/asm-alpha/tlbflush.h	2004-10-18 14:55:46 -07:00
+++ b/include/asm-alpha/tlbflush.h	2004-10-18 14:55:46 -07:00
@@ -3,6 +3,7 @@
 
 #include <linux/config.h>
 #include <linux/mm.h>
+#include <asm/compiler.h>
 
 #ifndef __EXTERN_INLINE
 #define __EXTERN_INLINE extern inline
@@ -86,7 +87,7 @@
 static inline void
 flush_tlb_other(struct mm_struct *mm)
 {
-	long *mmc = &mm->context[smp_processor_id()];
+	unsigned long *mmc = &mm->context[smp_processor_id()];
 	/* Check it's not zero first to avoid cacheline ping pong
 	   when possible.  */
 	if (*mmc) *mmc = 0;
diff -Nru a/include/asm-alpha/uaccess.h b/include/asm-alpha/uaccess.h
--- a/include/asm-alpha/uaccess.h	2004-10-18 14:56:49 -07:00
+++ b/include/asm-alpha/uaccess.h	2004-10-18 14:56:49 -07:00
@@ -108,7 +108,6 @@
 ({									\
 	long __gu_err = -EFAULT, __gu_val = 0;				\
 	const __typeof__(*(ptr)) __user *__gu_addr = (ptr);		\
-	__chk_user_ptr(ptr);						\
 	if (__access_ok((unsigned long)__gu_addr,size,segment)) {	\
 		__gu_err = 0;						\
 		switch (size) {						\
@@ -223,7 +222,6 @@
 ({									\
 	long __pu_err = -EFAULT;					\
 	__typeof__(*(ptr)) __user *__pu_addr = (ptr);			\
-	__chk_user_ptr(ptr);						\
 	if (__access_ok((unsigned long)__pu_addr,size,segment)) {	\
 		__pu_err = 0;						\
 		switch (size) {						\
@@ -394,6 +392,10 @@
 	__chk_user_ptr(from);						\
 	__copy_tofrom_user_nocheck((to),(__force void *)(from),(n));	\
 })
+
+#define __copy_to_user_inatomic __copy_to_user
+#define __copy_from_user_inatomic __copy_from_user
+
 
 extern inline long
 copy_to_user(void __user *to, const void *from, long n)
diff -Nru a/include/asm-alpha/unistd.h b/include/asm-alpha/unistd.h
--- a/include/asm-alpha/unistd.h	2004-10-18 14:56:29 -07:00
+++ b/include/asm-alpha/unistd.h	2004-10-18 14:56:29 -07:00
@@ -373,8 +373,9 @@
 #define __NR_mq_timedreceive		435
 #define __NR_mq_notify			436
 #define __NR_mq_getsetattr		437
+#define __NR_waitid			438
 
-#define NR_SYSCALLS			438
+#define NR_SYSCALLS			439
 
 #if defined(__GNUC__)
 
@@ -617,7 +618,7 @@
 	return sys_read(fd, buf, nr);
 }
 
-extern long execve(char *, char **, char **);
+extern int execve(char *, char **, char **);
 
 static inline long setsid(void)
 {
diff -Nru a/include/asm-alpha/vga.h b/include/asm-alpha/vga.h
--- a/include/asm-alpha/vga.h	2004-10-18 14:56:20 -07:00
+++ b/include/asm-alpha/vga.h	2004-10-18 14:56:20 -07:00
@@ -15,24 +15,24 @@
 
 extern inline void scr_writew(u16 val, volatile u16 *addr)
 {
-	if (__is_ioaddr((unsigned long) addr))
-		__raw_writew(val, (unsigned long) addr);
+	if (__is_ioaddr(addr))
+		__raw_writew(val, (volatile u16 __iomem *) addr);
 	else
 		*addr = val;
 }
 
 extern inline u16 scr_readw(volatile const u16 *addr)
 {
-	if (__is_ioaddr((unsigned long) addr))
-		return __raw_readw((unsigned long) addr);
+	if (__is_ioaddr(addr))
+		return __raw_readw((volatile const u16 __iomem *) addr);
 	else
 		return *addr;
 }
 
 extern inline void scr_memsetw(u16 *s, u16 c, unsigned int count)
 {
-	if (__is_ioaddr((unsigned long) s))
-		memsetw_io(s, c, count);
+	if (__is_ioaddr(s))
+		memsetw_io((u16 __iomem *) s, c, count);
 	else
 		memsetw(s, c, count);
 }
@@ -43,9 +43,9 @@
 /* ??? These are currently only used for downloading character sets.  As
    such, they don't need memory barriers.  Is this all they are intended
    to be used for?  */
-#define vga_readb	readb
-#define vga_writeb	writeb
+#define vga_readb(a)	readb((u8 __iomem *)(a))
+#define vga_writeb(v,a)	writeb(v, (u8 __iomem *)(a))
 
-#define VGA_MAP_MEM(x)	((unsigned long) ioremap((x), 0))
+#define VGA_MAP_MEM(x)	((unsigned long) ioremap(x, 0))
 
 #endif
diff -Nru a/include/asm-arm/apm.h b/include/asm-arm/apm.h
--- a/include/asm-arm/apm.h	2004-10-18 14:57:04 -07:00
+++ b/include/asm-arm/apm.h	2004-10-18 14:57:04 -07:00
@@ -14,24 +14,7 @@
 #define ARM_ASM_SA1100_APM_H
 
 #include <linux/config.h>
-
-#ifdef CONFIG_APM
-
-
-#define APM_AC_OFFLINE 0
-#define APM_AC_ONLINE 1
-#define APM_AC_BACKUP 2
-#define APM_AC_UNKNOWN 0xFF
-
-#define APM_BATTERY_STATUS_HIGH 0
-#define APM_BATTERY_STATUS_LOW  1
-#define APM_BATTERY_STATUS_CRITICAL 2
-#define APM_BATTERY_STATUS_CHARGING 3
-#define APM_BATTERY_STATUS_UNKNOWN 0xFF
-
-#define APM_BATTERY_LIFE_UNKNOWN 0xFFFF
-#define APM_BATTERY_LIFE_MINUTES 0x8000
-#define APM_BATTERY_LIFE_VALUE_MASK 0x7FFF
+#include <linux/apm_bios.h>
 
 /*
  * This structure gets filled in by the machine specific 'get_power_status'
@@ -39,18 +22,44 @@
  */
 struct apm_power_info {
 	unsigned char	ac_line_status;
+#define APM_AC_OFFLINE			0
+#define APM_AC_ONLINE			1
+#define APM_AC_BACKUP			2
+#define APM_AC_UNKNOWN			0xff
+
 	unsigned char	battery_status;
+#define APM_BATTERY_STATUS_HIGH		0
+#define APM_BATTERY_STATUS_LOW		1
+#define APM_BATTERY_STATUS_CRITICAL	2
+#define APM_BATTERY_STATUS_CHARGING	3
+#define APM_BATTERY_STATUS_NOT_PRESENT	4
+#define APM_BATTERY_STATUS_UNKNOWN	0xff
+
 	unsigned char	battery_flag;
-	unsigned char	battery_life;
+#define APM_BATTERY_FLAG_HIGH		(1 << 0)
+#define APM_BATTERY_FLAG_LOW		(1 << 1)
+#define APM_BATTERY_FLAG_CRITICAL	(1 << 2)
+#define APM_BATTERY_FLAG_CHARGING	(1 << 3)
+#define APM_BATTERY_FLAG_NOT_PRESENT	(1 << 7)
+#define APM_BATTERY_FLAG_UNKNOWN	0xff
+
+	int		battery_life;
 	int		time;
 	int		units;
+#define APM_UNITS_MINS			0
+#define APM_UNITS_SECS			1
+#define APM_UNITS_UNKNOWN		-1
+
 };
 
 /*
  * This allows machines to provide their own "apm get power status" function.
  */
 extern void (*apm_get_power_status)(struct apm_power_info *);
-#endif
 
+/*
+ * Queue an event (APM_SYS_SUSPEND or APM_CRITICAL_SUSPEND)
+ */
+void apm_queue_event(apm_event_t event);
 
 #endif
diff -Nru a/include/asm-arm/arch-cl7500/uncompress.h b/include/asm-arm/arch-cl7500/uncompress.h
--- a/include/asm-arm/arch-cl7500/uncompress.h	2004-10-18 14:56:49 -07:00
+++ b/include/asm-arm/arch-cl7500/uncompress.h	2004-10-18 14:56:49 -07:00
@@ -16,7 +16,7 @@
 /*
  * This does not append a newline
  */
-static void puts(const char *s)
+static void putstr(const char *s)
 {
 	while (*s) {
 		putc(*s);
diff -Nru a/include/asm-arm/arch-clps711x/uncompress.h b/include/asm-arm/arch-clps711x/uncompress.h
--- a/include/asm-arm/arch-clps711x/uncompress.h	2004-10-18 14:56:20 -07:00
+++ b/include/asm-arm/arch-clps711x/uncompress.h	2004-10-18 14:56:20 -07:00
@@ -40,7 +40,7 @@
 /*
  * This does not append a newline
  */
-static void puts(const char *s)
+static void putstr(const char *s)
 {
 	char c;
 
diff -Nru a/include/asm-arm/arch-ebsa110/param.h b/include/asm-arm/arch-ebsa110/param.h
--- a/include/asm-arm/arch-ebsa110/param.h	2004-10-18 14:55:53 -07:00
+++ b/include/asm-arm/arch-ebsa110/param.h	2004-10-18 14:55:53 -07:00
@@ -1,4 +1,4 @@
 /*
  *  linux/include/asm-arm/arch-ebsa110/param.h
  */
-#define __KERNEL_HZ	200
+#define HZ	200
diff -Nru a/include/asm-arm/arch-ebsa110/uncompress.h b/include/asm-arm/arch-ebsa110/uncompress.h
--- a/include/asm-arm/arch-ebsa110/uncompress.h	2004-10-18 14:57:05 -07:00
+++ b/include/asm-arm/arch-ebsa110/uncompress.h	2004-10-18 14:57:05 -07:00
@@ -11,7 +11,7 @@
 /*
  * This does not append a newline
  */
-static void puts(const char *s)
+static void putstr(const char *s)
 {
 	unsigned long tmp1, tmp2;
 	__asm__ __volatile__(
diff -Nru a/include/asm-arm/arch-ebsa285/uncompress.h b/include/asm-arm/arch-ebsa285/uncompress.h
--- a/include/asm-arm/arch-ebsa285/uncompress.h	2004-10-18 14:57:04 -07:00
+++ b/include/asm-arm/arch-ebsa285/uncompress.h	2004-10-18 14:57:04 -07:00
@@ -29,7 +29,7 @@
 /*
  * This does not append a newline
  */
-static void puts(const char *s)
+static void putstr(const char *s)
 {
 	while (*s) {
 		putc(*s);
diff -Nru a/include/asm-arm/arch-epxa10db/uncompress.h b/include/asm-arm/arch-epxa10db/uncompress.h
--- a/include/asm-arm/arch-epxa10db/uncompress.h	2004-10-18 14:56:28 -07:00
+++ b/include/asm-arm/arch-epxa10db/uncompress.h	2004-10-18 14:56:28 -07:00
@@ -26,7 +26,7 @@
 /*
  * This does not append a newline
  */
-static void puts(const char *s)
+static void putstr(const char *s)
 {
 	while (*s) {
 		while ((*UART_TSR(EXC_UART00_BASE) &
diff -Nru a/include/asm-arm/arch-h720x/boards.h b/include/asm-arm/arch-h720x/boards.h
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/include/asm-arm/arch-h720x/boards.h	2004-10-18 14:57:22 -07:00
@@ -0,0 +1,53 @@
+/*
+ * linux/include/asm-arm/arch-h720x/boards.h
+ *
+ * Copyright (C) 2003 Thomas Gleixner <tglx@linutronix.de>
+ *           (C) 2003 Robert Schwebel <r.schwebel@pengutronix.de>
+ *
+ * This file contains the board specific defines for various devices
+ *
+ * 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.
+ */
+
+#ifndef __ASM_ARCH_HARDWARE_INCMACH_H
+#error Do not include this file directly. Include asm/hardware.h instead !
+#endif
+
+/* Hynix H7202 developer board specific device defines */
+#ifdef CONFIG_ARCH_H7202
+
+/* FLASH */
+#define FLASH_VIRT		0xd0000000
+#define FLASH_PHYS		0x00000000
+#define FLASH_SIZE		0x02000000
+
+/* onboard LAN controller */
+# define ETH0_PHYS		0x08000000
+
+/* Touch screen defines */
+/* GPIO Port */
+#define PEN_GPIO		GPIO_B_VIRT
+/* Bitmask for pen down interrupt */
+#define PEN_INT_BIT		(1<<7)
+/* Bitmask for pen up interrupt */
+#define PEN_ENA_BIT		(1<<6)
+/* pen up interrupt */
+#define IRQ_PEN			IRQ_MUX_GPIOB(7)
+
+#endif
+
+/* Hynix H7201 developer board specific device defines */
+#if defined (CONFIG_ARCH_H7201)
+/* ROM DISK SPACE */
+#define ROM_DISK_BASE           0xc1800000
+#define ROM_DISK_START          0x41800000
+#define ROM_DISK_SIZE           0x00700000
+
+/* SRAM DISK SPACE */
+#define SRAM_DISK_BASE          0xf1000000
+#define SRAM_DISK_START         0x04000000
+#define SRAM_DISK_SIZE          0x00400000
+#endif
+
diff -Nru a/include/asm-arm/arch-h720x/dma.h b/include/asm-arm/arch-h720x/dma.h
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/include/asm-arm/arch-h720x/dma.h	2004-10-18 14:57:23 -07:00
@@ -0,0 +1,26 @@
+/*
+ * linux/include/asm-arm/arch-h720x/dma.h
+ *
+ * Architecture DMA routes
+ *
+ * Copyright (C) 1997.1998 Russell King
+ */
+#ifndef __ASM_ARCH_DMA_H
+#define __ASM_ARCH_DMA_H
+
+/*
+ * This is the maximum DMA address that can be DMAd to.
+ * There should not be more than (0xd0000000 - 0xc0000000)
+ * bytes of RAM.
+ */
+#define MAX_DMA_ADDRESS		0xd0000000
+
+#if defined (CONFIG_CPU_H7201)
+#define MAX_DMA_CHANNELS	3
+#elif defined (CONFIG_CPU_H7202)
+#define MAX_DMA_CHANNELS	4
+#else
+#error processor definition missmatch
+#endif
+
+#endif /* __ASM_ARCH_DMA_H */
diff -Nru a/include/asm-arm/arch-h720x/h7201-regs.h b/include/asm-arm/arch-h720x/h7201-regs.h
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/include/asm-arm/arch-h720x/h7201-regs.h	2004-10-18 14:57:21 -07:00
@@ -0,0 +1,67 @@
+/*
+ * linux/include/asm-arm/arch-h720x/h7201-regs.h
+ *
+ * Copyright (C) 2000 Jungjun Kim, Hynix Semiconductor Inc.
+ *           (C) 2003 Thomas Gleixner <tglx@linutronix.de>
+ *           (C) 2003 Robert Schwebel <r.schwebel@pengutronix.de>
+ *           (C) 2004 Sascha Hauer    <s.hauer@pengutronix.de>
+ *
+ * This file contains the hardware definitions of the h720x processors
+ *
+ * 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.
+ *
+ * Do not add implementations specific defines here. This files contains
+ * only defines of the onchip peripherals. Add those defines to boards.h,
+ * which is included by this file.
+ */
+
+#define SERIAL2_VIRT 		(IO_VIRT + 0x50100)
+#define SERIAL3_VIRT 		(IO_VIRT + 0x50200)
+
+/*
+ * PCMCIA
+ */
+#define PCMCIA0_ATT_BASE        0xe5000000
+#define PCMCIA0_ATT_SIZE        0x00200000
+#define PCMCIA0_ATT_START       0x20000000
+#define PCMCIA0_MEM_BASE        0xe5200000
+#define PCMCIA0_MEM_SIZE        0x00200000
+#define PCMCIA0_MEM_START       0x24000000
+#define PCMCIA0_IO_BASE         0xe5400000
+#define PCMCIA0_IO_SIZE         0x00200000
+#define PCMCIA0_IO_START        0x28000000
+
+#define PCMCIA1_ATT_BASE        0xe5600000
+#define PCMCIA1_ATT_SIZE        0x00200000
+#define PCMCIA1_ATT_START       0x30000000
+#define PCMCIA1_MEM_BASE        0xe5800000
+#define PCMCIA1_MEM_SIZE        0x00200000
+#define PCMCIA1_MEM_START       0x34000000
+#define PCMCIA1_IO_BASE         0xe5a00000
+#define PCMCIA1_IO_SIZE         0x00200000
+#define PCMCIA1_IO_START        0x38000000
+
+#define PRIME3C_BASE            0xf0050000
+#define PRIME3C_SIZE            0x00001000
+#define PRIME3C_START           0x10000000
+
+/* VGA Controller */
+#define VGA_RAMBASE 		0x50
+#define VGA_TIMING0 		0x60
+#define VGA_TIMING1 		0x64
+#define VGA_TIMING2 		0x68
+#define VGA_TIMING3 		0x6c
+
+#define LCD_CTRL_VGA_ENABLE   	0x00000100
+#define LCD_CTRL_VGA_BPP_MASK 	0x00000600
+#define LCD_CTRL_VGA_4BPP    	0x00000000
+#define LCD_CTRL_VGA_8BPP    	0x00000200
+#define LCD_CTRL_VGA_16BPP   	0x00000300
+#define LCD_CTRL_SHARE_DMA    	0x00000800
+#define LCD_CTRL_VDE          	0x00100000
+#define LCD_CTRL_LPE          	0x00400000	/* LCD Power enable */
+#define LCD_CTRL_BLE          	0x00800000	/* LCD backlight enable */
+
+#define VGA_PALETTE_BASE	(IO_VIRT + 0x10800)
diff -Nru a/include/asm-arm/arch-h720x/h7202-regs.h b/include/asm-arm/arch-h720x/h7202-regs.h
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/include/asm-arm/arch-h720x/h7202-regs.h	2004-10-18 14:57:23 -07:00
@@ -0,0 +1,151 @@
+/*
+ * linux/include/asm-arm/arch-h720x/h7202-regs.h
+ *
+ * Copyright (C) 2000 Jungjun Kim, Hynix Semiconductor Inc.
+ *           (C) 2003 Thomas Gleixner <tglx@linutronix.de>
+ *           (C) 2003 Robert Schwebel <r.schwebel@pengutronix.de>
+ *           (C) 2004 Sascha Hauer    <s.hauer@pengutronix.de>
+ *
+ * This file contains the hardware definitions of the h720x processors
+ *
+ * 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.
+ *
+ * Do not add implementations specific defines here. This files contains
+ * only defines of the onchip peripherals. Add those defines to boards.h,
+ * which is included by this file.
+ */
+
+#define SERIAL2_VIRT 		(IO_VIRT + 0x2d000)
+#define SERIAL3_VIRT 		(IO_VIRT + 0x2e000)
+
+/* Matrix Keyboard Controller */
+#define KBD_VIRT		(IO_VIRT + 0x22000)
+#define KBD_KBCR		0x00
+#define KBD_KBSC		0x04
+#define KBD_KBTR		0x08
+#define KBD_KBVR0		0x0C
+#define KBD_KBVR1		0x10
+#define KBD_KBSR		0x18
+
+#define KBD_KBCR_SCANENABLE	(1 << 7)
+#define KBD_KBCR_NPOWERDOWN	(1 << 2)
+#define KBD_KBCR_CLKSEL_MASK	(3)
+#define KBD_KBCR_CLKSEL_PCLK2	0x0
+#define KBD_KBCR_CLKSEL_PCLK128	0x1
+#define KBD_KBCR_CLKSEL_PCLK256	0x2
+#define KBD_KBCR_CLKSEL_PCLK512	0x3
+
+#define KBD_KBSR_INTR		(1 << 0)
+#define KBD_KBSR_WAKEUP		(1 << 1)
+
+/* USB device controller */
+
+#define USBD_BASE		(IO_VIRT + 0x12000)
+#define USBD_LENGTH		0x3C
+
+#define USBD_GCTRL		0x00
+#define USBD_EPCTRL		0x04
+#define USBD_INTMASK		0x08
+#define USBD_INTSTAT		0x0C
+#define USBD_PWR		0x10
+#define USBD_DMARXTX		0x14
+#define USBD_DEVID		0x18
+#define USBD_DEVCLASS		0x1C
+#define USBD_INTCLASS		0x20
+#define USBD_SETUP0		0x24
+#define USBD_SETUP1		0x28
+#define USBD_ENDP0RD		0x2C
+#define USBD_ENDP0WT		0x30
+#define USBD_ENDP1RD		0x34
+#define USBD_ENDP2WT		0x38
+
+/* PS/2 port */
+#define PSDATA 0x00
+#define PSSTAT 0x04
+#define PSSTAT_TXEMPTY (1<<0)
+#define PSSTAT_TXBUSY (1<<1)
+#define PSSTAT_RXFULL (1<<2)
+#define PSSTAT_RXBUSY (1<<3)
+#define PSSTAT_CLKIN (1<<4)
+#define PSSTAT_DATAIN (1<<5)
+#define PSSTAT_PARITY (1<<6)
+
+#define PSCONF 0x08
+#define PSCONF_ENABLE (1<<0)
+#define PSCONF_TXINTEN (1<<2)
+#define PSCONF_RXINTEN (1<<3)
+#define PSCONF_FORCECLKLOW (1<<4)
+#define PSCONF_FORCEDATLOW (1<<5)
+#define PSCONF_LCE (1<<6)
+
+#define PSINTR 0x0C
+#define PSINTR_TXINT (1<<0)
+#define PSINTR_RXINT (1<<1)
+#define PSINTR_PAR (1<<2)
+#define PSINTR_RXTO (1<<3)
+#define PSINTR_TXTO (1<<4)
+
+#define PSTDLO 0x10 /* clk low before start transmission */
+#define PSTPRI 0x14 /* PRI clock */
+#define PSTXMT 0x18 /* maximum transmission time */
+#define PSTREC 0x20 /* maximum receive time */
+#define PSPWDN 0x3c
+
+/* ADC converter */
+#define ADC_BASE 		(IO_VIRT + 0x29000)
+#define ADC_CR 			0x00
+#define ADC_TSCTRL 		0x04
+#define ADC_BT_CTRL 		0x08
+#define ADC_MC_CTRL		0x0C
+#define ADC_STATUS		0x10
+
+/* ADC control register bits */
+#define ADC_CR_PW_CTRL 		0x80
+#define ADC_CR_DIRECTC		0x04
+#define ADC_CR_CONTIME_NO	0x00
+#define ADC_CR_CONTIME_2	0x04
+#define ADC_CR_CONTIME_4	0x08
+#define ADC_CR_CONTIME_ADE	0x0c
+#define ADC_CR_LONGCALTIME	0x01
+
+/* ADC touch panel register bits */
+#define ADC_TSCTRL_ENABLE 	0x80
+#define ADC_TSCTRL_INTR   	0x40
+#define	ADC_TSCTRL_SWBYPSS	0x20
+#define ADC_TSCTRL_SWINVT	0x10
+#define ADC_TSCTRL_S400   	0x03
+#define ADC_TSCTRL_S200   	0x02
+#define ADC_TSCTRL_S100   	0x01
+#define ADC_TSCTRL_S50    	0x00
+
+/* ADC Interrupt Status Register bits */
+#define ADC_STATUS_TS_BIT	0x80
+#define ADC_STATUS_MBT_BIT	0x40
+#define ADC_STATUS_BBT_BIT	0x20
+#define ADC_STATUS_MIC_BIT	0x10
+
+/* Touch data registers */
+#define ADC_TS_X0X1  		0x30
+#define ADC_TS_X2X3		0x34
+#define ADC_TS_Y0Y1		0x38
+#define ADC_TS_Y2Y3  		0x3c
+#define ADC_TS_X4X5  		0x40
+#define ADC_TS_X6X7  		0x44
+#define ADC_TS_Y4Y5		0x48
+#define ADC_TS_Y6Y7		0x50
+
+/* battery data */
+#define ADC_MB_DATA		0x54
+#define ADC_BB_DATA		0x58
+
+/* Sound data register */
+#define ADC_SD_DAT0 		0x60
+#define ADC_SD_DAT1		0x64
+#define ADC_SD_DAT2		0x68
+#define ADC_SD_DAT3		0x6c
+#define ADC_SD_DAT4		0x70
+#define ADC_SD_DAT5		0x74
+#define ADC_SD_DAT6		0x78
+#define ADC_SD_DAT7		0x7c
diff -Nru a/include/asm-arm/arch-h720x/hardware.h b/include/asm-arm/arch-h720x/hardware.h
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/include/asm-arm/arch-h720x/hardware.h	2004-10-18 14:57:23 -07:00
@@ -0,0 +1,182 @@
+/*
+ * linux/include/asm-arm/arch-h720x/hardware.h
+ *
+ * Copyright (C) 2000 Jungjun Kim, Hynix Semiconductor Inc.
+ *           (C) 2003 Thomas Gleixner <tglx@linutronix.de>
+ *           (C) 2003 Robert Schwebel <r.schwebel@pengutronix.de>
+ *
+ * This file contains the hardware definitions of the h720x processors
+ *
+ * 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.
+ *
+ * Do not add implementations specific defines here. This files contains
+ * only defines of the onchip peripherals. Add those defines to boards.h,
+ * which is included by this file.
+ */
+
+#ifndef __ASM_ARCH_HARDWARE_H
+#define __ASM_ARCH_HARDWARE_H
+
+#define IOCLK (3686400L)
+
+/* Onchip peripherals */
+
+#define IO_VIRT			0xf0000000	/* IO peripherals */
+#define IO_PHYS			0x80000000
+#define IO_SIZE			0x00050000
+
+#ifdef CONFIG_CPU_H7202
+#include "h7202-regs.h"
+#elif defined CONFIG_CPU_H7201
+#include "h7201-regs.h"
+#else
+#error machine definition mismatch
+#endif
+
+/* Macro to access the CPU IO */
+#define CPU_IO(x) (*(volatile u32*)(x))
+
+/* Macro to access general purpose regs (base, offset) */
+#define CPU_REG(x,y) CPU_IO(x+y)
+
+/* Macro to access irq related regs */
+#define IRQ_REG(x) CPU_REG(IRQC_VIRT,x)
+
+/* CPU registers */
+/* general purpose I/O */
+#define GPIO_VIRT(x)		(IO_VIRT + 0x23000 + ((x)<<5))
+#define GPIO_A_VIRT		(GPIO_VIRT(0))
+#define GPIO_B_VIRT		(GPIO_VIRT(1))
+#define GPIO_C_VIRT		(GPIO_VIRT(2))
+#define GPIO_D_VIRT		(GPIO_VIRT(3))
+#define GPIO_E_VIRT		(GPIO_VIRT(4))
+#define GPIO_AMULSEL		(GPIO_VIRT + 0xA4)
+/* Register offsets general purpose I/O */
+#define GPIO_DATA		0x00
+#define GPIO_DIR		0x04
+#define GPIO_MASK		0x08
+#define GPIO_STAT		0x0C
+#define GPIO_EDGE		0x10
+#define GPIO_CLR		0x14
+#define GPIO_POL		0x18
+#define GPIO_EN			0x1C
+
+/*interrupt controller */
+#define IRQC_VIRT		(IO_VIRT + 0x24000)
+/* register offset interrupt controller */
+#define IRQC_IER		0x00
+#define IRQC_ISR		0x04
+
+/* timer unit */
+#define TIMER_VIRT		(IO_VIRT + 0x25000)
+/* Register offsets timer unit */
+#define TM0_PERIOD   		0x00
+#define TM0_COUNT    		0x08
+#define TM0_CTRL     		0x10
+#define TM1_PERIOD   		0x20
+#define TM1_COUNT    		0x28
+#define TM1_CTRL     		0x30
+#define TM2_PERIOD   		0x40
+#define TM2_COUNT    		0x48
+#define TM2_CTRL     		0x50
+#define TIMER_TOPCTRL		0x60
+#define TIMER_TOPSTAT		0x64
+#define T64_COUNTL		0x80
+#define T64_COUNTH		0x84
+#define T64_CTRL		0x88
+#define T64_BASEL		0x94
+#define T64_BASEH		0x98
+/* Bitmaks timer unit TOPSTAT reg */
+#define TSTAT_T0INT		0x1
+#define TSTAT_T1INT		0x2
+#define TSTAT_T2INT		0x4
+#define TSTAT_T3INT		0x8
+/* Bit description of TMx_CTRL register */
+#define TM_START  		0x1
+#define TM_REPEAT 		0x2
+#define TM_RESET  		0x4
+/* Bit description of TIMER_CTRL register */
+#define ENABLE_TM0_INTR  	0x1
+#define ENABLE_TM1_INTR  	0x2
+#define ENABLE_TM2_INTR  	0x4
+#define TIMER_ENABLE_BIT 	0x8
+#define ENABLE_TIMER64   	0x10
+#define ENABLE_TIMER64_INT	0x20
+
+/* PMU & PLL */
+#define PMU_BASE 		(IO_VIRT + 0x1000)
+#define PMU_MODE		0x00
+#define PMU_STAT   		0x20
+#define PMU_PLL_CTRL 		0x28
+
+/* PMU Mode bits */
+#define PMU_MODE_SLOW		0x00
+#define PMU_MODE_RUN		0x01
+#define PMU_MODE_IDLE		0x02
+#define PMU_MODE_SLEEP		0x03
+#define PMU_MODE_INIT		0x04
+#define PMU_MODE_DEEPSLEEP	0x07
+#define PMU_MODE_WAKEUP		0x08
+
+/* PMU ... */
+#define PLL_2_EN		0x8000
+#define PLL_1_EN		0x4000
+#define PLL_3_MUTE		0x0080
+
+/* Control bits for PMU/ PLL */
+#define PMU_WARMRESET		0x00010000
+#define PLL_CTRL_MASK23		0x000080ff
+
+/* LCD Controller */
+#define LCD_BASE 		(IO_VIRT + 0x10000)
+#define LCD_CTRL 		0x00
+#define LCD_STATUS		0x04
+#define LCD_STATUS_M		0x08
+#define LCD_INTERRUPT		0x0C
+#define LCD_DBAR		0x10
+#define LCD_DCAR		0x14
+#define LCD_TIMING0 		0x20
+#define LCD_TIMING1 		0x24
+#define LCD_TIMING2 		0x28
+#define LCD_TEST		0x40
+
+/* LCD Control Bits */
+#define LCD_CTRL_LCD_ENABLE   	0x00000001
+/* Bits per pixel */
+#define LCD_CTRL_LCD_BPP_MASK 	0x00000006
+#define LCD_CTRL_LCD_4BPP    	0x00000000
+#define LCD_CTRL_LCD_8BPP    	0x00000002
+#define LCD_CTRL_LCD_16BPP   	0x00000004
+#define LCD_CTRL_LCD_BW		0x00000008
+#define LCD_CTRL_LCD_TFT	0x00000010
+#define LCD_CTRL_BGR		0x00001000
+#define LCD_CTRL_LCD_VCOMP	0x00080000
+#define LCD_CTRL_LCD_MONO8	0x00200000
+#define LCD_CTRL_LCD_PWR	0x00400000
+#define LCD_CTRL_LCD_BLE	0x00800000
+#define LCD_CTRL_LDBUSEN	0x01000000
+
+/* Palette */
+#define LCD_PALETTE_BASE 	(IO_VIRT + 0x10400)
+
+/* Serial ports */
+#define SERIAL0_VIRT 		(IO_VIRT + 0x20000)
+#define SERIAL1_VIRT 		(IO_VIRT + 0x21000)
+
+#define SERIAL0_BASE		SERIAL0_VIRT
+#define SERIAL1_BASE		SERIAL1_VIRT
+#define SERIAL2_BASE		SERIAL2_VIRT
+#define SERIAL3_BASE		SERIAL3_VIRT
+
+
+/* General defines to pacify gcc */
+#define PCIO_BASE 		(0)	/* for inb, outb and friends */
+#define PCIO_VIRT		PCIO_BASE
+
+#define __ASM_ARCH_HARDWARE_INCMACH_H
+#include "boards.h"
+#undef __ASM_ARCH_HARDWARE_INCMACH_H
+
+#endif				/* __ASM_ARCH_HARDWARE_H */
diff -Nru a/include/asm-arm/arch-h720x/io.h b/include/asm-arm/arch-h720x/io.h
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/include/asm-arm/arch-h720x/io.h	2004-10-18 14:57:21 -07:00
@@ -0,0 +1,24 @@
+/*
+ * linux/include/asm-arm/arch-h720x/io.h
+ *
+ * Copyright (C) 2000 Steve Hill (sjhill@cotw.com)
+ *
+ * Changelog:
+ *
+ *  09-19-2001	JJKIM
+ *  		Created from linux/include/asm-arm/arch-l7200/io.h
+ *
+ *  03-27-2003  Robert Schwebel <r.schwebel@pengutronix.de>:
+ *  		re-unified header files for h720x
+ */
+#ifndef __ASM_ARM_ARCH_IO_H
+#define __ASM_ARM_ARCH_IO_H
+
+#include <asm/arch/hardware.h>
+
+#define IO_SPACE_LIMIT 0xffffffff
+
+#define __io(a) (a)
+#define __mem_pci(a) (a)
+
+#endif
diff -Nru a/include/asm-arm/arch-h720x/irq.h b/include/asm-arm/arch-h720x/irq.h
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/include/asm-arm/arch-h720x/irq.h	2004-10-18 14:57:23 -07:00
@@ -0,0 +1,14 @@
+/*
+ * include/asm-arm/arch-h720x/irq.h
+ *
+ * Copyright (C) 2000-2002 Jungjun Kim
+ *           (C) 2003 Robert Schwebel <r.schwebel@pengutronix.de>
+ *           (C) 2003 Thomas Gleixner <tglx@linutronix.de>
+ */
+
+#ifndef __ASM_ARCH_IRQ_H
+#define __ASM_ARCH_IRQ_H
+
+extern void __init h720x_init_irq (void);
+
+#endif /* __ASM_ARCH_IRQ_H */
diff -Nru a/include/asm-arm/arch-h720x/irqs.h b/include/asm-arm/arch-h720x/irqs.h
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/include/asm-arm/arch-h720x/irqs.h	2004-10-18 14:57:24 -07:00
@@ -0,0 +1,116 @@
+/*
+ * linux/include/asm-arm/arch-h720x/irqs.h
+ *
+ * Copyright (C) 2000 Jungjun Kim
+ *           (C) 2003 Robert Schwebel <r.schwebel@pengutronix.de>
+ *           (C) 2003 Thomas Gleixner <tglx@linutronix.de>
+ *
+ */
+
+#ifndef __ASM_ARCH_IRQS_H
+#define __ASM_ARCH_IRQS_H
+
+#if defined (CONFIG_CPU_H7201)
+
+#define IRQ_PMU		0		/* 0x000001 */
+#define IRQ_DMA		1 		/* 0x000002 */
+#define IRQ_LCD		2		/* 0x000004 */
+#define IRQ_VGA		3 		/* 0x000008 */
+#define IRQ_PCMCIA1 	4 		/* 0x000010 */
+#define IRQ_PCMCIA2 	5 		/* 0x000020 */
+#define IRQ_AFE		6 		/* 0x000040 */
+#define IRQ_AIC		7 		/* 0x000080 */
+#define IRQ_KEYBOARD 	8 		/* 0x000100 */
+#define IRQ_TIMER0	9 		/* 0x000200 */
+#define IRQ_RTC		10		/* 0x000400 */
+#define IRQ_SOUND	11		/* 0x000800 */
+#define IRQ_USB		12		/* 0x001000 */
+#define IRQ_IrDA 	13		/* 0x002000 */
+#define IRQ_UART0	14		/* 0x004000 */
+#define IRQ_UART1	15		/* 0x008000 */
+#define IRQ_SPI		16		/* 0x010000 */
+#define IRQ_GPIOA 	17		/* 0x020000 */
+#define IRQ_GPIOB	18		/* 0x040000 */
+#define IRQ_GPIOC	19		/* 0x080000 */
+#define IRQ_GPIOD	20		/* 0x100000 */
+#define IRQ_CommRX	21		/* 0x200000 */
+#define IRQ_CommTX	22		/* 0x400000 */
+#define IRQ_Soft	23		/* 0x800000 */
+
+#define NR_GLBL_IRQS	24
+
+#define IRQ_CHAINED_GPIOA(x)  (NR_GLBL_IRQS + x)
+#define IRQ_CHAINED_GPIOB(x)  (IRQ_CHAINED_GPIOA(32) + x)
+#define IRQ_CHAINED_GPIOC(x)  (IRQ_CHAINED_GPIOB(32) + x)
+#define IRQ_CHAINED_GPIOD(x)  (IRQ_CHAINED_GPIOC(32) + x)
+#define NR_IRQS               IRQ_CHAINED_GPIOD(32)
+
+/* Enable mask for multiplexed interrupts */
+#define IRQ_ENA_MUX	(1<<IRQ_GPIOA) | (1<<IRQ_GPIOB) \
+			| (1<<IRQ_GPIOC) | (1<<IRQ_GPIOD)
+
+
+#elif defined (CONFIG_CPU_H7202)
+
+#define IRQ_PMU		0		/* 0x00000001 */
+#define IRQ_DMA		1		/* 0x00000002 */
+#define IRQ_LCD		2		/* 0x00000004 */
+#define IRQ_SOUND	3		/* 0x00000008 */
+#define IRQ_I2S		4		/* 0x00000010 */
+#define IRQ_USB 	5		/* 0x00000020 */
+#define IRQ_MMC 	6		/* 0x00000040 */
+#define IRQ_RTC 	7		/* 0x00000080 */
+#define IRQ_UART0 	8		/* 0x00000100 */
+#define IRQ_UART1 	9		/* 0x00000200 */
+#define IRQ_UART2 	10		/* 0x00000400 */
+#define IRQ_UART3 	11		/* 0x00000800 */
+#define IRQ_KBD 	12		/* 0x00001000 */
+#define IRQ_PS2 	13		/* 0x00002000 */
+#define IRQ_AIC 	14		/* 0x00004000 */
+#define IRQ_TIMER0 	15		/* 0x00008000 */
+#define IRQ_TIMERX 	16		/* 0x00010000 */
+#define IRQ_WDT 	17		/* 0x00020000 */
+#define IRQ_CAN0 	18		/* 0x00040000 */
+#define IRQ_CAN1 	19		/* 0x00080000 */
+#define IRQ_EXT0 	20		/* 0x00100000 */
+#define IRQ_EXT1 	21		/* 0x00200000 */
+#define IRQ_GPIOA 	22		/* 0x00400000 */
+#define IRQ_GPIOB 	23		/* 0x00800000 */
+#define IRQ_GPIOC 	24		/* 0x01000000 */
+#define IRQ_GPIOD 	25		/* 0x02000000 */
+#define IRQ_GPIOE 	26		/* 0x04000000 */
+#define IRQ_COMMRX 	27		/* 0x08000000 */
+#define IRQ_COMMTX 	28		/* 0x10000000 */
+#define IRQ_SMC 	29		/* 0x20000000 */
+#define IRQ_Soft 	30		/* 0x40000000 */
+#define IRQ_RESERVED1 	31		/* 0x80000000 */
+#define NR_GLBL_IRQS	32
+
+#define NR_TIMERX_IRQS	3
+
+#define IRQ_CHAINED_GPIOA(x)  (NR_GLBL_IRQS + x)
+#define IRQ_CHAINED_GPIOB(x)  (IRQ_CHAINED_GPIOA(32) + x)
+#define IRQ_CHAINED_GPIOC(x)  (IRQ_CHAINED_GPIOB(32) + x)
+#define IRQ_CHAINED_GPIOD(x)  (IRQ_CHAINED_GPIOC(32) + x)
+#define IRQ_CHAINED_GPIOE(x)  (IRQ_CHAINED_GPIOD(32) + x)
+#define IRQ_CHAINED_TIMERX(x) (IRQ_CHAINED_GPIOE(32) + x)
+#define IRQ_TIMER1            (IRQ_CHAINED_TIMERX(0))
+#define IRQ_TIMER2            (IRQ_CHAINED_TIMERX(1))
+#define IRQ_TIMER64B          (IRQ_CHAINED_TIMERX(2))
+
+#define NR_IRQS		(IRQ_CHAINED_TIMERX(NR_TIMERX_IRQS))
+
+/* Enable mask for multiplexed interrupts */
+#define IRQ_ENA_MUX	(1<<IRQ_TIMERX) | (1<<IRQ_GPIOA) | (1<<IRQ_GPIOB) | \
+			(1<<IRQ_GPIOC) 	| (1<<IRQ_GPIOD) | (1<<IRQ_GPIOE) | \
+			(1<<IRQ_TIMERX)
+
+#else
+#error cpu definition mismatch
+#endif
+
+/* decode irq number to register number */
+#define IRQ_TO_REGNO(irq) ((irq - NR_GLBL_IRQS) >> 5)
+#define IRQ_TO_BIT(irq) (1 << ((irq - NR_GLBL_IRQS) % 32))
+
+#endif
diff -Nru a/include/asm-arm/arch-h720x/memory.h b/include/asm-arm/arch-h720x/memory.h
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/include/asm-arm/arch-h720x/memory.h	2004-10-18 14:57:21 -07:00
@@ -0,0 +1,31 @@
+/*
+ * linux/include/asm-arm/arch-h720x/memory.h
+ *
+ * Copyright (c) 2000 Jungjun Kim
+ *
+ */
+#ifndef __ASM_ARCH_MEMORY_H
+#define __ASM_ARCH_MEMORY_H
+
+/*
+ * Page offset:
+ *    ( 0xc0000000UL )
+ */
+#define PHYS_OFFSET	(0x40000000UL)
+
+/*
+ * Virtual view <-> DMA view memory address translations
+ * virt_to_bus: Used to translate the virtual address to an
+ *              address suitable to be passed to set_dma_addr
+ * bus_to_virt: Used to convert an address for DMA operations
+ *              to an address that the kernel can use.
+ *
+ * There is something to do here later !, Mar 2000, Jungjun Kim
+ */
+
+#define __virt_to_bus__is_a_macro
+#define __virt_to_bus(x)	__virt_to_phys(x)
+#define __bus_to_virt__is_a_macro
+#define __bus_to_virt(x)	__phys_to_virt(x)
+
+#endif
diff -Nru a/include/asm-arm/arch-h720x/param.h b/include/asm-arm/arch-h720x/param.h
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/include/asm-arm/arch-h720x/param.h	2004-10-18 14:57:23 -07:00
@@ -0,0 +1,10 @@
+/*
+ * linux/include/asm-arm/arch-h720x/param.h
+ *
+ * Copyright (C) 2000 Jungjun Kim
+ */
+
+#ifndef __ASM_ARCH_PARAM_H
+#define __ASM_ARCH_PARAM_H
+
+#endif
diff -Nru a/include/asm-arm/arch-h720x/serial.h b/include/asm-arm/arch-h720x/serial.h
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/include/asm-arm/arch-h720x/serial.h	2004-10-18 14:57:21 -07:00
@@ -0,0 +1,101 @@
+/*
+ * linux/include/asm-arm/arch-h72x/serial.h
+ *
+ * Copyright (C) 2003 Thomas Gleixner <tglx@linutronix.de>
+ *               2003 Robert Schwebel <r.schwebel@pengutronix.de>
+ *
+ * Serial port setup for Hynix boards
+ *
+ * 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.
+ *
+ */
+
+#ifndef __ASM_ARCH_SERIAL_H
+#define __ASM_ARCH_SERIAL_H
+
+#include <asm/arch/irqs.h>
+
+/*
+ * Standard COM flags
+ */
+#define STD_COM_FLAGS (ASYNC_BOOT_AUTOCONF | ASYNC_SKIP_TEST)
+#define RS_TABLE_SIZE
+
+/* Base clock is 3.6864 MHz */
+#define BASE_BAUD       (115200*2)
+#define EXTRA_SERIAL_PORT_DEFNS
+
+/*
+ * Board dependend defines
+ */
+#if defined (CONFIG_CPU_H7201)
+#define BASE_BAUD_P3C 	(115200)
+
+#define STD_SERIAL_PORT_DEFNS \
+	{ \
+	.baud_base	= BASE_BAUD, \
+	.port		= SERIAL0_BASE, \
+	.iomem_base     = (u8*)SERIAL0_BASE, \
+	.io_type        = UPIO_MEM, \
+	.irq		= IRQ_UART0, \
+	.flags		= STD_COM_FLAGS, \
+	.iomem_reg_shift = 2,\
+	}, \
+	{ \
+	.baud_base	= BASE_BAUD, \
+	.port		= SERIAL1_BASE, \
+	.iomem_base     = (u8*)SERIAL1_BASE, \
+	.io_type        = UPIO_MEM, \
+	.irq		= IRQ_UART1, \
+	.flags		= STD_COM_FLAGS, \
+	.iomem_reg_shift = 2,\
+	}
+
+#elif defined (CONFIG_CPU_H7202)
+
+#define STD_SERIAL_PORT_DEFNS \
+	{ \
+	.baud_base	= BASE_BAUD, \
+	.port		= SERIAL0_BASE, \
+	.iomem_base     = (u8*)SERIAL0_BASE, \
+	.io_type        = UPIO_MEM, \
+	.irq		= IRQ_UART0, \
+	.flags		= STD_COM_FLAGS, \
+	.iomem_reg_shift = 2,\
+	}, \
+	{ \
+	.baud_base	= BASE_BAUD, \
+	.port		= SERIAL1_BASE, \
+	.iomem_base     = (u8*)SERIAL1_BASE, \
+	.io_type        = UPIO_MEM, \
+	.irq		= IRQ_UART1, \
+	.flags		= STD_COM_FLAGS, \
+	.iomem_reg_shift = 2,\
+	}, \
+	{ \
+	.baud_base	= BASE_BAUD, \
+	.port		= SERIAL2_BASE, \
+	.iomem_base     = (u8*)SERIAL2_BASE, \
+	.io_type        = UPIO_MEM, \
+	.irq		= IRQ_UART2, \
+	.flags		= STD_COM_FLAGS, \
+	.iomem_reg_shift = 2,\
+	}, \
+	{ \
+	.baud_base	= BASE_BAUD, \
+	.port		= SERIAL3_BASE, \
+	.iomem_base     = (u8*)SERIAL3_BASE, \
+	.io_type        = UPIO_MEM, \
+	.irq		= IRQ_UART3, \
+	.flags		= STD_COM_FLAGS, \
+	.iomem_reg_shift = 2,\
+	}
+
+#else
+#error machine definition mismatch
+#endif
+
+/* __ASM_ARCH_SERIAL_H */
+#endif
diff -Nru a/include/asm-arm/arch-h720x/system.h b/include/asm-arm/arch-h720x/system.h
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/include/asm-arm/arch-h720x/system.h	2004-10-18 14:57:23 -07:00
@@ -0,0 +1,31 @@
+/*
+ * linux/arch/arm/mach-h720x/system.h
+ *
+ * Copyright (C) 2001-2002 Jungjun Kim, Hynix Semiconductor Inc.
+ *
+ * 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.
+ * linux/include/asm-arm/arch-h720x/system.h
+ *
+ */
+
+#ifndef __ASM_ARCH_SYSTEM_H
+#define __ASM_ARCH_SYSTEM_H
+#include <asm/hardware.h>
+
+static void arch_idle(void)
+{
+	CPU_REG (PMU_BASE, PMU_MODE) = PMU_MODE_IDLE;
+	__asm__ __volatile__(
+	"mov	r0, r0\n\t"
+	"mov	r0, r0");
+}
+
+
+static __inline__ void arch_reset(char mode)
+{
+	CPU_REG (PMU_BASE, PMU_STAT) |= PMU_WARMRESET;
+}
+
+#endif
diff -Nru a/include/asm-arm/arch-h720x/timex.h b/include/asm-arm/arch-h720x/timex.h
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/include/asm-arm/arch-h720x/timex.h	2004-10-18 14:57:24 -07:00
@@ -0,0 +1,15 @@
+/*
+ * linux/include/asm-arm/arch-h720x/timex.h
+ * Copyright (C) 2000 Jungjun Kim, Hynix Semiconductor Inc.
+ *
+ * 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.
+ */
+
+#ifndef __ASM_ARCH_TIMEX
+#define __ASM_ARCH_TIMEX
+
+#define CLOCK_TICK_RATE		3686400
+
+#endif
diff -Nru a/include/asm-arm/arch-h720x/uncompress.h b/include/asm-arm/arch-h720x/uncompress.h
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/include/asm-arm/arch-h720x/uncompress.h	2004-10-18 14:57:24 -07:00
@@ -0,0 +1,39 @@
+/*
+ * linux/include/asm-arm/arch-h720x/uncompress.h
+ *
+ * Copyright (C) 2001-2002 Jungjun Kim
+ */
+
+#ifndef __ASM_ARCH_UNCOMPRESS_H
+#define __ASM_ARCH_UNCOMPRESS_H
+
+#include <asm/arch/hardware.h>
+
+#define LSR 	0x14
+#define TEMPTY 	0x40
+
+static void putstr(const char *s)
+{
+	char c;
+	volatile unsigned char *p = (volatile unsigned char *)(IO_PHYS+0x20000);
+
+	while ( (c = *s++) != '\0') {
+		/* wait until transmit buffer is empty */
+		while((p[LSR] & TEMPTY) == 0x0);
+		/* write next character */
+		*p = c;
+
+		if(c == '\n') {
+			while((p[LSR] & TEMPTY) == 0x0);
+			*p = '\r';
+		}
+	}
+}
+
+/*
+ * nothing to do
+ */
+#define arch_decomp_setup()
+#define arch_decomp_wdog()
+
+#endif
diff -Nru a/include/asm-arm/arch-h720x/vmalloc.h b/include/asm-arm/arch-h720x/vmalloc.h
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/include/asm-arm/arch-h720x/vmalloc.h	2004-10-18 14:57:21 -07:00
@@ -0,0 +1,21 @@
+/*
+ * linux/include/asm-arm/arch-h720x/vmalloc.h
+ */
+
+#ifndef __ARCH_ARM_VMALLOC_H
+#define __ARCH_ARM_VMALLOC_H
+
+/*
+ * Just any arbitrary offset to the start of the vmalloc VM area: the
+ * current 8MB value just means that there will be a 8MB "hole" after the
+ * physical memory until the kernel virtual memory starts.  That means that
+ * any out-of-bounds memory accesses will hopefully be caught.
+ * The vmalloc() routines leaves a hole of 4kB between each vmalloced
+ * area for the same reason. ;)
+ */
+#define VMALLOC_OFFSET	  (8*1024*1024)
+#define VMALLOC_START	  (((unsigned long)high_memory + VMALLOC_OFFSET) & ~(VMALLOC_OFFSET-1))
+#define VMALLOC_VMADDR(x) ((unsigned long)(x))
+#define VMALLOC_END       (PAGE_OFFSET + 0x10000000)
+
+#endif
diff -Nru a/include/asm-arm/arch-imx/dma.h b/include/asm-arm/arch-imx/dma.h
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/include/asm-arm/arch-imx/dma.h	2004-10-18 14:57:22 -07:00
@@ -0,0 +1,71 @@
+/*
+ *  linux/include/asm-arm/imxads/dma.h
+ *
+ *  Copyright (C) 1997,1998 Russell King
+ *
+ * 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
+ */
+#ifndef __ASM_ARCH_DMA_H
+#define __ASM_ARCH_DMA_H
+
+#define MAX_DMA_ADDRESS		0xffffffff
+
+#define MAX_DMA_CHANNELS	0
+
+/*
+ * DMA registration
+ */
+
+typedef enum {
+	DMA_PRIO_HIGH = 0,
+	DMA_PRIO_MEDIUM = 3,
+	DMA_PRIO_LOW = 6
+} imx_dma_prio;
+
+int imx_request_dma(char *name, imx_dma_prio prio,
+		    void (*irq_handler) (int, void *, struct pt_regs *),
+		    void (*err_handler) (int, void *, struct pt_regs *),
+		    void *data);
+
+void imx_free_dma(int dma_ch);
+
+
+#define DMA_REQ_UART3_T        2
+#define DMA_REQ_UART3_R        3
+#define DMA_REQ_SSI2_T         4
+#define DMA_REQ_SSI2_R         5
+#define DMA_REQ_CSI_STAT       6
+#define DMA_REQ_CSI_R          7
+#define DMA_REQ_MSHC           8
+#define DMA_REQ_DSPA_DCT_DOUT  9
+#define DMA_REQ_DSPA_DCT_DIN  10
+#define DMA_REQ_DSPA_MAC      11
+#define DMA_REQ_EXT           12
+#define DMA_REQ_SDHC          13
+#define DMA_REQ_SPI1_R        14
+#define DMA_REQ_SPI1_T        15
+#define DMA_REQ_SSI_T         16
+#define DMA_REQ_SSI_R         17
+#define DMA_REQ_ASP_DAC       18
+#define DMA_REQ_ASP_ADC       19
+#define DMA_REQ_USP_EP(x)    (20+(x))
+#define DMA_REQ_SPI2_R        26
+#define DMA_REQ_SPI2_T        27
+#define DMA_REQ_UART2_T       28
+#define DMA_REQ_UART2_R       29
+#define DMA_REQ_UART1_T       30
+#define DMA_REQ_UART1_R       31
+
+#endif				/* _ASM_ARCH_DMA_H */
diff -Nru a/include/asm-arm/arch-imx/hardware.h b/include/asm-arm/arch-imx/hardware.h
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/include/asm-arm/arch-imx/hardware.h	2004-10-18 14:57:21 -07:00
@@ -0,0 +1,101 @@
+/*
+ *  linux/include/asm-arm/arch-imx/hardware.h
+ *
+ *  Copyright (C) 1999 ARM Limited.
+ *
+ * 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
+ */
+#ifndef __ASM_ARCH_HARDWARE_H
+#define __ASM_ARCH_HARDWARE_H
+
+#include <asm/sizes.h>
+#include "imx-regs.h"
+
+#ifndef __ASSEMBLY__
+# define __REG(x)	(*((volatile u32 *)IO_ADDRESS(x)))
+
+# define __REG2(x,y)	\
+	( __builtin_constant_p(y) ? (__REG((x) + (y))) \
+			  : (*(volatile u32 *)((u32)&__REG(x) + (y))) )
+#endif
+
+/*
+ * Memory map
+ */
+
+#define IMX_IO_PHYS		0x00200000
+#define IMX_IO_SIZE		0x00100000
+#define IMX_IO_BASE		0xe0000000
+
+#define IMX_CS0_PHYS		0x10000000
+#define IMX_CS0_SIZE		0x02000000
+#define IMX_CS0_VIRT		0xe8000000
+
+#define IMX_CS1_PHYS		0x12000000
+#define IMX_CS1_SIZE		0x01000000
+#define IMX_CS1_VIRT		0xea000000
+
+#define IMX_CS2_PHYS		0x13000000
+#define IMX_CS2_SIZE		0x01000000
+#define IMX_CS2_VIRT		0xeb000000
+
+#define IMX_CS3_PHYS		0x14000000
+#define IMX_CS3_SIZE		0x01000000
+#define IMX_CS3_VIRT		0xec000000
+
+#define IMX_CS4_PHYS		0x15000000
+#define IMX_CS4_SIZE		0x01000000
+#define IMX_CS4_VIRT		0xed000000
+
+#define IMX_CS5_PHYS		0x16000000
+#define IMX_CS5_SIZE		0x01000000
+#define IMX_CS5_VIRT		0xee000000
+
+#define IMX_FB_VIRT		0xF1000000
+#define IMX_FB_SIZE		(256*1024)
+
+/* macro to get at IO space when running virtually */
+#define IO_ADDRESS(x) ((x) | IMX_IO_BASE)
+
+#ifndef __ASSEMBLY__
+/*
+ * Handy routine to set GPIO functions
+ */
+extern void imx_gpio_mode( int gpio_mode );
+
+/* get frequencies in Hz */
+extern unsigned int imx_get_system_clk(void);
+extern unsigned int imx_get_mcu_clk(void);
+extern unsigned int imx_get_perclk1(void); /* UART[12], Timer[12], PWM */
+extern unsigned int imx_get_perclk2(void); /* LCD, SD, SPI[12]         */
+extern unsigned int imx_get_perclk3(void); /* SSI                      */
+extern unsigned int imx_get_hclk(void);    /* SDRAM, CSI, Memory Stick,*/
+                                           /* I2C, DMA                 */
+#endif
+
+#define MAXIRQNUM                       62
+#define MAXFIQNUM                       62
+#define MAXSWINUM                       62
+
+/*
+ * Use SDRAM for memory
+ */
+#define MEM_SIZE		0x01000000
+
+#ifdef CONFIG_ARCH_MX1ADS
+#include "mx1ads.h"
+#endif
+
+#endif
diff -Nru a/include/asm-arm/arch-imx/imx-regs.h b/include/asm-arm/arch-imx/imx-regs.h
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/include/asm-arm/arch-imx/imx-regs.h	2004-10-18 14:57:22 -07:00
@@ -0,0 +1,548 @@
+#ifndef _IMX_REGS_H
+#define _IMX_REGS_H
+/* ------------------------------------------------------------------------
+ *  Motorola IMX system registers
+ * ------------------------------------------------------------------------
+ *
+ */
+
+/*
+ *  Register BASEs, based on OFFSETs
+ *
+ */
+#define IMX_AIPI1_BASE             (0x00000 + IMX_IO_BASE)
+#define IMX_WDT_BASE               (0x01000 + IMX_IO_BASE)
+#define IMX_TIM1_BASE              (0x02000 + IMX_IO_BASE)
+#define IMX_TIM2_BASE              (0x03000 + IMX_IO_BASE)
+#define IMX_RTC_BASE               (0x04000 + IMX_IO_BASE)
+#define IMX_LCDC_BASE              (0x05000 + IMX_IO_BASE)
+#define IMX_UART1_BASE             (0x06000 + IMX_IO_BASE)
+#define IMX_UART2_BASE             (0x07000 + IMX_IO_BASE)
+#define IMX_PWM_BASE               (0x08000 + IMX_IO_BASE)
+#define IMX_DMAC_BASE              (0x09000 + IMX_IO_BASE)
+#define IMX_AIPI2_BASE             (0x10000 + IMX_IO_BASE)
+#define IMX_SIM_BASE               (0x11000 + IMX_IO_BASE)
+#define IMX_USBD_BASE              (0x12000 + IMX_IO_BASE)
+#define IMX_SPI1_BASE              (0x13000 + IMX_IO_BASE)
+#define IMX_MMC_BASE               (0x14000 + IMX_IO_BASE)
+#define IMX_ASP_BASE               (0x15000 + IMX_IO_BASE)
+#define IMX_BTA_BASE               (0x16000 + IMX_IO_BASE)
+#define IMX_I2C_BASE               (0x17000 + IMX_IO_BASE)
+#define IMX_SSI_BASE               (0x18000 + IMX_IO_BASE)
+#define IMX_SPI2_BASE              (0x19000 + IMX_IO_BASE)
+#define IMX_MSHC_BASE              (0x1A000 + IMX_IO_BASE)
+#define IMX_PLL_BASE               (0x1B000 + IMX_IO_BASE)
+#define IMX_GPIO_BASE              (0x1C000 + IMX_IO_BASE)
+#define IMX_EIM_BASE               (0x20000 + IMX_IO_BASE)
+#define IMX_SDRAMC_BASE            (0x21000 + IMX_IO_BASE)
+#define IMX_MMA_BASE               (0x22000 + IMX_IO_BASE)
+#define IMX_AITC_BASE              (0x23000 + IMX_IO_BASE)
+#define IMX_CSI_BASE               (0x24000 + IMX_IO_BASE)
+
+/* PLL registers */
+#define CSCR   __REG(IMX_PLL_BASE)        /* Clock Source Control Register */
+#define CSCR_SYSTEM_SEL (1<<16)
+
+#define MPCTL0 __REG(IMX_PLL_BASE + 0x4)  /* MCU PLL Control Register 0 */
+#define MPCTL1 __REG(IMX_PLL_BASE + 0x8)  /* MCU PLL and System Clock Register 1 */
+#define SPCTL0 __REG(IMX_PLL_BASE + 0xc)  /* System PLL Control Register 0 */
+#define SPCTL1 __REG(IMX_PLL_BASE + 0x10) /* System PLL Control Register 1 */
+#define PCDR   __REG(IMX_PLL_BASE + 0x20) /* Peripheral Clock Divider Register */
+
+#define CSCR_MPLL_RESTART (1<<21)
+
+/*
+ *  GPIO Module and I/O Multiplexer
+ *  x = 0..3 for reg_A, reg_B, reg_C, reg_D
+ */
+#define DDIR(x)    __REG2(IMX_GPIO_BASE + 0x00, ((x) & 3) << 8)
+#define OCR1(x)    __REG2(IMX_GPIO_BASE + 0x04, ((x) & 3) << 8)
+#define OCR2(x)    __REG2(IMX_GPIO_BASE + 0x08, ((x) & 3) << 8)
+#define ICONFA1(x) __REG2(IMX_GPIO_BASE + 0x0c, ((x) & 3) << 8)
+#define ICONFA2(x) __REG2(IMX_GPIO_BASE + 0x10, ((x) & 3) << 8)
+#define ICONFB1(x) __REG2(IMX_GPIO_BASE + 0x14, ((x) & 3) << 8)
+#define ICONFB2(x) __REG2(IMX_GPIO_BASE + 0x18, ((x) & 3) << 8)
+#define DR(x)      __REG2(IMX_GPIO_BASE + 0x1c, ((x) & 3) << 8)
+#define GIUS(x)    __REG2(IMX_GPIO_BASE + 0x20, ((x) & 3) << 8)
+#define SSR(x)     __REG2(IMX_GPIO_BASE + 0x24, ((x) & 3) << 8)
+#define ICR1(x)    __REG2(IMX_GPIO_BASE + 0x28, ((x) & 3) << 8)
+#define ICR2(x)    __REG2(IMX_GPIO_BASE + 0x2c, ((x) & 3) << 8)
+#define IMR(x)     __REG2(IMX_GPIO_BASE + 0x30, ((x) & 3) << 8)
+#define ISR(x)     __REG2(IMX_GPIO_BASE + 0x34, ((x) & 3) << 8)
+#define GPR(x)     __REG2(IMX_GPIO_BASE + 0x38, ((x) & 3) << 8)
+#define SWR(x)     __REG2(IMX_GPIO_BASE + 0x3c, ((x) & 3) << 8)
+#define PUEN(x)    __REG2(IMX_GPIO_BASE + 0x40, ((x) & 3) << 8)
+
+#define GPIO_PIN_MASK 0x1f
+#define GPIO_PORT_MASK (0x3 << 5)
+
+#define GPIO_PORTA (0<<5)
+#define GPIO_PORTB (1<<5)
+#define GPIO_PORTC (2<<5)
+#define GPIO_PORTD (3<<5)
+
+#define GPIO_OUT   (1<<7)
+#define GPIO_IN    (0<<7)
+#define GPIO_PUEN  (1<<8)
+
+#define GPIO_PF    (0<<9)
+#define GPIO_AF    (1<<9)
+
+#define GPIO_OCR_MASK (3<<10)
+#define GPIO_AIN   (0<<10)
+#define GPIO_BIN   (1<<10)
+#define GPIO_CIN   (2<<10)
+#define GPIO_GPIO  (3<<10)
+
+#define GPIO_AOUT  (1<<12)
+#define GPIO_BOUT  (1<<13)
+
+/* assignements for GPIO alternate/primary functions */
+
+/* FIXME: This list is not completed. The correct directions are
+ * missing on some (many) pins
+ */
+#define PA0_PF_A24           ( GPIO_PORTA | GPIO_PF | 0 )
+#define PA0_AIN_SPI2_CLK     ( GPIO_PORTA | GPIO_OUT | GPIO_AIN | 0 )
+#define PA0_AF_ETMTRACESYNC  ( GPIO_PORTA | GPIO_AF | 0 )
+#define PA1_AOUT_SPI2_RXD    ( GPIO_PORTA | GPIO_IN | GPIO_AOUT | 1 )
+#define PA1_PF_TIN           ( GPIO_PORTA | GPIO_PF | 1 )
+#define PA2_PF_PWM0          ( GPIO_PORTA | GPIO_OUT | GPIO_PF | 2 )
+#define PA3_PF_CSI_MCLK      ( GPIO_PORTA | GPIO_PF | 3 )
+#define PA4_PF_CSI_D0        ( GPIO_PORTA | GPIO_PF | 4 )
+#define PA5_PF_CSI_D1        ( GPIO_PORTA | GPIO_PF | 5 )
+#define PA6_PF_CSI_D2        ( GPIO_PORTA | GPIO_PF | 6 )
+#define PA7_PF_CSI_D3        ( GPIO_PORTA | GPIO_PF | 7 )
+#define PA8_PF_CSI_D4        ( GPIO_PORTA | GPIO_PF | 8 )
+#define PA9_PF_CSI_D5        ( GPIO_PORTA | GPIO_PF | 9 )
+#define PA10_PF_CSI_D6       ( GPIO_PORTA | GPIO_PF | 10 )
+#define PA11_PF_CSI_D7       ( GPIO_PORTA | GPIO_PF | 11 )
+#define PA12_PF_CSI_VSYNC    ( GPIO_PORTA | GPIO_PF | 12 )
+#define PA13_PF_CSI_HSYNC    ( GPIO_PORTA | GPIO_PF | 13 )
+#define PA14_PF_CSI_PIXCLK   ( GPIO_PORTA | GPIO_PF | 14 )
+#define PA15_PF_I2C_SDA      ( GPIO_PORTA | GPIO_OUT | GPIO_PF | 15 )
+#define PA16_PF_I2C_SCL      ( GPIO_PORTA | GPIO_OUT | GPIO_PF | 16 )
+#define PA17_AF_ETMTRACEPKT4 ( GPIO_PORTA | GPIO_AF | 17 )
+#define PA17_AIN_SPI2_SS     ( GPIO_PORTA | GPIO_AIN | 17 )
+#define PA18_AF_ETMTRACEPKT5 ( GPIO_PORTA | GPIO_AF | 18 )
+#define PA19_AF_ETMTRACEPKT6 ( GPIO_PORTA | GPIO_AF | 19 )
+#define PA20_AF_ETMTRACEPKT7 ( GPIO_PORTA | GPIO_AF | 20 )
+#define PA21_PF_A0           ( GPIO_PORTA | GPIO_PF | 21 )
+#define PA22_PF_CS4          ( GPIO_PORTA | GPIO_PF | 22 )
+#define PA23_PF_CS5          ( GPIO_PORTA | GPIO_PF | 23 )
+#define PA24_PF_A16          ( GPIO_PORTA | GPIO_PF | 24 )
+#define PA24_AF_ETMTRACEPKT0 ( GPIO_PORTA | GPIO_AF | 24 )
+#define PA25_PF_A17          ( GPIO_PORTA | GPIO_PF | 25 )
+#define PA25_AF_ETMTRACEPKT1 ( GPIO_PORTA | GPIO_AF | 25 )
+#define PA26_PF_A18          ( GPIO_PORTA | GPIO_PF | 26 )
+#define PA26_AF_ETMTRACEPKT2 ( GPIO_PORTA | GPIO_AF | 26 )
+#define PA27_PF_A19          ( GPIO_PORTA | GPIO_PF | 27 )
+#define PA27_AF_ETMTRACEPKT3 ( GPIO_PORTA | GPIO_AF | 27 )
+#define PA28_PF_A20          ( GPIO_PORTA | GPIO_PF | 28 )
+#define PA28_AF_ETMPIPESTAT0 ( GPIO_PORTA | GPIO_AF | 28 )
+#define PA29_PF_A21          ( GPIO_PORTA | GPIO_PF | 29 )
+#define PA29_AF_ETMPIPESTAT1 ( GPIO_PORTA | GPIO_AF | 29 )
+#define PA30_PF_A22          ( GPIO_PORTA | GPIO_PF | 30 )
+#define PA30_AF_ETMPIPESTAT2 ( GPIO_PORTA | GPIO_AF | 30 )
+#define PA31_PF_A23          ( GPIO_PORTA | GPIO_PF | 31 )
+#define PA31_AF_ETMTRACECLK  ( GPIO_PORTA | GPIO_AF | 31 )
+#define PB8_PF_SD_DAT0       ( GPIO_PORTB | GPIO_PF | GPIO_PUEN | 8 )
+#define PB8_AF_MS_PIO        ( GPIO_PORTB | GPIO_AF | 8 )
+#define PB9_PF_SD_DAT1       ( GPIO_PORTB | GPIO_PF | GPIO_PUEN  | 9 )
+#define PB9_AF_MS_PI1        ( GPIO_PORTB | GPIO_AF | 9 )
+#define PB10_PF_SD_DAT2      ( GPIO_PORTB | GPIO_PF | GPIO_PUEN  | 10 )
+#define PB10_AF_MS_SCLKI     ( GPIO_PORTB | GPIO_AF | 10 )
+#define PB11_PF_SD_DAT3      ( GPIO_PORTB | GPIO_PF | 11 )
+#define PB11_AF_MS_SDIO      ( GPIO_PORTB | GPIO_AF | 11 )
+#define PB12_PF_SD_CLK       ( GPIO_PORTB | GPIO_PF | 12 )
+#define PB12_AF_MS_SCLK0     ( GPIO_PORTB | GPIO_AF | 12 )
+#define PB13_PF_SD_CMD       ( GPIO_PORTB | GPIO_PF | GPIO_PUEN | 13 )
+#define PB13_AF_MS_BS        ( GPIO_PORTB | GPIO_AF | 13 )
+#define PB14_AF_SSI_RXFS     ( GPIO_PORTB | GPIO_AF | 14 )
+#define PB15_AF_SSI_RXCLK    ( GPIO_PORTB | GPIO_AF | 15 )
+#define PB16_AF_SSI_RXDAT    ( GPIO_PORTB | GPIO_IN | GPIO_AF | 16 )
+#define PB17_AF_SSI_TXDAT    ( GPIO_PORTB | GPIO_OUT | GPIO_AF | 17 )
+#define PB18_AF_SSI_TXFS     ( GPIO_PORTB | GPIO_AF | 18 )
+#define PB19_AF_SSI_TXCLK    ( GPIO_PORTB | GPIO_AF | 19 )
+#define PB20_PF_USBD_AFE     ( GPIO_PORTB | GPIO_PF | 20 )
+#define PB21_PF_USBD_OE      ( GPIO_PORTB | GPIO_PF | 21 )
+#define PB22_PFUSBD_RCV      ( GPIO_PORTB | GPIO_PF | 22 )
+#define PB23_PF_USBD_SUSPND  ( GPIO_PORTB | GPIO_PF | 23 )
+#define PB24_PF_USBD_VP      ( GPIO_PORTB | GPIO_PF | 24 )
+#define PB25_PF_USBD_VM      ( GPIO_PORTB | GPIO_PF | 25 )
+#define PB26_PF_USBD_VPO     ( GPIO_PORTB | GPIO_PF | 26 )
+#define PB27_PF_USBD_VMO     ( GPIO_PORTB | GPIO_PF | 27 )
+#define PB28_PF_UART2_CTS    ( GPIO_PORTB | GPIO_OUT | GPIO_PF | 28 )
+#define PB29_PF_UART2_RTS    ( GPIO_PORTB | GPIO_IN | GPIO_PF | 29 )
+#define PB30_PF_UART2_TXD    ( GPIO_PORTB | GPIO_OUT | GPIO_PF | 30 )
+#define PB31_PF_UART2_RXD    ( GPIO_PORTB | GPIO_IN | GPIO_PF | 31 )
+#define PC3_PF_SSI_RXFS      ( GPIO_PORTC | GPIO_PF | 3 )
+#define PC4_PF_SSI_RXCLK     ( GPIO_PORTC | GPIO_PF | 4 )
+#define PC5_PF_SSI_RXDAT     ( GPIO_PORTC | GPIO_IN | GPIO_PF | 5 )
+#define PC6_PF_SSI_TXDAT     ( GPIO_PORTC | GPIO_OUT | GPIO_PF | 6 )
+#define PC7_PF_SSI_TXFS      ( GPIO_PORTC | GPIO_PF | 7 )
+#define PC8_PF_SSI_TXCLK     ( GPIO_PORTC | GPIO_PF | 8 )
+#define PC9_PF_UART1_CTS     ( GPIO_PORTC | GPIO_OUT | GPIO_PF | 9 )
+#define PC10_PF_UART1_RTS    ( GPIO_PORTC | GPIO_IN | GPIO_PF | 10 )
+#define PC11_PF_UART1_TXD    ( GPIO_PORTC | GPIO_OUT | GPIO_PF | 11 )
+#define PC12_PF_UART1_RXD    ( GPIO_PORTC | GPIO_IN | GPIO_PF | 12 )
+#define PC13_PF_SPI1_SPI_RDY ( GPIO_PORTC | GPIO_PF | 13 )
+#define PC14_PF_SPI1_SCLK    ( GPIO_PORTC | GPIO_PF | 14 )
+#define PC15_PF_SPI1_SS      ( GPIO_PORTC | GPIO_PF | 15 )
+#define PC16_PF_SPI1_MISO    ( GPIO_PORTC | GPIO_PF | 16 )
+#define PC17_PF_SPI1_MOSI    ( GPIO_PORTC | GPIO_PF | 17 )
+#define PD6_PF_LSCLK         ( GPIO_PORTD | GPIO_OUT | GPIO_PF | 6 )
+#define PD7_PF_REV           ( GPIO_PORTD | GPIO_PF | 7 )
+#define PD7_AF_UART2_DTR     ( GPIO_PORTD | GPIO_IN | GPIO_AF | 7 )
+#define PD7_AIN_SPI2_SCLK    ( GPIO_PORTD | GPIO_AIN | 7 )
+#define PD8_PF_CLS           ( GPIO_PORTD | GPIO_PF | 8 )
+#define PD8_AF_UART2_DCD     ( GPIO_PORTD | GPIO_OUT | GPIO_AF | 8 )
+#define PD8_AIN_SPI2_SS      ( GPIO_PORTD | GPIO_AIN | 8 )
+#define PD9_PF_PS            ( GPIO_PORTD | GPIO_PF | 9 )
+#define PD9_AF_UART2_RI      ( GPIO_PORTD | GPIO_OUT | GPIO_AF | 9 )
+#define PD9_AOUT_SPI2_RXD    ( GPIO_PORTD | GPIO_IN | GPIO_AOUT | 9 )
+#define PD10_PF_SPL_SPR      ( GPIO_PORTD | GPIO_OUT | GPIO_PF | 10 )
+#define PD10_AF_UART2_DSR    ( GPIO_PORTD | GPIO_OUT | GPIO_AF | 10 )
+#define PD10_AIN_SPI2_TXD    ( GPIO_PORTD | GPIO_OUT | GPIO_AIN | 10 )
+#define PD11_PF_CONTRAST     ( GPIO_PORTD | GPIO_OUT | GPIO_PF | 11 )
+#define PD12_PF_ACD_OE       ( GPIO_PORTD | GPIO_OUT | GPIO_PF | 12 )
+#define PD13_PF_LP_HSYNC     ( GPIO_PORTD | GPIO_OUT | GPIO_PF | 13 )
+#define PD14_PF_FLM_VSYNC    ( GPIO_PORTD | GPIO_OUT | GPIO_PF | 14 )
+#define PD15_PF_LD0          ( GPIO_PORTD | GPIO_OUT | GPIO_PF | 15 )
+#define PD16_PF_LD1          ( GPIO_PORTD | GPIO_OUT | GPIO_PF | 16 )
+#define PD17_PF_LD2          ( GPIO_PORTD | GPIO_OUT | GPIO_PF | 17 )
+#define PD18_PF_LD3          ( GPIO_PORTD | GPIO_OUT | GPIO_PF | 18 )
+#define PD19_PF_LD4          ( GPIO_PORTD | GPIO_OUT | GPIO_PF | 19 )
+#define PD20_PF_LD5          ( GPIO_PORTD | GPIO_OUT | GPIO_PF | 20 )
+#define PD21_PF_LD6          ( GPIO_PORTD | GPIO_OUT | GPIO_PF | 21 )
+#define PD22_PF_LD7          ( GPIO_PORTD | GPIO_OUT | GPIO_PF | 22 )
+#define PD23_PF_LD8          ( GPIO_PORTD | GPIO_OUT | GPIO_PF | 23 )
+#define PD24_PF_LD9          ( GPIO_PORTD | GPIO_OUT | GPIO_PF | 24 )
+#define PD25_PF_LD10         ( GPIO_PORTD | GPIO_OUT | GPIO_PF | 25 )
+#define PD26_PF_LD11         ( GPIO_PORTD | GPIO_OUT | GPIO_PF | 26 )
+#define PD27_PF_LD12         ( GPIO_PORTD | GPIO_OUT | GPIO_PF | 27 )
+#define PD28_PF_LD13         ( GPIO_PORTD | GPIO_OUT | GPIO_PF | 28 )
+#define PD29_PF_LD14         ( GPIO_PORTD | GPIO_OUT | GPIO_PF | 29 )
+#define PD30_PF_LD15         ( GPIO_PORTD | GPIO_OUT | GPIO_PF | 30 )
+#define PD31_PF_TMR2OUT      ( GPIO_PORTD | GPIO_PF | 31 )
+#define PD31_BIN_SPI2_TXD    ( GPIO_PORTD | GPIO_BIN | 31 )
+
+/*
+ *  DMA Controller
+ */
+#define DCR     __REG(IMX_DMAC_BASE +0x00)	/* DMA Control Register */
+#define DISR    __REG(IMX_DMAC_BASE +0x04)	/* DMA Interrupt status Register */
+#define DIMR    __REG(IMX_DMAC_BASE +0x08)	/* DMA Interrupt mask Register */
+#define DBTOSR  __REG(IMX_DMAC_BASE +0x0c)	/* DMA Burst timeout status Register */
+#define DRTOSR  __REG(IMX_DMAC_BASE +0x10)	/* DMA Request timeout Register */
+#define DSESR   __REG(IMX_DMAC_BASE +0x14)	/* DMA Transfer Error Status Register */
+#define DBOSR   __REG(IMX_DMAC_BASE +0x18)	/* DMA Buffer overflow status Register */
+#define DBTOCR  __REG(IMX_DMAC_BASE +0x1c)	/* DMA Burst timeout control Register */
+#define WSRA    __REG(IMX_DMAC_BASE +0x40)	/* W-Size Register A */
+#define XSRA    __REG(IMX_DMAC_BASE +0x44)	/* X-Size Register A */
+#define YSRA    __REG(IMX_DMAC_BASE +0x48)	/* Y-Size Register A */
+#define WSRB    __REG(IMX_DMAC_BASE +0x4c)	/* W-Size Register B */
+#define XSRB    __REG(IMX_DMAC_BASE +0x50)	/* X-Size Register B */
+#define YSRB    __REG(IMX_DMAC_BASE +0x54)	/* Y-Size Register B */
+#define SAR(x)  __REG2( IMX_DMAC_BASE + 0x80, (x) << 6)	/* Source Address Registers */
+#define DAR(x)  __REG2( IMX_DMAC_BASE + 0x84, (x) << 6)	/* Destination Address Registers */
+#define CNTR(x) __REG2( IMX_DMAC_BASE + 0x88, (x) << 6)	/* Count Registers */
+#define CCR(x)  __REG2( IMX_DMAC_BASE + 0x8c, (x) << 6)	/* Control Registers */
+#define RSSR(x) __REG2( IMX_DMAC_BASE + 0x90, (x) << 6)	/* Request source select Registers */
+#define BLR(x)  __REG2( IMX_DMAC_BASE + 0x94, (x) << 6)	/* Burst length Registers */
+#define RTOR(x) __REG2( IMX_DMAC_BASE + 0x98, (x) << 6)	/* Request timeout Registers */
+#define BUCR(x) __REG2( IMX_DMAC_BASE + 0x98, (x) << 6)	/* Bus Utilization Registers */
+
+#define DCR_DRST           (1<<1)
+#define DCR_DEN            (1<<0)
+#define DBTOCR_EN          (1<<15)
+#define DBTOCR_CNT(x)      ((x) & 0x7fff )
+#define CNTR_CNT(x)        ((x) & 0xffffff )
+#define CCR_DMOD_LINEAR    ( 0x0 << 12 )
+#define CCR_DMOD_2D        ( 0x1 << 12 )
+#define CCR_DMOD_FIFO      ( 0x2 << 12 )
+#define CCR_DMOD_EOBFIFO   ( 0x3 << 12 )
+#define CCR_SMOD_LINEAR    ( 0x0 << 10 )
+#define CCR_SMOD_2D        ( 0x1 << 10 )
+#define CCR_SMOD_FIFO      ( 0x2 << 10 )
+#define CCR_SMOD_EOBFIFO   ( 0x3 << 10 )
+#define CCR_MDIR_DEC       (1<<9)
+#define CCR_MSEL_B         (1<<8)
+#define CCR_DSIZ_32        ( 0x0 << 6 )
+#define CCR_DSIZ_8         ( 0x1 << 6 )
+#define CCR_DSIZ_16        ( 0x2 << 6 )
+#define CCR_SSIZ_32        ( 0x0 << 4 )
+#define CCR_SSIZ_8         ( 0x1 << 4 )
+#define CCR_SSIZ_16        ( 0x2 << 4 )
+#define CCR_REN            (1<<3)
+#define CCR_RPT            (1<<2)
+#define CCR_FRC            (1<<1)
+#define CCR_CEN            (1<<0)
+#define RTOR_EN            (1<<15)
+#define RTOR_CLK           (1<<14)
+#define RTOR_PSC           (1<<13)
+
+/*
+ *  Interrupt controller
+ */
+
+#define IMX_INTCNTL        __REG(IMX_AITC_BASE+0x00)
+#define INTCNTL_FIAD       (1<<19)
+#define INTCNTL_NIAD       (1<<20)
+
+#define IMX_NIMASK         __REG(IMX_AITC_BASE+0x04)
+#define IMX_INTENNUM       __REG(IMX_AITC_BASE+0x08)
+#define IMX_INTDISNUM      __REG(IMX_AITC_BASE+0x0c)
+#define IMX_INTENABLEH     __REG(IMX_AITC_BASE+0x10)
+#define IMX_INTENABLEL     __REG(IMX_AITC_BASE+0x14)
+
+/*
+ *  General purpose timers
+ */
+#define IMX_TCTL(x)        __REG( 0x00 + (x))
+#define TCTL_SWR           (1<<15)
+#define TCTL_FRR           (1<<8)
+#define TCTL_CAP_RIS       (1<<6)
+#define TCTL_CAP_FAL       (2<<6)
+#define TCTL_CAP_RIS_FAL   (3<<6)
+#define TCTL_OM            (1<<5)
+#define TCTL_IRQEN         (1<<4)
+#define TCTL_CLK_PCLK1     (1<<1)
+#define TCTL_CLK_PCLK1_16  (2<<1)
+#define TCTL_CLK_TIN       (3<<1)
+#define TCTL_CLK_32        (4<<1)
+#define TCTL_TEN           (1<<0)
+
+#define IMX_TPRER(x)       __REG( 0x04 + (x))
+#define IMX_TCMP(x)        __REG( 0x08 + (x))
+#define IMX_TCR(x)         __REG( 0x0C + (x))
+#define IMX_TCN(x)         __REG( 0x10 + (x))
+#define IMX_TSTAT(x)       __REG( 0x14 + (x))
+#define TSTAT_CAPT         (1<<1)
+#define TSTAT_COMP         (1<<0)
+
+/*
+ * LCD Controller
+ */
+
+#define LCDC_SSA	__REG(IMX_LCDC_BASE+0x00)
+
+#define LCDC_SIZE	__REG(IMX_LCDC_BASE+0x04)
+#define SIZE_XMAX(x)	((((x) >> 4) & 0x3f) << 20)
+#define SIZE_YMAX(y)    ( (y) & 0x1ff )
+
+#define LCDC_VPW	__REG(IMX_LCDC_BASE+0x08)
+#define VPW_VPW(x)	( (x) & 0x3ff )
+
+#define LCDC_CPOS	__REG(IMX_LCDC_BASE+0x0C)
+#define CPOS_CC1        (1<<31)
+#define CPOS_CC0        (1<<30)
+#define CPOS_OP         (1<<28)
+#define CPOS_CXP(x)     (((x) & 3ff) << 16)
+#define CPOS_CYP(y)     ((y) & 0x1ff)
+
+#define LCDC_LCWHB	__REG(IMX_LCDC_BASE+0x10)
+#define LCWHB_BK_EN     (1<<31)
+#define LCWHB_CW(w)     (((w) & 0x1f) << 24)
+#define LCWHB_CH(h)     (((h) & 0x1f) << 16)
+#define LCWHB_BD(x)     ((x) & 0xff)
+
+#define LCDC_LCHCC	__REG(IMX_LCDC_BASE+0x14)
+#define LCHCC_CUR_COL_R(r) (((r) & 0x1f) << 11)
+#define LCHCC_CUR_COL_G(g) (((g) & 0x3f) << 5)
+#define LCHCC_CUR_COL_B(b) ((b) & 0x1f)
+
+#define LCDC_PCR	__REG(IMX_LCDC_BASE+0x18)
+#define PCR_TFT         (1<<31)
+#define PCR_COLOR       (1<<30)
+#define PCR_PBSIZ_1     (0<<28)
+#define PCR_PBSIZ_2     (1<<28)
+#define PCR_PBSIZ_4     (2<<28)
+#define PCR_PBSIZ_8     (3<<28)
+#define PCR_BPIX_1      (0<<25)
+#define PCR_BPIX_2      (1<<25)
+#define PCR_BPIX_4      (2<<25)
+#define PCR_BPIX_8      (3<<25)
+#define PCR_BPIX_12     (4<<25)
+#define PCR_BPIX_16     (4<<25)
+#define PCR_PIXPOL      (1<<24)
+#define PCR_FLMPOL      (1<<23)
+#define PCR_LPPOL       (1<<22)
+#define PCR_CLKPOL      (1<<21)
+#define PCR_OEPOL       (1<<20)
+#define PCR_SCLKIDLE    (1<<19)
+#define PCR_END_SEL     (1<<18)
+#define PCR_END_BYTE_SWAP (1<<17)
+#define PCR_REV_VS      (1<<16)
+#define PCR_ACD_SEL     (1<<15)
+#define PCR_ACD(x)      (((x) & 0x7f) << 8)
+#define PCR_SCLK_SEL    (1<<7)
+#define PCR_SHARP       (1<<6)
+#define PCR_PCD(x)      ((x) & 0x3f)
+
+#define LCDC_HCR	__REG(IMX_LCDC_BASE+0x1C)
+#define HCR_H_WIDTH(x)  (((x) & 0x3f) << 26)
+#define HCR_H_WAIT_1(x) (((x) & 0xff) << 8)
+#define HCR_H_WAIT_2(x) ((x) & 0xff)
+
+#define LCDC_VCR	__REG(IMX_LCDC_BASE+0x20)
+#define VCR_V_WIDTH(x)  (((x) & 0x3f) << 26)
+#define VCR_V_WAIT_1(x) (((x) & 0xff) << 8)
+#define VCR_V_WAIT_2(x) ((x) & 0xff)
+
+#define LCDC_POS	__REG(IMX_LCDC_BASE+0x24)
+#define POS_POS(x)      ((x) & 1f)
+
+#define LCDC_LSCR1	__REG(IMX_LCDC_BASE+0x28)
+#define LSCR1_PS_RISE_DELAY(x)    (((x) & 0x7f) << 26)
+#define LSCR1_CLS_RISE_DELAY(x)   (((x) & 0x3f) << 16)
+#define LSCR1_REV_TOGGLE_DELAY(x) (((x) & 0xf) << 8)
+#define LSCR1_GRAY2(x)            (((x) & 0xf) << 4)
+#define LSCR1_GRAY1(x)            (((x) & 0xf))
+
+#define LCDC_PWMR	__REG(IMX_LCDC_BASE+0x2C)
+#define PWMR_CLS(x)     (((x) & 0x1ff) << 16)
+#define PWMR_LDMSK      (1<<15)
+#define PWMR_SCR1       (1<<10)
+#define PWMR_SCR0       (1<<9)
+#define PWMR_CC_EN      (1<<8)
+#define PWMR_PW(x)      ((x) & 0xff)
+
+#define LCDC_DMACR	__REG(IMX_LCDC_BASE+0x30)
+#define DMACR_BURST     (1<<31)
+#define DMACR_HM(x)     (((x) & 0xf) << 16)
+#define DMACR_TM(x)     ((x) &0xf)
+
+#define LCDC_RMCR	__REG(IMX_LCDC_BASE+0x34)
+#define RMCR_LCDC_EN		(1<<1)
+#define RMCR_SELF_REF		(1<<0)
+
+#define LCDC_LCDICR	__REG(IMX_LCDC_BASE+0x38)
+#define LCDICR_INT_SYN  (1<<2)
+#define LCDICR_INT_CON  (1)
+
+#define LCDC_LCDISR	__REG(IMX_LCDC_BASE+0x40)
+#define LCDISR_UDR_ERR (1<<3)
+#define LCDISR_ERR_RES (1<<2)
+#define LCDISR_EOF     (1<<1)
+#define LCDISR_BOF     (1<<0)
+
+/*
+ *  UART Module. Takes the UART base address as argument
+ */
+#define URXD0(x) __REG( 0x0 + (x)) /* Receiver Register */
+#define URTX0(x) __REG( 0x40 + (x)) /* Transmitter Register */
+#define UCR1(x)  __REG( 0x80 + (x)) /* Control Register 1 */
+#define UCR2(x)  __REG( 0x84 + (x)) /* Control Register 2 */
+#define UCR3(x)  __REG( 0x88 + (x)) /* Control Register 3 */
+#define UCR4(x)  __REG( 0x8c + (x)) /* Control Register 4 */
+#define UFCR(x)  __REG( 0x90 + (x)) /* FIFO Control Register */
+#define USR1(x)  __REG( 0x94 + (x)) /* Status Register 1 */
+#define USR2(x)  __REG( 0x98 + (x)) /* Status Register 2 */
+#define UESC(x)  __REG( 0x9c + (x)) /* Escape Character Register */
+#define UTIM(x)  __REG( 0xa0 + (x)) /* Escape Timer Register */
+#define UBIR(x)  __REG( 0xa4 + (x)) /* BRM Incremental Register */
+#define UBMR(x)  __REG( 0xa8 + (x)) /* BRM Modulator Register */
+#define UBRC(x)  __REG( 0xac + (x)) /* Baud Rate Count Register */
+#define BIPR1(x) __REG( 0xb0 + (x)) /* Incremental Preset Register 1 */
+#define BIPR2(x) __REG( 0xb4 + (x)) /* Incremental Preset Register 2 */
+#define BIPR3(x) __REG( 0xb8 + (x)) /* Incremental Preset Register 3 */
+#define BIPR4(x) __REG( 0xbc + (x)) /* Incremental Preset Register 4 */
+#define BMPR1(x) __REG( 0xc0 + (x)) /* BRM Modulator Register 1 */
+#define BMPR2(x) __REG( 0xc4 + (x)) /* BRM Modulator Register 2 */
+#define BMPR3(x) __REG( 0xc8 + (x)) /* BRM Modulator Register 3 */
+#define BMPR4(x) __REG( 0xcc + (x)) /* BRM Modulator Register 4 */
+#define UTS(x)   __REG( 0xd0 + (x)) /* UART Test Register */
+
+/* UART Control Register Bit Fields.*/
+#define  URXD_CHARRDY    (1<<15)
+#define  URXD_ERR        (1<<14)
+#define  URXD_OVRRUN     (1<<13)
+#define  URXD_FRMERR     (1<<12)
+#define  URXD_BRK        (1<<11)
+#define  URXD_PRERR      (1<<10)
+#define  UCR1_ADEN       (1<<15) /* Auto dectect interrupt */
+#define  UCR1_ADBR       (1<<14) /* Auto detect baud rate */
+#define  UCR1_TRDYEN     (1<<13) /* Transmitter ready interrupt enable */
+#define  UCR1_IDEN       (1<<12) /* Idle condition interrupt */
+#define  UCR1_RRDYEN     (1<<9)	 /* Recv ready interrupt enable */
+#define  UCR1_RDMAEN     (1<<8)	 /* Recv ready DMA enable */
+#define  UCR1_IREN       (1<<7)	 /* Infrared interface enable */
+#define  UCR1_TXMPTYEN   (1<<6)	 /* Transimitter empty interrupt enable */
+#define  UCR1_RTSDEN     (1<<5)	 /* RTS delta interrupt enable */
+#define  UCR1_SNDBRK     (1<<4)	 /* Send break */
+#define  UCR1_TDMAEN     (1<<3)	 /* Transmitter ready DMA enable */
+#define  UCR1_UARTCLKEN  (1<<2)	 /* UART clock enabled */
+#define  UCR1_DOZE       (1<<1)	 /* Doze */
+#define  UCR1_UARTEN     (1<<0)	 /* UART enabled */
+#define  UCR2_ESCI     	 (1<<15) /* Escape seq interrupt enable */
+#define  UCR2_IRTS  	 (1<<14) /* Ignore RTS pin */
+#define  UCR2_CTSC  	 (1<<13) /* CTS pin control */
+#define  UCR2_CTS        (1<<12) /* Clear to send */
+#define  UCR2_ESCEN      (1<<11) /* Escape enable */
+#define  UCR2_PREN       (1<<8)  /* Parity enable */
+#define  UCR2_PROE       (1<<7)  /* Parity odd/even */
+#define  UCR2_STPB       (1<<6)	 /* Stop */
+#define  UCR2_WS         (1<<5)	 /* Word size */
+#define  UCR2_RTSEN      (1<<4)	 /* Request to send interrupt enable */
+#define  UCR2_TXEN       (1<<2)	 /* Transmitter enabled */
+#define  UCR2_RXEN       (1<<1)	 /* Receiver enabled */
+#define  UCR2_SRST 	 (1<<0)	 /* SW reset */
+#define  UCR3_DTREN 	 (1<<13) /* DTR interrupt enable */
+#define  UCR3_PARERREN   (1<<12) /* Parity enable */
+#define  UCR3_FRAERREN   (1<<11) /* Frame error interrupt enable */
+#define  UCR3_DSR        (1<<10) /* Data set ready */
+#define  UCR3_DCD        (1<<9)  /* Data carrier detect */
+#define  UCR3_RI         (1<<8)  /* Ring indicator */
+#define  UCR3_TIMEOUTEN  (1<<7)  /* Timeout interrupt enable */
+#define  UCR3_RXDSEN	 (1<<6)  /* Receive status interrupt enable */
+#define  UCR3_AIRINTEN   (1<<5)  /* Async IR wake interrupt enable */
+#define  UCR3_AWAKEN	 (1<<4)  /* Async wake interrupt enable */
+#define  UCR3_REF25 	 (1<<3)  /* Ref freq 25 MHz */
+#define  UCR3_REF30 	 (1<<2)  /* Ref Freq 30 MHz */
+#define  UCR3_INVT  	 (1<<1)  /* Inverted Infrared transmission */
+#define  UCR3_BPEN  	 (1<<0)  /* Preset registers enable */
+#define  UCR4_CTSTL_32   (32<<10) /* CTS trigger level (32 chars) */
+#define  UCR4_INVR  	 (1<<9)  /* Inverted infrared reception */
+#define  UCR4_ENIRI 	 (1<<8)  /* Serial infrared interrupt enable */
+#define  UCR4_WKEN  	 (1<<7)  /* Wake interrupt enable */
+#define  UCR4_REF16 	 (1<<6)  /* Ref freq 16 MHz */
+#define  UCR4_IRSC  	 (1<<5)  /* IR special case */
+#define  UCR4_TCEN  	 (1<<3)  /* Transmit complete interrupt enable */
+#define  UCR4_BKEN  	 (1<<2)  /* Break condition interrupt enable */
+#define  UCR4_OREN  	 (1<<1)  /* Receiver overrun interrupt enable */
+#define  UCR4_DREN  	 (1<<0)  /* Recv data ready interrupt enable */
+#define  UFCR_RXTL_SHF   0       /* Receiver trigger level shift */
+#define  UFCR_RFDIV      (7<<7)  /* Reference freq divider mask */
+#define  UFCR_TXTL_SHF   10      /* Transmitter trigger level shift */
+#define  USR1_PARITYERR  (1<<15) /* Parity error interrupt flag */
+#define  USR1_RTSS  	 (1<<14) /* RTS pin status */
+#define  USR1_TRDY  	 (1<<13) /* Transmitter ready interrupt/dma flag */
+#define  USR1_RTSD  	 (1<<12) /* RTS delta */
+#define  USR1_ESCF  	 (1<<11) /* Escape seq interrupt flag */
+#define  USR1_FRAMERR    (1<<10) /* Frame error interrupt flag */
+#define  USR1_RRDY       (1<<9)	 /* Receiver ready interrupt/dma flag */
+#define  USR1_TIMEOUT    (1<<7)	 /* Receive timeout interrupt status */
+#define  USR1_RXDS  	 (1<<6)	 /* Receiver idle interrupt flag */
+#define  USR1_AIRINT	 (1<<5)	 /* Async IR wake interrupt flag */
+#define  USR1_AWAKE 	 (1<<4)	 /* Aysnc wake interrupt flag */
+#define  USR2_ADET  	 (1<<15) /* Auto baud rate detect complete */
+#define  USR2_TXFE  	 (1<<14) /* Transmit buffer FIFO empty */
+#define  USR2_DTRF  	 (1<<13) /* DTR edge interrupt flag */
+#define  USR2_IDLE  	 (1<<12) /* Idle condition */
+#define  USR2_IRINT 	 (1<<8)	 /* Serial infrared interrupt flag */
+#define  USR2_WAKE  	 (1<<7)	 /* Wake */
+#define  USR2_RTSF  	 (1<<4)	 /* RTS edge interrupt flag */
+#define  USR2_TXDC  	 (1<<3)	 /* Transmitter complete */
+#define  USR2_BRCD  	 (1<<2)	 /* Break condition */
+#define  USR2_ORE        (1<<1)	 /* Overrun error */
+#define  USR2_RDR        (1<<0)	 /* Recv data ready */
+#define  UTS_FRCPERR	 (1<<13) /* Force parity error */
+#define  UTS_LOOP        (1<<12) /* Loop tx and rx */
+#define  UTS_TXEMPTY	 (1<<6)	 /* TxFIFO empty */
+#define  UTS_RXEMPTY	 (1<<5)	 /* RxFIFO empty */
+#define  UTS_TXFULL 	 (1<<4)	 /* TxFIFO full */
+#define  UTS_RXFULL 	 (1<<3)	 /* RxFIFO full */
+#define  UTS_SOFTRST	 (1<<0)	 /* Software reset */
+
+#endif				// _IMX_REGS_H
diff -Nru a/include/asm-arm/arch-imx/io.h b/include/asm-arm/arch-imx/io.h
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/include/asm-arm/arch-imx/io.h	2004-10-18 14:57:24 -07:00
@@ -0,0 +1,28 @@
+/*
+ *  linux/include/asm-arm/arch-imxads/io.h
+ *
+ *  Copyright (C) 1999 ARM Limited
+ *
+ * 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
+ */
+#ifndef __ASM_ARM_ARCH_IO_H
+#define __ASM_ARM_ARCH_IO_H
+
+#define IO_SPACE_LIMIT 0xffffffff
+
+#define __io(a)       (a)
+#define __mem_pci(a)  (a)
+
+#endif
diff -Nru a/include/asm-arm/arch-imx/irq.h b/include/asm-arm/arch-imx/irq.h
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/include/asm-arm/arch-imx/irq.h	2004-10-18 14:57:23 -07:00
@@ -0,0 +1,20 @@
+/*
+ *  linux/include/asm-arm/arch-imxads/irq.h
+ *
+ *  Copyright (C) 1999 ARM Limited
+ *
+ * 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
+ */
+#define fixup_irq(i)	(i)
diff -Nru a/include/asm-arm/arch-imx/irqs.h b/include/asm-arm/arch-imx/irqs.h
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/include/asm-arm/arch-imx/irqs.h	2004-10-18 14:57:23 -07:00
@@ -0,0 +1,116 @@
+/*
+ *  linux/include/asm-arm/arch-imxads/irqs.h
+ *
+ *  Copyright (C) 1999 ARM Limited
+ *  Copyright (C) 2000 Deep Blue Solutions 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.
+ *
+ * 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
+ */
+
+#ifndef __ARM_IRQS_H__
+#define __ARM_IRQS_H__
+
+/* Use the imx definitions */
+#include <asm/arch/hardware.h>
+
+/*
+ *  IMX Interrupt numbers
+ *
+ */
+#define INT_SOFTINT                 0
+#define CSI_INT                     6
+#define DSPA_MAC_INT                7
+#define DSPA_INT                    8
+#define COMP_INT                    9
+#define MSHC_XINT                   10
+#define GPIO_INT_PORTA              11
+#define GPIO_INT_PORTB              12
+#define GPIO_INT_PORTC              13
+#define LCDC_INT                    14
+#define SIM_INT                     15
+#define SIM_DATA_INT                16
+#define RTC_INT                     17
+#define RTC_SAMINT                  18
+#define UART2_MINT_PFERR            19
+#define UART2_MINT_RTS              20
+#define UART2_MINT_DTR              21
+#define UART2_MINT_UARTC            22
+#define UART2_MINT_TX               23
+#define UART2_MINT_RX               24
+#define UART1_MINT_PFERR            25
+#define UART1_MINT_RTS              26
+#define UART1_MINT_DTR              27
+#define UART1_MINT_UARTC            28
+#define UART1_MINT_TX               29
+#define UART1_MINT_RX               30
+#define VOICE_DAC_INT               31
+#define VOICE_ADC_INT               32
+#define PEN_DATA_INT                33
+#define PWM_INT                     34
+#define SDHC_INT                    35
+#define I2C_INT                     39
+#define CSPI_INT                    41
+#define SSI_TX_INT                  42
+#define SSI_TX_ERR_INT              43
+#define SSI_RX_INT                  44
+#define SSI_RX_ERR_INT              45
+#define TOUCH_INT                   46
+#define USBD_INT0                   47
+#define USBD_INT1                   48
+#define USBD_INT2                   49
+#define USBD_INT3                   50
+#define USBD_INT4                   51
+#define USBD_INT5                   52
+#define USBD_INT6                   53
+#define BTSYS_INT                   55
+#define BTTIM_INT                   56
+#define BTWUI_INT                   57
+#define TIM2_INT                    58
+#define TIM1_INT                    59
+#define DMA_ERR                     60
+#define DMA_INT                     61
+#define GPIO_INT_PORTD              62
+
+#define IMX_IRQS                         (64)
+
+/* note: the IMX has four gpio ports (A-D), but only
+ *       the following pins are connected to the outside
+ *       world:
+ *
+ * PORT A: bits 0-31
+ * PORT B: bits 8-31
+ * PORT C: bits 3-17
+ * PORT D: bits 6-31
+ *
+ * We map these interrupts straight on. As a result we have
+ * several holes in the interrupt mapping. We do this for two
+ * reasons:
+ *   - mapping the interrupts without holes would get
+ *     far more complicated
+ *   - Motorola could well decide to bring some processor
+ *     with more pins connected
+ */
+
+#define IRQ_GPIOA(x)  (IMX_IRQS + x)
+#define IRQ_GPIOB(x)  (IRQ_GPIOA(32) + x)
+#define IRQ_GPIOC(x)  (IRQ_GPIOB(32) + x)
+#define IRQ_GPIOD(x)  (IRQ_GPIOC(32) + x)
+
+/* decode irq number to use with IMR(x), ISR(x) and friends */
+#define IRQ_TO_REG(irq) ((irq - IMX_IRQS) >> 5)
+
+#define NR_IRQS (IRQ_GPIOD(32) + 1)
+#define IRQ_GPIO(x)
+#endif
diff -Nru a/include/asm-arm/arch-imx/memory.h b/include/asm-arm/arch-imx/memory.h
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/include/asm-arm/arch-imx/memory.h	2004-10-18 14:57:24 -07:00
@@ -0,0 +1,38 @@
+/*
+ *  linux/include/asm-arm/arch-imx/memory.h
+ *
+ *  Copyright (C) 1999 ARM Limited
+ *  Copyright (C) 2002 Shane Nay (shane@minirl.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
+ */
+#ifndef __ASM_ARCH_MMU_H
+#define __ASM_ARCH_MMU_H
+
+#define PHYS_OFFSET	(0x08000000UL)
+
+/*
+ * Virtual view <-> DMA view memory address translations
+ * virt_to_bus: Used to translate the virtual address to an
+ *              address suitable to be passed to set_dma_addr
+ * bus_to_virt: Used to convert an address for DMA operations
+ *              to an address that the kernel can use.
+ */
+#define __virt_to_bus__is_a_macro
+#define __virt_to_bus(x)	(x - PAGE_OFFSET +  PHYS_OFFSET)
+#define __bus_to_virt__is_a_macro
+#define __bus_to_virt(x)	(x -  PHYS_OFFSET + PAGE_OFFSET)
+
+#endif
diff -Nru a/include/asm-arm/arch-imx/mx1ads.h b/include/asm-arm/arch-imx/mx1ads.h
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/include/asm-arm/arch-imx/mx1ads.h	2004-10-18 14:57:23 -07:00
@@ -0,0 +1,36 @@
+/*
+ * linux/include/asm-arm/arch-imx/mx1ads.h
+ *
+ * Copyright (C) 2004 Robert Schwebel, Pengutronix
+ *
+ * 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
+ *
+ */
+
+#ifndef __ASM_ARCH_MX1ADS_H
+#define __ASM_ARCH_MX1ADS_H
+
+/* ------------------------------------------------------------------------ */
+/* Memory Map for the M9328MX1ADS (MX1ADS) Board                            */
+/* ------------------------------------------------------------------------ */
+
+#define MX1ADS_FLASH_PHYS		0x10000000
+#define MX1ADS_FLASH_SIZE		(16*1024*1024)
+
+#define IMX_FB_PHYS			(0x0C000000 - 0x40000)
+
+#define CLK32 32000
+
+#endif /* __ASM_ARCH_MX1ADS_H */
diff -Nru a/include/asm-arm/arch-imx/param.h b/include/asm-arm/arch-imx/param.h
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/include/asm-arm/arch-imx/param.h	2004-10-18 14:57:23 -07:00
@@ -0,0 +1,19 @@
+/*
+ *  linux/include/asm-arm/arch-imx/param.h
+ *
+ *  Copyright (C) 1999 ARM Limited
+ *
+ * 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
+ */
diff -Nru a/include/asm-arm/arch-imx/serial.h b/include/asm-arm/arch-imx/serial.h
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/include/asm-arm/arch-imx/serial.h	2004-10-18 14:57:23 -07:00
@@ -0,0 +1,26 @@
+/*
+ *  linux/include/asm-arm/arch-imx/serial.h
+ *
+ *  Copyright (C) 1999 ARM Limited
+ *
+ * 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
+ */
+#ifndef __ASM_ARCH_SERIAL_H
+#define __ASM_ARCH_SERIAL_H
+
+#define STD_SERIAL_PORT_DEFNS
+#define EXTRA_SERIAL_PORT_DEFNS
+
+#endif /* __ASM_ARCH_SERIAL_H */
diff -Nru a/include/asm-arm/arch-imx/system.h b/include/asm-arm/arch-imx/system.h
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/include/asm-arm/arch-imx/system.h	2004-10-18 14:57:21 -07:00
@@ -0,0 +1,40 @@
+/*
+ *  linux/include/asm-arm/arch-imxads/system.h
+ *
+ *  Copyright (C) 1999 ARM Limited
+ *  Copyright (C) 2000 Deep Blue Solutions 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.
+ *
+ * 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
+ */
+#ifndef __ASM_ARCH_SYSTEM_H
+#define __ASM_ARCH_SYSTEM_H
+
+static void
+arch_idle(void)
+{
+	/*
+	 * This should do all the clock switching
+	 * and wait for interrupt tricks
+	 */
+	cpu_do_idle();
+}
+
+static inline void
+arch_reset(char mode)
+{
+	cpu_reset(0);
+}
+
+#endif
diff -Nru a/include/asm-arm/arch-imx/timex.h b/include/asm-arm/arch-imx/timex.h
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/include/asm-arm/arch-imx/timex.h	2004-10-18 14:57:23 -07:00
@@ -0,0 +1,27 @@
+/*
+ *  linux/include/asm-arm/imx/timex.h
+ *
+ *  Copyright (C) 1999 ARM Limited
+ *
+ * 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
+ */
+
+#ifndef __ASM_ARCH_TIMEX_H
+#define __ASM_ARCH_TIMEX_H
+
+#include <asm/arch/hardware.h>
+#define CLOCK_TICK_RATE		(CLK32)
+
+#endif
diff -Nru a/include/asm-arm/arch-imx/uncompress.h b/include/asm-arm/arch-imx/uncompress.h
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/include/asm-arm/arch-imx/uncompress.h	2004-10-18 14:57:24 -07:00
@@ -0,0 +1,78 @@
+/*
+ *  linux/include/asm-arm/arch-imxads/uncompress.h
+ *
+ *
+ *
+ *  Copyright (C) 1999 ARM Limited
+ *  Copyright (C) Shane Nay (shane@minirl.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
+ */
+
+#define UART(x) (*(volatile unsigned long *)(serial_port + (x)))
+
+#define UART1_BASE 0x206000
+#define UART2_BASE 0x207000
+#define USR2 0x98
+#define USR2_TXFE (1<<14)
+#define TXR  0x40
+#define UCR1 0x80
+#define UCR1_UARTEN 1
+
+/*
+ * The following code assumes the serial port has already been
+ * initialized by the bootloader.  We search for the first enabled
+ * port in the most probable order.  If you didn't setup a port in
+ * your bootloader then nothing will appear (which might be desired).
+ *
+ * This does not append a newline
+ */
+static void
+putstr(const char *s)
+{
+	unsigned long serial_port;
+
+	do {
+		serial_port = UART1_BASE;
+		if ( UART(UCR1) & UCR1_UARTEN )
+			break;
+		serial_port = UART2_BASE;
+		if ( UART(UCR1) & UCR1_UARTEN )
+			break;
+		return;
+	} while(0);
+
+	while (*s) {
+		while ( !(UART(USR2) & USR2_TXFE) )
+			barrier();
+
+		UART(TXR) = *s;
+
+		if (*s == '\n') {
+			while ( !(UART(USR2) & USR2_TXFE) )
+				barrier();
+
+			UART(TXR) = '\r';
+		}
+		s++;
+	}
+}
+
+/*
+ * nothing to do
+ */
+#define arch_decomp_setup()
+
+#define arch_decomp_wdog()
diff -Nru a/include/asm-arm/arch-imx/vmalloc.h b/include/asm-arm/arch-imx/vmalloc.h
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/include/asm-arm/arch-imx/vmalloc.h	2004-10-18 14:57:21 -07:00
@@ -0,0 +1,32 @@
+/*
+ *  linux/include/asm-arm/arch-imx/vmalloc.h
+ *
+ *  Copyright (C) 2000 Russell King.
+ *
+ * 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
+ */
+
+/*
+ * Just any arbitrary offset to the start of the vmalloc VM area: the
+ * current 8MB value just means that there will be a 8MB "hole" after the
+ * physical memory until the kernel virtual memory starts.  That means that
+ * any out-of-bounds memory accesses will hopefully be caught.
+ * The vmalloc() routines leaves a hole of 4kB between each vmalloced
+ * area for the same reason. ;)
+ */
+#define VMALLOC_OFFSET	  (8*1024*1024)
+#define VMALLOC_START	  (((unsigned long)high_memory + VMALLOC_OFFSET) & ~(VMALLOC_OFFSET-1))
+#define VMALLOC_VMADDR(x) ((unsigned long)(x))
+#define VMALLOC_END       (PAGE_OFFSET + 0x10000000)
diff -Nru a/include/asm-arm/arch-integrator/uncompress.h b/include/asm-arm/arch-integrator/uncompress.h
--- a/include/asm-arm/arch-integrator/uncompress.h	2004-10-18 14:56:29 -07:00
+++ b/include/asm-arm/arch-integrator/uncompress.h	2004-10-18 14:56:29 -07:00
@@ -28,7 +28,7 @@
 /*
  * This does not append a newline
  */
-static void puts(const char *s)
+static void putstr(const char *s)
 {
 	while (*s) {
 		while (AMBA_UART_FR & (1 << 5));
diff -Nru a/include/asm-arm/arch-iop3xx/dma.h b/include/asm-arm/arch-iop3xx/dma.h
--- a/include/asm-arm/arch-iop3xx/dma.h	2004-10-18 14:56:49 -07:00
+++ b/include/asm-arm/arch-iop3xx/dma.h	2004-10-18 14:56:49 -07:00
@@ -1,109 +1,16 @@
 /*
- * linux/include/asm-arm/arch-iop80310/dma.h
+ * linux/include/asm-arm/arch-iop3xx/dma.h
  *
- *  Copyright (C) 2001 MontaVista Software, Inc.
+ *  Copyright (C) 2004 Intel Corp.
  *
  * 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.
  */
 
-#ifndef _IOP310_DMA_H_
-#define _IOP310_DMA_H_
-
-/* 2 DMA on primary PCI and 1 on secondary for 80310 */
-#define MAX_IOP310_DMA_CHANNEL   3
-#define MAX_DMA_DESC        	64	/*128 */
-
-/*
- * Make the generic DMA bits go away since we don't use it
- */
-#define MAX_DMA_CHANNELS	0
+#ifndef _IOP3XX_DMA_H_P
+#define _IOP3XX_DMA_H_P
 
 #define MAX_DMA_ADDRESS		0xffffffff
 
-#define IOP310_DMA_P0      	0
-#define IOP310_DMA_P1		1
-#define IOP310_DMA_S0      	2
-
-#define DMA_MOD_READ        	0x0001
-#define DMA_MOD_WRITE		0x0002
-#define DMA_MOD_CACHED		0x0004
-#define DMA_MOD_NONCACHED	0x0008
-
-
-#define DMA_DESC_DONE   	0x0010
-#define DMA_INCOMPLETE  	0x0020
-#define DMA_HOLD		0x0040
-#define DMA_END_CHAIN		0x0080
-#define DMA_COMPLETE		0x0100
-#define DMA_NOTIFY		0x0200
-#define DMA_NEW_HEAD		0x0400
-
-#define DMA_USER_MASK	(DMA_NOTIFY | DMA_INCOMPLETE | \
-						 DMA_HOLD | DMA_COMPLETE)
-
-#define DMA_DCR_DAC		0x00000020	/* Dual Addr Cycle Enab */
-#define DMA_DCR_IE		0x00000010	/* Interrupt Enable */
-#define DMA_DCR_PCI_IOR		0x00000002	/* I/O Read */
-#define DMA_DCR_PCI_IOW		0x00000003	/* I/O Write */
-#define DMA_DCR_PCI_MR		0x00000006	/* Memory Read */
-#define DMA_DCR_PCI_MW		0x00000007	/* Memory Write */
-#define DMA_DCR_PCI_CR		0x0000000A	/* Configuration Read */
-#define DMA_DCR_PCI_CW		0x0000000B	/* Configuration Write */
-#define DMA_DCR_PCI_MRM		0x0000000C	/* Memory Read Multiple */
-#define DMA_DCR_PCI_MRL		0x0000000E	/* Memory Read Line */
-#define DMA_DCR_PCI_MWI		0x0000000F	/* Mem Write and Inval */
-
-#define DMA_USER_CMD_IE		0x00000001	/* user request int */
-#define DMA_USER_END_CHAIN	0x00000002	/* end of sgl chain flag */
-
-/* ATU defines */
-#define     IOP310_ATUCR_PRIM_OUT_ENAB  /* Configuration   */      0x00000002
-#define     IOP310_ATUCR_DIR_ADDR_ENAB  /* Configuration   */      0x00000080
-
-
-typedef void (*dma_callback_t) (void *buf_context);
-/*
- * DMA Descriptor
- */
-typedef struct _dma_desc
-{
-	u32 NDAR;					/* next descriptor address */
-	u32 PDAR;					/* PCI address */
-	u32 PUADR;					/* upper PCI address */
-	u32 LADR;					/* local address */
-	u32 BC;						/* byte count */
-	u32 DC;						/* descriptor control */
-} dma_desc_t;
-
-typedef struct _dma_sgl
-{
-	dma_desc_t dma_desc;		/* DMA descriptor pointer */
-	u32 status;					/* descriptor status */
-	void *data;					/* local virt */
-	struct _dma_sgl *next;		/* next descriptor */
-} dma_sgl_t;
-
-/* dma sgl head */
-typedef struct _dma_head
-{
-	u32 total;					/* total elements in SGL */
-	u32 status;					/* status of sgl */
-	u32 mode;					/* read or write mode */
-	dma_sgl_t *list;			/* pointer to list */
-	dma_callback_t callback;	/* callback function */
-} dma_head_t;
-
-/* function prototypes */
-int dma_request(dmach_t, const char *);
-int dma_queue_buffer(dmach_t, dma_head_t *);
-int dma_suspend(dmach_t);
-int dma_resume(dmach_t);
-int dma_flush_all(dmach_t);
-void dma_free(dmach_t);
-void dma_set_irq_threshold(dmach_t, int);
-dma_sgl_t *dma_get_buffer(dmach_t, int);
-void dma_return_buffer(dmach_t, dma_sgl_t *);
-
-#endif /* _ASM_ARCH_DMA_H */
+#endif /* _ASM_ARCH_DMA_H_P */
diff -Nru a/include/asm-arm/arch-iop3xx/hardware.h b/include/asm-arm/arch-iop3xx/hardware.h
--- a/include/asm-arm/arch-iop3xx/hardware.h	2004-10-18 14:56:17 -07:00
+++ b/include/asm-arm/arch-iop3xx/hardware.h	2004-10-18 14:56:17 -07:00
@@ -1,10 +1,10 @@
 /*
- * linux/include/asm-arm/arch-iop80310/hardware.h
+ * linux/include/asm-arm/arch-iop3xx/hardware.h
  */
 #ifndef __ASM_ARCH_HARDWARE_H
 #define __ASM_ARCH_HARDWARE_H
 
-#include <linux/config.h>
+#include <asm/types.h>
 
 /*
  * Note about PCI IO space mappings
@@ -15,41 +15,42 @@
  * The PCI IO space is located at virtual 0xfe000000 from physical
  * 0x90000000.  The PCI BARs must be programmed with physical addresses,
  * but when we read them, we convert them to virtual addresses.  See
- * arch/arm/mach-iop310/iop310-pci.c
+ * arch/arm/mach-iop3xx/iop3xx-pci.c
  */
 
 #define pcibios_assign_all_busses() 1
 
-#ifdef CONFIG_ARCH_IOP310
+
 /*
- * these are the values for the secondary PCI bus on the 80312 chip.  I will
- * have to do some fixup in the bus/dev fixup code
+ * The min PCI I/O and MEM space are dependent on what specific
+ * chipset/platform we are running on, so instead of hardcoding with
+ * #ifdefs, we just fill these in the platform level PCI init code.
  */
-#define PCIBIOS_MIN_IO      0
-#define PCIBIOS_MIN_MEM     0x88000000
-
-// Generic chipset bits
-#include "iop310.h"
+#ifndef __ASSEMBLY__
+extern unsigned long iop3xx_pcibios_min_io;
+extern unsigned long iop3xx_pcibios_min_mem;
 
-// Board specific
-#if defined(CONFIG_ARCH_IQ80310)
-#include "iq80310.h"
+extern unsigned int processor_id;
 #endif
-#endif
-
-#ifdef CONFIG_ARCH_IOP321
 
-#define PCIBIOS_MIN_IO		0x90000000
-#define PCIBIOS_MIN_MEM		0x80000000
+/*
+ * We just set these to zero since they are really bogus anyways
+ */
+#define PCIBIOS_MIN_IO      (iop3xx_pcibios_min_io)
+#define PCIBIOS_MIN_MEM     (iop3xx_pcibios_min_mem)
 
+/*
+ * Generic chipset bits
+ *
+ */
 #include "iop321.h"
+#include "iop331.h"
 
-#ifdef CONFIG_ARCH_IQ80321
+/*
+ * Board specific bits
+ */
 #include "iq80321.h"
-#endif
-#endif
-
-
-
+#include "iq31244.h"
+#include "iq80331.h"
 
 #endif  /* _ASM_ARCH_HARDWARE_H */
diff -Nru a/include/asm-arm/arch-iop3xx/iop310-irqs.h b/include/asm-arm/arch-iop3xx/iop310-irqs.h
--- a/include/asm-arm/arch-iop3xx/iop310-irqs.h	2004-10-18 14:55:54 -07:00
+++ /dev/null	Wed Dec 31 16:00:00 196900
@@ -1,80 +0,0 @@
-/*
- * linux/include/asm-arm/arch-iop310/irqs.h
- *
- * Author:	Nicolas Pitre
- * Copyright:	(C) 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 version 2 as
- * published by the Free Software Foundation.
- *
- * 06/13/01: Added 80310 on-chip interrupt sources <dsaxena@mvista.com>
- *
- */
-#include <linux/config.h>
-
-/*
- * XS80200 specific IRQs
- */
-#define IRQ_XS80200_BCU		0	/* Bus Control Unit */
-#define IRQ_XS80200_PMU		1	/* Performance Monitoring Unit */
-#define IRQ_XS80200_EXTIRQ	2	/* external IRQ signal */
-#define IRQ_XS80200_EXTFIQ	3	/* external IRQ signal */
-
-#define NR_XS80200_IRQS		4
-
-#define XSCALE_PMU_IRQ		IRQ_XS80200_PMU
-
-/*
- * IOP80310 chipset interrupts
- */
-#define IOP310_IRQ_OFS		NR_XS80200_IRQS
-#define IOP310_IRQ(x)		(IOP310_IRQ_OFS + (x))
-
-/*
- * On FIQ1ISR register
- */
-#define IRQ_IOP310_DMA0		IOP310_IRQ(0)	/* DMA Channel 0 */
-#define IRQ_IOP310_DMA1		IOP310_IRQ(1)	/* DMA Channel 1 */
-#define IRQ_IOP310_DMA2		IOP310_IRQ(2)	/* DMA Channel 2 */
-#define IRQ_IOP310_PMON		IOP310_IRQ(3)	/* Bus performance Unit */
-#define IRQ_IOP310_AAU		IOP310_IRQ(4)	/* Application Accelator Unit */
-
-/*
- * On FIQ2ISR register
- */
-#define IRQ_IOP310_I2C		IOP310_IRQ(5)	/* I2C unit */
-#define IRQ_IOP310_MU		IOP310_IRQ(6)	/* messaging unit */
-
-#define NR_IOP310_IRQS		(IOP310_IRQ(6) + 1)
-
-#define NR_IRQS			NR_IOP310_IRQS
-
-
-/*
- * Interrupts available on the Cyclone IQ80310 board
- */
-#ifdef CONFIG_ARCH_IQ80310
-
-#define IQ80310_IRQ_OFS		NR_IOP310_IRQS
-#define IQ80310_IRQ(y)		((IQ80310_IRQ_OFS) + (y))
-
-#define IRQ_IQ80310_TIMER	IQ80310_IRQ(0)	/* Timer Interrupt */
-#define IRQ_IQ80310_I82559	IQ80310_IRQ(1)	/* I82559 Ethernet Interrupt */
-#define IRQ_IQ80310_UART1	IQ80310_IRQ(2)	/* UART1 Interrupt */
-#define IRQ_IQ80310_UART2	IQ80310_IRQ(3)	/* UART2 Interrupt */
-#define IRQ_IQ80310_INTD	IQ80310_IRQ(4)	/* PCI INTD */
-
-
-/*
- * ONLY AVAILABLE ON REV F OR NEWER BOARDS!
- */
-#define	IRQ_IQ80310_INTA	IQ80310_IRQ(5)	/* PCI INTA */
-#define	IRQ_IQ80310_INTB	IQ80310_IRQ(6)	/* PCI INTB */
-#define	IRQ_IQ80310_INTC	IQ80310_IRQ(7)	/* PCI INTC */
-
-#undef	NR_IRQS
-#define NR_IRQS			(IQ80310_IRQ(7) + 1)
-
-#endif // CONFIG_ARCH_IQ80310
-
diff -Nru a/include/asm-arm/arch-iop3xx/iop310.h b/include/asm-arm/arch-iop3xx/iop310.h
--- a/include/asm-arm/arch-iop3xx/iop310.h	2004-10-18 14:56:29 -07:00
+++ /dev/null	Wed Dec 31 16:00:00 196900
@@ -1,255 +0,0 @@
-/*
- * linux/include/asm/arch-iop3xx/iop310.h
- *
- * Intel IOP310 Companion Chip definitions
- *
- * 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.
- */
-
-#ifndef _IOP310_HW_H_
-#define _IOP310_HW_H_
-
-/*
- * This is needed for mixed drivers that need to work on all
- * IOP3xx variants but behave slightly differently on each.
- */
-#ifndef __ASSEMBLY__
-#define iop_is_310() ((processor_id & 0xffffe3f0) == 0x69052000)
-#endif
-
-/*
- * IOP310 I/O and Mem space regions for PCI autoconfiguration
- */
-#define IOP310_PCISEC_LOWER_IO		0x90010000
-#define IOP310_PCISEC_UPPER_IO		0x9001ffff
-#define IOP310_PCISEC_LOWER_MEM		0x88000000
-#define IOP310_PCISEC_UPPER_MEM		0x8bffffff
-
-#define IOP310_PCIPRI_LOWER_IO		0x90000000
-#define IOP310_PCIPRI_UPPER_IO		0x9000ffff
-#define IOP310_PCIPRI_LOWER_MEM		0x80000000
-#define IOP310_PCIPRI_UPPER_MEM		0x83ffffff
-
-#define IOP310_PCI_WINDOW_SIZE		64 * 0x100000
-
-/*
- * IOP310 chipset registers
- */
-#define IOP310_VIRT_MEM_BASE 0xe8001000  /* chip virtual mem address*/
-#define IOP310_PHY_MEM_BASE  0x00001000  /* chip physical memory address */
-#define IOP310_REG_ADDR(reg) (IOP310_VIRT_MEM_BASE | IOP310_PHY_MEM_BASE | (reg))
-
-/* PCI-to-PCI Bridge Unit 0x00001000 through 0x000010FF */
-#define IOP310_VIDR    (volatile u16 *)IOP310_REG_ADDR(0x00001000)
-#define IOP310_DIDR    (volatile u16 *)IOP310_REG_ADDR(0x00001002)
-#define IOP310_PCR     (volatile u16 *)IOP310_REG_ADDR(0x00001004)
-#define IOP310_PSR     (volatile u16 *)IOP310_REG_ADDR(0x00001006)
-#define IOP310_RIDR    (volatile u8  *)IOP310_REG_ADDR(0x00001008)
-#define IOP310_CCR     (volatile u32 *)IOP310_REG_ADDR(0x00001009)
-#define IOP310_CLSR    (volatile u8  *)IOP310_REG_ADDR(0x0000100C)
-#define IOP310_PLTR    (volatile u8  *)IOP310_REG_ADDR(0x0000100D)
-#define IOP310_HTR     (volatile u8  *)IOP310_REG_ADDR(0x0000100E)
-/* Reserved 0x0000100F through  0x00001017 */
-#define IOP310_PBNR    (volatile u8  *)IOP310_REG_ADDR(0x00001018)
-#define IOP310_SBNR    (volatile u8  *)IOP310_REG_ADDR(0x00001019)
-#define IOP310_SUBBNR  (volatile u8  *)IOP310_REG_ADDR(0x0000101A)
-#define IOP310_SLTR    (volatile u8  *)IOP310_REG_ADDR(0x0000101B)
-#define IOP310_IOBR    (volatile u8  *)IOP310_REG_ADDR(0x0000101C)
-#define IOP310_IOLR    (volatile u8  *)IOP310_REG_ADDR(0x0000101D)
-#define IOP310_SSR     (volatile u16 *)IOP310_REG_ADDR(0x0000101E)
-#define IOP310_MBR     (volatile u16 *)IOP310_REG_ADDR(0x00001020)
-#define IOP310_MLR     (volatile u16 *)IOP310_REG_ADDR(0x00001022)
-#define IOP310_PMBR    (volatile u16 *)IOP310_REG_ADDR(0x00001024)
-#define IOP310_PMLR    (volatile u16 *)IOP310_REG_ADDR(0x00001026)
-/* Reserved 0x00001028 through 0x00001033 */
-#define IOP310_CAPR    (volatile u8  *)IOP310_REG_ADDR(0x00001034)
-/* Reserved 0x00001035 through 0x0000103D */
-#define IOP310_BCR     (volatile u16 *)IOP310_REG_ADDR(0x0000103E)
-#define IOP310_EBCR    (volatile u16 *)IOP310_REG_ADDR(0x00001040)
-#define IOP310_SISR    (volatile u16 *)IOP310_REG_ADDR(0x00001042)
-#define IOP310_PBISR   (volatile u32 *)IOP310_REG_ADDR(0x00001044)
-#define IOP310_SBISR   (volatile u32 *)IOP310_REG_ADDR(0x00001048)
-#define IOP310_SACR    (volatile u32 *)IOP310_REG_ADDR(0x0000104C)
-#define IOP310_PIRSR   (volatile u32 *)IOP310_REG_ADDR(0x00001050)
-#define IOP310_SIOBR   (volatile u8  *)IOP310_REG_ADDR(0x00001054)
-#define IOP310_SIOLR   (volatile u8  *)IOP310_REG_ADDR(0x00001055)
-#define IOP310_SCDR    (volatile u8  *)IOP310_REG_ADDR(0x00001056)
-
-#define IOP310_SMBR    (volatile u16 *)IOP310_REG_ADDR(0x00001058)
-#define IOP310_SMLR    (volatile u16 *)IOP310_REG_ADDR(0x0000105A)
-#define IOP310_SDER    (volatile u16 *)IOP310_REG_ADDR(0x0000105C)
-#define IOP310_QCR     (volatile u16 *)IOP310_REG_ADDR(0x0000105E)
-#define IOP310_CAPID   (volatile u8  *)IOP310_REG_ADDR(0x00001068)
-#define IOP310_NIPTR   (volatile u8  *)IOP310_REG_ADDR(0x00001069)
-#define IOP310_PMCR    (volatile u16 *)IOP310_REG_ADDR(0x0000106A)
-#define IOP310_PMCSR   (volatile u16 *)IOP310_REG_ADDR(0x0000106C)
-#define IOP310_PMCSRBSE (volatile u8 *)IOP310_REG_ADDR(0x0000106E)
-/* Reserved 0x00001064 through 0x000010FFH */
-
-/* Performance monitoring unit  0x00001100 through 0x000011FF*/
-#define IOP310_PMONGTMR    (volatile u32 *)IOP310_REG_ADDR(0x00001100)
-#define IOP310_PMONESR     (volatile u32 *)IOP310_REG_ADDR(0x00001104)
-#define IOP310_PMONEMISR   (volatile u32 *)IOP310_REG_ADDR(0x00001108)
-#define IOP310_PMONGTSR    (volatile u32 *)IOP310_REG_ADDR(0x00001110)
-#define IOP310_PMONPECR1   (volatile u32 *)IOP310_REG_ADDR(0x00001114)
-#define IOP310_PMONPECR2   (volatile u32 *)IOP310_REG_ADDR(0x00001118)
-#define IOP310_PMONPECR3   (volatile u32 *)IOP310_REG_ADDR(0x0000111C)
-#define IOP310_PMONPECR4   (volatile u32 *)IOP310_REG_ADDR(0x00001120)
-#define IOP310_PMONPECR5   (volatile u32 *)IOP310_REG_ADDR(0x00001124)
-#define IOP310_PMONPECR6   (volatile u32 *)IOP310_REG_ADDR(0x00001128)
-#define IOP310_PMONPECR7   (volatile u32 *)IOP310_REG_ADDR(0x0000112C)
-#define IOP310_PMONPECR8   (volatile u32 *)IOP310_REG_ADDR(0x00001130)
-#define IOP310_PMONPECR9   (volatile u32 *)IOP310_REG_ADDR(0x00001134)
-#define IOP310_PMONPECR10  (volatile u32 *)IOP310_REG_ADDR(0x00001138)
-#define IOP310_PMONPECR11  (volatile u32 *)IOP310_REG_ADDR(0x0000113C)
-#define IOP310_PMONPECR12  (volatile u32 *)IOP310_REG_ADDR(0x00001140)
-#define IOP310_PMONPECR13  (volatile u32 *)IOP310_REG_ADDR(0x00001144)
-#define IOP310_PMONPECR14  (volatile u32 *)IOP310_REG_ADDR(0x00001148)
-
-/* Address Translation Unit 0x00001200 through 0x000012FF */
-#define IOP310_ATUVID     (volatile u16 *)IOP310_REG_ADDR(0x00001200)
-#define IOP310_ATUDID     (volatile u16 *)IOP310_REG_ADDR(0x00001202)
-#define IOP310_PATUCMD    (volatile u16 *)IOP310_REG_ADDR(0x00001204)
-#define IOP310_PATUSR     (volatile u16 *)IOP310_REG_ADDR(0x00001206)
-#define IOP310_ATURID     (volatile u8  *)IOP310_REG_ADDR(0x00001208)
-#define IOP310_ATUCCR     (volatile u32 *)IOP310_REG_ADDR(0x00001209)
-#define IOP310_ATUCLSR    (volatile u8  *)IOP310_REG_ADDR(0x0000120C)
-#define IOP310_ATULT      (volatile u8  *)IOP310_REG_ADDR(0x0000120D)
-#define IOP310_ATUHTR     (volatile u8  *)IOP310_REG_ADDR(0x0000120E)
-
-#define IOP310_PIABAR     (volatile u32 *)IOP310_REG_ADDR(0x00001210)
-/* Reserved 0x00001214 through 0x0000122B */
-#define IOP310_ASVIR      (volatile u16 *)IOP310_REG_ADDR(0x0000122C)
-#define IOP310_ASIR       (volatile u16 *)IOP310_REG_ADDR(0x0000122E)
-#define IOP310_ERBAR      (volatile u32 *)IOP310_REG_ADDR(0x00001230)
-#define IOP310_ATUCAPPTR  (volatile u8  *)IOP310_REG_ADDR(0x00001234)
-/* Reserved 0x00001235 through 0x0000123B */
-#define IOP310_ATUILR     (volatile u8  *)IOP310_REG_ADDR(0x0000123C)
-#define IOP310_ATUIPR     (volatile u8  *)IOP310_REG_ADDR(0x0000123D)
-#define IOP310_ATUMGNT    (volatile u8  *)IOP310_REG_ADDR(0x0000123E)
-#define IOP310_ATUMLAT    (volatile u8  *)IOP310_REG_ADDR(0x0000123F)
-#define IOP310_PIALR      (volatile u32 *)IOP310_REG_ADDR(0x00001240)
-#define IOP310_PIATVR     (volatile u32 *)IOP310_REG_ADDR(0x00001244)
-#define IOP310_SIABAR     (volatile u32 *)IOP310_REG_ADDR(0x00001248)
-#define IOP310_SIALR      (volatile u32 *)IOP310_REG_ADDR(0x0000124C)
-#define IOP310_SIATVR     (volatile u32 *)IOP310_REG_ADDR(0x00001250)
-#define IOP310_POMWVR     (volatile u32 *)IOP310_REG_ADDR(0x00001254)
-/* Reserved 0x00001258 through 0x0000125B */
-#define IOP310_POIOWVR    (volatile u32 *)IOP310_REG_ADDR(0x0000125C)
-#define IOP310_PODWVR     (volatile u32 *)IOP310_REG_ADDR(0x00001260)
-#define IOP310_POUDR      (volatile u32 *)IOP310_REG_ADDR(0x00001264)
-#define IOP310_SOMWVR     (volatile u32 *)IOP310_REG_ADDR(0x00001268)
-#define IOP310_SOIOWVR    (volatile u32 *)IOP310_REG_ADDR(0x0000126C)
-/* Reserved 0x00001270 through 0x00001273*/
-#define IOP310_ERLR       (volatile u32 *)IOP310_REG_ADDR(0x00001274)
-#define IOP310_ERTVR      (volatile u32 *)IOP310_REG_ADDR(0x00001278)
-/* Reserved 0x00001279 through 0x0000127C*/
-#define IOP310_ATUCAPID   (volatile u8  *)IOP310_REG_ADDR(0x00001280)
-#define IOP310_ATUNIPTR   (volatile u8  *)IOP310_REG_ADDR(0x00001281)
-#define IOP310_APMCR      (volatile u16 *)IOP310_REG_ADDR(0x00001282)
-#define IOP310_APMCSR     (volatile u16 *)IOP310_REG_ADDR(0x00001284)
-/* Reserved 0x00001286 through 0x00001287 */
-#define IOP310_ATUCR      (volatile u32 *)IOP310_REG_ADDR(0x00001288)
-/* Reserved 0x00001289  through 0x0000128C*/
-#define IOP310_PATUISR    (volatile u32 *)IOP310_REG_ADDR(0x00001290)
-#define IOP310_SATUISR    (volatile u32 *)IOP310_REG_ADDR(0x00001294)
-#define IOP310_SATUCMD    (volatile u16 *)IOP310_REG_ADDR(0x00001298)
-#define IOP310_SATUSR     (volatile u16 *)IOP310_REG_ADDR(0x0000129A)
-#define IOP310_SODWVR     (volatile u32 *)IOP310_REG_ADDR(0x0000129C)
-#define IOP310_SOUDR      (volatile u32 *)IOP310_REG_ADDR(0x000012A0)
-#define IOP310_POCCAR     (volatile u32 *)IOP310_REG_ADDR(0x000012A4)
-#define IOP310_SOCCAR     (volatile u32 *)IOP310_REG_ADDR(0x000012A8)
-#define IOP310_POCCDR     (volatile u32 *)IOP310_REG_ADDR(0x000012AC)
-#define IOP310_SOCCDR     (volatile u32 *)IOP310_REG_ADDR(0x000012B0)
-#define IOP310_PAQCR      (volatile u32 *)IOP310_REG_ADDR(0x000012B4)
-#define IOP310_SAQCR      (volatile u32 *)IOP310_REG_ADDR(0x000012B8)
-#define IOP310_PATUIMR    (volatile u32 *)IOP310_REG_ADDR(0x000012BC)
-#define IOP310_SATUIMR    (volatile u32 *)IOP310_REG_ADDR(0x000012C0)
-/* Reserved 0x000012C4 through 0x000012FF */
-/* Messaging Unit 0x00001300 through 0x000013FF */
-#define IOP310_MUIMR0       (volatile u32 *)IOP310_REG_ADDR(0x00001310)
-#define IOP310_MUIMR1       (volatile u32 *)IOP310_REG_ADDR(0x00001314)
-#define IOP310_MUOMR0       (volatile u32 *)IOP310_REG_ADDR(0x00001318)
-#define IOP310_MUOMR1       (volatile u32 *)IOP310_REG_ADDR(0x0000131C)
-#define IOP310_MUIDR        (volatile u32 *)IOP310_REG_ADDR(0x00001320)
-#define IOP310_MUIISR       (volatile u32 *)IOP310_REG_ADDR(0x00001324)
-#define IOP310_MUIIMR       (volatile u32 *)IOP310_REG_ADDR(0x00001328)
-#define IOP310_MUODR        (volatile u32 *)IOP310_REG_ADDR(0x0000132C)
-#define IOP310_MUOISR       (volatile u32 *)IOP310_REG_ADDR(0x00001330)
-#define IOP310_MUOIMR       (volatile u32 *)IOP310_REG_ADDR(0x00001334)
-#define IOP310_MUMUCR       (volatile u32 *)IOP310_REG_ADDR(0x00001350)
-#define IOP310_MUQBAR       (volatile u32 *)IOP310_REG_ADDR(0x00001354)
-#define IOP310_MUIFHPR      (volatile u32 *)IOP310_REG_ADDR(0x00001360)
-#define IOP310_MUIFTPR      (volatile u32 *)IOP310_REG_ADDR(0x00001364)
-#define IOP310_MUIPHPR      (volatile u32 *)IOP310_REG_ADDR(0x00001368)
-#define IOP310_MUIPTPR      (volatile u32 *)IOP310_REG_ADDR(0x0000136C)
-#define IOP310_MUOFHPR      (volatile u32 *)IOP310_REG_ADDR(0x00001370)
-#define IOP310_MUOFTPR      (volatile u32 *)IOP310_REG_ADDR(0x00001374)
-#define IOP310_MUOPHPR      (volatile u32 *)IOP310_REG_ADDR(0x00001378)
-#define IOP310_MUOPTPR      (volatile u32 *)IOP310_REG_ADDR(0x0000137C)
-#define IOP310_MUIAR        (volatile u32 *)IOP310_REG_ADDR(0x00001380)
-/* DMA Controller 0x00001400 through 0x000014FF */
-#define IOP310_DMA0CCR     (volatile u32 *)IOP310_REG_ADDR(0x00001400)
-#define IOP310_DMA0CSR     (volatile u32 *)IOP310_REG_ADDR(0x00001404)
-/* Reserved 0x001408 through 0x00140B */
-#define IOP310_DMA0DAR     (volatile u32 *)IOP310_REG_ADDR(0x0000140C)
-#define IOP310_DMA0NDAR    (volatile u32 *)IOP310_REG_ADDR(0x00001410)
-#define IOP310_DMA0PADR    (volatile u32 *)IOP310_REG_ADDR(0x00001414)
-#define IOP310_DMA0PUADR   (volatile u32 *)IOP310_REG_ADDR(0x00001418)
-#define IOP310_DMA0LADR    (volatile u32 *)IOP310_REG_ADDR(0x0000141C)
-#define IOP310_DMA0BCR     (volatile u32 *)IOP310_REG_ADDR(0x00001420)
-#define IOP310_DMA0DCR     (volatile u32 *)IOP310_REG_ADDR(0x00001424)
-/* Reserved 0x00001428 through 0x0000143F */
-#define IOP310_DMA1CCR     (volatile u32 *)IOP310_REG_ADDR(0x00001440)
-#define IOP310_DMA1CSR     (volatile u32 *)IOP310_REG_ADDR(0x00001444)
-/* Reserved 0x00001448 through 0x0000144B */
-#define IOP310_DMA1DAR     (volatile u32 *)IOP310_REG_ADDR(0x0000144C)
-#define IOP310_DMA1NDAR    (volatile u32 *)IOP310_REG_ADDR(0x00001450)
-#define IOP310_DMA1PADR    (volatile u32 *)IOP310_REG_ADDR(0x00001454)
-#define IOP310_DMA1PUADR   (volatile u32 *)IOP310_REG_ADDR(0x00001458)
-#define IOP310_DMA1LADR    (volatile u32 *)IOP310_REG_ADDR(0x0000145C)
-#define IOP310_DMA1BCR     (volatile u32 *)IOP310_REG_ADDR(0x00001460)
-#define IOP310_DMA1DCR     (volatile u32 *)IOP310_REG_ADDR(0x00001464)
-/* Reserved 0x00001468 through 0x0000147F */
-#define IOP310_DMA2CCR     (volatile u32 *)IOP310_REG_ADDR(0x00001480)
-#define IOP310_DMA2CSR     (volatile u32 *)IOP310_REG_ADDR(0x00001484)
-/* Reserved 0x00001488 through 0x0000148B */
-#define IOP310_DMA2DAR     (volatile u32 *)IOP310_REG_ADDR(0x0000148C)
-#define IOP310_DMA2NDAR    (volatile u32 *)IOP310_REG_ADDR(0x00001490)
-#define IOP310_DMA2PADR    (volatile u32 *)IOP310_REG_ADDR(0x00001494)
-#define IOP310_DMA2PUADR   (volatile u32 *)IOP310_REG_ADDR(0x00001498)
-#define IOP310_DMA2LADR    (volatile u32 *)IOP310_REG_ADDR(0x0000149C)
-#define IOP310_DMA2BCR     (volatile u32 *)IOP310_REG_ADDR(0x000014A0)
-#define IOP310_DMA2DCR     (volatile u32 *)IOP310_REG_ADDR(0x000014A4)
-
-/* Memory controller 0x00001500 through 0x0015FF */
-
-/* core interface unit 0x00001640 - 0x0000167F */
-#define IOP310_CIUISR     (volatile u32 *)IOP310_REG_ADDR(0x00001644)
-
-/* PCI and Peripheral Interrupt Controller 0x00001700 - 0x0000171B */
-#define IOP310_IRQISR     (volatile u32 *)IOP310_REG_ADDR(0x00001700)
-#define IOP310_FIQ2ISR    (volatile u32 *)IOP310_REG_ADDR(0x00001704)
-#define IOP310_FIQ1ISR    (volatile u32 *)IOP310_REG_ADDR(0x00001708)
-#define IOP310_PDIDR      (volatile u32 *)IOP310_REG_ADDR(0x00001710)
-
-/* AAU registers. DJ 0x00001800 - 0x00001838 */
-#define IOP310_AAUACR    (volatile u32 *)IOP310_REG_ADDR(0x00001800)
-#define IOP310_AAUASR    (volatile u32 *)IOP310_REG_ADDR(0x00001804)
-#define IOP310_AAUADAR   (volatile u32 *)IOP310_REG_ADDR(0x00001808)
-#define IOP310_AAUANDAR  (volatile u32 *)IOP310_REG_ADDR(0x0000180C)
-#define IOP310_AAUSAR1   (volatile u32 *)IOP310_REG_ADDR(0x00001810)
-#define IOP310_AAUSAR2   (volatile u32 *)IOP310_REG_ADDR(0x00001814)
-#define IOP310_AAUSAR3   (volatile u32 *)IOP310_REG_ADDR(0x00001818)
-#define IOP310_AAUSAR4   (volatile u32 *)IOP310_REG_ADDR(0x0000181C)
-#define IOP310_AAUDAR    (volatile u32 *)IOP310_REG_ADDR(0x00001820)
-#define IOP310_AAUABCR   (volatile u32 *)IOP310_REG_ADDR(0x00001824)
-#define IOP310_AAUADCR   (volatile u32 *)IOP310_REG_ADDR(0x00001828)
-#define IOP310_AAUSAR5   (volatile u32 *)IOP310_REG_ADDR(0x0000182C)
-#define IOP310_AAUSAR6   (volatile u32 *)IOP310_REG_ADDR(0x00001830)
-#define IOP310_AAUSAR7   (volatile u32 *)IOP310_REG_ADDR(0x00001834)
-#define IOP310_AAUSAR8   (volatile u32 *)IOP310_REG_ADDR(0x00001838)
-
-#endif // _IOP310_HW_H_
diff -Nru a/include/asm-arm/arch-iop3xx/iop321-irqs.h b/include/asm-arm/arch-iop3xx/iop321-irqs.h
--- a/include/asm-arm/arch-iop3xx/iop321-irqs.h	2004-10-18 14:56:29 -07:00
+++ b/include/asm-arm/arch-iop3xx/iop321-irqs.h	2004-10-18 14:56:29 -07:00
@@ -9,8 +9,8 @@
  * published by the Free Software Foundation.
  *
  */
-
-#include <linux/config.h>
+#ifndef _IOP321_IRQS_H_
+#define _IOP321_IRQS_H_
 
 /*
  * IOP80321 chipset interrupts
@@ -62,7 +62,6 @@
 /*
  * Interrupts available on the IQ80321 board
  */
-#ifdef CONFIG_ARCH_IQ80321
 
 /*
  * On board devices
@@ -78,7 +77,24 @@
 #define	IRQ_IQ80321_INTC	IRQ_IOP321_XINT2
 #define	IRQ_IQ80321_INTD	IRQ_IOP321_XINT3
 
-#endif // CONFIG_ARCH_IQ80321
+/*
+ * Interrupts on the IQ31244 board
+ */
+
+/*
+ * On board devices
+ */
+#define IRQ_IQ31244_UART	IRQ_IOP321_XINT1
+#define	IRQ_IQ31244_I82546	IRQ_IOP321_XINT0
+#define IRQ_IQ31244_SATA	IRQ_IOP321_XINT2
+#define	IRQ_IQ31244_PCIX_SLOT	IRQ_IOP321_XINT3
 
-#define XSCALE_PMU_IRQ	IRQ_IOP321_CORE_PMU
+/*
+ * PCI interrupts
+ */
+#define	IRQ_IQ31244_INTA	IRQ_IOP321_XINT0
+#define	IRQ_IQ31244_INTB	IRQ_IOP321_XINT1
+#define	IRQ_IQ31244_INTC	IRQ_IOP321_XINT2
+#define	IRQ_IQ31244_INTD	IRQ_IOP321_XINT3
 
+#endif // _IOP321_IRQ_H_
diff -Nru a/include/asm-arm/arch-iop3xx/iop321.h b/include/asm-arm/arch-iop3xx/iop321.h
--- a/include/asm-arm/arch-iop3xx/iop321.h	2004-10-18 14:57:05 -07:00
+++ b/include/asm-arm/arch-iop3xx/iop321.h	2004-10-18 14:57:05 -07:00
@@ -20,23 +20,29 @@
  * IOP3xx variants but behave slightly differently on each.
  */
 #ifndef __ASSEMBLY__
-#define iop_is_321() ((processor_id & 0xfffff7e0) == 0x69052420)
+#ifdef	CONFIG_ARCH_IOP321
+#define iop_is_321() (((processor_id & 0xfffff5e0) == 0x69052420))
+#else
+#define	iop_is_321()	0
+#endif
 #endif
-
 
 /*
  * IOP321 I/O and Mem space regions for PCI autoconfiguration
  */
+#define IOP321_PCI_LOWER_IO             0x90000000
+#define IOP321_PCI_UPPER_IO             0x9000ffff
+#define IOP321_PCI_LOWER_MEM            0x80000000
+#define IOP321_PCI_UPPER_MEM            0x83ffffff
+
+#define IOP321_PCI_WINDOW_SIZE          64 * 0x100000
 
-#define	IOP321_PCI_IO_BASE		0x90000000
-#define	IOP321_PCI_IO_SIZE		0x00010000
-#define IOP321_PCI_MEM_BASE		0x40000000
-#define IOP321_PCI_MEM_SIZE		0x40000000
 
 /*
  * IOP321 chipset registers
  */
-#define IOP321_VIRT_MEM_BASE 0xfff00000  /* chip virtual mem address*/
+#define IOP321_VIRT_MEM_BASE 0xfeffe000  /* chip virtual mem address*/
+//#define IOP321_VIRT_MEM_BASE 0xfff00000  /* chip virtual mem address*/
 
 #define IOP321_PHY_MEM_BASE  0xffffe000  /* chip physical memory address */
 #define IOP321_REG_ADDR(reg) (IOP321_VIRT_MEM_BASE | (reg))
@@ -134,6 +140,16 @@
 #define IOP321_OPHPR      (volatile u32 *)IOP321_REG_ADDR(0x00000378)
 #define IOP321_OPTPR      (volatile u32 *)IOP321_REG_ADDR(0x0000037C)
 #define IOP321_IAR        (volatile u32 *)IOP321_REG_ADDR(0x00000380)
+
+#define IOP321_IIxR_MASK	0x7f /* masks all */
+#define IOP321_IIxR_IRI		0x40 /* RC Index Register Interrupt */
+#define IOP321_IIxR_OFQF	0x20 /* RC Output Free Q Full (ERROR) */
+#define IOP321_IIxR_ipq		0x10 /* RC Inbound Post Q (post) */
+#define IOP321_IIxR_ERRDI	0x08 /* RO Error Doorbell Interrupt */
+#define IOP321_IIxR_IDI		0x04 /* RO Inbound Doorbell Interrupt */
+#define IOP321_IIxR_IM1		0x02 /* RC Inbound Message 1 Interrupt */
+#define IOP321_IIxR_IM0		0x01 /* RC Inbound Message 0 Interrupt */
+
 /* Reserved 0x00000384 through 0x000003FF */
 
 /* DMA Controller 0x00000400 through 0x000004FF */
@@ -186,10 +202,21 @@
 
 #define IOP321_PBISR_BOOR_ERR 0x1
 
+/* Peripheral performance monitoring unit 0x00000700 through 0x00077F */
+#define IOP321_GTMR	(volatile u32 *)IOP321_REG_ADDR(0x00000700)
+#define IOP321_ESR	(volatile u32 *)IOP321_REG_ADDR(0x00000704)
+#define IOP321_EMISR	(volatile u32 *)IOP321_REG_ADDR(0x00000708)
+/* reserved 0x00000070c */
+#define IOP321_GTSR	(volatile u32 *)IOP321_REG_ADDR(0x00000710)
+/* PERC0 DOESN'T EXIST - index from 1! */
+#define IOP321_PERCR0	(volatile u32 *)IOP321_REG_ADDR(0x00000710)
 
+#define IOP321_GTMR_NGCE	0x04 /* (Not) Global Counter Enable */
 
-/* Peripheral performance monitoring unit 0x00000700 through 0x00077F */
 /* Internal arbitration unit 0x00000780 through 0x0007BF */
+#define IOP321_IACR	(volatile u32 *)IOP321_REG_ADDR(0x00000780)
+#define IOP321_MTTR1	(volatile u32 *)IOP321_REG_ADDR(0x00000784)
+#define IOP321_MTTR2	(volatile u32 *)IOP321_REG_ADDR(0x00000788)
 
 /* General Purpose I/O Registers */
 #define IOP321_GPOE       (volatile u32 *)IOP321_REG_ADDR(0x000007C4)
@@ -207,6 +234,17 @@
 #define IOP321_TU_TMR0		(volatile u32 *)IOP321_REG_ADDR(0x000007E0)
 #define IOP321_TU_TMR1		(volatile u32 *)IOP321_REG_ADDR(0x000007E4)
 
+#ifdef CONFIG_ARCH_IQ80321
+#define	IOP321_TICK_RATE	200000000	/* 200 MHz clock */
+#elif defined(CONFIG_ARCH_IQ31244)
+#define IOP321_TICK_RATE	198000000	/* 33.000 MHz crystal */
+#endif
+
+#ifdef CONFIG_ARCH_EP80219
+#undef IOP321_TICK_RATE
+#define IOP321_TICK_RATE 200000000 /* 33.333333 Mhz crystal */
+#endif
+
 #define IOP321_TMR_TC		0x01
 #define	IOP321_TMR_EN		0x02
 #define IOP321_TMR_RELOAD	0x04
@@ -224,15 +262,43 @@
 #define IOP321_TU_TISR    (volatile u32 *)IOP321_REG_ADDR(0x000007F8)
 #define IOP321_TU_WDTCR   (volatile u32 *)IOP321_REG_ADDR(0x000007FC)
 
-
-
 /* Application accelerator unit 0x00000800 - 0x000008FF */
 #define IOP321_AAU_ACR     (volatile u32 *)IOP321_REG_ADDR(0x00000800)
 #define IOP321_AAU_ASR     (volatile u32 *)IOP321_REG_ADDR(0x00000804)
 #define IOP321_AAU_ADAR    (volatile u32 *)IOP321_REG_ADDR(0x00000808)
 #define IOP321_AAU_ANDAR   (volatile u32 *)IOP321_REG_ADDR(0x0000080C)
 #define IOP321_AAU_SAR1    (volatile u32 *)IOP321_REG_ADDR(0x00000810)
-/* SAR2...SAR32 0x00000814 - 0x000008A4 */
+#define IOP321_AAU_SAR2    (volatile u32 *)IOP321_REG_ADDR(0x00000814)
+#define IOP321_AAU_SAR3    (volatile u32 *)IOP321_REG_ADDR(0x00000818)
+#define IOP321_AAU_SAR4    (volatile u32 *)IOP321_REG_ADDR(0x0000081C)
+#define IOP321_AAU_SAR5    (volatile u32 *)IOP321_REG_ADDR(0x0000082C)
+#define IOP321_AAU_SAR6    (volatile u32 *)IOP321_REG_ADDR(0x00000830)
+#define IOP321_AAU_SAR7    (volatile u32 *)IOP321_REG_ADDR(0x00000834)
+#define IOP321_AAU_SAR8    (volatile u32 *)IOP321_REG_ADDR(0x00000838)
+#define IOP321_AAU_SAR9    (volatile u32 *)IOP321_REG_ADDR(0x00000840)
+#define IOP321_AAU_SAR10   (volatile u32 *)IOP321_REG_ADDR(0x00000844)
+#define IOP321_AAU_SAR11   (volatile u32 *)IOP321_REG_ADDR(0x00000848)
+#define IOP321_AAU_SAR12   (volatile u32 *)IOP321_REG_ADDR(0x0000084C)
+#define IOP321_AAU_SAR13   (volatile u32 *)IOP321_REG_ADDR(0x00000850)
+#define IOP321_AAU_SAR14   (volatile u32 *)IOP321_REG_ADDR(0x00000854)
+#define IOP321_AAU_SAR15   (volatile u32 *)IOP321_REG_ADDR(0x00000858)
+#define IOP321_AAU_SAR16   (volatile u32 *)IOP321_REG_ADDR(0x0000085C)
+#define IOP321_AAU_SAR17   (volatile u32 *)IOP321_REG_ADDR(0x00000864)
+#define IOP321_AAU_SAR18   (volatile u32 *)IOP321_REG_ADDR(0x00000868)
+#define IOP321_AAU_SAR19   (volatile u32 *)IOP321_REG_ADDR(0x0000086C)
+#define IOP321_AAU_SAR20   (volatile u32 *)IOP321_REG_ADDR(0x00000870)
+#define IOP321_AAU_SAR21   (volatile u32 *)IOP321_REG_ADDR(0x00000874)
+#define IOP321_AAU_SAR22   (volatile u32 *)IOP321_REG_ADDR(0x00000878)
+#define IOP321_AAU_SAR23   (volatile u32 *)IOP321_REG_ADDR(0x0000087C)
+#define IOP321_AAU_SAR24   (volatile u32 *)IOP321_REG_ADDR(0x00000880)
+#define IOP321_AAU_SAR25   (volatile u32 *)IOP321_REG_ADDR(0x00000888)
+#define IOP321_AAU_SAR26   (volatile u32 *)IOP321_REG_ADDR(0x0000088C)
+#define IOP321_AAU_SAR27   (volatile u32 *)IOP321_REG_ADDR(0x00000890)
+#define IOP321_AAU_SAR28   (volatile u32 *)IOP321_REG_ADDR(0x00000894)
+#define IOP321_AAU_SAR29   (volatile u32 *)IOP321_REG_ADDR(0x00000898)
+#define IOP321_AAU_SAR30   (volatile u32 *)IOP321_REG_ADDR(0x0000089C)
+#define IOP321_AAU_SAR31   (volatile u32 *)IOP321_REG_ADDR(0x000008A0)
+#define IOP321_AAU_SAR32   (volatile u32 *)IOP321_REG_ADDR(0x000008A4)
 #define IOP321_AAU_DAR     (volatile u32 *)IOP321_REG_ADDR(0x00000820)
 #define IOP321_AAU_ABCR    (volatile u32 *)IOP321_REG_ADDR(0x00000824)
 #define IOP321_AAU_ADCR    (volatile u32 *)IOP321_REG_ADDR(0x00000828)
@@ -259,5 +325,12 @@
 /* Reserved 0x000016B8 through 0x000016FC */
 
 /* for I2C bit defs see drivers/i2c/i2c-iop3xx.h */
+
+
+#ifndef __ASSEMBLY__
+extern void iop321_map_io(void);
+extern void iop321_init_irq(void);
+extern void iop321_time_init(void);
+#endif
 
 #endif // _IOP321_HW_H_
diff -Nru a/include/asm-arm/arch-iop3xx/iop331-irqs.h b/include/asm-arm/arch-iop3xx/iop331-irqs.h
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/include/asm-arm/arch-iop3xx/iop331-irqs.h	2004-10-18 14:57:22 -07:00
@@ -0,0 +1,113 @@
+/*
+ * linux/include/asm-arm/arch-iop3xx/irqs.h
+ *
+ * Author:	Dave Jiang (dave.jiang@intel.com)
+ * Copyright:	(C) 2003 Intel Corp.
+ *
+ * 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.
+ *
+ */
+#ifndef _IOP331_IRQS_H_
+#define _IOP331_IRQS_H_
+
+/*
+ * IOP80331 chipset interrupts
+ */
+#define IOP331_IRQ_OFS		0
+#define IOP331_IRQ(x)		(IOP331_IRQ_OFS + (x))
+
+/*
+ * On IRQ or FIQ register
+ */
+#define IRQ_IOP331_DMA0_EOT	IOP331_IRQ(0)
+#define IRQ_IOP331_DMA0_EOC	IOP331_IRQ(1)
+#define IRQ_IOP331_DMA1_EOT	IOP331_IRQ(2)
+#define IRQ_IOP331_DMA1_EOC	IOP331_IRQ(3)
+#define IRQ_IOP331_RSVD_4	IOP331_IRQ(4)
+#define IRQ_IOP331_RSVD_5	IOP331_IRQ(5)
+#define IRQ_IOP331_AA_EOT	IOP331_IRQ(6)
+#define IRQ_IOP331_AA_EOC	IOP331_IRQ(7)
+#define IRQ_IOP331_TIMER0	IOP331_IRQ(8)
+#define IRQ_IOP331_TIMER1	IOP331_IRQ(9)
+#define IRQ_IOP331_I2C_0	IOP331_IRQ(10)
+#define IRQ_IOP331_I2C_1	IOP331_IRQ(11)
+#define IRQ_IOP331_MSG	    IOP331_IRQ(12)
+#define IRQ_IOP331_MSGIBQ   IOP331_IRQ(13)
+#define IRQ_IOP331_ATU_BIST	IOP331_IRQ(14)
+#define IRQ_IOP331_PERFMON	IOP331_IRQ(15)
+#define IRQ_IOP331_CORE_PMU	IOP331_IRQ(16)
+#define IRQ_IOP331_RSVD_17	IOP331_IRQ(17)
+#define IRQ_IOP331_RSVD_18	IOP331_IRQ(18)
+#define IRQ_IOP331_RSVD_19	IOP331_IRQ(19)
+#define IRQ_IOP331_RSVD_20	IOP331_IRQ(20)
+#define IRQ_IOP331_RSVD_21	IOP331_IRQ(21)
+#define IRQ_IOP331_RSVD_22	IOP331_IRQ(22)
+#define IRQ_IOP331_RSVD_23	IOP331_IRQ(23)
+#define IRQ_IOP331_XINT0	IOP331_IRQ(24)
+#define IRQ_IOP331_XINT1	IOP331_IRQ(25)
+#define IRQ_IOP331_XINT2	IOP331_IRQ(26)
+#define IRQ_IOP331_XINT3	IOP331_IRQ(27)
+#define IRQ_IOP331_RSVD_28  IOP331_IRQ(28)
+#define IRQ_IOP331_RSVD_29  IOP331_IRQ(29)
+#define IRQ_IOP331_RSVD_30  IOP331_IRQ(30)
+#define IRQ_IOP331_RSVD_31  IOP331_IRQ(31)
+#define IRQ_IOP331_XINT8    IOP331_IRQ(32)  // 0
+#define IRQ_IOP331_XINT9    IOP331_IRQ(33)  // 1
+#define IRQ_IOP331_XINT10   IOP331_IRQ(34)  // 2
+#define IRQ_IOP331_XINT11   IOP331_IRQ(35)  // 3
+#define IRQ_IOP331_XINT12   IOP331_IRQ(36)  // 4
+#define IRQ_IOP331_XINT13   IOP331_IRQ(37)  // 5
+#define IRQ_IOP331_XINT14   IOP331_IRQ(38)  // 6
+#define IRQ_IOP331_XINT15   IOP331_IRQ(39)  // 7
+#define IRQ_IOP331_RSVD_40  IOP331_IRQ(40)  // 8
+#define IRQ_IOP331_RSVD_41  IOP331_IRQ(41)  // 9
+#define IRQ_IOP331_RSVD_42  IOP331_IRQ(42)  // 10
+#define IRQ_IOP331_RSVD_43  IOP331_IRQ(43)  // 11
+#define IRQ_IOP331_RSVD_44  IOP331_IRQ(44)  // 12
+#define IRQ_IOP331_RSVD_45  IOP331_IRQ(45)  // 13
+#define IRQ_IOP331_RSVD_46  IOP331_IRQ(46)  // 14
+#define IRQ_IOP331_RSVD_47  IOP331_IRQ(47)  // 15
+#define IRQ_IOP331_RSVD_48  IOP331_IRQ(48)  // 16
+#define IRQ_IOP331_RSVD_49  IOP331_IRQ(49)  // 17
+#define IRQ_IOP331_RSVD_50  IOP331_IRQ(50)  // 18
+#define IRQ_IOP331_UART0    IOP331_IRQ(51)  // 19
+#define IRQ_IOP331_UART1    IOP331_IRQ(52)  // 20
+#define IRQ_IOP331_PBIE     IOP331_IRQ(53)  // 21
+#define IRQ_IOP331_ATU_CRW  IOP331_IRQ(54)  // 22
+#define IRQ_IOP331_ATU_ERR	IOP331_IRQ(55)  // 23
+#define IRQ_IOP331_MCU_ERR	IOP331_IRQ(56)  // 24
+#define IRQ_IOP331_DMA0_ERR	IOP331_IRQ(57)  // 25
+#define IRQ_IOP331_DMA1_ERR	IOP331_IRQ(58)  // 26
+#define IRQ_IOP331_RSVD_59  IOP331_IRQ(59)  // 27
+#define IRQ_IOP331_AA_ERR	IOP331_IRQ(60)  // 28
+#define IRQ_IOP331_RSVD_61  IOP331_IRQ(61)  // 29
+#define IRQ_IOP331_MSG_ERR	IOP331_IRQ(62)  // 30
+#define IRQ_IOP331_HPI		IOP331_IRQ(63)  // 31
+
+#define NR_IOP331_IRQS		(IOP331_IRQ(63) + 1)
+
+#define NR_IRQS			NR_IOP331_IRQS
+
+
+/*
+ * Interrupts available on the IQ80331 board
+ */
+
+/*
+ * On board devices
+ */
+#define	IRQ_IQ80331_I82544	IRQ_IOP331_XINT0
+#define IRQ_IQ80331_UART0	IRQ_IOP331_UART0
+#define IRQ_IQ80331_UART1	IRQ_IOP331_UART1
+
+/*
+ * PCI interrupts
+ */
+#define	IRQ_IQ80331_INTA	IRQ_IOP331_XINT0
+#define	IRQ_IQ80331_INTB	IRQ_IOP331_XINT1
+#define	IRQ_IQ80331_INTC	IRQ_IOP331_XINT2
+#define	IRQ_IQ80331_INTD	IRQ_IOP331_XINT3
+
+#endif // _IOP331_IRQ_H_
diff -Nru a/include/asm-arm/arch-iop3xx/iop331.h b/include/asm-arm/arch-iop3xx/iop331.h
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/include/asm-arm/arch-iop3xx/iop331.h	2004-10-18 14:57:23 -07:00
@@ -0,0 +1,342 @@
+/*
+ * linux/include/asm/arch-iop3xx/iop331.h
+ *
+ * Intel IOP331 Chip definitions
+ *
+ * Author: Dave Jiang (dave.jiang@intel.com)
+ * Copyright (C) 2003 Intel Corp.
+ *
+ * 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.
+ */
+
+#ifndef _IOP331_HW_H_
+#define _IOP331_HW_H_
+
+
+/*
+ * This is needed for mixed drivers that need to work on all
+ * IOP3xx variants but behave slightly differently on each.
+ */
+#ifndef __ASSEMBLY__
+#ifdef	CONFIG_ARCH_IOP331
+#define	iop_is_331()	((processor_id & 0xffffffb0) == 0x69054090)
+#else
+#define	iop_is_331()	0
+#endif
+#endif
+
+/*
+ * IOP331 I/O and Mem space regions for PCI autoconfiguration
+ */
+#define IOP331_PCI_LOWER_IO             0x90000000
+#define IOP331_PCI_UPPER_IO             0x900fffff
+#define IOP331_PCI_LOWER_MEM            0x80000000
+#define IOP331_PCI_UPPER_MEM            0x87ffffff
+
+#define IOP331_PCI_WINDOW_SIZE          128 * 0x100000
+
+
+/*
+ * IOP331 chipset registers
+ */
+#define IOP331_VIRT_MEM_BASE 0xfeffe000  /* chip virtual mem address*/
+// #define IOP331_VIRT_MEM_BASE 0xfff00000  /* chip virtual mem address*/
+
+#define IOP331_PHYS_MEM_BASE  0xffffe000  /* chip physical memory address */
+#define IOP331_REG_ADDR(reg) (IOP331_VIRT_MEM_BASE | (reg))
+
+/* Reserved 0x00000000 through 0x000000FF */
+
+/* Address Translation Unit 0x00000100 through 0x000001FF */
+#define IOP331_ATUVID     (volatile u16 *)IOP331_REG_ADDR(0x00000100)
+#define IOP331_ATUDID     (volatile u16 *)IOP331_REG_ADDR(0x00000102)
+#define IOP331_ATUCMD     (volatile u16 *)IOP331_REG_ADDR(0x00000104)
+#define IOP331_ATUSR      (volatile u16 *)IOP331_REG_ADDR(0x00000106)
+#define IOP331_ATURID     (volatile u8  *)IOP331_REG_ADDR(0x00000108)
+#define IOP331_ATUCCR     (volatile u32 *)IOP331_REG_ADDR(0x00000109)
+#define IOP331_ATUCLSR    (volatile u8  *)IOP331_REG_ADDR(0x0000010C)
+#define IOP331_ATULT      (volatile u8  *)IOP331_REG_ADDR(0x0000010D)
+#define IOP331_ATUHTR     (volatile u8  *)IOP331_REG_ADDR(0x0000010E)
+#define IOP331_ATUBIST    (volatile u8  *)IOP331_REG_ADDR(0x0000010F)
+#define IOP331_IABAR0     (volatile u32 *)IOP331_REG_ADDR(0x00000110)
+#define IOP331_IAUBAR0    (volatile u32 *)IOP331_REG_ADDR(0x00000114)
+#define IOP331_IABAR1     (volatile u32 *)IOP331_REG_ADDR(0x00000118)
+#define IOP331_IAUBAR1    (volatile u32 *)IOP331_REG_ADDR(0x0000011C)
+#define IOP331_IABAR2     (volatile u32 *)IOP331_REG_ADDR(0x00000120)
+#define IOP331_IAUBAR2    (volatile u32 *)IOP331_REG_ADDR(0x00000124)
+#define IOP331_ASVIR      (volatile u16 *)IOP331_REG_ADDR(0x0000012C)
+#define IOP331_ASIR       (volatile u16 *)IOP331_REG_ADDR(0x0000012E)
+#define IOP331_ERBAR      (volatile u32 *)IOP331_REG_ADDR(0x00000130)
+#define IOP331_ATU_CAPPTR (volatile u32 *)IOP331_REG_ADDR(0x00000134)
+/* Reserved 0x00000138 through 0x0000013B */
+#define IOP331_ATUILR     (volatile u8  *)IOP331_REG_ADDR(0x0000013C)
+#define IOP331_ATUIPR     (volatile u8  *)IOP331_REG_ADDR(0x0000013D)
+#define IOP331_ATUMGNT    (volatile u8  *)IOP331_REG_ADDR(0x0000013E)
+#define IOP331_ATUMLAT    (volatile u8  *)IOP331_REG_ADDR(0x0000013F)
+#define IOP331_IALR0      (volatile u32 *)IOP331_REG_ADDR(0x00000140)
+#define IOP331_IATVR0     (volatile u32 *)IOP331_REG_ADDR(0x00000144)
+#define IOP331_ERLR       (volatile u32 *)IOP331_REG_ADDR(0x00000148)
+#define IOP331_ERTVR      (volatile u32 *)IOP331_REG_ADDR(0x0000014C)
+#define IOP331_IALR1      (volatile u32 *)IOP331_REG_ADDR(0x00000150)
+#define IOP331_IALR2      (volatile u32 *)IOP331_REG_ADDR(0x00000154)
+#define IOP331_IATVR2     (volatile u32 *)IOP331_REG_ADDR(0x00000158)
+#define IOP331_OIOWTVR    (volatile u32 *)IOP331_REG_ADDR(0x0000015C)
+#define IOP331_OMWTVR0    (volatile u32 *)IOP331_REG_ADDR(0x00000160)
+#define IOP331_OUMWTVR0   (volatile u32 *)IOP331_REG_ADDR(0x00000164)
+#define IOP331_OMWTVR1    (volatile u32 *)IOP331_REG_ADDR(0x00000168)
+#define IOP331_OUMWTVR1   (volatile u32 *)IOP331_REG_ADDR(0x0000016C)
+/* Reserved 0x00000170 through 0x00000177*/
+#define IOP331_OUDWTVR    (volatile u32 *)IOP331_REG_ADDR(0x00000178)
+/* Reserved 0x0000017C through 0x0000017F*/
+#define IOP331_ATUCR      (volatile u32 *)IOP331_REG_ADDR(0x00000180)
+#define IOP331_PCSR       (volatile u32 *)IOP331_REG_ADDR(0x00000184)
+#define IOP331_ATUISR     (volatile u32 *)IOP331_REG_ADDR(0x00000188)
+#define IOP331_ATUIMR     (volatile u32 *)IOP331_REG_ADDR(0x0000018C)
+#define IOP331_IABAR3     (volatile u32 *)IOP331_REG_ADDR(0x00000190)
+#define IOP331_IAUBAR3    (volatile u32 *)IOP331_REG_ADDR(0x00000194)
+#define IOP331_IALR3      (volatile u32 *)IOP331_REG_ADDR(0x00000198)
+#define IOP331_IATVR3     (volatile u32 *)IOP331_REG_ADDR(0x0000019C)
+/* Reserved 0x000001A0 through 0x000001A3*/
+#define IOP331_OCCAR      (volatile u32 *)IOP331_REG_ADDR(0x000001A4)
+/* Reserved 0x000001A8 through 0x000001AB*/
+#define IOP331_OCCDR      (volatile u32 *)IOP331_REG_ADDR(0x000001AC)
+/* Reserved 0x000001B0 through 0x000001BB*/
+#define IOP331_VPDCAPID   (volatile u8 *)IOP331_REG_ADDR(0x000001B8)
+#define IOP331_VPDNXTP    (volatile u8 *)IOP331_REG_ADDR(0x000001B9)
+#define IOP331_VPDAR	  (volatile u16 *)IOP331_REG_ADDR(0x000001BA)
+#define IOP331_VPDDR      (volatile u32 *)IOP331_REG_ADDR(0x000001BC)
+#define IOP331_PMCAPID    (volatile u8 *)IOP331_REG_ADDR(0x000001C0)
+#define IOP331_PMNEXT     (volatile u8 *)IOP331_REG_ADDR(0x000001C1)
+#define IOP331_APMCR      (volatile u16 *)IOP331_REG_ADDR(0x000001C2)
+#define IOP331_APMCSR     (volatile u16 *)IOP331_REG_ADDR(0x000001C4)
+/* Reserved 0x000001C6 through 0x000001CF */
+#define IOP331_MSICAPID   (volatile u8 *)IOP331_REG_ADDR(0x000001D0)
+#define IOP331_MSINXTP	  (volatile u8 *)IOP331_REG_ADDR(0x000001D1)
+#define IOP331_MSIMCR     (volatile u16 *)IOP331_REG_ADDR(0x000001D2)
+#define IOP331_MSIMAR     (volatile u32 *)IOP331_REG_ADDR(0x000001D4)
+#define IOP331_MSIMUAR	  (volatile u32 *)IOP331_REG_ADDR(0x000001D8)
+#define IOP331_MSIMDR	  (volatile u32 *)IOP331_REG_ADDR(0x000001DC)
+#define IOP331_PCIXCAPID  (volatile u8 *)IOP331_REG_ADDR(0x000001E0)
+#define IOP331_PCIXNEXT   (volatile u8 *)IOP331_REG_ADDR(0x000001E1)
+#define IOP331_PCIXCMD    (volatile u16 *)IOP331_REG_ADDR(0x000001E2)
+#define IOP331_PCIXSR     (volatile u32 *)IOP331_REG_ADDR(0x000001E4)
+#define IOP331_PCIIRSR    (volatile u32 *)IOP331_REG_ADDR(0x000001EC)
+
+/* Messaging Unit 0x00000300 through 0x000003FF */
+
+/* Reserved 0x00000300 through 0x0000030c */
+#define IOP331_IMR0       (volatile u32 *)IOP331_REG_ADDR(0x00000310)
+#define IOP331_IMR1       (volatile u32 *)IOP331_REG_ADDR(0x00000314)
+#define IOP331_OMR0       (volatile u32 *)IOP331_REG_ADDR(0x00000318)
+#define IOP331_OMR1       (volatile u32 *)IOP331_REG_ADDR(0x0000031C)
+#define IOP331_IDR        (volatile u32 *)IOP331_REG_ADDR(0x00000320)
+#define IOP331_IISR       (volatile u32 *)IOP331_REG_ADDR(0x00000324)
+#define IOP331_IIMR       (volatile u32 *)IOP331_REG_ADDR(0x00000328)
+#define IOP331_ODR        (volatile u32 *)IOP331_REG_ADDR(0x0000032C)
+#define IOP331_OISR       (volatile u32 *)IOP331_REG_ADDR(0x00000330)
+#define IOP331_OIMR       (volatile u32 *)IOP331_REG_ADDR(0x00000334)
+/* Reserved 0x00000338 through 0x0000034F */
+#define IOP331_MUCR       (volatile u32 *)IOP331_REG_ADDR(0x00000350)
+#define IOP331_QBAR       (volatile u32 *)IOP331_REG_ADDR(0x00000354)
+/* Reserved 0x00000358 through 0x0000035C */
+#define IOP331_IFHPR      (volatile u32 *)IOP331_REG_ADDR(0x00000360)
+#define IOP331_IFTPR      (volatile u32 *)IOP331_REG_ADDR(0x00000364)
+#define IOP331_IPHPR      (volatile u32 *)IOP331_REG_ADDR(0x00000368)
+#define IOP331_IPTPR      (volatile u32 *)IOP331_REG_ADDR(0x0000036C)
+#define IOP331_OFHPR      (volatile u32 *)IOP331_REG_ADDR(0x00000370)
+#define IOP331_OFTPR      (volatile u32 *)IOP331_REG_ADDR(0x00000374)
+#define IOP331_OPHPR      (volatile u32 *)IOP331_REG_ADDR(0x00000378)
+#define IOP331_OPTPR      (volatile u32 *)IOP331_REG_ADDR(0x0000037C)
+#define IOP331_IAR        (volatile u32 *)IOP331_REG_ADDR(0x00000380)
+/* Reserved 0x00000384 through 0x000003FF */
+
+/* DMA Controller 0x00000400 through 0x000004FF */
+#define IOP331_DMA0_CCR   (volatile u32 *)IOP331_REG_ADDR(0x00000400)
+#define IOP331_DMA0_CSR   (volatile u32 *)IOP331_REG_ADDR(0x00000404)
+#define IOP331_DMA0_DAR   (volatile u32 *)IOP331_REG_ADDR(0x0000040C)
+#define IOP331_DMA0_NDAR  (volatile u32 *)IOP331_REG_ADDR(0x00000410)
+#define IOP331_DMA0_PADR  (volatile u32 *)IOP331_REG_ADDR(0x00000414)
+#define IOP331_DMA0_PUADR (volatile u32 *)IOP331_REG_ADDR(0x00000418)
+#define IOP331_DMA0_LADR  (volatile u32 *)IOP331_REG_ADDR(0X0000041C)
+#define IOP331_DMA0_BCR   (volatile u32 *)IOP331_REG_ADDR(0x00000420)
+#define IOP331_DMA0_DCR   (volatile u32 *)IOP331_REG_ADDR(0x00000424)
+/* Reserved 0x00000428 through 0x0000043C */
+#define IOP331_DMA1_CCR   (volatile u32 *)IOP331_REG_ADDR(0x00000440)
+#define IOP331_DMA1_CSR   (volatile u32 *)IOP331_REG_ADDR(0x00000444)
+#define IOP331_DMA1_DAR   (volatile u32 *)IOP331_REG_ADDR(0x0000044C)
+#define IOP331_DMA1_NDAR  (volatile u32 *)IOP331_REG_ADDR(0x00000450)
+#define IOP331_DMA1_PADR  (volatile u32 *)IOP331_REG_ADDR(0x00000454)
+#define IOP331_DMA1_PUADR (volatile u32 *)IOP331_REG_ADDR(0x00000458)
+#define IOP331_DMA1_LADR  (volatile u32 *)IOP331_REG_ADDR(0x0000045C)
+#define IOP331_DMA1_BCR   (volatile u32 *)IOP331_REG_ADDR(0x00000460)
+#define IOP331_DMA1_DCR   (volatile u32 *)IOP331_REG_ADDR(0x00000464)
+/* Reserved 0x00000468 through 0x000004FF */
+
+/* Memory controller 0x00000500 through 0x0005FF */
+
+/* Peripheral bus interface unit 0x00000680 through 0x0006FF */
+#define IOP331_PBCR       (volatile u32 *)IOP331_REG_ADDR(0x00000680)
+#define IOP331_PBISR      (volatile u32 *)IOP331_REG_ADDR(0x00000684)
+#define IOP331_PBBAR0     (volatile u32 *)IOP331_REG_ADDR(0x00000688)
+#define IOP331_PBLR0      (volatile u32 *)IOP331_REG_ADDR(0x0000068C)
+#define IOP331_PBBAR1     (volatile u32 *)IOP331_REG_ADDR(0x00000690)
+#define IOP331_PBLR1      (volatile u32 *)IOP331_REG_ADDR(0x00000694)
+#define IOP331_PBBAR2     (volatile u32 *)IOP331_REG_ADDR(0x00000698)
+#define IOP331_PBLR2      (volatile u32 *)IOP331_REG_ADDR(0x0000069C)
+#define IOP331_PBBAR3     (volatile u32 *)IOP331_REG_ADDR(0x000006A0)
+#define IOP331_PBLR3      (volatile u32 *)IOP331_REG_ADDR(0x000006A4)
+#define IOP331_PBBAR4     (volatile u32 *)IOP331_REG_ADDR(0x000006A8)
+#define IOP331_PBLR4      (volatile u32 *)IOP331_REG_ADDR(0x000006AC)
+#define IOP331_PBBAR5     (volatile u32 *)IOP331_REG_ADDR(0x000006B0)
+#define IOP331_PBLR5      (volatile u32 *)IOP331_REG_ADDR(0x000006B4)
+#define IOP331_PBDSCR     (volatile u32 *)IOP331_REG_ADDR(0x000006B8)
+/* Reserved 0x000006BC */
+#define IOP331_PMBR0      (volatile u32 *)IOP331_REG_ADDR(0x000006C0)
+/* Reserved 0x000006C4 through 0x000006DC */
+#define IOP331_PMBR1      (volatile u32 *)IOP331_REG_ADDR(0x000006E0)
+#define IOP331_PMBR2      (volatile u32 *)IOP331_REG_ADDR(0x000006E4)
+
+#define IOP331_PBCR_EN    0x1
+
+#define IOP331_PBISR_BOOR_ERR 0x1
+
+
+
+/* Peripheral performance monitoring unit 0x00000700 through 0x00077F */
+/* Internal arbitration unit 0x00000780 through 0x0007BF */
+
+/* Interrupt Controller */
+#define IOP331_INTCTL0    (volatile u32 *)IOP331_REG_ADDR(0x00000790)
+#define IOP331_INTCTL1    (volatile u32 *)IOP331_REG_ADDR(0x00000794)
+#define IOP331_INTSTR0    (volatile u32 *)IOP331_REG_ADDR(0x00000798)
+#define IOP331_INTSTR1    (volatile u32 *)IOP331_REG_ADDR(0x0000079C)
+#define IOP331_IINTSRC0   (volatile u32 *)IOP331_REG_ADDR(0x000007A0)
+#define IOP331_IINTSRC1   (volatile u32 *)IOP331_REG_ADDR(0x000007A4)
+#define IOP331_FINTSRC0   (volatile u32 *)IOP331_REG_ADDR(0x000007A8)
+#define IOP331_FINTSRC1   (volatile u32 *)IOP331_REG_ADDR(0x000007AC)
+#define IOP331_IPR0       (volatile u32 *)IOP331_REG_ADDR(0x000007B0)
+#define IOP331_IPR1       (volatile u32 *)IOP331_REG_ADDR(0x000007B4)
+#define IOP331_IPR2       (volatile u32 *)IOP331_REG_ADDR(0x000007B8)
+#define IOP331_IPR3       (volatile u32 *)IOP331_REG_ADDR(0x000007BC)
+#define IOP331_INTBASE    (volatile u32 *)IOP331_REG_ADDR(0x000007C0)
+#define IOP331_INTSIZE    (volatile u32 *)IOP331_REG_ADDR(0x000007C4)
+#define IOP331_IINTVEC    (volatile u32 *)IOP331_REG_ADDR(0x000007C8)
+#define IOP331_FINTVEC    (volatile u32 *)IOP331_REG_ADDR(0x000007CC)
+
+
+/* Timers */
+
+#define IOP331_TU_TMR0		(volatile u32 *)IOP331_REG_ADDR(0x000007D0)
+#define IOP331_TU_TMR1		(volatile u32 *)IOP331_REG_ADDR(0x000007D4)
+
+#define IOP331_TMR_TC		0x01
+#define	IOP331_TMR_EN		0x02
+#define IOP331_TMR_RELOAD	0x04
+#define	IOP331_TMR_PRIVILEGED	0x09
+
+#define	IOP331_TMR_RATIO_1_1	0x00
+#define	IOP331_TMR_RATIO_4_1	0x10
+#define	IOP331_TMR_RATIO_8_1	0x20
+#define	IOP331_TMR_RATIO_16_1	0x30
+
+#define IOP331_TU_TCR0    (volatile u32 *)IOP331_REG_ADDR(0x000007D8)
+#define IOP331_TU_TCR1    (volatile u32 *)IOP331_REG_ADDR(0x000007DC)
+#define IOP331_TU_TRR0    (volatile u32 *)IOP331_REG_ADDR(0x000007E0)
+#define IOP331_TU_TRR1    (volatile u32 *)IOP331_REG_ADDR(0x000007E4)
+#define IOP331_TU_TISR    (volatile u32 *)IOP331_REG_ADDR(0x000007E8)
+#define IOP331_TU_WDTCR   (volatile u32 *)IOP331_REG_ADDR(0x000007EC)
+
+#define	IOP331_TICK_RATE	266000000	/* 266 MHz clock */
+
+
+/* Application accelerator unit 0x00000800 - 0x000008FF */
+#define IOP331_AAU_ACR     (volatile u32 *)IOP331_REG_ADDR(0x00000800)
+#define IOP331_AAU_ASR     (volatile u32 *)IOP331_REG_ADDR(0x00000804)
+#define IOP331_AAU_ADAR    (volatile u32 *)IOP331_REG_ADDR(0x00000808)
+#define IOP331_AAU_ANDAR   (volatile u32 *)IOP331_REG_ADDR(0x0000080C)
+#define IOP331_AAU_SAR1    (volatile u32 *)IOP331_REG_ADDR(0x00000810)
+#define IOP331_AAU_SAR2    (volatile u32 *)IOP331_REG_ADDR(0x00000814)
+#define IOP331_AAU_SAR3    (volatile u32 *)IOP331_REG_ADDR(0x00000818)
+#define IOP331_AAU_SAR4    (volatile u32 *)IOP331_REG_ADDR(0x0000081C)
+#define IOP331_AAU_SAR5    (volatile u32 *)IOP331_REG_ADDR(0x0000082C)
+#define IOP331_AAU_SAR6    (volatile u32 *)IOP331_REG_ADDR(0x00000830)
+#define IOP331_AAU_SAR7    (volatile u32 *)IOP331_REG_ADDR(0x00000834)
+#define IOP331_AAU_SAR8    (volatile u32 *)IOP331_REG_ADDR(0x00000838)
+#define IOP331_AAU_SAR9    (volatile u32 *)IOP331_REG_ADDR(0x00000840)
+#define IOP331_AAU_SAR10   (volatile u32 *)IOP331_REG_ADDR(0x00000844)
+#define IOP331_AAU_SAR11   (volatile u32 *)IOP331_REG_ADDR(0x00000848)
+#define IOP331_AAU_SAR12   (volatile u32 *)IOP331_REG_ADDR(0x0000084C)
+#define IOP331_AAU_SAR13   (volatile u32 *)IOP331_REG_ADDR(0x00000850)
+#define IOP331_AAU_SAR14   (volatile u32 *)IOP331_REG_ADDR(0x00000854)
+#define IOP331_AAU_SAR15   (volatile u32 *)IOP331_REG_ADDR(0x00000858)
+#define IOP331_AAU_SAR16   (volatile u32 *)IOP331_REG_ADDR(0x0000085C)
+#define IOP331_AAU_SAR17   (volatile u32 *)IOP331_REG_ADDR(0x00000864)
+#define IOP331_AAU_SAR18   (volatile u32 *)IOP331_REG_ADDR(0x00000868)
+#define IOP331_AAU_SAR19   (volatile u32 *)IOP331_REG_ADDR(0x0000086C)
+#define IOP331_AAU_SAR20   (volatile u32 *)IOP331_REG_ADDR(0x00000870)
+#define IOP331_AAU_SAR21   (volatile u32 *)IOP331_REG_ADDR(0x00000874)
+#define IOP331_AAU_SAR22   (volatile u32 *)IOP331_REG_ADDR(0x00000878)
+#define IOP331_AAU_SAR23   (volatile u32 *)IOP331_REG_ADDR(0x0000087C)
+#define IOP331_AAU_SAR24   (volatile u32 *)IOP331_REG_ADDR(0x00000880)
+#define IOP331_AAU_SAR25   (volatile u32 *)IOP331_REG_ADDR(0x00000888)
+#define IOP331_AAU_SAR26   (volatile u32 *)IOP331_REG_ADDR(0x0000088C)
+#define IOP331_AAU_SAR27   (volatile u32 *)IOP331_REG_ADDR(0x00000890)
+#define IOP331_AAU_SAR28   (volatile u32 *)IOP331_REG_ADDR(0x00000894)
+#define IOP331_AAU_SAR29   (volatile u32 *)IOP331_REG_ADDR(0x00000898)
+#define IOP331_AAU_SAR30   (volatile u32 *)IOP331_REG_ADDR(0x0000089C)
+#define IOP331_AAU_SAR31   (volatile u32 *)IOP331_REG_ADDR(0x000008A0)
+#define IOP331_AAU_SAR32   (volatile u32 *)IOP331_REG_ADDR(0x000008A4)
+#define IOP331_AAU_DAR     (volatile u32 *)IOP331_REG_ADDR(0x00000820)
+#define IOP331_AAU_ABCR    (volatile u32 *)IOP331_REG_ADDR(0x00000824)
+#define IOP331_AAU_ADCR    (volatile u32 *)IOP331_REG_ADDR(0x00000828)
+#define IOP331_AAU_EDCR0   (volatile u32 *)IOP331_REG_ADDR(0x0000083c)
+#define IOP331_AAU_EDCR1   (volatile u32 *)IOP331_REG_ADDR(0x00000860)
+#define IOP331_AAU_EDCR2   (volatile u32 *)IOP331_REG_ADDR(0x00000884)
+
+
+#define IOP331_SPDSCR	  (volatile u32 *)IOP331_REG_ADDR(0x000015C0)
+#define IOP331_PPDSCR	  (volatile u32 *)IOP331_REG_ADDR(0x000015C8)
+/* SSP serial port unit 0x00001600 - 0x0000167F */
+
+/* I2C bus interface unit 0x00001680 - 0x000016FF */
+/* for I2C bit defs see drivers/i2c/i2c-iop3xx.h */
+
+#define IOP331_ICR0       (volatile u32 *)IOP331_REG_ADDR(0x00001680)
+#define IOP331_ISR0       (volatile u32 *)IOP331_REG_ADDR(0x00001684)
+#define IOP331_ISAR0      (volatile u32 *)IOP331_REG_ADDR(0x00001688)
+#define IOP331_IDBR0      (volatile u32 *)IOP331_REG_ADDR(0x0000168C)
+/* Reserved 0x00001690 */
+#define IOP331_IBMR0      (volatile u32 *)IOP331_REG_ADDR(0x00001694)
+/* Reserved 0x00001698 */
+/* Reserved 0x0000169C */
+#define IOP331_ICR1       (volatile u32 *)IOP331_REG_ADDR(0x000016A0)
+#define IOP331_ISR1       (volatile u32 *)IOP331_REG_ADDR(0x000016A4)
+#define IOP331_ISAR1      (volatile u32 *)IOP331_REG_ADDR(0x000016A8)
+#define IOP331_IDBR1      (volatile u32 *)IOP331_REG_ADDR(0x000016AC)
+#define IOP331_IBMR1      (volatile u32 *)IOP331_REG_ADDR(0x000016B4)
+/* Reserved 0x000016B8 through 0x000016FF */
+
+/* 0x00001700 through 0x0000172C  UART 0 */
+
+/* Reserved 0x00001730 through 0x0000173F */
+
+/* 0x00001740 through 0x0000176C UART 1 */
+
+/* Reserved 0x00001770 through 0x0000177F */
+
+/* General Purpose I/O Registers */
+#define IOP331_GPOE       (volatile u32 *)IOP331_REG_ADDR(0x00001780)
+#define IOP331_GPID       (volatile u32 *)IOP331_REG_ADDR(0x00001784)
+#define IOP331_GPOD       (volatile u32 *)IOP331_REG_ADDR(0x00001788)
+
+/* Reserved 0x0000178c through 0x000019ff */
+
+#ifndef __ASSEMBLY__
+extern void iop331_map_io(void);
+extern void iop331_init_irq(void);
+extern void iop331_time_init(void);
+#endif
+
+#endif // _IOP331_HW_H_
diff -Nru a/include/asm-arm/arch-iop3xx/iq31244.h b/include/asm-arm/arch-iop3xx/iq31244.h
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/include/asm-arm/arch-iop3xx/iq31244.h	2004-10-18 14:57:24 -07:00
@@ -0,0 +1,36 @@
+/*
+ * linux/include/asm/arch-iop3xx/iq31244.h
+ *
+ * Intel IQ31244 evaluation board registers
+ */
+
+#ifndef _IQ31244_H_
+#define _IQ31244_H_
+
+#define IQ31244_RAMBASE		0xa0000000
+
+#define	IQ31244_FLASHBASE	0xf0000000	/* Flash */
+#define	IQ31244_FLASHSIZE	0x00800000
+#define	IQ31244_FLASHWIDTH	2
+
+#define IQ31244_UART		0xfe800000	/* UART #1 */
+#define IQ31244_7SEG_1		0xfe840000	/* 7-Segment MSB */
+#define IQ31244_7SEG_0		0xfe850000	/* 7-Segment LSB (WO) */
+#define IQ31244_ROTARY_SW	0xfe8d0000	/* Rotary Switch */
+#define IQ31244_BATT_STAT	0xfe8f0000	/* Battery Status */
+
+/*
+ * IQ31244 PCI I/O and Mem space regions
+ */
+#define IQ31244_PCI_IO_BASE	0x90000000
+#define IQ31244_PCI_IO_SIZE	0x00010000
+#define IQ31244_PCI_MEM_BASE	0x80000000
+//#define IQ31244_PCI_MEM_SIZE	0x04000000
+#define IQ31244_PCI_MEM_SIZE	0x08000000
+#define	IQ31244_PCI_IO_OFFSET	0x6e000000
+
+#ifndef __ASSEMBLY__
+extern void iq31244_map_io(void);
+#endif
+
+#endif	// _IQ31244_H_
diff -Nru a/include/asm-arm/arch-iop3xx/iq80310.h b/include/asm-arm/arch-iop3xx/iq80310.h
--- a/include/asm-arm/arch-iop3xx/iq80310.h	2004-10-18 14:56:17 -07:00
+++ /dev/null	Wed Dec 31 16:00:00 196900
@@ -1,30 +0,0 @@
-/*
- * linux/include/asm/arch-iop80310/iq80310.h
- *
- * Intel IQ-80310 evaluation board registers
- */
-
-#ifndef _IQ80310_H_
-#define _IQ80310_H_
-
-#define IQ80310_RAMBASE      0xa0000000
-#define IQ80310_UART1        0xfe800000    /* UART #1 */
-#define IQ80310_UART2        0xfe810000    /* UART #2 */
-#define IQ80310_INT_STAT     0xfe820000    /* Interrupt (XINT3#) Status */
-#define IQ80310_BOARD_REV    0xfe830000    /* Board revision register */
-#define IQ80310_CPLD_REV     0xfe840000    /* CPLD revision register */
-#define IQ80310_7SEG_1       0xfe840000    /* 7-Segment MSB */
-#define IQ80310_7SEG_0       0xfe850000    /* 7-Segment LSB (WO) */
-#define IQ80310_PCI_INT_STAT 0xfe850000    /* PCI Interrupt  Status */
-#define IQ80310_INT_MASK     0xfe860000    /* Interrupt (XINT3#) Mask */
-#define IQ80310_BACKPLANE    0xfe870000    /* Backplane Detect */
-#define IQ80310_TIMER_LA0    0xfe880000    /* Timer LA0 */
-#define IQ80310_TIMER_LA1    0xfe890000    /* Timer LA1 */
-#define IQ80310_TIMER_LA2    0xfe8a0000    /* Timer LA2 */
-#define IQ80310_TIMER_LA3    0xfe8b0000    /* Timer LA3 */
-#define IQ80310_TIMER_EN     0xfe8c0000    /* Timer Enable */
-#define IQ80310_ROTARY_SW    0xfe8d0000    /* Rotary Switch */
-#define IQ80310_JTAG         0xfe8e0000    /* JTAG Port Access */
-#define IQ80310_BATT_STAT    0xfe8f0000    /* Battery Status */
-
-#endif	// _IQ80310_H_
diff -Nru a/include/asm-arm/arch-iop3xx/iq80321.h b/include/asm-arm/arch-iop3xx/iq80321.h
--- a/include/asm-arm/arch-iop3xx/iq80321.h	2004-10-18 14:56:29 -07:00
+++ b/include/asm-arm/arch-iop3xx/iq80321.h	2004-10-18 14:56:29 -07:00
@@ -1,17 +1,35 @@
 /*
  * linux/include/asm/arch-iop3xx/iq80321.h
  *
- * Intel IQ-80321 evaluation board registers
+ * Intel IQ80321 evaluation board registers
  */
 
 #ifndef _IQ80321_H_
 #define _IQ80321_H_
 
-#define IQ80321_RAMBASE      0xa0000000
-#define IQ80321_UART1        0xfe800000    /* UART #1 */
-#define IQ80321_7SEG_1       0xfe840000    /* 7-Segment MSB */
-#define IQ80321_7SEG_0       0xfe850000    /* 7-Segment LSB (WO) */
-#define IQ80321_ROTARY_SW    0xfe8d0000    /* Rotary Switch */
-#define IQ80321_BATT_STAT    0xfe8f0000    /* Battery Status */
+#define IQ80321_RAMBASE		0xa0000000
+
+#define	IQ80321_FLASHBASE	0xf0000000	/* Flash */
+#define	IQ80321_FLASHSIZE	0x00800000
+#define	IQ80321_FLASHWIDTH	1
+
+#define IQ80321_UART		0xfe800000	/* UART #1 */
+#define IQ80321_7SEG_1		0xfe840000	/* 7-Segment MSB */
+#define IQ80321_7SEG_0		0xfe850000	/* 7-Segment LSB (WO) */
+#define IQ80321_ROTARY_SW	0xfe8d0000	/* Rotary Switch */
+#define IQ80321_BATT_STAT	0xfe8f0000	/* Battery Status */
+
+/*
+ * IQ80321 PCI I/O and Mem space regions
+ */
+#define IQ80321_PCI_IO_BASE	0x90000000
+#define IQ80321_PCI_IO_SIZE	0x00010000
+#define IQ80321_PCI_MEM_BASE	0x80000000
+#define IQ80321_PCI_MEM_SIZE	0x04000000
+#define	IQ80321_PCI_IO_OFFSET	0x6e000000
+
+#ifndef __ASSEMBLY__
+extern void iq80321_map_io(void);
+#endif
 
 #endif	// _IQ80321_H_
diff -Nru a/include/asm-arm/arch-iop3xx/iq80331.h b/include/asm-arm/arch-iop3xx/iq80331.h
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/include/asm-arm/arch-iop3xx/iq80331.h	2004-10-18 14:57:23 -07:00
@@ -0,0 +1,38 @@
+/*
+ * linux/include/asm/arch-iop3xx/iq80331.h
+ *
+ * Intel IQ80331 evaluation board registers
+ */
+
+#ifndef _IQ80331_H_
+#define _IQ80331_H_
+
+#define IQ80331_RAMBASE		0x00000000
+
+#define	IQ80331_FLASHBASE	0xc0000000	/* Flash */
+#define	IQ80331_FLASHSIZE	0x00800000
+#define	IQ80331_FLASHWIDTH	1
+
+#define IQ80331_UART0_PHYS  (IOP331_PHYS_MEM_BASE | 0x00001700)	/* UART #1 physical */
+#define IQ80331_UART1_PHYS  (IOP331_PHYS_MEM_BASE | 0x00001740)	/* UART #2 physical */
+#define IQ80331_UART0_VIRT  (IOP331_VIRT_MEM_BASE | 0x00001700) /* UART #1 virtual addr */
+#define IQ80331_UART1_VIRT  (IOP331_VIRT_MEM_BASE | 0x00001740) /* UART #2 virtual addr */
+#define IQ80331_7SEG_1		0xce840000	/* 7-Segment MSB */
+#define IQ80331_7SEG_0		0xce850000	/* 7-Segment LSB (WO) */
+#define IQ80331_ROTARY_SW	0xce8d0000	/* Rotary Switch */
+#define IQ80331_BATT_STAT	0xce8f0000	/* Battery Status */
+
+/*
+ * IQ80331 PCI I/O and Mem space regions
+ */
+#define IQ80331_PCI_IO_BASE	0x90000000
+#define IQ80331_PCI_IO_SIZE	0x00010000
+#define IQ80331_PCI_MEM_BASE	0x80000000
+#define IQ80331_PCI_MEM_SIZE	0x08000000
+#define	IQ80331_PCI_IO_OFFSET	0x6e000000
+
+#ifndef __ASSEMBLY__
+extern void iq80331_map_io(void);
+#endif
+
+#endif	// _IQ80331_H_
diff -Nru a/include/asm-arm/arch-iop3xx/irqs.h b/include/asm-arm/arch-iop3xx/irqs.h
--- a/include/asm-arm/arch-iop3xx/irqs.h	2004-10-18 14:56:28 -07:00
+++ b/include/asm-arm/arch-iop3xx/irqs.h	2004-10-18 14:56:28 -07:00
@@ -1,27 +1,21 @@
 /*
  * linux/include/asm-arm/arch-iop3xx/irqs.h
  *
- * Copyright:	(C) 2001 MontaVista Software Inc.
+ * Copyright:	(C) 2001-2003 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 version 2 as
  * published by the Free Software Foundation.
  *
- *
  */
 
-#include <linux/config.h>
-
 /*
- * Whic iop3xx implementation is this?
+ * Chipset-specific bits
  */
-#ifdef CONFIG_ARCH_IOP310
-
-#include "iop310-irqs.h"
-
-#else
-
+#ifdef CONFIG_ARCH_IOP321
 #include "iop321-irqs.h"
-
 #endif
 
+#ifdef CONFIG_ARCH_IOP331
+#include "iop331-irqs.h"
+#endif
diff -Nru a/include/asm-arm/arch-iop3xx/memory.h b/include/asm-arm/arch-iop3xx/memory.h
--- a/include/asm-arm/arch-iop3xx/memory.h	2004-10-18 14:56:50 -07:00
+++ b/include/asm-arm/arch-iop3xx/memory.h	2004-10-18 14:56:50 -07:00
@@ -1,41 +1,39 @@
 /*
- * linux/include/asm-arm/arch-iop80310/memory.h
+ * linux/include/asm-arm/arch-iop3xx/memory.h
  */
 
 #ifndef __ASM_ARCH_MEMORY_H
 #define __ASM_ARCH_MEMORY_H
 
 #include <linux/config.h>
-#include <asm/arch/iop310.h>
-#include <asm/arch/iop321.h>
+#include <asm/hardware.h>
 
 /*
  * Physical DRAM offset.
  */
+#ifndef CONFIG_ARCH_IOP331
 #define PHYS_OFFSET	(0xa0000000UL)
+#else
+#define PHYS_OFFSET	(0x00000000UL)
+#endif
 
 /*
- * Virtual view <-> DMA view memory address translations
+ * Virtual view <-> PCI DMA view memory address translations
  * virt_to_bus: Used to translate the virtual address to an
  *		address suitable to be passed to set_dma_addr
  * bus_to_virt: Used to convert an address for DMA operations
  *		to an address that the kernel can use.
  */
-#ifdef CONFIG_ARCH_IOP310
-
-#define __virt_to_bus(x)	(((__virt_to_phys(x)) & ~(*IOP310_SIATVR)) | ((*IOP310_SIABAR) & 0xfffffff0))
-#define __bus_to_virt(x)    (__phys_to_virt(((x) & ~(*IOP310_SIALR)) | ( *IOP310_SIATVR)))
-
-#elif defined(CONFIG_ARCH_IOP321)
+#if defined(CONFIG_ARCH_IOP321)
 
 #define __virt_to_bus(x)	(((__virt_to_phys(x)) & ~(*IOP321_IATVR2)) | ((*IOP321_IABAR2) & 0xfffffff0))
 #define __bus_to_virt(x)    (__phys_to_virt(((x) & ~(*IOP321_IALR2)) | ( *IOP321_IATVR2)))
 
-#endif
+#elif defined(CONFIG_ARCH_IOP331)
+
+#define __virt_to_bus(x)	(((__virt_to_phys(x)) & ~(*IOP331_IATVR2)) | ((*IOP331_IABAR2) & 0xfffffff0))
+#define __bus_to_virt(x)    (__phys_to_virt(((x) & ~(*IOP331_IALR2)) | ( *IOP331_IATVR2)))
 
-/* boot mem allocate global pointer for MU circular queues QBAR */
-#ifdef CONFIG_IOP3XX_MU
-extern void *mu_mem;
 #endif
 
 #define PFN_TO_NID(addr)	(0)
diff -Nru a/include/asm-arm/arch-iop3xx/param.h b/include/asm-arm/arch-iop3xx/param.h
--- a/include/asm-arm/arch-iop3xx/param.h	2004-10-18 14:56:32 -07:00
+++ b/include/asm-arm/arch-iop3xx/param.h	2004-10-18 14:56:32 -07:00
@@ -1,3 +1,3 @@
 /*
- *  linux/include/asm-arm/arch-iop80310/param.h
+ *  linux/include/asm-arm/arch-iop3xx/param.h
  */
diff -Nru a/include/asm-arm/arch-iop3xx/pmon.h b/include/asm-arm/arch-iop3xx/pmon.h
--- a/include/asm-arm/arch-iop3xx/pmon.h	2004-10-18 14:56:33 -07:00
+++ /dev/null	Wed Dec 31 16:00:00 196900
@@ -1,50 +0,0 @@
-/*
- * Definitions for XScale 80312 PMON
- * (C) 2001 Intel Corporation
- * Author: Chen Chen(chen.chen@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.
- */
-
-#ifndef _IOP310_PMON_H_
-#define _IOP310_PMON_H_
-
-/*
- *  Different modes for Event Select Register for intel 80312
- */
-
-#define IOP310_PMON_MODE0                0x00000000
-#define IOP310_PMON_MODE1                0x00000001
-#define IOP310_PMON_MODE2                0x00000002
-#define IOP310_PMON_MODE3                0x00000003
-#define IOP310_PMON_MODE4                0x00000004
-#define IOP310_PMON_MODE5                0x00000005
-#define IOP310_PMON_MODE6                0x00000006
-#define IOP310_PMON_MODE7                0x00000007
-
-typedef struct _iop310_pmon_result
-{
-	u32 timestamp;			/* Global Time Stamp Register */
-	u32 timestamp_overflow;		/* Time Stamp overflow count */
-	u32 event_count[14];		/* Programmable Event Counter
-					   Registers 1-14 */
-	u32 event_overflow[14];		/* Overflow counter for PECR1-14 */
-} iop310_pmon_res_t;
-
-/* function prototypes */
-
-/* Claim IQ80312 PMON for usage */
-int iop310_pmon_claim(void);
-
-/* Start IQ80312 PMON */
-int iop310_pmon_start(int, int);
-
-/* Stop Performance Monitor Unit */
-int iop310_pmon_stop(iop310_pmon_res_t *);
-
-/* Release IQ80312 PMON */
-int iop310_pmon_release(int);
-
-#endif
diff -Nru a/include/asm-arm/arch-iop3xx/serial.h b/include/asm-arm/arch-iop3xx/serial.h
--- a/include/asm-arm/arch-iop3xx/serial.h	2004-10-18 14:57:03 -07:00
+++ b/include/asm-arm/arch-iop3xx/serial.h	2004-10-18 14:57:03 -07:00
@@ -15,26 +15,61 @@
 /* Standard COM flags */
 #define STD_COM_FLAGS (ASYNC_BOOT_AUTOCONF | ASYNC_SKIP_TEST)
 
-#ifdef CONFIG_ARCH_IQ80310
+#ifdef CONFIG_ARCH_IQ80321
+
+#define IRQ_UART1	IRQ_IQ80321_UART
 
-#define IRQ_UART1	IRQ_IQ80310_UART1
-#define IRQ_UART2	IRQ_IQ80310_UART2
+#define RS_TABLE_SIZE 1
 
 #define STD_SERIAL_PORT_DEFNS			\
        /* UART CLK      PORT        IRQ        FLAGS        */			\
-	{ 0, BASE_BAUD, IQ80310_UART2, IRQ_UART2, STD_COM_FLAGS },  /* ttyS0 */	\
-	{ 0, BASE_BAUD, IQ80310_UART1, IRQ_UART1, STD_COM_FLAGS }  /* ttyS1 */
+	{ 0, BASE_BAUD, 0xfe800000, IRQ_UART1, STD_COM_FLAGS },  /* ttyS0 */
+#endif // CONFIG_ARCH_IQ80321
 
-#endif // CONFIG_ARCH_IQ80310
+#ifdef CONFIG_ARCH_IQ31244
 
-#ifdef CONFIG_ARCH_IQ80321
+#define IRQ_UART1	IRQ_IQ31244_UART
 
-#define IRQ_UART1	IRQ_IQ80321_UART
+#define RS_TABLE_SIZE 1
 
 #define STD_SERIAL_PORT_DEFNS			\
        /* UART CLK      PORT        IRQ        FLAGS        */			\
 	{ 0, BASE_BAUD, 0xfe800000, IRQ_UART1, STD_COM_FLAGS },  /* ttyS0 */
-#endif // CONFIG_ARCH_IQ80321
+#endif // CONFIG_ARCH_IQ31244
+
+#ifdef CONFIG_ARCH_IQ80331
+
+#undef BASE_BAUD
+
+#define BASE_BAUD ( 33334000 / 16 )
+
+#define IRQ_UART0	IRQ_IQ80331_UART0
+#define IRQ_UART1	IRQ_IQ80331_UART1
+
+#define RS_TABLE_SIZE 2
+
+#define STD_SERIAL_PORT_DEFNS				\
+	{						\
+	  /*type: PORT_XSCALE,*/			\
+	  /*xmit_fifo_size: 32,*/			\
+	  baud_base: BASE_BAUD,				\
+	  irq: IRQ_UART0,			  	\
+	  flags: STD_COM_FLAGS,				\
+	  iomem_base: IQ80331_UART0_VIRT,		\
+	  io_type: SERIAL_IO_MEM,			\
+	  iomem_reg_shift: 2				\
+	}, /* ttyS0 */					\
+	{						\
+	  /*type: PORT_XSCALE,*/			\
+	  /*xmit_fifo_size: 32,*/			\
+	  baud_base: BASE_BAUD,				\
+	  irq: IRQ_UART1,			  	\
+	  flags: STD_COM_FLAGS,				\
+	  iomem_base: IQ80331_UART1_VIRT,		\
+	  io_type: SERIAL_IO_MEM,			\
+	  iomem_reg_shift: 2				\
+	} /* ttyS1 */
+#endif // CONFIG_ARCH_IQ80331
 
 
 #define EXTRA_SERIAL_PORT_DEFNS
diff -Nru a/include/asm-arm/arch-iop3xx/system.h b/include/asm-arm/arch-iop3xx/system.h
--- a/include/asm-arm/arch-iop3xx/system.h	2004-10-18 14:57:04 -07:00
+++ b/include/asm-arm/arch-iop3xx/system.h	2004-10-18 14:57:04 -07:00
@@ -1,5 +1,5 @@
 /*
- * linux/include/asm-arm/arch-iop80310/system.h
+ * linux/include/asm-arm/arch-iop3xx/system.h
  *
  *  Copyright (C) 2001 MontaVista Software, Inc.
  *
@@ -16,6 +16,14 @@
 
 static inline void arch_reset(char mode)
 {
+#ifdef CONFIG_ARCH_IOP321
+    *IOP321_PCSR = 0x30;
+#endif
+
+#ifdef CONFIG_ARCH_IOP331
+    *IOP331_PCSR = 0x30;
+#endif
+
 	if ( 1 && mode == 's') {
 		/* Jump into ROM at address 0 */
 		cpu_reset(0);
diff -Nru a/include/asm-arm/arch-iop3xx/timex.h b/include/asm-arm/arch-iop3xx/timex.h
--- a/include/asm-arm/arch-iop3xx/timex.h	2004-10-18 14:56:32 -07:00
+++ b/include/asm-arm/arch-iop3xx/timex.h	2004-10-18 14:56:32 -07:00
@@ -1,24 +1,18 @@
 /*
  * linux/include/asm-arm/arch-iop3xx/timex.h
  *
- * IOP310 architecture timex specifications
+ * IOP3xx architecture timex specifications
  */
 #include <linux/config.h>
 
 
-#ifdef CONFIG_ARCH_IQ80310
+#if defined(CONFIG_ARCH_IQ80321) || defined(CONFIG_ARCH_IQ31244)
 
-#ifndef CONFIG_XSCALE_PMU_TIMER
-/* This is for the on-board timer */
-#define CLOCK_TICK_RATE 33000000 /* Underlying HZ */
-#else
-/* This is for the underlying xs80200 PMU clock. We run the core @ 733MHz */
-#define CLOCK_TICK_RATE	733000000
-#endif // IQ80310
+#define CLOCK_TICK_RATE IOP321_TICK_RATE
 
-#elif defined(CONFIG_ARCH_IQ80321)
+#elif defined(CONFIG_ARCH_IQ80331)
 
-#define CLOCK_TICK_RATE 200000000
+#define CLOCK_TICK_RATE IOP331_TICK_RATE
 
 #else
 
diff -Nru a/include/asm-arm/arch-iop3xx/uncompress.h b/include/asm-arm/arch-iop3xx/uncompress.h
--- a/include/asm-arm/arch-iop3xx/uncompress.h	2004-10-18 14:56:32 -07:00
+++ b/include/asm-arm/arch-iop3xx/uncompress.h	2004-10-18 14:56:32 -07:00
@@ -1,26 +1,32 @@
 /*
- *  linux/include/asm-arm/arch-iop80310/uncompress.h
+ *  linux/include/asm-arm/arch-iop3xx/uncompress.h
  */
 #include <linux/config.h>
+#include <asm/types.h>
+#include <asm/mach-types.h>
 #include <linux/serial_reg.h>
 #include <asm/hardware.h>
 
-#ifdef CONFIG_ARCH_IQ80310
-#define UART2_BASE    ((volatile unsigned char *)IQ80310_UART2)
-#elif defined(CONFIG_ARCH_IQ80321)
-#define UART2_BASE    ((volatile unsigned char *)IQ80321_UART1)
+#ifdef CONFIG_ARCH_IOP321
+#define UTYPE unsigned char *
+#else
+#define UTYPE u32 *
 #endif
 
+static volatile UTYPE uart_base;
+
+#define TX_DONE (UART_LSR_TEMT|UART_LSR_THRE)
+
 static __inline__ void putc(char c)
 {
-	while ((UART2_BASE[5] & 0x60) != 0x60);
-	UART2_BASE[0] = c;
+	while ((uart_base[UART_LSR] & TX_DONE) != TX_DONE);
+	*uart_base = c;
 }
 
 /*
  * This does not append a newline
  */
-static void puts(const char *s)
+static void putstr(const char *s)
 {
 	while (*s) {
 		putc(*s);
@@ -30,8 +36,20 @@
 	}
 }
 
+static __inline__ void __arch_decomp_setup(unsigned long arch_id)
+{
+        if(machine_is_iq80321())
+			uart_base = (volatile UTYPE)IQ80321_UART;
+		else if(machine_is_iq31244())
+			uart_base = (volatile UTYPE)IQ31244_UART;
+		else if(machine_is_iq80331())
+			uart_base = (volatile UTYPE)IQ80331_UART0_PHYS;
+		else
+			uart_base = (volatile UTYPE)0xfe800000;
+}
+
 /*
  * nothing to do
  */
-#define arch_decomp_setup()
+#define arch_decomp_setup()	__arch_decomp_setup(arch_id)
 #define arch_decomp_wdog()
diff -Nru a/include/asm-arm/arch-iop3xx/vmalloc.h b/include/asm-arm/arch-iop3xx/vmalloc.h
--- a/include/asm-arm/arch-iop3xx/vmalloc.h	2004-10-18 14:56:33 -07:00
+++ b/include/asm-arm/arch-iop3xx/vmalloc.h	2004-10-18 14:56:33 -07:00
@@ -12,4 +12,5 @@
  */
 #define VMALLOC_OFFSET	  (8*1024*1024)
 #define VMALLOC_START	  (((unsigned long)high_memory + VMALLOC_OFFSET) & ~(VMALLOC_OFFSET-1))
+#define VMALLOC_VMADDR(x) ((unsigned long)(x))
 #define VMALLOC_END       (0xe8000000)
diff -Nru a/include/asm-arm/arch-ixp2000/dma.h b/include/asm-arm/arch-ixp2000/dma.h
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/include/asm-arm/arch-ixp2000/dma.h	2004-10-18 14:57:24 -07:00
@@ -0,0 +1,18 @@
+/*
+ * linux/include/asm-arm/arch-ixdp2400/dma.h
+ *
+ * Copyright (C) 2002 Intel Corp.
+ *
+ * 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.
+ */
+#ifndef __ASM_ARCH_DMA_H
+#define __ASM_ARCH_DMA_H
+
+#define MAX_DMA_ADDRESS		0xffffffff
+
+/* No DMA */
+#define MAX_DMA_CHANNELS	0
+
+#endif /* _ASM_ARCH_DMA_H */
diff -Nru a/include/asm-arm/arch-ixp2000/enp2611.h b/include/asm-arm/arch-ixp2000/enp2611.h
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/include/asm-arm/arch-ixp2000/enp2611.h	2004-10-18 14:57:21 -07:00
@@ -0,0 +1,28 @@
+/*
+ * include/asm-arm/arch-ixp2000/enp2611.h
+ *
+ * Register and other defines for Radisys ENP-2611
+ *
+ * Created 2004 by Lennert Buytenhek from the ixdp2x01 code.  The
+ * original version carries the following notices:
+ *
+ * Original Author: Naeem Afzal <naeem.m.afzal@intel.com>
+ * Maintainer: Deepak Saxena <dsaxena@plexity.net>
+ *
+ * Copyright (C) 2002 Intel Corp.
+ * Copyright (C) 2003-2004 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.
+ */
+
+#ifndef __ENP2611_H
+#define __ENP2611_H
+
+#define ENP2611_GPIO_SCL	0x07
+#define ENP2611_GPIO_SDA	0x06
+
+
+#endif
diff -Nru a/include/asm-arm/arch-ixp2000/gpio.h b/include/asm-arm/arch-ixp2000/gpio.h
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/include/asm-arm/arch-ixp2000/gpio.h	2004-10-18 14:57:23 -07:00
@@ -0,0 +1,55 @@
+/*
+ * include/asm-arm/arch-ixp2000/ixp2000-gpio.h
+ *
+ * Copyright (C) 2002 Intel Corporation.
+ *
+ * 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.
+ */
+
+/*
+ * IXP2000 GPIO in/out, edge/level detection for IRQs:
+ * IRQs are generated on Falling-edge, Rising-Edge, Level-low, Level-High
+ * or both Falling-edge and Rising-edge.  
+ * This must be called *before* the corresponding IRQ is registerd.
+ * Use this instead of directly setting the GPIO registers.
+ * GPIOs may also be used as GPIOs (e.g. for emulating i2c/smb)
+ */
+#ifndef _ASM_ARCH_IXP2000_GPIO_H_
+#define _ASM_ARCH_IXP2000_GPIO_H_
+
+#ifndef __ASSEMBLY__
+#define GPIO_OUT			0x0
+#define GPIO_IN				0x80
+
+#define IXP2000_GPIO_LOW		0
+#define IXP2000_GPIO_HIGH		1
+
+#define GPIO_NO_EDGES           	0
+#define GPIO_FALLING_EDGE       	1
+#define GPIO_RISING_EDGE        	2
+#define GPIO_BOTH_EDGES         	3
+#define GPIO_LEVEL_LOW          	4
+#define GPIO_LEVEL_HIGH         	8
+
+extern void set_GPIO_IRQ_edge(int gpio_nr, int edge);
+extern void set_GPIO_IRQ_level(int gpio_nr, int level);
+extern void gpio_line_config(int line, int style);
+
+static inline int gpio_line_get(int line)
+{
+	return (((*IXP2000_GPIO_PLR) >> line) & 1);
+}
+
+static inline void gpio_line_set(int line, int value)
+{
+	if (value == IXP2000_GPIO_HIGH) {
+		ixp_reg_write(IXP2000_GPIO_POSR, BIT(line));
+	} else if (value == IXP2000_GPIO_LOW)
+		ixp_reg_write(IXP2000_GPIO_POCR, BIT(line));
+}
+
+#endif /* !__ASSEMBLY__ */
+#endif /* ASM_ARCH_IXP2000_GPIO_H_ */
+
diff -Nru a/include/asm-arm/arch-ixp2000/hardware.h b/include/asm-arm/arch-ixp2000/hardware.h
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/include/asm-arm/arch-ixp2000/hardware.h	2004-10-18 14:57:21 -07:00
@@ -0,0 +1,44 @@
+/*
+ * linux/include/asm-arm/arch-ixp2000/hardware.h
+ *
+ * Hardware definitions for IXP2400/2800 based systems
+ *
+ * Original Author: Naeem M Afzal <naeem.m.afzal@intel.com>
+ *
+ * Maintainer: Deepak Saxena <dsaxena@mvista.com>
+ *
+ * Copyright (C) 2001-2002 Intel Corp.
+ * Copyright (C) 2003-2004 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.
+ */
+
+#ifndef __ASM_ARCH_HARDWARE_H__
+#define __ASM_ARCH_HARDWARE_H__
+
+/*
+ * This needs to be platform-specific?
+ */
+#define PCIBIOS_MIN_IO          0x00000000
+#define PCIBIOS_MIN_MEM         0x00000000
+
+#include "ixp2000-regs.h"	/* Chipset Registers */
+
+#define pcibios_assign_all_busses() 0
+
+/*
+ * Platform helper functions
+ */
+#include "platform.h"
+
+/*
+ * Platform-specific bits
+ */
+#include "enp2611.h"		/* ENP-2611 */
+#include "ixdp2x00.h"		/* IXDP2400/2800 */
+#include "ixdp2x01.h"		/* IXDP2401/2801 */
+
+#endif  /* _ASM_ARCH_HARDWARE_H__ */
diff -Nru a/include/asm-arm/arch-ixp2000/io.h b/include/asm-arm/arch-ixp2000/io.h
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/include/asm-arm/arch-ixp2000/io.h	2004-10-18 14:57:21 -07:00
@@ -0,0 +1,150 @@
+/*
+ * linux/include/asm-arm/arch-ixdp2000/io.h
+ *
+ * Original Author: Naeem M Afzal <naeem.m.afzal@intel.com>
+ * Maintainer: Deepak Saxena <dsaxena@plexity.net>
+ *
+ * Copyright (C) 2002  Intel Corp.
+ * Copyrgiht (C) 2003-2004 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 version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef __ASM_ARM_ARCH_IO_H
+#define __ASM_ARM_ARCH_IO_H
+
+#define IO_SPACE_LIMIT		0xffffffff
+#define __mem_pci(a)		((unsigned long)(a))
+
+/*
+ * Pick up VMALLOC_END
+ */
+#define ___io(p)		((unsigned long)((p)+IXP2000_PCI_IO_VIRT_BASE))
+
+/*
+ * IXP200 does not do proper byte-lane conversion for PCI addresses,
+ * so we need to override standard functions.
+ */
+#define alignb(addr)		((addr & ~3) + (3 - (addr & 3)))
+#define alignw(addr)		((addr & ~2) + (2 - (addr & 2)))
+
+#define outb(v,p)		__raw_writeb(v,alignb(___io(p)))
+#define outw(v,p)		__raw_writew((v),alignw(___io(p)))
+#define outl(v,p)		__raw_writel((v),___io(p))
+
+#define inb(p)		({ unsigned int __v = __raw_readb(alignb(___io(p))); __v; })
+#define inw(p)		\
+	({ unsigned int __v = (__raw_readw(alignw(___io(p)))); __v; })
+#define inl(p)		\
+	({ unsigned int __v = (__raw_readl(___io(p))); __v; })
+
+#define outsb(p,d,l)		__raw_writesb(alignb(___io(p)),d,l)
+#define outsw(p,d,l)		__raw_writesw(alignw(___io(p)),d,l)
+#define outsl(p,d,l)		__raw_writesl(___io(p),d,l)
+
+#define insb(p,d,l)		__raw_readsb(alignb(___io(p)),d,l)
+#define insw(p,d,l)		__raw_readsw(alignw(___io(p)),d,l)
+#define insl(p,d,l)		__raw_readsl(___io(p),d,l)
+
+
+#ifdef CONFIG_ARCH_IXDP2X01
+/*
+ * This is an ugly hack but the CS8900 on the 2x01's does not sit in any sort
+ * of "I/O space" and is just direct mapped into a 32-bit-only addressable
+ * bus. The address space for this bus is such that we can't really easilly
+ * make it contigous to the PCI I/O address range, and it also does not
+ * need swapping like PCI addresses do (IXDP2x01 is a BE platform).
+ * B/C of this we can't use the standard in/out functions and need to
+ * runtime check if the incoming address is a PCI address or for
+ * the CS89x0.
+ */
+#undef inw
+#undef outw
+#undef insw
+#undef outsw
+
+#include <asm/mach-types.h>
+
+static inline void insw(u32 ptr, void *buf, int length)
+{
+	register volatile u32 *port = (volatile u32 *)ptr;
+
+	/*
+	 * Is this cycle meant for the CS8900?
+	 */
+	if ((machine_is_ixdp2401() || machine_is_ixdp2801()) && 
+		((port >= IXDP2X01_CS8900_VIRT_BASE) && 
+		 (port <= IXDP2X01_CS8900_VIRT_END))) {
+		u8 *buf8 = (u8*)buf;
+		register u32 tmp32;
+
+		do {
+			tmp32 = *port;
+			*buf8++ = (u8)tmp32;
+			*buf8++ = (u8)(tmp32 >> 8);
+		} while(--length);
+
+		return;
+	}
+
+	__raw_readsw(alignw(___io(ptr)),buf,length);
+}
+
+static inline void outsw(u32 ptr, void *buf, int length)
+{
+	register volatile u32 *port = (volatile u32 *)ptr;
+
+	/*
+	 * Is this cycle meant for the CS8900?
+	 */
+	if ((machine_is_ixdp2401() || machine_is_ixdp2801()) && 
+		((port >= IXDP2X01_CS8900_VIRT_BASE) && 
+		 (port <= IXDP2X01_CS8900_VIRT_END))) {
+		register u32 tmp32;
+		u8 *buf8 = (u8*)buf;
+		do {
+			tmp32 = *buf8++;
+			tmp32 |= (*buf8++) << 8;
+			*port = tmp32;
+		} while(--length);
+		return;
+	}
+
+	__raw_writesw(alignw(___io(ptr)),buf,length);
+}
+
+
+static inline u16 inw(u32 ptr)
+{
+	register volatile u32 *port = (volatile u32 *)ptr;
+
+	/*
+	 * Is this cycle meant for the CS8900?
+	 */
+	if ((machine_is_ixdp2401() || machine_is_ixdp2801()) && 
+		((port >= IXDP2X01_CS8900_VIRT_BASE) && 
+		 (port <= IXDP2X01_CS8900_VIRT_END))) {
+		return (u16)(*port);  
+	}
+
+	return __raw_readw(alignw(___io(ptr)));
+}
+
+static inline void outw(u16 value, u32 ptr)
+{
+	register volatile u32 *port = (volatile u32 *)ptr;
+
+	if ((machine_is_ixdp2401() || machine_is_ixdp2801()) && 
+		((port >= IXDP2X01_CS8900_VIRT_BASE) && 
+		 (port <= IXDP2X01_CS8900_VIRT_END))) {
+		*port = value;  
+		return;
+	}
+
+	__raw_writew((value),alignw(___io(ptr)));
+}
+#endif	/* IXDP2x01 */
+
+#endif
diff -Nru a/include/asm-arm/arch-ixp2000/irq.h b/include/asm-arm/arch-ixp2000/irq.h
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/include/asm-arm/arch-ixp2000/irq.h	2004-10-18 14:57:24 -07:00
@@ -0,0 +1,13 @@
+/*
+ *  linux/include/asm-arm/arch-ixp2000/irq.h
+ *
+ *  Copyright (C) 2002 Intel Corp.
+ *
+ * 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.
+ */
+
+#define fixup_irq(irq)  (irq)
+
+
diff -Nru a/include/asm-arm/arch-ixp2000/irqs.h b/include/asm-arm/arch-ixp2000/irqs.h
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/include/asm-arm/arch-ixp2000/irqs.h	2004-10-18 14:57:24 -07:00
@@ -0,0 +1,190 @@
+/*
+ * linux/include/asm-arm/arch-ixp2000/irqs.h
+ *
+ * Original Author: Naeem Afzal <naeem.m.afzal@intel.com>
+ * Maintainer: Deepak Saxena <dsaxena@plexity.net>
+ *
+ * Copyright (C) 2002 Intel Corp.
+ * Copyright (C) 2003-2004 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 version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef _IRQS_H
+#define _IRQS_H
+
+/*
+ * Do NOT add #ifdef MACHINE_FOO in here.
+ * Simpy add your machine IRQs here and increase NR_IRQS if needed to
+ * hold your machine's IRQ table.
+ */
+
+/*
+ * Some interrupt numbers go unused b/c the IRQ mask/ummask/status
+ * register has those bit reserved. We just mark those interrupts
+ * as invalid and this allows us to do mask/unmask with a single
+ * shift operation instead of having to map the IRQ number to
+ * a HW IRQ number.
+ */
+#define	IRQ_IXP2000_SWI			0 /* soft interrupt */
+#define	IRQ_IXP2000_ERRSUM		1 /* OR of all bits in ErrorStatus reg*/
+#define	IRQ_IXP2000_UART		2
+#define	IRQ_IXP2000_GPIO		3
+#define	IRQ_IXP2000_TIMER1     		4
+#define	IRQ_IXP2000_TIMER2     		5
+#define	IRQ_IXP2000_TIMER3     		6
+#define	IRQ_IXP2000_TIMER4     		7
+#define	IRQ_IXP2000_PMU        		8               
+#define	IRQ_IXP2000_SPF        		9  /* Slow port framer IRQ */
+#define	IRQ_IXP2000_DMA1      		10
+#define	IRQ_IXP2000_DMA2      		11
+#define	IRQ_IXP2000_DMA3      		12
+#define	IRQ_IXP2000_PCI_DOORBELL	13
+#define	IRQ_IXP2000_ME_ATTN       	14 
+#define	IRQ_IXP2000_PCI   		15 /* PCI INTA or INTB */
+#define	IRQ_IXP2000_THDA0   		16 /* thread 0-31A */
+#define	IRQ_IXP2000_THDA1  		17 /* thread 32-63A */
+#define	IRQ_IXP2000_THDA2		18 /* thread 64-95A */
+#define	IRQ_IXP2000_THDA3 		19 /* thread 96-127A */
+#define	IRQ_IXP2000_THDB0		24 /* thread 0-31 B */
+#define	IRQ_IXP2000_THDB1		25 /* thread 32-63B */
+/* only 64 threads supported for IXP2400, rest or for IXP2800*/
+#define	IRQ_IXP2000_THDB2		26 /* thread 64-95B */
+#define	IRQ_IXP2000_THDB3		27 /* thread 96-127B */
+
+/* define generic GPIOs */
+#define IRQ_IXP2000_GPIO0		32
+#define IRQ_IXP2000_GPIO1		33
+#define IRQ_IXP2000_GPIO2		34
+#define IRQ_IXP2000_GPIO3		35
+#define IRQ_IXP2000_GPIO4		36
+#define IRQ_IXP2000_GPIO5		37
+#define IRQ_IXP2000_GPIO6		38
+#define IRQ_IXP2000_GPIO7		39
+
+/* split off the 2 PCI sources */
+#define IRQ_IXP2000_PCIA		40
+#define IRQ_IXP2000_PCIB		41
+
+/* Int sources from IRQ_ERROR_STATUS */
+#define IRQ_IXP2000_DRAM0_MIN_ERR	42
+#define IRQ_IXP2000_DRAM0_MAJ_ERR	43
+#define IRQ_IXP2000_DRAM1_MIN_ERR	44
+#define IRQ_IXP2000_DRAM1_MAJ_ERR	45
+#define IRQ_IXP2000_DRAM2_MIN_ERR	46
+#define IRQ_IXP2000_DRAM2_MAJ_ERR	47
+#define IRQ_IXP2000_SRAM0_ERR		48
+#define IRQ_IXP2000_SRAM1_ERR		49
+#define IRQ_IXP2000_SRAM2_ERR           50
+#define IRQ_IXP2000_SRAM3_ERR		51
+#define IRQ_IXP2000_MEDIA_ERR		52
+#define IRQ_IXP2000_PCI_ERR		53
+#define IRQ_IXP2000_SP_INT		54
+
+#define NR_IXP2000_IRQS                 55
+
+#define	IXP2000_BOARD_IRQ(x)		(NR_IXP2000_IRQS + (x))
+
+#define	IXP2000_BOARD_IRQ_MASK(irq)	(1 << (irq - NR_IXP2000_IRQS))	
+
+/*
+ * This allows for all the on-chip sources plus up to 32 CPLD based
+ * IRQs. Should be more than enough.
+ */
+#define	IXP2000_BOARD_IRQS		32
+#define NR_IRQS				(NR_IXP2000_IRQS + IXP2000_BOARD_IRQS)
+
+
+/* 
+ * IXDP2400 specific IRQs
+ */
+#define	IRQ_IXDP2400_INGRESS_NPU	IXP2000_BOARD_IRQ(0) 
+#define	IRQ_IXDP2400_ENET		IXP2000_BOARD_IRQ(1) 
+#define	IRQ_IXDP2400_MEDIA_PCI		IXP2000_BOARD_IRQ(2) 
+#define	IRQ_IXDP2400_MEDIA_SP		IXP2000_BOARD_IRQ(3) 
+#define	IRQ_IXDP2400_SF_PCI		IXP2000_BOARD_IRQ(4) 
+#define	IRQ_IXDP2400_SF_SP		IXP2000_BOARD_IRQ(5) 
+#define	IRQ_IXDP2400_PMC		IXP2000_BOARD_IRQ(6) 
+#define	IRQ_IXDP2400_TVM		IXP2000_BOARD_IRQ(7) 
+
+#define	NR_IXDP2400_IRQS		((IRQ_IXDP2400_TVM)+1)  
+#define	IXDP2400_NR_IRQS		NR_IXDP2400_IRQS - NR_IXP2000_IRQS
+
+/* IXDP2800 specific IRQs */
+#define IRQ_IXDP2800_EGRESS_ENET	IXP2000_BOARD_IRQ(0)
+#define IRQ_IXDP2800_INGRESS_NPU	IXP2000_BOARD_IRQ(1)
+#define IRQ_IXDP2800_PMC		IXP2000_BOARD_IRQ(2)
+#define IRQ_IXDP2800_FABRIC_PCI		IXP2000_BOARD_IRQ(3)
+#define IRQ_IXDP2800_FABRIC		IXP2000_BOARD_IRQ(4)
+#define IRQ_IXDP2800_MEDIA		IXP2000_BOARD_IRQ(5)
+
+#define	NR_IXDP2800_IRQS		((IRQ_IXDP2800_MEDIA)+1)
+#define	IXDP2800_NR_IRQS		NR_IXDP2800_IRQS - NR_IXP2000_IRQS
+
+/* 
+ * IRQs on both IXDP2x01 boards
+ */
+#define IRQ_IXDP2X01_SPCI_DB_0		IXP2000_BOARD_IRQ(2)
+#define IRQ_IXDP2X01_SPCI_DB_1		IXP2000_BOARD_IRQ(3)
+#define IRQ_IXDP2X01_SPCI_PMC_INTA	IXP2000_BOARD_IRQ(4)
+#define IRQ_IXDP2X01_SPCI_PMC_INTB	IXP2000_BOARD_IRQ(5)
+#define IRQ_IXDP2X01_SPCI_PMC_INTC	IXP2000_BOARD_IRQ(6)
+#define IRQ_IXDP2X01_SPCI_PMC_INTD	IXP2000_BOARD_IRQ(7)
+#define IRQ_IXDP2X01_SPCI_FIC_INT	IXP2000_BOARD_IRQ(8)
+#define IRQ_IXDP2X01_IPMI_FROM		IXP2000_BOARD_IRQ(16)
+#define IRQ_IXDP2X01_125US		IXP2000_BOARD_IRQ(17)
+#define IRQ_IXDP2X01_DB_0_ADD		IXP2000_BOARD_IRQ(18)
+#define IRQ_IXDP2X01_DB_1_ADD		IXP2000_BOARD_IRQ(19)
+#define IRQ_IXDP2X01_UART1		IXP2000_BOARD_IRQ(21)
+#define IRQ_IXDP2X01_UART2		IXP2000_BOARD_IRQ(22)
+#define IRQ_IXDP2X01_FIC_ADD_INT	IXP2000_BOARD_IRQ(24)
+#define IRQ_IXDP2X01_CS8900		IXP2000_BOARD_IRQ(25)
+#define IRQ_IXDP2X01_BBSRAM		IXP2000_BOARD_IRQ(26)
+
+#define IXDP2X01_VALID_IRQ_MASK ( \
+		IXP2000_BOARD_IRQ_MASK(IRQ_IXDP2X01_SPCI_DB_0) | \
+		IXP2000_BOARD_IRQ_MASK(IRQ_IXDP2X01_SPCI_DB_1) | \
+		IXP2000_BOARD_IRQ_MASK(IRQ_IXDP2X01_SPCI_PMC_INTA) | \
+		IXP2000_BOARD_IRQ_MASK(IRQ_IXDP2X01_SPCI_PMC_INTB) | \
+		IXP2000_BOARD_IRQ_MASK(IRQ_IXDP2X01_SPCI_PMC_INTC) | \
+		IXP2000_BOARD_IRQ_MASK(IRQ_IXDP2X01_SPCI_PMC_INTD) | \
+		IXP2000_BOARD_IRQ_MASK(IRQ_IXDP2X01_SPCI_FIC_INT) | \
+		IXP2000_BOARD_IRQ_MASK(IRQ_IXDP2X01_IPMI_FROM) | \
+		IXP2000_BOARD_IRQ_MASK(IRQ_IXDP2X01_125US) | \
+		IXP2000_BOARD_IRQ_MASK(IRQ_IXDP2X01_DB_0_ADD) | \
+		IXP2000_BOARD_IRQ_MASK(IRQ_IXDP2X01_DB_1_ADD) | \
+		IXP2000_BOARD_IRQ_MASK(IRQ_IXDP2X01_UART1) | \
+		IXP2000_BOARD_IRQ_MASK(IRQ_IXDP2X01_UART2) | \
+		IXP2000_BOARD_IRQ_MASK(IRQ_IXDP2X01_FIC_ADD_INT) | \
+		IXP2000_BOARD_IRQ_MASK(IRQ_IXDP2X01_CS8900) | \
+		IXP2000_BOARD_IRQ_MASK(IRQ_IXDP2X01_BBSRAM) )
+
+/* 
+ * IXDP2401 specific IRQs
+ */
+#define IRQ_IXDP2401_INTA_82546		IXP2000_BOARD_IRQ(0)
+#define IRQ_IXDP2401_INTB_82546		IXP2000_BOARD_IRQ(1)
+
+#define	IXDP2401_VALID_IRQ_MASK ( \
+		IXDP2X01_VALID_IRQ_MASK | \
+		IXP2000_BOARD_IRQ_MASK(IRQ_IXDP2401_INTA_82546) |\
+		IXP2000_BOARD_IRQ_MASK(IRQ_IXDP2401_INTB_82546))
+
+/*
+ * IXDP2801-specific IRQs
+ */
+#define IRQ_IXDP2801_RIV		IXP2000_BOARD_IRQ(0)
+#define IRQ_IXDP2801_CNFG_MEDIA		IXP2000_BOARD_IRQ(27)
+#define IRQ_IXDP2801_CLOCK_REF		IXP2000_BOARD_IRQ(28)
+
+#define	IXDP2801_VALID_IRQ_MASK ( \
+		IXDP2X01_VALID_IRQ_MASK | \
+		IXP2000_BOARD_IRQ_MASK(IRQ_IXDP2801_RIV) |\
+		IXP2000_BOARD_IRQ_MASK(IRQ_IXDP2801_CNFG_MEDIA) |\
+		IXP2000_BOARD_IRQ_MASK(IRQ_IXDP2801_CLOCK_REF))
+
+#define	NR_IXDP2X01_IRQS		((IRQ_IXDP2801_CLOCK_REF) + 1)
+
+#endif /*_IRQS_H*/
diff -Nru a/include/asm-arm/arch-ixp2000/ixdp2x00.h b/include/asm-arm/arch-ixp2000/ixdp2x00.h
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/include/asm-arm/arch-ixp2000/ixdp2x00.h	2004-10-18 14:57:21 -07:00
@@ -0,0 +1,93 @@
+/*
+ * include/asm-arm/arch-ixp2000/ixdp2x00.h
+ *
+ * Register and other defines for IXDP2[48]00 platforms
+ *
+ * Original Author: Naeem Afzal <naeem.m.afzal@intel.com>
+ * Maintainer: Deepak Saxena <dsaxena@plexity.net>
+ *
+ * Copyright (C) 2002 Intel Corp.
+ * Copyright (C) 2003-2004 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.
+ */
+#ifndef _IXDP2X00_H_
+#define _IXDP2X00_H_
+
+/*
+ * On board CPLD memory map
+ */
+#define IXDP2X00_PHYS_CPLD_BASE		0xc7000000
+#define IXDP2X00_VIRT_CPLD_BASE		0xfefdd000
+#define IXDP2X00_CPLD_SIZE		0x00001000
+
+
+#define IXDP2X00_CPLD_REG(x)  	\
+	(volatile unsigned long *)(IXDP2X00_VIRT_CPLD_BASE | x)
+
+/*
+ * IXDP2400 CPLD registers
+ */
+#define IXDP2400_CPLD_SYSLED		IXDP2X00_CPLD_REG(0x0)  
+#define IXDP2400_CPLD_DISP_DATA		IXDP2X00_CPLD_REG(0x4)
+#define IXDP2400_CPLD_CLOCK_SPEED	IXDP2X00_CPLD_REG(0x8)
+#define IXDP2400_CPLD_INT_STAT		IXDP2X00_CPLD_REG(0xc)
+#define IXDP2400_CPLD_REV		IXDP2X00_CPLD_REG(0x10)
+#define IXDP2400_CPLD_SYS_CLK_M		IXDP2X00_CPLD_REG(0x14)
+#define IXDP2400_CPLD_SYS_CLK_N		IXDP2X00_CPLD_REG(0x18)
+#define IXDP2400_CPLD_INT_MASK		IXDP2X00_CPLD_REG(0x48)
+
+/*
+ * IXDP2800 CPLD registers
+ */
+#define IXDP2800_CPLD_INT_STAT		IXDP2X00_CPLD_REG(0x0)
+#define IXDP2800_CPLD_INT_MASK		IXDP2X00_CPLD_REG(0x140)
+
+
+#define	IXDP2X00_GPIO_I2C_ENABLE	0x02
+#define	IXDP2X00_GPIO_SCL		0x07
+#define	IXDP2X00_GPIO_SDA		0x06
+
+/*
+ * PCI devfns for on-board devices. We need these to be able to
+ * properly translte IRQs and for device removal.
+ */
+#define	IXDP2400_SLAVE_ENET_DEVFN	0x18	/* Bus 1 */
+#define	IXDP2400_MASTER_ENET_DEVFN	0x20	/* Bus 1 */
+#define	IXDP2400_MEDIA_DEVFN		0x28	/* Bus 1 */
+#define	IXDP2400_SWITCH_FABRIC_DEVFN	0x30	/* Bus 1 */
+
+#define	IXDP2800_SLAVE_ENET_DEVFN	0x20	/* Bus 1 */
+#define	IXDP2800_MASTER_ENET_DEVFN	0x18	/* Bus 1 */
+#define	IXDP2800_SWITCH_FABRIC_DEVFN	0x30	/* Bus 1 */
+
+#define	IXDP2X00_P2P_DEVFN		0x20	/* Bus 0 */
+#define	IXDP2X00_21555_DEVFN		0x30	/* Bus 0 */
+#define IXDP2X00_SLAVE_NPU_DEVFN	0x28	/* Bus 1 */
+#define	IXDP2X00_PMC_DEVFN		0x38	/* Bus 1 */
+#define IXDP2X00_MASTER_NPU_DEVFN	0x38	/* Bus 1 */
+
+#ifndef __ASSEMBLY__
+/*
+ * Master NPU will always have flash and be PCI master.
+ * Slave NPU may or may not have flash but will never be PCI master.
+ */
+static inline unsigned int ixdp2x00_master_npu(void)
+{
+	return ((ixp2000_has_flash()) && (ixp2000_is_pcimaster()));
+}
+
+/*
+ * Helper functions used by ixdp2400 and ixdp2800 specific code
+ */
+void ixdp2x00_init_irq(volatile unsigned long*, volatile unsigned long *, unsigned long);
+void ixdp2x00_slave_pci_postinit(void);
+void ixdp2x00_init_machine(void);
+void ixdp2x00_map_io(void);
+
+#endif
+
+#endif /*_IXDP2X00_H_ */
diff -Nru a/include/asm-arm/arch-ixp2000/ixdp2x01.h b/include/asm-arm/arch-ixp2000/ixdp2x01.h
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/include/asm-arm/arch-ixp2000/ixdp2x01.h	2004-10-18 14:57:21 -07:00
@@ -0,0 +1,53 @@
+/*
+ * include/asm/arch/ixdp2x01.h
+ *
+ * Platform definitions for IXDP2X01 && IXDP2801 systems
+ *
+ * Author: Deepak Saxena <dsaxena@plexity.net>
+ *
+ * Copyright 2004 (c) MontaVista Software, Inc. 
+ *
+ * Based on original code Copyright (c) 2002-2003 Intel Corporation
+ * 
+ * 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 __IXDP2X01_H__
+#define __IXDP2X01_H__
+
+#define	IXDP2X01_PHYS_CPLD_BASE		0xc6024000
+#define	IXDP2X01_VIRT_CPLD_BASE		0xfefdd000
+#define	IXDP2X01_CPLD_REGION_SIZE	0x1000
+
+#define IXDP2X01_CPLD_VIRT_REG(reg) (volatile u32*)(IXDP2X01_VIRT_CPLD_BASE | reg)
+#define IXDP2X01_CPLD_PHYS_REG(reg) (volatile u32*)(IXDP2X01_PHYS_CPLD_BASE | reg)
+
+#define IXDP2X01_UART1_VIRT_BASE	IXDP2X01_CPLD_VIRT_REG(0x40)
+#define IXDP2X01_UART1_PHYS_BASE	IXDP2X01_CPLD_PHYS_REG(0x40)
+
+#define IXDP2X01_UART2_VIRT_BASE	IXDP2X01_CPLD_VIRT_REG(0x60)
+#define IXDP2X01_UART2_PHYS_BASE	IXDP2X01_CPLD_PHYS_REG(0x60)
+
+#define IXDP2X01_CS8900_VIRT_BASE	IXDP2X01_CPLD_VIRT_REG(0x80)
+#define IXDP2X01_CS8900_VIRT_END	(IXDP2X01_CS8900_VIRT_BASE + 16)
+
+#define IXDP2X01_CPLD_RESET_REG         IXDP2X01_CPLD_VIRT_REG(0x00)
+#define IXDP2X01_INT_MASK_SET_REG	IXDP2X01_CPLD_VIRT_REG(0x08)
+#define IXDP2X01_INT_STAT_REG		IXDP2X01_CPLD_VIRT_REG(0x0C)
+#define IXDP2X01_INT_RAW_REG		IXDP2X01_CPLD_VIRT_REG(0x10) 
+#define IXDP2X01_INT_MASK_CLR_REG	IXDP2X01_INT_RAW_REG
+#define IXDP2X01_INT_SIM_REG		IXDP2X01_CPLD_VIRT_REG(0x14)
+
+#define IXDP2X01_CPLD_FLASH_REG		IXDP2X01_CPLD_VIRT_REG(0x20)
+
+#define IXDP2X01_CPLD_FLASH_INTERN 	0x8000
+#define IXDP2X01_CPLD_FLASH_BANK_MASK 	0xF
+#define IXDP2X01_FLASH_WINDOW_BITS 	25
+#define IXDP2X01_FLASH_WINDOW_SIZE 	(1 << IXDP2X01_FLASH_WINDOW_BITS)
+#define IXDP2X01_FLASH_WINDOW_MASK 	(IXDP2X01_FLASH_WINDOW_SIZE - 1)
+
+#define	IXDP2X01_UART_CLK		1843200
+
+#endif /* __IXDP2x01_H__ */
diff -Nru a/include/asm-arm/arch-ixp2000/ixp2000-regs.h b/include/asm-arm/arch-ixp2000/ixp2000-regs.h
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/include/asm-arm/arch-ixp2000/ixp2000-regs.h	2004-10-18 14:57:21 -07:00
@@ -0,0 +1,337 @@
+/*
+ * include/asm-arm/arch-ixp2000/ixp2000-regs.h
+ *
+ * Chipset register definitions for IXP2400/2800 based systems.
+ *
+ * Original Author: Naeem Afzal <naeem.m.afzal@intel.com>
+ *
+ * Maintainer: Deepak Saxena <dsaxena@plexity.net>
+ *
+ * Copyright (C) 2002 Intel Corp.
+ * Copyright (C) 2003-2004 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.
+ */
+#ifndef _IXP2000_REGS_H_
+#define _IXP2000_REGS_H_
+
+/* 
+ * Static I/O regions. The manual defines each region as being several
+ * MB in size, but all the registers are within the first 4K, so there's
+ * no purpose in mapping the whole region in.
+ */
+#define	IXP2000_SLOWPORT_CSR_PHYS_BASE	0xc0080000
+#define	IXP2000_SLOWPORT_CSR_VIRT_BASE	0xfefff000
+#define	IXP2000_SLOWPORT_CSR_SIZE	0x1000
+
+#define	IXP2000_GLOBAL_REG_PHYS_BASE	0xc0004000
+#define	IXP2000_GLOBAL_REG_VIRT_BASE	0xfeffe000
+#define	IXP2000_GLOBAL_REG_SIZE		0x1000
+
+#define	IXP2000_UART_PHYS_BASE		0xc0030000
+#define	IXP2000_UART_VIRT_BASE		0xfef30000
+#define IXP2000_UART_SIZE		0x1000
+
+#define	IXP2000_TIMER_PHYS_BASE		0xc0020000
+#define	IXP2000_TIMER_VIRT_BASE		0xfeffc000
+#define	IXP2000_TIMER_SIZE		0x1000
+
+#define	IXP2000_GPIO_PHYS_BASE		0xc0010000
+#define	IXP2000_GPIO_VIRT_BASE		0xfeffb000
+#define	IXP2000_GPIO_SIZE		0x1000
+
+#define IXP2000_INTCTL_PHYS_BASE	0xd6000000
+#define	IXP2000_INTCTL_VIRT_BASE	0xfeffa000
+#define	IXP2000_INTCTL_SIZE		0x01000
+
+#define IXP2000_PCI_CREG_PHYS_BASE	0xde000000
+#define	IXP2000_PCI_CREG_VIRT_BASE	0xfeff0000
+#define	IXP2000_PCI_CREG_SIZE		0x1000
+
+#define IXP2000_PCI_CSR_PHYS_BASE	0xdf000000
+#define	IXP2000_PCI_CSR_VIRT_BASE	0xfefde000
+#define	IXP2000_PCI_CSR_SIZE		0x1000
+
+#define IXP2000_PCI_IO_PHYS_BASE	0xd8000000
+#define	IXP2000_PCI_IO_VIRT_BASE	0xfd000000
+#define IXP2000_PCI_IO_SIZE     	0x01000000
+
+#define IXP2000_PCI_CFG0_PHYS_BASE	0xda000000
+#define IXP2000_PCI_CFG0_VIRT_BASE	0xfc000000
+#define IXP2000_PCI_CFG0_SIZE   	0x01000000
+
+#define IXP2000_PCI_CFG1_PHYS_BASE	0xdb000000
+#define IXP2000_PCI_CFG1_VIRT_BASE	0xfb000000
+#define IXP2000_PCI_CFG1_SIZE		0x01000000
+
+
+/* 
+ * Timers
+ */
+#define	IXP2000_TIMER_REG(x)		((volatile unsigned long*)(IXP2000_TIMER_VIRT_BASE | (x)))
+/* Timer control */
+#define	IXP2000_T1_CTL			IXP2000_TIMER_REG(0x00)
+#define	IXP2000_T2_CTL			IXP2000_TIMER_REG(0x04)
+#define	IXP2000_T3_CTL			IXP2000_TIMER_REG(0x08)
+#define	IXP2000_T4_CTL			IXP2000_TIMER_REG(0x0c)
+/* Store initial value */
+#define	IXP2000_T1_CLD			IXP2000_TIMER_REG(0x10)
+#define	IXP2000_T2_CLD			IXP2000_TIMER_REG(0x14)
+#define	IXP2000_T3_CLD			IXP2000_TIMER_REG(0x18)
+#define	IXP2000_T4_CLD			IXP2000_TIMER_REG(0x1c)
+/* Read current value */
+#define	IXP2000_T1_CSR			IXP2000_TIMER_REG(0x20)
+#define	IXP2000_T2_CSR			IXP2000_TIMER_REG(0x24)
+#define	IXP2000_T3_CSR			IXP2000_TIMER_REG(0x28)
+#define	IXP2000_T4_CSR			IXP2000_TIMER_REG(0x2c)
+/* Clear associated timer interrupt */
+#define	IXP2000_T1_CLR			IXP2000_TIMER_REG(0x30)
+#define	IXP2000_T2_CLR			IXP2000_TIMER_REG(0x34)
+#define	IXP2000_T3_CLR			IXP2000_TIMER_REG(0x38)
+#define	IXP2000_T4_CLR			IXP2000_TIMER_REG(0x3c)
+/* Timer watchdog enable for T4 */
+#define	IXP2000_TWDE			IXP2000_TIMER_REG(0x40)
+
+#define	WDT_ENABLE			0x00000001
+#define	TIMER_DIVIDER_256		0x00000008
+#define	TIMER_ENABLE			0x00000080
+
+/*
+ * Interrupt controller registers
+ */
+#define IXP2000_INTCTL_REG(x)		(volatile unsigned long*)(IXP2000_INTCTL_VIRT_BASE | (x))
+#define IXP2000_IRQ_STATUS		IXP2000_INTCTL_REG(0x08)
+#define IXP2000_IRQ_ENABLE		IXP2000_INTCTL_REG(0x10)
+#define IXP2000_IRQ_ENABLE_SET		IXP2000_INTCTL_REG(0x10)
+#define IXP2000_IRQ_ENABLE_CLR		IXP2000_INTCTL_REG(0x18)
+#define IXP2000_FIQ_ENABLE_CLR		IXP2000_INTCTL_REG(0x14)
+#define IXP2000_IRQ_ERR_STATUS		IXP2000_INTCTL_REG(0x24)
+#define IXP2000_IRQ_ERR_ENABLE_SET	IXP2000_INTCTL_REG(0x2c)
+#define IXP2000_FIQ_ERR_ENABLE_CLR	IXP2000_INTCTL_REG(0x30)
+#define IXP2000_IRQ_ERR_ENABLE_CLR	IXP2000_INTCTL_REG(0x34)
+
+/*
+ * Mask of valid IRQs in the 32-bit IRQ register. We use
+ * this to mark certain IRQs as being in-valid.
+ */
+#define	IXP2000_VALID_IRQ_MASK	0x0f0fffff
+
+/*
+ * PCI config register access from core
+ */
+#define IXP2000_PCI_CREG(x)		(volatile unsigned long*)(IXP2000_PCI_CREG_VIRT_BASE | (x))
+#define IXP2000_PCI_CMDSTAT 		IXP2000_PCI_CREG(0x04)
+#define IXP2000_PCI_CSR_BAR		IXP2000_PCI_CREG(0x10)
+#define IXP2000_PCI_SRAM_BAR		IXP2000_PCI_CREG(0x14)
+#define IXP2000_PCI_SDRAM_BAR		IXP2000_PCI_CREG(0x18)
+
+/*
+ * PCI CSRs
+ */
+#define IXP2000_PCI_CSR(x)		(volatile unsigned long*)(IXP2000_PCI_CSR_VIRT_BASE | (x))
+
+/*
+ * PCI outbound interrupts
+ */
+#define IXP2000_PCI_OUT_INT_STATUS	IXP2000_PCI_CSR(0x30)
+#define IXP2000_PCI_OUT_INT_MASK	IXP2000_PCI_CSR(0x34)
+/*
+ * PCI communications
+ */
+#define IXP2000_PCI_MAILBOX0		IXP2000_PCI_CSR(0x50)
+#define IXP2000_PCI_MAILBOX1		IXP2000_PCI_CSR(0x54)
+#define IXP2000_PCI_MAILBOX2		IXP2000_PCI_CSR(0x58)
+#define IXP2000_PCI_MAILBOX3		IXP2000_PCI_CSR(0x5C)
+#define IXP2000_XSCALE_DOORBELL		IXP2000_PCI_CSR(0x60)
+#define IXP2000_XSCALE_DOORBELL_SETUP	IXP2000_PCI_CSR(0x64)
+#define IXP2000_PCI_DOORBELL		IXP2000_PCI_CSR(0x70)
+#define IXP2000_PCI_DOORBELL_SETUP	IXP2000_PCI_CSR(0x74)
+
+/*
+ * DMA engines
+ */
+#define IXP2000_PCI_CH1_BYTE_CNT	IXP2000_PCI_CSR(0x80)
+#define IXP2000_PCI_CH1_ADDR		IXP2000_PCI_CSR(0x84)
+#define IXP2000_PCI_CH1_DRAM_ADDR	IXP2000_PCI_CSR(0x88)
+#define IXP2000_PCI_CH1_DESC_PTR	IXP2000_PCI_CSR(0x8C)
+#define IXP2000_PCI_CH1_CNTRL		IXP2000_PCI_CSR(0x90)
+#define IXP2000_PCI_CH1_ME_PARAM	IXP2000_PCI_CSR(0x94)
+#define IXP2000_PCI_CH2_BYTE_CNT	IXP2000_PCI_CSR(0xA0)
+#define IXP2000_PCI_CH2_ADDR		IXP2000_PCI_CSR(0xA4)
+#define IXP2000_PCI_CH2_DRAM_ADDR	IXP2000_PCI_CSR(0xA8)
+#define IXP2000_PCI_CH2_DESC_PTR	IXP2000_PCI_CSR(0xAC)
+#define IXP2000_PCI_CH2_CNTRL		IXP2000_PCI_CSR(0xB0)
+#define IXP2000_PCI_CH2_ME_PARAM	IXP2000_PCI_CSR(0xB4)
+#define IXP2000_PCI_CH3_BYTE_CNT	IXP2000_PCI_CSR(0xC0)
+#define IXP2000_PCI_CH3_ADDR		IXP2000_PCI_CSR(0xC4)
+#define IXP2000_PCI_CH3_DRAM_ADDR	IXP2000_PCI_CSR(0xC8)
+#define IXP2000_PCI_CH3_DESC_PTR	IXP2000_PCI_CSR(0xCC)
+#define IXP2000_PCI_CH3_CNTRL		IXP2000_PCI_CSR(0xD0)
+#define IXP2000_PCI_CH3_ME_PARAM	IXP2000_PCI_CSR(0xD4)
+#define IXP2000_DMA_INF_MODE		IXP2000_PCI_CSR(0xE0)
+/*
+ * Size masks for BARs
+ */
+#define IXP2000_PCI_SRAM_BASE_ADDR_MASK	IXP2000_PCI_CSR(0xFC)
+#define IXP2000_PCI_DRAM_BASE_ADDR_MASK	IXP2000_PCI_CSR(0x100)
+/*
+ * Control and uEngine related
+ */
+#define IXP2000_PCI_CONTROL		IXP2000_PCI_CSR(0x13C)
+#define IXP2000_PCI_ADDR_EXT		IXP2000_PCI_CSR(0x140)
+#define IXP2000_PCI_ME_PUSH_STATUS	IXP2000_PCI_CSR(0x148)
+#define IXP2000_PCI_ME_PUSH_EN		IXP2000_PCI_CSR(0x14C)
+#define IXP2000_PCI_ERR_STATUS		IXP2000_PCI_CSR(0x150)
+#define IXP2000_PCI_ERR_ENABLE		IXP2000_PCI_CSR(0x154)
+/*
+ * Inbound PCI interrupt control
+ */
+#define IXP2000_PCI_XSCALE_INT_STATUS	IXP2000_PCI_CSR(0x158)
+#define IXP2000_PCI_XSCALE_INT_ENABLE	IXP2000_PCI_CSR(0x15C)
+
+#define IXP2000_PCICNTL_PNR		(1<<17)	/* PCI not Reset bit of PCI_CONTROL */
+#define IXP2000_PCICNTL_PCF		(1<<28)	/* PCI Centrolfunction bit */
+#define IXP2000_XSCALE_INT		(1<<1)	/* Interrupt from  XScale to PCI */
+
+/* These are from the IRQ register in the PCI ISR register */
+#define PCI_CONTROL_BE_DEO		(1 << 22)	/* Big Endian Data Enable Out */
+#define PCI_CONTROL_BE_DEI		(1 << 21)	/* Big Endian Data Enable In  */
+#define PCI_CONTROL_BE_BEO		(1 << 20)	/* Big Endian Byte Enable Out */
+#define PCI_CONTROL_BE_BEI		(1 << 19)	/* Big Endian Byte Enable In  */
+#define PCI_CONTROL_PNR			(1 << 17)	/* PCI Not Reset bit */
+
+#define IXP2000_PCI_RST_REL		(1 << 2)
+#define CFG_RST_DIR			(*IXP2000_PCI_CONTROL & IXP2000_PCICNTL_PCF)
+#define CFG_PCI_BOOT_HOST		(1 << 2)
+#define CFG_BOOT_PROM			(1 << 1)
+
+/*
+ * SlowPort CSRs
+ *
+ * The slowport is used to access things like flash, SONET framer control
+ * ports, slave microprocessors, CPLDs, and others of chip memory mapped
+ * peripherals.
+ */
+#define	SLOWPORT_CSR(x)		(volatile unsigned long*)(IXP2000_SLOWPORT_CSR_VIRT_BASE | (x))
+
+#define	IXP2000_SLOWPORT_CCR		SLOWPORT_CSR(0x00)
+#define	IXP2000_SLOWPORT_WTC1		SLOWPORT_CSR(0x04)
+#define	IXP2000_SLOWPORT_WTC2		SLOWPORT_CSR(0x08)
+#define	IXP2000_SLOWPORT_RTC1		SLOWPORT_CSR(0x0c)
+#define	IXP2000_SLOWPORT_RTC2		SLOWPORT_CSR(0x10)
+#define	IXP2000_SLOWPORT_FSR		SLOWPORT_CSR(0x14)
+#define	IXP2000_SLOWPORT_PCR		SLOWPORT_CSR(0x18)
+#define	IXP2000_SLOWPORT_ADC		SLOWPORT_CSR(0x1C)
+#define	IXP2000_SLOWPORT_FAC		SLOWPORT_CSR(0x20)
+#define	IXP2000_SLOWPORT_FRM		SLOWPORT_CSR(0x24)
+#define	IXP2000_SLOWPORT_FIN		SLOWPORT_CSR(0x28)
+
+/*
+ * CCR values.  
+ * The CCR configures the clock division for the slowport interface.
+ */
+#define	SLOWPORT_CCR_DIV_1		0x00
+#define	SLOWPORT_CCR_DIV_2		0x01
+#define	SLOWPORT_CCR_DIV_4		0x02
+#define	SLOWPORT_CCR_DIV_6		0x03
+#define	SLOWPORT_CCR_DIV_8		0x04
+#define	SLOWPORT_CCR_DIV_10		0x05
+#define	SLOWPORT_CCR_DIV_12		0x06
+#define	SLOWPORT_CCR_DIV_14		0x07
+#define	SLOWPORT_CCR_DIV_16		0x08
+#define	SLOWPORT_CCR_DIV_18		0x09
+#define	SLOWPORT_CCR_DIV_20		0x0a
+#define	SLOWPORT_CCR_DIV_22		0x0b
+#define	SLOWPORT_CCR_DIV_24		0x0c
+#define	SLOWPORT_CCR_DIV_26		0x0d
+#define	SLOWPORT_CCR_DIV_28		0x0e
+#define	SLOWPORT_CCR_DIV_30		0x0f
+
+/*
+ * PCR values.  PCR configure the mode of the interfac3
+ */
+#define	SLOWPORT_MODE_FLASH		0x00
+#define	SLOWPORT_MODE_LUCENT		0x01
+#define	SLOWPORT_MODE_PMC_SIERRA	0x02
+#define	SLOWPORT_MODE_INTEL_UP		0x03
+#define	SLOWPORT_MODE_MOTOROLA_UP	0x04
+
+/*
+ * ADC values.  Defines data and address bus widths
+ */
+#define	SLOWPORT_ADDR_WIDTH_8		0x00
+#define	SLOWPORT_ADDR_WIDTH_16		0x01
+#define	SLOWPORT_ADDR_WIDTH_24		0x02
+#define	SLOWPORT_ADDR_WIDTH_32		0x03
+#define	SLOWPORT_DATA_WIDTH_8		0x00
+#define	SLOWPORT_DATA_WIDTH_16		0x10
+#define	SLOWPORT_DATA_WIDTH_24		0x20
+#define	SLOWPORT_DATA_WIDTH_32		0x30
+
+/*
+ * Masks and shifts for various fields in the WTC and RTC registers
+ */
+#define	SLOWPORT_WRTC_MASK_HD		0x0003
+#define	SLOWPORT_WRTC_MASK_SU		0x003c
+#define	SLOWPORT_WRTC_MASK_PW		0x03c0
+
+#define	SLOWPORT_WRTC_SHIFT_HD		0x00
+#define	SLOWPORT_WRTC_SHIFT_SU		0x02
+#define	SLOWPORT_WRTC_SHFIT_PW		0x06
+
+
+/*
+ * GPIO registers & GPIO interface
+ */
+#define IXP2000_GPIO_REG(x)		((volatile unsigned long*)(IXP2000_GPIO_VIRT_BASE+(x)))
+#define IXP2000_GPIO_PLR		IXP2000_GPIO_REG(0x00)
+#define IXP2000_GPIO_PDPR		IXP2000_GPIO_REG(0x04)
+#define IXP2000_GPIO_PDSR		IXP2000_GPIO_REG(0x08)
+#define IXP2000_GPIO_PDCR		IXP2000_GPIO_REG(0x0c)
+#define IXP2000_GPIO_POPR		IXP2000_GPIO_REG(0x10)
+#define IXP2000_GPIO_POSR		IXP2000_GPIO_REG(0x14)
+#define IXP2000_GPIO_POCR		IXP2000_GPIO_REG(0x18)
+#define IXP2000_GPIO_REDR		IXP2000_GPIO_REG(0x1c)
+#define IXP2000_GPIO_FEDR		IXP2000_GPIO_REG(0x20)
+#define IXP2000_GPIO_EDSR		IXP2000_GPIO_REG(0x24)
+#define IXP2000_GPIO_LSHR		IXP2000_GPIO_REG(0x28)
+#define IXP2000_GPIO_LSLR		IXP2000_GPIO_REG(0x2c)
+#define IXP2000_GPIO_LDSR		IXP2000_GPIO_REG(0x30)
+#define IXP2000_GPIO_INER		IXP2000_GPIO_REG(0x34)
+#define IXP2000_GPIO_INSR		IXP2000_GPIO_REG(0x38)
+#define IXP2000_GPIO_INCR		IXP2000_GPIO_REG(0x3c)
+#define IXP2000_GPIO_INST		IXP2000_GPIO_REG(0x40)
+
+/*
+ * "Global" registers...whatever that's supposed to mean.
+ */
+#define GLOBAL_REG_BASE			(IXP2000_GLOBAL_REG_VIRT_BASE + 0x0a00)
+#define GLOBAL_REG(x)			(volatile unsigned long*)(GLOBAL_REG_BASE | (x))
+
+#define IXP2000_PROD_ID			GLOBAL_REG(0x00)
+
+#define IXP2000_MAJ_PROD_TYPE_MASK	0x001F0000
+#define IXP2000_MAJ_PROD_TYPE_IXP2000	0x00000000
+#define IXP2000_MIN_PROD_TYPE_MASK 	0x0000FF00
+#define IXP2000_MIN_PROD_TYPE_IXP2400	0x00000200
+#define IXP2000_MIN_PROD_TYPE_IXP2850	0x00000100
+#define IXP2000_MIN_PROD_TYPE_IXP2800	0x00000000
+#define IXP2000_MAJ_REV_MASK	      	0x000000F0
+#define IXP2000_MIN_REV_MASK	      	0x0000000F
+#define IXP2000_PROD_ID_MASK		0xFFFFFFFF
+
+#define IXP2000_MISC_CONTROL		GLOBAL_REG(0x04)
+#define IXP2000_MSF_CLK_CNTRL  		GLOBAL_REG(0x08)
+#define IXP2000_RESET0      		GLOBAL_REG(0x0c)
+#define IXP2000_RESET1      		GLOBAL_REG(0x10)
+#define IXP2000_CCR            		GLOBAL_REG(0x14)
+#define	IXP2000_STRAP_OPTIONS  		GLOBAL_REG(0x18)
+
+#define	RSTALL				(1 << 16)
+#define	WDT_RESET_ENABLE		0x01000000
+
+
+#endif				/* _IXP2000_H_ */
diff -Nru a/include/asm-arm/arch-ixp2000/memory.h b/include/asm-arm/arch-ixp2000/memory.h
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/include/asm-arm/arch-ixp2000/memory.h	2004-10-18 14:57:24 -07:00
@@ -0,0 +1,34 @@
+/*
+ * linux/include/asm-arm/arch-ixp2000/memory.h
+ *
+ * Copyright (c) 2002 Intel Corp.
+ * Copyright (c) 2003-2004 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.
+ */
+
+#ifndef __ASM_ARCH_MEMORY_H
+#define __ASM_ARCH_MEMORY_H
+
+#define PHYS_OFFSET	(0x00000000UL)
+
+/*
+ * Virtual view <-> DMA view memory address translations
+ * virt_to_bus: Used to translate the virtual address to an
+ *		address suitable to be passed to set_dma_addr
+ * bus_to_virt: Used to convert an address for DMA operations
+ *		to an address that the kernel can use.
+ */
+#include <asm/arch/ixp2000-regs.h>
+
+#define __virt_to_bus(v) \
+	(((__virt_to_phys(v) - 0x0) + (*IXP2000_PCI_SDRAM_BAR & 0xfffffff0)))
+
+#define __bus_to_virt(b) \
+	__phys_to_virt((((b - (*IXP2000_PCI_SDRAM_BAR & 0xfffffff0)) + 0x0)))
+
+#endif
+
diff -Nru a/include/asm-arm/arch-ixp2000/param.h b/include/asm-arm/arch-ixp2000/param.h
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/include/asm-arm/arch-ixp2000/param.h	2004-10-18 14:57:23 -07:00
@@ -0,0 +1,3 @@
+/*
+ *  linux/include/asm-arm/arch-ixp2000/param.h
+ */
diff -Nru a/include/asm-arm/arch-ixp2000/platform.h b/include/asm-arm/arch-ixp2000/platform.h
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/include/asm-arm/arch-ixp2000/platform.h	2004-10-18 14:57:21 -07:00
@@ -0,0 +1,165 @@
+/*
+ * include/asm-arh/arch-ixp2000/platform.h
+ *
+ * Various bits of code used by platform-level code.
+ *
+ * Author: Deepak Saxena <dsaxena@plexity.net>
+ *
+ * Copyright 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.
+ */
+
+
+#ifndef __ASSEMBLY__
+
+/*
+ * The IXP2400 B0 silicon contains an errata that causes writes to 
+ * on-chip I/O register to not complete fully. What this means is
+ * that if you have a write to on-chip I/O followed by a back-to-back
+ * read or write, the first write will happend twice. OR...if it's
+ * not a back-to-back trasaction, the read or write will generate 
+ * incorrect data.
+ *
+ * The official work around for this is to set the on-chip I/O regions
+ * as XCB=101 and then force a read-back from the register.
+ *
+ */
+#if defined(CONFIG_ARCH_ENP2611) || defined(CONFIG_ARCH_IXDP2400) || defined(CONFIG_ARCH_IXDP2401)
+
+#include <asm/system.h>		/* Pickup local_irq_ functions */
+
+static inline void ixp2000_reg_write(volatile unsigned long *reg, unsigned long val)
+{
+	volatile unsigned long dummy;
+	unsigned long flags;
+
+	local_irq_save(flags);
+	*reg = val;
+	barrier();
+	dummy = *reg;
+	local_irq_restore(flags);
+}
+#else
+#define	ixp2000_reg_write(reg, val) (*reg = val)
+#endif	/* IXDP2400 || IXDP2401 */
+
+/*
+ * Boards may multiplex different devices on the 2nd channel of 
+ * the slowport interface that each need different configuration 
+ * settings.  For example, the IXDP2400 uses channel 2 on the interface 
+ * to access the CPLD, the switch fabric card, and te media card.  Each 
+ * one needs a different mode so drivers must save/restore the mode 
+ * before and after each operation.  
+ *
+ * acquire_slowport(&your_config);
+ * ...
+ * do slowport operations
+ * ...
+ * release_slowport();
+ *
+ * Note that while you have the slowport, you are holding a spinlock,
+ * so your code should be written as if you explicitly acquired a lock.
+ *
+ * The configuration only affects device 2 on the slowport, so the
+ * MTD map driver does not acquire/release the slowport.  
+ */
+struct slowport_cfg {
+	unsigned long CCR;	/* Clock divide */
+	unsigned long WTC;	/* Write Timing Control */
+	unsigned long RTC;	/* Read Timing Control */
+	unsigned long PCR;	/* Protocol Control Register */
+	unsigned long ADC;	/* Address/Data Width Control */
+};
+
+
+void ixp2000_acquire_slowport(struct slowport_cfg *, struct slowport_cfg *);
+void ixp2000_release_slowport(struct slowport_cfg *);
+
+/*
+ * IXP2400 A0/A1 and  IXP2800 A0/A1/A2 have broken slowport that requires
+ * tweaking of addresses in the MTD driver.
+ */
+static inline unsigned ixp2000_has_broken_slowport(void)
+{
+	unsigned long id = *IXP2000_PROD_ID;
+	unsigned long id_prod = id & (IXP2000_MAJ_PROD_TYPE_MASK |
+				      IXP2000_MIN_PROD_TYPE_MASK);
+	return (((id_prod ==
+		  /* fixed in IXP2400-B0 */
+		  (IXP2000_MAJ_PROD_TYPE_IXP2000 |
+		   IXP2000_MIN_PROD_TYPE_IXP2400)) &&
+		 ((id & IXP2000_MAJ_REV_MASK) == 0)) ||
+		((id_prod ==
+		  /* fixed in IXP2800-B0 */
+		  (IXP2000_MAJ_PROD_TYPE_IXP2000 |
+		   IXP2000_MIN_PROD_TYPE_IXP2800)) &&
+		 ((id & IXP2000_MAJ_REV_MASK) == 0)) ||
+		((id_prod ==
+		  /* fixed in IXP2850-B0 */
+		  (IXP2000_MAJ_PROD_TYPE_IXP2000 |
+		   IXP2000_MIN_PROD_TYPE_IXP2850)) &&
+		 ((id & IXP2000_MAJ_REV_MASK) == 0)));
+}
+
+static inline unsigned int ixp2000_has_flash(void)
+{
+	return ((*IXP2000_STRAP_OPTIONS) & (CFG_BOOT_PROM));
+}
+
+static inline unsigned int ixp2000_is_pcimaster(void)
+{
+	return ((*IXP2000_STRAP_OPTIONS) & (CFG_PCI_BOOT_HOST));
+}
+
+void ixp2000_map_io(void);
+void ixp2000_init_irq(void);
+void ixp2000_init_time(unsigned long);
+
+struct pci_sys_data;
+
+void ixp2000_pci_preinit(void);
+int ixp2000_pci_setup(int, struct pci_sys_data*);
+struct pci_bus* ixp2000_pci_scan_bus(int, struct pci_sys_data*);
+int ixp2000_pci_read_config(struct pci_bus*, unsigned int, int, int, u32 *);
+int ixp2000_pci_write_config(struct pci_bus*, unsigned int, int, int, u32);
+
+/*
+ * Several of the IXP2000 systems have banked flash so we need to extend the
+ * flash_platform_data structure with some private pointers
+ */
+struct ixp2000_flash_data {
+	struct flash_platform_data *platform_data;
+	int nr_banks;
+	unsigned long (*bank_setup)(unsigned long);
+};
+
+/*
+ * GPIO helper functions
+ */
+#define	GPIO_IN		0
+#define	GPIO_OUT	1
+
+extern void gpio_line_config(int line, int style);
+
+static inline int gpio_line_get(int line)
+{
+	return (((*IXP2000_GPIO_PLR) >> line) & 1);
+}
+
+static inline void gpio_line_set(int line, int value)
+{
+	if (value) 
+		ixp2000_reg_write(IXP2000_GPIO_POSR, (1 << line));
+	else 
+		ixp2000_reg_write(IXP2000_GPIO_POCR, (1 << line));
+}
+
+struct ixp2000_i2c_pins {
+	unsigned long sda_pin;
+	unsigned long scl_pin;
+};
+
+#endif /*  !__ASSEMBLY__ */
diff -Nru a/include/asm-arm/arch-ixp2000/serial.h b/include/asm-arm/arch-ixp2000/serial.h
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/include/asm-arm/arch-ixp2000/serial.h	2004-10-18 14:57:21 -07:00
@@ -0,0 +1,27 @@
+/*
+ * include/asm-arm/arch-ixp2000/serial.h
+ *
+ * Serial port defn for ixp2000 based systems.
+ *
+ * Author: Deepak Saxena <dsaxena@plexity.net>
+ *
+ * Copyright (c) 2002-2004 MontaVista Software, Inc.
+ *
+ * We do not register serial ports staticly b/c there is no easy way
+ * to autodetect an XScale port. Instead we register them at runtime
+ * via early_serial_init().
+ */
+
+#ifndef _ARCH_SERIAL_H_
+#define _ARCH_SERIAL_H_
+
+#define BASE_BAUD (50000000/ 16)
+
+/*
+ * Currently no IXP2000 systems with > 3 serial ports.
+ * If you add a system that does, just up this.
+ */
+#define	STD_SERIAL_PORT_DEFNS
+#define	EXTRA_SERIAL_PORT_DEFNS
+
+#endif  // __ARCH_SERIAL_H_
diff -Nru a/include/asm-arm/arch-ixp2000/system.h b/include/asm-arm/arch-ixp2000/system.h
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/include/asm-arm/arch-ixp2000/system.h	2004-10-18 14:57:23 -07:00
@@ -0,0 +1,35 @@
+/*
+ * linux/include/asm-arm/arch-ixp2400/system.h
+ *
+ * Copyright (C) 2002 Intel Corp.
+ *
+ * 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 <asm/hardware.h>
+#include <asm/mach-types.h>
+
+static inline void arch_idle(void)
+{
+	cpu_do_idle();
+}
+
+static inline void arch_reset(char mode)
+{
+	cli();
+
+	if (machine_is_ixdp2401() || machine_is_ixdp2801()) {
+		*IXDP2X01_CPLD_FLASH_REG = ((0 >> IXDP2X01_FLASH_WINDOW_BITS) | IXDP2X01_CPLD_FLASH_INTERN);
+		*IXDP2X01_CPLD_RESET_REG = 0xffffffff;
+	}
+
+	/*
+	 * We do a reset all if we are PCI master. We could be a slave and we
+	 * don't want to do anything funky on the PCI bus.
+	 */
+	if (*IXP2000_STRAP_OPTIONS & CFG_PCI_BOOT_HOST) {
+		*(IXP2000_RESET0) |= (RSTALL);
+	}
+}
diff -Nru a/include/asm-arm/arch-ixp2000/timex.h b/include/asm-arm/arch-ixp2000/timex.h
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/include/asm-arm/arch-ixp2000/timex.h	2004-10-18 14:57:21 -07:00
@@ -0,0 +1,13 @@
+/*
+ * linux/include/asm-arm/arch-ixp2000/timex.h
+ *
+ * IXP2000 architecture timex specifications
+ */
+
+
+/*
+ * Default clock is 50MHz APB, but platform code can override this
+ */
+#define CLOCK_TICK_RATE	50000000
+
+
diff -Nru a/include/asm-arm/arch-ixp2000/uncompress.h b/include/asm-arm/arch-ixp2000/uncompress.h
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/include/asm-arm/arch-ixp2000/uncompress.h	2004-10-18 14:57:22 -07:00
@@ -0,0 +1,52 @@
+/*
+ * linux/include/asm-arm/arch-ixp2000/uncompress.h
+ *
+ *
+ * Original Author: Naeem Afzal <naeem.m.afzal@intel.com>
+ * Maintainer: Deepak Saxena <dsaxena@plexity.net>
+ *
+ * Copyright 2002 Intel Corp.
+ *
+ *  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/serial_reg.h>
+
+#define UART_BASE	0xc0030000
+
+#define PHYS(x)          ((volatile unsigned long *)(UART_BASE + x))
+
+#define UARTDR          PHYS(0x00)      /* Transmit reg dlab=0 */
+#define UARTDLL         PHYS(0x00)      /* Divisor Latch reg dlab=1*/
+#define UARTDLM         PHYS(0x04)      /* Divisor Latch reg dlab=1*/
+#define UARTIER         PHYS(0x04)      /* Interrupt enable reg */
+#define UARTFCR         PHYS(0x08)      /* FIFO control reg dlab =0*/
+#define UARTLCR         PHYS(0x0c)      /* Control reg */
+#define UARTSR          PHYS(0x14)      /* Status reg */
+
+
+static __inline__ void putc(char c)
+{
+	int j = 0x1000;
+
+	while (--j && !(*UARTSR & UART_LSR_THRE)); 
+	*UARTDR = c;
+}
+
+static void putstr(const char *s)
+{
+	while (*s)
+	{
+		putc(*s);
+		if (*s == '\n')
+			putc('\r');
+		s++;
+	}
+}
+
+#define arch_decomp_setup()
+#define arch_decomp_wdog()
diff -Nru a/include/asm-arm/arch-ixp2000/vmalloc.h b/include/asm-arm/arch-ixp2000/vmalloc.h
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/include/asm-arm/arch-ixp2000/vmalloc.h	2004-10-18 14:57:21 -07:00
@@ -0,0 +1,23 @@
+/*
+ * linux/include/asm-arm/arch-ixp2000/vmalloc.h
+ *
+ * Author: Naeem Afzal <naeem.m.afzal@intel.com>
+ *
+ * Copyright 2002 Intel Corp.
+ *
+ *  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.
+ *
+ * Just any arbitrary offset to the start of the vmalloc VM area: the
+ * current 8MB value just means that there will be a 8MB "hole" after the
+ * physical memory until the kernel virtual memory starts.  That means that
+ * any out-of-bounds memory accesses will hopefully be caught.
+ * The vmalloc() routines leaves a hole of 4kB between each vmalloced
+ * area for the same reason. ;)
+ */
+#define VMALLOC_OFFSET	    (8*1024*1024)
+#define VMALLOC_START	    (((unsigned long)high_memory + VMALLOC_OFFSET) & ~(VMALLOC_OFFSET-1))
+#define VMALLOC_VMADDR(x)   ((unsigned long)(x))
+#define VMALLOC_END	    0xfb000000
diff -Nru a/include/asm-arm/arch-ixp4xx/io.h b/include/asm-arm/arch-ixp4xx/io.h
--- a/include/asm-arm/arch-ixp4xx/io.h	2004-10-18 14:56:49 -07:00
+++ b/include/asm-arm/arch-ixp4xx/io.h	2004-10-18 14:56:49 -07:00
@@ -73,7 +73,7 @@
 {
 	extern void __iounmap(void *addr);
 
-	if ((u32)addr > VMALLOC_START)
+	if ((u32)addr >= VMALLOC_START)
 		__iounmap(addr);
 }
 
@@ -101,7 +101,7 @@
 {
 	u32 n, byte_enables, data;
 
-	if (addr > VMALLOC_START) {
+	if (addr >= VMALLOC_START) {
 		__raw_writeb(value, addr);
 		return;
 	}
@@ -124,7 +124,7 @@
 {
 	u32 n, byte_enables, data;
 
-	if (addr > VMALLOC_START) {
+	if (addr >= VMALLOC_START) {
 		__raw_writew(value, addr);
 		return;
 	}
@@ -145,7 +145,7 @@
 static inline void 
 __ixp4xx_writel(u32 value, u32 addr)
 {
-	if (addr > VMALLOC_START) {
+	if (addr >= VMALLOC_START) {
 		__raw_writel(value, addr);
 		return;
 	}
@@ -165,7 +165,7 @@
 {
 	u32 n, byte_enables, data;
 
-	if (addr > VMALLOC_START)
+	if (addr >= VMALLOC_START)
 		return __raw_readb(addr);
 
 	n = addr % 4;
@@ -188,7 +188,7 @@
 {
 	u32 n, byte_enables, data;
 
-	if (addr > VMALLOC_START)
+	if (addr >= VMALLOC_START)
 		return __raw_readw(addr);
 
 	n = addr % 4;
@@ -211,7 +211,7 @@
 {
 	u32 data;
 
-	if (addr > VMALLOC_START)
+	if (addr >= VMALLOC_START)
 		return __raw_readl(addr);
 
 	if (ixp4xx_pci_read(addr, NP_CMD_MEMREAD, &data))
diff -Nru a/include/asm-arm/arch-ixp4xx/uncompress.h b/include/asm-arm/arch-ixp4xx/uncompress.h
--- a/include/asm-arm/arch-ixp4xx/uncompress.h	2004-10-18 14:55:54 -07:00
+++ b/include/asm-arm/arch-ixp4xx/uncompress.h	2004-10-18 14:55:54 -07:00
@@ -32,7 +32,7 @@
 /*
  * This does not append a newline
  */
-static void puts(const char *s)
+static void putstr(const char *s)
 {
 	while (*s)
 	{
diff -Nru a/include/asm-arm/arch-l7200/param.h b/include/asm-arm/arch-l7200/param.h
--- a/include/asm-arm/arch-l7200/param.h	2004-10-18 14:56:29 -07:00
+++ b/include/asm-arm/arch-l7200/param.h	2004-10-18 14:56:29 -07:00
@@ -16,4 +16,4 @@
 /*
  * See 'time.h' for how the RTC HZ rate is set
  */
-#define __KERNEL_HZ 128
+#define HZ 128
diff -Nru a/include/asm-arm/arch-l7200/uncompress.h b/include/asm-arm/arch-l7200/uncompress.h
--- a/include/asm-arm/arch-l7200/uncompress.h	2004-10-18 14:57:04 -07:00
+++ b/include/asm-arm/arch-l7200/uncompress.h	2004-10-18 14:57:04 -07:00
@@ -23,7 +23,7 @@
 	__raw_writeb(c, IO_UART + 0x00);
 }
 
-static void puts(const char *s)
+static void putstr(const char *s)
 {
 	while (*s) {
 		if (*s == 10) {			/* If a LF, add CR */
diff -Nru a/include/asm-arm/arch-lh7a40x/uncompress.h b/include/asm-arm/arch-lh7a40x/uncompress.h
--- a/include/asm-arm/arch-lh7a40x/uncompress.h	2004-10-18 14:55:54 -07:00
+++ b/include/asm-arm/arch-lh7a40x/uncompress.h	2004-10-18 14:55:54 -07:00
@@ -29,7 +29,7 @@
 	UART_DATA = ch;
 }
 
-static void puts (const char* sz)
+static void putstr (const char* sz)
 {
 	for (; *sz; ++sz) {
 		putc (*sz);
diff -Nru a/include/asm-arm/arch-omap/board-h2.h b/include/asm-arm/arch-omap/board-h2.h
--- a/include/asm-arm/arch-omap/board-h2.h	2004-10-18 14:56:48 -07:00
+++ b/include/asm-arm/arch-omap/board-h2.h	2004-10-18 14:56:48 -07:00
@@ -31,5 +31,15 @@
 
 /* Placeholder for H2 specific defines */
 
+/* At OMAP1610 Innovator the Ethernet is directly connected to CS1 */
+#define OMAP1610_ETHR_BASE		0xE8000000
+#define OMAP1610_ETHR_SIZE		SZ_4K
+#define OMAP1610_ETHR_START		0x04000000
+
+/* Intel STRATA NOR flash at CS3 */
+#define OMAP1610_NOR_FLASH_BASE		0xD8000000
+#define OMAP1610_NOR_FLASH_SIZE		SZ_32M
+#define OMAP1610_NOR_FLASH_START	0x0C000000
+
 #endif /*  __ASM_ARCH_OMAP_H2_H */
 
diff -Nru a/include/asm-arm/arch-omap/board-h3.h b/include/asm-arm/arch-omap/board-h3.h
--- a/include/asm-arm/arch-omap/board-h3.h	2004-10-18 14:57:04 -07:00
+++ b/include/asm-arm/arch-omap/board-h3.h	2004-10-18 14:57:04 -07:00
@@ -1,9 +1,8 @@
 /*
  * linux/include/asm-arm/arch-omap/board-h3.h
  *
- * Hardware definitions for TI OMAP1610 H3 board.
- *
- * Initial creation by Dirk Behme <dirk.behme@de.bosch.com>
+ * Copyright (C) 2001 RidgeRun, Inc.
+ * Copyright (C) 2004 Texas Instruments, 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
@@ -25,11 +24,84 @@
  * with this program; if not, write  to the Free Software Foundation, Inc.,
  * 675 Mass Ave, Cambridge, MA 02139, USA.
  */
-
 #ifndef __ASM_ARCH_OMAP_H3_H
 #define __ASM_ARCH_OMAP_H3_H
 
-/* Placeholder for H3 specific defines */
+/* In OMAP1710 H3 the Ethernet is directly connected to CS1 */
+#define OMAP1710_ETHR_BASE		0xE8000000
+#define OMAP1710_ETHR_SIZE		SZ_4K
+#define OMAP1710_ETHR_START		0x04000000
 
-#endif /*  __ASM_ARCH_OMAP_H3_H */
+/* Intel STRATA NOR flash at CS3 */
+#define OMAP_NOR_FLASH_BASE		0xD8000000
+#define OMAP_NOR_FLASH_SIZE		SZ_32M
+#define OMAP_NOR_FLASH_START		0x00000000
+
+#define MAXIRQNUM			(IH_BOARD_BASE)
+#define MAXFIQNUM			MAXIRQNUM
+#define MAXSWINUM			MAXIRQNUM
 
+#define NR_IRQS				(MAXIRQNUM + 1)
+
+#define OMAP_MCBSP1_BASE		OMAP1610_MCBSP1_BASE
+#define AUDIO_DRR2  (OMAP_MCBSP1_BASE + 0x00)
+#define AUDIO_DRR1  (OMAP_MCBSP1_BASE + 0x02)
+#define AUDIO_DXR2  (OMAP_MCBSP1_BASE + 0x04)
+#define AUDIO_DXR1  (OMAP_MCBSP1_BASE + 0x06)
+#define AUDIO_SPCR2 (OMAP_MCBSP1_BASE + 0x08)
+#define AUDIO_SPCR1 (OMAP_MCBSP1_BASE + 0x0a)
+#define AUDIO_RCR2  (OMAP_MCBSP1_BASE + 0x0c)
+#define AUDIO_RCR1  (OMAP_MCBSP1_BASE + 0x0e)
+#define AUDIO_XCR2  (OMAP_MCBSP1_BASE + 0x10)
+#define AUDIO_XCR1  (OMAP_MCBSP1_BASE + 0x12)
+#define AUDIO_SRGR2 (OMAP_MCBSP1_BASE + 0x14)
+#define AUDIO_SRGR1 (OMAP_MCBSP1_BASE + 0x16)
+#define AUDIO_MCR2  (OMAP_MCBSP1_BASE + 0x18)
+#define AUDIO_MCR1  (OMAP_MCBSP1_BASE + 0x1a)
+#define AUDIO_RCERA (OMAP_MCBSP1_BASE + 0x1c)
+#define AUDIO_RCERB (OMAP_MCBSP1_BASE + 0x1e)
+#define AUDIO_XCERA (OMAP_MCBSP1_BASE + 0x20)
+#define AUDIO_XCERB (OMAP_MCBSP1_BASE + 0x22)
+#define AUDIO_PCR0  (OMAP_MCBSP1_BASE + 0x24)
+
+/* UART3 Registers Maping through MPU bus */
+#define OMAP_MPU_UART3_BASE     0xFFFB9800      /* UART3 through MPU bus */
+#define UART3_RHR               (OMAP_MPU_UART3_BASE + 0)
+#define UART3_THR               (OMAP_MPU_UART3_BASE + 0)
+#define UART3_DLL               (OMAP_MPU_UART3_BASE + 0)
+#define UART3_IER               (OMAP_MPU_UART3_BASE + 4)
+#define UART3_DLH               (OMAP_MPU_UART3_BASE + 4)
+#define UART3_IIR               (OMAP_MPU_UART3_BASE + 8)
+#define UART3_FCR               (OMAP_MPU_UART3_BASE + 8)
+#define UART3_EFR               (OMAP_MPU_UART3_BASE + 8)
+#define UART3_LCR               (OMAP_MPU_UART3_BASE + 0x0C)
+#define UART3_MCR               (OMAP_MPU_UART3_BASE + 0x10)
+#define UART3_XON1_ADDR1        (OMAP_MPU_UART3_BASE + 0x10)
+#define UART3_XON2_ADDR2        (OMAP_MPU_UART3_BASE + 0x14)
+#define UART3_LSR               (OMAP_MPU_UART3_BASE + 0x14)
+#define UART3_TCR               (OMAP_MPU_UART3_BASE + 0x18)
+#define UART3_MSR               (OMAP_MPU_UART3_BASE + 0x18)
+#define UART3_XOFF1             (OMAP_MPU_UART3_BASE + 0x18)
+#define UART3_XOFF2             (OMAP_MPU_UART3_BASE + 0x1C)
+#define UART3_SPR               (OMAP_MPU_UART3_BASE + 0x1C)
+#define UART3_TLR               (OMAP_MPU_UART3_BASE + 0x1C)
+#define UART3_MDR1              (OMAP_MPU_UART3_BASE + 0x20)
+#define UART3_MDR2              (OMAP_MPU_UART3_BASE + 0x24)
+#define UART3_SFLSR             (OMAP_MPU_UART3_BASE + 0x28)
+#define UART3_TXFLL             (OMAP_MPU_UART3_BASE + 0x28)
+#define UART3_RESUME            (OMAP_MPU_UART3_BASE + 0x2C)
+#define UART3_TXFLH             (OMAP_MPU_UART3_BASE + 0x2C)
+#define UART3_SFREGL            (OMAP_MPU_UART3_BASE + 0x30)
+#define UART3_RXFLL             (OMAP_MPU_UART3_BASE + 0x30)
+#define UART3_SFREGH            (OMAP_MPU_UART3_BASE + 0x34)
+#define UART3_RXFLH             (OMAP_MPU_UART3_BASE + 0x34)
+#define UART3_BLR               (OMAP_MPU_UART3_BASE + 0x38)
+#define UART3_ACREG             (OMAP_MPU_UART3_BASE + 0x3C)
+#define UART3_DIV16             (OMAP_MPU_UART3_BASE + 0x3C)
+#define UART3_SCR               (OMAP_MPU_UART3_BASE + 0x40)
+#define UART3_SSR               (OMAP_MPU_UART3_BASE + 0x44)
+#define UART3_EBLR              (OMAP_MPU_UART3_BASE + 0x48)
+#define UART3_OSC_12M_SEL       (OMAP_MPU_UART3_BASE + 0x4C)
+#define UART3_MVR               (OMAP_MPU_UART3_BASE + 0x50)
+
+#endif /*  __ASM_ARCH_OMAP_H3_H */
diff -Nru a/include/asm-arm/arch-omap/board-innovator.h b/include/asm-arm/arch-omap/board-innovator.h
--- a/include/asm-arm/arch-omap/board-innovator.h	2004-10-18 14:57:18 -07:00
+++ b/include/asm-arm/arch-omap/board-innovator.h	2004-10-18 14:57:18 -07:00
@@ -28,92 +28,6 @@
 
 #if defined (CONFIG_ARCH_OMAP1510)
 
-/*
- * ---------------------------------------------------------------------------
- *  OMAP-1510 FPGA
- * ---------------------------------------------------------------------------
- */
-#define OMAP1510_FPGA_BASE			0xE8000000	/* Virtual */
-#define OMAP1510_FPGA_SIZE			SZ_4K
-#define OMAP1510_FPGA_START			0x08000000	/* Physical */
-
-/* Revision */
-#define OMAP1510_FPGA_REV_LOW			(OMAP1510_FPGA_BASE + 0x0)
-#define OMAP1510_FPGA_REV_HIGH			(OMAP1510_FPGA_BASE + 0x1)
-
-#define OMAP1510_FPGA_LCD_PANEL_CONTROL		(OMAP1510_FPGA_BASE + 0x2)
-#define OMAP1510_FPGA_LED_DIGIT			(OMAP1510_FPGA_BASE + 0x3)
-#define INNOVATOR_FPGA_HID_SPI			(OMAP1510_FPGA_BASE + 0x4)
-#define OMAP1510_FPGA_POWER			(OMAP1510_FPGA_BASE + 0x5)
-
-/* Interrupt status */
-#define OMAP1510_FPGA_ISR_LO			(OMAP1510_FPGA_BASE + 0x6)
-#define OMAP1510_FPGA_ISR_HI			(OMAP1510_FPGA_BASE + 0x7)
-
-/* Interrupt mask */
-#define OMAP1510_FPGA_IMR_LO			(OMAP1510_FPGA_BASE + 0x8)
-#define OMAP1510_FPGA_IMR_HI			(OMAP1510_FPGA_BASE + 0x9)
-
-/* Reset registers */
-#define OMAP1510_FPGA_HOST_RESET		(OMAP1510_FPGA_BASE + 0xa)
-#define OMAP1510_FPGA_RST			(OMAP1510_FPGA_BASE + 0xb)
-
-#define OMAP1510_FPGA_AUDIO			(OMAP1510_FPGA_BASE + 0xc)
-#define OMAP1510_FPGA_DIP			(OMAP1510_FPGA_BASE + 0xe)
-#define OMAP1510_FPGA_FPGA_IO			(OMAP1510_FPGA_BASE + 0xf)
-#define OMAP1510_FPGA_UART1			(OMAP1510_FPGA_BASE + 0x14)
-#define OMAP1510_FPGA_UART2			(OMAP1510_FPGA_BASE + 0x15)
-#define OMAP1510_FPGA_OMAP1510_STATUS		(OMAP1510_FPGA_BASE + 0x16)
-#define OMAP1510_FPGA_BOARD_REV			(OMAP1510_FPGA_BASE + 0x18)
-#define OMAP1510P1_PPT_DATA			(OMAP1510_FPGA_BASE + 0x100)
-#define OMAP1510P1_PPT_STATUS			(OMAP1510_FPGA_BASE + 0x101)
-#define OMAP1510P1_PPT_CONTROL			(OMAP1510_FPGA_BASE + 0x102)
-
-#define OMAP1510_FPGA_TOUCHSCREEN		(OMAP1510_FPGA_BASE + 0x204)
-
-#define INNOVATOR_FPGA_INFO			(OMAP1510_FPGA_BASE + 0x205)
-#define INNOVATOR_FPGA_LCD_BRIGHT_LO		(OMAP1510_FPGA_BASE + 0x206)
-#define INNOVATOR_FPGA_LCD_BRIGHT_HI		(OMAP1510_FPGA_BASE + 0x207)
-#define INNOVATOR_FPGA_LED_GRN_LO		(OMAP1510_FPGA_BASE + 0x208)
-#define INNOVATOR_FPGA_LED_GRN_HI		(OMAP1510_FPGA_BASE + 0x209)
-#define INNOVATOR_FPGA_LED_RED_LO		(OMAP1510_FPGA_BASE + 0x20a)
-#define INNOVATOR_FPGA_LED_RED_HI		(OMAP1510_FPGA_BASE + 0x20b)
-#define INNOVATOR_FPGA_CAM_USB_CONTROL		(OMAP1510_FPGA_BASE + 0x20c)
-#define INNOVATOR_FPGA_EXP_CONTROL		(OMAP1510_FPGA_BASE + 0x20d)
-#define INNOVATOR_FPGA_ISR2			(OMAP1510_FPGA_BASE + 0x20e)
-#define INNOVATOR_FPGA_IMR2			(OMAP1510_FPGA_BASE + 0x210)
-
-#define OMAP1510_FPGA_ETHR_START		(OMAP1510_FPGA_START + 0x300)
-#define OMAP1510_FPGA_ETHR_BASE			(OMAP1510_FPGA_BASE + 0x300)
-
-/*
- * Power up Giga UART driver, turn on HID clock.
- * Turn off BT power, since we're not using it and it
- * draws power.
- */
-#define OMAP1510_FPGA_RESET_VALUE		0x42
-
-#define OMAP1510_FPGA_PCR_IF_PD0		(1 << 7)
-#define OMAP1510_FPGA_PCR_COM2_EN		(1 << 6)
-#define OMAP1510_FPGA_PCR_COM1_EN		(1 << 5)
-#define OMAP1510_FPGA_PCR_EXP_PD0		(1 << 4)
-#define OMAP1510_FPGA_PCR_EXP_PD1		(1 << 3)
-#define OMAP1510_FPGA_PCR_48MHZ_CLK		(1 << 2)
-#define OMAP1510_FPGA_PCR_4MHZ_CLK		(1 << 1)
-#define OMAP1510_FPGA_PCR_RSRVD_BIT0		(1 << 0)
-
-/*
- * Innovator/OMAP1510 FPGA HID register bit definitions
- */
-#define FPGA_HID_SCLK	(1<<0)	/* output */
-#define FPGA_HID_MOSI	(1<<1)	/* output */
-#define FPGA_HID_nSS	(1<<2)	/* output 0/1 chip idle/select */
-#define FPGA_HID_nHSUS	(1<<3)	/* output 0/1 host active/suspended */
-#define FPGA_HID_MISO	(1<<4)	/* input */
-#define FPGA_HID_ATN	(1<<5)	/* input  0/1 chip idle/ATN */
-#define FPGA_HID_rsrvd	(1<<6)
-#define FPGA_HID_RESETn (1<<7)	/* output - 0/1 USAR reset/run */
-
 #ifndef OMAP_SDRAM_DEVICE
 #define OMAP_SDRAM_DEVICE			D256M_1X16_4B
 #endif
@@ -147,37 +61,8 @@
 #define OMAP_FLASH_1_START	0x01000000
 #define OMAP_FLASH_1_SIZE	SZ_16M
 
-/* The FPGA IRQ is cascaded through GPIO_13 */
-#define INT_FPGA		(IH_GPIO_BASE + 13)
-
-/* IRQ Numbers for interrupts muxed through the FPGA */
-#define IH_FPGA_BASE		IH_BOARD_BASE
-#define INT_FPGA_ATN		(IH_FPGA_BASE + 0)
-#define INT_FPGA_ACK		(IH_FPGA_BASE + 1)
-#define INT_FPGA2		(IH_FPGA_BASE + 2)
-#define INT_FPGA3		(IH_FPGA_BASE + 3)
-#define INT_FPGA4		(IH_FPGA_BASE + 4)
-#define INT_FPGA5		(IH_FPGA_BASE + 5)
-#define INT_FPGA6		(IH_FPGA_BASE + 6)
-#define INT_FPGA7		(IH_FPGA_BASE + 7)
-#define INT_FPGA8		(IH_FPGA_BASE + 8)
-#define INT_FPGA9		(IH_FPGA_BASE + 9)
-#define INT_FPGA10		(IH_FPGA_BASE + 10)
-#define INT_FPGA11		(IH_FPGA_BASE + 11)
-#define INT_FPGA12		(IH_FPGA_BASE + 12)
-#define INT_ETHER		(IH_FPGA_BASE + 13)
-#define INT_FPGAUART1		(IH_FPGA_BASE + 14)
-#define INT_FPGAUART2		(IH_FPGA_BASE + 15)
-#define INT_FPGA_TS		(IH_FPGA_BASE + 16)
-#define INT_FPGA17		(IH_FPGA_BASE + 17)
-#define INT_FPGA_CAM		(IH_FPGA_BASE + 18)
-#define INT_FPGA_RTC_A		(IH_FPGA_BASE + 19)
-#define INT_FPGA_RTC_B		(IH_FPGA_BASE + 20)
-#define INT_FPGA_CD		(IH_FPGA_BASE + 21)
-#define INT_FPGA22		(IH_FPGA_BASE + 22)
-#define INT_FPGA23		(IH_FPGA_BASE + 23)
-
-#define NR_FPGA_IRQS		 24
+#define NR_FPGA_IRQS		24
+#define NR_IRQS                 IH_BOARD_BASE + NR_FPGA_IRQS
 
 #ifndef __ASSEMBLY__
 void fpga_write(unsigned char val, int reg);
diff -Nru a/include/asm-arm/arch-omap/board-perseus2.h b/include/asm-arm/arch-omap/board-perseus2.h
--- a/include/asm-arm/arch-omap/board-perseus2.h	2004-10-18 14:56:49 -07:00
+++ b/include/asm-arm/arch-omap/board-perseus2.h	2004-10-18 14:56:49 -07:00
@@ -2,8 +2,7 @@
  *  linux/include/asm-arm/arch-omap/board-perseus2.h
  *
  *  Copyright 2003 by Texas Instruments Incorporated
- *    OMAP730 / P2-sample additions
- *    Author: Jean Pihet
+ *    OMAP730 / Perseus2 support by Jean Pihet
  *
  * Copyright (C) 2001 RidgeRun, Inc. (http://www.ridgerun.com)
  * Author: RidgeRun, Inc.
@@ -28,46 +27,10 @@
  * with this program; if not, write to the Free Software Foundation, Inc.,
  * 675 Mass Ave, Cambridge, MA 02139, USA.
  */
-#ifndef __ASM_ARCH_OMAP_P2SAMPLE_H
-#define __ASM_ARCH_OMAP_P2SAMPLE_H
+#ifndef __ASM_ARCH_OMAP_PERSEUS2_H
+#define __ASM_ARCH_OMAP_PERSEUS2_H
 
-#if defined(CONFIG_ARCH_OMAP730) && defined (CONFIG_MACH_OMAP_PERSEUS2)
-
-/*
- * NOTE:  ALL DEFINITIONS IN THIS FILE NEED TO BE PREFIXED BY IDENTIFIER
- *	  P2SAMPLE_ since they are specific to the EVM and not the chip.
- */
-
-/* ---------------------------------------------------------------------------
- *  OMAP730 Debug Board FPGA
- * ---------------------------------------------------------------------------
- */
-
-/* maps in the FPGA registers and the ETHR registers */
-#define OMAP730_FPGA_BASE		0xE8000000	/* VA */
-#define OMAP730_FPGA_SIZE		SZ_4K		/* SIZE */
-#define OMAP730_FPGA_START		0x04000000	/* PA */
-
-#define OMAP730_FPGA_ETHR_START		OMAP730_FPGA_START
-#define OMAP730_FPGA_ETHR_BASE		OMAP730_FPGA_BASE
-#define OMAP730_FPGA_FPGA_REV		(OMAP730_FPGA_BASE + 0x10)	/* FPGA Revision */
-#define OMAP730_FPGA_BOARD_REV		(OMAP730_FPGA_BASE + 0x12)	/* Board Revision */
-#define OMAP730_FPGA_GPIO		(OMAP730_FPGA_BASE + 0x14)	/* GPIO outputs */
-#define OMAP730_FPGA_LEDS		(OMAP730_FPGA_BASE + 0x16)	/* LEDs outputs */
-#define OMAP730_FPGA_MISC_INPUTS	(OMAP730_FPGA_BASE + 0x18)	/* Misc inputs */
-#define OMAP730_FPGA_LAN_STATUS		(OMAP730_FPGA_BASE + 0x1A)	/* LAN Status line */
-#define OMAP730_FPGA_LAN_RESET		(OMAP730_FPGA_BASE + 0x1C)	/* LAN Reset line */
-
-// LEDs definition on debug board (16 LEDs)
-#define OMAP730_FPGA_LED_CLAIMRELEASE	(1 << 15)
-#define OMAP730_FPGA_LED_STARTSTOP	(1 << 14)
-#define OMAP730_FPGA_LED_HALTED		(1 << 13)
-#define OMAP730_FPGA_LED_IDLE		(1 << 12)
-#define OMAP730_FPGA_LED_TIMER		(1 << 11)
-// cpu0 load-meter LEDs
-#define OMAP730_FPGA_LOAD_METER		(1 << 0)	// A bit of fun on our board ...
-#define OMAP730_FPGA_LOAD_METER_SIZE	11
-#define OMAP730_FPGA_LOAD_METER_MASK	((1 << OMAP730_FPGA_LOAD_METER_SIZE) - 1)
+#include <asm/arch/fpga.h>
 
 #ifndef OMAP_SDRAM_DEVICE
 #define OMAP_SDRAM_DEVICE		D256M_1X16_4B
@@ -86,22 +49,10 @@
 #define OMAP_FLASH_0_START	0x00000000	/* PA */
 #define OMAP_FLASH_0_SIZE	SZ_32M
 
-/* The Ethernet Controller IRQ is cascaded to MPU_EXT_nIRQ througb the FPGA */
-#define INT_ETHER		INT_730_MPU_EXT_NIRQ
-
 #define MAXIRQNUM		IH_BOARD_BASE
 #define MAXFIQNUM		MAXIRQNUM
 #define MAXSWINUM		MAXIRQNUM
 
 #define NR_IRQS			(MAXIRQNUM + 1)
-
-#ifndef __ASSEMBLY__
-void fpga_write(unsigned char val, int reg);
-unsigned char fpga_read(int reg);
-#endif
-
-#else
-#error "Only OMAP730 Perseus2 supported!"
-#endif
 
 #endif
diff -Nru a/include/asm-arm/arch-omap/board.h b/include/asm-arm/arch-omap/board.h
--- a/include/asm-arm/arch-omap/board.h	2004-10-18 14:56:32 -07:00
+++ b/include/asm-arm/arch-omap/board.h	2004-10-18 14:56:32 -07:00
@@ -17,32 +17,69 @@
 #define OMAP_TAG_CLOCK		0x4f01
 #define OMAP_TAG_MMC		0x4f02
 #define OMAP_TAG_UART		0x4f03
+#define OMAP_TAG_USB            0x4f04
 
-struct omap_clock_info {
+struct omap_clock_config {
 	/* 0 for 12 MHz, 1 for 13 MHz and 2 for 19.2 MHz */
 	u8 system_clock_type;
 };
 
-struct omap_mmc_info {
+struct omap_mmc_config {
 	u8 mmc_blocks;
 	s8 mmc1_power_pin, mmc2_power_pin;
 	s8 mmc1_switch_pin, mmc2_switch_pin;
 };
 
-struct omap_uart_info {
+struct omap_uart_config {
 	u8 console_uart;
 	u32 console_speed;
 };
 
-struct omap_board_info_entry {
+struct omap_usb_config {
+	/* Configure drivers according to the connectors on your board:
+	 *  - "A" connector (rectagular)
+	 *	... for host/OHCI use, set "register_host".
+	 *  - "B" connector (squarish) or "Mini-B"
+	 *	... for device/gadget use, set "register_dev".
+	 *  - "Mini-AB" connector (very similar to Mini-B)
+	 *	... for OTG use as device OR host, initialize "otg"
+	 */
+	unsigned	register_host:1;
+	unsigned	register_dev:1;
+	u8		otg;	/* port number, 1-based:  usb1 == 2 */
+
+	u8		hmc_mode;
+
+	/* implicitly true if otg:  host supports remote wakeup? */
+	u8		rwc;
+
+	/* signaling pins used to talk to transceiver on usbN:
+	 *  0 == usbN unused
+	 *  2 == usb0-only, using internal transceiver
+	 *  3 == 3 wire bidirectional
+	 *  4 == 4 wire bidirectional
+	 *  6 == 6 wire unidirectional (or TLL)
+	 */
+	u8		pins[3];
+};
+
+struct omap_board_config_entry {
 	u16 tag;
 	u16 len;
 	u8  data[0];
 };
 
-extern const void *__omap_get_per_info(u16 tag, size_t len);
+struct omap_board_config_kernel {
+	u16 tag;
+	const void *data;
+};
+
+extern const void *__omap_get_config(u16 tag, size_t len);
+
+#define omap_get_config(tag, type) \
+	((const type *) __omap_get_config((tag), sizeof(type)))
 
-#define omap_get_per_info(tag, type) \
-	((const type *) __omap_get_per_info((tag), sizeof(type)))
+extern struct omap_board_config_kernel *omap_board_config;
+extern int omap_board_config_size;
 
 #endif
diff -Nru a/include/asm-arm/arch-omap/bus.h b/include/asm-arm/arch-omap/bus.h
--- a/include/asm-arm/arch-omap/bus.h	2004-10-18 14:56:49 -07:00
+++ /dev/null	Wed Dec 31 16:00:00 196900
@@ -1,102 +0,0 @@
-/*
- * linux/include/asm-arm/arch-omap/bus.h
- *
- * Virtual bus for OMAP. Allows better power management, such as managing
- * shared clocks, and mapping of bus addresses to Local Bus addresses.
- *
- * See drivers/usb/host/ohci-omap.c or drivers/video/omap/omapfb.c for
- * examples on how to register drivers to this bus.
- *
- * Copyright (C) 2003 - 2004 Nokia Corporation
- * Written by Tony Lindgren <tony@atomide.com>
- * Portions of code based on sa1111.c.
- *
- * 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
- */
-
-#ifndef __ASM_ARM_ARCH_OMAP_BUS_H
-#define __ASM_ARM_ARCH_OMAP_BUS_H
-
-extern struct bus_type omap_bus_types[];
-
-/*
- * Description for physical device
- */
-struct omap_dev {
-	struct device	dev;		/* Standard device description */
-	char		*name;
-	unsigned int	devid;		/* OMAP device id */
-	unsigned int	busid;		/* OMAP virtual busid */
-	struct resource res;		/* Standard resource description */
-	void		*mapbase;	/* OMAP physical address */
-	unsigned int	irq[6];		/* OMAP interrupts */
-	u64		*dma_mask;	/* Used by USB OHCI only */
-	u64		coherent_dma_mask;	/* Used by USB OHCI only */
-};
-
-#define OMAP_DEV(_d)	container_of((_d), struct omap_dev, dev)
-
-#define omap_get_drvdata(d)	dev_get_drvdata(&(d)->dev)
-#define omap_set_drvdata(d,p)	dev_set_drvdata(&(d)->dev, p)
-
-/*
- * Description for device driver
- */
-struct omap_driver {
-	struct device_driver	drv;	/* Standard driver description */
-	unsigned int		devid;	/* OMAP device id for bus */
-	unsigned int		busid;	/* OMAP virtual busid */
-	unsigned int		clocks; /* OMAP shared clocks */
-	int (*probe)(struct omap_dev *);
-	int (*remove)(struct omap_dev *);
-	int (*suspend)(struct omap_dev *, u32);
-	int (*resume)(struct omap_dev *);
-};
-
-#define OMAP_DRV(_d)	container_of((_d), struct omap_driver, drv)
-#define OMAP_DRIVER_NAME(_omapdev) ((_omapdev)->dev.driver->name)
-
-/*
- * Device ID numbers for bus types
- */
-#define OMAP_OCP_DEVID_USB	0
-
-#define OMAP_TIPB_DEVID_OHCI	0
-#define OMAP_TIPB_DEVID_LCD	1
-#define OMAP_TIPB_DEVID_MMC	2
-#define OMAP_TIPB_DEVID_OTG	3
-#define OMAP_TIPB_DEVID_UDC	4
-
-/*
- * Virtual bus definitions for OMAP
- */
-#define OMAP_NR_BUSES	2
-
-#define OMAP_BUS_NAME_TIPB	"tipb"
-#define OMAP_BUS_NAME_LBUS	"lbus"
-
-enum {
-	OMAP_BUS_TIPB = 0,
-	OMAP_BUS_LBUS,
-};
-
-/* See arch/arm/mach-omap/bus.c for the rest of the bus definitions. */
-
-extern int omap_driver_register(struct omap_driver *driver);
-extern void omap_driver_unregister(struct omap_driver *driver);
-extern int omap_device_register(struct omap_dev *odev);
-extern void omap_device_unregister(struct omap_dev *odev);
-
-#endif
diff -Nru a/include/asm-arm/arch-omap/fpga.h b/include/asm-arm/arch-omap/fpga.h
--- a/include/asm-arm/arch-omap/fpga.h	2004-10-18 14:56:19 -07:00
+++ b/include/asm-arm/arch-omap/fpga.h	2004-10-18 14:56:19 -07:00
@@ -19,8 +19,161 @@
 #ifndef __ASM_ARCH_OMAP_FPGA_H
 #define __ASM_ARCH_OMAP_FPGA_H
 
-extern void fpga_init_irq(void);
-extern unsigned char fpga_read(int reg);
-extern void fpga_write(unsigned char val, int reg);
+#if defined(CONFIG_MACH_OMAP_INNOVATOR) && defined(CONFIG_ARCH_OMAP1510)
+extern void omap1510_fpga_init_irq(void);
+#else
+#define omap1510_fpga_init_irq()	(0)
+#endif
+
+#define fpga_read(reg)			__raw_readb(reg)
+#define fpga_write(val, reg)		__raw_writeb(val, reg)
+
+/*
+ * ---------------------------------------------------------------------------
+ *  H2/P2 Debug board FPGA
+ * ---------------------------------------------------------------------------
+ */
+/* maps in the FPGA registers and the ETHR registers */
+#define H2P2_DBG_FPGA_BASE		0xE8000000	/* VA */
+#define H2P2_DBG_FPGA_SIZE		SZ_4K		/* SIZE */
+#define H2P2_DBG_FPGA_START		0x04000000	/* PA */
+
+#define H2P2_DBG_FPGA_ETHR_START	H2P2_DBG_FPGA_START
+#define H2P2_DBG_FPGA_ETHR_BASE		H2P2_DBG_FPGA_BASE
+#define H2P2_DBG_FPGA_FPGA_REV		(H2P2_DBG_FPGA_BASE + 0x10)	/* FPGA Revision */
+#define H2P2_DBG_FPGA_BOARD_REV		(H2P2_DBG_FPGA_BASE + 0x12)	/* Board Revision */
+#define H2P2_DBG_FPGA_GPIO		(H2P2_DBG_FPGA_BASE + 0x14)	/* GPIO outputs */
+#define H2P2_DBG_FPGA_LEDS		(H2P2_DBG_FPGA_BASE + 0x16)	/* LEDs outputs */
+#define H2P2_DBG_FPGA_MISC_INPUTS	(H2P2_DBG_FPGA_BASE + 0x18)	/* Misc inputs */
+#define H2P2_DBG_FPGA_LAN_STATUS	(H2P2_DBG_FPGA_BASE + 0x1A)	/* LAN Status line */
+#define H2P2_DBG_FPGA_LAN_RESET		(H2P2_DBG_FPGA_BASE + 0x1C)	/* LAN Reset line */
+
+/* LEDs definition on debug board (16 LEDs) */
+#define H2P2_DBG_FPGA_LED_CLAIMRELEASE	(1 << 15)
+#define H2P2_DBG_FPGA_LED_STARTSTOP	(1 << 14)
+#define H2P2_DBG_FPGA_LED_HALTED	(1 << 13)
+#define H2P2_DBG_FPGA_LED_IDLE		(1 << 12)
+#define H2P2_DBG_FPGA_LED_TIMER		(1 << 11)
+/*  cpu0 load-meter LEDs */
+#define H2P2_DBG_FPGA_LOAD_METER	(1 << 0)	// A bit of fun on our board ...
+#define H2P2_DBG_FPGA_LOAD_METER_SIZE	11
+#define H2P2_DBG_FPGA_LOAD_METER_MASK	((1 << H2P2_DBG_FPGA_LOAD_METER_SIZE) - 1)
+
+
+/*
+ * ---------------------------------------------------------------------------
+ *  OMAP-1510 FPGA
+ * ---------------------------------------------------------------------------
+ */
+#define OMAP1510_FPGA_BASE			0xE8000000	/* Virtual */
+#define OMAP1510_FPGA_SIZE			SZ_4K
+#define OMAP1510_FPGA_START			0x08000000	/* Physical */
+
+/* Revision */
+#define OMAP1510_FPGA_REV_LOW			(OMAP1510_FPGA_BASE + 0x0)
+#define OMAP1510_FPGA_REV_HIGH			(OMAP1510_FPGA_BASE + 0x1)
+
+#define OMAP1510_FPGA_LCD_PANEL_CONTROL		(OMAP1510_FPGA_BASE + 0x2)
+#define OMAP1510_FPGA_LED_DIGIT			(OMAP1510_FPGA_BASE + 0x3)
+#define INNOVATOR_FPGA_HID_SPI			(OMAP1510_FPGA_BASE + 0x4)
+#define OMAP1510_FPGA_POWER			(OMAP1510_FPGA_BASE + 0x5)
+
+/* Interrupt status */
+#define OMAP1510_FPGA_ISR_LO			(OMAP1510_FPGA_BASE + 0x6)
+#define OMAP1510_FPGA_ISR_HI			(OMAP1510_FPGA_BASE + 0x7)
+
+/* Interrupt mask */
+#define OMAP1510_FPGA_IMR_LO			(OMAP1510_FPGA_BASE + 0x8)
+#define OMAP1510_FPGA_IMR_HI			(OMAP1510_FPGA_BASE + 0x9)
+
+/* Reset registers */
+#define OMAP1510_FPGA_HOST_RESET		(OMAP1510_FPGA_BASE + 0xa)
+#define OMAP1510_FPGA_RST			(OMAP1510_FPGA_BASE + 0xb)
+
+#define OMAP1510_FPGA_AUDIO			(OMAP1510_FPGA_BASE + 0xc)
+#define OMAP1510_FPGA_DIP			(OMAP1510_FPGA_BASE + 0xe)
+#define OMAP1510_FPGA_FPGA_IO			(OMAP1510_FPGA_BASE + 0xf)
+#define OMAP1510_FPGA_UART1			(OMAP1510_FPGA_BASE + 0x14)
+#define OMAP1510_FPGA_UART2			(OMAP1510_FPGA_BASE + 0x15)
+#define OMAP1510_FPGA_OMAP1510_STATUS		(OMAP1510_FPGA_BASE + 0x16)
+#define OMAP1510_FPGA_BOARD_REV			(OMAP1510_FPGA_BASE + 0x18)
+#define OMAP1510P1_PPT_DATA			(OMAP1510_FPGA_BASE + 0x100)
+#define OMAP1510P1_PPT_STATUS			(OMAP1510_FPGA_BASE + 0x101)
+#define OMAP1510P1_PPT_CONTROL			(OMAP1510_FPGA_BASE + 0x102)
+
+#define OMAP1510_FPGA_TOUCHSCREEN		(OMAP1510_FPGA_BASE + 0x204)
+
+#define INNOVATOR_FPGA_INFO			(OMAP1510_FPGA_BASE + 0x205)
+#define INNOVATOR_FPGA_LCD_BRIGHT_LO		(OMAP1510_FPGA_BASE + 0x206)
+#define INNOVATOR_FPGA_LCD_BRIGHT_HI		(OMAP1510_FPGA_BASE + 0x207)
+#define INNOVATOR_FPGA_LED_GRN_LO		(OMAP1510_FPGA_BASE + 0x208)
+#define INNOVATOR_FPGA_LED_GRN_HI		(OMAP1510_FPGA_BASE + 0x209)
+#define INNOVATOR_FPGA_LED_RED_LO		(OMAP1510_FPGA_BASE + 0x20a)
+#define INNOVATOR_FPGA_LED_RED_HI		(OMAP1510_FPGA_BASE + 0x20b)
+#define INNOVATOR_FPGA_CAM_USB_CONTROL		(OMAP1510_FPGA_BASE + 0x20c)
+#define INNOVATOR_FPGA_EXP_CONTROL		(OMAP1510_FPGA_BASE + 0x20d)
+#define INNOVATOR_FPGA_ISR2			(OMAP1510_FPGA_BASE + 0x20e)
+#define INNOVATOR_FPGA_IMR2			(OMAP1510_FPGA_BASE + 0x210)
+
+#define OMAP1510_FPGA_ETHR_START		(OMAP1510_FPGA_START + 0x300)
+#define OMAP1510_FPGA_ETHR_BASE			(OMAP1510_FPGA_BASE + 0x300)
+
+/*
+ * Power up Giga UART driver, turn on HID clock.
+ * Turn off BT power, since we're not using it and it
+ * draws power.
+ */
+#define OMAP1510_FPGA_RESET_VALUE		0x42
+
+#define OMAP1510_FPGA_PCR_IF_PD0		(1 << 7)
+#define OMAP1510_FPGA_PCR_COM2_EN		(1 << 6)
+#define OMAP1510_FPGA_PCR_COM1_EN		(1 << 5)
+#define OMAP1510_FPGA_PCR_EXP_PD0		(1 << 4)
+#define OMAP1510_FPGA_PCR_EXP_PD1		(1 << 3)
+#define OMAP1510_FPGA_PCR_48MHZ_CLK		(1 << 2)
+#define OMAP1510_FPGA_PCR_4MHZ_CLK		(1 << 1)
+#define OMAP1510_FPGA_PCR_RSRVD_BIT0		(1 << 0)
+
+/*
+ * Innovator/OMAP1510 FPGA HID register bit definitions
+ */
+#define OMAP1510_FPGA_HID_SCLK	(1<<0)	/* output */
+#define OMAP1510_FPGA_HID_MOSI	(1<<1)	/* output */
+#define OMAP1510_FPGA_HID_nSS	(1<<2)	/* output 0/1 chip idle/select */
+#define OMAP1510_FPGA_HID_nHSUS	(1<<3)	/* output 0/1 host active/suspended */
+#define OMAP1510_FPGA_HID_MISO	(1<<4)	/* input */
+#define OMAP1510_FPGA_HID_ATN	(1<<5)	/* input  0/1 chip idle/ATN */
+#define OMAP1510_FPGA_HID_rsrvd	(1<<6)
+#define OMAP1510_FPGA_HID_RESETn (1<<7)	/* output - 0/1 USAR reset/run */
+
+/* The FPGA IRQ is cascaded through GPIO_13 */
+#define OMAP1510_INT_FPGA		(IH_GPIO_BASE + 13)
+
+/* IRQ Numbers for interrupts muxed through the FPGA */
+#define OMAP1510_IH_FPGA_BASE		IH_BOARD_BASE
+#define OMAP1510_INT_FPGA_ATN		(OMAP1510_IH_FPGA_BASE + 0)
+#define OMAP1510_INT_FPGA_ACK		(OMAP1510_IH_FPGA_BASE + 1)
+#define OMAP1510_INT_FPGA2		(OMAP1510_IH_FPGA_BASE + 2)
+#define OMAP1510_INT_FPGA3		(OMAP1510_IH_FPGA_BASE + 3)
+#define OMAP1510_INT_FPGA4		(OMAP1510_IH_FPGA_BASE + 4)
+#define OMAP1510_INT_FPGA5		(OMAP1510_IH_FPGA_BASE + 5)
+#define OMAP1510_INT_FPGA6		(OMAP1510_IH_FPGA_BASE + 6)
+#define OMAP1510_INT_FPGA7		(OMAP1510_IH_FPGA_BASE + 7)
+#define OMAP1510_INT_FPGA8		(OMAP1510_IH_FPGA_BASE + 8)
+#define OMAP1510_INT_FPGA9		(OMAP1510_IH_FPGA_BASE + 9)
+#define OMAP1510_INT_FPGA10		(OMAP1510_IH_FPGA_BASE + 10)
+#define OMAP1510_INT_FPGA11		(OMAP1510_IH_FPGA_BASE + 11)
+#define OMAP1510_INT_FPGA12		(OMAP1510_IH_FPGA_BASE + 12)
+#define OMAP1510_INT_ETHER		(OMAP1510_IH_FPGA_BASE + 13)
+#define OMAP1510_INT_FPGAUART1		(OMAP1510_IH_FPGA_BASE + 14)
+#define OMAP1510_INT_FPGAUART2		(OMAP1510_IH_FPGA_BASE + 15)
+#define OMAP1510_INT_FPGA_TS		(OMAP1510_IH_FPGA_BASE + 16)
+#define OMAP1510_INT_FPGA17		(OMAP1510_IH_FPGA_BASE + 17)
+#define OMAP1510_INT_FPGA_CAM		(OMAP1510_IH_FPGA_BASE + 18)
+#define OMAP1510_INT_FPGA_RTC_A		(OMAP1510_IH_FPGA_BASE + 19)
+#define OMAP1510_INT_FPGA_RTC_B		(OMAP1510_IH_FPGA_BASE + 20)
+#define OMAP1510_INT_FPGA_CD		(OMAP1510_IH_FPGA_BASE + 21)
+#define OMAP1510_INT_FPGA22		(OMAP1510_IH_FPGA_BASE + 22)
+#define OMAP1510_INT_FPGA23		(OMAP1510_IH_FPGA_BASE + 23)
 
 #endif
diff -Nru a/include/asm-arm/arch-omap/hardware.h b/include/asm-arm/arch-omap/hardware.h
--- a/include/asm-arm/arch-omap/hardware.h	2004-10-18 14:55:55 -07:00
+++ b/include/asm-arm/arch-omap/hardware.h	2004-10-18 14:55:55 -07:00
@@ -178,6 +178,7 @@
 #define IRQ_CONTROL_REG_OFFSET	0x18
 #define IRQ_ISR_REG_OFFSET	0x9c
 #define IRQ_ILR0_REG_OFFSET	0x1c
+#define IRQ_GMR_REG_OFFSET	0xa0
 
 /*
  * ---------------------------------------------------------------------------
@@ -185,22 +186,23 @@
  * ---------------------------------------------------------------------------
  */
 #define TCMIF_BASE		0xfffecc00
-#define IMIF_PRIO		(TCMIF_BASE + 0x00)
-#define EMIFS_PRIO		(TCMIF_BASE + 0x04)
-#define EMIFF_PRIO		(TCMIF_BASE + 0x08)
-#define EMIFS_CONFIG		(TCMIF_BASE + 0x0c)
-#define EMIFS_CS0_CONFIG	(TCMIF_BASE + 0x10)
-#define EMIFS_CS1_CONFIG	(TCMIF_BASE + 0x14)
-#define EMIFS_CS2_CONFIG	(TCMIF_BASE + 0x18)
-#define EMIFS_CS3_CONFIG	(TCMIF_BASE + 0x1c)
-#define EMIFF_SDRAM_CONFIG	(TCMIF_BASE + 0x20)
-#define EMIFF_MRS		(TCMIF_BASE + 0x24)
-#define TC_TIMEOUT1		(TCMIF_BASE + 0x28)
-#define TC_TIMEOUT2		(TCMIF_BASE + 0x2c)
-#define TC_TIMEOUT3		(TCMIF_BASE + 0x30)
-#define TC_ENDIANISM		(TCMIF_BASE + 0x34)
-#define EMIFF_SDRAM_CONFIG_2	(TCMIF_BASE + 0x3c)
-#define EMIF_CFG_DYNAMIC_WS	(TCMIF_BASE + 0x40)
+#define IMIF_PRIO_REG		__REG32(TCMIF_BASE + 0x00)
+#define EMIFS_PRIO_REG		__REG32(TCMIF_BASE + 0x04)
+#define EMIFF_PRIO_REG		__REG32(TCMIF_BASE + 0x08)
+#define EMIFS_CONFIG_REG	__REG32(TCMIF_BASE + 0x0c)
+#define EMIFS_CS0_CONFIG_REG	__REG32(TCMIF_BASE + 0x10)
+#define EMIFS_CS1_CONFIG_REG	__REG32(TCMIF_BASE + 0x14)
+#define EMIFS_CS2_CONFIG_REG	__REG32(TCMIF_BASE + 0x18)
+#define EMIFS_CS3_CONFIG_REG	__REG32(TCMIF_BASE + 0x1c)
+#define EMIFF_SDRAM_CONFIG_REG	__REG32(TCMIF_BASE + 0x20)
+#define EMIFF_MRS_REG		__REG32(TCMIF_BASE + 0x24)
+#define TC_TIMEOUT1_REG		__REG32(TCMIF_BASE + 0x28)
+#define TC_TIMEOUT2_REG		__REG32(TCMIF_BASE + 0x2c)
+#define TC_TIMEOUT3_REG		__REG32(TCMIF_BASE + 0x30)
+#define TC_ENDIANISM_REG	__REG32(TCMIF_BASE + 0x34)
+#define EMIFF_SDRAM_CONFIG_2_REG __REG32(TCMIF_BASE + 0x3c)
+#define EMIF_CFG_DYNAMIC_WS_REG	__REG32(TCMIF_BASE + 0x40)
+
 /*
  * ----------------------------------------------------------------------------
  * System control registers
@@ -290,6 +292,7 @@
 #define OMAP_ID_1610		0x3576
 #define OMAP_ID_1710		0x35F7
 #define OMAP_ID_5912		0x358C
+#define OMAP_ID_1611            0x358C
 
 #ifdef CONFIG_ARCH_OMAP730
 #include "omap730.h"
@@ -307,12 +310,16 @@
 
 #ifdef CONFIG_ARCH_OMAP1610
 #include "omap1610.h"
-#define cpu_is_omap1710()       (((OMAP_ID_REG >> ID_SHIFT) & ID_MASK) == OMAP_ID_1710)
-/* Detect 1710 as 1610 for now */
-#define cpu_is_omap1610()	(((OMAP_ID_REG >> ID_SHIFT) & ID_MASK) == OMAP_ID_1610 \
-				|| cpu_is_omap1710())
+#define cpu_is_omap1610()	(((OMAP_ID_REG >> ID_SHIFT) & ID_MASK) == OMAP_ID_1610) || \
+				(((OMAP_ID_REG >> ID_SHIFT) & ID_MASK) == OMAP_ID_1611)
 #else
 #define cpu_is_omap1610()	0
+#endif
+
+#ifdef CONFIG_ARCH_OMAP1710
+#include "omap1610.h"
+#define cpu_is_omap1710()       (((OMAP_ID_REG >> ID_SHIFT) & ID_MASK) == OMAP_ID_1710)
+#else
 #define cpu_is_omap1710()	0
 #endif
 
@@ -343,7 +350,6 @@
 
 #ifdef CONFIG_MACH_OMAP_H3
 #include "board-h3.h"
-#error "Support for H3 board not yet implemented."
 #endif
 
 #ifdef CONFIG_MACH_OMAP_H4
diff -Nru a/include/asm-arm/arch-omap/mcbsp.h b/include/asm-arm/arch-omap/mcbsp.h
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/include/asm-arm/arch-omap/mcbsp.h	2004-10-18 14:57:23 -07:00
@@ -0,0 +1,253 @@
+/*
+ * linux/include/asm-arm/arch-omap/gpio.h
+ *
+ * Defines for Multi-Channel Buffered Serial Port
+ *
+ * Copyright (C) 2002 RidgeRun, Inc.
+ * Author: Steve Johnson
+ *
+ * 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
+ *
+ */
+#ifndef __ASM_ARCH_OMAP_MCBSP_H
+#define __ASM_ARCH_OMAP_MCBSP_H
+
+#include <asm/arch/hardware.h>
+
+#define OMAP730_MCBSP1_BASE	0xfffb1000
+#define OMAP730_MCBSP2_BASE	0xfffb1800
+
+#define OMAP1510_MCBSP1_BASE	0xe1011000
+#define OMAP1510_MCBSP2_BASE	0xfffb1000
+#define OMAP1510_MCBSP3_BASE	0xe1017000
+
+#define OMAP1610_MCBSP1_BASE	0xe1011800
+#define OMAP1610_MCBSP2_BASE	0xfffb1000
+#define OMAP1610_MCBSP3_BASE	0xe1017000
+
+#define OMAP_MCBSP_REG_DRR2	0x00
+#define OMAP_MCBSP_REG_DRR1	0x02
+#define OMAP_MCBSP_REG_DXR2	0x04
+#define OMAP_MCBSP_REG_DXR1	0x06
+#define OMAP_MCBSP_REG_SPCR2	0x08
+#define OMAP_MCBSP_REG_SPCR1	0x0a
+#define OMAP_MCBSP_REG_RCR2	0x0c
+#define OMAP_MCBSP_REG_RCR1	0x0e
+#define OMAP_MCBSP_REG_XCR2	0x10
+#define OMAP_MCBSP_REG_XCR1	0x12
+#define OMAP_MCBSP_REG_SRGR2	0x14
+#define OMAP_MCBSP_REG_SRGR1	0x16
+#define OMAP_MCBSP_REG_MCR2	0x18
+#define OMAP_MCBSP_REG_MCR1	0x1a
+#define OMAP_MCBSP_REG_RCERA	0x1c
+#define OMAP_MCBSP_REG_RCERB	0x1e
+#define OMAP_MCBSP_REG_XCERA	0x20
+#define OMAP_MCBSP_REG_XCERB	0x22
+#define OMAP_MCBSP_REG_PCR0	0x24
+#define OMAP_MCBSP_REG_RCERC	0x26
+#define OMAP_MCBSP_REG_RCERD	0x28
+#define OMAP_MCBSP_REG_XCERC	0x2A
+#define OMAP_MCBSP_REG_XCERD	0x2C
+#define OMAP_MCBSP_REG_RCERE	0x2E
+#define OMAP_MCBSP_REG_RCERF	0x30
+#define OMAP_MCBSP_REG_XCERE	0x32
+#define OMAP_MCBSP_REG_XCERF	0x34
+#define OMAP_MCBSP_REG_RCERG	0x36
+#define OMAP_MCBSP_REG_RCERH	0x38
+#define OMAP_MCBSP_REG_XCERG	0x3A
+#define OMAP_MCBSP_REG_XCERH	0x3C
+
+#define OMAP_MAX_MCBSP_COUNT 3
+
+#define OMAP_MCBSP_READ(base, reg)		__raw_readw((base) + OMAP_MCBSP_REG_##reg)
+#define OMAP_MCBSP_WRITE(base, reg, val)	__raw_writew((val), (base) + OMAP_MCBSP_REG_##reg)
+
+/************************** McBSP SPCR1 bit definitions ***********************/
+#define RRST			0x0001
+#define RRDY			0x0002
+#define RFULL			0x0004
+#define RSYNC_ERR		0x0008
+#define RINTM(value)		((value)<<4)	/* bits 4:5 */
+#define ABIS			0x0040
+#define DXENA			0x0080
+#define CLKSTP(value)		((value)<<11)	/* bits 11:12 */
+#define RJUST(value)		((value)<<13)	/* bits 13:14 */
+#define DLB			0x8000
+
+/************************** McBSP SPCR2 bit definitions ***********************/
+#define XRST		0x0001
+#define XRDY		0x0002
+#define XEMPTY		0x0004
+#define XSYNC_ERR	0x0008
+#define XINTM(value)	((value)<<4)		/* bits 4:5 */
+#define GRST		0x0040
+#define FRST		0x0080
+#define SOFT		0x0100
+#define FREE		0x0200
+
+/************************** McBSP PCR bit definitions *************************/
+#define CLKRP		0x0001
+#define CLKXP		0x0002
+#define FSRP		0x0004
+#define FSXP		0x0008
+#define DR_STAT		0x0010
+#define DX_STAT		0x0020
+#define CLKS_STAT	0x0040
+#define SCLKME		0x0080
+#define CLKRM		0x0100
+#define CLKXM		0x0200
+#define FSRM		0x0400
+#define FSXM		0x0800
+#define RIOEN		0x1000
+#define XIOEN		0x2000
+#define IDLE_EN		0x4000
+
+/************************** McBSP RCR1 bit definitions ************************/
+#define RWDLEN1(value)		((value)<<5)	/* Bits 5:7 */
+#define RFRLEN1(value)		((value)<<8)	/* Bits 8:14 */
+
+/************************** McBSP XCR1 bit definitions ************************/
+#define XWDLEN1(value)		((value)<<5)	/* Bits 5:7 */
+#define XFRLEN1(value)		((value)<<8)	/* Bits 8:14 */
+
+/*************************** McBSP RCR2 bit definitions ***********************/
+#define RDATDLY(value)		(value)		/* Bits 0:1 */
+#define RFIG			0x0004
+#define RCOMPAND(value)		((value)<<3)	/* Bits 3:4 */
+#define RWDLEN2(value)		((value)<<5)	/* Bits 5:7 */
+#define RFRLEN2(value)		((value)<<8)	/* Bits 8:14 */
+#define RPHASE			0x8000
+
+/*************************** McBSP XCR2 bit definitions ***********************/
+#define XDATDLY(value)		(value)		/* Bits 0:1 */
+#define XFIG			0x0004
+#define XCOMPAND(value)		((value)<<3)	/* Bits 3:4 */
+#define XWDLEN2(value)		((value)<<5)	/* Bits 5:7 */
+#define XFRLEN2(value)		((value)<<8)	/* Bits 8:14 */
+#define XPHASE			0x8000
+
+/************************* McBSP SRGR1 bit definitions ************************/
+#define CLKGDV(value)		(value)		/* Bits 0:7 */
+#define FWID(value)		((value)<<8)	/* Bits 8:15 */
+
+/************************* McBSP SRGR2 bit definitions ************************/
+#define FPER(value)		(value)		/* Bits 0:11 */
+#define FSGM			0x1000
+#define CLKSM			0x2000
+#define CLKSP			0x4000
+#define GSYNC			0x8000
+
+/************************* McBSP MCR1 bit definitions *************************/
+#define RMCM			0x0001
+#define RCBLK(value)		((value)<<2)	/* Bits 2:4 */
+#define RPABLK(value)		((value)<<5)	/* Bits 5:6 */
+#define RPBBLK(value)		((value)<<7)	/* Bits 7:8 */
+
+/************************* McBSP MCR2 bit definitions *************************/
+#define XMCM(value)		(value)		/* Bits 0:1 */
+#define XCBLK(value)		((value)<<2)	/* Bits 2:4 */
+#define XPABLK(value)		((value)<<5)	/* Bits 5:6 */
+#define XPBBLK(value)		((value)<<7)	/* Bits 7:8 */
+
+
+/* we don't do multichannel for now */
+struct omap_mcbsp_reg_cfg {
+	u16 spcr2;
+	u16 spcr1;
+	u16 rcr2;
+	u16 rcr1;
+	u16 xcr2;
+	u16 xcr1;
+	u16 srgr2;
+	u16 srgr1;
+	u16 mcr2;
+	u16 mcr1;
+	u16 pcr0;
+	u16 rcerc;
+	u16 rcerd;
+	u16 xcerc;
+	u16 xcerd;
+	u16 rcere;
+	u16 rcerf;
+	u16 xcere;
+	u16 xcerf;
+	u16 rcerg;
+	u16 rcerh;
+	u16 xcerg;
+	u16 xcerh;
+};
+
+typedef enum {
+	OMAP_MCBSP1 = 0,
+	OMAP_MCBSP2,
+	OMAP_MCBSP3,
+} omap_mcbsp_id;
+
+typedef enum {
+	OMAP_MCBSP_WORD_8 = 0,
+	OMAP_MCBSP_WORD_12,
+	OMAP_MCBSP_WORD_16,
+	OMAP_MCBSP_WORD_20,
+	OMAP_MCBSP_WORD_24,
+	OMAP_MCBSP_WORD_32,
+} omap_mcbsp_word_length;
+
+typedef enum {
+	OMAP_MCBSP_CLK_RISING = 0,
+	OMAP_MCBSP_CLK_FALLING,
+} omap_mcbsp_clk_polarity;
+
+typedef enum {
+	OMAP_MCBSP_FS_ACTIVE_HIGH = 0,
+	OMAP_MCBSP_FS_ACTIVE_LOW,
+} omap_mcbsp_fs_polarity;
+
+typedef enum {
+	OMAP_MCBSP_CLK_STP_MODE_NO_DELAY = 0,
+	OMAP_MCBSP_CLK_STP_MODE_DELAY,
+} omap_mcbsp_clk_stp_mode;
+
+
+/******* SPI specific mode **********/
+typedef enum {
+	OMAP_MCBSP_SPI_MASTER = 0,
+	OMAP_MCBSP_SPI_SLAVE,
+} omap_mcbsp_spi_mode;
+
+struct omap_mcbsp_spi_cfg {
+	omap_mcbsp_spi_mode		spi_mode;
+	omap_mcbsp_clk_polarity		rx_clock_polarity;
+	omap_mcbsp_clk_polarity		tx_clock_polarity;
+	omap_mcbsp_fs_polarity		fsx_polarity;
+	u8				clk_div;
+	omap_mcbsp_clk_stp_mode		clk_stp_mode;
+	omap_mcbsp_word_length		word_length;
+};
+
+void omap_mcbsp_config(unsigned int id, const struct omap_mcbsp_reg_cfg * config);
+int omap_mcbsp_request(unsigned int id);
+void omap_mcbsp_free(unsigned int id);
+void omap_mcbsp_start(unsigned int id);
+void omap_mcbsp_stop(unsigned int id);
+void omap_mcbsp_xmit_word(unsigned int id, u32 word);
+u32 omap_mcbsp_recv_word(unsigned int id);
+
+int omap_mcbsp_xmit_buffer(unsigned int id, dma_addr_t buffer, unsigned int length);
+int omap_mcbsp_recv_buffer(unsigned int id, dma_addr_t buffer, unsigned int length);
+
+/* SPI specific API */
+void omap_mcbsp_set_spi_mode(unsigned int id, const struct omap_mcbsp_spi_cfg * spi_cfg);
+
+#endif
diff -Nru a/include/asm-arm/arch-omap/memory.h b/include/asm-arm/arch-omap/memory.h
--- a/include/asm-arm/arch-omap/memory.h	2004-10-18 14:56:29 -07:00
+++ b/include/asm-arm/arch-omap/memory.h	2004-10-18 14:56:29 -07:00
@@ -64,7 +64,7 @@
 
 #define virt_to_lbus(x)		((x) - PAGE_OFFSET + OMAP1510_LB_OFFSET)
 #define lbus_to_virt(x)		((x) - OMAP1510_LB_OFFSET + PAGE_OFFSET)
-#define is_lbus_device(dev)	(cpu_is_omap1510() && dev->coherent_dma_mask == 0x0fffffff)
+#define is_lbus_device(dev)	(cpu_is_omap1510() && dev && dev->coherent_dma_mask == 0x0fffffff)
 
 #define __arch_page_to_dma(dev, page)	({is_lbus_device(dev) ? \
 					(dma_addr_t)virt_to_lbus(page_address(page)) : \
diff -Nru a/include/asm-arm/arch-omap/mux.h b/include/asm-arm/arch-omap/mux.h
--- a/include/asm-arm/arch-omap/mux.h	2004-10-18 14:56:28 -07:00
+++ b/include/asm-arm/arch-omap/mux.h	2004-10-18 14:56:28 -07:00
@@ -135,6 +135,10 @@
 	UART3_CLKREQ,
 	UART3_BCLK,	/* 12MHz clock out */
 
+	/* PWT & PWL */
+	PWT,
+	PWL,
+
 	/* USB master generic */
 	R18_USB_VBUS,
 	R18_1510_USB_GPIO0,
@@ -154,6 +158,7 @@
 	USB1_RCV,
 	USB1_SPEED,
 	R13_1610_USB1_SPEED,
+	R13_1710_USB1_SE0,
 
 	/* USB2 master */
 	USB2_SUSP,
@@ -169,6 +174,10 @@
 	R19_1510_GPIO1,
 	M14_1510_GPIO2,
 
+	/* OMAP-1710 GPIO */
+	R18_1710_GPIO0,
+	W15_1710_GPIO40,
+
 	/* MPUIO */
 	MPUIO2,
 	MPUIO4,
@@ -225,6 +234,7 @@
 	P10_1610_GPIO22,
 	V5_1610_GPIO24,
 	AA20_1610_GPIO_41,
+	W19_1610_GPIO48,
 
 	/* OMAP-1610 uWire */
 	V19_1610_UWIRE_SCLK,
@@ -242,6 +252,11 @@
 	MMC_CLK,
 	MMC_DAT3,
 
+	/* OMAP-1710 MMC CMDDIR and DATDIR0 */
+	M15_1710_MMC_CLKI,
+	P19_1710_MMC_CMDDIR,
+	P20_1710_MMC_DATDIR0,
+
 	/* OMAP-1610 USB0 alternate pin configuration */
 	W9_USB0_TXEN,
 	AA9_USB0_VP,
@@ -317,6 +332,10 @@
 MUX_CFG("UART3_CLKREQ",		 9,   27,    0,	  2,   5,   0,	 NA,	 0,  0)
 MUX_CFG("UART3_BCLK",		 A,    0,    0,	  2,   6,   0,	 NA,	 0,  0)
 
+/* PWT & PWL, conflicts with UART3 */
+MUX_CFG("PWT",		 	 6,    0,    2,	  0,  30,   0,	 NA,	 0,  0)
+MUX_CFG("PWL",		 	 6,    3,    1,	  0,  31,   1,	 NA,	 0,  0)
+
 /* USB internal master generic */
 MUX_CFG("R18_USB_VBUS",		 7,    9,    2,	  1,  11,   0,	 NA,	 0,  1)
 MUX_CFG("R18_1510_USB_GPIO0",	 7,    9,    0,	  1,  11,   1,	 NA,	 0,  1)
@@ -336,6 +355,7 @@
 MUX_CFG("USB1_RCV",		 A,    9,    1,	  2,   9,   0,	 NA,	 0,  1)
 MUX_CFG("USB1_SPEED",		 A,   12,    2,	  2,  10,   0,	 NA,	 0,  1)
 MUX_CFG("R13_1610_USB1_SPEED",	 A,   12,    5,	  2,  10,   0,	 NA,	 0,  1)
+MUX_CFG("R13_1710_USB1_SEO",	 A,   12,    5,   2,  10,   0,   NA,     0,  1)
 
 /* USB2 master */
 MUX_CFG("USB2_SUSP",		 B,    3,    1,	  2,  17,   0,	 NA,	 0,  1)
@@ -347,9 +367,13 @@
 MUX_CFG("USB2_TXD",		 C,   27,    2,	  3,   3,   0,	 NA,	 0,  1)
 
 /* OMAP-1510 GPIO */
-MUX_CFG("R18_1510_GPIO0",	 7,    9,   0,	  1,  11,   1,	  0,	 0,  1)
-MUX_CFG("R19_1510_GPIO1",	 7,    6,   0,	  1,  10,   1,	  0,	 0,  1)
-MUX_CFG("M14_1510_GPIO2",	 7,    3,   0,	  1,   9,   1,	  0,	 0,  1)
+MUX_CFG("R18_1510_GPIO0",	 7,    9,    0,   1,  11,   1,    0,     0,  1)
+MUX_CFG("R19_1510_GPIO1",	 7,    6,    0,   1,  10,   1,    0,     0,  1)
+MUX_CFG("M14_1510_GPIO2",	 7,    3,    0,   1,   9,   1,    0,     0,  1)
+
+/* OMAP-1710 GPIO */
+MUX_CFG("R18_1710_GPIO0",	 7,    9,    0,   1,  11,   1,    1,     1,  1)
+MUX_CFG("W15_1710_GPIO40",	 9,   27,    7,   2,   5,   1,    2,     1,  1)
 
 /* MPUIO */
 MUX_CFG("MPUIO2",		 7,   18,    0,	  1,   1,   1,	 NA,	 0,  1)
@@ -408,6 +432,7 @@
 MUX_CFG("P10_1610_GPIO22",	 C,    0,    7,	  2,  26,   0,	  2,	 1,  1)
 MUX_CFG("V5_1610_GPIO24",	 B,   15,    7,	  2,  21,   0,	  2,	 1,  1)
 MUX_CFG("AA20_1610_GPIO_41",	 9,    9,    7,	  1,  31,   0,	  1,	 1,  1)
+MUX_CFG("W19_1610_GPIO48",	 8,   15,    7,   1,  23,   1,    1,     0,  1)
 
 /* OMAP-1610 uWire */
 MUX_CFG("V19_1610_UWIRE_SCLK",	 8,    6,    0,	  1,  20,   0,	  1,	 1,  1)
@@ -417,13 +442,16 @@
 MUX_CFG("P15_1610_UWIRE_CS3",	 8,   12,    1,	  1,  22,   0,	  1,	 1,  1)
 MUX_CFG("N15_1610_UWIRE_CS1",	 7,   18,    2,	  1,  14,   0,	 NA,	 0,  1)
 
-/* First MMC interface, same on 1510 and 1610 */
+/* First MMC interface, same on 1510, 1610 and 1710 */
 MUX_CFG("MMC_CMD",		 A,   27,    0,	  2,  15,   1,	  2,	 1,  1)
 MUX_CFG("MMC_DAT1",		 A,   24,    0,	  2,  14,   1,	  2,	 1,  1)
 MUX_CFG("MMC_DAT2",		 A,   18,    0,	  2,  12,   1,	  2,	 1,  1)
 MUX_CFG("MMC_DAT0",		 B,    0,    0,	  2,  16,   1,	  2,	 1,  1)
 MUX_CFG("MMC_CLK",		 A,   21,    0,	 NA,   0,   0,	 NA,	 0,  1)
 MUX_CFG("MMC_DAT3",		10,   15,    0,	  3,   8,   1,	  3,	 1,  1)
+MUX_CFG("M15_1710_MMC_CLKI",	 6,   21,    2,   0,   0,   0,   NA,     0,  1)
+MUX_CFG("P19_1710_MMC_CMDDIR",	 6,   24,    6,   0,   0,   0,   NA,     0,  1)
+MUX_CFG("P20_1710_MMC_DATDIR0",	 6,   27,    5,   0,   0,   0,   NA,     0,  1)
 
 /* OMAP-1610 USB0 alternate configuration */
 MUX_CFG("W9_USB0_TXEN",		 B,   9,     5,	  2,  19,   0,	  2,	 0,  1)
diff -Nru a/include/asm-arm/arch-omap/omap1510.h b/include/asm-arm/arch-omap/omap1510.h
--- a/include/asm-arm/arch-omap/omap1510.h	2004-10-18 14:56:27 -07:00
+++ b/include/asm-arm/arch-omap/omap1510.h	2004-10-18 14:56:27 -07:00
@@ -40,16 +40,6 @@
 #define OMAP1510_SRAM_SIZE	(SZ_128K + SZ_64K)
 #define OMAP1510_SRAM_START	0x20000000
 
-#define OMAP1510_MCBSP1_BASE	0xE1011000
-#define OMAP1510_MCBSP1_SIZE	SZ_4K
-#define OMAP1510_MCBSP1_START	0xE1011000
-
-#define OMAP1510_MCBSP2_BASE	0xFFFB1000
-
-#define OMAP1510_MCBSP3_BASE	0xE1017000
-#define OMAP1510_MCBSP3_SIZE	SZ_4K
-#define OMAP1510_MCBSP3_START	0xE1017000
-
 #define OMAP1510_DSP_BASE	0xE0000000
 #define OMAP1510_DSP_SIZE	0x28000
 #define OMAP1510_DSP_START	0xE0000000
@@ -57,6 +47,15 @@
 #define OMAP1510_DSPREG_BASE	0xE1000000
 #define OMAP1510_DSPREG_SIZE	SZ_128K
 #define OMAP1510_DSPREG_START	0xE1000000
+
+/*
+ * ----------------------------------------------------------------------------
+ * Memory used by power management
+ * ----------------------------------------------------------------------------
+ */
+
+#define OMAP1510_SRAM_IDLE_SUSPEND	(OMAP1510_SRAM_BASE + OMAP1510_SRAM_SIZE - 0x200)
+#define OMAP1510_SRAM_API_SUSPEND	(OMAP1510_SRAM_IDLE_SUSPEND + 0x100)
 
 #endif /*  __ASM_ARCH_OMAP1510_H */
 
diff -Nru a/include/asm-arm/arch-omap/omap1610.h b/include/asm-arm/arch-omap/omap1610.h
--- a/include/asm-arm/arch-omap/omap1610.h	2004-10-18 14:55:54 -07:00
+++ b/include/asm-arm/arch-omap/omap1610.h	2004-10-18 14:55:54 -07:00
@@ -49,6 +49,15 @@
 #define OMAP1610_DSPREG_START	0xE1000000
 
 /*
+ * ----------------------------------------------------------------------------
+ * Memory used by power management
+ * ----------------------------------------------------------------------------
+ */
+
+#define OMAP1610_SRAM_IDLE_SUSPEND	(OMAP1610_SRAM_BASE + OMAP1610_SRAM_SIZE - 0x200)
+#define OMAP1610_SRAM_API_SUSPEND	(OMAP1610_SRAM_IDLE_SUSPEND + 0x100)
+
+/*
  * ---------------------------------------------------------------------------
  * Interrupts
  * ---------------------------------------------------------------------------
diff -Nru a/include/asm-arm/arch-omap/omap5912.h b/include/asm-arm/arch-omap/omap5912.h
--- a/include/asm-arm/arch-omap/omap5912.h	2004-10-18 14:55:55 -07:00
+++ b/include/asm-arm/arch-omap/omap5912.h	2004-10-18 14:55:55 -07:00
@@ -50,6 +50,15 @@
 #define OMAP5912_DSPREG_START	0xE1000000
 
 /*
+ * ----------------------------------------------------------------------------
+ * Memory used by power management
+ * ----------------------------------------------------------------------------
+ */
+
+#define OMAP5912_SRAM_IDLE_SUSPEND	(OMAP5912_SRAM_BASE + OMAP5912_SRAM_SIZE - 0x200)
+#define OMAP5912_SRAM_API_SUSPEND	(OMAP5912_SRAM_IDLE_SUSPEND + 0x100)
+
+/*
  * ---------------------------------------------------------------------------
  * Interrupts
  * ---------------------------------------------------------------------------
diff -Nru a/include/asm-arm/arch-omap/omap730.h b/include/asm-arm/arch-omap/omap730.h
--- a/include/asm-arm/arch-omap/omap730.h	2004-10-18 14:57:04 -07:00
+++ b/include/asm-arm/arch-omap/omap730.h	2004-10-18 14:57:04 -07:00
@@ -40,12 +40,6 @@
 #define OMAP730_SRAM_SIZE	(SZ_128K + SZ_64K + SZ_8K)
 #define OMAP730_SRAM_START	0x20000000
 
-#define OMAP730_MCBSP1_BASE	0xfffb1000
-#define OMAP730_MCBSP1_SIZE	(SZ_1K * 2)
-#define OMAP730_MCBSP1_START	0xfffb1000
-
-#define OMAP730_MCBSP2_BASE	0xfffb1800
-
 #define OMAP730_DSP_BASE	0xE0000000
 #define OMAP730_DSP_SIZE	0x50000
 #define OMAP730_DSP_START	0xE0000000
diff -Nru a/include/asm-arm/arch-omap/tps65010.h b/include/asm-arm/arch-omap/tps65010.h
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/include/asm-arm/arch-omap/tps65010.h	2004-10-18 14:57:23 -07:00
@@ -0,0 +1,80 @@
+/* linux/include/asm-arm/arch-omap/tps65010.h
+ *
+ * Functions to access TPS65010 power management device.
+ *
+ * Copyright (C) 2004 Dirk Behme <dirk.behme@de.bosch.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 SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
+ * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * You should have received a copy of the  GNU General Public License along
+ * with this program; if not, write  to the Free Software Foundation, Inc.,
+ * 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef __ASM_ARCH_TPS65010_H
+#define __ASM_ARCH_TPS65010_H
+
+/*
+ * ----------------------------------------------------------------------------
+ * Macros used by exported functions
+ * ----------------------------------------------------------------------------
+ */
+
+#define LED1  1
+#define LED2  2
+#define OFF   0
+#define ON    1
+#define BLINK 2
+#define GPIO1 1
+#define GPIO2 2
+#define GPIO3 3
+#define GPIO4 4
+#define LOW   0
+#define HIGH  1
+
+/*
+ * ----------------------------------------------------------------------------
+ * Exported functions
+ * ----------------------------------------------------------------------------
+ */
+
+/* Draw from VBUS:
+ *   0 mA -- DON'T DRAW (might supply power instead)
+ * 100 mA -- usb unit load (slowest charge rate)
+ * 500 mA -- usb high power (fast battery charge)
+ */
+extern int tps65010_set_vbus_draw(unsigned mA);
+
+/* tps65010_set_gpio_out_value parameter:
+ * gpio:  GPIO1, GPIO2, GPIO3 or GPIO4
+ * value: LOW or HIGH
+ */
+extern int tps65010_set_gpio_out_value(unsigned gpio, unsigned value);
+
+/* tps65010_set_led parameter:
+ * led:  LED1 or LED2
+ * mode: ON, OFF or BLINK
+ */
+extern int tps65010_set_led(unsigned led, unsigned mode);
+
+/* tps65010_set_low_pwr parameter:
+ * mode: ON or OFF
+ */
+extern int tps65010_set_low_pwr(unsigned mode);
+
+#endif /*  __ASM_ARCH_TPS65010_H */
+
diff -Nru a/include/asm-arm/arch-omap/uncompress.h b/include/asm-arm/arch-omap/uncompress.h
--- a/include/asm-arm/arch-omap/uncompress.h	2004-10-18 14:56:50 -07:00
+++ b/include/asm-arm/arch-omap/uncompress.h	2004-10-18 14:56:50 -07:00
@@ -28,7 +28,7 @@
 #define omap_get_id() ((*(volatile unsigned int *)(0xfffed404)) >> 12) & ID_MASK
 
 static void
-puts(const char *s)
+putstr(const char *s)
 {
 	volatile u8 * uart = 0;
 	int shift = 0;
diff -Nru a/include/asm-arm/arch-omap/usb.h b/include/asm-arm/arch-omap/usb.h
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/include/asm-arm/arch-omap/usb.h	2004-10-18 14:57:24 -07:00
@@ -0,0 +1,108 @@
+// include/asm-arm/mach-omap/usb.h
+
+#ifndef	__ASM_ARCH_OMAP_USB_H
+#define	__ASM_ARCH_OMAP_USB_H
+
+#include <asm/arch/board.h>
+
+/*-------------------------------------------------------------------------*/
+
+#define OTG_BASE			0xfffb0400
+#define UDC_BASE			0xfffb4000
+#define OMAP_OHCI_BASE			0xfffba000
+
+/*-------------------------------------------------------------------------*/
+
+/*
+ * OTG and transceiver registers, for OMAPs starting with ARM926
+ */
+#define OTG_REG32(offset)		__REG32(OTG_BASE + (offset))
+#define OTG_REG16(offset)		__REG16(OTG_BASE + (offset))
+
+#define OTG_REV_REG			OTG_REG32(0x00)
+#define OTG_SYSCON_1_REG		OTG_REG32(0x04)
+#	define	 USB2_TRX_MODE(w)	(((w)>>24)&0x07)
+#	define	 USB1_TRX_MODE(w)	(((w)>>20)&0x07)
+#	define	 USB0_TRX_MODE(w)	(((w)>>16)&0x07)
+#	define	 OTG_IDLE_EN		(1 << 15)
+#	define	 HST_IDLE_EN		(1 << 14)
+#	define	 DEV_IDLE_EN		(1 << 13)
+#	define	 OTG_RESET_DONE		(1 << 2)
+#define OTG_SYSCON_2_REG		OTG_REG32(0x08)
+#	define	 OTG_EN			(1 << 31)
+#	define	 USBX_SYNCHRO		(1 << 30)
+#	define	 OTG_MST16		(1 << 29)
+#	define	 SRP_GPDATA		(1 << 28)
+#	define	 SRP_GPDVBUS		(1 << 27)
+#	define	 SRP_GPUVBUS(w)		(((w)>>24)&0x07)
+#	define	 A_WAIT_VRISE(w)	(((w)>>20)&0x07)
+#	define	 B_ASE_BRST(w)		(((w)>>16)&0x07)
+#	define	 SRP_DPW		(1 << 14)
+#	define	 SRP_DATA		(1 << 13)
+#	define	 SRP_VBUS		(1 << 12)
+#	define	 OTG_PADEN		(1 << 10)
+#	define	 HMC_PADEN		(1 << 9)
+#	define	 UHOST_EN		(1 << 8)
+#	define	 HMC_TLLSPEED		(1 << 7)
+#	define	 HMC_TLLATTACH		(1 << 6)
+#	define	 OTG_HMC(w)		(((w)>>0)&0x3f)
+#define OTG_CTRL_REG			OTG_REG32(0x0c)
+#	define	 OTG_ASESSVLD		(1 << 20)
+#	define	 OTG_BSESSEND		(1 << 19)
+#	define	 OTG_BSESSVLD		(1 << 18)
+#	define	 OTG_VBUSVLD		(1 << 17)
+#	define	 OTG_ID			(1 << 16)
+#	define	 OTG_DRIVER_SEL		(1 << 15)
+#	define	 OTG_A_SETB_HNPEN	(1 << 12)
+#	define	 OTG_A_BUSREQ		(1 << 11)
+#	define	 OTG_B_HNPEN		(1 << 9)
+#	define	 OTG_B_BUSREQ		(1 << 8)
+#	define	 OTG_BUSDROP		(1 << 7)
+#	define	 OTG_PULLDOWN		(1 << 5)
+#	define	 OTG_PULLUP		(1 << 4)
+#	define	 OTG_DRV_VBUS		(1 << 3)
+#	define	 OTG_PD_VBUS		(1 << 2)
+#	define	 OTG_PU_VBUS		(1 << 1)
+#	define	 OTG_PU_ID		(1 << 0)
+#define OTG_IRQ_EN_REG			OTG_REG16(0x10)
+#	define	 DRIVER_SWITCH		(1 << 15)
+#	define	 A_VBUS_ERR		(1 << 13)
+#	define	 A_REQ_TMROUT		(1 << 12)
+#	define	 A_SRP_DETECT		(1 << 11)
+#	define	 B_HNP_FAIL		(1 << 10)
+#	define	 B_SRP_TMROUT		(1 << 9)
+#	define	 B_SRP_DONE		(1 << 8)
+#	define	 B_SRP_STARTED		(1 << 7)
+#	define	 OPRT_CHG		(1 << 0)
+#define OTG_IRQ_SRC_REG			OTG_REG16(0x14)
+	// same bits as in IRQ_EN
+#define OTG_OUTCTRL_REG			OTG_REG16(0x18)
+#	define	 OTGVPD			(1 << 14)
+#	define	 OTGVPU			(1 << 13)
+#	define	 OTGPUID		(1 << 12)
+#	define	 USB2VDR		(1 << 10)
+#	define	 USB2PDEN		(1 << 9)
+#	define	 USB2PUEN		(1 << 8)
+#	define	 USB1VDR		(1 << 6)
+#	define	 USB1PDEN		(1 << 5)
+#	define	 USB1PUEN		(1 << 4)
+#	define	 USB0VDR		(1 << 2)
+#	define	 USB0PDEN		(1 << 1)
+#	define	 USB0PUEN		(1 << 0)
+#define OTG_TEST_REG			OTG_REG16(0x20)
+#define OTG_VENDOR_CODE_REG		OTG_REG32(0xfc)
+
+/*-------------------------------------------------------------------------*/
+
+#define	USB_TRANSCEIVER_CTRL_REG	__REG32(0xfffe1000 + 0x0064)
+#	define	CONF_USB2_UNI_R		(1 << 8)
+#	define	CONF_USB1_UNI_R		(1 << 7)
+#	define	CONF_USB_PORT0_R(x)	(((x)>>4)&0x7)
+#	define	CONF_USB0_ISOLATE_R	(1 << 3)
+#	define	CONF_USB_PWRDN_DM_R	(1 << 2)
+#	define	CONF_USB_PWRDN_DP_R	(1 << 1)
+
+
+
+
+#endif	/* __ASM_ARCH_OMAP_USB_H */
diff -Nru a/include/asm-arm/arch-pxa/dma.h b/include/asm-arm/arch-pxa/dma.h
--- a/include/asm-arm/arch-pxa/dma.h	2004-10-18 14:57:04 -07:00
+++ b/include/asm-arm/arch-pxa/dma.h	2004-10-18 14:57:04 -07:00
@@ -22,7 +22,7 @@
  * Note: this structure must always be aligned to a 16-byte boundary.
  */
 
-typedef struct {
+typedef struct pxa_dma_desc {
 	volatile u32 ddadr;	/* Points to the next descriptor + flags */
 	volatile u32 dsadr;	/* DSADR value for the current transfer */
 	volatile u32 dtadr;	/* DTADR value for the current transfer */
diff -Nru a/include/asm-arm/arch-pxa/hardware.h b/include/asm-arm/arch-pxa/hardware.h
--- a/include/asm-arm/arch-pxa/hardware.h	2004-10-18 14:55:54 -07:00
+++ b/include/asm-arm/arch-pxa/hardware.h	2004-10-18 14:55:54 -07:00
@@ -59,10 +59,9 @@
 # define __REG(x)	__REGP(io_p2v(x))
 #endif
 
-/* Let's kick gcc's ass again... */
-# define __REG2(x,y)	\
-	( __builtin_constant_p(y) ? (__REG((x) + (y))) \
-				  : (*(volatile u32 *)((u32)&__REG(x) + (y))) )
+/* With indexed regs we don't want to feed the index through io_p2v()
+   especially if it is a variable, otherwise horrible code will result. */
+# define __REG2(x,y)     (*(volatile u32 *)((u32)&__REG(x) + (y)))
 
 # define __PREG(x)	(io_v2p((u32)&(x)))
 
@@ -72,8 +71,6 @@
 # define __PREG(x)	io_v2p(x)
 
 #endif
-
-#include "pxa-regs.h"
 
 #ifndef __ASSEMBLY__
 
diff -Nru a/include/asm-arm/arch-pxa/irqs.h b/include/asm-arm/arch-pxa/irqs.h
--- a/include/asm-arm/arch-pxa/irqs.h	2004-10-18 14:55:55 -07:00
+++ b/include/asm-arm/arch-pxa/irqs.h	2004-10-18 14:55:55 -07:00
@@ -12,19 +12,34 @@
 
 #include <linux/config.h>
 
-#define PXA_IRQ_SKIP	7	/* The first 7 IRQs are not yet used */
+#ifdef CONFIG_PXA27x
+#define PXA_IRQ_SKIP	0
+#else
+#define PXA_IRQ_SKIP	7
+#endif
+
 #define PXA_IRQ(x)	((x) - PXA_IRQ_SKIP)
 
-#define IRQ_HWUART	PXA_IRQ(7)	/* HWUART Transmit/Receive/Error */
+#define IRQ_SSP3	PXA_IRQ(0)	/* SSP3 service request */
+#define IRQ_MSL		PXA_IRQ(1)	/* MSL Interface interrupt */
+#define IRQ_USBH2	PXA_IRQ(2)	/* USB Host interrupt 1 (OHCI) */
+#define IRQ_USBH1	PXA_IRQ(3)	/* USB Host interrupt 2 (non-OHCI) */
+#define IRQ_KEYPAD	PXA_IRQ(4)	/* Key pad controller */
+#define IRQ_MEMSTK	PXA_IRQ(5)	/* Memory Stick interrupt */
+#define IRQ_PWRI2C	PXA_IRQ(6)	/* Power I2C interrupt */
+#define IRQ_HWUART	PXA_IRQ(7)	/* HWUART Transmit/Receive/Error (PXA26x) */
+#define IRQ_OST_4_11	PXA_IRQ(7)	/* OS timer 4-11 matches (PXA27x) */
 #define	IRQ_GPIO0	PXA_IRQ(8)	/* GPIO0 Edge Detect */
 #define	IRQ_GPIO1	PXA_IRQ(9)	/* GPIO1 Edge Detect */
-#define	IRQ_GPIO_2_80	PXA_IRQ(10)	/* GPIO[2-80] Edge Detect */
+#define	IRQ_GPIO_2_x	PXA_IRQ(10)	/* GPIO[2-x] Edge Detect */
 #define	IRQ_USB		PXA_IRQ(11)	/* USB Service */
 #define	IRQ_PMU		PXA_IRQ(12)	/* Performance Monitoring Unit */
 #define	IRQ_I2S		PXA_IRQ(13)	/* I2S Interrupt */
 #define	IRQ_AC97	PXA_IRQ(14)	/* AC97 Interrupt */
-#define IRQ_ASSP	PXA_IRQ(15)	/* Audio SSP Service Request */
-#define IRQ_NSSP	PXA_IRQ(16)	/* Network SSP Service Request */
+#define IRQ_ASSP	PXA_IRQ(15)	/* Audio SSP Service Request (PXA25x) */
+#define IRQ_USIM	PXA_IRQ(15)     /* Smart Card interface interrupt (PXA27x) */
+#define IRQ_NSSP	PXA_IRQ(16)	/* Network SSP Service Request (PXA25x) */
+#define IRQ_SSP2	PXA_IRQ(16)	/* SSP2 interrupt (PXA27x) */
 #define	IRQ_LCD		PXA_IRQ(17)	/* LCD Controller Service Request */
 #define	IRQ_I2C		PXA_IRQ(18)	/* I2C Service Request */
 #define	IRQ_ICP		PXA_IRQ(19)	/* ICP Transmit/Receive/Error */
@@ -41,13 +56,28 @@
 #define	IRQ_RTC1Hz	PXA_IRQ(30)	/* RTC HZ Clock Tick */
 #define	IRQ_RTCAlrm	PXA_IRQ(31)	/* RTC Alarm */
 
-#define GPIO_2_80_TO_IRQ(x)	\
-			PXA_IRQ((x) - 2 + 32)
-#define IRQ_GPIO(x)	(((x) < 2) ? (IRQ_GPIO0 + (x)) : GPIO_2_80_TO_IRQ(x))
-
-#define IRQ_TO_GPIO_2_80(i)	\
-			((i) - PXA_IRQ(32) + 2)
-#define IRQ_TO_GPIO(i)	((i) - (((i) > IRQ_GPIO1) ? IRQ_GPIO(2) - 2 : IRQ_GPIO(0)))
+#ifdef CONFIG_PXA27x
+#define IRQ_TPM		PXA_IRQ(32)	/* TPM interrupt */
+#define IRQ_CAMERA	PXA_IRQ(33)	/* Camera Interface */
+
+#define PXA_INTERNAL_IRQS 34
+#else
+#define PXA_INTERNAL_IRQS 32
+#endif
+
+#define GPIO_2_x_TO_IRQ(x)	\
+			PXA_IRQ((x) - 2 + PXA_INTERNAL_IRQS)
+#define IRQ_GPIO(x)	(((x) < 2) ? (IRQ_GPIO0 + (x)) : GPIO_2_x_TO_IRQ(x))
+
+#define IRQ_TO_GPIO_2_x(i)	\
+			((i) - IRQ_GPIO(2) + 2)
+#define IRQ_TO_GPIO(i)	(((i) < IRQ_GPIO(2)) ? ((i) - IRQ_GPIO0) : IRQ_TO_GPIO_2_x(i))
+
+#if defined(CONFIG_PXA25x)
+#define PXA_LAST_GPIO	80
+#elif defined(CONFIG_PXA27x)
+#define PXA_LAST_GPIO	127
+#endif
 
 /*
  * The next 16 interrupts are for board specific purposes.  Since
@@ -55,7 +85,7 @@
  * these.  If you need more, increase IRQ_BOARD_END, but keep it
  * within sensible limits.
  */
-#define IRQ_BOARD_START		(IRQ_GPIO(80) + 1)
+#define IRQ_BOARD_START		(IRQ_GPIO(PXA_LAST_GPIO) + 1)
 #define IRQ_BOARD_END		(IRQ_BOARD_START + 16)
 
 #define IRQ_SA1111_START	(IRQ_BOARD_END)
diff -Nru a/include/asm-arm/arch-pxa/mmc.h b/include/asm-arm/arch-pxa/mmc.h
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/include/asm-arm/arch-pxa/mmc.h	2004-10-18 14:57:24 -07:00
@@ -0,0 +1,19 @@
+#ifndef ASMARM_ARCH_MMC_H
+#define ASMARM_ARCH_MMC_H
+
+#include <linux/mmc/protocol.h>
+#include <linux/interrupt.h>
+
+struct device;
+struct mmc_host;
+
+struct pxamci_platform_data {
+	unsigned int ocr_mask;			/* available voltages */
+	int (*init)(struct device *, irqreturn_t (*)(int, void *, struct pt_regs *), void *);
+	void (*setpower)(struct device *, unsigned int);
+	void (*exit)(struct device *, void *);
+};
+
+extern void pxa_set_mci_info(struct pxamci_platform_data *info);
+
+#endif
diff -Nru a/include/asm-arm/arch-pxa/pxa-regs.h b/include/asm-arm/arch-pxa/pxa-regs.h
--- a/include/asm-arm/arch-pxa/pxa-regs.h	2004-10-18 14:56:33 -07:00
+++ b/include/asm-arm/arch-pxa/pxa-regs.h	2004-10-18 14:56:33 -07:00
@@ -15,17 +15,6 @@
 
 #include <linux/config.h>
 
-// FIXME hack so that SA-1111.h will work [cb]
-
-#ifndef __ASSEMBLY__
-typedef unsigned short  Word16 ;
-typedef unsigned int    Word32 ;
-typedef Word32          Word ;
-typedef Word            Quad [4] ;
-typedef void            *Address ;
-typedef void            (*ExcpHndlr) (void) ;
-#endif
-
 /*
  * PXA Chip selects
  */
@@ -962,7 +951,7 @@
 #define ICCR0_LBM	(1 << 1)	/* Loopback mode */
 #define ICCR0_ITR	(1 << 0)	/* IrDA transmission */
 
-#ifdef CONFIG_CPU_BULVERDE
+#ifdef CONFIG_PXA27x
 #define ICCR2_RXP       (1 << 3)	/* Receive Pin Polarity select */
 #define ICCR2_TXP       (1 << 2)	/* Transmit Pin Polarity select */
 #define ICCR2_TRIG	(3 << 0)	/* Receive FIFO Trigger threshold */
@@ -971,7 +960,7 @@
 #define ICCR2_TRIG_32   (2 << 0)	/*	>= 32 bytes */
 #endif
 
-#ifdef CONFIG_CPU_BULVERDE
+#ifdef CONFIG_PXA27x
 #define ICSR0_EOC	(1 << 6)	/* DMA End of Descriptor Chain */
 #endif
 #define ICSR0_FRE	(1 << 5)	/* Framing error */
@@ -1134,15 +1123,15 @@
 #define _GEDR(x)	__REG2(0x40E00048, ((x) & 0x60) >> 3)
 #define _GAFR(x)	__REG2(0x40E00054, ((x) & 0x70) >> 2)
 
-#define GPLR(x) 	((((x) & 0x7f) < 96) ? _GPLR(x) : GPLR3)
-#define GPDR(x)		((((x) & 0x7f) < 96) ? _GPDR(x) : GPDR3)
-#define GPSR(x)		((((x) & 0x7f) < 96) ? _GPSR(x) : GPSR3)
-#define GPCR(x)		((((x) & 0x7f) < 96) ? _GPCR(x) : GPCR3)
-#define GRER(x)		((((x) & 0x7f) < 96) ? _GRER(x) : GRER3)
-#define GFER(x)		((((x) & 0x7f) < 96) ? _GFER(x) : GFER3)
-#define GEDR(x)		((((x) & 0x7f) < 96) ? _GEDR(x) : GEDR3)
-#define GAFR(x)		((((x) & 0x7f) < 96) ? _GAFR(x) : \
-			 ((((x) & 0x7f) < 112) ? GAFR3_L : GAFR3_U))
+#define GPLR(x) 	(*((((x) & 0x7f) < 96) ? &_GPLR(x) : &GPLR3))
+#define GPDR(x)		(*((((x) & 0x7f) < 96) ? &_GPDR(x) : &GPDR3))
+#define GPSR(x)		(*((((x) & 0x7f) < 96) ? &_GPSR(x) : &GPSR3))
+#define GPCR(x)		(*((((x) & 0x7f) < 96) ? &_GPCR(x) : &GPCR3))
+#define GRER(x)		(*((((x) & 0x7f) < 96) ? &_GRER(x) : &GRER3))
+#define GFER(x)		(*((((x) & 0x7f) < 96) ? &_GFER(x) : &GFER3))
+#define GEDR(x)		(*((((x) & 0x7f) < 96) ? &_GEDR(x) : &GEDR3))
+#define GAFR(x)		(*((((x) & 0x7f) < 96) ? &_GAFR(x) : \
+			 ((((x) & 0x7f) < 112) ? &GAFR3_L : &GAFR3_U)))
 #else
 
 #define GPLR(x)		__REG2(0x40E00000, ((x) & 0x60) >> 3)
@@ -1185,6 +1174,7 @@
 #define GPIO30_SDATA_OUT	30	/* AC97/I2S Sdata_out */
 #define GPIO31_SYNC		31	/* AC97/I2S sync */
 #define GPIO32_SDATA_IN1	32	/* AC97 Sdata_in1 */
+#define GPIO32_MMCCLK		32	/* MMC Clock (PXA270) */
 #define GPIO33_nCS_5		33	/* chip select 5 */
 #define GPIO34_FFRXD		34	/* FFUART receive */
 #define GPIO34_MMCCS0		34	/* MMC Chip Select 0 */
@@ -1213,6 +1203,7 @@
 #define GPIO53_MMCCLK		53	/* MMC Clock */
 #define GPIO54_MMCCLK		54	/* MMC Clock */
 #define GPIO54_pSKTSEL		54	/* Socket Select for Card Space */
+#define GPIO54_nPCE_2		54	/* Card Enable for Card Space (PXA27x) */
 #define GPIO55_nPREG		55	/* Card Address bit 26 */
 #define GPIO56_nPWAIT		56	/* Wait signal for Card Space */
 #define GPIO57_nIOIS16		57	/* Bus Width select for I/O Card Space */
@@ -1247,6 +1238,15 @@
 #define GPIO78_nCS_2		78	/* chip select 2 */
 #define GPIO79_nCS_3		79	/* chip select 3 */
 #define GPIO80_nCS_4		80	/* chip select 4 */
+#define GPIO85_nPCE_1		85	/* Card Enable for Card Space (PXA27x) */
+#define GPIO92_MMCDAT0		92	/* MMC DAT0 (PXA27x) */
+#define GPIO109_MMCDAT1		109	/* MMC DAT1 (PXA27x) */
+#define GPIO110_MMCDAT2		110	/* MMC DAT2 (PXA27x) */
+#define GPIO110_MMCCS0		110	/* MMC Chip Select 0 (PXA27x) */
+#define GPIO111_MMCDAT3		111	/* MMC DAT3 (PXA27x) */
+#define GPIO111_MMCCS1		111	/* MMC Chip Select 1 (PXA27x) */
+#define GPIO112_MMCCMD		112	/* MMC CMD (PXA27x) */
+#define GPIO113_AC97_RESET_N	113	/* AC97 NRESET on (PXA27x) */
 
 /* GPIO alternate function mode & direction */
 
@@ -1292,6 +1292,7 @@
 #define GPIO31_SYNC_AC97_MD	(31 | GPIO_ALT_FN_2_OUT)
 #define GPIO31_SYNC_I2S_MD	(31 | GPIO_ALT_FN_1_OUT)
 #define GPIO32_SDATA_IN1_AC97_MD	(32 | GPIO_ALT_FN_1_IN)
+#define GPIO32_MMCCLK_MD		( 32 | GPIO_ALT_FN_2_OUT)
 #define GPIO33_nCS_5_MD		(33 | GPIO_ALT_FN_2_OUT)
 #define GPIO34_FFRXD_MD		(34 | GPIO_ALT_FN_1_IN)
 #define GPIO34_MMCCS0_MD	(34 | GPIO_ALT_FN_2_OUT)
@@ -1319,6 +1320,7 @@
 #define GPIO53_nPCE_2_MD	(53 | GPIO_ALT_FN_2_OUT)
 #define GPIO53_MMCCLK_MD	(53 | GPIO_ALT_FN_1_OUT)
 #define GPIO54_MMCCLK_MD	(54 | GPIO_ALT_FN_1_OUT)
+#define GPIO54_nPCE_2_MD	(54 | GPIO_ALT_FN_2_OUT)
 #define GPIO54_pSKTSEL_MD	(54 | GPIO_ALT_FN_2_OUT)
 #define GPIO55_nPREG_MD		(55 | GPIO_ALT_FN_2_OUT)
 #define GPIO56_nPWAIT_MD	(56 | GPIO_ALT_FN_1_IN)
@@ -1353,7 +1355,17 @@
 #define GPIO77_LCD_ACBIAS_MD	(77 | GPIO_ALT_FN_2_OUT)
 #define GPIO78_nCS_2_MD		(78 | GPIO_ALT_FN_2_OUT)
 #define GPIO79_nCS_3_MD		(79 | GPIO_ALT_FN_2_OUT)
+#define GPIO79_pSKTSEL_MD	(79 | GPIO_ALT_FN_1_OUT)
 #define GPIO80_nCS_4_MD		(80 | GPIO_ALT_FN_2_OUT)
+#define GPIO85_nPCE_1_MD	(85 | GPIO_ALT_FN_1_OUT)
+#define GPIO92_MMCDAT0_MD	(92 | GPIO_ALT_FN_1_OUT)
+#define GPIO109_MMCDAT1_MD	(109 | GPIO_ALT_FN_1_OUT)
+#define GPIO110_MMCDAT2_MD	(110 | GPIO_ALT_FN_1_OUT)
+#define GPIO110_MMCCS0_MD	(110 | GPIO_ALT_FN_1_OUT)
+#define GPIO111_MMCDAT3_MD	(111 | GPIO_ALT_FN_1_OUT)
+#define GPIO110_MMCCS1_MD	(111 | GPIO_ALT_FN_1_OUT)
+#define GPIO112_MMCCMD_MD	(112 | GPIO_ALT_FN_1_OUT)
+#define GPIO113_AC97_RESET_N_MD	(113 | GPIO_ALT_FN_2_OUT)
 
 
 /*
diff -Nru a/include/asm-arm/arch-pxa/serial.h b/include/asm-arm/arch-pxa/serial.h
--- a/include/asm-arm/arch-pxa/serial.h	2004-10-18 14:56:31 -07:00
+++ b/include/asm-arm/arch-pxa/serial.h	2004-10-18 14:56:31 -07:00
@@ -9,6 +9,7 @@
  * published by the Free Software Foundation.
  */
 
+#include <asm/arch/pxa-regs.h>
 
 #define BAUD_BASE	921600
 
diff -Nru a/include/asm-arm/arch-pxa/system.h b/include/asm-arm/arch-pxa/system.h
--- a/include/asm-arm/arch-pxa/system.h	2004-10-18 14:56:28 -07:00
+++ b/include/asm-arm/arch-pxa/system.h	2004-10-18 14:56:28 -07:00
@@ -11,6 +11,7 @@
  */
 
 #include "hardware.h"
+#include "pxa-regs.h"
 
 static inline void arch_idle(void)
 {
diff -Nru a/include/asm-arm/arch-pxa/uncompress.h b/include/asm-arm/arch-pxa/uncompress.h
--- a/include/asm-arm/arch-pxa/uncompress.h	2004-10-18 14:55:54 -07:00
+++ b/include/asm-arm/arch-pxa/uncompress.h	2004-10-18 14:55:54 -07:00
@@ -25,7 +25,7 @@
 /*
  * This does not append a newline
  */
-static void puts(const char *s)
+static void putstr(const char *s)
 {
 	while (*s) {
 		putc(*s);
diff -Nru a/include/asm-arm/arch-rpc/io.h b/include/asm-arm/arch-rpc/io.h
--- a/include/asm-arm/arch-rpc/io.h	2004-10-18 14:56:33 -07:00
+++ b/include/asm-arm/arch-rpc/io.h	2004-10-18 14:56:33 -07:00
@@ -22,40 +22,40 @@
  */
 #define __arch_base_getb(b,o)			\
  ({						\
-	unsigned int v, r = (b);		\
+	unsigned int __v, __r = (b);		\
 	__asm__ __volatile__(			\
 		"ldrb	%0, [%1, %2]"		\
-		: "=r" (v)			\
-		: "r" (r), "Ir" (o));		\
-	v;					\
+		: "=r" (__v)			\
+		: "r" (__r), "Ir" (o));		\
+	__v;					\
  })
 
 #define __arch_base_getl(b,o)			\
  ({						\
-	unsigned int v, r = (b);		\
+	unsigned int __v, __r = (b);		\
 	__asm__ __volatile__(			\
 		"ldr	%0, [%1, %2]"		\
-		: "=r" (v)			\
-		: "r" (r), "Ir" (o));		\
-	v;					\
+		: "=r" (__v)			\
+		: "r" (__r), "Ir" (o));		\
+	__v;					\
  })
 
 #define __arch_base_putb(v,b,o)			\
  ({						\
-	unsigned int r = (b);			\
+	unsigned int __r = (b);			\
 	__asm__ __volatile__(			\
 		"strb	%0, [%1, %2]"		\
 		:				\
-		: "r" (v), "r" (r), "Ir" (o));	\
+		: "r" (v), "r" (__r), "Ir" (o));\
  })
 
 #define __arch_base_putl(v,b,o)			\
  ({						\
-	unsigned int r = (b);			\
+	unsigned int __r = (b);			\
 	__asm__ __volatile__(			\
 		"str	%0, [%1, %2]"		\
 		:				\
-		: "r" (v), "r" (r), "Ir" (o));	\
+		: "r" (v), "r" (__r), "Ir" (o));\
  })
 
 /*
@@ -176,15 +176,15 @@
 
 #define __outwc(value,port)							\
 ({										\
-	unsigned long v = value;						\
+	unsigned long __v = value;						\
 	if (__PORT_PCIO((port)))						\
 		__asm__ __volatile__(						\
 		"str	%0, [%1, %2]	@ outwc"				\
-		: : "r" (v|v<<16), "r" (PCIO_BASE), "Jr" ((port) << 2));	\
+		: : "r" (__v|__v<<16), "r" (PCIO_BASE), "Jr" ((port) << 2));	\
 	else									\
 		__asm__ __volatile__(						\
 		"str	%0, [%1, %2]	@ outwc"				\
-		: : "r" (v|v<<16), "r" (IO_BASE), "r" ((port) << 2));		\
+		: : "r" (__v|__v<<16), "r" (IO_BASE), "r" ((port) << 2));		\
 })
 
 #define __inwc(port)								\
@@ -203,15 +203,15 @@
 
 #define __outlc(value,port)							\
 ({										\
-	unsigned long v = value;						\
+	unsigned long __v = value;						\
 	if (__PORT_PCIO((port)))						\
 		__asm__ __volatile__(						\
 		"str	%0, [%1, %2]	@ outlc"				\
-		: : "r" (v), "r" (PCIO_BASE), "Jr" ((port) << 2));		\
+		: : "r" (__v), "r" (PCIO_BASE), "Jr" ((port) << 2));		\
 	else									\
 		__asm__ __volatile__(						\
 		"str	%0, [%1, %2]	@ outlc"				\
-		: : "r" (v), "r" (IO_BASE), "r" ((port) << 2));			\
+		: : "r" (__v), "r" (IO_BASE), "r" ((port) << 2));			\
 })
 
 #define __inlc(port)								\
@@ -250,6 +250,6 @@
 /*
  * 1:1 mapping for ioremapped regions.
  */
-#define __mem_pci(x)	(x)
+#define __mem_pci(x)	((unsigned long)(x))
 
 #endif
diff -Nru a/include/asm-arm/arch-rpc/uncompress.h b/include/asm-arm/arch-rpc/uncompress.h
--- a/include/asm-arm/arch-rpc/uncompress.h	2004-10-18 14:56:32 -07:00
+++ b/include/asm-arm/arch-rpc/uncompress.h	2004-10-18 14:56:32 -07:00
@@ -60,14 +60,14 @@
  * params_phys is a linker defined symbol - see
  * arch/arm/boot/compressed/Makefile
  */
-extern struct param_struct params_phys;
-#define params (&params_phys)
+extern __attribute__((pure)) struct param_struct *params(void);
+#define params (params())
 
 #ifndef STANDALONE_DEBUG 
 /*
  * This does not append a newline
  */
-static void puts(const char *s)
+static void putstr(const char *s)
 {
 	extern void ll_write_char(char *, char c, char white);
 	int x,y;
diff -Nru a/include/asm-arm/arch-s3c2410/bast-cpld.h b/include/asm-arm/arch-s3c2410/bast-cpld.h
--- a/include/asm-arm/arch-s3c2410/bast-cpld.h	2004-10-18 14:57:04 -07:00
+++ b/include/asm-arm/arch-s3c2410/bast-cpld.h	2004-10-18 14:57:04 -07:00
@@ -1,6 +1,6 @@
 /* linux/include/asm-arm/arch-s3c2410/bast-cpld.h
  *
- * (c) 2003 Simtec Electronics
+ * (c) 2003,2004 Simtec Electronics
  *  Ben Dooks <ben@simtec.co.uk>
  *
  * BAST - CPLD control constants
@@ -11,15 +11,48 @@
  *
  * Changelog:
  *  25-May-2003 BJD  Created file, added CTRL1 registers
+ *  30-Aug-2004 BJD  Updated definitions from 2.4.26 port
+ *  30-Aug-2004 BJD  Added CTRL3 and CTRL4 definitions
 */
 
 #ifndef __ASM_ARCH_BASTCPLD_H
 #define __ASM_ARCH_BASTCPLD_H
 
+/* CTRL1 - Audio LR routing */
+
 #define BAST_CPLD_CTRL1_LRCOFF	    (0x00)
 #define BAST_CPLD_CTRL1_LRCADC	    (0x01)
 #define BAST_CPLD_CTRL1_LRCDAC	    (0x02)
 #define BAST_CPLD_CTRL1_LRCARM	    (0x03)
 #define BAST_CPLD_CTRL1_LRMASK	    (0x03)
+
+/* CTRL2 - NAND WP control, IDE Reset assert/check */
+
+#define BAST_CPLD_CTRL2_WNAND       (0x04)
+#define BAST_CPLD_CTLR2_IDERST      (0x08)
+
+/* CTRL3 - rom write control, CPLD identity */
+
+#define BAST_CPLD_CTRL3_IDMASK      (0x0e)
+#define BAST_CPLD_CTRL3_ROMWEN      (0x01)
+
+/* CTRL4 - 8bit LCD interface control/status */
+
+#define BAST_CPLD_CTRL4_LLAT	    (0x01)
+#define BAST_CPLD_CTRL4_LCDRW	    (0x02)
+#define BAST_CPLD_CTRL4_LCDCMD	    (0x04)
+#define BAST_CPLD_CTRL4_LCDE2	    (0x01)
+
+/* CTRL5 - DMA routing */
+
+#define BAST_CPLD_DMA0_PRIIDE      (0<<0)
+#define BAST_CPLD_DMA0_SECIDE      (1<<0)
+#define BAST_CPLD_DMA0_ISA15       (2<<0)
+#define BAST_CPLD_DMA0_ISA36       (3<<0)
+
+#define BAST_CPLD_DMA1_PRIIDE      (0<<2)
+#define BAST_CPLD_DMA1_SECIDE      (1<<2)
+#define BAST_CPLD_DMA1_ISA15       (2<<2)
+#define BAST_CPLD_DMA1_ISA36       (3<<2)
 
 #endif /* __ASM_ARCH_BASTCPLD_H */
diff -Nru a/include/asm-arm/arch-s3c2410/bast-irq.h b/include/asm-arm/arch-s3c2410/bast-irq.h
--- a/include/asm-arm/arch-s3c2410/bast-irq.h	2004-10-18 14:56:48 -07:00
+++ b/include/asm-arm/arch-s3c2410/bast-irq.h	2004-10-18 14:56:48 -07:00
@@ -10,6 +10,7 @@
  * published by the Free Software Foundation.
  *
  * Changelog:
+ *  14-Sep-2004 BJD  Fixed IRQ_USBOC definition
  *  06-Jan-2003 BJD  Linux 2.6.0 version
  */
 
@@ -18,7 +19,7 @@
 
 /* irq numbers to onboard peripherals */
 
-#define IRQ_USBOC      IRQ_EINT19
+#define IRQ_USBOC      IRQ_EINT18
 #define IRQ_IDE0       IRQ_EINT16
 #define IRQ_IDE1       IRQ_EINT17
 #define IRQ_PCSERIAL1  IRQ_EINT15
diff -Nru a/include/asm-arm/arch-s3c2410/dma.h b/include/asm-arm/arch-s3c2410/dma.h
--- a/include/asm-arm/arch-s3c2410/dma.h	2004-10-18 14:56:28 -07:00
+++ b/include/asm-arm/arch-s3c2410/dma.h	2004-10-18 14:56:28 -07:00
@@ -27,7 +27,7 @@
  *
  */
 #define MAX_DMA_ADDRESS		0x20000000
-#define MAX_DMA_TRANSFER_SIZE	0x100000 /* Data Unit is half word  */
+#define MAX_DMA_TRANSFER_SIZE   0x100000 /* Data Unit is half word  */
 
 
 /* according to the samsung port, we cannot use the regular
@@ -39,131 +39,282 @@
 
 
 /* we have 4 dma channels */
-#define S3C2410_DMA_CHANNELS	    (4)
+#define S3C2410_DMA_CHANNELS        (4)
 
+/* types */
+
+typedef enum {
+	S3C2410_DMA_IDLE,
+	S3C2410_DMA_RUNNING,
+	S3C2410_DMA_PAUSED
+} s3c2410_dma_state_t;
+
+
+/* s3c2410_dma_loadst_t
+ *
+ * This represents the state of the DMA engine, wrt to the loaded / running
+ * transfers. Since we don't have any way of knowing exactly the state of
+ * the DMA transfers, we need to know the state to make decisions on wether
+ * we can
+ *
+ * S3C2410_DMA_NONE
+ *
+ * There are no buffers loaded (the channel should be inactive)
+ *
+ * S3C2410_DMA_1LOADED
+ *
+ * There is one buffer loaded, however it has not been confirmed to be
+ * loaded by the DMA engine. This may be because the channel is not
+ * yet running, or the DMA driver decided that it was too costly to
+ * sit and wait for it to happen.
+ *
+ * S3C2410_DMA_1RUNNING
+ *
+ * The buffer has been confirmed running, and not finisged
+ *
+ * S3C2410_DMA_1LOADED_1RUNNING
+ *
+ * There is a buffer waiting to be loaded by the DMA engine, and one
+ * currently running.
+*/
+
+typedef enum {
+	S3C2410_DMALOAD_NONE,
+	S3C2410_DMALOAD_1LOADED,
+	S3C2410_DMALOAD_1RUNNING,
+	S3C2410_DMALOAD_1LOADED_1RUNNING,
+} s3c2410_dma_loadst_t;
+
+typedef enum {
+	S3C2410_RES_OK,
+	S3C2410_RES_ERR,
+	S3C2410_RES_ABORT
+} s3c2410_dma_buffresult_t;
+
+
+typedef enum s3c2410_dmasrc_e s3c2410_dmasrc_t;
+
+enum s3c2410_dmasrc_e {
+	S3C2410_DMASRC_HW,      /* source is memory */
+	S3C2410_DMASRC_MEM      /* source is hardware */
+};
+
+/* enum s3c2410_chan_op_e
+ *
+ * operation codes passed to the DMA code by the user, and also used
+ * to inform the current channel owner of any changes to the system state
+*/
+
+enum s3c2410_chan_op_e {
+	S3C2410_DMAOP_START,
+	S3C2410_DMAOP_STOP,
+	S3C2410_DMAOP_PAUSE,
+	S3C2410_DMAOP_RESUME,
+	S3C2410_DMAOP_FLUSH,
+	S3C2410_DMAOP_TIMEOUT,           /* internal signal to handler */
+};
+
+typedef enum s3c2410_chan_op_e s3c2410_chan_op_t;
+
+/* flags */
+
+#define S3C2410_DMAF_SLOW         (1<<0)   /* slow, so don't worry about
+					    * waiting for reloads */
+#define S3C2410_DMAF_AUTOSTART    (1<<1)   /* auto-start if buffer queued */
 
 /* dma buffer */
 
 typedef struct s3c2410_dma_buf_s s3c2410_dma_buf_t;
 
+struct s3c2410_dma_client {
+	char                *name;
+};
+
+typedef struct s3c2410_dma_client s3c2410_dma_client_t;
+
+/* s3c2410_dma_buf_s
+ *
+ * internally used buffer structure to describe a queued or running
+ * buffer.
+*/
+
 struct s3c2410_dma_buf_s {
 	s3c2410_dma_buf_t   *next;
-	int		     magic;	   /* magic */
-	int		     size;	   /* buffer size in bytes */
-	dma_addr_t	     data;	   /* start of DMA data */
-	dma_addr_t	     ptr;	   /* where the DMA got to [1] */
-	int		     ref;
-	void		     *id;	   /* client's id */
-	unsigned char	     no_callback;  /* disable callback for buffer */
+	int                  magic;        /* magic */
+	int                  size;         /* buffer size in bytes */
+	dma_addr_t           data;         /* start of DMA data */
+	dma_addr_t           ptr;          /* where the DMA got to [1] */
+	void                *id;           /* client's id */
 };
 
 /* [1] is this updated for both recv/send modes? */
 
 typedef struct s3c2410_dma_chan_s s3c2410_dma_chan_t;
 
-typedef void (*s3c2410_dma_cbfn_t)(s3c2410_dma_chan_t *, void *buf, int size);
-typedef void (*s3c2410_dma_enfn_t)(s3c2410_dma_chan_t *, int on);
-typedef void (*s3c2410_dma_pausefn_t)(s3c2410_dma_chan_t *, int on);
+/* s3c2410_dma_cbfn_t
+ *
+ * buffer callback routine type
+*/
+
+typedef void (*s3c2410_dma_cbfn_t)(s3c2410_dma_chan_t *, void *buf, int size,
+				   s3c2410_dma_buffresult_t result);
+
+typedef int  (*s3c2410_dma_opfn_t)(s3c2410_dma_chan_t *,
+				   s3c2410_chan_op_t );
+
+struct s3c2410_dma_stats_s {
+	unsigned long          loads;
+	unsigned long          timeout_longest;
+	unsigned long          timeout_shortest;
+	unsigned long          timeout_avg;
+	unsigned long          timeout_failed;
+};
+
+typedef struct s3c2410_dma_stats_s s3c2410_dma_stats_t;
+
+/* struct s3c2410_dma_chan_s
+ *
+ * full state information for each DMA channel
+*/
 
 struct s3c2410_dma_chan_s {
-	/* channel state flags */
-	unsigned char	       number;	      /* number of this dma channel */
-	unsigned char	       in_use;	      /* channel allocated */
-	unsigned char	       started;	      /* channel has been started */
-	unsigned char	       stopped;	      /* channel stopped */
-	unsigned char	       sleeping;
-	unsigned char	       xfer_unit;     /* size of an transfer */
-	unsigned char	       irq_claimed;
+	/* channel state flags and information */
+	unsigned char          number;      /* number of this dma channel */
+	unsigned char          in_use;      /* channel allocated */
+	unsigned char          irq_claimed; /* irq claimed for channel */
+	unsigned char          irq_enabled; /* irq enabled for channel */
+	unsigned char          xfer_unit;   /* size of an transfer */
+
+	/* channel state */
+
+	s3c2410_dma_state_t    state;
+	s3c2410_dma_loadst_t   load_state;
+	s3c2410_dma_client_t  *client;
+
+	/* channel configuration */
+	s3c2410_dmasrc_t       source;
+	unsigned long          dev_addr;
+	unsigned long          load_timeout;
+	unsigned int           flags;        /* channel flags */
 
 	/* channel's hardware position and configuration */
-	unsigned long	       regs;	      /* channels registers */
-	unsigned int	       irq;	      /* channel irq */
-	unsigned long	       addr_reg;      /* data address register for buffs */
-	unsigned long	       dcon;	      /* default value of DCON */
-
-	/* driver handlers for channel */
-	s3c2410_dma_cbfn_t     callback_fn;   /* callback function for buf-done */
-	s3c2410_dma_enfn_t     enable_fn;     /* channel enable function */
-	s3c2410_dma_pausefn_t  pause_fn;      /* channel pause function */
+	unsigned long          regs;         /* channels registers */
+	unsigned int           irq;          /* channel irq */
+	unsigned long          addr_reg;     /* data address register */
+	unsigned long          dcon;         /* default value of DCON */
+
+	/* driver handles */
+	s3c2410_dma_cbfn_t     callback_fn;  /* buffer done callback */
+	s3c2410_dma_opfn_t     op_fn;        /* channel operation callback */
+
+	/* stats gathering */
+	s3c2410_dma_stats_t   *stats;
+	s3c2410_dma_stats_t    stats_store;
 
 	/* buffer list and information */
-	s3c2410_dma_buf_t      *curr;	      /* current dma buffer */
-	s3c2410_dma_buf_t      *next;	      /* next buffer to load */
-	s3c2410_dma_buf_t      *end;	      /* end of queue */
-
-	int		       queue_count;   /* number of items in queue */
-	int		       loaded_count;  /* number of loaded buffers */
+	s3c2410_dma_buf_t      *curr;        /* current dma buffer */
+	s3c2410_dma_buf_t      *next;        /* next buffer to load */
+	s3c2410_dma_buf_t      *end;         /* end of queue */
 };
 
-/* note, we don't really use dma_deivce_t at the moment */
+/* the currently allocated channel information */
+extern s3c2410_dma_chan_t s3c2410_chans[];
+
+/* note, we don't really use dma_device_t at the moment */
 typedef unsigned long dma_device_t;
 
-typedef enum s3c2410_dmasrc_e s3c2410_dmasrc_t;
+/* functions --------------------------------------------------------------- */
 
-/* these two defines control the source for the dma channel,
- * wether it is from memory or an device
+/* s3c2410_dma_request
+ *
+ * request a dma channel exclusivley
 */
 
-enum s3c2410_dmasrc_e {
-  S3C2410_DMASRC_HW,	  /* source is memory */
-  S3C2410_DMASRC_MEM	  /* source is hardware */
-};
+extern int s3c2410_dma_request(dmach_t channel,
+			       s3c2410_dma_client_t *, void *dev);
 
-/* dma control routines */
 
-extern int s3c2410_request_dma(dmach_t channel, const char *devid, void *dev);
-extern int s3c2410_free_dma(dmach_t channel);
-extern int s3c2410_dma_flush_all(dmach_t channel);
+/* s3c2410_dma_ctrl
+ *
+ * change the state of the dma channel
+*/
 
-extern int s3c2410_dma_stop(dmach_t channel);
-extern int s3c2410_dma_resume(dmach_t channel);
+extern int s3c2410_dma_ctrl(dmach_t channel, s3c2410_chan_op_t op);
 
-extern int s3c2410_dma_queue(dmach_t channel, void *id,
-			     dma_addr_t data, int size);
+/* s3c2410_dma_setflags
+ *
+ * set the channel's flags to a given state
+*/
 
-#define s3c2410_dma_queue_buffer s3c2410_dma_queue
+extern int s3c2410_dma_setflags(dmach_t channel,
+				unsigned int flags);
 
-/* channel configuration */
+/* s3c2410_dma_free
+ *
+ * free the dma channel (will also abort any outstanding operations)
+*/
+
+extern int s3c2410_dma_free(dmach_t channel, s3c2410_dma_client_t *);
+
+/* s3c2410_dma_enqueue
+ *
+ * place the given buffer onto the queue of operations for the channel.
+ * The buffer must be allocated from dma coherent memory, or the Dcache/WB
+ * drained before the buffer is given to the DMA system.
+*/
+
+extern int s3c2410_dma_enqueue(dmach_t channel, void *id,
+			       dma_addr_t data, int size);
+
+/* s3c2410_dma_config
+ *
+ * configure the dma channel
+*/
 
 extern int s3c2410_dma_config(dmach_t channel, int xferunit, int dcon);
 
+/* s3c2410_dma_devconfig
+ *
+ * configure the device we're talking to
+*/
+
 extern int s3c2410_dma_devconfig(int channel, s3c2410_dmasrc_t source,
 				 int hwcfg, unsigned long devaddr);
 
-extern int s3c2410_dma_set_enablefn(dmach_t, s3c2410_dma_enfn_t rtn);
-extern int s3c2410_dma_set_pausefn(dmach_t, s3c2410_dma_pausefn_t rtn);
-extern int s3c2410_dma_set_callbackfn(dmach_t, s3c2410_dma_cbfn_t rtn);
-
-#define s3c2410_dma_set_callback s3c2410_dma_set_callbackfn
-
-#define S3C2410_DMA_DISRC	(0x00)
-#define S3C2410_DMA_DISRCC	(0x04)
-#define S3C2410_DMA_DIDST	(0x08)
-#define S3C2410_DMA_DIDSTC	(0x0C)
-#define S3C2410_DMA_DCON	(0x10)
-#define S3C2410_DMA_DSTAT	(0x14)
-#define S3C2410_DMA_DCSRC	(0x18)
-#define S3C2410_DMA_DCDST	(0x1C)
-#define S3C2410_DMA_DMASKTRIG	(0x20)
+extern int s3c2410_dma_set_opfn(dmach_t, s3c2410_dma_opfn_t rtn);
+extern int s3c2410_dma_set_buffdone_fn(dmach_t, s3c2410_dma_cbfn_t rtn);
+
+/* DMA Register definitions */
+
+#define S3C2410_DMA_DISRC       (0x00)
+#define S3C2410_DMA_DISRCC      (0x04)
+#define S3C2410_DMA_DIDST       (0x08)
+#define S3C2410_DMA_DIDSTC      (0x0C)
+#define S3C2410_DMA_DCON        (0x10)
+#define S3C2410_DMA_DSTAT       (0x14)
+#define S3C2410_DMA_DCSRC       (0x18)
+#define S3C2410_DMA_DCDST       (0x1C)
+#define S3C2410_DMA_DMASKTRIG   (0x20)
 
-#define S3C2410_DMASKTRIG_STOP	 (1<<2)
-#define S3C2410_DMASKTRIG_ON	 (1<<1)
+#define S3C2410_DMASKTRIG_STOP   (1<<2)
+#define S3C2410_DMASKTRIG_ON     (1<<1)
 #define S3C2410_DMASKTRIG_SWTRIG (1<<0)
 
-#define S3C2410_DCOM_DEMAND	(0<<31)
+#define S3C2410_DCOM_DEMAND     (0<<31)
 #define S3C2410_DCON_HANDSHAKE  (1<<31)
 #define S3C2410_DCON_SYNC_PCLK  (0<<30)
 #define S3C2410_DCON_SYNC_HCLK  (1<<30)
 
-#define S3C2410_DCON_INTREQ	(1<<29)
+#define S3C2410_DCON_INTREQ     (1<<29)
 
-#define S3C2410_DCON_SRCSHIFT	(24)
+#define S3C2410_DCON_SRCSHIFT   (24)
 
-#define S3C2410_DCON_BYTE	(0<<20)
-#define S3C2410_DCON_HALFWORD	(1<<20)
-#define S3C2410_DCON_WORD	(2<<20)
+#define S3C2410_DCON_BYTE       (0<<20)
+#define S3C2410_DCON_HALFWORD   (1<<20)
+#define S3C2410_DCON_WORD       (2<<20)
 
 #define S3C2410_DCON_AUTORELOAD (0<<22)
-#define S3C2410_DCON_HWTRIG	(1<<23)
+#define S3C2410_DCON_NORELOAD   (1<<22)
+#define S3C2410_DCON_HWTRIG     (1<<23)
 
 #endif /* __ASM_ARCH_DMA_H */
diff -Nru a/include/asm-arm/arch-s3c2410/hardware.h b/include/asm-arm/arch-s3c2410/hardware.h
--- a/include/asm-arm/arch-s3c2410/hardware.h	2004-10-18 14:56:29 -07:00
+++ b/include/asm-arm/arch-s3c2410/hardware.h	2004-10-18 14:56:29 -07:00
@@ -14,6 +14,8 @@
  *  06-Jun-2003 BJD  Added CPU frequency settings
  *  03-Sep-2003 BJD  Linux v2.6 support
  *  12-Mar-2004 BJD  Fixed include protection, fixed type of clock vars
+ *  14-Sep-2004 BJD  Added misccr and getpin to gpio
+ *  01-Oct-2004 BJD  Added the new gpio functions
 */
 
 #ifndef __ASM_ARCH_HARDWARE_H
@@ -44,6 +46,35 @@
 
 extern void s3c2410_gpio_cfgpin(unsigned int pin, unsigned int function);
 
+extern unsigned int s3c2410_gpio_getcfg(unsigned int pin);
+
+/* s3c2410_gpio_getirq
+ *
+ * turn the given pin number into the corresponding IRQ number
+ *
+ * returns:
+ *	< 0 = no interrupt for this pin
+ *	>=0 = interrupt number for the pin
+*/
+
+extern int s3c2410_gpio_getirq(unsigned int pin);
+
+/* s3c2410_gpio_irqfilter
+ *
+ * set the irq filtering on the given pin
+ *
+ * on = 0 => disable filtering
+ *      1 => enable filtering
+ *
+ * config = S3C2410_EINTFLT_PCLK or S3C2410_EINTFLT_EXTCLK orred with
+ *          width of filter (0 through 63)
+ *
+ *
+*/
+
+extern int s3c2410_gpio_irqfilter(unsigned int pin, unsigned int on,
+				  unsigned int config);
+
 /* s3c2410_gpio_pullup
  *
  * configure the pull-up control on the given pin
@@ -60,6 +91,10 @@
 extern void s3c2410_gpio_pullup(unsigned int pin, unsigned int to);
 
 extern void s3c2410_gpio_setpin(unsigned int pin, unsigned int to);
+
+extern unsigned int s3c2410_gpio_getpin(unsigned int pin);
+
+extern unsigned int s3c2410_modify_misccr(unsigned int clr, unsigned int chg);
 
 #endif /* __ASSEMBLY__ */
 
diff -Nru a/include/asm-arm/arch-s3c2410/nand.h b/include/asm-arm/arch-s3c2410/nand.h
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/include/asm-arm/arch-s3c2410/nand.h	2004-10-18 14:57:24 -07:00
@@ -0,0 +1,48 @@
+/* linux/include/asm-arm/arch-s3c2410/nand.h
+ *
+ * (c) 2004 Simtec Electronics
+ *  Ben Dooks <ben@simtec.co.uk>
+ *
+ * S3C2410 - NAND device controller platfrom_device info
+ *
+ * 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.
+ *
+ * Changelog:
+ *	23-Sep-2004 BJD  Created file
+*/
+
+/* struct s3c2410_nand_set
+ *
+ * define an set of one or more nand chips registered with an unique mtd
+ *
+ * nr_chips	 = number of chips in this set
+ * nr_partitions = number of partitions pointed to be partitoons (or zero)
+ * name		 = name of set (optional)
+ * nr_map	 = map for low-layer logical to physical chip numbers (option)
+ * partitions	 = mtd partition list
+*/
+
+struct s3c2410_nand_set {
+	int			nr_chips;
+	int			nr_partitions;
+	char			*name;
+	int			*nr_map;
+	struct mtd_partition	*partitions;
+};
+
+struct s3c2410_platform_nand {
+	/* timing information for controller, all times in nanoseconds */
+
+	int	tacls;	/* time for active CLE/ALE to nWE/nOE */
+	int	twrph0;	/* active time for nWE/nOE */
+	int	twrph1;	/* time for release CLE/ALE from nWE/nOE inactive */
+
+	int			nr_sets;
+	struct s3c2410_nand_set *sets;
+
+	void			(*select_chip)(struct s3c2410_nand_set *,
+					       int chip);
+};
+
diff -Nru a/include/asm-arm/arch-s3c2410/param.h b/include/asm-arm/arch-s3c2410/param.h
--- a/include/asm-arm/arch-s3c2410/param.h	2004-10-18 14:57:04 -07:00
+++ b/include/asm-arm/arch-s3c2410/param.h	2004-10-18 14:57:04 -07:00
@@ -22,6 +22,6 @@
  * add a software pre-scaler to the evil timer systems.
 */
 
-#define __KERNEL_HZ   200
+#define HZ   200
 
 #endif /* __ASM_ARCH_PARAM_H */
diff -Nru a/include/asm-arm/arch-s3c2410/regs-clock.h b/include/asm-arm/arch-s3c2410/regs-clock.h
--- a/include/asm-arm/arch-s3c2410/regs-clock.h	2004-10-18 14:55:54 -07:00
+++ b/include/asm-arm/arch-s3c2410/regs-clock.h	2004-10-18 14:55:54 -07:00
@@ -1,6 +1,6 @@
 /* linux/include/asm/arch-s3c2410/regs-clock.h
  *
- * Copyright (c) 2003 Simtec Electronics <linux@simtec.co.uk>
+ * Copyright (c) 2003,2004 Simtec Electronics <linux@simtec.co.uk>
  *		      http://www.simtec.co.uk/products/SWLINUX/
  *
  * This program is free software; you can redistribute it and/or modify
@@ -10,12 +10,13 @@
  * S3C2410 clock register definitions
  *
  *  Changelog:
- *    19-06-2003     BJD     Created file
- *    12-03-2004     BJD     Updated include protection
+ *    18-Aug-2004 Ben Dooks      Added 2440 definitions
+ *    08-Aug-2004 Herbert Pötzl  Added CLKCON definitions
+ *    19-06-2003  Ben Dooks      Created file
+ *    12-03-2004  Ben Dooks      Updated include protection
+ *    29-Sep-2004 Ben Dooks	 Fixed usage for assembly inclusion
  */
 
-
-
 #ifndef __ASM_ARM_REGS_CLOCK
 #define __ASM_ARM_REGS_CLOCK "$Id: clock.h,v 1.4 2003/04/30 14:50:51 ben Exp $"
 
@@ -30,6 +31,24 @@
 #define S3C2410_CLKSLOW	    S3C2410_CLKREG(0x10)
 #define S3C2410_CLKDIVN	    S3C2410_CLKREG(0x14)
 
+#define S3C2410_CLKCON_IDLE	     (1<<2)
+#define S3C2410_CLKCON_POWER	     (1<<3)
+#define S3C2410_CLKCON_NAND	     (1<<4)
+#define S3C2410_CLKCON_LCDC	     (1<<5)
+#define S3C2410_CLKCON_USBH	     (1<<6)
+#define S3C2410_CLKCON_USBD	     (1<<7)
+#define S3C2410_CLKCON_PWMT	     (1<<8)
+#define S3C2410_CLKCON_SDI	     (1<<9)
+#define S3C2410_CLKCON_UART0	     (1<<10)
+#define S3C2410_CLKCON_UART1	     (1<<11)
+#define S3C2410_CLKCON_UART2	     (1<<12)
+#define S3C2410_CLKCON_GPIO	     (1<<13)
+#define S3C2410_CLKCON_RTC	     (1<<14)
+#define S3C2410_CLKCON_ADC	     (1<<15)
+#define S3C2410_CLKCON_IIC	     (1<<16)
+#define S3C2410_CLKCON_IIS	     (1<<17)
+#define S3C2410_CLKCON_SPI	     (1<<18)
+
 #define S3C2410_PLLCON_MDIVSHIFT     12
 #define S3C2410_PLLCON_PDIVSHIFT     4
 #define S3C2410_PLLCON_SDIVSHIFT     0
@@ -53,6 +72,8 @@
 #define S3C2410_CLKDIVN_PDIVN	     (1<<0)
 #define S3C2410_CLKDIVN_HDIVN	     (1<<1)
 
+#ifndef __ASSEMBLY__
+
 static inline unsigned int
 s3c2410_get_pll(int pllval, int baseclk)
 {
@@ -68,5 +89,32 @@
 
   return (baseclk * (mdiv + 8)) / ((pdiv + 2) << sdiv);
 }
+
+#endif /* __ASSEMBLY__ */
+
+#ifdef CONFIG_CPU_S3C2440
+
+/* extra registers */
+#define S3C2440_CAMDIVN	    S3C2410_CLKREG(0x14)
+
+#define S3C2440_CLKCON_CAMERA        (1<<19)
+#define S3C2440_CLKCON_AC97          (1<<20)
+
+#define S3C2440_CLKDIVN_PDIVN	     (1<<0)
+#define S3C2440_CLKDIVN_HDIVN_MASK   (3<<1)
+#define S3C2440_CLKDIVN_HDIVN_1      (0<<1)
+#define S3C2440_CLKDIVN_HDIVN_2      (1<<1)
+#define S3C2440_CLKDIVN_HDIVN_4_8    (2<<1)
+#define S3C2440_CLKDIVN_HDIVN_3_6    (3<<1)
+#define S3C2440_CLKDIVN_UCLK         (1<<3)
+
+#define S3C2440_CAMDIVN_CAMCLK_MASK  (0xf<<0)
+#define S3C2440_CAMDIVN_CAMCLK_SEL   (1<<4)
+#define S3C2440_CAMDIVN_HCLK3_HALF   (1<<8)
+#define S3C2440_CAMDIVN_HCLK4_HALF   (1<<9)
+#define S3C2440_CAMDIVN_DVSEN        (1<<12)
+
+#endif /* CONFIG_CPU_S3C2440 */
+
 
 #endif /* __ASM_ARM_REGS_CLOCK */
diff -Nru a/include/asm-arm/arch-s3c2410/regs-dsc.h b/include/asm-arm/arch-s3c2410/regs-dsc.h
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/include/asm-arm/arch-s3c2410/regs-dsc.h	2004-10-18 14:57:23 -07:00
@@ -0,0 +1,183 @@
+/* linux/include/asm/hardware/s3c2410/regs-dsc.h
+ *
+ * Copyright (c) 2004 Simtec Electronics <linux@simtec.co.uk>
+ *		      http://www.simtec.co.uk/products/SWLINUX/
+ *
+ * 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.
+ *
+ * S3C2440 Signal Drive Strength Control
+ *
+ *  Changelog:
+ *    11-Aug-2004     BJD     Created file
+ *    25-Aug-2004     BJD     Added the _SELECT_* defs for using with functions
+*/
+
+
+#ifndef __ASM_ARCH_REGS_DSC_H
+#define __ASM_ARCH_REGS_DSC_H "2440-dsc"
+
+#ifdef CONFIG_CPU_S3C2440
+
+#define S3C2440_DSC0	   S3C2410_GPIOREG(0xc0)
+#define S3C2440_DSC1	   S3C2410_GPIOREG(0xc4)
+
+#define S3C2440_SELECT_DSC0 (0)
+#define S3C2440_SELECT_DSC1 (1<<31)
+
+#define S3C2440_DSC_GETSHIFT(x) ((x) & 31)
+
+#define S3C2440_DSC0_ENABLE     (1<<31)
+
+#define S3C2440_DSC0_ADDR       (S3C2440_SELECT_DSC0 | 8)
+#define S3C2440_DSC0_ADDR_12mA  (0<<8)
+#define S3C2440_DSC0_ADDR_10mA  (1<<8)
+#define S3C2440_DSC0_ADDR_8mA   (2<<8)
+#define S3C2440_DSC0_ADDR_6mA   (3<<8)
+#define S3C2440_DSC0_ADDR_MASK  (3<<8)
+
+/* D24..D31 */
+#define S3C2440_DSC0_DATA3      (S3C2440_SELECT_DSC0 | 6)
+#define S3C2440_DSC0_DATA3_12mA (0<<6)
+#define S3C2440_DSC0_DATA3_10mA (1<<6)
+#define S3C2440_DSC0_DATA3_8mA  (2<<6)
+#define S3C2440_DSC0_DATA3_6mA  (3<<6)
+#define S3C2440_DSC0_DATA3_MASK (3<<6)
+
+/* D16..D23 */
+#define S3C2440_DSC0_DATA2      (S3C2440_SELECT_DSC0 | 4)
+#define S3C2440_DSC0_DATA2_12mA (0<<4)
+#define S3C2440_DSC0_DATA2_10mA (1<<4)
+#define S3C2440_DSC0_DATA2_8mA  (2<<4)
+#define S3C2440_DSC0_DATA2_6mA  (3<<4)
+#define S3C2440_DSC0_DATA2_MASK (3<<4)
+
+/* D8..D15 */
+#define S3C2440_DSC0_DATA1      (S3C2440_SELECT_DSC0 | 2)
+#define S3C2440_DSC0_DATA1_12mA (0<<2)
+#define S3C2440_DSC0_DATA1_10mA (1<<2)
+#define S3C2440_DSC0_DATA1_8mA  (2<<2)
+#define S3C2440_DSC0_DATA1_6mA  (3<<2)
+#define S3C2440_DSC0_DATA1_MASK (3<<2)
+
+/* D0..D7 */
+#define S3C2440_DSC0_DATA0      (S3C2440_SELECT_DSC0 | 0)
+#define S3C2440_DSC0_DATA0_12mA (0<<0)
+#define S3C2440_DSC0_DATA0_10mA (1<<0)
+#define S3C2440_DSC0_DATA0_8mA  (2<<0)
+#define S3C2440_DSC0_DATA0_6mA  (3<<0)
+#define S3C2440_DSC0_DATA0_MASK (3<<0)
+
+#define S3C2440_DSC1_SCK0       (S3C2440_SELECT_DSC1 | 28)
+#define S3C2440_DSC1_SCK0_12mA  (0<<28)
+#define S3C2440_DSC1_SCK0_10mA  (1<<28)
+#define S3C2440_DSC1_SCK0_8mA   (2<<28)
+#define S3C2440_DSC1_SCK0_6mA   (3<<28)
+#define S3C2440_DSC1_SCK0_MASK  (3<<28)
+
+#define S3C2440_DSC1_SCK1       (S3C2440_SELECT_DSC1 | 26)
+#define S3C2440_DSC1_SCK1_12mA  (0<<26)
+#define S3C2440_DSC1_SCK1_10mA  (1<<26)
+#define S3C2440_DSC1_SCK1_8mA   (2<<26)
+#define S3C2440_DSC1_SCK1_6mA   (3<<26)
+#define S3C2440_DSC1_SCK1_MASK  (3<<26)
+
+#define S3C2440_DSC1_SCKE       (S3C2440_SELECT_DSC1 | 24)
+#define S3C2440_DSC1_SCKE_10mA  (0<<24)
+#define S3C2440_DSC1_SCKE_8mA   (1<<24)
+#define S3C2440_DSC1_SCKE_6mA   (2<<24)
+#define S3C2440_DSC1_SCKE_4mA   (3<<24)
+#define S3C2440_DSC1_SCKE_MASK  (3<<24)
+
+/* SDRAM nRAS/nCAS */
+#define S3C2440_DSC1_SDR        (S3C2440_SELECT_DSC1 | 22)
+#define S3C2440_DSC1_SDR_10mA   (0<<22)
+#define S3C2440_DSC1_SDR_8mA    (1<<22)
+#define S3C2440_DSC1_SDR_6mA    (2<<22)
+#define S3C2440_DSC1_SDR_4mA    (3<<22)
+#define S3C2440_DSC1_SDR_MASK   (3<<22)
+
+/* NAND Flash Controller */
+#define S3C2440_DSC1_NFC        (S3C2440_SELECT_DSC1 | 20)
+#define S3C2440_DSC1_NFC_10mA   (0<<20)
+#define S3C2440_DSC1_NFC_8mA    (1<<20)
+#define S3C2440_DSC1_NFC_6mA    (2<<20)
+#define S3C2440_DSC1_NFC_4mA    (3<<20)
+#define S3C2440_DSC1_NFC_MASK   (3<<20)
+
+/* nBE[0..3] */
+#define S3C2440_DSC1_nBE        (S3C2440_SELECT_DSC1 | 18)
+#define S3C2440_DSC1_nBE_10mA   (0<<18)
+#define S3C2440_DSC1_nBE_8mA    (1<<18)
+#define S3C2440_DSC1_nBE_6mA    (2<<18)
+#define S3C2440_DSC1_nBE_4mA    (3<<18)
+#define S3C2440_DSC1_nBE_MASK   (3<<18)
+
+#define S3C2440_DSC1_WOE        (S3C2440_SELECT_DSC1 | 16)
+#define S3C2440_DSC1_WOE_10mA   (0<<16)
+#define S3C2440_DSC1_WOE_8mA    (1<<16)
+#define S3C2440_DSC1_WOE_6mA    (2<<16)
+#define S3C2440_DSC1_WOE_4mA    (3<<16)
+#define S3C2440_DSC1_WOE_MASK   (3<<16)
+
+#define S3C2440_DSC1_CS7        (S3C2440_SELECT_DSC1 | 14)
+#define S3C2440_DSC1_CS7_10mA   (0<<14)
+#define S3C2440_DSC1_CS7_8mA    (1<<14)
+#define S3C2440_DSC1_CS7_6mA    (2<<14)
+#define S3C2440_DSC1_CS7_4mA    (3<<14)
+#define S3C2440_DSC1_CS7_MASK   (3<<14)
+
+#define S3C2440_DSC1_CS6        (S3C2440_SELECT_DSC1 | 12)
+#define S3C2440_DSC1_CS6_10mA   (0<<12)
+#define S3C2440_DSC1_CS6_8mA    (1<<12)
+#define S3C2440_DSC1_CS6_6mA    (2<<12)
+#define S3C2440_DSC1_CS6_4mA    (3<<12)
+#define S3C2440_DSC1_CS6_MASK   (3<<12)
+
+#define S3C2440_DSC1_CS5        (S3C2440_SELECT_DSC1 | 10)
+#define S3C2440_DSC1_CS5_10mA   (0<<10)
+#define S3C2440_DSC1_CS5_8mA    (1<<10)
+#define S3C2440_DSC1_CS5_6mA    (2<<10)
+#define S3C2440_DSC1_CS5_4mA    (3<<10)
+#define S3C2440_DSC1_CS5_MASK   (3<<10)
+
+#define S3C2440_DSC1_CS4        (S3C2440_SELECT_DSC1 | 8)
+#define S3C2440_DSC1_CS4_10mA   (0<<8)
+#define S3C2440_DSC1_CS4_8mA    (1<<8)
+#define S3C2440_DSC1_CS4_6mA    (2<<8)
+#define S3C2440_DSC1_CS4_4mA    (3<<8)
+#define S3C2440_DSC1_CS4_MASK   (3<<8)
+
+#define S3C2440_DSC1_CS3        (S3C2440_SELECT_DSC1 | 6)
+#define S3C2440_DSC1_CS3_10mA   (0<<6)
+#define S3C2440_DSC1_CS3_8mA    (1<<6)
+#define S3C2440_DSC1_CS3_6mA    (2<<6)
+#define S3C2440_DSC1_CS3_4mA    (3<<6)
+#define S3C2440_DSC1_CS3_MASK   (3<<6)
+
+#define S3C2440_DSC1_CS2        (S3C2440_SELECT_DSC1 | 4)
+#define S3C2440_DSC1_CS2_10mA   (0<<4)
+#define S3C2440_DSC1_CS2_8mA    (1<<4)
+#define S3C2440_DSC1_CS2_6mA    (2<<4)
+#define S3C2440_DSC1_CS2_4mA    (3<<4)
+#define S3C2440_DSC1_CS2_MASK   (3<<4)
+
+#define S3C2440_DSC1_CS1        (S3C2440_SELECT_DSC1 | 2)
+#define S3C2440_DSC1_CS1_10mA   (0<<2)
+#define S3C2440_DSC1_CS1_8mA    (1<<2)
+#define S3C2440_DSC1_CS1_6mA    (2<<2)
+#define S3C2440_DSC1_CS1_4mA    (3<<2)
+#define S3C2440_DSC1_CS1_MASK   (3<<2)
+
+#define S3C2440_DSC1_CS0        (S3C2440_SELECT_DSC1 | 0
+#define S3C2440_DSC1_CS0_10mA   (0<<0)
+#define S3C2440_DSC1_CS0_8mA    (1<<0)
+#define S3C2440_DSC1_CS0_6mA    (2<<0)
+#define S3C2440_DSC1_CS0_4mA    (3<<0)
+#define S3C2440_DSC1_CS0_MASK   (3<<0)
+
+#endif /* CONFIG_CPU_S3C2440 */
+
+#endif	/* __ASM_ARCH_REGS_DSC_H */
+
diff -Nru a/include/asm-arm/arch-s3c2410/regs-gpio.h b/include/asm-arm/arch-s3c2410/regs-gpio.h
--- a/include/asm-arm/arch-s3c2410/regs-gpio.h	2004-10-18 14:56:48 -07:00
+++ b/include/asm-arm/arch-s3c2410/regs-gpio.h	2004-10-18 14:56:48 -07:00
@@ -14,7 +14,8 @@
  *    23-06-2003     BJD     Updated GSTATUS registers
  *    12-03-2004     BJD     Updated include protection
  *    20-07-2004     BJD     Added GPIO pin numbers, added Port A definitions
- */
+ *    04-10-2004     BJD     Fixed number of bugs, added EXT IRQ filter defs
+*/
 
 
 #ifndef __ASM_ARCH_REGS_GPIO_H
@@ -614,34 +615,34 @@
 #define S3C2410_GPG10_OUTP    (0x01 << 20)
 #define S3C2410_GPG10_EINT18  (0x02 << 20)
 
-#define S3C2410_GPG10         S3C2410_GPIONO(S3C2410_GPIO_BANKG, 10)
+#define S3C2410_GPG11         S3C2410_GPIONO(S3C2410_GPIO_BANKG, 11)
 #define S3C2410_GPG11_INP     (0x00 << 22)
 #define S3C2410_GPG11_OUTP    (0x01 << 22)
 #define S3C2410_GPG11_EINT19  (0x02 << 22)
 #define S3C2410_GPG11_TCLK1   (0x03 << 22)
 
-#define S3C2410_GPG10         S3C2410_GPIONO(S3C2410_GPIO_BANKG, 10)
+#define S3C2410_GPG12         S3C2410_GPIONO(S3C2410_GPIO_BANKG, 12)
 #define S3C2410_GPG12_INP     (0x00 << 24)
 #define S3C2410_GPG12_OUTP    (0x01 << 24)
-#define S3C2410_GPG12_EINT18  (0x02 << 24)
+#define S3C2410_GPG12_EINT20  (0x02 << 24)
 #define S3C2410_GPG12_XMON    (0x03 << 24)
 
-#define S3C2410_GPG10         S3C2410_GPIONO(S3C2410_GPIO_BANKG, 10)
+#define S3C2410_GPG13         S3C2410_GPIONO(S3C2410_GPIO_BANKG, 13)
 #define S3C2410_GPG13_INP     (0x00 << 26)
 #define S3C2410_GPG13_OUTP    (0x01 << 26)
-#define S3C2410_GPG13_EINT18  (0x02 << 26)
+#define S3C2410_GPG13_EINT21  (0x02 << 26)
 #define S3C2410_GPG13_nXPON   (0x03 << 26)
 
-#define S3C2410_GPG10         S3C2410_GPIONO(S3C2410_GPIO_BANKG, 10)
+#define S3C2410_GPG14         S3C2410_GPIONO(S3C2410_GPIO_BANKG, 14)
 #define S3C2410_GPG14_INP     (0x00 << 28)
 #define S3C2410_GPG14_OUTP    (0x01 << 28)
-#define S3C2410_GPG14_EINT18  (0x02 << 28)
+#define S3C2410_GPG14_EINT22  (0x02 << 28)
 #define S3C2410_GPG14_YMON    (0x03 << 28)
 
-#define S3C2410_GPG10         S3C2410_GPIONO(S3C2410_GPIO_BANKG, 10)
+#define S3C2410_GPG15         S3C2410_GPIONO(S3C2410_GPIO_BANKG, 15)
 #define S3C2410_GPG15_INP     (0x00 << 30)
 #define S3C2410_GPG15_OUTP    (0x01 << 30)
-#define S3C2410_GPG15_EINT18  (0x02 << 30)
+#define S3C2410_GPG15_EINT23  (0x02 << 30)
 #define S3C2410_GPG15_nYPON   (0x03 << 30)
 
 
@@ -751,6 +752,11 @@
 
 #define S3C2410_MISCCR_nRSTCON	    (1<<16)
 
+#define S3C2410_MISCCR_nEN_SCLK0    (1<<17)
+#define S3C2410_MISCCR_nEN_SCLK1    (1<<18)
+#define S3C2410_MISCCR_nEN_SCLKE    (1<<19)
+#define S3C2410_MISCCR_SDSLEEP	    (7<<17)
+
 /* external interrupt control... */
 /* S3C2410_EXTINT0 -> irq sense control for EINT0..EINT7
  * S3C2410_EXTINT1 -> irq sense control for EINT8..EINT15
@@ -777,6 +783,11 @@
 #define S3C2410_EINFLT1	   S3C2410_GPIOREG(0x98)
 #define S3C2410_EINFLT2	   S3C2410_GPIOREG(0x9C)
 #define S3C2410_EINFLT3	   S3C2410_GPIOREG(0xA0)
+
+/* values for interrupt filtering */
+#define S3C2410_EINTFLT_PCLK		(0x00)
+#define S3C2410_EINTFLT_EXTCLK		(1<<7)
+#define S3C2410_EINTFLT_WIDTHMSK(x)	((x) & 0x3f)
 
 /* removed EINTxxxx defs from here, not meant for this */
 
diff -Nru a/include/asm-arm/arch-s3c2410/regs-gpioj.h b/include/asm-arm/arch-s3c2410/regs-gpioj.h
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/include/asm-arm/arch-s3c2410/regs-gpioj.h	2004-10-18 14:57:24 -07:00
@@ -0,0 +1,100 @@
+/* linux/include/asm/hardware/s3c2410/regs-gpioj.h
+ *
+ * Copyright (c) 2004 Simtec Electronics <linux@simtec.co.uk>
+ *		      http://www.simtec.co.uk/products/SWLINUX/
+ *
+ * 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.
+ *
+ * S3C2440 GPIO J register definitions
+ *
+ *  Changelog:
+ *    11-Aug-2004     BJD     Created file
+*/
+
+
+#ifndef __ASM_ARCH_REGS_GPIOJ_H
+#define __ASM_ARCH_REGS_GPIOJ_H "gpioj"
+
+/* Port J consists of 13 GPIO/Camera pins
+ *
+ * GPJCON has 2 bits for each of the input pins on port F
+ *   00 = 0 input, 1 output, 2 Camera
+ *
+ * pull up works like all other ports.
+*/
+
+#define S3C2440_GPIO_BANKJ  (416)
+
+#define S3C2440_GPJCON	    S3C2410_GPIOREG(0xd0)
+#define S3C2440_GPJDAT	    S3C2410_GPIOREG(0xd4)
+#define S3C2440_GPJUP	    S3C2410_GPIOREG(0xd8)
+
+#define S3C2440_GPJ0            S3C2410_GPIONO(S3C2440_GPIO_BANKJ, 0)
+#define S3C2440_GPJ0_INP        (0x00 << 0)
+#define S3C2440_GPJ0_OUTP       (0x01 << 0)
+#define S3C2440_GPJ0_CAMDATA0   (0x02 << 0)
+
+#define S3C2440_GPJ1            S3C2410_GPIONO(S3C2440_GPIO_BANKJ, 1)
+#define S3C2440_GPJ1_INP        (0x00 << 2)
+#define S3C2440_GPJ1_OUTP       (0x01 << 2)
+#define S3C2440_GPJ1_CAMDATA1   (0x02 << 2)
+
+#define S3C2440_GPJ2            S3C2410_GPIONO(S3C2440_GPIO_BANKJ, 2)
+#define S3C2440_GPJ2_INP        (0x00 << 4)
+#define S3C2440_GPJ2_OUTP       (0x01 << 4)
+#define S3C2440_GPJ2_CAMDATA2   (0x02 << 4)
+
+#define S3C2440_GPJ3            S3C2410_GPIONO(S3C2440_GPIO_BANKJ, 3)
+#define S3C2440_GPJ3_INP        (0x00 << 6)
+#define S3C2440_GPJ3_OUTP       (0x01 << 6)
+#define S3C2440_GPJ3_CAMDATA3   (0x02 << 6)
+
+#define S3C2440_GPJ4            S3C2410_GPIONO(S3C2440_GPIO_BANKJ, 4)
+#define S3C2440_GPJ4_INP        (0x00 << 8)
+#define S3C2440_GPJ4_OUTP       (0x01 << 8)
+#define S3C2440_GPJ4_CAMDATA4   (0x02 << 8)
+
+#define S3C2440_GPJ5            S3C2410_GPIONO(S3C2440_GPIO_BANKJ, 5)
+#define S3C2440_GPJ5_INP        (0x00 << 10)
+#define S3C2440_GPJ5_OUTP       (0x01 << 10)
+#define S3C2440_GPJ5_CAMDATA5   (0x02 << 10)
+
+#define S3C2440_GPJ6            S3C2410_GPIONO(S3C2440_GPIO_BANKJ, 6)
+#define S3C2440_GPJ6_INP        (0x00 << 12)
+#define S3C2440_GPJ6_OUTP       (0x01 << 12)
+#define S3C2440_GPJ6_CAMDATA6   (0x02 << 12)
+
+#define S3C2440_GPJ7            S3C2410_GPIONO(S3C2440_GPIO_BANKJ, 7)
+#define S3C2440_GPJ7_INP        (0x00 << 14)
+#define S3C2440_GPJ7_OUTP       (0x01 << 14)
+#define S3C2440_GPJ7_CAMDATA7   (0x02 << 14)
+
+#define S3C2440_GPJ8            S3C2410_GPIONO(S3C2440_GPIO_BANKJ, 8)
+#define S3C2440_GPJ8_INP        (0x00 << 16)
+#define S3C2440_GPJ8_OUTP       (0x01 << 16)
+#define S3C2440_GPJ8_CAMPCLK    (0x02 << 16)
+
+#define S3C2440_GPJ9            S3C2410_GPIONO(S3C2440_GPIO_BANKJ, 9)
+#define S3C2440_GPJ9_INP        (0x00 << 18)
+#define S3C2440_GPJ9_OUTP       (0x01 << 18)
+#define S3C2440_GPJ9_CAMVSYNC   (0x02 << 18)
+
+#define S3C2440_GPJ10           S3C2410_GPIONO(S3C2440_GPIO_BANKJ, 10)
+#define S3C2440_GPJ10_INP       (0x00 << 20)
+#define S3C2440_GPJ10_OUTP      (0x01 << 20)
+#define S3C2440_GPJ10_CAMHREF   (0x02 << 20)
+
+#define S3C2440_GPJ11           S3C2410_GPIONO(S3C2440_GPIO_BANKJ, 11)
+#define S3C2440_GPJ11_INP       (0x00 << 22)
+#define S3C2440_GPJ11_OUTP      (0x01 << 22)
+#define S3C2440_GPJ11_CAMCLKOUT (0x02 << 22)
+
+#define S3C2440_GPJ12           S3C2410_GPIONO(S3C2440_GPIO_BANKJ, 12)
+#define S3C2440_GPJ12_INP       (0x00 << 24)
+#define S3C2440_GPJ12_OUTP      (0x01 << 24)
+#define S3C2440_GPJ12_CAMCLKOUT (0x02 << 24)
+
+#endif	/* __ASM_ARCH_REGS_GPIOJ_H */
+
diff -Nru a/include/asm-arm/arch-s3c2410/regs-iic.h b/include/asm-arm/arch-s3c2410/regs-iic.h
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/include/asm-arm/arch-s3c2410/regs-iic.h	2004-10-18 14:57:21 -07:00
@@ -0,0 +1,50 @@
+/* linux/include/asm-arm/arch-s3c2410/regs-iic.h
+ *
+ * Copyright (c) 2004 Simtec Electronics <linux@simtec.co.uk>
+ *		http://www.simtec.co.uk/products/SWLINUX/
+ *
+ * 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.
+ *
+ * S3C2410 I2C Controller
+ *
+ *  Changelog:
+ *	03-Oct-2004  BJD  Initial include for Linux
+*/
+
+#ifndef __ASM_ARCH_IIC_H
+#define __ASM_ARCH_IIC_H __FILE__
+
+/* see s3c2410x user guide, v1.1, section 9 (p447) for more info */
+
+#define S3C2410_IICREG(x) (x)
+
+#define S3C2410_IICCON    S3C2410_IICREG(0x00)
+#define S3C2410_IICSTAT   S3C2410_IICREG(0x04)
+#define S3C2410_IICADD    S3C2410_IICREG(0x08)
+#define S3C2410_IICDS     S3C2410_IICREG(0x0C)
+
+#define S3C2410_IICCON_ACKEN		(1<<7)
+#define S3C2410_IICCON_TXDIV_16		(0<<6)
+#define S3C2410_IICCON_TXDIV_512	(1<<6)
+#define S3C2410_IICCON_IRQEN		(1<<5)
+#define S3C2410_IICCON_IRQPEND		(1<<4)
+#define S3C2410_IICCON_SCALE(x)		((x)&15)
+#define S3C2410_IICCON_SCALEMASK	(0xf)
+
+#define S3C2410_IICSTAT_MASTER_RX	(2<<6)
+#define S3C2410_IICSTAT_MASTER_TX	(3<<6)
+#define S3C2410_IICSTAT_SLAVE_RX	(0<<6)
+#define S3C2410_IICSTAT_SLAVE_TX	(1<<6)
+#define S3C2410_IICSTAT_MODEMASK	(3<<6)
+
+#define S3C2410_IICSTAT_START		(1<<5)
+#define S3C2410_IICSTAT_BUSBUSY		(1<<5)
+#define S3C2410_IICSTAT_TXRXEN		(1<<4)
+#define S3C2410_IICSTAT_ARBITR		(1<<3)
+#define S3C2410_IICSTAT_ASSLAVE		(1<<2)
+#define S3C2410_IICSTAT_ADDR0		(1<<1)
+#define S3C2410_IICSTAT_LASTBIT		(1<<0)
+
+#endif /* __ASM_ARCH_IIC_H */
diff -Nru a/include/asm-arm/arch-s3c2410/regs-mem.h b/include/asm-arm/arch-s3c2410/regs-mem.h
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/include/asm-arm/arch-s3c2410/regs-mem.h	2004-10-18 14:57:21 -07:00
@@ -0,0 +1,190 @@
+/* linux/include/asm-arm/arch-s3c2410/regs-mem.h
+ *
+ * Copyright (c) 2004 Simtec Electronics <linux@simtec.co.uk>
+ *		http://www.simtec.co.uk/products/SWLINUX/
+ *
+ * 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.
+ *
+ * S3C2410 Memory Control register definitions
+ *
+ *  Changelog:
+ *	29-Sep-2004  BJD  Initial include for Linux
+ *
+*/
+
+#ifndef __ASM_ARM_MEMREGS_H
+#define __ASM_ARM_MEMREGS_H "$Id: regs.h,v 1.8 2003/05/01 15:55:41 ben Exp $"
+
+#ifndef S3C2410_MEMREG
+#define S3C2410_MEMREG(x) (S3C2410_VA_MEMCTRL + (x))
+#endif
+
+/* bus width, and wait state control */
+#define S3C2410_BWSCON			S3C2410_MEMREG(0x0000)
+
+/* bank zero config - note, pinstrapped from OM pins! */
+#define S3C2410_BWSCON_DW0_16		(1<<1)
+#define S3C2410_BWSCON_DW0_32		(2<<1)
+
+/* bank one configs */
+#define S3C2410_BWSCON_DW1_8		(0<<4)
+#define S3C2410_BWSCON_DW1_16		(1<<4)
+#define S3C2410_BWSCON_DW1_32		(2<<4)
+#define S3C2410_BWSCON_WS1		(1<<6)
+#define S3C2410_BWSCON_ST1		(1<<7)
+
+/* bank 2 configurations */
+#define S3C2410_BWSCON_DW2_8		(0<<8)
+#define S3C2410_BWSCON_DW2_16		(1<<8)
+#define S3C2410_BWSCON_DW2_32		(2<<8)
+#define S3C2410_BWSCON_WS2		(1<<10)
+#define S3C2410_BWSCON_ST2		(1<<11)
+
+/* bank 3 configurations */
+#define S3C2410_BWSCON_DW3_8		(0<<12)
+#define S3C2410_BWSCON_DW3_16		(1<<12)
+#define S3C2410_BWSCON_DW3_32		(2<<12)
+#define S3C2410_BWSCON_WS3		(1<<14)
+#define S3C2410_BWSCON_ST3		(1<<15)
+
+/* bank 4 configurations */
+#define S3C2410_BWSCON_DW4_8		(0<<16)
+#define S3C2410_BWSCON_DW4_16		(1<<16)
+#define S3C2410_BWSCON_DW4_32		(2<<16)
+#define S3C2410_BWSCON_WS4		(1<<18)
+#define S3C2410_BWSCON_ST4		(1<<19)
+
+/* bank 5 configurations */
+#define S3C2410_BWSCON_DW5_8		(0<<20)
+#define S3C2410_BWSCON_DW5_16		(1<<20)
+#define S3C2410_BWSCON_DW5_32		(2<<20)
+#define S3C2410_BWSCON_WS5		(1<<22)
+#define S3C2410_BWSCON_ST5		(1<<23)
+
+/* bank 6 configurations */
+#define S3C2410_BWSCON_DW6_8		(0<<24)
+#define S3C2410_BWSCON_DW6_16		(1<<24)
+#define S3C2410_BWSCON_DW6_32		(2<<24)
+#define S3C2410_BWSCON_WS6		(1<<26)
+#define S3C2410_BWSCON_ST6		(1<<27)
+
+/* bank 7 configurations */
+#define S3C2410_BWSCON_DW7_8		(0<<28)
+#define S3C2410_BWSCON_DW7_16		(1<<28)
+#define S3C2410_BWSCON_DW7_32		(2<<28)
+#define S3C2410_BWSCON_WS7		(1<<30)
+#define S3C2410_BWSCON_ST7		(1<<31)
+
+/* memory set (rom, ram) */
+#define S3C2410_BANKCON0		S3C2410_MEMREG(0x0004)
+#define S3C2410_BANKCON1		S3C2410_MEMREG(0x0008)
+#define S3C2410_BANKCON2		S3C2410_MEMREG(0x000C)
+#define S3C2410_BANKCON3		S3C2410_MEMREG(0x0010)
+#define S3C2410_BANKCON4		S3C2410_MEMREG(0x0014)
+#define S3C2410_BANKCON5		S3C2410_MEMREG(0x0018)
+#define S3C2410_BANKCON6		S3C2410_MEMREG(0x001C)
+#define S3C2410_BANKCON7		S3C2410_MEMREG(0x0020)
+
+/* bank configuration registers */
+
+#define S3C2410_BANKCON_PMCnorm		(0x00)
+#define S3C2410_BANKCON_PMC4		(0x01)
+#define S3C2410_BANKCON_PMC8		(0x02)
+#define S3C2410_BANKCON_PMC16		(0x03)
+
+/* bank configurations for banks 0..7, note banks
+ * 6 and 7 have differnt configurations depending on
+ * the memory type bits */
+
+#define S3C2410_BANKCON_Tacp2		(0x0 << 2)
+#define S3C2410_BANKCON_Tacp3		(0x1 << 2)
+#define S3C2410_BANKCON_Tacp4		(0x2 << 2)
+#define S3C2410_BANKCON_Tacp6		(0x3 << 2)
+
+#define S3C2410_BANKCON_Tcah0		(0x0 << 4)
+#define S3C2410_BANKCON_Tcah1		(0x1 << 4)
+#define S3C2410_BANKCON_Tcah2		(0x2 << 4)
+#define S3C2410_BANKCON_Tcah4		(0x3 << 4)
+
+#define S3C2410_BANKCON_Tcoh0		(0x0 << 6)
+#define S3C2410_BANKCON_Tcoh1		(0x1 << 6)
+#define S3C2410_BANKCON_Tcoh2		(0x2 << 6)
+#define S3C2410_BANKCON_Tcoh4		(0x3 << 6)
+
+#define S3C2410_BANKCON_Tacc1		(0x0 << 8)
+#define S3C2410_BANKCON_Tacc2		(0x1 << 8)
+#define S3C2410_BANKCON_Tacc3		(0x2 << 8)
+#define S3C2410_BANKCON_Tacc4		(0x3 << 8)
+#define S3C2410_BANKCON_Tacc6		(0x4 << 8)
+#define S3C2410_BANKCON_Tacc8		(0x5 << 8)
+#define S3C2410_BANKCON_Tacc10		(0x6 << 8)
+#define S3C2410_BANKCON_Tacc14		(0x7 << 8)
+
+#define S3C2410_BANKCON_Tcos0		(0x0 << 11)
+#define S3C2410_BANKCON_Tcos1		(0x1 << 11)
+#define S3C2410_BANKCON_Tcos2		(0x2 << 11)
+#define S3C2410_BANKCON_Tcos4		(0x3 << 11)
+
+#define S3C2410_BANKCON_Tacs0		(0x0 << 13)
+#define S3C2410_BANKCON_Tacs1		(0x1 << 13)
+#define S3C2410_BANKCON_Tacs2		(0x2 << 13)
+#define S3C2410_BANKCON_Tacs4		(0x3 << 13)
+
+#define S3C2410_BANKCON_SRAM		(0x0 << 15)
+#define S3C2410_BANKCON_SDRAM		(0x3 << 15)
+
+/* next bits only for SDRAM in 6,7 */
+#define S3C2410_BANKCON_Trdc2		(0x00 << 2)
+#define S3C2410_BANKCON_Trdc3		(0x01 << 2)
+#define S3C2410_BANKCON_Trdc4		(0x02 << 2)
+
+/* control column address select */
+#define S3C2410_BANKCON_SCANb8		(0x00 << 0)
+#define S3C2410_BANKCON_SCANb9		(0x01 << 0)
+#define S3C2410_BANKCON_SCANb10		(0x02 << 0)
+
+#define S3C2410_REFRESH			S3C2410_MEMREG(0x0024)
+#define S3C2410_BANKSIZE		S3C2410_MEMREG(0x0028)
+#define S3C2410_MRSRB6			S3C2410_MEMREG(0x002C)
+#define S3C2410_MRSRB7			S3C2410_MEMREG(0x0030)
+
+/* refresh control */
+
+#define S3C2410_REFRESH_REFEN		(1<<23)
+#define S3C2410_REFRESH_SELF		(1<<22)
+#define S3C2410_REFRESH_REFCOUNTER	((1<<11)-1)
+
+#define S3C2410_REFRESH_TRP_MASK	(3<<20)
+#define S3C2410_REFRESH_TRP_2clk	(0<<20)
+#define S3C2410_REFRESH_TRP_3clk	(1<<20)
+#define S3C2410_REFRESH_TRP_4clk	(2<<20)
+
+#define S3C2410_REFRESH_TSRC_MASK	(3<<18)
+#define S3C2410_REFRESH_TSRC_4clk	(0<<18)
+#define S3C2410_REFRESH_TSRC_5clk	(1<<18)
+#define S3C2410_REFRESH_TSRC_6clk	(2<<18)
+#define S3C2410_REFRESH_TSRC_7clk	(3<<18)
+
+
+/* mode select register(s) */
+
+#define  S3C2410_MRSRB_CL1		(0x00 << 4)
+#define  S3C2410_MRSRB_CL2		(0x02 << 4)
+#define  S3C2410_MRSRB_CL3		(0x03 << 4)
+
+/* bank size register */
+#define S3C2410_BANKSIZE_128M		(0x2 << 0)
+#define S3C2410_BANKSIZE_64M		(0x1 << 0)
+#define S3C2410_BANKSIZE_32M		(0x0 << 0)
+#define S3C2410_BANKSIZE_16M		(0x7 << 0)
+#define S3C2410_BANKSIZE_8M		(0x6 << 0)
+#define S3C2410_BANKSIZE_4M		(0x5 << 0)
+#define S3C2410_BANKSIZE_2M		(0x4 << 0)
+#define S3C2410_BANKSIZE_MASK		(0x7 << 0)
+#define S3C2410_BANKSIZE_SCLK_EN	(1<<4)
+#define S3C2410_BANKSIZE_SCKE_EN	(1<<5)
+#define S3C2410_BANKSIZE_BURST		(1<<7)
+
+#endif /* __ASM_ARM_MEMREGS_H */
diff -Nru a/include/asm-arm/arch-s3c2410/regs-nand.h b/include/asm-arm/arch-s3c2410/regs-nand.h
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/include/asm-arm/arch-s3c2410/regs-nand.h	2004-10-18 14:57:21 -07:00
@@ -0,0 +1,43 @@
+/* linux/include/asm-arm/arch-s3c2410/regs-nand.h
+ *
+ * Copyright (c) 2004 Simtec Electronics <linux@simtec.co.uk>
+ *		      http://www.simtec.co.uk/products/SWLINUX/
+ *
+ * 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.
+ *
+ * S3C2410 clock register definitions
+ *
+ *  Changelog:
+ *    18-Aug-2004    BJD     Copied file from 2.4 and updated
+*/
+
+#ifndef __ASM_ARM_REGS_NAND
+#define __ASM_ARM_REGS_NAND "$Id: nand.h,v 1.3 2003/12/09 11:36:29 ben Exp $"
+
+
+#define S3C2410_NFREG(x) (x)
+
+#define S3C2410_NFCONF  S3C2410_NFREG(0x00)
+#define S3C2410_NFCMD   S3C2410_NFREG(0x04)
+#define S3C2410_NFADDR  S3C2410_NFREG(0x08)
+#define S3C2410_NFDATA  S3C2410_NFREG(0x0C)
+#define S3C2410_NFSTAT  S3C2410_NFREG(0x10)
+#define S3C2410_NFECC   S3C2410_NFREG(0x14)
+
+#define S3C2410_NFCONF_EN          (1<<15)
+#define S3C2410_NFCONF_512BYTE     (1<<14)
+#define S3C2410_NFCONF_4STEP       (1<<13)
+#define S3C2410_NFCONF_INITECC     (1<<12)
+#define S3C2410_NFCONF_nFCE        (1<<11)
+#define S3C2410_NFCONF_TACLS(x)    ((x)<<8)
+#define S3C2410_NFCONF_TWRPH0(x)   ((x)<<4)
+#define S3C2410_NFCONF_TWRPH1(x)   ((x)<<0)
+
+#define S3C2410_NFSTAT_BUSY        (1<<0)
+
+/* think ECC can only be 8bit read? */
+
+#endif /* __ASM_ARM_REGS_NAND */
+
diff -Nru a/include/asm-arm/arch-s3c2410/regs-sdi.h b/include/asm-arm/arch-s3c2410/regs-sdi.h
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/include/asm-arm/arch-s3c2410/regs-sdi.h	2004-10-18 14:57:21 -07:00
@@ -0,0 +1,112 @@
+/* linux/include/asm/arch-s3c2410/regs-sdi.h
+ *
+ * Copyright (c) 2004 Simtec Electronics <linux@simtec.co.uk>
+ *		      http://www.simtec.co.uk/products/SWLINUX/
+ *
+ * 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.
+ *
+ * S3C2410 MMC/SDIO register definitions
+ *
+ *  Changelog:
+ *    18-Aug-2004 Ben Dooks      Created initial file
+*/
+
+#ifndef __ASM_ARM_REGS_SDI
+#define __ASM_ARM_REGS_SDI "regs-sdi.h"
+
+#define S3C2410_SDICON                (0x00)
+#define S3C2410_SDIPRE                (0x04)
+#define S3C2410_SDICMDARG             (0x08)
+#define S3C2410_SDICMDCON             (0x0C)
+#define S3C2410_SDICMDSTAT            (0x10)
+#define S3C2410_SDIRSP0               (0x14)
+#define S3C2410_SDIRSP1               (0x18)
+#define S3C2410_SDIRSP2               (0x1C)
+#define S3C2410_SDIRSP3               (0x20)
+#define S3C2410_SDITIMER              (0x24)
+#define S3C2410_SDIBSIZE              (0x28)
+#define S3C2410_SDIDCON               (0x2C)
+#define S3C2410_SDIDCNT               (0x30)
+#define S3C2410_SDIDSTA               (0x34)
+#define S3C2410_SDIFSTA               (0x38)
+#define S3C2410_SDIDATA               (0x3C)
+#define S3C2410_SDIIMSK               (0x40)
+
+#define S3C2410_SDICON_BYTEORDER      (1<<4)
+#define S3C2410_SDICON_SDIOIRQ        (1<<3)
+#define S3C2410_SDICON_RWAITEN        (1<<2)
+#define S3C2410_SDICON_FIFORESET      (1<<1)
+#define S3C2410_SDICON_CLOCKTYPE      (1<<0)
+
+#define S3C2410_SDICMDCON_ABORT       (1<<12)
+#define S3C2410_SDICMDCON_WITHDATA    (1<<11)
+#define S3C2410_SDICMDCON_LONGRSP     (1<<10)
+#define S3C2410_SDICMDCON_WAITRSP     (1<<9)
+#define S3C2410_SDICMDCON_CMDSTART    (1<<8)
+#define S3C2410_SDICMDCON_INDEX       (0xff)
+
+#define S3C2410_SDICMDSTAT_CRCFAIL    (1<<12)
+#define S3C2410_SDICMDSTAT_CMDSENT    (1<<11)
+#define S3C2410_SDICMDSTAT_CMDTIMEOUT (1<<10)
+#define S3C2410_SDICMDSTAT_RSPFIN     (1<<9)
+#define S3C2410_SDICMDSTAT_XFERING    (1<<8)
+#define S3C2410_SDICMDSTAT_INDEX      (0xff)
+
+#define S3C2410_SDIDCON_IRQPERIOD     (1<<21)
+#define S3C2410_SDIDCON_TXAFTERRESP   (1<<20)
+#define S3C2410_SDIDCON_RXAFTERCMD    (1<<19)
+#define S3C2410_SDIDCON_BUSYAFTERCMD  (1<<18)
+#define S3C2410_SDIDCON_BLOCKMODE     (1<<17)
+#define S3C2410_SDIDCON_WIDEBUS       (1<<16)
+#define S3C2410_SDIDCON_DMAEN         (1<<15)
+#define S3C2410_SDIDCON_STOP          (1<<14)
+
+#define S3C2410_SDIDCON_XFER_MASK     (3<<12)
+#define S3C2410_SDIDCON_XFER_READY    (0<<12)
+#define S3C2410_SDIDCON_XFER_CHKSTART (1<<12)
+#define S3C2410_SDIDCON_XFER_RXSTART  (2<<12)
+#define S3C2410_SDIDCON_XFER_TXSTART  (3<<12)
+
+#define S3C2410_SDIDCNT_BLKNUM_SHIFT  (12)
+
+#define S3C2410_SDIDSTA_RDYWAITREQ    (1<<10)
+#define S3C2410_SDIDSTA_SDIOIRQDETECT (1<<9)
+#define S3C2410_SDIDSTA_FIFOFAIL      (1<<8)
+#define S3C2410_SDIDSTA_CRCFAIL       (1<<7)
+#define S3C2410_SDIDSTA_RXCRCFAIL     (1<<6)
+#define S3C2410_SDIDSTA_DATATIMEOUT   (1<<5)
+#define S3C2410_SDIDSTA_XFERFINISH    (1<<4)
+#define S3C2410_SDIDSTA_BUSYFINISH    (1<<3)
+#define S3C2410_SDIDSTA_TXDATAON      (1<<1)
+#define S3C2410_SDIDSTA_RXDATAON      (1<<0)
+
+#define S3C2410_SDIFSTA_TXFULL         (1<<13)
+#define S3C2410_SDIFSTA_RXFULL         (1<<12)
+#define S3C2410_SDIFSTA_TXHALF         (1<<11)
+#define S3C2410_SDIFSTA_TXEMPTY        (1<<10)
+#define S3C2410_SDIFSTA_RXLAST         (1<<9)
+#define S3C2410_SDIFSTA_RXFULL         (1<<8)
+#define S3C2410_SDIFSTA_RXHALF         (1<<7)
+#define S3C2410_SDIFSTA_COUNTMASK      (0x7f)
+
+#define S3C2410_SDIIMSK_RESPONSECRC    (1<<17)
+#define S3C2410_SDIIMSK_CMDSENT        (1<<16)
+#define S3C2410_SDIIMSK_CMDTIMEOUT     (1<<15)
+#define S3C2410_SDIIMSK_RESPONSEND     (1<<14)
+#define S3C2410_SDIIMSK_READWAIT       (1<<13)
+#define S3C2410_SDIIMSK_SDIOIRQ        (1<<12)
+#define S3C2410_SDIIMSK_FIFOFAIL       (1<<11)
+#define S3C2410_SDIIMSK_CRCSTATUS      (1<<10)
+#define S3C2410_SDIIMSK_DATACRC        (1<<9)
+#define S3C2410_SDIIMSK_DATATIMEOUT    (1<<8)
+#define S3C2410_SDIIMSK_DATAFINISH     (1<<7)
+#define S3C2410_SDIIMSK_BUSYFINISH     (1<<6)
+#define S3C2410_SDIIMSK_TXFIFOHALF     (1<<4)
+#define S3C2410_SDIIMSK_TXFIFOEMPTY    (1<<3)
+#define S3C2410_SDIIMSK_RXFIFOLAST     (1<<2)
+#define S3C2410_SDIIMSK_RXFIFOFULL     (1<<1)
+#define S3C2410_SDIIMSK_RXFIFOHALF     (1<<0)
+
+#endif /* __ASM_ARM_REGS_SDI */
diff -Nru a/include/asm-arm/arch-s3c2410/regs-spi.h b/include/asm-arm/arch-s3c2410/regs-spi.h
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/include/asm-arm/arch-s3c2410/regs-spi.h	2004-10-18 14:57:22 -07:00
@@ -0,0 +1,56 @@
+/* linux/include/asm-arm/arch-s3c2410/regs-spi.h
+ *
+ * Copyright (c) 2004 Fetron GmbH
+ *
+ * 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.
+ *
+ * S3C2410 SPI register definition
+ *
+ *  Changelog:
+ *    20-04-2004     KF      Created file
+ *    04-10-2004     BJD     Removed VA address (no longer mapped)
+ *			     tidied file for submission
+ */
+
+#ifndef __ASM_ARCH_REGS_SPI_H
+#define __ASM_ARCH_REGS_SPI_H
+
+
+#define S3C2410_SPCON	(0x00)
+
+#define S3C2410_SPCON_SMOD_DMA	  (2<<5)	/* DMA mode */
+#define S3C2410_SPCON_SMOD_INT	  (1<<5)	/* interrupt mode */
+#define S3C2410_SPCON_SMOD_POLL   (0<<5)	/* polling mode */
+#define S3C2410_SPCON_ENSCK	  (1<<4)	/* Enable SCK */
+#define S3C2410_SPCON_MSTR	  (1<<3)	/* Master/Slave select
+						   0: slave, 1: master */
+#define S3C2410_SPCON_CPOL_HIGH	  (1<<2)	/* Clock polarity select */
+#define S3C2410_SPCON_CPOL_LOW	  (0<<2)	/* Clock polarity select */
+
+#define S3C2410_SPCON_CPHA_FMTB	  (1<<1)	/* Clock Phase Select */
+#define S3C2410_SPCON_CPHA_FMTA	  (0<<1)	/* Clock Phase Select */
+
+#define S3C2410_SPCON_TAGD	  (1<<0)	/* Tx auto garbage data mode */
+
+
+#define S3C2410_SPSTA	 (0x04)
+
+#define S3C2410_SPSTA_DCOL	  (1<<2)	/* Data Collision Error */
+#define S3C2410_SPSTA_MULD	  (1<<1)	/* Multi Master Error */
+#define S3C2410_SPSTA_READY	  (1<<0)	/* Data Tx/Rx ready */
+
+
+#define S3C2410_SPPIN	 (0x08)
+
+#define S3C2410_SPPIN_ENMUL	  (1<<2)	/* Multi Master Error detect */
+#define S3C2410_SPPIN_RESERVED	  (1<<1)
+#define S3C2410_SPPIN_KEEP	  (1<<0)	/* Master Out keep */
+
+
+#define S3C2410_SPPRE	 (0x0C)
+#define S3C2410_SPTDAT	 (0x10)
+#define S3C2410_SPRDAT	 (0x14)
+
+#endif /* __ASM_ARCH_REGS_SPI_H */
diff -Nru a/include/asm-arm/arch-s3c2410/regs-timer.h b/include/asm-arm/arch-s3c2410/regs-timer.h
--- a/include/asm-arm/arch-s3c2410/regs-timer.h	2004-10-18 14:57:04 -07:00
+++ b/include/asm-arm/arch-s3c2410/regs-timer.h	2004-10-18 14:57:04 -07:00
@@ -29,6 +29,8 @@
 #define S3C2410_TCFG_PRESCALER0_MASK (255<<0)
 #define S3C2410_TCFG_PRESCALER1_MASK (255<<8)
 #define S3C2410_TCFG_PRESCALER1_SHIFT (8)
+#define S3C2410_TCFG_DEADZONE_MASK   (255<<16)
+#define S3C2410_TCFG_DEADZONE_SHIFT  (16)
 
 #define S3C2410_TCFG1_MUX4_DIV2	  (0<<16)
 #define S3C2410_TCFG1_MUX4_DIV4	  (1<<16)
diff -Nru a/include/asm-arm/arch-s3c2410/regs-udc.h b/include/asm-arm/arch-s3c2410/regs-udc.h
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/include/asm-arm/arch-s3c2410/regs-udc.h	2004-10-18 14:57:22 -07:00
@@ -0,0 +1,162 @@
+/* linux/include/asm/arch-s3c2410/regs-udc.h
+ *
+ * Copyright (C) 2004 Herbert Poetzl <herbert@13thfloor.at>
+ *
+ * This include file 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.
+ *
+ *  Changelog:
+ *    01-08-2004	initial creation
+ *    12-09-2004	cleanup for submission
+ */
+
+#ifndef __ASM_ARCH_REGS_UDC_H
+#define __ASM_ARCH_REGS_UDC_H
+
+
+#define S3C2410_USBDREG(x) ((x) + S3C2410_VA_USBDEV)
+
+#define S3C2410_UDC_FUNC_ADDR_REG	S3C2410_USBDREG(0x0140)
+#define S3C2410_UDC_PWR_REG		S3C2410_USBDREG(0x0144)
+#define S3C2410_UDC_EP_INT_REG		S3C2410_USBDREG(0x0148)
+
+#define S3C2410_UDC_USB_INT_REG		S3C2410_USBDREG(0x0158)
+#define S3C2410_UDC_EP_INT_EN_REG	S3C2410_USBDREG(0x015c)
+
+#define S3C2410_UDC_USB_INT_EN_REG	S3C2410_USBDREG(0x016c)
+
+#define S3C2410_UDC_FRAME_NUM1_REG	S3C2410_USBDREG(0x0170)
+#define S3C2410_UDC_FRAME_NUM2_REG	S3C2410_USBDREG(0x0174)
+
+#define S3C2410_UDC_EP0_FIFO_REG	S3C2410_USBDREG(0x01c0)
+#define S3C2410_UDC_EP1_FIFO_REG	S3C2410_USBDREG(0x01c4)
+#define S3C2410_UDC_EP2_FIFO_REG	S3C2410_USBDREG(0x01c8)
+#define S3C2410_UDC_EP3_FIFO_REG	S3C2410_USBDREG(0x01cc)
+#define S3C2410_UDC_EP4_FIFO_REG	S3C2410_USBDREG(0x01d0)
+
+#define S3C2410_UDC_EP1_DMA_CON		S3C2410_USBDREG(0x0200)
+#define S3C2410_UDC_EP1_DMA_UNIT	S3C2410_USBDREG(0x0204)
+#define S3C2410_UDC_EP1_DMA_FIFO	S3C2410_USBDREG(0x0208)
+#define S3C2410_UDC_EP1_DMA_TTC_L	S3C2410_USBDREG(0x020c)
+#define S3C2410_UDC_EP1_DMA_TTC_M	S3C2410_USBDREG(0x0210)
+#define S3C2410_UDC_EP1_DMA_TTC_H	S3C2410_USBDREG(0x0214)
+
+#define S3C2410_UDC_EP2_DMA_CON		S3C2410_USBDREG(0x0218)
+#define S3C2410_UDC_EP2_DMA_UNIT	S3C2410_USBDREG(0x021c)
+#define S3C2410_UDC_EP2_DMA_FIFO	S3C2410_USBDREG(0x0220)
+#define S3C2410_UDC_EP2_DMA_TTC_L	S3C2410_USBDREG(0x0224)
+#define S3C2410_UDC_EP2_DMA_TTC_M	S3C2410_USBDREG(0x0228)
+#define S3C2410_UDC_EP2_DMA_TTC_H	S3C2410_USBDREG(0x022c)
+
+#define S3C2410_UDC_EP3_DMA_CON		S3C2410_USBDREG(0x0240)
+#define S3C2410_UDC_EP3_DMA_UNIT	S3C2410_USBDREG(0x0244)
+#define S3C2410_UDC_EP3_DMA_FIFO	S3C2410_USBDREG(0x0248)
+#define S3C2410_UDC_EP3_DMA_TTC_L	S3C2410_USBDREG(0x024c)
+#define S3C2410_UDC_EP3_DMA_TTC_M	S3C2410_USBDREG(0x0250)
+#define S3C2410_UDC_EP3_DMA_TTC_H	S3C2410_USBDREG(0x0254)
+
+#define S3C2410_UDC_EP4_DMA_CON		S3C2410_USBDREG(0x0258)
+#define S3C2410_UDC_EP4_DMA_UNIT	S3C2410_USBDREG(0x025c)
+#define S3C2410_UDC_EP4_DMA_FIFO	S3C2410_USBDREG(0x0260)
+#define S3C2410_UDC_EP4_DMA_TTC_L	S3C2410_USBDREG(0x0264)
+#define S3C2410_UDC_EP4_DMA_TTC_M	S3C2410_USBDREG(0x0268)
+#define S3C2410_UDC_EP4_DMA_TTC_H	S3C2410_USBDREG(0x026c)
+
+#define S3C2410_UDC_INDEX_REG		S3C2410_USBDREG(0x0178)
+
+/* indexed registers */
+
+#define S3C2410_UDC_MAXP_REG		S3C2410_USBDREG(0x018c)
+
+#define S3C2410_UDC_EP0_CSR_REG		S3C2410_USBDREG(0x0184)
+
+#define S3C2410_UDC_IN_CSR1_REG		S3C2410_USBDREG(0x0184)
+#define S3C2410_UDC_IN_CSR2_REG		S3C2410_USBDREG(0x0188)
+
+#define S3C2410_UDC_OUT_CSR1_REG	S3C2410_USBDREG(0x0190)
+#define S3C2410_UDC_OUT_CSR2_REG	S3C2410_USBDREG(0x0194)
+#define S3C2410_UDC_OUT_FIFO_CNT1_REG	S3C2410_USBDREG(0x0198)
+#define S3C2410_UDC_OUT_FIFO_CNT2_REG	S3C2410_USBDREG(0x019c)
+
+
+
+#define S3C2410_UDC_PWR_ISOUP		(1<<7) // R/W
+#define S3C2410_UDC_PWR_RESET		(1<<3) // R
+#define S3C2410_UDC_PWR_RESUME		(1<<2) // R/W
+#define S3C2410_UDC_PWR_SUSPEND		(1<<1) // R
+#define S3C2410_UDC_PWR_ENSUSPEND	(1<<0) // R/W
+
+#define S3C2410_UDC_PWR_DEFAULT		0x00
+
+#define S3C2410_UDC_INT_EP4		(1<<4) // R/W (clear only)
+#define S3C2410_UDC_INT_EP3		(1<<3) // R/W (clear only)
+#define S3C2410_UDC_INT_EP2		(1<<2) // R/W (clear only)
+#define S3C2410_UDC_INT_EP1		(1<<1) // R/W (clear only)
+#define S3C2410_UDC_INT_EP0		(1<<0) // R/W (clear only)
+
+#define S3C2410_UDC_USBINT_RESET	(1<<2) // R/W (clear only)
+#define S3C2410_UDC_USBINT_RESUME	(1<<1) // R/W (clear only)
+#define S3C2410_UDC_USBINT_SUSPEND	(1<<0) // R/W (clear only)
+
+#define S3C2410_UDC_INTE_EP4		(1<<4) // R/W
+#define S3C2410_UDC_INTE_EP3		(1<<3) // R/W
+#define S3C2410_UDC_INTE_EP2		(1<<2) // R/W
+#define S3C2410_UDC_INTE_EP1		(1<<1) // R/W
+#define S3C2410_UDC_INTE_EP0		(1<<0) // R/W
+
+#define S3C2410_UDC_USBINTE_RESET	(1<<2) // R/W
+#define S3C2410_UDC_USBINTE_SUSPEND	(1<<0) // R/W
+
+
+#define S3C2410_UDC_INDEX_EP0		(0x00)
+#define S3C2410_UDC_INDEX_EP1		(0x01) // ??
+#define S3C2410_UDC_INDEX_EP2		(0x02) // ??
+#define S3C2410_UDC_INDEX_EP3		(0x03) // ??
+#define S3C2410_UDC_INDEX_EP4		(0x04) // ??
+
+#define S3C2410_UDC_ICSR1_CLRDT		(1<<6) // R/W
+#define S3C2410_UDC_ICSR1_SENTSTL	(1<<5) // R/W (clear only)
+#define S3C2410_UDC_ICSR1_SENDSTL	(1<<4) // R/W
+#define S3C2410_UDC_ICSR1_FFLUSH	(1<<3) // W   (set only)
+#define S3C2410_UDC_ICSR1_UNDRUN	(1<<2) // R/W (clear only)
+#define S3C2410_UDC_ICSR1_PKTRDY	(1<<0) // R/W (set only)
+
+#define S3C2410_UDC_ICSR2_AUTOSET	(1<<7) // R/W
+#define S3C2410_UDC_ICSR2_ISO		(1<<6) // R/W
+#define S3C2410_UDC_ICSR2_MODEIN	(1<<5) // R/W
+#define S3C2410_UDC_ICSR2_DMAIEN	(1<<4) // R/W
+
+#define S3C2410_UDC_OCSR1_CLRDT		(1<<7) // R/W
+#define S3C2410_UDC_OCSR1_SENTSTL	(1<<6) // R/W (clear only)
+#define S3C2410_UDC_OCSR1_SENDSTL	(1<<5) // R/W
+#define S3C2410_UDC_OCSR1_FFLUSH	(1<<4) // R/W
+#define S3C2410_UDC_OCSR1_DERROR	(1<<3) // R
+#define S3C2410_UDC_OCSR1_OVRRUN	(1<<2) // R/W (clear only)
+#define S3C2410_UDC_OCSR1_PKTRDY	(1<<0) // R/W (clear only)
+
+#define S3C2410_UDC_OCSR2_AUTOCLR	(1<<7) // R/W
+#define S3C2410_UDC_OCSR2_ISO		(1<<6) // R/W
+#define S3C2410_UDC_OCSR2_DMAIEN	(1<<5) // R/W
+
+#define S3C2410_UDC_SETIX(x)	    \
+	__raw_writel(S3C2410_UDC_INDEX_ ## x, S3C2410_UDC_INDEX_REG);
+
+
+#define S3C2410_UDC_EP0_CSR_OPKRDY	(1<<0)
+#define S3C2410_UDC_EP0_CSR_IPKRDY	(1<<1)
+#define S3C2410_UDC_EP0_CSR_SENTSTL	(1<<2)
+#define S3C2410_UDC_EP0_CSR_DE		(1<<3)
+#define S3C2410_UDC_EP0_CSR_SE		(1<<4)
+#define S3C2410_UDC_EP0_CSR_SENDSTL	(1<<5)
+#define S3C2410_UDC_EP0_CSR_SOPKTRDY	(1<<6)
+#define S3C2410_UDC_EP0_CSR_SSE	(1<<7)
+
+#define S3C2410_UDC_MAXP_8		(1<<0)
+#define S3C2410_UDC_MAXP_16		(1<<1)
+#define S3C2410_UDC_MAXP_32		(1<<2)
+#define S3C2410_UDC_MAXP_64		(1<<3)
+
+
+#endif
diff -Nru a/include/asm-arm/arch-s3c2410/uncompress.h b/include/asm-arm/arch-s3c2410/uncompress.h
--- a/include/asm-arm/arch-s3c2410/uncompress.h	2004-10-18 14:57:19 -07:00
+++ b/include/asm-arm/arch-s3c2410/uncompress.h	2004-10-18 14:57:19 -07:00
@@ -100,7 +100,7 @@
 }
 
 static void
-puts(const char *ptr)
+putstr(const char *ptr)
 {
 	for (; *ptr != '\0'; ptr++) {
 		putc(*ptr);
diff -Nru a/include/asm-arm/arch-s3c2410/usb-control.h b/include/asm-arm/arch-s3c2410/usb-control.h
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/include/asm-arm/arch-s3c2410/usb-control.h	2004-10-18 14:57:23 -07:00
@@ -0,0 +1,45 @@
+/* linux/include/asm-arm/arch-s3c2410/usb-control.h
+ *
+ * (c) 2004 Simtec Electronics
+ *  Ben Dooks <ben@simtec.co.uk>
+ *
+ * S3C2410 - usb port information
+ *
+ * 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.
+ *
+ * Changelog:
+ *  11-Sep-2004 BJD  Created file
+ *  21-Sep-2004 BJD  Updated port info
+*/
+
+#ifndef __ASM_ARCH_USBCONTROL_H
+#define __ASM_ARCH_USBCONTROL_H "include/asm-arm/arch-s3c2410/usb-control.h"
+
+#define S3C_HCDFLG_USED	(1)
+
+struct s3c2410_hcd_port {
+	unsigned char	flags;
+	unsigned char	power;
+	unsigned char	oc_status;
+	unsigned char	oc_changed;
+};
+
+struct s3c2410_hcd_info {
+	struct usb_hcd		*hcd;
+	struct s3c2410_hcd_port	port[2];
+
+	void		(*power_control)(int port, int to);
+	void		(*enable_oc)(struct s3c2410_hcd_info *, int on);
+	void		(*report_oc)(struct s3c2410_hcd_info *, int ports);
+};
+
+static void inline s3c2410_report_oc(struct s3c2410_hcd_info *info, int ports)
+{
+	if (info->report_oc != NULL) {
+		(info->report_oc)(info, ports);
+	}
+}
+
+#endif /*__ASM_ARCH_USBCONTROL_H */
diff -Nru a/include/asm-arm/arch-sa1100/uncompress.h b/include/asm-arm/arch-sa1100/uncompress.h
--- a/include/asm-arm/arch-sa1100/uncompress.h	2004-10-18 14:56:29 -07:00
+++ b/include/asm-arm/arch-sa1100/uncompress.h	2004-10-18 14:56:29 -07:00
@@ -17,7 +17,7 @@
 
 #define UART(x)		(*(volatile unsigned long *)(serial_port + (x)))
 
-static void puts( const char *s )
+static void putstr( const char *s )
 {
 	unsigned long serial_port;
 
diff -Nru a/include/asm-arm/arch-shark/uncompress.h b/include/asm-arm/arch-shark/uncompress.h
--- a/include/asm-arm/arch-shark/uncompress.h	2004-10-18 14:56:27 -07:00
+++ b/include/asm-arm/arch-shark/uncompress.h	2004-10-18 14:56:27 -07:00
@@ -21,7 +21,7 @@
 /*
  * This does not append a newline
  */
-static void puts(const char *s)
+static void putstr(const char *s)
 {
 	while (*s) {
 		putc(*s);
diff -Nru a/include/asm-arm/arch-versatile/uncompress.h b/include/asm-arm/arch-versatile/uncompress.h
--- a/include/asm-arm/arch-versatile/uncompress.h	2004-10-18 14:57:05 -07:00
+++ b/include/asm-arm/arch-versatile/uncompress.h	2004-10-18 14:57:05 -07:00
@@ -25,7 +25,7 @@
 /*
  * This does not append a newline
  */
-static void puts(const char *s)
+static void putstr(const char *s)
 {
 	while (*s) {
 		while (AMBA_UART_FR & (1 << 5))
diff -Nru a/include/asm-arm/atomic.h b/include/asm-arm/atomic.h
--- a/include/asm-arm/atomic.h	2004-10-18 14:55:55 -07:00
+++ b/include/asm-arm/atomic.h	2004-10-18 14:55:55 -07:00
@@ -44,21 +44,6 @@
 	: "cc");
 }
 
-static inline void atomic_add(int i, atomic_t *v)
-{
-	unsigned long tmp, tmp2;
-
-	__asm__ __volatile__("@ atomic_add\n"
-"1:	ldrex	%0, [%2]\n"
-"	add	%0, %0, %3\n"
-"	strex	%1, %0, [%2]\n"
-"	teq	%1, #0\n"
-"	bne	1b"
-	: "=&r" (tmp), "=&r" (tmp2)
-	: "r" (&v->counter), "Ir" (i)
-	: "cc");
-}
-
 static inline int atomic_add_return(int i, atomic_t *v)
 {
 	unsigned long tmp;
@@ -77,21 +62,6 @@
 	return result;
 }
 
-static inline void atomic_sub(int i, atomic_t *v)
-{
-	unsigned long tmp, tmp2;
-
-	__asm__ __volatile__("@ atomic_sub\n"
-"1:	ldrex	%0, [%2]\n"
-"	sub	%0, %0, %3\n"
-"	strex	%1, %0, [%2]\n"
-"	teq	%1, #0\n"
-"	bne	1b"
-	: "=&r" (tmp), "=&r" (tmp2)
-	: "r" (&v->counter), "Ir" (i)
-	: "cc");
-}
-
 static inline int atomic_sub_return(int i, atomic_t *v)
 {
 	unsigned long tmp;
@@ -135,15 +105,6 @@
 
 #define atomic_set(v,i)	(((v)->counter) = (i))
 
-static inline void atomic_add(int i, atomic_t *v)
-{
-	unsigned long flags;
-
-	local_irq_save(flags);
-	v->counter += i;
-	local_irq_restore(flags);
-}
-
 static inline int atomic_add_return(int i, atomic_t *v)
 {
 	unsigned long flags;
@@ -157,15 +118,6 @@
 	return val;
 }
 
-static inline void atomic_sub(int i, atomic_t *v)
-{
-	unsigned long flags;
-
-	local_irq_save(flags);
-	v->counter -= i;
-	local_irq_restore(flags);
-}
-
 static inline int atomic_sub_return(int i, atomic_t *v)
 {
 	unsigned long flags;
@@ -190,8 +142,10 @@
 
 #endif /* __LINUX_ARM_ARCH__ */
 
-#define atomic_inc(v)		atomic_add(1, v)
-#define atomic_dec(v)		atomic_sub(1, v)
+#define atomic_add(i, v)	(void) atomic_add_return(i, v)
+#define atomic_inc(v)		(void) atomic_add_return(1, v)
+#define atomic_sub(i, v)	(void) atomic_sub_return(i, v)
+#define atomic_dec(v)		(void) atomic_sub_return(1, v)
 
 #define atomic_inc_and_test(v)	(atomic_add_return(1, v) == 0)
 #define atomic_dec_and_test(v)	(atomic_sub_return(1, v) == 0)
diff -Nru a/include/asm-arm/bitops.h b/include/asm-arm/bitops.h
--- a/include/asm-arm/bitops.h	2004-10-18 14:55:54 -07:00
+++ b/include/asm-arm/bitops.h	2004-10-18 14:55:54 -07:00
@@ -345,7 +345,7 @@
 extern __inline__ int generic_fls(int x);
 #define fls(x) \
 	( __builtin_constant_p(x) ? generic_fls(x) : \
-	  ({ int __r; asm("clz%?\t%0, %1" : "=r"(__r) : "r"(x)); 32-__r; }) )
+	  ({ int __r; asm("clz\t%0, %1" : "=r"(__r) : "r"(x) : "cc"); 32-__r; }) )
 #define ffs(x) ({ unsigned long __t = (x); fls(__t & -__t); })
 #define __ffs(x) (ffs(x) - 1)
 #define ffz(x) __ffs( ~(x) )
diff -Nru a/include/asm-arm/bug.h b/include/asm-arm/bug.h
--- a/include/asm-arm/bug.h	2004-10-18 14:55:54 -07:00
+++ b/include/asm-arm/bug.h	2004-10-18 14:55:54 -07:00
@@ -8,23 +8,15 @@
 
 /* give file/line information */
 #define BUG()		__bug(__FILE__, __LINE__, NULL)
-#define PAGE_BUG(page)	__bug(__FILE__, __LINE__, page)
 
 #else
 
-/* these just cause an oops */
+/* this just causes an oops */
 #define BUG()		(*(int *)0 = 0)
-#define PAGE_BUG(page)	(*(int *)0 = 0)
 
 #endif
 
-#define BUG_ON(condition) do { if (unlikely((condition)!=0)) BUG(); } while(0)
-
-#define WARN_ON(condition) do { \
-	if (unlikely((condition)!=0)) { \
-		printk("Badness in %s at %s:%d\n", __FUNCTION__, __FILE__, __LINE__); \
-		dump_stack(); \
-	} \
-} while (0)
+#define HAVE_ARCH_BUG
+#include <asm-generic/bug.h>
 
 #endif
diff -Nru a/include/asm-arm/cacheflush.h b/include/asm-arm/cacheflush.h
--- a/include/asm-arm/cacheflush.h	2004-10-18 14:57:03 -07:00
+++ b/include/asm-arm/cacheflush.h	2004-10-18 14:57:03 -07:00
@@ -157,6 +157,7 @@
 	void (*flush_user_range)(unsigned long, unsigned long, unsigned int);
 
 	void (*coherent_kern_range)(unsigned long, unsigned long);
+	void (*coherent_user_range)(unsigned long, unsigned long);
 	void (*flush_kern_dcache_page)(void *);
 
 	void (*dma_inv_range)(unsigned long, unsigned long);
@@ -175,6 +176,7 @@
 #define __cpuc_flush_user_all		cpu_cache.flush_user_all
 #define __cpuc_flush_user_range		cpu_cache.flush_user_range
 #define __cpuc_coherent_kern_range	cpu_cache.coherent_kern_range
+#define __cpuc_coherent_user_range	cpu_cache.coherent_user_range
 #define __cpuc_flush_dcache_page	cpu_cache.flush_kern_dcache_page
 
 /*
@@ -193,12 +195,14 @@
 #define __cpuc_flush_user_all		__glue(_CACHE,_flush_user_cache_all)
 #define __cpuc_flush_user_range		__glue(_CACHE,_flush_user_cache_range)
 #define __cpuc_coherent_kern_range	__glue(_CACHE,_coherent_kern_range)
+#define __cpuc_coherent_user_range	__glue(_CACHE,_coherent_user_range)
 #define __cpuc_flush_dcache_page	__glue(_CACHE,_flush_kern_dcache_page)
 
 extern void __cpuc_flush_kern_all(void);
 extern void __cpuc_flush_user_all(void);
 extern void __cpuc_flush_user_range(unsigned long, unsigned long, unsigned int);
 extern void __cpuc_coherent_kern_range(unsigned long, unsigned long);
+extern void __cpuc_coherent_user_range(unsigned long, unsigned long);
 extern void __cpuc_flush_dcache_page(void *);
 
 /*
@@ -233,11 +237,17 @@
  * space" model to handle this.
  */
 #define copy_to_user_page(vma, page, vaddr, dst, src, len) \
-do { memcpy(dst, src, len); \
-     flush_icache_user_range(vma, page, vaddr, len); \
-} while (0)
+	do {					\
+		flush_cache_page(vma, vaddr);	\
+		memcpy(dst, src, len);		\
+		flush_dcache_page(page);	\
+	} while (0)
+
 #define copy_from_user_page(vma, page, vaddr, dst, src, len) \
-	memcpy(dst, src, len)
+	do {					\
+		flush_cache_page(vma, vaddr);	\
+		memcpy(dst, src, len);		\
+	} while (0)
 
 /*
  * Convert calls to our calling convention.
@@ -266,6 +276,14 @@
 		__cpuc_flush_user_range(addr, addr + PAGE_SIZE, vma->vm_flags);
 	}
 }
+
+/*
+ * flush_cache_user_range is used when we want to ensure that the
+ * Harvard caches are synchronised for the user space address range.
+ * This is used for the ARM private sys_cacheflush system call.
+ */
+#define flush_cache_user_range(vma,start,end) \
+	__cpuc_coherent_user_range((start) & PAGE_MASK, PAGE_ALIGN(end))
 
 /*
  * Perform necessary cache operations to ensure that data previously
diff -Nru a/include/asm-arm/checksum.h b/include/asm-arm/checksum.h
--- a/include/asm-arm/checksum.h	2004-10-18 14:57:03 -07:00
+++ b/include/asm-arm/checksum.h	2004-10-18 14:57:03 -07:00
@@ -37,7 +37,7 @@
 csum_partial_copy_nocheck(const char *src, char *dst, int len, int sum);
 
 unsigned int
-csum_partial_copy_from_user(const char *src, char *dst, int len, int sum, int *err_ptr);
+csum_partial_copy_from_user(const char __user *src, char *dst, int len, int sum, int *err_ptr);
 
 /*
  * This is the old (and unsafe) way of doing checksums, a warning message will
diff -Nru a/include/asm-arm/elf.h b/include/asm-arm/elf.h
--- a/include/asm-arm/elf.h	2004-10-18 14:57:03 -07:00
+++ b/include/asm-arm/elf.h	2004-10-18 14:57:03 -07:00
@@ -1,6 +1,8 @@
 #ifndef __ASMARM_ELF_H
 #define __ASMARM_ELF_H
 
+#include <linux/config.h>
+
 /*
  * ELF register definitions..
  */
@@ -14,6 +16,7 @@
 
 #define EM_ARM	40
 #define EF_ARM_APCS26 0x08
+#define EF_ARM_SOFT_FLOAT 0x200
 
 #define R_ARM_NONE	0
 #define R_ARM_PC24	1
@@ -91,6 +94,8 @@
 	(( (elf_hwcap & HWCAP_26BIT) && (x)->e_flags & EF_ARM_APCS26) || \
 	  ((x)->e_flags & EF_ARM_APCS26) == 0)
 
+#ifndef CONFIG_IWMMXT
+
 /* Old NetWinder binaries were compiled in such a way that the iBCS
    heuristic always trips on them.  Until these binaries become uncommon
    enough not to care, don't trust the `ibcs' flag here.  In any case
@@ -98,6 +103,28 @@
    @@ Could print a warning message to encourage users to upgrade.  */
 #define SET_PERSONALITY(ex,ibcs2) \
 	set_personality(((ex).e_flags&EF_ARM_APCS26 ?PER_LINUX :PER_LINUX_32BIT))
+
+#else
+
+/*
+ * All iWMMXt capable CPUs don't support 26-bit mode.  Yet they can run
+ * legacy binaries which used to contain FPA11 floating point instructions
+ * that have always been emulated by the kernel.  PFA11 and iWMMXt overlap
+ * on coprocessor 1 space though.  We therefore must decide if given task
+ * is allowed to use CP 0 and 1 for iWMMXt, or if they should be blocked
+ * at all times for the prefetch exception handler to catch FPA11 opcodes
+ * and emulate them.  The best indication to discriminate those two cases
+ * is the SOFT_FLOAT flag in the ELF header.
+ */
+
+#define SET_PERSONALITY(ex,ibcs2) \
+do { \
+	set_personality(PER_LINUX_32BIT); \
+	if ((ex).e_flags & EF_ARM_SOFT_FLOAT) \
+		set_thread_flag(TIF_USING_IWMMXT); \
+} while (0)
+
+#endif
 
 #endif
 
diff -Nru a/include/asm-arm/fpstate.h b/include/asm-arm/fpstate.h
--- a/include/asm-arm/fpstate.h	2004-10-18 14:57:04 -07:00
+++ b/include/asm-arm/fpstate.h	2004-10-18 14:57:04 -07:00
@@ -11,7 +11,7 @@
 #ifndef __ASM_ARM_FPSTATE_H
 #define __ASM_ARM_FPSTATE_H
 
-#define FP_SIZE 35
+#include <linux/config.h>
 
 #ifndef __ASSEMBLY__
 
@@ -43,18 +43,31 @@
 extern void vfp_flush_thread(union vfp_state *);
 extern void vfp_release_thread(union vfp_state *);
 
+#define FP_HARD_SIZE 35
+
 struct fp_hard_struct {
-	unsigned int save[FP_SIZE];		/* as yet undefined */
+	unsigned int save[FP_HARD_SIZE];		/* as yet undefined */
 };
 
+#define FP_SOFT_SIZE 35
+
 struct fp_soft_struct {
-	unsigned int save[FP_SIZE];		/* undefined information */
+	unsigned int save[FP_SOFT_SIZE];		/* undefined information */
+};
+
+struct iwmmxt_struct {
+	unsigned int save[0x98/sizeof(int) + 1];
 };
 
 union fp_state {
 	struct fp_hard_struct	hard;
 	struct fp_soft_struct	soft;
+#ifdef CONFIG_IWMMXT
+	struct iwmmxt_struct	iwmmxt;
+#endif
 };
+
+#define FP_SIZE (sizeof(union fp_state) / sizeof(int))
 
 #endif
 
diff -Nru a/include/asm-arm/hardirq.h b/include/asm-arm/hardirq.h
--- a/include/asm-arm/hardirq.h	2004-10-18 14:56:33 -07:00
+++ b/include/asm-arm/hardirq.h	2004-10-18 14:56:33 -07:00
@@ -22,31 +22,25 @@
  *
  * - bits 0-7 are the preemption count (max depth: 256)
  * - bits 8-15 are the softirq count (max # of softirqs: 256)
- * - bits 16-23 are the hardirq count (max # of hardirqs: 256)
+ * - bits 16-24 are the hardirq count (max # of hardirqs: 512)
  * - bit 26 is the PREEMPT_ACTIVE flag
+ *
+ * We optimize HARDIRQ_BITS for immediate constant, and only
+ * increase it if really needed.
  */
 #define PREEMPT_BITS	8
 #define SOFTIRQ_BITS	8
+
+#if NR_IRQS > 256
+#define HARDIRQ_BITS	9
+#else
 #define HARDIRQ_BITS	8
+#endif
 
 #define PREEMPT_SHIFT	0
 #define SOFTIRQ_SHIFT	(PREEMPT_SHIFT + PREEMPT_BITS)
 #define HARDIRQ_SHIFT	(SOFTIRQ_SHIFT + SOFTIRQ_BITS)
 
-#define __MASK(x)	((1UL << (x))-1)
-
-#define PREEMPT_MASK	(__MASK(PREEMPT_BITS) << PREEMPT_SHIFT)
-#define HARDIRQ_MASK	(__MASK(HARDIRQ_BITS) << HARDIRQ_SHIFT)
-#define SOFTIRQ_MASK	(__MASK(SOFTIRQ_BITS) << SOFTIRQ_SHIFT)
-
-#define hardirq_count()	(preempt_count() & HARDIRQ_MASK)
-#define softirq_count()	(preempt_count() & SOFTIRQ_MASK)
-#define irq_count()	(preempt_count() & (HARDIRQ_MASK|SOFTIRQ_MASK))
-
-#define PREEMPT_OFFSET	(1UL << PREEMPT_SHIFT)
-#define SOFTIRQ_OFFSET	(1UL << SOFTIRQ_SHIFT)
-#define HARDIRQ_OFFSET	(1UL << HARDIRQ_SHIFT)
-
 /*
  * The hardirq mask has to be large enough to have space
  * for potentially all IRQ sources in the system nesting
@@ -56,29 +50,9 @@
 # error HARDIRQ_BITS is too low!
 #endif
 
-/*
- * Are we doing bottom half or hardware interrupt processing?
- * Are we in a softirq context? Interrupt context?
- */
-#define in_irq()		(hardirq_count())
-#define in_softirq()		(softirq_count())
-#define in_interrupt()		(irq_count())
-
-#define hardirq_trylock()	(!in_interrupt())
-#define hardirq_endlock()	do { } while (0)
-
 #define irq_enter()		(preempt_count() += HARDIRQ_OFFSET)
 
-#ifdef CONFIG_PREEMPT
-# define in_atomic()	((preempt_count() & ~PREEMPT_ACTIVE) != kernel_locked())
-# define IRQ_EXIT_OFFSET (HARDIRQ_OFFSET-1)
-#else
-# define in_atomic()	(preempt_count() != 0)
-# define IRQ_EXIT_OFFSET HARDIRQ_OFFSET
-#endif
-
 #ifndef CONFIG_SMP
-
 extern asmlinkage void __do_softirq(void);
 
 #define irq_exit()							\
@@ -88,10 +62,6 @@
 			__do_softirq();					\
 		preempt_enable_no_resched();				\
 	} while (0)
-
-#define synchronize_irq(irq)	barrier()
-#else
-extern void synchronize_irq(unsigned int irq);
 #endif
 
 #endif /* __ASM_HARDIRQ_H */
diff -Nru a/include/asm-arm/hardware/amba_clcd.h b/include/asm-arm/hardware/amba_clcd.h
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/include/asm-arm/hardware/amba_clcd.h	2004-10-18 14:57:23 -07:00
@@ -0,0 +1,259 @@
+/*
+ * linux/include/asm-arm/hardware/amba_clcd.h -- Integrator LCD panel.
+ *
+ * David A Rusling
+ *
+ * Copyright (C) 2001 ARM Limited
+ *
+ * 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.
+ */
+#include <linux/config.h>
+#include <linux/fb.h>
+
+/*
+ * CLCD Controller Internal Register addresses
+ */
+#define CLCD_TIM0		0x00000000
+#define CLCD_TIM1 		0x00000004
+#define CLCD_TIM2 		0x00000008
+#define CLCD_TIM3 		0x0000000c
+#define CLCD_UBAS 		0x00000010
+#define CLCD_LBAS 		0x00000014
+
+#ifndef CONFIG_ARCH_VERSATILE_PB
+#define CLCD_IENB 		0x00000018
+#define CLCD_CNTL 		0x0000001c
+#else
+/*
+ * Someone rearranged these two registers on the Versatile
+ * platform...
+ */
+#define CLCD_IENB 		0x0000001c
+#define CLCD_CNTL 		0x00000018
+#endif
+
+#define CLCD_STAT 		0x00000020
+#define CLCD_INTR 		0x00000024
+#define CLCD_UCUR 		0x00000028
+#define CLCD_LCUR 		0x0000002C
+#define CLCD_PALL 		0x00000200
+#define CLCD_PALETTE		0x00000200
+
+#define TIM2_CLKSEL		(1 << 5)
+#define TIM2_IVS		(1 << 11)
+#define TIM2_IHS		(1 << 12)
+#define TIM2_IPC		(1 << 13)
+#define TIM2_IOE		(1 << 14)
+#define TIM2_BCD		(1 << 26)
+
+#define CNTL_LCDEN		(1 << 0)
+#define CNTL_LCDBPP1		(0 << 1)
+#define CNTL_LCDBPP2		(1 << 1)
+#define CNTL_LCDBPP4		(2 << 1)
+#define CNTL_LCDBPP8		(3 << 1)
+#define CNTL_LCDBPP16		(4 << 1)
+#define CNTL_LCDBPP24		(5 << 1)
+#define CNTL_LCDBW		(1 << 4)
+#define CNTL_LCDTFT		(1 << 5)
+#define CNTL_LCDMONO8		(1 << 6)
+#define CNTL_LCDDUAL		(1 << 7)
+#define CNTL_BGR		(1 << 8)
+#define CNTL_BEBO		(1 << 9)
+#define CNTL_BEPO		(1 << 10)
+#define CNTL_LCDPWR		(1 << 11)
+#define CNTL_LCDVCOMP(x)	((x) << 12)
+#define CNTL_LDMAFIFOTIME	(1 << 15)
+#define CNTL_WATERMARK		(1 << 16)
+
+struct clcd_panel {
+	struct fb_videomode	mode;
+	signed short		width;	/* width in mm */
+	signed short		height;	/* height in mm */
+	u32			tim2;
+	u32			tim3;
+	u32			cntl;
+	unsigned int		bpp:8,
+				fixedtimings:1,
+				grayscale:1;
+	unsigned int		connector;
+};
+
+struct clcd_regs {
+	u32			tim0;
+	u32			tim1;
+	u32			tim2;
+	u32			tim3;
+	u32			cntl;
+	unsigned long		pixclock;
+};
+
+struct clcd_fb;
+
+/*
+ * the board-type specific routines
+ */
+struct clcd_board {
+	const char *name;
+
+	/*
+	 * Optional.  Check whether the var structure is acceptable
+	 * for this display.
+	 */
+	int	(*check)(struct clcd_fb *fb, struct fb_var_screeninfo *var);
+
+	/*
+	 * Compulsary.  Decode fb->fb.var into regs->*.  In the case of
+	 * fixed timing, set regs->* to the register values required.
+	 */
+	void	(*decode)(struct clcd_fb *fb, struct clcd_regs *regs);
+
+	/*
+	 * Optional.  Disable any extra display hardware.
+	 */
+	void	(*disable)(struct clcd_fb *);
+
+	/*
+	 * Optional.  Enable any extra display hardware.
+	 */
+	void	(*enable)(struct clcd_fb *);
+
+	/*
+	 * Setup platform specific parts of CLCD driver
+	 */
+	int	(*setup)(struct clcd_fb *);
+
+	/*
+	 * Remove platform specific parts of CLCD driver
+	 */
+	void	(*remove)(struct clcd_fb *);
+};
+
+struct amba_device;
+struct clk;
+
+/* this data structure describes each frame buffer device we find */
+struct clcd_fb {
+	struct fb_info		fb;
+	struct amba_device	*dev;
+	struct clk		*clk;
+	struct clcd_panel	*panel;
+	struct clcd_board	*board;
+	void			*board_data;
+	void			*regs;
+	u32			clcd_cntl;
+	u32			cmap[16];
+};
+
+static inline void clcdfb_decode(struct clcd_fb *fb, struct clcd_regs *regs)
+{
+	u32 val;
+
+	/*
+	 * Program the CLCD controller registers and start the CLCD
+	 */
+	val = ((fb->fb.var.xres / 16) - 1) << 2;
+	val |= (fb->fb.var.hsync_len - 1) << 8;
+	val |= (fb->fb.var.right_margin - 1) << 16;
+	val |= (fb->fb.var.left_margin - 1) << 24;
+	regs->tim0 = val;
+
+	val = fb->fb.var.yres - 1;
+	val |= (fb->fb.var.vsync_len - 1) << 10;
+	val |= fb->fb.var.lower_margin << 16;
+	val |= fb->fb.var.upper_margin << 24;
+	regs->tim1 = val;
+
+	val = fb->panel->tim2;
+	val |= fb->fb.var.sync & FB_SYNC_HOR_HIGH_ACT  ? 0 : TIM2_IHS;
+	val |= fb->fb.var.sync & FB_SYNC_VERT_HIGH_ACT ? 0 : TIM2_IVS;
+
+	if (fb->panel->cntl & CNTL_LCDTFT)
+		val |= (fb->fb.var.xres_virtual - 1) << 16;
+	else if (fb->panel->cntl & CNTL_LCDBW)
+		printk("what value for CPL for stnmono panels?");
+	else
+		val |= ((fb->fb.var.xres_virtual * 8 / 3) - 1) << 16;
+	regs->tim2 = val;
+
+	regs->tim3 = fb->panel->tim3;
+
+	val = fb->panel->cntl;
+	if (fb->fb.var.grayscale)
+		val |= CNTL_LCDBW;
+
+	switch (fb->fb.var.bits_per_pixel) {
+	case 1:
+		val |= CNTL_LCDBPP1;
+		break;
+	case 2:
+		val |= CNTL_LCDBPP2;
+		break;
+	case 4:
+		val |= CNTL_LCDBPP4;
+		break;
+	case 8:
+		val |= CNTL_LCDBPP8;
+		break;
+	case 16:
+		val |= CNTL_LCDBPP16;
+		break;
+	case 24:
+		val |= CNTL_LCDBPP24;
+		break;
+	}
+
+	regs->cntl = val;
+	regs->pixclock = fb->fb.var.pixclock;
+}
+
+static inline int clcdfb_check(struct clcd_fb *fb, struct fb_var_screeninfo *var)
+{
+	var->xres_virtual = var->xres = (var->xres + 7) & ~7;
+	var->yres_virtual = var->yres;
+
+#define CHECK(e,l,h) (var->e < l || var->e > h)
+	if (CHECK(right_margin, (5+1), 256) ||	/* back porch */
+	    CHECK(left_margin, (5+1), 256) ||	/* front porch */
+	    CHECK(hsync_len, (5+1), 256) ||
+	    var->xres > 4096 ||
+	    var->lower_margin > 255 ||		/* back porch */
+	    var->upper_margin > 255 ||		/* front porch */
+	    var->vsync_len > 32 ||
+	    var->yres > 1024)
+		return -EINVAL;
+#undef CHECK
+
+	/* single panel mode: PCD = max(PCD, 1) */
+	/* dual panel mode: PCD = max(PCD, 5) */
+
+	/*
+	 * You can't change the grayscale setting, and
+	 * we can only do non-interlaced video.
+	 */
+	if (var->grayscale != fb->fb.var.grayscale ||
+	    (var->vmode & FB_VMODE_MASK) != FB_VMODE_NONINTERLACED)
+		return -EINVAL;
+
+#define CHECK(e) (var->e != fb->fb.var.e)
+	if (fb->panel->fixedtimings &&
+	    (CHECK(xres)		||
+	     CHECK(yres)		||
+	     CHECK(bits_per_pixel)	||
+	     CHECK(pixclock)		||
+	     CHECK(left_margin)		||
+	     CHECK(right_margin)	||
+	     CHECK(upper_margin)	||
+	     CHECK(lower_margin)	||
+	     CHECK(hsync_len)		||
+	     CHECK(vsync_len)		||
+	     CHECK(sync)))
+		return -EINVAL;
+#undef CHECK
+
+	var->nonstd = 0;
+	var->accel_flags = 0;
+
+	return 0;
+}
diff -Nru a/include/asm-arm/hardware/clock.h b/include/asm-arm/hardware/clock.h
--- a/include/asm-arm/hardware/clock.h	2004-10-18 14:56:27 -07:00
+++ b/include/asm-arm/hardware/clock.h	2004-10-18 14:56:27 -07:00
@@ -64,7 +64,7 @@
 void clk_unuse(struct clk *clk);
 
 /**
- * clk_get_rate - obtain the current clock rate for a clock source.
+ * clk_get_rate - obtain the current clock rate (in Hz) for a clock source.
  *		  This is only valid once the clock source has been enabled.
  * @clk: clock source
  */
@@ -85,16 +85,16 @@
 /**
  * clk_round_rate - adjust a rate to the exact rate a clock can provide
  * @clk: clock source
- * @rate: desired clock rate in kHz
+ * @rate: desired clock rate in Hz
  *
- * Returns rounded clock rate, or negative errno.
+ * Returns rounded clock rate in Hz, or negative errno.
  */
 long clk_round_rate(struct clk *clk, unsigned long rate);
  
 /**
  * clk_set_rate - set the clock rate for a clock source
  * @clk: clock source
- * @rate: desired clock rate in kHz
+ * @rate: desired clock rate in Hz
  *
  * Returns success (0) or negative errno.
  */
diff -Nru a/include/asm-arm/hardware.h b/include/asm-arm/hardware.h
--- a/include/asm-arm/hardware.h	2004-10-18 14:55:54 -07:00
+++ b/include/asm-arm/hardware.h	2004-10-18 14:55:54 -07:00
@@ -15,13 +15,4 @@
 
 #include <asm/arch/hardware.h>
 
-#ifndef __ASSEMBLY__
-
-struct platform_device;
-
-extern int platform_add_devices(struct platform_device **, int);
-extern int platform_add_device(struct platform_device *);
-
-#endif
-
 #endif
diff -Nru a/include/asm-arm/io.h b/include/asm-arm/io.h
--- a/include/asm-arm/io.h	2004-10-18 14:56:28 -07:00
+++ b/include/asm-arm/io.h	2004-10-18 14:56:28 -07:00
@@ -271,10 +271,12 @@
 #ifndef __arch_ioremap
 #define ioremap(cookie,size)		__ioremap(cookie,size,0,1)
 #define ioremap_nocache(cookie,size)	__ioremap(cookie,size,0,1)
+#define ioremap_cached(cookie,size)	__ioremap(cookie,size,L_PTE_CACHEABLE,1)
 #define iounmap(cookie)			__iounmap(cookie)
 #else
 #define ioremap(cookie,size)		__arch_ioremap((cookie),(size),0,1)
 #define ioremap_nocache(cookie,size)	__arch_ioremap((cookie),(size),0,1)
+#define ioremap_cached(cookie,size)	__arch_ioremap((cookie),(size),L_PTE_CACHEABLE,1)
 #define iounmap(cookie)			__arch_iounmap(cookie)
 #endif
 
diff -Nru a/include/asm-arm/mach/mmc.h b/include/asm-arm/mach/mmc.h
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/include/asm-arm/mach/mmc.h	2004-10-18 14:57:24 -07:00
@@ -0,0 +1,16 @@
+/*
+ *  linux/include/asm-arm/mach/mmc.h
+ */
+#ifndef ASMARM_MACH_MMC_H
+#define ASMARM_MACH_MMC_H
+
+#include <linux/mmc/protocol.h>
+
+struct mmc_platform_data {
+	unsigned int mclk;			/* mmc base clock rate */
+	unsigned int ocr_mask;			/* available voltages */
+	u32 (*translate_vdd)(struct device *, unsigned int);
+	unsigned int (*status)(struct device *);
+};
+
+#endif
diff -Nru a/include/asm-arm/mach/pci.h b/include/asm-arm/mach/pci.h
--- a/include/asm-arm/mach/pci.h	2004-10-18 14:56:32 -07:00
+++ b/include/asm-arm/mach/pci.h	2004-10-18 14:56:32 -07:00
@@ -52,13 +52,13 @@
 /*
  * PCI controllers
  */
-extern int iop310_setup(int nr, struct pci_sys_data *);
-extern struct pci_bus *iop310_scan_bus(int nr, struct pci_sys_data *);
-extern void iop310_init(void);
-
 extern int iop321_setup(int nr, struct pci_sys_data *);
 extern struct pci_bus *iop321_scan_bus(int nr, struct pci_sys_data *);
 extern void iop321_init(void);
+
+extern int iop331_setup(int nr, struct pci_sys_data *);
+extern struct pci_bus *iop331_scan_bus(int nr, struct pci_sys_data *);
+extern void iop331_init(void);
 
 extern int dc21285_setup(int nr, struct pci_sys_data *);
 extern struct pci_bus *dc21285_scan_bus(int nr, struct pci_sys_data *);
diff -Nru a/include/asm-arm/mach/time.h b/include/asm-arm/mach/time.h
--- a/include/asm-arm/mach/time.h	2004-10-18 14:56:29 -07:00
+++ b/include/asm-arm/mach/time.h	2004-10-18 14:56:29 -07:00
@@ -13,8 +13,11 @@
 extern void (*init_arch_time)(void);
 
 extern int (*set_rtc)(void);
-extern unsigned long(*gettimeoffset)(void);
+extern unsigned long (*gettimeoffset)(void);
 
-void timer_tick(struct pt_regs *);
+extern void timer_tick(struct pt_regs *);
+
+extern void save_time_delta(struct timespec *delta, struct timespec *rtc);
+extern void restore_time_delta(struct timespec *delta, struct timespec *rtc);
 
 #endif
diff -Nru a/include/asm-arm/memory.h b/include/asm-arm/memory.h
--- a/include/asm-arm/memory.h	2004-10-18 14:57:03 -07:00
+++ b/include/asm-arm/memory.h	2004-10-18 14:57:03 -07:00
@@ -13,6 +13,7 @@
 #define __ASM_ARM_MEMORY_H
 
 #include <linux/config.h>
+#include <linux/compiler.h>
 #include <asm/arch/memory.h>
 
 #ifndef TASK_SIZE
@@ -108,10 +109,18 @@
 /*
  * Virtual <-> DMA view memory address translations
  * Again, these are *only* valid on the kernel direct mapped RAM
- * memory.  Use of these is *deprecated*.
+ * memory.  Use of these is *deprecated* (and that doesn't mean
+ * use the __ prefixed forms instead.)  See dma-mapping.h.
  */
-#define virt_to_bus(x)		(__virt_to_bus((unsigned long)(x)))
-#define bus_to_virt(x)		((void *)(__bus_to_virt((unsigned long)(x))))
+static inline __deprecated unsigned long virt_to_bus(void *x)
+{
+	return __virt_to_bus((unsigned long)x);
+}
+
+static inline __deprecated void *bus_to_virt(unsigned long x)
+{
+	return (void *)__bus_to_virt(x);
+}
 
 /*
  * Conversion between a struct page and a physical address.
@@ -177,9 +186,9 @@
  * We should really eliminate virt_to_bus() here - it's deprecated.
  */
 #ifndef __arch_page_to_dma
-#define page_to_dma(dev, page)		((dma_addr_t)__virt_to_bus(page_address(page)))
-#define dma_to_virt(dev, addr)		(__bus_to_virt(addr))
-#define virt_to_dma(dev, addr)		(__virt_to_bus(addr))
+#define page_to_dma(dev, page)		((dma_addr_t)__virt_to_bus((unsigned long)page_address(page)))
+#define dma_to_virt(dev, addr)		((void *)__bus_to_virt(addr))
+#define virt_to_dma(dev, addr)		((dma_addr_t)__virt_to_bus((unsigned long)(addr)))
 #else
 #define page_to_dma(dev, page)		(__arch_page_to_dma(dev, page))
 #define dma_to_virt(dev, addr)		(__arch_dma_to_virt(dev, addr))
diff -Nru a/include/asm-arm/page.h b/include/asm-arm/page.h
--- a/include/asm-arm/page.h	2004-10-18 14:56:16 -07:00
+++ b/include/asm-arm/page.h	2004-10-18 14:56:16 -07:00
@@ -133,7 +133,7 @@
 	} while (0)
 
 #define clear_page(page)	memzero((void *)(page), PAGE_SIZE)
-extern void copy_page(void *to, void *from);
+extern void copy_page(void *to, const void *from);
 
 #undef STRICT_MM_TYPECHECKS
 
diff -Nru a/include/asm-arm/param.h b/include/asm-arm/param.h
--- a/include/asm-arm/param.h	2004-10-18 14:56:32 -07:00
+++ b/include/asm-arm/param.h	2004-10-18 14:56:32 -07:00
@@ -10,14 +10,13 @@
 #ifndef __ASM_PARAM_H
 #define __ASM_PARAM_H
 
-#include <asm/arch/param.h>	/* for HZ */
+#ifdef __KERNEL__
+# include <asm/arch/param.h>		/* for kernel version of HZ */
 
-#ifndef __KERNEL_HZ
-#define __KERNEL_HZ	100
-#endif
+# ifndef HZ
+#  define HZ		100		/* Internal kernel timer frequency */
+# endif
 
-#ifdef __KERNEL__
-# define HZ		__KERNEL_HZ	/* Internal kernel timer frequency */
 # define USER_HZ	100		/* User interfaces are in "ticks" */
 # define CLOCKS_PER_SEC	(USER_HZ)	/* like times() */
 #else
diff -Nru a/include/asm-arm/ptrace.h b/include/asm-arm/ptrace.h
--- a/include/asm-arm/ptrace.h	2004-10-18 14:56:33 -07:00
+++ b/include/asm-arm/ptrace.h	2004-10-18 14:56:33 -07:00
@@ -131,6 +131,12 @@
 #define instruction_pointer(regs) \
 	(pc_pointer((regs)->ARM_pc))
 
+#ifdef CONFIG_SMP
+extern unsigned long profile_pc(struct pt_regs *regs);
+#else
+#define profile_pc(regs) instruction_pointer(regs)
+#endif
+
 #ifdef __KERNEL__
 extern void show_regs(struct pt_regs *);
 
diff -Nru a/include/asm-arm/resource.h b/include/asm-arm/resource.h
--- a/include/asm-arm/resource.h	2004-10-18 14:56:50 -07:00
+++ b/include/asm-arm/resource.h	2004-10-18 14:56:50 -07:00
@@ -39,7 +39,7 @@
 	{ RLIM_INFINITY, RLIM_INFINITY },	\
 	{ 0,             0             },	\
 	{ INR_OPEN,      INR_OPEN      },	\
-	{ RLIM_INFINITY, RLIM_INFINITY },	\
+	{ MLOCK_LIMIT,	 MLOCK_LIMIT   },	\
 	{ RLIM_INFINITY, RLIM_INFINITY },	\
 	{ RLIM_INFINITY, RLIM_INFINITY },	\
 	{ MAX_SIGPENDING, MAX_SIGPENDING},	\
diff -Nru a/include/asm-arm/semaphore.h b/include/asm-arm/semaphore.h
--- a/include/asm-arm/semaphore.h	2004-10-18 14:56:32 -07:00
+++ b/include/asm-arm/semaphore.h	2004-10-18 14:56:32 -07:00
@@ -16,21 +16,12 @@
 	atomic_t count;
 	int sleepers;
 	wait_queue_head_t wait;
-#ifdef WAITQUEUE_DEBUG
-	long __magic;
-#endif
 };
 
-#ifdef WAITQUEUE_DEBUG
-# define __SEM_DEBUG_INIT(name)	.__magic = (long)&(name).__magic
-#else
-# define __SEM_DEBUG_INIT(name)
-#endif
-
-#define __SEMAPHORE_INIT(name,cnt) {				\
+#define __SEMAPHORE_INIT(name, cnt)				\
+{								\
 	.count	= ATOMIC_INIT(cnt),				\
 	.wait	= __WAIT_QUEUE_HEAD_INITIALIZER((name).wait),	\
-	__SEM_DEBUG_INIT(name)					\
 }
 
 #define __MUTEX_INITIALIZER(name) __SEMAPHORE_INIT(name,1)
@@ -46,9 +37,6 @@
 	atomic_set(&sem->count, val);
 	sem->sleepers = 0;
 	init_waitqueue_head(&sem->wait);
-#ifdef WAITQUEUE_DEBUG
-	sem->__magic = (long)&sem->__magic;
-#endif
 }
 
 static inline void init_MUTEX(struct semaphore *sem)
@@ -85,9 +73,6 @@
  */
 static inline void down(struct semaphore * sem)
 {
-#ifdef WAITQUEUE_DEBUG
-	CHECK_MAGIC(sem->__magic);
-#endif
 	might_sleep();
 	__down_op(sem, __down_failed);
 }
@@ -98,19 +83,12 @@
  */
 static inline int down_interruptible (struct semaphore * sem)
 {
-#ifdef WAITQUEUE_DEBUG
-	CHECK_MAGIC(sem->__magic);
-#endif
 	might_sleep();
 	return __down_op_ret(sem, __down_interruptible_failed);
 }
 
 static inline int down_trylock(struct semaphore *sem)
 {
-#ifdef WAITQUEUE_DEBUG
-	CHECK_MAGIC(sem->__magic);
-#endif
-
 	return __down_op_ret(sem, __down_trylock_failed);
 }
 
@@ -122,10 +100,6 @@
  */
 static inline void up(struct semaphore * sem)
 {
-#ifdef WAITQUEUE_DEBUG
-	CHECK_MAGIC(sem->__magic);
-#endif
-
 	__up_op(sem, __up_wakeup);
 }
 
diff -Nru a/include/asm-arm/socket.h b/include/asm-arm/socket.h
--- a/include/asm-arm/socket.h	2004-10-18 14:56:27 -07:00
+++ b/include/asm-arm/socket.h	2004-10-18 14:56:27 -07:00
@@ -47,20 +47,4 @@
 
 #define SO_PEERSEC		31
 
-/* Nast libc5 fixup - bletch */
-#if defined(__KERNEL__)
-/* Socket types. */
-#define SOCK_STREAM	1		/* stream (connection) socket	*/
-#define SOCK_DGRAM	2		/* datagram (conn.less) socket	*/
-#define SOCK_RAW	3		/* raw socket			*/
-#define SOCK_RDM	4		/* reliably-delivered message	*/
-#define SOCK_SEQPACKET	5		/* sequential packet socket	*/
-#define SOCK_PACKET	10		/* linux specific way of	*/
-					/* getting packets at the dev	*/
-					/* level.  For writing rarp and	*/
-					/* other similar things on the	*/
-					/* user level.			*/
-#define	SOCK_MAX	(SOCK_PACKET+1)
-#endif
-
 #endif /* _ASM_SOCKET_H */
diff -Nru a/include/asm-arm/system.h b/include/asm-arm/system.h
--- a/include/asm-arm/system.h	2004-10-18 14:55:55 -07:00
+++ b/include/asm-arm/system.h	2004-10-18 14:55:55 -07:00
@@ -50,11 +50,45 @@
 #define read_cpuid(reg)							\
 	({								\
 		unsigned int __val;					\
-		asm("mrc%? p15, 0, %0, c0, c0, " __stringify(reg)	\
-		    : "=r" (__val));					\
+		asm("mrc	p15, 0, %0, c0, c0, " __stringify(reg)	\
+		    : "=r" (__val)					\
+		    :							\
+		    : "cc");						\
 		__val;							\
 	})
 
+#define __cacheid_present(val)		(val != read_cpuid(CPUID_ID))
+#define __cacheid_vivt(val)		((val & (15 << 25)) != (14 << 25))
+#define __cacheid_vipt(val)		((val & (15 << 25)) == (14 << 25))
+#define __cacheid_vipt_nonaliasing(val)	((val & (15 << 25 | 1 << 23)) == (14 << 25))
+#define __cacheid_vipt_aliasing(val)	((val & (15 << 25 | 1 << 23)) == (14 << 25 | 1 << 23))
+
+#define cache_is_vivt()							\
+	({								\
+		unsigned int __val = read_cpuid(CPUID_CACHETYPE);	\
+		(!__cacheid_present(__val)) || __cacheid_vivt(__val);	\
+	})
+		
+#define cache_is_vipt()							\
+	({								\
+		unsigned int __val = read_cpuid(CPUID_CACHETYPE);	\
+		__cacheid_present(__val) && __cacheid_vipt(__val);	\
+	})
+
+#define cache_is_vipt_nonaliasing()					\
+	({								\
+		unsigned int __val = read_cpuid(CPUID_CACHETYPE);	\
+		__cacheid_present(__val) &&				\
+		 __cacheid_vipt_nonaliasing(__val);			\
+	})
+
+#define cache_is_vipt_aliasing()					\
+	({								\
+		unsigned int __val = read_cpuid(CPUID_CACHETYPE);	\
+		__cacheid_present(__val) &&				\
+		 __cacheid_vipt_aliasing(__val);			\
+	})
+
 /*
  * This is used to ensure the compiler did actually allocate the register we
  * asked it for some inline assembly sequences.  Apparently we can't trust
@@ -66,9 +100,10 @@
 
 #ifndef __ASSEMBLY__
 
-#include <linux/kernel.h>
+#include <linux/linkage.h>
 
 struct thread_info;
+struct task_struct;
 
 /* information about the system we're running on */
 extern unsigned int system_rev;
@@ -171,8 +206,6 @@
  * `prev' will never be the same as `next'.  schedule() itself
  * contains the memory barrier to tell GCC not to cache `current'.
  */
-struct thread_info;
-struct task_struct;
 extern struct task_struct *__switch_to(struct task_struct *, struct thread_info *, struct thread_info *);
 
 #define switch_to(prev,next,last)					\
diff -Nru a/include/asm-arm/thread_info.h b/include/asm-arm/thread_info.h
--- a/include/asm-arm/thread_info.h	2004-10-18 14:56:29 -07:00
+++ b/include/asm-arm/thread_info.h	2004-10-18 14:56:29 -07:00
@@ -100,23 +100,18 @@
 #define thread_saved_fp(tsk)	\
 	((unsigned long)((tsk)->thread_info->cpu_context.fp))
 
-#else /* !__ASSEMBLY__ */
-
-#define TI_FLAGS	0
-#define TI_PREEMPT	4
-#define TI_ADDR_LIMIT	8
-#define TI_TASK		12
-#define TI_EXEC_DOMAIN	16
-#define TI_CPU		20
-#define TI_CPU_DOMAIN	24
-#define TI_CPU_SAVE	28
-#define TI_USED_CP	76
-#define TI_FPSTATE	(TI_USED_CP+16)
-#define TI_VFPSTATE	(TI_FPSTATE+FP_SIZE*4)
+extern void iwmmxt_task_disable(struct thread_info *);
+extern void iwmmxt_task_copy(struct thread_info *, void *);
+extern void iwmmxt_task_restore(struct thread_info *, void *);
+extern void iwmmxt_task_release(struct thread_info *);
 
 #endif
 
-#define PREEMPT_ACTIVE	0x04000000
+/*
+ * We use bit 30 of the preempt_count to indicate that kernel
+ * preemption is occuring.  See include/asm-arm/hardirq.h.
+ */
+#define PREEMPT_ACTIVE	0x40000000
 
 /*
  * thread information flags:
@@ -131,15 +126,15 @@
 #define TIF_SIGPENDING		1
 #define TIF_NEED_RESCHED	2
 #define TIF_SYSCALL_TRACE	8
-#define TIF_USED_FPU		16
-#define TIF_POLLING_NRFLAG	17
+#define TIF_POLLING_NRFLAG	16
+#define TIF_USING_IWMMXT	17
 
 #define _TIF_NOTIFY_RESUME	(1 << TIF_NOTIFY_RESUME)
 #define _TIF_SIGPENDING		(1 << TIF_SIGPENDING)
 #define _TIF_NEED_RESCHED	(1 << TIF_NEED_RESCHED)
 #define _TIF_SYSCALL_TRACE	(1 << TIF_SYSCALL_TRACE)
-#define _TIF_USED_FPU		(1 << TIF_USED_FPU)
 #define _TIF_POLLING_NRFLAG	(1 << TIF_POLLING_NRFLAG)
+#define _TIF_USING_IWMMXT	(1 << TIF_USING_IWMMXT)
 
 /*
  * Change these and you break ASM code in entry-common.S
diff -Nru a/include/asm-arm/uaccess.h b/include/asm-arm/uaccess.h
--- a/include/asm-arm/uaccess.h	2004-10-18 14:56:33 -07:00
+++ b/include/asm-arm/uaccess.h	2004-10-18 14:56:33 -07:00
@@ -394,6 +394,9 @@
 	return __arch_copy_to_user(to, from, n);
 }
 
+#define __copy_to_user_inatomic __copy_to_user
+#define __copy_from_user_inatomic __copy_from_user
+
 static inline unsigned long clear_user (void __user *to, unsigned long n)
 {
 	if (access_ok(VERIFY_WRITE, to, n))
diff -Nru a/include/asm-arm/unistd.h b/include/asm-arm/unistd.h
--- a/include/asm-arm/unistd.h	2004-10-18 14:57:04 -07:00
+++ b/include/asm-arm/unistd.h	2004-10-18 14:57:04 -07:00
@@ -299,6 +299,13 @@
 #define __NR_pciconfig_iobase		(__NR_SYSCALL_BASE+271)
 #define __NR_pciconfig_read		(__NR_SYSCALL_BASE+272)
 #define __NR_pciconfig_write		(__NR_SYSCALL_BASE+273)
+#define __NR_mq_open			(__NR_SYSCALL_BASE+274)
+#define __NR_mq_unlink			(__NR_SYSCALL_BASE+275)
+#define __NR_mq_timedsend		(__NR_SYSCALL_BASE+276)
+#define __NR_mq_timedreceive		(__NR_SYSCALL_BASE+277)
+#define __NR_mq_notify			(__NR_SYSCALL_BASE+278)
+#define __NR_mq_getsetattr		(__NR_SYSCALL_BASE+279)
+#define __NR_waitid			(__NR_SYSCALL_BASE+280)
 
 /*
  * The following SWIs are ARM private.
@@ -474,51 +481,6 @@
 #include <linux/compiler.h>
 #include <linux/types.h>
 #include <linux/syscalls.h>
-
-static inline pid_t setsid(void)
-{
-	return sys_setsid();
-}
-
-static inline long write(int fd, const char *buf, off_t count)
-{
-	return sys_write(fd, buf, count);
-}
-
-static inline long read(int fd, char *buf, off_t count)
-{
-	return sys_read(fd, buf, count);
-}
-
-static inline off_t lseek(int fd, off_t offset, int count)
-{
-	return sys_lseek(fd, offset, count);
-}
-
-static inline long dup(int fd)
-{
-	return sys_dup(fd);
-}
-
-static inline long open(const char *file, int flag, int mode)
-{
-	return sys_open(file, flag, mode);
-}
-
-static inline long close(int fd)
-{
-	return sys_close(fd);
-}
-
-static inline long _exit(int exitcode)
-{
-	return sys_exit(exitcode);
-}
-
-static inline pid_t waitpid(pid_t pid, int *wait_stat, int options)
-{
-	return sys_wait4((int)pid, wait_stat, options, NULL);
-}
 
 extern long execve(const char *file, char **argv, char **envp);
 
diff -Nru a/include/asm-arm26/bug.h b/include/asm-arm26/bug.h
--- a/include/asm-arm26/bug.h	2004-10-18 14:57:04 -07:00
+++ b/include/asm-arm26/bug.h	2004-10-18 14:57:04 -07:00
@@ -5,26 +5,13 @@
 
 #ifdef CONFIG_DEBUG_BUGVERBOSE
 extern volatile void __bug(const char *file, int line, void *data);
-
 /* give file/line information */
 #define BUG()		__bug(__FILE__, __LINE__, NULL)
-#define PAGE_BUG(page)	__bug(__FILE__, __LINE__, page)
-
 #else
-
-/* these just cause an oops */
 #define BUG()		(*(int *)0 = 0)
-#define PAGE_BUG(page)	(*(int *)0 = 0)
-
 #endif
 
-#define BUG_ON(condition) do { if (unlikely((condition)!=0)) BUG(); } while(0)
-
-#define WARN_ON(condition) do { \
-	if (unlikely((condition)!=0)) { \
-		printk("Badness in %s at %s:%d\n", __FUNCTION__, __FILE__, __LINE__); \
-		dump_stack(); \
-	} \
-} while (0)
+#define HAVE_ARCH_BUG
+#include <asm-generic/bug.h>
 
 #endif
diff -Nru a/include/asm-arm26/hardirq.h b/include/asm-arm26/hardirq.h
--- a/include/asm-arm26/hardirq.h	2004-10-18 14:56:28 -07:00
+++ b/include/asm-arm26/hardirq.h	2004-10-18 14:56:28 -07:00
@@ -32,20 +32,6 @@
 #define SOFTIRQ_SHIFT	(PREEMPT_SHIFT + PREEMPT_BITS)
 #define HARDIRQ_SHIFT	(SOFTIRQ_SHIFT + SOFTIRQ_BITS)
 
-#define __MASK(x)	((1UL << (x))-1)
-
-#define PREEMPT_MASK	(__MASK(PREEMPT_BITS) << PREEMPT_SHIFT)
-#define HARDIRQ_MASK	(__MASK(HARDIRQ_BITS) << HARDIRQ_SHIFT)
-#define SOFTIRQ_MASK	(__MASK(SOFTIRQ_BITS) << SOFTIRQ_SHIFT)
-
-#define hardirq_count()	(preempt_count() & HARDIRQ_MASK)
-#define softirq_count()	(preempt_count() & SOFTIRQ_MASK)
-#define irq_count()	(preempt_count() & (HARDIRQ_MASK|SOFTIRQ_MASK))
-
-#define PREEMPT_OFFSET	(1UL << PREEMPT_SHIFT)
-#define SOFTIRQ_OFFSET	(1UL << SOFTIRQ_SHIFT)
-#define HARDIRQ_OFFSET	(1UL << HARDIRQ_SHIFT)
-
 /*
  * The hardirq mask has to be large enough to have space
  * for potentially all IRQ sources in the system nesting
@@ -55,26 +41,8 @@
 # error HARDIRQ_BITS is too low!
 #endif
 
-/*
- * Are we doing bottom half or hardware interrupt processing?
- * Are we in a softirq context? Interrupt context?
- */
-#define in_irq()		(hardirq_count())
-#define in_softirq()		(softirq_count())
-#define in_interrupt()		(irq_count())
-
-#define hardirq_trylock()	(!in_interrupt())
-#define hardirq_endlock()	do { } while (0)
-
 #define irq_enter()		(preempt_count() += HARDIRQ_OFFSET)
 
-#ifdef CONFIG_PREEMPT
-# define in_atomic()    ((preempt_count() & ~PREEMPT_ACTIVE) != kernel_locked())# define IRQ_EXIT_OFFSET (HARDIRQ_OFFSET-1)
-#else
-# define in_atomic()    (preempt_count() != 0)
-# define IRQ_EXIT_OFFSET HARDIRQ_OFFSET
-#endif
-
 #ifndef CONFIG_SMP
 #define irq_exit()							\
 	do {								\
@@ -84,9 +52,6 @@
 		preempt_enable_no_resched();				\
 	} while (0)
 
-#define synchronize_irq(irq)	barrier()
-#else
-#error SMP not supported
 #endif
 
 #endif /* __ASM_HARDIRQ_H */
diff -Nru a/include/asm-arm26/ptrace.h b/include/asm-arm26/ptrace.h
--- a/include/asm-arm26/ptrace.h	2004-10-18 14:56:18 -07:00
+++ b/include/asm-arm26/ptrace.h	2004-10-18 14:56:18 -07:00
@@ -30,6 +30,7 @@
 
 #define pc_pointer(v) ((v) & ~PCMASK)   /* convert v to pc type address */
 #define instruction_pointer(regs) (pc_pointer((regs)->ARM_pc)) /* get pc */
+#define profile_pc(regs) instruction_pointer(regs)
 
 /* this struct defines the way the registers are stored on the
    stack during a system call. */
diff -Nru a/include/asm-arm26/resource.h b/include/asm-arm26/resource.h
--- a/include/asm-arm26/resource.h	2004-10-18 14:55:54 -07:00
+++ b/include/asm-arm26/resource.h	2004-10-18 14:55:54 -07:00
@@ -39,7 +39,7 @@
 	{ RLIM_INFINITY, RLIM_INFINITY },	\
 	{ 0,             0             },	\
 	{ INR_OPEN,      INR_OPEN      },	\
-	{ RLIM_INFINITY, RLIM_INFINITY },	\
+	{ MLOCK_LIMIT,	 MLOCK_LIMIT   },	\
 	{ RLIM_INFINITY, RLIM_INFINITY },	\
 	{ RLIM_INFINITY, RLIM_INFINITY },	\
 	{ MAX_SIGPENDING, MAX_SIGPENDING},	\
diff -Nru a/include/asm-arm26/semaphore.h b/include/asm-arm26/semaphore.h
--- a/include/asm-arm26/semaphore.h	2004-10-18 14:57:04 -07:00
+++ b/include/asm-arm26/semaphore.h	2004-10-18 14:57:04 -07:00
@@ -16,22 +16,14 @@
 	atomic_t count;
 	int sleepers;
 	wait_queue_head_t wait;
-#if WAITQUEUE_DEBUG
-	long __magic;
-#endif
 };
 
-#if WAITQUEUE_DEBUG
-# define __SEM_DEBUG_INIT(name) \
-		, (long)&(name).__magic
-#else
-# define __SEM_DEBUG_INIT(name)
-#endif
-
-#define __SEMAPHORE_INIT(name,count)			\
-	{ ATOMIC_INIT(count), 0,			\
-	  __WAIT_QUEUE_HEAD_INITIALIZER((name).wait)	\
-	  __SEM_DEBUG_INIT(name) }
+#define __SEMAPHORE_INIT(name, n)					\
+{									\
+	.count		= ATOMIC_INIT(n),				\
+	.sleepers	= 0,						\
+	.wait		= __WAIT_QUEUE_HEAD_INITIALIZER((name).wait),	\
+}
 
 #define __MUTEX_INITIALIZER(name) \
 	__SEMAPHORE_INIT(name,1)
@@ -47,9 +39,6 @@
 	atomic_set(&sem->count, val);
 	sem->sleepers = 0;
 	init_waitqueue_head(&sem->wait);
-#if WAITQUEUE_DEBUG
-	sem->__magic = (long)&sem->__magic;
-#endif
 }
 
 static inline void init_MUTEX(struct semaphore *sem)
@@ -81,9 +70,6 @@
  */
 static inline void down(struct semaphore * sem)
 {
-#if WAITQUEUE_DEBUG
-	CHECK_MAGIC(sem->__magic);
-#endif
 	might_sleep();
 	__down_op(sem, __down_failed);
 }
@@ -94,19 +80,12 @@
  */
 static inline int down_interruptible (struct semaphore * sem)
 {
-#if WAITQUEUE_DEBUG
-	CHECK_MAGIC(sem->__magic);
-#endif
 	might_sleep();
 	return __down_op_ret(sem, __down_interruptible_failed);
 }
 
 static inline int down_trylock(struct semaphore *sem)
 {
-#if WAITQUEUE_DEBUG
-	CHECK_MAGIC(sem->__magic);
-#endif
-
 	return __down_op_ret(sem, __down_trylock_failed);
 }
 
@@ -118,10 +97,6 @@
  */
 static inline void up(struct semaphore * sem)
 {
-#if WAITQUEUE_DEBUG
-	CHECK_MAGIC(sem->__magic);
-#endif
-
 	__up_op(sem, __up_wakeup);
 }
 
diff -Nru a/include/asm-arm26/socket.h b/include/asm-arm26/socket.h
--- a/include/asm-arm26/socket.h	2004-10-18 14:57:19 -07:00
+++ b/include/asm-arm26/socket.h	2004-10-18 14:57:19 -07:00
@@ -47,20 +47,4 @@
 
 #define SO_PEERSEC		31
 
-/* Nast libc5 fixup - bletch */
-#if defined(__KERNEL__)
-/* Socket types. */
-#define SOCK_STREAM	1		/* stream (connection) socket	*/
-#define SOCK_DGRAM	2		/* datagram (conn.less) socket	*/
-#define SOCK_RAW	3		/* raw socket			*/
-#define SOCK_RDM	4		/* reliably-delivered message	*/
-#define SOCK_SEQPACKET	5		/* sequential packet socket	*/
-#define SOCK_PACKET	10		/* linux specific way of	*/
-					/* getting packets at the dev	*/
-					/* level.  For writing rarp and	*/
-					/* other similar things on the	*/
-					/* user level.			*/
-#define	SOCK_MAX	(SOCK_PACKET+1)
-#endif
-
 #endif /* _ASM_SOCKET_H */
diff -Nru a/include/asm-arm26/uaccess.h b/include/asm-arm26/uaccess.h
--- a/include/asm-arm26/uaccess.h	2004-10-18 14:55:55 -07:00
+++ b/include/asm-arm26/uaccess.h	2004-10-18 14:55:55 -07:00
@@ -217,6 +217,9 @@
 	return n;
 }
 
+#define __copy_to_user_inatomic __copy_to_user
+#define __copy_from_user_inatomic __copy_from_user
+
 static __inline__ unsigned long clear_user (void *to, unsigned long n)
 {
 	if (access_ok(VERIFY_WRITE, to, n))
diff -Nru a/include/asm-cris/arch-v10/ptrace.h b/include/asm-cris/arch-v10/ptrace.h
--- a/include/asm-cris/arch-v10/ptrace.h	2004-10-18 14:56:18 -07:00
+++ b/include/asm-cris/arch-v10/ptrace.h	2004-10-18 14:56:18 -07:00
@@ -109,6 +109,7 @@
 /* bit 8 is user-mode flag */
 #define user_mode(regs) (((regs)->dccr & 0x100) != 0)
 #define instruction_pointer(regs) ((regs)->irp)
+#define profile_pc(regs) instruction_pointer(regs)
 extern void show_regs(struct pt_regs *);
 
 #endif
diff -Nru a/include/asm-cris/bug.h b/include/asm-cris/bug.h
--- a/include/asm-cris/bug.h	2004-10-18 14:57:04 -07:00
+++ b/include/asm-cris/bug.h	2004-10-18 14:57:04 -07:00
@@ -1,21 +1,4 @@
 #ifndef _CRIS_BUG_H
 #define _CRIS_BUG_H
-
-#define BUG() do { \
-  printk("kernel BUG at %s:%d!\n", __FILE__, __LINE__); \
-} while (0)
-
-#define PAGE_BUG(page) do { \
-         BUG(); \
-} while (0)
-
-#define BUG_ON(condition) do { if (unlikely((condition)!=0)) BUG(); } while(0)
-
-#define WARN_ON(condition) do { \
-	if (unlikely((condition)!=0)) { \
-		printk("Badness in %s at %s:%d\n", __FUNCTION__, __FILE__, __LINE__); \
-		dump_stack(); \
-	} \
-} while (0)
-
+#include <asm-generic/bug.h>
 #endif
diff -Nru a/include/asm-cris/hardirq.h b/include/asm-cris/hardirq.h
--- a/include/asm-cris/hardirq.h	2004-10-18 14:56:28 -07:00
+++ b/include/asm-cris/hardirq.h	2004-10-18 14:56:28 -07:00
@@ -40,20 +40,6 @@
 #define SOFTIRQ_SHIFT	(PREEMPT_SHIFT + PREEMPT_BITS)
 #define HARDIRQ_SHIFT	(SOFTIRQ_SHIFT + SOFTIRQ_BITS)
 
-#define __MASK(x)	((1UL << (x))-1)
-
-#define PREEMPT_MASK	(__MASK(PREEMPT_BITS) << PREEMPT_SHIFT)
-#define HARDIRQ_MASK	(__MASK(HARDIRQ_BITS) << HARDIRQ_SHIFT)
-#define SOFTIRQ_MASK	(__MASK(SOFTIRQ_BITS) << SOFTIRQ_SHIFT)
-
-#define hardirq_count()	(preempt_count() & HARDIRQ_MASK)
-#define softirq_count()	(preempt_count() & SOFTIRQ_MASK)
-#define irq_count()	(preempt_count() & (HARDIRQ_MASK | SOFTIRQ_MASK))
-
-#define PREEMPT_OFFSET	(1UL << PREEMPT_SHIFT)
-#define SOFTIRQ_OFFSET	(1UL << SOFTIRQ_SHIFT)
-#define HARDIRQ_OFFSET	(1UL << HARDIRQ_SHIFT)
-
 /*
  * The hardirq mask has to be large enough to have
  * space for potentially all IRQ sources in the system
@@ -63,27 +49,7 @@
 # error HARDIRQ_BITS is too low!
 #endif
 
-/*
- * Are we doing bottom half or hardware interrupt processing?
- * Are we in a softirq context? Interrupt context?
- */
-#define in_irq()		(hardirq_count())
-#define in_softirq()		(softirq_count())
-#define in_interrupt()		(irq_count())
-
-
-#define hardirq_trylock()	(!in_interrupt())
-#define hardirq_endlock()	do { } while (0)
-
 #define irq_enter()		(preempt_count() += HARDIRQ_OFFSET)
-
-#ifdef CONFIG_PREEMPT
-# define in_atomic()	((preempt_count() & ~PREEMPT_ACTIVE) != kernel_locked())
-# define IRQ_EXIT_OFFSET (HARDIRQ_OFFSET-1)
-#else
-# define in_atomic()	(preempt_count() != 0)
-# define IRQ_EXIT_OFFSET HARDIRQ_OFFSET
-#endif
 #define irq_exit()							\
 do {									\
 		preempt_count() -= IRQ_EXIT_OFFSET;			\
@@ -91,7 +57,5 @@
 			do_softirq();					\
 		preempt_enable_no_resched();				\
 } while (0)
-
-#define synchronize_irq(irq)	barrier()
 
 #endif /* __ASM_HARDIRQ_H */
diff -Nru a/include/asm-cris/resource.h b/include/asm-cris/resource.h
--- a/include/asm-cris/resource.h	2004-10-18 14:56:33 -07:00
+++ b/include/asm-cris/resource.h	2004-10-18 14:56:33 -07:00
@@ -39,7 +39,7 @@
 	{ RLIM_INFINITY, RLIM_INFINITY },		\
 	{             0,             0 },		\
 	{      INR_OPEN,     INR_OPEN  },		\
-	{ RLIM_INFINITY, RLIM_INFINITY },               \
+	{   MLOCK_LIMIT,   MLOCK_LIMIT },               \
 	{ RLIM_INFINITY, RLIM_INFINITY },		\
 	{ RLIM_INFINITY, RLIM_INFINITY },		\
 	{ MAX_SIGPENDING, MAX_SIGPENDING },		\
diff -Nru a/include/asm-cris/semaphore.h b/include/asm-cris/semaphore.h
--- a/include/asm-cris/semaphore.h	2004-10-18 14:56:28 -07:00
+++ b/include/asm-cris/semaphore.h	2004-10-18 14:56:28 -07:00
@@ -24,21 +24,14 @@
 	atomic_t count;
 	atomic_t waking;
 	wait_queue_head_t wait;
-#if WAITQUEUE_DEBUG
-	long __magic;
-#endif
 };
 
-#if WAITQUEUE_DEBUG
-# define __SEM_DEBUG_INIT(name)         , (long)&(name).__magic
-#else
-# define __SEM_DEBUG_INIT(name)
-#endif
-
-#define __SEMAPHORE_INITIALIZER(name,count)             \
-        { ATOMIC_INIT(count), ATOMIC_INIT(0),           \
-          __WAIT_QUEUE_HEAD_INITIALIZER((name).wait)    \
-          __SEM_DEBUG_INIT(name) }
+#define __SEMAPHORE_INITIALIZER(name, n)				\
+{									\
+	.count		= ATOMIC_INIT(n),				\
+	.waking		= ATOMIC_INIT(0),				\
+	.wait		= __WAIT_QUEUE_HEAD_INITIALIZER((name).wait)    \
+}
 
 #define __MUTEX_INITIALIZER(name) \
         __SEMAPHORE_INITIALIZER(name,1)
@@ -76,9 +69,6 @@
 	unsigned long flags;
 	int failed;
 
-#if WAITQUEUE_DEBUG
-	CHECK_MAGIC(sem->__magic);
-#endif
 	might_sleep();
 
 	/* atomically decrement the semaphores count, and if its negative, we wait */
@@ -102,9 +92,6 @@
 	unsigned long flags;
 	int failed;
 
-#if WAITQUEUE_DEBUG
-	CHECK_MAGIC(sem->__magic);
-#endif
 	might_sleep();
 
 	/* atomically decrement the semaphores count, and if its negative, we wait */
@@ -122,10 +109,6 @@
 	unsigned long flags;
 	int failed;
 
-#if WAITQUEUE_DEBUG
-	CHECK_MAGIC(sem->__magic);
-#endif
-
 	local_save_flags(flags);
 	local_irq_disable();
 	failed = --(sem->count.counter) < 0;
@@ -145,10 +128,6 @@
 {  
 	unsigned long flags;
 	int wakeup;
-
-#if WAITQUEUE_DEBUG
-	CHECK_MAGIC(sem->__magic);
-#endif
 
 	/* atomically increment the semaphores count, and if it was negative, we wake people */
 	local_save_flags(flags);
diff -Nru a/include/asm-cris/socket.h b/include/asm-cris/socket.h
--- a/include/asm-cris/socket.h	2004-10-18 14:56:50 -07:00
+++ b/include/asm-cris/socket.h	2004-10-18 14:56:50 -07:00
@@ -49,21 +49,6 @@
 
 #define SO_PEERSEC             31
 
-#if defined(__KERNEL__)
-/* Socket types. */
-#define SOCK_STREAM     1               /* stream (connection) socket   */
-#define SOCK_DGRAM      2               /* datagram (conn.less) socket  */
-#define SOCK_RAW        3               /* raw socket                   */
-#define SOCK_RDM        4               /* reliably-delivered message   */
-#define SOCK_SEQPACKET  5               /* sequential packet socket     */
-#define SOCK_PACKET     10              /* linux specific way of        */
-                                        /* getting packets at the dev   */
-                                        /* level.  For writing rarp and */
-                                        /* other similar things on the  */
-                                        /* user level.                  */
-#define        SOCK_MAX        (SOCK_PACKET+1)
-#endif
-
 #endif /* _ASM_SOCKET_H */
 
 
diff -Nru a/include/asm-cris/uaccess.h b/include/asm-cris/uaccess.h
--- a/include/asm-cris/uaccess.h	2004-10-18 14:55:55 -07:00
+++ b/include/asm-cris/uaccess.h	2004-10-18 14:55:55 -07:00
@@ -434,6 +434,8 @@
 
 #define __copy_to_user(to,from,n)   __generic_copy_to_user_nocheck((to),(from),(n))
 #define __copy_from_user(to,from,n) __generic_copy_from_user_nocheck((to),(from),(n))
+#define __copy_to_user_inatomic __copy_to_user
+#define __copy_from_user_inatomic __copy_from_user
 #define __clear_user(to,n) __generic_clear_user_nocheck((to),(n))
 
 #define strlen_user(str)	strnlen_user((str), 0x7ffffffe)
diff -Nru a/include/asm-generic/bug.h b/include/asm-generic/bug.h
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/include/asm-generic/bug.h	2004-10-18 14:57:21 -07:00
@@ -0,0 +1,34 @@
+#ifndef _ASM_GENERIC_BUG_H
+#define _ASM_GENERIC_BUG_H
+
+#include <linux/compiler.h>
+#include <linux/config.h>
+
+#ifndef HAVE_ARCH_BUG
+#define BUG() do { \
+	printk("kernel BUG at %s:%d!\n", __FILE__, __LINE__); \
+	panic("BUG!"); \
+} while (0)
+#endif
+
+#ifndef HAVE_ARCH_PAGE_BUG
+#define PAGE_BUG(page) do { \
+	printk("page BUG for page at %p\n", page); \
+	BUG(); \
+} while (0)
+#endif
+
+#ifndef HAVE_ARCH_BUG_ON
+#define BUG_ON(condition) do { if (unlikely((condition)!=0)) BUG(); } while(0)
+#endif
+
+#ifndef HAVE_ARCH_WARN_ON
+#define WARN_ON(condition) do { \
+	if (unlikely((condition)!=0)) { \
+		printk("Badness in %s at %s:%d\n", __FUNCTION__, __FILE__, __LINE__); \
+		dump_stack(); \
+	} \
+} while (0)
+#endif
+
+#endif
diff -Nru a/include/asm-generic/ide_iops.h b/include/asm-generic/ide_iops.h
--- a/include/asm-generic/ide_iops.h	2004-10-18 14:56:49 -07:00
+++ b/include/asm-generic/ide_iops.h	2004-10-18 14:56:49 -07:00
@@ -5,7 +5,7 @@
 #define __ide_outsw	outsw
 #define __ide_outsl	outsl
 
-static __inline__ void __ide_mm_insw(unsigned long port, void *addr, u32 count)
+static __inline__ void __ide_mm_insw(void __iomem *port, void *addr, u32 count)
 {
 	while (count--) {
 		*(u16 *)addr = readw(port);
@@ -13,7 +13,7 @@
 	}
 }
 
-static __inline__ void __ide_mm_insl(unsigned long port, void *addr, u32 count)
+static __inline__ void __ide_mm_insl(void __iomem *port, void *addr, u32 count)
 {
 	while (count--) {
 		*(u32 *)addr = readl(port);
@@ -21,7 +21,7 @@
 	}
 }
 
-static __inline__ void __ide_mm_outsw(unsigned long port, void *addr, u32 count)
+static __inline__ void __ide_mm_outsw(void __iomem *port, void *addr, u32 count)
 {
 	while (count--) {
 		writew(*(u16 *)addr, port);
@@ -29,7 +29,7 @@
 	}
 }
 
-static __inline__ void __ide_mm_outsl(unsigned long port, void *addr, u32 count)
+static __inline__ void __ide_mm_outsl(void __iomem * port, void *addr, u32 count)
 {
 	while (count--) {
 		writel(*(u32 *)addr, port);
diff -Nru a/include/asm-generic/iomap.h b/include/asm-generic/iomap.h
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/include/asm-generic/iomap.h	2004-10-18 14:57:24 -07:00
@@ -0,0 +1,63 @@
+#ifndef __GENERIC_IO_H
+#define __GENERIC_IO_H
+
+#include <linux/linkage.h>
+
+/*
+ * These are the "generic" interfaces for doing new-style
+ * memory-mapped or PIO accesses. Architectures may do
+ * their own arch-optimized versions, these just act as
+ * wrappers around the old-style IO register access functions:
+ * read[bwl]/write[bwl]/in[bwl]/out[bwl]
+ *
+ * Don't include this directly, include it from <asm/io.h>.
+ */
+
+/*
+ * Read/write from/to an (offsettable) iomem cookie. It might be a PIO
+ * access or a MMIO access, these functions don't care. The info is
+ * encoded in the hardware mapping set up by the mapping functions
+ * (or the cookie itself, depending on implementation and hw).
+ *
+ * The generic routines just encode the PIO/MMIO as part of the
+ * cookie, and coldly assume that the MMIO IO mappings are not
+ * in the low address range. Architectures for which this is not
+ * true can't use this generic implementation.
+ */
+extern unsigned int fastcall ioread8(void __iomem *);
+extern unsigned int fastcall ioread16(void __iomem *);
+extern unsigned int fastcall ioread32(void __iomem *);
+
+extern void fastcall iowrite8(u8, void __iomem *);
+extern void fastcall iowrite16(u16, void __iomem *);
+extern void fastcall iowrite32(u32, void __iomem *);
+
+/*
+ * "string" versions of the above. Note that they
+ * use native byte ordering for the accesses (on
+ * the assumption that IO and memory agree on a
+ * byte order, and CPU byteorder is irrelevant).
+ *
+ * They do _not_ update the port address. If you
+ * want MMIO that copies stuff laid out in MMIO
+ * memory across multiple ports, use "memcpy_toio()"
+ * and friends.
+ */
+extern void fastcall ioread8_rep(void __iomem *port, void *buf, unsigned long count);
+extern void fastcall ioread16_rep(void __iomem *port, void *buf, unsigned long count);
+extern void fastcall ioread32_rep(void __iomem *port, void *buf, unsigned long count);
+
+extern void fastcall iowrite8_rep(void __iomem *port, const void *buf, unsigned long count);
+extern void fastcall iowrite16_rep(void __iomem *port, const void *buf, unsigned long count);
+extern void fastcall iowrite32_rep(void __iomem *port, const void *buf, unsigned long count);
+
+/* Create a virtual mapping cookie for an IO port range */
+extern void __iomem *ioport_map(unsigned long port, unsigned int nr);
+extern void ioport_unmap(void __iomem *);
+
+/* Create a virtual mapping cookie for a PCI BAR (memory or IO) */
+struct pci_dev;
+extern void __iomem *pci_iomap(struct pci_dev *dev, int bar, unsigned long max);
+extern void pci_iounmap(struct pci_dev *dev, void __iomem *);
+
+#endif
diff -Nru a/include/asm-generic/local.h b/include/asm-generic/local.h
--- a/include/asm-generic/local.h	2004-10-18 14:56:49 -07:00
+++ b/include/asm-generic/local.h	2004-10-18 14:56:49 -07:00
@@ -3,8 +3,8 @@
 
 #include <linux/config.h>
 #include <linux/percpu.h>
+#include <linux/hardirq.h>
 #include <asm/types.h>
-#include <asm/hardirq.h>
 
 /* An unsigned long type for operations which are atomic for a single
  * CPU.  Usually used in combination with per-cpu variables. */
diff -Nru a/include/asm-generic/pgtable.h b/include/asm-generic/pgtable.h
--- a/include/asm-generic/pgtable.h	2004-10-18 14:56:28 -07:00
+++ b/include/asm-generic/pgtable.h	2004-10-18 14:56:28 -07:00
@@ -13,11 +13,19 @@
  * Note: the old pte is known to not be writable, so we don't need to
  * worry about dirty bits etc getting lost.
  */
+#ifndef __HAVE_ARCH_SET_PTE_ATOMIC
 #define ptep_establish(__vma, __address, __ptep, __entry)		\
 do {				  					\
 	set_pte(__ptep, __entry);					\
 	flush_tlb_page(__vma, __address);				\
 } while (0)
+#else /* __HAVE_ARCH_SET_PTE_ATOMIC */
+#define ptep_establish(__vma, __address, __ptep, __entry)		\
+do {				  					\
+	set_pte_atomic(__ptep, __entry);				\
+	flush_tlb_page(__vma, __address);				\
+} while (0)
+#endif /* __HAVE_ARCH_SET_PTE_ATOMIC */
 #endif
 
 #ifndef __HAVE_ARCH_PTEP_SET_ACCESS_FLAGS
diff -Nru a/include/asm-generic/siginfo.h b/include/asm-generic/siginfo.h
--- a/include/asm-generic/siginfo.h	2004-10-18 14:56:27 -07:00
+++ b/include/asm-generic/siginfo.h	2004-10-18 14:56:27 -07:00
@@ -3,6 +3,7 @@
 
 #include <linux/compiler.h>
 #include <linux/types.h>
+#include <linux/resource.h>
 
 typedef union sigval {
 	int sival_int;
diff -Nru a/include/asm-generic/uaccess.h b/include/asm-generic/uaccess.h
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/include/asm-generic/uaccess.h	2004-10-18 14:57:23 -07:00
@@ -0,0 +1,26 @@
+#ifndef _ASM_GENERIC_UACCESS_H_
+#define _ASM_GENERIC_UACCESS_H_
+
+/*
+ * This macro should be used instead of __get_user() when accessing
+ * values at locations that are not known to be aligned.
+ */
+#define __get_user_unaligned(x, ptr)					\
+({									\
+	__typeof__ (*(ptr)) __x;					\
+	__copy_from_user(&__x, (ptr), sizeof(*(ptr))) ? -EFAULT : 0;	\
+	(x) = __x;							\
+})
+
+
+/*
+ * This macro should be used instead of __put_user() when accessing
+ * values at locations that are not known to be aligned.
+ */
+#define __put_user_unaligned(x, ptr)					\
+({									\
+	__typeof__ (*(ptr)) __x = (x);					\
+	__copy_to_user((ptr), &__x, sizeof(*(ptr))) ? -EFAULT : 0;	\
+})
+
+#endif /* _ASM_GENERIC_UACCESS_H */
diff -Nru a/include/asm-generic/vmlinux.lds.h b/include/asm-generic/vmlinux.lds.h
--- a/include/asm-generic/vmlinux.lds.h	2004-10-18 14:55:54 -07:00
+++ b/include/asm-generic/vmlinux.lds.h	2004-10-18 14:55:54 -07:00
@@ -16,6 +16,16 @@
 		*(.rodata1)						\
 	}								\
 									\
+	/* PCI quirks */						\
+	.pci_fixup        : AT(ADDR(.pci_fixup) - LOAD_OFFSET) {	\
+		VMLINUX_SYMBOL(__start_pci_fixups_header) = .;		\
+		*(.pci_fixup_header)					\
+		VMLINUX_SYMBOL(__end_pci_fixups_header) = .;		\
+		VMLINUX_SYMBOL(__start_pci_fixups_final) = .;		\
+		*(.pci_fixup_final)					\
+		VMLINUX_SYMBOL(__end_pci_fixups_final) = .;		\
+	}								\
+									\
 	/* Kernel symbol table: Normal symbols */			\
 	__ksymtab         : AT(ADDR(__ksymtab) - LOAD_OFFSET) {		\
 		VMLINUX_SYMBOL(__start___ksymtab) = .;			\
@@ -47,6 +57,13 @@
 	/* Kernel symbol table: strings */				\
         __ksymtab_strings : AT(ADDR(__ksymtab_strings) - LOAD_OFFSET) {	\
 		*(__ksymtab_strings)					\
+	}								\
+									\
+	/* Built-in module parameters. */				\
+	__param : AT(ADDR(__param) - LOAD_OFFSET) {			\
+		VMLINUX_SYMBOL(__start___param) = .;			\
+		*(__param)						\
+		VMLINUX_SYMBOL(__stop___param) = .;			\
 	}
 
 #define SECURITY_INIT							\
@@ -60,3 +77,8 @@
 		VMLINUX_SYMBOL(__sched_text_start) = .;			\
 		*(.sched.text)						\
 		VMLINUX_SYMBOL(__sched_text_end) = .;
+
+#define LOCK_TEXT							\
+		VMLINUX_SYMBOL(__lock_text_start) = .;			\
+		*(.spinlock.text)					\
+		VMLINUX_SYMBOL(__lock_text_end) = .;
diff -Nru a/include/asm-h8300/bitops.h b/include/asm-h8300/bitops.h
--- a/include/asm-h8300/bitops.h	2004-10-18 14:56:28 -07:00
+++ b/include/asm-h8300/bitops.h	2004-10-18 14:56:28 -07:00
@@ -273,6 +273,8 @@
 	return result + __ffs(tmp);
 }
 
+#define find_first_bit(addr, size) find_next_bit(addr, size, 0)
+
 /*
  * Every architecture must define this function. It's the fastest
  * way of searching a 140-bit bitmap where the first 100 bits are
diff -Nru a/include/asm-h8300/bug.h b/include/asm-h8300/bug.h
--- a/include/asm-h8300/bug.h	2004-10-18 14:55:53 -07:00
+++ b/include/asm-h8300/bug.h	2004-10-18 14:55:53 -07:00
@@ -1,21 +1,4 @@
 #ifndef _H8300_BUG_H
 #define _H8300_BUG_H
-
-#define BUG() do { \
-  printk("%s(%d): kernel BUG!\n", __FILE__, __LINE__); \
-} while (0)
-
-#define PAGE_BUG(page) do { \
-         BUG(); \
-} while (0)
-
-#define BUG_ON(condition) do { if (unlikely((condition)!=0)) BUG(); } while(0)
-
-#define WARN_ON(condition) do { \
-	if (unlikely((condition)!=0)) { \
-		printk("Badness in %s at %s:%d\n", __FUNCTION__, __FILE__, __LINE__); \
-		dump_stack(); \
-	} \
-} while (0)
-
+#include <asm-generic/bug.h>
 #endif
diff -Nru a/include/asm-h8300/hardirq.h b/include/asm-h8300/hardirq.h
--- a/include/asm-h8300/hardirq.h	2004-10-18 14:56:32 -07:00
+++ b/include/asm-h8300/hardirq.h	2004-10-18 14:56:32 -07:00
@@ -38,20 +38,6 @@
 #define SOFTIRQ_SHIFT	(PREEMPT_SHIFT + PREEMPT_BITS)
 #define HARDIRQ_SHIFT	(SOFTIRQ_SHIFT + SOFTIRQ_BITS)
 
-#define __MASK(x)	((1UL << (x))-1)
-
-#define PREEMPT_MASK	(__MASK(PREEMPT_BITS) << PREEMPT_SHIFT)
-#define HARDIRQ_MASK	(__MASK(HARDIRQ_BITS) << HARDIRQ_SHIFT)
-#define SOFTIRQ_MASK	(__MASK(SOFTIRQ_BITS) << SOFTIRQ_SHIFT)
-
-#define hardirq_count()	(preempt_count() & HARDIRQ_MASK)
-#define softirq_count()	(preempt_count() & SOFTIRQ_MASK)
-#define irq_count()	(preempt_count() & (HARDIRQ_MASK | SOFTIRQ_MASK))
-
-#define PREEMPT_OFFSET	(1UL << PREEMPT_SHIFT)
-#define SOFTIRQ_OFFSET	(1UL << SOFTIRQ_SHIFT)
-#define HARDIRQ_OFFSET	(1UL << HARDIRQ_SHIFT)
-
 /*
  * The hardirq mask has to be large enough to have
  * space for potentially all IRQ sources in the system
@@ -61,27 +47,7 @@
 # error HARDIRQ_BITS is too low!
 #endif
 
-/*
- * Are we doing bottom half or hardware interrupt processing?
- * Are we in a softirq context? Interrupt context?
- */
-#define in_irq()		(hardirq_count())
-#define in_softirq()		(softirq_count())
-#define in_interrupt()		(irq_count())
-
-#define hardirq_trylock()	(!in_interrupt())
-#define hardirq_endlock()	do { } while (0)
-
 #define irq_enter()		(preempt_count() += HARDIRQ_OFFSET)
-
-#ifdef CONFIG_PREEMPT
-# define in_atomic()	((preempt_count() & ~PREEMPT_ACTIVE) != kernel_locked())
-# define IRQ_EXIT_OFFSET (HARDIRQ_OFFSET-1)
-#else
-# define in_atomic()	(preempt_count() != 0)
-# define IRQ_EXIT_OFFSET HARDIRQ_OFFSET
-#endif
-
 #define irq_exit()							\
 do {									\
 		preempt_count() -= IRQ_EXIT_OFFSET;			\
@@ -89,11 +55,5 @@
 			do_softirq();					\
 		preempt_enable_no_resched();				\
 } while (0)
-
-#ifndef CONFIG_SMP
-# define synchronize_irq(irq)	barrier()
-#else
-# error h8300 SMP is not available
-#endif /* CONFIG_SMP */
 
 #endif
diff -Nru a/include/asm-h8300/ptrace.h b/include/asm-h8300/ptrace.h
--- a/include/asm-h8300/ptrace.h	2004-10-18 14:57:03 -07:00
+++ b/include/asm-h8300/ptrace.h	2004-10-18 14:57:03 -07:00
@@ -57,6 +57,7 @@
 
 #define user_mode(regs) (!((regs)->ccr & PS_S))
 #define instruction_pointer(regs) ((regs)->pc)
+#define profile_pc(regs) instruction_pointer(regs)
 extern void show_regs(struct pt_regs *);
 #endif /* __KERNEL__ */
 #endif /* __ASSEMBLY__ */
diff -Nru a/include/asm-h8300/resource.h b/include/asm-h8300/resource.h
--- a/include/asm-h8300/resource.h	2004-10-18 14:55:54 -07:00
+++ b/include/asm-h8300/resource.h	2004-10-18 14:55:54 -07:00
@@ -39,7 +39,7 @@
 	{ RLIM_INFINITY, RLIM_INFINITY },		\
 	{             0,             0 },		\
 	{      INR_OPEN,     INR_OPEN  },		\
-	{ RLIM_INFINITY, RLIM_INFINITY },		\
+	{   MLOCK_LIMIT,   MLOCK_LIMIT },		\
 	{ RLIM_INFINITY, RLIM_INFINITY },		\
 	{ RLIM_INFINITY, RLIM_INFINITY },		\
 	{ MAX_SIGPENDING, MAX_SIGPENDING },		\
diff -Nru a/include/asm-h8300/semaphore.h b/include/asm-h8300/semaphore.h
--- a/include/asm-h8300/semaphore.h	2004-10-18 14:56:29 -07:00
+++ b/include/asm-h8300/semaphore.h	2004-10-18 14:56:29 -07:00
@@ -26,21 +26,14 @@
 	atomic_t count;
 	int sleepers;
 	wait_queue_head_t wait;
-#if WAITQUEUE_DEBUG
-	long __magic;
-#endif
 };
 
-#if WAITQUEUE_DEBUG
-# define __SEM_DEBUG_INIT(name) \
-		, (long)&(name).__magic
-#else
-# define __SEM_DEBUG_INIT(name)
-#endif
-
-#define __SEMAPHORE_INITIALIZER(name,count) \
-{ ATOMIC_INIT(count), 0, __WAIT_QUEUE_HEAD_INITIALIZER((name).wait) \
-	__SEM_DEBUG_INIT(name) }
+#define __SEMAPHORE_INITIALIZER(name, n)				\
+{									\
+	.count		= ATOMIC_INIT(n),				\
+	.sleepers	= 0,						\
+	.wait		= __WAIT_QUEUE_HEAD_INITIALIZER((name).wait)	\
+}
 
 #define __MUTEX_INITIALIZER(name) \
 	__SEMAPHORE_INITIALIZER(name,1)
@@ -87,9 +80,6 @@
 {
 	register atomic_t *count asm("er0");
 
-#if WAITQUEUE_DEBUG
-	CHECK_MAGIC(sem->__magic);
-#endif
 	might_sleep();
 
 	count = &(sem->count);
@@ -116,9 +106,6 @@
 {
 	register atomic_t *count asm("er0");
 
-#if WAITQUEUE_DEBUG
-	CHECK_MAGIC(sem->__magic);
-#endif
 	might_sleep();
 
 	count = &(sem->count);
@@ -147,10 +134,6 @@
 {
 	register atomic_t *count asm("er0");
 
-#if WAITQUEUE_DEBUG
-	CHECK_MAGIC(sem->__magic);
-#endif
-
 	count = &(sem->count);
 	__asm__ __volatile__(
 		"stc ccr,r3l\n\t"
@@ -186,10 +169,6 @@
 static inline void up(struct semaphore * sem)
 {
 	register atomic_t *count asm("er0");
-
-#if WAITQUEUE_DEBUG
-	CHECK_MAGIC(sem->__magic);
-#endif
 
 	count = &(sem->count);
 	__asm__ __volatile__(
diff -Nru a/include/asm-h8300/socket.h b/include/asm-h8300/socket.h
--- a/include/asm-h8300/socket.h	2004-10-18 14:56:33 -07:00
+++ b/include/asm-h8300/socket.h	2004-10-18 14:56:33 -07:00
@@ -47,20 +47,4 @@
 
 #define SO_PEERSEC		31
 
-/* Nast libc5 fixup - bletch */
-#if defined(__KERNEL__)
-/* Socket types. */
-#define SOCK_STREAM	1		/* stream (connection) socket	*/
-#define SOCK_DGRAM	2		/* datagram (conn.less) socket	*/
-#define SOCK_RAW	3		/* raw socket			*/
-#define SOCK_RDM	4		/* reliably-delivered message	*/
-#define SOCK_SEQPACKET	5		/* sequential packet socket	*/
-#define SOCK_PACKET	10		/* linux specific way of	*/
-					/* getting packets at the dev	*/
-					/* level.  For writing rarp and	*/
-					/* other similar things on the	*/
-					/* user level.			*/
-#define	SOCK_MAX	(SOCK_PACKET+1)
-#endif
-
 #endif /* _ASM_SOCKET_H */
diff -Nru a/include/asm-h8300/softirq.h b/include/asm-h8300/softirq.h
--- a/include/asm-h8300/softirq.h	2004-10-18 14:56:33 -07:00
+++ /dev/null	Wed Dec 31 16:00:00 196900
@@ -1,20 +0,0 @@
-#ifndef __ASM_SOFTIRQ_H
-#define __ASM_SOFTIRQ_H
-
-#include <linux/preempt.h>
-#include <asm/hardirq.h>
-
-#define local_bh_disable() \
-		do { preempt_count() += SOFTIRQ_OFFSET; barrier(); } while (0)
-#define __local_bh_enable() \
-		do { barrier(); preempt_count() -= SOFTIRQ_OFFSET; } while (0)
-
-#define local_bh_enable()						\
-do {									\
-	__local_bh_enable();						\
-	if (unlikely(!in_interrupt() && softirq_pending(smp_processor_id()))) \
-		do_softirq();						\
-	preempt_check_resched();					\
-} while (0)
-
-#endif	/* __ASM_SOFTIRQ_H */
diff -Nru a/include/asm-h8300/uaccess.h b/include/asm-h8300/uaccess.h
--- a/include/asm-h8300/uaccess.h	2004-10-18 14:56:28 -07:00
+++ b/include/asm-h8300/uaccess.h	2004-10-18 14:56:28 -07:00
@@ -123,6 +123,8 @@
 
 #define __copy_from_user(to, from, n) copy_from_user(to, from, n)
 #define __copy_to_user(to, from, n) copy_to_user(to, from, n)
+#define __copy_to_user_inatomic __copy_to_user
+#define __copy_from_user_inatomic __copy_from_user
 
 #define copy_to_user_ret(to,from,n,retval) ({ if (copy_to_user(to,from,n)) return retval; })
 
diff -Nru a/include/asm-i386/acpi.h b/include/asm-i386/acpi.h
--- a/include/asm-i386/acpi.h	2004-10-18 14:57:03 -07:00
+++ b/include/asm-i386/acpi.h	2004-10-18 14:57:03 -07:00
@@ -101,6 +101,17 @@
         :"=r"(n_hi), "=r"(n_lo)     \
         :"0"(n_hi), "1"(n_lo))
 
+/*
+ * Refer Intel ACPI _PDC support document for bit definitions
+ */
+#define ACPI_PDC_EST_CAPABILITY_SMP	0xa
+#define ACPI_PDC_EST_CAPABILITY_MSR	0x1
+
+/*
+ * Refer Intel ACPI _PDC support document for bit definitions
+ */
+#define ACPI_PDC_EST_CAPABILITY_SMP 	0xa
+#define ACPI_PDC_EST_CAPABILITY_MSR	0x1
 
 #ifdef CONFIG_ACPI_BOOT 
 extern int acpi_lapic;
@@ -177,6 +188,8 @@
 extern void acpi_reserve_bootmem(void);
 
 #endif /*CONFIG_ACPI_SLEEP*/
+
+extern u8 x86_acpiid_to_apicid[];
 
 #endif /*__KERNEL__*/
 
diff -Nru a/include/asm-i386/apic.h b/include/asm-i386/apic.h
--- a/include/asm-i386/apic.h	2004-10-18 14:57:04 -07:00
+++ b/include/asm-i386/apic.h	2004-10-18 14:57:04 -07:00
@@ -7,13 +7,28 @@
 #include <asm/apicdef.h>
 #include <asm/system.h>
 
-#define APIC_DEBUG 0
-
-#if APIC_DEBUG
-#define Dprintk(x...) printk(x)
-#else
 #define Dprintk(x...)
-#endif
+
+/*
+ * Debugging macros
+ */
+#define APIC_QUIET   0
+#define APIC_VERBOSE 1
+#define APIC_DEBUG   2
+
+extern int apic_verbosity;
+
+/*
+ * Define the default level of output to be very little
+ * This can be turned up by using apic=verbose for more
+ * information and apic=debug for _lots_ of information.
+ * apic_verbosity is defined in apic.c
+ */
+#define apic_printk(v, s, a...) do {       \
+		if ((v) <= apic_verbosity) \
+			printk(s, ##a);    \
+	} while (0)
+
 
 #ifdef CONFIG_X86_LOCAL_APIC
 
diff -Nru a/include/asm-i386/bitops.h b/include/asm-i386/bitops.h
--- a/include/asm-i386/bitops.h	2004-10-18 14:56:33 -07:00
+++ b/include/asm-i386/bitops.h	2004-10-18 14:56:33 -07:00
@@ -31,6 +31,11 @@
  *
  * This function is atomic and may not be reordered.  See __set_bit()
  * if you do not require the atomic guarantees.
+ *
+ * Note: there are no guarantees that this function will not be reordered
+ * on non x86 architectures, so if you are writting portable code,
+ * make sure not to rely on its reordering guarantees.
+ *
  * Note that @nr may be almost arbitrarily large; this function is not
  * restricted to acting on a single-word quantity.
  */
@@ -109,7 +114,8 @@
  * @nr: Bit to change
  * @addr: Address to start counting from
  *
- * change_bit() is atomic and may not be reordered.
+ * change_bit() is atomic and may not be reordered. It may be
+ * reordered on other architectures than x86.
  * Note that @nr may be almost arbitrarily large; this function is not
  * restricted to acting on a single-word quantity.
  */
@@ -127,6 +133,7 @@
  * @addr: Address to count from
  *
  * This operation is atomic and cannot be reordered.  
+ * It may be reordered on other architectures than x86.
  * It also implies a memory barrier.
  */
 static inline int test_and_set_bit(int nr, volatile unsigned long * addr)
@@ -165,7 +172,8 @@
  * @nr: Bit to clear
  * @addr: Address to count from
  *
- * This operation is atomic and cannot be reordered.  
+ * This operation is atomic and cannot be reordered.
+ * It can be reorderdered on other architectures other than x86.
  * It also implies a memory barrier.
  */
 static inline int test_and_clear_bit(int nr, volatile unsigned long * addr)
diff -Nru a/include/asm-i386/bug.h b/include/asm-i386/bug.h
--- a/include/asm-i386/bug.h	2004-10-18 14:56:11 -07:00
+++ b/include/asm-i386/bug.h	2004-10-18 14:56:11 -07:00
@@ -19,17 +19,7 @@
 #define BUG() __asm__ __volatile__("ud2\n")
 #endif
 
-#define BUG_ON(condition) do { if (unlikely((condition)!=0)) BUG(); } while(0)
-
-#define PAGE_BUG(page) do { \
-	BUG(); \
-} while (0)
-
-#define WARN_ON(condition) do { \
-	if (unlikely((condition)!=0)) { \
-		printk("Badness in %s at %s:%d\n", __FUNCTION__, __FILE__, __LINE__); \
-		dump_stack(); \
-	} \
-} while (0)
+#define HAVE_ARCH_BUG
+#include <asm-generic/bug.h>
 
 #endif
diff -Nru a/include/asm-i386/checksum.h b/include/asm-i386/checksum.h
--- a/include/asm-i386/checksum.h	2004-10-18 14:56:49 -07:00
+++ b/include/asm-i386/checksum.h	2004-10-18 14:56:49 -07:00
@@ -43,10 +43,12 @@
 }
 
 static __inline__
-unsigned int csum_partial_copy_from_user ( const char __user *src, char *dst,
+unsigned int csum_partial_copy_from_user(const char __user *src, char *dst,
 						int len, int sum, int *err_ptr)
 {
-	return csum_partial_copy_generic ( (__force char *)src, dst, len, sum, err_ptr, NULL);
+	might_sleep();
+	return csum_partial_copy_generic((__force char *)src, dst,
+					len, sum, err_ptr, NULL);
 }
 
 /*
@@ -177,6 +179,7 @@
 						     int len, int sum, 
 						     int *err_ptr)
 {
+	might_sleep();
 	if (access_ok(VERIFY_WRITE, dst, len))
 		return csum_partial_copy_generic(src, (__force char *)dst, len, sum, NULL, err_ptr);
 
diff -Nru a/include/asm-i386/cpufeature.h b/include/asm-i386/cpufeature.h
--- a/include/asm-i386/cpufeature.h	2004-10-18 14:56:49 -07:00
+++ b/include/asm-i386/cpufeature.h	2004-10-18 14:56:49 -07:00
@@ -71,9 +71,13 @@
 #define X86_FEATURE_P4		(3*32+ 7) /* P4 */
 
 /* Intel-defined CPU features, CPUID level 0x00000001 (ecx), word 4 */
-#define X86_FEATURE_EST		(4*32+ 7) /* Enhanced SpeedStep */
+#define X86_FEATURE_XMM3	(4*32+ 0) /* Streaming SIMD Extensions-3 */
 #define X86_FEATURE_MWAIT	(4*32+ 3) /* Monitor/Mwait support */
-
+#define X86_FEATURE_DSCPL	(4*32+ 4) /* CPL Qualified Debug Store */
+#define X86_FEATURE_EST		(4*32+ 7) /* Enhanced SpeedStep */
+#define X86_FEATURE_TM2		(4*32+ 8) /* Thermal Monitor 2 */
+#define X86_FEATURE_CID		(4*32+10) /* Context ID */
+#define X86_FEATURE_XTPR	(4*32+14) /* Send Task Priority Messages */
 
 /* VIA/Cyrix/Centaur-defined CPU features, CPUID level 0xC0000001, word 5 */
 #define X86_FEATURE_XSTORE	(5*32+ 2) /* on-CPU RNG present (xstore insn) */
@@ -92,13 +96,14 @@
 #define cpu_has_tsc		boot_cpu_has(X86_FEATURE_TSC)
 #define cpu_has_pae		boot_cpu_has(X86_FEATURE_PAE)
 #define cpu_has_pge		boot_cpu_has(X86_FEATURE_PGE)
-#define cpu_has_sse2		boot_cpu_has(X86_FEATURE_XMM2)
 #define cpu_has_apic		boot_cpu_has(X86_FEATURE_APIC)
 #define cpu_has_sep		boot_cpu_has(X86_FEATURE_SEP)
 #define cpu_has_mtrr		boot_cpu_has(X86_FEATURE_MTRR)
 #define cpu_has_mmx		boot_cpu_has(X86_FEATURE_MMX)
 #define cpu_has_fxsr		boot_cpu_has(X86_FEATURE_FXSR)
 #define cpu_has_xmm		boot_cpu_has(X86_FEATURE_XMM)
+#define cpu_has_xmm2		boot_cpu_has(X86_FEATURE_XMM2)
+#define cpu_has_xmm3		boot_cpu_has(X86_FEATURE_XMM3)
 #define cpu_has_ht		boot_cpu_has(X86_FEATURE_HT)
 #define cpu_has_mp		boot_cpu_has(X86_FEATURE_MP)
 #define cpu_has_nx		boot_cpu_has(X86_FEATURE_NX)
@@ -106,7 +111,9 @@
 #define cpu_has_cyrix_arr	boot_cpu_has(X86_FEATURE_CYRIX_ARR)
 #define cpu_has_centaur_mcr	boot_cpu_has(X86_FEATURE_CENTAUR_MCR)
 #define cpu_has_xstore		boot_cpu_has(X86_FEATURE_XSTORE)
+#define cpu_has_xstore_enabled	boot_cpu_has(X86_FEATURE_XSTORE_EN)
 #define cpu_has_xcrypt		boot_cpu_has(X86_FEATURE_XCRYPT)
+#define cpu_has_xcrypt_enabled	boot_cpu_has(X86_FEATURE_XCRYPT_EN)
 
 #endif /* __ASM_I386_CPUFEATURE_H */
 
diff -Nru a/include/asm-i386/desc.h b/include/asm-i386/desc.h
--- a/include/asm-i386/desc.h	2004-10-18 14:55:46 -07:00
+++ b/include/asm-i386/desc.h	2004-10-18 14:55:46 -07:00
@@ -8,10 +8,12 @@
 
 #include <linux/preempt.h>
 #include <linux/smp.h>
+#include <linux/percpu.h>
 
 #include <asm/mmu.h>
 
-extern struct desc_struct cpu_gdt_table[NR_CPUS][GDT_ENTRIES];
+extern struct desc_struct cpu_gdt_table[GDT_ENTRIES];
+DECLARE_PER_CPU(struct desc_struct, cpu_gdt_table[GDT_ENTRIES]);
 
 struct Xgt_desc_struct {
 	unsigned short size;
@@ -44,7 +46,7 @@
 
 static inline void __set_tss_desc(unsigned int cpu, unsigned int entry, void *addr)
 {
-	_set_tssldt_desc(&cpu_gdt_table[cpu][entry], (int)addr,
+	_set_tssldt_desc(&per_cpu(cpu_gdt_table, cpu)[entry], (int)addr,
 		offsetof(struct tss_struct, __cacheline_filler) - 1, 0x89);
 }
 
@@ -52,7 +54,7 @@
 
 static inline void set_ldt_desc(unsigned int cpu, void *addr, unsigned int size)
 {
-	_set_tssldt_desc(&cpu_gdt_table[cpu][GDT_ENTRY_LDT], (int)addr, ((size << 3)-1), 0x82);
+	_set_tssldt_desc(&per_cpu(cpu_gdt_table, cpu)[GDT_ENTRY_LDT], (int)addr, ((size << 3)-1), 0x82);
 }
 
 #define LDT_entry_a(info) \
@@ -86,7 +88,7 @@
 
 static inline void load_TLS(struct thread_struct *t, unsigned int cpu)
 {
-#define C(i) cpu_gdt_table[cpu][GDT_ENTRY_TLS_MIN + i] = t->tls_array[i]
+#define C(i) per_cpu(cpu_gdt_table, cpu)[GDT_ENTRY_TLS_MIN + i] = t->tls_array[i]
 	C(0); C(1); C(2);
 #undef C
 }
diff -Nru a/include/asm-i386/dma-mapping.h b/include/asm-i386/dma-mapping.h
--- a/include/asm-i386/dma-mapping.h	2004-10-18 14:57:05 -07:00
+++ b/include/asm-i386/dma-mapping.h	2004-10-18 14:57:05 -07:00
@@ -1,7 +1,6 @@
 #ifndef _ASM_I386_DMA_MAPPING_H
 #define _ASM_I386_DMA_MAPPING_H
 
-#include <linux/device.h>
 #include <linux/mm.h>
 
 #include <asm/cache.h>
@@ -162,5 +161,17 @@
 {
 	flush_write_buffers();
 }
+
+#define ARCH_HAS_DMA_DECLARE_COHERENT_MEMORY
+extern int
+dma_declare_coherent_memory(struct device *dev, dma_addr_t bus_addr,
+			    dma_addr_t device_addr, size_t size, int flags);
+
+extern void
+dma_release_declared_memory(struct device *dev);
+
+extern void *
+dma_mark_declared_memory_occupied(struct device *dev,
+				  dma_addr_t device_addr, size_t size);
 
 #endif
diff -Nru a/include/asm-i386/elf.h b/include/asm-i386/elf.h
--- a/include/asm-i386/elf.h	2004-10-18 14:56:48 -07:00
+++ b/include/asm-i386/elf.h	2004-10-18 14:56:48 -07:00
@@ -123,7 +123,7 @@
  * An executable for which elf_read_implies_exec() returns TRUE will
  * have the READ_IMPLIES_EXEC personality flag set automatically.
  */
-#define elf_read_implies_exec_binary(ex, have_pt_gnu_stack)	(!(have_pt_gnu_stack))
+#define elf_read_implies_exec(ex, have_pt_gnu_stack)	(!(have_pt_gnu_stack))
 
 extern int dump_task_regs (struct task_struct *, elf_gregset_t *);
 extern int dump_task_fpu (struct task_struct *, elf_fpregset_t *);
diff -Nru a/include/asm-i386/fixmap.h b/include/asm-i386/fixmap.h
--- a/include/asm-i386/fixmap.h	2004-10-18 14:55:54 -07:00
+++ b/include/asm-i386/fixmap.h	2004-10-18 14:55:54 -07:00
@@ -14,6 +14,15 @@
 #define _ASM_FIXMAP_H
 
 #include <linux/config.h>
+
+/* used by vmalloc.c, vsyscall.lds.S.
+ *
+ * Leave one empty page between vmalloc'ed areas and
+ * the start of the fixmap.
+ */
+#define __FIXADDR_TOP	0xfffff000
+
+#ifndef __ASSEMBLY__
 #include <linux/kernel.h>
 #include <asm/acpi.h>
 #include <asm/apicdef.h>
@@ -97,13 +106,8 @@
 #define clear_fixmap(idx) \
 		__set_fixmap(idx, 0, __pgprot(0))
 
-/*
- * used by vmalloc.c.
- *
- * Leave one empty page between vmalloc'ed areas and
- * the start of the fixmap.
- */
-#define FIXADDR_TOP	(0xfffff000UL)
+#define FIXADDR_TOP	((unsigned long)__FIXADDR_TOP)
+
 #define __FIXADDR_SIZE	(__end_of_permanent_fixed_addresses << PAGE_SHIFT)
 #define FIXADDR_START	(FIXADDR_TOP - __FIXADDR_SIZE)
 
@@ -125,7 +129,7 @@
  * directly without tranlation, we catch the bug with a NULL-deference
  * kernel oops. Illegal ranges of incoming indices are caught too.
  */
-static inline unsigned long fix_to_virt(const unsigned int idx)
+static __always_inline unsigned long fix_to_virt(const unsigned int idx)
 {
 	/*
 	 * this branch gets completely eliminated after inlining,
@@ -148,4 +152,5 @@
 	return __virt_to_fix(vaddr);
 }
 
+#endif /* !__ASSEMBLY__ */
 #endif
diff -Nru a/include/asm-i386/hardirq.h b/include/asm-i386/hardirq.h
--- a/include/asm-i386/hardirq.h	2004-10-18 14:56:49 -07:00
+++ b/include/asm-i386/hardirq.h	2004-10-18 14:56:49 -07:00
@@ -37,20 +37,6 @@
 #define SOFTIRQ_SHIFT	(PREEMPT_SHIFT + PREEMPT_BITS)
 #define HARDIRQ_SHIFT	(SOFTIRQ_SHIFT + SOFTIRQ_BITS)
 
-#define __MASK(x)	((1UL << (x))-1)
-
-#define PREEMPT_MASK	(__MASK(PREEMPT_BITS) << PREEMPT_SHIFT)
-#define HARDIRQ_MASK	(__MASK(HARDIRQ_BITS) << HARDIRQ_SHIFT)
-#define SOFTIRQ_MASK	(__MASK(SOFTIRQ_BITS) << SOFTIRQ_SHIFT)
-
-#define hardirq_count()	(preempt_count() & HARDIRQ_MASK)
-#define softirq_count()	(preempt_count() & SOFTIRQ_MASK)
-#define irq_count()	(preempt_count() & (HARDIRQ_MASK | SOFTIRQ_MASK))
-
-#define PREEMPT_OFFSET	(1UL << PREEMPT_SHIFT)
-#define SOFTIRQ_OFFSET	(1UL << SOFTIRQ_SHIFT)
-#define HARDIRQ_OFFSET	(1UL << HARDIRQ_SHIFT)
-
 /*
  * The hardirq mask has to be large enough to have
  * space for potentially all IRQ sources in the system
@@ -60,30 +46,10 @@
 # error HARDIRQ_BITS is too low!
 #endif
 
-/*
- * Are we doing bottom half or hardware interrupt processing?
- * Are we in a softirq context? Interrupt context?
- */
-#define in_irq()		(hardirq_count())
-#define in_softirq()		(softirq_count())
-#define in_interrupt()		(irq_count())
-
-
-#define hardirq_trylock()	(!in_interrupt())
-#define hardirq_endlock()	do { } while (0)
-
-#define irq_enter()		(preempt_count() += HARDIRQ_OFFSET)
 #define nmi_enter()		(irq_enter())
 #define nmi_exit()		(preempt_count() -= HARDIRQ_OFFSET)
 
-#ifdef CONFIG_PREEMPT
-# include <linux/smp_lock.h>
-# define in_atomic()	((preempt_count() & ~PREEMPT_ACTIVE) != kernel_locked())
-# define IRQ_EXIT_OFFSET (HARDIRQ_OFFSET-1)
-#else
-# define in_atomic()	(preempt_count() != 0)
-# define IRQ_EXIT_OFFSET HARDIRQ_OFFSET
-#endif
+#define irq_enter()		(preempt_count() += HARDIRQ_OFFSET)
 #define irq_exit()							\
 do {									\
 		preempt_count() -= IRQ_EXIT_OFFSET;			\
@@ -91,11 +57,5 @@
 			do_softirq();					\
 		preempt_enable_no_resched();				\
 } while (0)
-
-#ifndef CONFIG_SMP
-# define synchronize_irq(irq)	barrier()
-#else
-  extern void synchronize_irq(unsigned int irq);
-#endif /* CONFIG_SMP */
 
 #endif /* __ASM_HARDIRQ_H */
diff -Nru a/include/asm-i386/hw_irq.h b/include/asm-i386/hw_irq.h
--- a/include/asm-i386/hw_irq.h	2004-10-18 14:57:04 -07:00
+++ b/include/asm-i386/hw_irq.h	2004-10-18 14:57:04 -07:00
@@ -68,46 +68,6 @@
 
 #define IO_APIC_IRQ(x) (((x) >= 16) || ((1<<(x)) & io_apic_irqs))
 
-/*
- * 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 x86_do_profile(struct pt_regs * regs)
-{
-	unsigned long eip;
-	extern unsigned long prof_cpu_mask;
- 
-	profile_hook(regs);
- 
-	if (user_mode(regs))
-		return;
- 
-	if (!prof_buffer)
-		return;
-
-	eip = regs->eip;
- 
-	/*
-	 * Only measure the CPUs specified by /proc/irq/prof_cpu_mask.
-	 * (default is all CPUs.)
-	 */
-	if (!((1<<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]);
-}
- 
 #if defined(CONFIG_X86_IO_APIC)
 static inline void hw_resend_irq(struct hw_interrupt_type *h, unsigned int i)
 {
diff -Nru a/include/asm-i386/io.h b/include/asm-i386/io.h
--- a/include/asm-i386/io.h	2004-10-18 14:57:04 -07:00
+++ b/include/asm-i386/io.h	2004-10-18 14:57:04 -07:00
@@ -2,6 +2,8 @@
 #define _ASM_IO_H
 
 #include <linux/config.h>
+#include <linux/string.h>
+#include <linux/compiler.h>
 
 /*
  * This file contains the definitions for the x86 IO instructions
@@ -43,6 +45,8 @@
 
 #ifdef __KERNEL__
 
+#include <asm-generic/iomap.h>
+
 #include <linux/vmalloc.h>
 
 /**
@@ -86,7 +90,7 @@
  */
 #define page_to_phys(page)    ((dma_addr_t)page_to_pfn(page) << PAGE_SHIFT)
 
-extern void * __ioremap(unsigned long offset, unsigned long size, unsigned long flags);
+extern void __iomem * __ioremap(unsigned long offset, unsigned long size, unsigned long flags);
 
 /**
  * ioremap     -   map bus memory into CPU space
@@ -100,13 +104,13 @@
  * address. 
  */
 
-static inline void * ioremap (unsigned long offset, unsigned long size)
+static inline void __iomem * ioremap(unsigned long offset, unsigned long size)
 {
 	return __ioremap(offset, size, 0);
 }
 
-extern void * ioremap_nocache (unsigned long offset, unsigned long size);
-extern void iounmap(void *addr);
+extern void __iomem * ioremap_nocache(unsigned long offset, unsigned long size);
+extern void iounmap(volatile void __iomem *addr);
 
 /*
  * bt_ioremap() and bt_iounmap() are for temporary early boot-time
@@ -139,9 +143,18 @@
  * memory location directly.
  */
 
-#define readb(addr) (*(volatile unsigned char *) (addr))
-#define readw(addr) (*(volatile unsigned short *) (addr))
-#define readl(addr) (*(volatile unsigned int *) (addr))
+static inline unsigned char readb(const volatile void __iomem *addr)
+{
+	return *(volatile unsigned char __force *) addr;
+}
+static inline unsigned short readw(const volatile void __iomem *addr)
+{
+	return *(volatile unsigned short __force *) addr;
+}
+static inline unsigned int readl(const volatile void __iomem *addr)
+{
+	return *(volatile unsigned int __force *) addr;
+}
 #define readb_relaxed(addr) readb(addr)
 #define readw_relaxed(addr) readw(addr)
 #define readl_relaxed(addr) readl(addr)
@@ -149,16 +162,34 @@
 #define __raw_readw readw
 #define __raw_readl readl
 
-#define writeb(b,addr) (*(volatile unsigned char *) (addr) = (b))
-#define writew(b,addr) (*(volatile unsigned short *) (addr) = (b))
-#define writel(b,addr) (*(volatile unsigned int *) (addr) = (b))
+static inline void writeb(unsigned char b, volatile void __iomem *addr)
+{
+	*(volatile unsigned char __force *) addr = b;
+}
+static inline void writew(unsigned short b, volatile void __iomem *addr)
+{
+	*(volatile unsigned short __force *) addr = b;
+}
+static inline void writel(unsigned int b, volatile void __iomem *addr)
+{
+	*(volatile unsigned int __force *) addr = b;
+}
 #define __raw_writeb writeb
 #define __raw_writew writew
 #define __raw_writel writel
 
-#define memset_io(a,b,c)	memset((void *)(a),(b),(c))
-#define memcpy_fromio(a,b,c)	__memcpy((a),(void *)(b),(c))
-#define memcpy_toio(a,b,c)	__memcpy((void *)(a),(b),(c))
+static inline void memset_io(volatile void __iomem *addr, unsigned char val, int count)
+{
+	memset((void __force *) addr, val, count);
+}
+static inline void memcpy_fromio(void *dst, volatile void __iomem *src, int count)
+{
+	__memcpy(dst, (void __force *) src, count);
+}
+static inline void memcpy_toio(volatile void __iomem *dst, const void *src, int count)
+{
+	__memcpy((void __force *) dst, src, count);
+}
 
 /*
  * ISA space is 'always mapped' on a typical x86 system, no need to
@@ -168,7 +199,7 @@
  * used as the IO-area pointer (it can be iounmapped as well, so the
  * analogy with PCI is quite large):
  */
-#define __ISA_IO_base ((char *)(PAGE_OFFSET))
+#define __ISA_IO_base ((char __iomem *)(PAGE_OFFSET))
 
 #define isa_readb(a) readb(__ISA_IO_base + (a))
 #define isa_readw(a) readw(__ISA_IO_base + (a))
@@ -185,8 +216,8 @@
  * Again, i386 does not require mem IO specific function.
  */
 
-#define eth_io_copy_and_sum(a,b,c,d)		eth_copy_and_sum((a),(void *)(b),(c),(d))
-#define isa_eth_io_copy_and_sum(a,b,c,d)	eth_copy_and_sum((a),(void *)(__ISA_IO_base + (b)),(c),(d))
+#define eth_io_copy_and_sum(a,b,c,d)		eth_copy_and_sum((a),(void __force *)(b),(c),(d))
+#define isa_eth_io_copy_and_sum(a,b,c,d)	eth_copy_and_sum((a),(void __force *)(__ISA_IO_base + (b)),(c),(d))
 
 /**
  *	check_signature		-	find BIOS signatures
@@ -199,7 +230,7 @@
  *	Returns 1 on a match.
  */
  
-static inline int check_signature(unsigned long io_addr,
+static inline int check_signature(volatile void __iomem * io_addr,
 	const unsigned char *signature, int length)
 {
 	int retval = 0;
diff -Nru a/include/asm-i386/kdebug.h b/include/asm-i386/kdebug.h
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/include/asm-i386/kdebug.h	2004-10-18 14:57:24 -07:00
@@ -0,0 +1,50 @@
+#ifndef _I386_KDEBUG_H
+#define _I386_KDEBUG_H 1
+
+/*
+ * Aug-05 2004 Ported by Prasanna S Panchamukhi <prasanna@in.ibm.com>
+ * from x86_64 architecture.
+ */
+#include <linux/notifier.h>
+
+struct pt_regs;
+
+struct die_args {
+	struct pt_regs *regs;
+	const char *str;
+	long err;
+	int trapnr;
+	int signr;
+};
+
+/* Note - you should never unregister because that can race with NMIs.
+   If you really want to do it first unregister - then synchronize_kernel - then free.
+  */
+int register_die_notifier(struct notifier_block *nb);
+extern struct notifier_block *i386die_chain;
+
+
+/* Grossly misnamed. */
+enum die_val {
+	DIE_OOPS = 1,
+	DIE_INT3,
+	DIE_DEBUG,
+	DIE_PANIC,
+	DIE_NMI,
+	DIE_DIE,
+	DIE_NMIWATCHDOG,
+	DIE_KERNELDEBUG,
+	DIE_TRAP,
+	DIE_GPF,
+	DIE_CALL,
+	DIE_NMI_IPI,
+	DIE_PAGE_FAULT,
+};
+
+static inline int notify_die(enum die_val val,char *str,struct pt_regs *regs,long err,int trap, int sig)
+{
+	struct die_args args = { .regs=regs, .str=str, .err=err, .trapnr=trap,.signr=sig };
+	return notifier_call_chain(&i386die_chain, val, &args);
+}
+
+#endif
diff -Nru a/include/asm-i386/kprobes.h b/include/asm-i386/kprobes.h
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/include/asm-i386/kprobes.h	2004-10-18 14:57:23 -07:00
@@ -0,0 +1,60 @@
+#ifndef _ASM_KPROBES_H
+#define _ASM_KPROBES_H
+/*
+ *  Kernel Probes (KProbes)
+ *  include/asm-i386/kprobes.h
+ *
+ * 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.
+ *
+ * Copyright (C) IBM Corporation, 2002, 2004
+ *
+ * 2002-Oct	Created by Vamsi Krishna S <vamsi_krishna@in.ibm.com> Kernel
+ *		Probes initial implementation ( includes suggestions from
+ *		Rusty Russell).
+ */
+#include <linux/types.h>
+#include <linux/ptrace.h>
+
+struct pt_regs;
+
+typedef u8 kprobe_opcode_t;
+#define BREAKPOINT_INSTRUCTION	0xcc
+#define MAX_INSN_SIZE 16
+#define MAX_STACK_SIZE 64
+#define MIN_STACK_SIZE(ADDR) (((MAX_STACK_SIZE) < \
+	(((unsigned long)current_thread_info()) + THREAD_SIZE - (ADDR))) \
+	? (MAX_STACK_SIZE) \
+	: (((unsigned long)current_thread_info()) + THREAD_SIZE - (ADDR)))
+
+/* trap3/1 are intr gates for kprobes.  So, restore the status of IF,
+ * if necessary, before executing the original int3/1 (trap) handler.
+ */
+static inline void restore_interrupts(struct pt_regs *regs)
+{
+	if (regs->eflags & IF_MASK)
+		local_irq_enable();
+}
+
+#ifdef CONFIG_KPROBES
+extern int kprobe_exceptions_notify(struct notifier_block *self,
+				    unsigned long val, void *data);
+#else				/* !CONFIG_KPROBES */
+static inline int kprobe_exceptions_notify(struct notifier_block *self,
+					   unsigned long val, void *data)
+{
+	return 0;
+}
+#endif
+#endif				/* _ASM_KPROBES_H */
diff -Nru a/include/asm-i386/linkage.h b/include/asm-i386/linkage.h
--- a/include/asm-i386/linkage.h	2004-10-18 14:57:05 -07:00
+++ b/include/asm-i386/linkage.h	2004-10-18 14:57:05 -07:00
@@ -5,6 +5,10 @@
 #define FASTCALL(x)	x __attribute__((regparm(3)))
 #define fastcall	__attribute__((regparm(3)))
 
+#ifdef CONFIG_REGPARM
+# define prevent_tail_call(ret) __asm__ ("" : "=r" (ret) : "0" (ret))
+#endif
+
 #ifdef CONFIG_X86_ALIGNMENT_16
 #define __ALIGN .align 16,0x90
 #define __ALIGN_STR ".align 16,0x90"
diff -Nru a/include/asm-i386/mach-bigsmp/mach_ipi.h b/include/asm-i386/mach-bigsmp/mach_ipi.h
--- a/include/asm-i386/mach-bigsmp/mach_ipi.h	2004-10-18 14:56:29 -07:00
+++ b/include/asm-i386/mach-bigsmp/mach_ipi.h	2004-10-18 14:56:29 -07:00
@@ -1,7 +1,7 @@
 #ifndef __ASM_MACH_IPI_H
 #define __ASM_MACH_IPI_H
 
-inline void send_IPI_mask_sequence(cpumask_t mask, int vector);
+void send_IPI_mask_sequence(cpumask_t mask, int vector);
 
 static inline void send_IPI_mask(cpumask_t mask, int vector)
 {
diff -Nru a/include/asm-i386/mach-default/do_timer.h b/include/asm-i386/mach-default/do_timer.h
--- a/include/asm-i386/mach-default/do_timer.h	2004-10-18 14:57:03 -07:00
+++ b/include/asm-i386/mach-default/do_timer.h	2004-10-18 14:57:03 -07:00
@@ -22,7 +22,7 @@
  * system, in that case we have to call the local interrupt handler.
  */
 #ifndef CONFIG_X86_LOCAL_APIC
-	x86_do_profile(regs);
+	profile_tick(CPU_PROFILING, regs);
 #else
 	if (!using_apic_timer)
 		smp_local_timer_interrupt(regs);
diff -Nru a/include/asm-i386/mach-default/mach_ipi.h b/include/asm-i386/mach-default/mach_ipi.h
--- a/include/asm-i386/mach-default/mach_ipi.h	2004-10-18 14:57:03 -07:00
+++ b/include/asm-i386/mach-default/mach_ipi.h	2004-10-18 14:57:03 -07:00
@@ -1,8 +1,8 @@
 #ifndef __ASM_MACH_IPI_H
 #define __ASM_MACH_IPI_H
 
-inline void send_IPI_mask_bitmask(cpumask_t mask, int vector);
-inline void __send_IPI_shortcut(unsigned int shortcut, int vector);
+void send_IPI_mask_bitmask(cpumask_t mask, int vector);
+void __send_IPI_shortcut(unsigned int shortcut, int vector);
 
 static inline void send_IPI_mask(cpumask_t mask, int vector)
 {
diff -Nru a/include/asm-i386/mach-es7000/mach_ipi.h b/include/asm-i386/mach-es7000/mach_ipi.h
--- a/include/asm-i386/mach-es7000/mach_ipi.h	2004-10-18 14:56:28 -07:00
+++ b/include/asm-i386/mach-es7000/mach_ipi.h	2004-10-18 14:56:28 -07:00
@@ -1,7 +1,7 @@
 #ifndef __ASM_MACH_IPI_H
 #define __ASM_MACH_IPI_H
 
-inline void send_IPI_mask_sequence(cpumask_t mask, int vector);
+void send_IPI_mask_sequence(cpumask_t mask, int vector);
 
 static inline void send_IPI_mask(cpumask_t mask, int vector)
 {
diff -Nru a/include/asm-i386/mach-es7000/mach_mpparse.h b/include/asm-i386/mach-es7000/mach_mpparse.h
--- a/include/asm-i386/mach-es7000/mach_mpparse.h	2004-10-18 14:55:53 -07:00
+++ b/include/asm-i386/mach-es7000/mach_mpparse.h	2004-10-18 14:55:53 -07:00
@@ -21,7 +21,8 @@
 	if (mpc->mpc_oemptr) {
 		struct mp_config_oemtable *oem_table = 
 			(struct mp_config_oemtable *)mpc->mpc_oemptr;
-		return parse_unisys_oem((char *)oem_table, oem_table->oem_length);
+		if (!strncmp(oem, "UNISYS", 6))
+			return parse_unisys_oem((char *)oem_table, oem_table->oem_length);
 	}
 	return 0;
 }
diff -Nru a/include/asm-i386/mach-es7000/mach_mpspec.h b/include/asm-i386/mach-es7000/mach_mpspec.h
--- a/include/asm-i386/mach-es7000/mach_mpspec.h	2004-10-18 14:56:27 -07:00
+++ b/include/asm-i386/mach-es7000/mach_mpspec.h	2004-10-18 14:56:27 -07:00
@@ -3,6 +3,6 @@
 
 #define MAX_IRQ_SOURCES 256
 
-#define MAX_MP_BUSSES 32
+#define MAX_MP_BUSSES 256
 
 #endif /* __ASM_MACH_MPSPEC_H */
diff -Nru a/include/asm-i386/mach-numaq/mach_ipi.h b/include/asm-i386/mach-numaq/mach_ipi.h
--- a/include/asm-i386/mach-numaq/mach_ipi.h	2004-10-18 14:56:49 -07:00
+++ b/include/asm-i386/mach-numaq/mach_ipi.h	2004-10-18 14:56:49 -07:00
@@ -1,7 +1,7 @@
 #ifndef __ASM_MACH_IPI_H
 #define __ASM_MACH_IPI_H
 
-static inline void send_IPI_mask_sequence(cpumask_t, int vector);
+inline void send_IPI_mask_sequence(cpumask_t, int vector);
 
 static inline void send_IPI_mask(cpumask_t mask, int vector)
 {
diff -Nru a/include/asm-i386/mach-summit/mach_apic.h b/include/asm-i386/mach-summit/mach_apic.h
--- a/include/asm-i386/mach-summit/mach_apic.h	2004-10-18 14:56:33 -07:00
+++ b/include/asm-i386/mach-summit/mach_apic.h	2004-10-18 14:56:33 -07:00
@@ -19,11 +19,15 @@
 
 static inline cpumask_t target_cpus(void)
 {
-	return CPU_MASK_ALL;
+	/* CPU_MASK_ALL (0xff) has undefined behaviour with
+	 * dest_LowestPrio mode logical clustered apic interrupt routing
+	 * Just start on cpu 0.  IRQ balancing will spread load
+	 */
+	return cpumask_of_cpu(0);
 } 
 #define TARGET_CPUS	(target_cpus())
 
-#define INT_DELIVERY_MODE (dest_Fixed)
+#define INT_DELIVERY_MODE (dest_LowestPrio)
 #define INT_DEST_MODE 1     /* logical delivery broadcast to all procs */
 
 static inline unsigned long check_apicid_used(physid_mask_t bitmap, int apicid)
diff -Nru a/include/asm-i386/mach-summit/mach_ipi.h b/include/asm-i386/mach-summit/mach_ipi.h
--- a/include/asm-i386/mach-summit/mach_ipi.h	2004-10-18 14:56:17 -07:00
+++ b/include/asm-i386/mach-summit/mach_ipi.h	2004-10-18 14:56:17 -07:00
@@ -1,7 +1,7 @@
 #ifndef __ASM_MACH_IPI_H
 #define __ASM_MACH_IPI_H
 
-inline void send_IPI_mask_sequence(cpumask_t mask, int vector);
+void send_IPI_mask_sequence(cpumask_t mask, int vector);
 
 static inline void send_IPI_mask(cpumask_t mask, int vector)
 {
diff -Nru a/include/asm-i386/mach-visws/do_timer.h b/include/asm-i386/mach-visws/do_timer.h
--- a/include/asm-i386/mach-visws/do_timer.h	2004-10-18 14:56:28 -07:00
+++ b/include/asm-i386/mach-visws/do_timer.h	2004-10-18 14:56:28 -07:00
@@ -15,7 +15,7 @@
  * system, in that case we have to call the local interrupt handler.
  */
 #ifndef CONFIG_X86_LOCAL_APIC
-	x86_do_profile(regs);
+	profile_tick(CPU_PROFILING, regs);
 #else
 	if (!using_apic_timer)
 		smp_local_timer_interrupt(regs);
diff -Nru a/include/asm-i386/mach-visws/mach_apic.h b/include/asm-i386/mach-visws/mach_apic.h
--- a/include/asm-i386/mach-visws/mach_apic.h	2004-10-18 14:55:54 -07:00
+++ b/include/asm-i386/mach-visws/mach_apic.h	2004-10-18 14:55:54 -07:00
@@ -2,6 +2,7 @@
 #define __ASM_MACH_APIC_H
 
 #include <mach_apicdef.h>
+#include <asm/smp.h>
 
 #define APIC_DFR_VALUE	(APIC_DFR_FLAT)
 
diff -Nru a/include/asm-i386/mmu_context.h b/include/asm-i386/mmu_context.h
--- a/include/asm-i386/mmu_context.h	2004-10-18 14:55:53 -07:00
+++ b/include/asm-i386/mmu_context.h	2004-10-18 14:55:53 -07:00
@@ -18,8 +18,8 @@
 {
 #ifdef CONFIG_SMP
 	unsigned cpu = smp_processor_id();
-	if (cpu_tlbstate[cpu].state == TLBSTATE_OK)
-		cpu_tlbstate[cpu].state = TLBSTATE_LAZY;	
+	if (per_cpu(cpu_tlbstate, cpu).state == TLBSTATE_OK)
+		per_cpu(cpu_tlbstate, cpu).state = TLBSTATE_LAZY;
 #endif
 }
 
@@ -33,8 +33,8 @@
 		/* stop flush ipis for the previous mm */
 		cpu_clear(cpu, prev->cpu_vm_mask);
 #ifdef CONFIG_SMP
-		cpu_tlbstate[cpu].state = TLBSTATE_OK;
-		cpu_tlbstate[cpu].active_mm = next;
+		per_cpu(cpu_tlbstate, cpu).state = TLBSTATE_OK;
+		per_cpu(cpu_tlbstate, cpu).active_mm = next;
 #endif
 		cpu_set(cpu, next->cpu_vm_mask);
 
@@ -49,8 +49,8 @@
 	}
 #ifdef CONFIG_SMP
 	else {
-		cpu_tlbstate[cpu].state = TLBSTATE_OK;
-		BUG_ON(cpu_tlbstate[cpu].active_mm != next);
+		per_cpu(cpu_tlbstate, cpu).state = TLBSTATE_OK;
+		BUG_ON(per_cpu(cpu_tlbstate, cpu).active_mm != next);
 
 		if (!cpu_test_and_set(cpu, next->cpu_vm_mask)) {
 			/* We were in lazy tlb mode and leave_mm disabled 
diff -Nru a/include/asm-i386/mtrr.h b/include/asm-i386/mtrr.h
--- a/include/asm-i386/mtrr.h	2004-10-18 14:56:29 -07:00
+++ b/include/asm-i386/mtrr.h	2004-10-18 14:56:29 -07:00
@@ -67,8 +67,6 @@
 
 #ifdef __KERNEL__
 
-extern char *mtrr_strings[]; 
-
 /*  The following functions are for use by other drivers  */
 # ifdef CONFIG_MTRR
 extern int mtrr_add (unsigned long base, unsigned long size,
diff -Nru a/include/asm-i386/page.h b/include/asm-i386/page.h
--- a/include/asm-i386/page.h	2004-10-18 14:56:13 -07:00
+++ b/include/asm-i386/page.h	2004-10-18 14:56:13 -07:00
@@ -94,13 +94,13 @@
  * and CONFIG_HIGHMEM64G options in the kernel configuration.
  */
 
+#ifndef __ASSEMBLY__
+
 /*
  * This much address space is reserved for vmalloc() and iomap()
  * as well as fixmap mappings.
  */
-#define __VMALLOC_RESERVE	(128 << 20)
-
-#ifndef __ASSEMBLY__
+extern unsigned int __VMALLOC_RESERVE;
 
 /* Pure 2^n version of get_order */
 static __inline__ int get_order(unsigned long size)
@@ -115,6 +115,8 @@
 	} while (size);
 	return order;
 }
+
+extern int sysctl_legacy_va_layout;
 
 #endif /* __ASSEMBLY__ */
 
diff -Nru a/include/asm-i386/pgtable-2level.h b/include/asm-i386/pgtable-2level.h
--- a/include/asm-i386/pgtable-2level.h	2004-10-18 14:56:32 -07:00
+++ b/include/asm-i386/pgtable-2level.h	2004-10-18 14:56:32 -07:00
@@ -75,4 +75,11 @@
 #define pgoff_to_pte(off) \
 	((pte_t) { (((off) & 0x1f) << 1) + (((off) >> 5) << 8) + _PAGE_FILE })
 
+/* Encode and de-code a swap entry */
+#define __swp_type(x)			(((x).val >> 1) & 0x1f)
+#define __swp_offset(x)			((x).val >> 8)
+#define __swp_entry(type, offset)	((swp_entry_t) { ((type) << 1) | ((offset) << 8) })
+#define __pte_to_swp_entry(pte)		((swp_entry_t) { (pte).pte_low })
+#define __swp_entry_to_pte(x)		((pte_t) { (x).val })
+
 #endif /* _I386_PGTABLE_2LEVEL_H */
diff -Nru a/include/asm-i386/pgtable-3level.h b/include/asm-i386/pgtable-3level.h
--- a/include/asm-i386/pgtable-3level.h	2004-10-18 14:56:49 -07:00
+++ b/include/asm-i386/pgtable-3level.h	2004-10-18 14:56:49 -07:00
@@ -54,6 +54,7 @@
 	smp_wmb();
 	ptep->pte_low = pte.pte_low;
 }
+#define __HAVE_ARCH_SET_PTE_ATOMIC
 #define set_pte_atomic(pteptr,pteval) \
 		set_64bit((unsigned long long *)(pteptr),pte_val(pteval))
 #define set_pmd(pmdptr,pmdval) \
@@ -133,5 +134,12 @@
 #define pte_to_pgoff(pte) ((pte).pte_high)
 #define pgoff_to_pte(off) ((pte_t) { _PAGE_FILE, (off) })
 #define PTE_FILE_MAX_BITS       32
+
+/* Encode and de-code a swap entry */
+#define __swp_type(x)			(((x).val) & 0x1f)
+#define __swp_offset(x)			((x).val >> 5)
+#define __swp_entry(type, offset)	((swp_entry_t){(type) | (offset) << 5})
+#define __pte_to_swp_entry(pte)		((swp_entry_t){ (pte).pte_high })
+#define __swp_entry_to_pte(x)		((pte_t){ 0, (x).val })
 
 #endif /* _I386_PGTABLE_3LEVEL_H */
diff -Nru a/include/asm-i386/pgtable.h b/include/asm-i386/pgtable.h
--- a/include/asm-i386/pgtable.h	2004-10-18 14:56:49 -07:00
+++ b/include/asm-i386/pgtable.h	2004-10-18 14:56:49 -07:00
@@ -398,13 +398,6 @@
 		}							  \
 	} while (0)
 
-/* Encode and de-code a swap entry */
-#define __swp_type(x)			(((x).val >> 1) & 0x1f)
-#define __swp_offset(x)			((x).val >> 8)
-#define __swp_entry(type, offset)	((swp_entry_t) { ((type) << 1) | ((offset) << 8) })
-#define __pte_to_swp_entry(pte)		((swp_entry_t) { (pte).pte_low })
-#define __swp_entry_to_pte(x)		((pte_t) { (x).val })
-
 #endif /* !__ASSEMBLY__ */
 
 #ifndef CONFIG_DISCONTIGMEM
diff -Nru a/include/asm-i386/processor.h b/include/asm-i386/processor.h
--- a/include/asm-i386/processor.h	2004-10-18 14:55:54 -07:00
+++ b/include/asm-i386/processor.h	2004-10-18 14:55:54 -07:00
@@ -19,6 +19,7 @@
 #include <linux/cache.h>
 #include <linux/config.h>
 #include <linux/threads.h>
+#include <asm/percpu.h>
 
 /* flag for disabling the tsc */
 extern int tsc_disable;
@@ -84,8 +85,8 @@
 
 extern struct cpuinfo_x86 boot_cpu_data;
 extern struct cpuinfo_x86 new_cpu_data;
-extern struct tss_struct init_tss[NR_CPUS];
 extern struct tss_struct doublefault_tss;
+DECLARE_PER_CPU(struct tss_struct, init_tss);
 
 #ifdef CONFIG_SMP
 extern struct cpuinfo_x86 cpu_data[];
@@ -296,6 +297,8 @@
  */
 #define TASK_UNMAPPED_BASE	(PAGE_ALIGN(TASK_SIZE / 3))
 
+#define HAVE_ARCH_PICK_MMAP_LAYOUT
+
 /*
  * Size of io_bitmap.
  */
@@ -304,6 +307,7 @@
 #define IO_BITMAP_LONGS (IO_BITMAP_BYTES/sizeof(long))
 #define IO_BITMAP_OFFSET offsetof(struct tss_struct,io_bitmap)
 #define INVALID_IO_BITMAP_OFFSET 0x8000
+#define INVALID_IO_BITMAP_OFFSET_LAZY 0x9000
 
 struct i387_fsave_struct {
 	long	cwd;
@@ -357,6 +361,8 @@
 	unsigned long seg;
 } mm_segment_t;
 
+struct thread_struct;
+
 struct tss_struct {
 	unsigned short	back_link,__blh;
 	unsigned long	esp0;
@@ -389,9 +395,14 @@
 	 */
 	unsigned long	io_bitmap[IO_BITMAP_LONGS + 1];
 	/*
+	 * Cache the current maximum and the last task that used the bitmap:
+	 */
+	unsigned long io_bitmap_max;
+	struct thread_struct *io_bitmap_owner;
+	/*
 	 * pads the TSS to be cacheline-aligned (size is 0x100)
 	 */
-	unsigned long __cacheline_filler[37];
+	unsigned long __cacheline_filler[35];
 	/*
 	 * .. and then another 0x100 bytes for emergency kernel stack
 	 */
@@ -422,6 +433,8 @@
 	unsigned int		saved_fs, saved_gs;
 /* IO permissions */
 	unsigned long	*io_bitmap_ptr;
+/* max allowed port in the bitmap, in bytes: */
+	unsigned long	io_bitmap_max;
 };
 
 #define INIT_THREAD  {							\
@@ -439,7 +452,6 @@
 #define INIT_TSS  {							\
 	.esp0		= sizeof(init_stack) + (long)&init_stack,	\
 	.ss0		= __KERNEL_DS,					\
-	.esp1		= sizeof(init_tss[0]) + (long)&init_tss[0],	\
 	.ss1		= __KERNEL_CS,					\
 	.ldt		= GDT_ENTRY_LDT,				\
 	.io_bitmap_base	= INVALID_IO_BITMAP_OFFSET,			\
@@ -644,10 +656,5 @@
 extern void select_idle_routine(const struct cpuinfo_x86 *c);
 
 #define cache_line_size() (boot_cpu_data.x86_cache_alignment)
-
-#ifdef CONFIG_SCHED_SMT
-#define ARCH_HAS_SCHED_DOMAIN
-#define ARCH_HAS_SCHED_WAKE_IDLE
-#endif
 
 #endif /* __ASM_I386_PROCESSOR_H */
diff -Nru a/include/asm-i386/ptrace.h b/include/asm-i386/ptrace.h
--- a/include/asm-i386/ptrace.h	2004-10-18 14:55:54 -07:00
+++ b/include/asm-i386/ptrace.h	2004-10-18 14:55:54 -07:00
@@ -57,6 +57,11 @@
 #ifdef __KERNEL__
 #define user_mode(regs) ((VM_MASK & (regs)->eflags) || (3 & (regs)->xcs))
 #define instruction_pointer(regs) ((regs)->eip)
+#if defined(CONFIG_SMP) && defined(CONFIG_FRAME_POINTER)
+extern unsigned long profile_pc(struct pt_regs *regs);
+#else
+#define profile_pc(regs) instruction_pointer(regs)
+#endif
 #endif
 
 #endif
diff -Nru a/include/asm-i386/resource.h b/include/asm-i386/resource.h
--- a/include/asm-i386/resource.h	2004-10-18 14:57:19 -07:00
+++ b/include/asm-i386/resource.h	2004-10-18 14:57:19 -07:00
@@ -40,7 +40,7 @@
 	{ RLIM_INFINITY, RLIM_INFINITY },		\
 	{             0,             0 },		\
 	{      INR_OPEN,     INR_OPEN  },		\
-	{ RLIM_INFINITY, RLIM_INFINITY },		\
+	{   MLOCK_LIMIT,   MLOCK_LIMIT },		\
 	{ RLIM_INFINITY, RLIM_INFINITY },		\
 	{ RLIM_INFINITY, RLIM_INFINITY },		\
 	{ MAX_SIGPENDING, MAX_SIGPENDING },		\
diff -Nru a/include/asm-i386/rwlock.h b/include/asm-i386/rwlock.h
--- a/include/asm-i386/rwlock.h	2004-10-18 14:57:04 -07:00
+++ b/include/asm-i386/rwlock.h	2004-10-18 14:57:04 -07:00
@@ -22,25 +22,19 @@
 
 #define __build_read_lock_ptr(rw, helper)   \
 	asm volatile(LOCK "subl $1,(%0)\n\t" \
-		     "js 2f\n" \
+		     "jns 1f\n" \
+		     "call " helper "\n\t" \
 		     "1:\n" \
-		     LOCK_SECTION_START("") \
-		     "2:\tcall " helper "\n\t" \
-		     "jmp 1b\n" \
-		     LOCK_SECTION_END \
 		     ::"a" (rw) : "memory")
 
 #define __build_read_lock_const(rw, helper)   \
 	asm volatile(LOCK "subl $1,%0\n\t" \
-		     "js 2f\n" \
-		     "1:\n" \
-		     LOCK_SECTION_START("") \
-		     "2:\tpushl %%eax\n\t" \
+		     "jns 1f\n" \
+		     "pushl %%eax\n\t" \
 		     "leal %0,%%eax\n\t" \
 		     "call " helper "\n\t" \
 		     "popl %%eax\n\t" \
-		     "jmp 1b\n" \
-		     LOCK_SECTION_END \
+		     "1:\n" \
 		     :"=m" (*(volatile int *)rw) : : "memory")
 
 #define __build_read_lock(rw, helper)	do { \
@@ -52,25 +46,19 @@
 
 #define __build_write_lock_ptr(rw, helper) \
 	asm volatile(LOCK "subl $" RW_LOCK_BIAS_STR ",(%0)\n\t" \
-		     "jnz 2f\n" \
+		     "jz 1f\n" \
+		     "call " helper "\n\t" \
 		     "1:\n" \
-		     LOCK_SECTION_START("") \
-		     "2:\tcall " helper "\n\t" \
-		     "jmp 1b\n" \
-		     LOCK_SECTION_END \
 		     ::"a" (rw) : "memory")
 
 #define __build_write_lock_const(rw, helper) \
 	asm volatile(LOCK "subl $" RW_LOCK_BIAS_STR ",%0\n\t" \
-		     "jnz 2f\n" \
-		     "1:\n" \
-		     LOCK_SECTION_START("") \
-		     "2:\tpushl %%eax\n\t" \
+		     "jz 1f\n" \
+		     "pushl %%eax\n\t" \
 		     "leal %0,%%eax\n\t" \
 		     "call " helper "\n\t" \
 		     "popl %%eax\n\t" \
-		     "jmp 1b\n" \
-		     LOCK_SECTION_END \
+		     "1:\n" \
 		     :"=m" (*(volatile int *)rw) : : "memory")
 
 #define __build_write_lock(rw, helper)	do { \
diff -Nru a/include/asm-i386/semaphore.h b/include/asm-i386/semaphore.h
--- a/include/asm-i386/semaphore.h	2004-10-18 14:56:27 -07:00
+++ b/include/asm-i386/semaphore.h	2004-10-18 14:56:27 -07:00
@@ -45,21 +45,15 @@
 	atomic_t count;
 	int sleepers;
 	wait_queue_head_t wait;
-#ifdef WAITQUEUE_DEBUG
-	long __magic;
-#endif
 };
 
-#ifdef WAITQUEUE_DEBUG
-# define __SEM_DEBUG_INIT(name) \
-		, (int)&(name).__magic
-#else
-# define __SEM_DEBUG_INIT(name)
-#endif
-
-#define __SEMAPHORE_INITIALIZER(name,count) \
-{ ATOMIC_INIT(count), 0, __WAIT_QUEUE_HEAD_INITIALIZER((name).wait) \
-	__SEM_DEBUG_INIT(name) }
+
+#define __SEMAPHORE_INITIALIZER(name, n)				\
+{									\
+	.count		= ATOMIC_INIT(n),				\
+	.sleepers	= 0,						\
+	.wait		= __WAIT_QUEUE_HEAD_INITIALIZER((name).wait)	\
+}
 
 #define __MUTEX_INITIALIZER(name) \
 	__SEMAPHORE_INITIALIZER(name,1)
@@ -81,9 +75,6 @@
 	atomic_set(&sem->count, val);
 	sem->sleepers = 0;
 	init_waitqueue_head(&sem->wait);
-#ifdef WAITQUEUE_DEBUG
-	sem->__magic = (int)&sem->__magic;
-#endif
 }
 
 static inline void init_MUTEX (struct semaphore *sem)
@@ -113,9 +104,6 @@
  */
 static inline void down(struct semaphore * sem)
 {
-#ifdef WAITQUEUE_DEBUG
-	CHECK_MAGIC(sem->__magic);
-#endif
 	might_sleep();
 	__asm__ __volatile__(
 		"# atomic down operation\n\t"
@@ -139,9 +127,6 @@
 {
 	int result;
 
-#ifdef WAITQUEUE_DEBUG
-	CHECK_MAGIC(sem->__magic);
-#endif
 	might_sleep();
 	__asm__ __volatile__(
 		"# atomic interruptible down operation\n\t"
@@ -167,10 +152,6 @@
 {
 	int result;
 
-#ifdef WAITQUEUE_DEBUG
-	CHECK_MAGIC(sem->__magic);
-#endif
-
 	__asm__ __volatile__(
 		"# atomic interruptible down operation\n\t"
 		LOCK "decl %1\n\t"     /* --sem->count */
@@ -195,9 +176,6 @@
  */
 static inline void up(struct semaphore * sem)
 {
-#ifdef WAITQUEUE_DEBUG
-	CHECK_MAGIC(sem->__magic);
-#endif
 	__asm__ __volatile__(
 		"# atomic up operation\n\t"
 		LOCK "incl %0\n\t"     /* ++sem->count */
diff -Nru a/include/asm-i386/smp.h b/include/asm-i386/smp.h
--- a/include/asm-i386/smp.h	2004-10-18 14:56:33 -07:00
+++ b/include/asm-i386/smp.h	2004-10-18 14:56:33 -07:00
@@ -43,6 +43,7 @@
 extern void zap_low_mappings (void);
 
 #define MAX_APICID 256
+extern u8 x86_cpu_to_apicid[];
 
 /*
  * This function is needed by all SMP systems. It must _always_ be valid
diff -Nru a/include/asm-i386/socket.h b/include/asm-i386/socket.h
--- a/include/asm-i386/socket.h	2004-10-18 14:55:55 -07:00
+++ b/include/asm-i386/socket.h	2004-10-18 14:55:55 -07:00
@@ -47,20 +47,4 @@
 
 #define SO_PEERSEC		31
 
-/* Nasty libc5 fixup - bletch */
-#if defined(__KERNEL__) || !defined(__GLIBC__) || (__GLIBC__ < 2)
-/* Socket types. */
-#define SOCK_STREAM	1		/* stream (connection) socket	*/
-#define SOCK_DGRAM	2		/* datagram (conn.less) socket	*/
-#define SOCK_RAW	3		/* raw socket			*/
-#define SOCK_RDM	4		/* reliably-delivered message	*/
-#define SOCK_SEQPACKET	5		/* sequential packet socket	*/
-#define SOCK_PACKET	10		/* linux specific way of	*/
-					/* getting packets at the dev	*/
-					/* level.  For writing rarp and	*/
-					/* other similar things on the	*/
-					/* user level.			*/
-#define	SOCK_MAX	(SOCK_PACKET+1)
-#endif
-
 #endif /* _ASM_SOCKET_H */
diff -Nru a/include/asm-i386/spinlock.h b/include/asm-i386/spinlock.h
--- a/include/asm-i386/spinlock.h	2004-10-18 14:56:20 -07:00
+++ b/include/asm-i386/spinlock.h	2004-10-18 14:56:20 -07:00
@@ -46,20 +46,18 @@
 #define spin_lock_string \
 	"\n1:\t" \
 	"lock ; decb %0\n\t" \
-	"js 2f\n" \
-	LOCK_SECTION_START("") \
+	"jns 3f\n" \
 	"2:\t" \
 	"rep;nop\n\t" \
 	"cmpb $0,%0\n\t" \
 	"jle 2b\n\t" \
 	"jmp 1b\n" \
-	LOCK_SECTION_END
+	"3:\n\t"
 
 #define spin_lock_string_flags \
 	"\n1:\t" \
 	"lock ; decb %0\n\t" \
-	"js 2f\n\t" \
-	LOCK_SECTION_START("") \
+	"jns 4f\n\t" \
 	"2:\t" \
 	"testl $0x200, %1\n\t" \
 	"jz 3f\n\t" \
@@ -70,7 +68,7 @@
 	"jle 3b\n\t" \
 	"cli\n\t" \
 	"jmp 1b\n" \
-	LOCK_SECTION_END
+	"4:\n\t"
 
 /*
  * This works. Despite all the confusion.
@@ -130,10 +128,8 @@
 static inline void _raw_spin_lock(spinlock_t *lock)
 {
 #ifdef CONFIG_DEBUG_SPINLOCK
-	__label__ here;
-here:
 	if (unlikely(lock->magic != SPINLOCK_MAGIC)) {
-		printk("eip: %p\n", &&here);
+		printk("eip: %p\n", __builtin_return_address(0));
 		BUG();
 	}
 #endif
@@ -145,10 +141,8 @@
 static inline void _raw_spin_lock_flags (spinlock_t *lock, unsigned long flags)
 {
 #ifdef CONFIG_DEBUG_SPINLOCK
-	__label__ here;
-here:
 	if (unlikely(lock->magic != SPINLOCK_MAGIC)) {
-		printk("eip: %p\n", &&here);
+		printk("eip: %p\n", __builtin_return_address(0));
 		BUG();
 	}
 #endif
diff -Nru a/include/asm-i386/thread_info.h b/include/asm-i386/thread_info.h
--- a/include/asm-i386/thread_info.h	2004-10-18 14:55:55 -07:00
+++ b/include/asm-i386/thread_info.h	2004-10-18 14:55:55 -07:00
@@ -157,7 +157,7 @@
 
 /* work to do on interrupt/exception return */
 #define _TIF_WORK_MASK \
-  (0x0000FFFF & ~(_TIF_SYSCALL_TRACE|_TIF_SYSCALL_AUDIT))
+  (0x0000FFFF & ~(_TIF_SYSCALL_TRACE|_TIF_SYSCALL_AUDIT|_TIF_SINGLESTEP))
 #define _TIF_ALLWORK_MASK	0x0000FFFF	/* work to do on any return to u-space */
 
 /*
diff -Nru a/include/asm-i386/timer.h b/include/asm-i386/timer.h
--- a/include/asm-i386/timer.h	2004-10-18 14:56:27 -07:00
+++ b/include/asm-i386/timer.h	2004-10-18 14:56:27 -07:00
@@ -28,6 +28,7 @@
 
 extern struct timer_opts* select_timer(void);
 extern void clock_fallback(void);
+void setup_pit_timer(void);
 
 /* Modifiers for buggy PIT handling */
 
diff -Nru a/include/asm-i386/timex.h b/include/asm-i386/timex.h
--- a/include/asm-i386/timex.h	2004-10-18 14:56:28 -07:00
+++ b/include/asm-i386/timex.h	2004-10-18 14:56:28 -07:00
@@ -7,7 +7,7 @@
 #define _ASMi386_TIMEX_H
 
 #include <linux/config.h>
-#include <asm/msr.h>
+#include <asm/processor.h>
 
 #ifdef CONFIG_X86_ELAN
 #  define CLOCK_TICK_RATE 1189200 /* AMD Elan has different frequency! */
@@ -40,14 +40,17 @@
 
 static inline cycles_t get_cycles (void)
 {
+	unsigned long long ret=0;
+
 #ifndef CONFIG_X86_TSC
-	return 0;
-#else
-	unsigned long long ret;
+	if (!cpu_has_tsc)
+		return 0;
+#endif
 
+#if defined(CONFIG_X86_GENERIC) || defined(CONFIG_X86_TSC)
 	rdtscll(ret);
-	return ret;
 #endif
+	return ret;
 }
 
 extern unsigned long cpu_khz;
diff -Nru a/include/asm-i386/tlbflush.h b/include/asm-i386/tlbflush.h
--- a/include/asm-i386/tlbflush.h	2004-10-18 14:57:04 -07:00
+++ b/include/asm-i386/tlbflush.h	2004-10-18 14:57:04 -07:00
@@ -131,7 +131,7 @@
 	int state;
 	char __cacheline_padding[L1_CACHE_BYTES-8];
 };
-extern struct tlb_state cpu_tlbstate[NR_CPUS];
+DECLARE_PER_CPU(struct tlb_state, cpu_tlbstate);
 
 
 #endif
diff -Nru a/include/asm-i386/topology.h b/include/asm-i386/topology.h
--- a/include/asm-i386/topology.h	2004-10-18 14:56:16 -07:00
+++ b/include/asm-i386/topology.h	2004-10-18 14:56:16 -07:00
@@ -67,7 +67,7 @@
 }
 
 /* Node-to-Node distance */
-#define node_distance(from, to) (from != to)
+#define node_distance(from, to) ((from) != (to))
 
 /* Cross-node load balancing interval. */
 #define NODE_BALANCE_RATE 100
diff -Nru a/include/asm-i386/uaccess.h b/include/asm-i386/uaccess.h
--- a/include/asm-i386/uaccess.h	2004-10-18 14:56:11 -07:00
+++ b/include/asm-i386/uaccess.h	2004-10-18 14:56:11 -07:00
@@ -375,8 +375,10 @@
 		: "m"(__m(addr)), "i"(errret), "0"(err))
 
 
-unsigned long __copy_to_user_ll(void __user *to, const void *from, unsigned long n);
-unsigned long __copy_from_user_ll(void *to, const void __user *from, unsigned long n);
+unsigned long __must_check __copy_to_user_ll(void __user *to,
+				const void *from, unsigned long n);
+unsigned long __must_check __copy_from_user_ll(void *to,
+				const void __user *from, unsigned long n);
 
 /*
  * Here we special-case 1, 2 and 4-byte copy_*_user invocations.  On a fault
@@ -399,8 +401,8 @@
  * Returns number of bytes that could not be copied.
  * On success, this will be zero.
  */
-static inline unsigned long
-__copy_to_user(void __user *to, const void *from, unsigned long n)
+static inline unsigned long __must_check
+__copy_to_user_inatomic(void __user *to, const void *from, unsigned long n)
 {
 	if (__builtin_constant_p(n)) {
 		unsigned long ret;
@@ -420,6 +422,13 @@
 	return __copy_to_user_ll(to, from, n);
 }
 
+static inline unsigned long __must_check
+__copy_to_user(void __user *to, const void *from, unsigned long n)
+{
+       might_sleep();
+       return __copy_to_user_inatomic(to, from, n);
+}
+
 /**
  * __copy_from_user: - Copy a block of data from user space, with less checking.
  * @to:   Destination address, in kernel space.
@@ -438,7 +447,7 @@
  * data to the requested size using zero bytes.
  */
 static inline unsigned long
-__copy_from_user(void *to, const void __user *from, unsigned long n)
+__copy_from_user_inatomic(void *to, const void __user *from, unsigned long n)
 {
 	if (__builtin_constant_p(n)) {
 		unsigned long ret;
@@ -458,11 +467,20 @@
 	return __copy_from_user_ll(to, from, n);
 }
 
-unsigned long copy_to_user(void __user *to, const void *from, unsigned long n);
-unsigned long copy_from_user(void *to,
-			const void __user *from, unsigned long n);
-long strncpy_from_user(char *dst, const char __user *src, long count);
-long __strncpy_from_user(char *dst, const char __user *src, long count);
+static inline unsigned long
+__copy_from_user(void *to, const void __user *from, unsigned long n)
+{
+       might_sleep();
+       return __copy_from_user_inatomic(to, from, n);
+}
+unsigned long __must_check copy_to_user(void __user *to,
+				const void *from, unsigned long n);
+unsigned long __must_check copy_from_user(void *to,
+				const void __user *from, unsigned long n);
+long __must_check strncpy_from_user(char *dst, const char __user *src,
+				long count);
+long __must_check __strncpy_from_user(char *dst,
+				const char __user *src, long count);
 
 /**
  * strlen_user: - Get the size of a string in user space.
@@ -481,7 +499,7 @@
 #define strlen_user(str) strnlen_user(str, ~0UL >> 1)
 
 long strnlen_user(const char __user *str, long n);
-unsigned long clear_user(void __user *mem, unsigned long len);
-unsigned long __clear_user(void __user *mem, unsigned long len);
+unsigned long __must_check clear_user(void __user *mem, unsigned long len);
+unsigned long __must_check __clear_user(void __user *mem, unsigned long len);
 
 #endif /* __i386_UACCESS_H */
diff -Nru a/include/asm-i386/unistd.h b/include/asm-i386/unistd.h
--- a/include/asm-i386/unistd.h	2004-10-18 14:56:33 -07:00
+++ b/include/asm-i386/unistd.h	2004-10-18 14:56:33 -07:00
@@ -289,8 +289,9 @@
 #define __NR_mq_notify		(__NR_mq_open+4)
 #define __NR_mq_getsetattr	(__NR_mq_open+5)
 #define __NR_sys_kexec_load	283
+#define __NR_waitid		284
 
-#define NR_syscalls 284
+#define NR_syscalls 285
 
 /* user-visible error numbers are in the range -1 - -124: see <asm-i386/errno.h> */
 
diff -Nru a/include/asm-ia64/acpi.h b/include/asm-ia64/acpi.h
--- a/include/asm-ia64/acpi.h	2004-10-18 14:56:50 -07:00
+++ b/include/asm-ia64/acpi.h	2004-10-18 14:56:50 -07:00
@@ -89,13 +89,13 @@
 	((Acq) = ia64_acpi_release_global_lock((unsigned int *) GLptr))
 
 #define acpi_disabled 0	/* ACPI always enabled on IA64 */
+#define acpi_noirq 0	/* ACPI always enabled on IA64 */
 #define acpi_pci_disabled 0 /* ACPI PCI always enabled on IA64 */
 #define acpi_strict 1	/* no ACPI spec workarounds on IA64 */
 static inline void disable_acpi(void) { }
 
 const char *acpi_get_sysname (void);
 int acpi_request_vector (u32 int_type);
-int acpi_register_irq (u32 gsi, u32 polarity, u32 trigger);
 int acpi_gsi_to_irq (u32 gsi, unsigned int *irq);
 
 #ifdef CONFIG_ACPI_NUMA
@@ -104,6 +104,8 @@
 extern int __initdata pxm_to_nid_map[MAX_PXM_DOMAINS];
 extern int __initdata nid_to_pxm_map[MAX_NUMNODES];
 #endif
+
+extern u16 ia64_acpiid_to_sapicid[];
 
 #endif /*__KERNEL__*/
 
diff -Nru a/include/asm-ia64/bug.h b/include/asm-ia64/bug.h
--- a/include/asm-ia64/bug.h	2004-10-18 14:55:54 -07:00
+++ b/include/asm-ia64/bug.h	2004-10-18 14:55:54 -07:00
@@ -8,15 +8,8 @@
 #endif
 #define BUG() do { printk("kernel BUG at %s:%d!\n", __FILE__, __LINE__); ia64_abort(); } while (0)
 
-#define BUG_ON(condition) do { if (unlikely((condition)!=0)) BUG(); } while(0)
-
-#define PAGE_BUG(page) do { BUG(); } while (0)
-
-#define WARN_ON(condition) do { \
-	if (unlikely((condition)!=0)) { \
-		printk("Badness in %s at %s:%d\n", __FUNCTION__, __FILE__, __LINE__); \
-		dump_stack(); \
-	} \
-} while (0)
+/* should this BUG should be made generic? */
+#define HAVE_ARCH_BUG
+#include <asm-generic/bug.h>
 
 #endif
diff -Nru a/include/asm-ia64/compat.h b/include/asm-ia64/compat.h
--- a/include/asm-ia64/compat.h	2004-10-18 14:57:04 -07:00
+++ b/include/asm-ia64/compat.h	2004-10-18 14:57:04 -07:00
@@ -182,17 +182,17 @@
  */
 typedef	u32		compat_uptr_t;
 
-static inline void *
+static inline void __user *
 compat_ptr (compat_uptr_t uptr)
 {
-	return (void *) (unsigned long) uptr;
+	return (void __user *) (unsigned long) uptr;
 }
 
-static __inline__ void *
+static __inline__ void __user *
 compat_alloc_user_space (long len)
 {
 	struct pt_regs *regs = ia64_task_regs(current);
-	return (void *) (((regs->r12 & 0xffffffff) & -16) - len);
+	return (void __user *) (((regs->r12 & 0xffffffff) & -16) - len);
 }
 
 #endif /* _ASM_IA64_COMPAT_H */
diff -Nru a/include/asm-ia64/dma-mapping.h b/include/asm-ia64/dma-mapping.h
--- a/include/asm-ia64/dma-mapping.h	2004-10-18 14:56:49 -07:00
+++ b/include/asm-ia64/dma-mapping.h	2004-10-18 14:56:49 -07:00
@@ -5,7 +5,7 @@
  * Copyright (C) 2003-2004 Hewlett-Packard Co
  *	David Mosberger-Tang <davidm@hpl.hp.com>
  */
-
+#include <linux/config.h>
 #include <asm/machvec.h>
 
 #define dma_alloc_coherent	platform_dma_alloc_coherent
diff -Nru a/include/asm-ia64/elf.h b/include/asm-ia64/elf.h
--- a/include/asm-ia64/elf.h	2004-10-18 14:56:48 -07:00
+++ b/include/asm-ia64/elf.h	2004-10-18 14:56:48 -07:00
@@ -4,7 +4,7 @@
 /*
  * ELF-specific definitions.
  *
- * Copyright (C) 1998-1999, 2002-2003 Hewlett-Packard Co
+ * Copyright (C) 1998-1999, 2002-2004 Hewlett-Packard Co
  *	David Mosberger-Tang <davidm@hpl.hp.com>
  */
 
@@ -40,7 +40,7 @@
  * the way of the program that it will "exec", and that there is
  * sufficient room for the brk.
  */
-#define ELF_ET_DYN_BASE		(TASK_UNMAPPED_BASE + 0x800000000)
+#define ELF_ET_DYN_BASE		(TASK_UNMAPPED_BASE + 0x800000000UL)
 
 #define PT_IA_64_UNWIND		0x70000001
 
@@ -175,7 +175,7 @@
 /* This macro yields a string that ld.so will use to load
    implementation specific libraries for optimization.  Not terribly
    relevant until we have real hardware to play with... */
-#define ELF_PLATFORM	0
+#define ELF_PLATFORM	NULL
 
 /*
  * Architecture-neutral AT_ values are in the range 0-17.  Leave some room for more of
diff -Nru a/include/asm-ia64/gcc_intrin.h b/include/asm-ia64/gcc_intrin.h
--- a/include/asm-ia64/gcc_intrin.h	2004-10-18 14:56:29 -07:00
+++ b/include/asm-ia64/gcc_intrin.h	2004-10-18 14:56:29 -07:00
@@ -259,35 +259,35 @@
 	ia64_intri_res;								\
 })
 
-#define ia64_xchg1(ptr,x)						\
-({									\
-	__u64 ia64_intri_res;						\
-	asm __volatile ("xchg1 %0=[%1],%2" : "=r" (ia64_intri_res)	\
-			    : "r" (ptr), "r" (x) : "memory");		\
-	ia64_intri_res;							\
+#define ia64_xchg1(ptr,x)							\
+({										\
+	__u64 ia64_intri_res;							\
+	asm volatile ("xchg1 %0=[%1],%2"					\
+		      : "=r" (ia64_intri_res) : "r" (ptr), "r" (x) : "memory");	\
+	ia64_intri_res;								\
 })
 
 #define ia64_xchg2(ptr,x)						\
 ({									\
 	__u64 ia64_intri_res;						\
-	asm __volatile ("xchg2 %0=[%1],%2" : "=r" (ia64_intri_res)	\
-			    : "r" (ptr), "r" (x) : "memory");		\
+	asm volatile ("xchg2 %0=[%1],%2" : "=r" (ia64_intri_res)	\
+		      : "r" (ptr), "r" (x) : "memory");			\
 	ia64_intri_res;							\
 })
 
 #define ia64_xchg4(ptr,x)						\
 ({									\
 	__u64 ia64_intri_res;						\
-	asm __volatile ("xchg4 %0=[%1],%2" : "=r" (ia64_intri_res)	\
-			    : "r" (ptr), "r" (x) : "memory");		\
+	asm volatile ("xchg4 %0=[%1],%2" : "=r" (ia64_intri_res)	\
+		      : "r" (ptr), "r" (x) : "memory");			\
 	ia64_intri_res;							\
 })
 
 #define ia64_xchg8(ptr,x)						\
 ({									\
 	__u64 ia64_intri_res;						\
-	asm __volatile ("xchg8 %0=[%1],%2" : "=r" (ia64_intri_res)	\
-			    : "r" (ptr), "r" (x) : "memory");		\
+	asm volatile ("xchg8 %0=[%1],%2" : "=r" (ia64_intri_res)	\
+		      : "r" (ptr), "r" (x) : "memory");			\
 	ia64_intri_res;							\
 })
 
diff -Nru a/include/asm-ia64/hardirq.h b/include/asm-ia64/hardirq.h
--- a/include/asm-ia64/hardirq.h	2004-10-18 14:56:27 -07:00
+++ b/include/asm-ia64/hardirq.h	2004-10-18 14:56:27 -07:00
@@ -52,20 +52,6 @@
 #define SOFTIRQ_SHIFT	(PREEMPT_SHIFT + PREEMPT_BITS)
 #define HARDIRQ_SHIFT	(SOFTIRQ_SHIFT + SOFTIRQ_BITS)
 
-#define __MASK(x)	((1UL << (x))-1)
-
-#define PREEMPT_MASK	(__MASK(PREEMPT_BITS) << PREEMPT_SHIFT)
-#define HARDIRQ_MASK	(__MASK(HARDIRQ_BITS) << HARDIRQ_SHIFT)
-#define SOFTIRQ_MASK	(__MASK(SOFTIRQ_BITS) << SOFTIRQ_SHIFT)
-
-#define hardirq_count()	(preempt_count() & HARDIRQ_MASK)
-#define softirq_count()	(preempt_count() & SOFTIRQ_MASK)
-#define irq_count()	(preempt_count() & (HARDIRQ_MASK | SOFTIRQ_MASK))
-
-#define PREEMPT_OFFSET	(1UL << PREEMPT_SHIFT)
-#define SOFTIRQ_OFFSET	(1UL << SOFTIRQ_SHIFT)
-#define HARDIRQ_OFFSET	(1UL << HARDIRQ_SHIFT)
-
 /*
  * The hardirq mask has to be large enough to have space for potentially all IRQ sources
  * in the system nesting on a single CPU:
@@ -74,31 +60,6 @@
 # error HARDIRQ_BITS is too low!
 #endif
 
-/*
- * Are we doing bottom half or hardware interrupt processing?
- * Are we in a softirq context?
- * Interrupt context?
- */
-#define in_irq()		(hardirq_count())
-#define in_softirq()		(softirq_count())
-#define in_interrupt()		(irq_count())
-
-#define hardirq_trylock()	(!in_interrupt())
-#define hardirq_endlock()	do { } while (0)
-
-#ifdef CONFIG_PREEMPT
-# include <linux/smp_lock.h>
-# define in_atomic()		((preempt_count() & ~PREEMPT_ACTIVE) != kernel_locked())
-# define IRQ_EXIT_OFFSET (HARDIRQ_OFFSET-1)
-#else
-# define in_atomic()		(preempt_count() != 0)
-# define IRQ_EXIT_OFFSET HARDIRQ_OFFSET
-#endif
-
-#ifdef CONFIG_SMP
-  extern void synchronize_irq (unsigned int irq);
-#else
-# define synchronize_irq(irq)	barrier()
-#endif /* CONFIG_SMP */
+extern void __iomem *ipi_base_addr;
 
 #endif /* _ASM_IA64_HARDIRQ_H */
diff -Nru a/include/asm-ia64/hw_irq.h b/include/asm-ia64/hw_irq.h
--- a/include/asm-ia64/hw_irq.h	2004-10-18 14:56:29 -07:00
+++ b/include/asm-ia64/hw_irq.h	2004-10-18 14:56:29 -07:00
@@ -78,8 +78,6 @@
 extern __u8 isa_irq_to_vector_map[16];
 #define isa_irq_to_vector(x)	isa_irq_to_vector_map[(x)]
 
-extern unsigned long ipi_base_addr;
-
 extern struct hw_interrupt_type irq_type_ia64_lsapic;	/* CPU-internal interrupt controller */
 
 extern int assign_irq_vector (int irq);	/* allocate a free vector */
diff -Nru a/include/asm-ia64/ia32.h b/include/asm-ia64/ia32.h
--- a/include/asm-ia64/ia32.h	2004-10-18 14:57:04 -07:00
+++ b/include/asm-ia64/ia32.h	2004-10-18 14:57:04 -07:00
@@ -6,7 +6,7 @@
 #include <asm/ptrace.h>
 #include <asm/signal.h>
 
-#define IA32_NR_syscalls		283	/* length of syscall table */
+#define IA32_NR_syscalls		285	/* length of syscall table */
 #define IA32_PAGE_SHIFT			12	/* 4KB pages */
 
 #ifndef __ASSEMBLY__
@@ -14,7 +14,7 @@
 # ifdef CONFIG_IA32_SUPPORT
 
 extern void ia32_cpu_init (void);
-extern void ia32_boot_gdt_init (void);
+extern void ia32_mem_init (void);
 extern void ia32_gdt_init (void);
 extern int ia32_exception (struct pt_regs *regs, unsigned long isr);
 extern int ia32_intercept (struct pt_regs *regs, unsigned long isr);
diff -Nru a/include/asm-ia64/io.h b/include/asm-ia64/io.h
--- a/include/asm-ia64/io.h	2004-10-18 14:55:54 -07:00
+++ b/include/asm-ia64/io.h	2004-10-18 14:55:54 -07:00
@@ -23,7 +23,7 @@
 #define __SLOW_DOWN_IO	do { } while (0)
 #define SLOW_DOWN_IO	do { } while (0)
 
-#define __IA64_UNCACHED_OFFSET	0xc000000000000000	/* region 6 */
+#define __IA64_UNCACHED_OFFSET	0xc000000000000000UL	/* region 6 */
 
 /*
  * The legacy I/O space defined by the ia64 architecture supports only 65536 ports, but
@@ -248,7 +248,7 @@
 }
 
 static inline void
-__outsl (unsigned long port, void *src, unsigned long count)
+__outsl (unsigned long port, const void *src, unsigned long count)
 {
 	const unsigned int *sp = src;
 
@@ -290,51 +290,51 @@
  * hopefully it'll stay that way).
  */
 static inline unsigned char
-___ia64_readb (void *addr)
+___ia64_readb (const volatile void __iomem *addr)
 {
-	return *(volatile unsigned char *)addr;
+	return *(volatile unsigned char __force *)addr;
 }
 
 static inline unsigned short
-___ia64_readw (void *addr)
+___ia64_readw (const volatile void __iomem *addr)
 {
-	return *(volatile unsigned short *)addr;
+	return *(volatile unsigned short __force *)addr;
 }
 
 static inline unsigned int
-___ia64_readl (void *addr)
+___ia64_readl (const volatile void __iomem *addr)
 {
-	return *(volatile unsigned int *) addr;
+	return *(volatile unsigned int __force *) addr;
 }
 
 static inline unsigned long
-___ia64_readq (void *addr)
+___ia64_readq (const volatile void __iomem *addr)
 {
-	return *(volatile unsigned long *) addr;
+	return *(volatile unsigned long __force *) addr;
 }
 
 static inline void
-__writeb (unsigned char val, void *addr)
+__writeb (unsigned char val, volatile void __iomem *addr)
 {
-	*(volatile unsigned char *) addr = val;
+	*(volatile unsigned char __force *) addr = val;
 }
 
 static inline void
-__writew (unsigned short val, void *addr)
+__writew (unsigned short val, volatile void __iomem *addr)
 {
-	*(volatile unsigned short *) addr = val;
+	*(volatile unsigned short __force *) addr = val;
 }
 
 static inline void
-__writel (unsigned int val, void *addr)
+__writel (unsigned int val, volatile void __iomem *addr)
 {
-	*(volatile unsigned int *) addr = val;
+	*(volatile unsigned int __force *) addr = val;
 }
 
 static inline void
-__writeq (unsigned long val, void *addr)
+__writeq (unsigned long val, volatile void __iomem *addr)
 {
-	*(volatile unsigned long *) addr = val;
+	*(volatile unsigned long __force *) addr = val;
 }
 
 #define __readb		platform_readb
@@ -346,14 +346,14 @@
 #define __readl_relaxed	platform_readl_relaxed
 #define __readq_relaxed	platform_readq_relaxed
 
-#define readb(a)	__readb((void *)(a))
-#define readw(a)	__readw((void *)(a))
-#define readl(a)	__readl((void *)(a))
-#define readq(a)	__readq((void *)(a))
-#define readb_relaxed(a)	__readb_relaxed((void *)(a))
-#define readw_relaxed(a)	__readw_relaxed((void *)(a))
-#define readl_relaxed(a)	__readl_relaxed((void *)(a))
-#define readq_relaxed(a)	__readq_relaxed((void *)(a))
+#define readb(a)	__readb((a))
+#define readw(a)	__readw((a))
+#define readl(a)	__readl((a))
+#define readq(a)	__readq((a))
+#define readb_relaxed(a)	__readb_relaxed((a))
+#define readw_relaxed(a)	__readw_relaxed((a))
+#define readl_relaxed(a)	__readl_relaxed((a))
+#define readq_relaxed(a)	__readq_relaxed((a))
 #define __raw_readb	readb
 #define __raw_readw	readw
 #define __raw_readl	readl
@@ -362,10 +362,10 @@
 #define __raw_readw_relaxed	readw_relaxed
 #define __raw_readl_relaxed	readl_relaxed
 #define __raw_readq_relaxed	readq_relaxed
-#define writeb(v,a)	__writeb((v), (void *) (a))
-#define writew(v,a)	__writew((v), (void *) (a))
-#define writel(v,a)	__writel((v), (void *) (a))
-#define writeq(v,a)	__writeq((v), (void *) (a))
+#define writeb(v,a)	__writeb((v), (a))
+#define writew(v,a)	__writew((v), (a))
+#define writel(v,a)	__writel((v), (a))
+#define writeq(v,a)	__writeq((v), (a))
 #define __raw_writeb	writeb
 #define __raw_writew	writew
 #define __raw_writel	writel
@@ -397,14 +397,14 @@
  *
  * On ia-64, we access the physical I/O memory space through the uncached kernel region.
  */
-static inline void *
+static inline void __iomem *
 ioremap (unsigned long offset, unsigned long size)
 {
-	return (void *) (__IA64_UNCACHED_OFFSET | (offset));
+	return (void __iomem *) (__IA64_UNCACHED_OFFSET | (offset));
 }
 
 static inline void
-iounmap (void *addr)
+iounmap (volatile void __iomem *addr)
 {
 }
 
@@ -415,17 +415,14 @@
 /*
  * String version of IO memory access ops:
  */
-extern void __ia64_memcpy_fromio (void *, unsigned long, long);
-extern void __ia64_memcpy_toio (unsigned long, void *, long);
-extern void __ia64_memset_c_io (unsigned long, unsigned long, long);
-
-#define memcpy_fromio(to,from,len) \
-  __ia64_memcpy_fromio((to),(unsigned long)(from),(len))
-#define memcpy_toio(to,from,len) \
-  __ia64_memcpy_toio((unsigned long)(to),(from),(len))
-#define memset_io(addr,c,len) \
-  __ia64_memset_c_io((unsigned long)(addr),0x0101010101010101UL*(u8)(c),(len))
-
+extern void __ia64_memcpy_fromio (void *, volatile void __iomem *, long);
+extern void __ia64_memcpy_toio (volatile void __iomem *, void *, long);
+extern void __ia64_memset_c_io (volatile void __iomem *, unsigned long, long);
+
+#define memcpy_fromio(to,from,len)	__ia64_memcpy_fromio((to), (from),(len))
+#define memcpy_toio(to,from,len)	__ia64_memcpy_toio((to),(from),(len))
+#define memset_io(addr,c,len)		__ia64_memset_c_io((addr), 0x0101010101010101UL*(u8)(c), \
+							   (len))
 
 #define dma_cache_inv(_start,_size)             do { } while (0)
 #define dma_cache_wback(_start,_size)           do { } while (0)
diff -Nru a/include/asm-ia64/iosapic.h b/include/asm-ia64/iosapic.h
--- a/include/asm-ia64/iosapic.h	2004-10-18 14:56:32 -07:00
+++ b/include/asm-ia64/iosapic.h	2004-10-18 14:56:32 -07:00
@@ -53,19 +53,19 @@
 
 #define NR_IOSAPICS			256
 
-static inline unsigned int iosapic_read(char *iosapic, unsigned int reg)
+static inline unsigned int iosapic_read(char __iomem *iosapic, unsigned int reg)
 {
 	writel(reg, iosapic + IOSAPIC_REG_SELECT);
 	return readl(iosapic + IOSAPIC_WINDOW);
 }
 
-static inline void iosapic_write(char *iosapic, unsigned int reg, u32 val)
+static inline void iosapic_write(char __iomem *iosapic, unsigned int reg, u32 val)
 {
 	writel(reg, iosapic + IOSAPIC_REG_SELECT);
 	writel(val, iosapic + IOSAPIC_WINDOW);
 }
 
-static inline void iosapic_eoi(char *iosapic, u32 vector)
+static inline void iosapic_eoi(char __iomem *iosapic, u32 vector)
 {
 	writel(vector, iosapic + IOSAPIC_EOI);
 }
@@ -87,9 +87,12 @@
 					   u16 eid, u16 id,
 					   unsigned long polarity,
 					   unsigned long trigger);
-extern unsigned int iosapic_version (char *addr);
+extern unsigned int iosapic_version (char __iomem *addr);
 
 extern void iosapic_pci_fixup (int);
+#ifdef CONFIG_NUMA
+extern void __init map_iosapic_to_node (unsigned int, int);
+#endif
 #else
 #define iosapic_system_init(pcat_compat)			do { } while (0)
 #define iosapic_init(address,gsi_base)				do { } while (0)
diff -Nru a/include/asm-ia64/mca.h b/include/asm-ia64/mca.h
--- a/include/asm-ia64/mca.h	2004-10-18 14:56:17 -07:00
+++ b/include/asm-ia64/mca.h	2004-10-18 14:56:17 -07:00
@@ -22,6 +22,11 @@
 
 #define IA64_MCA_RENDEZ_TIMEOUT		(20 * 1000)	/* value in milliseconds - 20 seconds */
 
+typedef struct ia64_fptr {
+	unsigned long fp;
+	unsigned long gp;
+} ia64_fptr_t;
+
 typedef union cmcv_reg_u {
 	u64	cmcv_regval;
 	struct	{
@@ -114,6 +119,8 @@
 extern void ia64_monarch_init_handler(void);
 extern void ia64_slave_init_handler(void);
 extern void ia64_mca_cmc_vector_setup(void);
+extern int  ia64_reg_MCA_extension(void*);
+extern void ia64_unreg_MCA_extension(void);
 
 #endif /* !__ASSEMBLY__ */
 #endif /* _ASM_IA64_MCA_H */
diff -Nru a/include/asm-ia64/mca_asm.h b/include/asm-ia64/mca_asm.h
--- a/include/asm-ia64/mca_asm.h	2004-10-18 14:57:03 -07:00
+++ b/include/asm-ia64/mca_asm.h	2004-10-18 14:57:03 -07:00
@@ -162,9 +162,6 @@
 	;;							\
 	srlz.d;							\
 	mov	r13 = ar.k6;					\
-	;;							\
-	DATA_PA_TO_VA(r13,temp1);				\
-	;;							\
 	mov	temp2 = ar.bspstore;				\
 	;;							\
 	DATA_PA_TO_VA(temp2,temp1);				\
diff -Nru a/include/asm-ia64/mmu_context.h b/include/asm-ia64/mmu_context.h
--- a/include/asm-ia64/mmu_context.h	2004-10-18 14:55:55 -07:00
+++ b/include/asm-ia64/mmu_context.h	2004-10-18 14:55:55 -07:00
@@ -28,36 +28,6 @@
 
 #include <asm/processor.h>
 
-#define MMU_CONTEXT_DEBUG	0
-
-#if MMU_CONTEXT_DEBUG
-
-#include <ia64intrin.h>
-
-extern struct mmu_trace_entry {
-	char op;
-	u8 cpu;
-	u32 context;
-	void *mm;
-} mmu_tbuf[1024];
-
-extern volatile int mmu_tbuf_index;
-
-# define MMU_TRACE(_op,_cpu,_mm,_ctx)							\
-do {											\
-	int i = __sync_fetch_and_add(&mmu_tbuf_index, 1) % ARRAY_SIZE(mmu_tbuf);	\
-	struct mmu_trace_entry e;							\
-	e.op = (_op);									\
-	e.cpu = (_cpu);									\
-	e.mm = (_mm);									\
-	e.context = (_ctx);								\
-	mmu_tbuf[i] = e;								\
-} while (0)
-
-#else
-# define MMU_TRACE(op,cpu,mm,ctx)	do { ; } while (0)
-#endif
-
 struct ia64_ctx {
 	spinlock_t lock;
 	unsigned int next;	/* next context number to use */
@@ -123,7 +93,6 @@
 static inline int
 init_new_context (struct task_struct *p, struct mm_struct *mm)
 {
-	MMU_TRACE('N', smp_processor_id(), mm, 0);
 	mm->context = 0;
 	return 0;
 }
@@ -132,7 +101,6 @@
 destroy_context (struct mm_struct *mm)
 {
 	/* Nothing to do.  */
-	MMU_TRACE('D', smp_processor_id(), mm, mm->context);
 }
 
 static inline void
@@ -142,7 +110,7 @@
 	unsigned long rid_incr = 0;
 	unsigned long rr0, rr1, rr2, rr3, rr4, old_rr4;
 
-	old_rr4 = ia64_get_rr(0x8000000000000000);
+	old_rr4 = ia64_get_rr(0x8000000000000000UL);
 	rid = context << 3;	/* make space for encoding the region number */
 	rid_incr = 1 << 8;
 
@@ -156,11 +124,11 @@
 	rr4 = (rr4 & (~(0xfcUL))) | (old_rr4 & 0xfc);
 #endif
 
-	ia64_set_rr(0x0000000000000000, rr0);
-	ia64_set_rr(0x2000000000000000, rr1);
-	ia64_set_rr(0x4000000000000000, rr2);
-	ia64_set_rr(0x6000000000000000, rr3);
-	ia64_set_rr(0x8000000000000000, rr4);
+	ia64_set_rr(0x0000000000000000UL, rr0);
+	ia64_set_rr(0x2000000000000000UL, rr1);
+	ia64_set_rr(0x4000000000000000UL, rr2);
+	ia64_set_rr(0x6000000000000000UL, rr3);
+	ia64_set_rr(0x8000000000000000UL, rr4);
 	ia64_srlz_i();			/* srlz.i implies srlz.d */
 }
 
@@ -171,19 +139,14 @@
 
 	do {
 		context = get_mmu_context(mm);
-		MMU_TRACE('A', smp_processor_id(), mm, context);
 		if (!cpu_isset(smp_processor_id(), mm->cpu_vm_mask))
 			cpu_set(smp_processor_id(), mm->cpu_vm_mask);
 		reload_context(context);
-		MMU_TRACE('a', smp_processor_id(), mm, context);
 		/* in the unlikely event of a TLB-flush by another thread, redo the load: */
 	} while (unlikely(context != mm->context));
 }
 
-#define deactivate_mm(tsk,mm)					\
-do {								\
-	MMU_TRACE('d', smp_processor_id(), mm, mm->context);	\
-} while (0)
+#define deactivate_mm(tsk,mm)	do { } while (0)
 
 /*
  * Switch from address space PREV to address space NEXT.
diff -Nru a/include/asm-ia64/mmzone.h b/include/asm-ia64/mmzone.h
--- a/include/asm-ia64/mmzone.h	2004-10-18 14:57:18 -07:00
+++ b/include/asm-ia64/mmzone.h	2004-10-18 14:57:18 -07:00
@@ -27,12 +27,6 @@
 # define NR_NODE_MEMBLKS	(NR_NODES * 4)
 #endif
 
-extern unsigned long max_low_pfn;
-
-#define pfn_valid(pfn)		(((pfn) < max_low_pfn) && ia64_pfn_valid(pfn))
-#define page_to_pfn(page)	((unsigned long) (page - vmem_map))
-#define pfn_to_page(pfn)	(vmem_map + (pfn))
-
 #else /* CONFIG_DISCONTIGMEM */
 # define NR_NODE_MEMBLKS	4
 #endif /* CONFIG_DISCONTIGMEM */
diff -Nru a/include/asm-ia64/numa.h b/include/asm-ia64/numa.h
--- a/include/asm-ia64/numa.h	2004-10-18 14:56:28 -07:00
+++ b/include/asm-ia64/numa.h	2004-10-18 14:56:28 -07:00
@@ -59,7 +59,7 @@
  */
 
 extern u8 numa_slit[MAX_NUMNODES * MAX_NUMNODES];
-#define node_distance(from,to) (numa_slit[from * numnodes + to])
+#define node_distance(from,to) (numa_slit[(from) * numnodes + (to)])
 
 extern int paddr_to_nid(unsigned long paddr);
 
diff -Nru a/include/asm-ia64/page.h b/include/asm-ia64/page.h
--- a/include/asm-ia64/page.h	2004-10-18 14:55:55 -07:00
+++ b/include/asm-ia64/page.h	2004-10-18 14:55:55 -07:00
@@ -84,10 +84,16 @@
 #endif
 
 #ifndef CONFIG_DISCONTIGMEM
-#define pfn_valid(pfn)		(((pfn) < max_mapnr) && ia64_pfn_valid(pfn))
-#define page_to_pfn(page)	((unsigned long) (page - mem_map))
-#define pfn_to_page(pfn)	(mem_map + (pfn))
-#endif /* CONFIG_DISCONTIGMEM */
+# define pfn_valid(pfn)		(((pfn) < max_mapnr) && ia64_pfn_valid(pfn))
+# define page_to_pfn(page)	((unsigned long) (page - mem_map))
+# define pfn_to_page(pfn)	(mem_map + (pfn))
+#else
+extern struct page *vmem_map;
+extern unsigned long max_low_pfn;
+# define pfn_valid(pfn)		(((pfn) < max_low_pfn) && ia64_pfn_valid(pfn))
+# define page_to_pfn(page)	((unsigned long) (page - vmem_map))
+# define pfn_to_page(pfn)	(vmem_map + (pfn))
+#endif
 
 #define page_to_phys(page)	(page_to_pfn(page) << PAGE_SHIFT)
 #define virt_to_page(kaddr)	pfn_to_page(__pa(kaddr) >> PAGE_SHIFT)
@@ -117,7 +123,7 @@
 #define REGION_KERNEL		7
 
 #ifdef CONFIG_HUGETLB_PAGE
-# define htlbpage_to_page(x)	((REGION_NUMBER(x) << 61)				\
+# define htlbpage_to_page(x)	(((unsigned long) REGION_NUMBER(x) << 61)			\
 				 | (REGION_OFFSET(x) >> (HPAGE_SHIFT-PAGE_SHIFT)))
 # define HUGETLB_PAGE_ORDER	(HPAGE_SHIFT - PAGE_SHIFT)
 # define is_hugepage_only_range(addr, len)		\
@@ -180,7 +186,7 @@
 # define __pgprot(x)	(x)
 #endif /* !STRICT_MM_TYPECHECKS */
 
-#define PAGE_OFFSET			0xe000000000000000
+#define PAGE_OFFSET			__IA64_UL_CONST(0xe000000000000000)
 
 #define VM_DATA_DEFAULT_FLAGS		(VM_READ | VM_WRITE |					\
 					 VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC |		\
diff -Nru a/include/asm-ia64/pgtable.h b/include/asm-ia64/pgtable.h
--- a/include/asm-ia64/pgtable.h	2004-10-18 14:56:28 -07:00
+++ b/include/asm-ia64/pgtable.h	2004-10-18 14:56:28 -07:00
@@ -206,18 +206,18 @@
 #define RGN_SIZE	(1UL << 61)
 #define RGN_KERNEL	7
 
-#define VMALLOC_START		0xa000000200000000
+#define VMALLOC_START		0xa000000200000000UL
 #ifdef CONFIG_VIRTUAL_MEM_MAP
-# define VMALLOC_END_INIT	(0xa000000000000000 + (1UL << (4*PAGE_SHIFT - 9)))
+# define VMALLOC_END_INIT	(0xa000000000000000UL + (1UL << (4*PAGE_SHIFT - 9)))
 # define VMALLOC_END		vmalloc_end
   extern unsigned long vmalloc_end;
 #else
-# define VMALLOC_END		(0xa000000000000000 + (1UL << (4*PAGE_SHIFT - 9)))
+# define VMALLOC_END		(0xa000000000000000UL + (1UL << (4*PAGE_SHIFT - 9)))
 #endif
 
 /* fs/proc/kcore.c */
-#define	kc_vaddr_to_offset(v) ((v) - 0xa000000000000000)
-#define	kc_offset_to_vaddr(o) ((o) + 0xa000000000000000)
+#define	kc_vaddr_to_offset(v) ((v) - 0xa000000000000000UL)
+#define	kc_offset_to_vaddr(o) ((o) + 0xa000000000000000UL)
 
 /*
  * Conversion functions: convert page frame number (pfn) and a protection value to a page
@@ -520,7 +520,7 @@
 #  ifdef CONFIG_VIRTUAL_MEM_MAP
   /* arch mem_map init routine is needed due to holes in a virtual mem_map */
 #   define __HAVE_ARCH_MEMMAP_INIT
-    extern void memmap_init (struct page *start, unsigned long size, int nid, unsigned long zone,
+    extern void memmap_init (unsigned long size, int nid, unsigned long zone,
 			     unsigned long start_pfn);
 #  endif /* CONFIG_VIRTUAL_MEM_MAP */
 # endif /* !__ASSEMBLY__ */
diff -Nru a/include/asm-ia64/processor.h b/include/asm-ia64/processor.h
--- a/include/asm-ia64/processor.h	2004-10-18 14:56:28 -07:00
+++ b/include/asm-ia64/processor.h	2004-10-18 14:56:28 -07:00
@@ -28,8 +28,8 @@
 #define IA64_NUM_PMC_REGS	32
 #define IA64_NUM_PMD_REGS	32
 
-#define DEFAULT_MAP_BASE	0x2000000000000000
-#define DEFAULT_TASK_SIZE	0xa000000000000000
+#define DEFAULT_MAP_BASE	__IA64_UL_CONST(0x2000000000000000)
+#define DEFAULT_TASK_SIZE	__IA64_UL_CONST(0xa000000000000000)
 
 /*
  * TASK_SIZE really is a mis-named.  It really is the maximum user
@@ -200,7 +200,7 @@
 #define GET_UNALIGN_CTL(task,addr)								\
 ({												\
 	put_user(((task)->thread.flags & IA64_THREAD_UAC_MASK) >> IA64_THREAD_UAC_SHIFT,	\
-		 (int *) (addr));								\
+		 (int __user *) (addr));							\
 })
 
 #define SET_FPEMU_CTL(task,value)								\
@@ -212,7 +212,7 @@
 #define GET_FPEMU_CTL(task,addr)								\
 ({												\
 	put_user(((task)->thread.flags & IA64_THREAD_FPEMU_MASK) >> IA64_THREAD_FPEMU_SHIFT,	\
-		 (int *) (addr));								\
+		 (int __user *) (addr));							\
 })
 
 #ifdef CONFIG_IA32_SUPPORT
@@ -262,7 +262,7 @@
 				.fdr =		0,			\
 				.old_k1 =	0,			\
 				.old_iob =	0,			\
-				.ppl =		0,
+				.ppl =		NULL,
 #else
 # define INIT_THREAD_IA32
 #endif /* CONFIG_IA32_SUPPORT */
@@ -333,6 +333,26 @@
 
 /* Prepare to copy thread state - unlazy all lazy status */
 #define prepare_to_copy(tsk)	do { } while (0)
+
+#ifdef CONFIG_NUMA
+#define SD_NODE_INIT (struct sched_domain) {		\
+	.span			= CPU_MASK_NONE,	\
+	.parent			= NULL,			\
+	.groups			= NULL,			\
+	.min_interval		= 80,			\
+	.max_interval		= 320,			\
+	.busy_factor		= 320,			\
+	.imbalance_pct		= 125,			\
+	.cache_hot_time		= (10*1000000),		\
+	.cache_nice_tries	= 1,			\
+	.per_cpu_gain		= 100,			\
+	.flags			= SD_BALANCE_EXEC	\
+				| SD_WAKE_BALANCE,	\
+	.last_balance		= jiffies,		\
+	.balance_interval	= 10,			\
+	.nr_balance_failed	= 0,			\
+}
+#endif
 
 /*
  * This is the mechanism for creating a new kernel thread.
diff -Nru a/include/asm-ia64/ptrace.h b/include/asm-ia64/ptrace.h
--- a/include/asm-ia64/ptrace.h	2004-10-18 14:56:33 -07:00
+++ b/include/asm-ia64/ptrace.h	2004-10-18 14:56:33 -07:00
@@ -229,6 +229,15 @@
  * the canonical representation by adding to instruction pointer.
  */
 # define instruction_pointer(regs) ((regs)->cr_iip + ia64_psr(regs)->ri)
+/* Conserve space in histogram by encoding slot bits in address
+ * bits 2 and 3 rather than bits 0 and 1.
+ */
+#define profile_pc(regs)						\
+({									\
+	unsigned long __ip = instruction_pointer(regs);			\
+	(__ip & ~3UL) + ((__ip & 3UL) << 2);				\
+})
+
   /* given a pointer to a task_struct, return the user's pt_regs */
 # define ia64_task_regs(t)		(((struct pt_regs *) ((char *) (t) + IA64_STK_OFFSET)) - 1)
 # define ia64_psr(regs)			((struct ia64_psr *) &(regs)->cr_ipsr)
diff -Nru a/include/asm-ia64/resource.h b/include/asm-ia64/resource.h
--- a/include/asm-ia64/resource.h	2004-10-18 14:56:49 -07:00
+++ b/include/asm-ia64/resource.h	2004-10-18 14:56:49 -07:00
@@ -46,7 +46,7 @@
 	{ RLIM_INFINITY, RLIM_INFINITY },		\
 	{             0,             0 },		\
 	{      INR_OPEN,     INR_OPEN  },		\
-	{ RLIM_INFINITY, RLIM_INFINITY },		\
+	{   MLOCK_LIMIT,   MLOCK_LIMIT },		\
 	{ RLIM_INFINITY, RLIM_INFINITY },		\
 	{ RLIM_INFINITY, RLIM_INFINITY },		\
 	{ MAX_SIGPENDING, MAX_SIGPENDING },		\
diff -Nru a/include/asm-ia64/sal.h b/include/asm-ia64/sal.h
--- a/include/asm-ia64/sal.h	2004-10-18 14:57:04 -07:00
+++ b/include/asm-ia64/sal.h	2004-10-18 14:57:04 -07:00
@@ -364,7 +364,7 @@
 	u64 cr[128];
 	u64 ar[128];
 	u64 rr[8];
-	struct ia64_fpreg fr[128];
+	struct ia64_fpreg __attribute__ ((packed)) fr[128];
 } sal_processor_static_info_t;
 
 struct sal_cpuid_info {
@@ -818,6 +818,16 @@
 struct sal_ret_values {
 	long r8; long r9; long r10; long r11;
 };
+
+#define IA64_SAL_OEMFUNC_MIN		0x02000000
+#define IA64_SAL_OEMFUNC_MAX		0x03ffffff
+
+extern int ia64_sal_oemcall(struct ia64_sal_retval *, u64, u64, u64, u64, u64,
+			    u64, u64, u64);
+extern int ia64_sal_oemcall_nolock(struct ia64_sal_retval *, u64, u64, u64,
+				   u64, u64, u64, u64, u64);
+extern int ia64_sal_oemcall_reentrant(struct ia64_sal_retval *, u64, u64, u64,
+				      u64, u64, u64, u64, u64);
 
 #endif /* __ASSEMBLY__ */
 
diff -Nru a/include/asm-ia64/semaphore.h b/include/asm-ia64/semaphore.h
--- a/include/asm-ia64/semaphore.h	2004-10-18 14:56:29 -07:00
+++ b/include/asm-ia64/semaphore.h	2004-10-18 14:56:29 -07:00
@@ -15,21 +15,13 @@
 	atomic_t count;
 	int sleepers;
 	wait_queue_head_t wait;
-#if WAITQUEUE_DEBUG
-	long __magic;		/* initialized by __SEM_DEBUG_INIT() */
-#endif
 };
 
-#if WAITQUEUE_DEBUG
-# define __SEM_DEBUG_INIT(name)		, (long) &(name).__magic
-#else
-# define __SEM_DEBUG_INIT(name)
-#endif
-
-#define __SEMAPHORE_INITIALIZER(name,count)					\
-{										\
-	ATOMIC_INIT(count), 0, __WAIT_QUEUE_HEAD_INITIALIZER((name).wait)	\
-	__SEM_DEBUG_INIT(name)							\
+#define __SEMAPHORE_INITIALIZER(name, n)				\
+{									\
+	.count		= ATOMIC_INIT(n),				\
+	.sleepers	= 0,						\
+	.wait		= __WAIT_QUEUE_HEAD_INITIALIZER((name).wait)	\
 }
 
 #define __MUTEX_INITIALIZER(name)	__SEMAPHORE_INITIALIZER(name,1)
@@ -70,9 +62,6 @@
 static inline void
 down (struct semaphore *sem)
 {
-#if WAITQUEUE_DEBUG
-	CHECK_MAGIC(sem->__magic);
-#endif
 	might_sleep();
 	if (atomic_dec_return(&sem->count) < 0)
 		__down(sem);
@@ -87,9 +76,6 @@
 {
 	int ret = 0;
 
-#if WAITQUEUE_DEBUG
-	CHECK_MAGIC(sem->__magic);
-#endif
 	might_sleep();
 	if (atomic_dec_return(&sem->count) < 0)
 		ret = __down_interruptible(sem);
@@ -101,9 +87,6 @@
 {
 	int ret = 0;
 
-#if WAITQUEUE_DEBUG
-	CHECK_MAGIC(sem->__magic);
-#endif
 	if (atomic_dec_return(&sem->count) < 0)
 		ret = __down_trylock(sem);
 	return ret;
@@ -112,9 +95,6 @@
 static inline void
 up (struct semaphore * sem)
 {
-#if WAITQUEUE_DEBUG
-	CHECK_MAGIC(sem->__magic);
-#endif
 	if (atomic_inc_return(&sem->count) <= 0)
 		__up(sem);
 }
diff -Nru a/include/asm-ia64/siginfo.h b/include/asm-ia64/siginfo.h
--- a/include/asm-ia64/siginfo.h	2004-10-18 14:57:03 -07:00
+++ b/include/asm-ia64/siginfo.h	2004-10-18 14:57:03 -07:00
@@ -60,7 +60,7 @@
 
 		/* SIGILL, SIGFPE, SIGSEGV, SIGBUS */
 		struct {
-			void *_addr;		/* faulting insn/memory ref. */
+			void __user *_addr;	/* faulting insn/memory ref. */
 			int _imm;		/* immediate value for "break" */
 			unsigned int _flags;	/* see below */
 			unsigned long _isr;	/* isr */
diff -Nru a/include/asm-ia64/signal.h b/include/asm-ia64/signal.h
--- a/include/asm-ia64/signal.h	2004-10-18 14:55:55 -07:00
+++ b/include/asm-ia64/signal.h	2004-10-18 14:55:55 -07:00
@@ -144,10 +144,10 @@
 struct siginfo;
 
 /* Type of a signal handler.  */
-typedef void (*__sighandler_t)(int);
+typedef void __user (*__sighandler_t)(int);
 
 typedef struct sigaltstack {
-	void *ss_sp;
+	void __user *ss_sp;
 	int ss_flags;
 	size_t ss_size;
 } stack_t;
diff -Nru a/include/asm-ia64/smp.h b/include/asm-ia64/smp.h
--- a/include/asm-ia64/smp.h	2004-10-18 14:56:31 -07:00
+++ b/include/asm-ia64/smp.h	2004-10-18 14:56:31 -07:00
@@ -39,7 +39,7 @@
 extern char no_int_routing __devinitdata;
 
 extern cpumask_t cpu_online_map;
-extern unsigned long ipi_base_addr;
+extern void __iomem *ipi_base_addr;
 extern unsigned char smp_int_redirect;
 
 extern volatile int ia64_cpu_to_sapicid[];
@@ -73,21 +73,21 @@
 min_xtp (void)
 {
 	if (smp_int_redirect & SMP_IRQ_REDIRECTION)
-		writeb(0x00, ipi_base_addr | XTP_OFFSET); /* XTP to min */
+		writeb(0x00, ipi_base_addr + XTP_OFFSET); /* XTP to min */
 }
 
 static inline void
 normal_xtp (void)
 {
 	if (smp_int_redirect & SMP_IRQ_REDIRECTION)
-		writeb(0x08, ipi_base_addr | XTP_OFFSET); /* XTP normal */
+		writeb(0x08, ipi_base_addr + XTP_OFFSET); /* XTP normal */
 }
 
 static inline void
 max_xtp (void)
 {
 	if (smp_int_redirect & SMP_IRQ_REDIRECTION)
-		writeb(0x0f, ipi_base_addr | XTP_OFFSET); /* Set XTP to max */
+		writeb(0x0f, ipi_base_addr + XTP_OFFSET); /* Set XTP to max */
 }
 
 static inline unsigned int
diff -Nru a/include/asm-ia64/sn/sn2/shubio.h b/include/asm-ia64/sn/sn2/shubio.h
--- a/include/asm-ia64/sn/sn2/shubio.h	2004-10-18 14:56:29 -07:00
+++ b/include/asm-ia64/sn/sn2/shubio.h	2004-10-18 14:56:29 -07:00
@@ -3384,7 +3384,7 @@
 
 #define IO_PERF_SETS	32
 
-#if __KERNEL__
+#ifdef __KERNEL__
 #include <asm/sn/dmamap.h>
 #include <asm/sn/driver.h>
 #include <asm/sn/xtalk/xtalk.h>
diff -Nru a/include/asm-ia64/sn/sn2/sn_hwperf.h b/include/asm-ia64/sn/sn2/sn_hwperf.h
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/include/asm-ia64/sn/sn2/sn_hwperf.h	2004-10-18 14:57:24 -07:00
@@ -0,0 +1,218 @@
+/*
+ * 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) 2004 Silicon Graphics, Inc. All rights reserved.
+ *
+ * Data types used by the SN_SAL_HWPERF_OP SAL call for monitoring
+ * SGI Altix node and router hardware
+ *
+ * Mark Goodwin <markgw@sgi.com> Mon Aug 30 12:23:46 EST 2004
+ */
+
+#ifndef SN_HWPERF_H
+#define SN_HWPERF_H
+
+/*
+ * object structure. SN_HWPERF_ENUM_OBJECTS and SN_HWPERF_GET_CPU_INFO
+ * return an array of these. Do not change this without also
+ * changing the corresponding SAL code.
+ */
+#define SN_HWPERF_MAXSTRING		128
+struct sn_hwperf_object_info {
+	u32 id;
+	union {
+		struct {
+			u64 this_part:1;
+			u64 is_shared:1;
+		} fields;
+		struct {
+			u64 flags;
+			u64 reserved;
+		} b;
+	} f;
+	char name[SN_HWPERF_MAXSTRING];
+	char location[SN_HWPERF_MAXSTRING];
+	u32 ports;
+};
+
+#define sn_hwp_this_part	f.fields.this_part
+#define sn_hwp_is_shared	f.fields.is_shared
+#define sn_hwp_flags		f.b.flags
+
+#define SN_HWPERF_FOREIGN(x)	(!(x)->sn_hwp_this_part && !(x)->sn_hwp_is_shared)
+
+/* numa port structure, SN_HWPERF_ENUM_PORTS returns an array of these */
+struct sn_hwperf_port_info {
+	u32 port;
+	u32 conn_id;
+	u32 conn_port;
+};
+
+/* for HWPERF_{GET,SET}_MMRS */
+struct sn_hwperf_data {
+	u64 addr;
+	u64 data;
+};
+
+/* user ioctl() argument, see below */
+struct sn_hwperf_ioctl_args {
+        u64 arg;		/* argument, usually an object id */
+        u64 sz;                 /* size of transfer */
+        void *ptr;              /* pointer to source/target */
+        u32 v0;			/* second return value */
+};
+
+/*
+ * For SN_HWPERF_{GET,SET}_MMRS and SN_HWPERF_OBJECT_DISTANCE,
+ * sn_hwperf_ioctl_args.arg can be used to specify a CPU on which
+ * to call SAL, and whether to use an interprocessor interrupt
+ * or task migration in order to do so. If the CPU specified is
+ * SN_HWPERF_ARG_ANY_CPU, then the current CPU will be used.
+ */
+#define SN_HWPERF_ARG_ANY_CPU		0x7fffffffUL
+#define SN_HWPERF_ARG_CPU_MASK		0x7fffffff00000000ULL
+#define SN_HWPERF_ARG_USE_IPI_MASK	0x8000000000000000ULL
+#define SN_HWPERF_ARG_OBJID_MASK	0x00000000ffffffffULL
+
+/* 
+ * ioctl requests on the "sn_hwperf" misc device that call SAL.
+ */
+#define SN_HWPERF_OP_MEM_COPYIN		0x1000
+#define SN_HWPERF_OP_MEM_COPYOUT	0x2000
+#define SN_HWPERF_OP_MASK		0x0fff
+
+/*
+ * Determine mem requirement.
+ * arg	don't care
+ * sz	8
+ * p	pointer to u64 integer
+ */
+#define	SN_HWPERF_GET_HEAPSIZE		1
+
+/*
+ * Install mem for SAL drvr
+ * arg	don't care
+ * sz	sizeof buffer pointed to by p
+ * p	pointer to buffer for scratch area
+ */
+#define SN_HWPERF_INSTALL_HEAP		2
+
+/*
+ * Determine number of objects
+ * arg	don't care
+ * sz	8
+ * p	pointer to u64 integer
+ */
+#define SN_HWPERF_OBJECT_COUNT		(10|SN_HWPERF_OP_MEM_COPYOUT)
+
+/*
+ * Determine object "distance", relative to a cpu. This operation can
+ * execute on a designated logical cpu number, using either an IPI or
+ * via task migration. If the cpu number is SN_HWPERF_ANY_CPU, then
+ * the current CPU is used. See the SN_HWPERF_ARG_* macros above.
+ *
+ * arg	bitmap of IPI flag, cpu number and object id
+ * sz	8
+ * p	pointer to u64 integer
+ */
+#define SN_HWPERF_OBJECT_DISTANCE	(11|SN_HWPERF_OP_MEM_COPYOUT)
+
+/*
+ * Enumerate objects. Special case if sz == 8, returns the required
+ * buffer size.
+ * arg	don't care
+ * sz	sizeof buffer pointed to by p
+ * p	pointer to array of struct sn_hwperf_object_info
+ */
+#define SN_HWPERF_ENUM_OBJECTS		(12|SN_HWPERF_OP_MEM_COPYOUT)
+
+/*
+ * Enumerate NumaLink ports for an object. Special case if sz == 8,
+ * returns the required buffer size.
+ * arg	object id
+ * sz	sizeof buffer pointed to by p
+ * p	pointer to array of struct sn_hwperf_port_info
+ */
+#define SN_HWPERF_ENUM_PORTS		(13|SN_HWPERF_OP_MEM_COPYOUT)
+
+/*
+ * SET/GET memory mapped registers. These operations can execute
+ * on a designated logical cpu number, using either an IPI or via
+ * task migration. If the cpu number is SN_HWPERF_ANY_CPU, then
+ * the current CPU is used. See the SN_HWPERF_ARG_* macros above.
+ *
+ * arg	bitmap of ipi flag, cpu number and object id
+ * sz	sizeof buffer pointed to by p
+ * p	pointer to array of struct sn_hwperf_data
+ */
+#define SN_HWPERF_SET_MMRS		(14|SN_HWPERF_OP_MEM_COPYIN)
+#define SN_HWPERF_GET_MMRS		(15|SN_HWPERF_OP_MEM_COPYOUT| \
+					    SN_HWPERF_OP_MEM_COPYIN)
+/*
+ * Lock a shared object
+ * arg	object id
+ * sz	don't care
+ * p	don't care
+ */
+#define SN_HWPERF_ACQUIRE		16
+
+/*
+ * Unlock a shared object
+ * arg	object id
+ * sz	don't care
+ * p	don't care
+ */
+#define SN_HWPERF_RELEASE		17
+
+/*
+ * Break a lock on a shared object
+ * arg	object id
+ * sz	don't care
+ * p	don't care
+ */
+#define SN_HWPERF_FORCE_RELEASE		18
+
+/*
+ * ioctl requests on "sn_hwperf" that do not call SAL
+ */
+
+/*
+ * get cpu info as an array of hwperf_object_info_t. 
+ * id is logical CPU number, name is description, location
+ * is geoid (e.g. 001c04#1c). Special case if sz == 8,
+ * returns the required buffer size.
+ *
+ * arg	don't care
+ * sz	sizeof buffer pointed to by p
+ * p	pointer to array of struct sn_hwperf_object_info
+ */
+#define SN_HWPERF_GET_CPU_INFO		(100|SN_HWPERF_OP_MEM_COPYOUT)
+
+/*
+ * Given an object id, return it's node number (aka cnode).
+ * arg	object id
+ * sz	8
+ * p	pointer to u64 integer
+ */
+#define SN_HWPERF_GET_OBJ_NODE		(101|SN_HWPERF_OP_MEM_COPYOUT)
+
+/*
+ * Given a node number (cnode), return it's nasid.
+ * arg	ordinal node number (aka cnodeid)
+ * sz	8
+ * p	pointer to u64 integer
+ */
+#define SN_HWPERF_GET_NODE_NASID	(102|SN_HWPERF_OP_MEM_COPYOUT)
+
+/* return codes */
+#define SN_HWPERF_OP_OK			0
+#define SN_HWPERF_OP_NOMEM		1
+#define SN_HWPERF_OP_NO_PERM		2
+#define SN_HWPERF_OP_IO_ERROR		3
+#define SN_HWPERF_OP_BUSY		4
+#define SN_HWPERF_OP_RECONFIGURE	253
+#define SN_HWPERF_OP_INVAL		254
+
+#endif				/* SN_HWPERF_H */
diff -Nru a/include/asm-ia64/sn/sn_cpuid.h b/include/asm-ia64/sn/sn_cpuid.h
--- a/include/asm-ia64/sn/sn_cpuid.h	2004-10-18 14:55:55 -07:00
+++ b/include/asm-ia64/sn/sn_cpuid.h	2004-10-18 14:55:55 -07:00
@@ -4,7 +4,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.
  */
 
 
@@ -93,6 +93,7 @@
  */
 #define cpu_physical_id_to_nasid(cpi)		((cpi) &0xfff)
 #define cpu_physical_id_to_slice(cpi)		((cpi>>12) & 3)
+#define cpu_physical_id_to_coherence_id(cpi)	(cpu_physical_id_to_nasid(cpi) >> 9)
 #define get_nasid()				((ia64_getreg(_IA64_REG_CR_LID) >> 16) & 0xfff)
 #define get_slice()				((ia64_getreg(_IA64_REG_CR_LID) >> 28) & 0xf)
 #define get_node_number(addr)			(((unsigned long)(addr)>>38) & 0x7ff)
@@ -172,6 +173,11 @@
 
 #define smp_physical_node_id()			(cpuid_to_nasid(smp_processor_id()))
 
+/*
+ * cpuid_to_coherence_id - convert a cpuid to the coherence domain id it
+ * resides on
+ */
+#define cpuid_to_coherence_id(cpuid)	cpu_physical_id_to_coherence_id(cpu_physical_id(cpuid))
 
 #endif /* _ASM_IA64_SN_SN_CPUID_H */
 
diff -Nru a/include/asm-ia64/sn/sn_sal.h b/include/asm-ia64/sn/sn_sal.h
--- a/include/asm-ia64/sn/sn_sal.h	2004-10-18 14:57:05 -07:00
+++ b/include/asm-ia64/sn/sn_sal.h	2004-10-18 14:57:05 -07:00
@@ -8,7 +8,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.
  */
 
 
@@ -34,6 +34,7 @@
 #define  SN_SAL_NO_FAULT_ZONE_PHYSICAL		   0x02000011
 #define  SN_SAL_PRINT_ERROR			   0x02000012
 #define  SN_SAL_SET_ERROR_HANDLING_FEATURES	   0x0200001a	// reentrant
+#define  SN_SAL_GET_FIT_COMPT			   0x0200001b	// reentrant
 #define  SN_SAL_CONSOLE_PUTC                       0x02000021
 #define  SN_SAL_CONSOLE_GETC                       0x02000022
 #define  SN_SAL_CONSOLE_PUTS                       0x02000023
@@ -60,6 +61,8 @@
 #define  SN_SAL_SYSCTL_FRU_CAPTURE		   0x0200003f
 
 #define  SN_SAL_SYSCTL_IOBRICK_PCI_OP		   0x02000042	// reentrant
+#define	 SN_SAL_IROUTER_OP			   0x02000043
+#define  SN_SAL_HWPERF_OP			   0x02000050   // lock
 
 /*
  * Service-specific constants
@@ -86,12 +89,32 @@
 #endif	/* CONFIG_HOTPLUG_PCI_SGI */
 
 /*
- * SN_SAL_GET_PARTITION_ADDR return constants
+ * IRouter (i.e. generalized system controller) operations
+ */
+#define SAL_IROUTER_OPEN	0	/* open a subchannel */
+#define SAL_IROUTER_CLOSE	1	/* close a subchannel */
+#define SAL_IROUTER_SEND	2	/* send part of an IRouter packet */
+#define SAL_IROUTER_RECV	3	/* receive part of an IRouter packet */
+#define SAL_IROUTER_INTR_STATUS	4	/* check the interrupt status for
+					 * an open subchannel
+					 */
+#define SAL_IROUTER_INTR_ON	5	/* enable an interrupt */
+#define SAL_IROUTER_INTR_OFF	6	/* disable an interrupt */
+#define SAL_IROUTER_INIT	7	/* initialize IRouter driver */
+
+/* IRouter interrupt mask bits */
+#define SAL_IROUTER_INTR_XMIT	SAL_CONSOLE_INTR_XMIT
+#define SAL_IROUTER_INTR_RECV	SAL_CONSOLE_INTR_RECV
+
+
+/*
+ * SAL Error Codes
  */
 #define SALRET_MORE_PASSES	1
 #define SALRET_OK		0
-#define SALRET_INVALID_ARG	-2
-#define SALRET_ERROR		-3
+#define SALRET_NOT_IMPLEMENTED	(-1)
+#define SALRET_INVALID_ARG	(-2)
+#define SALRET_ERROR		(-3)
 
 /*
  * SN_SAL_SET_ERROR_HANDLING_FEATURES bit settings
@@ -702,6 +725,171 @@
 			feature_bits[5],
 			feature_bits[6]);
 	return rv.status;
+}
+
+
+/*
+ * Open a subchannel for sending arbitrary data to the system
+ * controller network via the system controller device associated with
+ * 'nasid'.  Return the subchannel number or a negative error code.
+ */
+static inline int
+ia64_sn_irtr_open(nasid_t nasid)
+{
+	struct ia64_sal_retval rv;
+	SAL_CALL_REENTRANT(rv, SN_SAL_IROUTER_OP, SAL_IROUTER_OPEN, nasid,
+			   0, 0, 0, 0, 0);
+	return (int) rv.v0;
+}
+
+/*
+ * Close system controller subchannel 'subch' previously opened on 'nasid'.
+ */
+static inline int
+ia64_sn_irtr_close(nasid_t nasid, int subch)
+{
+	struct ia64_sal_retval rv;
+	SAL_CALL_REENTRANT(rv, SN_SAL_IROUTER_OP, SAL_IROUTER_CLOSE,
+			   (u64) nasid, (u64) subch, 0, 0, 0, 0);
+	return (int) rv.status;
+}
+
+/*
+ * Read data from system controller associated with 'nasid' on
+ * subchannel 'subch'.  The buffer to be filled is pointed to by
+ * 'buf', and its capacity is in the integer pointed to by 'len'.  The
+ * referent of 'len' is set to the number of bytes read by the SAL
+ * call.  The return value is either SALRET_OK (for bytes read) or
+ * SALRET_ERROR (for error or "no data available").
+ */
+static inline int
+ia64_sn_irtr_recv(nasid_t nasid, int subch, char *buf, int *len)
+{
+	struct ia64_sal_retval rv;
+	SAL_CALL_REENTRANT(rv, SN_SAL_IROUTER_OP, SAL_IROUTER_RECV,
+			   (u64) nasid, (u64) subch, (u64) buf, (u64) len,
+			   0, 0);
+	return (int) rv.status;
+}
+
+/*
+ * Write data to the system controller network via the system
+ * controller associated with 'nasid' on suchannel 'subch'.  The
+ * buffer to be written out is pointed to by 'buf', and 'len' is the
+ * number of bytes to be written.  The return value is either the
+ * number of bytes written (which could be zero) or a negative error
+ * code.
+ */
+static inline int
+ia64_sn_irtr_send(nasid_t nasid, int subch, char *buf, int len)
+{
+	struct ia64_sal_retval rv;
+	SAL_CALL_REENTRANT(rv, SN_SAL_IROUTER_OP, SAL_IROUTER_SEND,
+			   (u64) nasid, (u64) subch, (u64) buf, (u64) len,
+			   0, 0);
+	return (int) rv.v0;
+}
+
+/*
+ * Check whether any interrupts are pending for the system controller
+ * associated with 'nasid' and its subchannel 'subch'.  The return
+ * value is a mask of pending interrupts (SAL_IROUTER_INTR_XMIT and/or
+ * SAL_IROUTER_INTR_RECV).
+ */
+static inline int
+ia64_sn_irtr_intr(nasid_t nasid, int subch)
+{
+	struct ia64_sal_retval rv;
+	SAL_CALL_REENTRANT(rv, SN_SAL_IROUTER_OP, SAL_IROUTER_INTR_STATUS,
+			   (u64) nasid, (u64) subch, 0, 0, 0, 0);
+	return (int) rv.v0;
+}
+
+/*
+ * Enable the interrupt indicated by the intr parameter (either
+ * SAL_IROUTER_INTR_XMIT or SAL_IROUTER_INTR_RECV).
+ */
+static inline int
+ia64_sn_irtr_intr_enable(nasid_t nasid, int subch, u64 intr)
+{
+	struct ia64_sal_retval rv;
+	SAL_CALL_REENTRANT(rv, SN_SAL_IROUTER_OP, SAL_IROUTER_INTR_ON,
+			   (u64) nasid, (u64) subch, intr, 0, 0, 0);
+	return (int) rv.v0;
+}
+
+/*
+ * Disable the interrupt indicated by the intr parameter (either
+ * SAL_IROUTER_INTR_XMIT or SAL_IROUTER_INTR_RECV).
+ */
+static inline int
+ia64_sn_irtr_intr_disable(nasid_t nasid, int subch, u64 intr)
+{
+	struct ia64_sal_retval rv;
+	SAL_CALL_REENTRANT(rv, SN_SAL_IROUTER_OP, SAL_IROUTER_INTR_OFF,
+			   (u64) nasid, (u64) subch, intr, 0, 0, 0);
+	return (int) rv.v0;
+}
+
+/**
+ * ia64_sn_get_fit_compt - read a FIT entry from the PROM header
+ * @nasid: NASID of node to read
+ * @index: FIT entry index to be retrieved (0..n)
+ * @fitentry: 16 byte buffer where FIT entry will be stored.
+ * @banbuf: optional buffer for retrieving banner
+ * @banlen: length of banner buffer
+ *
+ * Access to the physical PROM chips needs to be serialized since reads and
+ * writes can't occur at the same time, so we need to call into the SAL when
+ * we want to look at the FIT entries on the chips.
+ *
+ * Returns:
+ *	%SALRET_OK if ok
+ *	%SALRET_INVALID_ARG if index too big
+ *	%SALRET_NOT_IMPLEMENTED if running on older PROM
+ *	??? if nasid invalid OR banner buffer not large enough
+ */
+static inline int
+ia64_sn_get_fit_compt(u64 nasid, u64 index, void *fitentry, void *banbuf,
+		      u64 banlen)
+{
+	struct ia64_sal_retval rv;
+	SAL_CALL_NOLOCK(rv, SN_SAL_GET_FIT_COMPT, nasid, index, fitentry,
+			banbuf, banlen, 0, 0);
+	return (int) rv.status;
+}
+
+/*
+ * Initialize the SAL components of the system controller
+ * communication driver; specifically pass in a sizable buffer that
+ * can be used for allocation of subchannel queues as new subchannels
+ * are opened.  "buf" points to the buffer, and "len" specifies its
+ * length.
+ */
+static inline int
+ia64_sn_irtr_init(nasid_t nasid, void *buf, int len)
+{
+	struct ia64_sal_retval rv;
+	SAL_CALL_REENTRANT(rv, SN_SAL_IROUTER_OP, SAL_IROUTER_INIT,
+			   (u64) nasid, (u64) buf, (u64) len, 0, 0, 0);
+	return (int) rv.status;
+}
+
+/*
+ * This is the access point to the Altix PROM hardware performance
+ * and status monitoring interface. For info on using this, see
+ * include/asm-ia64/sn/sn2/sn_hwperf.h
+ */
+static inline int
+ia64_sn_hwperf_op(nasid_t nasid, u64 opcode, u64 a0, u64 a1, u64 a2,
+                  u64 a3, u64 a4, int *v0)
+{
+	struct ia64_sal_retval rv;
+	SAL_CALL_NOLOCK(rv, SN_SAL_HWPERF_OP, (u64)nasid,
+		opcode, a0, a1, a2, a3, a4);
+	if (v0)
+		*v0 = (int) rv.v0;
+	return (int) rv.status;
 }
 
 #endif /* _ASM_IA64_SN_SN_SAL_H */
diff -Nru a/include/asm-ia64/sn/xtalk/xtalk.h b/include/asm-ia64/sn/xtalk/xtalk.h
--- a/include/asm-ia64/sn/xtalk/xtalk.h	2004-10-18 14:56:33 -07:00
+++ b/include/asm-ia64/sn/xtalk/xtalk.h	2004-10-18 14:56:33 -07:00
@@ -55,7 +55,7 @@
 /*
  * Kernel/driver only definitions
  */
-#if __KERNEL__
+#ifdef __KERNEL__
 
 #include <asm/types.h>
 #include <asm/sn/types.h>
diff -Nru a/include/asm-ia64/sn/xtalk/xwidget.h b/include/asm-ia64/sn/xtalk/xwidget.h
--- a/include/asm-ia64/sn/xtalk/xwidget.h	2004-10-18 14:55:46 -07:00
+++ b/include/asm-ia64/sn/xtalk/xwidget.h	2004-10-18 14:55:46 -07:00
@@ -183,7 +183,7 @@
 
 
 /* Generic crosstalk widget initialization interface */
-#if __KERNEL__
+#ifdef __KERNEL__
 
 extern int              xwidget_driver_register(xwidget_part_num_t part_num,
 						xwidget_mfg_num_t mfg_num,
diff -Nru a/include/asm-ia64/socket.h b/include/asm-ia64/socket.h
--- a/include/asm-ia64/socket.h	2004-10-18 14:55:53 -07:00
+++ b/include/asm-ia64/socket.h	2004-10-18 14:55:53 -07:00
@@ -56,20 +56,4 @@
 
 #define SO_PEERSEC             31
 
-/* Nast libc5 fixup - bletch */
-#if defined(__KERNEL__)
-/* Socket types. */
-#define SOCK_STREAM	1		/* stream (connection) socket	*/
-#define SOCK_DGRAM	2		/* datagram (conn.less) socket	*/
-#define SOCK_RAW	3		/* raw socket			*/
-#define SOCK_RDM	4		/* reliably-delivered message	*/
-#define SOCK_SEQPACKET	5		/* sequential packet socket	*/
-#define SOCK_PACKET	10		/* linux specific way of	*/
-					/* getting packets at the dev	*/
-					/* level.  For writing rarp and	*/
-					/* other similar things on the	*/
-					/* user level.			*/
-#define	SOCK_MAX	(SOCK_PACKET+1)
-#endif
-
 #endif /* _ASM_IA64_SOCKET_H */
diff -Nru a/include/asm-ia64/spinlock.h b/include/asm-ia64/spinlock.h
--- a/include/asm-ia64/spinlock.h	2004-10-18 14:55:54 -07:00
+++ b/include/asm-ia64/spinlock.h	2004-10-18 14:55:54 -07:00
@@ -114,8 +114,8 @@
 #define spin_unlock_wait(x)	do { barrier(); } while ((x)->lock)
 
 typedef struct {
-	volatile int read_counter	: 31;
-	volatile int write_lock		:  1;
+	volatile unsigned int read_counter	: 31;
+	volatile unsigned int write_lock	:  1;
 } rwlock_t;
 #define RW_LOCK_UNLOCKED (rwlock_t) { 0, 0 }
 
diff -Nru a/include/asm-ia64/system.h b/include/asm-ia64/system.h
--- a/include/asm-ia64/system.h	2004-10-18 14:56:29 -07:00
+++ b/include/asm-ia64/system.h	2004-10-18 14:56:29 -07:00
@@ -19,12 +19,12 @@
 #include <asm/pal.h>
 #include <asm/percpu.h>
 
-#define GATE_ADDR		(0xa000000000000000)
+#define GATE_ADDR		__IA64_UL_CONST(0xa000000000000000)
 /*
  * 0xa000000000000000+2*PERCPU_PAGE_SIZE
  * - 0xa000000000000000+3*PERCPU_PAGE_SIZE remain unmapped (guard page)
  */
-#define KERNEL_START		 0xa000000100000000
+#define KERNEL_START		 __IA64_UL_CONST(0xa000000100000000)
 #define PERCPU_ADDR		(-PERCPU_PAGE_SIZE)
 
 #ifndef __ASSEMBLY__
diff -Nru a/include/asm-ia64/thread_info.h b/include/asm-ia64/thread_info.h
--- a/include/asm-ia64/thread_info.h	2004-10-18 14:57:05 -07:00
+++ b/include/asm-ia64/thread_info.h	2004-10-18 14:57:05 -07:00
@@ -9,14 +9,6 @@
 #include <asm/processor.h>
 #include <asm/ptrace.h>
 
-#define TI_TASK			0x00
-#define TI_EXEC_DOMAIN		0x08
-#define TI_FLAGS		0x10
-#define TI_CPU			0x14
-#define TI_ADDR_LIMIT		0x18
-#define TI_PRE_COUNT		0x20
-#define TI_RESTART_BLOCK	0x28
-
 #define PREEMPT_ACTIVE_BIT 30
 #define PREEMPT_ACTIVE	(1 << PREEMPT_ACTIVE_BIT)
 
diff -Nru a/include/asm-ia64/tlb.h b/include/asm-ia64/tlb.h
--- a/include/asm-ia64/tlb.h	2004-10-18 14:56:29 -07:00
+++ b/include/asm-ia64/tlb.h	2004-10-18 14:56:29 -07:00
@@ -39,6 +39,7 @@
  */
 #include <linux/config.h>
 #include <linux/mm.h>
+#include <linux/pagemap.h>
 #include <linux/swap.h>
 
 #include <asm/pgalloc.h>
diff -Nru a/include/asm-ia64/tlbflush.h b/include/asm-ia64/tlbflush.h
--- a/include/asm-ia64/tlbflush.h	2004-10-18 14:57:03 -07:00
+++ b/include/asm-ia64/tlbflush.h	2004-10-18 14:57:03 -07:00
@@ -48,22 +48,19 @@
 static inline void
 flush_tlb_mm (struct mm_struct *mm)
 {
-	MMU_TRACE('F', smp_processor_id(), mm, mm->context);
 	if (!mm)
-		goto out;
+		return;
 
 	mm->context = 0;
 
 	if (atomic_read(&mm->mm_users) == 0)
-		goto out;		/* happens as a result of exit_mmap() */
+		return;		/* happens as a result of exit_mmap() */
 
 #ifdef CONFIG_SMP
 	smp_flush_tlb_mm(mm);
 #else
 	local_finish_flush_tlb_mm(mm);
 #endif
-  out:
-	MMU_TRACE('f', smp_processor_id(), mm, mm->context);
 }
 
 extern void flush_tlb_range (struct vm_area_struct *vma, unsigned long start, unsigned long end);
diff -Nru a/include/asm-ia64/uaccess.h b/include/asm-ia64/uaccess.h
--- a/include/asm-ia64/uaccess.h	2004-10-18 14:56:28 -07:00
+++ b/include/asm-ia64/uaccess.h	2004-10-18 14:56:28 -07:00
@@ -60,14 +60,17 @@
  * address TASK_SIZE is never valid.  We also need to make sure that the address doesn't
  * point inside the virtually mapped linear page table.
  */
-#define __access_ok(addr, size, segment)					\
-	(likely((unsigned long) (addr) <= (segment).seg)			\
-	 && ((segment).seg == KERNEL_DS.seg					\
-	     || likely(REGION_OFFSET((unsigned long) (addr)) < RGN_MAP_LIMIT)))
+#define __access_ok(addr, size, segment)						\
+({											\
+	__chk_user_ptr(addr);								\
+	(likely((unsigned long) (addr) <= (segment).seg)				\
+	 && ((segment).seg == KERNEL_DS.seg						\
+	     || likely(REGION_OFFSET((unsigned long) (addr)) < RGN_MAP_LIMIT)));	\
+})
 #define access_ok(type, addr, size)	__access_ok((addr), (size), get_fs())
 
 static inline int
-verify_area (int type, const void *addr, unsigned long size)
+verify_area (int type, const void __user *addr, unsigned long size)
 {
 	return access_ok(type, addr, size) ? 0 : -EFAULT;
 }
@@ -91,6 +94,42 @@
 #define __put_user(x, ptr)	__put_user_nocheck((__typeof__(*(ptr))) (x), (ptr), sizeof(*(ptr)))
 #define __get_user(x, ptr)	__get_user_nocheck((x), (ptr), sizeof(*(ptr)))
 
+extern long __put_user_unaligned_unknown (void);
+
+#define __put_user_unaligned(x, ptr)								\
+({												\
+	long __ret;										\
+	switch (sizeof(*(ptr))) {								\
+		case 1: __ret = __put_user((x), (ptr)); break;					\
+		case 2: __ret = (__put_user((x), (u8 __user *)(ptr)))				\
+			| (__put_user((x) >> 8, ((u8 __user *)(ptr) + 1))); break;		\
+		case 4: __ret = (__put_user((x), (u16 __user *)(ptr)))				\
+			| (__put_user((x) >> 16, ((u16 __user *)(ptr) + 1))); break;		\
+		case 8: __ret = (__put_user((x), (u32 __user *)(ptr)))				\
+			| (__put_user((x) >> 32, ((u32 __user *)(ptr) + 1))); break;		\
+		default: __ret = __put_user_unaligned_unknown();				\
+	}											\
+	__ret;											\
+})
+
+extern long __get_user_unaligned_unknown (void);
+
+#define __get_user_unaligned(x, ptr)								\
+({												\
+	long __ret;										\
+	switch (sizeof(*(ptr))) {								\
+		case 1: __ret = __get_user((x), (ptr)); break;					\
+		case 2: __ret = (__get_user((x), (u8 __user *)(ptr)))				\
+			| (__get_user((x) >> 8, ((u8 __user *)(ptr) + 1))); break;		\
+		case 4: __ret = (__get_user((x), (u16 __user *)(ptr)))				\
+			| (__get_user((x) >> 16, ((u16 __user *)(ptr) + 1))); break;		\
+		case 8: __ret = (__get_user((x), (u32 __user *)(ptr)))				\
+			| (__get_user((x) >> 32, ((u32 __user *)(ptr) + 1))); break;		\
+		default: __ret = __get_user_unaligned_unknown();				\
+	}											\
+	__ret;											\
+})
+
 #ifdef ASM_SUPPORTED
   struct __large_struct { unsigned long buf[100]; };
 # define __m(x) (*(struct __large_struct *)(x))
@@ -149,11 +188,11 @@
  */
 #define __do_get_user(check, x, ptr, size, segment)					\
 ({											\
-	const __typeof__(*(ptr)) *__gu_ptr = (ptr);					\
+	const __typeof__(*(ptr)) __user *__gu_ptr = (ptr);				\
 	__typeof__ (size) __gu_size = (size);						\
 	long __gu_err = -EFAULT, __gu_val = 0;						\
 											\
-	if (!check || __access_ok((long) __gu_ptr, size, segment))			\
+	if (!check || __access_ok(__gu_ptr, size, segment))				\
 		switch (__gu_size) {							\
 		      case 1: __get_user_size(__gu_val, __gu_ptr, 1, __gu_err); break;	\
 		      case 2: __get_user_size(__gu_val, __gu_ptr, 2, __gu_err); break;	\
@@ -177,11 +216,11 @@
 #define __do_put_user(check, x, ptr, size, segment)					\
 ({											\
 	__typeof__ (x) __pu_x = (x);							\
-	__typeof__ (*(ptr)) *__pu_ptr = (ptr);						\
+	__typeof__ (*(ptr)) __user *__pu_ptr = (ptr);					\
 	__typeof__ (size) __pu_size = (size);						\
 	long __pu_err = -EFAULT;							\
 											\
-	if (!check || __access_ok((long) __pu_ptr, __pu_size, segment))			\
+	if (!check || __access_ok(__pu_ptr, __pu_size, segment))			\
 		switch (__pu_size) {							\
 		      case 1: __put_user_size(__pu_x, __pu_ptr, 1, __pu_err); break;	\
 		      case 2: __put_user_size(__pu_x, __pu_ptr, 2, __pu_err); break;	\
@@ -198,43 +237,64 @@
 /*
  * Complex access routines
  */
-extern unsigned long __copy_user (void *to, const void *from, unsigned long count);
+extern unsigned long __must_check __copy_user (void __user *to, const void __user *from,
+					       unsigned long count);
+
+static inline unsigned long
+__copy_to_user (void __user *to, const void *from, unsigned long count)
+{
+	return __copy_user(to, (void __user *) from, count);
+}
 
-#define __copy_to_user(to, from, n)	__copy_user((to), (from), (n))
-#define __copy_from_user(to, from, n)	__copy_user((to), (from), (n))
+static inline unsigned long
+__copy_from_user (void *to, const void __user *from, unsigned long count)
+{
+	return __copy_user((void __user *) to, from, count);
+}
 
-#define copy_to_user(to, from, n)	__copy_tofrom_user((to), (from), (n), 1)
-#define copy_from_user(to, from, n)	__copy_tofrom_user((to), (from), (n), 0)
+#define __copy_to_user_inatomic		__copy_to_user
+#define __copy_from_user_inatomic	__copy_from_user
+#define copy_to_user(to, from, n)							\
+({											\
+	void __user *__cu_to = (to);							\
+	const void *__cu_from = (from);							\
+	long __cu_len = (n);								\
+											\
+	if (__access_ok(__cu_to, __cu_len, get_fs()))					\
+		__cu_len = __copy_user(__cu_to, (void __user *) __cu_from, __cu_len);	\
+	__cu_len;									\
+})
 
-#define __copy_tofrom_user(to, from, n, check_to)					\
+#define copy_from_user(to, from, n)							\
 ({											\
 	void *__cu_to = (to);								\
-	const void *__cu_from = (from);							\
+	const void __user *__cu_from = (from);						\
 	long __cu_len = (n);								\
 											\
-	if (__access_ok((long) ((check_to) ? __cu_to : __cu_from), __cu_len, get_fs()))	\
-		__cu_len = __copy_user(__cu_to, __cu_from, __cu_len);			\
+	__chk_user_ptr(__cu_from);							\
+	if (__access_ok(__cu_from, __cu_len, get_fs()))					\
+		__cu_len = __copy_user((void __user *) __cu_to, __cu_from, __cu_len);	\
 	__cu_len;									\
 })
 
 #define __copy_in_user(to, from, size)	__copy_user((to), (from), (size))
 
 static inline unsigned long
-copy_in_user (void *to, const void *from, unsigned long n)
+copy_in_user (void __user *to, const void __user *from, unsigned long n)
 {
 	if (likely(access_ok(VERIFY_READ, from, n) && access_ok(VERIFY_WRITE, to, n)))
 		n = __copy_user(to, from, n);
 	return n;
 }
 
-extern unsigned long __do_clear_user (void *, unsigned long);
+extern unsigned long __do_clear_user (void __user *, unsigned long);
 
 #define __clear_user(to, n)		__do_clear_user(to, n)
 
 #define clear_user(to, n)					\
 ({								\
 	unsigned long __cu_len = (n);				\
-	if (__access_ok((long) to, __cu_len, get_fs()))		\
+	if (__access_ok(to, __cu_len, get_fs()))		\
 		__cu_len = __do_clear_user(to, __cu_len);	\
 	__cu_len;						\
 })
@@ -244,25 +304,25 @@
  * Returns: -EFAULT if exception before terminator, N if the entire buffer filled, else
  * strlen.
  */
-extern long __strncpy_from_user (char *to, const char *from, long to_len);
+extern long __must_check __strncpy_from_user (char *to, const char __user *from, long to_len);
 
 #define strncpy_from_user(to, from, n)					\
 ({									\
-	const char * __sfu_from = (from);				\
+	const char __user * __sfu_from = (from);			\
 	long __sfu_ret = -EFAULT;					\
-	if (__access_ok((long) __sfu_from, 0, get_fs()))		\
+	if (__access_ok(__sfu_from, 0, get_fs()))			\
 		__sfu_ret = __strncpy_from_user((to), __sfu_from, (n));	\
 	__sfu_ret;							\
 })
 
 /* Returns: 0 if bad, string length+1 (memory size) of string if ok */
-extern unsigned long __strlen_user (const char *);
+extern unsigned long __strlen_user (const char __user *);
 
 #define strlen_user(str)				\
 ({							\
-	const char *__su_str = (str);			\
+	const char __user *__su_str = (str);		\
 	unsigned long __su_ret = 0;			\
-	if (__access_ok((long) __su_str, 0, get_fs()))	\
+	if (__access_ok(__su_str, 0, get_fs()))		\
 		__su_ret = __strlen_user(__su_str);	\
 	__su_ret;					\
 })
@@ -272,13 +332,13 @@
  * (N), a value greater than N if the limit would be exceeded, else
  * strlen.
  */
-extern unsigned long __strnlen_user (const char *, long);
+extern unsigned long __strnlen_user (const char __user *, long);
 
 #define strnlen_user(str, len)					\
 ({								\
-	const char *__su_str = (str);				\
+	const char __user *__su_str = (str);			\
 	unsigned long __su_ret = 0;				\
-	if (__access_ok((long) __su_str, 0, get_fs()))		\
+	if (__access_ok(__su_str, 0, get_fs()))			\
 		__su_ret = __strnlen_user(__su_str, len);	\
 	__su_ret;						\
 })
diff -Nru a/include/asm-ia64/unistd.h b/include/asm-ia64/unistd.h
--- a/include/asm-ia64/unistd.h	2004-10-18 14:55:55 -07:00
+++ b/include/asm-ia64/unistd.h	2004-10-18 14:55:55 -07:00
@@ -369,8 +369,8 @@
 				int fd, long pgoff);
 struct pt_regs;
 struct sigaction;
-asmlinkage long sys_execve(char *filename, char **argv, char **envp,
-				struct pt_regs *regs);
+asmlinkage long sys_execve(char __user *filename, char __user * __user *argv,
+			   char __user * __user *envp, struct pt_regs *regs);
 asmlinkage long sys_pipe(long arg0, long arg1, long arg2, long arg3,
 			long arg4, long arg5, long arg6, long arg7, long stack);
 asmlinkage long sys_ptrace(long request, pid_t pid,
diff -Nru a/include/asm-m32r/a.out.h b/include/asm-m32r/a.out.h
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/include/asm-m32r/a.out.h	2004-10-18 14:57:22 -07:00
@@ -0,0 +1,28 @@
+#ifndef _ASM_M32R_A_OUT_H
+#define _ASM_M32R_A_OUT_H
+
+/* orig : i386 2.4.18 */
+
+struct exec
+{
+  unsigned long a_info;		/* Use macros N_MAGIC, etc for access */
+  unsigned a_text;		/* length of text, in bytes */
+  unsigned a_data;		/* length of data, in bytes */
+  unsigned a_bss;		/* length of uninitialized data area for file, in bytes */
+  unsigned a_syms;		/* length of symbol table data in file, in bytes */
+  unsigned a_entry;		/* start address */
+  unsigned a_trsize;		/* length of relocation info for text, in bytes */
+  unsigned a_drsize;		/* length of relocation info for data, in bytes */
+};
+
+#define N_TRSIZE(a)	((a).a_trsize)
+#define N_DRSIZE(a)	((a).a_drsize)
+#define N_SYMSIZE(a)	((a).a_syms)
+
+#ifdef __KERNEL__
+
+#define STACK_TOP	TASK_SIZE
+
+#endif
+
+#endif /* _ASM_M32R_A_OUT_H */
diff -Nru a/include/asm-m32r/addrspace.h b/include/asm-m32r/addrspace.h
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/include/asm-m32r/addrspace.h	2004-10-18 14:57:24 -07:00
@@ -0,0 +1,58 @@
+/* $Id$ */
+/*
+ * 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 by Hiroyuki Kondo
+ *
+ * Defitions for the address spaces of the M32R CPUs.
+ */
+#ifndef __ASM_M32R_ADDRSPACE_H
+#define __ASM_M32R_ADDRSPACE_H
+
+/*
+ * Memory segments (32bit kernel mode addresses)
+ */
+#define KUSEG                   0x00000000
+#define KSEG0                   0x80000000
+#define KSEG1                   0xa0000000
+#define KSEG2                   0xc0000000
+#define KSEG3                   0xe0000000
+
+#define K0BASE  KSEG0
+
+/*
+ * Returns the kernel segment base of a given address
+ */
+#ifndef __ASSEMBLY__
+#define KSEGX(a)                (((unsigned long)(a)) & 0xe0000000)
+#else
+#define KSEGX(a)                ((a) & 0xe0000000)
+#endif
+
+/*
+ * Returns the physical address of a KSEG0/KSEG1 address
+ */
+#ifndef __ASSEMBLY__
+#define PHYSADDR(a)		(((unsigned long)(a)) & 0x1fffffff)
+#else
+#define PHYSADDR(a)		((a) & 0x1fffffff)
+#endif
+
+/*
+ * Map an address to a certain kernel segment
+ */
+#ifndef __ASSEMBLY__
+#define KSEG0ADDR(a)		((__typeof__(a))(((unsigned long)(a) & 0x1fffffff) | KSEG0))
+#define KSEG1ADDR(a)		((__typeof__(a))(((unsigned long)(a) & 0x1fffffff) | KSEG1))
+#define KSEG2ADDR(a)		((__typeof__(a))(((unsigned long)(a) & 0x1fffffff) | KSEG2))
+#define KSEG3ADDR(a)		((__typeof__(a))(((unsigned long)(a) & 0x1fffffff) | KSEG3))
+#else
+#define KSEG0ADDR(a)		(((a) & 0x1fffffff) | KSEG0)
+#define KSEG1ADDR(a)		(((a) & 0x1fffffff) | KSEG1)
+#define KSEG2ADDR(a)		(((a) & 0x1fffffff) | KSEG2)
+#define KSEG3ADDR(a)		(((a) & 0x1fffffff) | KSEG3)
+#endif
+
+#endif /* __ASM_M32R_ADDRSPACE_H */
diff -Nru a/include/asm-m32r/assembler.h b/include/asm-m32r/assembler.h
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/include/asm-m32r/assembler.h	2004-10-18 14:57:21 -07:00
@@ -0,0 +1,212 @@
+#ifndef _ASM_M32R_ASSEMBLER_H
+#define _ASM_M32R_ASSEMBLER_H
+
+/* $Id$ */
+
+/*
+ * linux/asm-m32r/assembler.h
+ *
+ * This file contains M32R architecture specific defines.
+ *
+ * Do not include any C declarations in this file - it is included by
+ * assembler source.
+ */
+
+#include <linux/config.h>
+
+
+#undef ENTRY
+#define ENTRY(name) ENTRY_M name
+	.macro  ENTRY_M name
+	.global \name
+	ALIGN
+\name:
+	.endm
+
+/*
+ * LDIMM: load immediate value
+ *
+ * STI: enable interruption
+ * CLI: disable interruption
+ */
+
+#ifdef __ASSEMBLY__
+
+#define LDIMM(reg,x) LDIMM reg x
+	.macro LDIMM reg x
+	seth	\reg, #high(\x)
+	or3	\reg, \reg, #low(\x)
+	.endm
+
+#if !defined(CONFIG_CHIP_M32102)
+#define STI(reg) STI_M reg
+	.macro STI_M reg
+	setpsw  #0x40	    ->	nop
+	; WORKAROUND: "-> nop" is a workaround for the M32700(TS1).
+	.endm
+
+#define CLI(reg) CLI_M reg
+	.macro CLI_M reg
+	clrpsw  #0x40	    ->	nop
+	; WORKAROUND: "-> nop" is a workaround for the M32700(TS1).
+	.endm
+#else	/* CONFIG_CHIP_M32102 */
+#define STI(reg) STI_M reg
+	.macro STI_M reg
+	mvfc	\reg, psw
+	or3	\reg, \reg, #0x0040
+	mvtc	\reg, psw
+	.endm
+
+#define CLI(reg) CLI_M reg
+	.macro CLI_M reg
+	mvfc	\reg, psw
+	and3	\reg, \reg, #0xffbf
+	mvtc	\reg, psw
+	.endm
+#endif	/* CONFIG_CHIP_M32102 */
+
+	.macro	SAVE_ALL
+	push	r0		; orig_r0
+	push	sp		; spi (r15)
+	push	lr		; r14
+	push	r13
+	mvfc	r13, cr3	; spu
+	push	r13
+	mvfc	r13, bbpc
+	push	r13
+	mvfc	r13, bbpsw
+	push	r13
+	mvfc	r13, bpc
+	push	r13
+	mvfc	r13, psw
+	push	r13
+#if defined(CONFIG_ISA_M32R2) && defined(CONFIG_ISA_DSP_LEVEL2)
+	mvfaclo	r13, a1
+	push	r13
+	mvfachi r13, a1
+	push	r13
+	mvfaclo	r13, a0
+	push	r13
+	mvfachi	r13, a0
+	push	r13
+#elif defined(CONFIG_ISA_M32R2) || defined(CONFIG_ISA_M32R)
+	mvfaclo	r13
+	push	r13
+	mvfachi	r13
+	push	r13
+#else
+#error unknown isa configuration
+#endif
+	ldi	r13, #-1
+	push	r13		; syscall_nr (default: -1)
+	push	r12
+	push	r11
+	push	r10
+	push	r9
+	push	r8
+	push	r7
+	push	r3
+	push	r2
+	push	r1
+	push	r0
+	addi	sp, #-4		; room for implicit pt_regs parameter
+	push	r6
+	push	r5
+	push	r4
+	.endm
+
+	.macro	RESTORE_ALL
+	pop	r4
+	pop	r5
+	pop	r6
+	addi	sp, #4
+	pop	r0
+	pop	r1
+	pop	r2
+	pop	r3
+	pop	r7
+	pop	r8
+	pop	r9
+	pop	r10
+	pop	r11
+	pop	r12
+	addi	r15, #4		; Skip syscall number
+#if defined(CONFIG_ISA_M32R2) && defined(CONFIG_ISA_DSP_LEVEL2)
+	pop	r13
+	mvtachi	r13, a0
+	pop	r13
+	mvtaclo	r13, a0
+	pop	r13
+	mvtachi	r13, a1
+	pop	r13
+	mvtaclo	r13, a1
+#elif defined(CONFIG_ISA_M32R2) || defined(CONFIG_ISA_M32R)
+	pop	r13
+	mvtachi	r13
+	pop	r13
+	mvtaclo	r13
+#else
+#error unknown isa configuration
+#endif
+	pop	r14
+	mvtc	r14, psw
+	pop	r14
+	mvtc	r14, bpc
+	addi	sp, #8		; Skip bbpsw, bbpc
+	pop	r14
+	mvtc	r14, cr3	; spu
+	pop	r13
+	pop	lr		; r14
+	pop	sp		; spi (r15)
+	addi	sp, #4		; Skip orig_r0
+	.fillinsn
+1:	rte
+	.section .fixup,"ax"
+2:	bl	do_exit
+	.previous
+	.section __ex_table,"a"
+	ALIGN
+	.long	1b, 2b
+	.previous
+	.endm
+
+#define GET_CURRENT(reg)  get_current reg
+	.macro get_current reg
+	ldi  \reg, #-8192
+	and  \reg, sp
+	.endm
+
+#if !defined(CONFIG_CHIP_M32102)
+	.macro	SWITCH_TO_KERNEL_STACK
+	; switch to kernel stack (spi)
+	clrpsw	#0x80	    ->	nop
+	.endm
+#else	/* CONFIG_CHIP_M32102 */
+	.macro	SWITCH_TO_KERNEL_STACK
+	push	r0		; save r0 for working
+	mvfc	r0, psw
+	and3	r0, r0, #0x00ff7f
+	mvtc	r0, psw
+	slli	r0, #16
+	bltz	r0, 1f		; check BSM-bit
+;
+	;; called from kernel context: previous stack = spi
+	pop	r0		; retrieve r0
+	bra	2f
+	.fillinsn
+1:
+	;; called from user context: previous stack = spu
+	mvfc	r0, cr3		; spu
+	addi	r0, #4
+	mvtc	r0, cr3		; spu
+	ld	r0, @(-4,r0)	; retrieve r0
+	.fillinsn
+2:
+	.endm
+#endif	/* CONFIG_CHIP_M32102 */
+
+#endif	/* __ASSEMBLY__ */
+
+#endif	/* _ASM_M32R_ASSEMBLER_H */
+
diff -Nru a/include/asm-m32r/atomic.h b/include/asm-m32r/atomic.h
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/include/asm-m32r/atomic.h	2004-10-18 14:57:23 -07:00
@@ -0,0 +1,305 @@
+#ifndef _ASM_M32R_ATOMIC_H
+#define _ASM_M32R_ATOMIC_H
+
+/*
+ *  linux/include/asm-m32r/atomic.h
+ *
+ *  M32R version:
+ *    Copyright (C) 2001, 2002  Hitoshi Yamamoto
+ *    Copyright (C) 2004  Hirokazu Takata <takata at linux-m32r.org>
+ */
+
+#include <linux/config.h>
+#include <asm/system.h>
+
+/*
+ * Atomic operations that C can't guarantee us.  Useful for
+ * resource counting etc..
+ */
+
+#undef LOAD
+#undef STORE
+#ifdef CONFIG_SMP
+#define LOAD	"lock"
+#define STORE	"unlock"
+#else
+#define LOAD	"ld"
+#define STORE	"st"
+#endif
+
+/*
+ * Make sure gcc doesn't try to be clever and move things around
+ * on us. We need to use _exactly_ the address the user gave us,
+ * not some alias that contains the same information.
+ */
+typedef struct { volatile int counter; } atomic_t;
+
+#define ATOMIC_INIT(i)	{ (i) }
+
+/**
+ * atomic_read - read atomic variable
+ * @v: pointer of type atomic_t
+ *
+ * Atomically reads the value of @v.
+ */
+#define atomic_read(v)	((v)->counter)
+
+/**
+ * atomic_set - set atomic variable
+ * @v: pointer of type atomic_t
+ * @i: required value
+ *
+ * Atomically sets the value of @v to @i.
+ */
+#define atomic_set(v,i)	(((v)->counter) = (i))
+
+/**
+ * atomic_add_return - add integer to atomic variable and return it
+ * @i: integer value to add
+ * @v: pointer of type atomic_t
+ *
+ * Atomically adds @i to @v and return (@i + @v).
+ */
+static inline int atomic_add_return(int i, atomic_t *v)
+{
+	unsigned long flags;
+	int result;
+
+	local_irq_save(flags);
+	__asm__ __volatile__ (
+		"# atomic_add_return		\n\t"
+		DCACHE_CLEAR("%0", "r4", "%1")
+		LOAD"	%0, @%1;		\n\t"
+		"add	%0, %2;			\n\t"
+		STORE"	%0, @%1;		\n\t"
+		: "=&r" (result)
+		: "r" (&v->counter), "r" (i)
+		: "memory"
+#ifdef CONFIG_CHIP_M32700_TS1
+		, "r4"
+#endif	/* CONFIG_CHIP_M32700_TS1 */
+	);
+	local_irq_restore(flags);
+
+	return result;
+}
+
+/**
+ * atomic_sub_return - subtract integer from atomic variable and return it
+ * @i: integer value to subtract
+ * @v: pointer of type atomic_t
+ *
+ * Atomically subtracts @i from @v and return (@v - @i).
+ */
+static inline int atomic_sub_return(int i, atomic_t *v)
+{
+	unsigned long flags;
+	int result;
+
+	local_irq_save(flags);
+	__asm__ __volatile__ (
+		"# atomic_sub_return		\n\t"
+		DCACHE_CLEAR("%0", "r4", "%1")
+		LOAD"	%0, @%1;		\n\t"
+		"sub	%0, %2;			\n\t"
+		STORE"	%0, @%1;		\n\t"
+		: "=&r" (result)
+		: "r" (&v->counter), "r" (i)
+		: "memory"
+#ifdef CONFIG_CHIP_M32700_TS1
+		, "r4"
+#endif	/* CONFIG_CHIP_M32700_TS1 */
+	);
+	local_irq_restore(flags);
+
+	return result;
+}
+
+/**
+ * atomic_add - add integer to atomic variable
+ * @i: integer value to add
+ * @v: pointer of type atomic_t
+ *
+ * Atomically adds @i to @v.
+ */
+#define atomic_add(i,v) ((void) atomic_add_return((i), (v)))
+
+/**
+ * atomic_sub - subtract the atomic variable
+ * @i: integer value to subtract
+ * @v: pointer of type atomic_t
+ *
+ * Atomically subtracts @i from @v.
+ */
+#define atomic_sub(i,v) ((void) atomic_sub_return((i), (v)))
+
+/**
+ * atomic_sub_and_test - subtract value from variable and test result
+ * @i: integer value to subtract
+ * @v: pointer of type atomic_t
+ *
+ * Atomically subtracts @i from @v and returns
+ * true if the result is zero, or false for all
+ * other cases.
+ */
+#define atomic_sub_and_test(i,v) (atomic_sub_return((i), (v)) == 0)
+
+/**
+ * atomic_inc_return - increment atomic variable and return it
+ * @v: pointer of type atomic_t
+ *
+ * Atomically increments @v by 1 and returns the result.
+ */
+static inline int atomic_inc_return(atomic_t *v)
+{
+	unsigned long flags;
+	int result;
+
+	local_irq_save(flags);
+	__asm__ __volatile__ (
+		"# atomic_inc_return		\n\t"
+		DCACHE_CLEAR("%0", "r4", "%1")
+		LOAD"	%0, @%1;		\n\t"
+		"addi	%0, #1;			\n\t"
+		STORE"	%0, @%1;		\n\t"
+		: "=&r" (result)
+		: "r" (&v->counter)
+		: "memory"
+#ifdef CONFIG_CHIP_M32700_TS1
+		, "r4"
+#endif	/* CONFIG_CHIP_M32700_TS1 */
+	);
+	local_irq_restore(flags);
+
+	return result;
+}
+
+/**
+ * atomic_dec_return - decrement atomic variable and return it
+ * @v: pointer of type atomic_t
+ *
+ * Atomically decrements @v by 1 and returns the result.
+ */
+static inline int atomic_dec_return(atomic_t *v)
+{
+	unsigned long flags;
+	int result;
+
+	local_irq_save(flags);
+	__asm__ __volatile__ (
+		"# atomic_dec_return		\n\t"
+		DCACHE_CLEAR("%0", "r4", "%1")
+		LOAD"	%0, @%1;		\n\t"
+		"addi	%0, #-1;		\n\t"
+		STORE"	%0, @%1;		\n\t"
+		: "=&r" (result)
+		: "r" (&v->counter)
+		: "memory"
+#ifdef CONFIG_CHIP_M32700_TS1
+		, "r4"
+#endif	/* CONFIG_CHIP_M32700_TS1 */
+	);
+	local_irq_restore(flags);
+
+	return result;
+}
+
+/**
+ * atomic_inc - increment atomic variable
+ * @v: pointer of type atomic_t
+ *
+ * Atomically increments @v by 1.
+ */
+#define atomic_inc(v) ((void)atomic_inc_return(v))
+
+/**
+ * atomic_dec - decrement atomic variable
+ * @v: pointer of type atomic_t
+ *
+ * Atomically decrements @v by 1.
+ */
+#define atomic_dec(v) ((void)atomic_dec_return(v))
+
+/**
+ * atomic_inc_and_test - increment and test
+ * @v: pointer of type atomic_t
+ *
+ * Atomically increments @v by 1
+ * and returns true if the result is zero, or false for all
+ * other cases.
+ */
+#define atomic_inc_and_test(v) (atomic_inc_return(v) == 0)
+
+/**
+ * atomic_dec_and_test - decrement and test
+ * @v: pointer of type atomic_t
+ *
+ * Atomically decrements @v by 1 and
+ * returns true if the result is 0, or false for all
+ * other cases.
+ */
+#define atomic_dec_and_test(v) (atomic_dec_return(v) == 0)
+
+/**
+ * atomic_add_negative - add and test if negative
+ * @v: pointer of type atomic_t
+ * @i: integer value to add
+ *
+ * Atomically adds @i to @v and returns true
+ * if the result is negative, or false when
+ * result is greater than or equal to zero.
+ */
+#define atomic_add_negative(i,v) (atomic_add_return((i), (v)) < 0)
+
+static inline void atomic_clear_mask(unsigned long  mask, atomic_t *addr)
+{
+	unsigned long flags;
+	unsigned long tmp;
+
+	local_irq_save(flags);
+	__asm__ __volatile__ (
+		"# atomic_clear_mask		\n\t"
+		DCACHE_CLEAR("%0", "r5", "%1")
+		LOAD"	%0, @%1;		\n\t"
+		"and	%0, %2;			\n\t"
+		STORE"	%0, @%1;		\n\t"
+		: "=&r" (tmp)
+		: "r" (addr), "r" (~mask)
+		: "memory"
+#ifdef CONFIG_CHIP_M32700_TS1
+		, "r5"
+#endif	/* CONFIG_CHIP_M32700_TS1 */
+	);
+	local_irq_restore(flags);
+}
+
+static inline void atomic_set_mask(unsigned long  mask, atomic_t *addr)
+{
+	unsigned long flags;
+	unsigned long tmp;
+
+	local_irq_save(flags);
+	__asm__ __volatile__ (
+		"# atomic_set_mask		\n\t"
+		DCACHE_CLEAR("%0", "r5", "%1")
+		LOAD"	%0, @%1;		\n\t"
+		"or	%0, %2;			\n\t"
+		STORE"	%0, @%1;		\n\t"
+		: "=&r" (tmp)
+		: "r" (addr), "r" (mask)
+		: "memory"
+#ifdef CONFIG_CHIP_M32700_TS1
+		, "r5"
+#endif	/* CONFIG_CHIP_M32700_TS1 */
+	);
+	local_irq_restore(flags);
+}
+
+/* Atomic operations are already serializing on m32r */
+#define smp_mb__before_atomic_dec()	barrier()
+#define smp_mb__after_atomic_dec()	barrier()
+#define smp_mb__before_atomic_inc()	barrier()
+#define smp_mb__after_atomic_inc()	barrier()
+
+#endif	/* _ASM_M32R_ATOMIC_H */
+
diff -Nru a/include/asm-m32r/bitops.h b/include/asm-m32r/bitops.h
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/include/asm-m32r/bitops.h	2004-10-18 14:57:23 -07:00
@@ -0,0 +1,716 @@
+#ifndef _ASM_M32R_BITOPS_H
+#define _ASM_M32R_BITOPS_H
+
+/*
+ *  linux/include/asm-m32r/bitops.h
+ *
+ *  Copyright 1992, Linus Torvalds.
+ *
+ *  M32R version:
+ *    Copyright (C) 2001, 2002  Hitoshi Yamamoto
+ *    Copyright (C) 2004  Hirokazu Takata <takata at linux-m32r.org>
+ */
+
+#include <linux/config.h>
+#include <linux/compiler.h>
+#include <asm/system.h>
+#include <asm/byteorder.h>
+#include <asm/types.h>
+
+/*
+ * These have to be done with inline assembly: that way the bit-setting
+ * is guaranteed to be atomic. All bit operations return 0 if the bit
+ * was cleared before the operation and != 0 if it was not.
+ *
+ * bit 0 is the LSB of addr; bit 32 is the LSB of (addr+1).
+ */
+
+#undef LOAD
+#undef STORE
+#ifdef CONFIG_SMP
+#define LOAD	"lock"
+#define STORE	"unlock"
+#else
+#define LOAD	"ld"
+#define STORE	"st"
+#endif
+
+/* #define ADDR (*(volatile long *) addr) */
+
+/**
+ * set_bit - Atomically set a bit in memory
+ * @nr: the bit to set
+ * @addr: the address to start counting from
+ *
+ * This function is atomic and may not be reordered.  See __set_bit()
+ * if you do not require the atomic guarantees.
+ * Note that @nr may be almost arbitrarily large; this function is not
+ * restricted to acting on a single-word quantity.
+ */
+static inline void set_bit(int nr, volatile void * addr)
+{
+	__u32 mask;
+	volatile __u32 *a = addr;
+	unsigned long flags;
+	unsigned long tmp;
+
+	a += (nr >> 5);
+	mask = (1 << (nr & 0x1F));
+
+	local_irq_save(flags);
+	__asm__ __volatile__ (
+		DCACHE_CLEAR("%0", "r6", "%1")
+		LOAD"	%0, @%1;		\n\t"
+		"or	%0, %2;			\n\t"
+		STORE"	%0, @%1;		\n\t"
+		: "=&r" (tmp)
+		: "r" (a), "r" (mask)
+		: "memory"
+#ifdef CONFIG_CHIP_M32700_TS1
+		, "r6"
+#endif	/* CONFIG_CHIP_M32700_TS1 */
+	);
+	local_irq_restore(flags);
+}
+
+/**
+ * __set_bit - Set a bit in memory
+ * @nr: the bit to set
+ * @addr: the address to start counting from
+ *
+ * Unlike set_bit(), this function is non-atomic and may be reordered.
+ * If it's called on the same region of memory simultaneously, the effect
+ * may be that only one operation succeeds.
+ */
+static inline void __set_bit(int nr, volatile void * addr)
+{
+	__u32 mask;
+	volatile __u32 *a = addr;
+
+	a += (nr >> 5);
+	mask = (1 << (nr & 0x1F));
+	*a |= mask;
+}
+
+/**
+ * clear_bit - Clears a bit in memory
+ * @nr: Bit to clear
+ * @addr: Address to start counting from
+ *
+ * clear_bit() is atomic and may not be reordered.  However, it does
+ * not contain a memory barrier, so if it is used for locking purposes,
+ * you should call smp_mb__before_clear_bit() and/or smp_mb__after_clear_bit()
+ * in order to ensure changes are visible on other processors.
+ */
+static inline void clear_bit(int nr, volatile void * addr)
+{
+	__u32 mask;
+	volatile __u32 *a = addr;
+	unsigned long flags;
+	unsigned long tmp;
+
+	a += (nr >> 5);
+	mask = (1 << (nr & 0x1F));
+
+	local_irq_save(flags);
+
+	__asm__ __volatile__ (
+		DCACHE_CLEAR("%0", "r6", "%1")
+		LOAD"	%0, @%1;		\n\t"
+		"and	%0, %2;			\n\t"
+		STORE"	%0, @%1;		\n\t"
+		: "=&r" (tmp)
+		: "r" (a), "r" (~mask)
+		: "memory"
+#ifdef CONFIG_CHIP_M32700_TS1
+		, "r6"
+#endif	/* CONFIG_CHIP_M32700_TS1 */
+	);
+	local_irq_restore(flags);
+}
+
+static inline void __clear_bit(int nr, volatile unsigned long * addr)
+{
+	unsigned long mask;
+	volatile unsigned long *a = addr;
+
+	a += (nr >> 5);
+	mask = (1 << (nr & 0x1F));
+	*a &= ~mask;
+}
+
+#define smp_mb__before_clear_bit()	barrier()
+#define smp_mb__after_clear_bit()	barrier()
+
+/**
+ * __change_bit - Toggle a bit in memory
+ * @nr: the bit to set
+ * @addr: the address to start counting from
+ *
+ * Unlike change_bit(), this function is non-atomic and may be reordered.
+ * If it's called on the same region of memory simultaneously, the effect
+ * may be that only one operation succeeds.
+ */
+static inline void __change_bit(int nr, volatile void * addr)
+{
+	__u32 mask;
+	volatile __u32 *a = addr;
+
+	a += (nr >> 5);
+	mask = (1 << (nr & 0x1F));
+	*a ^= mask;
+}
+
+/**
+ * change_bit - Toggle a bit in memory
+ * @nr: Bit to clear
+ * @addr: Address to start counting from
+ *
+ * change_bit() is atomic and may not be reordered.
+ * Note that @nr may be almost arbitrarily large; this function is not
+ * restricted to acting on a single-word quantity.
+ */
+static inline void change_bit(int nr, volatile void * addr)
+{
+	__u32  mask;
+	volatile __u32  *a = addr;
+	unsigned long flags;
+	unsigned long tmp;
+
+	a += (nr >> 5);
+	mask = (1 << (nr & 0x1F));
+
+	local_irq_save(flags);
+	__asm__ __volatile__ (
+		DCACHE_CLEAR("%0", "r6", "%1")
+		LOAD"	%0, @%1;		\n\t"
+		"xor	%0, %2;			\n\t"
+		STORE"	%0, @%1;		\n\t"
+		: "=&r" (tmp)
+		: "r" (a), "r" (mask)
+		: "memory"
+#ifdef CONFIG_CHIP_M32700_TS1
+		, "r6"
+#endif	/* CONFIG_CHIP_M32700_TS1 */
+	);
+	local_irq_restore(flags);
+}
+
+/**
+ * test_and_set_bit - Set a bit and return its old value
+ * @nr: Bit to set
+ * @addr: Address to count from
+ *
+ * This operation is atomic and cannot be reordered.
+ * It also implies a memory barrier.
+ */
+static inline int test_and_set_bit(int nr, volatile void * addr)
+{
+	__u32 mask, oldbit;
+	volatile __u32 *a = addr;
+	unsigned long flags;
+	unsigned long tmp;
+
+	a += (nr >> 5);
+	mask = (1 << (nr & 0x1F));
+
+	local_irq_save(flags);
+	__asm__ __volatile__ (
+		DCACHE_CLEAR("%0", "%1", "%2")
+		LOAD"	%0, @%2;		\n\t"
+		"mv	%1, %0;			\n\t"
+		"and	%0, %3;			\n\t"
+		"or	%1, %3;			\n\t"
+		STORE"	%1, @%2;		\n\t"
+		: "=&r" (oldbit), "=&r" (tmp)
+		: "r" (a), "r" (mask)
+		: "memory"
+	);
+	local_irq_restore(flags);
+
+	return (oldbit != 0);
+}
+
+/**
+ * __test_and_set_bit - Set a bit and return its old value
+ * @nr: Bit to set
+ * @addr: Address to count from
+ *
+ * This operation is non-atomic and can be reordered.
+ * If two examples of this operation race, one can appear to succeed
+ * but actually fail.  You must protect multiple accesses with a lock.
+ */
+static inline int __test_and_set_bit(int nr, volatile void * addr)
+{
+	__u32 mask, oldbit;
+	volatile __u32 *a = addr;
+
+	a += (nr >> 5);
+	mask = (1 << (nr & 0x1F));
+	oldbit = (*a & mask);
+	*a |= mask;
+
+	return (oldbit != 0);
+}
+
+/**
+ * test_and_clear_bit - Clear a bit and return its old value
+ * @nr: Bit to set
+ * @addr: Address to count from
+ *
+ * This operation is atomic and cannot be reordered.
+ * It also implies a memory barrier.
+ */
+static inline int test_and_clear_bit(int nr, volatile void * addr)
+{
+	__u32 mask, oldbit;
+	volatile __u32 *a = addr;
+	unsigned long flags;
+	unsigned long tmp;
+
+	a += (nr >> 5);
+	mask = (1 << (nr & 0x1F));
+
+	local_irq_save(flags);
+
+	__asm__ __volatile__ (
+		DCACHE_CLEAR("%0", "%1", "%3")
+		LOAD"	%0, @%3;		\n\t"
+		"mv	%1, %0; \n\t"
+		"and	%0, %2; \n\t"
+		"not	%2, %2; \n\t"
+		"and	%1, %2; \n\t"
+		STORE"	%1, @%3;		\n\t"
+		: "=&r" (oldbit), "=&r" (tmp), "+r" (mask)
+		: "r" (a)
+		: "memory"
+	);
+	local_irq_restore(flags);
+
+	return (oldbit != 0);
+}
+
+/**
+ * __test_and_clear_bit - Clear a bit and return its old value
+ * @nr: Bit to set
+ * @addr: Address to count from
+ *
+ * This operation is non-atomic and can be reordered.
+ * If two examples of this operation race, one can appear to succeed
+ * but actually fail.  You must protect multiple accesses with a lock.
+ */
+static inline int __test_and_clear_bit(int nr, volatile void * addr)
+{
+	__u32 mask, oldbit;
+	volatile __u32 *a = addr;
+
+	a += (nr >> 5);
+	mask = (1 << (nr & 0x1F));
+	oldbit = (*a & mask);
+	*a &= ~mask;
+
+	return (oldbit != 0);
+}
+
+/* WARNING: non atomic and it can be reordered! */
+static inline int __test_and_change_bit(int nr, volatile void * addr)
+{
+	__u32 mask, oldbit;
+	volatile __u32 *a = addr;
+
+	a += (nr >> 5);
+	mask = (1 << (nr & 0x1F));
+	oldbit = (*a & mask);
+	*a ^= mask;
+
+	return (oldbit != 0);
+}
+
+/**
+ * test_and_change_bit - Change a bit and return its old value
+ * @nr: Bit to set
+ * @addr: Address to count from
+ *
+ * This operation is atomic and cannot be reordered.
+ * It also implies a memory barrier.
+ */
+static inline int test_and_change_bit(int nr, volatile void * addr)
+{
+	__u32 mask, oldbit;
+	volatile __u32 *a = addr;
+	unsigned long flags;
+	unsigned long tmp;
+
+	a += (nr >> 5);
+	mask = (1 << (nr & 0x1F));
+
+	local_irq_save(flags);
+	__asm__ __volatile__ (
+		DCACHE_CLEAR("%0", "%1", "%2")
+		LOAD"	%0, @%2;		\n\t"
+		"mv	%1, %0;			\n\t"
+		"and	%0, %3;			\n\t"
+		"xor	%1, %3;			\n\t"
+		STORE"	%1, @%2;		\n\t"
+		: "=&r" (oldbit), "=&r" (tmp)
+		: "r" (a), "r" (mask)
+		: "memory"
+	);
+	local_irq_restore(flags);
+
+	return (oldbit != 0);
+}
+
+#if 0 /* Fool kernel-doc since it doesn't do macros yet */
+/**
+ * test_bit - Determine whether a bit is set
+ * @nr: bit number to test
+ * @addr: Address to start counting from
+ */
+static int test_bit(int nr, const volatile void * addr);
+#endif
+
+static inline int test_bit(int nr, const volatile void * addr)
+{
+	__u32 mask;
+	const volatile __u32 *a = addr;
+
+	a += (nr >> 5);
+	mask = (1 << (nr & 0x1F));
+
+	return ((*a & mask) != 0);
+}
+
+/**
+ * ffz - find first zero in word.
+ * @word: The word to search
+ *
+ * Undefined if no zero exists, so code should check against ~0UL first.
+ */
+static inline unsigned long ffz(unsigned long word)
+{
+	int k;
+
+	word = ~word;
+	k = 0;
+	if (!(word & 0x0000ffff)) { k += 16; word >>= 16; }
+	if (!(word & 0x000000ff)) { k += 8; word >>= 8; }
+	if (!(word & 0x0000000f)) { k += 4; word >>= 4; }
+	if (!(word & 0x00000003)) { k += 2; word >>= 2; }
+	if (!(word & 0x00000001)) { k += 1; }
+
+	return k;
+}
+
+/**
+ * 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.
+ */
+
+#define find_first_zero_bit(addr, size) \
+	find_next_zero_bit((addr), (size), 0)
+
+/**
+ * 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
+ */
+static inline int find_next_zero_bit(void *addr, int size, int offset)
+{
+	unsigned long *p = ((unsigned long *) addr) + (offset >> 5);
+	unsigned long result = offset & ~31UL;
+	unsigned long tmp;
+
+	if (offset >= size)
+		return size;
+	size -= result;
+	offset &= 31UL;
+	if (offset) {
+		tmp = *(p++);
+		tmp |= ~0UL >> (32-offset);
+		if (size < 32)
+			goto found_first;
+		if (~tmp)
+			goto found_middle;
+		size -= 32;
+		result += 32;
+	}
+	while (size & ~31UL) {
+		if (~(tmp = *(p++)))
+			goto found_middle;
+		result += 32;
+		size -= 32;
+	}
+	if (!size)
+		return result;
+	tmp = *p;
+
+found_first:
+	tmp |= ~0UL << size;
+found_middle:
+	return result + ffz(tmp);
+}
+
+/**
+ * __ffs - find first bit in word.
+ * @word: The word to search
+ *
+ * Undefined if no bit exists, so code should check against 0 first.
+ */
+static inline unsigned long __ffs(unsigned long word)
+{
+	int k = 0;
+
+	if (!(word & 0x0000ffff)) { k += 16; word >>= 16; }
+	if (!(word & 0x000000ff)) { k += 8; word >>= 8; }
+	if (!(word & 0x0000000f)) { k += 4; word >>= 4; }
+	if (!(word & 0x00000003)) { k += 2; word >>= 2; }
+	if (!(word & 0x00000001)) { k += 1;}
+
+	return k;
+}
+
+/*
+ * fls: find last bit set.
+ */
+#define fls(x) generic_fls(x)
+
+#ifdef __KERNEL__
+
+/*
+ * Every architecture must define this function. It's the fastest
+ * way of searching a 140-bit bitmap where the first 100 bits are
+ * unlikely to be set. It's guaranteed that at least one of the 140
+ * bits is cleared.
+ */
+static inline int sched_find_first_bit(unsigned long *b)
+{
+	if (unlikely(b[0]))
+		return __ffs(b[0]);
+	if (unlikely(b[1]))
+		return __ffs(b[1]) + 32;
+	if (unlikely(b[2]))
+		return __ffs(b[2]) + 64;
+	if (b[3])
+		return __ffs(b[3]) + 96;
+	return __ffs(b[4]) + 128;
+}
+
+/**
+ * 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
+ */
+static inline unsigned long find_next_bit(const unsigned long *addr,
+	unsigned long size, unsigned long offset)
+{
+	unsigned int *p = ((unsigned int *) addr) + (offset >> 5);
+	unsigned int result = offset & ~31UL;
+	unsigned int tmp;
+
+	if (offset >= size)
+		return size;
+	size -= result;
+	offset &= 31UL;
+	if (offset) {
+		tmp = *p++;
+		tmp &= ~0UL << offset;
+		if (size < 32)
+			goto found_first;
+		if (tmp)
+			goto found_middle;
+		size -= 32;
+		result += 32;
+	}
+	while (size >= 32) {
+		if ((tmp = *p++) != 0)
+			goto found_middle;
+		result += 32;
+		size -= 32;
+	}
+	if (!size)
+		return result;
+	tmp = *p;
+
+found_first:
+	tmp &= ~0UL >> (32 - size);
+	if (tmp == 0UL)        /* Are any bits set? */
+		return result + size; /* Nope. */
+found_middle:
+	return result + __ffs(tmp);
+}
+
+/**
+ * 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.
+ */
+#define find_first_bit(addr, size) \
+	find_next_bit((addr), (size), 0)
+
+/**
+ * ffs - find first bit set
+ * @x: the word to search
+ *
+ * This is defined the same way as
+ * the libc and compiler builtin ffs routines, therefore
+ * differs in spirit from the above ffz (man ffs).
+ */
+#define ffs(x)	generic_ffs(x)
+
+/**
+ * hweightN - returns the hamming weight of a N-bit word
+ * @x: the word to weigh
+ *
+ * The Hamming Weight of a number is the total number of bits set in it.
+ */
+
+#define hweight32(x)	generic_hweight32(x)
+#define hweight16(x)	generic_hweight16(x)
+#define hweight8(x)	generic_hweight8(x)
+
+#endif /* __KERNEL__ */
+
+#ifdef __KERNEL__
+
+/*
+ * ext2_XXXX function
+ * orig: include/asm-sh/bitops.h
+ */
+
+#ifdef __LITTLE_ENDIAN__
+#define ext2_set_bit			test_and_set_bit
+#define ext2_clear_bit			__test_and_clear_bit
+#define ext2_test_bit			test_bit
+#define ext2_find_first_zero_bit	find_first_zero_bit
+#define ext2_find_next_zero_bit		find_next_zero_bit
+#else
+static inline int ext2_set_bit(int nr, volatile void * addr)
+{
+	__u8 mask, oldbit;
+	volatile __u8 *a = addr;
+
+	a += (nr >> 3);
+	mask = (1 << (nr & 0x07));
+	oldbit = (*a & mask);
+	*a |= mask;
+
+	return (oldbit != 0);
+}
+
+static inline int ext2_clear_bit(int nr, volatile void * addr)
+{
+	__u8 mask, oldbit;
+	volatile __u8 *a = addr;
+
+	a += (nr >> 3);
+	mask = (1 << (nr & 0x07));
+	oldbit = (*a & mask);
+	*a &= ~mask;
+
+	return (oldbit != 0);
+}
+
+static inline int ext2_test_bit(int nr, const volatile void * addr)
+{
+	__u32 mask;
+	const volatile __u8 *a = addr;
+
+	a += (nr >> 3);
+	mask = (1 << (nr & 0x07));
+
+	return ((mask & *a) != 0);
+}
+
+#define ext2_find_first_zero_bit(addr, size) \
+	ext2_find_next_zero_bit((addr), (size), 0)
+
+static inline unsigned long ext2_find_next_zero_bit(void *addr,
+	unsigned long size, unsigned long offset)
+{
+	unsigned long *p = ((unsigned long *) addr) + (offset >> 5);
+	unsigned long result = offset & ~31UL;
+	unsigned long tmp;
+
+	if (offset >= size)
+		return size;
+	size -= result;
+	offset &= 31UL;
+	if(offset) {
+		/* We hold the little endian value in tmp, but then the
+		 * shift is illegal. So we could keep a big endian value
+		 * in tmp, like this:
+		 *
+		 * tmp = __swab32(*(p++));
+		 * tmp |= ~0UL >> (32-offset);
+		 *
+		 * but this would decrease preformance, so we change the
+		 * shift:
+		 */
+		tmp = *(p++);
+		tmp |= __swab32(~0UL >> (32-offset));
+		if(size < 32)
+			goto found_first;
+		if(~tmp)
+			goto found_middle;
+		size -= 32;
+		result += 32;
+	}
+	while(size & ~31UL) {
+		if(~(tmp = *(p++)))
+			goto found_middle;
+		result += 32;
+		size -= 32;
+	}
+	if(!size)
+		return result;
+	tmp = *p;
+
+found_first:
+	/* tmp is little endian, so we would have to swab the shift,
+	 * see above. But then we have to swab tmp below for ffz, so
+	 * we might as well do this here.
+	 */
+	return result + ffz(__swab32(tmp) | (~0UL << size));
+found_middle:
+	return result + ffz(__swab32(tmp));
+}
+#endif
+
+#define ext2_set_bit_atomic(lock, nr, addr)		\
+	({						\
+		int ret;				\
+		spin_lock(lock);			\
+		ret = ext2_set_bit((nr), (addr));	\
+		spin_unlock(lock);			\
+		ret;					\
+	})
+
+#define ext2_clear_bit_atomic(lock, nr, addr)		\
+	({						\
+		int ret;				\
+		spin_lock(lock);			\
+		ret = ext2_clear_bit((nr), (addr));	\
+		spin_unlock(lock);			\
+		ret;					\
+	})
+
+/* Bitmap functions for the minix filesystem.  */
+#define minix_test_and_set_bit(nr,addr)		__test_and_set_bit(nr,addr)
+#define minix_set_bit(nr,addr)			__set_bit(nr,addr)
+#define minix_test_and_clear_bit(nr,addr)	__test_and_clear_bit(nr,addr)
+#define minix_test_bit(nr,addr) test_bit(nr,addr)
+#define minix_find_first_zero_bit(addr,size)	find_first_zero_bit(addr,size)
+
+#endif /* __KERNEL__ */
+
+#endif /* _ASM_M32R_BITOPS_H */
diff -Nru a/include/asm-m32r/bug.h b/include/asm-m32r/bug.h
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/include/asm-m32r/bug.h	2004-10-18 14:57:21 -07:00
@@ -0,0 +1,22 @@
+#ifndef _M32R_BUG_H
+#define _M32R_BUG_H
+
+#define BUG()	do { \
+	printk("kernel BUG at %s:%d!\n", __FILE__, __LINE__); \
+} while (0)
+
+#define PAGE_BUG(page)	do { BUG(); } while (0)
+
+#define BUG_ON(condition) \
+	do { if (unlikely((condition)!=0)) BUG(); } while(0)
+
+#define WARN_ON(condition) do { \
+	if (unlikely((condition)!=0)) { \
+		printk("Badness in %s at %s:%d\n", __FUNCTION__, \
+		__FILE__, __LINE__); \
+		dump_stack(); \
+	} \
+} while (0)
+
+#endif /* _M32R_BUG_H */
+
diff -Nru a/include/asm-m32r/bugs.h b/include/asm-m32r/bugs.h
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/include/asm-m32r/bugs.h	2004-10-18 14:57:21 -07:00
@@ -0,0 +1,21 @@
+#ifndef _ASM_M32R_BUGS_H
+#define _ASM_M32R_BUGS_H
+
+/* $Id$ */
+
+/*
+ * This is included by init/main.c to check for architecture-dependent bugs.
+ *
+ * Needs:
+ *     void check_bugs(void);
+ */
+#include <asm/processor.h>
+
+static void __init check_bugs(void)
+{
+	extern unsigned long loops_per_jiffy;
+
+	current_cpu_data.loops_per_jiffy = loops_per_jiffy;
+}
+
+#endif  /* _ASM_M32R_BUGS_H */
diff -Nru a/include/asm-m32r/byteorder.h b/include/asm-m32r/byteorder.h
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/include/asm-m32r/byteorder.h	2004-10-18 14:57:24 -07:00
@@ -0,0 +1,19 @@
+#ifndef _ASM_M32R_BYTEORDER_H
+#define _ASM_M32R_BYTEORDER_H
+
+/* $Id$ */
+
+#include <asm/types.h>
+
+#if !defined(__STRICT_ANSI__) || defined(__KERNEL__)
+#  define __BYTEORDER_HAS_U64__
+#  define __SWAB_64_THRU_32__
+#endif
+
+#if defined(__LITTLE_ENDIAN__)
+#  include <linux/byteorder/little_endian.h>
+#else
+#  include <linux/byteorder/big_endian.h>
+#endif
+
+#endif /* _ASM_M32R_BYTEORDER_H */
diff -Nru a/include/asm-m32r/cache.h b/include/asm-m32r/cache.h
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/include/asm-m32r/cache.h	2004-10-18 14:57:23 -07:00
@@ -0,0 +1,12 @@
+#ifndef _ASM_M32R_CACHE_H
+#define _ASM_M32R_CACHE_H
+
+/* $Id$ */
+
+/* L1 cache line size */
+#define L1_CACHE_SHIFT		4
+#define L1_CACHE_BYTES		(1 << L1_CACHE_SHIFT)
+
+#define L1_CACHE_SHIFT_MAX	4
+
+#endif  /* _ASM_M32R_CACHE_H */
diff -Nru a/include/asm-m32r/cachectl.h b/include/asm-m32r/cachectl.h
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/include/asm-m32r/cachectl.h	2004-10-18 14:57:24 -07:00
@@ -0,0 +1,26 @@
+/*
+ * cachectl.h -- defines for M32R cache control system calls
+ *
+ * Copyright (C) 2003 by Kazuhiro Inaoka
+ */
+#ifndef	__ASM_M32R_CACHECTL
+#define	__ASM_M32R_CACHECTL
+
+/*
+ * Options for cacheflush system call
+ *
+ * cacheflush() is currently fluch_cache_all().
+ */
+#define	ICACHE	(1<<0)		/* flush instruction cache        */
+#define	DCACHE	(1<<1)		/* writeback and flush data cache */
+#define	BCACHE	(ICACHE|DCACHE)	/* flush both caches              */
+
+/*
+ * Caching modes for the cachectl(2) call
+ *
+ * cachectl(2) is currently not supported and returns ENOSYS.
+ */
+#define CACHEABLE	0	/* make pages cacheable */
+#define UNCACHEABLE	1	/* make pages uncacheable */
+
+#endif	/* __ASM_M32R_CACHECTL */
diff -Nru a/include/asm-m32r/cacheflush.h b/include/asm-m32r/cacheflush.h
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/include/asm-m32r/cacheflush.h	2004-10-18 14:57:23 -07:00
@@ -0,0 +1,68 @@
+#ifndef _ASM_M32R_CACHEFLUSH_H
+#define _ASM_M32R_CACHEFLUSH_H
+
+#include <linux/config.h>
+#include <linux/mm.h>
+
+extern void _flush_cache_all(void);
+extern void _flush_cache_copyback_all(void);
+
+#if defined(CONFIG_CHIP_M32700) || defined(CONFIG_CHIP_OPSP)
+#define flush_cache_all()			do { } while (0)
+#define flush_cache_mm(mm)			do { } while (0)
+#define flush_cache_range(vma, start, end)	do { } while (0)
+#define flush_cache_page(vma, vmaddr)		do { } while (0)
+#define flush_dcache_page(page)			do { } while (0)
+#define flush_dcache_mmap_lock(mapping)		do { } while (0)
+#define flush_dcache_mmap_unlock(mapping)	do { } while (0)
+#ifndef CONFIG_SMP
+#define flush_icache_range(start, end)		_flush_cache_copyback_all()
+#define flush_icache_page(vma,pg)		_flush_cache_copyback_all()
+#define flush_icache_user_range(vma,pg,adr,len)	_flush_cache_copyback_all()
+#define flush_cache_sigtramp(addr)		_flush_cache_copyback_all()
+#else	/* CONFIG_SMP */
+extern void smp_flush_cache_all(void);
+#define flush_icache_range(start, end)		smp_flush_cache_all()
+#define flush_icache_page(vma,pg)		smp_flush_cache_all()
+#define flush_icache_user_range(vma,pg,adr,len)	smp_flush_cache_all()
+#define flush_cache_sigtramp(addr)		_flush_cache_copyback_all()
+#endif	/* CONFIG_SMP */
+#elif defined(CONFIG_CHIP_M32102)
+#define flush_cache_all()			do { } while (0)
+#define flush_cache_mm(mm)			do { } while (0)
+#define flush_cache_range(vma, start, end)	do { } while (0)
+#define flush_cache_page(vma, vmaddr)		do { } while (0)
+#define flush_dcache_page(page)			do { } while (0)
+#define flush_dcache_mmap_lock(mapping)		do { } while (0)
+#define flush_dcache_mmap_unlock(mapping)	do { } while (0)
+#define flush_icache_range(start, end)		_flush_cache_all()
+#define flush_icache_page(vma,pg)		_flush_cache_all()
+#define flush_icache_user_range(vma,pg,adr,len)	_flush_cache_all()
+#define flush_cache_sigtramp(addr)		_flush_cache_all()
+#else
+#define flush_cache_all()			do { } while (0)
+#define flush_cache_mm(mm)			do { } while (0)
+#define flush_cache_range(vma, start, end)	do { } while (0)
+#define flush_cache_page(vma, vmaddr)		do { } while (0)
+#define flush_dcache_page(page)			do { } while (0)
+#define flush_dcache_mmap_lock(mapping)		do { } while (0)
+#define flush_dcache_mmap_unlock(mapping)	do { } while (0)
+#define flush_icache_range(start, end)		do { } while (0)
+#define flush_icache_page(vma,pg)		do { } while (0)
+#define flush_icache_user_range(vma,pg,adr,len)	do { } while (0)
+#define flush_cache_sigtramp(addr)		do { } while (0)
+#endif	/* CONFIG_CHIP_* */
+
+#define flush_cache_vmap(start, end)	do { } while (0)
+#define flush_cache_vunmap(start, end)	do { } while (0)
+
+#define copy_to_user_page(vma, page, vaddr, dst, src, len)	\
+do {								\
+	memcpy(dst, src, len);					\
+	flush_icache_user_range(vma, page, vaddr, len);		\
+} while (0)
+#define copy_from_user_page(vma, page, vaddr, dst, src, len)	\
+	memcpy(dst, src, len)
+
+#endif /* _ASM_M32R_CACHEFLUSH_H */
+
diff -Nru a/include/asm-m32r/checksum.h b/include/asm-m32r/checksum.h
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/include/asm-m32r/checksum.h	2004-10-18 14:57:21 -07:00
@@ -0,0 +1,206 @@
+#ifdef __KERNEL__
+#ifndef _ASM_M32R_CHECKSUM_H
+#define _ASM_M32R_CHECKSUM_H
+
+/*
+ * include/asm-m32r/checksum.h
+ *
+ * IP/TCP/UDP checksum routines
+ *
+ * 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.
+ *
+ * Some code taken from mips and parisc architecture.
+ *
+ *    Copyright (C) 2001, 2002  Hiroyuki Kondo, Hirokazu Takata
+ *    Copyright (C) 2004  Hirokazu Takata <takata at linux-m32r.org>
+ */
+
+#include <linux/in6.h>
+
+/*
+ * computes the checksum of a memory block at buff, length len,
+ * and adds in "sum" (32-bit)
+ *
+ * returns a 32-bit number suitable for feeding into itself
+ * or csum_tcpudp_magic
+ *
+ * this function must be called with even lengths, except
+ * for the last fragment, which may be odd
+ *
+ * it's best to have buff aligned on a 32-bit boundary
+ */
+asmlinkage unsigned int csum_partial(const unsigned char *buff, int len, unsigned int sum);
+
+/*
+ * The same as csum_partial, but copies from src while it checksums.
+ *
+ * Here even more important to align src and dst on a 32-bit (or even
+ * better 64-bit) boundary
+ */
+extern unsigned int csum_partial_copy_nocheck(const char *src, char *dst,
+                                              int len, unsigned int sum);
+
+/*
+ * This is a new version of the above that records errors it finds in *errp,
+ * but continues and zeros thre rest of the buffer.
+ */
+extern unsigned int csum_partial_copy_from_user(const char __user *src,
+                                                char *dst,
+                                                int len, unsigned int sum,
+                                                int *err_ptr);
+
+/*
+ *	Fold a partial checksum
+ */
+
+static inline unsigned int csum_fold(unsigned int sum)
+{
+	unsigned long tmpreg;
+	__asm__(
+		"	sll3	%1, %0, #16 \n"
+		"	cmp	%0, %0 \n"
+		"	addx	%0, %1 \n"
+		"	ldi	%1, #0 \n"
+		"	srli	%0, #16 \n"
+		"	addx	%0, %1 \n"
+		"	xor3	%0, %0, #0x0000ffff \n"
+		: "=r" (sum), "=&r" (tmpreg)
+		: "0"  (sum)
+		: "cbit"
+	);
+	return sum;
+}
+
+/*
+ * This is a version of ip_compute_csum() optimized for IP headers,
+ * which always checksum on 4 octet boundaries.
+ */
+static inline unsigned short ip_fast_csum(unsigned char * iph,
+					  unsigned int ihl) {
+	unsigned long sum, tmpreg0, tmpreg1;
+
+	__asm__ __volatile__(
+		"	ld	%0, @%1+ \n"
+		"	addi	%2, #-4 \n"
+		"#	bgez	%2, 2f \n"
+		"	cmp	%0, %0 \n"
+		"	ld	%3, @%1+ \n"
+		"	ld	%4, @%1+ \n"
+		"	addx	%0, %3 \n"
+		"	ld	%3, @%1+ \n"
+		"	addx	%0, %4 \n"
+		"	addx	%0, %3 \n"
+		"	.fillinsn\n"
+		"1: \n"
+		"	ld	%4, @%1+ \n"
+		"	addi	%2, #-1 \n"
+		"	addx	%0, %4 \n"
+		"	bgtz	%2, 1b \n"
+		"\n"
+		"	ldi	%3, #0 \n"
+		"	addx	%0, %3 \n"
+		"	.fillinsn\n"
+		"2: \n"
+	/* Since the input registers which are loaded with iph and ipl
+	   are modified, we must also specify them as outputs, or gcc
+	   will assume they contain their original values. */
+	: "=&r" (sum), "=r" (iph), "=r" (ihl), "=&r" (tmpreg0), "=&r" (tmpreg1)
+	: "1" (iph), "2" (ihl)
+	: "cbit", "memory");
+
+	return csum_fold(sum);
+}
+
+static inline unsigned long csum_tcpudp_nofold(unsigned long saddr,
+					       unsigned long daddr,
+					       unsigned short len,
+					       unsigned short proto,
+					       unsigned int sum)
+{
+#if defined(__LITTLE_ENDIAN)
+	unsigned long len_proto = (ntohs(len)<<16)+proto*256;
+#else
+	unsigned long len_proto = (proto<<16)+len;
+#endif
+	unsigned long tmpreg;
+
+	__asm__(
+		"	cmp	%0, %0 \n"
+		"	addx	%0, %2 \n"
+		"	addx	%0, %3 \n"
+		"	addx	%0, %4 \n"
+		"	ldi	%1, #0 \n"
+		"	addx	%0, %1 \n"
+		: "=r" (sum), "=&r" (tmpreg)
+		: "r" (daddr), "r" (saddr), "r" (len_proto), "0" (sum)
+		: "cbit"
+	);
+
+	return sum;
+}
+
+/*
+ * computes the checksum of the TCP/UDP pseudo-header
+ * returns a 16-bit checksum, already complemented
+ */
+static inline unsigned short int csum_tcpudp_magic(unsigned long saddr,
+						   unsigned long daddr,
+						   unsigned short len,
+						   unsigned short proto,
+						   unsigned int sum)
+{
+	return csum_fold(csum_tcpudp_nofold(saddr,daddr,len,proto,sum));
+}
+
+/*
+ * this routine is used for miscellaneous IP-like checksums, mainly
+ * in icmp.c
+ */
+
+static inline unsigned short ip_compute_csum(unsigned char * buff, int len) {
+	return csum_fold (csum_partial(buff, len, 0));
+}
+
+#define _HAVE_ARCH_IPV6_CSUM
+static inline unsigned short int csum_ipv6_magic(struct in6_addr *saddr,
+						 struct in6_addr *daddr,
+						 __u16 len,
+						 unsigned short proto,
+						 unsigned int sum)
+{
+	unsigned long tmpreg0, tmpreg1, tmpreg2, tmpreg3;
+	__asm__(
+		"	ld	%1, @(%5) \n"
+		"	ld	%2, @(4,%5) \n"
+		"	ld	%3, @(8,%5) \n"
+		"	ld	%4, @(12,%5) \n"
+		"	add	%0, %1 \n"
+		"	addx	%0, %2 \n"
+		"	addx	%0, %3 \n"
+		"	addx	%0, %4 \n"
+		"	ld	%1, @(%6) \n"
+		"	ld	%2, @(4,%6) \n"
+		"	ld	%3, @(8,%6) \n"
+		"	ld	%4, @(12,%6) \n"
+		"	addx	%0, %1 \n"
+		"	addx	%0, %2 \n"
+		"	addx	%0, %3 \n"
+		"	addx	%0, %4 \n"
+		"	addx	%0, %7 \n"
+		"	addx	%0, %8 \n"
+		"	ldi	%1, #0 \n"
+		"	addx	%0, %1 \n"
+		: "=&r" (sum), "=&r" (tmpreg0), "=&r" (tmpreg1),
+		  "=&r" (tmpreg2), "=&r" (tmpreg3)
+		: "r" (saddr), "r" (daddr),
+		  "r" (htonl((__u32) (len))), "r" (htonl(proto)), "0" (sum)
+		: "cbit"
+	);
+
+	return csum_fold(sum);
+}
+
+#endif /* _ASM_M32R_CHECKSUM_H */
+#endif /* __KERNEL__ */
diff -Nru a/include/asm-m32r/current.h b/include/asm-m32r/current.h
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/include/asm-m32r/current.h	2004-10-18 14:57:22 -07:00
@@ -0,0 +1,18 @@
+#ifndef _ASM_M32R_CURRENT_H
+#define _ASM_M32R_CURRENT_H
+
+/* $Id$ */
+
+#include <linux/thread_info.h>
+
+struct task_struct;
+
+static __inline__ struct task_struct *get_current(void)
+{
+	return current_thread_info()->task;
+}
+
+#define current	(get_current())
+
+#endif	/* _ASM_M32R_CURRENT_H */
+
diff -Nru a/include/asm-m32r/delay.h b/include/asm-m32r/delay.h
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/include/asm-m32r/delay.h	2004-10-18 14:57:22 -07:00
@@ -0,0 +1,28 @@
+#ifndef _ASM_M32R_DELAY_H
+#define _ASM_M32R_DELAY_H
+
+/* $Id$ */
+
+/*
+ * Copyright (C) 1993 Linus Torvalds
+ *
+ * Delay routines calling functions in arch/m32r/lib/delay.c
+ */
+
+extern void __bad_udelay(void);
+extern void __bad_ndelay(void);
+
+extern void __udelay(unsigned long usecs);
+extern void __ndelay(unsigned long nsecs);
+extern void __const_udelay(unsigned long usecs);
+extern void __delay(unsigned long loops);
+
+#define udelay(n) (__builtin_constant_p(n) ? \
+	((n) > 20000 ? __bad_udelay() : __const_udelay((n) * 0x10c7ul)) : \
+	__udelay(n))
+
+#define ndelay(n) (__builtin_constant_p(n) ? \
+	((n) > 20000 ? __bad_ndelay() : __const_udelay((n) * 5ul)) : \
+	__ndelay(n))
+
+#endif /* _ASM_M32R_DELAY_H */
diff -Nru a/include/asm-m32r/div64.h b/include/asm-m32r/div64.h
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/include/asm-m32r/div64.h	2004-10-18 14:57:21 -07:00
@@ -0,0 +1,38 @@
+#ifndef _ASM_M32R_DIV64
+#define _ASM_M32R_DIV64
+
+/* $Id$ */
+
+/* unsigned long long division.
+ * Input:
+ *  unsigned long long  n
+ *  unsigned long  base
+ * Output:
+ *  n = n / base;
+ *  return value = n % base;
+ */
+#define do_div(n, base)						\
+({								\
+	unsigned long _res, _high, _mid, _low;			\
+								\
+	_low = (n) & 0xffffffffUL;				\
+	_high = (n) >> 32;					\
+	if (_high) {						\
+		_mid = (_high % (unsigned long)(base)) << 16;	\
+		_high = _high / (unsigned long)(base);		\
+		_mid += _low >> 16;				\
+		_low &= 0x0000ffffUL;				\
+		_low += (_mid % (unsigned long)(base)) << 16;	\
+		_mid = _mid / (unsigned long)(base);		\
+		_res = _low % (unsigned long)(base);		\
+		_low = _low / (unsigned long)(base);		\
+		n = _low + ((long long)_mid << 16) +		\
+			((long long)_high << 32);		\
+	} else {						\
+		_res = _low % (unsigned long)(base);		\
+		n = (_low / (unsigned long)(base));		\
+	}							\
+	_res;							\
+})
+
+#endif  /* _ASM_M32R_DIV64 */
diff -Nru a/include/asm-m32r/dma-mapping.h b/include/asm-m32r/dma-mapping.h
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/include/asm-m32r/dma-mapping.h	2004-10-18 14:57:21 -07:00
@@ -0,0 +1,23 @@
+#ifndef _ASM_M32R_DMA_MAPPING_H
+#define _ASM_M32R_DMA_MAPPING_H
+
+/*
+ * NOTE: Do not include <asm-generic/dma-mapping.h>
+ * Because it requires PCI stuffs, but current M32R don't provide these.
+ */
+
+static inline void *
+dma_alloc_coherent(struct device *dev, size_t size, dma_addr_t *dma_handle,
+		   int flag)
+{
+	return (void *)NULL;
+}
+
+static inline void
+dma_free_coherent(struct device *dev, size_t size, void *cpu_addr,
+		    dma_addr_t dma_handle)
+{
+	return;
+}
+
+#endif /* _ASM_M32R_DMA_MAPPING_H */
diff -Nru a/include/asm-m32r/dma.h b/include/asm-m32r/dma.h
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/include/asm-m32r/dma.h	2004-10-18 14:57:23 -07:00
@@ -0,0 +1,14 @@
+#ifndef _ASM_M32R_DMA_H
+#define _ASM_M32R_DMA_H
+
+/* $Id$ */
+
+#include <asm/io.h>
+
+/*
+ * The maximum address that we can perform a DMA transfer
+ * to on this platform
+ */
+#define MAX_DMA_ADDRESS      (PAGE_OFFSET+0x20000000)
+
+#endif /* _ASM_M32R_DMA_H */
diff -Nru a/include/asm-m32r/elf.h b/include/asm-m32r/elf.h
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/include/asm-m32r/elf.h	2004-10-18 14:57:23 -07:00
@@ -0,0 +1,172 @@
+#ifndef _ASM_M32R__ELF_H
+#define _ASM_M32R__ELF_H
+
+/*
+ * ELF-specific definitions.
+ *
+ * Copyright (C) 1999-2004, Renesas Technology Corp.
+ *      Hirokazu Takata <takata at linux-m32r.org>
+ */
+
+#include <asm/ptrace.h>
+#include <asm/user.h>
+#include <asm/page.h>
+
+/* M32R relocation types  */
+#define	R_M32R_NONE		0
+#define	R_M32R_16		1
+#define	R_M32R_32		2
+#define	R_M32R_24		3
+#define	R_M32R_10_PCREL		4
+#define	R_M32R_18_PCREL		5
+#define	R_M32R_26_PCREL		6
+#define	R_M32R_HI16_ULO		7
+#define	R_M32R_HI16_SLO		8
+#define	R_M32R_LO16		9
+#define	R_M32R_SDA16		10
+#ifdef OLD_TYPE
+#define	R_M32R_GOT24		11
+#define	R_M32R_26_PLTREL	12
+#define	R_M32R_GOT16_HI_ULO	13
+#define	R_M32R_GOT16_HI_SLO	14
+#define	R_M32R_GOT16_LO		15
+#define	R_M32R_GOTPC24		16
+#define	R_M32R_COPY		17
+#define	R_M32R_GLOB_DAT		18
+#define	R_M32R_JMP_SLOT		19
+#define	R_M32R_RELATIVE		20
+#define	R_M32R_GNU_VTINHERIT	21
+#define	R_M32R_GNU_VTENTRY	22
+
+#define R_M32R_16_RELA		R_M32R_16
+#define R_M32R_32_RELA		R_M32R_32
+#define R_M32R_24_RELA		R_M32R_24
+#define R_M32R_10_PCREL_RELA	R_M32R_10_PCREL
+#define R_M32R_18_PCREL_RELA	R_M32R_18_PCREL
+#define R_M32R_26_PCREL_RELA	R_M32R_26_PCREL
+#define R_M32R_HI16_ULO_RELA	R_M32R_HI16_ULO
+#define R_M32R_HI16_SLO_RELA	R_M32R_HI16_SLO
+#define R_M32R_LO16_RELA	R_M32R_LO16
+#define R_M32R_SDA16_RELA	R_M32R_SDA16
+#else /* not OLD_TYPE */
+#define	R_M32R_GNU_VTINHERIT	11
+#define	R_M32R_GNU_VTENTRY	12
+
+#define	R_M32R_GOT24_SAMPLE		11 /* comflict */
+#define	R_M32R_26_PLTREL_SAMPLE	12 /* comflict */
+#define	R_M32R_GOT16_HI_ULO_SAMPLE	13
+#define	R_M32R_GOT16_HI_SLO_SAMPLE	14
+#define	R_M32R_GOT16_LO_SAMPLE		15
+#define	R_M32R_GOTPC24_SAMPLE		16
+#define	R_M32R_COPY_SAMPLE		17
+#define	R_M32R_GLOB_DAT_SAMPLE		18
+#define	R_M32R_JMP_SLOT_SAMPLE		19
+#define	R_M32R_RELATIVE_SAMPLE		20
+#define	R_M32R_GNU_VTINHERIT_SAMPLE	21
+#define	R_M32R_GNU_VTENTRY_SAMPLE	22
+
+#define R_M32R_16_RELA		33
+#define R_M32R_32_RELA		34
+#define R_M32R_24_RELA		35
+#define R_M32R_10_PCREL_RELA	36
+#define R_M32R_18_PCREL_RELA	37
+#define R_M32R_26_PCREL_RELA	38
+#define R_M32R_HI16_ULO_RELA	39
+#define R_M32R_HI16_SLO_RELA	40
+#define R_M32R_LO16_RELA	41
+#define R_M32R_SDA16_RELA	42
+#define	R_M32R_RELA_GNU_VTINHERIT	43
+#define	R_M32R_RELA_GNU_VTENTRY	44
+
+#define R_M32R_GOT24		48
+#define R_M32R_26_PLTREL	49
+#define R_M32R_COPY		50
+#define R_M32R_GLOB_DAT		51
+#define R_M32R_JMP_SLOT		52
+#define R_M32R_RELATIVE		53
+#define R_M32R_GOTOFF		54
+#define R_M32R_GOTPC24		55
+#define R_M32R_GOT16_HI_ULO	56
+#define R_M32R_GOT16_HI_SLO	57
+#define R_M32R_GOT16_LO		58
+#define R_M32R_GOTPC_HI_ULO	59
+#define R_M32R_GOTPC_HI_SLO	60
+#define R_M32R_GOTPC_LO		61
+#endif /* not OLD_TYPE */
+
+#define R_M32R_NUM		256
+
+/*
+ * ELF register definitions..
+ */
+#define ELF_NGREG (sizeof (struct pt_regs) / sizeof(elf_greg_t))
+
+typedef unsigned long elf_greg_t;
+typedef elf_greg_t elf_gregset_t[ELF_NGREG];
+
+/* We have no FP mumumu.  */
+typedef double elf_fpreg_t;
+typedef elf_fpreg_t elf_fpregset_t;
+
+/*
+ * This is used to ensure we don't load something for the wrong architecture.
+ */
+#define elf_check_arch(x) \
+	(((x)->e_machine == EM_M32R) || ((x)->e_machine == EM_CYGNUS_M32R))
+
+/*
+ * These are used to set parameters in the core dumps.
+ */
+#define ELF_CLASS	ELFCLASS32
+#if defined(__LITTLE_ENDIAN)
+#define ELF_DATA	ELFDATA2LSB
+#elif defined(__BIG_ENDIAN)
+#define ELF_DATA	ELFDATA2MSB
+#else
+#error no endian defined
+#endif
+#define ELF_ARCH	EM_M32R
+
+/* r0 is set by ld.so to a pointer to a function which might be
+ * registered using 'atexit'.  This provides a mean for the dynamic
+ * linker to call DT_FINI functions for shared libraries that have
+ * been loaded before the code runs.
+ *
+ * So that we can use the same startup file with static executables,
+ * we start programs with a value of 0 to indicate that there is no
+ * such function.
+ */
+#define ELF_PLAT_INIT(_r, load_addr)	(_r)->r0 = 0
+
+#define USE_ELF_CORE_DUMP
+#define ELF_EXEC_PAGESIZE	PAGE_SIZE
+
+/*
+ * This is the location that an ET_DYN program is loaded if exec'ed.
+ * Typical use of this is to invoke "./ld.so someprog" to test out a
+ * new version of the loader.  We need to make sure that it is out of
+ * the way of the program that it will "exec", and that there is
+ * sufficient room for the brk.
+ */
+#define ELF_ET_DYN_BASE         (TASK_SIZE / 3 * 2)
+
+/* regs is struct pt_regs, pr_reg is elf_gregset_t (which is
+   now struct_user_regs, they are different) */
+
+#define ELF_CORE_COPY_REGS(pr_reg, regs)  \
+	memcpy((char *)&pr_reg, (char *)&regs, sizeof (struct pt_regs));
+
+/* This yields a mask that user programs can use to figure out what
+   instruction set this CPU supports.  */
+#define ELF_HWCAP	(0)
+
+/* This yields a string that ld.so will use to load implementation
+   specific libraries for optimization.  This is more specific in
+   intent than poking at uname or /proc/cpuinfo.  */
+#define ELF_PLATFORM	(NULL)
+
+#ifdef __KERNEL__
+#define SET_PERSONALITY(ex, ibcs2) set_personality(PER_LINUX)
+#endif
+
+#endif  /* _ASM_M32R__ELF_H */
diff -Nru a/include/asm-m32r/errno.h b/include/asm-m32r/errno.h
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/include/asm-m32r/errno.h	2004-10-18 14:57:23 -07:00
@@ -0,0 +1,9 @@
+#ifndef _ASM_M32R_ERRNO_H
+#define _ASM_M32R_ERRNO_H
+
+/* $Id$ */
+
+#include <asm-generic/errno.h>
+
+#endif /* _ASM_M32R_ERRNO_H */
+
diff -Nru a/include/asm-m32r/fcntl.h b/include/asm-m32r/fcntl.h
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/include/asm-m32r/fcntl.h	2004-10-18 14:57:21 -07:00
@@ -0,0 +1,92 @@
+#ifndef _ASM_M32R_FCNTL_H
+#define _ASM_M32R_FCNTL_H
+
+/* $Id$ */
+
+/* orig : i386 2.4.18 */
+
+/* open/fcntl - O_SYNC is only implemented on blocks devices and on files
+   located on an ext2 file system */
+#define O_ACCMODE	   0003
+#define O_RDONLY	     00
+#define O_WRONLY	     01
+#define O_RDWR		     02
+#define O_CREAT		   0100	/* not fcntl */
+#define O_EXCL		   0200	/* not fcntl */
+#define O_NOCTTY	   0400	/* not fcntl */
+#define O_TRUNC		  01000	/* not fcntl */
+#define O_APPEND	  02000
+#define O_NONBLOCK	  04000
+#define O_NDELAY	O_NONBLOCK
+#define O_SYNC		 010000
+#define FASYNC		 020000	/* fcntl, for BSD compatibility */
+#define O_DIRECT	 040000	/* direct disk access hint */
+#define O_LARGEFILE	0100000
+#define O_DIRECTORY	0200000	/* must be a directory */
+#define O_NOFOLLOW	0400000 /* don't follow links */
+#define O_NOATIME	01000000
+
+#define F_DUPFD		0	/* dup */
+#define F_GETFD		1	/* get close_on_exec */
+#define F_SETFD		2	/* set/clear close_on_exec */
+#define F_GETFL		3	/* get file->f_flags */
+#define F_SETFL		4	/* set file->f_flags */
+#define F_GETLK		5
+#define F_SETLK		6
+#define F_SETLKW	7
+
+#define F_SETOWN	8	/*  for sockets. */
+#define F_GETOWN	9	/*  for sockets. */
+#define F_SETSIG	10	/*  for sockets. */
+#define F_GETSIG	11	/*  for sockets. */
+
+#define F_GETLK64	12	/*  using 'struct flock64' */
+#define F_SETLK64	13
+#define F_SETLKW64	14
+
+/* for F_[GET|SET]FL */
+#define FD_CLOEXEC	1	/* actually anything with low bit set goes */
+
+/* for posix fcntl() and lockf() */
+#define F_RDLCK		0
+#define F_WRLCK		1
+#define F_UNLCK		2
+
+/* for old implementation of bsd flock () */
+#define F_EXLCK		4	/* or 3 */
+#define F_SHLCK		8	/* or 4 */
+
+/* for leases */
+#define F_INPROGRESS	16
+
+/* operations for bsd flock(), also used by the kernel implementation */
+#define LOCK_SH		1	/* shared lock */
+#define LOCK_EX		2	/* exclusive lock */
+#define LOCK_NB		4	/* or'd with one of the above to prevent
+				   blocking */
+#define LOCK_UN		8	/* remove lock */
+
+#define LOCK_MAND	32	/* This is a mandatory flock */
+#define LOCK_READ	64	/* ... Which allows concurrent read operations */
+#define LOCK_WRITE	128	/* ... Which allows concurrent write operations */
+#define LOCK_RW		192	/* ... Which allows concurrent read & write ops */
+
+struct flock {
+	short l_type;
+	short l_whence;
+	off_t l_start;
+	off_t l_len;
+	pid_t l_pid;
+};
+
+struct flock64 {
+	short  l_type;
+	short  l_whence;
+	loff_t l_start;
+	loff_t l_len;
+	pid_t  l_pid;
+};
+
+#define F_LINUX_SPECIFIC_BASE	1024
+
+#endif  /* _ASM_M32R_FCNTL_H */
diff -Nru a/include/asm-m32r/flat.h b/include/asm-m32r/flat.h
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/include/asm-m32r/flat.h	2004-10-18 14:57:23 -07:00
@@ -0,0 +1,145 @@
+/*
+ * include/asm-m32r/flat.h
+ *
+ * uClinux flat-format executables
+ *
+ * Copyright (C) 2004  Kazuhiro Inaoka
+ *
+ * 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.
+ */
+#ifndef __ASM_M32R_FLAT_H
+#define __ASM_M32R_FLAT_H
+
+#define	flat_stack_align(sp)		(*sp += (*sp & 3 ? (4 - (*sp & 3)): 0))
+#define	flat_argvp_envp_on_stack()		0
+#define	flat_old_ram_flag(flags)		(flags)
+#define	flat_reloc_valid(reloc, size)		\
+	(((reloc) - textlen_for_m32r_lo16_data) <= (size))
+#define flat_get_addr_from_rp(rp, relval, flags) \
+	m32r_flat_get_addr_from_rp(rp, relval, (text_len) )
+
+#define flat_put_addr_at_rp(rp, addr, relval) \
+	m32r_flat_put_addr_at_rp(rp, addr, relval)
+
+/* Convert a relocation entry into an address.  */
+static inline unsigned long
+flat_get_relocate_addr (unsigned long relval)
+{
+        return relval & 0x00ffffff; /* Mask out top 8-bits */
+}
+
+#define	flat_m32r_get_reloc_type(relval)	((relval) >> 24)
+
+#define M32R_SETH_OPCODE	0xd0c00000 /* SETH instruction code */
+
+#define FLAT_M32R_32		0x00	/* 32bits reloc */
+#define FLAT_M32R_24		0x01	/* unsigned 24bits reloc */
+#define FLAT_M32R_16		0x02	/* 16bits reloc */
+#define FLAT_M32R_LO16		0x03	/* signed low 16bits reloc (low()) */
+#define FLAT_M32R_LO16_DATA	0x04	/* signed low 16bits reloc (low())
+					   for a symbol in .data section */
+					/* High 16bits of an address used
+					   when the lower 16bbits are treated
+					   as unsigned.
+                                           To create SETH instruction only.
+					   0x1X: X means a number of register.
+					   0x10 - 0x3F are reserved. */
+#define FLAT_M32R_HI16_ULO	0x10	/* reloc for SETH Rn,#high(imm16) */
+					/* High 16bits of an address used
+					   when the lower 16bbits are treated
+					   as signed.
+                                           To create SETH instruction only.
+					   0x2X: X means a number of register.
+					   0x20 - 0x4F are reserved. */
+#define FLAT_M32R_HI16_SLO	0x20	/* reloc for SETH Rn,#shigh(imm16) */
+
+static unsigned long textlen_for_m32r_lo16_data = 0;
+
+static inline unsigned long m32r_flat_get_addr_from_rp (unsigned long *rp,
+                                                        unsigned long relval,
+						        unsigned long textlen)
+{
+        unsigned int reloc = flat_m32r_get_reloc_type (relval);
+	textlen_for_m32r_lo16_data = 0;
+	if (reloc & 0xf0) {
+		unsigned long addr = htonl(*rp);
+		switch (reloc & 0xf0)
+		{
+		case FLAT_M32R_HI16_ULO:
+		case FLAT_M32R_HI16_SLO:
+			if (addr == 0) {
+				/* put "seth Rn,#0x0" instead of 0 (addr). */
+				*rp = (M32R_SETH_OPCODE | ((reloc & 0x0f)<<24));
+			}
+			return addr;
+		default:
+			break;
+		}
+	} else {
+		switch (reloc)
+		{
+		case FLAT_M32R_LO16:
+			return htonl(*rp) & 0xFFFF;
+		case FLAT_M32R_LO16_DATA:
+                        /* FIXME: The return value will decrease by textlen
+			   at m32r_flat_put_addr_at_rp () */
+			textlen_for_m32r_lo16_data = textlen;
+			return (htonl(*rp) & 0xFFFF) + textlen;
+		case FLAT_M32R_16:
+			return htons(*(unsigned short *)rp) & 0xFFFF;
+		case FLAT_M32R_24:
+			return htonl(*rp) & 0xFFFFFF;
+		case FLAT_M32R_32:
+			return htonl(*rp);
+		default:
+			break;
+		}
+	}
+	return ~0;      /* bogus value */
+}
+
+static inline void m32r_flat_put_addr_at_rp (unsigned long *rp,
+					     unsigned long addr,
+                                             unsigned long relval)
+{
+        unsigned int reloc = flat_m32r_get_reloc_type (relval);
+	if (reloc & 0xf0) {
+		unsigned long Rn = reloc & 0x0f; /* get a number of register */
+		Rn <<= 24; /* 0x0R000000 */
+		reloc &= 0xf0;
+		switch (reloc)
+		{
+		case FLAT_M32R_HI16_ULO: /* To create SETH Rn,#high(imm16) */
+			*rp = (M32R_SETH_OPCODE | Rn
+			       | ((addr >> 16) & 0xFFFF));
+			break;
+		case FLAT_M32R_HI16_SLO: /* To create SETH Rn,#shigh(imm16) */
+			*rp = (M32R_SETH_OPCODE | Rn
+			       | (((addr >> 16) + ((addr & 0x8000) ? 1 : 0))
+				  & 0xFFFF));
+			break;
+		}
+	} else {
+		switch (reloc) {
+		case FLAT_M32R_LO16_DATA:
+			addr -= textlen_for_m32r_lo16_data;
+			textlen_for_m32r_lo16_data = 0;
+		case FLAT_M32R_LO16:
+			*rp = (htonl(*rp) & 0xFFFF0000) | (addr & 0xFFFF);
+			break;
+		case FLAT_M32R_16:
+			*(unsigned short *)rp = addr & 0xFFFF;
+			break;
+		case FLAT_M32R_24:
+			*rp = (htonl(*rp) & 0xFF000000) | (addr & 0xFFFFFF);
+			break;
+		case FLAT_M32R_32:
+			*rp = addr;
+			break;
+		}
+	}
+}
+
+#endif /* __ASM_M32R_FLAT_H */
diff -Nru a/include/asm-m32r/hardirq.h b/include/asm-m32r/hardirq.h
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/include/asm-m32r/hardirq.h	2004-10-18 14:57:23 -07:00
@@ -0,0 +1,65 @@
+#ifndef __ASM_HARDIRQ_H
+#define __ASM_HARDIRQ_H
+
+#include <linux/config.h>
+#include <linux/threads.h>
+#include <linux/irq.h>
+
+typedef struct {
+	unsigned int __softirq_pending;
+	unsigned int __syscall_count;
+	struct task_struct * __ksoftirqd_task; /* waitqueue is too large */
+} ____cacheline_aligned irq_cpustat_t;
+
+#include <linux/irq_cpustat.h>	/* Standard mappings for irq_cpustat_t above */
+
+/*
+ * We put the hardirq and softirq counter into the preemption
+ * counter. The bitmask has the following meaning:
+ *
+ * - bits 0-7 are the preemption count (max preemption depth: 256)
+ * - bits 8-15 are the softirq count (max # of softirqs: 256)
+ * - bits 16-23 are the hardirq count (max # of hardirqs: 256)
+ *
+ * - ( bit 26 is the PREEMPT_ACTIVE flag. )
+ *
+ * PREEMPT_MASK: 0x000000ff
+ * SOFTIRQ_MASK: 0x0000ff00
+ * HARDIRQ_MASK: 0x00ff0000
+ */
+
+#define PREEMPT_BITS	8
+#define SOFTIRQ_BITS	8
+
+#if NR_IRQS > 256
+#define HARDIRQ_BITS	9
+#else
+#define HARDIRQ_BITS	8
+#endif
+
+#define PREEMPT_SHIFT	0
+#define SOFTIRQ_SHIFT	(PREEMPT_SHIFT + PREEMPT_BITS)
+#define HARDIRQ_SHIFT	(SOFTIRQ_SHIFT + SOFTIRQ_BITS)
+
+/*
+ * The hardirq mask has to be large enough to have
+ * space for potentially all IRQ sources in the system
+ * nesting on a single CPU:
+ */
+#if (1 << HARDIRQ_BITS) < NR_IRQS
+# error HARDIRQ_BITS is too low!
+#endif
+
+#define irq_enter()		(preempt_count() += HARDIRQ_OFFSET)
+#define nmi_enter()		(irq_enter())
+#define nmi_exit()		(preempt_count() -= HARDIRQ_OFFSET)
+
+#define irq_exit()							\
+do {									\
+		preempt_count() -= IRQ_EXIT_OFFSET;			\
+		if (!in_interrupt() && softirq_pending(smp_processor_id())) \
+			do_softirq();					\
+		preempt_enable_no_resched();				\
+} while (0)
+
+#endif /* __ASM_HARDIRQ_H */
diff -Nru a/include/asm-m32r/hdreg.h b/include/asm-m32r/hdreg.h
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/include/asm-m32r/hdreg.h	2004-10-18 14:57:24 -07:00
@@ -0,0 +1 @@
+#include <asm-generic/hdreg.h>
diff -Nru a/include/asm-m32r/hw_irq.h b/include/asm-m32r/hw_irq.h
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/include/asm-m32r/hw_irq.h	2004-10-18 14:57:23 -07:00
@@ -0,0 +1,9 @@
+#ifndef _ASM_M32R_HW_IRQ_H
+#define _ASM_M32R_HW_IRQ_H
+
+static inline void hw_resend_irq(struct hw_interrupt_type *h, unsigned int i)
+{
+	/* Nothing to do */
+}
+
+#endif /* _ASM_M32R_HW_IRQ_H */
diff -Nru a/include/asm-m32r/ide.h b/include/asm-m32r/ide.h
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/include/asm-m32r/ide.h	2004-10-18 14:57:23 -07:00
@@ -0,0 +1,82 @@
+#ifndef _ASM_M32R_IDE_H
+#define _ASM_M32R_IDE_H
+
+/* $Id$ */
+
+/*
+ *  linux/include/asm-m32r/ide.h
+ *
+ *  Copyright (C) 1994-1996  Linus Torvalds & authors
+ */
+
+/*
+ *  This file contains the i386 architecture specific IDE code.
+ */
+
+#ifdef __KERNEL__
+
+#include <linux/config.h>
+
+#ifndef MAX_HWIFS
+# ifdef CONFIG_BLK_DEV_IDEPCI
+#define MAX_HWIFS	10
+# else
+#define MAX_HWIFS	2
+# endif
+#endif
+
+#if defined(CONFIG_PLAT_M32700UT)
+#include <asm/irq.h>
+#include <asm/m32700ut/m32700ut_pld.h>
+#endif
+
+#define IDE_ARCH_OBSOLETE_DEFAULTS
+
+static __inline__ int ide_default_irq(unsigned long base)
+{
+	switch (base) {
+#if defined(CONFIG_PLAT_M32700UT)
+		case 0x1f0: return PLD_IRQ_CFIREQ;
+		default:
+			return 0;
+#else
+		case 0x1f0: return 14;
+		case 0x170: return 15;
+		case 0x1e8: return 11;
+		case 0x168: return 10;
+		case 0x1e0: return 8;
+		case 0x160: return 12;
+		default:
+			return 0;
+#endif
+	}
+}
+
+static __inline__ unsigned long ide_default_io_base(int index)
+{
+	switch (index) {
+		case 0:	return 0x1f0;
+		case 1:	return 0x170;
+		case 2: return 0x1e8;
+		case 3: return 0x168;
+		case 4: return 0x1e0;
+		case 5: return 0x160;
+		default:
+			return 0;
+	}
+}
+
+#define IDE_ARCH_OBSOLETE_INIT
+#define ide_default_io_ctl(base)	((base) + 0x206) /* obsolete */
+
+#ifdef CONFIG_BLK_DEV_IDEPCI
+#define ide_init_default_irq(base)     (0)
+#else
+#define ide_init_default_irq(base)     ide_default_irq(base)
+#endif
+
+#include <asm-generic/ide_iops.h>
+
+#endif /* __KERNEL__ */
+
+#endif /* _ASM_M32R_IDE_H */
diff -Nru a/include/asm-m32r/io.h b/include/asm-m32r/io.h
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/include/asm-m32r/io.h	2004-10-18 14:57:23 -07:00
@@ -0,0 +1,216 @@
+#ifndef _ASM_M32R_IO_H
+#define _ASM_M32R_IO_H
+
+#include <linux/string.h>
+#include <linux/compiler.h>
+#include <asm/page.h>  /* __va */
+
+#ifdef __KERNEL__
+
+#define IO_SPACE_LIMIT  0xFFFFFFFF
+
+/**
+ *	virt_to_phys	-	map virtual addresses to physical
+ *	@address: address to remap
+ *
+ *	The returned physical address is the physical (CPU) mapping for
+ *	the memory address given. It is only valid to use this function on
+ *	addresses directly mapped or allocated via kmalloc.
+ *
+ *	This function does not give bus mappings for DMA transfers. In
+ *	almost all conceivable cases a device driver should not be using
+ *	this function
+ */
+
+static inline unsigned long virt_to_phys(volatile void * address)
+{
+	return __pa(address);
+}
+
+/**
+ *	phys_to_virt	-	map physical address to virtual
+ *	@address: address to remap
+ *
+ *	The returned virtual address is a current CPU mapping for
+ *	the memory address given. It is only valid to use this function on
+ *	addresses that have a kernel mapping
+ *
+ *	This function does not handle bus mappings for DMA transfers. In
+ *	almost all conceivable cases a device driver should not be using
+ *	this function
+ */
+
+static inline void *phys_to_virt(unsigned long address)
+{
+	return __va(address);
+}
+
+extern void __iomem *
+__ioremap(unsigned long offset, unsigned long size, unsigned long flags);
+
+/**
+ *	ioremap		-	map bus memory into CPU space
+ *	@offset:	bus address of the memory
+ *	@size:		size of the resource to map
+ *
+ *	ioremap performs a platform specific sequence of operations to
+ *	make bus memory CPU accessible via the readb/readw/readl/writeb/
+ *	writew/writel functions and the other mmio helpers. The returned
+ *	address is not guaranteed to be usable directly as a virtual
+ *	address.
+ */
+
+static inline void * ioremap(unsigned long offset, unsigned long size)
+{
+	return __ioremap(offset, size, 0);
+}
+
+extern void iounmap(volatile void __iomem *addr);
+#define ioremap_nocache(off,size) ioremap(off,size)
+
+/*
+ * IO bus memory addresses are also 1:1 with the physical address
+ */
+#define page_to_phys(page)	(page_to_pfn(page) << PAGE_SHIFT)
+#define page_to_bus	page_to_phys
+#define virt_to_bus	virt_to_phys
+
+extern unsigned char _inb(unsigned long);
+extern unsigned short _inw(unsigned long);
+extern unsigned long _inl(unsigned long);
+extern unsigned char _inb_p(unsigned long);
+extern unsigned short _inw_p(unsigned long);
+extern unsigned long _inl_p(unsigned long);
+extern void _outb(unsigned char, unsigned long);
+extern void _outw(unsigned short, unsigned long);
+extern void _outl(unsigned long, unsigned long);
+extern void _outb_p(unsigned char, unsigned long);
+extern void _outw_p(unsigned short, unsigned long);
+extern void _outl_p(unsigned long, unsigned long);
+extern void _insb(unsigned int, void *, unsigned long);
+extern void _insw(unsigned int, void *, unsigned long);
+extern void _insl(unsigned int, void *, unsigned long);
+extern void _outsb(unsigned int, const void *, unsigned long);
+extern void _outsw(unsigned int, const void *, unsigned long);
+extern void _outsl(unsigned int, const void *, unsigned long);
+
+static inline unsigned char _readb(unsigned long addr)
+{
+	return *(volatile unsigned char __force *)addr;
+}
+
+static inline unsigned short _readw(unsigned long addr)
+{
+	return *(volatile unsigned short __force *)addr;
+}
+
+static inline unsigned long _readl(unsigned long addr)
+{
+	return *(volatile unsigned long __force *)addr;
+}
+
+static inline void _writeb(unsigned char b, unsigned long addr)
+{
+	*(volatile unsigned char __force *)addr = b;
+}
+
+static inline void _writew(unsigned short w, unsigned long addr)
+{
+	*(volatile unsigned short __force *)addr = w;
+}
+
+static inline void _writel(unsigned long l, unsigned long addr)
+{
+	*(volatile unsigned long __force *)addr = l;
+}
+
+#define inb     _inb
+#define inw     _inw
+#define inl     _inl
+#define outb    _outb
+#define outw    _outw
+#define outl    _outl
+
+#define inb_p   _inb_p
+#define inw_p   _inw_p
+#define inl_p   _inl_p
+#define outb_p  _outb_p
+#define outw_p  _outw_p
+#define outl_p  _outl_p
+
+#define insb    _insb
+#define insw    _insw
+#define insl    _insl
+#define outsb   _outsb
+#define outsw   _outsw
+#define outsl   _outsl
+
+#define readb(addr)   _readb((unsigned long)(addr))
+#define readw(addr)   _readw((unsigned long)(addr))
+#define readl(addr)   _readl((unsigned long)(addr))
+#define __raw_readb readb
+#define __raw_readw readw
+#define __raw_readl readl
+
+#define writeb(val, addr)  _writeb((val), (unsigned long)(addr))
+#define writew(val, addr)  _writew((val), (unsigned long)(addr))
+#define writel(val, addr)  _writel((val), (unsigned long)(addr))
+#define __raw_writeb writeb
+#define __raw_writew writew
+#define __raw_writel writel
+
+#define flush_write_buffers() do { } while (0)  /* M32R_FIXME */
+
+/**
+ *	isa_check_signature		-	find BIOS signatures
+ *	@io_addr: mmio address to check
+ *	@signature:  signature block
+ *	@length: length of signature
+ *
+ *	Perform a signature comparison with the ISA mmio address io_addr.
+ *	Returns 1 on a match.
+ *
+ *	This function is deprecated. New drivers should use ioremap and
+ *	check_signature.
+ */
+
+static inline int isa_check_signature(unsigned long io_addr,
+        const unsigned char *signature, int length)
+{
+        int retval = 0;
+#if 0
+printk("isa_check_signature\n");
+        do {
+                if (isa_readb(io_addr) != *signature)
+                        goto out;
+                io_addr++;
+                signature++;
+                length--;
+        } while (length);
+        retval = 1;
+out:
+#endif
+        return retval;
+}
+
+static inline void
+memset_io(volatile void __iomem *addr, unsigned char val, int count)
+{
+	memset((void __force *) addr, val, count);
+}
+
+static inline void
+memcpy_fromio(void *dst, volatile void __iomem *src, int count)
+{
+	memcpy(dst, (void __force *) src, count);
+}
+
+static inline void
+memcpy_toio(volatile void __iomem *dst, const void *src, int count)
+{
+	memcpy((void __force *) dst, src, count);
+}
+
+#endif  /* __KERNEL__ */
+
+#endif  /* _ASM_M32R_IO_H */
diff -Nru a/include/asm-m32r/ioctl.h b/include/asm-m32r/ioctl.h
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/include/asm-m32r/ioctl.h	2004-10-18 14:57:24 -07:00
@@ -0,0 +1,78 @@
+#ifndef _ASM_M32R_IOCTL_H
+#define _ASM_M32R_IOCTL_H
+
+/* $Id$ */
+
+/* orig : i386 2.4.18 */
+
+/*
+ * linux/ioctl.h for Linux by H.H. Bergman.
+ */
+
+/* ioctl command encoding: 32 bits total, command in lower 16 bits,
+ * size of the parameter structure in the lower 14 bits of the
+ * upper 16 bits.
+ * Encoding the size of the parameter structure in the ioctl request
+ * is useful for catching programs compiled with old versions
+ * and to avoid overwriting user space outside the user buffer area.
+ * The highest 2 bits are reserved for indicating the ``access mode''.
+ * NOTE: This limits the max parameter size to 16kB -1 !
+ */
+
+/*
+ * The following is for compatibility across the various Linux
+ * platforms.  The i386 ioctl numbering scheme doesn't really enforce
+ * a type field.  De facto, however, the top 8 bits of the lower 16
+ * bits are indeed used as a type field, so we might just as well make
+ * this explicit here.  Please be sure to use the decoding macros
+ * below from now on.
+ */
+#define _IOC_NRBITS	8
+#define _IOC_TYPEBITS	8
+#define _IOC_SIZEBITS	14
+#define _IOC_DIRBITS	2
+
+#define _IOC_NRMASK	((1 << _IOC_NRBITS)-1)
+#define _IOC_TYPEMASK	((1 << _IOC_TYPEBITS)-1)
+#define _IOC_SIZEMASK	((1 << _IOC_SIZEBITS)-1)
+#define _IOC_DIRMASK	((1 << _IOC_DIRBITS)-1)
+
+#define _IOC_NRSHIFT	0
+#define _IOC_TYPESHIFT	(_IOC_NRSHIFT+_IOC_NRBITS)
+#define _IOC_SIZESHIFT	(_IOC_TYPESHIFT+_IOC_TYPEBITS)
+#define _IOC_DIRSHIFT	(_IOC_SIZESHIFT+_IOC_SIZEBITS)
+
+/*
+ * Direction bits.
+ */
+#define _IOC_NONE	0U
+#define _IOC_WRITE	1U
+#define _IOC_READ	2U
+
+#define _IOC(dir,type,nr,size) \
+	(((dir)  << _IOC_DIRSHIFT) | \
+	 ((type) << _IOC_TYPESHIFT) | \
+	 ((nr)   << _IOC_NRSHIFT) | \
+	 ((size) << _IOC_SIZESHIFT))
+
+/* used to create numbers */
+#define _IO(type,nr)		_IOC(_IOC_NONE,(type),(nr),0)
+#define _IOR(type,nr,size)	_IOC(_IOC_READ,(type),(nr),sizeof(size))
+#define _IOW(type,nr,size)	_IOC(_IOC_WRITE,(type),(nr),sizeof(size))
+#define _IOWR(type,nr,size)	_IOC(_IOC_READ|_IOC_WRITE,(type),(nr),sizeof(size))
+
+/* used to decode ioctl numbers.. */
+#define _IOC_DIR(nr)		(((nr) >> _IOC_DIRSHIFT) & _IOC_DIRMASK)
+#define _IOC_TYPE(nr)		(((nr) >> _IOC_TYPESHIFT) & _IOC_TYPEMASK)
+#define _IOC_NR(nr)		(((nr) >> _IOC_NRSHIFT) & _IOC_NRMASK)
+#define _IOC_SIZE(nr)		(((nr) >> _IOC_SIZESHIFT) & _IOC_SIZEMASK)
+
+/* ...and for the drivers/sound files... */
+
+#define IOC_IN		(_IOC_WRITE << _IOC_DIRSHIFT)
+#define IOC_OUT		(_IOC_READ << _IOC_DIRSHIFT)
+#define IOC_INOUT	((_IOC_WRITE|_IOC_READ) << _IOC_DIRSHIFT)
+#define IOCSIZE_MASK	(_IOC_SIZEMASK << _IOC_SIZESHIFT)
+#define IOCSIZE_SHIFT	(_IOC_SIZESHIFT)
+
+#endif /* _ASM_M32R_IOCTL_H */
diff -Nru a/include/asm-m32r/ioctls.h b/include/asm-m32r/ioctls.h
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/include/asm-m32r/ioctls.h	2004-10-18 14:57:23 -07:00
@@ -0,0 +1,88 @@
+#ifndef __ARCH_M32R_IOCTLS_H__
+#define __ARCH_M32R_IOCTLS_H__
+
+/* $Id$ */
+
+/* orig : i386 2.5.67 */
+
+#include <asm/ioctl.h>
+
+/* 0x54 is just a magic number to make these relatively unique ('T') */
+
+#define TCGETS		0x5401
+#define TCSETS		0x5402 /* Clashes with SNDCTL_TMR_START sound ioctl */
+#define TCSETSW		0x5403
+#define TCSETSF		0x5404
+#define TCGETA		0x5405
+#define TCSETA		0x5406
+#define TCSETAW		0x5407
+#define TCSETAF		0x5408
+#define TCSBRK		0x5409
+#define TCXONC		0x540A
+#define TCFLSH		0x540B
+#define TIOCEXCL	0x540C
+#define TIOCNXCL	0x540D
+#define TIOCSCTTY	0x540E
+#define TIOCGPGRP	0x540F
+#define TIOCSPGRP	0x5410
+#define TIOCOUTQ	0x5411
+#define TIOCSTI		0x5412
+#define TIOCGWINSZ	0x5413
+#define TIOCSWINSZ	0x5414
+#define TIOCMGET	0x5415
+#define TIOCMBIS	0x5416
+#define TIOCMBIC	0x5417
+#define TIOCMSET	0x5418
+#define TIOCGSOFTCAR	0x5419
+#define TIOCSSOFTCAR	0x541A
+#define FIONREAD	0x541B
+#define TIOCINQ		FIONREAD
+#define TIOCLINUX	0x541C
+#define TIOCCONS	0x541D
+#define TIOCGSERIAL	0x541E
+#define TIOCSSERIAL	0x541F
+#define TIOCPKT		0x5420
+#define FIONBIO		0x5421
+#define TIOCNOTTY	0x5422
+#define TIOCSETD	0x5423
+#define TIOCGETD	0x5424
+#define TCSBRKP		0x5425	/* Needed for POSIX tcsendbreak() */
+/* #define TIOCTTYGSTRUCT 0x5426 - Former debugging-only ioctl */
+#define TIOCSBRK	0x5427  /* BSD compatibility */
+#define TIOCCBRK	0x5428  /* BSD compatibility */
+#define TIOCGSID	0x5429  /* Return the session ID of FD */
+#define TIOCGPTN	_IOR('T',0x30, unsigned int) /* Get Pty Number (of pty-mux device) */
+#define TIOCSPTLCK	_IOW('T',0x31, int)  /* Lock/unlock Pty */
+
+#define FIONCLEX	0x5450
+#define FIOCLEX		0x5451
+#define FIOASYNC	0x5452
+#define TIOCSERCONFIG	0x5453
+#define TIOCSERGWILD	0x5454
+#define TIOCSERSWILD	0x5455
+#define TIOCGLCKTRMIOS	0x5456
+#define TIOCSLCKTRMIOS	0x5457
+#define TIOCSERGSTRUCT	0x5458 /* For debugging only */
+#define TIOCSERGETLSR   0x5459 /* Get line status register */
+#define TIOCSERGETMULTI 0x545A /* Get multiport config  */
+#define TIOCSERSETMULTI 0x545B /* Set multiport config */
+
+#define TIOCMIWAIT	0x545C	/* wait for a change on serial input line(s) */
+#define TIOCGICOUNT	0x545D	/* read serial port inline interrupt counts */
+#define TIOCGHAYESESP   0x545E  /* Get Hayes ESP configuration */
+#define TIOCSHAYESESP   0x545F  /* Set Hayes ESP configuration */
+#define FIOQSIZE	0x5460
+
+/* Used for packet mode */
+#define TIOCPKT_DATA		 0
+#define TIOCPKT_FLUSHREAD	 1
+#define TIOCPKT_FLUSHWRITE	 2
+#define TIOCPKT_STOP		 4
+#define TIOCPKT_START		 8
+#define TIOCPKT_NOSTOP		16
+#define TIOCPKT_DOSTOP		32
+
+#define TIOCSER_TEMT    0x01	/* Transmitter physically empty */
+
+#endif /* __ARCH_M32R_IOCTLS_H__ */
+
diff -Nru a/include/asm-m32r/ipc.h b/include/asm-m32r/ipc.h
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/include/asm-m32r/ipc.h	2004-10-18 14:57:23 -07:00
@@ -0,0 +1,35 @@
+#ifndef __M32R_IPC_H__
+#define __M32R_IPC_H__
+
+/* orig : i386/ipc.h 2.6.0-test3 */
+
+/*
+ * These are used to wrap system calls on x86.
+ *
+ * See arch/i386/kernel/sys_i386.c for ugly details..
+ */
+struct ipc_kludge {
+	struct msgbuf __user *msgp;
+	long msgtyp;
+};
+
+#define SEMOP		 1
+#define SEMGET		 2
+#define SEMCTL		 3
+#define SEMTIMEDOP	 4
+#define MSGSND		11
+#define MSGRCV		12
+#define MSGGET		13
+#define MSGCTL		14
+#define SHMAT		21
+#define SHMDT		22
+#define SHMGET		23
+#define SHMCTL		24
+
+/* Used by the DIPC package, try and avoid reusing it */
+#define DIPC            25
+
+#define IPCCALL(version,op)	((version)<<16 | (op))
+
+#endif	/* __M32R_IPC_H__ */
+
diff -Nru a/include/asm-m32r/ipcbuf.h b/include/asm-m32r/ipcbuf.h
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/include/asm-m32r/ipcbuf.h	2004-10-18 14:57:24 -07:00
@@ -0,0 +1,33 @@
+#ifndef _ASM_M32R_IPCBUF_H
+#define _ASM_M32R_IPCBUF_H
+
+/* $Id$ */
+
+/* orig : i386 2.4.18 */
+
+/*
+ * The ipc64_perm structure for m32r architecture.
+ * Note extra padding because this structure is passed back and forth
+ * between kernel and user space.
+ *
+ * Pad space is left for:
+ * - 32-bit mode_t and seq
+ * - 2 miscellaneous 32-bit values
+ */
+
+struct ipc64_perm
+{
+	__kernel_key_t		key;
+	__kernel_uid32_t	uid;
+	__kernel_gid32_t	gid;
+	__kernel_uid32_t	cuid;
+	__kernel_gid32_t	cgid;
+	__kernel_mode_t		mode;
+	unsigned short		__pad1;
+	unsigned short		seq;
+	unsigned short		__pad2;
+	unsigned long		__unused1;
+	unsigned long		__unused2;
+};
+
+#endif /* _ASM_M32R_IPCBUF_H */
diff -Nru a/include/asm-m32r/irq.h b/include/asm-m32r/irq.h
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/include/asm-m32r/irq.h	2004-10-18 14:57:21 -07:00
@@ -0,0 +1,86 @@
+#ifndef _ASM_M32R_IRQ_H
+#define _ASM_M32R_IRQ_H
+
+/* $Id$ */
+
+#include <linux/config.h>
+
+#if defined(CONFIG_PLAT_M32700UT_Alpha) || defined(CONFIG_PLAT_USRV)
+/*
+ * IRQ definitions for M32700UT
+ *  M32700 Chip: 64 interrupts
+ *  ICU of M32700UT-on-board PLD: 32 interrupts cascaded to INT1# chip pin
+ */
+#define	M32700UT_NUM_CPU_IRQ	(64)
+#define M32700UT_NUM_PLD_IRQ	(32)
+#define M32700UT_IRQ_BASE	0
+#define M32700UT_CPU_IRQ_BASE	M32700UT_IRQ_BASE
+#define M32700UT_PLD_IRQ_BASE	(M32700UT_CPU_IRQ_BASE + M32700UT_NUM_CPU_IRQ)
+
+#define NR_IRQS	(M32700UT_NUM_CPU_IRQ + M32700UT_NUM_PLD_IRQ)
+#elif defined(CONFIG_PLAT_M32700UT)
+/*
+ * IRQ definitions for M32700UT(Rev.C) + M32R-LAN
+ *  M32700 Chip: 64 interrupts
+ *  ICU of M32700UT-on-board PLD: 32 interrupts cascaded to INT1# chip pin
+ *  ICU of M32R-LCD-on-board PLD: 32 interrupts cascaded to INT2# chip pin
+ *  ICU of M32R-LAN-on-board PLD: 32 interrupts cascaded to INT0# chip pin
+ */
+#define M32700UT_NUM_CPU_IRQ		(64)
+#define M32700UT_NUM_PLD_IRQ		(32)
+#define M32700UT_NUM_LCD_PLD_IRQ	(32)
+#define M32700UT_NUM_LAN_PLD_IRQ	(32)
+#define M32700UT_IRQ_BASE		0
+#define M32700UT_CPU_IRQ_BASE		(M32700UT_IRQ_BASE)
+#define M32700UT_PLD_IRQ_BASE \
+	(M32700UT_CPU_IRQ_BASE + M32700UT_NUM_CPU_IRQ)
+#define M32700UT_LCD_PLD_IRQ_BASE \
+	(M32700UT_PLD_IRQ_BASE + M32700UT_NUM_PLD_IRQ)
+#define M32700UT_LAN_PLD_IRQ_BASE \
+	(M32700UT_LCD_PLD_IRQ_BASE + M32700UT_NUM_LCD_PLD_IRQ)
+
+#define NR_IRQS \
+	(M32700UT_NUM_CPU_IRQ + M32700UT_NUM_PLD_IRQ \
+	+ M32700UT_NUM_LCD_PLD_IRQ + M32700UT_NUM_LAN_PLD_IRQ)
+#elif defined(CONFIG_PLAT_OPSPUT)
+/*
+ * IRQ definitions for OPSPUT + M32R-LAN
+ *  OPSP Chip: 64 interrupts
+ *  ICU of OPSPUT-on-board PLD: 32 interrupts cascaded to INT1# chip pin
+ *  ICU of M32R-LCD-on-board PLD: 32 interrupts cascaded to INT2# chip pin
+ *  ICU of M32R-LAN-on-board PLD: 32 interrupts cascaded to INT0# chip pin
+ */
+#define OPSPUT_NUM_CPU_IRQ		(64)
+#define OPSPUT_NUM_PLD_IRQ		(32)
+#define OPSPUT_NUM_LCD_PLD_IRQ	(32)
+#define OPSPUT_NUM_LAN_PLD_IRQ	(32)
+#define OPSPUT_IRQ_BASE		0
+#define OPSPUT_CPU_IRQ_BASE		(OPSPUT_IRQ_BASE)
+#define OPSPUT_PLD_IRQ_BASE \
+	(OPSPUT_CPU_IRQ_BASE + OPSPUT_NUM_CPU_IRQ)
+#define OPSPUT_LCD_PLD_IRQ_BASE \
+	(OPSPUT_PLD_IRQ_BASE + OPSPUT_NUM_PLD_IRQ)
+#define OPSPUT_LAN_PLD_IRQ_BASE \
+	(OPSPUT_LCD_PLD_IRQ_BASE + OPSPUT_NUM_LCD_PLD_IRQ)
+
+#define NR_IRQS \
+	(OPSPUT_NUM_CPU_IRQ + OPSPUT_NUM_PLD_IRQ \
+	+ OPSPUT_NUM_LCD_PLD_IRQ + OPSPUT_NUM_LAN_PLD_IRQ)
+#else
+#define NR_IRQS	64
+#endif
+
+#define irq_canonicalize(irq)	(irq)
+
+#ifndef __ASSEMBLY__
+extern void disable_irq(unsigned int);
+extern void disable_irq_nosync(unsigned int);
+extern void enable_irq(unsigned int);
+
+struct irqaction;
+struct pt_regs;
+int handle_IRQ_event(unsigned int, struct pt_regs *, struct irqaction *);
+#endif
+
+#endif	/* _ASM_M32R_IRQ_H */
+
diff -Nru a/include/asm-m32r/kmap_types.h b/include/asm-m32r/kmap_types.h
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/include/asm-m32r/kmap_types.h	2004-10-18 14:57:24 -07:00
@@ -0,0 +1,34 @@
+#ifndef __M32R_KMAP_TYPES_H
+#define __M32R_KMAP_TYPES_H
+
+/* Dummy header just to define km_type. */
+
+#include <linux/config.h>
+
+#ifdef CONFIG_DEBUG_HIGHMEM
+# define D(n) __KM_FENCE_##n ,
+#else
+# define D(n)
+#endif
+
+enum km_type {
+D(0)	KM_BOUNCE_READ,
+D(1)	KM_SKB_SUNRPC_DATA,
+D(2)	KM_SKB_DATA_SOFTIRQ,
+D(3)	KM_USER0,
+D(4)	KM_USER1,
+D(5)	KM_BIO_SRC_IRQ,
+D(6)	KM_BIO_DST_IRQ,
+D(7)	KM_PTE0,
+D(8)	KM_PTE1,
+D(9)	KM_IRQ0,
+D(10)	KM_IRQ1,
+D(11)	KM_SOFTIRQ0,
+D(12)	KM_SOFTIRQ1,
+D(13)	KM_TYPE_NR
+};
+
+#undef D
+
+#endif /* __M32R_KMAP_TYPES_H */
+
diff -Nru a/include/asm-m32r/linkage.h b/include/asm-m32r/linkage.h
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/include/asm-m32r/linkage.h	2004-10-18 14:57:24 -07:00
@@ -0,0 +1,7 @@
+#ifndef __ASM_LINKAGE_H
+#define __ASM_LINKAGE_H
+
+#define __ALIGN		.balign 4
+#define __ALIGN_STR	".balign 4"
+
+#endif /* __ASM_LINKAGE_H */
diff -Nru a/include/asm-m32r/local.h b/include/asm-m32r/local.h
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/include/asm-m32r/local.h	2004-10-18 14:57:21 -07:00
@@ -0,0 +1,6 @@
+#ifndef __M32R_LOCAL_H
+#define __M32R_LOCAL_H
+
+#include <asm-generic/local.h>
+
+#endif /* __M32R_LOCAL_H */
diff -Nru a/include/asm-m32r/m32102.h b/include/asm-m32r/m32102.h
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/include/asm-m32r/m32102.h	2004-10-18 14:57:23 -07:00
@@ -0,0 +1,266 @@
+#ifndef _M32102_H_
+#define _M32102_H_
+
+/*
+ * Renesas M32R 32102 group
+ *
+ * Copyright (c) 2001  Hitoshi Yamamoto
+ * Copyright (c) 2003, 2004  Renesas Technology Corp.
+ */
+
+/*======================================================================*
+ * Special Function Register
+ *======================================================================*/
+#define M32R_SFR_OFFSET  (0x00E00000)  /* 0x00E00000-0x00EFFFFF 1[MB] */
+
+/*
+ * Clock and Power Management registers.
+ */
+#define M32R_CPM_OFFSET          (0x000F4000+M32R_SFR_OFFSET)
+
+#define M32R_CPM_CPUCLKCR_PORTL  (0x00+M32R_CPM_OFFSET)
+#define M32R_CPM_CLKMOD_PORTL    (0x04+M32R_CPM_OFFSET)
+#define M32R_CPM_PLLCR_PORTL     (0x08+M32R_CPM_OFFSET)
+
+/*
+ * Multi Function Timer registers.
+ */
+#define M32R_MFT_OFFSET        (0x000FC000+M32R_SFR_OFFSET)
+
+#define M32R_MFTCR_PORTL       (0x000+M32R_MFT_OFFSET)  /* MFT control */
+#define M32R_MFTRPR_PORTL      (0x004+M32R_MFT_OFFSET)  /* MFT real port */
+
+#define M32R_MFT0_OFFSET       (0x100+M32R_MFT_OFFSET)
+#define M32R_MFT0MOD_PORTL     (0x00+M32R_MFT0_OFFSET)  /* MFT0 mode */
+#define M32R_MFT0BOS_PORTL     (0x04+M32R_MFT0_OFFSET)  /* MFT0 b-port output status */
+#define M32R_MFT0CUT_PORTL     (0x08+M32R_MFT0_OFFSET)  /* MFT0 count */
+#define M32R_MFT0RLD_PORTL     (0x0C+M32R_MFT0_OFFSET)  /* MFT0 reload */
+#define M32R_MFT0CMPRLD_PORTL  (0x10+M32R_MFT0_OFFSET)  /* MFT0 compare reload */
+
+#define M32R_MFT1_OFFSET       (0x200+M32R_MFT_OFFSET)
+#define M32R_MFT1MOD_PORTL     (0x00+M32R_MFT1_OFFSET)  /* MFT1 mode */
+#define M32R_MFT1BOS_PORTL     (0x04+M32R_MFT1_OFFSET)  /* MFT1 b-port output status */
+#define M32R_MFT1CUT_PORTL     (0x08+M32R_MFT1_OFFSET)  /* MFT1 count */
+#define M32R_MFT1RLD_PORTL     (0x0C+M32R_MFT1_OFFSET)  /* MFT1 reload */
+#define M32R_MFT1CMPRLD_PORTL  (0x10+M32R_MFT1_OFFSET)  /* MFT1 compare reload */
+
+#define M32R_MFT2_OFFSET       (0x300+M32R_MFT_OFFSET)
+#define M32R_MFT2MOD_PORTL     (0x00+M32R_MFT2_OFFSET)  /* MFT2 mode */
+#define M32R_MFT2BOS_PORTL     (0x04+M32R_MFT2_OFFSET)  /* MFT2 b-port output status */
+#define M32R_MFT2CUT_PORTL     (0x08+M32R_MFT2_OFFSET)  /* MFT2 count */
+#define M32R_MFT2RLD_PORTL     (0x0C+M32R_MFT2_OFFSET)  /* MFT2 reload */
+#define M32R_MFT2CMPRLD_PORTL  (0x10+M32R_MFT2_OFFSET)  /* MFT2 compare reload */
+
+#define M32R_MFT3_OFFSET       (0x400+M32R_MFT_OFFSET)
+#define M32R_MFT3MOD_PORTL     (0x00+M32R_MFT3_OFFSET)  /* MFT3 mode */
+#define M32R_MFT3BOS_PORTL     (0x04+M32R_MFT3_OFFSET)  /* MFT3 b-port output status */
+#define M32R_MFT3CUT_PORTL     (0x08+M32R_MFT3_OFFSET)  /* MFT3 count */
+#define M32R_MFT3RLD_PORTL     (0x0C+M32R_MFT3_OFFSET)  /* MFT3 reload */
+#define M32R_MFT3CMPRLD_PORTL  (0x10+M32R_MFT3_OFFSET)  /* MFT3 compare reload */
+
+#define M32R_MFT4_OFFSET       (0x500+M32R_MFT_OFFSET)
+#define M32R_MFT4MOD_PORTL     (0x00+M32R_MFT4_OFFSET)  /* MFT4 mode */
+#define M32R_MFT4BOS_PORTL     (0x04+M32R_MFT4_OFFSET)  /* MFT4 b-port output status */
+#define M32R_MFT4CUT_PORTL     (0x08+M32R_MFT4_OFFSET)  /* MFT4 count */
+#define M32R_MFT4RLD_PORTL     (0x0C+M32R_MFT4_OFFSET)  /* MFT4 reload */
+#define M32R_MFT4CMPRLD_PORTL  (0x10+M32R_MFT4_OFFSET)  /* MFT4 compare reload */
+
+#define M32R_MFT5_OFFSET       (0x600+M32R_MFT_OFFSET)
+#define M32R_MFT5MOD_PORTL     (0x00+M32R_MFT5_OFFSET)  /* MFT4 mode */
+#define M32R_MFT5BOS_PORTL     (0x04+M32R_MFT5_OFFSET)  /* MFT4 b-port output status */
+#define M32R_MFT5CUT_PORTL     (0x08+M32R_MFT5_OFFSET)  /* MFT4 count */
+#define M32R_MFT5RLD_PORTL     (0x0C+M32R_MFT5_OFFSET)  /* MFT4 reload */
+#define M32R_MFT5CMPRLD_PORTL  (0x10+M32R_MFT5_OFFSET)  /* MFT4 compare reload */
+
+#ifdef CONFIG_CHIP_M32700
+#define M32R_MFTCR_MFT0MSK  (1UL<<31)  /* b0 */
+#define M32R_MFTCR_MFT1MSK  (1UL<<30)  /* b1 */
+#define M32R_MFTCR_MFT2MSK  (1UL<<29)  /* b2 */
+#define M32R_MFTCR_MFT3MSK  (1UL<<28)  /* b3 */
+#define M32R_MFTCR_MFT4MSK  (1UL<<27)  /* b4 */
+#define M32R_MFTCR_MFT5MSK  (1UL<<26)  /* b5 */
+#define M32R_MFTCR_MFT0EN   (1UL<<23)  /* b8 */
+#define M32R_MFTCR_MFT1EN   (1UL<<22)  /* b9 */
+#define M32R_MFTCR_MFT2EN   (1UL<<21)  /* b10 */
+#define M32R_MFTCR_MFT3EN   (1UL<<20)  /* b11 */
+#define M32R_MFTCR_MFT4EN   (1UL<<19)  /* b12 */
+#define M32R_MFTCR_MFT5EN   (1UL<<18)  /* b13 */
+#else	/* not CONFIG_CHIP_M32700 */
+#define M32R_MFTCR_MFT0MSK  (1UL<<15)  /* b16 */
+#define M32R_MFTCR_MFT1MSK  (1UL<<14)  /* b17 */
+#define M32R_MFTCR_MFT2MSK  (1UL<<13)  /* b18 */
+#define M32R_MFTCR_MFT3MSK  (1UL<<12)  /* b19 */
+#define M32R_MFTCR_MFT4MSK  (1UL<<11)  /* b20 */
+#define M32R_MFTCR_MFT5MSK  (1UL<<10)  /* b21 */
+#define M32R_MFTCR_MFT0EN   (1UL<<7)   /* b24 */
+#define M32R_MFTCR_MFT1EN   (1UL<<6)   /* b25 */
+#define M32R_MFTCR_MFT2EN   (1UL<<5)   /* b26 */
+#define M32R_MFTCR_MFT3EN   (1UL<<4)   /* b27 */
+#define M32R_MFTCR_MFT4EN   (1UL<<3)   /* b28 */
+#define M32R_MFTCR_MFT5EN   (1UL<<2)   /* b29 */
+#endif	/* not CONFIG_CHIP_M32700 */
+
+#define M32R_MFTMOD_CC_MASK    (1UL<<15)  /* b16 */
+#define M32R_MFTMOD_TCCR       (1UL<<13)  /* b18 */
+#define M32R_MFTMOD_GTSEL000   (0UL<<8)   /* b21-23 : 000 */
+#define M32R_MFTMOD_GTSEL001   (1UL<<8)   /* b21-23 : 001 */
+#define M32R_MFTMOD_GTSEL010   (2UL<<8)   /* b21-23 : 010 */
+#define M32R_MFTMOD_GTSEL011   (3UL<<8)   /* b21-23 : 011 */
+#define M32R_MFTMOD_GTSEL110   (6UL<<8)   /* b21-23 : 110 */
+#define M32R_MFTMOD_GTSEL111   (7UL<<8)   /* b21-23 : 111 */
+#define M32R_MFTMOD_CMSEL      (1UL<<3)   /* b28 */
+#define M32R_MFTMOD_CSSEL000   (0UL<<0)   /* b29-b31 : 000 */
+#define M32R_MFTMOD_CSSEL001   (1UL<<0)   /* b29-b31 : 001 */
+#define M32R_MFTMOD_CSSEL010   (2UL<<0)   /* b29-b31 : 010 */
+#define M32R_MFTMOD_CSSEL011   (3UL<<0)   /* b29-b31 : 011 */
+#define M32R_MFTMOD_CSSEL100   (4UL<<0)   /* b29-b31 : 100 */
+#define M32R_MFTMOD_CSSEL110   (6UL<<0)   /* b29-b31 : 110 */
+
+/*
+ * Serial I/O registers.
+ */
+#define M32R_SIO_OFFSET  (0x000FD000+M32R_SFR_OFFSET)
+
+#define M32R_SIO0_CR_PORTL     (0x000+M32R_SIO_OFFSET)
+#define M32R_SIO0_MOD0_PORTL   (0x004+M32R_SIO_OFFSET)
+#define M32R_SIO0_MOD1_PORTL   (0x008+M32R_SIO_OFFSET)
+#define M32R_SIO0_STS_PORTL    (0x00C+M32R_SIO_OFFSET)
+#define M32R_SIO0_TRCR_PORTL   (0x010+M32R_SIO_OFFSET)
+#define M32R_SIO0_BAUR_PORTL   (0x014+M32R_SIO_OFFSET)
+#define M32R_SIO0_RBAUR_PORTL  (0x018+M32R_SIO_OFFSET)
+#define M32R_SIO0_TXB_PORTL    (0x01C+M32R_SIO_OFFSET)
+#define M32R_SIO0_RXB_PORTL    (0x020+M32R_SIO_OFFSET)
+
+/*
+ * Interrupt Control Unit registers.
+ */
+#define M32R_ICU_OFFSET       (0x000FF000+M32R_SFR_OFFSET)
+#define M32R_ICU_ISTS_PORTL   (0x004+M32R_ICU_OFFSET)
+#define M32R_ICU_IREQ0_PORTL  (0x008+M32R_ICU_OFFSET)
+#define M32R_ICU_IREQ1_PORTL  (0x00C+M32R_ICU_OFFSET)
+#define M32R_ICU_SBICR_PORTL  (0x018+M32R_ICU_OFFSET)
+#define M32R_ICU_IMASK_PORTL  (0x01C+M32R_ICU_OFFSET)
+#define M32R_ICU_CR1_PORTL    (0x200+M32R_ICU_OFFSET)  /* INT0 */
+#define M32R_ICU_CR2_PORTL    (0x204+M32R_ICU_OFFSET)  /* INT1 */
+#define M32R_ICU_CR3_PORTL    (0x208+M32R_ICU_OFFSET)  /* INT2 */
+#define M32R_ICU_CR4_PORTL    (0x20C+M32R_ICU_OFFSET)  /* INT3 */
+#define M32R_ICU_CR5_PORTL    (0x210+M32R_ICU_OFFSET)  /* INT4 */
+#define M32R_ICU_CR6_PORTL    (0x214+M32R_ICU_OFFSET)  /* INT5 */
+#define M32R_ICU_CR7_PORTL    (0x218+M32R_ICU_OFFSET)  /* INT6 */
+#define M32R_ICU_CR16_PORTL   (0x23C+M32R_ICU_OFFSET)  /* MFT0 */
+#define M32R_ICU_CR17_PORTL   (0x240+M32R_ICU_OFFSET)  /* MFT1 */
+#define M32R_ICU_CR18_PORTL   (0x244+M32R_ICU_OFFSET)  /* MFT2 */
+#define M32R_ICU_CR19_PORTL   (0x248+M32R_ICU_OFFSET)  /* MFT3 */
+#define M32R_ICU_CR20_PORTL   (0x24C+M32R_ICU_OFFSET)  /* MFT4 */
+#define M32R_ICU_CR21_PORTL   (0x250+M32R_ICU_OFFSET)  /* MFT5 */
+#define M32R_ICU_CR32_PORTL   (0x27C+M32R_ICU_OFFSET)  /* DMA0 */
+#define M32R_ICU_CR33_PORTL   (0x280+M32R_ICU_OFFSET)  /* DMA1 */
+#define M32R_ICU_CR48_PORTL   (0x2BC+M32R_ICU_OFFSET)  /* SIO0 */
+#define M32R_ICU_CR49_PORTL   (0x2C0+M32R_ICU_OFFSET)  /* SIO0 */
+#define M32R_ICU_CR50_PORTL   (0x2C4+M32R_ICU_OFFSET)  /* SIO1 */
+#define M32R_ICU_CR51_PORTL   (0x2C8+M32R_ICU_OFFSET)  /* SIO1 */
+#define M32R_ICU_CR52_PORTL   (0x2CC+M32R_ICU_OFFSET)  /* SIO2 */
+#define M32R_ICU_CR53_PORTL   (0x2D0+M32R_ICU_OFFSET)  /* SIO2 */
+#define M32R_ICU_CR54_PORTL   (0x2D4+M32R_ICU_OFFSET)  /* SIO3 */
+#define M32R_ICU_CR55_PORTL   (0x2D8+M32R_ICU_OFFSET)  /* SIO3 */
+#define M32R_ICU_CR56_PORTL   (0x2DC+M32R_ICU_OFFSET)  /* SIO4 */
+#define M32R_ICU_CR57_PORTL   (0x2E0+M32R_ICU_OFFSET)  /* SIO4 */
+
+#ifdef CONFIG_SMP
+#define M32R_ICU_IPICR0_PORTL (0x2dc+M32R_ICU_OFFSET)  /* IPI0 */
+#define M32R_ICU_IPICR1_PORTL (0x2e0+M32R_ICU_OFFSET)  /* IPI1 */
+#define M32R_ICU_IPICR2_PORTL (0x2e4+M32R_ICU_OFFSET)  /* IPI2 */
+#define M32R_ICU_IPICR3_PORTL (0x2e8+M32R_ICU_OFFSET)  /* IPI3 */
+#define M32R_ICU_IPICR4_PORTL (0x2ec+M32R_ICU_OFFSET)  /* IPI4 */
+#define M32R_ICU_IPICR5_PORTL (0x2f0+M32R_ICU_OFFSET)  /* IPI5 */
+#define M32R_ICU_IPICR6_PORTL (0x2f4+M32R_ICU_OFFSET)  /* IPI6 */
+#define M32R_ICU_IPICR7_PORTL (0x2f8+M32R_ICU_OFFSET)  /* IPI7 */
+#endif /* CONFIG_SMP */
+
+#define M32R_ICUIMASK_IMSK0  (0UL<<16)  /* b13-b15: Disable interrupt */
+#define M32R_ICUIMASK_IMSK1  (1UL<<16)  /* b13-b15: Enable level 0 interrupt */
+#define M32R_ICUIMASK_IMSK2  (2UL<<16)  /* b13-b15: Enable level 0,1 interrupt */
+#define M32R_ICUIMASK_IMSK3  (3UL<<16)  /* b13-b15: Enable level 0-2 interrupt */
+#define M32R_ICUIMASK_IMSK4  (4UL<<16)  /* b13-b15: Enable level 0-3 interrupt */
+#define M32R_ICUIMASK_IMSK5  (5UL<<16)  /* b13-b15: Enable level 0-4 interrupt */
+#define M32R_ICUIMASK_IMSK6  (6UL<<16)  /* b13-b15: Enable level 0-5 interrupt */
+#define M32R_ICUIMASK_IMSK7  (7UL<<16)  /* b13-b15: Enable level 0-6 interrupt */
+
+#define M32R_ICUCR_IEN      (1UL<<12)  /* b19: Interrupt enable */
+#define M32R_ICUCR_IRQ      (1UL<<8)   /* b23: Interrupt request */
+#define M32R_ICUCR_ISMOD00  (0UL<<4)   /* b26-b27: Interrupt sense mode Edge HtoL */
+#define M32R_ICUCR_ISMOD01  (1UL<<4)   /* b26-b27: Interrupt sense mode Level L */
+#define M32R_ICUCR_ISMOD10  (2UL<<4)   /* b26-b27: Interrupt sense mode Edge LtoH*/
+#define M32R_ICUCR_ISMOD11  (3UL<<4)   /* b26-b27: Interrupt sense mode Level H */
+#define M32R_ICUCR_ILEVEL0  (0UL<<0)   /* b29-b31: Interrupt priority level 0 */
+#define M32R_ICUCR_ILEVEL1  (1UL<<0)   /* b29-b31: Interrupt priority level 1 */
+#define M32R_ICUCR_ILEVEL2  (2UL<<0)   /* b29-b31: Interrupt priority level 2 */
+#define M32R_ICUCR_ILEVEL3  (3UL<<0)   /* b29-b31: Interrupt priority level 3 */
+#define M32R_ICUCR_ILEVEL4  (4UL<<0)   /* b29-b31: Interrupt priority level 4 */
+#define M32R_ICUCR_ILEVEL5  (5UL<<0)   /* b29-b31: Interrupt priority level 5 */
+#define M32R_ICUCR_ILEVEL6  (6UL<<0)   /* b29-b31: Interrupt priority level 6 */
+#define M32R_ICUCR_ILEVEL7  (7UL<<0)   /* b29-b31: Disable interrupt */
+
+#define  M32R_IRQ_INT0    (1)   /* INT0 */
+#define  M32R_IRQ_INT1    (2)   /* INT1 */
+#define  M32R_IRQ_INT2    (3)   /* INT2 */
+#define  M32R_IRQ_INT3    (4)   /* INT3 */
+#define  M32R_IRQ_INT4    (5)   /* INT4 */
+#define  M32R_IRQ_INT5    (6)   /* INT5 */
+#define  M32R_IRQ_INT6    (7)   /* INT6 */
+#define  M32R_IRQ_MFT0    (16)  /* MFT0 */
+#define  M32R_IRQ_MFT1    (17)  /* MFT1 */
+#define  M32R_IRQ_MFT2    (18)  /* MFT2 */
+#define  M32R_IRQ_MFT3    (19)  /* MFT3 */
+#define  M32R_IRQ_MFT4    (20)  /* MFT4 */
+#define  M32R_IRQ_MFT5    (21)  /* MFT5 */
+#define  M32R_IRQ_DMA0    (32)  /* DMA0 */
+#define  M32R_IRQ_DMA1    (33)  /* DMA1 */
+#define  M32R_IRQ_SIO0_R  (48)  /* SIO0 send    */
+#define  M32R_IRQ_SIO0_S  (49)  /* SIO0 receive */
+#define  M32R_IRQ_SIO1_R  (50)  /* SIO1 send    */
+#define  M32R_IRQ_SIO1_S  (51)  /* SIO1 receive */
+#define  M32R_IRQ_SIO2_R  (52)  /* SIO2 send    */
+#define  M32R_IRQ_SIO2_S  (53)  /* SIO2 receive */
+#define  M32R_IRQ_SIO3_R  (54)  /* SIO3 send    */
+#define  M32R_IRQ_SIO3_S  (55)  /* SIO3 receive */
+#define  M32R_IRQ_SIO4_R  (56)  /* SIO4 send    */
+#define  M32R_IRQ_SIO4_S  (57)  /* SIO4 receive */
+
+#ifdef CONFIG_SMP
+#define M32R_IRQ_IPI0 (56)
+#define M32R_IRQ_IPI1 (57)
+#define M32R_IRQ_IPI2 (58)
+#define M32R_IRQ_IPI3 (59)
+#define M32R_IRQ_IPI4 (60)
+#define M32R_IRQ_IPI5 (61)
+#define M32R_IRQ_IPI6 (62)
+#define M32R_IRQ_IPI7 (63)
+#define M32R_CPUID_PORTL (0xffffffe0)
+
+#define M32R_FPGA_TOP (0x000F0000+M32R_SFR_OFFSET)
+
+#define M32R_FPGA_NUM_OF_CPUS_PORTL (0x00+M32R_FPGA_TOP)
+#define M32R_FPGA_CPU_NAME0_PORTL   (0x10+M32R_FPGA_TOP)
+#define M32R_FPGA_CPU_NAME1_PORTL   (0x14+M32R_FPGA_TOP)
+#define M32R_FPGA_CPU_NAME2_PORTL   (0x18+M32R_FPGA_TOP)
+#define M32R_FPGA_CPU_NAME3_PORTL   (0x1c+M32R_FPGA_TOP)
+#define M32R_FPGA_MODEL_ID0_PORTL   (0x20+M32R_FPGA_TOP)
+#define M32R_FPGA_MODEL_ID1_PORTL   (0x24+M32R_FPGA_TOP)
+#define M32R_FPGA_MODEL_ID2_PORTL   (0x28+M32R_FPGA_TOP)
+#define M32R_FPGA_MODEL_ID3_PORTL   (0x2c+M32R_FPGA_TOP)
+#define M32R_FPGA_VERSION0_PORTL    (0x30+M32R_FPGA_TOP)
+#define M32R_FPGA_VERSION1_PORTL    (0x34+M32R_FPGA_TOP)
+
+#ifndef __ASSEMBLY__
+/* For NETDEV WATCHDOG */
+typedef struct {
+	unsigned long icucr;	/* ICU Control Register */
+} icu_data_t;
+
+extern icu_data_t icu_data[];
+#endif
+
+#endif /* CONFIG_SMP */
+
+#endif /* _M32102_H_ */
diff -Nru a/include/asm-m32r/m32102peri.h b/include/asm-m32r/m32102peri.h
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/include/asm-m32r/m32102peri.h	2004-10-18 14:57:23 -07:00
@@ -0,0 +1,468 @@
+/* $Id$
+ *
+ * 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,2001 by Hiroyuki Kondo
+ */
+
+#ifndef __ASSEMBLY__
+
+typedef	void	V;
+typedef	char	B;
+typedef	short	S;
+typedef	int		W;
+typedef	long	L;
+typedef	float	F;
+typedef	double	D;
+typedef	unsigned char	UB;
+typedef	unsigned short	US;
+typedef	unsigned int	UW;
+typedef	unsigned long	UL;
+typedef	const unsigned int	CUW;
+
+/*********************************
+
+M32102 ICU
+
+*********************************/
+#define		ICUISTS		(UW *)0xa0EFF004
+#define		ICUIREQ0	(UW *)0xa0EFF008
+#define		ICUIREQ1	(UW *)0xa0EFF00C
+
+#define		ICUSBICR	(UW *)0xa0EFF018
+#define		ICUIMASK	(UW *)0xa0EFF01C
+
+#define		ICUCR1		(UW *)0xa0EFF200	/* INT0 */
+#define		ICUCR2		(UW *)0xa0EFF204	/* INT1 */
+#define		ICUCR3		(UW *)0xa0EFF208	/* INT2 */
+#define		ICUCR4		(UW *)0xa0EFF20C	/* INT3 */
+#define		ICUCR5		(UW *)0xa0EFF210	/* INT4 */
+#define		ICUCR6		(UW *)0xa0EFF214	/* INT5 */
+#define		ICUCR7		(UW *)0xa0EFF218	/* INT6 */
+
+#define		ICUCR16		(UW *)0xa0EFF23C	/* MFT0 */
+#define		ICUCR17		(UW *)0xa0EFF240	/* MFT1 */
+#define		ICUCR18		(UW *)0xa0EFF244	/* MFT2 */
+#define		ICUCR19		(UW *)0xa0EFF248	/* MFT3 */
+#define		ICUCR20		(UW *)0xa0EFF24C	/* MFT4 */
+#define		ICUCR21		(UW *)0xa0EFF250	/* MFT5 */
+
+#define		ICUCR32		(UW *)0xa0EFF27C	/* DMA0 */
+#define		ICUCR33		(UW *)0xa0EFF280	/* DMA1 */
+
+#define		ICUCR48		(UW *)0xa0EFF2BC	/* SIO0R */
+#define		ICUCR49		(UW *)0xa0EFF2C0	/* SIO0S */
+#define		ICUCR50		(UW *)0xa0EFF2C4	/* SIO1R */
+#define		ICUCR51		(UW *)0xa0EFF2C8	/* SIO1S */
+#define		ICUCR52		(UW *)0xa0EFF2CC	/* SIO2R */
+#define		ICUCR53		(UW *)0xa0EFF2D0	/* SIO2S */
+#define		ICUCR54		(UW *)0xa0EFF2D4	/* SIO3R */
+#define		ICUCR55		(UW *)0xa0EFF2D8	/* SIO3S */
+#define		ICUCR56		(UW *)0xa0EFF2DC	/* SIO4R */
+#define		ICUCR57		(UW *)0xa0EFF2E0	/* SIO4S */
+
+/*********************************
+
+M32102 MFT
+
+*********************************/
+#define		MFTCR		(US *)0xa0EFC002
+#define		MFTRPR		(UB *)0xa0EFC006
+
+#define		MFT0MOD		(US *)0xa0EFC102
+#define		MFT0BOS		(US *)0xa0EFC106
+#define		MFT0CUT		(US *)0xa0EFC10A
+#define		MFT0RLD		(US *)0xa0EFC10E
+#define		MFT0CRLD	(US *)0xa0EFC112
+
+#define		MFT1MOD		(US *)0xa0EFC202
+#define		MFT1BOS		(US *)0xa0EFC206
+#define		MFT1CUT		(US *)0xa0EFC20A
+#define		MFT1RLD		(US *)0xa0EFC20E
+#define		MFT1CRLD	(US *)0xa0EFC212
+
+#define		MFT2MOD		(US *)0xa0EFC302
+#define		MFT2BOS		(US *)0xa0EFC306
+#define		MFT2CUT		(US *)0xa0EFC30A
+#define		MFT2RLD		(US *)0xa0EFC30E
+#define		MFT2CRLD	(US *)0xa0EFC312
+
+#define		MFT3MOD		(US *)0xa0EFC402
+#define		MFT3CUT		(US *)0xa0EFC40A
+#define		MFT3RLD		(US *)0xa0EFC40E
+#define		MFT3CRLD	(US *)0xa0EFC412
+
+#define		MFT4MOD		(US *)0xa0EFC502
+#define		MFT4CUT		(US *)0xa0EFC50A
+#define		MFT4RLD		(US *)0xa0EFC50E
+#define		MFT4CRLD	(US *)0xa0EFC512
+
+#define		MFT5MOD		(US *)0xa0EFC602
+#define		MFT5CUT		(US *)0xa0EFC60A
+#define		MFT5RLD		(US *)0xa0EFC60E
+#define		MFT5CRLD	(US *)0xa0EFC612
+
+/*********************************
+
+M32102 SIO
+
+*********************************/
+
+#define SIO0CR     (volatile int *)0xa0efd000
+#define SIO0MOD0   (volatile int *)0xa0efd004
+#define SIO0MOD1   (volatile int *)0xa0efd008
+#define SIO0STS    (volatile int *)0xa0efd00c
+#define SIO0IMASK  (volatile int *)0xa0efd010
+#define SIO0BAUR   (volatile int *)0xa0efd014
+#define SIO0RBAUR  (volatile int *)0xa0efd018
+#define SIO0TXB    (volatile int *)0xa0efd01c
+#define SIO0RXB    (volatile int *)0xa0efd020
+
+#define SIO1CR     (volatile int *)0xa0efd100
+#define SIO1MOD0   (volatile int *)0xa0efd104
+#define SIO1MOD1   (volatile int *)0xa0efd108
+#define SIO1STS    (volatile int *)0xa0efd10c
+#define SIO1IMASK  (volatile int *)0xa0efd110
+#define SIO1BAUR   (volatile int *)0xa0efd114
+#define SIO1RBAUR  (volatile int *)0xa0efd118
+#define SIO1TXB    (volatile int *)0xa0efd11c
+#define SIO1RXB    (volatile int *)0xa0efd120
+/*********************************
+
+M32102 PORT
+
+*********************************/
+#define		PIEN		(UB *)0xa0EF1003	/* input enable */
+
+#define		P0DATA		(UB *)0xa0EF1020	/* data */
+#define		P1DATA		(UB *)0xa0EF1021
+#define		P2DATA		(UB *)0xa0EF1022
+#define		P3DATA		(UB *)0xa0EF1023
+#define		P4DATA		(UB *)0xa0EF1024
+#define		P5DATA		(UB *)0xa0EF1025
+#define		P6DATA		(UB *)0xa0EF1026
+#define		P7DATA		(UB *)0xa0EF1027
+
+#define		P0DIR		(UB *)0xa0EF1040	/* direction */
+#define		P1DIR		(UB *)0xa0EF1041
+#define		P2DIR		(UB *)0xa0EF1042
+#define		P3DIR		(UB *)0xa0EF1043
+#define		P4DIR		(UB *)0xa0EF1044
+#define		P5DIR		(UB *)0xa0EF1045
+#define		P6DIR		(UB *)0xa0EF1046
+#define		P7DIR		(UB *)0xa0EF1047
+
+#define		P0MOD		(US *)0xa0EF1060	/* mode control */
+#define		P1MOD		(US *)0xa0EF1062
+#define		P2MOD		(US *)0xa0EF1064
+#define		P3MOD		(US *)0xa0EF1066
+#define		P4MOD		(US *)0xa0EF1068
+#define		P5MOD		(US *)0xa0EF106A
+#define		P6MOD		(US *)0xa0EF106C
+#define		P7MOD		(US *)0xa0EF106E
+
+#define		P0ODCR		(UB *)0xa0EF1080	/* open-drain control */
+#define		P1ODCR		(UB *)0xa0EF1081
+#define		P2ODCR		(UB *)0xa0EF1082
+#define		P3ODCR		(UB *)0xa0EF1083
+#define		P4ODCR		(UB *)0xa0EF1084
+#define		P5ODCR		(UB *)0xa0EF1085
+#define		P6ODCR		(UB *)0xa0EF1086
+#define		P7ODCR		(UB *)0xa0EF1087
+
+/*********************************
+
+M32102 Cache
+
+********************************/
+
+#define		MCCR	(US *)0xFFFFFFFE
+
+
+#else  /* __ASSEMBLY__ */
+
+;;
+;; PIO     0x80ef1000
+;;
+
+#define PIEN          0xa0ef1000
+
+#define P0DATA        0xa0ef1020
+#define P1DATA        0xa0ef1021
+#define P2DATA        0xa0ef1022
+#define P3DATA        0xa0ef1023
+#define P4DATA        0xa0ef1024
+#define P5DATA        0xa0ef1025
+#define P6DATA        0xa0ef1026
+#define P7DATA        0xa0ef1027
+
+#define P0DIR         0xa0ef1040
+#define P1DIR         0xa0ef1041
+#define P2DIR         0xa0ef1042
+#define P3DIR         0xa0ef1043
+#define P4DIR         0xa0ef1044
+#define P5DIR         0xa0ef1045
+#define P6DIR         0xa0ef1046
+#define P7DIR         0xa0ef1047
+
+#define P0MOD         0xa0ef1060
+#define P1MOD         0xa0ef1062
+#define P2MOD         0xa0ef1064
+#define P3MOD         0xa0ef1066
+#define P4MOD         0xa0ef1068
+#define P5MOD         0xa0ef106a
+#define P6MOD         0xa0ef106c
+#define P7MOD         0xa0ef106e
+;
+#define P0ODCR        0xa0ef1080
+#define P1ODCR        0xa0ef1081
+#define P2ODCR        0xa0ef1082
+#define P3ODCR        0xa0ef1083
+#define P4ODCR        0xa0ef1084
+#define P5ODCR        0xa0ef1085
+#define P6ODCR        0xa0ef1086
+#define P7ODCR        0xa0ef1087
+
+;;
+;; WDT     0xa0ef2000
+;;
+
+#define WDTCR         0xa0ef2000
+
+
+;;
+;; CLK     0xa0ef4000
+;;
+
+#define CPUCLKCR      0xa0ef4000
+#define CLKMOD        0xa0ef4004
+#define PLLCR         0xa0ef4008
+
+
+;;
+;; BSEL    0xa0ef5000
+;;
+
+#define BSEL0CR       0xa0ef5000
+#define BSEL1CR       0xa0ef5004
+#define BSEL2CR       0xa0ef5008
+#define BSEL3CR       0xa0ef500c
+#define BSEL4CR       0xa0ef5010
+#define BSEL5CR       0xa0ef5014
+
+
+;;
+;; SDRAMC  0xa0ef6000
+;;
+
+#define SDRF0         0xa0ef6000
+#define SDRF1         0xa0ef6004
+#define SDIR0         0xa0ef6008
+#define SDIR1         0xa0ef600c
+#define SDBR          0xa0ef6010
+
+;; CH0
+#define SD0ADR        0xa0ef6020
+#define SD0SZ         0xa0ef6022
+#define SD0ER         0xa0ef6024
+#define SD0TR         0xa0ef6028
+#define SD0MOD        0xa0ef602c
+
+;; CH1
+#define SD1ADR        0xa0ef6040
+#define SD1SZ         0xa0ef6042
+#define SD1ER         0xa0ef6044
+#define SD1TR         0xa0ef6048
+#define SD1MOD        0xa0ef604c
+
+
+;;
+;; DMAC    0xa0ef8000
+;;
+
+#define DMAEN         0xa0ef8000
+#define DMAISTS       0xa0ef8004
+#define DMAEDET       0xa0ef8008
+#define DMAASTS       0xa0ef800c
+
+;; CH0
+#define DMA0CR0       0xa0ef8100
+#define DMA0CR1       0xa0ef8104
+#define DMA0CSA       0xa0ef8108
+#define DMA0RSA       0xa0ef810c
+#define DMA0CDA       0xa0ef8110
+#define DMA0RDA       0xa0ef8114
+#define DMA0CBCUT     0xa0ef8118
+#define DMA0RBCUT     0xa0ef811c
+
+;; CH1
+#define DMA1CR0       0xa0ef8200
+#define DMA1CR1       0xa0ef8204
+#define DMA1CSA       0xa0ef8208
+#define DMA1RSA       0xa0ef820c
+#define DMA1CDA       0xa0ef8210
+#define DMA1RDA       0xa0ef8214
+#define DMA1CBCUT     0xa0ef8218
+#define DMA1RBCUT     0xa0ef821c
+
+
+;;
+;; MFT     0xa0efc000
+;;
+
+#define MFTCR        0xa0efc000
+#define MFTRPR       0xa0efc004
+
+;; CH0
+#define MFT0MOD      0xa0efc100
+#define MFT0BOS      0xa0efc104
+#define MFT0CUT      0xa0efc108
+#define MFT0RLD      0xa0efc10c
+#define MFT0CMPRLD   0xa0efc110
+
+;; CH1
+#define MFT1MOD      0xa0efc200
+#define MFT1BOS      0xa0efc204
+#define MFT1CUT      0xa0efc208
+#define MFT1RLD      0xa0efc20c
+#define MFT1CMPRLD   0xa0efc210
+
+;; CH2
+#define MFT2MOD      0xa0efc300
+#define MFT2BOS      0xa0efc304
+#define MFT2CUT      0xa0efc308
+#define MFT2RLD      0xa0efc30c
+#define MFT2CMPRLD   0xa0efc310
+
+;; CH3
+#define MFT3MOD      0xa0efc400
+#define MFT3BOS      0xa0efc404
+#define MFT3CUT      0xa0efc408
+#define MFT3RLD      0xa0efc40c
+#define MFT3CMPRLD   0xa0efc410
+
+;; CH4
+#define MFT4MOD      0xa0efc500
+#define MFT4BOS      0xa0efc504
+#define MFT4CUT      0xa0efc508
+#define MFT4RLD      0xa0efc50c
+#define MFT4CMPRLD   0xa0efc510
+
+;; CH5
+#define MFT5MOD      0xa0efc600
+#define MFT5BOS      0xa0efc604
+#define MFT5CUT      0xa0efc608
+#define MFT5RLD      0xa0efc60c
+#define MFT5CMPRLD   0xa0efc610
+
+
+;;
+;; SIO     0xa0efd000
+;;
+
+;; CH0
+#define SIO0CR        0xa0efd000
+#define SIO0MOD0      0xa0efd004
+#define SIO0MOD1      0xa0efd008
+#define SIO0STS       0xa0efd00c
+#define SIO0IMASK     0xa0efd010
+#define SIO0BAUR      0xa0efd014
+#define SIO0RBAUR     0xa0efd018
+#define SIO0TXB       0xa0efd01c
+#define SIO0RXB       0xa0efd020
+
+;; CH1
+#define SIO1CR        0xa0efd100
+#define SIO1MOD0      0xa0efd104
+#define SIO1MOD1      0xa0efd108
+#define SIO1STS       0xa0efd10c
+#define SIO1IMASK     0xa0efd110
+#define SIO1BAUR      0xa0efd114
+#define SIO1RBAUR     0xa0efd118
+#define SIO1TXB       0xa0efd11c
+#define SIO1RXB       0xa0efd120
+
+;; CH2
+#define SIO2CR        0xa0efd200
+#define SIO2MOD0      0xa0efd204
+#define SIO2MOD1      0xa0efd208
+#define SIO2STS       0xa0efd20c
+#define SIO2IMASK     0xa0efd210
+#define SIO2BAUR      0xa0efd214
+#define SIO2RBAUR     0xa0efd218
+#define SIO2TXB       0xa0efd21c
+#define SIO2RXB       0xa0efd220
+
+;; CH3
+#define SIO3CR        0xa0efd300
+#define SIO3MOD0      0xa0efd304
+#define SIO3MOD1      0xa0efd308
+#define SIO3STS       0xa0efd30c
+#define SIO3IMASK     0xa0efd310
+#define SIO3BAUR      0xa0efd314
+#define SIO3RBAUR     0xa0efd318
+#define SIO3TXB       0xa0efd31c
+#define SIO3RXB       0xa0efd320
+
+;; CH4
+#define SIO4CR        0xa0efd400
+#define SIO4MOD0      0xa0efd404
+#define SIO4MOD1      0xa0efd408
+#define SIO4STS       0xa0efd40c
+#define SIO4IMASK     0xa0efd410
+#define SIO4BAUR      0xa0efd414
+#define SIO4RBAUR     0xa0efd418
+#define SIO4TXB       0xa0efd41c
+#define SIO4RXB       0xa0efd420
+
+
+;;
+;; ICU     0xa0eff000
+;;
+
+#define ICUISTS       0xa0eff004
+#define ICUIREQ0      0xa0eff008
+#define ICUIREQ1      0xa0eff00c
+
+#define ICUSBICR      0xa0eff018
+#define ICUIMASK      0xa0eff01c
+
+#define ICUCR1        0xa0eff200
+#define ICUCR2        0xa0eff204
+#define ICUCR3        0xa0eff208
+#define ICUCR4        0xa0eff20c
+#define ICUCR5        0xa0eff210
+#define ICUCR6        0xa0eff214
+#define ICUCR7        0xa0eff218
+
+#define ICUCR16       0xa0eff23c
+#define ICUCR17       0xa0eff240
+#define ICUCR18       0xa0eff244
+#define ICUCR19       0xa0eff248
+#define ICUCR20       0xa0eff24c
+#define ICUCR21       0xa0eff250
+
+#define ICUCR32       0xa0eff27c
+#define ICUCR33       0xa0eff280
+
+#define ICUCR48       0xa0eff2bc
+#define ICUCR49       0xa0eff2c0
+#define ICUCR50       0xa0eff2c4
+#define ICUCR51       0xa0eff2c8
+#define ICUCR52       0xa0eff2cc
+#define ICUCR53       0xa0eff2d0
+#define ICUCR54       0xa0eff2d4
+#define ICUCR55       0xa0eff2d8
+#define ICUCR56       0xa0eff2dc
+#define ICUCR57       0xa0eff2e0
+
+;;
+;; CACHE
+;;
+
+#define MCCR		  0xfffffffc
+
+
+#endif  /* __ASSEMBLY__ */
diff -Nru a/include/asm-m32r/m32700ut/m32700ut_lan.h b/include/asm-m32r/m32700ut/m32700ut_lan.h
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/include/asm-m32r/m32700ut/m32700ut_lan.h	2004-10-18 14:57:23 -07:00
@@ -0,0 +1,107 @@
+/*
+ * include/asm/m32700ut_lan.h
+ *
+ * M32700UT-LAN board
+ *
+ * Copyright (c) 2002	Takeo Takahashi
+ *
+ * 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.
+ *
+ * $Id$
+ */
+
+#ifndef _M32700UT_M32700UT_LAN_H
+#define _M32700UT_M32700UT_LAN_H
+
+#include <linux/config.h>
+
+#ifndef __ASSEMBLY__
+/*
+ * C functions use non-cache address.
+ */
+#define M32700UT_LAN_BASE	(0x10000000 /* + NONCACHE_OFFSET */)
+#else
+#define M32700UT_LAN_BASE	(0x10000000 + NONCACHE_OFFSET)
+#endif	/* __ASSEMBLY__ */
+
+/* ICU
+ *  ICUISTS:	status register
+ *  ICUIREQ0: 	request register
+ *  ICUIREQ1: 	request register
+ *  ICUCR3:	control register for CFIREQ# interrupt
+ *  ICUCR4:	control register for CFC Card insert interrupt
+ *  ICUCR5:	control register for CFC Card eject interrupt
+ *  ICUCR6:	control register for external interrupt
+ *  ICUCR11:	control register for MMC Card insert/eject interrupt
+ *  ICUCR13:	control register for SC error interrupt
+ *  ICUCR14:	control register for SC receive interrupt
+ *  ICUCR15:	control register for SC send interrupt
+ *  ICUCR16:	control register for SIO0 receive interrupt
+ *  ICUCR17:	control register for SIO0 send interrupt
+ */
+#define M32700UT_LAN_IRQ_LAN	(M32700UT_LAN_PLD_IRQ_BASE + 1)	/* LAN */
+#define M32700UT_LAN_IRQ_I2C	(M32700UT_LAN_PLD_IRQ_BASE + 3)	/* I2C */
+
+#define M32700UT_LAN_ICUISTS	__reg16(M32700UT_LAN_BASE + 0xc0002)
+#define M32700UT_LAN_ICUISTS_VECB_MASK	(0xf000)
+#define M32700UT_LAN_VECB(x)	((x) & M32700UT_LAN_ICUISTS_VECB_MASK)
+#define M32700UT_LAN_ICUISTS_ISN_MASK	(0x07c0)
+#define M32700UT_LAN_ICUISTS_ISN(x)	((x) & M32700UT_LAN_ICUISTS_ISN_MASK)
+#define M32700UT_LAN_ICUIREQ0	__reg16(M32700UT_LAN_BASE + 0xc0004)
+#define M32700UT_LAN_ICUCR1	__reg16(M32700UT_LAN_BASE + 0xc0010)
+#define M32700UT_LAN_ICUCR3	__reg16(M32700UT_LAN_BASE + 0xc0014)
+
+/*
+ * AR register on PLD
+ */
+#define ARVCR0		__reg32(M32700UT_LAN_BASE + 0x40000)
+#define ARVCR0_VDS		0x00080000
+#define ARVCR0_RST		0x00010000
+#define ARVCR1		__reg32(M32700UT_LAN_BASE + 0x40004)
+#define ARVCR1_QVGA		0x02000000
+#define ARVCR1_NORMAL		0x01000000
+#define ARVCR1_HIEN		0x00010000
+#define ARVHCOUNT	__reg32(M32700UT_LAN_BASE + 0x40008)
+#define ARDATA		__reg32(M32700UT_LAN_BASE + 0x40010)
+#define ARINTSEL	__reg32(M32700UT_LAN_BASE + 0x40014)
+#define ARINTSEL_INT3		0x10000000	/* CPU INT3 */
+#define ARDATA32	__reg32(M32700UT_LAN_BASE + 0x04040010)	// Block 5
+/*
+#define ARINTSEL_SEL2		0x00002000
+#define ARINTSEL_SEL3		0x00001000
+#define ARINTSEL_SEL6		0x00000200
+#define ARINTSEL_SEL7		0x00000100
+#define ARINTSEL_SEL9		0x00000040
+#define ARINTSEL_SEL10		0x00000020
+#define ARINTSEL_SEL11		0x00000010
+#define ARINTSEL_SEL12		0x00000008
+*/
+
+/*
+ * I2C register on PLD
+ */
+#define PLDI2CCR	__reg32(M32700UT_LAN_BASE + 0x40040)
+#define	PLDI2CCR_ES0		0x00000001	/* enable I2C interface */
+#define PLDI2CMOD	__reg32(M32700UT_LAN_BASE + 0x40044)
+#define PLDI2CMOD_ACKCLK	0x00000200
+#define PLDI2CMOD_DTWD		0x00000100
+#define PLDI2CMOD_10BT		0x00000004
+#define PLDI2CMOD_ATM_NORMAL	0x00000000
+#define PLDI2CMOD_ATM_AUTO	0x00000003
+#define PLDI2CACK	__reg32(M32700UT_LAN_BASE + 0x40048)
+#define PLDI2CACK_ACK		0x00000001
+#define PLDI2CFREQ	__reg32(M32700UT_LAN_BASE + 0x4004c)
+#define PLDI2CCND	__reg32(M32700UT_LAN_BASE + 0x40050)
+#define PLDI2CCND_START		0x00000001
+#define PLDI2CCND_STOP		0x00000002
+#define PLDI2CSTEN	__reg32(M32700UT_LAN_BASE + 0x40054)
+#define PLDI2CSTEN_STEN		0x00000001
+#define PLDI2CDATA	__reg32(M32700UT_LAN_BASE + 0x40060)
+#define PLDI2CSTS	__reg32(M32700UT_LAN_BASE + 0x40064)
+#define PLDI2CSTS_TRX		0x00000020
+#define PLDI2CSTS_BB		0x00000010
+#define PLDI2CSTS_NOACK		0x00000001	/* 0:ack, 1:noack */
+
+#endif	/* _M32700UT_M32700UT_LAN_H */
diff -Nru a/include/asm-m32r/m32700ut/m32700ut_lcd.h b/include/asm-m32r/m32700ut/m32700ut_lcd.h
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/include/asm-m32r/m32700ut/m32700ut_lcd.h	2004-10-18 14:57:23 -07:00
@@ -0,0 +1,59 @@
+/*
+ * include/asm/m32700ut_lcd.h
+ *
+ * M32700UT-LCD board
+ *
+ * Copyright (c) 2002	Takeo Takahashi
+ *
+ * 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.
+ *
+ * $Id$
+ */
+
+#ifndef _M32700UT_M32700UT_LCD_H
+#define _M32700UT_M32700UT_LCD_H
+
+#include <linux/config.h>
+
+#ifndef __ASSEMBLY__
+/*
+ * C functions use non-cache address.
+ */
+#define M32700UT_LCD_BASE	(0x10000000 /* + NONCACHE_OFFSET */)
+#else
+#define M32700UT_LCD_BASE	(0x10000000 + NONCACHE_OFFSET)
+#endif	/* __ASSEMBLY__ */
+
+/*
+ * ICU
+ */
+#define M32700UT_LCD_IRQ_BAT_INT	(M32700UT_LCD_PLD_IRQ_BASE + 1)
+#define M32700UT_LCD_IRQ_USB_INT1	(M32700UT_LCD_PLD_IRQ_BASE + 2)
+#define M32700UT_LCD_IRQ_AUDT0		(M32700UT_LCD_PLD_IRQ_BASE + 3)
+#define M32700UT_LCD_IRQ_AUDT2		(M32700UT_LCD_PLD_IRQ_BASE + 4)
+#define M32700UT_LCD_IRQ_BATSIO_RCV	(M32700UT_LCD_PLD_IRQ_BASE + 16)
+#define M32700UT_LCD_IRQ_BATSIO_SND	(M32700UT_LCD_PLD_IRQ_BASE + 17)
+#define M32700UT_LCD_IRQ_ASNDSIO_RCV	(M32700UT_LCD_PLD_IRQ_BASE + 18)
+#define M32700UT_LCD_IRQ_ASNDSIO_SND	(M32700UT_LCD_PLD_IRQ_BASE + 19)
+#define M32700UT_LCD_IRQ_ACNLSIO_SND	(M32700UT_LCD_PLD_IRQ_BASE + 21)
+
+#define M32700UT_LCD_ICUISTS	__reg16(M32700UT_LCD_BASE + 0x300002)
+#define M32700UT_LCD_ICUISTS_VECB_MASK	(0xf000)
+#define M32700UT_LCD_VECB(x)	((x) & M32700UT_LCD_ICUISTS_VECB_MASK)
+#define M32700UT_LCD_ICUISTS_ISN_MASK	(0x07c0)
+#define M32700UT_LCD_ICUISTS_ISN(x)	((x) & M32700UT_LCD_ICUISTS_ISN_MASK)
+#define M32700UT_LCD_ICUIREQ0	__reg16(M32700UT_LCD_BASE + 0x300004)
+#define M32700UT_LCD_ICUIREQ1	__reg16(M32700UT_LCD_BASE + 0x300006)
+#define M32700UT_LCD_ICUCR1	__reg16(M32700UT_LCD_BASE + 0x300020)
+#define M32700UT_LCD_ICUCR2	__reg16(M32700UT_LCD_BASE + 0x300022)
+#define M32700UT_LCD_ICUCR3	__reg16(M32700UT_LCD_BASE + 0x300024)
+#define M32700UT_LCD_ICUCR4	__reg16(M32700UT_LCD_BASE + 0x300026)
+#define M32700UT_LCD_ICUCR16	__reg16(M32700UT_LCD_BASE + 0x300030)
+#define M32700UT_LCD_ICUCR17	__reg16(M32700UT_LCD_BASE + 0x300032)
+#define M32700UT_LCD_ICUCR18	__reg16(M32700UT_LCD_BASE + 0x300034)
+#define M32700UT_LCD_ICUCR19	__reg16(M32700UT_LCD_BASE + 0x300036)
+#define M32700UT_LCD_ICUCR21	__reg16(M32700UT_LCD_BASE + 0x30003a)
+
+#endif	/* _M32700UT_M32700UT_LCD_H */
diff -Nru a/include/asm-m32r/m32700ut/m32700ut_pld.h b/include/asm-m32r/m32700ut/m32700ut_pld.h
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/include/asm-m32r/m32700ut/m32700ut_pld.h	2004-10-18 14:57:23 -07:00
@@ -0,0 +1,265 @@
+/*
+ * include/asm/m32700ut/m32700ut_pld.h
+ *
+ * Definitions for Programable Logic Device(PLD) on M32700UT board.
+ *
+ * Copyright (c) 2002	Takeo Takahashi
+ *
+ * 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.
+ *
+ * $Id$
+ */
+
+#ifndef _M32700UT_M32700UT_PLD_H
+#define _M32700UT_M32700UT_PLD_H
+
+#include <linux/config.h>
+
+#if defined(CONFIG_PLAT_M32700UT_Alpha)
+#define PLD_PLAT_BASE		0x08c00000
+#elif defined(CONFIG_PLAT_M32700UT) || defined(CONFIG_PLAT_USRV)
+#define PLD_PLAT_BASE		0x04c00000
+#else
+#error "no platform configuration"
+#endif
+
+#ifndef __ASSEMBLY__
+/*
+ * C functions use non-cache address.
+ */
+#define PLD_BASE		(PLD_PLAT_BASE /* + NONCACHE_OFFSET */)
+#define __reg8			(volatile unsigned char *)
+#define __reg16			(volatile unsigned short *)
+#define __reg32			(volatile unsigned int *)
+#else
+#define PLD_BASE		(PLD_PLAT_BASE + NONCACHE_OFFSET)
+#define __reg8
+#define __reg16
+#define __reg32
+#endif	/* __ASSEMBLY__ */
+
+/* CFC */
+#define	PLD_CFRSTCR		__reg16(PLD_BASE + 0x0000)
+#define PLD_CFSTS		__reg16(PLD_BASE + 0x0002)
+#define PLD_CFIMASK		__reg16(PLD_BASE + 0x0004)
+#define PLD_CFBUFCR		__reg16(PLD_BASE + 0x0006)
+#define PLD_CFVENCR		__reg16(PLD_BASE + 0x0008)
+#define PLD_CFCR0		__reg16(PLD_BASE + 0x000a)
+#define PLD_CFCR1		__reg16(PLD_BASE + 0x000c)
+#define PLD_IDERSTCR		__reg16(PLD_BASE + 0x0010)
+
+/* MMC */
+#define PLD_MMCCR		__reg16(PLD_BASE + 0x4000)
+#define PLD_MMCMOD		__reg16(PLD_BASE + 0x4002)
+#define PLD_MMCSTS		__reg16(PLD_BASE + 0x4006)
+#define PLD_MMCBAUR		__reg16(PLD_BASE + 0x400a)
+#define PLD_MMCCMDBCUT		__reg16(PLD_BASE + 0x400c)
+#define PLD_MMCCDTBCUT		__reg16(PLD_BASE + 0x400e)
+#define PLD_MMCDET		__reg16(PLD_BASE + 0x4010)
+#define PLD_MMCWP		__reg16(PLD_BASE + 0x4012)
+#define PLD_MMCWDATA		__reg16(PLD_BASE + 0x5000)
+#define PLD_MMCRDATA		__reg16(PLD_BASE + 0x6000)
+#define PLD_MMCCMDDATA		__reg16(PLD_BASE + 0x7000)
+#define PLD_MMCRSPDATA		__reg16(PLD_BASE + 0x7006)
+
+/* ICU
+ *  ICUISTS:	status register
+ *  ICUIREQ0: 	request register
+ *  ICUIREQ1: 	request register
+ *  ICUCR3:	control register for CFIREQ# interrupt
+ *  ICUCR4:	control register for CFC Card insert interrupt
+ *  ICUCR5:	control register for CFC Card eject interrupt
+ *  ICUCR6:	control register for external interrupt
+ *  ICUCR11:	control register for MMC Card insert/eject interrupt
+ *  ICUCR13:	control register for SC error interrupt
+ *  ICUCR14:	control register for SC receive interrupt
+ *  ICUCR15:	control register for SC send interrupt
+ *  ICUCR16:	control register for SIO0 receive interrupt
+ *  ICUCR17:	control register for SIO0 send interrupt
+ */
+#if !defined(CONFIG_PLAT_USRV)
+#define PLD_IRQ_INT0		(M32700UT_PLD_IRQ_BASE + 0)	/* None */
+#define PLD_IRQ_INT1		(M32700UT_PLD_IRQ_BASE + 1)	/* reserved */
+#define PLD_IRQ_INT2		(M32700UT_PLD_IRQ_BASE + 2)	/* reserved */
+#define PLD_IRQ_CFIREQ		(M32700UT_PLD_IRQ_BASE + 3)	/* CF IREQ */
+#define PLD_IRQ_CFC_INSERT	(M32700UT_PLD_IRQ_BASE + 4)	/* CF Insert */
+#define PLD_IRQ_CFC_EJECT	(M32700UT_PLD_IRQ_BASE + 5)	/* CF Eject */
+#define PLD_IRQ_EXINT		(M32700UT_PLD_IRQ_BASE + 6)	/* EXINT */
+#define PLD_IRQ_INT7		(M32700UT_PLD_IRQ_BASE + 7)	/* reserved */
+#define PLD_IRQ_INT8		(M32700UT_PLD_IRQ_BASE + 8)	/* reserved */
+#define PLD_IRQ_INT9		(M32700UT_PLD_IRQ_BASE + 9)	/* reserved */
+#define PLD_IRQ_INT10		(M32700UT_PLD_IRQ_BASE + 10)	/* reserved */
+#define PLD_IRQ_MMCCARD		(M32700UT_PLD_IRQ_BASE + 11)	/* MMC Insert/Eject */
+#define PLD_IRQ_INT12		(M32700UT_PLD_IRQ_BASE + 12)	/* reserved */
+#define PLD_IRQ_SC_ERROR	(M32700UT_PLD_IRQ_BASE + 13)	/* SC error */
+#define PLD_IRQ_SC_RCV		(M32700UT_PLD_IRQ_BASE + 14)	/* SC receive */
+#define PLD_IRQ_SC_SND		(M32700UT_PLD_IRQ_BASE + 15)	/* SC send */
+#define PLD_IRQ_SIO0_RCV	(M32700UT_PLD_IRQ_BASE + 16)	/* SIO receive */
+#define PLD_IRQ_SIO0_SND	(M32700UT_PLD_IRQ_BASE + 17)	/* SIO send */
+#define PLD_IRQ_INT18		(M32700UT_PLD_IRQ_BASE + 18)	/* reserved */
+#define PLD_IRQ_INT19		(M32700UT_PLD_IRQ_BASE + 19)	/* reserved */
+#define PLD_IRQ_INT20		(M32700UT_PLD_IRQ_BASE + 20)	/* reserved */
+#define PLD_IRQ_INT21		(M32700UT_PLD_IRQ_BASE + 21)	/* reserved */
+#define PLD_IRQ_INT22		(M32700UT_PLD_IRQ_BASE + 22)	/* reserved */
+#define PLD_IRQ_INT23		(M32700UT_PLD_IRQ_BASE + 23)	/* reserved */
+#define PLD_IRQ_INT24		(M32700UT_PLD_IRQ_BASE + 24)	/* reserved */
+#define PLD_IRQ_INT25		(M32700UT_PLD_IRQ_BASE + 25)	/* reserved */
+#define PLD_IRQ_INT26		(M32700UT_PLD_IRQ_BASE + 26)	/* reserved */
+#define PLD_IRQ_INT27		(M32700UT_PLD_IRQ_BASE + 27)	/* reserved */
+#define PLD_IRQ_INT28		(M32700UT_PLD_IRQ_BASE + 28)	/* reserved */
+#define PLD_IRQ_INT29		(M32700UT_PLD_IRQ_BASE + 29)	/* reserved */
+#define PLD_IRQ_INT30		(M32700UT_PLD_IRQ_BASE + 30)	/* reserved */
+#define PLD_IRQ_INT31		(M32700UT_PLD_IRQ_BASE + 31)	/* reserved */
+
+#else	/* CONFIG_PLAT_USRV */
+
+#define PLD_IRQ_INT0		(M32700UT_PLD_IRQ_BASE + 0)	/* None */
+#define PLD_IRQ_INT1		(M32700UT_PLD_IRQ_BASE + 1)	/* reserved */
+#define PLD_IRQ_INT2		(M32700UT_PLD_IRQ_BASE + 2)	/* reserved */
+#define PLD_IRQ_CF0		(M32700UT_PLD_IRQ_BASE + 3)	/* CF0# */
+#define PLD_IRQ_CF1		(M32700UT_PLD_IRQ_BASE + 4)	/* CF1# */
+#define PLD_IRQ_CF2		(M32700UT_PLD_IRQ_BASE + 5)	/* CF2# */
+#define PLD_IRQ_CF3		(M32700UT_PLD_IRQ_BASE + 6)	/* CF3# */
+#define PLD_IRQ_CF4		(M32700UT_PLD_IRQ_BASE + 7)	/* CF4# */
+#define PLD_IRQ_INT8		(M32700UT_PLD_IRQ_BASE + 8)	/* reserved */
+#define PLD_IRQ_INT9		(M32700UT_PLD_IRQ_BASE + 9)	/* reserved */
+#define PLD_IRQ_INT10		(M32700UT_PLD_IRQ_BASE + 10)	/* reserved */
+#define PLD_IRQ_INT11		(M32700UT_PLD_IRQ_BASE + 11)	/* reserved */
+#define PLD_IRQ_UART0		(M32700UT_PLD_IRQ_BASE + 12)	/* UARTIRQ0 */
+#define PLD_IRQ_UART1		(M32700UT_PLD_IRQ_BASE + 13)	/* UARTIRQ1 */
+#define PLD_IRQ_INT14		(M32700UT_PLD_IRQ_BASE + 14)	/* reserved */
+#define PLD_IRQ_INT15		(M32700UT_PLD_IRQ_BASE + 15)	/* reserved */
+#define PLD_IRQ_SNDINT		(M32700UT_PLD_IRQ_BASE + 16)	/* SNDINT# */
+#define PLD_IRQ_INT17		(M32700UT_PLD_IRQ_BASE + 17)	/* reserved */
+#define PLD_IRQ_INT18		(M32700UT_PLD_IRQ_BASE + 18)	/* reserved */
+#define PLD_IRQ_INT19		(M32700UT_PLD_IRQ_BASE + 19)	/* reserved */
+#define PLD_IRQ_INT20		(M32700UT_PLD_IRQ_BASE + 20)	/* reserved */
+#define PLD_IRQ_INT21		(M32700UT_PLD_IRQ_BASE + 21)	/* reserved */
+#define PLD_IRQ_INT22		(M32700UT_PLD_IRQ_BASE + 22)	/* reserved */
+#define PLD_IRQ_INT23		(M32700UT_PLD_IRQ_BASE + 23)	/* reserved */
+#define PLD_IRQ_INT24		(M32700UT_PLD_IRQ_BASE + 24)	/* reserved */
+#define PLD_IRQ_INT25		(M32700UT_PLD_IRQ_BASE + 25)	/* reserved */
+#define PLD_IRQ_INT26		(M32700UT_PLD_IRQ_BASE + 26)	/* reserved */
+#define PLD_IRQ_INT27		(M32700UT_PLD_IRQ_BASE + 27)	/* reserved */
+#define PLD_IRQ_INT28		(M32700UT_PLD_IRQ_BASE + 28)	/* reserved */
+#define PLD_IRQ_INT29		(M32700UT_PLD_IRQ_BASE + 29)	/* reserved */
+#define PLD_IRQ_INT30		(M32700UT_PLD_IRQ_BASE + 30)	/* reserved */
+
+#endif	/* CONFIG_PLAT_USRV */
+
+#define PLD_ICUISTS		__reg16(PLD_BASE + 0x8002)
+#define PLD_ICUISTS_VECB_MASK	(0xf000)
+#define PLD_ICUISTS_VECB(x)	((x) & PLD_ICUISTS_VECB_MASK)
+#define PLD_ICUISTS_ISN_MASK	(0x07c0)
+#define PLD_ICUISTS_ISN(x)	((x) & PLD_ICUISTS_ISN_MASK)
+#define PLD_ICUIREQ0		__reg16(PLD_BASE + 0x8004)
+#define PLD_ICUIREQ1		__reg16(PLD_BASE + 0x8006)
+#define PLD_ICUCR1		__reg16(PLD_BASE + 0x8100)
+#define PLD_ICUCR2		__reg16(PLD_BASE + 0x8102)
+#define PLD_ICUCR3		__reg16(PLD_BASE + 0x8104)
+#define PLD_ICUCR4		__reg16(PLD_BASE + 0x8106)
+#define PLD_ICUCR5		__reg16(PLD_BASE + 0x8108)
+#define PLD_ICUCR6		__reg16(PLD_BASE + 0x810a)
+#define PLD_ICUCR7		__reg16(PLD_BASE + 0x810c)
+#define PLD_ICUCR8		__reg16(PLD_BASE + 0x810e)
+#define PLD_ICUCR9		__reg16(PLD_BASE + 0x8110)
+#define PLD_ICUCR10		__reg16(PLD_BASE + 0x8112)
+#define PLD_ICUCR11		__reg16(PLD_BASE + 0x8114)
+#define PLD_ICUCR12		__reg16(PLD_BASE + 0x8116)
+#define PLD_ICUCR13		__reg16(PLD_BASE + 0x8118)
+#define PLD_ICUCR14		__reg16(PLD_BASE + 0x811a)
+#define PLD_ICUCR15		__reg16(PLD_BASE + 0x811c)
+#define PLD_ICUCR16		__reg16(PLD_BASE + 0x811e)
+#define PLD_ICUCR17		__reg16(PLD_BASE + 0x8120)
+#define PLD_ICUCR_IEN		(0x1000)
+#define PLD_ICUCR_IREQ		(0x0100)
+#define PLD_ICUCR_ISMOD00	(0x0000)	/* Low edge */
+#define PLD_ICUCR_ISMOD01	(0x0010)	/* Low level */
+#define PLD_ICUCR_ISMOD02	(0x0020)	/* High edge */
+#define PLD_ICUCR_ISMOD03	(0x0030)	/* High level */
+#define PLD_ICUCR_ILEVEL0	(0x0000)
+#define PLD_ICUCR_ILEVEL1	(0x0001)
+#define PLD_ICUCR_ILEVEL2	(0x0002)
+#define PLD_ICUCR_ILEVEL3	(0x0003)
+#define PLD_ICUCR_ILEVEL4	(0x0004)
+#define PLD_ICUCR_ILEVEL5	(0x0005)
+#define PLD_ICUCR_ILEVEL6	(0x0006)
+#define PLD_ICUCR_ILEVEL7	(0x0007)
+
+/* Power Control of MMC and CF */
+#define PLD_CPCR		__reg16(PLD_BASE + 0x14000)
+#define PLD_CPCR_CF		0x0001
+#define PLD_CPCR_MMC		0x0002
+
+/* LED Control
+ *
+ * 1: DIP swich side
+ * 2: Reset switch side
+ */
+#define PLD_IOLEDCR		__reg16(PLD_BASE + 0x14002)
+#define PLD_IOLED_1_ON		0x001
+#define PLD_IOLED_1_OFF		0x000
+#define PLD_IOLED_2_ON		0x002
+#define PLD_IOLED_2_OFF		0x000
+
+/* DIP Switch
+ *  0: Write-protect of Flash Memory (0:protected, 1:non-protected)
+ *  1: -
+ *  2: -
+ *  3: -
+ */
+#define PLD_IOSWSTS		__reg16(PLD_BASE + 0x14004)
+#define	PLD_IOSWSTS_IOSW2	0x0200
+#define	PLD_IOSWSTS_IOSW1	0x0100
+#define	PLD_IOSWSTS_IOWP0	0x0001
+
+/* CRC */
+#define PLD_CRC7DATA		__reg16(PLD_BASE + 0x18000)
+#define PLD_CRC7INDATA		__reg16(PLD_BASE + 0x18002)
+#define PLD_CRC16DATA		__reg16(PLD_BASE + 0x18004)
+#define PLD_CRC16INDATA		__reg16(PLD_BASE + 0x18006)
+#define PLD_CRC16ADATA		__reg16(PLD_BASE + 0x18008)
+#define PLD_CRC16AINDATA	__reg16(PLD_BASE + 0x1800a)
+
+/* RTC */
+#define PLD_RTCCR		__reg16(PLD_BASE + 0x1c000)
+#define PLD_RTCBAUR		__reg16(PLD_BASE + 0x1c002)
+#define PLD_RTCWRDATA		__reg16(PLD_BASE + 0x1c004)
+#define PLD_RTCRDDATA		__reg16(PLD_BASE + 0x1c006)
+#define PLD_RTCRSTODT		__reg16(PLD_BASE + 0x1c008)
+
+/* SIO0 */
+#define PLD_ESIO0CR		__reg16(PLD_BASE + 0x20000)
+#define	PLD_ESIO0CR_TXEN	0x0001
+#define	PLD_ESIO0CR_RXEN	0x0002
+#define PLD_ESIO0MOD0		__reg16(PLD_BASE + 0x20002)
+#define	PLD_ESIO0MOD0_CTSS	0x0040
+#define	PLD_ESIO0MOD0_RTSS	0x0080
+#define PLD_ESIO0MOD1		__reg16(PLD_BASE + 0x20004)
+#define	PLD_ESIO0MOD1_LMFS	0x0010
+#define PLD_ESIO0STS		__reg16(PLD_BASE + 0x20006)
+#define	PLD_ESIO0STS_TEMP	0x0001
+#define	PLD_ESIO0STS_TXCP	0x0002
+#define	PLD_ESIO0STS_RXCP	0x0004
+#define	PLD_ESIO0STS_TXSC	0x0100
+#define	PLD_ESIO0STS_RXSC	0x0200
+#define PLD_ESIO0STS_TXREADY	(PLD_ESIO0STS_TXCP | PLD_ESIO0STS_TEMP)
+#define PLD_ESIO0INTCR		__reg16(PLD_BASE + 0x20008)
+#define	PLD_ESIO0INTCR_TXIEN	0x0002
+#define	PLD_ESIO0INTCR_RXCEN	0x0004
+#define PLD_ESIO0BAUR		__reg16(PLD_BASE + 0x2000a)
+#define PLD_ESIO0TXB		__reg16(PLD_BASE + 0x2000c)
+#define PLD_ESIO0RXB		__reg16(PLD_BASE + 0x2000e)
+
+/* SIM Card */
+#define PLD_SCCR		__reg16(PLD_BASE + 0x38000)
+#define PLD_SCMOD		__reg16(PLD_BASE + 0x38004)
+#define PLD_SCSTS		__reg16(PLD_BASE + 0x38006)
+#define PLD_SCINTCR		__reg16(PLD_BASE + 0x38008)
+#define PLD_SCBAUR		__reg16(PLD_BASE + 0x3800a)
+#define PLD_SCTXB		__reg16(PLD_BASE + 0x3800c)
+#define PLD_SCRXB		__reg16(PLD_BASE + 0x3800e)
+
+#endif	/* _M32700UT_M32700UT_PLD.H */
diff -Nru a/include/asm-m32r/m32r.h b/include/asm-m32r/m32r.h
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/include/asm-m32r/m32r.h	2004-10-18 14:57:23 -07:00
@@ -0,0 +1,134 @@
+#ifndef _ASM_M32R_M32R_H_
+#define _ASM_M32R_M32R_H_
+
+/*
+ * Renesas M32R processor
+ *
+ * Copyright (C) 2003, 2004  Renesas Technology Corp.
+ */
+
+#include <linux/config.h>
+
+/* Chip type */
+#if defined(CONFIG_CHIP_XNUX_MP) || defined(CONFIG_CHIP_XNUX2_MP)
+#include <asm/m32r_mp_fpga.h>
+#elif defined(CONFIG_CHIP_VDEC2) || defined(CONFIG_CHIP_XNUX2) \
+	|| defined(CONFIG_CHIP_M32700) || defined(CONFIG_CHIP_M32102) \
+        || defined(CONFIG_CHIP_OPSP)
+#include <asm/m32102.h>
+#include <asm/m32102peri.h>
+#endif
+
+/* Platform type */
+#if defined(CONFIG_PLAT_M32700UT)
+#include <asm/m32700ut/m32700ut_pld.h>
+#include <asm/m32700ut/m32700ut_lan.h>
+#include <asm/m32700ut/m32700ut_lcd.h>
+#endif  /* CONFIG_PLAT_M32700UT */
+
+#if defined(CONFIG_PLAT_OPSPUT)
+#include <asm/opsput/opsput_pld.h>
+#include <asm/opsput/opsput_lan.h>
+#include <asm/opsput/opsput_lcd.h>
+#endif  /* CONFIG_PLAT_OPSPUT */
+
+#if defined(CONFIG_PLAT_MAPPI2)
+#include <asm/mappi2/mappi2_pld.h>
+#endif	/* CONFIG_PLAT_MAPPI2 */
+
+#if defined(CONFIG_PLAT_USRV)
+#include <asm/m32700ut/m32700ut_pld.h>
+#endif
+
+/*
+ * M32R Register
+ */
+
+/*
+ * MMU Register
+ */
+
+#define MMU_REG_BASE	(0xffff0000)
+#define ITLB_BASE	(0xfe000000)
+#define DTLB_BASE	(0xfe000800)
+
+#define NR_TLB_ENTRIES	CONFIG_TLB_ENTRIES
+
+#define MATM	MMU_REG_BASE		/* MMU Address Translation Mode
+					   Register */
+#define MPSZ	(0x04 + MMU_REG_BASE)	/* MMU Page Size Designation Register */
+#define MASID	(0x08 + MMU_REG_BASE)	/* MMU Address Space ID Register */
+#define MESTS	(0x0c + MMU_REG_BASE)	/* MMU Exception Status Register */
+#define MDEVA	(0x10 + MMU_REG_BASE)	/* MMU Operand Exception Virtual
+					   Address Register */
+#define MDEVP	(0x14 + MMU_REG_BASE)	/* MMU Operand Exception Virtual Page
+					   Number Register */
+#define MPTB	(0x18 + MMU_REG_BASE)	/* MMU Page Table Base Register */
+#define MSVA	(0x20 + MMU_REG_BASE)	/* MMU Search Virtual Address
+					   Register */
+#define MTOP	(0x24 + MMU_REG_BASE)	/* MMU TLB Operation Register */
+#define MIDXI	(0x28 + MMU_REG_BASE)	/* MMU Index Register for
+					   Instruciton */
+#define MIDXD	(0x2c + MMU_REG_BASE)	/* MMU Index Register for Operand */
+
+#define MATM_offset	(MATM - MMU_REG_BASE)
+#define MPSZ_offset	(MPSZ - MMU_REG_BASE)
+#define MASID_offset	(MASID - MMU_REG_BASE)
+#define MESTS_offset	(MESTS - MMU_REG_BASE)
+#define MDEVA_offset	(MDEVA - MMU_REG_BASE)
+#define MDEVP_offset	(MDEVP - MMU_REG_BASE)
+#define MPTB_offset	(MPTB - MMU_REG_BASE)
+#define MSVA_offset	(MSVA - MMU_REG_BASE)
+#define MTOP_offset	(MTOP - MMU_REG_BASE)
+#define MIDXI_offset	(MIDXI - MMU_REG_BASE)
+#define MIDXD_offset	(MIDXD - MMU_REG_BASE)
+
+#define MESTS_IT	(1 << 0)	/* Instruction TLB miss */
+#define MESTS_IA	(1 << 1)	/* Instruction Access Exception */
+#define MESTS_DT	(1 << 4)	/* Operand TLB miss */
+#define MESTS_DA	(1 << 5)	/* Operand Access Exception */
+#define MESTS_DRW	(1 << 6)	/* Operand Write Exception Flag */
+
+/*
+ * PSW (Processor Status Word)
+ */
+
+/* PSW bit */
+#define M32R_PSW_BIT_SM   (7)    /* Stack Mode */
+#define M32R_PSW_BIT_IE   (6)    /* Interrupt Enable */
+#define M32R_PSW_BIT_PM   (3)    /* Processor Mode [0:Supervisor,1:User] */
+#define M32R_PSW_BIT_C    (0)    /* Condition */
+#define M32R_PSW_BIT_BSM  (7+8)  /* Backup Stack Mode */
+#define M32R_PSW_BIT_BIE  (6+8)  /* Backup Interrupt Enable */
+#define M32R_PSW_BIT_BPM  (3+8)  /* Backup Processor Mode */
+#define M32R_PSW_BIT_BC   (0+8)  /* Backup Condition */
+
+/* PSW bit map */
+#define M32R_PSW_SM   (1UL<< M32R_PSW_BIT_SM)   /* Stack Mode */
+#define M32R_PSW_IE   (1UL<< M32R_PSW_BIT_IE)   /* Interrupt Enable */
+#define M32R_PSW_PM   (1UL<< M32R_PSW_BIT_PM)   /* Processor Mode */
+#define M32R_PSW_C    (1UL<< M32R_PSW_BIT_C)    /* Condition */
+#define M32R_PSW_BSM  (1UL<< M32R_PSW_BIT_BSM)  /* Backup Stack Mode */
+#define M32R_PSW_BIE  (1UL<< M32R_PSW_BIT_BIE)  /* Backup Interrupt Enable */
+#define M32R_PSW_BPM  (1UL<< M32R_PSW_BIT_BPM)  /* Backup Processor Mode */
+#define M32R_PSW_BC   (1UL<< M32R_PSW_BIT_BC)   /* Backup Condition */
+
+/*
+ * Direct address to SFR
+ */
+
+#include <asm/page.h>
+#ifdef CONFIG_MMU
+#define NONCACHE_OFFSET  __PAGE_OFFSET+0x20000000
+#else
+#define NONCACHE_OFFSET  __PAGE_OFFSET
+#endif /* CONFIG_MMU */
+
+#define M32R_ICU_ISTS_ADDR  M32R_ICU_ISTS_PORTL+NONCACHE_OFFSET
+#define M32R_ICU_IPICR_ADDR  M32R_ICU_IPICR0_PORTL+NONCACHE_OFFSET
+#define M32R_ICU_IMASK_ADDR  M32R_ICU_IMASK_PORTL+NONCACHE_OFFSET
+#define M32R_FPGA_CPU_NAME_ADDR  M32R_FPGA_CPU_NAME0_PORTL+NONCACHE_OFFSET
+#define M32R_FPGA_MODEL_ID_ADDR  M32R_FPGA_MODEL_ID0_PORTL+NONCACHE_OFFSET
+#define M32R_FPGA_VERSION_ADDR   M32R_FPGA_VERSION0_PORTL+NONCACHE_OFFSET
+
+#endif /* _ASM_M32R_M32R_H_ */
diff -Nru a/include/asm-m32r/m32r_mp_fpga.h b/include/asm-m32r/m32r_mp_fpga.h
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/include/asm-m32r/m32r_mp_fpga.h	2004-10-18 14:57:24 -07:00
@@ -0,0 +1,313 @@
+#ifndef _ASM_M32R_M32R_MP_FPGA_
+#define _ASM_M32R_M32R_MP_FPGA_
+
+/*
+ * Renesas M32R-MP-FPGA
+ *
+ * Copyright (c) 2002  Hitoshi Yamamoto
+ * Copyright (c) 2003, 2004  Renesas Technology Corp.
+ */
+
+/*
+ * ========================================================
+ * M32R-MP-FPGA Memory Map
+ * ========================================================
+ * 0x00000000 : Block#0 : 64[MB]
+ *              0x03E00000 : SFR
+ *                           0x03E00000 : reserved
+ *                           0x03EF0000 : FPGA
+ *                           0x03EF1000 : reserved
+ *                           0x03EF4000 : CKM
+ *                           0x03EF4000 : BSELC
+ *                           0x03EF5000 : reserved
+ *                           0x03EFC000 : MFT
+ *                           0x03EFD000 : SIO
+ *                           0x03EFE000 : reserved
+ *                           0x03EFF000 : ICU
+ *              0x03F00000 : Internal SRAM 64[KB]
+ *              0x03F10000 : reserved
+ * --------------------------------------------------------
+ * 0x04000000 : Block#1 : 64[MB]
+ *              0x04000000 : Debug board SRAM 4[MB]
+ *              0x04400000 : reserved
+ * --------------------------------------------------------
+ * 0x08000000 : Block#2 : 64[MB]
+ * --------------------------------------------------------
+ * 0x0C000000 : Block#3 : 64[MB]
+ * --------------------------------------------------------
+ * 0x10000000 : Block#4 : 64[MB]
+ * --------------------------------------------------------
+ * 0x14000000 : Block#5 : 64[MB]
+ * --------------------------------------------------------
+ * 0x18000000 : Block#6 : 64[MB]
+ * --------------------------------------------------------
+ * 0x1C000000 : Block#7 : 64[MB]
+ * --------------------------------------------------------
+ * 0xFE000000 : TLB
+ *              0xFE000000 : ITLB
+ *              0xFE000080 : reserved
+ *              0xFE000800 : DTLB
+ *              0xFE000880 : reserved
+ * --------------------------------------------------------
+ * 0xFF000000 : System area
+ *              0xFFFF0000 : MMU
+ *              0xFFFF0030 : reserved
+ *              0xFFFF8000 : Debug function
+ *              0xFFFFA000 : reserved
+ *              0xFFFFC000 : CPU control
+ * 0xFFFFFFFF
+ * ========================================================
+ */
+
+/*======================================================================*
+ * Special Function Register
+ *======================================================================*/
+#define M32R_SFR_OFFSET  (0x00E00000)  /* 0x03E00000-0x03EFFFFF 1[MB] */
+
+/*
+ * FPGA registers.
+ */
+#define M32R_FPGA_TOP  (0x000F0000+M32R_SFR_OFFSET)
+
+#define M32R_FPGA_NUM_OF_CPUS_PORTL  (0x00+M32R_FPGA_TOP)
+#define M32R_FPGA_CPU_NAME0_PORTL    (0x10+M32R_FPGA_TOP)
+#define M32R_FPGA_CPU_NAME1_PORTL    (0x14+M32R_FPGA_TOP)
+#define M32R_FPGA_CPU_NAME2_PORTL    (0x18+M32R_FPGA_TOP)
+#define M32R_FPGA_CPU_NAME3_PORTL    (0x1C+M32R_FPGA_TOP)
+#define M32R_FPGA_MODEL_ID0_PORTL    (0x20+M32R_FPGA_TOP)
+#define M32R_FPGA_MODEL_ID1_PORTL    (0x24+M32R_FPGA_TOP)
+#define M32R_FPGA_MODEL_ID2_PORTL    (0x28+M32R_FPGA_TOP)
+#define M32R_FPGA_MODEL_ID3_PORTL    (0x2C+M32R_FPGA_TOP)
+#define M32R_FPGA_VERSION0_PORTL     (0x30+M32R_FPGA_TOP)
+#define M32R_FPGA_VERSION1_PORTL     (0x34+M32R_FPGA_TOP)
+
+/*
+ * Clock and Power Manager registers.
+ */
+#define M32R_CPM_OFFSET  (0x000F4000+M32R_SFR_OFFSET)
+
+#define M32R_CPM_CPUCLKCR_PORTL  (0x00+M32R_CPM_OFFSET)
+#define M32R_CPM_CLKMOD_PORTL    (0x04+M32R_CPM_OFFSET)
+#define M32R_CPM_PLLCR_PORTL     (0x08+M32R_CPM_OFFSET)
+
+/*
+ * Block SELect Controller registers.
+ */
+#define M32R_BSELC_OFFSET  (0x000F5000+M32R_SFR_OFFSET)
+
+#define M32R_BSEL0_CR0_PORTL  (0x000+M32R_BSELC_OFFSET)
+#define M32R_BSEL0_CR1_PORTL  (0x004+M32R_BSELC_OFFSET)
+#define M32R_BSEL1_CR0_PORTL  (0x100+M32R_BSELC_OFFSET)
+#define M32R_BSEL1_CR1_PORTL  (0x104+M32R_BSELC_OFFSET)
+#define M32R_BSEL2_CR0_PORTL  (0x200+M32R_BSELC_OFFSET)
+#define M32R_BSEL2_CR1_PORTL  (0x204+M32R_BSELC_OFFSET)
+#define M32R_BSEL3_CR0_PORTL  (0x300+M32R_BSELC_OFFSET)
+#define M32R_BSEL3_CR1_PORTL  (0x304+M32R_BSELC_OFFSET)
+#define M32R_BSEL4_CR0_PORTL  (0x400+M32R_BSELC_OFFSET)
+#define M32R_BSEL4_CR1_PORTL  (0x404+M32R_BSELC_OFFSET)
+#define M32R_BSEL5_CR0_PORTL  (0x500+M32R_BSELC_OFFSET)
+#define M32R_BSEL5_CR1_PORTL  (0x504+M32R_BSELC_OFFSET)
+#define M32R_BSEL6_CR0_PORTL  (0x600+M32R_BSELC_OFFSET)
+#define M32R_BSEL6_CR1_PORTL  (0x604+M32R_BSELC_OFFSET)
+#define M32R_BSEL7_CR0_PORTL  (0x700+M32R_BSELC_OFFSET)
+#define M32R_BSEL7_CR1_PORTL  (0x704+M32R_BSELC_OFFSET)
+
+/*
+ * Multi Function Timer registers.
+ */
+#define M32R_MFT_OFFSET        (0x000FC000+M32R_SFR_OFFSET)
+
+#define M32R_MFTCR_PORTL       (0x000+M32R_MFT_OFFSET)  /* MFT control */
+#define M32R_MFTRPR_PORTL      (0x004+M32R_MFT_OFFSET)  /* MFT real port */
+
+#define M32R_MFT0_OFFSET       (0x100+M32R_MFT_OFFSET)
+#define M32R_MFT0MOD_PORTL     (0x00+M32R_MFT0_OFFSET)  /* MFT0 mode */
+#define M32R_MFT0BOS_PORTL     (0x04+M32R_MFT0_OFFSET)  /* MFT0 b-port output status */
+#define M32R_MFT0CUT_PORTL     (0x08+M32R_MFT0_OFFSET)  /* MFT0 count */
+#define M32R_MFT0RLD_PORTL     (0x0C+M32R_MFT0_OFFSET)  /* MFT0 reload */
+#define M32R_MFT0CMPRLD_PORTL  (0x10+M32R_MFT0_OFFSET)  /* MFT0 compare reload */
+
+#define M32R_MFT1_OFFSET       (0x200+M32R_MFT_OFFSET)
+#define M32R_MFT1MOD_PORTL     (0x00+M32R_MFT1_OFFSET)  /* MFT1 mode */
+#define M32R_MFT1BOS_PORTL     (0x04+M32R_MFT1_OFFSET)  /* MFT1 b-port output status */
+#define M32R_MFT1CUT_PORTL     (0x08+M32R_MFT1_OFFSET)  /* MFT1 count */
+#define M32R_MFT1RLD_PORTL     (0x0C+M32R_MFT1_OFFSET)  /* MFT1 reload */
+#define M32R_MFT1CMPRLD_PORTL  (0x10+M32R_MFT1_OFFSET)  /* MFT1 compare reload */
+
+#define M32R_MFT2_OFFSET       (0x300+M32R_MFT_OFFSET)
+#define M32R_MFT2MOD_PORTL     (0x00+M32R_MFT2_OFFSET)  /* MFT2 mode */
+#define M32R_MFT2BOS_PORTL     (0x04+M32R_MFT2_OFFSET)  /* MFT2 b-port output status */
+#define M32R_MFT2CUT_PORTL     (0x08+M32R_MFT2_OFFSET)  /* MFT2 count */
+#define M32R_MFT2RLD_PORTL     (0x0C+M32R_MFT2_OFFSET)  /* MFT2 reload */
+#define M32R_MFT2CMPRLD_PORTL  (0x10+M32R_MFT2_OFFSET)  /* MFT2 compare reload */
+
+#define M32R_MFT3_OFFSET       (0x400+M32R_MFT_OFFSET)
+#define M32R_MFT3MOD_PORTL     (0x00+M32R_MFT3_OFFSET)  /* MFT3 mode */
+#define M32R_MFT3BOS_PORTL     (0x04+M32R_MFT3_OFFSET)  /* MFT3 b-port output status */
+#define M32R_MFT3CUT_PORTL     (0x08+M32R_MFT3_OFFSET)  /* MFT3 count */
+#define M32R_MFT3RLD_PORTL     (0x0C+M32R_MFT3_OFFSET)  /* MFT3 reload */
+#define M32R_MFT3CMPRLD_PORTL  (0x10+M32R_MFT3_OFFSET)  /* MFT3 compare reload */
+
+#define M32R_MFT4_OFFSET       (0x500+M32R_MFT_OFFSET)
+#define M32R_MFT4MOD_PORTL     (0x00+M32R_MFT4_OFFSET)  /* MFT4 mode */
+#define M32R_MFT4BOS_PORTL     (0x04+M32R_MFT4_OFFSET)  /* MFT4 b-port output status */
+#define M32R_MFT4CUT_PORTL     (0x08+M32R_MFT4_OFFSET)  /* MFT4 count */
+#define M32R_MFT4RLD_PORTL     (0x0C+M32R_MFT4_OFFSET)  /* MFT4 reload */
+#define M32R_MFT4CMPRLD_PORTL  (0x10+M32R_MFT4_OFFSET)  /* MFT4 compare reload */
+
+#define M32R_MFT5_OFFSET       (0x600+M32R_MFT_OFFSET)
+#define M32R_MFT5MOD_PORTL     (0x00+M32R_MFT5_OFFSET)  /* MFT4 mode */
+#define M32R_MFT5BOS_PORTL     (0x04+M32R_MFT5_OFFSET)  /* MFT4 b-port output status */
+#define M32R_MFT5CUT_PORTL     (0x08+M32R_MFT5_OFFSET)  /* MFT4 count */
+#define M32R_MFT5RLD_PORTL     (0x0C+M32R_MFT5_OFFSET)  /* MFT4 reload */
+#define M32R_MFT5CMPRLD_PORTL  (0x10+M32R_MFT5_OFFSET)  /* MFT4 compare reload */
+
+#define M32R_MFTCR_MFT0MSK  (1UL<<15)  /* b16 */
+#define M32R_MFTCR_MFT1MSK  (1UL<<14)  /* b17 */
+#define M32R_MFTCR_MFT2MSK  (1UL<<13)  /* b18 */
+#define M32R_MFTCR_MFT3MSK  (1UL<<12)  /* b19 */
+#define M32R_MFTCR_MFT4MSK  (1UL<<11)  /* b20 */
+#define M32R_MFTCR_MFT5MSK  (1UL<<10)  /* b21 */
+#define M32R_MFTCR_MFT0EN   (1UL<<7)   /* b24 */
+#define M32R_MFTCR_MFT1EN   (1UL<<6)   /* b25 */
+#define M32R_MFTCR_MFT2EN   (1UL<<5)   /* b26 */
+#define M32R_MFTCR_MFT3EN   (1UL<<4)   /* b27 */
+#define M32R_MFTCR_MFT4EN   (1UL<<3)   /* b28 */
+#define M32R_MFTCR_MFT5EN   (1UL<<2)   /* b29 */
+
+#define M32R_MFTMOD_CC_MASK    (1UL<<15)  /* b16 */
+#define M32R_MFTMOD_TCCR       (1UL<<13)  /* b18 */
+#define M32R_MFTMOD_GTSEL000   (0UL<<8)   /* b21-23 : 000 */
+#define M32R_MFTMOD_GTSEL001   (1UL<<8)   /* b21-23 : 001 */
+#define M32R_MFTMOD_GTSEL010   (2UL<<8)   /* b21-23 : 010 */
+#define M32R_MFTMOD_GTSEL011   (3UL<<8)   /* b21-23 : 011 */
+#define M32R_MFTMOD_GTSEL110   (6UL<<8)   /* b21-23 : 110 */
+#define M32R_MFTMOD_GTSEL111   (7UL<<8)   /* b21-23 : 111 */
+#define M32R_MFTMOD_CMSEL      (1UL<<3)   /* b28 */
+#define M32R_MFTMOD_CSSEL000   (0UL<<0)   /* b29-b31 : 000 */
+#define M32R_MFTMOD_CSSEL001   (1UL<<0)   /* b29-b31 : 001 */
+#define M32R_MFTMOD_CSSEL010   (2UL<<0)   /* b29-b31 : 010 */
+#define M32R_MFTMOD_CSSEL011   (3UL<<0)   /* b29-b31 : 011 */
+#define M32R_MFTMOD_CSSEL100   (4UL<<0)   /* b29-b31 : 100 */
+#define M32R_MFTMOD_CSSEL110   (6UL<<0)   /* b29-b31 : 110 */
+
+/*
+ * Serial I/O registers.
+ */
+#define M32R_SIO_OFFSET  (0x000FD000+M32R_SFR_OFFSET)
+
+#define M32R_SIO0_CR_PORTL     (0x000+M32R_SIO_OFFSET)
+#define M32R_SIO0_MOD0_PORTL   (0x004+M32R_SIO_OFFSET)
+#define M32R_SIO0_MOD1_PORTL   (0x008+M32R_SIO_OFFSET)
+#define M32R_SIO0_STS_PORTL    (0x00C+M32R_SIO_OFFSET)
+#define M32R_SIO0_TRCR_PORTL   (0x010+M32R_SIO_OFFSET)
+#define M32R_SIO0_BAUR_PORTL   (0x014+M32R_SIO_OFFSET)
+#define M32R_SIO0_RBAUR_PORTL  (0x018+M32R_SIO_OFFSET)
+#define M32R_SIO0_TXB_PORTL    (0x01C+M32R_SIO_OFFSET)
+#define M32R_SIO0_RXB_PORTL    (0x020+M32R_SIO_OFFSET)
+
+/*
+ * Interrupt Control Unit registers.
+ */
+#define M32R_ICU_OFFSET  (0x000FF000+M32R_SFR_OFFSET)
+
+#define M32R_ICU_ISTS_PORTL     (0x004+M32R_ICU_OFFSET)
+#define M32R_ICU_IREQ0_PORTL    (0x008+M32R_ICU_OFFSET)
+#define M32R_ICU_IREQ1_PORTL    (0x00C+M32R_ICU_OFFSET)
+#define M32R_ICU_SBICR_PORTL    (0x018+M32R_ICU_OFFSET)
+#define M32R_ICU_IMASK_PORTL    (0x01C+M32R_ICU_OFFSET)
+#define M32R_ICU_CR1_PORTL      (0x200+M32R_ICU_OFFSET)  /* INT0 */
+#define M32R_ICU_CR2_PORTL      (0x204+M32R_ICU_OFFSET)  /* INT1 */
+#define M32R_ICU_CR3_PORTL      (0x208+M32R_ICU_OFFSET)  /* INT2 */
+#define M32R_ICU_CR4_PORTL      (0x20C+M32R_ICU_OFFSET)  /* INT3 */
+#define M32R_ICU_CR5_PORTL      (0x210+M32R_ICU_OFFSET)  /* INT4 */
+#define M32R_ICU_CR6_PORTL      (0x214+M32R_ICU_OFFSET)  /* INT5 */
+#define M32R_ICU_CR7_PORTL      (0x218+M32R_ICU_OFFSET)  /* INT6 */
+#define M32R_ICU_CR8_PORTL      (0x218+M32R_ICU_OFFSET)  /* INT7 */
+#define M32R_ICU_CR32_PORTL     (0x27C+M32R_ICU_OFFSET)  /* SIO0 RX */
+#define M32R_ICU_CR33_PORTL     (0x280+M32R_ICU_OFFSET)  /* SIO0 TX */
+#define M32R_ICU_CR40_PORTL     (0x29C+M32R_ICU_OFFSET)  /* DMAC0 */
+#define M32R_ICU_CR41_PORTL     (0x2A0+M32R_ICU_OFFSET)  /* DMAC1 */
+#define M32R_ICU_CR48_PORTL     (0x2BC+M32R_ICU_OFFSET)  /* MFT0 */
+#define M32R_ICU_CR49_PORTL     (0x2C0+M32R_ICU_OFFSET)  /* MFT1 */
+#define M32R_ICU_CR50_PORTL     (0x2C4+M32R_ICU_OFFSET)  /* MFT2 */
+#define M32R_ICU_CR51_PORTL     (0x2C8+M32R_ICU_OFFSET)  /* MFT3 */
+#define M32R_ICU_CR52_PORTL     (0x2CC+M32R_ICU_OFFSET)  /* MFT4 */
+#define M32R_ICU_CR53_PORTL     (0x2D0+M32R_ICU_OFFSET)  /* MFT5 */
+#define M32R_ICU_IPICR0_PORTL   (0x2DC+M32R_ICU_OFFSET)  /* IPI0 */
+#define M32R_ICU_IPICR1_PORTL   (0x2E0+M32R_ICU_OFFSET)  /* IPI1 */
+#define M32R_ICU_IPICR2_PORTL   (0x2E4+M32R_ICU_OFFSET)  /* IPI2 */
+#define M32R_ICU_IPICR3_PORTL   (0x2E8+M32R_ICU_OFFSET)  /* IPI3 */
+#define M32R_ICU_IPICR4_PORTL   (0x2EC+M32R_ICU_OFFSET)  /* IPI4 */
+#define M32R_ICU_IPICR5_PORTL   (0x2F0+M32R_ICU_OFFSET)  /* IPI5 */
+#define M32R_ICU_IPICR6_PORTL   (0x2F4+M32R_ICU_OFFSET)  /* IPI6 */
+#define M32R_ICU_IPICR7_PORTL   (0x2FC+M32R_ICU_OFFSET)  /* IPI7 */
+
+#define M32R_ICUISTS_VECB(val)  ((val>>28) & 0xF)
+#define M32R_ICUISTS_ISN(val)   ((val>>22) & 0x3F)
+#define M32R_ICUISTS_PIML(val)  ((val>>16) & 0x7)
+
+#define M32R_ICUIMASK_IMSK0  (0UL<<16)  /* b13-b15: Disable interrupt */
+#define M32R_ICUIMASK_IMSK1  (1UL<<16)  /* b13-b15: Enable level 0 interrupt */
+#define M32R_ICUIMASK_IMSK2  (2UL<<16)  /* b13-b15: Enable level 0,1 interrupt */
+#define M32R_ICUIMASK_IMSK3  (3UL<<16)  /* b13-b15: Enable level 0-2 interrupt */
+#define M32R_ICUIMASK_IMSK4  (4UL<<16)  /* b13-b15: Enable level 0-3 interrupt */
+#define M32R_ICUIMASK_IMSK5  (5UL<<16)  /* b13-b15: Enable level 0-4 interrupt */
+#define M32R_ICUIMASK_IMSK6  (6UL<<16)  /* b13-b15: Enable level 0-5 interrupt */
+#define M32R_ICUIMASK_IMSK7  (7UL<<16)  /* b13-b15: Enable level 0-6 interrupt */
+
+#define M32R_ICUCR_IEN      (1UL<<12)  /* b19: Interrupt enable */
+#define M32R_ICUCR_IRQ      (1UL<<8)   /* b23: Interrupt request */
+#define M32R_ICUCR_ISMOD00  (0UL<<4)   /* b26-b27: Interrupt sense mode Edge HtoL */
+#define M32R_ICUCR_ISMOD01  (1UL<<4)   /* b26-b27: Interrupt sense mode Level L */
+#define M32R_ICUCR_ISMOD10  (2UL<<4)   /* b26-b27: Interrupt sense mode Edge LtoH*/
+#define M32R_ICUCR_ISMOD11  (3UL<<4)   /* b26-b27: Interrupt sense mode Level H */
+#define M32R_ICUCR_ILEVEL0  (0UL<<0)   /* b29-b31: Interrupt priority level 0 */
+#define M32R_ICUCR_ILEVEL1  (1UL<<0)   /* b29-b31: Interrupt priority level 1 */
+#define M32R_ICUCR_ILEVEL2  (2UL<<0)   /* b29-b31: Interrupt priority level 2 */
+#define M32R_ICUCR_ILEVEL3  (3UL<<0)   /* b29-b31: Interrupt priority level 3 */
+#define M32R_ICUCR_ILEVEL4  (4UL<<0)   /* b29-b31: Interrupt priority level 4 */
+#define M32R_ICUCR_ILEVEL5  (5UL<<0)   /* b29-b31: Interrupt priority level 5 */
+#define M32R_ICUCR_ILEVEL6  (6UL<<0)   /* b29-b31: Interrupt priority level 6 */
+#define M32R_ICUCR_ILEVEL7  (7UL<<0)   /* b29-b31: Disable interrupt */
+#define M32R_ICUCR_ILEVEL_MASK  (7UL)
+
+#define M32R_IRQ_INT0    (1)   /* INT0 */
+#define M32R_IRQ_INT1    (2)   /* INT1 */
+#define M32R_IRQ_INT2    (3)   /* INT2 */
+#define M32R_IRQ_INT3    (4)   /* INT3 */
+#define M32R_IRQ_INT4    (5)   /* INT4 */
+#define M32R_IRQ_INT5    (6)   /* INT5 */
+#define M32R_IRQ_INT6    (7)   /* INT6 */
+#define M32R_IRQ_INT7    (8)   /* INT7 */
+#define M32R_IRQ_MFT0    (16)  /* MFT0 */
+#define M32R_IRQ_MFT1    (17)  /* MFT1 */
+#define M32R_IRQ_MFT2    (18)  /* MFT2 */
+#define M32R_IRQ_MFT3    (19)  /* MFT3 */
+#define M32R_IRQ_MFT4    (20)  /* MFT4 */
+#define M32R_IRQ_MFT5    (21)  /* MFT5 */
+#define M32R_IRQ_DMAC0   (32)  /* DMAC0 */
+#define M32R_IRQ_DMAC1   (33)  /* DMAC1 */
+#define M32R_IRQ_SIO0_R  (48)  /* SIO0 receive */
+#define M32R_IRQ_SIO0_S  (49)  /* SIO0 send    */
+#define M32R_IRQ_SIO1_R  (50)  /* SIO1 send    */
+#define M32R_IRQ_SIO1_S  (51)  /* SIO1 receive */
+#define M32R_IRQ_IPI0    (56)  /* IPI0 */
+#define M32R_IRQ_IPI1    (57)  /* IPI1 */
+#define M32R_IRQ_IPI2    (58)  /* IPI2 */
+#define M32R_IRQ_IPI3    (59)  /* IPI3 */
+#define M32R_IRQ_IPI4    (60)  /* IPI4 */
+#define M32R_IRQ_IPI5    (61)  /* IPI5 */
+#define M32R_IRQ_IPI6    (62)  /* IPI6 */
+#define M32R_IRQ_IPI7    (63)  /* IPI7 */
+
+/*======================================================================*
+ * CPU
+ *======================================================================*/
+
+#define M32R_CPUID_PORTL   (0xFFFFFFE0)
+#define M32R_MCICAR_PORTL  (0xFFFFFFF0)
+#define M32R_MCDCAR_PORTL  (0xFFFFFFF4)
+#define M32R_MCCR_PORTL    (0xFFFFFFFC)
+
+#endif  /* _ASM_M32R_M32R_MP_FPGA_ */
diff -Nru a/include/asm-m32r/mappi2/mappi2_pld.h b/include/asm-m32r/mappi2/mappi2_pld.h
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/include/asm-m32r/mappi2/mappi2_pld.h	2004-10-18 14:57:23 -07:00
@@ -0,0 +1,151 @@
+/*
+ * include/asm/mappi2/mappi2_pld.h
+ *
+ * Definitions for Extended IO Logic on MAPPI2 board.
+ *  based on m32700ut_pld.h by
+ *
+ * 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.
+ *
+ */
+
+#ifndef _MAPPI2_PLD_H
+#define _MAPPI2_PLD_H
+
+#ifndef __ASSEMBLY__
+/* FIXME:
+ * Some C functions use non-cache address, so can't define non-cache address.
+ */
+#define PLD_BASE		(0x10c00000 /* + NONCACHE_OFFSET */)
+#define __reg8			(volatile unsigned char *)
+#define __reg16			(volatile unsigned short *)
+#define __reg32			(volatile unsigned int *)
+#else
+#define PLD_BASE		(0x10c00000 + NONCACHE_OFFSET)
+#define __reg8
+#define __reg16
+#define __reg32
+#endif	/* __ASSEMBLY__ */
+
+/* CFC */
+#define	PLD_CFRSTCR		__reg16(PLD_BASE + 0x0000)
+#define PLD_CFSTS		__reg16(PLD_BASE + 0x0002)
+#define PLD_CFIMASK		__reg16(PLD_BASE + 0x0004)
+#define PLD_CFBUFCR		__reg16(PLD_BASE + 0x0006)
+#define PLD_CFCR0		__reg16(PLD_BASE + 0x000a)
+#define PLD_CFCR1		__reg16(PLD_BASE + 0x000c)
+
+/* MMC */
+#define PLD_MMCCR		__reg16(PLD_BASE + 0x4000)
+#define PLD_MMCMOD		__reg16(PLD_BASE + 0x4002)
+#define PLD_MMCSTS		__reg16(PLD_BASE + 0x4006)
+#define PLD_MMCBAUR		__reg16(PLD_BASE + 0x400a)
+#define PLD_MMCCMDBCUT		__reg16(PLD_BASE + 0x400c)
+#define PLD_MMCCDTBCUT		__reg16(PLD_BASE + 0x400e)
+#define PLD_MMCDET		__reg16(PLD_BASE + 0x4010)
+#define PLD_MMCWP		__reg16(PLD_BASE + 0x4012)
+#define PLD_MMCWDATA		__reg16(PLD_BASE + 0x5000)
+#define PLD_MMCRDATA		__reg16(PLD_BASE + 0x6000)
+#define PLD_MMCCMDDATA		__reg16(PLD_BASE + 0x7000)
+#define PLD_MMCRSPDATA		__reg16(PLD_BASE + 0x7006)
+
+/* Power Control of MMC and CF */
+#define PLD_CPCR		__reg16(PLD_BASE + 0x14000)
+
+
+/*==== ICU ====*/
+#define  M32R_IRQ_PC104        (5)   /* INT4(PC/104) */
+#define  M32R_IRQ_I2C          (28)  /* I2C-BUS     */
+#if 1
+#define  PLD_IRQ_CFIREQ       (40)  /* CFC Card Interrupt */
+#define  PLD_IRQ_CFC_INSERT   (41)  /* CFC Card Insert */
+#define  PLD_IRQ_CFC_EJECT    (42)  /* CFC Card Eject */
+#define  PLD_IRQ_MMCCARD      (43)  /* MMC Card Insert */
+#define  PLD_IRQ_MMCIRQ       (44)  /* MMC Transfer Done */
+#else
+#define  PLD_IRQ_CFIREQ       (34)  /* CFC Card Interrupt */
+#define  PLD_IRQ_CFC_INSERT   (35)  /* CFC Card Insert */
+#define  PLD_IRQ_CFC_EJECT    (36)  /* CFC Card Eject */
+#define  PLD_IRQ_MMCCARD      (37)  /* MMC Card Insert */
+#define  PLD_IRQ_MMCIRQ       (38)  /* MMC Transfer Done */
+#endif
+
+
+#if 0
+/* LED Control
+ *
+ * 1: DIP swich side
+ * 2: Reset switch side
+ */
+#define PLD_IOLEDCR		__reg16(PLD_BASE + 0x14002)
+#define PLD_IOLED_1_ON		0x001
+#define PLD_IOLED_1_OFF		0x000
+#define PLD_IOLED_2_ON		0x002
+#define PLD_IOLED_2_OFF		0x000
+
+/* DIP Switch
+ *  0: Write-protect of Flash Memory (0:protected, 1:non-protected)
+ *  1: -
+ *  2: -
+ *  3: -
+ */
+#define PLD_IOSWSTS		__reg16(PLD_BASE + 0x14004)
+#define	PLD_IOSWSTS_IOSW2	0x0200
+#define	PLD_IOSWSTS_IOSW1	0x0100
+#define	PLD_IOSWSTS_IOWP0	0x0001
+
+#endif
+
+/* CRC */
+#define PLD_CRC7DATA		__reg16(PLD_BASE + 0x18000)
+#define PLD_CRC7INDATA		__reg16(PLD_BASE + 0x18002)
+#define PLD_CRC16DATA		__reg16(PLD_BASE + 0x18004)
+#define PLD_CRC16INDATA		__reg16(PLD_BASE + 0x18006)
+#define PLD_CRC16ADATA		__reg16(PLD_BASE + 0x18008)
+#define PLD_CRC16AINDATA	__reg16(PLD_BASE + 0x1800a)
+
+
+#if 0
+/* RTC */
+#define PLD_RTCCR		__reg16(PLD_BASE + 0x1c000)
+#define PLD_RTCBAUR		__reg16(PLD_BASE + 0x1c002)
+#define PLD_RTCWRDATA		__reg16(PLD_BASE + 0x1c004)
+#define PLD_RTCRDDATA		__reg16(PLD_BASE + 0x1c006)
+#define PLD_RTCRSTODT		__reg16(PLD_BASE + 0x1c008)
+
+/* SIO0 */
+#define PLD_ESIO0CR		__reg16(PLD_BASE + 0x20000)
+#define	PLD_ESIO0CR_TXEN	0x0001
+#define	PLD_ESIO0CR_RXEN	0x0002
+#define PLD_ESIO0MOD0		__reg16(PLD_BASE + 0x20002)
+#define	PLD_ESIO0MOD0_CTSS	0x0040
+#define	PLD_ESIO0MOD0_RTSS	0x0080
+#define PLD_ESIO0MOD1		__reg16(PLD_BASE + 0x20004)
+#define	PLD_ESIO0MOD1_LMFS	0x0010
+#define PLD_ESIO0STS		__reg16(PLD_BASE + 0x20006)
+#define	PLD_ESIO0STS_TEMP	0x0001
+#define	PLD_ESIO0STS_TXCP	0x0002
+#define	PLD_ESIO0STS_RXCP	0x0004
+#define	PLD_ESIO0STS_TXSC	0x0100
+#define	PLD_ESIO0STS_RXSC	0x0200
+#define PLD_ESIO0STS_TXREADY	(PLD_ESIO0STS_TXCP | PLD_ESIO0STS_TEMP)
+#define PLD_ESIO0INTCR		__reg16(PLD_BASE + 0x20008)
+#define	PLD_ESIO0INTCR_TXIEN	0x0002
+#define	PLD_ESIO0INTCR_RXCEN	0x0004
+#define PLD_ESIO0BAUR		__reg16(PLD_BASE + 0x2000a)
+#define PLD_ESIO0TXB		__reg16(PLD_BASE + 0x2000c)
+#define PLD_ESIO0RXB		__reg16(PLD_BASE + 0x2000e)
+
+/* SIM Card */
+#define PLD_SCCR		__reg16(PLD_BASE + 0x38000)
+#define PLD_SCMOD		__reg16(PLD_BASE + 0x38004)
+#define PLD_SCSTS		__reg16(PLD_BASE + 0x38006)
+#define PLD_SCINTCR		__reg16(PLD_BASE + 0x38008)
+#define PLD_SCBAUR		__reg16(PLD_BASE + 0x3800a)
+#define PLD_SCTXB		__reg16(PLD_BASE + 0x3800c)
+#define PLD_SCRXB		__reg16(PLD_BASE + 0x3800e)
+
+#endif
+
+#endif	/* _MAPPI2_PLD.H */
diff -Nru a/include/asm-m32r/mc146818rtc.h b/include/asm-m32r/mc146818rtc.h
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/include/asm-m32r/mc146818rtc.h	2004-10-18 14:57:24 -07:00
@@ -0,0 +1,32 @@
+/*
+ * Machine dependent access functions for RTC registers.
+ */
+#ifndef _ASM_MC146818RTC_H
+#define _ASM_MC146818RTC_H
+
+#include <asm/io.h>
+
+#ifndef RTC_PORT
+// #define RTC_PORT(x)	(0x70 + (x))
+#define RTC_PORT(x)	((x))
+#define RTC_ALWAYS_BCD	1	/* RTC operates in binary mode */
+#endif
+
+/*
+ * The yet supported machines all access the RTC index register via
+ * an ISA port access but the way to access the date register differs ...
+ */
+#define CMOS_READ(addr) ({ \
+outb_p((addr),RTC_PORT(0)); \
+inb_p(RTC_PORT(1)); \
+})
+#define CMOS_WRITE(val, addr) ({ \
+outb_p((addr),RTC_PORT(0)); \
+outb_p((val),RTC_PORT(1)); \
+})
+
+#define RTC_IRQ 8
+#if 0
+#endif
+
+#endif /* _ASM_MC146818RTC_H */
diff -Nru a/include/asm-m32r/mman.h b/include/asm-m32r/mman.h
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/include/asm-m32r/mman.h	2004-10-18 14:57:23 -07:00
@@ -0,0 +1,45 @@
+#ifndef __M32R_MMAN_H__
+#define __M32R_MMAN_H__
+
+/* orig : i386 2.6.0-test6 */
+
+#define PROT_READ	0x1		/* page can be read */
+#define PROT_WRITE	0x2		/* page can be written */
+#define PROT_EXEC	0x4		/* page can be executed */
+#define PROT_SEM	0x8		/* page may be used for atomic ops */
+#define PROT_NONE	0x0		/* page can not be accessed */
+#define PROT_GROWSDOWN	0x01000000	/* mprotect flag: extend change to start of growsdown vma */
+#define PROT_GROWSUP	0x02000000	/* mprotect flag: extend change to end of growsup vma */
+
+#define MAP_SHARED	0x01		/* Share changes */
+#define MAP_PRIVATE	0x02		/* Changes are private */
+#define MAP_TYPE	0x0f		/* Mask for type of mapping */
+#define MAP_FIXED	0x10		/* Interpret addr exactly */
+#define MAP_ANONYMOUS	0x20		/* don't use a file */
+
+#define MAP_GROWSDOWN	0x0100		/* stack-like segment */
+#define MAP_DENYWRITE	0x0800		/* ETXTBSY */
+#define MAP_EXECUTABLE	0x1000		/* mark it as an executable */
+#define MAP_LOCKED	0x2000		/* pages are locked */
+#define MAP_NORESERVE	0x4000		/* don't check for reservations */
+#define MAP_POPULATE	0x8000		/* populate (prefault) pagetables */
+#define MAP_NONBLOCK	0x10000		/* do not block on IO */
+
+#define MS_ASYNC	1		/* sync memory asynchronously */
+#define MS_INVALIDATE	2		/* invalidate the caches */
+#define MS_SYNC		4		/* synchronous memory sync */
+
+#define MCL_CURRENT	1		/* lock all current mappings */
+#define MCL_FUTURE	2		/* lock all future mappings */
+
+#define MADV_NORMAL	0x0		/* default page-in behavior */
+#define MADV_RANDOM	0x1		/* page-in minimum required */
+#define MADV_SEQUENTIAL	0x2		/* read-ahead aggressively */
+#define MADV_WILLNEED	0x3		/* pre-fault pages */
+#define MADV_DONTNEED	0x4		/* discard these pages */
+
+/* compatibility flags */
+#define MAP_ANON	MAP_ANONYMOUS
+#define MAP_FILE	0
+
+#endif /* __M32R_MMAN_H__ */
diff -Nru a/include/asm-m32r/mmu.h b/include/asm-m32r/mmu.h
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/include/asm-m32r/mmu.h	2004-10-18 14:57:23 -07:00
@@ -0,0 +1,35 @@
+#ifndef _ASM_M32R_MMU_H
+#define _ASM_M32R_MMU_H
+
+/* $Id$ */
+
+#include <linux/config.h>
+
+#if !defined(CONFIG_MMU)
+struct mm_rblock_struct {
+  int     size;
+  int     refcount;
+  void    *kblock;
+};
+
+struct mm_tblock_struct {
+  struct mm_rblock_struct *rblock;
+  struct mm_tblock_struct *next;
+};
+
+typedef struct {
+  struct mm_tblock_struct tblock;
+  unsigned long           end_brk;
+} mm_context_t;
+#else
+
+/* Default "unsigned long" context */
+#ifndef CONFIG_SMP
+typedef unsigned long mm_context_t;
+#else
+typedef unsigned long mm_context_t[NR_CPUS];
+#endif
+
+#endif  /* CONFIG_MMU */
+#endif  /* _ASM_M32R_MMU_H */
+
diff -Nru a/include/asm-m32r/mmu_context.h b/include/asm-m32r/mmu_context.h
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/include/asm-m32r/mmu_context.h	2004-10-18 14:57:24 -07:00
@@ -0,0 +1,169 @@
+#ifndef _ASM_M32R_MMU_CONTEXT_H
+#define _ASM_M32R_MMU_CONTEXT_H
+
+/* $Id */
+
+#include <linux/config.h>
+
+#include <asm/m32r.h>
+
+#define MMU_CONTEXT_ASID_MASK      (0x000000FF)
+#define MMU_CONTEXT_VERSION_MASK   (0xFFFFFF00)
+#define MMU_CONTEXT_FIRST_VERSION  (0x00000100)
+#define NO_CONTEXT                 (0x00000000)
+
+
+#ifndef __ASSEMBLY__
+
+#include <linux/config.h>
+#include <asm/atomic.h>
+#include <asm/pgalloc.h>
+#include <asm/mmu.h>
+#include <asm/tlbflush.h>
+
+/*
+ * Cache of MMU context last used.
+ */
+#ifndef CONFIG_SMP
+extern unsigned long mmu_context_cache_dat;
+#define mmu_context_cache	mmu_context_cache_dat
+#define mm_context(mm)		mm->context
+#else /* not CONFIG_SMP */
+extern unsigned long mmu_context_cache_dat[];
+#define mmu_context_cache	mmu_context_cache_dat[smp_processor_id()]
+#define mm_context(mm)		mm->context[smp_processor_id()]
+#endif /* not CONFIG_SMP */
+
+#define set_tlb_tag(entry, tag)	(*entry = (tag & PAGE_MASK)|get_asid())
+#define set_tlb_data(entry, data)	(*entry = (data | _PAGE_PRESENT))
+
+#ifdef CONFIG_MMU
+#define enter_lazy_tlb(mm, tsk)	do { } while (0)
+
+static __inline__ void get_new_mmu_context(struct mm_struct *mm)
+{
+	unsigned long mc = ++mmu_context_cache;
+
+	if (!(mc & MMU_CONTEXT_ASID_MASK)) {
+		/* We exhaust ASID of this version.
+		   Flush all TLB and start new cycle. */
+		local_flush_tlb_all();
+		/* Fix version if needed.
+		   Note that we avoid version #0 to distingush NO_CONTEXT. */
+		if (!mc)
+			mmu_context_cache = mc = MMU_CONTEXT_FIRST_VERSION;
+	}
+	mm_context(mm) = mc;
+}
+
+/*
+ * Get MMU context if needed.
+ */
+static __inline__ void get_mmu_context(struct mm_struct *mm)
+{
+	if (mm) {
+		unsigned long mc = mmu_context_cache;
+
+		/* Check if we have old version of context.
+		   If it's old, we need to get new context with new version. */
+		if ((mm_context(mm) ^ mc) & MMU_CONTEXT_VERSION_MASK)
+			get_new_mmu_context(mm);
+	}
+}
+
+/*
+ * Initialize the context related info for a new mm_struct
+ * instance.
+ */
+static __inline__ int init_new_context(struct task_struct *tsk,
+	struct mm_struct *mm)
+{
+#ifndef CONFIG_SMP
+	mm->context = NO_CONTEXT;
+#else /* CONFIG_SMP */
+	int num_cpus = num_online_cpus();
+	int i;
+
+	for (i = 0 ; i < num_cpus ; i++)
+		mm->context[i] = NO_CONTEXT;
+#endif /* CONFIG_SMP */
+
+	return 0;
+}
+
+/*
+ * Destroy context related info for an mm_struct that is about
+ * to be put to rest.
+ */
+#define destroy_context(mm)	do { } while (0)
+
+static __inline__ void set_asid(unsigned long asid)
+{
+	*(volatile unsigned long *)MASID = (asid & MMU_CONTEXT_ASID_MASK);
+}
+
+static __inline__ unsigned long get_asid(void)
+{
+	unsigned long asid;
+
+	asid = *(volatile long *)MASID;
+	asid &= MMU_CONTEXT_ASID_MASK;
+
+	return asid;
+}
+
+/*
+ * After we have set current->mm to a new value, this activates
+ * the context for the new mm so we see the new mappings.
+ */
+static __inline__ void activate_context(struct mm_struct *mm)
+{
+	get_mmu_context(mm);
+	set_asid(mm_context(mm) & MMU_CONTEXT_ASID_MASK);
+}
+
+static __inline__ void switch_mm(struct mm_struct *prev,
+	struct mm_struct *next, struct task_struct *tsk)
+{
+#ifdef CONFIG_SMP
+	int cpu = smp_processor_id();
+#endif	/* CONFIG_SMP */
+
+	if (prev != next) {
+#ifdef CONFIG_SMP
+		cpu_set(cpu, next->cpu_vm_mask);
+#endif /* CONFIG_SMP */
+		/* Set MPTB = next->pgd */
+		*(volatile unsigned long *)MPTB = (unsigned long)next->pgd;
+		activate_context(next);
+	}
+#ifdef CONFIG_SMP
+	else
+		if (!cpu_test_and_set(cpu, next->cpu_vm_mask))
+			activate_context(next);
+#endif /* CONFIG_SMP */
+}
+
+#define deactivate_mm(tsk, mm)	do { } while (0)
+
+#define activate_mm(prev, next)	\
+	switch_mm((prev), (next), NULL)
+
+#else
+#define get_mmu_context(mm)             do { } while (0)
+#define init_new_context(tsk,mm)        (0)
+#define destroy_context(mm)             do { } while (0)
+#define set_asid(asid)                  do { } while (0)
+#define get_asid()                      (0)
+#define activate_context(mm)            do { } while (0)
+#define switch_mm(prev,next,tsk)        do { } while (0)
+#define deactivate_mm(mm,tsk)           do { } while (0)
+#define activate_mm(prev,next)          do { } while (0)
+#define enter_lazy_tlb(mm,tsk)          do { } while (0)
+#endif /* CONFIG_MMU */
+
+
+#endif /* not __ASSEMBLY__ */
+
+#endif /* _ASM_M32R_MMU_CONTEXT_H */
+
diff -Nru a/include/asm-m32r/mmzone.h b/include/asm-m32r/mmzone.h
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/include/asm-m32r/mmzone.h	2004-10-18 14:57:23 -07:00
@@ -0,0 +1,80 @@
+/*
+ * Written by Pat Gaughen (gone@us.ibm.com) Mar 2002
+ *
+ */
+
+#ifndef _ASM_MMZONE_H_
+#define _ASM_MMZONE_H_
+
+#include <asm/smp.h>
+
+#ifdef CONFIG_DISCONTIGMEM
+
+extern struct pglist_data *node_data[];
+#define NODE_DATA(nid)		(node_data[nid])
+
+#define node_localnr(pfn, nid)	((pfn) - NODE_DATA(nid)->node_start_pfn)
+#define node_mem_map(nid)	(NODE_DATA(nid)->node_mem_map)
+#define node_start_pfn(nid)	(NODE_DATA(nid)->node_start_pfn)
+#define node_end_pfn(nid)						\
+({									\
+	pg_data_t *__pgdat = NODE_DATA(nid);				\
+	__pgdat->node_start_pfn + __pgdat->node_spanned_pages - 1;	\
+})
+
+#define local_mapnr(kvaddr)						\
+({									\
+	unsigned long __pfn = __pa(kvaddr) >> PAGE_SHIFT;		\
+	(__pfn - node_start_pfn(pfn_to_nid(__pfn)));			\
+})
+
+#define pfn_to_page(pfn)						\
+({									\
+	unsigned long __pfn = pfn;					\
+	int __node  = pfn_to_nid(__pfn);				\
+	&node_mem_map(__node)[node_localnr(__pfn,__node)];		\
+})
+
+#define page_to_pfn(pg)							\
+({									\
+	struct page *__page = pg;					\
+	struct zone *__zone = page_zone(__page);			\
+	(unsigned long)(__page - __zone->zone_mem_map)			\
+		+ __zone->zone_start_pfn;				\
+})
+#define pmd_page(pmd)		(pfn_to_page(pmd_val(pmd) >> PAGE_SHIFT))
+/*
+ * pfn_valid should be made as fast as possible, and the current definition
+ * is valid for machines that are NUMA, but still contiguous, which is what
+ * is currently supported. A more generalised, but slower definition would
+ * be something like this - mbligh:
+ * ( pfn_to_pgdat(pfn) && ((pfn) < node_end_pfn(pfn_to_nid(pfn))) )
+ */
+#if 1	/* M32R_FIXME */
+#define pfn_valid(pfn)	(1)
+#else
+#define pfn_valid(pfn)	((pfn) < num_physpages)
+#endif
+
+/*
+ * generic node memory support, the following assumptions apply:
+ */
+
+static __inline__ int pfn_to_nid(unsigned long pfn)
+{
+	int node;
+
+	for (node = 0 ; node < MAX_NUMNODES ; node++)
+		if (pfn >= node_start_pfn(node) && pfn <= node_end_pfn(node))
+			break;
+
+	return node;
+}
+
+static __inline__ struct pglist_data *pfn_to_pgdat(unsigned long pfn)
+{
+	return(NODE_DATA(pfn_to_nid(pfn)));
+}
+
+#endif /* CONFIG_DISCONTIGMEM */
+#endif /* _ASM_MMZONE_H_ */
diff -Nru a/include/asm-m32r/module.h b/include/asm-m32r/module.h
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/include/asm-m32r/module.h	2004-10-18 14:57:24 -07:00
@@ -0,0 +1,13 @@
+#ifndef _ASM_M32R_MODULE_H
+#define _ASM_M32R_MODULE_H
+
+/* $Id$ */
+
+struct mod_arch_specific { };
+
+#define Elf_Shdr	Elf32_Shdr
+#define Elf_Sym		Elf32_Sym
+#define Elf_Ehdr	Elf32_Ehdr
+
+#endif /* _ASM_M32R_MODULE_H */
+
diff -Nru a/include/asm-m32r/msgbuf.h b/include/asm-m32r/msgbuf.h
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/include/asm-m32r/msgbuf.h	2004-10-18 14:57:21 -07:00
@@ -0,0 +1,35 @@
+#ifndef _ASM_M32R_MSGBUF_H
+#define _ASM_M32R_MSGBUF_H
+
+/* $Id$ */
+
+/* orig : i386 2.4.18 */
+
+/*
+ * The msqid64_ds structure for m32r architecture.
+ * Note extra padding because this structure is passed back and forth
+ * between kernel and user space.
+ *
+ * Pad space is left for:
+ * - 64-bit time_t to solve y2038 problem
+ * - 2 miscellaneous 32-bit values
+ */
+
+struct msqid64_ds {
+	struct ipc64_perm msg_perm;
+	__kernel_time_t msg_stime;	/* last msgsnd time */
+	unsigned long	__unused1;
+	__kernel_time_t msg_rtime;	/* last msgrcv time */
+	unsigned long	__unused2;
+	__kernel_time_t msg_ctime;	/* last change time */
+	unsigned long	__unused3;
+	unsigned long  msg_cbytes;	/* current number of bytes on queue */
+	unsigned long  msg_qnum;	/* number of messages in queue */
+	unsigned long  msg_qbytes;	/* max number of bytes on queue */
+	__kernel_pid_t msg_lspid;	/* pid of last msgsnd */
+	__kernel_pid_t msg_lrpid;	/* last receive pid */
+	unsigned long  __unused4;
+	unsigned long  __unused5;
+};
+
+#endif /* _ASM_M32R_MSGBUF_H */
diff -Nru a/include/asm-m32r/namei.h b/include/asm-m32r/namei.h
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/include/asm-m32r/namei.h	2004-10-18 14:57:24 -07:00
@@ -0,0 +1,21 @@
+#ifndef _ASM_M32R_NAMEI_H
+#define _ASM_M32R_NAMEI_H
+
+/* $Id$ */
+
+/* orig : i386 2.4.18 */
+
+/*
+ * linux/include/asm-m32r/namei.h
+ *
+ * Included from linux/fs/namei.c
+ */
+
+/* This dummy routine maybe changed to something useful
+ * for /usr/gnemul/ emulation stuff.
+ * Look at asm-sparc/namei.h for details.
+ */
+
+#define __emul_prefix() NULL
+
+#endif /* _ASM_M32R_NAMEI_H */
diff -Nru a/include/asm-m32r/numnodes.h b/include/asm-m32r/numnodes.h
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/include/asm-m32r/numnodes.h	2004-10-18 14:57:23 -07:00
@@ -0,0 +1,15 @@
+#ifndef _ASM_NUMNODES_H_
+#define _ASM_NUMNODES_H_
+
+#include <linux/config.h>
+
+#ifdef CONFIG_DISCONTIGMEM
+
+#if defined(CONFIG_CHIP_M32700)
+#define	NODES_SHIFT	1	/* Max 2 Nodes */
+#endif	/* CONFIG_CHIP_M32700 */
+
+#endif	/* CONFIG_DISCONTIGMEM */
+
+#endif	/* _ASM_NUMNODES_H_ */
+
diff -Nru a/include/asm-m32r/opsput/opsput_lan.h b/include/asm-m32r/opsput/opsput_lan.h
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/include/asm-m32r/opsput/opsput_lan.h	2004-10-18 14:57:21 -07:00
@@ -0,0 +1,56 @@
+/*
+ * include/asm/opsput_lan.h
+ *
+ * OPSPUT-LAN board
+ *
+ * Copyright (c) 2002-2004	Takeo Takahashi, Mamoru Sakugawa
+ *
+ * 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.
+ *
+ * $Id: opsput_lan.h,v 1.1 2004/07/27 06:54:20 sakugawa Exp $
+ */
+
+#ifndef _OPSPUT_OPSPUT_LAN_H
+#define _OPSPUT_OPSPUT_LAN_H
+
+#include <linux/config.h>
+
+#ifndef __ASSEMBLY__
+/*
+ * C functions use non-cache address.
+ */
+#define OPSPUT_LAN_BASE	(0x10000000 /* + NONCACHE_OFFSET */)
+#else
+#define OPSPUT_LAN_BASE	(0x10000000 + NONCACHE_OFFSET)
+#endif	/* __ASSEMBLY__ */
+
+/* ICU
+ *  ICUISTS:	status register
+ *  ICUIREQ0: 	request register
+ *  ICUIREQ1: 	request register
+ *  ICUCR3:	control register for CFIREQ# interrupt
+ *  ICUCR4:	control register for CFC Card insert interrupt
+ *  ICUCR5:	control register for CFC Card eject interrupt
+ *  ICUCR6:	control register for external interrupt
+ *  ICUCR11:	control register for MMC Card insert/eject interrupt
+ *  ICUCR13:	control register for SC error interrupt
+ *  ICUCR14:	control register for SC receive interrupt
+ *  ICUCR15:	control register for SC send interrupt
+ *  ICUCR16:	control register for SIO0 receive interrupt
+ *  ICUCR17:	control register for SIO0 send interrupt
+ */
+#define OPSPUT_LAN_IRQ_LAN	(OPSPUT_LAN_PLD_IRQ_BASE + 1)	/* LAN */
+#define OPSPUT_LAN_IRQ_I2C	(OPSPUT_LAN_PLD_IRQ_BASE + 3)	/* I2C */
+
+#define OPSPUT_LAN_ICUISTS	__reg16(OPSPUT_LAN_BASE + 0xc0002)
+#define OPSPUT_LAN_ICUISTS_VECB_MASK	(0xf000)
+#define OPSPUT_LAN_VECB(x)	((x) & OPSPUT_LAN_ICUISTS_VECB_MASK)
+#define OPSPUT_LAN_ICUISTS_ISN_MASK	(0x07c0)
+#define OPSPUT_LAN_ICUISTS_ISN(x)	((x) & OPSPUT_LAN_ICUISTS_ISN_MASK)
+#define OPSPUT_LAN_ICUIREQ0	__reg16(OPSPUT_LAN_BASE + 0xc0004)
+#define OPSPUT_LAN_ICUCR1	__reg16(OPSPUT_LAN_BASE + 0xc0010)
+#define OPSPUT_LAN_ICUCR3	__reg16(OPSPUT_LAN_BASE + 0xc0014)
+
+#endif	/* _OPSPUT_OPSPUT_LAN_H */
diff -Nru a/include/asm-m32r/opsput/opsput_lcd.h b/include/asm-m32r/opsput/opsput_lcd.h
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/include/asm-m32r/opsput/opsput_lcd.h	2004-10-18 14:57:23 -07:00
@@ -0,0 +1,59 @@
+/*
+ * include/asm/opsput_lcd.h
+ *
+ * OPSPUT-LCD board
+ *
+ * Copyright (c) 2002	Takeo Takahashi
+ *
+ * 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.
+ *
+ * $Id: opsput_lcd.h,v 1.1 2004/07/27 06:54:20 sakugawa Exp $
+ */
+
+#ifndef _OPSPUT_OPSPUT_LCD_H
+#define _OPSPUT_OPSPUT_LCD_H
+
+#include <linux/config.h>
+
+#ifndef __ASSEMBLY__
+/*
+ * C functions use non-cache address.
+ */
+#define OPSPUT_LCD_BASE	(0x10000000 /* + NONCACHE_OFFSET */)
+#else
+#define OPSPUT_LCD_BASE	(0x10000000 + NONCACHE_OFFSET)
+#endif	/* __ASSEMBLY__ */
+
+/*
+ * ICU
+ */
+#define OPSPUT_LCD_IRQ_BAT_INT	(OPSPUT_LCD_PLD_IRQ_BASE + 1)
+#define OPSPUT_LCD_IRQ_USB_INT1	(OPSPUT_LCD_PLD_IRQ_BASE + 2)
+#define OPSPUT_LCD_IRQ_AUDT0		(OPSPUT_LCD_PLD_IRQ_BASE + 3)
+#define OPSPUT_LCD_IRQ_AUDT2		(OPSPUT_LCD_PLD_IRQ_BASE + 4)
+#define OPSPUT_LCD_IRQ_BATSIO_RCV	(OPSPUT_LCD_PLD_IRQ_BASE + 16)
+#define OPSPUT_LCD_IRQ_BATSIO_SND	(OPSPUT_LCD_PLD_IRQ_BASE + 17)
+#define OPSPUT_LCD_IRQ_ASNDSIO_RCV	(OPSPUT_LCD_PLD_IRQ_BASE + 18)
+#define OPSPUT_LCD_IRQ_ASNDSIO_SND	(OPSPUT_LCD_PLD_IRQ_BASE + 19)
+#define OPSPUT_LCD_IRQ_ACNLSIO_SND	(OPSPUT_LCD_PLD_IRQ_BASE + 21)
+
+#define OPSPUT_LCD_ICUISTS	__reg16(OPSPUT_LCD_BASE + 0x300002)
+#define OPSPUT_LCD_ICUISTS_VECB_MASK	(0xf000)
+#define OPSPUT_LCD_VECB(x)	((x) & OPSPUT_LCD_ICUISTS_VECB_MASK)
+#define OPSPUT_LCD_ICUISTS_ISN_MASK	(0x07c0)
+#define OPSPUT_LCD_ICUISTS_ISN(x)	((x) & OPSPUT_LCD_ICUISTS_ISN_MASK)
+#define OPSPUT_LCD_ICUIREQ0	__reg16(OPSPUT_LCD_BASE + 0x300004)
+#define OPSPUT_LCD_ICUIREQ1	__reg16(OPSPUT_LCD_BASE + 0x300006)
+#define OPSPUT_LCD_ICUCR1	__reg16(OPSPUT_LCD_BASE + 0x300020)
+#define OPSPUT_LCD_ICUCR2	__reg16(OPSPUT_LCD_BASE + 0x300022)
+#define OPSPUT_LCD_ICUCR3	__reg16(OPSPUT_LCD_BASE + 0x300024)
+#define OPSPUT_LCD_ICUCR4	__reg16(OPSPUT_LCD_BASE + 0x300026)
+#define OPSPUT_LCD_ICUCR16	__reg16(OPSPUT_LCD_BASE + 0x300030)
+#define OPSPUT_LCD_ICUCR17	__reg16(OPSPUT_LCD_BASE + 0x300032)
+#define OPSPUT_LCD_ICUCR18	__reg16(OPSPUT_LCD_BASE + 0x300034)
+#define OPSPUT_LCD_ICUCR19	__reg16(OPSPUT_LCD_BASE + 0x300036)
+#define OPSPUT_LCD_ICUCR21	__reg16(OPSPUT_LCD_BASE + 0x30003a)
+
+#endif	/* _OPSPUT_OPSPUT_LCD_H */
diff -Nru a/include/asm-m32r/opsput/opsput_pld.h b/include/asm-m32r/opsput/opsput_pld.h
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/include/asm-m32r/opsput/opsput_pld.h	2004-10-18 14:57:21 -07:00
@@ -0,0 +1,259 @@
+/*
+ * include/asm/opsput/opsput_pld.h
+ *
+ * Definitions for Programable Logic Device(PLD) on OPSPUT board.
+ *
+ * Copyright (c) 2002	Takeo Takahashi
+ *
+ * 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.
+ *
+ * $Id: opsput_pld.h,v 1.1 2004/07/27 06:54:20 sakugawa Exp $
+ */
+
+#ifndef _OPSPUT_OPSPUT_PLD_H
+#define _OPSPUT_OPSPUT_PLD_H
+
+#include <linux/config.h>
+
+#define PLD_PLAT_BASE		0x1cc00000
+
+#ifndef __ASSEMBLY__
+/*
+ * C functions use non-cache address.
+ */
+#define PLD_BASE		(PLD_PLAT_BASE /* + NONCACHE_OFFSET */)
+#define __reg8			(volatile unsigned char *)
+#define __reg16			(volatile unsigned short *)
+#define __reg32			(volatile unsigned int *)
+#else
+#define PLD_BASE		(PLD_PLAT_BASE + NONCACHE_OFFSET)
+#define __reg8
+#define __reg16
+#define __reg32
+#endif	/* __ASSEMBLY__ */
+
+/* CFC */
+#define	PLD_CFRSTCR		__reg16(PLD_BASE + 0x0000)
+#define PLD_CFSTS		__reg16(PLD_BASE + 0x0002)
+#define PLD_CFIMASK		__reg16(PLD_BASE + 0x0004)
+#define PLD_CFBUFCR		__reg16(PLD_BASE + 0x0006)
+#define PLD_CFVENCR		__reg16(PLD_BASE + 0x0008)
+#define PLD_CFCR0		__reg16(PLD_BASE + 0x000a)
+#define PLD_CFCR1		__reg16(PLD_BASE + 0x000c)
+#define PLD_IDERSTCR		__reg16(PLD_BASE + 0x0010)
+
+/* MMC */
+#define PLD_MMCCR		__reg16(PLD_BASE + 0x4000)
+#define PLD_MMCMOD		__reg16(PLD_BASE + 0x4002)
+#define PLD_MMCSTS		__reg16(PLD_BASE + 0x4006)
+#define PLD_MMCBAUR		__reg16(PLD_BASE + 0x400a)
+#define PLD_MMCCMDBCUT		__reg16(PLD_BASE + 0x400c)
+#define PLD_MMCCDTBCUT		__reg16(PLD_BASE + 0x400e)
+#define PLD_MMCDET		__reg16(PLD_BASE + 0x4010)
+#define PLD_MMCWP		__reg16(PLD_BASE + 0x4012)
+#define PLD_MMCWDATA		__reg16(PLD_BASE + 0x5000)
+#define PLD_MMCRDATA		__reg16(PLD_BASE + 0x6000)
+#define PLD_MMCCMDDATA		__reg16(PLD_BASE + 0x7000)
+#define PLD_MMCRSPDATA		__reg16(PLD_BASE + 0x7006)
+
+/* ICU
+ *  ICUISTS:	status register
+ *  ICUIREQ0: 	request register
+ *  ICUIREQ1: 	request register
+ *  ICUCR3:	control register for CFIREQ# interrupt
+ *  ICUCR4:	control register for CFC Card insert interrupt
+ *  ICUCR5:	control register for CFC Card eject interrupt
+ *  ICUCR6:	control register for external interrupt
+ *  ICUCR11:	control register for MMC Card insert/eject interrupt
+ *  ICUCR13:	control register for SC error interrupt
+ *  ICUCR14:	control register for SC receive interrupt
+ *  ICUCR15:	control register for SC send interrupt
+ *  ICUCR16:	control register for SIO0 receive interrupt
+ *  ICUCR17:	control register for SIO0 send interrupt
+ */
+#if !defined(CONFIG_PLAT_USRV)
+#define PLD_IRQ_INT0		(OPSPUT_PLD_IRQ_BASE + 0)	/* None */
+#define PLD_IRQ_INT1		(OPSPUT_PLD_IRQ_BASE + 1)	/* reserved */
+#define PLD_IRQ_INT2		(OPSPUT_PLD_IRQ_BASE + 2)	/* reserved */
+#define PLD_IRQ_CFIREQ		(OPSPUT_PLD_IRQ_BASE + 3)	/* CF IREQ */
+#define PLD_IRQ_CFC_INSERT	(OPSPUT_PLD_IRQ_BASE + 4)	/* CF Insert */
+#define PLD_IRQ_CFC_EJECT	(OPSPUT_PLD_IRQ_BASE + 5)	/* CF Eject */
+#define PLD_IRQ_EXINT		(OPSPUT_PLD_IRQ_BASE + 6)	/* EXINT */
+#define PLD_IRQ_INT7		(OPSPUT_PLD_IRQ_BASE + 7)	/* reserved */
+#define PLD_IRQ_INT8		(OPSPUT_PLD_IRQ_BASE + 8)	/* reserved */
+#define PLD_IRQ_INT9		(OPSPUT_PLD_IRQ_BASE + 9)	/* reserved */
+#define PLD_IRQ_INT10		(OPSPUT_PLD_IRQ_BASE + 10)	/* reserved */
+#define PLD_IRQ_MMCCARD		(OPSPUT_PLD_IRQ_BASE + 11)	/* MMC Insert/Eject */
+#define PLD_IRQ_INT12		(OPSPUT_PLD_IRQ_BASE + 12)	/* reserved */
+#define PLD_IRQ_SC_ERROR	(OPSPUT_PLD_IRQ_BASE + 13)	/* SC error */
+#define PLD_IRQ_SC_RCV		(OPSPUT_PLD_IRQ_BASE + 14)	/* SC receive */
+#define PLD_IRQ_SC_SND		(OPSPUT_PLD_IRQ_BASE + 15)	/* SC send */
+#define PLD_IRQ_SIO0_RCV	(OPSPUT_PLD_IRQ_BASE + 16)	/* SIO receive */
+#define PLD_IRQ_SIO0_SND	(OPSPUT_PLD_IRQ_BASE + 17)	/* SIO send */
+#define PLD_IRQ_INT18		(OPSPUT_PLD_IRQ_BASE + 18)	/* reserved */
+#define PLD_IRQ_INT19		(OPSPUT_PLD_IRQ_BASE + 19)	/* reserved */
+#define PLD_IRQ_INT20		(OPSPUT_PLD_IRQ_BASE + 20)	/* reserved */
+#define PLD_IRQ_INT21		(OPSPUT_PLD_IRQ_BASE + 21)	/* reserved */
+#define PLD_IRQ_INT22		(OPSPUT_PLD_IRQ_BASE + 22)	/* reserved */
+#define PLD_IRQ_INT23		(OPSPUT_PLD_IRQ_BASE + 23)	/* reserved */
+#define PLD_IRQ_INT24		(OPSPUT_PLD_IRQ_BASE + 24)	/* reserved */
+#define PLD_IRQ_INT25		(OPSPUT_PLD_IRQ_BASE + 25)	/* reserved */
+#define PLD_IRQ_INT26		(OPSPUT_PLD_IRQ_BASE + 26)	/* reserved */
+#define PLD_IRQ_INT27		(OPSPUT_PLD_IRQ_BASE + 27)	/* reserved */
+#define PLD_IRQ_INT28		(OPSPUT_PLD_IRQ_BASE + 28)	/* reserved */
+#define PLD_IRQ_INT29		(OPSPUT_PLD_IRQ_BASE + 29)	/* reserved */
+#define PLD_IRQ_INT30		(OPSPUT_PLD_IRQ_BASE + 30)	/* reserved */
+#define PLD_IRQ_INT31		(OPSPUT_PLD_IRQ_BASE + 31)	/* reserved */
+
+#else	/* CONFIG_PLAT_USRV */
+
+#define PLD_IRQ_INT0		(OPSPUT_PLD_IRQ_BASE + 0)	/* None */
+#define PLD_IRQ_INT1		(OPSPUT_PLD_IRQ_BASE + 1)	/* reserved */
+#define PLD_IRQ_INT2		(OPSPUT_PLD_IRQ_BASE + 2)	/* reserved */
+#define PLD_IRQ_CF0		(OPSPUT_PLD_IRQ_BASE + 3)	/* CF0# */
+#define PLD_IRQ_CF1		(OPSPUT_PLD_IRQ_BASE + 4)	/* CF1# */
+#define PLD_IRQ_CF2		(OPSPUT_PLD_IRQ_BASE + 5)	/* CF2# */
+#define PLD_IRQ_CF3		(OPSPUT_PLD_IRQ_BASE + 6)	/* CF3# */
+#define PLD_IRQ_CF4		(OPSPUT_PLD_IRQ_BASE + 7)	/* CF4# */
+#define PLD_IRQ_INT8		(OPSPUT_PLD_IRQ_BASE + 8)	/* reserved */
+#define PLD_IRQ_INT9		(OPSPUT_PLD_IRQ_BASE + 9)	/* reserved */
+#define PLD_IRQ_INT10		(OPSPUT_PLD_IRQ_BASE + 10)	/* reserved */
+#define PLD_IRQ_INT11		(OPSPUT_PLD_IRQ_BASE + 11)	/* reserved */
+#define PLD_IRQ_UART0		(OPSPUT_PLD_IRQ_BASE + 12)	/* UARTIRQ0 */
+#define PLD_IRQ_UART1		(OPSPUT_PLD_IRQ_BASE + 13)	/* UARTIRQ1 */
+#define PLD_IRQ_INT14		(OPSPUT_PLD_IRQ_BASE + 14)	/* reserved */
+#define PLD_IRQ_INT15		(OPSPUT_PLD_IRQ_BASE + 15)	/* reserved */
+#define PLD_IRQ_SNDINT		(OPSPUT_PLD_IRQ_BASE + 16)	/* SNDINT# */
+#define PLD_IRQ_INT17		(OPSPUT_PLD_IRQ_BASE + 17)	/* reserved */
+#define PLD_IRQ_INT18		(OPSPUT_PLD_IRQ_BASE + 18)	/* reserved */
+#define PLD_IRQ_INT19		(OPSPUT_PLD_IRQ_BASE + 19)	/* reserved */
+#define PLD_IRQ_INT20		(OPSPUT_PLD_IRQ_BASE + 20)	/* reserved */
+#define PLD_IRQ_INT21		(OPSPUT_PLD_IRQ_BASE + 21)	/* reserved */
+#define PLD_IRQ_INT22		(OPSPUT_PLD_IRQ_BASE + 22)	/* reserved */
+#define PLD_IRQ_INT23		(OPSPUT_PLD_IRQ_BASE + 23)	/* reserved */
+#define PLD_IRQ_INT24		(OPSPUT_PLD_IRQ_BASE + 24)	/* reserved */
+#define PLD_IRQ_INT25		(OPSPUT_PLD_IRQ_BASE + 25)	/* reserved */
+#define PLD_IRQ_INT26		(OPSPUT_PLD_IRQ_BASE + 26)	/* reserved */
+#define PLD_IRQ_INT27		(OPSPUT_PLD_IRQ_BASE + 27)	/* reserved */
+#define PLD_IRQ_INT28		(OPSPUT_PLD_IRQ_BASE + 28)	/* reserved */
+#define PLD_IRQ_INT29		(OPSPUT_PLD_IRQ_BASE + 29)	/* reserved */
+#define PLD_IRQ_INT30		(OPSPUT_PLD_IRQ_BASE + 30)	/* reserved */
+
+#endif	/* CONFIG_PLAT_USRV */
+
+#define PLD_ICUISTS		__reg16(PLD_BASE + 0x8002)
+#define PLD_ICUISTS_VECB_MASK	(0xf000)
+#define PLD_ICUISTS_VECB(x)	((x) & PLD_ICUISTS_VECB_MASK)
+#define PLD_ICUISTS_ISN_MASK	(0x07c0)
+#define PLD_ICUISTS_ISN(x)	((x) & PLD_ICUISTS_ISN_MASK)
+#define PLD_ICUIREQ0		__reg16(PLD_BASE + 0x8004)
+#define PLD_ICUIREQ1		__reg16(PLD_BASE + 0x8006)
+#define PLD_ICUCR1		__reg16(PLD_BASE + 0x8100)
+#define PLD_ICUCR2		__reg16(PLD_BASE + 0x8102)
+#define PLD_ICUCR3		__reg16(PLD_BASE + 0x8104)
+#define PLD_ICUCR4		__reg16(PLD_BASE + 0x8106)
+#define PLD_ICUCR5		__reg16(PLD_BASE + 0x8108)
+#define PLD_ICUCR6		__reg16(PLD_BASE + 0x810a)
+#define PLD_ICUCR7		__reg16(PLD_BASE + 0x810c)
+#define PLD_ICUCR8		__reg16(PLD_BASE + 0x810e)
+#define PLD_ICUCR9		__reg16(PLD_BASE + 0x8110)
+#define PLD_ICUCR10		__reg16(PLD_BASE + 0x8112)
+#define PLD_ICUCR11		__reg16(PLD_BASE + 0x8114)
+#define PLD_ICUCR12		__reg16(PLD_BASE + 0x8116)
+#define PLD_ICUCR13		__reg16(PLD_BASE + 0x8118)
+#define PLD_ICUCR14		__reg16(PLD_BASE + 0x811a)
+#define PLD_ICUCR15		__reg16(PLD_BASE + 0x811c)
+#define PLD_ICUCR16		__reg16(PLD_BASE + 0x811e)
+#define PLD_ICUCR17		__reg16(PLD_BASE + 0x8120)
+#define PLD_ICUCR_IEN		(0x1000)
+#define PLD_ICUCR_IREQ		(0x0100)
+#define PLD_ICUCR_ISMOD00	(0x0000)	/* Low edge */
+#define PLD_ICUCR_ISMOD01	(0x0010)	/* Low level */
+#define PLD_ICUCR_ISMOD02	(0x0020)	/* High edge */
+#define PLD_ICUCR_ISMOD03	(0x0030)	/* High level */
+#define PLD_ICUCR_ILEVEL0	(0x0000)
+#define PLD_ICUCR_ILEVEL1	(0x0001)
+#define PLD_ICUCR_ILEVEL2	(0x0002)
+#define PLD_ICUCR_ILEVEL3	(0x0003)
+#define PLD_ICUCR_ILEVEL4	(0x0004)
+#define PLD_ICUCR_ILEVEL5	(0x0005)
+#define PLD_ICUCR_ILEVEL6	(0x0006)
+#define PLD_ICUCR_ILEVEL7	(0x0007)
+
+/* Power Control of MMC and CF */
+#define PLD_CPCR		__reg16(PLD_BASE + 0x14000)
+#define PLD_CPCR_CF		0x0001
+#define PLD_CPCR_MMC		0x0002
+
+/* LED Control
+ *
+ * 1: DIP swich side
+ * 2: Reset switch side
+ */
+#define PLD_IOLEDCR		__reg16(PLD_BASE + 0x14002)
+#define PLD_IOLED_1_ON		0x001
+#define PLD_IOLED_1_OFF		0x000
+#define PLD_IOLED_2_ON		0x002
+#define PLD_IOLED_2_OFF		0x000
+
+/* DIP Switch
+ *  0: Write-protect of Flash Memory (0:protected, 1:non-protected)
+ *  1: -
+ *  2: -
+ *  3: -
+ */
+#define PLD_IOSWSTS		__reg16(PLD_BASE + 0x14004)
+#define	PLD_IOSWSTS_IOSW2	0x0200
+#define	PLD_IOSWSTS_IOSW1	0x0100
+#define	PLD_IOSWSTS_IOWP0	0x0001
+
+/* CRC */
+#define PLD_CRC7DATA		__reg16(PLD_BASE + 0x18000)
+#define PLD_CRC7INDATA		__reg16(PLD_BASE + 0x18002)
+#define PLD_CRC16DATA		__reg16(PLD_BASE + 0x18004)
+#define PLD_CRC16INDATA		__reg16(PLD_BASE + 0x18006)
+#define PLD_CRC16ADATA		__reg16(PLD_BASE + 0x18008)
+#define PLD_CRC16AINDATA	__reg16(PLD_BASE + 0x1800a)
+
+/* RTC */
+#define PLD_RTCCR		__reg16(PLD_BASE + 0x1c000)
+#define PLD_RTCBAUR		__reg16(PLD_BASE + 0x1c002)
+#define PLD_RTCWRDATA		__reg16(PLD_BASE + 0x1c004)
+#define PLD_RTCRDDATA		__reg16(PLD_BASE + 0x1c006)
+#define PLD_RTCRSTODT		__reg16(PLD_BASE + 0x1c008)
+
+/* SIO0 */
+#define PLD_ESIO0CR		__reg16(PLD_BASE + 0x20000)
+#define	PLD_ESIO0CR_TXEN	0x0001
+#define	PLD_ESIO0CR_RXEN	0x0002
+#define PLD_ESIO0MOD0		__reg16(PLD_BASE + 0x20002)
+#define	PLD_ESIO0MOD0_CTSS	0x0040
+#define	PLD_ESIO0MOD0_RTSS	0x0080
+#define PLD_ESIO0MOD1		__reg16(PLD_BASE + 0x20004)
+#define	PLD_ESIO0MOD1_LMFS	0x0010
+#define PLD_ESIO0STS		__reg16(PLD_BASE + 0x20006)
+#define	PLD_ESIO0STS_TEMP	0x0001
+#define	PLD_ESIO0STS_TXCP	0x0002
+#define	PLD_ESIO0STS_RXCP	0x0004
+#define	PLD_ESIO0STS_TXSC	0x0100
+#define	PLD_ESIO0STS_RXSC	0x0200
+#define PLD_ESIO0STS_TXREADY	(PLD_ESIO0STS_TXCP | PLD_ESIO0STS_TEMP)
+#define PLD_ESIO0INTCR		__reg16(PLD_BASE + 0x20008)
+#define	PLD_ESIO0INTCR_TXIEN	0x0002
+#define	PLD_ESIO0INTCR_RXCEN	0x0004
+#define PLD_ESIO0BAUR		__reg16(PLD_BASE + 0x2000a)
+#define PLD_ESIO0TXB		__reg16(PLD_BASE + 0x2000c)
+#define PLD_ESIO0RXB		__reg16(PLD_BASE + 0x2000e)
+
+/* SIM Card */
+#define PLD_SCCR		__reg16(PLD_BASE + 0x38000)
+#define PLD_SCMOD		__reg16(PLD_BASE + 0x38004)
+#define PLD_SCSTS		__reg16(PLD_BASE + 0x38006)
+#define PLD_SCINTCR		__reg16(PLD_BASE + 0x38008)
+#define PLD_SCBAUR		__reg16(PLD_BASE + 0x3800a)
+#define PLD_SCTXB		__reg16(PLD_BASE + 0x3800c)
+#define PLD_SCRXB		__reg16(PLD_BASE + 0x3800e)
+
+#endif	/* _OPSPUT_OPSPUT_PLD.H */
diff -Nru a/include/asm-m32r/page.h b/include/asm-m32r/page.h
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/include/asm-m32r/page.h	2004-10-18 14:57:22 -07:00
@@ -0,0 +1,112 @@
+#ifndef _ASM_M32R_PAGE_H
+#define _ASM_M32R_PAGE_H
+
+#include <linux/config.h>
+
+/* PAGE_SHIFT determines the page size */
+#define PAGE_SHIFT	12
+#define PAGE_SIZE	(1UL << PAGE_SHIFT)
+#define PAGE_MASK	(~(PAGE_SIZE-1))
+
+#ifdef __KERNEL__
+#ifndef __ASSEMBLY__
+
+extern void clear_page(void *to);
+extern void copy_page(void *to, void *from);
+
+#define clear_user_page(page, vaddr, pg)	clear_page(page)
+#define copy_user_page(to, from, vaddr, pg)	copy_page(to, from)
+
+/*
+ * These are used to make use of C type-checking..
+ */
+typedef struct { unsigned long pte; } pte_t;
+typedef struct { unsigned long pmd; } pmd_t;
+typedef struct { unsigned long pgd; } pgd_t;
+#define pte_val(x)	((x).pte)
+#define PTE_MASK	PAGE_MASK
+
+typedef struct { unsigned long pgprot; } pgprot_t;
+
+#define pmd_val(x)	((x).pmd)
+#define pgd_val(x)	((x).pgd)
+#define pgprot_val(x)	((x).pgprot)
+
+#define __pte(x) ((pte_t) { (x) } )
+#define __pmd(x) ((pmd_t) { (x) } )
+#define __pgd(x) ((pgd_t) { (x) } )
+#define __pgprot(x)	((pgprot_t) { (x) } )
+
+#endif /* !__ASSEMBLY__ */
+
+/* to align the pointer to the (next) page boundary */
+#define PAGE_ALIGN(addr)	(((addr) + PAGE_SIZE - 1) & PAGE_MASK)
+
+/*
+ * This handles the memory map.. We could make this a config
+ * option, but too many people screw it up, and too few need
+ * it.
+ *
+ * A __PAGE_OFFSET of 0xC0000000 means that the kernel has
+ * a virtual address space of one gigabyte, which limits the
+ * amount of physical memory you can use to about 950MB.
+ *
+ * If you want more physical memory than this then see the CONFIG_HIGHMEM4G
+ * and CONFIG_HIGHMEM64G options in the kernel configuration.
+ */
+
+
+/* This handles the memory map.. */
+
+#ifndef __ASSEMBLY__
+
+/* Pure 2^n version of get_order */
+static __inline__ int get_order(unsigned long size)
+{
+	int order;
+
+	size = (size - 1) >> (PAGE_SHIFT - 1);
+	order = -1;
+	do {
+		size >>= 1;
+		order++;
+	} while (size);
+
+	return order;
+}
+
+#endif /* __ASSEMBLY__ */
+
+#define __MEMORY_START  CONFIG_MEMORY_START
+#define __MEMORY_SIZE   CONFIG_MEMORY_SIZE
+
+#ifdef CONFIG_MMU
+#define __PAGE_OFFSET  (0x80000000)
+#else
+#define __PAGE_OFFSET  (0x00000000)
+#endif
+
+#define PAGE_OFFSET		((unsigned long)__PAGE_OFFSET)
+#define __pa(x)			((unsigned long)(x) - PAGE_OFFSET)
+#define __va(x)			((void *)((unsigned long)(x) + PAGE_OFFSET))
+
+#ifndef CONFIG_DISCONTIGMEM
+#define PFN_BASE		(CONFIG_MEMORY_START >> PAGE_SHIFT)
+#define pfn_to_page(pfn)	(mem_map + ((pfn) - PFN_BASE))
+#define page_to_pfn(page)	\
+	((unsigned long)((page) - mem_map) + PFN_BASE)
+#define pfn_valid(pfn)		(((pfn) - PFN_BASE) < max_mapnr)
+#endif  /* !CONFIG_DISCONTIGMEM */
+
+#define virt_to_page(kaddr)	pfn_to_page(__pa(kaddr) >> PAGE_SHIFT)
+#define virt_addr_valid(kaddr)	pfn_valid(__pa(kaddr) >> PAGE_SHIFT)
+
+#define VM_DATA_DEFAULT_FLAGS	(VM_READ | VM_WRITE | VM_EXEC | \
+				 VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC )
+
+#define devmem_is_allowed(x) 1
+
+#endif /* __KERNEL__ */
+
+#endif /* _ASM_M32R_PAGE_H */
+
diff -Nru a/include/asm-m32r/param.h b/include/asm-m32r/param.h
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/include/asm-m32r/param.h	2004-10-18 14:57:21 -07:00
@@ -0,0 +1,27 @@
+#ifndef _ASM_M32R_PARAM_H
+#define _ASM_M32R_PARAM_H
+
+/* $Id$ */
+
+/* orig : i386 2.5.67 */
+
+#ifdef __KERNEL__
+# define HZ		100		/* Internal kernel timer frequency */
+# define USER_HZ	100		/* .. some user interfaces are in "ticks" */
+# define CLOCKS_PER_SEC	(USER_HZ)	/* like times() */
+#endif
+
+#ifndef HZ
+#define HZ 100
+#endif
+
+#define EXEC_PAGESIZE	4096
+
+#ifndef NOGROUP
+#define NOGROUP		(-1)
+#endif
+
+#define MAXHOSTNAMELEN	64	/* max length of hostname */
+
+#endif /* _ASM_M32R_PARAM_H */
+
diff -Nru a/include/asm-m32r/pci.h b/include/asm-m32r/pci.h
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/include/asm-m32r/pci.h	2004-10-18 14:57:21 -07:00
@@ -0,0 +1,10 @@
+#ifndef _ASM_M32R_PCI_H
+#define _ASM_M32R_PCI_H
+
+/* $Id$ */
+
+#include <asm-generic/pci.h>
+
+#define PCI_DMA_BUS_IS_PHYS	(1)
+
+#endif /* _ASM_M32R_PCI_H */
diff -Nru a/include/asm-m32r/percpu.h b/include/asm-m32r/percpu.h
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/include/asm-m32r/percpu.h	2004-10-18 14:57:23 -07:00
@@ -0,0 +1,6 @@
+#ifndef __ARCH_M32R_PERCPU__
+#define __ARCH_M32R_PERCPU__
+
+#include <asm-generic/percpu.h>
+
+#endif /* __ARCH_M32R_PERCPU__ */
diff -Nru a/include/asm-m32r/pgalloc.h b/include/asm-m32r/pgalloc.h
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/include/asm-m32r/pgalloc.h	2004-10-18 14:57:24 -07:00
@@ -0,0 +1,87 @@
+#ifndef _ASM_M32R_PGALLOC_H
+#define _ASM_M32R_PGALLOC_H
+
+/* $Id$ */
+
+#include <linux/config.h>
+#include <linux/mm.h>
+
+#include <asm/io.h>
+#include <asm/pgtable.h>
+
+#define pmd_populate_kernel(mm, pmd, pte)	\
+	set_pmd(pmd, __pmd(_PAGE_TABLE + __pa(pte)))
+
+static __inline__ void pmd_populate(struct mm_struct *mm, pmd_t *pmd,
+	struct page *pte)
+{
+	set_pmd(pmd, __pmd(_PAGE_TABLE + page_to_phys(pte)));
+}
+
+/*
+ * Allocate and free page tables.
+ */
+static __inline__ pgd_t *pgd_alloc(struct mm_struct *mm)
+{
+	pgd_t *pgd = (pgd_t *)__get_free_page(GFP_KERNEL);
+
+	if (pgd)
+		clear_page(pgd);
+
+	return pgd;
+}
+
+static __inline__ void pgd_free(pgd_t *pgd)
+{
+	free_page((unsigned long)pgd);
+}
+
+static __inline__ pte_t *pte_alloc_one_kernel(struct mm_struct *mm,
+	unsigned long address)
+{
+	pte_t *pte = (pte_t *)__get_free_page(GFP_KERNEL);
+
+	if (pte)
+		clear_page(pte);
+
+	return pte;
+}
+
+static __inline__ struct page *pte_alloc_one(struct mm_struct *mm,
+	unsigned long address)
+{
+	struct page *pte = alloc_page(GFP_KERNEL);
+
+	if (pte)
+		clear_page(page_address(pte));
+
+	return pte;
+}
+
+static __inline__ void pte_free_kernel(pte_t *pte)
+{
+	free_page((unsigned long)pte);
+}
+
+static __inline__ void pte_free(struct page *pte)
+{
+	__free_page(pte);
+}
+
+#define __pte_free_tlb(tlb, pte)	pte_free((pte))
+
+/*
+ * allocating and freeing a pmd is trivial: the 1-entry pmd is
+ * inside the pgd, so has no extra memory associated with it.
+ * (In the PAE case we free the pmds as part of the pgd.)
+ */
+
+#define pmd_alloc_one(mm, addr)		({ BUG(); ((pmd_t *)2); })
+#define pmd_free(x)			do { } while (0)
+#define __pmd_free_tlb(tlb, x)		do { } while (0)
+#define pgd_populate(mm, pmd, pte)	BUG()
+
+#define check_pgt_cache()	do { } while (0)
+
+#endif /* _ASM_M32R_PGALLOC_H */
+
diff -Nru a/include/asm-m32r/pgtable-2level.h b/include/asm-m32r/pgtable-2level.h
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/include/asm-m32r/pgtable-2level.h	2004-10-18 14:57:22 -07:00
@@ -0,0 +1,77 @@
+#ifndef _ASM_M32R_PGTABLE_2LEVEL_H
+#define _ASM_M32R_PGTABLE_2LEVEL_H
+
+/* $Id$ */
+
+#include <linux/config.h>
+
+/*
+ * traditional M32R two-level paging structure:
+ */
+
+#define PGDIR_SHIFT	22
+#define PTRS_PER_PGD	1024
+
+/*
+ * the M32R is two-level, so we don't really have any
+ * PMD directory physically.
+ */
+#define PMD_SHIFT	22
+#define PTRS_PER_PMD	1
+
+#define PTRS_PER_PTE	1024
+
+#define pte_ERROR(e) \
+	printk("%s:%d: bad pte %08lx.\n", __FILE__, __LINE__, pte_val(e))
+#define pmd_ERROR(e) \
+	printk("%s:%d: bad pmd %08lx.\n", __FILE__, __LINE__, pmd_val(e))
+#define pgd_ERROR(e) \
+	printk("%s:%d: bad pgd %08lx.\n", __FILE__, __LINE__, pgd_val(e))
+
+/*
+ * The "pgd_xxx()" functions here are trivial for a folded two-level
+ * setup: the pgd is never bad, and a pmd always exists (as it's folded
+ * into the pgd entry)
+ */
+static __inline__ int pgd_none(pgd_t pgd)	{ return 0; }
+static __inline__ int pgd_bad(pgd_t pgd)	{ return 0; }
+static __inline__ int pgd_present(pgd_t pgd)	{ return 1; }
+#define pgd_clear(xp)				do { } while (0)
+
+/*
+ * Certain architectures need to do special things when PTEs
+ * within a page table are directly modified.  Thus, the following
+ * hook is made available.
+ */
+#define set_pte(pteptr, pteval) (*(pteptr) = pteval)
+#define set_pte_atomic(pteptr, pteval)	set_pte(pteptr, pteval)
+/*
+ * (pmds are folded into pgds so this doesnt get actually called,
+ * but the define is needed for a generic inline function.)
+ */
+#define set_pmd(pmdptr, pmdval) (*(pmdptr) = pmdval)
+#define set_pgd(pgdptr, pgdval) (*(pgdptr) = pgdval)
+
+#define pgd_page(pgd) \
+((unsigned long) __va(pgd_val(pgd) & PAGE_MASK))
+
+static __inline__ pmd_t *pmd_offset(pgd_t * dir, unsigned long address)
+{
+	return (pmd_t *) dir;
+}
+
+#define ptep_get_and_clear(xp)	__pte(xchg(&(xp)->pte, 0))
+#define pte_same(a, b)		(pte_val(a) == pte_val(b))
+#define pte_page(x)		pfn_to_page(pte_pfn(x))
+#define pte_none(x)		(!pte_val(x))
+#define pte_pfn(x)		(pte_val(x) >> PAGE_SHIFT)
+#define pfn_pte(pfn, prot)	__pte(((pfn) << PAGE_SHIFT) | pgprot_val(prot))
+#define pfn_pmd(pfn, prot)	__pmd(((pfn) << PAGE_SHIFT) | pgprot_val(prot))
+
+/* M32R_FIXME : PTE_FILE_MAX_BITS, pte_to_pgoff, pgoff_to_pte */
+#define PTE_FILE_MAX_BITS	31
+#define pte_to_pgoff(pte)	(pte_val(pte) >> 1)
+#define pgoff_to_pte(off)	((pte_t) { ((off) << 1) | _PAGE_FILE })
+
+#endif /* _ASM_M32R_PGTABLE_2LEVEL_H */
+
diff -Nru a/include/asm-m32r/pgtable.h b/include/asm-m32r/pgtable.h
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/include/asm-m32r/pgtable.h	2004-10-18 14:57:21 -07:00
@@ -0,0 +1,422 @@
+#ifndef _ASM_M32R_PGTABLE_H
+#define _ASM_M32R_PGTABLE_H
+
+/* $Id$ */
+
+/*
+ * The Linux memory management assumes a three-level page table setup. On
+ * the M32R, we use that, but "fold" the mid level into the top-level page
+ * table, so that we physically have the same two-level page table as the
+ * M32R mmu expects.
+ *
+ * This file contains the functions and defines necessary to modify and use
+ * the M32R page table tree.
+ */
+
+/* CAUTION!: If you change macro definitions in this file, you might have to
+ * change arch/m32r/mmu.S manually.
+ */
+
+#ifndef __ASSEMBLY__
+
+#include <linux/config.h>
+#include <linux/threads.h>
+#include <asm/processor.h>
+#include <asm/addrspace.h>
+#include <asm/bitops.h>
+#include <asm/page.h>
+
+extern pgd_t swapper_pg_dir[1024];
+extern void paging_init(void);
+
+/*
+ * ZERO_PAGE is a global shared page that is always zero: used
+ * for zero-mapped memory areas etc..
+ */
+extern unsigned long empty_zero_page[1024];
+#define ZERO_PAGE(vaddr)	(virt_to_page(empty_zero_page))
+
+#endif /* !__ASSEMBLY__ */
+
+/*
+ * The Linux x86 paging architecture is 'compile-time dual-mode', it
+ * implements both the traditional 2-level x86 page tables and the
+ * newer 3-level PAE-mode page tables.
+ */
+#ifndef __ASSEMBLY__
+#include <asm/pgtable-2level.h>
+#endif
+
+#define pgtable_cache_init()	do { } while (0)
+
+#define PMD_SIZE	(1UL << PMD_SHIFT)
+#define PMD_MASK	(~(PMD_SIZE - 1))
+#define PGDIR_SIZE	(1UL << PGDIR_SHIFT)
+#define PGDIR_MASK	(~(PGDIR_SIZE - 1))
+
+#define USER_PTRS_PER_PGD	(TASK_SIZE / PGDIR_SIZE)
+#define FIRST_USER_PGD_NR	0
+
+#ifndef __ASSEMBLY__
+/* Just any arbitrary offset to the start of the vmalloc VM area: the
+ * current 8MB value just means that there will be a 8MB "hole" after the
+ * physical memory until the kernel virtual memory starts.  That means that
+ * any out-of-bounds memory accesses will hopefully be caught.
+ * The vmalloc() routines leaves a hole of 4kB between each vmalloced
+ * area for the same reason. ;)
+ */
+#define VMALLOC_START		KSEG2
+#define VMALLOC_END		KSEG3
+
+/*
+ * The 4MB page is guessing..  Detailed in the infamous "Chapter H"
+ * of the Pentium details, but assuming intel did the straightforward
+ * thing, this bit set in the page directory entry just means that
+ * the page directory entry points directly to a 4MB-aligned block of
+ * memory.
+ */
+
+/*
+ *     M32R TLB format
+ *
+ *     [0]    [1:19]           [20:23]       [24:31]
+ *     +-----------------------+----+-------------+
+ *     |          VPN          |0000|    ASID     |
+ *     +-----------------------+----+-------------+
+ *     +-+---------------------+----+-+---+-+-+-+-+
+ *     |0         PPN          |0000|N|AC |L|G|V| |
+ *     +-+---------------------+----+-+---+-+-+-+-+
+ *                                     RWX
+ */
+
+#define _PAGE_BIT_DIRTY		0	/* software */
+#define _PAGE_BIT_FILE		0	/* when !present: nonlinear file
+					   mapping */
+#define _PAGE_BIT_PRESENT	1	/* Valid */
+#define _PAGE_BIT_GLOBAL	2	/* Global */
+#define _PAGE_BIT_LARGE		3	/* Large */
+#define _PAGE_BIT_EXEC		4	/* Execute */
+#define _PAGE_BIT_WRITE		5	/* Write */
+#define _PAGE_BIT_READ		6	/* Read */
+#define _PAGE_BIT_NONCACHABLE	7	/* Non cachable */
+#define _PAGE_BIT_USER		8	/* software */
+#define _PAGE_BIT_ACCESSED	9	/* software */
+
+#define _PAGE_DIRTY	\
+	(1UL << _PAGE_BIT_DIRTY)	/* software : page changed */
+#define _PAGE_FILE	\
+	(1UL << _PAGE_BIT_FILE)		/* when !present: nonlinear file
+					   mapping */
+#define _PAGE_PRESENT	\
+	(1UL << _PAGE_BIT_PRESENT)	/* Valid : Page is Valid */
+#define _PAGE_GLOBAL	\
+	(1UL << _PAGE_BIT_GLOBAL)	/* Global */
+#define _PAGE_LARGE	\
+	(1UL << _PAGE_BIT_LARGE)	/* Large */
+#define _PAGE_EXEC	\
+	(1UL << _PAGE_BIT_EXEC)		/* Execute */
+#define _PAGE_WRITE	\
+	(1UL << _PAGE_BIT_WRITE)	/* Write */
+#define _PAGE_READ	\
+	(1UL << _PAGE_BIT_READ)		/* Read */
+#define _PAGE_NONCACHABLE	\
+	(1UL<<_PAGE_BIT_NONCACHABLE)	/* Non cachable */
+#define _PAGE_USER	\
+	(1UL << _PAGE_BIT_USER)		/* software : user space access
+					   allowed */
+#define _PAGE_ACCESSED	\
+	(1UL << _PAGE_BIT_ACCESSED)	/* software : page referenced */
+
+#define _PAGE_TABLE	\
+	( _PAGE_PRESENT | _PAGE_WRITE | _PAGE_READ | _PAGE_USER \
+	| _PAGE_ACCESSED | _PAGE_DIRTY )
+#define _KERNPG_TABLE	\
+	( _PAGE_PRESENT | _PAGE_WRITE | _PAGE_READ | _PAGE_ACCESSED \
+	| _PAGE_DIRTY )
+#define _PAGE_CHG_MASK	\
+	( PTE_MASK | _PAGE_ACCESSED | _PAGE_DIRTY )
+
+#ifdef CONFIG_MMU
+#define PAGE_NONE	\
+	__pgprot(_PAGE_PRESENT | _PAGE_ACCESSED)
+#define PAGE_SHARED	\
+	__pgprot(_PAGE_PRESENT | _PAGE_WRITE | _PAGE_READ | _PAGE_USER \
+		| _PAGE_ACCESSED)
+#define PAGE_SHARED_X	\
+	__pgprot(_PAGE_PRESENT | _PAGE_EXEC | _PAGE_WRITE | _PAGE_READ \
+		| _PAGE_USER | _PAGE_ACCESSED)
+#define PAGE_COPY	\
+	__pgprot(_PAGE_PRESENT | _PAGE_EXEC | _PAGE_READ | _PAGE_USER \
+		| _PAGE_ACCESSED)
+#define PAGE_COPY_X	\
+	__pgprot(_PAGE_PRESENT | _PAGE_EXEC | _PAGE_READ | _PAGE_USER \
+		| _PAGE_ACCESSED)
+#define PAGE_READONLY	\
+	__pgprot(_PAGE_PRESENT | _PAGE_READ | _PAGE_USER | _PAGE_ACCESSED)
+#define PAGE_READONLY_X	\
+	__pgprot(_PAGE_PRESENT | _PAGE_EXEC | _PAGE_READ | _PAGE_USER \
+		| _PAGE_ACCESSED)
+
+#define __PAGE_KERNEL	\
+	( _PAGE_PRESENT | _PAGE_EXEC | _PAGE_WRITE | _PAGE_READ | _PAGE_DIRTY \
+	| _PAGE_ACCESSED )
+#define __PAGE_KERNEL_RO	( __PAGE_KERNEL & ~_PAGE_WRITE )
+#define __PAGE_KERNEL_NOCACHE	( __PAGE_KERNEL | _PAGE_NONCACHABLE)
+
+#define MAKE_GLOBAL(x)	__pgprot((x) | _PAGE_GLOBAL)
+
+#define PAGE_KERNEL		MAKE_GLOBAL(__PAGE_KERNEL)
+#define PAGE_KERNEL_RO		MAKE_GLOBAL(__PAGE_KERNEL_RO)
+#define PAGE_KERNEL_NOCACHE	MAKE_GLOBAL(__PAGE_KERNEL_NOCACHE)
+
+#else
+#define PAGE_NONE               __pgprot(0)
+#define PAGE_SHARED             __pgprot(0)
+#define PAGE_SHARED_X           __pgprot(0)
+#define PAGE_COPY               __pgprot(0)
+#define PAGE_COPY_X             __pgprot(0)
+#define PAGE_READONLY           __pgprot(0)
+#define PAGE_READONLY_X         __pgprot(0)
+
+#define PAGE_KERNEL             __pgprot(0)
+#define PAGE_KERNEL_RO          __pgprot(0)
+#define PAGE_KERNEL_NOCACHE     __pgprot(0)
+#endif /* CONFIG_MMU */
+
+/*
+ * The i386 can't do page protection for execute, and considers that
+ * the same are read. Also, write permissions imply read permissions.
+ * This is the closest we can get..
+ */
+	/* rwx */
+#define __P000	PAGE_NONE
+#define __P001	PAGE_READONLY_X
+#define __P010	PAGE_COPY_X
+#define __P011	PAGE_COPY_X
+#define __P100	PAGE_READONLY
+#define __P101	PAGE_READONLY_X
+#define __P110	PAGE_COPY_X
+#define __P111	PAGE_COPY_X
+
+#define __S000	PAGE_NONE
+#define __S001	PAGE_READONLY_X
+#define __S010	PAGE_SHARED
+#define __S011	PAGE_SHARED_X
+#define __S100	PAGE_READONLY
+#define __S101	PAGE_READONLY_X
+#define __S110	PAGE_SHARED
+#define __S111	PAGE_SHARED_X
+
+/* page table for 0-4MB for everybody */
+
+#define pte_present(x)	(pte_val(x) & _PAGE_PRESENT)
+#define pte_clear(xp)	do { set_pte(xp, __pte(0)); } while (0)
+
+#define pmd_none(x)	(!pmd_val(x))
+#define pmd_present(x)	(pmd_val(x) & _PAGE_PRESENT)
+#define pmd_clear(xp)	do { set_pmd(xp, __pmd(0)); } while (0)
+#define	pmd_bad(x)	((pmd_val(x) & (~PAGE_MASK & ~_PAGE_USER)) \
+	!= _KERNPG_TABLE)
+
+#define pages_to_mb(x)	((x) >> (20 - PAGE_SHIFT))
+
+/*
+ * The following only work if pte_present() is true.
+ * Undefined behaviour if not..
+ */
+static __inline__ int pte_user(pte_t pte)
+{
+	return pte_val(pte) & _PAGE_USER;
+}
+
+static __inline__ int pte_read(pte_t pte)
+{
+	return pte_val(pte) & _PAGE_READ;
+}
+
+static __inline__ int pte_exec(pte_t pte)
+{
+	return pte_val(pte) & _PAGE_EXEC;
+}
+
+static __inline__ int pte_dirty(pte_t pte)
+{
+	return pte_val(pte) & _PAGE_DIRTY;
+}
+
+static __inline__ int pte_young(pte_t pte)
+{
+	return pte_val(pte) & _PAGE_ACCESSED;
+}
+
+static __inline__ int pte_write(pte_t pte)
+{
+	return pte_val(pte) & _PAGE_WRITE;
+}
+
+/*
+ * The following only works if pte_present() is not true.
+ */
+static __inline__ int pte_file(pte_t pte)
+{
+	return pte_val(pte) & _PAGE_FILE;
+}
+
+static __inline__ pte_t pte_rdprotect(pte_t pte)
+{
+	pte_val(pte) &= ~_PAGE_READ;
+	return pte;
+}
+
+static __inline__ pte_t pte_exprotect(pte_t pte)
+{
+	pte_val(pte) &= ~_PAGE_EXEC;
+	return pte;
+}
+
+static __inline__ pte_t pte_mkclean(pte_t pte)
+{
+	pte_val(pte) &= ~_PAGE_DIRTY;
+	return pte;
+}
+
+static __inline__ pte_t pte_mkold(pte_t pte)
+{
+	pte_val(pte) &= ~_PAGE_ACCESSED;return pte;}
+
+static __inline__ pte_t pte_wrprotect(pte_t pte)
+{
+	pte_val(pte) &= ~_PAGE_WRITE;
+	return pte;
+}
+
+static __inline__ pte_t pte_mkread(pte_t pte)
+{
+	pte_val(pte) |= _PAGE_READ;
+	return pte;
+}
+
+static __inline__ pte_t pte_mkexec(pte_t pte)
+{
+	pte_val(pte) |= _PAGE_EXEC;
+	return pte;
+}
+
+static __inline__ pte_t pte_mkdirty(pte_t pte)
+{
+	pte_val(pte) |= _PAGE_DIRTY;
+	return pte;
+}
+
+static __inline__ pte_t pte_mkyoung(pte_t pte)
+{
+	pte_val(pte) |= _PAGE_ACCESSED;
+	return pte;
+}
+
+static __inline__ pte_t pte_mkwrite(pte_t pte)
+{
+	pte_val(pte) |= _PAGE_WRITE;
+	return pte;
+}
+
+static __inline__  int ptep_test_and_clear_dirty(pte_t *ptep)
+{
+	return test_and_clear_bit(_PAGE_BIT_DIRTY, ptep);
+}
+
+static __inline__  int ptep_test_and_clear_young(pte_t *ptep)
+{
+	return test_and_clear_bit(_PAGE_BIT_ACCESSED, ptep);
+}
+
+static __inline__ void ptep_set_wrprotect(pte_t *ptep)
+{
+	clear_bit(_PAGE_BIT_WRITE, ptep);
+}
+
+static __inline__ void ptep_mkdirty(pte_t *ptep)
+{
+	set_bit(_PAGE_BIT_DIRTY, ptep);
+}
+
+/*
+ * Conversion functions: convert a page and protection to a page entry,
+ * and a page entry and page directory to the page they refer to.
+ */
+#define mk_pte(page, pgprot)	pfn_pte(page_to_pfn(page), pgprot)
+
+static __inline__ pte_t pte_modify(pte_t pte, pgprot_t newprot)
+{
+	set_pte(&pte, __pte((pte_val(pte) & _PAGE_CHG_MASK) \
+		| pgprot_val(newprot)));
+
+	return pte;
+}
+
+#define page_pte(page)	page_pte_prot(page, __pgprot(0))
+
+/*
+ * Conversion functions: convert a page and protection to a page entry,
+ * and a page entry and page directory to the page they refer to.
+ */
+
+static __inline__ void pmd_set(pmd_t * pmdp, pte_t * ptep)
+{
+	pmd_val(*pmdp) = (((unsigned long) ptep) & PAGE_MASK);
+}
+
+#define pmd_page_kernel(pmd)	\
+	((unsigned long) __va(pmd_val(pmd) & PAGE_MASK))
+
+#ifndef CONFIG_DISCONTIGMEM
+#define pmd_page(pmd)	(mem_map + ((pmd_val(pmd) >> PAGE_SHIFT) - PFN_BASE))
+#endif /* !CONFIG_DISCONTIGMEM */
+
+/* to find an entry in a page-table-directory. */
+#define pgd_index(address)	\
+	(((address) >> PGDIR_SHIFT) & (PTRS_PER_PGD - 1))
+
+#define pgd_offset(mm, address)	((mm)->pgd + pgd_index(address))
+
+/* to find an entry in a kernel page-table-directory */
+#define pgd_offset_k(address)	pgd_offset(&init_mm, address)
+
+#define pmd_index(address)	\
+	(((address) >> PMD_SHIFT) & (PTRS_PER_PMD - 1))
+
+#define pte_index(address)	\
+	(((address) >> PAGE_SHIFT) & (PTRS_PER_PTE - 1))
+#define pte_offset_kernel(dir, address)	\
+	((pte_t *)pmd_page_kernel(*(dir)) + pte_index(address))
+#define pte_offset_map(dir, address)	\
+	((pte_t *)page_address(pmd_page(*(dir))) + pte_index(address))
+#define pte_offset_map_nested(dir, address)	pte_offset_map(dir, address)
+#define pte_unmap(pte)		do { } while (0)
+#define pte_unmap_nested(pte)	do { } while (0)
+
+/* Encode and de-code a swap entry */
+#define __swp_type(x)			(((x).val >> 1) & 0x3f)
+#define __swp_offset(x)			((x).val >> 8)
+#define __swp_entry(type, offset)	\
+	((swp_entry_t) { ((type) << 1) | ((offset) << 8) })
+#define __pte_to_swp_entry(pte)		((swp_entry_t) { pte_val(pte) })
+#define __swp_entry_to_pte(x)		((pte_t) { (x).val })
+
+#endif /* !__ASSEMBLY__ */
+
+/* Needs to be defined here and not in linux/mm.h, as it is arch dependent */
+#define kern_addr_valid(addr)	(1)
+
+#define io_remap_page_range	remap_page_range
+
+#define __HAVE_ARCH_PTEP_TEST_AND_CLEAR_YOUNG
+#define __HAVE_ARCH_PTEP_TEST_AND_CLEAR_DIRTY
+#define __HAVE_ARCH_PTEP_GET_AND_CLEAR
+#define __HAVE_ARCH_PTEP_SET_WRPROTECT
+#define __HAVE_ARCH_PTEP_MKDIRTY
+#define __HAVE_ARCH_PTE_SAME
+#include <asm-generic/pgtable.h>
+
+#endif /* _ASM_M32R_PGTABLE_H */
+
diff -Nru a/include/asm-m32r/poll.h b/include/asm-m32r/poll.h
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/include/asm-m32r/poll.h	2004-10-18 14:57:23 -07:00
@@ -0,0 +1,31 @@
+#ifndef _ASM_M32R_POLL_H
+#define _ASM_M32R_POLL_H
+
+/*
+ * poll(2) bit definitions.  Based on <asm-i386/poll.h>.
+ *
+ * Modified 2004
+ *      Hirokazu Takata <takata at linux-m32r.org>
+ */
+
+#define POLLIN		0x0001
+#define POLLPRI		0x0002
+#define POLLOUT		0x0004
+#define POLLERR		0x0008
+#define POLLHUP		0x0010
+#define POLLNVAL	0x0020
+
+#define POLLRDNORM	0x0040
+#define POLLRDBAND	0x0080
+#define POLLWRNORM	0x0100
+#define POLLWRBAND	0x0200
+#define POLLMSG		0x0400
+#define POLLREMOVE	0x1000
+
+struct pollfd {
+	int fd;
+	short events;
+	short revents;
+};
+
+#endif  /* _ASM_M32R_POLL_H */
diff -Nru a/include/asm-m32r/posix_types.h b/include/asm-m32r/posix_types.h
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/include/asm-m32r/posix_types.h	2004-10-18 14:57:24 -07:00
@@ -0,0 +1,126 @@
+#ifndef _ASM_M32R_POSIX_TYPES_H
+#define _ASM_M32R_POSIX_TYPES_H
+
+/* $Id$ */
+
+/* orig : i386, sh 2.4.18 */
+
+/*
+ * This file is generally used by user-level software, so you need to
+ * be a little careful about namespace pollution etc.  Also, we cannot
+ * assume GCC is being used.
+ */
+
+typedef unsigned long	__kernel_ino_t;
+typedef unsigned short	__kernel_mode_t;
+typedef unsigned short	__kernel_nlink_t;
+typedef long		__kernel_off_t;
+typedef int		__kernel_pid_t;
+typedef unsigned short	__kernel_ipc_pid_t;
+typedef unsigned short	__kernel_uid_t;
+typedef unsigned short	__kernel_gid_t;
+typedef unsigned int	__kernel_size_t;
+typedef int		__kernel_ssize_t;
+typedef int		__kernel_ptrdiff_t;
+typedef long		__kernel_time_t;
+typedef long		__kernel_suseconds_t;
+typedef long		__kernel_clock_t;
+typedef int		__kernel_timer_t;
+typedef int		__kernel_clockid_t;
+typedef int		__kernel_daddr_t;
+typedef char *		__kernel_caddr_t;
+typedef unsigned short	__kernel_uid16_t;
+typedef unsigned short	__kernel_gid16_t;
+typedef unsigned int	__kernel_uid32_t;
+typedef unsigned int	__kernel_gid32_t;
+
+typedef unsigned short	__kernel_old_uid_t;
+typedef unsigned short	__kernel_old_gid_t;
+typedef unsigned short	__kernel_old_dev_t;
+
+#ifdef __GNUC__
+typedef long long	__kernel_loff_t;
+#endif
+
+typedef struct {
+#if defined(__KERNEL__) || defined(__USE_ALL)
+	int	val[2];
+#else /* !defined(__KERNEL__) && !defined(__USE_ALL) */
+	int	__val[2];
+#endif /* !defined(__KERNEL__) && !defined(__USE_ALL) */
+} __kernel_fsid_t;
+
+#if defined(__KERNEL__) || !defined(__GLIBC__) || (__GLIBC__ < 2)
+
+#undef	__FD_SET
+static __inline__ void __FD_SET(unsigned long __fd, __kernel_fd_set *__fdsetp)
+{
+	unsigned long __tmp = __fd / __NFDBITS;
+	unsigned long __rem = __fd % __NFDBITS;
+	__fdsetp->fds_bits[__tmp] |= (1UL<<__rem);
+}
+
+#undef	__FD_CLR
+static __inline__ void __FD_CLR(unsigned long __fd, __kernel_fd_set *__fdsetp)
+{
+	unsigned long __tmp = __fd / __NFDBITS;
+	unsigned long __rem = __fd % __NFDBITS;
+	__fdsetp->fds_bits[__tmp] &= ~(1UL<<__rem);
+}
+
+
+#undef	__FD_ISSET
+static __inline__ int __FD_ISSET(unsigned long __fd, const __kernel_fd_set *__p)
+{
+	unsigned long __tmp = __fd / __NFDBITS;
+	unsigned long __rem = __fd % __NFDBITS;
+	return (__p->fds_bits[__tmp] & (1UL<<__rem)) != 0;
+}
+
+/*
+ * This will unroll the loop for the normal constant case (8 ints,
+ * for a 256-bit fd_set)
+ */
+#undef	__FD_ZERO
+static __inline__ void __FD_ZERO(__kernel_fd_set *__p)
+{
+	unsigned long *__tmp = __p->fds_bits;
+	int __i;
+
+	if (__builtin_constant_p(__FDSET_LONGS)) {
+		switch (__FDSET_LONGS) {
+		case 16:
+			__tmp[ 0] = 0; __tmp[ 1] = 0;
+			__tmp[ 2] = 0; __tmp[ 3] = 0;
+			__tmp[ 4] = 0; __tmp[ 5] = 0;
+			__tmp[ 6] = 0; __tmp[ 7] = 0;
+			__tmp[ 8] = 0; __tmp[ 9] = 0;
+			__tmp[10] = 0; __tmp[11] = 0;
+			__tmp[12] = 0; __tmp[13] = 0;
+			__tmp[14] = 0; __tmp[15] = 0;
+			return;
+
+		case 8:
+			__tmp[ 0] = 0; __tmp[ 1] = 0;
+			__tmp[ 2] = 0; __tmp[ 3] = 0;
+			__tmp[ 4] = 0; __tmp[ 5] = 0;
+			__tmp[ 6] = 0; __tmp[ 7] = 0;
+			return;
+
+		case 4:
+			__tmp[ 0] = 0; __tmp[ 1] = 0;
+			__tmp[ 2] = 0; __tmp[ 3] = 0;
+			return;
+		}
+	}
+	__i = __FDSET_LONGS;
+	while (__i) {
+		__i--;
+		*__tmp = 0;
+		__tmp++;
+	}
+}
+
+#endif /* defined(__KERNEL__) || !defined(__GLIBC__) || (__GLIBC__ < 2) */
+
+#endif  /* _ASM_M32R_POSIX_TYPES_H */
diff -Nru a/include/asm-m32r/processor.h b/include/asm-m32r/processor.h
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/include/asm-m32r/processor.h	2004-10-18 14:57:21 -07:00
@@ -0,0 +1,157 @@
+#ifndef _ASM_M32R_PROCESSOR_H
+#define _ASM_M32R_PROCESSOR_H
+
+/* $Id$ */
+
+/*
+ * 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  by Hiroyuki Kondo, Hirokazu Takata, and Hitoshi Yamamoto
+ */
+
+/*
+ * include/asm-m32r/processor.h
+ *
+ * Copyright (C) 1994 Linus Torvalds
+ */
+#include <linux/kernel.h>
+#include <linux/config.h>
+#include <asm/cache.h>
+#include <asm/ptrace.h>  /* pt_regs */
+
+#include <asm/cachectl.h>
+
+/*
+ * Default implementation of macro that returns current
+ * instruction pointer ("program counter").
+ */
+#define current_text_addr() ({ __label__ _l; _l: &&_l; })
+
+/*
+ *  CPU type and hardware bug flags. Kept separately for each CPU.
+ *  Members of this structure are referenced in head.S, so think twice
+ *  before touching them. [mj]
+ */
+
+struct cpuinfo_m32r {
+	unsigned long pgtable_cache_sz;
+	unsigned long cpu_clock;
+	unsigned long bus_clock;
+	unsigned long timer_divide;
+	unsigned long loops_per_jiffy;
+};
+
+/*
+ * capabilities of CPUs
+ */
+
+extern struct cpuinfo_m32r boot_cpu_data;
+
+#ifdef CONFIG_SMP
+extern struct cpuinfo_m32r cpu_data[];
+#define current_cpu_data cpu_data[smp_processor_id()]
+#else
+#define cpu_data &boot_cpu_data
+#define current_cpu_data boot_cpu_data
+#endif
+
+/*
+ * User space process size: 2GB (default).
+ */
+#ifdef CONFIG_MMU
+#define TASK_SIZE  (0x80000000UL)
+#else
+#define TASK_SIZE  (0x00400000UL)
+#endif
+
+/* This decides where the kernel will search for a free chunk of vm
+ * space during mmap's.
+ */
+#define TASK_UNMAPPED_BASE	PAGE_ALIGN(TASK_SIZE / 3)
+
+typedef struct {
+	unsigned long seg;
+} mm_segment_t;
+
+struct debug_trap {
+	int nr_trap;
+	unsigned long	addr;
+	unsigned long	insn;
+};
+
+struct thread_struct {
+	unsigned long address;
+	unsigned long trap_no;		/* Trap number  */
+	unsigned long error_code;	/* Error code of trap */
+	unsigned long lr;		/* saved pc */
+	unsigned long sp;		/* user stack pointer */
+	struct debug_trap debug_trap;
+};
+
+#define INIT_SP	(sizeof(init_stack) + (unsigned long) &init_stack)
+
+#define INIT_THREAD	{	\
+	.sp = INIT_SP,		\
+}
+
+/*
+ * Do necessary setup to start up a newly executed thread.
+ */
+
+/* User process Backup PSW */
+#define USERPS_BPSW (M32R_PSW_BSM|M32R_PSW_BIE|M32R_PSW_BPM)
+
+#define start_thread(regs, new_pc, new_spu) 				\
+	do {								\
+		set_fs(USER_DS); 					\
+		regs->psw = (regs->psw | USERPS_BPSW) & 0x0000FFFFUL;	\
+		regs->bpc = new_pc;					\
+		regs->spu = new_spu;					\
+	} while (0)
+
+/* Forward declaration, a strange C thing */
+struct task_struct;
+struct mm_struct;
+
+/* Free all resources held by a thread. */
+extern void release_thread(struct task_struct *);
+
+#define prepare_to_copy(tsk)	do { } while (0)
+
+/*
+ * create a kernel thread without removing it from tasklists
+ */
+extern int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags);
+
+/* Copy and release all segment info associated with a VM */
+extern void copy_segments(struct task_struct *p, struct mm_struct * mm);
+extern void release_segments(struct mm_struct * mm);
+
+extern unsigned long thread_saved_pc(struct task_struct *);
+
+/* Copy and release all segment info associated with a VM */
+#define copy_segments(p, mm)  do { } while (0)
+#define release_segments(mm)  do { } while (0)
+
+unsigned long get_wchan(struct task_struct *p);
+#define KSTK_EIP(tsk)  ((tsk)->thread.lr)
+#define KSTK_ESP(tsk)  ((tsk)->thread.sp)
+
+#define THREAD_SIZE (2*PAGE_SIZE)
+
+/* REP NOP (PAUSE) is a good thing to insert into busy-wait loops. */
+static __inline__ void rep_nop(void)
+{
+	__asm__ __volatile__(
+		"nop \n\t"
+		"nop \n\t"
+		:
+		:
+		: "memory");
+}
+
+#define cpu_relax()     rep_nop()
+
+#endif /* _ASM_M32R_PROCESSOR_H */
diff -Nru a/include/asm-m32r/ptrace.h b/include/asm-m32r/ptrace.h
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/include/asm-m32r/ptrace.h	2004-10-18 14:57:21 -07:00
@@ -0,0 +1,165 @@
+#ifndef _ASM_M32R_PTRACE_H
+#define _ASM_M32R_PTRACE_H
+
+/*
+ * linux/include/asm-m32r/ptrace.h
+ *
+ * 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.
+ *
+ * M32R version:
+ *   Copyright (C) 2001-2002, 2004  Hirokazu Takata <takata at linux-m32r.org>
+ */
+
+#include <linux/config.h>
+#include <asm/m32r.h>		/* M32R_PSW_BSM, M32R_PSW_BPM */
+
+/* 0 - 13 are integer registers (general purpose registers).  */
+#define PT_R4		0
+#define PT_R5		1
+#define PT_R6		2
+#define PT_REGS 	3
+#define PT_R0		4
+#define PT_R1		5
+#define PT_R2		6
+#define PT_R3		7
+#define PT_R7		8
+#define PT_R8		9
+#define PT_R9		10
+#define PT_R10		11
+#define PT_R11		12
+#define PT_R12		13
+#define PT_SYSCNR	14
+#define PT_R13		PT_FP
+#define PT_R14		PT_LR
+#define PT_R15		PT_SP
+
+/* processor status and miscellaneous context registers.  */
+#if defined(CONFIG_ISA_M32R2) && defined(CONFIG_ISA_DSP_LEVEL2)
+#define PT_ACC0H	15
+#define PT_ACC0L	16
+#define PT_ACC1H	17
+#define PT_ACC1L	18
+#define PT_ACCH		PT_ACC0H
+#define PT_ACCL		PT_ACC0L
+#define PT_PSW		19
+#define PT_BPC		20
+#define PT_BBPSW	21
+#define PT_BBPC		22
+#define PT_SPU		23
+#define PT_FP		24
+#define PT_LR		25
+#define PT_SPI		26
+#define PT_ORIGR0	27
+#elif defined(CONFIG_ISA_M32R2) || defined(CONFIG_ISA_M32R)
+#define PT_ACCH		15
+#define PT_ACCL		16
+#define PT_PSW		17
+#define PT_BPC		18
+#define PT_BBPSW	19
+#define PT_BBPC		20
+#define PT_SPU		21
+#define PT_FP		22
+#define PT_LR		23
+#define PT_SPI		24
+#define PT_ORIGR0	25
+#else
+#error unknown isa conifiguration
+#endif
+
+/* virtual pt_reg entry for gdb */
+#define PT_PC		30
+#define PT_CBR		31
+#define PT_EVB		32
+
+
+/* Control registers.  */
+#define SPR_CR0 PT_PSW
+#define SPR_CR1 PT_CBR		/* read only */
+#define SPR_CR2 PT_SPI
+#define SPR_CR3 PT_SPU
+#define SPR_CR4
+#define SPR_CR5 PT_EVB		/* part of M32R/E, M32R/I core only */
+#define SPR_CR6 PT_BPC
+#define SPR_CR7
+#define SPR_CR8 PT_BBPSW
+#define SPR_CR9
+#define SPR_CR10
+#define SPR_CR11
+#define SPR_CR12
+#define SPR_CR13 PT_WR
+#define SPR_CR14 PT_BBPC
+#define SPR_CR15
+
+/* this struct defines the way the registers are stored on the
+   stack during a system call. */
+struct pt_regs {
+	/* Saved main processor registers. */
+	unsigned long r4;
+	unsigned long r5;
+	unsigned long r6;
+	struct pt_regs *pt_regs;
+	unsigned long r0;
+	unsigned long r1;
+	unsigned long r2;
+	unsigned long r3;
+	unsigned long r7;
+	unsigned long r8;
+	unsigned long r9;
+	unsigned long r10;
+	unsigned long r11;
+	unsigned long r12;
+	long syscall_nr;
+
+	/* Saved main processor status and miscellaneous context registers. */
+#if defined(CONFIG_ISA_M32R2) && defined(CONFIG_ISA_DSP_LEVEL2)
+	unsigned long acc0h;
+	unsigned long acc0l;
+	unsigned long acc1h;
+	unsigned long acc1l;
+#elif defined(CONFIG_ISA_M32R2) || defined(CONFIG_ISA_M32R)
+	unsigned long acch;
+	unsigned long accl;
+#else
+#error unknown isa configuration
+#endif
+	unsigned long psw;
+	unsigned long bpc;		/* saved PC for TRAP syscalls */
+	unsigned long bbpsw;
+	unsigned long bbpc;
+	unsigned long spu;		/* saved user stack */
+	unsigned long fp;
+	unsigned long lr;		/* saved PC for JL syscalls */
+	unsigned long spi;		/* saved kernel stack */
+	unsigned long orig_r0;
+};
+
+/* Arbitrarily choose the same ptrace numbers as used by the Sparc code. */
+#define PTRACE_GETREGS		12
+#define PTRACE_SETREGS		13
+
+#define PTRACE_OLDSETOPTIONS	21
+
+/* options set using PTRACE_SETOPTIONS */
+#define PTRACE_O_TRACESYSGOOD	0x00000001
+
+#ifdef __KERNEL__
+#if defined(CONFIG_ISA_M32R2) || defined(CONFIG_CHIP_VDEC2)
+#define user_mode(regs) ((M32R_PSW_BPM & (regs)->psw) != 0)
+#elif defined(CONFIG_ISA_M32R)
+#define user_mode(regs) ((M32R_PSW_BSM & (regs)->psw) != 0)
+#else
+#error unknown isa configuration
+#endif
+
+#define instruction_pointer(regs) ((regs)->bpc)
+#define profile_pc(regs) instruction_pointer(regs)
+
+extern void show_regs(struct pt_regs *);
+
+extern void withdraw_debug_trap(struct pt_regs *regs);
+
+#endif /* __KERNEL */
+
+#endif /* _ASM_M32R_PTRACE_H */
diff -Nru a/include/asm-m32r/resource.h b/include/asm-m32r/resource.h
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/include/asm-m32r/resource.h	2004-10-18 14:57:22 -07:00
@@ -0,0 +1,55 @@
+#ifndef _ASM_M32R_RESOURCE_H
+#define _ASM_M32R_RESOURCE_H
+
+/* $Id$ */
+
+/* orig : i386 2.4.18 */
+
+/*
+ * Resource limits
+ */
+
+#define RLIMIT_CPU	0		/* CPU time in ms */
+#define RLIMIT_FSIZE	1		/* Maximum filesize */
+#define RLIMIT_DATA	2		/* max data size */
+#define RLIMIT_STACK	3		/* max stack size */
+#define RLIMIT_CORE	4		/* max core file size */
+#define RLIMIT_RSS	5		/* max resident set size */
+#define RLIMIT_NPROC	6		/* max number of processes */
+#define RLIMIT_NOFILE	7		/* max number of open files */
+#define RLIMIT_MEMLOCK	8		/* max locked-in-memory address space */
+#define RLIMIT_AS	9		/* address space limit */
+#define RLIMIT_LOCKS	10		/* maximum file locks held */
+#define RLIMIT_SIGPENDING 11		/* max number of pending signals */
+#define RLIMIT_MSGQUEUE	12		/* maximum bytes in POSIX mqueues */
+
+#define RLIM_NLIMITS	13
+
+/*
+ * SuS says limits have to be unsigned.
+ * Which makes a ton more sense anyway.
+ */
+#define RLIM_INFINITY	(~0UL)
+
+#ifdef __KERNEL__
+
+#define INIT_RLIMITS					\
+{							\
+	{ RLIM_INFINITY, RLIM_INFINITY },		\
+	{ RLIM_INFINITY, RLIM_INFINITY },		\
+	{ RLIM_INFINITY, RLIM_INFINITY },		\
+	{      _STK_LIM, RLIM_INFINITY },		\
+	{             0, RLIM_INFINITY },		\
+	{ RLIM_INFINITY, RLIM_INFINITY },		\
+	{             0,             0 },		\
+	{      INR_OPEN,     INR_OPEN  },		\
+	{ MLOCK_LIMIT,   MLOCK_LIMIT   },		\
+	{ RLIM_INFINITY, RLIM_INFINITY },		\
+	{ RLIM_INFINITY, RLIM_INFINITY },		\
+	{ MAX_SIGPENDING, MAX_SIGPENDING },		\
+	{ MQ_BYTES_MAX, MQ_BYTES_MAX },			\
+}
+
+#endif /* __KERNEL__ */
+
+#endif  /* _ASM_M32R_RESOURCE_H */
diff -Nru a/include/asm-m32r/rtc.h b/include/asm-m32r/rtc.h
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/include/asm-m32r/rtc.h	2004-10-18 14:57:24 -07:00
@@ -0,0 +1,70 @@
+/* $Id: rtc.h,v 1.1.1.1 2004/03/25 04:29:22 hitoshiy Exp $ */
+
+#ifndef __RTC_H__
+#define __RTC_H__
+
+
+#include <linux/config.h>
+
+   /* Dallas DS1302 clock/calendar register numbers. */
+#  define RTC_SECONDS      0
+#  define RTC_MINUTES      1
+#  define RTC_HOURS        2
+#  define RTC_DAY_OF_MONTH 3
+#  define RTC_MONTH        4
+#  define RTC_WEEKDAY      5
+#  define RTC_YEAR         6
+#  define RTC_CONTROL      7
+
+   /* Bits in CONTROL register. */
+#  define RTC_CONTROL_WRITEPROTECT 	0x80
+#  define RTC_TRICKLECHARGER 		8
+
+  /* Bits in TRICKLECHARGER register TCS TCS TCS TCS DS DS RS RS. */
+#  define RTC_TCR_PATTERN 	0xA0	/* 1010xxxx */
+#  define RTC_TCR_1DIOD 	0x04	/* xxxx01xx */
+#  define RTC_TCR_2DIOD 	0x08	/* xxxx10xx */
+#  define RTC_TCR_DISABLED 	0x00	/* xxxxxx00 Disabled */
+#  define RTC_TCR_2KOHM 	0x01	/* xxxxxx01 2KOhm */
+#  define RTC_TCR_4KOHM 	0x02	/* xxxxxx10 4kOhm */
+#  define RTC_TCR_8KOHM 	0x03	/* xxxxxx11 8kOhm */
+
+#ifdef CONFIG_M32700UT_DS1302
+extern unsigned char ds1302_readreg(int reg);
+extern void ds1302_writereg(int reg, unsigned char val);
+extern int ds1302_init(void);
+#  define CMOS_READ(x) ds1302_readreg(x)
+#  define CMOS_WRITE(val,reg) ds1302_writereg(reg,val)
+#  define RTC_INIT() ds1302_init()
+#else
+  /* No RTC configured so we shouldn't try to access any. */
+#  define CMOS_READ(x) 42
+#  define CMOS_WRITE(x,y)
+#  define RTC_INIT() (-1)
+#endif
+
+/*
+ * The struct used to pass data via the following ioctl. Similar to the
+ * struct tm in <time.h>, but it needs to be here so that the kernel
+ * source is self contained, allowing cross-compiles, etc. etc.
+ */
+struct rtc_time {
+	int tm_sec;
+	int tm_min;
+	int tm_hour;
+	int tm_mday;
+	int tm_mon;
+	int tm_year;
+	int tm_wday;
+	int tm_yday;
+	int tm_isdst;
+};
+
+/* ioctl() calls that are permitted to the /dev/rtc interface. */
+#define RTC_MAGIC 'p'
+#define RTC_RD_TIME		_IOR(RTC_MAGIC, 0x09, struct rtc_time)	/* Read RTC time. */
+#define RTC_SET_TIME		_IOW(RTC_MAGIC, 0x0a, struct rtc_time)	/* Set RTC time. */
+#define RTC_SET_CHARGE  	_IOW(RTC_MAGIC, 0x0b, int)
+#define RTC_MAX_IOCTL 0x0b
+
+#endif /* __RTC_H__ */
diff -Nru a/include/asm-m32r/scatterlist.h b/include/asm-m32r/scatterlist.h
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/include/asm-m32r/scatterlist.h	2004-10-18 14:57:23 -07:00
@@ -0,0 +1,18 @@
+#ifndef _ASM_M32R_SCATTERLIST_H
+#define _ASM_M32R_SCATTERLIST_H
+
+/* $Id$ */
+
+struct scatterlist {
+    char *  address;    /* Location data is to be transferred to, NULL for
+                         * highmem page */
+    struct page * page; /* Location for highmem page, if any */
+    unsigned int offset;/* for highmem, page offset */
+
+    dma_addr_t dma_address;
+    unsigned int length;
+};
+
+#define ISA_DMA_THRESHOLD (0x1fffffff)
+
+#endif /* _ASM_M32R_SCATTERLIST_H */
diff -Nru a/include/asm-m32r/sections.h b/include/asm-m32r/sections.h
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/include/asm-m32r/sections.h	2004-10-18 14:57:21 -07:00
@@ -0,0 +1,8 @@
+#ifndef _M32R_SECTIONS_H
+#define _M32R_SECTIONS_H
+
+/* nothing to see, move along */
+#include <asm-generic/sections.h>
+
+#endif	/* _M32R_SECTIONS_H */
+
diff -Nru a/include/asm-m32r/segment.h b/include/asm-m32r/segment.h
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/include/asm-m32r/segment.h	2004-10-18 14:57:23 -07:00
@@ -0,0 +1,14 @@
+#ifndef _ASM_M32R_SEGMENT_H
+#define _ASM_M32R_SEGMENT_H
+
+/* $Id$ */
+
+/* orig : i386 (2.4.18) */
+
+#define __KERNEL_CS	0x10
+#define __KERNEL_DS	0x18
+
+#define __USER_CS	0x23
+#define __USER_DS	0x2B
+
+#endif  /* _ASM_M32R_SEGMENT_H */
diff -Nru a/include/asm-m32r/semaphore.h b/include/asm-m32r/semaphore.h
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/include/asm-m32r/semaphore.h	2004-10-18 14:57:22 -07:00
@@ -0,0 +1,214 @@
+#ifndef _ASM_M32R_SEMAPHORE_H
+#define _ASM_M32R_SEMAPHORE_H
+
+#include <linux/linkage.h>
+
+#ifdef __KERNEL__
+
+/*
+ * SMP- and interrupt-safe semaphores..
+ *
+ * Copyright (C) 1996  Linus Torvalds
+ * Copyright (C) 2004  Hirokazu Takata <takata at linux-m32r.org>
+ */
+
+#include <linux/config.h>
+#include <linux/wait.h>
+#include <linux/rwsem.h>
+#include <asm/system.h>
+#include <asm/atomic.h>
+
+#undef LOAD
+#undef STORE
+#ifdef CONFIG_SMP
+#define LOAD	"lock"
+#define STORE	"unlock"
+#else
+#define LOAD	"ld"
+#define STORE	"st"
+#endif
+
+struct semaphore {
+	atomic_t count;
+	int sleepers;
+	wait_queue_head_t wait;
+};
+
+#define __SEMAPHORE_INITIALIZER(name, n)				\
+{									\
+	.count		= ATOMIC_INIT(n),				\
+	.sleepers	= 0,						\
+	.wait		= __WAIT_QUEUE_HEAD_INITIALIZER((name).wait)	\
+}
+
+#define __MUTEX_INITIALIZER(name) \
+	__SEMAPHORE_INITIALIZER(name,1)
+
+#define __DECLARE_SEMAPHORE_GENERIC(name,count) \
+	struct semaphore name = __SEMAPHORE_INITIALIZER(name,count)
+
+#define DECLARE_MUTEX(name) __DECLARE_SEMAPHORE_GENERIC(name,1)
+#define DECLARE_MUTEX_LOCKED(name) __DECLARE_SEMAPHORE_GENERIC(name,0)
+
+static inline void sema_init (struct semaphore *sem, int val)
+{
+/*
+ *	*sem = (struct semaphore)__SEMAPHORE_INITIALIZER((*sem),val);
+ *
+ * i'd rather use the more flexible initialization above, but sadly
+ * GCC 2.7.2.3 emits a bogus warning. EGCS doesnt. Oh well.
+ */
+	atomic_set(&sem->count, val);
+	sem->sleepers = 0;
+	init_waitqueue_head(&sem->wait);
+}
+
+static inline void init_MUTEX (struct semaphore *sem)
+{
+	sema_init(sem, 1);
+}
+
+static inline void init_MUTEX_LOCKED (struct semaphore *sem)
+{
+	sema_init(sem, 0);
+}
+
+asmlinkage void __down_failed(void /* special register calling convention */);
+asmlinkage int  __down_failed_interruptible(void  /* params in registers */);
+asmlinkage int  __down_failed_trylock(void  /* params in registers */);
+asmlinkage void __up_wakeup(void /* special register calling convention */);
+
+asmlinkage void __down(struct semaphore * sem);
+asmlinkage int  __down_interruptible(struct semaphore * sem);
+asmlinkage int  __down_trylock(struct semaphore * sem);
+asmlinkage void __up(struct semaphore * sem);
+
+/*
+ * Atomically decrement the semaphore's count.  If it goes negative,
+ * block the calling thread in the TASK_UNINTERRUPTIBLE state.
+ */
+static inline void down(struct semaphore * sem)
+{
+	unsigned long flags;
+	long count;
+
+	might_sleep();
+	local_irq_save(flags);
+	__asm__ __volatile__ (
+		"# down				\n\t"
+		DCACHE_CLEAR("%0", "r4", "%1")
+		LOAD"	%0, @%1;		\n\t"
+		"addi	%0, #-1;		\n\t"
+		STORE"	%0, @%1;		\n\t"
+		: "=&r" (count)
+		: "r" (&sem->count)
+		: "memory"
+#ifdef CONFIG_CHIP_M32700_TS1
+		, "r4"
+#endif	/* CONFIG_CHIP_M32700_TS1 */
+	);
+	local_irq_restore(flags);
+
+	if (unlikely(count < 0))
+		__down(sem);
+}
+
+/*
+ * Interruptible try to acquire a semaphore.  If we obtained
+ * it, return zero.  If we were interrupted, returns -EINTR
+ */
+static inline int down_interruptible(struct semaphore * sem)
+{
+	unsigned long flags;
+	long count;
+	int result = 0;
+
+	might_sleep();
+	local_irq_save(flags);
+	__asm__ __volatile__ (
+		"# down_interruptible		\n\t"
+		DCACHE_CLEAR("%0", "r4", "%1")
+		LOAD"	%0, @%1;		\n\t"
+		"addi	%0, #-1;		\n\t"
+		STORE"	%0, @%1;		\n\t"
+		: "=&r" (count)
+		: "r" (&sem->count)
+		: "memory"
+#ifdef CONFIG_CHIP_M32700_TS1
+		, "r4"
+#endif	/* CONFIG_CHIP_M32700_TS1 */
+	);
+	local_irq_restore(flags);
+
+	if (unlikely(count < 0))
+		result = __down_interruptible(sem);
+
+	return result;
+}
+
+/*
+ * Non-blockingly attempt to down() a semaphore.
+ * Returns zero if we acquired it
+ */
+static inline int down_trylock(struct semaphore * sem)
+{
+	unsigned long flags;
+	long count;
+	int result = 0;
+
+	local_irq_save(flags);
+	__asm__ __volatile__ (
+		"# down_trylock			\n\t"
+		DCACHE_CLEAR("%0", "r4", "%1")
+		LOAD"	%0, @%1;		\n\t"
+		"addi	%0, #-1;		\n\t"
+		STORE"	%0, @%1;		\n\t"
+		: "=&r" (count)
+		: "r" (&sem->count)
+		: "memory"
+#ifdef CONFIG_CHIP_M32700_TS1
+		, "r4"
+#endif	/* CONFIG_CHIP_M32700_TS1 */
+	);
+	local_irq_restore(flags);
+
+	if (unlikely(count < 0))
+		result = __down_trylock(sem);
+
+	return result;
+}
+
+/*
+ * Note! This is subtle. We jump to wake people up only if
+ * the semaphore was negative (== somebody was waiting on it).
+ * The default case (no contention) will result in NO
+ * jumps for both down() and up().
+ */
+static inline void up(struct semaphore * sem)
+{
+	unsigned long flags;
+	long count;
+
+	local_irq_save(flags);
+	__asm__ __volatile__ (
+		"# up				\n\t"
+		DCACHE_CLEAR("%0", "r4", "%1")
+		LOAD"	%0, @%1;		\n\t"
+		"addi	%0, #1;			\n\t"
+		STORE"	%0, @%1;		\n\t"
+		: "=&r" (count)
+		: "r" (&sem->count)
+		: "memory"
+#ifdef CONFIG_CHIP_M32700_TS1
+		, "r4"
+#endif	/* CONFIG_CHIP_M32700_TS1 */
+	);
+	local_irq_restore(flags);
+
+	if (unlikely(count <= 0))
+		__up(sem);
+}
+
+#endif  /* __KERNEL__ */
+
+#endif  /* _ASM_M32R_SEMAPHORE_H */
diff -Nru a/include/asm-m32r/sembuf.h b/include/asm-m32r/sembuf.h
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/include/asm-m32r/sembuf.h	2004-10-18 14:57:22 -07:00
@@ -0,0 +1,29 @@
+#ifndef _ASM_M32R_SEMBUF_H
+#define _ASM_M32R_SEMBUF_H
+
+/* $Id$ */
+
+/* orig : i386 2.4.18 */
+
+/*
+ * The semid64_ds structure for m32r architecture.
+ * Note extra padding because this structure is passed back and forth
+ * between kernel and user space.
+ *
+ * Pad space is left for:
+ * - 64-bit time_t to solve y2038 problem
+ * - 2 miscellaneous 32-bit values
+ */
+
+struct semid64_ds {
+	struct ipc64_perm sem_perm;		/* permissions .. see ipc.h */
+	__kernel_time_t	sem_otime;		/* last semop time */
+	unsigned long	__unused1;
+	__kernel_time_t	sem_ctime;		/* last change time */
+	unsigned long	__unused2;
+	unsigned long	sem_nsems;		/* no. of semaphores in array */
+	unsigned long	__unused3;
+	unsigned long	__unused4;
+};
+
+#endif /* _ASM_M32R_SEMBUF_H */
diff -Nru a/include/asm-m32r/serial.h b/include/asm-m32r/serial.h
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/include/asm-m32r/serial.h	2004-10-18 14:57:24 -07:00
@@ -0,0 +1,151 @@
+#ifndef _ASM_M32R_SERIAL_H
+#define _ASM_M32R_SERIAL_H
+
+/* $Id$ */
+
+/* orig : i386 2.4.18 */
+
+/*
+ * include/asm-m32r/serial.h
+ */
+
+#include <linux/config.h>
+#include <asm/m32r.h>
+
+/*
+ * This assumes you have a 1.8432 MHz clock for your UART.
+ *
+ * It'd be nice if someone built a serial card with a 24.576 MHz
+ * clock, since the 16550A is capable of handling a top speed of 1.5
+ * megabits/second; but this requires the faster clock.
+ */
+#define BASE_BAUD ( 1843200 / 16 )
+
+/* Standard COM flags (except for COM4, because of the 8514 problem) */
+#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
+
+#ifdef CONFIG_SERIAL_MANY_PORTS
+#define FOURPORT_FLAGS ASYNC_FOURPORT
+#define ACCENT_FLAGS 0
+#define BOCA_FLAGS 0
+#define HUB6_FLAGS 0
+#define RS_TABLE_SIZE	64
+#else
+#define RS_TABLE_SIZE
+#endif
+
+#define MCA_COM_FLAGS	(STD_COM_FLAGS|ASYNC_BOOT_ONLYMCA)
+
+/*
+ * The following define the access methods for the HUB6 card. All
+ * access is through two ports for all 24 possible chips. The card is
+ * selected through the high 2 bits, the port on that card with the
+ * "middle" 3 bits, and the register on that port with the bottom
+ * 3 bits.
+ *
+ * While the access port and interrupt is configurable, the default
+ * port locations are 0x302 for the port control register, and 0x303
+ * for the data read/write register. Normally, the interrupt is at irq3
+ * but can be anything from 3 to 7 inclusive. Note that using 3 will
+ * require disabling com2.
+ */
+
+#define C_P(card,port) (((card)<<6|(port)<<3) + 1)
+
+#define STD_SERIAL_PORT_DEFNS			\
+	/* UART CLK   PORT IRQ     FLAGS        */			\
+	{ 0, BASE_BAUD, 0x3F8, 4, STD_COM_FLAGS },	/* ttyS0 */	\
+	{ 0, BASE_BAUD, 0x2F8, 3, STD_COM_FLAGS },	/* ttyS1 */	\
+	{ 0, BASE_BAUD, 0x3E8, 4, STD_COM_FLAGS },	/* ttyS2 */	\
+	{ 0, BASE_BAUD, 0x2E8, 3, STD_COM4_FLAGS },	/* ttyS3 */
+
+
+#ifdef CONFIG_SERIAL_MANY_PORTS
+#define EXTRA_SERIAL_PORT_DEFNS			\
+	{ 0, BASE_BAUD, 0x1A0, 9, FOURPORT_FLAGS }, 	/* ttyS4 */	\
+	{ 0, BASE_BAUD, 0x1A8, 9, FOURPORT_FLAGS },	/* ttyS5 */	\
+	{ 0, BASE_BAUD, 0x1B0, 9, FOURPORT_FLAGS },	/* ttyS6 */	\
+	{ 0, BASE_BAUD, 0x1B8, 9, FOURPORT_FLAGS },	/* ttyS7 */	\
+	{ 0, BASE_BAUD, 0x2A0, 5, FOURPORT_FLAGS },	/* ttyS8 */	\
+	{ 0, BASE_BAUD, 0x2A8, 5, FOURPORT_FLAGS },	/* ttyS9 */	\
+	{ 0, BASE_BAUD, 0x2B0, 5, FOURPORT_FLAGS },	/* ttyS10 */	\
+	{ 0, BASE_BAUD, 0x2B8, 5, FOURPORT_FLAGS },	/* ttyS11 */	\
+	{ 0, BASE_BAUD, 0x330, 4, ACCENT_FLAGS },	/* ttyS12 */	\
+	{ 0, BASE_BAUD, 0x338, 4, ACCENT_FLAGS },	/* ttyS13 */	\
+	{ 0, BASE_BAUD, 0x000, 0, 0 },	/* ttyS14 (spare) */		\
+	{ 0, BASE_BAUD, 0x000, 0, 0 },	/* ttyS15 (spare) */		\
+	{ 0, BASE_BAUD, 0x100, 12, BOCA_FLAGS },	/* ttyS16 */	\
+	{ 0, BASE_BAUD, 0x108, 12, BOCA_FLAGS },	/* ttyS17 */	\
+	{ 0, BASE_BAUD, 0x110, 12, BOCA_FLAGS },	/* ttyS18 */	\
+	{ 0, BASE_BAUD, 0x118, 12, BOCA_FLAGS },	/* ttyS19 */	\
+	{ 0, BASE_BAUD, 0x120, 12, BOCA_FLAGS },	/* ttyS20 */	\
+	{ 0, BASE_BAUD, 0x128, 12, BOCA_FLAGS },	/* ttyS21 */	\
+	{ 0, BASE_BAUD, 0x130, 12, BOCA_FLAGS },	/* ttyS22 */	\
+	{ 0, BASE_BAUD, 0x138, 12, BOCA_FLAGS },	/* ttyS23 */	\
+	{ 0, BASE_BAUD, 0x140, 12, BOCA_FLAGS },	/* ttyS24 */	\
+	{ 0, BASE_BAUD, 0x148, 12, BOCA_FLAGS },	/* ttyS25 */	\
+	{ 0, BASE_BAUD, 0x150, 12, BOCA_FLAGS },	/* ttyS26 */	\
+	{ 0, BASE_BAUD, 0x158, 12, BOCA_FLAGS },	/* ttyS27 */	\
+	{ 0, BASE_BAUD, 0x160, 12, BOCA_FLAGS },	/* ttyS28 */	\
+	{ 0, BASE_BAUD, 0x168, 12, BOCA_FLAGS },	/* ttyS29 */	\
+	{ 0, BASE_BAUD, 0x170, 12, BOCA_FLAGS },	/* ttyS30 */	\
+	{ 0, BASE_BAUD, 0x178, 12, BOCA_FLAGS },	/* ttyS31 */
+#else
+#define EXTRA_SERIAL_PORT_DEFNS
+#endif
+
+/* You can have up to four HUB6's in the system, but I've only
+ * included two cards here for a total of twelve ports.
+ */
+#if (defined(CONFIG_HUB6) && defined(CONFIG_SERIAL_MANY_PORTS))
+#define HUB6_SERIAL_PORT_DFNS		\
+	{ 0, BASE_BAUD, 0x302, 3, HUB6_FLAGS, C_P(0,0) },  /* ttyS32 */	\
+	{ 0, BASE_BAUD, 0x302, 3, HUB6_FLAGS, C_P(0,1) },  /* ttyS33 */	\
+	{ 0, BASE_BAUD, 0x302, 3, HUB6_FLAGS, C_P(0,2) },  /* ttyS34 */	\
+	{ 0, BASE_BAUD, 0x302, 3, HUB6_FLAGS, C_P(0,3) },  /* ttyS35 */	\
+	{ 0, BASE_BAUD, 0x302, 3, HUB6_FLAGS, C_P(0,4) },  /* ttyS36 */	\
+	{ 0, BASE_BAUD, 0x302, 3, HUB6_FLAGS, C_P(0,5) },  /* ttyS37 */	\
+	{ 0, BASE_BAUD, 0x302, 3, HUB6_FLAGS, C_P(1,0) },  /* ttyS38 */	\
+	{ 0, BASE_BAUD, 0x302, 3, HUB6_FLAGS, C_P(1,1) },  /* ttyS39 */	\
+	{ 0, BASE_BAUD, 0x302, 3, HUB6_FLAGS, C_P(1,2) },  /* ttyS40 */	\
+	{ 0, BASE_BAUD, 0x302, 3, HUB6_FLAGS, C_P(1,3) },  /* ttyS41 */	\
+	{ 0, BASE_BAUD, 0x302, 3, HUB6_FLAGS, C_P(1,4) },  /* ttyS42 */	\
+	{ 0, BASE_BAUD, 0x302, 3, HUB6_FLAGS, C_P(1,5) },  /* ttyS43 */
+#else
+#define HUB6_SERIAL_PORT_DFNS
+#endif
+
+#ifdef CONFIG_MCA
+#define MCA_SERIAL_PORT_DFNS			\
+	{ 0, BASE_BAUD, 0x3220, 3, MCA_COM_FLAGS },	\
+	{ 0, BASE_BAUD, 0x3228, 3, MCA_COM_FLAGS },	\
+	{ 0, BASE_BAUD, 0x4220, 3, MCA_COM_FLAGS },	\
+	{ 0, BASE_BAUD, 0x4228, 3, MCA_COM_FLAGS },	\
+	{ 0, BASE_BAUD, 0x5220, 3, MCA_COM_FLAGS },	\
+	{ 0, BASE_BAUD, 0x5228, 3, MCA_COM_FLAGS },
+#else
+#define MCA_SERIAL_PORT_DFNS
+#endif
+
+#ifndef CONFIG_PLAT_USRV
+#define SERIAL_PORT_DFNS		\
+	STD_SERIAL_PORT_DEFNS		\
+	EXTRA_SERIAL_PORT_DEFNS		\
+	HUB6_SERIAL_PORT_DFNS		\
+	MCA_SERIAL_PORT_DFNS
+
+#else	/* CONFIG_PLAT_USRV */
+
+#define SERIAL_PORT_DFNS		\
+	/* UART CLK   PORT IRQ     FLAGS        */			\
+	{ 0, BASE_BAUD, 0x3F8, PLD_IRQ_UART0, STD_COM_FLAGS },	/* ttyS0 */	\
+	{ 0, BASE_BAUD, 0x2F8, PLD_IRQ_UART1, STD_COM_FLAGS },	/* ttyS1 */
+#endif	/* CONFIG_PLAT_USRV */
+
+#endif  /* _ASM_M32R_SERIAL_H */
diff -Nru a/include/asm-m32r/setup.h b/include/asm-m32r/setup.h
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/include/asm-m32r/setup.h	2004-10-18 14:57:23 -07:00
@@ -0,0 +1,33 @@
+/*
+ * This is set up by the setup-routine at boot-time
+ */
+#define PARAM			((unsigned char *)empty_zero_page)
+
+#define MOUNT_ROOT_RDONLY	(*(unsigned long *) (PARAM+0x000))
+#define RAMDISK_FLAGS		(*(unsigned long *) (PARAM+0x004))
+#define ORIG_ROOT_DEV		(*(unsigned long *) (PARAM+0x008))
+#define LOADER_TYPE		(*(unsigned long *) (PARAM+0x00c))
+#define INITRD_START		(*(unsigned long *) (PARAM+0x010))
+#define INITRD_SIZE		(*(unsigned long *) (PARAM+0x014))
+
+#define M32R_CPUCLK		(*(unsigned long *) (PARAM+0x018))
+#define M32R_BUSCLK		(*(unsigned long *) (PARAM+0x01c))
+#define M32R_TIMER_DIVIDE	(*(unsigned long *) (PARAM+0x020))
+
+#define COMMAND_LINE		((char *) (PARAM+0x100))
+
+#define SCREEN_INFO		(*(struct screen_info *) (PARAM+0x200))
+
+#define COMMAND_LINE_SIZE	(512)
+
+#define RAMDISK_IMAGE_START_MASK	(0x07FF)
+#define RAMDISK_PROMPT_FLAG		(0x8000)
+#define RAMDISK_LOAD_FLAG		(0x4000)
+
+#define PFN_UP(x)	(((x) + PAGE_SIZE-1) >> PAGE_SHIFT)
+#define PFN_DOWN(x)	((x) >> PAGE_SHIFT)
+#define PFN_PHYS(x)	((x) << PAGE_SHIFT)
+
+extern unsigned long memory_start;
+extern unsigned long memory_end;
+
diff -Nru a/include/asm-m32r/shmbuf.h b/include/asm-m32r/shmbuf.h
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/include/asm-m32r/shmbuf.h	2004-10-18 14:57:23 -07:00
@@ -0,0 +1,46 @@
+#ifndef _ASM_M32R_SHMBUF_H
+#define _ASM_M32R_SHMBUF_H
+
+/* $Id$ */
+
+/* orig : i386 2.4.18 */
+
+/*
+ * The shmid64_ds structure for M32R architecture.
+ * Note extra padding because this structure is passed back and forth
+ * between kernel and user space.
+ *
+ * Pad space is left for:
+ * - 64-bit time_t to solve y2038 problem
+ * - 2 miscellaneous 32-bit values
+ */
+
+struct shmid64_ds {
+	struct ipc64_perm	shm_perm;	/* operation perms */
+	size_t			shm_segsz;	/* size of segment (bytes) */
+	__kernel_time_t		shm_atime;	/* last attach time */
+	unsigned long		__unused1;
+	__kernel_time_t		shm_dtime;	/* last detach time */
+	unsigned long		__unused2;
+	__kernel_time_t		shm_ctime;	/* last change time */
+	unsigned long		__unused3;
+	__kernel_pid_t		shm_cpid;	/* pid of creator */
+	__kernel_pid_t		shm_lpid;	/* pid of last operator */
+	unsigned long		shm_nattch;	/* no. of current attaches */
+	unsigned long		__unused4;
+	unsigned long		__unused5;
+};
+
+struct shminfo64 {
+	unsigned long	shmmax;
+	unsigned long	shmmin;
+	unsigned long	shmmni;
+	unsigned long	shmseg;
+	unsigned long	shmall;
+	unsigned long	__unused1;
+	unsigned long	__unused2;
+	unsigned long	__unused3;
+	unsigned long	__unused4;
+};
+
+#endif /* _ASM_M32R_SHMBUF_H */
diff -Nru a/include/asm-m32r/shmparam.h b/include/asm-m32r/shmparam.h
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/include/asm-m32r/shmparam.h	2004-10-18 14:57:24 -07:00
@@ -0,0 +1,8 @@
+#ifndef _ASM_M32R_SHMPARAM_H
+#define _ASM_M32R_SHMPARAM_H
+
+/* $Id$ */
+
+#define	SHMLBA PAGE_SIZE		 /* attach addr a multiple of this */
+
+#endif /* _ASM_M32R_SHMPARAM_H */
diff -Nru a/include/asm-m32r/sigcontext.h b/include/asm-m32r/sigcontext.h
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/include/asm-m32r/sigcontext.h	2004-10-18 14:57:21 -07:00
@@ -0,0 +1,50 @@
+#ifndef _ASM_M32R_SIGCONTEXT_H
+#define _ASM_M32R_SIGCONTEXT_H
+
+/* $Id$ */
+
+#include <linux/config.h>
+
+struct sigcontext {
+	/* CPU registers */
+	/* Saved main processor registers. */
+	unsigned long sc_r4;
+	unsigned long sc_r5;
+	unsigned long sc_r6;
+	struct pt_regs *sc_pt_regs;
+	unsigned long sc_r0;
+	unsigned long sc_r1;
+	unsigned long sc_r2;
+	unsigned long sc_r3;
+	unsigned long sc_r7;
+	unsigned long sc_r8;
+	unsigned long sc_r9;
+	unsigned long sc_r10;
+	unsigned long sc_r11;
+	unsigned long sc_r12;
+
+	/* Saved main processor status and miscellaneous context registers. */
+#if defined(CONFIG_ISA_M32R2) && defined(CONFIG_ISA_DSP_LEVEL2)
+	unsigned long sc_acc0h;
+	unsigned long sc_acc0l;
+	unsigned long sc_acc1h;
+	unsigned long sc_acc1l;
+#elif defined(CONFIG_ISA_M32R2) || defined(CONFIG_ISA_M32R)
+	unsigned long sc_acch;
+	unsigned long sc_accl;
+#else
+#error unknown isa configuration
+#endif
+	unsigned long sc_psw;
+	unsigned long sc_bpc;		/* saved PC for TRAP syscalls */
+	unsigned long sc_bbpsw;
+	unsigned long sc_bbpc;
+	unsigned long sc_spu;		/* saved user stack */
+	unsigned long sc_fp;
+	unsigned long sc_lr;		/* saved PC for JL syscalls */
+	unsigned long sc_spi;		/* saved kernel stack */
+
+	unsigned long	oldmask;
+};
+
+#endif  /* _ASM_M32R_SIGCONTEXT_H */
diff -Nru a/include/asm-m32r/siginfo.h b/include/asm-m32r/siginfo.h
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/include/asm-m32r/siginfo.h	2004-10-18 14:57:23 -07:00
@@ -0,0 +1,8 @@
+#ifndef _M32R_SIGINFO_H
+#define _M32R_SIGINFO_H
+
+/* $Id$ */
+
+#include <asm-generic/siginfo.h>
+
+#endif /* _M32R_SIGINFO_H */
diff -Nru a/include/asm-m32r/signal.h b/include/asm-m32r/signal.h
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/include/asm-m32r/signal.h	2004-10-18 14:57:23 -07:00
@@ -0,0 +1,200 @@
+#ifndef _ASM_M32R_SIGNAL_H
+#define _ASM_M32R_SIGNAL_H
+
+/* $Id$ */
+
+/* orig : i386 2.4.18 */
+
+#include <linux/types.h>
+#include <linux/linkage.h>
+#include <linux/time.h>
+#include <linux/compiler.h>
+
+/* Avoid too many header ordering problems.  */
+struct siginfo;
+
+#ifdef __KERNEL__
+/* Most things should be clean enough to redefine this at will, if care
+   is taken to make libc match.  */
+
+#define _NSIG		64
+#define _NSIG_BPW	32
+#define _NSIG_WORDS	(_NSIG / _NSIG_BPW)
+
+typedef unsigned long old_sigset_t;		/* at least 32 bits */
+
+typedef struct {
+	unsigned long sig[_NSIG_WORDS];
+} sigset_t;
+
+#else
+/* Here we must cater to libcs that poke about in kernel headers.  */
+
+#define NSIG		32
+typedef unsigned long sigset_t;
+
+#endif /* __KERNEL__ */
+
+#define SIGHUP		 1
+#define SIGINT		 2
+#define SIGQUIT		 3
+#define SIGILL		 4
+#define SIGTRAP		 5
+#define SIGABRT		 6
+#define SIGIOT		 6
+#define SIGBUS		 7
+#define SIGFPE		 8
+#define SIGKILL		 9
+#define SIGUSR1		10
+#define SIGSEGV		11
+#define SIGUSR2		12
+#define SIGPIPE		13
+#define SIGALRM		14
+#define SIGTERM		15
+#define SIGSTKFLT	16
+#define SIGCHLD		17
+#define SIGCONT		18
+#define SIGSTOP		19
+#define SIGTSTP		20
+#define SIGTTIN		21
+#define SIGTTOU		22
+#define SIGURG		23
+#define SIGXCPU		24
+#define SIGXFSZ		25
+#define SIGVTALRM	26
+#define SIGPROF		27
+#define SIGWINCH	28
+#define SIGIO		29
+#define SIGPOLL		SIGIO
+/*
+#define SIGLOST		29
+*/
+#define SIGPWR		30
+#define SIGSYS		31
+#define	SIGUNUSED	31
+
+/* These should not be considered constants from userland.  */
+#define SIGRTMIN	32
+#define SIGRTMAX	_NSIG
+
+/*
+ * SA_FLAGS values:
+ *
+ * SA_ONSTACK indicates that a registered stack_t will be used.
+ * SA_INTERRUPT is a no-op, but left due to historical reasons. Use the
+ * SA_RESTART flag to get restarting signals (which were the default long ago)
+ * SA_NOCLDSTOP flag to turn off SIGCHLD when children stop.
+ * SA_RESETHAND clears the handler when the signal is delivered.
+ * SA_NOCLDWAIT flag on SIGCHLD to inhibit zombies.
+ * SA_NODEFER prevents the current signal from being masked in the handler.
+ *
+ * SA_ONESHOT and SA_NOMASK are the historical Linux names for the Single
+ * Unix names RESETHAND and NODEFER respectively.
+ */
+#define SA_NOCLDSTOP	0x00000001u
+#define SA_NOCLDWAIT	0x00000002u
+#define SA_SIGINFO	0x00000004u
+#define SA_ONSTACK	0x08000000u
+#define SA_RESTART	0x10000000u
+#define SA_NODEFER	0x40000000u
+#define SA_RESETHAND	0x80000000u
+
+#define SA_NOMASK	SA_NODEFER
+#define SA_ONESHOT	SA_RESETHAND
+#define SA_INTERRUPT	0x20000000 /* dummy -- ignored */
+
+#define SA_RESTORER	0x04000000
+
+/*
+ * sigaltstack controls
+ */
+#define SS_ONSTACK	1
+#define SS_DISABLE	2
+
+#define MINSIGSTKSZ	2048
+#define SIGSTKSZ	8192
+
+#ifdef __KERNEL__
+
+/*
+ * These values of sa_flags are used only by the kernel as part of the
+ * irq handling routines.
+ *
+ * SA_INTERRUPT is also used by the irq handling routines.
+ * SA_SHIRQ is for shared interrupt support on PCI and EISA.
+ */
+#define SA_PROBE		SA_ONESHOT
+#define SA_SAMPLE_RANDOM	SA_RESTART
+#define SA_SHIRQ		0x04000000
+#endif
+
+#define SIG_BLOCK          0	/* for blocking signals */
+#define SIG_UNBLOCK        1	/* for unblocking signals */
+#define SIG_SETMASK        2	/* for setting the signal mask */
+
+/* Type of a signal handler.  */
+typedef void __signalfn_t(int);
+typedef __signalfn_t __user *__sighandler_t;
+
+typedef void __restorefn_t(void);
+typedef __restorefn_t __user *__sigrestore_t;
+
+#define SIG_DFL	((__sighandler_t)0)	/* default signal handling */
+#define SIG_IGN	((__sighandler_t)1)	/* ignore signal */
+#define SIG_ERR	((__sighandler_t)-1)	/* error return from signal */
+
+#ifdef __KERNEL__
+struct old_sigaction {
+	__sighandler_t sa_handler;
+	old_sigset_t sa_mask;
+	unsigned long sa_flags;
+	__sigrestore_t sa_restorer;
+};
+
+struct sigaction {
+	__sighandler_t sa_handler;
+	unsigned long sa_flags;
+	__sigrestore_t sa_restorer;
+	sigset_t sa_mask;		/* mask last for extensibility */
+};
+
+struct k_sigaction {
+	struct sigaction sa;
+};
+#else
+/* Here we must cater to libcs that poke about in kernel headers.  */
+
+struct sigaction {
+	union {
+	  __sighandler_t _sa_handler;
+	  void (*_sa_sigaction)(int, struct siginfo *, void *);
+	} _u;
+	sigset_t sa_mask;
+	unsigned long sa_flags;
+	void (*sa_restorer)(void);
+};
+
+#define sa_handler	_u._sa_handler
+#define sa_sigaction	_u._sa_sigaction
+
+#endif /* __KERNEL__ */
+
+typedef struct sigaltstack {
+	void __user *ss_sp;
+	int ss_flags;
+	size_t ss_size;
+} stack_t;
+
+#ifdef __KERNEL__
+#include <asm/sigcontext.h>
+
+#undef __HAVE_ARCH_SIG_BITOPS
+
+struct pt_regs;
+extern int FASTCALL(do_signal(struct pt_regs *regs, sigset_t *oldset));
+
+#define ptrace_signal_deliver(regs, cookie)	do { } while (0)
+
+#endif /* __KERNEL__ */
+
+#endif  /* _ASM_M32R_SIGNAL_H */
diff -Nru a/include/asm-m32r/smp.h b/include/asm-m32r/smp.h
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/include/asm-m32r/smp.h	2004-10-18 14:57:21 -07:00
@@ -0,0 +1,119 @@
+#ifndef _ASM_M32R_SMP_H
+#define _ASM_M32R_SMP_H
+
+/* $Id$ */
+
+#include <linux/config.h>
+
+#ifdef CONFIG_SMP
+#ifndef __ASSEMBLY__
+
+#include <linux/cpumask.h>
+#include <linux/spinlock.h>
+#include <linux/threads.h>
+#include <asm/m32r.h>
+
+#define PHYSID_ARRAY_SIZE       1
+
+struct physid_mask
+{
+	unsigned long mask[PHYSID_ARRAY_SIZE];
+};
+
+typedef struct physid_mask physid_mask_t;
+
+#define physid_set(physid, map)                 set_bit(physid, (map).mask)
+#define physid_clear(physid, map)               clear_bit(physid, (map).mask)
+#define physid_isset(physid, map)               test_bit(physid, (map).mask)
+#define physid_test_and_set(physid, map)        test_and_set_bit(physid, (map).mask)
+
+#define physids_and(dst, src1, src2)            bitmap_and((dst).mask, (src1).mask, (src2).mask, MAX_APICS)
+#define physids_or(dst, src1, src2)             bitmap_or((dst).mask, (src1).mask, (src2).mask, MAX_APICS)
+#define physids_clear(map)                      bitmap_zero((map).mask, MAX_APICS)
+#define physids_complement(dst, src)            bitmap_complement((dst).mask,(src).mask, MAX_APICS)
+#define physids_empty(map)                      bitmap_empty((map).mask, MAX_APICS)
+#define physids_equal(map1, map2)               bitmap_equal((map1).mask, (map2).mask, MAX_APICS)
+#define physids_weight(map)                     bitmap_weight((map).mask, MAX_APICS)
+#define physids_shift_right(d, s, n)            bitmap_shift_right((d).mask, (s).mask, n, MAX_APICS)
+#define physids_shift_left(d, s, n)             bitmap_shift_left((d).mask, (s).mask, n, MAX_APICS)
+#define physids_coerce(map)                     ((map).mask[0])
+
+#define physids_promote(physids)					\
+	({								\
+		physid_mask_t __physid_mask = PHYSID_MASK_NONE;		\
+		__physid_mask.mask[0] = physids;			\
+		__physid_mask;						\
+	})
+
+#define physid_mask_of_physid(physid)					\
+	({								\
+		physid_mask_t __physid_mask = PHYSID_MASK_NONE;		\
+		physid_set(physid, __physid_mask);			\
+		__physid_mask;						\
+	})
+
+#define PHYSID_MASK_ALL         { {[0 ... PHYSID_ARRAY_SIZE-1] = ~0UL} }
+#define PHYSID_MASK_NONE        { {[0 ... PHYSID_ARRAY_SIZE-1] = 0UL} }
+
+extern physid_mask_t phys_cpu_present_map;
+
+/*
+ * Some lowlevel functions might want to know about
+ * the real CPU ID <-> CPU # mapping.
+ */
+extern volatile int physid_2_cpu[NR_CPUS];
+extern volatile int cpu_2_physid[NR_CPUS];
+#define physid_to_cpu(physid)	physid_2_cpu[physid]
+#define cpu_to_physid(cpu_id)	cpu_2_physid[cpu_id]
+
+#define smp_processor_id()	(current_thread_info()->cpu)
+
+extern cpumask_t cpu_callout_map;
+#define cpu_possible_map cpu_callout_map
+
+static __inline__ int hard_smp_processor_id(void)
+{
+	return (int)*(volatile long *)M32R_CPUID_PORTL;
+}
+
+static __inline__ int cpu_logical_map(int cpu)
+{
+	return cpu;
+}
+
+static __inline__ int cpu_number_map(int cpu)
+{
+	return cpu;
+}
+
+static __inline__ unsigned int num_booting_cpus(void)
+{
+	return cpus_weight(cpu_callout_map);
+}
+
+extern void smp_send_timer(void);
+extern void calibrate_delay(void);
+extern unsigned long send_IPI_mask_phys(cpumask_t, int, int);
+
+#endif	/* not __ASSEMBLY__ */
+
+#define NO_PROC_ID (0xff)	/* No processor magic marker */
+
+#define PROC_CHANGE_PENALTY	(15)	/* Schedule penalty */
+
+/*
+ * M32R-mp IPI
+ */
+#define RESCHEDULE_IPI		(M32R_IRQ_IPI0-M32R_IRQ_IPI0)
+#define INVALIDATE_TLB_IPI	(M32R_IRQ_IPI1-M32R_IRQ_IPI0)
+#define CALL_FUNCTION_IPI	(M32R_IRQ_IPI2-M32R_IRQ_IPI0)
+#define LOCAL_TIMER_IPI		(M32R_IRQ_IPI3-M32R_IRQ_IPI0)
+#define INVALIDATE_CACHE_IPI	(M32R_IRQ_IPI4-M32R_IRQ_IPI0)
+#define CPU_BOOT_IPI		(M32R_IRQ_IPI5-M32R_IRQ_IPI0)
+
+#define IPI_SHIFT	(0)
+#define NR_IPIS		(8)
+
+#endif	/* CONFIG_SMP */
+
+#endif	/* _ASM_M32R_SMP_H */
diff -Nru a/include/asm-m32r/socket.h b/include/asm-m32r/socket.h
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/include/asm-m32r/socket.h	2004-10-18 14:57:21 -07:00
@@ -0,0 +1,50 @@
+#ifndef _ASM_M32R_SOCKET_H
+#define _ASM_M32R_SOCKET_H
+
+#include <asm/sockios.h>
+
+/* For setsockoptions(2) */
+#define SOL_SOCKET	1
+
+#define SO_DEBUG	1
+#define SO_REUSEADDR	2
+#define SO_TYPE		3
+#define SO_ERROR	4
+#define SO_DONTROUTE	5
+#define SO_BROADCAST	6
+#define SO_SNDBUF	7
+#define SO_RCVBUF	8
+#define SO_KEEPALIVE	9
+#define SO_OOBINLINE	10
+#define SO_NO_CHECK	11
+#define SO_PRIORITY	12
+#define SO_LINGER	13
+#define SO_BSDCOMPAT	14
+/* To add :#define SO_REUSEPORT 15 */
+#define SO_PASSCRED	16
+#define SO_PEERCRED	17
+#define SO_RCVLOWAT	18
+#define SO_SNDLOWAT	19
+#define SO_RCVTIMEO	20
+#define SO_SNDTIMEO	21
+
+/* Security levels - as per NRL IPv6 - don't actually do anything */
+#define SO_SECURITY_AUTHENTICATION		22
+#define SO_SECURITY_ENCRYPTION_TRANSPORT	23
+#define SO_SECURITY_ENCRYPTION_NETWORK		24
+
+#define SO_BINDTODEVICE	25
+
+/* Socket filtering */
+#define SO_ATTACH_FILTER        26
+#define SO_DETACH_FILTER        27
+
+#define SO_PEERNAME		28
+#define SO_TIMESTAMP		29
+#define SCM_TIMESTAMP		SO_TIMESTAMP
+
+#define SO_ACCEPTCONN		30
+
+#define SO_PEERSEC		31
+
+#endif /* _ASM_M32R_SOCKET_H */
diff -Nru a/include/asm-m32r/sockios.h b/include/asm-m32r/sockios.h
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/include/asm-m32r/sockios.h	2004-10-18 14:57:23 -07:00
@@ -0,0 +1,14 @@
+#ifndef _ASM_M32R_SOCKIOS_H
+#define _ASM_M32R_SOCKIOS_H
+
+/* $Id$ */
+
+/* Socket-level I/O control calls. */
+#define FIOSETOWN 	0x8901
+#define SIOCSPGRP	0x8902
+#define FIOGETOWN	0x8903
+#define SIOCGPGRP	0x8904
+#define SIOCATMARK	0x8905
+#define SIOCGSTAMP	0x8906		/* Get stamp */
+
+#endif  /* _ASM_M32R_SOCKIOS_H */
diff -Nru a/include/asm-m32r/spinlock.h b/include/asm-m32r/spinlock.h
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/include/asm-m32r/spinlock.h	2004-10-18 14:57:24 -07:00
@@ -0,0 +1,382 @@
+#ifndef _ASM_M32R_SPINLOCK_H
+#define _ASM_M32R_SPINLOCK_H
+
+/*
+ *  linux/include/asm-m32r/spinlock.h
+ *
+ *  M32R version:
+ *    Copyright (C) 2001, 2002  Hitoshi Yamamoto
+ *    Copyright (C) 2004  Hirokazu Takata <takata at linux-m32r.org>
+ */
+
+#include <linux/config.h>	/* CONFIG_DEBUG_SPINLOCK, CONFIG_SMP */
+#include <linux/compiler.h>
+#include <asm/atomic.h>
+#include <asm/page.h>
+
+extern int printk(const char * fmt, ...)
+	__attribute__ ((format (printf, 1, 2)));
+
+#define RW_LOCK_BIAS		 0x01000000
+#define RW_LOCK_BIAS_STR	"0x01000000"
+
+/* It seems that people are forgetting to
+ * initialize their spinlocks properly, tsk tsk.
+ * Remember to turn this off in 2.4. -ben
+ */
+#if defined(CONFIG_DEBUG_SPINLOCK)
+#define SPINLOCK_DEBUG	1
+#else
+#define SPINLOCK_DEBUG	0
+#endif
+
+/*
+ * Your basic SMP spinlocks, allowing only a single CPU anywhere
+ */
+
+typedef struct {
+	volatile int lock;
+#if SPINLOCK_DEBUG
+	unsigned magic;
+#endif
+#ifdef CONFIG_PREEMPT
+	unsigned int break_lock;
+#endif
+} spinlock_t;
+
+#define SPINLOCK_MAGIC	0xdead4ead
+
+#if SPINLOCK_DEBUG
+#define SPINLOCK_MAGIC_INIT	, SPINLOCK_MAGIC
+#else
+#define SPINLOCK_MAGIC_INIT	/* */
+#endif
+
+#define SPIN_LOCK_UNLOCKED (spinlock_t) { 1 SPINLOCK_MAGIC_INIT }
+
+#define spin_lock_init(x)	do { *(x) = SPIN_LOCK_UNLOCKED; } while(0)
+
+/*
+ * Simple spin lock operations.  There are two variants, one clears IRQ's
+ * on the local processor, one does not.
+ *
+ * We make no fairness assumptions. They have a cost.
+ */
+
+#define spin_is_locked(x)	(*(volatile int *)(&(x)->lock) <= 0)
+#define spin_unlock_wait(x)	do { barrier(); } while(spin_is_locked(x))
+#define _raw_spin_lock_flags(lock, flags) _raw_spin_lock(lock)
+
+/**
+ * _raw_spin_trylock - Try spin lock and return a result
+ * @lock: Pointer to the lock variable
+ *
+ * _raw_spin_trylock() tries to get the lock and returns a result.
+ * On the m32r, the result value is 1 (= Success) or 0 (= Failure).
+ */
+static inline int _raw_spin_trylock(spinlock_t *lock)
+{
+	int oldval;
+	unsigned long tmp1, tmp2;
+
+	/*
+	 * lock->lock :  =1 : unlock
+	 *            : <=0 : lock
+	 * {
+	 *   oldval = lock->lock; <--+ need atomic operation
+	 *   lock->lock = 0;      <--+
+	 * }
+	 */
+	__asm__ __volatile__ (
+		"# spin_trylock			\n\t"
+		"ldi	%1, #0;			\n\t"
+		"mvfc	%2, psw;		\n\t"
+		"clrpsw	#0x40 -> nop;		\n\t"
+		DCACHE_CLEAR("%0", "r6", "%3")
+		"lock	%0, @%3;		\n\t"
+		"unlock	%1, @%3;		\n\t"
+		"mvtc	%2, psw;		\n\t"
+		: "=&r" (oldval), "=&r" (tmp1), "=&r" (tmp2)
+		: "r" (&lock->lock)
+		: "memory"
+#ifdef CONFIG_CHIP_M32700_TS1
+		, "r6"
+#endif	/* CONFIG_CHIP_M32700_TS1 */
+	);
+
+	return (oldval > 0);
+}
+
+static inline void _raw_spin_lock(spinlock_t *lock)
+{
+	unsigned long tmp0, tmp1;
+
+#if SPINLOCK_DEBUG
+	__label__ here;
+here:
+	if (lock->magic != SPINLOCK_MAGIC) {
+		printk("eip: %p\n", &&here);
+		BUG();
+	}
+#endif
+	/*
+	 * lock->lock :  =1 : unlock
+	 *            : <=0 : lock
+	 *
+	 * for ( ; ; ) {
+	 *   lock->lock -= 1;  <-- need atomic operation
+	 *   if (lock->lock == 0) break;
+	 *   for ( ; lock->lock <= 0 ; );
+	 * }
+	 */
+	__asm__ __volatile__ (
+		"# spin_lock			\n\t"
+		".fillinsn			\n"
+		"1:				\n\t"
+		"mvfc	%1, psw;		\n\t"
+		"clrpsw	#0x40 -> nop;		\n\t"
+		DCACHE_CLEAR("%0", "r6", "%2")
+		"lock	%0, @%2;		\n\t"
+		"addi	%0, #-1;		\n\t"
+		"unlock	%0, @%2;		\n\t"
+		"mvtc	%1, psw;		\n\t"
+		"bltz	%0, 2f;			\n\t"
+		LOCK_SECTION_START(".balign 4 \n\t")
+		".fillinsn			\n"
+		"2:				\n\t"
+		"ld	%0, @%2;		\n\t"
+		"bgtz	%0, 1b;			\n\t"
+		"bra	2b;			\n\t"
+		LOCK_SECTION_END
+		: "=&r" (tmp0), "=&r" (tmp1)
+		: "r" (&lock->lock)
+		: "memory"
+#ifdef CONFIG_CHIP_M32700_TS1
+		, "r6"
+#endif	/* CONFIG_CHIP_M32700_TS1 */
+	);
+}
+
+static inline void _raw_spin_unlock(spinlock_t *lock)
+{
+#if SPINLOCK_DEBUG
+	BUG_ON(lock->magic != SPINLOCK_MAGIC);
+	BUG_ON(!spin_is_locked(lock));
+#endif
+	mb();
+	lock->lock = 1;
+}
+
+/*
+ * Read-write spinlocks, allowing multiple readers
+ * but only one writer.
+ *
+ * NOTE! it is quite common to have readers in interrupts
+ * but no interrupt writers. For those circumstances we
+ * can "mix" irq-safe locks - any writer needs to get a
+ * irq-safe write-lock, but readers can get non-irqsafe
+ * read-locks.
+ */
+typedef struct {
+	volatile int lock;
+#if SPINLOCK_DEBUG
+	unsigned magic;
+#endif
+#ifdef CONFIG_PREEMPT
+	unsigned int break_lock;
+#endif
+} rwlock_t;
+
+#define RWLOCK_MAGIC	0xdeaf1eed
+
+#if SPINLOCK_DEBUG
+#define RWLOCK_MAGIC_INIT	, RWLOCK_MAGIC
+#else
+#define RWLOCK_MAGIC_INIT	/* */
+#endif
+
+#define RW_LOCK_UNLOCKED (rwlock_t) { RW_LOCK_BIAS RWLOCK_MAGIC_INIT }
+
+#define rwlock_init(x)	do { *(x) = RW_LOCK_UNLOCKED; } while(0)
+
+#define rwlock_is_locked(x)	((x)->lock != RW_LOCK_BIAS)
+
+/*
+ * On x86, we implement read-write locks as a 32-bit counter
+ * with the high bit (sign) being the "contended" bit.
+ *
+ * The inline assembly is non-obvious. Think about it.
+ *
+ * Changed to use the same technique as rw semaphores.  See
+ * semaphore.h for details.  -ben
+ */
+/* the spinlock helpers are in arch/i386/kernel/semaphore.c */
+
+static inline void _raw_read_lock(rwlock_t *rw)
+{
+	unsigned long tmp0, tmp1;
+
+#if SPINLOCK_DEBUG
+	BUG_ON(rw->magic != RWLOCK_MAGIC);
+#endif
+	/*
+	 * rw->lock :  >0 : unlock
+	 *          : <=0 : lock
+	 *
+	 * for ( ; ; ) {
+	 *   rw->lock -= 1;  <-- need atomic operation
+	 *   if (rw->lock >= 0) break;
+	 *   rw->lock += 1;  <-- need atomic operation
+	 *   for ( ; rw->lock <= 0 ; );
+	 * }
+	 */
+	__asm__ __volatile__ (
+		"# read_lock			\n\t"
+		".fillinsn			\n"
+		"1:				\n\t"
+		"mvfc	%1, psw;		\n\t"
+		"clrpsw	#0x40 -> nop;		\n\t"
+		DCACHE_CLEAR("%0", "r6", "%2")
+		"lock	%0, @%2;		\n\t"
+		"addi	%0, #-1;		\n\t"
+		"unlock	%0, @%2;		\n\t"
+		"mvtc	%1, psw;		\n\t"
+		"bltz	%0, 2f;			\n\t"
+		LOCK_SECTION_START(".balign 4 \n\t")
+		".fillinsn			\n"
+		"2:				\n\t"
+		"clrpsw	#0x40 -> nop;		\n\t"
+		DCACHE_CLEAR("%0", "r6", "%2")
+		"lock	%0, @%2;		\n\t"
+		"addi	%0, #1;			\n\t"
+		"unlock	%0, @%2;		\n\t"
+		"mvtc	%1, psw;		\n\t"
+		".fillinsn			\n"
+		"3:				\n\t"
+		"ld	%0, @%2;		\n\t"
+		"bgtz	%0, 1b;			\n\t"
+		"bra	3b;			\n\t"
+		LOCK_SECTION_END
+		: "=&r" (tmp0), "=&r" (tmp1)
+		: "r" (&rw->lock)
+		: "memory"
+#ifdef CONFIG_CHIP_M32700_TS1
+		, "r6"
+#endif	/* CONFIG_CHIP_M32700_TS1 */
+	);
+}
+
+static inline void _raw_write_lock(rwlock_t *rw)
+{
+	unsigned long tmp0, tmp1, tmp2;
+
+#if SPINLOCK_DEBUG
+	BUG_ON(rw->magic != RWLOCK_MAGIC);
+#endif
+	/*
+	 * rw->lock :  =RW_LOCK_BIAS_STR : unlock
+	 *          : !=RW_LOCK_BIAS_STR : lock
+	 *
+	 * for ( ; ; ) {
+	 *   rw->lock -= RW_LOCK_BIAS_STR;  <-- need atomic operation
+	 *   if (rw->lock == 0) break;
+	 *   rw->lock += RW_LOCK_BIAS_STR;  <-- need atomic operation
+	 *   for ( ; rw->lock != RW_LOCK_BIAS_STR ; ) ;
+	 * }
+	 */
+	__asm__ __volatile__ (
+		"# write_lock					\n\t"
+		"seth	%1, #high(" RW_LOCK_BIAS_STR ");	\n\t"
+		"or3	%1, %1, #low(" RW_LOCK_BIAS_STR ");	\n\t"
+		".fillinsn					\n"
+		"1:						\n\t"
+		"mvfc	%2, psw;				\n\t"
+		"clrpsw	#0x40 -> nop;				\n\t"
+		DCACHE_CLEAR("%0", "r7", "%3")
+		"lock	%0, @%3;				\n\t"
+		"sub	%0, %1;					\n\t"
+		"unlock	%0, @%3;				\n\t"
+		"mvtc	%2, psw;				\n\t"
+		"bnez	%0, 2f;					\n\t"
+		LOCK_SECTION_START(".balign 4 \n\t")
+		".fillinsn					\n"
+		"2:						\n\t"
+		"clrpsw	#0x40 -> nop;				\n\t"
+		DCACHE_CLEAR("%0", "r7", "%3")
+		"lock	%0, @%3;				\n\t"
+		"add	%0, %1;					\n\t"
+		"unlock	%0, @%3;				\n\t"
+		"mvtc	%2, psw;				\n\t"
+		".fillinsn					\n"
+		"3:						\n\t"
+		"ld	%0, @%3;				\n\t"
+		"beq	%0, %1, 1b;				\n\t"
+		"bra	3b;					\n\t"
+		LOCK_SECTION_END
+		: "=&r" (tmp0), "=&r" (tmp1), "=&r" (tmp2)
+		: "r" (&rw->lock)
+		: "memory"
+#ifdef CONFIG_CHIP_M32700_TS1
+		, "r7"
+#endif	/* CONFIG_CHIP_M32700_TS1 */
+	);
+}
+
+static inline void _raw_read_unlock(rwlock_t *rw)
+{
+	unsigned long tmp0, tmp1;
+
+	__asm__ __volatile__ (
+		"# read_unlock			\n\t"
+		"mvfc	%1, psw;		\n\t"
+		"clrpsw	#0x40 -> nop;		\n\t"
+		DCACHE_CLEAR("%0", "r6", "%2")
+		"lock	%0, @%2;		\n\t"
+		"addi	%0, #1;			\n\t"
+		"unlock	%0, @%2;		\n\t"
+		"mvtc	%1, psw;		\n\t"
+		: "=&r" (tmp0), "=&r" (tmp1)
+		: "r" (&rw->lock)
+		: "memory"
+#ifdef CONFIG_CHIP_M32700_TS1
+		, "r6"
+#endif	/* CONFIG_CHIP_M32700_TS1 */
+	);
+}
+
+static inline void _raw_write_unlock(rwlock_t *rw)
+{
+	unsigned long tmp0, tmp1, tmp2;
+
+	__asm__ __volatile__ (
+		"# write_unlock					\n\t"
+		"seth	%1, #high(" RW_LOCK_BIAS_STR ");	\n\t"
+		"or3	%1, %1, #low(" RW_LOCK_BIAS_STR ");	\n\t"
+		"mvfc	%2, psw;				\n\t"
+		"clrpsw	#0x40 -> nop;				\n\t"
+		DCACHE_CLEAR("%0", "r7", "%3")
+		"lock	%0, @%3;				\n\t"
+		"add	%0, %1;					\n\t"
+		"unlock	%0, @%3;				\n\t"
+		"mvtc	%2, psw;				\n\t"
+		: "=&r" (tmp0), "=&r" (tmp1), "=&r" (tmp2)
+		: "r" (&rw->lock)
+		: "memory"
+#ifdef CONFIG_CHIP_M32700_TS1
+		, "r7"
+#endif	/* CONFIG_CHIP_M32700_TS1 */
+	);
+}
+
+#define _raw_read_trylock(lock) generic_raw_read_trylock(lock)
+
+static inline int _raw_write_trylock(rwlock_t *lock)
+{
+	atomic_t *count = (atomic_t *)lock;
+	if (atomic_sub_and_test(RW_LOCK_BIAS, count))
+		return 1;
+	atomic_add(RW_LOCK_BIAS, count);
+	return 0;
+}
+
+#endif	/* _ASM_M32R_SPINLOCK_H */
diff -Nru a/include/asm-m32r/stat.h b/include/asm-m32r/stat.h
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/include/asm-m32r/stat.h	2004-10-18 14:57:23 -07:00
@@ -0,0 +1,91 @@
+#ifndef _ASM_M32R_STAT_H
+#define _ASM_M32R_STAT_H
+
+/* $Id$ */
+
+/* orig : i386 2.4.18 */
+
+#include <asm/byteorder.h>
+
+struct __old_kernel_stat {
+	unsigned short st_dev;
+	unsigned short st_ino;
+	unsigned short st_mode;
+	unsigned short st_nlink;
+	unsigned short st_uid;
+	unsigned short st_gid;
+	unsigned short st_rdev;
+	unsigned long  st_size;
+	unsigned long  st_atime;
+	unsigned long  st_mtime;
+	unsigned long  st_ctime;
+};
+
+#define STAT_HAVE_NSEC	1
+
+struct stat {
+	unsigned short st_dev;
+	unsigned short __pad1;
+	unsigned long  st_ino;
+	unsigned short st_mode;
+	unsigned short st_nlink;
+	unsigned short st_uid;
+	unsigned short st_gid;
+	unsigned short st_rdev;
+	unsigned short __pad2;
+	unsigned long  st_size;
+	unsigned long  st_blksize;
+	unsigned long  st_blocks;
+	unsigned long  st_atime;
+	unsigned long  st_atime_nsec;
+	unsigned long  st_mtime;
+	unsigned long  st_mtime_nsec;
+	unsigned long  st_ctime;
+	unsigned long  st_ctime_nsec;
+	unsigned long  __unused4;
+	unsigned long  __unused5;
+};
+
+/* This matches struct stat64 in glibc2.1, hence the absolutely
+ * insane amounts of padding around dev_t's.
+ */
+struct stat64 {
+	unsigned long long	st_dev;
+	unsigned char	__pad0[4];
+#define STAT64_HAS_BROKEN_ST_INO
+	unsigned long	__st_ino;
+
+	unsigned int	st_mode;
+	unsigned int	st_nlink;
+
+	unsigned long	st_uid;
+	unsigned long	st_gid;
+
+	unsigned long long	st_rdev;
+	unsigned char	__pad3[4];
+
+	long long	st_size;
+	unsigned long	st_blksize;
+
+#if defined(__BIG_ENDIAN)
+	unsigned long	__pad4;		/* future possible st_blocks high bits */
+	unsigned long	st_blocks;	/* Number 512-byte blocks allocated. */
+#elif defined(__LITTLE_ENDIAN)
+	unsigned long	st_blocks;	/* Number 512-byte blocks allocated. */
+	unsigned long	__pad4;		/* future possible st_blocks high bits */
+#else
+#error no endian defined
+#endif
+	unsigned long	st_atime;
+	unsigned long	st_atime_nsec;
+
+	unsigned long	st_mtime;
+	unsigned long	st_mtime_nsec;
+
+	unsigned long	st_ctime;
+	unsigned long	st_ctime_nsec;
+
+	unsigned long long	st_ino;
+};
+
+#endif  /* _ASM_M32R_STAT_H */
diff -Nru a/include/asm-m32r/statfs.h b/include/asm-m32r/statfs.h
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/include/asm-m32r/statfs.h	2004-10-18 14:57:24 -07:00
@@ -0,0 +1,6 @@
+#ifndef _ASM_M32R_STATFS_H
+#define _ASM_M32R_STATFS_H
+
+#include <asm-generic/statfs.h>
+
+#endif  /* _ASM_M32R_STATFS_H */
diff -Nru a/include/asm-m32r/string.h b/include/asm-m32r/string.h
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/include/asm-m32r/string.h	2004-10-18 14:57:24 -07:00
@@ -0,0 +1,15 @@
+#ifndef _ASM_M32R_STRING_H
+#define _ASM_M32R_STRING_H
+
+/* $Id$ */
+
+#define  __HAVE_ARCH_STRLEN
+extern size_t strlen(const char * s);
+
+#define  __HAVE_ARCH_MEMCPY
+extern void *memcpy(void *__to, __const__ void *__from, size_t __n);
+
+#define  __HAVE_ARCH_MEMSET
+extern void *memset(void *__s, int __c, size_t __count);
+
+#endif  /* _ASM_M32R_STRING_H */
diff -Nru a/include/asm-m32r/syscall.h b/include/asm-m32r/syscall.h
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/include/asm-m32r/syscall.h	2004-10-18 14:57:22 -07:00
@@ -0,0 +1,11 @@
+#ifndef _ASM_M32R_SYSCALL_H
+#define _ASM_M32R_SYSCALL_H
+
+/* $Id$ */
+
+/* Definitions for the system call vector.  */
+#define SYSCALL_VECTOR          "2"
+#define SYSCALL_VECTOR_ADDRESS  "0xa0"
+
+#endif /* _ASM_M32R_SYSCALL_H */
+
diff -Nru a/include/asm-m32r/system.h b/include/asm-m32r/system.h
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/include/asm-m32r/system.h	2004-10-18 14:57:21 -07:00
@@ -0,0 +1,301 @@
+#ifndef _ASM_M32R_SYSTEM_H
+#define _ASM_M32R_SYSTEM_H
+
+/*
+ * 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  by Hiroyuki Kondo, Hirokazu Takata, and Hitoshi Yamamoto
+ */
+
+#include <linux/config.h>
+
+#ifdef __KERNEL__
+
+/*
+ * switch_to(prev, next) should switch from task `prev' to `next'
+ * `prev' will never be the same as `next'.
+ *
+ * `next' and `prev' should be struct task_struct, but it isn't always defined
+ */
+
+#ifndef CONFIG_SMP
+#define prepare_to_switch()  do { } while(0)
+#endif	/* not CONFIG_SMP */
+
+#define switch_to(prev, next, last)  do { \
+	register unsigned long  arg0 __asm__ ("r0") = (unsigned long)prev; \
+	register unsigned long  arg1 __asm__ ("r1") = (unsigned long)next; \
+	register unsigned long  *oldsp __asm__ ("r2") = &(prev->thread.sp); \
+	register unsigned long  *newsp __asm__ ("r3") = &(next->thread.sp); \
+	register unsigned long  *oldlr __asm__ ("r4") = &(prev->thread.lr); \
+	register unsigned long  *newlr __asm__ ("r5") = &(next->thread.lr); \
+	register struct task_struct  *__last __asm__ ("r6"); \
+	__asm__ __volatile__ ( \
+		"st     r8, @-r15                                 \n\t" \
+		"st     r9, @-r15                                 \n\t" \
+		"st    r10, @-r15                                 \n\t" \
+		"st    r11, @-r15                                 \n\t" \
+		"st    r12, @-r15                                 \n\t" \
+		"st    r13, @-r15                                 \n\t" \
+		"st    r14, @-r15                                 \n\t" \
+		"seth  r14, #high(1f)                             \n\t" \
+		"or3   r14, r14, #low(1f)                         \n\t" \
+		"st    r14, @r4    ; store old LR                 \n\t" \
+		"st    r15, @r2    ; store old SP                 \n\t" \
+		"ld    r15, @r3    ; load new SP                  \n\t" \
+		"st     r0, @-r15  ; store 'prev' onto new stack  \n\t" \
+		"ld    r14, @r5    ; load new LR                  \n\t" \
+		"jmp   r14                                        \n\t" \
+		".fillinsn                                        \n  " \
+		"1:                                               \n\t" \
+		"ld     r6, @r15+  ; load 'prev' from new stack   \n\t" \
+		"ld    r14, @r15+                                 \n\t" \
+		"ld    r13, @r15+                                 \n\t" \
+		"ld    r12, @r15+                                 \n\t" \
+		"ld    r11, @r15+                                 \n\t" \
+		"ld    r10, @r15+                                 \n\t" \
+		"ld     r9, @r15+                                 \n\t" \
+		"ld     r8, @r15+                                 \n\t" \
+		: "=&r" (__last) \
+		: "r" (arg0), "r" (arg1), "r" (oldsp), "r" (newsp), \
+		  "r" (oldlr), "r" (newlr) \
+		: "memory" \
+	); \
+	last = __last; \
+} while(0)
+
+/* Interrupt Control */
+#if !defined(CONFIG_CHIP_M32102)
+#define local_irq_enable() \
+	__asm__ __volatile__ ("setpsw #0x40 -> nop": : :"memory")
+#define local_irq_disable() \
+	__asm__ __volatile__ ("clrpsw #0x40 -> nop": : :"memory")
+#else	/* CONFIG_CHIP_M32102 */
+static __inline__ void local_irq_enable(void)
+{
+	unsigned long tmpreg;
+	__asm__ __volatile__(
+		"mvfc	%0, psw;		\n\t"
+		"or3	%0, %0, #0x0040;	\n\t"
+		"mvtc	%0, psw;		\n\t"
+	: "=&r" (tmpreg) : : "cbit", "memory");
+}
+
+static __inline__ void local_irq_disable(void)
+{
+	unsigned long tmpreg0, tmpreg1;
+	__asm__ __volatile__(
+		"ld24	%0, #0	; Use 32-bit insn. \n\t"
+		"mvfc	%1, psw	; No interrupt can be accepted here. \n\t"
+		"mvtc	%0, psw	\n\t"
+		"and3	%0, %1, #0xffbf	\n\t"
+		"mvtc	%0, psw	\n\t"
+	: "=&r" (tmpreg0), "=&r" (tmpreg1) : : "cbit", "memory");
+}
+#endif	/* CONFIG_CHIP_M32102 */
+
+#define local_save_flags(x) \
+	__asm__ __volatile__("mvfc %0,psw" : "=r"(x) : /* no input */)
+
+#define local_irq_restore(x) \
+	__asm__ __volatile__("mvtc %0,psw" : /* no outputs */ \
+		: "r" (x) : "cbit", "memory")
+
+#if !defined(CONFIG_CHIP_M32102)
+#define local_irq_save(x)				\
+	__asm__ __volatile__(				\
+  		"mvfc	%0, psw;		\n\t"	\
+	  	"clrpsw	#0x40 -> nop;		\n\t"	\
+  		: "=r" (x) : /* no input */ : "memory")
+#else	/* CONFIG_CHIP_M32102 */
+#define local_irq_save(x) 				\
+	({						\
+		unsigned long tmpreg;			\
+		__asm__ __volatile__( 			\
+			"ld24	%1, #0 \n\t" 		\
+			"mvfc	%0, psw \n\t"		\
+			"mvtc	%1, psw \n\t"		\
+			"and3	%1, %0, #0xffbf \n\t"	\
+			"mvtc	%1, psw \n\t" 		\
+			: "=r" (x), "=&r" (tmpreg)	\
+			: : "cbit", "memory");		\
+	})
+#endif	/* CONFIG_CHIP_M32102 */
+
+#define irqs_disabled()					\
+	({						\
+		unsigned long flags;			\
+		local_save_flags(flags);		\
+		!(flags & 0x40);			\
+	})
+
+#endif  /* __KERNEL__ */
+
+#define nop()	__asm__ __volatile__ ("nop" : : )
+
+#define xchg(ptr,x) \
+	((__typeof__(*(ptr)))__xchg((unsigned long)(x),(ptr),sizeof(*(ptr))))
+
+#define tas(ptr)	(xchg((ptr),1))
+
+#ifdef CONFIG_SMP
+extern void  __xchg_called_with_bad_pointer(void);
+#endif
+
+#ifdef CONFIG_CHIP_M32700_TS1
+#define DCACHE_CLEAR(reg0, reg1, addr)				\
+	"seth	"reg1", #high(dcache_dummy);		\n\t"	\
+	"or3	"reg1", "reg1", #low(dcache_dummy);	\n\t"	\
+	"lock	"reg0", @"reg1";			\n\t"	\
+	"add3	"reg0", "addr", #0x1000;		\n\t"	\
+	"ld	"reg0", @"reg0";			\n\t"	\
+	"add3	"reg0", "addr", #0x2000;		\n\t"	\
+	"ld	"reg0", @"reg0";			\n\t"	\
+	"unlock	"reg0", @"reg1";			\n\t"
+	/* FIXME: This workaround code cannot handle kenrel modules
+	 * correctly under SMP environment.
+	 */
+#else	/* CONFIG_CHIP_M32700_TS1 */
+#define DCACHE_CLEAR(reg0, reg1, addr)
+#endif	/* CONFIG_CHIP_M32700_TS1 */
+
+static __inline__ unsigned long __xchg(unsigned long x, volatile void * ptr,
+	int size)
+{
+	unsigned long flags;
+	unsigned long tmp = 0;
+
+	local_irq_save(flags);
+
+	switch (size) {
+#ifndef CONFIG_SMP
+	case 1:
+		__asm__ __volatile__ (
+			"ldb	%0, @%2 \n\t"
+			"stb	%1, @%2 \n\t"
+			: "=&r" (tmp) : "r" (x), "r" (ptr) : "memory");
+		break;
+	case 2:
+		__asm__ __volatile__ (
+			"ldh	%0, @%2 \n\t"
+			"sth	%1, @%2 \n\t"
+			: "=&r" (tmp) : "r" (x), "r" (ptr) : "memory");
+		break;
+	case 4:
+		__asm__ __volatile__ (
+			"ld	%0, @%2 \n\t"
+			"st	%1, @%2 \n\t"
+			: "=&r" (tmp) : "r" (x), "r" (ptr) : "memory");
+		break;
+#else  /* CONFIG_SMP */
+	case 4:
+		__asm__ __volatile__ (
+			DCACHE_CLEAR("%0", "r4", "%2")
+			"lock	%0, @%2;	\n\t"
+			"unlock	%1, @%2;	\n\t"
+			: "=&r" (tmp) : "r" (x), "r" (ptr)
+			: "memory"
+#ifdef CONFIG_CHIP_M32700_TS1
+			, "r4"
+#endif	/* CONFIG_CHIP_M32700_TS1 */
+		);
+		break;
+	default:
+		__xchg_called_with_bad_pointer();
+#endif  /* CONFIG_SMP */
+	}
+
+	local_irq_restore(flags);
+
+	return (tmp);
+}
+
+/*
+ * Memory barrier.
+ *
+ * mb() prevents loads and stores being reordered across this point.
+ * rmb() prevents loads being reordered across this point.
+ * wmb() prevents stores being reordered across this point.
+ */
+#if 0
+#define mb()   __asm__ __volatile__ ("push r0; \n\t pop r0;" : : : "memory")
+#else
+#define mb()   __asm__ __volatile__ ("" : : : "memory")
+#endif
+#define rmb()  mb()
+#define wmb()  mb()
+
+/**
+ * read_barrier_depends - Flush all pending reads that subsequents reads
+ * depend on.
+ *
+ * No data-dependent reads from memory-like regions are ever reordered
+ * over this barrier.  All reads preceding this primitive are guaranteed
+ * to access memory (but not necessarily other CPUs' caches) before any
+ * reads following this primitive that depend on the data return by
+ * any of the preceding reads.  This primitive is much lighter weight than
+ * rmb() on most CPUs, and is never heavier weight than is
+ * rmb().
+ *
+ * These ordering constraints are respected by both the local CPU
+ * and the compiler.
+ *
+ * Ordering is not guaranteed by anything other than these primitives,
+ * not even by data dependencies.  See the documentation for
+ * memory_barrier() for examples and URLs to more information.
+ *
+ * For example, the following code would force ordering (the initial
+ * value of "a" is zero, "b" is one, and "p" is "&a"):
+ *
+ * <programlisting>
+ *      CPU 0                           CPU 1
+ *
+ *      b = 2;
+ *      memory_barrier();
+ *      p = &b;                         q = p;
+ *                                      read_barrier_depends();
+ *                                      d = *q;
+ * </programlisting>
+ *
+ *
+ * because the read of "*q" depends on the read of "p" and these
+ * two reads are separated by a read_barrier_depends().  However,
+ * the following code, with the same initial values for "a" and "b":
+ *
+ * <programlisting>
+ *      CPU 0                           CPU 1
+ *
+ *      a = 2;
+ *      memory_barrier();
+ *      b = 3;                          y = b;
+ *                                      read_barrier_depends();
+ *                                      x = a;
+ * </programlisting>
+ *
+ * does not enforce ordering, since there is no data dependency between
+ * the read of "a" and the read of "b".  Therefore, on some CPUs, such
+ * as Alpha, "y" could be set to 3 and "x" to 0.  Use rmb()
+ * in cases like thiswhere there are no data dependencies.
+ **/
+
+#define read_barrier_depends()	do { } while (0)
+
+#ifdef CONFIG_SMP
+#define smp_mb()	mb()
+#define smp_rmb()	rmb()
+#define smp_wmb()	wmb()
+#define smp_read_barrier_depends()	read_barrier_depends()
+#else
+#define smp_mb()	barrier()
+#define smp_rmb()	barrier()
+#define smp_wmb()	barrier()
+#define smp_read_barrier_depends()	do { } while (0)
+#endif
+
+#define set_mb(var, value) do { xchg(&var, value); } while (0)
+#define set_wmb(var, value) do { var = value; wmb(); } while (0)
+
+#endif  /* _ASM_M32R_SYSTEM_H */
+
diff -Nru a/include/asm-m32r/termbits.h b/include/asm-m32r/termbits.h
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/include/asm-m32r/termbits.h	2004-10-18 14:57:23 -07:00
@@ -0,0 +1,175 @@
+#ifndef _ASM_M32R_TERMBITS_H
+#define _ASM_M32R_TERMBITS_H
+
+/* $Id$ */
+
+#include <linux/posix_types.h>
+
+typedef unsigned char	cc_t;
+typedef unsigned int	speed_t;
+typedef unsigned int	tcflag_t;
+
+#define NCCS 19
+struct termios {
+	tcflag_t c_iflag;		/* input mode flags */
+	tcflag_t c_oflag;		/* output mode flags */
+	tcflag_t c_cflag;		/* control mode flags */
+	tcflag_t c_lflag;		/* local mode flags */
+	cc_t c_line;			/* line discipline */
+	cc_t c_cc[NCCS];		/* control characters */
+};
+
+/* c_cc characters */
+#define VINTR 0
+#define VQUIT 1
+#define VERASE 2
+#define VKILL 3
+#define VEOF 4
+#define VTIME 5
+#define VMIN 6
+#define VSWTC 7
+#define VSTART 8
+#define VSTOP 9
+#define VSUSP 10
+#define VEOL 11
+#define VREPRINT 12
+#define VDISCARD 13
+#define VWERASE 14
+#define VLNEXT 15
+#define VEOL2 16
+
+/* c_iflag bits */
+#define IGNBRK	0000001
+#define BRKINT	0000002
+#define IGNPAR	0000004
+#define PARMRK	0000010
+#define INPCK	0000020
+#define ISTRIP	0000040
+#define INLCR	0000100
+#define IGNCR	0000200
+#define ICRNL	0000400
+#define IUCLC	0001000
+#define IXON	0002000
+#define IXANY	0004000
+#define IXOFF	0010000
+#define IMAXBEL	0020000
+#define IUTF8   0040000
+
+/* c_oflag bits */
+#define OPOST	0000001
+#define OLCUC	0000002
+#define ONLCR	0000004
+#define OCRNL	0000010
+#define ONOCR	0000020
+#define ONLRET	0000040
+#define OFILL	0000100
+#define OFDEL	0000200
+#define NLDLY	0000400
+#define   NL0	0000000
+#define   NL1	0000400
+#define CRDLY	0003000
+#define   CR0	0000000
+#define   CR1	0001000
+#define   CR2	0002000
+#define   CR3	0003000
+#define TABDLY	0014000
+#define   TAB0	0000000
+#define   TAB1	0004000
+#define   TAB2	0010000
+#define   TAB3	0014000
+#define   XTABS	0014000
+#define BSDLY	0020000
+#define   BS0	0000000
+#define   BS1	0020000
+#define VTDLY	0040000
+#define   VT0	0000000
+#define   VT1	0040000
+#define FFDLY	0100000
+#define   FF0	0000000
+#define   FF1	0100000
+
+/* c_cflag bit meaning */
+#define CBAUD	0010017
+#define  B0	0000000		/* hang up */
+#define  B50	0000001
+#define  B75	0000002
+#define  B110	0000003
+#define  B134	0000004
+#define  B150	0000005
+#define  B200	0000006
+#define  B300	0000007
+#define  B600	0000010
+#define  B1200	0000011
+#define  B1800	0000012
+#define  B2400	0000013
+#define  B4800	0000014
+#define  B9600	0000015
+#define  B19200	0000016
+#define  B38400	0000017
+#define EXTA B19200
+#define EXTB B38400
+#define CSIZE	0000060
+#define   CS5	0000000
+#define   CS6	0000020
+#define   CS7	0000040
+#define   CS8	0000060
+#define CSTOPB	0000100
+#define CREAD	0000200
+#define PARENB	0000400
+#define PARODD	0001000
+#define HUPCL	0002000
+#define CLOCAL	0004000
+#define CBAUDEX 0010000
+#define    B57600 0010001
+#define   B115200 0010002
+#define   B230400 0010003
+#define   B460800 0010004
+#define   B500000 0010005
+#define   B576000 0010006
+#define   B921600 0010007
+#define  B1000000 0010010
+#define  B1152000 0010011
+#define  B1500000 0010012
+#define  B2000000 0010013
+#define  B2500000 0010014
+#define  B3000000 0010015
+#define  B3500000 0010016
+#define  B4000000 0010017
+#define CIBAUD	  002003600000	/* input baud rate (not used) */
+#define CMSPAR	  010000000000		/* mark or space (stick) parity */
+#define CRTSCTS	  020000000000		/* flow control */
+
+/* c_lflag bits */
+#define ISIG	0000001
+#define ICANON	0000002
+#define XCASE	0000004
+#define ECHO	0000010
+#define ECHOE	0000020
+#define ECHOK	0000040
+#define ECHONL	0000100
+#define NOFLSH	0000200
+#define TOSTOP	0000400
+#define ECHOCTL	0001000
+#define ECHOPRT	0002000
+#define ECHOKE	0004000
+#define FLUSHO	0010000
+#define PENDIN	0040000
+#define IEXTEN	0100000
+
+/* tcflow() and TCXONC use these */
+#define	TCOOFF		0
+#define	TCOON		1
+#define	TCIOFF		2
+#define	TCION		3
+
+/* tcflush() and TCFLSH use these */
+#define	TCIFLUSH	0
+#define	TCOFLUSH	1
+#define	TCIOFLUSH	2
+
+/* tcsetattr uses these */
+#define	TCSANOW		0
+#define	TCSADRAIN	1
+#define	TCSAFLUSH	2
+
+#endif  /* _ASM_M32R_TERMBITS_H */
diff -Nru a/include/asm-m32r/termios.h b/include/asm-m32r/termios.h
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/include/asm-m32r/termios.h	2004-10-18 14:57:21 -07:00
@@ -0,0 +1,109 @@
+#ifndef _M32R_TERMIOS_H
+#define _M32R_TERMIOS_H
+
+/* orig : i386 2.6.0-test5 */
+
+#include <asm/termbits.h>
+#include <asm/ioctls.h>
+
+struct winsize {
+	unsigned short ws_row;
+	unsigned short ws_col;
+	unsigned short ws_xpixel;
+	unsigned short ws_ypixel;
+};
+
+#define NCC 8
+struct termio {
+	unsigned short c_iflag;		/* input mode flags */
+	unsigned short c_oflag;		/* output mode flags */
+	unsigned short c_cflag;		/* control mode flags */
+	unsigned short c_lflag;		/* local mode flags */
+	unsigned char c_line;		/* line discipline */
+	unsigned char c_cc[NCC];	/* control characters */
+};
+
+/* modem lines */
+#define TIOCM_LE	0x001
+#define TIOCM_DTR	0x002
+#define TIOCM_RTS	0x004
+#define TIOCM_ST	0x008
+#define TIOCM_SR	0x010
+#define TIOCM_CTS	0x020
+#define TIOCM_CAR	0x040
+#define TIOCM_RNG	0x080
+#define TIOCM_DSR	0x100
+#define TIOCM_CD	TIOCM_CAR
+#define TIOCM_RI	TIOCM_RNG
+#define TIOCM_OUT1	0x2000
+#define TIOCM_OUT2	0x4000
+#define TIOCM_LOOP	0x8000
+
+/* ioctl (fd, TIOCSERGETLSR, &result) where result may be as below */
+
+/* line disciplines */
+#define N_TTY		0
+#define N_SLIP		1
+#define N_MOUSE		2
+#define N_PPP		3
+#define N_STRIP		4
+#define N_AX25		5
+#define N_X25		6	/* X.25 async */
+#define N_6PACK		7
+#define N_MASC		8	/* Reserved for Mobitex module <kaz@cafe.net> */
+#define N_R3964		9	/* Reserved for Simatic R3964 module */
+#define N_PROFIBUS_FDL	10	/* Reserved for Profibus <Dave@mvhi.com> */
+#define N_IRDA		11	/* Linux IR - http://irda.sourceforge.net/ */
+#define N_SMSBLOCK	12	/* SMS block mode - for talking to GSM data cards about SMS messages */
+#define N_HDLC		13	/* synchronous HDLC */
+#define N_SYNC_PPP	14	/* synchronous PPP */
+#define N_HCI		15  /* Bluetooth HCI UART */
+
+#ifdef __KERNEL__
+#include <linux/module.h>
+
+/*	intr=^C		quit=^\		erase=del	kill=^U
+	eof=^D		vtime=\0	vmin=\1		sxtc=\0
+	start=^Q	stop=^S		susp=^Z		eol=\0
+	reprint=^R	discard=^U	werase=^W	lnext=^V
+	eol2=\0
+*/
+#define INIT_C_CC "\003\034\177\025\004\0\1\0\021\023\032\0\022\017\027\026\0"
+
+/*
+ * Translate a "termio" structure into a "termios". Ugh.
+ */
+#define SET_LOW_TERMIOS_BITS(termios, termio, x) { \
+	unsigned short __tmp; \
+	get_user(__tmp,&(termio)->x); \
+	*(unsigned short *) &(termios)->x = __tmp; \
+}
+
+#define user_termio_to_kernel_termios(termios, termio) \
+({ \
+	SET_LOW_TERMIOS_BITS(termios, termio, c_iflag); \
+	SET_LOW_TERMIOS_BITS(termios, termio, c_oflag); \
+	SET_LOW_TERMIOS_BITS(termios, termio, c_cflag); \
+	SET_LOW_TERMIOS_BITS(termios, termio, c_lflag); \
+	copy_from_user((termios)->c_cc, (termio)->c_cc, NCC); \
+})
+
+/*
+ * Translate a "termios" structure into a "termio". Ugh.
+ */
+#define kernel_termios_to_user_termio(termio, termios) \
+({ \
+	put_user((termios)->c_iflag, &(termio)->c_iflag); \
+	put_user((termios)->c_oflag, &(termio)->c_oflag); \
+	put_user((termios)->c_cflag, &(termio)->c_cflag); \
+	put_user((termios)->c_lflag, &(termio)->c_lflag); \
+	put_user((termios)->c_line,  &(termio)->c_line); \
+	copy_to_user((termio)->c_cc, (termios)->c_cc, NCC); \
+})
+
+#define user_termios_to_kernel_termios(k, u) copy_from_user(k, u, sizeof(struct termios))
+#define kernel_termios_to_user_termios(u, k) copy_to_user(u, k, sizeof(struct termios))
+
+#endif	/* __KERNEL__ */
+
+#endif	/* _M32R_TERMIOS_H */
diff -Nru a/include/asm-m32r/thread_info.h b/include/asm-m32r/thread_info.h
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/include/asm-m32r/thread_info.h	2004-10-18 14:57:24 -07:00
@@ -0,0 +1,149 @@
+/* thread_info.h: i386 low-level thread information
+ *
+ * Copyright (C) 2002  David Howells (dhowells@redhat.com)
+ * - Incorporating suggestions made by Linus Torvalds and Dave Miller
+ */
+
+#ifndef _ASM_THREAD_INFO_H
+#define _ASM_THREAD_INFO_H
+
+#ifdef __KERNEL__
+
+#ifndef __ASSEMBLY__
+#include <asm/processor.h>
+#endif
+
+/*
+ * low level task data that entry.S needs immediate access to
+ * - this struct should fit entirely inside of one cache line
+ * - this struct shares the supervisor stack pages
+ * - if the contents of this structure are changed, the assembly constants must also be changed
+ */
+#ifndef __ASSEMBLY__
+
+struct thread_info {
+	struct task_struct	*task;		/* main task structure */
+	struct exec_domain	*exec_domain;	/* execution domain */
+	unsigned long		flags;		/* low level flags */
+	unsigned long		status;		/* thread-synchronous flags */
+	__u32			cpu;		/* current CPU */
+	__s32			preempt_count; /* 0 => preemptable, <0 => BUG */
+
+	mm_segment_t		addr_limit;	/* thread address space:
+					 	   0-0xBFFFFFFF for user-thead
+						   0-0xFFFFFFFF for kernel-thread
+						*/
+	struct restart_block    restart_block;
+
+	__u8			supervisor_stack[0];
+};
+
+#else /* !__ASSEMBLY__ */
+
+/* offsets into the thread_info struct for assembly code access */
+#define TI_TASK		0x00000000
+#define TI_EXEC_DOMAIN	0x00000004
+#define TI_FLAGS	0x00000008
+#define TI_STATUS	0x0000000C
+#define TI_CPU		0x00000010
+#define TI_PRE_COUNT	0x00000014
+#define TI_ADDR_LIMIT	0x00000018
+#define TI_RESTART_BLOCK 0x000001C
+
+#endif
+
+#define PREEMPT_ACTIVE		0x4000000
+
+/*
+ * macros/functions for gaining access to the thread information structure
+ *
+ * preempt_count needs to be 1 initially, until the scheduler is functional.
+ */
+#ifndef __ASSEMBLY__
+
+#define INIT_THREAD_INFO(tsk)			\
+{						\
+	.task		= &tsk,			\
+	.exec_domain	= &default_exec_domain,	\
+	.flags		= 0,			\
+	.cpu		= 0,			\
+	.preempt_count	= 1,			\
+	.addr_limit	= KERNEL_DS,		\
+	.restart_block = {			\
+		.fn = do_no_restart_syscall,	\
+	},					\
+}
+
+#define init_thread_info	(init_thread_union.thread_info)
+#define init_stack		(init_thread_union.stack)
+
+/* how to get the thread information struct from C */
+static inline struct thread_info *current_thread_info(void)
+{
+	struct thread_info *ti;
+
+	__asm__ __volatile__ (
+		"ldi	%0, #0xffffe000;	\n\t"
+		"and	%0, sp;			\n\t"
+		: "=r" (ti)
+	);
+
+	return ti;
+}
+
+/* thread information allocation */
+#define THREAD_SIZE (2*PAGE_SIZE)
+#define alloc_thread_info(task) \
+	((struct thread_info *) __get_free_pages(GFP_KERNEL,1))
+#define free_thread_info(ti) free_pages((unsigned long) (ti), 1)
+#define get_thread_info(ti) get_task_struct((ti)->task)
+#define put_thread_info(ti) put_task_struct((ti)->task)
+
+#else /* !__ASSEMBLY__ */
+
+/* how to get the thread information struct from ASM */
+#define GET_THREAD_INFO(reg)	GET_THREAD_INFO reg
+	.macro GET_THREAD_INFO reg
+	ldi	\reg, #0xffffe000
+	and	\reg, sp
+	.endm
+
+#endif
+
+/*
+ * thread information flags
+ * - these are process state flags that various assembly files may need to access
+ * - pending work-to-be-done flags are in LSW
+ * - other flags in MSW
+ */
+#define TIF_SYSCALL_TRACE	0	/* syscall trace active */
+#define TIF_NOTIFY_RESUME	1	/* resumption notification requested */
+#define TIF_SIGPENDING		2	/* signal pending */
+#define TIF_NEED_RESCHED	3	/* rescheduling necessary */
+#define TIF_SINGLESTEP		4	/* restore singlestep on return to user mode */
+#define TIF_IRET		5	/* return with iret */
+#define TIF_POLLING_NRFLAG	16	/* true if poll_idle() is polling TIF_NEED_RESCHED */
+
+#define _TIF_SYSCALL_TRACE	(1<<TIF_SYSCALL_TRACE)
+#define _TIF_NOTIFY_RESUME	(1<<TIF_NOTIFY_RESUME)
+#define _TIF_SIGPENDING		(1<<TIF_SIGPENDING)
+#define _TIF_NEED_RESCHED	(1<<TIF_NEED_RESCHED)
+#define _TIF_SINGLESTEP		(1<<TIF_SINGLESTEP)
+#define _TIF_IRET		(1<<TIF_IRET)
+#define _TIF_POLLING_NRFLAG	(1<<TIF_POLLING_NRFLAG)
+
+#define _TIF_WORK_MASK		0x0000FFFE	/* work to do on interrupt/exception return */
+#define _TIF_ALLWORK_MASK	0x0000FFFF	/* work to do on any return to u-space */
+
+/*
+ * Thread-synchronous status.
+ *
+ * This is different from the flags in that nobody else
+ * ever touches our thread-synchronous status, so we don't
+ * have to worry about atomic accesses.
+ */
+#define TS_USEDFPU		0x0001	/* FPU was used by this task this quantum (SMP) */
+
+#endif /* __KERNEL__ */
+
+#endif /* _ASM_THREAD_INFO_H */
diff -Nru a/include/asm-m32r/timex.h b/include/asm-m32r/timex.h
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/include/asm-m32r/timex.h	2004-10-18 14:57:24 -07:00
@@ -0,0 +1,36 @@
+#ifndef _ASM_M32R_TIMEX_H
+#define _ASM_M32R_TIMEX_H
+
+/* $Id$ */
+
+/*
+ * linux/include/asm-m32r/timex.h
+ *
+ * m32r architecture timex specifications
+ */
+
+#include <linux/config.h>
+
+#define CLOCK_TICK_RATE	(CONFIG_BUS_CLOCK / CONFIG_TIMER_DIVIDE)
+#define CLOCK_TICK_FACTOR	20	/* Factor of both 1000000 and CLOCK_TICK_RATE */
+#define FINETUNE ((((((long)LATCH * HZ - CLOCK_TICK_RATE) << SHIFT_HZ) * \
+	(1000000/CLOCK_TICK_FACTOR) / (CLOCK_TICK_RATE/CLOCK_TICK_FACTOR)) \
+		<< (SHIFT_SCALE-SHIFT_HZ)) / HZ)
+
+#ifdef __KERNEL__
+/*
+ * Standard way to access the cycle counter.
+ * Currently only used on SMP.
+ */
+
+typedef unsigned long long cycles_t;
+
+extern cycles_t cacheflush_time;
+
+static __inline__ cycles_t get_cycles (void)
+{
+	return 0;
+}
+#endif  /* __KERNEL__ */
+
+#endif  /* _ASM_M32R_TIMEX_H */
diff -Nru a/include/asm-m32r/tlb.h b/include/asm-m32r/tlb.h
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/include/asm-m32r/tlb.h	2004-10-18 14:57:23 -07:00
@@ -0,0 +1,20 @@
+#ifndef _M32R_TLB_H
+#define _M32R_TLB_H
+
+/*
+ * x86 doesn't need any special per-pte or
+ * per-vma handling..
+ */
+#define tlb_start_vma(tlb, vma) do { } while (0)
+#define tlb_end_vma(tlb, vma) do { } while (0)
+#define __tlb_remove_tlb_entry(tlb, pte, address) do { } while (0)
+
+/*
+ * .. because we flush the whole mm when it
+ * fills up.
+ */
+#define tlb_flush(tlb) flush_tlb_mm((tlb)->mm)
+
+#include <asm-generic/tlb.h>
+
+#endif /* _M32R_TLB_H */
diff -Nru a/include/asm-m32r/tlbflush.h b/include/asm-m32r/tlbflush.h
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/include/asm-m32r/tlbflush.h	2004-10-18 14:57:24 -07:00
@@ -0,0 +1,102 @@
+#ifndef _ASM_M32R_TLBFLUSH_H
+#define _ASM_M32R_TLBFLUSH_H
+
+#include <linux/config.h>
+#include <asm/m32r.h>
+
+/*
+ * TLB flushing:
+ *
+ *  - flush_tlb() flushes the current mm struct TLBs
+ *  - flush_tlb_all() flushes all processes TLBs
+ *  - flush_tlb_mm(mm) flushes the specified mm context TLB's
+ *  - flush_tlb_page(vma, vmaddr) flushes one page
+ *  - flush_tlb_range(vma, start, end) flushes a range of pages
+ *  - flush_tlb_kernel_range(start, end) flushes a range of kernel pages
+ *  - flush_tlb_pgtables(mm, start, end) flushes a range of page tables
+ */
+
+extern void local_flush_tlb_all(void);
+extern void local_flush_tlb_mm(struct mm_struct *);
+extern void local_flush_tlb_page(struct vm_area_struct *, unsigned long);
+extern void local_flush_tlb_range(struct vm_area_struct *, unsigned long,
+	unsigned long);
+
+#ifndef CONFIG_SMP
+#ifdef CONFIG_MMU
+#define flush_tlb_all()			local_flush_tlb_all()
+#define flush_tlb_mm(mm)		local_flush_tlb_mm(mm)
+#define flush_tlb_page(vma, page)	local_flush_tlb_page(vma, page)
+#define flush_tlb_range(vma, start, end)	\
+	local_flush_tlb_range(vma, start, end)
+#define flush_tlb_kernel_range(start, end)	local_flush_tlb_all()
+#else	/* CONFIG_MMU */
+#define flush_tlb_all()			do { } while (0)
+#define flush_tlb_mm(mm)		do { } while (0)
+#define flush_tlb_page(vma, vmaddr)	do { } while (0)
+#define flush_tlb_range(vma, start, end)	do { } while (0)
+#endif	/* CONFIG_MMU */
+#else	/* CONFIG_SMP */
+extern void smp_flush_tlb_all(void);
+extern void smp_flush_tlb_mm(struct mm_struct *);
+extern void smp_flush_tlb_page(struct vm_area_struct *, unsigned long);
+extern void smp_flush_tlb_range(struct vm_area_struct *, unsigned long,
+	unsigned long);
+
+#define flush_tlb_all()			smp_flush_tlb_all()
+#define flush_tlb_mm(mm)		smp_flush_tlb_mm(mm)
+#define flush_tlb_page(vma, page)	smp_flush_tlb_page(vma, page)
+#define flush_tlb_range(vma, start, end)	\
+	smp_flush_tlb_range(vma, start, end)
+#define flush_tlb_kernel_range(start, end)	smp_flush_tlb_all()
+#endif	/* CONFIG_SMP */
+
+static __inline__ void __flush_tlb_page(unsigned long page)
+{
+	unsigned int tmpreg0, tmpreg1, tmpreg2;
+
+	__asm__ __volatile__ (
+		"seth	%0, #high(%4)	\n\t"
+		"st	%3, @(%5, %0)	\n\t"
+		"ldi	%1, #1		\n\t"
+		"st	%1, @(%6, %0)	\n\t"
+		"add3	%1, %0, %7	\n\t"
+		".fillinsn		\n"
+		"1:			\n\t"
+		"ld	%2, @(%6, %0)	\n\t"
+		"bnez	%2, 1b		\n\t"
+		"ld	%0, @%1+	\n\t"
+		"ld	%1, @%1		\n\t"
+		"st	%2, @+%0	\n\t"
+		"st	%2, @+%1	\n\t"
+		: "=&r" (tmpreg0), "=&r" (tmpreg1), "=&r" (tmpreg2)
+		: "r" (page), "i" (MMU_REG_BASE), "i" (MSVA_offset),
+		"i" (MTOP_offset), "i" (MIDXI_offset)
+		: "memory"
+	);
+}
+
+static __inline__ void __flush_tlb_all(void)
+{
+	unsigned int tmpreg0, tmpreg1;
+
+	__asm__ __volatile__ (
+		"seth	%0, #high(%2)		\n\t"
+		"or3	%0, %0, #low(%2)	\n\t"
+		"ldi	%1, #0xc		\n\t"
+		"st	%1, @%0			\n\t"
+		".fillinsn			\n"
+		"1:				\n\t"
+		"ld	%1, @%0			\n\t"
+		"bnez	%1, 1b			\n\t"
+		: "=&r" (tmpreg0), "=&r" (tmpreg1)
+		: "i" (MTOP) : "memory"
+	);
+}
+
+#define flush_tlb_pgtables(mm, start, end)	do { } while (0)
+
+extern void update_mmu_cache(struct vm_area_struct *, unsigned long, pte_t);
+
+#endif	/* _ASM_M32R_TLBFLUSH_H */
+
diff -Nru a/include/asm-m32r/topology.h b/include/asm-m32r/topology.h
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/include/asm-m32r/topology.h	2004-10-18 14:57:21 -07:00
@@ -0,0 +1,53 @@
+/*
+ * linux/include/asm-generic/topology.h
+ *
+ * Written by: Matthew Dobson, IBM Corporation
+ *
+ * Copyright (C) 2002, IBM Corp.
+ *
+ * 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, GOOD TITLE or
+ * NON INFRINGEMENT.  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.
+ *
+ * Send feedback to <colpatch@us.ibm.com>
+ */
+#ifndef _ASM_M32R_TOPOLOGY_H
+#define _ASM_M32R_TOPOLOGY_H
+
+/* Other architectures wishing to use this simple topology API should fill
+   in the below functions as appropriate in their own <asm/topology.h> file. */
+
+#define cpu_to_node(cpu)	(0)
+
+#ifndef parent_node
+#define parent_node(node)	(0)
+#endif
+#ifndef node_to_cpumask
+#define node_to_cpumask(node)	(cpu_online_map)
+#endif
+#ifndef node_to_first_cpu
+#define node_to_first_cpu(node)	(0)
+#endif
+#ifndef pcibus_to_cpumask
+#define pcibus_to_cpumask(bus)	(cpu_online_map)
+#endif
+
+/* Cross-node load balancing interval. */
+#ifndef NODE_BALANCE_RATE
+#define NODE_BALANCE_RATE 10
+#endif
+
+#endif /* _ASM_M32R_TOPOLOGY_H */
diff -Nru a/include/asm-m32r/types.h b/include/asm-m32r/types.h
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/include/asm-m32r/types.h	2004-10-18 14:57:23 -07:00
@@ -0,0 +1,64 @@
+#ifndef _ASM_M32R_TYPES_H
+#define _ASM_M32R_TYPES_H
+
+#ifndef __ASSEMBLY__
+
+/* $Id$ */
+
+/* orig : i386 2.4.18 */
+
+typedef unsigned short umode_t;
+
+/*
+ * __xx is ok: it doesn't pollute the POSIX namespace. Use these in the
+ * header files exported to user space
+ */
+
+typedef __signed__ char __s8;
+typedef unsigned char __u8;
+
+typedef __signed__ short __s16;
+typedef unsigned short __u16;
+
+typedef __signed__ int __s32;
+typedef unsigned int __u32;
+
+#if defined(__GNUC__) && !defined(__STRICT_ANSI__)
+typedef __signed__ long long __s64;
+typedef unsigned long long __u64;
+#endif
+#endif /* __ASSEMBLY__ */
+
+/*
+ * These aren't exported outside the kernel to avoid name space clashes
+ */
+#ifdef __KERNEL__
+
+#define BITS_PER_LONG 32
+
+#ifndef __ASSEMBLY__
+
+typedef signed char s8;
+typedef unsigned char u8;
+
+typedef signed short s16;
+typedef unsigned short u16;
+
+typedef signed int s32;
+typedef unsigned int u32;
+
+typedef signed long long s64;
+typedef unsigned long long u64;
+
+/* DMA addresses are 32-bits wide.  */
+
+typedef u32 dma_addr_t;
+typedef u64 dma64_addr_t;
+
+typedef unsigned short kmem_bufctl_t;
+
+#endif /* __ASSEMBLY__ */
+
+#endif /* __KERNEL__ */
+
+#endif  /* _ASM_M32R_TYPES_H */
diff -Nru a/include/asm-m32r/uaccess.h b/include/asm-m32r/uaccess.h
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/include/asm-m32r/uaccess.h	2004-10-18 14:57:24 -07:00
@@ -0,0 +1,752 @@
+#ifndef _ASM_M32R_UACCESS_H
+#define _ASM_M32R_UACCESS_H
+
+/*
+ *  linux/include/asm-m32r/uaccess.h
+ *
+ *  M32R version.
+ *    Copyright (C) 2004  Hirokazu Takata <takata at linux-m32r.org>
+ */
+
+#undef UACCESS_DEBUG
+
+#ifdef UACCESS_DEBUG
+#define UAPRINTK(args...) printk(args)
+#else
+#define UAPRINTK(args...)
+#endif /* UACCESS_DEBUG */
+
+/*
+ * User space memory access functions
+ */
+#include <linux/config.h>
+#include <linux/errno.h>
+#include <linux/thread_info.h>
+#include <asm/page.h>
+
+#define VERIFY_READ 0
+#define VERIFY_WRITE 1
+
+/*
+ * The fs value determines whether argument validity checking should be
+ * performed or not.  If get_fs() == USER_DS, checking is performed, with
+ * get_fs() == KERNEL_DS, checking is bypassed.
+ *
+ * For historical reasons, these macros are grossly misnamed.
+ */
+
+#define MAKE_MM_SEG(s)	((mm_segment_t) { (s) })
+
+#ifdef CONFIG_MMU
+#define KERNEL_DS	MAKE_MM_SEG(0xFFFFFFFF)
+#define USER_DS		MAKE_MM_SEG(PAGE_OFFSET)
+#else
+#define KERNEL_DS	MAKE_MM_SEG(0xFFFFFFFF)
+#define USER_DS		MAKE_MM_SEG(0xFFFFFFFF)
+#endif /* CONFIG_MMU */
+
+#define get_ds()	(KERNEL_DS)
+#ifdef CONFIG_MMU
+#define get_fs()	(current_thread_info()->addr_limit)
+#define set_fs(x)	(current_thread_info()->addr_limit = (x))
+#else
+static inline mm_segment_t get_fs(void)
+{
+  return USER_DS;
+}
+
+static inline void set_fs(mm_segment_t s)
+{
+}
+#endif /* CONFIG_MMU */
+
+#define segment_eq(a,b)	((a).seg == (b).seg)
+
+#define __addr_ok(addr) \
+	((unsigned long)(addr) < (current_thread_info()->addr_limit.seg))
+
+/*
+ * Test whether a block of memory is a valid user space address.
+ * Returns 0 if the range is valid, nonzero otherwise.
+ *
+ * This is equivalent to the following test:
+ * (u33)addr + (u33)size >= (u33)current->addr_limit.seg
+ *
+ * This needs 33-bit arithmetic. We have a carry...
+ */
+#define __range_ok(addr,size) ({					\
+	unsigned long flag, sum; 					\
+	__chk_user_ptr(addr);						\
+	asm ( 								\
+		"	cmpu	%1, %1    ; clear cbit\n"		\
+		"	addx	%1, %3    ; set cbit if overflow\n"	\
+		"	subx	%0, %0\n"				\
+		"	cmpu	%4, %1\n"				\
+		"	subx	%0, %5\n"				\
+		: "=&r"(flag), "=r"(sum)				\
+		: "1"(addr), "r"((int)(size)), 				\
+		  "r"(current_thread_info()->addr_limit.seg), "r"(0)	\
+		: "cbit" );						\
+	flag; })
+
+/**
+ * access_ok: - Checks if a user space pointer is valid
+ * @type: Type of access: %VERIFY_READ or %VERIFY_WRITE.  Note that
+ *        %VERIFY_WRITE is a superset of %VERIFY_READ - if it is safe
+ *        to write to a block, it is always safe to read from it.
+ * @addr: User space pointer to start of block to check
+ * @size: Size of block to check
+ *
+ * Context: User context only.  This function may sleep.
+ *
+ * Checks if a pointer to a block of memory in user space is valid.
+ *
+ * Returns true (nonzero) if the memory block may be valid, false (zero)
+ * if it is definitely invalid.
+ *
+ * Note that, depending on architecture, this function probably just
+ * checks that the pointer is in the user space range - after calling
+ * this function, memory access functions may still return -EFAULT.
+ */
+#ifdef CONFIG_MMU
+#define access_ok(type,addr,size) (likely(__range_ok(addr,size) == 0))
+#else
+static inline int access_ok(int type, const void *addr, unsigned long size)
+{
+  extern unsigned long memory_start, memory_end;
+  unsigned long val = (unsigned long)addr;
+
+  return ((val >= memory_start) && ((val + size) < memory_end));
+}
+#endif /* CONFIG_MMU */
+
+/**
+ * verify_area: - Obsolete, use access_ok()
+ * @type: Type of access: %VERIFY_READ or %VERIFY_WRITE
+ * @addr: User space pointer to start of block to check
+ * @size: Size of block to check
+ *
+ * Context: User context only.  This function may sleep.
+ *
+ * This function has been replaced by access_ok().
+ *
+ * Checks if a pointer to a block of memory in user space is valid.
+ *
+ * Returns zero if the memory block may be valid, -EFAULT
+ * if it is definitely invalid.
+ *
+ * See access_ok() for more details.
+ */
+static inline int verify_area(int type, const void __user *addr,
+			      unsigned long size)
+{
+	return access_ok(type, addr, size) ? 0 : -EFAULT;
+}
+
+
+/*
+ * The exception table consists of pairs of addresses: the first is the
+ * address of an instruction that is allowed to fault, and the second is
+ * the address at which the program should continue.  No registers are
+ * modified, so it is entirely up to the continuation code to figure out
+ * what to do.
+ *
+ * All the routines below use bits of fixup code that are out of line
+ * with the main instruction path.  This means when everything is well,
+ * we don't even have to jump over them.  Further, they do not intrude
+ * on our cache or tlb entries.
+ */
+
+struct exception_table_entry
+{
+	unsigned long insn, fixup;
+};
+
+extern int fixup_exception(struct pt_regs *regs);
+
+/*
+ * These are the main single-value transfer routines.  They automatically
+ * use the right size if we just have the right pointer type.
+ *
+ * This gets kind of ugly. We want to return _two_ values in "get_user()"
+ * and yet we don't want to do any pointers, because that is too much
+ * of a performance impact. Thus we have a few rather ugly macros here,
+ * and hide all the uglyness from the user.
+ *
+ * The "__xxx" versions of the user access functions are versions that
+ * do not verify the address space, that must have been done previously
+ * with a separate "access_ok()" call (this is used when we do multiple
+ * accesses to the same area of user memory).
+ */
+
+extern void __get_user_1(void);
+extern void __get_user_2(void);
+extern void __get_user_4(void);
+
+#ifndef MODULE
+#define __get_user_x(size,ret,x,ptr) 					\
+	__asm__ __volatile__(						\
+		"	mv	r0, %0\n"				\
+		"	mv	r1, %1\n" 				\
+		"	bl __get_user_" #size "\n"			\
+		"	mv	%0, r0\n"				\
+		"	mv	%1, r1\n" 				\
+		: "=r"(ret), "=r"(x) 					\
+		: "0"(ptr)						\
+		: "r0", "r1", "r14" )
+#else /* MODULE */
+/*
+ * Use "jl" instead of "bl" for MODULE
+ */
+#define __get_user_x(size,ret,x,ptr) 					\
+	__asm__ __volatile__(						\
+		"	mv	r0, %0\n"				\
+		"	mv	r1, %1\n" 				\
+		"	seth	lr, #high(__get_user_" #size ")\n"	\
+		"	or3	lr, lr, #low(__get_user_" #size ")\n"	\
+		"	jl 	lr\n"					\
+		"	mv	%0, r0\n"				\
+		"	mv	%1, r1\n" 				\
+		: "=r"(ret), "=r"(x) 					\
+		: "0"(ptr)						\
+		: "r0", "r1", "r14" )
+#endif
+
+/* Careful: we have to cast the result to the type of the pointer for sign
+   reasons */
+/**
+ * get_user: - Get a simple variable from user space.
+ * @x:   Variable to store result.
+ * @ptr: Source address, in user space.
+ *
+ * Context: User context only.  This function may sleep.
+ *
+ * This macro copies a single simple variable from user space to kernel
+ * space.  It supports simple types like char and int, but not larger
+ * data types like structures or arrays.
+ *
+ * @ptr must have pointer-to-simple-variable type, and the result of
+ * dereferencing @ptr must be assignable to @x without a cast.
+ *
+ * Returns zero on success, or -EFAULT on error.
+ * On error, the variable @x is set to zero.
+ */
+#define get_user(x,ptr)							\
+({	int __ret_gu,__val_gu;						\
+	__chk_user_ptr(ptr);						\
+	switch(sizeof (*(ptr))) {					\
+	case 1:  __get_user_x(1,__ret_gu,__val_gu,ptr); break;		\
+	case 2:  __get_user_x(2,__ret_gu,__val_gu,ptr); break;		\
+	case 4:  __get_user_x(4,__ret_gu,__val_gu,ptr); break;		\
+	default: __get_user_x(X,__ret_gu,__val_gu,ptr); break;		\
+	}								\
+	(x) = (__typeof__(*(ptr)))__val_gu;				\
+	__ret_gu;							\
+})
+
+extern void __put_user_bad(void);
+
+/**
+ * put_user: - Write a simple value into user space.
+ * @x:   Value to copy to user space.
+ * @ptr: Destination address, in user space.
+ *
+ * Context: User context only.  This function may sleep.
+ *
+ * This macro copies a single simple value from kernel space to user
+ * space.  It supports simple types like char and int, but not larger
+ * data types like structures or arrays.
+ *
+ * @ptr must have pointer-to-simple-variable type, and @x must be assignable
+ * to the result of dereferencing @ptr.
+ *
+ * Returns zero on success, or -EFAULT on error.
+ */
+#define put_user(x,ptr)							\
+  __put_user_check((__typeof__(*(ptr)))(x),(ptr),sizeof(*(ptr)))
+
+
+/**
+ * __get_user: - Get a simple variable from user space, with less checking.
+ * @x:   Variable to store result.
+ * @ptr: Source address, in user space.
+ *
+ * Context: User context only.  This function may sleep.
+ *
+ * This macro copies a single simple variable from user space to kernel
+ * space.  It supports simple types like char and int, but not larger
+ * data types like structures or arrays.
+ *
+ * @ptr must have pointer-to-simple-variable type, and the result of
+ * dereferencing @ptr must be assignable to @x without a cast.
+ *
+ * Caller must check the pointer with access_ok() before calling this
+ * function.
+ *
+ * Returns zero on success, or -EFAULT on error.
+ * On error, the variable @x is set to zero.
+ */
+#define __get_user(x,ptr) \
+  __get_user_nocheck((x),(ptr),sizeof(*(ptr)))
+
+
+/**
+ * __put_user: - Write a simple value into user space, with less checking.
+ * @x:   Value to copy to user space.
+ * @ptr: Destination address, in user space.
+ *
+ * Context: User context only.  This function may sleep.
+ *
+ * This macro copies a single simple value from kernel space to user
+ * space.  It supports simple types like char and int, but not larger
+ * data types like structures or arrays.
+ *
+ * @ptr must have pointer-to-simple-variable type, and @x must be assignable
+ * to the result of dereferencing @ptr.
+ *
+ * Caller must check the pointer with access_ok() before calling this
+ * function.
+ *
+ * Returns zero on success, or -EFAULT on error.
+ */
+#define __put_user(x,ptr) \
+  __put_user_nocheck((__typeof__(*(ptr)))(x),(ptr),sizeof(*(ptr)))
+
+#define __put_user_nocheck(x,ptr,size)					\
+({									\
+	long __pu_err;							\
+	__put_user_size((x),(ptr),(size),__pu_err);			\
+	__pu_err;							\
+})
+
+
+#define __put_user_check(x,ptr,size)					\
+({									\
+	long __pu_err = -EFAULT;					\
+	__typeof__(*(ptr)) __user *__pu_addr = (ptr);			\
+	might_sleep();							\
+	if (access_ok(VERIFY_WRITE,__pu_addr,size))			\
+		__put_user_size((x),__pu_addr,(size),__pu_err);		\
+	__pu_err;							\
+})
+
+#if defined(__LITTLE_ENDIAN__)
+#define __put_user_u64(x, addr, err)                                    \
+        __asm__ __volatile__(                                           \
+                "       .fillinsn\n"                                    \
+                "1:     st %L1,@%2\n"                                    \
+                "       .fillinsn\n"                                    \
+                "2:     st %H1,@(4,%2)\n"                                \
+                "       .fillinsn\n"                                    \
+                "3:\n"                                                  \
+                ".section .fixup,\"ax\"\n"                              \
+                "       .balign 4\n"                                    \
+                "4:     ldi %0,%3\n"                                    \
+                "       seth r14,#high(3b)\n"                           \
+                "       or3 r14,r14,#low(3b)\n"                         \
+                "       jmp r14\n"                                      \
+                ".previous\n"                                           \
+                ".section __ex_table,\"a\"\n"                           \
+                "       .balign 4\n"                                    \
+                "       .long 1b,4b\n"                                  \
+                "       .long 2b,4b\n"                                  \
+                ".previous"                                             \
+                : "=r"(err)                                             \
+                : "r"(x), "r"(addr), "i"(-EFAULT), "0"(err)		\
+                : "r14", "memory")
+
+#elif defined(__BIG_ENDIAN__)
+#define __put_user_u64(x, addr, err)					\
+	__asm__ __volatile__(						\
+		"	.fillinsn\n"					\
+		"1:	st %H1,@%2\n"					\
+		"	.fillinsn\n"					\
+		"2:	st %L1,@(4,%2)\n"				\
+		"	.fillinsn\n"					\
+		"3:\n"							\
+		".section .fixup,\"ax\"\n"				\
+		"	.balign 4\n"					\
+		"4:	ldi %0,%3\n"					\
+		"	seth r14,#high(3b)\n"				\
+		"	or3 r14,r14,#low(3b)\n"				\
+		"	jmp r14\n"					\
+		".previous\n"						\
+		".section __ex_table,\"a\"\n"				\
+		"	.balign 4\n"					\
+		"	.long 1b,4b\n"					\
+		"	.long 2b,4b\n"					\
+		".previous"						\
+		: "=r"(err)						\
+		: "r"(x), "r"(addr), "i"(-EFAULT), "0"(err)		\
+		: "r14", "memory")
+#else
+#error no endian defined
+#endif
+
+#define __put_user_size(x,ptr,size,retval)				\
+do {									\
+	retval = 0;							\
+	__chk_user_ptr(ptr);						\
+	switch (size) {							\
+	  case 1: __put_user_asm(x,ptr,retval,"b"); break;		\
+	  case 2: __put_user_asm(x,ptr,retval,"h"); break;		\
+	  case 4: __put_user_asm(x,ptr,retval,""); break;		\
+	  case 8: __put_user_u64((__typeof__(*ptr))(x),ptr,retval); break;\
+	  default: __put_user_bad();					\
+	}								\
+} while (0)
+
+struct __large_struct { unsigned long buf[100]; };
+#define __m(x) (*(struct __large_struct *)(x))
+
+/*
+ * Tell gcc we read from memory instead of writing: this is because
+ * we do not write to any memory gcc knows about, so there are no
+ * aliasing issues.
+ */
+#define __put_user_asm(x, addr, err, itype)				\
+	__asm__ __volatile__(						\
+		"	.fillinsn\n"					\
+		"1:	st"itype" %1,@%2\n"				\
+		"	.fillinsn\n"					\
+		"2:\n"							\
+		".section .fixup,\"ax\"\n"				\
+		"	.balign 4\n"					\
+		"3:	ldi %0,%3\n"					\
+		"	seth r14,#high(2b)\n"				\
+		"	or3 r14,r14,#low(2b)\n"				\
+		"	jmp r14\n"					\
+		".previous\n"						\
+		".section __ex_table,\"a\"\n"				\
+		"	.balign 4\n"					\
+		"	.long 1b,3b\n"					\
+		".previous"						\
+		: "=r"(err)						\
+		: "r"(x), "r"(addr), "i"(-EFAULT), "0"(err)		\
+		: "r14", "memory")
+
+#define __get_user_nocheck(x,ptr,size)					\
+({									\
+	long __gu_err, __gu_val;					\
+	__get_user_size(__gu_val,(ptr),(size),__gu_err);		\
+	(x) = (__typeof__(*(ptr)))__gu_val;				\
+	__gu_err;							\
+})
+
+extern long __get_user_bad(void);
+
+#define __get_user_size(x,ptr,size,retval)				\
+do {									\
+	retval = 0;							\
+	__chk_user_ptr(ptr);						\
+	switch (size) {							\
+	  case 1: __get_user_asm(x,ptr,retval,"ub"); break;		\
+	  case 2: __get_user_asm(x,ptr,retval,"uh"); break;		\
+	  case 4: __get_user_asm(x,ptr,retval,""); break;		\
+	  default: (x) = __get_user_bad();				\
+	}								\
+} while (0)
+
+#define __get_user_asm(x, addr, err, itype)				\
+	__asm__ __volatile__(						\
+		"	.fillinsn\n"					\
+		"1:	ld"itype" %1,@%2\n"				\
+		"	.fillinsn\n"					\
+		"2:\n"							\
+		".section .fixup,\"ax\"\n"				\
+		"	.balign 4\n"					\
+		"3:	ldi %0,%3\n"					\
+		"	seth r14,#high(2b)\n"				\
+		"	or3 r14,r14,#low(2b)\n"				\
+		"	jmp r14\n"					\
+		".previous\n"						\
+		".section __ex_table,\"a\"\n"				\
+		"	.balign 4\n"					\
+		"	.long 1b,3b\n"					\
+		".previous"						\
+		: "=r"(err), "=&r"(x)					\
+		: "r"(addr), "i"(-EFAULT), "0"(err)			\
+		: "r14", "memory")
+
+/*
+ * Here we special-case 1, 2 and 4-byte copy_*_user invocations.  On a fault
+ * we return the initial request size (1, 2 or 4), as copy_*_user should do.
+ * If a store crosses a page boundary and gets a fault, the m32r will not write
+ * anything, so this is accurate.
+ */
+
+
+/*
+ * Copy To/From Userspace
+ */
+
+/* Generic arbitrary sized copy.  */
+/* Return the number of bytes NOT copied.  */
+#define __copy_user(to,from,size)					\
+do {									\
+	unsigned long __dst, __src, __c;				\
+	__asm__ __volatile__ (						\
+		"	mv	r14, %0\n"				\
+		"	or	r14, %1\n"				\
+		"	beq	%0, %1, 9f\n"				\
+		"	beqz	%2, 9f\n"				\
+		"	and3	r14, r14, #3\n"				\
+		"	bnez	r14, 2f\n"				\
+		"	and3	%2, %2, #3\n"				\
+		"	beqz	%3, 2f\n"				\
+		"	addi	%0, #-4		; word_copy \n"		\
+		"	.fillinsn\n"					\
+		"0:	ld	r14, @%1+\n"				\
+		"	addi	%3, #-1\n"				\
+		"	.fillinsn\n"					\
+		"1:	st	r14, @+%0\n"				\
+		"	bnez	%3, 0b\n"				\
+		"	beqz	%2, 9f\n"				\
+		"	addi	%0, #4\n"				\
+		"	.fillinsn\n"					\
+		"2:	ldb	r14, @%1	; byte_copy \n"		\
+		"	.fillinsn\n"					\
+		"3:	stb	r14, @%0\n"				\
+		"	addi	%1, #1\n"				\
+		"	addi	%2, #-1\n"				\
+		"	addi	%0, #1\n"				\
+		"	bnez	%2, 2b\n"				\
+		"	.fillinsn\n"					\
+		"9:\n"							\
+		".section .fixup,\"ax\"\n"				\
+		"	.balign 4\n"					\
+		"5:	addi	%3, #1\n"				\
+		"	addi	%1, #-4\n"				\
+		"	.fillinsn\n"					\
+		"6:	slli	%3, #2\n"				\
+		"	add	%2, %3\n"				\
+		"	addi	%0, #4\n"				\
+		"	.fillinsn\n"					\
+		"7:	seth	r14, #high(9b)\n"			\
+		"	or3	r14, r14, #low(9b)\n"			\
+		"	jmp	r14\n"					\
+		".previous\n"						\
+		".section __ex_table,\"a\"\n"				\
+		"	.balign 4\n"					\
+		"	.long 0b,6b\n"					\
+		"	.long 1b,5b\n"					\
+		"	.long 2b,9b\n"					\
+		"	.long 3b,9b\n"					\
+		".previous\n"						\
+		: "=&r"(__dst), "=&r"(__src), "=&r"(size), "=&r"(__c)	\
+		: "0"(to), "1"(from), "2"(size), "3"(size / 4)		\
+		: "r14", "memory");					\
+} while (0)
+
+#define __copy_user_zeroing(to,from,size)				\
+do {									\
+	unsigned long __dst, __src, __c;				\
+	__asm__ __volatile__ (						\
+		"	mv	r14, %0\n"				\
+		"	or	r14, %1\n"				\
+		"	beq	%0, %1, 9f\n"				\
+		"	beqz	%2, 9f\n"				\
+		"	and3	r14, r14, #3\n"				\
+		"	bnez	r14, 2f\n"				\
+		"	and3	%2, %2, #3\n"				\
+		"	beqz	%3, 2f\n"				\
+		"	addi	%0, #-4		; word_copy \n"		\
+		"	.fillinsn\n"					\
+		"0:	ld	r14, @%1+\n"				\
+		"	addi	%3, #-1\n"				\
+		"	.fillinsn\n"					\
+		"1:	st	r14, @+%0\n"				\
+		"	bnez	%3, 0b\n"				\
+		"	beqz	%2, 9f\n"				\
+		"	addi	%0, #4\n"				\
+		"	.fillinsn\n"					\
+		"2:	ldb	r14, @%1	; byte_copy \n"		\
+		"	.fillinsn\n"					\
+		"3:	stb	r14, @%0\n"				\
+		"	addi	%1, #1\n"				\
+		"	addi	%2, #-1\n"				\
+		"	addi	%0, #1\n"				\
+		"	bnez	%2, 2b\n"				\
+		"	.fillinsn\n"					\
+		"9:\n"							\
+		".section .fixup,\"ax\"\n"				\
+		"	.balign 4\n"					\
+		"5:	addi	%3, #1\n"				\
+		"	addi	%1, #-4\n"				\
+		"	.fillinsn\n"					\
+		"6:	slli	%3, #2\n"				\
+		"	add	%2, %3\n"				\
+		"	addi	%0, #4\n"				\
+		"	.fillinsn\n"					\
+		"7:	ldi	r14, #0		; store zero \n"	\
+		"	.fillinsn\n"					\
+		"8:	addi	%2, #-1\n"				\
+		"	stb	r14, @%0	; ACE? \n"		\
+		"	addi	%0, #1\n"				\
+		"	bnez	%2, 8b\n"				\
+		"	seth	r14, #high(9b)\n"			\
+		"	or3	r14, r14, #low(9b)\n"			\
+		"	jmp	r14\n"					\
+		".previous\n"						\
+		".section __ex_table,\"a\"\n"				\
+		"	.balign 4\n"					\
+		"	.long 0b,6b\n"					\
+		"	.long 1b,5b\n"					\
+		"	.long 2b,7b\n"					\
+		"	.long 3b,7b\n"					\
+		".previous\n"						\
+		: "=&r"(__dst), "=&r"(__src), "=&r"(size), "=&r"(__c)	\
+		: "0"(to), "1"(from), "2"(size), "3"(size / 4)		\
+		: "r14", "memory");					\
+} while (0)
+
+
+/* We let the __ versions of copy_from/to_user inline, because they're often
+ * used in fast paths and have only a small space overhead.
+ */
+static inline unsigned long __generic_copy_from_user_nocheck(void *to,
+	const void __user *from, unsigned long n)
+{
+	__copy_user_zeroing(to,from,n);
+	return n;
+}
+
+static inline unsigned long __generic_copy_to_user_nocheck(void __user *to,
+	const void *from, unsigned long n)
+{
+	__copy_user(to,from,n);
+	return n;
+}
+
+unsigned long __generic_copy_to_user(void *, const void *, unsigned long);
+unsigned long __generic_copy_from_user(void *, const void *, unsigned long);
+
+/**
+ * __copy_to_user: - Copy a block of data into user space, with less checking.
+ * @to:   Destination address, in user space.
+ * @from: Source address, in kernel space.
+ * @n:    Number of bytes to copy.
+ *
+ * Context: User context only.  This function may sleep.
+ *
+ * Copy data from kernel space to user space.  Caller must check
+ * the specified block with access_ok() before calling this function.
+ *
+ * Returns number of bytes that could not be copied.
+ * On success, this will be zero.
+ */
+#define __copy_to_user(to,from,n)			\
+	__generic_copy_to_user_nocheck((to),(from),(n))
+
+#define __copy_to_user_inatomic __copy_to_user
+#define __copy_from_user_inatomic __copy_from_user
+
+/**
+ * copy_to_user: - Copy a block of data into user space.
+ * @to:   Destination address, in user space.
+ * @from: Source address, in kernel space.
+ * @n:    Number of bytes to copy.
+ *
+ * Context: User context only.  This function may sleep.
+ *
+ * Copy data from kernel space to user space.
+ *
+ * Returns number of bytes that could not be copied.
+ * On success, this will be zero.
+ */
+#define copy_to_user(to,from,n)				\
+({							\
+	might_sleep();					\
+	__generic_copy_to_user((to),(from),(n));	\
+})
+
+/**
+ * __copy_from_user: - Copy a block of data from user space, with less checking. * @to:   Destination address, in kernel space.
+ * @from: Source address, in user space.
+ * @n:    Number of bytes to copy.
+ *
+ * Context: User context only.  This function may sleep.
+ *
+ * Copy data from user space to kernel space.  Caller must check
+ * the specified block with access_ok() before calling this function.
+ *
+ * Returns number of bytes that could not be copied.
+ * On success, this will be zero.
+ *
+ * If some data could not be copied, this function will pad the copied
+ * data to the requested size using zero bytes.
+ */
+#define __copy_from_user(to,from,n)			\
+	__generic_copy_from_user_nocheck((to),(from),(n))
+
+/**
+ * copy_from_user: - Copy a block of data from user space.
+ * @to:   Destination address, in kernel space.
+ * @from: Source address, in user space.
+ * @n:    Number of bytes to copy.
+ *
+ * Context: User context only.  This function may sleep.
+ *
+ * Copy data from user space to kernel space.
+ *
+ * Returns number of bytes that could not be copied.
+ * On success, this will be zero.
+ *
+ * If some data could not be copied, this function will pad the copied
+ * data to the requested size using zero bytes.
+ */
+#define copy_from_user(to,from,n)			\
+({							\
+	might_sleep();					\
+__generic_copy_from_user((to),(from),(n));	\
+})
+
+long __must_check strncpy_from_user(char *dst, const char __user *src,
+				long count);
+long __must_check __strncpy_from_user(char *dst,
+				const char __user *src, long 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.
+ */
+unsigned long __clear_user(void __user *mem, unsigned long 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.  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.
+ */
+unsigned long clear_user(void __user *mem, unsigned long len);
+
+/**
+ * strlen_user: - Get the size of a string in user space.
+ * @str: The string to measure.
+ *
+ * Context: User context only.  This function may sleep.
+ *
+ * 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 there is a limit on the length of a valid string, you may wish to
+ * consider using strnlen_user() instead.
+ */
+#define strlen_user(str) strnlen_user(str, ~0UL >> 1)
+long strnlen_user(const char __user *str, long n);
+
+#endif /* _ASM_M32R_UACCESS_H */
diff -Nru a/include/asm-m32r/ucontext.h b/include/asm-m32r/ucontext.h
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/include/asm-m32r/ucontext.h	2004-10-18 14:57:21 -07:00
@@ -0,0 +1,14 @@
+#ifndef _ASM_M32R_UCONTEXT_H
+#define _ASM_M32R_UCONTEXT_H
+
+/* orig : i386 2.4.18 */
+
+struct ucontext {
+	unsigned long	  uc_flags;
+	struct ucontext  *uc_link;
+	stack_t		  uc_stack;
+	struct sigcontext uc_mcontext;
+	sigset_t	  uc_sigmask;	/* mask last for extensibility */
+};
+
+#endif /* _ASM_M32R_UCONTEXT_H */
diff -Nru a/include/asm-m32r/unaligned.h b/include/asm-m32r/unaligned.h
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/include/asm-m32r/unaligned.h	2004-10-18 14:57:24 -07:00
@@ -0,0 +1,25 @@
+#ifndef _ASM_M32R_UNALIGNED_H
+#define _ASM_M32R_UNALIGNED_H
+
+/* $Id$ */
+
+/* orig : generic 2.4.18 */
+
+/*
+ * For the benefit of those who are trying to port Linux to another
+ * architecture, here are some C-language equivalents.
+ */
+
+#include <asm/string.h>
+
+
+#define get_unaligned(ptr) \
+  ({ __typeof__(*(ptr)) __tmp; memmove(&__tmp, (ptr), sizeof(*(ptr))); __tmp; })
+
+#define put_unaligned(val, ptr)				\
+  ({ __typeof__(*(ptr)) __tmp = (val);			\
+     memmove((ptr), &__tmp, sizeof(*(ptr)));		\
+     (void)0; })
+
+
+#endif  /* _ASM_M32R_UNALIGNED_H */
diff -Nru a/include/asm-m32r/unistd.h b/include/asm-m32r/unistd.h
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/include/asm-m32r/unistd.h	2004-10-18 14:57:23 -07:00
@@ -0,0 +1,483 @@
+#ifndef _ASM_M32R_UNISTD_H
+#define _ASM_M32R_UNISTD_H
+
+/* $Id$ */
+
+#include <asm/syscall.h>	/* SYSCALL_* */
+
+/*
+ * This file contains the system call numbers.
+ */
+
+#define __NR_restart_syscall	  0
+#define __NR_exit		  1
+#define __NR_fork		  2
+#define __NR_read		  3
+#define __NR_write		  4
+#define __NR_open		  5
+#define __NR_close		  6
+#define __NR_waitpid		  7
+#define __NR_creat		  8
+#define __NR_link		  9
+#define __NR_unlink		 10
+#define __NR_execve		 11
+#define __NR_chdir		 12
+#define __NR_time		 13
+#define __NR_mknod		 14
+#define __NR_chmod		 15
+#define __NR_lchown		 16
+#define __NR_break		 17
+#define __NR_oldstat		 18
+#define __NR_lseek		 19
+#define __NR_getpid		 20
+#define __NR_mount		 21
+#define __NR_umount		 22
+#define __NR_setuid		 23
+#define __NR_getuid		 24
+#define __NR_stime		 25
+#define __NR_ptrace		 26
+#define __NR_alarm		 27
+#define __NR_oldfstat		 28
+#define __NR_pause		 29
+#define __NR_utime		 30
+#define __NR_cacheflush		 31 /* old #define __NR_stty		 31*/
+#define __NR_cachectl		 32 /* old #define __NR_gtty		 32*/
+#define __NR_access		 33
+#define __NR_nice		 34
+#define __NR_ftime		 35
+#define __NR_sync		 36
+#define __NR_kill		 37
+#define __NR_rename		 38
+#define __NR_mkdir		 39
+#define __NR_rmdir		 40
+#define __NR_dup		 41
+#define __NR_pipe		 42
+#define __NR_times		 43
+#define __NR_prof		 44
+#define __NR_brk		 45
+#define __NR_setgid		 46
+#define __NR_getgid		 47
+#define __NR_signal		 48
+#define __NR_geteuid		 49
+#define __NR_getegid		 50
+#define __NR_acct		 51
+#define __NR_umount2		 52
+#define __NR_lock		 53
+#define __NR_ioctl		 54
+#define __NR_fcntl		 55
+#define __NR_mpx		 56
+#define __NR_setpgid		 57
+#define __NR_ulimit		 58
+#define __NR_oldolduname	 59
+#define __NR_umask		 60
+#define __NR_chroot		 61
+#define __NR_ustat		 62
+#define __NR_dup2		 63
+#define __NR_getppid		 64
+#define __NR_getpgrp		 65
+#define __NR_setsid		 66
+#define __NR_sigaction		 67
+#define __NR_sgetmask		 68
+#define __NR_ssetmask		 69
+#define __NR_setreuid		 70
+#define __NR_setregid		 71
+#define __NR_sigsuspend		 72
+#define __NR_sigpending		 73
+#define __NR_sethostname	 74
+#define __NR_setrlimit		 75
+#define __NR_getrlimit		 76	/* Back compatible 2Gig limited rlimit */
+#define __NR_getrusage		 77
+#define __NR_gettimeofday	 78
+#define __NR_settimeofday	 79
+#define __NR_getgroups		 80
+#define __NR_setgroups		 81
+#define __NR_select		 82
+#define __NR_symlink		 83
+#define __NR_oldlstat		 84
+#define __NR_readlink		 85
+#define __NR_uselib		 86
+#define __NR_swapon		 87
+#define __NR_reboot		 88
+#define __NR_readdir		 89
+#define __NR_mmap		 90
+#define __NR_munmap		 91
+#define __NR_truncate		 92
+#define __NR_ftruncate		 93
+#define __NR_fchmod		 94
+#define __NR_fchown		 95
+#define __NR_getpriority	 96
+#define __NR_setpriority	 97
+#define __NR_profil		 98
+#define __NR_statfs		 99
+#define __NR_fstatfs		100
+#define __NR_ioperm		101
+#define __NR_socketcall		102
+#define __NR_syslog		103
+#define __NR_setitimer		104
+#define __NR_getitimer		105
+#define __NR_stat		106
+#define __NR_lstat		107
+#define __NR_fstat		108
+#define __NR_olduname		109
+#define __NR_iopl		110
+#define __NR_vhangup		111
+#define __NR_idle		112
+#define __NR_vm86old		113
+#define __NR_wait4		114
+#define __NR_swapoff		115
+#define __NR_sysinfo		116
+#define __NR_ipc		117
+#define __NR_fsync		118
+#define __NR_sigreturn		119
+#define __NR_clone		120
+#define __NR_setdomainname	121
+#define __NR_uname		122
+#define __NR_modify_ldt		123
+#define __NR_adjtimex		124
+#define __NR_mprotect		125
+#define __NR_sigprocmask	126
+#define __NR_create_module	127
+#define __NR_init_module	128
+#define __NR_delete_module	129
+#define __NR_get_kernel_syms	130
+#define __NR_quotactl		131
+#define __NR_getpgid		132
+#define __NR_fchdir		133
+#define __NR_bdflush		134
+#define __NR_sysfs		135
+#define __NR_personality	136
+#define __NR_afs_syscall	137 /* Syscall for Andrew File System */
+#define __NR_setfsuid		138
+#define __NR_setfsgid		139
+#define __NR__llseek		140
+#define __NR_getdents		141
+#define __NR__newselect		142
+#define __NR_flock		143
+#define __NR_msync		144
+#define __NR_readv		145
+#define __NR_writev		146
+#define __NR_getsid		147
+#define __NR_fdatasync		148
+#define __NR__sysctl		149
+#define __NR_mlock		150
+#define __NR_munlock		151
+#define __NR_mlockall		152
+#define __NR_munlockall		153
+#define __NR_sched_setparam		154
+#define __NR_sched_getparam		155
+#define __NR_sched_setscheduler		156
+#define __NR_sched_getscheduler		157
+#define __NR_sched_yield		158
+#define __NR_sched_get_priority_max	159
+#define __NR_sched_get_priority_min	160
+#define __NR_sched_rr_get_interval	161
+#define __NR_nanosleep		162
+#define __NR_mremap		163
+#define __NR_setresuid		164
+#define __NR_getresuid		165
+#define __NR_tas		166
+#define __NR_query_module	167
+#define __NR_poll		168
+#define __NR_nfsservctl		169
+#define __NR_setresgid		170
+#define __NR_getresgid		171
+#define __NR_prctl              172
+#define __NR_rt_sigreturn	173
+#define __NR_rt_sigaction	174
+#define __NR_rt_sigprocmask	175
+#define __NR_rt_sigpending	176
+#define __NR_rt_sigtimedwait	177
+#define __NR_rt_sigqueueinfo	178
+#define __NR_rt_sigsuspend	179
+#define __NR_pread64		180
+#define __NR_pwrite64		181
+#define __NR_chown		182
+#define __NR_getcwd		183
+#define __NR_capget		184
+#define __NR_capset		185
+#define __NR_sigaltstack	186
+#define __NR_sendfile		187
+#define __NR_getpmsg		188	/* some people actually want streams */
+#define __NR_putpmsg		189	/* some people actually want streams */
+#define __NR_vfork		190
+#define __NR_ugetrlimit		191	/* SuS compliant getrlimit */
+#define __NR_mmap2		192
+#define __NR_truncate64		193
+#define __NR_ftruncate64	194
+#define __NR_stat64		195
+#define __NR_lstat64		196
+#define __NR_fstat64		197
+#define __NR_lchown32		198
+#define __NR_getuid32		199
+#define __NR_getgid32		200
+#define __NR_geteuid32		201
+#define __NR_getegid32		202
+#define __NR_setreuid32		203
+#define __NR_setregid32		204
+#define __NR_getgroups32	205
+#define __NR_setgroups32	206
+#define __NR_fchown32		207
+#define __NR_setresuid32	208
+#define __NR_getresuid32	209
+#define __NR_setresgid32	210
+#define __NR_getresgid32	211
+#define __NR_chown32		212
+#define __NR_setuid32		213
+#define __NR_setgid32		214
+#define __NR_setfsuid32		215
+#define __NR_setfsgid32		216
+#define __NR_pivot_root		217
+#define __NR_mincore		218
+#define __NR_madvise		219
+#define __NR_madvise1		219	/* delete when C lib stub is removed */
+#define __NR_getdents64		220
+#define __NR_fcntl64		221
+#define __NR_security           223     /* syscall for security modules */
+#define __NR_gettid             224
+#define __NR_readahead          225
+#define __NR_setxattr           226
+#define __NR_lsetxattr          227
+#define __NR_fsetxattr          228
+#define __NR_getxattr           229
+#define __NR_lgetxattr          230
+#define __NR_fgetxattr          231
+#define __NR_listxattr          232
+#define __NR_llistxattr         233
+#define __NR_flistxattr         234
+#define __NR_removexattr        235
+#define __NR_lremovexattr       236
+#define __NR_fremovexattr       237
+#define __NR_tkill		238
+#define __NR_sendfile64		239
+#define __NR_futex		240
+#define __NR_sched_setaffinity	241
+#define __NR_sched_getaffinity	242
+#define __NR_set_thread_area    243
+#define __NR_get_thread_area    244
+#define __NR_io_setup           245
+#define __NR_io_destroy         246
+#define __NR_io_getevents       247
+#define __NR_io_submit          248
+#define __NR_io_cancel          249
+#define __NR_fadvise64          250
+
+#define __NR_exit_group         252
+#define __NR_lookup_dcookie     253
+#define __NR_epoll_create       254
+#define __NR_epoll_ctl          255
+#define __NR_epoll_wait         256
+#define __NR_remap_file_pages   257
+#define __NR_set_tid_address    258
+#define __NR_timer_create       259
+#define __NR_timer_settime      (__NR_timer_create+1)
+#define __NR_timer_gettime      (__NR_timer_create+2)
+#define __NR_timer_getoverrun   (__NR_timer_create+3)
+#define __NR_timer_delete       (__NR_timer_create+4)
+#define __NR_clock_settime      (__NR_timer_create+5)
+#define __NR_clock_gettime      (__NR_timer_create+6)
+#define __NR_clock_getres       (__NR_timer_create+7)
+#define __NR_clock_nanosleep    (__NR_timer_create+8)
+#define __NR_statfs64           268
+#define __NR_fstatfs64          269
+#define __NR_tgkill             270
+#define __NR_utimes             271
+#define __NR_fadvise64_64       272
+#define __NR_vserver            273
+#define __NR_mbind              274
+#define __NR_get_mempolicy      275
+#define __NR_set_mempolicy      276
+#define __NR_mq_open            277
+#define __NR_mq_unlink          (__NR_mq_open+1)
+#define __NR_mq_timedsend       (__NR_mq_open+2)
+#define __NR_mq_timedreceive    (__NR_mq_open+3)
+#define __NR_mq_notify          (__NR_mq_open+4)
+#define __NR_mq_getsetattr      (__NR_mq_open+5)
+#define __NR_sys_kexec_load    283
+#define __NR_waitid            284
+
+#define NR_syscalls 285
+
+/* user-visible error numbers are in the range -1 - -124: see
+ * <asm-m32r/errno.h>
+ */
+
+#define __syscall_return(type, res) \
+do { \
+	if ((unsigned long)(res) >= (unsigned long)(-(124 + 1))) { \
+	/* Avoid using "res" which is declared to be in register r0; \
+	   errno might expand to a function call and clobber it.  */ \
+		int __err = -(res); \
+		errno = __err; \
+		res = -1; \
+	} \
+	return (type) (res); \
+} while (0)
+
+#define _syscall0(type,name) \
+type name(void) \
+{ \
+register long __scno __asm__ ("r7") = __NR_##name; \
+register long __res __asm__("r0"); \
+__asm__ __volatile__ (\
+	"trap #" SYSCALL_VECTOR \
+	: "=r" (__res) \
+	: "r" (__scno) \
+	: "memory"); \
+__syscall_return(type,__res); \
+}
+
+#define _syscall1(type,name,type1,arg1) \
+type name(type1 arg1) \
+{ \
+register long __scno __asm__ ("r7") = __NR_##name; \
+register long __res __asm__ ("r0") = (long)(arg1); \
+__asm__ __volatile__ (\
+	"trap #" SYSCALL_VECTOR \
+	: "=r" (__res) \
+	: "r" (__scno), "0" (__res) \
+	: "memory"); \
+__syscall_return(type,__res); \
+}
+
+#define _syscall2(type,name,type1,arg1,type2,arg2) \
+type name(type1 arg1,type2 arg2) \
+{ \
+register long __scno __asm__ ("r7") = __NR_##name; \
+register long __arg2 __asm__ ("r1") = (long)(arg2); \
+register long __res __asm__ ("r0") = (long)(arg1); \
+__asm__ __volatile__ (\
+	"trap #" SYSCALL_VECTOR \
+	: "=r" (__res) \
+	: "r" (__scno), "0" (__res), "r" (__arg2) \
+	: "memory"); \
+__syscall_return(type,__res); \
+}
+
+#define _syscall3(type,name,type1,arg1,type2,arg2,type3,arg3) \
+type name(type1 arg1,type2 arg2,type3 arg3) \
+{ \
+register long __scno __asm__ ("r7") = __NR_##name; \
+register long __arg3 __asm__ ("r2") = (long)(arg3); \
+register long __arg2 __asm__ ("r1") = (long)(arg2); \
+register long __res __asm__ ("r0") = (long)(arg1); \
+__asm__ __volatile__ (\
+	"trap #" SYSCALL_VECTOR \
+	: "=r" (__res) \
+	: "r" (__scno), "0" (__res), "r" (__arg2), \
+		"r" (__arg3) \
+	: "memory"); \
+__syscall_return(type,__res); \
+}
+
+#define _syscall4(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4) \
+type name(type1 arg1,type2 arg2,type3 arg3,type4 arg4) \
+{ \
+register long __scno __asm__ ("r7") = __NR_##name; \
+register long __arg4 __asm__ ("r3") = (long)(arg4); \
+register long __arg3 __asm__ ("r2") = (long)(arg3); \
+register long __arg2 __asm__ ("r1") = (long)(arg2); \
+register long __res __asm__ ("r0") = (long)(arg1); \
+__asm__ __volatile__ (\
+	"trap #" SYSCALL_VECTOR \
+	: "=r" (__res) \
+	: "r" (__scno), "0" (__res), "r" (__arg2), \
+		"r" (__arg3), "r" (__arg4) \
+	: "memory"); \
+__syscall_return(type,__res); \
+}
+
+#define _syscall5(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4, \
+	type5,arg5) \
+type name(type1 arg1,type2 arg2,type3 arg3,type4 arg4,type5 arg5) \
+{ \
+register long __scno __asm__ ("r7") = __NR_##name; \
+register long __arg5 __asm__ ("r4") = (long)(arg5); \
+register long __arg4 __asm__ ("r3") = (long)(arg4); \
+register long __arg3 __asm__ ("r2") = (long)(arg3); \
+register long __arg2 __asm__ ("r1") = (long)(arg2); \
+register long __res __asm__ ("r0") = (long)(arg1); \
+__asm__ __volatile__ (\
+	"trap #" SYSCALL_VECTOR \
+	: "=r" (__res) \
+	: "r" (__scno), "0" (__res), "r" (__arg2), \
+		"r" (__arg3), "r" (__arg4), "r" (__arg5) \
+	: "memory"); \
+__syscall_return(type,__res); \
+}
+
+#ifdef __KERNEL__
+#define __ARCH_WANT_IPC_PARSE_VERSION
+#define __ARCH_WANT_OLD_READDIR
+#define __ARCH_WANT_OLD_STAT
+#define __ARCH_WANT_STAT64
+#define __ARCH_WANT_SYS_ALARM
+#define __ARCH_WANT_SYS_GETHOSTNAME
+#define __ARCH_WANT_SYS_PAUSE
+#define __ARCH_WANT_SYS_SGETMASK
+#define __ARCH_WANT_SYS_SIGNAL
+#define __ARCH_WANT_SYS_TIME
+#define __ARCH_WANT_SYS_UTIME
+#define __ARCH_WANT_SYS_WAITPID
+#define __ARCH_WANT_SYS_SOCKETCALL
+#define __ARCH_WANT_SYS_FADVISE64
+#define __ARCH_WANT_SYS_GETPGRP
+#define __ARCH_WANT_SYS_LLSEEK
+#define __ARCH_WANT_SYS_NICE
+#define __ARCH_WANT_SYS_OLD_GETRLIMIT
+#define __ARCH_WANT_SYS_OLDUMOUNT
+#define __ARCH_WANT_SYS_SIGPENDING
+#define __ARCH_WANT_SYS_SIGPROCMASK
+#define __ARCH_WANT_SYS_RT_SIGACTION
+#endif
+
+#ifdef __KERNEL_SYSCALLS__
+
+#include <linux/compiler.h>
+#include <linux/types.h>
+#include <linux/linkage.h>
+#include <asm/ptrace.h>
+
+/*
+ * we need this inline - forking from kernel space will result
+ * in NO COPY ON WRITE (!!!), until an execve is executed. This
+ * is no problem, but for the stack. This is handled by not letting
+ * main() use the stack at all after fork(). Thus, no function
+ * calls - which means inline code for fork too, as otherwise we
+ * would use the stack upon exit from 'fork()'.
+ *
+ * Actually only pause and fork are needed inline, so that there
+ * won't be any messing with the stack from main(), but we define
+ * some others too.
+ */
+static __inline__ _syscall3(int,execve,const char *,file,char **,argv,char **,envp)
+
+asmlinkage int sys_modify_ldt(int func, void __user *ptr, unsigned long bytecount);
+asmlinkage long sys_mmap2(unsigned long addr, unsigned long len,
+			  unsigned long prot, unsigned long flags,
+			  unsigned long fd, unsigned long pgoff);
+asmlinkage int sys_execve(struct pt_regs regs);
+asmlinkage int sys_clone(struct pt_regs regs);
+asmlinkage int sys_fork(struct pt_regs regs);
+asmlinkage int sys_vfork(struct pt_regs regs);
+asmlinkage int sys_pipe(unsigned long __user *fildes);
+asmlinkage int sys_ptrace(long request, long pid, long addr, long data);
+asmlinkage long sys_iopl(unsigned long unused);
+struct sigaction;
+asmlinkage long sys_rt_sigaction(int sig,
+				 const struct sigaction __user *act,
+				 struct sigaction __user *oact,
+				 size_t sigsetsize);
+
+#endif /* __KERNEL_SYSCALLS__ */
+
+/*
+ * "Conditional" syscalls
+ *
+ * What we want is __attribute__((weak,alias("sys_ni_syscall"))),
+ * but it doesn't work on all toolchains, so we just do it by hand
+ */
+#ifndef cond_syscall
+#define cond_syscall(x) asm(".weak\t" #x "\n\t.set\t" #x ",sys_ni_syscall");
+#endif
+
+#endif /* _ASM_M32R_UNISTD_H */
diff -Nru a/include/asm-m32r/user.h b/include/asm-m32r/user.h
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/include/asm-m32r/user.h	2004-10-18 14:57:24 -07:00
@@ -0,0 +1,59 @@
+#ifndef _ASM_M32R_USER_H
+#define _ASM_M32R_USER_H
+
+/* $Id$ */
+
+/* orig : sh 2.4.18
+ * mod  : remove fpu registers
+ */
+
+#include <linux/types.h>
+#include <asm/processor.h>
+#include <asm/ptrace.h>
+#include <asm/page.h>
+
+/*
+ * Core file format: The core file is written in such a way that gdb
+ * can understand it and provide useful information to the user (under
+ * linux we use the `trad-core' bfd).
+ *
+ * The actual file contents are as follows:
+ * UPAGE: 1 page consisting of a user struct that tells gdb
+ *	what is present in the file.  Directly after this is a
+ *	copy of the task_struct, which is currently not used by gdb,
+ *	but it may come in handy at some point.  All of the registers
+ *	are stored as part of the upage.  The upage should always be
+ *	only one page.
+ * DATA: The data area is stored.  We use current->end_text to
+ *	current->brk to pick up all of the user variables, plus any memory
+ *	that may have been sbrk'ed.  No attempt is made to determine if a
+ *	page is demand-zero or if a page is totally unused, we just cover
+ *	the entire range.  All of the addresses are rounded in such a way
+ *	that an integral number of pages is written.
+ * STACK: We need the stack information in order to get a meaningful
+ *	backtrace.  We need to write the data from usp to
+ *	current->start_stack, so we round each of these off in order to be
+ *	able to write an integer number of pages.
+ */
+
+struct user {
+	struct pt_regs	regs;			/* entire machine state */
+	size_t		u_tsize;		/* text size (pages) */
+	size_t		u_dsize;		/* data size (pages) */
+	size_t		u_ssize;		/* stack size (pages) */
+	unsigned long	start_code;		/* text starting address */
+	unsigned long	start_data;		/* data starting address */
+	unsigned long	start_stack;		/* stack starting address */
+	long int	signal;			/* signal causing core dump */
+	struct regs *	u_ar0;			/* help gdb find registers */
+	unsigned long	magic;			/* identifies a core file */
+	char		u_comm[32];		/* user command name */
+};
+
+#define NBPG			PAGE_SIZE
+#define UPAGES			1
+#define HOST_TEXT_START_ADDR	(u.start_code)
+#define HOST_DATA_START_ADDR	(u.start_data)
+#define HOST_STACK_END_ADDR	(u.start_stack + u.u_ssize * NBPG)
+
+#endif /* _ASM_M32R_USER_H */
diff -Nru a/include/asm-m32r/vga.h b/include/asm-m32r/vga.h
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/include/asm-m32r/vga.h	2004-10-18 14:57:21 -07:00
@@ -0,0 +1,22 @@
+#ifndef _ASM_M32R_VGA_H
+#define _ASM_M32R_VGA_H
+
+/* $Id$ */
+
+/*
+ *	Access to VGA videoram
+ *
+ *	(c) 1998 Martin Mares <mj@ucw.cz>
+ */
+
+/*
+ *	On the PC, we can just recalculate addresses and then
+ *	access the videoram directly without any black magic.
+ */
+
+#define VGA_MAP_MEM(x) (unsigned long)phys_to_virt(x)
+
+#define vga_readb(x) (*(x))
+#define vga_writeb(x,y) (*(y) = (x))
+
+#endif  /* _ASM_M32R_VGA_H */
diff -Nru a/include/asm-m32r/xor.h b/include/asm-m32r/xor.h
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/include/asm-m32r/xor.h	2004-10-18 14:57:23 -07:00
@@ -0,0 +1,8 @@
+#ifndef _ASM_M32R_XOR_H
+#define _ASM_M32R_XOR_H
+
+/* $Id$ */
+
+#include <asm-generic/xor.h>
+
+#endif  /* _ASM_M32R_XOR_H */
diff -Nru a/include/asm-m68k/bug.h b/include/asm-m68k/bug.h
--- a/include/asm-m68k/bug.h	2004-10-18 14:56:49 -07:00
+++ b/include/asm-m68k/bug.h	2004-10-18 14:56:49 -07:00
@@ -21,20 +21,7 @@
 } while (0)
 #endif
 
-#define BUG_ON(condition) do { \
-	if (unlikely((condition)!=0)) \
-		BUG(); \
-} while(0)
-
-#define PAGE_BUG(page) do { \
-	BUG(); \
-} while (0)
-
-#define WARN_ON(condition) do { \
-	if (unlikely((condition)!=0)) { \
-		printk("Badness in %s at %s:%d\n", __FUNCTION__, __FILE__, __LINE__); \
-		dump_stack(); \
-	} \
-} while (0)
+#define HAVE_ARCH_BUG
+#include <asm-generic/bug.h>
 
 #endif
diff -Nru a/include/asm-m68k/cacheflush.h b/include/asm-m68k/cacheflush.h
--- a/include/asm-m68k/cacheflush.h	2004-10-18 14:56:33 -07:00
+++ b/include/asm-m68k/cacheflush.h	2004-10-18 14:56:33 -07:00
@@ -132,10 +132,18 @@
 #define flush_dcache_mmap_unlock(mapping)	do { } while (0)
 #define flush_icache_page(vma, page)	__flush_page_to_ram(page_address(page))
 #define flush_icache_user_range(vma,pg,adr,len)	do { } while (0)
+
 #define copy_to_user_page(vma, page, vaddr, dst, src, len) \
-	memcpy(dst, src, len)
+	do {					\
+		flush_cache_page(vma, vaddr);	\
+		memcpy(dst, src, len);		\
+	} while (0)
+
 #define copy_from_user_page(vma, page, vaddr, dst, src, len) \
-	memcpy(dst, src, len)
+	do {					\
+		flush_cache_page(vma, vaddr);	\
+		memcpy(dst, src, len);		\
+	} while (0)
 
 extern void flush_icache_range(unsigned long address, unsigned long endaddr);
 
diff -Nru a/include/asm-m68k/hardirq.h b/include/asm-m68k/hardirq.h
--- a/include/asm-m68k/hardirq.h	2004-10-18 14:56:29 -07:00
+++ b/include/asm-m68k/hardirq.h	2004-10-18 14:56:29 -07:00
@@ -35,20 +35,6 @@
 #define SOFTIRQ_SHIFT	(PREEMPT_SHIFT + PREEMPT_BITS)
 #define HARDIRQ_SHIFT	(SOFTIRQ_SHIFT + SOFTIRQ_BITS)
 
-#define __MASK(x)	((1UL << (x))-1)
-
-#define PREEMPT_MASK	(__MASK(PREEMPT_BITS) << PREEMPT_SHIFT)
-#define HARDIRQ_MASK	(__MASK(HARDIRQ_BITS) << HARDIRQ_SHIFT)
-#define SOFTIRQ_MASK	(__MASK(SOFTIRQ_BITS) << SOFTIRQ_SHIFT)
-
-#define hardirq_count()	(preempt_count() & HARDIRQ_MASK)
-#define softirq_count()	(preempt_count() & SOFTIRQ_MASK)
-#define irq_count()	(preempt_count() & (HARDIRQ_MASK | SOFTIRQ_MASK))
-
-#define PREEMPT_OFFSET	(1UL << PREEMPT_SHIFT)
-#define SOFTIRQ_OFFSET	(1UL << SOFTIRQ_SHIFT)
-#define HARDIRQ_OFFSET	(1UL << HARDIRQ_SHIFT)
-
 /*
  * The hardirq mask has to be large enough to have
  * space for potentially all IRQ sources in the system
@@ -58,27 +44,7 @@
 # error HARDIRQ_BITS is too low!
 #endif
 
-/*
- * Are we doing bottom half or hardware interrupt processing?
- * Are we in a softirq context? Interrupt context?
- */
-#define in_irq()		(hardirq_count())
-#define in_softirq()		(softirq_count())
-#define in_interrupt()		(irq_count())
-
-
-#define hardirq_trylock()	(!in_interrupt())
-#define hardirq_endlock()	do { } while (0)
-
 #define irq_enter()		(preempt_count() += HARDIRQ_OFFSET)
-
-#ifdef CONFIG_PREEMPT
-# define in_atomic()	(preempt_count() != kernel_locked())
-# define IRQ_EXIT_OFFSET (HARDIRQ_OFFSET-1)
-#else
-# define in_atomic()	(preempt_count() != 0)
-# define IRQ_EXIT_OFFSET HARDIRQ_OFFSET
-#endif
 #define irq_exit()							\
 do {									\
 		preempt_count() -= IRQ_EXIT_OFFSET;			\
@@ -86,7 +52,5 @@
 			do_softirq();					\
 		preempt_enable_no_resched();				\
 } while (0)
-
-#define synchronize_irq(irq)	barrier()
 
 #endif
diff -Nru a/include/asm-m68k/ptrace.h b/include/asm-m68k/ptrace.h
--- a/include/asm-m68k/ptrace.h	2004-10-18 14:57:05 -07:00
+++ b/include/asm-m68k/ptrace.h	2004-10-18 14:57:05 -07:00
@@ -73,6 +73,7 @@
 
 #define user_mode(regs) (!((regs)->sr & PS_S))
 #define instruction_pointer(regs) ((regs)->pc)
+#define profile_pc(regs) instruction_pointer(regs)
 extern void show_regs(struct pt_regs *);
 #endif /* __KERNEL__ */
 #endif /* __ASSEMBLY__ */
diff -Nru a/include/asm-m68k/resource.h b/include/asm-m68k/resource.h
--- a/include/asm-m68k/resource.h	2004-10-18 14:55:54 -07:00
+++ b/include/asm-m68k/resource.h	2004-10-18 14:55:54 -07:00
@@ -39,7 +39,7 @@
 	{ RLIM_INFINITY, RLIM_INFINITY },		\
 	{             0,             0 },		\
 	{      INR_OPEN,     INR_OPEN  },		\
-	{ RLIM_INFINITY, RLIM_INFINITY },		\
+	{   MLOCK_LIMIT,   MLOCK_LIMIT },		\
 	{ RLIM_INFINITY, RLIM_INFINITY },		\
 	{ RLIM_INFINITY, RLIM_INFINITY },		\
 	{ MAX_SIGPENDING, MAX_SIGPENDING },		\
diff -Nru a/include/asm-m68k/semaphore.h b/include/asm-m68k/semaphore.h
--- a/include/asm-m68k/semaphore.h	2004-10-18 14:57:04 -07:00
+++ b/include/asm-m68k/semaphore.h	2004-10-18 14:57:04 -07:00
@@ -27,21 +27,14 @@
 	atomic_t count;
 	atomic_t waking;
 	wait_queue_head_t wait;
-#ifdef WAITQUEUE_DEBUG
-	long __magic;
-#endif
 };
 
-#ifdef WAITQUEUE_DEBUG
-# define __SEM_DEBUG_INIT(name) \
-		, (long)&(name).__magic
-#else
-# define __SEM_DEBUG_INIT(name)
-#endif
-
-#define __SEMAPHORE_INITIALIZER(name,count) \
-{ ATOMIC_INIT(count), ATOMIC_INIT(0), __WAIT_QUEUE_HEAD_INITIALIZER((name).wait) \
-	__SEM_DEBUG_INIT(name) }
+#define __SEMAPHORE_INITIALIZER(name, n)				\
+{									\
+	.count		= ATOMIC_INIT(n),				\
+	.waking		= ATOMIC_INIT(0),				\
+	.wait		= __WAIT_QUEUE_HEAD_INITIALIZER((name).wait)	\
+}
 
 #define __MUTEX_INITIALIZER(name) \
 	__SEMAPHORE_INITIALIZER(name,1)
@@ -86,9 +79,6 @@
 {
 	register struct semaphore *sem1 __asm__ ("%a1") = sem;
 
-#ifdef WAITQUEUE_DEBUG
-	CHECK_MAGIC(sem->__magic);
-#endif
 	might_sleep();
 	__asm__ __volatile__(
 		"| atomic down operation\n\t"
@@ -109,9 +99,6 @@
 	register struct semaphore *sem1 __asm__ ("%a1") = sem;
 	register int result __asm__ ("%d0");
 
-#ifdef WAITQUEUE_DEBUG
-	CHECK_MAGIC(sem->__magic);
-#endif
 	might_sleep();
 	__asm__ __volatile__(
 		"| atomic interruptible down operation\n\t"
@@ -134,10 +121,6 @@
 	register struct semaphore *sem1 __asm__ ("%a1") = sem;
 	register int result __asm__ ("%d0");
 
-#ifdef WAITQUEUE_DEBUG
-	CHECK_MAGIC(sem->__magic);
-#endif
-
 	__asm__ __volatile__(
 		"| atomic down trylock operation\n\t"
 		"subql #1,%1@\n\t"
@@ -163,10 +146,6 @@
 static inline void up(struct semaphore *sem)
 {
 	register struct semaphore *sem1 __asm__ ("%a1") = sem;
-
-#ifdef WAITQUEUE_DEBUG
-	CHECK_MAGIC(sem->__magic);
-#endif
 
 	__asm__ __volatile__(
 		"| atomic up operation\n\t"
diff -Nru a/include/asm-m68k/socket.h b/include/asm-m68k/socket.h
--- a/include/asm-m68k/socket.h	2004-10-18 14:56:19 -07:00
+++ b/include/asm-m68k/socket.h	2004-10-18 14:56:19 -07:00
@@ -47,20 +47,4 @@
 
 #define SO_PEERSEC             31
 
-/* Nast libc5 fixup - bletch */
-#if defined(__KERNEL__)
-/* Socket types. */
-#define SOCK_STREAM	1		/* stream (connection) socket	*/
-#define SOCK_DGRAM	2		/* datagram (conn.less) socket	*/
-#define SOCK_RAW	3		/* raw socket			*/
-#define SOCK_RDM	4		/* reliably-delivered message	*/
-#define SOCK_SEQPACKET	5		/* sequential packet socket	*/
-#define SOCK_PACKET	10		/* linux specific way of	*/
-					/* getting packets at the dev	*/
-					/* level.  For writing rarp and	*/
-					/* other similar things on the	*/
-					/* user level.			*/
-#define	SOCK_MAX	(SOCK_PACKET+1)
-#endif
-
 #endif /* _ASM_SOCKET_H */
diff -Nru a/include/asm-m68k/system.h b/include/asm-m68k/system.h
--- a/include/asm-m68k/system.h	2004-10-18 14:56:48 -07:00
+++ b/include/asm-m68k/system.h	2004-10-18 14:56:48 -07:00
@@ -51,7 +51,7 @@
 #if 0
 #define local_irq_enable() asm volatile ("andiw %0,%%sr": : "i" (ALLOWINT) : "memory")
 #else
-#include <asm/hardirq.h>
+#include <linux/hardirq.h>
 #define local_irq_enable() ({							\
 	if (MACH_IS_Q40 || !hardirq_count())					\
 		asm volatile ("andiw %0,%%sr": : "i" (ALLOWINT) : "memory");	\
diff -Nru a/include/asm-m68k/uaccess.h b/include/asm-m68k/uaccess.h
--- a/include/asm-m68k/uaccess.h	2004-10-18 14:56:17 -07:00
+++ b/include/asm-m68k/uaccess.h	2004-10-18 14:56:17 -07:00
@@ -521,6 +521,9 @@
 	 : "0"(to), "1"(from), "2"(n/4)			\
 	 : "d0", "memory")
 
+#define __copy_to_user_inatomic __copy_to_user
+#define __copy_from_user_inatomic __copy_from_user
+
 static inline unsigned long
 __constant_copy_to_user(void *to, const void *from, unsigned long n)
 {
diff -Nru a/include/asm-m68knommu/bug.h b/include/asm-m68knommu/bug.h
--- a/include/asm-m68knommu/bug.h	2004-10-18 14:56:17 -07:00
+++ b/include/asm-m68knommu/bug.h	2004-10-18 14:56:17 -07:00
@@ -1,24 +1,4 @@
 #ifndef _M68KNOMMU_BUG_H
 #define _M68KNOMMU_BUG_H
-
-#define BUG() do { \
-  printk("%s(%d): kernel BUG!\n", __FILE__, __LINE__); \
-} while (0)
-
-#define BUG_ON(condition) do { \
-	if (unlikely((condition)!=0)) \
-		BUG(); \
-} while(0)
-
-#define PAGE_BUG(page) do { \
-         BUG(); \
-} while (0)
-
-#define WARN_ON(condition) do { \
-	if (unlikely((condition)!=0)) { \
-		printk("Badness in %s at %s:%d\n", __FUNCTION__, __FILE__, __LINE__); \
-		dump_stack(); \
-	} \
-} while (0)
-
+#include <asm-generic/bug.h>
 #endif
diff -Nru a/include/asm-m68knommu/hardirq.h b/include/asm-m68knommu/hardirq.h
--- a/include/asm-m68knommu/hardirq.h	2004-10-18 14:55:54 -07:00
+++ b/include/asm-m68knommu/hardirq.h	2004-10-18 14:55:54 -07:00
@@ -36,20 +36,6 @@
 #define SOFTIRQ_SHIFT	(PREEMPT_SHIFT + PREEMPT_BITS)
 #define HARDIRQ_SHIFT	(SOFTIRQ_SHIFT + SOFTIRQ_BITS)
 
-#define __MASK(x)	((1UL << (x))-1)
-
-#define PREEMPT_MASK	(__MASK(PREEMPT_BITS) << PREEMPT_SHIFT)
-#define HARDIRQ_MASK	(__MASK(HARDIRQ_BITS) << HARDIRQ_SHIFT)
-#define SOFTIRQ_MASK	(__MASK(SOFTIRQ_BITS) << SOFTIRQ_SHIFT)
-
-#define hardirq_count()	(preempt_count() & HARDIRQ_MASK)
-#define softirq_count()	(preempt_count() & SOFTIRQ_MASK)
-#define irq_count()	(preempt_count() & (HARDIRQ_MASK | SOFTIRQ_MASK))
-
-#define PREEMPT_OFFSET	(1UL << PREEMPT_SHIFT)
-#define SOFTIRQ_OFFSET	(1UL << SOFTIRQ_SHIFT)
-#define HARDIRQ_OFFSET	(1UL << HARDIRQ_SHIFT)
-
 /*
  * The hardirq mask has to be large enough to have
  * space for potentially all IRQ sources in the system
@@ -59,33 +45,7 @@
 # error HARDIRQ_BITS is too low!
 #endif
 
-/*
- * Are we doing bottom half or hardware interrupt processing?
- * Are we in a softirq context? Interrupt context?
- */
-#define in_irq()		(hardirq_count())
-#define in_softirq()		(softirq_count())
-#define in_interrupt()		(irq_count())
-
-#define hardirq_trylock()	(!in_interrupt())
-#define hardirq_endlock()	do { } while (0)
-
 #define irq_enter()		(preempt_count() += HARDIRQ_OFFSET)
-
-#ifdef CONFIG_PREEMPT
-# define IRQ_EXIT_OFFSET (HARDIRQ_OFFSET-1)
-#else
-# define IRQ_EXIT_OFFSET HARDIRQ_OFFSET
-#endif
-
-#ifdef CONFIG_PREEMPT
-# define in_atomic()	(preempt_count() != kernel_locked())
-# define IRQ_EXIT_OFFSET (HARDIRQ_OFFSET-1)
-#else
-# define in_atomic()	(preempt_count() != 0)
-# define IRQ_EXIT_OFFSET HARDIRQ_OFFSET
-#endif
-
 #define irq_exit()							\
 do {									\
 		preempt_count() -= IRQ_EXIT_OFFSET;			\
@@ -93,11 +53,5 @@
 			do_softirq();					\
 		preempt_enable_no_resched();				\
 } while (0)
-
-#ifndef CONFIG_SMP
-# define synchronize_irq(irq)	barrier()
-#else
-# error m68knommu SMP is not available
-#endif /* CONFIG_SMP */
 
 #endif /* __M68K_HARDIRQ_H */
diff -Nru a/include/asm-m68knommu/ptrace.h b/include/asm-m68knommu/ptrace.h
--- a/include/asm-m68knommu/ptrace.h	2004-10-18 14:55:54 -07:00
+++ b/include/asm-m68knommu/ptrace.h	2004-10-18 14:55:54 -07:00
@@ -84,6 +84,7 @@
 
 #define user_mode(regs) (!((regs)->sr & PS_S))
 #define instruction_pointer(regs) ((regs)->pc)
+#define profile_pc(regs) instruction_pointer(regs)
 extern void show_regs(struct pt_regs *);
 #endif /* __KERNEL__ */
 #endif /* __ASSEMBLY__ */
diff -Nru a/include/asm-m68knommu/semaphore.h b/include/asm-m68knommu/semaphore.h
--- a/include/asm-m68knommu/semaphore.h	2004-10-18 14:56:33 -07:00
+++ b/include/asm-m68knommu/semaphore.h	2004-10-18 14:56:33 -07:00
@@ -26,21 +26,14 @@
 	atomic_t count;
 	atomic_t waking;
 	wait_queue_head_t wait;
-#if WAITQUEUE_DEBUG
-	long __magic;
-#endif
 };
 
-#if WAITQUEUE_DEBUG
-# define __SEM_DEBUG_INIT(name) \
-		, (long)&(name).__magic
-#else
-# define __SEM_DEBUG_INIT(name)
-#endif
-
-#define __SEMAPHORE_INITIALIZER(name,count) \
-{ ATOMIC_INIT(count), ATOMIC_INIT(0), __WAIT_QUEUE_HEAD_INITIALIZER((name).wait) \
-	__SEM_DEBUG_INIT(name) }
+#define __SEMAPHORE_INITIALIZER(name, n)				\
+{									\
+	.count		= ATOMIC_INIT(n),				\
+	.waking		= ATOMIC_INIT(0),				\
+	.wait		= __WAIT_QUEUE_HEAD_INITIALIZER((name).wait)	\
+}
 
 #define __MUTEX_INITIALIZER(name) \
 	__SEMAPHORE_INITIALIZER(name,1)
@@ -85,9 +78,6 @@
  */
 extern inline void down(struct semaphore * sem)
 {
-#if WAITQUEUE_DEBUG
-	CHECK_MAGIC(sem->__magic);
-#endif
 	might_sleep();
 	__asm__ __volatile__(
 		"| atomic down operation\n\t"
@@ -105,9 +95,6 @@
 {
 	int ret;
 
-#if WAITQUEUE_DEBUG
-	CHECK_MAGIC(sem->__magic);
-#endif
 	might_sleep();
 	__asm__ __volatile__(
 		"| atomic down operation\n\t"
@@ -128,10 +115,6 @@
 	register struct semaphore *sem1 __asm__ ("%a1") = sem;
 	register int result __asm__ ("%d0");
 
-#if WAITQUEUE_DEBUG
-	CHECK_MAGIC(sem->__magic);
-#endif
-
 	__asm__ __volatile__(
 		"| atomic down trylock operation\n\t"
 		"subql #1,%1@\n\t"
@@ -157,10 +140,6 @@
  */
 extern inline void up(struct semaphore * sem)
 {
-#if WAITQUEUE_DEBUG
-	CHECK_MAGIC(sem->__magic);
-#endif
-
 	__asm__ __volatile__(
 		"| atomic up operation\n\t"
 		"movel	%0, %%a1\n\t"
diff -Nru a/include/asm-m68knommu/uaccess.h b/include/asm-m68knommu/uaccess.h
--- a/include/asm-m68knommu/uaccess.h	2004-10-18 14:56:48 -07:00
+++ b/include/asm-m68knommu/uaccess.h	2004-10-18 14:56:48 -07:00
@@ -134,6 +134,8 @@
 
 #define __copy_from_user(to, from, n) copy_from_user(to, from, n)
 #define __copy_to_user(to, from, n) copy_to_user(to, from, n)
+#define __copy_to_user_inatomic __copy_to_user
+#define __copy_from_user_inatomic __copy_from_user
 
 #define copy_to_user_ret(to,from,n,retval) ({ if (copy_to_user(to,from,n)) return retval; })
 
diff -Nru a/include/asm-mips/bug.h b/include/asm-mips/bug.h
--- a/include/asm-mips/bug.h	2004-10-18 14:56:48 -07:00
+++ b/include/asm-mips/bug.h	2004-10-18 14:56:48 -07:00
@@ -7,14 +7,8 @@
 do {									\
 	__asm__ __volatile__("break %0" : : "i" (BRK_BUG));		\
 } while (0)
-#define BUG_ON(condition) do { if (unlikely((condition)!=0)) BUG(); } while(0)
-#define PAGE_BUG(page) do {  BUG(); } while (0)
 
-#define WARN_ON(condition) do { \
-	if (unlikely((condition)!=0)) { \
-		printk("Badness in %s at %s:%d\n", __FUNCTION__, __FILE__, __LINE__); \
-	dump_stack(); \
-	} \
-} while (0)
+#define HAVE_ARCH_BUG
+#include <asm-generic/bug.h>
 
 #endif
diff -Nru a/include/asm-mips/dma-mapping.h b/include/asm-mips/dma-mapping.h
--- a/include/asm-mips/dma-mapping.h	2004-10-18 14:56:33 -07:00
+++ b/include/asm-mips/dma-mapping.h	2004-10-18 14:56:33 -07:00
@@ -1,7 +1,6 @@
 #ifndef _ASM_DMA_MAPPING_H
 #define _ASM_DMA_MAPPING_H
 
-#include <linux/device.h>
 #include <asm/scatterlist.h>
 #include <asm/cache.h>
 
diff -Nru a/include/asm-mips/hardirq.h b/include/asm-mips/hardirq.h
--- a/include/asm-mips/hardirq.h	2004-10-18 14:56:27 -07:00
+++ b/include/asm-mips/hardirq.h	2004-10-18 14:56:27 -07:00
@@ -43,20 +43,6 @@
 #define SOFTIRQ_SHIFT	(PREEMPT_SHIFT + PREEMPT_BITS)
 #define HARDIRQ_SHIFT	(SOFTIRQ_SHIFT + SOFTIRQ_BITS)
 
-#define __MASK(x)	((1UL << (x))-1)
-
-#define PREEMPT_MASK	(__MASK(PREEMPT_BITS) << PREEMPT_SHIFT)
-#define HARDIRQ_MASK	(__MASK(HARDIRQ_BITS) << HARDIRQ_SHIFT)
-#define SOFTIRQ_MASK	(__MASK(SOFTIRQ_BITS) << SOFTIRQ_SHIFT)
-
-#define hardirq_count()	(preempt_count() & HARDIRQ_MASK)
-#define softirq_count()	(preempt_count() & SOFTIRQ_MASK)
-#define irq_count()	(preempt_count() & (HARDIRQ_MASK | SOFTIRQ_MASK))
-
-#define PREEMPT_OFFSET	(1UL << PREEMPT_SHIFT)
-#define SOFTIRQ_OFFSET	(1UL << SOFTIRQ_SHIFT)
-#define HARDIRQ_OFFSET	(1UL << HARDIRQ_SHIFT)
-
 /*
  * The hardirq mask has to be large enough to have
  * space for potentially all IRQ sources in the system
@@ -66,27 +52,7 @@
 # error HARDIRQ_BITS is too low!
 #endif
 
-/*
- * Are we doing bottom half or hardware interrupt processing?
- * Are we in a softirq context? Interrupt context?
- */
-#define in_irq()		(hardirq_count())
-#define in_softirq()		(softirq_count())
-#define in_interrupt()		(irq_count())
-
-#define hardirq_trylock()	(!in_interrupt())
-#define hardirq_endlock()	do { } while (0)
-
 #define irq_enter()		(preempt_count() += HARDIRQ_OFFSET)
-
-#ifdef CONFIG_PREEMPT
-# include <linux/smp_lock.h>
-# define in_atomic()	((preempt_count() & ~PREEMPT_ACTIVE) != kernel_locked())
-# define IRQ_EXIT_OFFSET (HARDIRQ_OFFSET-1)
-#else
-# define in_atomic()	(preempt_count() != 0)
-# define IRQ_EXIT_OFFSET HARDIRQ_OFFSET
-#endif
 #define irq_exit()                                                     \
 do {                                                                   \
 	preempt_count() -= IRQ_EXIT_OFFSET;                     \
@@ -94,11 +60,5 @@
 		do_softirq();                                   \
 	preempt_enable_no_resched();                            \
 } while (0)
-
-#ifndef CONFIG_SMP
-# define synchronize_irq(irq)	barrier()
-#else
-  extern void synchronize_irq(unsigned int irq);
-#endif /* CONFIG_SMP */
 
 #endif /* _ASM_HARDIRQ_H */
diff -Nru a/include/asm-mips/mv64340.h b/include/asm-mips/mv64340.h
--- a/include/asm-mips/mv64340.h	2004-10-18 14:56:49 -07:00
+++ /dev/null	Wed Dec 31 16:00:00 196900
@@ -1,1039 +0,0 @@
-/*
- * mv64340.h - MV-64340 Internal registers definition file.
- *
- * Copyright 2002 Momentum Computer, Inc.
- * 	Author: Matthew Dharm <mdharm@momenco.com>
- * Copyright 2002 GALILEO TECHNOLOGY, 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.
- */
-#ifndef __ASM_MV64340_H
-#define __ASM_MV64340_H
-
-#include <asm/addrspace.h>
-#include <asm/marvell.h>
-
-/****************************************/
-/* Processor Address Space              */
-/****************************************/
-
-/* DDR SDRAM BAR and size registers */
-
-#define MV64340_CS_0_BASE_ADDR                                      0x008
-#define MV64340_CS_0_SIZE                                           0x010
-#define MV64340_CS_1_BASE_ADDR                                      0x208
-#define MV64340_CS_1_SIZE                                           0x210
-#define MV64340_CS_2_BASE_ADDR                                      0x018
-#define MV64340_CS_2_SIZE                                           0x020
-#define MV64340_CS_3_BASE_ADDR                                      0x218
-#define MV64340_CS_3_SIZE                                           0x220
-
-/* Devices BAR and size registers */
-
-#define MV64340_DEV_CS0_BASE_ADDR                                   0x028
-#define MV64340_DEV_CS0_SIZE                                        0x030
-#define MV64340_DEV_CS1_BASE_ADDR                                   0x228
-#define MV64340_DEV_CS1_SIZE                                        0x230
-#define MV64340_DEV_CS2_BASE_ADDR                                   0x248
-#define MV64340_DEV_CS2_SIZE                                        0x250
-#define MV64340_DEV_CS3_BASE_ADDR                                   0x038
-#define MV64340_DEV_CS3_SIZE                                        0x040
-#define MV64340_BOOTCS_BASE_ADDR                                    0x238
-#define MV64340_BOOTCS_SIZE                                         0x240
-
-/* PCI 0 BAR and size registers */
-
-#define MV64340_PCI_0_IO_BASE_ADDR                                  0x048
-#define MV64340_PCI_0_IO_SIZE                                       0x050
-#define MV64340_PCI_0_MEMORY0_BASE_ADDR                             0x058
-#define MV64340_PCI_0_MEMORY0_SIZE                                  0x060
-#define MV64340_PCI_0_MEMORY1_BASE_ADDR                             0x080
-#define MV64340_PCI_0_MEMORY1_SIZE                                  0x088
-#define MV64340_PCI_0_MEMORY2_BASE_ADDR                             0x258
-#define MV64340_PCI_0_MEMORY2_SIZE                                  0x260
-#define MV64340_PCI_0_MEMORY3_BASE_ADDR                             0x280
-#define MV64340_PCI_0_MEMORY3_SIZE                                  0x288
-
-/* PCI 1 BAR and size registers */
-#define MV64340_PCI_1_IO_BASE_ADDR                                  0x090
-#define MV64340_PCI_1_IO_SIZE                                       0x098
-#define MV64340_PCI_1_MEMORY0_BASE_ADDR                             0x0a0
-#define MV64340_PCI_1_MEMORY0_SIZE                                  0x0a8
-#define MV64340_PCI_1_MEMORY1_BASE_ADDR                             0x0b0
-#define MV64340_PCI_1_MEMORY1_SIZE                                  0x0b8
-#define MV64340_PCI_1_MEMORY2_BASE_ADDR                             0x2a0
-#define MV64340_PCI_1_MEMORY2_SIZE                                  0x2a8
-#define MV64340_PCI_1_MEMORY3_BASE_ADDR                             0x2b0
-#define MV64340_PCI_1_MEMORY3_SIZE                                  0x2b8
-
-/* SRAM base address */
-#define MV64340_INTEGRATED_SRAM_BASE_ADDR                           0x268
-
-/* internal registers space base address */
-#define MV64340_INTERNAL_SPACE_BASE_ADDR                            0x068
-
-/* Enables the CS , DEV_CS , PCI 0 and PCI 1 
-   windows above */
-#define MV64340_BASE_ADDR_ENABLE                                    0x278
-
-/****************************************/
-/* PCI remap registers                  */
-/****************************************/
-      /* PCI 0 */
-#define MV64340_PCI_0_IO_ADDR_REMAP                                 0x0f0
-#define MV64340_PCI_0_MEMORY0_LOW_ADDR_REMAP                        0x0f8
-#define MV64340_PCI_0_MEMORY0_HIGH_ADDR_REMAP                       0x320
-#define MV64340_PCI_0_MEMORY1_LOW_ADDR_REMAP                        0x100
-#define MV64340_PCI_0_MEMORY1_HIGH_ADDR_REMAP                       0x328
-#define MV64340_PCI_0_MEMORY2_LOW_ADDR_REMAP                        0x2f8
-#define MV64340_PCI_0_MEMORY2_HIGH_ADDR_REMAP                       0x330
-#define MV64340_PCI_0_MEMORY3_LOW_ADDR_REMAP                        0x300
-#define MV64340_PCI_0_MEMORY3_HIGH_ADDR_REMAP                       0x338
-      /* PCI 1 */
-#define MV64340_PCI_1_IO_ADDR_REMAP                                 0x108
-#define MV64340_PCI_1_MEMORY0_LOW_ADDR_REMAP                        0x110
-#define MV64340_PCI_1_MEMORY0_HIGH_ADDR_REMAP                       0x340
-#define MV64340_PCI_1_MEMORY1_LOW_ADDR_REMAP                        0x118
-#define MV64340_PCI_1_MEMORY1_HIGH_ADDR_REMAP                       0x348
-#define MV64340_PCI_1_MEMORY2_LOW_ADDR_REMAP                        0x310
-#define MV64340_PCI_1_MEMORY2_HIGH_ADDR_REMAP                       0x350
-#define MV64340_PCI_1_MEMORY3_LOW_ADDR_REMAP                        0x318
-#define MV64340_PCI_1_MEMORY3_HIGH_ADDR_REMAP                       0x358
- 
-#define MV64340_CPU_PCI_0_HEADERS_RETARGET_CONTROL                  0x3b0
-#define MV64340_CPU_PCI_0_HEADERS_RETARGET_BASE                     0x3b8
-#define MV64340_CPU_PCI_1_HEADERS_RETARGET_CONTROL                  0x3c0
-#define MV64340_CPU_PCI_1_HEADERS_RETARGET_BASE                     0x3c8
-#define MV64340_CPU_GE_HEADERS_RETARGET_CONTROL                     0x3d0
-#define MV64340_CPU_GE_HEADERS_RETARGET_BASE                        0x3d8
-#define MV64340_CPU_IDMA_HEADERS_RETARGET_CONTROL                   0x3e0
-#define MV64340_CPU_IDMA_HEADERS_RETARGET_BASE                      0x3e8
-
-/****************************************/
-/*         CPU Control Registers        */
-/****************************************/
-
-#define MV64340_CPU_CONFIG                                          0x000
-#define MV64340_CPU_MODE                                            0x120
-#define MV64340_CPU_MASTER_CONTROL                                  0x160
-#define MV64340_CPU_CROSS_BAR_CONTROL_LOW                           0x150
-#define MV64340_CPU_CROSS_BAR_CONTROL_HIGH                          0x158
-#define MV64340_CPU_CROSS_BAR_TIMEOUT                               0x168
-
-/****************************************/
-/* SMP RegisterS                        */
-/****************************************/
-
-#define MV64340_SMP_WHO_AM_I                                        0x200
-#define MV64340_SMP_CPU0_DOORBELL                                   0x214
-#define MV64340_SMP_CPU0_DOORBELL_CLEAR                             0x21C
-#define MV64340_SMP_CPU1_DOORBELL                                   0x224
-#define MV64340_SMP_CPU1_DOORBELL_CLEAR                             0x22C
-#define MV64340_SMP_CPU0_DOORBELL_MASK                              0x234
-#define MV64340_SMP_CPU1_DOORBELL_MASK                              0x23C
-#define MV64340_SMP_SEMAPHOR0                                       0x244
-#define MV64340_SMP_SEMAPHOR1                                       0x24c
-#define MV64340_SMP_SEMAPHOR2                                       0x254
-#define MV64340_SMP_SEMAPHOR3                                       0x25c
-#define MV64340_SMP_SEMAPHOR4                                       0x264
-#define MV64340_SMP_SEMAPHOR5                                       0x26c
-#define MV64340_SMP_SEMAPHOR6                                       0x274
-#define MV64340_SMP_SEMAPHOR7                                       0x27c
-
-/****************************************/
-/*  CPU Sync Barrier Register           */
-/****************************************/
-
-#define MV64340_CPU_0_SYNC_BARRIER_TRIGGER                          0x0c0
-#define MV64340_CPU_0_SYNC_BARRIER_VIRTUAL                          0x0c8
-#define MV64340_CPU_1_SYNC_BARRIER_TRIGGER                          0x0d0
-#define MV64340_CPU_1_SYNC_BARRIER_VIRTUAL                          0x0d8
-
-/****************************************/
-/* CPU Access Protect                   */
-/****************************************/
-
-#define MV64340_CPU_PROTECT_WINDOW_0_BASE_ADDR                      0x180
-#define MV64340_CPU_PROTECT_WINDOW_0_SIZE                           0x188
-#define MV64340_CPU_PROTECT_WINDOW_1_BASE_ADDR                      0x190
-#define MV64340_CPU_PROTECT_WINDOW_1_SIZE                           0x198
-#define MV64340_CPU_PROTECT_WINDOW_2_BASE_ADDR                      0x1a0
-#define MV64340_CPU_PROTECT_WINDOW_2_SIZE                           0x1a8
-#define MV64340_CPU_PROTECT_WINDOW_3_BASE_ADDR                      0x1b0
-#define MV64340_CPU_PROTECT_WINDOW_3_SIZE                           0x1b8
-
-
-/****************************************/
-/*          CPU Error Report            */
-/****************************************/
-
-#define MV64340_CPU_ERROR_ADDR_LOW                                  0x070
-#define MV64340_CPU_ERROR_ADDR_HIGH                                 0x078
-#define MV64340_CPU_ERROR_DATA_LOW                                  0x128
-#define MV64340_CPU_ERROR_DATA_HIGH                                 0x130
-#define MV64340_CPU_ERROR_PARITY                                    0x138
-#define MV64340_CPU_ERROR_CAUSE                                     0x140
-#define MV64340_CPU_ERROR_MASK                                      0x148
-
-/****************************************/
-/*      CPU Interface Debug Registers 	*/
-/****************************************/
-
-#define MV64340_PUNIT_SLAVE_DEBUG_LOW                               0x360
-#define MV64340_PUNIT_SLAVE_DEBUG_HIGH                              0x368
-#define MV64340_PUNIT_MASTER_DEBUG_LOW                              0x370
-#define MV64340_PUNIT_MASTER_DEBUG_HIGH                             0x378
-#define MV64340_PUNIT_MMASK                                         0x3e4
-
-/****************************************/
-/*  Integrated SRAM Registers           */
-/****************************************/
-
-#define MV64340_SRAM_CONFIG                                         0x380
-#define MV64340_SRAM_TEST_MODE                                      0X3F4
-#define MV64340_SRAM_ERROR_CAUSE                                    0x388
-#define MV64340_SRAM_ERROR_ADDR                                     0x390
-#define MV64340_SRAM_ERROR_ADDR_HIGH                                0X3F8
-#define MV64340_SRAM_ERROR_DATA_LOW                                 0x398
-#define MV64340_SRAM_ERROR_DATA_HIGH                                0x3a0
-#define MV64340_SRAM_ERROR_DATA_PARITY                              0x3a8
-
-/****************************************/
-/* SDRAM Configuration                  */
-/****************************************/
-
-#define MV64340_SDRAM_CONFIG                                        0x1400
-#define MV64340_D_UNIT_CONTROL_LOW                                  0x1404
-#define MV64340_D_UNIT_CONTROL_HIGH                                 0x1424
-#define MV64340_SDRAM_TIMING_CONTROL_LOW                            0x1408
-#define MV64340_SDRAM_TIMING_CONTROL_HIGH                           0x140c
-#define MV64340_SDRAM_ADDR_CONTROL                                  0x1410
-#define MV64340_SDRAM_OPEN_PAGES_CONTROL                            0x1414
-#define MV64340_SDRAM_OPERATION                                     0x1418
-#define MV64340_SDRAM_MODE                                          0x141c
-#define MV64340_EXTENDED_DRAM_MODE                                  0x1420
-#define MV64340_SDRAM_CROSS_BAR_CONTROL_LOW                         0x1430
-#define MV64340_SDRAM_CROSS_BAR_CONTROL_HIGH                        0x1434
-#define MV64340_SDRAM_CROSS_BAR_TIMEOUT                             0x1438
-#define MV64340_SDRAM_ADDR_CTRL_PADS_CALIBRATION                    0x14c0
-#define MV64340_SDRAM_DATA_PADS_CALIBRATION                         0x14c4
-
-/****************************************/
-/* SDRAM Error Report                   */
-/****************************************/
-
-#define MV64340_SDRAM_ERROR_DATA_LOW                                0x1444
-#define MV64340_SDRAM_ERROR_DATA_HIGH                               0x1440
-#define MV64340_SDRAM_ERROR_ADDR                                    0x1450
-#define MV64340_SDRAM_RECEIVED_ECC                                  0x1448
-#define MV64340_SDRAM_CALCULATED_ECC                                0x144c
-#define MV64340_SDRAM_ECC_CONTROL                                   0x1454
-#define MV64340_SDRAM_ECC_ERROR_COUNTER                             0x1458
-
-/******************************************/
-/*  Controlled Delay Line (CDL) Registers */
-/******************************************/
-
-#define MV64340_DFCDL_CONFIG0                                       0x1480
-#define MV64340_DFCDL_CONFIG1                                       0x1484
-#define MV64340_DLL_WRITE                                           0x1488
-#define MV64340_DLL_READ                                            0x148c
-#define MV64340_SRAM_ADDR                                           0x1490
-#define MV64340_SRAM_DATA0                                          0x1494
-#define MV64340_SRAM_DATA1                                          0x1498
-#define MV64340_SRAM_DATA2                                          0x149c
-#define MV64340_DFCL_PROBE                                          0x14a0
-
-/******************************************/
-/*   Debug Registers                      */
-/******************************************/
-
-#define MV64340_DUNIT_DEBUG_LOW                                     0x1460
-#define MV64340_DUNIT_DEBUG_HIGH                                    0x1464
-#define MV64340_DUNIT_MMASK                                         0X1b40
-
-/****************************************/
-/* Device Parameters			*/
-/****************************************/
-
-#define MV64340_DEVICE_BANK0_PARAMETERS				    0x45c
-#define MV64340_DEVICE_BANK1_PARAMETERS				    0x460
-#define MV64340_DEVICE_BANK2_PARAMETERS				    0x464
-#define MV64340_DEVICE_BANK3_PARAMETERS				    0x468
-#define MV64340_DEVICE_BOOT_BANK_PARAMETERS			    0x46c
-#define MV64340_DEVICE_INTERFACE_CONTROL                            0x4c0
-#define MV64340_DEVICE_INTERFACE_CROSS_BAR_CONTROL_LOW              0x4c8
-#define MV64340_DEVICE_INTERFACE_CROSS_BAR_CONTROL_HIGH             0x4cc
-#define MV64340_DEVICE_INTERFACE_CROSS_BAR_TIMEOUT                  0x4c4
-
-/****************************************/
-/* Device interrupt registers		*/
-/****************************************/
-
-#define MV64340_DEVICE_INTERRUPT_CAUSE				    0x4d0
-#define MV64340_DEVICE_INTERRUPT_MASK				    0x4d4
-#define MV64340_DEVICE_ERROR_ADDR				    0x4d8
-#define MV64340_DEVICE_ERROR_DATA   				    0x4dc
-#define MV64340_DEVICE_ERROR_PARITY     			    0x4e0
-
-/****************************************/
-/* Device debug registers   		*/
-/****************************************/
-
-#define MV64340_DEVICE_DEBUG_LOW     				    0x4e4
-#define MV64340_DEVICE_DEBUG_HIGH     				    0x4e8
-#define MV64340_RUNIT_MMASK                                         0x4f0
-
-/****************************************/
-/* PCI Slave Address Decoding registers */
-/****************************************/
-
-#define MV64340_PCI_0_CS_0_BANK_SIZE                                0xc08
-#define MV64340_PCI_1_CS_0_BANK_SIZE                                0xc88
-#define MV64340_PCI_0_CS_1_BANK_SIZE                                0xd08
-#define MV64340_PCI_1_CS_1_BANK_SIZE                                0xd88
-#define MV64340_PCI_0_CS_2_BANK_SIZE                                0xc0c
-#define MV64340_PCI_1_CS_2_BANK_SIZE                                0xc8c
-#define MV64340_PCI_0_CS_3_BANK_SIZE                                0xd0c
-#define MV64340_PCI_1_CS_3_BANK_SIZE                                0xd8c
-#define MV64340_PCI_0_DEVCS_0_BANK_SIZE                             0xc10
-#define MV64340_PCI_1_DEVCS_0_BANK_SIZE                             0xc90
-#define MV64340_PCI_0_DEVCS_1_BANK_SIZE                             0xd10
-#define MV64340_PCI_1_DEVCS_1_BANK_SIZE                             0xd90
-#define MV64340_PCI_0_DEVCS_2_BANK_SIZE                             0xd18
-#define MV64340_PCI_1_DEVCS_2_BANK_SIZE                             0xd98
-#define MV64340_PCI_0_DEVCS_3_BANK_SIZE                             0xc14
-#define MV64340_PCI_1_DEVCS_3_BANK_SIZE                             0xc94
-#define MV64340_PCI_0_DEVCS_BOOT_BANK_SIZE                          0xd14
-#define MV64340_PCI_1_DEVCS_BOOT_BANK_SIZE                          0xd94
-#define MV64340_PCI_0_P2P_MEM0_BAR_SIZE                             0xd1c
-#define MV64340_PCI_1_P2P_MEM0_BAR_SIZE                             0xd9c
-#define MV64340_PCI_0_P2P_MEM1_BAR_SIZE                             0xd20
-#define MV64340_PCI_1_P2P_MEM1_BAR_SIZE                             0xda0
-#define MV64340_PCI_0_P2P_I_O_BAR_SIZE                              0xd24
-#define MV64340_PCI_1_P2P_I_O_BAR_SIZE                              0xda4
-#define MV64340_PCI_0_CPU_BAR_SIZE                                  0xd28
-#define MV64340_PCI_1_CPU_BAR_SIZE                                  0xda8
-#define MV64340_PCI_0_INTERNAL_SRAM_BAR_SIZE                        0xe00
-#define MV64340_PCI_1_INTERNAL_SRAM_BAR_SIZE                        0xe80
-#define MV64340_PCI_0_EXPANSION_ROM_BAR_SIZE                        0xd2c
-#define MV64340_PCI_1_EXPANSION_ROM_BAR_SIZE                        0xd9c
-#define MV64340_PCI_0_BASE_ADDR_REG_ENABLE                          0xc3c
-#define MV64340_PCI_1_BASE_ADDR_REG_ENABLE                          0xcbc
-#define MV64340_PCI_0_CS_0_BASE_ADDR_REMAP			    0xc48
-#define MV64340_PCI_1_CS_0_BASE_ADDR_REMAP			    0xcc8
-#define MV64340_PCI_0_CS_1_BASE_ADDR_REMAP			    0xd48
-#define MV64340_PCI_1_CS_1_BASE_ADDR_REMAP			    0xdc8
-#define MV64340_PCI_0_CS_2_BASE_ADDR_REMAP			    0xc4c
-#define MV64340_PCI_1_CS_2_BASE_ADDR_REMAP			    0xccc
-#define MV64340_PCI_0_CS_3_BASE_ADDR_REMAP			    0xd4c
-#define MV64340_PCI_1_CS_3_BASE_ADDR_REMAP			    0xdcc
-#define MV64340_PCI_0_CS_0_BASE_HIGH_ADDR_REMAP			    0xF04
-#define MV64340_PCI_1_CS_0_BASE_HIGH_ADDR_REMAP			    0xF84
-#define MV64340_PCI_0_CS_1_BASE_HIGH_ADDR_REMAP			    0xF08
-#define MV64340_PCI_1_CS_1_BASE_HIGH_ADDR_REMAP			    0xF88
-#define MV64340_PCI_0_CS_2_BASE_HIGH_ADDR_REMAP			    0xF0C
-#define MV64340_PCI_1_CS_2_BASE_HIGH_ADDR_REMAP			    0xF8C
-#define MV64340_PCI_0_CS_3_BASE_HIGH_ADDR_REMAP			    0xF10
-#define MV64340_PCI_1_CS_3_BASE_HIGH_ADDR_REMAP			    0xF90
-#define MV64340_PCI_0_DEVCS_0_BASE_ADDR_REMAP			    0xc50
-#define MV64340_PCI_1_DEVCS_0_BASE_ADDR_REMAP			    0xcd0
-#define MV64340_PCI_0_DEVCS_1_BASE_ADDR_REMAP			    0xd50
-#define MV64340_PCI_1_DEVCS_1_BASE_ADDR_REMAP			    0xdd0
-#define MV64340_PCI_0_DEVCS_2_BASE_ADDR_REMAP			    0xd58
-#define MV64340_PCI_1_DEVCS_2_BASE_ADDR_REMAP			    0xdd8
-#define MV64340_PCI_0_DEVCS_3_BASE_ADDR_REMAP           	    0xc54
-#define MV64340_PCI_1_DEVCS_3_BASE_ADDR_REMAP           	    0xcd4
-#define MV64340_PCI_0_DEVCS_BOOTCS_BASE_ADDR_REMAP      	    0xd54
-#define MV64340_PCI_1_DEVCS_BOOTCS_BASE_ADDR_REMAP      	    0xdd4
-#define MV64340_PCI_0_P2P_MEM0_BASE_ADDR_REMAP_LOW                  0xd5c
-#define MV64340_PCI_1_P2P_MEM0_BASE_ADDR_REMAP_LOW                  0xddc
-#define MV64340_PCI_0_P2P_MEM0_BASE_ADDR_REMAP_HIGH                 0xd60
-#define MV64340_PCI_1_P2P_MEM0_BASE_ADDR_REMAP_HIGH                 0xde0
-#define MV64340_PCI_0_P2P_MEM1_BASE_ADDR_REMAP_LOW                  0xd64
-#define MV64340_PCI_1_P2P_MEM1_BASE_ADDR_REMAP_LOW                  0xde4
-#define MV64340_PCI_0_P2P_MEM1_BASE_ADDR_REMAP_HIGH                 0xd68
-#define MV64340_PCI_1_P2P_MEM1_BASE_ADDR_REMAP_HIGH                 0xde8
-#define MV64340_PCI_0_P2P_I_O_BASE_ADDR_REMAP                       0xd6c
-#define MV64340_PCI_1_P2P_I_O_BASE_ADDR_REMAP                       0xdec 
-#define MV64340_PCI_0_CPU_BASE_ADDR_REMAP_LOW                       0xd70
-#define MV64340_PCI_1_CPU_BASE_ADDR_REMAP_LOW                       0xdf0
-#define MV64340_PCI_0_CPU_BASE_ADDR_REMAP_HIGH                      0xd74
-#define MV64340_PCI_1_CPU_BASE_ADDR_REMAP_HIGH                      0xdf4
-#define MV64340_PCI_0_INTEGRATED_SRAM_BASE_ADDR_REMAP               0xf00
-#define MV64340_PCI_1_INTEGRATED_SRAM_BASE_ADDR_REMAP               0xf80
-#define MV64340_PCI_0_EXPANSION_ROM_BASE_ADDR_REMAP                 0xf38
-#define MV64340_PCI_1_EXPANSION_ROM_BASE_ADDR_REMAP                 0xfb8
-#define MV64340_PCI_0_ADDR_DECODE_CONTROL                           0xd3c
-#define MV64340_PCI_1_ADDR_DECODE_CONTROL                           0xdbc
-#define MV64340_PCI_0_HEADERS_RETARGET_CONTROL                      0xF40
-#define MV64340_PCI_1_HEADERS_RETARGET_CONTROL                      0xFc0
-#define MV64340_PCI_0_HEADERS_RETARGET_BASE                         0xF44
-#define MV64340_PCI_1_HEADERS_RETARGET_BASE                         0xFc4
-#define MV64340_PCI_0_HEADERS_RETARGET_HIGH                         0xF48
-#define MV64340_PCI_1_HEADERS_RETARGET_HIGH                         0xFc8
-
-/***********************************/
-/*   PCI Control Register Map      */
-/***********************************/
-
-#define MV64340_PCI_0_DLL_STATUS_AND_COMMAND                        0x1d20
-#define MV64340_PCI_1_DLL_STATUS_AND_COMMAND                        0x1da0
-#define MV64340_PCI_0_MPP_PADS_DRIVE_CONTROL                        0x1d1C
-#define MV64340_PCI_1_MPP_PADS_DRIVE_CONTROL                        0x1d9C
-#define MV64340_PCI_0_COMMAND			         	    0xc00
-#define MV64340_PCI_1_COMMAND					    0xc80
-#define MV64340_PCI_0_MODE                                          0xd00
-#define MV64340_PCI_1_MODE                                          0xd80
-#define MV64340_PCI_0_RETRY	        	 		    0xc04
-#define MV64340_PCI_1_RETRY				            0xc84
-#define MV64340_PCI_0_READ_BUFFER_DISCARD_TIMER                     0xd04
-#define MV64340_PCI_1_READ_BUFFER_DISCARD_TIMER                     0xd84
-#define MV64340_PCI_0_MSI_TRIGGER_TIMER                             0xc38
-#define MV64340_PCI_1_MSI_TRIGGER_TIMER                             0xcb8
-#define MV64340_PCI_0_ARBITER_CONTROL                               0x1d00
-#define MV64340_PCI_1_ARBITER_CONTROL                               0x1d80
-#define MV64340_PCI_0_CROSS_BAR_CONTROL_LOW                         0x1d08
-#define MV64340_PCI_1_CROSS_BAR_CONTROL_LOW                         0x1d88
-#define MV64340_PCI_0_CROSS_BAR_CONTROL_HIGH                        0x1d0c
-#define MV64340_PCI_1_CROSS_BAR_CONTROL_HIGH                        0x1d8c
-#define MV64340_PCI_0_CROSS_BAR_TIMEOUT                             0x1d04
-#define MV64340_PCI_1_CROSS_BAR_TIMEOUT                             0x1d84
-#define MV64340_PCI_0_SYNC_BARRIER_TRIGGER_REG                      0x1D18
-#define MV64340_PCI_1_SYNC_BARRIER_TRIGGER_REG                      0x1D98
-#define MV64340_PCI_0_SYNC_BARRIER_VIRTUAL_REG                      0x1d10
-#define MV64340_PCI_1_SYNC_BARRIER_VIRTUAL_REG                      0x1d90
-#define MV64340_PCI_0_P2P_CONFIG                                    0x1d14
-#define MV64340_PCI_1_P2P_CONFIG                                    0x1d94
-
-#define MV64340_PCI_0_ACCESS_CONTROL_BASE_0_LOW                     0x1e00
-#define MV64340_PCI_0_ACCESS_CONTROL_BASE_0_HIGH                    0x1e04
-#define MV64340_PCI_0_ACCESS_CONTROL_SIZE_0                         0x1e08
-#define MV64340_PCI_0_ACCESS_CONTROL_BASE_1_LOW                     0x1e10
-#define MV64340_PCI_0_ACCESS_CONTROL_BASE_1_HIGH                    0x1e14
-#define MV64340_PCI_0_ACCESS_CONTROL_SIZE_1                         0x1e18
-#define MV64340_PCI_0_ACCESS_CONTROL_BASE_2_LOW                     0x1e20
-#define MV64340_PCI_0_ACCESS_CONTROL_BASE_2_HIGH                    0x1e24
-#define MV64340_PCI_0_ACCESS_CONTROL_SIZE_2                         0x1e28
-#define MV64340_PCI_0_ACCESS_CONTROL_BASE_3_LOW                     0x1e30
-#define MV64340_PCI_0_ACCESS_CONTROL_BASE_3_HIGH                    0x1e34
-#define MV64340_PCI_0_ACCESS_CONTROL_SIZE_3                         0x1e38
-#define MV64340_PCI_0_ACCESS_CONTROL_BASE_4_LOW                     0x1e40
-#define MV64340_PCI_0_ACCESS_CONTROL_BASE_4_HIGH                    0x1e44
-#define MV64340_PCI_0_ACCESS_CONTROL_SIZE_4                         0x1e48
-#define MV64340_PCI_0_ACCESS_CONTROL_BASE_5_LOW                     0x1e50
-#define MV64340_PCI_0_ACCESS_CONTROL_BASE_5_HIGH                    0x1e54
-#define MV64340_PCI_0_ACCESS_CONTROL_SIZE_5                         0x1e58
-
-#define MV64340_PCI_1_ACCESS_CONTROL_BASE_0_LOW                     0x1e80
-#define MV64340_PCI_1_ACCESS_CONTROL_BASE_0_HIGH                    0x1e84
-#define MV64340_PCI_1_ACCESS_CONTROL_SIZE_0                         0x1e88
-#define MV64340_PCI_1_ACCESS_CONTROL_BASE_1_LOW                     0x1e90
-#define MV64340_PCI_1_ACCESS_CONTROL_BASE_1_HIGH                    0x1e94
-#define MV64340_PCI_1_ACCESS_CONTROL_SIZE_1                         0x1e98
-#define MV64340_PCI_1_ACCESS_CONTROL_BASE_2_LOW                     0x1ea0
-#define MV64340_PCI_1_ACCESS_CONTROL_BASE_2_HIGH                    0x1ea4
-#define MV64340_PCI_1_ACCESS_CONTROL_SIZE_2                         0x1ea8
-#define MV64340_PCI_1_ACCESS_CONTROL_BASE_3_LOW                     0x1eb0
-#define MV64340_PCI_1_ACCESS_CONTROL_BASE_3_HIGH                    0x1eb4
-#define MV64340_PCI_1_ACCESS_CONTROL_SIZE_3                         0x1eb8
-#define MV64340_PCI_1_ACCESS_CONTROL_BASE_4_LOW                     0x1ec0
-#define MV64340_PCI_1_ACCESS_CONTROL_BASE_4_HIGH                    0x1ec4
-#define MV64340_PCI_1_ACCESS_CONTROL_SIZE_4                         0x1ec8
-#define MV64340_PCI_1_ACCESS_CONTROL_BASE_5_LOW                     0x1ed0
-#define MV64340_PCI_1_ACCESS_CONTROL_BASE_5_HIGH                    0x1ed4
-#define MV64340_PCI_1_ACCESS_CONTROL_SIZE_5                         0x1ed8
-
-/****************************************/
-/*   PCI Configuration Access Registers */
-/****************************************/
-
-#define MV64340_PCI_0_CONFIG_ADDR 				    0xcf8
-#define MV64340_PCI_0_CONFIG_DATA_VIRTUAL_REG                       0xcfc
-#define MV64340_PCI_1_CONFIG_ADDR 				    0xc78
-#define MV64340_PCI_1_CONFIG_DATA_VIRTUAL_REG                       0xc7c
-#define MV64340_PCI_0_INTERRUPT_ACKNOWLEDGE_VIRTUAL_REG	            0xc34
-#define MV64340_PCI_1_INTERRUPT_ACKNOWLEDGE_VIRTUAL_REG	            0xcb4
-
-/****************************************/
-/*   PCI Error Report Registers         */
-/****************************************/
-
-#define MV64340_PCI_0_SERR_MASK					    0xc28
-#define MV64340_PCI_1_SERR_MASK					    0xca8
-#define MV64340_PCI_0_ERROR_ADDR_LOW                                0x1d40
-#define MV64340_PCI_1_ERROR_ADDR_LOW                                0x1dc0
-#define MV64340_PCI_0_ERROR_ADDR_HIGH                               0x1d44
-#define MV64340_PCI_1_ERROR_ADDR_HIGH                               0x1dc4
-#define MV64340_PCI_0_ERROR_ATTRIBUTE                               0x1d48
-#define MV64340_PCI_1_ERROR_ATTRIBUTE                               0x1dc8
-#define MV64340_PCI_0_ERROR_COMMAND                                 0x1d50
-#define MV64340_PCI_1_ERROR_COMMAND                                 0x1dd0
-#define MV64340_PCI_0_ERROR_CAUSE                                   0x1d58
-#define MV64340_PCI_1_ERROR_CAUSE                                   0x1dd8
-#define MV64340_PCI_0_ERROR_MASK                                    0x1d5c
-#define MV64340_PCI_1_ERROR_MASK                                    0x1ddc
-
-/****************************************/
-/*   PCI Debug Registers                */
-/****************************************/
-
-#define MV64340_PCI_0_MMASK                                         0X1D24
-#define MV64340_PCI_1_MMASK                                         0X1DA4
-
-/*********************************************/
-/* PCI Configuration, Function 0, Registers  */
-/*********************************************/
-
-#define MV64340_PCI_DEVICE_AND_VENDOR_ID 			    0x000
-#define MV64340_PCI_STATUS_AND_COMMAND				    0x004
-#define MV64340_PCI_CLASS_CODE_AND_REVISION_ID			    0x008
-#define MV64340_PCI_BIST_HEADER_TYPE_LATENCY_TIMER_CACHE_LINE 	    0x00C
-
-#define MV64340_PCI_SCS_0_BASE_ADDR_LOW   	      		    0x010
-#define MV64340_PCI_SCS_0_BASE_ADDR_HIGH   		            0x014
-#define MV64340_PCI_SCS_1_BASE_ADDR_LOW  	     	            0x018
-#define MV64340_PCI_SCS_1_BASE_ADDR_HIGH 		            0x01C
-#define MV64340_PCI_INTERNAL_REG_MEM_MAPPED_BASE_ADDR_LOW      	    0x020
-#define MV64340_PCI_INTERNAL_REG_MEM_MAPPED_BASE_ADDR_HIGH     	    0x024
-#define MV64340_PCI_SUBSYSTEM_ID_AND_SUBSYSTEM_VENDOR_ID	    0x02c
-#define MV64340_PCI_EXPANSION_ROM_BASE_ADDR_REG	                    0x030
-#define MV64340_PCI_CAPABILTY_LIST_POINTER                          0x034
-#define MV64340_PCI_INTERRUPT_PIN_AND_LINE 			    0x03C
-       /* capability list */
-#define MV64340_PCI_POWER_MANAGEMENT_CAPABILITY                     0x040
-#define MV64340_PCI_POWER_MANAGEMENT_STATUS_AND_CONTROL             0x044
-#define MV64340_PCI_VPD_ADDR                                        0x048
-#define MV64340_PCI_VPD_DATA                                        0x04c
-#define MV64340_PCI_MSI_MESSAGE_CONTROL                             0x050
-#define MV64340_PCI_MSI_MESSAGE_ADDR                                0x054
-#define MV64340_PCI_MSI_MESSAGE_UPPER_ADDR                          0x058
-#define MV64340_PCI_MSI_MESSAGE_DATA                                0x05c
-#define MV64340_PCI_X_COMMAND                                       0x060
-#define MV64340_PCI_X_STATUS                                        0x064
-#define MV64340_PCI_COMPACT_PCI_HOT_SWAP                            0x068
-
-/***********************************************/
-/*   PCI Configuration, Function 1, Registers  */
-/***********************************************/
-
-#define MV64340_PCI_SCS_2_BASE_ADDR_LOW   			    0x110
-#define MV64340_PCI_SCS_2_BASE_ADDR_HIGH			    0x114
-#define MV64340_PCI_SCS_3_BASE_ADDR_LOW 			    0x118
-#define MV64340_PCI_SCS_3_BASE_ADDR_HIGH			    0x11c
-#define MV64340_PCI_INTERNAL_SRAM_BASE_ADDR_LOW          	    0x120
-#define MV64340_PCI_INTERNAL_SRAM_BASE_ADDR_HIGH         	    0x124
-
-/***********************************************/
-/*  PCI Configuration, Function 2, Registers   */
-/***********************************************/
-
-#define MV64340_PCI_DEVCS_0_BASE_ADDR_LOW	    		    0x210
-#define MV64340_PCI_DEVCS_0_BASE_ADDR_HIGH 			    0x214
-#define MV64340_PCI_DEVCS_1_BASE_ADDR_LOW 			    0x218
-#define MV64340_PCI_DEVCS_1_BASE_ADDR_HIGH      		    0x21c
-#define MV64340_PCI_DEVCS_2_BASE_ADDR_LOW 			    0x220
-#define MV64340_PCI_DEVCS_2_BASE_ADDR_HIGH      		    0x224
-
-/***********************************************/
-/*  PCI Configuration, Function 3, Registers   */
-/***********************************************/
-
-#define MV64340_PCI_DEVCS_3_BASE_ADDR_LOW	    		    0x310
-#define MV64340_PCI_DEVCS_3_BASE_ADDR_HIGH 			    0x314
-#define MV64340_PCI_BOOT_CS_BASE_ADDR_LOW			    0x318
-#define MV64340_PCI_BOOT_CS_BASE_ADDR_HIGH      		    0x31c
-#define MV64340_PCI_CPU_BASE_ADDR_LOW 				    0x220
-#define MV64340_PCI_CPU_BASE_ADDR_HIGH      			    0x224
-
-/***********************************************/
-/*  PCI Configuration, Function 4, Registers   */
-/***********************************************/
-
-#define MV64340_PCI_P2P_MEM0_BASE_ADDR_LOW  			    0x410
-#define MV64340_PCI_P2P_MEM0_BASE_ADDR_HIGH 			    0x414
-#define MV64340_PCI_P2P_MEM1_BASE_ADDR_LOW   			    0x418
-#define MV64340_PCI_P2P_MEM1_BASE_ADDR_HIGH 			    0x41c
-#define MV64340_PCI_P2P_I_O_BASE_ADDR                 	            0x420
-#define MV64340_PCI_INTERNAL_REGS_I_O_MAPPED_BASE_ADDR              0x424
-
-/****************************************/
-/* Messaging Unit Registers (I20)   	*/
-/****************************************/
-
-#define MV64340_I2O_INBOUND_MESSAGE_REG0_PCI_0_SIDE		    0x010
-#define MV64340_I2O_INBOUND_MESSAGE_REG1_PCI_0_SIDE  		    0x014
-#define MV64340_I2O_OUTBOUND_MESSAGE_REG0_PCI_0_SIDE 		    0x018
-#define MV64340_I2O_OUTBOUND_MESSAGE_REG1_PCI_0_SIDE  		    0x01C
-#define MV64340_I2O_INBOUND_DOORBELL_REG_PCI_0_SIDE  		    0x020
-#define MV64340_I2O_INBOUND_INTERRUPT_CAUSE_REG_PCI_0_SIDE          0x024
-#define MV64340_I2O_INBOUND_INTERRUPT_MASK_REG_PCI_0_SIDE	    0x028
-#define MV64340_I2O_OUTBOUND_DOORBELL_REG_PCI_0_SIDE 		    0x02C
-#define MV64340_I2O_OUTBOUND_INTERRUPT_CAUSE_REG_PCI_0_SIDE         0x030
-#define MV64340_I2O_OUTBOUND_INTERRUPT_MASK_REG_PCI_0_SIDE          0x034
-#define MV64340_I2O_INBOUND_QUEUE_PORT_VIRTUAL_REG_PCI_0_SIDE       0x040
-#define MV64340_I2O_OUTBOUND_QUEUE_PORT_VIRTUAL_REG_PCI_0_SIDE      0x044
-#define MV64340_I2O_QUEUE_CONTROL_REG_PCI_0_SIDE 		    0x050
-#define MV64340_I2O_QUEUE_BASE_ADDR_REG_PCI_0_SIDE 		    0x054
-#define MV64340_I2O_INBOUND_FREE_HEAD_POINTER_REG_PCI_0_SIDE        0x060
-#define MV64340_I2O_INBOUND_FREE_TAIL_POINTER_REG_PCI_0_SIDE        0x064
-#define MV64340_I2O_INBOUND_POST_HEAD_POINTER_REG_PCI_0_SIDE        0x068
-#define MV64340_I2O_INBOUND_POST_TAIL_POINTER_REG_PCI_0_SIDE        0x06C
-#define MV64340_I2O_OUTBOUND_FREE_HEAD_POINTER_REG_PCI_0_SIDE       0x070
-#define MV64340_I2O_OUTBOUND_FREE_TAIL_POINTER_REG_PCI_0_SIDE       0x074
-#define MV64340_I2O_OUTBOUND_POST_HEAD_POINTER_REG_PCI_0_SIDE       0x0F8
-#define MV64340_I2O_OUTBOUND_POST_TAIL_POINTER_REG_PCI_0_SIDE       0x0FC
-
-#define MV64340_I2O_INBOUND_MESSAGE_REG0_PCI_1_SIDE		    0x090
-#define MV64340_I2O_INBOUND_MESSAGE_REG1_PCI_1_SIDE  		    0x094
-#define MV64340_I2O_OUTBOUND_MESSAGE_REG0_PCI_1_SIDE 		    0x098
-#define MV64340_I2O_OUTBOUND_MESSAGE_REG1_PCI_1_SIDE  		    0x09C
-#define MV64340_I2O_INBOUND_DOORBELL_REG_PCI_1_SIDE  		    0x0A0
-#define MV64340_I2O_INBOUND_INTERRUPT_CAUSE_REG_PCI_1_SIDE          0x0A4
-#define MV64340_I2O_INBOUND_INTERRUPT_MASK_REG_PCI_1_SIDE	    0x0A8
-#define MV64340_I2O_OUTBOUND_DOORBELL_REG_PCI_1_SIDE 		    0x0AC
-#define MV64340_I2O_OUTBOUND_INTERRUPT_CAUSE_REG_PCI_1_SIDE         0x0B0
-#define MV64340_I2O_OUTBOUND_INTERRUPT_MASK_REG_PCI_1_SIDE          0x0B4
-#define MV64340_I2O_INBOUND_QUEUE_PORT_VIRTUAL_REG_PCI_1_SIDE       0x0C0
-#define MV64340_I2O_OUTBOUND_QUEUE_PORT_VIRTUAL_REG_PCI_1_SIDE      0x0C4
-#define MV64340_I2O_QUEUE_CONTROL_REG_PCI_1_SIDE 		    0x0D0
-#define MV64340_I2O_QUEUE_BASE_ADDR_REG_PCI_1_SIDE 		    0x0D4
-#define MV64340_I2O_INBOUND_FREE_HEAD_POINTER_REG_PCI_1_SIDE        0x0E0
-#define MV64340_I2O_INBOUND_FREE_TAIL_POINTER_REG_PCI_1_SIDE        0x0E4
-#define MV64340_I2O_INBOUND_POST_HEAD_POINTER_REG_PCI_1_SIDE        0x0E8
-#define MV64340_I2O_INBOUND_POST_TAIL_POINTER_REG_PCI_1_SIDE        0x0EC
-#define MV64340_I2O_OUTBOUND_FREE_HEAD_POINTER_REG_PCI_1_SIDE       0x0F0
-#define MV64340_I2O_OUTBOUND_FREE_TAIL_POINTER_REG_PCI_1_SIDE       0x0F4
-#define MV64340_I2O_OUTBOUND_POST_HEAD_POINTER_REG_PCI_1_SIDE       0x078
-#define MV64340_I2O_OUTBOUND_POST_TAIL_POINTER_REG_PCI_1_SIDE       0x07C
-
-#define MV64340_I2O_INBOUND_MESSAGE_REG0_CPU0_SIDE		    0x1C10
-#define MV64340_I2O_INBOUND_MESSAGE_REG1_CPU0_SIDE  		    0x1C14
-#define MV64340_I2O_OUTBOUND_MESSAGE_REG0_CPU0_SIDE 		    0x1C18
-#define MV64340_I2O_OUTBOUND_MESSAGE_REG1_CPU0_SIDE  		    0x1C1C
-#define MV64340_I2O_INBOUND_DOORBELL_REG_CPU0_SIDE  		    0x1C20
-#define MV64340_I2O_INBOUND_INTERRUPT_CAUSE_REG_CPU0_SIDE  	    0x1C24
-#define MV64340_I2O_INBOUND_INTERRUPT_MASK_REG_CPU0_SIDE	    0x1C28
-#define MV64340_I2O_OUTBOUND_DOORBELL_REG_CPU0_SIDE 		    0x1C2C
-#define MV64340_I2O_OUTBOUND_INTERRUPT_CAUSE_REG_CPU0_SIDE          0x1C30
-#define MV64340_I2O_OUTBOUND_INTERRUPT_MASK_REG_CPU0_SIDE           0x1C34
-#define MV64340_I2O_INBOUND_QUEUE_PORT_VIRTUAL_REG_CPU0_SIDE        0x1C40
-#define MV64340_I2O_OUTBOUND_QUEUE_PORT_VIRTUAL_REG_CPU0_SIDE       0x1C44
-#define MV64340_I2O_QUEUE_CONTROL_REG_CPU0_SIDE 		    0x1C50
-#define MV64340_I2O_QUEUE_BASE_ADDR_REG_CPU0_SIDE 		    0x1C54
-#define MV64340_I2O_INBOUND_FREE_HEAD_POINTER_REG_CPU0_SIDE         0x1C60
-#define MV64340_I2O_INBOUND_FREE_TAIL_POINTER_REG_CPU0_SIDE         0x1C64
-#define MV64340_I2O_INBOUND_POST_HEAD_POINTER_REG_CPU0_SIDE         0x1C68
-#define MV64340_I2O_INBOUND_POST_TAIL_POINTER_REG_CPU0_SIDE         0x1C6C
-#define MV64340_I2O_OUTBOUND_FREE_HEAD_POINTER_REG_CPU0_SIDE        0x1C70
-#define MV64340_I2O_OUTBOUND_FREE_TAIL_POINTER_REG_CPU0_SIDE        0x1C74
-#define MV64340_I2O_OUTBOUND_POST_HEAD_POINTER_REG_CPU0_SIDE        0x1CF8
-#define MV64340_I2O_OUTBOUND_POST_TAIL_POINTER_REG_CPU0_SIDE        0x1CFC
-#define MV64340_I2O_INBOUND_MESSAGE_REG0_CPU1_SIDE		    0x1C90
-#define MV64340_I2O_INBOUND_MESSAGE_REG1_CPU1_SIDE  		    0x1C94
-#define MV64340_I2O_OUTBOUND_MESSAGE_REG0_CPU1_SIDE 		    0x1C98
-#define MV64340_I2O_OUTBOUND_MESSAGE_REG1_CPU1_SIDE  		    0x1C9C
-#define MV64340_I2O_INBOUND_DOORBELL_REG_CPU1_SIDE  		    0x1CA0
-#define MV64340_I2O_INBOUND_INTERRUPT_CAUSE_REG_CPU1_SIDE  	    0x1CA4
-#define MV64340_I2O_INBOUND_INTERRUPT_MASK_REG_CPU1_SIDE	    0x1CA8
-#define MV64340_I2O_OUTBOUND_DOORBELL_REG_CPU1_SIDE 		    0x1CAC
-#define MV64340_I2O_OUTBOUND_INTERRUPT_CAUSE_REG_CPU1_SIDE          0x1CB0
-#define MV64340_I2O_OUTBOUND_INTERRUPT_MASK_REG_CPU1_SIDE           0x1CB4
-#define MV64340_I2O_INBOUND_QUEUE_PORT_VIRTUAL_REG_CPU1_SIDE        0x1CC0
-#define MV64340_I2O_OUTBOUND_QUEUE_PORT_VIRTUAL_REG_CPU1_SIDE       0x1CC4
-#define MV64340_I2O_QUEUE_CONTROL_REG_CPU1_SIDE 		    0x1CD0
-#define MV64340_I2O_QUEUE_BASE_ADDR_REG_CPU1_SIDE 		    0x1CD4
-#define MV64340_I2O_INBOUND_FREE_HEAD_POINTER_REG_CPU1_SIDE         0x1CE0
-#define MV64340_I2O_INBOUND_FREE_TAIL_POINTER_REG_CPU1_SIDE         0x1CE4
-#define MV64340_I2O_INBOUND_POST_HEAD_POINTER_REG_CPU1_SIDE         0x1CE8
-#define MV64340_I2O_INBOUND_POST_TAIL_POINTER_REG_CPU1_SIDE         0x1CEC
-#define MV64340_I2O_OUTBOUND_FREE_HEAD_POINTER_REG_CPU1_SIDE        0x1CF0
-#define MV64340_I2O_OUTBOUND_FREE_TAIL_POINTER_REG_CPU1_SIDE        0x1CF4
-#define MV64340_I2O_OUTBOUND_POST_HEAD_POINTER_REG_CPU1_SIDE        0x1C78
-#define MV64340_I2O_OUTBOUND_POST_TAIL_POINTER_REG_CPU1_SIDE        0x1C7C
-
-/****************************************/
-/*        Ethernet Unit Registers  		*/
-/****************************************/
-
-#define MV64340_ETH_PHY_ADDR_REG                                    0x2000
-#define MV64340_ETH_SMI_REG                                         0x2004
-#define MV64340_ETH_UNIT_DEFAULT_ADDR_REG                           0x2008
-#define MV64340_ETH_UNIT_DEFAULTID_REG                              0x200c
-#define MV64340_ETH_UNIT_INTERRUPT_CAUSE_REG                        0x2080
-#define MV64340_ETH_UNIT_INTERRUPT_MASK_REG                         0x2084
-#define MV64340_ETH_UNIT_INTERNAL_USE_REG                           0x24fc
-#define MV64340_ETH_UNIT_ERROR_ADDR_REG                             0x2094
-#define MV64340_ETH_BAR_0                                           0x2200
-#define MV64340_ETH_BAR_1                                           0x2208
-#define MV64340_ETH_BAR_2                                           0x2210
-#define MV64340_ETH_BAR_3                                           0x2218
-#define MV64340_ETH_BAR_4                                           0x2220
-#define MV64340_ETH_BAR_5                                           0x2228
-#define MV64340_ETH_SIZE_REG_0                                      0x2204
-#define MV64340_ETH_SIZE_REG_1                                      0x220c
-#define MV64340_ETH_SIZE_REG_2                                      0x2214
-#define MV64340_ETH_SIZE_REG_3                                      0x221c
-#define MV64340_ETH_SIZE_REG_4                                      0x2224
-#define MV64340_ETH_SIZE_REG_5                                      0x222c
-#define MV64340_ETH_HEADERS_RETARGET_BASE_REG                       0x2230
-#define MV64340_ETH_HEADERS_RETARGET_CONTROL_REG                    0x2234
-#define MV64340_ETH_HIGH_ADDR_REMAP_REG_0                           0x2280
-#define MV64340_ETH_HIGH_ADDR_REMAP_REG_1                           0x2284
-#define MV64340_ETH_HIGH_ADDR_REMAP_REG_2                           0x2288
-#define MV64340_ETH_HIGH_ADDR_REMAP_REG_3                           0x228c
-#define MV64340_ETH_BASE_ADDR_ENABLE_REG                            0x2290
-#define MV64340_ETH_ACCESS_PROTECTION_REG(port)                    (0x2294 + (port<<2))
-#define MV64340_ETH_MIB_COUNTERS_BASE(port)                        (0x3000 + (port<<7))
-#define MV64340_ETH_PORT_CONFIG_REG(port)                          (0x2400 + (port<<10))
-#define MV64340_ETH_PORT_CONFIG_EXTEND_REG(port)                   (0x2404 + (port<<10))
-#define MV64340_ETH_MII_SERIAL_PARAMETRS_REG(port)                 (0x2408 + (port<<10))
-#define MV64340_ETH_GMII_SERIAL_PARAMETRS_REG(port)                (0x240c + (port<<10))
-#define MV64340_ETH_VLAN_ETHERTYPE_REG(port)                       (0x2410 + (port<<10))
-#define MV64340_ETH_MAC_ADDR_LOW(port)                             (0x2414 + (port<<10))
-#define MV64340_ETH_MAC_ADDR_HIGH(port)                            (0x2418 + (port<<10))
-#define MV64340_ETH_SDMA_CONFIG_REG(port)                          (0x241c + (port<<10))
-#define MV64340_ETH_DSCP_0(port)                                   (0x2420 + (port<<10))
-#define MV64340_ETH_DSCP_1(port)                                   (0x2424 + (port<<10))
-#define MV64340_ETH_DSCP_2(port)                                   (0x2428 + (port<<10))
-#define MV64340_ETH_DSCP_3(port)                                   (0x242c + (port<<10))
-#define MV64340_ETH_DSCP_4(port)                                   (0x2430 + (port<<10))
-#define MV64340_ETH_DSCP_5(port)                                   (0x2434 + (port<<10))
-#define MV64340_ETH_DSCP_6(port)                                   (0x2438 + (port<<10))
-#define MV64340_ETH_PORT_SERIAL_CONTROL_REG(port)                  (0x243c + (port<<10))
-#define MV64340_ETH_VLAN_PRIORITY_TAG_TO_PRIORITY(port)            (0x2440 + (port<<10))
-#define MV64340_ETH_PORT_STATUS_REG(port)                          (0x2444 + (port<<10))
-#define MV64340_ETH_TRANSMIT_QUEUE_COMMAND_REG(port)               (0x2448 + (port<<10))
-#define MV64340_ETH_TX_QUEUE_FIXED_PRIORITY(port)                  (0x244c + (port<<10))
-#define MV64340_ETH_PORT_TX_TOKEN_BUCKET_RATE_CONFIG(port)         (0x2450 + (port<<10))
-#define MV64340_ETH_MAXIMUM_TRANSMIT_UNIT(port)                    (0x2458 + (port<<10))
-#define MV64340_ETH_PORT_MAXIMUM_TOKEN_BUCKET_SIZE(port)           (0x245c + (port<<10))
-#define MV64340_ETH_INTERRUPT_CAUSE_REG(port)                      (0x2460 + (port<<10))
-#define MV64340_ETH_INTERRUPT_CAUSE_EXTEND_REG(port)               (0x2464 + (port<<10))
-#define MV64340_ETH_INTERRUPT_MASK_REG(port)                       (0x2468 + (port<<10))
-#define MV64340_ETH_INTERRUPT_EXTEND_MASK_REG(port)                (0x246c + (port<<10))
-#define MV64340_ETH_RX_FIFO_URGENT_THRESHOLD_REG(port)             (0x2470 + (port<<10))
-#define MV64340_ETH_TX_FIFO_URGENT_THRESHOLD_REG(port)             (0x2474 + (port<<10))
-#define MV64340_ETH_RX_MINIMAL_FRAME_SIZE_REG(port)                (0x247c + (port<<10))
-#define MV64340_ETH_RX_DISCARDED_FRAMES_COUNTER(port)              (0x2484 + (port<<10)
-#define MV64340_ETH_PORT_DEBUG_0_REG(port)                         (0x248c + (port<<10))
-#define MV64340_ETH_PORT_DEBUG_1_REG(port)                         (0x2490 + (port<<10))
-#define MV64340_ETH_PORT_INTERNAL_ADDR_ERROR_REG(port)             (0x2494 + (port<<10))
-#define MV64340_ETH_INTERNAL_USE_REG(port)                         (0x24fc + (port<<10))
-#define MV64340_ETH_RECEIVE_QUEUE_COMMAND_REG(port)                (0x2680 + (port<<10))
-#define MV64340_ETH_CURRENT_SERVED_TX_DESC_PTR(port)               (0x2684 + (port<<10))      
-#define MV64340_ETH_RX_CURRENT_QUEUE_DESC_PTR_0(port)              (0x260c + (port<<10))     
-#define MV64340_ETH_RX_CURRENT_QUEUE_DESC_PTR_1(port)              (0x261c + (port<<10))     
-#define MV64340_ETH_RX_CURRENT_QUEUE_DESC_PTR_2(port)              (0x262c + (port<<10))     
-#define MV64340_ETH_RX_CURRENT_QUEUE_DESC_PTR_3(port)              (0x263c + (port<<10))     
-#define MV64340_ETH_RX_CURRENT_QUEUE_DESC_PTR_4(port)              (0x264c + (port<<10))     
-#define MV64340_ETH_RX_CURRENT_QUEUE_DESC_PTR_5(port)              (0x265c + (port<<10))     
-#define MV64340_ETH_RX_CURRENT_QUEUE_DESC_PTR_6(port)              (0x266c + (port<<10))     
-#define MV64340_ETH_RX_CURRENT_QUEUE_DESC_PTR_7(port)              (0x267c + (port<<10))     
-#define MV64340_ETH_TX_CURRENT_QUEUE_DESC_PTR_0(port)              (0x26c0 + (port<<10))     
-#define MV64340_ETH_TX_CURRENT_QUEUE_DESC_PTR_1(port)              (0x26c4 + (port<<10))     
-#define MV64340_ETH_TX_CURRENT_QUEUE_DESC_PTR_2(port)              (0x26c8 + (port<<10))     
-#define MV64340_ETH_TX_CURRENT_QUEUE_DESC_PTR_3(port)              (0x26cc + (port<<10))     
-#define MV64340_ETH_TX_CURRENT_QUEUE_DESC_PTR_4(port)              (0x26d0 + (port<<10))     
-#define MV64340_ETH_TX_CURRENT_QUEUE_DESC_PTR_5(port)              (0x26d4 + (port<<10))     
-#define MV64340_ETH_TX_CURRENT_QUEUE_DESC_PTR_6(port)              (0x26d8 + (port<<10))     
-#define MV64340_ETH_TX_CURRENT_QUEUE_DESC_PTR_7(port)              (0x26dc + (port<<10))     
-#define MV64340_ETH_TX_QUEUE_0_TOKEN_BUCKET_COUNT(port)            (0x2700 + (port<<10))
-#define MV64340_ETH_TX_QUEUE_1_TOKEN_BUCKET_COUNT(port)            (0x2710 + (port<<10))
-#define MV64340_ETH_TX_QUEUE_2_TOKEN_BUCKET_COUNT(port)            (0x2720 + (port<<10))
-#define MV64340_ETH_TX_QUEUE_3_TOKEN_BUCKET_COUNT(port)            (0x2730 + (port<<10))
-#define MV64340_ETH_TX_QUEUE_4_TOKEN_BUCKET_COUNT(port)            (0x2740 + (port<<10))
-#define MV64340_ETH_TX_QUEUE_5_TOKEN_BUCKET_COUNT(port)            (0x2750 + (port<<10))
-#define MV64340_ETH_TX_QUEUE_6_TOKEN_BUCKET_COUNT(port)            (0x2760 + (port<<10))
-#define MV64340_ETH_TX_QUEUE_7_TOKEN_BUCKET_COUNT(port)            (0x2770 + (port<<10))
-#define MV64340_ETH_TX_QUEUE_0_TOKEN_BUCKET_CONFIG(port)           (0x2704 + (port<<10))
-#define MV64340_ETH_TX_QUEUE_1_TOKEN_BUCKET_CONFIG(port)           (0x2714 + (port<<10))
-#define MV64340_ETH_TX_QUEUE_2_TOKEN_BUCKET_CONFIG(port)           (0x2724 + (port<<10))
-#define MV64340_ETH_TX_QUEUE_3_TOKEN_BUCKET_CONFIG(port)           (0x2734 + (port<<10))
-#define MV64340_ETH_TX_QUEUE_4_TOKEN_BUCKET_CONFIG(port)           (0x2744 + (port<<10))
-#define MV64340_ETH_TX_QUEUE_5_TOKEN_BUCKET_CONFIG(port)           (0x2754 + (port<<10))
-#define MV64340_ETH_TX_QUEUE_6_TOKEN_BUCKET_CONFIG(port)           (0x2764 + (port<<10))
-#define MV64340_ETH_TX_QUEUE_7_TOKEN_BUCKET_CONFIG(port)           (0x2774 + (port<<10))
-#define MV64340_ETH_TX_QUEUE_0_ARBITER_CONFIG(port)                (0x2708 + (port<<10))
-#define MV64340_ETH_TX_QUEUE_1_ARBITER_CONFIG(port)                (0x2718 + (port<<10))
-#define MV64340_ETH_TX_QUEUE_2_ARBITER_CONFIG(port)                (0x2728 + (port<<10))
-#define MV64340_ETH_TX_QUEUE_3_ARBITER_CONFIG(port)                (0x2738 + (port<<10))
-#define MV64340_ETH_TX_QUEUE_4_ARBITER_CONFIG(port)                (0x2748 + (port<<10))
-#define MV64340_ETH_TX_QUEUE_5_ARBITER_CONFIG(port)                (0x2758 + (port<<10))
-#define MV64340_ETH_TX_QUEUE_6_ARBITER_CONFIG(port)                (0x2768 + (port<<10))
-#define MV64340_ETH_TX_QUEUE_7_ARBITER_CONFIG(port)                (0x2778 + (port<<10))
-#define MV64340_ETH_PORT_TX_TOKEN_BUCKET_COUNT(port)               (0x2780 + (port<<10))
-#define MV64340_ETH_DA_FILTER_SPECIAL_MULTICAST_TABLE_BASE(port)   (0x3400 + (port<<10))
-#define MV64340_ETH_DA_FILTER_OTHER_MULTICAST_TABLE_BASE(port)     (0x3500 + (port<<10))
-#define MV64340_ETH_DA_FILTER_UNICAST_TABLE_BASE(port)             (0x3600 + (port<<10))
-
-/*******************************************/
-/*          CUNIT  Registers               */
-/*******************************************/
-
-         /* Address Decoding Register Map */
-           
-#define MV64340_CUNIT_BASE_ADDR_REG0                                0xf200
-#define MV64340_CUNIT_BASE_ADDR_REG1                                0xf208
-#define MV64340_CUNIT_BASE_ADDR_REG2                                0xf210
-#define MV64340_CUNIT_BASE_ADDR_REG3                                0xf218
-#define MV64340_CUNIT_SIZE0                                         0xf204
-#define MV64340_CUNIT_SIZE1                                         0xf20c
-#define MV64340_CUNIT_SIZE2                                         0xf214
-#define MV64340_CUNIT_SIZE3                                         0xf21c
-#define MV64340_CUNIT_HIGH_ADDR_REMAP_REG0                          0xf240
-#define MV64340_CUNIT_HIGH_ADDR_REMAP_REG1                          0xf244
-#define MV64340_CUNIT_BASE_ADDR_ENABLE_REG                          0xf250
-#define MV64340_MPSC0_ACCESS_PROTECTION_REG                         0xf254
-#define MV64340_MPSC1_ACCESS_PROTECTION_REG                         0xf258
-#define MV64340_CUNIT_INTERNAL_SPACE_BASE_ADDR_REG                  0xf25C
-
-        /*  Error Report Registers  */
-
-#define MV64340_CUNIT_INTERRUPT_CAUSE_REG                           0xf310
-#define MV64340_CUNIT_INTERRUPT_MASK_REG                            0xf314
-#define MV64340_CUNIT_ERROR_ADDR                                    0xf318
-
-        /*  Cunit Control Registers */
-
-#define MV64340_CUNIT_ARBITER_CONTROL_REG                           0xf300
-#define MV64340_CUNIT_CONFIG_REG                                    0xb40c
-#define MV64340_CUNIT_CRROSBAR_TIMEOUT_REG                          0xf304
-
-        /*  Cunit Debug Registers   */
-
-#define MV64340_CUNIT_DEBUG_LOW                                     0xf340
-#define MV64340_CUNIT_DEBUG_HIGH                                    0xf344
-#define MV64340_CUNIT_MMASK                                         0xf380
-
-        /*  MPSCs Clocks Routing Registers  */
-
-#define MV64340_MPSC_ROUTING_REG                                    0xb400
-#define MV64340_MPSC_RX_CLOCK_ROUTING_REG                           0xb404
-#define MV64340_MPSC_TX_CLOCK_ROUTING_REG                           0xb408
-
-        /*  MPSCs Interrupts Registers    */
-
-#define MV64340_MPSC_CAUSE_REG(port)                               (0xb804 + (port<<3))
-#define MV64340_MPSC_MASK_REG(port)                                (0xb884 + (port<<3))
- 
-#define MV64340_MPSC_MAIN_CONFIG_LOW(port)                         (0x8000 + (port<<12))
-#define MV64340_MPSC_MAIN_CONFIG_HIGH(port)                        (0x8004 + (port<<12))    
-#define MV64340_MPSC_PROTOCOL_CONFIG(port)                         (0x8008 + (port<<12))    
-#define MV64340_MPSC_CHANNEL_REG1(port)                            (0x800c + (port<<12))    
-#define MV64340_MPSC_CHANNEL_REG2(port)                            (0x8010 + (port<<12))    
-#define MV64340_MPSC_CHANNEL_REG3(port)                            (0x8014 + (port<<12))    
-#define MV64340_MPSC_CHANNEL_REG4(port)                            (0x8018 + (port<<12))    
-#define MV64340_MPSC_CHANNEL_REG5(port)                            (0x801c + (port<<12))    
-#define MV64340_MPSC_CHANNEL_REG6(port)                            (0x8020 + (port<<12))    
-#define MV64340_MPSC_CHANNEL_REG7(port)                            (0x8024 + (port<<12))    
-#define MV64340_MPSC_CHANNEL_REG8(port)                            (0x8028 + (port<<12))    
-#define MV64340_MPSC_CHANNEL_REG9(port)                            (0x802c + (port<<12))    
-#define MV64340_MPSC_CHANNEL_REG10(port)                           (0x8030 + (port<<12))    
-        
-        /*  MPSC0 Registers      */
-
-
-/***************************************/
-/*          SDMA Registers             */
-/***************************************/
-
-#define MV64340_SDMA_CONFIG_REG(channel)                        (0x4000 + (channel<<13))        
-#define MV64340_SDMA_COMMAND_REG(channel)                       (0x4008 + (channel<<13))        
-#define MV64340_SDMA_CURRENT_RX_DESCRIPTOR_POINTER(channel)     (0x4810 + (channel<<13))        
-#define MV64340_SDMA_CURRENT_TX_DESCRIPTOR_POINTER(channel)     (0x4c10 + (channel<<13))        
-#define MV64340_SDMA_FIRST_TX_DESCRIPTOR_POINTER(channel)       (0x4c14 + (channel<<13)) 
-
-#define MV64340_SDMA_CAUSE_REG                                      0xb800
-#define MV64340_SDMA_MASK_REG                                       0xb880
-         
-/* BRG Interrupts */
-
-#define MV64340_BRG_CONFIG_REG(brg)                              (0xb200 + (brg<<3))
-#define MV64340_BRG_BAUDE_TUNING_REG(brg)                        (0xb208 + (brg<<3))
-#define MV64340_BRG_CAUSE_REG                                       0xb834
-#define MV64340_BRG_MASK_REG                                        0xb8b4
-
-/****************************************/
-/* DMA Channel Control			*/
-/****************************************/
-
-#define MV64340_DMA_CHANNEL0_CONTROL 				    0x840
-#define MV64340_DMA_CHANNEL0_CONTROL_HIGH			    0x880
-#define MV64340_DMA_CHANNEL1_CONTROL 				    0x844
-#define MV64340_DMA_CHANNEL1_CONTROL_HIGH			    0x884
-#define MV64340_DMA_CHANNEL2_CONTROL 				    0x848
-#define MV64340_DMA_CHANNEL2_CONTROL_HIGH			    0x888
-#define MV64340_DMA_CHANNEL3_CONTROL 				    0x84C
-#define MV64340_DMA_CHANNEL3_CONTROL_HIGH			    0x88C
-
-
-/****************************************/
-/*           IDMA Registers             */
-/****************************************/
-
-#define MV64340_DMA_CHANNEL0_BYTE_COUNT                             0x800
-#define MV64340_DMA_CHANNEL1_BYTE_COUNT                             0x804
-#define MV64340_DMA_CHANNEL2_BYTE_COUNT                             0x808
-#define MV64340_DMA_CHANNEL3_BYTE_COUNT                             0x80C
-#define MV64340_DMA_CHANNEL0_SOURCE_ADDR                            0x810
-#define MV64340_DMA_CHANNEL1_SOURCE_ADDR                            0x814
-#define MV64340_DMA_CHANNEL2_SOURCE_ADDR                            0x818
-#define MV64340_DMA_CHANNEL3_SOURCE_ADDR                            0x81c
-#define MV64340_DMA_CHANNEL0_DESTINATION_ADDR                       0x820
-#define MV64340_DMA_CHANNEL1_DESTINATION_ADDR                       0x824
-#define MV64340_DMA_CHANNEL2_DESTINATION_ADDR                       0x828
-#define MV64340_DMA_CHANNEL3_DESTINATION_ADDR                       0x82C
-#define MV64340_DMA_CHANNEL0_NEXT_DESCRIPTOR_POINTER                0x830
-#define MV64340_DMA_CHANNEL1_NEXT_DESCRIPTOR_POINTER                0x834
-#define MV64340_DMA_CHANNEL2_NEXT_DESCRIPTOR_POINTER                0x838
-#define MV64340_DMA_CHANNEL3_NEXT_DESCRIPTOR_POINTER                0x83C
-#define MV64340_DMA_CHANNEL0_CURRENT_DESCRIPTOR_POINTER             0x870
-#define MV64340_DMA_CHANNEL1_CURRENT_DESCRIPTOR_POINTER             0x874
-#define MV64340_DMA_CHANNEL2_CURRENT_DESCRIPTOR_POINTER             0x878
-#define MV64340_DMA_CHANNEL3_CURRENT_DESCRIPTOR_POINTER             0x87C
-
- /*  IDMA Address Decoding Base Address Registers  */
- 
-#define MV64340_DMA_BASE_ADDR_REG0                                  0xa00
-#define MV64340_DMA_BASE_ADDR_REG1                                  0xa08
-#define MV64340_DMA_BASE_ADDR_REG2                                  0xa10
-#define MV64340_DMA_BASE_ADDR_REG3                                  0xa18
-#define MV64340_DMA_BASE_ADDR_REG4                                  0xa20
-#define MV64340_DMA_BASE_ADDR_REG5                                  0xa28
-#define MV64340_DMA_BASE_ADDR_REG6                                  0xa30
-#define MV64340_DMA_BASE_ADDR_REG7                                  0xa38
- 
- /*  IDMA Address Decoding Size Address Register   */
- 
-#define MV64340_DMA_SIZE_REG0                                       0xa04
-#define MV64340_DMA_SIZE_REG1                                       0xa0c
-#define MV64340_DMA_SIZE_REG2                                       0xa14
-#define MV64340_DMA_SIZE_REG3                                       0xa1c
-#define MV64340_DMA_SIZE_REG4                                       0xa24
-#define MV64340_DMA_SIZE_REG5                                       0xa2c
-#define MV64340_DMA_SIZE_REG6                                       0xa34
-#define MV64340_DMA_SIZE_REG7                                       0xa3C
-
- /* IDMA Address Decoding High Address Remap and Access 
-                  Protection Registers                    */
-                  
-#define MV64340_DMA_HIGH_ADDR_REMAP_REG0                            0xa60
-#define MV64340_DMA_HIGH_ADDR_REMAP_REG1                            0xa64
-#define MV64340_DMA_HIGH_ADDR_REMAP_REG2                            0xa68
-#define MV64340_DMA_HIGH_ADDR_REMAP_REG3                            0xa6C
-#define MV64340_DMA_BASE_ADDR_ENABLE_REG                            0xa80
-#define MV64340_DMA_CHANNEL0_ACCESS_PROTECTION_REG                  0xa70
-#define MV64340_DMA_CHANNEL1_ACCESS_PROTECTION_REG                  0xa74
-#define MV64340_DMA_CHANNEL2_ACCESS_PROTECTION_REG                  0xa78
-#define MV64340_DMA_CHANNEL3_ACCESS_PROTECTION_REG                  0xa7c
-#define MV64340_DMA_ARBITER_CONTROL                                 0x860
-#define MV64340_DMA_CROSS_BAR_TIMEOUT                               0x8d0
-
- /*  IDMA Headers Retarget Registers   */
-
-#define MV64340_DMA_HEADERS_RETARGET_CONTROL                        0xa84
-#define MV64340_DMA_HEADERS_RETARGET_BASE                           0xa88
-
- /*  IDMA Interrupt Register  */
-
-#define MV64340_DMA_INTERRUPT_CAUSE_REG                             0x8c0
-#define MV64340_DMA_INTERRUPT_CAUSE_MASK                            0x8c4
-#define MV64340_DMA_ERROR_ADDR                                      0x8c8
-#define MV64340_DMA_ERROR_SELECT                                    0x8cc
-
- /*  IDMA Debug Register ( for internal use )    */
-
-#define MV64340_DMA_DEBUG_LOW                                       0x8e0
-#define MV64340_DMA_DEBUG_HIGH                                      0x8e4
-#define MV64340_DMA_SPARE                                           0xA8C
-
-/****************************************/
-/* Timer_Counter 			*/
-/****************************************/
-
-#define MV64340_TIMER_COUNTER0					    0x850
-#define MV64340_TIMER_COUNTER1					    0x854
-#define MV64340_TIMER_COUNTER2					    0x858
-#define MV64340_TIMER_COUNTER3					    0x85C
-#define MV64340_TIMER_COUNTER_0_3_CONTROL			    0x864
-#define MV64340_TIMER_COUNTER_0_3_INTERRUPT_CAUSE		    0x868
-#define MV64340_TIMER_COUNTER_0_3_INTERRUPT_MASK      		    0x86c
-
-/****************************************/
-/*         Watchdog registers  	        */
-/****************************************/
-
-#define MV64340_WATCHDOG_CONFIG_REG                                 0xb410
-#define MV64340_WATCHDOG_VALUE_REG                                  0xb414
-
-/****************************************/
-/* I2C Registers                        */
-/****************************************/
-
-#define MV64340_I2C_SLAVE_ADDR                                      0xc000
-#define MV64340_I2C_EXTENDED_SLAVE_ADDR                             0xc010
-#define MV64340_I2C_DATA                                            0xc004
-#define MV64340_I2C_CONTROL                                         0xc008
-#define MV64340_I2C_STATUS_BAUDE_RATE                               0xc00C
-#define MV64340_I2C_SOFT_RESET                                      0xc01c
-
-/****************************************/
-/* GPP Interface Registers              */
-/****************************************/
-
-#define MV64340_GPP_IO_CONTROL                                      0xf100
-#define MV64340_GPP_LEVEL_CONTROL                                   0xf110
-#define MV64340_GPP_VALUE                                           0xf104
-#define MV64340_GPP_INTERRUPT_CAUSE                                 0xf108
-#define MV64340_GPP_INTERRUPT_MASK0                                 0xf10c
-#define MV64340_GPP_INTERRUPT_MASK1                                 0xf114
-#define MV64340_GPP_VALUE_SET                                       0xf118
-#define MV64340_GPP_VALUE_CLEAR                                     0xf11c
-
-/****************************************/
-/* Interrupt Controller Registers       */
-/****************************************/
-
-/****************************************/
-/* Interrupts	  			*/
-/****************************************/
-
-#define MV64340_MAIN_INTERRUPT_CAUSE_LOW                            0x004
-#define MV64340_MAIN_INTERRUPT_CAUSE_HIGH                           0x00c
-#define MV64340_CPU_INTERRUPT0_MASK_LOW                             0x014
-#define MV64340_CPU_INTERRUPT0_MASK_HIGH                            0x01c
-#define MV64340_CPU_INTERRUPT0_SELECT_CAUSE                         0x024
-#define MV64340_CPU_INTERRUPT1_MASK_LOW                             0x034
-#define MV64340_CPU_INTERRUPT1_MASK_HIGH                            0x03c
-#define MV64340_CPU_INTERRUPT1_SELECT_CAUSE                         0x044
-#define MV64340_INTERRUPT0_MASK_0_LOW                               0x054
-#define MV64340_INTERRUPT0_MASK_0_HIGH                              0x05c
-#define MV64340_INTERRUPT0_SELECT_CAUSE                             0x064
-#define MV64340_INTERRUPT1_MASK_0_LOW                               0x074
-#define MV64340_INTERRUPT1_MASK_0_HIGH                              0x07c
-#define MV64340_INTERRUPT1_SELECT_CAUSE                             0x084
-
-/****************************************/
-/*      MPP Interface Registers         */
-/****************************************/
-
-#define MV64340_MPP_CONTROL0                                        0xf000
-#define MV64340_MPP_CONTROL1                                        0xf004
-#define MV64340_MPP_CONTROL2                                        0xf008
-#define MV64340_MPP_CONTROL3                                        0xf00c
-
-/****************************************/
-/*    Serial Initialization registers   */
-/****************************************/
-
-#define MV64340_SERIAL_INIT_LAST_DATA                               0xf324
-#define MV64340_SERIAL_INIT_CONTROL                                 0xf328
-#define MV64340_SERIAL_INIT_STATUS                                  0xf32c
-
-extern void mv64340_irq_init(unsigned int base);
-
-#endif /* __ASM_MV64340_H */
diff -Nru a/include/asm-mips/ptrace.h b/include/asm-mips/ptrace.h
--- a/include/asm-mips/ptrace.h	2004-10-18 14:56:33 -07:00
+++ b/include/asm-mips/ptrace.h	2004-10-18 14:56:33 -07:00
@@ -66,6 +66,7 @@
 #define user_mode(regs) (((regs)->cp0_status & KU_MASK) == KU_USER)
 
 #define instruction_pointer(regs) ((regs)->cp0_epc)
+#define profile_pc(regs) instruction_pointer(regs)
 
 extern void show_regs(struct pt_regs *);
 
diff -Nru a/include/asm-mips/resource.h b/include/asm-mips/resource.h
--- a/include/asm-mips/resource.h	2004-10-18 14:56:50 -07:00
+++ b/include/asm-mips/resource.h	2004-10-18 14:56:50 -07:00
@@ -53,7 +53,7 @@
 	{ INR_OPEN,      INR_OPEN      },		\
 	{ RLIM_INFINITY, RLIM_INFINITY },		\
 	{ RLIM_INFINITY, RLIM_INFINITY },		\
-	{ 0,             0             },		\
+	{ MLOCK_LIMIT,     MLOCK_LIMIT },		\
 	{ RLIM_INFINITY, RLIM_INFINITY },		\
 	{ RLIM_INFINITY, RLIM_INFINITY },		\
 	{ MAX_SIGPENDING, MAX_SIGPENDING },		\
diff -Nru a/include/asm-mips/semaphore.h b/include/asm-mips/semaphore.h
--- a/include/asm-mips/semaphore.h	2004-10-18 14:56:28 -07:00
+++ b/include/asm-mips/semaphore.h	2004-10-18 14:56:28 -07:00
@@ -37,22 +37,13 @@
 	 */
 	atomic_t count;
 	wait_queue_head_t wait;
-#ifdef WAITQUEUE_DEBUG
-	long __magic;
-#endif
 };
 
-#ifdef WAITQUEUE_DEBUG
-# define __SEM_DEBUG_INIT(name) \
-		, (long)&(name).__magic
-#else
-# define __SEM_DEBUG_INIT(name)
-#endif
-
-#define __SEMAPHORE_INITIALIZER(name, count) \
-	{ ATOMIC_INIT(count), \
-	  __WAIT_QUEUE_HEAD_INITIALIZER((name).wait) \
-	  __SEM_DEBUG_INIT(name) }
+#define __SEMAPHORE_INITIALIZER(name, n)				\
+{									\
+	.count		= ATOMIC_INIT(n),				\
+	.wait		= __WAIT_QUEUE_HEAD_INITIALIZER((name).wait)	\
+}
 
 #define __MUTEX_INITIALIZER(name) \
 	__SEMAPHORE_INITIALIZER(name, 1)
@@ -67,9 +58,6 @@
 {
 	atomic_set(&sem->count, val);
 	init_waitqueue_head(&sem->wait);
-#ifdef WAITQUEUE_DEBUG
-	sem->__magic = (long)&sem->__magic;
-#endif
 }
 
 static inline void init_MUTEX (struct semaphore *sem)
@@ -88,9 +76,6 @@
 
 static inline void down(struct semaphore * sem)
 {
-#ifdef WAITQUEUE_DEBUG
-	CHECK_MAGIC(sem->__magic);
-#endif
 	might_sleep();
 
 	/*
@@ -104,9 +89,6 @@
 {
 	int ret = 0;
 
-#ifdef WAITQUEUE_DEBUG
-	CHECK_MAGIC(sem->__magic);
-#endif
 	might_sleep();
 
 	if (unlikely(atomic_dec_return(&sem->count) < 0))
@@ -116,19 +98,11 @@
 
 static inline int down_trylock(struct semaphore * sem)
 {
-#ifdef WAITQUEUE_DEBUG
-	CHECK_MAGIC(sem->__magic);
-#endif
-
 	return atomic_dec_if_positive(&sem->count) < 0;
 }
 
 static inline void up(struct semaphore * sem)
 {
-#ifdef WAITQUEUE_DEBUG
-	CHECK_MAGIC(sem->__magic);
-#endif
-
 	if (unlikely(atomic_inc_return(&sem->count) <= 0))
 		__up(sem);
 }
diff -Nru a/include/asm-mips/siginfo.h b/include/asm-mips/siginfo.h
--- a/include/asm-mips/siginfo.h	2004-10-18 14:56:32 -07:00
+++ b/include/asm-mips/siginfo.h	2004-10-18 14:56:32 -07:00
@@ -47,8 +47,8 @@
 		struct {
 			pid_t _pid;		/* which child */
 			uid_t _uid;		/* sender's uid */
-			clock_t _utime;
 			int _status;		/* exit code */
+			clock_t _utime;
 			clock_t _stime;
 		} _sigchld;
 
diff -Nru a/include/asm-mips/socket.h b/include/asm-mips/socket.h
--- a/include/asm-mips/socket.h	2004-10-18 14:56:49 -07:00
+++ b/include/asm-mips/socket.h	2004-10-18 14:56:49 -07:00
@@ -68,20 +68,31 @@
 
 #define SO_PEERSEC		30
 
-/* Nast libc5 fixup - bletch */
-#if defined(__KERNEL__)
-/* Socket types. */
-#define SOCK_DGRAM	1		/* datagram (conn.less) socket	*/
-#define SOCK_STREAM	2		/* stream (connection) socket	*/
-#define SOCK_RAW	3		/* raw socket			*/
-#define SOCK_RDM	4		/* reliably-delivered message	*/
-#define SOCK_SEQPACKET	5		/* sequential packet socket	*/
-#define SOCK_PACKET	10		/* linux specific way of	*/
-					/* getting packets at the dev	*/
-					/* level.  For writing rarp and	*/
-					/* other similar things on the	*/
-					/* user level.			*/
-#define	SOCK_MAX	(SOCK_PACKET+1)
-#endif
+/** sock_type - Socket types
+ *
+ * Please notice that for binary compat reasons MIPS has to
+ * override the enum sock_type in include/linux/net.h, so
+ * we define ARCH_HAS_SOCKET_TYPES here.
+ *
+ * @SOCK_DGRAM - datagram (conn.less) socket
+ * @SOCK_STREAM - stream (connection) socket
+ * @SOCK_RAW - raw socket
+ * @SOCK_RDM - reliably-delivered message
+ * @SOCK_SEQPACKET - sequential packet socket 
+ * @SOCK_PACKET - linux specific way of getting packets at the dev level.
+ *		  For writing rarp and other similar things on the user level.
+ */
+enum sock_type {
+	SOCK_DGRAM	= 1,
+	SOCK_STREAM	= 2,
+	SOCK_RAW	= 3,
+	SOCK_RDM	= 4,
+	SOCK_SEQPACKET	= 5,
+	SOCK_PACKET	= 10,
+};
+
+#define SOCK_MAX (SOCK_PACKET + 1)
+
+#define ARCH_HAS_SOCKET_TYPES
 
 #endif /* _ASM_SOCKET_H */
diff -Nru a/include/asm-mips/uaccess.h b/include/asm-mips/uaccess.h
--- a/include/asm-mips/uaccess.h	2004-10-18 14:55:54 -07:00
+++ b/include/asm-mips/uaccess.h	2004-10-18 14:55:54 -07:00
@@ -13,6 +13,7 @@
 #include <linux/compiler.h>
 #include <linux/errno.h>
 #include <linux/thread_info.h>
+#include <asm-generic/uaccess.h>
 
 /*
  * The fs value determines whether argument validity checking should be
@@ -462,6 +463,9 @@
 	__cu_len = __invoke_copy_to_user(__cu_to, __cu_from, __cu_len);	\
 	__cu_len;							\
 })
+
+#define __copy_to_user_inatomic __copy_to_user
+#define __copy_from_user_inatomic __copy_from_user
 
 /*
  * copy_to_user: - Copy a block of data into user space.
diff -Nru a/include/asm-mips/vr41xx/vrc4173.h b/include/asm-mips/vr41xx/vrc4173.h
--- a/include/asm-mips/vr41xx/vrc4173.h	2004-10-18 14:57:03 -07:00
+++ b/include/asm-mips/vr41xx/vrc4173.h	2004-10-18 14:57:03 -07:00
@@ -48,6 +48,8 @@
 /*
  * PCI I/O accesses
  */
+#ifdef CONFIG_VRC4173
+
 extern unsigned long vrc4173_io_offset;
 
 #define set_vrc4173_io_offset(offset)	do { vrc4173_io_offset = (offset); } while (0)
@@ -74,6 +76,34 @@
 #define vrc4173_insw(port,addr,count)	insw(vrc4173_io_offset+(port),(addr),(count))
 #define vrc4173_insl(port,addr,count)	insl(vrc4173_io_offset+(port),(addr),(count))
 
+#else
+
+#define set_vrc4173_io_offset(offset)	do {} while (0)
+
+#define vrc4173_outb(val,port)		do {} while (0)
+#define vrc4173_outw(val,port)		do {} while (0)
+#define vrc4173_outl(val,port)		do {} while (0)
+#define vrc4173_outb_p(val,port)	do {} while (0)
+#define vrc4173_outw_p(val,port)	do {} while (0)
+#define vrc4173_outl_p(val,port)	do {} while (0)
+
+#define vrc4173_inb(port)		0
+#define vrc4173_inw(port)		0
+#define vrc4173_inl(port)		0
+#define vrc4173_inb_p(port)		0
+#define vrc4173_inw_p(port)		0
+#define vrc4173_inl_p(port)		0
+
+#define vrc4173_outsb(port,addr,count)	do {} while (0)
+#define vrc4173_outsw(port,addr,count)	do {} while (0)
+#define vrc4173_outsl(port,addr,count)	do {} while (0)
+
+#define vrc4173_insb(port,addr,count)	do {} while (0)
+#define vrc4173_insw(port,addr,count)	do {} while (0)
+#define vrc4173_insl(port,addr,count)	do {} while (0)
+
+#endif
+
 /*
  * Clock Mask Unit
  */
@@ -92,9 +122,77 @@
 	VRC4173_48MHz_CLOCK,
 } vrc4173_clock_t;
 
+#ifdef CONFIG_VRC4173
+
 extern void vrc4173_supply_clock(vrc4173_clock_t clock);
 extern void vrc4173_mask_clock(vrc4173_clock_t clock);
 
+#else
+
+static inline void vrc4173_supply_clock(vrc4173_clock_t clock) {}
+static inline void vrc4173_mask_clock(vrc4173_clock_t clock) {}
+
+#endif
+
+/*
+ * Interupt Control Unit
+ */
+
+#define VRC4173_PIUINT_COMMAND		0x0040
+#define VRC4173_PIUINT_DATA		0x0020
+#define VRC4173_PIUINT_PAGE1		0x0010
+#define VRC4173_PIUINT_PAGE0		0x0008
+#define VRC4173_PIUINT_DATALOST		0x0004
+#define VRC4173_PIUINT_STATUSCHANGE	0x0001
+
+#ifdef CONFIG_VRC4173
+
+extern void vrc4173_enable_piuint(uint16_t mask);
+extern void vrc4173_disable_piuint(uint16_t mask);
+
+#else
+
+static inline void vrc4173_enable_piuint(uint16_t mask) {}
+static inline void vrc4173_disable_piuint(uint16_t mask) {}
+
+#endif
+
+#define VRC4173_AIUINT_INPUT_DMAEND	0x0800
+#define VRC4173_AIUINT_INPUT_DMAHALT	0x0400
+#define VRC4173_AIUINT_INPUT_DATALOST	0x0200
+#define VRC4173_AIUINT_INPUT_DATA	0x0100
+#define VRC4173_AIUINT_OUTPUT_DMAEND	0x0008
+#define VRC4173_AIUINT_OUTPUT_DMAHALT	0x0004
+#define VRC4173_AIUINT_OUTPUT_NODATA	0x0002
+
+#ifdef CONFIG_VRC4173
+
+extern void vrc4173_enable_aiuint(uint16_t mask);
+extern void vrc4173_disable_aiuint(uint16_t mask);
+
+#else
+
+static inline void vrc4173_enable_aiuint(uint16_t mask) {}
+static inline void vrc4173_disable_aiuint(uint16_t mask) {}
+
+#endif
+
+#define VRC4173_KIUINT_DATALOST		0x0004
+#define VRC4173_KIUINT_DATAREADY	0x0002
+#define VRC4173_KIUINT_SCAN		0x0001
+
+#ifdef CONFIG_VRC4173
+
+extern void vrc4173_enable_kiuint(uint16_t mask);
+extern void vrc4173_disable_kiuint(uint16_t mask);
+
+#else
+
+static inline void vrc4173_enable_kiuint(uint16_t mask) {}
+static inline void vrc4173_disable_kiuint(uint16_t mask) {}
+
+#endif
+
 /*
  * General-Purpose I/O Unit
  */
@@ -109,6 +207,14 @@
 	GPIO_16_20PINS,
 } vrc4173_function_t;
 
+#ifdef CONFIG_VRC4173
+
 extern void vrc4173_select_function(vrc4173_function_t function);
+
+#else
+
+static inline void vrc4173_select_function(vrc4173_function_t function) {}
+
+#endif
 
 #endif /* __NEC_VRC4173_H */
diff -Nru a/include/asm-parisc/bug.h b/include/asm-parisc/bug.h
--- a/include/asm-parisc/bug.h	2004-10-18 14:56:49 -07:00
+++ b/include/asm-parisc/bug.h	2004-10-18 14:56:49 -07:00
@@ -1,29 +1,4 @@
 #ifndef _PARISC_BUG_H
 #define _PARISC_BUG_H
-
-/*
- * Tell the user there is some problem.
- */
-#define BUG() do { \
-	extern void dump_stack(void); \
-	printk("kernel BUG at %s:%d!\n", __FILE__, __LINE__); \
-	dump_stack(); \
-} while (0)
-
-#define BUG_ON(condition) do { \
-	if (unlikely((condition)!=0)) \
-		BUG(); \
-} while(0)
-
-#define PAGE_BUG(page) do { \
-	BUG(); \
-} while (0)
-
-#define WARN_ON(condition) do { \
-	if (unlikely((condition)!=0)) { \
-		printk("Badness in %s at %s:%d\n", __FUNCTION__, __FILE__, __LINE__); \
-		dump_stack(); \
-	} \
-} while (0)
-
+#include <asm-generic/bug.h>
 #endif
diff -Nru a/include/asm-parisc/cacheflush.h b/include/asm-parisc/cacheflush.h
--- a/include/asm-parisc/cacheflush.h	2004-10-18 14:57:04 -07:00
+++ b/include/asm-parisc/cacheflush.h	2004-10-18 14:57:04 -07:00
@@ -77,11 +77,17 @@
 #define flush_icache_range(s,e)		do { flush_kernel_dcache_range_asm(s,e); flush_kernel_icache_range_asm(s,e); } while (0)
 
 #define copy_to_user_page(vma, page, vaddr, dst, src, len) \
-do { memcpy(dst, src, len); \
-     flush_kernel_dcache_range_asm((unsigned long)dst, (unsigned long)dst + len); \
+do { \
+	flush_cache_page(vma, vaddr); \
+	memcpy(dst, src, len); \
+	flush_kernel_dcache_range_asm((unsigned long)dst, (unsigned long)dst + len); \
 } while (0)
+
 #define copy_from_user_page(vma, page, vaddr, dst, src, len) \
-	memcpy(dst, src, len)
+do { \
+	flush_cache_page(vma, vaddr); \
+	memcpy(dst, src, len); \
+} while (0)
 
 static inline void flush_cache_range(struct vm_area_struct *vma,
 		unsigned long start, unsigned long end)
diff -Nru a/include/asm-parisc/hardirq.h b/include/asm-parisc/hardirq.h
--- a/include/asm-parisc/hardirq.h	2004-10-18 14:57:03 -07:00
+++ b/include/asm-parisc/hardirq.h	2004-10-18 14:57:03 -07:00
@@ -51,20 +51,6 @@
 #define SOFTIRQ_SHIFT	(PREEMPT_SHIFT + PREEMPT_BITS)
 #define HARDIRQ_SHIFT	(SOFTIRQ_SHIFT + SOFTIRQ_BITS)
 
-#define __MASK(x)	((1UL << (x))-1)
-
-#define PREEMPT_MASK	(__MASK(PREEMPT_BITS) << PREEMPT_SHIFT)
-#define HARDIRQ_MASK	(__MASK(HARDIRQ_BITS) << HARDIRQ_SHIFT)
-#define SOFTIRQ_MASK	(__MASK(SOFTIRQ_BITS) << SOFTIRQ_SHIFT)
-
-#define hardirq_count()	(preempt_count() & HARDIRQ_MASK)
-#define softirq_count()	(preempt_count() & SOFTIRQ_MASK)
-#define irq_count()	(preempt_count() & (HARDIRQ_MASK | SOFTIRQ_MASK))
-
-#define PREEMPT_OFFSET	(1UL << PREEMPT_SHIFT)
-#define SOFTIRQ_OFFSET	(1UL << SOFTIRQ_SHIFT)
-#define HARDIRQ_OFFSET	(1UL << HARDIRQ_SHIFT)
-
 /*
  * The hardirq mask has to be large enough to have space for potentially all IRQ sources
  * in the system nesting on a single CPU:
@@ -73,29 +59,7 @@
 # error HARDIRQ_BITS is too low!
 #endif
 
-/*
- * Are we doing bottom half or hardware interrupt processing?
- * Are we in a softirq context?
- * Interrupt context?
- */
-#define in_irq()		(hardirq_count())
-#define in_softirq()		(softirq_count())
-#define in_interrupt()		(irq_count())
-
-#define hardirq_trylock()	(!in_interrupt())
-#define hardirq_endlock()	do { } while (0)
-
 #define irq_enter()		(preempt_count() += HARDIRQ_OFFSET)
-
-#ifdef CONFIG_PREEMPT
-# error CONFIG_PREEMT currently not supported.
-# define in_atomic()	 BUG()
-# define IRQ_EXIT_OFFSET (HARDIRQ_OFFSET-1)
-#else
-# define in_atomic()	(preempt_count() != 0)
-# define IRQ_EXIT_OFFSET HARDIRQ_OFFSET
-#endif
-
 #define irq_exit()								\
 do {										\
 		preempt_count() -= IRQ_EXIT_OFFSET;				\
@@ -103,11 +67,5 @@
 			do_softirq();						\
 		preempt_enable_no_resched();					\
 } while (0)
-
-#ifdef CONFIG_SMP
-  extern void synchronize_irq (unsigned int irq);
-#else
-# define synchronize_irq(irq)	barrier()
-#endif /* CONFIG_SMP */
 
 #endif /* _PARISC_HARDIRQ_H */
diff -Nru a/include/asm-parisc/ptrace.h b/include/asm-parisc/ptrace.h
--- a/include/asm-parisc/ptrace.h	2004-10-18 14:56:29 -07:00
+++ b/include/asm-parisc/ptrace.h	2004-10-18 14:56:29 -07:00
@@ -48,6 +48,7 @@
 /* XXX should we use iaoq[1] or iaoq[0] ? */
 #define user_mode(regs)			(((regs)->iaoq[0] &  3) ? 1 : 0)
 #define instruction_pointer(regs)	((regs)->iaoq[0] & ~3)
+#define profile_pc(regs) instruction_pointer(regs)
 extern void show_regs(struct pt_regs *);
 #endif
 
diff -Nru a/include/asm-parisc/resource.h b/include/asm-parisc/resource.h
--- a/include/asm-parisc/resource.h	2004-10-18 14:56:48 -07:00
+++ b/include/asm-parisc/resource.h	2004-10-18 14:56:48 -07:00
@@ -39,7 +39,7 @@
 	{ RLIM_INFINITY, RLIM_INFINITY },		\
 	{             0,             0 },		\
 	{      INR_OPEN,     INR_OPEN  },		\
-	{ RLIM_INFINITY, RLIM_INFINITY },		\
+	{   MLOCK_LIMIT,   MLOCK_LIMIT },		\
 	{ RLIM_INFINITY, RLIM_INFINITY },		\
 	{ RLIM_INFINITY, RLIM_INFINITY },		\
 	{ MAX_SIGPENDING, MAX_SIGPENDING },		\
diff -Nru a/include/asm-parisc/semaphore.h b/include/asm-parisc/semaphore.h
--- a/include/asm-parisc/semaphore.h	2004-10-18 14:55:53 -07:00
+++ b/include/asm-parisc/semaphore.h	2004-10-18 14:55:53 -07:00
@@ -40,21 +40,14 @@
 	spinlock_t	sentry;
 	int		count;
 	wait_queue_head_t wait;
-#if WAITQUEUE_DEBUG
-	long __magic;
-#endif
 };
 
-#if WAITQUEUE_DEBUG
-# define __SEM_DEBUG_INIT(name) \
-		, (long)&(name).__magic
-#else
-# define __SEM_DEBUG_INIT(name)
-#endif
-
-#define __SEMAPHORE_INITIALIZER(name,count) \
-{ SPIN_LOCK_UNLOCKED, count, __WAIT_QUEUE_HEAD_INITIALIZER((name).wait) \
-	__SEM_DEBUG_INIT(name) }
+#define __SEMAPHORE_INITIALIZER(name, n)				\
+{									\
+	.sentry		= SPIN_LOCK_UNLOCKED,				\
+	.count		= n,						\
+	.wait		= __WAIT_QUEUE_HEAD_INITIALIZER((name).wait)	\
+}
 
 #define __MUTEX_INITIALIZER(name) \
 	__SEMAPHORE_INITIALIZER(name,1)
@@ -95,9 +88,6 @@
 
 extern __inline__ void down(struct semaphore * sem)
 {
-#if WAITQUEUE_DEBUG
-	CHECK_MAGIC(sem->__magic);
-#endif
 	might_sleep();
 	spin_lock_irq(&sem->sentry);
 	if (sem->count > 0) {
@@ -111,9 +101,6 @@
 extern __inline__ int down_interruptible(struct semaphore * sem)
 {
 	int ret = 0;
-#if WAITQUEUE_DEBUG
-	CHECK_MAGIC(sem->__magic);
-#endif
 	might_sleep();
 	spin_lock_irq(&sem->sentry);
 	if (sem->count > 0) {
@@ -132,9 +119,6 @@
 extern __inline__ int down_trylock(struct semaphore * sem)
 {
 	int flags, count;
-#if WAITQUEUE_DEBUG
-	CHECK_MAGIC(sem->__magic);
-#endif
 
 	spin_lock_irqsave(&sem->sentry, flags);
 	count = sem->count - 1;
@@ -151,9 +135,6 @@
 extern __inline__ void up(struct semaphore * sem)
 {
 	int flags;
-#if WAITQUEUE_DEBUG
-	CHECK_MAGIC(sem->__magic);
-#endif
 	spin_lock_irqsave(&sem->sentry, flags);
 	if (sem->count < 0) {
 		__up(sem);
diff -Nru a/include/asm-parisc/socket.h b/include/asm-parisc/socket.h
--- a/include/asm-parisc/socket.h	2004-10-18 14:56:33 -07:00
+++ b/include/asm-parisc/socket.h	2004-10-18 14:56:33 -07:00
@@ -47,18 +47,4 @@
 
 #define SO_PEERSEC		0x401d
 
-#if defined(__KERNEL__)
-#define SOCK_STREAM	1	/* stream (connection) socket	*/
-#define SOCK_DGRAM	2	/* datagram (conn.less) socket	*/
-#define SOCK_RAW	3	/* raw socket			*/
-#define SOCK_RDM	4	/* reliably-delivered message	*/
-#define SOCK_SEQPACKET	5	/* sequential packet socket	*/
-#define SOCK_PACKET	10	/* linux specific way of	*/
-				/* getting packets at the dev	*/
-				/* level.  For writing rarp and	*/
-				/* other similar things on the	*/
-				/* user level.			*/
-#define	SOCK_MAX	(SOCK_PACKET+1)
-#endif
-
 #endif /* _ASM_SOCKET_H */
diff -Nru a/include/asm-parisc/uaccess.h b/include/asm-parisc/uaccess.h
--- a/include/asm-parisc/uaccess.h	2004-10-18 14:56:20 -07:00
+++ b/include/asm-parisc/uaccess.h	2004-10-18 14:56:20 -07:00
@@ -279,5 +279,7 @@
 #define __copy_to_user lcopy_to_user
 #define copy_in_user lcopy_in_user
 #define __copy_in_user lcopy_in_user
+#define __copy_to_user_inatomic __copy_to_user
+#define __copy_from_user_inatomic __copy_from_user
 
 #endif /* __PARISC_UACCESS_H */
diff -Nru a/include/asm-ppc/8253pit.h b/include/asm-ppc/8253pit.h
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/include/asm-ppc/8253pit.h	2004-10-18 14:57:24 -07:00
@@ -0,0 +1,10 @@
+/*
+ * 8253/8254 Programmable Interval Timer
+ */
+
+#ifndef _8253PIT_H
+#define _8253PIT_H
+
+#define PIT_TICK_RATE 	1193182UL
+
+#endif
diff -Nru a/include/asm-ppc/bug.h b/include/asm-ppc/bug.h
--- a/include/asm-ppc/bug.h	2004-10-18 14:56:49 -07:00
+++ b/include/asm-ppc/bug.h	2004-10-18 14:56:49 -07:00
@@ -35,8 +35,6 @@
 	}								\
 } while (0)
 
-#define PAGE_BUG(page)	BUG()
-
 #define WARN_ON(x) do {							\
 	if (!__builtin_constant_p(x) || (x)) {				\
 		__asm__ __volatile__(					\
@@ -48,5 +46,10 @@
 			    "i" (__FILE__), "i" (__FUNCTION__));	\
 	}								\
 } while (0)
+
+#define HAVE_ARCH_BUG
+#define HAVE_ARCH_BUG_ON
+#define HAVE_ARCH_WARN_ON
+#include <asm-generic/bug.h>
 
 #endif
diff -Nru a/include/asm-ppc/checksum.h b/include/asm-ppc/checksum.h
--- a/include/asm-ppc/checksum.h	2004-10-18 14:56:27 -07:00
+++ b/include/asm-ppc/checksum.h	2004-10-18 14:56:27 -07:00
@@ -33,7 +33,7 @@
 					      int *src_err, int *dst_err);
 
 #define csum_partial_copy_from_user(src, dst, len, sum, errp)	\
-	csum_partial_copy_generic((src), (dst), (len), (sum), (errp), NULL)
+	csum_partial_copy_generic((__force void *)(src), (dst), (len), (sum), (errp), NULL)
 
 /* FIXME: this needs to be written to really do no check -- Cort */
 #define csum_partial_copy_nocheck(src, dst, len, sum)	\
diff -Nru a/include/asm-ppc/dma-mapping.h b/include/asm-ppc/dma-mapping.h
--- a/include/asm-ppc/dma-mapping.h	2004-10-18 14:56:49 -07:00
+++ b/include/asm-ppc/dma-mapping.h	2004-10-18 14:56:49 -07:00
@@ -8,7 +8,6 @@
 #include <linux/config.h>
 /* need struct page definitions */
 #include <linux/mm.h>
-#include <linux/device.h>
 #include <asm/scatterlist.h>
 #include <asm/io.h>
 
diff -Nru a/include/asm-ppc/fsl_ocp.h b/include/asm-ppc/fsl_ocp.h
--- a/include/asm-ppc/fsl_ocp.h	2004-10-18 14:57:03 -07:00
+++ b/include/asm-ppc/fsl_ocp.h	2004-10-18 14:57:03 -07:00
@@ -48,7 +48,7 @@
 
 /* Flags for I2C */
 #define FS_I2C_SEPARATE_DFSRR	0x02
-#define FS_I2C_32BIT		0x01
+#define FS_I2C_CLOCK_5200	0x01
 
 #endif	/* __ASM_FS_OCP_H__ */
 #endif	/* __KERNEL__ */
diff -Nru a/include/asm-ppc/hardirq.h b/include/asm-ppc/hardirq.h
--- a/include/asm-ppc/hardirq.h	2004-10-18 14:55:53 -07:00
+++ b/include/asm-ppc/hardirq.h	2004-10-18 14:55:53 -07:00
@@ -44,20 +44,6 @@
 #define SOFTIRQ_SHIFT	(PREEMPT_SHIFT + PREEMPT_BITS)
 #define HARDIRQ_SHIFT	(SOFTIRQ_SHIFT + SOFTIRQ_BITS)
 
-#define __MASK(x)	((1UL << (x))-1)
-
-#define PREEMPT_MASK	(__MASK(PREEMPT_BITS) << PREEMPT_SHIFT)
-#define HARDIRQ_MASK	(__MASK(HARDIRQ_BITS) << HARDIRQ_SHIFT)
-#define SOFTIRQ_MASK	(__MASK(SOFTIRQ_BITS) << SOFTIRQ_SHIFT)
-
-#define hardirq_count()	(preempt_count() & HARDIRQ_MASK)
-#define softirq_count()	(preempt_count() & SOFTIRQ_MASK)
-#define irq_count()	(preempt_count() & (HARDIRQ_MASK | SOFTIRQ_MASK))
-
-#define PREEMPT_OFFSET	(1UL << PREEMPT_SHIFT)
-#define SOFTIRQ_OFFSET	(1UL << SOFTIRQ_SHIFT)
-#define HARDIRQ_OFFSET	(1UL << HARDIRQ_SHIFT)
-
 /*
  * The hardirq mask has to be large enough to have
  * space for potentially all IRQ sources in the system
@@ -67,31 +53,7 @@
 # error HARDIRQ_BITS is too low!
 #endif
 
-/*
- * Are we doing bottom half or hardware interrupt processing?
- * Are we in a softirq context? Interrupt context?
- */
-#define in_irq()		(hardirq_count())
-#define in_softirq()		(softirq_count())
-#define in_interrupt()		(irq_count())
-
-
-#define hardirq_trylock()	(!in_interrupt())
-#define hardirq_endlock()	do { } while (0)
-
 #define irq_enter()		(preempt_count() += HARDIRQ_OFFSET)
-
-#ifdef CONFIG_PREEMPT
-# define in_atomic()	((preempt_count() & ~PREEMPT_ACTIVE) != kernel_locked())
-# define preemptible()	(preempt_count() == 0 && !irqs_disabled())
-# define IRQ_EXIT_OFFSET (HARDIRQ_OFFSET-1)
-
-#else
-# define in_atomic()	(preempt_count() != 0)
-# define preemptible()	0
-# define IRQ_EXIT_OFFSET HARDIRQ_OFFSET
-#endif
-
 #define irq_exit()							\
 do {									\
 	preempt_count() -= IRQ_EXIT_OFFSET;				\
@@ -99,12 +61,6 @@
 		do_softirq();						\
 	preempt_enable_no_resched();					\
 } while (0)
-
-#ifndef CONFIG_SMP
-# define synchronize_irq(irq)	barrier()
-#else
-  extern void synchronize_irq(unsigned int irq);
-#endif /* CONFIG_SMP */
 
 #endif /* __ASM_HARDIRQ_H */
 #endif /* __KERNEL__ */
diff -Nru a/include/asm-ppc/ibm44x.h b/include/asm-ppc/ibm44x.h
--- a/include/asm-ppc/ibm44x.h	2004-10-18 14:56:50 -07:00
+++ b/include/asm-ppc/ibm44x.h	2004-10-18 14:56:50 -07:00
@@ -94,8 +94,8 @@
 #define DCRN_SDR_CONFIG_DATA	0xf
 #define DCRN_SDR_PFC0		0x4100
 #define DCRN_SDR_PFC1		0x4101
-#define DCRN_SDR_PFC1_EPS	0x1c000000
-#define DCRN_SDR_PFC1_EPS_SHIFT	26
+#define DCRN_SDR_PFC1_EPS	0x1c00000
+#define DCRN_SDR_PFC1_EPS_SHIFT	22
 #define DCRN_SDR_PFC1_RMII	0x02000000
 #define DCRN_SDR_MFR		0x4300
 #define DCRN_SDR_MFR_TAH0 	0x80000000  	/* TAHOE0 Enable */
diff -Nru a/include/asm-ppc/ide.h b/include/asm-ppc/ide.h
--- a/include/asm-ppc/ide.h	2004-10-18 14:57:03 -07:00
+++ b/include/asm-ppc/ide.h	2004-10-18 14:57:03 -07:00
@@ -24,10 +24,10 @@
 #include <linux/ioport.h>
 #include <asm/io.h>
 
-extern void __ide_mm_insw(unsigned long port, void *addr, u32 count);
-extern void __ide_mm_outsw(unsigned long port, void *addr, u32 count);
-extern void __ide_mm_insl(unsigned long port, void *addr, u32 count);
-extern void __ide_mm_outsl(unsigned long port, void *addr, u32 count);
+extern void __ide_mm_insw(void __iomem *port, void *addr, u32 count);
+extern void __ide_mm_outsw(void __iomem *port, void *addr, u32 count);
+extern void __ide_mm_insl(void __iomem *port, void *addr, u32 count);
+extern void __ide_mm_outsl(void __iomem *port, void *addr, u32 count);
 
 struct ide_machdep_calls {
         int         (*default_irq)(unsigned long base);
diff -Nru a/include/asm-ppc/io.h b/include/asm-ppc/io.h
--- a/include/asm-ppc/io.h	2004-10-18 14:56:49 -07:00
+++ b/include/asm-ppc/io.h	2004-10-18 14:56:49 -07:00
@@ -4,7 +4,6 @@
 
 #include <linux/config.h>
 #include <linux/types.h>
-#include <linux/mm.h>
 
 #include <asm/page.h>
 #include <asm/byteorder.h>
@@ -398,6 +397,79 @@
 {
 	return 0;
 }
+
+/*
+ * Here comes the ppc implementation of the IOMAP 
+ * interfaces.
+ */
+static inline unsigned int ioread8(void __iomem *addr)
+{
+	return readb(addr);
+}
+
+static inline unsigned int ioread16(void __iomem *addr)
+{
+	return readw(addr);
+}
+
+static inline unsigned int ioread32(void __iomem *addr)
+{
+	return readl(addr);
+}
+
+static inline void iowrite8(u8 val, void __iomem *addr)
+{
+	writeb(val, addr);
+}
+
+static inline void iowrite16(u16 val, void __iomem *addr)
+{
+	writew(val, addr);
+}
+
+static inline void iowrite32(u32 val, void __iomem *addr)
+{
+	writel(val, addr);
+}
+
+static inline void ioread8_rep(void __iomem *addr, void *dst, unsigned long count)
+{
+	_insb((u8 __force *) addr, dst, count);
+}
+
+static inline void ioread16_rep(void __iomem *addr, void *dst, unsigned long count)
+{
+	_insw_ns((u16 __force *) addr, dst, count);
+}
+
+static inline void ioread32_rep(void __iomem *addr, void *dst, unsigned long count)
+{
+	_insl_ns((u32 __force *) addr, dst, count);
+}
+
+static inline void iowrite8_rep(void __iomem *addr, const void *src, unsigned long count)
+{
+	_outsb((u8 __force *) addr, src, count);
+}
+
+static inline void iowrite16_rep(void __iomem *addr, const void *src, unsigned long count)
+{
+	_outsw_ns((u16 __force *) addr, src, count);
+}
+
+static inline void iowrite32_rep(void __iomem *addr, const void *src, unsigned long count)
+{
+	_outsl_ns((u32 __force *) addr, src, count);
+}
+
+/* Create a virtual mapping cookie for an IO port range */
+extern void __iomem *ioport_map(unsigned long port, unsigned int nr);
+extern void ioport_unmap(void __iomem *);
+
+/* Create a virtual mapping cookie for a PCI BAR (memory or IO) */
+struct pci_dev;
+extern void __iomem *pci_iomap(struct pci_dev *dev, int bar, unsigned long max);
+extern void pci_iounmap(struct pci_dev *dev, void __iomem *);
 
 #endif /* _PPC_IO_H */
 
diff -Nru a/include/asm-ppc/mpc52xx.h b/include/asm-ppc/mpc52xx.h
--- a/include/asm-ppc/mpc52xx.h	2004-10-18 14:57:03 -07:00
+++ b/include/asm-ppc/mpc52xx.h	2004-10-18 14:57:03 -07:00
@@ -42,6 +42,7 @@
 #define MPC52xx_MBAR_VIRT	0xf0000000	/* Virt address */
 
 #define MPC52xx_MMAP_CTL	(MPC52xx_MBAR + 0x0000)
+#define MPC52xx_SDRAM		(MPC52xx_MBAR + 0x0100)
 #define MPC52xx_CDM		(MPC52xx_MBAR + 0x0200)
 #define MPC52xx_SFTRST		(MPC52xx_MBAR + 0x0220)
 #define MPC52xx_SFTRST_BIT	0x01000000
@@ -51,6 +52,7 @@
 #define MPC52xx_MSCAN1		(MPC52xx_MBAR + 0x0900)
 #define MPC52xx_MSCAN2		(MPC52xx_MBAR + 0x0980)
 #define MPC52xx_GPIO		(MPC52xx_MBAR + 0x0b00)
+#define MPC52xx_GPIO_WKUP	(MPC52xx_MBAR + 0x0c00)
 #define MPC52xx_PCI		(MPC52xx_MBAR + 0x0d00)
 #define MPC52xx_USB_OHCI	(MPC52xx_MBAR + 0x1000)
 #define MPC52xx_SDMA		(MPC52xx_MBAR + 0x1200)
@@ -71,10 +73,6 @@
 /* SRAM used for SDMA */
 #define MPC52xx_SRAM		(MPC52xx_MBAR + 0x8000)
 #define MPC52xx_SRAM_SIZE	(16*1024)
-#define MPC52xx_SDMA_MAX_TASKS	16
-
-	/* Memory allocation block size */
-#define MPC52xx_SDRAM_UNIT	0x8000		/* 32K byte */
 
 
 /* ======================================================================== */
@@ -137,206 +135,240 @@
 
 /* Memory Mapping Control */
 struct mpc52xx_mmap_ctl {
-	volatile u32	mbar;		/* MMAP_CTRL + 0x00 */
+	u32	mbar;		/* MMAP_CTRL + 0x00 */
+
+	u32	cs0_start;	/* MMAP_CTRL + 0x04 */
+	u32	cs0_stop;	/* MMAP_CTRL + 0x08 */
+	u32	cs1_start;	/* MMAP_CTRL + 0x0c */
+	u32	cs1_stop;	/* MMAP_CTRL + 0x10 */
+	u32	cs2_start;	/* MMAP_CTRL + 0x14 */
+	u32	cs2_stop;	/* MMAP_CTRL + 0x18 */
+	u32	cs3_start;	/* MMAP_CTRL + 0x1c */
+	u32	cs3_stop;	/* MMAP_CTRL + 0x20 */
+	u32	cs4_start;	/* MMAP_CTRL + 0x24 */
+	u32	cs4_stop;	/* MMAP_CTRL + 0x28 */
+	u32	cs5_start;	/* MMAP_CTRL + 0x2c */
+	u32	cs5_stop;	/* MMAP_CTRL + 0x30 */
+
+	u32	sdram0;		/* MMAP_CTRL + 0x34 */
+	u32	sdram1;		/* MMAP_CTRL + 0X38 */
+
+	u32	reserved[4];	/* MMAP_CTRL + 0x3c .. 0x48 */
+
+	u32	boot_start;	/* MMAP_CTRL + 0x4c */
+	u32	boot_stop;	/* MMAP_CTRL + 0x50 */
+
+	u32	ipbi_ws_ctrl;	/* MMAP_CTRL + 0x54 */
+
+	u32	cs6_start;	/* MMAP_CTRL + 0x58 */
+	u32	cs6_stop;	/* MMAP_CTRL + 0x5c */
+	u32	cs7_start;	/* MMAP_CTRL + 0x60 */
+	u32	cs7_stop;	/* MMAP_CTRL + 0x60 */
+};
 
-	volatile u32	cs0_start;	/* MMAP_CTRL + 0x04 */
-	volatile u32	cs0_stop;	/* MMAP_CTRL + 0x08 */
-	volatile u32	cs1_start;	/* MMAP_CTRL + 0x0c */
-	volatile u32	cs1_stop;	/* MMAP_CTRL + 0x10 */
-	volatile u32	cs2_start;	/* MMAP_CTRL + 0x14 */
-	volatile u32	cs2_stop;	/* MMAP_CTRL + 0x18 */
-	volatile u32	cs3_start;	/* MMAP_CTRL + 0x1c */
-	volatile u32	cs3_stop;	/* MMAP_CTRL + 0x20 */
-	volatile u32	cs4_start;	/* MMAP_CTRL + 0x24 */
-	volatile u32	cs4_stop;	/* MMAP_CTRL + 0x28 */
-	volatile u32	cs5_start;	/* MMAP_CTRL + 0x2c */
-	volatile u32	cs5_stop;	/* MMAP_CTRL + 0x30 */
-
-	volatile u32	sdram0;		/* MMAP_CTRL + 0x34 */
-	volatile u32	sdram1;		/* MMAP_CTRL + 0X38 */
-
-	volatile u32	reserved[4];	/* MMAP_CTRL + 0x3c .. 0x48 */
-
-	volatile u32	boot_start;	/* MMAP_CTRL + 0x4c */
-	volatile u32	boot_stop;	/* MMAP_CTRL + 0x50 */
-	
-	volatile u32	ipbi_ws_ctrl;	/* MMAP_CTRL + 0x54 */
-	
-	volatile u32	cs6_start;	/* MMAP_CTRL + 0x58 */
-	volatile u32	cs6_stop;	/* MMAP_CTRL + 0x5c */
-	volatile u32	cs7_start;	/* MMAP_CTRL + 0x60 */
-	volatile u32	cs7_stop;	/* MMAP_CTRL + 0x60 */
+/* SDRAM control */
+struct mpc52xx_sdram {
+	u32	mode;		/* SDRAM + 0x00 */
+	u32	ctrl;		/* SDRAM + 0x04 */
+	u32	config1;	/* SDRAM + 0x08 */
+	u32	config2;	/* SDRAM + 0x0c */
 };
 
 /* Interrupt controller */
 struct mpc52xx_intr {
-	volatile u32	per_mask;	/* INTR + 0x00 */
-	volatile u32	per_pri1;	/* INTR + 0x04 */
-	volatile u32	per_pri2;	/* INTR + 0x08 */
-	volatile u32	per_pri3;	/* INTR + 0x0c */
-	volatile u32	ctrl;		/* INTR + 0x10 */
-	volatile u32	main_mask;	/* INTR + 0x14 */
-	volatile u32	main_pri1;	/* INTR + 0x18 */
-	volatile u32	main_pri2;	/* INTR + 0x1c */
-	volatile u32	reserved1;	/* INTR + 0x20 */
-	volatile u32	enc_status;	/* INTR + 0x24 */
-	volatile u32	crit_status;	/* INTR + 0x28 */
-	volatile u32	main_status;	/* INTR + 0x2c */
-	volatile u32	per_status;	/* INTR + 0x30 */
-	volatile u32	reserved2;	/* INTR + 0x34 */
-	volatile u32	per_error;	/* INTR + 0x38 */
+	u32	per_mask;	/* INTR + 0x00 */
+	u32	per_pri1;	/* INTR + 0x04 */
+	u32	per_pri2;	/* INTR + 0x08 */
+	u32	per_pri3;	/* INTR + 0x0c */
+	u32	ctrl;		/* INTR + 0x10 */
+	u32	main_mask;	/* INTR + 0x14 */
+	u32	main_pri1;	/* INTR + 0x18 */
+	u32	main_pri2;	/* INTR + 0x1c */
+	u32	reserved1;	/* INTR + 0x20 */
+	u32	enc_status;	/* INTR + 0x24 */
+	u32	crit_status;	/* INTR + 0x28 */
+	u32	main_status;	/* INTR + 0x2c */
+	u32	per_status;	/* INTR + 0x30 */
+	u32	reserved2;	/* INTR + 0x34 */
+	u32	per_error;	/* INTR + 0x38 */
 };
 
 /* SDMA */
 struct mpc52xx_sdma {
-	volatile u32	taskBar;	/* SDMA + 0x00 */
-	volatile u32	currentPointer;	/* SDMA + 0x04 */
-	volatile u32	endPointer;	/* SDMA + 0x08 */
-	volatile u32	variablePointer;/* SDMA + 0x0c */
-
-	volatile u8	IntVect1;	/* SDMA + 0x10 */
-	volatile u8	IntVect2;	/* SDMA + 0x11 */
-	volatile u16	PtdCntrl;	/* SDMA + 0x12 */
-
-	volatile u32	IntPend;	/* SDMA + 0x14 */
-	volatile u32	IntMask;	/* SDMA + 0x18 */
-	
-	volatile u16	tcr[16];	/* SDMA + 0x1c .. 0x3a */
-
-	volatile u8	ipr[31];	/* SDMA + 0x3c .. 5b */
-
-	volatile u32	res1;		/* SDMA + 0x5c */
-	volatile u32	task_size0;	/* SDMA + 0x60 */
-	volatile u32	task_size1;	/* SDMA + 0x64 */
-	volatile u32	MDEDebug;	/* SDMA + 0x68 */
-	volatile u32	ADSDebug;	/* SDMA + 0x6c */
-	volatile u32	Value1;		/* SDMA + 0x70 */
-	volatile u32	Value2;		/* SDMA + 0x74 */
-	volatile u32	Control;	/* SDMA + 0x78 */
-	volatile u32	Status;		/* SDMA + 0x7c */
+	u32	taskBar;	/* SDMA + 0x00 */
+	u32	currentPointer;	/* SDMA + 0x04 */
+	u32	endPointer;	/* SDMA + 0x08 */
+	u32	variablePointer;/* SDMA + 0x0c */
+
+	u8	IntVect1;	/* SDMA + 0x10 */
+	u8	IntVect2;	/* SDMA + 0x11 */
+	u16	PtdCntrl;	/* SDMA + 0x12 */
+
+	u32	IntPend;	/* SDMA + 0x14 */
+	u32	IntMask;	/* SDMA + 0x18 */
+
+	u16	tcr[16];	/* SDMA + 0x1c .. 0x3a */
+
+	u8	ipr[32];	/* SDMA + 0x3c .. 5b */
+
+	u32	cReqSelect;	/* SDMA + 0x5c */
+	u32	task_size0;	/* SDMA + 0x60 */
+	u32	task_size1;	/* SDMA + 0x64 */
+	u32	MDEDebug;	/* SDMA + 0x68 */
+	u32	ADSDebug;	/* SDMA + 0x6c */
+	u32	Value1;		/* SDMA + 0x70 */
+	u32	Value2;		/* SDMA + 0x74 */
+	u32	Control;	/* SDMA + 0x78 */
+	u32	Status;		/* SDMA + 0x7c */
+	u32	PTDDebug;	/* SDMA + 0x80 */
 };
 
 /* GPT */
 struct mpc52xx_gpt {
-	volatile u32	mode;		/* GPTx + 0x00 */
-	volatile u32	count;		/* GPTx + 0x04 */
-	volatile u32	pwm;		/* GPTx + 0x08 */
-	volatile u32	status;		/* GPTx + 0X0c */
+	u32	mode;		/* GPTx + 0x00 */
+	u32	count;		/* GPTx + 0x04 */
+	u32	pwm;		/* GPTx + 0x08 */
+	u32	status;		/* GPTx + 0X0c */
 };
 
 /* RTC */
 struct mpc52xx_rtc {
-	volatile u32	time_set;	/* RTC + 0x00 */
-	volatile u32	date_set;	/* RTC + 0x04 */
-	volatile u32	stopwatch;	/* RTC + 0x08 */
-	volatile u32	int_enable;	/* RTC + 0x0c */
-	volatile u32	time;		/* RTC + 0x10 */
-	volatile u32	date;		/* RTC + 0x14 */
-	volatile u32	stopwatch_intr;	/* RTC + 0x18 */
-	volatile u32	bus_error;	/* RTC + 0x1c */
-	volatile u32	dividers;	/* RTC + 0x20 */
+	u32	time_set;	/* RTC + 0x00 */
+	u32	date_set;	/* RTC + 0x04 */
+	u32	stopwatch;	/* RTC + 0x08 */
+	u32	int_enable;	/* RTC + 0x0c */
+	u32	time;		/* RTC + 0x10 */
+	u32	date;		/* RTC + 0x14 */
+	u32	stopwatch_intr;	/* RTC + 0x18 */
+	u32	bus_error;	/* RTC + 0x1c */
+	u32	dividers;	/* RTC + 0x20 */
 };
 
 /* GPIO */
 struct mpc52xx_gpio {
-	volatile u32	port_config;	/* GPIO + 0x00 */
-	volatile u32	simple_gpioe;	/* GPIO + 0x04 */
-	volatile u32	simple_ode;	/* GPIO + 0x08 */
-	volatile u32	simple_ddr;	/* GPIO + 0x0c */
-	volatile u32	simple_dvo;	/* GPIO + 0x10 */
-	volatile u32	simple_ival;	/* GPIO + 0x14 */
-	volatile u8	outo_gpioe;	/* GPIO + 0x18 */
-	volatile u8	reserved1[3];	/* GPIO + 0x19 */
-	volatile u8	outo_dvo;	/* GPIO + 0x1c */
-	volatile u8	reserved2[3];	/* GPIO + 0x1d */
-	volatile u8	sint_gpioe;	/* GPIO + 0x20 */
-	volatile u8	reserved3[3];	/* GPIO + 0x21 */
-	volatile u8	sint_ode;	/* GPIO + 0x24 */
-	volatile u8	reserved4[3];	/* GPIO + 0x25 */
-	volatile u8	sint_ddr;	/* GPIO + 0x28 */
-	volatile u8	reserved5[3];	/* GPIO + 0x29 */
-	volatile u8	sint_dvo;	/* GPIO + 0x2c */
-	volatile u8	reserved6[3];	/* GPIO + 0x2d */
-	volatile u8	sint_inten;	/* GPIO + 0x30 */
-	volatile u8	reserved7[3];	/* GPIO + 0x31 */
-	volatile u16	sint_itype;	/* GPIO + 0x34 */
-	volatile u16	reserved8;	/* GPIO + 0x36 */
-	volatile u8	gpio_control;	/* GPIO + 0x38 */
-	volatile u8	reserved9[3];	/* GPIO + 0x39 */
-	volatile u8	sint_istat;	/* GPIO + 0x3c */
-	volatile u8	sint_ival;	/* GPIO + 0x3d */
-	volatile u8	bus_errs;	/* GPIO + 0x3e */
-	volatile u8	reserved10;	/* GPIO + 0x3f */
+	u32	port_config;	/* GPIO + 0x00 */
+	u32	simple_gpioe;	/* GPIO + 0x04 */
+	u32	simple_ode;	/* GPIO + 0x08 */
+	u32	simple_ddr;	/* GPIO + 0x0c */
+	u32	simple_dvo;	/* GPIO + 0x10 */
+	u32	simple_ival;	/* GPIO + 0x14 */
+	u8	outo_gpioe;	/* GPIO + 0x18 */
+	u8	reserved1[3];	/* GPIO + 0x19 */
+	u8	outo_dvo;	/* GPIO + 0x1c */
+	u8	reserved2[3];	/* GPIO + 0x1d */
+	u8	sint_gpioe;	/* GPIO + 0x20 */
+	u8	reserved3[3];	/* GPIO + 0x21 */
+	u8	sint_ode;	/* GPIO + 0x24 */
+	u8	reserved4[3];	/* GPIO + 0x25 */
+	u8	sint_ddr;	/* GPIO + 0x28 */
+	u8	reserved5[3];	/* GPIO + 0x29 */
+	u8	sint_dvo;	/* GPIO + 0x2c */
+	u8	reserved6[3];	/* GPIO + 0x2d */
+	u8	sint_inten;	/* GPIO + 0x30 */
+	u8	reserved7[3];	/* GPIO + 0x31 */
+	u16	sint_itype;	/* GPIO + 0x34 */
+	u16	reserved8;	/* GPIO + 0x36 */
+	u8	gpio_control;	/* GPIO + 0x38 */
+	u8	reserved9[3];	/* GPIO + 0x39 */
+	u8	sint_istat;	/* GPIO + 0x3c */
+	u8	sint_ival;	/* GPIO + 0x3d */
+	u8	bus_errs;	/* GPIO + 0x3e */
+	u8	reserved10;	/* GPIO + 0x3f */
 };
 
 #define MPC52xx_GPIO_PSC_CONFIG_UART_WITHOUT_CD	4
 #define MPC52xx_GPIO_PSC_CONFIG_UART_WITH_CD	5
 #define MPC52xx_GPIO_PCI_DIS			(1<<15)
 
+/* GPIO with WakeUp*/
+struct mpc52xx_gpio_wkup {
+	u8	wkup_gpioe;	/* GPIO_WKUP + 0x00 */
+	u8	reserved1[3];	/* GPIO_WKUP + 0x03 */
+	u8	wkup_ode;	/* GPIO_WKUP + 0x04 */
+	u8	reserved2[3];	/* GPIO_WKUP + 0x05 */
+	u8	wkup_ddr;	/* GPIO_WKUP + 0x08 */
+	u8	reserved3[3];	/* GPIO_WKUP + 0x09 */
+	u8	wkup_dvo;	/* GPIO_WKUP + 0x0C */
+	u8	reserved4[3];	/* GPIO_WKUP + 0x0D */
+	u8	wkup_inten;	/* GPIO_WKUP + 0x10 */
+	u8	reserved5[3];	/* GPIO_WKUP + 0x11 */
+	u8	wkup_iinten;	/* GPIO_WKUP + 0x14 */
+	u8	reserved6[3];	/* GPIO_WKUP + 0x15 */
+	u16	wkup_itype;	/* GPIO_WKUP + 0x18 */
+	u8	reserved7[2];	/* GPIO_WKUP + 0x1A */
+	u8	wkup_maste;	/* GPIO_WKUP + 0x1C */
+	u8	reserved8[3];	/* GPIO_WKUP + 0x1D */
+	u8	wkup_ival;	/* GPIO_WKUP + 0x20 */
+	u8	reserved9[3];	/* GPIO_WKUP + 0x21 */
+	u8	wkup_istat;	/* GPIO_WKUP + 0x24 */
+	u8	reserved10[3];	/* GPIO_WKUP + 0x25 */
+};
+
 /* XLB Bus control */
 struct mpc52xx_xlb {
-	volatile u8 reserved[0x40];
-	volatile u32 config;		/* XLB + 0x40 */
-	volatile u32 version;		/* XLB + 0x44 */
-	volatile u32 status;		/* XLB + 0x48 */
-	volatile u32 int_enable;	/* XLB + 0x4c */
-	volatile u32 addr_capture;	/* XLB + 0x50 */
-	volatile u32 bus_sig_capture;	/* XLB + 0x54 */
-	volatile u32 addr_timeout;	/* XLB + 0x58 */
-	volatile u32 data_timeout;	/* XLB + 0x5c */
-	volatile u32 bus_act_timeout;	/* XLB + 0x60 */
-	volatile u32 master_pri_enable;	/* XLB + 0x64 */
-	volatile u32 master_priority;	/* XLB + 0x68 */
-	volatile u32 base_address;	/* XLB + 0x6c */
-	volatile u32 snoop_window;	/* XLB + 0x70 */
+	u8	reserved[0x40];
+	u32	config;			/* XLB + 0x40 */
+	u32	version;		/* XLB + 0x44 */
+	u32	status;			/* XLB + 0x48 */
+	u32	int_enable;		/* XLB + 0x4c */
+	u32	addr_capture;		/* XLB + 0x50 */
+	u32	bus_sig_capture;	/* XLB + 0x54 */
+	u32	addr_timeout;		/* XLB + 0x58 */
+	u32	data_timeout;		/* XLB + 0x5c */
+	u32	bus_act_timeout;	/* XLB + 0x60 */
+	u32	master_pri_enable;	/* XLB + 0x64 */
+	u32	master_priority;	/* XLB + 0x68 */
+	u32	base_address;		/* XLB + 0x6c */
+	u32	snoop_window;		/* XLB + 0x70 */
 };
 
+#define MPC52xx_XLB_CFG_SNOOP		(1 << 15)
 
 /* Clock Distribution control */
 struct mpc52xx_cdm {
-	volatile u32	jtag_id;	/* MBAR_CDM + 0x00  reg0 read only */
-	volatile u32	rstcfg;		/* MBAR_CDM + 0x04  reg1 read only */
-	volatile u32	breadcrumb;	/* MBAR_CDM + 0x08  reg2 */
-
-	volatile u8	mem_clk_sel;	/* MBAR_CDM + 0x0c  reg3 byte0 */
-	volatile u8	xlb_clk_sel;	/* MBAR_CDM + 0x0d  reg3 byte1 read only */
-	volatile u8	ipb_clk_sel;	/* MBAR_CDM + 0x0e  reg3 byte2 */
-	volatile u8	pci_clk_sel;	/* MBAR_CDM + 0x0f  reg3 byte3 */
-
-	volatile u8	ext_48mhz_en;	/* MBAR_CDM + 0x10  reg4 byte0 */
-	volatile u8	fd_enable;	/* MBAR_CDM + 0x11  reg4 byte1 */
-	volatile u16	fd_counters;	/* MBAR_CDM + 0x12  reg4 byte2,3 */
-
-	volatile u32	clk_enables;	/* MBAR_CDM + 0x14  reg5 */
-
-	volatile u8	osc_disable;	/* MBAR_CDM + 0x18  reg6 byte0 */
-	volatile u8	reserved0[3];	/* MBAR_CDM + 0x19  reg6 byte1,2,3 */
-
-	volatile u8	ccs_sleep_enable;/* MBAR_CDM + 0x1c  reg7 byte0 */
-	volatile u8	osc_sleep_enable;/* MBAR_CDM + 0x1d  reg7 byte1 */
-	volatile u8	reserved1;	/* MBAR_CDM + 0x1e  reg7 byte2 */
-	volatile u8	ccs_qreq_test;	/* MBAR_CDM + 0x1f  reg7 byte3 */
-
-	volatile u8	soft_reset;	/* MBAR_CDM + 0x20  u8 byte0 */
-	volatile u8	no_ckstp;	/* MBAR_CDM + 0x21  u8 byte0 */
-	volatile u8	reserved2[2];	/* MBAR_CDM + 0x22  u8 byte1,2,3 */
-
-	volatile u8	pll_lock;	/* MBAR_CDM + 0x24  reg9 byte0 */
-	volatile u8	pll_looselock;	/* MBAR_CDM + 0x25  reg9 byte1 */
-	volatile u8	pll_sm_lockwin;	/* MBAR_CDM + 0x26  reg9 byte2 */
-	volatile u8	reserved3;	/* MBAR_CDM + 0x27  reg9 byte3 */
-
-	volatile u16	reserved4;	/* MBAR_CDM + 0x28  reg10 byte0,1 */
-	volatile u16	mclken_div_psc1;/* MBAR_CDM + 0x2a  reg10 byte2,3 */
-    
-	volatile u16	reserved5;	/* MBAR_CDM + 0x2c  reg11 byte0,1 */
-	volatile u16	mclken_div_psc2;/* MBAR_CDM + 0x2e  reg11 byte2,3 */
-		
-	volatile u16	reserved6;	/* MBAR_CDM + 0x30  reg12 byte0,1 */
-	volatile u16	mclken_div_psc3;/* MBAR_CDM + 0x32  reg12 byte2,3 */
-    
-	volatile u16	reserved7;	/* MBAR_CDM + 0x34  reg13 byte0,1 */
-	volatile u16	mclken_div_psc6;/* MBAR_CDM + 0x36  reg13 byte2,3 */
+	u32	jtag_id;		/* CDM + 0x00  reg0 read only */
+	u32	rstcfg;			/* CDM + 0x04  reg1 read only */
+	u32	breadcrumb;		/* CDM + 0x08  reg2 */
+
+	u8	mem_clk_sel;		/* CDM + 0x0c  reg3 byte0 */
+	u8	xlb_clk_sel;		/* CDM + 0x0d  reg3 byte1 read only */
+	u8	ipb_clk_sel;		/* CDM + 0x0e  reg3 byte2 */
+	u8	pci_clk_sel;		/* CDM + 0x0f  reg3 byte3 */
+
+	u8	ext_48mhz_en;		/* CDM + 0x10  reg4 byte0 */
+	u8	fd_enable;		/* CDM + 0x11  reg4 byte1 */
+	u16	fd_counters;		/* CDM + 0x12  reg4 byte2,3 */
+
+	u32	clk_enables;		/* CDM + 0x14  reg5 */
+
+	u8	osc_disable;		/* CDM + 0x18  reg6 byte0 */
+	u8	reserved0[3];		/* CDM + 0x19  reg6 byte1,2,3 */
+
+	u8	ccs_sleep_enable;	/* CDM + 0x1c  reg7 byte0 */
+	u8	osc_sleep_enable;	/* CDM + 0x1d  reg7 byte1 */
+	u8	reserved1;		/* CDM + 0x1e  reg7 byte2 */
+	u8	ccs_qreq_test;		/* CDM + 0x1f  reg7 byte3 */
+
+	u8	soft_reset;		/* CDM + 0x20  u8 byte0 */
+	u8	no_ckstp;		/* CDM + 0x21  u8 byte0 */
+	u8	reserved2[2];		/* CDM + 0x22  u8 byte1,2,3 */
+
+	u8	pll_lock;		/* CDM + 0x24  reg9 byte0 */
+	u8	pll_looselock;		/* CDM + 0x25  reg9 byte1 */
+	u8	pll_sm_lockwin;		/* CDM + 0x26  reg9 byte2 */
+	u8	reserved3;		/* CDM + 0x27  reg9 byte3 */
+
+	u16	reserved4;		/* CDM + 0x28  reg10 byte0,1 */
+	u16	mclken_div_psc1;	/* CDM + 0x2a  reg10 byte2,3 */
+
+	u16	reserved5;		/* CDM + 0x2c  reg11 byte0,1 */
+	u16	mclken_div_psc2;	/* CDM + 0x2e  reg11 byte2,3 */
+
+	u16	reserved6;		/* CDM + 0x30  reg12 byte0,1 */
+	u16	mclken_div_psc3;	/* CDM + 0x32  reg12 byte2,3 */
+
+	u16	reserved7;		/* CDM + 0x34  reg13 byte0,1 */
+	u16	mclken_div_psc6;	/* CDM + 0x36  reg13 byte2,3 */
 };
 
 #endif /* __ASSEMBLY__ */
diff -Nru a/include/asm-ppc/mpc52xx_psc.h b/include/asm-ppc/mpc52xx_psc.h
--- a/include/asm-ppc/mpc52xx_psc.h	2004-10-18 14:56:50 -07:00
+++ b/include/asm-ppc/mpc52xx_psc.h	2004-10-18 14:56:50 -07:00
@@ -19,8 +19,8 @@
  * kind, whether express or implied.
  */
 
-#ifndef __MPC52xx_PSC_H__
-#define __MPC52xx_PSC_H__
+#ifndef __ASM_MPC52xx_PSC_H__
+#define __ASM_MPC52xx_PSC_H__
 
 #include <asm/types.h>
 
@@ -95,97 +95,97 @@
 
 /* Structure of the hardware registers */
 struct mpc52xx_psc {
-	volatile u8		mode;		/* PSC + 0x00 */
-	volatile u8		reserved0[3];
-	union {					/* PSC + 0x04 */
-		volatile u16	status;
-		volatile u16	clock_select;
+	u8		mode;		/* PSC + 0x00 */
+	u8		reserved0[3];
+	union {				/* PSC + 0x04 */
+		u16	status;
+		u16	clock_select;
 	} sr_csr;
 #define mpc52xx_psc_status	sr_csr.status
-#define mpc52xx_psc_clock_select	sr_csr.clock_select
-	volatile u16		reserved1;
-	volatile u8		command;	/* PSC + 0x08 */
-volatile u8		reserved2[3];
-	union {					/* PSC + 0x0c */
-		volatile u8	buffer_8;
-		volatile u16	buffer_16;
-		volatile u32	buffer_32;
+#define mpc52xx_psc_clock_select sr_csr.clock_select
+	u16		reserved1;
+	u8		command;	/* PSC + 0x08 */
+	u8		reserved2[3];
+	union {				/* PSC + 0x0c */
+		u8	buffer_8;
+		u16	buffer_16;
+		u32	buffer_32;
 	} buffer;
 #define mpc52xx_psc_buffer_8	buffer.buffer_8
 #define mpc52xx_psc_buffer_16	buffer.buffer_16
 #define mpc52xx_psc_buffer_32	buffer.buffer_32
-	union {					/* PSC + 0x10 */
-		volatile u8	ipcr;
-		volatile u8	acr;
+	union {				/* PSC + 0x10 */
+		u8	ipcr;
+		u8	acr;
 	} ipcr_acr;
 #define mpc52xx_psc_ipcr	ipcr_acr.ipcr
 #define mpc52xx_psc_acr		ipcr_acr.acr
-	volatile u8		reserved3[3];
-	union {					/* PSC + 0x14 */
-		volatile u16	isr;
-		volatile u16	imr;
+	u8		reserved3[3];
+	union {				/* PSC + 0x14 */
+		u16	isr;
+		u16	imr;
 	} isr_imr;
 #define mpc52xx_psc_isr		isr_imr.isr
 #define mpc52xx_psc_imr		isr_imr.imr
-	volatile u16		reserved4;
-	volatile u8		ctur;		/* PSC + 0x18 */
-	volatile u8		reserved5[3];
-	volatile u8		ctlr;		/* PSC + 0x1c */
-	volatile u8		reserved6[3];
-	volatile u16		ccr;		/* PSC + 0x20 */
-	volatile u8		reserved7[14];
-	volatile u8		ivr;		/* PSC + 0x30 */
-	volatile u8		reserved8[3];
-	volatile u8		ip;		/* PSC + 0x34 */
-	volatile u8		reserved9[3];
-	volatile u8		op1;		/* PSC + 0x38 */
-	volatile u8		reserved10[3];
-	volatile u8		op0;		/* PSC + 0x3c */
-	volatile u8		reserved11[3];
-	volatile u32		sicr;		/* PSC + 0x40 */
-	volatile u8		ircr1;		/* PSC + 0x44 */
-	volatile u8		reserved13[3];
-	volatile u8		ircr2;		/* PSC + 0x44 */
-	volatile u8		reserved14[3];
-	volatile u8		irsdr;		/* PSC + 0x4c */
-	volatile u8		reserved15[3];
-	volatile u8		irmdr;		/* PSC + 0x50 */
-	volatile u8		reserved16[3];
-	volatile u8		irfdr;		/* PSC + 0x54 */
-	volatile u8		reserved17[3];
-	volatile u16		rfnum;		/* PSC + 0x58 */
-	volatile u16		reserved18;
-	volatile u16		tfnum;		/* PSC + 0x5c */
-	volatile u16		reserved19;
-	volatile u32		rfdata;		/* PSC + 0x60 */
-	volatile u16		rfstat;		/* PSC + 0x64 */
-	volatile u16		reserved20;
-	volatile u8		rfcntl;		/* PSC + 0x68 */
-	volatile u8		reserved21[5];
-	volatile u16		rfalarm;	/* PSC + 0x6e */
-	volatile u16		reserved22;
-	volatile u16		rfrptr;		/* PSC + 0x72 */
-	volatile u16		reserved23;
-	volatile u16		rfwptr;		/* PSC + 0x76 */
-	volatile u16		reserved24;
-	volatile u16		rflrfptr;	/* PSC + 0x7a */
-	volatile u16		reserved25;
-	volatile u16		rflwfptr;	/* PSC + 0x7e */
-	volatile u32		tfdata;		/* PSC + 0x80 */
-	volatile u16		tfstat;		/* PSC + 0x84 */
-	volatile u16		reserved26;
-	volatile u8		tfcntl;		/* PSC + 0x88 */
-	volatile u8		reserved27[5];
-	volatile u16		tfalarm;	/* PSC + 0x8e */
-	volatile u16		reserved28;
-	volatile u16		tfrptr;		/* PSC + 0x92 */
-	volatile u16		reserved29;
-	volatile u16		tfwptr;		/* PSC + 0x96 */
-	volatile u16		reserved30;
-	volatile u16		tflrfptr;	/* PSC + 0x9a */
-	volatile u16		reserved31;
-	volatile u16		tflwfptr;	/* PSC + 0x9e */
+	u16		reserved4;
+	u8		ctur;		/* PSC + 0x18 */
+	u8		reserved5[3];
+	u8		ctlr;		/* PSC + 0x1c */
+	u8		reserved6[3];
+	u16		ccr;		/* PSC + 0x20 */
+	u8		reserved7[14];
+	u8		ivr;		/* PSC + 0x30 */
+	u8		reserved8[3];
+	u8		ip;		/* PSC + 0x34 */
+	u8		reserved9[3];
+	u8		op1;		/* PSC + 0x38 */
+	u8		reserved10[3];
+	u8		op0;		/* PSC + 0x3c */
+	u8		reserved11[3];
+	u32		sicr;		/* PSC + 0x40 */
+	u8		ircr1;		/* PSC + 0x44 */
+	u8		reserved13[3];
+	u8		ircr2;		/* PSC + 0x44 */
+	u8		reserved14[3];
+	u8		irsdr;		/* PSC + 0x4c */
+	u8		reserved15[3];
+	u8		irmdr;		/* PSC + 0x50 */
+	u8		reserved16[3];
+	u8		irfdr;		/* PSC + 0x54 */
+	u8		reserved17[3];
+	u16		rfnum;		/* PSC + 0x58 */
+	u16		reserved18;
+	u16		tfnum;		/* PSC + 0x5c */
+	u16		reserved19;
+	u32		rfdata;		/* PSC + 0x60 */
+	u16		rfstat;		/* PSC + 0x64 */
+	u16		reserved20;
+	u8		rfcntl;		/* PSC + 0x68 */
+	u8		reserved21[5];
+	u16		rfalarm;	/* PSC + 0x6e */
+	u16		reserved22;
+	u16		rfrptr;		/* PSC + 0x72 */
+	u16		reserved23;
+	u16		rfwptr;		/* PSC + 0x76 */
+	u16		reserved24;
+	u16		rflrfptr;	/* PSC + 0x7a */
+	u16		reserved25;
+	u16		rflwfptr;	/* PSC + 0x7e */
+	u32		tfdata;		/* PSC + 0x80 */
+	u16		tfstat;		/* PSC + 0x84 */
+	u16		reserved26;
+	u8		tfcntl;		/* PSC + 0x88 */
+	u8		reserved27[5];
+	u16		tfalarm;	/* PSC + 0x8e */
+	u16		reserved28;
+	u16		tfrptr;		/* PSC + 0x92 */
+	u16		reserved29;
+	u16		tfwptr;		/* PSC + 0x96 */
+	u16		reserved30;
+	u16		tflrfptr;	/* PSC + 0x9a */
+	u16		reserved31;
+	u16		tflwfptr;	/* PSC + 0x9e */
 };
 
 
-#endif  /* __MPC52xx_PSC_H__ */
+#endif  /* __ASM_MPC52xx_PSC_H__ */
diff -Nru a/include/asm-ppc/mpc8260.h b/include/asm-ppc/mpc8260.h
--- a/include/asm-ppc/mpc8260.h	2004-10-18 14:55:53 -07:00
+++ b/include/asm-ppc/mpc8260.h	2004-10-18 14:55:53 -07:00
@@ -40,6 +40,10 @@
 #include <platforms/pq2ads.h>
 #endif
 
+#ifdef CONFIG_PCI_8260
+#include <syslib/m8260_pci.h>
+#endif
+
 /* Make sure the memory translation stuff is there if PCI not used.
  */
 #ifndef _IO_BASE
diff -Nru a/include/asm-ppc/open_pic.h b/include/asm-ppc/open_pic.h
--- a/include/asm-ppc/open_pic.h	2004-10-18 14:56:28 -07:00
+++ b/include/asm-ppc/open_pic.h	2004-10-18 14:56:28 -07:00
@@ -23,7 +23,7 @@
 
 #define OPENPIC_VEC_TIMER	110	/* and up */
 #define OPENPIC_VEC_IPI		118	/* and up */
-#define OPENPIC_VEC_SPURIOUS	127
+#define OPENPIC_VEC_SPURIOUS	255
 
 /* OpenPIC IRQ controller structure */
 extern struct hw_interrupt_type open_pic;
diff -Nru a/include/asm-ppc/ppcboot.h b/include/asm-ppc/ppcboot.h
--- a/include/asm-ppc/ppcboot.h	2004-10-18 14:57:03 -07:00
+++ b/include/asm-ppc/ppcboot.h	2004-10-18 14:57:03 -07:00
@@ -30,20 +30,6 @@
 #ifndef __ASSEMBLY__
 #include <linux/types.h>
 
-typedef void (interrupt_handler_t)(void *);
-
-typedef struct monitor_functions {
-	int	(*getc)(void);
-	int	(*tstc)(void);
-	void	(*putc)(const char c);
-	void	(*puts)(const char *s);
-	void	(*printf)(const char *fmt, ...);
-	void	(*install_hdlr)(int, interrupt_handler_t *, void *);
-	void	(*free_hdlr)(int);
-	void	*(*malloc)(size_t);
-	void	(*free)(void *);
-} mon_fnc_t;
-
 typedef struct bd_info {
 	unsigned long	bi_memstart;	/* start of DRAM memory */
 	unsigned long	bi_memsize;	/* size	 of DRAM memory in bytes */
@@ -75,7 +61,7 @@
 	unsigned long   bi_pcifreq;     /* PCI Bus Freq, in MHz */
 #endif
 	unsigned long	bi_baudrate;	/* Console Baudrate */
-#if defined(CONFIG_405GP)
+#if defined(CONFIG_4xx)
 	unsigned char	bi_s_version[4];	/* Version of this structure */
 	unsigned char	bi_r_version[32];	/* Version of the ROM (IBM) */
 	unsigned int	bi_procfreq;	/* CPU (Internal) Freq, in Hz */
@@ -86,12 +72,26 @@
 #if defined(CONFIG_HYMOD)
 	hymod_conf_t	bi_hymod_conf;	/* hymod configuration information */
 #endif
-#if defined(CONFIG_EVB64260) || defined(CONFIG_85xx)
-	/* the board has three onboard ethernet ports */
+#if defined(CONFIG_EVB64260) || defined(CONFIG_44x) || defined(CONFIG_85xx)
+	/* second onboard ethernet port */
 	unsigned char	bi_enet1addr[6];
+#endif
+#if defined(CONFIG_EVB64260) || defined(CONFIG_440GX) || defined(CONFIG_85xx)
+	/* third onboard ethernet ports */
 	unsigned char	bi_enet2addr[6];
 #endif
-	mon_fnc_t	*bi_mon_fnc;	/* Pointer to monitor functions	*/
+#if defined(CONFIG_440GX)
+	/* fourth onboard ethernet ports */
+	unsigned char	bi_enet3addr[6];
+#endif
+#if defined(CONFIG_4xx)
+	unsigned int	bi_opbfreq;		/* OB clock in Hz */
+	int		bi_iic_fast[2];		/* Use fast i2c mode */
+#endif
+#if defined(CONFIG_440GX)
+	int		bi_phynum[4];		/* phy mapping */
+	int		bi_phymode[4];		/* phy mode */
+#endif
 } bd_t;
 
 #endif /* __ASSEMBLY__ */
diff -Nru a/include/asm-ppc/ptrace.h b/include/asm-ppc/ptrace.h
--- a/include/asm-ppc/ptrace.h	2004-10-18 14:56:32 -07:00
+++ b/include/asm-ppc/ptrace.h	2004-10-18 14:56:32 -07:00
@@ -47,6 +47,12 @@
 
 #ifndef __ASSEMBLY__
 #define instruction_pointer(regs) ((regs)->nip)
+#ifdef CONFIG_SMP
+extern unsigned long profile_pc(struct pt_regs *regs);
+#else
+#define profile_pc(regs) instruction_pointer(regs)
+#endif
+
 #define user_mode(regs) (((regs)->msr & MSR_PR) != 0)
 
 #define force_successful_syscall_return()   \
diff -Nru a/include/asm-ppc/reg_booke.h b/include/asm-ppc/reg_booke.h
--- a/include/asm-ppc/reg_booke.h	2004-10-18 14:56:49 -07:00
+++ b/include/asm-ppc/reg_booke.h	2004-10-18 14:56:49 -07:00
@@ -123,9 +123,10 @@
 #define SPRN_PID2	0x27A	/* Process ID Register 2 */
 #define SPRN_TLB0CFG	0x2B0	/* TLB 0 Config Register */
 #define SPRN_TLB1CFG	0x2B1	/* TLB 1 Config Register */
+#define SPRN_CCR1	0x378	/* Core Configuration Register 1 */
 #define SPRN_ZPR	0x3B0	/* Zone Protection Register (40x) */
 #define SPRN_MMUCR	0x3B2	/* MMU Control Register */
-#define SPRN_CCR0	0x3B3	/* Core Configuration Register */
+#define SPRN_CCR0	0x3B3	/* Core Configuration Register 0 */
 #define SPRN_SGR	0x3B9	/* Storage Guarded Register */
 #define SPRN_DCWR	0x3BA	/* Data Cache Write-thru Register */
 #define SPRN_SLER	0x3BB	/* Little-endian real mode */
@@ -178,6 +179,9 @@
 #define SPRN_CSRR0	SPRN_SRR2 /* Critical Save and Restore Register 0 */
 #define SPRN_CSRR1	SPRN_SRR3 /* Critical Save and Restore Register 1 */
 #endif
+
+/* Bit definitions for CCR1. */
+#define	CCR1_TCS	0x00000080 /* Timer Clock Select */
 
 /* Bit definitions for the MCSR. */
 #ifdef CONFIG_440A
diff -Nru a/include/asm-ppc/residual.h b/include/asm-ppc/residual.h
--- a/include/asm-ppc/residual.h	2004-10-18 14:56:29 -07:00
+++ b/include/asm-ppc/residual.h	2004-10-18 14:56:29 -07:00
@@ -315,11 +315,20 @@
   } RESIDUAL;
 
 
+/*
+ * Forward declaration - we can't include <linux/pci.h> because it
+ * breaks the boot loader
+ */
+struct pci_dev;
+
 extern RESIDUAL *res;
 extern void print_residual_device_info(void);
 extern PPC_DEVICE *residual_find_device(unsigned long BusMask,
 					unsigned char * DevID, int BaseType,
 					int SubType, int Interface, int n);
+extern int residual_pcidev_irq(struct pci_dev *dev);
+extern void residual_irq_mask(char *irq_edge_mask_lo, char *irq_edge_mask_hi);
+extern unsigned int residual_isapic_addr(void);
 extern PnP_TAG_PACKET *PnP_find_packet(unsigned char *p, unsigned packet_tag,
 				       int n);
 extern PnP_TAG_PACKET *PnP_find_small_vendor_packet(unsigned char *p,
@@ -328,6 +337,13 @@
 extern PnP_TAG_PACKET *PnP_find_large_vendor_packet(unsigned char *p,
 						    unsigned packet_type,
 						    int n);
+
+#ifdef CONFIG_PREP_RESIDUAL
+#define have_residual_data	(res && res->ResidualLength)
+#else
+#define have_residual_data	0
+#endif
+
 #endif /* __ASSEMBLY__ */
 #endif  /* ndef _RESIDUAL_ */
 
diff -Nru a/include/asm-ppc/resource.h b/include/asm-ppc/resource.h
--- a/include/asm-ppc/resource.h	2004-10-18 14:56:28 -07:00
+++ b/include/asm-ppc/resource.h	2004-10-18 14:56:28 -07:00
@@ -36,7 +36,7 @@
 	{ RLIM_INFINITY, RLIM_INFINITY },		\
 	{             0,             0 },		\
 	{      INR_OPEN,     INR_OPEN  },		\
-	{ RLIM_INFINITY, RLIM_INFINITY },		\
+	{   MLOCK_LIMIT,   MLOCK_LIMIT },		\
 	{ RLIM_INFINITY, RLIM_INFINITY },		\
 	{ RLIM_INFINITY, RLIM_INFINITY },		\
 	{ MAX_SIGPENDING, MAX_SIGPENDING },		\
diff -Nru a/include/asm-ppc/semaphore.h b/include/asm-ppc/semaphore.h
--- a/include/asm-ppc/semaphore.h	2004-10-18 14:56:32 -07:00
+++ b/include/asm-ppc/semaphore.h	2004-10-18 14:56:32 -07:00
@@ -29,22 +29,13 @@
 	 */
 	atomic_t count;
 	wait_queue_head_t wait;
-#ifdef WAITQUEUE_DEBUG
-	long __magic;
-#endif
 };
 
-#ifdef WAITQUEUE_DEBUG
-# define __SEM_DEBUG_INIT(name) \
-		, (long)&(name).__magic
-#else
-# define __SEM_DEBUG_INIT(name)
-#endif
-
-#define __SEMAPHORE_INITIALIZER(name, count) \
-	{ ATOMIC_INIT(count), \
-	  __WAIT_QUEUE_HEAD_INITIALIZER((name).wait) \
-	  __SEM_DEBUG_INIT(name) }
+#define __SEMAPHORE_INITIALIZER(name, n)				\
+{									\
+	.count		= ATOMIC_INIT(n),				\
+	.wait		= __WAIT_QUEUE_HEAD_INITIALIZER((name).wait)	\
+}
 
 #define __MUTEX_INITIALIZER(name) \
 	__SEMAPHORE_INITIALIZER(name, 1)
@@ -59,9 +50,6 @@
 {
 	atomic_set(&sem->count, val);
 	init_waitqueue_head(&sem->wait);
-#ifdef WAITQUEUE_DEBUG
-	sem->__magic = (long)&sem->__magic;
-#endif
 }
 
 static inline void init_MUTEX (struct semaphore *sem)
@@ -80,9 +68,6 @@
 
 extern inline void down(struct semaphore * sem)
 {
-#ifdef WAITQUEUE_DEBUG
-	CHECK_MAGIC(sem->__magic);
-#endif
 	might_sleep();
 
 	/*
@@ -97,9 +82,6 @@
 {
 	int ret = 0;
 
-#ifdef WAITQUEUE_DEBUG
-	CHECK_MAGIC(sem->__magic);
-#endif
 	might_sleep();
 
 	if (atomic_dec_return(&sem->count) < 0)
@@ -112,10 +94,6 @@
 {
 	int ret;
 
-#ifdef WAITQUEUE_DEBUG
-	CHECK_MAGIC(sem->__magic);
-#endif
-
 	ret = atomic_dec_if_positive(&sem->count) < 0;
 	smp_wmb();
 	return ret;
@@ -123,10 +101,6 @@
 
 extern inline void up(struct semaphore * sem)
 {
-#ifdef WAITQUEUE_DEBUG
-	CHECK_MAGIC(sem->__magic);
-#endif
-
 	smp_wmb();
 	if (atomic_inc_return(&sem->count) <= 0)
 		__up(sem);
diff -Nru a/include/asm-ppc/serial.h b/include/asm-ppc/serial.h
--- a/include/asm-ppc/serial.h	2004-10-18 14:57:04 -07:00
+++ b/include/asm-ppc/serial.h	2004-10-18 14:57:04 -07:00
@@ -13,17 +13,17 @@
 #elif defined(CONFIG_GEMINI)
 #include <platforms/gemini_serial.h>
 #elif defined(CONFIG_POWERPMC250)
-#include <platforms/powerpmc250_serial.h>
+#include <platforms/powerpmc250.h>
 #elif defined(CONFIG_LOPEC)
-#include <platforms/lopec_serial.h>
+#include <platforms/lopec.h>
 #elif defined(CONFIG_MCPN765)
-#include <platforms/mcpn765_serial.h>
+#include <platforms/mcpn765.h>
 #elif defined(CONFIG_MVME5100)
-#include <platforms/mvme5100_serial.h>
+#include <platforms/mvme5100.h>
 #elif defined(CONFIG_PRPMC750)
-#include <platforms/prpmc750_serial.h>
+#include <platforms/prpmc750.h>
 #elif defined(CONFIG_PRPMC800)
-#include <platforms/prpmc800_serial.h>
+#include <platforms/prpmc800.h>
 #elif defined(CONFIG_SANDPOINT)
 #include <platforms/sandpoint.h>
 #elif defined(CONFIG_SPRUCE)
diff -Nru a/include/asm-ppc/socket.h b/include/asm-ppc/socket.h
--- a/include/asm-ppc/socket.h	2004-10-18 14:56:29 -07:00
+++ b/include/asm-ppc/socket.h	2004-10-18 14:56:29 -07:00
@@ -53,20 +53,4 @@
 
 #define SO_PEERSEC		31
 
-/* Nast libc5 fixup - bletch */
-#if defined(__KERNEL__)
-/* Socket types. */
-#define SOCK_STREAM	1		/* stream (connection) socket	*/
-#define SOCK_DGRAM	2		/* datagram (conn.less) socket	*/
-#define SOCK_RAW	3		/* raw socket			*/
-#define SOCK_RDM	4		/* reliably-delivered message	*/
-#define SOCK_SEQPACKET	5		/* sequential packet socket	*/
-#define SOCK_PACKET	10		/* linux specific way of	*/
-					/* getting packets at the dev	*/
-					/* level.  For writing rarp and	*/
-					/* other similar things on the	*/
-					/* user level.			*/
-#define	SOCK_MAX	(SOCK_PACKET+1)
-#endif /* __KERNEL__ */
-
 #endif /* _ASM_SOCKET_H */
diff -Nru a/include/asm-ppc/thread_info.h b/include/asm-ppc/thread_info.h
--- a/include/asm-ppc/thread_info.h	2004-10-18 14:56:18 -07:00
+++ b/include/asm-ppc/thread_info.h	2004-10-18 14:56:18 -07:00
@@ -65,16 +65,6 @@
  */
 #define THREAD_SIZE		8192	/* 2 pages */
 
-/*
- * Offsets in thread_info structure, used in assembly code
- */
-#define TI_TASK		0
-#define TI_EXECDOMAIN	4
-#define TI_FLAGS	8
-#define TI_LOCAL_FLAGS	12
-#define TI_CPU		16
-#define TI_PREEMPT	20
-
 #define PREEMPT_ACTIVE		0x4000000
 
 /*
diff -Nru a/include/asm-ppc/uaccess.h b/include/asm-ppc/uaccess.h
--- a/include/asm-ppc/uaccess.h	2004-10-18 14:55:54 -07:00
+++ b/include/asm-ppc/uaccess.h	2004-10-18 14:55:54 -07:00
@@ -331,6 +331,8 @@
 	__copy_tofrom_user((void __user *)(to), (from), (size))
 #define __copy_to_user(to, from, size) \
 	__copy_tofrom_user((to), (void __user *)(from), (size))
+#define __copy_to_user_inatomic __copy_to_user
+#define __copy_from_user_inatomic __copy_from_user
 
 extern unsigned long __clear_user(void __user *addr, unsigned long size);
 
diff -Nru a/include/asm-ppc64/8253pit.h b/include/asm-ppc64/8253pit.h
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/include/asm-ppc64/8253pit.h	2004-10-18 14:57:24 -07:00
@@ -0,0 +1,10 @@
+/*
+ * 8253/8254 Programmable Interval Timer
+ */
+
+#ifndef _8253PIT_H
+#define _8253PIT_H
+
+#define PIT_TICK_RATE 	1193182UL
+
+#endif
diff -Nru a/include/asm-ppc64/bitops.h b/include/asm-ppc64/bitops.h
--- a/include/asm-ppc64/bitops.h	2004-10-18 14:57:21 -07:00
+++ b/include/asm-ppc64/bitops.h	2004-10-18 14:57:21 -07:00
@@ -22,6 +22,15 @@
  * it will be a bad memory reference since we want to store in chunks
  * of unsigned long (64 bits here) size.
  *
+ * There are a few little-endian macros used mostly for filesystem bitmaps,
+ * these work on similar bit arrays layouts, but byte-oriented:
+ *
+ *   |7...0|15...8|23...16|31...24|39...32|47...40|55...48|63...56|
+ *
+ * The main difference is that bit 3-5 in the bit number field needs to be
+ * reversed compared to the big-endian bit fields. This can be achieved
+ * by XOR with 0b111000 (0x38).
+ *
  * 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
@@ -306,71 +315,34 @@
 	return (ADDR[nr >> 3] >> (nr & 7)) & 1;
 }
 
+#define test_and_clear_le_bit(nr, addr) \
+	test_and_clear_bit((nr) ^ 0x38, (addr))
+#define test_and_set_le_bit(nr, addr) \
+	test_and_set_bit((nr) ^ 0x38, (addr))
+
 /*
  * non-atomic versions
  */
-static __inline__ void __set_le_bit(unsigned long nr, unsigned long *addr)
-{
-	unsigned char *ADDR = (unsigned char *)addr;
-
-	ADDR += nr >> 3;
-	*ADDR |= 1 << (nr & 0x07);
-}
-
-static __inline__ void __clear_le_bit(unsigned long nr, unsigned long *addr)
-{
-	unsigned char *ADDR = (unsigned char *)addr;
-
-	ADDR += nr >> 3;
-	*ADDR &= ~(1 << (nr & 0x07));
-}
 
-static __inline__ int __test_and_set_le_bit(unsigned long nr, unsigned long *addr)
-{
-	int mask, retval;
-	unsigned char *ADDR = (unsigned char *)addr;
-
-	ADDR += nr >> 3;
-	mask = 1 << (nr & 0x07);
-	retval = (mask & *ADDR) != 0;
-	*ADDR |= mask;
-	return retval;
-}
-
-static __inline__ int __test_and_clear_le_bit(unsigned long nr, unsigned long *addr)
-{
-	int mask, retval;
-	unsigned char *ADDR = (unsigned char *)addr;
-
-	ADDR += nr >> 3;
-	mask = 1 << (nr & 0x07);
-	retval = (mask & *ADDR) != 0;
-	*ADDR &= ~mask;
-	return retval;
-}
+#define __set_le_bit(nr, addr) \
+	__set_bit((nr) ^ 0x38, (addr))
+#define __clear_le_bit(nr, addr) \
+	__clear_bit((nr) ^ 0x38, (addr))
+#define __test_and_clear_le_bit(nr, addr) \
+	__test_and_clear_bit((nr) ^ 0x38, (addr))
+#define __test_and_set_le_bit(nr, addr) \
+	__test_and_set_bit((nr) ^ 0x38, (addr))
 
 #define ext2_set_bit(nr,addr) \
-	__test_and_set_le_bit((nr),(unsigned long*)addr)
+	__test_and_set_le_bit((nr), (unsigned long*)addr)
 #define ext2_clear_bit(nr, addr) \
-	__test_and_clear_le_bit((nr),(unsigned long*)addr)
+	__test_and_clear_le_bit((nr), (unsigned long*)addr)
+
+#define ext2_set_bit_atomic(lock, nr, addr) \
+	test_and_set_le_bit((nr), (unsigned long*)addr)
+#define ext2_clear_bit_atomic(lock, nr, addr) \
+	test_and_clear_le_bit((nr), (unsigned long*)addr)
 
-#define ext2_set_bit_atomic(lock, nr, addr)		\
-	({						\
-		int ret;				\
-		spin_lock(lock);			\
-		ret = ext2_set_bit((nr), (addr));	\
-		spin_unlock(lock);			\
-		ret;					\
-	})
-
-#define ext2_clear_bit_atomic(lock, nr, addr)		\
-	({						\
-		int ret;				\
-		spin_lock(lock);			\
-		ret = ext2_clear_bit((nr), (addr));	\
-		spin_unlock(lock);			\
-		ret;					\
-	})
 
 #define ext2_test_bit(nr, addr)      test_le_bit((nr),(unsigned long*)addr)
 #define ext2_find_first_zero_bit(addr, size) \
diff -Nru a/include/asm-ppc64/bootx.h b/include/asm-ppc64/bootx.h
--- a/include/asm-ppc64/bootx.h	2004-10-18 14:56:32 -07:00
+++ /dev/null	Wed Dec 31 16:00:00 196900
@@ -1,135 +0,0 @@
-/*
- * This file describes the structure passed from the BootX application
- * (for MacOS) when it is used to boot Linux.
- *
- * Written by Benjamin Herrenschmidt.
- */
-
-
-#ifndef __ASM_BOOTX_H__
-#define __ASM_BOOTX_H__
-
-#ifdef macintosh
-#include <Types.h>
-#include "linux_type_defs.h"
-#endif
-
-#ifdef macintosh
-/* All this requires PowerPC alignment */
-#pragma options align=power
-#endif
-
-/* On kernel entry:
- *
- * r3 = 0x426f6f58    ('BooX')
- * r4 = pointer to boot_infos
- * r5 = NULL
- *
- * Data and instruction translation disabled, interrupts
- * disabled, kernel loaded at physical 0x00000000 on PCI
- * machines (will be different on NuBus).
- */
-
-#define BOOT_INFO_VERSION               5
-#define BOOT_INFO_COMPATIBLE_VERSION    1
-
-/* Bit in the architecture flag mask. More to be defined in
-   future versions. Note that either BOOT_ARCH_PCI or
-   BOOT_ARCH_NUBUS is set. The other BOOT_ARCH_NUBUS_xxx are
-   set additionally when BOOT_ARCH_NUBUS is set.
- */
-#define BOOT_ARCH_PCI                   0x00000001UL
-#define BOOT_ARCH_NUBUS                 0x00000002UL
-#define BOOT_ARCH_NUBUS_PDM             0x00000010UL
-#define BOOT_ARCH_NUBUS_PERFORMA        0x00000020UL
-#define BOOT_ARCH_NUBUS_POWERBOOK       0x00000040UL
-
-/*  Maximum number of ranges in phys memory map */
-#define MAX_MEM_MAP_SIZE				26
-
-/* This is the format of an element in the physical memory map. Note that
-   the map is optional and current BootX will only build it for pre-PCI
-   machines */
-typedef struct boot_info_map_entry
-{
-    __u32       physAddr;                /* Physical starting address */
-    __u32       size;                    /* Size in bytes */
-} boot_info_map_entry_t;
-
-
-/* Here are the boot informations that are passed to the bootstrap
- * Note that the kernel arguments and the device tree are appended
- * at the end of this structure. */
-typedef struct boot_infos
-{
-    /* Version of this structure */
-    __u32       version;
-    /* backward compatible down to version: */
-    __u32       compatible_version;
-
-    /* NEW (vers. 2) this holds the current _logical_ base addr of
-       the frame buffer (for use by early boot message) */
-    __u8*       logicalDisplayBase;
-
-    /* NEW (vers. 4) Apple's machine identification */
-    __u32       machineID;
-
-    /* NEW (vers. 4) Detected hw architecture */
-    __u32       architecture;
-
-    /* The device tree (internal addresses relative to the beginning of the tree,
-     * device tree offset relative to the beginning of this structure).
-     * On pre-PCI macintosh (BOOT_ARCH_PCI bit set to 0 in architecture), this
-     * field is 0.
-     */
-    __u32       deviceTreeOffset;        /* Device tree offset */
-    __u32       deviceTreeSize;          /* Size of the device tree */
-
-    /* Some infos about the current MacOS display */
-    __u32       dispDeviceRect[4];       /* left,top,right,bottom */
-    __u32       dispDeviceDepth;         /* (8, 16 or 32) */
-    __u8*       dispDeviceBase;          /* base address (physical) */
-    __u32       dispDeviceRowBytes;      /* rowbytes (in bytes) */
-    __u32       dispDeviceColorsOffset;  /* Colormap (8 bits only) or 0 (*) */
-    /* Optional offset in the registry to the current
-     * MacOS display. (Can be 0 when not detected) */
-     __u32      dispDeviceRegEntryOffset;
-
-    /* Optional pointer to boot ramdisk (offset from this structure) */
-    __u32       ramDisk;
-    __u32       ramDiskSize;             /* size of ramdisk image */
-
-    /* Kernel command line arguments (offset from this structure) */
-    __u32       kernelParamsOffset;
-
-    /* ALL BELOW NEW (vers. 4) */
-
-    /* This defines the physical memory. Valid with BOOT_ARCH_NUBUS flag
-       (non-PCI) only. On PCI, memory is contiguous and it's size is in the
-       device-tree. */
-    boot_info_map_entry_t
-    	        physMemoryMap[MAX_MEM_MAP_SIZE]; /* Where the phys memory is */
-    __u32       physMemoryMapSize;               /* How many entries in map */
-
-
-    /* The framebuffer size (optional, currently 0) */
-    __u32       frameBufferSize;         /* Represents a max size, can be 0. */
-
-    /* NEW (vers. 5) */
-
-    /* Total params size (args + colormap + device tree + ramdisk) */
-    __u32       totalParamsSize;
-
-} boot_infos_t;
-
-/* (*) The format of the colormap is 256 * 3 * 2 bytes. Each color index is represented
- * by 3 short words containing a 16 bits (unsigned) color component.
- * Later versions may contain the gamma table for direct-color devices here.
- */
-#define BOOTX_COLORTABLE_SIZE    (256UL*3UL*2UL)
-
-#ifdef macintosh
-#pragma options align=reset
-#endif
-
-#endif
diff -Nru a/include/asm-ppc64/btext.h b/include/asm-ppc64/btext.h
--- a/include/asm-ppc64/btext.h	2004-10-18 14:56:49 -07:00
+++ b/include/asm-ppc64/btext.h	2004-10-18 14:56:49 -07:00
@@ -7,23 +7,20 @@
 #define __PPC_BTEXT_H
 #ifdef __KERNEL__
 
-#include <asm/bootx.h>
-
 extern void btext_clearscreen(void);
 extern void btext_flushscreen(void);
 
-extern boot_infos_t disp_bi;
 extern int boot_text_mapped;
 
-void btext_setup_display(int width, int height, int depth, int pitch,
-			 unsigned long address);
-void map_boot_text(void);
-void btext_update_display(unsigned long phys, int width, int height,
-			  int depth, int pitch);
+extern int btext_initialize(struct device_node *np);
+
+extern void map_boot_text(void);
+extern void btext_update_display(unsigned long phys, int width, int height,
+				 int depth, int pitch);
 
-void btext_drawchar(char c);
-void btext_drawstring(const char *str);
-void btext_drawhex(unsigned long v);
+extern void btext_drawchar(char c);
+extern void btext_drawstring(const char *str);
+extern void btext_drawhex(unsigned long v);
 
 #endif /* __KERNEL__ */
 #endif /* __PPC_BTEXT_H */
diff -Nru a/include/asm-ppc64/bug.h b/include/asm-ppc64/bug.h
--- a/include/asm-ppc64/bug.h	2004-10-18 14:57:19 -07:00
+++ b/include/asm-ppc64/bug.h	2004-10-18 14:57:19 -07:00
@@ -43,8 +43,6 @@
 		    "i" (__FUNCTION__));			\
 } while (0)
 
-#define PAGE_BUG(page) do { BUG(); } while (0)
-
 #define WARN_ON(x) do {						\
 	__asm__ __volatile__(					\
 		"1:	tdnei %0,0\n"				\
@@ -56,4 +54,10 @@
 } while (0)
 
 #endif
+
+#define HAVE_ARCH_BUG
+#define HAVE_ARCH_BUG_ON
+#define HAVE_ARCH_WARN_ON
+#include <asm-generic/bug.h>
+
 #endif
diff -Nru a/include/asm-ppc64/checksum.h b/include/asm-ppc64/checksum.h
--- a/include/asm-ppc64/checksum.h	2004-10-18 14:56:32 -07:00
+++ b/include/asm-ppc64/checksum.h	2004-10-18 14:56:32 -07:00
@@ -84,10 +84,10 @@
 }
 
 #define csum_partial_copy_from_user(src, dst, len, sum, errp)   \
-        csum_partial_copy_generic((src), (dst), (len), (sum), (errp), 0)
+        csum_partial_copy_generic((src), (dst), (len), (sum), (errp), NULL)
 
 #define csum_partial_copy_nocheck(src, dst, len, sum)   \
-        csum_partial_copy_generic((src), (dst), (len), (sum), 0, 0)
+        csum_partial_copy_generic((src), (dst), (len), (sum), NULL, NULL)
 
 static inline u32 csum_tcpudp_nofold(u32 saddr,
                                      u32 daddr,
diff -Nru a/include/asm-ppc64/dma-mapping.h b/include/asm-ppc64/dma-mapping.h
--- a/include/asm-ppc64/dma-mapping.h	2004-10-18 14:57:04 -07:00
+++ b/include/asm-ppc64/dma-mapping.h	2004-10-18 14:57:04 -07:00
@@ -8,7 +8,6 @@
 #define _ASM_DMA_MAPPING_H
 
 #include <linux/types.h>
-#include <linux/device.h>
 #include <linux/cache.h>
 /* need struct page definitions */
 #include <linux/mm.h>
diff -Nru a/include/asm-ppc64/eeh.h b/include/asm-ppc64/eeh.h
--- a/include/asm-ppc64/eeh.h	2004-10-18 14:57:03 -07:00
+++ b/include/asm-ppc64/eeh.h	2004-10-18 14:57:03 -07:00
@@ -26,26 +26,19 @@
 struct pci_dev;
 struct device_node;
 
-/* I/O addresses are converted to EEH "tokens" such that a driver will cause
- * a bad page fault if the address is used directly (i.e. these addresses are
- * never actually mapped.  Translation between IO <-> EEH region is 1 to 1.
- */
-#define IO_TOKEN_TO_ADDR(token) \
-	(((unsigned long)(token) & ~(0xfUL << REGION_SHIFT)) | \
-	(IO_REGION_ID << REGION_SHIFT))
-
-#define IO_ADDR_TO_TOKEN(addr) \
-	(((unsigned long)(addr) & ~(0xfUL << REGION_SHIFT)) | \
-	(EEH_REGION_ID << REGION_SHIFT))
-
 /* Values for eeh_mode bits in device_node */
 #define EEH_MODE_SUPPORTED	(1<<0)
 #define EEH_MODE_NOCHECK	(1<<1)
 
+#ifdef CONFIG_PPC_PSERIES
 extern void __init eeh_init(void);
-unsigned long eeh_check_failure(void *token, unsigned long val);
-void *eeh_ioremap(unsigned long addr, void *vaddr);
+unsigned long eeh_check_failure(const volatile void __iomem *token, unsigned long val);
+int eeh_dn_check_failure (struct device_node *dn, struct pci_dev *dev);
+void __iomem *eeh_ioremap(unsigned long addr, void __iomem *vaddr);
 void __init pci_addr_cache_build(void);
+#else
+#define eeh_check_failure(token, val) (val)
+#endif
 
 /**
  * eeh_add_device_early
@@ -78,113 +71,107 @@
 /*
  * EEH_POSSIBLE_ERROR() -- test for possible MMIO failure.
  *
- * Order this macro for performance.
- * If EEH is off for a device and it is a memory BAR, ioremap will
- * map it to the IOREGION.  In this case addr == vaddr and since these
- * should be in registers we compare them first.  Next we check for
- * ff's which indicates a (very) possible failure.
- *
  * If this macro yields TRUE, the caller relays to eeh_check_failure()
  * which does further tests out of line.
  */
-#define EEH_POSSIBLE_IO_ERROR(val, type)	((val) == (type)~0)
+#define EEH_POSSIBLE_ERROR(val, type)	((val) == (type)~0)
 
-/* The vaddr will equal the addr if EEH checking is disabled for
- * this device.  This is because eeh_ioremap() will not have
- * remapped to 0xA0, and thus both vaddr and addr will be 0xE0...
+/*
+ * Reads from a device which has been isolated by EEH will return
+ * all 1s.  This macro gives an all-1s value of the given size (in
+ * bytes: 1, 2, or 4) for comparing with the result of a read.
  */
-#define EEH_POSSIBLE_ERROR(addr, vaddr, val, type) \
-		((vaddr) != (addr) && EEH_POSSIBLE_IO_ERROR(val, type))
+#define EEH_IO_ERROR_VALUE(size)	(~0U >> ((4 - (size)) * 8))
 
 /* 
  * MMIO read/write operations with EEH support.
  */
-static inline u8 eeh_readb(void *addr) {
-	volatile u8 *vaddr = (volatile u8 *)IO_TOKEN_TO_ADDR(addr);
+static inline u8 eeh_readb(const volatile void __iomem *addr) {
+	volatile u8 *vaddr = (volatile u8 __force *) addr;
 	u8 val = in_8(vaddr);
-	if (EEH_POSSIBLE_ERROR(addr, vaddr, val, u8))
+	if (EEH_POSSIBLE_ERROR(val, u8))
 		return eeh_check_failure(addr, val);
 	return val;
 }
-static inline void eeh_writeb(u8 val, void *addr) {
-	volatile u8 *vaddr = (volatile u8 *)IO_TOKEN_TO_ADDR(addr);
+static inline void eeh_writeb(u8 val, volatile void __iomem *addr) {
+	volatile u8 *vaddr = (volatile u8 __force *) addr;
 	out_8(vaddr, val);
 }
 
-static inline u16 eeh_readw(void *addr) {
-	volatile u16 *vaddr = (volatile u16 *)IO_TOKEN_TO_ADDR(addr);
+static inline u16 eeh_readw(const volatile void __iomem *addr) {
+	volatile u16 *vaddr = (volatile u16 __force *) addr;
 	u16 val = in_le16(vaddr);
-	if (EEH_POSSIBLE_ERROR(addr, vaddr, val, u16))
+	if (EEH_POSSIBLE_ERROR(val, u16))
 		return eeh_check_failure(addr, val);
 	return val;
 }
-static inline void eeh_writew(u16 val, void *addr) {
-	volatile u16 *vaddr = (volatile u16 *)IO_TOKEN_TO_ADDR(addr);
+static inline void eeh_writew(u16 val, volatile void __iomem *addr) {
+	volatile u16 *vaddr = (volatile u16 __force *) addr;
 	out_le16(vaddr, val);
 }
-static inline u16 eeh_raw_readw(void *addr) {
-	volatile u16 *vaddr = (volatile u16 *)IO_TOKEN_TO_ADDR(addr);
+static inline u16 eeh_raw_readw(const volatile void __iomem *addr) {
+	volatile u16 *vaddr = (volatile u16 __force *) addr;
 	u16 val = in_be16(vaddr);
-	if (EEH_POSSIBLE_ERROR(addr, vaddr, val, u16))
+	if (EEH_POSSIBLE_ERROR(val, u16))
 		return eeh_check_failure(addr, val);
 	return val;
 }
-static inline void eeh_raw_writew(u16 val, void *addr) {
-	volatile u16 *vaddr = (volatile u16 *)IO_TOKEN_TO_ADDR(addr);
+static inline void eeh_raw_writew(u16 val, volatile void __iomem *addr) {
+	volatile u16 *vaddr = (volatile u16 __force *) addr;
 	out_be16(vaddr, val);
 }
 
-static inline u32 eeh_readl(void *addr) {
-	volatile u32 *vaddr = (volatile u32 *)IO_TOKEN_TO_ADDR(addr);
+static inline u32 eeh_readl(const volatile void __iomem *addr) {
+	volatile u32 *vaddr = (volatile u32 __force *) addr;
 	u32 val = in_le32(vaddr);
-	if (EEH_POSSIBLE_ERROR(addr, vaddr, val, u32))
+	if (EEH_POSSIBLE_ERROR(val, u32))
 		return eeh_check_failure(addr, val);
 	return val;
 }
-static inline void eeh_writel(u32 val, void *addr) {
-	volatile u32 *vaddr = (volatile u32 *)IO_TOKEN_TO_ADDR(addr);
+static inline void eeh_writel(u32 val, volatile void __iomem *addr) {
+	volatile u32 *vaddr = (volatile u32 __force *) addr;
 	out_le32(vaddr, val);
 }
-static inline u32 eeh_raw_readl(void *addr) {
-	volatile u32 *vaddr = (volatile u32 *)IO_TOKEN_TO_ADDR(addr);
+static inline u32 eeh_raw_readl(const volatile void __iomem *addr) {
+	volatile u32 *vaddr = (volatile u32 __force *) addr;
 	u32 val = in_be32(vaddr);
-	if (EEH_POSSIBLE_ERROR(addr, vaddr, val, u32))
+	if (EEH_POSSIBLE_ERROR(val, u32))
 		return eeh_check_failure(addr, val);
 	return val;
 }
-static inline void eeh_raw_writel(u32 val, void *addr) {
-	volatile u32 *vaddr = (volatile u32 *)IO_TOKEN_TO_ADDR(addr);
+static inline void eeh_raw_writel(u32 val, volatile void __iomem *addr) {
+	volatile u32 *vaddr = (volatile u32 __force *) addr;
 	out_be32(vaddr, val);
 }
 
-static inline u64 eeh_readq(void *addr) {
-	volatile u64 *vaddr = (volatile u64 *)IO_TOKEN_TO_ADDR(addr);
+static inline u64 eeh_readq(const volatile void __iomem *addr) {
+	volatile u64 *vaddr = (volatile u64 __force *) addr;
 	u64 val = in_le64(vaddr);
-	if (EEH_POSSIBLE_ERROR(addr, vaddr, val, u64))
+	if (EEH_POSSIBLE_ERROR(val, u64))
 		return eeh_check_failure(addr, val);
 	return val;
 }
-static inline void eeh_writeq(u64 val, void *addr) {
-	volatile u64 *vaddr = (volatile u64 *)IO_TOKEN_TO_ADDR(addr);
+static inline void eeh_writeq(u64 val, volatile void __iomem *addr) {
+	volatile u64 *vaddr = (volatile u64 __force *) addr;
 	out_le64(vaddr, val);
 }
-static inline u64 eeh_raw_readq(void *addr) {
-	volatile u64 *vaddr = (volatile u64 *)IO_TOKEN_TO_ADDR(addr);
+static inline u64 eeh_raw_readq(const volatile void __iomem *addr) {
+	volatile u64 *vaddr = (volatile u64 __force *) addr;
 	u64 val = in_be64(vaddr);
-	if (EEH_POSSIBLE_ERROR(addr, vaddr, val, u64))
+	if (EEH_POSSIBLE_ERROR(val, u64))
 		return eeh_check_failure(addr, val);
 	return val;
 }
-static inline void eeh_raw_writeq(u64 val, void *addr) {
-	volatile u64 *vaddr = (volatile u64 *)IO_TOKEN_TO_ADDR(addr);
+static inline void eeh_raw_writeq(u64 val, volatile void __iomem *addr) {
+	volatile u64 *vaddr = (volatile u64 __force *) addr;
 	out_be64(vaddr, val);
 }
 
 #define EEH_CHECK_ALIGN(v,a) \
 	((((unsigned long)(v)) & ((a) - 1)) == 0)
 
-static inline void eeh_memset_io(void *addr, int c, unsigned long n) {
-	void *vaddr = (void *)IO_TOKEN_TO_ADDR(addr);
+static inline void eeh_memset_io(volatile void __iomem *addr, int c, unsigned long n) {
+	void *vaddr = (void __force *) addr;
 	u32 lc = c;
 	lc |= lc << 8;
 	lc |= lc << 16;
@@ -206,9 +193,9 @@
 	}
 	__asm__ __volatile__ ("sync" : : : "memory");
 }
-static inline void eeh_memcpy_fromio(void *dest, void *src, unsigned long n) {
-	void *vsrc = (void *)IO_TOKEN_TO_ADDR(src);
-	void *vsrcsave = vsrc, *destsave = dest, *srcsave = src;
+static inline void eeh_memcpy_fromio(void *dest, const volatile void __iomem *src, unsigned long n) {
+	void *vsrc = (void __force *) src;
+	void *destsave = dest;
 	unsigned long nsave = n;
 
 	while(n && (!EEH_CHECK_ALIGN(vsrc, 4) || !EEH_CHECK_ALIGN(dest, 4))) {
@@ -238,14 +225,13 @@
 	 * were copied. Check all four bytes.
 	 */
 	if ((nsave >= 4) &&
-		(EEH_POSSIBLE_ERROR(srcsave, vsrcsave, (*((u32 *) destsave+nsave-4)),
-				    u32))) {
-		eeh_check_failure(srcsave, (*((u32 *) destsave+nsave-4)));
+		(EEH_POSSIBLE_ERROR((*((u32 *) destsave+nsave-4)), u32))) {
+		eeh_check_failure(src, (*((u32 *) destsave+nsave-4)));
 	}
 }
 
-static inline void eeh_memcpy_toio(void *dest, void *src, unsigned long n) {
-	void *vdest = (void *)IO_TOKEN_TO_ADDR(dest);
+static inline void eeh_memcpy_toio(volatile void __iomem *dest, const void *src, unsigned long n) {
+	void *vdest = (void __force *) dest;
 
 	while(n && (!EEH_CHECK_ALIGN(vdest, 4) || !EEH_CHECK_ALIGN(src, 4))) {
 		*((volatile u8 *)vdest) = *((u8 *)src);
@@ -279,8 +265,8 @@
 	if (!_IO_IS_VALID(port))
 		return ~0;
 	val = in_8((u8 *)(port+pci_io_base));
-	if (EEH_POSSIBLE_IO_ERROR(val, u8))
-		return eeh_check_failure((void*)(port), val);
+	if (EEH_POSSIBLE_ERROR(val, u8))
+		return eeh_check_failure((void __iomem *)(port), val);
 	return val;
 }
 
@@ -294,8 +280,8 @@
 	if (!_IO_IS_VALID(port))
 		return ~0;
 	val = in_le16((u16 *)(port+pci_io_base));
-	if (EEH_POSSIBLE_IO_ERROR(val, u16))
-		return eeh_check_failure((void*)(port), val);
+	if (EEH_POSSIBLE_ERROR(val, u16))
+		return eeh_check_failure((void __iomem *)(port), val);
 	return val;
 }
 
@@ -309,8 +295,8 @@
 	if (!_IO_IS_VALID(port))
 		return ~0;
 	val = in_le32((u32 *)(port+pci_io_base));
-	if (EEH_POSSIBLE_IO_ERROR(val, u32))
-		return eeh_check_failure((void*)(port), val);
+	if (EEH_POSSIBLE_ERROR(val, u32))
+		return eeh_check_failure((void __iomem *)(port), val);
 	return val;
 }
 
@@ -322,20 +308,20 @@
 /* in-string eeh macros */
 static inline void eeh_insb(unsigned long port, void * buf, int ns) {
 	_insb((u8 *)(port+pci_io_base), buf, ns);
-	if (EEH_POSSIBLE_IO_ERROR((*(((u8*)buf)+ns-1)), u8))
-		eeh_check_failure((void*)(port), *(u8*)buf);
+	if (EEH_POSSIBLE_ERROR((*(((u8*)buf)+ns-1)), u8))
+		eeh_check_failure((void __iomem *)(port), *(u8*)buf);
 }
 
 static inline void eeh_insw_ns(unsigned long port, void * buf, int ns) {
 	_insw_ns((u16 *)(port+pci_io_base), buf, ns);
-	if (EEH_POSSIBLE_IO_ERROR((*(((u16*)buf)+ns-1)), u16))
-		eeh_check_failure((void*)(port), *(u16*)buf);
+	if (EEH_POSSIBLE_ERROR((*(((u16*)buf)+ns-1)), u16))
+		eeh_check_failure((void __iomem *)(port), *(u16*)buf);
 }
 
 static inline void eeh_insl_ns(unsigned long port, void * buf, int nl) {
 	_insl_ns((u32 *)(port+pci_io_base), buf, nl);
-	if (EEH_POSSIBLE_IO_ERROR((*(((u32*)buf)+nl-1)), u32))
-		eeh_check_failure((void*)(port), *(u32*)buf);
+	if (EEH_POSSIBLE_ERROR((*(((u32*)buf)+nl-1)), u32))
+		eeh_check_failure((void __iomem *)(port), *(u32*)buf);
 }
 
 #endif /* _PPC64_EEH_H */
diff -Nru a/include/asm-ppc64/hardirq.h b/include/asm-ppc64/hardirq.h
--- a/include/asm-ppc64/hardirq.h	2004-10-18 14:56:17 -07:00
+++ b/include/asm-ppc64/hardirq.h	2004-10-18 14:56:17 -07:00
@@ -1,4 +1,3 @@
-#ifdef __KERNEL__
 #ifndef __ASM_HARDIRQ_H
 #define __ASM_HARDIRQ_H
 
@@ -43,20 +42,6 @@
 #define SOFTIRQ_SHIFT	(PREEMPT_SHIFT + PREEMPT_BITS)
 #define HARDIRQ_SHIFT	(SOFTIRQ_SHIFT + SOFTIRQ_BITS)
 
-#define __HARDIRQ_MASK(x)	((1UL << (x))-1)
-
-#define PREEMPT_MASK	(__HARDIRQ_MASK(PREEMPT_BITS) << PREEMPT_SHIFT)
-#define SOFTIRQ_MASK	(__HARDIRQ_MASK(SOFTIRQ_BITS) << SOFTIRQ_SHIFT)
-#define HARDIRQ_MASK	(__HARDIRQ_MASK(HARDIRQ_BITS) << HARDIRQ_SHIFT)
-
-#define hardirq_count()	(preempt_count() & HARDIRQ_MASK)
-#define softirq_count()	(preempt_count() & SOFTIRQ_MASK)
-#define irq_count()	(preempt_count() & (HARDIRQ_MASK | SOFTIRQ_MASK))
-
-#define PREEMPT_OFFSET	(1UL << PREEMPT_SHIFT)
-#define SOFTIRQ_OFFSET	(1UL << SOFTIRQ_SHIFT)
-#define HARDIRQ_OFFSET	(1UL << HARDIRQ_SHIFT)
-
 /*
  * The hardirq mask has to be large enough to have
  * space for potentially all IRQ sources in the system
@@ -66,29 +51,7 @@
 # error HARDIRQ_BITS is too low!
 #endif
 
-/*
- * Are we doing bottom half or hardware interrupt processing?
- * Are we in a softirq context? Interrupt context?
- */
-#define in_irq()		(hardirq_count())
-#define in_softirq()		(softirq_count())
-#define in_interrupt()		(irq_count())
-
-
-#define hardirq_trylock()	(!in_interrupt())
-#define hardirq_endlock()	do { } while (0)
-
 #define irq_enter()		(preempt_count() += HARDIRQ_OFFSET)
-
-#ifdef CONFIG_PREEMPT
-# define in_atomic()	((preempt_count() & ~PREEMPT_ACTIVE) != kernel_locked())
-# define preemptible()	(preempt_count() == 0 && !irqs_disabled())
-# define IRQ_EXIT_OFFSET (HARDIRQ_OFFSET-1)
-#else
-# define in_atomic()	(preempt_count() != 0)
-# define preemptible()	0
-# define IRQ_EXIT_OFFSET HARDIRQ_OFFSET
-#endif
 #define irq_exit()							\
 do {									\
 		preempt_count() -= IRQ_EXIT_OFFSET;			\
@@ -97,12 +60,4 @@
 		preempt_enable_no_resched();				\
 } while (0)
 
-#ifndef CONFIG_SMP
-# define synchronize_irq(irq)	barrier()
-#else
-  extern void synchronize_irq(unsigned int irq);
-#endif /* CONFIG_SMP */
-
-#endif /* __KERNEL__ */
-	
 #endif /* __ASM_HARDIRQ_H */
diff -Nru a/include/asm-ppc64/hvcall.h b/include/asm-ppc64/hvcall.h
--- a/include/asm-ppc64/hvcall.h	2004-10-18 14:55:54 -07:00
+++ b/include/asm-ppc64/hvcall.h	2004-10-18 14:55:54 -07:00
@@ -101,10 +101,12 @@
 #define H_VIO_SIGNAL		0x104
 #define H_SEND_CRQ		0x108
 #define H_COPY_RDMA             0x110
-#define H_POLL_PENDING	        0x1D8
+#define H_STUFF_TCE		0x138
+#define H_PUT_TCE_INDIRECT	0x13C
 #define H_VTERM_PARTNER_INFO	0x150
-#define H_REGISTER_VTERM		0x154
-#define H_FREE_VTERM			0x158
+#define H_REGISTER_VTERM	0x154
+#define H_FREE_VTERM		0x158
+#define H_POLL_PENDING	        0x1D8
 
 /* plpar_hcall() -- Generic call interface using above opcodes
  *
diff -Nru a/include/asm-ppc64/hvconsole.h b/include/asm-ppc64/hvconsole.h
--- a/include/asm-ppc64/hvconsole.h	2004-10-18 14:56:33 -07:00
+++ b/include/asm-ppc64/hvconsole.h	2004-10-18 14:56:33 -07:00
@@ -22,9 +22,19 @@
 #ifndef _PPC64_HVCONSOLE_H
 #define _PPC64_HVCONSOLE_H
 
-extern int hvc_get_chars(int index, char *buf, int count);
-extern int hvc_put_chars(int index, const char *buf, int count);
-extern int hvc_count(int *start_termno);
+/*
+ * This is the max number of console adapters that can/will be found as
+ * console devices on first stage console init.  Any number beyond this range
+ * can't be used as a console device but is still a valid tty device.
+ */
+#define MAX_NR_HVC_CONSOLES	16
 
-#endif /* _PPC64_HVCONSOLE_H */
+extern int hvc_get_chars(uint32_t vtermno, char *buf, int count);
+extern int hvc_put_chars(uint32_t vtermno, const char *buf, int count);
+
+/* Early discovery of console adapters. */
+extern int hvc_find_vtys(void);
 
+/* Implemented by a console driver */
+extern int hvc_instantiate(uint32_t vtermno, int index);
+#endif /* _PPC64_HVCONSOLE_H */
diff -Nru a/include/asm-ppc64/hvcserver.h b/include/asm-ppc64/hvcserver.h
--- a/include/asm-ppc64/hvcserver.h	2004-10-18 14:56:28 -07:00
+++ b/include/asm-ppc64/hvcserver.h	2004-10-18 14:56:28 -07:00
@@ -27,18 +27,31 @@
 /* Converged Location Code length */
 #define HVCS_CLC_LENGTH	79
 
+/**
+ * hvcs_partner_info - an element in a list of partner info
+ * @node: list_head denoting this partner_info struct's position in the list of
+ *	partner info.
+ * @unit_address: The partner unit address of this entry.
+ * @partition_ID: The partner partition ID of this entry.
+ * @location_code: The converged location code of this entry + 1 char for the
+ *	null-term.
+ *
+ * This structure outlines the format that partner info is presented to a caller
+ * of the hvcs partner info fetching functions.  These are strung together into
+ * a list using linux kernel lists.
+ */
 struct hvcs_partner_info {
 	struct list_head node;
-	unsigned int unit_address;
-	unsigned int partition_ID;
+	uint32_t unit_address;
+	uint32_t partition_ID;
 	char location_code[HVCS_CLC_LENGTH + 1]; /* CLC + 1 null-term char */
 };
 
 extern int hvcs_free_partner_info(struct list_head *head);
-extern int hvcs_get_partner_info(unsigned int unit_address,
+extern int hvcs_get_partner_info(uint32_t unit_address,
 		struct list_head *head, unsigned long *pi_buff);
-extern int hvcs_register_connection(unsigned int unit_address,
-		unsigned int p_partition_ID, unsigned int p_unit_address);
-extern int hvcs_free_connection(unsigned int unit_address);
+extern int hvcs_register_connection(uint32_t unit_address,
+		uint32_t p_partition_ID, uint32_t p_unit_address);
+extern int hvcs_free_connection(uint32_t unit_address);
 
 #endif /* _PPC64_HVCSERVER_H */
diff -Nru a/include/asm-ppc64/iSeries/iSeries_io.h b/include/asm-ppc64/iSeries/iSeries_io.h
--- a/include/asm-ppc64/iSeries/iSeries_io.h	2004-10-18 14:57:04 -07:00
+++ b/include/asm-ppc64/iSeries/iSeries_io.h	2004-10-18 14:57:04 -07:00
@@ -31,16 +31,16 @@
 /*   Created December 28, 2000                                          */
 /* End Change Activity                                                  */
 /************************************************************************/
-extern u8   iSeries_Read_Byte(void* IoAddress);
-extern u16  iSeries_Read_Word(void* IoAddress);
-extern u32  iSeries_Read_Long(void* IoAddress);
-extern void iSeries_Write_Byte(u8  IoData,void* IoAddress);
-extern void iSeries_Write_Word(u16 IoData,void* IoAddress);
-extern void iSeries_Write_Long(u32 IoData,void* IoAddress);
+extern u8   iSeries_Read_Byte(const volatile void __iomem * IoAddress);
+extern u16  iSeries_Read_Word(const volatile void __iomem * IoAddress);
+extern u32  iSeries_Read_Long(const volatile void __iomem * IoAddress);
+extern void iSeries_Write_Byte(u8  IoData, volatile void __iomem * IoAddress);
+extern void iSeries_Write_Word(u16 IoData, volatile void __iomem * IoAddress);
+extern void iSeries_Write_Long(u32 IoData, volatile void __iomem * IoAddress);
 
-extern void* iSeries_memset_io(void *dest, char x, size_t n);
-extern void* iSeries_memcpy_toio(void *dest, void *source, size_t n);
-extern void* iSeries_memcpy_fromio(void *dest, void *source, size_t n);
+extern void iSeries_memset_io(volatile void __iomem *dest, char x, size_t n);
+extern void iSeries_memcpy_toio(volatile void __iomem *dest, void *source, size_t n);
+extern void iSeries_memcpy_fromio(void *dest, const volatile void __iomem *source, size_t n);
 
 #endif /* CONFIG_PPC_ISERIES */
 #endif /* _ISERIES_IO_H */
diff -Nru a/include/asm-ppc64/io.h b/include/asm-ppc64/io.h
--- a/include/asm-ppc64/io.h	2004-10-18 14:57:04 -07:00
+++ b/include/asm-ppc64/io.h	2004-10-18 14:57:04 -07:00
@@ -9,6 +9,7 @@
  */
 
 #include <linux/config.h>
+#include <linux/compiler.h>
 #include <asm/page.h>
 #include <asm/byteorder.h>
 #ifdef CONFIG_PPC_ISERIES 
@@ -17,6 +18,8 @@
 #include <asm/memory.h>
 #include <asm/delay.h>
 
+#include <asm-generic/iomap.h>
+
 #define __ide_mm_insw(p, a, c) _insw_ns((volatile u16 *)(p), (a), (c))
 #define __ide_mm_insl(p, a, c) _insl_ns((volatile u32 *)(p), (a), (c))
 #define __ide_mm_outsw(p, a, c) _outsw_ns((volatile u16 *)(p), (a), (c))
@@ -41,21 +44,22 @@
 #define __raw_writew(v, addr)   { BUG(); 0; }
 #define __raw_writel(v, addr)   { BUG(); 0; }
 #define __raw_writeq(v, addr)   { BUG(); 0; }
-#define readb(addr)		iSeries_Read_Byte((void*)(addr))  
-#define readw(addr)		iSeries_Read_Word((void*)(addr))  
-#define readl(addr)		iSeries_Read_Long((void*)(addr))
-#define writeb(data, addr)	iSeries_Write_Byte(data,((void*)(addr)))
-#define writew(data, addr)	iSeries_Write_Word(data,((void*)(addr)))
-#define writel(data, addr)	iSeries_Write_Long(data,((void*)(addr)))
-#define memset_io(a,b,c)	iSeries_memset_io((void *)(a),(b),(c))
-#define memcpy_fromio(a,b,c)	iSeries_memcpy_fromio((void *)(a), (void *)(b), (c))
-#define memcpy_toio(a,b,c)	iSeries_memcpy_toio((void *)(a), (void *)(b), (c))
-#define inb(addr)		readb(((unsigned long)(addr)))  
-#define inw(addr)		readw(((unsigned long)(addr)))  
-#define inl(addr)		readl(((unsigned long)(addr)))
-#define outb(data,addr)		writeb(data,((unsigned long)(addr)))  
-#define outw(data,addr)		writew(data,((unsigned long)(addr)))  
-#define outl(data,addr)		writel(data,((unsigned long)(addr)))
+#define readb(addr)		iSeries_Read_Byte(addr)
+#define readw(addr)		iSeries_Read_Word(addr)
+#define readl(addr)		iSeries_Read_Long(addr)
+#define writeb(data, addr)	iSeries_Write_Byte((data),(addr))
+#define writew(data, addr)	iSeries_Write_Word((data),(addr))
+#define writel(data, addr)	iSeries_Write_Long((data),(addr))
+#define memset_io(a,b,c)	iSeries_memset_io((a),(b),(c))
+#define memcpy_fromio(a,b,c)	iSeries_memcpy_fromio((a), (b), (c))
+#define memcpy_toio(a,b,c)	iSeries_memcpy_toio((a), (b), (c))
+
+#define inb(addr)		readb(((void __iomem *)(long)(addr)))
+#define inw(addr)		readw(((void __iomem *)(long)(addr)))
+#define inl(addr)		readl(((void __iomem *)(long)(addr)))
+#define outb(data,addr)		writeb(data,((void __iomem *)(long)(addr)))
+#define outw(data,addr)		writew(data,((void __iomem *)(long)(addr)))
+#define outl(data,addr)		writel(data,((void __iomem *)(long)(addr)))
 /*
  * The *_ns versions below don't do byte-swapping.
  * Neither do the standard versions now, these are just here
@@ -64,25 +68,50 @@
 #define insw_ns(port, buf, ns)	_insw_ns((u16 *)((port)+pci_io_base), (buf), (ns))
 #define insl_ns(port, buf, nl)	_insl_ns((u32 *)((port)+pci_io_base), (buf), (nl))
 #else
-#define __raw_readb(addr)       (*(volatile unsigned char *)(addr))
-#define __raw_readw(addr)       (*(volatile unsigned short *)(addr))
-#define __raw_readl(addr)       (*(volatile unsigned int *)(addr))
-#define __raw_readq(addr)       (*(volatile unsigned long *)(addr))
-#define __raw_writeb(v, addr)   (*(volatile unsigned char *)(addr) = (v))
-#define __raw_writew(v, addr)   (*(volatile unsigned short *)(addr) = (v))
-#define __raw_writel(v, addr)   (*(volatile unsigned int *)(addr) = (v))
-#define __raw_writeq(v, addr)   (*(volatile unsigned long *)(addr) = (v))
-#define readb(addr)		eeh_readb((void*)(addr))  
-#define readw(addr)		eeh_readw((void*)(addr))  
-#define readl(addr)		eeh_readl((void*)(addr))
-#define readq(addr)		eeh_readq((void*)(addr))
-#define writeb(data, addr)	eeh_writeb((data), ((void*)(addr)))
-#define writew(data, addr)	eeh_writew((data), ((void*)(addr)))
-#define writel(data, addr)	eeh_writel((data), ((void*)(addr)))
-#define writeq(data, addr)	eeh_writeq((data), ((void*)(addr)))
-#define memset_io(a,b,c)	eeh_memset_io((void *)(a),(b),(c))
-#define memcpy_fromio(a,b,c)	eeh_memcpy_fromio((a),(void *)(b),(c))
-#define memcpy_toio(a,b,c)	eeh_memcpy_toio((void *)(a),(b),(c))
+
+static inline unsigned char __raw_readb(const volatile void __iomem *addr)
+{
+	return *(volatile unsigned char __force *)addr;
+}
+static inline unsigned short __raw_readw(const volatile void __iomem *addr)
+{
+	return *(volatile unsigned short __force *)addr;
+}
+static inline unsigned int __raw_readl(const volatile void __iomem *addr)
+{
+	return *(volatile unsigned int __force *)addr;
+}
+static inline unsigned long __raw_readq(const volatile void __iomem *addr)
+{
+	return *(volatile unsigned long __force *)addr;
+}
+static inline void __raw_writeb(unsigned char v, volatile void __iomem *addr)
+{
+	*(volatile unsigned char __force *)addr = v;
+}
+static inline void __raw_writew(unsigned short v, volatile void __iomem *addr)
+{
+	*(volatile unsigned short __force *)addr = v;
+}
+static inline void __raw_writel(unsigned int v, volatile void __iomem *addr)
+{
+	*(volatile unsigned int __force *)addr = v;
+}
+static inline void __raw_writeq(unsigned long v, volatile void __iomem *addr)
+{
+	*(volatile unsigned long __force *)addr = v;
+}
+#define readb(addr)		eeh_readb(addr)
+#define readw(addr)		eeh_readw(addr)
+#define readl(addr)		eeh_readl(addr)
+#define readq(addr)		eeh_readq(addr)
+#define writeb(data, addr)	eeh_writeb((data), (addr))
+#define writew(data, addr)	eeh_writew((data), (addr))
+#define writel(data, addr)	eeh_writel((data), (addr))
+#define writeq(data, addr)	eeh_writeq((data), (addr))
+#define memset_io(a,b,c)	eeh_memset_io((a),(b),(c))
+#define memcpy_fromio(a,b,c)	eeh_memcpy_fromio((a),(b),(c))
+#define memcpy_toio(a,b,c)	eeh_memcpy_toio((a),(b),(c))
 #define inb(port)		eeh_inb((unsigned long)port)
 #define outb(val, port)		eeh_outb(val, (unsigned long)port)
 #define inw(port)		eeh_inw((unsigned long)port)
@@ -149,7 +178,7 @@
 #ifdef __KERNEL__
 extern int __ioremap_explicit(unsigned long p_addr, unsigned long v_addr,
 		     	      unsigned long size, unsigned long flags);
-extern void *__ioremap(unsigned long address, unsigned long size,
+extern void __iomem *__ioremap(unsigned long address, unsigned long size,
 		       unsigned long flags);
 
 /**
@@ -163,11 +192,11 @@
  * address is not guaranteed to be usable directly as a virtual
  * address.
  */
-extern void *ioremap(unsigned long address, unsigned long size);
+extern void __iomem *ioremap(unsigned long address, unsigned long size);
 
 #define ioremap_nocache(addr, size)	ioremap((addr), (size))
-extern int iounmap_explicit(void *addr, unsigned long size);
-extern void iounmap(void *addr);
+extern int iounmap_explicit(volatile void __iomem *addr, unsigned long size);
+extern void iounmap(volatile void __iomem *addr);
 extern void * reserve_phb_iospace(unsigned long size);
 
 /**
@@ -377,7 +406,7 @@
  *	address should have been obtained by ioremap.
  *	Returns 1 on a match.
  */
-static inline int check_signature(unsigned long io_addr,
+static inline int check_signature(const volatile void __iomem * io_addr,
 	const unsigned char *signature, int length)
 {
 	int retval = 0;
diff -Nru a/include/asm-ppc64/iommu.h b/include/asm-ppc64/iommu.h
--- a/include/asm-ppc64/iommu.h	2004-10-18 14:56:48 -07:00
+++ b/include/asm-ppc64/iommu.h	2004-10-18 14:56:48 -07:00
@@ -104,16 +104,19 @@
 
 struct scatterlist;
 
-#ifdef CONFIG_PPC_PSERIES
+#ifdef CONFIG_PPC_MULTIPLATFORM
+
 /* Walks all buses and creates iommu tables */
 extern void iommu_setup_pSeries(void);
-extern void iommu_setup_pmac(void);
+extern void iommu_setup_u3(void);
 
 /* Creates table for an individual device node */
 extern void iommu_devnode_init(struct device_node *dn);
-#endif /* CONFIG_PPC_PSERIES */
+
+#endif /* CONFIG_PPC_MULTIPLATFORM */
 
 #ifdef CONFIG_PPC_ISERIES
+
 /* Walks all buses and creates iommu tables */
 extern void iommu_setup_iSeries(void);
 
@@ -123,8 +126,8 @@
 struct iSeries_Device_Node;
 /* Creates table for an individual device node */
 extern void iommu_devnode_init(struct iSeries_Device_Node *dn);
-#endif /* CONFIG_PPC_ISERIES */
 
+#endif /* CONFIG_PPC_ISERIES */
 
 /* Initializes an iommu_table based in values set in the passed-in
  * structure
@@ -151,6 +154,8 @@
 
 extern void pci_iommu_init(void);
 extern void pci_dma_init_direct(void);
+
+extern void alloc_u3_dart_table(void);
 
 extern int ppc64_iommu_off;
 
diff -Nru a/include/asm-ppc64/lmb.h b/include/asm-ppc64/lmb.h
--- a/include/asm-ppc64/lmb.h	2004-10-18 14:56:49 -07:00
+++ b/include/asm-ppc64/lmb.h	2004-10-18 14:56:49 -07:00
@@ -20,12 +20,6 @@
 
 #define MAX_LMB_REGIONS 128
 
-union lmb_reg_property { 
-	struct reg_property32	 addr32[MAX_LMB_REGIONS];
-	struct reg_property64	 addr64[MAX_LMB_REGIONS];
-	struct reg_property_pmac addrPM[MAX_LMB_REGIONS];
-};
-
 #define LMB_ALLOC_ANYWHERE	0
 
 struct lmb_property {
@@ -47,7 +41,7 @@
 	struct lmb_region reserved;
 };
 
-extern struct lmb lmb __initdata;
+extern struct lmb lmb;
 
 extern void __init lmb_init(void);
 extern void __init lmb_analyze(void);
@@ -59,6 +53,8 @@
 extern unsigned long __init lmb_phys_mem_size(void);
 extern unsigned long __init lmb_end_of_DRAM(void);
 extern unsigned long __init lmb_abs_to_phys(unsigned long);
+
+extern void lmb_dump_all(void);
 
 extern unsigned long io_hole_start;
 
diff -Nru a/include/asm-ppc64/machdep.h b/include/asm-ppc64/machdep.h
--- a/include/asm-ppc64/machdep.h	2004-10-18 14:56:28 -07:00
+++ b/include/asm-ppc64/machdep.h	2004-10-18 14:56:28 -07:00
@@ -56,6 +56,9 @@
 	void		(*flush_hash_range)(unsigned long context,
 					    unsigned long number,
 					    int local);
+	/* special for kexec, to be called in real mode, linar mapping is
+	 * destroyed as well */
+	void		(*hpte_clear_all)(void);
 
 	void		(*tce_build)(struct iommu_table * tbl,
 				     long index,
@@ -67,7 +70,9 @@
 				    long npages);
 	void		(*tce_flush)(struct iommu_table *tbl);
 
+	int		(*probe)(int platform);
 	void		(*setup_arch)(void);
+	void		(*init_early)(void);
 	/* Optional, may be NULL. */
 	void		(*get_cpuinfo)(struct seq_file *m);
 
@@ -76,9 +81,6 @@
 
 	/* PCI stuff */
 	void		(*pcibios_fixup)(void);
-
-	/* Optional, may be NULL. */
-	void		(*init)(void);
 
 	void		(*restart)(char *cmd);
 	void		(*power_off)(void);
diff -Nru a/include/asm-ppc64/memory.h b/include/asm-ppc64/memory.h
--- a/include/asm-ppc64/memory.h	2004-10-18 14:57:05 -07:00
+++ b/include/asm-ppc64/memory.h	2004-10-18 14:57:05 -07:00
@@ -56,14 +56,4 @@
 #define HMT_MEDIUM_HIGH "\tor   5,5,5           # medium high priority\n"
 #define HMT_HIGH	"\tor	3,3,3		# high priority\n"
 
-/* 
- * Various operational modes for SMT
- * Off    : never run threaded
- * On     : always run threaded
- * Dynamic: Allow the system to switch modes as needed
- */
-#define SMT_OFF      0
-#define SMT_ON       1
-#define SMT_DYNAMIC  2
-
 #endif
diff -Nru a/include/asm-ppc64/mmu.h b/include/asm-ppc64/mmu.h
--- a/include/asm-ppc64/mmu.h	2004-10-18 14:56:48 -07:00
+++ b/include/asm-ppc64/mmu.h	2004-10-18 14:56:48 -07:00
@@ -15,6 +15,7 @@
 
 #include <linux/config.h>
 #include <asm/page.h>
+#include <linux/stringify.h>
 
 #ifndef __ASSEMBLY__
 
@@ -27,43 +28,17 @@
 #endif
 } mm_context_t;
 
-#ifdef CONFIG_HUGETLB_PAGE
-#define KERNEL_LOW_HPAGES	.htlb_segs = 0,
-#else
-#define KERNEL_LOW_HPAGES
-#endif
-
-#define KERNEL_CONTEXT(ea) ({ \
-		mm_context_t ctx = { .id = REGION_ID(ea), KERNEL_LOW_HPAGES}; \
-		ctx; })
-
-typedef struct {
-	unsigned long esid: 36; /* Effective segment ID */
-	unsigned long resv0:20; /* Reserved */
-	unsigned long v:     1; /* Entry valid (v=1) or invalid */
-	unsigned long resv1: 1; /* Reserved */
-	unsigned long ks:    1; /* Supervisor (privileged) state storage key */
-	unsigned long kp:    1; /* Problem state storage key */
-	unsigned long n:     1; /* No-execute if n=1 */
-	unsigned long resv2: 3; /* padding to a 64b boundary */
-} ste_dword0;
-
-typedef struct {
-	unsigned long vsid: 52; /* Virtual segment ID */
-	unsigned long resv0:12; /* Padding to a 64b boundary */
-} ste_dword1;
-
-typedef struct _STE {
-	union {
-		unsigned long dword0;
-		ste_dword0    dw0;
-	} dw0;
-
-	union {
-		unsigned long dword1;
-		ste_dword1    dw1;
-	} dw1;
-} STE;
+#define STE_ESID_V	0x80
+#define STE_ESID_KS	0x20
+#define STE_ESID_KP	0x10
+#define STE_ESID_N	0x08
+
+#define STE_VSID_SHIFT	12
+
+struct stab_entry {
+	unsigned long esid_data;
+	unsigned long vsid_data;
+};
 
 /* Hardware Page Table Entry */
 
@@ -132,20 +107,6 @@
 
 extern HTAB htab_data;
 
-void invalidate_hpte( unsigned long slot );
-long select_hpte_slot( unsigned long vpn );
-void create_valid_hpte( unsigned long slot, unsigned long vpn,
-			unsigned long prpn, unsigned hash,
-			void * ptep, unsigned hpteflags,
-			unsigned bolted );
-
-#define PD_SHIFT (10+12)		/* Page directory */
-#define PD_MASK  0x02FF
-#define PT_SHIFT (12)			/* Page Table */
-#define PT_MASK  0x02FF
-
-#define LARGE_PAGE_SHIFT 24
-
 static inline unsigned long hpt_hash(unsigned long vpn, int large)
 {
 	unsigned long vsid;
@@ -224,7 +185,7 @@
 #define STAB0_PHYS_ADDR	(STAB0_PAGE<<PAGE_SHIFT)
 #define STAB0_VIRT_ADDR	(KERNELBASE+STAB0_PHYS_ADDR)
 
-#define SLB_NUM_BOLTED		2
+#define SLB_NUM_BOLTED		3
 #define SLB_CACHE_ENTRIES	8
 
 /* Bits in the SLB ESID word */
@@ -241,156 +202,43 @@
 #define SLB_VSID_KERNEL		(SLB_VSID_KP|SLB_VSID_C)
 #define SLB_VSID_USER		(SLB_VSID_KP|SLB_VSID_KS)
 
-#define VSID_RANDOMIZER ASM_CONST(42470972311)
-#define VSID_MASK	0xfffffffffUL
-/* Because we never access addresses below KERNELBASE as kernel
- * addresses, this VSID is never used for anything real, and will
- * never have pages hashed into it */
-#define BAD_VSID	ASM_CONST(0)
-
-/* Block size masks */
-#define BL_128K	0x000
-#define BL_256K 0x001
-#define BL_512K 0x003
-#define BL_1M   0x007
-#define BL_2M   0x00F
-#define BL_4M   0x01F
-#define BL_8M   0x03F
-#define BL_16M  0x07F
-#define BL_32M  0x0FF
-#define BL_64M  0x1FF
-#define BL_128M 0x3FF
-#define BL_256M 0x7FF
-
-/* Used to set up SDR1 register */
-#define HASH_TABLE_SIZE_64K	0x00010000
-#define HASH_TABLE_SIZE_128K	0x00020000
-#define HASH_TABLE_SIZE_256K	0x00040000
-#define HASH_TABLE_SIZE_512K	0x00080000
-#define HASH_TABLE_SIZE_1M	0x00100000
-#define HASH_TABLE_SIZE_2M	0x00200000
-#define HASH_TABLE_SIZE_4M	0x00400000
-#define HASH_TABLE_MASK_64K	0x000   
-#define HASH_TABLE_MASK_128K	0x001   
-#define HASH_TABLE_MASK_256K	0x003   
-#define HASH_TABLE_MASK_512K	0x007
-#define HASH_TABLE_MASK_1M	0x00F   
-#define HASH_TABLE_MASK_2M	0x01F   
-#define HASH_TABLE_MASK_4M	0x03F   
-
-/* These are the Ks and Kp from the PowerPC books.  For proper operation,
- * Ks = 0, Kp = 1.
- */
-#define MI_AP		786
-#define MI_Ks		0x80000000	/* Should not be set */
-#define MI_Kp		0x40000000	/* Should always be set */
-
-/* The effective page number register.  When read, contains the information
- * about the last instruction TLB miss.  When MI_RPN is written, bits in
- * this register are used to create the TLB entry.
- */
-#define MI_EPN		787
-#define MI_EPNMASK	0xfffff000	/* Effective page number for entry */
-#define MI_EVALID	0x00000200	/* Entry is valid */
-#define MI_ASIDMASK	0x0000000f	/* ASID match value */
-					/* Reset value is undefined */
-
-/* A "level 1" or "segment" or whatever you want to call it register.
- * For the instruction TLB, it contains bits that get loaded into the
- * TLB entry when the MI_RPN is written.
- */
-#define MI_TWC		789
-#define MI_APG		0x000001e0	/* Access protection group (0) */
-#define MI_GUARDED	0x00000010	/* Guarded storage */
-#define MI_PSMASK	0x0000000c	/* Mask of page size bits */
-#define MI_PS8MEG	0x0000000c	/* 8M page size */
-#define MI_PS512K	0x00000004	/* 512K page size */
-#define MI_PS4K_16K	0x00000000	/* 4K or 16K page size */
-#define MI_SVALID	0x00000001	/* Segment entry is valid */
-					/* Reset value is undefined */
-
-/* Real page number.  Defined by the pte.  Writing this register
- * causes a TLB entry to be created for the instruction TLB, using
- * additional information from the MI_EPN, and MI_TWC registers.
- */
-#define MI_RPN		790
-
-/* Define an RPN value for mapping kernel memory to large virtual
- * pages for boot initialization.  This has real page number of 0,
- * large page size, shared page, cache enabled, and valid.
- * Also mark all subpages valid and write access.
- */
-#define MI_BOOTINIT	0x000001fd
-
-#define MD_CTR		792	/* Data TLB control register */
-#define MD_GPM		0x80000000	/* Set domain manager mode */
-#define MD_PPM		0x40000000	/* Set subpage protection */
-#define MD_CIDEF	0x20000000	/* Set cache inhibit when MMU dis */
-#define MD_WTDEF	0x10000000	/* Set writethrough when MMU dis */
-#define MD_RSV4I	0x08000000	/* Reserve 4 TLB entries */
-#define MD_TWAM		0x04000000	/* Use 4K page hardware assist */
-#define MD_PPCS		0x02000000	/* Use MI_RPN prob/priv state */
-#define MD_IDXMASK	0x00001f00	/* TLB index to be loaded */
-#define MD_RESETVAL	0x04000000	/* Value of register at reset */
-
-#define M_CASID		793	/* Address space ID (context) to match */
-#define MC_ASIDMASK	0x0000000f	/* Bits used for ASID value */
+#define VSID_MULTIPLIER	ASM_CONST(200730139)	/* 28-bit prime */
+#define VSID_BITS	36
+#define VSID_MODULUS	((1UL<<VSID_BITS)-1)
 
+#define CONTEXT_BITS	20
+#define USER_ESID_BITS	15
 
-/* These are the Ks and Kp from the PowerPC books.  For proper operation,
- * Ks = 0, Kp = 1.
- */
-#define MD_AP		794
-#define MD_Ks		0x80000000	/* Should not be set */
-#define MD_Kp		0x40000000	/* Should always be set */
-
-/* The effective page number register.  When read, contains the information
- * about the last instruction TLB miss.  When MD_RPN is written, bits in
- * this register are used to create the TLB entry.
- */
-#define MD_EPN		795
-#define MD_EPNMASK	0xfffff000	/* Effective page number for entry */
-#define MD_EVALID	0x00000200	/* Entry is valid */
-#define MD_ASIDMASK	0x0000000f	/* ASID match value */
-					/* Reset value is undefined */
-
-/* The pointer to the base address of the first level page table.
- * During a software tablewalk, reading this register provides the address
- * of the entry associated with MD_EPN.
- */
-#define M_TWB		796
-#define	M_L1TB		0xfffff000	/* Level 1 table base address */
-#define M_L1INDX	0x00000ffc	/* Level 1 index, when read */
-					/* Reset value is undefined */
-
-/* A "level 1" or "segment" or whatever you want to call it register.
- * For the data TLB, it contains bits that get loaded into the TLB entry
- * when the MD_RPN is written.  It is also provides the hardware assist
- * for finding the PTE address during software tablewalk.
- */
-#define MD_TWC		797
-#define MD_L2TB		0xfffff000	/* Level 2 table base address */
-#define MD_L2INDX	0xfffffe00	/* Level 2 index (*pte), when read */
-#define MD_APG		0x000001e0	/* Access protection group (0) */
-#define MD_GUARDED	0x00000010	/* Guarded storage */
-#define MD_PSMASK	0x0000000c	/* Mask of page size bits */
-#define MD_PS8MEG	0x0000000c	/* 8M page size */
-#define MD_PS512K	0x00000004	/* 512K page size */
-#define MD_PS4K_16K	0x00000000	/* 4K or 16K page size */
-#define MD_WT		0x00000002	/* Use writethrough page attribute */
-#define MD_SVALID	0x00000001	/* Segment entry is valid */
-					/* Reset value is undefined */
-
-
-/* Real page number.  Defined by the pte.  Writing this register
- * causes a TLB entry to be created for the data TLB, using
- * additional information from the MD_EPN, and MD_TWC registers.
- */
-#define MD_RPN		798
-
-/* This is a temporary storage register that could be used to save
- * a processor working register during a tablewalk.
- */
-#define M_TW		799
+/*
+ * This macro generates asm code to compute the VSID scramble
+ * function.  Used in slb_allocate() and do_stab_bolted.  The function
+ * computed is: (protovsid*VSID_MULTIPLIER) % VSID_MODULUS
+ *
+ *	rt = register continaing the proto-VSID and into which the
+ *		VSID will be stored
+ *	rx = scratch register (clobbered)
+ *
+ * 	- rt and rx must be different registers
+ * 	- The answer will end up in the low 36 bits of rt.  The higher
+ * 	  bits may contain other garbage, so you may need to mask the
+ * 	  result.
+ */
+#define ASM_VSID_SCRAMBLE(rt, rx)	\
+	lis	rx,VSID_MULTIPLIER@h;					\
+	ori	rx,rx,VSID_MULTIPLIER@l;				\
+	mulld	rt,rt,rx;		/* rt = rt * MULTIPLIER */	\
+									\
+	srdi	rx,rt,VSID_BITS;					\
+	clrldi	rt,rt,(64-VSID_BITS);					\
+	add	rt,rt,rx;		/* add high and low bits */	\
+	/* Now, r3 == VSID (mod 2^36-1), and lies between 0 and		\
+	 * 2^36-1+2^28-1.  That in particular means that if r3 >=	\
+	 * 2^36-1, then r3+1 has the 2^36 bit set.  So, if r3+1 has	\
+	 * the bit clear, r3 already has the answer we want, if it	\
+	 * doesn't, the answer is the low 36 bits of r3+1.  So in all	\
+	 * cases the answer is the low 36 bits of (r3 + ((r3+1) >> 36))*/\
+	addi	rx,rt,1;						\
+	srdi	rx,rx,VSID_BITS;	/* extract 2^36 bit */		\
+	add	rt,rt,rx
 
 #endif /* _PPC64_MMU_H_ */
diff -Nru a/include/asm-ppc64/mmu_context.h b/include/asm-ppc64/mmu_context.h
--- a/include/asm-ppc64/mmu_context.h	2004-10-18 14:56:28 -07:00
+++ b/include/asm-ppc64/mmu_context.h	2004-10-18 14:56:28 -07:00
@@ -2,11 +2,9 @@
 #define __PPC64_MMU_CONTEXT_H
 
 #include <linux/config.h>
-#include <linux/spinlock.h>	
 #include <linux/kernel.h>	
 #include <linux/mm.h>	
 #include <asm/mmu.h>	
-#include <asm/ppcdebug.h>	
 #include <asm/cputable.h>
 
 /*
@@ -33,109 +31,17 @@
 	return __ffs(b[2]) + 128;
 }
 
-#define NO_CONTEXT		0
-#define FIRST_USER_CONTEXT	0x10    /* First 16 reserved for kernel */
-#define LAST_USER_CONTEXT	0x8000  /* Same as PID_MAX for now... */
-#define NUM_USER_CONTEXT	(LAST_USER_CONTEXT-FIRST_USER_CONTEXT)
-
-/* Choose whether we want to implement our context
- * number allocator as a LIFO or FIFO queue.
- */
-#if 1
-#define MMU_CONTEXT_LIFO
-#else
-#define MMU_CONTEXT_FIFO
-#endif
-
-struct mmu_context_queue_t {
-	spinlock_t lock;
-	long head;
-	long tail;
-	long size;
-	mm_context_id_t elements[LAST_USER_CONTEXT];
-};
-
-extern struct mmu_context_queue_t mmu_context_queue;
-
-static inline void
-enter_lazy_tlb(struct mm_struct *mm, struct task_struct *tsk)
-{
-}
-
-/*
- * The context number queue has underflowed.
- * Meaning: we tried to push a context number that was freed
- * back onto the context queue and the queue was already full.
- */
-static inline void
-mmu_context_underflow(void)
-{
-	printk(KERN_DEBUG "mmu_context_underflow\n");
-	panic("mmu_context_underflow");
-}
-
-/*
- * Set up the context for a new address space.
- */
-static inline int
-init_new_context(struct task_struct *tsk, struct mm_struct *mm)
+static inline void enter_lazy_tlb(struct mm_struct *mm, struct task_struct *tsk)
 {
-	long head;
-	unsigned long flags;
-	/* This does the right thing across a fork (I hope) */
-
-	spin_lock_irqsave(&mmu_context_queue.lock, flags);
-
-	if (mmu_context_queue.size <= 0) {
-		spin_unlock_irqrestore(&mmu_context_queue.lock, flags);
-		return -ENOMEM;
-	}
-
-	head = mmu_context_queue.head;
-	mm->context.id = mmu_context_queue.elements[head];
-
-	head = (head < LAST_USER_CONTEXT-1) ? head+1 : 0;
-	mmu_context_queue.head = head;
-	mmu_context_queue.size--;
-
-	spin_unlock_irqrestore(&mmu_context_queue.lock, flags);
-
-	return 0;
 }
 
-/*
- * We're finished using the context for an address space.
- */
-static inline void
-destroy_context(struct mm_struct *mm)
-{
-	long index;
-	unsigned long flags;
-
-	spin_lock_irqsave(&mmu_context_queue.lock, flags);
+#define NO_CONTEXT	0
+#define MAX_CONTEXT	(0x100000-1)
 
-	if (mmu_context_queue.size >= NUM_USER_CONTEXT) {
-		spin_unlock_irqrestore(&mmu_context_queue.lock, flags);
-		mmu_context_underflow();
-	}
-
-#ifdef MMU_CONTEXT_LIFO
-	index = mmu_context_queue.head;
-	index = (index > 0) ? index-1 : LAST_USER_CONTEXT-1;
-	mmu_context_queue.head = index;
-#else
-	index = mmu_context_queue.tail;
-	index = (index < LAST_USER_CONTEXT-1) ? index+1 : 0;
-	mmu_context_queue.tail = index;
-#endif
+extern int init_new_context(struct task_struct *tsk, struct mm_struct *mm);
+extern void destroy_context(struct mm_struct *mm);
 
-	mmu_context_queue.size++;
-	mmu_context_queue.elements[index] = mm->context.id;
-
-	spin_unlock_irqrestore(&mmu_context_queue.lock, flags);
-}
-
-extern void flush_stab(struct task_struct *tsk, struct mm_struct *mm);
+extern void switch_stab(struct task_struct *tsk, struct mm_struct *mm);
 extern void switch_slb(struct task_struct *tsk, struct mm_struct *mm);
 
 /*
@@ -163,7 +69,7 @@
 	if (cur_cpu_spec->cpu_features & CPU_FTR_SLB)
 		switch_slb(tsk, next);
 	else
-		flush_stab(tsk, next);
+		switch_stab(tsk, next);
 }
 
 #define deactivate_mm(tsk,mm)	do { } while (0)
@@ -181,46 +87,86 @@
 	local_irq_restore(flags);
 }
 
-/* This is only valid for kernel (including vmalloc, imalloc and bolted) EA's
+/* VSID allocation
+ * ===============
+ *
+ * We first generate a 36-bit "proto-VSID".  For kernel addresses this
+ * is equal to the ESID, for user addresses it is:
+ *	(context << 15) | (esid & 0x7fff)
+ *
+ * The two forms are distinguishable because the top bit is 0 for user
+ * addresses, whereas the top two bits are 1 for kernel addresses.
+ * Proto-VSIDs with the top two bits equal to 0b10 are reserved for
+ * now.
+ *
+ * The proto-VSIDs are then scrambled into real VSIDs with the
+ * multiplicative hash:
+ *
+ *	VSID = (proto-VSID * VSID_MULTIPLIER) % VSID_MODULUS
+ *	where	VSID_MULTIPLIER = 268435399 = 0xFFFFFC7
+ *		VSID_MODULUS = 2^36-1 = 0xFFFFFFFFF
+ *
+ * This scramble is only well defined for proto-VSIDs below
+ * 0xFFFFFFFFF, so both proto-VSID and actual VSID 0xFFFFFFFFF are
+ * reserved.  VSID_MULTIPLIER is prime, so in particular it is
+ * co-prime to VSID_MODULUS, making this a 1:1 scrambling function.
+ * Because the modulus is 2^n-1 we can compute it efficiently without
+ * a divide or extra multiply (see below).
+ *
+ * This scheme has several advantages over older methods:
+ *
+ * 	- We have VSIDs allocated for every kernel address
+ * (i.e. everything above 0xC000000000000000), except the very top
+ * segment, which simplifies several things.
+ *
+ * 	- We allow for 15 significant bits of ESID and 20 bits of
+ * context for user addresses.  i.e. 8T (43 bits) of address space for
+ * up to 1M contexts (although the page table structure and context
+ * allocation will need changes to take advantage of this).
+ *
+ * 	- The scramble function gives robust scattering in the hash
+ * table (at least based on some initial results).  The previous
+ * method was more susceptible to pathological cases giving excessive
+ * hash collisions.
  */
-static inline unsigned long
-get_kernel_vsid( unsigned long ea )
+
+/*
+ * WARNING - If you change these you must make sure the asm
+ * implementations in slb_allocate(), do_stab_bolted and mmu.h
+ * (ASM_VSID_SCRAMBLE macro) are changed accordingly.
+ *
+ * You'll also need to change the precomputed VSID values in head.S
+ * which are used by the iSeries firmware.
+ */
+
+static inline unsigned long vsid_scramble(unsigned long protovsid)
 {
-	unsigned long ordinal, vsid;
-	
-	ordinal = (((ea >> 28) & 0x1fff) * LAST_USER_CONTEXT) | (ea >> 60);
-	vsid = (ordinal * VSID_RANDOMIZER) & VSID_MASK;
-
-#ifdef HTABSTRESS
-	/* For debug, this path creates a very poor vsid distribuition.
-	 * A user program can access virtual addresses in the form
-	 * 0x0yyyyxxxx000 where yyyy = xxxx to cause multiple mappings
-	 * to hash to the same page table group.
-	 */
-	ordinal = ((ea >> 28) & 0x1fff) | (ea >> 44);
-	vsid = ordinal & VSID_MASK;
-#endif /* HTABSTRESS */
-
-	return vsid;
-} 
-
-/* This is only valid for user EA's (user EA's do not exceed 2^41 (EADDR_SIZE))
- */
-static inline unsigned long
-get_vsid( unsigned long context, unsigned long ea )
-{
-	unsigned long ordinal, vsid;
-
-	ordinal = (((ea >> 28) & 0x1fff) * LAST_USER_CONTEXT) | context;
-	vsid = (ordinal * VSID_RANDOMIZER) & VSID_MASK;
-
-#ifdef HTABSTRESS
-	/* See comment above. */
-	ordinal = ((ea >> 28) & 0x1fff) | (context << 16);
-	vsid = ordinal & VSID_MASK;
-#endif /* HTABSTRESS */
+#if 0
+	/* The code below is equivalent to this function for arguments
+	 * < 2^VSID_BITS, which is all this should ever be called
+	 * with.  However gcc is not clever enough to compute the
+	 * modulus (2^n-1) without a second multiply. */
+	return ((protovsid * VSID_MULTIPLIER) % VSID_MODULUS);
+#else /* 1 */
+	unsigned long x;
 
-	return vsid;
+	x = protovsid * VSID_MULTIPLIER;
+	x = (x >> VSID_BITS) + (x & VSID_MODULUS);
+	return (x + ((x+1) >> VSID_BITS)) & VSID_MODULUS;
+#endif /* 1 */
+}
+
+/* This is only valid for addresses >= KERNELBASE */
+static inline unsigned long get_kernel_vsid(unsigned long ea)
+{
+	return vsid_scramble(ea >> SID_SHIFT);
+}
+
+/* This is only valid for user addresses (which are below 2^41) */
+static inline unsigned long get_vsid(unsigned long context, unsigned long ea)
+{
+	return vsid_scramble((context << USER_ESID_BITS)
+			     | (ea >> SID_SHIFT));
 }
 
 #endif /* __PPC64_MMU_CONTEXT_H */
diff -Nru a/include/asm-ppc64/mmzone.h b/include/asm-ppc64/mmzone.h
--- a/include/asm-ppc64/mmzone.h	2004-10-18 14:57:04 -07:00
+++ b/include/asm-ppc64/mmzone.h	2004-10-18 14:57:04 -07:00
@@ -12,7 +12,7 @@
 
 #ifdef CONFIG_DISCONTIGMEM
 
-extern struct pglist_data node_data[];
+extern struct pglist_data *node_data[];
 
 /*
  * Following are specific to this numa platform.
@@ -52,7 +52,7 @@
 /*
  * Return a pointer to the node data for node n.
  */
-#define NODE_DATA(nid)		(&node_data[nid])
+#define NODE_DATA(nid)		(node_data[nid])
 
 #define node_localnr(pfn, nid)	((pfn) - NODE_DATA(nid)->node_start_pfn)
 
diff -Nru a/include/asm-ppc64/naca.h b/include/asm-ppc64/naca.h
--- a/include/asm-ppc64/naca.h	2004-10-18 14:56:31 -07:00
+++ b/include/asm-ppc64/naca.h	2004-10-18 14:56:31 -07:00
@@ -37,9 +37,6 @@
 	u32 dCacheL1LinesPerPage;	/* L1 d-cache lines / page   0x64 */
 	u32 iCacheL1LogLineSize;	/* L1 i-cache line size Log2 0x68 */
 	u32 iCacheL1LinesPerPage;	/* L1 i-cache lines / page   0x6c */
-	u8  smt_state;                  /* 0 = SMT off               0x70 */
-	                                /* 1 = SMT on                     */
-	                                /* 2 = SMT dynamic                */
 	u8  resv0[15];                  /* Reserved           0x71 - 0x7F */
 };
 
diff -Nru a/include/asm-ppc64/paca.h b/include/asm-ppc64/paca.h
--- a/include/asm-ppc64/paca.h	2004-10-18 14:56:28 -07:00
+++ b/include/asm-ppc64/paca.h	2004-10-18 14:56:28 -07:00
@@ -16,6 +16,7 @@
  * 2 of the License, or (at your option) any later version.
  */    
 
+#include	<linux/config.h>
 #include	<asm/types.h>
 #include	<asm/iSeries/ItLpPaca.h>
 #include	<asm/iSeries/ItLpRegSave.h>
@@ -78,7 +79,6 @@
 	u64 exmc[8];		/* used for machine checks */
 	u64 exslb[8];		/* used for SLB/segment table misses
 				 * on the linear mapping */
-	u64 slb_r3;		/* spot to save R3 on SLB miss */
 	mm_context_t context;
 	u16 slb_cache[SLB_CACHE_ENTRIES];
 	u16 slb_cache_ptr;
@@ -104,22 +104,9 @@
 	 * The lppaca is also used on POWER5 pSeries boxes.
 	 */
 	struct ItLpPaca lppaca __attribute__((aligned(0x80)));
+#ifdef CONFIG_PPC_ISERIES
 	struct ItLpRegSave reg_save;
-
-	/*
-	 * iSeries profiling support
-	 *
-	 * FIXME: do we still want this, or can we ditch it in favour
-	 * of oprofile?
-	 */
-	u32 *prof_buffer;		/* iSeries profiling buffer */
-	u32 *prof_stext;		/* iSeries start of kernel text */
-	u32 prof_multiplier;
-	u32 prof_counter;
-	u32 prof_shift;			/* iSeries shift for profile
-					 * bucket size */
-	u32 prof_len;			/* iSeries length of profile */
-	u8 prof_enabled;		/* 1=iSeries profiling enabled */
+#endif
 };
 
 #endif /* _PPC64_PACA_H */
diff -Nru a/include/asm-ppc64/page.h b/include/asm-ppc64/page.h
--- a/include/asm-ppc64/page.h	2004-10-18 14:55:54 -07:00
+++ b/include/asm-ppc64/page.h	2004-10-18 14:55:54 -07:00
@@ -30,11 +30,12 @@
 #define ESID_MASK	0xfffffffff0000000UL
 #define GET_ESID(x)     (((x) >> SID_SHIFT) & SID_MASK)
 
-#ifdef CONFIG_HUGETLB_PAGE
-
 #define HPAGE_SHIFT	24
 #define HPAGE_SIZE	((1UL) << HPAGE_SHIFT)
 #define HPAGE_MASK	(~(HPAGE_SIZE - 1))
+
+#ifdef CONFIG_HUGETLB_PAGE
+
 #define HUGETLB_PAGE_ORDER	(HPAGE_SHIFT - PAGE_SHIFT)
 
 /* For 64-bit processes the hugepage range is 1T-1.5T */
@@ -181,8 +182,7 @@
 
 #define __pa(x) ((unsigned long)(x)-PAGE_OFFSET)
 
-/* Not 100% correct, for use by /dev/mem only */
-extern int page_is_ram(unsigned long physaddr);
+extern int page_is_ram(unsigned long pfn);
 
 #endif /* __ASSEMBLY__ */
 
@@ -202,9 +202,9 @@
 /*             to change!                               */
 #define PAGE_OFFSET     ASM_CONST(0xC000000000000000)
 #define KERNELBASE      PAGE_OFFSET
-#define VMALLOCBASE     0xD000000000000000UL
-#define IOREGIONBASE    0xE000000000000000UL
-#define EEHREGIONBASE   0xA000000000000000UL
+#define VMALLOCBASE     ASM_CONST(0xD000000000000000)
+#define IOREGIONBASE    ASM_CONST(0xE000000000000000)
+#define EEHREGIONBASE   ASM_CONST(0xA000000000000000)
 
 #define IO_REGION_ID       (IOREGIONBASE>>REGION_SHIFT)
 #define EEH_REGION_ID      (EEHREGIONBASE>>REGION_SHIFT)
@@ -213,17 +213,6 @@
 #define USER_REGION_ID     (0UL)
 #define REGION_ID(X)	   (((unsigned long)(X))>>REGION_SHIFT)
 
-/*
- * Define valid/invalid EA bits (for all ranges)
- */
-#define VALID_EA_BITS   (0x000001ffffffffffUL)
-#define INVALID_EA_BITS (~(REGION_MASK|VALID_EA_BITS))
-
-#define IS_VALID_REGION_ID(x) \
-        (((x) == USER_REGION_ID) || ((x) >= KERNEL_REGION_ID))
-#define IS_VALID_EA(x) \
-        ((!((x) & INVALID_EA_BITS)) && IS_VALID_REGION_ID(REGION_ID(x)))
-
 #define __bpn_to_ba(x) ((((unsigned long)(x))<<PAGE_SHIFT) + KERNELBASE)
 #define __ba_to_bpn(x) ((((unsigned long)(x)) & ~REGION_MASK) >> PAGE_SHIFT)
 
@@ -240,6 +229,7 @@
 #endif
 
 #define virt_to_page(kaddr)	pfn_to_page(__pa(kaddr) >> PAGE_SHIFT)
+#define pfn_to_kaddr(pfn)	__va((pfn) << PAGE_SHIFT)
 
 #define virt_addr_valid(kaddr)	pfn_valid(__pa(kaddr) >> PAGE_SHIFT)
 
diff -Nru a/include/asm-ppc64/pci-bridge.h b/include/asm-ppc64/pci-bridge.h
--- a/include/asm-ppc64/pci-bridge.h	2004-10-18 14:55:54 -07:00
+++ b/include/asm-ppc64/pci-bridge.h	2004-10-18 14:55:54 -07:00
@@ -33,9 +33,9 @@
 struct pci_controller {
 	char what[8];                     /* Eye catcher      */
 	enum phb_types type;              /* Type of hardware */
-	struct pci_controller *next;
 	struct pci_bus *bus;
 	void *arch_data;
+	struct list_head list_node;
 
 	int first_busno;
 	int last_busno;
@@ -70,8 +70,8 @@
  * for a device on a PCI bus, given its device_node struct.
  * It returns 0 if OK, -1 on error.
  */
-int pci_device_loc(struct device_node *dev, unsigned char *bus_ptr,
-		   unsigned char *devfn_ptr);
+extern int pci_device_loc(struct device_node *dev, unsigned char *bus_ptr,
+			  unsigned char *devfn_ptr);
 
 struct device_node *fetch_dev_dn(struct pci_dev *dev);
 
@@ -86,6 +86,9 @@
 	else
 		return fetch_dev_dn(dev);
 }
+
+extern void pci_process_bridge_OF_ranges(struct pci_controller *hose,
+					 struct device_node *dev, int primary);
 
 /* Use this macro after the PCI bus walk for max performance when it
  * is known that sysdata is correct.
diff -Nru a/include/asm-ppc64/pgalloc.h b/include/asm-ppc64/pgalloc.h
--- a/include/asm-ppc64/pgalloc.h	2004-10-18 14:55:54 -07:00
+++ b/include/asm-ppc64/pgalloc.h	2004-10-18 14:55:54 -07:00
@@ -7,6 +7,7 @@
 #include <linux/percpu.h>
 #include <asm/processor.h>
 #include <asm/tlb.h>
+#include <asm/page.h>
 
 extern kmem_cache_t *zero_cache;
 
diff -Nru a/include/asm-ppc64/pgtable.h b/include/asm-ppc64/pgtable.h
--- a/include/asm-ppc64/pgtable.h	2004-10-18 14:57:04 -07:00
+++ b/include/asm-ppc64/pgtable.h	2004-10-18 14:57:04 -07:00
@@ -45,10 +45,16 @@
                     PGD_INDEX_SIZE + PAGE_SHIFT) 
 
 /*
+ * Size of EA range mapped by our pagetables.
+ */
+#define PGTABLE_EA_BITS	41
+#define PGTABLE_EA_MASK	((1UL<<PGTABLE_EA_BITS)-1)
+
+/*
  * Define the address range of the vmalloc VM area.
  */
 #define VMALLOC_START (0xD000000000000000ul)
-#define VMALLOC_END   (VMALLOC_START + VALID_EA_BITS)
+#define VMALLOC_END   (VMALLOC_START + PGTABLE_EA_MASK)
 
 /*
  * Define the address range of the imalloc VM area.
@@ -58,19 +64,19 @@
 #define IMALLOC_VMADDR(x) ((unsigned long)(x))
 #define PHBS_IO_BASE  	  (0xE000000000000000ul)	/* Reserve 2 gigs for PHBs */
 #define IMALLOC_BASE      (0xE000000080000000ul)  
-#define IMALLOC_END       (IMALLOC_BASE + VALID_EA_BITS)
+#define IMALLOC_END       (IMALLOC_BASE + PGTABLE_EA_MASK)
 
 /*
  * Define the address range mapped virt <-> physical
  */
 #define KRANGE_START KERNELBASE
-#define KRANGE_END   (KRANGE_START + VALID_EA_BITS)
+#define KRANGE_END   (KRANGE_START + PGTABLE_EA_MASK)
 
 /*
  * Define the user address range
  */
 #define USER_START (0UL)
-#define USER_END   (USER_START + VALID_EA_BITS)
+#define USER_END   (USER_START + PGTABLE_EA_MASK)
 
 
 /*
@@ -167,6 +173,7 @@
 #endif /* __ASSEMBLY__ */
 
 #define HAVE_ARCH_UNMAPPED_AREA
+#define HAVE_ARCH_UNMAPPED_AREA_TOPDOWN
 #else
 
 #define hash_huge_page(mm,a,ea,vsid,local)	-1
@@ -489,7 +496,8 @@
 
 void pgtable_cache_init(void);
 
-extern void hpte_init_pSeries(void);
+extern void hpte_init_native(void);
+extern void hpte_init_lpar(void);
 extern void hpte_init_iSeries(void);
 
 /* imalloc region types */
@@ -497,20 +505,21 @@
 #define IM_REGION_SUBSET	0x2
 #define IM_REGION_EXISTS	0x4
 #define IM_REGION_OVERLAP	0x8
+#define IM_REGION_SUPERSET	0x10
 
 extern struct vm_struct * im_get_free_area(unsigned long size);
 extern struct vm_struct * im_get_area(unsigned long v_addr, unsigned long size,
 			int region_type);
 unsigned long im_free(void *addr);
 
-long pSeries_lpar_hpte_insert(unsigned long hpte_group,
-			      unsigned long va, unsigned long prpn,
-			      int secondary, unsigned long hpteflags,
-			      int bolted, int large);
-
-long pSeries_hpte_insert(unsigned long hpte_group, unsigned long va,
-			 unsigned long prpn, int secondary,
-			 unsigned long hpteflags, int bolted, int large);
+extern long pSeries_lpar_hpte_insert(unsigned long hpte_group,
+				     unsigned long va, unsigned long prpn,
+				     int secondary, unsigned long hpteflags,
+				     int bolted, int large);
+
+extern long native_hpte_insert(unsigned long hpte_group, unsigned long va,
+			       unsigned long prpn, int secondary,
+			       unsigned long hpteflags, int bolted, int large);
 
 /*
  * find_linux_pte returns the address of a linux pte for a given 
diff -Nru a/include/asm-ppc64/plpar_wrappers.h b/include/asm-ppc64/plpar_wrappers.h
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/include/asm-ppc64/plpar_wrappers.h	2004-10-18 14:57:23 -07:00
@@ -0,0 +1,109 @@
+#ifndef _PPC64_PLPAR_WRAPPERS_H
+#define _PPC64_PLPAR_WRAPPERS_H
+
+#include <asm/hvcall.h>
+
+static inline long poll_pending(void)
+{
+	unsigned long dummy;
+	return plpar_hcall(H_POLL_PENDING, 0, 0, 0, 0,
+			   &dummy, &dummy, &dummy);
+}
+
+static inline long prod_processor(void)
+{
+	plpar_hcall_norets(H_PROD);
+	return(0); 
+}
+
+static inline long cede_processor(void)
+{
+	plpar_hcall_norets(H_CEDE);
+	return(0); 
+}
+
+static inline long register_vpa(unsigned long flags, unsigned long proc, unsigned long vpa)
+{
+	plpar_hcall_norets(H_REGISTER_VPA, flags, proc, vpa);
+	return(0); 
+}
+
+static inline long plpar_pte_remove(unsigned long flags,
+				    unsigned long ptex,
+				    unsigned long avpn,
+				    unsigned long *old_pteh_ret,
+				    unsigned long *old_ptel_ret)
+{
+	unsigned long dummy;
+	return plpar_hcall(H_REMOVE, flags, ptex, avpn, 0,
+			   old_pteh_ret, old_ptel_ret, &dummy);
+}
+
+static inline long plpar_pte_read(unsigned long flags,
+				  unsigned long ptex,
+				  unsigned long *old_pteh_ret, unsigned long *old_ptel_ret)
+{
+	unsigned long dummy;
+	return plpar_hcall(H_READ, flags, ptex, 0, 0,
+			   old_pteh_ret, old_ptel_ret, &dummy);
+}
+
+static inline long plpar_pte_protect(unsigned long flags,
+				     unsigned long ptex,
+				     unsigned long avpn)
+{
+	return plpar_hcall_norets(H_PROTECT, flags, ptex, avpn);
+}
+
+static inline long plpar_tce_get(unsigned long liobn,
+				 unsigned long ioba,
+				 unsigned long *tce_ret)
+{
+	unsigned long dummy;
+	return plpar_hcall(H_GET_TCE, liobn, ioba, 0, 0,
+			   tce_ret, &dummy, &dummy);
+}
+
+static inline long plpar_tce_put(unsigned long liobn,
+				 unsigned long ioba,
+				 unsigned long tceval)
+{
+	return plpar_hcall_norets(H_PUT_TCE, liobn, ioba, tceval);
+}
+
+static inline long plpar_tce_put_indirect(unsigned long liobn,
+					  unsigned long ioba,
+					  unsigned long page,
+					  unsigned long count)
+{
+	return plpar_hcall_norets(H_PUT_TCE_INDIRECT, liobn, ioba, page, count);
+}
+
+static inline long plpar_tce_stuff(unsigned long liobn,
+				   unsigned long ioba,
+				   unsigned long tceval,
+				   unsigned long count)
+{
+	return plpar_hcall_norets(H_STUFF_TCE, liobn, ioba, tceval, count);
+}
+
+static inline long plpar_get_term_char(unsigned long termno,
+				       unsigned long *len_ret,
+				       char *buf_ret)
+{
+	unsigned long *lbuf = (unsigned long *)buf_ret;  /* ToDo: alignment? */
+	return plpar_hcall(H_GET_TERM_CHAR, termno, 0, 0, 0,
+			   len_ret, lbuf+0, lbuf+1);
+}
+
+static inline long plpar_put_term_char(unsigned long termno,
+				       unsigned long len,
+				       const char *buffer)
+{
+	unsigned long *lbuf = (unsigned long *)buffer;  /* ToDo: alignment? */
+	return plpar_hcall_norets(H_PUT_TERM_CHAR, termno, len, lbuf[0],
+				  lbuf[1]);
+}
+
+
+#endif /* _PPC64_PLPAR_WRAPPERS_H */
diff -Nru a/include/asm-ppc64/ppc32.h b/include/asm-ppc64/ppc32.h
--- a/include/asm-ppc64/ppc32.h	2004-10-18 14:56:29 -07:00
+++ b/include/asm-ppc64/ppc32.h	2004-10-18 14:56:29 -07:00
@@ -14,30 +14,6 @@
  * 2 of the License, or (at your option) any later version.
  */
 
-/* Use this to get at 32-bit user passed pointers. */
-/* Things to consider: the low-level assembly stub does
-   srl x, 0, x for first four arguments, so if you have
-   pointer to something in the first four arguments, just
-   declare it as a pointer, not u32. On the other side, 
-   arguments from 5th onwards should be declared as u32
-   for pointers, and need AA() around each usage.
-   A() macro should be used for places where you e.g.
-   have some internal variable u32 and just want to get
-   rid of a compiler warning. AA() has to be used in
-   places where you want to convert a function argument
-   to 32bit pointer or when you e.g. access pt_regs
-   structure and want to consider 32bit registers only.
-   -
- */
-#define A(__x) ((unsigned long)(__x))
-#define AA(__x)				\
-({	unsigned long __ret;		\
-	__asm__ ("clrldi	%0, %0, 32"	\
-		 : "=r" (__ret)		\
-		 : "0" (__x));		\
-	__ret;				\
-})
-
 /* These are here to support 32-bit syscalls on a 64-bit kernel. */
 
 typedef struct compat_siginfo {
@@ -56,8 +32,10 @@
 
 		/* POSIX.1b timers */
 		struct {
-			unsigned int _timer1;
-			unsigned int _timer2;
+			timer_t _tid;			/* timer id */
+			int _overrun;			/* overrun count */
+			compat_sigval_t _sigval;		/* same as below */
+			int _sys_private;		/* not to be passed to user */
 		} _timer;
 
 		/* POSIX.1b signals */
diff -Nru a/include/asm-ppc64/processor.h b/include/asm-ppc64/processor.h
--- a/include/asm-ppc64/processor.h	2004-10-18 14:55:54 -07:00
+++ b/include/asm-ppc64/processor.h	2004-10-18 14:55:54 -07:00
@@ -20,12 +20,6 @@
 #include <asm/ptrace.h>
 #include <asm/types.h>
 
-/*
- * Default implementation of macro that returns current
- * instruction pointer ("program counter").
- */
-#define current_text_addr() ({ __label__ _l; _l: &&_l;})
-
 /* Machine State Register (MSR) Fields */
 #define MSR_SF_LG	63              /* Enable 64 bit mode */
 #define MSR_ISF_LG	61              /* Interrupt 64b mode valid on 630 */
@@ -410,6 +404,12 @@
 #define XGLUE(a,b) a##b
 #define GLUE(a,b) XGLUE(a,b)
 
+/* iSeries CTRL register (for runlatch) */
+
+#define CTRLT		0x098
+#define CTRLF		0x088
+#define RUNLATCH	0x0001
+
 #ifdef __ASSEMBLY__
 
 #define _GLOBAL(name) \
@@ -438,8 +438,13 @@
 	.type GLUE(.,name),@function; \
 GLUE(.,name):
 
-#endif /* __ASSEMBLY__ */
+#else /* __ASSEMBLY__ */
 
+/*
+ * Default implementation of macro that returns current
+ * instruction pointer ("program counter").
+ */
+#define current_text_addr() ({ __label__ _l; _l: &&_l;})
 
 /* Macros for setting and retrieving special purpose registers */
 
@@ -461,20 +466,9 @@
 #define mttbl(v)	asm volatile("mttbl %0":: "r"(v))
 #define mttbu(v)	asm volatile("mttbu %0":: "r"(v))
 
-/* iSeries CTRL register (for runlatch) */
-
-#define CTRLT		0x098
-#define CTRLF		0x088
-#define RUNLATCH	0x0001
-
-/* Size of an exception stack frame contained in the paca. */
-#define EXC_FRAME_SIZE 64
-
 #define mfasr()		({unsigned long rval; \
 			asm volatile("mfasr %0" : "=r" (rval)); rval;})
 
-#ifndef __ASSEMBLY__
-
 static inline void set_tb(unsigned int upper, unsigned int lower)
 {
 	mttbl(0);
@@ -485,6 +479,8 @@
 #define __get_SP()	({unsigned long sp; \
 			asm volatile("mr %0,1": "=r" (sp)); sp;})
 
+#ifdef __KERNEL__
+
 extern int have_of;
 
 struct task_struct;
@@ -507,8 +503,6 @@
 extern struct task_struct *last_task_used_math;
 extern struct task_struct *last_task_used_altivec;
 
-
-#ifdef __KERNEL__
 /* 64-bit user address space is 41-bits (2TBs user VM) */
 #define TASK_SIZE_USER64 (0x0000020000000000UL)
 
@@ -520,8 +514,6 @@
 
 #define TASK_SIZE (test_thread_flag(TIF_32BIT) ? \
 		TASK_SIZE_USER32 : TASK_SIZE_USER64)
-#endif /* __KERNEL__ */
-
 
 /* This decides where the kernel will search for a free chunk of vm
  * space during mmap's.
@@ -538,6 +530,7 @@
 
 struct thread_struct {
 	unsigned long	ksp;		/* Kernel stack pointer */
+	unsigned long	ksp_vsid;
 	struct pt_regs	*regs;		/* Pointer to saved register state */
 	mm_segment_t	fs;		/* for get_fs() validation */
 	double		fpr[32];	/* Complete floating point set */
@@ -559,12 +552,12 @@
 #define INIT_SP		(sizeof(init_stack) + (unsigned long) &init_stack)
 
 #define INIT_THREAD  { \
-	INIT_SP, /* ksp */ \
-	(struct pt_regs *)INIT_SP - 1, /* regs */ \
-	KERNEL_DS, /*fs*/ \
-	{0}, /* fpr */ \
-	0, /* fpscr */ \
-	MSR_FE0|MSR_FE1, /* fpexc_mode */ \
+	.ksp = INIT_SP, \
+	.regs = (struct pt_regs *)INIT_SP - 1, \
+	.fs = KERNEL_DS, \
+	.fpr = {0}, \
+	.fpscr = 0, \
+	.fpexc_mode = MSR_FE0|MSR_FE1, \
 }
 
 /*
@@ -626,12 +619,11 @@
 
 #define spin_lock_prefetch(x)	prefetchw(x)
 
-#ifdef CONFIG_SCHED_SMT
-#define ARCH_HAS_SCHED_DOMAIN
-#define ARCH_HAS_SCHED_WAKE_IDLE
-#endif
+#define HAVE_ARCH_PICK_MMAP_LAYOUT
+
+#endif /* __KERNEL__ */
 
-#endif /* ASSEMBLY */
+#endif /* __ASSEMBLY__ */
 
 /*
  * Number of entries in the SLB. If this ever changes we should handle
diff -Nru a/include/asm-ppc64/prom.h b/include/asm-ppc64/prom.h
--- a/include/asm-ppc64/prom.h	2004-10-18 14:57:05 -07:00
+++ b/include/asm-ppc64/prom.h	2004-10-18 14:57:05 -07:00
@@ -24,14 +24,47 @@
 #define LONG_LSW(X) (((unsigned long)X) & 0xffffffff)
 #define LONG_MSW(X) (((unsigned long)X) >> 32)
 
+/* Definitions used by the flattened device tree */
+#define OF_DT_HEADER		0xd00dfeed	/* 4: version, 4: total size */
+#define OF_DT_BEGIN_NODE	0x1		/* Start node: full name */
+#define OF_DT_END_NODE		0x2		/* End node */
+#define OF_DT_PROP		0x3		/* Property: name off, size, content */
+#define OF_DT_END		0x9
+
+#define OF_DT_VERSION		1
+
+/*
+ * This is what gets passed to the kernel by prom_init or kexec
+ *
+ * The dt struct contains the device tree structure, full pathes and
+ * property contents. The dt strings contain a separate block with just
+ * the strings for the property names, and is fully page aligned and
+ * self contained in a page, so that it can be kept around by the kernel,
+ * each property name appears only once in this page (cheap compression)
+ *
+ * the mem_rsvmap contains a map of reserved ranges of physical memory,
+ * passing it here instead of in the device-tree itself greatly simplifies
+ * the job of everybody. It's just a list of u64 pairs (base/size) that
+ * ends when size is 0
+ */
+struct boot_param_header
+{
+	u32	magic;			/* magic word OF_DT_HEADER */
+	u32	totalsize;		/* total size of DT block */
+	u32	off_dt_struct;		/* offset to structure */
+	u32	off_dt_strings;		/* offset to strings */
+	u32	off_mem_rsvmap;		/* offset to memory reserve map */
+	u32	version;		/* format version */
+	u32	last_comp_version;	/* last compatible version */
+};
+
+
+
 typedef u32 phandle;
 typedef u32 ihandle;
 typedef u32 phandle32;
 typedef u32 ihandle32;
 
-extern char *prom_display_paths[];
-extern unsigned int prom_num_displays;
-
 struct address_range {
 	unsigned long space;
 	unsigned long address;
@@ -136,6 +169,7 @@
  */
 struct pci_controller;
 struct iommu_table;
+
 struct device_node {
 	char	*name;
 	char	*type;
@@ -171,6 +205,8 @@
 	unsigned long _flags;
 };
 
+extern struct device_node *of_chosen;
+
 /* flag descriptions */
 #define OF_STALE   0 /* node is slated for deletion */
 #define OF_DYNAMIC 1 /* node and properties were allocated via kmalloc */
@@ -202,34 +238,6 @@
 	dn->addr_link = de;
 }
 
-typedef u32 prom_arg_t;
-
-struct prom_args {
-        u32 service;
-        u32 nargs;
-        u32 nret;
-        prom_arg_t args[10];
-        prom_arg_t *rets;     /* Pointer to return values in args[16]. */
-};
-
-struct prom_t {
-	unsigned long entry;
-	ihandle root;
-	ihandle chosen;
-	int cpu;
-	ihandle stdout;
-	ihandle disp_node;
-	struct prom_args args;
-	unsigned long version;
-	unsigned long encode_phys_size;
-	struct bi_record *bi_recs;
-};
-
-extern struct prom_t prom;
-extern char *of_stdout_device;
-
-extern int boot_cpuid;
-
 /* OBSOLETE: Old stlye node lookup */
 extern struct device_node *find_devices(const char *name);
 extern struct device_node *find_type_devices(const char *type);
@@ -246,6 +254,7 @@
 extern struct device_node *of_find_compatible_node(struct device_node *from,
 	const char *type, const char *compat);
 extern struct device_node *of_find_node_by_path(const char *path);
+extern struct device_node *of_find_node_by_phandle(phandle handle);
 extern struct device_node *of_find_all_nodes(struct device_node *prev);
 extern struct device_node *of_get_parent(const struct device_node *node);
 extern struct device_node *of_get_next_child(const struct device_node *node,
diff -Nru a/include/asm-ppc64/ptrace.h b/include/asm-ppc64/ptrace.h
--- a/include/asm-ppc64/ptrace.h	2004-10-18 14:56:48 -07:00
+++ b/include/asm-ppc64/ptrace.h	2004-10-18 14:56:48 -07:00
@@ -60,15 +60,21 @@
 	PPC_REG_32 result; 	/* Result of a system call */
 };
 
+#define instruction_pointer(regs) ((regs)->nip)
+#ifdef CONFIG_SMP
+extern unsigned long profile_pc(struct pt_regs *regs);
+#else
+#define profile_pc(regs) instruction_pointer(regs)
 #endif
 
+#endif /* __ASSEMBLY__ */
+
 #define STACK_FRAME_OVERHEAD	112	/* size of minimum stack frame */
 
 /* Size of dummy stack frame allocated when calling signal handler. */
 #define __SIGNAL_FRAMESIZE	128
 #define __SIGNAL_FRAMESIZE32	64
 
-#define instruction_pointer(regs) ((regs)->nip)
 #define user_mode(regs) ((((regs)->msr) >> MSR_PR_LG) & 0x1)
 
 #define force_successful_syscall_return()   \
diff -Nru a/include/asm-ppc64/resource.h b/include/asm-ppc64/resource.h
--- a/include/asm-ppc64/resource.h	2004-10-18 14:56:48 -07:00
+++ b/include/asm-ppc64/resource.h	2004-10-18 14:56:48 -07:00
@@ -45,7 +45,7 @@
 	{ RLIM_INFINITY, RLIM_INFINITY },		\
 	{             0,             0 },		\
 	{      INR_OPEN,     INR_OPEN  },		\
-	{ RLIM_INFINITY, RLIM_INFINITY },		\
+	{   MLOCK_LIMIT,   MLOCK_LIMIT },		\
 	{ RLIM_INFINITY, RLIM_INFINITY },		\
 	{ RLIM_INFINITY, RLIM_INFINITY },		\
 	{ MAX_SIGPENDING, MAX_SIGPENDING },		\
diff -Nru a/include/asm-ppc64/rtas.h b/include/asm-ppc64/rtas.h
--- a/include/asm-ppc64/rtas.h	2004-10-18 14:57:04 -07:00
+++ b/include/asm-ppc64/rtas.h	2004-10-18 14:57:04 -07:00
@@ -22,12 +22,13 @@
 /* Buffer size for ppc_rtas system call. */
 #define RTAS_RMOBUF_MAX (64 * 1024)
 
-/* RTAS return codes */
-#define RTAS_BUSY		-2	/* RTAS Return Status - Busy */
-#define RTAS_EXTENDED_DELAY_MIN 9900
-#define RTAS_EXTENDED_DELAY_MAX 9905
+/* RTAS return status codes */
+#define RTAS_BUSY		-2    /* RTAS Busy */
+#define RTAS_NO_SUCH_INDICATOR	-3    /* No such indicator implemented */
+#define RTAS_EXTENDED_DELAY_MIN	9900
+#define RTAS_EXTENDED_DELAY_MAX	9905
 
-#define RTAS_UNKNOWN_OP		-1099	/* Return Status - Unknown RTAS Token */
+#define RTAS_UNKNOWN_OP		-1099 /* Unknown RTAS Token */
 
 /*
  * In general to call RTAS use rtas_token("string") to lookup
@@ -65,67 +66,78 @@
 	struct device_node *dev;	/* virtual address pointer */
 };
 
-/* Event classes */
+/* RTAS event classes */
 #define RTAS_INTERNAL_ERROR		0x80000000 /* set bit 0 */
 #define RTAS_EPOW_WARNING		0x40000000 /* set bit 1 */
 #define RTAS_POWERMGM_EVENTS		0x20000000 /* set bit 2 */
 #define RTAS_HOTPLUG_EVENTS		0x10000000 /* set bit 3 */
 #define RTAS_EVENT_SCAN_ALL_EVENTS	0xf0000000
 
-/* event-scan returns */
-#define SEVERITY_FATAL		0x5
-#define SEVERITY_ERROR		0x4
-#define SEVERITY_ERROR_SYNC	0x3
-#define SEVERITY_WARNING	0x2
-#define SEVERITY_EVENT		0x1
-#define SEVERITY_NO_ERROR	0x0
-#define DISP_FULLY_RECOVERED	0x0
-#define DISP_LIMITED_RECOVERY	0x1
-#define DISP_NOT_RECOVERED	0x2
-#define PART_PRESENT		0x0
-#define PART_NOT_PRESENT	0x1
-#define INITIATOR_UNKNOWN	0x0
-#define INITIATOR_CPU		0x1
-#define INITIATOR_PCI		0x2
-#define INITIATOR_ISA		0x3
-#define INITIATOR_MEMORY	0x4
-#define INITIATOR_POWERMGM	0x5
-#define TARGET_UNKNOWN		0x0
-#define TARGET_CPU		0x1
-#define TARGET_PCI		0x2
-#define TARGET_ISA		0x3
-#define TARGET_MEMORY		0x4
-#define TARGET_POWERMGM		0x5
-#define TYPE_RETRY		0x01
-#define TYPE_TCE_ERR		0x02
-#define TYPE_INTERN_DEV_FAIL	0x03
-#define TYPE_TIMEOUT		0x04
-#define TYPE_DATA_PARITY	0x05
-#define TYPE_ADDR_PARITY	0x06
-#define TYPE_CACHE_PARITY	0x07
-#define TYPE_ADDR_INVALID	0x08
-#define TYPE_ECC_UNCORR		0x09
-#define TYPE_ECC_CORR		0x0a
-#define TYPE_EPOW		0x40
+/* RTAS event severity */
+#define RTAS_SEVERITY_FATAL		0x5
+#define RTAS_SEVERITY_ERROR		0x4
+#define RTAS_SEVERITY_ERROR_SYNC	0x3
+#define RTAS_SEVERITY_WARNING		0x2
+#define RTAS_SEVERITY_EVENT		0x1
+#define RTAS_SEVERITY_NO_ERROR		0x0
+
+/* RTAS event disposition */
+#define RTAS_DISP_FULLY_RECOVERED	0x0
+#define RTAS_DISP_LIMITED_RECOVERY	0x1
+#define RTAS_DISP_NOT_RECOVERED		0x2
+
+/* RTAS event initiator */
+#define RTAS_INITIATOR_UNKNOWN		0x0
+#define RTAS_INITIATOR_CPU		0x1
+#define RTAS_INITIATOR_PCI		0x2
+#define RTAS_INITIATOR_ISA		0x3
+#define RTAS_INITIATOR_MEMORY		0x4
+#define RTAS_INITIATOR_POWERMGM		0x5
+
+/* RTAS event target */
+#define RTAS_TARGET_UNKNOWN		0x0
+#define RTAS_TARGET_CPU			0x1
+#define RTAS_TARGET_PCI			0x2
+#define RTAS_TARGET_ISA			0x3
+#define RTAS_TARGET_MEMORY		0x4
+#define RTAS_TARGET_POWERMGM		0x5
+
+/* RTAS event type */
+#define RTAS_TYPE_RETRY			0x01
+#define RTAS_TYPE_TCE_ERR		0x02
+#define RTAS_TYPE_INTERN_DEV_FAIL	0x03
+#define RTAS_TYPE_TIMEOUT		0x04
+#define RTAS_TYPE_DATA_PARITY		0x05
+#define RTAS_TYPE_ADDR_PARITY		0x06
+#define RTAS_TYPE_CACHE_PARITY		0x07
+#define RTAS_TYPE_ADDR_INVALID		0x08
+#define RTAS_TYPE_ECC_UNCORR		0x09
+#define RTAS_TYPE_ECC_CORR		0x0a
+#define RTAS_TYPE_EPOW			0x40
+#define RTAS_TYPE_PLATFORM		0xE0
+#define RTAS_TYPE_IO			0xE1
+#define RTAS_TYPE_INFO			0xE2
+#define RTAS_TYPE_DEALLOC		0xE3
+#define RTAS_TYPE_DUMP			0xE4
 /* I don't add PowerMGM events right now, this is a different topic */ 
-#define TYPE_PMGM_POWER_SW_ON	0x60
-#define TYPE_PMGM_POWER_SW_OFF	0x61
-#define TYPE_PMGM_LID_OPEN	0x62
-#define TYPE_PMGM_LID_CLOSE	0x63
-#define TYPE_PMGM_SLEEP_BTN	0x64
-#define TYPE_PMGM_WAKE_BTN	0x65
-#define TYPE_PMGM_BATTERY_WARN	0x66
-#define TYPE_PMGM_BATTERY_CRIT	0x67
-#define TYPE_PMGM_SWITCH_TO_BAT	0x68
-#define TYPE_PMGM_SWITCH_TO_AC	0x69
-#define TYPE_PMGM_KBD_OR_MOUSE	0x6a
-#define TYPE_PMGM_ENCLOS_OPEN	0x6b
-#define TYPE_PMGM_ENCLOS_CLOSED	0x6c
-#define TYPE_PMGM_RING_INDICATE	0x6d
-#define TYPE_PMGM_LAN_ATTENTION	0x6e
-#define TYPE_PMGM_TIME_ALARM	0x6f
-#define TYPE_PMGM_CONFIG_CHANGE	0x70
-#define TYPE_PMGM_SERVICE_PROC	0x71
+#define RTAS_TYPE_PMGM_POWER_SW_ON	0x60
+#define RTAS_TYPE_PMGM_POWER_SW_OFF	0x61
+#define RTAS_TYPE_PMGM_LID_OPEN		0x62
+#define RTAS_TYPE_PMGM_LID_CLOSE	0x63
+#define RTAS_TYPE_PMGM_SLEEP_BTN	0x64
+#define RTAS_TYPE_PMGM_WAKE_BTN		0x65
+#define RTAS_TYPE_PMGM_BATTERY_WARN	0x66
+#define RTAS_TYPE_PMGM_BATTERY_CRIT	0x67
+#define RTAS_TYPE_PMGM_SWITCH_TO_BAT	0x68
+#define RTAS_TYPE_PMGM_SWITCH_TO_AC	0x69
+#define RTAS_TYPE_PMGM_KBD_OR_MOUSE	0x6a
+#define RTAS_TYPE_PMGM_ENCLOS_OPEN	0x6b
+#define RTAS_TYPE_PMGM_ENCLOS_CLOSED	0x6c
+#define RTAS_TYPE_PMGM_RING_INDICATE	0x6d
+#define RTAS_TYPE_PMGM_LAN_ATTENTION	0x6e
+#define RTAS_TYPE_PMGM_TIME_ALARM	0x6f
+#define RTAS_TYPE_PMGM_CONFIG_CHANGE	0x70
+#define RTAS_TYPE_PMGM_SERVICE_PROC	0x71
 
 struct rtas_error_log {
 	unsigned long version:8;		/* Architectural version */
@@ -168,7 +180,7 @@
 extern void enter_rtas(unsigned long);
 extern int rtas_token(const char *service);
 extern int rtas_call(int token, int, int, int *, ...);
-extern void call_rtas_display_status(char);
+extern void call_rtas_display_status(unsigned char);
 extern void rtas_restart(char *cmd);
 extern void rtas_power_off(void);
 extern void rtas_halt(void);
@@ -177,6 +189,7 @@
 extern int rtas_get_power_level(int powerdomain, int *level);
 extern int rtas_set_power_level(int powerdomain, int level, int *setlevel);
 extern int rtas_set_indicator(int indicator, int index, int new_value);
+extern void rtas_initialize(void);
 
 /* Given an RTAS status code of 9900..9905 compute the hinted delay */
 unsigned int rtas_extended_busy_delay_time(int status);
@@ -199,8 +212,14 @@
 #define RTAS_DEBUG KERN_DEBUG "RTAS: "
  
 #define RTAS_ERROR_LOG_MAX 2048
- 
- 
+
+/*
+ * Return the firmware-specified size of the error log buffer
+ *  for all rtas calls that require an error buffer argument.
+ *  This includes 'check-exception' and 'rtas-last-error'.
+ */
+extern int rtas_get_error_log_max(void);
+
 /* Event Scan Parameters */
 #define EVENT_SCAN_ALL_EVENTS	0xf0000000
 #define SURVEILLANCE_TOKEN	9000
diff -Nru a/include/asm-ppc64/semaphore.h b/include/asm-ppc64/semaphore.h
--- a/include/asm-ppc64/semaphore.h	2004-10-18 14:56:29 -07:00
+++ b/include/asm-ppc64/semaphore.h	2004-10-18 14:56:29 -07:00
@@ -23,22 +23,13 @@
 	 */
 	atomic_t count;
 	wait_queue_head_t wait;
-#ifdef WAITQUEUE_DEBUG
-	long __magic;
-#endif
 };
 
-#ifdef WAITQUEUE_DEBUG
-# define __SEM_DEBUG_INIT(name) \
-		, (long)&(name).__magic
-#else
-# define __SEM_DEBUG_INIT(name)
-#endif
-
-#define __SEMAPHORE_INITIALIZER(name, count) \
-	{ ATOMIC_INIT(count), \
-	  __WAIT_QUEUE_HEAD_INITIALIZER((name).wait) \
-	  __SEM_DEBUG_INIT(name) }
+#define __SEMAPHORE_INITIALIZER(name, n)				\
+{									\
+	.count		= ATOMIC_INIT(n),				\
+	.wait		= __WAIT_QUEUE_HEAD_INITIALIZER((name).wait)	\
+}
 
 #define __MUTEX_INITIALIZER(name) \
 	__SEMAPHORE_INITIALIZER(name, 1)
@@ -53,9 +44,6 @@
 {
 	atomic_set(&sem->count, val);
 	init_waitqueue_head(&sem->wait);
-#ifdef WAITQUEUE_DEBUG
-	sem->__magic = (long)&sem->__magic;
-#endif
 }
 
 static inline void init_MUTEX (struct semaphore *sem)
@@ -74,9 +62,6 @@
 
 static inline void down(struct semaphore * sem)
 {
-#ifdef WAITQUEUE_DEBUG
-	CHECK_MAGIC(sem->__magic);
-#endif
 	might_sleep();
 
 	/*
@@ -90,9 +75,6 @@
 {
 	int ret = 0;
 
-#ifdef WAITQUEUE_DEBUG
-	CHECK_MAGIC(sem->__magic);
-#endif
 	might_sleep();
 
 	if (unlikely(atomic_dec_return(&sem->count) < 0))
@@ -102,19 +84,11 @@
 
 static inline int down_trylock(struct semaphore * sem)
 {
-#ifdef WAITQUEUE_DEBUG
-	CHECK_MAGIC(sem->__magic);
-#endif
-
 	return atomic_dec_if_positive(&sem->count) < 0;
 }
 
 static inline void up(struct semaphore * sem)
 {
-#ifdef WAITQUEUE_DEBUG
-	CHECK_MAGIC(sem->__magic);
-#endif
-
 	if (unlikely(atomic_inc_return(&sem->count) <= 0))
 		__up(sem);
 }
diff -Nru a/include/asm-ppc64/smp.h b/include/asm-ppc64/smp.h
--- a/include/asm-ppc64/smp.h	2004-10-18 14:55:46 -07:00
+++ b/include/asm-ppc64/smp.h	2004-10-18 14:55:46 -07:00
@@ -26,6 +26,8 @@
 
 #include <asm/paca.h>
 
+extern int boot_cpuid;
+
 #ifdef CONFIG_SMP
 
 extern void smp_send_debugger_break(int cpu);
@@ -36,22 +38,7 @@
 #define smp_processor_id() (get_paca()->paca_index)
 #define hard_smp_processor_id() (get_paca()->hw_cpu_id)
 
-/*
- * Retrieve the state of a CPU:
- * online:          CPU is in a normal run state
- * possible:        CPU is a candidate to be made online
- * available:       CPU is candidate for the 'possible' pool
- *                  Used to get SMT threads started at boot time.
- * present_at_boot: CPU was available at boot time.  Used in DLPAR
- *                  code to handle special cases for processor start up.
- */
-extern cpumask_t cpu_present_at_boot;
-extern cpumask_t cpu_online_map;
-extern cpumask_t cpu_possible_map;
-extern cpumask_t cpu_available_map;
-
-#define cpu_present_at_boot(cpu) cpu_isset(cpu, cpu_present_at_boot)
-#define cpu_available(cpu)       cpu_isset(cpu, cpu_available_map) 
+extern cpumask_t cpu_sibling_map[NR_CPUS];
 
 /* Since OpenPIC has only 4 IPIs, we use slightly different message numbers.
  *
@@ -73,11 +60,14 @@
 extern int __cpu_disable(void);
 extern void __cpu_die(unsigned int cpu);
 extern void cpu_die(void) __attribute__((noreturn));
+extern int query_cpu_stopped(unsigned int pcpu);
 #endif /* !(CONFIG_SMP) */
 
 #define get_hard_smp_processor_id(CPU) (paca[(CPU)].hw_cpu_id)
 #define set_hard_smp_processor_id(CPU, VAL) \
-	do { (paca[(CPU)].hw_proc_num = (VAL)); } while (0)
+	do { (paca[(CPU)].hw_cpu_id = (VAL)); } while (0)
+
+extern int smt_enabled_at_boot;
 
 #endif /* __ASSEMBLY__ */
 
diff -Nru a/include/asm-ppc64/socket.h b/include/asm-ppc64/socket.h
--- a/include/asm-ppc64/socket.h	2004-10-18 14:56:32 -07:00
+++ b/include/asm-ppc64/socket.h	2004-10-18 14:56:32 -07:00
@@ -54,20 +54,4 @@
 
 #define SO_PEERSEC             31
 
-/* Nast libc5 fixup - bletch */
-#if defined(__KERNEL__)
-/* Socket types. */
-#define SOCK_STREAM	1		/* stream (connection) socket	*/
-#define SOCK_DGRAM	2		/* datagram (conn.less) socket	*/
-#define SOCK_RAW	3		/* raw socket			*/
-#define SOCK_RDM	4		/* reliably-delivered message	*/
-#define SOCK_SEQPACKET	5		/* sequential packet socket	*/
-#define SOCK_PACKET	10		/* linux specific way of	*/
-					/* getting packets at the dev	*/
-					/* level.  For writing rarp and	*/
-					/* other similar things on the	*/
-					/* user level.			*/
-#define	SOCK_MAX	(SOCK_PACKET+1)
-#endif
-
 #endif /* _ASM_SOCKET_H */
diff -Nru a/include/asm-ppc64/spinlock.h b/include/asm-ppc64/spinlock.h
--- a/include/asm-ppc64/spinlock.h	2004-10-18 14:55:54 -07:00
+++ b/include/asm-ppc64/spinlock.h	2004-10-18 14:55:54 -07:00
@@ -6,6 +6,8 @@
  *
  * Copyright (C) 2001-2004 Paul Mackerras <paulus@au.ibm.com>, IBM
  * Copyright (C) 2001 Anton Blanchard <anton@au.ibm.com>, IBM
+ * Copyright (C) 2002 Dave Engebretsen <engebret@us.ibm.com>, IBM
+ *	Rework to support virtual processors
  *
  * Type of int is used as a full 64b word is not necessary.
  *
@@ -16,11 +18,17 @@
  */
 #include <linux/config.h>
 #include <asm/paca.h>
+#include <asm/hvcall.h>
+#include <asm/iSeries/HvCall.h>
 
 typedef struct {
 	volatile unsigned int lock;
 } spinlock_t;
 
+typedef struct {
+	volatile signed int lock;
+} rwlock_t;
+
 #ifdef __KERNEL__
 #define SPIN_LOCK_UNLOCKED	(spinlock_t) { 0 }
 
@@ -34,101 +42,91 @@
 }
 
 /*
- * Normally we use the spinlock functions in arch/ppc64/lib/locks.c.
- * For special applications such as profiling, we can have the
- * spinlock functions inline by defining CONFIG_SPINLINE.
- * This is not recommended on partitioned systems with shared
- * processors, since the inline spinlock functions don't include
- * the code for yielding the CPU to the lock holder.
+ * On a system with shared processors (that is, where a physical
+ * processor is multiplexed between several virtual processors),
+ * there is no point spinning on a lock if the holder of the lock
+ * isn't currently scheduled on a physical processor.  Instead
+ * we detect this situation and ask the hypervisor to give the
+ * rest of our timeslice to the lock holder.
+ *
+ * So that we can tell which virtual processor is holding a lock,
+ * we put 0x80000000 | smp_processor_id() in the lock when it is
+ * held.  Conveniently, we have a word in the paca that holds this
+ * value.
  */
 
-#ifndef CONFIG_SPINLINE
-extern int _raw_spin_trylock(spinlock_t *lock);
-extern void _raw_spin_lock(spinlock_t *lock);
-extern void _raw_spin_lock_flags(spinlock_t *lock, unsigned long flags);
+#if defined(CONFIG_PPC_SPLPAR) || defined(CONFIG_PPC_ISERIES)
+/* We only yield to the hypervisor if we are in shared processor mode */
+#define SHARED_PROCESSOR (get_paca()->lppaca.xSharedProc)
+extern void __spin_yield(spinlock_t *lock);
+extern void __rw_yield(rwlock_t *lock);
+#else /* SPLPAR || ISERIES */
+#define __spin_yield(x)	barrier()
+#define __rw_yield(x)	barrier()
+#define SHARED_PROCESSOR	0
+#endif
 extern void spin_unlock_wait(spinlock_t *lock);
 
-#else
-
-static __inline__ int _raw_spin_trylock(spinlock_t *lock)
+/*
+ * This returns the old value in the lock, so we succeeded
+ * in getting the lock if the return value is 0.
+ */
+static __inline__ unsigned long __spin_trylock(spinlock_t *lock)
 {
-	unsigned int tmp, tmp2;
+	unsigned long tmp, tmp2;
 
 	__asm__ __volatile__(
-"1:	lwarx		%0,0,%2		# spin_trylock\n\
+"	lwz		%1,%3(13)		# __spin_trylock\n\
+1:	lwarx		%0,0,%2\n\
 	cmpwi		0,%0,0\n\
 	bne-		2f\n\
-	lwz		%1,%3(13)\n\
 	stwcx.		%1,0,%2\n\
 	bne-		1b\n\
 	isync\n\
-2:"	: "=&r"(tmp), "=&r"(tmp2)
-	: "r"(&lock->lock), "i"(offsetof(struct paca_struct, lock_token))
+2:"	: "=&r" (tmp), "=&r" (tmp2)
+	: "r" (&lock->lock), "i" (offsetof(struct paca_struct, lock_token))
 	: "cr0", "memory");
 
-	return tmp == 0;
+	return tmp;
 }
 
-static __inline__ void _raw_spin_lock(spinlock_t *lock)
+static int __inline__ _raw_spin_trylock(spinlock_t *lock)
 {
-	unsigned int tmp;
-
-	__asm__ __volatile__(
-	"b		2f		# spin_lock\n\
-1:"
-	HMT_LOW
-"	lwzx		%0,0,%1\n\
-	cmpwi		0,%0,0\n\
-	bne+		1b\n"
-	HMT_MEDIUM
-"2:	lwarx		%0,0,%1\n\
-	cmpwi		0,%0,0\n\
-	bne-		1b\n\
-	lwz		%0,%2(13)\n\
-	stwcx.		%0,0,%1\n\
-	bne-		2b\n\
-	isync"
-	: "=&r"(tmp)
-	: "r"(&lock->lock), "i"(offsetof(struct paca_struct, lock_token))
-	: "cr0", "memory");
+	return __spin_trylock(lock) == 0;
 }
 
-/*
- * Note: if we ever want to inline the spinlocks on iSeries,
- * we will have to change the irq enable/disable stuff in here.
- */
-static __inline__ void _raw_spin_lock_flags(spinlock_t *lock,
-					    unsigned long flags)
+static void __inline__ _raw_spin_lock(spinlock_t *lock)
 {
-	unsigned int tmp;
-	unsigned long tmp2;
-
-	__asm__ __volatile__(
-	"b		3f		# spin_lock\n\
-1:	mfmsr		%1\n\
-	mtmsrd		%3,1\n\
-2:"	HMT_LOW
-"	lwzx		%0,0,%2\n\
-	cmpwi		0,%0,0\n\
-	bne+		2b\n"
-	HMT_MEDIUM
-"	mtmsrd		%1,1\n\
-3:	lwarx		%0,0,%2\n\
-	cmpwi		0,%0,0\n\
-	bne-		1b\n\
-	lwz		%1,%4(13)\n\
-	stwcx.		%1,0,%2\n\
-	bne-		3b\n\
-	isync"
-	: "=&r"(tmp), "=&r"(tmp2)
-	: "r"(&lock->lock), "r"(flags),
-	  "i" (offsetof(struct paca_struct, lock_token))
-	: "cr0", "memory");
+	while (1) {
+		if (likely(__spin_trylock(lock) == 0))
+			break;
+		do {
+			HMT_low();
+			if (SHARED_PROCESSOR)
+				__spin_yield(lock);
+		} while (likely(lock->lock != 0));
+		HMT_medium();
+	}
 }
 
-#define spin_unlock_wait(x)	do { cpu_relax(); } while (spin_is_locked(x))
+static void __inline__ _raw_spin_lock_flags(spinlock_t *lock, unsigned long flags)
+{
+	unsigned long flags_dis;
 
-#endif /* CONFIG_SPINLINE */
+	while (1) {
+		if (likely(__spin_trylock(lock) == 0))
+			break;
+		local_save_flags(flags_dis);
+		local_irq_restore(flags);
+		do {
+			HMT_low();
+			if (SHARED_PROCESSOR)
+				__spin_yield(lock);
+		} while (likely(lock->lock != 0));
+		HMT_medium();
+		local_irq_restore(flags_dis);
+	}
+}
 
 /*
  * Read-write spinlocks, allowing multiple readers
@@ -140,10 +138,6 @@
  * irq-safe write-lock, but readers can get non-irqsafe
  * read-locks.
  */
-typedef struct {
-	volatile signed int lock;
-} rwlock_t;
-
 #define RW_LOCK_UNLOCKED (rwlock_t) { 0 }
 
 #define rwlock_init(x)		do { *(x) = RW_LOCK_UNLOCKED; } while(0)
@@ -165,67 +159,54 @@
 	rw->lock = 0;
 }
 
-#ifndef CONFIG_SPINLINE
-extern int _raw_read_trylock(rwlock_t *rw);
-extern void _raw_read_lock(rwlock_t *rw);
-extern void _raw_read_unlock(rwlock_t *rw);
-extern int _raw_write_trylock(rwlock_t *rw);
-extern void _raw_write_lock(rwlock_t *rw);
-extern void _raw_write_unlock(rwlock_t *rw);
-
-#else
-static __inline__ int _raw_read_trylock(rwlock_t *rw)
+/*
+ * This returns the old value in the lock + 1,
+ * so we got a read lock if the return value is > 0.
+ */
+static long __inline__ __read_trylock(rwlock_t *rw)
 {
-	unsigned int tmp;
-	unsigned int ret;
+	long tmp;
 
 	__asm__ __volatile__(
-"1:	lwarx		%0,0,%2		# read_trylock\n\
-	li		%1,0\n\
+"1:	lwarx		%0,0,%1		# read_trylock\n\
 	extsw		%0,%0\n\
 	addic.		%0,%0,1\n\
 	ble-		2f\n\
-	stwcx.		%0,0,%2\n\
+	stwcx.		%0,0,%1\n\
 	bne-		1b\n\
-	li		%1,1\n\
 	isync\n\
-2:"	: "=&r"(tmp), "=&r"(ret)
-	: "r"(&rw->lock)
-	: "cr0", "memory");
+2:"	: "=&r" (tmp)
+	: "r" (&rw->lock)
+	: "cr0", "xer", "memory");
 
-	return ret;
+	return tmp;
 }
 
-static __inline__ void _raw_read_lock(rwlock_t *rw)
+static int __inline__ _raw_read_trylock(rwlock_t *rw)
 {
-	unsigned int tmp;
+	return __read_trylock(rw) > 0;
+}
 
-	__asm__ __volatile__(
-	"b		2f		# read_lock\n\
-1:"
-	HMT_LOW
-"	lwax		%0,0,%1\n\
-	cmpwi		0,%0,0\n\
-	blt+		1b\n"
-	HMT_MEDIUM
-"2:	lwarx		%0,0,%1\n\
-	extsw		%0,%0\n\
-	addic.		%0,%0,1\n\
-	ble-		1b\n\
-	stwcx.		%0,0,%1\n\
-	bne-		2b\n\
-	isync"
-	: "=&r"(tmp)
-	: "r"(&rw->lock)
-	: "cr0", "memory");
+static void __inline__ _raw_read_lock(rwlock_t *rw)
+{
+	while (1) {
+		if (likely(__read_trylock(rw) > 0))
+			break;
+		do {
+			HMT_low();
+			if (SHARED_PROCESSOR)
+				__rw_yield(rw);
+		} while (likely(rw->lock < 0));
+		HMT_medium();
+	}
 }
 
-static __inline__ void _raw_read_unlock(rwlock_t *rw)
+static void __inline__ _raw_read_unlock(rwlock_t *rw)
 {
-	unsigned int tmp;
+	long tmp;
 
 	__asm__ __volatile__(
-	"lwsync				# read_unlock\n\
+	"eieio				# read_unlock\n\
 1:	lwarx		%0,0,%1\n\
 	addic		%0,%0,-1\n\
 	stwcx.		%0,0,%1\n\
@@ -235,50 +216,47 @@
 	: "cr0", "memory");
 }
 
-static __inline__ int _raw_write_trylock(rwlock_t *rw)
+/*
+ * This returns the old value in the lock,
+ * so we got the write lock if the return value is 0.
+ */
+static __inline__ long __write_trylock(rwlock_t *rw)
 {
-	unsigned int tmp;
-	unsigned int ret;
+	long tmp, tmp2;
 
 	__asm__ __volatile__(
-"1:	lwarx		%0,0,%2		# write_trylock\n\
+"	lwz		%1,%3(13)	# write_trylock\n\
+1:	lwarx		%0,0,%2\n\
 	cmpwi		0,%0,0\n\
-	li		%1,0\n\
 	bne-		2f\n\
-	stwcx.		%3,0,%2\n\
+	stwcx.		%1,0,%2\n\
 	bne-		1b\n\
-	li		%1,1\n\
 	isync\n\
-2:"	: "=&r"(tmp), "=&r"(ret)
-	: "r"(&rw->lock), "r"(-1)
+2:"	: "=&r" (tmp), "=&r" (tmp2)
+	: "r" (&rw->lock), "i" (offsetof(struct paca_struct, lock_token))
 	: "cr0", "memory");
 
-	return ret;
+	return tmp;
 }
 
-static __inline__ void _raw_write_lock(rwlock_t *rw)
+static int __inline__ _raw_write_trylock(rwlock_t *rw)
 {
-	unsigned int tmp;
+	return __write_trylock(rw) == 0;
+}
 
-	__asm__ __volatile__(
-	"b		2f		# write_lock\n\
-1:"
-	HMT_LOW
-	"lwax		%0,0,%1\n\
-	cmpwi		0,%0,0\n\
-	bne+		1b\n"
-	HMT_MEDIUM
-"2:	lwarx		%0,0,%1\n\
-	cmpwi		0,%0,0\n\
-	bne-		1b\n\
-	stwcx.		%2,0,%1\n\
-	bne-		2b\n\
-	isync"
-	: "=&r"(tmp)
-	: "r"(&rw->lock), "r"(-1)
-	: "cr0", "memory");
+static void __inline__ _raw_write_lock(rwlock_t *rw)
+{
+	while (1) {
+		if (likely(__write_trylock(rw) == 0))
+			break;
+		do {
+			HMT_low();
+			if (SHARED_PROCESSOR)
+				__rw_yield(rw);
+		} while (likely(rw->lock != 0));
+		HMT_medium();
+	}
 }
-#endif /* CONFIG_SPINLINE */
 
 #endif /* __KERNEL__ */
 #endif /* __ASM_SPINLOCK_H */
diff -Nru a/include/asm-ppc64/system.h b/include/asm-ppc64/system.h
--- a/include/asm-ppc64/system.h	2004-10-18 14:57:04 -07:00
+++ b/include/asm-ppc64/system.h	2004-10-18 14:57:04 -07:00
@@ -105,6 +105,7 @@
 extern void bad_page_fault(struct pt_regs *regs, unsigned long address,
 			   int sig);
 extern void show_regs(struct pt_regs * regs);
+extern void low_hash_fault(struct pt_regs *regs, unsigned long address);
 extern int die(const char *str, struct pt_regs *regs, long err);
 
 extern void flush_instruction_cache(void);
@@ -127,6 +128,8 @@
 {
 }
 #endif
+
+extern int mem_init_done;	/* set on boot once kmalloc can be called */
 
 /* EBCDIC -> ASCII conversion for [0-9A-Z] on iSeries */
 extern unsigned char e2a(unsigned char);
diff -Nru a/include/asm-ppc64/systemcfg.h b/include/asm-ppc64/systemcfg.h
--- a/include/asm-ppc64/systemcfg.h	2004-10-18 14:56:32 -07:00
+++ b/include/asm-ppc64/systemcfg.h	2004-10-18 14:56:32 -07:00
@@ -59,54 +59,7 @@
 
 #ifdef __KERNEL__
 extern struct systemcfg *systemcfg;
-#else
-
-/* Processor Version Register (PVR) field extraction */
-#define PVR_VER(pvr)  (((pvr) >>  16) & 0xFFFF) /* Version field */
-#define PVR_REV(pvr)  (((pvr) >>   0) & 0xFFFF) /* Revison field */
-
-/* Processor Version Numbers */
-#define PV_NORTHSTAR    0x0033
-#define PV_PULSAR       0x0034
-#define PV_POWER4       0x0035
-#define PV_ICESTAR      0x0036
-#define PV_SSTAR        0x0037
-#define PV_POWER4p      0x0038
-#define PV_GPUL		0x0039
-#define PV_POWER5	0x003a
-#define PV_970FX	0x003c
-#define PV_630          0x0040
-#define PV_630p         0x0041
-
-/* Platforms supported by PPC64 */
-#define PLATFORM_PSERIES      0x0100
-#define PLATFORM_PSERIES_LPAR 0x0101
-#define PLATFORM_ISERIES_LPAR 0x0201
-#define PLATFORM_POWERMAC     0x0400
-
-/* Compatibility with drivers coming from PPC32 world */
-#define _machine	(systemcfg->platform)
-#define _MACH_Pmac	PLATFORM_POWERMAC
-
-
-static inline volatile struct systemcfg *systemcfg_init(void)
-{
-	int fd = open("/proc/ppc64/systemcfg", O_RDONLY);
-	volatile struct systemcfg *ret;
-
-	if (fd == -1)
-		return 0;
-	ret = mmap(0, sizeof(struct systemcfg), PROT_READ, MAP_SHARED, fd, 0);
-	close(fd);
-	if (!ret)
-		return 0;
-	if (ret->version.major != SYSTEMCFG_MAJOR || ret->version.minor < SYSTEMCFG_MINOR) {
-		munmap((void *)ret, sizeof(struct systemcfg));
-		return 0;
-	}
-	return ret;
-}
-#endif /* __KERNEL__ */
+#endif
 
 #endif /* __ASSEMBLY__ */
 
diff -Nru a/include/asm-ppc64/tlb.h b/include/asm-ppc64/tlb.h
--- a/include/asm-ppc64/tlb.h	2004-10-18 14:57:19 -07:00
+++ b/include/asm-ppc64/tlb.h	2004-10-18 14:57:19 -07:00
@@ -15,7 +15,14 @@
 #include <asm/tlbflush.h>
 
 struct mmu_gather;
-static inline void tlb_flush(struct mmu_gather *tlb);
+
+extern void pte_free_finish(void);
+
+static inline void tlb_flush(struct mmu_gather *tlb)
+{
+	flush_tlb_pending();
+	pte_free_finish();
+}
 
 /* Avoid pulling in another include just for this */
 #define check_pgt_cache()	do { } while (0)
@@ -28,13 +35,5 @@
 #define tlb_end_vma(tlb, vma)	do { } while (0)
 
 #define __tlb_remove_tlb_entry(tlb, pte, address) do { } while (0)
-
-extern void pte_free_finish(void);
-
-static inline void tlb_flush(struct mmu_gather *tlb)
-{
-	flush_tlb_pending();
-	pte_free_finish();
-}
 
 #endif /* _PPC64_TLB_H */
diff -Nru a/include/asm-ppc64/uaccess.h b/include/asm-ppc64/uaccess.h
--- a/include/asm-ppc64/uaccess.h	2004-10-18 14:56:32 -07:00
+++ b/include/asm-ppc64/uaccess.h	2004-10-18 14:56:32 -07:00
@@ -111,6 +111,9 @@
 #define __put_user(x,ptr) \
   __put_user_nocheck((__typeof__(*(ptr)))(x),(ptr),sizeof(*(ptr)))
 
+#define __get_user_unaligned __get_user
+#define __put_user_unaligned __put_user
+
 extern long __put_user_bad(void);
 
 #define __put_user_nocheck(x,ptr,size)				\
@@ -280,6 +283,9 @@
 				  unsigned long n);
 
 extern unsigned long __clear_user(void __user *addr, unsigned long size);
+
+#define __copy_to_user_inatomic __copy_to_user
+#define __copy_from_user_inatomic __copy_from_user
 
 static inline unsigned long
 clear_user(void __user *addr, unsigned long size)
diff -Nru a/include/asm-ppc64/unistd.h b/include/asm-ppc64/unistd.h
--- a/include/asm-ppc64/unistd.h	2004-10-18 14:55:54 -07:00
+++ b/include/asm-ppc64/unistd.h	2004-10-18 14:55:54 -07:00
@@ -269,9 +269,9 @@
 /* Number 256 is reserved for sys_debug_setcontext */
 /* Number 257 is reserved for vserver */
 /* Number 258 is reserved for new sys_remap_file_pages */
-/* Number 259 is reserved for new sys_mbind */
-/* Number 260 is reserved for new sys_get_mempolicy */
-/* Number 261 is reserved for new sys_set_mempolicy */
+#define __NR_mbind		259
+#define __NR_get_mempolicy	260
+#define __NR_set_mempolicy	261
 #define __NR_mq_open		262
 #define __NR_mq_unlink		263
 #define __NR_mq_timedsend	264
diff -Nru a/include/asm-s390/bug.h b/include/asm-s390/bug.h
--- a/include/asm-s390/bug.h	2004-10-18 14:56:49 -07:00
+++ b/include/asm-s390/bug.h	2004-10-18 14:56:49 -07:00
@@ -6,22 +6,9 @@
 #define BUG() do { \
         printk("kernel BUG at %s:%d!\n", __FILE__, __LINE__); \
         __asm__ __volatile__(".long 0"); \
-} while (0)                                       
-
-#define BUG_ON(condition) do { \
-	if (unlikely((condition)!=0)) \
-		BUG(); \
-} while(0)
-
-#define PAGE_BUG(page) do { \
-        BUG(); \
-} while (0)                      
-
-#define WARN_ON(condition) do { \
-	if (unlikely((condition)!=0)) { \
-		printk("Badness in %s at %s:%d\n", __FUNCTION__, __FILE__, __LINE__); \
-		dump_stack(); \
-	} \
 } while (0)
+
+#define HAVE_ARCH_BUG
+#include <asm-generic/bug.h>
 
 #endif
diff -Nru a/include/asm-s390/dma-mapping.h b/include/asm-s390/dma-mapping.h
--- a/include/asm-s390/dma-mapping.h	2004-10-18 14:57:18 -07:00
+++ b/include/asm-s390/dma-mapping.h	2004-10-18 14:57:18 -07:00
@@ -9,17 +9,6 @@
 #ifndef _ASM_DMA_MAPPING_H
 #define _ASM_DMA_MAPPING_H
 
-static inline void *dma_alloc_coherent(struct device *dev, size_t size,
-			 dma_addr_t *dma_handle, int flag)
-{
-	BUG();
-	return 0;
-}
-
-static inline void dma_free_coherent(struct device *dev, size_t size,
-		       void *vaddr, dma_addr_t dma_handle)
-{
-	BUG();
-}
+#include <asm-generic/dma-mapping-broken.h>
 
 #endif /* _ASM_DMA_MAPPING_H */
diff -Nru a/include/asm-s390/hardirq.h b/include/asm-s390/hardirq.h
--- a/include/asm-s390/hardirq.h	2004-10-18 14:57:05 -07:00
+++ b/include/asm-s390/hardirq.h	2004-10-18 14:57:05 -07:00
@@ -61,57 +61,20 @@
 #define SOFTIRQ_SHIFT	(PREEMPT_SHIFT + PREEMPT_BITS)
 #define HARDIRQ_SHIFT	(SOFTIRQ_SHIFT + SOFTIRQ_BITS)
 
-#define __MASK(x)	((1UL << (x))-1)
-
-#define PREEMPT_MASK	(__MASK(PREEMPT_BITS) << PREEMPT_SHIFT)
-#define SOFTIRQ_MASK	(__MASK(SOFTIRQ_BITS) << SOFTIRQ_SHIFT)
-#define HARDIRQ_MASK	(__MASK(HARDIRQ_BITS) << HARDIRQ_SHIFT)
-
-#define hardirq_count()	(preempt_count() & HARDIRQ_MASK)
-#define softirq_count()	(preempt_count() & SOFTIRQ_MASK)
-#define irq_count()	(preempt_count() & (HARDIRQ_MASK | SOFTIRQ_MASK))
-
-#define PREEMPT_OFFSET	(1UL << PREEMPT_SHIFT)
-#define SOFTIRQ_OFFSET	(1UL << SOFTIRQ_SHIFT)
-#define HARDIRQ_OFFSET	(1UL << HARDIRQ_SHIFT)
-
-/*
- * Are we doing bottom half or hardware interrupt processing?
- * Are we in a softirq context? Interrupt context?
- */
-#define in_irq()		(hardirq_count())
-#define in_softirq()		(softirq_count())
-#define in_interrupt()		(irq_count())
-
+extern void account_ticks(struct pt_regs *);
 
-#define hardirq_trylock()	(!in_interrupt())
-#define hardirq_endlock()	do { } while (0)
+#define __ARCH_HAS_DO_SOFTIRQ
 
 #define irq_enter()							\
 do {									\
 	(preempt_count() += HARDIRQ_OFFSET);				\
 } while(0)
-	
-
-extern void do_call_softirq(void);
-extern void account_ticks(struct pt_regs *);
-
-#define invoke_softirq() do_call_softirq()
-
-#ifdef CONFIG_PREEMPT
-# define in_atomic()	((preempt_count() & ~PREEMPT_ACTIVE) != kernel_locked())
-# define IRQ_EXIT_OFFSET (HARDIRQ_OFFSET-1)
-#else
-# define in_atomic()	(preempt_count() != 0)
-# define IRQ_EXIT_OFFSET HARDIRQ_OFFSET
-#endif
-
 #define irq_exit()							\
 do {									\
 	preempt_count() -= IRQ_EXIT_OFFSET;				\
 	if (!in_interrupt() && local_softirq_pending())			\
 		/* Use the async. stack for softirq */			\
-		do_call_softirq();					\
+		do_softirq();						\
 	preempt_enable_no_resched();					\
 } while (0)
 
diff -Nru a/include/asm-s390/idals.h b/include/asm-s390/idals.h
--- a/include/asm-s390/idals.h	2004-10-18 14:55:54 -07:00
+++ b/include/asm-s390/idals.h	2004-10-18 14:55:54 -07:00
@@ -35,7 +35,7 @@
 idal_is_needed(void *vaddr, unsigned int length)
 {
 #ifdef __s390x__
-	return ((__pa(vaddr) + length) >> 31) != 0;
+	return ((__pa(vaddr) + length - 1) >> 31) != 0;
 #else
 	return 0;
 #endif
diff -Nru a/include/asm-s390/irq.h b/include/asm-s390/irq.h
--- a/include/asm-s390/irq.h	2004-10-18 14:56:50 -07:00
+++ b/include/asm-s390/irq.h	2004-10-18 14:56:50 -07:00
@@ -2,7 +2,7 @@
 #define _ASM_IRQ_H
 
 #ifdef __KERNEL__
-#include <asm/hardirq.h>
+#include <linux/hardirq.h>
 
 /*
  * the definition of irqs has changed in 2.5.46:
diff -Nru a/include/asm-s390/lowcore.h b/include/asm-s390/lowcore.h
--- a/include/asm-s390/lowcore.h	2004-10-18 14:56:29 -07:00
+++ b/include/asm-s390/lowcore.h	2004-10-18 14:56:29 -07:00
@@ -68,6 +68,7 @@
 #define __LC_ASYNC_STACK                0xC48
 #define __LC_KERNEL_ASCE		0xC4C
 #define __LC_USER_ASCE			0xC50
+#define __LC_PANIC_STACK                0xC54
 #define __LC_CPUID                      0xC60
 #define __LC_CPUADDR                    0xC68
 #define __LC_IPLDEV                     0xC7C
@@ -80,6 +81,7 @@
 #define __LC_ASYNC_STACK                0xD50
 #define __LC_KERNEL_ASCE		0xD58
 #define __LC_USER_ASCE			0xD60
+#define __LC_PANIC_STACK                0xD68
 #define __LC_CPUID                      0xD90
 #define __LC_CPUADDR                    0xD98
 #define __LC_IPLDEV                     0xDB8
@@ -176,7 +178,8 @@
 	__u32        async_stack;              /* 0xc48 */
 	__u32        kernel_asce;              /* 0xc4c */
 	__u32        user_asce;                /* 0xc50 */
-	__u8         pad10[0xc60-0xc54];       /* 0xc54 */
+	__u32        panic_stack;              /* 0xc54 */
+	__u8         pad10[0xc60-0xc58];       /* 0xc58 */
 	/* entry.S sensitive area start */
 	struct       cpuinfo_S390 cpu_data;    /* 0xc60 */
 	__u32        ipl_device;               /* 0xc7c */
@@ -257,7 +260,8 @@
 	__u64        async_stack;              /* 0xd50 */
 	__u64        kernel_asce;              /* 0xd58 */
 	__u64        user_asce;                /* 0xd60 */
-	__u8         pad10[0xd80-0xd68];       /* 0xd68 */
+	__u64        panic_stack;              /* 0xd68 */
+	__u8         pad10[0xd80-0xd70];       /* 0xd70 */
 	/* entry.S sensitive area start */
 	struct       cpuinfo_S390 cpu_data;    /* 0xd80 */
 	__u32        ipl_device;               /* 0xdb8 */
diff -Nru a/include/asm-s390/page.h b/include/asm-s390/page.h
--- a/include/asm-s390/page.h	2004-10-18 14:56:16 -07:00
+++ b/include/asm-s390/page.h	2004-10-18 14:56:16 -07:00
@@ -162,6 +162,25 @@
 #define __pgd(x)        ((pgd_t) { (x) } )
 #define __pgprot(x)     ((pgprot_t) { (x) } )
 
+/* default storage key used for all pages */
+extern unsigned int default_storage_key;
+
+static inline void
+page_set_storage_key(unsigned long addr, unsigned int skey)
+{
+	asm volatile ( "sske %0,%1" : : "d" (skey), "a" (addr) );
+}
+
+static inline unsigned int
+page_get_storage_key(unsigned long addr)
+{
+	unsigned int skey;
+
+	asm volatile ( "iske %0,%1" : "=d" (skey) : "a" (addr), "0" (0) );
+
+	return skey;
+}
+
 #endif /* !__ASSEMBLY__ */
 
 /* to align the pointer to the (next) page boundary */
diff -Nru a/include/asm-s390/pgtable.h b/include/asm-s390/pgtable.h
--- a/include/asm-s390/pgtable.h	2004-10-18 14:56:49 -07:00
+++ b/include/asm-s390/pgtable.h	2004-10-18 14:56:49 -07:00
@@ -597,17 +597,13 @@
  * should therefore only be called if it is not mapped in any
  * address space.
  */
-#define page_test_and_clear_dirty(page)					  \
+#define page_test_and_clear_dirty(_page)				  \
 ({									  \
-	struct page *__page = (page);					  \
+	struct page *__page = (_page);					  \
 	unsigned long __physpage = __pa((__page-mem_map) << PAGE_SHIFT);  \
-	int __skey;							  \
-	asm volatile ("iske %0,%1" : "=d" (__skey) : "a" (__physpage));   \
-	if (__skey & _PAGE_CHANGED) {					  \
-		asm volatile ("sske %0,%1"				  \
-			      : : "d" (__skey & ~_PAGE_CHANGED),	  \
-			          "a" (__physpage));			  \
-	}								  \
+	int __skey = page_get_storage_key(__physpage);			  \
+	if (__skey & _PAGE_CHANGED)					  \
+		page_set_storage_key(__physpage, __skey & ~_PAGE_CHANGED);\
 	(__skey & _PAGE_CHANGED);					  \
 })
 
@@ -655,11 +651,10 @@
 })
 
 #define SetPageUptodate(_page) \
-	do {								  \
-		struct page *__page = (_page);				  \
-		if (!test_and_set_bit(PG_uptodate, &__page->flags))	  \
-			asm volatile ("sske %0,%1" : : "d" (0),		  \
-			      "a" (__pa((__page-mem_map) << PAGE_SHIFT)));\
+	do {								      \
+		struct page *__page = (_page);				      \
+		if (!test_and_set_bit(PG_uptodate, &__page->flags))	      \
+			page_test_and_clear_dirty(_page);		      \
 	} while (0)
 
 #ifdef __s390x__
diff -Nru a/include/asm-s390/processor.h b/include/asm-s390/processor.h
--- a/include/asm-s390/processor.h	2004-10-18 14:56:29 -07:00
+++ b/include/asm-s390/processor.h	2004-10-18 14:56:29 -07:00
@@ -76,6 +76,8 @@
 
 #define MM_VM_SIZE(mm)		DEFAULT_TASK_SIZE
 
+#define HAVE_ARCH_PICK_MMAP_LAYOUT
+
 typedef struct {
         __u32 ar4;
 } mm_segment_t;
@@ -100,6 +102,25 @@
 };
 
 typedef struct thread_struct thread_struct;
+
+/*
+ * Stack layout of a C stack frame.
+ */
+#ifndef __PACK_STACK
+struct stack_frame {
+	unsigned long back_chain;
+	unsigned long empty1[5];
+	unsigned long gprs[10];
+	unsigned int  empty2[8];
+};
+#else
+struct stack_frame {
+	unsigned long empty1[5];
+	unsigned int  empty2[8];
+	unsigned long gprs[10];
+	unsigned long back_chain;
+};
+#endif
 
 #define ARCH_MIN_TASKALIGN	8
 
diff -Nru a/include/asm-s390/ptrace.h b/include/asm-s390/ptrace.h
--- a/include/asm-s390/ptrace.h	2004-10-18 14:56:48 -07:00
+++ b/include/asm-s390/ptrace.h	2004-10-18 14:56:48 -07:00
@@ -466,6 +466,7 @@
 #ifdef __KERNEL__
 #define user_mode(regs) (((regs)->psw.mask & PSW_MASK_PSTATE) != 0)
 #define instruction_pointer(regs) ((regs)->psw.addr & PSW_ADDR_INSN)
+#define profile_pc(regs) instruction_pointer(regs)
 extern void show_regs(struct pt_regs * regs);
 #endif
 
diff -Nru a/include/asm-s390/resource.h b/include/asm-s390/resource.h
--- a/include/asm-s390/resource.h	2004-10-18 14:56:28 -07:00
+++ b/include/asm-s390/resource.h	2004-10-18 14:56:28 -07:00
@@ -47,7 +47,7 @@
 	{ RLIM_INFINITY, RLIM_INFINITY },		\
 	{             0,             0 },		\
 	{ INR_OPEN, INR_OPEN },                         \
-	{ RLIM_INFINITY, RLIM_INFINITY },		\
+	{   MLOCK_LIMIT,   MLOCK_LIMIT },		\
 	{ RLIM_INFINITY, RLIM_INFINITY },		\
 	{ RLIM_INFINITY, RLIM_INFINITY },		\
 	{ MAX_SIGPENDING, MAX_SIGPENDING },		\
diff -Nru a/include/asm-s390/socket.h b/include/asm-s390/socket.h
--- a/include/asm-s390/socket.h	2004-10-18 14:56:33 -07:00
+++ b/include/asm-s390/socket.h	2004-10-18 14:56:33 -07:00
@@ -55,20 +55,4 @@
 
 #define SO_PEERSEC		31
 
-/* Nast libc5 fixup - bletch */
-#if defined(__KERNEL__)
-/* Socket types. */
-#define SOCK_STREAM	1		/* stream (connection) socket	*/
-#define SOCK_DGRAM	2		/* datagram (conn.less) socket	*/
-#define SOCK_RAW	3		/* raw socket			*/
-#define SOCK_RDM	4		/* reliably-delivered message	*/
-#define SOCK_SEQPACKET	5		/* sequential packet socket	*/
-#define SOCK_PACKET	10		/* linux specific way of	*/
-					/* getting packets at the dev	*/
-					/* level.  For writing rarp and	*/
-					/* other similar things on the	*/
-					/* user level.			*/
-#define	SOCK_MAX	(SOCK_PACKET+1)
-#endif
-
 #endif /* _ASM_SOCKET_H */
diff -Nru a/include/asm-s390/thread_info.h b/include/asm-s390/thread_info.h
--- a/include/asm-s390/thread_info.h	2004-10-18 14:56:48 -07:00
+++ b/include/asm-s390/thread_info.h	2004-10-18 14:56:48 -07:00
@@ -11,6 +11,30 @@
 
 #ifdef __KERNEL__
 
+/*
+ * Size of kernel stack for each process
+ */
+#ifndef __s390x__
+#ifndef __SMALL_STACK
+#define THREAD_ORDER 1
+#define ASYNC_ORDER  1
+#else
+#define THREAD_ORDER 0
+#define ASYNC_ORDER  0
+#endif
+#else /* __s390x__ */
+#ifndef __SMALL_STACK
+#define THREAD_ORDER 2
+#define ASYNC_ORDER  2
+#else
+#define THREAD_ORDER 1
+#define ASYNC_ORDER  1
+#endif
+#endif /* __s390x__ */
+
+#define THREAD_SIZE (PAGE_SIZE << THREAD_ORDER)
+#define ASYNC_SIZE  (PAGE_SIZE << ASYNC_ORDER)
+
 #ifndef __ASSEMBLY__
 #include <asm/processor.h>
 #include <asm/lowcore.h>
@@ -46,20 +70,6 @@
 
 #define init_thread_info	(init_thread_union.thread_info)
 #define init_stack		(init_thread_union.stack)
-
-/*
- * Size of kernel stack for each process
- */
-#ifndef __s390x__
-#define THREAD_ORDER 1
-#define ASYNC_ORDER  1
-#else /* __s390x__ */
-#define THREAD_ORDER 2
-#define ASYNC_ORDER  2
-#endif /* __s390x__ */
-
-#define THREAD_SIZE (PAGE_SIZE << THREAD_ORDER)
-#define ASYNC_SIZE  (PAGE_SIZE << ASYNC_ORDER)
 
 /* how to get the thread information struct from C */
 static inline struct thread_info *current_thread_info(void)
diff -Nru a/include/asm-s390/timer.h b/include/asm-s390/timer.h
--- a/include/asm-s390/timer.h	2004-10-18 14:56:18 -07:00
+++ b/include/asm-s390/timer.h	2004-10-18 14:56:18 -07:00
@@ -45,6 +45,4 @@
 extern int mod_virt_timer(struct vtimer_list *timer, __u64 expires);
 extern int del_virt_timer(struct vtimer_list *timer);
 
-int stop_timers(void);
-
 #endif
diff -Nru a/include/asm-s390/uaccess.h b/include/asm-s390/uaccess.h
--- a/include/asm-s390/uaccess.h	2004-10-18 14:56:17 -07:00
+++ b/include/asm-s390/uaccess.h	2004-10-18 14:56:17 -07:00
@@ -250,6 +250,9 @@
 
 extern int __get_user_bad(void);
 
+#define __put_user_unaligned __put_user
+#define __get_user_unaligned __get_user
+
 extern long __copy_to_user_asm(const void *from, long n, void __user *to);
 
 /**
@@ -271,6 +274,9 @@
 {
 	return __copy_to_user_asm(from, n, to);
 }
+
+#define __copy_to_user_inatomic __copy_to_user
+#define __copy_from_user_inatomic __copy_from_user
 
 /**
  * copy_to_user: - Copy a block of data into user space.
diff -Nru a/include/asm-sh/bug.h b/include/asm-sh/bug.h
--- a/include/asm-sh/bug.h	2004-10-18 14:57:03 -07:00
+++ b/include/asm-sh/bug.h	2004-10-18 14:57:03 -07:00
@@ -11,20 +11,7 @@
 	asm volatile("nop"); \
 } while (0)
 
-#define BUG_ON(condition) do { \
-	if (unlikely((condition)!=0)) \
-		BUG(); \
-} while(0)
-
-#define PAGE_BUG(page) do { \
-	BUG(); \
-} while (0)
-
-#define WARN_ON(condition) do { \
-	if (unlikely((condition)!=0)) { \
-		printk("Badness in %s at %s:%d\n", __FUNCTION__, __FILE__, __LINE__); \
-		dump_stack(); \
-	} \
-} while (0)
+#define HAVE_ARCH_BUG
+#include <asm-generic/bug.h>
 
 #endif
diff -Nru a/include/asm-sh/cacheflush.h b/include/asm-sh/cacheflush.h
--- a/include/asm-sh/cacheflush.h	2004-10-18 14:56:29 -07:00
+++ b/include/asm-sh/cacheflush.h	2004-10-18 14:56:29 -07:00
@@ -14,10 +14,16 @@
 #define flush_cache_vunmap(start, end)		flush_cache_all()
 
 #define copy_to_user_page(vma, page, vaddr, dst, src, len) \
-do { memcpy(dst, src, len); \
-     flush_icache_user_range(vma, page, vaddr, len); \
-} while (0)
+	do {							\
+		flush_cache_page(vma, vaddr);			\
+		memcpy(dst, src, len);				\
+		flush_icache_user_range(vma, page, vaddr, len);	\
+	} while (0)
+
 #define copy_from_user_page(vma, page, vaddr, dst, src, len) \
-	memcpy(dst, src, len)
+	do {							\
+		flush_cache_page(vma, vaddr);			\
+		memcpy(dst, src, len);				\
+	} while (0)
 
 #endif /* __ASM_SH_CACHEFLUSH_H */
diff -Nru a/include/asm-sh/dma-mapping.h b/include/asm-sh/dma-mapping.h
--- a/include/asm-sh/dma-mapping.h	2004-10-18 14:57:05 -07:00
+++ b/include/asm-sh/dma-mapping.h	2004-10-18 14:57:05 -07:00
@@ -3,7 +3,6 @@
 
 #include <linux/config.h>
 #include <linux/mm.h>
-#include <linux/device.h>
 #include <asm/scatterlist.h>
 #include <asm/io.h>
 
diff -Nru a/include/asm-sh/hardirq.h b/include/asm-sh/hardirq.h
--- a/include/asm-sh/hardirq.h	2004-10-18 14:56:28 -07:00
+++ b/include/asm-sh/hardirq.h	2004-10-18 14:56:28 -07:00
@@ -35,20 +35,6 @@
 #define SOFTIRQ_SHIFT	(PREEMPT_SHIFT + PREEMPT_BITS)
 #define HARDIRQ_SHIFT	(SOFTIRQ_SHIFT + SOFTIRQ_BITS)
 
-#define __MASK(x)	((1UL << (x))-1)
-
-#define PREEMPT_MASK	(__MASK(PREEMPT_BITS) << PREEMPT_SHIFT)
-#define HARDIRQ_MASK	(__MASK(HARDIRQ_BITS) << HARDIRQ_SHIFT)
-#define SOFTIRQ_MASK	(__MASK(SOFTIRQ_BITS) << SOFTIRQ_SHIFT)
-
-#define hardirq_count()	(preempt_count() & HARDIRQ_MASK)
-#define softirq_count()	(preempt_count() & SOFTIRQ_MASK)
-#define irq_count()	(preempt_count() & (HARDIRQ_MASK | SOFTIRQ_MASK))
-
-#define PREEMPT_OFFSET	(1UL << PREEMPT_SHIFT)
-#define SOFTIRQ_OFFSET	(1UL << SOFTIRQ_SHIFT)
-#define HARDIRQ_OFFSET	(1UL << HARDIRQ_SHIFT)
-
 /*
  * The hardirq mask has to be large enough to have
  * space for potentially all IRQ sources in the system
@@ -58,29 +44,10 @@
 # error HARDIRQ_BITS is too low!
 #endif
 
-/*
- * Are we in an interrupt context? Either doing bottom half
- * or hardware interrupt processing?
- */
-#define in_irq()		(hardirq_count())
-#define in_softirq()		(softirq_count())
-#define in_interrupt()		(irq_count())
-
-
-#define hardirq_trylock()	(!in_interrupt())
-#define hardirq_endlock()	do { } while (0)
-
-#define irq_enter()		(preempt_count() += HARDIRQ_OFFSET)
 #define nmi_enter()		(irq_enter())
 #define nmi_exit()		(preempt_count() -= HARDIRQ_OFFSET)
 
-#ifdef CONFIG_PREEMPT
-# define in_atomic()	((preempt_count() & ~PREEMPT_ACTIVE) != kernel_locked())
-# define IRQ_EXIT_OFFSET (HARDIRQ_OFFSET-1)
-#else
-# define in_atomic()	(preempt_count() != 0)
-# define IRQ_EXIT_OFFSET HARDIRQ_OFFSET
-#endif
+#define irq_enter()		(preempt_count() += HARDIRQ_OFFSET)
 #define irq_exit()							\
 do {									\
 		preempt_count() -= IRQ_EXIT_OFFSET;			\
@@ -88,11 +55,5 @@
 			do_softirq();					\
 		preempt_enable_no_resched();				\
 } while (0)
-
-#ifndef CONFIG_SMP
-# define synchronize_irq(irq)	barrier()
-#else
-extern void synchronize_irq(unsigned int irq);
-#endif /* CONFIG_SMP */
 
 #endif /* __ASM_SH_HARDIRQ_H */
diff -Nru a/include/asm-sh/ptrace.h b/include/asm-sh/ptrace.h
--- a/include/asm-sh/ptrace.h	2004-10-18 14:56:50 -07:00
+++ b/include/asm-sh/ptrace.h	2004-10-18 14:56:50 -07:00
@@ -90,6 +90,15 @@
 #define user_mode(regs) (((regs)->sr & 0x40000000)==0)
 #define instruction_pointer(regs) ((regs)->pc)
 extern void show_regs(struct pt_regs *);
+
+static inline unsigned long profile_pc(struct pt_regs *regs)
+{
+	unsigned long pc = instruction_pointer(regs);
+
+	if (pc >= 0xa0000000UL && pc < 0xc0000000UL)
+		pc -= 0x20000000;
+	return pc;
+}
 #endif
 
 #endif /* __ASM_SH_PTRACE_H */
diff -Nru a/include/asm-sh/resource.h b/include/asm-sh/resource.h
--- a/include/asm-sh/resource.h	2004-10-18 14:56:33 -07:00
+++ b/include/asm-sh/resource.h	2004-10-18 14:56:33 -07:00
@@ -39,7 +39,7 @@
 	{ RLIM_INFINITY, RLIM_INFINITY },		\
 	{             0,             0 },		\
 	{      INR_OPEN,     INR_OPEN  },		\
-	{ RLIM_INFINITY, RLIM_INFINITY },		\
+	{   MLOCK_LIMIT,   MLOCK_LIMIT },		\
 	{ RLIM_INFINITY, RLIM_INFINITY },		\
 	{ RLIM_INFINITY, RLIM_INFINITY },		\
 	{ MAX_SIGPENDING, MAX_SIGPENDING },		\
diff -Nru a/include/asm-sh/semaphore.h b/include/asm-sh/semaphore.h
--- a/include/asm-sh/semaphore.h	2004-10-18 14:57:04 -07:00
+++ b/include/asm-sh/semaphore.h	2004-10-18 14:57:04 -07:00
@@ -24,21 +24,14 @@
 	atomic_t count;
 	int sleepers;
 	wait_queue_head_t wait;
-#ifdef WAITQUEUE_DEBUG
-	long __magic;
-#endif
 };
 
-#ifdef WAITQUEUE_DEBUG
-# define __SEM_DEBUG_INIT(name) \
-		, (int)&(name).__magic
-#else
-# define __SEM_DEBUG_INIT(name)
-#endif
-
-#define __SEMAPHORE_INITIALIZER(name,count) \
-{ ATOMIC_INIT(count), 0, __WAIT_QUEUE_HEAD_INITIALIZER((name).wait) \
-	__SEM_DEBUG_INIT(name) }
+#define __SEMAPHORE_INITIALIZER(name, n)				\
+{									\
+	.count		= ATOMIC_INIT(n),				\
+	.sleepers	= 0,						\
+	.wait		= __WAIT_QUEUE_HEAD_INITIALIZER((name).wait)	\
+}
 
 #define __MUTEX_INITIALIZER(name) \
 	__SEMAPHORE_INITIALIZER(name,1)
@@ -60,9 +53,6 @@
 	atomic_set(&sem->count, val);
 	sem->sleepers = 0;
 	init_waitqueue_head(&sem->wait);
-#ifdef WAITQUEUE_DEBUG
-	sem->__magic = (int)&sem->__magic;
-#endif
 }
 
 static inline void init_MUTEX (struct semaphore *sem)
@@ -91,10 +81,6 @@
 
 static inline void down(struct semaphore * sem)
 {
-#ifdef WAITQUEUE_DEBUG
-	CHECK_MAGIC(sem->__magic);
-#endif
-
 	might_sleep();
 	if (atomic_dec_return(&sem->count) < 0)
 		__down(sem);
@@ -103,9 +89,6 @@
 static inline int down_interruptible(struct semaphore * sem)
 {
 	int ret = 0;
-#ifdef WAITQUEUE_DEBUG
-	CHECK_MAGIC(sem->__magic);
-#endif
 
 	might_sleep();
 	if (atomic_dec_return(&sem->count) < 0)
@@ -116,9 +99,6 @@
 static inline int down_trylock(struct semaphore * sem)
 {
 	int ret = 0;
-#ifdef WAITQUEUE_DEBUG
-	CHECK_MAGIC(sem->__magic);
-#endif
 
 	if (atomic_dec_return(&sem->count) < 0)
 		ret = __down_trylock(sem);
@@ -131,9 +111,6 @@
  */
 static inline void up(struct semaphore * sem)
 {
-#ifdef WAITQUEUE_DEBUG
-	CHECK_MAGIC(sem->__magic);
-#endif
 	if (atomic_inc_return(&sem->count) <= 0)
 		__up(sem);
 }
diff -Nru a/include/asm-sh/socket.h b/include/asm-sh/socket.h
--- a/include/asm-sh/socket.h	2004-10-18 14:56:31 -07:00
+++ b/include/asm-sh/socket.h	2004-10-18 14:56:31 -07:00
@@ -47,20 +47,4 @@
 
 #define SO_PEERSEC		31
 
-/* Nast libc5 fixup - bletch */
-#if defined(__KERNEL__)
-/* Socket types. */
-#define SOCK_STREAM	1		/* stream (connection) socket	*/
-#define SOCK_DGRAM	2		/* datagram (conn.less) socket	*/
-#define SOCK_RAW	3		/* raw socket			*/
-#define SOCK_RDM	4		/* reliably-delivered message	*/
-#define SOCK_SEQPACKET	5		/* sequential packet socket	*/
-#define SOCK_PACKET	10		/* linux specific way of	*/
-					/* getting packets at the dev	*/
-					/* level.  For writing rarp and	*/
-					/* other similar things on the	*/
-					/* user level.			*/
-#define	SOCK_MAX	(SOCK_PACKET+1)
-#endif
-
 #endif /* __ASM_SH_SOCKET_H */
diff -Nru a/include/asm-sh/uaccess.h b/include/asm-sh/uaccess.h
--- a/include/asm-sh/uaccess.h	2004-10-18 14:56:29 -07:00
+++ b/include/asm-sh/uaccess.h	2004-10-18 14:56:29 -07:00
@@ -446,6 +446,10 @@
 	__copy_user((void *)(to),		\
 		    (void *)(from), n)
 
+#define __copy_to_user_inatomic __copy_to_user
+#define __copy_from_user_inatomic __copy_from_user
+
+
 #define copy_from_user(to,from,n) ({ \
 void *__copy_to = (void *) (to); \
 void *__copy_from = (void *) (from); \
diff -Nru a/include/asm-sh64/cacheflush.h b/include/asm-sh64/cacheflush.h
--- a/include/asm-sh64/cacheflush.h	2004-10-18 14:56:28 -07:00
+++ b/include/asm-sh64/cacheflush.h	2004-10-18 14:56:28 -07:00
@@ -30,13 +30,17 @@
 #define flush_icache_page(vma, page)	do { } while (0)
 
 #define copy_to_user_page(vma, page, vaddr, dst, src, len) \
-do { memcpy(dst, src, len); \
-     flush_icache_user_range(vma, page, vaddr, len); \
-} while (0)
+	do {							\
+		flush_cache_page(vma, vaddr);			\
+		memcpy(dst, src, len);				\
+		flush_icache_user_range(vma, page, vaddr, len);	\
+	} while (0)
 
 #define copy_from_user_page(vma, page, vaddr, dst, src, len) \
-	memcpy(dst, src, len)
-
+	do {							\
+		flush_cache_page(vma, vaddr);			\
+		memcpy(dst, src, len);				\
+	} while (0)
 
 #endif /* __ASSEMBLY__ */
 
diff -Nru a/include/asm-sh64/dma-mapping.h b/include/asm-sh64/dma-mapping.h
--- a/include/asm-sh64/dma-mapping.h	2004-10-18 14:57:05 -07:00
+++ b/include/asm-sh64/dma-mapping.h	2004-10-18 14:57:05 -07:00
@@ -3,7 +3,6 @@
 
 #include <linux/config.h>
 #include <linux/mm.h>
-#include <linux/device.h>
 #include <asm/scatterlist.h>
 #include <asm/io.h>
 
diff -Nru a/include/asm-sh64/ptrace.h b/include/asm-sh64/ptrace.h
--- a/include/asm-sh64/ptrace.h	2004-10-18 14:56:48 -07:00
+++ b/include/asm-sh64/ptrace.h	2004-10-18 14:56:48 -07:00
@@ -28,6 +28,7 @@
 #ifdef __KERNEL__
 #define user_mode(regs) (((regs)->sr & 0x40000000)==0)
 #define instruction_pointer(regs) ((regs)->pc)
+#define profile_pc(regs) instruction_pointer(regs)
 extern void show_regs(struct pt_regs *);
 #endif
 
diff -Nru a/include/asm-sh64/semaphore.h b/include/asm-sh64/semaphore.h
--- a/include/asm-sh64/semaphore.h	2004-10-18 14:56:28 -07:00
+++ b/include/asm-sh64/semaphore.h	2004-10-18 14:56:28 -07:00
@@ -31,21 +31,14 @@
 	atomic_t count;
 	int sleepers;
 	wait_queue_head_t wait;
-#ifdef WAITQUEUE_DEBUG
-	long __magic;
-#endif
 };
 
-#ifdef WAITQUEUE_DEBUG
-# define __SEM_DEBUG_INIT(name) \
-		, (int)&(name).__magic
-#else
-# define __SEM_DEBUG_INIT(name)
-#endif
-
-#define __SEMAPHORE_INITIALIZER(name,count) \
-{ ATOMIC_INIT(count), 0, __WAIT_QUEUE_HEAD_INITIALIZER((name).wait) \
-	__SEM_DEBUG_INIT(name) }
+#define __SEMAPHORE_INITIALIZER(name, n)				\
+{									\
+	.count		= ATOMIC_INIT(n),				\
+	.sleepers	= 0,						\
+	.wait		= __WAIT_QUEUE_HEAD_INITIALIZER((name).wait)	\
+}
 
 #define __MUTEX_INITIALIZER(name) \
 	__SEMAPHORE_INITIALIZER(name,1)
@@ -67,9 +60,6 @@
 	atomic_set(&sem->count, val);
 	sem->sleepers = 0;
 	init_waitqueue_head(&sem->wait);
-#ifdef WAITQUEUE_DEBUG
-	sem->__magic = (int)&sem->__magic;
-#endif
 }
 
 static inline void init_MUTEX (struct semaphore *sem)
@@ -98,10 +88,6 @@
 
 static inline void down(struct semaphore * sem)
 {
-#ifdef WAITQUEUE_DEBUG
-	CHECK_MAGIC(sem->__magic);
-#endif
-
 	if (atomic_dec_return(&sem->count) < 0)
 		__down(sem);
 }
@@ -109,9 +95,6 @@
 static inline int down_interruptible(struct semaphore * sem)
 {
 	int ret = 0;
-#ifdef WAITQUEUE_DEBUG
-	CHECK_MAGIC(sem->__magic);
-#endif
 
 	if (atomic_dec_return(&sem->count) < 0)
 		ret = __down_interruptible(sem);
@@ -121,9 +104,6 @@
 static inline int down_trylock(struct semaphore * sem)
 {
 	int ret = 0;
-#ifdef WAITQUEUE_DEBUG
-	CHECK_MAGIC(sem->__magic);
-#endif
 
 	if (atomic_dec_return(&sem->count) < 0)
 		ret = __down_trylock(sem);
@@ -136,9 +116,6 @@
  */
 static inline void up(struct semaphore * sem)
 {
-#ifdef WAITQUEUE_DEBUG
-	CHECK_MAGIC(sem->__magic);
-#endif
 	if (atomic_inc_return(&sem->count) <= 0)
 		__up(sem);
 }
diff -Nru a/include/asm-sh64/smplock.h b/include/asm-sh64/smplock.h
--- a/include/asm-sh64/smplock.h	2004-10-18 14:55:54 -07:00
+++ /dev/null	Wed Dec 31 16:00:00 196900
@@ -1,77 +0,0 @@
-#ifndef __ASM_SH64_SMPLOCK_H
-#define __ASM_SH64_SMPLOCK_H
-
-/*
- * 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.
- *
- * include/asm-sh64/smplock.h
- *
- * Copyright (C) 2000, 2001  Paolo Alberelli
- *
- */
-
-#include <linux/config.h>
-
-#ifndef CONFIG_SMP
-
-#define lock_kernel()				do { } while(0)
-#define unlock_kernel()				do { } while(0)
-#define release_kernel_lock(task, cpu, depth)	((depth) = 1)
-#define reacquire_kernel_lock(task, cpu, depth)	do { } while(0)
-
-#else
-
-#error "We do not support SMP on SH64 yet"
-/*
- * Default SMP lock implementation
- */
-
-#include <linux/interrupt.h>
-#include <asm/spinlock.h>
-
-extern spinlock_t kernel_flag;
-
-/*
- * Getting the big kernel lock.
- *
- * This cannot happen asynchronously,
- * so we only need to worry about other
- * CPU's.
- */
-extern __inline__ void lock_kernel(void)
-{
-	if (!++current->lock_depth)
-		spin_lock(&kernel_flag);
-}
-
-extern __inline__ void unlock_kernel(void)
-{
-	if (--current->lock_depth < 0)
-		spin_unlock(&kernel_flag);
-}
-
-/*
- * Release global kernel lock and global interrupt lock
- */
-#define release_kernel_lock(task, cpu) \
-do { \
-	if (task->lock_depth >= 0) \
-		spin_unlock(&kernel_flag); \
-	release_irqlock(cpu); \
-	__sti(); \
-} while (0)
-
-/*
- * Re-acquire the kernel lock
- */
-#define reacquire_kernel_lock(task) \
-do { \
-	if (task->lock_depth >= 0) \
-		spin_lock(&kernel_flag); \
-} while (0)
-
-#endif /* CONFIG_SMP */
-
-#endif /* __ASM_SH64_SMPLOCK_H */
diff -Nru a/include/asm-sh64/softirq.h b/include/asm-sh64/softirq.h
--- a/include/asm-sh64/softirq.h	2004-10-18 14:55:55 -07:00
+++ /dev/null	Wed Dec 31 16:00:00 196900
@@ -1,30 +0,0 @@
-#ifndef __ASM_SH_SOFTIRQ_H
-#define __ASM_SH_SOFTIRQ_H
-
-#include <asm/atomic.h>
-#include <asm/hardirq.h>
-
-#define local_bh_disable()			\
-do {						\
-	local_bh_count(smp_processor_id())++;	\
-	barrier();				\
-} while (0)
-
-#define __local_bh_enable()			\
-do {						\
-	barrier();				\
-	local_bh_count(smp_processor_id())--;	\
-} while (0)
-
-#define local_bh_enable()				\
-do {							\
-	barrier();					\
-	if (!--local_bh_count(smp_processor_id())	\
-	    && softirq_pending(smp_processor_id())) {	\
-		do_softirq();				\
-	}						\
-} while (0)
-
-#define in_softirq() (local_bh_count(smp_processor_id()) != 0)
-
-#endif /* __ASM_SH_SOFTIRQ_H */
diff -Nru a/include/asm-sh64/uaccess.h b/include/asm-sh64/uaccess.h
--- a/include/asm-sh64/uaccess.h	2004-10-18 14:56:27 -07:00
+++ b/include/asm-sh64/uaccess.h	2004-10-18 14:56:27 -07:00
@@ -261,6 +261,9 @@
 	return retval; \
 })
 
+#define __copy_to_user_inatomic __copy_to_user
+#define __copy_from_user_inatomic __copy_from_user
+
 /* XXX: Not sure it works well..
    should be such that: 4byte clear and the rest. */
 extern __kernel_size_t __clear_user(void *addr, __kernel_size_t size);
diff -Nru a/include/asm-sparc/bug.h b/include/asm-sparc/bug.h
--- a/include/asm-sparc/bug.h	2004-10-18 14:57:05 -07:00
+++ b/include/asm-sparc/bug.h	2004-10-18 14:57:05 -07:00
@@ -25,20 +25,7 @@
 #define BUG()		__bug_trap()
 #endif
 
-#define BUG_ON(condition) do { \
-	if (unlikely((condition)!=0)) \
-		BUG(); \
-} while(0)
-
-#define PAGE_BUG(page) do { \
-	BUG(); \
-} while (0)
-
-#define WARN_ON(condition) do { \
-	if (unlikely((condition)!=0)) { \
-		printk("Badness in %s at %s:%d\n", __FUNCTION__, __FILE__, __LINE__); \
-		dump_stack(); \
-	} \
-} while (0)
+#define HAVE_ARCH_BUG
+#include <asm-generic/bug.h>
 
 #endif
diff -Nru a/include/asm-sparc/cacheflush.h b/include/asm-sparc/cacheflush.h
--- a/include/asm-sparc/cacheflush.h	2004-10-18 14:56:28 -07:00
+++ b/include/asm-sparc/cacheflush.h	2004-10-18 14:56:28 -07:00
@@ -57,9 +57,15 @@
 #define flush_icache_user_range(vma,pg,adr,len)	do { } while (0)
 
 #define copy_to_user_page(vma, page, vaddr, dst, src, len) \
-	memcpy(dst, src, len)
+	do {					\
+		flush_cache_page(vma, vaddr);	\
+		memcpy(dst, src, len);		\
+	} while (0)
 #define copy_from_user_page(vma, page, vaddr, dst, src, len) \
-	memcpy(dst, src, len)
+	do {					\
+		flush_cache_page(vma, vaddr);	\
+		memcpy(dst, src, len);		\
+	} while (0)
 
 BTFIXUPDEF_CALL(void, __flush_page_to_ram, unsigned long)
 BTFIXUPDEF_CALL(void, flush_sig_insns, struct mm_struct *, unsigned long)
diff -Nru a/include/asm-sparc/dma-mapping.h b/include/asm-sparc/dma-mapping.h
--- a/include/asm-sparc/dma-mapping.h	2004-10-18 14:57:04 -07:00
+++ b/include/asm-sparc/dma-mapping.h	2004-10-18 14:57:04 -07:00
@@ -2,7 +2,6 @@
 #define _ASM_SPARC_DMA_MAPPING_H
 
 #include <linux/config.h>
-#include <linux/device.h>
 
 #ifdef CONFIG_PCI
 #include <asm-generic/dma-mapping.h>
diff -Nru a/include/asm-sparc/hardirq.h b/include/asm-sparc/hardirq.h
--- a/include/asm-sparc/hardirq.h	2004-10-18 14:57:18 -07:00
+++ b/include/asm-sparc/hardirq.h	2004-10-18 14:57:18 -07:00
@@ -42,42 +42,7 @@
 #define SOFTIRQ_SHIFT   (PREEMPT_SHIFT + PREEMPT_BITS)
 #define HARDIRQ_SHIFT   (SOFTIRQ_SHIFT + SOFTIRQ_BITS)
 
-#define __MASK(x)       ((1UL << (x))-1)
-
-#define PREEMPT_MASK    (__MASK(PREEMPT_BITS) << PREEMPT_SHIFT)
-#define HARDIRQ_MASK    (__MASK(HARDIRQ_BITS) << HARDIRQ_SHIFT)
-#define SOFTIRQ_MASK    (__MASK(SOFTIRQ_BITS) << SOFTIRQ_SHIFT)
-
-#define hardirq_count() (preempt_count() & HARDIRQ_MASK)
-#define softirq_count() (preempt_count() & SOFTIRQ_MASK)
-#define irq_count()     (preempt_count() & (HARDIRQ_MASK | SOFTIRQ_MASK))
-
-#define PREEMPT_OFFSET  (1UL << PREEMPT_SHIFT)
-#define SOFTIRQ_OFFSET  (1UL << SOFTIRQ_SHIFT)
-#define HARDIRQ_OFFSET  (1UL << HARDIRQ_SHIFT)
-
-/*
- * Are we doing bottom half or hardware interrupt processing?
- * Are we in a softirq context? Interrupt context?
- */
-#define in_irq()                (hardirq_count())
-#define in_softirq()            (softirq_count())
-#define in_interrupt()          (irq_count())
-
-
-#define hardirq_trylock()       (!in_interrupt())
-#define hardirq_endlock()       do { } while (0)
-
 #define irq_enter()             (preempt_count() += HARDIRQ_OFFSET)
-
-#ifdef CONFIG_PREEMPT
-#include <linux/smp_lock.h>
-# define in_atomic()	((preempt_count() & ~PREEMPT_ACTIVE) != kernel_locked())
-# define IRQ_EXIT_OFFSET (HARDIRQ_OFFSET-1)
-#else
-# define in_atomic()	(preempt_count() != 0)
-# define IRQ_EXIT_OFFSET HARDIRQ_OFFSET
-#endif
 #define irq_exit()                                                      \
 do {                                                                    \
                 preempt_count() -= IRQ_EXIT_OFFSET;                     \
@@ -85,11 +50,5 @@
                         do_softirq();                                   \
                 preempt_enable_no_resched();                            \
 } while (0)
-
-#ifndef CONFIG_SMP
-# define synchronize_irq(irq)	barrier()
-#else /* SMP */
-extern void synchronize_irq(unsigned int irq);
-#endif /* SMP */
 
 #endif /* __SPARC_HARDIRQ_H */
diff -Nru a/include/asm-sparc/ptrace.h b/include/asm-sparc/ptrace.h
--- a/include/asm-sparc/ptrace.h	2004-10-18 14:57:03 -07:00
+++ b/include/asm-sparc/ptrace.h	2004-10-18 14:57:03 -07:00
@@ -62,6 +62,7 @@
 #ifdef __KERNEL__
 #define user_mode(regs) (!((regs)->psr & PSR_PS))
 #define instruction_pointer(regs) ((regs)->pc)
+unsigned long profile_pc(struct pt_regs *);
 extern void show_regs(struct pt_regs *);
 #endif
 
diff -Nru a/include/asm-sparc/resource.h b/include/asm-sparc/resource.h
--- a/include/asm-sparc/resource.h	2004-10-18 14:55:55 -07:00
+++ b/include/asm-sparc/resource.h	2004-10-18 14:55:55 -07:00
@@ -44,7 +44,7 @@
     {       0, RLIM_INFINITY},		\
     {RLIM_INFINITY, RLIM_INFINITY},	\
     {INR_OPEN, INR_OPEN}, {0, 0},	\
-    {RLIM_INFINITY, RLIM_INFINITY},	\
+    {MLOCK_LIMIT,   MLOCK_LIMIT},	\
     {RLIM_INFINITY, RLIM_INFINITY},	\
     {RLIM_INFINITY, RLIM_INFINITY},	\
     {MAX_SIGPENDING, MAX_SIGPENDING},	\
diff -Nru a/include/asm-sparc/semaphore.h b/include/asm-sparc/semaphore.h
--- a/include/asm-sparc/semaphore.h	2004-10-18 14:57:04 -07:00
+++ b/include/asm-sparc/semaphore.h	2004-10-18 14:57:04 -07:00
@@ -13,21 +13,14 @@
 	atomic24_t count;
 	int sleepers;
 	wait_queue_head_t wait;
-#ifdef WAITQUEUE_DEBUG
-	long __magic;
-#endif
 };
 
-#ifdef WAITQUEUE_DEBUG
-# define __SEM_DEBUG_INIT(name) \
-		, (long)&(name).__magic
-#else
-# define __SEM_DEBUG_INIT(name)
-#endif
-
-#define __SEMAPHORE_INITIALIZER(name,count) \
-{ ATOMIC24_INIT(count), 0, __WAIT_QUEUE_HEAD_INITIALIZER((name).wait) \
-	__SEM_DEBUG_INIT(name) }
+#define __SEMAPHORE_INITIALIZER(name, n)				\
+{									\
+	.count		= ATOMIC24_INIT(n),				\
+	.sleepers	= 0,						\
+	.wait		= __WAIT_QUEUE_HEAD_INITIALIZER((name).wait)	\
+}
 
 #define __MUTEX_INITIALIZER(name) \
 	__SEMAPHORE_INITIALIZER(name,1)
@@ -43,9 +36,6 @@
 	atomic24_set(&sem->count, val);
 	sem->sleepers = 0;
 	init_waitqueue_head(&sem->wait);
-#ifdef WAITQUEUE_DEBUG
-	sem->__magic = (long)&sem->__magic;
-#endif
 }
 
 static inline void init_MUTEX (struct semaphore *sem)
@@ -68,9 +58,6 @@
 	register volatile int *ptr asm("g1");
 	register int increment asm("g2");
 
-#ifdef WAITQUEUE_DEBUG
-	CHECK_MAGIC(sem->__magic);
-#endif
 	might_sleep();
 
 	ptr = &(sem->count.counter);
@@ -105,9 +92,6 @@
 	register volatile int *ptr asm("g1");
 	register int increment asm("g2");
 
-#ifdef WAITQUEUE_DEBUG
-	CHECK_MAGIC(sem->__magic);
-#endif
 	might_sleep();
 
 	ptr = &(sem->count.counter);
@@ -145,10 +129,6 @@
 	register volatile int *ptr asm("g1");
 	register int increment asm("g2");
 
-#ifdef WAITQUEUE_DEBUG
-	CHECK_MAGIC(sem->__magic);
-#endif
-
 	ptr = &(sem->count.counter);
 	increment = 1;
 
@@ -183,10 +163,6 @@
 {
 	register volatile int *ptr asm("g1");
 	register int increment asm("g2");
-
-#ifdef WAITQUEUE_DEBUG
-	CHECK_MAGIC(sem->__magic);
-#endif
 
 	ptr = &(sem->count.counter);
 	increment = 1;
diff -Nru a/include/asm-sparc/sigcontext.h b/include/asm-sparc/sigcontext.h
--- a/include/asm-sparc/sigcontext.h	2004-10-18 14:56:20 -07:00
+++ b/include/asm-sparc/sigcontext.h	2004-10-18 14:56:20 -07:00
@@ -57,20 +57,6 @@
 	} si_fpqueue [16];
 } __siginfo_fpu_t;
 
-#ifdef __KERNEL__
-
-/* This magic should be in g_upper[0] for all upper parts
-   to be valid.
-   This is generated by sparc64 only, but for 32bit processes,
-   so we define it here as well.  */
-#define SIGINFO_EXTRA_V8PLUS_MAGIC      0x130e269
-typedef struct {
-	unsigned   int g_upper[8];
-	unsigned   int o_upper[8];
-} siginfo_extra_v8plus_t;
-
-#endif
-
 #endif /* !(__ASSEMBLY__) */
 
 #endif /* !(__SPARC_SIGCONTEXT_H) */
diff -Nru a/include/asm-sparc/socket.h b/include/asm-sparc/socket.h
--- a/include/asm-sparc/socket.h	2004-10-18 14:56:33 -07:00
+++ b/include/asm-sparc/socket.h	2004-10-18 14:56:33 -07:00
@@ -52,20 +52,4 @@
 #define SO_SECURITY_ENCRYPTION_TRANSPORT	0x5002
 #define SO_SECURITY_ENCRYPTION_NETWORK		0x5004
 
-/* Nast libc5 fixup - bletch */
-#if defined(__KERNEL__)
-/* Socket types. */
-#define SOCK_STREAM	1		/* stream (connection) socket	*/
-#define SOCK_DGRAM	2		/* datagram (conn.less) socket	*/
-#define SOCK_RAW	3		/* raw socket			*/
-#define SOCK_RDM	4		/* reliably-delivered message	*/
-#define SOCK_SEQPACKET	5		/* sequential packet socket	*/
-#define SOCK_PACKET	10		/* linux specific way of	*/
-					/* getting packets at the dev	*/
-					/* level.  For writing rarp and	*/
-					/* other similar things on the	*/
-					/* user level.			*/
-#define	SOCK_MAX	(SOCK_PACKET+1)
-#endif
-
 #endif /* _ASM_SOCKET_H */
diff -Nru a/include/asm-sparc/uaccess.h b/include/asm-sparc/uaccess.h
--- a/include/asm-sparc/uaccess.h	2004-10-18 14:57:03 -07:00
+++ b/include/asm-sparc/uaccess.h	2004-10-18 14:57:03 -07:00
@@ -322,6 +322,9 @@
 	return __copy_user((void __user *) to, from, n);
 }
 
+#define __copy_to_user_inatomic __copy_to_user
+#define __copy_from_user_inatomic __copy_from_user
+
 static inline unsigned long __clear_user(void __user *addr, unsigned long size)
 {
 	unsigned long ret;
diff -Nru a/include/asm-sparc/unistd.h b/include/asm-sparc/unistd.h
--- a/include/asm-sparc/unistd.h	2004-10-18 14:55:54 -07:00
+++ b/include/asm-sparc/unistd.h	2004-10-18 14:55:54 -07:00
@@ -290,11 +290,12 @@
 #define __NR_io_cancel		271
 #define __NR_io_getevents	272
 #define __NR_mq_open		273
-#define __NR_mq_unlink		(__NR_mq_open+1)
-#define __NR_mq_timedsend	(__NR_mq_open+2)
-#define __NR_mq_timedreceive	(__NR_mq_open+3)
-#define __NR_mq_notify		(__NR_mq_open+4)
-#define __NR_mq_getsetattr	(__NR_mq_open+5)
+#define __NR_mq_unlink		274
+#define __NR_mq_timedsend	275
+#define __NR_mq_timedreceive	276
+#define __NR_mq_notify		277
+#define __NR_mq_getsetattr	278
+#define __NR_waitid		279
 
 /* WARNING: You MAY NOT add syscall numbers larger than 282, since
  *          all of the syscall tables in the Sparc kernel are
diff -Nru a/include/asm-sparc/vaddrs.h b/include/asm-sparc/vaddrs.h
--- a/include/asm-sparc/vaddrs.h	2004-10-18 14:55:54 -07:00
+++ b/include/asm-sparc/vaddrs.h	2004-10-18 14:55:54 -07:00
@@ -33,9 +33,9 @@
 
 #define SUN4M_IOBASE_VADDR	0xfd000000 /* Base for mapping pages */
 #define IOBASE_VADDR		0xfe000000
-#define IOBASE_END		0xfe300000
+#define IOBASE_END		0xfe600000
 
-#define VMALLOC_START		0xfe300000
+#define VMALLOC_START		0xfe600000
 
 /* XXX Alter this when I get around to fixing sun4c - Anton */
 #define VMALLOC_END		0xffc00000
diff -Nru a/include/asm-sparc64/bitops.h b/include/asm-sparc64/bitops.h
--- a/include/asm-sparc64/bitops.h	2004-10-18 14:56:13 -07:00
+++ b/include/asm-sparc64/bitops.h	2004-10-18 14:56:13 -07:00
@@ -228,13 +228,10 @@
 #define find_first_zero_bit(addr, size) \
         find_next_zero_bit((addr), (size), 0)
 
-extern long ___test_and_set_le_bit(int nr, volatile unsigned long *addr);
-extern long ___test_and_clear_le_bit(int nr, volatile unsigned long *addr);
-
-#define test_and_set_le_bit(nr,addr)	({___test_and_set_le_bit(nr,addr)!=0;})
-#define test_and_clear_le_bit(nr,addr)	({___test_and_clear_le_bit(nr,addr)!=0;})
-#define set_le_bit(nr,addr)		((void)___test_and_set_le_bit(nr,addr))
-#define clear_le_bit(nr,addr)		((void)___test_and_clear_le_bit(nr,addr))
+#define test_and_set_le_bit(nr,addr)	\
+	({ ___test_and_set_bit((nr) ^ 0x38, (addr)) != 0; })
+#define test_and_clear_le_bit(nr,addr)	\
+	({ ___test_and_clear_bit((nr) ^ 0x38, (addr)) != 0; })
 
 static __inline__ int test_le_bit(int nr, __const__ unsigned long * addr)
 {
@@ -253,22 +250,30 @@
 
 #ifdef __KERNEL__
 
-#define ext2_set_bit(nr,addr)		test_and_set_le_bit((nr),(unsigned long *)(addr))
-#define ext2_set_bit_atomic(lock,nr,addr) test_and_set_le_bit((nr),(unsigned long *)(addr))
-#define ext2_clear_bit(nr,addr)		test_and_clear_le_bit((nr),(unsigned long *)(addr))
-#define ext2_clear_bit_atomic(lock,nr,addr) test_and_clear_le_bit((nr),(unsigned long *)(addr))
-#define ext2_test_bit(nr,addr)		test_le_bit((nr),(unsigned long *)(addr))
+#define ext2_set_bit(nr,addr)	\
+	test_and_set_le_bit((nr),(unsigned long *)(addr))
+#define ext2_set_bit_atomic(lock,nr,addr) \
+	test_and_set_le_bit((nr),(unsigned long *)(addr))
+#define ext2_clear_bit(nr,addr)	\
+	test_and_clear_le_bit((nr),(unsigned long *)(addr))
+#define ext2_clear_bit_atomic(lock,nr,addr) \
+	test_and_clear_le_bit((nr),(unsigned long *)(addr))
+#define ext2_test_bit(nr,addr)	\
+	test_le_bit((nr),(unsigned long *)(addr))
 #define ext2_find_first_zero_bit(addr, size) \
 	find_first_zero_le_bit((unsigned long *)(addr), (size))
 #define ext2_find_next_zero_bit(addr, size, off) \
 	find_next_zero_le_bit((unsigned long *)(addr), (size), (off))
 
 /* Bitmap functions for the minix filesystem.  */
-#define minix_test_and_set_bit(nr,addr)	test_and_set_bit((nr),(unsigned long *)(addr))
-#define minix_set_bit(nr,addr)		set_bit((nr),(unsigned long *)(addr))
+#define minix_test_and_set_bit(nr,addr)	\
+	test_and_set_bit((nr),(unsigned long *)(addr))
+#define minix_set_bit(nr,addr)	\
+	set_bit((nr),(unsigned long *)(addr))
 #define minix_test_and_clear_bit(nr,addr) \
 	test_and_clear_bit((nr),(unsigned long *)(addr))
-#define minix_test_bit(nr,addr)		test_bit((nr),(unsigned long *)(addr))
+#define minix_test_bit(nr,addr)	\
+	test_bit((nr),(unsigned long *)(addr))
 #define minix_find_first_zero_bit(addr,size) \
 	find_first_zero_bit((unsigned long *)(addr),(size))
 
diff -Nru a/include/asm-sparc64/bug.h b/include/asm-sparc64/bug.h
--- a/include/asm-sparc64/bug.h	2004-10-18 14:56:33 -07:00
+++ b/include/asm-sparc64/bug.h	2004-10-18 14:56:33 -07:00
@@ -1,5 +1,3 @@
-/* $Id$ */
-
 #ifndef _SPARC64_BUG_H
 #define _SPARC64_BUG_H
 
@@ -15,20 +13,7 @@
 #define BUG()		__builtin_trap()
 #endif
 
-#define BUG_ON(condition) do { \
-	if (unlikely((condition)!=0)) \
-		BUG(); \
-} while(0)
-
-#define PAGE_BUG(page) do { \
-	BUG(); \
-} while (0)
-
-#define WARN_ON(condition) do { \
-	if (unlikely((condition)!=0)) { \
-		printk("Badness in %s at %s:%d\n", __FUNCTION__, __FILE__, __LINE__); \
-		dump_stack(); \
-	} \
-} while (0)
+#define HAVE_ARCH_BUG
+#include <asm-generic/bug.h>
 
 #endif
diff -Nru a/include/asm-sparc64/cacheflush.h b/include/asm-sparc64/cacheflush.h
--- a/include/asm-sparc64/cacheflush.h	2004-10-18 14:57:04 -07:00
+++ b/include/asm-sparc64/cacheflush.h	2004-10-18 14:57:04 -07:00
@@ -38,9 +38,16 @@
 #define flush_icache_user_range(vma,pg,adr,len)	do { } while (0)
 
 #define copy_to_user_page(vma, page, vaddr, dst, src, len) \
-	memcpy(dst, src, len)
+	do {					\
+		flush_cache_page(vma, vaddr);	\
+		memcpy(dst, src, len);		\
+	} while (0)
+
 #define copy_from_user_page(vma, page, vaddr, dst, src, len) \
-	memcpy(dst, src, len)
+	do {					\
+		flush_cache_page(vma, vaddr);	\
+		memcpy(dst, src, len);		\
+	} while (0)
 
 extern void flush_dcache_page(struct page *page);
 #define flush_dcache_mmap_lock(mapping)		do { } while (0)
diff -Nru a/include/asm-sparc64/checksum.h b/include/asm-sparc64/checksum.h
--- a/include/asm-sparc64/checksum.h	2004-10-18 14:56:28 -07:00
+++ b/include/asm-sparc64/checksum.h	2004-10-18 14:56:28 -07:00
@@ -40,7 +40,7 @@
  */
 extern unsigned int csum_partial_copy_sparc64(const char *src, char *dst, int len, unsigned int sum);
 			
-static __inline__ unsigned int 
+static inline unsigned int 
 csum_partial_copy_nocheck (const char *src, char *dst, int len, 
 			   unsigned int sum)
 {
@@ -52,22 +52,23 @@
 	return ret;
 }
 
-static __inline__ unsigned int 
-csum_partial_copy_from_user(const char *src, char *dst, int len, 
+static inline unsigned int 
+csum_partial_copy_from_user(const char __user *src, char *dst, int len, 
 			    unsigned int sum, int *err)
 {
 	__asm__ __volatile__ ("stx	%0, [%%sp + 0x7ff + 128]"
 			      : : "r" (err));
-	return csum_partial_copy_sparc64(src, dst, len, sum);
+	return csum_partial_copy_sparc64((__force const char *) src,
+					 dst, len, sum);
 }
 
 /* 
  *	Copy and checksum to user
  */
 #define HAVE_CSUM_COPY_USER
-extern unsigned int csum_partial_copy_user_sparc64(const char *src, char *dst, int len, unsigned int sum);
+extern unsigned int csum_partial_copy_user_sparc64(const char *src, char __user *dst, int len, unsigned int sum);
 
-static __inline__ unsigned int 
+static inline unsigned int 
 csum_and_copy_to_user(const char *src, char __user *dst, int len, 
 		      unsigned int sum, int *err)
 {
@@ -83,7 +84,7 @@
 				   unsigned int ihl);
 
 /* Fold a partial checksum without adding pseudo headers. */
-static __inline__ unsigned short csum_fold(unsigned int sum)
+static inline unsigned short csum_fold(unsigned int sum)
 {
 	unsigned int tmp;
 
@@ -98,11 +99,11 @@
 	return (sum & 0xffff);
 }
 
-static __inline__ unsigned long csum_tcpudp_nofold(unsigned long saddr,
-						   unsigned long daddr,
-						   unsigned int len,
-						   unsigned short proto,
-						   unsigned int sum)
+static inline unsigned long csum_tcpudp_nofold(unsigned long saddr,
+					       unsigned long daddr,
+					       unsigned int len,
+					       unsigned short proto,
+					       unsigned int sum)
 {
 	__asm__ __volatile__(
 "	addcc		%1, %0, %0\n"
@@ -130,11 +131,11 @@
 
 #define _HAVE_ARCH_IPV6_CSUM
 
-static __inline__ unsigned short int csum_ipv6_magic(struct in6_addr *saddr,
-						     struct in6_addr *daddr,
-						     __u32 len,
-						     unsigned short proto,
-						     unsigned int sum) 
+static inline unsigned short int csum_ipv6_magic(struct in6_addr *saddr,
+						 struct in6_addr *daddr,
+						 __u32 len,
+						 unsigned short proto,
+						 unsigned int sum) 
 {
 	__asm__ __volatile__ (
 "	addcc		%3, %4, %%g7\n"
@@ -165,7 +166,7 @@
 }
 
 /* this routine is used for miscellaneous IP-like checksums, mainly in icmp.c */
-static __inline__ unsigned short ip_compute_csum(unsigned char * buff, int len)
+static inline unsigned short ip_compute_csum(unsigned char * buff, int len)
 {
 	return csum_fold(csum_partial(buff, len, 0));
 }
diff -Nru a/include/asm-sparc64/delay.h b/include/asm-sparc64/delay.h
--- a/include/asm-sparc64/delay.h	2004-10-18 14:56:48 -07:00
+++ b/include/asm-sparc64/delay.h	2004-10-18 14:56:48 -07:00
@@ -1,7 +1,11 @@
-/* $Id: delay.h,v 1.13 2002/02/02 03:33:48 kanoj Exp $
- * delay.h: Linux delay routines on the V9.
+/* delay.h: Linux delay routines on sparc64.
  *
- * Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu).
+ * Copyright (C) 1996, 2004 David S. Miller (davem@davemloft.net).
+ *
+ * Based heavily upon x86 variant which is:
+ * Copyright (C) 1993 Linus Torvalds
+ *
+ * Delay routines calling functions in arch/sparc64/lib/delay.c
  */
 
 #ifndef __SPARC64_DELAY_H
@@ -13,50 +17,21 @@
 
 #ifndef __ASSEMBLY__
 
-static __inline__ 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");
-}
-
-static __inline__ void __udelay(unsigned long usecs, unsigned long lps)
-{
-	usecs *= 0x00000000000010c6UL;		/* 2**32 / 1000000 */
-
-	__asm__ __volatile__(
-"	mulx	%1, %2, %0\n"
-"	srlx	%0, 32, %0\n"
-	: "=r" (usecs)
-	: "r" (usecs), "r" (lps));
-
-	__delay(usecs * HZ);
-}
-
-extern __inline__ void __ndelay(unsigned long usecs, unsigned long lps)
-{
-	usecs *= 0x0000000000000005UL;		/* 2**32 / 10000 */
-
-	__asm__ __volatile__(
-"	mulx	%1, %2, %0\n"
-"	srlx	%0, 32, %0\n"
-	: "=r" (usecs)
-	: "r" (usecs), "r" (lps));
-
-	__delay(usecs * HZ);
-}
-
-#define __udelay_val cpu_data(smp_processor_id()).udelay_val
+extern void __bad_udelay(void);
+extern void __bad_ndelay(void);
 
-#define udelay(usecs) __udelay((usecs),__udelay_val)
-#define ndelay(usecs) __ndelay((usecs),__udelay_val)
+extern void __udelay(unsigned long usecs);
+extern void __ndelay(unsigned long nsecs);
+extern void __const_udelay(unsigned long usecs);
+extern void __delay(unsigned long loops);
+
+#define udelay(n) (__builtin_constant_p(n) ? \
+	((n) > 20000 ? __bad_udelay() : __const_udelay((n) * 0x10c7ul)) : \
+	__udelay(n))
+	
+#define ndelay(n) (__builtin_constant_p(n) ? \
+	((n) > 20000 ? __bad_ndelay() : __const_udelay((n) * 5ul)) : \
+	__ndelay(n))
 
 #endif /* !__ASSEMBLY__ */
 
diff -Nru a/include/asm-sparc64/dma.h b/include/asm-sparc64/dma.h
--- a/include/asm-sparc64/dma.h	2004-10-18 14:55:53 -07:00
+++ b/include/asm-sparc64/dma.h	2004-10-18 14:55:53 -07:00
@@ -62,7 +62,7 @@
 struct sbus_dma {
 	struct sbus_dma *next;
 	struct sbus_dev *sdev;
-	unsigned long regs;
+	void __iomem *regs;
 
 	/* Status, misc info */
 	int node;                /* Prom node for this DMA device */
diff -Nru a/include/asm-sparc64/ebus.h b/include/asm-sparc64/ebus.h
--- a/include/asm-sparc64/ebus.h	2004-10-18 14:56:48 -07:00
+++ b/include/asm-sparc64/ebus.h	2004-10-18 14:56:48 -07:00
@@ -53,7 +53,7 @@
 
 struct ebus_dma_info {
 	spinlock_t	lock;
-	unsigned long	regs;
+	void __iomem	*regs;
 
 	unsigned int	flags;
 #define EBUS_DMA_FLAG_USE_EBDMA_HANDLER		0x00000001
diff -Nru a/include/asm-sparc64/elf.h b/include/asm-sparc64/elf.h
--- a/include/asm-sparc64/elf.h	2004-10-18 14:56:28 -07:00
+++ b/include/asm-sparc64/elf.h	2004-10-18 14:56:28 -07:00
@@ -94,12 +94,12 @@
 #define ELF_CORE_COPY_REGS(__elf_regs, __pt_regs)	\
 do {	unsigned long *dest = &(__elf_regs[0]);		\
 	struct pt_regs *src = (__pt_regs);		\
-	unsigned long *sp;				\
+	unsigned long __user *sp;			\
 	int i;						\
 	for(i = 0; i < 16; i++)				\
 		dest[i] = src->u_regs[i];		\
 	/* Don't try this at home kids... */		\
-	sp = (unsigned long *)				\
+	sp = (unsigned long __user *)			\
 	 ((src->u_regs[14] + STACK_BIAS)		\
 	  & 0xfffffffffffffff8UL);			\
 	for(i = 0; i < 16; i++)				\
diff -Nru a/include/asm-sparc64/hardirq.h b/include/asm-sparc64/hardirq.h
--- a/include/asm-sparc64/hardirq.h	2004-10-18 14:56:48 -07:00
+++ b/include/asm-sparc64/hardirq.h	2004-10-18 14:56:48 -07:00
@@ -41,42 +41,7 @@
 #define SOFTIRQ_SHIFT	(PREEMPT_SHIFT + PREEMPT_BITS)
 #define HARDIRQ_SHIFT	(SOFTIRQ_SHIFT + SOFTIRQ_BITS)
 
-#define __MASK(x)	((1UL << (x))-1)
-
-#define PREEMPT_MASK	(__MASK(PREEMPT_BITS) << PREEMPT_SHIFT)
-#define HARDIRQ_MASK	(__MASK(HARDIRQ_BITS) << HARDIRQ_SHIFT)
-#define SOFTIRQ_MASK	(__MASK(SOFTIRQ_BITS) << SOFTIRQ_SHIFT)
-
-#define hardirq_count()	(preempt_count() & HARDIRQ_MASK)
-#define softirq_count()	(preempt_count() & SOFTIRQ_MASK)
-#define irq_count()	(preempt_count() & (HARDIRQ_MASK | SOFTIRQ_MASK))
-
-#define PREEMPT_OFFSET	(1UL << PREEMPT_SHIFT)
-#define SOFTIRQ_OFFSET	(1UL << SOFTIRQ_SHIFT)
-#define HARDIRQ_OFFSET	(1UL << HARDIRQ_SHIFT)
-
-/*
- * Are we doing bottom half or hardware interrupt processing?
- * Are we in a softirq context? Interrupt context?
- */
-#define in_irq()		(hardirq_count())
-#define in_softirq()		(softirq_count())
-#define in_interrupt()		(irq_count())
-
-
-#define hardirq_trylock()	(!in_interrupt())
-#define hardirq_endlock()	do { } while (0)
-
 #define irq_enter()		(preempt_count() += HARDIRQ_OFFSET)
-
-#ifdef CONFIG_PREEMPT
-# include <linux/smp_lock.h>
-# define in_atomic()	((preempt_count() & ~PREEMPT_ACTIVE) != kernel_locked())
-# define IRQ_EXIT_OFFSET (HARDIRQ_OFFSET-1)
-#else
-# define in_atomic()	(preempt_count() != 0)
-# define IRQ_EXIT_OFFSET HARDIRQ_OFFSET
-#endif
 #define irq_exit()							\
 do {									\
 		preempt_count() -= IRQ_EXIT_OFFSET;			\
@@ -84,11 +49,5 @@
 			do_softirq();					\
 		preempt_enable_no_resched();				\
 } while (0)
-
-#ifndef CONFIG_SMP
-# define synchronize_irq(irq)	barrier()
-#else
-  extern void synchronize_irq(unsigned int irq);
-#endif /* CONFIG_SMP */
 
 #endif /* !(__SPARC64_HARDIRQ_H) */
diff -Nru a/include/asm-sparc64/ide.h b/include/asm-sparc64/ide.h
--- a/include/asm-sparc64/ide.h	2004-10-18 14:56:28 -07:00
+++ b/include/asm-sparc64/ide.h	2004-10-18 14:56:28 -07:00
@@ -38,7 +38,7 @@
 #define __ide_mm_outsw	__ide_outsw
 #define __ide_mm_outsl	__ide_outsl
 
-static __inline__ unsigned int inw_be(unsigned long addr)
+static inline unsigned int inw_be(void __iomem *addr)
 {
 	unsigned int ret;
 
@@ -49,9 +49,7 @@
 	return ret;
 }
 
-static __inline__ void __ide_insw(unsigned long port,
-				  void *dst,
-				  u32 count)
+static inline void __ide_insw(void __iomem *port, void *dst, u32 count)
 {
 #if (L1DCACHE_SIZE > PAGE_SIZE)		/* is there D$ aliasing problem */
 	unsigned long end = (unsigned long)dst + (count << 1);
@@ -81,16 +79,14 @@
 #endif
 }
 
-static __inline__ void outw_be(unsigned short w, unsigned long addr)
+static inline void outw_be(unsigned short w, void __iomem *addr)
 {
 	__asm__ __volatile__("stha %0, [%1] %2"
 			     : /* no outputs */
 			     : "r" (w), "r" (addr), "i" (ASI_PHYS_BYPASS_EC_E));
 }
 
-static __inline__ void __ide_outsw(unsigned long port,
-				   void *src,
-				   u32 count)
+static inline void __ide_outsw(void __iomem *port, void *src, u32 count)
 {
 #if (L1DCACHE_SIZE > PAGE_SIZE)		/* is there D$ aliasing problem */
 	unsigned long end = (unsigned long)src + (count << 1);
diff -Nru a/include/asm-sparc64/io.h b/include/asm-sparc64/io.h
--- a/include/asm-sparc64/io.h	2004-10-18 14:56:50 -07:00
+++ b/include/asm-sparc64/io.h	2004-10-18 14:56:50 -07:00
@@ -3,6 +3,7 @@
 #define __SPARC64_IO_H
 
 #include <linux/kernel.h>
+#include <linux/compiler.h>
 #include <linux/types.h>
 
 #include <asm/page.h>      /* IO address mapping routines need this */
@@ -99,28 +100,31 @@
 #define inl_p(__addr)		inl(__addr)
 #define outl_p(__l, __addr)	outl(__l, __addr)
 
-extern void outsb(unsigned long addr, const void *src, unsigned long count);
-extern void outsw(unsigned long addr, const void *src, unsigned long count);
-extern void outsl(unsigned long addr, const void *src, unsigned long count);
-extern void insb(unsigned long addr, void *dst, unsigned long count);
-extern void insw(unsigned long addr, void *dst, unsigned long count);
-extern void insl(unsigned long addr, void *dst, unsigned long count);
+extern void outsb(void __iomem *addr, const void *src, unsigned long count);
+extern void outsw(void __iomem *addr, const void *src, unsigned long count);
+extern void outsl(void __iomem *addr, const void *src, unsigned long count);
+extern void insb(void __iomem *addr, void *dst, unsigned long count);
+extern void insw(void __iomem *addr, void *dst, unsigned long count);
+extern void insl(void __iomem *addr, void *dst, unsigned long count);
+#define ioread8_rep(a,d,c)	insb(a,d,c)
+#define ioread16_rep(a,d,c)	insw(a,d,c)
+#define ioread32_rep(a,d,c)	insl(a,d,c)
+#define iowrite8_rep(a,s,c)	outsb(a,s,c)
+#define iowrite16_rep(a,s,c)	outsw(a,s,c)
+#define iowrite32_rep(a,s,c)	outsl(a,s,c)
 
 /* Memory functions, same as I/O accesses on Ultra. */
-static __inline__ u8 _readb(unsigned long addr)
-{
-	u8 ret;
+static inline u8 _readb(void __iomem *addr)
+{	u8 ret;
 
 	__asm__ __volatile__("lduba\t[%1] %2, %0\t/* pci_readb */"
 			     : "=r" (ret)
 			     : "r" (addr), "i" (ASI_PHYS_BYPASS_EC_E_L));
-
 	return ret;
 }
 
-static __inline__ u16 _readw(unsigned long addr)
-{
-	u16 ret;
+static inline u16 _readw(void __iomem *addr)
+{	u16 ret;
 
 	__asm__ __volatile__("lduha\t[%1] %2, %0\t/* pci_readw */"
 			     : "=r" (ret)
@@ -129,9 +133,8 @@
 	return ret;
 }
 
-static __inline__ u32 _readl(unsigned long addr)
-{
-	u32 ret;
+static inline u32 _readl(void __iomem *addr)
+{	u32 ret;
 
 	__asm__ __volatile__("lduwa\t[%1] %2, %0\t/* pci_readl */"
 			     : "=r" (ret)
@@ -140,9 +143,8 @@
 	return ret;
 }
 
-static __inline__ u64 _readq(unsigned long addr)
-{
-	u64 ret;
+static inline u64 _readq(void __iomem *addr)
+{	u64 ret;
 
 	__asm__ __volatile__("ldxa\t[%1] %2, %0\t/* pci_readq */"
 			     : "=r" (ret)
@@ -151,46 +153,46 @@
 	return ret;
 }
 
-static __inline__ void _writeb(u8 b, unsigned long addr)
+static inline void _writeb(u8 b, void __iomem *addr)
 {
 	__asm__ __volatile__("stba\t%r0, [%1] %2\t/* pci_writeb */"
 			     : /* no outputs */
 			     : "Jr" (b), "r" (addr), "i" (ASI_PHYS_BYPASS_EC_E_L));
 }
 
-static __inline__ void _writew(u16 w, unsigned long addr)
+static inline void _writew(u16 w, void __iomem *addr)
 {
 	__asm__ __volatile__("stha\t%r0, [%1] %2\t/* pci_writew */"
 			     : /* no outputs */
 			     : "Jr" (w), "r" (addr), "i" (ASI_PHYS_BYPASS_EC_E_L));
 }
 
-static __inline__ void _writel(u32 l, unsigned long addr)
+static inline void _writel(u32 l, void __iomem *addr)
 {
 	__asm__ __volatile__("stwa\t%r0, [%1] %2\t/* pci_writel */"
 			     : /* no outputs */
 			     : "Jr" (l), "r" (addr), "i" (ASI_PHYS_BYPASS_EC_E_L));
 }
 
-static __inline__ void _writeq(u64 q, unsigned long addr)
+static inline void _writeq(u64 q, void __iomem *addr)
 {
 	__asm__ __volatile__("stxa\t%r0, [%1] %2\t/* pci_writeq */"
 			     : /* no outputs */
 			     : "Jr" (q), "r" (addr), "i" (ASI_PHYS_BYPASS_EC_E_L));
 }
 
-#define readb(__addr)		(_readb((unsigned long)(__addr)))
-#define readw(__addr)		(_readw((unsigned long)(__addr)))
-#define readl(__addr)		(_readl((unsigned long)(__addr)))
-#define readq(__addr)		(_readq((unsigned long)(__addr)))
-#define readb_relaxed(a)	readb(a)
-#define readw_relaxed(a)	readw(a)
-#define readl_relaxed(a)	readl(a)
-#define readq_relaxed(a)	readq(a)
-#define writeb(__b, __addr)	(_writeb((u8)(__b), (unsigned long)(__addr)))
-#define writew(__w, __addr)	(_writew((u16)(__w), (unsigned long)(__addr)))
-#define writel(__l, __addr)	(_writel((u32)(__l), (unsigned long)(__addr)))
-#define writeq(__q, __addr)	(_writeq((u64)(__q), (unsigned long)(__addr)))
+#define readb(__addr)		_readb(__addr)
+#define readw(__addr)		_readw(__addr)
+#define readl(__addr)		_readl(__addr)
+#define readq(__addr)		_readq(__addr)
+#define readb_relaxed(__addr)	_readb(__addr)
+#define readw_relaxed(__addr)	_readw(__addr)
+#define readl_relaxed(__addr)	_readl(__addr)
+#define readq_relaxed(__addr)	_readq(__addr)
+#define writeb(__b, __addr)	_writeb(__b, __addr)
+#define writew(__w, __addr)	_writew(__w, __addr)
+#define writel(__l, __addr)	_writel(__l, __addr)
+#define writeq(__q, __addr)	_writeq(__q, __addr)
 
 /* Now versions without byte-swapping. */
 static __inline__ u8 _raw_readb(unsigned long addr)
@@ -282,7 +284,7 @@
 /* Now, SBUS variants, only difference from PCI is that we do
  * not use little-endian ASIs.
  */
-static __inline__ u8 _sbus_readb(unsigned long addr)
+static inline u8 _sbus_readb(void __iomem *addr)
 {
 	u8 ret;
 
@@ -293,7 +295,7 @@
 	return ret;
 }
 
-static __inline__ u16 _sbus_readw(unsigned long addr)
+static inline u16 _sbus_readw(void __iomem *addr)
 {
 	u16 ret;
 
@@ -304,7 +306,7 @@
 	return ret;
 }
 
-static __inline__ u32 _sbus_readl(unsigned long addr)
+static inline u32 _sbus_readl(void __iomem *addr)
 {
 	u32 ret;
 
@@ -315,7 +317,7 @@
 	return ret;
 }
 
-static __inline__ u64 _sbus_readq(unsigned long addr)
+static inline u64 _sbus_readq(void __iomem *addr)
 {
 	u64 ret;
 
@@ -326,44 +328,45 @@
 	return ret;
 }
 
-static __inline__ void _sbus_writeb(u8 b, unsigned long addr)
+static inline void _sbus_writeb(u8 b, void __iomem *addr)
 {
 	__asm__ __volatile__("stba\t%r0, [%1] %2\t/* sbus_writeb */"
 			     : /* no outputs */
 			     : "Jr" (b), "r" (addr), "i" (ASI_PHYS_BYPASS_EC_E));
 }
 
-static __inline__ void _sbus_writew(u16 w, unsigned long addr)
+static inline void _sbus_writew(u16 w, void __iomem *addr)
 {
 	__asm__ __volatile__("stha\t%r0, [%1] %2\t/* sbus_writew */"
 			     : /* no outputs */
 			     : "Jr" (w), "r" (addr), "i" (ASI_PHYS_BYPASS_EC_E));
 }
 
-static __inline__ void _sbus_writel(u32 l, unsigned long addr)
+static inline void _sbus_writel(u32 l, void __iomem *addr)
 {
 	__asm__ __volatile__("stwa\t%r0, [%1] %2\t/* sbus_writel */"
 			     : /* no outputs */
 			     : "Jr" (l), "r" (addr), "i" (ASI_PHYS_BYPASS_EC_E));
 }
 
-static __inline__ void _sbus_writeq(u64 l, unsigned long addr)
+static inline void _sbus_writeq(u64 l, void __iomem *addr)
 {
 	__asm__ __volatile__("stxa\t%r0, [%1] %2\t/* sbus_writeq */"
 			     : /* no outputs */
 			     : "Jr" (l), "r" (addr), "i" (ASI_PHYS_BYPASS_EC_E));
 }
 
-#define sbus_readb(__addr)		(_sbus_readb((unsigned long)(__addr)))
-#define sbus_readw(__addr)		(_sbus_readw((unsigned long)(__addr)))
-#define sbus_readl(__addr)		(_sbus_readl((unsigned long)(__addr)))
-#define sbus_readq(__addr)		(_sbus_readq((unsigned long)(__addr)))
-#define sbus_writeb(__b, __addr)	(_sbus_writeb((__b), (unsigned long)(__addr)))
-#define sbus_writew(__w, __addr)	(_sbus_writew((__w), (unsigned long)(__addr)))
-#define sbus_writel(__l, __addr)	(_sbus_writel((__l), (unsigned long)(__addr)))
-#define sbus_writeq(__l, __addr)	(_sbus_writeq((__l), (unsigned long)(__addr)))
+#define sbus_readb(__addr)		_sbus_readb(__addr)
+#define sbus_readw(__addr)		_sbus_readw(__addr)
+#define sbus_readl(__addr)		_sbus_readl(__addr)
+#define sbus_readq(__addr)		_sbus_readq(__addr)
+#define sbus_writeb(__b, __addr)	_sbus_writeb(__b, __addr)
+#define sbus_writew(__w, __addr)	_sbus_writew(__w, __addr)
+#define sbus_writel(__l, __addr)	_sbus_writel(__l, __addr)
+#define sbus_writeq(__l, __addr)	_sbus_writeq(__l, __addr)
 
-static inline void *_sbus_memset_io(unsigned long dst, int c, __kernel_size_t n)
+static inline void __iomem*_sbus_memset_io(void __iomem *dst, int c,
+					   __kernel_size_t n)
 {
 	while(n--) {
 		sbus_writeb(c, dst);
@@ -372,13 +375,12 @@
 	return (void *) dst;
 }
 
-#define sbus_memset_io(d,c,sz)	\
-	_sbus_memset_io((unsigned long)d,(int)c,(__kernel_size_t)sz)
+#define sbus_memset_io(d,c,sz)	_sbus_memset_io(d,c,sz)
 
-static inline void *
-_memset_io(void *dst, int c, __kernel_size_t n)
+static inline void __iomem *
+_memset_io(void __iomem *dst, int c, __kernel_size_t n)
 {
-	char *d = dst;
+	void __iomem *d = dst;
 
 	while (n--) {
 		writeb(c, d);
@@ -388,11 +390,10 @@
 	return dst;
 }
 
-#define memset_io(d,c,sz)	\
-	_memset_io((void *)d,(int)c,(__kernel_size_t)sz)
+#define memset_io(d,c,sz)	_memset_io(d,c,sz)
 
-static inline void *
-_memcpy_fromio(void *dst, unsigned long src, __kernel_size_t n)
+static inline void __iomem *
+_memcpy_fromio(void *dst, void __iomem *src, __kernel_size_t n)
 {
 	char *d = dst;
 
@@ -405,25 +406,23 @@
 	return dst;
 }
 
-#define memcpy_fromio(d,s,sz)	\
-	_memcpy_fromio((void *)d,(unsigned long)s,(__kernel_size_t)sz)
+#define memcpy_fromio(d,s,sz)	_memcpy_fromio(d,s,sz)
 
-static inline void *
-_memcpy_toio(unsigned long dst, const void *src, __kernel_size_t n)
+static inline void __iomem *
+_memcpy_toio(void __iomem *dst, const void *src, __kernel_size_t n)
 {
 	const char *s = src;
-	unsigned long d = dst;
+	void __iomem *d = dst;
 
 	while (n--) {
 		char tmp = *s++;
 		writeb(tmp, d);
 		d++;
 	}
-	return (void *)dst;
+	return dst;
 }
 
-#define memcpy_toio(d,s,sz)	\
-	_memcpy_toio((unsigned long)d,(const void *)s,(__kernel_size_t)sz)
+#define memcpy_toio(d,s,sz)	_memcpy_toio(d,s,sz)
 
 static inline int check_signature(unsigned long io_addr,
 				  const unsigned char *signature,
@@ -431,8 +430,9 @@
 {
 	int retval = 0;
 	do {
-		if (readb(io_addr++) != *signature++)
+		if (readb((void __iomem *)io_addr) != *signature++)
 			goto out;
+		io_addr++;
 	} while (--length);
 	retval = 1;
 out:
@@ -444,10 +444,26 @@
 /* On sparc64 we have the whole physical IO address space accessible
  * using physically addressed loads and stores, so this does nothing.
  */
-#define ioremap(__offset, __size)	((void *)(__offset))
+#define ioremap(__offset, __size)	((void __iomem *)(__offset))
 #define ioremap_nocache(X,Y)		ioremap((X),(Y))
 #define iounmap(__addr)			do { (void)(__addr); } while(0)
 
+#define ioread8(X)			readb(X)
+#define ioread16(X)			readw(X)
+#define ioread32(X)			readl(X)
+#define iowrite8(val,X)			writeb(val,X)
+#define iowrite16(val,X)		writew(val,X)
+#define iowrite32(val,X)		writel(val,X)
+
+/* Create a virtual mapping cookie for an IO port range */
+extern void __iomem *ioport_map(unsigned long port, unsigned int nr);
+extern void ioport_unmap(void __iomem *);
+
+/* Create a virtual mapping cookie for a PCI BAR (memory or IO) */
+struct pci_dev;
+extern void __iomem *pci_iomap(struct pci_dev *dev, int bar, unsigned long max);
+extern void pci_iounmap(struct pci_dev *dev, void __iomem *);
+
 /* Similarly for SBUS. */
 #define sbus_ioremap(__res, __offset, __size, __name) \
 ({	unsigned long __ret; \
@@ -455,11 +471,11 @@
 	__ret += (unsigned long) (__offset); \
 	if (! request_region((__ret), (__size), (__name))) \
 		__ret = 0UL; \
-	__ret; \
+	(void __iomem *) __ret; \
 })
 
 #define sbus_iounmap(__addr, __size)	\
-	release_region((__addr), (__size))
+	release_region((unsigned long)(__addr), (__size))
 
 /* Nothing to do */
 
diff -Nru a/include/asm-sparc64/kdebug.h b/include/asm-sparc64/kdebug.h
--- a/include/asm-sparc64/kdebug.h	2004-10-18 14:57:04 -07:00
+++ b/include/asm-sparc64/kdebug.h	2004-10-18 14:57:04 -07:00
@@ -1,9 +1,52 @@
 #ifndef _SPARC64_KDEBUG_H
 #define _SPARC64_KDEBUG_H
 
-/* 
- * No kernel debugger on sparc64. Kept here because drivers/sbus/char/
- * includes it for sparc32 sake.
+/* Nearly identical to x86_64/i386 code. */
+
+#include <linux/notifier.h>
+
+struct pt_regs;
+
+struct die_args {
+	struct pt_regs *regs;
+	const char *str;
+	long err;
+	int trapnr;
+	int signr;
+};
+
+/* Note - you should never unregister because that can race with NMIs.
+ * If you really want to do it first unregister - then synchronize_kernel
+ * - then free.
  */
+int register_die_notifier(struct notifier_block *nb);
+extern struct notifier_block *sparc64die_chain;
+
+extern void bad_trap(struct pt_regs *, long);
+
+/* Grossly misnamed. */
+enum die_val {
+	DIE_OOPS = 1,
+	DIE_DEBUG,	/* ta 0x70 */
+	DIE_DEBUG_2,	/* ta 0x71 */
+	DIE_DIE,
+	DIE_TRAP,
+	DIE_TRAP_TL1,
+	DIE_GPF,
+	DIE_CALL,
+	DIE_PAGE_FAULT,
+};
+
+static inline int notify_die(enum die_val val,char *str, struct pt_regs *regs,
+			     long err, int trap, int sig)
+{
+	struct die_args args = { .regs		= regs,
+				 .str		= str,
+				 .err		= err,
+				 .trapnr	= trap,
+				 .signr		= sig };
+
+	return notifier_call_chain(&sparc64die_chain, val, &args);
+}
 
 #endif
diff -Nru a/include/asm-sparc64/kprobes.h b/include/asm-sparc64/kprobes.h
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/include/asm-sparc64/kprobes.h	2004-10-18 14:57:23 -07:00
@@ -0,0 +1,24 @@
+#ifndef _SPARC64_KPROBES_H
+#define _SPARC64_KPROBES_H
+
+#include <linux/config.h>
+#include <linux/types.h>
+
+typedef u32 kprobe_opcode_t;
+
+#define BREAKPOINT_INSTRUCTION   0x91d02070 /* ta 0x70 */
+#define BREAKPOINT_INSTRUCTION_2 0x91d02071 /* ta 0x71 */
+#define MAX_INSN_SIZE 2
+
+#ifdef CONFIG_KPROBES
+extern int kprobe_exceptions_notify(struct notifier_block *self,
+				    unsigned long val, void *data);
+#else				/* !CONFIG_KPROBES */
+static inline int kprobe_exceptions_notify(struct notifier_block *self,
+					   unsigned long val, void *data)
+{
+	return 0;
+}
+#endif
+
+#endif /* _SPARC64_KPROBES_H */
diff -Nru a/include/asm-sparc64/parport.h b/include/asm-sparc64/parport.h
--- a/include/asm-sparc64/parport.h	2004-10-18 14:57:19 -07:00
+++ b/include/asm-sparc64/parport.h	2004-10-18 14:57:19 -07:00
@@ -126,10 +126,14 @@
 			if (ebus_ecpp_p(edev)) {
 				unsigned long base = edev->resource[0].start;
 				unsigned long config = edev->resource[1].start;
+				unsigned long d_base = edev->resource[2].start;
+				unsigned long d_len;
 
 				spin_lock_init(&sparc_ebus_dmas[count].info.lock);
+				d_len = (edev->resource[2].end -
+					 d_base) + 1;
 				sparc_ebus_dmas[count].info.regs =
-					edev->resource[2].start;
+					ioremap(d_base, d_len);
 				if (!sparc_ebus_dmas[count].info.regs)
 					continue;
 				sparc_ebus_dmas[count].info.flags = 0;
diff -Nru a/include/asm-sparc64/pbm.h b/include/asm-sparc64/pbm.h
--- a/include/asm-sparc64/pbm.h	2004-10-18 14:57:19 -07:00
+++ b/include/asm-sparc64/pbm.h	2004-10-18 14:57:19 -07:00
@@ -70,6 +70,13 @@
 	 */
 	u32		lowest_consistent_map;
 
+	/* In order to deal with some buggy third-party PCI bridges that
+	 * do wrong prefetching, we never mark valid mappings as invalid.
+	 * Instead we point them at this dummy page.
+	 */
+	unsigned long	dummy_page;
+	unsigned long	dummy_page_pa;
+
 	/* If PBM_NCLUSTERS is ever decreased to 4 or lower,
 	 * or if largest supported page_table_sz * 8K goes above
 	 * 2GB, you must increase the size of the type of
@@ -92,6 +99,8 @@
 	 */
 	u32 dma_addr_mask;
 };
+
+extern void pci_iommu_table_init(struct pci_iommu *, int);
 
 /* This describes a PCI bus module's streaming buffer. */
 struct pci_strbuf {
diff -Nru a/include/asm-sparc64/ptrace.h b/include/asm-sparc64/ptrace.h
--- a/include/asm-sparc64/ptrace.h	2004-10-18 14:56:33 -07:00
+++ b/include/asm-sparc64/ptrace.h	2004-10-18 14:56:33 -07:00
@@ -98,6 +98,11 @@
 	set_thread_flag(TIF_SYSCALL_SUCCESS)
 #define user_mode(regs) (!((regs)->tstate & TSTATE_PRIV))
 #define instruction_pointer(regs) ((regs)->tpc)
+#ifdef CONFIG_SMP
+extern unsigned long profile_pc(struct pt_regs *);
+#else
+#define profile_pc(regs) instruction_pointer(regs)
+#endif
 extern void show_regs(struct pt_regs *);
 #endif
 
diff -Nru a/include/asm-sparc64/resource.h b/include/asm-sparc64/resource.h
--- a/include/asm-sparc64/resource.h	2004-10-18 14:55:54 -07:00
+++ b/include/asm-sparc64/resource.h	2004-10-18 14:55:54 -07:00
@@ -43,7 +43,7 @@
     {       0, RLIM_INFINITY},		\
     {RLIM_INFINITY, RLIM_INFINITY},	\
     {INR_OPEN, INR_OPEN}, {0, 0},	\
-    {RLIM_INFINITY, RLIM_INFINITY},	\
+    {  MLOCK_LIMIT,   MLOCK_LIMIT},	\
     {RLIM_INFINITY, RLIM_INFINITY},	\
     {RLIM_INFINITY, RLIM_INFINITY},	\
     {MAX_SIGPENDING, MAX_SIGPENDING},	\
diff -Nru a/include/asm-sparc64/sigcontext.h b/include/asm-sparc64/sigcontext.h
--- a/include/asm-sparc64/sigcontext.h	2004-10-18 14:56:27 -07:00
+++ b/include/asm-sparc64/sigcontext.h	2004-10-18 14:56:27 -07:00
@@ -83,18 +83,6 @@
 	unsigned long		sigc_mask;
 };
 
-#ifdef __KERNEL__
-
-/* 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];
-} siginfo_extra_v8plus_t;
-
-#endif
-
 #endif /* !(__ASSEMBLY__) */
 
 #endif /* !(__SPARC64_SIGCONTEXT_H) */
diff -Nru a/include/asm-sparc64/siginfo.h b/include/asm-sparc64/siginfo.h
--- a/include/asm-sparc64/siginfo.h	2004-10-18 14:56:49 -07:00
+++ b/include/asm-sparc64/siginfo.h	2004-10-18 14:56:49 -07:00
@@ -24,57 +24,8 @@
 	u32 sival_ptr;
 } sigval_t32;
 
-typedef struct siginfo32 {
-	int si_signo;
-	int si_errno;
-	int si_code;
+struct siginfo32;
 
-	union {
-		int _pad[SI_PAD_SIZE32];
-
-		/* kill() */
-		struct {
-			compat_pid_t _pid;		/* sender's pid */
-			unsigned int _uid;		/* sender's uid */
-		} _kill;
-
-		/* POSIX.1b timers */
-		struct {
-			timer_t _tid;			/* timer id */
-			int _overrun;			/* overrun count */
-			sigval_t32 _sigval;		/* same as below */
-			int _sys_private;		/* not to be passed to user */
-		} _timer;
-
-		/* POSIX.1b signals */
-		struct {
-			compat_pid_t _pid;		/* sender's pid */
-			unsigned int _uid;		/* sender's uid */
-			sigval_t32 _sigval;
-		} _rt;
-
-		/* SIGCHLD */
-		struct {
-			compat_pid_t _pid;		/* which child */
-			unsigned int _uid;		/* sender's uid */
-			int _status;			/* exit code */
-			compat_clock_t _utime;
-			compat_clock_t _stime;
-		} _sigchld;
-
-		/* SIGILL, SIGFPE, SIGSEGV, SIGBUS, SIGEMT */
-		struct {
-			u32 _addr; /* faulting insn/memory ref. */
-			int _trapno;
-		} _sigfault;
-
-		/* SIGPOLL */
-		struct {
-			int _band;	/* POLL_IN, POLL_OUT, POLL_MSG */
-			int _fd;
-		} _sigpoll;
-	} _sifields;
-} siginfo_t32;
 #endif /* CONFIG_COMPAT */
 
 #endif /* __KERNEL__ */
@@ -105,7 +56,8 @@
 	} _sigev_un;
 } sigevent_t32;
 
-extern int copy_siginfo_to_user32(siginfo_t32 __user *to, siginfo_t *from);
+extern int copy_siginfo_to_user32(struct siginfo32 __user *to, siginfo_t *from);
+extern int copy_siginfo_to_kernel32(siginfo_t *to, struct siginfo32 __user *from);
 
 #endif /* CONFIG_COMPAT */
 
diff -Nru a/include/asm-sparc64/socket.h b/include/asm-sparc64/socket.h
--- a/include/asm-sparc64/socket.h	2004-10-18 14:56:28 -07:00
+++ b/include/asm-sparc64/socket.h	2004-10-18 14:56:28 -07:00
@@ -52,20 +52,4 @@
 #define SO_SECURITY_ENCRYPTION_TRANSPORT	0x5002
 #define SO_SECURITY_ENCRYPTION_NETWORK		0x5004
 
-/* Nast libc5 fixup - bletch */
-#if defined(__KERNEL__)
-/* Socket types. */
-#define SOCK_STREAM	1		/* stream (connection) socket	*/
-#define SOCK_DGRAM	2		/* datagram (conn.less) socket	*/
-#define SOCK_RAW	3		/* raw socket			*/
-#define SOCK_RDM	4		/* reliably-delivered message	*/
-#define SOCK_SEQPACKET	5		/* sequential packet socket	*/
-#define SOCK_PACKET	10		/* linux specific way of	*/
-					/* getting packets at the dev	*/
-					/* level.  For writing rarp and	*/
-					/* other similar things on the	*/
-					/* user level.			*/
-#define	SOCK_MAX	(SOCK_PACKET+1)
-#endif
-
 #endif /* _ASM_SOCKET_H */
diff -Nru a/include/asm-sparc64/spinlock.h b/include/asm-sparc64/spinlock.h
--- a/include/asm-sparc64/spinlock.h	2004-10-18 14:56:17 -07:00
+++ b/include/asm-sparc64/spinlock.h	2004-10-18 14:56:17 -07:00
@@ -41,30 +41,70 @@
 do {	membar("#LoadLoad");	\
 } while(*((volatile unsigned char *)lock))
 
-/* arch/sparc64/lib/spinlock.S */
-extern void _raw_spin_lock(spinlock_t *lock);
+static inline void _raw_spin_lock(spinlock_t *lock)
+{
+	unsigned long tmp;
+
+	__asm__ __volatile__(
+"1:	ldstub		[%1], %0\n"
+"	brnz,pn		%0, 2f\n"
+"	 membar		#StoreLoad | #StoreStore\n"
+"	.subsection	2\n"
+"2:	ldub		[%1], %0\n"
+"	brnz,pt		%0, 2b\n"
+"	 membar		#LoadLoad\n"
+"	ba,a,pt		%%xcc, 1b\n"
+"	.previous"
+	: "=&r" (tmp)
+	: "r" (lock)
+	: "memory");
+}
 
-static __inline__ int _raw_spin_trylock(spinlock_t *lock)
+static inline int _raw_spin_trylock(spinlock_t *lock)
 {
-	unsigned int result;
-	__asm__ __volatile__("ldstub [%1], %0\n\t"
-			     "membar #StoreLoad | #StoreStore"
-			     : "=r" (result)
-			     : "r" (lock)
-			     : "memory");
-	return (result == 0);
+	unsigned long result;
+
+	__asm__ __volatile__(
+"	ldstub		[%1], %0\n"
+"	membar		#StoreLoad | #StoreStore"
+	: "=r" (result)
+	: "r" (lock)
+	: "memory");
+
+	return (result == 0UL);
 }
 
-static __inline__ void _raw_spin_unlock(spinlock_t *lock)
+static inline void _raw_spin_unlock(spinlock_t *lock)
 {
-	__asm__ __volatile__("membar	#StoreStore | #LoadStore\n\t"
-			     "stb	%%g0, [%0]"
-			     : /* No outputs */
-			     : "r" (lock)
-			     : "memory");
+	__asm__ __volatile__(
+"	membar		#StoreStore | #LoadStore\n"
+"	stb		%%g0, [%0]"
+	: /* No outputs */
+	: "r" (lock)
+	: "memory");
 }
 
-extern void _raw_spin_lock_flags(spinlock_t *lock, unsigned long flags);
+static inline void _raw_spin_lock_flags(spinlock_t *lock, unsigned long flags)
+{
+	unsigned long tmp1, tmp2;
+
+	__asm__ __volatile__(
+"1:	ldstub		[%2], %0\n"
+"	brnz,pn		%0, 2f\n"
+"	membar		#StoreLoad | #StoreStore\n"
+"	.subsection	2\n"
+"2:	rdpr		%%pil, %1\n"
+"	wrpr		%3, %%pil\n"
+"3:	ldub		[%2], %0\n"
+"	brnz,pt		%0, 3b\n"
+"	membar		#LoadLoad\n"
+"	ba,pt		%%xcc, 1b\n"
+"	wrpr		%1, %%pil\n"
+"	.previous"
+	: "=&r" (tmp1), "=&r" (tmp2)
+	: "r"(lock), "r"(flags)
+	: "memory");
+}
 
 #else /* !(CONFIG_DEBUG_SPINLOCK) */
 
@@ -86,9 +126,9 @@
 
 extern void _do_spin_lock (spinlock_t *lock, char *str);
 extern void _do_spin_unlock (spinlock_t *lock);
-extern int _spin_trylock (spinlock_t *lock);
+extern int _do_spin_trylock (spinlock_t *lock);
 
-#define _raw_spin_trylock(lp)	_spin_trylock(lp)
+#define _raw_spin_trylock(lp)	_do_spin_trylock(lp)
 #define _raw_spin_lock(lock)	_do_spin_lock(lock, "spin_lock")
 #define _raw_spin_unlock(lock)	_do_spin_unlock(lock)
 #define _raw_spin_lock_flags(lock, flags) _raw_spin_lock(lock)
@@ -104,11 +144,103 @@
 #define rwlock_init(lp) do { *(lp) = RW_LOCK_UNLOCKED; } while(0)
 #define rwlock_is_locked(x) (*(x) != RW_LOCK_UNLOCKED)
 
-extern void __read_lock(rwlock_t *);
-extern void __read_unlock(rwlock_t *);
-extern void __write_lock(rwlock_t *);
-extern void __write_unlock(rwlock_t *);
-extern int __write_trylock(rwlock_t *);
+static void inline __read_lock(rwlock_t *lock)
+{
+	unsigned long tmp1, tmp2;
+
+	__asm__ __volatile__ (
+"1:	ldsw		[%2], %0\n"
+"	brlz,pn		%0, 2f\n"
+"4:	 add		%0, 1, %1\n"
+"	cas		[%2], %0, %1\n"
+"	cmp		%0, %1\n"
+"	bne,pn		%%icc, 1b\n"
+"	 membar		#StoreLoad | #StoreStore\n"
+"	.subsection	2\n"
+"2:	ldsw		[%2], %0\n"
+"	brlz,pt		%0, 2b\n"
+"	 membar		#LoadLoad\n"
+"	ba,a,pt		%%xcc, 4b\n"
+"	.previous"
+	: "=&r" (tmp1), "=&r" (tmp2)
+	: "r" (lock)
+	: "memory");
+}
+
+static void inline __read_unlock(rwlock_t *lock)
+{
+	unsigned long tmp1, tmp2;
+
+	__asm__ __volatile__(
+"1:	lduw	[%2], %0\n"
+"	sub	%0, 1, %1\n"
+"	cas	[%2], %0, %1\n"
+"	cmp	%0, %1\n"
+"	bne,pn	%%xcc, 1b\n"
+"	 membar	#StoreLoad | #StoreStore"
+	: "=&r" (tmp1), "=&r" (tmp2)
+	: "r" (lock)
+	: "memory");
+}
+
+static void inline __write_lock(rwlock_t *lock)
+{
+	unsigned long mask, tmp1, tmp2;
+
+	mask = 0x80000000UL;
+
+	__asm__ __volatile__(
+"1:	lduw		[%2], %0\n"
+"	brnz,pn		%0, 2f\n"
+"4:	 or		%0, %3, %1\n"
+"	cas		[%2], %0, %1\n"
+"	cmp		%0, %1\n"
+"	bne,pn		%%icc, 1b\n"
+"	 membar		#StoreLoad | #StoreStore\n"
+"	.subsection	2\n"
+"2:	lduw		[%2], %0\n"
+"	brnz,pt		%0, 2b\n"
+"	 membar		#LoadLoad\n"
+"	ba,a,pt		%%xcc, 4b\n"
+"	.previous"
+	: "=&r" (tmp1), "=&r" (tmp2)
+	: "r" (lock), "r" (mask)
+	: "memory");
+}
+
+static void inline __write_unlock(rwlock_t *lock)
+{
+	__asm__ __volatile__(
+"	membar		#LoadStore | #StoreStore\n"
+"	stw		%%g0, [%0]"
+	: /* no outputs */
+	: "r" (lock)
+	: "memory");
+}
+
+static int inline __write_trylock(rwlock_t *lock)
+{
+	unsigned long mask, tmp1, tmp2, result;
+
+	mask = 0x80000000UL;
+
+	__asm__ __volatile__(
+"	mov		0, %2\n"
+"1:	lduw		[%3], %0\n"
+"	brnz,pn		%0, 2f\n"
+"	 or		%0, %4, %1\n"
+"	cas		[%3], %0, %1\n"
+"	cmp		%0, %1\n"
+"	bne,pn		%%icc, 1b\n"
+"	 membar		#StoreLoad | #StoreStore\n"
+"	mov		1, %2\n"
+"2:"
+	: "=&r" (tmp1), "=&r" (tmp2), "=&r" (result)
+	: "r" (lock), "r" (mask)
+	: "memory");
+
+	return result;
+}
 
 #define _raw_read_lock(p)	__read_lock(p)
 #define _raw_read_unlock(p)	__read_unlock(p)
diff -Nru a/include/asm-sparc64/string.h b/include/asm-sparc64/string.h
--- a/include/asm-sparc64/string.h	2004-10-18 14:56:50 -07:00
+++ b/include/asm-sparc64/string.h	2004-10-18 14:56:50 -07:00
@@ -15,35 +15,25 @@
 
 #include <asm/asi.h>
 
-extern void __memmove(void *,const void *,__kernel_size_t);
 extern void *__memset(void *,int,__kernel_size_t);
-extern void *__builtin_memset(void *,int,__kernel_size_t);
 
 #ifndef EXPORT_SYMTAB_STROPS
 
 /* First the mem*() things. */
-#define __HAVE_ARCH_BCOPY
 #define __HAVE_ARCH_MEMMOVE
-
-#undef memmove
-#define memmove(_to, _from, _n) \
-({ \
-	void *_t = (_to); \
-	__memmove(_t, (_from), (_n)); \
-	_t; \
-})
+extern void *memmove(void *, const void *, __kernel_size_t);
 
 #define __HAVE_ARCH_MEMCPY
-
-extern void * memcpy(void *,const void *,__kernel_size_t);
+extern void *memcpy(void *, const void *, __kernel_size_t);
 
 #define __HAVE_ARCH_MEMSET
+extern void *__builtin_memset(void *,int,__kernel_size_t);
 
 static inline void *__constant_memset(void *s, int c, __kernel_size_t count)
 {
 	extern __kernel_size_t __bzero(void *, __kernel_size_t);
 
-	if(!c) {
+	if (!c) {
 		__bzero(s, count);
 		return s;
 	} else
@@ -61,19 +51,19 @@
 #define __HAVE_ARCH_MEMSCAN
 
 #undef memscan
-#define memscan(__arg0, __char, __arg2)						\
-({										\
-	extern void *__memscan_zero(void *, size_t);				\
-	extern void *__memscan_generic(void *, int, size_t);			\
-	void *__retval, *__addr = (__arg0);					\
-	size_t __size = (__arg2);						\
-										\
-	if(__builtin_constant_p(__char) && !(__char))				\
-		__retval = __memscan_zero(__addr, __size);			\
-	else									\
-		__retval = __memscan_generic(__addr, (__char), __size);		\
-										\
-	__retval;								\
+#define memscan(__arg0, __char, __arg2)					\
+({									\
+	extern void *__memscan_zero(void *, size_t);			\
+	extern void *__memscan_generic(void *, int, size_t);		\
+	void *__retval, *__addr = (__arg0);				\
+	size_t __size = (__arg2);					\
+									\
+	if(__builtin_constant_p(__char) && !(__char))			\
+		__retval = __memscan_zero(__addr, __size);		\
+	else								\
+		__retval = __memscan_generic(__addr, (__char), __size);	\
+									\
+	__retval;							\
 })
 
 #define __HAVE_ARCH_MEMCMP
@@ -81,73 +71,10 @@
 
 /* Now the str*() stuff... */
 #define __HAVE_ARCH_STRLEN
-
-extern __kernel_size_t __strlen(const char *);
 extern __kernel_size_t strlen(const char *);
 
 #define __HAVE_ARCH_STRNCMP
-
-extern int __strncmp(const char *, const char *, __kernel_size_t);
-
-static inline int __constant_strncmp(const char *src, const char *dest, __kernel_size_t count)
-{
-	register int retval;
-	switch(count) {
-	case 0: return 0;
-	case 1: return (src[0] - dest[0]);
-	case 2: retval = (src[0] - dest[0]);
-		if(!retval && src[0])
-		  retval = (src[1] - dest[1]);
-		return retval;
-	case 3: retval = (src[0] - dest[0]);
-		if(!retval && src[0]) {
-		  retval = (src[1] - dest[1]);
-		  if(!retval && src[1])
-		    retval = (src[2] - dest[2]);
-		}
-		return retval;
-	case 4: retval = (src[0] - dest[0]);
-		if(!retval && src[0]) {
-		  retval = (src[1] - dest[1]);
-		  if(!retval && src[1]) {
-		    retval = (src[2] - dest[2]);
-		    if (!retval && src[2])
-		      retval = (src[3] - dest[3]);
-		  }
-		}
-		return retval;
-	case 5: retval = (src[0] - dest[0]);
-		if(!retval && src[0]) {
-		  retval = (src[1] - dest[1]);
-		  if(!retval && src[1]) {
-		    retval = (src[2] - dest[2]);
-		    if (!retval && src[2]) {
-		      retval = (src[3] - dest[3]);
-		      if (!retval && src[3])
-		        retval = (src[4] - dest[4]);
-		    }
-		  }
-		}
-		return retval;
-	default:
-		retval = (src[0] - dest[0]);
-		if(!retval && src[0]) {
-		  retval = (src[1] - dest[1]);
-		  if(!retval && src[1]) {
-		    retval = (src[2] - dest[2]);
-		    if(!retval && src[2])
-		      retval = __strncmp(src+3,dest+3,count-3);
-		  }
-		}
-		return retval;
-	}
-}
-
-#undef strncmp
-#define strncmp(__arg0, __arg1, __arg2)	\
-(__builtin_constant_p(__arg2) ?	\
- __constant_strncmp(__arg0, __arg1, __arg2) : \
- __strncmp(__arg0, __arg1, __arg2))
+extern int strncmp(const char *, const char *, __kernel_size_t);
 
 #endif /* !EXPORT_SYMTAB_STROPS */
 
diff -Nru a/include/asm-sparc64/ttable.h b/include/asm-sparc64/ttable.h
--- a/include/asm-sparc64/ttable.h	2004-10-18 14:55:54 -07:00
+++ b/include/asm-sparc64/ttable.h	2004-10-18 14:55:54 -07:00
@@ -176,6 +176,12 @@
 	ba,pt	%xcc, rtrap_clr_l6;					\
 	 stx	%l2, [%sp + PTREGS_OFF + PT_V9_TNPC];
 	        
+#ifdef CONFIG_KPROBES
+#define KPROBES_TRAP(lvl) TRAP_IRQ(kprobe_trap, lvl)
+#else
+#define KPROBES_TRAP(lvl) TRAP_ARG(bad_trap, lvl)
+#endif
+
 /* Before touching these macros, you owe it to yourself to go and
  * see how arch/sparc64/kernel/winfixup.S works... -DaveM
  *
diff -Nru a/include/asm-sparc64/uaccess.h b/include/asm-sparc64/uaccess.h
--- a/include/asm-sparc64/uaccess.h	2004-10-18 14:57:20 -07:00
+++ b/include/asm-sparc64/uaccess.h	2004-10-18 14:57:20 -07:00
@@ -14,6 +14,7 @@
 #include <asm/asi.h>
 #include <asm/system.h>
 #include <asm/spitfire.h>
+#include <asm-generic/uaccess.h>
 #endif
 
 #ifndef __ASSEMBLY__
@@ -252,18 +253,50 @@
 
 extern int __get_user_bad(void);
 
-extern unsigned long __copy_from_user(void *to, const void __user *from,
-				      unsigned long size);
+extern unsigned long ___copy_from_user(void *to, const void __user *from,
+				       unsigned long size);
+extern unsigned long copy_from_user_fixup(void *to, const void __user *from,
+					  unsigned long size);
+static inline unsigned long copy_from_user(void *to, const void __user *from,
+					   unsigned long size)
+{
+	unsigned long ret = ___copy_from_user(to, from, size);
+
+	if (ret)
+		ret = copy_from_user_fixup(to, from, size);
+	return ret;
+}
+#define __copy_from_user copy_from_user
+
+extern unsigned long ___copy_to_user(void __user *to, const void *from,
+				     unsigned long size);
+extern unsigned long copy_to_user_fixup(void __user *to, const void *from,
+					unsigned long size);
+static inline unsigned long copy_to_user(void __user *to, const void *from,
+					 unsigned long size)
+{
+	unsigned long ret = ___copy_to_user(to, from, size);
 
-extern unsigned long __copy_to_user(void __user *to, const void *from,
-				    unsigned long size);
+	if (ret)
+		ret = copy_to_user_fixup(to, from, size);
+	return ret;
+}
+#define __copy_to_user copy_to_user
 
-extern unsigned long __copy_in_user(void __user *to, const void __user *from,
-				    unsigned long size);
+extern unsigned long ___copy_in_user(void __user *to, const void __user *from,
+				     unsigned long size);
+extern unsigned long copy_in_user_fixup(void __user *to, void __user *from,
+					unsigned long size);
+static inline unsigned long copy_in_user(void __user *to, void __user *from,
+					 unsigned long size)
+{
+	unsigned long ret = ___copy_in_user(to, from, size);
 
-#define copy_from_user __copy_from_user
-#define copy_to_user __copy_to_user
-#define copy_in_user __copy_in_user
+	if (ret)
+		ret = copy_in_user_fixup(to, from, size);
+	return ret;
+}
+#define __copy_in_user copy_in_user
 
 extern unsigned long __bzero_noasi(void __user *, unsigned long);
 
@@ -284,6 +317,8 @@
 
 #define strlen_user __strlen_user
 #define strnlen_user __strnlen_user
+#define __copy_to_user_inatomic __copy_to_user
+#define __copy_from_user_inatomic __copy_from_user
 
 #endif  /* __ASSEMBLY__ */
 
diff -Nru a/include/asm-sparc64/unistd.h b/include/asm-sparc64/unistd.h
--- a/include/asm-sparc64/unistd.h	2004-10-18 14:56:15 -07:00
+++ b/include/asm-sparc64/unistd.h	2004-10-18 14:56:15 -07:00
@@ -292,11 +292,13 @@
 #define __NR_io_cancel		271
 #define __NR_io_getevents	272
 #define __NR_mq_open		273
-#define __NR_mq_unlink		(__NR_mq_open+1)
-#define __NR_mq_timedsend	(__NR_mq_open+2)
-#define __NR_mq_timedreceive	(__NR_mq_open+3)
-#define __NR_mq_notify		(__NR_mq_open+4)
-#define __NR_mq_getsetattr	(__NR_mq_open+5)
+#define __NR_mq_unlink		274
+#define __NR_mq_timedsend	275
+#define __NR_mq_timedreceive	276
+#define __NR_mq_notify		277
+#define __NR_mq_getsetattr	278
+#define __NR_waitid		279
+
 /* WARNING: You MAY NOT add syscall numbers larger than 282, since
  *          all of the syscall tables in the Sparc kernel are
  *          sized to have 283 entries (starting at zero).  Therefore
diff -Nru a/include/asm-sparc64/vga.h b/include/asm-sparc64/vga.h
--- a/include/asm-sparc64/vga.h	2004-10-18 14:56:17 -07:00
+++ b/include/asm-sparc64/vga.h	2004-10-18 14:56:17 -07:00
@@ -11,6 +11,9 @@
 
 #define VT_BUF_HAVE_RW
 
+#undef scr_writew
+#undef scr_readw
+
 static inline void scr_writew(u16 val, u16 *addr)
 {
 	BUG_ON((long) addr >= 0);
diff -Nru a/include/asm-um/archparam-i386.h b/include/asm-um/archparam-i386.h
--- a/include/asm-um/archparam-i386.h	2004-10-18 14:56:49 -07:00
+++ b/include/asm-um/archparam-i386.h	2004-10-18 14:56:49 -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
  */
 
@@ -55,6 +55,93 @@
 	pr_reg[15] = PT_REGS_SP(regs);		\
 	pr_reg[16] = PT_REGS_SS(regs);		\
 } while(0);
+
+#if 0 /* Turn this back on when UML has VSYSCALL working */
+#define VSYSCALL_BASE	(__fix_to_virt(FIX_VSYSCALL))
+#else
+#define VSYSCALL_BASE	0
+#endif
+
+#define VSYSCALL_EHDR	((const struct elfhdr *) VSYSCALL_BASE)
+#define VSYSCALL_ENTRY	((unsigned long) &__kernel_vsyscall)
+extern void *__kernel_vsyscall;
+
+/*
+ * Architecture-neutral AT_ values in 0-17, leave some room
+ * for more of them, start the x86-specific ones at 32.
+ */
+#define AT_SYSINFO		32
+#define AT_SYSINFO_EHDR		33
+
+#define ARCH_DLINFO						\
+do {								\
+		NEW_AUX_ENT(AT_SYSINFO,	VSYSCALL_ENTRY);	\
+		NEW_AUX_ENT(AT_SYSINFO_EHDR, VSYSCALL_BASE);	\
+} while (0)
+
+/*
+ * These macros parameterize elf_core_dump in fs/binfmt_elf.c to write out
+ * extra segments containing the vsyscall DSO contents.  Dumping its
+ * contents makes post-mortem fully interpretable later without matching up
+ * the same kernel and hardware config to see what PC values meant.
+ * Dumping its extra ELF program headers includes all the other information
+ * a debugger needs to easily find how the vsyscall DSO was being used.
+ */
+#if 0
+#define ELF_CORE_EXTRA_PHDRS		(VSYSCALL_EHDR->e_phnum)
+#endif
+
+#undef ELF_CORE_EXTRA_PHDRS
+
+#if 0
+#define ELF_CORE_WRITE_EXTRA_PHDRS					      \
+do {									      \
+	const struct elf_phdr *const vsyscall_phdrs =			      \
+		(const struct elf_phdr *) (VSYSCALL_BASE		      \
+					   + VSYSCALL_EHDR->e_phoff);	      \
+	int i;								      \
+	Elf32_Off ofs = 0;						      \
+	for (i = 0; i < VSYSCALL_EHDR->e_phnum; ++i) {			      \
+		struct elf_phdr phdr = vsyscall_phdrs[i];		      \
+		if (phdr.p_type == PT_LOAD) {				      \
+			ofs = phdr.p_offset = offset;			      \
+			offset += phdr.p_filesz;			      \
+		}							      \
+		else							      \
+			phdr.p_offset += ofs;				      \
+		phdr.p_paddr = 0; /* match other core phdrs */		      \
+		DUMP_WRITE(&phdr, sizeof(phdr));			      \
+	}								      \
+} while (0)
+#define ELF_CORE_WRITE_EXTRA_DATA					      \
+do {									      \
+	const struct elf_phdr *const vsyscall_phdrs =			      \
+		(const struct elf_phdr *) (VSYSCALL_BASE		      \
+					   + VSYSCALL_EHDR->e_phoff);	      \
+	int i;								      \
+	for (i = 0; i < VSYSCALL_EHDR->e_phnum; ++i) {			      \
+		if (vsyscall_phdrs[i].p_type == PT_LOAD)		      \
+			DUMP_WRITE((void *) vsyscall_phdrs[i].p_vaddr,	      \
+				   vsyscall_phdrs[i].p_filesz);		      \
+	}								      \
+} while (0)
+#endif
+
+#undef ELF_CORE_WRITE_EXTRA_PHDRS
+#undef ELF_CORE_WRITE_EXTRA_DATA
+
+#define R_386_NONE	0
+#define R_386_32	1
+#define R_386_PC32	2
+#define R_386_GOT32	3
+#define R_386_PLT32	4
+#define R_386_COPY	5
+#define R_386_GLOB_DAT	6
+#define R_386_JMP_SLOT	7
+#define R_386_RELATIVE	8
+#define R_386_GOTOFF	9
+#define R_386_GOTPC	10
+#define R_386_NUM	11
 
 /********* Bits for asm-um/delay.h **********/
 
diff -Nru a/include/asm-um/bug.h b/include/asm-um/bug.h
--- a/include/asm-um/bug.h	2004-10-18 14:56:29 -07:00
+++ b/include/asm-um/bug.h	2004-10-18 14:56:29 -07:00
@@ -1,30 +1,4 @@
 #ifndef __UM_BUG_H
 #define __UM_BUG_H
-
-#ifndef __ASSEMBLY__
-
-#define BUG() do { \
-	panic("kernel BUG at %s:%d!\n", __FILE__, __LINE__); \
-} while (0)
-
-#define BUG_ON(condition) do { \
-	if (unlikely((condition)!=0)) \
-		BUG(); \
-} while(0)
-
-#define PAGE_BUG(page) do { \
-	BUG(); \
-} while (0)
-
-#define WARN_ON(condition) do { \
-	if (unlikely((condition)!=0)) { \
-		printk("Badness in %s at %s:%d\n", __FUNCTION__, __FILE__, __LINE__); \
-		dump_stack(); \
-	} \
-} while (0)
-
-extern int foo;
-
-#endif
-
+#include <asm-generic/bug.h>
 #endif
diff -Nru a/include/asm-um/common.lds.S b/include/asm-um/common.lds.S
--- a/include/asm-um/common.lds.S	2004-10-18 14:56:17 -07:00
+++ b/include/asm-um/common.lds.S	2004-10-18 14:56:17 -07:00
@@ -1,3 +1,5 @@
+#include <asm-generic/vmlinux.lds.h>
+
   .fini      : { *(.fini)    } =0x9090
   _etext = .;
   PROVIDE (etext = .);
@@ -13,18 +15,6 @@
 
   RODATA
 
-  __start___ksymtab = .;	/* Kernel symbol table */
-  __ksymtab : { *(__ksymtab) }
-  __stop___ksymtab = .;
-
-  __start___gpl_ksymtab = .;	/* Kernel symbol table:	GPL-only symbols */
-  __gpl_ksymtab : { *(__gpl_ksymtab) }
-  __stop___gpl_ksymtab = .;
-
-  __start___kallsyms = .;       /* All kernel symbols */
-  __kallsyms : { *(__kallsyms) }
-  __stop___kallsyms = .;
-
   .unprotected : { *(.unprotected) }
   . = ALIGN(4096);
   PROVIDE (_unprotected_end = .);
@@ -46,10 +36,6 @@
   .init.setup : { *(.init.setup) }
   __setup_end = .;
 
-  __start___param = .;
-  __param : { *(__param) }
-  __stop___param = .;
-
   . = ALIGN(32);
   __per_cpu_start = . ; 
   .data.percpu : { *(.data.percpu) }
@@ -67,11 +53,17 @@
   }
   __initcall_end = .;
 
+  __con_initcall_start = .;
+  .con_initcall.init : { *(.con_initcall.init) }
+  __con_initcall_end = .;
+
   __uml_initcall_start = .;
   .uml.initcall.init : { *(.uml.initcall.init) }
   __uml_initcall_end = .;
   __init_end = .;
 
+  SECURITY_INIT
+
   __exitcall_begin = .;
   .exitcall : { *(.exitcall.exit) }
   __exitcall_end = .;
@@ -80,7 +72,33 @@
   .uml.exitcall : { *(.uml.exitcall.exit) }
   __uml_exitcall_end = .;
 
-  . = ALIGN(4096);
+  . = ALIGN(4);
+  __alt_instructions = .;
+  .altinstructions : { *(.altinstructions) }
+  __alt_instructions_end = .;
+  .altinstr_replacement : { *(.altinstr_replacement) }
+  /* .exit.text is discard at runtime, not link time, to deal with references
+     from .altinstructions and .eh_frame */
+  .exit.text : { *(.exit.text) }
+  .exit.data : { *(.exit.data) }
+
+  __preinit_array_start = .;
+  .preinit_array : { *(.preinit_array) }
+  __preinit_array_end = .;
+  __init_array_start = .;
+  .init_array : { *(.init_array) }
+  __init_array_end = .;
+  __fini_array_start = .;
+  .fini_array : { *(.fini_array) }
+  __fini_array_end = .;
+
+   . = ALIGN(4096);
   __initramfs_start = .;
   .init.ramfs : { *(.init.ramfs) }
   __initramfs_end = .;
+
+  /* Sections to be discarded */
+  /DISCARD/ : {
+ 	*(.exitcall.exit)
+  }
+
diff -Nru a/include/asm-um/cpufeature.h b/include/asm-um/cpufeature.h
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/include/asm-um/cpufeature.h	2004-10-18 14:57:24 -07:00
@@ -0,0 +1,6 @@
+#ifndef __UM_CPUFEATURE_H
+#define __UM_CPUFEATURE_H
+
+#include "asm/arch/cpufeature.h"
+
+#endif
diff -Nru a/include/asm-um/current.h b/include/asm-um/current.h
--- a/include/asm-um/current.h	2004-10-18 14:55:54 -07:00
+++ b/include/asm-um/current.h	2004-10-18 14:55:54 -07:00
@@ -16,8 +16,10 @@
 #define CURRENT_THREAD(dummy) (((unsigned long) &dummy) & \
 			        (PAGE_MASK << CONFIG_KERNEL_STACK_ORDER))
 
-#define current ({ int dummy; \
-                   ((struct thread_info *) CURRENT_THREAD(dummy))->task; })
+#define current_thread \
+	({ int dummy; ((struct thread_info *) CURRENT_THREAD(dummy)); })
+
+#define current (current_thread->task)
 
 #endif /* __ASSEMBLY__ */
 
diff -Nru a/include/asm-um/dma-mapping.h b/include/asm-um/dma-mapping.h
--- a/include/asm-um/dma-mapping.h	2004-10-18 14:55:55 -07:00
+++ b/include/asm-um/dma-mapping.h	2004-10-18 14:55:55 -07:00
@@ -1 +1,121 @@
-#include <asm-generic/dma-mapping.h>
+#ifndef _ASM_DMA_MAPPING_H
+#define _ASM_DMA_MAPPING_H
+
+#include <asm/scatterlist.h>
+
+static inline int
+dma_supported(struct device *dev, u64 mask)
+{
+	BUG();
+	return(0);
+}
+
+static inline int
+dma_set_mask(struct device *dev, u64 dma_mask)
+{
+	BUG();
+	return(0);
+}
+
+static inline void *
+dma_alloc_coherent(struct device *dev, size_t size, dma_addr_t *dma_handle,
+		   int flag)
+{
+	BUG();
+	return((void *) 0);
+}
+
+static inline void
+dma_free_coherent(struct device *dev, size_t size, void *cpu_addr,
+		  dma_addr_t dma_handle)
+{
+	BUG();
+}
+
+static inline dma_addr_t
+dma_map_single(struct device *dev, void *cpu_addr, size_t size,
+	       enum dma_data_direction direction)
+{
+	BUG();
+	return(0);
+}
+
+static inline void
+dma_unmap_single(struct device *dev, dma_addr_t dma_addr, size_t size,
+		 enum dma_data_direction direction)
+{
+	BUG();
+}
+
+static inline dma_addr_t
+dma_map_page(struct device *dev, struct page *page,
+	     unsigned long offset, size_t size,
+	     enum dma_data_direction direction)
+{
+	BUG();
+	return(0);
+}
+
+static inline void
+dma_unmap_page(struct device *dev, dma_addr_t dma_address, size_t size,
+	       enum dma_data_direction direction)
+{
+	BUG();
+}
+
+static inline int
+dma_map_sg(struct device *dev, struct scatterlist *sg, int nents,
+	   enum dma_data_direction direction)
+{
+	BUG();
+	return(0);
+}
+
+static inline void
+dma_unmap_sg(struct device *dev, struct scatterlist *sg, int nhwentries,
+	     enum dma_data_direction direction)
+{
+	BUG();
+}
+
+static inline void
+dma_sync_single(struct device *dev, dma_addr_t dma_handle, size_t size,
+		enum dma_data_direction direction)
+{
+	BUG();
+}
+
+static inline void
+dma_sync_sg(struct device *dev, struct scatterlist *sg, int nelems,
+	    enum dma_data_direction direction)
+{
+	BUG();
+}
+
+#define dma_alloc_noncoherent(d, s, h, f) dma_alloc_coherent(d, s, h, f)
+#define dma_free_noncoherent(d, s, v, h) dma_free_coherent(d, s, v, h)
+#define dma_is_consistent(d) (1)
+
+static inline int
+dma_get_cache_alignment(void)
+{
+	BUG();
+	return(0);
+}
+
+static inline void
+dma_sync_single_range(struct device *dev, dma_addr_t dma_handle,
+		      unsigned long offset, size_t size,
+		      enum dma_data_direction direction)
+{
+	BUG();
+}
+
+static inline void
+dma_cache_sync(void *vaddr, size_t size,
+	       enum dma_data_direction direction)
+{
+	BUG();
+}
+
+#endif
diff -Nru a/include/asm-um/elf.h b/include/asm-um/elf.h
--- a/include/asm-um/elf.h	2004-10-18 14:56:33 -07:00
+++ b/include/asm-um/elf.h	2004-10-18 14:56:33 -07:00
@@ -15,4 +15,17 @@
 
 #define USE_ELF_CORE_DUMP
 
+#define R_386_NONE	0
+#define R_386_32	1
+#define R_386_PC32	2
+#define R_386_GOT32	3
+#define R_386_PLT32	4
+#define R_386_COPY	5
+#define R_386_GLOB_DAT	6
+#define R_386_JMP_SLOT	7
+#define R_386_RELATIVE	8
+#define R_386_GOTOFF	9
+#define R_386_GOTPC	10
+#define R_386_NUM	11
+
 #endif
diff -Nru a/include/asm-um/fixmap.h b/include/asm-um/fixmap.h
--- a/include/asm-um/fixmap.h	2004-10-18 14:57:03 -07:00
+++ b/include/asm-um/fixmap.h	2004-10-18 14:57:03 -07:00
@@ -34,6 +34,7 @@
 	FIX_KMAP_BEGIN,	/* reserved pte's for temporary kernel mappings */
 	FIX_KMAP_END = FIX_KMAP_BEGIN+(KM_TYPE_NR*NR_CPUS)-1,
 #endif
+	FIX_VSYSCALL,
 	__end_of_fixed_addresses
 };
 
@@ -62,6 +63,13 @@
 
 #define __fix_to_virt(x)	(FIXADDR_TOP - ((x) << PAGE_SHIFT))
 #define __virt_to_fix(x)      ((FIXADDR_TOP - ((x)&PAGE_MASK)) >> PAGE_SHIFT)
+
+/*
+ * This is the range that is readable by user mode, and things
+ * acting like user mode such as get_user_pages.
+ */
+#define FIXADDR_USER_START	(__fix_to_virt(FIX_VSYSCALL))
+#define FIXADDR_USER_END	(FIXADDR_USER_START + PAGE_SIZE)
 
 extern void __this_fixmap_does_not_exist(void);
 
diff -Nru a/include/asm-um/irq.h b/include/asm-um/irq.h
--- a/include/asm-um/irq.h	2004-10-18 14:57:04 -07:00
+++ b/include/asm-um/irq.h	2004-10-18 14:57:04 -07:00
@@ -1,15 +1,6 @@
 #ifndef __UM_IRQ_H
 #define __UM_IRQ_H
 
-/* The i386 irq.h has a struct task_struct in a prototype without including
- * sched.h.  This forward declaration kills the resulting warning.
- */
-struct task_struct;
-
-#include "asm/ptrace.h"
-
-#undef NR_IRQS
-
 #define TIMER_IRQ		0
 #define UMN_IRQ			1
 #define CONSOLE_IRQ		2
@@ -27,14 +18,5 @@
 
 #define LAST_IRQ XTERM_IRQ
 #define NR_IRQS (LAST_IRQ + 1)
-
-extern int um_request_irq(unsigned int irq, int fd, int type,
-			  void (*handler)(int, void *, struct pt_regs *),
-			  unsigned long irqflags,  const char * devname,
-			  void *dev_id);
-
-struct irqaction;
-struct pt_regs;
-int handle_IRQ_event(unsigned int, struct pt_regs *, struct irqaction *);
 
 #endif
diff -Nru a/include/asm-um/local.h b/include/asm-um/local.h
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/include/asm-um/local.h	2004-10-18 14:57:23 -07:00
@@ -0,0 +1,6 @@
+#ifndef __UM_LOCAL_H
+#define __UM_LOCAL_H
+
+#include "asm/arch/local.h"
+
+#endif
diff -Nru a/include/asm-um/mmu_context.h b/include/asm-um/mmu_context.h
--- a/include/asm-um/mmu_context.h	2004-10-18 14:56:32 -07:00
+++ b/include/asm-um/mmu_context.h	2004-10-18 14:56:32 -07:00
@@ -26,8 +26,8 @@
 	unsigned 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);
 		if(next != &init_mm)
 			CHOOSE_MODE((void) 0, 
 				    switch_mm_skas(next->context.skas.mm_fd));
diff -Nru a/include/asm-um/module-generic.h b/include/asm-um/module-generic.h
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/include/asm-um/module-generic.h	2004-10-18 14:57:21 -07:00
@@ -0,0 +1,6 @@
+#ifndef __UM_MODULE_GENERIC_H
+#define __UM_MODULE_GENERIC_H
+
+#include "asm/arch/module.h"
+
+#endif
diff -Nru a/include/asm-um/module-i386.h b/include/asm-um/module-i386.h
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/include/asm-um/module-i386.h	2004-10-18 14:57:23 -07:00
@@ -0,0 +1,13 @@
+#ifndef __UM_MODULE_I386_H
+#define __UM_MODULE_I386_H
+
+/* UML is simple */
+struct mod_arch_specific
+{
+};
+
+#define Elf_Shdr Elf32_Shdr
+#define Elf_Sym Elf32_Sym
+#define Elf_Ehdr Elf32_Ehdr
+
+#endif
diff -Nru a/include/asm-um/module.h b/include/asm-um/module.h
--- a/include/asm-um/module.h	2004-10-18 14:56:33 -07:00
+++ /dev/null	Wed Dec 31 16:00:00 196900
@@ -1,13 +0,0 @@
-#ifndef __UM_MODULE_H
-#define __UM_MODULE_H
-
-/* UML is simple */
-struct mod_arch_specific
-{
-};
-
-#define Elf_Shdr Elf32_Shdr
-#define Elf_Sym Elf32_Sym
-#define Elf_Ehdr Elf32_Ehdr
-
-#endif
diff -Nru a/include/asm-um/page.h b/include/asm-um/page.h
--- a/include/asm-um/page.h	2004-10-18 14:56:33 -07:00
+++ b/include/asm-um/page.h	2004-10-18 14:56:33 -07:00
@@ -1,10 +1,14 @@
+/*
+ *  Copyright (C) 2000 - 2003 Jeff Dike (jdike@addtoit.com)
+ * Licensed under the GPL
+ */
+
 #ifndef __UM_PAGE_H
 #define __UM_PAGE_H
 
 struct page;
 
 #include "asm/arch/page.h"
-#include "asm/bug.h"
 
 #undef __pa
 #undef __va
@@ -24,25 +28,25 @@
 
 #define __va_space (8*1024*1024)
 
-extern unsigned long region_pa(void *virt);
-extern void *region_va(unsigned long phys);
-
-#define __pa(virt) region_pa((void *) (virt))
-#define __va(phys) region_va((unsigned long) (phys))
-
-extern unsigned long page_to_pfn(struct page *page);
-extern struct page *pfn_to_page(unsigned long pfn);
+extern unsigned long to_phys(void *virt);
+extern void *to_virt(unsigned long phys);
 
-extern struct page *phys_to_page(unsigned long phys);
+#define __pa(virt) to_phys((void *) virt)
+#define __va(phys) to_virt((unsigned long) phys)
 
-#define virt_to_page(v) (phys_to_page(__pa(v)))
+#define page_to_pfn(page) ((page) - mem_map)
+#define pfn_to_page(pfn) (mem_map + (pfn))
 
-extern struct page *page_mem_map(struct page *page);
-
-#define pfn_valid(pfn) (page_mem_map(pfn_to_page(pfn)) != NULL)
-#define virt_addr_valid(v) pfn_valid(__pa(v) >> PAGE_SHIFT)
+#define phys_to_pfn(p) ((p) >> PAGE_SHIFT)
+#define pfn_to_phys(pfn) ((pfn) << PAGE_SHIFT)
 
+#define pfn_valid(pfn) ((pfn) < max_mapnr)
+#define virt_addr_valid(v) pfn_valid(phys_to_pfn(__pa(v)))
+  
 extern struct page *arch_validate(struct page *page, int mask, int order);
 #define HAVE_ARCH_VALIDATE
+
+extern void arch_free_page(struct page *page, int order);
+#define HAVE_ARCH_FREE_PAGE
 
 #endif
diff -Nru a/include/asm-um/pgtable.h b/include/asm-um/pgtable.h
--- a/include/asm-um/pgtable.h	2004-10-18 14:57:19 -07:00
+++ b/include/asm-um/pgtable.h	2004-10-18 14:57:19 -07:00
@@ -12,8 +12,6 @@
 #include "asm/page.h"
 #include "asm/fixmap.h"
 
-extern pgd_t swapper_pg_dir[1024];
-
 extern void *um_virt_to_phys(struct task_struct *task, unsigned long virt,
 			     pte_t *pte_out);
 
@@ -49,6 +47,8 @@
 #define pgd_ERROR(e) \
         printk("%s:%d: bad pgd %08lx.\n", __FILE__, __LINE__, pgd_val(e))
 
+extern pgd_t swapper_pg_dir[PTRS_PER_PGD];
+
 /*
  * pgd entries used up by user/kernel:
  */
@@ -65,10 +65,10 @@
  * area for the same reason. ;)
  */
 
-extern unsigned long high_physmem;
+extern unsigned long end_iomem;
 
 #define VMALLOC_OFFSET	(__va_space)
-#define VMALLOC_START	(((unsigned long) high_physmem + VMALLOC_OFFSET) & ~(VMALLOC_OFFSET-1))
+#define VMALLOC_START	((end_iomem + VMALLOC_OFFSET) & ~(VMALLOC_OFFSET-1))
 
 #ifdef CONFIG_HIGHMEM
 # define VMALLOC_END	(PKMAP_BASE-2*PAGE_SIZE)
@@ -78,12 +78,13 @@
 
 #define _PAGE_PRESENT	0x001
 #define _PAGE_NEWPAGE	0x002
-#define _PAGE_PROTNONE	0x004	/* If not present */
-#define _PAGE_RW	0x008
-#define _PAGE_USER	0x010
-#define _PAGE_ACCESSED	0x020
-#define _PAGE_DIRTY	0x040
-#define _PAGE_NEWPROT   0x080
+#define _PAGE_NEWPROT   0x004
+#define _PAGE_FILE	0x008   /* set:pagecache unset:swap */
+#define _PAGE_PROTNONE	0x010	/* If not present */
+#define _PAGE_RW	0x020
+#define _PAGE_USER	0x040
+#define _PAGE_ACCESSED	0x080
+#define _PAGE_DIRTY	0x100
 
 #define REGION_MASK	0xf0000000
 #define REGION_SHIFT	28
@@ -143,7 +144,8 @@
 
 #define BAD_PAGETABLE __bad_pagetable()
 #define BAD_PAGE __bad_page()
-#define ZERO_PAGE(vaddr) (virt_to_page(empty_zero_page))
+
+#define ZERO_PAGE(vaddr) virt_to_page(empty_zero_page)
 
 /* number of bits that fit into a memory pointer */
 #define BITS_PER_PTR			(8*sizeof(unsigned long))
@@ -164,9 +166,6 @@
 
 #define pte_clear(xp)	do { pte_val(*(xp)) = _PAGE_NEWPAGE; } while (0)
 
-#define phys_region_index(x) (((x) & REGION_MASK) >> REGION_SHIFT)
-#define pte_region_index(x) phys_region_index(pte_val(x))
-
 #define pmd_none(x)	(!(pmd_val(x) & ~_PAGE_NEWPAGE))
 #define	pmd_bad(x)	((pmd_val(x) & (~PAGE_MASK & ~_PAGE_USER)) != _KERNPG_TABLE)
 #define pmd_present(x)	(pmd_val(x) & _PAGE_PRESENT)
@@ -188,19 +187,25 @@
 
 #define pages_to_mb(x) ((x) >> (20-PAGE_SHIFT))
 
-extern struct page *pte_mem_map(pte_t pte);
-extern struct page *phys_mem_map(unsigned long phys);
-extern unsigned long phys_to_pfn(unsigned long p);
-extern unsigned long pfn_to_phys(unsigned long pfn);
-
-#define pte_page(x) pfn_to_page(pte_pfn(x))
-#define pte_address(x) (__va(pte_val(x) & PAGE_MASK))
-#define mk_phys(a, r) ((a) + (r << REGION_SHIFT))
-#define phys_addr(p) ((p) & ~REGION_MASK)
-#define phys_page(p) (phys_mem_map(p) + ((phys_addr(p)) >> PAGE_SHIFT))
+#define pte_page(pte) phys_to_page(pte_val(pte))
+#define pmd_page(pmd) phys_to_page(pmd_val(pmd) & PAGE_MASK)
+
 #define pte_pfn(x) phys_to_pfn(pte_val(x))
 #define pfn_pte(pfn, prot) __pte(pfn_to_phys(pfn) | pgprot_val(prot))
-#define pfn_pmd(pfn, prot) __pmd(pfn_to_phys(pfn) | pgprot_val(prot))
+
+extern struct page *phys_to_page(const unsigned long phys);
+extern struct page *__virt_to_page(const unsigned long virt);
+#define virt_to_page(addr) __virt_to_page((const unsigned long) addr)
+
+/*
+ * Bits 0 through 3 are taken
+ */
+#define PTE_FILE_MAX_BITS	28
+
+#define pte_to_pgoff(pte) ((pte).pte_low >> 4)
+
+#define pgoff_to_pte(off) \
+	((pte_t) { ((off) << 4) + _PAGE_FILE })
 
 static inline pte_t pte_mknewprot(pte_t pte)
 {
@@ -235,6 +240,12 @@
  * The following only work if pte_present() is true.
  * Undefined behaviour if not..
  */
+static inline int pte_user(pte_t pte)
+{
+	return((pte_val(pte) & _PAGE_USER) &&
+	       !(pte_val(pte) & _PAGE_PROTNONE));
+}
+
 static inline int pte_read(pte_t pte)
 { 
 	return((pte_val(pte) & _PAGE_USER) && 
@@ -252,6 +263,14 @@
 	       !(pte_val(pte) & _PAGE_PROTNONE));
 }
 
+/*
+ * The following only works if pte_present() is not true.
+ */
+static inline int pte_file(pte_t pte)
+{
+	return (pte).pte_low & _PAGE_FILE;
+}
+
 static inline int pte_dirty(pte_t pte)	{ return pte_val(pte) & _PAGE_DIRTY; }
 static inline int pte_young(pte_t pte)	{ return pte_val(pte) & _PAGE_ACCESSED; }
 static inline int pte_newpage(pte_t pte) { return pte_val(pte) & _PAGE_NEWPAGE; }
@@ -334,14 +353,7 @@
  * and a page entry and page directory to the page they refer to.
  */
 
-#define mk_pte(page, pgprot) \
-({					\
-	pte_t __pte;                    \
-                                        \
-	pte_val(__pte) = page_to_phys(page) + pgprot_val(pgprot);\
-	if(pte_present(__pte)) pte_mknewprot(pte_mknewpage(__pte)); \
-	__pte;                          \
-})
+extern pte_t mk_pte(struct page *page, pgprot_t pgprot);
 
 static inline pte_t pte_modify(pte_t pte, pgprot_t newprot)
 {
@@ -351,17 +363,27 @@
 }
 
 #define pmd_page_kernel(pmd) ((unsigned long) __va(pmd_val(pmd) & PAGE_MASK))
-#define pmd_page(pmd) (phys_mem_map(pmd_val(pmd) & PAGE_MASK) + \
-		       ((phys_addr(pmd_val(pmd)) >> PAGE_SHIFT)))
 
-/* to find an entry in a page-table-directory. */
+/*
+ * the pgd page can be thought of an array like this: pgd_t[PTRS_PER_PGD]
+ *
+ * this macro returns the index of the entry in the pgd page which would
+ * control the given virtual address
+ */
 #define pgd_index(address) ((address >> PGDIR_SHIFT) & (PTRS_PER_PGD-1))
 
-/* to find an entry in a page-table-directory */
+/*
+ * pgd_offset() returns a (pgd_t *)
+ * pgd_index() is used get the offset into the pgd page's array of pgd_t's;
+ */
 #define pgd_offset(mm, address) \
 ((mm)->pgd + ((address) >> PGDIR_SHIFT))
 
-/* to find an entry in a kernel page-table-directory */
+
+/*
+ * a shortcut which implies the use of the kernel's pgd, instead
+ * of a process's
+ */
 #define pgd_offset_k(address) pgd_offset(&init_mm, address)
 
 #define pmd_index(address) \
@@ -373,7 +395,12 @@
 	return (pmd_t *) dir;
 }
 
-/* Find an entry in the third-level page table.. */ 
+/*
+ * the pte page can be thought of an array like this: pte_t[PTRS_PER_PTE]
+ *
+ * this macro returns the index of the entry in the pte page which would
+ * control the given virtual address
+ */
 #define pte_index(address) (((address) >> PAGE_SHIFT) & (PTRS_PER_PTE - 1))
 #define pte_offset_kernel(dir, address) \
 	((pte_t *) pmd_page_kernel(*(dir)) +  pte_index(address))
@@ -387,11 +414,11 @@
 #define update_mmu_cache(vma,address,pte) do ; while (0)
 
 /* Encode and de-code a swap entry */
-#define __swp_type(x)			(((x).val >> 3) & 0x7f)
-#define __swp_offset(x)			((x).val >> 10)
+#define __swp_type(x)			(((x).val >> 4) & 0x3f)
+#define __swp_offset(x)			((x).val >> 11)
 
 #define __swp_entry(type, offset) \
-	((swp_entry_t) { ((type) << 3) | ((offset) << 10) })
+	((swp_entry_t) { ((type) << 4) | ((offset) << 11) })
 #define __pte_to_swp_entry(pte) \
 	((swp_entry_t) { pte_val(pte_mkuptodate(pte)) })
 #define __swp_entry_to_pte(x)		((pte_t) { (x).val })
diff -Nru a/include/asm-um/processor-generic.h b/include/asm-um/processor-generic.h
--- a/include/asm-um/processor-generic.h	2004-10-18 14:56:17 -07:00
+++ b/include/asm-um/processor-generic.h	2004-10-18 14:56:17 -07:00
@@ -11,41 +11,20 @@
 struct task_struct;
 
 #include "linux/config.h"
-#include "linux/signal.h"
 #include "asm/ptrace.h"
-#include "asm/siginfo.h"
 #include "choose-mode.h"
 
 struct mm_struct;
 
-#define current_text_addr() ((void *) 0)
-
-#define cpu_relax()	do ; while (0)
-
-#ifdef CONFIG_MODE_TT
-struct proc_tt_mode {
-	int extern_pid;
-	int tracing;
-	int switch_pipe[2];
-	int singlestep_syscall;
-	int vm_seq;
-};
-#endif
-
-#ifdef CONFIG_MODE_SKAS
-struct proc_skas_mode {
-	void *switch_buf;
-	void *fork_buf;
-};
-#endif
+#define cpu_relax()   barrier()
 
 struct thread_struct {
 	int forking;
-	unsigned long kernel_stack;
 	int nsyscalls;
 	struct pt_regs regs;
 	unsigned long cr2;
 	int err;
+	unsigned long trap_no;
 	void *fault_addr;
 	void *fault_catcher;
 	struct task_struct *prev_sched;
@@ -54,10 +33,20 @@
 	struct arch_thread arch;
 	union {
 #ifdef CONFIG_MODE_TT
-		struct proc_tt_mode tt;
+		struct {
+			int extern_pid;
+			int tracing;
+			int switch_pipe[2];
+			int singlestep_syscall;
+			int vm_seq;
+		} tt;
 #endif
 #ifdef CONFIG_MODE_SKAS
-		struct proc_skas_mode skas;
+		struct {
+			void *switch_buf;
+			void *fork_buf;
+			int mm_count;
+		} skas;
 #endif
 	} mode;
 	struct {
@@ -81,7 +70,6 @@
 #define INIT_THREAD \
 { \
 	.forking		= 0, \
-	.kernel_stack		= 0, \
 	.nsyscalls		= 0, \
         .regs		   	= EMPTY_REGS, \
 	.cr2			= 0, \
@@ -99,13 +87,18 @@
 } mm_segment_t;
 
 extern struct task_struct *alloc_task_struct(void);
-extern void free_task_struct(struct task_struct *task);
 
 extern void release_thread(struct task_struct *);
 extern int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags);
 extern void dump_thread(struct pt_regs *regs, struct user *u);
+extern void prepare_to_copy(struct task_struct *tsk);
 
 extern unsigned long thread_saved_pc(struct task_struct *t);
+
+static inline void mm_copy_segments(struct mm_struct *from_mm,
+				    struct mm_struct *new_mm)
+{
+}
 
 #define init_stack	(init_thread_union.stack)
 
diff -Nru a/include/asm-um/processor-i386.h b/include/asm-um/processor-i386.h
--- a/include/asm-um/processor-i386.h	2004-10-18 14:55:54 -07:00
+++ b/include/asm-um/processor-i386.h	2004-10-18 14:55:54 -07:00
@@ -6,8 +6,8 @@
 #ifndef __UM_PROCESSOR_I386_H
 #define __UM_PROCESSOR_I386_H
 
-extern int cpu_has_xmm;
-extern int cpu_has_cmov;
+extern int host_has_xmm;
+extern int host_has_cmov;
 
 struct arch_thread {
 	unsigned long debugregs[8];
@@ -18,6 +18,13 @@
                            .debugregs_seq	= 0 }
 
 #include "asm/arch/user.h"
+
+/*
+ * Default implementation of macro that returns current
+ * instruction pointer ("program counter"). Stolen
+ * from asm-i386/processor.h
+ */
+#define current_text_addr() ({ void *pc; __asm__("movl $1f,%0\n1:":"=g" (pc)); pc; })
 
 #include "asm/processor-generic.h"
 
diff -Nru a/include/asm-um/ptrace-generic.h b/include/asm-um/ptrace-generic.h
--- a/include/asm-um/ptrace-generic.h	2004-10-18 14:56:49 -07:00
+++ b/include/asm-um/ptrace-generic.h	2004-10-18 14:56:49 -07:00
@@ -45,6 +45,8 @@
 
 #define PT_REGS_SC(r) UPT_SC(&(r)->regs)
 
+#define instruction_pointer(regs) PT_REGS_IP(regs)
+
 struct task_struct;
 
 extern unsigned long getreg(struct task_struct *child, int regno);
diff -Nru a/include/asm-um/sections.h b/include/asm-um/sections.h
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/include/asm-um/sections.h	2004-10-18 14:57:24 -07:00
@@ -0,0 +1,7 @@
+#ifndef _UM_SECTIONS_H
+#define _UM_SECTIONS_H
+
+/* nothing to see, move along */
+#include <asm-generic/sections.h>
+
+#endif
diff -Nru a/include/asm-um/smp.h b/include/asm-um/smp.h
--- a/include/asm-um/smp.h	2004-10-18 14:55:53 -07:00
+++ b/include/asm-um/smp.h	2004-10-18 14:55:53 -07:00
@@ -8,16 +8,12 @@
 #include "asm/current.h"
 #include "linux/cpumask.h"
 
-extern cpumask_t cpu_online_map;
-
-#define smp_processor_id() (current->thread_info->cpu)
+#define smp_processor_id() (current_thread->cpu)
 #define cpu_logical_map(n) (n)
 #define cpu_number_map(n) (n)
 #define PROC_CHANGE_PENALTY	15 /* Pick a number, any number */
 extern int hard_smp_processor_id(void);
 #define NO_PROC_ID -1
-
-#define cpu_online(cpu) cpu_isset(cpu, cpu_online_map)
 
 extern int ncpus;
 
diff -Nru a/include/asm-um/smplock.h b/include/asm-um/smplock.h
--- a/include/asm-um/smplock.h	2004-10-18 14:56:13 -07:00
+++ /dev/null	Wed Dec 31 16:00:00 196900
@@ -1,6 +0,0 @@
-#ifndef __UM_SMPLOCK_H
-#define __UM_SMPLOCK_H
-
-#include "asm/arch/smplock.h"
-
-#endif
diff -Nru a/include/asm-um/spinlock.h b/include/asm-um/spinlock.h
--- a/include/asm-um/spinlock.h	2004-10-18 14:57:03 -07:00
+++ b/include/asm-um/spinlock.h	2004-10-18 14:57:21 -07:00
@@ -1,10 +1,6 @@
 #ifndef __UM_SPINLOCK_H
 #define __UM_SPINLOCK_H
 
-#include "linux/config.h"
-
-#ifdef CONFIG_SMP
 #include "asm/arch/spinlock.h"
-#endif
 
 #endif
diff -Nru a/include/asm-um/system-generic.h b/include/asm-um/system-generic.h
--- a/include/asm-um/system-generic.h	2004-10-18 14:57:04 -07:00
+++ b/include/asm-um/system-generic.h	2004-10-18 14:57:04 -07:00
@@ -23,8 +23,10 @@
 extern void block_signals(void);
 extern void unblock_signals(void);
 
-#define local_save_flags(flags) do { (flags) = get_signals(); } while(0)
-#define local_irq_restore(flags) do { set_signals(flags); } while(0)
+#define local_save_flags(flags) do { typecheck(unsigned long, flags); \
+				     (flags) = get_signals(); } while(0)
+#define local_irq_restore(flags) do { typecheck(unsigned long, flags); \
+				      set_signals(flags); } while(0)
 
 #define local_irq_save(flags) do { local_save_flags(flags); \
                                    local_irq_disable(); } while(0)
@@ -38,5 +40,8 @@
         local_save_flags(flags);        \
         (flags == 0);                   \
 })
+
+extern void *_switch_to(void *prev, void *next, void *last);
+#define switch_to(prev, next, last) prev = _switch_to(prev, next, last)
 
 #endif
diff -Nru a/include/asm-um/system-i386.h b/include/asm-um/system-i386.h
--- a/include/asm-um/system-i386.h	2004-10-18 14:56:28 -07:00
+++ b/include/asm-um/system-i386.h	2004-10-18 14:56:28 -07:00
@@ -2,36 +2,5 @@
 #define __UM_SYSTEM_I386_H
 
 #include "asm/system-generic.h"
-
-static inline unsigned long __cmpxchg(volatile void *ptr, unsigned long old,
-				      unsigned long new, int size)
-{
-	unsigned long prev;
-	switch (size) {
-	case 1:
-		__asm__ __volatile__(LOCK_PREFIX "cmpxchgb %b1,%2"
-				     : "=a"(prev)
-				     : "q"(new), "m"(*__xg(ptr)), "0"(old)
-				     : "memory");
-		return prev;
-	case 2:
-		__asm__ __volatile__(LOCK_PREFIX "cmpxchgw %w1,%2"
-				     : "=a"(prev)
-				     : "q"(new), "m"(*__xg(ptr)), "0"(old)
-				     : "memory");
-		return prev;
-	case 4:
-		__asm__ __volatile__(LOCK_PREFIX "cmpxchgl %1,%2"
-				     : "=a"(prev)
-				     : "q"(new), "m"(*__xg(ptr)), "0"(old)
-				     : "memory");
-		return prev;
-	}
-	return old;
-}
-
-#define cmpxchg(ptr,o,n)\
-	((__typeof__(*(ptr)))__cmpxchg((ptr),(unsigned long)(o),\
-					(unsigned long)(n),sizeof(*(ptr))))
     
 #endif
diff -Nru a/include/asm-um/thread_info.h b/include/asm-um/thread_info.h
--- a/include/asm-um/thread_info.h	2004-10-18 14:56:28 -07:00
+++ b/include/asm-um/thread_info.h	2004-10-18 14:56:28 -07:00
@@ -9,6 +9,7 @@
 #ifndef __ASSEMBLY__
 
 #include <asm/processor.h>
+#include <asm/types.h>
 
 struct thread_info {
 	struct task_struct	*task;		/* main task structure */
@@ -43,15 +44,18 @@
 static inline struct thread_info *current_thread_info(void)
 {
 	struct thread_info *ti;
-	__asm__("andl %%esp,%0; ":"=r" (ti) : "0" (~16383UL));
+	unsigned long mask = PAGE_SIZE *
+		(1 << CONFIG_KERNEL_STACK_ORDER) - 1;
+	__asm__("andl %%esp,%0; ":"=r" (ti) : "0" (~mask));
 	return ti;
 }
 
 /* thread information allocation */
-#define THREAD_SIZE (4*PAGE_SIZE)
-#define alloc_thread_info(tsk) ((struct thread_info *) \
-	__get_free_pages(GFP_KERNEL,2))
-#define free_thread_info(ti) free_pages((unsigned long) (ti), 2)
+#define THREAD_SIZE ((1 << CONFIG_KERNEL_STACK_ORDER) * PAGE_SIZE)
+#define alloc_thread_info(tsk) \
+	((struct thread_info *) kmalloc(THREAD_SIZE, GFP_KERNEL))
+#define free_thread_info(ti) kfree(ti)
+
 #define get_thread_info(ti) get_task_struct((ti)->task)
 #define put_thread_info(ti) put_task_struct((ti)->task)
 
@@ -65,11 +69,13 @@
 #define TIF_POLLING_NRFLAG      3       /* true if poll_idle() is polling 
 					 * TIF_NEED_RESCHED 
 					 */
+#define TIF_RESTART_BLOCK 	4
 
 #define _TIF_SYSCALL_TRACE	(1 << TIF_SYSCALL_TRACE)
 #define _TIF_SIGPENDING		(1 << TIF_SIGPENDING)
 #define _TIF_NEED_RESCHED	(1 << TIF_NEED_RESCHED)
 #define _TIF_POLLING_NRFLAG     (1 << TIF_POLLING_NRFLAG)
+#define _TIF_RESTART_BLOCK	(1 << TIF_RESTART_BLOCK)
 
 #endif
 
diff -Nru a/include/asm-um/timex.h b/include/asm-um/timex.h
--- a/include/asm-um/timex.h	2004-10-18 14:56:33 -07:00
+++ b/include/asm-um/timex.h	2004-10-18 14:56:33 -07:00
@@ -1,8 +1,6 @@
 #ifndef __UM_TIMEX_H
 #define __UM_TIMEX_H
 
-#include "linux/time.h"
-
 typedef unsigned long cycles_t;
 
 #define cacheflush_time (0)
diff -Nru a/include/asm-um/uaccess.h b/include/asm-um/uaccess.h
--- a/include/asm-um/uaccess.h	2004-10-18 14:56:48 -07:00
+++ b/include/asm-um/uaccess.h	2004-10-18 14:56:48 -07:00
@@ -6,6 +6,8 @@
 #ifndef __UM_UACCESS_H
 #define __UM_UACCESS_H
 
+#include "linux/sched.h"
+
 #define VERIFY_READ 0
 #define VERIFY_WRITE 1
 
@@ -34,6 +36,9 @@
 
 #define __copy_to_user(to, from, n) copy_to_user(to, from, n)
 
+#define __copy_to_user_inatomic __copy_to_user
+#define __copy_from_user_inatomic __copy_from_user
+
 #define __get_user(x, ptr) \
 ({ \
         const __typeof__(ptr) __private_ptr = ptr; \
@@ -50,7 +55,7 @@
 
 #define get_user(x, ptr) \
 ({ \
-        const __typeof__((*ptr)) *private_ptr = (ptr); \
+        const __typeof__((*(ptr))) *private_ptr = (ptr); \
         (access_ok(VERIFY_READ, private_ptr, sizeof(*private_ptr)) ? \
 	 __get_user(x, private_ptr) : ((x) = 0, -EFAULT)); \
 })
diff -Nru a/include/asm-um/unistd.h b/include/asm-um/unistd.h
--- a/include/asm-um/unistd.h	2004-10-18 14:56:49 -07:00
+++ b/include/asm-um/unistd.h	2004-10-18 14:56:49 -07:00
@@ -48,7 +48,10 @@
 	set_fs(KERNEL_DS);			\
 	ret = sys(args);			\
 	set_fs(fs);				\
-	return ret;
+	if (ret >= 0)				\
+		return ret;			\
+	errno = -(long)ret;			\
+	return -1;
 
 static inline long open(const char *pathname, int flags, int mode) 
 {
diff -Nru a/include/asm-v850/bug.h b/include/asm-v850/bug.h
--- a/include/asm-v850/bug.h	2004-10-18 14:56:17 -07:00
+++ b/include/asm-v850/bug.h	2004-10-18 14:56:17 -07:00
@@ -16,15 +16,7 @@
 
 extern void __bug (void) __attribute__ ((noreturn));
 #define BUG()		__bug()
-#define PAGE_BUG(page)	__bug()
-
-#define BUG_ON(condition) do { if (unlikely((condition)!=0)) BUG(); } while(0)
-
-#define WARN_ON(condition) do { \
-	if (unlikely((condition)!=0)) { \
-		printk("Badness in %s at %s:%d\n", __FUNCTION__, __FILE__, __LINE__); \
-		dump_stack(); \
-	} \
-} while (0)
+#define HAVE_ARCH_BUG
+#include <asm-generic/bug.h>
 
 #endif /* __V850_BUG_H__ */
diff -Nru a/include/asm-v850/hardirq.h b/include/asm-v850/hardirq.h
--- a/include/asm-v850/hardirq.h	2004-10-18 14:55:55 -07:00
+++ b/include/asm-v850/hardirq.h	2004-10-18 14:55:55 -07:00
@@ -36,20 +36,6 @@
 #define SOFTIRQ_SHIFT	(PREEMPT_SHIFT + PREEMPT_BITS)
 #define HARDIRQ_SHIFT	(SOFTIRQ_SHIFT + SOFTIRQ_BITS)
 
-#define __MASK(x)	((1UL << (x))-1)
-
-#define PREEMPT_MASK	(__MASK(PREEMPT_BITS) << PREEMPT_SHIFT)
-#define HARDIRQ_MASK	(__MASK(HARDIRQ_BITS) << HARDIRQ_SHIFT)
-#define SOFTIRQ_MASK	(__MASK(SOFTIRQ_BITS) << SOFTIRQ_SHIFT)
-
-#define hardirq_count()	(preempt_count() & HARDIRQ_MASK)
-#define softirq_count()	(preempt_count() & SOFTIRQ_MASK)
-#define irq_count()	(preempt_count() & (HARDIRQ_MASK | SOFTIRQ_MASK))
-
-#define PREEMPT_OFFSET	(1UL << PREEMPT_SHIFT)
-#define SOFTIRQ_OFFSET	(1UL << SOFTIRQ_SHIFT)
-#define HARDIRQ_OFFSET	(1UL << HARDIRQ_SHIFT)
-
 /*
  * The hardirq mask has to be large enough to have
  * space for potentially all IRQ sources in the system
@@ -59,27 +45,7 @@
 # error HARDIRQ_BITS is too low!
 #endif
 
-/*
- * Are we doing bottom half or hardware interrupt processing?
- * Are we in a softirq context? Interrupt context?
- */
-#define in_irq()		(hardirq_count())
-#define in_softirq()		(softirq_count())
-#define in_interrupt()		(irq_count())
-
-#define hardirq_trylock()	(!in_interrupt())
-#define hardirq_endlock()	do { } while (0)
-
 #define irq_enter()		(preempt_count() += HARDIRQ_OFFSET)
-
-#ifdef CONFIG_PREEMPT
-# define in_atomic()    (preempt_count() != kernel_locked())
-# define IRQ_EXIT_OFFSET (HARDIRQ_OFFSET-1)
-#else
-# define in_atomic()    (preempt_count() != 0)
-# define IRQ_EXIT_OFFSET HARDIRQ_OFFSET
-#endif
-
 #define irq_exit()							      \
 do {									      \
 	preempt_count() -= IRQ_EXIT_OFFSET;				      \
@@ -87,11 +53,5 @@
 		do_softirq();						      \
 	preempt_enable_no_resched();					      \
 } while (0)
-
-#ifndef CONFIG_SMP
-# define synchronize_irq(irq)	barrier()
-#else
-# error v850nommu SMP is not available
-#endif /* CONFIG_SMP */
 
 #endif /* __V850_HARDIRQ_H__ */
diff -Nru a/include/asm-v850/ptrace.h b/include/asm-v850/ptrace.h
--- a/include/asm-v850/ptrace.h	2004-10-18 14:57:05 -07:00
+++ b/include/asm-v850/ptrace.h	2004-10-18 14:57:05 -07:00
@@ -76,6 +76,7 @@
 
 
 #define instruction_pointer(regs)	((regs)->pc)
+#define profile_pc(regs) instruction_pointer(regs)
 #define user_mode(regs)			(!(regs)->kernel_mode)
 
 /* When a struct pt_regs is used to save user state for a system call in
diff -Nru a/include/asm-v850/resource.h b/include/asm-v850/resource.h
--- a/include/asm-v850/resource.h	2004-10-18 14:55:54 -07:00
+++ b/include/asm-v850/resource.h	2004-10-18 14:55:54 -07:00
@@ -39,7 +39,7 @@
 	{ RLIM_INFINITY, RLIM_INFINITY },		\
 	{             0,             0 },		\
 	{      INR_OPEN,     INR_OPEN  },		\
-	{ RLIM_INFINITY, RLIM_INFINITY },		\
+	{   MLOCK_LIMIT,   MLOCK_LIMIT },		\
 	{ RLIM_INFINITY, RLIM_INFINITY },		\
 	{ RLIM_INFINITY, RLIM_INFINITY },		\
 	{ MAX_SIGPENDING, MAX_SIGPENDING },		\
diff -Nru a/include/asm-v850/socket.h b/include/asm-v850/socket.h
--- a/include/asm-v850/socket.h	2004-10-18 14:56:27 -07:00
+++ b/include/asm-v850/socket.h	2004-10-18 14:56:27 -07:00
@@ -47,20 +47,4 @@
 
 #define SO_PEERSEC		31
 
-/* Nast libc5 fixup - bletch */
-#if defined(__KERNEL__)
-/* Socket types. */
-#define SOCK_STREAM	1		/* stream (connection) socket	*/
-#define SOCK_DGRAM	2		/* datagram (conn.less) socket	*/
-#define SOCK_RAW	3		/* raw socket			*/
-#define SOCK_RDM	4		/* reliably-delivered message	*/
-#define SOCK_SEQPACKET	5		/* sequential packet socket	*/
-#define SOCK_PACKET	10		/* linux specific way of	*/
-					/* getting packets at the dev	*/
-					/* level.  For writing rarp and	*/
-					/* other similar things on the	*/
-					/* user level.			*/
-#define	SOCK_MAX	(SOCK_PACKET+1)
-#endif
-
 #endif /* __V850_SOCKET_H__ */
diff -Nru a/include/asm-v850/uaccess.h b/include/asm-v850/uaccess.h
--- a/include/asm-v850/uaccess.h	2004-10-18 14:56:49 -07:00
+++ b/include/asm-v850/uaccess.h	2004-10-18 14:56:49 -07:00
@@ -112,6 +112,9 @@
 #define __copy_from_user(to, from, n)	(memcpy (to, from, n), 0)
 #define __copy_to_user(to, from, n)	(memcpy(to, from, n), 0)
 
+#define __copy_to_user_inatomic __copy_to_user
+#define __copy_from_user_inatomic __copy_from_user
+
 #define copy_from_user(to, from, n)	__copy_from_user (to, from, n)
 #define copy_to_user(to, from, n) 	__copy_to_user(to, from, n)
 
diff -Nru a/include/asm-x86_64/acpi.h b/include/asm-x86_64/acpi.h
--- a/include/asm-x86_64/acpi.h	2004-10-18 14:56:48 -07:00
+++ b/include/asm-x86_64/acpi.h	2004-10-18 14:56:48 -07:00
@@ -99,6 +99,11 @@
         :"=r"(n_hi), "=r"(n_lo)     \
         :"0"(n_hi), "1"(n_lo))
 
+/*
+ * Refer Intel ACPI _PDC support document for bit definitions
+ */
+#define ACPI_PDC_EST_CAPABILITY_SMP 	0xa
+#define ACPI_PDC_EST_CAPABILITY_MSR	0x1
 
 #ifdef CONFIG_ACPI_BOOT
 extern int acpi_lapic;
@@ -158,6 +163,8 @@
 
 extern int acpi_disabled;
 extern int acpi_pci_disabled;
+
+extern u8 x86_acpiid_to_apicid[];
 
 #endif /*__KERNEL__*/
 
diff -Nru a/include/asm-x86_64/apic.h b/include/asm-x86_64/apic.h
--- a/include/asm-x86_64/apic.h	2004-10-18 14:57:03 -07:00
+++ b/include/asm-x86_64/apic.h	2004-10-18 14:57:03 -07:00
@@ -7,15 +7,29 @@
 #include <asm/apicdef.h>
 #include <asm/system.h>
 
-#ifdef CONFIG_X86_LOCAL_APIC
+#define Dprintk(x...)
 
-#define APIC_DEBUG 0
+/*
+ * Debugging macros
+ */
+#define APIC_QUIET   0
+#define APIC_VERBOSE 1
+#define APIC_DEBUG   2
 
-#if APIC_DEBUG
-#define Dprintk(x...) printk(x)
-#else
-#define Dprintk(x...)
-#endif
+extern int apic_verbosity;
+
+/*
+ * Define the default level of output to be very little
+ * This can be turned up by using apic=verbose for more
+ * information and apic=debug for _lots_ of information.
+ * apic_verbosity is defined in apic.c
+ */
+#define apic_printk(v, s, a...) do {       \
+		if ((v) <= apic_verbosity) \
+			printk(s, ##a);    \
+	} while (0)
+
+#ifdef CONFIG_X86_LOCAL_APIC
 
 struct pt_regs;
 
diff -Nru a/include/asm-x86_64/apicdef.h b/include/asm-x86_64/apicdef.h
--- a/include/asm-x86_64/apicdef.h	2004-10-18 14:56:27 -07:00
+++ b/include/asm-x86_64/apicdef.h	2004-10-18 14:56:27 -07:00
@@ -108,7 +108,7 @@
 
 #define APIC_BASE (fix_to_virt(FIX_APIC_BASE))
 
-#define MAX_IO_APICS 16
+#define MAX_IO_APICS 32
 
 /*
  * the local APIC register structure, memory mapped. Not terribly well
diff -Nru a/include/asm-x86_64/atomic.h b/include/asm-x86_64/atomic.h
--- a/include/asm-x86_64/atomic.h	2004-10-18 14:57:04 -07:00
+++ b/include/asm-x86_64/atomic.h	2004-10-18 14:57:04 -07:00
@@ -178,6 +178,166 @@
 	return c;
 }
 
+/* An 64bit atomic type */
+
+typedef struct { volatile long counter; } atomic64_t;
+
+#define ATOMIC64_INIT(i)	{ (i) }
+
+/**
+ * atomic64_read - read atomic64 variable
+ * @v: pointer of type atomic64_t
+ *
+ * Atomically reads the value of @v.
+ * Doesn't imply a read memory barrier.
+ */
+#define atomic64_read(v)		((v)->counter)
+
+/**
+ * atomic64_set - set atomic64 variable
+ * @v: pointer to type atomic64_t
+ * @i: required value
+ *
+ * Atomically sets the value of @v to @i.
+ */
+#define atomic64_set(v,i)		(((v)->counter) = (i))
+
+/**
+ * atomic64_add - add integer to atomic64 variable
+ * @i: integer value to add
+ * @v: pointer to type atomic64_t
+ *
+ * Atomically adds @i to @v.
+ */
+static __inline__ void atomic64_add(long i, atomic64_t *v)
+{
+	__asm__ __volatile__(
+		LOCK "addq %1,%0"
+		:"=m" (v->counter)
+		:"ir" (i), "m" (v->counter));
+}
+
+/**
+ * atomic64_sub - subtract the atomic64 variable
+ * @i: integer value to subtract
+ * @v: pointer to type atomic64_t
+ *
+ * Atomically subtracts @i from @v.
+ */
+static __inline__ void atomic64_sub(long i, atomic64_t *v)
+{
+	__asm__ __volatile__(
+		LOCK "subq %1,%0"
+		:"=m" (v->counter)
+		:"ir" (i), "m" (v->counter));
+}
+
+/**
+ * atomic64_sub_and_test - subtract value from variable and test result
+ * @i: integer value to subtract
+ * @v: pointer to type atomic64_t
+ *
+ * Atomically subtracts @i from @v and returns
+ * true if the result is zero, or false for all
+ * other cases.
+ */
+static __inline__ int atomic64_sub_and_test(long i, atomic64_t *v)
+{
+	unsigned char c;
+
+	__asm__ __volatile__(
+		LOCK "subq %2,%0; sete %1"
+		:"=m" (v->counter), "=qm" (c)
+		:"ir" (i), "m" (v->counter) : "memory");
+	return c;
+}
+
+/**
+ * atomic64_inc - increment atomic64 variable
+ * @v: pointer to type atomic64_t
+ *
+ * Atomically increments @v by 1.
+ */
+static __inline__ void atomic64_inc(atomic64_t *v)
+{
+	__asm__ __volatile__(
+		LOCK "incq %0"
+		:"=m" (v->counter)
+		:"m" (v->counter));
+}
+
+/**
+ * atomic64_dec - decrement atomic64 variable
+ * @v: pointer to type atomic64_t
+ *
+ * Atomically decrements @v by 1.
+ */
+static __inline__ void atomic64_dec(atomic64_t *v)
+{
+	__asm__ __volatile__(
+		LOCK "decq %0"
+		:"=m" (v->counter)
+		:"m" (v->counter));
+}
+
+/**
+ * atomic64_dec_and_test - decrement and test
+ * @v: pointer to type atomic64_t
+ *
+ * Atomically decrements @v by 1 and
+ * returns true if the result is 0, or false for all other
+ * cases.
+ */
+static __inline__ int atomic64_dec_and_test(atomic64_t *v)
+{
+	unsigned char c;
+
+	__asm__ __volatile__(
+		LOCK "decq %0; sete %1"
+		:"=m" (v->counter), "=qm" (c)
+		:"m" (v->counter) : "memory");
+	return c != 0;
+}
+
+/**
+ * atomic64_inc_and_test - increment and test
+ * @v: pointer to type atomic64_t
+ *
+ * Atomically increments @v by 1
+ * and returns true if the result is zero, or false for all
+ * other cases.
+ */
+static __inline__ int atomic64_inc_and_test(atomic64_t *v)
+{
+	unsigned char c;
+
+	__asm__ __volatile__(
+		LOCK "incq %0; sete %1"
+		:"=m" (v->counter), "=qm" (c)
+		:"m" (v->counter) : "memory");
+	return c != 0;
+}
+
+/**
+ * atomic64_add_negative - add and test if negative
+ * @v: pointer to atomic64_t
+ * @i: integer value to add
+ *
+ * Atomically adds @i to @v and returns true
+ * if the result is negative, or false when
+ * result is greater than or equal to zero.
+ */
+static __inline__ long atomic64_add_negative(long i, atomic64_t *v)
+{
+	unsigned char c;
+
+	__asm__ __volatile__(
+		LOCK "addq %2,%0; sets %1"
+		:"=m" (v->counter), "=qm" (c)
+		:"ir" (i), "m" (v->counter) : "memory");
+	return c;
+}
+
 /* These are x86-specific, used by some header files */
 #define atomic_clear_mask(mask, addr) \
 __asm__ __volatile__(LOCK "andl %0,%1" \
diff -Nru a/include/asm-x86_64/bitops.h b/include/asm-x86_64/bitops.h
--- a/include/asm-x86_64/bitops.h	2004-10-18 14:56:29 -07:00
+++ b/include/asm-x86_64/bitops.h	2004-10-18 14:56:29 -07:00
@@ -25,10 +25,10 @@
  * Note that @nr may be almost arbitrarily large; this function is not
  * restricted to acting on a single-word quantity.
  */
-static __inline__ void set_bit(long nr, volatile void * addr)
+static __inline__ void set_bit(int nr, volatile void * addr)
 {
 	__asm__ __volatile__( LOCK_PREFIX
-		"btsq %1,%0"
+		"btsl %1,%0"
 		:"=m" (ADDR)
 		:"dIr" (nr) : "memory");
 }
@@ -254,128 +254,37 @@
 
 #undef ADDR
 
-/**
- * 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.
- */
-static __inline__ int find_first_zero_bit(const unsigned long * addr, unsigned size)
-{
-	int d0, d1, d2;
-	int res;
-
-	if (!size)
-		return 0;
-	__asm__ __volatile__(
-		"movl $-1,%%eax\n\t"
-		"xorl %%edx,%%edx\n\t"
-		"repe; scasl\n\t"
-		"je 1f\n\t"
-		"xorl -4(%%rdi),%%eax\n\t"
-		"subq $4,%%rdi\n\t"
-		"bsfl %%eax,%%edx\n"
-		"1:\tsubq %%rbx,%%rdi\n\t"
-		"shlq $3,%%rdi\n\t"
-		"addq %%rdi,%%rdx"
-		:"=d" (res), "=&c" (d0), "=&D" (d1), "=&a" (d2)
-		:"1" ((size + 31) >> 5), "2" (addr), "b" (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
- */
-static __inline__ int find_next_zero_bit (const unsigned long * addr, int size, int 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);
-}
-
-
-/**
- * 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.
- */
-static __inline__ int find_first_bit(const unsigned long * addr, unsigned size)
-{
-	int d0, d1;
-	int res;
-
-	/* This looks at memory. Mark it volatile to tell gcc not to move it around */
-	__asm__ __volatile__(
-		"xorl %%eax,%%eax\n\t"
-		"repe; scasl\n\t"
-		"jz 1f\n\t"
-		"leaq -4(%%rdi),%%rdi\n\t"
-		"bsfl (%%rdi),%%eax\n"
-		"1:\tsubq %%rbx,%%rdi\n\t"
-		"shll $3,%%edi\n\t"
-		"addl %%edi,%%eax"
-		:"=a" (res), "=&c" (d0), "=&D" (d1)
-		:"1" ((size + 31) >> 5), "2" (addr), "b" (addr) : "memory");
-	return res;
-}
-
-/**
- * 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
- */
-static __inline__ int find_next_bit(const unsigned long * addr, int size, int offset)
-{
-	const unsigned long * p = addr + (offset >> 6);
-	unsigned long set = 0, bit = offset & 63, res;
+extern long find_first_zero_bit(const unsigned long * addr, unsigned long size);
+extern long find_next_zero_bit (const unsigned long * addr, long size, long offset);
+extern long find_first_bit(const unsigned long * addr, unsigned long size);
+extern long find_next_bit(const unsigned long * addr, long size, long offset);
+
+/* return index of first bet set in val or max when no bit is set */
+static inline unsigned long __scanbit(unsigned long val, unsigned long max)
+{
+	asm("bsfq %1,%0 ; cmovz %2,%0" : "=&r" (val) : "r" (val), "r" (max));
+	return val;
+}
+
+#define find_first_bit(addr,size) \
+((__builtin_constant_p(size) && size <= BITS_PER_LONG ? \
+  (__scanbit(*(unsigned long *)addr,(size))) : \
+  find_first_bit(addr,size)))
+
+#define find_next_bit(addr,size,off) \
+((__builtin_constant_p(size) && size <= BITS_PER_LONG ? 	  \
+  ((off) + (__scanbit((*(unsigned long *)addr) >> (off),(size)-(off)))) : \
+	find_next_bit(addr,size,off)))
+
+#define find_first_zero_bit(addr,size) \
+((__builtin_constant_p(size) && size <= BITS_PER_LONG ? \
+  (__scanbit(~*(unsigned long *)addr,(size))) : \
+  	find_first_zero_bit(addr,size)))
 	
-	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);
-}
+#define find_next_zero_bit(addr,size,off) \
+((__builtin_constant_p(size) && size <= BITS_PER_LONG ? 	  \
+  ((off)+(__scanbit(~(((*(unsigned long *)addr)) >> (off)),(size)-(off)))) : \
+	find_next_zero_bit(addr,size,off)))
 
 /* 
  * Find string of zero bits in a bitmap. -1 when not found.
diff -Nru a/include/asm-x86_64/bug.h b/include/asm-x86_64/bug.h
--- a/include/asm-x86_64/bug.h	2004-10-18 14:57:04 -07:00
+++ b/include/asm-x86_64/bug.h	2004-10-18 14:57:04 -07:00
@@ -6,27 +6,20 @@
 /*
  * Tell the user there is some problem.  The exception handler decodes 
  * this frame.
- */ 
-struct bug_frame { 
-       unsigned char ud2[2];          
+ */
+struct bug_frame {
+       unsigned char ud2[2];
 	/* should use 32bit offset instead, but the assembler doesn't 
-	   like it */ 
-	char *filename;   
-	unsigned short line; 
-} __attribute__((packed)); 
+	   like it */
+	char *filename;
+	unsigned short line;
+} __attribute__((packed));
 
+#define HAVE_ARCH_BUG
 #define BUG() \
 	asm volatile("ud2 ; .quad %c1 ; .short %c0" :: \
 		     "i"(__LINE__), "i" (__stringify(KBUILD_BASENAME)))
-#define BUG_ON(condition) do { if (unlikely((condition)!=0)) BUG(); } while(0)
-#define PAGE_BUG(page) BUG()
 void out_of_line_bug(void);
-
-#define WARN_ON(condition) do { \
-	if (unlikely((condition)!=0)) { \
-		printk("Badness in %s at %s:%d\n", __FUNCTION__, __FILE__, __LINE__); \
-		dump_stack(); \
-	} \
-} while (0)
+#include <asm-generic/bug.h>
 
 #endif
diff -Nru a/include/asm-x86_64/cpufeature.h b/include/asm-x86_64/cpufeature.h
--- a/include/asm-x86_64/cpufeature.h	2004-10-18 14:56:32 -07:00
+++ b/include/asm-x86_64/cpufeature.h	2004-10-18 14:56:32 -07:00
@@ -7,7 +7,7 @@
 #ifndef __ASM_X8664_CPUFEATURE_H
 #define __ASM_X8664_CPUFEATURE_H
 
-#define NCAPINTS	5	/* Currently we have 4 32-bit words worth of info */
+#define NCAPINTS	6
 
 /* Intel-defined CPU features, CPUID level 0x00000001, word 0 */
 #define X86_FEATURE_FPU		(0*32+ 0) /* Onboard FPU */
@@ -63,8 +63,17 @@
 #define X86_FEATURE_K8_C	(3*32+ 4) /* C stepping K8 */
 
 /* Intel-defined CPU features, CPUID level 0x00000001 (ecx), word 4 */
-#define X86_FEATURE_EST		(4*32+ 7) /* Enhanced SpeedStep */
+#define X86_FEATURE_XMM3	(4*32+ 0) /* Streaming SIMD Extensions-3 */
 #define X86_FEATURE_MWAIT	(4*32+ 3) /* Monitor/Mwait support */
+#define X86_FEATURE_DSCPL	(4*32+ 4) /* CPL Qualified Debug Store */
+#define X86_FEATURE_EST		(4*32+ 7) /* Enhanced SpeedStep */
+#define X86_FEATURE_TM2		(4*32+ 8) /* Thermal Monitor 2 */
+#define X86_FEATURE_CID		(4*32+10) /* Context ID */
+#define X86_FEATURE_CX16	(4*32+13) /* CMPXCHG16B */
+#define X86_FEATURE_XTPR	(4*32+14) /* Send Task Priority Messages */
+
+/* More extended AMD flags: CPUID level 0x80000001, ecx, word 5 */
+#define X86_FEATURE_HTVALID	(5*32+ 0) /* HyperThreading valid, otherwise CMP */
 
 #define cpu_has(c, bit)                test_bit(bit, (c)->x86_capability)
 #define boot_cpu_has(bit)      test_bit(bit, boot_cpu_data.x86_capability)
@@ -81,6 +90,8 @@
 #define cpu_has_mmx            1
 #define cpu_has_fxsr           1
 #define cpu_has_xmm            1
+#define cpu_has_xmm2           1
+#define cpu_has_xmm3           boot_cpu_has(X86_FEATURE_XMM3)
 #define cpu_has_ht             boot_cpu_has(X86_FEATURE_HT)
 #define cpu_has_mp             1 /* XXX */
 #define cpu_has_k6_mtrr        0
diff -Nru a/include/asm-x86_64/desc.h b/include/asm-x86_64/desc.h
--- a/include/asm-x86_64/desc.h	2004-10-18 14:57:18 -07:00
+++ b/include/asm-x86_64/desc.h	2004-10-18 14:57:18 -07:00
@@ -128,13 +128,13 @@
 { 
 	set_tssldt_descriptor(&cpu_gdt_table[cpu][GDT_ENTRY_TSS], (unsigned long)addr, 
 			      DESC_TSS,
-			      sizeof(struct tss_struct)); 
+			      sizeof(struct tss_struct) - 1);
 } 
 
 static inline void set_ldt_desc(unsigned cpu, void *addr, int size)
 { 
 	set_tssldt_descriptor(&cpu_gdt_table[cpu][GDT_ENTRY_LDT], (unsigned long)addr, 
-			      DESC_LDT, size * 8);
+			      DESC_LDT, size * 8 - 1);
 }
 
 static inline void set_seg_base(unsigned cpu, int entry, void *base)
diff -Nru a/include/asm-x86_64/dma-mapping.h b/include/asm-x86_64/dma-mapping.h
--- a/include/asm-x86_64/dma-mapping.h	2004-10-18 14:56:32 -07:00
+++ b/include/asm-x86_64/dma-mapping.h	2004-10-18 14:56:32 -07:00
@@ -1,6 +1,138 @@
 #ifndef _X8664_DMA_MAPPING_H
 #define _X8664_DMA_MAPPING_H 1
 
-#include <asm-generic/dma-mapping.h>
+/*
+ * IOMMU interface. See Documentation/DMA-mapping.txt and DMA-API.txt for
+ * documentation.
+ */
+
+#include <linux/config.h>
+
+#include <asm/scatterlist.h>
+#include <asm/io.h>
+#include <asm/swiotlb.h>
+
+extern dma_addr_t bad_dma_address;
+#define dma_mapping_error(x) \
+	(swiotlb ? swiotlb_dma_mapping_error(x) : ((x) == bad_dma_address))
+
+void *dma_alloc_coherent(struct device *dev, size_t size, dma_addr_t *dma_handle,
+			 unsigned gfp);
+void dma_free_coherent(struct device *dev, size_t size, void *vaddr,
+			 dma_addr_t dma_handle);
+
+#ifdef CONFIG_GART_IOMMU
+
+extern dma_addr_t dma_map_single(struct device *hwdev, void *ptr, size_t size,
+				 int direction);
+extern void dma_unmap_single(struct device *dev, dma_addr_t addr,size_t size,
+			     int direction);
+
+#else
+
+/* No IOMMU */
+
+static inline dma_addr_t dma_map_single(struct device *hwdev, void *ptr,
+					size_t size, int direction)
+{
+	dma_addr_t addr;
+
+	if (direction == DMA_NONE)
+		out_of_line_bug();
+	addr = virt_to_bus(ptr);
+
+	if ((addr+size) & ~*hwdev->dma_mask)
+		out_of_line_bug();
+	return addr;
+}
+
+static inline void dma_unmap_single(struct device *hwdev, dma_addr_t dma_addr,
+				    size_t size, int direction)
+{
+	if (direction == DMA_NONE)
+		out_of_line_bug();
+	/* Nothing to do */
+}
+
+#endif
+
+#define dma_map_page(dev,page,offset,size,dir) \
+	dma_map_single((dev), page_address(page)+(offset), (size), (dir))
+
+static inline void dma_sync_single_for_cpu(struct device *hwdev,
+					       dma_addr_t dma_handle,
+					       size_t size, int direction)
+{
+	if (direction == DMA_NONE)
+		out_of_line_bug();
+
+	if (swiotlb)
+		return swiotlb_sync_single_for_cpu(hwdev,dma_handle,size,direction);
+
+	flush_write_buffers();
+}
+
+static inline void dma_sync_single_for_device(struct device *hwdev,
+						  dma_addr_t dma_handle,
+						  size_t size, int direction)
+{
+        if (direction == DMA_NONE)
+		out_of_line_bug();
+
+	if (swiotlb)
+		return swiotlb_sync_single_for_device(hwdev,dma_handle,size,direction);
+
+	flush_write_buffers();
+}
+
+static inline void dma_sync_sg_for_cpu(struct device *hwdev,
+				       struct scatterlist *sg,
+				       int nelems, int direction)
+{
+	if (direction == DMA_NONE)
+		out_of_line_bug();
+
+	if (swiotlb)
+		return swiotlb_sync_sg_for_cpu(hwdev,sg,nelems,direction);
+
+	flush_write_buffers();
+}
+
+static inline void dma_sync_sg_for_device(struct device *hwdev,
+					  struct scatterlist *sg,
+					  int nelems, int direction)
+{
+	if (direction == DMA_NONE)
+		out_of_line_bug();
+
+	if (swiotlb)
+		return swiotlb_sync_sg_for_device(hwdev,sg,nelems,direction);
+
+	flush_write_buffers();
+}
+
+extern int dma_map_sg(struct device *hwdev, struct scatterlist *sg,
+		      int nents, int direction);
+extern void dma_unmap_sg(struct device *hwdev, struct scatterlist *sg,
+			 int nents, int direction);
+
+#define dma_unmap_page dma_unmap_single
+
+extern int dma_supported(struct device *hwdev, u64 mask);
+extern int dma_get_cache_alignment(void);
+#define dma_is_consistent(h) 1
+
+static inline int dma_set_mask(struct device *dev, u64 mask)
+{
+	if (!dev->dma_mask || !dma_supported(dev, mask))
+		return -EIO;
+	*dev->dma_mask = mask;
+	return 0;
+}
+
+static inline void dma_cache_sync(void *vaddr, size_t size, enum dma_data_direction dir)
+{
+	flush_write_buffers();
+}
 
 #endif
diff -Nru a/include/asm-x86_64/elf.h b/include/asm-x86_64/elf.h
--- a/include/asm-x86_64/elf.h	2004-10-18 14:56:49 -07:00
+++ b/include/asm-x86_64/elf.h	2004-10-18 14:56:49 -07:00
@@ -144,6 +144,13 @@
 extern void set_personality_64bit(void);
 #define SET_PERSONALITY(ex, ibcs2) set_personality_64bit()
 	
+/*
+ * An executable for which elf_read_implies_exec() returns TRUE will
+ * have the READ_IMPLIES_EXEC personality flag set automatically.
+ */
+#define elf_read_implies_exec_binary(ex, have_pt_gnu_stack)   \
+	 (!(have_pt_gnu_stack))
+
 extern int dump_task_regs (struct task_struct *, elf_gregset_t *);
 extern int dump_task_fpu (struct task_struct *, elf_fpregset_t *);
 
diff -Nru a/include/asm-x86_64/hardirq.h b/include/asm-x86_64/hardirq.h
--- a/include/asm-x86_64/hardirq.h	2004-10-18 14:56:17 -07:00
+++ b/include/asm-x86_64/hardirq.h	2004-10-18 14:56:17 -07:00
@@ -37,20 +37,6 @@
 #define SOFTIRQ_SHIFT	(PREEMPT_SHIFT + PREEMPT_BITS)
 #define HARDIRQ_SHIFT	(SOFTIRQ_SHIFT + SOFTIRQ_BITS)
 
-#define __MASK(x)	((1UL << (x))-1)
-
-#define PREEMPT_MASK	(__MASK(PREEMPT_BITS) << PREEMPT_SHIFT)
-#define HARDIRQ_MASK	(__MASK(HARDIRQ_BITS) << HARDIRQ_SHIFT)
-#define SOFTIRQ_MASK	(__MASK(SOFTIRQ_BITS) << SOFTIRQ_SHIFT)
-
-#define hardirq_count()	(preempt_count() & HARDIRQ_MASK)
-#define softirq_count()	(preempt_count() & SOFTIRQ_MASK)
-#define irq_count()	(preempt_count() & (HARDIRQ_MASK | SOFTIRQ_MASK))
-
-#define PREEMPT_OFFSET	(1UL << PREEMPT_SHIFT)
-#define SOFTIRQ_OFFSET	(1UL << SOFTIRQ_SHIFT)
-#define HARDIRQ_OFFSET	(1UL << HARDIRQ_SHIFT)
-
 /*
  * The hardirq mask has to be large enough to have
  * space for potentially all IRQ sources in the system
@@ -60,31 +46,10 @@
 # error HARDIRQ_BITS is too low!
 #endif
 
-/*
- * Are we doing bottom half or hardware interrupt processing?
- * Are we in a softirq context? Interrupt context?
- */
-#define in_irq()		(hardirq_count())
-#define in_softirq()		(softirq_count())
-#define in_interrupt()		(irq_count())
-
-
-#define hardirq_trylock()	(!in_interrupt())
-#define hardirq_endlock()	do { } while (0)
-
-#define irq_enter()		(preempt_count() += HARDIRQ_OFFSET)
 #define nmi_enter()		(irq_enter())
 #define nmi_exit()		(preempt_count() -= HARDIRQ_OFFSET)
 
-
-#ifdef CONFIG_PREEMPT
-# include <linux/smp_lock.h>
-# define in_atomic()   ((preempt_count() & ~PREEMPT_ACTIVE) != kernel_locked())
-# define IRQ_EXIT_OFFSET (HARDIRQ_OFFSET-1)
-#else
-# define in_atomic()   (preempt_count() != 0)
-# define IRQ_EXIT_OFFSET HARDIRQ_OFFSET
-#endif
+#define irq_enter()		(preempt_count() += HARDIRQ_OFFSET)
 #define irq_exit()							\
 do {									\
 		preempt_count() -= IRQ_EXIT_OFFSET;			\
@@ -92,11 +57,5 @@
 			do_softirq();					\
 		preempt_enable_no_resched();				\
 } while (0)
-
-#ifndef CONFIG_SMP
-# define synchronize_irq(irq)	barrier()
-#else
-  extern void synchronize_irq(unsigned int irq);
-#endif /* CONFIG_SMP */
 
 #endif /* __ASM_HARDIRQ_H */
diff -Nru a/include/asm-x86_64/hw_irq.h b/include/asm-x86_64/hw_irq.h
--- a/include/asm-x86_64/hw_irq.h	2004-10-18 14:57:04 -07:00
+++ b/include/asm-x86_64/hw_irq.h	2004-10-18 14:57:04 -07:00
@@ -101,6 +101,7 @@
 extern void print_IO_APIC(void);
 extern int IO_APIC_get_PCI_irq_vector(int bus, int slot, int fn);
 extern void send_IPI(int dest, int vector);
+extern void setup_ioapic_dest(void);
 
 extern unsigned long io_apic_irqs;
 
@@ -128,40 +129,6 @@
 "IRQ" #nr "_interrupt:\n\t" \
 	"push $" #nr "-256 ; " \
 	"jmp common_interrupt");
-
-static inline void x86_do_profile (struct pt_regs *regs) 
-{
-	unsigned long rip;
-	extern unsigned long prof_cpu_mask;
-	extern char _stext[];
- 
-	profile_hook(regs);
-
-	if (user_mode(regs))
-		return;
-	if (!prof_buffer)
-		return;
-
-	rip = regs->rip;
-
-	/*
-	 * Only measure the CPUs specified by /proc/irq/prof_cpu_mask.
-	 * (default is all CPUs.)
-	 */
-	if (!((1<<smp_processor_id()) & prof_cpu_mask))
-		return;
-
-	rip -= (unsigned long) &_stext;
-	rip >>= 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 (rip > prof_len-1)
-		rip = prof_len-1;
-	atomic_inc((atomic_t *)&prof_buffer[rip]);
-}
 
 #if defined(CONFIG_X86_IO_APIC) && defined(CONFIG_SMP)
 static inline void hw_resend_irq(struct hw_interrupt_type *h, unsigned int i) {
diff -Nru a/include/asm-x86_64/i387.h b/include/asm-x86_64/i387.h
--- a/include/asm-x86_64/i387.h	2004-10-18 14:56:32 -07:00
+++ b/include/asm-x86_64/i387.h	2004-10-18 14:56:32 -07:00
@@ -39,16 +39,25 @@
  * FPU lazy state save handling...
  */
 
-#define kernel_fpu_end() stts()
-
 #define unlazy_fpu(tsk) do { \
 	if ((tsk)->thread_info->status & TS_USEDFPU) \
 		save_init_fpu(tsk); \
 } while (0)
 
+/* Ignore delayed exceptions from user space */
+static inline void tolerant_fwait(void)
+{
+	asm volatile("1: fwait\n"
+		     "2:\n"
+		     "   .section __ex_table,\"a\"\n"
+		     "	.align 8\n"
+		     "	.quad 1b,2b\n"
+		     "	.previous\n");
+}
+
 #define clear_fpu(tsk) do { \
 	if ((tsk)->thread_info->status & TS_USEDFPU) {		\
-		asm volatile("fnclex ; fwait");			\
+		tolerant_fwait();				\
 		(tsk)->thread_info->status &= ~TS_USEDFPU;	\
 		stts();						\
 	}							\
@@ -116,6 +125,7 @@
 static inline void kernel_fpu_begin(void)
 {
 	struct thread_info *me = current_thread_info();
+	preempt_disable();
 	if (me->status & TS_USEDFPU) { 
 		asm volatile("rex64 ; fxsave %0 ; fnclex"
 			      : "=m" (me->task->thread.i387.fxsave));
@@ -125,9 +135,15 @@
 	clts();
 }
 
+static inline void kernel_fpu_end(void)
+{
+	stts();
+	preempt_enable();
+}
+
 static inline void save_init_fpu( struct task_struct *tsk )
 {
-	asm volatile( "fxsave %0 ; fnclex"
+	asm volatile( "rex64 ; fxsave %0 ; fnclex"
 		      : "=m" (tsk->thread.i387.fxsave));
 	tsk->thread_info->status &= ~TS_USEDFPU;
 	stts();
diff -Nru a/include/asm-x86_64/ia32.h b/include/asm-x86_64/ia32.h
--- a/include/asm-x86_64/ia32.h	2004-10-18 14:57:03 -07:00
+++ b/include/asm-x86_64/ia32.h	2004-10-18 14:57:03 -07:00
@@ -78,12 +78,6 @@
 	unsigned long long	st_ino;
 } __attribute__((packed));
 
-
-typedef union sigval32 {
-	int sival_int;
-	unsigned int sival_ptr;
-} sigval_t32;
-
 typedef struct siginfo32 {
 	int si_signo;
 	int si_errno;
@@ -102,7 +96,7 @@
 		struct {
 			int _tid;		/* timer id */
 			int _overrun;		/* overrun count */
-			sigval_t32 _sigval;	/* same as below */
+			compat_sigval_t _sigval;	/* same as below */
 			int _sys_private;	/* not to be passed to user */
 			int _overrun_incr;	/* amount to add to overrun */
 		} _timer;
@@ -111,7 +105,7 @@
 		struct {
 			unsigned int _pid;	/* sender's pid */
 			unsigned int _uid;	/* sender's uid */
-			sigval_t32 _sigval;
+			compat_sigval_t _sigval;
 		} _rt;
 
 		/* SIGCHLD */
diff -Nru a/include/asm-x86_64/ia32_unistd.h b/include/asm-x86_64/ia32_unistd.h
--- a/include/asm-x86_64/ia32_unistd.h	2004-10-18 14:56:33 -07:00
+++ b/include/asm-x86_64/ia32_unistd.h	2004-10-18 14:56:33 -07:00
@@ -289,7 +289,8 @@
 #define __NR_ia32_mq_notify		(__NR_ia32_mq_open+4)
 #define __NR_ia32_mq_getsetattr	(__NR_ia32_mq_open+5)
 #define __NR_ia32_kexec		283
+#define __NR_ia32_waitid		284
 
-#define IA32_NR_syscalls 287	/* must be > than biggest syscall! */
+#define IA32_NR_syscalls 285	/* must be > than biggest syscall! */
 
 #endif /* _ASM_X86_64_IA32_UNISTD_H_ */
diff -Nru a/include/asm-x86_64/io.h b/include/asm-x86_64/io.h
--- a/include/asm-x86_64/io.h	2004-10-18 14:56:29 -07:00
+++ b/include/asm-x86_64/io.h	2004-10-18 14:56:29 -07:00
@@ -135,9 +135,9 @@
 #define page_to_phys(page)	((page - mem_map) << PAGE_SHIFT)
 #endif
 
-extern void * __ioremap(unsigned long offset, unsigned long size, unsigned long flags);
+extern void __iomem *__ioremap(unsigned long offset, unsigned long size, unsigned long flags);
 
-extern inline void * ioremap (unsigned long offset, unsigned long size)
+extern inline void __iomem * ioremap (unsigned long offset, unsigned long size)
 {
 	return __ioremap(offset, size, 0);
 }
@@ -147,8 +147,8 @@
  * it's useful if some control registers are in such an area and write combining
  * or read caching is not desirable:
  */
-extern void * ioremap_nocache (unsigned long offset, unsigned long size);
-extern void iounmap(void *addr);
+extern void __iomem * ioremap_nocache (unsigned long offset, unsigned long size);
+extern void iounmap(void __iomem *addr);
 
 /*
  * ISA I/O bus memory addresses are 1:1 with the physical address.
@@ -173,10 +173,10 @@
  * memory location directly.
  */
 
-#define readb(addr) (*(volatile unsigned char *) (addr))
-#define readw(addr) (*(volatile unsigned short *) (addr))
-#define readl(addr) (*(volatile unsigned int *) (addr))
-#define readq(addr) (*(volatile unsigned long *) (addr))
+#define readb(addr) (*(__force volatile __u8 *) (__u8 __iomem *)(addr))
+#define readw(addr) (*(__force volatile __u16 *) (__u16 __iomem *)(addr))
+#define readl(addr) (*(__force volatile __u32 *) (__u32 __iomem *)(addr))
+#define readq(addr) (*(__force volatile __u64 *) (__u64 __iomem *)(addr))
 #define readb_relaxed(a) readb(a)
 #define readw_relaxed(a) readw(a)
 #define readl_relaxed(a) readl(a)
@@ -186,10 +186,30 @@
 #define __raw_readl readl
 #define __raw_readq readq
 
-#define writeb(b,addr) (*(volatile unsigned char *) (addr) = (b))
-#define writew(b,addr) (*(volatile unsigned short *) (addr) = (b))
-#define writel(b,addr) (*(volatile unsigned int *) (addr) = (b))
-#define writeq(b,addr) (*(volatile unsigned long *) (addr) = (b))
+#ifdef CONFIG_UNORDERED_IO
+static inline void __writel(__u32 val, void __iomem *addr)
+{
+	volatile __u32 __iomem *target = addr;
+	asm volatile("movnti %1,%0"
+		     : "=m" (*target)
+		     : "r" (val) : "memory");
+}
+
+static inline void __writeq(__u64 val, void __iomem *addr)
+{
+	volatile __u64 *target = addr;
+	asm volatile("movnti %1,%0"
+		     : "=m" (*target)
+		     : "r" (val) : "memory");
+}
+#define writeq(val,addr) __writeq((val),(void __iomem *)(addr))
+#define writel(val,addr) __writel((val),(void __iomem *)(addr))
+#else
+#define writel(b,addr) (*(__force volatile __u32 *)(__u32 __iomem *)(addr) = (b))
+#define writeq(b,addr) (*(__force volatile __u64 *)(__u64 __iomem *)(addr) = (b))
+#endif
+#define writeb(b,addr) (*(__force volatile __u8 *)(__u8 __iomem *)(addr) = (b))
+#define writew(b,addr) (*(__force volatile __u16 *)(__u16 __iomem *)(addr) = (b))
 #define __raw_writeb writeb
 #define __raw_writew writew
 #define __raw_writel writel
@@ -199,10 +219,10 @@
 void *__memcpy_toio(unsigned long,const void*,unsigned);
 
 #define memcpy_fromio(to,from,len) \
-  __memcpy_fromio((to),(unsigned long)(from),(len))
+  __memcpy_fromio((to),(unsigned long)(void __iomem *)(from),(len))
 #define memcpy_toio(to,from,len) \
-  __memcpy_toio((unsigned long)(to),(from),(len))
-#define memset_io(a,b,c)	memset((void *)(a),(b),(c))
+  __memcpy_toio((unsigned long)(void __iomem *)(to),(from),(len))
+#define memset_io(a,b,c)	memset((__force void *)(void __iomem *)(a),(b),(c))
 
 /*
  * ISA space is 'always mapped' on a typical x86 system, no need to
@@ -212,7 +232,7 @@
  * used as the IO-area pointer (it can be iounmapped as well, so the
  * analogy with PCI is quite large):
  */
-#define __ISA_IO_base ((char *)(PAGE_OFFSET))
+#define __ISA_IO_base ((char __iomem *)(PAGE_OFFSET))
 
 #define isa_readb(a) readb(__ISA_IO_base + (a))
 #define isa_readw(a) readw(__ISA_IO_base + (a))
@@ -299,11 +319,8 @@
 
 #define flush_write_buffers() 
 
-/* Disable vmerge for now. Need to fix the block layer code
-   to check for non iommu addresses first.
-   When the IOMMU is force it is safe to enable. */
-extern int iommu_merge;
-#define BIO_VMERGE_BOUNDARY (iommu_merge ? 4096 : 0)
+extern int iommu_bio_merge;
+#define BIO_VMERGE_BOUNDARY iommu_bio_merge
 
 #endif /* __KERNEL__ */
 
diff -Nru a/include/asm-x86_64/mpspec.h b/include/asm-x86_64/mpspec.h
--- a/include/asm-x86_64/mpspec.h	2004-10-18 14:56:29 -07:00
+++ b/include/asm-x86_64/mpspec.h	2004-10-18 14:56:29 -07:00
@@ -156,8 +156,8 @@
  *	7	2 CPU MCA+PCI
  */
 
+#define MAX_MP_BUSSES 270
 #define MAX_IRQ_SOURCES 256
-#define MAX_MP_BUSSES 32
 enum mp_bustype {
 	MP_BUS_ISA = 1,
 	MP_BUS_EISA,
@@ -166,7 +166,6 @@
 };
 extern unsigned char mp_bus_id_to_type [MAX_MP_BUSSES];
 extern int mp_bus_id_to_pci_bus [MAX_MP_BUSSES];
-extern cpumask_t pci_bus_to_cpumask [256];
 
 extern unsigned int boot_cpu_physical_apicid;
 extern int smp_found_config;
diff -Nru a/include/asm-x86_64/msi.h b/include/asm-x86_64/msi.h
--- a/include/asm-x86_64/msi.h	2004-10-18 14:56:50 -07:00
+++ b/include/asm-x86_64/msi.h	2004-10-18 14:56:50 -07:00
@@ -7,10 +7,11 @@
 #define ASM_MSI_H
 
 #include <asm/desc.h>
+#include <asm/smp.h>
 
 #define LAST_DEVICE_VECTOR		232
 #define MSI_DEST_MODE			MSI_LOGICAL_MODE
 #define MSI_TARGET_CPU_SHIFT		12
-#define MSI_TARGET_CPU			TARGET_CPUS
+#define MSI_TARGET_CPU			logical_smp_processor_id()
 
 #endif /* ASM_MSI_H */
diff -Nru a/include/asm-x86_64/mtrr.h b/include/asm-x86_64/mtrr.h
--- a/include/asm-x86_64/mtrr.h	2004-10-18 14:56:17 -07:00
+++ b/include/asm-x86_64/mtrr.h	2004-10-18 14:56:17 -07:00
@@ -71,8 +71,6 @@
 
 #ifdef __KERNEL__
 
-extern char *mtrr_strings[MTRR_NUM_TYPES];
-
 /*  The following functions are for use by other drivers  */
 # ifdef CONFIG_MTRR
 extern int mtrr_add (unsigned long base, unsigned long size,
diff -Nru a/include/asm-x86_64/pci.h b/include/asm-x86_64/pci.h
--- a/include/asm-x86_64/pci.h	2004-10-18 14:56:29 -07:00
+++ b/include/asm-x86_64/pci.h	2004-10-18 14:56:29 -07:00
@@ -44,81 +44,25 @@
 #include <asm/io.h>
 #include <asm/page.h>
 
-struct pci_dev;
-
 extern int iommu_setup(char *opt);
 
-extern dma_addr_t bad_dma_address;
-#define pci_dma_mapping_error(x) ((x) == bad_dma_address)
-
-/* Allocate and map kernel buffer using consistent mode DMA for a device.
- * hwdev should be valid struct pci_dev pointer for PCI devices,
- * NULL for PCI-like buses (ISA, EISA).
- * Returns non-NULL cpu-view pointer to the buffer if successful and
- * sets *dma_addrp to the pci side dma address as well, else *dma_addrp
- * is undefined.
- */
-extern void *pci_alloc_consistent(struct pci_dev *hwdev, size_t size,
-				  dma_addr_t *dma_handle);
-
-/* Free and unmap a consistent DMA buffer.
- * cpu_addr is what was returned from pci_alloc_consistent,
- * size must be the same as what as passed into pci_alloc_consistent,
- * and likewise dma_addr must be the same as what *dma_addrp was set to.
- *
- * References to the memory and mappings associated with cpu_addr/dma_addr
- * past this call are illegal.
- */
-extern void pci_free_consistent(struct pci_dev *hwdev, size_t size,
-				void *vaddr, dma_addr_t dma_handle);
-
-#ifdef CONFIG_SWIOTLB
-extern int swiotlb; 
-extern dma_addr_t swiotlb_map_single (struct device *hwdev, void *ptr, size_t size, 
-				      int dir);
-extern void swiotlb_unmap_single (struct device *hwdev, dma_addr_t dev_addr,
-				  size_t size, int dir);
-extern void swiotlb_sync_single_for_cpu (struct device *hwdev,
-					 dma_addr_t dev_addr,
-					 size_t size, int dir);
-extern void swiotlb_sync_single_for_device (struct device *hwdev,
-					    dma_addr_t dev_addr,
-					    size_t size, int dir);
-extern void swiotlb_sync_sg_for_cpu (struct device *hwdev,
-				     struct scatterlist *sg, int nelems,
-				     int dir);
-extern void swiotlb_sync_sg_for_device (struct device *hwdev,
-					struct scatterlist *sg, int nelems,
-					int dir);
-extern int swiotlb_map_sg(struct device *hwdev, struct scatterlist *sg,
-		      int nents, int direction);
-extern void swiotlb_unmap_sg(struct device *hwdev, struct scatterlist *sg,
-			 int nents, int direction);
-
-#endif
-
 #ifdef CONFIG_GART_IOMMU
-
-/* Map a single buffer of the indicated size for DMA in streaming mode.
- * The 32-bit bus address to use is returned.
+/* The PCI address space does equal the physical memory
+ * address space.  The networking and block device layers use
+ * this boolean for bounce buffer decisions
  *
- * Once the device is given the dma address, the device owns this memory
- * until either pci_unmap_single or pci_dma_sync_single_for_cpu is performed.
+ * On AMD64 it mostly equals, but we set it to zero to tell some subsystems
+ * that an IOMMU is available.
  */
-extern dma_addr_t pci_map_single(struct pci_dev *hwdev, void *ptr, size_t size, 
-				 int direction);
-
-
-void pci_unmap_single(struct pci_dev *hwdev, dma_addr_t addr,
-				   size_t size, int direction);
+#define PCI_DMA_BUS_IS_PHYS	(no_iommu ? 1 : 0)
 
 /*
- * pci_{map,unmap}_single_page maps a kernel page to a dma_addr_t. identical
- * to pci_map_single, but takes a struct page instead of a virtual address
+ * x86-64 always supports DAC, but sometimes it is useful to force
+ * devices through the IOMMU to get automatic sg list merging.
+ * Optional right now.
  */
-
-#define pci_map_page(dev,page,offset,size,dir) \
-	pci_map_single((dev), page_address(page)+(offset), (size), (dir)) 
+extern int iommu_sac_force;
+#define pci_dac_dma_supported(pci_dev, mask)	(!iommu_sac_force)
 
 #define DECLARE_PCI_UNMAP_ADDR(ADDR_NAME)	\
 	dma_addr_t ADDR_NAME;
@@ -133,113 +77,12 @@
 #define pci_unmap_len_set(PTR, LEN_NAME, VAL)		\
 	(((PTR)->LEN_NAME) = (VAL))
 
-static inline void pci_dma_sync_single_for_cpu(struct pci_dev *hwdev,
-					       dma_addr_t dma_handle,
-					       size_t size, int direction)
-{
-	BUG_ON(direction == PCI_DMA_NONE); 
-
-#ifdef CONFIG_SWIOTLB
-	if (swiotlb)
-		return swiotlb_sync_single_for_cpu(&hwdev->dev,dma_handle,size,direction);
-#endif
-
-	flush_write_buffers();
-} 
-
-static inline void pci_dma_sync_single_for_device(struct pci_dev *hwdev,
-						  dma_addr_t dma_handle,
-						  size_t size, int direction)
-{
-	BUG_ON(direction == PCI_DMA_NONE);
-
-#ifdef CONFIG_SWIOTLB
-	if (swiotlb)
-		return swiotlb_sync_single_for_device(&hwdev->dev,dma_handle,size,direction);
-#endif
-
-	flush_write_buffers();
-}
-
-static inline void pci_dma_sync_sg_for_cpu(struct pci_dev *hwdev,
-					   struct scatterlist *sg,
-					   int nelems, int direction)
-{
-	BUG_ON(direction == PCI_DMA_NONE);
-
-#ifdef CONFIG_SWIOTLB
-	if (swiotlb)
-		return swiotlb_sync_sg_for_cpu(&hwdev->dev,sg,nelems,direction);
-#endif
-	flush_write_buffers();
-}
-
-static inline void pci_dma_sync_sg_for_device(struct pci_dev *hwdev,
-					      struct scatterlist *sg,
-					      int nelems, int direction)
-{ 
-	BUG_ON(direction == PCI_DMA_NONE); 
-
-#ifdef CONFIG_SWIOTLB
-	if (swiotlb)
-		return swiotlb_sync_sg_for_device(&hwdev->dev,sg,nelems,direction);
-#endif
-	flush_write_buffers();
-} 
-
-/* The PCI address space does equal the physical memory
- * address space.  The networking and block device layers use
- * this boolean for bounce buffer decisions
- *
- * On AMD64 it mostly equals, but we set it to zero to tell some subsystems
- * that an IOMMU is available.
- */
-#define PCI_DMA_BUS_IS_PHYS	(no_iommu ? 1 : 0) 
-
-/* We lie slightly when the IOMMU is forced to get the device to 
-   use SAC instead of DAC. */
-#define pci_dac_dma_supported(pci_dev, mask)	(force_iommu ? 0 : 1)
-
 #else
-static inline dma_addr_t pci_map_single(struct pci_dev *hwdev, void *ptr,
-					size_t size, int direction)
-{
-	dma_addr_t addr; 
+/* No IOMMU */
 
-	if (direction == PCI_DMA_NONE)
-		out_of_line_bug();	
-	addr = virt_to_bus(ptr); 
-
-	/* 
-	 * This is gross, but what should I do.
-	 * Unfortunately drivers do not test the return value of this.
- */
-	if ((addr+size) & ~hwdev->dma_mask) 
-		out_of_line_bug(); 
-	return addr;
-}
-
-static inline void pci_unmap_single(struct pci_dev *hwdev, dma_addr_t dma_addr,
-				    size_t size, int direction)
-{
-	if (direction == PCI_DMA_NONE)
-		out_of_line_bug();
-	/* Nothing to do */
-}
-
-static inline dma_addr_t pci_map_page(struct pci_dev *hwdev, struct page *page,
-				      unsigned long offset, size_t size, int direction)
-{
-	dma_addr_t addr;
-	if (direction == PCI_DMA_NONE)
-		out_of_line_bug();	
- 	addr = page_to_pfn(page) * PAGE_SIZE + offset;
-	if ((addr+size) & ~hwdev->dma_mask) 
-		out_of_line_bug();
-	return addr;
-}
+#define PCI_DMA_BUS_IS_PHYS	1
+#define pci_dac_dma_supported(pci_dev, mask)    1
 
-/* pci_unmap_{page,single} is a nop so... */
 #define DECLARE_PCI_UNMAP_ADDR(ADDR_NAME)
 #define DECLARE_PCI_UNMAP_LEN(LEN_NAME)
 #define pci_unmap_addr(PTR, ADDR_NAME)		(0)
@@ -247,74 +90,9 @@
 #define pci_unmap_len(PTR, LEN_NAME)		(0)
 #define pci_unmap_len_set(PTR, LEN_NAME, VAL)	do { } while (0)
 
-/* Make physical memory consistent for a single
- * streaming mode DMA translation after a transfer.
- *
- * If you perform a pci_map_single() but wish to interrogate the
- * buffer using the cpu, yet do not wish to teardown the PCI dma
- * mapping, you must call this function before doing so.  At the
- * next point you give the PCI dma address back to the card, you
- * must first perform a pci_dma_sync_for_device, and then the
- * device again owns the buffer.
- */
-static inline void pci_dma_sync_single_for_cpu(struct pci_dev *hwdev,
-					       dma_addr_t dma_handle,
-					       size_t size, int direction)
-{
-	if (direction == PCI_DMA_NONE)
-		out_of_line_bug();
-}
-
-static inline void pci_dma_sync_single_for_device(struct pci_dev *hwdev,
-						  dma_addr_t dma_handle,
-						  size_t size, int direction)
-{
-	if (direction == PCI_DMA_NONE)
-		out_of_line_bug();
-	flush_write_buffers();
-}
-
-/* Make physical memory consistent for a set of streaming
- * mode DMA translations after a transfer.
- *
- * The same as pci_dma_sync_single_* but for a scatter-gather list,
- * same rules and usage.
- */
-static inline void pci_dma_sync_sg_for_cpu(struct pci_dev *hwdev,
-					   struct scatterlist *sg,
-					   int nelems, int direction)
-{
-	if (direction == PCI_DMA_NONE)
-		out_of_line_bug();
-}
-
-static inline void pci_dma_sync_sg_for_device(struct pci_dev *hwdev,
-					      struct scatterlist *sg,
-					      int nelems, int direction)
-{
-	if (direction == PCI_DMA_NONE)
-		out_of_line_bug();
-	flush_write_buffers();
-}
-
-#define PCI_DMA_BUS_IS_PHYS	1
-
-#define pci_dac_dma_supported(pci_dev, mask)	1
 #endif
 
-extern int pci_map_sg(struct pci_dev *hwdev, struct scatterlist *sg,
-		      int nents, int direction);
-extern void pci_unmap_sg(struct pci_dev *hwdev, struct scatterlist *sg,
-			 int nents, int direction);
-
-#define pci_unmap_page pci_unmap_single
-
-/* Return whether the given PCI device DMA address mask can
- * be supported properly.  For example, if your device can
- * only drive the low 24-bits during PCI bus mastering, then
- * you would pass 0x00ffffff as the mask to this function.
- */
-extern int pci_dma_supported(struct pci_dev *hwdev, u64 mask);
+#include <asm-generic/pci-dma-compat.h>
 
 static inline dma64_addr_t
 pci_dac_page_to_dma(struct pci_dev *pdev, struct page *page, unsigned long offset, int direction)
@@ -359,7 +137,6 @@
 /* generic pci stuff */
 #ifdef CONFIG_PCI
 #include <asm-generic/pci.h>
-#include <linux/dma-mapping.h>
 #endif
 
 #endif /* __x8664_PCI_H */
diff -Nru a/include/asm-x86_64/processor.h b/include/asm-x86_64/processor.h
--- a/include/asm-x86_64/processor.h	2004-10-18 14:57:04 -07:00
+++ b/include/asm-x86_64/processor.h	2004-10-18 14:57:04 -07:00
@@ -18,6 +18,7 @@
 #include <asm/current.h>
 #include <asm/system.h>
 #include <asm/mmsegment.h>
+#include <asm/percpu.h>
 #include <linux/personality.h>
 
 #define TF_MASK		0x00000100
@@ -60,6 +61,8 @@
 	int	x86_cache_alignment;
 	int	x86_tlbsize;	/* number of 4K pages in DTLB/ITLB combined(in pages)*/
         __u8    x86_virt_bits, x86_phys_bits;
+	__u8	x86_num_cores;
+	__u8	x86_apicid;
         __u32   x86_power; 	
 	unsigned long loops_per_jiffy;
 } ____cacheline_aligned;
@@ -75,14 +78,11 @@
 #define X86_VENDOR_NUM 8
 #define X86_VENDOR_UNKNOWN 0xff
 
-extern struct cpuinfo_x86 boot_cpu_data;
-extern struct tss_struct init_tss[NR_CPUS];
-
 #ifdef CONFIG_SMP
 extern struct cpuinfo_x86 cpu_data[];
 #define current_cpu_data cpu_data[smp_processor_id()]
 #else
-#define cpu_data &boot_cpu_data
+#define cpu_data (&boot_cpu_data)
 #define current_cpu_data boot_cpu_data
 #endif
 
@@ -227,6 +227,9 @@
 	unsigned long io_bitmap[IO_BITMAP_LONGS + 1];
 } __attribute__((packed)) ____cacheline_aligned;
 
+extern struct cpuinfo_x86 boot_cpu_data;
+DECLARE_PER_CPU(struct tss_struct,init_tss);
+
 #define ARCH_MIN_TASKALIGN	16
 
 struct thread_struct {
@@ -251,6 +254,7 @@
    switch faster for a limited number of ioperm using tasks. -AK */
 	int		ioperm;
 	unsigned long	*io_bitmap_ptr;
+	unsigned io_bitmap_max;
 /* cached TLS descriptors. */
 	u64 tls_array[GDT_ENTRY_TLS_ENTRIES];
 } __attribute__((aligned(16)));
@@ -455,10 +459,5 @@
 })
 
 #define cache_line_size() (boot_cpu_data.x86_cache_alignment)
-
-#ifdef CONFIG_SCHED_SMT
-#define ARCH_HAS_SCHED_DOMAIN
-#define ARCH_HAS_SCHED_WAKE_IDLE
-#endif
 
 #endif /* __ASM_X86_64_PROCESSOR_H */
diff -Nru a/include/asm-x86_64/proto.h b/include/asm-x86_64/proto.h
--- a/include/asm-x86_64/proto.h	2004-10-18 14:57:03 -07:00
+++ b/include/asm-x86_64/proto.h	2004-10-18 14:57:03 -07:00
@@ -70,6 +70,7 @@
 extern void show_regs(struct pt_regs * regs);
 
 extern int map_syscall32(struct mm_struct *mm, unsigned long address);
+extern int __map_syscall32(struct mm_struct *mm, unsigned long address);
 extern char *syscall32_page;
 extern void syscall32_cpu_init(void);
 
@@ -82,7 +83,6 @@
 
 extern void select_idle_routine(const struct cpuinfo_x86 *c);
 extern void swiotlb_init(void);
-extern int swiotlb;
 
 extern unsigned long max_mapnr;
 extern unsigned long end_pfn; 
@@ -103,6 +103,8 @@
 extern int iommu_aperture;
 extern int iommu_aperture_disabled;
 extern int iommu_aperture_allowed;
+extern int fix_aperture;
+extern int force_iommu;
 
 extern void smp_local_timer_interrupt(struct pt_regs * regs);
 
diff -Nru a/include/asm-x86_64/ptrace.h b/include/asm-x86_64/ptrace.h
--- a/include/asm-x86_64/ptrace.h	2004-10-18 14:56:27 -07:00
+++ b/include/asm-x86_64/ptrace.h	2004-10-18 14:56:27 -07:00
@@ -83,6 +83,7 @@
 #if defined(__KERNEL__) && !defined(__ASSEMBLY__) 
 #define user_mode(regs) (!!((regs)->cs & 3))
 #define instruction_pointer(regs) ((regs)->rip)
+extern unsigned long profile_pc(struct pt_regs *regs);
 void signal_fault(struct pt_regs *regs, void __user *frame, char *where);
 
 enum {
diff -Nru a/include/asm-x86_64/resource.h b/include/asm-x86_64/resource.h
--- a/include/asm-x86_64/resource.h	2004-10-18 14:56:48 -07:00
+++ b/include/asm-x86_64/resource.h	2004-10-18 14:56:48 -07:00
@@ -39,7 +39,7 @@
 	{ RLIM_INFINITY, RLIM_INFINITY },		\
 	{             0,             0 },		\
 	{      INR_OPEN,     INR_OPEN  },		\
-	{ RLIM_INFINITY, RLIM_INFINITY },		\
+	{   MLOCK_LIMIT,   MLOCK_LIMIT },		\
 	{ RLIM_INFINITY, RLIM_INFINITY },		\
 	{ RLIM_INFINITY, RLIM_INFINITY },		\
 	{ MAX_SIGPENDING, MAX_SIGPENDING },		\
diff -Nru a/include/asm-x86_64/semaphore.h b/include/asm-x86_64/semaphore.h
--- a/include/asm-x86_64/semaphore.h	2004-10-18 14:55:53 -07:00
+++ b/include/asm-x86_64/semaphore.h	2004-10-18 14:55:53 -07:00
@@ -47,21 +47,14 @@
 	atomic_t count;
 	int sleepers;
 	wait_queue_head_t wait;
-#ifdef WAITQUEUE_DEBUG
-	long __magic;
-#endif
 };
 
-#ifdef WAITQUEUE_DEBUG
-# define __SEM_DEBUG_INIT(name) \
-		, (int)&(name).__magic
-#else
-# define __SEM_DEBUG_INIT(name)
-#endif
-
-#define __SEMAPHORE_INITIALIZER(name,count) \
-{ ATOMIC_INIT(count), 0, __WAIT_QUEUE_HEAD_INITIALIZER((name).wait) \
-	__SEM_DEBUG_INIT(name) }
+#define __SEMAPHORE_INITIALIZER(name, n)				\
+{									\
+	.count		= ATOMIC_INIT(n),				\
+	.sleepers	= 0,						\
+	.wait		= __WAIT_QUEUE_HEAD_INITIALIZER((name).wait)	\
+}
 
 #define __MUTEX_INITIALIZER(name) \
 	__SEMAPHORE_INITIALIZER(name,1)
@@ -83,9 +76,6 @@
 	atomic_set(&sem->count, val);
 	sem->sleepers = 0;
 	init_waitqueue_head(&sem->wait);
-#ifdef WAITQUEUE_DEBUG
-	sem->__magic = (int)&sem->__magic;
-#endif
 }
 
 static inline void init_MUTEX (struct semaphore *sem)
@@ -115,9 +105,6 @@
  */
 static inline void down(struct semaphore * sem)
 {
-#ifdef WAITQUEUE_DEBUG
-	CHECK_MAGIC(sem->__magic);
-#endif
 	might_sleep();
 
 	__asm__ __volatile__(
@@ -142,9 +129,6 @@
 {
 	int result;
 
-#ifdef WAITQUEUE_DEBUG
-	CHECK_MAGIC(sem->__magic);
-#endif
 	might_sleep();
 
 	__asm__ __volatile__(
@@ -171,10 +155,6 @@
 {
 	int result;
 
-#ifdef WAITQUEUE_DEBUG
-	CHECK_MAGIC(sem->__magic);
-#endif
-
 	__asm__ __volatile__(
 		"# atomic interruptible down operation\n\t"
 		LOCK "decl %1\n\t"     /* --sem->count */
@@ -199,9 +179,6 @@
  */
 static inline void up(struct semaphore * sem)
 {
-#ifdef WAITQUEUE_DEBUG
-	CHECK_MAGIC(sem->__magic);
-#endif
 	__asm__ __volatile__(
 		"# atomic up operation\n\t"
 		LOCK "incl %0\n\t"     /* ++sem->count */
diff -Nru a/include/asm-x86_64/smp.h b/include/asm-x86_64/smp.h
--- a/include/asm-x86_64/smp.h	2004-10-18 14:55:53 -07:00
+++ b/include/asm-x86_64/smp.h	2004-10-18 14:55:53 -07:00
@@ -110,9 +110,13 @@
 
 #endif
 #define INT_DELIVERY_MODE 1     /* logical delivery */
-#define TARGET_CPUS 1
 
 #ifndef ASSEMBLY
+#ifdef CONFIG_SMP
+#define TARGET_CPUS cpu_online_map
+#else
+#define TARGET_CPUS cpumask_of_cpu(0)
+#endif
 static inline unsigned int cpu_mask_to_apicid(cpumask_t cpumask)
 {
 	return cpus_addr(cpumask)[0];
@@ -131,6 +135,14 @@
 	__asm__("andq %%rsp,%0; ":"=r" (ti) : "0" (CURRENT_MASK));	\
 	ti->cpu;						\
 })
+#endif
+
+#ifndef __ASSEMBLY__
+static __inline int logical_smp_processor_id(void)
+{
+	/* we don't want to mark this access volatile - bad code generation */
+	return GET_APIC_LOGICAL_ID(*(unsigned long *)(APIC_BASE+APIC_LDR));
+}
 #endif
 
 #endif
diff -Nru a/include/asm-x86_64/socket.h b/include/asm-x86_64/socket.h
--- a/include/asm-x86_64/socket.h	2004-10-18 14:55:53 -07:00
+++ b/include/asm-x86_64/socket.h	2004-10-18 14:55:53 -07:00
@@ -47,20 +47,4 @@
 
 #define SO_PEERSEC             31
 
-/* Nasty libc5 fixup - bletch */
-#if defined(__KERNEL__) || !defined(__GLIBC__) || (__GLIBC__ < 2)
-/* Socket types. */
-#define SOCK_STREAM	1		/* stream (connection) socket	*/
-#define SOCK_DGRAM	2		/* datagram (conn.less) socket	*/
-#define SOCK_RAW	3		/* raw socket			*/
-#define SOCK_RDM	4		/* reliably-delivered message	*/
-#define SOCK_SEQPACKET	5		/* sequential packet socket	*/
-#define SOCK_PACKET	10		/* linux specific way of	*/
-					/* getting packets at the dev	*/
-					/* level.  For writing rarp and	*/
-					/* other similar things on the	*/
-					/* user level.			*/
-#define	SOCK_MAX	(SOCK_PACKET+1)
-#endif
-
 #endif /* _ASM_SOCKET_H */
diff -Nru a/include/asm-x86_64/spinlock.h b/include/asm-x86_64/spinlock.h
--- a/include/asm-x86_64/spinlock.h	2004-10-18 14:57:04 -07:00
+++ b/include/asm-x86_64/spinlock.h	2004-10-18 14:57:04 -07:00
@@ -113,10 +113,8 @@
 static inline void _raw_spin_lock(spinlock_t *lock)
 {
 #ifdef CONFIG_DEBUG_SPINLOCK
-	__label__ here;
-here:
 	if (lock->magic != SPINLOCK_MAGIC) {
-printk("eip: %p\n", &&here);
+		printk("eip: %p\n", __builtin_return_address(0));
 		BUG();
 	}
 #endif
diff -Nru a/include/asm-x86_64/swiotlb.h b/include/asm-x86_64/swiotlb.h
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/include/asm-x86_64/swiotlb.h	2004-10-18 14:57:21 -07:00
@@ -0,0 +1,36 @@
+#ifndef _ASM_SWIOTLB_H
+#define _ASM_SWTIOLB_H 1
+
+#include <linux/config.h>
+
+/* SWIOTLB interface */
+
+extern dma_addr_t swiotlb_map_single(struct device *hwdev, void *ptr, size_t size,
+				      int dir);
+extern void swiotlb_unmap_single(struct device *hwdev, dma_addr_t dev_addr,
+				  size_t size, int dir);
+extern void swiotlb_sync_single_for_cpu(struct device *hwdev,
+					 dma_addr_t dev_addr,
+					 size_t size, int dir);
+extern void swiotlb_sync_single_for_device(struct device *hwdev,
+					    dma_addr_t dev_addr,
+					    size_t size, int dir);
+extern void swiotlb_sync_sg_for_cpu(struct device *hwdev,
+				     struct scatterlist *sg, int nelems,
+				     int dir);
+extern void swiotlb_sync_sg_for_device(struct device *hwdev,
+					struct scatterlist *sg, int nelems,
+					int dir);
+extern int swiotlb_map_sg(struct device *hwdev, struct scatterlist *sg,
+		      int nents, int direction);
+extern void swiotlb_unmap_sg(struct device *hwdev, struct scatterlist *sg,
+			 int nents, int direction);
+extern int swiotlb_dma_mapping_error(dma_addr_t dma_addr);
+
+#ifdef CONFIG_SWIOTLB
+extern int swiotlb;
+#else
+#define swiotlb 0
+#endif
+
+#endif
diff -Nru a/include/asm-x86_64/system.h b/include/asm-x86_64/system.h
--- a/include/asm-x86_64/system.h	2004-10-18 14:56:49 -07:00
+++ b/include/asm-x86_64/system.h	2004-10-18 14:56:49 -07:00
@@ -297,11 +297,11 @@
 #define mb() 	asm volatile("mfence":::"memory")
 #define rmb()	asm volatile("lfence":::"memory")
 
-/* could use SFENCE here, but it would be only needed for unordered SSE
-   store instructions and we always do an explicit sfence with them currently.
-   the ordering of normal stores is serialized enough. Just make it a compile
-   barrier. */
+#ifdef CONFIG_UNORDERED_IO
+#define wmb()	asm volatile("sfence" ::: "memory")
+#else
 #define wmb()	asm volatile("" ::: "memory")
+#endif
 #define read_barrier_depends()	do {} while(0)
 #define set_mb(var, value) do { xchg(&var, value); } while (0)
 #define set_wmb(var, value) do { var = value; wmb(); } while (0)
diff -Nru a/include/asm-x86_64/topology.h b/include/asm-x86_64/topology.h
--- a/include/asm-x86_64/topology.h	2004-10-18 14:56:48 -07:00
+++ b/include/asm-x86_64/topology.h	2004-10-18 14:56:48 -07:00
@@ -14,18 +14,23 @@
 
 extern unsigned char cpu_to_node[];
 extern cpumask_t     node_to_cpumask[];
+extern cpumask_t pci_bus_to_cpumask[];
 
 #define cpu_to_node(cpu)		(cpu_to_node[cpu])
 #define parent_node(node)		(node)
 #define node_to_first_cpu(node) 	(__ffs(node_to_cpumask[node]))
 #define node_to_cpumask(node)		(node_to_cpumask[node])
 
-static inline cpumask_t pcibus_to_cpumask(int bus)
+static inline cpumask_t __pcibus_to_cpumask(int bus)
 {
+	cpumask_t busmask = pci_bus_to_cpumask[bus];
+	cpumask_t online = cpu_online_map;
 	cpumask_t res;
-	cpus_and(res,  pci_bus_to_cpumask[bus], cpu_online_map);
+	cpus_and(res, busmask, online);
 	return res;
 }
+/* broken generic file uses #ifndef later on this */
+#define pcibus_to_cpumask(bus) __pcibus_to_cpumask(bus)
 
 #define NODE_BALANCE_RATE 30	/* CHECKME */ 
 
diff -Nru a/include/asm-x86_64/uaccess.h b/include/asm-x86_64/uaccess.h
--- a/include/asm-x86_64/uaccess.h	2004-10-18 14:57:19 -07:00
+++ b/include/asm-x86_64/uaccess.h	2004-10-18 14:57:19 -07:00
@@ -137,6 +137,9 @@
 #define __put_user(x,ptr) \
   __put_user_nocheck((__typeof__(*(ptr)))(x),(ptr),sizeof(*(ptr)))
 
+#define __get_user_unaligned __get_user
+#define __put_user_unaligned __put_user
+
 #define __put_user_nocheck(x,ptr,size)			\
 ({							\
 	int __pu_err;					\
@@ -350,5 +353,8 @@
 long strlen_user(const char __user *str);
 unsigned long clear_user(void __user *mem, unsigned long len);
 unsigned long __clear_user(void __user *mem, unsigned long len);
+
+#define __copy_to_user_inatomic __copy_to_user
+#define __copy_from_user_inatomic __copy_from_user
 
 #endif /* __X86_64_UACCESS_H */
diff -Nru a/include/asm-x86_64/unistd.h b/include/asm-x86_64/unistd.h
--- a/include/asm-x86_64/unistd.h	2004-10-18 14:56:48 -07:00
+++ b/include/asm-x86_64/unistd.h	2004-10-18 14:56:48 -07:00
@@ -554,8 +554,10 @@
 __SYSCALL(__NR_mq_getsetattr, sys_mq_getsetattr)
 #define __NR_kexec_load 	246
 __SYSCALL(__NR_kexec_load, sys_ni_syscall)
+#define __NR_waitid		247
+__SYSCALL(__NR_waitid, sys_waitid)
 
-#define __NR_syscall_max __NR_kexec_load
+#define __NR_syscall_max __NR_waitid
 #ifndef __NO_STUBS
 
 /* user-visible error numbers are in the range -1 - -4095 */
diff -Nru a/include/linux/acct.h b/include/linux/acct.h
--- a/include/linux/acct.h	2004-10-18 14:56:17 -07:00
+++ b/include/linux/acct.h	2004-10-18 14:56:17 -07:00
@@ -172,17 +172,24 @@
 #endif
 }
 
-static inline u64 jiffies_64_to_AHZ(u64 x)
+static inline u64 nsec_to_AHZ(u64 x)
 {
-#if (TICK_NSEC % (NSEC_PER_SEC / AHZ)) == 0
-#if HZ != AHZ
-	do_div(x, HZ / AHZ);
-#endif
-#else
-	x *= TICK_NSEC;
+#if (NSEC_PER_SEC % AHZ) == 0
 	do_div(x, (NSEC_PER_SEC / AHZ));
+#elif (AHZ % 512) == 0
+	x *= AHZ/512;
+	do_div(x, (NSEC_PER_SEC / 512));
+#else
+	/*
+         * max relative error 5.7e-8 (1.8s per year) for AHZ <= 1024,
+         * overflow after 64.99 years.
+         * exact for AHZ=60, 72, 90, 120, 144, 180, 300, 600, 900, ...
+         */
+	x *= 9;
+	do_div(x, (unsigned long)((9ull * NSEC_PER_SEC + (AHZ/2))
+	                          / AHZ));
 #endif
-       return x;
+	return x;
 }
 
 #endif  /* __KERNEL */
diff -Nru a/include/linux/acpi.h b/include/linux/acpi.h
--- a/include/linux/acpi.h	2004-10-18 14:55:53 -07:00
+++ b/include/linux/acpi.h	2004-10-18 14:55:53 -07:00
@@ -453,14 +453,15 @@
 
 #ifdef CONFIG_ACPI_EC
 
-int ec_read(u8 addr, u8 *val);
-int ec_write(u8 addr, u8 val);
+extern int ec_read(u8 addr, u8 *val);
+extern int ec_write(u8 addr, u8 val);
 
 #endif /*CONFIG_ACPI_EC*/
 
 #ifdef CONFIG_ACPI_INTERPRETER
 
-int acpi_blacklisted(void);
+extern int acpi_blacklisted(void);
+extern void acpi_bios_year(char *s);
 
 #else /*!CONFIG_ACPI_INTERPRETER*/
 
diff -Nru a/include/linux/adfs_fs.h b/include/linux/adfs_fs.h
--- a/include/linux/adfs_fs.h	2004-10-18 14:56:49 -07:00
+++ b/include/linux/adfs_fs.h	2004-10-18 14:56:49 -07:00
@@ -17,20 +17,20 @@
     __u8  bootoption;
     __u8  lowsector;
     __u8  nzones;
-    __u16 zone_spare;
-    __u32 root;
-    __u32 disc_size;
-    __u16 disc_id;
+    __le16 zone_spare;
+    __le32 root;
+    __le32 disc_size;
+    __le16 disc_id;
     __u8  disc_name[10];
-    __u32 disc_type;
-    __u32 disc_size_high;
+    __le32 disc_type;
+    __le32 disc_size_high;
     __u8  log2sharesize:4;
     __u8  unused40:4;
     __u8  big_flag:1;
     __u8  unused41:1;
     __u8  nzones_high;
-    __u32 format_version;
-    __u32 root_size;
+    __le32 format_version;
+    __le32 root_size;
     __u8  unused52[60 - 52];
 };
 
diff -Nru a/include/linux/adfs_fs_i.h b/include/linux/adfs_fs_i.h
--- a/include/linux/adfs_fs_i.h	2004-10-18 14:56:28 -07:00
+++ b/include/linux/adfs_fs_i.h	2004-10-18 14:56:28 -07:00
@@ -17,7 +17,7 @@
 	__u32		execaddr;	/* RISC OS exec address		*/
 	unsigned int	filetype;	/* RISC OS file type		*/
 	unsigned int	attr;		/* RISC OS permissions		*/
-	int		stamped:1;	/* RISC OS file has date/time	*/
+	unsigned int	stamped:1;	/* RISC OS file has date/time	*/
 	struct inode vfs_inode;
 };
 
diff -Nru a/include/linux/adfs_fs_sb.h b/include/linux/adfs_fs_sb.h
--- a/include/linux/adfs_fs_sb.h	2004-10-18 14:56:33 -07:00
+++ b/include/linux/adfs_fs_sb.h	2004-10-18 14:56:33 -07:00
@@ -31,7 +31,7 @@
 	unsigned long	s_size;		/* total size (in blocks) of this fs	 */
 	signed int	s_map2blk;	/* shift left by this for map->sector	 */
 	unsigned int	s_log2sharesize;/* log2 share size			 */
-	unsigned int	s_version;	/* disc format version			 */
+	__le32		s_version;	/* disc format version			 */
 	unsigned int	s_namelen;	/* maximum number of characters in name	 */
 };
 
diff -Nru a/include/linux/affs_fs.h b/include/linux/affs_fs.h
--- a/include/linux/affs_fs.h	2004-10-18 14:55:53 -07:00
+++ b/include/linux/affs_fs.h	2004-10-18 14:55:53 -07:00
@@ -32,7 +32,6 @@
 
 /* bitmap. c */
 
-extern u32	affs_count_free_bits(u32 blocksize, const void *data);
 extern u32	affs_count_free_blocks(struct super_block *s);
 extern void	affs_free_block(struct super_block *sb, u32 block);
 extern u32	affs_alloc_block(struct inode *inode, u32 goal);
@@ -63,7 +62,7 @@
 extern void			 affs_delete_inode(struct inode *inode);
 extern void			 affs_clear_inode(struct inode *inode);
 extern void			 affs_read_inode(struct inode *inode);
-extern void			 affs_write_inode(struct inode *inode, int);
+extern int			 affs_write_inode(struct inode *inode, int);
 extern int			 affs_add_entry(struct inode *dir, struct inode *inode, struct dentry *dentry, s32 type);
 
 /* super.c */
diff -Nru a/include/linux/affs_hardblocks.h b/include/linux/affs_hardblocks.h
--- a/include/linux/affs_hardblocks.h	2004-10-18 14:56:32 -07:00
+++ b/include/linux/affs_hardblocks.h	2004-10-18 14:56:32 -07:00
@@ -5,13 +5,13 @@
 
 struct RigidDiskBlock {
 	u32	rdb_ID;
-	u32	rdb_SummedLongs;
+	__be32	rdb_SummedLongs;
 	s32	rdb_ChkSum;
 	u32	rdb_HostID;
-	u32	rdb_BlockBytes;
+	__be32	rdb_BlockBytes;
 	u32	rdb_Flags;
 	u32	rdb_BadBlockList;
-	u32	rdb_PartitionList;
+	__be32	rdb_PartitionList;
 	u32	rdb_FileSysHeaderList;
 	u32	rdb_DriveInit;
 	u32	rdb_Reserved1[6];
@@ -45,17 +45,17 @@
 #define	IDNAME_RIGIDDISK	0x5244534B	/* "RDSK" */
 
 struct PartitionBlock {
-	u32	pb_ID;
-	u32	pb_SummedLongs;
+	__be32	pb_ID;
+	__be32	pb_SummedLongs;
 	s32	pb_ChkSum;
 	u32	pb_HostID;
-	u32	pb_Next;
+	__be32	pb_Next;
 	u32	pb_Flags;
 	u32	pb_Reserved1[2];
 	u32	pb_DevFlags;
 	u8	pb_DriveName[32];
 	u32	pb_Reserved2[15];
-	u32	pb_Environment[17];
+	__be32	pb_Environment[17];
 	u32	pb_EReserved[15];
 };
 
diff -Nru a/include/linux/aio.h b/include/linux/aio.h
--- a/include/linux/aio.h	2004-10-18 14:55:54 -07:00
+++ b/include/linux/aio.h	2004-10-18 14:55:54 -07:00
@@ -52,7 +52,7 @@
 	struct file		*ki_filp;
 	struct kioctx		*ki_ctx;	/* may be NULL for sync ops */
 	int			(*ki_cancel)(struct kiocb *, struct io_event *);
-	long			(*ki_retry)(struct kiocb *);
+	ssize_t			(*ki_retry)(struct kiocb *);
 	void			(*ki_dtor)(struct kiocb *);
 
 	struct list_head	ki_list;	/* the aio core uses this
@@ -64,6 +64,16 @@
 	} ki_obj;
 	__u64			ki_user_data;	/* user's data for completion */
 	loff_t			ki_pos;
+	/* State that we remember to be able to restart/retry  */
+	unsigned short		ki_opcode;
+	size_t			ki_nbytes; 	/* copy of iocb->aio_nbytes */
+	char 			__user *ki_buf;	/* remaining iocb->aio_buf */
+	size_t			ki_left; 	/* remaining bytes */
+	wait_queue_t		ki_wait;
+	long			ki_retried; 	/* just for testing */
+	long			ki_kicked; 	/* just for testing */
+	long			ki_queued; 	/* just for testing */
+
 	void			*private;
 };
 
@@ -79,6 +89,8 @@
 		(x)->ki_cancel = NULL;			\
 		(x)->ki_dtor = NULL;			\
 		(x)->ki_obj.tsk = tsk;			\
+		(x)->ki_user_data = 0;                  \
+		init_wait((&(x)->ki_wait));             \
 	} while (0)
 
 #define AIO_RING_MAGIC			0xa10a10a1
@@ -160,6 +172,20 @@
 
 #define get_ioctx(kioctx)	do { if (unlikely(atomic_read(&(kioctx)->users) <= 0)) BUG(); atomic_inc(&(kioctx)->users); } while (0)
 #define put_ioctx(kioctx)	do { if (unlikely(atomic_dec_and_test(&(kioctx)->users))) __put_ioctx(kioctx); else if (unlikely(atomic_read(&(kioctx)->users) < 0)) BUG(); } while (0)
+
+#define in_aio() !is_sync_wait(current->io_wait)
+/* may be used for debugging */
+#define warn_if_async()							\
+do {									\
+	if (in_aio()) {							\
+		printk(KERN_ERR "%s(%s:%d) called in async context!\n",	\
+			__FUNCTION__, __FILE__, __LINE__);		\
+		dump_stack();						\
+	}								\
+} while (0)
+
+#define io_wait_to_kiocb(wait) container_of(wait, struct kiocb, ki_wait)
+#define is_retried_kiocb(iocb) ((iocb)->ki_retried > 1)
 
 #include <linux/aio_abi.h>
 
diff -Nru a/include/linux/amigaffs.h b/include/linux/amigaffs.h
--- a/include/linux/amigaffs.h	2004-10-18 14:56:17 -07:00
+++ b/include/linux/amigaffs.h	2004-10-18 14:56:17 -07:00
@@ -80,14 +80,14 @@
 static inline void
 affs_adjust_checksum(struct buffer_head *bh, u32 val)
 {
-	u32 tmp = be32_to_cpu(((u32 *)bh->b_data)[5]);
-	((u32 *)bh->b_data)[5] = cpu_to_be32(tmp - val);
+	u32 tmp = be32_to_cpu(((__be32 *)bh->b_data)[5]);
+	((__be32 *)bh->b_data)[5] = cpu_to_be32(tmp - val);
 }
 static inline void
 affs_adjust_bitmapchecksum(struct buffer_head *bh, u32 val)
 {
-	u32 tmp = be32_to_cpu(((u32 *)bh->b_data)[0]);
-	((u32 *)bh->b_data)[0] = cpu_to_be32(tmp - val);
+	u32 tmp = be32_to_cpu(((__be32 *)bh->b_data)[0]);
+	((__be32 *)bh->b_data)[0] = cpu_to_be32(tmp - val);
 }
 
 static inline void
@@ -164,89 +164,89 @@
 #define AFFS_DATA(bh)		(((struct affs_data_head *)(bh)->b_data)->data)
 
 struct affs_date {
-	u32 days;
-	u32 mins;
-	u32 ticks;
+	__be32 days;
+	__be32 mins;
+	__be32 ticks;
 };
 
 struct affs_short_date {
-	u16 days;
-	u16 mins;
-	u16 ticks;
+	__be16 days;
+	__be16 mins;
+	__be16 ticks;
 };
 
 struct affs_root_head {
-	u32 ptype;
-	u32 spare1;
-	u32 spare2;
-	u32 hash_size;
-	u32 spare3;
-	u32 checksum;
-	u32 hashtable[1];
+	__be32 ptype;
+	__be32 spare1;
+	__be32 spare2;
+	__be32 hash_size;
+	__be32 spare3;
+	__be32 checksum;
+	__be32 hashtable[1];
 };
 
 struct affs_root_tail {
-	u32 bm_flag;
-	u32 bm_blk[AFFS_ROOT_BMAPS];
-	u32 bm_ext;
+	__be32 bm_flag;
+	__be32 bm_blk[AFFS_ROOT_BMAPS];
+	__be32 bm_ext;
 	struct affs_date root_change;
 	u8 disk_name[32];
-	u32 spare1;
-	u32 spare2;
+	__be32 spare1;
+	__be32 spare2;
 	struct affs_date disk_change;
 	struct affs_date disk_create;
-	u32 spare3;
-	u32 spare4;
-	u32 dcache;
-	u32 stype;
+	__be32 spare3;
+	__be32 spare4;
+	__be32 dcache;
+	__be32 stype;
 };
 
 struct affs_head {
-	u32 ptype;
-	u32 key;
-	u32 block_count;
-	u32 spare1;
-	u32 first_data;
-	u32 checksum;
-	u32 table[1];
+	__be32 ptype;
+	__be32 key;
+	__be32 block_count;
+	__be32 spare1;
+	__be32 first_data;
+	__be32 checksum;
+	__be32 table[1];
 };
 
 struct affs_tail {
-	u32 spare1;
-	u16 uid;
-	u16 gid;
-	u32 protect;
-	u32 size;
+	__be32 spare1;
+	__be16 uid;
+	__be16 gid;
+	__be32 protect;
+	__be32 size;
 	u8 comment[92];
 	struct affs_date change;
 	u8 name[32];
-	u32 spare2;
-	u32 original;
-	u32 link_chain;
-	u32 spare[5];
-	u32 hash_chain;
-	u32 parent;
-	u32 extension;
-	u32 stype;
+	__be32 spare2;
+	__be32 original;
+	__be32 link_chain;
+	__be32 spare[5];
+	__be32 hash_chain;
+	__be32 parent;
+	__be32 extension;
+	__be32 stype;
 };
 
 struct slink_front
 {
-	u32 ptype;
-	u32 key;
-	u32 spare1[3];
-	u32 checksum;
+	__be32 ptype;
+	__be32 key;
+	__be32 spare1[3];
+	__be32 checksum;
 	u8 symname[1];	/* depends on block size */
 };
 
 struct affs_data_head
 {
-	u32 ptype;
-	u32 key;
-	u32 sequence;
-	u32 size;
-	u32 next;
-	u32 checksum;
+	__be32 ptype;
+	__be32 key;
+	__be32 sequence;
+	__be32 size;
+	__be32 next;
+	__be32 checksum;
 	u8 data[1];	/* depends on block size */
 };
 
diff -Nru a/include/linux/arcdevice.h b/include/linux/arcdevice.h
--- a/include/linux/arcdevice.h	2004-10-18 14:56:17 -07:00
+++ b/include/linux/arcdevice.h	2004-10-18 14:56:17 -07:00
@@ -305,7 +305,7 @@
 					void *buf, int count);
 	} hw;
 
-	void *mem_start;	/* pointer to ioremap'ed MMIO */
+	void __iomem *mem_start;	/* pointer to ioremap'ed MMIO */
 };
 
 
diff -Nru a/include/linux/ata.h b/include/linux/ata.h
--- a/include/linux/ata.h	2004-10-18 14:56:33 -07:00
+++ b/include/linux/ata.h	2004-10-18 14:56:33 -07:00
@@ -42,6 +42,7 @@
 	ATA_ID_SERNO_OFS	= 10,
 	ATA_ID_MAJOR_VER	= 80,
 	ATA_ID_PIO_MODES	= 64,
+	ATA_ID_MWDMA_MODES	= 63,
 	ATA_ID_UDMA_MODES	= 88,
 	ATA_ID_PIO4		= (1 << 1),
 
@@ -133,13 +134,20 @@
 	XFER_UDMA_2		= 0x42,
 	XFER_UDMA_1		= 0x41,
 	XFER_UDMA_0		= 0x40,
+	XFER_MW_DMA_2		= 0x22,
+	XFER_MW_DMA_1		= 0x21,
+	XFER_MW_DMA_0		= 0x20,
 	XFER_PIO_4		= 0x0C,
 	XFER_PIO_3		= 0x0B,
+	XFER_PIO_2		= 0x0A,
+	XFER_PIO_1		= 0x09,
+	XFER_PIO_0		= 0x08,
 
 	/* ATAPI stuff */
 	ATAPI_PKT_DMA		= (1 << 0),
 	ATAPI_DMADIR		= (1 << 2),	/* ATAPI data dir:
 						   0=to device, 1=to host */
+	ATAPI_CDB_LEN		= 16,
 
 	/* cable types */
 	ATA_CBL_NONE		= 0,
@@ -169,16 +177,22 @@
 	ATA_PROT_PIO,		/* PIO single sector */
 	ATA_PROT_PIO_MULT,	/* PIO multiple sector */
 	ATA_PROT_DMA,		/* DMA */
-	ATA_PROT_ATAPI,		/* packet command */
+	ATA_PROT_ATAPI,		/* packet command, PIO data xfer*/
+	ATA_PROT_ATAPI_NODATA,	/* packet command, no data */
 	ATA_PROT_ATAPI_DMA,	/* packet command with special DMA sauce */
 };
 
+enum ata_ioctls {
+	ATA_IOC_GET_IO32	= 0x309,
+	ATA_IOC_SET_IO32	= 0x324,
+};
+
 /* core structures */
 
 struct ata_prd {
 	u32			addr;
 	u32			flags_len;
-} __attribute__((packed));
+};
 
 struct ata_taskfile {
 	unsigned long		flags;		/* ATA_TFLAG_xxx */
@@ -206,6 +220,8 @@
 #define ata_id_is_ata(dev)	(((dev)->id[0] & (1 << 15)) == 0)
 #define ata_id_rahead_enabled(dev) ((dev)->id[85] & (1 << 6))
 #define ata_id_wcache_enabled(dev) ((dev)->id[85] & (1 << 5))
+#define ata_id_has_flush(dev) ((dev)->id[83] & (1 << 12))
+#define ata_id_has_flush_ext(dev) ((dev)->id[83] & (1 << 13))
 #define ata_id_has_lba48(dev)	((dev)->id[83] & (1 << 10))
 #define ata_id_has_wcache(dev)	((dev)->id[82] & (1 << 5))
 #define ata_id_has_pm(dev)	((dev)->id[82] & (1 << 3))
@@ -220,9 +236,20 @@
 	  ((u64) dev->id[(n) + 1] << 16) |	\
 	  ((u64) dev->id[(n) + 0]) )
 
+static inline int atapi_cdb_len(u16 *dev_id)
+{
+	u16 tmp = dev_id[0] & 0x3;
+	switch (tmp) {
+	case 0:		return 12;
+	case 1:		return 16;
+	default:	return -1;
+	}
+}
+
 static inline int is_atapi_taskfile(struct ata_taskfile *tf)
 {
 	return (tf->protocol == ATA_PROT_ATAPI) ||
+	       (tf->protocol == ATA_PROT_ATAPI_NODATA) ||
 	       (tf->protocol == ATA_PROT_ATAPI_DMA);
 }
 
diff -Nru a/include/linux/atalk.h b/include/linux/atalk.h
--- a/include/linux/atalk.h	2004-10-18 14:56:49 -07:00
+++ b/include/linux/atalk.h	2004-10-18 14:56:49 -07:00
@@ -191,10 +191,13 @@
 extern void		 aarp_send_probe(struct net_device *dev,
 					 struct atalk_addr *addr);
 extern void		 aarp_device_down(struct net_device *dev);
+extern void		 aarp_probe_network(struct atalk_iface *atif);
+extern int 		 aarp_proxy_probe_network(struct atalk_iface *atif,
+				     struct atalk_addr *sa);
+extern void		 aarp_proxy_remove(struct net_device *dev,
+					   struct atalk_addr *sa);
 
-#ifdef MODULE
-extern void aarp_cleanup_module(void);
-#endif /* MODULE */
+extern void		aarp_cleanup_module(void);
 
 #define at_sk(__sk) ((struct atalk_sock *)(__sk)->sk_protinfo)
 
@@ -209,8 +212,28 @@
 
 extern struct atalk_route atrtr_default;
 
+extern struct file_operations atalk_seq_arp_fops;
+
+extern int sysctl_aarp_expiry_time;
+extern int sysctl_aarp_tick_time;
+extern int sysctl_aarp_retransmit_limit;
+extern int sysctl_aarp_resolve_time;
+
+#ifdef CONFIG_SYSCTL
+extern void atalk_register_sysctl(void);
+extern void atalk_unregister_sysctl(void);
+#else
+#define atalk_register_sysctl()		do { } while(0)
+#define atalk_unregister_sysctl()	do { } while(0)
+#endif
+
+#ifdef CONFIG_PROC_FS
 extern int atalk_proc_init(void);
 extern void atalk_proc_exit(void);
+#else
+#define atalk_proc_init()	0
+#define atalk_proc_exit()	do { } while(0)
+#endif /* CONFIG_PROC_FS */
 
 #endif /* __KERNEL__ */
 #endif /* __LINUX_ATALK_H__ */
diff -Nru a/include/linux/bio.h b/include/linux/bio.h
--- a/include/linux/bio.h	2004-10-18 14:56:49 -07:00
+++ b/include/linux/bio.h	2004-10-18 14:56:49 -07:00
@@ -121,6 +121,7 @@
 #define BIO_CLONED	4	/* doesn't own data */
 #define BIO_BOUNCED	5	/* bio is a bounce bio */
 #define BIO_USER_MAPPED 6	/* contains user pages */
+#define BIO_EOPNOTSUPP	7	/* not supported */
 #define bio_flagged(bio, flag)	((bio)->bi_flags & (1 << (flag)))
 
 /*
@@ -160,6 +161,8 @@
 #define bio_data(bio)		(page_address(bio_page((bio))) + bio_offset((bio)))
 #define bio_barrier(bio)	((bio)->bi_rw & (1 << BIO_RW_BARRIER))
 #define bio_sync(bio)		((bio)->bi_rw & (1 << BIO_RW_SYNC))
+#define bio_failfast(bio)	((bio)->bi_rw & (1 << BIO_RW_FAILFAST))
+#define bio_rw_ahead(bio)	((bio)->bi_rw & (1 << BIO_RW_AHEAD))
 
 /*
  * will die
diff -Nru a/include/linux/bitmap.h b/include/linux/bitmap.h
--- a/include/linux/bitmap.h	2004-10-18 14:57:05 -07:00
+++ b/include/linux/bitmap.h	2004-10-18 14:57:05 -07:00
@@ -98,6 +98,9 @@
 			const unsigned long *src, int nbits);
 extern int bitmap_parse(const char __user *ubuf, unsigned int ulen,
 			unsigned long *dst, int nbits);
+extern int bitmap_find_free_region(unsigned long *bitmap, int bits, int order);
+extern void bitmap_release_region(unsigned long *bitmap, int pos, int order);
+extern int bitmap_allocate_region(unsigned long *bitmap, int pos, int order);
 
 #define BITMAP_LAST_WORD_MASK(nbits)					\
 (									\
diff -Nru a/include/linux/blkdev.h b/include/linux/blkdev.h
--- a/include/linux/blkdev.h	2004-10-18 14:56:18 -07:00
+++ b/include/linux/blkdev.h	2004-10-18 14:56:18 -07:00
@@ -195,6 +195,8 @@
 	__REQ_PM_SUSPEND,	/* suspend request */
 	__REQ_PM_RESUME,	/* resume request */
 	__REQ_PM_SHUTDOWN,	/* shutdown request */
+	__REQ_BAR_PREFLUSH,	/* barrier pre-flush done */
+	__REQ_BAR_POSTFLUSH,	/* barrier post-flush */
 	__REQ_NR_BITS,		/* stops here */
 };
 
@@ -220,6 +222,8 @@
 #define REQ_PM_SUSPEND	(1 << __REQ_PM_SUSPEND)
 #define REQ_PM_RESUME	(1 << __REQ_PM_RESUME)
 #define REQ_PM_SHUTDOWN	(1 << __REQ_PM_SHUTDOWN)
+#define REQ_BAR_PREFLUSH	(1 << __REQ_BAR_PREFLUSH)
+#define REQ_BAR_POSTFLUSH	(1 << __REQ_BAR_POSTFLUSH)
 
 /*
  * State information carried for REQ_PM_SUSPEND and REQ_PM_RESUME
@@ -248,6 +252,7 @@
 struct bio_vec;
 typedef int (merge_bvec_fn) (request_queue_t *, struct bio *, struct bio_vec *);
 typedef void (activity_fn) (void *data, int rw);
+typedef int (issue_flush_fn) (request_queue_t *, struct gendisk *, sector_t *);
 
 enum blk_queue_state {
 	Queue_down,
@@ -290,6 +295,7 @@
 	unplug_fn		*unplug_fn;
 	merge_bvec_fn		*merge_bvec_fn;
 	activity_fn		*activity_fn;
+	issue_flush_fn		*issue_flush_fn;
 
 	/*
 	 * Auto-unplugging state
@@ -338,6 +344,7 @@
 	unsigned int		nr_congestion_off;
 
 	unsigned short		max_sectors;
+	unsigned short		max_hw_sectors;
 	unsigned short		max_phys_segments;
 	unsigned short		max_hw_segments;
 	unsigned short		hardsect_size;
@@ -373,6 +380,7 @@
 #define QUEUE_FLAG_DEAD		5	/* queue being torn down */
 #define QUEUE_FLAG_REENTER	6	/* Re-entrancy avoidance */
 #define QUEUE_FLAG_PLUGGED	7	/* queue is plugged */
+#define QUEUE_FLAG_ORDERED	8	/* supports ordered writes */
 
 #define blk_queue_plugged(q)	test_bit(QUEUE_FLAG_PLUGGED, &(q)->queue_flags)
 #define blk_queue_tagged(q)	test_bit(QUEUE_FLAG_QUEUED, &(q)->queue_flags)
@@ -390,6 +398,10 @@
 #define blk_pm_request(rq)	\
 	((rq)->flags & (REQ_PM_SUSPEND | REQ_PM_RESUME))
 
+#define blk_barrier_rq(rq)	((rq)->flags & REQ_HARDBARRIER)
+#define blk_barrier_preflush(rq)	((rq)->flags & REQ_BAR_PREFLUSH)
+#define blk_barrier_postflush(rq)	((rq)->flags & REQ_BAR_POSTFLUSH)
+
 #define list_entry_rq(ptr)	list_entry((ptr), struct request, queuelist)
 
 #define rq_data_dir(rq)		((rq)->flags & 1)
@@ -560,6 +572,14 @@
 extern int process_that_request_first(struct request *, unsigned int);
 extern void end_request(struct request *req, int uptodate);
 
+/*
+ * end_that_request_first/chunk() takes an uptodate argument. we account
+ * any value <= as an io error. 0 means -EIO for compatability reasons,
+ * any other < 0 value is the direct error type. An uptodate value of
+ * 1 indicates successful io completion
+ */
+#define end_io_error(uptodate)	(unlikely((uptodate) <= 0))
+
 static inline void blkdev_dequeue_request(struct request *req)
 {
 	BUG_ON(list_empty(&req->queuelist));
@@ -588,6 +608,9 @@
 extern void blk_queue_merge_bvec(request_queue_t *, merge_bvec_fn *);
 extern void blk_queue_dma_alignment(request_queue_t *, int);
 extern struct backing_dev_info *blk_get_backing_dev_info(struct block_device *bdev);
+extern void blk_queue_ordered(request_queue_t *, int);
+extern void blk_queue_issue_flush_fn(request_queue_t *, issue_flush_fn *);
+extern int blkdev_scsi_issue_flush_fn(request_queue_t *, struct gendisk *, sector_t *);
 
 extern int blk_rq_map_sg(request_queue_t *, struct request *, struct scatterlist *);
 extern void blk_dump_rq_flags(struct request *, char *);
@@ -616,6 +639,7 @@
 
 extern void blk_rq_bio_prep(request_queue_t *, struct request *, struct bio *);
 extern void blk_rq_prep_restart(struct request *);
+extern int blkdev_issue_flush(struct block_device *, sector_t *);
 
 #define MAX_PHYS_SEGMENTS 128
 #define MAX_HW_SEGMENTS 128
diff -Nru a/include/linux/bootmem.h b/include/linux/bootmem.h
--- a/include/linux/bootmem.h	2004-10-18 14:56:50 -07:00
+++ b/include/linux/bootmem.h	2004-10-18 14:56:50 -07:00
@@ -67,6 +67,9 @@
 	__alloc_bootmem_node((pgdat), (x), PAGE_SIZE, 0)
 #endif /* !CONFIG_HAVE_ARCH_BOOTMEM_NODE */
 
+extern unsigned long __initdata nr_kernel_pages;
+extern unsigned long __initdata nr_all_pages;
+
 extern void *__init alloc_large_system_hash(const char *tablename,
 					    unsigned long bucketsize,
 					    unsigned long numentries,
diff -Nru a/include/linux/buffer_head.h b/include/linux/buffer_head.h
--- a/include/linux/buffer_head.h	2004-10-18 14:55:54 -07:00
+++ b/include/linux/buffer_head.h	2004-10-18 14:55:54 -07:00
@@ -26,6 +26,8 @@
 	BH_Delay,	/* Buffer is not yet allocated on disk */
 	BH_Boundary,	/* Block is followed by a discontiguity */
 	BH_Write_EIO,	/* I/O error on write */
+	BH_Ordered,	/* ordered write */
+	BH_Eopnotsupp,	/* operation not supported (barrier) */
 
 	BH_PrivateStart,/* not a state bit, but the first bit available
 			 * for private allocation by other entities
@@ -47,12 +49,12 @@
 struct buffer_head {
 	/* First cache line: */
 	unsigned long b_state;		/* buffer state bitmap (see above) */
-	atomic_t b_count;		/* users using this block */
 	struct buffer_head *b_this_page;/* circular list of page's buffers */
 	struct page *b_page;		/* the page this bh is mapped to */
+	atomic_t b_count;		/* users using this block */
+	u32 b_size;			/* block size */
 
 	sector_t b_blocknr;		/* block number */
-	u32 b_size;			/* block size */
 	char *b_data;			/* pointer to data block */
 
 	struct block_device *b_bdev;
@@ -110,7 +112,9 @@
 BUFFER_FNS(Async_Write, async_write)
 BUFFER_FNS(Delay, delay)
 BUFFER_FNS(Boundary, boundary)
-BUFFER_FNS(Write_EIO,write_io_error)
+BUFFER_FNS(Write_EIO, write_io_error)
+BUFFER_FNS(Ordered, ordered)
+BUFFER_FNS(Eopnotsupp, eopnotsupp)
 
 #define bh_offset(bh)		((unsigned long)(bh)->b_data & ~PAGE_MASK)
 #define touch_buffer(bh)	mark_page_accessed(bh->b_page)
@@ -139,17 +143,13 @@
 void end_buffer_async_write(struct buffer_head *bh, int uptodate);
 
 /* Things to do with buffers at mapping->private_list */
-void buffer_insert_list(spinlock_t *lock,
-			struct buffer_head *, struct list_head *);
 void mark_buffer_dirty_inode(struct buffer_head *bh, struct inode *inode);
 int inode_has_buffers(struct inode *);
 void invalidate_inode_buffers(struct inode *);
 int remove_inode_buffers(struct inode *inode);
-int fsync_buffers_list(spinlock_t *lock, struct list_head *);
 int sync_mapping_buffers(struct address_space *mapping);
 void unmap_underlying_metadata(struct block_device *bdev, sector_t block);
 
-void mark_buffer_async_read(struct buffer_head *bh);
 void mark_buffer_async_write(struct buffer_head *bh);
 void invalidate_bdev(struct block_device *, int);
 int sync_blockdev(struct block_device *bdev);
@@ -172,8 +172,8 @@
 void FASTCALL(unlock_buffer(struct buffer_head *bh));
 void FASTCALL(__lock_buffer(struct buffer_head *bh));
 void ll_rw_block(int, int, struct buffer_head * bh[]);
-void sync_dirty_buffer(struct buffer_head *bh);
-void submit_bh(int, struct buffer_head *);
+int sync_dirty_buffer(struct buffer_head *bh);
+int submit_bh(int, struct buffer_head *);
 void write_boundary_block(struct block_device *bdev,
 			sector_t bblock, unsigned blocksize);
 
@@ -202,12 +202,6 @@
 int nobh_commit_write(struct file *, struct page *, unsigned, unsigned);
 int nobh_truncate_page(struct address_space *, loff_t);
 
-#define OSYNC_METADATA	(1<<0)
-#define OSYNC_DATA	(1<<1)
-#define OSYNC_INODE	(1<<2)
-int generic_osync_inode(struct inode *, struct address_space *, int);
-
-
 /*
  * inline definitions
  */
@@ -274,12 +268,14 @@
  */
 static inline void wait_on_buffer(struct buffer_head *bh)
 {
+	might_sleep();
 	if (buffer_locked(bh) || atomic_read(&bh->b_count) == 0)
 		__wait_on_buffer(bh);
 }
 
 static inline void lock_buffer(struct buffer_head *bh)
 {
+	might_sleep();
 	if (test_set_buffer_locked(bh))
 		__lock_buffer(bh);
 }
diff -Nru a/include/linux/byteorder/big_endian.h b/include/linux/byteorder/big_endian.h
--- a/include/linux/byteorder/big_endian.h	2004-10-18 14:57:03 -07:00
+++ b/include/linux/byteorder/big_endian.h	2004-10-18 14:57:03 -07:00
@@ -8,48 +8,86 @@
 #define __BIG_ENDIAN_BITFIELD
 #endif
 
+#include <linux/types.h>
 #include <linux/byteorder/swab.h>
 
-#define __constant_htonl(x) ((__u32)(x))
-#define __constant_ntohl(x) ((__u32)(x))
-#define __constant_htons(x) ((__u16)(x))
-#define __constant_ntohs(x) ((__u16)(x))
-#define __constant_cpu_to_le64(x) ___constant_swab64((x))
-#define __constant_le64_to_cpu(x) ___constant_swab64((x))
-#define __constant_cpu_to_le32(x) ___constant_swab32((x))
-#define __constant_le32_to_cpu(x) ___constant_swab32((x))
-#define __constant_cpu_to_le16(x) ___constant_swab16((x))
-#define __constant_le16_to_cpu(x) ___constant_swab16((x))
-#define __constant_cpu_to_be64(x) ((__u64)(x))
-#define __constant_be64_to_cpu(x) ((__u64)(x))
-#define __constant_cpu_to_be32(x) ((__u32)(x))
-#define __constant_be32_to_cpu(x) ((__u32)(x))
-#define __constant_cpu_to_be16(x) ((__u16)(x))
-#define __constant_be16_to_cpu(x) ((__u16)(x))
-#define __cpu_to_le64(x) __swab64((x))
-#define __le64_to_cpu(x) __swab64((x))
-#define __cpu_to_le32(x) __swab32((x))
-#define __le32_to_cpu(x) __swab32((x))
-#define __cpu_to_le16(x) __swab16((x))
-#define __le16_to_cpu(x) __swab16((x))
-#define __cpu_to_be64(x) ((__u64)(x))
-#define __be64_to_cpu(x) ((__u64)(x))
-#define __cpu_to_be32(x) ((__u32)(x))
-#define __be32_to_cpu(x) ((__u32)(x))
-#define __cpu_to_be16(x) ((__u16)(x))
-#define __be16_to_cpu(x) ((__u16)(x))
-#define __cpu_to_le64p(x) __swab64p((x))
-#define __le64_to_cpup(x) __swab64p((x))
-#define __cpu_to_le32p(x) __swab32p((x))
-#define __le32_to_cpup(x) __swab32p((x))
-#define __cpu_to_le16p(x) __swab16p((x))
-#define __le16_to_cpup(x) __swab16p((x))
-#define __cpu_to_be64p(x) (*(__u64*)(x))
-#define __be64_to_cpup(x) (*(__u64*)(x))
-#define __cpu_to_be32p(x) (*(__u32*)(x))
-#define __be32_to_cpup(x) (*(__u32*)(x))
-#define __cpu_to_be16p(x) (*(__u16*)(x))
-#define __be16_to_cpup(x) (*(__u16*)(x))
+#define __constant_htonl(x) ((__force __be32)(__u32)(x))
+#define __constant_ntohl(x) ((__force __u32)(__be32)(x))
+#define __constant_htons(x) ((__force __be16)(__u16)(x))
+#define __constant_ntohs(x) ((__force __u16)(__be16)(x))
+#define __constant_cpu_to_le64(x) ((__force __le64)___constant_swab64((x)))
+#define __constant_le64_to_cpu(x) ___constant_swab64((__force __u64)(__le64)(x))
+#define __constant_cpu_to_le32(x) ((__force __le32)___constant_swab32((x)))
+#define __constant_le32_to_cpu(x) ___constant_swab32((__force __u32)(__le32)(x))
+#define __constant_cpu_to_le16(x) ((__force __le16)___constant_swab16((x)))
+#define __constant_le16_to_cpu(x) ___constant_swab16((__force __u16)(__le16)(x))
+#define __constant_cpu_to_be64(x) ((__force __be64)(__u64)(x))
+#define __constant_be64_to_cpu(x) ((__force __u64)(__be64)(x))
+#define __constant_cpu_to_be32(x) ((__force __be32)(__u32)(x))
+#define __constant_be32_to_cpu(x) ((__force __u32)(__be32)(x))
+#define __constant_cpu_to_be16(x) ((__force __be16)(__u16)(x))
+#define __constant_be16_to_cpu(x) ((__force __u16)(__be16)(x))
+#define __cpu_to_le64(x) ((__force __le64)___swab64((x)))
+#define __le64_to_cpu(x) ___swab64((__force __u64)(__le64)(x))
+#define __cpu_to_le32(x) ((__force __le32)___swab32((x)))
+#define __le32_to_cpu(x) ___swab32((__force __u32)(__le32)(x))
+#define __cpu_to_le16(x) ((__force __le16)___swab16((x)))
+#define __le16_to_cpu(x) ___swab16((__force __u16)(__le16)(x))
+#define __cpu_to_be64(x) ((__force __be64)(__u64)(x))
+#define __be64_to_cpu(x) ((__force __u64)(__be64)(x))
+#define __cpu_to_be32(x) ((__force __be32)(__u32)(x))
+#define __be32_to_cpu(x) ((__force __u32)(__be32)(x))
+#define __cpu_to_be16(x) ((__force __be16)(__u16)(x))
+#define __be16_to_cpu(x) ((__force __u16)(__be16)(x))
+
+static inline __le64 __cpu_to_le64p(const __u64 *p)
+{
+	return (__force __le64)__swab64p(p);
+}
+static inline __u64 __le64_to_cpup(const __le64 *p)
+{
+	return __swab64p((__u64 *)p);
+}
+static inline __le32 __cpu_to_le32p(const __u32 *p)
+{
+	return (__force __le32)__swab32p(p);
+}
+static inline __u32 __le32_to_cpup(const __le32 *p)
+{
+	return __swab32p((__u32 *)p);
+}
+static inline __le16 __cpu_to_le16p(const __u16 *p)
+{
+	return (__force __le16)__swab16p(p);
+}
+static inline __u16 __le16_to_cpup(const __le16 *p)
+{
+	return __swab16p((__u16 *)p);
+}
+static inline __be64 __cpu_to_be64p(const __u64 *p)
+{
+	return (__force __be64)*p;
+}
+static inline __u64 __be64_to_cpup(const __be64 *p)
+{
+	return (__force __u64)*p;
+}
+static inline __be32 __cpu_to_be32p(const __u32 *p)
+{
+	return (__force __be32)*p;
+}
+static inline __u32 __be32_to_cpup(const __be32 *p)
+{
+	return (__force __u32)*p;
+}
+static inline __be16 __cpu_to_be16p(const __u16 *p)
+{
+	return (__force __be16)*p;
+}
+static inline __u16 __be16_to_cpup(const __be16 *p)
+{
+	return (__force __u16)*p;
+}
 #define __cpu_to_le64s(x) __swab64s((x))
 #define __le64_to_cpus(x) __swab64s((x))
 #define __cpu_to_le32s(x) __swab32s((x))
diff -Nru a/include/linux/byteorder/generic.h b/include/linux/byteorder/generic.h
--- a/include/linux/byteorder/generic.h	2004-10-18 14:55:46 -07:00
+++ b/include/linux/byteorder/generic.h	2004-10-18 14:55:46 -07:00
@@ -147,10 +147,10 @@
  * Do the prototypes. Somebody might want to take the
  * address or some such sick thing..
  */
-extern __u32			ntohl(__u32);
-extern __u32			htonl(__u32);
-extern unsigned short int	ntohs(unsigned short int);
-extern unsigned short int	htons(unsigned short int);
+extern __u32			ntohl(__be32);
+extern __be32			htonl(__u32);
+extern __u16			ntohs(__be16);
+extern __be16			htons(__u16);
 
 #if defined(__GNUC__) && (__GNUC__ >= 2) && defined(__OPTIMIZE__)
 
diff -Nru a/include/linux/byteorder/little_endian.h b/include/linux/byteorder/little_endian.h
--- a/include/linux/byteorder/little_endian.h	2004-10-18 14:56:33 -07:00
+++ b/include/linux/byteorder/little_endian.h	2004-10-18 14:56:33 -07:00
@@ -8,48 +8,86 @@
 #define __LITTLE_ENDIAN_BITFIELD
 #endif
 
+#include <linux/types.h>
 #include <linux/byteorder/swab.h>
 
-#define __constant_htonl(x) ___constant_swab32((x))
-#define __constant_ntohl(x) ___constant_swab32((x))
-#define __constant_htons(x) ___constant_swab16((x))
-#define __constant_ntohs(x) ___constant_swab16((x))
-#define __constant_cpu_to_le64(x) ((__u64)(x))
-#define __constant_le64_to_cpu(x) ((__u64)(x))
-#define __constant_cpu_to_le32(x) ((__u32)(x))
-#define __constant_le32_to_cpu(x) ((__u32)(x))
-#define __constant_cpu_to_le16(x) ((__u16)(x))
-#define __constant_le16_to_cpu(x) ((__u16)(x))
-#define __constant_cpu_to_be64(x) ___constant_swab64((x))
-#define __constant_be64_to_cpu(x) ___constant_swab64((x))
-#define __constant_cpu_to_be32(x) ___constant_swab32((x))
-#define __constant_be32_to_cpu(x) ___constant_swab32((x))
-#define __constant_cpu_to_be16(x) ___constant_swab16((x))
-#define __constant_be16_to_cpu(x) ___constant_swab16((x))
-#define __cpu_to_le64(x) ((__u64)(x))
-#define __le64_to_cpu(x) ((__u64)(x))
-#define __cpu_to_le32(x) ((__u32)(x))
-#define __le32_to_cpu(x) ((__u32)(x))
-#define __cpu_to_le16(x) ((__u16)(x))
-#define __le16_to_cpu(x) ((__u16)(x))
-#define __cpu_to_be64(x) __swab64((x))
-#define __be64_to_cpu(x) __swab64((x))
-#define __cpu_to_be32(x) __swab32((x))
-#define __be32_to_cpu(x) __swab32((x))
-#define __cpu_to_be16(x) __swab16((x))
-#define __be16_to_cpu(x) __swab16((x))
-#define __cpu_to_le64p(x) (*(__u64*)(x))
-#define __le64_to_cpup(x) (*(__u64*)(x))
-#define __cpu_to_le32p(x) (*(__u32*)(x))
-#define __le32_to_cpup(x) (*(__u32*)(x))
-#define __cpu_to_le16p(x) (*(__u16*)(x))
-#define __le16_to_cpup(x) (*(__u16*)(x))
-#define __cpu_to_be64p(x) __swab64p((x))
-#define __be64_to_cpup(x) __swab64p((x))
-#define __cpu_to_be32p(x) __swab32p((x))
-#define __be32_to_cpup(x) __swab32p((x))
-#define __cpu_to_be16p(x) __swab16p((x))
-#define __be16_to_cpup(x) __swab16p((x))
+#define __constant_htonl(x) ((__force __be32)___constant_swab32((x)))
+#define __constant_ntohl(x) ___constant_swab32((__force __be32)(x))
+#define __constant_htons(x) ((__force __be16)___constant_swab16((x)))
+#define __constant_ntohs(x) ___constant_swab16((__force __be16)(x))
+#define __constant_cpu_to_le64(x) ((__force __le64)(__u64)(x))
+#define __constant_le64_to_cpu(x) ((__force __u64)(__le64)(x))
+#define __constant_cpu_to_le32(x) ((__force __le32)(__u32)(x))
+#define __constant_le32_to_cpu(x) ((__force __u32)(__le32)(x))
+#define __constant_cpu_to_le16(x) ((__force __le16)(__u16)(x))
+#define __constant_le16_to_cpu(x) ((__force __u16)(__le16)(x))
+#define __constant_cpu_to_be64(x) ((__force __be64)___constant_swab64((x)))
+#define __constant_be64_to_cpu(x) ___constant_swab64((__force __u64)(__be64)(x))
+#define __constant_cpu_to_be32(x) ((__force __be32)___constant_swab32((x)))
+#define __constant_be32_to_cpu(x) ___constant_swab32((__force __u32)(__be32)(x))
+#define __constant_cpu_to_be16(x) ((__force __be16)___constant_swab16((x)))
+#define __constant_be16_to_cpu(x) ___constant_swab16((__force __u16)(__be16)(x))
+#define __cpu_to_le64(x) ((__force __le64)(__u64)(x))
+#define __le64_to_cpu(x) ((__force __u64)(__le64)(x))
+#define __cpu_to_le32(x) ((__force __le32)(__u32)(x))
+#define __le32_to_cpu(x) ((__force __u32)(__le32)(x))
+#define __cpu_to_le16(x) ((__force __le16)(__u16)(x))
+#define __le16_to_cpu(x) ((__force __u16)(__le16)(x))
+#define __cpu_to_be64(x) ((__force __be64)___swab64((x)))
+#define __be64_to_cpu(x) ___swab64((__force __u64)(__be64)(x))
+#define __cpu_to_be32(x) ((__force __be32)___swab32((x)))
+#define __be32_to_cpu(x) ___swab32((__force __u32)(__be32)(x))
+#define __cpu_to_be16(x) ((__force __be16)___swab16((x)))
+#define __be16_to_cpu(x) ___swab16((__force __u16)(__be16)(x))
+
+static inline __le64 __cpu_to_le64p(const __u64 *p)
+{
+	return (__force __le64)*p;
+}
+static inline __u64 __le64_to_cpup(const __le64 *p)
+{
+	return (__force __u64)*p;
+}
+static inline __le32 __cpu_to_le32p(const __u32 *p)
+{
+	return (__force __le32)*p;
+}
+static inline __u32 __le32_to_cpup(const __le32 *p)
+{
+	return (__force __u32)*p;
+}
+static inline __le16 __cpu_to_le16p(const __u16 *p)
+{
+	return (__force __le16)*p;
+}
+static inline __u16 __le16_to_cpup(const __le16 *p)
+{
+	return (__force __u16)*p;
+}
+static inline __be64 __cpu_to_be64p(const __u64 *p)
+{
+	return (__force __be64)__swab64p(p);
+}
+static inline __u64 __be64_to_cpup(const __be64 *p)
+{
+	return __swab64p((__u64 *)p);
+}
+static inline __be32 __cpu_to_be32p(const __u32 *p)
+{
+	return (__force __be32)__swab32p(p);
+}
+static inline __u32 __be32_to_cpup(const __be32 *p)
+{
+	return __swab32p((__u32 *)p);
+}
+static inline __be16 __cpu_to_be16p(const __u16 *p)
+{
+	return (__force __be16)__swab16p(p);
+}
+static inline __u16 __be16_to_cpup(const __be16 *p)
+{
+	return __swab16p((__u16 *)p);
+}
 #define __cpu_to_le64s(x) do {} while (0)
 #define __le64_to_cpus(x) do {} while (0)
 #define __cpu_to_le32s(x) do {} while (0)
diff -Nru a/include/linux/cdrom.h b/include/linux/cdrom.h
--- a/include/linux/cdrom.h	2004-10-18 14:55:54 -07:00
+++ b/include/linux/cdrom.h	2004-10-18 14:55:54 -07:00
@@ -466,9 +466,10 @@
 #define GPCMD_REPORT_KEY		    0xa4
 #define GPCMD_REQUEST_SENSE		    0x03
 #define GPCMD_RESERVE_RZONE_TRACK	    0x53
+#define GPCMD_SEND_CUE_SHEET		    0x5d
 #define GPCMD_SCAN			    0xba
 #define GPCMD_SEEK			    0x2b
-#define GPCMD_SEND_DVD_STRUCTURE	    0xad
+#define GPCMD_SEND_DVD_STRUCTURE	    0xbf
 #define GPCMD_SEND_EVENT		    0xa2
 #define GPCMD_SEND_KEY			    0xa3
 #define GPCMD_SEND_OPC			    0x54
diff -Nru a/include/linux/coda.h b/include/linux/coda.h
--- a/include/linux/coda.h	2004-10-18 14:56:29 -07:00
+++ b/include/linux/coda.h	2004-10-18 14:56:29 -07:00
@@ -200,7 +200,7 @@
 typedef u_int32_t vgid_t;
 #endif /*_VUID_T_ */
 
-#ifdef CODA_FS_OLD_API
+#ifdef CONFIG_CODA_FS_OLD_API
 struct CodaFid {
 	u_int32_t opaque[3];
 };
@@ -220,7 +220,7 @@
     vgid_t cr_groupid, cr_egid, cr_sgid, cr_fsgid; /* same for groups */
 };
 
-#else /* not defined(CODA_FS_OLD_API) */
+#else /* not defined(CONFIG_CODA_FS_OLD_API) */
 
 struct CodaFid {
 	u_int32_t opaque[4];
@@ -318,7 +318,7 @@
 #define CODA_KERNEL_VERSION 0 /* don't care about kernel version number */
 #define CODA_KERNEL_VERSION 1 /* The old venus 4.6 compatible interface */
 #endif
-#ifdef CODA_FS_OLD_API
+#ifdef CONFIG_CODA_FS_OLD_API
 #define CODA_KERNEL_VERSION 2 /* venus_lookup got an extra parameter */
 #else
 #define CODA_KERNEL_VERSION 3 /* 128-bit file identifiers */
@@ -330,7 +330,7 @@
 struct coda_in_hdr {
     u_int32_t opcode;
     u_int32_t unique;	    /* Keep multiple outstanding msgs distinct */
-#ifdef CODA_FS_OLD_API
+#ifdef CONFIG_CODA_FS_OLD_API
     u_int16_t pid;	    /* Common to all */
     u_int16_t pgid;	    /* Common to all */
     u_int16_t sid;          /* Common to all */
@@ -614,7 +614,7 @@
 /* CODA_PURGEUSER is a venus->kernel call */
 struct coda_purgeuser_out {
     struct coda_out_hdr oh;
-#ifdef CODA_FS_OLD_API
+#ifdef CONFIG_CODA_FS_OLD_API
     struct coda_cred cred;
 #else
     vuid_t uid;
diff -Nru a/include/linux/compat.h b/include/linux/compat.h
--- a/include/linux/compat.h	2004-10-18 14:56:29 -07:00
+++ b/include/linux/compat.h	2004-10-18 14:56:29 -07:00
@@ -79,6 +79,8 @@
 	compat_long_t	ru_nivcsw;
 };
 
+extern int put_compat_rusage(const struct rusage *, struct compat_rusage __user *);
+
 struct compat_dirent {
 	u32		d_ino;
 	compat_off_t	d_off;
@@ -129,6 +131,16 @@
 asmlinkage long compat_sys_select(int n, compat_ulong_t __user *inp,
 		compat_ulong_t __user *outp, compat_ulong_t __user *exp,
 		struct compat_timeval __user *tvp);
+
+#define BITS_PER_COMPAT_LONG    (8*sizeof(compat_long_t))
+
+#define BITS_TO_COMPAT_LONGS(bits) \
+	(((bits)+BITS_PER_COMPAT_LONG-1)/BITS_PER_COMPAT_LONG)
+
+long compat_get_bitmap(unsigned long *mask, compat_ulong_t __user *umask,
+		       unsigned long bitmap_size);
+long compat_put_bitmap(compat_ulong_t __user *umask, unsigned long *mask,
+		       unsigned long bitmap_size);
 
 #endif /* CONFIG_COMPAT */
 #endif /* _LINUX_COMPAT_H */
diff -Nru a/include/linux/compat_ioctl.h b/include/linux/compat_ioctl.h
--- a/include/linux/compat_ioctl.h	2004-10-18 14:57:04 -07:00
+++ b/include/linux/compat_ioctl.h	2004-10-18 14:57:04 -07:00
@@ -384,6 +384,7 @@
 COMPATIBLE_IOCTL(DVD_AUTH)
 /* Big L */
 ULONG_IOCTL(LOOP_SET_FD)
+ULONG_IOCTL(LOOP_CHANGE_FD)
 COMPATIBLE_IOCTL(LOOP_CLR_FD)
 COMPATIBLE_IOCTL(LOOP_GET_STATUS64)
 COMPATIBLE_IOCTL(LOOP_SET_STATUS64)
@@ -592,13 +593,15 @@
 COMPATIBLE_IOCTL(ATMTCP_REMOVE)
 COMPATIBLE_IOCTL(ATMMPC_CTRL)
 COMPATIBLE_IOCTL(ATMMPC_DATA)
-/* Big W */
-/* WIOC_GETSUPPORT not yet implemented -E */
+/* Watchdog */
+COMPATIBLE_IOCTL(WDIOC_GETSUPPORT)
 COMPATIBLE_IOCTL(WDIOC_GETSTATUS)
 COMPATIBLE_IOCTL(WDIOC_GETBOOTSTATUS)
 COMPATIBLE_IOCTL(WDIOC_GETTEMP)
 COMPATIBLE_IOCTL(WDIOC_SETOPTIONS)
 COMPATIBLE_IOCTL(WDIOC_KEEPALIVE)
+COMPATIBLE_IOCTL(WDIOC_SETTIMEOUT)
+COMPATIBLE_IOCTL(WDIOC_GETTIMEOUT)
 /* Big R */
 COMPATIBLE_IOCTL(RNDGETENTCNT)
 COMPATIBLE_IOCTL(RNDADDTOENTCNT)
@@ -732,3 +735,20 @@
 COMPATIBLE_IOCTL(SIOCGIWRETRY)
 COMPATIBLE_IOCTL(SIOCSIWPOWER)
 COMPATIBLE_IOCTL(SIOCGIWPOWER)
+/* hiddev */
+COMPATIBLE_IOCTL(HIDIOCGVERSION)
+COMPATIBLE_IOCTL(HIDIOCAPPLICATION)
+COMPATIBLE_IOCTL(HIDIOCGDEVINFO)
+COMPATIBLE_IOCTL(HIDIOCGSTRING)
+COMPATIBLE_IOCTL(HIDIOCINITREPORT)
+COMPATIBLE_IOCTL(HIDIOCGREPORT)
+COMPATIBLE_IOCTL(HIDIOCSREPORT)
+COMPATIBLE_IOCTL(HIDIOCGREPORTINFO)
+COMPATIBLE_IOCTL(HIDIOCGFIELDINFO)
+COMPATIBLE_IOCTL(HIDIOCGUSAGE)
+COMPATIBLE_IOCTL(HIDIOCSUSAGE)
+COMPATIBLE_IOCTL(HIDIOCGUCODE)
+COMPATIBLE_IOCTL(HIDIOCGFLAG)
+COMPATIBLE_IOCTL(HIDIOCSFLAG)
+COMPATIBLE_IOCTL(HIDIOCGCOLLECTIONINDEX)
+COMPATIBLE_IOCTL(HIDIOCGCOLLECTIONINFO)
diff -Nru a/include/linux/compiler-gcc+.h b/include/linux/compiler-gcc+.h
--- a/include/linux/compiler-gcc+.h	2004-10-18 14:57:04 -07:00
+++ b/include/linux/compiler-gcc+.h	2004-10-18 14:57:04 -07:00
@@ -6,9 +6,9 @@
  */
 #include <linux/compiler-gcc.h>
 
-#define inline			__inline__ __attribute__((always_inline))
-#define __inline__		__inline__ __attribute__((always_inline))
-#define __inline		__inline__ __attribute__((always_inline))
+#define inline			inline		__attribute__((always_inline))
+#define __inline__		__inline__	__attribute__((always_inline))
+#define __inline		__inline	__attribute__((always_inline))
 #define __deprecated		__attribute__((deprecated))
 #define __attribute_used__	__attribute__((__used__))
 #define __attribute_pure__	__attribute__((pure))
diff -Nru a/include/linux/compiler-gcc3.h b/include/linux/compiler-gcc3.h
--- a/include/linux/compiler-gcc3.h	2004-10-18 14:55:54 -07:00
+++ b/include/linux/compiler-gcc3.h	2004-10-18 14:55:54 -07:00
@@ -3,10 +3,10 @@
 /* These definitions are for GCC v3.x.  */
 #include <linux/compiler-gcc.h>
 
-#if __GNUC_MINOR__ >= 1  && __GNUC_MINOR__ < 4
-# define inline		__inline__ __attribute__((always_inline))
-# define __inline__	__inline__ __attribute__((always_inline))
-# define __inline	__inline__ __attribute__((always_inline))
+#if __GNUC_MINOR__ >= 1
+# define inline		inline		__attribute__((always_inline))
+# define __inline__	__inline__	__attribute__((always_inline))
+# define __inline	__inline	__attribute__((always_inline))
 #endif
 
 #if __GNUC_MINOR__ > 0
@@ -27,4 +27,8 @@
 #endif
 #if __GNUC_MINOR__ >= 4
 #define __must_check __attribute__((warn_unused_result))
+#endif
+
+#if __GNUC_MINOR__ >= 5
+#define __compiler_offsetof(a,b) __builtin_offsetof(a,b)
 #endif
diff -Nru a/include/linux/compiler.h b/include/linux/compiler.h
--- a/include/linux/compiler.h	2004-10-18 14:56:33 -07:00
+++ b/include/linux/compiler.h	2004-10-18 14:56:33 -07:00
@@ -6,13 +6,17 @@
 # define __kernel	/* default address space */
 # define __safe		__attribute__((safe))
 # define __force	__attribute__((force))
+# define __iomem	__attribute__((noderef, address_space(2)))
 extern void __chk_user_ptr(void __user *);
+extern void __chk_io_ptr(void __iomem *);
 #else
 # define __user
 # define __kernel
 # define __safe
 # define __force
+# define __iomem
 # define __chk_user_ptr(x) (void)0
+# define __chk_io_ptr(x) (void)0
 #endif
 
 #ifdef __KERNEL__
@@ -122,6 +126,10 @@
 
 #ifndef noinline
 #define noinline
+#endif
+
+#ifndef __always_inline
+#define __always_inline inline
 #endif
 
 #endif /* __LINUX_COMPILER_H */
diff -Nru a/include/linux/cpu.h b/include/linux/cpu.h
--- a/include/linux/cpu.h	2004-10-18 14:56:17 -07:00
+++ b/include/linux/cpu.h	2004-10-18 14:56:17 -07:00
@@ -74,7 +74,7 @@
 #define hotcpu_notifier(fn, pri)
 
 /* CPUs don't go offline once they're online w/o CONFIG_HOTPLUG_CPU */
-#define cpu_is_offline(cpu) 0
+static inline int cpu_is_offline(int cpu) { return 0; }
 #endif
 
 #endif /* _LINUX_CPU_H_ */
diff -Nru a/include/linux/cpufreq.h b/include/linux/cpufreq.h
--- a/include/linux/cpufreq.h	2004-10-18 14:56:33 -07:00
+++ b/include/linux/cpufreq.h	2004-10-18 14:56:33 -07:00
@@ -209,13 +209,6 @@
 #define CPUFREQ_CONST_LOOPS 	0x02	/* loops_per_jiffy or other kernel
 					 * "constants" aren't affected by
 					 * frequency transitions */
-#define CPUFREQ_PANIC_OUTOFSYNC	0x04	/* panic if cpufreq's opinion of
-					 * current frequency differs from
-					 * actual frequency */
-#define CPUFREQ_PANIC_RESUME_OUTOFSYNC 0x08 /* panic if cpufreq's opinion of
-					 * current frequency differs from
-					 * actual frequency on resume
-					 * from sleep. */
 
 
 int cpufreq_register_driver(struct cpufreq_driver *driver_data);
diff -Nru a/include/linux/cpumask.h b/include/linux/cpumask.h
--- a/include/linux/cpumask.h	2004-10-18 14:56:28 -07:00
+++ b/include/linux/cpumask.h	2004-10-18 14:56:28 -07:00
@@ -73,6 +73,7 @@
  *    inside a macro, the way we do the other calls.
  */
 
+#include <linux/kernel.h>
 #include <linux/threads.h>
 #include <linux/bitmap.h>
 #include <asm/bug.h>
@@ -207,13 +208,13 @@
 #define first_cpu(src) __first_cpu(&(src), NR_CPUS)
 static inline int __first_cpu(const cpumask_t *srcp, int nbits)
 {
-	return find_first_bit(srcp->bits, nbits);
+	return min_t(int, nbits, find_first_bit(srcp->bits, nbits));
 }
 
 #define next_cpu(n, src) __next_cpu((n), &(src), NR_CPUS)
 static inline int __next_cpu(int n, const cpumask_t *srcp, int nbits)
 {
-	return find_next_bit(srcp->bits, nbits, n+1);
+	return min_t(int, nbits, find_next_bit(srcp->bits, nbits, n+1));
 }
 
 #define cpumask_of_cpu(cpu)						\
diff -Nru a/include/linux/cyclades.h b/include/linux/cyclades.h
--- a/include/linux/cyclades.h	2004-10-18 14:57:05 -07:00
+++ b/include/linux/cyclades.h	2004-10-18 14:57:05 -07:00
@@ -511,8 +511,8 @@
 struct cyclades_card {
     unsigned long base_phys;
     unsigned long ctl_phys;
-    unsigned long base_addr;
-    unsigned long ctl_addr;
+    void __iomem *base_addr;
+    void __iomem *ctl_addr;
     int irq;
     int num_chips;	/* 0 if card absent, -1 if Z/PCI, else Y */
     int first_line;	/* minor number of first channel on card */
@@ -539,9 +539,9 @@
  * (required to support Alpha systems) *
  ***************************************/
 
-#define cy_writeb(port,val)     {writeb((ucchar)(val),(ulong)(port)); mb();}
-#define cy_writew(port,val)     {writew((ushort)(val),(ulong)(port)); mb();}
-#define cy_writel(port,val)     {writel((uclong)(val),(ulong)(port)); mb();}
+#define cy_writeb(port,val)     {writeb((val),(port)); mb();}
+#define cy_writew(port,val)     {writew((val),(port)); mb();}
+#define cy_writel(port,val)     {writel((val),(port)); mb();}
 
 #define cy_readb(port)  readb(port)
 #define cy_readw(port)  readw(port)
diff -Nru a/include/linux/dcache.h b/include/linux/dcache.h
--- a/include/linux/dcache.h	2004-10-18 14:57:04 -07:00
+++ b/include/linux/dcache.h	2004-10-18 14:57:04 -07:00
@@ -33,8 +33,8 @@
  */
 struct qstr {
 	unsigned int hash;
-	const unsigned char *name;
 	unsigned int len;
+	const unsigned char *name;
 };
 
 struct dentry_stat_t {
@@ -101,11 +101,11 @@
 	unsigned long d_time;		/* used by d_revalidate */
 	struct dentry_operations *d_op;
 	struct super_block *d_sb;	/* The root of the dentry tree */
-	int d_mounted;
 	void *d_fsdata;			/* fs-specific data */
  	struct rcu_head d_rcu;
 	struct dcookie_struct *d_cookie; /* cookie, if any */
 	struct hlist_node d_hash;	/* lookup hash list */	
+	int d_mounted;
 	unsigned char d_iname[DNAME_INLINE_LEN_MIN];	/* small names */
 };
 
diff -Nru a/include/linux/delay.h b/include/linux/delay.h
--- a/include/linux/delay.h	2004-10-18 14:56:27 -07:00
+++ b/include/linux/delay.h	2004-10-18 14:56:27 -07:00
@@ -39,5 +39,11 @@
 #endif
 
 void msleep(unsigned int msecs);
+unsigned long msleep_interruptible(unsigned int msecs);
+
+static inline void ssleep(unsigned int seconds)
+{
+	msleep(seconds * 1000);
+}
 
 #endif /* defined(_LINUX_DELAY_H) */
diff -Nru a/include/linux/device.h b/include/linux/device.h
--- a/include/linux/device.h	2004-10-18 14:57:03 -07:00
+++ b/include/linux/device.h	2004-10-18 14:57:03 -07:00
@@ -59,7 +59,6 @@
 	struct driver_attribute	* drv_attrs;
 
 	int		(*match)(struct device * dev, struct device_driver * drv);
-	struct device * (*add)	(struct device * parent, char * bus_id);
 	int		(*hotplug) (struct device *dev, char **envp, 
 				    int num_envp, char *buffer, int buffer_size);
 	int		(*suspend)(struct device * dev, u32 state);
@@ -284,6 +283,9 @@
 					     allocations such descriptors. */
 
 	struct list_head	dma_pools;	/* dma pools (if dma'ble) */
+
+	struct dma_coherent_mem	*dma_mem; /* internal for coherent mem
+					     override */
 
 	void	(*release)(struct device * dev);
 };
diff -Nru a/include/linux/dma-mapping.h b/include/linux/dma-mapping.h
--- a/include/linux/dma-mapping.h	2004-10-18 14:56:50 -07:00
+++ b/include/linux/dma-mapping.h	2004-10-18 14:56:50 -07:00
@@ -1,6 +1,9 @@
 #ifndef _ASM_LINUX_DMA_MAPPING_H
 #define _ASM_LINUX_DMA_MAPPING_H
 
+#include <linux/device.h>
+#include <linux/err.h>
+
 /* These definitions mirror those in pci.h, so they can be used
  * interchangeably with their PCI_ counterparts */
 enum dma_data_direction {
@@ -20,6 +23,33 @@
 #define dma_sync_sg		dma_sync_sg_for_cpu
 
 extern u64 dma_get_required_mask(struct device *dev);
+
+/* flags for the coherent memory api */
+#define	DMA_MEMORY_MAP			0x01
+#define DMA_MEMORY_IO			0x02
+#define DMA_MEMORY_INCLUDES_CHILDREN	0x04
+#define DMA_MEMORY_EXCLUSIVE		0x08
+
+#ifndef ARCH_HAS_DMA_DECLARE_COHERENT_MEMORY
+static inline int
+dma_declare_coherent_memory(struct device *dev, dma_addr_t bus_addr,
+			    dma_addr_t device_addr, size_t size, int flags)
+{
+	return 0;
+}
+
+static inline void
+dma_release_declared_memory(struct device *dev)
+{
+}
+
+static inline void *
+dma_mark_declared_memory_occupied(struct device *dev,
+				  dma_addr_t device_addr, size_t size)
+{
+	return ERR_PTR(-EBUSY);
+}
+#endif
 
 #endif
 
diff -Nru a/include/linux/dqblk_xfs.h b/include/linux/dqblk_xfs.h
--- a/include/linux/dqblk_xfs.h	2004-10-18 14:56:49 -07:00
+++ b/include/linux/dqblk_xfs.h	2004-10-18 14:56:49 -07:00
@@ -1,34 +1,22 @@
 /*
- * Copyright (c) 1995-2001 Silicon Graphics, Inc.  All Rights Reserved.
+ * Copyright (c) 1995-2001,2004 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.1 of the GNU Lesser 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.
+ * 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
  *
- * 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 Lesser 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/SGIGPLNoticeExplan/
+ * Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane,
+ * Mountain View, CA 94043, USA, or: http://www.sgi.com
  */
 #ifndef _LINUX_DQBLK_XFS_H
 #define _LINUX_DQBLK_XFS_H
@@ -40,12 +28,12 @@
  */
 
 #define XQM_CMD(x)	(('X'<<8)+(x))	/* note: forms first QCMD argument */
-#define Q_XQUOTAON	XQM_CMD(0x1)	/* enable accounting/enforcement */
-#define Q_XQUOTAOFF	XQM_CMD(0x2)	/* disable accounting/enforcement */
-#define Q_XGETQUOTA	XQM_CMD(0x3)	/* get disk limits and usage */
-#define Q_XSETQLIM	XQM_CMD(0x4)	/* set disk limits */
-#define Q_XGETQSTAT	XQM_CMD(0x5)	/* get quota subsystem status */
-#define Q_XQUOTARM	XQM_CMD(0x6)	/* free disk space used by dquots */
+#define Q_XQUOTAON	XQM_CMD(1)	/* enable accounting/enforcement */
+#define Q_XQUOTAOFF	XQM_CMD(2)	/* disable accounting/enforcement */
+#define Q_XGETQUOTA	XQM_CMD(3)	/* get disk limits and usage */
+#define Q_XSETQLIM	XQM_CMD(4)	/* set disk limits */
+#define Q_XGETQSTAT	XQM_CMD(5)	/* get quota subsystem status */
+#define Q_XQUOTARM	XQM_CMD(6)	/* free disk space used by dquots */
 
 /*
  * fs_disk_quota structure:
@@ -105,15 +93,30 @@
 #define FS_DQ_TIMER_MASK	(FS_DQ_BTIMER | FS_DQ_ITIMER | FS_DQ_RTBTIMER)
 
 /*
+ * Warning counts are set in both super user's dquot and others. For others,
+ * warnings are set/cleared by the administrators (or automatically by going
+ * below the soft limit).  Superusers warning values set the warning limits
+ * for the rest.  In case these values are zero, the DQ_{F,B}WARNLIMIT values
+ * defined below are used. 
+ * These values also apply only to the d_fieldmask field for Q_XSETQLIM.
+ */
+#define FS_DQ_BWARNS	(1<<9)
+#define FS_DQ_IWARNS	(1<<10)
+#define FS_DQ_RTBWARNS	(1<<11)
+#define FS_DQ_WARNS_MASK	(FS_DQ_BWARNS | FS_DQ_IWARNS | FS_DQ_RTBWARNS)
+
+/*
  * Various flags related to quotactl(2).  Only relevant to XFS filesystems.
  */
 #define XFS_QUOTA_UDQ_ACCT	(1<<0)  /* user quota accounting */
 #define XFS_QUOTA_UDQ_ENFD	(1<<1)  /* user quota limits enforcement */
 #define XFS_QUOTA_GDQ_ACCT	(1<<2)  /* group quota accounting */
 #define XFS_QUOTA_GDQ_ENFD	(1<<3)  /* group quota limits enforcement */
+#define XFS_QUOTA_PDQ_ACCT	(1<<4)  /* project quota accounting */
+#define XFS_QUOTA_PDQ_ENFD	(1<<5)  /* project quota limits enforcement */
 
 #define XFS_USER_QUOTA		(1<<0)	/* user quota type */
-#define XFS_PROJ_QUOTA		(1<<1)	/* (IRIX) project quota type */
+#define XFS_PROJ_QUOTA		(1<<1)	/* project quota type */
 #define XFS_GROUP_QUOTA		(1<<2)	/* group quota type */
 
 /*
diff -Nru a/include/linux/efs_dir.h b/include/linux/efs_dir.h
--- a/include/linux/efs_dir.h	2004-10-18 14:56:27 -07:00
+++ b/include/linux/efs_dir.h	2004-10-18 14:56:27 -07:00
@@ -11,7 +11,7 @@
 #define EFS_DIRBSIZE		(1 << EFS_DIRBSIZE_BITS)
 
 struct efs_dentry {
-	unsigned int	inode;
+	__be32		inode;
 	unsigned char	namelen;
 	char		name[3];
 };
@@ -23,7 +23,7 @@
 #define EFS_DIRBLK_MAGIC	0xbeef	/* moo */
 
 struct efs_dir {
-	unsigned short	magic;
+	__be16	magic;
 	unsigned char	firstused;
 	unsigned char	slots;
 
diff -Nru a/include/linux/efs_fs.h b/include/linux/efs_fs.h
--- a/include/linux/efs_fs.h	2004-10-18 14:56:29 -07:00
+++ b/include/linux/efs_fs.h	2004-10-18 14:56:29 -07:00
@@ -40,11 +40,9 @@
 extern struct file_operations efs_dir_operations;
 extern struct address_space_operations efs_symlink_aops;
 
-extern int efs_fill_super(struct super_block *, void *, int);
-extern int efs_statfs(struct super_block *, struct kstatfs *);
-
 extern void efs_read_inode(struct inode *);
 extern efs_block_t efs_map_block(struct inode *, efs_block_t);
+extern int efs_get_block(struct inode *, sector_t, struct buffer_head *, int);
 
 extern struct dentry *efs_lookup(struct inode *, struct dentry *, struct nameidata *);
 extern int efs_bmap(struct inode *, int);
diff -Nru a/include/linux/efs_fs_i.h b/include/linux/efs_fs_i.h
--- a/include/linux/efs_fs_i.h	2004-10-18 14:56:28 -07:00
+++ b/include/linux/efs_fs_i.h	2004-10-18 14:56:28 -07:00
@@ -28,8 +28,8 @@
 } efs_extent;
 
 typedef struct edevs {
-	short		odev;
-	unsigned int	ndev;
+	__be16		odev;
+	__be32		ndev;
 } efs_devs;
 
 /*
@@ -37,16 +37,16 @@
  * is exactly 128 bytes long.
  */
 struct	efs_dinode {
-	u_short		di_mode;	/* mode and type of file */
-	short		di_nlink;	/* number of links to file */
-	u_short		di_uid;		/* owner's user id */
-	u_short		di_gid;		/* owner's group id */
-	int32_t		di_size;	/* number of bytes in file */
-	int32_t		di_atime;	/* time last accessed */
-	int32_t		di_mtime;	/* time last modified */
-	int32_t		di_ctime;	/* time created */
-	uint32_t	di_gen;		/* generation number */
-	short		di_numextents;	/* # of extents */
+	__be16		di_mode;	/* mode and type of file */
+	__be16		di_nlink;	/* number of links to file */
+	__be16		di_uid;		/* owner's user id */
+	__be16		di_gid;		/* owner's group id */
+	__be32		di_size;	/* number of bytes in file */
+	__be32		di_atime;	/* time last accessed */
+	__be32		di_mtime;	/* time last modified */
+	__be32		di_ctime;	/* time created */
+	__be32		di_gen;		/* generation number */
+	__be16		di_numextents;	/* # of extents */
 	u_char		di_version;	/* version of inode */
 	u_char		di_spare;	/* spare - used by AFS */
 	union di_addr {
diff -Nru a/include/linux/efs_fs_sb.h b/include/linux/efs_fs_sb.h
--- a/include/linux/efs_fs_sb.h	2004-10-18 14:56:33 -07:00
+++ b/include/linux/efs_fs_sb.h	2004-10-18 14:56:33 -07:00
@@ -23,39 +23,39 @@
 
 /* efs superblock on disk */
 struct efs_super {
-	int32_t		fs_size;        /* size of filesystem, in sectors */
-	int32_t		fs_firstcg;     /* bb offset to first cg */
-	int32_t		fs_cgfsize;     /* size of cylinder group in bb's */
-	short		fs_cgisize;     /* bb's of inodes per cylinder group */
-	short		fs_sectors;     /* sectors per track */
-	short		fs_heads;       /* heads per cylinder */
-	short		fs_ncg;         /* # of cylinder groups in filesystem */
-	short		fs_dirty;       /* fs needs to be fsck'd */
-	int32_t		fs_time;        /* last super-block update */
-	int32_t		fs_magic;       /* magic number */
+	__be32		fs_size;        /* size of filesystem, in sectors */
+	__be32		fs_firstcg;     /* bb offset to first cg */
+	__be32		fs_cgfsize;     /* size of cylinder group in bb's */
+	__be16		fs_cgisize;     /* bb's of inodes per cylinder group */
+	__be16		fs_sectors;     /* sectors per track */
+	__be16		fs_heads;       /* heads per cylinder */
+	__be16		fs_ncg;         /* # of cylinder groups in filesystem */
+	__be16		fs_dirty;       /* fs needs to be fsck'd */
+	__be32		fs_time;        /* last super-block update */
+	__be32		fs_magic;       /* magic number */
 	char		fs_fname[6];    /* file system name */
 	char		fs_fpack[6];    /* file system pack name */
-	int32_t		fs_bmsize;      /* size of bitmap in bytes */
-	int32_t		fs_tfree;       /* total free data blocks */
-	int32_t		fs_tinode;      /* total free inodes */
-	int32_t		fs_bmblock;     /* bitmap location. */
-	int32_t		fs_replsb;      /* Location of replicated superblock. */
-	int32_t		fs_lastialloc;  /* last allocated inode */
+	__be32		fs_bmsize;      /* size of bitmap in bytes */
+	__be32		fs_tfree;       /* total free data blocks */
+	__be32		fs_tinode;      /* total free inodes */
+	__be32		fs_bmblock;     /* bitmap location. */
+	__be32		fs_replsb;      /* Location of replicated superblock. */
+	__be32		fs_lastialloc;  /* last allocated inode */
 	char		fs_spare[20];   /* space for expansion - MUST BE ZERO */
-	int32_t		fs_checksum;    /* checksum of volume portion of fs */
+	__be32		fs_checksum;    /* checksum of volume portion of fs */
 };
 
 /* efs superblock information in memory */
 struct efs_sb_info {
-	int32_t	fs_magic;	/* superblock magic number */
-	int32_t	fs_start;	/* first block of filesystem */
-	int32_t	first_block;	/* first data block in filesystem */
-	int32_t	total_blocks;	/* total number of blocks in filesystem */
-	int32_t	group_size;	/* # of blocks a group consists of */ 
-	int32_t	data_free;	/* # of free data blocks */
-	int32_t	inode_free;	/* # of free inodes */
-	short	inode_blocks;	/* # of blocks used for inodes in every grp */
-	short	total_groups;	/* # of groups */
+	__u32	fs_magic;	/* superblock magic number */
+	__u32	fs_start;	/* first block of filesystem */
+	__u32	first_block;	/* first data block in filesystem */
+	__u32	total_blocks;	/* total number of blocks in filesystem */
+	__u32	group_size;	/* # of blocks a group consists of */ 
+	__u32	data_free;	/* # of free data blocks */
+	__u32	inode_free;	/* # of free inodes */
+	__u16	inode_blocks;	/* # of blocks used for inodes in every grp */
+	__u16	total_groups;	/* # of groups */
 };
 
 #endif /* __EFS_FS_SB_H__ */
diff -Nru a/include/linux/efs_vh.h b/include/linux/efs_vh.h
--- a/include/linux/efs_vh.h	2004-10-18 14:56:28 -07:00
+++ b/include/linux/efs_vh.h	2004-10-18 14:56:28 -07:00
@@ -17,26 +17,26 @@
 
 struct volume_directory {
 	char	vd_name[VDNAMESIZE];	/* name */
-	int	vd_lbn;			/* logical block number */
-	int	vd_nbytes;		/* file length in bytes */
+	__be32	vd_lbn;			/* logical block number */
+	__be32	vd_nbytes;		/* file length in bytes */
 };
 
 struct partition_table {	/* one per logical partition */
-	int	pt_nblks;	/* # of logical blks in partition */
-	int	pt_firstlbn;	/* first lbn of partition */
-	int	pt_type;	/* use of partition */
+	__be32	pt_nblks;	/* # of logical blks in partition */
+	__be32	pt_firstlbn;	/* first lbn of partition */
+	__be32	pt_type;	/* use of partition */
 };
 
 struct volume_header {
-	int	vh_magic;			/* identifies volume header */
-	short	vh_rootpt;			/* root partition number */
-	short	vh_swappt;			/* swap partition number */
+	__be32	vh_magic;			/* identifies volume header */
+	__be16	vh_rootpt;			/* root partition number */
+	__be16	vh_swappt;			/* swap partition number */
 	char	vh_bootfile[BFNAMESIZE];	/* name of file to boot */
 	char	pad[48];			/* device param space */
 	struct volume_directory vh_vd[NVDIR];	/* other vol hdr contents */
 	struct partition_table  vh_pt[NPARTAB];	/* device partition layout */
-	int	vh_csum;			/* volume header checksum */
-	int	vh_fill;			/* fill out to 512 bytes */
+	__be32	vh_csum;			/* volume header checksum */
+	__be32	vh_fill;			/* fill out to 512 bytes */
 };
 
 /* partition type sysv is used for EFS format CD-ROM partitions */
diff -Nru a/include/linux/elf.h b/include/linux/elf.h
--- a/include/linux/elf.h	2004-10-18 14:56:13 -07:00
+++ b/include/linux/elf.h	2004-10-18 14:56:13 -07:00
@@ -88,7 +88,9 @@
 
 #define EM_V850		87	/* NEC v850 */
 
-#define EM_H8_300       46      /* Hitachi H8/300,300H,H8S */
+#define EM_M32R		88	/* Renesas M32R */
+
+#define EM_H8_300       46      /* Renesas H8/300,300H,H8S */
 
 /*
  * This is an interim value that we will use until the committee comes
@@ -98,6 +100,9 @@
 
 /* Bogus old v850 magic number, used by old tools.  */
 #define EM_CYGNUS_V850	0x9080
+
+/* Bogus old m32r magic number, used by old tools.  */
+#define EM_CYGNUS_M32R	0x9041
 
 /*
  * This is the old interim value for S/390 architecture
diff -Nru a/include/linux/err.h b/include/linux/err.h
--- a/include/linux/err.h	2004-10-18 14:57:03 -07:00
+++ b/include/linux/err.h	2004-10-18 14:57:03 -07:00
@@ -1,6 +1,8 @@
 #ifndef _LINUX_ERR_H
 #define _LINUX_ERR_H
 
+#include <linux/compiler.h>
+
 #include <asm/errno.h>
 
 /*
@@ -23,7 +25,7 @@
 
 static inline long IS_ERR(const void *ptr)
 {
-	return (unsigned long)ptr > (unsigned long)-1000L;
+	return unlikely((unsigned long)ptr > (unsigned long)-1000L);
 }
 
 #endif /* _LINUX_ERR_H */
diff -Nru a/include/linux/errno.h b/include/linux/errno.h
--- a/include/linux/errno.h	2004-10-18 14:56:49 -07:00
+++ b/include/linux/errno.h	2004-10-18 14:56:49 -07:00
@@ -22,6 +22,7 @@
 #define EBADTYPE	527	/* Type not supported by server */
 #define EJUKEBOX	528	/* Request initiated, but will not complete before timeout */
 #define EIOCBQUEUED	529	/* iocb queued, will get completion event */
+#define EIOCBRETRY	530	/* iocb queued, will trigger a retry */
 
 #endif
 
diff -Nru a/include/linux/ext2_fs.h b/include/linux/ext2_fs.h
--- a/include/linux/ext2_fs.h	2004-10-18 14:55:55 -07:00
+++ b/include/linux/ext2_fs.h	2004-10-18 14:55:55 -07:00
@@ -135,14 +135,14 @@
  */
 struct ext2_group_desc
 {
-	__u32	bg_block_bitmap;		/* Blocks bitmap block */
-	__u32	bg_inode_bitmap;		/* Inodes bitmap block */
-	__u32	bg_inode_table;		/* Inodes table block */
-	__u16	bg_free_blocks_count;	/* Free blocks count */
-	__u16	bg_free_inodes_count;	/* Free inodes count */
-	__u16	bg_used_dirs_count;	/* Directories count */
-	__u16	bg_pad;
-	__u32	bg_reserved[3];
+	__le32	bg_block_bitmap;		/* Blocks bitmap block */
+	__le32	bg_inode_bitmap;		/* Inodes bitmap block */
+	__le32	bg_inode_table;		/* Inodes table block */
+	__le16	bg_free_blocks_count;	/* Free blocks count */
+	__le16	bg_free_inodes_count;	/* Free inodes count */
+	__le16	bg_used_dirs_count;	/* Directories count */
+	__le16	bg_pad;
+	__le32	bg_reserved[3];
 };
 
 /*
@@ -209,49 +209,49 @@
  * Structure of an inode on the disk
  */
 struct ext2_inode {
-	__u16	i_mode;		/* File mode */
-	__u16	i_uid;		/* Low 16 bits of Owner Uid */
-	__u32	i_size;		/* Size in bytes */
-	__u32	i_atime;	/* Access time */
-	__u32	i_ctime;	/* Creation time */
-	__u32	i_mtime;	/* Modification time */
-	__u32	i_dtime;	/* Deletion Time */
-	__u16	i_gid;		/* Low 16 bits of Group Id */
-	__u16	i_links_count;	/* Links count */
-	__u32	i_blocks;	/* Blocks count */
-	__u32	i_flags;	/* File flags */
+	__le16	i_mode;		/* File mode */
+	__le16	i_uid;		/* Low 16 bits of Owner Uid */
+	__le32	i_size;		/* Size in bytes */
+	__le32	i_atime;	/* Access time */
+	__le32	i_ctime;	/* Creation time */
+	__le32	i_mtime;	/* Modification time */
+	__le32	i_dtime;	/* Deletion Time */
+	__le16	i_gid;		/* Low 16 bits of Group Id */
+	__le16	i_links_count;	/* Links count */
+	__le32	i_blocks;	/* Blocks count */
+	__le32	i_flags;	/* File flags */
 	union {
 		struct {
-			__u32  l_i_reserved1;
+			__le32  l_i_reserved1;
 		} linux1;
 		struct {
-			__u32  h_i_translator;
+			__le32  h_i_translator;
 		} hurd1;
 		struct {
-			__u32  m_i_reserved1;
+			__le32  m_i_reserved1;
 		} masix1;
 	} osd1;				/* OS dependent 1 */
-	__u32	i_block[EXT2_N_BLOCKS];/* Pointers to blocks */
-	__u32	i_generation;	/* File version (for NFS) */
-	__u32	i_file_acl;	/* File ACL */
-	__u32	i_dir_acl;	/* Directory ACL */
-	__u32	i_faddr;	/* Fragment address */
+	__le32	i_block[EXT2_N_BLOCKS];/* Pointers to blocks */
+	__le32	i_generation;	/* File version (for NFS) */
+	__le32	i_file_acl;	/* File ACL */
+	__le32	i_dir_acl;	/* Directory ACL */
+	__le32	i_faddr;	/* Fragment address */
 	union {
 		struct {
 			__u8	l_i_frag;	/* Fragment number */
 			__u8	l_i_fsize;	/* Fragment size */
 			__u16	i_pad1;
-			__u16	l_i_uid_high;	/* these 2 fields    */
-			__u16	l_i_gid_high;	/* were reserved2[0] */
+			__le16	l_i_uid_high;	/* these 2 fields    */
+			__le16	l_i_gid_high;	/* were reserved2[0] */
 			__u32	l_i_reserved2;
 		} linux2;
 		struct {
 			__u8	h_i_frag;	/* Fragment number */
 			__u8	h_i_fsize;	/* Fragment size */
-			__u16	h_i_mode_high;
-			__u16	h_i_uid_high;
-			__u16	h_i_gid_high;
-			__u32	h_i_author;
+			__le16	h_i_mode_high;
+			__le16	h_i_uid_high;
+			__le16	h_i_gid_high;
+			__le32	h_i_author;
 		} hurd2;
 		struct {
 			__u8	m_i_frag;	/* Fragment number */
@@ -335,31 +335,31 @@
  * Structure of the super block
  */
 struct ext2_super_block {
-	__u32	s_inodes_count;		/* Inodes count */
-	__u32	s_blocks_count;		/* Blocks count */
-	__u32	s_r_blocks_count;	/* Reserved blocks count */
-	__u32	s_free_blocks_count;	/* Free blocks count */
-	__u32	s_free_inodes_count;	/* Free inodes count */
-	__u32	s_first_data_block;	/* First Data Block */
-	__u32	s_log_block_size;	/* Block size */
-	__s32	s_log_frag_size;	/* Fragment size */
-	__u32	s_blocks_per_group;	/* # Blocks per group */
-	__u32	s_frags_per_group;	/* # Fragments per group */
-	__u32	s_inodes_per_group;	/* # Inodes per group */
-	__u32	s_mtime;		/* Mount time */
-	__u32	s_wtime;		/* Write time */
-	__u16	s_mnt_count;		/* Mount count */
-	__s16	s_max_mnt_count;	/* Maximal mount count */
-	__u16	s_magic;		/* Magic signature */
-	__u16	s_state;		/* File system state */
-	__u16	s_errors;		/* Behaviour when detecting errors */
-	__u16	s_minor_rev_level; 	/* minor revision level */
-	__u32	s_lastcheck;		/* time of last check */
-	__u32	s_checkinterval;	/* max. time between checks */
-	__u32	s_creator_os;		/* OS */
-	__u32	s_rev_level;		/* Revision level */
-	__u16	s_def_resuid;		/* Default uid for reserved blocks */
-	__u16	s_def_resgid;		/* Default gid for reserved blocks */
+	__le32	s_inodes_count;		/* Inodes count */
+	__le32	s_blocks_count;		/* Blocks count */
+	__le32	s_r_blocks_count;	/* Reserved blocks count */
+	__le32	s_free_blocks_count;	/* Free blocks count */
+	__le32	s_free_inodes_count;	/* Free inodes count */
+	__le32	s_first_data_block;	/* First Data Block */
+	__le32	s_log_block_size;	/* Block size */
+	__le32	s_log_frag_size;	/* Fragment size */
+	__le32	s_blocks_per_group;	/* # Blocks per group */
+	__le32	s_frags_per_group;	/* # Fragments per group */
+	__le32	s_inodes_per_group;	/* # Inodes per group */
+	__le32	s_mtime;		/* Mount time */
+	__le32	s_wtime;		/* Write time */
+	__le16	s_mnt_count;		/* Mount count */
+	__le16	s_max_mnt_count;	/* Maximal mount count */
+	__le16	s_magic;		/* Magic signature */
+	__le16	s_state;		/* File system state */
+	__le16	s_errors;		/* Behaviour when detecting errors */
+	__le16	s_minor_rev_level; 	/* minor revision level */
+	__le32	s_lastcheck;		/* time of last check */
+	__le32	s_checkinterval;	/* max. time between checks */
+	__le32	s_creator_os;		/* OS */
+	__le32	s_rev_level;		/* Revision level */
+	__le16	s_def_resuid;		/* Default uid for reserved blocks */
+	__le16	s_def_resgid;		/* Default gid for reserved blocks */
 	/*
 	 * These fields are for EXT2_DYNAMIC_REV superblocks only.
 	 *
@@ -373,16 +373,16 @@
 	 * feature set, it must abort and not try to meddle with
 	 * things it doesn't understand...
 	 */
-	__u32	s_first_ino; 		/* First non-reserved inode */
-	__u16   s_inode_size; 		/* size of inode structure */
-	__u16	s_block_group_nr; 	/* block group # of this superblock */
-	__u32	s_feature_compat; 	/* compatible feature set */
-	__u32	s_feature_incompat; 	/* incompatible feature set */
-	__u32	s_feature_ro_compat; 	/* readonly-compatible feature set */
+	__le32	s_first_ino; 		/* First non-reserved inode */
+	__le16   s_inode_size; 		/* size of inode structure */
+	__le16	s_block_group_nr; 	/* block group # of this superblock */
+	__le32	s_feature_compat; 	/* compatible feature set */
+	__le32	s_feature_incompat; 	/* incompatible feature set */
+	__le32	s_feature_ro_compat; 	/* readonly-compatible feature set */
 	__u8	s_uuid[16];		/* 128-bit uuid for volume */
 	char	s_volume_name[16]; 	/* volume name */
 	char	s_last_mounted[64]; 	/* directory where last mounted */
-	__u32	s_algorithm_usage_bitmap; /* For compression */
+	__le32	s_algorithm_usage_bitmap; /* For compression */
 	/*
 	 * Performance hints.  Directory preallocation should only
 	 * happen if the EXT2_COMPAT_PREALLOC flag is on.
@@ -401,8 +401,8 @@
 	__u8	s_def_hash_version;	/* Default hash version to use */
 	__u8	s_reserved_char_pad;
 	__u16	s_reserved_word_pad;
-	__u32	s_default_mount_opts;
- 	__u32	s_first_meta_bg; 	/* First metablock block group */
+	__le32	s_default_mount_opts;
+ 	__le32	s_first_meta_bg; 	/* First metablock block group */
 	__u32	s_reserved[190];	/* Padding to the end of the block */
 };
 
@@ -504,9 +504,9 @@
 #define EXT2_NAME_LEN 255
 
 struct ext2_dir_entry {
-	__u32	inode;			/* Inode number */
-	__u16	rec_len;		/* Directory entry length */
-	__u16	name_len;		/* Name length */
+	__le32	inode;			/* Inode number */
+	__le16	rec_len;		/* Directory entry length */
+	__le16	name_len;		/* Name length */
 	char	name[EXT2_NAME_LEN];	/* File name */
 };
 
@@ -517,8 +517,8 @@
  * file_type field.
  */
 struct ext2_dir_entry_2 {
-	__u32	inode;			/* Inode number */
-	__u16	rec_len;		/* Directory entry length */
+	__le32	inode;			/* Inode number */
+	__le16	rec_len;		/* Directory entry length */
 	__u8	name_len;		/* Name length */
 	__u8	file_type;
 	char	name[EXT2_NAME_LEN];	/* File name */
diff -Nru a/include/linux/ext3_fs.h b/include/linux/ext3_fs.h
--- a/include/linux/ext3_fs.h	2004-10-18 14:56:33 -07:00
+++ b/include/linux/ext3_fs.h	2004-10-18 14:56:33 -07:00
@@ -129,14 +129,14 @@
  */
 struct ext3_group_desc
 {
-	__u32	bg_block_bitmap;		/* Blocks bitmap block */
-	__u32	bg_inode_bitmap;		/* Inodes bitmap block */
-	__u32	bg_inode_table;		/* Inodes table block */
-	__u16	bg_free_blocks_count;	/* Free blocks count */
-	__u16	bg_free_inodes_count;	/* Free inodes count */
-	__u16	bg_used_dirs_count;	/* Directories count */
+	__le32	bg_block_bitmap;		/* Blocks bitmap block */
+	__le32	bg_inode_bitmap;		/* Inodes bitmap block */
+	__le32	bg_inode_table;		/* Inodes table block */
+	__le16	bg_free_blocks_count;	/* Free blocks count */
+	__le16	bg_free_inodes_count;	/* Free inodes count */
+	__le16	bg_used_dirs_count;	/* Directories count */
 	__u16	bg_pad;
-	__u32	bg_reserved[3];
+	__le32	bg_reserved[3];
 };
 
 /*
@@ -213,17 +213,17 @@
  * Structure of an inode on the disk
  */
 struct ext3_inode {
-	__u16	i_mode;		/* File mode */
-	__u16	i_uid;		/* Low 16 bits of Owner Uid */
-	__u32	i_size;		/* Size in bytes */
-	__u32	i_atime;	/* Access time */
-	__u32	i_ctime;	/* Creation time */
-	__u32	i_mtime;	/* Modification time */
-	__u32	i_dtime;	/* Deletion Time */
-	__u16	i_gid;		/* Low 16 bits of Group Id */
-	__u16	i_links_count;	/* Links count */
-	__u32	i_blocks;	/* Blocks count */
-	__u32	i_flags;	/* File flags */
+	__le16	i_mode;		/* File mode */
+	__le16	i_uid;		/* Low 16 bits of Owner Uid */
+	__le32	i_size;		/* Size in bytes */
+	__le32	i_atime;	/* Access time */
+	__le32	i_ctime;	/* Creation time */
+	__le32	i_mtime;	/* Modification time */
+	__le32	i_dtime;	/* Deletion Time */
+	__le16	i_gid;		/* Low 16 bits of Group Id */
+	__le16	i_links_count;	/* Links count */
+	__le32	i_blocks;	/* Blocks count */
+	__le32	i_flags;	/* File flags */
 	union {
 		struct {
 			__u32  l_i_reserved1;
@@ -235,18 +235,18 @@
 			__u32  m_i_reserved1;
 		} masix1;
 	} osd1;				/* OS dependent 1 */
-	__u32	i_block[EXT3_N_BLOCKS];/* Pointers to blocks */
-	__u32	i_generation;	/* File version (for NFS) */
-	__u32	i_file_acl;	/* File ACL */
-	__u32	i_dir_acl;	/* Directory ACL */
-	__u32	i_faddr;	/* Fragment address */
+	__le32	i_block[EXT3_N_BLOCKS];/* Pointers to blocks */
+	__le32	i_generation;	/* File version (for NFS) */
+	__le32	i_file_acl;	/* File ACL */
+	__le32	i_dir_acl;	/* Directory ACL */
+	__le32	i_faddr;	/* Fragment address */
 	union {
 		struct {
 			__u8	l_i_frag;	/* Fragment number */
 			__u8	l_i_fsize;	/* Fragment size */
 			__u16	i_pad1;
-			__u16	l_i_uid_high;	/* these 2 fields    */
-			__u16	l_i_gid_high;	/* were reserved2[0] */
+			__le16	l_i_uid_high;	/* these 2 fields    */
+			__le16	l_i_gid_high;	/* were reserved2[0] */
 			__u32	l_i_reserved2;
 		} linux2;
 		struct {
@@ -324,6 +324,7 @@
 #define EXT3_MOUNT_NO_UID32		0x2000  /* Disable 32-bit UIDs */
 #define EXT3_MOUNT_XATTR_USER		0x4000	/* Extended user attributes */
 #define EXT3_MOUNT_POSIX_ACL		0x8000	/* POSIX Access Control Lists */
+#define EXT3_MOUNT_BARRIER		0x10000 /* Use block barriers */
 
 /* Compatibility, for having both ext2_fs.h and ext3_fs.h included at once */
 #ifndef _LINUX_EXT2_FS_H
@@ -363,31 +364,31 @@
  * Structure of the super block
  */
 struct ext3_super_block {
-/*00*/	__u32	s_inodes_count;		/* Inodes count */
-	__u32	s_blocks_count;		/* Blocks count */
-	__u32	s_r_blocks_count;	/* Reserved blocks count */
-	__u32	s_free_blocks_count;	/* Free blocks count */
-/*10*/	__u32	s_free_inodes_count;	/* Free inodes count */
-	__u32	s_first_data_block;	/* First Data Block */
-	__u32	s_log_block_size;	/* Block size */
-	__s32	s_log_frag_size;	/* Fragment size */
-/*20*/	__u32	s_blocks_per_group;	/* # Blocks per group */
-	__u32	s_frags_per_group;	/* # Fragments per group */
-	__u32	s_inodes_per_group;	/* # Inodes per group */
-	__u32	s_mtime;		/* Mount time */
-/*30*/	__u32	s_wtime;		/* Write time */
-	__u16	s_mnt_count;		/* Mount count */
-	__s16	s_max_mnt_count;	/* Maximal mount count */
-	__u16	s_magic;		/* Magic signature */
-	__u16	s_state;		/* File system state */
-	__u16	s_errors;		/* Behaviour when detecting errors */
-	__u16	s_minor_rev_level;	/* minor revision level */
-/*40*/	__u32	s_lastcheck;		/* time of last check */
-	__u32	s_checkinterval;	/* max. time between checks */
-	__u32	s_creator_os;		/* OS */
-	__u32	s_rev_level;		/* Revision level */
-/*50*/	__u16	s_def_resuid;		/* Default uid for reserved blocks */
-	__u16	s_def_resgid;		/* Default gid for reserved blocks */
+/*00*/	__le32	s_inodes_count;		/* Inodes count */
+	__le32	s_blocks_count;		/* Blocks count */
+	__le32	s_r_blocks_count;	/* Reserved blocks count */
+	__le32	s_free_blocks_count;	/* Free blocks count */
+/*10*/	__le32	s_free_inodes_count;	/* Free inodes count */
+	__le32	s_first_data_block;	/* First Data Block */
+	__le32	s_log_block_size;	/* Block size */
+	__le32	s_log_frag_size;	/* Fragment size */
+/*20*/	__le32	s_blocks_per_group;	/* # Blocks per group */
+	__le32	s_frags_per_group;	/* # Fragments per group */
+	__le32	s_inodes_per_group;	/* # Inodes per group */
+	__le32	s_mtime;		/* Mount time */
+/*30*/	__le32	s_wtime;		/* Write time */
+	__le16	s_mnt_count;		/* Mount count */
+	__le16	s_max_mnt_count;	/* Maximal mount count */
+	__le16	s_magic;		/* Magic signature */
+	__le16	s_state;		/* File system state */
+	__le16	s_errors;		/* Behaviour when detecting errors */
+	__le16	s_minor_rev_level;	/* minor revision level */
+/*40*/	__le32	s_lastcheck;		/* time of last check */
+	__le32	s_checkinterval;	/* max. time between checks */
+	__le32	s_creator_os;		/* OS */
+	__le32	s_rev_level;		/* Revision level */
+/*50*/	__le16	s_def_resuid;		/* Default uid for reserved blocks */
+	__le16	s_def_resgid;		/* Default gid for reserved blocks */
 	/*
 	 * These fields are for EXT3_DYNAMIC_REV superblocks only.
 	 *
@@ -401,16 +402,16 @@
 	 * feature set, it must abort and not try to meddle with
 	 * things it doesn't understand...
 	 */
-	__u32	s_first_ino;		/* First non-reserved inode */
-	__u16   s_inode_size;		/* size of inode structure */
-	__u16	s_block_group_nr;	/* block group # of this superblock */
-	__u32	s_feature_compat;	/* compatible feature set */
-/*60*/	__u32	s_feature_incompat;	/* incompatible feature set */
-	__u32	s_feature_ro_compat;	/* readonly-compatible feature set */
+	__le32	s_first_ino;		/* First non-reserved inode */
+	__le16   s_inode_size;		/* size of inode structure */
+	__le16	s_block_group_nr;	/* block group # of this superblock */
+	__le32	s_feature_compat;	/* compatible feature set */
+/*60*/	__le32	s_feature_incompat;	/* incompatible feature set */
+	__le32	s_feature_ro_compat;	/* readonly-compatible feature set */
 /*68*/	__u8	s_uuid[16];		/* 128-bit uuid for volume */
 /*78*/	char	s_volume_name[16];	/* volume name */
 /*88*/	char	s_last_mounted[64];	/* directory where last mounted */
-/*C8*/	__u32	s_algorithm_usage_bitmap; /* For compression */
+/*C8*/	__le32	s_algorithm_usage_bitmap; /* For compression */
 	/*
 	 * Performance hints.  Directory preallocation should only
 	 * happen if the EXT3_FEATURE_COMPAT_DIR_PREALLOC flag is on.
@@ -422,15 +423,15 @@
 	 * Journaling support valid if EXT3_FEATURE_COMPAT_HAS_JOURNAL set.
 	 */
 /*D0*/	__u8	s_journal_uuid[16];	/* uuid of journal superblock */
-/*E0*/	__u32	s_journal_inum;		/* inode number of journal file */
-	__u32	s_journal_dev;		/* device number of journal file */
-	__u32	s_last_orphan;		/* start of list of inodes to delete */
-	__u32	s_hash_seed[4];		/* HTREE hash seed */
+/*E0*/	__le32	s_journal_inum;		/* inode number of journal file */
+	__le32	s_journal_dev;		/* device number of journal file */
+	__le32	s_last_orphan;		/* start of list of inodes to delete */
+	__le32	s_hash_seed[4];		/* HTREE hash seed */
 	__u8	s_def_hash_version;	/* Default hash version to use */
 	__u8	s_reserved_char_pad;
 	__u16	s_reserved_word_pad;
-	__u32	s_default_mount_opts;
-	__u32	s_first_meta_bg; 	/* First metablock block group */
+	__le32	s_default_mount_opts;
+	__le32	s_first_meta_bg; 	/* First metablock block group */
 	__u32	s_reserved[190];	/* Padding to the end of the block */
 };
 
@@ -545,9 +546,9 @@
 #define EXT3_NAME_LEN 255
 
 struct ext3_dir_entry {
-	__u32	inode;			/* Inode number */
-	__u16	rec_len;		/* Directory entry length */
-	__u16	name_len;		/* Name length */
+	__le32	inode;			/* Inode number */
+	__le16	rec_len;		/* Directory entry length */
+	__le16	name_len;		/* Name length */
 	char	name[EXT3_NAME_LEN];	/* File name */
 };
 
@@ -558,8 +559,8 @@
  * file_type field.
  */
 struct ext3_dir_entry_2 {
-	__u32	inode;			/* Inode number */
-	__u16	rec_len;		/* Directory entry length */
+	__le32	inode;			/* Inode number */
+	__le16	rec_len;		/* Directory entry length */
 	__u8	name_len;		/* Name length */
 	__u8	file_type;
 	char	name[EXT3_NAME_LEN];	/* File name */
@@ -723,7 +724,7 @@
 extern struct buffer_head * ext3_bread (handle_t *, struct inode *, int, int, int *);
 
 extern void ext3_read_inode (struct inode *);
-extern void ext3_write_inode (struct inode *, int);
+extern int  ext3_write_inode (struct inode *, int);
 extern int  ext3_setattr (struct dentry *, struct iattr *);
 extern void ext3_put_inode (struct inode *);
 extern void ext3_delete_inode (struct inode *);
diff -Nru a/include/linux/ext3_fs_i.h b/include/linux/ext3_fs_i.h
--- a/include/linux/ext3_fs_i.h	2004-10-18 14:55:54 -07:00
+++ b/include/linux/ext3_fs_i.h	2004-10-18 14:55:54 -07:00
@@ -22,7 +22,7 @@
  * second extended file system inode data in memory
  */
 struct ext3_inode_info {
-	__u32	i_data[15];
+	__le32	i_data[15];	/* unconverted */
 	__u32	i_flags;
 #ifdef EXT3_FRAGMENTS
 	__u32	i_faddr;
diff -Nru a/include/linux/fb.h b/include/linux/fb.h
--- a/include/linux/fb.h	2004-10-18 14:56:28 -07:00
+++ b/include/linux/fb.h	2004-10-18 14:56:28 -07:00
@@ -158,6 +158,7 @@
 #define FB_CHANGE_CMAP_VBL     32	/* change colormap on vbl	*/
 #define FB_ACTIVATE_ALL	       64	/* change all VCs on this fb	*/
 #define FB_ACTIVATE_FORCE     128	/* force apply even when no change*/
+#define FB_ACTIVATE_INV_MODE  256       /* invalidate videomode */
 
 #define FB_ACCELF_TEXT		1	/* (OBSOLETE) see fb_info.flags and vc_mode */
 
@@ -241,73 +242,6 @@
 #define VESA_HSYNC_SUSPEND      2
 #define VESA_POWERDOWN          3
 
-/* Definitions below are used in the parsed monitor specs */
-#define FB_DPMS_ACTIVE_OFF	1
-#define FB_DPMS_SUSPEND		2
-#define FB_DPMS_STANDBY		4
-
-#define FB_DISP_DDI		1
-#define FB_DISP_ANA_700_300	2
-#define FB_DISP_ANA_714_286	4
-#define FB_DISP_ANA_1000_400	8
-#define FB_DISP_ANA_700_000	16
-
-#define FB_DISP_MONO		32
-#define FB_DISP_RGB		64
-#define FB_DISP_MULTI		128
-#define FB_DISP_UNKNOWN		256
-
-#define FB_SIGNAL_NONE		0
-#define FB_SIGNAL_BLANK_BLANK	1
-#define FB_SIGNAL_SEPARATE	2
-#define FB_SIGNAL_COMPOSITE	4
-#define FB_SIGNAL_SYNC_ON_GREEN	8
-#define FB_SIGNAL_SERRATION_ON	16
-
-#define FB_MISC_PRIM_COLOR	1
-#define FB_MISC_1ST_DETAIL	2	/* First Detailed Timing is preferred */
-
-struct fb_chroma {
-	__u32 redx;	/* in fraction of 1024 */
-	__u32 greenx;
-	__u32 bluex;
-	__u32 whitex;
-	__u32 redy;
-	__u32 greeny;
-	__u32 bluey;
-	__u32 whitey;
-};
-
-struct fb_monspecs {
-	struct fb_chroma chroma;
-	struct fb_videomode *modedb;	/* mode database */
-	__u8  manufacturer[4];		/* Manufacturer */
-	__u8  monitor[14];		/* Monitor String */
-	__u8  serial_no[14];		/* Serial Number */
-	__u8  ascii[14];		/* ? */
-	__u32 modedb_len;		/* mode database length */
-	__u32 model;			/* Monitor Model */
-	__u32 serial;			/* Serial Number - Integer */
-	__u32 year;			/* Year manufactured */
-	__u32 week;			/* Week Manufactured */
-	__u32 hfmin;			/* hfreq lower limit (Hz) */
-	__u32 hfmax;			/* hfreq upper limit (Hz) */
-	__u32 dclkmin;			/* pixelclock lower limit (Hz) */
-	__u32 dclkmax;			/* pixelclock upper limit (Hz) */
-	__u16 input;			/* display type - see FB_DISP_* */
-	__u16 dpms;			/* DPMS support - see FB_DPMS_ */
-	__u16 signal;			/* Signal Type - see FB_SIGNAL_* */
-	__u16 vfmin;			/* vfreq lower limit (Hz) */
-	__u16 vfmax;			/* vfreq upper limit (Hz) */
-	__u16 gamma;			/* Gamma - in fractions of 100 */
-	__u16 gtf	: 1;		/* supports GTF */
-	__u16 misc;			/* Misc flags - see FB_MISC_* */
-	__u8  version;			/* EDID version... */
-	__u8  revision;			/* ...and revision */
-	__u8  max_x;			/* Maximum horizontal size (cm) */
-	__u8  max_y;			/* Maximum vertical size (cm) */
-};
-
 #define FB_VBLANK_VBLANKING	0x001	/* currently in a vertical blank */
 #define FB_VBLANK_HBLANKING	0x002	/* currently in a horizontal blank */
 #define FB_VBLANK_HAVE_VBLANK	0x004	/* vertical blanks can be detected */
@@ -383,6 +317,8 @@
 	const char *mask;	/* cursor mask bits */
 	struct fbcurpos hot;	/* cursor hot spot */
 	struct fb_image	image;	/* Cursor image */
+/* all fields below are for fbcon use only */
+	char  *data;             /* copy of bitmap */
 };
 
 #ifdef __KERNEL__
@@ -394,6 +330,7 @@
 #include <linux/workqueue.h>
 #include <linux/devfs_fs_kernel.h>
 #include <linux/notifier.h>
+#include <linux/list.h>
 #include <asm/io.h>
 
 struct vm_area_struct;
@@ -401,6 +338,72 @@
 struct device;
 struct file;
 
+/* Definitions below are used in the parsed monitor specs */
+#define FB_DPMS_ACTIVE_OFF	1
+#define FB_DPMS_SUSPEND		2
+#define FB_DPMS_STANDBY		4
+
+#define FB_DISP_DDI		1
+#define FB_DISP_ANA_700_300	2
+#define FB_DISP_ANA_714_286	4
+#define FB_DISP_ANA_1000_400	8
+#define FB_DISP_ANA_700_000	16
+
+#define FB_DISP_MONO		32
+#define FB_DISP_RGB		64
+#define FB_DISP_MULTI		128
+#define FB_DISP_UNKNOWN		256
+
+#define FB_SIGNAL_NONE		0
+#define FB_SIGNAL_BLANK_BLANK	1
+#define FB_SIGNAL_SEPARATE	2
+#define FB_SIGNAL_COMPOSITE	4
+#define FB_SIGNAL_SYNC_ON_GREEN	8
+#define FB_SIGNAL_SERRATION_ON	16
+
+#define FB_MISC_PRIM_COLOR	1
+#define FB_MISC_1ST_DETAIL	2	/* First Detailed Timing is preferred */
+struct fb_chroma {
+	__u32 redx;	/* in fraction of 1024 */
+	__u32 greenx;
+	__u32 bluex;
+	__u32 whitex;
+	__u32 redy;
+	__u32 greeny;
+	__u32 bluey;
+	__u32 whitey;
+};
+
+struct fb_monspecs {
+	struct fb_chroma chroma;
+	struct fb_videomode *modedb;	/* mode database */
+	__u8  manufacturer[4];		/* Manufacturer */
+	__u8  monitor[14];		/* Monitor String */
+	__u8  serial_no[14];		/* Serial Number */
+	__u8  ascii[14];		/* ? */
+	__u32 modedb_len;		/* mode database length */
+	__u32 model;			/* Monitor Model */
+	__u32 serial;			/* Serial Number - Integer */
+	__u32 year;			/* Year manufactured */
+	__u32 week;			/* Week Manufactured */
+	__u32 hfmin;			/* hfreq lower limit (Hz) */
+	__u32 hfmax;			/* hfreq upper limit (Hz) */
+	__u32 dclkmin;			/* pixelclock lower limit (Hz) */
+	__u32 dclkmax;			/* pixelclock upper limit (Hz) */
+	__u16 input;			/* display type - see FB_DISP_* */
+	__u16 dpms;			/* DPMS support - see FB_DPMS_ */
+	__u16 signal;			/* Signal Type - see FB_SIGNAL_* */
+	__u16 vfmin;			/* vfreq lower limit (Hz) */
+	__u16 vfmax;			/* vfreq upper limit (Hz) */
+	__u16 gamma;			/* Gamma - in fractions of 100 */
+	__u16 gtf	: 1;		/* supports GTF */
+	__u16 misc;			/* Misc flags - see FB_MISC_* */
+	__u8  version;			/* EDID version... */
+	__u8  revision;			/* ...and revision */
+	__u8  max_x;			/* Maximum horizontal size (cm) */
+	__u8  max_y;			/* Maximum vertical size (cm) */
+};
+
 struct fb_cmap_user {
 	__u32 start;			/* First entry	*/
 	__u32 len;			/* Number of entries */
@@ -445,6 +448,21 @@
  *	if you own it
  */
 #define FB_EVENT_RESUME			0x03
+/*      An entry from the modelist was removed */
+#define FB_EVENT_MODE_DELETE            0x04
+/*      A driver registered itself */
+#define FB_EVENT_FB_REGISTERED          0x05
+/*      get console to framebuffer mapping */
+#define FB_EVENT_GET_CONSOLE_MAP        0x06
+/*      set console to framebuffer mapping */
+#define FB_EVENT_SET_CONSOLE_MAP        0x07
+
+
+struct fb_event {
+	struct fb_info *info;
+	void *data;
+};
+
 
 extern int fb_register_client(struct notifier_block *nb);
 extern int fb_unregister_client(struct notifier_block *nb);
@@ -581,8 +599,10 @@
 	struct fb_pixmap pixmap;	/* Image hardware mapper */
 	struct fb_pixmap sprite;	/* Cursor hardware mapper */
 	struct fb_cmap cmap;		/* Current cmap */
+	struct list_head modelist;      /* mode list */
 	struct fb_ops *fbops;
-	char *screen_base;		/* Virtual address */
+	char __iomem *screen_base;	/* Virtual address */
+	unsigned long screen_size;	/* Amount of ioremapped VRAM or 0 */ 
 	int currcon;			/* Current VC. */
 	void *pseudo_palette;		/* Fake palette of 16 colors */ 
 #define FBINFO_STATE_RUNNING	0
@@ -687,6 +707,8 @@
 				u32 height);
 extern void fb_load_cursor_image(struct fb_info *);
 extern void fb_set_suspend(struct fb_info *info, int state);
+extern int fb_get_color_depth(struct fb_info *info);
+extern int fb_get_options(char *name, char **option);
 
 extern struct fb_info *registered_fb[FB_MAX];
 extern int num_registered_fb;
@@ -708,6 +730,7 @@
 #define FB_MODE_IS_VESA		4
 #define FB_MODE_IS_CALCULATED	8
 #define FB_MODE_IS_FIRST	16
+#define FB_MODE_IS_FROM_VAR     32
 
 extern int fbmon_valid_timings(u_int pixclock, u_int htotal, u_int vtotal,
 			       const struct fb_info *fb_info);
@@ -726,6 +749,22 @@
 /* drivers/video/modedb.c */
 #define VESA_MODEDB_SIZE 34
 extern const struct fb_videomode vesa_modes[];
+extern void fb_var_to_videomode(struct fb_videomode *mode,
+				struct fb_var_screeninfo *var);
+extern void fb_videomode_to_var(struct fb_var_screeninfo *var,
+				struct fb_videomode *mode);
+extern int fb_mode_is_equal(struct fb_videomode *mode1,
+			    struct fb_videomode *mode2);
+extern int fb_add_videomode(struct fb_videomode *mode, struct list_head *head);
+extern void fb_delete_videomode(struct fb_videomode *mode,
+				struct list_head *head);
+extern struct fb_videomode *fb_match_mode(struct fb_var_screeninfo *var,
+					  struct list_head *head);
+extern struct fb_videomode *fb_find_best_mode(struct fb_var_screeninfo *var,
+					      struct list_head *head);
+extern void fb_destroy_modelist(struct list_head *head);
+extern void fb_videomode_to_modelist(struct fb_videomode *modedb, int num,
+				     struct list_head *head);
 
 /* drivers/video/fbcmap.c */
 extern int fb_alloc_cmap(struct fb_cmap *cmap, int len, int transp);
@@ -752,6 +791,11 @@
 	u32 sync;
 	u32 vmode;
 	u32 flag;
+};
+
+struct fb_modelist {
+	struct list_head list;
+	struct fb_videomode mode;
 };
 
 extern int fb_find_mode(struct fb_var_screeninfo *var,
diff -Nru a/include/linux/fs.h b/include/linux/fs.h
--- a/include/linux/fs.h	2004-10-18 14:56:27 -07:00
+++ b/include/linux/fs.h	2004-10-18 14:56:27 -07:00
@@ -88,6 +88,7 @@
 #define SPECIAL 4	/* For non-blockdevice requests in request queue */
 #define READ_SYNC	(READ | (1 << BIO_RW_SYNC))
 #define WRITE_SYNC	(WRITE | (1 << BIO_RW_SYNC))
+#define WRITE_BARRIER	((1 << BIO_RW) | (1 << BIO_RW_BARRIER))
 
 #define SEL_IN		1
 #define SEL_OUT		2
@@ -334,14 +335,14 @@
 	struct inode		*host;		/* owner: inode, block_device */
 	struct radix_tree_root	page_tree;	/* radix tree of all pages */
 	spinlock_t		tree_lock;	/* and spinlock protecting it */
-	unsigned long		nrpages;	/* number of total pages */
-	pgoff_t			writeback_index;/* writeback starts here */
-	struct address_space_operations *a_ops;	/* methods */
-	struct prio_tree_root	i_mmap;		/* tree of private mappings */
 	unsigned int		i_mmap_writable;/* count VM_SHARED mappings */
+	struct prio_tree_root	i_mmap;		/* tree of private and shared mappings */
 	struct list_head	i_mmap_nonlinear;/*list VM_NONLINEAR mappings */
 	spinlock_t		i_mmap_lock;	/* protect tree, count, list */
 	atomic_t		truncate_count;	/* Cover race condition with truncate */
+	unsigned long		nrpages;	/* number of total pages */
+	pgoff_t			writeback_index;/* writeback starts here */
+	struct address_space_operations *a_ops;	/* methods */
 	unsigned long		flags;		/* error bits/gfp mask */
 	struct backing_dev_info *backing_dev_info; /* device readahead, etc */
 	spinlock_t		private_lock;	/* for use by the address_space */
@@ -436,6 +437,7 @@
 	unsigned long		i_version;
 	unsigned long		i_blocks;
 	unsigned short          i_bytes;
+	unsigned char		i_sock;
 	spinlock_t		i_lock;	/* i_blocks, i_bytes, maybe i_size */
 	struct semaphore	i_sem;
 	struct rw_semaphore	i_alloc_sem;
@@ -455,6 +457,8 @@
 	struct cdev		*i_cdev;
 	int			i_cindex;
 
+	__u32			i_generation;
+
 	unsigned long		i_dnotify_mask; /* Directory notify events */
 	struct dnotify_struct	*i_dnotify; /* for directory notifications */
 
@@ -462,11 +466,9 @@
 	unsigned long		dirtied_when;	/* jiffies of first dirtying */
 
 	unsigned int		i_flags;
-	unsigned char		i_sock;
 
 	atomic_t		i_writecount;
 	void			*i_security;
-	__u32			i_generation;
 	union {
 		void		*generic_ip;
 	} u;
@@ -554,8 +556,8 @@
 	unsigned long prev_page;	/* Cache last read() position */
 	unsigned long ahead_start;	/* Ahead window */
 	unsigned long ahead_size;
-	unsigned long serial_cnt;	/* measure of sequentiality */
-	unsigned long average;		/* another measure of sequentiality */
+	unsigned long currnt_wnd_hit;	/* locality in the current window */
+	unsigned long average;		/* size of next current window */
 	unsigned long ra_pages;		/* Maximum readahead window */
 	unsigned long mmap_hit;		/* Cache hit stat for mmap accesses */
 	unsigned long mmap_miss;	/* Cache miss stat for mmap accesses */
@@ -595,11 +597,6 @@
 #define get_file(x)	atomic_inc(&(x)->f_count)
 #define file_count(x)	atomic_read(&(x)->f_count)
 
-/* Initialize and open a private file and allocate its security structure. */
-extern int open_private_file(struct file *, struct dentry *, int);
-/* Release a private file and free its security structure. */
-extern void close_private_file(struct file *file);
-
 #define	MAX_NON_LFS	((1UL<<31) - 1)
 
 /* Page cache limit. The filesystems should put that into their s_maxbytes 
@@ -626,6 +623,18 @@
  */
 typedef struct files_struct *fl_owner_t;
 
+struct file_lock_operations {
+	void (*fl_insert)(struct file_lock *);	/* lock insertion callback */
+	void (*fl_remove)(struct file_lock *);	/* lock removal callback */
+	void (*fl_copy_lock)(struct file_lock *, struct file_lock *);
+	void (*fl_release_private)(struct file_lock *);
+};
+
+struct lock_manager_operations {
+	int (*fl_compare_owner)(struct file_lock *, struct file_lock *);
+	void (*fl_notify)(struct file_lock *);	/* unblock callback */
+};
+
 /* that will die - we need it for nfs_lock_info */
 #include <linux/nfs_fs_i.h>
 
@@ -642,13 +651,11 @@
 	loff_t fl_start;
 	loff_t fl_end;
 
-	void (*fl_notify)(struct file_lock *);	/* unblock callback */
-	void (*fl_insert)(struct file_lock *);	/* lock insertion callback */
-	void (*fl_remove)(struct file_lock *);	/* lock removal callback */
-
 	struct fasync_struct *	fl_fasync; /* for lease break notifications */
 	unsigned long fl_break_time;	/* for nonblocking lease breaks */
 
+	struct file_lock_operations *fl_ops;	/* Callbacks for filesystems */
+	struct lock_manager_operations *fl_lmops;	/* Callbacks for lockmanagers */
 	union {
 		struct nfs_lock_info	nfs_fl;
 	} fl_u;
@@ -684,9 +691,11 @@
 extern void locks_remove_flock(struct file *);
 extern struct file_lock *posix_test_lock(struct file *, struct file_lock *);
 extern int posix_lock_file(struct file *, struct file_lock *);
+extern int posix_lock_file_wait(struct file *, struct file_lock *);
 extern void posix_block_lock(struct file_lock *, struct file_lock *);
 extern void posix_unblock_lock(struct file *, struct file_lock *);
 extern int posix_locks_deadlock(struct file_lock *, struct file_lock *);
+extern int flock_lock_file_wait(struct file *filp, struct file_lock *fl);
 extern int __break_lease(struct inode *inode, unsigned int flags);
 extern void lease_get_mtime(struct inode *, struct timespec *time);
 extern int lock_may_read(struct inode *, loff_t start, unsigned long count);
@@ -811,6 +820,11 @@
 extern int vfs_rename(struct inode *, struct dentry *, struct inode *, struct dentry *);
 
 /*
+ * VFS dentry helper functions.
+ */
+extern void dentry_unhash(struct dentry *dentry);
+
+/*
  * File types
  *
  * NOTE! These match bits 12..15 of stat.st_mode
@@ -826,6 +840,11 @@
 #define DT_SOCK		12
 #define DT_WHT		14
 
+#define OSYNC_METADATA	(1<<0)
+#define OSYNC_DATA	(1<<1)
+#define OSYNC_INODE	(1<<2)
+int generic_osync_inode(struct inode *, struct address_space *, int);
+
 /*
  * This is the "filldir" function type, used by readdir() to let
  * the kernel specify what kind of dirent layout it wants to have.
@@ -894,6 +913,7 @@
 	unsigned long (*get_unmapped_area)(struct file *, unsigned long, unsigned long, unsigned long, unsigned long);
 	int (*check_flags)(int);
 	int (*dir_notify)(struct file *filp, unsigned long arg);
+	int (*flock) (struct file *, int, struct file_lock *);
 };
 
 struct inode_operations {
@@ -940,7 +960,7 @@
 	void (*read_inode) (struct inode *);
   
    	void (*dirty_inode) (struct inode *);
-	void (*write_inode) (struct inode *, int);
+	int (*write_inode) (struct inode *, int);
 	void (*put_inode) (struct inode *);
 	void (*drop_inode) (struct inode *);
 	void (*delete_inode) (struct inode *);
@@ -1129,6 +1149,7 @@
 struct super_block *get_sb_pseudo(struct file_system_type *, char *,
 			struct super_operations *ops, unsigned long);
 int __put_super(struct super_block *sb);
+int __put_super_and_need_restart(struct super_block *sb);
 void unnamed_dev_init(void);
 
 /* Alas, no aliases. Too much hassle with bringing module.h everywhere */
@@ -1411,7 +1432,11 @@
 extern ssize_t __generic_file_aio_read(struct kiocb *, const struct iovec *, unsigned long, loff_t *);
 extern ssize_t generic_file_aio_write(struct kiocb *, const char __user *, size_t, loff_t);
 extern ssize_t generic_file_aio_write_nolock(struct kiocb *, const struct iovec *,
-				unsigned long, loff_t *);
+		unsigned long, loff_t *);
+extern ssize_t generic_file_direct_write(struct kiocb *, const struct iovec *,
+		unsigned long *, loff_t, loff_t *, size_t, size_t);
+extern ssize_t generic_file_buffered_write(struct kiocb *, const struct iovec *,
+		unsigned long, loff_t, loff_t *, size_t, ssize_t);
 extern ssize_t do_sync_read(struct file *filp, char __user *buf, size_t len, loff_t *ppos);
 extern ssize_t do_sync_write(struct file *filp, const char __user *buf, size_t len, loff_t *ppos);
 ssize_t generic_file_write_nolock(struct file *file, const struct iovec *iov,
@@ -1449,18 +1474,21 @@
 ssize_t __blockdev_direct_IO(int rw, struct kiocb *iocb, struct inode *inode,
 	struct block_device *bdev, const struct iovec *iov, loff_t offset,
 	unsigned long nr_segs, get_blocks_t get_blocks, dio_iodone_t end_io,
-	int needs_special_locking);
+	int lock_type);
+
+enum {
+	DIO_LOCKING = 1, /* need locking between buffered and direct access */
+	DIO_NO_LOCKING,  /* bdev; no locking at all between buffered/direct */
+	DIO_OWN_LOCKING, /* filesystem locks buffered and direct internally */
+};
 
-/*
- * For filesystems which need locking between buffered and direct access
- */
 static inline ssize_t blockdev_direct_IO(int rw, struct kiocb *iocb,
 	struct inode *inode, struct block_device *bdev, const struct iovec *iov,
 	loff_t offset, unsigned long nr_segs, get_blocks_t get_blocks,
 	dio_iodone_t end_io)
 {
 	return __blockdev_direct_IO(rw, iocb, inode, bdev, iov, offset,
-				nr_segs, get_blocks, end_io, 1);
+				nr_segs, get_blocks, end_io, DIO_LOCKING);
 }
 
 static inline ssize_t blockdev_direct_IO_no_locking(int rw, struct kiocb *iocb,
@@ -1469,7 +1497,16 @@
 	dio_iodone_t end_io)
 {
 	return __blockdev_direct_IO(rw, iocb, inode, bdev, iov, offset,
-				nr_segs, get_blocks, end_io, 0);
+				nr_segs, get_blocks, end_io, DIO_NO_LOCKING);
+}
+
+static inline ssize_t blockdev_direct_IO_own_locking(int rw, struct kiocb *iocb,
+	struct inode *inode, struct block_device *bdev, const struct iovec *iov,
+	loff_t offset, unsigned long nr_segs, get_blocks_t get_blocks,
+	dio_iodone_t end_io)
+{
+	return __blockdev_direct_IO(rw, iocb, inode, bdev, iov, offset,
+				nr_segs, get_blocks, end_io, DIO_OWN_LOCKING);
 }
 
 extern struct file_operations generic_ro_fops;
@@ -1549,6 +1586,39 @@
 
 /* kernel/fork.c */
 extern int unshare_files(void);
+
+/* Transaction based IO helpers */
+
+/*
+ * An argresp is stored in an allocated page and holds the
+ * size of the argument or response, along with its content
+ */
+struct simple_transaction_argresp {
+	ssize_t size;
+	char data[0];
+};
+
+#define SIMPLE_TRANSACTION_LIMIT (PAGE_SIZE - sizeof(struct simple_transaction_argresp))
+
+char *simple_transaction_get(struct file *file, const char __user *buf,
+				size_t size);
+ssize_t simple_transaction_read(struct file *file, char __user *buf,
+				size_t size, loff_t *pos);
+int simple_transaction_release(struct inode *inode, struct file *file);
+
+static inline void simple_transaction_set(struct file *file, size_t n)
+{
+	struct simple_transaction_argresp *ar = file->private_data;
+
+	BUG_ON(n > SIMPLE_TRANSACTION_LIMIT);
+
+	/*
+	 * The barrier ensures that ar->size will really remain zero until
+	 * ar->data is ready for reading.
+	 */
+	smp_mb();
+	ar->size = n;
+}
 
 #ifdef CONFIG_SECURITY
 static inline char *alloc_secdata(void)
diff -Nru a/include/linux/gen_stats.h b/include/linux/gen_stats.h
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/include/linux/gen_stats.h	2004-10-18 14:57:23 -07:00
@@ -0,0 +1,62 @@
+#ifndef __LINUX_GEN_STATS_H
+#define __LINUX_GEN_STATS_H
+
+#include <linux/types.h>
+
+enum {
+	TCA_STATS_UNSPEC,
+	TCA_STATS_BASIC,
+	TCA_STATS_RATE_EST,
+	TCA_STATS_QUEUE,
+	TCA_STATS_APP,
+	__TCA_STATS_MAX,
+};
+#define TCA_STATS_MAX (__TCA_STATS_MAX - 1)
+
+/**
+ * @bytes: number of seen bytes
+ * @packets: number of seen packets
+ */
+struct gnet_stats_basic
+{
+	__u64	bytes;
+	__u32	packets;
+};
+
+/**
+ * @bps: current byte rate
+ * @pps: current packet rate
+ */
+struct gnet_stats_rate_est
+{
+	__u32	bps;
+	__u32	pps;
+};
+
+/**
+ * @qlen: queue length
+ * @backlog: backlog size of queue
+ * @drops: number of dropped packets
+ * @requeues: number of requeues
+ */
+struct gnet_stats_queue
+{
+	__u32	qlen;
+	__u32	backlog;
+	__u32	drops;
+	__u32	requeues;
+	__u32	overlimits;
+};
+
+/**
+ * @interval: sampling period
+ * @ewma_log: the log of measurement window weight
+ */
+struct gnet_estimator
+{
+	signed char	interval;
+	unsigned char	ewma_log;
+};
+
+
+#endif /* __LINUX_GEN_STATS_H */
diff -Nru a/include/linux/genhd.h b/include/linux/genhd.h
--- a/include/linux/genhd.h	2004-10-18 14:56:11 -07:00
+++ b/include/linux/genhd.h	2004-10-18 14:56:11 -07:00
@@ -42,6 +42,8 @@
 	UNIXWARE_PARTITION = 0x63,	/* Same as GNU_HURD and SCO Unix */
 };
 
+#ifndef __KERNEL__
+
 struct partition {
 	unsigned char boot_ind;		/* 0x80 - active */
 	unsigned char head;		/* starting head */
@@ -55,7 +57,22 @@
 	unsigned int nr_sects;		/* nr of sectors in partition */
 } __attribute__((packed));
 
+#endif
+
 #ifdef __KERNEL__
+struct partition {
+	unsigned char boot_ind;		/* 0x80 - active */
+	unsigned char head;		/* starting head */
+	unsigned char sector;		/* starting sector */
+	unsigned char cyl;		/* starting cylinder */
+	unsigned char sys_ind;		/* What partition type */
+	unsigned char end_head;		/* end head */
+	unsigned char end_sector;	/* end sector */
+	unsigned char end_cyl;		/* end cylinder */
+	__le32 start_sect;	/* starting sector counting from 0 */
+	__le32 nr_sects;		/* nr of sectors in partition */
+} __attribute__((packed));
+
 struct hd_struct {
 	sector_t start_sect;
 	sector_t nr_sects;
@@ -100,7 +117,7 @@
 	struct timer_rand_state *random;
 	int policy;
 
-	unsigned sync_io;		/* RAID */
+	atomic_t sync_io;		/* RAID */
 	unsigned long stamp, stamp_idle;
 	int in_flight;
 #ifdef	CONFIG_SMP
@@ -218,19 +235,19 @@
 #define SOLARIS_X86_VTOC_SANE	(0x600DDEEEUL)
 
 struct solaris_x86_slice {
-	ushort	s_tag;			/* ID tag of partition */
-	ushort	s_flag;			/* permission flags */
-	unsigned int s_start;		/* start sector no of partition */
-	unsigned int s_size;		/* # of blocks in partition */
+	__le16 s_tag;		/* ID tag of partition */
+	__le16 s_flag;		/* permission flags */
+	__le32 s_start;		/* start sector no of partition */
+	__le32 s_size;		/* # of blocks in partition */
 };
 
 struct solaris_x86_vtoc {
 	unsigned int v_bootinfo[3];	/* info needed by mboot (unsupported) */
-	unsigned int v_sanity;		/* to verify vtoc sanity */
-	unsigned int v_version;		/* layout version */
+	__le32 v_sanity;		/* to verify vtoc sanity */
+	__le32 v_version;		/* layout version */
 	char	v_volume[8];		/* volume name */
-	ushort	v_sectorsz;		/* sector size in bytes */
-	ushort	v_nparts;		/* number of partitions */
+	__le16	v_sectorsz;		/* sector size in bytes */
+	__le16	v_nparts;		/* number of partitions */
 	unsigned int v_reserved[10];	/* free space */
 	struct solaris_x86_slice
 		v_slice[SOLARIS_X86_NUMSLICE]; /* slice headers */
@@ -249,11 +266,11 @@
 /* check against BSD src/sys/sys/disklabel.h for consistency */
 
 #define BSD_DISKMAGIC	(0x82564557UL)	/* The disk magic number */
-#define BSD_MAXPARTITIONS	8
+#define BSD_MAXPARTITIONS	16
 #define OPENBSD_MAXPARTITIONS	16
 #define BSD_FS_UNUSED		0	/* disklabel unused partition entry ID */
 struct bsd_disklabel {
-	__u32	d_magic;		/* the magic number */
+	__le32	d_magic;		/* the magic number */
 	__s16	d_type;			/* drive type */
 	__s16	d_subtype;		/* controller/d_type specific */
 	char	d_typename[16];		/* type name, e.g. "eagle" */
@@ -278,20 +295,20 @@
 	__u32	d_drivedata[NDDATA];	/* drive-type specific information */
 #define NSPARE 5
 	__u32	d_spare[NSPARE];	/* reserved for future use */
-	__u32	d_magic2;		/* the magic number (again) */
-	__u16	d_checksum;		/* xor of data incl. partitions */
+	__le32	d_magic2;		/* the magic number (again) */
+	__le16	d_checksum;		/* xor of data incl. partitions */
 
 			/* filesystem and partition information: */
-	__u16	d_npartitions;		/* number of partitions in following */
-	__u32	d_bbsize;		/* size of boot area at sn0, bytes */
-	__u32	d_sbsize;		/* max size of fs superblock, bytes */
+	__le16	d_npartitions;		/* number of partitions in following */
+	__le32	d_bbsize;		/* size of boot area at sn0, bytes */
+	__le32	d_sbsize;		/* max size of fs superblock, bytes */
 	struct	bsd_partition {		/* the partition table */
-		__u32	p_size;		/* number of sectors in partition */
-		__u32	p_offset;	/* starting sector */
-		__u32	p_fsize;	/* filesystem basic fragment size */
+		__le32	p_size;		/* number of sectors in partition */
+		__le32	p_offset;	/* starting sector */
+		__le32	p_fsize;	/* filesystem basic fragment size */
 		__u8	p_fstype;	/* filesystem type, see below */
 		__u8	p_frag;		/* filesystem fragments per block */
-		__u16	p_cpg;		/* filesystem cylinders per group */
+		__le16	p_cpg;		/* filesystem cylinders per group */
 	} d_partitions[BSD_MAXPARTITIONS];	/* actually may be more */
 };
 
@@ -309,40 +326,40 @@
 #define UNIXWARE_FS_UNUSED     0		/* Unused slice entry ID */
 
 struct unixware_slice {
-	__u16   s_label;	/* label */
-	__u16   s_flags;	/* permission flags */
-	__u32   start_sect;	/* starting sector */
-	__u32   nr_sects;	/* number of sectors in slice */
+	__le16   s_label;	/* label */
+	__le16   s_flags;	/* permission flags */
+	__le32   start_sect;	/* starting sector */
+	__le32   nr_sects;	/* number of sectors in slice */
 };
 
 struct unixware_disklabel {
-	__u32   d_type;               	/* drive type */
-	__u32   d_magic;                /* the magic number */
-	__u32   d_version;              /* version number */
+	__le32   d_type;               	/* drive type */
+	__le32   d_magic;                /* the magic number */
+	__le32   d_version;              /* version number */
 	char    d_serial[12];           /* serial number of the device */
-	__u32   d_ncylinders;           /* # of data cylinders per device */
-	__u32   d_ntracks;              /* # of tracks per cylinder */
-	__u32   d_nsectors;             /* # of data sectors per track */
-	__u32   d_secsize;              /* # of bytes per sector */
-	__u32   d_part_start;           /* # of first sector of this partition */
-	__u32   d_unknown1[12];         /* ? */
- 	__u32	d_alt_tbl;              /* byte offset of alternate table */
- 	__u32	d_alt_len;              /* byte length of alternate table */
- 	__u32	d_phys_cyl;             /* # of physical cylinders per device */
- 	__u32	d_phys_trk;             /* # of physical tracks per cylinder */
- 	__u32	d_phys_sec;             /* # of physical sectors per track */
- 	__u32	d_phys_bytes;           /* # of physical bytes per sector */
- 	__u32	d_unknown2;             /* ? */
-	__u32   d_unknown3;             /* ? */
-	__u32	d_pad[8];               /* pad */
+	__le32   d_ncylinders;           /* # of data cylinders per device */
+	__le32   d_ntracks;              /* # of tracks per cylinder */
+	__le32   d_nsectors;             /* # of data sectors per track */
+	__le32   d_secsize;              /* # of bytes per sector */
+	__le32   d_part_start;           /* # of first sector of this partition */
+	__le32   d_unknown1[12];         /* ? */
+ 	__le32	d_alt_tbl;              /* byte offset of alternate table */
+ 	__le32	d_alt_len;              /* byte length of alternate table */
+ 	__le32	d_phys_cyl;             /* # of physical cylinders per device */
+ 	__le32	d_phys_trk;             /* # of physical tracks per cylinder */
+ 	__le32	d_phys_sec;             /* # of physical sectors per track */
+ 	__le32	d_phys_bytes;           /* # of physical bytes per sector */
+ 	__le32	d_unknown2;             /* ? */
+	__le32   d_unknown3;             /* ? */
+	__le32	d_pad[8];               /* pad */
 
 	struct unixware_vtoc {
-		__u32	v_magic;		/* the magic number */
-		__u32	v_version;		/* version number */
+		__le32	v_magic;		/* the magic number */
+		__le32	v_version;		/* version number */
 		char	v_name[8];		/* volume name */
-		__u16	v_nslices;		/* # of slices */
-		__u16	v_unknown1;		/* ? */
-		__u32	v_reserved[10];		/* reserved */
+		__le16	v_nslices;		/* # of slices */
+		__le16	v_unknown1;		/* ? */
+		__le32	v_reserved[10];		/* reserved */
 		struct unixware_slice
 			v_slice[UNIXWARE_NUMSLICE];	/* slice headers */
 	} vtoc;
diff -Nru a/include/linux/gfp.h b/include/linux/gfp.h
--- a/include/linux/gfp.h	2004-10-18 14:56:21 -07:00
+++ b/include/linux/gfp.h	2004-10-18 14:56:21 -07:00
@@ -73,6 +73,11 @@
  * For the normal case of non-DISCONTIGMEM systems the NODE_DATA() gets
  * optimized to &contig_page_data at compile-time.
  */
+
+#ifndef HAVE_ARCH_FREE_PAGE
+static inline void arch_free_page(struct page *page, int order) { }
+#endif
+
 extern struct page *
 FASTCALL(__alloc_pages(unsigned int, unsigned int, struct zonelist *));
 
diff -Nru a/include/linux/hardirq.h b/include/linux/hardirq.h
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/include/linux/hardirq.h	2004-10-18 14:57:23 -07:00
@@ -0,0 +1,46 @@
+#ifndef LINUX_HARDIRQ_H
+#define LINUX_HARDIRQ_H
+
+#include <linux/config.h>
+#include <linux/smp_lock.h>
+#include <asm/hardirq.h>
+
+#define __IRQ_MASK(x)	((1UL << (x))-1)
+
+#define PREEMPT_MASK	(__IRQ_MASK(PREEMPT_BITS) << PREEMPT_SHIFT)
+#define HARDIRQ_MASK	(__IRQ_MASK(HARDIRQ_BITS) << HARDIRQ_SHIFT)
+#define SOFTIRQ_MASK	(__IRQ_MASK(SOFTIRQ_BITS) << SOFTIRQ_SHIFT)
+
+#define PREEMPT_OFFSET	(1UL << PREEMPT_SHIFT)
+#define SOFTIRQ_OFFSET	(1UL << SOFTIRQ_SHIFT)
+#define HARDIRQ_OFFSET	(1UL << HARDIRQ_SHIFT)
+
+#define hardirq_count()	(preempt_count() & HARDIRQ_MASK)
+#define softirq_count()	(preempt_count() & SOFTIRQ_MASK)
+#define irq_count()	(preempt_count() & (HARDIRQ_MASK | SOFTIRQ_MASK))
+
+/*
+ * Are we doing bottom half or hardware interrupt processing?
+ * Are we in a softirq context? Interrupt context?
+ */
+#define in_irq()		(hardirq_count())
+#define in_softirq()		(softirq_count())
+#define in_interrupt()		(irq_count())
+
+#ifdef CONFIG_PREEMPT
+# define in_atomic()	((preempt_count() & ~PREEMPT_ACTIVE) != kernel_locked())
+# define preemptible()	(preempt_count() == 0 && !irqs_disabled())
+# define IRQ_EXIT_OFFSET (HARDIRQ_OFFSET-1)
+#else
+# define in_atomic()	(preempt_count() != 0)
+# define preemptible()	0
+# define IRQ_EXIT_OFFSET HARDIRQ_OFFSET
+#endif
+
+#ifdef CONFIG_SMP
+extern void synchronize_irq(unsigned int irq);
+#else
+# define synchronize_irq(irq)	barrier()
+#endif
+
+#endif /* LINUX_HARDIRQ_H */
diff -Nru a/include/linux/hdreg.h b/include/linux/hdreg.h
--- a/include/linux/hdreg.h	2004-10-18 14:56:29 -07:00
+++ b/include/linux/hdreg.h	2004-10-18 14:56:29 -07:00
@@ -449,9 +449,8 @@
 /* hd/ide ctl's that pass (arg) ptrs to user space are numbered 0x033n/0x033n */
 /* 0x330 is reserved - used to be HDIO_GETGEO_BIG */
 /* 0x331 is reserved - used to be HDIO_GETGEO_BIG_RAW */
-
-#define HDIO_SET_IDE_SCSI      0x0338
-#define HDIO_SET_SCSI_IDE      0x0339
+/* 0x338 is reserved - used to be HDIO_SET_IDE_SCSI */
+/* 0x339 is reserved - used to be HDIO_SET_SCSI_IDE */
 
 #define __NEW_HD_DRIVE_ID
 
diff -Nru a/include/linux/hiddev.h b/include/linux/hiddev.h
--- a/include/linux/hiddev.h	2004-10-18 14:56:21 -07:00
+++ b/include/linux/hiddev.h	2004-10-18 14:56:21 -07:00
@@ -128,10 +128,11 @@
 
 /* hiddev_usage_ref_multi is used for sending multiple bytes to a control.
  * It really manifests itself as setting the value of consecutive usages */
+#define HID_MAX_MULTI_USAGES 1024
 struct hiddev_usage_ref_multi {
 	struct hiddev_usage_ref uref;
 	__u32 num_values;
-	__s32 values[HID_MAX_USAGES];
+	__s32 values[HID_MAX_MULTI_USAGES];
 };
 
 /* FIELD_INDEX_NONE is returned in read() data from the kernel when flags
@@ -211,6 +212,11 @@
 /*
  * In-kernel definitions.
  */
+
+struct hid_device;
+struct hid_usage;
+struct hid_field;
+struct hid_report;
 
 #ifdef CONFIG_USB_HIDDEV
 int hiddev_connect(struct hid_device *);
diff -Nru a/include/linux/highmem.h b/include/linux/highmem.h
--- a/include/linux/highmem.h	2004-10-18 14:56:49 -07:00
+++ b/include/linux/highmem.h	2004-10-18 14:56:49 -07:00
@@ -40,6 +40,8 @@
 	void *addr = kmap_atomic(page, KM_USER0);
 	clear_user_page(addr, vaddr, page);
 	kunmap_atomic(addr, KM_USER0);
+	/* Make sure this page is cleared on other CPU's too before using it */
+	smp_wmb();
 }
 
 static inline void clear_highpage(struct page *page)
@@ -73,6 +75,8 @@
 	copy_user_page(vto, vfrom, vaddr, to);
 	kunmap_atomic(vfrom, KM_USER0);
 	kunmap_atomic(vto, KM_USER1);
+	/* Make sure this page is cleared on other CPU's too before using it */
+	smp_wmb();
 }
 
 static inline void copy_highpage(struct page *to, struct page *from)
diff -Nru a/include/linux/highuid.h b/include/linux/highuid.h
--- a/include/linux/highuid.h	2004-10-18 14:56:33 -07:00
+++ b/include/linux/highuid.h	2004-10-18 14:56:33 -07:00
@@ -44,8 +44,8 @@
 #ifdef CONFIG_UID16
 
 /* prevent uid mod 65536 effect by returning a default value for high UIDs */
-#define high2lowuid(uid) ((uid) > 65535 ? (old_uid_t)overflowuid : (old_uid_t)(uid))
-#define high2lowgid(gid) ((gid) > 65535 ? (old_gid_t)overflowgid : (old_gid_t)(gid))
+#define high2lowuid(uid) ((uid) & ~0xFFFF ? (old_uid_t)overflowuid : (old_uid_t)(uid))
+#define high2lowgid(gid) ((gid) & ~0xFFFF ? (old_gid_t)overflowgid : (old_gid_t)(gid))
 /*
  * -1 is different in 16 bits than it is in 32 bits
  * these macros are used by chown(), setreuid(), ...,
@@ -89,8 +89,8 @@
  * Since these macros are used in architectures that only need limited
  * 16-bit UID back compatibility, we won't use old_uid_t and old_gid_t
  */
-#define fs_high2lowuid(uid) ((uid) > 65535 ? (uid16_t)fs_overflowuid : (uid16_t)(uid))
-#define fs_high2lowgid(gid) ((gid) > 65535 ? (gid16_t)fs_overflowgid : (gid16_t)(gid))
+#define fs_high2lowuid(uid) ((uid) & ~0xFFFF ? (uid16_t)fs_overflowuid : (uid16_t)(uid))
+#define fs_high2lowgid(gid) ((gid) & ~0xFFFF ? (gid16_t)fs_overflowgid : (gid16_t)(gid))
 
 #define low_16_bits(x)	((x) & 0xFFFF)
 #define high_16_bits(x)	(((x) & 0xFFFF0000) >> 16)
diff -Nru a/include/linux/hpet.h b/include/linux/hpet.h
--- a/include/linux/hpet.h	2004-10-18 14:56:48 -07:00
+++ b/include/linux/hpet.h	2004-10-18 14:56:48 -07:00
@@ -1,6 +1,8 @@
 #ifndef	__HPET__
 #define	__HPET__ 1
 
+#include <linux/compiler.h>
+
 /*
  * Offsets into HPET Registers
  */
@@ -110,7 +112,7 @@
 };
 
 struct hpet_data {
-	unsigned long hd_address;
+	void __iomem *hd_address;
 	unsigned short hd_nirqs;
 	unsigned short hd_flags;
 	unsigned int hd_state;	/* timer allocated */
diff -Nru a/include/linux/i2c-algo-pca.h b/include/linux/i2c-algo-pca.h
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/include/linux/i2c-algo-pca.h	2004-10-18 14:57:23 -07:00
@@ -0,0 +1,17 @@
+#ifndef _LINUX_I2C_ALGO_PCA_H
+#define _LINUX_I2C_ALGO_PCA_H
+
+struct i2c_algo_pca_data {
+	int  (*get_own)			(struct i2c_algo_pca_data *adap); /* Obtain own address */
+	int  (*get_clock)		(struct i2c_algo_pca_data *adap);
+	void (*write_byte)		(struct i2c_algo_pca_data *adap, int reg, int val);
+	int  (*read_byte)		(struct i2c_algo_pca_data *adap, int reg);
+	int  (*wait_for_interrupt)	(struct i2c_algo_pca_data *adap);
+};
+
+#define I2C_PCA_ADAP_MAX	16
+
+int i2c_pca_add_bus(struct i2c_adapter *);
+int i2c_pca_del_bus(struct i2c_adapter *);
+
+#endif /* _LINUX_I2C_ALGO_PCA_H */
diff -Nru a/include/linux/i2c-id.h b/include/linux/i2c-id.h
--- a/include/linux/i2c-id.h	2004-10-18 14:55:54 -07:00
+++ b/include/linux/i2c-id.h	2004-10-18 14:55:54 -07:00
@@ -194,6 +194,7 @@
 #define I2C_ALGO_OCP    0x120000	/* IBM or otherwise On-chip I2C algorithm */
 #define I2C_ALGO_BITHS	0x130000	/* enhanced bit style adapters	*/
 #define I2C_ALGO_OCP_IOP3XX  0x140000	/* XSCALE IOP3XX On-chip I2C alg */
+#define I2C_ALGO_PCA	0x150000	/* PCA 9564 style adapters	*/
 
 #define I2C_ALGO_EXP	0x800000	/* experimental			*/
 
@@ -238,6 +239,9 @@
 #define I2C_HW_P_LP	0x00	/* Parallel port interface		*/
 #define I2C_HW_P_ISA	0x01	/* generic ISA Bus inteface card	*/
 #define I2C_HW_P_ELEK	0x02	/* Elektor ISA Bus inteface card	*/
+
+/* --- PCA 9564 based algorithms */
+#define I2C_HW_A_ISA	0x00	/* generic ISA Bus interface card	*/
 
 /* --- ACPI Embedded controller algorithms                              */
 #define I2C_HW_ACPI_EC          0x00
diff -Nru a/include/linux/i2c-vid.h b/include/linux/i2c-vid.h
--- a/include/linux/i2c-vid.h	2004-10-18 14:55:54 -07:00
+++ b/include/linux/i2c-vid.h	2004-10-18 14:55:54 -07:00
@@ -35,12 +35,15 @@
     to avoid floating point in the kernel.
 */
 
+int i2c_which_vrm(void);
+
 #define DEFAULT_VRM	82
 
 static inline int vid_from_reg(int val, int vrm)
 {
 	switch(vrm) {
-
+	case  0:
+		return 0;
 	case 91:		/* VRM 9.1 */
 	case 90:		/* VRM 9.0 */
 		return(val == 0x1f ? 0 :
diff -Nru a/include/linux/i2c.h b/include/linux/i2c.h
--- a/include/linux/i2c.h	2004-10-18 14:56:17 -07:00
+++ b/include/linux/i2c.h	2004-10-18 14:56:17 -07:00
@@ -566,7 +566,9 @@
 
 #define I2C_CLIENT_MODULE_PARM(var,desc) \
   static unsigned short var[I2C_CLIENT_MAX_OPTS] = I2C_CLIENT_DEFAULTS; \
-  MODULE_PARM(var,I2C_CLIENT_MODPARM); \
+  static unsigned int var##_num; \
+  /*MODULE_PARM(var,I2C_CLIENT_MODPARM);*/ \
+  module_param_array(var, short, var##_num, 0); \
   MODULE_PARM_DESC(var,desc)
 
 /* This is the one you want to use in your own modules */
diff -Nru a/include/linux/i2o-dev.h b/include/linux/i2o-dev.h
--- a/include/linux/i2o-dev.h	2004-10-18 14:55:55 -07:00
+++ b/include/linux/i2o-dev.h	2004-10-18 14:55:55 -07:00
@@ -1,13 +1,13 @@
 /*
  * I2O user space accessible structures/APIs
- * 
+ *
  * (c) Copyright 1999, 2000 Red Hat Software
  *
- * 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 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 header file defines the I2O APIs that are available to both
@@ -23,7 +23,7 @@
 /* How many controllers are we allowing */
 #define MAX_I2O_CONTROLLERS	32
 
-#include <linux/ioctl.h>
+//#include <linux/ioctl.h>
 
 /*
  * I2O Control IOCTLs and structures
@@ -42,22 +42,25 @@
 #define I2OEVTREG		_IOW(I2O_MAGIC_NUMBER,10,struct i2o_evt_id)
 #define I2OEVTGET		_IOR(I2O_MAGIC_NUMBER,11,struct i2o_evt_info)
 #define I2OPASSTHRU		_IOR(I2O_MAGIC_NUMBER,12,struct i2o_cmd_passthru)
+#define I2OPASSTHRU32		_IOR(I2O_MAGIC_NUMBER,12,struct i2o_cmd_passthru32)
+
+struct i2o_cmd_passthru32 {
+	unsigned int iop;	/* IOP unit number */
+	u32 msg;		/* message */
+};
 
-struct i2o_cmd_passthru
-{
+struct i2o_cmd_passthru {
 	unsigned int iop;	/* IOP unit number */
 	void __user *msg;	/* message */
 };
 
-struct i2o_cmd_hrtlct
-{
+struct i2o_cmd_hrtlct {
 	unsigned int iop;	/* IOP unit number */
 	void __user *resbuf;	/* Buffer for result */
 	unsigned int __user *reslen;	/* Buffer length in bytes */
 };
 
-struct i2o_cmd_psetget
-{
+struct i2o_cmd_psetget {
 	unsigned int iop;	/* IOP unit number */
 	unsigned int tid;	/* Target device TID */
 	void __user *opbuf;	/* Operation List buffer */
@@ -66,8 +69,7 @@
 	unsigned int __user *reslen;	/* Result List buffer length in bytes */
 };
 
-struct i2o_sw_xfer
-{
+struct i2o_sw_xfer {
 	unsigned int iop;	/* IOP unit number */
 	unsigned char flags;	/* Flags field */
 	unsigned char sw_type;	/* Software type */
@@ -78,21 +80,19 @@
 	unsigned int __user *curfrag;	/* Current fragment count */
 };
 
-struct i2o_html
-{
+struct i2o_html {
 	unsigned int iop;	/* IOP unit number */
 	unsigned int tid;	/* Target device ID */
 	unsigned int page;	/* HTML page */
-	void __user *resbuf;		/* Buffer for reply HTML page */
+	void __user *resbuf;	/* Buffer for reply HTML page */
 	unsigned int __user *reslen;	/* Length in bytes of reply buffer */
-	void __user *qbuf;		/* Pointer to HTTP query string */
+	void __user *qbuf;	/* Pointer to HTTP query string */
 	unsigned int qlen;	/* Length in bytes of query string buffer */
 };
 
 #define I2O_EVT_Q_LEN 32
 
-struct i2o_evt_id
-{
+struct i2o_evt_id {
 	unsigned int iop;
 	unsigned int tid;
 	unsigned int evt_mask;
@@ -101,21 +101,18 @@
 /* Event data size = frame size - message header + evt indicator */
 #define I2O_EVT_DATA_SIZE 88
 
-struct i2o_evt_info
-{
+struct i2o_evt_info {
 	struct i2o_evt_id id;
 	unsigned char evt_data[I2O_EVT_DATA_SIZE];
 	unsigned int data_size;
 };
 
-struct i2o_evt_get
-{
+struct i2o_evt_get {
 	struct i2o_evt_info info;
 	int pending;
 	int lost;
 };
 
-
 /**************************************************************************
  * HRT related constants and structures
  **************************************************************************/
@@ -135,139 +132,127 @@
 typedef unsigned short u16;
 typedef unsigned int u32;
 
-#endif /* __KERNEL__ */
+#endif				/* __KERNEL__ */
 
-typedef struct _i2o_pci_bus
-{
-	u8	PciFunctionNumber;
-	u8	PciDeviceNumber;
-	u8	PciBusNumber;
-	u8	reserved;
-	u16	PciVendorID;
-	u16	PciDeviceID;
+typedef struct _i2o_pci_bus {
+	u8 PciFunctionNumber;
+	u8 PciDeviceNumber;
+	u8 PciBusNumber;
+	u8 reserved;
+	u16 PciVendorID;
+	u16 PciDeviceID;
 } i2o_pci_bus;
 
-typedef struct _i2o_local_bus
-{
-	u16	LbBaseIOPort;
-	u16	reserved;
-	u32	LbBaseMemoryAddress;
+typedef struct _i2o_local_bus {
+	u16 LbBaseIOPort;
+	u16 reserved;
+	u32 LbBaseMemoryAddress;
 } i2o_local_bus;
 
-typedef struct _i2o_isa_bus
-{
-	u16	IsaBaseIOPort;
-	u8	CSN;
-	u8	reserved;
-	u32	IsaBaseMemoryAddress;
+typedef struct _i2o_isa_bus {
+	u16 IsaBaseIOPort;
+	u8 CSN;
+	u8 reserved;
+	u32 IsaBaseMemoryAddress;
 } i2o_isa_bus;
 
-typedef struct _i2o_eisa_bus_info
-{
-	u16	EisaBaseIOPort;
-	u8	reserved;
-	u8	EisaSlotNumber;
-	u32	EisaBaseMemoryAddress;
+typedef struct _i2o_eisa_bus_info {
+	u16 EisaBaseIOPort;
+	u8 reserved;
+	u8 EisaSlotNumber;
+	u32 EisaBaseMemoryAddress;
 } i2o_eisa_bus;
 
-typedef struct _i2o_mca_bus
-{
-	u16	McaBaseIOPort;
-	u8	reserved;
-	u8	McaSlotNumber;
-	u32	McaBaseMemoryAddress;
+typedef struct _i2o_mca_bus {
+	u16 McaBaseIOPort;
+	u8 reserved;
+	u8 McaSlotNumber;
+	u32 McaBaseMemoryAddress;
 } i2o_mca_bus;
 
-typedef struct _i2o_other_bus
-{
+typedef struct _i2o_other_bus {
 	u16 BaseIOPort;
 	u16 reserved;
 	u32 BaseMemoryAddress;
 } i2o_other_bus;
 
-typedef struct _i2o_hrt_entry
-{
-	u32	adapter_id;
-	u32	parent_tid:12;
-	u32 	state:4;
-	u32	bus_num:8;
-	u32	bus_type:8;
-	union
-	{
-		i2o_pci_bus	pci_bus;
-		i2o_local_bus	local_bus;
-		i2o_isa_bus	isa_bus;
-		i2o_eisa_bus	eisa_bus;
-		i2o_mca_bus	mca_bus;
-		i2o_other_bus	other_bus;
+typedef struct _i2o_hrt_entry {
+	u32 adapter_id;
+	u32 parent_tid:12;
+	u32 state:4;
+	u32 bus_num:8;
+	u32 bus_type:8;
+	union {
+		i2o_pci_bus pci_bus;
+		i2o_local_bus local_bus;
+		i2o_isa_bus isa_bus;
+		i2o_eisa_bus eisa_bus;
+		i2o_mca_bus mca_bus;
+		i2o_other_bus other_bus;
 	} bus;
 } i2o_hrt_entry;
 
-typedef struct _i2o_hrt
-{
-	u16	num_entries;
-	u8	entry_len;
-	u8	hrt_version;
-	u32	change_ind;
+typedef struct _i2o_hrt {
+	u16 num_entries;
+	u8 entry_len;
+	u8 hrt_version;
+	u32 change_ind;
 	i2o_hrt_entry hrt_entry[1];
 } i2o_hrt;
 
-typedef struct _i2o_lct_entry
-{
-	u32	entry_size:16;
-	u32	tid:12;
-	u32	reserved:4;
-	u32	change_ind;
-	u32	device_flags;
-	u32	class_id:12;
-	u32	version:4;
-	u32	vendor_id:16;
-	u32	sub_class;
-	u32	user_tid:12;
-	u32	parent_tid:12;
-	u32	bios_info:8;
-	u8	identity_tag[8];
-	u32	event_capabilities;
+typedef struct _i2o_lct_entry {
+	u32 entry_size:16;
+	u32 tid:12;
+	u32 reserved:4;
+	u32 change_ind;
+	u32 device_flags;
+	u32 class_id:12;
+	u32 version:4;
+	u32 vendor_id:16;
+	u32 sub_class;
+	u32 user_tid:12;
+	u32 parent_tid:12;
+	u32 bios_info:8;
+	u8 identity_tag[8];
+	u32 event_capabilities;
 } i2o_lct_entry;
 
-typedef struct _i2o_lct
-{
-	u32	table_size:16;
-	u32	boot_tid:12;
-	u32	lct_ver:4;
-	u32	iop_flags;
-	u32	change_ind;
+typedef struct _i2o_lct {
+	u32 table_size:16;
+	u32 boot_tid:12;
+	u32 lct_ver:4;
+	u32 iop_flags;
+	u32 change_ind;
 	i2o_lct_entry lct_entry[1];
 } i2o_lct;
 
-typedef struct _i2o_status_block
-{
-	u16	org_id;
-	u16	reserved;
-	u16	iop_id:12;
-	u16	reserved1:4;
-	u16	host_unit_id;
-	u16	segment_number:12;
-	u16	i2o_version:4;
-	u8	iop_state;
-	u8	msg_type;
-	u16	inbound_frame_size;
-	u8	init_code;
-	u8	reserved2;
-	u32	max_inbound_frames;
-	u32	cur_inbound_frames;
-	u32	max_outbound_frames;
-	char	product_id[24];
-	u32	expected_lct_size;
-	u32	iop_capabilities;
-	u32	desired_mem_size;
-	u32	current_mem_size;
-	u32	current_mem_base;
-	u32	desired_io_size;
-	u32	current_io_size;
-	u32	current_io_base;
-	u32	reserved3:24;
-	u32	cmd_status:8;
+typedef struct _i2o_status_block {
+	u16 org_id;
+	u16 reserved;
+	u16 iop_id:12;
+	u16 reserved1:4;
+	u16 host_unit_id;
+	u16 segment_number:12;
+	u16 i2o_version:4;
+	u8 iop_state;
+	u8 msg_type;
+	u16 inbound_frame_size;
+	u8 init_code;
+	u8 reserved2;
+	u32 max_inbound_frames;
+	u32 cur_inbound_frames;
+	u32 max_outbound_frames;
+	char product_id[24];
+	u32 expected_lct_size;
+	u32 iop_capabilities;
+	u32 desired_mem_size;
+	u32 current_mem_size;
+	u32 current_mem_base;
+	u32 desired_io_size;
+	u32 current_io_size;
+	u32 current_io_base;
+	u32 reserved3:24;
+	u32 cmd_status:8;
 } i2o_status_block;
 
 /* Event indicator mask flags */
@@ -351,14 +336,15 @@
 #define I2O_CLASS_BUS_ADAPTER_PORT		0x080
 #define I2O_CLASS_PEER_TRANSPORT_AGENT		0x090
 #define I2O_CLASS_PEER_TRANSPORT		0x091
+#define	I2O_CLASS_END				0xfff
 
-/* 
+/*
  *  Rest of 0x092 - 0x09f reserved for peer-to-peer classes
  */
 
 #define I2O_CLASS_MATCH_ANYCLASS		0xffffffff
 
-/* 
+/*
  *  Subclasses
  */
 
@@ -380,7 +366,7 @@
 #define I2O_PARAMS_TABLE_CLEAR			0x000A
 
 /*
- * I2O serial number conventions / formats 
+ * I2O serial number conventions / formats
  * (circa v1.5)
  */
 
@@ -391,7 +377,7 @@
 #define I2O_SNFORMAT_LAN48_MAC			4
 #define I2O_SNFORMAT_WAN			5
 
-/* 
+/*
  * Plus new in v2.0 (Yellowstone pdf doc)
  */
 
@@ -402,7 +388,7 @@
 #define I2O_SNFORMAT_UNKNOWN2			0xff
 
 /*
- *	I2O Get Status State values 
+ *	I2O Get Status State values
  */
 
 #define ADAPTER_STATE_INITIALIZING		0x01
@@ -413,4 +399,4 @@
 #define ADAPTER_STATE_FAILED			0x10
 #define ADAPTER_STATE_FAULTED			0x11
 
-#endif /* _I2O_DEV_H */
+#endif				/* _I2O_DEV_H */
diff -Nru a/include/linux/i2o.h b/include/linux/i2o.h
--- a/include/linux/i2o.h	2004-10-18 14:56:19 -07:00
+++ b/include/linux/i2o.h	2004-10-18 14:56:19 -07:00
@@ -1,16 +1,16 @@
 /*
  * I2O kernel space accessible structures/APIs
- * 
+ *
  * (c) Copyright 1999, 2000 Red Hat Software
  *
- * 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 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 header file defined the I2O APIs/structures for use by 
+ * This header file defined the I2O APIs/structures for use by
  * the I2O kernel modules.
  *
  */
@@ -18,309 +18,586 @@
 #ifndef _I2O_H
 #define _I2O_H
 
-#ifdef __KERNEL__ /* This file to be included by kernel only */
+#ifdef __KERNEL__		/* This file to be included by kernel only */
 
 #include <linux/i2o-dev.h>
 
 /* How many different OSM's are we allowing */
-#define MAX_I2O_MODULES		4
-
-/* How many OSMs can register themselves for device status updates? */
-#define I2O_MAX_MANAGERS	4
+#define I2O_MAX_DRIVERS		4
 
+#include <asm/io.h>
 #include <asm/semaphore.h>	/* Needed for MUTEX init macros */
-#include <linux/config.h>
-#include <linux/notifier.h>
-#include <asm/atomic.h>
+#include <linux/pci.h>
+#include <linux/dma-mapping.h>
+
+/* message queue empty */
+#define I2O_QUEUE_EMPTY		0xffffffff
 
 /*
  *	Message structures
  */
-struct i2o_message
-{
-	u8	version_offset;
-	u8	flags;
-	u16	size;
-	u32	target_tid:12;
-	u32	init_tid:12;
-	u32	function:8;
-	u32	initiator_context;
+struct i2o_message {
+	union {
+		struct {
+			u8 version_offset;
+			u8 flags;
+			u16 size;
+			u32 target_tid:12;
+			u32 init_tid:12;
+			u32 function:8;
+			u32 icntxt;	/* initiator context */
+			u32 tcntxt;	/* transaction context */
+		} s;
+		u32 head[4];
+	} u;
 	/* List follows */
+	u32 body[0];
 };
 
 /*
- *	Each I2O device entity has one or more of these. There is one
- *	per device.
+ *	Each I2O device entity has one of these. There is one per device.
  */
-struct i2o_device
-{
-	i2o_lct_entry lct_data;		/* Device LCT information */
-	u32 flags;
-	int i2oversion;			/* I2O version supported. Actually
-					 * there should be high and low
-					 * version */
+struct i2o_device {
+	i2o_lct_entry lct_data;	/* Device LCT information */
 
-	struct proc_dir_entry *proc_entry;	/* /proc dir */
+	struct i2o_controller *iop;	/* Controlling IOP */
+	struct list_head list;	/* node in IOP devices list */
+
+	struct device device;
 
-	/* Primary user */
-	struct i2o_handler *owner;
+	struct semaphore lock;	/* device lock */
 
-	/* Management users */
-	struct i2o_handler *managers[I2O_MAX_MANAGERS];
-	int num_managers;
+	struct class_device classdev;	/* i2o device class */
+};
 
-	struct i2o_controller *controller;	/* Controlling IOP */
-	struct i2o_device *next;	/* Chain */
-	struct i2o_device *prev;
-	char dev_name[8];		/* linux /dev name if available */
+/*
+ *	Event structure provided to the event handling function
+ */
+struct i2o_event {
+	struct work_struct work;
+	struct i2o_device *i2o_dev;	/* I2O device pointer from which the
+					   event reply was initiated */
+	u16 size;		/* Size of data in 32-bit words */
+	u32 tcntxt;		/* Transaction context used at
+				   registration */
+	u32 event_indicator;	/* Event indicator from reply */
+	u32 data[0];		/* Event data from reply */
 };
 
 /*
- * context queue entry, used for 32-bit context on 64-bit systems
+ *	I2O classes which could be handled by the OSM
+ */
+struct i2o_class_id {
+	u16 class_id:12;
+};
+
+/*
+ *	I2O driver structure for OSMs
+ */
+struct i2o_driver {
+	char *name;		/* OSM name */
+	int context;		/* Low 8 bits of the transaction info */
+	struct i2o_class_id *classes;	/* I2O classes that this OSM handles */
+
+	/* Message reply handler */
+	int (*reply) (struct i2o_controller *, u32, struct i2o_message *);
+
+	/* Event handler */
+	void (*event) (struct i2o_event *);
+
+	struct workqueue_struct *event_queue;	/* Event queue */
+
+	struct device_driver driver;
+
+	/* notification of changes */
+	void (*notify_controller_add) (struct i2o_controller *);
+	void (*notify_controller_remove) (struct i2o_controller *);
+	void (*notify_device_add) (struct i2o_device *);
+	void (*notify_device_remove) (struct i2o_device *);
+
+	struct semaphore lock;
+};
+
+/*
+ *	Contains all information which are necessary for DMA operations
+ */
+struct i2o_dma {
+	void *virt;
+	dma_addr_t phys;
+	u32 len;
+};
+
+/*
+ *	Context queue entry, used for 32-bit context on 64-bit systems
  */
 struct i2o_context_list_element {
-	struct i2o_context_list_element *next;
+	struct list_head list;
 	u32 context;
 	void *ptr;
-	unsigned int flags;
+	unsigned long timestamp;
 };
 
 /*
  * Each I2O controller has one of these objects
  */
-struct i2o_controller
-{
+struct i2o_controller {
 	char name[16];
 	int unit;
 	int type;
-	int enabled;
-	
-	struct pci_dev *pdev;		/* PCI device */
-	int		irq;
-	int		short_req:1;	/* Use small block sizes        */
-	int		dpt:1;		/* Don't quiesce                */
-	int		raptor:1;	/* split bar                    */
-	int		promise:1;	/* Promise controller		*/
+
+	struct pci_dev *pdev;	/* PCI device */
+
+	int short_req:1;	/* use small block sizes */
+	int no_quiesce:1;	/* dont quiesce before reset */
+	int raptor:1;		/* split bar */
+	int promise:1;		/* Promise controller */
+
 #ifdef CONFIG_MTRR
-	int		mtrr_reg0;
-	int		mtrr_reg1;
+	int mtrr_reg0;
+	int mtrr_reg1;
 #endif
 
+	struct list_head devices;	/* list of I2O devices */
+
 	struct notifier_block *event_notifer;	/* Events */
 	atomic_t users;
-	struct i2o_device *devices;		/* I2O device chain */
-	struct i2o_controller *next;		/* Controller chain */
-	void *post_port;			/* Inbout port address */
-	void *reply_port;			/* Outbound port address */
-	void *irq_mask;				/* Interrupt register address */
+	struct list_head list;	/* Controller list */
+	void *post_port;	/* Inbout port address */
+	void *reply_port;	/* Outbound port address */
+	void *irq_mask;		/* Interrupt register address */
 
 	/* Dynamic LCT related data */
-	struct semaphore lct_sem;
-	int lct_pid;
-	int lct_running;
-
-	i2o_status_block *status_block;		/* IOP status block */
-	dma_addr_t status_block_phys;
-	i2o_lct *lct;				/* Logical Config Table */
-	dma_addr_t lct_phys;
-	i2o_lct *dlct;				/* Temp LCT */
-	dma_addr_t dlct_phys;
-	i2o_hrt *hrt;				/* HW Resource Table */
-	dma_addr_t hrt_phys;
-	u32 hrt_len;
-
-	void *base_virt;			/* base virtual address */
-	unsigned long base_phys;		/* base physical address */
-
-	void *msg_virt;				/* messages virtual address */
-	unsigned long msg_phys;			/* messages physical address */
-
-	int battery:1;				/* Has a battery backup */
-	int io_alloc:1;				/* An I/O resource was allocated */
-	int mem_alloc:1;			/* A memory resource was allocated */
 
-	struct resource io_resource;		/* I/O resource allocated to the IOP */
-	struct resource mem_resource;		/* Mem resource allocated to the IOP */
+	struct i2o_dma status;	/* status of IOP */
 
-	struct proc_dir_entry *proc_entry;	/* /proc dir */
+	struct i2o_dma hrt;	/* HW Resource Table */
+	i2o_lct *lct;		/* Logical Config Table */
+	struct i2o_dma dlct;	/* Temp LCT */
+	struct semaphore lct_lock;	/* Lock for LCT updates */
+	struct i2o_dma status_block;	/* IOP status block */
+
+	struct i2o_dma base;	/* controller messaging unit */
+	struct i2o_dma in_queue;	/* inbound message queue Host->IOP */
+	struct i2o_dma out_queue;	/* outbound message queue IOP->Host */
+
+	int battery:1;		/* Has a battery backup */
+	int io_alloc:1;		/* An I/O resource was allocated */
+	int mem_alloc:1;	/* A memory resource was allocated */
+
+	struct resource io_resource;	/* I/O resource allocated to the IOP */
+	struct resource mem_resource;	/* Mem resource allocated to the IOP */
 
+	struct proc_dir_entry *proc_entry;	/* /proc dir */
 
-	void *page_frame;			/* Message buffers */
-	dma_addr_t page_frame_map;		/* Cache map */
+	struct list_head bus_list;	/* list of busses on IOP */
+	struct device device;
+	struct i2o_device *exec;	/* Executive */
 #if BITS_PER_LONG == 64
-	spinlock_t context_list_lock;		/* lock for context_list */
-	struct i2o_context_list_element *context_list; /* list of context id's
-						    and pointers */
+	spinlock_t context_list_lock;	/* lock for context_list */
+	atomic_t context_list_counter;	/* needed for unique contexts */
+	struct list_head context_list;	/* list of context id's
+					   and pointers */
 #endif
+	spinlock_t lock;	/* lock for controller
+				   configuration */
+
+	void *driver_data[I2O_MAX_DRIVERS];	/* storage for drivers */
 };
 
 /*
- * OSM resgistration block
+ * I2O System table entry
  *
- * Each OSM creates at least one of these and registers it with the
- * I2O core through i2o_register_handler.  An OSM may want to
- * register more than one if it wants a fast path to a reply
- * handler by having a separate initiator context for each 
- * class function.
+ * The system table contains information about all the IOPs in the
+ * system.  It is sent to all IOPs so that they can create peer2peer
+ * connections between them.
  */
-struct i2o_handler
+struct i2o_sys_tbl_entry {
+	u16 org_id;
+	u16 reserved1;
+	u32 iop_id:12;
+	u32 reserved2:20;
+	u16 seg_num:12;
+	u16 i2o_version:4;
+	u8 iop_state;
+	u8 msg_type;
+	u16 frame_size;
+	u16 reserved3;
+	u32 last_changed;
+	u32 iop_capabilities;
+	u32 inbound_low;
+	u32 inbound_high;
+};
+
+struct i2o_sys_tbl {
+	u8 num_entries;
+	u8 version;
+	u16 reserved1;
+	u32 change_ind;
+	u32 reserved2;
+	u32 reserved3;
+	struct i2o_sys_tbl_entry iops[0];
+};
+
+extern struct list_head i2o_controllers;
+
+/* Message functions */
+static inline u32 i2o_msg_get(struct i2o_controller *, struct i2o_message **);
+extern u32 i2o_msg_get_wait(struct i2o_controller *, struct i2o_message **,
+			    int);
+static inline void i2o_msg_post(struct i2o_controller *, u32);
+static inline int i2o_msg_post_wait(struct i2o_controller *, u32,
+				    unsigned long);
+extern int i2o_msg_post_wait_mem(struct i2o_controller *, u32, unsigned long,
+				 struct i2o_dma *);
+extern void i2o_msg_nop(struct i2o_controller *, u32);
+static inline void i2o_flush_reply(struct i2o_controller *, u32);
+
+/* DMA handling functions */
+static inline int i2o_dma_alloc(struct device *, struct i2o_dma *, size_t,
+				unsigned int);
+static inline void i2o_dma_free(struct device *, struct i2o_dma *);
+int i2o_dma_realloc(struct device *, struct i2o_dma *, size_t, unsigned int);
+
+static inline int i2o_dma_map(struct device *, struct i2o_dma *);
+static inline void i2o_dma_unmap(struct device *, struct i2o_dma *);
+
+/* IOP functions */
+extern int i2o_status_get(struct i2o_controller *);
+extern int i2o_hrt_get(struct i2o_controller *);
+
+extern int i2o_event_register(struct i2o_device *, struct i2o_driver *, int,
+			      u32);
+extern struct i2o_device *i2o_iop_find_device(struct i2o_controller *, u16);
+extern struct i2o_controller *i2o_find_iop(int);
+
+/* Functions needed for handling 64-bit pointers in 32-bit context */
+#if BITS_PER_LONG == 64
+extern u32 i2o_cntxt_list_add(struct i2o_controller *, void *);
+extern void *i2o_cntxt_list_get(struct i2o_controller *, u32);
+extern u32 i2o_cntxt_list_remove(struct i2o_controller *, void *);
+extern u32 i2o_cntxt_list_get_ptr(struct i2o_controller *, void *);
+
+static inline u32 i2o_ptr_low(void *ptr)
 {
-	/* Message reply handler */
-	void (*reply)(struct i2o_handler *, struct i2o_controller *,
-		      struct i2o_message *);
+	return (u32) (u64) ptr;
+};
+
+static inline u32 i2o_ptr_high(void *ptr)
+{
+	return (u32) ((u64) ptr >> 32);
+};
+#else
+static inline u32 i2o_cntxt_list_add(struct i2o_controller *c, void *ptr)
+{
+	return (u32) ptr;
+};
 
-	/* New device notification handler */
-	void (*new_dev_notify)(struct i2o_controller *, struct i2o_device *);
+static inline void *i2o_cntxt_list_get(struct i2o_controller *c, u32 context)
+{
+	return (void *)context;
+};
 
-	/* Device deltion handler */
-	void (*dev_del_notify)(struct i2o_controller *, struct i2o_device *);
+static inline u32 i2o_cntxt_list_remove(struct i2o_controller *c, void *ptr)
+{
+	return (u32) ptr;
+};
 
-	/* Reboot notification handler */
-	void (*reboot_notify)(void);
+static inline u32 i2o_cntxt_list_get_ptr(struct i2o_controller *c, void *ptr)
+{
+	return (u32) ptr;
+};
 
-	char *name;		/* OSM name */
-	int context;		/* Low 8 bits of the transaction info */
-	u32 class;		/* I2O classes that this driver handles */
-	/* User data follows */
+static inline u32 i2o_ptr_low(void *ptr)
+{
+	return (u32) ptr;
 };
 
-#ifdef MODULE
-/*
- * Used by bus specific modules to communicate with the core
+static inline u32 i2o_ptr_high(void *ptr)
+{
+	return 0;
+};
+#endif
+
+/* I2O driver (OSM) functions */
+extern int i2o_driver_register(struct i2o_driver *);
+extern void i2o_driver_unregister(struct i2o_driver *);
+
+/**
+ *	i2o_driver_notify_controller_add - Send notification of added controller
+ *					   to a single I2O driver
  *
- * This is needed because the bus modules cannot make direct
- * calls to the core as this results in the i2o_bus_specific_module
- * being dependent on the core, not the otherway around.
- * In that case, a 'modprobe i2o_lan' loads i2o_core & i2o_lan,
- * but _not_ i2o_pci...which makes the whole thing pretty useless :)
+ *	Send notification of added controller to a single registered driver.
+ */
+static inline void i2o_driver_notify_controller_add(struct i2o_driver *drv,
+						    struct i2o_controller *c)
+{
+	if (drv->notify_controller_add)
+		drv->notify_controller_add(c);
+};
+
+/**
+ *	i2o_driver_notify_controller_remove - Send notification of removed
+ *					      controller to a single I2O driver
  *
+ *	Send notification of removed controller to a single registered driver.
  */
-struct i2o_core_func_table
+static inline void i2o_driver_notify_controller_remove(struct i2o_driver *drv,
+						       struct i2o_controller *c)
 {
-	int	(*install)(struct i2o_controller *);
-	int	(*activate)(struct i2o_controller *);
-	struct i2o_controller *(*find)(int);
-	void	(*unlock)(struct i2o_controller *);
-	void	(*run_queue)(struct i2o_controller * c);
-	int	(*delete)(struct i2o_controller *);
+	if (drv->notify_controller_remove)
+		drv->notify_controller_remove(c);
 };
-#endif /* MODULE */
 
-/*
- * I2O System table entry
+/**
+ *	i2o_driver_notify_device_add - Send notification of added device to a
+ *				       single I2O driver
  *
- * The system table contains information about all the IOPs in the
- * system.  It is sent to all IOPs so that they can create peer2peer
- * connections between them.
+ *	Send notification of added device to a single registered driver.
  */
-struct i2o_sys_tbl_entry
+static inline void i2o_driver_notify_device_add(struct i2o_driver *drv,
+						struct i2o_device *i2o_dev)
 {
-	u16	org_id;
-	u16	reserved1;
-	u32	iop_id:12;
-	u32	reserved2:20;
-	u16	seg_num:12;
-	u16	i2o_version:4;
-	u8	iop_state;
-	u8	msg_type;
-	u16	frame_size;
-	u16	reserved3;
-	u32	last_changed;
-	u32	iop_capabilities;
-	u32	inbound_low;
-	u32	inbound_high;
-};
-
-struct i2o_sys_tbl
-{
-	u8	num_entries;
-	u8	version;
-	u16	reserved1;
-	u32	change_ind;
-	u32	reserved2;
-	u32	reserved3;
-	struct i2o_sys_tbl_entry iops[0];
+	if (drv->notify_device_add)
+		drv->notify_device_add(i2o_dev);
+};
+
+/**
+ *	i2o_driver_notify_device_remove - Send notification of removed device
+ *					  to a single I2O driver
+ *
+ *	Send notification of removed device to a single registered driver.
+ */
+static inline void i2o_driver_notify_device_remove(struct i2o_driver *drv,
+						   struct i2o_device *i2o_dev)
+{
+	if (drv->notify_device_remove)
+		drv->notify_device_remove(i2o_dev);
 };
 
+extern void i2o_driver_notify_controller_add_all(struct i2o_controller *);
+extern void i2o_driver_notify_controller_remove_all(struct i2o_controller *);
+extern void i2o_driver_notify_device_add_all(struct i2o_device *);
+extern void i2o_driver_notify_device_remove_all(struct i2o_device *);
+
+/* I2O device functions */
+extern int i2o_device_claim(struct i2o_device *);
+extern int i2o_device_claim_release(struct i2o_device *);
+
+/* Exec OSM functions */
+extern int i2o_exec_lct_get(struct i2o_controller *);
+extern int i2o_exec_lct_notify(struct i2o_controller *, u32);
+
+/* device to i2o_device and driver to i2o_driver convertion functions */
+#define to_i2o_driver(drv) container_of(drv,struct i2o_driver, driver)
+#define to_i2o_device(dev) container_of(dev, struct i2o_device, device)
+
 /*
  *	Messenger inlines
  */
 static inline u32 I2O_POST_READ32(struct i2o_controller *c)
 {
+	rmb();
 	return readl(c->post_port);
-}
+};
 
 static inline void I2O_POST_WRITE32(struct i2o_controller *c, u32 val)
 {
+	wmb();
 	writel(val, c->post_port);
-}
-
+};
 
 static inline u32 I2O_REPLY_READ32(struct i2o_controller *c)
 {
+	rmb();
 	return readl(c->reply_port);
-}
+};
 
 static inline void I2O_REPLY_WRITE32(struct i2o_controller *c, u32 val)
 {
+	wmb();
 	writel(val, c->reply_port);
-}
-
+};
 
 static inline u32 I2O_IRQ_READ32(struct i2o_controller *c)
 {
+	rmb();
 	return readl(c->irq_mask);
-}
+};
 
 static inline void I2O_IRQ_WRITE32(struct i2o_controller *c, u32 val)
 {
+	wmb();
 	writel(val, c->irq_mask);
-}
+	wmb();
+};
 
+/**
+ *	i2o_msg_get - obtain an I2O message from the IOP
+ *	@c: I2O controller
+ *	@msg: pointer to a I2O message pointer
+ *
+ *	This function tries to get a message slot. If no message slot is
+ *	available do not wait until one is availabe (see also i2o_msg_get_wait).
+ *
+ *	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.
+ */
+static inline u32 i2o_msg_get(struct i2o_controller *c,
+			      struct i2o_message **msg)
+{
+	u32 m;
 
-static inline void i2o_post_message(struct i2o_controller *c, u32 m)
+	if ((m = I2O_POST_READ32(c)) != I2O_QUEUE_EMPTY)
+		*msg = c->in_queue.virt + m;
+
+	return m;
+};
+
+/**
+ *	i2o_msg_post - Post I2O message to I2O controller
+ *	@c: I2O controller to which the message should be send
+ *	@m: the message identifier
+ *
+ *	Post the message to the I2O controller.
+ */
+static inline void i2o_msg_post(struct i2o_controller *c, u32 m)
 {
-	/* The second line isnt spurious - thats forcing PCI posting */
 	I2O_POST_WRITE32(c, m);
-	(void) I2O_IRQ_READ32(c);
-}
+};
 
+/**
+ * 	i2o_msg_post_wait - Post and wait a message and wait until return
+ *	@c: controller
+ *	@m: message to post
+ *	@timeout: time in seconds to wait
+ *
+ * 	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.
+ *
+ *	Returns 0 on success or negative error code on failure.
+ */
+static inline int i2o_msg_post_wait(struct i2o_controller *c, u32 m,
+				    unsigned long timeout)
+{
+	return i2o_msg_post_wait_mem(c, m, timeout, NULL);
+};
+
+/**
+ *	i2o_flush_reply - Flush reply from I2O controller
+ *	@c: I2O controller
+ *	@m: the message identifier
+ *
+ *	The I2O controller must be informed that the reply message is not needed
+ *	anymore. If you forget to flush the reply, the message frame can't be
+ *	used by the controller anymore and is therefore lost.
+ *
+ *	FIXME: is there a timeout after which the controller reuse the message?
+ */
 static inline void i2o_flush_reply(struct i2o_controller *c, u32 m)
 {
 	I2O_REPLY_WRITE32(c, m);
-}
+};
+
+/**
+ *	i2o_dma_alloc - Allocate DMA memory
+ *	@dev: struct device pointer to the PCI device of the I2O controller
+ *	@addr: i2o_dma struct which should get the DMA buffer
+ *	@len: length of the new DMA memory
+ *	@gfp_mask: GFP mask
+ *
+ *	Allocate a coherent DMA memory and write the pointers into addr.
+ *
+ *	Returns 0 on success or -ENOMEM on failure.
+ */
+static inline int i2o_dma_alloc(struct device *dev, struct i2o_dma *addr,
+				size_t len, unsigned int gfp_mask)
+{
+	addr->virt = dma_alloc_coherent(dev, len, &addr->phys, gfp_mask);
+	if (!addr->virt)
+		return -ENOMEM;
+
+	memset(addr->virt, 0, len);
+	addr->len = len;
+
+	return 0;
+};
+
+/**
+ *	i2o_dma_free - Free DMA memory
+ *	@dev: struct device pointer to the PCI device of the I2O controller
+ *	@addr: i2o_dma struct which contains the DMA buffer
+ *
+ *	Free a coherent DMA memory and set virtual address of addr to NULL.
+ */
+static inline void i2o_dma_free(struct device *dev, struct i2o_dma *addr)
+{
+	if (addr->virt) {
+		if (addr->phys)
+			dma_free_coherent(dev, addr->len, addr->virt,
+					  addr->phys);
+		else
+			kfree(addr->virt);
+		addr->virt = NULL;
+	}
+};
+
+/**
+ *	i2o_dma_map - Map the memory to DMA
+ *	@dev: struct device pointer to the PCI device of the I2O controller
+ *	@addr: i2o_dma struct which should be mapped
+ *
+ *	Map the memory in addr->virt to coherent DMA memory and write the
+ *	physical address into addr->phys.
+ *
+ *	Returns 0 on success or -ENOMEM on failure.
+ */
+static inline int i2o_dma_map(struct device *dev, struct i2o_dma *addr)
+{
+	if (!addr->virt)
+		return -EFAULT;
+
+	if (!addr->phys)
+		addr->phys = dma_map_single(dev, addr->virt, addr->len,
+					    DMA_BIDIRECTIONAL);
+	if (!addr->phys)
+		return -ENOMEM;
+
+	return 0;
+};
+
+/**
+ *	i2o_dma_unmap - Unmap the DMA memory
+ *	@dev: struct device pointer to the PCI device of the I2O controller
+ *	@addr: i2o_dma struct which should be unmapped
+ *
+ *	Unmap the memory in addr->virt from DMA memory.
+ */
+static inline void i2o_dma_unmap(struct device *dev, struct i2o_dma *addr)
+{
+	if (!addr->virt)
+		return;
+
+	if (addr->phys) {
+		dma_unmap_single(dev, addr->phys, addr->len, DMA_BIDIRECTIONAL);
+		addr->phys = 0;
+	}
+};
 
 /*
  *	Endian handling wrapped into the macro - keeps the core code
  *	cleaner.
  */
- 
-#define i2o_raw_writel(val, mem)	__raw_writel(cpu_to_le32(val), mem)
-
-extern struct i2o_controller *i2o_find_controller(int);
-extern void i2o_unlock_controller(struct i2o_controller *);
-extern struct i2o_controller *i2o_controller_chain;
-extern int i2o_num_controllers;
-extern int i2o_status_get(struct i2o_controller *);
 
-extern int i2o_install_handler(struct i2o_handler *);
-extern int i2o_remove_handler(struct i2o_handler *);
-
-extern int i2o_claim_device(struct i2o_device *, struct i2o_handler *);
-extern int i2o_release_device(struct i2o_device *, struct i2o_handler *);
-extern int i2o_device_notify_on(struct i2o_device *, struct i2o_handler *);
-extern int i2o_device_notify_off(struct i2o_device *,
-				 struct i2o_handler *);
-
-extern int i2o_post_this(struct i2o_controller *, u32 *, int);
-extern int i2o_post_wait(struct i2o_controller *, u32 *, int, int);
-extern int i2o_post_wait_mem(struct i2o_controller *, u32 *, int, int,
-			     void *, void *, dma_addr_t, dma_addr_t, int, int);
+#define i2o_raw_writel(val, mem)	__raw_writel(cpu_to_le32(val), mem)
 
-extern int i2o_query_scalar(struct i2o_controller *, int, int, int, void *,
-			    int);
-extern int i2o_set_scalar(struct i2o_controller *, int, int, int, void *,
-			  int);
+extern int i2o_parm_field_get(struct i2o_device *, int, int, void *, int);
+extern int i2o_parm_field_set(struct i2o_device *, int, int, void *, int);
+extern int i2o_parm_table_get(struct i2o_device *, int, int, int, void *, int,
+			      void *, int);
+/* FIXME: remove
 extern int i2o_query_table(int, struct i2o_controller *, int, int, int,
 			   void *, int, void *, int);
 extern int i2o_clear_table(struct i2o_controller *, int, int);
@@ -328,51 +605,24 @@
 			     void *, int);
 extern int i2o_issue_params(int, struct i2o_controller *, int, void *, int,
 			    void *, int);
+*/
 
-extern int i2o_event_register(struct i2o_controller *, u32, u32, u32, u32);
-extern int i2o_event_ack(struct i2o_controller *, u32 *);
-
-extern void i2o_report_status(const char *, const char *, u32 *);
-extern void i2o_dump_message(u32 *);
-extern const char *i2o_get_class_name(int);
-
-extern int i2o_install_controller(struct i2o_controller *);
-extern int i2o_activate_controller(struct i2o_controller *);
-extern void i2o_run_queue(struct i2o_controller *);
-extern int i2o_delete_controller(struct i2o_controller *);
-
-#if BITS_PER_LONG == 64
-extern u32 i2o_context_list_add(void *, struct i2o_controller *);
-extern void *i2o_context_list_get(u32, struct i2o_controller *);
-extern u32 i2o_context_list_remove(void *, struct i2o_controller *);
-#else
-static inline u32 i2o_context_list_add(void *ptr, struct i2o_controller *c)
-{
-	return (u32)ptr;
-}
-
-static inline void *i2o_context_list_get(u32 context, struct i2o_controller *c)
-{
-	return (void *)context;
-}
-
-static inline u32 i2o_context_list_remove(void *ptr, struct i2o_controller *c)
-{
-	return (u32)ptr;
-}
-#endif
+/* debugging functions */
+extern void i2o_report_status(const char *, const char *, struct i2o_message *);
+extern void i2o_dump_message(struct i2o_message *);
+extern void i2o_dump_hrt(struct i2o_controller *c);
+extern void i2o_debug_state(struct i2o_controller *c);
 
 /*
  *	Cache strategies
  */
- 
- 
+
 /*	The NULL strategy leaves everything up to the controller. This tends to be a
  *	pessimal but functional choice.
  */
 #define CACHE_NULL		0
 /*	Prefetch data when reading. We continually attempt to load the next 32 sectors
- *	into the controller cache. 
+ *	into the controller cache.
  */
 #define CACHE_PREFETCH		1
 /*	Prefetch data when reading. We sometimes attempt to load the next 32 sectors
@@ -406,15 +656,11 @@
 /*
  *	Ioctl structures
  */
- 
-
-#define 	BLKI2OGRSTRAT	_IOR('2', 1, int) 
-#define 	BLKI2OGWSTRAT	_IOR('2', 2, int) 
-#define 	BLKI2OSRSTRAT	_IOW('2', 3, int) 
-#define 	BLKI2OSWSTRAT	_IOW('2', 4, int) 
-
-
 
+#define 	BLKI2OGRSTRAT	_IOR('2', 1, int)
+#define 	BLKI2OGWSTRAT	_IOR('2', 2, int)
+#define 	BLKI2OSRSTRAT	_IOW('2', 3, int)
+#define 	BLKI2OSWSTRAT	_IOW('2', 4, int)
 
 /*
  *	I2O Function codes
@@ -652,7 +898,6 @@
 #define TRL_SINGLE_VARIABLE_LENGTH	0x40
 #define TRL_MULTIPLE_FIXED_LENGTH	0x80
 
-
  /* msg header defines for MsgFlags */
 #define MSG_STATIC	0x0100
 #define MSG_64BIT_CNTXT	0x0200
@@ -673,13 +918,12 @@
 #define ELEVEN_WORD_MSG_SIZE	0x000B0000
 #define I2O_MESSAGE_SIZE(x)	((x)<<16)
 
-
 /* Special TID Assignments */
 
 #define ADAPTER_TID		0
 #define HOST_TID		1
 
-#define MSG_FRAME_SIZE		64	/* i2o_scsi assumes >= 32 */
+#define MSG_FRAME_SIZE		128	/* i2o_scsi assumes >= 32 */
 #define REPLY_FRAME_SIZE	17
 #define SG_TABLESIZE		30
 #define NMBR_MSG_FRAMES		128
@@ -693,5 +937,23 @@
 #define I2O_CONTEXT_LIST_USED		0x01
 #define I2O_CONTEXT_LIST_DELETED	0x02
 
-#endif /* __KERNEL__ */
-#endif /* _I2O_H */
+/* timeouts */
+#define I2O_TIMEOUT_INIT_OUTBOUND_QUEUE	15
+#define I2O_TIMEOUT_MESSAGE_GET		5
+#define I2O_TIMEOUT_RESET		30
+#define I2O_TIMEOUT_STATUS_GET		5
+#define I2O_TIMEOUT_LCT_GET		20
+#define I2O_TIMEOUT_SCSI_SCB_ABORT	240
+
+/* retries */
+#define I2O_HRT_GET_TRIES		3
+#define I2O_LCT_GET_TRIES		3
+
+/* request queue sizes */
+#define I2O_MAX_SECTORS			1024
+#define I2O_MAX_SEGMENTS		128
+
+#define I2O_REQ_MEMPOOL_SIZE		32
+
+#endif				/* __KERNEL__ */
+#endif				/* _I2O_H */
diff -Nru a/include/linux/ide.h b/include/linux/ide.h
--- a/include/linux/ide.h	2004-10-18 14:56:28 -07:00
+++ b/include/linux/ide.h	2004-10-18 14:56:28 -07:00
@@ -51,16 +51,6 @@
 #ifndef OK_TO_RESET_CONTROLLER		/* 1 needed for good error recovery */
 #define OK_TO_RESET_CONTROLLER	1	/* 0 for use with AH2372A/B interface */
 #endif
-#ifndef FANCY_STATUS_DUMPS		/* 1 for human-readable drive errors */
-#define FANCY_STATUS_DUMPS	1	/* 0 to reduce kernel size */
-#endif
-
-#ifdef CONFIG_BLK_DEV_CMD640
-#if 0	/* change to 1 when debugging cmd640 problems */
-void cmd640_dump_regs (void);
-#define CMD640_DUMP_REGS cmd640_dump_regs() /* for debugging cmd640 chipset */
-#endif
-#endif  /* CONFIG_BLK_DEV_CMD640 */
 
 #ifndef DISABLE_IRQ_NOSYNC
 #define DISABLE_IRQ_NOSYNC	0
@@ -756,8 +746,8 @@
 					 *  2=48-bit doing 28-bit
 					 *  3=64-bit
 					 */
+	unsigned scsi		: 1;	/* 0=default, 1=ide-scsi emulation */
 
-	u8	scsi;		/* 0=default, 1=skip current ide-subdriver for ide-scsi emulation */
         u8	quirk_list;	/* considered quirky, set for a specific host */
         u8	suspend_reset;	/* drive suspend mode flag, soft-reset recovers */
         u8	init_speed;	/* transfer rate set at boot */
@@ -780,6 +770,7 @@
 	u8	sect;		/* "real" sectors per track */
 	u8	bios_head;	/* BIOS/fdisk/LILO number of heads */
 	u8	bios_sect;	/* BIOS/fdisk/LILO sectors per track */
+	u8	doing_barrier;	/* state, 1=currently doing flush */
 
 	unsigned int	bios_cyl;	/* BIOS/fdisk/LILO number of cyls */
 	unsigned int	cyl;		/* "real" number of cyls */
@@ -798,31 +789,6 @@
 	struct gendisk *disk;
 } ide_drive_t;
 
-typedef struct ide_pio_ops_s {
-	void (*ata_input_data)(ide_drive_t *, void *, u32);
-	void (*ata_output_data)(ide_drive_t *, void *, u32);
-
-	void (*atapi_input_bytes)(ide_drive_t *, void *, u32);
-	void (*atapi_output_bytes)(ide_drive_t *, void *, u32);
-} ide_pio_ops_t;
-
-typedef struct ide_dma_ops_s {
-	/* insert dma operations here! */
-	int (*ide_dma_read)(ide_drive_t *drive);
-	int (*ide_dma_write)(ide_drive_t *drive);
-	int (*ide_dma_begin)(ide_drive_t *drive);
-	int (*ide_dma_end)(ide_drive_t *drive);
-	int (*ide_dma_check)(ide_drive_t *drive);
-	int (*ide_dma_on)(ide_drive_t *drive);
-	int (*ide_dma_off_quietly)(ide_drive_t *drive);
-	int (*ide_dma_test_irq)(ide_drive_t *drive);
-	int (*ide_dma_host_on)(ide_drive_t *drive);
-	int (*ide_dma_host_off)(ide_drive_t *drive);
-	int (*ide_dma_verbose)(ide_drive_t *drive);
-	int (*ide_dma_lostirq)(ide_drive_t *drive);
-	int (*ide_dma_timeout)(ide_drive_t *drive);
-} ide_dma_ops_t;
-
 /*
  * mapping stuff, prepare for highmem...
  * 
@@ -915,15 +881,11 @@
 //	u8	(*ratefilter)(ide_drive_t *, u8);
 #endif
 
-#if 0
-	ide_pio_ops_t	*pioops;
-#else
 	void (*ata_input_data)(ide_drive_t *, void *, u32);
 	void (*ata_output_data)(ide_drive_t *, void *, u32);
 
 	void (*atapi_input_bytes)(ide_drive_t *, void *, u32);
 	void (*atapi_output_bytes)(ide_drive_t *, void *, u32);
-#endif
 
 	int (*ide_dma_read)(ide_drive_t *drive);
 	int (*ide_dma_write)(ide_drive_t *drive);
@@ -960,7 +922,9 @@
 	struct scatterlist *sg_table;
 	int sg_nents;			/* Current number of entries in it */
 	int sg_dma_direction;		/* dma transfer direction */
-	int sg_dma_active;		/* is it in use */
+
+	/* data phase of the active command (currently only valid for PIO/DMA) */
+	int		data_phase;
 
 	int		mmio;		/* hosts iomio (0) or custom (2) select */
 	int		rqsize;		/* max sectors per request */
@@ -988,6 +952,7 @@
 	unsigned	autodma    : 1;	/* auto-attempt using DMA at boot */
 	unsigned	udma_four  : 1;	/* 1=ATA-66 capable, 0=default */
 	unsigned	no_lba48   : 1; /* 1 = cannot do LBA48 */
+	unsigned	no_lba48_dma : 1; /* 1 = cannot do LBA48 DMA */
 	unsigned	no_dsc     : 1;	/* 0 default, 1 dsc_overlap disabled */
 	unsigned	auto_poll  : 1; /* supports nop auto-poll */
 
@@ -1293,6 +1258,11 @@
 extern void ide_init_drive_cmd (struct request *rq);
 
 /*
+ * this function returns error location sector offset in case of a write error
+ */
+extern u64 ide_get_error_location(ide_drive_t *, char *);
+
+/*
  * "action" parameter type for ide_do_drive_cmd() below.
  */
 typedef enum {
@@ -1446,11 +1416,8 @@
 extern ide_startstop_t recal_intr(ide_drive_t *);
 extern ide_startstop_t task_no_data_intr(ide_drive_t *);
 extern ide_startstop_t task_in_intr(ide_drive_t *);
-extern ide_startstop_t task_mulin_intr(ide_drive_t *);
 extern ide_startstop_t pre_task_out_intr(ide_drive_t *, struct request *);
 extern ide_startstop_t task_out_intr(ide_drive_t *);
-extern ide_startstop_t pre_task_mulout_intr(ide_drive_t *, struct request *);
-extern ide_startstop_t task_mulout_intr(ide_drive_t *);
 
 extern int ide_raw_taskfile(ide_drive_t *, ide_task_t *, u8 *);
 
@@ -1663,5 +1630,12 @@
 #define local_irq_set(flags)	do { local_save_flags((flags)); local_irq_enable(); } while (0)
 
 extern struct bus_type ide_bus_type;
+
+/* check if CACHE FLUSH (EXT) command is supported (bits defined in ATA-6) */
+#define ide_id_has_flush_cache(id)	((id)->cfs_enable_2 & 0x3000)
+
+/* some Maxtor disks have bit 13 defined incorrectly so check bit 10 too */
+#define ide_id_has_flush_cache_ext(id)	\
+	(((id)->cfs_enable_2 & 0x2400) == 0x2400)
 
 #endif /* _IDE_H */
diff -Nru a/include/linux/if_bridge.h b/include/linux/if_bridge.h
--- a/include/linux/if_bridge.h	2004-10-18 14:56:31 -07:00
+++ b/include/linux/if_bridge.h	2004-10-18 14:56:31 -07:00
@@ -105,7 +105,7 @@
 #include <linux/netdevice.h>
 
 extern void brioctl_set(int (*ioctl_hook)(unsigned int, void __user *));
-extern int (*br_handle_frame_hook)(struct sk_buff *skb);
+extern int (*br_handle_frame_hook)(struct net_bridge_port *p, struct sk_buff **pskb);
 extern int (*br_should_route_hook)(struct sk_buff **pskb);
 
 #endif
diff -Nru a/include/linux/if_ether.h b/include/linux/if_ether.h
--- a/include/linux/if_ether.h	2004-10-18 14:56:33 -07:00
+++ b/include/linux/if_ether.h	2004-10-18 14:56:33 -07:00
@@ -59,6 +59,8 @@
 #define ETH_P_8021Q	0x8100          /* 802.1Q VLAN Extended Header  */
 #define ETH_P_IPX	0x8137		/* IPX over DIX			*/
 #define ETH_P_IPV6	0x86DD		/* IPv6 over bluebook		*/
+#define ETH_P_WCCP	0x883E		/* Web-cache coordination protocol
+					 * defined in draft-wilson-wrec-wccp-v2-00.txt */
 #define ETH_P_PPP_DISC	0x8863		/* PPPoE discovery messages     */
 #define ETH_P_PPP_SES	0x8864		/* PPPoE session messages	*/
 #define ETH_P_MPLS_UC	0x8847		/* MPLS Unicast traffic		*/
@@ -94,11 +96,19 @@
  *	This is an Ethernet frame header.
  */
  
-struct ethhdr 
-{
+struct ethhdr {
 	unsigned char	h_dest[ETH_ALEN];	/* destination eth addr	*/
 	unsigned char	h_source[ETH_ALEN];	/* source ether addr	*/
 	unsigned short	h_proto;		/* packet type ID field	*/
 } __attribute__((packed));
+
+#ifdef __KERNEL__
+#include <linux/skbuff.h>
+
+static inline struct ethhdr *eth_hdr(const struct sk_buff *skb)
+{
+	return (struct ethhdr *)skb->mac.raw;
+}
+#endif
 
 #endif	/* _LINUX_IF_ETHER_H */
diff -Nru a/include/linux/if_fddi.h b/include/linux/if_fddi.h
--- a/include/linux/if_fddi.h	2004-10-18 14:56:32 -07:00
+++ b/include/linux/if_fddi.h	2004-10-18 14:56:32 -07:00
@@ -5,7 +5,7 @@
  *
  *		Global definitions for the ANSI FDDI interface.
  *
- * Version:	@(#)if_fddi.h	1.0.1	09/16/96
+ * Version:	@(#)if_fddi.h	1.0.2	Sep 29 2004
  *
  * Author:	Lawrence V. Stefani, <stefani@lkg.dec.com>
  *
@@ -103,38 +103,12 @@
 	} __attribute__ ((packed));
 
 /* Define FDDI statistics structure */
-struct fddi_statistics
-	{
-	__u32	rx_packets;				/* total packets received */
-	__u32	tx_packets;				/* total packets transmitted */
-	__u32	rx_bytes;				/* total bytes received	*/
-	__u32	tx_bytes;				/* total bytes transmitted */
-	__u32	rx_errors;				/* bad packets received	*/
-	__u32	tx_errors;				/* packet transmit problems	*/
-	__u32	rx_dropped;				/* no space in linux buffers */
-	__u32	tx_dropped;				/* no space available in linux */
-	__u32	multicast;				/* multicast packets received */
-	__u32	transmit_collision;		/* always 0 for FDDI */
-
-	/* detailed rx_errors */
-	__u32	rx_length_errors;
-	__u32	rx_over_errors;		/* receiver ring buff overflow	*/
-	__u32	rx_crc_errors;		/* recved pkt with crc error	*/
-	__u32	rx_frame_errors;	/* recv'd frame alignment error */
-	__u32	rx_fifo_errors;		/* recv'r fifo overrun		*/
-	__u32	rx_missed_errors;	/* receiver missed packet	*/
-
-	/* detailed tx_errors */
-	__u32	tx_aborted_errors;
-	__u32	tx_carrier_errors;
-	__u32	tx_fifo_errors;
-	__u32	tx_heartbeat_errors;
-	__u32	tx_window_errors;
-	
-	/* for cslip etc */
-	__u32	rx_compressed;
-	__u32	tx_compressed;
-   
+struct fddi_statistics {
+
+	/* Generic statistics. */
+
+	struct net_device_stats gen;
+
 	/* Detailed FDDI statistics.  Adopted from RFC 1512 */
 
 	__u8	smt_station_id[8];
diff -Nru a/include/linux/if_tr.h b/include/linux/if_tr.h
--- a/include/linux/if_tr.h	2004-10-18 14:55:53 -07:00
+++ b/include/linux/if_tr.h	2004-10-18 14:55:53 -07:00
@@ -48,6 +48,15 @@
 	__u16 rseg[8];			/* routing registers */
 };
 
+#ifdef __KERNEL__
+#include <linux/skbuff.h>
+
+static inline struct trh_hdr *tr_hdr(const struct sk_buff *skb)
+{
+	return (struct trh_hdr *)skb->mac.raw;
+}
+#endif
+
 /* This is an Token-Ring LLC structure */
 struct trllc {
 	__u8  dsap;			/* destination SAP */
diff -Nru a/include/linux/if_vlan.h b/include/linux/if_vlan.h
--- a/include/linux/if_vlan.h	2004-10-18 14:56:17 -07:00
+++ b/include/linux/if_vlan.h	2004-10-18 14:56:17 -07:00
@@ -18,7 +18,6 @@
 /* externally defined structs */
 struct vlan_group;
 struct net_device;
-struct sk_buff;
 struct packet_type;
 struct vlan_collection;
 struct vlan_dev_info;
@@ -48,6 +47,13 @@
    unsigned short	h_vlan_encapsulated_proto; /* packet type ID field (or len) */
 };
 
+#include <linux/skbuff.h>
+
+static inline struct vlan_ethhdr *vlan_eth_hdr(const struct sk_buff *skb)
+{
+	return (struct vlan_ethhdr *)skb->mac.raw;
+}
+
 struct vlan_hdr {
    unsigned short       h_vlan_TCI;                /* Encapsulates priority and VLAN ID */
    unsigned short       h_vlan_encapsulated_proto; /* packet type ID field (or len) */
@@ -152,7 +158,7 @@
 	skb->real_dev = skb->dev;
 	skb->dev = grp->vlan_devices[vlan_tag & VLAN_VID_MASK];
 	if (skb->dev == NULL) {
-		kfree_skb(skb);
+		dev_kfree_skb_any(skb);
 
 		/* Not NET_RX_DROP, this is not being dropped
 		 * due to congestion.
@@ -180,7 +186,7 @@
 		 * This allows the VLAN to have a different MAC than the underlying
 		 * device, and still route correctly.
 		 */
-		if (!memcmp(skb->mac.ethernet->h_dest, skb->dev->dev_addr, ETH_ALEN))
+		if (!memcmp(eth_hdr(skb)->h_dest, skb->dev->dev_addr, ETH_ALEN))
 			skb->pkt_type = PACKET_HOST;
 		break;
 	};
diff -Nru a/include/linux/inetdevice.h b/include/linux/inetdevice.h
--- a/include/linux/inetdevice.h	2004-10-18 14:56:34 -07:00
+++ b/include/linux/inetdevice.h	2004-10-18 14:56:34 -07:00
@@ -3,6 +3,8 @@
 
 #ifdef __KERNEL__
 
+#include <linux/rcupdate.h>
+
 struct ipv4_devconf
 {
 	int	accept_redirects;
@@ -31,13 +33,13 @@
 
 struct in_device
 {
-	struct net_device		*dev;
+	struct net_device	*dev;
 	atomic_t		refcnt;
-	rwlock_t		lock;
 	int			dead;
 	struct in_ifaddr	*ifa_list;	/* IP ifaddr chain		*/
+	rwlock_t		mc_list_lock;
 	struct ip_mc_list	*mc_list;	/* IP multicast filter chain    */
-	rwlock_t		mc_lock;	/* for mc_tomb */
+	spinlock_t		mc_tomb_lock;
 	struct ip_mc_list	*mc_tomb;
 	unsigned long		mr_v1_seen;
 	unsigned long		mr_v2_seen;
@@ -50,6 +52,7 @@
 
 	struct neigh_parms	*arp_parms;
 	struct ipv4_devconf	cnf;
+	struct rcu_head		rcu_head;
 };
 
 #define IN_DEV_FORWARD(in_dev)		((in_dev)->cnf.forwarding)
@@ -80,6 +83,7 @@
 {
 	struct in_ifaddr	*ifa_next;
 	struct in_device	*ifa_dev;
+	struct rcu_head		rcu_head;
 	u32			ifa_local;
 	u32			ifa_address;
 	u32			ifa_mask;
@@ -133,19 +137,16 @@
 
 #define endfor_ifa(in_dev) }
 
-extern rwlock_t inetdev_lock;
-
-
 static __inline__ struct in_device *
 in_dev_get(const struct net_device *dev)
 {
 	struct in_device *in_dev;
 
-	read_lock(&inetdev_lock);
+	rcu_read_lock();
 	in_dev = dev->ip_ptr;
 	if (in_dev)
 		atomic_inc(&in_dev->refcnt);
-	read_unlock(&inetdev_lock);
+	rcu_read_unlock();
 	return in_dev;
 }
 
@@ -157,8 +158,7 @@
 
 extern void in_dev_finish_destroy(struct in_device *idev);
 
-static __inline__ void
-in_dev_put(struct in_device *idev)
+static inline void in_dev_put(struct in_device *idev)
 {
 	if (atomic_dec_and_test(&idev->refcnt))
 		in_dev_finish_destroy(idev);
diff -Nru a/include/linux/input.h b/include/linux/input.h
--- a/include/linux/input.h	2004-10-18 14:56:29 -07:00
+++ b/include/linux/input.h	2004-10-18 14:56:29 -07:00
@@ -527,6 +527,8 @@
 #define MSC_SERIAL		0x00
 #define MSC_PULSELED		0x01
 #define MSC_GESTURE		0x02
+#define MSC_RAW			0x03
+#define MSC_SCAN		0x04
 #define MSC_MAX			0x07
 
 /*
diff -Nru a/include/linux/interrupt.h b/include/linux/interrupt.h
--- a/include/linux/interrupt.h	2004-10-18 14:56:32 -07:00
+++ b/include/linux/interrupt.h	2004-10-18 14:56:32 -07:00
@@ -8,8 +8,8 @@
 #include <linux/bitops.h>
 #include <linux/preempt.h>
 #include <linux/cpumask.h>
+#include <linux/hardirq.h>
 #include <asm/atomic.h>
-#include <asm/hardirq.h>
 #include <asm/ptrace.h>
 #include <asm/system.h>
 
diff -Nru a/include/linux/ioctl32.h b/include/linux/ioctl32.h
--- a/include/linux/ioctl32.h	2004-10-18 14:55:54 -07:00
+++ b/include/linux/ioctl32.h	2004-10-18 14:55:54 -07:00
@@ -3,6 +3,15 @@
 
 struct file;
 
+typedef int (*ioctl_trans_handler_t)(unsigned int, unsigned int,
+					unsigned long, struct file *);
+
+struct ioctl_trans {
+	unsigned long cmd;
+	ioctl_trans_handler_t handler;
+	struct ioctl_trans *next;
+};
+
 /* 
  * Register an 32bit ioctl translation handler for ioctl cmd.
  *
@@ -13,16 +22,16 @@
  *                        struct file *file: file descriptor pointer.
  */ 
 
-extern int register_ioctl32_conversion(unsigned int cmd, int (*handler)(unsigned int, unsigned int, unsigned long, struct file *));
-
+#ifdef CONFIG_COMPAT
+extern int register_ioctl32_conversion(unsigned int cmd,
+				ioctl_trans_handler_t handler);
 extern int unregister_ioctl32_conversion(unsigned int cmd);
 
-typedef int (*ioctl_trans_handler_t)(unsigned int, unsigned int, unsigned long, struct file *);
+#else
 
-struct ioctl_trans {
-	unsigned long cmd;
-	ioctl_trans_handler_t handler;
-	struct ioctl_trans *next;
-};
+#define register_ioctl32_conversion(cmd, handler)	({ 0; })
+#define unregister_ioctl32_conversion(cmd)		({ 0; })
+
+#endif
 
 #endif
diff -Nru a/include/linux/ip6_tunnel.h b/include/linux/ip6_tunnel.h
--- a/include/linux/ip6_tunnel.h	2004-10-18 14:55:53 -07:00
+++ b/include/linux/ip6_tunnel.h	2004-10-18 14:55:53 -07:00
@@ -16,6 +16,8 @@
 #define IP6_TNL_F_USE_ORIG_FLOWLABEL 0x4
 /* being used for Mobile IPv6 */
 #define IP6_TNL_F_MIP6_DEV 0x8
+/* copy DSCP from the outer packet */
+#define IP6_TNL_F_RCV_DSCP_COPY 0x10
 
 struct ip6_tnl_parm {
 	char name[IFNAMSIZ];	/* name of tunnel device */
diff -Nru a/include/linux/ipmi.h b/include/linux/ipmi.h
--- a/include/linux/ipmi.h	2004-10-18 14:57:05 -07:00
+++ b/include/linux/ipmi.h	2004-10-18 14:57:05 -07:00
@@ -406,6 +406,12 @@
 			    unsigned char cmd);
 
 /*
+ * Allow run-to-completion mode to be set for the interface of
+ * a specific user.
+ */
+void ipmi_user_set_run_to_completion(ipmi_user_t user, int val);
+
+/*
  * When the user is created, it will not receive IPMI events by
  * default.  The user must set this to TRUE to get incoming events.
  * The first user that sets this to TRUE will receive all events that
diff -Nru a/include/linux/ipv6.h b/include/linux/ipv6.h
--- a/include/linux/ipv6.h	2004-10-18 14:56:48 -07:00
+++ b/include/linux/ipv6.h	2004-10-18 14:56:48 -07:00
@@ -182,8 +182,7 @@
    as offsets from skb->nh.
  */
 
-struct inet6_skb_parm
-{
+struct inet6_skb_parm {
 	int			iif;
 	__u16			ra;
 	__u16			hop;
@@ -194,6 +193,14 @@
 
 #define IP6CB(skb)	((struct inet6_skb_parm*)((skb)->cb))
 
+/**
+ * struct ipv6_pinfo - ipv6 private area
+ *
+ * In the struct sock hierarchy (tcp6_sock, upd6_sock, etc)
+ * this _must_ be the last member, so that inet6_sk_generic
+ * is able to calculate its offset from the base struct sock
+ * by using the struct proto->slab_obj_size member. -acme
+ */
 struct ipv6_pinfo {
 	struct in6_addr 	saddr;
 	struct in6_addr 	rcv_saddr;
diff -Nru a/include/linux/isicom.h b/include/linux/isicom.h
--- a/include/linux/isicom.h	2004-10-18 14:56:28 -07:00
+++ b/include/linux/isicom.h	2004-10-18 14:56:28 -07:00
@@ -102,7 +102,6 @@
 #define ClearInterrupt(base) (inw((base)+0x0a))	
 
 #define	BOARD(line)  (((line) >> 4) & 0x3)
-#define MIN(a, b) ( (a) < (b) ? (a) : (b) )
 
 	/*	isi kill queue bitmap	*/
 	
diff -Nru a/include/linux/iso_fs.h b/include/linux/iso_fs.h
--- a/include/linux/iso_fs.h	2004-10-18 14:56:33 -07:00
+++ b/include/linux/iso_fs.h	2004-10-18 14:56:33 -07:00
@@ -192,29 +192,29 @@
 }
 static inline unsigned int isonum_721(char *p)
 {
-	return le16_to_cpu(get_unaligned((u16 *)p));
+	return le16_to_cpu(get_unaligned((__le16 *)p));
 }
 static inline unsigned int isonum_722(char *p)
 {
-	return be16_to_cpu(get_unaligned((u16 *)p));
+	return be16_to_cpu(get_unaligned((__le16 *)p));
 }
 static inline unsigned int isonum_723(char *p)
 {
 	/* Ignore bigendian datum due to broken mastering programs */
-	return le16_to_cpu(get_unaligned((u16 *)p));
+	return le16_to_cpu(get_unaligned((__le16 *)p));
 }
 static inline unsigned int isonum_731(char *p)
 {
-	return le32_to_cpu(get_unaligned((u32 *)p));
+	return le32_to_cpu(get_unaligned((__le32 *)p));
 }
 static inline unsigned int isonum_732(char *p)
 {
-	return be32_to_cpu(get_unaligned((u32 *)p));
+	return be32_to_cpu(get_unaligned((__le32 *)p));
 }
 static inline unsigned int isonum_733(char *p)
 {
 	/* Ignore bigendian datum due to broken mastering programs */
-	return le32_to_cpu(get_unaligned((u32 *)p));
+	return le32_to_cpu(get_unaligned((__le32 *)p));
 }
 extern int iso_date(char *, int);
 
diff -Nru a/include/linux/jbd.h b/include/linux/jbd.h
--- a/include/linux/jbd.h	2004-10-18 14:56:49 -07:00
+++ b/include/linux/jbd.h	2004-10-18 14:56:49 -07:00
@@ -137,9 +137,9 @@
  */
 typedef struct journal_header_s
 {
-	__u32		h_magic;
-	__u32		h_blocktype;
-	__u32		h_sequence;
+	__be32		h_magic;
+	__be32		h_blocktype;
+	__be32		h_sequence;
 } journal_header_t;
 
 
@@ -148,8 +148,8 @@
  */
 typedef struct journal_block_tag_s
 {
-	__u32		t_blocknr;	/* The on-disk block number */
-	__u32		t_flags;	/* See below */
+	__be32		t_blocknr;	/* The on-disk block number */
+	__be32		t_flags;	/* See below */
 } journal_block_tag_t;
 
 /* 
@@ -159,7 +159,7 @@
 typedef struct journal_revoke_header_s
 {
 	journal_header_t r_header;
-	int		 r_count;	/* Count of bytes used in the block */
+	__be32		 r_count;	/* Count of bytes used in the block */
 } journal_revoke_header_t;
 
 
@@ -180,35 +180,35 @@
 
 /* 0x000C */
 	/* Static information describing the journal */
-	__u32	s_blocksize;		/* journal device blocksize */
-	__u32	s_maxlen;		/* total blocks in journal file */
-	__u32	s_first;		/* first block of log information */
+	__be32	s_blocksize;		/* journal device blocksize */
+	__be32	s_maxlen;		/* total blocks in journal file */
+	__be32	s_first;		/* first block of log information */
 
 /* 0x0018 */
 	/* Dynamic information describing the current state of the log */
-	__u32	s_sequence;		/* first commit ID expected in log */
-	__u32	s_start;		/* blocknr of start of log */
+	__be32	s_sequence;		/* first commit ID expected in log */
+	__be32	s_start;		/* blocknr of start of log */
 
 /* 0x0020 */
 	/* Error value, as set by journal_abort(). */
-	__s32	s_errno;
+	__be32	s_errno;
 
 /* 0x0024 */
 	/* Remaining fields are only valid in a version-2 superblock */
-	__u32	s_feature_compat; 	/* compatible feature set */
-	__u32	s_feature_incompat; 	/* incompatible feature set */
-	__u32	s_feature_ro_compat; 	/* readonly-compatible feature set */
+	__be32	s_feature_compat; 	/* compatible feature set */
+	__be32	s_feature_incompat; 	/* incompatible feature set */
+	__be32	s_feature_ro_compat; 	/* readonly-compatible feature set */
 /* 0x0030 */
 	__u8	s_uuid[16];		/* 128-bit uuid for journal */
 
 /* 0x0040 */
-	__u32	s_nr_users;		/* Nr of filesystems sharing log */
+	__be32	s_nr_users;		/* Nr of filesystems sharing log */
 
-	__u32	s_dynsuper;		/* Blocknr of dynamic superblock copy*/
+	__be32	s_dynsuper;		/* Blocknr of dynamic superblock copy*/
 
 /* 0x0048 */
-	__u32	s_max_transaction;	/* Limit of journal blocks per trans.*/
-	__u32	s_max_trans_data;	/* Limit of data blocks per trans. */
+	__be32	s_max_transaction;	/* Limit of journal blocks per trans.*/
+	__be32	s_max_trans_data;	/* Limit of data blocks per trans. */
 
 /* 0x0050 */
 	__u32	s_padding[44];
@@ -840,6 +840,7 @@
 #define JFS_ACK_ERR	0x004	/* The errno in the sb has been acked */
 #define JFS_FLUSHED	0x008	/* The journal superblock has been flushed */
 #define JFS_LOADED	0x010	/* The journal superblock has been loaded */
+#define JFS_BARRIER	0x020	/* Use IDE barriers */
 
 /* 
  * Function declarations for the journaling transaction and buffer
diff -Nru a/include/linux/kernel.h b/include/linux/kernel.h
--- a/include/linux/kernel.h	2004-10-18 14:55:53 -07:00
+++ b/include/linux/kernel.h	2004-10-18 14:55:53 -07:00
@@ -12,6 +12,7 @@
 #include <linux/stddef.h>
 #include <linux/types.h>
 #include <linux/compiler.h>
+#include <linux/bitops.h>
 #include <asm/byteorder.h>
 #include <asm/bug.h>
 
@@ -97,6 +98,7 @@
 extern int kernel_text_address(unsigned long addr);
 extern int session_of_pgrp(int pgrp);
 
+asmlinkage int vprintk(const char *fmt, va_list args);
 asmlinkage int printk(const char * fmt, ...)
 	__attribute__ ((format (printf, 1, 2)));
 
@@ -110,6 +112,10 @@
 	return r;
 }
 
+static inline unsigned long __attribute_const__ roundup_pow_of_two(unsigned long x)
+{
+	return (1UL << fls(x - 1));
+}
 
 extern int printk_ratelimit(void);
 extern int __printk_ratelimit(int ratelimit_jiffies, int ratelimit_burst);
diff -Nru a/include/linux/kmod.h b/include/linux/kmod.h
--- a/include/linux/kmod.h	2004-10-18 14:56:17 -07:00
+++ b/include/linux/kmod.h	2004-10-18 14:56:17 -07:00
@@ -35,6 +35,7 @@
 
 #define try_then_request_module(x, mod...) ((x) ?: (request_module(mod), (x)))
 extern int call_usermodehelper(char *path, char *argv[], char *envp[], int wait);
+extern void usermodehelper_init(void);
 
 #ifdef CONFIG_HOTPLUG
 extern char hotplug_path [];
diff -Nru a/include/linux/kobject.h b/include/linux/kobject.h
--- a/include/linux/kobject.h	2004-10-18 14:55:54 -07:00
+++ b/include/linux/kobject.h	2004-10-18 14:55:54 -07:00
@@ -12,13 +12,16 @@
  * destructors. 
  */
 
-#if defined(__KERNEL__) && !defined(_KOBJECT_H_)
+#ifndef _KOBJECT_H_
 #define _KOBJECT_H_
 
+#ifdef __KERNEL__
+
 #include <linux/types.h>
 #include <linux/list.h>
 #include <linux/sysfs.h>
 #include <linux/rwsem.h>
+#include <linux/kref.h>
 #include <asm/atomic.h>
 
 #define KOBJ_NAME_LEN	20
@@ -26,7 +29,7 @@
 struct kobject {
 	char			* k_name;
 	char			name[KOBJ_NAME_LEN];
-	atomic_t		refcount;
+	struct kref		kref;
 	struct list_head	entry;
 	struct kobject		* parent;
 	struct kset		* kset;
@@ -58,6 +61,8 @@
 
 extern void kobject_hotplug(const char *action, struct kobject *);
 
+extern char * kobject_get_path(struct kset *, struct kobject *, int);
+
 struct kobj_type {
 	void (*release)(struct kobject *);
 	struct sysfs_ops	* sysfs_ops;
@@ -229,5 +234,5 @@
 extern int subsys_create_file(struct subsystem * , struct subsys_attribute *);
 extern void subsys_remove_file(struct subsystem * , struct subsys_attribute *);
 
-
+#endif /* __KERNEL__ */
 #endif /* _KOBJECT_H_ */
diff -Nru a/include/linux/kprobes.h b/include/linux/kprobes.h
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/include/linux/kprobes.h	2004-10-18 14:57:22 -07:00
@@ -0,0 +1,134 @@
+#ifndef _LINUX_KPROBES_H
+#define _LINUX_KPROBES_H
+/*
+ *  Kernel Probes (KProbes)
+ *  include/linux/kprobes.h
+ *
+ * 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.
+ *
+ * Copyright (C) IBM Corporation, 2002, 2004
+ *
+ * 2002-Oct	Created by Vamsi Krishna S <vamsi_krishna@in.ibm.com> Kernel
+ *		Probes initial implementation ( includes suggestions from
+ *		Rusty Russell).
+ * 2004-July	Suparna Bhattacharya <suparna@in.ibm.com> added jumper probes
+ *		interface to access function arguments.
+ */
+#include <linux/config.h>
+#include <linux/list.h>
+#include <linux/notifier.h>
+#include <linux/smp.h>
+#include <asm/kprobes.h>
+
+struct kprobe;
+struct pt_regs;
+typedef int (*kprobe_pre_handler_t) (struct kprobe *, struct pt_regs *);
+typedef int (*kprobe_break_handler_t) (struct kprobe *, struct pt_regs *);
+typedef void (*kprobe_post_handler_t) (struct kprobe *, struct pt_regs *,
+				       unsigned long flags);
+typedef int (*kprobe_fault_handler_t) (struct kprobe *, struct pt_regs *,
+				       int trapnr);
+struct kprobe {
+	struct hlist_node hlist;
+
+	/* location of the probe point */
+	kprobe_opcode_t *addr;
+
+	/* Called before addr is executed. */
+	kprobe_pre_handler_t pre_handler;
+
+	/* Called after addr is executed, unless... */
+	kprobe_post_handler_t post_handler;
+
+	/* ... called if executing addr causes a fault (eg. page fault).
+	 * Return 1 if it handled fault, otherwise kernel will see it. */
+	kprobe_fault_handler_t fault_handler;
+
+	/* ... called if breakpoint trap occurs in probe handler.
+	 * Return 1 if it handled break, otherwise kernel will see it. */
+	kprobe_break_handler_t break_handler;
+
+	/* Saved opcode (which has been replaced with breakpoint) */
+	kprobe_opcode_t opcode;
+
+	/* copy of the original instruction */
+	kprobe_opcode_t insn[MAX_INSN_SIZE];
+};
+
+/*
+ * Special probe type that uses setjmp-longjmp type tricks to resume
+ * execution at a specified entry with a matching prototype corresponding
+ * to the probed function - a trick to enable arguments to become
+ * accessible seamlessly by probe handling logic.
+ * Note:
+ * Because of the way compilers allocate stack space for local variables
+ * etc upfront, regardless of sub-scopes within a function, this mirroring
+ * principle currently works only for probes placed on function entry points.
+ */
+struct jprobe {
+	struct kprobe kp;
+	kprobe_opcode_t *entry;	/* probe handling code to jump to */
+};
+
+#ifdef CONFIG_KPROBES
+/* Locks kprobe: irq must be disabled */
+void lock_kprobes(void);
+void unlock_kprobes(void);
+
+/* kprobe running now on this CPU? */
+static inline int kprobe_running(void)
+{
+	extern unsigned int kprobe_cpu;
+	return kprobe_cpu == smp_processor_id();
+}
+
+extern void arch_prepare_kprobe(struct kprobe *p);
+extern void show_registers(struct pt_regs *regs);
+
+/* Get the kprobe at this addr (if any).  Must have called lock_kprobes */
+struct kprobe *get_kprobe(void *addr);
+
+int register_kprobe(struct kprobe *p);
+void unregister_kprobe(struct kprobe *p);
+int setjmp_pre_handler(struct kprobe *, struct pt_regs *);
+int longjmp_break_handler(struct kprobe *, struct pt_regs *);
+int register_jprobe(struct jprobe *p);
+void unregister_jprobe(struct jprobe *p);
+void jprobe_return(void);
+
+#else
+static inline int kprobe_running(void)
+{
+	return 0;
+}
+static inline int register_kprobe(struct kprobe *p)
+{
+	return -ENOSYS;
+}
+static inline void unregister_kprobe(struct kprobe *p)
+{
+}
+static inline int register_jprobe(struct jprobe *p)
+{
+	return -ENOSYS;
+}
+static inline void unregister_jprobe(struct jprobe *p)
+{
+}
+static inline void jprobe_return(void)
+{
+}
+#endif
+#endif				/* _LINUX_KPROBES_H */
diff -Nru a/include/linux/kref.h b/include/linux/kref.h
--- a/include/linux/kref.h	2004-10-18 14:56:11 -07:00
+++ b/include/linux/kref.h	2004-10-18 14:56:11 -07:00
@@ -12,21 +12,21 @@
  *
  */
 
-#if defined(__KERNEL__) && !defined(_KREF_H_)
+#ifndef _KREF_H_
 #define _KREF_H_
 
+#ifdef __KERNEL__
+
 #include <linux/types.h>
 #include <asm/atomic.h>
 
-
 struct kref {
 	atomic_t refcount;
-	void (*release)(struct kref *kref);
 };
 
-void kref_init(struct kref *kref, void (*release)(struct kref *));
-struct kref *kref_get(struct kref *kref);
-void kref_put(struct kref *kref);
-
+void kref_init(struct kref *kref);
+void kref_get(struct kref *kref);
+void kref_put(struct kref *kref, void (*release) (struct kref *kref));
 
+#endif /* __KERNEL__ */
 #endif /* _KREF_H_ */
diff -Nru a/include/linux/libata.h b/include/linux/libata.h
--- a/include/linux/libata.h	2004-10-18 14:55:54 -07:00
+++ b/include/linux/libata.h	2004-10-18 14:55:54 -07:00
@@ -32,7 +32,6 @@
 /*
  * compile-time options
  */
-#undef ATA_FORCE_PIO		/* do not configure or use DMA */
 #undef ATA_DEBUG		/* debugging output */
 #undef ATA_VERBOSE_DEBUG	/* yet more debugging output */
 #undef ATA_IRQ_TRAP		/* define to ack screaming irqs */
@@ -88,10 +87,7 @@
 	/* struct ata_device stuff */
 	ATA_DFLAG_LBA48		= (1 << 0), /* device supports LBA48 */
 	ATA_DFLAG_PIO		= (1 << 1), /* device currently in PIO mode */
-	ATA_DFLAG_MASTER	= (1 << 2), /* is device 0? */
-	ATA_DFLAG_WCACHE	= (1 << 3), /* has write cache we can
-					     * (hopefully) flush? */
-	ATA_DFLAG_LOCK_SECTORS	= (1 << 4), /* don't adjust max_sectors */
+	ATA_DFLAG_LOCK_SECTORS	= (1 << 2), /* don't adjust max_sectors */
 
 	ATA_DEV_UNKNOWN		= 0,	/* unknown device */
 	ATA_DEV_ATA		= 1,	/* ATA device */
@@ -111,7 +107,6 @@
 	ATA_FLAG_SATA_RESET	= (1 << 7), /* use COMRESET */
 
 	ATA_QCFLAG_ACTIVE	= (1 << 1), /* cmd not yet ack'd to scsi lyer */
-	ATA_QCFLAG_DMA		= (1 << 2), /* data delivered via DMA */
 	ATA_QCFLAG_SG		= (1 << 3), /* have s/g table? */
 	ATA_QCFLAG_SINGLE	= (1 << 4), /* no s/g, just a single buffer */
 	ATA_QCFLAG_DMAMAP	= ATA_QCFLAG_SG | ATA_QCFLAG_SINGLE,
@@ -140,6 +135,13 @@
 	PORT_UNKNOWN		= 0,
 	PORT_ENABLED		= 1,
 	PORT_DISABLED		= 2,
+
+	/* encoding various smaller bitmaps into a single
+	 * unsigned long bitmap
+	 */
+	ATA_SHIFT_UDMA		= 0,
+	ATA_SHIFT_MWDMA		= 8,
+	ATA_SHIFT_PIO		= 11,
 };
 
 enum pio_task_states {
@@ -188,12 +190,13 @@
 	struct ata_ioports	port[ATA_MAX_PORTS];
 	unsigned int		n_ports;
 	unsigned int		pio_mask;
+	unsigned int		mwdma_mask;
 	unsigned int		udma_mask;
 	unsigned int		legacy_mode;
 	unsigned long		irq;
 	unsigned int		irq_flags;
 	unsigned long		host_flags;
-	void			*mmio_base;
+	void __iomem		*mmio_base;
 	void			*private_data;
 };
 
@@ -201,7 +204,7 @@
 	spinlock_t		lock;
 	struct pci_dev		*pdev;
 	unsigned long		irq;
-	void			*mmio_base;
+	void __iomem		*mmio_base;
 	unsigned int		n_ports;
 	void			*private_data;
 	struct ata_port_operations *ops;
@@ -215,6 +218,9 @@
 	struct scsi_cmnd	*scsicmd;
 	void			(*scsidone)(struct scsi_cmnd *);
 
+	struct ata_taskfile	tf;
+	u8			cdb[ATAPI_CDB_LEN];
+
 	unsigned long		flags;		/* ATA_QCFLAG_xxx */
 	unsigned int		tag;
 	unsigned int		n_elem;
@@ -226,7 +232,6 @@
 	unsigned int		cursg;
 	unsigned int		cursg_ofs;
 
-	struct ata_taskfile	tf;
 	struct scatterlist	sgent;
 	void			*buf_virt;
 
@@ -251,8 +256,10 @@
 	unsigned int		class;		/* ATA_DEV_xxx */
 	unsigned int		devno;		/* 0 or 1 */
 	u16			id[ATA_ID_WORDS]; /* IDENTIFY xxx DEVICE data */
-	unsigned int		pio_mode;
-	unsigned int		udma_mode;
+	u8			pio_mode;
+	u8			dma_mode;
+	u8			xfer_mode;
+	unsigned int		xfer_shift;	/* ATA_SHIFT_xxx */
 
 	/* cache info about current transfer mode */
 	u8			xfer_protocol;	/* taskfile xfer protocol */
@@ -277,8 +284,10 @@
 	unsigned int		bus_state;
 	unsigned int		port_state;
 	unsigned int		pio_mask;
+	unsigned int		mwdma_mask;
 	unsigned int		udma_mask;
 	unsigned int		cbl;	/* cable type; ATA_CBL_xxx */
+	unsigned int		cdb_len;
 
 	struct ata_device	device[ATA_MAX_DEVICES];
 
@@ -303,16 +312,15 @@
 
 	void (*dev_config) (struct ata_port *, struct ata_device *);
 
-	void (*set_piomode) (struct ata_port *, struct ata_device *,
-			     unsigned int);
-	void (*set_udmamode) (struct ata_port *, struct ata_device *,
-			     unsigned int);
+	void (*set_piomode) (struct ata_port *, struct ata_device *);
+	void (*set_dmamode) (struct ata_port *, struct ata_device *);
 
 	void (*tf_load) (struct ata_port *ap, struct ata_taskfile *tf);
 	void (*tf_read) (struct ata_port *ap, struct ata_taskfile *tf);
 
 	void (*exec_command)(struct ata_port *ap, struct ata_taskfile *tf);
 	u8   (*check_status)(struct ata_port *ap);
+	void (*dev_select)(struct ata_port *ap, unsigned int device);
 
 	void (*phy_reset) (struct ata_port *ap);
 	void (*post_set_mode) (struct ata_port *ap);
@@ -342,6 +350,7 @@
 	Scsi_Host_Template	*sht;
 	unsigned long		host_flags;
 	unsigned long		pio_mask;
+	unsigned long		mwdma_mask;
 	unsigned long		udma_mask;
 	struct ata_port_operations	*port_ops;
 };
@@ -354,6 +363,7 @@
 };
 
 extern void ata_port_probe(struct ata_port *);
+extern void __sata_phy_reset(struct ata_port *ap);
 extern void sata_phy_reset(struct ata_port *ap);
 extern void ata_bus_reset(struct ata_port *ap);
 extern void ata_port_disable(struct ata_port *);
@@ -363,6 +373,7 @@
 extern void ata_pci_remove_one (struct pci_dev *pdev);
 extern int ata_device_add(struct ata_probe_ent *ent);
 extern int ata_scsi_detect(Scsi_Host_Template *sht);
+extern int ata_scsi_ioctl(struct scsi_device *dev, int cmd, void __user *arg);
 extern int ata_scsi_queuecmd(struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd *));
 extern int ata_scsi_error(struct Scsi_Host *host);
 extern int ata_scsi_release(struct Scsi_Host *host);
@@ -370,31 +381,32 @@
 /*
  * Default driver ops implementations
  */
-extern void ata_tf_load_pio(struct ata_port *ap, struct ata_taskfile *tf);
-extern void ata_tf_load_mmio(struct ata_port *ap, struct ata_taskfile *tf);
-extern void ata_tf_read_pio(struct ata_port *ap, struct ata_taskfile *tf);
-extern void ata_tf_read_mmio(struct ata_port *ap, struct ata_taskfile *tf);
+extern void ata_tf_load(struct ata_port *ap, struct ata_taskfile *tf);
+extern void ata_tf_read(struct ata_port *ap, struct ata_taskfile *tf);
 extern void ata_tf_to_fis(struct ata_taskfile *tf, u8 *fis, u8 pmp);
 extern void ata_tf_from_fis(u8 *fis, struct ata_taskfile *tf);
-extern u8 ata_check_status_pio(struct ata_port *ap);
-extern u8 ata_check_status_mmio(struct ata_port *ap);
-extern void ata_exec_command_pio(struct ata_port *ap, struct ata_taskfile *tf);
-extern void ata_exec_command_mmio(struct ata_port *ap, struct ata_taskfile *tf);
+extern void ata_noop_dev_select (struct ata_port *ap, unsigned int device);
+extern void ata_std_dev_select (struct ata_port *ap, unsigned int device);
+extern u8 ata_check_status(struct ata_port *ap);
+extern void ata_exec_command(struct ata_port *ap, struct ata_taskfile *tf);
 extern int ata_port_start (struct ata_port *ap);
 extern void ata_port_stop (struct ata_port *ap);
 extern irqreturn_t ata_interrupt (int irq, void *dev_instance, struct pt_regs *regs);
+extern struct ata_probe_ent *
+ata_pci_init_native_mode(struct pci_dev *pdev, struct ata_port_info **port);
+extern struct ata_probe_ent *
+ata_pci_init_legacy_mode(struct pci_dev *pdev, struct ata_port_info **port);
 extern void ata_qc_prep(struct ata_queued_cmd *qc);
 extern int ata_qc_issue_prot(struct ata_queued_cmd *qc);
 extern void ata_sg_init_one(struct ata_queued_cmd *qc, void *buf,
 		unsigned int buflen);
 extern void ata_sg_init(struct ata_queued_cmd *qc, struct scatterlist *sg,
 		 unsigned int n_elem);
+extern unsigned int ata_dev_classify(struct ata_taskfile *tf);
 extern void ata_dev_id_string(struct ata_device *dev, unsigned char *s,
 			      unsigned int ofs, unsigned int len);
-extern void ata_bmdma_setup_mmio (struct ata_queued_cmd *qc);
-extern void ata_bmdma_start_mmio (struct ata_queued_cmd *qc);
-extern void ata_bmdma_setup_pio (struct ata_queued_cmd *qc);
-extern void ata_bmdma_start_pio (struct ata_queued_cmd *qc);
+extern void ata_bmdma_setup (struct ata_queued_cmd *qc);
+extern void ata_bmdma_start (struct ata_queued_cmd *qc);
 extern void ata_bmdma_irq_clear(struct ata_port *ap);
 extern int pci_test_config_bits(struct pci_dev *pdev, struct pci_bits *bits);
 extern void ata_qc_complete(struct ata_queued_cmd *qc, u8 drv_stat);
@@ -419,7 +431,7 @@
 static inline u8 ata_chk_err(struct ata_port *ap)
 {
 	if (ap->flags & ATA_FLAG_MMIO) {
-		return readb((void *) ap->ioaddr.error_addr);
+		return readb((void __iomem *) ap->ioaddr.error_addr);
 	}
 	return inb(ap->ioaddr.error_addr);
 }
@@ -432,7 +444,7 @@
 static inline u8 ata_altstatus(struct ata_port *ap)
 {
 	if (ap->flags & ATA_FLAG_MMIO)
-		return readb(ap->ioaddr.altstatus_addr);
+		return readb((void __iomem *)ap->ioaddr.altstatus_addr);
 	return inb(ap->ioaddr.altstatus_addr);
 }
 
@@ -472,7 +484,6 @@
 
 static inline void ata_qc_set_polling(struct ata_queued_cmd *qc)
 {
-	qc->flags &= ~ATA_QCFLAG_DMA;
 	qc->tf.ctl |= ATA_NIEN;
 }
 
@@ -504,7 +515,7 @@
 	ap->last_ctl = ap->ctl;
 
 	if (ap->flags & ATA_FLAG_MMIO)
-		writeb(ap->ctl, ioaddr->ctl_addr);
+		writeb(ap->ctl, (void __iomem *) ioaddr->ctl_addr);
 	else
 		outb(ap->ctl, ioaddr->ctl_addr);
 	tmp = ata_wait_idle(ap);
@@ -525,7 +536,7 @@
 
 	/* get controller status; clear intr, err bits */
 	if (ap->flags & ATA_FLAG_MMIO) {
-		void *mmio = (void *) ap->ioaddr.bmdma_addr;
+		void __iomem *mmio = (void __iomem *) ap->ioaddr.bmdma_addr;
 		host_stat = readb(mmio + ATA_DMA_STATUS);
 		writeb(host_stat | ATA_DMA_INTR | ATA_DMA_ERR,
 		       mmio + ATA_DMA_STATUS);
@@ -563,7 +574,7 @@
 static inline void ata_bmdma_stop(struct ata_port *ap)
 {
 	if (ap->flags & ATA_FLAG_MMIO) {
-		void *mmio = (void *) ap->ioaddr.bmdma_addr;
+		void __iomem *mmio = (void __iomem *) ap->ioaddr.bmdma_addr;
 
 		/* clear start/stop bit */
 		writeb(readb(mmio + ATA_DMA_CMD) & ~ATA_DMA_START,
@@ -581,7 +592,7 @@
 static inline void ata_bmdma_ack_irq(struct ata_port *ap)
 {
 	if (ap->flags & ATA_FLAG_MMIO) {
-		void *mmio = ((void *) ap->ioaddr.bmdma_addr) + ATA_DMA_STATUS;
+		void __iomem *mmio = ((void __iomem *) ap->ioaddr.bmdma_addr) + ATA_DMA_STATUS;
 		writeb(readb(mmio), mmio);
 	} else {
 		unsigned long addr = ap->ioaddr.bmdma_addr + ATA_DMA_STATUS;
@@ -593,11 +604,18 @@
 {
 	u8 host_stat;
 	if (ap->flags & ATA_FLAG_MMIO) {
-		void *mmio = (void *) ap->ioaddr.bmdma_addr;
+		void __iomem *mmio = (void __iomem *) ap->ioaddr.bmdma_addr;
 		host_stat = readb(mmio + ATA_DMA_STATUS);
 	} else
 		host_stat = inb(ap->ioaddr.bmdma_addr + ATA_DMA_STATUS);
 	return host_stat;
+}
+
+static inline int ata_try_flush_cache(struct ata_device *dev)
+{
+	return ata_id_wcache_enabled(dev) ||
+	       ata_id_has_flush(dev) ||
+	       ata_id_has_flush_ext(dev);
 }
 
 #endif /* __LINUX_LIBATA_H__ */
diff -Nru a/include/linux/linkage.h b/include/linux/linkage.h
--- a/include/linux/linkage.h	2004-10-18 14:56:33 -07:00
+++ b/include/linux/linkage.h	2004-10-18 14:56:33 -07:00
@@ -14,6 +14,10 @@
 #define asmlinkage CPP_ASMLINKAGE
 #endif
 
+#ifndef prevent_tail_call
+# define prevent_tail_call(ret) do { } while (0)
+#endif
+
 #ifndef __ALIGN
 #define __ALIGN		.align 4,0x90
 #define __ALIGN_STR	".align 4,0x90"
diff -Nru a/include/linux/list.h b/include/linux/list.h
--- a/include/linux/list.h	2004-10-18 14:56:32 -07:00
+++ b/include/linux/list.h	2004-10-18 14:56:32 -07:00
@@ -195,6 +195,21 @@
 	entry->prev = LIST_POISON2;
 }
 
+/*
+ * list_replace_rcu - replace old entry by new one
+ * @old : the element to be replaced
+ * @new : the new element to insert
+ *
+ * The old entry will be replaced with the new entry atomically.
+ */
+static inline void list_replace_rcu(struct list_head *old, struct list_head *new){
+	new->next = old->next;
+	new->prev = old->prev;
+	smp_wmb();
+	new->next->prev = new;
+	new->prev->next = new;
+}
+
 /**
  * list_del_init - deletes entry from list and reinitialize it.
  * @entry: the element to delete from the list.
@@ -420,11 +435,11 @@
  */
 #define list_for_each_rcu(pos, head) \
 	for (pos = (head)->next, prefetch(pos->next); pos != (head); \
-        	pos = pos->next, ({ smp_read_barrier_depends(); 0;}), prefetch(pos->next))
+        	pos = rcu_dereference(pos->next), prefetch(pos->next))
 
 #define __list_for_each_rcu(pos, head) \
 	for (pos = (head)->next; pos != (head); \
-        	pos = pos->next, ({ smp_read_barrier_depends(); 0;}))
+        	pos = rcu_dereference(pos->next))
 
 /**
  * list_for_each_safe_rcu	-	iterate over an rcu-protected list safe
@@ -439,7 +454,7 @@
  */
 #define list_for_each_safe_rcu(pos, n, head) \
 	for (pos = (head)->next, n = pos->next; pos != (head); \
-		pos = n, ({ smp_read_barrier_depends(); 0;}), n = pos->next)
+		pos = rcu_dereference(n), n = pos->next)
 
 /**
  * list_for_each_entry_rcu	-	iterate over rcu list of given type
@@ -455,8 +470,8 @@
 	for (pos = list_entry((head)->next, typeof(*pos), member),	\
 		     prefetch(pos->member.next);			\
 	     &pos->member != (head); 					\
-	     pos = list_entry(pos->member.next, typeof(*pos), member),	\
-		     ({ smp_read_barrier_depends(); 0;}),		\
+	     pos = rcu_dereference(list_entry(pos->member.next, 	\
+					typeof(*pos), member)),		\
 		     prefetch(pos->member.next))
 
 
@@ -472,7 +487,7 @@
  */
 #define list_for_each_continue_rcu(pos, head) \
 	for ((pos) = (pos)->next, prefetch((pos)->next); (pos) != (head); \
-        	(pos) = (pos)->next, ({ smp_read_barrier_depends(); 0;}), prefetch((pos)->next))
+        	(pos) = rcu_dereference((pos)->next), prefetch((pos)->next))
 
 /*
  * Double linked lists with a single pointer list head.
@@ -578,12 +593,9 @@
  * or hlist_del_rcu(), running on this same list.
  * However, it is perfectly legal to run concurrently with
  * the _rcu list-traversal primitives, such as
- * hlist_for_each_entry(), but only if smp_read_barrier_depends()
- * is used to prevent memory-consistency problems on Alpha CPUs.
- * Regardless of the type of CPU, the list-traversal primitive
- * must be guarded by rcu_read_lock().
- *
- * OK, so why don't we have an hlist_for_each_entry_rcu()???
+ * hlist_for_each_rcu(), used to prevent memory-consistency
+ * problems on Alpha CPUs.  Regardless of the type of CPU, the
+ * list-traversal primitive must be guarded by rcu_read_lock().
  */
 static inline void hlist_add_head_rcu(struct hlist_node *n,
 					struct hlist_head *h)
@@ -628,6 +640,10 @@
 	for (pos = (head)->first; pos && ({ n = pos->next; 1; }); \
 	     pos = n)
 
+#define hlist_for_each_rcu(pos, head) \
+	for ((pos) = (head)->first; pos && ({ prefetch((pos)->next); 1; }); \
+		(pos) = rcu_dereference((pos)->next))
+
 /**
  * hlist_for_each_entry	- iterate over list of given type
  * @tpos:	the type * to use as a loop counter.
@@ -693,7 +709,7 @@
 	for (pos = (head)->first;					 \
 	     pos && ({ prefetch(pos->next); 1;}) &&			 \
 		({ tpos = hlist_entry(pos, typeof(*tpos), member); 1;}); \
-	     pos = pos->next, ({ smp_read_barrier_depends(); 0; }) )
+	     pos = rcu_dereference(pos->next))
 
 #else
 #warning "don't include kernel headers in userspace"
diff -Nru a/include/linux/lockd/bind.h b/include/linux/lockd/bind.h
--- a/include/linux/lockd/bind.h	2004-10-18 14:56:28 -07:00
+++ b/include/linux/lockd/bind.h	2004-10-18 14:56:28 -07:00
@@ -20,7 +20,7 @@
 struct nlmsvc_binding {
 	u32			(*fopen)(struct svc_rqst *,
 						struct nfs_fh *,
-						struct file *);
+						struct file **);
 	void			(*fclose)(struct file *);
 };
 
diff -Nru a/include/linux/lockd/lockd.h b/include/linux/lockd/lockd.h
--- a/include/linux/lockd/lockd.h	2004-10-18 14:56:16 -07:00
+++ b/include/linux/lockd/lockd.h	2004-10-18 14:56:16 -07:00
@@ -52,10 +52,25 @@
 	wait_queue_head_t	h_gracewait;	/* wait while reclaiming */
 	u32			h_state;	/* pseudo-state counter */
 	u32			h_nsmstate;	/* true remote NSM state */
-	unsigned int		h_count;	/* reference count */
+	u32			h_pidcount;	/* Pseudopids */
+	atomic_t		h_count;	/* reference count */
 	struct semaphore	h_sema;		/* mutex for pmap binding */
 	unsigned long		h_nextrebind;	/* next portmap call */
 	unsigned long		h_expires;	/* eligible for GC */
+	struct list_head	h_lockowners;	/* Lockowners for the client */
+	spinlock_t		h_lock;
+};
+
+/*
+ * Map an fl_owner_t into a unique 32-bit "pid"
+ */
+struct nlm_lockowner {
+	struct list_head list;
+	atomic_t count;
+
+	struct nlm_host *host;
+	fl_owner_t owner;
+	uint32_t pid;
 };
 
 /*
@@ -77,7 +92,7 @@
 struct nlm_file {
 	struct nlm_file *	f_next;		/* linked list */
 	struct nfs_fh		f_handle;	/* NFS file handle */
-	struct file		f_file;		/* VFS file pointer */
+	struct file *		f_file;		/* VFS file pointer */
 	struct nlm_share *	f_shares;	/* DOS shares */
 	struct nlm_block *	f_blocks;	/* blocked locks */
 	unsigned int		f_locks;	/* guesstimate # of locks */
@@ -180,7 +195,7 @@
 static __inline__ struct inode *
 nlmsvc_file_inode(struct nlm_file *file)
 {
-	return file->f_file.f_dentry->d_inode;
+	return file->f_file->f_dentry->d_inode;
 }
 
 /*
@@ -204,6 +219,8 @@
 	     && fl1->fl_end   == fl2->fl_end
 	     &&(fl1->fl_type  == fl2->fl_type || fl2->fl_type == F_UNLCK);
 }
+
+extern struct lock_manager_operations nlmsvc_lock_operations;
 
 #endif /* __KERNEL__ */
 
diff -Nru a/include/linux/mempolicy.h b/include/linux/mempolicy.h
--- a/include/linux/mempolicy.h	2004-10-18 14:55:54 -07:00
+++ b/include/linux/mempolicy.h	2004-10-18 14:55:54 -07:00
@@ -68,9 +68,6 @@
 	} v;
 };
 
-/* An NULL mempolicy pointer is a synonym of &default_policy. */
-extern struct mempolicy default_policy;
-
 /*
  * Support for managing mempolicy data objects (clone, copy, destroy)
  * The default fast path of a NULL MPOL_DEFAULT policy is always inlined.
diff -Nru a/include/linux/mii.h b/include/linux/mii.h
--- a/include/linux/mii.h	2004-10-18 14:55:53 -07:00
+++ b/include/linux/mii.h	2004-10-18 14:55:53 -07:00
@@ -33,7 +33,8 @@
 #define MII_NCONFIG         0x1c        /* Network interface config    */
 
 /* Basic mode control register. */
-#define BMCR_RESV               0x007f  /* Unused...                   */
+#define BMCR_RESV               0x003f  /* Unused...                   */
+#define BMCR_SPEED1000		0x0040  /* MSB of Speed (1000)         */
 #define BMCR_CTST               0x0080  /* Collision test              */
 #define BMCR_FULLDPLX           0x0100  /* Full duplex                 */
 #define BMCR_ANRESTART          0x0200  /* Auto negotiation restart    */
diff -Nru a/include/linux/miscdevice.h b/include/linux/miscdevice.h
--- a/include/linux/miscdevice.h	2004-10-18 14:56:33 -07:00
+++ b/include/linux/miscdevice.h	2004-10-18 14:56:33 -07:00
@@ -19,6 +19,7 @@
 #define SUN_OPENPROM_MINOR 139
 #define DMAPI_MINOR		140	/* DMAPI */
 #define NVRAM_MINOR 144
+#define SGI_MMTIMER        153
 #define STORE_QUEUE_MINOR	155
 #define I2O_MINOR 166
 #define MICROCODE_MINOR		184
diff -Nru a/include/linux/mm.h b/include/linux/mm.h
--- a/include/linux/mm.h	2004-10-18 14:55:54 -07:00
+++ b/include/linux/mm.h	2004-10-18 14:55:54 -07:00
@@ -26,6 +26,12 @@
 extern unsigned long vmalloc_earlyreserve;
 extern int page_cluster;
 
+#ifdef CONFIG_SYSCTL
+extern int sysctl_legacy_va_layout;
+#else
+#define sysctl_legacy_va_layout 0
+#endif
+
 #include <asm/page.h>
 #include <asm/pgtable.h>
 #include <asm/processor.h>
@@ -195,21 +201,21 @@
 	page_flags_t flags;		/* Atomic flags, some possibly
 					 * updated asynchronously */
 	atomic_t _count;		/* Usage count, see below. */
-	unsigned int mapcount;		/* Count of ptes mapped in mms,
+	atomic_t _mapcount;		/* Count of ptes mapped in mms,
 					 * to show when page is mapped
-					 * & limit reverse map searches,
-					 * protected by PG_maplock.
+					 * & limit reverse map searches.
 					 */
 	unsigned long private;		/* Mapping-private opaque data:
 					 * usually used for buffer_heads
 					 * if PagePrivate set; used for
 					 * swp_entry_t if PageSwapCache
 					 */
-	struct address_space *mapping;	/* If PG_anon clear, points to
+	struct address_space *mapping;	/* If low bit clear, points to
 					 * inode address_space, or NULL.
 					 * If page mapped as anonymous
-					 * memory, PG_anon is set, and
-					 * it points to anon_vma object.
+					 * memory, low bit is set, and
+					 * it points to anon_vma object:
+					 * see PAGE_MAPPING_ANON below.
 					 */
 	pgoff_t index;			/* Our offset within mapping. */
 	struct list_head lru;		/* Pageout list, eg. active_list
@@ -433,24 +439,32 @@
 
 /*
  * On an anonymous page mapped into a user virtual memory area,
- * page->mapping points to its anon_vma, not to a struct address_space.
+ * page->mapping points to its anon_vma, not to a struct address_space;
+ * with the PAGE_MAPPING_ANON bit set to distinguish it.
  *
  * Please note that, confusingly, "page_mapping" refers to the inode
  * address_space which maps the page from disk; whereas "page_mapped"
  * refers to user virtual address space into which the page is mapped.
  */
+#define PAGE_MAPPING_ANON	1
+
 extern struct address_space swapper_space;
 static inline struct address_space *page_mapping(struct page *page)
 {
-	struct address_space *mapping = NULL;
+	struct address_space *mapping = page->mapping;
 
 	if (unlikely(PageSwapCache(page)))
 		mapping = &swapper_space;
-	else if (likely(!PageAnon(page)))
-		mapping = page->mapping;
+	else if (unlikely((unsigned long)mapping & PAGE_MAPPING_ANON))
+		mapping = NULL;
 	return mapping;
 }
 
+static inline int PageAnon(struct page *page)
+{
+	return ((unsigned long)page->mapping & PAGE_MAPPING_ANON) != 0;
+}
+
 /*
  * Return the pagecache index of the passed page.  Regular pagecache pages
  * use ->index whereas swapcache pages use ->private
@@ -463,11 +477,26 @@
 }
 
 /*
+ * The atomic page->_mapcount, like _count, starts from -1:
+ * so that transitions both from it and to it can be tracked,
+ * using atomic_inc_and_test and atomic_add_negative(-1).
+ */
+static inline void reset_page_mapcount(struct page *page)
+{
+	atomic_set(&(page)->_mapcount, -1);
+}
+
+static inline int page_mapcount(struct page *page)
+{
+	return atomic_read(&(page)->_mapcount) + 1;
+}
+
+/*
  * Return true if this page is mapped into pagetables.
  */
 static inline int page_mapped(struct page *page)
 {
-	return page->mapcount != 0;
+	return atomic_read(&(page)->_mapcount) >= 0;
 }
 
 /*
@@ -490,15 +519,34 @@
 
 extern void show_free_areas(void);
 
-struct page *shmem_nopage(struct vm_area_struct * vma,
+#ifdef CONFIG_SHMEM
+struct page *shmem_nopage(struct vm_area_struct *vma,
 			unsigned long address, int *type);
 int shmem_set_policy(struct vm_area_struct *vma, struct mempolicy *new);
 struct mempolicy *shmem_get_policy(struct vm_area_struct *vma,
 					unsigned long addr);
-struct file *shmem_file_setup(char * name, loff_t size, unsigned long flags);
-void shmem_lock(struct file * file, int lock);
+int shmem_lock(struct file *file, int lock, struct user_struct *user);
+#else
+#define shmem_nopage filemap_nopage
+#define shmem_lock(a, b, c) 	({0;})	/* always in memory, no need to lock */
+#define shmem_set_policy(a, b)	(0)
+#define shmem_get_policy(a, b)	(NULL)
+#endif
+struct file *shmem_file_setup(char *name, loff_t size, unsigned long flags);
+
 int shmem_zero_setup(struct vm_area_struct *);
 
+static inline int can_do_mlock(void)
+{
+	if (capable(CAP_IPC_LOCK))
+		return 1;
+	if (current->rlim[RLIMIT_MEMLOCK].rlim_cur != 0)
+		return 1;
+	return 0;
+}
+extern int user_shm_lock(size_t, struct user_struct *);
+extern void user_shm_unlock(size_t, struct user_struct *);
+
 /*
  * Parameter block passed down to zap_pte_range in exceptional cases.
  */
@@ -588,31 +636,32 @@
 }
 
 extern void free_area_init(unsigned long * zones_size);
-extern void free_area_init_node(int nid, pg_data_t *pgdat, struct page *pmap,
+extern void free_area_init_node(int nid, pg_data_t *pgdat,
 	unsigned long * zones_size, unsigned long zone_start_pfn, 
 	unsigned long *zholes_size);
-extern void memmap_init_zone(struct page *, unsigned long, int,
-	unsigned long, unsigned long);
+extern void memmap_init_zone(unsigned long, int, unsigned long, unsigned long);
 extern void mem_init(void);
 extern void show_mem(void);
 extern void si_meminfo(struct sysinfo * val);
 extern void si_meminfo_node(struct sysinfo *val, int nid);
 
-static inline void vma_prio_tree_init(struct vm_area_struct *vma)
-{
-	vma->shared.vm_set.list.next = NULL;
-	vma->shared.vm_set.list.prev = NULL;
-	vma->shared.vm_set.parent = NULL;
-	vma->shared.vm_set.head = NULL;
-}
-
 /* prio_tree.c */
 void vma_prio_tree_add(struct vm_area_struct *, struct vm_area_struct *old);
 void vma_prio_tree_insert(struct vm_area_struct *, struct prio_tree_root *);
 void vma_prio_tree_remove(struct vm_area_struct *, struct prio_tree_root *);
-struct vm_area_struct *vma_prio_tree_next(
-	struct vm_area_struct *, struct prio_tree_root *,
-	struct prio_tree_iter *, pgoff_t begin, pgoff_t end);
+struct vm_area_struct *vma_prio_tree_next(struct vm_area_struct *vma,
+	struct prio_tree_iter *iter);
+
+#define vma_prio_tree_foreach(vma, iter, root, begin, end)	\
+	for (prio_tree_iter_init(iter, root, begin, end), vma = NULL;	\
+		(vma = vma_prio_tree_next(vma, iter)); )
+
+static inline void vma_nonlinear_insert(struct vm_area_struct *vma,
+					struct list_head *list)
+{
+	vma->shared.vm_set.parent = NULL;
+	list_add_tail(&vma->shared.vm_set.list, list);
+}
 
 /* mmap.c */
 extern void vma_adjust(struct vm_area_struct *vma, unsigned long start,
@@ -711,6 +760,27 @@
 		int write);
 extern int remap_page_range(struct vm_area_struct *vma, unsigned long from,
 		unsigned long to, unsigned long size, pgprot_t prot);
+
+#ifdef CONFIG_PROC_FS
+void __vm_stat_account(struct mm_struct *, unsigned long, struct file *, long);
+#else
+static inline void __vm_stat_account(struct mm_struct *mm,
+			unsigned long flags, struct file *file, long pages)
+{
+}
+#endif /* CONFIG_PROC_FS */
+
+static inline void vm_stat_account(struct vm_area_struct *vma)
+{
+	__vm_stat_account(vma->vm_mm, vma->vm_flags, vma->vm_file,
+							vma_pages(vma));
+}
+
+static inline void vm_stat_unaccount(struct vm_area_struct *vma)
+{
+	__vm_stat_account(vma->vm_mm, vma->vm_flags, vma->vm_file,
+							-vma_pages(vma));
+}
 
 #ifndef CONFIG_DEBUG_PAGEALLOC
 static inline void
diff -Nru a/include/linux/mman.h b/include/linux/mman.h
--- a/include/linux/mman.h	2004-10-18 14:55:55 -07:00
+++ b/include/linux/mman.h	2004-10-18 14:55:55 -07:00
@@ -10,6 +10,9 @@
 #define MREMAP_MAYMOVE	1
 #define MREMAP_FIXED	2
 
+#define OVERCOMMIT_GUESS		0
+#define OVERCOMMIT_ALWAYS		1
+#define OVERCOMMIT_NEVER		2
 extern int sysctl_overcommit_memory;
 extern int sysctl_overcommit_ratio;
 extern atomic_t vm_committed_space;
diff -Nru a/include/linux/mmc/card.h b/include/linux/mmc/card.h
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/include/linux/mmc/card.h	2004-10-18 14:57:24 -07:00
@@ -0,0 +1,92 @@
+/*
+ *  linux/include/linux/mmc/card.h
+ *
+ * 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.
+ *
+ *  Card driver specific definitions.
+ */
+#ifndef LINUX_MMC_CARD_H
+#define LINUX_MMC_CARD_H
+
+#include <linux/mmc/mmc.h>
+
+struct mmc_cid {
+	unsigned int		manfid;
+	char			prod_name[8];
+	unsigned int		serial;
+	unsigned short		oemid;
+	unsigned short		year;
+	unsigned char		hwrev;
+	unsigned char		fwrev;
+	unsigned char		month;
+};
+
+struct mmc_csd {
+	unsigned char		mmca_vsn;
+	unsigned short		cmdclass;
+	unsigned short		tacc_clks;
+	unsigned int		tacc_ns;
+	unsigned int		max_dtr;
+	unsigned int		read_blkbits;
+	unsigned int		capacity;
+};
+
+struct mmc_host;
+
+/*
+ * MMC device
+ */
+struct mmc_card {
+	struct list_head	node;		/* node in hosts devices list */
+	struct mmc_host		*host;		/* the host this device belongs to */
+	struct device		dev;		/* the device */
+	unsigned int		rca;		/* relative card address of device */
+	unsigned int		state;		/* (our) card state */
+#define MMC_STATE_PRESENT	(1<<0)		/* present in sysfs */
+#define MMC_STATE_DEAD		(1<<1)		/* device no longer in stack */
+#define MMC_STATE_BAD		(1<<2)		/* unrecognised device */
+	u32			raw_cid[4];	/* raw card CID */
+	u32			raw_csd[4];	/* raw card CSD */
+	struct mmc_cid		cid;		/* card identification */
+	struct mmc_csd		csd;		/* card specific */
+};
+
+#define mmc_card_present(c)	((c)->state & MMC_STATE_PRESENT)
+#define mmc_card_dead(c)	((c)->state & MMC_STATE_DEAD)
+#define mmc_card_bad(c)		((c)->state & MMC_STATE_BAD)
+
+#define mmc_card_set_present(c)	((c)->state |= MMC_STATE_PRESENT)
+#define mmc_card_set_dead(c)	((c)->state |= MMC_STATE_DEAD)
+#define mmc_card_set_bad(c)	((c)->state |= MMC_STATE_BAD)
+
+#define mmc_card_name(c)	((c)->cid.prod_name)
+#define mmc_card_id(c)		((c)->dev.bus_id)
+
+#define mmc_list_to_card(l)	container_of(l, struct mmc_card, node)
+#define mmc_get_drvdata(c)	dev_get_drvdata(&(c)->dev)
+#define mmc_set_drvdata(c,d)	dev_set_drvdata(&(c)->dev, d)
+
+/*
+ * MMC device driver (e.g., Flash card, I/O card...)
+ */
+struct mmc_driver {
+	struct device_driver drv;
+	int (*probe)(struct mmc_card *);
+	void (*remove)(struct mmc_card *);
+	int (*suspend)(struct mmc_card *, u32);
+	int (*resume)(struct mmc_card *);
+};
+
+extern int mmc_register_driver(struct mmc_driver *);
+extern void mmc_unregister_driver(struct mmc_driver *);
+
+static inline int mmc_card_claim_host(struct mmc_card *card)
+{
+	return __mmc_claim_host(card->host, card);
+}
+
+#define mmc_card_release_host(c)	mmc_release_host((c)->host)
+
+#endif
diff -Nru a/include/linux/mmc/host.h b/include/linux/mmc/host.h
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/include/linux/mmc/host.h	2004-10-18 14:57:23 -07:00
@@ -0,0 +1,108 @@
+/*
+ *  linux/include/linux/mmc/host.h
+ *
+ * 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.
+ *
+ *  Host driver specific definitions.
+ */
+#ifndef LINUX_MMC_HOST_H
+#define LINUX_MMC_HOST_H
+
+#include <linux/mmc/mmc.h>
+
+struct mmc_ios {
+	unsigned int	clock;			/* clock rate */
+	unsigned short	vdd;
+
+#define	MMC_VDD_150	0
+#define	MMC_VDD_155	1
+#define	MMC_VDD_160	2
+#define	MMC_VDD_165	3
+#define	MMC_VDD_170	4
+#define	MMC_VDD_180	5
+#define	MMC_VDD_190	6
+#define	MMC_VDD_200	7
+#define	MMC_VDD_210	8
+#define	MMC_VDD_220	9
+#define	MMC_VDD_230	10
+#define	MMC_VDD_240	11
+#define	MMC_VDD_250	12
+#define	MMC_VDD_260	13
+#define	MMC_VDD_270	14
+#define	MMC_VDD_280	15
+#define	MMC_VDD_290	16
+#define	MMC_VDD_300	17
+#define	MMC_VDD_310	18
+#define	MMC_VDD_320	19
+#define	MMC_VDD_330	20
+#define	MMC_VDD_340	21
+#define	MMC_VDD_350	22
+#define	MMC_VDD_360	23
+
+	unsigned char	bus_mode;		/* command output mode */
+
+#define MMC_BUSMODE_OPENDRAIN	1
+#define MMC_BUSMODE_PUSHPULL	2
+
+	unsigned char	power_mode;		/* power supply mode */
+
+#define MMC_POWER_OFF		0
+#define MMC_POWER_UP		1
+#define MMC_POWER_ON		2
+};
+
+struct mmc_host_ops {
+	void	(*request)(struct mmc_host *host, struct mmc_request *req);
+	void	(*set_ios)(struct mmc_host *host, struct mmc_ios *ios);
+};
+
+struct mmc_card;
+struct device;
+
+struct mmc_host {
+	struct device		*dev;
+	struct mmc_host_ops	*ops;
+	unsigned int		f_min;
+	unsigned int		f_max;
+	u32			ocr_avail;
+	char			host_name[8];
+
+	/* host specific block data */
+	unsigned int		max_seg_size;	/* see blk_queue_max_segment_size */
+	unsigned short		max_hw_segs;	/* see blk_queue_max_hw_segments */
+	unsigned short		max_phys_segs;	/* see blk_queue_max_phys_segments */
+	unsigned short		max_sectors;	/* see blk_queue_max_sectors */
+	unsigned short		unused;
+
+	/* private data */
+	struct mmc_ios		ios;		/* current io bus settings */
+	u32			ocr;		/* the current OCR setting */
+
+	struct list_head	cards;		/* devices attached to this host */
+
+	wait_queue_head_t	wq;
+	spinlock_t		lock;		/* card_busy lock */
+	struct mmc_card		*card_busy;	/* the MMC card claiming host */
+	struct mmc_card		*card_selected;	/* the selected MMC card */
+
+	struct work_struct	detect;
+};
+
+extern struct mmc_host *mmc_alloc_host(int extra, struct device *);
+extern int mmc_add_host(struct mmc_host *);
+extern void mmc_remove_host(struct mmc_host *);
+extern void mmc_free_host(struct mmc_host *);
+
+#define mmc_priv(x)	((void *)((x) + 1))
+#define mmc_dev(x)	((x)->dev)
+
+extern int mmc_suspend_host(struct mmc_host *, u32);
+extern int mmc_resume_host(struct mmc_host *);
+
+extern void mmc_detect_change(struct mmc_host *);
+extern void mmc_request_done(struct mmc_host *, struct mmc_request *);
+
+#endif
+
diff -Nru a/include/linux/mmc/mmc.h b/include/linux/mmc/mmc.h
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/include/linux/mmc/mmc.h	2004-10-18 14:57:23 -07:00
@@ -0,0 +1,98 @@
+/*
+ *  linux/include/linux/mmc/mmc.h
+ *
+ * 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.
+ */
+#ifndef MMC_H
+#define MMC_H
+
+#include <linux/list.h>
+#include <linux/interrupt.h>
+#include <linux/device.h>
+
+struct request;
+struct mmc_data;
+struct mmc_request;
+
+struct mmc_command {
+	u32			opcode;
+	u32			arg;
+	u32			resp[4];
+	unsigned int		flags;		/* expected response type */
+#define MMC_RSP_NONE	(0 << 0)
+#define MMC_RSP_SHORT	(1 << 0)
+#define MMC_RSP_LONG	(2 << 0)
+#define MMC_RSP_MASK	(3 << 0)
+#define MMC_RSP_CRC	(1 << 3)		/* expect valid crc */
+#define MMC_RSP_BUSY	(1 << 4)		/* card may send busy */
+
+/*
+ * These are the response types, and correspond to valid bit
+ * patterns of the above flags.  One additional valid pattern
+ * is all zeros, which means we don't expect a response.
+ */
+#define MMC_RSP_R1	(MMC_RSP_SHORT|MMC_RSP_CRC)
+#define MMC_RSP_R1B	(MMC_RSP_SHORT|MMC_RSP_CRC|MMC_RSP_BUSY)
+#define MMC_RSP_R2	(MMC_RSP_LONG|MMC_RSP_CRC)
+#define MMC_RSP_R3	(MMC_RSP_SHORT)
+
+	unsigned int		retries;	/* max number of retries */
+	unsigned int		error;		/* command error */
+
+#define MMC_ERR_NONE	0
+#define MMC_ERR_TIMEOUT	1
+#define MMC_ERR_BADCRC	2
+#define MMC_ERR_FIFO	3
+#define MMC_ERR_FAILED	4
+#define MMC_ERR_INVALID	5
+
+	struct mmc_data		*data;		/* data segment associated with cmd */
+	struct mmc_request	*mrq;		/* assoicated request */
+};
+
+struct mmc_data {
+	unsigned int		timeout_ns;	/* data timeout (in ns, max 80ms) */
+	unsigned int		timeout_clks;	/* data timeout (in clocks) */
+	unsigned int		blksz_bits;	/* data block size */
+	unsigned int		blocks;		/* number of blocks */
+	struct request		*req;		/* request structure */
+	unsigned int		error;		/* data error */
+	unsigned int		flags;
+
+#define MMC_DATA_WRITE	(1 << 8)
+#define MMC_DATA_READ	(1 << 9)
+#define MMC_DATA_STREAM	(1 << 10)
+
+	unsigned int		bytes_xfered;
+
+	struct mmc_command	*stop;		/* stop command */
+	struct mmc_request	*mrq;		/* assoicated request */
+};
+
+struct mmc_request {
+	struct mmc_command	*cmd;
+	struct mmc_data		*data;
+	struct mmc_command	*stop;
+
+	void			*done_data;	/* completion data */
+	void			(*done)(struct mmc_request *);/* completion function */
+};
+
+struct mmc_host;
+struct mmc_card;
+
+extern int mmc_wait_for_req(struct mmc_host *, struct mmc_request *);
+extern int mmc_wait_for_cmd(struct mmc_host *, struct mmc_command *, int);
+
+extern int __mmc_claim_host(struct mmc_host *host, struct mmc_card *card);
+
+static inline void mmc_claim_host(struct mmc_host *host)
+{
+	__mmc_claim_host(host, (struct mmc_card *)-1);
+}
+
+extern void mmc_release_host(struct mmc_host *host);
+
+#endif
diff -Nru a/include/linux/mmc/protocol.h b/include/linux/mmc/protocol.h
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/include/linux/mmc/protocol.h	2004-10-18 14:57:24 -07:00
@@ -0,0 +1,203 @@
+/*
+ * Header for MultiMediaCard (MMC)
+ *
+ * Copyright 2002 Hewlett-Packard Company
+ *
+ * Use consistent with the GNU GPL is permitted,
+ * provided that this copyright notice is
+ * preserved in its entirety in all copies and derived works.
+ *
+ * HEWLETT-PACKARD COMPANY MAKES NO WARRANTIES, EXPRESSED OR IMPLIED,
+ * AS TO THE USEFULNESS OR CORRECTNESS OF THIS CODE OR ITS
+ * FITNESS FOR ANY PARTICULAR PURPOSE.
+ *
+ * Many thanks to Alessandro Rubini and Jonathan Corbet!
+ *
+ * Based strongly on code by:
+ *
+ * Author: Yong-iL Joh <tolkien@mizi.com>
+ * Date  : $Date: 2002/06/18 12:37:30 $
+ *
+ * Author:  Andrew Christian
+ *          15 May 2002
+ */
+
+#ifndef MMC_MMC_PROTOCOL_H
+#define MMC_MMC_PROTOCOL_H
+
+/* Standard MMC commands (3.1)           type  argument     response */
+   /* class 1 */
+#define	MMC_GO_IDLE_STATE         0   /* bc                          */
+#define MMC_SEND_OP_COND          1   /* bcr  [31:0] OCR         R3  */
+#define MMC_ALL_SEND_CID          2   /* bcr                     R2  */
+#define MMC_SET_RELATIVE_ADDR     3   /* ac   [31:16] RCA        R1  */
+#define MMC_SET_DSR               4   /* bc   [31:16] RCA            */
+#define MMC_SELECT_CARD           7   /* ac   [31:16] RCA        R1  */
+#define MMC_SEND_CSD              9   /* ac   [31:16] RCA        R2  */
+#define MMC_SEND_CID             10   /* ac   [31:16] RCA        R2  */
+#define MMC_READ_DAT_UNTIL_STOP  11   /* adtc [31:0] dadr        R1  */
+#define MMC_STOP_TRANSMISSION    12   /* ac                      R1b */
+#define MMC_SEND_STATUS	         13   /* ac   [31:16] RCA        R1  */
+#define MMC_GO_INACTIVE_STATE    15   /* ac   [31:16] RCA            */
+
+  /* class 2 */
+#define MMC_SET_BLOCKLEN         16   /* ac   [31:0] block len   R1  */
+#define MMC_READ_SINGLE_BLOCK    17   /* adtc [31:0] data addr   R1  */
+#define MMC_READ_MULTIPLE_BLOCK  18   /* adtc [31:0] data addr   R1  */
+
+  /* class 3 */
+#define MMC_WRITE_DAT_UNTIL_STOP 20   /* adtc [31:0] data addr   R1  */
+
+  /* class 4 */
+#define MMC_SET_BLOCK_COUNT      23   /* adtc [31:0] data addr   R1  */
+#define MMC_WRITE_BLOCK          24   /* adtc [31:0] data addr   R1  */
+#define MMC_WRITE_MULTIPLE_BLOCK 25   /* adtc                    R1  */
+#define MMC_PROGRAM_CID          26   /* adtc                    R1  */
+#define MMC_PROGRAM_CSD          27   /* adtc                    R1  */
+
+  /* class 6 */
+#define MMC_SET_WRITE_PROT       28   /* ac   [31:0] data addr   R1b */
+#define MMC_CLR_WRITE_PROT       29   /* ac   [31:0] data addr   R1b */
+#define MMC_SEND_WRITE_PROT      30   /* adtc [31:0] wpdata addr R1  */
+
+  /* class 5 */
+#define MMC_ERASE_GROUP_START    35   /* ac   [31:0] data addr   R1  */
+#define MMC_ERASE_GROUP_END      36   /* ac   [31:0] data addr   R1  */
+#define MMC_ERASE                37   /* ac                      R1b */
+
+  /* class 9 */
+#define MMC_FAST_IO              39   /* ac   <Complex>          R4  */
+#define MMC_GO_IRQ_STATE         40   /* bcr                     R5  */
+
+  /* class 7 */
+#define MMC_LOCK_UNLOCK          42   /* adtc                    R1b */
+
+  /* class 8 */
+#define MMC_APP_CMD              55   /* ac   [31:16] RCA        R1  */
+#define MMC_GEN_CMD              56   /* adtc [0] RD/WR          R1b */
+
+/*
+  MMC status in R1
+  Type
+  	e : error bit
+	s : status bit
+	r : detected and set for the actual command response
+	x : detected and set during command execution. the host must poll
+            the card by sending status command in order to read these bits.
+  Clear condition
+  	a : according to the card state
+	b : always related to the previous command. Reception of
+            a valid command will clear it (with a delay of one command)
+	c : clear by read
+ */
+
+#define R1_OUT_OF_RANGE		(1 << 31)	/* er, c */
+#define R1_ADDRESS_ERROR	(1 << 30)	/* erx, c */
+#define R1_BLOCK_LEN_ERROR	(1 << 29)	/* er, c */
+#define R1_ERASE_SEQ_ERROR      (1 << 28)	/* er, c */
+#define R1_ERASE_PARAM		(1 << 27)	/* ex, c */
+#define R1_WP_VIOLATION		(1 << 26)	/* erx, c */
+#define R1_CARD_IS_LOCKED	(1 << 25)	/* sx, a */
+#define R1_LOCK_UNLOCK_FAILED	(1 << 24)	/* erx, c */
+#define R1_COM_CRC_ERROR	(1 << 23)	/* er, b */
+#define R1_ILLEGAL_COMMAND	(1 << 22)	/* er, b */
+#define R1_CARD_ECC_FAILED	(1 << 21)	/* ex, c */
+#define R1_CC_ERROR		(1 << 20)	/* erx, c */
+#define R1_ERROR		(1 << 19)	/* erx, c */
+#define R1_UNDERRUN		(1 << 18)	/* ex, c */
+#define R1_OVERRUN		(1 << 17)	/* ex, c */
+#define R1_CID_CSD_OVERWRITE	(1 << 16)	/* erx, c, CID/CSD overwrite */
+#define R1_WP_ERASE_SKIP	(1 << 15)	/* sx, c */
+#define R1_CARD_ECC_DISABLED	(1 << 14)	/* sx, a */
+#define R1_ERASE_RESET		(1 << 13)	/* sr, c */
+#define R1_STATUS(x)            (x & 0xFFFFE000)
+#define R1_CURRENT_STATE(x)    	((x & 0x00001E00) >> 9)	/* sx, b (4 bits) */
+#define R1_READY_FOR_DATA	(1 << 8)	/* sx, a */
+#define R1_APP_CMD		(1 << 7)	/* sr, c */
+
+/* These are unpacked versions of the actual responses */
+
+struct _mmc_csd {
+	u8  csd_structure;
+	u8  spec_vers;
+	u8  taac;
+	u8  nsac;
+	u8  tran_speed;
+	u16 ccc;
+	u8  read_bl_len;
+	u8  read_bl_partial;
+	u8  write_blk_misalign;
+	u8  read_blk_misalign;
+	u8  dsr_imp;
+	u16 c_size;
+	u8  vdd_r_curr_min;
+	u8  vdd_r_curr_max;
+	u8  vdd_w_curr_min;
+	u8  vdd_w_curr_max;
+	u8  c_size_mult;
+	union {
+		struct { /* MMC system specification version 3.1 */
+			u8  erase_grp_size;
+			u8  erase_grp_mult;
+		} v31;
+		struct { /* MMC system specification version 2.2 */
+			u8  sector_size;
+			u8  erase_grp_size;
+		} v22;
+	} erase;
+	u8  wp_grp_size;
+	u8  wp_grp_enable;
+	u8  default_ecc;
+	u8  r2w_factor;
+	u8  write_bl_len;
+	u8  write_bl_partial;
+	u8  file_format_grp;
+	u8  copy;
+	u8  perm_write_protect;
+	u8  tmp_write_protect;
+	u8  file_format;
+	u8  ecc;
+};
+
+#define MMC_VDD_145_150	0x00000001	/* VDD voltage 1.45 - 1.50 */
+#define MMC_VDD_150_155	0x00000002	/* VDD voltage 1.50 - 1.55 */
+#define MMC_VDD_155_160	0x00000004	/* VDD voltage 1.55 - 1.60 */
+#define MMC_VDD_160_165	0x00000008	/* VDD voltage 1.60 - 1.65 */
+#define MMC_VDD_165_170	0x00000010	/* VDD voltage 1.65 - 1.70 */
+#define MMC_VDD_17_18	0x00000020	/* VDD voltage 1.7 - 1.8 */
+#define MMC_VDD_18_19	0x00000040	/* VDD voltage 1.8 - 1.9 */
+#define MMC_VDD_19_20	0x00000080	/* VDD voltage 1.9 - 2.0 */
+#define MMC_VDD_20_21	0x00000100	/* VDD voltage 2.0 ~ 2.1 */
+#define MMC_VDD_21_22	0x00000200	/* VDD voltage 2.1 ~ 2.2 */
+#define MMC_VDD_22_23	0x00000400	/* VDD voltage 2.2 ~ 2.3 */
+#define MMC_VDD_23_24	0x00000800	/* VDD voltage 2.3 ~ 2.4 */
+#define MMC_VDD_24_25	0x00001000	/* VDD voltage 2.4 ~ 2.5 */
+#define MMC_VDD_25_26	0x00002000	/* VDD voltage 2.5 ~ 2.6 */
+#define MMC_VDD_26_27	0x00004000	/* VDD voltage 2.6 ~ 2.7 */
+#define MMC_VDD_27_28	0x00008000	/* VDD voltage 2.7 ~ 2.8 */
+#define MMC_VDD_28_29	0x00010000	/* VDD voltage 2.8 ~ 2.9 */
+#define MMC_VDD_29_30	0x00020000	/* VDD voltage 2.9 ~ 3.0 */
+#define MMC_VDD_30_31	0x00040000	/* VDD voltage 3.0 ~ 3.1 */
+#define MMC_VDD_31_32	0x00080000	/* VDD voltage 3.1 ~ 3.2 */
+#define MMC_VDD_32_33	0x00100000	/* VDD voltage 3.2 ~ 3.3 */
+#define MMC_VDD_33_34	0x00200000	/* VDD voltage 3.3 ~ 3.4 */
+#define MMC_VDD_34_35	0x00400000	/* VDD voltage 3.4 ~ 3.5 */
+#define MMC_VDD_35_36	0x00800000	/* VDD voltage 3.5 ~ 3.6 */
+#define MMC_CARD_BUSY	0x80000000	/* Card Power up status bit */
+
+
+/*
+ * CSD field definitions
+ */
+
+#define CSD_STRUCT_VER_1_0  0           /* Valid for system specification 1.0 - 1.2 */
+#define CSD_STRUCT_VER_1_1  1           /* Valid for system specification 1.4 - 2.2 */
+#define CSD_STRUCT_VER_1_2  2           /* Valid for system specification 3.1       */
+
+#define CSD_SPEC_VER_0      0           /* Implements system specification 1.0 - 1.2 */
+#define CSD_SPEC_VER_1      1           /* Implements system specification 1.4 */
+#define CSD_SPEC_VER_2      2           /* Implements system specification 2.0 - 2.2 */
+#define CSD_SPEC_VER_3      3           /* Implements system specification 3.1 */
+
+#endif  /* MMC_MMC_PROTOCOL_H */
+
diff -Nru a/include/linux/mmtimer.h b/include/linux/mmtimer.h
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/include/linux/mmtimer.h	2004-10-18 14:57:22 -07:00
@@ -0,0 +1,56 @@
+/*
+ * Intel Multimedia Timer device interface
+ *
+ * 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-2004 Silicon Graphics, Inc.  All rights reserved.
+ *
+ * This file should define an interface compatible with the IA-PC Multimedia
+ * Timers Draft Specification (rev. 0.97) from Intel.  Note that some
+ * hardware may not be able to safely export its registers to userspace,
+ * so the ioctl interface should support all necessary functionality.
+ *
+ * 11/01/01 - jbarnes - initial revision
+ * 9/10/04 - Christoph Lameter - remove interrupt support
+ * 9/17/04 - jbarnes - remove test program, move some #defines to the driver
+ */
+
+#ifndef _LINUX_MMTIMER_H
+#define _LINUX_MMTIMER_H
+
+/*
+ * Breakdown of the ioctl's available.  An 'optional' next to the command
+ * indicates that supporting this command is optional, while 'required'
+ * commands must be implemented if conformance is desired.
+ *
+ * MMTIMER_GETOFFSET - optional
+ *   Should return the offset (relative to the start of the page where the
+ *   registers are mapped) for the counter in question.
+ *
+ * MMTIMER_GETRES - required
+ *   The resolution of the clock in femto (10^-15) seconds
+ *
+ * MMTIMER_GETFREQ - required
+ *   Frequency of the clock in Hz
+ *
+ * MMTIMER_GETBITS - required
+ *   Number of bits in the clock's counter
+ *
+ * MMTIMER_MMAPAVAIL - required
+ *   Returns nonzero if the registers can be mmap'd into userspace, 0 otherwise
+ *
+ * MMTIMER_GETCOUNTER - required
+ *   Gets the current value in the counter
+ */
+#define MMTIMER_IOCTL_BASE 'm'
+
+#define MMTIMER_GETOFFSET _IO(MMTIMER_IOCTL_BASE, 0)
+#define MMTIMER_GETRES _IOR(MMTIMER_IOCTL_BASE, 1, unsigned long)
+#define MMTIMER_GETFREQ _IOR(MMTIMER_IOCTL_BASE, 2, unsigned long)
+#define MMTIMER_GETBITS _IO(MMTIMER_IOCTL_BASE, 4)
+#define MMTIMER_MMAPAVAIL _IO(MMTIMER_IOCTL_BASE, 6)
+#define MMTIMER_GETCOUNTER _IOR(MMTIMER_IOCTL_BASE, 9, unsigned long)
+
+#endif /* _LINUX_MMTIMER_H */
diff -Nru a/include/linux/mmzone.h b/include/linux/mmzone.h
--- a/include/linux/mmzone.h	2004-10-18 14:56:32 -07:00
+++ b/include/linux/mmzone.h	2004-10-18 14:56:32 -07:00
@@ -20,18 +20,6 @@
 #define MAX_ORDER CONFIG_FORCE_MAX_ZONEORDER
 #endif
 
-/*
- * system hash table size limits
- * - on large memory machines, we may want to allocate a bigger hash than that
- *   permitted by MAX_ORDER, so we allocate with the bootmem allocator, and are
- *   limited to this size
- */
-#if MAX_ORDER > 14
-#define MAX_SYS_HASH_TABLE_ORDER MAX_ORDER
-#else
-#define MAX_SYS_HASH_TABLE_ORDER 14
-#endif
-
 struct free_area {
 	struct list_head	free_list;
 	unsigned long		*map;
@@ -284,6 +272,8 @@
 extern int numnodes;
 extern struct pglist_data *pgdat_list;
 
+void __get_zone_counts(unsigned long *active, unsigned long *inactive,
+			unsigned long *free, struct pglist_data *pgdat);
 void get_zone_counts(unsigned long *active, unsigned long *inactive,
 			unsigned long *free);
 void build_all_zonelists(void);
diff -Nru a/include/linux/moduleparam.h b/include/linux/moduleparam.h
--- a/include/linux/moduleparam.h	2004-10-18 14:56:29 -07:00
+++ b/include/linux/moduleparam.h	2004-10-18 14:56:29 -07:00
@@ -73,7 +73,7 @@
 #define module_param_string(name, string, len, perm)			\
 	static struct kparam_string __param_string_##name		\
 		= { len, string };					\
-	module_param_call(name, param_set_copystring, param_get_charp,	\
+	module_param_call(name, param_set_copystring, param_get_string,	\
 		   &__param_string_##name, perm)
 
 /* Called on module insert or kernel boot */
@@ -89,6 +89,10 @@
 #define __param_check(name, p, type) \
 	static inline type *__check_##name(void) { return(p); }
 
+extern int param_set_byte(const char *val, struct kernel_param *kp);
+extern int param_get_byte(char *buffer, struct kernel_param *kp);
+#define param_check_byte(name, p) __param_check(name, p, unsigned char)
+
 extern int param_set_short(const char *val, struct kernel_param *kp);
 extern int param_get_short(char *buffer, struct kernel_param *kp);
 #define param_check_short(name, p) __param_check(name, p, short)
@@ -140,6 +144,7 @@
 extern int param_array_get(char *buffer, struct kernel_param *kp);
 
 extern int param_set_copystring(const char *val, struct kernel_param *kp);
+extern int param_get_string(char *buffer, struct kernel_param *kp);
 
 int param_array(const char *name,
 		const char *val,
diff -Nru a/include/linux/msdos_fs.h b/include/linux/msdos_fs.h
--- a/include/linux/msdos_fs.h	2004-10-18 14:56:49 -07:00
+++ b/include/linux/msdos_fs.h	2004-10-18 14:56:49 -07:00
@@ -123,34 +123,34 @@
 				   partition manager volumes */
 	__u8	sector_size[2];	/* bytes per logical sector */
 	__u8	sec_per_clus;	/* sectors/cluster */
-	__u16	reserved;	/* reserved sectors */
+	__le16	reserved;	/* reserved sectors */
 	__u8	fats;		/* number of FATs */
 	__u8	dir_entries[2];	/* root directory entries */
 	__u8	sectors[2];	/* number of sectors */
 	__u8	media;		/* media code */
-	__u16	fat_length;	/* sectors/FAT */
-	__u16	secs_track;	/* sectors per track */
-	__u16	heads;		/* number of heads */
-	__u32	hidden;		/* hidden sectors (unused) */
-	__u32	total_sect;	/* number of sectors (if sectors == 0) */
+	__le16	fat_length;	/* sectors/FAT */
+	__le16	secs_track;	/* sectors per track */
+	__le16	heads;		/* number of heads */
+	__le32	hidden;		/* hidden sectors (unused) */
+	__le32	total_sect;	/* number of sectors (if sectors == 0) */
 
 	/* The following fields are only used by FAT32 */
-	__u32	fat32_length;	/* sectors/FAT */
-	__u16	flags;		/* bit 8: fat mirroring, low 4: active fat */
+	__le32	fat32_length;	/* sectors/FAT */
+	__le16	flags;		/* bit 8: fat mirroring, low 4: active fat */
 	__u8	version[2];	/* major, minor filesystem version */
-	__u32	root_cluster;	/* first cluster in root directory */
-	__u16	info_sector;	/* filesystem info sector */
-	__u16	backup_boot;	/* backup boot sector */
-	__u16	reserved2[6];	/* Unused */
+	__le32	root_cluster;	/* first cluster in root directory */
+	__le16	info_sector;	/* filesystem info sector */
+	__le16	backup_boot;	/* backup boot sector */
+	__le16	reserved2[6];	/* Unused */
 };
 
 struct fat_boot_fsinfo {
-	__u32   signature1;	/* 0x41615252L */
-	__u32   reserved1[120];	/* Nothing as far as I can tell */
-	__u32   signature2;	/* 0x61417272L */
-	__u32   free_clusters;	/* Free cluster count.  -1 if unknown */
-	__u32   next_cluster;	/* Most recently allocated cluster */
-	__u32   reserved2[4];
+	__le32   signature1;	/* 0x41615252L */
+	__le32   reserved1[120];	/* Nothing as far as I can tell */
+	__le32   signature2;	/* 0x61417272L */
+	__le32   free_clusters;	/* Free cluster count.  -1 if unknown */
+	__le32   next_cluster;	/* Most recently allocated cluster */
+	__le32   reserved2[4];
 };
 
 struct msdos_dir_entry {
@@ -158,12 +158,12 @@
 	__u8	attr;		/* attribute bits */
 	__u8    lcase;		/* Case for base and extension */
 	__u8	ctime_ms;	/* Creation time, milliseconds */
-	__u16	ctime;		/* Creation time */
-	__u16	cdate;		/* Creation date */
-	__u16	adate;		/* Last access date */
-	__u16   starthi;	/* High 16 bits of cluster in FAT32 */
-	__u16	time,date,start;/* time, date and first cluster */
-	__u32	size;		/* file size (in bytes) */
+	__le16	ctime;		/* Creation time */
+	__le16	cdate;		/* Creation date */
+	__le16	adate;		/* Last access date */
+	__le16   starthi;	/* High 16 bits of cluster in FAT32 */
+	__le16	time,date,start;/* time, date and first cluster */
+	__le32	size;		/* file size (in bytes) */
 };
 
 /* Up to 13 characters of the name */
@@ -174,7 +174,7 @@
 	__u8    reserved;	/* always 0 */
 	__u8    alias_checksum;	/* checksum for 8.3 alias */
 	__u8    name5_10[12];	/* 6 more characters in name */
-	__u16   start;		/* starting cluster number, 0 in long slots */
+	__le16   start;		/* starting cluster number, 0 in long slots */
 	__u8    name11_12[4];	/* last 2 characters in name */
 };
 
@@ -233,8 +233,6 @@
 extern int __fat_access(struct super_block *sb, int nr, int new_value);
 extern int fat_bmap(struct inode *inode, sector_t sector, sector_t *phys);
 extern void fat_cache_init(struct super_block *sb);
-extern void fat_cache_lookup(struct inode *inode, int cluster, int *f_clu,
-			     int *d_clu);
 extern void fat_cache_add(struct inode *inode, int f_clu, int d_clu);
 extern void fat_cache_inval_inode(struct inode *inode);
 extern int fat_get_cluster(struct inode *inode, int cluster,
@@ -278,7 +276,7 @@
 int fat_fill_super(struct super_block *sb, void *data, int silent,
 		   struct inode_operations *fs_dir_inode_ops, int isvfat);
 extern int fat_statfs(struct super_block *sb, struct kstatfs *buf);
-extern void fat_write_inode(struct inode *inode, int wait);
+extern int fat_write_inode(struct inode *inode, int wait);
 extern int fat_notify_change(struct dentry * dentry, struct iattr * attr);
 
 /* fat/misc.c */
@@ -289,8 +287,7 @@
 extern int fat_add_cluster(struct inode *inode);
 extern struct buffer_head *fat_extend_dir(struct inode *inode);
 extern int date_dos2unix(unsigned short time, unsigned short date);
-extern void fat_date_unix2dos(int unix_date, unsigned short *time,
-			      unsigned short *date);
+extern void fat_date_unix2dos(int unix_date, __le16 *time, __le16 *date);
 extern int fat__get_entry(struct inode *dir, loff_t *pos,
 			  struct buffer_head **bh,
 			  struct msdos_dir_entry **de, loff_t *i_pos);
diff -Nru a/include/linux/mtd/map.h b/include/linux/mtd/map.h
--- a/include/linux/mtd/map.h	2004-10-18 14:56:28 -07:00
+++ b/include/linux/mtd/map.h	2004-10-18 14:56:28 -07:00
@@ -179,7 +179,7 @@
 	unsigned long phys;
 #define NO_XIP (-1UL)
 
-	unsigned long virt;
+	void __iomem *virt;
 	void *cached;
 
 	int bankwidth; /* in octets. This isn't necessarily the width
diff -Nru a/include/linux/mv643xx.h b/include/linux/mv643xx.h
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/include/linux/mv643xx.h	2004-10-18 14:56:49 -07:00
@@ -0,0 +1,1039 @@
+/*
+ * mv64340.h - MV-64340 Internal registers definition file.
+ *
+ * Copyright 2002 Momentum Computer, Inc.
+ * 	Author: Matthew Dharm <mdharm@momenco.com>
+ * Copyright 2002 GALILEO TECHNOLOGY, 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.
+ */
+#ifndef __ASM_MV64340_H
+#define __ASM_MV64340_H
+
+#include <asm/addrspace.h>
+#include <asm/marvell.h>
+
+/****************************************/
+/* Processor Address Space              */
+/****************************************/
+
+/* DDR SDRAM BAR and size registers */
+
+#define MV64340_CS_0_BASE_ADDR                                      0x008
+#define MV64340_CS_0_SIZE                                           0x010
+#define MV64340_CS_1_BASE_ADDR                                      0x208
+#define MV64340_CS_1_SIZE                                           0x210
+#define MV64340_CS_2_BASE_ADDR                                      0x018
+#define MV64340_CS_2_SIZE                                           0x020
+#define MV64340_CS_3_BASE_ADDR                                      0x218
+#define MV64340_CS_3_SIZE                                           0x220
+
+/* Devices BAR and size registers */
+
+#define MV64340_DEV_CS0_BASE_ADDR                                   0x028
+#define MV64340_DEV_CS0_SIZE                                        0x030
+#define MV64340_DEV_CS1_BASE_ADDR                                   0x228
+#define MV64340_DEV_CS1_SIZE                                        0x230
+#define MV64340_DEV_CS2_BASE_ADDR                                   0x248
+#define MV64340_DEV_CS2_SIZE                                        0x250
+#define MV64340_DEV_CS3_BASE_ADDR                                   0x038
+#define MV64340_DEV_CS3_SIZE                                        0x040
+#define MV64340_BOOTCS_BASE_ADDR                                    0x238
+#define MV64340_BOOTCS_SIZE                                         0x240
+
+/* PCI 0 BAR and size registers */
+
+#define MV64340_PCI_0_IO_BASE_ADDR                                  0x048
+#define MV64340_PCI_0_IO_SIZE                                       0x050
+#define MV64340_PCI_0_MEMORY0_BASE_ADDR                             0x058
+#define MV64340_PCI_0_MEMORY0_SIZE                                  0x060
+#define MV64340_PCI_0_MEMORY1_BASE_ADDR                             0x080
+#define MV64340_PCI_0_MEMORY1_SIZE                                  0x088
+#define MV64340_PCI_0_MEMORY2_BASE_ADDR                             0x258
+#define MV64340_PCI_0_MEMORY2_SIZE                                  0x260
+#define MV64340_PCI_0_MEMORY3_BASE_ADDR                             0x280
+#define MV64340_PCI_0_MEMORY3_SIZE                                  0x288
+
+/* PCI 1 BAR and size registers */
+#define MV64340_PCI_1_IO_BASE_ADDR                                  0x090
+#define MV64340_PCI_1_IO_SIZE                                       0x098
+#define MV64340_PCI_1_MEMORY0_BASE_ADDR                             0x0a0
+#define MV64340_PCI_1_MEMORY0_SIZE                                  0x0a8
+#define MV64340_PCI_1_MEMORY1_BASE_ADDR                             0x0b0
+#define MV64340_PCI_1_MEMORY1_SIZE                                  0x0b8
+#define MV64340_PCI_1_MEMORY2_BASE_ADDR                             0x2a0
+#define MV64340_PCI_1_MEMORY2_SIZE                                  0x2a8
+#define MV64340_PCI_1_MEMORY3_BASE_ADDR                             0x2b0
+#define MV64340_PCI_1_MEMORY3_SIZE                                  0x2b8
+
+/* SRAM base address */
+#define MV64340_INTEGRATED_SRAM_BASE_ADDR                           0x268
+
+/* internal registers space base address */
+#define MV64340_INTERNAL_SPACE_BASE_ADDR                            0x068
+
+/* Enables the CS , DEV_CS , PCI 0 and PCI 1 
+   windows above */
+#define MV64340_BASE_ADDR_ENABLE                                    0x278
+
+/****************************************/
+/* PCI remap registers                  */
+/****************************************/
+      /* PCI 0 */
+#define MV64340_PCI_0_IO_ADDR_REMAP                                 0x0f0
+#define MV64340_PCI_0_MEMORY0_LOW_ADDR_REMAP                        0x0f8
+#define MV64340_PCI_0_MEMORY0_HIGH_ADDR_REMAP                       0x320
+#define MV64340_PCI_0_MEMORY1_LOW_ADDR_REMAP                        0x100
+#define MV64340_PCI_0_MEMORY1_HIGH_ADDR_REMAP                       0x328
+#define MV64340_PCI_0_MEMORY2_LOW_ADDR_REMAP                        0x2f8
+#define MV64340_PCI_0_MEMORY2_HIGH_ADDR_REMAP                       0x330
+#define MV64340_PCI_0_MEMORY3_LOW_ADDR_REMAP                        0x300
+#define MV64340_PCI_0_MEMORY3_HIGH_ADDR_REMAP                       0x338
+      /* PCI 1 */
+#define MV64340_PCI_1_IO_ADDR_REMAP                                 0x108
+#define MV64340_PCI_1_MEMORY0_LOW_ADDR_REMAP                        0x110
+#define MV64340_PCI_1_MEMORY0_HIGH_ADDR_REMAP                       0x340
+#define MV64340_PCI_1_MEMORY1_LOW_ADDR_REMAP                        0x118
+#define MV64340_PCI_1_MEMORY1_HIGH_ADDR_REMAP                       0x348
+#define MV64340_PCI_1_MEMORY2_LOW_ADDR_REMAP                        0x310
+#define MV64340_PCI_1_MEMORY2_HIGH_ADDR_REMAP                       0x350
+#define MV64340_PCI_1_MEMORY3_LOW_ADDR_REMAP                        0x318
+#define MV64340_PCI_1_MEMORY3_HIGH_ADDR_REMAP                       0x358
+ 
+#define MV64340_CPU_PCI_0_HEADERS_RETARGET_CONTROL                  0x3b0
+#define MV64340_CPU_PCI_0_HEADERS_RETARGET_BASE                     0x3b8
+#define MV64340_CPU_PCI_1_HEADERS_RETARGET_CONTROL                  0x3c0
+#define MV64340_CPU_PCI_1_HEADERS_RETARGET_BASE                     0x3c8
+#define MV64340_CPU_GE_HEADERS_RETARGET_CONTROL                     0x3d0
+#define MV64340_CPU_GE_HEADERS_RETARGET_BASE                        0x3d8
+#define MV64340_CPU_IDMA_HEADERS_RETARGET_CONTROL                   0x3e0
+#define MV64340_CPU_IDMA_HEADERS_RETARGET_BASE                      0x3e8
+
+/****************************************/
+/*         CPU Control Registers        */
+/****************************************/
+
+#define MV64340_CPU_CONFIG                                          0x000
+#define MV64340_CPU_MODE                                            0x120
+#define MV64340_CPU_MASTER_CONTROL                                  0x160
+#define MV64340_CPU_CROSS_BAR_CONTROL_LOW                           0x150
+#define MV64340_CPU_CROSS_BAR_CONTROL_HIGH                          0x158
+#define MV64340_CPU_CROSS_BAR_TIMEOUT                               0x168
+
+/****************************************/
+/* SMP RegisterS                        */
+/****************************************/
+
+#define MV64340_SMP_WHO_AM_I                                        0x200
+#define MV64340_SMP_CPU0_DOORBELL                                   0x214
+#define MV64340_SMP_CPU0_DOORBELL_CLEAR                             0x21C
+#define MV64340_SMP_CPU1_DOORBELL                                   0x224
+#define MV64340_SMP_CPU1_DOORBELL_CLEAR                             0x22C
+#define MV64340_SMP_CPU0_DOORBELL_MASK                              0x234
+#define MV64340_SMP_CPU1_DOORBELL_MASK                              0x23C
+#define MV64340_SMP_SEMAPHOR0                                       0x244
+#define MV64340_SMP_SEMAPHOR1                                       0x24c
+#define MV64340_SMP_SEMAPHOR2                                       0x254
+#define MV64340_SMP_SEMAPHOR3                                       0x25c
+#define MV64340_SMP_SEMAPHOR4                                       0x264
+#define MV64340_SMP_SEMAPHOR5                                       0x26c
+#define MV64340_SMP_SEMAPHOR6                                       0x274
+#define MV64340_SMP_SEMAPHOR7                                       0x27c
+
+/****************************************/
+/*  CPU Sync Barrier Register           */
+/****************************************/
+
+#define MV64340_CPU_0_SYNC_BARRIER_TRIGGER                          0x0c0
+#define MV64340_CPU_0_SYNC_BARRIER_VIRTUAL                          0x0c8
+#define MV64340_CPU_1_SYNC_BARRIER_TRIGGER                          0x0d0
+#define MV64340_CPU_1_SYNC_BARRIER_VIRTUAL                          0x0d8
+
+/****************************************/
+/* CPU Access Protect                   */
+/****************************************/
+
+#define MV64340_CPU_PROTECT_WINDOW_0_BASE_ADDR                      0x180
+#define MV64340_CPU_PROTECT_WINDOW_0_SIZE                           0x188
+#define MV64340_CPU_PROTECT_WINDOW_1_BASE_ADDR                      0x190
+#define MV64340_CPU_PROTECT_WINDOW_1_SIZE                           0x198
+#define MV64340_CPU_PROTECT_WINDOW_2_BASE_ADDR                      0x1a0
+#define MV64340_CPU_PROTECT_WINDOW_2_SIZE                           0x1a8
+#define MV64340_CPU_PROTECT_WINDOW_3_BASE_ADDR                      0x1b0
+#define MV64340_CPU_PROTECT_WINDOW_3_SIZE                           0x1b8
+
+
+/****************************************/
+/*          CPU Error Report            */
+/****************************************/
+
+#define MV64340_CPU_ERROR_ADDR_LOW                                  0x070
+#define MV64340_CPU_ERROR_ADDR_HIGH                                 0x078
+#define MV64340_CPU_ERROR_DATA_LOW                                  0x128
+#define MV64340_CPU_ERROR_DATA_HIGH                                 0x130
+#define MV64340_CPU_ERROR_PARITY                                    0x138
+#define MV64340_CPU_ERROR_CAUSE                                     0x140
+#define MV64340_CPU_ERROR_MASK                                      0x148
+
+/****************************************/
+/*      CPU Interface Debug Registers 	*/
+/****************************************/
+
+#define MV64340_PUNIT_SLAVE_DEBUG_LOW                               0x360
+#define MV64340_PUNIT_SLAVE_DEBUG_HIGH                              0x368
+#define MV64340_PUNIT_MASTER_DEBUG_LOW                              0x370
+#define MV64340_PUNIT_MASTER_DEBUG_HIGH                             0x378
+#define MV64340_PUNIT_MMASK                                         0x3e4
+
+/****************************************/
+/*  Integrated SRAM Registers           */
+/****************************************/
+
+#define MV64340_SRAM_CONFIG                                         0x380
+#define MV64340_SRAM_TEST_MODE                                      0X3F4
+#define MV64340_SRAM_ERROR_CAUSE                                    0x388
+#define MV64340_SRAM_ERROR_ADDR                                     0x390
+#define MV64340_SRAM_ERROR_ADDR_HIGH                                0X3F8
+#define MV64340_SRAM_ERROR_DATA_LOW                                 0x398
+#define MV64340_SRAM_ERROR_DATA_HIGH                                0x3a0
+#define MV64340_SRAM_ERROR_DATA_PARITY                              0x3a8
+
+/****************************************/
+/* SDRAM Configuration                  */
+/****************************************/
+
+#define MV64340_SDRAM_CONFIG                                        0x1400
+#define MV64340_D_UNIT_CONTROL_LOW                                  0x1404
+#define MV64340_D_UNIT_CONTROL_HIGH                                 0x1424
+#define MV64340_SDRAM_TIMING_CONTROL_LOW                            0x1408
+#define MV64340_SDRAM_TIMING_CONTROL_HIGH                           0x140c
+#define MV64340_SDRAM_ADDR_CONTROL                                  0x1410
+#define MV64340_SDRAM_OPEN_PAGES_CONTROL                            0x1414
+#define MV64340_SDRAM_OPERATION                                     0x1418
+#define MV64340_SDRAM_MODE                                          0x141c
+#define MV64340_EXTENDED_DRAM_MODE                                  0x1420
+#define MV64340_SDRAM_CROSS_BAR_CONTROL_LOW                         0x1430
+#define MV64340_SDRAM_CROSS_BAR_CONTROL_HIGH                        0x1434
+#define MV64340_SDRAM_CROSS_BAR_TIMEOUT                             0x1438
+#define MV64340_SDRAM_ADDR_CTRL_PADS_CALIBRATION                    0x14c0
+#define MV64340_SDRAM_DATA_PADS_CALIBRATION                         0x14c4
+
+/****************************************/
+/* SDRAM Error Report                   */
+/****************************************/
+
+#define MV64340_SDRAM_ERROR_DATA_LOW                                0x1444
+#define MV64340_SDRAM_ERROR_DATA_HIGH                               0x1440
+#define MV64340_SDRAM_ERROR_ADDR                                    0x1450
+#define MV64340_SDRAM_RECEIVED_ECC                                  0x1448
+#define MV64340_SDRAM_CALCULATED_ECC                                0x144c
+#define MV64340_SDRAM_ECC_CONTROL                                   0x1454
+#define MV64340_SDRAM_ECC_ERROR_COUNTER                             0x1458
+
+/******************************************/
+/*  Controlled Delay Line (CDL) Registers */
+/******************************************/
+
+#define MV64340_DFCDL_CONFIG0                                       0x1480
+#define MV64340_DFCDL_CONFIG1                                       0x1484
+#define MV64340_DLL_WRITE                                           0x1488
+#define MV64340_DLL_READ                                            0x148c
+#define MV64340_SRAM_ADDR                                           0x1490
+#define MV64340_SRAM_DATA0                                          0x1494
+#define MV64340_SRAM_DATA1                                          0x1498
+#define MV64340_SRAM_DATA2                                          0x149c
+#define MV64340_DFCL_PROBE                                          0x14a0
+
+/******************************************/
+/*   Debug Registers                      */
+/******************************************/
+
+#define MV64340_DUNIT_DEBUG_LOW                                     0x1460
+#define MV64340_DUNIT_DEBUG_HIGH                                    0x1464
+#define MV64340_DUNIT_MMASK                                         0X1b40
+
+/****************************************/
+/* Device Parameters			*/
+/****************************************/
+
+#define MV64340_DEVICE_BANK0_PARAMETERS				    0x45c
+#define MV64340_DEVICE_BANK1_PARAMETERS				    0x460
+#define MV64340_DEVICE_BANK2_PARAMETERS				    0x464
+#define MV64340_DEVICE_BANK3_PARAMETERS				    0x468
+#define MV64340_DEVICE_BOOT_BANK_PARAMETERS			    0x46c
+#define MV64340_DEVICE_INTERFACE_CONTROL                            0x4c0
+#define MV64340_DEVICE_INTERFACE_CROSS_BAR_CONTROL_LOW              0x4c8
+#define MV64340_DEVICE_INTERFACE_CROSS_BAR_CONTROL_HIGH             0x4cc
+#define MV64340_DEVICE_INTERFACE_CROSS_BAR_TIMEOUT                  0x4c4
+
+/****************************************/
+/* Device interrupt registers		*/
+/****************************************/
+
+#define MV64340_DEVICE_INTERRUPT_CAUSE				    0x4d0
+#define MV64340_DEVICE_INTERRUPT_MASK				    0x4d4
+#define MV64340_DEVICE_ERROR_ADDR				    0x4d8
+#define MV64340_DEVICE_ERROR_DATA   				    0x4dc
+#define MV64340_DEVICE_ERROR_PARITY     			    0x4e0
+
+/****************************************/
+/* Device debug registers   		*/
+/****************************************/
+
+#define MV64340_DEVICE_DEBUG_LOW     				    0x4e4
+#define MV64340_DEVICE_DEBUG_HIGH     				    0x4e8
+#define MV64340_RUNIT_MMASK                                         0x4f0
+
+/****************************************/
+/* PCI Slave Address Decoding registers */
+/****************************************/
+
+#define MV64340_PCI_0_CS_0_BANK_SIZE                                0xc08
+#define MV64340_PCI_1_CS_0_BANK_SIZE                                0xc88
+#define MV64340_PCI_0_CS_1_BANK_SIZE                                0xd08
+#define MV64340_PCI_1_CS_1_BANK_SIZE                                0xd88
+#define MV64340_PCI_0_CS_2_BANK_SIZE                                0xc0c
+#define MV64340_PCI_1_CS_2_BANK_SIZE                                0xc8c
+#define MV64340_PCI_0_CS_3_BANK_SIZE                                0xd0c
+#define MV64340_PCI_1_CS_3_BANK_SIZE                                0xd8c
+#define MV64340_PCI_0_DEVCS_0_BANK_SIZE                             0xc10
+#define MV64340_PCI_1_DEVCS_0_BANK_SIZE                             0xc90
+#define MV64340_PCI_0_DEVCS_1_BANK_SIZE                             0xd10
+#define MV64340_PCI_1_DEVCS_1_BANK_SIZE                             0xd90
+#define MV64340_PCI_0_DEVCS_2_BANK_SIZE                             0xd18
+#define MV64340_PCI_1_DEVCS_2_BANK_SIZE                             0xd98
+#define MV64340_PCI_0_DEVCS_3_BANK_SIZE                             0xc14
+#define MV64340_PCI_1_DEVCS_3_BANK_SIZE                             0xc94
+#define MV64340_PCI_0_DEVCS_BOOT_BANK_SIZE                          0xd14
+#define MV64340_PCI_1_DEVCS_BOOT_BANK_SIZE                          0xd94
+#define MV64340_PCI_0_P2P_MEM0_BAR_SIZE                             0xd1c
+#define MV64340_PCI_1_P2P_MEM0_BAR_SIZE                             0xd9c
+#define MV64340_PCI_0_P2P_MEM1_BAR_SIZE                             0xd20
+#define MV64340_PCI_1_P2P_MEM1_BAR_SIZE                             0xda0
+#define MV64340_PCI_0_P2P_I_O_BAR_SIZE                              0xd24
+#define MV64340_PCI_1_P2P_I_O_BAR_SIZE                              0xda4
+#define MV64340_PCI_0_CPU_BAR_SIZE                                  0xd28
+#define MV64340_PCI_1_CPU_BAR_SIZE                                  0xda8
+#define MV64340_PCI_0_INTERNAL_SRAM_BAR_SIZE                        0xe00
+#define MV64340_PCI_1_INTERNAL_SRAM_BAR_SIZE                        0xe80
+#define MV64340_PCI_0_EXPANSION_ROM_BAR_SIZE                        0xd2c
+#define MV64340_PCI_1_EXPANSION_ROM_BAR_SIZE                        0xd9c
+#define MV64340_PCI_0_BASE_ADDR_REG_ENABLE                          0xc3c
+#define MV64340_PCI_1_BASE_ADDR_REG_ENABLE                          0xcbc
+#define MV64340_PCI_0_CS_0_BASE_ADDR_REMAP			    0xc48
+#define MV64340_PCI_1_CS_0_BASE_ADDR_REMAP			    0xcc8
+#define MV64340_PCI_0_CS_1_BASE_ADDR_REMAP			    0xd48
+#define MV64340_PCI_1_CS_1_BASE_ADDR_REMAP			    0xdc8
+#define MV64340_PCI_0_CS_2_BASE_ADDR_REMAP			    0xc4c
+#define MV64340_PCI_1_CS_2_BASE_ADDR_REMAP			    0xccc
+#define MV64340_PCI_0_CS_3_BASE_ADDR_REMAP			    0xd4c
+#define MV64340_PCI_1_CS_3_BASE_ADDR_REMAP			    0xdcc
+#define MV64340_PCI_0_CS_0_BASE_HIGH_ADDR_REMAP			    0xF04
+#define MV64340_PCI_1_CS_0_BASE_HIGH_ADDR_REMAP			    0xF84
+#define MV64340_PCI_0_CS_1_BASE_HIGH_ADDR_REMAP			    0xF08
+#define MV64340_PCI_1_CS_1_BASE_HIGH_ADDR_REMAP			    0xF88
+#define MV64340_PCI_0_CS_2_BASE_HIGH_ADDR_REMAP			    0xF0C
+#define MV64340_PCI_1_CS_2_BASE_HIGH_ADDR_REMAP			    0xF8C
+#define MV64340_PCI_0_CS_3_BASE_HIGH_ADDR_REMAP			    0xF10
+#define MV64340_PCI_1_CS_3_BASE_HIGH_ADDR_REMAP			    0xF90
+#define MV64340_PCI_0_DEVCS_0_BASE_ADDR_REMAP			    0xc50
+#define MV64340_PCI_1_DEVCS_0_BASE_ADDR_REMAP			    0xcd0
+#define MV64340_PCI_0_DEVCS_1_BASE_ADDR_REMAP			    0xd50
+#define MV64340_PCI_1_DEVCS_1_BASE_ADDR_REMAP			    0xdd0
+#define MV64340_PCI_0_DEVCS_2_BASE_ADDR_REMAP			    0xd58
+#define MV64340_PCI_1_DEVCS_2_BASE_ADDR_REMAP			    0xdd8
+#define MV64340_PCI_0_DEVCS_3_BASE_ADDR_REMAP           	    0xc54
+#define MV64340_PCI_1_DEVCS_3_BASE_ADDR_REMAP           	    0xcd4
+#define MV64340_PCI_0_DEVCS_BOOTCS_BASE_ADDR_REMAP      	    0xd54
+#define MV64340_PCI_1_DEVCS_BOOTCS_BASE_ADDR_REMAP      	    0xdd4
+#define MV64340_PCI_0_P2P_MEM0_BASE_ADDR_REMAP_LOW                  0xd5c
+#define MV64340_PCI_1_P2P_MEM0_BASE_ADDR_REMAP_LOW                  0xddc
+#define MV64340_PCI_0_P2P_MEM0_BASE_ADDR_REMAP_HIGH                 0xd60
+#define MV64340_PCI_1_P2P_MEM0_BASE_ADDR_REMAP_HIGH                 0xde0
+#define MV64340_PCI_0_P2P_MEM1_BASE_ADDR_REMAP_LOW                  0xd64
+#define MV64340_PCI_1_P2P_MEM1_BASE_ADDR_REMAP_LOW                  0xde4
+#define MV64340_PCI_0_P2P_MEM1_BASE_ADDR_REMAP_HIGH                 0xd68
+#define MV64340_PCI_1_P2P_MEM1_BASE_ADDR_REMAP_HIGH                 0xde8
+#define MV64340_PCI_0_P2P_I_O_BASE_ADDR_REMAP                       0xd6c
+#define MV64340_PCI_1_P2P_I_O_BASE_ADDR_REMAP                       0xdec 
+#define MV64340_PCI_0_CPU_BASE_ADDR_REMAP_LOW                       0xd70
+#define MV64340_PCI_1_CPU_BASE_ADDR_REMAP_LOW                       0xdf0
+#define MV64340_PCI_0_CPU_BASE_ADDR_REMAP_HIGH                      0xd74
+#define MV64340_PCI_1_CPU_BASE_ADDR_REMAP_HIGH                      0xdf4
+#define MV64340_PCI_0_INTEGRATED_SRAM_BASE_ADDR_REMAP               0xf00
+#define MV64340_PCI_1_INTEGRATED_SRAM_BASE_ADDR_REMAP               0xf80
+#define MV64340_PCI_0_EXPANSION_ROM_BASE_ADDR_REMAP                 0xf38
+#define MV64340_PCI_1_EXPANSION_ROM_BASE_ADDR_REMAP                 0xfb8
+#define MV64340_PCI_0_ADDR_DECODE_CONTROL                           0xd3c
+#define MV64340_PCI_1_ADDR_DECODE_CONTROL                           0xdbc
+#define MV64340_PCI_0_HEADERS_RETARGET_CONTROL                      0xF40
+#define MV64340_PCI_1_HEADERS_RETARGET_CONTROL                      0xFc0
+#define MV64340_PCI_0_HEADERS_RETARGET_BASE                         0xF44
+#define MV64340_PCI_1_HEADERS_RETARGET_BASE                         0xFc4
+#define MV64340_PCI_0_HEADERS_RETARGET_HIGH                         0xF48
+#define MV64340_PCI_1_HEADERS_RETARGET_HIGH                         0xFc8
+
+/***********************************/
+/*   PCI Control Register Map      */
+/***********************************/
+
+#define MV64340_PCI_0_DLL_STATUS_AND_COMMAND                        0x1d20
+#define MV64340_PCI_1_DLL_STATUS_AND_COMMAND                        0x1da0
+#define MV64340_PCI_0_MPP_PADS_DRIVE_CONTROL                        0x1d1C
+#define MV64340_PCI_1_MPP_PADS_DRIVE_CONTROL                        0x1d9C
+#define MV64340_PCI_0_COMMAND			         	    0xc00
+#define MV64340_PCI_1_COMMAND					    0xc80
+#define MV64340_PCI_0_MODE                                          0xd00
+#define MV64340_PCI_1_MODE                                          0xd80
+#define MV64340_PCI_0_RETRY	        	 		    0xc04
+#define MV64340_PCI_1_RETRY				            0xc84
+#define MV64340_PCI_0_READ_BUFFER_DISCARD_TIMER                     0xd04
+#define MV64340_PCI_1_READ_BUFFER_DISCARD_TIMER                     0xd84
+#define MV64340_PCI_0_MSI_TRIGGER_TIMER                             0xc38
+#define MV64340_PCI_1_MSI_TRIGGER_TIMER                             0xcb8
+#define MV64340_PCI_0_ARBITER_CONTROL                               0x1d00
+#define MV64340_PCI_1_ARBITER_CONTROL                               0x1d80
+#define MV64340_PCI_0_CROSS_BAR_CONTROL_LOW                         0x1d08
+#define MV64340_PCI_1_CROSS_BAR_CONTROL_LOW                         0x1d88
+#define MV64340_PCI_0_CROSS_BAR_CONTROL_HIGH                        0x1d0c
+#define MV64340_PCI_1_CROSS_BAR_CONTROL_HIGH                        0x1d8c
+#define MV64340_PCI_0_CROSS_BAR_TIMEOUT                             0x1d04
+#define MV64340_PCI_1_CROSS_BAR_TIMEOUT                             0x1d84
+#define MV64340_PCI_0_SYNC_BARRIER_TRIGGER_REG                      0x1D18
+#define MV64340_PCI_1_SYNC_BARRIER_TRIGGER_REG                      0x1D98
+#define MV64340_PCI_0_SYNC_BARRIER_VIRTUAL_REG                      0x1d10
+#define MV64340_PCI_1_SYNC_BARRIER_VIRTUAL_REG                      0x1d90
+#define MV64340_PCI_0_P2P_CONFIG                                    0x1d14
+#define MV64340_PCI_1_P2P_CONFIG                                    0x1d94
+
+#define MV64340_PCI_0_ACCESS_CONTROL_BASE_0_LOW                     0x1e00
+#define MV64340_PCI_0_ACCESS_CONTROL_BASE_0_HIGH                    0x1e04
+#define MV64340_PCI_0_ACCESS_CONTROL_SIZE_0                         0x1e08
+#define MV64340_PCI_0_ACCESS_CONTROL_BASE_1_LOW                     0x1e10
+#define MV64340_PCI_0_ACCESS_CONTROL_BASE_1_HIGH                    0x1e14
+#define MV64340_PCI_0_ACCESS_CONTROL_SIZE_1                         0x1e18
+#define MV64340_PCI_0_ACCESS_CONTROL_BASE_2_LOW                     0x1e20
+#define MV64340_PCI_0_ACCESS_CONTROL_BASE_2_HIGH                    0x1e24
+#define MV64340_PCI_0_ACCESS_CONTROL_SIZE_2                         0x1e28
+#define MV64340_PCI_0_ACCESS_CONTROL_BASE_3_LOW                     0x1e30
+#define MV64340_PCI_0_ACCESS_CONTROL_BASE_3_HIGH                    0x1e34
+#define MV64340_PCI_0_ACCESS_CONTROL_SIZE_3                         0x1e38
+#define MV64340_PCI_0_ACCESS_CONTROL_BASE_4_LOW                     0x1e40
+#define MV64340_PCI_0_ACCESS_CONTROL_BASE_4_HIGH                    0x1e44
+#define MV64340_PCI_0_ACCESS_CONTROL_SIZE_4                         0x1e48
+#define MV64340_PCI_0_ACCESS_CONTROL_BASE_5_LOW                     0x1e50
+#define MV64340_PCI_0_ACCESS_CONTROL_BASE_5_HIGH                    0x1e54
+#define MV64340_PCI_0_ACCESS_CONTROL_SIZE_5                         0x1e58
+
+#define MV64340_PCI_1_ACCESS_CONTROL_BASE_0_LOW                     0x1e80
+#define MV64340_PCI_1_ACCESS_CONTROL_BASE_0_HIGH                    0x1e84
+#define MV64340_PCI_1_ACCESS_CONTROL_SIZE_0                         0x1e88
+#define MV64340_PCI_1_ACCESS_CONTROL_BASE_1_LOW                     0x1e90
+#define MV64340_PCI_1_ACCESS_CONTROL_BASE_1_HIGH                    0x1e94
+#define MV64340_PCI_1_ACCESS_CONTROL_SIZE_1                         0x1e98
+#define MV64340_PCI_1_ACCESS_CONTROL_BASE_2_LOW                     0x1ea0
+#define MV64340_PCI_1_ACCESS_CONTROL_BASE_2_HIGH                    0x1ea4
+#define MV64340_PCI_1_ACCESS_CONTROL_SIZE_2                         0x1ea8
+#define MV64340_PCI_1_ACCESS_CONTROL_BASE_3_LOW                     0x1eb0
+#define MV64340_PCI_1_ACCESS_CONTROL_BASE_3_HIGH                    0x1eb4
+#define MV64340_PCI_1_ACCESS_CONTROL_SIZE_3                         0x1eb8
+#define MV64340_PCI_1_ACCESS_CONTROL_BASE_4_LOW                     0x1ec0
+#define MV64340_PCI_1_ACCESS_CONTROL_BASE_4_HIGH                    0x1ec4
+#define MV64340_PCI_1_ACCESS_CONTROL_SIZE_4                         0x1ec8
+#define MV64340_PCI_1_ACCESS_CONTROL_BASE_5_LOW                     0x1ed0
+#define MV64340_PCI_1_ACCESS_CONTROL_BASE_5_HIGH                    0x1ed4
+#define MV64340_PCI_1_ACCESS_CONTROL_SIZE_5                         0x1ed8
+
+/****************************************/
+/*   PCI Configuration Access Registers */
+/****************************************/
+
+#define MV64340_PCI_0_CONFIG_ADDR 				    0xcf8
+#define MV64340_PCI_0_CONFIG_DATA_VIRTUAL_REG                       0xcfc
+#define MV64340_PCI_1_CONFIG_ADDR 				    0xc78
+#define MV64340_PCI_1_CONFIG_DATA_VIRTUAL_REG                       0xc7c
+#define MV64340_PCI_0_INTERRUPT_ACKNOWLEDGE_VIRTUAL_REG	            0xc34
+#define MV64340_PCI_1_INTERRUPT_ACKNOWLEDGE_VIRTUAL_REG	            0xcb4
+
+/****************************************/
+/*   PCI Error Report Registers         */
+/****************************************/
+
+#define MV64340_PCI_0_SERR_MASK					    0xc28
+#define MV64340_PCI_1_SERR_MASK					    0xca8
+#define MV64340_PCI_0_ERROR_ADDR_LOW                                0x1d40
+#define MV64340_PCI_1_ERROR_ADDR_LOW                                0x1dc0
+#define MV64340_PCI_0_ERROR_ADDR_HIGH                               0x1d44
+#define MV64340_PCI_1_ERROR_ADDR_HIGH                               0x1dc4
+#define MV64340_PCI_0_ERROR_ATTRIBUTE                               0x1d48
+#define MV64340_PCI_1_ERROR_ATTRIBUTE                               0x1dc8
+#define MV64340_PCI_0_ERROR_COMMAND                                 0x1d50
+#define MV64340_PCI_1_ERROR_COMMAND                                 0x1dd0
+#define MV64340_PCI_0_ERROR_CAUSE                                   0x1d58
+#define MV64340_PCI_1_ERROR_CAUSE                                   0x1dd8
+#define MV64340_PCI_0_ERROR_MASK                                    0x1d5c
+#define MV64340_PCI_1_ERROR_MASK                                    0x1ddc
+
+/****************************************/
+/*   PCI Debug Registers                */
+/****************************************/
+
+#define MV64340_PCI_0_MMASK                                         0X1D24
+#define MV64340_PCI_1_MMASK                                         0X1DA4
+
+/*********************************************/
+/* PCI Configuration, Function 0, Registers  */
+/*********************************************/
+
+#define MV64340_PCI_DEVICE_AND_VENDOR_ID 			    0x000
+#define MV64340_PCI_STATUS_AND_COMMAND				    0x004
+#define MV64340_PCI_CLASS_CODE_AND_REVISION_ID			    0x008
+#define MV64340_PCI_BIST_HEADER_TYPE_LATENCY_TIMER_CACHE_LINE 	    0x00C
+
+#define MV64340_PCI_SCS_0_BASE_ADDR_LOW   	      		    0x010
+#define MV64340_PCI_SCS_0_BASE_ADDR_HIGH   		            0x014
+#define MV64340_PCI_SCS_1_BASE_ADDR_LOW  	     	            0x018
+#define MV64340_PCI_SCS_1_BASE_ADDR_HIGH 		            0x01C
+#define MV64340_PCI_INTERNAL_REG_MEM_MAPPED_BASE_ADDR_LOW      	    0x020
+#define MV64340_PCI_INTERNAL_REG_MEM_MAPPED_BASE_ADDR_HIGH     	    0x024
+#define MV64340_PCI_SUBSYSTEM_ID_AND_SUBSYSTEM_VENDOR_ID	    0x02c
+#define MV64340_PCI_EXPANSION_ROM_BASE_ADDR_REG	                    0x030
+#define MV64340_PCI_CAPABILTY_LIST_POINTER                          0x034
+#define MV64340_PCI_INTERRUPT_PIN_AND_LINE 			    0x03C
+       /* capability list */
+#define MV64340_PCI_POWER_MANAGEMENT_CAPABILITY                     0x040
+#define MV64340_PCI_POWER_MANAGEMENT_STATUS_AND_CONTROL             0x044
+#define MV64340_PCI_VPD_ADDR                                        0x048
+#define MV64340_PCI_VPD_DATA                                        0x04c
+#define MV64340_PCI_MSI_MESSAGE_CONTROL                             0x050
+#define MV64340_PCI_MSI_MESSAGE_ADDR                                0x054
+#define MV64340_PCI_MSI_MESSAGE_UPPER_ADDR                          0x058
+#define MV64340_PCI_MSI_MESSAGE_DATA                                0x05c
+#define MV64340_PCI_X_COMMAND                                       0x060
+#define MV64340_PCI_X_STATUS                                        0x064
+#define MV64340_PCI_COMPACT_PCI_HOT_SWAP                            0x068
+
+/***********************************************/
+/*   PCI Configuration, Function 1, Registers  */
+/***********************************************/
+
+#define MV64340_PCI_SCS_2_BASE_ADDR_LOW   			    0x110
+#define MV64340_PCI_SCS_2_BASE_ADDR_HIGH			    0x114
+#define MV64340_PCI_SCS_3_BASE_ADDR_LOW 			    0x118
+#define MV64340_PCI_SCS_3_BASE_ADDR_HIGH			    0x11c
+#define MV64340_PCI_INTERNAL_SRAM_BASE_ADDR_LOW          	    0x120
+#define MV64340_PCI_INTERNAL_SRAM_BASE_ADDR_HIGH         	    0x124
+
+/***********************************************/
+/*  PCI Configuration, Function 2, Registers   */
+/***********************************************/
+
+#define MV64340_PCI_DEVCS_0_BASE_ADDR_LOW	    		    0x210
+#define MV64340_PCI_DEVCS_0_BASE_ADDR_HIGH 			    0x214
+#define MV64340_PCI_DEVCS_1_BASE_ADDR_LOW 			    0x218
+#define MV64340_PCI_DEVCS_1_BASE_ADDR_HIGH      		    0x21c
+#define MV64340_PCI_DEVCS_2_BASE_ADDR_LOW 			    0x220
+#define MV64340_PCI_DEVCS_2_BASE_ADDR_HIGH      		    0x224
+
+/***********************************************/
+/*  PCI Configuration, Function 3, Registers   */
+/***********************************************/
+
+#define MV64340_PCI_DEVCS_3_BASE_ADDR_LOW	    		    0x310
+#define MV64340_PCI_DEVCS_3_BASE_ADDR_HIGH 			    0x314
+#define MV64340_PCI_BOOT_CS_BASE_ADDR_LOW			    0x318
+#define MV64340_PCI_BOOT_CS_BASE_ADDR_HIGH      		    0x31c
+#define MV64340_PCI_CPU_BASE_ADDR_LOW 				    0x220
+#define MV64340_PCI_CPU_BASE_ADDR_HIGH      			    0x224
+
+/***********************************************/
+/*  PCI Configuration, Function 4, Registers   */
+/***********************************************/
+
+#define MV64340_PCI_P2P_MEM0_BASE_ADDR_LOW  			    0x410
+#define MV64340_PCI_P2P_MEM0_BASE_ADDR_HIGH 			    0x414
+#define MV64340_PCI_P2P_MEM1_BASE_ADDR_LOW   			    0x418
+#define MV64340_PCI_P2P_MEM1_BASE_ADDR_HIGH 			    0x41c
+#define MV64340_PCI_P2P_I_O_BASE_ADDR                 	            0x420
+#define MV64340_PCI_INTERNAL_REGS_I_O_MAPPED_BASE_ADDR              0x424
+
+/****************************************/
+/* Messaging Unit Registers (I20)   	*/
+/****************************************/
+
+#define MV64340_I2O_INBOUND_MESSAGE_REG0_PCI_0_SIDE		    0x010
+#define MV64340_I2O_INBOUND_MESSAGE_REG1_PCI_0_SIDE  		    0x014
+#define MV64340_I2O_OUTBOUND_MESSAGE_REG0_PCI_0_SIDE 		    0x018
+#define MV64340_I2O_OUTBOUND_MESSAGE_REG1_PCI_0_SIDE  		    0x01C
+#define MV64340_I2O_INBOUND_DOORBELL_REG_PCI_0_SIDE  		    0x020
+#define MV64340_I2O_INBOUND_INTERRUPT_CAUSE_REG_PCI_0_SIDE          0x024
+#define MV64340_I2O_INBOUND_INTERRUPT_MASK_REG_PCI_0_SIDE	    0x028
+#define MV64340_I2O_OUTBOUND_DOORBELL_REG_PCI_0_SIDE 		    0x02C
+#define MV64340_I2O_OUTBOUND_INTERRUPT_CAUSE_REG_PCI_0_SIDE         0x030
+#define MV64340_I2O_OUTBOUND_INTERRUPT_MASK_REG_PCI_0_SIDE          0x034
+#define MV64340_I2O_INBOUND_QUEUE_PORT_VIRTUAL_REG_PCI_0_SIDE       0x040
+#define MV64340_I2O_OUTBOUND_QUEUE_PORT_VIRTUAL_REG_PCI_0_SIDE      0x044
+#define MV64340_I2O_QUEUE_CONTROL_REG_PCI_0_SIDE 		    0x050
+#define MV64340_I2O_QUEUE_BASE_ADDR_REG_PCI_0_SIDE 		    0x054
+#define MV64340_I2O_INBOUND_FREE_HEAD_POINTER_REG_PCI_0_SIDE        0x060
+#define MV64340_I2O_INBOUND_FREE_TAIL_POINTER_REG_PCI_0_SIDE        0x064
+#define MV64340_I2O_INBOUND_POST_HEAD_POINTER_REG_PCI_0_SIDE        0x068
+#define MV64340_I2O_INBOUND_POST_TAIL_POINTER_REG_PCI_0_SIDE        0x06C
+#define MV64340_I2O_OUTBOUND_FREE_HEAD_POINTER_REG_PCI_0_SIDE       0x070
+#define MV64340_I2O_OUTBOUND_FREE_TAIL_POINTER_REG_PCI_0_SIDE       0x074
+#define MV64340_I2O_OUTBOUND_POST_HEAD_POINTER_REG_PCI_0_SIDE       0x0F8
+#define MV64340_I2O_OUTBOUND_POST_TAIL_POINTER_REG_PCI_0_SIDE       0x0FC
+
+#define MV64340_I2O_INBOUND_MESSAGE_REG0_PCI_1_SIDE		    0x090
+#define MV64340_I2O_INBOUND_MESSAGE_REG1_PCI_1_SIDE  		    0x094
+#define MV64340_I2O_OUTBOUND_MESSAGE_REG0_PCI_1_SIDE 		    0x098
+#define MV64340_I2O_OUTBOUND_MESSAGE_REG1_PCI_1_SIDE  		    0x09C
+#define MV64340_I2O_INBOUND_DOORBELL_REG_PCI_1_SIDE  		    0x0A0
+#define MV64340_I2O_INBOUND_INTERRUPT_CAUSE_REG_PCI_1_SIDE          0x0A4
+#define MV64340_I2O_INBOUND_INTERRUPT_MASK_REG_PCI_1_SIDE	    0x0A8
+#define MV64340_I2O_OUTBOUND_DOORBELL_REG_PCI_1_SIDE 		    0x0AC
+#define MV64340_I2O_OUTBOUND_INTERRUPT_CAUSE_REG_PCI_1_SIDE         0x0B0
+#define MV64340_I2O_OUTBOUND_INTERRUPT_MASK_REG_PCI_1_SIDE          0x0B4
+#define MV64340_I2O_INBOUND_QUEUE_PORT_VIRTUAL_REG_PCI_1_SIDE       0x0C0
+#define MV64340_I2O_OUTBOUND_QUEUE_PORT_VIRTUAL_REG_PCI_1_SIDE      0x0C4
+#define MV64340_I2O_QUEUE_CONTROL_REG_PCI_1_SIDE 		    0x0D0
+#define MV64340_I2O_QUEUE_BASE_ADDR_REG_PCI_1_SIDE 		    0x0D4
+#define MV64340_I2O_INBOUND_FREE_HEAD_POINTER_REG_PCI_1_SIDE        0x0E0
+#define MV64340_I2O_INBOUND_FREE_TAIL_POINTER_REG_PCI_1_SIDE        0x0E4
+#define MV64340_I2O_INBOUND_POST_HEAD_POINTER_REG_PCI_1_SIDE        0x0E8
+#define MV64340_I2O_INBOUND_POST_TAIL_POINTER_REG_PCI_1_SIDE        0x0EC
+#define MV64340_I2O_OUTBOUND_FREE_HEAD_POINTER_REG_PCI_1_SIDE       0x0F0
+#define MV64340_I2O_OUTBOUND_FREE_TAIL_POINTER_REG_PCI_1_SIDE       0x0F4
+#define MV64340_I2O_OUTBOUND_POST_HEAD_POINTER_REG_PCI_1_SIDE       0x078
+#define MV64340_I2O_OUTBOUND_POST_TAIL_POINTER_REG_PCI_1_SIDE       0x07C
+
+#define MV64340_I2O_INBOUND_MESSAGE_REG0_CPU0_SIDE		    0x1C10
+#define MV64340_I2O_INBOUND_MESSAGE_REG1_CPU0_SIDE  		    0x1C14
+#define MV64340_I2O_OUTBOUND_MESSAGE_REG0_CPU0_SIDE 		    0x1C18
+#define MV64340_I2O_OUTBOUND_MESSAGE_REG1_CPU0_SIDE  		    0x1C1C
+#define MV64340_I2O_INBOUND_DOORBELL_REG_CPU0_SIDE  		    0x1C20
+#define MV64340_I2O_INBOUND_INTERRUPT_CAUSE_REG_CPU0_SIDE  	    0x1C24
+#define MV64340_I2O_INBOUND_INTERRUPT_MASK_REG_CPU0_SIDE	    0x1C28
+#define MV64340_I2O_OUTBOUND_DOORBELL_REG_CPU0_SIDE 		    0x1C2C
+#define MV64340_I2O_OUTBOUND_INTERRUPT_CAUSE_REG_CPU0_SIDE          0x1C30
+#define MV64340_I2O_OUTBOUND_INTERRUPT_MASK_REG_CPU0_SIDE           0x1C34
+#define MV64340_I2O_INBOUND_QUEUE_PORT_VIRTUAL_REG_CPU0_SIDE        0x1C40
+#define MV64340_I2O_OUTBOUND_QUEUE_PORT_VIRTUAL_REG_CPU0_SIDE       0x1C44
+#define MV64340_I2O_QUEUE_CONTROL_REG_CPU0_SIDE 		    0x1C50
+#define MV64340_I2O_QUEUE_BASE_ADDR_REG_CPU0_SIDE 		    0x1C54
+#define MV64340_I2O_INBOUND_FREE_HEAD_POINTER_REG_CPU0_SIDE         0x1C60
+#define MV64340_I2O_INBOUND_FREE_TAIL_POINTER_REG_CPU0_SIDE         0x1C64
+#define MV64340_I2O_INBOUND_POST_HEAD_POINTER_REG_CPU0_SIDE         0x1C68
+#define MV64340_I2O_INBOUND_POST_TAIL_POINTER_REG_CPU0_SIDE         0x1C6C
+#define MV64340_I2O_OUTBOUND_FREE_HEAD_POINTER_REG_CPU0_SIDE        0x1C70
+#define MV64340_I2O_OUTBOUND_FREE_TAIL_POINTER_REG_CPU0_SIDE        0x1C74
+#define MV64340_I2O_OUTBOUND_POST_HEAD_POINTER_REG_CPU0_SIDE        0x1CF8
+#define MV64340_I2O_OUTBOUND_POST_TAIL_POINTER_REG_CPU0_SIDE        0x1CFC
+#define MV64340_I2O_INBOUND_MESSAGE_REG0_CPU1_SIDE		    0x1C90
+#define MV64340_I2O_INBOUND_MESSAGE_REG1_CPU1_SIDE  		    0x1C94
+#define MV64340_I2O_OUTBOUND_MESSAGE_REG0_CPU1_SIDE 		    0x1C98
+#define MV64340_I2O_OUTBOUND_MESSAGE_REG1_CPU1_SIDE  		    0x1C9C
+#define MV64340_I2O_INBOUND_DOORBELL_REG_CPU1_SIDE  		    0x1CA0
+#define MV64340_I2O_INBOUND_INTERRUPT_CAUSE_REG_CPU1_SIDE  	    0x1CA4
+#define MV64340_I2O_INBOUND_INTERRUPT_MASK_REG_CPU1_SIDE	    0x1CA8
+#define MV64340_I2O_OUTBOUND_DOORBELL_REG_CPU1_SIDE 		    0x1CAC
+#define MV64340_I2O_OUTBOUND_INTERRUPT_CAUSE_REG_CPU1_SIDE          0x1CB0
+#define MV64340_I2O_OUTBOUND_INTERRUPT_MASK_REG_CPU1_SIDE           0x1CB4
+#define MV64340_I2O_INBOUND_QUEUE_PORT_VIRTUAL_REG_CPU1_SIDE        0x1CC0
+#define MV64340_I2O_OUTBOUND_QUEUE_PORT_VIRTUAL_REG_CPU1_SIDE       0x1CC4
+#define MV64340_I2O_QUEUE_CONTROL_REG_CPU1_SIDE 		    0x1CD0
+#define MV64340_I2O_QUEUE_BASE_ADDR_REG_CPU1_SIDE 		    0x1CD4
+#define MV64340_I2O_INBOUND_FREE_HEAD_POINTER_REG_CPU1_SIDE         0x1CE0
+#define MV64340_I2O_INBOUND_FREE_TAIL_POINTER_REG_CPU1_SIDE         0x1CE4
+#define MV64340_I2O_INBOUND_POST_HEAD_POINTER_REG_CPU1_SIDE         0x1CE8
+#define MV64340_I2O_INBOUND_POST_TAIL_POINTER_REG_CPU1_SIDE         0x1CEC
+#define MV64340_I2O_OUTBOUND_FREE_HEAD_POINTER_REG_CPU1_SIDE        0x1CF0
+#define MV64340_I2O_OUTBOUND_FREE_TAIL_POINTER_REG_CPU1_SIDE        0x1CF4
+#define MV64340_I2O_OUTBOUND_POST_HEAD_POINTER_REG_CPU1_SIDE        0x1C78
+#define MV64340_I2O_OUTBOUND_POST_TAIL_POINTER_REG_CPU1_SIDE        0x1C7C
+
+/****************************************/
+/*        Ethernet Unit Registers  		*/
+/****************************************/
+
+#define MV64340_ETH_PHY_ADDR_REG                                    0x2000
+#define MV64340_ETH_SMI_REG                                         0x2004
+#define MV64340_ETH_UNIT_DEFAULT_ADDR_REG                           0x2008
+#define MV64340_ETH_UNIT_DEFAULTID_REG                              0x200c
+#define MV64340_ETH_UNIT_INTERRUPT_CAUSE_REG                        0x2080
+#define MV64340_ETH_UNIT_INTERRUPT_MASK_REG                         0x2084
+#define MV64340_ETH_UNIT_INTERNAL_USE_REG                           0x24fc
+#define MV64340_ETH_UNIT_ERROR_ADDR_REG                             0x2094
+#define MV64340_ETH_BAR_0                                           0x2200
+#define MV64340_ETH_BAR_1                                           0x2208
+#define MV64340_ETH_BAR_2                                           0x2210
+#define MV64340_ETH_BAR_3                                           0x2218
+#define MV64340_ETH_BAR_4                                           0x2220
+#define MV64340_ETH_BAR_5                                           0x2228
+#define MV64340_ETH_SIZE_REG_0                                      0x2204
+#define MV64340_ETH_SIZE_REG_1                                      0x220c
+#define MV64340_ETH_SIZE_REG_2                                      0x2214
+#define MV64340_ETH_SIZE_REG_3                                      0x221c
+#define MV64340_ETH_SIZE_REG_4                                      0x2224
+#define MV64340_ETH_SIZE_REG_5                                      0x222c
+#define MV64340_ETH_HEADERS_RETARGET_BASE_REG                       0x2230
+#define MV64340_ETH_HEADERS_RETARGET_CONTROL_REG                    0x2234
+#define MV64340_ETH_HIGH_ADDR_REMAP_REG_0                           0x2280
+#define MV64340_ETH_HIGH_ADDR_REMAP_REG_1                           0x2284
+#define MV64340_ETH_HIGH_ADDR_REMAP_REG_2                           0x2288
+#define MV64340_ETH_HIGH_ADDR_REMAP_REG_3                           0x228c
+#define MV64340_ETH_BASE_ADDR_ENABLE_REG                            0x2290
+#define MV64340_ETH_ACCESS_PROTECTION_REG(port)                    (0x2294 + (port<<2))
+#define MV64340_ETH_MIB_COUNTERS_BASE(port)                        (0x3000 + (port<<7))
+#define MV64340_ETH_PORT_CONFIG_REG(port)                          (0x2400 + (port<<10))
+#define MV64340_ETH_PORT_CONFIG_EXTEND_REG(port)                   (0x2404 + (port<<10))
+#define MV64340_ETH_MII_SERIAL_PARAMETRS_REG(port)                 (0x2408 + (port<<10))
+#define MV64340_ETH_GMII_SERIAL_PARAMETRS_REG(port)                (0x240c + (port<<10))
+#define MV64340_ETH_VLAN_ETHERTYPE_REG(port)                       (0x2410 + (port<<10))
+#define MV64340_ETH_MAC_ADDR_LOW(port)                             (0x2414 + (port<<10))
+#define MV64340_ETH_MAC_ADDR_HIGH(port)                            (0x2418 + (port<<10))
+#define MV64340_ETH_SDMA_CONFIG_REG(port)                          (0x241c + (port<<10))
+#define MV64340_ETH_DSCP_0(port)                                   (0x2420 + (port<<10))
+#define MV64340_ETH_DSCP_1(port)                                   (0x2424 + (port<<10))
+#define MV64340_ETH_DSCP_2(port)                                   (0x2428 + (port<<10))
+#define MV64340_ETH_DSCP_3(port)                                   (0x242c + (port<<10))
+#define MV64340_ETH_DSCP_4(port)                                   (0x2430 + (port<<10))
+#define MV64340_ETH_DSCP_5(port)                                   (0x2434 + (port<<10))
+#define MV64340_ETH_DSCP_6(port)                                   (0x2438 + (port<<10))
+#define MV64340_ETH_PORT_SERIAL_CONTROL_REG(port)                  (0x243c + (port<<10))
+#define MV64340_ETH_VLAN_PRIORITY_TAG_TO_PRIORITY(port)            (0x2440 + (port<<10))
+#define MV64340_ETH_PORT_STATUS_REG(port)                          (0x2444 + (port<<10))
+#define MV64340_ETH_TRANSMIT_QUEUE_COMMAND_REG(port)               (0x2448 + (port<<10))
+#define MV64340_ETH_TX_QUEUE_FIXED_PRIORITY(port)                  (0x244c + (port<<10))
+#define MV64340_ETH_PORT_TX_TOKEN_BUCKET_RATE_CONFIG(port)         (0x2450 + (port<<10))
+#define MV64340_ETH_MAXIMUM_TRANSMIT_UNIT(port)                    (0x2458 + (port<<10))
+#define MV64340_ETH_PORT_MAXIMUM_TOKEN_BUCKET_SIZE(port)           (0x245c + (port<<10))
+#define MV64340_ETH_INTERRUPT_CAUSE_REG(port)                      (0x2460 + (port<<10))
+#define MV64340_ETH_INTERRUPT_CAUSE_EXTEND_REG(port)               (0x2464 + (port<<10))
+#define MV64340_ETH_INTERRUPT_MASK_REG(port)                       (0x2468 + (port<<10))
+#define MV64340_ETH_INTERRUPT_EXTEND_MASK_REG(port)                (0x246c + (port<<10))
+#define MV64340_ETH_RX_FIFO_URGENT_THRESHOLD_REG(port)             (0x2470 + (port<<10))
+#define MV64340_ETH_TX_FIFO_URGENT_THRESHOLD_REG(port)             (0x2474 + (port<<10))
+#define MV64340_ETH_RX_MINIMAL_FRAME_SIZE_REG(port)                (0x247c + (port<<10))
+#define MV64340_ETH_RX_DISCARDED_FRAMES_COUNTER(port)              (0x2484 + (port<<10)
+#define MV64340_ETH_PORT_DEBUG_0_REG(port)                         (0x248c + (port<<10))
+#define MV64340_ETH_PORT_DEBUG_1_REG(port)                         (0x2490 + (port<<10))
+#define MV64340_ETH_PORT_INTERNAL_ADDR_ERROR_REG(port)             (0x2494 + (port<<10))
+#define MV64340_ETH_INTERNAL_USE_REG(port)                         (0x24fc + (port<<10))
+#define MV64340_ETH_RECEIVE_QUEUE_COMMAND_REG(port)                (0x2680 + (port<<10))
+#define MV64340_ETH_CURRENT_SERVED_TX_DESC_PTR(port)               (0x2684 + (port<<10))      
+#define MV64340_ETH_RX_CURRENT_QUEUE_DESC_PTR_0(port)              (0x260c + (port<<10))     
+#define MV64340_ETH_RX_CURRENT_QUEUE_DESC_PTR_1(port)              (0x261c + (port<<10))     
+#define MV64340_ETH_RX_CURRENT_QUEUE_DESC_PTR_2(port)              (0x262c + (port<<10))     
+#define MV64340_ETH_RX_CURRENT_QUEUE_DESC_PTR_3(port)              (0x263c + (port<<10))     
+#define MV64340_ETH_RX_CURRENT_QUEUE_DESC_PTR_4(port)              (0x264c + (port<<10))     
+#define MV64340_ETH_RX_CURRENT_QUEUE_DESC_PTR_5(port)              (0x265c + (port<<10))     
+#define MV64340_ETH_RX_CURRENT_QUEUE_DESC_PTR_6(port)              (0x266c + (port<<10))     
+#define MV64340_ETH_RX_CURRENT_QUEUE_DESC_PTR_7(port)              (0x267c + (port<<10))     
+#define MV64340_ETH_TX_CURRENT_QUEUE_DESC_PTR_0(port)              (0x26c0 + (port<<10))     
+#define MV64340_ETH_TX_CURRENT_QUEUE_DESC_PTR_1(port)              (0x26c4 + (port<<10))     
+#define MV64340_ETH_TX_CURRENT_QUEUE_DESC_PTR_2(port)              (0x26c8 + (port<<10))     
+#define MV64340_ETH_TX_CURRENT_QUEUE_DESC_PTR_3(port)              (0x26cc + (port<<10))     
+#define MV64340_ETH_TX_CURRENT_QUEUE_DESC_PTR_4(port)              (0x26d0 + (port<<10))     
+#define MV64340_ETH_TX_CURRENT_QUEUE_DESC_PTR_5(port)              (0x26d4 + (port<<10))     
+#define MV64340_ETH_TX_CURRENT_QUEUE_DESC_PTR_6(port)              (0x26d8 + (port<<10))     
+#define MV64340_ETH_TX_CURRENT_QUEUE_DESC_PTR_7(port)              (0x26dc + (port<<10))     
+#define MV64340_ETH_TX_QUEUE_0_TOKEN_BUCKET_COUNT(port)            (0x2700 + (port<<10))
+#define MV64340_ETH_TX_QUEUE_1_TOKEN_BUCKET_COUNT(port)            (0x2710 + (port<<10))
+#define MV64340_ETH_TX_QUEUE_2_TOKEN_BUCKET_COUNT(port)            (0x2720 + (port<<10))
+#define MV64340_ETH_TX_QUEUE_3_TOKEN_BUCKET_COUNT(port)            (0x2730 + (port<<10))
+#define MV64340_ETH_TX_QUEUE_4_TOKEN_BUCKET_COUNT(port)            (0x2740 + (port<<10))
+#define MV64340_ETH_TX_QUEUE_5_TOKEN_BUCKET_COUNT(port)            (0x2750 + (port<<10))
+#define MV64340_ETH_TX_QUEUE_6_TOKEN_BUCKET_COUNT(port)            (0x2760 + (port<<10))
+#define MV64340_ETH_TX_QUEUE_7_TOKEN_BUCKET_COUNT(port)            (0x2770 + (port<<10))
+#define MV64340_ETH_TX_QUEUE_0_TOKEN_BUCKET_CONFIG(port)           (0x2704 + (port<<10))
+#define MV64340_ETH_TX_QUEUE_1_TOKEN_BUCKET_CONFIG(port)           (0x2714 + (port<<10))
+#define MV64340_ETH_TX_QUEUE_2_TOKEN_BUCKET_CONFIG(port)           (0x2724 + (port<<10))
+#define MV64340_ETH_TX_QUEUE_3_TOKEN_BUCKET_CONFIG(port)           (0x2734 + (port<<10))
+#define MV64340_ETH_TX_QUEUE_4_TOKEN_BUCKET_CONFIG(port)           (0x2744 + (port<<10))
+#define MV64340_ETH_TX_QUEUE_5_TOKEN_BUCKET_CONFIG(port)           (0x2754 + (port<<10))
+#define MV64340_ETH_TX_QUEUE_6_TOKEN_BUCKET_CONFIG(port)           (0x2764 + (port<<10))
+#define MV64340_ETH_TX_QUEUE_7_TOKEN_BUCKET_CONFIG(port)           (0x2774 + (port<<10))
+#define MV64340_ETH_TX_QUEUE_0_ARBITER_CONFIG(port)                (0x2708 + (port<<10))
+#define MV64340_ETH_TX_QUEUE_1_ARBITER_CONFIG(port)                (0x2718 + (port<<10))
+#define MV64340_ETH_TX_QUEUE_2_ARBITER_CONFIG(port)                (0x2728 + (port<<10))
+#define MV64340_ETH_TX_QUEUE_3_ARBITER_CONFIG(port)                (0x2738 + (port<<10))
+#define MV64340_ETH_TX_QUEUE_4_ARBITER_CONFIG(port)                (0x2748 + (port<<10))
+#define MV64340_ETH_TX_QUEUE_5_ARBITER_CONFIG(port)                (0x2758 + (port<<10))
+#define MV64340_ETH_TX_QUEUE_6_ARBITER_CONFIG(port)                (0x2768 + (port<<10))
+#define MV64340_ETH_TX_QUEUE_7_ARBITER_CONFIG(port)                (0x2778 + (port<<10))
+#define MV64340_ETH_PORT_TX_TOKEN_BUCKET_COUNT(port)               (0x2780 + (port<<10))
+#define MV64340_ETH_DA_FILTER_SPECIAL_MULTICAST_TABLE_BASE(port)   (0x3400 + (port<<10))
+#define MV64340_ETH_DA_FILTER_OTHER_MULTICAST_TABLE_BASE(port)     (0x3500 + (port<<10))
+#define MV64340_ETH_DA_FILTER_UNICAST_TABLE_BASE(port)             (0x3600 + (port<<10))
+
+/*******************************************/
+/*          CUNIT  Registers               */
+/*******************************************/
+
+         /* Address Decoding Register Map */
+           
+#define MV64340_CUNIT_BASE_ADDR_REG0                                0xf200
+#define MV64340_CUNIT_BASE_ADDR_REG1                                0xf208
+#define MV64340_CUNIT_BASE_ADDR_REG2                                0xf210
+#define MV64340_CUNIT_BASE_ADDR_REG3                                0xf218
+#define MV64340_CUNIT_SIZE0                                         0xf204
+#define MV64340_CUNIT_SIZE1                                         0xf20c
+#define MV64340_CUNIT_SIZE2                                         0xf214
+#define MV64340_CUNIT_SIZE3                                         0xf21c
+#define MV64340_CUNIT_HIGH_ADDR_REMAP_REG0                          0xf240
+#define MV64340_CUNIT_HIGH_ADDR_REMAP_REG1                          0xf244
+#define MV64340_CUNIT_BASE_ADDR_ENABLE_REG                          0xf250
+#define MV64340_MPSC0_ACCESS_PROTECTION_REG                         0xf254
+#define MV64340_MPSC1_ACCESS_PROTECTION_REG                         0xf258
+#define MV64340_CUNIT_INTERNAL_SPACE_BASE_ADDR_REG                  0xf25C
+
+        /*  Error Report Registers  */
+
+#define MV64340_CUNIT_INTERRUPT_CAUSE_REG                           0xf310
+#define MV64340_CUNIT_INTERRUPT_MASK_REG                            0xf314
+#define MV64340_CUNIT_ERROR_ADDR                                    0xf318
+
+        /*  Cunit Control Registers */
+
+#define MV64340_CUNIT_ARBITER_CONTROL_REG                           0xf300
+#define MV64340_CUNIT_CONFIG_REG                                    0xb40c
+#define MV64340_CUNIT_CRROSBAR_TIMEOUT_REG                          0xf304
+
+        /*  Cunit Debug Registers   */
+
+#define MV64340_CUNIT_DEBUG_LOW                                     0xf340
+#define MV64340_CUNIT_DEBUG_HIGH                                    0xf344
+#define MV64340_CUNIT_MMASK                                         0xf380
+
+        /*  MPSCs Clocks Routing Registers  */
+
+#define MV64340_MPSC_ROUTING_REG                                    0xb400
+#define MV64340_MPSC_RX_CLOCK_ROUTING_REG                           0xb404
+#define MV64340_MPSC_TX_CLOCK_ROUTING_REG                           0xb408
+
+        /*  MPSCs Interrupts Registers    */
+
+#define MV64340_MPSC_CAUSE_REG(port)                               (0xb804 + (port<<3))
+#define MV64340_MPSC_MASK_REG(port)                                (0xb884 + (port<<3))
+ 
+#define MV64340_MPSC_MAIN_CONFIG_LOW(port)                         (0x8000 + (port<<12))
+#define MV64340_MPSC_MAIN_CONFIG_HIGH(port)                        (0x8004 + (port<<12))    
+#define MV64340_MPSC_PROTOCOL_CONFIG(port)                         (0x8008 + (port<<12))    
+#define MV64340_MPSC_CHANNEL_REG1(port)                            (0x800c + (port<<12))    
+#define MV64340_MPSC_CHANNEL_REG2(port)                            (0x8010 + (port<<12))    
+#define MV64340_MPSC_CHANNEL_REG3(port)                            (0x8014 + (port<<12))    
+#define MV64340_MPSC_CHANNEL_REG4(port)                            (0x8018 + (port<<12))    
+#define MV64340_MPSC_CHANNEL_REG5(port)                            (0x801c + (port<<12))    
+#define MV64340_MPSC_CHANNEL_REG6(port)                            (0x8020 + (port<<12))    
+#define MV64340_MPSC_CHANNEL_REG7(port)                            (0x8024 + (port<<12))    
+#define MV64340_MPSC_CHANNEL_REG8(port)                            (0x8028 + (port<<12))    
+#define MV64340_MPSC_CHANNEL_REG9(port)                            (0x802c + (port<<12))    
+#define MV64340_MPSC_CHANNEL_REG10(port)                           (0x8030 + (port<<12))    
+        
+        /*  MPSC0 Registers      */
+
+
+/***************************************/
+/*          SDMA Registers             */
+/***************************************/
+
+#define MV64340_SDMA_CONFIG_REG(channel)                        (0x4000 + (channel<<13))        
+#define MV64340_SDMA_COMMAND_REG(channel)                       (0x4008 + (channel<<13))        
+#define MV64340_SDMA_CURRENT_RX_DESCRIPTOR_POINTER(channel)     (0x4810 + (channel<<13))        
+#define MV64340_SDMA_CURRENT_TX_DESCRIPTOR_POINTER(channel)     (0x4c10 + (channel<<13))        
+#define MV64340_SDMA_FIRST_TX_DESCRIPTOR_POINTER(channel)       (0x4c14 + (channel<<13)) 
+
+#define MV64340_SDMA_CAUSE_REG                                      0xb800
+#define MV64340_SDMA_MASK_REG                                       0xb880
+         
+/* BRG Interrupts */
+
+#define MV64340_BRG_CONFIG_REG(brg)                              (0xb200 + (brg<<3))
+#define MV64340_BRG_BAUDE_TUNING_REG(brg)                        (0xb208 + (brg<<3))
+#define MV64340_BRG_CAUSE_REG                                       0xb834
+#define MV64340_BRG_MASK_REG                                        0xb8b4
+
+/****************************************/
+/* DMA Channel Control			*/
+/****************************************/
+
+#define MV64340_DMA_CHANNEL0_CONTROL 				    0x840
+#define MV64340_DMA_CHANNEL0_CONTROL_HIGH			    0x880
+#define MV64340_DMA_CHANNEL1_CONTROL 				    0x844
+#define MV64340_DMA_CHANNEL1_CONTROL_HIGH			    0x884
+#define MV64340_DMA_CHANNEL2_CONTROL 				    0x848
+#define MV64340_DMA_CHANNEL2_CONTROL_HIGH			    0x888
+#define MV64340_DMA_CHANNEL3_CONTROL 				    0x84C
+#define MV64340_DMA_CHANNEL3_CONTROL_HIGH			    0x88C
+
+
+/****************************************/
+/*           IDMA Registers             */
+/****************************************/
+
+#define MV64340_DMA_CHANNEL0_BYTE_COUNT                             0x800
+#define MV64340_DMA_CHANNEL1_BYTE_COUNT                             0x804
+#define MV64340_DMA_CHANNEL2_BYTE_COUNT                             0x808
+#define MV64340_DMA_CHANNEL3_BYTE_COUNT                             0x80C
+#define MV64340_DMA_CHANNEL0_SOURCE_ADDR                            0x810
+#define MV64340_DMA_CHANNEL1_SOURCE_ADDR                            0x814
+#define MV64340_DMA_CHANNEL2_SOURCE_ADDR                            0x818
+#define MV64340_DMA_CHANNEL3_SOURCE_ADDR                            0x81c
+#define MV64340_DMA_CHANNEL0_DESTINATION_ADDR                       0x820
+#define MV64340_DMA_CHANNEL1_DESTINATION_ADDR                       0x824
+#define MV64340_DMA_CHANNEL2_DESTINATION_ADDR                       0x828
+#define MV64340_DMA_CHANNEL3_DESTINATION_ADDR                       0x82C
+#define MV64340_DMA_CHANNEL0_NEXT_DESCRIPTOR_POINTER                0x830
+#define MV64340_DMA_CHANNEL1_NEXT_DESCRIPTOR_POINTER                0x834
+#define MV64340_DMA_CHANNEL2_NEXT_DESCRIPTOR_POINTER                0x838
+#define MV64340_DMA_CHANNEL3_NEXT_DESCRIPTOR_POINTER                0x83C
+#define MV64340_DMA_CHANNEL0_CURRENT_DESCRIPTOR_POINTER             0x870
+#define MV64340_DMA_CHANNEL1_CURRENT_DESCRIPTOR_POINTER             0x874
+#define MV64340_DMA_CHANNEL2_CURRENT_DESCRIPTOR_POINTER             0x878
+#define MV64340_DMA_CHANNEL3_CURRENT_DESCRIPTOR_POINTER             0x87C
+
+ /*  IDMA Address Decoding Base Address Registers  */
+ 
+#define MV64340_DMA_BASE_ADDR_REG0                                  0xa00
+#define MV64340_DMA_BASE_ADDR_REG1                                  0xa08
+#define MV64340_DMA_BASE_ADDR_REG2                                  0xa10
+#define MV64340_DMA_BASE_ADDR_REG3                                  0xa18
+#define MV64340_DMA_BASE_ADDR_REG4                                  0xa20
+#define MV64340_DMA_BASE_ADDR_REG5                                  0xa28
+#define MV64340_DMA_BASE_ADDR_REG6                                  0xa30
+#define MV64340_DMA_BASE_ADDR_REG7                                  0xa38
+ 
+ /*  IDMA Address Decoding Size Address Register   */
+ 
+#define MV64340_DMA_SIZE_REG0                                       0xa04
+#define MV64340_DMA_SIZE_REG1                                       0xa0c
+#define MV64340_DMA_SIZE_REG2                                       0xa14
+#define MV64340_DMA_SIZE_REG3                                       0xa1c
+#define MV64340_DMA_SIZE_REG4                                       0xa24
+#define MV64340_DMA_SIZE_REG5                                       0xa2c
+#define MV64340_DMA_SIZE_REG6                                       0xa34
+#define MV64340_DMA_SIZE_REG7                                       0xa3C
+
+ /* IDMA Address Decoding High Address Remap and Access 
+                  Protection Registers                    */
+                  
+#define MV64340_DMA_HIGH_ADDR_REMAP_REG0                            0xa60
+#define MV64340_DMA_HIGH_ADDR_REMAP_REG1                            0xa64
+#define MV64340_DMA_HIGH_ADDR_REMAP_REG2                            0xa68
+#define MV64340_DMA_HIGH_ADDR_REMAP_REG3                            0xa6C
+#define MV64340_DMA_BASE_ADDR_ENABLE_REG                            0xa80
+#define MV64340_DMA_CHANNEL0_ACCESS_PROTECTION_REG                  0xa70
+#define MV64340_DMA_CHANNEL1_ACCESS_PROTECTION_REG                  0xa74
+#define MV64340_DMA_CHANNEL2_ACCESS_PROTECTION_REG                  0xa78
+#define MV64340_DMA_CHANNEL3_ACCESS_PROTECTION_REG                  0xa7c
+#define MV64340_DMA_ARBITER_CONTROL                                 0x860
+#define MV64340_DMA_CROSS_BAR_TIMEOUT                               0x8d0
+
+ /*  IDMA Headers Retarget Registers   */
+
+#define MV64340_DMA_HEADERS_RETARGET_CONTROL                        0xa84
+#define MV64340_DMA_HEADERS_RETARGET_BASE                           0xa88
+
+ /*  IDMA Interrupt Register  */
+
+#define MV64340_DMA_INTERRUPT_CAUSE_REG                             0x8c0
+#define MV64340_DMA_INTERRUPT_CAUSE_MASK                            0x8c4
+#define MV64340_DMA_ERROR_ADDR                                      0x8c8
+#define MV64340_DMA_ERROR_SELECT                                    0x8cc
+
+ /*  IDMA Debug Register ( for internal use )    */
+
+#define MV64340_DMA_DEBUG_LOW                                       0x8e0
+#define MV64340_DMA_DEBUG_HIGH                                      0x8e4
+#define MV64340_DMA_SPARE                                           0xA8C
+
+/****************************************/
+/* Timer_Counter 			*/
+/****************************************/
+
+#define MV64340_TIMER_COUNTER0					    0x850
+#define MV64340_TIMER_COUNTER1					    0x854
+#define MV64340_TIMER_COUNTER2					    0x858
+#define MV64340_TIMER_COUNTER3					    0x85C
+#define MV64340_TIMER_COUNTER_0_3_CONTROL			    0x864
+#define MV64340_TIMER_COUNTER_0_3_INTERRUPT_CAUSE		    0x868
+#define MV64340_TIMER_COUNTER_0_3_INTERRUPT_MASK      		    0x86c
+
+/****************************************/
+/*         Watchdog registers  	        */
+/****************************************/
+
+#define MV64340_WATCHDOG_CONFIG_REG                                 0xb410
+#define MV64340_WATCHDOG_VALUE_REG                                  0xb414
+
+/****************************************/
+/* I2C Registers                        */
+/****************************************/
+
+#define MV64340_I2C_SLAVE_ADDR                                      0xc000
+#define MV64340_I2C_EXTENDED_SLAVE_ADDR                             0xc010
+#define MV64340_I2C_DATA                                            0xc004
+#define MV64340_I2C_CONTROL                                         0xc008
+#define MV64340_I2C_STATUS_BAUDE_RATE                               0xc00C
+#define MV64340_I2C_SOFT_RESET                                      0xc01c
+
+/****************************************/
+/* GPP Interface Registers              */
+/****************************************/
+
+#define MV64340_GPP_IO_CONTROL                                      0xf100
+#define MV64340_GPP_LEVEL_CONTROL                                   0xf110
+#define MV64340_GPP_VALUE                                           0xf104
+#define MV64340_GPP_INTERRUPT_CAUSE                                 0xf108
+#define MV64340_GPP_INTERRUPT_MASK0                                 0xf10c
+#define MV64340_GPP_INTERRUPT_MASK1                                 0xf114
+#define MV64340_GPP_VALUE_SET                                       0xf118
+#define MV64340_GPP_VALUE_CLEAR                                     0xf11c
+
+/****************************************/
+/* Interrupt Controller Registers       */
+/****************************************/
+
+/****************************************/
+/* Interrupts	  			*/
+/****************************************/
+
+#define MV64340_MAIN_INTERRUPT_CAUSE_LOW                            0x004
+#define MV64340_MAIN_INTERRUPT_CAUSE_HIGH                           0x00c
+#define MV64340_CPU_INTERRUPT0_MASK_LOW                             0x014
+#define MV64340_CPU_INTERRUPT0_MASK_HIGH                            0x01c
+#define MV64340_CPU_INTERRUPT0_SELECT_CAUSE                         0x024
+#define MV64340_CPU_INTERRUPT1_MASK_LOW                             0x034
+#define MV64340_CPU_INTERRUPT1_MASK_HIGH                            0x03c
+#define MV64340_CPU_INTERRUPT1_SELECT_CAUSE                         0x044
+#define MV64340_INTERRUPT0_MASK_0_LOW                               0x054
+#define MV64340_INTERRUPT0_MASK_0_HIGH                              0x05c
+#define MV64340_INTERRUPT0_SELECT_CAUSE                             0x064
+#define MV64340_INTERRUPT1_MASK_0_LOW                               0x074
+#define MV64340_INTERRUPT1_MASK_0_HIGH                              0x07c
+#define MV64340_INTERRUPT1_SELECT_CAUSE                             0x084
+
+/****************************************/
+/*      MPP Interface Registers         */
+/****************************************/
+
+#define MV64340_MPP_CONTROL0                                        0xf000
+#define MV64340_MPP_CONTROL1                                        0xf004
+#define MV64340_MPP_CONTROL2                                        0xf008
+#define MV64340_MPP_CONTROL3                                        0xf00c
+
+/****************************************/
+/*    Serial Initialization registers   */
+/****************************************/
+
+#define MV64340_SERIAL_INIT_LAST_DATA                               0xf324
+#define MV64340_SERIAL_INIT_CONTROL                                 0xf328
+#define MV64340_SERIAL_INIT_STATUS                                  0xf32c
+
+extern void mv64340_irq_init(unsigned int base);
+
+#endif /* __ASM_MV64340_H */
diff -Nru a/include/linux/ncp.h b/include/linux/ncp.h
--- a/include/linux/ncp.h	2004-10-18 14:55:53 -07:00
+++ b/include/linux/ncp.h	2004-10-18 14:55:53 -07:00
@@ -57,9 +57,9 @@
 	char volume_name[NCP_VOLNAME_LEN + 1];
 };
 
-#define AR_READ      (ntohs(0x0100))
-#define AR_WRITE     (ntohs(0x0200))
-#define AR_EXCLUSIVE (ntohs(0x2000))
+#define AR_READ      (cpu_to_le16(1))
+#define AR_WRITE     (cpu_to_le16(2))
+#define AR_EXCLUSIVE (cpu_to_le16(0x20))
 
 #define NCP_FILE_ID_LEN 6
 
@@ -71,20 +71,20 @@
 #define NW_NS_OS2     4
 
 /*  Defines for ReturnInformationMask */
-#define RIM_NAME	      (ntohl(0x01000000L))
-#define RIM_SPACE_ALLOCATED   (ntohl(0x02000000L))
-#define RIM_ATTRIBUTES	      (ntohl(0x04000000L))
-#define RIM_DATA_SIZE	      (ntohl(0x08000000L))
-#define RIM_TOTAL_SIZE	      (ntohl(0x10000000L))
-#define RIM_EXT_ATTR_INFO     (ntohl(0x20000000L))
-#define RIM_ARCHIVE	      (ntohl(0x40000000L))
-#define RIM_MODIFY	      (ntohl(0x80000000L))
-#define RIM_CREATION	      (ntohl(0x00010000L))
-#define RIM_OWNING_NAMESPACE  (ntohl(0x00020000L))
-#define RIM_DIRECTORY	      (ntohl(0x00040000L))
-#define RIM_RIGHTS	      (ntohl(0x00080000L))
-#define RIM_ALL 	      (ntohl(0xFF0F0000L))
-#define RIM_COMPRESSED_INFO   (ntohl(0x00000080L))
+#define RIM_NAME	      (cpu_to_le32(1))
+#define RIM_SPACE_ALLOCATED   (cpu_to_le32(2))
+#define RIM_ATTRIBUTES	      (cpu_to_le32(4))
+#define RIM_DATA_SIZE	      (cpu_to_le32(8))
+#define RIM_TOTAL_SIZE	      (cpu_to_le32(0x10))
+#define RIM_EXT_ATTR_INFO     (cpu_to_le32(0x20))
+#define RIM_ARCHIVE	      (cpu_to_le32(0x40))
+#define RIM_MODIFY	      (cpu_to_le32(0x80))
+#define RIM_CREATION	      (cpu_to_le32(0x100))
+#define RIM_OWNING_NAMESPACE  (cpu_to_le32(0x200))
+#define RIM_DIRECTORY	      (cpu_to_le32(0x400))
+#define RIM_RIGHTS	      (cpu_to_le32(0x800))
+#define RIM_ALL 	      (cpu_to_le32(0xFFF))
+#define RIM_COMPRESSED_INFO   (cpu_to_le32(0x80000000))
 
 /* Defines for NSInfoBitMask */
 #define NSIBM_NFS_NAME		0x0001
@@ -129,24 +129,24 @@
 
 struct nw_info_struct {
 	__u32 spaceAlloc __attribute__((packed));
-	__u32 attributes __attribute__((packed));
+	__le32 attributes __attribute__((packed));
 	__u16 flags __attribute__((packed));
-	__u32 dataStreamSize __attribute__((packed));
-	__u32 totalStreamSize __attribute__((packed));
+	__le32 dataStreamSize __attribute__((packed));
+	__le32 totalStreamSize __attribute__((packed));
 	__u16 numberOfStreams __attribute__((packed));
-	__u16 creationTime __attribute__((packed));
-	__u16 creationDate __attribute__((packed));
+	__le16 creationTime __attribute__((packed));
+	__le16 creationDate __attribute__((packed));
 	__u32 creatorID __attribute__((packed));
-	__u16 modifyTime __attribute__((packed));
-	__u16 modifyDate __attribute__((packed));
+	__le16 modifyTime __attribute__((packed));
+	__le16 modifyDate __attribute__((packed));
 	__u32 modifierID __attribute__((packed));
-	__u16 lastAccessDate __attribute__((packed));
+	__le16 lastAccessDate __attribute__((packed));
 	__u16 archiveTime __attribute__((packed));
 	__u16 archiveDate __attribute__((packed));
 	__u32 archiverID __attribute__((packed));
 	__u16 inheritedRightsMask __attribute__((packed));
-	__u32 dirEntNum __attribute__((packed));
-	__u32 DosDirNum __attribute__((packed));
+	__le32 dirEntNum __attribute__((packed));
+	__le32 DosDirNum __attribute__((packed));
 	__u32 volNumber __attribute__((packed));
 	__u32 EADataSize __attribute__((packed));
 	__u32 EAKeyCount __attribute__((packed));
@@ -161,32 +161,32 @@
 };
 
 /* modify mask - use with MODIFY_DOS_INFO structure */
-#define DM_ATTRIBUTES		  (ntohl(0x02000000L))
-#define DM_CREATE_DATE		  (ntohl(0x04000000L))
-#define DM_CREATE_TIME		  (ntohl(0x08000000L))
-#define DM_CREATOR_ID		  (ntohl(0x10000000L))
-#define DM_ARCHIVE_DATE 	  (ntohl(0x20000000L))
-#define DM_ARCHIVE_TIME 	  (ntohl(0x40000000L))
-#define DM_ARCHIVER_ID		  (ntohl(0x80000000L))
-#define DM_MODIFY_DATE		  (ntohl(0x00010000L))
-#define DM_MODIFY_TIME		  (ntohl(0x00020000L))
-#define DM_MODIFIER_ID		  (ntohl(0x00040000L))
-#define DM_LAST_ACCESS_DATE	  (ntohl(0x00080000L))
-#define DM_INHERITED_RIGHTS_MASK  (ntohl(0x00100000L))
-#define DM_MAXIMUM_SPACE	  (ntohl(0x00200000L))
+#define DM_ATTRIBUTES		  (cpu_to_le32(0x02))
+#define DM_CREATE_DATE		  (cpu_to_le32(0x04))
+#define DM_CREATE_TIME		  (cpu_to_le32(0x08))
+#define DM_CREATOR_ID		  (cpu_to_le32(0x10))
+#define DM_ARCHIVE_DATE 	  (cpu_to_le32(0x20))
+#define DM_ARCHIVE_TIME 	  (cpu_to_le32(0x40))
+#define DM_ARCHIVER_ID		  (cpu_to_le32(0x80))
+#define DM_MODIFY_DATE		  (cpu_to_le32(0x0100))
+#define DM_MODIFY_TIME		  (cpu_to_le32(0x0200))
+#define DM_MODIFIER_ID		  (cpu_to_le32(0x0400))
+#define DM_LAST_ACCESS_DATE	  (cpu_to_le32(0x0800))
+#define DM_INHERITED_RIGHTS_MASK  (cpu_to_le32(0x1000))
+#define DM_MAXIMUM_SPACE	  (cpu_to_le32(0x2000))
 
 struct nw_modify_dos_info {
-	__u32 attributes __attribute__((packed));
-	__u16 creationDate __attribute__((packed));
-	__u16 creationTime __attribute__((packed));
+	__le32 attributes __attribute__((packed));
+	__le16 creationDate __attribute__((packed));
+	__le16 creationTime __attribute__((packed));
 	__u32 creatorID __attribute__((packed));
-	__u16 modifyDate __attribute__((packed));
-	__u16 modifyTime __attribute__((packed));
+	__le16 modifyDate __attribute__((packed));
+	__le16 modifyTime __attribute__((packed));
 	__u32 modifierID __attribute__((packed));
 	__u16 archiveDate __attribute__((packed));
 	__u16 archiveTime __attribute__((packed));
 	__u32 archiverID __attribute__((packed));
-	__u16 lastAccessDate __attribute__((packed));
+	__le16 lastAccessDate __attribute__((packed));
 	__u16 inheritanceGrantMask __attribute__((packed));
 	__u16 inheritanceRevokeMask __attribute__((packed));
 	__u32 maximumSpace __attribute__((packed));
diff -Nru a/include/linux/ncp_fs.h b/include/linux/ncp_fs.h
--- a/include/linux/ncp_fs.h	2004-10-18 14:56:17 -07:00
+++ b/include/linux/ncp_fs.h	2004-10-18 14:56:17 -07:00
@@ -36,7 +36,7 @@
 				   used for read/write requests! */
 
 	int volume_number;
-	__u32 directory_id;
+	__le32 directory_id;
 };
 
 struct ncp_fs_info_v2 {
@@ -46,7 +46,7 @@
 	unsigned int buffer_size;
 
 	unsigned int volume_number;
-	__u32 directory_id;
+	__le32 directory_id;
 
 	__u32 dummy1;
 	__u32 dummy2;
@@ -78,7 +78,7 @@
 {
 	int		volNumber;
 	int		namespace;
-	__u32		dirEntNum;
+	__le32		dirEntNum;
 };
 
 struct ncp_objectname_ioctl
@@ -239,8 +239,8 @@
 extern struct inode_operations ncp_dir_inode_operations;
 extern struct file_operations ncp_dir_operations;
 int ncp_conn_logged_in(struct super_block *);
-int ncp_date_dos2unix(__u16 time, __u16 date);
-void ncp_date_unix2dos(int unix_date, __u16 * time, __u16 * date);
+int ncp_date_dos2unix(__le16 time, __le16 date);
+void ncp_date_unix2dos(int unix_date, __le16 * time, __le16 * date);
 
 /* linux/fs/ncpfs/ioctl.c */
 int ncp_ioctl(struct inode *, struct file *, unsigned int, unsigned long);
diff -Nru a/include/linux/ncp_fs_i.h b/include/linux/ncp_fs_i.h
--- a/include/linux/ncp_fs_i.h	2004-10-18 14:56:49 -07:00
+++ b/include/linux/ncp_fs_i.h	2004-10-18 14:56:49 -07:00
@@ -15,10 +15,10 @@
  * all the information we need to work with an inode after creation.
  */
 struct ncp_inode_info {
-	__u32	dirEntNum;
-	__u32	DosDirNum;
-	__u32	volNumber;
-	__u32	nwattr;
+	__le32	dirEntNum;
+	__le32	DosDirNum;
+	__u8	volNumber;
+	__le32	nwattr;
 	struct semaphore open_sem;
 	atomic_t	opened;
 	int	access;
diff -Nru a/include/linux/ncp_no.h b/include/linux/ncp_no.h
--- a/include/linux/ncp_no.h	2004-10-18 14:55:54 -07:00
+++ b/include/linux/ncp_no.h	2004-10-18 14:55:54 -07:00
@@ -2,18 +2,18 @@
 #define _NCP_NO
 
 /* these define the attribute byte as seen by NCP */
-#define aRONLY			(ntohl(0x01000000))
-#define aHIDDEN			(__constant_ntohl(0x02000000))
-#define aSYSTEM			(__constant_ntohl(0x04000000))
-#define aEXECUTE		(ntohl(0x08000000))
-#define aDIR			(ntohl(0x10000000))
-#define aARCH			(ntohl(0x20000000))
-#define aSHARED			(ntohl(0x80000000))
-#define aDONTSUBALLOCATE	(ntohl(1L<<(11+8)))
-#define aTRANSACTIONAL		(ntohl(1L<<(12+8)))
-#define aPURGE			(ntohl(1L<<(16-8)))
-#define aRENAMEINHIBIT		(ntohl(1L<<(17-8)))
-#define aDELETEINHIBIT		(ntohl(1L<<(18-8)))
-#define aDONTCOMPRESS		(nothl(1L<<(27-24)))
+#define aRONLY			(__constant_cpu_to_le32(1))
+#define aHIDDEN			(__constant_cpu_to_le32(2))
+#define aSYSTEM			(__constant_cpu_to_le32(4))
+#define aEXECUTE		(__constant_cpu_to_le32(8))
+#define aDIR			(__constant_cpu_to_le32(0x10))
+#define aARCH			(__constant_cpu_to_le32(0x20))
+#define aSHARED			(__constant_cpu_to_le32(0x80))
+#define aDONTSUBALLOCATE	(__constant_cpu_to_le32(1L<<11))
+#define aTRANSACTIONAL		(__constant_cpu_to_le32(1L<<12))
+#define aPURGE			(__constant_cpu_to_le32(1L<<16))
+#define aRENAMEINHIBIT		(__constant_cpu_to_le32(1L<<17))
+#define aDELETEINHIBIT		(__constant_cpu_to_le32(1L<<18))
+#define aDONTCOMPRESS		(__constant_cpu_to_le32(1L<<27))
 
 #endif /* _NCP_NO */
diff -Nru a/include/linux/net.h b/include/linux/net.h
--- a/include/linux/net.h	2004-10-18 14:56:28 -07:00
+++ b/include/linux/net.h	2004-10-18 14:56:28 -07:00
@@ -21,6 +21,7 @@
 #include <linux/config.h>
 #include <linux/wait.h>
 #include <linux/stringify.h>
+#include <asm/socket.h>
 
 struct poll_table_struct;
 struct inode;
@@ -61,6 +62,34 @@
 #define SOCK_ASYNC_WAITDATA	1
 #define SOCK_NOSPACE		2
 
+#ifndef ARCH_HAS_SOCKET_TYPES
+/** sock_type - Socket types
+ * 
+ * When adding some new socket type please
+ * grep ARCH_HAS_SOCKET_TYPE include/asm-* /socket.h, at least MIPS
+ * overrides this enum for binary compat reasons.
+ * 
+ * @SOCK_STREAM - stream (connection) socket
+ * @SOCK_DGRAM - datagram (conn.less) socket
+ * @SOCK_RAW - raw socket
+ * @SOCK_RDM - reliably-delivered message
+ * @SOCK_SEQPACKET - sequential packet socket 
+ * @SOCK_PACKET - linux specific way of getting packets at the dev level.
+ *		  For writing rarp and other similar things on the user level.
+ */
+enum sock_type {
+	SOCK_STREAM	= 1,
+	SOCK_DGRAM	= 2,
+	SOCK_RAW	= 3,
+	SOCK_RDM	= 4,
+	SOCK_SEQPACKET	= 5,
+	SOCK_PACKET	= 10,
+};
+
+#define SOCK_MAX (SOCK_PACKET + 1)
+
+#endif /* ARCH_HAS_SOCKET_TYPES */
+
 /**
  *  struct socket - general BSD socket
  *  @state - socket state (%SS_CONNECTED, etc)
@@ -169,6 +198,7 @@
 extern int	     net_ratelimit(void);
 extern unsigned long net_random(void);
 extern void	     net_srandom(unsigned long);
+extern void	     net_random_init(void);
 
 extern int   	     kernel_sendmsg(struct socket *sock, struct msghdr *msg,
 				    struct kvec *vec, size_t num, size_t len);
diff -Nru a/include/linux/netdevice.h b/include/linux/netdevice.h
--- a/include/linux/netdevice.h	2004-10-18 14:57:04 -07:00
+++ b/include/linux/netdevice.h	2004-10-18 14:57:04 -07:00
@@ -73,6 +73,11 @@
 
 #define MAX_ADDR_LEN	32		/* Largest hardware address length */
 
+/* Driver transmit return codes */
+#define NETDEV_TX_OK 0		/* driver took care of packet */
+#define NETDEV_TX_BUSY 1	/* driver tx path was busy*/
+#define NETDEV_TX_LOCKED -1	/* driver tx lock was already taken */
+
 /*
  *	Compute the worst case header length according to the protocols
  *	used.
@@ -462,7 +467,7 @@
 						     unsigned char *haddr);
 	int			(*neigh_setup)(struct net_device *dev, struct neigh_parms *);
 	int			(*accept_fastpath)(struct net_device *, struct dst_entry*);
-#ifdef CONFIG_NETPOLL_RX
+#ifdef CONFIG_NETPOLL
 	int			netpoll_rx;
 #endif
 #ifdef CONFIG_NET_POLL_CONTROLLER
@@ -479,7 +484,6 @@
 
 	/* class/net/name entry */
 	struct class_device	class_dev;
-	struct net_device_stats* (*last_stats)(struct net_device *);
 	/* how much padding had been added by alloc_netdev() */
 	int padded;
 };
@@ -677,6 +681,7 @@
 extern int		dev_ethtool(struct ifreq *);
 extern unsigned		dev_get_flags(const struct net_device *);
 extern int		dev_change_flags(struct net_device *, unsigned);
+extern int		dev_change_name(struct net_device *, char *);
 extern int		dev_set_mtu(struct net_device *, int);
 extern void		dev_queue_xmit_nit(struct sk_buff *skb, struct net_device *dev);
 
diff -Nru a/include/linux/netfilter.h b/include/linux/netfilter.h
--- a/include/linux/netfilter.h	2004-10-18 14:56:32 -07:00
+++ b/include/linux/netfilter.h	2004-10-18 14:56:32 -07:00
@@ -178,7 +178,7 @@
 ip6t_find_target_lock(const char *name, int *error, struct semaphore *mutex);
 extern inline struct arpt_target *
 arpt_find_target_lock(const char *name, int *error, struct semaphore *mutex);
-extern void (*ip_ct_attach)(struct sk_buff *, struct nf_ct_info *);
+extern void (*ip_ct_attach)(struct sk_buff *, struct sk_buff *);
 
 #ifdef CONFIG_NETFILTER_DEBUG
 extern void nf_dump_skb(int pf, struct sk_buff *skb);
diff -Nru a/include/linux/netfilter_bridge/ebt_802_3.h b/include/linux/netfilter_bridge/ebt_802_3.h
--- a/include/linux/netfilter_bridge/ebt_802_3.h	2004-10-18 14:57:03 -07:00
+++ b/include/linux/netfilter_bridge/ebt_802_3.h	2004-10-18 14:57:03 -07:00
@@ -49,6 +49,15 @@
 	} llc;
 };
 
+#ifdef __KERNEL__
+#include <linux/skbuff.h>
+
+static inline struct ebt_802_3_hdr *ebt_802_3_hdr(const struct sk_buff *skb)
+{
+	return (struct ebt_802_3_hdr *)skb->mac.raw;
+}
+#endif
+
 struct ebt_802_3_info 
 {
 	uint8_t  sap;
diff -Nru a/include/linux/netfilter_ipv4/ip_conntrack.h b/include/linux/netfilter_ipv4/ip_conntrack.h
--- a/include/linux/netfilter_ipv4/ip_conntrack.h	2004-10-18 14:57:03 -07:00
+++ b/include/linux/netfilter_ipv4/ip_conntrack.h	2004-10-18 14:57:03 -07:00
@@ -51,10 +51,12 @@
 
 #include <linux/netfilter_ipv4/ip_conntrack_tcp.h>
 #include <linux/netfilter_ipv4/ip_conntrack_icmp.h>
+#include <linux/netfilter_ipv4/ip_conntrack_sctp.h>
 
 /* per conntrack: protocol private data */
 union ip_conntrack_proto {
 	/* insert conntrack proto private data here */
+	struct ip_ct_sctp sctp;
 	struct ip_ct_tcp tcp;
 	struct ip_ct_icmp icmp;
 };
@@ -156,6 +158,12 @@
 	union ip_conntrack_expect_help help;
 };
 
+struct ip_conntrack_counter
+{
+	u_int64_t packets;
+	u_int64_t bytes;
+};
+
 struct ip_conntrack_helper;
 
 struct ip_conntrack
@@ -164,15 +172,17 @@
            plus 1 for any connection(s) we are `master' for */
 	struct nf_conntrack ct_general;
 
-	/* These are my tuples; original and reply */
-	struct ip_conntrack_tuple_hash tuplehash[IP_CT_DIR_MAX];
-
 	/* Have we seen traffic both ways yet? (bitset) */
 	unsigned long status;
 
 	/* Timer function; drops refcnt when it goes off. */
 	struct timer_list timeout;
 
+#ifdef CONFIG_IP_NF_CT_ACCT
+	/* Accounting Information (same cache line as other written members) */
+	struct ip_conntrack_counter counters[IP_CT_DIR_MAX];
+#endif
+
 	/* If we're expecting another related connection, this will be
            in expected linked list */
 	struct list_head sibling_list;
@@ -186,12 +196,7 @@
 	/* Helper, if any. */
 	struct ip_conntrack_helper *helper;
 
-	/* Our various nf_ct_info structs specify *what* relation this
-           packet has to the conntrack */
-	struct nf_ct_info infos[IP_CT_NUMBER];
-
 	/* Storage reserved for other modules: */
-
 	union ip_conntrack_proto proto;
 
 	union ip_conntrack_help help;
@@ -207,6 +212,9 @@
 	} nat;
 #endif /* CONFIG_IP_NF_NAT_NEEDED */
 
+	/* Traversed often, so hopefully in different cacheline to top */
+	/* These are my tuples; original and reply */
+	struct ip_conntrack_tuple_hash tuplehash[IP_CT_DIR_MAX];
 };
 
 /* get master conntrack via master expectation */
@@ -225,8 +233,12 @@
 			 const struct ip_conntrack *ignored_conntrack);
 
 /* Return conntrack_info and tuple hash for given skb. */
-extern struct ip_conntrack *
-ip_conntrack_get(struct sk_buff *skb, enum ip_conntrack_info *ctinfo);
+static inline struct ip_conntrack *
+ip_conntrack_get(const struct sk_buff *skb, enum ip_conntrack_info *ctinfo)
+{
+	*ctinfo = skb->nfctinfo;
+	return (struct ip_conntrack *)skb->nfct;
+}
 
 /* decrement reference count on a conntrack */
 extern inline void ip_conntrack_put(struct ip_conntrack *ct);
@@ -245,16 +257,24 @@
 			  const struct ip_conntrack_tuple *orig);
 
 /* Refresh conntrack for this many jiffies */
-extern void ip_ct_refresh(struct ip_conntrack *ct,
-			  unsigned long extra_jiffies);
+extern void ip_ct_refresh_acct(struct ip_conntrack *ct,
+			       enum ip_conntrack_info ctinfo,
+			       const struct sk_buff *skb,
+			       unsigned long extra_jiffies);
 
 /* These are for NAT.  Icky. */
+/* Update TCP window tracking data when NAT mangles the packet */
+extern int ip_conntrack_tcp_update(struct sk_buff *skb,
+				   struct ip_conntrack *conntrack,
+				   int dir);
+
 /* Call me when a conntrack is destroyed. */
 extern void (*ip_conntrack_destroyed)(struct ip_conntrack *conntrack);
 
 /* Fake conntrack entry for untracked connections */
 extern struct ip_conntrack ip_conntrack_untracked;
 
+extern int ip_ct_no_defrag;
 /* Returns new sk_buff, or NULL */
 struct sk_buff *
 ip_ct_gather_frags(struct sk_buff *skb);
@@ -271,6 +291,27 @@
 }
 
 extern unsigned int ip_conntrack_htable_size;
+ 
+struct ip_conntrack_stat
+{
+	unsigned int searched;
+	unsigned int found;
+	unsigned int new;
+	unsigned int invalid;
+	unsigned int ignore;
+	unsigned int delete;
+	unsigned int delete_list;
+	unsigned int insert;
+	unsigned int insert_failed;
+	unsigned int drop;
+	unsigned int early_drop;
+	unsigned int error;
+	unsigned int expect_new;
+	unsigned int expect_create;
+	unsigned int expect_delete;
+};
+
+#define CONNTRACK_STAT_INC(count) (__get_cpu_var(ip_conntrack_stat).count++)
 
 /* eg. PROVIDES_CONNTRACK(ftp); */
 #define PROVIDES_CONNTRACK(name)                        \
diff -Nru a/include/linux/netfilter_ipv4/ip_conntrack_core.h b/include/linux/netfilter_ipv4/ip_conntrack_core.h
--- a/include/linux/netfilter_ipv4/ip_conntrack_core.h	2004-10-18 14:57:05 -07:00
+++ b/include/linux/netfilter_ipv4/ip_conntrack_core.h	2004-10-18 14:57:05 -07:00
@@ -16,34 +16,32 @@
 extern void ip_conntrack_cleanup(void);
 
 struct ip_conntrack_protocol;
-extern struct ip_conntrack_protocol *ip_ct_find_proto(u_int8_t protocol);
-/* Like above, but you already have conntrack read lock. */
-extern struct ip_conntrack_protocol *__ip_ct_find_proto(u_int8_t protocol);
-extern struct list_head protocol_list;
 
-/* Returns conntrack if it dealt with ICMP, and filled in skb->nfct */
-extern struct ip_conntrack *icmp_error_track(struct sk_buff *skb,
-					     enum ip_conntrack_info *ctinfo,
-					     unsigned int hooknum);
-extern int get_tuple(const struct iphdr *iph,
-		     const struct sk_buff *skb,
-		     unsigned int dataoff,
-		     struct ip_conntrack_tuple *tuple,
-		     const struct ip_conntrack_protocol *protocol);
+extern int
+ip_ct_get_tuple(const struct iphdr *iph,
+		const struct sk_buff *skb,
+		unsigned int dataoff,
+		struct ip_conntrack_tuple *tuple,
+		const struct ip_conntrack_protocol *protocol);
+
+extern int
+ip_ct_invert_tuple(struct ip_conntrack_tuple *inverse,
+		   const struct ip_conntrack_tuple *orig,
+		   const struct ip_conntrack_protocol *protocol);
 
 /* Find a connection corresponding to a tuple. */
 struct ip_conntrack_tuple_hash *
 ip_conntrack_find_get(const struct ip_conntrack_tuple *tuple,
 		      const struct ip_conntrack *ignored_conntrack);
 
-extern int __ip_conntrack_confirm(struct nf_ct_info *nfct);
+extern int __ip_conntrack_confirm(struct sk_buff *skb);
 
 /* Confirm a connection: returns NF_DROP if packet must be dropped. */
 static inline int ip_conntrack_confirm(struct sk_buff *skb)
 {
 	if (skb->nfct
-	    && !is_confirmed((struct ip_conntrack *)skb->nfct->master))
-		return __ip_conntrack_confirm(skb->nfct);
+	    && !is_confirmed((struct ip_conntrack *)skb->nfct))
+		return __ip_conntrack_confirm(skb);
 	return NF_ACCEPT;
 }
 
diff -Nru a/include/linux/netfilter_ipv4/ip_conntrack_ftp.h b/include/linux/netfilter_ipv4/ip_conntrack_ftp.h
--- a/include/linux/netfilter_ipv4/ip_conntrack_ftp.h	2004-10-18 14:57:05 -07:00
+++ b/include/linux/netfilter_ipv4/ip_conntrack_ftp.h	2004-10-18 14:57:05 -07:00
@@ -4,11 +4,6 @@
 
 #ifdef __KERNEL__
 
-#include <linux/netfilter_ipv4/lockhelp.h>
-
-/* Protects ftp part of conntracks */
-DECLARE_LOCK_EXTERN(ip_ftp_lock);
-
 #define FTP_PORT	21
 
 #endif /* __KERNEL__ */
diff -Nru a/include/linux/netfilter_ipv4/ip_conntrack_irc.h b/include/linux/netfilter_ipv4/ip_conntrack_irc.h
--- a/include/linux/netfilter_ipv4/ip_conntrack_irc.h	2004-10-18 14:56:28 -07:00
+++ b/include/linux/netfilter_ipv4/ip_conntrack_irc.h	2004-10-18 14:56:28 -07:00
@@ -33,12 +33,7 @@
 
 #ifdef __KERNEL__
 
-#include <linux/netfilter_ipv4/lockhelp.h>
-
 #define IRC_PORT	6667
-
-/* Protects irc part of conntracks */
-DECLARE_LOCK_EXTERN(ip_irc_lock);
 
 #endif /* __KERNEL__ */
 
diff -Nru a/include/linux/netfilter_ipv4/ip_conntrack_protocol.h b/include/linux/netfilter_ipv4/ip_conntrack_protocol.h
--- a/include/linux/netfilter_ipv4/ip_conntrack_protocol.h	2004-10-18 14:57:04 -07:00
+++ b/include/linux/netfilter_ipv4/ip_conntrack_protocol.h	2004-10-18 14:57:04 -07:00
@@ -3,11 +3,10 @@
 #define _IP_CONNTRACK_PROTOCOL_H
 #include <linux/netfilter_ipv4/ip_conntrack.h>
 
+struct seq_file;
+
 struct ip_conntrack_protocol
 {
-	/* Next pointer. */
-	struct list_head list;
-
 	/* Protocol number. */
 	u_int8_t proto;
 
@@ -26,13 +25,12 @@
 	int (*invert_tuple)(struct ip_conntrack_tuple *inverse,
 			    const struct ip_conntrack_tuple *orig);
 
-	/* Print out the per-protocol part of the tuple. */
-	unsigned int (*print_tuple)(char *buffer,
-				    const struct ip_conntrack_tuple *);
+	/* Print out the per-protocol part of the tuple. Return like seq_* */
+	int (*print_tuple)(struct seq_file *,
+			   const struct ip_conntrack_tuple *);
 
 	/* Print out the private part of the conntrack. */
-	unsigned int (*print_conntrack)(char *buffer,
-					const struct ip_conntrack *);
+	int (*print_conntrack)(struct seq_file *, const struct ip_conntrack *);
 
 	/* Returns verdict for packet, or -1 for invalid. */
 	int (*packet)(struct ip_conntrack *conntrack,
@@ -50,17 +48,46 @@
 	int (*exp_matches_pkt)(struct ip_conntrack_expect *exp,
 			       const struct sk_buff *skb);
 
+	int (*error)(struct sk_buff *skb, enum ip_conntrack_info *ctinfo,
+		     unsigned int hooknum);
+
 	/* Module (if any) which this is connected to. */
 	struct module *me;
 };
 
+#define MAX_IP_CT_PROTO 256
+extern struct ip_conntrack_protocol *ip_ct_protos[MAX_IP_CT_PROTO];
+
 /* Protocol registration. */
 extern int ip_conntrack_protocol_register(struct ip_conntrack_protocol *proto);
 extern void ip_conntrack_protocol_unregister(struct ip_conntrack_protocol *proto);
 
+static inline struct ip_conntrack_protocol *ip_ct_find_proto(u_int8_t protocol)
+{
+	return ip_ct_protos[protocol];
+}
+
 /* Existing built-in protocols */
 extern struct ip_conntrack_protocol ip_conntrack_protocol_tcp;
 extern struct ip_conntrack_protocol ip_conntrack_protocol_udp;
 extern struct ip_conntrack_protocol ip_conntrack_protocol_icmp;
+extern struct ip_conntrack_protocol ip_conntrack_generic_protocol;
 extern int ip_conntrack_protocol_tcp_init(void);
+
+/* Log invalid packets */
+extern unsigned int ip_ct_log_invalid;
+
+#ifdef CONFIG_SYSCTL
+#ifdef DEBUG_INVALID_PACKETS
+#define LOG_INVALID(proto) \
+	(ip_ct_log_invalid == (proto) || ip_ct_log_invalid == IPPROTO_RAW)
+#else
+#define LOG_INVALID(proto) \
+	((ip_ct_log_invalid == (proto) || ip_ct_log_invalid == IPPROTO_RAW) \
+	 && net_ratelimit())
+#endif
+#else
+#define LOG_INVALID(proto) 0
+#endif /* CONFIG_SYSCTL */
+
 #endif /*_IP_CONNTRACK_PROTOCOL_H*/
diff -Nru a/include/linux/netfilter_ipv4/ip_conntrack_sctp.h b/include/linux/netfilter_ipv4/ip_conntrack_sctp.h
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/include/linux/netfilter_ipv4/ip_conntrack_sctp.h	2004-10-18 14:57:21 -07:00
@@ -0,0 +1,25 @@
+#ifndef _IP_CONNTRACK_SCTP_H
+#define _IP_CONNTRACK_SCTP_H
+/* SCTP tracking. */
+
+enum sctp_conntrack {
+	SCTP_CONNTRACK_NONE,
+	SCTP_CONNTRACK_CLOSED,
+	SCTP_CONNTRACK_COOKIE_WAIT,
+	SCTP_CONNTRACK_COOKIE_ECHOED,
+	SCTP_CONNTRACK_ESTABLISHED,
+	SCTP_CONNTRACK_SHUTDOWN_SENT,
+	SCTP_CONNTRACK_SHUTDOWN_RECD,
+	SCTP_CONNTRACK_SHUTDOWN_ACK_SENT,
+	SCTP_CONNTRACK_MAX
+};
+
+struct ip_ct_sctp
+{
+	enum sctp_conntrack state;
+
+	u_int32_t vtag[IP_CT_DIR_MAX];
+	u_int32_t ttag[IP_CT_DIR_MAX];
+};
+
+#endif /* _IP_CONNTRACK_SCTP_H */
diff -Nru a/include/linux/netfilter_ipv4/ip_conntrack_tcp.h b/include/linux/netfilter_ipv4/ip_conntrack_tcp.h
--- a/include/linux/netfilter_ipv4/ip_conntrack_tcp.h	2004-10-18 14:56:28 -07:00
+++ b/include/linux/netfilter_ipv4/ip_conntrack_tcp.h	2004-10-18 14:56:28 -07:00
@@ -4,25 +4,44 @@
 
 enum tcp_conntrack {
 	TCP_CONNTRACK_NONE,
-	TCP_CONNTRACK_ESTABLISHED,
 	TCP_CONNTRACK_SYN_SENT,
 	TCP_CONNTRACK_SYN_RECV,
+	TCP_CONNTRACK_ESTABLISHED,
 	TCP_CONNTRACK_FIN_WAIT,
-	TCP_CONNTRACK_TIME_WAIT,
-	TCP_CONNTRACK_CLOSE,
 	TCP_CONNTRACK_CLOSE_WAIT,
 	TCP_CONNTRACK_LAST_ACK,
+	TCP_CONNTRACK_TIME_WAIT,
+	TCP_CONNTRACK_CLOSE,
 	TCP_CONNTRACK_LISTEN,
-	TCP_CONNTRACK_MAX
+	TCP_CONNTRACK_MAX,
+	TCP_CONNTRACK_IGNORE
+};
+
+/* Window scaling is advertised by the sender */
+#define IP_CT_TCP_STATE_FLAG_WINDOW_SCALE	0x01
+
+/* SACK is permitted by the sender */
+#define IP_CT_TCP_FLAG_SACK_PERM		0x02
+
+struct ip_ct_tcp_state {
+	u_int32_t	td_end;		/* max of seq + len */
+	u_int32_t	td_maxend;	/* max of ack + max(win, 1) */
+	u_int32_t	td_maxwin;	/* max(win) */
+	u_int8_t	td_scale;	/* window scale factor */
+	u_int8_t	loose;		/* used when connection picked up from the middle */
+	u_int8_t	flags;		/* per direction state flags */
 };
 
 struct ip_ct_tcp
 {
-	enum tcp_conntrack state;
-
-	/* Poor man's window tracking: sequence number of valid ACK
-           handshake completion packet */
-	u_int32_t handshake_ack;
+	struct ip_ct_tcp_state seen[2];	/* connection parameters per direction */
+	u_int8_t	state;		/* state of the connection (enum tcp_conntrack) */
+	/* For detecting stale connections */
+	u_int8_t	last_dir;	/* Direction of the last packet (enum ip_conntrack_dir) */
+	u_int8_t	retrans;	/* Number of retransmitted packets */
+	u_int8_t	last_index;	/* Index of the last packet */
+	u_int32_t	last_seq;	/* Last sequence number seen in dir */
+	u_int32_t	last_end;	/* Last seq + len */
 };
 
 #endif /* _IP_CONNTRACK_TCP_H */
diff -Nru a/include/linux/netfilter_ipv4/ip_conntrack_tuple.h b/include/linux/netfilter_ipv4/ip_conntrack_tuple.h
--- a/include/linux/netfilter_ipv4/ip_conntrack_tuple.h	2004-10-18 14:56:49 -07:00
+++ b/include/linux/netfilter_ipv4/ip_conntrack_tuple.h	2004-10-18 14:56:49 -07:00
@@ -25,6 +25,9 @@
 	struct {
 		u_int16_t id;
 	} icmp;
+	struct {
+		u_int16_t port;
+	} sctp;
 };
 
 /* The manipulable part of the tuple. */
@@ -55,6 +58,9 @@
 			struct {
 				u_int8_t type, code;
 			} icmp;
+			struct {
+				u_int16_t port;
+			} sctp;
 		} u;
 
 		/* The protocol. */
diff -Nru a/include/linux/netfilter_ipv4/ip_nat.h b/include/linux/netfilter_ipv4/ip_nat.h
--- a/include/linux/netfilter_ipv4/ip_nat.h	2004-10-18 14:57:04 -07:00
+++ b/include/linux/netfilter_ipv4/ip_nat.h	2004-10-18 14:57:04 -07:00
@@ -80,27 +80,18 @@
 /* Protects NAT hash tables, and NAT-private part of conntracks. */
 DECLARE_RWLOCK_EXTERN(ip_nat_lock);
 
-/* Hashes for by-source and IP/protocol. */
-struct ip_nat_hash
-{
-	struct list_head list;
-
-	/* conntrack we're embedded in: NULL if not in hash. */
-	struct ip_conntrack *conntrack;
-};
-
 /* The structure embedded in the conntrack structure. */
 struct ip_nat_info
 {
 	/* Set to zero when conntrack created: bitmask of maniptypes */
-	int initialized;
+	u_int16_t initialized;
 
-	unsigned int num_manips;
+	u_int16_t num_manips;
 
 	/* Manipulations to be done on this conntrack. */
 	struct ip_nat_info_manip manips[IP_NAT_MAX_MANIPS];
 
-	struct ip_nat_hash bysource, byipsproto;
+	struct list_head bysource, byipsproto;
 
 	/* Helper (NULL if none). */
 	struct ip_nat_helper *helper;
diff -Nru a/include/linux/netfilter_ipv4/ip_nat_core.h b/include/linux/netfilter_ipv4/ip_nat_core.h
--- a/include/linux/netfilter_ipv4/ip_nat_core.h	2004-10-18 14:55:53 -07:00
+++ b/include/linux/netfilter_ipv4/ip_nat_core.h	2004-10-18 14:55:53 -07:00
@@ -14,8 +14,6 @@
 				unsigned int hooknum,
 				struct sk_buff **pskb);
 
-extern struct list_head protos;
-
 extern int icmp_reply_translation(struct sk_buff **pskb,
 				  struct ip_conntrack *conntrack,
 				  unsigned int hooknum,
@@ -26,8 +24,4 @@
 extern void place_in_hashes(struct ip_conntrack *conntrack,
 			    struct ip_nat_info *info);
 
-/* Built-in protocols. */
-extern struct ip_nat_protocol ip_nat_protocol_tcp;
-extern struct ip_nat_protocol ip_nat_protocol_udp;
-extern struct ip_nat_protocol ip_nat_protocol_icmp;
 #endif /* _IP_NAT_CORE_H */
diff -Nru a/include/linux/netfilter_ipv4/ip_nat_helper.h b/include/linux/netfilter_ipv4/ip_nat_helper.h
--- a/include/linux/netfilter_ipv4/ip_nat_helper.h	2004-10-18 14:56:27 -07:00
+++ b/include/linux/netfilter_ipv4/ip_nat_helper.h	2004-10-18 14:56:27 -07:00
@@ -38,10 +38,14 @@
 			       struct ip_nat_info *info);
 };
 
-extern struct list_head helpers;
-
 extern int ip_nat_helper_register(struct ip_nat_helper *me);
 extern void ip_nat_helper_unregister(struct ip_nat_helper *me);
+
+extern struct ip_nat_helper *
+ip_nat_find_helper(const struct ip_conntrack_tuple *tuple);
+
+extern struct ip_nat_helper *
+__ip_nat_find_helper(const struct ip_conntrack_tuple *tuple);
 
 /* These return true or false. */
 extern int ip_nat_mangle_tcp_packet(struct sk_buff **skb,
diff -Nru a/include/linux/netfilter_ipv4/ip_nat_protocol.h b/include/linux/netfilter_ipv4/ip_nat_protocol.h
--- a/include/linux/netfilter_ipv4/ip_nat_protocol.h	2004-10-18 14:56:32 -07:00
+++ b/include/linux/netfilter_ipv4/ip_nat_protocol.h	2004-10-18 14:56:32 -07:00
@@ -9,8 +9,6 @@
 
 struct ip_nat_protocol
 {
-	struct list_head list;
-
 	/* Protocol name */
 	const char *name;
 
@@ -47,9 +45,23 @@
 				    const struct ip_nat_range *range);
 };
 
+#define MAX_IP_NAT_PROTO 256
+extern struct ip_nat_protocol *ip_nat_protos[MAX_IP_NAT_PROTO];
+
 /* Protocol registration. */
 extern int ip_nat_protocol_register(struct ip_nat_protocol *proto);
 extern void ip_nat_protocol_unregister(struct ip_nat_protocol *proto);
+
+static inline struct ip_nat_protocol *ip_nat_find_proto(u_int8_t protocol)
+{
+	return ip_nat_protos[protocol];
+}
+
+/* Built-in protocols. */
+extern struct ip_nat_protocol ip_nat_protocol_tcp;
+extern struct ip_nat_protocol ip_nat_protocol_udp;
+extern struct ip_nat_protocol ip_nat_protocol_icmp;
+extern struct ip_nat_protocol ip_nat_unknown_protocol;
 
 extern int init_protocols(void) __init;
 extern void cleanup_protocols(void);
diff -Nru a/include/linux/netfilter_ipv4/ip_tables.h b/include/linux/netfilter_ipv4/ip_tables.h
--- a/include/linux/netfilter_ipv4/ip_tables.h	2004-10-18 14:56:32 -07:00
+++ b/include/linux/netfilter_ipv4/ip_tables.h	2004-10-18 14:56:32 -07:00
@@ -336,7 +336,6 @@
  *	Main firewall chains definitions and global var's definitions.
  */
 #ifdef __KERNEL__
-static DECLARE_MUTEX(ipt_mutex);
 
 #include <linux/init.h>
 extern void ipt_init(void) __init;
diff -Nru a/include/linux/netfilter_ipv4/ipt_comment.h b/include/linux/netfilter_ipv4/ipt_comment.h
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/include/linux/netfilter_ipv4/ipt_comment.h	2004-10-18 14:57:21 -07:00
@@ -0,0 +1,10 @@
+#ifndef _IPT_COMMENT_H
+#define _IPT_COMMENT_H
+
+#define IPT_MAX_COMMENT_LEN 256
+
+struct ipt_comment_info {
+	unsigned char comment[IPT_MAX_COMMENT_LEN];
+};
+
+#endif /* _IPT_COMMENT_H */
diff -Nru a/include/linux/netfilter_ipv4/ipt_sctp.h b/include/linux/netfilter_ipv4/ipt_sctp.h
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/include/linux/netfilter_ipv4/ipt_sctp.h	2004-10-18 14:57:24 -07:00
@@ -0,0 +1,107 @@
+#ifndef _IPT_SCTP_H_
+#define _IPT_SCTP_H_
+
+#define IPT_SCTP_SRC_PORTS	        0x01
+#define IPT_SCTP_DEST_PORTS	        0x02
+#define IPT_SCTP_CHUNK_TYPES		0x04
+
+#define IPT_SCTP_VALID_FLAGS		0x07
+
+#define ELEMCOUNT(x) (sizeof(x)/sizeof(x[0]))
+
+
+struct ipt_sctp_flag_info {
+	u_int8_t chunktype;
+	u_int8_t flag;
+	u_int8_t flag_mask;
+};
+
+#define IPT_NUM_SCTP_FLAGS	4
+
+struct ipt_sctp_info {
+	u_int16_t dpts[2];  /* Min, Max */
+	u_int16_t spts[2];  /* Min, Max */
+
+	u_int32_t chunkmap[256 / sizeof (u_int32_t)];  /* Bit mask of chunks to be matched according to RFC 2960 */
+
+#define SCTP_CHUNK_MATCH_ANY   0x01  /* Match if any of the chunk types are present */
+#define SCTP_CHUNK_MATCH_ALL   0x02  /* Match if all of the chunk types are present */
+#define SCTP_CHUNK_MATCH_ONLY  0x04  /* Match if these are the only chunk types present */
+
+	u_int32_t chunk_match_type;
+	struct ipt_sctp_flag_info flag_info[IPT_NUM_SCTP_FLAGS];
+	int flag_count;
+
+	u_int32_t flags;
+	u_int32_t invflags;
+};
+
+#define bytes(type) (sizeof(type) * 8)
+
+#define SCTP_CHUNKMAP_SET(chunkmap, type) 		\
+	do { 						\
+		chunkmap[type / bytes(u_int32_t)] |= 	\
+			1 << (type % bytes(u_int32_t));	\
+	} while (0)
+
+#define SCTP_CHUNKMAP_CLEAR(chunkmap, type)		 	\
+	do {							\
+		chunkmap[type / bytes(u_int32_t)] &= 		\
+			~(1 << (type % bytes(u_int32_t)));	\
+	} while (0)
+
+#define SCTP_CHUNKMAP_IS_SET(chunkmap, type) 			\
+({								\
+	(chunkmap[type / bytes (u_int32_t)] & 			\
+		(1 << (type % bytes (u_int32_t)))) ? 1: 0;	\
+})
+
+#define SCTP_CHUNKMAP_RESET(chunkmap) 				\
+	do {							\
+		int i; 						\
+		for (i = 0; i < ELEMCOUNT(chunkmap); i++)	\
+			chunkmap[i] = 0;			\
+	} while (0)
+
+#define SCTP_CHUNKMAP_SET_ALL(chunkmap) 			\
+	do {							\
+		int i; 						\
+		for (i = 0; i < ELEMCOUNT(chunkmap); i++) 	\
+			chunkmap[i] = ~0;			\
+	} while (0)
+
+#define SCTP_CHUNKMAP_COPY(destmap, srcmap) 			\
+	do {							\
+		int i; 						\
+		for (i = 0; i < ELEMCOUNT(chunkmap); i++) 	\
+			destmap[i] = srcmap[i];			\
+	} while (0)
+
+#define SCTP_CHUNKMAP_IS_CLEAR(chunkmap) 		\
+({							\
+	int i; 						\
+	int flag = 1;					\
+	for (i = 0; i < ELEMCOUNT(chunkmap); i++) {	\
+		if (chunkmap[i]) {			\
+			flag = 0;			\
+			break;				\
+		}					\
+	}						\
+        flag;						\
+})
+
+#define SCTP_CHUNKMAP_IS_ALL_SET(chunkmap) 		\
+({							\
+	int i; 						\
+	int flag = 1;					\
+	for (i = 0; i < ELEMCOUNT(chunkmap); i++) {	\
+		if (chunkmap[i] != ~0) {		\
+			flag = 0;			\
+				break;			\
+		}					\
+	}						\
+        flag;						\
+})
+
+#endif /* _IPT_SCTP_H_ */
+
diff -Nru a/include/linux/netfilter_ipv6/ip6_tables.h b/include/linux/netfilter_ipv6/ip6_tables.h
--- a/include/linux/netfilter_ipv6/ip6_tables.h	2004-10-18 14:57:04 -07:00
+++ b/include/linux/netfilter_ipv6/ip6_tables.h	2004-10-18 14:57:04 -07:00
@@ -107,10 +107,6 @@
 	u_int64_t pcnt, bcnt;			/* Packet and byte counters */
 };
 
-#ifdef __KERNEL__
-static DECLARE_MUTEX(ip6t_mutex);
-#endif
-
 /* Values for "flag" field in struct ip6t_ip6 (general ip6 structure). */
 #define IP6T_F_PROTO		0x01	/* Set if rule cares about upper 
 					   protocols */
diff -Nru a/include/linux/netfilter_ipv6/ip6t_REJECT.h b/include/linux/netfilter_ipv6/ip6t_REJECT.h
--- a/include/linux/netfilter_ipv6/ip6t_REJECT.h	2004-10-18 14:55:53 -07:00
+++ /dev/null	Wed Dec 31 16:00:00 196900
@@ -1,16 +0,0 @@
-#ifndef _IP6T_REJECT_H
-#define _IP6T_REJECT_H
-
-enum ip6t_reject_with {
-	IP6T_ICMP_NET_UNREACHABLE,
-	IP6T_ICMP_HOST_UNREACHABLE,
-	IP6T_ICMP_PROT_UNREACHABLE,
-	IP6T_ICMP_PORT_UNREACHABLE,
-	IP6T_ICMP_ECHOREPLY
-};
-
-struct ip6t_reject_info {
-	enum ip6t_reject_with with;      /* reject type */
-};
-
-#endif /*_IPT_REJECT_H*/
diff -Nru a/include/linux/netfilter_ipv6/ip6t_physdev.h b/include/linux/netfilter_ipv6/ip6t_physdev.h
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/include/linux/netfilter_ipv6/ip6t_physdev.h	2004-10-18 14:57:21 -07:00
@@ -0,0 +1,24 @@
+#ifndef _IP6T_PHYSDEV_H
+#define _IP6T_PHYSDEV_H
+
+#ifdef __KERNEL__
+#include <linux/if.h>
+#endif
+
+#define IP6T_PHYSDEV_OP_IN		0x01
+#define IP6T_PHYSDEV_OP_OUT		0x02
+#define IP6T_PHYSDEV_OP_BRIDGED		0x04
+#define IP6T_PHYSDEV_OP_ISIN		0x08
+#define IP6T_PHYSDEV_OP_ISOUT		0x10
+#define IP6T_PHYSDEV_OP_MASK		(0x20 - 1)
+
+struct ip6t_physdev_info {
+	char physindev[IFNAMSIZ];
+	char in_mask[IFNAMSIZ];
+	char physoutdev[IFNAMSIZ];
+	char out_mask[IFNAMSIZ];
+	u_int8_t invert;
+	u_int8_t bitmask;
+};
+
+#endif /*_IP6T_PHYSDEV_H*/
diff -Nru a/include/linux/netfilter_ipv6.h b/include/linux/netfilter_ipv6.h
--- a/include/linux/netfilter_ipv6.h	2004-10-18 14:56:50 -07:00
+++ b/include/linux/netfilter_ipv6.h	2004-10-18 14:56:50 -07:00
@@ -58,8 +58,10 @@
 	NF_IP6_PRI_FIRST = INT_MIN,
 	NF_IP6_PRI_SELINUX_FIRST = -225,
 	NF_IP6_PRI_CONNTRACK = -200,
+	NF_IP6_PRI_BRIDGE_SABOTAGE_FORWARD = -175,
 	NF_IP6_PRI_MANGLE = -150,
 	NF_IP6_PRI_NAT_DST = -100,
+	NF_IP6_PRI_BRIDGE_SABOTAGE_LOCAL_OUT = -50,
 	NF_IP6_PRI_FILTER = 0,
 	NF_IP6_PRI_NAT_SRC = 100,
 	NF_IP6_PRI_SELINUX_LAST = 225,
diff -Nru a/include/linux/netlink.h b/include/linux/netlink.h
--- a/include/linux/netlink.h	2004-10-18 14:56:50 -07:00
+++ b/include/linux/netlink.h	2004-10-18 14:56:50 -07:00
@@ -99,6 +99,7 @@
 #ifdef __KERNEL__
 
 #include <linux/capability.h>
+#include <linux/skbuff.h>
 
 struct netlink_skb_parms
 {
@@ -125,13 +126,6 @@
 extern void netlink_set_err(struct sock *ssk, __u32 pid, __u32 group, int code);
 extern int netlink_register_notifier(struct notifier_block *nb);
 extern int netlink_unregister_notifier(struct notifier_block *nb);
-
-/* finegrained unicast helpers: */
-struct sock *netlink_getsockbypid(struct sock *ssk, u32 pid);
-struct sock *netlink_getsockbyfilp(struct file *filp);
-int netlink_attachskb(struct sock *sk, struct sk_buff *skb, int nonblock, long timeo);
-void netlink_detachskb(struct sock *sk, struct sk_buff *skb);
-int netlink_sendskb(struct sock *sk, struct sk_buff *skb, int protocol);
 
 /* finegrained unicast helpers: */
 struct sock *netlink_getsockbypid(struct sock *ssk, u32 pid);
diff -Nru a/include/linux/nfs.h b/include/linux/nfs.h
--- a/include/linux/nfs.h	2004-10-18 14:56:49 -07:00
+++ b/include/linux/nfs.h	2004-10-18 14:56:49 -07:00
@@ -8,6 +8,7 @@
 #define _LINUX_NFS_H
 
 #include <linux/sunrpc/msg_prot.h>
+#include <linux/string.h>
 
 #define NFS_PROGRAM	100003
 #define NFS_PORT	2049
@@ -137,6 +138,22 @@
 	unsigned short		size;
 	unsigned char		data[NFS_MAXFHSIZE];
 };
+
+/*
+ * Returns a zero iff the size and data fields match.
+ * Checks only "size" bytes in the data field.
+ */
+static inline int nfs_compare_fh(const struct nfs_fh *a, const struct nfs_fh *b)
+{
+	return a->size != b->size || memcmp(a->data, b->data, a->size) != 0;
+}
+
+static inline void nfs_copy_fh(struct nfs_fh *target, const struct nfs_fh *source)
+{
+	target->size = source->size;
+	memcpy(target->data, source->data, source->size);
+}
+
 
 /*
  * This is really a general kernel constant, but since nothing like
diff -Nru a/include/linux/nfs4.h b/include/linux/nfs4.h
--- a/include/linux/nfs4.h	2004-10-18 14:56:29 -07:00
+++ b/include/linux/nfs4.h	2004-10-18 14:56:29 -07:00
@@ -13,8 +13,12 @@
 #ifndef _LINUX_NFS4_H
 #define _LINUX_NFS4_H
 
+#include <linux/types.h>
+#include <linux/list.h>
+
 #define NFS4_VERIFIER_SIZE	8
 #define NFS4_FHSIZE		128
+#define NFS4_MAXPATHLEN		PATH_MAX
 #define NFS4_MAXNAMLEN		NAME_MAX
 
 #define NFS4_ACCESS_READ        0x0001
@@ -52,6 +56,60 @@
 #define ACL4_SUPPORT_AUDIT_ACL 0x04
 #define ACL4_SUPPORT_ALARM_ACL 0x08
 
+#define NFS4_ACE_FILE_INHERIT_ACE             0x00000001
+#define NFS4_ACE_DIRECTORY_INHERIT_ACE        0x00000002
+#define NFS4_ACE_NO_PROPAGATE_INHERIT_ACE     0x00000004
+#define NFS4_ACE_INHERIT_ONLY_ACE             0x00000008
+#define NFS4_ACE_SUCCESSFUL_ACCESS_ACE_FLAG   0x00000010
+#define NFS4_ACE_FAILED_ACCESS_ACE_FLAG       0x00000020
+#define NFS4_ACE_IDENTIFIER_GROUP             0x00000040
+#define NFS4_ACE_OWNER                        0x00000080
+#define NFS4_ACE_GROUP                        0x00000100
+#define NFS4_ACE_EVERYONE                     0x00000200
+
+#define NFS4_ACE_READ_DATA                    0x00000001
+#define NFS4_ACE_LIST_DIRECTORY               0x00000001
+#define NFS4_ACE_WRITE_DATA                   0x00000002
+#define NFS4_ACE_ADD_FILE                     0x00000002
+#define NFS4_ACE_APPEND_DATA                  0x00000004
+#define NFS4_ACE_ADD_SUBDIRECTORY             0x00000004
+#define NFS4_ACE_READ_NAMED_ATTRS             0x00000008
+#define NFS4_ACE_WRITE_NAMED_ATTRS            0x00000010
+#define NFS4_ACE_EXECUTE                      0x00000020
+#define NFS4_ACE_DELETE_CHILD                 0x00000040
+#define NFS4_ACE_READ_ATTRIBUTES              0x00000080
+#define NFS4_ACE_WRITE_ATTRIBUTES             0x00000100
+#define NFS4_ACE_DELETE                       0x00010000
+#define NFS4_ACE_READ_ACL                     0x00020000
+#define NFS4_ACE_WRITE_ACL                    0x00040000
+#define NFS4_ACE_WRITE_OWNER                  0x00080000
+#define NFS4_ACE_SYNCHRONIZE                  0x00100000
+#define NFS4_ACE_GENERIC_READ                 0x00120081
+#define NFS4_ACE_GENERIC_WRITE                0x00160106
+#define NFS4_ACE_GENERIC_EXECUTE              0x001200A0
+#define NFS4_ACE_MASK_ALL                     0x001F01FF
+
+enum nfs4_acl_whotype {
+	NFS4_ACL_WHO_NAMED = 0,
+	NFS4_ACL_WHO_OWNER,
+	NFS4_ACL_WHO_GROUP,
+	NFS4_ACL_WHO_EVERYONE,
+};
+
+struct nfs4_ace {
+	uint32_t	type;
+	uint32_t	flag;
+	uint32_t	access_mask;
+	int		whotype;
+	uid_t		who;
+	struct list_head l_ace;
+};
+
+struct nfs4_acl {
+	uint32_t	naces;
+	struct list_head ace_head;
+};
+
 typedef struct { char data[NFS4_VERIFIER_SIZE]; } nfs4_verifier;
 typedef struct { char data[16]; } nfs4_stateid;
 
@@ -297,7 +355,7 @@
 	NFSPROC4_CLNT_COMMIT,
 	NFSPROC4_CLNT_OPEN,
 	NFSPROC4_CLNT_OPEN_CONFIRM,
-	NFSPROC4_CLNT_OPEN_RECLAIM,
+	NFSPROC4_CLNT_OPEN_NOATTR,
 	NFSPROC4_CLNT_OPEN_DOWNGRADE,
 	NFSPROC4_CLNT_CLOSE,
 	NFSPROC4_CLNT_SETATTR,
@@ -315,12 +373,14 @@
 	NFSPROC4_CLNT_REMOVE,
 	NFSPROC4_CLNT_RENAME,
 	NFSPROC4_CLNT_LINK,
+	NFSPROC4_CLNT_SYMLINK,
 	NFSPROC4_CLNT_CREATE,
 	NFSPROC4_CLNT_PATHCONF,
 	NFSPROC4_CLNT_STATFS,
 	NFSPROC4_CLNT_READLINK,
 	NFSPROC4_CLNT_READDIR,
 	NFSPROC4_CLNT_SERVER_CAPS,
+	NFSPROC4_CLNT_DELEGRETURN,
 };
 
 #endif
diff -Nru a/include/linux/nfs4_acl.h b/include/linux/nfs4_acl.h
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/include/linux/nfs4_acl.h	2004-10-18 14:57:24 -07:00
@@ -0,0 +1,59 @@
+/*
+ *  include/linux/nfs4_acl.c
+ *
+ *  Common NFSv4 ACL handling definitions.
+ *
+ *  Copyright (c) 2002 The Regents of the University of Michigan.
+ *  All rights reserved.
+ *
+ *  Marius Aamodt Eriksen <marius@umich.edu>
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions
+ *  are met:
+ *
+ *  1. Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ *  2. Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in the
+ *     documentation and/or other materials provided with the distribution.
+ *  3. Neither the name of the University nor the names of its
+ *     contributors may be used to endorse or promote products derived
+ *     from this software without specific prior written permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ *  WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ *  DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ *  FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ *  CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ *  SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ *  BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ *  LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ *  NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ *  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef LINUX_NFS4_ACL_H
+#define LINUX_NFS4_ACL_H
+
+#include <linux/posix_acl.h>
+
+struct nfs4_acl *nfs4_acl_new(void);
+void nfs4_acl_free(struct nfs4_acl *);
+int nfs4_acl_add_ace(struct nfs4_acl *, u32, u32, u32, int, uid_t);
+int nfs4_acl_get_whotype(char *, u32);
+int nfs4_acl_write_who(int who, char *p);
+int nfs4_acl_permission(struct nfs4_acl *acl, uid_t owner, gid_t group,
+		                        uid_t who, u32 mask);
+
+#define NFS4_ACL_TYPE_DEFAULT	0x01
+#define NFS4_ACL_DIR		0x02
+#define NFS4_ACL_OWNER		0x04
+
+struct nfs4_acl *nfs4_acl_posix_to_nfsv4(struct posix_acl *,
+				struct posix_acl *, unsigned int flags);
+int nfs4_acl_nfsv4_to_posix(struct nfs4_acl *, struct posix_acl **,
+				struct posix_acl **, unsigned int flags);
+
+#endif /* LINUX_NFS4_ACL_H */
diff -Nru a/include/linux/nfs_fs.h b/include/linux/nfs_fs.h
--- a/include/linux/nfs_fs.h	2004-10-18 14:56:28 -07:00
+++ b/include/linux/nfs_fs.h	2004-10-18 14:56:28 -07:00
@@ -28,6 +28,7 @@
 #include <linux/nfs3.h>
 #include <linux/nfs4.h>
 #include <linux/nfs_xdr.h>
+#include <linux/rwsem.h>
 #include <linux/workqueue.h>
 
 /*
@@ -75,16 +76,34 @@
 #ifdef __KERNEL__
 
 /*
- * NFSv3 Access mode cache
+ * NFSv3/v4 Access mode cache entry
  */
-struct nfs_access_cache {
+struct nfs_access_entry {
 	unsigned long		jiffies;
 	struct rpc_cred *	cred;
 	int			mask;
-	int			err;
+};
+
+struct nfs4_state;
+struct nfs_open_context {
+	atomic_t count;
+	struct dentry *dentry;
+	struct rpc_cred *cred;
+	struct nfs4_state *state;
+	fl_owner_t lockowner;
+	int mode;
+	int error;
+
+	struct list_head list;
+	wait_queue_head_t waitq;
 };
 
 /*
+ * NFSv4 delegation
+ */
+struct nfs_delegation;
+
+/*
  * nfs fs inode data in memory
  */
 struct nfs_inode {
@@ -137,7 +156,7 @@
 	 */
 	atomic_t		data_updates;
 
-	struct nfs_access_cache	cache_access;
+	struct nfs_access_entry	cache_access;
 
 	/*
 	 * This is the cookie verifier used for NFSv3 readdir
@@ -148,6 +167,7 @@
 	/*
 	 * This is the list of dirty unwritten pages.
 	 */
+	spinlock_t		req_lock;
 	struct list_head	dirty;
 	struct list_head	commit;
 	struct radix_tree_root	nfs_page_tree;
@@ -156,14 +176,17 @@
 				ncommit,
 				npages;
 
-	/* Credentials for shared mmap */
-	struct rpc_cred		*mm_cred;
+	/* Open contexts for shared mmap writes */
+	struct list_head	open_files;
 
 	wait_queue_head_t	nfs_i_wait;
 
 #ifdef CONFIG_NFS_V4
         /* NFSv4 state */
 	struct list_head	open_states;
+	struct nfs_delegation	*delegation;
+	int			 delegation_state;
+	struct rw_semaphore	rwsem;
 #endif /* CONFIG_NFS_V4*/
 
 	struct inode		vfs_inode;
@@ -268,9 +291,12 @@
 extern int nfs_refresh_inode(struct inode *, struct nfs_fattr *);
 extern int nfs_getattr(struct vfsmount *, struct dentry *, struct kstat *);
 extern int nfs_permission(struct inode *, int, struct nameidata *);
-extern void nfs_set_mmcred(struct inode *, struct rpc_cred *);
+extern int nfs_access_get_cached(struct inode *, struct rpc_cred *, struct nfs_access_entry *);
+extern void nfs_access_add_cache(struct inode *, struct nfs_access_entry *);
 extern int nfs_open(struct inode *, struct file *);
 extern int nfs_release(struct inode *, struct file *);
+extern int nfs_attribute_timeout(struct inode *inode);
+extern int nfs_revalidate_inode(struct nfs_server *server, struct inode *inode);
 extern int __nfs_revalidate_inode(struct nfs_server *, struct inode *);
 extern int nfs_setattr(struct dentry *, struct iattr *);
 extern void nfs_begin_attr_update(struct inode *);
@@ -278,6 +304,12 @@
 extern void nfs_begin_data_update(struct inode *);
 extern void nfs_end_data_update(struct inode *);
 extern void nfs_end_data_update_defer(struct inode *);
+extern struct nfs_open_context *alloc_nfs_open_context(struct dentry *dentry, struct rpc_cred *cred);
+extern struct nfs_open_context *get_nfs_open_context(struct nfs_open_context *ctx);
+extern void put_nfs_open_context(struct nfs_open_context *ctx);
+extern void nfs_file_set_open_context(struct file *filp, struct nfs_open_context *ctx);
+extern struct nfs_open_context *nfs_find_open_context(struct inode *inode, int mode);
+extern void nfs_file_clear_open_context(struct file *filp);
 
 /* linux/net/ipv4/ipconfig.c: trims ip addr off front of name, too. */
 extern u32 root_nfs_parse_addr(char *name); /*__init*/
@@ -289,16 +321,15 @@
 extern struct file_operations nfs_file_operations;
 extern struct address_space_operations nfs_file_aops;
 
-static __inline__ struct rpc_cred *
-nfs_file_cred(struct file *file)
+static inline struct rpc_cred *nfs_file_cred(struct file *file)
 {
-	struct rpc_cred *cred = NULL;
-	if (file)
-		cred = (struct rpc_cred *)file->private_data;
-#ifdef RPC_DEBUG
-	BUG_ON(cred && cred->cr_magic != RPCAUTH_CRED_MAGIC);
-#endif
-	return cred;
+	if (file != NULL) {
+		struct nfs_open_context *ctx;
+
+		ctx = (struct nfs_open_context*)file->private_data;
+		return ctx->cred;
+	}
+	return NULL;
 }
 
 /*
@@ -418,28 +449,6 @@
  * inline functions
  */
 
-static inline int nfs_attribute_timeout(struct inode *inode)
-{
-	struct nfs_inode *nfsi = NFS_I(inode);
-
-	return time_after(jiffies, nfsi->read_cache_jiffies+nfsi->attrtimeo);
-}
-
-/**
- * nfs_revalidate_inode - Revalidate the inode attributes
- * @server - pointer to nfs_server struct
- * @inode - pointer to inode struct
- *
- * Updates inode attribute information by retrieving the data from the server.
- */
-static inline int nfs_revalidate_inode(struct nfs_server *server, struct inode *inode)
-{
-	if (!(NFS_FLAGS(inode) & (NFS_INO_INVALID_ATTR|NFS_INO_INVALID_DATA))
-			&& !nfs_attribute_timeout(inode))
-		return NFS_STALE(inode) ? -ESTALE : 0;
-	return __nfs_revalidate_inode(server, inode);
-}
-
 static inline loff_t
 nfs_size_to_loff_t(__u64 size)
 {
@@ -507,8 +516,6 @@
 
 enum nfs4_client_state {
 	NFS4CLNT_OK  = 0,
-	NFS4CLNT_NEW,
-	NFS4CLNT_SETUP_STATE,
 };
 
 /*
@@ -520,7 +527,6 @@
 	u64			cl_clientid;	/* constant */
 	nfs4_verifier		cl_confirm;
 	unsigned long		cl_state;
-	long			cl_generation;
 
 	u32			cl_lockowner_id;
 
@@ -530,6 +536,7 @@
 	 */
 	struct rw_semaphore	cl_sem;
 
+	struct list_head	cl_delegations;
 	struct list_head	cl_state_owners;
 	struct list_head	cl_unused;
 	int			cl_nunused;
@@ -573,12 +580,11 @@
 	u32                  so_id;      /* 32-bit identifier, unique */
 	struct semaphore     so_sema;
 	u32                  so_seqid;   /* protected by so_sema */
-	unsigned int         so_flags;   /* protected by so_sema */
 	atomic_t	     so_count;
-	long		     so_generation;
 
 	struct rpc_cred	     *so_cred;	 /* Associated cred */
 	struct list_head     so_states;
+	struct list_head     so_delegations;
 };
 
 /*
@@ -596,7 +602,8 @@
 struct nfs4_lock_state {
 	struct list_head	ls_locks;	/* Other lock stateids */
 	fl_owner_t		ls_owner;	/* POSIX lock owner */
-	struct nfs4_state *	ls_parent;	/* Parent nfs4_state */
+#define NFS_LOCK_INITIALIZED 1
+	int			ls_flags;
 	u32			ls_seqid;
 	u32			ls_id;
 	nfs4_stateid		ls_stateid;
@@ -606,6 +613,7 @@
 /* bits for nfs4_state->flags */
 enum {
 	LK_STATE_IN_USE,
+	NFS_DELEGATED_STATE,
 };
 
 struct nfs4_state {
@@ -629,6 +637,11 @@
 };
 
 
+struct nfs4_exception {
+	long timeout;
+	int retry;
+};
+
 extern struct dentry_operations nfs4_dentry_operations;
 extern struct inode_operations nfs4_dir_inode_operations;
 
@@ -639,10 +652,12 @@
 extern int nfs4_proc_async_renew(struct nfs4_client *);
 extern int nfs4_proc_renew(struct nfs4_client *);
 extern int nfs4_do_close(struct inode *, struct nfs4_state *);
-int nfs4_do_downgrade(struct inode *inode, struct nfs4_state *state, mode_t mode);
+extern int nfs4_do_downgrade(struct inode *inode, struct nfs4_state *state, mode_t mode);
 extern int nfs4_wait_clnt_recover(struct rpc_clnt *, struct nfs4_client *);
 extern struct inode *nfs4_atomic_open(struct inode *, struct dentry *, struct nameidata *);
 extern int nfs4_open_revalidate(struct inode *, struct dentry *, int);
+extern int nfs4_handle_exception(struct nfs_server *, int, struct nfs4_exception *);
+extern int nfs4_lock_reclaim(struct nfs4_state *state, struct file_lock *request);
 
 /* nfs4renewd.c */
 extern void nfs4_schedule_state_renewal(struct nfs4_client *);
@@ -654,6 +669,8 @@
 extern void destroy_nfsv4_state(struct nfs_server *);
 extern struct nfs4_client *nfs4_get_client(struct in_addr *);
 extern void nfs4_put_client(struct nfs4_client *clp);
+extern int nfs4_init_client(struct nfs4_client *clp);
+extern struct nfs4_client *nfs4_find_client(struct in_addr *);
 extern u32 nfs4_alloc_lockowner_id(struct nfs4_client *);
 
 extern struct nfs4_state_owner * nfs4_get_state_owner(struct nfs_server *, struct rpc_cred *);
@@ -663,14 +680,13 @@
 extern void nfs4_close_state(struct nfs4_state *, mode_t);
 extern struct nfs4_state *nfs4_find_state(struct inode *, struct rpc_cred *, mode_t mode);
 extern void nfs4_increment_seqid(int status, struct nfs4_state_owner *sp);
-extern int nfs4_handle_error(struct nfs_server *, int);
 extern void nfs4_schedule_state_recovery(struct nfs4_client *);
 extern struct nfs4_lock_state *nfs4_find_lock_state(struct nfs4_state *state, fl_owner_t);
-extern struct nfs4_lock_state *nfs4_alloc_lock_state(struct nfs4_state *state, fl_owner_t);
+extern struct nfs4_lock_state *nfs4_get_lock_state(struct nfs4_state *state, fl_owner_t);
 extern void nfs4_put_lock_state(struct nfs4_lock_state *state);
 extern void nfs4_increment_lock_seqid(int status, struct nfs4_lock_state *ls);
-extern void nfs4_notify_setlk(struct inode *, struct file_lock *, struct nfs4_lock_state *);
-extern void nfs4_notify_unlck(struct inode *, struct file_lock *, struct nfs4_lock_state *);
+extern void nfs4_notify_setlk(struct nfs4_state *, struct file_lock *, struct nfs4_lock_state *);
+extern void nfs4_notify_unlck(struct nfs4_state *, struct file_lock *, struct nfs4_lock_state *);
 extern void nfs4_copy_stateid(nfs4_stateid *, struct nfs4_state *, fl_owner_t);
 
 
@@ -681,6 +697,7 @@
 #define destroy_nfsv4_state(server)       do { } while (0)
 #define nfs4_put_state_owner(inode, owner) do { } while (0)
 #define nfs4_put_open_state(state) do { } while (0)
+#define nfs4_close_state(a, b) do { } while (0)
 #define nfs4_renewd_prepare_shutdown(server) do { } while (0)
 #endif
 
@@ -697,6 +714,7 @@
 #define NFSDBG_XDR		0x0020
 #define NFSDBG_FILE		0x0040
 #define NFSDBG_ROOT		0x0080
+#define NFSDBG_CALLBACK		0x0100
 #define NFSDBG_ALL		0xFFFF
 
 #ifdef __KERNEL__
diff -Nru a/include/linux/nfs_fs_i.h b/include/linux/nfs_fs_i.h
--- a/include/linux/nfs_fs_i.h	2004-10-18 14:57:19 -07:00
+++ b/include/linux/nfs_fs_i.h	2004-10-18 14:57:19 -07:00
@@ -5,13 +5,15 @@
 #include <linux/list.h>
 #include <linux/nfs.h>
 
+struct nlm_lockowner;
+
 /*
  * NFS lock info
  */
 struct nfs_lock_info {
 	u32		state;
 	u32		flags;
-	struct nlm_host	*host;
+	struct nlm_lockowner *owner;
 };
 
 /*
diff -Nru a/include/linux/nfs_fs_sb.h b/include/linux/nfs_fs_sb.h
--- a/include/linux/nfs_fs_sb.h	2004-10-18 14:57:18 -07:00
+++ b/include/linux/nfs_fs_sb.h	2004-10-18 14:57:18 -07:00
@@ -18,6 +18,7 @@
 	unsigned int		rpages;		/* read size (in pages) */
 	unsigned int		wsize;		/* write size */
 	unsigned int		wpages;		/* write size (in pages) */
+	unsigned int		wtmult;		/* server disk block size */
 	unsigned int		dtsize;		/* readdir size */
 	unsigned int		bsize;		/* server block size */
 	unsigned int		acregmin;	/* attr cache timeouts */
diff -Nru a/include/linux/nfs_page.h b/include/linux/nfs_page.h
--- a/include/linux/nfs_page.h	2004-10-18 14:55:54 -07:00
+++ b/include/linux/nfs_page.h	2004-10-18 14:55:54 -07:00
@@ -29,19 +29,14 @@
 struct nfs_page {
 	struct list_head	wb_list,	/* Defines state of page: */
 				*wb_list_head;	/*      read/write/commit */
-	struct file		*wb_file;
-	fl_owner_t		wb_lockowner;
-	struct inode		*wb_inode;
-	struct rpc_cred		*wb_cred;
-	struct nfs4_state	*wb_state;
 	struct page		*wb_page;	/* page to read in/write out */
+	struct nfs_open_context	*wb_context;	/* File state context info */
 	atomic_t		wb_complete;	/* i/os we're waiting for */
-	wait_queue_head_t	wb_wait;	/* wait queue */
 	unsigned long		wb_index;	/* Offset >> PAGE_CACHE_SHIFT */
 	unsigned int		wb_offset,	/* Offset & ~PAGE_CACHE_MASK */
 				wb_pgbase,	/* Start of page data */
-				wb_bytes,	/* Length of request */
-				wb_count;	/* reference count */
+				wb_bytes;	/* Length of request */
+	atomic_t		wb_count;	/* reference count */
 	unsigned long		wb_flags;
 	struct nfs_writeverf	wb_verf;	/* Commit cookie */
 };
@@ -50,9 +45,11 @@
 #define NFS_NEED_COMMIT(req)	(test_bit(PG_NEED_COMMIT,&(req)->wb_flags))
 #define NFS_NEED_RESCHED(req)	(test_bit(PG_NEED_RESCHED,&(req)->wb_flags))
 
-extern	struct nfs_page *nfs_create_request(struct file *, struct inode *,
-					    struct page *,
-					    unsigned int, unsigned int);
+extern	struct nfs_page *nfs_create_request(struct nfs_open_context *ctx,
+					    struct inode *inode,
+					    struct page *page,
+					    unsigned int offset,
+					    unsigned int count);
 extern	void nfs_clear_request(struct nfs_page *req);
 extern	void nfs_release_request(struct nfs_page *req);
 
@@ -64,8 +61,7 @@
 extern	int nfs_coalesce_requests(struct list_head *, struct list_head *,
 				  unsigned int);
 extern  int nfs_wait_on_request(struct nfs_page *);
-
-extern	spinlock_t nfs_wreq_lock;
+extern	void nfs_unlock_request(struct nfs_page *req);
 
 /*
  * Lock the page of an asynchronous request without incrementing the wb_count
@@ -86,23 +82,10 @@
 {
 	if (test_and_set_bit(PG_BUSY, &req->wb_flags))
 		return 0;
-	req->wb_count++;
+	atomic_inc(&req->wb_count);
 	return 1;
 }
 
-static inline void
-nfs_unlock_request(struct nfs_page *req)
-{
-	if (!NFS_WBACK_BUSY(req)) {
-		printk(KERN_ERR "NFS: Invalid unlock attempted\n");
-		BUG();
-	}
-	smp_mb__before_clear_bit();
-	clear_bit(PG_BUSY, &req->wb_flags);
-	smp_mb__after_clear_bit();
-	wake_up_all(&req->wb_wait);
-	nfs_release_request(req);
-}
 
 /**
  * nfs_list_remove_request - Remove a request from its wb_list
diff -Nru a/include/linux/nfs_xdr.h b/include/linux/nfs_xdr.h
--- a/include/linux/nfs_xdr.h	2004-10-18 14:56:49 -07:00
+++ b/include/linux/nfs_xdr.h	2004-10-18 14:56:49 -07:00
@@ -99,20 +99,21 @@
  * Arguments to the open call.
  */
 struct nfs_openargs {
-	struct nfs_fh *         fh;
+	const struct nfs_fh *	fh;
 	__u32                   seqid;
-	__u32                   share_access;
+	int			open_flags;
 	__u64                   clientid;
 	__u32                   id;
-	__u32                   opentype;
-	__u32                   createmode;
 	union {
 		struct iattr *  attrs;    /* UNCHECKED, GUARDED */
 		nfs4_verifier   verifier; /* EXCLUSIVE */
+		nfs4_stateid	delegation;		/* CLAIM_DELEGATE_CUR */
+		int		delegation_type;	/* CLAIM_PREVIOUS */
 	} u;
 	const struct qstr *	name;
 	const struct nfs_server *server;	 /* Needed for ID mapping */
 	const u32 *		bitmask;
+	__u32			claim;
 };
 
 struct nfs_openres {
@@ -122,13 +123,17 @@
 	__u32                   rflags;
 	struct nfs_fattr *      f_attr;
 	const struct nfs_server *server;
+	int			delegation_type;
+	nfs4_stateid		delegation;
+	__u32			do_recall;
+	__u64			maxsize;
 };
 
 /*
  * Arguments to the open_confirm call.
  */
 struct nfs_open_confirmargs {
-	struct nfs_fh *         fh;
+	const struct nfs_fh *	fh;
 	nfs4_stateid            stateid;
 	__u32                   seqid;
 };
@@ -138,26 +143,13 @@
 };
 
 /*
- * Arguments to the open_reclaim call.
- */
-struct nfs_open_reclaimargs {
-	struct nfs_fh *		fh;
-	__u64			clientid;
-	__u32			seqid;
-	__u32			id;
-	__u32			share_access;
-	__u32			claim;
-	const __u32 *		bitmask;
-};
-
-/*
  * Arguments to the close call.
  */
 struct nfs_closeargs {
 	struct nfs_fh *         fh;
 	nfs4_stateid            stateid;
 	__u32                   seqid;
-	__u32			share_access;
+	int			open_flags;
 };
 
 struct nfs_closeres {
@@ -224,6 +216,11 @@
 	const struct nfs_server *	server;
 };
 
+struct nfs4_delegreturnargs {
+	const struct nfs_fh *fhandle;
+	const nfs4_stateid *stateid;
+};
+
 /*
  * Arguments to the read call.
  */
@@ -235,8 +232,7 @@
 
 struct nfs_readargs {
 	struct nfs_fh *		fh;
-	fl_owner_t		lockowner;
-	struct nfs4_state *	state;
+	struct nfs_open_context *context;
 	__u64			offset;
 	__u32			count;
 	unsigned int		pgbase;
@@ -259,8 +255,7 @@
 
 struct nfs_writeargs {
 	struct nfs_fh *		fh;
-	fl_owner_t		lockowner;
-	struct nfs4_state *	state;
+	struct nfs_open_context *context;
 	__u64			offset;
 	__u32			count;
 	enum nfs3_stable_how	stable;
@@ -366,7 +361,8 @@
 
 struct nfs_readlinkargs {
 	struct nfs_fh *		fh;
-	unsigned int		count;
+	unsigned int		pgbase;
+	unsigned int		pglen;
 	struct page **		pages;
 };
 
@@ -460,7 +456,8 @@
 
 struct nfs3_readlinkargs {
 	struct nfs_fh *		fh;
-	unsigned int		count;
+	unsigned int		pgbase;
+	unsigned int		pglen;
 	struct page **		pages;
 };
 
@@ -575,7 +572,8 @@
 
 struct nfs4_readlink {
 	const struct nfs_fh *		fh;
-	u32				count;   /* zero-copy data */
+	unsigned int			pgbase;
+	unsigned int			pglen;   /* zero-copy data */
 	struct page **			pages;   /* zero-copy data */
 };
 
@@ -597,13 +595,15 @@
 };
 
 struct nfs4_setclientid {
-	nfs4_verifier			sc_verifier;      /* request */
-	char *				sc_name;	  /* request */
+	const nfs4_verifier *		sc_verifier;      /* request */
+	unsigned int			sc_name_len;
+	char				sc_name[32];	  /* request */
 	u32				sc_prog;          /* request */
+	unsigned int			sc_netid_len;
 	char				sc_netid[4];	  /* request */
+	unsigned int			sc_uaddr_len;
 	char				sc_uaddr[24];     /* request */
 	u32				sc_cb_ident;      /* request */
-	struct nfs4_client *		sc_state;	  /* response */
 };
 
 struct nfs4_statfs_arg {
@@ -657,6 +657,8 @@
 	void (*complete) (struct nfs_write_data *, int);
 };
 
+struct nfs_access_entry;
+
 /*
  * RPC procedure vector for NFSv2/NFSv3 demuxing
  */
@@ -667,16 +669,18 @@
 
 	int	(*getroot) (struct nfs_server *, struct nfs_fh *,
 			    struct nfs_fsinfo *);
-	int	(*getattr) (struct inode *, struct nfs_fattr *);
+	int	(*getattr) (struct nfs_server *, struct nfs_fh *,
+			    struct nfs_fattr *);
 	int	(*setattr) (struct dentry *, struct nfs_fattr *,
 			    struct iattr *);
 	int	(*lookup)  (struct inode *, struct qstr *,
 			    struct nfs_fh *, struct nfs_fattr *);
-	int	(*access)  (struct inode *, struct rpc_cred *, int);
-	int	(*readlink)(struct inode *, struct page *);
-	int	(*read)    (struct nfs_read_data *, struct file *);
-	int	(*write)   (struct nfs_write_data *, struct file *);
-	int	(*commit)  (struct nfs_write_data *, struct file *);
+	int	(*access)  (struct inode *, struct nfs_access_entry *);
+	int	(*readlink)(struct inode *, struct page *, unsigned int,
+			    unsigned int);
+	int	(*read)    (struct nfs_read_data *);
+	int	(*write)   (struct nfs_write_data *);
+	int	(*commit)  (struct nfs_write_data *);
 	struct inode *	(*create)  (struct inode *, struct qstr *,
 			    struct iattr *, int);
 	int	(*remove)  (struct inode *, struct qstr *);
@@ -708,8 +712,6 @@
 	void	(*commit_setup) (struct nfs_write_data *, int how);
 	int	(*file_open)   (struct inode *, struct file *);
 	int	(*file_release) (struct inode *, struct file *);
-	void	(*request_init)(struct nfs_page *, struct file *);
-	int	(*request_compatible)(struct nfs_page *, struct file *, struct page *);
 	int	(*lock)(struct file *, int, struct file_lock *);
 };
 
diff -Nru a/include/linux/nfsd/nfsd.h b/include/linux/nfsd/nfsd.h
--- a/include/linux/nfsd/nfsd.h	2004-10-18 14:57:04 -07:00
+++ b/include/linux/nfsd/nfsd.h	2004-10-18 14:57:04 -07:00
@@ -76,6 +76,11 @@
 				const char *, int, struct svc_fh *);
 int		nfsd_setattr(struct svc_rqst *, struct svc_fh *,
 				struct iattr *, int, time_t);
+#ifdef CONFIG_NFSD_V4
+int             nfsd4_set_nfs4_acl(struct svc_rqst *, struct svc_fh *,
+                    struct nfs4_acl *);
+int             nfsd4_get_nfs4_acl(struct svc_rqst *, struct dentry *, struct nfs4_acl **);
+#endif /* CONFIG_NFSD_V4 */
 int		nfsd_create(struct svc_rqst *, struct svc_fh *,
 				char *name, int len, struct iattr *attrs,
 				int type, dev_t rdev, struct svc_fh *res);
@@ -89,7 +94,7 @@
 				loff_t, unsigned long);
 #endif /* CONFIG_NFSD_V3 */
 int		nfsd_open(struct svc_rqst *, struct svc_fh *, int,
-				int, struct file *);
+				int, struct file **);
 void		nfsd_close(struct file *);
 int		nfsd_read(struct svc_rqst *, struct svc_fh *,
 				loff_t, struct kvec *,int, unsigned long *);
@@ -258,7 +263,6 @@
 
 /*
  * The following attributes are currently not supported by the NFSv4 server:
- *    ACL           (will be supported in a forthcoming patch)
  *    ARCHIVE       (deprecated anyway)
  *    FS_LOCATIONS  (will be supported eventually)
  *    HIDDEN        (unlikely to be supported any time soon)
@@ -278,7 +282,7 @@
  | FATTR4_WORD0_FILEHANDLE      | FATTR4_WORD0_FILEID       | FATTR4_WORD0_FILES_AVAIL      \
  | FATTR4_WORD0_FILES_FREE      | FATTR4_WORD0_FILES_TOTAL  | FATTR4_WORD0_HOMOGENEOUS      \
  | FATTR4_WORD0_MAXFILESIZE     | FATTR4_WORD0_MAXLINK      | FATTR4_WORD0_MAXNAME          \
- | FATTR4_WORD0_MAXREAD         | FATTR4_WORD0_MAXWRITE)
+ | FATTR4_WORD0_MAXREAD         | FATTR4_WORD0_MAXWRITE     | FATTR4_WORD0_ACL)
 
 #define NFSD_SUPPORTED_ATTRS_WORD1                                                          \
 (FATTR4_WORD1_MODE              | FATTR4_WORD1_NO_TRUNC     | FATTR4_WORD1_NUMLINKS         \
@@ -293,7 +297,8 @@
 (FATTR4_WORD1_TIME_ACCESS_SET   | FATTR4_WORD1_TIME_MODIFY_SET)
 
 /* These are the only attrs allowed in CREATE/OPEN/SETATTR. */
-#define NFSD_WRITEABLE_ATTRS_WORD0                            FATTR4_WORD0_SIZE
+#define NFSD_WRITEABLE_ATTRS_WORD0                                                          \
+(FATTR4_WORD0_SIZE              | FATTR4_WORD0_ACL                                         )
 #define NFSD_WRITEABLE_ATTRS_WORD1                                                          \
 (FATTR4_WORD1_MODE              | FATTR4_WORD1_OWNER         | FATTR4_WORD1_OWNER_GROUP     \
  | FATTR4_WORD1_TIME_ACCESS_SET | FATTR4_WORD1_TIME_METADATA | FATTR4_WORD1_TIME_MODIFY_SET)
diff -Nru a/include/linux/nfsd/state.h b/include/linux/nfsd/state.h
--- a/include/linux/nfsd/state.h	2004-10-18 14:55:54 -07:00
+++ b/include/linux/nfsd/state.h	2004-10-18 14:55:54 -07:00
@@ -218,7 +218,7 @@
 	struct nfs4_stateowner      * st_stateowner;
 	struct nfs4_file            * st_file;
 	stateid_t                     st_stateid;
-	struct file                   st_vfs_file;
+	struct file                 * st_vfs_file;
 	int                           st_vfs_set;
 	unsigned long                 st_access_bmap;
 	unsigned long                 st_deny_bmap;
diff -Nru a/include/linux/nfsd/xdr4.h b/include/linux/nfsd/xdr4.h
--- a/include/linux/nfsd/xdr4.h	2004-10-18 14:56:11 -07:00
+++ b/include/linux/nfsd/xdr4.h	2004-10-18 14:56:11 -07:00
@@ -39,6 +39,8 @@
 #ifndef _LINUX_NFSD_XDR4_H
 #define _LINUX_NFSD_XDR4_H
 
+#include <linux/nfs4.h>
+
 #define NFSD4_MAX_TAGLEN	128
 #define XDR_LEN(n)                     (((n) + 3) & ~3)
 
@@ -95,6 +97,7 @@
 	u32		cr_bmval[2];        /* request */
 	struct iattr	cr_iattr;           /* request */
 	struct nfsd4_change_info  cr_cinfo; /* response */
+	struct nfs4_acl *cr_acl;
 };
 #define cr_linklen	u.link.namelen
 #define cr_linkname	u.link.name
@@ -216,7 +219,7 @@
 	u32		op_rflags;          /* response */
 	int		op_truncate;        /* used during processing */
 	struct nfs4_stateowner *op_stateowner; /* used during processing */
-
+	struct nfs4_acl *op_acl;
 };
 #define op_iattr	u.iattr
 #define op_verf		u.verf
@@ -291,6 +294,7 @@
 	stateid_t	sa_stateid;         /* request */
 	u32		sa_bmval[2];        /* request */
 	struct iattr	sa_iattr;           /* request */
+	struct nfs4_acl *sa_acl;
 };
 
 struct nfsd4_setclientid {
diff -Nru a/include/linux/nls.h b/include/linux/nls.h
--- a/include/linux/nls.h	2004-10-18 14:56:28 -07:00
+++ b/include/linux/nls.h	2004-10-18 14:56:28 -07:00
@@ -33,6 +33,31 @@
 extern int utf8_wctomb(__u8 *, wchar_t, int);
 extern int utf8_wcstombs(__u8 *, const wchar_t *, int);
 
+static inline unsigned char nls_tolower(struct nls_table *t, unsigned char c)
+{
+	unsigned char nc = t->charset2lower[c];
+
+	return nc ? nc : c;
+}
+
+static inline unsigned char nls_toupper(struct nls_table *t, unsigned char c)
+{
+	unsigned char nc = t->charset2upper[c];
+
+	return nc ? nc : c;
+}
+
+static inline int nls_strnicmp(struct nls_table *t, const unsigned char *s1,
+		const unsigned char *s2, int len)
+{
+	while (len--) {
+		if (nls_tolower(t, *s1++) != nls_tolower(t, *s2++))
+			return 1;
+	}
+
+	return 0;
+}
+
 #define MODULE_ALIAS_NLS(name)	MODULE_ALIAS("nls_" __stringify(name))
 
 #endif /* _LINUX_NLS_H */
diff -Nru a/include/linux/node.h b/include/linux/node.h
--- a/include/linux/node.h	2004-10-18 14:57:04 -07:00
+++ b/include/linux/node.h	2004-10-18 14:57:04 -07:00
@@ -23,7 +23,6 @@
 #include <linux/cpumask.h>
 
 struct node {
-	cpumask_t cpumap;	/* Bitmap of CPUs on the Node */
 	struct sys_device	sysdev;
 };
 
diff -Nru a/include/linux/notifier.h b/include/linux/notifier.h
--- a/include/linux/notifier.h	2004-10-18 14:55:54 -07:00
+++ b/include/linux/notifier.h	2004-10-18 14:55:54 -07:00
@@ -29,6 +29,10 @@
 #define NOTIFY_OK		0x0001		/* Suits me */
 #define NOTIFY_STOP_MASK	0x8000		/* Don't call further */
 #define NOTIFY_BAD		(NOTIFY_STOP_MASK|0x0002)	/* Bad/Veto action	*/
+/*
+ * Clean way to return from the notifier and stop further calls.
+ */
+#define NOTIFY_STOP		(NOTIFY_OK|NOTIFY_STOP_MASK)
 
 /*
  *	Declared notifiers so far. I can imagine quite a few more chains
diff -Nru a/include/linux/page-flags.h b/include/linux/page-flags.h
--- a/include/linux/page-flags.h	2004-10-18 14:56:48 -07:00
+++ b/include/linux/page-flags.h	2004-10-18 14:56:48 -07:00
@@ -69,14 +69,11 @@
 #define PG_private		12	/* Has something at ->private */
 #define PG_writeback		13	/* Page is under writeback */
 #define PG_nosave		14	/* Used for system suspend/resume */
-#define PG_maplock		15	/* Lock bit for rmap to ptes */
+#define PG_compound		15	/* Part of a compound page */
 
 #define PG_swapcache		16	/* Swap page: swp_entry_t in private */
 #define PG_mappedtodisk		17	/* Has blocks allocated on-disk */
 #define PG_reclaim		18	/* To be reclaimed asap */
-#define PG_compound		19	/* Part of a compound page */
-
-#define PG_anon			20	/* Anonymous: anon_vma in mapping */
 
 
 /*
@@ -236,6 +233,7 @@
 #define PageReserved(page)	test_bit(PG_reserved, &(page)->flags)
 #define SetPageReserved(page)	set_bit(PG_reserved, &(page)->flags)
 #define ClearPageReserved(page)	clear_bit(PG_reserved, &(page)->flags)
+#define __ClearPageReserved(page)	__clear_bit(PG_reserved, &(page)->flags)
 
 #define SetPagePrivate(page)	set_bit(PG_private, &(page)->flags)
 #define ClearPagePrivate(page)	clear_bit(PG_private, &(page)->flags)
@@ -291,10 +289,6 @@
 #define PageCompound(page)	test_bit(PG_compound, &(page)->flags)
 #define SetPageCompound(page)	set_bit(PG_compound, &(page)->flags)
 #define ClearPageCompound(page)	clear_bit(PG_compound, &(page)->flags)
-
-#define PageAnon(page)		test_bit(PG_anon, &(page)->flags)
-#define SetPageAnon(page)	set_bit(PG_anon, &(page)->flags)
-#define ClearPageAnon(page)	clear_bit(PG_anon, &(page)->flags)
 
 #ifdef CONFIG_SWAP
 #define PageSwapCache(page)	test_bit(PG_swapcache, &(page)->flags)
diff -Nru a/include/linux/pagemap.h b/include/linux/pagemap.h
--- a/include/linux/pagemap.h	2004-10-18 14:55:54 -07:00
+++ b/include/linux/pagemap.h	2004-10-18 14:55:54 -07:00
@@ -156,6 +156,7 @@
 
 static inline void lock_page(struct page *page)
 {
+	might_sleep();
 	if (TestSetPageLocked(page))
 		__lock_page(page);
 }
diff -Nru a/include/linux/pci.h b/include/linux/pci.h
--- a/include/linux/pci.h	2004-10-18 14:56:29 -07:00
+++ b/include/linux/pci.h	2004-10-18 14:56:29 -07:00
@@ -536,7 +536,7 @@
 	unsigned int	is_enabled:1;	/* pci_enable_device has been called */
 	unsigned int	is_busmaster:1; /* device is busmaster */
 	
-	unsigned int 	saved_config_space[16]; /* config space saved at suspend time */
+	u32		saved_config_space[16]; /* config space saved at suspend time */
 #ifdef CONFIG_PCI_NAMES
 #define PCI_NAME_SIZE	96
 #define PCI_NAME_HALF	__stringify(43)	/* less than half to handle slop */
@@ -712,7 +712,7 @@
 int pci_get_interrupt_pin(struct pci_dev *dev, struct pci_dev **bridge);
 extern struct pci_dev *pci_dev_get(struct pci_dev *dev);
 extern void pci_dev_put(struct pci_dev *dev);
-
+extern void pci_remove_bus(struct pci_bus *b);
 extern void pci_remove_bus_device(struct pci_dev *dev);
 
 /* Generic PCI functions exported to card drivers */
@@ -1001,17 +1001,27 @@
  */
 
 struct pci_fixup {
-	int pass;
 	u16 vendor, device;			/* You can use PCI_ANY_ID here of course */
 	void (*hook)(struct pci_dev *dev);
 };
 
-extern struct pci_fixup pcibios_fixups[];
+enum pci_fixup_pass {
+	pci_fixup_header,	/* Called immediately after reading configuration header */
+	pci_fixup_final,	/* Final phase of device fixups */
+};
 
-#define PCI_FIXUP_HEADER	1		/* Called immediately after reading configuration header */
-#define PCI_FIXUP_FINAL		2		/* Final phase of device fixups */
+/* Anonymous variables would be nice... */
+#define DECLARE_PCI_FIXUP_HEADER(vendor, device, hook)					\
+	static struct pci_fixup __pci_fixup_##vendor##device##hook __attribute_used__	\
+	__attribute__((__section__(".pci_fixup_header"))) = {				\
+		vendor, device, hook };
+
+#define DECLARE_PCI_FIXUP_FINAL(vendor, device, hook)				\
+	static struct pci_fixup __pci_fixup_##vendor##device##hook __attribute_used__	\
+	__attribute__((__section__(".pci_fixup_final"))) = {				\
+		vendor, device, hook };
 
-void pci_fixup_device(int pass, struct pci_dev *dev);
+void pci_fixup_device(enum pci_fixup_pass pass, struct pci_dev *dev);
 
 extern int pci_pci_problems;
 #define PCIPCI_FAIL		1
diff -Nru a/include/linux/pci_ids.h b/include/linux/pci_ids.h
--- a/include/linux/pci_ids.h	2004-10-18 14:57:19 -07:00
+++ b/include/linux/pci_ids.h	2004-10-18 14:57:19 -07:00
@@ -438,8 +438,14 @@
 #define	PCI_DEVICE_ID_IBM_405GP		0x0156
 #define PCI_DEVICE_ID_IBM_SNIPE		0x0180
 #define PCI_DEVICE_ID_IBM_SERVERAIDI960	0x01bd
+#define PCI_DEVICE_ID_IBM_CITRINE		0x028C
 #define PCI_DEVICE_ID_IBM_GEMSTONE		0xB166
 #define PCI_DEVICE_ID_IBM_MPIC_2	0xffff
+#define PCI_DEVICE_ID_IBM_ICOM_DEV_ID_1	0x0031
+#define PCI_DEVICE_ID_IBM_ICOM_DEV_ID_2	0x0219
+#define PCI_DEVICE_ID_IBM_ICOM_V2_TWO_PORTS_RVX		0x021A
+#define PCI_DEVICE_ID_IBM_ICOM_V2_ONE_PORT_RVX_ONE_PORT_MDM	0x0251
+#define PCI_DEVICE_ID_IBM_ICOM_FOUR_PORT_MODEL	0x252
 
 #define PCI_VENDOR_ID_COMPEX2		0x101a // pci.ids says "AT&T GIS (NCR)"
 #define PCI_DEVICE_ID_COMPEX2_100VG	0x0005
@@ -670,6 +676,7 @@
 #define PCI_DEVICE_ID_HP_SX1000_IOC	0x127c
 #define PCI_DEVICE_ID_HP_DIVA_EVEREST	0x1282
 #define PCI_DEVICE_ID_HP_DIVA_AUX	0x1290
+#define PCI_DEVICE_ID_HP_CISS		0x3210
 
 #define PCI_VENDOR_ID_PCTECH		0x1042
 #define PCI_DEVICE_ID_PCTECH_RZ1000	0x1000
@@ -727,6 +734,7 @@
 #define PCI_DEVICE_ID_TI_1251B		0xac1f
 #define PCI_DEVICE_ID_TI_4410		0xac41
 #define PCI_DEVICE_ID_TI_4451		0xac42
+#define PCI_DEVICE_ID_TI_4520		0xac46
 #define PCI_DEVICE_ID_TI_1410		0xac50
 #define PCI_DEVICE_ID_TI_1420		0xac51
 #define PCI_DEVICE_ID_TI_1451A		0xac52
@@ -1071,6 +1079,7 @@
 #define PCI_DEVICE_ID_NVIDIA_NFORCE_CK804_SATA2	0x0055
 #define PCI_DEVICE_ID_NVIDIA_NVENET_8		0x0056
 #define PCI_DEVICE_ID_NVIDIA_NVENET_9		0x0057
+#define PCI_DEVICE_ID_NVIDIA_CK804_AUDIO	0x0059
 #define PCI_DEVICE_ID_NVIDIA_NFORCE2_IDE	0x0065
 #define PCI_DEVICE_ID_NVIDIA_NVENET_2		0x0066
 #define PCI_DEVICE_ID_NVIDIA_MCP2_AUDIO		0x006a
@@ -1234,6 +1243,7 @@
 #define PCI_DEVICE_ID_VIA_8233C_0	0x3109
 #define PCI_DEVICE_ID_VIA_8361		0x3112
 #define PCI_DEVICE_ID_VIA_XM266		0x3116
+#define PCI_DEVICE_ID_VIA_612X		0x3119
 #define PCI_DEVICE_ID_VIA_862X_0	0x3123
 #define PCI_DEVICE_ID_VIA_8753_0	0x3128
 #define PCI_DEVICE_ID_VIA_8233A		0x3147
@@ -1798,6 +1808,11 @@
 #define PCI_DEVICE_ID_CCD_B00C		0xb00c
 #define PCI_DEVICE_ID_CCD_B100		0xb100
 
+#define PCI_VENDOR_ID_EXAR		0x13a8
+#define PCI_DEVICE_ID_EXAR_XR17C152	0x0152
+#define PCI_DEVICE_ID_EXAR_XR17C154	0x0154
+#define PCI_DEVICE_ID_EXAR_XR17C158	0x0158
+
 #define PCI_VENDOR_ID_MICROGATE		0x13c0
 #define PCI_DEVICE_ID_MICROGATE_USC	0x0010
 #define PCI_DEVICE_ID_MICROGATE_SCC	0x0020
@@ -2228,7 +2243,9 @@
 #define PCI_DEVICE_ID_INTEL_82451NX	0x84ca
 #define PCI_DEVICE_ID_INTEL_82454NX     0x84cb
 #define PCI_DEVICE_ID_INTEL_84460GX	0x84ea
-#define	PCI_DEVICE_ID_INTEL_IXP4XX	0x8500
+#define PCI_DEVICE_ID_INTEL_IXP4XX	0x8500
+#define PCI_DEVICE_ID_INTEL_IXP2400	0x9001
+#define PCI_DEVICE_ID_INTEL_IXP2800	0x9004
 
 #define PCI_VENDOR_ID_COMPUTONE		0x8e0e
 #define PCI_DEVICE_ID_COMPUTONE_IP2EX	0x0291
@@ -2299,6 +2316,8 @@
 #define PCI_DEVICE_ID_NETMOS_9815	0x9815
 #define PCI_DEVICE_ID_NETMOS_9835	0x9835
 #define PCI_DEVICE_ID_NETMOS_9855	0x9855
+#define PCI_DEVICE_ID_NETMOS_9755	0x9755
+#define PCI_DEVICE_ID_NETMOS_9715	0x9715
 
 #define PCI_SUBVENDOR_ID_EXSYS		0xd84d
 #define PCI_SUBDEVICE_ID_EXSYS_4014	0x4014
diff -Nru a/include/linux/percpu.h b/include/linux/percpu.h
--- a/include/linux/percpu.h	2004-10-18 14:57:03 -07:00
+++ b/include/linux/percpu.h	2004-10-18 14:57:03 -07:00
@@ -24,8 +24,8 @@
 
 /* 
  * Use this to get to a cpu's version of the per-cpu object allocated using
- * alloc_percpu.  If you want to get "this cpu's version", maybe you want
- * to use get_cpu_ptr... 
+ * alloc_percpu.  Non-atomic access to the current CPU's version should
+ * probably be combined with get_cpu()/put_cpu().
  */ 
 #define per_cpu_ptr(ptr, cpu)                   \
 ({                                              \
@@ -57,27 +57,5 @@
 /* Simple wrapper for the common case: zeros memory. */
 #define alloc_percpu(type) \
 	((type *)(__alloc_percpu(sizeof(type), __alignof__(type))))
-
-/* 
- * Use these with alloc_percpu. If
- * 1. You want to operate on memory allocated by alloc_percpu (dereference
- *    and read/modify/write)  AND 
- * 2. You want "this cpu's version" of the object AND 
- * 3. You want to do this safely since:
- *    a. On multiprocessors, you don't want to switch between cpus after 
- *    you've read the current processor id due to preemption -- this would 
- *    take away the implicit  advantage to not have any kind of traditional 
- *    serialization for per-cpu data
- *    b. On uniprocessors, you don't want another kernel thread messing
- *    up with the same per-cpu data due to preemption
- *    
- * So, Use get_cpu_ptr to disable preemption and get pointer to the 
- * local cpu version of the per-cpu object. Use put_cpu_ptr to enable
- * preemption.  Operations on per-cpu data between get_ and put_ is
- * then considered to be safe. And ofcourse, "Thou shalt not sleep between 
- * get_cpu_ptr and put_cpu_ptr"
- */
-#define get_cpu_ptr(ptr) per_cpu_ptr(ptr, get_cpu())
-#define put_cpu_ptr(ptr) put_cpu()
 
 #endif /* __LINUX_PERCPU_H */
diff -Nru a/include/linux/personality.h b/include/linux/personality.h
--- a/include/linux/personality.h	2004-10-18 14:56:32 -07:00
+++ b/include/linux/personality.h	2004-10-18 14:56:32 -07:00
@@ -12,17 +12,6 @@
 extern int		unregister_exec_domain(struct exec_domain *);
 extern int		__set_personality(unsigned long);
 
-
-/*
- * Sysctl variables related to binary emulation.
- */
-extern unsigned long abi_defhandler_coff;
-extern unsigned long abi_defhandler_elf;
-extern unsigned long abi_defhandler_lcall7;
-extern unsigned long abi_defhandler_libcso;
-extern int abi_fake_utsname;
-
-
 /*
  * Flags for bug emulation.
  *
@@ -30,6 +19,7 @@
  */
 enum {
 	MMAP_PAGE_ZERO =	0x0100000,
+	ADDR_COMPAT_LAYOUT =	0x0200000,
 	READ_IMPLIES_EXEC =	0x0400000,
 	ADDR_LIMIT_32BIT =	0x0800000,
 	SHORT_INODE =		0x1000000,
diff -Nru a/include/linux/pfkeyv2.h b/include/linux/pfkeyv2.h
--- a/include/linux/pfkeyv2.h	2004-10-18 14:56:50 -07:00
+++ b/include/linux/pfkeyv2.h	2004-10-18 14:56:50 -07:00
@@ -245,6 +245,7 @@
 
 /* Security Association flags */
 #define SADB_SAFLAGS_PFS	1
+#define SADB_SAFLAGS_DECAP_DSCP	0x40000000
 #define SADB_SAFLAGS_NOECN	0x80000000
 
 /* Security Association states */
diff -Nru a/include/linux/pid.h b/include/linux/pid.h
--- a/include/linux/pid.h	2004-10-18 14:56:20 -07:00
+++ b/include/linux/pid.h	2004-10-18 14:56:20 -07:00
@@ -12,34 +12,22 @@
 
 struct pid
 {
+	/* Try to keep pid_chain in the same cacheline as nr for find_pid */
 	int nr;
-	atomic_t count;
-	struct task_struct *task;
-	struct list_head task_list;
-	struct list_head hash_chain;
-};
-
-struct pid_link
-{
-	struct list_head pid_chain;
-	struct pid *pidptr;
-	struct pid pid;
+	struct hlist_node pid_chain;
+	/* list of pids with the same nr, only one of them is in the hash */
+	struct list_head pid_list;
 };
 
 #define pid_task(elem, type) \
-	list_entry(elem, struct task_struct, pids[type].pid_chain)
+	list_entry(elem, struct task_struct, pids[type].pid_list)
 
 /*
- * attach_pid() and link_pid() must be called with the tasklist_lock
+ * attach_pid() and detach_pid() must be called with the tasklist_lock
  * write-held.
  */
 extern int FASTCALL(attach_pid(struct task_struct *task, enum pid_type type, int nr));
 
-extern void FASTCALL(link_pid(struct task_struct *task, struct pid_link *link, struct pid *pid));
-
-/*
- * detach_pid() must be called with the tasklist_lock write-held.
- */
 extern void FASTCALL(detach_pid(struct task_struct *task, enum pid_type));
 
 /*
@@ -52,13 +40,16 @@
 extern void FASTCALL(free_pidmap(int));
 extern void switch_exec_pids(struct task_struct *leader, struct task_struct *thread);
 
-#define for_each_task_pid(who, type, task, elem, pid)		\
-	if ((pid = find_pid(type, who)))			\
-	        for (elem = pid->task_list.next,			\
-			prefetch(elem->next),				\
-			task = pid_task(elem, type);			\
-			elem != &pid->task_list;			\
-			elem = elem->next, prefetch(elem->next), 	\
-			task = pid_task(elem, type))
+#define do_each_task_pid(who, type, task)				\
+	if ((task = find_task_by_pid_type(type, who))) {		\
+		prefetch((task)->pids[type].pid_list.next);		\
+		do {
+
+#define while_each_task_pid(who, type, task)				\
+		} while (task = pid_task((task)->pids[type].pid_list.next,\
+						type),			\
+			prefetch((task)->pids[type].pid_list.next),	\
+			hlist_unhashed(&(task)->pids[type].pid_chain));	\
+	}								\
 
 #endif /* _LINUX_PID_H */
diff -Nru a/include/linux/pkt_sched.h b/include/linux/pkt_sched.h
--- a/include/linux/pkt_sched.h	2004-10-18 14:56:48 -07:00
+++ b/include/linux/pkt_sched.h	2004-10-18 14:56:48 -07:00
@@ -402,6 +402,16 @@
 #define TCA_ATM_MAX	TCA_ATM_STATE
 
 /* Network emulator */
+
+enum
+{
+	TCA_NETEM_UNSPEC,
+	TCA_NETEM_CORR,
+	TCA_NETEM_DELAY_DIST,
+};
+
+#define TCA_NETEM_MAX	TCA_NETEM_DELAY_DIST
+
 struct tc_netem_qopt
 {
 	__u32	latency;	/* added delay (us) */
@@ -411,4 +421,14 @@
 	__u32   duplicate;	/* random packet dup  (0=none ~0=100%) */
 	__u32	jitter;		/* random jitter in latency (us) */
 };
+
+struct tc_netem_corr
+{
+	__u32	delay_corr;	/* delay correlation */
+	__u32	loss_corr;	/* packet loss correlation */
+	__u32	dup_corr;	/* duplicate correlation  */
+};
+
+#define NETEM_DIST_SCALE	8192
+
 #endif
diff -Nru a/include/linux/pm.h b/include/linux/pm.h
--- a/include/linux/pm.h	2004-10-18 14:56:33 -07:00
+++ b/include/linux/pm.h	2004-10-18 14:56:33 -07:00
@@ -194,11 +194,12 @@
 extern void (*pm_power_off)(void);
 
 enum {
-	PM_SUSPEND_ON,
-	PM_SUSPEND_STANDBY,
-	PM_SUSPEND_MEM,
-	PM_SUSPEND_DISK,
-	PM_SUSPEND_MAX,
+	PM_SUSPEND_ON = 0,
+	PM_SUSPEND_STANDBY = 1,
+	/* NOTE: PM_SUSPEND_MEM == PCI_D3hot */
+	PM_SUSPEND_MEM = 3,
+	PM_SUSPEND_DISK = 4,
+	PM_SUSPEND_MAX = 5,
 };
 
 enum {
diff -Nru a/include/linux/poll.h b/include/linux/poll.h
--- a/include/linux/poll.h	2004-10-18 14:57:04 -07:00
+++ b/include/linux/poll.h	2004-10-18 14:57:04 -07:00
@@ -5,6 +5,7 @@
 
 #ifdef __KERNEL__
 
+#include <linux/compiler.h>
 #include <linux/wait.h>
 #include <linux/string.h>
 #include <linux/mm.h>
@@ -81,11 +82,12 @@
 	return 0;
 }
 
-static inline
-void set_fd_set(unsigned long nr, void __user *ufdset, unsigned long *fdset)
+static inline unsigned long __must_check
+set_fd_set(unsigned long nr, void __user *ufdset, unsigned long *fdset)
 {
 	if (ufdset)
-		__copy_to_user(ufdset, fdset, FDS_BYTES(nr));
+		return __copy_to_user(ufdset, fdset, FDS_BYTES(nr));
+	return 0;
 }
 
 static inline
diff -Nru a/include/linux/prctl.h b/include/linux/prctl.h
--- a/include/linux/prctl.h	2004-10-18 14:56:32 -07:00
+++ b/include/linux/prctl.h	2004-10-18 14:56:32 -07:00
@@ -50,4 +50,6 @@
                                                    process timing */
 
 
+#define PR_SET_NAME    15		/* Set process name */
+
 #endif /* _LINUX_PRCTL_H */
diff -Nru a/include/linux/prio_tree.h b/include/linux/prio_tree.h
--- a/include/linux/prio_tree.h	2004-10-18 14:56:31 -07:00
+++ b/include/linux/prio_tree.h	2004-10-18 14:56:31 -07:00
@@ -17,7 +17,19 @@
 	unsigned long		mask;
 	unsigned long		value;
 	int			size_level;
+
+	struct prio_tree_root	*root;
+	pgoff_t			r_index;
+	pgoff_t			h_index;
 };
+
+static inline void prio_tree_iter_init(struct prio_tree_iter *iter,
+		struct prio_tree_root *root, pgoff_t r_index, pgoff_t h_index)
+{
+	iter->root = root;
+	iter->r_index = r_index;
+	iter->h_index = h_index;
+}
 
 #define INIT_PRIO_TREE_ROOT(ptr)	\
 do {					\
diff -Nru a/include/linux/proc_fs.h b/include/linux/proc_fs.h
--- a/include/linux/proc_fs.h	2004-10-18 14:57:19 -07:00
+++ b/include/linux/proc_fs.h	2004-10-18 14:57:19 -07:00
@@ -79,6 +79,7 @@
 extern struct proc_dir_entry proc_root;
 extern struct proc_dir_entry *proc_root_fs;
 extern struct proc_dir_entry *proc_net;
+extern struct proc_dir_entry *proc_net_stat;
 extern struct proc_dir_entry *proc_bus;
 extern struct proc_dir_entry *proc_root_driver;
 extern struct proc_dir_entry *proc_root_kcore;
@@ -86,10 +87,15 @@
 extern void proc_root_init(void);
 extern void proc_misc_init(void);
 
+struct mm_struct;
+
 struct dentry *proc_pid_lookup(struct inode *dir, struct dentry * dentry, struct nameidata *);
 struct dentry *proc_pid_unhash(struct task_struct *p);
 void proc_pid_flush(struct dentry *proc_dentry);
 int proc_pid_readdir(struct file * filp, void * dirent, filldir_t filldir);
+unsigned long task_vsize(struct mm_struct *);
+int task_statm(struct mm_struct *, int *, int *, int *, int *);
+char *task_mem(struct mm_struct *, char *);
 
 extern struct proc_dir_entry *create_proc_entry(const char *name, mode_t mode,
 						struct proc_dir_entry *parent);
@@ -201,14 +207,13 @@
 #define remove_proc_entry(name, parent) do {} while (0)
 
 static inline struct proc_dir_entry *proc_symlink(const char *name,
-		struct proc_dir_entry *parent,char *dest) {return NULL;}
+		struct proc_dir_entry *parent,const char *dest) {return NULL;}
 static inline struct proc_dir_entry *proc_mkdir(const char *name,
 	struct proc_dir_entry *parent) {return NULL;}
 
 static inline struct proc_dir_entry *create_proc_read_entry(const char *name,
 	mode_t mode, struct proc_dir_entry *base, 
-	int (*read_proc)(char *, char **, off_t, int, int *, void *),
-	void * data) { return NULL; }
+	read_proc_t *read_proc, void * data) { return NULL; }
 static inline struct proc_dir_entry *create_proc_info_entry(const char *name,
 	mode_t mode, struct proc_dir_entry *base, get_info_t *get_info)
 	{ return NULL; }
diff -Nru a/include/linux/profile.h b/include/linux/profile.h
--- a/include/linux/profile.h	2004-10-18 14:56:29 -07:00
+++ b/include/linux/profile.h	2004-10-18 14:56:29 -07:00
@@ -6,24 +6,28 @@
 #include <linux/kernel.h>
 #include <linux/config.h>
 #include <linux/init.h>
+#include <linux/cpumask.h>
 #include <asm/errno.h>
 
-/* parse command line */
-int __init profile_setup(char * str);
+#define CPU_PROFILING	1
+#define SCHED_PROFILING	2
+
+struct proc_dir_entry;
+struct pt_regs;
 
 /* init basic kernel profiler */
 void __init profile_init(void);
-
-extern unsigned int * prof_buffer;
-extern unsigned long prof_len;
-extern unsigned long prof_shift;
-extern int prof_on;
-
+void profile_tick(int, struct pt_regs *);
+void profile_hit(int, void *);
+#ifdef CONFIG_PROC_FS
+void create_prof_cpu_mask(struct proc_dir_entry *);
+#else
+#define create_prof_cpu_mask(x)			do { (void)(x); } while (0)
+#endif
 
 enum profile_type {
-	EXIT_TASK,
-	EXIT_MMAP,
-	EXEC_UNMAP
+	PROFILE_TASK_EXIT,
+	PROFILE_MUNMAP
 };
 
 #ifdef CONFIG_PROFILING
@@ -33,16 +37,20 @@
 struct mm_struct;
 
 /* task is in do_exit() */
-void profile_exit_task(struct task_struct * task);
+void profile_task_exit(struct task_struct * task);
 
-/* change of vma mappings */
-void profile_exec_unmap(struct mm_struct * mm);
+/* task is dead, free task struct ? Returns 1 if
+ * the task was taken, 0 if the task should be freed.
+ */
+int profile_handoff_task(struct task_struct * task);
 
-/* exit of all vmas for a task */
-void profile_exit_mmap(struct mm_struct * mm);
+/* sys_munmap */
+void profile_munmap(unsigned long addr);
 
-int profile_event_register(enum profile_type, struct notifier_block * n);
+int task_handoff_register(struct notifier_block * n);
+int task_handoff_unregister(struct notifier_block * n);
 
+int profile_event_register(enum profile_type, struct notifier_block * n);
 int profile_event_unregister(enum profile_type, struct notifier_block * n);
 
 int register_profile_notifier(struct notifier_block * nb);
@@ -55,6 +63,16 @@
 
 #else
 
+static inline int task_handoff_register(struct notifier_block * n)
+{
+	return -ENOSYS;
+}
+
+static inline int task_handoff_unregister(struct notifier_block * n)
+{
+	return -ENOSYS;
+}
+
 static inline int profile_event_register(enum profile_type t, struct notifier_block * n)
 {
 	return -ENOSYS;
@@ -65,9 +83,9 @@
 	return -ENOSYS;
 }
 
-#define profile_exit_task(a) do { } while (0)
-#define profile_exec_unmap(a) do { } while (0)
-#define profile_exit_mmap(a) do { } while (0)
+#define profile_task_exit(a) do { } while (0)
+#define profile_handoff_task(a) (0)
+#define profile_munmap(a) do { } while (0)
 
 static inline int register_profile_notifier(struct notifier_block * nb)
 {
diff -Nru a/include/linux/quota.h b/include/linux/quota.h
--- a/include/linux/quota.h	2004-10-18 14:56:49 -07:00
+++ b/include/linux/quota.h	2004-10-18 14:56:49 -07:00
@@ -45,7 +45,6 @@
 typedef __kernel_uid32_t qid_t; /* Type in which we store ids in memory */
 typedef __u64 qsize_t;          /* Type in which we store sizes */
 
-extern spinlock_t dq_list_lock;
 extern spinlock_t dq_data_lock;
 
 /* Size of blocks in which are counted size limits */
diff -Nru a/include/linux/quotaio_v2.h b/include/linux/quotaio_v2.h
--- a/include/linux/quotaio_v2.h	2004-10-18 14:56:32 -07:00
+++ b/include/linux/quotaio_v2.h	2004-10-18 14:56:32 -07:00
@@ -27,15 +27,15 @@
  * to blocks of these structures.
  */
 struct v2_disk_dqblk {
-	__u32 dqb_id;		/* id this quota applies to */
-	__u32 dqb_ihardlimit;	/* absolute limit on allocated inodes */
-	__u32 dqb_isoftlimit;	/* preferred inode limit */
-	__u32 dqb_curinodes;	/* current # allocated inodes */
-	__u32 dqb_bhardlimit;	/* absolute limit on disk space (in QUOTABLOCK_SIZE) */
-	__u32 dqb_bsoftlimit;	/* preferred limit on disk space (in QUOTABLOCK_SIZE) */
-	__u64 dqb_curspace;	/* current space occupied (in bytes) */
-	__u64 dqb_btime;	/* time limit for excessive disk use */
-	__u64 dqb_itime;	/* time limit for excessive inode use */
+	__le32 dqb_id;		/* id this quota applies to */
+	__le32 dqb_ihardlimit;	/* absolute limit on allocated inodes */
+	__le32 dqb_isoftlimit;	/* preferred inode limit */
+	__le32 dqb_curinodes;	/* current # allocated inodes */
+	__le32 dqb_bhardlimit;	/* absolute limit on disk space (in QUOTABLOCK_SIZE) */
+	__le32 dqb_bsoftlimit;	/* preferred limit on disk space (in QUOTABLOCK_SIZE) */
+	__le64 dqb_curspace;	/* current space occupied (in bytes) */
+	__le64 dqb_btime;	/* time limit for excessive disk use */
+	__le64 dqb_itime;	/* time limit for excessive inode use */
 };
 
 /*
@@ -43,18 +43,18 @@
  */
 /* First generic header */
 struct v2_disk_dqheader {
-	__u32 dqh_magic;	/* Magic number identifying file */
-	__u32 dqh_version;	/* File version */
+	__le32 dqh_magic;	/* Magic number identifying file */
+	__le32 dqh_version;	/* File version */
 };
 
 /* Header with type and version specific information */
 struct v2_disk_dqinfo {
-	__u32 dqi_bgrace;	/* Time before block soft limit becomes hard limit */
-	__u32 dqi_igrace;	/* Time before inode soft limit becomes hard limit */
-	__u32 dqi_flags;	/* Flags for quotafile (DQF_*) */
-	__u32 dqi_blocks;	/* Number of blocks in file */
-	__u32 dqi_free_blk;	/* Number of first free block in the list */
-	__u32 dqi_free_entry;	/* Number of block with at least one free entry */
+	__le32 dqi_bgrace;	/* Time before block soft limit becomes hard limit */
+	__le32 dqi_igrace;	/* Time before inode soft limit becomes hard limit */
+	__le32 dqi_flags;	/* Flags for quotafile (DQF_*) */
+	__le32 dqi_blocks;	/* Number of blocks in file */
+	__le32 dqi_free_blk;	/* Number of first free block in the list */
+	__le32 dqi_free_entry;	/* Number of block with at least one free entry */
 };
 
 /*
@@ -62,11 +62,11 @@
  *  there will be space for exactly 21 quota-entries in a block
  */
 struct v2_disk_dqdbheader {
-	__u32 dqdh_next_free;	/* Number of next block with free entry */
-	__u32 dqdh_prev_free;	/* Number of previous block with free entry */
-	__u16 dqdh_entries;	/* Number of valid entries in block */
-	__u16 dqdh_pad1;
-	__u32 dqdh_pad2;
+	__le32 dqdh_next_free;	/* Number of next block with free entry */
+	__le32 dqdh_prev_free;	/* Number of previous block with free entry */
+	__le16 dqdh_entries;	/* Number of valid entries in block */
+	__le16 dqdh_pad1;
+	__le32 dqdh_pad2;
 };
 
 #define V2_DQINFOOFF	sizeof(struct v2_disk_dqheader)	/* Offset of info header in file */
diff -Nru a/include/linux/raid/md.h b/include/linux/raid/md.h
--- a/include/linux/raid/md.h	2004-10-18 14:55:54 -07:00
+++ b/include/linux/raid/md.h	2004-10-18 14:55:54 -07:00
@@ -69,12 +69,10 @@
 extern void md_unregister_thread (mdk_thread_t *thread);
 extern void md_wakeup_thread(mdk_thread_t *thread);
 extern void md_check_recovery(mddev_t *mddev);
-extern void md_interrupt_thread (mdk_thread_t *thread);
 extern void md_write_start(mddev_t *mddev);
 extern void md_write_end(mddev_t *mddev);
 extern void md_handle_safemode(mddev_t *mddev);
 extern void md_done_sync(mddev_t *mddev, int blocks, int ok);
-extern void md_sync_acct(mdk_rdev_t *rdev, unsigned long nr_sectors);
 extern void md_error (mddev_t *mddev, mdk_rdev_t *rdev);
 extern void md_unplug_mddev(mddev_t *mddev);
 
diff -Nru a/include/linux/raid/md_k.h b/include/linux/raid/md_k.h
--- a/include/linux/raid/md_k.h	2004-10-18 14:55:54 -07:00
+++ b/include/linux/raid/md_k.h	2004-10-18 14:55:54 -07:00
@@ -24,7 +24,8 @@
 #define HSM               6UL
 #define MULTIPATH         7UL
 #define RAID6		  8UL
-#define MAX_PERSONALITY   9UL
+#define	RAID10		  9UL
+#define MAX_PERSONALITY   10UL
 
 #define	LEVEL_MULTIPATH		(-4)
 #define	LEVEL_LINEAR		(-1)
@@ -43,6 +44,7 @@
 		case RAID1:		return 1;
 		case RAID5:		return 5;
 		case RAID6:		return 6;
+		case RAID10:		return 10;
 	}
 	BUG();
 	return MD_RESERVED;
@@ -60,6 +62,7 @@
 		case 4:
 		case 5: return RAID5;
 		case 6: return RAID6;
+		case 10: return RAID10;
 	}
 	return MD_RESERVED;
 }
@@ -216,6 +219,7 @@
 	unsigned long			resync_mark;	/* a recent timestamp */
 	sector_t			resync_mark_cnt;/* blocks written at resync_mark */
 
+	sector_t			resync_max_sectors; /* may be set by personality */
 	/* recovery/resync flags 
 	 * NEEDED:   we might need to start a resync/recover
 	 * RUNNING:  a thread is running, or about to be started
@@ -261,6 +265,11 @@
 	int faulty = rdev->faulty;
 	if (atomic_dec_and_test(&rdev->nr_pending) && faulty)
 		set_bit(MD_RECOVERY_NEEDED, &mddev->recovery);
+}
+
+static inline void md_sync_acct(struct block_device *bdev, unsigned long nr_sectors)
+{
+        atomic_add(nr_sectors, &bdev->bd_contains->bd_disk->sync_io);
 }
 
 struct mdk_personality_s
diff -Nru a/include/linux/raid/raid10.h b/include/linux/raid/raid10.h
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/include/linux/raid/raid10.h	2004-10-18 14:57:24 -07:00
@@ -0,0 +1,103 @@
+#ifndef _RAID10_H
+#define _RAID10_H
+
+#include <linux/raid/md.h>
+
+typedef struct mirror_info mirror_info_t;
+
+struct mirror_info {
+	mdk_rdev_t	*rdev;
+	sector_t	head_position;
+};
+
+typedef struct r10bio_s r10bio_t;
+
+struct r10_private_data_s {
+	mddev_t			*mddev;
+	mirror_info_t		*mirrors;
+	int			raid_disks;
+	int			working_disks;
+	spinlock_t		device_lock;
+
+	/* geometry */
+	int			near_copies;  /* number of copies layed out raid0 style */
+	int 			far_copies;   /* number of copies layed out
+					       * at large strides across drives
+					       */
+	int			copies;	      /* near_copies * far_copies.
+					       * must be <= raid_disks
+					       */
+	sector_t		stride;	      /* distance between far copies.
+					       * This is size / far_copies
+					       */
+
+	int chunk_shift; /* shift from chunks to sectors */
+	sector_t chunk_mask;
+
+	struct list_head	retry_list;
+	/* for use when syncing mirrors: */
+
+	spinlock_t		resync_lock;
+	int nr_pending;
+	int barrier;
+	sector_t		next_resync;
+
+	wait_queue_head_t	wait_idle;
+	wait_queue_head_t	wait_resume;
+
+	mempool_t *r10bio_pool;
+	mempool_t *r10buf_pool;
+};
+
+typedef struct r10_private_data_s conf_t;
+
+/*
+ * this is the only point in the RAID code where we violate
+ * C type safety. mddev->private is an 'opaque' pointer.
+ */
+#define mddev_to_conf(mddev) ((conf_t *) mddev->private)
+
+/*
+ * this is our 'private' RAID10 bio.
+ *
+ * it contains information about what kind of IO operations were started
+ * for this RAID10 operation, and about their status:
+ */
+
+struct r10bio_s {
+	atomic_t		remaining; /* 'have we finished' count,
+					    * used from IRQ handlers
+					    */
+	sector_t		sector;	/* virtual sector number */
+	int			sectors;
+	unsigned long		state;
+	mddev_t			*mddev;
+	/*
+	 * original bio going to /dev/mdx
+	 */
+	struct bio		*master_bio;
+	/*
+	 * if the IO is in READ direction, then this is where we read
+	 */
+	int			read_slot;
+
+	struct list_head	retry_list;
+	/*
+	 * if the IO is in WRITE direction, then multiple bios are used,
+	 * one for each copy.
+	 * When resyncing we also use one for each copy.
+	 * When reconstructing, we use 2 bios, one for read, one for write.
+	 * We choose the number when they are allocated.
+	 */
+	struct {
+		struct bio		*bio;
+		sector_t addr;
+		int devnum;
+	} devs[0];
+};
+
+/* bits for r10bio.state */
+#define	R10BIO_Uptodate	0
+#define	R10BIO_IsSync	1
+#define	R10BIO_IsRecover 2
+#endif
diff -Nru a/include/linux/ramfs.h b/include/linux/ramfs.h
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/include/linux/ramfs.h	2004-10-18 14:57:24 -07:00
@@ -0,0 +1,11 @@
+#ifndef _LINUX_RAMFS_H
+#define _LINUX_RAMFS_H
+
+struct inode *ramfs_get_inode(struct super_block *sb, int mode, dev_t dev);
+struct super_block *ramfs_get_sb(struct file_system_type *fs_type,
+	 int flags, const char *dev_name, void *data);
+
+extern struct file_operations ramfs_file_operations;
+extern struct vm_operations_struct generic_file_vm_ops;
+
+#endif
diff -Nru a/include/linux/random.h b/include/linux/random.h
--- a/include/linux/random.h	2004-10-18 14:57:04 -07:00
+++ b/include/linux/random.h	2004-10-18 14:57:04 -07:00
@@ -67,8 +67,6 @@
 extern __u32 secure_tcpv6_sequence_number(__u32 *saddr, __u32 *daddr,
 					  __u16 sport, __u16 dport);
 
-extern __u32 secure_ipv6_id(__u32 *daddr);
-
 #ifndef MODULE
 extern struct file_operations random_fops, urandom_fops;
 #endif
diff -Nru a/include/linux/rbtree.h b/include/linux/rbtree.h
--- a/include/linux/rbtree.h	2004-10-18 14:56:28 -07:00
+++ b/include/linux/rbtree.h	2004-10-18 14:56:28 -07:00
@@ -123,6 +123,7 @@
 extern struct rb_node *rb_next(struct rb_node *);
 extern struct rb_node *rb_prev(struct rb_node *);
 extern struct rb_node *rb_first(struct rb_root *);
+extern struct rb_node *rb_last(struct rb_root *);
 
 /* Fast replacement of a single node without remove/rebalance/add/rebalance */
 extern void rb_replace_node(struct rb_node *victim, struct rb_node *new, 
diff -Nru a/include/linux/rcupdate.h b/include/linux/rcupdate.h
--- a/include/linux/rcupdate.h	2004-10-18 14:56:21 -07:00
+++ b/include/linux/rcupdate.h	2004-10-18 14:56:21 -07:00
@@ -87,61 +87,165 @@
  */
 struct rcu_data {
 	/* 1) quiescent state handling : */
-        long		quiescbatch;     /* Batch # for grace period */
+	long		quiescbatch;     /* Batch # for grace period */
 	long		qsctr;		 /* User-mode/idle loop etc. */
-        long            last_qsctr;	 /* value of qsctr at beginning */
-                                         /* of rcu grace period */
+	long            last_qsctr;	 /* value of qsctr at beginning */
+					 /* of rcu grace period */
 	int		qs_pending;	 /* core waits for quiesc state */
 
 	/* 2) batch handling */
-        long  	       	batch;           /* Batch # for current RCU batch */
-        struct rcu_head *nxtlist;
+	long  	       	batch;           /* Batch # for current RCU batch */
+	struct rcu_head *nxtlist;
 	struct rcu_head **nxttail;
-        struct rcu_head *curlist;
+	struct rcu_head *curlist;
+	struct rcu_head **curtail;
+	struct rcu_head *donelist;
+	struct rcu_head **donetail;
+	int cpu;
 };
 
 DECLARE_PER_CPU(struct rcu_data, rcu_data);
+DECLARE_PER_CPU(struct rcu_data, rcu_bh_data);
 extern struct rcu_ctrlblk rcu_ctrlblk;
+extern struct rcu_ctrlblk rcu_bh_ctrlblk;
 
-#define RCU_quiescbatch(cpu)	(per_cpu(rcu_data, (cpu)).quiescbatch)
-#define RCU_qsctr(cpu) 		(per_cpu(rcu_data, (cpu)).qsctr)
-#define RCU_last_qsctr(cpu) 	(per_cpu(rcu_data, (cpu)).last_qsctr)
-#define RCU_qs_pending(cpu)	(per_cpu(rcu_data, (cpu)).qs_pending)
-#define RCU_batch(cpu) 		(per_cpu(rcu_data, (cpu)).batch)
-#define RCU_nxtlist(cpu) 	(per_cpu(rcu_data, (cpu)).nxtlist)
-#define RCU_curlist(cpu) 	(per_cpu(rcu_data, (cpu)).curlist)
-#define RCU_nxttail(cpu) 	(per_cpu(rcu_data, (cpu)).nxttail)
+/*
+ * Increment the quiscent state counter.
+ */
+static inline void rcu_qsctr_inc(int cpu)
+{
+	struct rcu_data *rdp = &per_cpu(rcu_data, cpu);
+	rdp->qsctr++;
+}
+static inline void rcu_bh_qsctr_inc(int cpu)
+{
+	struct rcu_data *rdp = &per_cpu(rcu_bh_data, cpu);
+	rdp->qsctr++;
+}
 
-static inline int rcu_pending(int cpu) 
+static inline int __rcu_pending(struct rcu_ctrlblk *rcp,
+						struct rcu_data *rdp)
 {
 	/* This cpu has pending rcu entries and the grace period
 	 * for them has completed.
 	 */
-	if (RCU_curlist(cpu) &&
-		  !rcu_batch_before(rcu_ctrlblk.completed,RCU_batch(cpu)))
+	if (rdp->curlist && !rcu_batch_before(rcp->completed, rdp->batch))
 		return 1;
 
 	/* This cpu has no pending entries, but there are new entries */
-	if (!RCU_curlist(cpu) && RCU_nxtlist(cpu))
+	if (!rdp->curlist && rdp->nxtlist)
+		return 1;
+
+	/* This cpu has finished callbacks to invoke */
+	if (rdp->donelist)
 		return 1;
 
 	/* The rcu core waits for a quiescent state from the cpu */
-	if (RCU_quiescbatch(cpu) != rcu_ctrlblk.cur || RCU_qs_pending(cpu))
+	if (rdp->quiescbatch != rcp->cur || rdp->qs_pending)
 		return 1;
 
 	/* nothing to do */
 	return 0;
 }
 
+static inline int rcu_pending(int cpu)
+{
+	return __rcu_pending(&rcu_ctrlblk, &per_cpu(rcu_data, cpu)) ||
+		__rcu_pending(&rcu_bh_ctrlblk, &per_cpu(rcu_bh_data, cpu));
+}
+
+/**
+ * rcu_read_lock - mark the beginning of an RCU read-side critical section.
+ *
+ * When synchronize_kernel() is invoked on one CPU while other CPUs
+ * are within RCU read-side critical sections, then the
+ * synchronize_kernel() is guaranteed to block until after all the other
+ * CPUs exit their critical sections.  Similarly, if call_rcu() is invoked
+ * on one CPU while other CPUs are within RCU read-side critical
+ * sections, invocation of the corresponding RCU callback is deferred
+ * until after the all the other CPUs exit their critical sections.
+ *
+ * Note, however, that RCU callbacks are permitted to run concurrently
+ * with RCU read-side critical sections.  One way that this can happen
+ * is via the following sequence of events: (1) CPU 0 enters an RCU
+ * read-side critical section, (2) CPU 1 invokes call_rcu() to register
+ * an RCU callback, (3) CPU 0 exits the RCU read-side critical section,
+ * (4) CPU 2 enters a RCU read-side critical section, (5) the RCU
+ * callback is invoked.  This is legal, because the RCU read-side critical
+ * section that was running concurrently with the call_rcu() (and which
+ * therefore might be referencing something that the corresponding RCU
+ * callback would free up) has completed before the corresponding
+ * RCU callback is invoked.
+ *
+ * RCU read-side critical sections may be nested.  Any deferred actions
+ * will be deferred until the outermost RCU read-side critical section
+ * completes.
+ *
+ * It is illegal to block while in an RCU read-side critical section.
+ */
 #define rcu_read_lock()		preempt_disable()
+
+/**
+ * rcu_read_unlock - marks the end of an RCU read-side critical section.
+ *
+ * See rcu_read_lock() for more information.
+ */
 #define rcu_read_unlock()	preempt_enable()
 
+/*
+ * So where is rcu_write_lock()?  It does not exist, as there is no
+ * way for writers to lock out RCU readers.  This is a feature, not
+ * a bug -- this property is what provides RCU's performance benefits.
+ * Of course, writers must coordinate with each other.  The normal
+ * spinlock primitives work well for this, but any other technique may be
+ * used as well.  RCU does not care how the writers keep out of each
+ * others' way, as long as they do so.
+ */
+
+/**
+ * rcu_read_lock_bh - mark the beginning of a softirq-only RCU critical section
+ *
+ * This is equivalent of rcu_read_lock(), but to be used when updates
+ * are being done using call_rcu_bh(). Since call_rcu_bh() callbacks
+ * consider completion of a softirq handler to be a quiescent state,
+ * a process in RCU read-side critical section must be protected by
+ * disabling softirqs. Read-side critical sections in interrupt context
+ * can use just rcu_read_lock().
+ *
+ */
+#define rcu_read_lock_bh()	local_bh_disable()
+
+/*
+ * rcu_read_unlock_bh - marks the end of a softirq-only RCU critical section
+ *
+ * See rcu_read_lock_bh() for more information.
+ */
+#define rcu_read_unlock_bh()	local_bh_enable()
+
+/**
+ * rcu_dereference - fetch an RCU-protected pointer in an
+ * RCU read-side critical section.  This pointer may later
+ * be safely dereferenced.
+ *
+ * Inserts memory barriers on architectures that require them
+ * (currently only the Alpha), and, more importantly, documents
+ * exactly which pointers are protected by RCU.
+ */
+
+#define rcu_dereference(p)     ({ \
+				typeof(p) _________p1 = p; \
+				smp_read_barrier_depends(); \
+				(_________p1); \
+				})
+
 extern void rcu_init(void);
 extern void rcu_check_callbacks(int cpu, int user);
 extern void rcu_restart_cpu(int cpu);
 
 /* Exported interfaces */
 extern void FASTCALL(call_rcu(struct rcu_head *head, 
+				void (*func)(struct rcu_head *head)));
+extern void FASTCALL(call_rcu_bh(struct rcu_head *head,
 				void (*func)(struct rcu_head *head)));
 extern void synchronize_kernel(void);
 
diff -Nru a/include/linux/reiserfs_fs.h b/include/linux/reiserfs_fs.h
--- a/include/linux/reiserfs_fs.h	2004-10-18 14:57:03 -07:00
+++ b/include/linux/reiserfs_fs.h	2004-10-18 14:57:03 -07:00
@@ -1734,7 +1734,7 @@
   int t_blocks_allocated ;      /* number of blocks this writer allocated */
   unsigned long t_trans_id ;    /* sanity check, equals the current trans id */
   void *t_handle_save ;		/* save existing current->journal_info */
-  int displace_new_blocks:1;	/* if new block allocation occurres, that block
+  unsigned displace_new_blocks:1; /* if new block allocation occurres, that block
 				   should be displaced from others */
 } ;
 
@@ -1777,7 +1777,8 @@
 int reiserfs_commit_page(struct inode *inode, struct page *page,
 		unsigned from, unsigned to);
 int reiserfs_flush_old_commits(struct super_block *);
-void reiserfs_commit_for_inode(struct inode *) ;
+int reiserfs_commit_for_inode(struct inode *) ;
+int  reiserfs_inode_needs_commit(struct inode *) ;
 void reiserfs_update_inode_transaction(struct inode *) ;
 void reiserfs_wait_on_write_block(struct super_block *s) ;
 void reiserfs_block_writes(struct reiserfs_transaction_handle *th) ;
@@ -1944,7 +1945,7 @@
 int reiserfs_find_actor(struct inode * inode, void *p) ;
 int reiserfs_init_locked_inode(struct inode * inode, void *p) ;
 void reiserfs_delete_inode (struct inode * inode);
-void reiserfs_write_inode (struct inode * inode, int) ;
+int reiserfs_write_inode (struct inode * inode, int) ;
 struct dentry *reiserfs_get_dentry(struct super_block *, void *) ;
 struct dentry *reiserfs_decode_fh(struct super_block *sb, __u32 *data,
                                      int len, int fhtype,
@@ -2153,9 +2154,9 @@
     int prealloc_size;			/* is set in determine_prealloc_size() function, used by underlayed
 					 * function that do actual allocation */
 
-    int formatted_node:1;		/* the allocator uses different polices for getting disk space for
+    unsigned formatted_node:1;		/* the allocator uses different polices for getting disk space for
 					 * formatted/unformatted blocks with/without preallocation */
-    int preallocate:1;
+    unsigned preallocate:1;
 };
 
 typedef struct __reiserfs_blocknr_hint reiserfs_blocknr_hint_t;
diff -Nru a/include/linux/reiserfs_fs_i.h b/include/linux/reiserfs_fs_i.h
--- a/include/linux/reiserfs_fs_i.h	2004-10-18 14:56:49 -07:00
+++ b/include/linux/reiserfs_fs_i.h	2004-10-18 14:56:49 -07:00
@@ -45,7 +45,7 @@
     struct list_head i_prealloc_list; /* per-transaction list of inodes which
                                        * have preallocated blocks */
 
-    int new_packing_locality:1;	      /* new_packig_locality is created; new blocks
+    unsigned new_packing_locality:1;  /* new_packig_locality is created; new blocks
 				       * for the contents of this directory should be
 				       * displaced */
 
diff -Nru a/include/linux/reiserfs_fs_sb.h b/include/linux/reiserfs_fs_sb.h
--- a/include/linux/reiserfs_fs_sb.h	2004-10-18 14:56:32 -07:00
+++ b/include/linux/reiserfs_fs_sb.h	2004-10-18 14:56:32 -07:00
@@ -444,6 +444,8 @@
     REISERFS_XATTRS,
     REISERFS_XATTRS_USER,
     REISERFS_POSIXACL,
+    REISERFS_BARRIER_NONE,
+    REISERFS_BARRIER_FLUSH,
 
     REISERFS_TEST1,
     REISERFS_TEST2,
@@ -473,6 +475,8 @@
 #define reiserfs_xattrs_user(s) (REISERFS_SB(s)->s_mount_opt & (1 << REISERFS_XATTRS_USER))
 #define reiserfs_posixacl(s) (REISERFS_SB(s)->s_mount_opt & (1 << REISERFS_POSIXACL))
 #define reiserfs_xattrs_optional(s) (reiserfs_xattrs_user(s) || reiserfs_posixacl(s))
+#define reiserfs_barrier_none(s) (REISERFS_SB(s)->s_mount_opt & (1 << REISERFS_BARRIER_NONE))
+#define reiserfs_barrier_flush(s) (REISERFS_SB(s)->s_mount_opt & (1 << REISERFS_BARRIER_FLUSH))
 
 void reiserfs_file_buffer (struct buffer_head * bh, int list);
 extern struct file_system_type reiserfs_fs_type;
diff -Nru a/include/linux/resource.h b/include/linux/resource.h
--- a/include/linux/resource.h	2004-10-18 14:55:54 -07:00
+++ b/include/linux/resource.h	2004-10-18 14:55:54 -07:00
@@ -56,6 +56,12 @@
 #define _STK_LIM	(8*1024*1024)
 
 /*
+ * GPG wants 32kB of mlocked memory, to make sure pass phrases
+ * and other sensitive information are never written to disk.
+ */
+#define MLOCK_LIMIT	(8 * PAGE_SIZE)
+
+/*
  * Due to binary compatibility, the actual resource numbers
  * may be different for different linux versions..
  */
diff -Nru a/include/linux/rmap.h b/include/linux/rmap.h
--- a/include/linux/rmap.h	2004-10-18 14:55:54 -07:00
+++ b/include/linux/rmap.h	2004-10-18 14:55:54 -07:00
@@ -9,11 +9,6 @@
 #include <linux/slab.h>
 #include <linux/spinlock.h>
 
-#define page_map_lock(page) \
-	bit_spin_lock(PG_maplock, (unsigned long *)&(page)->flags)
-#define page_map_unlock(page) \
-	bit_spin_unlock(PG_maplock, (unsigned long *)&(page)->flags)
-
 /*
  * The anon_vma heads a list of private "related" vmas, to scan if
  * an anonymous page pointing to this anon_vma needs to be unmapped:
@@ -87,24 +82,27 @@
  */
 static inline void page_dup_rmap(struct page *page)
 {
-	page_map_lock(page);
-	page->mapcount++;
-	page_map_unlock(page);
+	atomic_inc(&page->_mapcount);
 }
 
 /*
  * Called from mm/vmscan.c to handle paging out
  */
-int page_referenced(struct page *);
+int page_referenced(struct page *, int is_locked);
 int try_to_unmap(struct page *);
 
+/*
+ * Used by swapoff to help locate where page is expected in vma.
+ */
+unsigned long page_address_in_vma(struct page *, struct vm_area_struct *);
+
 #else	/* !CONFIG_MMU */
 
 #define anon_vma_init()		do {} while (0)
 #define anon_vma_prepare(vma)	(0)
 #define anon_vma_link(vma)	do {} while (0)
 
-#define page_referenced(page)	TestClearPageReferenced(page)
+#define page_referenced(page,l)	TestClearPageReferenced(page)
 #define try_to_unmap(page)	SWAP_FAIL
 
 #endif	/* CONFIG_MMU */
diff -Nru a/include/linux/romfs_fs.h b/include/linux/romfs_fs.h
--- a/include/linux/romfs_fs.h	2004-10-18 14:56:28 -07:00
+++ b/include/linux/romfs_fs.h	2004-10-18 14:56:28 -07:00
@@ -12,27 +12,27 @@
 
 #define __mkw(h,l) (((h)&0x00ff)<< 8|((l)&0x00ff))
 #define __mkl(h,l) (((h)&0xffff)<<16|((l)&0xffff))
-#define __mk4(a,b,c,d) htonl(__mkl(__mkw(a,b),__mkw(c,d)))
+#define __mk4(a,b,c,d) cpu_to_be32(__mkl(__mkw(a,b),__mkw(c,d)))
 #define ROMSB_WORD0 __mk4('-','r','o','m')
 #define ROMSB_WORD1 __mk4('1','f','s','-')
 
 /* On-disk "super block" */
 
 struct romfs_super_block {
-	__u32 word0;
-	__u32 word1;
-	__u32 size;
-	__u32 checksum;
+	__be32 word0;
+	__be32 word1;
+	__be32 size;
+	__be32 checksum;
 	char name[0];		/* volume name */
 };
 
 /* On disk inode */
 
 struct romfs_inode {
-	__u32 next;		/* low 4 bits see ROMFH_ */
-	__u32 spec;
-	__u32 size;
-	__u32 checksum;
+	__be32 next;		/* low 4 bits see ROMFH_ */
+	__be32 spec;
+	__be32 size;
+	__be32 checksum;
 	char name[0];
 };
 
diff -Nru a/include/linux/rtnetlink.h b/include/linux/rtnetlink.h
--- a/include/linux/rtnetlink.h	2004-10-18 14:56:49 -07:00
+++ b/include/linux/rtnetlink.h	2004-10-18 14:56:49 -07:00
@@ -9,53 +9,89 @@
 
 /* Types of messages */
 
-#define RTM_BASE	0x10
+enum {
+	RTM_BASE	= 16,
+#define RTM_BASE	RTM_BASE
+
+	RTM_NEWLINK	= 16,
+#define RTM_NEWLINK	RTM_NEWLINK
+	RTM_DELLINK,
+#define RTM_DELLINK	RTM_DELLINK
+	RTM_GETLINK,
+#define RTM_GETLINK	RTM_GETLINK
+	RTM_SETLINK,
+#define RTM_SETLINK	RTM_SETLINK
+
+	RTM_NEWADDR	= 20,
+#define RTM_NEWADDR	RTM_NEWADDR
+	RTM_DELADDR,
+#define RTM_DELADDR	RTM_DELADDR
+	RTM_GETADDR,
+#define RTM_GETADDR	RTM_GETADDR
+
+	RTM_NEWROUTE	= 24,
+#define RTM_NEWROUTE	RTM_NEWROUTE
+	RTM_DELROUTE,
+#define RTM_DELROUTE	RTM_DELROUTE
+	RTM_GETROUTE,
+#define RTM_GETROUTE	RTM_GETROUTE
+
+	RTM_NEWNEIGH	= 28,
+#define RTM_NEWNEIGH	RTM_NEWNEIGH
+	RTM_DELNEIGH,
+#define RTM_DELNEIGH	RTM_DELNEIGH
+	RTM_GETNEIGH,
+#define RTM_GETNEIGH	RTM_GETNEIGH
+
+	RTM_NEWRULE	= 32,
+#define RTM_NEWRULE	RTM_NEWRULE
+	RTM_DELRULE,
+#define RTM_DELRULE	RTM_DELRULE
+	RTM_GETRULE,
+#define RTM_GETRULE	RTM_GETRULE
+
+	RTM_NEWQDISC	= 36,
+#define RTM_NEWQDISC	RTM_NEWQDISC
+	RTM_DELQDISC,
+#define RTM_DELQDISC	RTM_DELQDISC
+	RTM_GETQDISC,
+#define RTM_GETQDISC	RTM_GETQDISC
+
+	RTM_NEWTCLASS	= 40,
+#define RTM_NEWTCLASS	RTM_NEWTCLASS
+	RTM_DELTCLASS,
+#define RTM_DELTCLASS	RTM_DELTCLASS
+	RTM_GETTCLASS,
+#define RTM_GETTCLASS	RTM_GETTCLASS
+
+	RTM_NEWTFILTER	= 44,
+#define RTM_NEWTFILTER	RTM_NEWTFILTER
+	RTM_DELTFILTER,
+#define RTM_DELTFILTER	RTM_DELTFILTER
+	RTM_GETTFILTER,
+#define RTM_GETTFILTER	RTM_GETTFILTER
+
+	RTM_NEWACTION	= 48,
+#define RTM_NEWACTION   RTM_NEWACTION
+	RTM_DELACTION,
+#define RTM_DELACTION   RTM_DELACTION
+	RTM_GETACTION,
+#define RTM_GETACTION   RTM_GETACTION
+
+	RTM_NEWPREFIX	= 52,
+#define RTM_NEWPREFIX	RTM_NEWPREFIX
+	RTM_GETPREFIX	= 54,
+#define RTM_GETPREFIX	RTM_GETPREFIX
 
-#define	RTM_NEWLINK	(RTM_BASE+0)
-#define	RTM_DELLINK	(RTM_BASE+1)
-#define	RTM_GETLINK	(RTM_BASE+2)
-#define	RTM_SETLINK	(RTM_BASE+3)
+	RTM_GETMULTICAST = 58,
+#define RTM_GETMULTICAST RTM_GETMULTICAST
 
-#define	RTM_NEWADDR	(RTM_BASE+4)
-#define	RTM_DELADDR	(RTM_BASE+5)
-#define	RTM_GETADDR	(RTM_BASE+6)
+	RTM_GETANYCAST	= 62,
+#define RTM_GETANYCAST	RTM_GETANYCAST
 
-#define	RTM_NEWROUTE	(RTM_BASE+8)
-#define	RTM_DELROUTE	(RTM_BASE+9)
-#define	RTM_GETROUTE	(RTM_BASE+10)
-
-#define	RTM_NEWNEIGH	(RTM_BASE+12)
-#define	RTM_DELNEIGH	(RTM_BASE+13)
-#define	RTM_GETNEIGH	(RTM_BASE+14)
-
-#define	RTM_NEWRULE	(RTM_BASE+16)
-#define	RTM_DELRULE	(RTM_BASE+17)
-#define	RTM_GETRULE	(RTM_BASE+18)
-
-#define	RTM_NEWQDISC	(RTM_BASE+20)
-#define	RTM_DELQDISC	(RTM_BASE+21)
-#define	RTM_GETQDISC	(RTM_BASE+22)
-
-#define	RTM_NEWTCLASS	(RTM_BASE+24)
-#define	RTM_DELTCLASS	(RTM_BASE+25)
-#define	RTM_GETTCLASS	(RTM_BASE+26)
-
-#define	RTM_NEWTFILTER	(RTM_BASE+28)
-#define	RTM_DELTFILTER	(RTM_BASE+29)
-#define	RTM_GETTFILTER	(RTM_BASE+30)
-
-#define RTM_NEWACTION   (RTM_BASE+32)
-#define RTM_DELACTION   (RTM_BASE+33)
-#define RTM_GETACTION   (RTM_BASE+34)
-
-#define RTM_NEWPREFIX	(RTM_BASE+36)
-#define RTM_GETPREFIX	(RTM_BASE+38)
-
-#define	RTM_GETMULTICAST (RTM_BASE+42)
-
-#define	RTM_GETANYCAST	(RTM_BASE+46)
-
-#define	RTM_MAX		(RTM_BASE+47)
+	RTM_MAX,
+#define RTM_MAX		RTM_MAX
+};
 
 /* 
    Generic structure for encapsulation of optional route information.
@@ -541,6 +577,17 @@
 	__u32	tx_compressed;
 };
 
+/* The struct should be in sync with struct ifmap */
+struct rtnl_link_ifmap
+{
+	__u64	mem_start;
+	__u64	mem_end;
+	__u64	base_addr;
+	__u16	irq;
+	__u8	dma;
+	__u8	port;
+};
+
 enum
 {
 	IFLA_UNSPEC,
@@ -561,6 +608,12 @@
 #define IFLA_WIRELESS IFLA_WIRELESS
 	IFLA_PROTINFO,		/* Protocol specific information for a link */
 #define IFLA_PROTINFO IFLA_PROTINFO
+	IFLA_TXQLEN,
+#define IFLA_TXQLEN IFLA_TXQLEN
+	IFLA_MAP,
+#define IFLA_MAP IFLA_MAP
+	IFLA_WEIGHT,
+#define IFLA_WEIGHT IFLA_WEIGHT
 	__IFLA_MAX
 };
 
@@ -653,10 +706,6 @@
 #define TCA_RTA(r)  ((struct rtattr*)(((char*)(r)) + NLMSG_ALIGN(sizeof(struct tcmsg))))
 #define TCA_PAYLOAD(n) NLMSG_PAYLOAD(n,sizeof(struct tcmsg))
 
-
-/* SUMMARY: maximal rtattr understood by kernel */
-
-#define RTATTR_MAX		RTA_MAX
 
 /* RTnetlink multicast groups */
 
diff -Nru a/include/linux/sched.h b/include/linux/sched.h
--- a/include/linux/sched.h	2004-10-18 14:55:54 -07:00
+++ b/include/linux/sched.h	2004-10-18 14:55:54 -07:00
@@ -40,7 +40,6 @@
 #define CLONE_FS	0x00000200	/* set if fs info shared between processes */
 #define CLONE_FILES	0x00000400	/* set if open files shared between processes */
 #define CLONE_SIGHAND	0x00000800	/* set if signal handlers and blocked signals shared */
-#define CLONE_IDLETASK	0x00001000	/* set if new pid should be 0 (kernel only)*/
 #define CLONE_PTRACE	0x00002000	/* set if we want to let tracing continue on the child too */
 #define CLONE_VFORK	0x00004000	/* set if the parent wants the child to wake it up on mm_release */
 #define CLONE_PARENT	0x00008000	/* set if we want to have the same parent as the cloner */
@@ -107,8 +106,9 @@
 #define TASK_INTERRUPTIBLE	1
 #define TASK_UNINTERRUPTIBLE	2
 #define TASK_STOPPED		4
-#define TASK_ZOMBIE		8
-#define TASK_DEAD		16
+#define TASK_TRACED		8
+#define TASK_ZOMBIE		16
+#define TASK_DEAD		32
 
 #define __set_task_state(tsk, state_value)		\
 	do { (tsk)->state = (state_value); } while (0)
@@ -189,10 +189,26 @@
 
 #include <linux/aio.h>
 
+extern unsigned long
+arch_get_unmapped_area(struct file *, unsigned long, unsigned long,
+		       unsigned long, unsigned long);
+extern unsigned long
+arch_get_unmapped_area_topdown(struct file *filp, unsigned long addr,
+			  unsigned long len, unsigned long pgoff,
+			  unsigned long flags);
+extern void arch_unmap_area(struct vm_area_struct *area);
+extern void arch_unmap_area_topdown(struct vm_area_struct *area);
+
+
 struct mm_struct {
 	struct vm_area_struct * mmap;		/* list of VMAs */
 	struct rb_root mm_rb;
 	struct vm_area_struct * mmap_cache;	/* last find_vma result */
+	unsigned long (*get_unmapped_area) (struct file *filp,
+				unsigned long addr, unsigned long len,
+				unsigned long pgoff, unsigned long flags);
+	void (*unmap_area) (struct vm_area_struct *area);
+	unsigned long mmap_base;		/* base of mmap area */
 	unsigned long free_area_cache;		/* first hole */
 	pgd_t * pgd;
 	atomic_t mm_users;			/* How many users with user space? */
@@ -209,10 +225,10 @@
 	unsigned long start_code, end_code, start_data, end_data;
 	unsigned long start_brk, brk, start_stack;
 	unsigned long arg_start, arg_end, env_start, env_end;
-	unsigned long rss, total_vm, locked_vm;
-	unsigned long def_flags;
+	unsigned long rss, total_vm, locked_vm, shared_vm;
+	unsigned long exec_vm, stack_vm, reserved_vm, def_flags;
 
-	unsigned long saved_auxv[40]; /* for /proc/PID/auxv */
+	unsigned long saved_auxv[42]; /* for /proc/PID/auxv */
 
 	unsigned dumpable:1;
 	cpumask_t cpu_vm_mask;
@@ -220,6 +236,10 @@
 	/* Architecture-specific MM context */
 	mm_context_t context;
 
+	/* Token based thrashing protection. */
+	unsigned long swap_token_time;
+	char recent_pagein;
+
 	/* coredumping support */
 	int core_waiters;
 	struct completion *core_startup_done, core_done;
@@ -268,6 +288,8 @@
 
 	/* thread group stop support, overloads group_exit_code too */
 	int			group_stop_count;
+	/* 1 if group stopped since last SIGCONT, -1 if SIGCONT since report */
+  	int			stop_state;
 
 	/* POSIX.1b Interval Timers */
 	struct list_head posix_timers;
@@ -280,6 +302,16 @@
 	int leader;
 
 	struct tty_struct *tty; /* NULL if no tty */
+
+	/*
+	 * Cumulative resource counters for dead threads in the group,
+	 * and for reaped dead child processes forked by this group.
+	 * Live threads maintain their own counters and add to these
+	 * in __exit_signal, except for the group leader.
+	 */
+	unsigned long utime, stime, cutime, cstime;
+	unsigned long nvcsw, nivcsw, cnvcsw, cnivcsw;
+	unsigned long min_flt, maj_flt, cmin_flt, cmaj_flt;
 };
 
 /*
@@ -300,7 +332,7 @@
 
 #define MAX_PRIO		(MAX_RT_PRIO + 40)
 
-#define rt_task(p)		((p)->prio < MAX_RT_PRIO)
+#define rt_task(p)		(unlikely((p)->prio < MAX_RT_PRIO))
 
 /*
  * Some day this will be a full-fledged user tracking system..
@@ -312,6 +344,7 @@
 	atomic_t sigpending;	/* How many pending signals does this user have? */
 	/* protected by mq_lock	*/
 	unsigned long mq_bytes;	/* How many bytes can be allocated to mqueue? */
+	unsigned long locked_shm; /* How many pages of mlocked shm ? */
 
 	/* Hash table maintenance information */
 	struct list_head uidhash_list;
@@ -347,6 +380,20 @@
 	struct timespec wall_to_prev;   /* wall_to_monotonic used when set */
 };
 
+#ifdef CONFIG_SCHEDSTATS
+struct sched_info {
+	/* cumulative counters */
+	unsigned long	cpu_time,	/* time spent on the cpu */
+			run_delay,	/* time spent waiting on a runqueue */
+			pcnt;		/* # of timeslices run on this cpu */
+
+	/* timestamps */
+	unsigned long	last_arrival,	/* when we last ran on a cpu */
+			last_queued;	/* when we were last queued to run */
+};
+
+extern struct file_operations proc_schedstat_operations;
+#endif
 
 struct io_context;			/* See blkdev.h */
 void exit_io_context(void);
@@ -402,13 +449,17 @@
 
 	unsigned long sleep_avg;
 	long interactive_credit;
-	unsigned long long timestamp;
+	unsigned long long timestamp, last_ran;
 	int activated;
 
 	unsigned long policy;
 	cpumask_t cpus_allowed;
 	unsigned int time_slice, first_time_slice;
 
+#ifdef CONFIG_SCHEDSTATS
+	struct sched_info sched_info;
+#endif
+
 	struct list_head tasks;
 	/*
 	 * ptrace_list/ptrace_children forms the list of my children
@@ -425,7 +476,7 @@
 	int pdeath_signal;  /*  The signal sent when the parent dies  */
 	/* ??? */
 	unsigned long personality;
-	int did_exec:1;
+	unsigned did_exec:1;
 	pid_t pid;
 	pid_t tgid;
 	/* 
@@ -444,7 +495,7 @@
 	struct task_struct *group_leader;	/* threadgroup leader */
 
 	/* PID/PID hash table linkage. */
-	struct pid_link pids[PIDTYPE_MAX];
+	struct pid pids[PIDTYPE_MAX];
 
 	wait_queue_head_t wait_chldexit;	/* for wait4() */
 	struct completion *vfork_done;		/* for vfork() */
@@ -455,17 +506,17 @@
 	unsigned long it_real_value, it_prof_value, it_virt_value;
 	unsigned long it_real_incr, it_prof_incr, it_virt_incr;
 	struct timer_list real_timer;
-	unsigned long utime, stime, cutime, cstime;
-	unsigned long nvcsw, nivcsw, cnvcsw, cnivcsw; /* context switch counts */
-	u64 start_time;
+	unsigned long utime, stime;
+	unsigned long nvcsw, nivcsw; /* context switch counts */
+	struct timespec start_time;
 /* mm fault and swap info: this can arguably be seen as either mm-specific or thread-specific */
-	unsigned long min_flt, maj_flt, cmin_flt, cmaj_flt;
+	unsigned long min_flt, maj_flt;
 /* process credentials */
 	uid_t uid,euid,suid,fsuid;
 	gid_t gid,egid,sgid,fsgid;
 	struct group_info *group_info;
 	kernel_cap_t   cap_effective, cap_inheritable, cap_permitted;
-	int keep_capabilities:1;
+	unsigned keep_capabilities:1;
 	struct user_struct *user;
 /* limits */
 	struct rlimit rlim[RLIM_NLIMITS];
@@ -522,7 +573,13 @@
 
 	unsigned long ptrace_message;
 	siginfo_t *last_siginfo; /* For ptrace use.  */
-
+/*
+ * current io wait handle: wait queue entry to use for io waits
+ * If this thread is processing aio, this points at the waitqueue
+ * inside the currently handled kiocb. It may be NULL (i.e. default
+ * to a stack based synchronous wait) if its doing sync IO.
+ */
+	wait_queue_t *io_wait;
 #ifdef CONFIG_NUMA
   	struct mempolicy *mempolicy;
   	short il_next;		/* could be shared with used_math */
@@ -534,6 +591,7 @@
 	return tsk->signal->pgrp;
 }
 
+extern void free_task(struct task_struct *tsk);
 extern void __put_task_struct(struct task_struct *tsk);
 #define get_task_struct(tsk) do { atomic_inc(&(tsk)->usage); } while(0)
 #define put_task_struct(tsk) \
@@ -565,118 +623,6 @@
 #define PF_SYNCWRITE	0x00200000	/* I am doing a sync write */
 
 #ifdef CONFIG_SMP
-#define SCHED_LOAD_SCALE	128UL	/* increase resolution of load */
-
-#define SD_BALANCE_NEWIDLE	1	/* Balance when about to become idle */
-#define SD_BALANCE_EXEC		2	/* Balance on exec */
-#define SD_BALANCE_CLONE	4	/* Balance on clone */
-#define SD_WAKE_IDLE		8	/* Wake to idle CPU on task wakeup */
-#define SD_WAKE_AFFINE		16	/* Wake task to waking CPU */
-#define SD_WAKE_BALANCE		32	/* Perform balancing at task wakeup */
-#define SD_SHARE_CPUPOWER	64	/* Domain members share cpu power */
-
-struct sched_group {
-	struct sched_group *next;	/* Must be a circular list */
-	cpumask_t cpumask;
-
-	/*
-	 * CPU power of this group, SCHED_LOAD_SCALE being max power for a
-	 * single CPU. This should be read only (except for setup). Although
-	 * it will need to be written to at cpu hot(un)plug time, perhaps the
-	 * cpucontrol semaphore will provide enough exclusion?
-	 */
-	unsigned long cpu_power;
-};
-
-struct sched_domain {
-	/* These fields must be setup */
-	struct sched_domain *parent;	/* top domain must be null terminated */
-	struct sched_group *groups;	/* the balancing groups of the domain */
-	cpumask_t span;			/* span of all CPUs in this domain */
-	unsigned long min_interval;	/* Minimum balance interval ms */
-	unsigned long max_interval;	/* Maximum balance interval ms */
-	unsigned int busy_factor;	/* less balancing by factor if busy */
-	unsigned int imbalance_pct;	/* No balance until over watermark */
-	unsigned long long cache_hot_time; /* Task considered cache hot (ns) */
-	unsigned int cache_nice_tries;	/* Leave cache hot tasks for # tries */
-	unsigned int per_cpu_gain;	/* CPU % gained by adding domain cpus */
-	int flags;			/* See SD_* */
-
-	/* Runtime fields. */
-	unsigned long last_balance;	/* init to jiffies. units in jiffies */
-	unsigned int balance_interval;	/* initialise to 1. units in ms. */
-	unsigned int nr_balance_failed; /* initialise to 0 */
-};
-
-/* Common values for SMT siblings */
-#define SD_SIBLING_INIT (struct sched_domain) {		\
-	.span			= CPU_MASK_NONE,	\
-	.parent			= NULL,			\
-	.groups			= NULL,			\
-	.min_interval		= 1,			\
-	.max_interval		= 2,			\
-	.busy_factor		= 8,			\
-	.imbalance_pct		= 110,			\
-	.cache_hot_time		= 0,			\
-	.cache_nice_tries	= 0,			\
-	.per_cpu_gain		= 15,			\
-	.flags			= SD_BALANCE_NEWIDLE	\
-				| SD_BALANCE_EXEC	\
-				| SD_BALANCE_CLONE	\
-				| SD_WAKE_AFFINE	\
-				| SD_WAKE_IDLE		\
-				| SD_SHARE_CPUPOWER,	\
-	.last_balance		= jiffies,		\
-	.balance_interval	= 1,			\
-	.nr_balance_failed	= 0,			\
-}
-
-/* Common values for CPUs */
-#define SD_CPU_INIT (struct sched_domain) {		\
-	.span			= CPU_MASK_NONE,	\
-	.parent			= NULL,			\
-	.groups			= NULL,			\
-	.min_interval		= 1,			\
-	.max_interval		= 4,			\
-	.busy_factor		= 64,			\
-	.imbalance_pct		= 125,			\
-	.cache_hot_time		= (5*1000000/2),	\
-	.cache_nice_tries	= 1,			\
-	.per_cpu_gain		= 100,			\
-	.flags			= SD_BALANCE_NEWIDLE	\
-				| SD_BALANCE_EXEC	\
-				| SD_BALANCE_CLONE	\
-				| SD_WAKE_AFFINE	\
-				| SD_WAKE_BALANCE,	\
-	.last_balance		= jiffies,		\
-	.balance_interval	= 1,			\
-	.nr_balance_failed	= 0,			\
-}
-
-#ifdef CONFIG_NUMA
-/* Common values for NUMA nodes */
-#define SD_NODE_INIT (struct sched_domain) {		\
-	.span			= CPU_MASK_NONE,	\
-	.parent			= NULL,			\
-	.groups			= NULL,			\
-	.min_interval		= 8,			\
-	.max_interval		= 32,			\
-	.busy_factor		= 32,			\
-	.imbalance_pct		= 125,			\
-	.cache_hot_time		= (10*1000000),		\
-	.cache_nice_tries	= 1,			\
-	.per_cpu_gain		= 100,			\
-	.flags			= SD_BALANCE_EXEC	\
-				| SD_BALANCE_CLONE	\
-				| SD_WAKE_BALANCE,	\
-	.last_balance		= jiffies,		\
-	.balance_interval	= 1,			\
-	.nr_balance_failed	= 0,			\
-}
-#endif
-
-extern void cpu_attach_domain(struct sched_domain *sd, int cpu);
-
 extern int set_cpus_allowed(task_t *p, cpumask_t new_mask);
 #else
 static inline int set_cpus_allowed(task_t *p, cpumask_t new_mask)
@@ -687,10 +633,11 @@
 
 extern unsigned long long sched_clock(void);
 
+/* sched_exec is called by processes performing an exec */
 #ifdef CONFIG_SMP
-extern void sched_balance_exec(void);
+extern void sched_exec(void);
 #else
-#define sched_balance_exec()   {}
+#define sched_exec()   {}
 #endif
 
 extern void sched_idle_next(void);
@@ -727,7 +674,8 @@
 
 extern struct   mm_struct init_mm;
 
-extern struct task_struct *find_task_by_pid(int pid);
+#define find_task_by_pid(nr)	find_task_by_pid_type(PIDTYPE_PID, nr)
+extern struct task_struct *find_task_by_pid_type(int type, int pid);
 extern void set_special_pids(pid_t session, pid_t pgrp);
 extern void __set_special_pids(pid_t session, pid_t pgrp);
 
@@ -749,16 +697,12 @@
 
 extern int FASTCALL(wake_up_state(struct task_struct * tsk, unsigned int state));
 extern int FASTCALL(wake_up_process(struct task_struct * tsk));
-extern void FASTCALL(wake_up_forked_process(struct task_struct * tsk));
+extern void FASTCALL(wake_up_new_task(struct task_struct * tsk,
+						unsigned long clone_flags));
 #ifdef CONFIG_SMP
  extern void kick_process(struct task_struct *tsk);
- extern void FASTCALL(wake_up_forked_thread(struct task_struct * tsk));
 #else
  static inline void kick_process(struct task_struct *tsk) { }
- static inline void wake_up_forked_thread(struct task_struct * tsk)
- {
-	wake_up_forked_process(tsk);
- }
 #endif
 extern void FASTCALL(sched_fork(task_t * p));
 extern void FASTCALL(sched_exit(task_t * p));
@@ -789,12 +733,12 @@
 extern void release_task(struct task_struct * p);
 extern int send_sig_info(int, struct siginfo *, struct task_struct *);
 extern int send_group_sig_info(int, struct siginfo *, struct task_struct *);
+extern int force_sigsegv(int, struct task_struct *);
 extern int force_sig_info(int, struct siginfo *, struct task_struct *);
 extern int __kill_pg_info(int sig, struct siginfo *info, pid_t pgrp);
 extern int kill_pg_info(int, struct siginfo *, pid_t);
 extern int kill_sl_info(int, struct siginfo *, pid_t);
 extern int kill_proc_info(int, struct siginfo *, pid_t);
-extern void notify_parent(struct task_struct *, int);
 extern void do_notify_parent(struct task_struct *, int);
 extern void force_sig(int, struct task_struct *);
 extern void force_sig_specific(int, struct task_struct *);
@@ -858,8 +802,8 @@
 
 /* mmput gets rid of the mappings and all user-space */
 extern void mmput(struct mm_struct *);
-/* Grab a reference to the mm if its not already going away */
-extern struct mm_struct *mmgrab(struct mm_struct *);
+/* Grab a reference to a task's mm, if it is not already going away */
+extern struct mm_struct *get_task_mm(struct task_struct *task);
 /* Remove the current tasks stale references to the old mm_struct */
 extern void mm_release(struct task_struct *, struct mm_struct *);
 
@@ -885,7 +829,10 @@
 
 extern int do_execve(char *, char __user * __user *, char __user * __user *, struct pt_regs *);
 extern long do_fork(unsigned long, unsigned long, struct pt_regs *, unsigned long, int __user *, int __user *);
-extern struct task_struct * copy_process(unsigned long, unsigned long, struct pt_regs *, unsigned long, int __user *, int __user *);
+task_t *fork_idle(int);
+
+extern void set_task_comm(struct task_struct *tsk, char *from);
+extern void get_task_comm(char *to, struct task_struct *tsk);
 
 #ifdef CONFIG_SMP
 extern void wait_task_inactive(task_t * p);
@@ -930,9 +877,7 @@
 
 static inline int thread_group_empty(task_t *p)
 {
-	struct pid *pid = p->pids[PIDTYPE_TGID].pidptr;
-
-	return pid->task_list.next->next == &pid->task_list;
+	return list_empty(&p->pids[PIDTYPE_TGID].pid_list);
 }
 
 #define delay_group_leader(p) \
@@ -941,8 +886,8 @@
 extern void unhash_process(struct task_struct *p);
 
 /*
- * Protects ->fs, ->files, ->mm, ->ptrace, ->group_info and synchronises with
- * wait4().
+ * Protects ->fs, ->files, ->mm, ->ptrace, ->group_info, ->comm and
+ * synchronises with wait4().
  *
  * Nests both inside and outside of read_lock(&tasklist_lock).
  * It must not be nested with write_lock_irq(&tasklist_lock),
@@ -957,27 +902,7 @@
 {
 	spin_unlock(&p->alloc_lock);
 }
- 
-/**
- * get_task_mm - acquire a reference to the task's mm
- *
- * Returns %NULL if the task has no mm. User must release
- * the mm via mmput() after use.
- */
-static inline struct mm_struct * get_task_mm(struct task_struct * task)
-{
-	struct mm_struct * mm;
- 
-	task_lock(task);
-	mm = task->mm;
-	if (mm)
-		mm = mmgrab(mm);
-	task_unlock(task);
 
-	return mm;
-}
- 
- 
 /* set thread flags in other task's structures
  * - see asm/thread_info.h for TIF_xxxx flags available
  */
@@ -1087,6 +1012,20 @@
 }
 
 #endif /* CONFIG_SMP */
+
+#ifdef HAVE_ARCH_PICK_MMAP_LAYOUT
+extern void arch_pick_mmap_layout(struct mm_struct *mm);
+#else
+static inline void arch_pick_mmap_layout(struct mm_struct *mm)
+{
+	mm->mmap_base = TASK_UNMAPPED_BASE;
+	mm->get_unmapped_area = arch_get_unmapped_area;
+	mm->unmap_area = arch_unmap_area;
+}
+#endif
+
+extern long sched_setaffinity(pid_t pid, cpumask_t new_mask);
+extern long sched_getaffinity(pid_t pid, cpumask_t *mask);
 
 #endif /* __KERNEL__ */
 
diff -Nru a/include/linux/serial_core.h b/include/linux/serial_core.h
--- a/include/linux/serial_core.h	2004-10-18 14:55:55 -07:00
+++ b/include/linux/serial_core.h	2004-10-18 14:55:55 -07:00
@@ -176,6 +176,7 @@
 #define UPIO_PORT		(0)
 #define UPIO_HUB6		(1)
 #define UPIO_MEM		(2)
+#define UPIO_MEM32		(3)
 
 	unsigned int		read_status_mask;	/* driver specific */
 	unsigned int		ignore_status_mask;	/* driver specific */
diff -Nru a/include/linux/serio.h b/include/linux/serio.h
--- a/include/linux/serio.h	2004-10-18 14:56:33 -07:00
+++ b/include/linux/serio.h	2004-10-18 14:56:33 -07:00
@@ -17,12 +17,17 @@
 #ifdef __KERNEL__
 
 #include <linux/list.h>
+#include <linux/spinlock.h>
+#include <linux/device.h>
 
 struct serio {
 	void *private;
-	void *driver;
-	char *name;
-	char *phys;
+	void *port_data;
+
+	char name[32];
+	char phys[32];
+
+	unsigned int manual_bind;
 
 	unsigned short idbus;
 	unsigned short idvendor;
@@ -32,31 +37,43 @@
 	unsigned long type;
 	unsigned long event;
 
+	spinlock_t lock;		/* protects critical sections from port's interrupt handler */
+
 	int (*write)(struct serio *, unsigned char);
 	int (*open)(struct serio *);
 	void (*close)(struct serio *);
 
-	struct serio_dev *dev;
+	struct serio *parent, *child;
+
+	struct serio_driver *drv;	/* accessed from interrupt, must be protected by serio->lock */
+
+	struct device dev;
 
 	struct list_head node;
 };
+#define to_serio_port(d)	container_of(d, struct serio, dev)
 
-struct serio_dev {
+struct serio_driver {
 	void *private;
-	char *name;
+	char *description;
+
+	unsigned int manual_bind;
 
 	void (*write_wakeup)(struct serio *);
 	irqreturn_t (*interrupt)(struct serio *, unsigned char,
 			unsigned int, struct pt_regs *);
-	void (*connect)(struct serio *, struct serio_dev *dev);
+	void (*connect)(struct serio *, struct serio_driver *drv);
 	int  (*reconnect)(struct serio *);
 	void (*disconnect)(struct serio *);
 	void (*cleanup)(struct serio *);
 
+	struct device_driver driver;
+
 	struct list_head node;
 };
+#define to_serio_driver(d)	container_of(d, struct serio_driver, driver)
 
-int serio_open(struct serio *serio, struct serio_dev *dev);
+int serio_open(struct serio *serio, struct serio_driver *drv);
 void serio_close(struct serio *serio);
 void serio_rescan(struct serio *serio);
 void serio_reconnect(struct serio *serio);
@@ -64,12 +81,11 @@
 
 void serio_register_port(struct serio *serio);
 void serio_register_port_delayed(struct serio *serio);
-void __serio_register_port(struct serio *serio);
 void serio_unregister_port(struct serio *serio);
 void serio_unregister_port_delayed(struct serio *serio);
-void __serio_unregister_port(struct serio *serio);
-void serio_register_device(struct serio_dev *dev);
-void serio_unregister_device(struct serio_dev *dev);
+
+void serio_register_driver(struct serio_driver *drv);
+void serio_unregister_driver(struct serio_driver *drv);
 
 static __inline__ int serio_write(struct serio *serio, unsigned char data)
 {
@@ -79,17 +95,33 @@
 		return -1;
 }
 
-static __inline__ void serio_dev_write_wakeup(struct serio *serio)
+static __inline__ void serio_drv_write_wakeup(struct serio *serio)
 {
-	if (serio->dev && serio->dev->write_wakeup)
-		serio->dev->write_wakeup(serio);
+	if (serio->drv && serio->drv->write_wakeup)
+		serio->drv->write_wakeup(serio);
 }
 
 static __inline__ void serio_cleanup(struct serio *serio)
 {
-	if (serio->dev && serio->dev->cleanup)
-		serio->dev->cleanup(serio);
+	if (serio->drv && serio->drv->cleanup)
+		serio->drv->cleanup(serio);
 }
+
+
+/*
+ * Use the following fucntions to protect critical sections in
+ * driver code from port's interrupt handler
+ */
+static __inline__ void serio_pause_rx(struct serio *serio)
+{
+	spin_lock_irq(&serio->lock);
+}
+
+static __inline__ void serio_continue_rx(struct serio *serio)
+{
+	spin_unlock_irq(&serio->lock);
+}
+
 
 #endif
 
diff -Nru a/include/linux/shm.h b/include/linux/shm.h
--- a/include/linux/shm.h	2004-10-18 14:56:49 -07:00
+++ b/include/linux/shm.h	2004-10-18 14:56:49 -07:00
@@ -44,6 +44,7 @@
 #define	SHM_RDONLY	010000	/* read-only access */
 #define	SHM_RND		020000	/* round attach address to SHMLBA boundary */
 #define	SHM_REMAP	040000	/* take-over region on attach */
+#define	SHM_EXEC	0100000	/* execution access */
 
 /* super user shmctl commands */
 #define SHM_LOCK 	11
@@ -84,6 +85,7 @@
 	time_t			shm_ctim;
 	pid_t			shm_cprid;
 	pid_t			shm_lprid;
+	struct user_struct	*mlock_user;
 };
 
 /* shm_mode upper byte flags */
diff -Nru a/include/linux/shmem_fs.h b/include/linux/shmem_fs.h
--- a/include/linux/shmem_fs.h	2004-10-18 14:56:50 -07:00
+++ b/include/linux/shmem_fs.h	2004-10-18 14:56:50 -07:00
@@ -10,14 +10,14 @@
 
 struct shmem_inode_info {
 	spinlock_t		lock;
-	unsigned long		next_index;
-	swp_entry_t		i_direct[SHMEM_NR_DIRECT]; /* for the first blocks */
-	struct page	       *i_indirect; /* indirect blocks */
-	unsigned long		alloced;    /* data pages allocated to file */
-	unsigned long		swapped;    /* subtotal assigned to swap */
 	unsigned long		flags;
-	struct shared_policy     policy;
-	struct list_head	list;
+	unsigned long		alloced;	/* data pages alloced to file */
+	unsigned long		swapped;	/* subtotal assigned to swap */
+	unsigned long		next_index;	/* highest alloced index + 1 */
+	struct shared_policy	policy;		/* NUMA memory alloc policy */
+	struct page		*i_indirect;	/* top indirect blocks page */
+	swp_entry_t		i_direct[SHMEM_NR_DIRECT]; /* first blocks */
+	struct list_head	swaplist;	/* chain of maybes on swap */
 	struct inode		vfs_inode;
 };
 
diff -Nru a/include/linux/signal.h b/include/linux/signal.h
--- a/include/linux/signal.h	2004-10-18 14:56:17 -07:00
+++ b/include/linux/signal.h	2004-10-18 14:56:17 -07:00
@@ -217,7 +217,7 @@
 
 #ifndef HAVE_ARCH_GET_SIGNAL_TO_DELIVER
 struct pt_regs;
-extern int get_signal_to_deliver(siginfo_t *info, struct pt_regs *regs, void *cookie);
+extern int get_signal_to_deliver(siginfo_t *info, struct k_sigaction *return_ka, struct pt_regs *regs, void *cookie);
 #endif
 
 #endif /* __KERNEL__ */
diff -Nru a/include/linux/skbuff.h b/include/linux/skbuff.h
--- a/include/linux/skbuff.h	2004-10-18 14:56:33 -07:00
+++ b/include/linux/skbuff.h	2004-10-18 14:56:33 -07:00
@@ -89,16 +89,14 @@
 #define NET_CALLER(arg) __builtin_return_address(0)
 #endif
 
+struct net_device;
+
 #ifdef CONFIG_NETFILTER
 struct nf_conntrack {
 	atomic_t use;
 	void (*destroy)(struct nf_conntrack *);
 };
 
-struct nf_ct_info {
-	struct nf_conntrack *master;
-};
-
 #ifdef CONFIG_BRIDGE_NETFILTER
 struct nf_bridge_info {
 	atomic_t use;
@@ -184,6 +182,7 @@
  *	@nfmark: Can be used for communication between hooks
  *	@nfcache: Cache info
  *	@nfct: Associated connection, if any
+ *	@nfctinfo: Relationship of this skb to the connection
  *	@nf_debug: Netfilter debugging
  *	@nf_bridge: Saved data about a bridged frame - see br_netfilter.c
  *      @private: Data which is private to the HIPPI implementation
@@ -220,7 +219,6 @@
 	} nh;
 
 	union {
-	  	struct ethhdr	*ethernet;
 	  	unsigned char 	*raw;
 	} mac;
 
@@ -251,7 +249,8 @@
 #ifdef CONFIG_NETFILTER
         unsigned long		nfmark;
 	__u32			nfcache;
-	struct nf_ct_info	*nfct;
+	__u32			nfctinfo;
+	struct nf_conntrack	*nfct;
 #ifdef CONFIG_NETFILTER_DEBUG
         unsigned int		nf_debug;
 #endif
@@ -269,7 +268,7 @@
 #ifdef CONFIG_NET_CLS_ACT
 	__u32           tc_verd;               /* traffic control verdict */
 	__u32           tc_classid;            /* traffic control classid */
- #endif
+#endif
 
 #endif
 
@@ -1105,6 +1104,20 @@
 extern void	       skb_split(struct sk_buff *skb,
 				 struct sk_buff *skb1, const u32 len);
 
+static inline void *skb_header_pointer(const struct sk_buff *skb, int offset,
+				       int len, void *buffer)
+{
+	int hlen = skb_headlen(skb);
+
+	if (offset + len <= hlen)
+		return skb->data + offset;
+
+	if (skb_copy_bits(skb, offset, buffer, len) < 0)
+		return NULL;
+
+	return buffer;
+}
+
 extern void skb_init(void);
 extern void skb_add_mtu(int mtu);
 
@@ -1125,20 +1138,26 @@
 extern void skb_iter_abort(const struct sk_buff *skb, struct skb_iter *i);
 
 #ifdef CONFIG_NETFILTER
-static inline void nf_conntrack_put(struct nf_ct_info *nfct)
+static inline void nf_conntrack_put(struct nf_conntrack *nfct)
 {
-	if (nfct && atomic_dec_and_test(&nfct->master->use))
-		nfct->master->destroy(nfct->master);
+	if (nfct && atomic_dec_and_test(&nfct->use))
+		nfct->destroy(nfct);
 }
-static inline void nf_conntrack_get(struct nf_ct_info *nfct)
+static inline void nf_conntrack_get(struct nf_conntrack *nfct)
 {
 	if (nfct)
-		atomic_inc(&nfct->master->use);
+		atomic_inc(&nfct->use);
 }
 static inline void nf_reset(struct sk_buff *skb)
 {
 	nf_conntrack_put(skb->nfct);
 	skb->nfct = NULL;
+#ifdef CONFIG_NETFILTER_DEBUG
+	skb->nf_debug = 0;
+#endif
+}
+static inline void nf_reset_debug(struct sk_buff *skb)
+{
 #ifdef CONFIG_NETFILTER_DEBUG
 	skb->nf_debug = 0;
 #endif
diff -Nru a/include/linux/slab.h b/include/linux/slab.h
--- a/include/linux/slab.h	2004-10-18 14:57:04 -07:00
+++ b/include/linux/slab.h	2004-10-18 14:57:04 -07:00
@@ -4,7 +4,7 @@
  * (markhe@nextd.demon.co.uk)
  */
 
-#if	!defined(_LINUX_SLAB_H)
+#ifndef _LINUX_SLAB_H
 #define	_LINUX_SLAB_H
 
 #if	defined(__KERNEL__)
@@ -45,6 +45,7 @@
 #define SLAB_RECLAIM_ACCOUNT	0x00020000UL	/* track pages allocated to indicate
 						   what is reclaimable later*/
 #define SLAB_PANIC		0x00040000UL	/* panic if kmem_cache_create() fails */
+#define SLAB_DESTROY_BY_RCU	0x00080000UL	/* defer freeing pages to RCU */
 
 /* flags passed to a constructor func */
 #define	SLAB_CTOR_CONSTRUCTOR	0x001UL		/* if not set, then deconstructor */
@@ -54,7 +55,6 @@
 /* prototypes */
 extern void kmem_cache_init(void);
 
-extern kmem_cache_t *kmem_find_general_cachep(size_t, int gfpflags);
 extern kmem_cache_t *kmem_cache_create(const char *, size_t, size_t, unsigned long,
 				       void (*)(void *, kmem_cache_t *, unsigned long),
 				       void (*)(void *, kmem_cache_t *, unsigned long));
@@ -97,6 +97,7 @@
 	return __kmalloc(size, flags);
 }
 
+extern void *kcalloc(size_t, size_t, int);
 extern void kfree(const void *);
 extern unsigned int ksize(const void *);
 
@@ -114,8 +115,6 @@
 extern kmem_cache_t	*signal_cachep;
 extern kmem_cache_t	*sighand_cachep;
 extern kmem_cache_t	*bio_cachep;
-
-void ptrinfo(unsigned long addr);
 
 extern atomic_t slab_reclaim_pages;
 
diff -Nru a/include/linux/socket.h b/include/linux/socket.h
--- a/include/linux/socket.h	2004-10-18 14:56:49 -07:00
+++ b/include/linux/socket.h	2004-10-18 14:56:49 -07:00
@@ -140,7 +140,6 @@
 
 #define	SCM_RIGHTS	0x01		/* rw: access rights (array of int) */
 #define SCM_CREDENTIALS 0x02		/* rw: struct ucred		*/
-#define SCM_CONNECT	0x03		/* rw: struct scm_connect	*/
 
 struct ucred {
 	__u32	pid;
diff -Nru a/include/linux/spinlock.h b/include/linux/spinlock.h
--- a/include/linux/spinlock.h	2004-10-18 14:56:31 -07:00
+++ b/include/linux/spinlock.h	2004-10-18 14:56:31 -07:00
@@ -19,18 +19,18 @@
 /*
  * Must define these before including other files, inline functions need them
  */
-#define LOCK_SECTION_NAME			\
-	".text.lock." __stringify(KBUILD_BASENAME)
+#define LOCK_SECTION_NAME                       \
+        ".text.lock." __stringify(KBUILD_BASENAME)
 
-#define LOCK_SECTION_START(extra)		\
-	".subsection 1\n\t"			\
-	extra					\
-	".ifndef " LOCK_SECTION_NAME "\n\t"	\
-	LOCK_SECTION_NAME ":\n\t"		\
-	".endif\n\t"
+#define LOCK_SECTION_START(extra)               \
+        ".subsection 1\n\t"                     \
+        extra                                   \
+        ".ifndef " LOCK_SECTION_NAME "\n\t"     \
+        LOCK_SECTION_NAME ":\n\t"               \
+        ".endif\n\t"
 
-#define LOCK_SECTION_END			\
-	".previous\n\t"
+#define LOCK_SECTION_END                        \
+        ".previous\n\t"
 
 /*
  * If CONFIG_SMP is set, pull in the _raw_* definitions
@@ -38,9 +38,40 @@
 #ifdef CONFIG_SMP
 #include <asm/spinlock.h>
 
+#define __lockfunc fastcall __attribute__((section(".spinlock.text")))
+
+int __lockfunc _spin_trylock(spinlock_t *lock);
+int __lockfunc _write_trylock(rwlock_t *lock);
+void __lockfunc _spin_lock(spinlock_t *lock);
+void __lockfunc _write_lock(rwlock_t *lock);
+void __lockfunc _spin_lock(spinlock_t *lock);
+void __lockfunc _read_lock(rwlock_t *lock);
+void __lockfunc _spin_unlock(spinlock_t *lock);
+void __lockfunc _write_unlock(rwlock_t *lock);
+void __lockfunc _read_unlock(rwlock_t *lock);
+unsigned long __lockfunc _spin_lock_irqsave(spinlock_t *lock);
+unsigned long __lockfunc _read_lock_irqsave(rwlock_t *lock);
+unsigned long __lockfunc _write_lock_irqsave(rwlock_t *lock);
+void __lockfunc _spin_lock_irq(spinlock_t *lock);
+void __lockfunc _spin_lock_bh(spinlock_t *lock);
+void __lockfunc _read_lock_irq(rwlock_t *lock);
+void __lockfunc _read_lock_bh(rwlock_t *lock);
+void __lockfunc _write_lock_irq(rwlock_t *lock);
+void __lockfunc _write_lock_bh(rwlock_t *lock);
+void __lockfunc _spin_unlock_irqrestore(spinlock_t *lock, unsigned long flags);
+void __lockfunc _spin_unlock_irq(spinlock_t *lock);
+void __lockfunc _spin_unlock_bh(spinlock_t *lock);
+void __lockfunc _read_unlock_irqrestore(rwlock_t *lock, unsigned long flags);
+void __lockfunc _read_unlock_irq(rwlock_t *lock);
+void __lockfunc _read_unlock_bh(rwlock_t *lock);
+void __lockfunc _write_unlock_irqrestore(rwlock_t *lock, unsigned long flags);
+void __lockfunc _write_unlock_irq(rwlock_t *lock);
+void __lockfunc _write_unlock_bh(rwlock_t *lock);
+int __lockfunc _spin_trylock_bh(spinlock_t *lock);
+int in_lock_functions(unsigned long addr);
 #else
 
-#define _raw_spin_lock_flags(lock, flags) _raw_spin_lock(lock)
+#define in_lock_functions(ADDR) 0
 
 #if !defined(CONFIG_PREEMPT) && !defined(CONFIG_DEBUG_SPINLOCK)
 # define atomic_dec_and_lock(atomic,lock) atomic_dec_and_test(atomic)
@@ -162,9 +193,9 @@
 #define spin_lock_init(lock)	do { (void)(lock); } while(0)
 #define _raw_spin_lock(lock)	do { (void)(lock); } while(0)
 #define spin_is_locked(lock)	((void)(lock), 0)
-#define _raw_spin_trylock(lock)	((void)(lock), 1)
-#define spin_unlock_wait(lock)	do { (void)(lock); } while(0)
-#define _raw_spin_unlock(lock)	do { (void)(lock); } while(0)
+#define _raw_spin_trylock(lock)	(((void)(lock), 1))
+#define spin_unlock_wait(lock)	(void)(lock);
+#define _raw_spin_unlock(lock) do { (void)(lock); } while(0)
 #endif /* CONFIG_DEBUG_SPINLOCK */
 
 /* RW spinlocks: No debug version */
@@ -184,141 +215,116 @@
 #define _raw_write_unlock(lock)	do { (void)(lock); } while(0)
 #define _raw_write_trylock(lock) ({ (void)(lock); (1); })
 
-#endif /* !SMP */
-
-/*
- * Define the various spin_lock and rw_lock methods.  Note we define these
- * regardless of whether CONFIG_SMP or CONFIG_PREEMPT are set. The various
- * methods are defined as nops in the case they are not required.
- */
-#define spin_trylock(lock)	({preempt_disable(); _raw_spin_trylock(lock) ? \
+#define _spin_trylock(lock)	({preempt_disable(); _raw_spin_trylock(lock) ? \
 				1 : ({preempt_enable(); 0;});})
 
-#define write_trylock(lock)	({preempt_disable();_raw_write_trylock(lock) ? \
+#define _write_trylock(lock)	({preempt_disable(); _raw_write_trylock(lock) ? \
 				1 : ({preempt_enable(); 0;});})
 
-/* Where's read_trylock? */
-
-#if defined(CONFIG_SMP) && defined(CONFIG_PREEMPT)
-void __preempt_spin_lock(spinlock_t *lock);
-void __preempt_write_lock(rwlock_t *lock);
-
-#define spin_lock(lock) \
-do { \
-	preempt_disable(); \
-	if (unlikely(!_raw_spin_trylock(lock))) \
-		__preempt_spin_lock(lock); \
-} while (0)
-
-#define write_lock(lock) \
-do { \
-	preempt_disable(); \
-	if (unlikely(!_raw_write_trylock(lock))) \
-		__preempt_write_lock(lock); \
-} while (0)
+#define _spin_trylock_bh(lock)	({preempt_disable(); local_bh_disable(); \
+				_raw_spin_trylock(lock) ? \
+				1 : ({preempt_enable(); local_bh_enable(); 0;});})
 
-#else
-#define spin_lock(lock)	\
+#define _spin_lock(lock)	\
 do { \
 	preempt_disable(); \
 	_raw_spin_lock(lock); \
 } while(0)
 
-#define write_lock(lock) \
+#define _write_lock(lock) \
 do { \
 	preempt_disable(); \
 	_raw_write_lock(lock); \
 } while(0)
-#endif
-
-#define read_lock(lock)	\
+ 
+#define _read_lock(lock)	\
 do { \
 	preempt_disable(); \
 	_raw_read_lock(lock); \
 } while(0)
 
-#define spin_unlock(lock) \
+#define _spin_unlock(lock) \
 do { \
 	_raw_spin_unlock(lock); \
 	preempt_enable(); \
 } while (0)
 
-#define write_unlock(lock) \
+#define _write_unlock(lock) \
 do { \
 	_raw_write_unlock(lock); \
 	preempt_enable(); \
 } while(0)
 
-#define read_unlock(lock) \
+#define _read_unlock(lock) \
 do { \
 	_raw_read_unlock(lock); \
 	preempt_enable(); \
 } while(0)
 
-#define spin_lock_irqsave(lock, flags) \
-do { \
+#define _spin_lock_irqsave(lock, flags) \
+do {	\
 	local_irq_save(flags); \
 	preempt_disable(); \
-	_raw_spin_lock_flags(lock, flags); \
+	_raw_spin_lock(lock); \
 } while (0)
 
-#define spin_lock_irq(lock) \
+#define _spin_lock_irq(lock) \
 do { \
 	local_irq_disable(); \
 	preempt_disable(); \
 	_raw_spin_lock(lock); \
 } while (0)
 
-#define spin_lock_bh(lock) \
+#define _spin_lock_bh(lock) \
 do { \
 	local_bh_disable(); \
 	preempt_disable(); \
 	_raw_spin_lock(lock); \
 } while (0)
 
-#define read_lock_irqsave(lock, flags) \
-do { \
+#define _read_lock_irqsave(lock, flags) \
+do {	\
 	local_irq_save(flags); \
 	preempt_disable(); \
 	_raw_read_lock(lock); \
 } while (0)
 
-#define read_lock_irq(lock) \
+#define _read_lock_irq(lock) \
 do { \
 	local_irq_disable(); \
 	preempt_disable(); \
 	_raw_read_lock(lock); \
 } while (0)
 
-#define read_lock_bh(lock) \
+#define _read_lock_bh(lock) \
 do { \
 	local_bh_disable(); \
 	preempt_disable(); \
 	_raw_read_lock(lock); \
 } while (0)
 
-#define write_lock_irqsave(lock, flags) \
-do { \
+#define _write_lock_irqsave(lock, flags) \
+do {	\
 	local_irq_save(flags); \
 	preempt_disable(); \
 	_raw_write_lock(lock); \
 } while (0)
 
-#define write_lock_irq(lock) \
+#define _write_lock_irq(lock) \
 do { \
 	local_irq_disable(); \
 	preempt_disable(); \
 	_raw_write_lock(lock); \
 } while (0)
 
-#define write_lock_bh(lock) \
+#define _write_lock_bh(lock) \
 do { \
 	local_bh_disable(); \
 	preempt_disable(); \
 	_raw_write_lock(lock); \
 } while (0)
 
-#define spin_unlock_irqrestore(lock, flags) \
+#define _spin_unlock_irqrestore(lock, flags) \
 do { \
 	_raw_spin_unlock(lock); \
 	local_irq_restore(flags); \
@@ -331,65 +337,123 @@
 	local_irq_restore(flags); \
 } while (0)
 
-#define spin_unlock_irq(lock) \
+#define _spin_unlock_irq(lock) \
 do { \
 	_raw_spin_unlock(lock); \
 	local_irq_enable(); \
 	preempt_enable(); \
 } while (0)
 
-#define spin_unlock_bh(lock) \
+#define _spin_unlock_bh(lock) \
 do { \
 	_raw_spin_unlock(lock); \
 	preempt_enable(); \
 	local_bh_enable(); \
 } while (0)
 
-#define read_unlock_irqrestore(lock, flags) \
+#define _write_unlock_bh(lock) \
 do { \
-	_raw_read_unlock(lock); \
-	local_irq_restore(flags); \
+	_raw_write_unlock(lock); \
 	preempt_enable(); \
+	local_bh_enable(); \
 } while (0)
 
-#define read_unlock_irq(lock) \
+#define _read_unlock_irqrestore(lock, flags) \
 do { \
 	_raw_read_unlock(lock); \
-	local_irq_enable(); \
+	local_irq_restore(flags); \
 	preempt_enable(); \
 } while (0)
 
-#define read_unlock_bh(lock) \
+#define _write_unlock_irqrestore(lock, flags) \
 do { \
-	_raw_read_unlock(lock); \
+	_raw_write_unlock(lock); \
+	local_irq_restore(flags); \
 	preempt_enable(); \
-	local_bh_enable(); \
 } while (0)
 
-#define write_unlock_irqrestore(lock, flags) \
+#define _read_unlock_irq(lock)	\
 do { \
-	_raw_write_unlock(lock); \
-	local_irq_restore(flags); \
-	preempt_enable(); \
+	_raw_read_unlock(lock);	\
+	local_irq_enable();	\
+	preempt_enable();	\
 } while (0)
 
-#define write_unlock_irq(lock) \
+#define _read_unlock_bh(lock)	\
 do { \
-	_raw_write_unlock(lock); \
-	local_irq_enable(); \
-	preempt_enable(); \
+	_raw_read_unlock(lock);	\
+	local_bh_enable();	\
+	preempt_enable();	\
 } while (0)
 
-#define write_unlock_bh(lock) \
+#define _write_unlock_irq(lock)	\
 do { \
-	_raw_write_unlock(lock); \
-	preempt_enable(); \
-	local_bh_enable(); \
+	_raw_write_unlock(lock);	\
+	local_irq_enable();	\
+	preempt_enable();	\
 } while (0)
 
-#define spin_trylock_bh(lock)	({ local_bh_disable(); preempt_disable(); \
-				_raw_spin_trylock(lock) ? 1 : \
-				({preempt_enable(); local_bh_enable(); 0;});})
+#endif /* !SMP */
+
+/*
+ * Define the various spin_lock and rw_lock methods.  Note we define these
+ * regardless of whether CONFIG_SMP or CONFIG_PREEMPT are set. The various
+ * methods are defined as nops in the case they are not required.
+ */
+#define spin_trylock(lock)	_spin_trylock(lock)
+#define write_trylock(lock)	_write_trylock(lock)
+
+/* Where's read_trylock? */
+
+#define spin_lock(lock)		_spin_lock(lock)
+#define write_lock(lock)	_write_lock(lock)
+#define read_lock(lock)		_read_lock(lock)
+#define spin_unlock(lock)	_spin_unlock(lock)
+#define write_unlock(lock)	_write_unlock(lock)
+#define read_unlock(lock)	_read_unlock(lock)
+
+#ifdef CONFIG_SMP
+#define spin_lock_irqsave(lock, flags)	flags = _spin_lock_irqsave(lock)
+#define read_lock_irqsave(lock, flags)	flags = _read_lock_irqsave(lock)
+#define write_lock_irqsave(lock, flags)	flags = _write_lock_irqsave(lock)
+#else
+#define spin_lock_irqsave(lock, flags)	_spin_lock_irqsave(lock, flags)
+#define read_lock_irqsave(lock, flags)	_read_lock_irqsave(lock, flags)
+#define write_lock_irqsave(lock, flags)	_write_lock_irqsave(lock, flags)
+#endif
+
+#define spin_lock_irq(lock)		_spin_lock_irq(lock)
+#define spin_lock_bh(lock)		_spin_lock_bh(lock)
+
+#define read_lock_irq(lock)		_read_lock_irq(lock)
+#define read_lock_bh(lock)		_read_lock_bh(lock)
+
+#define write_lock_irq(lock)		_write_lock_irq(lock)
+#define write_lock_bh(lock)		_write_lock_bh(lock)
+#define spin_unlock_irqrestore(lock, flags)	_spin_unlock_irqrestore(lock, flags)
+#define spin_unlock_irq(lock)		_spin_unlock_irq(lock)
+#define spin_unlock_bh(lock)		_spin_unlock_bh(lock)
+
+#define read_unlock_irqrestore(lock, flags)	_read_unlock_irqrestore(lock, flags)
+#define read_unlock_irq(lock)			_read_unlock_irq(lock)
+#define read_unlock_bh(lock)			_read_unlock_bh(lock)
+
+#define write_unlock_irqrestore(lock, flags)	_write_unlock_irqrestore(lock, flags)
+#define write_unlock_irq(lock)			_write_unlock_irq(lock)
+#define write_unlock_bh(lock)			_write_unlock_bh(lock)
+
+#define spin_trylock_bh(lock)			_spin_trylock_bh(lock)
+
+#ifdef CONFIG_LOCKMETER
+extern void _metered_spin_lock   (spinlock_t *lock);
+extern void _metered_spin_unlock (spinlock_t *lock);
+extern int  _metered_spin_trylock(spinlock_t *lock);
+extern void _metered_read_lock    (rwlock_t *lock);
+extern void _metered_read_unlock  (rwlock_t *lock);
+extern void _metered_write_lock   (rwlock_t *lock);
+extern void _metered_write_unlock (rwlock_t *lock);
+extern int  _metered_write_trylock(rwlock_t *lock);
+#endif
 
 /* "lock on reference count zero" */
 #ifndef ATOMIC_DEC_AND_LOCK
diff -Nru a/include/linux/stddef.h b/include/linux/stddef.h
--- a/include/linux/stddef.h	2004-10-18 14:56:31 -07:00
+++ b/include/linux/stddef.h	2004-10-18 14:56:31 -07:00
@@ -1,6 +1,8 @@
 #ifndef _LINUX_STDDEF_H
 #define _LINUX_STDDEF_H
 
+#include <linux/compiler.h>
+
 #undef NULL
 #if defined(__cplusplus)
 #define NULL 0
@@ -9,6 +11,10 @@
 #endif
 
 #undef offsetof
+#ifdef __compiler_offsetof
+#define offsetof(TYPE,MEMBER) __compiler_offsetof(TYPE,MEMBER)
+#else
 #define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)
+#endif
 
 #endif
diff -Nru a/include/linux/sunrpc/auth_gss.h b/include/linux/sunrpc/auth_gss.h
--- a/include/linux/sunrpc/auth_gss.h	2004-10-18 14:55:55 -07:00
+++ b/include/linux/sunrpc/auth_gss.h	2004-10-18 14:55:55 -07:00
@@ -15,11 +15,9 @@
 #define _LINUX_SUNRPC_AUTH_GSS_H
 
 #ifdef __KERNEL__
-#ifdef __linux__
 #include <linux/sunrpc/auth.h>
 #include <linux/sunrpc/svc.h>
 #include <linux/sunrpc/gss_api.h>
-#endif
 
 #define RPC_GSS_VERSION		1
 
diff -Nru a/include/linux/sunrpc/cache.h b/include/linux/sunrpc/cache.h
--- a/include/linux/sunrpc/cache.h	2004-10-18 14:56:32 -07:00
+++ b/include/linux/sunrpc/cache.h	2004-10-18 14:56:32 -07:00
@@ -161,6 +161,10 @@
  * INIT copies key information from "item" to "new"
  * UPDATE copies content information from "item" to "tmp"
  * INPLACE is true if updates can happen inplace rather than allocating a new structure
+ *
+ * WARNING: any substantial changes to this must be reflected in
+ *   net/sunrpc/svcauth.c(auth_domain_lookup)
+ *  which is a similar routine that is open-coded.
  */
 #define DefineCacheLookup(RTN,MEMBER,FNAME,ARGS,SETUP,DETAIL,HASHFN,TEST,INIT,UPDATE,INPLACE)	\
 RTN *FNAME ARGS										\
@@ -233,7 +237,6 @@
 	new = kmalloc(sizeof(*new), GFP_KERNEL);					\
 	if (new) {									\
 		cache_init(&new->MEMBER);						\
-		cache_get(&new->MEMBER);						\
 		goto retry;								\
 	}										\
 	return NULL;									\
diff -Nru a/include/linux/sunrpc/gss_asn1.h b/include/linux/sunrpc/gss_asn1.h
--- a/include/linux/sunrpc/gss_asn1.h	2004-10-18 14:57:04 -07:00
+++ b/include/linux/sunrpc/gss_asn1.h	2004-10-18 14:57:04 -07:00
@@ -69,7 +69,6 @@
      struct xdr_netobj *mech,
      int *body_size,
      unsigned char **buf_in,
-     int tok_type,
      int toksize);
 
 u32 g_get_mech_oid(struct xdr_netobj *mech, struct xdr_netobj * in_buf);
diff -Nru a/include/linux/sunrpc/gss_spkm3.h b/include/linux/sunrpc/gss_spkm3.h
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/include/linux/sunrpc/gss_spkm3.h	2004-10-18 14:57:23 -07:00
@@ -0,0 +1,61 @@
+/*
+ *  linux/include/linux/sunrpc/gss_spkm3.h
+ *
+ *  Copyright (c) 2000 The Regents of the University of Michigan.
+ *  All rights reserved.
+ *
+ *  Andy Adamson   <andros@umich.edu>
+ */
+
+#include <linux/sunrpc/auth_gss.h>
+#include <linux/sunrpc/gss_err.h>
+#include <linux/sunrpc/gss_asn1.h>
+
+struct spkm3_ctx {
+	struct xdr_netobj	ctx_id; /* per message context id */
+	int			qop;         /* negotiated qop */
+	struct xdr_netobj	mech_used;
+	unsigned int		ret_flags ;
+	unsigned int		req_flags ;
+	struct xdr_netobj	share_key;
+	int			conf_alg;
+	struct crypto_tfm*	derived_conf_key;
+	int			intg_alg;
+	struct crypto_tfm*	derived_integ_key;
+	int			keyestb_alg;   /* alg used to get share_key */
+	int			owf_alg;   /* one way function */
+};
+
+/* from openssl/objects.h */
+/* XXX need SEAL_ALG_NONE */
+#define NID_md5		4
+#define NID_dhKeyAgreement	28 
+#define NID_des_cbc		31 
+#define NID_sha1		64
+#define NID_cast5_cbc		108
+
+/* SPKM InnerContext Token types */
+
+#define SPKM_ERROR_TOK	3
+#define SPKM_MIC_TOK	4
+#define SPKM_WRAP_TOK	5
+#define SPKM_DEL_TOK	6
+
+u32 spkm3_make_token(struct spkm3_ctx *ctx, int qop_req, struct xdr_buf * text, struct xdr_netobj * token, int toktype);
+
+u32 spkm3_read_token(struct spkm3_ctx *ctx, struct xdr_netobj *read_token, struct xdr_buf *message_buffer, int *qop_state, int toktype);
+
+#define CKSUMTYPE_RSA_MD5            0x0007
+
+s32 make_checksum(s32 cksumtype, char *header, int hdrlen, struct xdr_buf *body,
+                   struct xdr_netobj *cksum);
+void asn1_bitstring_len(struct xdr_netobj *in, int *enclen, int *zerobits);
+int decode_asn1_bitstring(struct xdr_netobj *out, char *in, int enclen, 
+                   int explen);
+void spkm3_mic_header(unsigned char **hdrbuf, unsigned int *hdrlen, 
+                   unsigned char *ctxhdr, int elen, int zbit);
+void spkm3_make_mic_token(unsigned  char **tokp, int toklen, 
+                   struct xdr_netobj *mic_hdr,
+                   struct xdr_netobj *md5cksum, int md5elen, int md5zbit);
+u32 spkm3_verify_mic_token(unsigned char **tokp, int *mic_hdrlen, 
+                   unsigned char **cksum);
diff -Nru a/include/linux/sunrpc/sched.h b/include/linux/sunrpc/sched.h
--- a/include/linux/sunrpc/sched.h	2004-10-18 14:56:48 -07:00
+++ b/include/linux/sunrpc/sched.h	2004-10-18 14:56:48 -07:00
@@ -113,6 +113,7 @@
 #define RPC_TASK_DYNAMIC	0x0080		/* task was kmalloc'ed */
 #define RPC_TASK_KILLED		0x0100		/* task was killed */
 #define RPC_TASK_SOFT		0x0200		/* Use soft timeouts */
+#define RPC_TASK_NOINTR		0x0400		/* uninterruptible task */
 
 #define RPC_IS_ASYNC(t)		((t)->tk_flags & RPC_TASK_ASYNC)
 #define RPC_IS_SETUID(t)	((t)->tk_flags & RPC_TASK_SETUID)
@@ -123,6 +124,7 @@
 #define RPC_IS_ACTIVATED(t)	((t)->tk_active)
 #define RPC_DO_CALLBACK(t)	((t)->tk_callback != NULL)
 #define RPC_IS_SOFT(t)		((t)->tk_flags & RPC_TASK_SOFT)
+#define RPC_TASK_UNINTERRUPTIBLE(t) ((t)->tk_flags & RPC_TASK_NOINTR)
 
 #define RPC_TASK_SLEEPING	0
 #define RPC_TASK_RUNNING	1
diff -Nru a/include/linux/sunrpc/svc.h b/include/linux/sunrpc/svc.h
--- a/include/linux/sunrpc/svc.h	2004-10-18 14:56:32 -07:00
+++ b/include/linux/sunrpc/svc.h	2004-10-18 14:56:32 -07:00
@@ -87,6 +87,14 @@
 	iov->iov_len -= sizeof(u32);
 	return val;
 }
+
+static inline void svc_ungetu32(struct kvec *iov)
+{
+	u32 *vp = (u32 *)iov->iov_base;
+	iov->iov_base = (void *)(vp - 1);
+	iov->iov_len += sizeof(*vp);
+}
+
 static inline void svc_putu32(struct kvec *iov, u32 val)
 {
 	u32 *vp = iov->iov_base + iov->iov_len;
@@ -243,6 +251,8 @@
 	char *			pg_name;	/* service name */
 	char *			pg_class;	/* class name: services sharing authentication */
 	struct svc_stat *	pg_stats;	/* rpc statistics */
+	/* Override authentication. NULL means use default */
+	int			(*pg_authenticate)(struct svc_rqst *, u32 *);
 };
 
 /*
diff -Nru a/include/linux/suspend.h b/include/linux/suspend.h
--- a/include/linux/suspend.h	2004-10-18 14:56:21 -07:00
+++ b/include/linux/suspend.h	2004-10-18 14:56:21 -07:00
@@ -23,16 +23,6 @@
 
 #define SWAP_FILENAME_MAXLENGTH	32
 
-struct suspend_header {
-	u32 version_code;
-	unsigned long num_physpages;
-	char machine[8];
-	char version[20];
-	int num_cpus;
-	int page_size;
-	suspend_pagedir_t *suspend_pagedir;
-	unsigned int num_pbes;
-};
 
 #define SUSPEND_PD_PAGES(x)     (((x)*sizeof(struct pbe))/PAGE_SIZE+1)
    
@@ -45,16 +35,12 @@
 /* kernel/power/swsusp.c */
 extern int software_suspend(void);
 
-extern unsigned int nr_copy_pages __nosavedata;
-extern suspend_pagedir_t *pagedir_nosave __nosavedata;
-
 #else	/* CONFIG_SOFTWARE_SUSPEND */
 static inline int software_suspend(void)
 {
 	printk("Warning: fake suspend called\n");
 	return -EPERM;
 }
-#define software_resume()		do { } while(0)
 #endif	/* CONFIG_SOFTWARE_SUSPEND */
 
 
@@ -77,12 +63,6 @@
 static inline void disable_nonboot_cpus(void) {}
 static inline void enable_nonboot_cpus(void) {}
 #endif
-
-asmlinkage void do_magic(int is_resume);
-asmlinkage void do_magic_resume_1(void);
-asmlinkage void do_magic_resume_2(void);
-asmlinkage void do_magic_suspend_1(void);
-asmlinkage void do_magic_suspend_2(void);
 
 void save_processor_state(void);
 void restore_processor_state(void);
diff -Nru a/include/linux/swap.h b/include/linux/swap.h
--- a/include/linux/swap.h	2004-10-18 14:55:54 -07:00
+++ b/include/linux/swap.h	2004-10-18 14:55:54 -07:00
@@ -204,7 +204,6 @@
 extern struct page * lookup_swap_cache(swp_entry_t);
 extern struct page * read_swap_cache_async(swp_entry_t, struct vm_area_struct *vma,
 					   unsigned long addr);
-
 /* linux/mm/swapfile.c */
 extern long total_swap_pages;
 extern unsigned int nr_swapfiles;
@@ -229,6 +228,22 @@
 #define swap_device_lock(p)	spin_lock(&p->sdev_lock)
 #define swap_device_unlock(p)	spin_unlock(&p->sdev_lock)
 
+/* linux/mm/thrash.c */
+extern struct mm_struct * swap_token_mm;
+extern void grab_swap_token(void);
+extern void __put_swap_token(struct mm_struct *);
+
+static inline int has_swap_token(struct mm_struct *mm)
+{
+	return (mm == swap_token_mm);
+}
+
+static inline void put_swap_token(struct mm_struct *mm)
+{
+	if (has_swap_token(mm))
+		__put_swap_token(mm);
+}
+
 #else /* CONFIG_SWAP */
 
 #define total_swap_pages			0
@@ -265,6 +280,11 @@
 	entry.val = 0;
 	return entry;
 }
+
+/* linux/mm/thrash.c */
+#define put_swap_token(x) do { } while(0)
+#define grab_swap_token()  do { } while(0)
+#define has_swap_token(x) 0
 
 #endif /* CONFIG_SWAP */
 #endif /* __KERNEL__*/
diff -Nru a/include/linux/syscalls.h b/include/linux/syscalls.h
--- a/include/linux/syscalls.h	2004-10-18 14:57:05 -07:00
+++ b/include/linux/syscalls.h	2004-10-18 14:57:05 -07:00
@@ -114,6 +114,9 @@
 asmlinkage long sys_setitimer(int which,
 				struct itimerval __user *value,
 				struct itimerval __user *ovalue);
+asmlinkage long sys_timer_create(clockid_t which_clock,
+				 struct sigevent __user *timer_event_spec,
+				 timer_t __user * created_timer_id);
 asmlinkage long sys_timer_gettime(timer_t timer_id,
 				struct itimerspec __user *setting);
 asmlinkage long sys_timer_getoverrun(timer_t timer_id);
@@ -160,9 +163,12 @@
 
 asmlinkage long sys_exit(int error_code);
 asmlinkage void sys_exit_group(int error_code);
-asmlinkage long sys_wait4(pid_t pid, unsigned int __user *stat_addr,
+asmlinkage long sys_wait4(pid_t pid, int __user *stat_addr,
 				int options, struct rusage __user *ru);
-asmlinkage long sys_waitpid(pid_t pid, unsigned int __user *stat_addr, int options);
+asmlinkage long sys_waitid(int which, pid_t pid,
+			   struct siginfo __user *infop,
+			   int options, struct rusage __user *ru);
+asmlinkage long sys_waitpid(pid_t pid, int __user *stat_addr, int options);
 asmlinkage long sys_set_tid_address(int __user *tidptr);
 asmlinkage long sys_futex(u32 __user *uaddr, int op, int val,
 			struct timespec __user *utime, u32 __user *uaddr2,
diff -Nru a/include/linux/sysctl.h b/include/linux/sysctl.h
--- a/include/linux/sysctl.h	2004-10-18 14:56:32 -07:00
+++ b/include/linux/sysctl.h	2004-10-18 14:56:32 -07:00
@@ -133,6 +133,7 @@
 	KERN_NGROUPS_MAX=63,	/* int: NGROUPS_MAX */
 	KERN_SPARC_SCONS_PWROFF=64, /* int: serial console power-off halt */
 	KERN_HZ_TIMER=65,	/* int: hz timer on or off */
+	KERN_UNKNOWN_NMI_PANIC=66, /* int: unknown nmi panic flag */
 };
 
 
@@ -165,6 +166,7 @@
 	VM_BLOCK_DUMP=24,	/* block dump mode */
 	VM_HUGETLB_GROUP=25,	/* permitted hugetlb group */
 	VM_VFS_CACHE_PRESSURE=26, /* dcache/icache reclaim pressure */
+	VM_LEGACY_VA_LAYOUT=27, /* legacy/compatibility virtual address space layout */
 };
 
 
@@ -339,6 +341,7 @@
 	NET_TCP_BIC_LOW_WINDOW=104,
 	NET_TCP_DEFAULT_WIN_SCALE=105,
 	NET_TCP_MODERATE_RCVBUF=106,
+	NET_TCP_TSO_WIN_DIVISOR=107,
 };
 
 enum {
@@ -410,6 +413,19 @@
 	NET_IPV4_NF_CONNTRACK_ICMP_TIMEOUT=12,
 	NET_IPV4_NF_CONNTRACK_GENERIC_TIMEOUT=13,
 	NET_IPV4_NF_CONNTRACK_BUCKETS=14,
+	NET_IPV4_NF_CONNTRACK_LOG_INVALID=15,
+	NET_IPV4_NF_CONNTRACK_TCP_TIMEOUT_MAX_RETRANS=16,
+	NET_IPV4_NF_CONNTRACK_TCP_LOOSE=17,
+	NET_IPV4_NF_CONNTRACK_TCP_BE_LIBERAL=18,
+	NET_IPV4_NF_CONNTRACK_TCP_MAX_RETRANS=19,
+ 	NET_IPV4_NF_CONNTRACK_SCTP_TIMEOUT_CLOSED=20,
+ 	NET_IPV4_NF_CONNTRACK_SCTP_TIMEOUT_COOKIE_WAIT=21,
+ 	NET_IPV4_NF_CONNTRACK_SCTP_TIMEOUT_COOKIE_ECHOED=22,
+ 	NET_IPV4_NF_CONNTRACK_SCTP_TIMEOUT_ESTABLISHED=23,
+ 	NET_IPV4_NF_CONNTRACK_SCTP_TIMEOUT_SHUTDOWN_SENT=24,
+ 	NET_IPV4_NF_CONNTRACK_SCTP_TIMEOUT_SHUTDOWN_RECD=25,
+ 	NET_IPV4_NF_CONNTRACK_SCTP_TIMEOUT_SHUTDOWN_ACK_SENT=26,
+	NET_IPV4_NF_CONNTRACK_COUNT=27,
 };
  
 /* /proc/sys/net/ipv6 */
diff -Nru a/include/linux/sysv_fs.h b/include/linux/sysv_fs.h
--- a/include/linux/sysv_fs.h	2004-10-18 14:56:29 -07:00
+++ b/include/linux/sysv_fs.h	2004-10-18 14:56:29 -07:00
@@ -8,13 +8,18 @@
 #endif
 
 
+#ifndef __KERNEL__
+typedef u16 __fs16;
+typedef u32 __fs16;
+#endif
+
 /* inode numbers are 16 bit */
-typedef u16 sysv_ino_t;
+typedef __fs16 sysv_ino_t;
 
 /* Block numbers are 24 bit, sometimes stored in 32 bit.
    On Coherent FS, they are always stored in PDP-11 manner: the least
    significant 16 bits come last. */
-typedef u32 sysv_zone_t;
+typedef __fs32 sysv_zone_t;
 
 /* 0 is non-existent */
 #define SYSV_BADBL_INO	1	/* inode of bad blocks file */
@@ -25,29 +30,29 @@
 #define XENIX_NICINOD	100	/* number of inode cache entries */
 #define XENIX_NICFREE	100	/* number of free block list chunk entries */
 struct xenix_super_block {
-	u16		s_isize; /* index of first data zone */
-	u32		s_fsize __packed2__; /* total number of zones of this fs */
+	__fs16		s_isize; /* index of first data zone */
+	__fs32		s_fsize __packed2__; /* total number of zones of this fs */
 	/* the start of the free block list: */
-	u16		s_nfree;	/* number of free blocks in s_free, <= XENIX_NICFREE */
-	u32		s_free[XENIX_NICFREE]; /* first free block list chunk */
+	__fs16		s_nfree;	/* number of free blocks in s_free, <= XENIX_NICFREE */
+	sysv_zone_t	s_free[XENIX_NICFREE]; /* first free block list chunk */
 	/* the cache of free inodes: */
-	u16		s_ninode; /* number of free inodes in s_inode, <= XENIX_NICINOD */
+	__fs16		s_ninode; /* number of free inodes in s_inode, <= XENIX_NICINOD */
 	sysv_ino_t	s_inode[XENIX_NICINOD]; /* some free inodes */
 	/* locks, not used by Linux: */
 	char		s_flock;	/* lock during free block list manipulation */
 	char		s_ilock;	/* lock during inode cache manipulation */
 	char		s_fmod;		/* super-block modified flag */
 	char		s_ronly;	/* flag whether fs is mounted read-only */
-	u32		s_time __packed2__; /* time of last super block update */
-	u32		s_tfree __packed2__; /* total number of free zones */
-	u16		s_tinode;	/* total number of free inodes */
-	s16		s_dinfo[4];	/* device information ?? */
+	__fs32		s_time __packed2__; /* time of last super block update */
+	__fs32		s_tfree __packed2__; /* total number of free zones */
+	__fs16		s_tinode;	/* total number of free inodes */
+	__fs16		s_dinfo[4];	/* device information ?? */
 	char		s_fname[6];	/* file system volume name */
 	char		s_fpack[6];	/* file system pack name */
 	char		s_clean;	/* set to 0x46 when filesystem is properly unmounted */
 	char		s_fill[371];
 	s32		s_magic;	/* version of file system */
-	s32		s_type;		/* type of file system: 1 for 512 byte blocks
+	__fs32		s_type;		/* type of file system: 1 for 512 byte blocks
 								2 for 1024 byte blocks
 								3 for 2048 byte blocks */
 								
@@ -63,15 +68,15 @@
 
 /* SystemV4 super-block data on disk */
 struct sysv4_super_block {
-	u16	s_isize;	/* index of first data zone */
+	__fs16	s_isize;	/* index of first data zone */
 	u16	s_pad0;
-	u32	s_fsize;	/* total number of zones of this fs */
+	__fs32	s_fsize;	/* total number of zones of this fs */
 	/* the start of the free block list: */
-	u16	s_nfree;	/* number of free blocks in s_free, <= SYSV_NICFREE */
+	__fs16	s_nfree;	/* number of free blocks in s_free, <= SYSV_NICFREE */
 	u16	s_pad1;
-	u32	s_free[SYSV_NICFREE]; /* first free block list chunk */
+	sysv_zone_t	s_free[SYSV_NICFREE]; /* first free block list chunk */
 	/* the cache of free inodes: */
-	u16	s_ninode;	/* number of free inodes in s_inode, <= SYSV_NICINOD */
+	__fs16	s_ninode;	/* number of free inodes in s_inode, <= SYSV_NICINOD */
 	u16	s_pad2;
 	sysv_ino_t     s_inode[SYSV_NICINOD]; /* some free inodes */
 	/* locks, not used by Linux: */
@@ -79,45 +84,45 @@
 	char	s_ilock;	/* lock during inode cache manipulation */
 	char	s_fmod;		/* super-block modified flag */
 	char	s_ronly;	/* flag whether fs is mounted read-only */
-	u32	s_time;		/* time of last super block update */
-	s16	s_dinfo[4];	/* device information ?? */
-	u32	s_tfree;	/* total number of free zones */
-	u16	s_tinode;	/* total number of free inodes */
+	__fs32	s_time;		/* time of last super block update */
+	__fs16	s_dinfo[4];	/* device information ?? */
+	__fs32	s_tfree;	/* total number of free zones */
+	__fs16	s_tinode;	/* total number of free inodes */
 	u16	s_pad3;
 	char	s_fname[6];	/* file system volume name */
 	char	s_fpack[6];	/* file system pack name */
 	s32	s_fill[12];
-	s32	s_state;	/* file system state: 0x7c269d38-s_time means clean */
+	__fs32	s_state;	/* file system state: 0x7c269d38-s_time means clean */
 	s32	s_magic;	/* version of file system */
-	s32	s_type;		/* type of file system: 1 for 512 byte blocks
+	__fs32	s_type;		/* type of file system: 1 for 512 byte blocks
 								2 for 1024 byte blocks */
 };
 
 /* SystemV2 super-block data on disk */
 struct sysv2_super_block {
-	u16	s_isize; 		/* index of first data zone */
-	u32	s_fsize __packed2__;	/* total number of zones of this fs */
+	__fs16	s_isize; 		/* index of first data zone */
+	__fs32	s_fsize __packed2__;	/* total number of zones of this fs */
 	/* the start of the free block list: */
-	u16	s_nfree;		/* number of free blocks in s_free, <= SYSV_NICFREE */
-	u32	s_free[SYSV_NICFREE];	/* first free block list chunk */
+	__fs16	s_nfree;		/* number of free blocks in s_free, <= SYSV_NICFREE */
+	sysv_zone_t s_free[SYSV_NICFREE];	/* first free block list chunk */
 	/* the cache of free inodes: */
-	u16	s_ninode;		/* number of free inodes in s_inode, <= SYSV_NICINOD */
+	__fs16	s_ninode;		/* number of free inodes in s_inode, <= SYSV_NICINOD */
 	sysv_ino_t     s_inode[SYSV_NICINOD]; /* some free inodes */
 	/* locks, not used by Linux: */
 	char	s_flock;		/* lock during free block list manipulation */
 	char	s_ilock;		/* lock during inode cache manipulation */
 	char	s_fmod;			/* super-block modified flag */
 	char	s_ronly;		/* flag whether fs is mounted read-only */
-	u32	s_time __packed2__;	/* time of last super block update */
-	s16	s_dinfo[4];		/* device information ?? */
-	u32	s_tfree __packed2__;	/* total number of free zones */
-	u16	s_tinode;		/* total number of free inodes */
+	__fs32	s_time __packed2__;	/* time of last super block update */
+	__fs16	s_dinfo[4];		/* device information ?? */
+	__fs32	s_tfree __packed2__;	/* total number of free zones */
+	__fs16	s_tinode;		/* total number of free inodes */
 	char	s_fname[6];		/* file system volume name */
 	char	s_fpack[6];		/* file system pack name */
 	s32	s_fill[14];
-	s32	s_state;		/* file system state: 0xcb096f43 means clean */
+	__fs32	s_state;		/* file system state: 0xcb096f43 means clean */
 	s32	s_magic;		/* version of file system */
-	s32	s_type;			/* type of file system: 1 for 512 byte blocks
+	__fs32	s_type;			/* type of file system: 1 for 512 byte blocks
 								2 for 1024 byte blocks */
 };
 
@@ -125,25 +130,25 @@
 #define V7_NICINOD     100     /* number of inode cache entries */
 #define V7_NICFREE     50      /* number of free block list chunk entries */
 struct v7_super_block {
-	u16    s_isize;        /* index of first data zone */
-	u32    s_fsize __packed2__; /* total number of zones of this fs */
+	__fs16 s_isize;        /* index of first data zone */
+	__fs32 s_fsize __packed2__; /* total number of zones of this fs */
 	/* the start of the free block list: */
-	u16    s_nfree;        /* number of free blocks in s_free, <= V7_NICFREE */
-	u32    s_free[V7_NICFREE]; /* first free block list chunk */
+	__fs16 s_nfree;        /* number of free blocks in s_free, <= V7_NICFREE */
+	sysv_zone_t s_free[V7_NICFREE]; /* first free block list chunk */
 	/* the cache of free inodes: */
-	u16    s_ninode;       /* number of free inodes in s_inode, <= V7_NICINOD */
+	__fs16 s_ninode;       /* number of free inodes in s_inode, <= V7_NICINOD */
 	sysv_ino_t      s_inode[V7_NICINOD]; /* some free inodes */
 	/* locks, not used by Linux or V7: */
 	char    s_flock;        /* lock during free block list manipulation */
 	char    s_ilock;        /* lock during inode cache manipulation */
 	char    s_fmod;         /* super-block modified flag */
 	char    s_ronly;        /* flag whether fs is mounted read-only */
-	u32     s_time __packed2__; /* time of last super block update */
+	__fs32  s_time __packed2__; /* time of last super block update */
 	/* the following fields are not maintained by V7: */
-	u32     s_tfree __packed2__; /* total number of free zones */
-	u16     s_tinode;       /* total number of free inodes */
-	u16     s_m;            /* interleave factor */
-	u16     s_n;            /* interleave factor */
+	__fs32  s_tfree __packed2__; /* total number of free zones */
+	__fs16  s_tinode;       /* total number of free inodes */
+	__fs16  s_m;            /* interleave factor */
+	__fs16  s_n;            /* interleave factor */
 	char    s_fname[6];     /* file system name */
 	char    s_fpack[6];     /* file system pack name */
 };
@@ -152,41 +157,41 @@
 #define COH_NICINOD	100	/* number of inode cache entries */
 #define COH_NICFREE	64	/* number of free block list chunk entries */
 struct coh_super_block {
-	u16		s_isize;	/* index of first data zone */
-	u32		s_fsize __packed2__; /* total number of zones of this fs */
+	__fs16		s_isize;	/* index of first data zone */
+	__fs32		s_fsize __packed2__; /* total number of zones of this fs */
 	/* the start of the free block list: */
-	u16 s_nfree;	/* number of free blocks in s_free, <= COH_NICFREE */
-	u32		s_free[COH_NICFREE] __packed2__; /* first free block list chunk */
+	__fs16 s_nfree;	/* number of free blocks in s_free, <= COH_NICFREE */
+	sysv_zone_t	s_free[COH_NICFREE] __packed2__; /* first free block list chunk */
 	/* the cache of free inodes: */
-	u16		s_ninode;	/* number of free inodes in s_inode, <= COH_NICINOD */
+	__fs16		s_ninode;	/* number of free inodes in s_inode, <= COH_NICINOD */
 	sysv_ino_t	s_inode[COH_NICINOD]; /* some free inodes */
 	/* locks, not used by Linux: */
 	char		s_flock;	/* lock during free block list manipulation */
 	char		s_ilock;	/* lock during inode cache manipulation */
 	char		s_fmod;		/* super-block modified flag */
 	char		s_ronly;	/* flag whether fs is mounted read-only */
-	u32		s_time __packed2__; /* time of last super block update */
-	u32		s_tfree __packed2__; /* total number of free zones */
-	u16		s_tinode;	/* total number of free inodes */
-	u16		s_interleave_m;	/* interleave factor */
-	u16		s_interleave_n;
+	__fs32		s_time __packed2__; /* time of last super block update */
+	__fs32		s_tfree __packed2__; /* total number of free zones */
+	__fs16		s_tinode;	/* total number of free inodes */
+	__fs16		s_interleave_m;	/* interleave factor */
+	__fs16		s_interleave_n;
 	char		s_fname[6];	/* file system volume name */
 	char		s_fpack[6];	/* file system pack name */
-	u32		s_unique;	/* zero, not used */
+	__fs32		s_unique;	/* zero, not used */
 };
 
 /* SystemV/Coherent inode data on disk */
 struct sysv_inode {
-	u16 i_mode;
-	u16 i_nlink;
-	u16 i_uid;
-	u16 i_gid;
-	u32 i_size;
+	__fs16 i_mode;
+	__fs16 i_nlink;
+	__fs16 i_uid;
+	__fs16 i_gid;
+	__fs32 i_size;
 	u8  i_data[3*(10+1+1+1)];
 	u8  i_gen;
-	u32 i_atime;	/* time of last access */
-	u32 i_mtime;	/* time of last modification */
-	u32 i_ctime;	/* time of creation */
+	__fs32 i_atime;	/* time of last access */
+	__fs32 i_mtime;	/* time of last modification */
+	__fs32 i_ctime;	/* time of creation */
 };
 
 /* SystemV/Coherent directory entry on disk */
diff -Nru a/include/linux/tc_act/tc_gact.h b/include/linux/tc_act/tc_gact.h
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/include/linux/tc_act/tc_gact.h	2004-10-18 14:57:23 -07:00
@@ -0,0 +1,34 @@
+#ifndef __LINUX_TC_GACT_H
+#define __LINUX_TC_GACT_H
+
+#include <linux/pkt_cls.h>
+
+#define TCA_ACT_GACT 5
+struct tc_gact
+{
+	tc_gen;
+
+};
+
+struct tc_gact_p
+{
+#define PGACT_NONE              0
+#define PGACT_NETRAND           1
+#define PGACT_DETERM            2
+#define MAX_RAND                (PGACT_DETERM + 1 )
+	__u16                 ptype;
+	__u16                 pval;
+	int                   paction;
+};
+ 
+enum
+{
+	TCA_GACT_UNSPEC,
+	TCA_GACT_TM,
+	TCA_GACT_PARMS,
+	TCA_GACT_PROB,
+	__TCA_GACT_MAX
+};
+#define TCA_GACT_MAX (__TCA_GACT_MAX - 1)
+ 
+#endif
diff -Nru a/include/linux/tcp.h b/include/linux/tcp.h
--- a/include/linux/tcp.h	2004-10-18 14:56:29 -07:00
+++ b/include/linux/tcp.h	2004-10-18 14:56:29 -07:00
@@ -201,6 +201,17 @@
 	__u32	end_seq;
 };
 
+typedef struct tcp_pcount {
+	__u32	val;
+} tcp_pcount_t;
+
+enum tcp_congestion_algo {
+	TCP_RENO=0,
+	TCP_VEGAS,
+	TCP_WESTWOOD,
+	TCP_BIC,
+};
+
 struct tcp_opt {
 	int	tcp_header_len;	/* Bytes of tcp header to send		*/
 
@@ -261,22 +272,22 @@
 	__u8	frto_counter;	/* Number of new acks after RTO */
 	__u32	frto_highmark;	/* snd_nxt when RTO occurred */
 
-	__u8	unused_pad;
+	__u8	adv_cong;	/* Using Vegas, Westwood, or BIC */
 	__u8	defer_accept;	/* User waits for some data after accept() */
 	/* one byte hole, try to pack */
 
 /* RTT measurement */
 	__u8	backoff;	/* backoff				*/
-	__u32	srtt;		/* smothed round trip time << 3		*/
+	__u32	srtt;		/* smoothed round trip time << 3	*/
 	__u32	mdev;		/* medium deviation			*/
 	__u32	mdev_max;	/* maximal mdev for the last rtt period	*/
 	__u32	rttvar;		/* smoothed mdev_max			*/
 	__u32	rtt_seq;	/* sequence number to update rttvar	*/
 	__u32	rto;		/* retransmit timeout			*/
 
-	__u32	packets_out;	/* Packets which are "in flight"	*/
-	__u32	left_out;	/* Packets which leaved network		*/
-	__u32	retrans_out;	/* Retransmitted packets out		*/
+	tcp_pcount_t packets_out; /* Packets which are "in flight"	*/
+	tcp_pcount_t left_out;	  /* Packets which leaved network	*/
+	tcp_pcount_t retrans_out; /* Retransmitted packets out		*/
 
 
 /*
@@ -337,9 +348,9 @@
 	__u8	syn_retries;	/* num of allowed syn retries */
 	__u8	ecn_flags;	/* ECN status bits.			*/
 	__u16	prior_ssthresh; /* ssthresh saved at recovery start	*/
-	__u32	lost_out;	/* Lost packets				*/
-	__u32	sacked_out;	/* SACK'd packets			*/
-	__u32	fackets_out;	/* FACK'd packets			*/
+	tcp_pcount_t lost_out;	/* Lost packets			*/
+	tcp_pcount_t sacked_out;/* SACK'd packets			*/
+	tcp_pcount_t fackets_out;/* FACK'd packets			*/
 	__u32	high_seq;	/* snd_nxt at onset of congestion	*/
 
 	__u32	retrans_stamp;	/* Timestamp of the last retransmit,
@@ -408,7 +419,6 @@
 		__u32	beg_snd_nxt;	/* right edge during last RTT */
 		__u32	beg_snd_una;	/* left edge  during last RTT */
 		__u32	beg_snd_cwnd;	/* saves the size of the cwnd */
-		__u8	do_vegas;	/* do vegas for this connection */
 		__u8	doing_vegas_now;/* if true, do vegas for this RTT */
 		__u16	cntRTT;		/* # of RTTs measured within last RTT */
 		__u32	minRTT;		/* min of RTTs measured within last RTT (in usec) */
diff -Nru a/include/linux/time.h b/include/linux/time.h
--- a/include/linux/time.h	2004-10-18 14:56:33 -07:00
+++ b/include/linux/time.h	2004-10-18 14:56:33 -07:00
@@ -194,8 +194,22 @@
 	return (j * 1000) / HZ;
 #endif
 }
+
+static inline unsigned int jiffies_to_usecs(const unsigned long j)
+{
+#if HZ <= 1000 && !(1000 % HZ)
+	return (1000000 / HZ) * j;
+#elif HZ > 1000 && !(HZ % 1000)
+	return (j*1000 + (HZ - 1000))/(HZ / 1000);
+#else
+	return (j * 1000000) / HZ;
+#endif
+}
+
 static inline unsigned long msecs_to_jiffies(const unsigned int m)
 {
+	if (m > jiffies_to_msecs(MAX_JIFFY_OFFSET))
+		return MAX_JIFFY_OFFSET;
 #if HZ <= 1000 && !(1000 % HZ)
 	return (m + (1000 / HZ) - 1) / (1000 / HZ);
 #elif HZ > 1000 && !(HZ % 1000)
@@ -348,6 +362,7 @@
 struct itimerval;
 extern int do_setitimer(int which, struct itimerval *value, struct itimerval *ovalue);
 extern int do_getitimer(int which, struct itimerval *value);
+extern void getnstimeofday (struct timespec *tv);
 
 static inline void
 set_normalized_timespec (struct timespec *ts, time_t sec, long nsec)
diff -Nru a/include/linux/times.h b/include/linux/times.h
--- a/include/linux/times.h	2004-10-18 14:55:54 -07:00
+++ b/include/linux/times.h	2004-10-18 14:55:54 -07:00
@@ -55,6 +55,26 @@
 }
 #endif
 
+static inline u64 nsec_to_clock_t(u64 x)
+{
+#if (NSEC_PER_SEC % USER_HZ) == 0
+	do_div(x, (NSEC_PER_SEC / USER_HZ));
+#elif (USER_HZ % 512) == 0
+	x *= USER_HZ/512;
+	do_div(x, (NSEC_PER_SEC / 512));
+#else
+	/*
+         * max relative error 5.7e-8 (1.8s per year) for USER_HZ <= 1024,
+         * overflow after 64.99 years.
+         * exact for HZ=60, 72, 90, 120, 144, 180, 300, 600, 900, ...
+         */
+	x *= 9;
+	do_div(x, (unsigned long)((9ull * NSEC_PER_SEC + (USER_HZ/2))
+	                          / USER_HZ));
+#endif
+	return x;
+}
+
 struct tms {
 	clock_t tms_utime;
 	clock_t tms_stime;
diff -Nru a/include/linux/timex.h b/include/linux/timex.h
--- a/include/linux/timex.h	2004-10-18 14:55:54 -07:00
+++ b/include/linux/timex.h	2004-10-18 14:55:54 -07:00
@@ -47,6 +47,8 @@
  *      kernel PLL updated to 1994-12-13 specs (rfc-1589)
  * 1997-08-30    Ulrich Windl
  *      Added new constant NTP_PHASE_LIMIT
+ * 2004-08-12    Christoph Lameter
+ *      Reworked time interpolation logic
  */
 #ifndef _LINUX_TIMEX_H
 #define _LINUX_TIMEX_H
@@ -320,99 +322,58 @@
 
 #ifdef CONFIG_TIME_INTERPOLATION
 
-struct time_interpolator {
-	/* cache-hot stuff first: */
-	unsigned long (*get_offset) (void);
-	void (*update) (long);
-	void (*reset) (void);
+#define TIME_SOURCE_CPU 0
+#define TIME_SOURCE_MMIO64 1
+#define TIME_SOURCE_MMIO32 2
+#define TIME_SOURCE_FUNCTION 3
+
+/* For proper operations time_interpolator clocks must run slightly slower
+ * than the standard clock since the interpolator may only correct by having
+ * time jump forward during a tick. A slower clock is usually a side effect
+ * of the integer divide of the nanoseconds in a second by the frequency.
+ * The accuracy of the division can be increased by specifying a shift.
+ * However, this may cause the clock not to be slow enough.
+ * The interpolator will self-tune the clock by slowing down if no
+ * resets occur or speeding up if the time jumps per analysis cycle
+ * become too high.
+ *
+ * Setting jitter compensates for a fluctuating timesource by comparing
+ * to the last value read from the timesource to insure that an earlier value
+ * is not returned by a later call. The price to pay
+ * for the compensation is that the timer routines are not as scalable anymore.
+ */
 
-	/* cache-cold stuff follows here: */
-	struct time_interpolator *next;
+#define INTERPOLATOR_ADJUST 65536
+#define INTERPOLATOR_MAX_SKIP 10*INTERPOLATOR_ADJUST
+
+struct time_interpolator {
+	unsigned short source;		/* time source flags */
+	unsigned char shift;		/* increases accuracy of multiply by shifting. */
+			/* Note that bits may be lost if shift is set too high */
+	unsigned char jitter;		/* if set compensate for fluctuations */
+	unsigned nsec_per_cyc;		/* set by register_time_interpolator() */
+	void *addr;			/* address of counter or function */
+	unsigned long offset;		/* nsec offset at last update of interpolator */
+	unsigned long last_counter;	/* counter value in units of the counter at last update */
+	unsigned long last_cycle;	/* Last timer value if TIME_SOURCE_JITTER is set */
 	unsigned long frequency;	/* frequency in counts/second */
 	long drift;			/* drift in parts-per-million (or -1) */
+	unsigned long skips;		/* skips forward */
+	unsigned long ns_skipped;	/* nanoseconds skipped */
+	struct time_interpolator *next;
 };
 
-extern volatile unsigned long last_nsec_offset;
-#ifndef __HAVE_ARCH_CMPXCHG
-extern spin_lock_t last_nsec_offset_lock;
-#endif
-extern struct time_interpolator *time_interpolator;
-
 extern void register_time_interpolator(struct time_interpolator *);
 extern void unregister_time_interpolator(struct time_interpolator *);
-
-/* Called with xtime WRITE-lock acquired.  */
-static inline void
-time_interpolator_update(long delta_nsec)
-{
-	struct time_interpolator *ti = time_interpolator;
-
-	if (last_nsec_offset > 0) {
-#ifdef __HAVE_ARCH_CMPXCHG
-		unsigned long new, old;
-
-		do {
-			old = last_nsec_offset;
-			if (old > delta_nsec)
-				new = old - delta_nsec;
-			else
-				new = 0;
-		} while (cmpxchg(&last_nsec_offset, old, new) != old);
-#else
-		/*
-		 * This really hurts, because it serializes gettimeofday(), but without an
-		 * atomic single-word compare-and-exchange, there isn't all that much else
-		 * we can do.
-		 */
-		spin_lock(&last_nsec_offset_lock);
-		{
-			last_nsec_offset -= min(last_nsec_offset, delta_nsec);
-		}
-		spin_unlock(&last_nsec_offset_lock);
-#endif
-	}
-
-	if (ti)
-		(*ti->update)(delta_nsec);
-}
-
-/* Called with xtime WRITE-lock acquired.  */
-static inline void
-time_interpolator_reset(void)
-{
-	struct time_interpolator *ti = time_interpolator;
-
-	last_nsec_offset = 0;
-	if (ti)
-		(*ti->reset)();
-}
-
-/* Called with xtime READ-lock acquired.  */
-static inline unsigned long
-time_interpolator_get_offset(void)
-{
-	struct time_interpolator *ti = time_interpolator;
-	if (ti)
-		return (*ti->get_offset)();
-	return last_nsec_offset;
-}
+extern void time_interpolator_reset(void);
+extern unsigned long time_interpolator_resolution(void);
+extern unsigned long time_interpolator_get_offset(void);
 
 #else /* !CONFIG_TIME_INTERPOLATION */
 
 static inline void
-time_interpolator_update(long delta_nsec)
-{
-}
-
-static inline void
 time_interpolator_reset(void)
 {
-}
-
-static inline unsigned long
-time_interpolator_get_offset(void)
-{
-	return 0;
 }
 
 #endif /* !CONFIG_TIME_INTERPOLATION */
diff -Nru a/include/linux/topology.h b/include/linux/topology.h
--- a/include/linux/topology.h	2004-10-18 14:56:48 -07:00
+++ b/include/linux/topology.h	2004-10-18 14:56:48 -07:00
@@ -55,7 +55,7 @@
 	for (node = 0; node < numnodes; node = __next_node_with_cpus(node))
 
 #ifndef node_distance
-#define node_distance(from,to)	(from != to)
+#define node_distance(from,to)	((from) != (to))
 #endif
 #ifndef PENALTY_FOR_NODE_WITH_CPUS
 #define PENALTY_FOR_NODE_WITH_CPUS	(1)
diff -Nru a/include/linux/tty.h b/include/linux/tty.h
--- a/include/linux/tty.h	2004-10-18 14:56:32 -07:00
+++ b/include/linux/tty.h	2004-10-18 14:56:32 -07:00
@@ -244,6 +244,7 @@
 	struct tty_driver *driver;
 	int index;
 	struct tty_ldisc ldisc;
+	struct semaphore termios_sem;
 	struct termios *termios, *termios_locked;
 	char name[64];
 	int pgrp;
@@ -306,26 +307,27 @@
  * tty->write.  Thus, you must use the inline functions set_bit() and
  * clear_bit() to make things atomic.
  */
-#define TTY_THROTTLED 0
-#define TTY_IO_ERROR 1
-#define TTY_OTHER_CLOSED 2
-#define TTY_EXCLUSIVE 3
-#define TTY_DEBUG 4
-#define TTY_DO_WRITE_WAKEUP 5
-#define TTY_PUSH 6
-#define TTY_CLOSING 7
-#define TTY_DONT_FLIP 8
-#define TTY_HW_COOK_OUT 14
-#define TTY_HW_COOK_IN 15
-#define TTY_PTY_LOCK 16
-#define TTY_NO_WRITE_SPLIT 17
+#define TTY_THROTTLED 		0	/* Call unthrottle() at threshold min */
+#define TTY_IO_ERROR 		1	/* Canse an I/O error (may be no ldisc too) */
+#define TTY_OTHER_CLOSED 	2	/* Other side (if any) has closed */
+#define TTY_EXCLUSIVE 		3	/* Exclusive open mode */
+#define TTY_DEBUG 		4	/* Debugging */
+#define TTY_DO_WRITE_WAKEUP 	5	/* Call write_wakeup after queuing new */
+#define TTY_PUSH 		6	/* n_tty private */
+#define TTY_CLOSING 		7	/* ->close() in progress */
+#define TTY_DONT_FLIP 		8	/* Defer buffer flip */
+#define TTY_LDISC 		9	/* Line discipline attached */
+#define TTY_HW_COOK_OUT 	14	/* Hardware can do output cooking */
+#define TTY_HW_COOK_IN 		15	/* Hardware can do input cooking */
+#define TTY_PTY_LOCK 		16	/* pty private */
+#define TTY_NO_WRITE_SPLIT 	17	/* Preserve write boundaries to driver */
+#define TTY_HUPPED 		18	/* Post driver->hangup() */
 
 #define TTY_WRITE_FLUSH(tty) tty_write_flush((tty))
 
 extern void tty_write_flush(struct tty_struct *);
 
 extern struct termios tty_std_termios;
-extern struct tty_ldisc ldiscs[];
 extern int fg_console, last_console, want_console;
 
 extern int kmsg_redirect;
@@ -361,6 +363,16 @@
 extern void tty_flip_buffer_push(struct tty_struct *tty);
 extern int tty_get_baud_rate(struct tty_struct *tty);
 extern int tty_termios_baud_rate(struct termios *termios);
+
+extern struct tty_ldisc *tty_ldisc_ref(struct tty_struct *);
+extern void tty_ldisc_deref(struct tty_ldisc *);
+extern struct tty_ldisc *tty_ldisc_ref_wait(struct tty_struct *);
+
+extern struct tty_ldisc *tty_ldisc_get(int);
+extern void tty_ldisc_put(int);
+
+extern void tty_wakeup(struct tty_struct *tty);
+extern void tty_ldisc_flush(struct tty_struct *tty);
 
 struct semaphore;
 extern struct semaphore tty_sem;
diff -Nru a/include/linux/tty_ldisc.h b/include/linux/tty_ldisc.h
--- a/include/linux/tty_ldisc.h	2004-10-18 14:57:04 -07:00
+++ b/include/linux/tty_ldisc.h	2004-10-18 14:57:04 -07:00
@@ -95,6 +95,13 @@
  * 	that line discpline should try to send more characters to the
  * 	low-level driver for transmission.  If the line discpline does
  * 	not have any more data to send, it can just return.
+ *
+ * int (*hangup)(struct tty_struct *)
+ *
+ *	Called on a hangup. Tells the discipline that it should
+ *	cease I/O to the tty driver. Can sleep. The driver should
+ *	seek to perform this action quickly but should wait until
+ *	any pending driver I/O is completed.
  */
 
 #include <linux/fs.h>
@@ -122,6 +129,7 @@
 	void	(*set_termios)(struct tty_struct *tty, struct termios * old);
 	unsigned int (*poll)(struct tty_struct *, struct file *,
 			     struct poll_table_struct *);
+	int	(*hangup)(struct tty_struct *tty);
 	
 	/*
 	 * The following routines are called from below.
@@ -132,6 +140,8 @@
 	void	(*write_wakeup)(struct tty_struct *);
 
 	struct  module *owner;
+	
+	int refcount;
 };
 
 #define TTY_LDISC_MAGIC	0x5403
diff -Nru a/include/linux/types.h b/include/linux/types.h
--- a/include/linux/types.h	2004-10-18 14:57:03 -07:00
+++ b/include/linux/types.h	2004-10-18 14:57:03 -07:00
@@ -140,6 +140,19 @@
 #define pgoff_t unsigned long
 #endif
 
+#ifdef __CHECKER__
+#define __bitwise __attribute__((bitwise))
+#else
+#define __bitwise
+#endif
+
+typedef __u16 __bitwise __le16;
+typedef __u16 __bitwise __be16;
+typedef __u32 __bitwise __le32;
+typedef __u32 __bitwise __be32;
+typedef __u64 __bitwise __le64;
+typedef __u64 __bitwise __be64;
+
 #endif /* __KERNEL_STRICT_NAMES */
 
 /*
diff -Nru a/include/linux/udf_fs_i.h b/include/linux/udf_fs_i.h
--- a/include/linux/udf_fs_i.h	2004-10-18 14:55:54 -07:00
+++ b/include/linux/udf_fs_i.h	2004-10-18 14:55:54 -07:00
@@ -45,7 +45,7 @@
 {
 	struct timespec		i_crtime;
 	/* Physical address of inode */
-	lb_addr			i_location;
+	kernel_lb_addr		i_location;
 	__u64			i_unique;
 	__u32			i_lenEAttr;
 	__u32			i_lenAlloc;
diff -Nru a/include/linux/ufs_fs.h b/include/linux/ufs_fs.h
--- a/include/linux/ufs_fs.h	2004-10-18 14:56:49 -07:00
+++ b/include/linux/ufs_fs.h	2004-10-18 14:56:49 -07:00
@@ -36,6 +36,16 @@
 #include <linux/stat.h>
 #include <linux/fs.h>
 
+#ifndef __KERNEL__
+typedef __u64 __fs64;
+typedef __u32 __fs32;
+typedef __u16 __fs16;
+#else
+typedef __u64 __bitwise __fs64;
+typedef __u32 __bitwise __fs32;
+typedef __u16 __bitwise __fs16;
+#endif
+
 #include <linux/ufs_fs_i.h>
 #include <linux/ufs_fs_sb.h>
 
@@ -297,15 +307,15 @@
 #define UFS_DIR_REC_LEN(name_len)	(((name_len) + 1 + 8 + UFS_DIR_ROUND) & ~UFS_DIR_ROUND)
 
 struct ufs_timeval {
-	__s32	tv_sec;
-	__s32	tv_usec;
+	__fs32	tv_sec;
+	__fs32	tv_usec;
 };
 
 struct ufs_dir_entry {
-	__u32  d_ino;			/* inode number of this entry */
-	__u16  d_reclen;		/* length of this entry */
+	__fs32  d_ino;			/* inode number of this entry */
+	__fs16  d_reclen;		/* length of this entry */
 	union {
-		__u16	d_namlen;		/* actual length of d_name */
+		__fs16	d_namlen;		/* actual length of d_name */
 		struct {
 			__u8	d_type;		/* file type */
 			__u8	d_namlen;	/* length of string in d_name */
@@ -315,92 +325,92 @@
 };
 
 struct ufs_csum {
-	__u32	cs_ndir;	/* number of directories */
-	__u32	cs_nbfree;	/* number of free blocks */
-	__u32	cs_nifree;	/* number of free inodes */
-	__u32	cs_nffree;	/* number of free frags */
+	__fs32	cs_ndir;	/* number of directories */
+	__fs32	cs_nbfree;	/* number of free blocks */
+	__fs32	cs_nifree;	/* number of free inodes */
+	__fs32	cs_nffree;	/* number of free frags */
 };
 struct ufs2_csum_total {
-	__u64	cs_ndir;	/* number of directories */
-	__u64	cs_nbfree;	/* number of free blocks */
-	__u64	cs_nifree;	/* number of free inodes */
-	__u64	cs_nffree;	/* number of free frags */
-	__u64   cs_numclusters;	/* number of free clusters */
-	__u64   cs_spare[3];	/* future expansion */
+	__fs64	cs_ndir;	/* number of directories */
+	__fs64	cs_nbfree;	/* number of free blocks */
+	__fs64	cs_nifree;	/* number of free inodes */
+	__fs64	cs_nffree;	/* number of free frags */
+	__fs64   cs_numclusters;	/* number of free clusters */
+	__fs64   cs_spare[3];	/* future expansion */
 };
 
 /*
  * This is the actual superblock, as it is laid out on the disk.
  */
 struct ufs_super_block {
-	__u32	fs_link;	/* UNUSED */
-	__u32	fs_rlink;	/* UNUSED */
-	__u32	fs_sblkno;	/* addr of super-block in filesys */
-	__u32	fs_cblkno;	/* offset of cyl-block in filesys */
-	__u32	fs_iblkno;	/* offset of inode-blocks in filesys */
-	__u32	fs_dblkno;	/* offset of first data after cg */
-	__u32	fs_cgoffset;	/* cylinder group offset in cylinder */
-	__u32	fs_cgmask;	/* used to calc mod fs_ntrak */
-	__u32	fs_time;	/* last time written -- time_t */
-	__u32	fs_size;	/* number of blocks in fs */
-	__u32	fs_dsize;	/* number of data blocks in fs */
-	__u32	fs_ncg;		/* number of cylinder groups */
-	__u32	fs_bsize;	/* size of basic blocks in fs */
-	__u32	fs_fsize;	/* size of frag blocks in fs */
-	__u32	fs_frag;	/* number of frags in a block in fs */
+	__fs32	fs_link;	/* UNUSED */
+	__fs32	fs_rlink;	/* UNUSED */
+	__fs32	fs_sblkno;	/* addr of super-block in filesys */
+	__fs32	fs_cblkno;	/* offset of cyl-block in filesys */
+	__fs32	fs_iblkno;	/* offset of inode-blocks in filesys */
+	__fs32	fs_dblkno;	/* offset of first data after cg */
+	__fs32	fs_cgoffset;	/* cylinder group offset in cylinder */
+	__fs32	fs_cgmask;	/* used to calc mod fs_ntrak */
+	__fs32	fs_time;	/* last time written -- time_t */
+	__fs32	fs_size;	/* number of blocks in fs */
+	__fs32	fs_dsize;	/* number of data blocks in fs */
+	__fs32	fs_ncg;		/* number of cylinder groups */
+	__fs32	fs_bsize;	/* size of basic blocks in fs */
+	__fs32	fs_fsize;	/* size of frag blocks in fs */
+	__fs32	fs_frag;	/* number of frags in a block in fs */
 /* these are configuration parameters */
-	__u32	fs_minfree;	/* minimum percentage of free blocks */
-	__u32	fs_rotdelay;	/* num of ms for optimal next block */
-	__u32	fs_rps;		/* disk revolutions per second */
+	__fs32	fs_minfree;	/* minimum percentage of free blocks */
+	__fs32	fs_rotdelay;	/* num of ms for optimal next block */
+	__fs32	fs_rps;		/* disk revolutions per second */
 /* these fields can be computed from the others */
-	__u32	fs_bmask;	/* ``blkoff'' calc of blk offsets */
-	__u32	fs_fmask;	/* ``fragoff'' calc of frag offsets */
-	__u32	fs_bshift;	/* ``lblkno'' calc of logical blkno */
-	__u32	fs_fshift;	/* ``numfrags'' calc number of frags */
+	__fs32	fs_bmask;	/* ``blkoff'' calc of blk offsets */
+	__fs32	fs_fmask;	/* ``fragoff'' calc of frag offsets */
+	__fs32	fs_bshift;	/* ``lblkno'' calc of logical blkno */
+	__fs32	fs_fshift;	/* ``numfrags'' calc number of frags */
 /* these are configuration parameters */
-	__u32	fs_maxcontig;	/* max number of contiguous blks */
-	__u32	fs_maxbpg;	/* max number of blks per cyl group */
+	__fs32	fs_maxcontig;	/* max number of contiguous blks */
+	__fs32	fs_maxbpg;	/* max number of blks per cyl group */
 /* these fields can be computed from the others */
-	__u32	fs_fragshift;	/* block to frag shift */
-	__u32	fs_fsbtodb;	/* fsbtodb and dbtofsb shift constant */
-	__u32	fs_sbsize;	/* actual size of super block */
-	__u32	fs_csmask;	/* csum block offset */
-	__u32	fs_csshift;	/* csum block number */
-	__u32	fs_nindir;	/* value of NINDIR */
-	__u32	fs_inopb;	/* value of INOPB */
-	__u32	fs_nspf;	/* value of NSPF */
+	__fs32	fs_fragshift;	/* block to frag shift */
+	__fs32	fs_fsbtodb;	/* fsbtodb and dbtofsb shift constant */
+	__fs32	fs_sbsize;	/* actual size of super block */
+	__fs32	fs_csmask;	/* csum block offset */
+	__fs32	fs_csshift;	/* csum block number */
+	__fs32	fs_nindir;	/* value of NINDIR */
+	__fs32	fs_inopb;	/* value of INOPB */
+	__fs32	fs_nspf;	/* value of NSPF */
 /* yet another configuration parameter */
-	__u32	fs_optim;	/* optimization preference, see below */
+	__fs32	fs_optim;	/* optimization preference, see below */
 /* these fields are derived from the hardware */
 	union {
 		struct {
-			__u32	fs_npsect;	/* # sectors/track including spares */
+			__fs32	fs_npsect;	/* # sectors/track including spares */
 		} fs_sun;
 		struct {
-			__s32	fs_state;	/* file system state time stamp */
+			__fs32	fs_state;	/* file system state time stamp */
 		} fs_sunx86;
 	} fs_u1;
-	__u32	fs_interleave;	/* hardware sector interleave */
-	__u32	fs_trackskew;	/* sector 0 skew, per track */
+	__fs32	fs_interleave;	/* hardware sector interleave */
+	__fs32	fs_trackskew;	/* sector 0 skew, per track */
 /* a unique id for this filesystem (currently unused and unmaintained) */
 /* In 4.3 Tahoe this space is used by fs_headswitch and fs_trkseek */
 /* Neither of those fields is used in the Tahoe code right now but */
 /* there could be problems if they are.                            */
-	__u32	fs_id[2];	/* file system id */
+	__fs32	fs_id[2];	/* file system id */
 /* sizes determined by number of cylinder groups and their sizes */
-	__u32	fs_csaddr;	/* blk addr of cyl grp summary area */
-	__u32	fs_cssize;	/* size of cyl grp summary area */
-	__u32	fs_cgsize;	/* cylinder group size */
+	__fs32	fs_csaddr;	/* blk addr of cyl grp summary area */
+	__fs32	fs_cssize;	/* size of cyl grp summary area */
+	__fs32	fs_cgsize;	/* cylinder group size */
 /* these fields are derived from the hardware */
-	__u32	fs_ntrak;	/* tracks per cylinder */
-	__u32	fs_nsect;	/* sectors per track */
-	__u32	fs_spc;		/* sectors per cylinder */
+	__fs32	fs_ntrak;	/* tracks per cylinder */
+	__fs32	fs_nsect;	/* sectors per track */
+	__fs32	fs_spc;		/* sectors per cylinder */
 /* this comes from the disk driver partitioning */
-	__u32	fs_ncyl;	/* cylinders in file system */
+	__fs32	fs_ncyl;	/* cylinders in file system */
 /* these fields can be computed from the others */
-	__u32	fs_cpg;		/* cylinders per group */
-	__u32	fs_ipg;		/* inodes per cylinder group */
-	__u32	fs_fpg;		/* blocks per group * fs_frag */
+	__fs32	fs_cpg;		/* cylinders per group */
+	__fs32	fs_ipg;		/* inodes per cylinder group */
+	__fs32	fs_fpg;		/* blocks per group * fs_frag */
 /* this data must be re-computed after crashes */
 	struct ufs_csum fs_cstotal;	/* cylinder summary information */
 /* these fields are cleared at mount time */
@@ -411,69 +421,69 @@
 	union {
 		struct {
 			__s8	fs_fsmnt[UFS_MAXMNTLEN];/* name mounted on */
-			__u32	fs_cgrotor;	/* last cg searched */
-			__u32	fs_csp[UFS_MAXCSBUFS];/*list of fs_cs info buffers */
-			__u32	fs_maxcluster;
-			__u32	fs_cpc;		/* cyl per cycle in postbl */
-			__u16	fs_opostbl[16][8]; /* old rotation block list head */
+			__fs32	fs_cgrotor;	/* last cg searched */
+			__fs32	fs_csp[UFS_MAXCSBUFS];/*list of fs_cs info buffers */
+			__fs32	fs_maxcluster;
+			__fs32	fs_cpc;		/* cyl per cycle in postbl */
+			__fs16	fs_opostbl[16][8]; /* old rotation block list head */
 		} fs_u1;
 		struct {
 			__s8  fs_fsmnt[UFS2_MAXMNTLEN];	/* name mounted on */
 			__u8   fs_volname[UFS2_MAXVOLLEN]; /* volume name */
-			__u64  fs_swuid;		/* system-wide uid */
-			__s32  fs_pad;	/* due to alignment of fs_swuid */
-			__u32   fs_cgrotor;     /* last cg searched */
-			__u32   fs_ocsp[UFS2_NOCSPTRS]; /*list of fs_cs info buffers */
-			__u32   fs_contigdirs;/*# of contiguously allocated dirs */
-			__u32   fs_csp;	/* cg summary info buffer for fs_cs */
-			__u32   fs_maxcluster;
-			__u32   fs_active;/* used by snapshots to track fs */
-			__s32   fs_old_cpc;	/* cyl per cycle in postbl */
-			__s32   fs_maxbsize;/*maximum blocking factor permitted */
-			__s64   fs_sparecon64[17];/*old rotation block list head */
-			__s64   fs_sblockloc; /* byte offset of standard superblock */
+			__fs64  fs_swuid;		/* system-wide uid */
+			__fs32  fs_pad;	/* due to alignment of fs_swuid */
+			__fs32   fs_cgrotor;     /* last cg searched */
+			__fs32   fs_ocsp[UFS2_NOCSPTRS]; /*list of fs_cs info buffers */
+			__fs32   fs_contigdirs;/*# of contiguously allocated dirs */
+			__fs32   fs_csp;	/* cg summary info buffer for fs_cs */
+			__fs32   fs_maxcluster;
+			__fs32   fs_active;/* used by snapshots to track fs */
+			__fs32   fs_old_cpc;	/* cyl per cycle in postbl */
+			__fs32   fs_maxbsize;/*maximum blocking factor permitted */
+			__fs64   fs_sparecon64[17];/*old rotation block list head */
+			__fs64   fs_sblockloc; /* byte offset of standard superblock */
 			struct  ufs2_csum_total fs_cstotal;/*cylinder summary information*/
 			struct  ufs_timeval    fs_time;		/* last time written */
-			__s64    fs_size;		/* number of blocks in fs */
-			__s64    fs_dsize;	/* number of data blocks in fs */
-			__u64    fs_csaddr;	/* blk addr of cyl grp summary area */
-			__s64    fs_pendingblocks;/* blocks in process of being freed */
-			__s32    fs_pendinginodes;/*inodes in process of being freed */
+			__fs64    fs_size;		/* number of blocks in fs */
+			__fs64    fs_dsize;	/* number of data blocks in fs */
+			__fs64   fs_csaddr;	/* blk addr of cyl grp summary area */
+			__fs64    fs_pendingblocks;/* blocks in process of being freed */
+			__fs32    fs_pendinginodes;/*inodes in process of being freed */
 		} fs_u2;
 	}  fs_u11;
 	union {
 		struct {
-			__s32	fs_sparecon[53];/* reserved for future constants */
-			__s32	fs_reclaim;
-			__s32	fs_sparecon2[1];
-			__s32	fs_state;	/* file system state time stamp */
-			__u32	fs_qbmask[2];	/* ~usb_bmask */
-			__u32	fs_qfmask[2];	/* ~usb_fmask */
+			__fs32	fs_sparecon[53];/* reserved for future constants */
+			__fs32	fs_reclaim;
+			__fs32	fs_sparecon2[1];
+			__fs32	fs_state;	/* file system state time stamp */
+			__fs32	fs_qbmask[2];	/* ~usb_bmask */
+			__fs32	fs_qfmask[2];	/* ~usb_fmask */
 		} fs_sun;
 		struct {
-			__s32	fs_sparecon[53];/* reserved for future constants */
-			__s32	fs_reclaim;
-			__s32	fs_sparecon2[1];
-			__u32	fs_npsect;	/* # sectors/track including spares */
-			__u32	fs_qbmask[2];	/* ~usb_bmask */
-			__u32	fs_qfmask[2];	/* ~usb_fmask */
+			__fs32	fs_sparecon[53];/* reserved for future constants */
+			__fs32	fs_reclaim;
+			__fs32	fs_sparecon2[1];
+			__fs32	fs_npsect;	/* # sectors/track including spares */
+			__fs32	fs_qbmask[2];	/* ~usb_bmask */
+			__fs32	fs_qfmask[2];	/* ~usb_fmask */
 		} fs_sunx86;
 		struct {
-			__s32	fs_sparecon[50];/* reserved for future constants */
-			__s32	fs_contigsumsize;/* size of cluster summary array */
-			__s32	fs_maxsymlinklen;/* max length of an internal symlink */
-			__s32	fs_inodefmt;	/* format of on-disk inodes */
-			__u32	fs_maxfilesize[2];	/* max representable file size */
-			__u32	fs_qbmask[2];	/* ~usb_bmask */
-			__u32	fs_qfmask[2];	/* ~usb_fmask */
-			__s32	fs_state;	/* file system state time stamp */
+			__fs32	fs_sparecon[50];/* reserved for future constants */
+			__fs32	fs_contigsumsize;/* size of cluster summary array */
+			__fs32	fs_maxsymlinklen;/* max length of an internal symlink */
+			__fs32	fs_inodefmt;	/* format of on-disk inodes */
+			__fs32	fs_maxfilesize[2];	/* max representable file size */
+			__fs32	fs_qbmask[2];	/* ~usb_bmask */
+			__fs32	fs_qfmask[2];	/* ~usb_fmask */
+			__fs32	fs_state;	/* file system state time stamp */
 		} fs_44;
 	} fs_u2;
-	__s32	fs_postblformat;	/* format of positional layout tables */
-	__s32	fs_nrpos;		/* number of rotational positions */
-	__s32	fs_postbloff;		/* (__s16) rotation block list head */
-	__s32	fs_rotbloff;		/* (__u8) blocks for each rotation */
-	__s32	fs_magic;		/* magic number */
+	__fs32	fs_postblformat;	/* format of positional layout tables */
+	__fs32	fs_nrpos;		/* number of rotational positions */
+	__fs32	fs_postbloff;		/* (__s16) rotation block list head */
+	__fs32	fs_rotbloff;		/* (__u8) blocks for each rotation */
+	__fs32	fs_magic;		/* magic number */
 	__u8	fs_space[1];		/* list of blocks for each rotation */
 };
 
@@ -509,41 +519,41 @@
  * size of this structure is 172 B
  */
 struct	ufs_cylinder_group {
-	__u32	cg_link;		/* linked list of cyl groups */
-	__u32	cg_magic;		/* magic number */
-	__u32	cg_time;		/* time last written */
-	__u32	cg_cgx;			/* we are the cgx'th cylinder group */
-	__u16	cg_ncyl;		/* number of cyl's this cg */
-	__u16	cg_niblk;		/* number of inode blocks this cg */
-	__u32	cg_ndblk;		/* number of data blocks this cg */
+	__fs32	cg_link;		/* linked list of cyl groups */
+	__fs32	cg_magic;		/* magic number */
+	__fs32	cg_time;		/* time last written */
+	__fs32	cg_cgx;			/* we are the cgx'th cylinder group */
+	__fs16	cg_ncyl;		/* number of cyl's this cg */
+	__fs16	cg_niblk;		/* number of inode blocks this cg */
+	__fs32	cg_ndblk;		/* number of data blocks this cg */
 	struct	ufs_csum cg_cs;		/* cylinder summary information */
-	__u32	cg_rotor;		/* position of last used block */
-	__u32	cg_frotor;		/* position of last used frag */
-	__u32	cg_irotor;		/* position of last used inode */
-	__u32	cg_frsum[UFS_MAXFRAG];	/* counts of available frags */
-	__u32	cg_btotoff;		/* (__u32) block totals per cylinder */
-	__u32	cg_boff;		/* (short) free block positions */
-	__u32	cg_iusedoff;		/* (char) used inode map */
-	__u32	cg_freeoff;		/* (u_char) free block map */
-	__u32	cg_nextfreeoff;		/* (u_char) next available space */
+	__fs32	cg_rotor;		/* position of last used block */
+	__fs32	cg_frotor;		/* position of last used frag */
+	__fs32	cg_irotor;		/* position of last used inode */
+	__fs32	cg_frsum[UFS_MAXFRAG];	/* counts of available frags */
+	__fs32	cg_btotoff;		/* (__u32) block totals per cylinder */
+	__fs32	cg_boff;		/* (short) free block positions */
+	__fs32	cg_iusedoff;		/* (char) used inode map */
+	__fs32	cg_freeoff;		/* (u_char) free block map */
+	__fs32	cg_nextfreeoff;		/* (u_char) next available space */
 	union {
 		struct {
-			__u32	cg_clustersumoff;	/* (u_int32) counts of avail clusters */
-			__u32	cg_clusteroff;		/* (u_int8) free cluster map */
-			__u32	cg_nclusterblks;	/* number of clusters this cg */
-			__u32	cg_sparecon[13];	/* reserved for future use */
+			__fs32	cg_clustersumoff;	/* (u_int32) counts of avail clusters */
+			__fs32	cg_clusteroff;		/* (u_int8) free cluster map */
+			__fs32	cg_nclusterblks;	/* number of clusters this cg */
+			__fs32	cg_sparecon[13];	/* reserved for future use */
 		} cg_44;
 		struct {
-			__u32	cg_clustersumoff;/* (u_int32) counts of avail clusters */
-			__u32	cg_clusteroff;	/* (u_int8) free cluster map */
-			__u32	cg_nclusterblks;/* number of clusters this cg */
-			__u32   cg_niblk; /* number of inode blocks this cg */
-			__u32   cg_initediblk;	/* last initialized inode */
-			__u32   cg_sparecon32[3];/* reserved for future use */
-			__u64   cg_time;	/* time last written */
-			__u64	cg_sparecon[3];	/* reserved for future use */
+			__fs32	cg_clustersumoff;/* (u_int32) counts of avail clusters */
+			__fs32	cg_clusteroff;	/* (u_int8) free cluster map */
+			__fs32	cg_nclusterblks;/* number of clusters this cg */
+			__fs32   cg_niblk; /* number of inode blocks this cg */
+			__fs32   cg_initediblk;	/* last initialized inode */
+			__fs32   cg_sparecon32[3];/* reserved for future use */
+			__fs64   cg_time;	/* time last written */
+			__fs64	cg_sparecon[3];	/* reserved for future use */
 		} cg_u2;
-		__u32	cg_sparecon[16];	/* reserved for future use */
+		__fs32	cg_sparecon[16];	/* reserved for future use */
 	} cg_u;
 	__u8	cg_space[1];		/* space for cylinder group maps */
 /* actually longer */
@@ -553,82 +563,82 @@
  * structure of an on-disk inode
  */
 struct ufs_inode {
-	__u16	ui_mode;		/*  0x0 */
-	__u16	ui_nlink;		/*  0x2 */
+	__fs16	ui_mode;		/*  0x0 */
+	__fs16	ui_nlink;		/*  0x2 */
 	union {
 		struct {
-			__u16	ui_suid;	/*  0x4 */
-			__u16	ui_sgid;	/*  0x6 */
+			__fs16	ui_suid;	/*  0x4 */
+			__fs16	ui_sgid;	/*  0x6 */
 		} oldids;
-		__u32	ui_inumber;		/*  0x4 lsf: inode number */
-		__u32	ui_author;		/*  0x4 GNU HURD: author */
+		__fs32	ui_inumber;		/*  0x4 lsf: inode number */
+		__fs32	ui_author;		/*  0x4 GNU HURD: author */
 	} ui_u1;
-	__u64	ui_size;		/*  0x8 */
+	__fs64	ui_size;		/*  0x8 */
 	struct ufs_timeval ui_atime;	/* 0x10 access */
 	struct ufs_timeval ui_mtime;	/* 0x18 modification */
 	struct ufs_timeval ui_ctime;	/* 0x20 creation */
 	union {
 		struct {
-			__u32	ui_db[UFS_NDADDR];/* 0x28 data blocks */
-			__u32	ui_ib[UFS_NINDIR];/* 0x58 indirect blocks */
+			__fs32	ui_db[UFS_NDADDR];/* 0x28 data blocks */
+			__fs32	ui_ib[UFS_NINDIR];/* 0x58 indirect blocks */
 		} ui_addr;
 		__u8	ui_symlink[4*(UFS_NDADDR+UFS_NINDIR)];/* 0x28 fast symlink */
 	} ui_u2;
-	__u32	ui_flags;		/* 0x64 immutable, append-only... */
-	__u32	ui_blocks;		/* 0x68 blocks in use */
-	__u32	ui_gen;			/* 0x6c like ext2 i_version, for NFS support */
+	__fs32	ui_flags;		/* 0x64 immutable, append-only... */
+	__fs32	ui_blocks;		/* 0x68 blocks in use */
+	__fs32	ui_gen;			/* 0x6c like ext2 i_version, for NFS support */
 	union {
 		struct {
-			__u32	ui_shadow;	/* 0x70 shadow inode with security data */
-			__u32	ui_uid;		/* 0x74 long EFT version of uid */
-			__u32	ui_gid;		/* 0x78 long EFT version of gid */
-			__u32	ui_oeftflag;	/* 0x7c reserved */
+			__fs32	ui_shadow;	/* 0x70 shadow inode with security data */
+			__fs32	ui_uid;		/* 0x74 long EFT version of uid */
+			__fs32	ui_gid;		/* 0x78 long EFT version of gid */
+			__fs32	ui_oeftflag;	/* 0x7c reserved */
 		} ui_sun;
 		struct {
-			__u32	ui_uid;		/* 0x70 File owner */
-			__u32	ui_gid;		/* 0x74 File group */
-			__s32	ui_spare[2];	/* 0x78 reserved */
+			__fs32	ui_uid;		/* 0x70 File owner */
+			__fs32	ui_gid;		/* 0x74 File group */
+			__fs32	ui_spare[2];	/* 0x78 reserved */
 		} ui_44;
 		struct {
-			__u32	ui_uid;		/* 0x70 */
-			__u32	ui_gid;		/* 0x74 */
-			__u16	ui_modeh;	/* 0x78 mode high bits */
-			__u16	ui_spare;	/* 0x7A unused */
-			__u32	ui_trans;	/* 0x7c filesystem translator */
+			__fs32	ui_uid;		/* 0x70 */
+			__fs32	ui_gid;		/* 0x74 */
+			__fs16	ui_modeh;	/* 0x78 mode high bits */
+			__fs16	ui_spare;	/* 0x7A unused */
+			__fs32	ui_trans;	/* 0x7c filesystem translator */
 		} ui_hurd;
 	} ui_u3;
 };
 
 #define UFS_NXADDR  2            /* External addresses in inode. */
 struct ufs2_inode {
-	__u16     ui_mode;        /*   0: IFMT, permissions; see below. */
-	__s16     ui_nlink;       /*   2: File link count. */
-	__u32     ui_uid;         /*   4: File owner. */
-	__u32     ui_gid;         /*   8: File group. */
-	__u32     ui_blksize;     /*  12: Inode blocksize. */
-	__u64     ui_size;        /*  16: File byte count. */
-	__u64     ui_blocks;      /*  24: Bytes actually held. */
+	__fs16     ui_mode;        /*   0: IFMT, permissions; see below. */
+	__fs16     ui_nlink;       /*   2: File link count. */
+	__fs32     ui_uid;         /*   4: File owner. */
+	__fs32     ui_gid;         /*   8: File group. */
+	__fs32     ui_blksize;     /*  12: Inode blocksize. */
+	__fs64     ui_size;        /*  16: File byte count. */
+	__fs64     ui_blocks;      /*  24: Bytes actually held. */
 	struct ufs_timeval   ui_atime;       /*  32: Last access time. */
 	struct ufs_timeval   ui_mtime;       /*  40: Last modified time. */
 	struct ufs_timeval   ui_ctime;       /*  48: Last inode change time. */
 	struct ufs_timeval   ui_birthtime;   /*  56: Inode creation time. */
-	__s32     ui_mtimensec;   /*  64: Last modified time. */
-	__s32     ui_atimensec;   /*  68: Last access time. */
-	__s32     ui_ctimensec;   /*  72: Last inode change time. */
-	__s32     ui_birthnsec;   /*  76: Inode creation time. */
-	__s32     ui_gen;         /*  80: Generation number. */
-	__u32     ui_kernflags;   /*  84: Kernel flags. */
-	__u32     ui_flags;       /*  88: Status flags (chflags). */
-	__s32     ui_extsize;     /*  92: External attributes block. */
-	__s64     ui_extb[UFS_NXADDR];/*  96: External attributes block. */
+	__fs32     ui_mtimensec;   /*  64: Last modified time. */
+	__fs32     ui_atimensec;   /*  68: Last access time. */
+	__fs32     ui_ctimensec;   /*  72: Last inode change time. */
+	__fs32     ui_birthnsec;   /*  76: Inode creation time. */
+	__fs32     ui_gen;         /*  80: Generation number. */
+	__fs32     ui_kernflags;   /*  84: Kernel flags. */
+	__fs32     ui_flags;       /*  88: Status flags (chflags). */
+	__fs32     ui_extsize;     /*  92: External attributes block. */
+	__fs64     ui_extb[UFS_NXADDR];/*  96: External attributes block. */
 	union {
 		struct {
-			__s64     ui_db[UFS_NDADDR]; /* 112: Direct disk blocks. */
-			__s64     ui_ib[UFS_NINDIR];/* 208: Indirect disk blocks.*/
+			__fs64     ui_db[UFS_NDADDR]; /* 112: Direct disk blocks. */
+			__fs64     ui_ib[UFS_NINDIR];/* 208: Indirect disk blocks.*/
 		} ui_addr;
 	__u8	ui_symlink[2*4*(UFS_NDADDR+UFS_NINDIR)];/* 0x28 fast symlink */
 	} ui_u2;
-	__s64     ui_spare[3];    /* 232: Reserved; currently unused */
+	__fs64     ui_spare[3];    /* 232: Reserved; currently unused */
 };
 
 
@@ -752,60 +762,60 @@
  *	ufs_super_block_third	356
  */
 struct ufs_super_block_first {
-	__u32	fs_link;
-	__u32	fs_rlink;
-	__u32	fs_sblkno;
-	__u32	fs_cblkno;
-	__u32	fs_iblkno;
-	__u32	fs_dblkno;
-	__u32	fs_cgoffset;
-	__u32	fs_cgmask;
-	__u32	fs_time;
-	__u32	fs_size;
-	__u32	fs_dsize;
-	__u32	fs_ncg;
-	__u32	fs_bsize;
-	__u32	fs_fsize;
-	__u32	fs_frag;
-	__u32	fs_minfree;
-	__u32	fs_rotdelay;
-	__u32	fs_rps;
-	__u32	fs_bmask;
-	__u32	fs_fmask;
-	__u32	fs_bshift;
-	__u32	fs_fshift;
-	__u32	fs_maxcontig;
-	__u32	fs_maxbpg;
-	__u32	fs_fragshift;
-	__u32	fs_fsbtodb;
-	__u32	fs_sbsize;
-	__u32	fs_csmask;
-	__u32	fs_csshift;
-	__u32	fs_nindir;
-	__u32	fs_inopb;
-	__u32	fs_nspf;
-	__u32	fs_optim;
+	__fs32	fs_link;
+	__fs32	fs_rlink;
+	__fs32	fs_sblkno;
+	__fs32	fs_cblkno;
+	__fs32	fs_iblkno;
+	__fs32	fs_dblkno;
+	__fs32	fs_cgoffset;
+	__fs32	fs_cgmask;
+	__fs32	fs_time;
+	__fs32	fs_size;
+	__fs32	fs_dsize;
+	__fs32	fs_ncg;
+	__fs32	fs_bsize;
+	__fs32	fs_fsize;
+	__fs32	fs_frag;
+	__fs32	fs_minfree;
+	__fs32	fs_rotdelay;
+	__fs32	fs_rps;
+	__fs32	fs_bmask;
+	__fs32	fs_fmask;
+	__fs32	fs_bshift;
+	__fs32	fs_fshift;
+	__fs32	fs_maxcontig;
+	__fs32	fs_maxbpg;
+	__fs32	fs_fragshift;
+	__fs32	fs_fsbtodb;
+	__fs32	fs_sbsize;
+	__fs32	fs_csmask;
+	__fs32	fs_csshift;
+	__fs32	fs_nindir;
+	__fs32	fs_inopb;
+	__fs32	fs_nspf;
+	__fs32	fs_optim;
 	union {
 		struct {
-			__u32	fs_npsect;
+			__fs32	fs_npsect;
 		} fs_sun;
 		struct {
-			__s32	fs_state;
+			__fs32	fs_state;
 		} fs_sunx86;
 	} fs_u1;
-	__u32	fs_interleave;
-	__u32	fs_trackskew;
-	__u32	fs_id[2];
-	__u32	fs_csaddr;
-	__u32	fs_cssize;
-	__u32	fs_cgsize;
-	__u32	fs_ntrak;
-	__u32	fs_nsect;
-	__u32	fs_spc;
-	__u32	fs_ncyl;
-	__u32	fs_cpg;
-	__u32	fs_ipg;
-	__u32	fs_fpg;
+	__fs32	fs_interleave;
+	__fs32	fs_trackskew;
+	__fs32	fs_id[2];
+	__fs32	fs_csaddr;
+	__fs32	fs_cssize;
+	__fs32	fs_cgsize;
+	__fs32	fs_ntrak;
+	__fs32	fs_nsect;
+	__fs32	fs_spc;
+	__fs32	fs_ncyl;
+	__fs32	fs_cpg;
+	__fs32	fs_ipg;
+	__fs32	fs_fpg;
 	struct ufs_csum fs_cstotal;
 	__s8	fs_fmod;
 	__s8	fs_clean;
@@ -817,48 +827,48 @@
 
 struct ufs_super_block_second {
 	__s8	fs_fsmnt[212];
-	__u32	fs_cgrotor;
-	__u32	fs_csp[UFS_MAXCSBUFS];
-	__u32	fs_maxcluster;
-	__u32	fs_cpc;
-	__u16	fs_opostbl[82];
+	__fs32	fs_cgrotor;
+	__fs32	fs_csp[UFS_MAXCSBUFS];
+	__fs32	fs_maxcluster;
+	__fs32	fs_cpc;
+	__fs16	fs_opostbl[82];
 };	
 
 struct ufs_super_block_third {
-	__u16	fs_opostbl[46];
+	__fs16	fs_opostbl[46];
 	union {
 		struct {
-			__s32	fs_sparecon[53];/* reserved for future constants */
-			__s32	fs_reclaim;
-			__s32	fs_sparecon2[1];
-			__s32	fs_state;	/* file system state time stamp */
-			__u32	fs_qbmask[2];	/* ~usb_bmask */
-			__u32	fs_qfmask[2];	/* ~usb_fmask */
+			__fs32	fs_sparecon[53];/* reserved for future constants */
+			__fs32	fs_reclaim;
+			__fs32	fs_sparecon2[1];
+			__fs32	fs_state;	/* file system state time stamp */
+			__fs32	fs_qbmask[2];	/* ~usb_bmask */
+			__fs32	fs_qfmask[2];	/* ~usb_fmask */
 		} fs_sun;
 		struct {
-			__s32	fs_sparecon[53];/* reserved for future constants */
-			__s32	fs_reclaim;
-			__s32	fs_sparecon2[1];
-			__u32	fs_npsect;	/* # sectors/track including spares */
-			__u32	fs_qbmask[2];	/* ~usb_bmask */
-			__u32	fs_qfmask[2];	/* ~usb_fmask */
+			__fs32	fs_sparecon[53];/* reserved for future constants */
+			__fs32	fs_reclaim;
+			__fs32	fs_sparecon2[1];
+			__fs32	fs_npsect;	/* # sectors/track including spares */
+			__fs32	fs_qbmask[2];	/* ~usb_bmask */
+			__fs32	fs_qfmask[2];	/* ~usb_fmask */
 		} fs_sunx86;
 		struct {
-			__s32	fs_sparecon[50];/* reserved for future constants */
-			__s32	fs_contigsumsize;/* size of cluster summary array */
-			__s32	fs_maxsymlinklen;/* max length of an internal symlink */
-			__s32	fs_inodefmt;	/* format of on-disk inodes */
-			__u32	fs_maxfilesize[2];	/* max representable file size */
-			__u32	fs_qbmask[2];	/* ~usb_bmask */
-			__u32	fs_qfmask[2];	/* ~usb_fmask */
-			__s32	fs_state;	/* file system state time stamp */
+			__fs32	fs_sparecon[50];/* reserved for future constants */
+			__fs32	fs_contigsumsize;/* size of cluster summary array */
+			__fs32	fs_maxsymlinklen;/* max length of an internal symlink */
+			__fs32	fs_inodefmt;	/* format of on-disk inodes */
+			__fs32	fs_maxfilesize[2];	/* max representable file size */
+			__fs32	fs_qbmask[2];	/* ~usb_bmask */
+			__fs32	fs_qfmask[2];	/* ~usb_fmask */
+			__fs32	fs_state;	/* file system state time stamp */
 		} fs_44;
 	} fs_u2;
-	__s32	fs_postblformat;
-	__s32	fs_nrpos;
-	__s32	fs_postbloff;
-	__s32	fs_rotbloff;
-	__s32	fs_magic;
+	__fs32	fs_postblformat;
+	__fs32	fs_nrpos;
+	__fs32	fs_postbloff;
+	__fs32	fs_rotbloff;
+	__fs32	fs_magic;
 	__u8	fs_space[1];
 };
 
@@ -867,7 +877,7 @@
 /* balloc.c */
 extern void ufs_free_fragments (struct inode *, unsigned, unsigned);
 extern void ufs_free_blocks (struct inode *, unsigned, unsigned);
-extern unsigned ufs_new_fragments (struct inode *, u32 *, unsigned, unsigned, unsigned, int *);
+extern unsigned ufs_new_fragments (struct inode *, __fs32 *, unsigned, unsigned, unsigned, int *);
 
 /* cylinder.c */
 extern struct ufs_cg_private_info * ufs_load_cylinder (struct super_block *, unsigned);
@@ -875,7 +885,6 @@
 
 /* dir.c */
 extern struct inode_operations ufs_dir_inode_operations;
-extern int ufs_check_dir_entry (const char *, struct inode *, struct ufs_dir_entry *, struct buffer_head *, unsigned long);
 extern int ufs_add_link (struct dentry *, struct inode *);
 extern ino_t ufs_inode_by_name(struct inode *, struct dentry *);
 extern int ufs_make_empty(struct inode *, struct inode *);
@@ -899,7 +908,7 @@
 extern u64  ufs_frag_map (struct inode *, sector_t);
 extern void ufs_read_inode (struct inode *);
 extern void ufs_put_inode (struct inode *);
-extern void ufs_write_inode (struct inode *, int);
+extern int ufs_write_inode (struct inode *, int);
 extern int ufs_sync_inode (struct inode *);
 extern void ufs_delete_inode (struct inode *);
 extern struct buffer_head * ufs_getfrag (struct inode *, unsigned, int, int *);
@@ -909,11 +918,9 @@
 extern struct file_operations ufs_dir_operations;
         
 /* super.c */
-extern struct file_system_type ufs_fs_type;
 extern void ufs_warning (struct super_block *, const char *, const char *, ...) __attribute__ ((format (printf, 3, 4)));
 extern void ufs_error (struct super_block *, const char *, const char *, ...) __attribute__ ((format (printf, 3, 4)));
 extern void ufs_panic (struct super_block *, const char *, const char *, ...) __attribute__ ((format (printf, 3, 4)));
-extern void ufs_write_super (struct super_block *);
 
 /* symlink.c */
 extern struct inode_operations ufs_fast_symlink_inode_operations;
diff -Nru a/include/linux/ufs_fs_i.h b/include/linux/ufs_fs_i.h
--- a/include/linux/ufs_fs_i.h	2004-10-18 14:56:32 -07:00
+++ b/include/linux/ufs_fs_i.h	2004-10-18 14:56:32 -07:00
@@ -15,9 +15,9 @@
 
 struct ufs_inode_info {
 	union {
-		__u32	i_data[15];
+		__fs32	i_data[15];
 		__u8	i_symlink[4*15];
-		__u64	u2_i_data[15];
+		__fs64	u2_i_data[15];
 	} i_u1;
 	__u32	i_flags;
 	__u32	i_gen;
diff -Nru a/include/linux/umem.h b/include/linux/umem.h
--- a/include/linux/umem.h	2004-10-18 14:55:54 -07:00
+++ b/include/linux/umem.h	2004-10-18 14:55:54 -07:00
@@ -110,19 +110,19 @@
 #define DMA_WRITE_TO_HOST 1
 
 struct mm_dma_desc {
-	u64	pci_addr;
-	u64	local_addr;
-	u32	transfer_size;
+	__le64	pci_addr;
+	__le64	local_addr;
+	__le32	transfer_size;
 	u32	zero1;
-	u64	next_desc_addr;
-	u64	sem_addr;
-	u32	control_bits;
+	__le64	next_desc_addr;
+	__le64	sem_addr;
+	__le32	control_bits;
 	u32	zero2;
 
 	dma_addr_t data_dma_handle;
 
 	/* Copy of the bits */
-	u64	sem_control_bits;
+	__le64	sem_control_bits;
 } __attribute__((aligned(8)));
 
 #define PCI_VENDOR_ID_MICRO_MEMORY		0x1332
diff -Nru a/include/linux/usb.h b/include/linux/usb.h
--- a/include/linux/usb.h	2004-10-18 14:56:29 -07:00
+++ b/include/linux/usb.h	2004-10-18 14:56:29 -07:00
@@ -294,8 +294,6 @@
 	struct semaphore serialize;
 
 	unsigned int toggle[2];		/* one bit for each endpoint ([0] = IN, [1] = OUT) */
-	unsigned int halted[2];		/* endpoint halts; one bit per endpoint # & direction; */
-					/* [0] = IN, [1] = OUT */
 	int epmaxpacketin[16];		/* INput endpoint specific maximums */
 	int epmaxpacketout[16];		/* OUTput endpoint specific maximums */
 
@@ -653,8 +651,6 @@
  *	it likes with the URB, including resubmitting or freeing it.
  * @iso_frame_desc: Used to provide arrays of ISO transfer buffers and to 
  *	collect the transfer status for each buffer.
- * @timeout: If set to zero, the urb will never timeout.  Otherwise this is
- *	the time in jiffies that this urb will timeout in.
  *
  * This structure identifies USB transfer requests.  URBs must be allocated by
  * calling usb_alloc_urb() and freed with a call to usb_free_urb().
@@ -684,8 +680,8 @@
  *
  * Initialization:
  *
- * All URBs submitted must initialize dev, pipe,
- * transfer_flags (may be zero), complete, timeout (may be zero).
+ * All URBs submitted must initialize the dev, pipe, transfer_flags (may be
+ * zero), and complete fields.
  * The URB_ASYNC_UNLINK transfer flag affects later invocations of
  * the usb_unlink_urb() routine.  Note: Failure to set URB_ASYNC_UNLINK
  * with usb_unlink_urb() is deprecated.  For synchronous unlinks use
@@ -785,7 +781,6 @@
 	int number_of_packets;		/* (in) number of ISO packets */
 	int interval;			/* (modify) transfer interval (INT/ISO) */
 	int error_count;		/* (return) number of ISO errors */
-	int timeout;			/* (in) timeout, in jiffies */
 	void *context;			/* (in) context for completion */
 	usb_complete_t complete;	/* (in) completion routine */
 	struct usb_iso_packet_descriptor iso_frame_desc[0];	/* (in) ISO ONLY */
@@ -1083,10 +1078,6 @@
 #define usb_gettoggle(dev, ep, out) (((dev)->toggle[out] >> (ep)) & 1)
 #define	usb_dotoggle(dev, ep, out)  ((dev)->toggle[out] ^= (1 << (ep)))
 #define usb_settoggle(dev, ep, out, bit) ((dev)->toggle[out] = ((dev)->toggle[out] & ~(1 << (ep))) | ((bit) << (ep)))
-
-/* Endpoint halt control/status ... likewise USE WITH CAUTION */
-#define usb_endpoint_running(dev, ep, out) ((dev)->halted[out] &= ~(1 << (ep)))
-#define usb_endpoint_halted(dev, ep, out) ((dev)->halted[out] & (1 << (ep)))
 
 
 static inline unsigned int __create_pipe(struct usb_device *dev, unsigned int endpoint)
diff -Nru a/include/linux/usb_ch9.h b/include/linux/usb_ch9.h
--- a/include/linux/usb_ch9.h	2004-10-18 14:56:29 -07:00
+++ b/include/linux/usb_ch9.h	2004-10-18 14:56:29 -07:00
@@ -103,9 +103,9 @@
 struct usb_ctrlrequest {
 	__u8 bRequestType;
 	__u8 bRequest;
-	__u16 wValue;
-	__u16 wIndex;
-	__u16 wLength;
+	__le16 wValue;
+	__le16 wIndex;
+	__le16 wLength;
 } __attribute__ ((packed));
 
 /*-------------------------------------------------------------------------*/
@@ -230,7 +230,7 @@
 	__u8  bLength;
 	__u8  bDescriptorType;
 
-	__u16 wData[1];		/* UTF-16LE encoded */
+	__le16 wData[1];		/* UTF-16LE encoded */
 } __attribute__ ((packed));
 
 /* note that "string" zero is special, it holds language codes that
diff -Nru a/include/linux/usb_gadget.h b/include/linux/usb_gadget.h
--- a/include/linux/usb_gadget.h	2004-10-18 14:56:29 -07:00
+++ b/include/linux/usb_gadget.h	2004-10-18 14:56:29 -07:00
@@ -767,12 +767,6 @@
  * the (remote) host can't do that any longer; or an error state might
  * be cleared, to make the device behave identically whether or not
  * power is maintained.
- *
- * If the OTG b_hnp_enabled flag is set during a suspend() call, the
- * device may use HNP to switch from "B-Peripheral" to "B-Host" mode
- * (or back from "A-Peripheral" mode to the original "A-Host") if
- * the gadget driver calls usb_gadget_disconnect() before the device
- * is resumed.
  */
 struct usb_gadget_driver {
 	char			*function;
diff -Nru a/include/linux/usb_otg.h b/include/linux/usb_otg.h
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/include/linux/usb_otg.h	2004-10-18 14:57:24 -07:00
@@ -0,0 +1,118 @@
+// include/linux/usb_otg.h 
+
+/*
+ * These APIs may be used between USB controllers.  USB device drivers
+ * (for either host or peripheral roles) don't use these calls; they
+ * continue to use just usb_device and usb_gadget.
+ */
+
+
+/* OTG defines lots of enumeration states before device reset */
+enum usb_otg_state {
+	OTG_STATE_UNDEFINED = 0,
+
+	/* single-role peripheral, and dual-role default-b */
+	OTG_STATE_B_IDLE,
+	OTG_STATE_B_SRP_INIT,
+	OTG_STATE_B_PERIPHERAL,
+
+	/* extra dual-role default-b states */
+	OTG_STATE_B_WAIT_ACON,
+	OTG_STATE_B_HOST,
+
+	/* dual-role default-a */
+	OTG_STATE_A_IDLE,
+	OTG_STATE_A_WAIT_VRISE,
+	OTG_STATE_A_WAIT_BCON,
+	OTG_STATE_A_HOST,
+	OTG_STATE_A_SUSPEND,
+	OTG_STATE_A_PERIPHERAL,
+	OTG_STATE_A_WAIT_VFALL,
+	OTG_STATE_A_VBUS_ERR,
+};
+
+/*
+ * the otg driver needs to interact with both device side and host side
+ * usb controllers.  it decides which controller is active at a given
+ * moment, using the transceiver, ID signal, HNP and sometimes static
+ * configuration information (including "board isn't wired for otg").
+ */
+struct otg_transceiver {
+	struct device		*dev;
+	const char		*label;
+
+	u8			default_a;
+	enum usb_otg_state	state;
+
+	struct usb_bus		*host;
+	struct usb_gadget	*gadget;
+
+	/* to pass extra port status to the root hub */
+	u16			port_status;
+	u16			port_change;
+
+	/* bind/unbind the host controller */
+	int 	(*set_host)(struct otg_transceiver *otg,
+				struct usb_bus *host);
+
+	/* bind/unbind the peripheral controller */
+	int	(*set_peripheral)(struct otg_transceiver *otg,
+				struct usb_gadget *gadget);
+
+	/* effective for B devices, ignored for A-peripheral */
+	int	(*set_power)(struct otg_transceiver *otg,
+				unsigned mA);
+
+	/* for B devices only:  start session with A-Host */
+	int	(*start_srp)(struct otg_transceiver *otg);
+
+	/* start or continue HNP role switch */
+	int	(*start_hnp)(struct otg_transceiver *otg);
+
+};
+
+
+/* for board-specific init logic */
+extern int otg_set_transceiver(struct otg_transceiver *);
+
+
+/* for usb host and peripheral controller drivers */
+extern struct otg_transceiver *otg_get_transceiver(void);
+
+static inline int
+otg_start_hnp(struct otg_transceiver *otg)
+{
+	return otg->start_hnp(otg);
+}
+
+
+/* for HCDs */
+static inline int
+otg_set_host(struct otg_transceiver *otg, struct usb_bus *host)
+{
+	return otg->set_host(otg, host);
+}
+
+
+/* for usb peripheral controller drivers */
+static inline int
+otg_set_peripheral(struct otg_transceiver *otg, struct usb_gadget *periph)
+{
+	return otg->set_peripheral(otg, periph);
+}
+
+static inline int
+otg_set_power(struct otg_transceiver *otg, unsigned mA)
+{
+	return otg->set_power(otg, mA);
+}
+
+static inline int
+otg_start_srp(struct otg_transceiver *otg)
+{
+	return otg->start_srp(otg);
+}
+
+
+/* for OTG controller drivers (and maybe other stuff) */
+extern int usb_bus_start_enum(struct usb_bus *bus, unsigned port_num);
diff -Nru a/include/linux/videodev.h b/include/linux/videodev.h
--- a/include/linux/videodev.h	2004-10-18 14:57:19 -07:00
+++ b/include/linux/videodev.h	2004-10-18 14:57:19 -07:00
@@ -1,6 +1,7 @@
 #ifndef __LINUX_VIDEODEV_H
 #define __LINUX_VIDEODEV_H
 
+#include <linux/compiler.h>
 #include <linux/types.h>
 #include <linux/version.h>
 
diff -Nru a/include/linux/vt_kern.h b/include/linux/vt_kern.h
--- a/include/linux/vt_kern.h	2004-10-18 14:56:50 -07:00
+++ b/include/linux/vt_kern.h	2004-10-18 14:56:50 -07:00
@@ -93,8 +93,8 @@
  * vc_screen.c shares this temporary buffer with the console write code so that
  * we can easily avoid touching user space while holding the console spinlock.
  */
-extern char con_buf[PAGE_SIZE];
 #define CON_BUF_SIZE	PAGE_SIZE
+extern char con_buf[CON_BUF_SIZE];
 extern struct semaphore con_buf_sem;
 
 #endif /* _VT_KERN_H */
diff -Nru a/include/linux/wait.h b/include/linux/wait.h
--- a/include/linux/wait.h	2004-10-18 14:56:32 -07:00
+++ b/include/linux/wait.h	2004-10-18 14:56:32 -07:00
@@ -3,11 +3,20 @@
 
 #define WNOHANG		0x00000001
 #define WUNTRACED	0x00000002
+#define WSTOPPED	WUNTRACED
+#define WEXITED		0x00000004
+#define WCONTINUED	0x00000008
+#define WNOWAIT		0x01000000	/* Don't reap, just poll status.  */
 
 #define __WNOTHREAD	0x20000000	/* Don't wait on children of other threads in this group */
 #define __WALL		0x40000000	/* Wait on all children, regardless of type */
 #define __WCLONE	0x80000000	/* Wait only on non-SIGCHLD children */
 
+/* First argument to waitid: */
+#define P_ALL		0
+#define P_PID		1
+#define P_PGID		2
+
 #ifdef __KERNEL__
 
 #include <linux/config.h>
@@ -80,6 +89,15 @@
 	return !list_empty(&q->task_list);
 }
 
+/*
+ * Used to distinguish between sync and async io wait context:
+ * sync i/o typically specifies a NULL wait queue entry or a wait
+ * queue entry bound to a task (current task) to wake up.
+ * aio specifies a wait queue entry with an async notification
+ * callback routine, not associated with any task.
+ */
+#define is_sync_wait(wait)	(!(wait) || ((wait)->task))
+
 extern void FASTCALL(add_wait_queue(wait_queue_head_t *q, wait_queue_t * wait));
 extern void FASTCALL(add_wait_queue_exclusive(wait_queue_head_t *q, wait_queue_t * wait));
 extern void FASTCALL(remove_wait_queue(wait_queue_head_t *q, wait_queue_t * wait));
@@ -137,6 +155,29 @@
 		break;							\
 	__wait_event(wq, condition);					\
 } while (0)
+
+#define __wait_event_timeout(wq, condition, ret)			\
+do {									\
+	DEFINE_WAIT(__wait);						\
+									\
+	for (;;) {							\
+		prepare_to_wait(&wq, &__wait, TASK_UNINTERRUPTIBLE);	\
+		if (condition)						\
+			break;						\
+		ret = schedule_timeout(ret);				\
+		if (!ret)						\
+			break;						\
+	}								\
+	finish_wait(&wq, &__wait);					\
+} while (0)
+
+#define wait_event_timeout(wq, condition, timeout)			\
+({									\
+	long __ret = timeout;						\
+	if (!(condition)) 						\
+		__wait_event_timeout(wq, condition, __ret);		\
+	__ret;								\
+})
 
 #define __wait_event_interruptible(wq, condition, ret)			\
 do {									\
diff -Nru a/include/linux/workqueue.h b/include/linux/workqueue.h
--- a/include/linux/workqueue.h	2004-10-18 14:56:49 -07:00
+++ b/include/linux/workqueue.h	2004-10-18 14:56:49 -07:00
@@ -63,6 +63,8 @@
 
 extern int FASTCALL(schedule_work(struct work_struct *work));
 extern int FASTCALL(schedule_delayed_work(struct work_struct *work, unsigned long delay));
+
+extern int schedule_delayed_work_on(int cpu, struct work_struct *work, unsigned long delay);
 extern void flush_scheduled_work(void);
 extern int current_is_keventd(void);
 extern int keventd_up(void);
diff -Nru a/include/linux/writeback.h b/include/linux/writeback.h
--- a/include/linux/writeback.h	2004-10-18 14:55:55 -07:00
+++ b/include/linux/writeback.h	2004-10-18 14:55:55 -07:00
@@ -29,7 +29,9 @@
 };
 
 /*
- * A control structure which tells the writeback code what to do
+ * A control structure which tells the writeback code what to do.  These are
+ * always on the stack, and hence need no locking.  They are always initialised
+ * in a manner such that unspecified fields are set to zero.
  */
 struct writeback_control {
 	struct backing_dev_info *bdi;	/* If !NULL, only write back this
@@ -40,10 +42,19 @@
 	long nr_to_write;		/* Write this many pages, and decrement
 					   this for each page written */
 	long pages_skipped;		/* Pages which were not written */
-	int nonblocking;		/* Don't get stuck on request queues */
-	int encountered_congestion;	/* An output: a queue is full */
-	int for_kupdate;		/* A kupdate writeback */
-	int for_reclaim;		/* Invoked from the page allocator */
+
+	/*
+	 * For a_ops->writepages(): is start or end are non-zero then this is
+	 * a hint that the filesystem need only write out the pages inside that
+	 * byterange.  The byte at `end' is included in the writeout request.
+	 */
+	loff_t start;
+	loff_t end;
+
+	unsigned nonblocking:1;			/* Don't get stuck on request queues */
+	unsigned encountered_congestion:1;	/* An output: a queue is full */
+	unsigned for_kupdate:1;			/* A kupdate writeback */
+	unsigned for_reclaim:1;			/* Invoked from the page allocator */
 };
 
 /*
@@ -64,6 +75,7 @@
 /* writeback.h requires fs.h; it, too, is not included from here. */
 static inline void wait_on_inode(struct inode *inode)
 {
+	might_sleep();
 	if (inode->i_state & I_LOCK)
 		__wait_on_inode(inode);
 }
@@ -92,6 +104,8 @@
 void balance_dirty_pages_ratelimited(struct address_space *mapping);
 int pdflush_operation(void (*fn)(unsigned long), unsigned long arg0);
 int do_writepages(struct address_space *mapping, struct writeback_control *wbc);
+int sync_page_range(struct inode *inode, struct address_space *mapping,
+			loff_t pos, size_t count);
 
 /* pdflush.c */
 extern int nr_pdflush_threads;	/* Global so it can be exported to sysctl
diff -Nru a/include/linux/xfrm.h b/include/linux/xfrm.h
--- a/include/linux/xfrm.h	2004-10-18 14:56:18 -07:00
+++ b/include/linux/xfrm.h	2004-10-18 14:56:18 -07:00
@@ -190,6 +190,7 @@
 	__u8				replay_window;
 	__u8				flags;
 #define XFRM_STATE_NOECN	1
+#define XFRM_STATE_DECAP_DSCP	2
 };
 
 struct xfrm_usersa_id {
diff -Nru a/include/math-emu/op-common.h b/include/math-emu/op-common.h
--- a/include/math-emu/op-common.h	2004-10-18 14:56:28 -07:00
+++ b/include/math-emu/op-common.h	2004-10-18 14:56:28 -07:00
@@ -769,9 +769,9 @@
 	X##_c = FP_CLS_NORMAL;						\
 									\
 	if ((X##_s = (r < 0)))						\
-	  r = -r;							\
-									\
-	ur_ = (unsigned rtype) r;					\
+	  ur_ = (unsigned rtype) -r;					\
+	else								\
+	  ur_ = (unsigned rtype) r;					\
 	if (rsize <= _FP_W_TYPE_SIZE)					\
 	  __FP_CLZ(X##_e, ur_);						\
 	else								\
diff -Nru a/include/media/id.h b/include/media/id.h
--- a/include/media/id.h	2004-10-18 14:56:31 -07:00
+++ b/include/media/id.h	2004-10-18 14:56:31 -07:00
@@ -35,4 +35,3 @@
 #ifndef I2C_ALGO_SAA7134
 # define I2C_ALGO_SAA7134 0x090000
 #endif
-
diff -Nru a/include/media/tuner.h b/include/media/tuner.h
--- a/include/media/tuner.h	2004-10-18 14:56:48 -07:00
+++ b/include/media/tuner.h	2004-10-18 14:56:48 -07:00
@@ -70,6 +70,8 @@
 #define TUNER_PHILIPS_FM1236_MK3 43
 #define TUNER_PHILIPS_4IN1       44	/* ATI TV Wonder Pro - Conexant */
 #define TUNER_MICROTUNE_4049FM5  45
+#define TUNER_LG_NTSC_TAPE       47
+#define TUNER_TNF_8831BGFF       48
 
 #define NOTUNER 0
 #define PAL     1	/* PAL_BG */
@@ -88,6 +90,7 @@
 #define Samsung 7
 #define Microtune 8
 #define HITACHI 9
+#define Panasonic 10
 
 #define TUNER_SET_TYPE               _IOW('t',1,int)    /* set tuner type */
 #define TUNER_SET_TVFREQ             _IOW('t',2,int)    /* set tv freq */
@@ -95,5 +98,19 @@
 # define TUNER_SET_RADIOFREQ         _IOW('t',3,int)    /* set radio freq */
 # define TUNER_SET_MODE              _IOW('t',4,int)    /* set tuner mode */
 #endif
+
+#define  TDA9887_SET_CONFIG          _IOW('t',5,int)
+/* tv card specific */
+# define TDA9887_PRESENT             (1<<0)
+# define TDA9887_PORT1               (1<<1)
+# define TDA9887_PORT2               (1<<2)
+# define TDA9887_QSS                 (1<<3)
+# define TDA9887_INTERCARRIER        (1<<4)
+/* config options */
+# define TDA9887_DEEMPHASIS_MASK     (3<<16)
+# define TDA9887_DEEMPHASIS_NONE     (1<<16)
+# define TDA9887_DEEMPHASIS_50       (2<<16)
+# define TDA9887_DEEMPHASIS_75       (3<<16)
+# define TDA9887_AUTOMUTE            (1<<18)
 
 #endif
diff -Nru a/include/net/addrconf.h b/include/net/addrconf.h
--- a/include/net/addrconf.h	2004-10-18 14:56:49 -07:00
+++ b/include/net/addrconf.h	2004-10-18 14:56:49 -07:00
@@ -74,7 +74,7 @@
 						      const struct sock *sk2);
 extern void			addrconf_join_solict(struct net_device *dev,
 					struct in6_addr *addr);
-extern void			addrconf_leave_solict(struct net_device *dev,
+extern void			addrconf_leave_solict(struct inet6_dev *idev,
 					struct in6_addr *addr);
 
 /*
@@ -89,6 +89,7 @@
 		struct in6_addr *src_addr);
 
 extern int ipv6_dev_mc_inc(struct net_device *dev, struct in6_addr *addr);
+extern int __ipv6_dev_mc_dec(struct inet6_dev *idev, struct in6_addr *addr);
 extern int ipv6_dev_mc_dec(struct net_device *dev, struct in6_addr *addr);
 extern void ipv6_mc_up(struct inet6_dev *idev);
 extern void ipv6_mc_down(struct inet6_dev *idev);
@@ -111,6 +112,7 @@
 extern int inet6_ac_check(struct sock *sk, struct in6_addr *addr, int ifindex);
 
 extern int ipv6_dev_ac_inc(struct net_device *dev, struct in6_addr *addr);
+extern int __ipv6_dev_ac_dec(struct inet6_dev *idev, struct in6_addr *addr);
 extern int ipv6_dev_ac_dec(struct net_device *dev, struct in6_addr *addr);
 extern int ipv6_chk_acast_addr(struct net_device *dev, struct in6_addr *addr);
 
diff -Nru a/include/net/af_unix.h b/include/net/af_unix.h
--- a/include/net/af_unix.h	2004-10-18 14:56:49 -07:00
+++ b/include/net/af_unix.h	2004-10-18 14:56:49 -07:00
@@ -37,16 +37,14 @@
 #define forall_unix_sockets(i, s) \
 	for (s = first_unix_socket(&(i)); s; s = next_unix_socket(&(i),(s)))
 
-struct unix_address
-{
+struct unix_address {
 	atomic_t	refcnt;
 	int		len;
 	unsigned	hash;
 	struct sockaddr_un name[0];
 };
 
-struct unix_skb_parms
-{
+struct unix_skb_parms {
 	struct ucred		creds;		/* Skb credentials	*/
 	struct scm_fp_list	*fp;		/* Passed files		*/
 };
@@ -68,6 +66,7 @@
         struct dentry		*dentry;
         struct vfsmount		*mnt;
         struct semaphore        readsem;
+        struct sock		*peer;
         struct sock		*other;
         struct sock		*gc_tree;
         atomic_t                inflight;
diff -Nru a/include/net/dn_neigh.h b/include/net/dn_neigh.h
--- a/include/net/dn_neigh.h	2004-10-18 14:56:31 -07:00
+++ b/include/net/dn_neigh.h	2004-10-18 14:56:31 -07:00
@@ -18,7 +18,6 @@
 
 extern void dn_neigh_init(void);
 extern void dn_neigh_cleanup(void);
-extern struct neighbour *dn_neigh_lookup(struct neigh_table *tbl, const void *ptr);
 extern int dn_neigh_router_hello(struct sk_buff *skb);
 extern int dn_neigh_endnode_hello(struct sk_buff *skb);
 extern void dn_neigh_pointopoint_hello(struct sk_buff *skb);
diff -Nru a/include/net/gen_stats.h b/include/net/gen_stats.h
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/include/net/gen_stats.h	2004-10-18 14:57:24 -07:00
@@ -0,0 +1,45 @@
+#ifndef __NET_GEN_STATS_H
+#define __NET_GEN_STATS_H
+
+#include <linux/gen_stats.h>
+#include <linux/socket.h>
+#include <linux/rtnetlink.h>
+#include <linux/pkt_sched.h>
+
+struct gnet_dump
+{
+	spinlock_t *      lock;
+	struct sk_buff *  skb;
+	struct rtattr *   tail;
+
+	/* Backward compatability */
+	int               compat_tc_stats;
+	int               compat_xstats;
+	struct rtattr *   xstats;
+	struct tc_stats   tc_stats;
+};
+
+extern int gnet_stats_start_copy(struct sk_buff *skb, int type,
+				 spinlock_t *lock, struct gnet_dump *d);
+
+extern int gnet_stats_start_copy_compat(struct sk_buff *skb, int type,
+					int tc_stats_type,int xstats_type,
+					spinlock_t *lock, struct gnet_dump *d);
+
+extern int gnet_stats_copy_basic(struct gnet_dump *d,
+				 struct gnet_stats_basic *b);
+extern int gnet_stats_copy_rate_est(struct gnet_dump *d,
+				    struct gnet_stats_rate_est *r);
+extern int gnet_stats_copy_queue(struct gnet_dump *d,
+				 struct gnet_stats_queue *q);
+extern int gnet_stats_copy_app(struct gnet_dump *d, void *st, int len);
+
+extern int gnet_stats_finish_copy(struct gnet_dump *d);
+
+extern int gen_new_estimator(struct gnet_stats_basic *bstats,
+			     struct gnet_stats_rate_est *rate_est,
+			     spinlock_t *stats_lock, struct rtattr *opt);
+extern void gen_kill_estimator(struct gnet_stats_basic *bstats,
+			       struct gnet_stats_rate_est *rate_est);
+
+#endif
diff -Nru a/include/net/if_inet6.h b/include/net/if_inet6.h
--- a/include/net/if_inet6.h	2004-10-18 14:57:04 -07:00
+++ b/include/net/if_inet6.h	2004-10-18 14:57:04 -07:00
@@ -51,6 +51,7 @@
 	struct timer_list	timer;
 
 	struct inet6_dev	*idev;
+	struct rt6_info		*rt;
 
 	struct inet6_ifaddr	*lst_next;      /* next addr in addr_lst */
 	struct inet6_ifaddr	*if_next;       /* next addr in inet6_dev */
@@ -133,6 +134,7 @@
 {
 	struct in6_addr		aca_addr;
 	struct inet6_dev	*aca_idev;
+	struct rt6_info		*aca_rt;
 	struct ifacaddr6	*aca_next;
 	int			aca_users;
 	atomic_t		aca_refcnt;
diff -Nru a/include/net/inet_ecn.h b/include/net/inet_ecn.h
--- a/include/net/inet_ecn.h	2004-10-18 14:57:03 -07:00
+++ b/include/net/inet_ecn.h	2004-10-18 14:57:03 -07:00
@@ -2,6 +2,7 @@
 #define _INET_ECN_H_
 
 #include <linux/ip.h>
+#include <net/dsfield.h>
 
 enum {
 	INET_ECN_NOT_ECT = 0,
@@ -16,9 +17,9 @@
 	return (dsfield & INET_ECN_MASK) == INET_ECN_CE;
 }
 
-static inline int INET_ECN_is_not_ce(__u8 dsfield)
+static inline int INET_ECN_is_not_ect(__u8 dsfield)
 {
-	return (dsfield & INET_ECN_MASK) == INET_ECN_ECT_0;
+	return (dsfield & INET_ECN_MASK) == INET_ECN_NOT_ECT;
 }
 
 static inline int INET_ECN_is_capable(__u8 dsfield)
@@ -29,8 +30,8 @@
 static inline __u8 INET_ECN_encapsulate(__u8 outer, __u8 inner)
 {
 	outer &= ~INET_ECN_MASK;
-	if (INET_ECN_is_capable(inner))
-		outer |= (inner & INET_ECN_MASK);
+	outer |= !INET_ECN_is_ce(inner) ? (inner & INET_ECN_MASK) :
+					  INET_ECN_ECT_0;
 	return outer;
 }
 
@@ -50,7 +51,25 @@
 static inline void IP_ECN_set_ce(struct iphdr *iph)
 {
 	u32 check = iph->check;
-	check += __constant_htons(0xFFFE);
+	u32 ecn = (iph->tos + 1) & INET_ECN_MASK;
+
+	/*
+	 * After the last operation we have (in binary):
+	 * INET_ECN_NOT_ECT => 01
+	 * INET_ECN_ECT_1   => 10
+	 * INET_ECN_ECT_0   => 11
+	 * INET_ECN_CE      => 00
+	 */
+	if (!(ecn & 2))
+		return;
+
+	/*
+	 * The following gives us:
+	 * INET_ECN_ECT_1 => check += htons(0xFFFD)
+	 * INET_ECN_ECT_0 => check += htons(0xFFFE)
+	 */
+	check += htons(0xFFFB) + htons(ecn);
+
 	iph->check = check + (check>=0xFFFF);
 	iph->tos |= INET_ECN_CE;
 }
@@ -60,10 +79,18 @@
 	iph->tos &= ~INET_ECN_MASK;
 }
 
+static inline void ipv4_copy_dscp(struct iphdr *outer, struct iphdr *inner)
+{
+	u32 dscp = ipv4_get_dsfield(outer) & ~INET_ECN_MASK;
+	ipv4_change_dsfield(inner, INET_ECN_MASK, dscp);
+}
+
 struct ipv6hdr;
 
 static inline void IP6_ECN_set_ce(struct ipv6hdr *iph)
 {
+	if (INET_ECN_is_not_ect(ipv6_get_dsfield(iph)))
+		return;
 	*(u32*)iph |= htonl(INET_ECN_CE << 20);
 }
 
@@ -72,6 +99,10 @@
 	*(u32*)iph &= ~htonl(INET_ECN_MASK << 20);
 }
 
-#define ip6_get_dsfield(iph) ((ntohs(*(u16*)(iph)) >> 4) & 0xFF)
+static inline void ipv6_copy_dscp(struct ipv6hdr *outer, struct ipv6hdr *inner)
+{
+	u32 dscp = ipv6_get_dsfield(outer) & ~INET_ECN_MASK;
+	ipv6_change_dsfield(inner, INET_ECN_MASK, dscp);
+}
 
 #endif
diff -Nru a/include/net/ip.h b/include/net/ip.h
--- a/include/net/ip.h	2004-10-18 14:56:48 -07:00
+++ b/include/net/ip.h	2004-10-18 14:56:48 -07:00
@@ -255,6 +255,7 @@
  */
  
 struct sk_buff *ip_defrag(struct sk_buff *skb);
+extern void ipfrag_flush(void);
 extern int ip_frag_nqueues;
 extern atomic_t ip_frag_mem;
 
diff -Nru a/include/net/ip6_fib.h b/include/net/ip6_fib.h
--- a/include/net/ip6_fib.h	2004-10-18 14:56:49 -07:00
+++ b/include/net/ip6_fib.h	2004-10-18 14:56:49 -07:00
@@ -20,6 +20,7 @@
 #include <net/dst.h>
 #include <net/flow.h>
 #include <linux/rtnetlink.h>
+#include <linux/spinlock.h>
 
 struct rt6_info;
 
diff -Nru a/include/net/ip6_route.h b/include/net/ip6_route.h
--- a/include/net/ip6_route.h	2004-10-18 14:56:19 -07:00
+++ b/include/net/ip6_route.h	2004-10-18 14:56:19 -07:00
@@ -11,8 +11,10 @@
 
 #include <net/flow.h>
 #include <net/ip6_fib.h>
+#include <net/sock.h>
 #include <linux/tcp.h>
 #include <linux/ip.h>
+#include <linux/ipv6.h>
 
 struct pol_chain {
 	int			type;
@@ -40,6 +42,9 @@
 extern int			ip6_route_add(struct in6_rtmsg *rtmsg,
 					      struct nlmsghdr *,
 					      void *rtattr);
+extern int			ip6_ins_rt(struct rt6_info *,
+					   struct nlmsghdr *,
+					   void *rtattr);
 extern int			ip6_del_rt(struct rt6_info *,
 					   struct nlmsghdr *,
 					   void *rtattr);
@@ -69,6 +74,10 @@
 extern int ndisc_dst_gc(int *more);
 extern void fib6_force_start_gc(void);
 
+extern struct rt6_info *addrconf_dst_alloc(struct inet6_dev *idev,
+					   const struct in6_addr *addr,
+					   int anycast);
+
 /*
  *	support functions for ND
  *
@@ -80,9 +89,12 @@
 
 extern void			rt6_purge_dflt_routers(int lst_resort);
 
+extern void			rt6_reset_dflt_pointer(struct rt6_info *rt);
+
 extern void			rt6_redirect(struct in6_addr *dest,
 					     struct in6_addr *saddr,
 					     struct neighbour *neigh,
+					     u8 *lladdr,
 					     int on_link);
 
 extern void			rt6_pmtu_discovery(struct in6_addr *daddr,
diff -Nru a/include/net/ip_fib.h b/include/net/ip_fib.h
--- a/include/net/ip_fib.h	2004-10-18 14:57:03 -07:00
+++ b/include/net/ip_fib.h	2004-10-18 14:57:03 -07:00
@@ -23,8 +23,7 @@
 /* WARNING: The ordering of these elements must match ordering
  *          of RTA_* rtnetlink attribute numbers.
  */
-struct kern_rta
-{
+struct kern_rta {
 	void		*rta_dst;
 	void		*rta_src;
 	int		*rta_iif;
@@ -40,9 +39,12 @@
 	struct rta_session *rta_sess;
 };
 
-struct fib_nh
-{
-	struct net_device		*nh_dev;
+struct fib_info;
+
+struct fib_nh {
+	struct net_device	*nh_dev;
+	struct hlist_node	nh_hash;
+	struct fib_info		*nh_parent;
 	unsigned		nh_flags;
 	unsigned char		nh_scope;
 #ifdef CONFIG_IP_ROUTE_MULTIPATH
@@ -60,10 +62,9 @@
  * This structure contains data shared by many of routes.
  */
 
-struct fib_info
-{
-	struct fib_info		*fib_next;
-	struct fib_info		*fib_prev;
+struct fib_info {
+	struct hlist_node	fib_hash;
+	struct hlist_node	fib_lhash;
 	int			fib_treeref;
 	atomic_t		fib_clntref;
 	int			fib_dead;
@@ -89,8 +90,7 @@
 struct fib_rule;
 #endif
 
-struct fib_result
-{
+struct fib_result {
 	unsigned char	prefixlen;
 	unsigned char	nh_sel;
 	unsigned char	type;
@@ -119,8 +119,7 @@
 #define FIB_RES_DEV(res)		(FIB_RES_NH(res).nh_dev)
 #define FIB_RES_OIF(res)		(FIB_RES_NH(res).nh_oif)
 
-struct fib_table
-{
+struct fib_table {
 	unsigned char	tb_id;
 	unsigned	tb_stamp;
 	int		(*tb_lookup)(struct fib_table *tb, const struct flowi *flp, struct fib_result *res);
@@ -211,22 +210,11 @@
 extern void fib_select_multipath(const struct flowi *flp, struct fib_result *res);
 
 /* Exported by fib_semantics.c */
-extern int 		ip_fib_check_default(u32 gw, struct net_device *dev);
-extern void		fib_release_info(struct fib_info *);
-extern int		fib_semantic_match(int type, struct fib_info *,
-					   const struct flowi *, struct fib_result*);
-extern struct fib_info	*fib_create_info(const struct rtmsg *r, struct kern_rta *rta,
-					 const struct nlmsghdr *, int *err);
-extern int fib_nh_match(struct rtmsg *r, struct nlmsghdr *, struct kern_rta *rta, struct fib_info *fi);
-extern int fib_dump_info(struct sk_buff *skb, u32 pid, u32 seq, int event,
-			 u8 tb_id, u8 type, u8 scope, void *dst, int dst_len, u8 tos,
-			 struct fib_info *fi);
+extern int ip_fib_check_default(u32 gw, struct net_device *dev);
 extern int fib_sync_down(u32 local, struct net_device *dev, int force);
 extern int fib_sync_up(struct net_device *dev);
 extern int fib_convert_rtentry(int cmd, struct nlmsghdr *nl, struct rtmsg *rtm,
 			       struct kern_rta *rta, struct rtentry *r);
-extern void fib_node_seq_show(struct seq_file *seq, int type, int dead,
-			      struct fib_info *fi, u32 prefix, u32 mask);
 extern u32  __fib_res_prefsrc(struct fib_result *res);
 
 /* Exported by fib_hash.c */
@@ -242,7 +230,6 @@
 #ifdef CONFIG_NET_CLS_ROUTE
 extern u32 fib_rules_tclass(struct fib_result *res);
 #endif
-extern u32 fib_rules_policy(u32 saddr, struct fib_result *res, unsigned *flags);
 extern void fib_rules_init(void);
 #endif
 
diff -Nru a/include/net/ipcomp.h b/include/net/ipcomp.h
--- a/include/net/ipcomp.h	2004-10-18 14:56:15 -07:00
+++ b/include/net/ipcomp.h	2004-10-18 14:56:15 -07:00
@@ -5,8 +5,7 @@
 
 struct ipcomp_data {
 	u16 threshold;
-	u8 *scratch;
-	struct crypto_tfm *tfm;
+	struct crypto_tfm **tfms;
 };
 
 #endif
diff -Nru a/include/net/ipv6.h b/include/net/ipv6.h
--- a/include/net/ipv6.h	2004-10-18 14:56:49 -07:00
+++ b/include/net/ipv6.h	2004-10-18 14:56:49 -07:00
@@ -16,7 +16,7 @@
 #define _NET_IPV6_H
 
 #include <linux/ipv6.h>
-#include <asm/hardirq.h>
+#include <linux/hardirq.h>
 #include <net/ndisc.h>
 #include <net/flow.h>
 #include <net/snmp.h>
diff -Nru a/include/net/llc_pdu.h b/include/net/llc_pdu.h
--- a/include/net/llc_pdu.h	2004-10-18 14:56:49 -07:00
+++ b/include/net/llc_pdu.h	2004-10-18 14:56:49 -07:00
@@ -253,9 +253,9 @@
 static inline void llc_pdu_decode_sa(struct sk_buff *skb, u8 *sa)
 {
 	if (skb->protocol == ntohs(ETH_P_802_2))
-		memcpy(sa, ((struct ethhdr *)skb->mac.raw)->h_source, ETH_ALEN);
+		memcpy(sa, eth_hdr(skb)->h_source, ETH_ALEN);
 	else if (skb->protocol == ntohs(ETH_P_TR_802_2))
-		memcpy(sa, ((struct trh_hdr *)skb->mac.raw)->saddr, ETH_ALEN);
+		memcpy(sa, tr_hdr(skb)->saddr, ETH_ALEN);
 }
 
 /**
@@ -268,9 +268,9 @@
 static inline void llc_pdu_decode_da(struct sk_buff *skb, u8 *da)
 {
 	if (skb->protocol == ntohs(ETH_P_802_2))
-		memcpy(da, ((struct ethhdr *)skb->mac.raw)->h_dest, ETH_ALEN);
+		memcpy(da, eth_hdr(skb)->h_dest, ETH_ALEN);
 	else if (skb->protocol == ntohs(ETH_P_TR_802_2))
-		memcpy(da, ((struct trh_hdr *)skb->mac.raw)->daddr, ETH_ALEN);
+		memcpy(da, tr_hdr(skb)->daddr, ETH_ALEN);
 }
 
 /**
@@ -347,7 +347,7 @@
 		struct llc_pdu_un *ev_pdu = llc_pdu_un_hdr(ev_skb);
 		int dsize;
 
-		dsize = ntohs(((struct ethhdr *)ev_skb->mac.raw)->h_proto) - 3;
+		dsize = ntohs(eth_hdr(ev_skb)->h_proto) - 3;
 		memcpy(((u8 *)pdu) + 3, ((u8 *)ev_pdu) + 3, dsize);
 		skb_put(skb, dsize);
 	}
diff -Nru a/include/net/neighbour.h b/include/net/neighbour.h
--- a/include/net/neighbour.h	2004-10-18 14:57:04 -07:00
+++ b/include/net/neighbour.h	2004-10-18 14:57:04 -07:00
@@ -7,6 +7,11 @@
  *	Authors:
  *	Pedro Roque		<roque@di.fc.ul.pt>
  *	Alexey Kuznetsov	<kuznet@ms2.inr.ac.ru>
+ *
+ * 	Changes:
+ *
+ *	Harald Welte:		<laforge@gnumonks.org>
+ *		- Add neighbour cache statistics like rtstat
  */
 
 /* The following flags & states are exported to user space,
@@ -45,14 +50,19 @@
 
 #include <asm/atomic.h>
 #include <linux/skbuff.h>
+#include <linux/netdevice.h>
+#include <linux/rcupdate.h>
+#include <linux/seq_file.h>
 
 #include <linux/err.h>
 #include <linux/sysctl.h>
 
-#define NUD_IN_TIMER	(NUD_INCOMPLETE|NUD_DELAY|NUD_PROBE)
+#define NUD_IN_TIMER	(NUD_INCOMPLETE|NUD_REACHABLE|NUD_DELAY|NUD_PROBE)
 #define NUD_VALID	(NUD_PERMANENT|NUD_NOARP|NUD_REACHABLE|NUD_PROBE|NUD_STALE|NUD_DELAY)
 #define NUD_CONNECTED	(NUD_PERMANENT|NUD_NOARP|NUD_REACHABLE)
 
+struct neighbour;
+
 struct neigh_parms
 {
 	struct neigh_parms *next;
@@ -63,6 +73,10 @@
 
 	void	*sysctl_table;
 
+	int dead;
+	atomic_t refcnt;
+	struct rcu_head rcu_head;
+
 	int	base_reachable_time;
 	int	retrans_time;
 	int	gc_staletime;
@@ -81,12 +95,25 @@
 
 struct neigh_statistics
 {
-	unsigned long allocs;
-	unsigned long res_failed;
-	unsigned long rcv_probes_mcast;
-	unsigned long rcv_probes_ucast;
+	unsigned long allocs;		/* number of allocated neighs */
+	unsigned long destroys;		/* number of destroyed neighs */
+	unsigned long hash_grows;	/* number of hash resizes */
+
+	unsigned long res_failed;	/* nomber of failed resolutions */
+
+	unsigned long lookups;		/* number of lookups */
+	unsigned long hits;		/* number of hits (among lookups) */
+
+	unsigned long rcv_probes_mcast;	/* number of received mcast ipv6 */
+	unsigned long rcv_probes_ucast; /* number of received ucast ipv6 */
+
+	unsigned long periodic_gc_runs;	/* number of periodic GC runs */
+	unsigned long forced_gc_runs;	/* number of forced GC runs */
 };
 
+#define NEIGH_CACHE_STAT_INC(tbl, field)				\
+		(per_cpu_ptr((tbl)->stats, smp_processor_id())->field++)
+
 struct neighbour
 {
 	struct neighbour	*next;
@@ -131,9 +158,6 @@
 	u8			key[0];
 };
 
-#define NEIGH_HASHMASK		0x1F
-#define PNEIGH_HASHMASK		0xF
-
 /*
  *	neighbour table manipulation
  */
@@ -166,22 +190,38 @@
 	unsigned long		last_rand;
 	struct neigh_parms	*parms_list;
 	kmem_cache_t		*kmem_cachep;
-	struct neigh_statistics	stats;
-	struct neighbour	*hash_buckets[NEIGH_HASHMASK+1];
-	struct pneigh_entry	*phash_buckets[PNEIGH_HASHMASK+1];
+	struct neigh_statistics	*stats;
+	struct neighbour	**hash_buckets;
+	unsigned int		hash_mask;
+	__u32			hash_rnd;
+	unsigned int		hash_chain_gc;
+	struct pneigh_entry	**phash_buckets;
+#ifdef CONFIG_PROC_FS
+	struct proc_dir_entry	*pde;
+#endif
 };
 
+/* flags for neigh_update() */
+#define NEIGH_UPDATE_F_OVERRIDE			0x00000001
+#define NEIGH_UPDATE_F_WEAK_OVERRIDE		0x00000002
+#define NEIGH_UPDATE_F_OVERRIDE_ISROUTER	0x00000004
+#define NEIGH_UPDATE_F_ISROUTER			0x40000000
+#define NEIGH_UPDATE_F_ADMIN			0x80000000
+
 extern void			neigh_table_init(struct neigh_table *tbl);
 extern int			neigh_table_clear(struct neigh_table *tbl);
 extern struct neighbour *	neigh_lookup(struct neigh_table *tbl,
 					     const void *pkey,
 					     struct net_device *dev);
+extern struct neighbour *	neigh_lookup_nodev(struct neigh_table *tbl,
+						   const void *pkey);
 extern struct neighbour *	neigh_create(struct neigh_table *tbl,
 					     const void *pkey,
 					     struct net_device *dev);
 extern void			neigh_destroy(struct neighbour *neigh);
 extern int			__neigh_event_send(struct neighbour *neigh, struct sk_buff *skb);
-extern int			neigh_update(struct neighbour *neigh, const u8 *lladdr, u8 new, int override, int arp);
+extern int			neigh_update(struct neighbour *neigh, const u8 *lladdr, u8 new, 
+					     u32 flags);
 extern void			neigh_changeaddr(struct neigh_table *tbl, struct net_device *dev);
 extern int			neigh_ifdown(struct neigh_table *tbl, struct net_device *dev);
 extern int			neigh_resolve_output(struct sk_buff *skb);
@@ -193,6 +233,7 @@
 
 extern struct neigh_parms	*neigh_parms_alloc(struct net_device *dev, struct neigh_table *tbl);
 extern void			neigh_parms_release(struct neigh_table *tbl, struct neigh_parms *parms);
+extern void			neigh_parms_destroy(struct neigh_parms *parms);
 extern unsigned long		neigh_rand_reach_time(unsigned long base);
 
 extern void			pneigh_enqueue(struct neigh_table *tbl, struct neigh_parms *p,
@@ -207,12 +248,47 @@
 extern int neigh_delete(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg);
 extern void neigh_app_ns(struct neighbour *n);
 
+extern void neigh_for_each(struct neigh_table *tbl, void (*cb)(struct neighbour *, void *), void *cookie);
+extern void __neigh_for_each_release(struct neigh_table *tbl, int (*cb)(struct neighbour *));
+extern void pneigh_for_each(struct neigh_table *tbl, void (*cb)(struct pneigh_entry *));
+
+struct neigh_seq_state {
+	struct neigh_table *tbl;
+	void *(*neigh_sub_iter)(struct neigh_seq_state *state,
+				struct neighbour *n, loff_t *pos);
+	unsigned int bucket;
+	unsigned int flags;
+#define NEIGH_SEQ_NEIGH_ONLY	0x00000001
+#define NEIGH_SEQ_IS_PNEIGH	0x00000002
+#define NEIGH_SEQ_SKIP_NOARP	0x00000004
+};
+extern void *neigh_seq_start(struct seq_file *, loff_t *, struct neigh_table *, unsigned int);
+extern void *neigh_seq_next(struct seq_file *, void *, loff_t *);
+extern void neigh_seq_stop(struct seq_file *, void *);
+
 extern int			neigh_sysctl_register(struct net_device *dev, 
 						      struct neigh_parms *p,
 						      int p_id, int pdev_id,
 						      char *p_name,
 						      proc_handler *proc_handler);
 extern void			neigh_sysctl_unregister(struct neigh_parms *p);
+
+static inline void __neigh_parms_put(struct neigh_parms *parms)
+{
+	atomic_dec(&parms->refcnt);
+}
+
+static inline void neigh_parms_put(struct neigh_parms *parms)
+{
+	if (atomic_dec_and_test(&parms->refcnt))
+		neigh_parms_destroy(parms);
+}
+
+static inline struct neigh_parms *neigh_parms_clone(struct neigh_parms *parms)
+{
+	atomic_inc(&parms->refcnt);
+	return parms;
+}
 
 /*
  *	Neighbour references
diff -Nru a/include/net/pkt_act.h b/include/net/pkt_act.h
--- a/include/net/pkt_act.h	2004-10-18 14:56:49 -07:00
+++ b/include/net/pkt_act.h	2004-10-18 14:56:49 -07:00
@@ -212,9 +212,8 @@
 	if (p != NULL) {
 		a->priv = p;
 		return 1;
-	} else {
-		return 0;
 	}
+	return 0;
 }
 
 #ifdef CONFIG_NET_ACT_INIT
@@ -274,11 +273,11 @@
 static inline struct tcf_st *
 tcf_hash_init(struct tc_st *parm, struct rtattr *est, struct tc_action *a, int size, int ovr, int bind)
 {
-	struct tcf_st *p;
-	p = tcf_hash_check (parm,a,ovr,bind);
-	if (NULL == p) {
-		return tcf_hash_create(parm, est, a, size, ovr, bind);
-	}
+	struct tcf_st *p = tcf_hash_check (parm,a,ovr,bind);
+
+	if (!p)
+		p = tcf_hash_create(parm, est, a, size, ovr, bind);
+	return p;
 }
 
 #endif
diff -Nru a/include/net/pkt_sched.h b/include/net/pkt_sched.h
--- a/include/net/pkt_sched.h	2004-10-18 14:56:17 -07:00
+++ b/include/net/pkt_sched.h	2004-10-18 14:56:17 -07:00
@@ -80,6 +80,7 @@
 	int			padded;
 	struct Qdisc_ops	*ops;
 	u32			handle;
+	u32			parent;
 	atomic_t		refcnt;
 	struct sk_buff_head	q;
 	struct net_device	*dev;
@@ -375,7 +376,7 @@
 extern int tcf_register_action(struct tc_action_ops *a);
 extern int tcf_unregister_action(struct tc_action_ops *a);
 extern void tcf_action_destroy(struct tc_action *a, int bind);
-extern int tcf_action_exec(struct sk_buff *skb, struct tc_action *a);
+extern int tcf_action_exec(struct sk_buff *skb, struct tc_action *a, struct tcf_result *res);
 extern int tcf_action_init(struct rtattr *rta, struct rtattr *est, struct tc_action *a,char *n, int ovr, int bind);
 extern int tcf_action_init_1(struct rtattr *rta, struct rtattr *est, struct tc_action *a,char *n, int ovr, int bind);
 extern int tcf_action_dump(struct sk_buff *skb, struct tc_action *a, int, int);
diff -Nru a/include/net/route.h b/include/net/route.h
--- a/include/net/route.h	2004-10-18 14:55:53 -07:00
+++ b/include/net/route.h	2004-10-18 14:55:53 -07:00
@@ -73,11 +73,6 @@
 	/* Miscellaneous cached information */
 	__u32			rt_spec_dst; /* RFC1122 specific destination */
 	struct inet_peer	*peer; /* long-living peer info */
-
-#ifdef CONFIG_IP_ROUTE_NAT
-	__u32			rt_src_map;
-	__u32			rt_dst_map;
-#endif
 };
 
 struct ip_rt_acct
diff -Nru a/include/net/sctp/sctp.h b/include/net/sctp/sctp.h
--- a/include/net/sctp/sctp.h	2004-10-18 14:56:27 -07:00
+++ b/include/net/sctp/sctp.h	2004-10-18 14:56:27 -07:00
@@ -505,6 +505,7 @@
 /* External references. */
 
 extern struct proto sctp_prot;
+extern struct proto sctpv6_prot;
 extern struct proc_dir_entry *proc_net_sctp;
 void sctp_put_port(struct sock *sk);
 
diff -Nru a/include/net/sock.h b/include/net/sock.h
--- a/include/net/sock.h	2004-10-18 14:56:49 -07:00
+++ b/include/net/sock.h	2004-10-18 14:56:49 -07:00
@@ -142,7 +142,6 @@
   *	@sk_route_caps - route capabilities (e.g. %NETIF_F_TSO)
   *	@sk_lingertime - %SO_LINGER l_linger setting
   *	@sk_hashent - hash entry in several tables (e.g. tcp_ehash)
-  *	@sk_pair - socket pair (e.g. AF_UNIX/unix_peer)
   *	@sk_backlog - always used with the per-socket spinlock held
   *	@sk_callback_lock - used with the callbacks in the end of this struct
   *	@sk_error_queue - rarely used
@@ -219,7 +218,6 @@
 	int			sk_route_caps;
 	unsigned long	        sk_lingertime;
 	int			sk_hashent;
-	struct sock		*sk_pair;
 	/*
 	 * The backlog queue is special, it is always used with
 	 * the per-socket spinlock held and requires low latency
@@ -555,6 +553,9 @@
 	int			*sysctl_rmem;
 	int			max_header;
 
+	kmem_cache_t		*slab;
+	int			slab_obj_size;
+
 	char			name[32];
 
 	struct {
@@ -562,6 +563,14 @@
 		u8  __pad[SMP_CACHE_BYTES - sizeof(int)];
 	} stats[NR_CPUS];
 };
+
+extern int sk_alloc_slab(struct proto *prot, char *name);
+extern void sk_free_slab(struct proto *prot);
+
+static inline void sk_alloc_slab_error(struct proto *proto)
+{
+	printk(KERN_CRIT "%s: Can't create sock SLAB cache!\n", proto->name);
+}
 
 static __inline__ void sk_set_owner(struct sock *sk, struct module *owner)
 {
diff -Nru a/include/net/tc_act/tc_gact.h b/include/net/tc_act/tc_gact.h
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/include/net/tc_act/tc_gact.h	2004-10-18 14:57:23 -07:00
@@ -0,0 +1,17 @@
+#ifndef __NET_TC_GACT_H
+#define __NET_TC_GACT_H
+
+#include <net/pkt_sched.h>
+
+struct tcf_gact
+{
+        tca_gen(gact);
+#ifdef CONFIG_GACT_PROB
+        u16                 ptype;
+        u16                 pval;
+        int                 paction;
+#endif
+                                                                                
+};
+                                                                                
+#endif
diff -Nru a/include/net/tcp.h b/include/net/tcp.h
--- a/include/net/tcp.h	2004-10-18 14:55:55 -07:00
+++ b/include/net/tcp.h	2004-10-18 14:55:55 -07:00
@@ -153,9 +153,6 @@
 #define tcp_lhash_wait	(tcp_hashinfo.__tcp_lhash_wait)
 #define tcp_portalloc_lock (tcp_hashinfo.__tcp_portalloc_lock)
 
-/* SLAB cache for TCP socks */
-extern kmem_cache_t *tcp_sk_cachep;
-
 extern kmem_cache_t *tcp_bucket_cachep;
 extern struct tcp_bind_bucket *tcp_bucket_create(struct tcp_bind_hashbucket *head,
 						 unsigned short snum);
@@ -611,8 +608,8 @@
 extern int sysctl_tcp_bic;
 extern int sysctl_tcp_bic_fast_convergence;
 extern int sysctl_tcp_bic_low_window;
-extern int sysctl_tcp_default_win_scale;
 extern int sysctl_tcp_moderate_rcvbuf;
+extern int sysctl_tcp_tso_win_divisor;
 
 extern atomic_t tcp_memory_allocated;
 extern atomic_t tcp_sockets_allocated;
@@ -948,6 +945,7 @@
 extern int tcp_retransmit_skb(struct sock *, struct sk_buff *);
 extern void tcp_xmit_retransmit_queue(struct sock *);
 extern void tcp_simple_retransmit(struct sock *);
+extern int tcp_trim_head(struct sock *, struct sk_buff *, u32);
 
 extern void tcp_send_probe0(struct sock *);
 extern void tcp_send_partial(struct sock *);
@@ -955,7 +953,6 @@
 extern void tcp_send_fin(struct sock *sk);
 extern void tcp_send_active_reset(struct sock *sk, int priority);
 extern int  tcp_send_synack(struct sock *);
-extern int  tcp_transmit_skb(struct sock *, struct sk_buff *);
 extern void tcp_push_one(struct sock *, unsigned mss_now);
 extern void tcp_send_ack(struct sock *sk);
 extern void tcp_send_delayed_ack(struct sock *sk);
@@ -966,7 +963,8 @@
 
 extern void tcp_delete_keepalive_timer (struct sock *);
 extern void tcp_reset_keepalive_timer (struct sock *, unsigned long);
-extern int tcp_sync_mss(struct sock *sk, u32 pmtu);
+extern unsigned int tcp_sync_mss(struct sock *sk, u32 pmtu);
+extern unsigned int tcp_current_mss(struct sock *sk, int large);
 
 extern const char timer_bug_msg[];
 
@@ -1040,34 +1038,6 @@
 	};
 }
 
-/* Compute the current effective MSS, taking SACKs and IP options,
- * and even PMTU discovery events into account.
- *
- * LARGESEND note: !urg_mode is overkill, only frames up to snd_up
- * cannot be large. However, taking into account rare use of URG, this
- * is not a big flaw.
- */
-
-static __inline__ unsigned int tcp_current_mss(struct sock *sk, int large)
-{
-	struct tcp_opt *tp = tcp_sk(sk);
-	struct dst_entry *dst = __sk_dst_get(sk);
-	int mss_now = large && (sk->sk_route_caps & NETIF_F_TSO) &&
-		      !tp->urg_mode ?
-		tp->mss_cache : tp->mss_cache_std;
-
-	if (dst) {
-		u32 mtu = dst_pmtu(dst);
-		if (mtu != tp->pmtu_cookie ||
-		    tp->ext2_header_len != dst->header_len)
-			mss_now = tcp_sync_mss(sk, mtu);
-	}
-	if (tp->eff_sacks)
-		mss_now -= (TCPOLEN_SACK_BASE_ALIGNED +
-			    (tp->eff_sacks * TCPOLEN_SACK_PERBLOCK));
-	return mss_now;
-}
-
 /* Initialize RCV_MSS value.
  * RCV_MSS is an our guess about MSS used by the peer.
  * We haven't any direct information about the MSS.
@@ -1188,6 +1158,75 @@
 
 #include <net/tcp_ecn.h>
 
+/* Due to TSO, an SKB can be composed of multiple actual
+ * packets.  To keep these tracked properly, we use this.
+ */
+static inline int tcp_skb_pcount(struct sk_buff *skb)
+{
+	return skb_shinfo(skb)->tso_segs;
+}
+
+/* This is valid iff tcp_skb_pcount() > 1. */
+static inline int tcp_skb_mss(struct sk_buff *skb)
+{
+	return skb_shinfo(skb)->tso_size;
+}
+
+static inline void tcp_inc_pcount(tcp_pcount_t *count, struct sk_buff *skb)
+{
+	count->val += tcp_skb_pcount(skb);
+}
+
+static inline void tcp_inc_pcount_explicit(tcp_pcount_t *count, int amt)
+{
+	count->val += amt;
+}
+
+static inline void tcp_dec_pcount_explicit(tcp_pcount_t *count, int amt)
+{
+	count->val -= amt;
+}
+
+static inline void tcp_dec_pcount(tcp_pcount_t *count, struct sk_buff *skb)
+{
+	count->val -= tcp_skb_pcount(skb);
+}
+
+static inline void tcp_dec_pcount_approx(tcp_pcount_t *count,
+					 struct sk_buff *skb)
+{
+	if (count->val) {
+		count->val -= tcp_skb_pcount(skb);
+		if ((int)count->val < 0)
+			count->val = 0;
+	}
+}
+
+static inline __u32 tcp_get_pcount(tcp_pcount_t *count)
+{
+	return count->val;
+}
+
+static inline void tcp_set_pcount(tcp_pcount_t *count, __u32 val)
+{
+	count->val = val;
+}
+
+static inline void tcp_packets_out_inc(struct sock *sk, struct tcp_opt *tp,
+				       struct sk_buff *skb)
+{
+	int orig = tcp_get_pcount(&tp->packets_out);
+
+	tcp_inc_pcount(&tp->packets_out, skb);
+	if (!orig)
+		tcp_reset_xmit_timer(sk, TCP_TIME_RETRANS, tp->rto);
+}
+
+static inline void tcp_packets_out_dec(struct tcp_opt *tp, struct sk_buff *skb)
+{
+	tcp_dec_pcount(&tp->packets_out, skb);
+}
+
 /* This determines how many packets are "in the network" to the best
  * of our knowledge.  In many cases it is conservative, but where
  * detailed information is available from the receiver (via SACK
@@ -1204,9 +1243,18 @@
  */
 static __inline__ unsigned int tcp_packets_in_flight(struct tcp_opt *tp)
 {
-	return tp->packets_out - tp->left_out + tp->retrans_out;
+	return (tcp_get_pcount(&tp->packets_out) -
+		tcp_get_pcount(&tp->left_out) +
+		tcp_get_pcount(&tp->retrans_out));
 }
 
+/*
+ * Which congestion algorithim is in use on the connection.
+ */
+#define tcp_is_vegas(__tp)	((__tp)->adv_cong == TCP_VEGAS)
+#define tcp_is_westwood(__tp)	((__tp)->adv_cong == TCP_WESTWOOD)
+#define tcp_is_bic(__tp)	((__tp)->adv_cong == TCP_BIC)
+
 /* Recalculate snd_ssthresh, we want to set it to:
  *
  * Reno:
@@ -1219,7 +1267,7 @@
  */
 static inline __u32 tcp_recalc_ssthresh(struct tcp_opt *tp)
 {
-	if (sysctl_tcp_bic) {
+	if (tcp_is_bic(tp)) {
 		if (sysctl_tcp_bic_fast_convergence &&
 		    tp->snd_cwnd < tp->bictcp.last_max_cwnd)
 			tp->bictcp.last_max_cwnd
@@ -1238,11 +1286,6 @@
 
 /* Stop taking Vegas samples for now. */
 #define tcp_vegas_disable(__tp)	((__tp)->vegas.doing_vegas_now = 0)
-
-/* Is this TCP connection using Vegas (regardless of whether it is taking
- * Vegas measurements at the current time)?
- */
-#define tcp_is_vegas(__tp)	((__tp)->vegas.do_vegas)
     
 static inline void tcp_vegas_enable(struct tcp_opt *tp)
 {
@@ -1276,7 +1319,7 @@
 /* Should we be taking Vegas samples right now? */
 #define tcp_vegas_enabled(__tp)	((__tp)->vegas.doing_vegas_now)
 
-extern void tcp_vegas_init(struct tcp_opt *tp);
+extern void tcp_ca_init(struct tcp_opt *tp);
 
 static inline void tcp_set_ca_state(struct tcp_opt *tp, u8 ca_state)
 {
@@ -1305,9 +1348,15 @@
 
 static inline void tcp_sync_left_out(struct tcp_opt *tp)
 {
-	if (tp->sack_ok && tp->sacked_out >= tp->packets_out - tp->lost_out)
-		tp->sacked_out = tp->packets_out - tp->lost_out;
-	tp->left_out = tp->sacked_out + tp->lost_out;
+	if (tp->sack_ok &&
+	    (tcp_get_pcount(&tp->sacked_out) >=
+	     tcp_get_pcount(&tp->packets_out) - tcp_get_pcount(&tp->lost_out)))
+		tcp_set_pcount(&tp->sacked_out,
+			       (tcp_get_pcount(&tp->packets_out) -
+				tcp_get_pcount(&tp->lost_out)));
+	tcp_set_pcount(&tp->left_out,
+		       (tcp_get_pcount(&tp->sacked_out) +
+			tcp_get_pcount(&tp->lost_out)));
 }
 
 extern void tcp_cwnd_application_limited(struct sock *sk);
@@ -1316,14 +1365,16 @@
 
 static inline void tcp_cwnd_validate(struct sock *sk, struct tcp_opt *tp)
 {
-	if (tp->packets_out >= tp->snd_cwnd) {
+	__u32 packets_out = tcp_get_pcount(&tp->packets_out);
+
+	if (packets_out >= tp->snd_cwnd) {
 		/* Network is feed fully. */
 		tp->snd_cwnd_used = 0;
 		tp->snd_cwnd_stamp = tcp_time_stamp;
 	} else {
 		/* Network starves. */
-		if (tp->packets_out > tp->snd_cwnd_used)
-			tp->snd_cwnd_used = tp->packets_out;
+		if (tcp_get_pcount(&tp->packets_out) > tp->snd_cwnd_used)
+			tp->snd_cwnd_used = tcp_get_pcount(&tp->packets_out);
 
 		if ((s32)(tcp_time_stamp - tp->snd_cwnd_stamp) >= tp->rto)
 			tcp_cwnd_application_limited(sk);
@@ -1389,16 +1440,25 @@
 		!(TCP_SKB_CB(skb)->flags & TCPCB_FLAG_FIN) &&
 		((nonagle&TCP_NAGLE_CORK) ||
 		 (!nonagle &&
-		  tp->packets_out &&
+		  tcp_get_pcount(&tp->packets_out) &&
 		  tcp_minshall_check(tp))));
 }
 
+extern void tcp_set_skb_tso_segs(struct sk_buff *, unsigned int);
+
 /* This checks if the data bearing packet SKB (usually sk->sk_send_head)
  * should be put on the wire right now.
  */
 static __inline__ int tcp_snd_test(struct tcp_opt *tp, struct sk_buff *skb,
 				   unsigned cur_mss, int nonagle)
 {
+	int pkts = tcp_skb_pcount(skb);
+
+	if (!pkts) {
+		tcp_set_skb_tso_segs(skb, tp->mss_cache_std);
+		pkts = tcp_skb_pcount(skb);
+	}
+
 	/*	RFC 1122 - section 4.2.3.4
 	 *
 	 *	We must queue if
@@ -1425,14 +1485,14 @@
 	 */
 	return (((nonagle&TCP_NAGLE_PUSH) || tp->urg_mode
 		 || !tcp_nagle_check(tp, skb, cur_mss, nonagle)) &&
-		((tcp_packets_in_flight(tp) < tp->snd_cwnd) ||
+		(((tcp_packets_in_flight(tp) + (pkts-1)) < tp->snd_cwnd) ||
 		 (TCP_SKB_CB(skb)->flags & TCPCB_FLAG_FIN)) &&
 		!after(TCP_SKB_CB(skb)->end_seq, tp->snd_una + tp->snd_wnd));
 }
 
 static __inline__ void tcp_check_probe_timer(struct sock *sk, struct tcp_opt *tp)
 {
-	if (!tp->packets_out && !tp->pending)
+	if (!tcp_get_pcount(&tp->packets_out) && !tp->pending)
 		tcp_reset_xmit_timer(sk, TCP_TIME_PROBE0, tp->rto);
 }
 
@@ -1690,68 +1750,10 @@
 		*ptr++ = htonl((TCPOPT_NOP << 24) | (TCPOPT_WINDOW << 16) | (TCPOLEN_WINDOW << 8) | (wscale));
 }
 
-/* Determine a window scaling and initial window to offer.
- * Based on the assumption that the given amount of space
- * will be offered. Store the results in the tp structure.
- * NOTE: for smooth operation initial space offering should
- * be a multiple of mss if possible. We assume here that mss >= 1.
- * This MUST be enforced by all callers.
- */
-static inline void tcp_select_initial_window(int __space, __u32 mss,
-	__u32 *rcv_wnd,
-	__u32 *window_clamp,
-	int wscale_ok,
-	__u8 *rcv_wscale)
-{
-	unsigned int space = (__space < 0 ? 0 : __space);
-
-	/* If no clamp set the clamp to the max possible scaled window */
-	if (*window_clamp == 0)
-		(*window_clamp) = (65535 << 14);
-	space = min(*window_clamp, space);
-
-	/* Quantize space offering to a multiple of mss if possible. */
-	if (space > mss)
-		space = (space / mss) * mss;
-
-	/* NOTE: offering an initial window larger than 32767
-	 * will break some buggy TCP stacks. We try to be nice.
-	 * If we are not window scaling, then this truncates
-	 * our initial window offering to 32k. There should also
-	 * be a sysctl option to stop being nice.
-	 */
-	(*rcv_wnd) = min(space, MAX_TCP_WINDOW);
-	(*rcv_wscale) = 0;
-	if (wscale_ok) {
-		/* See RFC1323 for an explanation of the limit to 14 */
-		while (space > 65535 && (*rcv_wscale) < 14) {
-			space >>= 1;
-			(*rcv_wscale)++;
-		}
-		if (*rcv_wscale && sysctl_tcp_app_win && space>=mss &&
-		    space - max((space>>sysctl_tcp_app_win), mss>>*rcv_wscale) < 65536/2)
-			(*rcv_wscale)--;
-
-		*rcv_wscale = max((__u8)sysctl_tcp_default_win_scale,
-				  *rcv_wscale);
-	}
-
-	/* Set initial window to value enough for senders,
-	 * following RFC1414. Senders, not following this RFC,
-	 * will be satisfied with 2.
-	 */
-	if (mss > (1<<*rcv_wscale)) {
-		int init_cwnd = 4;
-		if (mss > 1460*3)
-			init_cwnd = 2;
-		else if (mss > 1460)
-			init_cwnd = 3;
-		if (*rcv_wnd > init_cwnd*mss)
-			*rcv_wnd = init_cwnd*mss;
-	}
-	/* Set the clamp no higher than max representable value */
-	(*window_clamp) = min(65535U << (*rcv_wscale), *window_clamp);
-}
+/* Determine a window scaling and initial window to offer. */
+extern void tcp_select_initial_window(int __space, __u32 mss,
+				      __u32 *rcv_wnd, __u32 *window_clamp,
+				      int wscale_ok, __u8 *rcv_wscale);
 
 static inline int tcp_win_from_space(int space)
 {
@@ -1761,13 +1763,13 @@
 }
 
 /* Note: caller must be prepared to deal with negative returns */ 
-static inline int tcp_space(struct sock *sk)
+static inline int tcp_space(const struct sock *sk)
 {
 	return tcp_win_from_space(sk->sk_rcvbuf -
 				  atomic_read(&sk->sk_rmem_alloc));
 } 
 
-static inline int tcp_full_space( struct sock *sk)
+static inline int tcp_full_space(const struct sock *sk)
 {
 	return tcp_win_from_space(sk->sk_rcvbuf); 
 }
@@ -2001,7 +2003,7 @@
 
 static inline void tcp_westwood_update_rtt(struct tcp_opt *tp, __u32 rtt_seq)
 {
-        if (sysctl_tcp_westwood)
+        if (tcp_is_westwood(tp))
                 tp->westwood.rtt = rtt_seq;
 }
 
@@ -2010,33 +2012,33 @@
 
 static inline void tcp_westwood_fast_bw(struct sock *sk, struct sk_buff *skb)
 {
-        if (sysctl_tcp_westwood)
+        if (tcp_is_westwood(tcp_sk(sk)))
                 __tcp_westwood_fast_bw(sk, skb);
 }
 
 static inline void tcp_westwood_slow_bw(struct sock *sk, struct sk_buff *skb)
 {
-        if (sysctl_tcp_westwood)
+        if (tcp_is_westwood(tcp_sk(sk)))
                 __tcp_westwood_slow_bw(sk, skb);
 }
 
 static inline __u32 __tcp_westwood_bw_rttmin(const struct tcp_opt *tp)
 {
         return max((tp->westwood.bw_est) * (tp->westwood.rtt_min) /
-		   (__u32) (tp->mss_cache),
+		   (__u32) (tp->mss_cache_std),
 		   2U);
 }
 
 static inline __u32 tcp_westwood_bw_rttmin(const struct tcp_opt *tp)
 {
-	return sysctl_tcp_westwood ? __tcp_westwood_bw_rttmin(tp) : 0;
+	return tcp_is_westwood(tp) ? __tcp_westwood_bw_rttmin(tp) : 0;
 }
 
 static inline int tcp_westwood_ssthresh(struct tcp_opt *tp)
 {
 	__u32 ssthresh = 0;
 
-	if (sysctl_tcp_westwood) {
+	if (tcp_is_westwood(tp)) {
 		ssthresh = __tcp_westwood_bw_rttmin(tp);
 		if (ssthresh)
 			tp->snd_ssthresh = ssthresh;  
@@ -2049,7 +2051,7 @@
 {
 	__u32 cwnd = 0;
 
-	if (sysctl_tcp_westwood) {
+	if (tcp_is_westwood(tp)) {
 		cwnd = __tcp_westwood_bw_rttmin(tp);
 		if (cwnd)
 			tp->snd_cwnd = cwnd;
diff -Nru a/include/net/tcp_ecn.h b/include/net/tcp_ecn.h
--- a/include/net/tcp_ecn.h	2004-10-18 14:56:48 -07:00
+++ b/include/net/tcp_ecn.h	2004-10-18 14:56:48 -07:00
@@ -90,7 +90,7 @@
 		/* Funny extension: if ECT is not set on a segment,
 		 * it is surely retransmit. It is not in ECN RFC,
 		 * but Linux follows this rule. */
-		else if (!INET_ECN_is_capable((TCP_SKB_CB(skb)->flags)))
+		else if (INET_ECN_is_not_ect((TCP_SKB_CB(skb)->flags)))
 			tcp_enter_quickack_mode(tp);
 	}
 }
diff -Nru a/include/net/xfrm.h b/include/net/xfrm.h
--- a/include/net/xfrm.h	2004-10-18 14:56:49 -07:00
+++ b/include/net/xfrm.h	2004-10-18 14:56:49 -07:00
@@ -216,7 +216,7 @@
 	void			(*destructor)(struct xfrm_state *);
 	int			(*input)(struct xfrm_state *, struct xfrm_decap_state *, struct sk_buff *skb);
 	int			(*post_input)(struct xfrm_state *, struct xfrm_decap_state *, struct sk_buff *skb);
-	int			(*output)(struct sk_buff **pskb);
+	int			(*output)(struct sk_buff *pskb);
 	/* Estimate maximal size of result of transformation of a dgram */
 	u32			(*get_max_size)(struct xfrm_state *, int size);
 };
@@ -304,47 +304,6 @@
 extern int xfrm_unregister_km(struct xfrm_mgr *km);
 
 
-#define XFRM_FLOWCACHE_HASH_SIZE	1024
-
-static inline u32 __flow_hash4(struct flowi *fl)
-{
-	u32 hash = fl->fl4_src ^ fl->fl_ip_sport;
-
-	hash = ((hash & 0xF0F0F0F0) >> 4) | ((hash & 0x0F0F0F0F) << 4);
-
-	hash ^= fl->fl4_dst ^ fl->fl_ip_dport;
-	hash ^= (hash >> 10);
-	hash ^= (hash >> 20);
-	return hash & (XFRM_FLOWCACHE_HASH_SIZE-1);
-}
-
-static inline u32 __flow_hash6(struct flowi *fl)
-{
-	u32 hash = fl->fl6_src.s6_addr32[2] ^
-		   fl->fl6_src.s6_addr32[3] ^ 
-		   fl->fl_ip_sport;
-
-	hash = ((hash & 0xF0F0F0F0) >> 4) | ((hash & 0x0F0F0F0F) << 4);
-
-	hash ^= fl->fl6_dst.s6_addr32[2] ^
-		fl->fl6_dst.s6_addr32[3] ^ 
-		fl->fl_ip_dport;
-	hash ^= (hash >> 10);
-	hash ^= (hash >> 20);
-	return hash & (XFRM_FLOWCACHE_HASH_SIZE-1);
-}
-
-static inline u32 flow_hash(struct flowi *fl, unsigned short family)
-{
-	switch (family) {
-	case AF_INET:
-		return __flow_hash4(fl);
-	case AF_INET6:
-		return __flow_hash6(fl);
-	}
-	return 0;	/*XXX*/
-}
-
 extern struct xfrm_policy *xfrm_policy_list[XFRM_POLICY_MAX*2];
 
 static inline void xfrm_pol_hold(struct xfrm_policy *policy)
@@ -462,13 +421,53 @@
 	return 1;
 }
 
+static __inline__
+u16 xfrm_flowi_sport(struct flowi *fl)
+{
+	u16 port;
+	switch(fl->proto) {
+	case IPPROTO_TCP:
+	case IPPROTO_UDP:
+	case IPPROTO_SCTP:
+		port = fl->fl_ip_sport;
+		break;
+	case IPPROTO_ICMP:
+	case IPPROTO_ICMPV6:
+		port = htons(fl->fl_icmp_type);
+		break;
+	default:
+		port = 0;	/*XXX*/
+	}
+	return port;
+}
+
+static __inline__
+u16 xfrm_flowi_dport(struct flowi *fl)
+{
+	u16 port;
+	switch(fl->proto) {
+	case IPPROTO_TCP:
+	case IPPROTO_UDP:
+	case IPPROTO_SCTP:
+		port = fl->fl_ip_dport;
+		break;
+	case IPPROTO_ICMP:
+	case IPPROTO_ICMPV6:
+		port = htons(fl->fl_icmp_code);
+		break;
+	default:
+		port = 0;	/*XXX*/
+	}
+	return port;
+}
+
 static inline int
 __xfrm4_selector_match(struct xfrm_selector *sel, struct flowi *fl)
 {
 	return  addr_match(&fl->fl4_dst, &sel->daddr, sel->prefixlen_d) &&
 		addr_match(&fl->fl4_src, &sel->saddr, sel->prefixlen_s) &&
-		!((fl->fl_ip_dport^sel->dport)&sel->dport_mask) &&
-		!((fl->fl_ip_sport^sel->sport)&sel->sport_mask) &&
+		!((xfrm_flowi_dport(fl) ^ sel->dport) & sel->dport_mask) &&
+		!((xfrm_flowi_sport(fl) ^ sel->sport) & sel->sport_mask) &&
 		(fl->proto == sel->proto || !sel->proto) &&
 		(fl->oif == sel->ifindex || !sel->ifindex);
 }
@@ -478,8 +477,8 @@
 {
 	return  addr_match(&fl->fl6_dst, &sel->daddr, sel->prefixlen_d) &&
 		addr_match(&fl->fl6_src, &sel->saddr, sel->prefixlen_s) &&
-		!((fl->fl_ip_dport^sel->dport)&sel->dport_mask) &&
-		!((fl->fl_ip_sport^sel->sport)&sel->sport_mask) &&
+		!((xfrm_flowi_dport(fl) ^ sel->dport) & sel->dport_mask) &&
+		!((xfrm_flowi_sport(fl) ^ sel->sport) & sel->sport_mask) &&
 		(fl->proto == sel->proto || !sel->proto) &&
 		(fl->oif == sel->ifindex || !sel->ifindex);
 }
@@ -795,8 +794,6 @@
 extern void xfrm4_state_fini(void);
 extern void xfrm6_state_init(void);
 extern void xfrm6_state_fini(void);
-extern void xfrm6_tunnel_init(void);
-extern void xfrm6_tunnel_fini(void);
 
 extern int xfrm_state_walk(u8 proto, int (*func)(struct xfrm_state *, int, void*), void *);
 extern struct xfrm_state *xfrm_state_alloc(void);
@@ -821,6 +818,7 @@
 extern int xfrm4_output(struct sk_buff **pskb);
 extern int xfrm4_tunnel_register(struct xfrm_tunnel *handler);
 extern int xfrm4_tunnel_deregister(struct xfrm_tunnel *handler);
+extern int xfrm6_rcv_spi(struct sk_buff **pskb, unsigned int *nhoffp, u32 spi);
 extern int xfrm6_rcv(struct sk_buff **pskb, unsigned int *nhoffp);
 extern int xfrm6_tunnel_register(struct xfrm6_tunnel *handler);
 extern int xfrm6_tunnel_deregister(struct xfrm6_tunnel *handler);
@@ -852,8 +850,6 @@
 #endif
 
 void xfrm_policy_init(void);
-void xfrm4_policy_init(void);
-void xfrm6_policy_init(void);
 struct xfrm_policy *xfrm_policy_alloc(int gfp);
 extern int xfrm_policy_walk(int (*func)(struct xfrm_policy *, int, int, void*), void *);
 int xfrm_policy_insert(int dir, struct xfrm_policy *policy, int excl);
@@ -899,5 +895,18 @@
 
 extern void skb_icv_walk(const struct sk_buff *skb, struct crypto_tfm *tfm,
 			 int offset, int len, icv_update_fn_t icv_update);
+
+static inline int xfrm_addr_cmp(xfrm_address_t *a, xfrm_address_t *b,
+				int family)
+{
+	switch (family) {
+	default:
+	case AF_INET:
+		return a->a4 - b->a4;
+	case AF_INET6:
+		return ipv6_addr_cmp((struct in6_addr *)a,
+				     (struct in6_addr *)b);
+	}
+}
 
 #endif	/* _NET_XFRM_H */
diff -Nru a/include/pcmcia/ss.h b/include/pcmcia/ss.h
--- a/include/pcmcia/ss.h	2004-10-18 14:57:04 -07:00
+++ b/include/pcmcia/ss.h	2004-10-18 14:57:04 -07:00
@@ -103,7 +103,7 @@
     u_char	map;
     u_char	flags;
     u_short	speed;
-    u_long	sys_start, sys_stop;
+    u_long	static_start;
     u_int	card_start;
     struct resource *res;
 } pccard_mem_map;
@@ -176,7 +176,7 @@
 	u_short				lock_count;
 	client_handle_t			clients;
 	pccard_mem_map			cis_mem;
-	u_char				*cis_virt;
+	void __iomem 			*cis_virt;
 	struct config_t			*config;
 	struct {
 		u_int			AssignedIRQ;
@@ -227,7 +227,7 @@
 	/* cardbus (32-bit) */
 #ifdef CONFIG_CARDBUS
 	struct resource *		cb_cis_res;
-	u_char				*cb_cis_virt;
+	void __iomem			*cb_cis_virt;
 #endif
 
 	/* socket device */
diff -Nru a/include/rxrpc/call.h b/include/rxrpc/call.h
--- a/include/rxrpc/call.h	2004-10-18 14:55:55 -07:00
+++ b/include/rxrpc/call.h	2004-10-18 14:55:55 -07:00
@@ -67,8 +67,8 @@
 	wait_queue_head_t	waitq;		/* wait queue for events to happen */
 	struct list_head	link;		/* general internal list link */
 	struct list_head	call_link;	/* master call list link */
-	uint32_t		chan_ix;	/* connection channel index (net order) */
-	uint32_t		call_id;	/* call ID on connection (net order) */
+	__be32			chan_ix;	/* connection channel index  */
+	__be32			call_id;	/* call ID on connection  */
 	unsigned long		cjif;		/* jiffies at call creation */
 	unsigned long		flags;		/* control flags */
 #define RXRPC_CALL_ACKS_TIMO	0x00000001	/* ACKS timeout reached */
@@ -97,7 +97,7 @@
 	rxrpc_seq_t		ackr_win_bot;	/* bottom of ACK window */
 	rxrpc_seq_t		ackr_win_top;	/* top of ACK window */
 	rxrpc_seq_t		ackr_high_seq;	/* highest seqno yet received */
-	rxrpc_seq_t		ackr_prev_seq;	/* previous seqno received */
+	rxrpc_seq_net_t		ackr_prev_seq;	/* previous seqno received */
 	unsigned		ackr_pend_cnt;	/* number of pending ACKs */
 	struct timer_list	ackr_dfr_timo;	/* timeout on deferred ACK */
 	char			ackr_dfr_perm;	/* request for deferred ACKs permitted */
diff -Nru a/include/rxrpc/connection.h b/include/rxrpc/connection.h
--- a/include/rxrpc/connection.h	2004-10-18 14:56:49 -07:00
+++ b/include/rxrpc/connection.h	2004-10-18 14:56:49 -07:00
@@ -45,18 +45,18 @@
 	rxrpc_serial_t		serial_counter;	/* packet serial number counter */
 
 	/* the following should all be in net order */
-	uint32_t		in_epoch;	/* peer's epoch */
-	uint32_t		out_epoch;	/* my epoch */
-	uint32_t		conn_id;	/* connection ID, appropriately shifted */
-	uint16_t		service_id;	/* service ID */
+	__be32			in_epoch;	/* peer's epoch */
+	__be32			out_epoch;	/* my epoch */
+	__be32			conn_id;	/* connection ID, appropriately shifted */
+	__be16			service_id;	/* service ID */
 	uint8_t			security_ix;	/* security ID */
 	uint8_t			in_clientflag;	/* RXRPC_CLIENT_INITIATED if we are server */
 	uint8_t			out_clientflag;	/* RXRPC_CLIENT_INITIATED if we are client */
 };
 
 extern int rxrpc_create_connection(struct rxrpc_transport *trans,
-				   uint16_t port,
-				   uint32_t addr,
+				   __be16 port,
+				   __be32 addr,
 				   uint16_t service_id,
 				   void *security,
 				   struct rxrpc_connection **_conn);
diff -Nru a/include/rxrpc/packet.h b/include/rxrpc/packet.h
--- a/include/rxrpc/packet.h	2004-10-18 14:56:27 -07:00
+++ b/include/rxrpc/packet.h	2004-10-18 14:56:27 -07:00
@@ -27,19 +27,19 @@
  */
 struct rxrpc_header
 {
-	uint32_t	epoch;		/* client boot timestamp */
+	__be32		epoch;		/* client boot timestamp */
 
-	uint32_t	cid;		/* connection and channel ID */
+	__be32		cid;		/* connection and channel ID */
 #define RXRPC_MAXCALLS		4			/* max active calls per conn */
 #define RXRPC_CHANNELMASK	(RXRPC_MAXCALLS-1)	/* mask for channel ID */
 #define RXRPC_CIDMASK		(~RXRPC_CHANNELMASK)	/* mask for connection ID */
 #define RXRPC_CIDSHIFT		2			/* shift for connection ID */
 
-	uint32_t	callNumber;	/* call ID (0 for connection-level packets) */
+	__be32		callNumber;	/* call ID (0 for connection-level packets) */
 #define RXRPC_PROCESS_MAXCALLS	(1<<2)	/* maximum number of active calls per conn (power of 2) */
 
-	uint32_t	seq;		/* sequence number of pkt in call stream */
-	uint32_t	serial;		/* serial number of pkt sent to network */
+	__be32		seq;		/* sequence number of pkt in call stream */
+	__be32		serial;		/* serial number of pkt sent to network */
 
 	uint8_t		type;		/* packet type */
 #define RXRPC_PACKET_TYPE_DATA		1	/* data */
@@ -62,8 +62,8 @@
 
 	uint8_t		userStatus;	/* app-layer defined status */
 	uint8_t		securityIndex;	/* security protocol ID */
-	uint16_t	_rsvd;		/* reserved (used by kerberos security as cksum) */
-	uint16_t	serviceId;	/* service ID */
+	__be16		_rsvd;		/* reserved (used by kerberos security as cksum) */
+	__be16		serviceId;	/* service ID */
 
 } __attribute__((packed));
 
@@ -85,7 +85,7 @@
 {
 	uint8_t		flags;		/* packet flags (as per rxrpc_header) */
 	uint8_t		pad;
-	uint16_t	_rsvd;		/* reserved (used by kerberos security as cksum) */
+	__be16		_rsvd;		/* reserved (used by kerberos security as cksum) */
 };
 
 #define RXRPC_JUMBO_DATALEN	1412	/* non-terminal jumbo packet data length */
@@ -97,12 +97,12 @@
  */
 struct rxrpc_ackpacket
 {
-	uint16_t	bufferSpace;	/* number of packet buffers available */
-	uint16_t	maxSkew;	/* diff between serno being ACK'd and highest serial no
+	__be16		bufferSpace;	/* number of packet buffers available */
+	__be16		maxSkew;	/* diff between serno being ACK'd and highest serial no
 					 * received */
-	uint32_t	firstPacket;	/* sequence no of first ACK'd packet in attached list */
-	uint32_t	previousPacket;	/* sequence no of previous packet received */
-	uint32_t	serial;		/* serial no of packet that prompted this ACK */
+	__be32		firstPacket;	/* sequence no of first ACK'd packet in attached list */
+	__be32		previousPacket;	/* sequence no of previous packet received */
+	__be32		serial;		/* serial no of packet that prompted this ACK */
 
 	uint8_t		reason;		/* reason for ACK */
 #define RXRPC_ACK_REQUESTED		1	/* ACK was requested on packet */
diff -Nru a/include/rxrpc/peer.h b/include/rxrpc/peer.h
--- a/include/rxrpc/peer.h	2004-10-18 14:56:48 -07:00
+++ b/include/rxrpc/peer.h	2004-10-18 14:56:48 -07:00
@@ -67,7 +67,7 @@
 
 
 extern int rxrpc_peer_lookup(struct rxrpc_transport *trans,
-			     u32 addr,
+			     __be32 addr,
 			     struct rxrpc_peer **_peer);
 
 static inline void rxrpc_get_peer(struct rxrpc_peer *peer)
diff -Nru a/include/rxrpc/rxrpc.h b/include/rxrpc/rxrpc.h
--- a/include/rxrpc/rxrpc.h	2004-10-18 14:56:50 -07:00
+++ b/include/rxrpc/rxrpc.h	2004-10-18 14:56:50 -07:00
@@ -14,12 +14,19 @@
 
 #ifdef __KERNEL__
 
-extern uint32_t rxrpc_epoch;
+extern __be32 rxrpc_epoch;
 
+#ifdef CONFIG_SYSCTL
 extern int rxrpc_ktrace;
 extern int rxrpc_kdebug;
 extern int rxrpc_kproto;
 extern int rxrpc_knet;
+#else
+#define rxrpc_ktrace	0
+#define rxrpc_kdebug	0
+#define rxrpc_kproto	0
+#define rxrpc_knet	0
+#endif
 
 extern int rxrpc_sysctl_init(void);
 extern void rxrpc_sysctl_cleanup(void);
diff -Nru a/include/rxrpc/transport.h b/include/rxrpc/transport.h
--- a/include/rxrpc/transport.h	2004-10-18 14:57:05 -07:00
+++ b/include/rxrpc/transport.h	2004-10-18 14:57:05 -07:00
@@ -78,8 +78,6 @@
 	volatile char		error_rcvd;	/* T if received ICMP error outstanding */
 };
 
-extern struct list_head rxrpc_transports;
-
 extern int rxrpc_create_transport(unsigned short port,
 				  struct rxrpc_transport **_trans);
 
diff -Nru a/include/rxrpc/types.h b/include/rxrpc/types.h
--- a/include/rxrpc/types.h	2004-10-18 14:56:28 -07:00
+++ b/include/rxrpc/types.h	2004-10-18 14:56:28 -07:00
@@ -21,6 +21,8 @@
 
 typedef uint32_t	rxrpc_seq_t;	/* Rx message sequence number */
 typedef uint32_t	rxrpc_serial_t;	/* Rx message serial number */
+typedef __be32	rxrpc_seq_net_t; /* on-the-wire Rx message sequence number */
+typedef __be32	rxrpc_serial_net_t; /* on-the-wire Rx message serial number */
 
 struct rxrpc_call;
 struct rxrpc_connection;
diff -Nru a/include/scsi/scsi.h b/include/scsi/scsi.h
--- a/include/scsi/scsi.h	2004-10-18 14:57:04 -07:00
+++ b/include/scsi/scsi.h	2004-10-18 14:57:04 -07:00
@@ -108,6 +108,7 @@
 #define WRITE_LONG_2          0xea
 #define READ_16               0x88
 #define WRITE_16              0x8a
+#define VERIFY_16	      0x8f
 #define SERVICE_ACTION_IN     0x9e
 /* values for service action in */
 #define	SAI_READ_CAPACITY_16  0x10
@@ -353,14 +354,19 @@
 		     ((lun) & 0x07))
 
 /*
- *  SCSI command sets
+ *  struct scsi_device::scsi_level values. For SCSI devices other than those
+ *  prior to SCSI-2 (i.e. over 12 years old) this value is (resp[2] + 1)
+ *  where "resp" is a byte array of the response to an INQUIRY. The scsi_level
+ *  variable is visible to the user via sysfs.
  */
 
 #define SCSI_UNKNOWN    0
 #define SCSI_1          1
 #define SCSI_1_CCS      2
 #define SCSI_2          3
-#define SCSI_3          4
+#define SCSI_3          4        /* SPC */
+#define SCSI_SPC_2      5
+#define SCSI_SPC_3      6
 
 /*
  * INQ PERIPHERAL QUALIFIERS
diff -Nru a/include/scsi/scsi_device.h b/include/scsi/scsi_device.h
--- a/include/scsi/scsi_device.h	2004-10-18 14:55:54 -07:00
+++ b/include/scsi/scsi_device.h	2004-10-18 14:55:54 -07:00
@@ -129,8 +129,10 @@
 #define transport_class_to_sdev(class_dev) \
 	container_of(class_dev, struct scsi_device, transport_classdev)
 
-extern struct scsi_device *scsi_add_device(struct Scsi_Host *,
-		uint, uint, uint);
+extern struct scsi_device *__scsi_add_device(struct Scsi_Host *,
+		uint, uint, uint, void *hostdata);
+#define scsi_add_device(host, channel, target, lun) \
+	__scsi_add_device(host, channel, target, lun, NULL)
 extern void scsi_remove_device(struct scsi_device *);
 extern int scsi_device_cancel(struct scsi_device *, int);
 
@@ -183,13 +185,47 @@
 extern int scsi_mode_sense(struct scsi_device *sdev, int dbd, int modepage,
 			   unsigned char *buffer, int len, int timeout,
 			   int retries, struct scsi_mode_data *data);
+extern int scsi_test_unit_ready(struct scsi_device *sdev, int timeout,
+				int retries);
 extern int scsi_device_set_state(struct scsi_device *sdev,
 				 enum scsi_device_state state);
 extern int scsi_device_quiesce(struct scsi_device *sdev);
 extern void scsi_device_resume(struct scsi_device *sdev);
 extern const char *scsi_device_state_name(enum scsi_device_state);
-static int inline scsi_device_online(struct scsi_device *sdev)
+static inline int scsi_device_online(struct scsi_device *sdev)
 {
 	return sdev->sdev_state != SDEV_OFFLINE;
+}
+
+/* accessor functions for the SCSI parameters */
+static inline int scsi_device_sync(struct scsi_device *sdev)
+{
+	return sdev->sdtr;
+}
+static inline int scsi_device_wide(struct scsi_device *sdev)
+{
+	return sdev->wdtr;
+}
+static inline int scsi_device_dt(struct scsi_device *sdev)
+{
+	return sdev->ppr;
+}
+static inline int scsi_device_dt_only(struct scsi_device *sdev)
+{
+	if (sdev->inquiry_len < 57)
+		return 0;
+	return (sdev->inquiry[56] & 0x0c) == 0x04;
+}
+static inline int scsi_device_ius(struct scsi_device *sdev)
+{
+	if (sdev->inquiry_len < 57)
+		return 0;
+	return sdev->inquiry[56] & 0x01;
+}
+static inline int scsi_device_qas(struct scsi_device *sdev)
+{
+	if (sdev->inquiry_len < 57)
+		return 0;
+	return sdev->inquiry[56] & 0x02;
 }
 #endif /* _SCSI_SCSI_DEVICE_H */
diff -Nru a/include/scsi/scsi_driver.h b/include/scsi/scsi_driver.h
--- a/include/scsi/scsi_driver.h	2004-10-18 14:56:48 -07:00
+++ b/include/scsi/scsi_driver.h	2004-10-18 14:56:48 -07:00
@@ -13,6 +13,7 @@
 
 	int (*init_command)(struct scsi_cmnd *);
 	void (*rescan)(struct device *);
+	int (*issue_flush)(struct device *, sector_t *);
 };
 #define to_scsi_driver(drv) \
 	container_of((drv), struct scsi_driver, gendrv)
diff -Nru a/include/scsi/scsi_eh.h b/include/scsi/scsi_eh.h
--- a/include/scsi/scsi_eh.h	2004-10-18 14:57:04 -07:00
+++ b/include/scsi/scsi_eh.h	2004-10-18 14:57:04 -07:00
@@ -11,7 +11,6 @@
 extern void scsi_report_bus_reset(struct Scsi_Host *, int);
 extern void scsi_report_device_reset(struct Scsi_Host *, int, int);
 extern int scsi_block_when_processing_errors(struct scsi_device *);
-extern void scsi_sleep(int);
 
 /*
  * Reset request from external source
diff -Nru a/include/sound/ac97_codec.h b/include/sound/ac97_codec.h
--- a/include/sound/ac97_codec.h	2004-10-18 14:56:32 -07:00
+++ b/include/sound/ac97_codec.h	2004-10-18 14:56:32 -07:00
@@ -364,11 +364,21 @@
 #define AC97_RATES_MIC_ADC	4
 #define AC97_RATES_SPDIF	5
 
+/* shared controllers */
+enum {
+	AC97_SHARED_TYPE_NONE,
+	AC97_SHARED_TYPE_ICH,
+	AC97_SHARED_TYPE_ATIIXP,
+	AC97_SHARED_TYPES
+};
+
 /*
  *
  */
 
 typedef struct _snd_ac97_bus ac97_bus_t;
+typedef struct _snd_ac97_bus_ops ac97_bus_ops_t;
+typedef struct _snd_ac97_template ac97_template_t;
 typedef struct _snd_ac97 ac97_t;
 
 enum ac97_pcm_cfg {
@@ -405,29 +415,45 @@
 	int (*build_post_spdif) (ac97_t *ac97);
 };
 
-struct _snd_ac97_bus {
-	/* -- lowlevel (hardware) driver specific -- */
+struct _snd_ac97_bus_ops {
 	void (*reset) (ac97_t *ac97);
 	void (*write) (ac97_t *ac97, unsigned short reg, unsigned short val);
 	unsigned short (*read) (ac97_t *ac97, unsigned short reg);
 	void (*wait) (ac97_t *ac97);
 	void (*init) (ac97_t *ac97);
+};
+
+struct _snd_ac97_bus {
+	/* -- lowlevel (hardware) driver specific -- */
+	ac97_bus_ops_t *ops;
 	void *private_data;
 	void (*private_free) (ac97_bus_t *bus);
 	/* --- */
 	snd_card_t *card;
 	unsigned short num;	/* bus number */
-	unsigned short vra: 1,	/* bridge supports VRA */
+	unsigned short no_vra: 1, /* bridge doesn't support VRA */
 		       isdin: 1;/* independent SDIN */
 	unsigned int clock;	/* AC'97 base clock (usually 48000Hz) */
 	spinlock_t bus_lock;	/* used mainly for slot allocation */
 	unsigned short used_slots[2][4]; /* actually used PCM slots */
 	unsigned short pcms_count; /* count of PCMs */
 	struct ac97_pcm *pcms;
+	unsigned int shared_type;	/* type of shared controller betwen audio and modem */
 	ac97_t *codec[4];
 	snd_info_entry_t *proc;
 };
 
+struct _snd_ac97_template {
+	void *private_data;
+	void (*private_free) (ac97_t *ac97);
+	struct pci_dev *pci;	/* assigned PCI device - used for quirks */
+	unsigned short num;	/* number of codec: 0 = primary, 1 = secondary */
+	unsigned short addr;	/* physical address of codec [0-3] */
+	unsigned int scaps;	/* driver capabilities */
+	unsigned int limited_regs; /* allow limited registers only */
+	DECLARE_BITMAP(reg_accessed, 0x80); /* bit flags */
+};
+
 struct _snd_ac97 {
 	/* -- lowlevel (hardware) driver specific -- */
 	struct snd_ac97_build_ops * build_ops;
@@ -441,6 +467,7 @@
 	unsigned short subsystem_vendor;
 	unsigned short subsystem_device;
 	spinlock_t reg_lock;
+	struct semaphore mutex;	/* mutex for AD18xx multi-codecs and paging (2.3) */
 	unsigned short num;	/* number of codec: 0 = primary, 1 = secondary */
 	unsigned short addr;	/* physical address of codec [0-3] */
 	unsigned int id;	/* identification of codec */
@@ -461,7 +488,6 @@
 			unsigned short id[3];		// codec IDs (lower 16-bit word)
 			unsigned short pcmreg[3];	// PCM registers
 			unsigned short codec_cfg[3];	// CODEC_CFG bits
-			struct semaphore mutex;
 		} ad18xx;
 		unsigned int dev_flags;		/* device specific */
 	} spec;
@@ -484,10 +510,14 @@
 {
 	return (ac97->ext_id & AC97_EI_AMAP) != 0;
 }
+static inline int ac97_can_spdif(ac97_t * ac97)
+{
+	return (ac97->ext_id & AC97_EI_SPDIF) != 0;
+}
 
 /* functions */
-int snd_ac97_bus(snd_card_t * card, ac97_bus_t * _bus, ac97_bus_t ** rbus); /* create new AC97 bus */
-int snd_ac97_mixer(ac97_bus_t * bus, ac97_t * _ac97, ac97_t ** rac97);	/* create mixer controls */
+int snd_ac97_bus(snd_card_t *card, int num, ac97_bus_ops_t *ops, void *private_data, ac97_bus_t **rbus); /* create new AC97 bus */
+int snd_ac97_mixer(ac97_bus_t *bus, ac97_template_t *template, ac97_t **rac97);	/* create mixer controls */
 
 void snd_ac97_write(ac97_t *ac97, unsigned short reg, unsigned short value);
 unsigned short snd_ac97_read(ac97_t *ac97, unsigned short reg);
diff -Nru a/include/sound/asequencer.h b/include/sound/asequencer.h
--- a/include/sound/asequencer.h	2004-10-18 14:56:33 -07:00
+++ b/include/sound/asequencer.h	2004-10-18 14:56:33 -07:00
@@ -177,7 +177,7 @@
 
 /* 150-151: kernel events with quote - DO NOT use in user clients */
 #define SNDRV_SEQ_EVENT_KERNEL_ERROR	150
-#define SNDRV_SEQ_EVENT_KERNEL_QUOTE	151
+#define SNDRV_SEQ_EVENT_KERNEL_QUOTE	151	/* obsolete */
 
 /* 152-191: reserved */
 
@@ -640,7 +640,7 @@
 	 *  etc. if the queue is locked for other clients
 	 */
 	int owner;		/* client id for owner of the queue */
-	int locked:1;		/* timing queue locked for other queues */
+	unsigned locked:1;	/* timing queue locked for other queues */
 	char name[64];		/* name of this queue */
 	unsigned int flags;	/* flags */
 	char reserved[60];	/* for future use */
diff -Nru a/include/sound/asound.h b/include/sound/asound.h
--- a/include/sound/asound.h	2004-10-18 14:56:33 -07:00
+++ b/include/sound/asound.h	2004-10-18 14:56:33 -07:00
@@ -275,7 +275,6 @@
 #define SNDRV_PCM_INFO_HALF_DUPLEX	0x00100000	/* only half duplex */
 #define SNDRV_PCM_INFO_JOINT_DUPLEX	0x00200000	/* playback and capture stream are somewhat correlated */
 #define SNDRV_PCM_INFO_SYNC_START	0x00400000	/* pcm support some kind of sync go */
-#define SNDRV_PCM_INFO_NONATOMIC_OPS	0x00800000	/* non-atomic prepare callback */
 
 enum sndrv_pcm_state {
 	SNDRV_PCM_STATE_OPEN = 0,	/* stream is open */
diff -Nru a/include/sound/control.h b/include/sound/control.h
--- a/include/sound/control.h	2004-10-18 14:56:32 -07:00
+++ b/include/sound/control.h	2004-10-18 14:56:32 -07:00
@@ -35,8 +35,7 @@
 typedef enum sndrv_ctl_event_type snd_ctl_event_type_t;
 typedef struct sndrv_ctl_event snd_ctl_event_t;
 
-#define _snd_kcontrol_chip(kcontrol) ((kcontrol)->private_data)
-#define snd_kcontrol_chip(kcontrol) snd_magic_cast1(chip_t, _snd_kcontrol_chip(kcontrol), return -ENXIO)
+#define snd_kcontrol_chip(kcontrol) ((kcontrol)->private_data)
 
 typedef int (snd_kcontrol_info_t) (snd_kcontrol_t * kcontrol, snd_ctl_elem_info_t * uinfo);
 typedef int (snd_kcontrol_get_t) (snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol);
diff -Nru a/include/sound/core.h b/include/sound/core.h
--- a/include/sound/core.h	2004-10-18 14:57:04 -07:00
+++ b/include/sound/core.h	2004-10-18 14:57:04 -07:00
@@ -211,23 +211,27 @@
 				 void *private_data);
 #define snd_card_set_isa_pm_callback(card,suspend,resume,data) \
 	snd_card_set_dev_pm_callback(card, PM_ISA_DEV, suspend, resume, data)
+#ifdef CONFIG_PCI
 #ifndef SND_PCI_PM_CALLBACKS
 int snd_card_pci_suspend(struct pci_dev *dev, u32 state);
 int snd_card_pci_resume(struct pci_dev *dev);
 #define SND_PCI_PM_CALLBACKS \
 	.suspend = snd_card_pci_suspend,  .resume = snd_card_pci_resume
 #endif
+#endif
 #else
 #define snd_power_lock(card)		do { (void)(card); } while (0)
 #define snd_power_unlock(card)		do { (void)(card); } while (0)
 static inline int snd_power_wait(snd_card_t *card, unsigned int state, struct file *file) { return 0; }
 #define snd_power_get_state(card)	SNDRV_CTL_POWER_D0
 #define snd_power_change_state(card, state)	do { (void)(card); } while (0)
-#define snd_card_set_pm_callback(card,suspend,resume,data) -EINVAL
-#define snd_card_set_dev_pm_callback(card,suspend,resume,data) -EINVAL
-#define snd_card_set_isa_pm_callback(card,suspend,resume,data) -EINVAL
+#define snd_card_set_pm_callback(card,suspend,resume,data)
+#define snd_card_set_dev_pm_callback(card,suspend,resume,data)
+#define snd_card_set_isa_pm_callback(card,suspend,resume,data)
+#ifdef CONFIG_PCI
 #define SND_PCI_PM_CALLBACKS
 #endif
+#endif
 
 /* device.c */
 
@@ -268,7 +272,7 @@
 #else
 #define snd_minor_info_oss_init() /*NOP*/
 #define snd_minor_info_oss_done() /*NOP*/
-#define snd_oss_init_module() /*NOP*/
+#define snd_oss_init_module() 0
 #endif
 
 /* memory.c */
@@ -279,10 +283,12 @@
 int snd_memory_info_init(void);
 int snd_memory_info_done(void);
 void *snd_hidden_kmalloc(size_t size, int flags);
+void *snd_hidden_kcalloc(size_t n, size_t size, int flags);
 void snd_hidden_kfree(const void *obj);
 void *snd_hidden_vmalloc(unsigned long size);
 void snd_hidden_vfree(void *obj);
 #define kmalloc(size, flags) snd_hidden_kmalloc(size, flags)
+#define kcalloc(n, size, flags) snd_hidden_kcalloc(n, size, flags)
 #define kfree(obj) snd_hidden_kfree(obj)
 #define vmalloc(size) snd_hidden_vmalloc(size)
 #define vfree(obj) snd_hidden_vfree(obj)
@@ -300,7 +306,6 @@
 #define kfree_nocheck(obj) kfree(obj)
 #define vfree_nocheck(obj) vfree(obj)
 #endif
-void *snd_kcalloc(size_t size, int flags);
 char *snd_kmalloc_strdup(const char *string, int flags);
 int copy_to_user_fromio(void __user *dst, unsigned long src, size_t count);
 int copy_from_user_toio(unsigned long dst, const void __user *src, size_t count);
@@ -411,7 +416,7 @@
  * not checked.
  */
 #define snd_assert(expr, args...) do {\
-	if (!(expr)) {\
+	if (unlikely(!(expr))) {				\
 		snd_printk("BUG? (%s) (called from %p)\n", __ASTRING__(expr), __builtin_return_address(0));\
 		args;\
 	}\
@@ -427,7 +432,7 @@
  * CONFIG_SND_DEBUG is not set but without any error messages.
  */
 #define snd_runtime_check(expr, args...) do {\
-	if (!(expr)) {\
+	if (unlikely(!(expr))) {				\
 		snd_printk("ERROR (%s) (called from %p)\n", __ASTRING__(expr), __builtin_return_address(0));\
 		args;\
 	}\
diff -Nru a/include/sound/cs46xx.h b/include/sound/cs46xx.h
--- a/include/sound/cs46xx.h	2004-10-18 14:56:28 -07:00
+++ b/include/sound/cs46xx.h	2004-10-18 14:56:28 -07:00
@@ -24,6 +24,7 @@
  */
 
 #include "pcm.h"
+#include "pcm-indirect.h"
 #include "rawmidi.h"
 #include "ac97_codec.h"
 #include "cs46xx_dsp_spos.h"
@@ -1650,14 +1651,7 @@
   
 	unsigned int ctl;
 	unsigned int shift;	/* Shift count to trasform frames in bytes */
-	unsigned int sw_bufsize;
-	unsigned int sw_data;	/* Offset to next dst (or src) in sw ring buffer */
-	unsigned int sw_io;
-	int sw_ready;		/* Bytes ready to be transferred to/from hw */
-	unsigned int hw_data;	/* Offset to next dst (or src) in hw ring buffer */
-	unsigned int hw_io;	/* Ring buffer hw pointer */
-	int hw_ready;		/* Bytes ready for play (or captured) in hw ring buffer */
-	size_t appl_ptr;	/* Last seen appl_ptr */
+	snd_pcm_indirect_t pcm_rec;
 	snd_pcm_substream_t *substream;
 
 	pcm_channel_descriptor_t * pcm_channel;
@@ -1695,14 +1689,7 @@
 
 		unsigned int ctl;
 		unsigned int shift;	/* Shift count to trasform frames in bytes */
-		unsigned int sw_bufsize;
-		unsigned int sw_data;	/* Offset to next dst (or src) in sw ring buffer */
-		unsigned int sw_io;
-		int sw_ready;		/* Bytes ready to be transferred to/from hw */
-		unsigned int hw_data;	/* Offset to next dst (or src) in hw ring buffer */
-		unsigned int hw_io;	/* Ring buffer hw pointer */
-		int hw_ready;		/* Bytes ready for play (or captured) in hw ring buffer */
-		size_t appl_ptr;	/* Last seen appl_ptr */
+		snd_pcm_indirect_t pcm_rec;
 		snd_pcm_substream_t *substream;
 	} capt;
 
@@ -1722,8 +1709,6 @@
 	spinlock_t reg_lock;
 	unsigned int midcr;
 	unsigned int uartm;
-
-	struct snd_dma_device dma_dev;
 
 	int amplifier;
 	void (*amplifier_ctrl)(cs46xx_t *, int);
diff -Nru a/include/sound/driver.h b/include/sound/driver.h
--- a/include/sound/driver.h	2004-10-18 14:56:28 -07:00
+++ b/include/sound/driver.h	2004-10-18 14:56:28 -07:00
@@ -61,6 +61,4 @@
 #undef vfree
 #endif
 
-#include "sndmagic.h"
-
 #endif /* __SOUND_DRIVER_H */
diff -Nru a/include/sound/emu10k1.h b/include/sound/emu10k1.h
--- a/include/sound/emu10k1.h	2004-10-18 14:56:27 -07:00
+++ b/include/sound/emu10k1.h	2004-10-18 14:56:27 -07:00
@@ -30,6 +30,7 @@
 #include <sound/hwdep.h>
 #include <sound/ac97_codec.h>
 #include <sound/util_mem.h>
+#include <sound/pcm-indirect.h>
 #include <linux/interrupt.h>
 #include <asm/io.h>
 
@@ -887,10 +888,7 @@
 	unsigned char gpr_trigger;	/* GPR containing trigger (activate) information (host) */
 	unsigned char gpr_running;	/* GPR containing info if PCM is running (FX8010) */
 	unsigned char etram[32];	/* external TRAM address & data */
-	unsigned int sw_data, hw_data;
-	unsigned int sw_io, hw_io;
-	unsigned int sw_ready, hw_ready;
-	unsigned int appl_ptr;
+	snd_pcm_indirect_t pcm_rec;
 	unsigned int tram_pos;
 	unsigned int tram_shift;
 	snd_emu10k1_fx8010_irq_t *irq;
@@ -935,11 +933,11 @@
 	int irq;
 
 	unsigned long port;			/* I/O port number */
-	struct resource *res_port;
 	int APS: 1,				/* APS flag */
 	    no_ac97: 1,				/* no AC'97 */
 	    tos_link: 1,			/* tos link detected */
-	    rear_ac97: 1;			/* rear channels are on AC'97 */
+	    rear_ac97: 1,			/* rear channels are on AC'97 */
+	    spk71:1;				/* 7.1 configuration (Audigy 2 ZS) */
 	unsigned int audigy;			/* is Audigy? */
 	unsigned int revision;			/* chip revision */
 	unsigned int serial;			/* serial number */
@@ -947,7 +945,6 @@
 	unsigned int card_type;			/* EMU10K1_CARD_* */
 	unsigned int ecard_ctrl;		/* ecard control bits */
 	unsigned long dma_mask;			/* PCI DMA mask */
-	struct snd_dma_device dma_dev;		/* DMA device description */
 	int max_cache_pages;			/* max memory size / PAGE_SIZE */
 	struct snd_dma_buffer silent_page;	/* silent page */
 	struct snd_dma_buffer ptb_pages;	/* page table pages */
@@ -972,7 +969,6 @@
 	snd_pcm_t *pcm;
 	snd_pcm_t *pcm_mic;
 	snd_pcm_t *pcm_efx;
-	snd_pcm_t *pcm_fx8010;
 
 	spinlock_t synth_lock;
 	void *synth;
@@ -1069,6 +1065,15 @@
 /* proc interface */
 int snd_emu10k1_proc_init(emu10k1_t * emu);
 
+/* fx8010 irq handler */
+int snd_emu10k1_fx8010_register_irq_handler(emu10k1_t *emu,
+					    snd_fx8010_irq_handler_t *handler,
+					    unsigned char gpr_running,
+					    void *private_data,
+					    snd_emu10k1_fx8010_irq_t **r_irq);
+int snd_emu10k1_fx8010_unregister_irq_handler(emu10k1_t *emu,
+					      snd_emu10k1_fx8010_irq_t *irq);
+
 #endif /* __KERNEL__ */
 
 /*
@@ -1162,6 +1167,8 @@
 #define FXBUS_PCM_RIGHT_FRONT	0x09
 #define FXBUS_MIDI_REVERB	0x0c
 #define FXBUS_MIDI_CHORUS	0x0d
+#define FXBUS_PCM_LEFT_SIDE	0x0e
+#define FXBUS_PCM_RIGHT_SIDE	0x0f
 #define FXBUS_PT_LEFT		0x14
 #define FXBUS_PT_RIGHT		0x15
 
@@ -1227,8 +1234,8 @@
 #define A_EXTOUT_AFRONT_R	0x09	/*              right */
 #define A_EXTOUT_ACENTER	0x0a	/* analog center */
 #define A_EXTOUT_ALFE		0x0b	/* analog LFE */
-/* 0x0c ?? */
-/* 0x0d ?? */
+#define A_EXTOUT_ASIDE_L	0x0c	/* analog side left  - Audigy 2 ZS */
+#define A_EXTOUT_ASIDE_R	0x0d	/*             right - Audigy 2 ZS */
 #define A_EXTOUT_AREAR_L	0x0e	/* analog rear left */
 #define A_EXTOUT_AREAR_R	0x0f	/*             right */
 #define A_EXTOUT_AC97_L		0x10	/* AC97 left (front) */
diff -Nru a/include/sound/es1688.h b/include/sound/es1688.h
--- a/include/sound/es1688.h	2004-10-18 14:56:33 -07:00
+++ b/include/sound/es1688.h	2004-10-18 14:56:33 -07:00
@@ -55,8 +55,6 @@
 
 typedef struct _snd_es1688 es1688_t;
 
-#define chip_t es1688_t
-
 /* I/O ports */
 
 #define ES1688P(codec, x) ((codec)->port + e_s_s_ESS1688##x)
diff -Nru a/include/sound/info.h b/include/sound/info.h
--- a/include/sound/info.h	2004-10-18 14:56:49 -07:00
+++ b/include/sound/info.h	2004-10-18 14:56:49 -07:00
@@ -91,9 +91,12 @@
 
 extern int snd_info_check_reserved_words(const char *str);
 
-#ifdef CONFIG_SND_OSSEMUL
+#if defined(CONFIG_SND_OSSEMUL) && defined(CONFIG_PROC_FS)
 extern int snd_info_minor_register(void);
 extern int snd_info_minor_unregister(void);
+#else
+#define snd_info_minor_register() /* NOP */
+#define snd_info_minor_unregister() /* NOP */
 #endif
 
 
diff -Nru a/include/sound/initval.h b/include/sound/initval.h
--- a/include/sound/initval.h	2004-10-18 14:55:54 -07:00
+++ b/include/sound/initval.h	2004-10-18 14:55:54 -07:00
@@ -21,20 +21,6 @@
  *
  */
 
-#ifndef MODULE_GENERIC_STRING
-#ifdef MODULE
-#define MODULE_GENERIC_STRING(name, string) \
-static const char __module_generic_string_##name [] \
-  __attribute__ ((unused, __section__(".modstring"))) = #name "=" string;
-#else
-#define MODULE_GENERIC_STRING(name, string)
-#endif
-#endif
-
-#define MODULE_CLASSES(val) MODULE_GENERIC_STRING(info_classes, val)
-#define MODULE_DEVICES(val) MODULE_GENERIC_STRING(info_devices, val)
-#define MODULE_PARM_SYNTAX(id, val) MODULE_GENERIC_STRING(info_parm_##id, val)
-
 #define SNDRV_AUTO_PORT		1
 #define SNDRV_AUTO_IRQ		0xffff
 #define SNDRV_AUTO_DMA		0xffff
@@ -63,25 +49,6 @@
 #define SNDRV_DEFAULT_DMA	{ [0 ... (SNDRV_CARDS-1)] = SNDRV_AUTO_DMA }
 #define SNDRV_DEFAULT_DMA_SIZE	{ [0 ... (SNDRV_CARDS-1)] = SNDRV_AUTO_DMA_SIZE }
 #define SNDRV_DEFAULT_PTR	SNDRV_DEFAULT_STR
-
-#define SNDRV_BOOLEAN_TRUE_DESC	"allows:{{0,Disabled},{1,Enabled}},default:1,dialog:check"
-#define SNDRV_BOOLEAN_FALSE_DESC "allows:{{0,Disabled},{1,Enabled}},default:0,dialog:check"
-
-#define SNDRV_ENABLED		"enable:(enable)"
-
-#define SNDRV_INDEX_DESC	SNDRV_ENABLED ",allows:{{0,7}},unique,skill:required,dialog:list"
-#define SNDRV_ID_DESC		SNDRV_ENABLED ",unique"
-#define SNDRV_ENABLE_DESC	SNDRV_BOOLEAN_FALSE_DESC
-#define SNDRV_ISAPNP_DESC	SNDRV_ENABLED "," SNDRV_BOOLEAN_TRUE_DESC
-#define SNDRV_DMA8_DESC		SNDRV_ENABLED ",allows:{{0,1},{3}},dialog:list"
-#define SNDRV_DMA16_DESC	SNDRV_ENABLED ",allows:{{5,7}},dialog:list"
-#define SNDRV_DMA_DESC		SNDRV_ENABLED ",allows:{{0,1},{3},{5,7}},dialog:list"
-#define SNDRV_IRQ_DESC		SNDRV_ENABLED ",allows:{{5},{7},{9},{10,12},{14,15}},dialog:list"
-#define SNDRV_DMA_SIZE_DESC	SNDRV_ENABLED ",allows:{{4,128}},default:64,skill:advanced"
-#define SNDRV_DMA8_SIZE_DESC	SNDRV_ENABLED ",allows:{{4, 64}},default:64,skill:advanced"
-#define SNDRV_DMA16_SIZE_DESC	SNDRV_ENABLED ",allows:{{4,128}},default:64,skill:advanced"
-#define SNDRV_PORT12_DESC	SNDRV_ENABLED ",allows:{{0,0x3fff}},base:16"
-#define SNDRV_PORT_DESC		SNDRV_ENABLED ",allows:{{0,0xffff}},base:16"
 
 #ifdef SNDRV_LEGACY_AUTO_PROBE
 static int snd_legacy_auto_probe(unsigned long *ports, int (*probe)(unsigned long port))
diff -Nru a/include/sound/memalloc.h b/include/sound/memalloc.h
--- a/include/sound/memalloc.h	2004-10-18 14:55:54 -07:00
+++ b/include/sound/memalloc.h	2004-10-18 14:55:54 -07:00
@@ -30,9 +30,8 @@
  * buffer device info
  */
 struct snd_dma_device {
-	int type;			/* SNDRV_MEM_TYPE_XXX */
+	int type;			/* SNDRV_DMA_TYPE_XXX */
 	struct device *dev;		/* generic device */
-	unsigned int id;		/* a unique ID */
 };
 
 #ifndef snd_dma_pci_data
@@ -56,6 +55,7 @@
  * info for buffer allocation
  */
 struct snd_dma_buffer {
+	struct snd_dma_device dev;	/* device type */
 	unsigned char *area;	/* virtual pointer */
 	dma_addr_t addr;	/* physical address */
 	size_t bytes;		/* buffer size in bytes */
@@ -76,7 +76,7 @@
 	int tblsize;	/* allocated table size */
 	struct snd_sg_page *table;	/* address table */
 	struct page **page_table;	/* page table (for vmap/vunmap) */
-	struct snd_dma_device dev;
+	struct device *dev;
 };
 
 /*
@@ -97,20 +97,21 @@
 
 
 /* allocate/release a buffer */
-int snd_dma_alloc_pages(const struct snd_dma_device *dev, size_t size,
+int snd_dma_alloc_pages(int type, struct device *dev, size_t size,
 			struct snd_dma_buffer *dmab);
-int snd_dma_alloc_pages_fallback(const struct snd_dma_device *dev, size_t size,
+int snd_dma_alloc_pages_fallback(int type, struct device *dev, size_t size,
                                  struct snd_dma_buffer *dmab);
-void snd_dma_free_pages(const struct snd_dma_device *dev, struct snd_dma_buffer *dmab);
+void snd_dma_free_pages(struct snd_dma_buffer *dmab);
 
 /* buffer-preservation managements */
-size_t snd_dma_get_reserved(const struct snd_dma_device *dev, struct snd_dma_buffer *dmab);
-int snd_dma_free_reserved(const struct snd_dma_device *dev);
-int snd_dma_set_reserved(const struct snd_dma_device *dev, struct snd_dma_buffer *dmab);
+
+#define snd_dma_pci_buf_id(pci)	(((unsigned int)(pci)->vendor << 16) | (pci)->device)
+
+size_t snd_dma_get_reserved_buf(struct snd_dma_buffer *dmab, unsigned int id);
+int snd_dma_reserve_buf(struct snd_dma_buffer *dmab, unsigned int id);
 
 /* basic memory allocation functions */
 void *snd_malloc_pages(size_t size, unsigned int gfp_flags);
-void *snd_malloc_pages_fallback(size_t size, unsigned int gfp_flags, size_t *res_size);
 void snd_free_pages(void *ptr, size_t size);
 
 #endif /* __SOUND_MEMALLOC_H */
diff -Nru a/include/sound/pcm-indirect.h b/include/sound/pcm-indirect.h
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/include/sound/pcm-indirect.h	2004-10-18 14:57:23 -07:00
@@ -0,0 +1,177 @@
+/*
+ * Helper functions for indirect PCM data transfer
+ *
+ *  Copyright (c) by Takashi Iwai <tiwai@suse.de>
+ *                   Jaroslav Kysela <perex@suse.cz>
+ *
+ *   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.
+ */
+
+#ifndef __SOUND_PCM_INDIRECT_H
+#define __SOUND_PCM_INDIRECT_H
+
+#include <sound/pcm.h>
+
+typedef struct sndrv_pcm_indirect {
+	unsigned int hw_buffer_size;	/* Byte size of hardware buffer */
+	unsigned int hw_queue_size;	/* Max queue size of hw buffer (0 = buffer size) */
+	unsigned int hw_data;	/* Offset to next dst (or src) in hw ring buffer */
+	unsigned int hw_io;	/* Ring buffer hw pointer */
+	int hw_ready;		/* Bytes ready for play (or captured) in hw ring buffer */
+	unsigned int sw_buffer_size;	/* Byte size of software buffer */
+	unsigned int sw_data;	/* Offset to next dst (or src) in sw ring buffer */
+	unsigned int sw_io;	/* Current software pointer in bytes */
+	int sw_ready;		/* Bytes ready to be transferred to/from hw */
+	snd_pcm_uframes_t appl_ptr;	/* Last seen appl_ptr */
+} snd_pcm_indirect_t;
+
+typedef void (*snd_pcm_indirect_copy_t)(snd_pcm_substream_t *substream,
+					snd_pcm_indirect_t *rec, size_t bytes);
+
+/*
+ * helper function for playback ack callback
+ */
+static inline void
+snd_pcm_indirect_playback_transfer(snd_pcm_substream_t *substream,
+				   snd_pcm_indirect_t *rec,
+				   snd_pcm_indirect_copy_t copy)
+{
+	snd_pcm_runtime_t *runtime = substream->runtime;
+	snd_pcm_uframes_t appl_ptr = runtime->control->appl_ptr;
+	snd_pcm_sframes_t diff = appl_ptr - rec->appl_ptr;
+	int qsize;
+
+	if (diff) {
+		if (diff < -(snd_pcm_sframes_t) (runtime->boundary / 2))
+			diff += runtime->boundary;
+		rec->sw_ready += (int)frames_to_bytes(runtime, diff);
+		rec->appl_ptr = appl_ptr;
+	}
+	qsize = rec->hw_queue_size ? rec->hw_queue_size : rec->hw_buffer_size;
+	while (rec->hw_ready < qsize && rec->sw_ready > 0) {
+		unsigned int hw_to_end = rec->hw_buffer_size - rec->hw_data;
+		unsigned int sw_to_end = rec->sw_buffer_size - rec->sw_data;
+		unsigned int bytes = qsize - rec->hw_ready;
+		if (rec->sw_ready < (int)bytes)
+			bytes = rec->sw_ready;
+		if (hw_to_end < bytes)
+			bytes = hw_to_end;
+		if (sw_to_end < bytes)
+			bytes = sw_to_end;
+		if (! bytes)
+			break;
+		copy(substream, rec, bytes);
+		rec->hw_data += bytes;
+		if (rec->hw_data == rec->hw_buffer_size)
+			rec->hw_data = 0;
+		rec->sw_data += bytes;
+		if (rec->sw_data == rec->sw_buffer_size)
+			rec->sw_data = 0;
+		rec->hw_ready += bytes;
+		rec->sw_ready -= bytes;
+	}
+}
+
+/*
+ * helper function for playback pointer callback
+ * ptr = current byte pointer
+ */
+static inline snd_pcm_uframes_t
+snd_pcm_indirect_playback_pointer(snd_pcm_substream_t *substream,
+				  snd_pcm_indirect_t *rec, unsigned int ptr)
+{
+	int bytes = ptr - rec->hw_io;
+	if (bytes < 0)
+		bytes += rec->hw_buffer_size;
+	rec->hw_io = ptr;
+	rec->hw_ready -= bytes;
+	rec->sw_io += bytes;
+	if (rec->sw_io >= rec->sw_buffer_size)
+		rec->sw_io -= rec->sw_buffer_size;
+	if (substream->ops->ack)
+		substream->ops->ack(substream);
+	return bytes_to_frames(substream->runtime, rec->sw_io);
+}
+
+
+/*
+ * helper function for capture ack callback
+ */
+static inline void
+snd_pcm_indirect_capture_transfer(snd_pcm_substream_t *substream,
+				  snd_pcm_indirect_t *rec,
+				  snd_pcm_indirect_copy_t copy)
+{
+	snd_pcm_runtime_t *runtime = substream->runtime;
+	snd_pcm_uframes_t appl_ptr = runtime->control->appl_ptr;
+	snd_pcm_sframes_t diff = appl_ptr - rec->appl_ptr;
+
+	if (diff) {
+		if (diff < -(snd_pcm_sframes_t) (runtime->boundary / 2))
+			diff += runtime->boundary;
+		rec->sw_ready -= frames_to_bytes(runtime, diff);
+		rec->appl_ptr = appl_ptr;
+	}
+	while (rec->hw_ready > 0 && 
+	       rec->sw_ready < (int)rec->sw_buffer_size) {
+		size_t hw_to_end = rec->hw_buffer_size - rec->hw_data;
+		size_t sw_to_end = rec->sw_buffer_size - rec->sw_data;
+		size_t bytes = rec->sw_buffer_size - rec->sw_ready;
+		if (rec->hw_ready < (int)bytes)
+			bytes = rec->hw_ready;
+		if (hw_to_end < bytes)
+			bytes = hw_to_end;
+		if (sw_to_end < bytes)
+			bytes = sw_to_end;
+		if (! bytes)
+			break;
+		copy(substream, rec, bytes);
+		rec->hw_data += bytes;
+		if ((int)rec->hw_data == rec->hw_buffer_size)
+			rec->hw_data = 0;
+		rec->sw_data += bytes;
+		if (rec->sw_data == rec->sw_buffer_size)
+			rec->sw_data = 0;
+		rec->hw_ready -= bytes;
+		rec->sw_ready += bytes;
+	}
+}
+
+/*
+ * helper function for capture pointer callback,
+ * ptr = current byte pointer
+ */
+static inline snd_pcm_uframes_t
+snd_pcm_indirect_capture_pointer(snd_pcm_substream_t *substream,
+				 snd_pcm_indirect_t *rec, unsigned int ptr)
+{
+	int qsize;
+	int bytes = ptr - rec->hw_io;
+	if (bytes < 0)
+		bytes += rec->hw_buffer_size;
+	rec->hw_io = ptr;
+	rec->hw_ready += bytes;
+	qsize = rec->hw_queue_size ? rec->hw_queue_size : rec->hw_buffer_size;
+	if (rec->hw_ready > qsize)
+		return SNDRV_PCM_POS_XRUN;
+	rec->sw_io += bytes;
+	if (rec->sw_io >= rec->sw_buffer_size)
+		rec->sw_io -= rec->sw_buffer_size;
+	if (substream->ops->ack)
+		substream->ops->ack(substream);
+	return bytes_to_frames(substream->runtime, rec->sw_io);
+}
+
+#endif /* __SOUND_PCM_INDIRECT_H */
diff -Nru a/include/sound/pcm.h b/include/sound/pcm.h
--- a/include/sound/pcm.h	2004-10-18 14:56:29 -07:00
+++ b/include/sound/pcm.h	2004-10-18 14:56:29 -07:00
@@ -52,10 +52,8 @@
 typedef struct sndrv_mask snd_mask_t;
 typedef struct snd_sg_buf snd_pcm_sgbuf_t;
 
-#define _snd_pcm_substream_chip(substream) ((substream)->private_data)
-#define snd_pcm_substream_chip(substream) snd_magic_cast1(chip_t, _snd_pcm_substream_chip(substream), return -ENXIO)
-#define _snd_pcm_chip(pcm) ((pcm)->private_data)
-#define snd_pcm_chip(pcm) snd_magic_cast1(chip_t, _snd_pcm_chip(pcm), return -ENXIO)
+#define snd_pcm_substream_chip(substream) ((substream)->private_data)
+#define snd_pcm_chip(pcm) ((pcm)->private_data)
 
 typedef struct _snd_pcm_file snd_pcm_file_t;
 typedef struct _snd_pcm_runtime snd_pcm_runtime_t;
@@ -99,6 +97,7 @@
 	int (*silence)(snd_pcm_substream_t *substream, int channel, 
 		       snd_pcm_uframes_t pos, snd_pcm_uframes_t count);
 	struct page *(*page)(snd_pcm_substream_t *substream, unsigned long offset);
+	int (*mmap)(snd_pcm_substream_t *substream, struct vm_area_struct *vma);
 	int (*ack)(snd_pcm_substream_t *substream);
 } snd_pcm_ops_t;
 
@@ -123,6 +122,8 @@
 #define SNDRV_PCM_TRIGGER_SUSPEND	5
 #define SNDRV_PCM_TRIGGER_RESUME	6
 
+#define SNDRV_PCM_POS_XRUN		((snd_pcm_uframes_t)-1)
+
 /* If you change this don't forget to change rates[] table in pcm_native.c */
 #define SNDRV_PCM_RATE_5512		(1<<0)		/* 5512Hz */
 #define SNDRV_PCM_RATE_8000		(1<<1)		/* 8000Hz */
@@ -351,7 +352,8 @@
 	unsigned char *dma_area;	/* DMA area */
 	dma_addr_t dma_addr;		/* physical bus address (not accessible from main CPU) */
 	size_t dma_bytes;		/* size of DMA area */
-	void *dma_private;		/* private DMA data for the memory allocator */
+
+	struct snd_dma_buffer *dma_buffer_p;	/* allocated buffer */
 
 #if defined(CONFIG_SND_PCM_OSS) || defined(CONFIG_SND_PCM_OSS_MODULE)
 	/* -- OSS things -- */
@@ -372,8 +374,8 @@
 	char name[32];			/* substream name */
 	int stream;			/* stream (direction) */
 	size_t buffer_bytes_max;	/* limit ring buffer size */
-	struct snd_dma_device dma_device;
 	struct snd_dma_buffer dma_buffer;
+	unsigned int dma_buf_id;
 	size_t dma_max;
 	/* -- hardware operations -- */
 	unsigned int open_flag: 1;	/* lowlevel device has been opened */
@@ -382,7 +384,7 @@
 	snd_pcm_runtime_t *runtime;
         /* -- timer section -- */
 	snd_timer_t *timer;		/* timer */
-	int timer_running: 1;		/* time is running */
+	unsigned timer_running: 1;	/* time is running */
 	spinlock_t timer_lock;
 	/* -- next substream -- */
 	snd_pcm_substream_t *next;
@@ -851,7 +853,7 @@
 int snd_pcm_format_big_endian(snd_pcm_format_t format);
 int snd_pcm_format_width(snd_pcm_format_t format);			/* in bits */
 int snd_pcm_format_physical_width(snd_pcm_format_t format);		/* in bits */
-u_int64_t snd_pcm_format_silence_64(snd_pcm_format_t format);
+const unsigned char *snd_pcm_format_silence_64(snd_pcm_format_t format);
 int snd_pcm_format_set_silence(snd_pcm_format_t format, void *buf, unsigned int frames);
 snd_pcm_format_t snd_pcm_build_linear_format(int width, int unsignd, int big_endian);
 ssize_t snd_pcm_format_size(snd_pcm_format_t format, size_t samples);
@@ -892,6 +894,22 @@
 
 int snd_pcm_limit_hw_rates(snd_pcm_runtime_t *runtime);
 
+static inline void snd_pcm_set_runtime_buffer(snd_pcm_substream_t *substream,
+					      struct snd_dma_buffer *bufp)
+{
+	snd_pcm_runtime_t *runtime = substream->runtime;
+	if (bufp) {
+		runtime->dma_buffer_p = bufp;
+		runtime->dma_area = bufp->area;
+		runtime->dma_addr = bufp->addr;
+		runtime->dma_bytes = bufp->bytes;
+	} else {
+		runtime->dma_buffer_p = NULL;
+		runtime->dma_area = NULL;
+		runtime->dma_addr = 0;
+		runtime->dma_bytes = 0;
+	}
+}
 
 /*
  *  Timer interface
@@ -916,10 +934,32 @@
 int snd_pcm_lib_malloc_pages(snd_pcm_substream_t *substream, size_t size);
 int snd_pcm_lib_free_pages(snd_pcm_substream_t *substream);
 
-#define snd_pcm_substream_sgbuf(substream) ((substream)->runtime->dma_private)
+#define snd_pcm_substream_sgbuf(substream) ((substream)->runtime->dma_buffer_p->private_data)
 #define snd_pcm_sgbuf_pages(size) snd_sgbuf_aligned_pages(size)
 #define snd_pcm_sgbuf_get_addr(sgbuf,ofs) snd_sgbuf_get_addr(sgbuf,ofs)
 struct page *snd_pcm_sgbuf_ops_page(snd_pcm_substream_t *substream, unsigned long offset);
+
+/* handle mmap counter - PCM mmap callback should handle this counter properly */
+static inline void snd_pcm_mmap_data_open(struct vm_area_struct *area)
+{
+	snd_pcm_substream_t *substream = (snd_pcm_substream_t *)area->vm_private_data;
+	atomic_inc(&substream->runtime->mmap_count);
+}
+
+static inline void snd_pcm_mmap_data_close(struct vm_area_struct *area)
+{
+	snd_pcm_substream_t *substream = (snd_pcm_substream_t *)area->vm_private_data;
+	atomic_dec(&substream->runtime->mmap_count);
+}
+
+/* mmap for io-memory area */
+#if defined(CONFIG_X86) || defined(CONFIG_PPC) || defined(CONFIG_ALPHA)
+#define SNDRV_PCM_INFO_MMAP_IOMEM	SNDRV_PCM_INFO_MMAP
+int snd_pcm_lib_mmap_iomem(snd_pcm_substream_t *substream, struct vm_area_struct *area);
+#else
+#define SNDRV_PCM_INFO_MMAP_IOMEM	0
+#define snd_pcm_lib_mmap_iomem	NULL
+#endif
 
 static inline void snd_pcm_limit_isa_dma_size(int dma, size_t *max)
 {
diff -Nru a/include/sound/pcm_oss.h b/include/sound/pcm_oss.h
--- a/include/sound/pcm_oss.h	2004-10-18 14:56:48 -07:00
+++ b/include/sound/pcm_oss.h	2004-10-18 14:56:48 -07:00
@@ -39,10 +39,10 @@
 };
 
 typedef struct _snd_pcm_oss_runtime {
-	int params: 1,				/* format/parameter change */
-            prepare: 1,				/* need to prepare the operation */
-            trigger: 1,				/* trigger flag */
-            sync_trigger: 1;			/* sync trigger flag */
+	unsigned params: 1,			/* format/parameter change */
+		 prepare: 1,			/* need to prepare the operation */
+		 trigger: 1,			/* trigger flag */
+		 sync_trigger: 1;		/* sync trigger flag */
 	int rate;				/* requested rate */
 	int format;				/* requested OSS format */
 	unsigned int channels;			/* requested channels */
@@ -68,7 +68,7 @@
 } snd_pcm_oss_file_t;
 
 typedef struct _snd_pcm_oss_substream {
-	int oss: 1;				/* oss mode */
+	unsigned oss: 1;			/* oss mode */
 	snd_pcm_oss_setup_t *setup;		/* active setup */
 	snd_pcm_oss_file_t *file;
 } snd_pcm_oss_substream_t;
diff -Nru a/include/sound/seq_kernel.h b/include/sound/seq_kernel.h
--- a/include/sound/seq_kernel.h	2004-10-18 14:57:04 -07:00
+++ b/include/sound/seq_kernel.h	2004-10-18 14:57:04 -07:00
@@ -129,8 +129,8 @@
 
 typedef struct {
 	void *private_data;
-	int allow_input: 1,
-	    allow_output: 1;
+	unsigned allow_input: 1,
+		 allow_output: 1;
 	/*...*/
 } snd_seq_client_callback_t;
 
@@ -167,6 +167,9 @@
 typedef int (*snd_seq_dump_func_t)(void *ptr, void *buf, int count);
 int snd_seq_expand_var_event(const snd_seq_event_t *event, int count, char *buf, int in_kernel, int size_aligned);
 int snd_seq_dump_var_event(const snd_seq_event_t *event, snd_seq_dump_func_t func, void *private_data);
+
+/* interface for OSS emulation */
+int snd_seq_set_queue_tempo(int client, snd_seq_queue_tempo_t *tempo);
 
 /* port callback routines */
 void snd_port_init_callback(snd_seq_port_callback_t *p);
diff -Nru a/include/sound/sndmagic.h b/include/sound/sndmagic.h
--- a/include/sound/sndmagic.h	2004-10-18 14:56:28 -07:00
+++ /dev/null	Wed Dec 31 16:00:00 196900
@@ -1,218 +0,0 @@
-#ifndef __SOUND_SNDMAGIC_H
-#define __SOUND_SNDMAGIC_H
-
-/*
- *  Magic allocation, deallocation, check
- *  Copyright (c) 2000 by Abramo Bagnara <abramo@alsa-project.org>
- *
- *
- *   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
- *
- */
-
-
-#ifdef CONFIG_SND_DEBUG_MEMORY
-
-void *_snd_magic_kcalloc(unsigned long magic, size_t size, int flags);
-void *_snd_magic_kmalloc(unsigned long magic, size_t size, int flags);
-
-/**
- * snd_magic_kmalloc - allocate a record with a magic-prefix
- * @type: the type to allocate a record (like xxx_t)
- * @extra: the extra size to allocate in bytes
- * @flags: the allocation condition (GFP_XXX)
- *
- * Allocates a record of the given type with the extra space and
- * returns its pointer.  The allocated record has a secret magic-key
- * to be checked via snd_magic_cast() for safe casts.
- *
- * The allocated pointer must be released via snd_magic_kfree().
- *
- * The "struct xxx" style cannot be used as the type argument
- * because the magic-key constant is generated from the type-name
- * string.
- */
-#define snd_magic_kmalloc(type, extra, flags) \
-	(type *) _snd_magic_kmalloc(type##_magic, sizeof(type) + extra, flags)
-/**
- * snd_magic_kcalloc - allocate a record with a magic-prefix and initialize
- * @type: the type to allocate a record (like xxx_t)
- * @extra: the extra size to allocate in bytes
- * @flags: the allocation condition (GFP_XXX)
- *
- * Works like snd_magic_kmalloc() but this clears the area with zero
- * automatically.
- */
-#define snd_magic_kcalloc(type, extra, flags) \
-	(type *) _snd_magic_kcalloc(type##_magic, sizeof(type) + extra, flags)
-
-/**
- * snd_magic_kfree - release the allocated area
- * @ptr: the pointer allocated via snd_magic_kmalloc() or snd_magic_kcalloc()
- *
- * Releases the memory area allocated via snd_magic_kmalloc() or
- * snd_magic_kcalloc() function.
- */
-void snd_magic_kfree(void *ptr);
-
-static inline unsigned long _snd_magic_value(void *obj)
-{
-	return obj == NULL ? (unsigned long)-1 : *(((unsigned long *)obj) - 1);
-}
-
-static inline int _snd_magic_bad(void *obj, unsigned long magic)
-{
-	return _snd_magic_value(obj) != magic;
-}
-
-#define snd_magic_cast1(t, expr, cmd) snd_magic_cast(t, expr, cmd)
-
-/**
- * snd_magic_cast - check and cast the magic-allocated pointer
- * @type: the type of record to cast
- * @ptr: the magic-allocated pointer
- * @action...: the action to do if failed
- *
- * This macro provides a safe cast for the given type, which was
- * allocated via snd_magic_kmalloc() or snd_magic_kcallc().
- * If the pointer is invalid, i.e. the cast-type doesn't match,
- * the action arguments are called with a debug message.
- */
-#define snd_magic_cast(type, ptr, action...) \
-	(type *) ({\
-	void *__ptr = ptr;\
-	unsigned long __magic = _snd_magic_value(__ptr);\
-	if (__magic != type##_magic) {\
-		snd_printk("bad MAGIC (0x%lx)\n", __magic);\
-		action;\
-	}\
-	__ptr;\
-})
-
-#define snd_device_t_magic			0xa15a00ff
-#define snd_pcm_t_magic				0xa15a0101
-#define snd_pcm_file_t_magic			0xa15a0102
-#define snd_pcm_substream_t_magic		0xa15a0103
-#define snd_pcm_proc_private_t_magic		0xa15a0104
-#define snd_pcm_oss_file_t_magic		0xa15a0105
-#define snd_mixer_oss_t_magic			0xa15a0106
-// #define snd_pcm_sgbuf_t_magic			0xa15a0107
-
-#define snd_info_private_data_t_magic		0xa15a0201
-#define snd_info_entry_t_magic			0xa15a0202
-#define snd_ctl_file_t_magic			0xa15a0301
-#define snd_kcontrol_t_magic			0xa15a0302
-#define snd_rawmidi_t_magic			0xa15a0401
-#define snd_rawmidi_file_t_magic		0xa15a0402
-#define snd_virmidi_t_magic			0xa15a0403
-#define snd_virmidi_dev_t_magic			0xa15a0404
-#define snd_timer_t_magic			0xa15a0501
-#define snd_timer_user_t_magic			0xa15a0502
-#define snd_hwdep_t_magic			0xa15a0601
-#define snd_seq_device_t_magic			0xa15a0701
-
-#define es18xx_t_magic				0xa15a1101
-#define trident_t_magic				0xa15a1201
-#define es1938_t_magic				0xa15a1301
-#define cs46xx_t_magic				0xa15a1401
-#define cs46xx_pcm_t_magic			0xa15a1402
-#define ensoniq_t_magic				0xa15a1501
-#define sonicvibes_t_magic			0xa15a1601
-#define mpu401_t_magic				0xa15a1701
-#define fm801_t_magic				0xa15a1801
-#define ac97_t_magic				0xa15a1901
-#define ac97_bus_t_magic			0xa15a1902
-#define ak4531_t_magic				0xa15a1a01
-#define snd_uart16550_t_magic			0xa15a1b01
-#define emu10k1_t_magic				0xa15a1c01
-#define emu10k1_pcm_t_magic			0xa15a1c02
-#define emu10k1_midi_t_magic			0xa15a1c03
-#define snd_gus_card_t_magic			0xa15a1d01
-#define gus_pcm_private_t_magic			0xa15a1d02
-#define gus_proc_private_t_magic		0xa15a1d03
-#define tea6330t_t_magic			0xa15a1e01
-#define ad1848_t_magic				0xa15a1f01
-#define cs4231_t_magic				0xa15a2001
-#define es1688_t_magic				0xa15a2101
-#define opti93x_t_magic				0xa15a2201
-#define emu8000_t_magic				0xa15a2301
-#define emu8000_proc_private_t_magic		0xa15a2302
-#define snd_emux_t_magic			0xa15a2303
-#define snd_emux_port_t_magic			0xa15a2304
-#define sb_t_magic				0xa15a2401
-#define snd_sb_csp_t_magic			0xa15a2402
-#define snd_card_dummy_t_magic			0xa15a2501
-#define snd_card_dummy_pcm_t_magic		0xa15a2502
-#define opl3_t_magic				0xa15a2601
-#define opl4_t_magic				0xa15a2602
-#define snd_seq_dummy_port_t_magic		0xa15a2701
-#define ice1712_t_magic				0xa15a2801
-#define ad1816a_t_magic				0xa15a2901
-#define intel8x0_t_magic			0xa15a2a01
-#define es1968_t_magic				0xa15a2b01
-#define esschan_t_magic				0xa15a2b02
-#define via82xx_t_magic				0xa15a2c01
-#define pdplus_t_magic				0xa15a2d01
-#define cmipci_t_magic				0xa15a2e01
-#define ymfpci_t_magic				0xa15a2f01
-#define ymfpci_pcm_t_magic			0xa15a2f02
-#define cs4281_t_magic				0xa15a3001
-#define snd_i2c_bus_t_magic			0xa15a3101
-#define snd_i2c_device_t_magic			0xa15a3102
-#define cs8427_t_magic				0xa15a3111
-#define m3_t_magic				0xa15a3201
-#define m3_dma_t_magic				0xa15a3202
-#define nm256_t_magic				0xa15a3301
-#define nm256_dma_t_magic			0xa15a3302
-#define sam9407_t_magic				0xa15a3401
-#define pmac_t_magic				0xa15a3501
-#define ali_t_magic				0xa15a3601
-#define mtpav_t_magic				0xa15a3701
-#define mtpav_port_t_magic			0xa15a3702
-#define korg1212_t_magic			0xa15a3800
-#define opl3sa2_t_magic				0xa15a3900
-#define serialmidi_t_magic			0xa15a3a00
-#define sa11xx_uda1341_t_magic			0xa15a3b00
-#define uda1341_t_magic                         0xa15a3c00
-#define l3_client_t_magic                       0xa15a3d00
-#define snd_usb_audio_t_magic			0xa15a3e01
-#define usb_mixer_elem_info_t_magic		0xa15a3e02
-#define snd_usb_stream_t_magic			0xa15a3e03
-#define snd_usb_midi_t_magic			0xa15a3f01
-#define snd_usb_midi_out_endpoint_t_magic	0xa15a3f02
-#define snd_usb_midi_in_endpoint_t_magic	0xa15a3f03
-#define ak4117_t_magic				0xa15a4000
-#define psic_t_magic				0xa15a4100
-#define vx_core_t_magic				0xa15a4110
-#define vx_pipe_t_magic				0xa15a4112
-#define azf3328_t_magic				0xa15a4200
-#define snd_card_harmony_t_magic		0xa15a4300
-#define bt87x_t_magic				0xa15a4400
-#define pdacf_t_magic				0xa15a4500
-#define vortex_t_magic				0xa15a4601
-#define atiixp_t_magic				0xa15a4701
-#define amd7930_t_magic				0xa15a4801
-
-#else
-
-#define snd_magic_kcalloc(type, extra, flags) (type *) snd_kcalloc(sizeof(type) + extra, flags)
-#define snd_magic_kmalloc(type, extra, flags) (type *) kmalloc(sizeof(type) + extra, flags)
-#define snd_magic_cast(type, ptr, retval) (type *) ptr
-#define snd_magic_cast1(type, ptr, retval) snd_magic_cast(type, ptr, retval)
-#define snd_magic_kfree kfree
-
-#endif
-
-#endif /* __SOUND_SNDMAGIC_H */
diff -Nru a/include/sound/soundfont.h b/include/sound/soundfont.h
--- a/include/sound/soundfont.h	2004-10-18 14:57:04 -07:00
+++ b/include/sound/soundfont.h	2004-10-18 14:57:04 -07:00
@@ -95,6 +95,7 @@
 	int zone_locked;	/* locked time for zone */
 	int sample_locked;	/* locked time for sample */
 	snd_sf_callback_t callback;	/* callback functions */
+	int presets_locked;
 	struct semaphore presets_mutex;
 	spinlock_t lock;
 	snd_util_memhdr_t *memhdr;
diff -Nru a/include/sound/timer.h b/include/sound/timer.h
--- a/include/sound/timer.h	2004-10-18 14:56:32 -07:00
+++ b/include/sound/timer.h	2004-10-18 14:56:32 -07:00
@@ -40,8 +40,7 @@
 typedef struct sndrv_timer_read snd_timer_read_t;
 typedef struct sndrv_timer_tread snd_timer_tread_t;
 
-#define _snd_timer_chip(timer) ((timer)->private_data)
-#define snd_timer_chip(timer) snd_magic_cast1(chip_t, _snd_timer_chip(timer), return -ENXIO)
+#define snd_timer_chip(timer) ((timer)->private_data)
 
 #define SNDRV_TIMER_DEVICES	16
 
diff -Nru a/include/sound/trident.h b/include/sound/trident.h
--- a/include/sound/trident.h	2004-10-18 14:56:33 -07:00
+++ b/include/sound/trident.h	2004-10-18 14:56:33 -07:00
@@ -398,7 +398,6 @@
         unsigned char  bDMAStart;
 
 	unsigned long port;
-	struct resource *res_port;
 	unsigned long midi_port;
 
 	unsigned int spurious_irq_count;
diff -Nru a/include/sound/version.h b/include/sound/version.h
--- a/include/sound/version.h	2004-10-18 14:56:28 -07:00
+++ b/include/sound/version.h	2004-10-18 14:56:28 -07:00
@@ -1,3 +1,3 @@
 /* include/version.h.  Generated by configure.  */
-#define CONFIG_SND_VERSION "1.0.4"
-#define CONFIG_SND_DATE " (Mon May 17 14:31:44 2004 UTC)"
+#define CONFIG_SND_VERSION "1.0.6"
+#define CONFIG_SND_DATE " (Sun Aug 15 07:17:53 2004 UTC)"
diff -Nru a/include/sound/vx_core.h b/include/sound/vx_core.h
--- a/include/sound/vx_core.h	2004-10-18 14:55:54 -07:00
+++ b/include/sound/vx_core.h	2004-10-18 14:55:54 -07:00
@@ -182,6 +182,7 @@
 	/* clock and audio sources */
 	unsigned int audio_source;	/* current audio input source */
 	unsigned int audio_source_target;
+	unsigned int clock_mode;	/* clock mode (VX_CLOCK_MODE_XXX) */
 	unsigned int clock_source;	/* current clock source (INTERNAL_QUARTZ or UER_SYNC) */
 	unsigned int freq;		/* current frequency */
 	unsigned int freq_detected;	/* detected frequency from digital in */
@@ -362,6 +363,13 @@
 enum {
 	INTERNAL_QUARTZ,
 	UER_SYNC
+};
+
+/* clock mode */
+enum {
+	VX_CLOCK_MODE_AUTO,	/* depending on the current audio source */
+	VX_CLOCK_MODE_INTERNAL,	/* fixed to internal quartz */
+	VX_CLOCK_MODE_EXTERNAL	/* fixed to UER sync */
 };
 
 /* SPDIF/UER type */
diff -Nru a/include/sound/ymfpci.h b/include/sound/ymfpci.h
--- a/include/sound/ymfpci.h	2004-10-18 14:56:28 -07:00
+++ b/include/sound/ymfpci.h	2004-10-18 14:56:28 -07:00
@@ -316,7 +316,6 @@
 	struct gameport gameport;
 #endif
 
-	struct snd_dma_device dma_dev;
 	struct snd_dma_buffer work_ptr;
 
 	unsigned int bank_size_playback;
diff -Nru a/include/video/epson1355.h b/include/video/epson1355.h
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/include/video/epson1355.h	2004-10-18 14:57:23 -07:00
@@ -0,0 +1,64 @@
+/*
+ * include/video/epson13xx.h -- Epson 13xx frame buffer
+ *
+ * Copyright (C) Hewlett-Packard Company.  All rights reserved.
+ *
+ * Written by Christopher Hoover <ch@hpl.hp.com>
+ *
+ */
+
+#ifndef _EPSON13XX_H_
+#define _EPSON13XX_H_
+
+#define REG_REVISION_CODE              0x00
+#define REG_MEMORY_CONFIG              0x01
+#define REG_PANEL_TYPE                 0x02
+#define REG_MOD_RATE                   0x03
+#define REG_HORZ_DISP_WIDTH            0x04
+#define REG_HORZ_NONDISP_PERIOD        0x05
+#define REG_HRTC_START_POSITION        0x06
+#define REG_HRTC_PULSE_WIDTH           0x07
+#define REG_VERT_DISP_HEIGHT0          0x08
+#define REG_VERT_DISP_HEIGHT1          0x09
+#define REG_VERT_NONDISP_PERIOD        0x0A
+#define REG_VRTC_START_POSITION        0x0B
+#define REG_VRTC_PULSE_WIDTH           0x0C
+#define REG_DISPLAY_MODE               0x0D
+#define REG_SCRN1_LINE_COMPARE0        0x0E
+#define REG_SCRN1_LINE_COMPARE1        0x0F
+#define REG_SCRN1_DISP_START_ADDR0     0x10
+#define REG_SCRN1_DISP_START_ADDR1     0x11
+#define REG_SCRN1_DISP_START_ADDR2     0x12
+#define REG_SCRN2_DISP_START_ADDR0     0x13
+#define REG_SCRN2_DISP_START_ADDR1     0x14
+#define REG_SCRN2_DISP_START_ADDR2     0x15
+#define REG_MEM_ADDR_OFFSET0           0x16
+#define REG_MEM_ADDR_OFFSET1           0x17
+#define REG_PIXEL_PANNING              0x18
+#define REG_CLOCK_CONFIG               0x19
+#define REG_POWER_SAVE_CONFIG          0x1A
+#define REG_MISC                       0x1B
+#define REG_MD_CONFIG_READBACK0        0x1C
+#define REG_MD_CONFIG_READBACK1        0x1D
+#define REG_GPIO_CONFIG0               0x1E
+#define REG_GPIO_CONFIG1               0x1F
+#define REG_GPIO_CONTROL0              0x20
+#define REG_GPIO_CONTROL1              0x21
+#define REG_PERF_ENHANCEMENT0          0x22
+#define REG_PERF_ENHANCEMENT1          0x23
+#define REG_LUT_ADDR                   0x24
+#define REG_RESERVED_1                 0x25
+#define REG_LUT_DATA                   0x26
+#define REG_INK_CURSOR_CONTROL         0x27
+#define REG_CURSOR_X_POSITION0         0x28
+#define REG_CURSOR_X_POSITION1         0x29
+#define REG_CURSOR_Y_POSITION0         0x2A
+#define REG_CURSOR_Y_POSITION1         0x2B
+#define REG_INK_CURSOR_COLOR0_0        0x2C
+#define REG_INK_CURSOR_COLOR0_1        0x2D
+#define REG_INK_CURSOR_COLOR1_0        0x2E
+#define REG_INK_CURSOR_COLOR1_1        0x2F
+#define REG_INK_CURSOR_START_ADDR      0x30
+#define REG_ALTERNATE_FRM              0x31
+
+#endif
diff -Nru a/include/video/neomagic.h b/include/video/neomagic.h
--- a/include/video/neomagic.h	2004-10-18 14:56:28 -07:00
+++ b/include/video/neomagic.h	2004-10-18 14:56:28 -07:00
@@ -69,6 +69,9 @@
 #define NEO_ICON128_ENABLE	0x0000000C
 #define NEO_ICON_BLANK		0x00000010
 
+#define NEO_GR01_SUPPRESS_VSYNC 0x10
+#define NEO_GR01_SUPPRESS_HSYNC 0x20
+
 #ifdef __KERNEL__
 
 #ifdef NEOFB_DEBUG
diff -Nru a/include/video/tdfx.h b/include/video/tdfx.h
--- a/include/video/tdfx.h	2004-10-18 14:56:28 -07:00
+++ b/include/video/tdfx.h	2004-10-18 14:56:28 -07:00
@@ -114,6 +114,7 @@
 #define VGAINIT1_MASK                   0x1fffff
 #define VIDCFG_VIDPROC_ENABLE           BIT(0)
 #define VIDCFG_CURS_X11                 BIT(1)
+#define VIDCFG_INTERLACE                BIT(3)
 #define VIDCFG_HALF_MODE                BIT(4)
 #define VIDCFG_DESK_ENABLE              BIT(7)
 #define VIDCFG_CLUT_BYPASS              BIT(10)
diff -Nru a/include/video/vga.h b/include/video/vga.h
--- a/include/video/vga.h	2004-10-18 14:56:48 -07:00
+++ b/include/video/vga.h	2004-10-18 14:56:48 -07:00
@@ -203,7 +203,7 @@
 #define VGA_SAVE_CMAP  16 /* save/restore color map/DAC   */
 
 struct vgastate {
-	caddr_t vgabase;	/* mmio base, if supported 		   */
+	void __iomem *vgabase;	/* mmio base, if supported 		   */
 	unsigned long membase;	/* VGA window base, 0 for default - 0xA000 */
 	__u32 memsize;		/* VGA window size, 0 for default 64K	   */
 	__u32 flags;		/* what state[s] to save (see VGA_SAVE_*)  */
@@ -238,23 +238,23 @@
 	outw(VGA_OUT16VAL (val, reg), port);
 }
 
-static inline unsigned char vga_mm_r (caddr_t regbase, unsigned short port)
+static inline unsigned char vga_mm_r (void __iomem *regbase, unsigned short port)
 {
 	return readb (regbase + port);
 }
 
-static inline void vga_mm_w (caddr_t regbase, unsigned short port, unsigned char val)
+static inline void vga_mm_w (void __iomem *regbase, unsigned short port, unsigned char val)
 {
 	writeb (val, regbase + port);
 }
 
-static inline void vga_mm_w_fast (caddr_t regbase, unsigned short port,
+static inline void vga_mm_w_fast (void __iomem *regbase, unsigned short port,
 				  unsigned char reg, unsigned char val)
 {
 	writew (VGA_OUT16VAL (val, reg), regbase + port);
 }
 
-static inline unsigned char vga_r (caddr_t regbase, unsigned short port)
+static inline unsigned char vga_r (void __iomem *regbase, unsigned short port)
 {
 	if (regbase)
 		return vga_mm_r (regbase, port);
@@ -262,7 +262,7 @@
 		return vga_io_r (port);
 }
 
-static inline void vga_w (caddr_t regbase, unsigned short port, unsigned char val)
+static inline void vga_w (void __iomem *regbase, unsigned short port, unsigned char val)
 {
 	if (regbase)
 		vga_mm_w (regbase, port, val);
@@ -271,7 +271,7 @@
 }
 
 
-static inline void vga_w_fast (caddr_t regbase, unsigned short port,
+static inline void vga_w_fast (void __iomem *regbase, unsigned short port,
 			       unsigned char reg, unsigned char val)
 {
 	if (regbase)
@@ -285,13 +285,13 @@
  * VGA CRTC register read/write
  */
  
-static inline unsigned char vga_rcrt (caddr_t regbase, unsigned char reg)
+static inline unsigned char vga_rcrt (void __iomem *regbase, unsigned char reg)
 {
         vga_w (regbase, VGA_CRT_IC, reg);
         return vga_r (regbase, VGA_CRT_DC);
 }
 
-static inline void vga_wcrt (caddr_t regbase, unsigned char reg, unsigned char val)
+static inline void vga_wcrt (void __iomem *regbase, unsigned char reg, unsigned char val)
 {
 #ifdef VGA_OUTW_WRITE
 	vga_w_fast (regbase, VGA_CRT_IC, reg, val);
@@ -317,13 +317,13 @@
 #endif /* VGA_OUTW_WRITE */
 }
 
-static inline unsigned char vga_mm_rcrt (caddr_t regbase, unsigned char reg)
+static inline unsigned char vga_mm_rcrt (void __iomem *regbase, unsigned char reg)
 {
         vga_mm_w (regbase, VGA_CRT_IC, reg);
         return vga_mm_r (regbase, VGA_CRT_DC);
 }
 
-static inline void vga_mm_wcrt (caddr_t regbase, unsigned char reg, unsigned char val)
+static inline void vga_mm_wcrt (void __iomem *regbase, unsigned char reg, unsigned char val)
 {
 #ifdef VGA_OUTW_WRITE
 	vga_mm_w_fast (regbase, VGA_CRT_IC, reg, val);
@@ -338,13 +338,13 @@
  * VGA sequencer register read/write
  */
  
-static inline unsigned char vga_rseq (caddr_t regbase, unsigned char reg)
+static inline unsigned char vga_rseq (void __iomem *regbase, unsigned char reg)
 {
         vga_w (regbase, VGA_SEQ_I, reg);
         return vga_r (regbase, VGA_SEQ_D);
 }
 
-static inline void vga_wseq (caddr_t regbase, unsigned char reg, unsigned char val)
+static inline void vga_wseq (void __iomem *regbase, unsigned char reg, unsigned char val)
 {
 #ifdef VGA_OUTW_WRITE
 	vga_w_fast (regbase, VGA_SEQ_I, reg, val);
@@ -370,13 +370,13 @@
 #endif /* VGA_OUTW_WRITE */
 }
 
-static inline unsigned char vga_mm_rseq (caddr_t regbase, unsigned char reg)
+static inline unsigned char vga_mm_rseq (void __iomem *regbase, unsigned char reg)
 {
         vga_mm_w (regbase, VGA_SEQ_I, reg);
         return vga_mm_r (regbase, VGA_SEQ_D);
 }
 
-static inline void vga_mm_wseq (caddr_t regbase, unsigned char reg, unsigned char val)
+static inline void vga_mm_wseq (void __iomem *regbase, unsigned char reg, unsigned char val)
 {
 #ifdef VGA_OUTW_WRITE
 	vga_mm_w_fast (regbase, VGA_SEQ_I, reg, val);
@@ -390,13 +390,13 @@
  * VGA graphics controller register read/write
  */
  
-static inline unsigned char vga_rgfx (caddr_t regbase, unsigned char reg)
+static inline unsigned char vga_rgfx (void __iomem *regbase, unsigned char reg)
 {
         vga_w (regbase, VGA_GFX_I, reg);
         return vga_r (regbase, VGA_GFX_D);
 }
 
-static inline void vga_wgfx (caddr_t regbase, unsigned char reg, unsigned char val)
+static inline void vga_wgfx (void __iomem *regbase, unsigned char reg, unsigned char val)
 {
 #ifdef VGA_OUTW_WRITE
 	vga_w_fast (regbase, VGA_GFX_I, reg, val);
@@ -422,13 +422,13 @@
 #endif /* VGA_OUTW_WRITE */
 }
 
-static inline unsigned char vga_mm_rgfx (caddr_t regbase, unsigned char reg)
+static inline unsigned char vga_mm_rgfx (void __iomem *regbase, unsigned char reg)
 {
         vga_mm_w (regbase, VGA_GFX_I, reg);
         return vga_mm_r (regbase, VGA_GFX_D);
 }
 
-static inline void vga_mm_wgfx (caddr_t regbase, unsigned char reg, unsigned char val)
+static inline void vga_mm_wgfx (void __iomem *regbase, unsigned char reg, unsigned char val)
 {
 #ifdef VGA_OUTW_WRITE
 	vga_mm_w_fast (regbase, VGA_GFX_I, reg, val);
@@ -443,13 +443,13 @@
  * VGA attribute controller register read/write
  */
  
-static inline unsigned char vga_rattr (caddr_t regbase, unsigned char reg)
+static inline unsigned char vga_rattr (void __iomem *regbase, unsigned char reg)
 {
         vga_w (regbase, VGA_ATT_IW, reg);
         return vga_r (regbase, VGA_ATT_R);
 }
 
-static inline void vga_wattr (caddr_t regbase, unsigned char reg, unsigned char val)
+static inline void vga_wattr (void __iomem *regbase, unsigned char reg, unsigned char val)
 {
         vga_w (regbase, VGA_ATT_IW, reg);
         vga_w (regbase, VGA_ATT_W, val);
@@ -467,13 +467,13 @@
         vga_io_w (VGA_ATT_W, val);
 }
 
-static inline unsigned char vga_mm_rattr (caddr_t regbase, unsigned char reg)
+static inline unsigned char vga_mm_rattr (void __iomem *regbase, unsigned char reg)
 {
         vga_mm_w (regbase, VGA_ATT_IW, reg);
         return vga_mm_r (regbase, VGA_ATT_R);
 }
 
-static inline void vga_mm_wattr (caddr_t regbase, unsigned char reg, unsigned char val)
+static inline void vga_mm_wattr (void __iomem *regbase, unsigned char reg, unsigned char val)
 {
         vga_mm_w (regbase, VGA_ATT_IW, reg);
         vga_mm_w (regbase, VGA_ATT_W, val);
diff -Nru a/init/Kconfig b/init/Kconfig
--- a/init/Kconfig	2004-10-18 14:56:49 -07:00
+++ b/init/Kconfig	2004-10-18 14:56:49 -07:00
@@ -1,4 +1,3 @@
-
 menu "Code maturity level options"
 
 config EXPERIMENTAL
@@ -53,9 +52,18 @@
 
 endmenu
 
-
 menu "General setup"
 
+config LOCALVERSION
+	string "Local version - append to kernel release"
+	help
+	  Append an extra string to the end of your kernel version.
+	  This will show up when you type uname, for example.
+	  The string you set here will be appended after the contents of
+	  any files with a filename matching localversion* in your
+	  object and source tree, in that order.  Your total string can
+	  be a maximum of 64 characters.
+
 config SWAP
 	bool "Support for paging of anonymous memory (swap)"
 	depends on MMU
@@ -123,7 +131,7 @@
 	  process and it's parent. Note that this file format is incompatible
 	  with previous v0/v1/v2 file formats, so you will need updated tools
 	  for processing it. A preliminary version of these tools is available
-	  at <http://http://www.de.kernel.org/pub/linux/utils/acct/>.
+	  at <http://www.physik3.uni-rostock.de/tim/kernel/utils/acct/>.
 
 config SYSCTL
 	bool "Sysctl support"
@@ -285,8 +293,21 @@
 
 	  If unsure, say N.
 
+config SHMEM
+	default y
+	bool "Use full shmem filesystem" if EMBEDDED && MMU
+	help
+	  The shmem is an internal filesystem used to manage shared memory.
+	  It is backed by swap and manages resource limits. It is also exported
+	  to userspace as tmpfs if TMPFS is enabled. Disabling this
+	  option replaces shmem and tmpfs with the much simpler ramfs code,
+	  which may be appropriate on small systems without swap.
+
 endmenu		# General setup
 
+config TINY_SHMEM
+	default !SHMEM
+	bool
 
 menu "Loadable module support"
 
diff -Nru a/init/do_mounts_rd.c b/init/do_mounts_rd.c
--- a/init/do_mounts_rd.c	2004-10-18 14:56:48 -07:00
+++ b/init/do_mounts_rd.c	2004-10-18 14:56:48 -07:00
@@ -122,7 +122,8 @@
 		printk(KERN_NOTICE
 		       "RAMDISK: ext2 filesystem found at block %d\n",
 		       start_block);
-		nblocks = le32_to_cpu(ext2sb->s_blocks_count);
+		nblocks = le32_to_cpu(ext2sb->s_blocks_count) <<
+			le32_to_cpu(ext2sb->s_log_block_size);
 		goto done;
 	}
 
@@ -173,10 +174,15 @@
 	}
 
 	/*
-	 * NOTE NOTE: nblocks suppose that the blocksize is BLOCK_SIZE, so
-	 * rd_load_image will work only with filesystem BLOCK_SIZE wide!
-	 * So make sure to use 1k blocksize while generating ext2fs
-	 * ramdisk-images.
+	 * NOTE NOTE: nblocks is not actually blocks but
+	 * the number of kibibytes of data to load into a ramdisk.
+	 * So any ramdisk block size that is a multiple of 1KiB should
+	 * work when the appropriate ramdisk_blocksize is specified
+	 * on the command line.
+	 *
+	 * The default ramdisk_blocksize is 1KiB and it is generally
+	 * silly to use anything else, so make sure to use 1KiB
+	 * blocksize while generating ext2fs ramdisk-images.
 	 */
 	if (sys_ioctl(out_fd, BLKGETSIZE, (unsigned long)&rd_blocks) < 0)
 		rd_blocks = 0;
@@ -184,7 +190,7 @@
 		rd_blocks >>= 1;
 
 	if (nblocks > rd_blocks) {
-		printk("RAMDISK: image too big! (%d/%ld blocks)\n",
+		printk("RAMDISK: image too big! (%dKiB/%ldKiB)\n",
 		       nblocks, rd_blocks);
 		goto done;
 	}
@@ -211,7 +217,7 @@
 		goto done;
 	}
 
-	printk(KERN_NOTICE "RAMDISK: Loading %d blocks [%ld disk%s] into ram disk... ", 
+	printk(KERN_NOTICE "RAMDISK: Loading %dKiB [%ld disk%s] into ram disk... ",
 		nblocks, ((nblocks-1)/devblocks)+1, nblocks>devblocks ? "s" : "");
 	for (i = 0, disk = 1; i < nblocks; i++) {
 		if (i && (i % devblocks == 0)) {
diff -Nru a/init/main.c b/init/main.c
--- a/init/main.c	2004-10-18 14:56:16 -07:00
+++ b/init/main.c	2004-10-18 14:56:16 -07:00
@@ -31,6 +31,7 @@
 #include <linux/tty.h>
 #include <linux/gfp.h>
 #include <linux/percpu.h>
+#include <linux/kmod.h>
 #include <linux/kernel_stat.h>
 #include <linux/security.h>
 #include <linux/workqueue.h>
@@ -93,6 +94,11 @@
 extern void populate_rootfs(void);
 extern void driver_init(void);
 extern void prepare_namespace(void);
+#ifdef	CONFIG_ACPI
+extern void acpi_early_init(void);
+#else
+static inline void acpi_early_init(void) { }
+#endif
 
 #ifdef CONFIG_TC
 extern void tc_init(void);
@@ -104,8 +110,8 @@
 /*
  * Boot command-line arguments
  */
-#define MAX_INIT_ARGS 8
-#define MAX_INIT_ENVS 8
+#define MAX_INIT_ARGS 32
+#define MAX_INIT_ENVS 32
 
 extern void time_init(void);
 /* Default late time init is NULL. archs can override this later. */
@@ -150,8 +156,6 @@
 char * envp_init[MAX_INIT_ENVS+2] = { "HOME=/", "TERM=linux", NULL, };
 static const char *panic_later, *panic_param;
 
-__setup("profile=", profile_setup);
-
 static int __init obsolete_checksetup(char *line)
 {
 	struct obs_kernel_param *p;
@@ -178,15 +182,28 @@
 	return 0;
 }
 
-/* this should be approx 2 Bo*oMips to start (note initial shift), and will
-   still work even if initially too large, it will just take slightly longer */
+static unsigned long preset_lpj;
+static int __init lpj_setup(char *str)
+{
+	preset_lpj = simple_strtoul(str,NULL,0);
+	return 1;
+}
+
+__setup("lpj=", lpj_setup);
+
+/*
+ * This should be approx 2 Bo*oMips to start (note initial shift), and will
+ * still work even if initially too large, it will just take slightly longer
+ */
 unsigned long loops_per_jiffy = (1<<12);
 
 EXPORT_SYMBOL(loops_per_jiffy);
 
-/* This is the number of bits of precision for the loops_per_jiffy.  Each
-   bit takes on average 1.5/HZ seconds.  This (like the original) is a little
-   better than 1% */
+/*
+ * This is the number of bits of precision for the loops_per_jiffy.  Each
+ * bit takes on average 1.5/HZ seconds.  This (like the original) is a little
+ * better than 1%
+ */
 #define LPS_PREC 8
 
 void __devinit calibrate_delay(void)
@@ -194,40 +211,53 @@
 	unsigned long ticks, loopbit;
 	int lps_precision = LPS_PREC;
 
-	loops_per_jiffy = (1<<12);
+	if (preset_lpj) {
+		loops_per_jiffy = preset_lpj;
+		printk("Calibrating delay loop (skipped)... "
+			"%lu.%02lu BogoMIPS preset\n",
+			loops_per_jiffy/(500000/HZ),
+			(loops_per_jiffy/(5000/HZ)) % 100);
+	} else {
+		loops_per_jiffy = (1<<12);
 
-	printk("Calibrating delay loop... ");
-	while ((loops_per_jiffy <<= 1) != 0) {
-		/* wait for "start of" clock tick */
-		ticks = jiffies;
-		while (ticks == jiffies)
-			/* nothing */;
-		/* Go .. */
-		ticks = jiffies;
-		__delay(loops_per_jiffy);
-		ticks = jiffies - ticks;
-		if (ticks)
-			break;
-	}
+		printk(KERN_DEBUG "Calibrating delay loop... ");
+		while ((loops_per_jiffy <<= 1) != 0) {
+			/* wait for "start of" clock tick */
+			ticks = jiffies;
+			while (ticks == jiffies)
+				/* nothing */;
+			/* Go .. */
+			ticks = jiffies;
+			__delay(loops_per_jiffy);
+			ticks = jiffies - ticks;
+			if (ticks)
+				break;
+		}
+
+		/*
+		 * Do a binary approximation to get loops_per_jiffy set to
+		 * equal one clock (up to lps_precision bits)
+		 */
+		loops_per_jiffy >>= 1;
+		loopbit = loops_per_jiffy;
+		while (lps_precision-- && (loopbit >>= 1)) {
+			loops_per_jiffy |= loopbit;
+			ticks = jiffies;
+			while (ticks == jiffies)
+				/* nothing */;
+			ticks = jiffies;
+			__delay(loops_per_jiffy);
+			if (jiffies != ticks)	/* longer than 1 tick */
+				loops_per_jiffy &= ~loopbit;
+		}
 
-/* Do a binary approximation to get loops_per_jiffy set to equal one clock
-   (up to lps_precision bits) */
-	loops_per_jiffy >>= 1;
-	loopbit = loops_per_jiffy;
-	while ( lps_precision-- && (loopbit >>= 1) ) {
-		loops_per_jiffy |= loopbit;
-		ticks = jiffies;
-		while (ticks == jiffies);
-		ticks = jiffies;
-		__delay(loops_per_jiffy);
-		if (jiffies != ticks)	/* longer than 1 tick */
-			loops_per_jiffy &= ~loopbit;
+		/* Round the value and print it */
+		printk("%lu.%02lu BogoMIPS (lpj=%lu)\n",
+			loops_per_jiffy/(500000/HZ),
+			(loops_per_jiffy/(5000/HZ)) % 100,
+			loops_per_jiffy);
 	}
 
-/* Round the value and print it */	
-	printk("%lu.%02lu BogoMIPS\n",
-		loops_per_jiffy/(500000/HZ),
-		(loops_per_jiffy/(5000/HZ)) % 100);
 }
 
 static int __init debug_kernel(char *str)
@@ -249,20 +279,26 @@
 __setup("debug", debug_kernel);
 __setup("quiet", quiet_kernel);
 
-/* Unknown boot options get handed to init, unless they look like
-   failed parameters */
+/*
+ * Unknown boot options get handed to init, unless they look like
+ * failed parameters
+ */
 static int __init unknown_bootoption(char *param, char *val)
 {
 	/* Change NUL term back to "=", to make "param" the whole string. */
-	if (val)
-		val[-1] = '=';
+	if (val) {
+		if (val[-1] == '"') val[-2] = '=';
+		else val[-1] = '=';
+	}
 
 	/* Handle obsolete-style parameters */
 	if (obsolete_checksetup(param))
 		return 0;
 
-	/* Preemptive maintenance for "why didn't my mispelled command
-           line work?" */
+	/*
+	 * Preemptive maintenance for "why didn't my mispelled command
+	 * line work?"
+	 */
 	if (strchr(param, '.') && (!val || strchr(param, '.') < val)) {
 		printk(KERN_ERR "Unknown boot option `%s': ignoring\n", param);
 		return 0;
@@ -302,7 +338,8 @@
 	unsigned int i;
 
 	execute_command = str;
-	/* In case LILO is going to boot us with default command line,
+	/*
+	 * In case LILO is going to boot us with default command line,
 	 * it prepends "auto" before the whole cmdline which makes
 	 * the shell think it should execute a script with such name.
 	 * So we ignore all arguments entered _before_ init=... [MJ]
@@ -465,7 +502,6 @@
 	 * time - but meanwhile we still have a functioning scheduler.
 	 */
 	sched_init();
-
 	build_all_zonelists();
 	page_alloc_init();
 	printk("Kernel command line: %s\n", saved_command_line);
@@ -530,12 +566,7 @@
 #endif
 	check_bugs();
 
-	/* 
-	 *	We count on the initial thread going ok 
-	 *	Like idlers init is an unlocked kernel thread, which will
-	 *	make syscalls (and thus be locked).
-	 */
-	init_idle(current, smp_processor_id());
+	acpi_early_init(); /* before LAPIC and SMP init */
 
 	/* Do the rest non-__init'ed, we're now alive */
 	rest_init();
@@ -598,6 +629,10 @@
  */
 static void __init do_basic_setup(void)
 {
+	/* drivers will send hotplug events */
+	init_workqueues();
+	usermodehelper_init();
+
 	driver_init();
 
 #ifdef CONFIG_SYSCTL
@@ -607,7 +642,6 @@
 	/* Networking initialization needs a process context */ 
 	sock_init();
 
-	init_workqueues();
 	do_initcalls();
 }
 
diff -Nru a/ipc/mqueue.c b/ipc/mqueue.c
--- a/ipc/mqueue.c	2004-10-18 14:56:32 -07:00
+++ b/ipc/mqueue.c	2004-10-18 14:56:32 -07:00
@@ -828,7 +828,7 @@
 	/* First try to allocate memory, before doing anything with
 	 * existing queues. */
 	msg_ptr = load_msg(u_msg_ptr, msg_len);
-	if (unlikely(IS_ERR(msg_ptr))) {
+	if (IS_ERR(msg_ptr)) {
 		ret = PTR_ERR(msg_ptr);
 		goto out_fput;
 	}
diff -Nru a/ipc/msg.c b/ipc/msg.c
--- a/ipc/msg.c	2004-10-18 14:55:53 -07:00
+++ b/ipc/msg.c	2004-10-18 14:55:53 -07:00
@@ -100,14 +100,14 @@
 	msq->q_perm.security = NULL;
 	retval = security_msg_queue_alloc(msq);
 	if (retval) {
-		ipc_rcu_free(msq, sizeof(*msq));
+		ipc_rcu_putref(msq);
 		return retval;
 	}
 
 	id = ipc_addid(&msg_ids, &msq->q_perm, msg_ctlmni);
 	if(id == -1) {
 		security_msg_queue_free(msq);
-		ipc_rcu_free(msq, sizeof(*msq));
+		ipc_rcu_putref(msq);
 		return -ENOSPC;
 	}
 
@@ -163,8 +163,10 @@
 		
 		msr = list_entry(tmp,struct msg_receiver,r_list);
 		tmp = tmp->next;
-		msr->r_msg = ERR_PTR(res);
+		msr->r_msg = NULL;
 		wake_up_process(msr->r_tsk);
+		smp_mb();
+		msr->r_msg = ERR_PTR(res);
 	}
 }
 /* 
@@ -193,7 +195,7 @@
 	}
 	atomic_sub(msq->q_cbytes, &msg_bytes);
 	security_msg_queue_free(msq);
-	ipc_rcu_free(msq, sizeof(struct msg_queue));
+	ipc_rcu_putref(msq);
 }
 
 asmlinkage long sys_msgget (key_t key, int msgflg)
@@ -525,13 +527,17 @@
 		   !security_msg_queue_msgrcv(msq, msg, msr->r_tsk, msr->r_msgtype, msr->r_mode)) {
 			list_del(&msr->r_list);
 			if(msr->r_maxsize < msg->m_ts) {
-				msr->r_msg = ERR_PTR(-E2BIG);
+				msr->r_msg = NULL;
 				wake_up_process(msr->r_tsk);
+				smp_mb();
+				msr->r_msg = ERR_PTR(-E2BIG);
 			} else {
-				msr->r_msg = msg;
+				msr->r_msg = NULL;
 				msq->q_lrpid = msr->r_tsk->pid;
 				msq->q_rtime = get_seconds();
 				wake_up_process(msr->r_tsk);
+				smp_mb();
+				msr->r_msg = msg;
 				return 1;
 			}
 		}
@@ -564,43 +570,49 @@
 	err=-EINVAL;
 	if(msq==NULL)
 		goto out_free;
-retry:
+
 	err= -EIDRM;
 	if (msg_checkid(msq,msqid))
 		goto out_unlock_free;
 
-	err=-EACCES;
-	if (ipcperms(&msq->q_perm, S_IWUGO)) 
-		goto out_unlock_free;
+	for (;;) {
+		struct msg_sender s;
 
-	err = security_msg_queue_msgsnd(msq, msg, msgflg);
-	if (err)
-		goto out_unlock_free;
+		err=-EACCES;
+		if (ipcperms(&msq->q_perm, S_IWUGO))
+			goto out_unlock_free;
 
-	if(msgsz + msq->q_cbytes > msq->q_qbytes ||
-		1 + msq->q_qnum > msq->q_qbytes) {
-		struct msg_sender s;
+		err = security_msg_queue_msgsnd(msq, msg, msgflg);
+		if (err)
+			goto out_unlock_free;
+
+		if(msgsz + msq->q_cbytes <= msq->q_qbytes &&
+				1 + msq->q_qnum <= msq->q_qbytes) {
+			break;
+		}
 
+		/* queue full, wait: */
 		if(msgflg&IPC_NOWAIT) {
 			err=-EAGAIN;
 			goto out_unlock_free;
 		}
 		ss_add(msq, &s);
+		ipc_rcu_getref(msq);
 		msg_unlock(msq);
 		schedule();
-		current->state= TASK_RUNNING;
 
-		msq = msg_lock(msqid);
-		err = -EIDRM;
-		if(msq==NULL)
-			goto out_free;
+		ipc_lock_by_ptr(&msq->q_perm);
+		ipc_rcu_putref(msq);
+		if (msq->q_perm.deleted) {
+			err = -EIDRM;
+			goto out_unlock_free;
+		}
 		ss_del(&s);
 		
 		if (signal_pending(current)) {
-			err=-EINTR;
+			err=-ERESTARTNOHAND;
 			goto out_unlock_free;
 		}
-		goto retry;
 	}
 
 	msq->q_lspid = current->tgid;
@@ -649,10 +661,7 @@
 			    long msgtyp, int msgflg)
 {
 	struct msg_queue *msq;
-	struct msg_receiver msr_d;
-	struct list_head* tmp;
-	struct msg_msg* msg, *found_msg;
-	int err;
+	struct msg_msg *msg;
 	int mode;
 
 	if (msqid < 0 || (long) msgsz < 0)
@@ -662,62 +671,57 @@
 	msq = msg_lock(msqid);
 	if(msq==NULL)
 		return -EINVAL;
-retry:
-	err = -EIDRM;
+
+	msg = ERR_PTR(-EIDRM);
 	if (msg_checkid(msq,msqid))
 		goto out_unlock;
 
-	err=-EACCES;
-	if (ipcperms (&msq->q_perm, S_IRUGO))
-		goto out_unlock;
+	for (;;) {
+		struct msg_receiver msr_d;
+		struct list_head* tmp;
 
-	tmp = msq->q_messages.next;
-	found_msg=NULL;
-	while (tmp != &msq->q_messages) {
-		msg = list_entry(tmp,struct msg_msg,m_list);
-		if(testmsg(msg,msgtyp,mode) &&
-		   !security_msg_queue_msgrcv(msq, msg, current, msgtyp, mode)) {
-			found_msg = msg;
-			if(mode == SEARCH_LESSEQUAL && msg->m_type != 1) {
-				found_msg=msg;
-				msgtyp=msg->m_type-1;
-			} else {
-				found_msg=msg;
-				break;
-			}
-		}
-		tmp = tmp->next;
-	}
-	if(found_msg) {
-		msg=found_msg;
-		if ((msgsz < msg->m_ts) && !(msgflg & MSG_NOERROR)) {
-			err=-E2BIG;
+		msg = ERR_PTR(-EACCES);
+		if (ipcperms (&msq->q_perm, S_IRUGO))
 			goto out_unlock;
+
+		msg = ERR_PTR(-EAGAIN);
+		tmp = msq->q_messages.next;
+		while (tmp != &msq->q_messages) {
+			struct msg_msg *walk_msg;
+			walk_msg = list_entry(tmp,struct msg_msg,m_list);
+			if(testmsg(walk_msg,msgtyp,mode) &&
+			   !security_msg_queue_msgrcv(msq, walk_msg, current, msgtyp, mode)) {
+				msg = walk_msg;
+				if(mode == SEARCH_LESSEQUAL && walk_msg->m_type != 1) {
+					msg=walk_msg;
+					msgtyp=walk_msg->m_type-1;
+				} else {
+					msg=walk_msg;
+					break;
+				}
+			}
+			tmp = tmp->next;
 		}
-		list_del(&msg->m_list);
-		msq->q_qnum--;
-		msq->q_rtime = get_seconds();
-		msq->q_lrpid = current->tgid;
-		msq->q_cbytes -= msg->m_ts;
-		atomic_sub(msg->m_ts,&msg_bytes);
-		atomic_dec(&msg_hdrs);
-		ss_wakeup(&msq->q_senders,0);
-		msg_unlock(msq);
-out_success:
-		msgsz = (msgsz > msg->m_ts) ? msg->m_ts : msgsz;
-		if (put_user (msg->m_type, &msgp->mtype) ||
-		    store_msg(msgp->mtext, msg, msgsz)) {
-			    msgsz = -EFAULT;
+		if(!IS_ERR(msg)) {
+			/* Found a suitable message. Unlink it from the queue. */
+			if ((msgsz < msg->m_ts) && !(msgflg & MSG_NOERROR)) {
+				msg = ERR_PTR(-E2BIG);
+				goto out_unlock;
+			}
+			list_del(&msg->m_list);
+			msq->q_qnum--;
+			msq->q_rtime = get_seconds();
+			msq->q_lrpid = current->tgid;
+			msq->q_cbytes -= msg->m_ts;
+			atomic_sub(msg->m_ts,&msg_bytes);
+			atomic_dec(&msg_hdrs);
+			ss_wakeup(&msq->q_senders,0);
+			msg_unlock(msq);
+			break;
 		}
-		free_msg(msg);
-		return msgsz;
-	} else
-	{
-		/* no message waiting. Prepare for pipelined
-		 * receive.
-		 */
+		/* No message waiting. Wait for a message */
 		if (msgflg & IPC_NOWAIT) {
-			err=-ENOMSG;
+			msg = ERR_PTR(-ENOMSG);
 			goto out_unlock;
 		}
 		list_add_tail(&msr_d.r_list,&msq->q_receivers);
@@ -727,52 +731,76 @@
 		if(msgflg & MSG_NOERROR)
 			msr_d.r_maxsize = INT_MAX;
 		 else
-		 	msr_d.r_maxsize = msgsz;
+			msr_d.r_maxsize = msgsz;
 		msr_d.r_msg = ERR_PTR(-EAGAIN);
 		current->state = TASK_INTERRUPTIBLE;
 		msg_unlock(msq);
 
 		schedule();
 
-		/*
-		 * The below optimisation is buggy.  A sleeping thread that is
-		 * woken up checks if it got a message and if so, copies it to
-		 * userspace and just returns without taking any locks.
-		 * But this return to user space can be faster than the message
-		 * send, and if the receiver immediately exits the
-		 * wake_up_process performed by the sender will oops.
+		/* Lockless receive, part 1:
+		 * Disable preemption.  We don't hold a reference to the queue
+		 * and getting a reference would defeat the idea of a lockless
+		 * operation, thus the code relies on rcu to guarantee the
+		 * existance of msq:
+		 * Prior to destruction, expunge_all(-EIRDM) changes r_msg.
+		 * Thus if r_msg is -EAGAIN, then the queue not yet destroyed.
+		 * rcu_read_lock() prevents preemption between reading r_msg
+		 * and the spin_lock() inside ipc_lock_by_ptr().
+		 */
+		rcu_read_lock();
+
+		/* Lockless receive, part 2:
+		 * Wait until pipelined_send or expunge_all are outside of
+		 * wake_up_process(). There is a race with exit(), see
+		 * ipc/mqueue.c for the details.
 		 */
-#if 0
 		msg = (struct msg_msg*) msr_d.r_msg;
-		if(!IS_ERR(msg)) 
-			goto out_success;
-#endif
+		while (msg == NULL) {
+			cpu_relax();
+			msg = (struct msg_msg*) msr_d.r_msg;
+		}
 
-		msq = msg_lock(msqid);
+		/* Lockless receive, part 3:
+		 * If there is a message or an error then accept it without
+		 * locking.
+		 */
+		if(msg != ERR_PTR(-EAGAIN)) {
+			rcu_read_unlock();
+			break;
+		}
+
+		/* Lockless receive, part 3:
+		 * Acquire the queue spinlock.
+		 */
+		ipc_lock_by_ptr(&msq->q_perm);
+		rcu_read_unlock();
+
+		/* Lockless receive, part 4:
+		 * Repeat test after acquiring the spinlock.
+		 */
 		msg = (struct msg_msg*)msr_d.r_msg;
-		if(!IS_ERR(msg)) {
-			/* our message arived while we waited for
-			 * the spinlock. Process it.
-			 */
-			if(msq)
-				msg_unlock(msq);
-			goto out_success;
-		}
-		err = PTR_ERR(msg);
-		if(err == -EAGAIN) {
-			if(!msq)
-				BUG();
-			list_del(&msr_d.r_list);
-			if (signal_pending(current))
-				err=-EINTR;
-			 else
-				goto retry;
+		if(msg != ERR_PTR(-EAGAIN))
+			goto out_unlock;
+
+		list_del(&msr_d.r_list);
+		if (signal_pending(current)) {
+			msg = ERR_PTR(-ERESTARTNOHAND);
+out_unlock:
+			msg_unlock(msq);
+			break;
 		}
 	}
-out_unlock:
-	if(msq)
-		msg_unlock(msq);
-	return err;
+	if (IS_ERR(msg))
+       		return PTR_ERR(msg);
+
+	msgsz = (msgsz > msg->m_ts) ? msg->m_ts : msgsz;
+	if (put_user (msg->m_type, &msgp->mtype) ||
+	    store_msg(msgp->mtext, msg, msgsz)) {
+		    msgsz = -EFAULT;
+	}
+	free_msg(msg);
+	return msgsz;
 }
 
 #ifdef CONFIG_PROC_FS
diff -Nru a/ipc/sem.c b/ipc/sem.c
--- a/ipc/sem.c	2004-10-18 14:56:28 -07:00
+++ b/ipc/sem.c	2004-10-18 14:56:28 -07:00
@@ -179,14 +179,14 @@
 	sma->sem_perm.security = NULL;
 	retval = security_sem_alloc(sma);
 	if (retval) {
-		ipc_rcu_free(sma, size);
+		ipc_rcu_putref(sma);
 		return retval;
 	}
 
 	id = ipc_addid(&sem_ids, &sma->sem_perm, sc_semmni);
 	if(id == -1) {
 		security_sem_free(sma);
-		ipc_rcu_free(sma, size);
+		ipc_rcu_putref(sma);
 		return -ENOSPC;
 	}
 	used_sems += nsems;
@@ -241,25 +241,6 @@
 	return err;
 }
 
-/* doesn't acquire the sem_lock on error! */
-static int sem_revalidate(int semid, struct sem_array* sma, int nsems, short flg)
-{
-	struct sem_array* smanew;
-
-	smanew = sem_lock(semid);
-	if(smanew==NULL)
-		return -EIDRM;
-	if(smanew != sma || sem_checkid(sma,semid) || sma->sem_nsems != nsems) {
-		sem_unlock(smanew);
-		return -EIDRM;
-	}
-
-	if (flg && ipcperms(&sma->sem_perm, flg)) {
-		sem_unlock(smanew);
-		return -EACCES;
-	}
-	return 0;
-}
 /* Manage the doubly linked list sma->sem_pending as a FIFO:
  * insert new queue elements at the tail sma->sem_pending_last.
  */
@@ -473,7 +454,7 @@
 	used_sems -= sma->sem_nsems;
 	size = sizeof (*sma) + sma->sem_nsems * sizeof (struct sem);
 	security_sem_free(sma);
-	ipc_rcu_free(sma, size);
+	ipc_rcu_putref(sma);
 }
 
 static unsigned long copy_semid_to_user(void __user *buf, struct semid64_ds *in, int version)
@@ -614,13 +595,24 @@
 		int i;
 
 		if(nsems > SEMMSL_FAST) {
+			ipc_rcu_getref(sma);
 			sem_unlock(sma);			
+
 			sem_io = ipc_alloc(sizeof(ushort)*nsems);
-			if(sem_io == NULL)
+			if(sem_io == NULL) {
+				ipc_lock_by_ptr(&sma->sem_perm);
+				ipc_rcu_putref(sma);
+				sem_unlock(sma);
 				return -ENOMEM;
-			err = sem_revalidate(semid, sma, nsems, S_IRUGO);
-			if(err)
+			}
+
+			ipc_lock_by_ptr(&sma->sem_perm);
+			ipc_rcu_putref(sma);
+			if (sma->sem_perm.deleted) {
+				sem_unlock(sma);
+				err = -EIDRM;
 				goto out_free;
+			}
 		}
 
 		for (i = 0; i < sma->sem_nsems; i++)
@@ -636,28 +628,43 @@
 		int i;
 		struct sem_undo *un;
 
+		ipc_rcu_getref(sma);
 		sem_unlock(sma);
 
 		if(nsems > SEMMSL_FAST) {
 			sem_io = ipc_alloc(sizeof(ushort)*nsems);
-			if(sem_io == NULL)
+			if(sem_io == NULL) {
+				ipc_lock_by_ptr(&sma->sem_perm);
+				ipc_rcu_putref(sma);
+				sem_unlock(sma);
 				return -ENOMEM;
+			}
 		}
 
 		if (copy_from_user (sem_io, arg.array, nsems*sizeof(ushort))) {
+			ipc_lock_by_ptr(&sma->sem_perm);
+			ipc_rcu_putref(sma);
+			sem_unlock(sma);
 			err = -EFAULT;
 			goto out_free;
 		}
 
 		for (i = 0; i < nsems; i++) {
 			if (sem_io[i] > SEMVMX) {
+				ipc_lock_by_ptr(&sma->sem_perm);
+				ipc_rcu_putref(sma);
+				sem_unlock(sma);
 				err = -ERANGE;
 				goto out_free;
 			}
 		}
-		err = sem_revalidate(semid, sma, nsems, S_IWUGO);
-		if(err)
+		ipc_lock_by_ptr(&sma->sem_perm);
+		ipc_rcu_putref(sma);
+		if (sma->sem_perm.deleted) {
+			sem_unlock(sma);
+			err = -EIDRM;
 			goto out_free;
+		}
 
 		for (i = 0; i < nsems; i++)
 			sma->sem_base[i].semval = sem_io[i];
@@ -977,11 +984,16 @@
 		goto out;
 	}
 	nsems = sma->sem_nsems;
+	ipc_rcu_getref(sma);
 	sem_unlock(sma);
 
 	new = (struct sem_undo *) kmalloc(sizeof(struct sem_undo) + sizeof(short)*nsems, GFP_KERNEL);
-	if (!new)
+	if (!new) {
+		ipc_lock_by_ptr(&sma->sem_perm);
+		ipc_rcu_putref(sma);
+		sem_unlock(sma);
 		return ERR_PTR(-ENOMEM);
+	}
 	memset(new, 0, sizeof(struct sem_undo) + sizeof(short)*nsems);
 	new->semadj = (short *) &new[1];
 	new->semid = semid;
@@ -991,13 +1003,18 @@
 	if (un) {
 		unlock_semundo();
 		kfree(new);
+		ipc_lock_by_ptr(&sma->sem_perm);
+		ipc_rcu_putref(sma);
+		sem_unlock(sma);
 		goto out;
 	}
-	error = sem_revalidate(semid, sma, nsems, 0);
-	if (error) {
+	ipc_lock_by_ptr(&sma->sem_perm);
+	ipc_rcu_putref(sma);
+	if (sma->sem_perm.deleted) {
+		sem_unlock(sma);
 		unlock_semundo();
 		kfree(new);
-		un = ERR_PTR(error);
+		un = ERR_PTR(-EIDRM);
 		goto out;
 	}
 	new->proc_next = ulp->proc_list;
@@ -1269,8 +1286,23 @@
 			struct sem * sem = &sma->sem_base[i];
 			if (u->semadj[i]) {
 				sem->semval += u->semadj[i];
+				/*
+				 * Range checks of the new semaphore value,
+				 * not defined by sus:
+				 * - Some unices ignore the undo entirely
+				 *   (e.g. HP UX 11i 11.22, Tru64 V5.1)
+				 * - some cap the value (e.g. FreeBSD caps
+				 *   at 0, but doesn't enforce SEMVMX)
+				 *
+				 * Linux caps the semaphore value, both at 0
+				 * and at SEMVMX.
+				 *
+				 * 	Manfred <manfred@colorfullife.com>
+				 */
 				if (sem->semval < 0)
-					sem->semval = 0; /* shouldn't happen */
+					sem->semval = 0;
+				if (sem->semval > SEMVMX)
+					sem->semval = SEMVMX;
 				sem->sempid = current->tgid;
 			}
 		}
diff -Nru a/ipc/shm.c b/ipc/shm.c
--- a/ipc/shm.c	2004-10-18 14:56:32 -07:00
+++ b/ipc/shm.c	2004-10-18 14:56:32 -07:00
@@ -78,7 +78,7 @@
 
 static inline int shm_addid(struct shmid_kernel *shp)
 {
-	return ipc_addid(&shm_ids, &shp->shm_perm, shm_ctlmni+1);
+	return ipc_addid(&shm_ids, &shp->shm_perm, shm_ctlmni);
 }
 
 
@@ -114,10 +114,13 @@
 	shm_rmid (shp->id);
 	shm_unlock(shp);
 	if (!is_file_hugepages(shp->shm_file))
-		shmem_lock(shp->shm_file, 0);
+		shmem_lock(shp->shm_file, 0, shp->mlock_user);
+	else
+		user_shm_unlock(shp->shm_file->f_dentry->d_inode->i_size,
+						shp->mlock_user);
 	fput (shp->shm_file);
 	security_shm_free(shp);
-	ipc_rcu_free(shp, sizeof(struct shmid_kernel));
+	ipc_rcu_putref(shp);
 }
 
 /*
@@ -190,17 +193,20 @@
 
 	shp->shm_perm.key = key;
 	shp->shm_flags = (shmflg & S_IRWXUGO);
+	shp->mlock_user = NULL;
 
 	shp->shm_perm.security = NULL;
 	error = security_shm_alloc(shp);
 	if (error) {
-		ipc_rcu_free(shp, sizeof(*shp));
+		ipc_rcu_putref(shp);
 		return error;
 	}
 
-	if (shmflg & SHM_HUGETLB)
+	if (shmflg & SHM_HUGETLB) {
+		/* hugetlb_zero_setup takes care of mlock user accounting */
 		file = hugetlb_zero_setup(size);
-	else {
+		shp->mlock_user = current->user;
+	} else {
 		sprintf (name, "SYSV%08x", key);
 		file = shmem_file_setup(name, size, VM_ACCOUNT);
 	}
@@ -234,7 +240,7 @@
 	fput(file);
 no_file:
 	security_shm_free(shp);
-	ipc_rcu_free(shp, sizeof(*shp));
+	ipc_rcu_putref(shp);
 	return error;
 }
 
@@ -504,14 +510,11 @@
 	case SHM_LOCK:
 	case SHM_UNLOCK:
 	{
-/* Allow superuser to lock segment in memory */
-/* Should the pages be faulted in here or leave it to user? */
-/* need to determine interaction with current->swappable */
-		if (!capable(CAP_IPC_LOCK)) {
+		/* Allow superuser to lock segment in memory */
+		if (!can_do_mlock() && cmd == SHM_LOCK) {
 			err = -EPERM;
 			goto out;
 		}
-
 		shp = shm_lock(shmid);
 		if(shp==NULL) {
 			err = -EINVAL;
@@ -526,13 +529,18 @@
 			goto out_unlock;
 		
 		if(cmd==SHM_LOCK) {
-			if (!is_file_hugepages(shp->shm_file))
-				shmem_lock(shp->shm_file, 1);
-			shp->shm_flags |= SHM_LOCKED;
-		} else {
-			if (!is_file_hugepages(shp->shm_file))
-				shmem_lock(shp->shm_file, 0);
+			struct user_struct * user = current->user;
+			if (!is_file_hugepages(shp->shm_file)) {
+				err = shmem_lock(shp->shm_file, 1, user);
+				if (!err) {
+					shp->shm_flags |= SHM_LOCKED;
+					shp->mlock_user = user;
+				}
+			}
+		} else if (!is_file_hugepages(shp->shm_file)) {
+			shmem_lock(shp->shm_file, 0, shp->mlock_user);
 			shp->shm_flags &= ~SHM_LOCKED;
+			shp->mlock_user = NULL;
 		}
 		shm_unlock(shp);
 		goto out;
@@ -679,6 +687,10 @@
 		prot = PROT_READ | PROT_WRITE;
 		o_flags = O_RDWR;
 		acc_mode = S_IRUGO | S_IWUGO;
+	}
+	if (shmflg & SHM_EXEC) {
+		prot |= PROT_EXEC;
+		acc_mode |= S_IXUGO;
 	}
 
 	/*
diff -Nru a/ipc/util.c b/ipc/util.c
--- a/ipc/util.c	2004-10-18 14:57:19 -07:00
+++ b/ipc/util.c	2004-10-18 14:57:19 -07:00
@@ -100,7 +100,7 @@
 	int max_id = ids->max_id;
 
 	/*
-	 * read_barrier_depends is not needed here
+	 * rcu_dereference() is not needed here
 	 * since ipc_ids.sem is held
 	 */
 	for (id = 0; id <= max_id; id++) {
@@ -135,7 +135,6 @@
 		new[i].p = NULL;
 	}
 	old = ids->entries;
-	i = ids->size;
 
 	/*
 	 * before setting the ids->entries to the new array, there must be a
@@ -147,7 +146,7 @@
 	smp_wmb();	/* prevent indexing into old array based on new size. */
 	ids->size = newsize;
 
-	ipc_rcu_free(old, sizeof(struct ipc_id)*i);
+	ipc_rcu_putref(old);
 	return ids->size;
 }
 
@@ -172,7 +171,7 @@
 	size = grow_ary(ids,size);
 
 	/*
-	 * read_barrier_depends() is not needed here since
+	 * rcu_dereference()() is not needed here since
 	 * ipc_ids.sem is held
 	 */
 	for (id = 0; id < size; id++) {
@@ -221,7 +220,7 @@
 		BUG();
 
 	/* 
-	 * do not need a read_barrier_depends() here to force ordering
+	 * do not need a rcu_dereference()() here to force ordering
 	 * on Alpha, since the ipc_ids.sem is held.
 	 */	
 	p = ids->entries[lid].p;
@@ -277,25 +276,47 @@
 		kfree(ptr);
 }
 
-struct ipc_rcu_kmalloc
+/*
+ * rcu allocations:
+ * There are three headers that are prepended to the actual allocation:
+ * - during use: ipc_rcu_hdr.
+ * - during the rcu grace period: ipc_rcu_grace.
+ * - [only if vmalloc]: ipc_rcu_sched.
+ * Their lifetime doesn't overlap, thus the headers share the same memory.
+ * Unlike a normal union, they are right-aligned, thus some container_of
+ * forward/backward casting is necessary:
+ */
+struct ipc_rcu_hdr
+{
+	int refcount;
+	int is_vmalloc;
+	void *data[0];
+};
+
+
+struct ipc_rcu_grace
 {
 	struct rcu_head rcu;
 	/* "void *" makes sure alignment of following data is sane. */
 	void *data[0];
 };
 
-struct ipc_rcu_vmalloc
+struct ipc_rcu_sched
 {
-	struct rcu_head rcu;
 	struct work_struct work;
 	/* "void *" makes sure alignment of following data is sane. */
 	void *data[0];
 };
 
+#define HDRLEN_KMALLOC		(sizeof(struct ipc_rcu_grace) > sizeof(struct ipc_rcu_hdr) ? \
+					sizeof(struct ipc_rcu_grace) : sizeof(struct ipc_rcu_hdr))
+#define HDRLEN_VMALLOC		(sizeof(struct ipc_rcu_sched) > HDRLEN_KMALLOC ? \
+					sizeof(struct ipc_rcu_sched) : HDRLEN_KMALLOC)
+
 static inline int rcu_use_vmalloc(int size)
 {
 	/* Too big for a single page? */
-	if (sizeof(struct ipc_rcu_kmalloc) + size > PAGE_SIZE)
+	if (HDRLEN_KMALLOC + size > PAGE_SIZE)
 		return 1;
 	return 0;
 }
@@ -317,16 +338,29 @@
 	 * workqueue if necessary (for vmalloc). 
 	 */
 	if (rcu_use_vmalloc(size)) {
-		out = vmalloc(sizeof(struct ipc_rcu_vmalloc) + size);
-		if (out) out += sizeof(struct ipc_rcu_vmalloc);
+		out = vmalloc(HDRLEN_VMALLOC + size);
+		if (out) {
+			out += HDRLEN_VMALLOC;
+			container_of(out, struct ipc_rcu_hdr, data)->is_vmalloc = 1;
+			container_of(out, struct ipc_rcu_hdr, data)->refcount = 1;
+		}
 	} else {
-		out = kmalloc(sizeof(struct ipc_rcu_kmalloc)+size, GFP_KERNEL);
-		if (out) out += sizeof(struct ipc_rcu_kmalloc);
+		out = kmalloc(HDRLEN_KMALLOC + size, GFP_KERNEL);
+		if (out) {
+			out += HDRLEN_KMALLOC;
+			container_of(out, struct ipc_rcu_hdr, data)->is_vmalloc = 0;
+			container_of(out, struct ipc_rcu_hdr, data)->refcount = 1;
+		}
 	}
 
 	return out;
 }
 
+void ipc_rcu_getref(void *ptr)
+{
+	container_of(ptr, struct ipc_rcu_hdr, data)->refcount++;
+}
+
 /**
  *	ipc_schedule_free	- free ipc + rcu space
  * 
@@ -335,11 +369,13 @@
  */
 static void ipc_schedule_free(struct rcu_head *head)
 {
-	struct ipc_rcu_vmalloc *free =
-		container_of(head, struct ipc_rcu_vmalloc, rcu);
+	struct ipc_rcu_grace *grace =
+		container_of(head, struct ipc_rcu_grace, rcu);
+	struct ipc_rcu_sched *sched =
+			container_of(&(grace->data[0]), struct ipc_rcu_sched, data[0]);
 
-	INIT_WORK(&free->work, vfree, free);
-	schedule_work(&free->work);
+	INIT_WORK(&sched->work, vfree, sched);
+	schedule_work(&sched->work);
 }
 
 /**
@@ -350,25 +386,23 @@
  */
 static void ipc_immediate_free(struct rcu_head *head)
 {
-	struct ipc_rcu_kmalloc *free =
-		container_of(head, struct ipc_rcu_kmalloc, rcu);
+	struct ipc_rcu_grace *free =
+		container_of(head, struct ipc_rcu_grace, rcu);
 	kfree(free);
 }
 
-
-
-void ipc_rcu_free(void* ptr, int size)
+void ipc_rcu_putref(void *ptr)
 {
-	if (rcu_use_vmalloc(size)) {
-		struct ipc_rcu_vmalloc *free;
-		free = ptr - sizeof(*free);
-		call_rcu(&free->rcu, ipc_schedule_free);
+	if (--container_of(ptr, struct ipc_rcu_hdr, data)->refcount > 0)
+		return;
+
+	if (container_of(ptr, struct ipc_rcu_hdr, data)->is_vmalloc) {
+		call_rcu(&container_of(ptr, struct ipc_rcu_grace, data)->rcu,
+				ipc_schedule_free);
 	} else {
-		struct ipc_rcu_kmalloc *free;
-		free = ptr - sizeof(*free);
-		call_rcu(&free->rcu, ipc_immediate_free);
+		call_rcu(&container_of(ptr, struct ipc_rcu_grace, data)->rcu,
+				ipc_immediate_free);
 	}
-
 }
 
 /**
@@ -481,13 +515,12 @@
 	 * Note: The following two read barriers are corresponding
 	 * to the two write barriers in grow_ary(). They guarantee 
 	 * the writes are seen in the same order on the read side. 
-	 * smp_rmb() has effect on all CPUs.  read_barrier_depends() 
+	 * smp_rmb() has effect on all CPUs.  rcu_dereference()
 	 * is used if there are data dependency between two reads, and 
 	 * has effect only on Alpha.
 	 */
 	smp_rmb(); /* prevent indexing old array with new size */
-	entries = ids->entries;
-	read_barrier_depends(); /*prevent seeing new array unitialized */
+	entries = rcu_dereference(ids->entries);
 	out = entries[lid].p;
 	if(out == NULL) {
 		rcu_read_unlock();
@@ -504,6 +537,12 @@
 		return NULL;
 	}
 	return out;
+}
+
+void ipc_lock_by_ptr(struct kern_ipc_perm *perm)
+{
+	rcu_read_lock();
+	spin_lock(&perm->lock);
 }
 
 void ipc_unlock(struct kern_ipc_perm* perm)
diff -Nru a/ipc/util.h b/ipc/util.h
--- a/ipc/util.h	2004-10-18 14:56:33 -07:00
+++ b/ipc/util.h	2004-10-18 14:56:33 -07:00
@@ -45,14 +45,20 @@
  */
 void* ipc_alloc(int size);
 void ipc_free(void* ptr, int size);
-/* for allocation that need to be freed by RCU
- * both function can sleep
+
+/*
+ * For allocation that need to be freed by RCU.
+ * Objects are reference counted, they start with reference count 1.
+ * getref increases the refcount, the putref call that reduces the recount
+ * to 0 schedules the rcu destruction. Caller must guarantee locking.
  */
 void* ipc_rcu_alloc(int size);
-void ipc_rcu_free(void* arg, int size);
+void ipc_rcu_getref(void *ptr);
+void ipc_rcu_putref(void *ptr);
 
 struct kern_ipc_perm* ipc_get(struct ipc_ids* ids, int id);
 struct kern_ipc_perm* ipc_lock(struct ipc_ids* ids, int id);
+void ipc_lock_by_ptr(struct kern_ipc_perm *ipcp);
 void ipc_unlock(struct kern_ipc_perm* perm);
 int ipc_buildid(struct ipc_ids* ids, int id, int seq);
 int ipc_checkid(struct ipc_ids* ids, struct kern_ipc_perm* ipcp, int uid);
diff -Nru a/kernel/Makefile b/kernel/Makefile
--- a/kernel/Makefile	2004-10-18 14:56:17 -07:00
+++ b/kernel/Makefile	2004-10-18 14:56:17 -07:00
@@ -11,7 +11,7 @@
 
 obj-$(CONFIG_FUTEX) += futex.o
 obj-$(CONFIG_GENERIC_ISA_DMA) += dma.o
-obj-$(CONFIG_SMP) += cpu.o
+obj-$(CONFIG_SMP) += cpu.o spinlock.o
 obj-$(CONFIG_UID16) += uid16.o
 obj-$(CONFIG_MODULES) += module.o
 obj-$(CONFIG_KALLSYMS) += kallsyms.o
@@ -23,6 +23,7 @@
 obj-$(CONFIG_STOP_MACHINE) += stop_machine.o
 obj-$(CONFIG_AUDIT) += audit.o
 obj-$(CONFIG_AUDITSYSCALL) += auditsc.o
+obj-$(CONFIG_KPROBES) += kprobes.o
 
 ifneq ($(CONFIG_IA64),y)
 # According to Alan Modra <alan@linuxcare.com.au>, the -fno-omit-frame-pointer is
diff -Nru a/kernel/acct.c b/kernel/acct.c
--- a/kernel/acct.c	2004-10-18 14:56:32 -07:00
+++ b/kernel/acct.c	2004-10-18 14:56:32 -07:00
@@ -384,6 +384,8 @@
 	unsigned long vsize;
 	unsigned long flim;
 	u64 elapsed;
+	u64 run_time;
+	struct timespec uptime;
 
 	/*
 	 * First check to see if there is enough free_space to continue
@@ -401,7 +403,13 @@
 	ac.ac_version = ACCT_VERSION | ACCT_BYTEORDER;
 	strlcpy(ac.ac_comm, current->comm, sizeof(ac.ac_comm));
 
-	elapsed = jiffies_64_to_AHZ(get_jiffies_64() - current->start_time);
+	/* calculate run_time in nsec*/
+	do_posix_clock_monotonic_gettime(&uptime);
+	run_time = (u64)uptime.tv_sec*NSEC_PER_SEC + uptime.tv_nsec;
+	run_time -= (u64)current->start_time.tv_sec*NSEC_PER_SEC
+					+ current->start_time.tv_nsec;
+	/* convert nsec -> AHZ */
+	elapsed = nsec_to_AHZ(run_time);
 #if ACCT_VERSION==3
 	ac.ac_etime = encode_float(elapsed);
 #else
diff -Nru a/kernel/audit.c b/kernel/audit.c
--- a/kernel/audit.c	2004-10-18 14:57:18 -07:00
+++ b/kernel/audit.c	2004-10-18 14:57:18 -07:00
@@ -708,7 +708,7 @@
 		audit_log_move(ab);
 	avail = sizeof(ab->tmp) - ab->len;
 	p = d_path(dentry, vfsmnt, ab->tmp + ab->len, avail);
-	if (p == ERR_PTR(-ENAMETOOLONG)) {
+	if (IS_ERR(p)) {
 		/* FIXME: can we save some information here? */
 		audit_log_format(ab, "<toolong>");
 	} else {
@@ -810,16 +810,3 @@
 		audit_log_end(ab);
 	}
 }
-
-EXPORT_SYMBOL_GPL(audit_set_rate_limit);
-EXPORT_SYMBOL_GPL(audit_set_backlog_limit);
-EXPORT_SYMBOL_GPL(audit_set_enabled);
-EXPORT_SYMBOL_GPL(audit_set_failure);
-
-EXPORT_SYMBOL_GPL(audit_log_start);
-EXPORT_SYMBOL_GPL(audit_log_format);
-EXPORT_SYMBOL_GPL(audit_log_end_irq);
-EXPORT_SYMBOL_GPL(audit_log_end_fast);
-EXPORT_SYMBOL_GPL(audit_log_end);
-EXPORT_SYMBOL_GPL(audit_log);
-EXPORT_SYMBOL_GPL(audit_log_d_path);
diff -Nru a/kernel/auditsc.c b/kernel/auditsc.c
--- a/kernel/auditsc.c	2004-10-18 14:56:49 -07:00
+++ b/kernel/auditsc.c	2004-10-18 14:56:49 -07:00
@@ -857,6 +857,7 @@
 	}
 #endif
 }
+EXPORT_SYMBOL(audit_putname);
 
 /* Store the inode and device from a lookup.  Called from
  * fs/namei.c:path_lookup(). */
@@ -913,11 +914,3 @@
 	}
 	return 0;
 }
-
-EXPORT_SYMBOL_GPL(audit_alloc);
-EXPORT_SYMBOL_GPL(audit_free);
-EXPORT_SYMBOL_GPL(audit_syscall_entry);
-EXPORT_SYMBOL_GPL(audit_syscall_exit);
-EXPORT_SYMBOL_GPL(audit_getname);
-EXPORT_SYMBOL_GPL(audit_putname);
-EXPORT_SYMBOL_GPL(audit_inode);
diff -Nru a/kernel/capability.c b/kernel/capability.c
--- a/kernel/capability.c	2004-10-18 14:56:48 -07:00
+++ b/kernel/capability.c	2004-10-18 14:56:48 -07:00
@@ -89,14 +89,12 @@
 			      kernel_cap_t *permitted)
 {
 	task_t *g, *target;
-	struct list_head *l;
-	struct pid *pid;
 
-	for_each_task_pid(pgrp, PIDTYPE_PGID, g, l, pid) {
+	do_each_task_pid(pgrp, PIDTYPE_PGID, g) {
 		target = g;
 		while_each_thread(g, target)
 			security_capset_set(target, effective, inheritable, permitted);
-	}
+	} while_each_task_pid(pgrp, PIDTYPE_PGID, g);
 }
 
 /*
diff -Nru a/kernel/compat.c b/kernel/compat.c
--- a/kernel/compat.c	2004-10-18 14:56:32 -07:00
+++ b/kernel/compat.c	2004-10-18 14:56:32 -07:00
@@ -160,10 +160,39 @@
 	 */
 	if (tbuf) {
 		struct compat_tms tmp;
-		tmp.tms_utime = compat_jiffies_to_clock_t(current->utime);
-		tmp.tms_stime = compat_jiffies_to_clock_t(current->stime);
-		tmp.tms_cutime = compat_jiffies_to_clock_t(current->cutime);
-		tmp.tms_cstime = compat_jiffies_to_clock_t(current->cstime);
+		struct task_struct *tsk = current;
+		struct task_struct *t;
+		unsigned long utime, stime, cutime, cstime;
+
+		read_lock(&tasklist_lock);
+		utime = tsk->signal->utime;
+		stime = tsk->signal->stime;
+		t = tsk;
+		do {
+			utime += t->utime;
+			stime += t->stime;
+			t = next_thread(t);
+		} while (t != tsk);
+
+		/*
+		 * While we have tasklist_lock read-locked, no dying thread
+		 * can be updating current->signal->[us]time.  Instead,
+		 * we got their counts included in the live thread loop.
+		 * However, another thread can come in right now and
+		 * do a wait call that updates current->signal->c[us]time.
+		 * To make sure we always see that pair updated atomically,
+		 * we take the siglock around fetching them.
+		 */
+		spin_lock_irq(&tsk->sighand->siglock);
+		cutime = tsk->signal->cutime;
+		cstime = tsk->signal->cstime;
+		spin_unlock_irq(&tsk->sighand->siglock);
+		read_unlock(&tasklist_lock);
+
+		tmp.tms_utime = compat_jiffies_to_clock_t(utime);
+		tmp.tms_stime = compat_jiffies_to_clock_t(stime);
+		tmp.tms_cutime = compat_jiffies_to_clock_t(cutime);
+		tmp.tms_cstime = compat_jiffies_to_clock_t(cstime);
 		if (copy_to_user(tbuf, &tmp, sizeof(tmp)))
 			return -EFAULT;
 	}
@@ -310,7 +339,7 @@
 	return ret;
 }
 
-static long put_compat_rusage(struct compat_rusage __user *ru, struct rusage *r)
+int put_compat_rusage(const struct rusage *r, struct compat_rusage __user *ru)
 {
 	if (!access_ok(VERIFY_WRITE, ru, sizeof(*ru)) ||
 	    __put_user(r->ru_utime.tv_sec, &ru->ru_utime.tv_sec) ||
@@ -348,7 +377,7 @@
 	if (ret)
 		return ret;
 
-	if (put_compat_rusage(ru, &r))
+	if (put_compat_rusage(&r, ru))
 		return -EFAULT;
 
 	return 0;
@@ -374,7 +403,7 @@
 		set_fs (old_fs);
 
 		if (ret > 0) {
-			if (put_compat_rusage(ru, &r)) 
+			if (put_compat_rusage(&r, ru))
 				return -EFAULT;
 			if (stat_addr && put_user(status, stat_addr))
 				return -EFAULT;
@@ -383,48 +412,58 @@
 	}
 }
 
-asmlinkage long compat_sys_sched_setaffinity(compat_pid_t pid, 
+static int compat_get_user_cpu_mask(compat_ulong_t __user *user_mask_ptr,
+				    unsigned len, cpumask_t *new_mask)
+{
+	unsigned long *k;
+
+	if (len < sizeof(cpumask_t))
+		memset(new_mask, 0, sizeof(cpumask_t));
+	else if (len > sizeof(cpumask_t))
+		len = sizeof(cpumask_t);
+
+	k = cpus_addr(*new_mask);
+	return compat_get_bitmap(k, user_mask_ptr, len * 8);
+}
+
+asmlinkage long compat_sys_sched_setaffinity(compat_pid_t pid,
 					     unsigned int len,
 					     compat_ulong_t __user *user_mask_ptr)
 {
-	unsigned long kern_mask;
-	mm_segment_t old_fs;
-	int ret;
-
-	if (get_user(kern_mask, user_mask_ptr))
-		return -EFAULT;
+	cpumask_t new_mask;
+	int retval;
 
-	old_fs = get_fs();
-	set_fs(KERNEL_DS);
-	ret = sys_sched_setaffinity(pid,
-				    sizeof(kern_mask),
-				    (unsigned long __user *) &kern_mask);
-	set_fs(old_fs);
+	retval = compat_get_user_cpu_mask(user_mask_ptr, len, &new_mask);
+	if (retval)
+		return retval;
 
-	return ret;
+	return sched_setaffinity(pid, new_mask);
 }
 
 asmlinkage long compat_sys_sched_getaffinity(compat_pid_t pid, unsigned int len,
 					     compat_ulong_t __user *user_mask_ptr)
 {
-	unsigned long kern_mask;
-	mm_segment_t old_fs;
 	int ret;
+	cpumask_t mask;
+	unsigned long *k;
+	unsigned int min_length = sizeof(cpumask_t);
 
-	old_fs = get_fs();
-	set_fs(KERNEL_DS);
-	ret = sys_sched_getaffinity(pid,
-				    sizeof(kern_mask),
-				    (unsigned long __user *) &kern_mask);
-	set_fs(old_fs);
+	if (NR_CPUS <= BITS_PER_COMPAT_LONG)
+		min_length = sizeof(compat_ulong_t);
 
-	if (ret > 0) {
-		ret = sizeof(compat_ulong_t);
-		if (put_user(kern_mask, user_mask_ptr))
-			return -EFAULT;
-	}
+	if (len < min_length)
+		return -EINVAL;
 
-	return ret;
+	ret = sched_getaffinity(pid, &mask);
+	if (ret < 0)
+		return ret;
+
+	k = cpus_addr(mask);
+	ret = compat_put_bitmap(user_mask_ptr, k, min_length * 8);
+	if (ret)
+		return ret;
+
+	return min_length;
 }
 
 static int get_compat_itimerspec(struct itimerspec *dst, 
@@ -561,3 +600,83 @@
 
 /* timer_create is architecture specific because it needs sigevent conversion */
 
+long compat_get_bitmap(unsigned long *mask, compat_ulong_t __user *umask,
+		       unsigned long bitmap_size)
+{
+	int i, j;
+	unsigned long m;
+	compat_ulong_t um;
+	unsigned long nr_compat_longs;
+
+	/* align bitmap up to nearest compat_long_t boundary */
+	bitmap_size = ALIGN(bitmap_size, BITS_PER_COMPAT_LONG);
+
+	if (verify_area(VERIFY_READ, umask, bitmap_size / 8))
+		return -EFAULT;
+
+	nr_compat_longs = BITS_TO_COMPAT_LONGS(bitmap_size);
+
+	for (i = 0; i < BITS_TO_LONGS(bitmap_size); i++) {
+		m = 0;
+
+		for (j = 0; j < sizeof(m)/sizeof(um); j++) {
+			/*
+			 * We dont want to read past the end of the userspace
+			 * bitmap. We must however ensure the end of the
+			 * kernel bitmap is zeroed.
+			 */
+			if (nr_compat_longs-- > 0) {
+				if (__get_user(um, umask))
+					return -EFAULT;
+			} else {
+				um = 0;
+			}
+
+			umask++;
+			m |= (long)um << (j * BITS_PER_COMPAT_LONG);
+		}
+		*mask++ = m;
+	}
+
+	return 0;
+}
+
+long compat_put_bitmap(compat_ulong_t __user *umask, unsigned long *mask,
+		       unsigned long bitmap_size)
+{
+	int i, j;
+	unsigned long m;
+	compat_ulong_t um;
+	unsigned long nr_compat_longs;
+
+	/* align bitmap up to nearest compat_long_t boundary */
+	bitmap_size = ALIGN(bitmap_size, BITS_PER_COMPAT_LONG);
+
+	if (verify_area(VERIFY_WRITE, umask, bitmap_size / 8))
+		return -EFAULT;
+
+	nr_compat_longs = BITS_TO_COMPAT_LONGS(bitmap_size);
+
+	for (i = 0; i < BITS_TO_LONGS(bitmap_size); i++) {
+		m = *mask++;
+
+		for (j = 0; j < sizeof(m)/sizeof(um); j++) {
+			um = m;
+
+			/*
+			 * We dont want to write past the end of the userspace
+			 * bitmap.
+			 */
+			if (nr_compat_longs-- > 0) {
+				if (__put_user(um, umask))
+					return -EFAULT;
+			}
+
+			umask++;
+			m >>= 4*sizeof(um);
+			m >>= 4*sizeof(um);
+		}
+	}
+
+	return 0;
+}
diff -Nru a/kernel/cpu.c b/kernel/cpu.c
--- a/kernel/cpu.c	2004-10-18 14:57:03 -07:00
+++ b/kernel/cpu.c	2004-10-18 14:57:03 -07:00
@@ -61,13 +61,13 @@
  * cpu' with certain environment variables set.  */
 static int cpu_run_sbin_hotplug(unsigned int cpu, const char *action)
 {
-	char *argv[3], *envp[5], cpu_str[12], action_str[32];
+	char *argv[3], *envp[6], cpu_str[12], action_str[32], devpath_str[40];
 	int i;
 
 	sprintf(cpu_str, "CPU=%d", cpu);
 	sprintf(action_str, "ACTION=%s", action);
-	/* FIXME: Add DEVPATH. --RR */
-
+	sprintf(devpath_str, "DEVPATH=devices/system/cpu/cpu%d", cpu);
+	
 	i = 0;
 	argv[i++] = hotplug_path;
 	argv[i++] = "cpu";
@@ -79,6 +79,7 @@
 	envp[i++] = "PATH=/sbin:/bin:/usr/sbin:/usr/bin";
 	envp[i++] = cpu_str;
 	envp[i++] = action_str;
+	envp[i++] = devpath_str;
 	envp[i] = NULL;
 
 	return call_usermodehelper(argv[0], argv, envp, 0);
diff -Nru a/kernel/exec_domain.c b/kernel/exec_domain.c
--- a/kernel/exec_domain.c	2004-10-18 14:56:33 -07:00
+++ b/kernel/exec_domain.c	2004-10-18 14:56:33 -07:00
@@ -44,29 +44,7 @@
 static void
 default_handler(int segment, struct pt_regs *regp)
 {
-	u_long			pers = 0;
-
-	/*
-	 * This may have been a static linked SVr4 binary, so we would
-	 * have the personality set incorrectly. Or it might have been
-	 * a Solaris/x86 binary. We can tell which because the former
-	 * uses lcall7, while the latter used lcall 0x27.
-	 * Try to find or load the appropriate personality, and fall back
-	 * to just forcing a SEGV.
-	 *
-	 * XXX: this is IA32-specific and should be moved to the MD-tree.
-	 */
-	switch (segment) {
-#ifdef __i386__
-	case 0x07:
-		pers = abi_defhandler_lcall7;
-		break;
-	case 0x27:
-		pers = PER_SOLARIS;
-		break;
-#endif
-	}
-	set_personality(pers);
+	set_personality(0);
 
 	if (current_thread_info()->exec_domain->handler != default_handler)
 		current_thread_info()->exec_domain->handler(segment, regp);
@@ -228,100 +206,3 @@
 EXPORT_SYMBOL(register_exec_domain);
 EXPORT_SYMBOL(unregister_exec_domain);
 EXPORT_SYMBOL(__set_personality);
-
-/*
- * We have to have all sysctl handling for the Linux-ABI
- * in one place as the dynamic registration of sysctls is
- * horribly crufty in Linux <= 2.4.
- *
- * I hope the new sysctl schemes discussed for future versions
- * will obsolete this.
- *
- * 				--hch
- */
-
-u_long abi_defhandler_coff = PER_SCOSVR3;
-u_long abi_defhandler_elf = PER_LINUX;
-u_long abi_defhandler_lcall7 = PER_SVR4;
-u_long abi_defhandler_libcso = PER_SVR4;
-u_int abi_traceflg;
-int abi_fake_utsname;
-
-static struct ctl_table abi_table[] = {
-	{
-		.ctl_name	= ABI_DEFHANDLER_COFF,
-		.procname	= "defhandler_coff",
-		.data		= &abi_defhandler_coff,
-		.maxlen		= sizeof(int),
-		.mode		= 0644,
-		.proc_handler	= &proc_doulongvec_minmax,
-	},
-	{
-		.ctl_name	= ABI_DEFHANDLER_ELF,
-		.procname	= "defhandler_elf",
-		.data		= &abi_defhandler_elf,
-		.maxlen		= sizeof(int),
-		.mode		= 0644,
-		.proc_handler	= &proc_doulongvec_minmax,
-	},
-	{
-		.ctl_name	= ABI_DEFHANDLER_LCALL7,
-		.procname	= "defhandler_lcall7",
-		.data		= &abi_defhandler_lcall7,
-		.maxlen		= sizeof(int),
-		.mode		= 0644,
-		.proc_handler	= &proc_doulongvec_minmax,
-	},
-	{
-		.ctl_name	= ABI_DEFHANDLER_LIBCSO,
-		.procname	= "defhandler_libcso",
-		.data		= &abi_defhandler_libcso,
-		.maxlen		= sizeof(int),
-		.mode		= 0644,
-		.proc_handler	= &proc_doulongvec_minmax,
-	},
-	{
-		.ctl_name	= ABI_TRACE,
-		.procname	= "trace",
-		.data		= &abi_traceflg,
-		.maxlen		= sizeof(u_int),
-		.mode		= 0644,
-		.proc_handler	= &proc_dointvec,
-	},
-	{
-		.ctl_name	= ABI_FAKE_UTSNAME,
-		.procname	= "fake_utsname",
-		.data		= &abi_fake_utsname,
-		.maxlen		= sizeof(int),
-		.mode		= 0644,
-		.proc_handler	= &proc_dointvec,
-	},
-	{ .ctl_name = 0 }
-};
-
-static struct ctl_table abi_root_table[] = {
-	{
-		.ctl_name	= CTL_ABI,
-		.procname	= "abi",
-		.mode		= 0555,
-		.child		= abi_table,
-	},
-	{ .ctl_name = 0 }
-};
-
-static int __init
-abi_register_sysctl(void)
-{
-	register_sysctl_table(abi_root_table, 1);
-	return 0;
-}
-
-__initcall(abi_register_sysctl);
-
-
-EXPORT_SYMBOL(abi_defhandler_coff);
-EXPORT_SYMBOL(abi_defhandler_elf);
-EXPORT_SYMBOL(abi_defhandler_lcall7);
-EXPORT_SYMBOL(abi_defhandler_libcso);
-EXPORT_SYMBOL(abi_traceflg);
-EXPORT_SYMBOL(abi_fake_utsname);
diff -Nru a/kernel/exit.c b/kernel/exit.c
--- a/kernel/exit.c	2004-10-18 14:56:50 -07:00
+++ b/kernel/exit.c	2004-10-18 14:56:50 -07:00
@@ -15,6 +15,7 @@
 #include <linux/tty.h>
 #include <linux/namespace.h>
 #include <linux/security.h>
+#include <linux/cpu.h>
 #include <linux/acct.h>
 #include <linux/file.h>
 #include <linux/binfmts.h>
@@ -56,8 +57,6 @@
 	struct dentry *proc_dentry;
 
 repeat: 
-	BUG_ON(p->state < TASK_ZOMBIE);
- 
 	atomic_dec(&p->user->processes);
 	spin_lock(&p->proc_lock);
 	proc_dentry = proc_pid_unhash(p);
@@ -90,12 +89,6 @@
 		zap_leader = (leader->exit_signal == -1);
 	}
 
-	p->parent->cutime += p->utime + p->cutime;
-	p->parent->cstime += p->stime + p->cstime;
-	p->parent->cmin_flt += p->min_flt + p->cmin_flt;
-	p->parent->cmaj_flt += p->maj_flt + p->cmaj_flt;
-	p->parent->cnvcsw += p->nvcsw + p->cnvcsw;
-	p->parent->cnivcsw += p->nivcsw + p->cnivcsw;
 	sched_exit(p);
 	write_unlock_irq(&tasklist_lock);
 	spin_unlock(&p->proc_lock);
@@ -131,16 +124,15 @@
 int session_of_pgrp(int pgrp)
 {
 	struct task_struct *p;
-	struct list_head *l;
-	struct pid *pid;
 	int sid = -1;
 
 	read_lock(&tasklist_lock);
-	for_each_task_pid(pgrp, PIDTYPE_PGID, p, l, pid)
+	do_each_task_pid(pgrp, PIDTYPE_PGID, p) {
 		if (p->signal->session > 0) {
 			sid = p->signal->session;
 			goto out;
 		}
+	} while_each_task_pid(pgrp, PIDTYPE_PGID, p);
 	p = find_task_by_pid(pgrp);
 	if (p)
 		sid = p->signal->session;
@@ -161,11 +153,9 @@
 static int will_become_orphaned_pgrp(int pgrp, task_t *ignored_task)
 {
 	struct task_struct *p;
-	struct list_head *l;
-	struct pid *pid;
 	int ret = 1;
 
-	for_each_task_pid(pgrp, PIDTYPE_PGID, p, l, pid) {
+	do_each_task_pid(pgrp, PIDTYPE_PGID, p) {
 		if (p == ignored_task
 				|| p->state >= TASK_ZOMBIE 
 				|| p->real_parent->pid == 1)
@@ -175,7 +165,7 @@
 			ret = 0;
 			break;
 		}
-	}
+	} while_each_task_pid(pgrp, PIDTYPE_PGID, p);
 	return ret;	/* (sighing) "Often!" */
 }
 
@@ -194,10 +184,8 @@
 {
 	int retval = 0;
 	struct task_struct *p;
-	struct list_head *l;
-	struct pid *pid;
 
-	for_each_task_pid(pgrp, PIDTYPE_PGID, p, l, pid) {
+	do_each_task_pid(pgrp, PIDTYPE_PGID, p) {
 		if (p->state != TASK_STOPPED)
 			continue;
 
@@ -213,7 +201,7 @@
 
 		retval = 1;
 		break;
-	}
+	} while_each_task_pid(pgrp, PIDTYPE_PGID, p);
 	return retval;
 }
 
@@ -529,10 +517,8 @@
 	 * Make sure we're not reparenting to ourselves and that
 	 * the parent is not a zombie.
 	 */
-	if (p == reaper || reaper->state >= TASK_ZOMBIE)
-		p->real_parent = child_reaper;
-	else
-		p->real_parent = reaper;
+	BUG_ON(p == reaper || reaper->state >= TASK_ZOMBIE);
+	p->real_parent = reaper;
 	if (p->parent == p->real_parent)
 		BUG();
 }
@@ -569,6 +555,14 @@
 		if (p->state == TASK_ZOMBIE && p->exit_signal != -1 &&
 		    thread_group_empty(p))
 			do_notify_parent(p, p->exit_signal);
+		else if (p->state == TASK_TRACED) {
+			/*
+			 * If it was at a trace stop, turn it into
+			 * a normal stop since it's no longer being
+			 * traced.
+			 */
+			p->state = TASK_STOPPED;
+		}
 	}
 
 	/*
@@ -600,9 +594,13 @@
 	struct task_struct *p, *reaper = father;
 	struct list_head *_p, *_n;
 
-	reaper = father->group_leader;
-	if (reaper == father)
-		reaper = child_reaper;
+	do {
+		reaper = next_thread(reaper);
+		if (reaper == father) {
+			reaper = child_reaper;
+			break;
+		}
+	} while (reaper->state >= TASK_ZOMBIE);
 
 	/*
 	 * There are only two places where our children can be:
@@ -756,7 +754,6 @@
 	if (tsk->exit_signal == -1 && tsk->ptrace == 0)
 		state = TASK_DEAD;
 	tsk->state = state;
-	tsk->flags |= PF_DEAD;
 
 	/*
 	 * Clear these here so that update_process_times() won't try to deliver
@@ -766,20 +763,7 @@
 	tsk->it_prof_value = 0;
 	tsk->rlim[RLIMIT_CPU].rlim_cur = RLIM_INFINITY;
 
-	/*
-	 * In the preemption case it must be impossible for the task
-	 * to get runnable again, so use "_raw_" unlock to keep
-	 * preempt_count elevated until we schedule().
-	 *
-	 * To avoid deadlock on SMP, interrupts must be unmasked.  If we
-	 * don't, subsequently called functions (e.g, wait_task_inactive()
-	 * via release_task()) will spin, with interrupt flags
-	 * unwittingly blocked, until the other task sleeps.  That task
-	 * may itself be waiting for smp_call_function() to answer and
-	 * complete, and with interrupts blocked that will never happen.
-	 */
-	_raw_write_unlock(&tasklist_lock);
-	local_irq_enable();
+	write_unlock_irq(&tasklist_lock);
 
 	list_for_each_safe(_p, _n, &ptrace_dead) {
 		list_del_init(_p);
@@ -791,12 +775,17 @@
 	if (state == TASK_DEAD)
 		release_task(tsk);
 
+	/* PF_DEAD causes final put_task_struct after we schedule. */
+	preempt_disable();
+	tsk->flags |= PF_DEAD;
 }
 
 asmlinkage NORET_TYPE void do_exit(long code)
 {
 	struct task_struct *tsk = current;
 
+	profile_task_exit(tsk);
+
 	if (unlikely(in_interrupt()))
 		panic("Aiee, killing interrupt handler!");
 	if (unlikely(!tsk->pid))
@@ -813,8 +802,6 @@
 				current->comm, current->pid,
 				preempt_count());
 
-	profile_exit_task(tsk);
- 
 	if (unlikely(current->ptrace & PT_TRACE_EXIT)) {
 		current->ptrace_message = code;
 		ptrace_notify((PTRACE_EVENT_EXIT << 8) | SIGTRAP);
@@ -865,9 +852,6 @@
 
 task_t fastcall *next_thread(const task_t *p)
 {
-	const struct pid_link *link = p->pids + PIDTYPE_TGID;
-	const struct list_head *tmp, *head = &link->pidptr->task_list;
-
 #ifdef CONFIG_SMP
 	if (!p->sighand)
 		BUG();
@@ -875,11 +859,7 @@
 				!rwlock_is_locked(&tasklist_lock))
 		BUG();
 #endif
-	tmp = link->pid_chain.next;
-	if (tmp == head)
-		tmp = head->next;
-
-	return pid_task(tmp, PIDTYPE_TGID);
+	return pid_task(p->pids[PIDTYPE_TGID].pid_list.next, PIDTYPE_TGID);
 }
 
 EXPORT_SYMBOL(next_thread);
@@ -967,16 +947,66 @@
 	return 1;
 }
 
+static int wait_noreap_copyout(task_t *p, pid_t pid, uid_t uid,
+			       int why, int status,
+			       struct siginfo __user *infop,
+			       struct rusage __user *rusagep)
+{
+	int retval = rusagep ? getrusage(p, RUSAGE_BOTH, rusagep) : 0;
+	put_task_struct(p);
+	if (!retval)
+		retval = put_user(SIGCHLD, &infop->si_signo);
+	if (!retval)
+		retval = put_user(0, &infop->si_errno);
+	if (!retval)
+		retval = put_user((short)why, &infop->si_code);
+	if (!retval)
+		retval = put_user(pid, &infop->si_pid);
+	if (!retval)
+		retval = put_user(uid, &infop->si_uid);
+	if (!retval)
+		retval = put_user(status, &infop->si_status);
+	if (!retval)
+		retval = pid;
+	return retval;
+}
+
 /*
  * Handle sys_wait4 work for one task in state TASK_ZOMBIE.  We hold
  * read_lock(&tasklist_lock) on entry.  If we return zero, we still hold
  * the lock and this task is uninteresting.  If we return nonzero, we have
  * released the lock and the system call should return.
  */
-static int wait_task_zombie(task_t *p, unsigned int __user *stat_addr, struct rusage __user *ru)
+static int wait_task_zombie(task_t *p, int noreap,
+			    struct siginfo __user *infop,
+			    int __user *stat_addr, struct rusage __user *ru)
 {
 	unsigned long state;
 	int retval;
+	int status;
+
+	if (unlikely(noreap)) {
+		pid_t pid = p->pid;
+		uid_t uid = p->uid;
+		int exit_code = p->exit_code;
+		int why, status;
+
+		if (unlikely(p->state != TASK_ZOMBIE))
+			return 0;
+		if (unlikely(p->exit_signal == -1 && p->ptrace == 0))
+			return 0;
+		get_task_struct(p);
+		read_unlock(&tasklist_lock);
+		if ((exit_code & 0x7f) == 0) {
+			why = CLD_EXITED;
+			status = exit_code >> 8;
+		} else {
+			why = (exit_code & 0x80) ? CLD_DUMPED : CLD_KILLED;
+			status = exit_code & 0x7f;
+		}
+		return wait_noreap_copyout(p, pid, uid, why,
+					   status, infop, ru);
+	}
 
 	/*
 	 * Try to move the task's state to DEAD
@@ -987,12 +1017,45 @@
 		BUG_ON(state != TASK_DEAD);
 		return 0;
 	}
-	if (unlikely(p->exit_signal == -1 && p->ptrace == 0))
+	if (unlikely(p->exit_signal == -1 && p->ptrace == 0)) {
 		/*
 		 * This can only happen in a race with a ptraced thread
 		 * dying on another processor.
 		 */
 		return 0;
+	}
+
+	if (likely(p->real_parent == p->parent) && likely(p->signal)) {
+		/*
+		 * The resource counters for the group leader are in its
+		 * own task_struct.  Those for dead threads in the group
+		 * are in its signal_struct, as are those for the child
+		 * processes it has previously reaped.  All these
+		 * accumulate in the parent's signal_struct c* fields.
+		 *
+		 * We don't bother to take a lock here to protect these
+		 * p->signal fields, because they are only touched by
+		 * __exit_signal, which runs with tasklist_lock
+		 * write-locked anyway, and so is excluded here.  We do
+		 * need to protect the access to p->parent->signal fields,
+		 * as other threads in the parent group can be right
+		 * here reaping other children at the same time.
+		 */
+		spin_lock_irq(&p->parent->sighand->siglock);
+		p->parent->signal->cutime +=
+			p->utime + p->signal->utime + p->signal->cutime;
+		p->parent->signal->cstime +=
+			p->stime + p->signal->stime + p->signal->cstime;
+		p->parent->signal->cmin_flt +=
+			p->min_flt + p->signal->min_flt + p->signal->cmin_flt;
+		p->parent->signal->cmaj_flt +=
+			p->maj_flt + p->signal->maj_flt + p->signal->cmaj_flt;
+		p->parent->signal->cnvcsw +=
+			p->nvcsw + p->signal->nvcsw + p->signal->cnvcsw;
+		p->parent->signal->cnivcsw +=
+			p->nivcsw + p->signal->nivcsw + p->signal->cnivcsw;
+		spin_unlock_irq(&p->parent->sighand->siglock);
+	}
 
 	/*
 	 * Now we are sure this task is interesting, and no other
@@ -1001,12 +1064,32 @@
 	read_unlock(&tasklist_lock);
 
 	retval = ru ? getrusage(p, RUSAGE_BOTH, ru) : 0;
-	if (!retval && stat_addr) {
-		if (p->signal->group_exit)
-			retval = put_user(p->signal->group_exit_code, stat_addr);
-		else
-			retval = put_user(p->exit_code, stat_addr);
-	}
+	status = p->signal->group_exit
+		? p->signal->group_exit_code : p->exit_code;
+	if (!retval && stat_addr)
+		retval = put_user(status, stat_addr);
+	if (!retval && infop)
+		retval = put_user(SIGCHLD, &infop->si_signo);
+	if (!retval && infop)
+		retval = put_user(0, &infop->si_errno);
+	if (!retval && infop) {
+		int why;
+
+		if ((status & 0x7f) == 0) {
+			why = CLD_EXITED;
+			status >>= 8;
+		} else {
+			why = (status & 0x80) ? CLD_DUMPED : CLD_KILLED;
+			status &= 0x7f;
+		}
+		retval = put_user((short)why, &infop->si_code);
+		if (!retval)
+			retval = put_user(status, &infop->si_status);
+	}
+	if (!retval && infop)
+		retval = put_user(p->pid, &infop->si_pid);
+	if (!retval && infop)
+		retval = put_user(p->uid, &infop->si_uid);
 	if (retval) {
 		p->state = TASK_ZOMBIE;
 		return retval;
@@ -1019,8 +1102,9 @@
 			__ptrace_unlink(p);
 			p->state = TASK_ZOMBIE;
 			/*
-			 * If this is not a detached task, notify the parent.  If it's
-			 * still not detached after that, don't release it now.
+			 * If this is not a detached task, notify the parent.
+			 * If it's still not detached after that, don't release
+			 * it now.
 			 */
 			if (p->exit_signal != -1) {
 				do_notify_parent(p, p->exit_signal);
@@ -1042,9 +1126,9 @@
  * the lock and this task is uninteresting.  If we return nonzero, we have
  * released the lock and the system call should return.
  */
-static int wait_task_stopped(task_t *p, int delayed_group_leader,
-			     unsigned int __user *stat_addr,
-			     struct rusage __user *ru)
+static int wait_task_stopped(task_t *p, int delayed_group_leader, int noreap,
+			     struct siginfo __user *infop,
+			     int __user *stat_addr, struct rusage __user *ru)
 {
 	int retval, exit_code;
 
@@ -1067,6 +1151,21 @@
 	 */
 	get_task_struct(p);
 	read_unlock(&tasklist_lock);
+
+	if (unlikely(noreap)) {
+		pid_t pid = p->pid;
+		uid_t uid = p->uid;
+		int why = (p->ptrace & PT_PTRACED) ? CLD_TRAPPED : CLD_STOPPED;
+
+		exit_code = p->exit_code;
+		if (unlikely(!exit_code) ||
+		    unlikely(p->state > TASK_STOPPED))
+			goto bail_ref;
+		return wait_noreap_copyout(p, pid, uid,
+					   why, (exit_code << 8) | 0x7f,
+					   infop, ru);
+	}
+
 	write_lock_irq(&tasklist_lock);
 
 	/*
@@ -1075,7 +1174,7 @@
 	 * race with the TASK_ZOMBIE case.
 	 */
 	exit_code = xchg(&p->exit_code, 0);
-	if (unlikely(p->state > TASK_STOPPED)) {
+	if (unlikely(p->state >= TASK_ZOMBIE)) {
 		/*
 		 * The task resumed and then died.  Let the next iteration
 		 * catch it in TASK_ZOMBIE.  Note that exit_code might
@@ -1092,6 +1191,7 @@
 		 * resumed, or it resumed and then died.
 		 */
 		write_unlock_irq(&tasklist_lock);
+bail_ref:
 		put_task_struct(p);
 		read_lock(&tasklist_lock);
 		return 0;
@@ -1106,6 +1206,20 @@
 	retval = ru ? getrusage(p, RUSAGE_BOTH, ru) : 0;
 	if (!retval && stat_addr)
 		retval = put_user((exit_code << 8) | 0x7f, stat_addr);
+	if (!retval && infop)
+		retval = put_user(SIGCHLD, &infop->si_signo);
+	if (!retval && infop)
+		retval = put_user(0, &infop->si_errno);
+	if (!retval && infop)
+		retval = put_user((short)((p->ptrace & PT_PTRACED)
+					  ? CLD_TRAPPED : CLD_STOPPED),
+				  &infop->si_code);
+	if (!retval && infop)
+		retval = put_user(exit_code, &infop->si_status);
+	if (!retval && infop)
+		retval = put_user(p->pid, &infop->si_pid);
+	if (!retval && infop)
+		retval = put_user(p->uid, &infop->si_uid);
 	if (!retval)
 		retval = p->pid;
 	put_task_struct(p);
@@ -1114,15 +1228,13 @@
 	return retval;
 }
 
-asmlinkage long sys_wait4(pid_t pid,unsigned int __user *stat_addr, int options, struct rusage __user *ru)
+static long do_wait(pid_t pid, int options, struct siginfo __user *infop,
+		    int __user *stat_addr, struct rusage __user *ru)
 {
 	DECLARE_WAITQUEUE(wait, current);
 	struct task_struct *tsk;
 	int flag, retval;
 
-	if (options & ~(WNOHANG|WUNTRACED|__WNOTHREAD|__WCLONE|__WALL))
-		return -EINVAL;
-
 	add_wait_queue(&current->wait_chldexit,&wait);
 repeat:
 	flag = 0;
@@ -1143,30 +1255,69 @@
 			flag = 1;
 
 			switch (p->state) {
+			case TASK_TRACED:
+				if (!(p->ptrace & PT_PTRACED))
+					continue;
+				/*FALLTHROUGH*/
 			case TASK_STOPPED:
 				if (!(options & WUNTRACED) &&
 				    !(p->ptrace & PT_PTRACED))
 					continue;
 				retval = wait_task_stopped(p, ret == 2,
+							   (options & WNOWAIT),
+							   infop,
 							   stat_addr, ru);
 				if (retval != 0) /* He released the lock.  */
-					goto end_wait4;
+					goto end;
 				break;
 			case TASK_ZOMBIE:
 				/*
 				 * Eligible but we cannot release it yet:
 				 */
 				if (ret == 2)
+					goto check_continued;
+				if (!likely(options & WEXITED))
 					continue;
-				retval = wait_task_zombie(p, stat_addr, ru);
+				retval = wait_task_zombie(
+					p, (options & WNOWAIT),
+					infop, stat_addr, ru);
 				if (retval != 0) /* He released the lock.  */
-					goto end_wait4;
+					goto end;
+				break;
+			case TASK_DEAD:
+				continue;
+			default:
+check_continued:
+				if (!unlikely(options & WCONTINUED))
+					continue;
+				if (unlikely(!p->signal))
+					continue;
+				spin_lock_irq(&p->sighand->siglock);
+				if (p->signal->stop_state < 0) {
+					pid_t pid;
+					uid_t uid;
+
+					if (!(options & WNOWAIT))
+						p->signal->stop_state = 0;
+					spin_unlock_irq(&p->sighand->siglock);
+					pid = p->pid;
+					uid = p->uid;
+					get_task_struct(p);
+					read_unlock(&tasklist_lock);
+					retval = wait_noreap_copyout(p, pid,
+							uid, CLD_CONTINUED,
+							SIGCONT, infop, ru);
+					BUG_ON(retval == 0);
+					goto end;
+				}
+				spin_unlock_irq(&p->sighand->siglock);
 				break;
 			}
 		}
 		if (!flag) {
-			list_for_each (_p,&tsk->ptrace_children) {
-				p = list_entry(_p,struct task_struct,ptrace_list);
+			list_for_each(_p, &tsk->ptrace_children) {
+				p = list_entry(_p, struct task_struct,
+						ptrace_list);
 				if (!eligible_child(pid, options, p))
 					continue;
 				flag = 1;
@@ -1179,31 +1330,104 @@
 		if (tsk->signal != current->signal)
 			BUG();
 	} while (tsk != current);
+
 	read_unlock(&tasklist_lock);
 	if (flag) {
 		retval = 0;
 		if (options & WNOHANG)
-			goto end_wait4;
+			goto end;
 		retval = -ERESTARTSYS;
 		if (signal_pending(current))
-			goto end_wait4;
+			goto end;
 		schedule();
 		goto repeat;
 	}
 	retval = -ECHILD;
-end_wait4:
+end:
 	current->state = TASK_RUNNING;
 	remove_wait_queue(&current->wait_chldexit,&wait);
+	if (infop) {
+		if (retval > 0)
+		retval = 0;
+		else {
+			/*
+			 * For a WNOHANG return, clear out all the fields
+			 * we would set so the user can easily tell the
+			 * difference.
+			 */
+			if (!retval)
+				retval = put_user(0, &infop->si_signo);
+			if (!retval)
+				retval = put_user(0, &infop->si_errno);
+			if (!retval)
+				retval = put_user(0, &infop->si_code);
+			if (!retval)
+				retval = put_user(0, &infop->si_pid);
+			if (!retval)
+				retval = put_user(0, &infop->si_uid);
+			if (!retval)
+				retval = put_user(0, &infop->si_status);
+		}
+	}
 	return retval;
 }
 
+asmlinkage long sys_waitid(int which, pid_t pid,
+			   struct siginfo __user *infop, int options,
+			   struct rusage __user *ru)
+{
+	long ret;
+
+	if (options & ~(WNOHANG|WNOWAIT|WEXITED|WSTOPPED|WCONTINUED))
+		return -EINVAL;
+	if (!(options & (WEXITED|WSTOPPED|WCONTINUED)))
+		return -EINVAL;
+
+	switch (which) {
+	case P_ALL:
+		pid = -1;
+		break;
+	case P_PID:
+		if (pid <= 0)
+			return -EINVAL;
+		break;
+	case P_PGID:
+		if (pid <= 0)
+			return -EINVAL;
+		pid = -pid;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	ret = do_wait(pid, options, infop, NULL, ru);
+
+	/* avoid REGPARM breakage on x86: */
+	prevent_tail_call(ret);
+	return ret;
+}
+
+asmlinkage long sys_wait4(pid_t pid, int __user *stat_addr,
+			  int options, struct rusage __user *ru)
+{
+	long ret;
+
+	if (options & ~(WNOHANG|WUNTRACED|__WNOTHREAD|__WCLONE|__WALL))
+		return -EINVAL;
+	ret = do_wait(pid, options | WEXITED, NULL, stat_addr, ru);
+
+	/* avoid REGPARM breakage on x86: */
+	prevent_tail_call(ret);
+	return ret;
+}
+
 #ifdef __ARCH_WANT_SYS_WAITPID
 
 /*
  * sys_waitpid() remains for compatibility. waitpid() should be
  * implemented by calling sys_wait4() from libc.a.
  */
-asmlinkage long sys_waitpid(pid_t pid, unsigned __user *stat_addr, int options)
+asmlinkage long sys_waitpid(pid_t pid, int __user *stat_addr, int options)
 {
 	return sys_wait4(pid, stat_addr, options, NULL);
 }
diff -Nru a/kernel/fork.c b/kernel/fork.c
--- a/kernel/fork.c	2004-10-18 14:55:54 -07:00
+++ b/kernel/fork.c	2004-10-18 14:55:54 -07:00
@@ -29,12 +29,14 @@
 #include <linux/fs.h>
 #include <linux/cpu.h>
 #include <linux/security.h>
+#include <linux/swap.h>
 #include <linux/syscalls.h>
 #include <linux/jiffies.h>
 #include <linux/futex.h>
 #include <linux/ptrace.h>
 #include <linux/mount.h>
 #include <linux/audit.h>
+#include <linux/profile.h>
 #include <linux/rmap.h>
 
 #include <asm/pgtable.h>
@@ -75,11 +77,12 @@
 static kmem_cache_t *task_struct_cachep;
 #endif
 
-static void free_task(struct task_struct *tsk)
+void free_task(struct task_struct *tsk)
 {
 	free_thread_info(tsk->thread_info);
 	free_task_struct(tsk);
 }
+EXPORT_SYMBOL(free_task);
 
 void __put_task_struct(struct task_struct *tsk)
 {
@@ -92,7 +95,9 @@
 	security_task_free(tsk);
 	free_uid(tsk->user);
 	put_group_info(tsk->group_info);
-	free_task(tsk);
+
+	if (!profile_handoff_task(tsk))
+		free_task(tsk);
 }
 
 void fastcall add_wait_queue(wait_queue_head_t *q, wait_queue_t * wait)
@@ -151,7 +156,12 @@
 	spin_lock_irqsave(&q->lock, flags);
 	if (list_empty(&wait->task_list))
 		__add_wait_queue(q, wait);
-	set_current_state(state);
+	/*
+	 * don't alter the task state if this is just going to
+	 * queue an async wait queue callback
+	 */
+	if (is_sync_wait(wait))
+		set_current_state(state);
 	spin_unlock_irqrestore(&q->lock, flags);
 }
 
@@ -166,7 +176,12 @@
 	spin_lock_irqsave(&q->lock, flags);
 	if (list_empty(&wait->task_list))
 		__add_wait_queue_tail(q, wait);
-	set_current_state(state);
+	/*
+	 * don't alter the task state if this is just going to
+ 	 * queue an async wait queue callback
+	 */
+	if (is_sync_wait(wait))
+		set_current_state(state);
 	spin_unlock_irqrestore(&q->lock, flags);
 }
 
@@ -279,7 +294,7 @@
 	mm->locked_vm = 0;
 	mm->mmap = NULL;
 	mm->mmap_cache = NULL;
-	mm->free_area_cache = TASK_UNMAPPED_BASE;
+	mm->free_area_cache = oldmm->mmap_base;
 	mm->map_count = 0;
 	mm->rss = 0;
 	cpus_clear(mm->cpu_vm_mask);
@@ -302,8 +317,11 @@
 	for (mpnt = current->mm->mmap ; mpnt ; mpnt = mpnt->vm_next) {
 		struct file *file;
 
-		if(mpnt->vm_flags & VM_DONTCOPY)
+		if (mpnt->vm_flags & VM_DONTCOPY) {
+			__vm_stat_account(mm, mpnt->vm_flags, mpnt->vm_file,
+							-vma_pages(mpnt));
 			continue;
+		}
 		charge = 0;
 		if (mpnt->vm_flags & VM_ACCOUNT) {
 			unsigned int len = (mpnt->vm_end - mpnt->vm_start) >> PAGE_SHIFT;
@@ -324,7 +342,6 @@
 		tmp->vm_mm = mm;
 		tmp->vm_next = NULL;
 		anon_vma_link(tmp);
-		vma_prio_tree_init(tmp);
 		file = tmp->vm_file;
 		if (file) {
 			struct inode *inode = file->f_dentry->d_inode;
@@ -462,26 +479,43 @@
 		spin_unlock(&mmlist_lock);
 		exit_aio(mm);
 		exit_mmap(mm);
+		put_swap_token(mm);
 		mmdrop(mm);
 	}
 }
+EXPORT_SYMBOL_GPL(mmput);
 
-/*
- * Checks if the use count of an mm is non-zero and if so
- * returns a reference to it after bumping up the use count.
- * If the use count is zero, it means this mm is going away,
- * so return NULL.
+/**
+ * get_task_mm - acquire a reference to the task's mm
+ *
+ * Returns %NULL if the task has no mm.  Checks if the use count
+ * of the mm is non-zero and if so returns a reference to it, after
+ * bumping up the use count.  User must release the mm via mmput()
+ * after use.  Typically used by /proc and ptrace.
+ *
+ * If the use count is zero, it means that this mm is going away,
+ * so return %NULL.  This only happens in the case of an AIO daemon
+ * which has temporarily adopted an mm (see use_mm), in the course
+ * of its final mmput, before exit_aio has completed.
  */
-struct mm_struct *mmgrab(struct mm_struct *mm)
+struct mm_struct *get_task_mm(struct task_struct *task)
 {
-	spin_lock(&mmlist_lock);
-	if (!atomic_read(&mm->mm_users))
-		mm = NULL;
-	else
-		atomic_inc(&mm->mm_users);
-	spin_unlock(&mmlist_lock);
+	struct mm_struct *mm;
+
+	task_lock(task);
+	mm = task->mm;
+	if (mm) {
+		spin_lock(&mmlist_lock);
+		if (!atomic_read(&mm->mm_users))
+			mm = NULL;
+		else
+			atomic_inc(&mm->mm_users);
+		spin_unlock(&mmlist_lock);
+	}
+	task_unlock(task);
 	return mm;
 }
+EXPORT_SYMBOL_GPL(get_task_mm);
 
 /* Please note the differences between mmput and mm_release.
  * mmput is called whenever we stop holding onto a mm_struct,
@@ -527,8 +561,7 @@
 	int retval;
 
 	tsk->min_flt = tsk->maj_flt = 0;
-	tsk->cmin_flt = tsk->cmaj_flt = 0;
-	tsk->nvcsw = tsk->nivcsw = tsk->cnvcsw = tsk->cnivcsw = 0;
+	tsk->nvcsw = tsk->nivcsw = 0;
 
 	tsk->mm = NULL;
 	tsk->active_mm = NULL;
@@ -835,6 +868,10 @@
 	sig->leader = 0;	/* session leadership doesn't inherit */
 	sig->tty_old_pgrp = 0;
 
+	sig->utime = sig->stime = sig->cutime = sig->cstime = 0;
+	sig->nvcsw = sig->nivcsw = sig->cnvcsw = sig->cnivcsw = 0;
+	sig->min_flt = sig->maj_flt = sig->cmin_flt = sig->cmaj_flt = 0;
+
 	return 0;
 }
 
@@ -864,12 +901,13 @@
  * parts of the process environment (as per the clone
  * flags). The actual kick-off is left to the caller.
  */
-struct task_struct *copy_process(unsigned long clone_flags,
+static task_t *copy_process(unsigned long clone_flags,
 				 unsigned long stack_start,
 				 struct pt_regs *regs,
 				 unsigned long stack_size,
 				 int __user *parent_tidptr,
-				 int __user *child_tidptr)
+				 int __user *child_tidptr,
+				 int pid)
 {
 	int retval;
 	struct task_struct *p = NULL;
@@ -929,13 +967,7 @@
 
 	p->did_exec = 0;
 	copy_flags(clone_flags, p);
-	if (clone_flags & CLONE_IDLETASK)
-		p->pid = 0;
-	else {
-		p->pid = alloc_pidmap();
-		if (p->pid == -1)
-			goto bad_fork_cleanup;
-	}
+	p->pid = pid;
 	retval = -EFAULT;
 	if (clone_flags & CLONE_PARENT_SETTID)
 		if (put_user(p->pid, parent_tidptr))
@@ -959,11 +991,11 @@
 	p->real_timer.data = (unsigned long) p;
 
 	p->utime = p->stime = 0;
-	p->cutime = p->cstime = 0;
 	p->lock_depth = -1;		/* -1 = no lock */
-	p->start_time = get_jiffies_64();
+	do_posix_clock_monotonic_gettime(&p->start_time);
 	p->security = NULL;
 	p->io_context = NULL;
+	p->io_wait = NULL;
 	p->audit_context = NULL;
 #ifdef CONFIG_NUMA
  	p->mempolicy = mpol_copy(p->mempolicy);
@@ -1032,6 +1064,17 @@
 
 	/* Need tasklist lock for parent etc handling! */
 	write_lock_irq(&tasklist_lock);
+
+	/*
+	 * The task hasn't been attached yet, so cpus_allowed mask cannot
+	 * have changed. The cpus_allowed mask of the parent may have
+	 * changed after it was copied first time, and it may then move to
+	 * another CPU - so we re-copy it here and set the child's CPU to
+	 * the parent's CPU. This avoids alot of nasty races.
+	 */
+	p->cpus_allowed = current->cpus_allowed;
+	set_task_cpu(p, smp_processor_id());
+
 	/*
 	 * Check for pending SIGKILL! The new thread should not be allowed
 	 * to slip out of an OOM kill. (or normal SIGKILL.)
@@ -1043,7 +1086,7 @@
 	}
 
 	/* CLONE_PARENT re-uses the old parent */
-	if (clone_flags & CLONE_PARENT)
+	if (clone_flags & (CLONE_PARENT|CLONE_THREAD))
 		p->real_parent = current->real_parent;
 	else
 		p->real_parent = current;
@@ -1079,18 +1122,17 @@
 	}
 
 	SET_LINKS(p);
-	if (p->ptrace & PT_PTRACED)
+	if (unlikely(p->ptrace & PT_PTRACED))
 		__ptrace_link(p, current->parent);
 
 	attach_pid(p, PIDTYPE_PID, p->pid);
+	attach_pid(p, PIDTYPE_TGID, p->tgid);
 	if (thread_group_leader(p)) {
-		attach_pid(p, PIDTYPE_TGID, p->tgid);
 		attach_pid(p, PIDTYPE_PGID, process_group(p));
 		attach_pid(p, PIDTYPE_SID, p->signal->session);
 		if (p->pid)
 			__get_cpu_var(process_counts)++;
-	} else
-		link_pid(p, p->pids + PIDTYPE_TGID, &p->group_leader->pids[PIDTYPE_TGID].pid);
+	}
 
 	nr_threads++;
 	write_unlock_irq(&tasklist_lock);
@@ -1104,9 +1146,8 @@
 bad_fork_cleanup_namespace:
 	exit_namespace(p);
 bad_fork_cleanup_mm:
-	exit_mm(p);
-	if (p->active_mm)
-		mmdrop(p->active_mm);
+	if (p->mm)
+		mmput(p->mm);
 bad_fork_cleanup_signal:
 	exit_signal(p);
 bad_fork_cleanup_sighand:
@@ -1126,8 +1167,6 @@
 	mpol_free(p->mempolicy);
 #endif
 bad_fork_cleanup:
-	if (p->pid > 0)
-		free_pidmap(p->pid);
 	if (p->binfmt)
 		module_put(p->binfmt->module);
 bad_fork_cleanup_put_domain:
@@ -1141,9 +1180,28 @@
 	goto fork_out;
 }
 
+struct pt_regs * __devinit __attribute__((weak)) idle_regs(struct pt_regs *regs)
+{
+	memset(regs, 0, sizeof(struct pt_regs));
+	return regs;
+}
+
+task_t * __devinit fork_idle(int cpu)
+{
+	task_t *task;
+	struct pt_regs regs;
+
+	task = copy_process(CLONE_VM, 0, idle_regs(&regs), 0, NULL, NULL, 0);
+	if (!task)
+		return ERR_PTR(-ENOMEM);
+	init_idle(task, cpu);
+	unhash_process(task);
+	return task;
+}
+
 static inline int fork_traceflag (unsigned clone_flags)
 {
-	if (clone_flags & (CLONE_UNTRACED | CLONE_IDLETASK))
+	if (clone_flags & CLONE_UNTRACED)
 		return 0;
 	else if (clone_flags & CLONE_VFORK) {
 		if (current->ptrace & PT_TRACE_VFORK)
@@ -1172,21 +1230,21 @@
 {
 	struct task_struct *p;
 	int trace = 0;
-	long pid;
+	long pid = alloc_pidmap();
 
+	if (pid < 0)
+		return -EAGAIN;
 	if (unlikely(current->ptrace)) {
 		trace = fork_traceflag (clone_flags);
 		if (trace)
 			clone_flags |= CLONE_PTRACE;
 	}
 
-	p = copy_process(clone_flags, stack_start, regs, stack_size, parent_tidptr, child_tidptr);
+	p = copy_process(clone_flags, stack_start, regs, stack_size, parent_tidptr, child_tidptr, pid);
 	/*
 	 * Do this prior waking up the new thread - the thread pointer
 	 * might get invalid after that point, if the thread exits quickly.
 	 */
-	pid = IS_ERR(p) ? PTR_ERR(p) : p->pid;
-
 	if (!IS_ERR(p)) {
 		struct completion vfork;
 
@@ -1203,31 +1261,10 @@
 			set_tsk_thread_flag(p, TIF_SIGPENDING);
 		}
 
-		if (!(clone_flags & CLONE_STOPPED)) {
-			/*
-			 * Do the wakeup last. On SMP we treat fork() and
-			 * CLONE_VM separately, because fork() has already
-			 * created cache footprint on this CPU (due to
-			 * copying the pagetables), hence migration would
-			 * probably be costy. Threads on the other hand
-			 * have less traction to the current CPU, and if
-			 * there's an imbalance then the scheduler can
-			 * migrate this fresh thread now, before it
-			 * accumulates a larger cache footprint:
-			 */
-			if (clone_flags & CLONE_VM)
-				wake_up_forked_thread(p);
-			else
-				wake_up_forked_process(p);
-		} else {
-			int cpu = get_cpu();
-
+		if (!(clone_flags & CLONE_STOPPED))
+			wake_up_new_task(p, clone_flags);
+		else
 			p->state = TASK_STOPPED;
-			if (cpu_is_offline(task_cpu(p)))
-				set_task_cpu(p, cpu);
-
-			put_cpu();
-		}
 		++total_forks;
 
 		if (unlikely (trace)) {
@@ -1239,12 +1276,10 @@
 			wait_for_completion(&vfork);
 			if (unlikely (current->ptrace & PT_TRACE_VFORK_DONE))
 				ptrace_notify ((PTRACE_EVENT_VFORK_DONE << 8) | SIGTRAP);
-		} else
-			/*
-			 * Let the child process run first, to avoid most of the
-			 * COW overhead when the child exec()s afterwards.
-			 */
-			set_need_resched();
+		}
+	} else {
+		free_pidmap(pid);
+		pid = PTR_ERR(p);
 	}
 	return pid;
 }
diff -Nru a/kernel/kmod.c b/kernel/kmod.c
--- a/kernel/kmod.c	2004-10-18 14:56:27 -07:00
+++ b/kernel/kmod.c	2004-10-18 14:56:27 -07:00
@@ -272,10 +272,8 @@
 }
 EXPORT_SYMBOL(call_usermodehelper);
 
-static __init int usermodehelper_init(void)
+void __init usermodehelper_init(void)
 {
 	khelper_wq = create_singlethread_workqueue("khelper");
 	BUG_ON(!khelper_wq);
-	return 0;
 }
-core_initcall(usermodehelper_init);
diff -Nru a/kernel/kprobes.c b/kernel/kprobes.c
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/kernel/kprobes.c	2004-10-18 14:57:24 -07:00
@@ -0,0 +1,149 @@
+/*
+ *  Kernel Probes (KProbes)
+ *  kernel/kprobes.c
+ *
+ * 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.
+ *
+ * Copyright (C) IBM Corporation, 2002, 2004
+ *
+ * 2002-Oct	Created by Vamsi Krishna S <vamsi_krishna@in.ibm.com> Kernel
+ *		Probes initial implementation (includes suggestions from
+ *		Rusty Russell).
+ * 2004-Aug	Updated by Prasanna S Panchamukhi <prasanna@in.ibm.com> with
+ *		hlists and exceptions notifier as suggested by Andi Kleen.
+ * 2004-July	Suparna Bhattacharya <suparna@in.ibm.com> added jumper probes
+ *		interface to access function arguments.
+ * 2004-Sep	Prasanna S Panchamukhi <prasanna@in.ibm.com> Changed Kprobes
+ *		exceptions notifier to be first on the priority list.
+ */
+#include <linux/kprobes.h>
+#include <linux/spinlock.h>
+#include <linux/hash.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <asm/cacheflush.h>
+#include <asm/errno.h>
+#include <asm/kdebug.h>
+
+#define KPROBE_HASH_BITS 6
+#define KPROBE_TABLE_SIZE (1 << KPROBE_HASH_BITS)
+
+static struct hlist_head kprobe_table[KPROBE_TABLE_SIZE];
+
+unsigned int kprobe_cpu = NR_CPUS;
+static spinlock_t kprobe_lock = SPIN_LOCK_UNLOCKED;
+
+/* Locks kprobe: irqs must be disabled */
+void lock_kprobes(void)
+{
+	spin_lock(&kprobe_lock);
+	kprobe_cpu = smp_processor_id();
+}
+
+void unlock_kprobes(void)
+{
+	kprobe_cpu = NR_CPUS;
+	spin_unlock(&kprobe_lock);
+}
+
+/* You have to be holding the kprobe_lock */
+struct kprobe *get_kprobe(void *addr)
+{
+	struct hlist_head *head;
+	struct hlist_node *node;
+
+	head = &kprobe_table[hash_ptr(addr, KPROBE_HASH_BITS)];
+	hlist_for_each(node, head) {
+		struct kprobe *p = hlist_entry(node, struct kprobe, hlist);
+		if (p->addr == addr)
+			return p;
+	}
+	return NULL;
+}
+
+int register_kprobe(struct kprobe *p)
+{
+	int ret = 0;
+	unsigned long flags;
+
+	spin_lock_irqsave(&kprobe_lock, flags);
+	INIT_HLIST_NODE(&p->hlist);
+	if (get_kprobe(p->addr)) {
+		ret = -EEXIST;
+		goto out;
+	}
+	hlist_add_head(&p->hlist,
+		       &kprobe_table[hash_ptr(p->addr, KPROBE_HASH_BITS)]);
+
+	arch_prepare_kprobe(p);
+	p->opcode = *p->addr;
+	*p->addr = BREAKPOINT_INSTRUCTION;
+	flush_icache_range((unsigned long) p->addr,
+			   (unsigned long) p->addr + sizeof(kprobe_opcode_t));
+      out:
+	spin_unlock_irqrestore(&kprobe_lock, flags);
+	return ret;
+}
+
+void unregister_kprobe(struct kprobe *p)
+{
+	unsigned long flags;
+	spin_lock_irqsave(&kprobe_lock, flags);
+	*p->addr = p->opcode;
+	hlist_del(&p->hlist);
+	flush_icache_range((unsigned long) p->addr,
+			   (unsigned long) p->addr + sizeof(kprobe_opcode_t));
+	spin_unlock_irqrestore(&kprobe_lock, flags);
+}
+
+static struct notifier_block kprobe_exceptions_nb = {
+	.notifier_call = kprobe_exceptions_notify,
+	.priority = 0x7fffffff /* we need to notified first */
+};
+
+int register_jprobe(struct jprobe *jp)
+{
+	/* Todo: Verify probepoint is a function entry point */
+	jp->kp.pre_handler = setjmp_pre_handler;
+	jp->kp.break_handler = longjmp_break_handler;
+
+	return register_kprobe(&jp->kp);
+}
+
+void unregister_jprobe(struct jprobe *jp)
+{
+	unregister_kprobe(&jp->kp);
+}
+
+static int __init init_kprobes(void)
+{
+	int i, err = 0;
+
+	/* FIXME allocate the probe table, currently defined statically */
+	/* initialize all list heads */
+	for (i = 0; i < KPROBE_TABLE_SIZE; i++)
+		INIT_HLIST_HEAD(&kprobe_table[i]);
+
+	err = register_die_notifier(&kprobe_exceptions_nb);
+	return err;
+}
+
+__initcall(init_kprobes);
+
+EXPORT_SYMBOL_GPL(register_kprobe);
+EXPORT_SYMBOL_GPL(unregister_kprobe);
+EXPORT_SYMBOL_GPL(register_jprobe);
+EXPORT_SYMBOL_GPL(unregister_jprobe);
+EXPORT_SYMBOL_GPL(jprobe_return);
diff -Nru a/kernel/module.c b/kernel/module.c
--- a/kernel/module.c	2004-10-18 14:56:48 -07:00
+++ b/kernel/module.c	2004-10-18 14:56:48 -07:00
@@ -89,13 +89,6 @@
 	return try_module_get(mod);
 }
 
-/* Stub function for modules which don't have an initfn */
-int init_module(void)
-{
-	return 0;
-}
-EXPORT_SYMBOL(init_module);
-
 /* A thread that wants to hold a reference to a module only while it
  * is running can call ths to safely exit.
  * nfsd and lockd use this.
@@ -529,12 +522,6 @@
 /* This exists whether we can unload or not */
 static void free_module(struct module *mod);
 
-/* Stub function for modules which don't have an exitfn */
-void cleanup_module(void)
-{
-}
-EXPORT_SYMBOL(cleanup_module);
-
 static void wait_for_zero_refcount(struct module *mod)
 {
 	/* Since we might sleep for some time, drop the semaphore first */
@@ -589,7 +576,7 @@
 	}
 
 	/* If it has an init func, it must have an exit func to unload */
-	if ((mod->init != init_module && mod->exit == cleanup_module)
+	if ((mod->init != NULL && mod->exit == NULL)
 	    || mod->unsafe) {
 		forced = try_force(flags);
 		if (!forced) {
@@ -610,9 +597,11 @@
 		wait_for_zero_refcount(mod);
 
 	/* Final destruction now noone is using it. */
-	up(&module_mutex);
-	mod->exit();
-	down(&module_mutex);
+	if (mod->exit != NULL) {
+		up(&module_mutex);
+		mod->exit();
+		down(&module_mutex);
+	}
 	free_module(mod);
 
  out:
@@ -639,7 +628,7 @@
 		seq_printf(m, "[unsafe],");
 	}
 
-	if (mod->init != init_module && mod->exit == cleanup_module) {
+	if (mod->init != NULL && mod->exit == NULL) {
 		printed_something = 1;
 		seq_printf(m, "[permanent],");
 	}
@@ -725,19 +714,6 @@
 #endif /* CONFIG_MODULE_UNLOAD */
 
 #ifdef CONFIG_OBSOLETE_MODPARM
-static int param_set_byte(const char *val, struct kernel_param *kp)  
-{
-	char *endp;
-	long l;
-
-	if (!val) return -EINVAL;
-	l = simple_strtol(val, &endp, 0);
-	if (endp == val || *endp || ((char)l != l))
-		return -EINVAL;
-	*((char *)kp->arg) = l;
-	return 0;
-}
-
 /* Bounds checking done below */
 static int obsparm_copy_string(const char *val, struct kernel_param *kp)
 {
@@ -1551,9 +1527,6 @@
 	secstrings = (void *)hdr + sechdrs[hdr->e_shstrndx].sh_offset;
 	sechdrs[0].sh_addr = 0;
 
-	/* And these should exist, but gcc whinges if we don't init them */
-	symindex = strindex = 0;
-
 	for (i = 1; i < hdr->e_shnum; i++) {
 		if (sechdrs[i].sh_type != SHT_NOBITS
 		    && len < sechdrs[i].sh_offset + sechdrs[i].sh_size)
@@ -1585,6 +1558,13 @@
 	}
 	mod = (void *)sechdrs[modindex].sh_addr;
 
+	if (symindex == 0) {
+		printk(KERN_WARNING "%s: module has no symbols (stripped?)\n",
+		       mod->name);
+		err = -ENOEXEC;
+		goto free_hdr;
+	}
+
 	/* Optional sections */
 	exportindex = find_sec(hdr, sechdrs, secstrings, "__ksymtab");
 	gplindex = find_sec(hdr, sechdrs, secstrings, "__ksymtab_gpl");
@@ -1845,7 +1825,7 @@
 		const char __user *uargs)
 {
 	struct module *mod;
-	int ret;
+	int ret = 0;
 
 	/* Must have permission */
 	if (!capable(CAP_SYS_MODULE))
@@ -1884,7 +1864,8 @@
 	up(&notify_mutex);
 
 	/* Start the module */
-	ret = mod->init();
+	if (mod->init != NULL)
+		ret = mod->init();
 	if (ret < 0) {
 		/* Init routine failed: abort.  Try to protect us from
                    buggy refcounters. */
diff -Nru a/kernel/panic.c b/kernel/panic.c
--- a/kernel/panic.c	2004-10-18 14:57:04 -07:00
+++ b/kernel/panic.c	2004-10-18 14:57:04 -07:00
@@ -59,13 +59,7 @@
 	va_start(args, fmt);
 	vsnprintf(buf, sizeof(buf), fmt, args);
 	va_end(args);
-	printk(KERN_EMERG "Kernel panic: %s\n",buf);
-	if (in_interrupt())
-		printk(KERN_EMERG "In interrupt handler - not syncing\n");
-	else if (!current->pid)
-		printk(KERN_EMERG "In idle task - not syncing\n");
-	else
-		sys_sync();
+	printk(KERN_EMERG "Kernel panic - not syncing: %s\n",buf);
 	bust_spinlocks(0);
 
 #ifdef CONFIG_SMP
diff -Nru a/kernel/params.c b/kernel/params.c
--- a/kernel/params.c	2004-10-18 14:56:49 -07:00
+++ b/kernel/params.c	2004-10-18 14:56:49 -07:00
@@ -171,6 +171,7 @@
 		return sprintf(buffer, format, *((type *)kp->arg));	\
 	}
 
+STANDARD_PARAM_DEF(byte, unsigned char, "%c", unsigned long, simple_strtoul);
 STANDARD_PARAM_DEF(short, short, "%hi", long, simple_strtol);
 STANDARD_PARAM_DEF(ushort, unsigned short, "%hu", unsigned long, simple_strtoul);
 STANDARD_PARAM_DEF(int, int, "%i", long, simple_strtol);
@@ -339,6 +340,14 @@
 	return 0;
 }
 
+int param_get_string(char *buffer, struct kernel_param *kp)
+{
+	struct kparam_string *kps = kp->arg;
+	return strlcpy(buffer, kps->string, kps->maxlen);
+}
+
+EXPORT_SYMBOL(param_set_byte);
+EXPORT_SYMBOL(param_get_byte);
 EXPORT_SYMBOL(param_set_short);
 EXPORT_SYMBOL(param_get_short);
 EXPORT_SYMBOL(param_set_ushort);
@@ -360,3 +369,4 @@
 EXPORT_SYMBOL(param_array_set);
 EXPORT_SYMBOL(param_array_get);
 EXPORT_SYMBOL(param_set_copystring);
+EXPORT_SYMBOL(param_get_string);
diff -Nru a/kernel/pid.c b/kernel/pid.c
--- a/kernel/pid.c	2004-10-18 14:56:33 -07:00
+++ b/kernel/pid.c	2004-10-18 14:56:33 -07:00
@@ -27,7 +27,7 @@
 #include <linux/hash.h>
 
 #define pid_hashfn(nr) hash_long((unsigned long)nr, pidhash_shift)
-static struct list_head *pid_hash[PIDTYPE_MAX];
+static struct hlist_head *pid_hash[PIDTYPE_MAX];
 static int pidhash_shift;
 
 int pid_max = PID_MAX_DEFAULT;
@@ -146,73 +146,66 @@
 	return -1;
 }
 
-fastcall struct pid *find_pid(enum pid_type type, int nr)
+struct pid * fastcall find_pid(enum pid_type type, int nr)
 {
-	struct list_head *elem, *bucket = &pid_hash[type][pid_hashfn(nr)];
+	struct hlist_node *elem;
 	struct pid *pid;
 
-	__list_for_each(elem, bucket) {
-		pid = list_entry(elem, struct pid, hash_chain);
+	hlist_for_each_entry(pid, elem,
+			&pid_hash[type][pid_hashfn(nr)], pid_chain) {
 		if (pid->nr == nr)
 			return pid;
 	}
 	return NULL;
 }
 
-void fastcall link_pid(task_t *task, struct pid_link *link, struct pid *pid)
-{
-	atomic_inc(&pid->count);
-	list_add_tail(&link->pid_chain, &pid->task_list);
-	link->pidptr = pid;
-}
-
 int fastcall attach_pid(task_t *task, enum pid_type type, int nr)
 {
-	struct pid *pid = find_pid(type, nr);
+	struct pid *pid, *task_pid;
 
-	if (pid)
-		atomic_inc(&pid->count);
-	else {
-		pid = &task->pids[type].pid;
-		pid->nr = nr;
-		atomic_set(&pid->count, 1);
-		INIT_LIST_HEAD(&pid->task_list);
-		pid->task = task;
-		get_task_struct(task);
-		list_add(&pid->hash_chain, &pid_hash[type][pid_hashfn(nr)]);
+	task_pid = &task->pids[type];
+	pid = find_pid(type, nr);
+	if (pid == NULL) {
+		hlist_add_head(&task_pid->pid_chain,
+				&pid_hash[type][pid_hashfn(nr)]);
+		INIT_LIST_HEAD(&task_pid->pid_list);
+	} else {
+		INIT_HLIST_NODE(&task_pid->pid_chain);
+		list_add_tail(&task_pid->pid_list, &pid->pid_list);
 	}
-	list_add_tail(&task->pids[type].pid_chain, &pid->task_list);
-	task->pids[type].pidptr = pid;
+	task_pid->nr = nr;
 
 	return 0;
 }
 
 static inline int __detach_pid(task_t *task, enum pid_type type)
 {
-	struct pid_link *link = task->pids + type;
-	struct pid *pid = link->pidptr;
+	struct pid *pid, *pid_next;
 	int nr;
 
-	list_del(&link->pid_chain);
-	if (!atomic_dec_and_test(&pid->count))
-		return 0;
-
+	pid = &task->pids[type];
+	if (!hlist_unhashed(&pid->pid_chain)) {
+		hlist_del(&pid->pid_chain);
+		if (!list_empty(&pid->pid_list)) {
+			pid_next = list_entry(pid->pid_list.next,
+						struct pid, pid_list);
+			/* insert next pid from pid_list to hash */
+			hlist_add_head(&pid_next->pid_chain,
+				&pid_hash[type][pid_hashfn(pid_next->nr)]);
+		}
+	}
+	list_del(&pid->pid_list);
 	nr = pid->nr;
-	list_del(&pid->hash_chain);
-	put_task_struct(pid->task);
+	pid->nr = 0;
 
 	return nr;
 }
 
-static void _detach_pid(task_t *task, enum pid_type type)
-{
-	__detach_pid(task, type);
-}
-
 void fastcall detach_pid(task_t *task, enum pid_type type)
 {
-	int nr = __detach_pid(task, type);
+	int nr;
 
+	nr = __detach_pid(task, type);
 	if (!nr)
 		return;
 
@@ -222,16 +215,18 @@
 	free_pidmap(nr);
 }
 
-task_t *find_task_by_pid(int nr)
+task_t *find_task_by_pid_type(int type, int nr)
 {
-	struct pid *pid = find_pid(PIDTYPE_PID, nr);
+	struct pid *pid;
 
+	pid = find_pid(type, nr);
 	if (!pid)
 		return NULL;
-	return pid_task(pid->task_list.next, PIDTYPE_PID);
+
+	return pid_task(&pid->pid_list, type);
 }
 
-EXPORT_SYMBOL(find_task_by_pid);
+EXPORT_SYMBOL(find_task_by_pid_type);
 
 /*
  * This function switches the PIDs if a non-leader thread calls
@@ -240,13 +235,13 @@
  */
 void switch_exec_pids(task_t *leader, task_t *thread)
 {
-	_detach_pid(leader, PIDTYPE_PID);
-	_detach_pid(leader, PIDTYPE_TGID);
-	_detach_pid(leader, PIDTYPE_PGID);
-	_detach_pid(leader, PIDTYPE_SID);
+	__detach_pid(leader, PIDTYPE_PID);
+	__detach_pid(leader, PIDTYPE_TGID);
+	__detach_pid(leader, PIDTYPE_PGID);
+	__detach_pid(leader, PIDTYPE_SID);
 
-	_detach_pid(thread, PIDTYPE_PID);
-	_detach_pid(thread, PIDTYPE_TGID);
+	__detach_pid(thread, PIDTYPE_PID);
+	__detach_pid(thread, PIDTYPE_TGID);
 
 	leader->pid = leader->tgid = thread->pid;
 	thread->pid = thread->tgid;
@@ -271,23 +266,23 @@
 void __init pidhash_init(void)
 {
 	int i, j, pidhash_size;
-	unsigned long megabytes = max_pfn >> (20 - PAGE_SHIFT);
+	unsigned long megabytes = nr_kernel_pages >> (20 - PAGE_SHIFT);
 
 	pidhash_shift = max(4, fls(megabytes * 4));
 	pidhash_shift = min(12, pidhash_shift);
 	pidhash_size = 1 << pidhash_shift;
 
-	printk("PID hash table entries: %d (order %d: %Zd bytes)\n",
+	printk("PID hash table entries: %d (order: %d, %Zd bytes)\n",
 		pidhash_size, pidhash_shift,
-		pidhash_size * sizeof(struct list_head));
+		PIDTYPE_MAX * pidhash_size * sizeof(struct hlist_head));
 
 	for (i = 0; i < PIDTYPE_MAX; i++) {
 		pid_hash[i] = alloc_bootmem(pidhash_size *
-					sizeof(struct list_head));
+					sizeof(*(pid_hash[i])));
 		if (!pid_hash[i])
 			panic("Could not alloc pidhash!\n");
 		for (j = 0; j < pidhash_size; j++)
-			INIT_LIST_HEAD(&pid_hash[i][j]);
+			INIT_HLIST_HEAD(&pid_hash[i][j]);
 	}
 }
 
diff -Nru a/kernel/posix-timers.c b/kernel/posix-timers.c
--- a/kernel/posix-timers.c	2004-10-18 14:56:32 -07:00
+++ b/kernel/posix-timers.c	2004-10-18 14:56:32 -07:00
@@ -650,7 +650,8 @@
 				list_add(&new_timer->list,
 					 &process->signal->posix_timers);
 				spin_unlock_irqrestore(&process->sighand->siglock, flags);
-				get_task_struct(process);
+				if (new_timer->it_sigev_notify == (SIGEV_SIGNAL|SIGEV_THREAD_ID))
+					get_task_struct(process);
 			} else {
 				spin_unlock_irqrestore(&process->sighand->siglock, flags);
 				process = NULL;
@@ -1102,7 +1103,7 @@
 	if (timer->it_process) {
 		if (timer->it_sigev_notify == (SIGEV_SIGNAL|SIGEV_THREAD_ID))
 			put_task_struct(timer->it_process);
-	timer->it_process = NULL;
+		timer->it_process = NULL;
 	}
 	unlock_timer(timer, flags);
 	release_posix_timer(timer, IT_ID_SET);
@@ -1168,15 +1169,10 @@
  */
 static int do_posix_gettime(struct k_clock *clock, struct timespec *tp)
 {
-	struct timeval tv;
-
 	if (clock->clock_get)
 		return clock->clock_get(tp);
 
-	do_gettimeofday(&tv);
-	tp->tv_sec = tv.tv_sec;
-	tp->tv_nsec = tv.tv_usec * NSEC_PER_USEC;
-
+	getnstimeofday(tp);
 	return 0;
 }
 
@@ -1192,23 +1188,15 @@
 	struct timespec *tp, struct timespec *mo)
 {
 	u64 jiff;
-	struct timeval tpv;
 	unsigned int seq;
 
 	do {
 		seq = read_seqbegin(&xtime_lock);
-		do_gettimeofday(&tpv);
+		getnstimeofday(tp);
 		*mo = wall_to_monotonic;
 		jiff = jiffies_64;
 
 	} while(read_seqretry(&xtime_lock, seq));
-
-	/*
-	 * Love to get this before it is converted to usec.
-	 * It would save a div AND a mpy.
-	 */
-	tp->tv_sec = tpv.tv_sec;
-	tp->tv_nsec = tpv.tv_usec * NSEC_PER_USEC;
 
 	return jiff;
 }
diff -Nru a/kernel/power/Kconfig b/kernel/power/Kconfig
--- a/kernel/power/Kconfig	2004-10-18 14:56:50 -07:00
+++ b/kernel/power/Kconfig	2004-10-18 14:56:50 -07:00
@@ -18,6 +18,13 @@
 	  will issue the hlt instruction if nothing is to be done, thereby
 	  sending the processor to sleep and saving power.
 
+config PM_DEBUG
+	bool "Power Management Debug Support"
+	---help---
+	This option enables verbose debugging support in the Power Management
+	code. This is helpful when debugging and reporting various PM bugs, 
+	like suspend support.
+
 config SOFTWARE_SUSPEND
 	bool "Software Suspend (EXPERIMENTAL)"
 	depends on EXPERIMENTAL && PM && SWAP
@@ -42,33 +49,12 @@
 
 	  For more information take a look at Documentation/power/swsusp.txt.
 
-config PM_DISK
-	bool "Suspend-to-Disk Support"
-	depends on PM && SWAP && X86 && !X86_64
-	---help---
-	  Suspend-to-disk is a power management state in which the contents
-	  of memory are stored on disk and the entire system is shut down or
-	  put into a low-power state (e.g. ACPI S4). When the computer is 
-	  turned back on, the stored image is loaded from disk and execution
-	  resumes from where it left off before suspending. 
-
-	  This config option enables the core infrastructure necessary to 
-	  perform the suspend and resume transition. 
-
-	  Currently, this suspend-to-disk implementation is based on a forked
-	  version of the swsusp code base. As such, it's still experimental,
-	  and still relies on CONFIG_SWAP. 
-
-	  More information can be found in Documentation/power/.
-
-	  If unsure, Say N.
-
-config PM_DISK_PARTITION
+config PM_STD_PARTITION
 	string "Default resume partition"
-	depends on PM_DISK
+	depends on SOFTWARE_SUSPEND
 	default ""
 	---help---
-	  The default resume partition is the partition that the pmdisk suspend-
+	  The default resume partition is the partition that the suspend-
 	  to-disk implementation will look for a suspended disk image. 
 
 	  The partition specified here will be different for almost every user. 
@@ -77,15 +63,9 @@
 
 	  The partition specified can be overridden by specifying:
 
-		pmdisk=/dev/<other device> 
+		resume=/dev/<other device> 
 
 	  which will set the resume partition to the device specified. 
-
-	  One may also do: 
-
-		pmdisk=off
-
-	  to inform the kernel not to perform a resume transition. 
 
 	  Note there is currently not a way to specify which device to save the
 	  suspended image to. It will simply pick the first available swap 
diff -Nru a/kernel/power/Makefile b/kernel/power/Makefile
--- a/kernel/power/Makefile	2004-10-18 14:56:49 -07:00
+++ b/kernel/power/Makefile	2004-10-18 14:56:49 -07:00
@@ -1,8 +1,11 @@
 
+ifeq ($(CONFIG_PM_DEBUG),y)
+EXTRA_CFLAGS	+=	-DDEBUG
+endif
+
 swsusp-smp-$(CONFIG_SMP)	+= smp.o
 
 obj-y				:= main.o process.o console.o pm.o
-obj-$(CONFIG_SOFTWARE_SUSPEND)	+= swsusp.o $(swsusp-smp-y)
-obj-$(CONFIG_PM_DISK)		+= disk.o pmdisk.o
+obj-$(CONFIG_SOFTWARE_SUSPEND)	+= swsusp.o $(swsusp-smp-y) disk.o
 
 obj-$(CONFIG_MAGIC_SYSRQ)	+= poweroff.o
diff -Nru a/kernel/power/console.c b/kernel/power/console.c
--- a/kernel/power/console.c	2004-10-18 14:55:53 -07:00
+++ b/kernel/power/console.c	2004-10-18 14:55:53 -07:00
@@ -11,7 +11,9 @@
 
 static int new_loglevel = 10;
 static int orig_loglevel;
+#ifdef SUSPEND_CONSOLE
 static int orig_fgconsole, orig_kmsg;
+#endif
 
 int pm_prepare_console(void)
 {
@@ -50,6 +52,7 @@
 	acquire_console_sem();
 	set_console(orig_fgconsole);
 	release_console_sem();
+	kmsg_redirect = orig_kmsg;
 #endif
 	return;
 }
diff -Nru a/kernel/power/disk.c b/kernel/power/disk.c
--- a/kernel/power/disk.c	2004-10-18 14:55:54 -07:00
+++ b/kernel/power/disk.c	2004-10-18 14:55:54 -07:00
@@ -8,13 +8,11 @@
  *
  */
 
-#define DEBUG
-
-
 #include <linux/suspend.h>
 #include <linux/syscalls.h>
 #include <linux/reboot.h>
 #include <linux/string.h>
+#include <linux/device.h>
 #include <linux/delay.h>
 #include <linux/fs.h>
 #include "power.h"
@@ -23,13 +21,16 @@
 extern u32 pm_disk_mode;
 extern struct pm_ops * pm_ops;
 
-extern int pmdisk_save(void);
-extern int pmdisk_write(void);
-extern int pmdisk_read(void);
-extern int pmdisk_restore(void);
-extern int pmdisk_free(void);
+extern int swsusp_suspend(void);
+extern int swsusp_write(void);
+extern int swsusp_read(void);
+extern int swsusp_resume(void);
+extern int swsusp_free(void);
 
 
+static int noresume = 0;
+char resume_file[256] = CONFIG_PM_STD_PARTITION;
+
 /**
  *	power_down - Shut machine down for hibernate.
  *	@mode:		Suspend-to-disk mode
@@ -46,22 +47,26 @@
 	int error = 0;
 
 	local_irq_save(flags);
-	device_power_down(PM_SUSPEND_DISK);
 	switch(mode) {
 	case PM_DISK_PLATFORM:
+		device_power_down(PM_SUSPEND_DISK);
 		error = pm_ops->enter(PM_SUSPEND_DISK);
 		break;
 	case PM_DISK_SHUTDOWN:
 		printk("Powering off system\n");
+		device_shutdown();
 		machine_power_off();
 		break;
 	case PM_DISK_REBOOT:
+		device_shutdown();
 		machine_restart(NULL);
 		break;
 	}
 	machine_halt();
-	device_power_up();
-	local_irq_restore(flags);
+	/* Valid image is on the disk, if we continue we risk serious data corruption
+	   after resume. */
+	printk(KERN_CRIT "Please power me down manually\n");
+	while(1);
 	return 0;
 }
 
@@ -99,6 +104,7 @@
 {
 	device_resume();
 	platform_finish();
+	enable_nonboot_cpus();
 	thaw_processes();
 	pm_restore_console();
 }
@@ -126,6 +132,7 @@
 	/* Free memory before shutting down devices. */
 	free_some_memory();
 
+	disable_nonboot_cpus();
 	if ((error = device_suspend(PM_SUSPEND_DISK)))
 		goto Finish;
 
@@ -133,6 +140,7 @@
  Finish:
 	platform_finish();
  Thaw:
+	enable_nonboot_cpus();
 	thaw_processes();
 	pm_restore_console();
 	return error;
@@ -161,7 +169,7 @@
 
 	pr_debug("PM: snapshotting memory.\n");
 	in_suspend = 1;
-	if ((error = pmdisk_save()))
+	if ((error = swsusp_suspend()))
 		goto Done;
 
 	if (in_suspend) {
@@ -173,14 +181,14 @@
 		mb();
 		barrier();
 
-		error = pmdisk_write();
+		error = swsusp_write();
 		if (!error) {
 			error = power_down(pm_disk_mode);
 			pr_debug("PM: Power down failed.\n");
 		}
 	} else
 		pr_debug("PM: Image restored successfully.\n");
-	pmdisk_free();
+	swsusp_free();
  Done:
 	finish();
 	return error;
@@ -188,7 +196,7 @@
 
 
 /**
- *	pm_resume - Resume from a saved image.
+ *	software_resume - Resume from a saved image.
  *
  *	Called as a late_initcall (so all devices are discovered and
  *	initialized), we call pmdisk to see if we have a saved image or not.
@@ -199,13 +207,21 @@
  *
  */
 
-static int pm_resume(void)
+static int software_resume(void)
 {
 	int error;
 
+	if (noresume) {
+		/**
+		 * FIXME: If noresume is specified, we need to find the partition
+		 * and reset it back to normal swap space.
+		 */
+		return 0;
+	}
+
 	pr_debug("PM: Reading pmdisk image.\n");
 
-	if ((error = pmdisk_read()))
+	if ((error = swsusp_read()))
 		goto Done;
 
 	pr_debug("PM: Preparing system for restore.\n");
@@ -216,28 +232,18 @@
 	barrier();
 	mb();
 
-	/* FIXME: The following (comment and mdelay()) are from swsusp.
-	 * Are they really necessary?
-	 *
-	 * We do not want some readahead with DMA to corrupt our memory, right?
-	 * Do it with disabled interrupts for best effect. That way, if some
-	 * driver scheduled DMA, we have good chance for DMA to finish ;-).
-	 */
-	pr_debug("PM: Waiting for DMAs to settle down.\n");
-	mdelay(1000);
-
 	pr_debug("PM: Restoring saved image.\n");
-	pmdisk_restore();
+	swsusp_resume();
 	pr_debug("PM: Restore failed, recovering.n");
 	finish();
  Free:
-	pmdisk_free();
+	swsusp_free();
  Done:
 	pr_debug("PM: Resume from disk failed.\n");
 	return 0;
 }
 
-late_initcall(pm_resume);
+late_initcall(software_resume);
 
 
 static char * pm_disk_modes[] = {
@@ -336,3 +342,22 @@
 }
 
 core_initcall(pm_disk_init);
+
+
+static int __init resume_setup(char *str)
+{
+	if (noresume)
+		return 1;
+
+	strncpy( resume_file, str, 255 );
+	return 1;
+}
+
+static int __init noresume_setup(char *str)
+{
+	noresume = 1;
+	return 1;
+}
+
+__setup("noresume", noresume_setup);
+__setup("resume=", resume_setup);
diff -Nru a/kernel/power/main.c b/kernel/power/main.c
--- a/kernel/power/main.c	2004-10-18 14:56:20 -07:00
+++ b/kernel/power/main.c	2004-10-18 14:56:20 -07:00
@@ -8,8 +8,6 @@
  *
  */
 
-#define DEBUG
-
 #include <linux/suspend.h>
 #include <linux/kobject.h>
 #include <linux/string.h>
@@ -35,8 +33,6 @@
 {
 	down(&pm_sem);
 	pm_ops = ops;
-	if (ops->pm_disk_mode && ops->pm_disk_mode < PM_DISK_MAX)
-		pm_disk_mode = ops->pm_disk_mode;
 	up(&pm_sem);
 }
 
@@ -169,6 +165,15 @@
 	return error;
 }
 
+/*
+ * This is main interface to the outside world. It needs to be
+ * called from process context.
+ */
+int software_suspend(void)
+{
+	return enter_state(PM_SUSPEND_DISK);
+}
+
 
 /**
  *	pm_suspend - Externally visible function for suspending system.
@@ -225,8 +230,8 @@
 	p = memchr(buf, '\n', n);
 	len = p ? p - buf : n;
 
-	for (s = &pm_states[state]; *s; s++, state++) {
-		if (!strncmp(buf, *s, len))
+	for (s = &pm_states[state]; state < PM_SUSPEND_MAX; s++, state++) {
+		if (*s && !strncmp(buf, *s, len))
 			break;
 	}
 	if (*s)
diff -Nru a/kernel/power/pmdisk.c b/kernel/power/pmdisk.c
--- a/kernel/power/pmdisk.c	2004-10-18 14:56:32 -07:00
+++ /dev/null	Wed Dec 31 16:00:00 196900
@@ -1,1166 +0,0 @@
-/*
- * kernel/power/pmdisk.c - Suspend-to-disk implmentation
- *
- * This STD implementation is initially derived from swsusp (suspend-to-swap).
- * The original copyright on that was: 
- *
- * Copyright (C) 1998-2001 Gabor Kuti <seasons@fornax.hu>
- * Copyright (C) 1998,2001,2002 Pavel Machek <pavel@suse.cz>
- *
- * The additional parts are: 
- * 
- * Copyright (C) 2003 Patrick Mochel
- * Copyright (C) 2003 Open Source Development Lab
- * 
- * This file is released under the GPLv2. 
- *
- * For more information, please see the text files in Documentation/power/
- *
- */
-
-#undef DEBUG
-
-#include <linux/mm.h>
-#include <linux/bio.h>
-#include <linux/suspend.h>
-#include <linux/version.h>
-#include <linux/reboot.h>
-#include <linux/device.h>
-#include <linux/swapops.h>
-#include <linux/bootmem.h>
-#include <linux/utsname.h>
-
-#include <asm/mmu_context.h>
-
-#include "power.h"
-
-
-extern asmlinkage int pmdisk_arch_suspend(int resume);
-
-#define __ADDRESS(x)  ((unsigned long) phys_to_virt(x))
-#define ADDRESS(x) __ADDRESS((x) << PAGE_SHIFT)
-#define ADDRESS2(x) __ADDRESS(__pa(x))		/* Needed for x86-64 where some pages are in memory twice */
-
-/* References to section boundaries */
-extern char __nosave_begin, __nosave_end;
-
-extern int is_head_of_free_region(struct page *);
-
-/* Variables to be preserved over suspend */
-static int pagedir_order_check;
-static int nr_copy_pages_check;
-
-/* For resume= kernel option */
-static char resume_file[256] = CONFIG_PM_DISK_PARTITION;
-
-static dev_t resume_device;
-/* Local variables that should not be affected by save */
-unsigned int pmdisk_pages __nosavedata = 0;
-
-/* Suspend pagedir is allocated before final copy, therefore it
-   must be freed after resume 
-
-   Warning: this is evil. There are actually two pagedirs at time of
-   resume. One is "pagedir_save", which is empty frame allocated at
-   time of suspend, that must be freed. Second is "pagedir_nosave", 
-   allocated at time of resume, that travels through memory not to
-   collide with anything.
- */
-suspend_pagedir_t *pm_pagedir_nosave __nosavedata = NULL;
-static suspend_pagedir_t *pagedir_save;
-static int pagedir_order __nosavedata = 0;
-
-
-struct pmdisk_info {
-	struct new_utsname	uts;
-	u32			version_code;
-	unsigned long		num_physpages;
-	int			cpus;
-	unsigned long		image_pages;
-	unsigned long		pagedir_pages;
-	swp_entry_t		pagedir[768];
-} __attribute__((aligned(PAGE_SIZE))) pmdisk_info;
-
-
-
-#define PMDISK_SIG	"pmdisk-swap1"
-
-struct pmdisk_header {
-	char reserved[PAGE_SIZE - 20 - sizeof(swp_entry_t)];
-	swp_entry_t pmdisk_info;
-	char	orig_sig[10];
-	char	sig[10];
-} __attribute__((packed, aligned(PAGE_SIZE))) pmdisk_header;
-
-/*
- * XXX: We try to keep some more pages free so that I/O operations succeed
- * without paging. Might this be more?
- */
-#define PAGES_FOR_IO	512
-
-
-/*
- * Saving part...
- */
-
-
-/* We memorize in swapfile_used what swap devices are used for suspension */
-#define SWAPFILE_UNUSED    0
-#define SWAPFILE_SUSPEND   1	/* This is the suspending device */
-#define SWAPFILE_IGNORED   2	/* Those are other swap devices ignored for suspension */
-
-static unsigned short swapfile_used[MAX_SWAPFILES];
-static unsigned short root_swap;
-
-
-static int mark_swapfiles(swp_entry_t prev)
-{
-	int error;
-
-	rw_swap_page_sync(READ, 
-			  swp_entry(root_swap, 0),
-			  virt_to_page((unsigned long)&pmdisk_header));
-	if (!memcmp("SWAP-SPACE",pmdisk_header.sig,10) ||
-	    !memcmp("SWAPSPACE2",pmdisk_header.sig,10)) {
-		memcpy(pmdisk_header.orig_sig,pmdisk_header.sig,10);
-		memcpy(pmdisk_header.sig,PMDISK_SIG,10);
-		pmdisk_header.pmdisk_info = prev;
-		error = rw_swap_page_sync(WRITE, 
-					  swp_entry(root_swap, 0),
-					  virt_to_page((unsigned long)
-						       &pmdisk_header));
-	} else {
-		pr_debug("pmdisk: Partition is not swap space.\n");
-		error = -ENODEV;
-	}
-	return error;
-}
-
-static int read_swapfiles(void) /* This is called before saving image */
-{
-	int i, len;
-	
-	len=strlen(resume_file);
-	root_swap = 0xFFFF;
-	
-	swap_list_lock();
-	for(i=0; i<MAX_SWAPFILES; i++) {
-		if (swap_info[i].flags == 0) {
-			swapfile_used[i]=SWAPFILE_UNUSED;
-		} else {
-			if(!len) {
-				pr_debug("pmdisk: Default resume partition not set.\n");
-				if(root_swap == 0xFFFF) {
-					swapfile_used[i] = SWAPFILE_SUSPEND;
-					root_swap = i;
-				} else
-					swapfile_used[i] = SWAPFILE_IGNORED;				  
-			} else {
-	  			/* we ignore all swap devices that are not the resume_file */
-				if (1) {
-// FIXME				if(resume_device == swap_info[i].swap_device) {
-					swapfile_used[i] = SWAPFILE_SUSPEND;
-					root_swap = i;
-				} else
-				  	swapfile_used[i] = SWAPFILE_IGNORED;
-			}
-		}
-	}
-	swap_list_unlock();
-	return (root_swap != 0xffff) ? 0 : -ENODEV;
-}
-
-
-/* This is called after saving image so modification
-   will be lost after resume... and that's what we want. */
-static void lock_swapdevices(void)
-{
-	int i;
-
-	swap_list_lock();
-	for(i = 0; i< MAX_SWAPFILES; i++)
-		if(swapfile_used[i] == SWAPFILE_IGNORED) {
-			swap_info[i].flags ^= 0xFF; /* we make the device unusable. A new call to
-						       lock_swapdevices can unlock the devices. */
-		}
-	swap_list_unlock();
-}
-
-
-
-/**
- *	write_swap_page - Write one page to a fresh swap location.
- *	@addr:	Address we're writing.
- *	@loc:	Place to store the entry we used.
- *
- *	Allocate a new swap entry and 'sync' it. Note we discard -EIO
- *	errors. That is an artifact left over from swsusp. It did not 
- *	check the return of rw_swap_page_sync() at all, since most pages
- *	written back to swap would return -EIO.
- *	This is a partial improvement, since we will at least return other
- *	errors, though we need to eventually fix the damn code.
- */
-
-static int write_swap_page(unsigned long addr, swp_entry_t * loc)
-{
-	swp_entry_t entry;
-	int error = 0;
-
-	entry = get_swap_page();
-	if (swp_offset(entry) && 
-	    swapfile_used[swp_type(entry)] == SWAPFILE_SUSPEND) {
-		error = rw_swap_page_sync(WRITE, entry,
-					  virt_to_page(addr));
-		if (error == -EIO)
-			error = 0;
-		if (!error)
-			*loc = entry;
-	} else
-		error = -ENOSPC;
-	return error;
-}
-
-
-/**
- *	free_data - Free the swap entries used by the saved image.
- *
- *	Walk the list of used swap entries and free each one. 
- */
-
-static void free_data(void)
-{
-	swp_entry_t entry;
-	int i;
-
-	for (i = 0; i < pmdisk_pages; i++) {
-		entry = (pm_pagedir_nosave + i)->swap_address;
-		if (entry.val)
-			swap_free(entry);
-		else
-			break;
-		(pm_pagedir_nosave + i)->swap_address = (swp_entry_t){0};
-	}
-}
-
-
-/**
- *	write_data - Write saved image to swap.
- *
- *	Walk the list of pages in the image and sync each one to swap.
- */
-
-static int write_data(void)
-{
-	int error = 0;
-	int i;
-
-	printk( "Writing data to swap (%d pages): ", pmdisk_pages );
-	for (i = 0; i < pmdisk_pages && !error; i++) {
-		if (!(i%100))
-			printk( "." );
-		error = write_swap_page((pm_pagedir_nosave+i)->address,
-					&((pm_pagedir_nosave+i)->swap_address));
-	}
-	printk(" %d Pages done.\n",i);
-	return error;
-}
-
-
-/**
- *	free_pagedir - Free pages used by the page directory.
- */
-
-static void free_pagedir_entries(void)
-{
-	int num = pmdisk_info.pagedir_pages;
-	int i;
-
-	for (i = 0; i < num; i++)
-		swap_free(pmdisk_info.pagedir[i]);
-}
-
-
-/**
- *	write_pagedir - Write the array of pages holding the page directory.
- *	@last:	Last swap entry we write (needed for header).
- */
-
-static int write_pagedir(void)
-{
-	unsigned long addr = (unsigned long)pm_pagedir_nosave;
-	int error = 0;
-	int n = SUSPEND_PD_PAGES(pmdisk_pages);
-	int i;
-
-	pmdisk_info.pagedir_pages = n;
-	printk( "Writing pagedir (%d pages)\n", n);
-	for (i = 0; i < n && !error; i++, addr += PAGE_SIZE)
-		error = write_swap_page(addr,&pmdisk_info.pagedir[i]);
-	return error;
-}
-
-
-#ifdef DEBUG
-static void dump_pmdisk_info(void)
-{
-	printk(" pmdisk: Version: %u\n",pmdisk_info.version_code);
-	printk(" pmdisk: Num Pages: %ld\n",pmdisk_info.num_physpages);
-	printk(" pmdisk: UTS Sys: %s\n",pmdisk_info.uts.sysname);
-	printk(" pmdisk: UTS Node: %s\n",pmdisk_info.uts.nodename);
-	printk(" pmdisk: UTS Release: %s\n",pmdisk_info.uts.release);
-	printk(" pmdisk: UTS Version: %s\n",pmdisk_info.uts.version);
-	printk(" pmdisk: UTS Machine: %s\n",pmdisk_info.uts.machine);
-	printk(" pmdisk: UTS Domain: %s\n",pmdisk_info.uts.domainname);
-	printk(" pmdisk: CPUs: %d\n",pmdisk_info.cpus);
-	printk(" pmdisk: Image: %ld Pages\n",pmdisk_info.image_pages);
-	printk(" pmdisk: Pagedir: %ld Pages\n",pmdisk_info.pagedir_pages);
-}
-#else
-static void dump_pmdisk_info(void)
-{
-
-}
-#endif
-
-static void init_header(void)
-{
-	memset(&pmdisk_info,0,sizeof(pmdisk_info));
-	pmdisk_info.version_code = LINUX_VERSION_CODE;
-	pmdisk_info.num_physpages = num_physpages;
-	memcpy(&pmdisk_info.uts,&system_utsname,sizeof(system_utsname));
-
-	pmdisk_info.cpus = num_online_cpus();
-	pmdisk_info.image_pages = pmdisk_pages;
-}
-
-/**
- *	write_header - Fill and write the suspend header.
- *	@entry:	Location of the last swap entry used.
- *
- *	Allocate a page, fill header, write header. 
- *
- *	@entry is the location of the last pagedir entry written on 
- *	entrance. On exit, it contains the location of the header. 
- */
-
-static int write_header(swp_entry_t * entry)
-{
-	dump_pmdisk_info();
-	return write_swap_page((unsigned long)&pmdisk_info,entry);
-}
-
-
-
-/**
- *	write_suspend_image - Write entire image and metadata.
- *
- */
-
-static int write_suspend_image(void)
-{
-	int error;
-	swp_entry_t prev = { 0 };
-
-	init_header();
-
-	if ((error = write_data()))
-		goto FreeData;
-
-	if ((error = write_pagedir()))
-		goto FreePagedir;
-
-	if ((error = write_header(&prev)))
-		goto FreePagedir;
-
-	error = mark_swapfiles(prev);
- Done:
-	return error;
- FreePagedir:
-	free_pagedir_entries();
- FreeData:
-	free_data();
-	goto Done;
-}
-
-
-
-/**
- *	saveable - Determine whether a page should be cloned or not.
- *	@pfn:	The page
- *
- *	We save a page if it's Reserved, and not in the range of pages
- *	statically defined as 'unsaveable', or if it isn't reserved, and
- *	isn't part of a free chunk of pages.
- *	If it is part of a free chunk, we update @pfn to point to the last 
- *	page of the chunk.
- */
-
-static int saveable(unsigned long * pfn)
-{
-	struct page * page = pfn_to_page(*pfn);
-
-	if (PageNosave(page))
-		return 0;
-
-	if (!PageReserved(page)) {
-		int chunk_size;
-
-		if ((chunk_size = is_head_of_free_region(page))) {
-			*pfn += chunk_size - 1;
-			return 0;
-		}
-	} else if (PageReserved(page)) {
-		/* Just copy whole code segment. 
-		 * Hopefully it is not that big.
-		 */
-		if ((ADDRESS(*pfn) >= (unsigned long) ADDRESS2(&__nosave_begin)) && 
-		    (ADDRESS(*pfn) <  (unsigned long) ADDRESS2(&__nosave_end))) {
-			pr_debug("[nosave %lx]\n", ADDRESS(*pfn));
-			return 0;
-		}
-		/* Hmm, perhaps copying all reserved pages is not 
-		 * too healthy as they may contain 
-		 * critical bios data? 
-		 */
-	}
-	return 1;
-}
-
-
-
-/**
- *	count_pages - Determine size of page directory.
- *	
- *	Iterate over all the pages in the system and tally the number
- *	we need to clone.
- */
-
-static void count_pages(void)
-{
-	unsigned long pfn;
-	int n = 0;
-	
-	for (pfn = 0; pfn < max_pfn; pfn++) {
-		if (saveable(&pfn))
-			n++;
-	}
-	pmdisk_pages = n;
-}
-
-
-/**
- *	copy_pages - Atomically snapshot memory.
- *
- *	Iterate over all the pages in the system and copy each one 
- *	into its corresponding location in the pagedir.
- *	We rely on the fact that the number of pages that we're snap-
- *	shotting hasn't changed since we counted them. 
- */
-
-static void copy_pages(void)
-{
-	struct pbe * p = pagedir_save;
-	unsigned long pfn;
-	int n = 0;
-
-	for (pfn = 0; pfn < max_pfn; pfn++) {
-		if (saveable(&pfn)) {
-			n++;
-			p->orig_address = ADDRESS(pfn);
-			copy_page((void *) p->address, 
-				  (void *) p->orig_address);
-			p++;
-		}
-	}
-	BUG_ON(n != pmdisk_pages);
-}
-
-
-/**
- *	free_image_pages - Free each page allocated for snapshot.
- */
-
-static void free_image_pages(void)
-{
-	struct pbe * p;
-	int i;
-
-	for (i = 0, p = pagedir_save; i < pmdisk_pages; i++, p++) {
-		ClearPageNosave(virt_to_page(p->address));
-		free_page(p->address);
-	}
-}
-
-
-/**
- *	free_pagedir - Free the page directory.
- */
-
-static void free_pagedir(void)
-{
-	free_image_pages();
-	free_pages((unsigned long)pagedir_save, pagedir_order);
-}
-
-
-static void calc_order(void)
-{
-	int diff;
-	int order;
-
-	order = get_bitmask_order(SUSPEND_PD_PAGES(pmdisk_pages));
-	pmdisk_pages += 1 << order;
-	do {
-		diff = get_bitmask_order(SUSPEND_PD_PAGES(pmdisk_pages)) - order;
-		if (diff) {
-			order += diff;
-			pmdisk_pages += 1 << diff;
-		}
-	} while(diff);
-	pagedir_order = order;
-}
-
-
-/**
- *	alloc_pagedir - Allocate the page directory.
- *
- *	First, determine exactly how many contiguous pages we need, 
- *	allocate them, then mark each 'unsavable'.
- */
-
-static int alloc_pagedir(void)
-{
-	calc_order();
-	pagedir_save = (suspend_pagedir_t *)__get_free_pages(GFP_ATOMIC | __GFP_COLD, 
-							     pagedir_order);
-	if(!pagedir_save)
-		return -ENOMEM;
-	memset(pagedir_save,0,(1 << pagedir_order) * PAGE_SIZE);
-	pm_pagedir_nosave = pagedir_save;
-	return 0;
-}
-
-
-/**
- *	alloc_image_pages - Allocate pages for the snapshot.
- *
- */
-
-static int alloc_image_pages(void)
-{
-	struct pbe * p;
-	int i;
-
-	for (i = 0, p = pagedir_save; i < pmdisk_pages; i++, p++) {
-		p->address = get_zeroed_page(GFP_ATOMIC | __GFP_COLD);
-		if(!p->address)
-			goto Error;
-		SetPageNosave(virt_to_page(p->address));
-	}
-	return 0;
- Error:
-	do { 
-		if (p->address)
-			free_page(p->address);
-		p->address = 0;
-	} while (p-- > pagedir_save);
-	return -ENOMEM;
-}
-
-
-/**
- *	enough_free_mem - Make sure we enough free memory to snapshot.
- *
- *	Returns TRUE or FALSE after checking the number of available 
- *	free pages.
- */
-
-static int enough_free_mem(void)
-{
-	if(nr_free_pages() < (pmdisk_pages + PAGES_FOR_IO)) {
-		pr_debug("pmdisk: Not enough free pages: Have %d\n",
-			 nr_free_pages());
-		return 0;
-	}
-	return 1;
-}
-
-
-/**
- *	enough_swap - Make sure we have enough swap to save the image.
- *
- *	Returns TRUE or FALSE after checking the total amount of swap 
- *	space avaiable.
- *
- *	FIXME: si_swapinfo(&i) returns all swap devices information.
- *	We should only consider resume_device. 
- */
-
-static int enough_swap(void)
-{
-	struct sysinfo i;
-
-	si_swapinfo(&i);
-	if (i.freeswap < (pmdisk_pages + PAGES_FOR_IO))  {
-		pr_debug("pmdisk: Not enough swap. Need %ld\n",i.freeswap);
-		return 0;
-	}
-	return 1;
-}
-
-
-/**
- *	pmdisk_suspend - Atomically snapshot the system.
- *
- *	This must be called with interrupts disabled, to prevent the 
- *	system changing at all from underneath us. 
- *
- *	To do this, we count the number of pages in the system that we 
- *	need to save; make sure	we have enough memory and swap to clone
- *	the pages and save them in swap, allocate the space to hold them,
- *	and then snapshot them all.
- */
-
-int pmdisk_suspend(void)
-{
-	int error = 0;
-
-	if ((error = read_swapfiles()))
-		return error;
-
-	drain_local_pages();
-
-	pm_pagedir_nosave = NULL;
-	pr_debug("pmdisk: Counting pages to copy.\n" );
-	count_pages();
-	
-	pr_debug("pmdisk: (pages needed: %d + %d free: %d)\n",
-		 pmdisk_pages,PAGES_FOR_IO,nr_free_pages());
-
-	if (!enough_free_mem())
-		return -ENOMEM;
-
-	if (!enough_swap())
-		return -ENOSPC;
-
-	if ((error = alloc_pagedir())) {
-		pr_debug("pmdisk: Allocating pagedir failed.\n");
-		return error;
-	}
-	if ((error = alloc_image_pages())) {
-		pr_debug("pmdisk: Allocating image pages failed.\n");
-		free_pagedir();
-		return error;
-	}
-
-	nr_copy_pages_check = pmdisk_pages;
-	pagedir_order_check = pagedir_order;
-
-	/* During allocating of suspend pagedir, new cold pages may appear. 
-	 * Kill them 
-	 */
-	drain_local_pages();
-
-	/* copy */
-	copy_pages();
-
-	/*
-	 * End of critical section. From now on, we can write to memory,
-	 * but we should not touch disk. This specially means we must _not_
-	 * touch swap space! Except we must write out our image of course.
-	 */
-
-	pr_debug("pmdisk: %d pages copied\n", pmdisk_pages );
-	return 0;
-}
-
-
-/**
- *	suspend_save_image - Prepare and write saved image to swap.
- *
- *	IRQs are re-enabled here so we can resume devices and safely write
- *	to the swap devices. We disable them again before we leave.
- *
- *	The second lock_swapdevices() will unlock ignored swap devices since
- *	writing is finished.
- *	It is important _NOT_ to umount filesystems at this point. We want
- *	them synced (in case something goes wrong) but we DO not want to mark
- *	filesystem clean: it is not. (And it does not matter, if we resume
- *	correctly, we'll mark system clean, anyway.)
- */
-
-static int suspend_save_image(void)
-{
-	int error;
-	device_resume();
-	lock_swapdevices();
-	error = write_suspend_image();
-	lock_swapdevices();
-	return error;
-}
-
-/*
- * Magic happens here
- */
-
-int pmdisk_resume(void)
-{
-	BUG_ON (nr_copy_pages_check != pmdisk_pages);
-	BUG_ON (pagedir_order_check != pagedir_order);
-	
-	/* Even mappings of "global" things (vmalloc) need to be fixed */
-	__flush_tlb_global();
-	return 0;
-}
-
-/* pmdisk_arch_suspend() is implemented in arch/?/power/pmdisk.S,
-   and basically does:
-
-	if (!resume) {
-		save_processor_state();
-		SAVE_REGISTERS
-		return pmdisk_suspend();
-	}
-	GO_TO_SWAPPER_PAGE_TABLES
-	COPY_PAGES_BACK
-	RESTORE_REGISTERS
-	restore_processor_state();
-	return pmdisk_resume();
-
- */
-
-
-/* More restore stuff */
-
-#define does_collide(addr) does_collide_order(pm_pagedir_nosave, addr, 0)
-
-/*
- * Returns true if given address/order collides with any orig_address 
- */
-static int __init does_collide_order(suspend_pagedir_t *pagedir, 
-				     unsigned long addr, int order)
-{
-	int i;
-	unsigned long addre = addr + (PAGE_SIZE<<order);
-	
-	for(i=0; i < pmdisk_pages; i++)
-		if((pagedir+i)->orig_address >= addr &&
-			(pagedir+i)->orig_address < addre)
-			return 1;
-
-	return 0;
-}
-
-/*
- * We check here that pagedir & pages it points to won't collide with pages
- * where we're going to restore from the loaded pages later
- */
-static int __init check_pagedir(void)
-{
-	int i;
-
-	for(i=0; i < pmdisk_pages; i++) {
-		unsigned long addr;
-
-		do {
-			addr = get_zeroed_page(GFP_ATOMIC);
-			if(!addr)
-				return -ENOMEM;
-		} while (does_collide(addr));
-
-		(pm_pagedir_nosave+i)->address = addr;
-	}
-	return 0;
-}
-
-static int __init relocate_pagedir(void)
-{
-	/*
-	 * We have to avoid recursion (not to overflow kernel stack),
-	 * and that's why code looks pretty cryptic 
-	 */
-	suspend_pagedir_t *old_pagedir = pm_pagedir_nosave;
-	void **eaten_memory = NULL;
-	void **c = eaten_memory, *m, *f;
-	int err;
-
-	pr_debug("pmdisk: Relocating pagedir\n");
-
-	if(!does_collide_order(old_pagedir, (unsigned long)old_pagedir, pagedir_order)) {
-		pr_debug("pmdisk: Relocation not necessary\n");
-		return 0;
-	}
-
-	err = -ENOMEM;
-	while ((m = (void *) __get_free_pages(GFP_ATOMIC, pagedir_order)) != NULL) {
-		if (!does_collide_order(old_pagedir, (unsigned long)m,
-					pagedir_order)) {
-			pm_pagedir_nosave =
-				memcpy(m, old_pagedir,
-				       PAGE_SIZE << pagedir_order);
-			err = 0;
-			break;
-		}
-		eaten_memory = m;
-		printk( "." ); 
-		*eaten_memory = c;
-		c = eaten_memory;
-	}
-
-	c = eaten_memory;
-	while(c) {
-		printk(":");
-		f = c;
-		c = *c;
-		free_pages((unsigned long)f, pagedir_order);
-	}
-	printk("|\n");
-	return err;
-}
-
-
-static struct block_device * resume_bdev;
-
-
-/**
- *	Using bio to read from swap.
- *	This code requires a bit more work than just using buffer heads
- *	but, it is the recommended way for 2.5/2.6.
- *	The following are to signal the beginning and end of I/O. Bios
- *	finish asynchronously, while we want them to happen synchronously.
- *	A simple atomic_t, and a wait loop take care of this problem.
- */
-
-static atomic_t io_done = ATOMIC_INIT(0);
-
-static void start_io(void)
-{
-	atomic_set(&io_done,1);
-}
-
-static int end_io(struct bio * bio, unsigned int num, int err)
-{
-	atomic_set(&io_done,0);
-	return 0;
-}
-
-static void wait_io(void)
-{
-	while(atomic_read(&io_done))
-		io_schedule();
-}
-
-
-/**
- *	submit - submit BIO request.
- *	@rw:	READ or WRITE.
- *	@off	physical offset of page.
- *	@page:	page we're reading or writing.
- *
- *	Straight from the textbook - allocate and initialize the bio.
- *	If we're writing, make sure the page is marked as dirty.
- *	Then submit it and wait.
- */
-
-static int submit(int rw, pgoff_t page_off, void * page)
-{
-	int error = 0;
-	struct bio * bio;
-
-	bio = bio_alloc(GFP_ATOMIC,1);
-	if (!bio)
-		return -ENOMEM;
-	bio->bi_sector = page_off * (PAGE_SIZE >> 9);
-	bio_get(bio);
-	bio->bi_bdev = resume_bdev;
-	bio->bi_end_io = end_io;
-
-	if (bio_add_page(bio, virt_to_page(page), PAGE_SIZE, 0) < PAGE_SIZE) {
-		printk("pmdisk: ERROR: adding page to bio at %ld\n",page_off);
-		error = -EFAULT;
-		goto Done;
-	}
-
-	if (rw == WRITE)
-		bio_set_pages_dirty(bio);
-	start_io();
-	submit_bio(rw | (1 << BIO_RW_SYNC), bio);
-	wait_io();
- Done:
-	bio_put(bio);
-	return error;
-}
-
-static int
-read_page(pgoff_t page_off, void * page)
-{
-	return submit(READ,page_off,page);
-}
-
-static int
-write_page(pgoff_t page_off, void * page)
-{
-	return submit(WRITE,page_off,page);
-}
-
-
-extern dev_t __init name_to_dev_t(const char *line);
-
-
-static int __init check_sig(void)
-{
-	int error;
-
-	memset(&pmdisk_header,0,sizeof(pmdisk_header));
-	if ((error = read_page(0,&pmdisk_header)))
-		return error;
-	if (!memcmp(PMDISK_SIG,pmdisk_header.sig,10)) {
-		memcpy(pmdisk_header.sig,pmdisk_header.orig_sig,10);
-
-		/*
-		 * Reset swap signature now.
-		 */
-		error = write_page(0,&pmdisk_header);
-	} else { 
-		pr_debug(KERN_ERR "pmdisk: Invalid partition type.\n");
-		return -EINVAL;
-	}
-	if (!error)
-		pr_debug("pmdisk: Signature found, resuming\n");
-	return error;
-}
-
-
-/*
- * Sanity check if this image makes sense with this kernel/swap context
- * I really don't think that it's foolproof but more than nothing..
- */
-
-static const char * __init sanity_check(void)
-{
-	dump_pmdisk_info();
-	if(pmdisk_info.version_code != LINUX_VERSION_CODE)
-		return "kernel version";
-	if(pmdisk_info.num_physpages != num_physpages)
-		return "memory size";
-	if (strcmp(pmdisk_info.uts.sysname,system_utsname.sysname))
-		return "system type";
-	if (strcmp(pmdisk_info.uts.release,system_utsname.release))
-		return "kernel release";
-	if (strcmp(pmdisk_info.uts.version,system_utsname.version))
-		return "version";
-	if (strcmp(pmdisk_info.uts.machine,system_utsname.machine))
-		return "machine";
-	if(pmdisk_info.cpus != num_online_cpus())
-		return "number of cpus";
-	return NULL;
-}
-
-
-static int __init check_header(void)
-{
-	const char * reason = NULL;
-	int error;
-
-	init_header();
-
-	if ((error = read_page(swp_offset(pmdisk_header.pmdisk_info), 
-			       &pmdisk_info)))
-		return error;
-
- 	/* Is this same machine? */
-	if ((reason = sanity_check())) {
-		printk(KERN_ERR "pmdisk: Resume mismatch: %s\n",reason);
-		return -EPERM;
-	}
-	pmdisk_pages = pmdisk_info.image_pages;
-	return error;
-}
-
-
-static int __init read_pagedir(void)
-{
-	unsigned long addr;
-	int i, n = pmdisk_info.pagedir_pages;
-	int error = 0;
-
-	pagedir_order = get_bitmask_order(n);
-
-	addr =__get_free_pages(GFP_ATOMIC, pagedir_order);
-	if (!addr)
-		return -ENOMEM;
-	pm_pagedir_nosave = (struct pbe *)addr;
-
-	pr_debug("pmdisk: Reading pagedir (%d Pages)\n",n);
-
-	for (i = 0; i < n && !error; i++, addr += PAGE_SIZE) {
-		unsigned long offset = swp_offset(pmdisk_info.pagedir[i]);
-		if (offset)
-			error = read_page(offset, (void *)addr);
-		else
-			error = -EFAULT;
-	}
-	if (error)
-		free_pages((unsigned long)pm_pagedir_nosave,pagedir_order);
-	return error;
-}
-
-
-/**
- *	read_image_data - Read image pages from swap.
- *
- *	You do not need to check for overlaps, check_pagedir()
- *	already did that.
- */
-
-static int __init read_image_data(void)
-{
-	struct pbe * p;
-	int error = 0;
-	int i;
-
-	printk( "Reading image data (%d pages): ", pmdisk_pages );
-	for(i = 0, p = pm_pagedir_nosave; i < pmdisk_pages && !error; i++, p++) {
-		if (!(i%100))
-			printk( "." );
-		error = read_page(swp_offset(p->swap_address),
-				  (void *)p->address);
-	}
-	printk(" %d done.\n",i);
-	return error;
-}
-
-
-static int __init read_suspend_image(void)
-{
-	int error = 0;
-
-	if ((error = check_sig()))
-		return error;
-	if ((error = check_header()))
-		return error;
-	if ((error = read_pagedir()))
-		return error;
-	if ((error = relocate_pagedir()))
-		goto FreePagedir;
-	if ((error = check_pagedir()))
-		goto FreePagedir;
-	if ((error = read_image_data()))
-		goto FreePagedir;
- Done:
-	return error;
- FreePagedir:
-	free_pages((unsigned long)pm_pagedir_nosave,pagedir_order);
-	goto Done;
-}
-
-/**
- *	pmdisk_save - Snapshot memory
- */
-
-int pmdisk_save(void) 
-{
-	int error;
-
-#if defined (CONFIG_HIGHMEM) || defined (CONFIG_DISCONTIGMEM)
-	pr_debug("pmdisk: not supported with high- or discontig-mem.\n");
-	return -EPERM;
-#endif
-	if ((error = arch_prepare_suspend()))
-		return error;
-	local_irq_disable();
-	save_processor_state();
-	error = pmdisk_arch_suspend(0);
-	restore_processor_state();
-	local_irq_enable();
-	return error;
-}
-
-
-/**
- *	pmdisk_write - Write saved memory image to swap.
- *
- *	pmdisk_arch_suspend(0) returns after system is resumed.
- *
- *	pmdisk_arch_suspend() copies all "used" memory to "free" memory,
- *	then unsuspends all device drivers, and writes memory to disk
- *	using normal kernel mechanism.
- */
-
-int pmdisk_write(void)
-{
-	return suspend_save_image();
-}
-
-
-/**
- *	pmdisk_read - Read saved image from swap.
- */
-
-int __init pmdisk_read(void)
-{
-	int error;
-
-	if (!strlen(resume_file))
-		return -ENOENT;
-
-	resume_device = name_to_dev_t(resume_file);
-	pr_debug("pmdisk: Resume From Partition: %s\n", resume_file);
-
-	resume_bdev = open_by_devnum(resume_device, FMODE_READ);
-	if (!IS_ERR(resume_bdev)) {
-		set_blocksize(resume_bdev, PAGE_SIZE);
-		error = read_suspend_image();
-		blkdev_put(resume_bdev);
-	} else
-		error = PTR_ERR(resume_bdev);
-
-	if (!error)
-		pr_debug("Reading resume file was successful\n");
-	else
-		pr_debug("pmdisk: Error %d resuming\n", error);
-	return error;
-}
-
-
-/**
- *	pmdisk_restore - Replace running kernel with saved image.
- */
-
-int __init pmdisk_restore(void)
-{
-	int error;
-	local_irq_disable();
-	save_processor_state();
-	error = pmdisk_arch_suspend(1);
-	restore_processor_state();
-	local_irq_enable();
-	return error;
-}
-
-
-/**
- *	pmdisk_free - Free memory allocated to hold snapshot.
- */
-
-int pmdisk_free(void)
-{
-	pr_debug( "Freeing prev allocated pagedir\n" );
-	free_pagedir();
-	return 0;
-}
-
-static int __init pmdisk_setup(char *str)
-{
-	if (strlen(str)) {
-		if (!strcmp(str,"off"))
-			resume_file[0] = '\0';
-		else
-			strncpy(resume_file, str, 255);
-	} else
-		resume_file[0] = '\0';
-	return 1;
-}
-
-__setup("pmdisk=", pmdisk_setup);
-
diff -Nru a/kernel/power/power.h b/kernel/power/power.h
--- a/kernel/power/power.h	2004-10-18 14:57:18 -07:00
+++ b/kernel/power/power.h	2004-10-18 14:57:18 -07:00
@@ -1,4 +1,5 @@
-
+#include <linux/suspend.h>
+#include <linux/utsname.h>
 
 /* With SUSPEND_CONSOLE defined, it suspend looks *really* cool, but
    we probably do not take enough locks for switching consoles, etc,
@@ -9,7 +10,20 @@
 #endif
 
 
-#ifdef CONFIG_PM_DISK
+struct swsusp_info {
+	struct new_utsname	uts;
+	u32			version_code;
+	unsigned long		num_physpages;
+	int			cpus;
+	unsigned long		image_pages;
+	unsigned long		pagedir_pages;
+	suspend_pagedir_t	* suspend_pagedir;
+	swp_entry_t		pagedir[768];
+} __attribute__((aligned(PAGE_SIZE)));
+
+
+
+#ifdef CONFIG_SOFTWARE_SUSPEND
 extern int pm_suspend_disk(void);
 
 #else
@@ -18,7 +32,6 @@
 	return -EPERM;
 }
 #endif
-
 extern struct semaphore pm_sem;
 #define power_attr(_name) \
 static struct subsys_attribute _name##_attr = {	\
diff -Nru a/kernel/power/process.c b/kernel/power/process.c
--- a/kernel/power/process.c	2004-10-18 14:55:54 -07:00
+++ b/kernel/power/process.c	2004-10-18 14:55:54 -07:00
@@ -25,7 +25,8 @@
 	    (p->flags & PF_NOFREEZE) ||
 	    (p->state == TASK_ZOMBIE) ||
 	    (p->state == TASK_DEAD) ||
-	    (p->state == TASK_STOPPED))
+	    (p->state == TASK_STOPPED) ||
+	    (p->state == TASK_TRACED))
 		return 0;
 	return 1;
 }
@@ -70,6 +71,7 @@
 			if (!freezeable(p))
 				continue;
 			if ((p->flags & PF_FROZEN) ||
+			    (p->state == TASK_TRACED) ||
 			    (p->state == TASK_STOPPED))
 				continue;
 
diff -Nru a/kernel/power/swsusp.c b/kernel/power/swsusp.c
--- a/kernel/power/swsusp.c	2004-10-18 14:56:21 -07:00
+++ b/kernel/power/swsusp.c	2004-10-18 14:56:21 -07:00
@@ -62,6 +62,7 @@
 #include <linux/syscalls.h>
 #include <linux/console.h>
 #include <linux/highmem.h>
+#include <linux/bio.h>
 
 #include <asm/uaccess.h>
 #include <asm/mmu_context.h>
@@ -70,25 +71,16 @@
 
 #include "power.h"
 
-unsigned char software_suspend_enabled = 0;
-
-#define NORESUME		1
-#define RESUME_SPECIFIED	2
-
 /* References to section boundaries */
 extern char __nosave_begin, __nosave_end;
 
 extern int is_head_of_free_region(struct page *);
 
-/* Locks */
-spinlock_t suspend_pagedir_lock __nosavedata = SPIN_LOCK_UNLOCKED;
-
 /* Variables to be preserved over suspend */
-static int pagedir_order_check;
-static int nr_copy_pages_check;
+int pagedir_order_check;
+int nr_copy_pages_check;
 
-static int resume_status;
-static char resume_file[256] = "";			/* For resume= kernel option */
+extern char resume_file[];
 static dev_t resume_device;
 /* Local variables that should not be affected by save */
 unsigned int nr_copy_pages __nosavedata = 0;
@@ -110,16 +102,16 @@
 static suspend_pagedir_t *pagedir_save;
 static int pagedir_order __nosavedata = 0;
 
-struct link {
-	char dummy[PAGE_SIZE - sizeof(swp_entry_t)];
-	swp_entry_t next;
-};
+#define SWSUSP_SIG	"S1SUSPEND"
 
-union diskpage {
-	union swap_header swh;
-	struct link link;
-	struct suspend_header sh;
-};
+struct swsusp_header {
+	char reserved[PAGE_SIZE - 20 - sizeof(swp_entry_t)];
+	swp_entry_t swsusp_info;
+	char	orig_sig[10];
+	char	sig[10];
+} __attribute__((packed, aligned(PAGE_SIZE))) swsusp_header;
+
+struct swsusp_info swsusp_info;
 
 /*
  * XXX: We try to keep some more pages free so that I/O operations succeed
@@ -127,54 +119,10 @@
  */
 #define PAGES_FOR_IO	512
 
-static const char name_suspend[] = "Suspend Machine: ";
-static const char name_resume[] = "Resume Machine: ";
-
-/*
- * Debug
- */
-#define	DEBUG_DEFAULT
-#undef	DEBUG_PROCESS
-#undef	DEBUG_SLOW
-#define TEST_SWSUSP 0		/* Set to 1 to reboot instead of halt machine after suspension */
-
-#ifdef DEBUG_DEFAULT
-# define PRINTK(f, a...)	printk(f, ## a)
-#else
-# define PRINTK(f, a...)       	do { } while(0)
-#endif
-
-#ifdef DEBUG_SLOW
-#define MDELAY(a) mdelay(a)
-#else
-#define MDELAY(a) do { } while(0)
-#endif
-
 /*
  * Saving part...
  */
 
-static __inline__ int fill_suspend_header(struct suspend_header *sh)
-{
-	memset((char *)sh, 0, sizeof(*sh));
-
-	sh->version_code = LINUX_VERSION_CODE;
-	sh->num_physpages = num_physpages;
-	strncpy(sh->machine, system_utsname.machine, 8);
-	strncpy(sh->version, system_utsname.version, 20);
-	/* FIXME: Is this bogus? --RR */
-	sh->num_cpus = num_online_cpus();
-	sh->page_size = PAGE_SIZE;
-	sh->suspend_pagedir = pagedir_nosave;
-	BUG_ON (pagedir_save != pagedir_nosave);
-	sh->num_pbes = nr_copy_pages;
-	/* TODO: needed? mounted fs' last mounted date comparison
-	 * [so they haven't been mounted since last suspend.
-	 * Maybe it isn't.] [we'd need to do this for _all_ fs-es]
-	 */
-	return 0;
-}
-
 /* We memorize in swapfile_used what swap devices are used for suspension */
 #define SWAPFILE_UNUSED    0
 #define SWAPFILE_SUSPEND   1	/* This is the suspending device */
@@ -182,47 +130,30 @@
 
 static unsigned short swapfile_used[MAX_SWAPFILES];
 static unsigned short root_swap;
-#define MARK_SWAP_SUSPEND 0
-#define MARK_SWAP_RESUME 2
 
-static void mark_swapfiles(swp_entry_t prev, int mode)
+static int mark_swapfiles(swp_entry_t prev)
 {
-	swp_entry_t entry;
-	union diskpage *cur;
-	struct page *page;
-
-	if (root_swap == 0xFFFF)  /* ignored */
-		return;
+	int error;
 
-	page = alloc_page(GFP_ATOMIC);
-	if (!page)
-		panic("Out of memory in mark_swapfiles");
-	cur = page_address(page);
-	/* XXX: this is dirty hack to get first page of swap file */
-	entry = swp_entry(root_swap, 0);
-	rw_swap_page_sync(READ, entry, page);
-
-	if (mode == MARK_SWAP_RESUME) {
-	  	if (!memcmp("S1",cur->swh.magic.magic,2))
-		  	memcpy(cur->swh.magic.magic,"SWAP-SPACE",10);
-		else if (!memcmp("S2",cur->swh.magic.magic,2))
-			memcpy(cur->swh.magic.magic,"SWAPSPACE2",10);
-		else printk("%sUnable to find suspended-data signature (%.10s - misspelled?\n", 
-		      	name_resume, cur->swh.magic.magic);
+	rw_swap_page_sync(READ, 
+			  swp_entry(root_swap, 0),
+			  virt_to_page((unsigned long)&swsusp_header));
+	if (!memcmp("SWAP-SPACE",swsusp_header.sig, 10) ||
+	    !memcmp("SWAPSPACE2",swsusp_header.sig, 10)) {
+		memcpy(swsusp_header.orig_sig,swsusp_header.sig, 10);
+		memcpy(swsusp_header.sig,SWSUSP_SIG, 10);
+		swsusp_header.swsusp_info = prev;
+		error = rw_swap_page_sync(WRITE, 
+					  swp_entry(root_swap, 0),
+					  virt_to_page((unsigned long)
+						       &swsusp_header));
 	} else {
-	  	if ((!memcmp("SWAP-SPACE",cur->swh.magic.magic,10)))
-		  	memcpy(cur->swh.magic.magic,"S1SUSP....",10);
-		else if ((!memcmp("SWAPSPACE2",cur->swh.magic.magic,10)))
-			memcpy(cur->swh.magic.magic,"S2SUSP....",10);
-		else panic("\nSwapspace is not swapspace (%.10s)\n", cur->swh.magic.magic);
-		cur->link.next = prev; /* prev is the first/last swap page of the resume area */
-		/* link.next lies *no more* in last 4/8 bytes of magic */
+		pr_debug("swsusp: Partition is not swap space.\n");
+		error = -ENODEV;
 	}
-	rw_swap_page_sync(WRITE, entry, page);
-	__free_page(page);
+	return error;
 }
 
-
 /*
  * Check whether the swap device is the specified resume
  * device, irrespective of whether they are specified by
@@ -243,7 +174,7 @@
 		resume_device == MKDEV(imajor(inode), iminor(inode));
 }
 
-static void read_swapfiles(void) /* This is called before saving image */
+int swsusp_swap_check(void) /* This is called before saving image */
 {
 	int i, len;
 	
@@ -274,114 +205,211 @@
 		}
 	}
 	swap_list_unlock();
+	return (root_swap != 0xffff) ? 0 : -ENODEV;
 }
 
-static void lock_swapdevices(void) /* This is called after saving image so modification
-				      will be lost after resume... and that's what we want. */
+/**
+ * This is called after saving image so modification
+ * will be lost after resume... and that's what we want.
+ * we make the device unusable. A new call to
+ * lock_swapdevices can unlock the devices. 
+ */
+static void lock_swapdevices(void)
 {
 	int i;
 
 	swap_list_lock();
 	for(i = 0; i< MAX_SWAPFILES; i++)
 		if(swapfile_used[i] == SWAPFILE_IGNORED) {
-			swap_info[i].flags ^= 0xFF; /* we make the device unusable. A new call to
-						       lock_swapdevices can unlock the devices. */
+			swap_info[i].flags ^= 0xFF;
 		}
 	swap_list_unlock();
 }
 
+
+
 /**
- *    write_suspend_image - Write entire image to disk.
+ *	write_swap_page - Write one page to a fresh swap location.
+ *	@addr:	Address we're writing.
+ *	@loc:	Place to store the entry we used.
  *
- *    After writing suspend signature to the disk, suspend may no
- *    longer fail: we have ready-to-run image in swap, and rollback
- *    would happen on next reboot -- corrupting data.
+ *	Allocate a new swap entry and 'sync' it. Note we discard -EIO
+ *	errors. That is an artifact left over from swsusp. It did not 
+ *	check the return of rw_swap_page_sync() at all, since most pages
+ *	written back to swap would return -EIO.
+ *	This is a partial improvement, since we will at least return other
+ *	errors, though we need to eventually fix the damn code.
+ */
+
+static int write_page(unsigned long addr, swp_entry_t * loc)
+{
+	swp_entry_t entry;
+	int error = 0;
+
+	entry = get_swap_page();
+	if (swp_offset(entry) && 
+	    swapfile_used[swp_type(entry)] == SWAPFILE_SUSPEND) {
+		error = rw_swap_page_sync(WRITE, entry,
+					  virt_to_page(addr));
+		if (error == -EIO)
+			error = 0;
+		if (!error)
+			*loc = entry;
+	} else
+		error = -ENOSPC;
+	return error;
+}
+
+
+/**
+ *	data_free - Free the swap entries used by the saved image.
  *
- *    Note: The buffer we allocate to use to write the suspend header is
- *    not freed; its not needed since the system is going down anyway
- *    (plus it causes an oops and I'm lazy^H^H^H^Htoo busy).
+ *	Walk the list of used swap entries and free each one. 
+ *	This is only used for cleanup when suspend fails.
  */
-static int write_suspend_image(void)
+
+static void data_free(void)
 {
+	swp_entry_t entry;
 	int i;
-	swp_entry_t entry, prev = { 0 };
-	int nr_pgdir_pages = SUSPEND_PD_PAGES(nr_copy_pages);
-	union diskpage *cur,  *buffer = (union diskpage *)get_zeroed_page(GFP_ATOMIC);
-	unsigned long address;
-	struct page *page;
 
-	if (!buffer)
-		return -ENOMEM;
+	for (i = 0; i < nr_copy_pages; i++) {
+		entry = (pagedir_nosave + i)->swap_address;
+		if (entry.val)
+			swap_free(entry);
+		else
+			break;
+		(pagedir_nosave + i)->swap_address = (swp_entry_t){0};
+	}
+}
+
+
+/**
+ *	data_write - Write saved image to swap.
+ *
+ *	Walk the list of pages in the image and sync each one to swap.
+ */
+
+static int data_write(void)
+{
+	int error = 0;
+	int i;
 
 	printk( "Writing data to swap (%d pages): ", nr_copy_pages );
-	for (i=0; i<nr_copy_pages; i++) {
+	for (i = 0; i < nr_copy_pages && !error; i++) {
 		if (!(i%100))
 			printk( "." );
-		entry = get_swap_page();
-		if (!entry.val)
-			panic("\nNot enough swapspace when writing data" );
-		
-		if (swapfile_used[swp_type(entry)] != SWAPFILE_SUSPEND)
-			panic("\nPage %d: not enough swapspace on suspend device", i );
-	    
-		address = (pagedir_nosave+i)->address;
-		page = virt_to_page(address);
-		rw_swap_page_sync(WRITE, entry, page);
-		(pagedir_nosave+i)->swap_address = entry;
-	}
-	printk( "|\n" );
-	printk( "Writing pagedir (%d pages): ", nr_pgdir_pages);
-	for (i=0; i<nr_pgdir_pages; i++) {
-		cur = (union diskpage *)((char *) pagedir_nosave)+i;
-		BUG_ON ((char *) cur != (((char *) pagedir_nosave) + i*PAGE_SIZE));
-		printk( "." );
-		entry = get_swap_page();
-		if (!entry.val) {
-			printk(KERN_CRIT "Not enough swapspace when writing pgdir\n" );
-			panic("Don't know how to recover");
-			free_page((unsigned long) buffer);
-			return -ENOSPC;
-		}
+		error = write_page((pagedir_nosave+i)->address,
+					  &((pagedir_nosave+i)->swap_address));
+	}
+	printk(" %d Pages done.\n",i);
+	return error;
+}
 
-		if(swapfile_used[swp_type(entry)] != SWAPFILE_SUSPEND)
-			panic("\nNot enough swapspace for pagedir on suspend device" );
+static void dump_info(void)
+{
+	pr_debug(" swsusp: Version: %u\n",swsusp_info.version_code);
+	pr_debug(" swsusp: Num Pages: %ld\n",swsusp_info.num_physpages);
+	pr_debug(" swsusp: UTS Sys: %s\n",swsusp_info.uts.sysname);
+	pr_debug(" swsusp: UTS Node: %s\n",swsusp_info.uts.nodename);
+	pr_debug(" swsusp: UTS Release: %s\n",swsusp_info.uts.release);
+	pr_debug(" swsusp: UTS Version: %s\n",swsusp_info.uts.version);
+	pr_debug(" swsusp: UTS Machine: %s\n",swsusp_info.uts.machine);
+	pr_debug(" swsusp: UTS Domain: %s\n",swsusp_info.uts.domainname);
+	pr_debug(" swsusp: CPUs: %d\n",swsusp_info.cpus);
+	pr_debug(" swsusp: Image: %ld Pages\n",swsusp_info.image_pages);
+	pr_debug(" swsusp: Pagedir: %ld Pages\n",swsusp_info.pagedir_pages);
+}
+
+static void init_header(void)
+{
+	memset(&swsusp_info,0,sizeof(swsusp_info));
+	swsusp_info.version_code = LINUX_VERSION_CODE;
+	swsusp_info.num_physpages = num_physpages;
+	memcpy(&swsusp_info.uts,&system_utsname,sizeof(system_utsname));
+
+	swsusp_info.suspend_pagedir = pagedir_nosave;
+	swsusp_info.cpus = num_online_cpus();
+	swsusp_info.image_pages = nr_copy_pages;
+	dump_info();
+}
 
-		BUG_ON (sizeof(swp_entry_t) != sizeof(long));
-		BUG_ON (PAGE_SIZE % sizeof(struct pbe));
+static int close_swap(void)
+{
+	swp_entry_t entry;
+	int error;
 
-		cur->link.next = prev;				
-		page = virt_to_page((unsigned long)cur);
-		rw_swap_page_sync(WRITE, entry, page);
-		prev = entry;
-	}
-	printk("H");
-	BUG_ON (sizeof(struct suspend_header) > PAGE_SIZE-sizeof(swp_entry_t));
-	BUG_ON (sizeof(union diskpage) != PAGE_SIZE);
-	BUG_ON (sizeof(struct link) != PAGE_SIZE);
-	entry = get_swap_page();
-	if (!entry.val)
-		panic( "\nNot enough swapspace when writing header" );
-	if (swapfile_used[swp_type(entry)] != SWAPFILE_SUSPEND)
-		panic("\nNot enough swapspace for header on suspend device" );
-
-	cur = (void *) buffer;
-	if (fill_suspend_header(&cur->sh))
-		BUG();		/* Not a BUG_ON(): we want fill_suspend_header to be called, always */
-		
-	cur->link.next = prev;
-
-	page = virt_to_page((unsigned long)cur);
-	rw_swap_page_sync(WRITE, entry, page);
-	prev = entry;
-
-	printk( "S" );
-	mark_swapfiles(prev, MARK_SWAP_SUSPEND);
-	printk( "|\n" );
+	error = write_page((unsigned long)&swsusp_info,&entry);
+	if (!error) { 
+		printk( "S" );
+		error = mark_swapfiles(entry);
+		printk( "|\n" );
+	}
+	return error;
+}
 
-	MDELAY(1000);
-	return 0;
+/**
+ *	free_pagedir_entries - Free pages used by the page directory.
+ *
+ *	This is used during suspend for error recovery.
+ */
+
+static void free_pagedir_entries(void)
+{
+	int i;
+
+	for (i = 0; i < swsusp_info.pagedir_pages; i++)
+		swap_free(swsusp_info.pagedir[i]);
+}
+
+
+/**
+ *	write_pagedir - Write the array of pages holding the page directory.
+ *	@last:	Last swap entry we write (needed for header).
+ */
+
+static int write_pagedir(void)
+{
+	unsigned long addr = (unsigned long)pagedir_nosave;
+	int error = 0;
+	int n = SUSPEND_PD_PAGES(nr_copy_pages);
+	int i;
+
+	swsusp_info.pagedir_pages = n;
+	printk( "Writing pagedir (%d pages)\n", n);
+	for (i = 0; i < n && !error; i++, addr += PAGE_SIZE)
+		error = write_page(addr, &swsusp_info.pagedir[i]);
+	return error;
 }
 
+/**
+ *	write_suspend_image - Write entire image and metadata.
+ *
+ */
+
+static int write_suspend_image(void)
+{
+	int error;
+
+	init_header();
+	if ((error = data_write()))
+		goto FreeData;
+
+	if ((error = write_pagedir()))
+		goto FreePagedir;
+
+	if ((error = close_swap()))
+		goto FreePagedir;
+ Done:
+	return error;
+ FreePagedir:
+	free_pagedir_entries();
+ FreeData:
+	data_free();
+	goto Done;
+}
+
+
 #ifdef CONFIG_HIGHMEM
 struct highmem_page {
 	char *data;
@@ -438,22 +466,30 @@
 	}
 	return 0;
 }
+#endif /* CONFIG_HIGHMEM */
+
 
 static int save_highmem(void)
 {
+#ifdef CONFIG_HIGHMEM
 	struct zone *zone;
 	int res = 0;
+
+	pr_debug("swsusp: Saving Highmem\n");
 	for_each_zone(zone) {
 		if (is_highmem(zone))
 			res = save_highmem_zone(zone);
 		if (res)
 			return res;
 	}
+#endif
 	return 0;
 }
 
 static int restore_highmem(void)
 {
+#ifdef CONFIG_HIGHMEM
+	printk("swsusp: Restoring Highmem\n");
 	while (highmem_copy) {
 		struct highmem_page *save = highmem_copy;
 		void *kaddr;
@@ -465,9 +501,10 @@
 		free_page((long) save->data);
 		kfree(save);
 	}
+#endif
 	return 0;
 }
-#endif
+
 
 static int pfn_is_nosave(unsigned long pfn)
 {
@@ -476,57 +513,82 @@
 	return (pfn >= nosave_begin_pfn) && (pfn < nosave_end_pfn);
 }
 
-/* if *pagedir_p != NULL it also copies the counted pages */
-static int count_and_copy_zone(struct zone *zone, struct pbe **pagedir_p)
+/**
+ *	saveable - Determine whether a page should be cloned or not.
+ *	@pfn:	The page
+ *
+ *	We save a page if it's Reserved, and not in the range of pages
+ *	statically defined as 'unsaveable', or if it isn't reserved, and
+ *	isn't part of a free chunk of pages.
+ *	If it is part of a free chunk, we update @pfn to point to the last 
+ *	page of the chunk.
+ */
+
+static int saveable(struct zone * zone, unsigned long * zone_pfn)
 {
-	unsigned long zone_pfn, chunk_size, nr_copy_pages = 0;
-	struct pbe *pbe = *pagedir_p;
-	for (zone_pfn = 0; zone_pfn < zone->spanned_pages; ++zone_pfn) {
-		struct page *page;
-		unsigned long pfn = zone_pfn + zone->zone_start_pfn;
+	unsigned long pfn = *zone_pfn + zone->zone_start_pfn;
+	unsigned long chunk_size;
+	struct page * page;
 
-		if (!(pfn%1000))
-			printk(".");
-		if (!pfn_valid(pfn))
-			continue;
-		page = pfn_to_page(pfn);
-		BUG_ON(PageReserved(page) && PageNosave(page));
-		if (PageNosave(page))
-			continue;
-		if (PageReserved(page) && pfn_is_nosave(pfn)) {
-			PRINTK("[nosave pfn 0x%lx]", pfn);
-			continue;
-		}
-		if ((chunk_size = is_head_of_free_region(page))) {
-			pfn += chunk_size - 1;
-			zone_pfn += chunk_size - 1;
-			continue;
+	if (!pfn_valid(pfn))
+		return 0;
+
+	if (!(pfn%1000))
+		printk(".");
+	page = pfn_to_page(pfn);
+	BUG_ON(PageReserved(page) && PageNosave(page));
+	if (PageNosave(page))
+		return 0;
+	if (PageReserved(page) && pfn_is_nosave(pfn)) {
+		pr_debug("[nosave pfn 0x%lx]", pfn);
+		return 0;
+	}
+	if ((chunk_size = is_head_of_free_region(page))) {
+		*zone_pfn += chunk_size - 1;
+		return 0;
+	}
+
+	return 1;
+}
+
+static void count_data_pages(void)
+{
+	struct zone *zone;
+	unsigned long zone_pfn;
+
+	nr_copy_pages = 0;
+
+	for_each_zone(zone) {
+		if (!is_highmem(zone)) {
+			for (zone_pfn = 0; zone_pfn < zone->spanned_pages; ++zone_pfn)
+				nr_copy_pages += saveable(zone, &zone_pfn);
 		}
-		nr_copy_pages++;
-		if (!pbe)
-			continue;
-		pbe->orig_address = (long) page_address(page);
-		/* Copy page is dangerous: it likes to mess with
-		   preempt count on specific cpus. Wrong preempt count is then copied,
-		   oops. */
-		copy_page((void *)pbe->address, (void *)pbe->orig_address);
-		pbe++;
 	}
-	*pagedir_p = pbe;
-	return nr_copy_pages;
 }
 
-static int count_and_copy_data_pages(struct pbe *pagedir_p)
+
+static void copy_data_pages(void)
 {
-	int nr_copy_pages = 0;
 	struct zone *zone;
+	unsigned long zone_pfn;
+	struct pbe * pbe = pagedir_nosave;
+	
 	for_each_zone(zone) {
 		if (!is_highmem(zone))
-			nr_copy_pages += count_and_copy_zone(zone, &pagedir_p);
+			for (zone_pfn = 0; zone_pfn < zone->spanned_pages; ++zone_pfn) {
+				if (saveable(zone, &zone_pfn)) {
+					struct page * page;
+					page = pfn_to_page(zone_pfn + zone->zone_start_pfn);
+					pbe->orig_address = (long) page_address(page);
+					/* copy_page is no usable for copying task structs. */
+					memcpy((void *)pbe->address, (void *)pbe->orig_address, PAGE_SIZE);
+					pbe++;
+				}
+			}
 	}
-	return nr_copy_pages;
 }
 
+
 static void free_suspend_pagedir_zone(struct zone *zone, unsigned long pagedir)
 {
 	unsigned long zone_pfn, pagedir_end, pagedir_pfn, pagedir_end_pfn;
@@ -547,119 +609,202 @@
 	}
 }
 
-static void free_suspend_pagedir(unsigned long this_pagedir)
+void swsusp_free(void)
 {
+	unsigned long p = (unsigned long)pagedir_save;
 	struct zone *zone;
 	for_each_zone(zone) {
 		if (!is_highmem(zone))
-			free_suspend_pagedir_zone(zone, this_pagedir);
+			free_suspend_pagedir_zone(zone, p);
 	}
-	free_pages(this_pagedir, pagedir_order);
+	free_pages(p, pagedir_order);
 }
 
-static suspend_pagedir_t *create_suspend_pagedir(int nr_copy_pages)
+
+/**
+ *	calc_order - Determine the order of allocation needed for pagedir_save.
+ *
+ *	This looks tricky, but is just subtle. Please fix it some time.
+ *	Since there are %nr_copy_pages worth of pages in the snapshot, we need
+ *	to allocate enough contiguous space to hold 
+ *		(%nr_copy_pages * sizeof(struct pbe)), 
+ *	which has the saved/orig locations of the page.. 
+ *
+ *	SUSPEND_PD_PAGES() tells us how many pages we need to hold those 
+ *	structures, then we call get_bitmask_order(), which will tell us the
+ *	last bit set in the number, starting with 1. (If we need 30 pages, that
+ *	is 0x0000001e in hex. The last bit is the 5th, which is the order we 
+ *	would use to allocate 32 contiguous pages).
+ *
+ *	Since we also need to save those pages, we add the number of pages that
+ *	we need to nr_copy_pages, and in case of an overflow, do the 
+ *	calculation again to update the number of pages needed. 
+ *
+ *	With this model, we will tend to waste a lot of memory if we just cross
+ *	an order boundary. Plus, the higher the order of allocation that we try
+ *	to do, the more likely we are to fail in a low-memory situtation 
+ *	(though	we're unlikely to get this far in such a case, since swsusp 
+ *	requires half of memory to be free anyway).
+ */
+
+
+static void calc_order(void)
 {
-	int i;
-	suspend_pagedir_t *pagedir;
-	struct pbe *p;
-	struct page *page;
+	int diff = 0;
+	int order = 0;
+
+	do {
+		diff = get_bitmask_order(SUSPEND_PD_PAGES(nr_copy_pages)) - order;
+		if (diff) {
+			order += diff;
+			nr_copy_pages += 1 << diff;
+		}
+	} while(diff);
+	pagedir_order = order;
+}
+
+
+/**
+ *	alloc_pagedir - Allocate the page directory.
+ *
+ *	First, determine exactly how many contiguous pages we need and
+ *	allocate them.
+ */
 
-	pagedir_order = get_bitmask_order(SUSPEND_PD_PAGES(nr_copy_pages));
+static int alloc_pagedir(void)
+{
+	calc_order();
+	pagedir_save = (suspend_pagedir_t *)__get_free_pages(GFP_ATOMIC | __GFP_COLD,
+							     pagedir_order);
+	if (!pagedir_save)
+		return -ENOMEM;
+	memset(pagedir_save, 0, (1 << pagedir_order) * PAGE_SIZE);
+	pagedir_nosave = pagedir_save;
+	return 0;
+}
+
+
+/**
+ *	alloc_image_pages - Allocate pages for the snapshot.
+ *
+ */
+
+static int alloc_image_pages(void)
+{
+	struct pbe * p;
+	int i;
 
-	p = pagedir = (suspend_pagedir_t *)__get_free_pages(GFP_ATOMIC | __GFP_COLD, pagedir_order);
-	if (!pagedir)
-		return NULL;
-
-	page = virt_to_page(pagedir);
-	for(i=0; i < 1<<pagedir_order; i++)
-		SetPageNosave(page++);
-		
-	while(nr_copy_pages--) {
+	for (i = 0, p = pagedir_save; i < nr_copy_pages; i++, p++) {
 		p->address = get_zeroed_page(GFP_ATOMIC | __GFP_COLD);
-		if (!p->address) {
-			free_suspend_pagedir((unsigned long) pagedir);
-			return NULL;
-		}
+		if(!p->address)
+			goto Error;
 		SetPageNosave(virt_to_page(p->address));
-		p->orig_address = 0;
-		p++;
 	}
-	return pagedir;
+	return 0;
+ Error:
+	do { 
+		if (p->address)
+			free_page(p->address);
+		p->address = 0;
+	} while (p-- > pagedir_save);
+	return -ENOMEM;
 }
 
-static int prepare_suspend_processes(void)
+
+/**
+ *	enough_free_mem - Make sure we enough free memory to snapshot.
+ *
+ *	Returns TRUE or FALSE after checking the number of available 
+ *	free pages.
+ */
+
+static int enough_free_mem(void)
 {
-	sys_sync();	/* Syncing needs pdflushd, so do it before stopping processes */
-	if (freeze_processes()) {
-		printk( KERN_ERR "Suspend failed: Not all processes stopped!\n" );
-		thaw_processes();
-		return 1;
+	if (nr_free_pages() < (nr_copy_pages + PAGES_FOR_IO)) {
+		pr_debug("swsusp: Not enough free pages: Have %d\n",
+			 nr_free_pages());
+		return 0;
 	}
-	return 0;
+	return 1;
 }
 
-/*
- * Try to free as much memory as possible, but do not OOM-kill anyone
+
+/**
+ *	enough_swap - Make sure we have enough swap to save the image.
+ *
+ *	Returns TRUE or FALSE after checking the total amount of swap 
+ *	space avaiable.
  *
- * Notice: all userland should be stopped at this point, or livelock is possible.
+ *	FIXME: si_swapinfo(&i) returns all swap devices information.
+ *	We should only consider resume_device. 
  */
-static void free_some_memory(void)
+
+static int enough_swap(void)
 {
-	printk("Freeing memory: ");
-	while (shrink_all_memory(10000))
-		printk(".");
-	printk("|\n");
+	struct sysinfo i;
+
+	si_swapinfo(&i);
+	if (i.freeswap < (nr_copy_pages + PAGES_FOR_IO))  {
+		pr_debug("swsusp: Not enough swap. Need %ld\n",i.freeswap);
+		return 0;
+	}
+	return 1;
 }
 
-static int suspend_prepare_image(void)
+static int swsusp_alloc(void)
 {
-	struct sysinfo i;
-	unsigned int nr_needed_pages = 0;
+	int error;
+
+	pr_debug("suspend: (pages needed: %d + %d free: %d)\n",
+		 nr_copy_pages, PAGES_FOR_IO, nr_free_pages());
 
 	pagedir_nosave = NULL;
-	printk( "/critical section: ");
-#ifdef CONFIG_HIGHMEM
-	printk( "handling highmem" );
-	if (save_highmem()) {
-		printk(KERN_CRIT "%sNot enough free pages for highmem\n", name_suspend);
+	if (!enough_free_mem())
 		return -ENOMEM;
-	}
-	printk(", ");
-#endif
 
-	printk("counting pages to copy" );
-	drain_local_pages();
-	nr_copy_pages = count_and_copy_data_pages(NULL);
-	nr_needed_pages = nr_copy_pages + PAGES_FOR_IO;
-	
-	printk(" (pages needed: %d+%d=%d free: %d)\n",nr_copy_pages,PAGES_FOR_IO,nr_needed_pages,nr_free_pages());
-	if(nr_free_pages() < nr_needed_pages) {
-		printk(KERN_CRIT "%sCouldn't get enough free pages, on %d pages short\n",
-		       name_suspend, nr_needed_pages-nr_free_pages());
-		root_swap = 0xFFFF;
-		return -ENOMEM;
-	}
-	si_swapinfo(&i);	/* FIXME: si_swapinfo(&i) returns all swap devices information.
-				   We should only consider resume_device. */
-	if (i.freeswap < nr_needed_pages)  {
-		printk(KERN_CRIT "%sThere's not enough swap space available, on %ld pages short\n",
-		       name_suspend, nr_needed_pages-i.freeswap);
+	if (!enough_swap())
 		return -ENOSPC;
-	}
 
-	PRINTK( "Alloc pagedir\n" ); 
-	pagedir_save = pagedir_nosave = create_suspend_pagedir(nr_copy_pages);
-	if (!pagedir_nosave) {
-		/* Pagedir is big, one-chunk allocation. It is easily possible for this allocation to fail */
-		printk(KERN_CRIT "%sCouldn't allocate continuous pagedir\n", name_suspend);
-		return -ENOMEM;
+	if ((error = alloc_pagedir())) {
+		pr_debug("suspend: Allocating pagedir failed.\n");
+		return error;
+	}
+	if ((error = alloc_image_pages())) {
+		pr_debug("suspend: Allocating image pages failed.\n");
+		swsusp_free();
+		return error;
 	}
+
 	nr_copy_pages_check = nr_copy_pages;
 	pagedir_order_check = pagedir_order;
+	return 0;
+}
+
+int suspend_prepare_image(void)
+{
+	unsigned int nr_needed_pages = 0;
+	int error;
+
+	pr_debug("swsusp: critical section: \n");
+	if (save_highmem()) {
+		printk(KERN_CRIT "Suspend machine: Not enough free pages for highmem\n");
+		return -ENOMEM;
+	}
+
+	drain_local_pages();
+	count_data_pages();
+	printk("swsusp: Need to copy %u pages\n",nr_copy_pages);
+	nr_needed_pages = nr_copy_pages + PAGES_FOR_IO;
 
-	drain_local_pages();	/* During allocating of suspend pagedir, new cold pages may appear. Kill them */
-	if (nr_copy_pages != count_and_copy_data_pages(pagedir_nosave))	/* copy */
-		BUG();
+	error = swsusp_alloc();
+	if (error)
+		return error;
+	
+	/* During allocating of suspend pagedir, new cold pages may appear. 
+	 * Kill them.
+	 */
+	drain_local_pages();
+	copy_data_pages();
 
 	/*
 	 * End of critical section. From now on, we can write to memory,
@@ -667,205 +812,86 @@
 	 * touch swap space! Except we must write out our image of course.
 	 */
 
-	printk( "critical section/: done (%d pages copied)\n", nr_copy_pages );
+	printk("swsusp: critical section/: done (%d pages copied)\n", nr_copy_pages );
 	return 0;
 }
 
-static void suspend_save_image(void)
+
+/* It is important _NOT_ to umount filesystems at this point. We want
+ * them synced (in case something goes wrong) but we DO not want to mark
+ * filesystem clean: it is not. (And it does not matter, if we resume
+ * correctly, we'll mark system clean, anyway.)
+ */
+int swsusp_write(void)
 {
+	int error;
 	device_resume();
-
 	lock_swapdevices();
-	write_suspend_image();
-	lock_swapdevices();	/* This will unlock ignored swap devices since writing is finished */
+	error = write_suspend_image();
+	/* This will unlock ignored swap devices since writing is finished */
+	lock_swapdevices();
+	return error;
 
-	/* It is important _NOT_ to umount filesystems at this point. We want
-	 * them synced (in case something goes wrong) but we DO not want to mark
-	 * filesystem clean: it is not. (And it does not matter, if we resume
-	 * correctly, we'll mark system clean, anyway.)
-	 */
 }
 
-static void suspend_power_down(void)
-{
-	extern int C_A_D;
-	C_A_D = 0;
-	printk(KERN_EMERG "%s%s Trying to power down.\n", name_suspend, TEST_SWSUSP ? "Disable TEST_SWSUSP. NOT ": "");
-#ifdef CONFIG_VT
-	PRINTK(KERN_EMERG "shift_state: %04x\n", shift_state);
-	mdelay(1000);
-	if (TEST_SWSUSP ^ (!!(shift_state & (1 << KG_CTRL))))
-		machine_restart(NULL);
-	else
-#endif
-	{
-		device_suspend(3);
-		device_shutdown();
-		machine_power_off();
-	}
 
-	printk(KERN_EMERG "%sProbably not capable for powerdown. System halted.\n", name_suspend);
-	machine_halt();
-	while (1);
-	/* NOTREACHED */
-}
+extern asmlinkage int swsusp_arch_suspend(void);
+extern asmlinkage int swsusp_arch_resume(void);
 
-/*
- * Magic happens here
- */
 
-asmlinkage void do_magic_resume_1(void)
+asmlinkage int swsusp_save(void)
 {
-	barrier();
-	mb();
-	spin_lock_irq(&suspend_pagedir_lock);	/* Done to disable interrupts */ 
+	int error = 0;
 
-	device_power_down(3);
-	PRINTK( "Waiting for DMAs to settle down...\n");
-	mdelay(1000);	/* We do not want some readahead with DMA to corrupt our memory, right?
-			   Do it with disabled interrupts for best effect. That way, if some
-			   driver scheduled DMA, we have good chance for DMA to finish ;-). */
+	if ((error = swsusp_swap_check()))
+		return error;
+	return suspend_prepare_image();
 }
 
-asmlinkage void do_magic_resume_2(void)
+int swsusp_suspend(void)
 {
-	BUG_ON (nr_copy_pages_check != nr_copy_pages);
-	BUG_ON (pagedir_order_check != pagedir_order);
-
-	__flush_tlb_global();		/* Even mappings of "global" things (vmalloc) need to be fixed */
-
-	PRINTK( "Freeing prev allocated pagedir\n" );
-	free_suspend_pagedir((unsigned long) pagedir_save);
-
-#ifdef CONFIG_HIGHMEM
-	printk( "Restoring highmem\n" );
+	int error;
+	if ((error = arch_prepare_suspend()))
+		return error;
+	local_irq_disable();
+	save_processor_state();
+	error = swsusp_arch_suspend();
+	/* Restore control flow magically appears here */
+	restore_processor_state();
 	restore_highmem();
-#endif
-	printk("done, devices\n");
-
-	device_power_up();
-	spin_unlock_irq(&suspend_pagedir_lock);
-	device_resume();
-
-	/* Fixme: this is too late; we should do this ASAP to avoid "infinite reboots" problem */
-	PRINTK( "Fixing swap signatures... " );
-	mark_swapfiles(((swp_entry_t) {0}), MARK_SWAP_RESUME);
-	PRINTK( "ok\n" );
-
-#ifdef SUSPEND_CONSOLE
-	acquire_console_sem();
-	update_screen(fg_console);
-	release_console_sem();
-#endif
+	local_irq_enable();
+	return error;
 }
 
-/* do_magic() is implemented in arch/?/kernel/suspend_asm.S, and basically does:
-
-	if (!resume) {
-		do_magic_suspend_1();
-		save_processor_state();
-		SAVE_REGISTERS
-		do_magic_suspend_2();
-		return;
-	}
-	GO_TO_SWAPPER_PAGE_TABLES
-	do_magic_resume_1();
-	COPY_PAGES_BACK
-	RESTORE_REGISTERS
-	restore_processor_state();
-	do_magic_resume_2();
-
- */
 
-asmlinkage void do_magic_suspend_1(void)
+asmlinkage int swsusp_restore(void)
 {
-	mb();
-	barrier();
-	BUG_ON(in_atomic());
-	spin_lock_irq(&suspend_pagedir_lock);
+	BUG_ON (nr_copy_pages_check != nr_copy_pages);
+	BUG_ON (pagedir_order_check != pagedir_order);
+	
+	/* Even mappings of "global" things (vmalloc) need to be fixed */
+	__flush_tlb_global();
+	return 0;
 }
 
-asmlinkage void do_magic_suspend_2(void)
+int swsusp_resume(void)
 {
-	int is_problem;
-	read_swapfiles();
-	device_power_down(3);
-	is_problem = suspend_prepare_image();
-	device_power_up();
-	spin_unlock_irq(&suspend_pagedir_lock);
-	if (!is_problem) {
-		kernel_fpu_end();	/* save_processor_state() does kernel_fpu_begin, and we need to revert it in order to pass in_atomic() checks */
-		BUG_ON(in_atomic());
-		suspend_save_image();
-		suspend_power_down();	/* FIXME: if suspend_power_down is commented out, console is lost after few suspends ?! */
-	}
-
-	printk(KERN_EMERG "%sSuspend failed, trying to recover...\n", name_suspend);
-	MDELAY(1000); /* So user can wait and report us messages if armageddon comes :-) */
-
-	barrier();
-	mb();
-	spin_lock_irq(&suspend_pagedir_lock);	/* Done to disable interrupts */ 
-
-	free_pages((unsigned long) pagedir_nosave, pagedir_order);
-	spin_unlock_irq(&suspend_pagedir_lock);
-
-	device_resume();
-	PRINTK( "Fixing swap signatures... " );
-	mark_swapfiles(((swp_entry_t) {0}), MARK_SWAP_RESUME);
-	PRINTK( "ok\n" );
+	int error;
+	local_irq_disable();
+	/* We'll ignore saved state, but this gets preempt count (etc) right */
+	save_processor_state();
+	error = swsusp_arch_resume();
+	/* Code below is only ever reached in case of failure. Otherwise
+	 * execution continues at place where swsusp_arch_suspend was called
+         */
+	BUG_ON(!error);
+	restore_processor_state();
+	restore_highmem();
+	local_irq_enable();
+	return error;
 }
 
-/*
- * This is main interface to the outside world. It needs to be
- * called from process context.
- */
-int software_suspend(void)
-{
-	int res;
-	if (!software_suspend_enabled)
-		return -EAGAIN;
-
-	software_suspend_enabled = 0;
-	might_sleep();
 
-	if (arch_prepare_suspend()) {
-		printk("%sArchitecture failed to prepare\n", name_suspend);
-		return -EPERM;
-	}		
-	if (pm_prepare_console())
-		printk( "%sCan't allocate a console... proceeding\n", name_suspend);
-	if (!prepare_suspend_processes()) {
-
-		/* At this point, all user processes and "dangerous"
-                   kernel threads are stopped. Free some memory, as we
-                   need half of memory free. */
-
-		free_some_memory();
-		disable_nonboot_cpus();
-		/* Save state of all device drivers, and stop them. */
-		printk("Suspending devices... ");
-		if ((res = device_suspend(3))==0) {
-			/* If stopping device drivers worked, we proceed basically into
-			 * suspend_save_image.
-			 *
-			 * do_magic(0) returns after system is resumed.
-			 *
-			 * do_magic() copies all "used" memory to "free" memory, then
-			 * unsuspends all device drivers, and writes memory to disk
-			 * using normal kernel mechanism.
-			 */
-			do_magic(0);
-		}
-		thaw_processes();
-		enable_nonboot_cpus();
-	} else
-		res = -EBUSY;
-	software_suspend_enabled = 1;
-	MDELAY(1000);
-	pm_restore_console();
-	return res;
-}
 
 /* More restore stuff */
 
@@ -874,14 +900,14 @@
 /*
  * Returns true if given address/order collides with any orig_address 
  */
-static int does_collide_order(suspend_pagedir_t *pagedir, unsigned long addr,
+static int __init does_collide_order(suspend_pagedir_t *pagedir, unsigned long addr,
 		int order)
 {
 	int i;
 	unsigned long addre = addr + (PAGE_SIZE<<order);
 	
-	for(i=0; i < nr_copy_pages; i++)
-		if((pagedir+i)->orig_address >= addr &&
+	for (i=0; i < nr_copy_pages; i++)
+		if ((pagedir+i)->orig_address >= addr &&
 			(pagedir+i)->orig_address < addre)
 			return 1;
 
@@ -892,7 +918,7 @@
  * We check here that pagedir & pages it points to won't collide with pages
  * where we're going to restore from the loaded pages later
  */
-static int check_pagedir(void)
+static int __init check_pagedir(void)
 {
 	int i;
 
@@ -910,7 +936,7 @@
 	return 0;
 }
 
-static int relocate_pagedir(void)
+static int __init swsusp_pagedir_relocate(void)
 {
 	/*
 	 * We have to avoid recursion (not to overflow kernel stack),
@@ -923,9 +949,9 @@
 
 	printk("Relocating pagedir ");
 
-	if(!does_collide_order(old_pagedir, (unsigned long)old_pagedir, pagedir_order)) {
+	if (!does_collide_order(old_pagedir, (unsigned long)old_pagedir, pagedir_order)) {
 		printk("not necessary\n");
-		return 0;
+		return check_pagedir();
 	}
 
 	while ((m = (void *) __get_free_pages(GFP_ATOMIC, pagedir_order)) != NULL) {
@@ -953,283 +979,253 @@
 		free_pages((unsigned long)f, pagedir_order);
 	}
 	printk("|\n");
-	return ret;
+	return check_pagedir();
 }
 
-/*
- * Sanity check if this image makes sense with this kernel/swap context
- * I really don't think that it's foolproof but more than nothing..
+/**
+ *	Using bio to read from swap.
+ *	This code requires a bit more work than just using buffer heads
+ *	but, it is the recommended way for 2.5/2.6.
+ *	The following are to signal the beginning and end of I/O. Bios
+ *	finish asynchronously, while we want them to happen synchronously.
+ *	A simple atomic_t, and a wait loop take care of this problem.
  */
 
-static int sanity_check_failed(char *reason)
-{
-	printk(KERN_ERR "%s%s\n", name_resume, reason);
-	return -EPERM;
-}
+static atomic_t io_done = ATOMIC_INIT(0);
 
-static int sanity_check(struct suspend_header *sh)
+static void start_io(void)
 {
-	if (sh->version_code != LINUX_VERSION_CODE)
-		return sanity_check_failed("Incorrect kernel version");
-	if (sh->num_physpages != num_physpages)
-		return sanity_check_failed("Incorrect memory size");
-	if (strncmp(sh->machine, system_utsname.machine, 8))
-		return sanity_check_failed("Incorrect machine type");
-	if (strncmp(sh->version, system_utsname.version, 20))
-		return sanity_check_failed("Incorrect version");
-	if (sh->num_cpus != num_online_cpus())
-		return sanity_check_failed("Incorrect number of cpus");
-	if (sh->page_size != PAGE_SIZE)
-		return sanity_check_failed("Incorrect PAGE_SIZE");
-	return 0;
+	atomic_set(&io_done,1);
 }
 
-static int bdev_read_page(struct block_device *bdev, long pos, void *buf)
+static int end_io(struct bio * bio, unsigned int num, int err)
 {
-	struct buffer_head *bh;
-	BUG_ON (pos%PAGE_SIZE);
-	bh = __bread(bdev, pos/PAGE_SIZE, PAGE_SIZE);
-	if (!bh || (!bh->b_data)) {
-		return -1;
-	}
-	memcpy(buf, bh->b_data, PAGE_SIZE);	/* FIXME: may need kmap() */
-	BUG_ON(!buffer_uptodate(bh));
-	brelse(bh);
-	return 0;
-} 
-
-static int bdev_write_page(struct block_device *bdev, long pos, void *buf)
-{
-#if 0
-	struct buffer_head *bh;
-	BUG_ON (pos%PAGE_SIZE);
-	bh = __bread(bdev, pos/PAGE_SIZE, PAGE_SIZE);
-	if (!bh || (!bh->b_data)) {
-		return -1;
-	}
-	memcpy(bh->b_data, buf, PAGE_SIZE);	/* FIXME: may need kmap() */
-	BUG_ON(!buffer_uptodate(bh));
-	generic_make_request(WRITE, bh);
-	if (!buffer_uptodate(bh))
-		printk(KERN_CRIT "%sWarning %s: Fixing swap signatures unsuccessful...\n", name_resume, resume_file);
-	wait_on_buffer(bh);
-	brelse(bh);
-	return 0;
-#endif
-	printk(KERN_CRIT "%sWarning %s: Fixing swap signatures unimplemented...\n", name_resume, resume_file);
+	atomic_set(&io_done,0);
 	return 0;
 }
 
-extern dev_t __init name_to_dev_t(const char *line);
-
-static int __init __read_suspend_image(struct block_device *bdev, union diskpage *cur, int noresume)
+static void wait_io(void)
 {
-	swp_entry_t next;
-	int i, nr_pgdir_pages;
+	while(atomic_read(&io_done))
+		io_schedule();
+}
 
-#define PREPARENEXT \
-	{	next = cur->link.next; \
-		next.val = swp_offset(next) * PAGE_SIZE; \
-        }
 
-	if (bdev_read_page(bdev, 0, cur)) return -EIO;
+static struct block_device * resume_bdev;
 
-	if ((!memcmp("SWAP-SPACE",cur->swh.magic.magic,10)) ||
-	    (!memcmp("SWAPSPACE2",cur->swh.magic.magic,10))) {
-		printk(KERN_ERR "%sThis is normal swap space\n", name_resume );
-		return -EINVAL;
-	}
+/**
+ *	submit - submit BIO request.
+ *	@rw:	READ or WRITE.
+ *	@off	physical offset of page.
+ *	@page:	page we're reading or writing.
+ *
+ *	Straight from the textbook - allocate and initialize the bio.
+ *	If we're writing, make sure the page is marked as dirty.
+ *	Then submit it and wait.
+ */
 
-	PREPARENEXT; /* We have to read next position before we overwrite it */
+static int submit(int rw, pgoff_t page_off, void * page)
+{
+	int error = 0;
+	struct bio * bio;
 
-	if (!memcmp("S1",cur->swh.magic.magic,2))
-		memcpy(cur->swh.magic.magic,"SWAP-SPACE",10);
-	else if (!memcmp("S2",cur->swh.magic.magic,2))
-		memcpy(cur->swh.magic.magic,"SWAPSPACE2",10);
-	else {
-		if (noresume)
-			return -EINVAL;
-		panic("%sUnable to find suspended-data signature (%.10s - misspelled?\n", 
-			name_resume, cur->swh.magic.magic);
-	}
-	if (noresume) {
-		/* We don't do a sanity check here: we want to restore the swap
-		   whatever version of kernel made the suspend image;
-		   We need to write swap, but swap is *not* enabled so
-		   we must write the device directly */
-		printk("%s: Fixing swap signatures %s...\n", name_resume, resume_file);
-		bdev_write_page(bdev, 0, cur);
-	}
+	bio = bio_alloc(GFP_ATOMIC, 1);
+	if (!bio)
+		return -ENOMEM;
+	bio->bi_sector = page_off * (PAGE_SIZE >> 9);
+	bio_get(bio);
+	bio->bi_bdev = resume_bdev;
+	bio->bi_end_io = end_io;
+
+	if (bio_add_page(bio, virt_to_page(page), PAGE_SIZE, 0) < PAGE_SIZE) {
+		printk("swsusp: ERROR: adding page to bio at %ld\n",page_off);
+		error = -EFAULT;
+		goto Done;
+	}
+
+	if (rw == WRITE)
+		bio_set_pages_dirty(bio);
+	start_io();
+	submit_bio(rw | (1 << BIO_RW_SYNC), bio);
+	wait_io();
+ Done:
+	bio_put(bio);
+	return error;
+}
 
-	printk( "%sSignature found, resuming\n", name_resume );
-	MDELAY(1000);
+int bio_read_page(pgoff_t page_off, void * page)
+{
+	return submit(READ, page_off, page);
+}
 
-	if (bdev_read_page(bdev, next.val, cur)) return -EIO;
-	if (sanity_check(&cur->sh)) 	/* Is this same machine? */	
-		return -EPERM;
-	PREPARENEXT;
+int bio_write_page(pgoff_t page_off, void * page)
+{
+	return submit(WRITE, page_off, page);
+}
 
-	pagedir_save = cur->sh.suspend_pagedir;
-	nr_copy_pages = cur->sh.num_pbes;
-	nr_pgdir_pages = SUSPEND_PD_PAGES(nr_copy_pages);
-	pagedir_order = get_bitmask_order(nr_pgdir_pages);
+/*
+ * Sanity check if this image makes sense with this kernel/swap context
+ * I really don't think that it's foolproof but more than nothing..
+ */
 
-	pagedir_nosave = (suspend_pagedir_t *)__get_free_pages(GFP_ATOMIC, pagedir_order);
-	if (!pagedir_nosave)
-		return -ENOMEM;
+static const char * __init sanity_check(void)
+{
+	dump_info();
+	if(swsusp_info.version_code != LINUX_VERSION_CODE)
+		return "kernel version";
+	if(swsusp_info.num_physpages != num_physpages)
+		return "memory size";
+	if (strcmp(swsusp_info.uts.sysname,system_utsname.sysname))
+		return "system type";
+	if (strcmp(swsusp_info.uts.release,system_utsname.release))
+		return "kernel release";
+	if (strcmp(swsusp_info.uts.version,system_utsname.version))
+		return "version";
+	if (strcmp(swsusp_info.uts.machine,system_utsname.machine))
+		return "machine";
+	if(swsusp_info.cpus != num_online_cpus())
+		return "number of cpus";
+	return NULL;
+}
 
-	PRINTK( "%sReading pagedir, ", name_resume );
 
-	/* We get pages in reverse order of saving! */
-	for (i=nr_pgdir_pages-1; i>=0; i--) {
-		BUG_ON (!next.val);
-		cur = (union diskpage *)((char *) pagedir_nosave)+i;
-		if (bdev_read_page(bdev, next.val, cur)) return -EIO;
-		PREPARENEXT;
-	}
-	BUG_ON (next.val);
+static int __init check_header(void)
+{
+	const char * reason = NULL;
+	int error;
 
-	if (relocate_pagedir())
-		return -ENOMEM;
-	if (check_pagedir())
-		return -ENOMEM;
+	if ((error = bio_read_page(swp_offset(swsusp_header.swsusp_info), &swsusp_info)))
+		return error;
 
-	printk( "Reading image data (%d pages): ", nr_copy_pages );
-	for(i=0; i < nr_copy_pages; i++) {
-		swp_entry_t swap_address = (pagedir_nosave+i)->swap_address;
-		if (!(i%100))
-			printk( "." );
-		/* You do not need to check for overlaps...
-		   ... check_pagedir already did this work */
-		if (bdev_read_page(bdev, swp_offset(swap_address) * PAGE_SIZE, (char *)((pagedir_nosave+i)->address)))
-			return -EIO;
+ 	/* Is this same machine? */
+	if ((reason = sanity_check())) {
+		printk(KERN_ERR "swsusp: Resume mismatch: %s\n",reason);
+		return -EPERM;
 	}
-	printk( "|\n" );
-	return 0;
+	nr_copy_pages = swsusp_info.image_pages;
+	return error;
 }
 
-static int __init read_suspend_image(const char * specialfile, int noresume)
+static int __init check_sig(void)
 {
-	union diskpage *cur;
-	unsigned long scratch_page = 0;
 	int error;
-	char b[BDEVNAME_SIZE];
 
-	resume_device = name_to_dev_t(specialfile);
-	scratch_page = get_zeroed_page(GFP_ATOMIC);
-	cur = (void *) scratch_page;
-	if (cur) {
-		struct block_device *bdev;
-		printk("Resuming from device %s\n",
-				__bdevname(resume_device, b));
-		bdev = open_by_devnum(resume_device, FMODE_READ);
-		if (IS_ERR(bdev)) {
-			error = PTR_ERR(bdev);
-		} else {
-			set_blocksize(bdev, PAGE_SIZE);
-			error = __read_suspend_image(bdev, cur, noresume);
-			blkdev_put(bdev);
-		}
-	} else error = -ENOMEM;
+	memset(&swsusp_header, 0, sizeof(swsusp_header));
+	if ((error = bio_read_page(0, &swsusp_header)))
+		return error;
+	if (!memcmp(SWSUSP_SIG, swsusp_header.sig, 10)) {
+		memcpy(swsusp_header.sig, swsusp_header.orig_sig, 10);
 
-	if (scratch_page)
-		free_page(scratch_page);
-	switch (error) {
-		case 0:
-			PRINTK("Reading resume file was successful\n");
-			break;
-		case -EINVAL:
-			break;
-		case -EIO:
-			printk( "%sI/O error\n", name_resume);
-			break;
-		case -ENOENT:
-			printk( "%s%s: No such file or directory\n", name_resume, specialfile);
-			break;
-		case -ENOMEM:
-			printk( "%sNot enough memory\n", name_resume);
-			break;
-		default:
-			printk( "%sError %d resuming\n", name_resume, error );
+		/*
+		 * Reset swap signature now.
+		 */
+		error = bio_write_page(0, &swsusp_header);
+	} else { 
+		pr_debug(KERN_ERR "swsusp: Invalid partition type.\n");
+		return -EINVAL;
 	}
-	MDELAY(1000);
+	if (!error)
+		pr_debug("swsusp: Signature found, resuming\n");
 	return error;
 }
 
 /**
- *	software_resume - Resume from a saved image.
- *
- *	Called as a late_initcall (so all devices are discovered and 
- *	initialized), we call swsusp to see if we have a saved image or not.
- *	If so, we quiesce devices, then restore the saved image. We will 
- *	return above (in pm_suspend_disk() ) if everything goes well. 
- *	Otherwise, we fail gracefully and return to the normally 
- *	scheduled program.
+ *	swsusp_read_data - Read image pages from swap.
  *
+ *	You do not need to check for overlaps, check_pagedir()
+ *	already did that.
  */
-static int __init software_resume(void)
-{
-	if (num_online_cpus() > 1) {
-		printk(KERN_WARNING "Software Suspend has malfunctioning SMP support. Disabled :(\n");	
-		return -EINVAL;
-	}
-	/* We enable the possibility of machine suspend */
-	software_suspend_enabled = 1;
-	if (!resume_status)
-		return 0;
 
-	printk( "%s", name_resume );
-	if (resume_status == NORESUME) {
-		if(resume_file[0])
-			read_suspend_image(resume_file, 1);
-		printk( "disabled\n" );
-		return 0;
-	}
-	MDELAY(1000);
+static int __init data_read(void)
+{
+	struct pbe * p;
+	int error;
+	int i;
 
-	if (pm_prepare_console())
-		printk("swsusp: Can't allocate a console... proceeding\n");
+	if ((error = swsusp_pagedir_relocate()))
+		return error;
 
-	if (!resume_file[0] && resume_status == RESUME_SPECIFIED) {
-		printk( "suspension device unspecified\n" );
-		return -EINVAL;
+	printk( "Reading image data (%d pages): ", nr_copy_pages );
+	for(i = 0, p = pagedir_nosave; i < nr_copy_pages && !error; i++, p++) {
+		if (!(i%100))
+			printk( "." );
+		error = bio_read_page(swp_offset(p->swap_address),
+				  (void *)p->address);
 	}
+	printk(" %d done.\n",i);
+	return error;
 
-	printk( "resuming from %s\n", resume_file);
-	if (read_suspend_image(resume_file, 0))
-		goto read_failure;
-	/* FIXME: Should we stop processes here, just to be safer? */
-	disable_nonboot_cpus();
-	device_suspend(3);
-	do_magic(1);
-	panic("This never returns");
-
-read_failure:
-	pm_restore_console();
-	return 0;
 }
 
-late_initcall(software_resume);
+extern dev_t __init name_to_dev_t(const char *line);
 
-static int __init resume_setup(char *str)
+static int __init read_pagedir(void)
 {
-	if (resume_status == NORESUME)
-		return 1;
+	unsigned long addr;
+	int i, n = swsusp_info.pagedir_pages;
+	int error = 0;
 
-	strncpy( resume_file, str, 255 );
-	resume_status = RESUME_SPECIFIED;
+	pagedir_order = get_bitmask_order(n);
 
-	return 1;
+	addr =__get_free_pages(GFP_ATOMIC, pagedir_order);
+	if (!addr)
+		return -ENOMEM;
+	pagedir_nosave = (struct pbe *)addr;
+
+	pr_debug("pmdisk: Reading pagedir (%d Pages)\n",n);
+
+	for (i = 0; i < n && !error; i++, addr += PAGE_SIZE) {
+		unsigned long offset = swp_offset(swsusp_info.pagedir[i]);
+		if (offset)
+			error = bio_read_page(offset, (void *)addr);
+		else
+			error = -EFAULT;
+	}
+	if (error)
+		free_pages((unsigned long)pagedir_nosave, pagedir_order);
+	return error;
 }
 
-static int __init noresume_setup(char *str)
+static int __init read_suspend_image(void)
 {
-	resume_status = NORESUME;
-	return 1;
+	int error = 0;
+
+	if ((error = check_sig()))
+		return error;
+	if ((error = check_header()))
+		return error;
+	if ((error = read_pagedir()))
+		return error;
+	if ((error = data_read()))
+		free_pages((unsigned long)pagedir_nosave, pagedir_order);
+	return error;
 }
 
-__setup("noresume", noresume_setup);
-__setup("resume=", resume_setup);
+/**
+ *	pmdisk_read - Read saved image from swap.
+ */
+
+int __init swsusp_read(void)
+{
+	int error;
+
+	if (!strlen(resume_file))
+		return -ENOENT;
 
-EXPORT_SYMBOL(software_suspend);
-EXPORT_SYMBOL(software_suspend_enabled);
+	resume_device = name_to_dev_t(resume_file);
+	pr_debug("swsusp: Resume From Partition: %s\n", resume_file);
+
+	resume_bdev = open_by_devnum(resume_device, FMODE_READ);
+	if (!IS_ERR(resume_bdev)) {
+		set_blocksize(resume_bdev, PAGE_SIZE);
+		error = read_suspend_image();
+		blkdev_put(resume_bdev);
+	} else
+		error = PTR_ERR(resume_bdev);
+
+	if (!error)
+		pr_debug("Reading resume file was successful\n");
+	else
+		pr_debug("pmdisk: Error %d resuming\n", error);
+	return error;
+}
diff -Nru a/kernel/printk.c b/kernel/printk.c
--- a/kernel/printk.c	2004-10-18 14:57:05 -07:00
+++ b/kernel/printk.c	2004-10-18 14:57:05 -07:00
@@ -192,6 +192,8 @@
 	unsigned long size = memparse(str, &str);
 	unsigned long flags;
 
+	if (size)
+		size = roundup_pow_of_two(size);
 	if (size > log_buf_len) {
 		unsigned long start, dest_idx, offset;
 		char * new_log_buf;
@@ -508,6 +510,17 @@
 asmlinkage int printk(const char *fmt, ...)
 {
 	va_list args;
+	int r;
+
+	va_start(args, fmt);
+	r = vprintk(fmt, args);
+	va_end(args);
+
+	return r;
+}
+
+asmlinkage int vprintk(const char *fmt, va_list args)
+{
 	unsigned long flags;
 	int printed_len;
 	char *p;
@@ -521,9 +534,7 @@
 	spin_lock_irqsave(&logbuf_lock, flags);
 
 	/* Emit the output into the temporary buffer */
-	va_start(args, fmt);
 	printed_len = vscnprintf(printk_buf, sizeof(printk_buf), fmt, args);
-	va_end(args);
 
 	/*
 	 * Copy the output into log_buf.  If the caller didn't provide
@@ -575,6 +586,7 @@
 	return printed_len;
 }
 EXPORT_SYMBOL(printk);
+EXPORT_SYMBOL(vprintk);
 
 /**
  * acquire_console_sem - lock the console system for exclusive use.
diff -Nru a/kernel/profile.c b/kernel/profile.c
--- a/kernel/profile.c	2004-10-18 14:57:04 -07:00
+++ b/kernel/profile.c	2004-10-18 14:57:04 -07:00
@@ -8,38 +8,44 @@
 #include <linux/bootmem.h>
 #include <linux/notifier.h>
 #include <linux/mm.h>
+#include <linux/cpumask.h>
+#include <linux/profile.h>
 #include <asm/sections.h>
 
-unsigned int * prof_buffer;
-unsigned long prof_len;
-unsigned long prof_shift;
-int prof_on;
+static atomic_t *prof_buffer;
+static unsigned long prof_len, prof_shift;
+static int prof_on;
+static cpumask_t prof_cpu_mask = CPU_MASK_ALL;
 
-int __init profile_setup(char * str)
+static int __init profile_setup(char * str)
 {
 	int par;
+
+	if (!strncmp(str, "schedule", 8)) {
+		prof_on = 2;
+		printk(KERN_INFO "kernel schedule profiling enabled\n");
+		if (str[7] == ',')
+			str += 8;
+	}
 	if (get_option(&str,&par)) {
 		prof_shift = par;
 		prof_on = 1;
-		printk(KERN_INFO "kernel profiling enabled\n");
+		printk(KERN_INFO "kernel profiling enabled (shift: %ld)\n",
+			prof_shift);
 	}
 	return 1;
 }
+__setup("profile=", profile_setup);
 
 
 void __init profile_init(void)
 {
-	unsigned int size;
- 
 	if (!prof_on) 
 		return;
  
 	/* only text is profiled */
-	prof_len = _etext - _stext;
-	prof_len >>= prof_shift;
-		
-	size = prof_len * sizeof(unsigned int) + PAGE_SIZE - 1;
-	prof_buffer = (unsigned int *) alloc_bootmem(size);
+	prof_len = (_etext - _stext) >> prof_shift;
+	prof_buffer = alloc_bootmem(prof_len*sizeof(atomic_t));
 }
 
 /* Profile event notifications */
@@ -47,31 +53,54 @@
 #ifdef CONFIG_PROFILING
  
 static DECLARE_RWSEM(profile_rwsem);
-static struct notifier_block * exit_task_notifier;
-static struct notifier_block * exit_mmap_notifier;
-static struct notifier_block * exec_unmap_notifier;
+static rwlock_t handoff_lock = RW_LOCK_UNLOCKED;
+static struct notifier_block * task_exit_notifier;
+static struct notifier_block * task_free_notifier;
+static struct notifier_block * munmap_notifier;
  
-void profile_exit_task(struct task_struct * task)
+void profile_task_exit(struct task_struct * task)
 {
 	down_read(&profile_rwsem);
-	notifier_call_chain(&exit_task_notifier, 0, task);
+	notifier_call_chain(&task_exit_notifier, 0, task);
 	up_read(&profile_rwsem);
 }
  
-void profile_exit_mmap(struct mm_struct * mm)
+int profile_handoff_task(struct task_struct * task)
 {
-	down_read(&profile_rwsem);
-	notifier_call_chain(&exit_mmap_notifier, 0, mm);
-	up_read(&profile_rwsem);
+	int ret;
+	read_lock(&handoff_lock);
+	ret = notifier_call_chain(&task_free_notifier, 0, task);
+	read_unlock(&handoff_lock);
+	return (ret == NOTIFY_OK) ? 1 : 0;
 }
 
-void profile_exec_unmap(struct mm_struct * mm)
+void profile_munmap(unsigned long addr)
 {
 	down_read(&profile_rwsem);
-	notifier_call_chain(&exec_unmap_notifier, 0, mm);
+	notifier_call_chain(&munmap_notifier, 0, (void *)addr);
 	up_read(&profile_rwsem);
 }
 
+int task_handoff_register(struct notifier_block * n)
+{
+	int err = -EINVAL;
+
+	write_lock(&handoff_lock);
+	err = notifier_chain_register(&task_free_notifier, n);
+	write_unlock(&handoff_lock);
+	return err;
+}
+
+int task_handoff_unregister(struct notifier_block * n)
+{
+	int err = -EINVAL;
+
+	write_lock(&handoff_lock);
+	err = notifier_chain_unregister(&task_free_notifier, n);
+	write_unlock(&handoff_lock);
+	return err;
+}
+
 int profile_event_register(enum profile_type type, struct notifier_block * n)
 {
 	int err = -EINVAL;
@@ -79,14 +108,11 @@
 	down_write(&profile_rwsem);
  
 	switch (type) {
-		case EXIT_TASK:
-			err = notifier_chain_register(&exit_task_notifier, n);
+		case PROFILE_TASK_EXIT:
+			err = notifier_chain_register(&task_exit_notifier, n);
 			break;
-		case EXIT_MMAP:
-			err = notifier_chain_register(&exit_mmap_notifier, n);
-			break;
-		case EXEC_UNMAP:
-			err = notifier_chain_register(&exec_unmap_notifier, n);
+		case PROFILE_MUNMAP:
+			err = notifier_chain_register(&munmap_notifier, n);
 			break;
 	}
  
@@ -103,14 +129,11 @@
 	down_write(&profile_rwsem);
  
 	switch (type) {
-		case EXIT_TASK:
-			err = notifier_chain_unregister(&exit_task_notifier, n);
-			break;
-		case EXIT_MMAP:
-			err = notifier_chain_unregister(&exit_mmap_notifier, n);
+		case PROFILE_TASK_EXIT:
+			err = notifier_chain_unregister(&task_exit_notifier, n);
 			break;
-		case EXEC_UNMAP:
-			err = notifier_chain_unregister(&exec_unmap_notifier, n);
+		case PROFILE_MUNMAP:
+			err = notifier_chain_unregister(&munmap_notifier, n);
 			break;
 	}
 
@@ -150,8 +173,150 @@
 
 EXPORT_SYMBOL_GPL(register_profile_notifier);
 EXPORT_SYMBOL_GPL(unregister_profile_notifier);
+EXPORT_SYMBOL_GPL(task_handoff_register);
+EXPORT_SYMBOL_GPL(task_handoff_unregister);
 
 #endif /* CONFIG_PROFILING */
 
 EXPORT_SYMBOL_GPL(profile_event_register);
 EXPORT_SYMBOL_GPL(profile_event_unregister);
+
+void profile_hit(int type, void *__pc)
+{
+	unsigned long pc;
+
+	if (prof_on != type || !prof_buffer)
+		return;
+	pc = ((unsigned long)__pc - (unsigned long)_stext) >> prof_shift;
+	atomic_inc(&prof_buffer[min(pc, prof_len - 1)]);
+}
+
+void profile_tick(int type, struct pt_regs *regs)
+{
+	if (type == CPU_PROFILING)
+		profile_hook(regs);
+	if (!user_mode(regs) && cpu_isset(smp_processor_id(), prof_cpu_mask))
+		profile_hit(type, (void *)profile_pc(regs));
+}
+
+#ifdef CONFIG_PROC_FS
+#include <linux/proc_fs.h>
+#include <asm/uaccess.h>
+#include <asm/ptrace.h>
+
+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;
+}
+
+void create_prof_cpu_mask(struct proc_dir_entry *root_irq_dir)
+{
+	struct proc_dir_entry *entry;
+
+	/* create /proc/irq/prof_cpu_mask */
+	if (!(entry = create_proc_entry("prof_cpu_mask", 0600, root_irq_dir)))
+		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;
+}
+
+/*
+ * This function accesses profiling information. The returned data is
+ * binary: the sampling step and the actual contents of the profile
+ * buffer. Use of the program readprofile is recommended in order to
+ * get meaningful info out of these data.
+ */
+static ssize_t
+read_profile(struct file *file, char __user *buf, size_t count, loff_t *ppos)
+{
+	unsigned long p = *ppos;
+	ssize_t read;
+	char * pnt;
+	unsigned int sample_step = 1 << prof_shift;
+
+	if (p >= (prof_len+1)*sizeof(unsigned int))
+		return 0;
+	if (count > (prof_len+1)*sizeof(unsigned int) - p)
+		count = (prof_len+1)*sizeof(unsigned int) - p;
+	read = 0;
+
+	while (p < sizeof(unsigned int) && count > 0) {
+		put_user(*((char *)(&sample_step)+p),buf);
+		buf++; p++; count--; read++;
+	}
+	pnt = (char *)prof_buffer + p - sizeof(atomic_t);
+	if (copy_to_user(buf,(void *)pnt,count))
+		return -EFAULT;
+	read += count;
+	*ppos += read;
+	return read;
+}
+
+/*
+ * Writing to /proc/profile resets the counters
+ *
+ * Writing a 'profiling multiplier' value into it also re-sets the profiling
+ * interrupt frequency, on architectures that support this.
+ */
+static ssize_t write_profile(struct file *file, const char __user *buf,
+			     size_t count, loff_t *ppos)
+{
+#ifdef CONFIG_SMP
+	extern int setup_profiling_timer (unsigned int multiplier);
+
+	if (count == sizeof(int)) {
+		unsigned int multiplier;
+
+		if (copy_from_user(&multiplier, buf, sizeof(int)))
+			return -EFAULT;
+
+		if (setup_profiling_timer(multiplier))
+			return -EINVAL;
+	}
+#endif
+
+	memset(prof_buffer, 0, prof_len * sizeof(atomic_t));
+	return count;
+}
+
+static struct file_operations proc_profile_operations = {
+	.read		= read_profile,
+	.write		= write_profile,
+};
+
+static int __init create_proc_profile(void)
+{
+	struct proc_dir_entry *entry;
+
+	if (!prof_on)
+		return 0;
+	if (!(entry = create_proc_entry("profile", S_IWUSR | S_IRUGO, NULL)))
+		return 0;
+	entry->proc_fops = &proc_profile_operations;
+	entry->size = (1+prof_len) * sizeof(atomic_t);
+	return 0;
+}
+module_init(create_proc_profile);
+#endif /* CONFIG_PROC_FS */
diff -Nru a/kernel/ptrace.c b/kernel/ptrace.c
--- a/kernel/ptrace.c	2004-10-18 14:57:05 -07:00
+++ b/kernel/ptrace.c	2004-10-18 14:57:05 -07:00
@@ -55,6 +55,15 @@
 	REMOVE_LINKS(child);
 	child->parent = child->real_parent;
 	SET_LINKS(child);
+
+	if (child->state == TASK_TRACED) {
+		/*
+		 * Turn a tracing stop into a normal stop now,
+		 * since with no tracer there would be no way
+		 * to wake it up with SIGCONT or SIGKILL.
+		 */
+		child->state = TASK_STOPPED;
+	}
 }
 
 /*
@@ -62,20 +71,35 @@
  */
 int ptrace_check_attach(struct task_struct *child, int kill)
 {
-	if (!(child->ptrace & PT_PTRACED))
-		return -ESRCH;
+	int ret = -ESRCH;
 
-	if (child->parent != current)
-		return -ESRCH;
+	/*
+	 * We take the read lock around doing both checks to close a
+	 * possible race where someone else was tracing our child and
+	 * detached between these two checks.  After this locked check,
+	 * we are sure that this is our traced child and that can only
+	 * be changed by us so it's not changing right after this.
+	 */
+	read_lock(&tasklist_lock);
+	if ((child->ptrace & PT_PTRACED) && child->parent == current &&
+	    child->signal != NULL) {
+		ret = 0;
+		spin_lock_irq(&child->sighand->siglock);
+		if (child->state == TASK_STOPPED) {
+			child->state = TASK_TRACED;
+		} else if (child->state != TASK_TRACED && !kill) {
+			ret = -ESRCH;
+		}
+		spin_unlock_irq(&child->sighand->siglock);
+	}
+	read_unlock(&tasklist_lock);
 
-	if (!kill) {
-		if (child->state != TASK_STOPPED)
-			return -ESRCH;
+	if (!ret && !kill) {
 		wait_task_inactive(child);
 	}
 
 	/* All systems go.. */
-	return 0;
+	return ret;
 }
 
 int ptrace_attach(struct task_struct *task)
@@ -178,8 +202,6 @@
 		if (bytes > PAGE_SIZE-offset)
 			bytes = PAGE_SIZE-offset;
 
-		flush_cache_page(vma, addr);
-
 		maddr = kmap(page);
 		if (write) {
 			copy_to_user_page(vma, page, addr,
@@ -322,24 +344,3 @@
 
 	return ret;
 }
-
-void ptrace_notify(int exit_code)
-{
-	BUG_ON (!(current->ptrace & PT_PTRACED));
-
-	/* Let the debugger run.  */
-	current->exit_code = exit_code;
-	set_current_state(TASK_STOPPED);
-	notify_parent(current, SIGCHLD);
-	schedule();
-
-	/*
-	 * Signals sent while we were stopped might set TIF_SIGPENDING.
-	 */
-
-	spin_lock_irq(&current->sighand->siglock);
-	recalc_sigpending();
-	spin_unlock_irq(&current->sighand->siglock);
-}
-
-EXPORT_SYMBOL(ptrace_notify);
diff -Nru a/kernel/rcupdate.c b/kernel/rcupdate.c
--- a/kernel/rcupdate.c	2004-10-18 14:55:54 -07:00
+++ b/kernel/rcupdate.c	2004-10-18 14:55:54 -07:00
@@ -17,9 +17,10 @@
  *
  * Copyright (C) IBM Corporation, 2001
  *
- * Author: Dipankar Sarma <dipankar@in.ibm.com>
+ * Authors: Dipankar Sarma <dipankar@in.ibm.com>
+ *	    Manfred Spraul <manfred@colorfullife.com>
  * 
- * Based on the original work by Paul McKenney <paul.mckenney@us.ibm.com>
+ * Based on the original work by Paul McKenney <paulmck@us.ibm.com>
  * and inputs from Rusty Russell, Andrea Arcangeli and Andi Kleen.
  * Papers:
  * http://www.rdrop.com/users/paulmck/paper/rclockpdcsproof.pdf
@@ -40,6 +41,7 @@
 #include <asm/bitops.h>
 #include <linux/module.h>
 #include <linux/completion.h>
+#include <linux/moduleparam.h>
 #include <linux/percpu.h>
 #include <linux/notifier.h>
 #include <linux/rcupdate.h>
@@ -48,44 +50,82 @@
 /* Definition for rcupdate control block. */
 struct rcu_ctrlblk rcu_ctrlblk = 
 	{ .cur = -300, .completed = -300 , .lock = SEQCNT_ZERO };
+struct rcu_ctrlblk rcu_bh_ctrlblk =
+	{ .cur = -300, .completed = -300 , .lock = SEQCNT_ZERO };
 
 /* Bookkeeping of the progress of the grace period */
-struct {
-	spinlock_t	mutex; /* Guard this struct and writes to rcu_ctrlblk */
-	cpumask_t	rcu_cpu_mask; /* CPUs that need to switch in order    */
+struct rcu_state {
+	spinlock_t	lock; /* Guard this struct and writes to rcu_ctrlblk */
+	cpumask_t	cpumask; /* CPUs that need to switch in order    */
 	                              /* for current batch to proceed.        */
-} rcu_state ____cacheline_maxaligned_in_smp =
-	  {.mutex = SPIN_LOCK_UNLOCKED, .rcu_cpu_mask = CPU_MASK_NONE };
+};
 
+struct rcu_state rcu_state ____cacheline_maxaligned_in_smp =
+	  {.lock = SPIN_LOCK_UNLOCKED, .cpumask = CPU_MASK_NONE };
+struct rcu_state rcu_bh_state ____cacheline_maxaligned_in_smp =
+	  {.lock = SPIN_LOCK_UNLOCKED, .cpumask = CPU_MASK_NONE };
 
 DEFINE_PER_CPU(struct rcu_data, rcu_data) = { 0L };
+DEFINE_PER_CPU(struct rcu_data, rcu_bh_data) = { 0L };
 
 /* Fake initialization required by compiler */
 static DEFINE_PER_CPU(struct tasklet_struct, rcu_tasklet) = {NULL};
-#define RCU_tasklet(cpu) (per_cpu(rcu_tasklet, cpu))
+static int maxbatch = 10;
 
 /**
- * call_rcu - Queue an RCU update request.
+ * call_rcu - Queue an RCU callback for invocation after a grace period.
  * @head: structure to be used for queueing the RCU updates.
  * @func: actual update function to be invoked after the grace period
  *
- * The update function will be invoked as soon as all CPUs have performed 
- * a context switch or been seen in the idle loop or in a user process. 
- * The read-side of critical section that use call_rcu() for updation must 
- * be protected by rcu_read_lock()/rcu_read_unlock().
+ * The update function will be invoked some time after a full grace
+ * period elapses, in other words after all currently executing RCU
+ * read-side critical sections have completed.  RCU read-side critical
+ * sections are delimited by rcu_read_lock() and rcu_read_unlock(),
+ * and may be nested.
  */
 void fastcall call_rcu(struct rcu_head *head,
 				void (*func)(struct rcu_head *rcu))
 {
-	int cpu;
 	unsigned long flags;
+	struct rcu_data *rdp;
 
 	head->func = func;
 	head->next = NULL;
 	local_irq_save(flags);
-	cpu = smp_processor_id();
-	*RCU_nxttail(cpu) = head;
-	RCU_nxttail(cpu) = &head->next;
+	rdp = &__get_cpu_var(rcu_data);
+	*rdp->nxttail = head;
+	rdp->nxttail = &head->next;
+	local_irq_restore(flags);
+}
+
+/**
+ * call_rcu_bh - Queue an RCU for invocation after a quicker grace period.
+ * @head: structure to be used for queueing the RCU updates.
+ * @func: actual update function to be invoked after the grace period
+ *
+ * The update function will be invoked some time after a full grace
+ * period elapses, in other words after all currently executing RCU
+ * read-side critical sections have completed. call_rcu_bh() assumes
+ * that the read-side critical sections end on completion of a softirq
+ * handler. This means that read-side critical sections in process
+ * context must not be interrupted by softirqs. This interface is to be
+ * used when most of the read-side critical sections are in softirq context.
+ * RCU read-side critical sections are delimited by rcu_read_lock() and
+ * rcu_read_unlock(), * if in interrupt context or rcu_read_lock_bh()
+ * and rcu_read_unlock_bh(), if in process context. These may be nested.
+ */
+void fastcall call_rcu_bh(struct rcu_head *head,
+				void (*func)(struct rcu_head *rcu))
+{
+	unsigned long flags;
+	struct rcu_data *rdp;
+
+	head->func = func;
+	head->next = NULL;
+	local_irq_save(flags);
+	rdp = &__get_cpu_var(rcu_bh_data);
+	*rdp->nxttail = head;
+	rdp->nxttail = &head->next;
 	local_irq_restore(flags);
 }
 
@@ -93,15 +133,23 @@
  * Invoke the completed RCU callbacks. They are expected to be in
  * a per-cpu list.
  */
-static void rcu_do_batch(struct rcu_head *list)
+static void rcu_do_batch(struct rcu_data *rdp)
 {
-	struct rcu_head *next;
+	struct rcu_head *next, *list;
+	int count = 0;
 
+	list = rdp->donelist;
 	while (list) {
-		next = list->next;
+		next = rdp->donelist = list->next;
 		list->func(list);
 		list = next;
+		if (++count >= maxbatch)
+			break;
 	}
+	if (!rdp->donelist)
+		rdp->donetail = &rdp->donelist;
+	else
+		tasklet_schedule(&per_cpu(rcu_tasklet, rdp->cpu));
 }
 
 /*
@@ -109,15 +157,15 @@
  * The grace period handling consists out of two steps:
  * - A new grace period is started.
  *   This is done by rcu_start_batch. The start is not broadcasted to
- *   all cpus, they must pick this up by comparing rcu_ctrlblk.cur with
- *   RCU_quiescbatch(cpu). All cpus are recorded  in the
- *   rcu_state.rcu_cpu_mask bitmap.
+ *   all cpus, they must pick this up by comparing rcp->cur with
+ *   rdp->quiescbatch. All cpus are recorded  in the
+ *   rcu_state.cpumask bitmap.
  * - All cpus must go through a quiescent state.
  *   Since the start of the grace period is not broadcasted, at least two
  *   calls to rcu_check_quiescent_state are required:
  *   The first call just notices that a new grace period is running. The
  *   following calls check if there was a quiescent state since the beginning
- *   of the grace period. If so, it updates rcu_state.rcu_cpu_mask. If
+ *   of the grace period. If so, it updates rcu_state.cpumask. If
  *   the bitmap is empty, then the grace period is completed.
  *   rcu_check_quiescent_state calls rcu_start_batch(0) to start the next grace
  *   period (if necessary).
@@ -125,22 +173,22 @@
 /*
  * Register a new batch of callbacks, and start it up if there is currently no
  * active batch and the batch to be registered has not already occurred.
- * Caller must hold rcu_state.mutex.
+ * Caller must hold rcu_state.lock.
  */
-static void rcu_start_batch(int next_pending)
+static void rcu_start_batch(struct rcu_ctrlblk *rcp, struct rcu_state *rsp,
+				int next_pending)
 {
 	if (next_pending)
-		rcu_ctrlblk.next_pending = 1;
+		rcp->next_pending = 1;
 
-	if (rcu_ctrlblk.next_pending &&
-			rcu_ctrlblk.completed == rcu_ctrlblk.cur) {
+	if (rcp->next_pending &&
+			rcp->completed == rcp->cur) {
 		/* Can't change, since spin lock held. */
-		cpus_andnot(rcu_state.rcu_cpu_mask, cpu_online_map,
-							nohz_cpu_mask);
-		write_seqcount_begin(&rcu_ctrlblk.lock);
-		rcu_ctrlblk.next_pending = 0;
-		rcu_ctrlblk.cur++;
-		write_seqcount_end(&rcu_ctrlblk.lock);
+		cpus_andnot(rsp->cpumask, cpu_online_map, nohz_cpu_mask);
+		write_seqcount_begin(&rcp->lock);
+		rcp->next_pending = 0;
+		rcp->cur++;
+		write_seqcount_end(&rcp->lock);
 	}
 }
 
@@ -149,13 +197,13 @@
  * Clear it from the cpu mask and complete the grace period if it was the last
  * cpu. Start another grace period if someone has further entries pending
  */
-static void cpu_quiet(int cpu)
+static void cpu_quiet(int cpu, struct rcu_ctrlblk *rcp, struct rcu_state *rsp)
 {
-	cpu_clear(cpu, rcu_state.rcu_cpu_mask);
-	if (cpus_empty(rcu_state.rcu_cpu_mask)) {
+	cpu_clear(cpu, rsp->cpumask);
+	if (cpus_empty(rsp->cpumask)) {
 		/* batch completed ! */
-		rcu_ctrlblk.completed = rcu_ctrlblk.cur;
-		rcu_start_batch(0);
+		rcp->completed = rcp->cur;
+		rcu_start_batch(rcp, rsp, 0);
 	}
 }
 
@@ -164,15 +212,14 @@
  * switch). If so and if it already hasn't done so in this RCU
  * quiescent cycle, then indicate that it has done so.
  */
-static void rcu_check_quiescent_state(void)
+static void rcu_check_quiescent_state(struct rcu_ctrlblk *rcp,
+			struct rcu_state *rsp, struct rcu_data *rdp)
 {
-	int cpu = smp_processor_id();
-
-	if (RCU_quiescbatch(cpu) != rcu_ctrlblk.cur) {
+	if (rdp->quiescbatch != rcp->cur) {
 		/* new grace period: record qsctr value. */
-		RCU_qs_pending(cpu) = 1;
-		RCU_last_qsctr(cpu) = RCU_qsctr(cpu);
-		RCU_quiescbatch(cpu) = rcu_ctrlblk.cur;
+		rdp->qs_pending = 1;
+		rdp->last_qsctr = rdp->qsctr;
+		rdp->quiescbatch = rcp->cur;
 		return;
 	}
 
@@ -180,7 +227,7 @@
 	 * qs_pending is checked instead of the actual bitmap to avoid
 	 * cacheline trashing.
 	 */
-	if (!RCU_qs_pending(cpu))
+	if (!rdp->qs_pending)
 		return;
 
 	/* 
@@ -188,19 +235,19 @@
 	 * we may miss one quiescent state of that CPU. That is
 	 * tolerable. So no need to disable interrupts.
 	 */
-	if (RCU_qsctr(cpu) == RCU_last_qsctr(cpu))
+	if (rdp->qsctr == rdp->last_qsctr)
 		return;
-	RCU_qs_pending(cpu) = 0;
+	rdp->qs_pending = 0;
 
-	spin_lock(&rcu_state.mutex);
+	spin_lock(&rsp->lock);
 	/*
-	 * RCU_quiescbatch/batch.cur and the cpu bitmap can come out of sync
+	 * rdp->quiescbatch/rcp->cur and the cpu bitmap can come out of sync
 	 * during cpu startup. Ignore the quiescent state.
 	 */
-	if (likely(RCU_quiescbatch(cpu) == rcu_ctrlblk.cur))
-		cpu_quiet(cpu);
+	if (likely(rdp->quiescbatch == rcp->cur))
+		cpu_quiet(rdp->cpu, rcp, rsp);
 
-	spin_unlock(&rcu_state.mutex);
+	spin_unlock(&rsp->lock);
 }
 
 
@@ -210,112 +257,140 @@
  * locking requirements, the list it's pulling from has to belong to a cpu
  * which is dead and hence not processing interrupts.
  */
-static void rcu_move_batch(struct rcu_head *list)
+static void rcu_move_batch(struct rcu_data *this_rdp, struct rcu_head *list,
+				struct rcu_head **tail)
 {
-	int cpu;
-
 	local_irq_disable();
-
-	cpu = smp_processor_id();
-
-	while (list != NULL) {
-		*RCU_nxttail(cpu) = list;
-		RCU_nxttail(cpu) = &list->next;
-		list = list->next;
-	}
+	*this_rdp->nxttail = list;
+	if (list)
+		this_rdp->nxttail = tail;
 	local_irq_enable();
 }
 
-static void rcu_offline_cpu(int cpu)
+static void __rcu_offline_cpu(struct rcu_data *this_rdp,
+	struct rcu_ctrlblk *rcp, struct rcu_state *rsp, struct rcu_data *rdp)
 {
 	/* if the cpu going offline owns the grace period
 	 * we can block indefinitely waiting for it, so flush
 	 * it here
 	 */
-	spin_lock_bh(&rcu_state.mutex);
-	if (rcu_ctrlblk.cur != rcu_ctrlblk.completed)
-		cpu_quiet(cpu);
-	spin_unlock_bh(&rcu_state.mutex);
+	spin_lock_bh(&rsp->lock);
+	if (rcp->cur != rcp->completed)
+		cpu_quiet(rdp->cpu, rcp, rsp);
+	spin_unlock_bh(&rsp->lock);
+	rcu_move_batch(this_rdp, rdp->curlist, rdp->curtail);
+	rcu_move_batch(this_rdp, rdp->nxtlist, rdp->nxttail);
 
-	rcu_move_batch(RCU_curlist(cpu));
-	rcu_move_batch(RCU_nxtlist(cpu));
+}
+static void rcu_offline_cpu(int cpu)
+{
+	struct rcu_data *this_rdp = &get_cpu_var(rcu_data);
+	struct rcu_data *this_bh_rdp = &get_cpu_var(rcu_bh_data);
 
-	tasklet_kill_immediate(&RCU_tasklet(cpu), cpu);
+	__rcu_offline_cpu(this_rdp, &rcu_ctrlblk, &rcu_state,
+					&per_cpu(rcu_data, cpu));
+	__rcu_offline_cpu(this_bh_rdp, &rcu_bh_ctrlblk, &rcu_bh_state,
+					&per_cpu(rcu_bh_data, cpu));
+	put_cpu_var(rcu_data);
+	put_cpu_var(rcu_bh_data);
+	tasklet_kill_immediate(&per_cpu(rcu_tasklet, cpu), cpu);
 }
 
-#endif
+#else
 
-void rcu_restart_cpu(int cpu)
+static void rcu_offline_cpu(int cpu)
 {
-	spin_lock_bh(&rcu_state.mutex);
-	RCU_quiescbatch(cpu) = rcu_ctrlblk.completed;
-	RCU_qs_pending(cpu) = 0;
-	spin_unlock_bh(&rcu_state.mutex);
 }
 
+#endif
+
 /*
  * This does the RCU processing work from tasklet context. 
  */
-static void rcu_process_callbacks(unsigned long unused)
+static void __rcu_process_callbacks(struct rcu_ctrlblk *rcp,
+			struct rcu_state *rsp, struct rcu_data *rdp)
 {
-	int cpu = smp_processor_id();
-	struct rcu_head *rcu_list = NULL;
-
-	if (RCU_curlist(cpu) &&
-	    !rcu_batch_before(rcu_ctrlblk.completed, RCU_batch(cpu))) {
-		rcu_list = RCU_curlist(cpu);
-		RCU_curlist(cpu) = NULL;
+	if (rdp->curlist && !rcu_batch_before(rcp->completed, rdp->batch)) {
+		*rdp->donetail = rdp->curlist;
+		rdp->donetail = rdp->curtail;
+		rdp->curlist = NULL;
+		rdp->curtail = &rdp->curlist;
 	}
 
 	local_irq_disable();
-	if (RCU_nxtlist(cpu) && !RCU_curlist(cpu)) {
+	if (rdp->nxtlist && !rdp->curlist) {
 		int next_pending, seq;
 
-		RCU_curlist(cpu) = RCU_nxtlist(cpu);
-		RCU_nxtlist(cpu) = NULL;
-		RCU_nxttail(cpu) = &RCU_nxtlist(cpu);
+		rdp->curlist = rdp->nxtlist;
+		rdp->curtail = rdp->nxttail;
+		rdp->nxtlist = NULL;
+		rdp->nxttail = &rdp->nxtlist;
 		local_irq_enable();
 
 		/*
 		 * start the next batch of callbacks
 		 */
 		do {
-			seq = read_seqcount_begin(&rcu_ctrlblk.lock);
+			seq = read_seqcount_begin(&rcp->lock);
 			/* determine batch number */
-			RCU_batch(cpu) = rcu_ctrlblk.cur + 1;
-			next_pending = rcu_ctrlblk.next_pending;
-		} while (read_seqcount_retry(&rcu_ctrlblk.lock, seq));
+			rdp->batch = rcp->cur + 1;
+			next_pending = rcp->next_pending;
+		} while (read_seqcount_retry(&rcp->lock, seq));
 
 		if (!next_pending) {
 			/* and start it/schedule start if it's a new batch */
-			spin_lock(&rcu_state.mutex);
-			rcu_start_batch(1);
-			spin_unlock(&rcu_state.mutex);
+			spin_lock(&rsp->lock);
+			rcu_start_batch(rcp, rsp, 1);
+			spin_unlock(&rsp->lock);
 		}
 	} else {
 		local_irq_enable();
 	}
-	rcu_check_quiescent_state();
-	if (rcu_list)
-		rcu_do_batch(rcu_list);
+	rcu_check_quiescent_state(rcp, rsp, rdp);
+	if (rdp->donelist)
+		rcu_do_batch(rdp);
+}
+
+static void rcu_process_callbacks(unsigned long unused)
+{
+	__rcu_process_callbacks(&rcu_ctrlblk, &rcu_state,
+				&__get_cpu_var(rcu_data));
+	__rcu_process_callbacks(&rcu_bh_ctrlblk, &rcu_bh_state,
+				&__get_cpu_var(rcu_bh_data));
 }
 
 void rcu_check_callbacks(int cpu, int user)
 {
 	if (user || 
 	    (idle_cpu(cpu) && !in_softirq() && 
-				hardirq_count() <= (1 << HARDIRQ_SHIFT)))
-		RCU_qsctr(cpu)++;
-	tasklet_schedule(&RCU_tasklet(cpu));
+				hardirq_count() <= (1 << HARDIRQ_SHIFT))) {
+		rcu_qsctr_inc(cpu);
+		rcu_bh_qsctr_inc(cpu);
+	} else if (!in_softirq())
+		rcu_bh_qsctr_inc(cpu);
+	tasklet_schedule(&per_cpu(rcu_tasklet, cpu));
+}
+
+static void rcu_init_percpu_data(int cpu, struct rcu_ctrlblk *rcp,
+						struct rcu_data *rdp)
+{
+	memset(rdp, 0, sizeof(*rdp));
+	rdp->curtail = &rdp->curlist;
+	rdp->nxttail = &rdp->nxtlist;
+	rdp->donetail = &rdp->donelist;
+	rdp->quiescbatch = rcp->completed;
+	rdp->qs_pending = 0;
+	rdp->cpu = cpu;
 }
 
 static void __devinit rcu_online_cpu(int cpu)
 {
-	memset(&per_cpu(rcu_data, cpu), 0, sizeof(struct rcu_data));
-	tasklet_init(&RCU_tasklet(cpu), rcu_process_callbacks, 0UL);
-	RCU_nxttail(cpu) = &RCU_nxtlist(cpu);
-	RCU_quiescbatch(cpu) = rcu_ctrlblk.completed;
-	RCU_qs_pending(cpu) = 0;
+	struct rcu_data *rdp = &per_cpu(rcu_data, cpu);
+	struct rcu_data *bh_rdp = &per_cpu(rcu_bh_data, cpu);
+
+	rcu_init_percpu_data(cpu, &rcu_ctrlblk, rdp);
+	rcu_init_percpu_data(cpu, &rcu_bh_ctrlblk, bh_rdp);
+	tasklet_init(&per_cpu(rcu_tasklet, cpu), rcu_process_callbacks, 0UL);
 }
 
 static int __devinit rcu_cpu_notify(struct notifier_block *self, 
@@ -326,11 +401,9 @@
 	case CPU_UP_PREPARE:
 		rcu_online_cpu(cpu);
 		break;
-#ifdef CONFIG_HOTPLUG_CPU
 	case CPU_DEAD:
 		rcu_offline_cpu(cpu);
 		break;
-#endif
 	default:
 		break;
 	}
@@ -370,8 +443,13 @@
 }
 
 /**
- * synchronize-kernel - wait until all the CPUs have gone
- * through a "quiescent" state. It may sleep.
+ * synchronize_kernel - wait until a grace period has elapsed.
+ *
+ * Control will return to the caller some time after a full grace
+ * period has elapsed, in other words after all currently executing RCU
+ * read-side critical sections have completed.  RCU read-side critical
+ * sections are delimited by rcu_read_lock() and rcu_read_unlock(),
+ * and may be nested.
  */
 void synchronize_kernel(void)
 {
@@ -385,6 +463,7 @@
 	wait_for_completion(&rcu.completion);
 }
 
-
+module_param(maxbatch, int, 0);
 EXPORT_SYMBOL(call_rcu);
+EXPORT_SYMBOL(call_rcu_bh);
 EXPORT_SYMBOL(synchronize_kernel);
diff -Nru a/kernel/resource.c b/kernel/resource.c
--- a/kernel/resource.c	2004-10-18 14:56:33 -07:00
+++ b/kernel/resource.c	2004-10-18 14:56:33 -07:00
@@ -315,11 +315,12 @@
  */
 int insert_resource(struct resource *parent, struct resource *new)
 {
-	int result = 0;
+	int result;
 	struct resource *first, *next;
 
 	write_lock(&resource_lock);
  begin:
+ 	result = 0;
 	first = __request_resource(parent, new);
 	if (!first)
 		goto out;
@@ -328,15 +329,20 @@
 	if (first == parent)
 		goto out;
 
-	for (next = first; next->sibling; next = next->sibling)
+	/* Resource fully contained by the clashing resource? Recurse into it */
+	if (first->start <= new->start && first->end >= new->end) {
+		parent = first;
+		goto begin;
+	}
+
+	for (next = first; ; next = next->sibling) {
+		/* Partial overlap? Bad, and unfixable */
+		if (next->start < new->start || next->end > new->end)
+			goto out;
+		if (!next->sibling)
+			break;
 		if (next->sibling->start > new->end)
 			break;
-
-	/* existing resource includes new resource */
-	if (next->end >= new->end) {
-		parent = next;
-		result = 0;
-		goto begin;
 	}
 
 	result = 0;
diff -Nru a/kernel/sched.c b/kernel/sched.c
--- a/kernel/sched.c	2004-10-18 14:56:49 -07:00
+++ b/kernel/sched.c	2004-10-18 14:56:49 -07:00
@@ -31,6 +31,7 @@
 #include <linux/kernel_stat.h>
 #include <linux/security.h>
 #include <linux/notifier.h>
+#include <linux/profile.h>
 #include <linux/suspend.h>
 #include <linux/blkdev.h>
 #include <linux/delay.h>
@@ -40,6 +41,8 @@
 #include <linux/cpu.h>
 #include <linux/percpu.h>
 #include <linux/kthread.h>
+#include <linux/seq_file.h>
+#include <linux/times.h>
 #include <asm/tlb.h>
 
 #include <asm/unistd.h>
@@ -67,8 +70,6 @@
 #define USER_PRIO(p)		((p)-MAX_RT_PRIO)
 #define TASK_USER_PRIO(p)	USER_PRIO((p)->static_prio)
 #define MAX_USER_PRIO		(USER_PRIO(MAX_PRIO))
-#define AVG_TIMESLICE	(MIN_TIMESLICE + ((MAX_TIMESLICE - MIN_TIMESLICE) *\
-			(MAX_PRIO-1-NICE_TO_PRIO(0))/(MAX_USER_PRIO - 1)))
 
 /*
  * Some helpers for converting nanosecond timing to jiffy resolution
@@ -79,12 +80,12 @@
 /*
  * These are the 'tuning knobs' of the scheduler:
  *
- * Minimum timeslice is 10 msecs, default timeslice is 100 msecs,
- * maximum timeslice is 200 msecs. Timeslices get refilled after
- * they expire.
+ * Minimum timeslice is 5 msecs (or 1 jiffy, whichever is larger),
+ * default timeslice is 100 msecs, maximum timeslice is 800 msecs.
+ * Timeslices get refilled after they expire.
  */
-#define MIN_TIMESLICE		( 10 * HZ / 1000)
-#define MAX_TIMESLICE		(200 * HZ / 1000)
+#define MIN_TIMESLICE		max(5 * HZ / 1000, 1)
+#define DEF_TIMESLICE		(100 * HZ / 1000)
 #define ON_RUNQUEUE_WEIGHT	 30
 #define CHILD_PENALTY		 95
 #define PARENT_PENALTY		100
@@ -92,7 +93,7 @@
 #define PRIO_BONUS_RATIO	 25
 #define MAX_BONUS		(MAX_USER_PRIO * PRIO_BONUS_RATIO / 100)
 #define INTERACTIVE_DELTA	  2
-#define MAX_SLEEP_AVG		(AVG_TIMESLICE * MAX_BONUS)
+#define MAX_SLEEP_AVG		(DEF_TIMESLICE * MAX_BONUS)
 #define STARVATION_LIMIT	(MAX_SLEEP_AVG)
 #define NS_MAX_SLEEP_AVG	(JIFFIES_TO_NS(MAX_SLEEP_AVG))
 #define CREDIT_LIMIT		100
@@ -161,26 +162,36 @@
 	((p)->prio < (rq)->curr->prio)
 
 /*
- * BASE_TIMESLICE scales user-nice values [ -20 ... 19 ]
- * to time slice values.
+ * task_timeslice() scales user-nice values [ -20 ... 0 ... 19 ]
+ * to time slice values: [800ms ... 100ms ... 5ms]
  *
  * The higher a thread's priority, the bigger timeslices
  * it gets during one round of execution. But even the lowest
  * priority thread gets MIN_TIMESLICE worth of execution time.
- *
- * task_timeslice() is the interface that is used by the scheduler.
  */
 
-#define BASE_TIMESLICE(p) (MIN_TIMESLICE + \
-		((MAX_TIMESLICE - MIN_TIMESLICE) * \
-			(MAX_PRIO-1 - (p)->static_prio) / (MAX_USER_PRIO-1)))
+#define SCALE_PRIO(x, prio) \
+	max(x * (MAX_PRIO - prio) / (MAX_USER_PRIO/2), MIN_TIMESLICE)
 
 static unsigned int task_timeslice(task_t *p)
 {
-	return BASE_TIMESLICE(p);
+	if (p->static_prio < NICE_TO_PRIO(0))
+		return SCALE_PRIO(DEF_TIMESLICE*4, p->static_prio);
+	else
+		return SCALE_PRIO(DEF_TIMESLICE, p->static_prio);
 }
+#define task_hot(p, now, sd) ((long long) ((now) - (p)->last_ran)	\
+				< (long long) (sd)->cache_hot_time)
+
+enum idle_type
+{
+	IDLE,
+	NOT_IDLE,
+	NEWLY_IDLE,
+	MAX_IDLE_TYPES
+};
 
-#define task_hot(p, now, sd) ((now) - (p)->timestamp < (sd)->cache_hot_time)
+struct sched_domain;
 
 /*
  * These are the runqueue data structures:
@@ -233,10 +244,186 @@
 	task_t *migration_thread;
 	struct list_head migration_queue;
 #endif
+
+#ifdef CONFIG_SCHEDSTATS
+	/* latency stats */
+	struct sched_info rq_sched_info;
+
+	/* sys_sched_yield() stats */
+	unsigned long yld_exp_empty;
+	unsigned long yld_act_empty;
+	unsigned long yld_both_empty;
+	unsigned long yld_cnt;
+
+	/* schedule() stats */
+	unsigned long sched_noswitch;
+	unsigned long sched_switch;
+	unsigned long sched_cnt;
+	unsigned long sched_goidle;
+
+	/* pull_task() stats */
+	unsigned long pt_gained[MAX_IDLE_TYPES];
+	unsigned long pt_lost[MAX_IDLE_TYPES];
+
+	/* active_load_balance() stats */
+	unsigned long alb_cnt;
+	unsigned long alb_lost;
+	unsigned long alb_gained;
+	unsigned long alb_failed;
+
+	/* try_to_wake_up() stats */
+	unsigned long ttwu_cnt;
+	unsigned long ttwu_attempts;
+	unsigned long ttwu_moved;
+
+	/* wake_up_new_task() stats */
+	unsigned long wunt_cnt;
+	unsigned long wunt_moved;
+
+	/* sched_migrate_task() stats */
+	unsigned long smt_cnt;
+
+	/* sched_balance_exec() stats */
+	unsigned long sbe_cnt;
+#endif
 };
 
 static DEFINE_PER_CPU(struct runqueue, runqueues);
 
+/*
+ * sched-domains (multiprocessor balancing) declarations:
+ */
+#ifdef CONFIG_SMP
+#define SCHED_LOAD_SCALE	128UL	/* increase resolution of load */
+
+#define SD_BALANCE_NEWIDLE	1	/* Balance when about to become idle */
+#define SD_BALANCE_EXEC		2	/* Balance on exec */
+#define SD_WAKE_IDLE		4	/* Wake to idle CPU on task wakeup */
+#define SD_WAKE_AFFINE		8	/* Wake task to waking CPU */
+#define SD_WAKE_BALANCE		16	/* Perform balancing at task wakeup */
+#define SD_SHARE_CPUPOWER	32	/* Domain members share cpu power */
+
+struct sched_group {
+	struct sched_group *next;	/* Must be a circular list */
+	cpumask_t cpumask;
+
+	/*
+	 * CPU power of this group, SCHED_LOAD_SCALE being max power for a
+	 * single CPU. This should be read only (except for setup). Although
+	 * it will need to be written to at cpu hot(un)plug time, perhaps the
+	 * cpucontrol semaphore will provide enough exclusion?
+	 */
+	unsigned long cpu_power;
+};
+
+struct sched_domain {
+	/* These fields must be setup */
+	struct sched_domain *parent;	/* top domain must be null terminated */
+	struct sched_group *groups;	/* the balancing groups of the domain */
+	cpumask_t span;			/* span of all CPUs in this domain */
+	unsigned long min_interval;	/* Minimum balance interval ms */
+	unsigned long max_interval;	/* Maximum balance interval ms */
+	unsigned int busy_factor;	/* less balancing by factor if busy */
+	unsigned int imbalance_pct;	/* No balance until over watermark */
+	unsigned long long cache_hot_time; /* Task considered cache hot (ns) */
+	unsigned int cache_nice_tries;	/* Leave cache hot tasks for # tries */
+	unsigned int per_cpu_gain;	/* CPU % gained by adding domain cpus */
+	int flags;			/* See SD_* */
+
+	/* Runtime fields. */
+	unsigned long last_balance;	/* init to jiffies. units in jiffies */
+	unsigned int balance_interval;	/* initialise to 1. units in ms. */
+	unsigned int nr_balance_failed; /* initialise to 0 */
+
+#ifdef CONFIG_SCHEDSTATS
+	/* load_balance() stats */
+	unsigned long lb_cnt[MAX_IDLE_TYPES];
+	unsigned long lb_failed[MAX_IDLE_TYPES];
+	unsigned long lb_imbalance[MAX_IDLE_TYPES];
+	unsigned long lb_nobusyg[MAX_IDLE_TYPES];
+	unsigned long lb_nobusyq[MAX_IDLE_TYPES];
+
+	/* sched_balance_exec() stats */
+	unsigned long sbe_attempts;
+	unsigned long sbe_pushed;
+
+	/* try_to_wake_up() stats */
+	unsigned long ttwu_wake_affine;
+	unsigned long ttwu_wake_balance;
+#endif
+};
+
+#ifndef ARCH_HAS_SCHED_TUNE
+#ifdef CONFIG_SCHED_SMT
+#define ARCH_HAS_SCHED_WAKE_IDLE
+/* Common values for SMT siblings */
+#define SD_SIBLING_INIT (struct sched_domain) {		\
+	.span			= CPU_MASK_NONE,	\
+	.parent			= NULL,			\
+	.groups			= NULL,			\
+	.min_interval		= 1,			\
+	.max_interval		= 2,			\
+	.busy_factor		= 8,			\
+	.imbalance_pct		= 110,			\
+	.cache_hot_time		= 0,			\
+	.cache_nice_tries	= 0,			\
+	.per_cpu_gain		= 25,			\
+	.flags			= SD_BALANCE_NEWIDLE	\
+				| SD_BALANCE_EXEC	\
+				| SD_WAKE_AFFINE	\
+				| SD_WAKE_IDLE		\
+				| SD_SHARE_CPUPOWER,	\
+	.last_balance		= jiffies,		\
+	.balance_interval	= 1,			\
+	.nr_balance_failed	= 0,			\
+}
+#endif
+
+/* Common values for CPUs */
+#define SD_CPU_INIT (struct sched_domain) {		\
+	.span			= CPU_MASK_NONE,	\
+	.parent			= NULL,			\
+	.groups			= NULL,			\
+	.min_interval		= 1,			\
+	.max_interval		= 4,			\
+	.busy_factor		= 64,			\
+	.imbalance_pct		= 125,			\
+	.cache_hot_time		= cache_decay_ticks*1000000 ? : (5*1000000/2),\
+	.cache_nice_tries	= 1,			\
+	.per_cpu_gain		= 100,			\
+	.flags			= SD_BALANCE_NEWIDLE	\
+				| SD_BALANCE_EXEC	\
+				| SD_WAKE_AFFINE	\
+				| SD_WAKE_BALANCE,	\
+	.last_balance		= jiffies,		\
+	.balance_interval	= 1,			\
+	.nr_balance_failed	= 0,			\
+}
+
+/* Arch can override this macro in processor.h */
+#if defined(CONFIG_NUMA) && !defined(SD_NODE_INIT)
+#define SD_NODE_INIT (struct sched_domain) {		\
+	.span			= CPU_MASK_NONE,	\
+	.parent			= NULL,			\
+	.groups			= NULL,			\
+	.min_interval		= 8,			\
+	.max_interval		= 32,			\
+	.busy_factor		= 32,			\
+	.imbalance_pct		= 125,			\
+	.cache_hot_time		= (10*1000000),		\
+	.cache_nice_tries	= 1,			\
+	.per_cpu_gain		= 100,			\
+	.flags			= SD_BALANCE_EXEC	\
+				| SD_WAKE_BALANCE,	\
+	.last_balance		= jiffies,		\
+	.balance_interval	= 1,			\
+	.nr_balance_failed	= 0,			\
+}
+#endif
+#endif /* ARCH_HAS_SCHED_TUNE */
+#endif
+
+
 #define for_each_domain(cpu, domain) \
 	for (domain = cpu_rq(cpu)->sd; domain; domain = domain->parent)
 
@@ -279,6 +466,104 @@
 	spin_unlock_irqrestore(&rq->lock, *flags);
 }
 
+#ifdef CONFIG_SCHEDSTATS
+/*
+ * bump this up when changing the output format or the meaning of an existing
+ * format, so that tools can adapt (or abort)
+ */
+#define SCHEDSTAT_VERSION 10
+
+static int show_schedstat(struct seq_file *seq, void *v)
+{
+	int cpu;
+	enum idle_type itype;
+
+	seq_printf(seq, "version %d\n", SCHEDSTAT_VERSION);
+	seq_printf(seq, "timestamp %lu\n", jiffies);
+	for_each_online_cpu(cpu) {
+		runqueue_t *rq = cpu_rq(cpu);
+#ifdef CONFIG_SMP
+		struct sched_domain *sd;
+		int dcnt = 0;
+#endif
+
+		/* runqueue-specific stats */
+		seq_printf(seq,
+		    "cpu%d %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu "
+		    "%lu %lu %lu %lu %lu %lu %lu %lu %lu %lu",
+		    cpu, rq->yld_both_empty,
+		    rq->yld_act_empty, rq->yld_exp_empty,
+		    rq->yld_cnt, rq->sched_noswitch,
+		    rq->sched_switch, rq->sched_cnt, rq->sched_goidle,
+		    rq->alb_cnt, rq->alb_gained, rq->alb_lost,
+		    rq->alb_failed,
+		    rq->ttwu_cnt, rq->ttwu_moved, rq->ttwu_attempts,
+		    rq->wunt_cnt, rq->wunt_moved,
+		    rq->smt_cnt, rq->sbe_cnt, rq->rq_sched_info.cpu_time,
+		    rq->rq_sched_info.run_delay, rq->rq_sched_info.pcnt);
+
+		for (itype = IDLE; itype < MAX_IDLE_TYPES; itype++)
+			seq_printf(seq, " %lu %lu", rq->pt_gained[itype],
+						    rq->pt_lost[itype]);
+		seq_printf(seq, "\n");
+
+#ifdef CONFIG_SMP
+		/* domain-specific stats */
+		for_each_domain(cpu, sd) {
+			char mask_str[NR_CPUS];
+
+			cpumask_scnprintf(mask_str, NR_CPUS, sd->span);
+			seq_printf(seq, "domain%d %s", dcnt++, mask_str);
+			for (itype = IDLE; itype < MAX_IDLE_TYPES; itype++) {
+				seq_printf(seq, " %lu %lu %lu %lu %lu",
+				    sd->lb_cnt[itype],
+				    sd->lb_failed[itype],
+				    sd->lb_imbalance[itype],
+				    sd->lb_nobusyq[itype],
+				    sd->lb_nobusyg[itype]);
+			}
+			seq_printf(seq, " %lu %lu %lu %lu\n",
+			    sd->sbe_pushed, sd->sbe_attempts,
+			    sd->ttwu_wake_affine, sd->ttwu_wake_balance);
+		}
+#endif
+	}
+	return 0;
+}
+
+static int schedstat_open(struct inode *inode, struct file *file)
+{
+	unsigned int size = PAGE_SIZE * (1 + num_online_cpus() / 32);
+	char *buf = kmalloc(size, GFP_KERNEL);
+	struct seq_file *m;
+	int res;
+
+	if (!buf)
+		return -ENOMEM;
+	res = single_open(file, show_schedstat, NULL);
+	if (!res) {
+		m = file->private_data;
+		m->buf = buf;
+		m->size = size;
+	} else
+		kfree(buf);
+	return res;
+}
+
+struct file_operations proc_schedstat_operations = {
+	.open    = schedstat_open,
+	.read    = seq_read,
+	.llseek  = seq_lseek,
+	.release = single_release,
+};
+
+# define schedstat_inc(rq, field)	rq->field++;
+# define schedstat_add(rq, field, amt)	rq->field += amt;
+#else /* !CONFIG_SCHEDSTATS */
+# define schedstat_inc(rq, field)	do { } while (0);
+# define schedstat_add(rq, field, amt)	do { } while (0);
+#endif
+
 /*
  * rq_lock - lock a given runqueue and disable interrupts.
  */
@@ -298,6 +583,112 @@
 	spin_unlock_irq(&rq->lock);
 }
 
+#ifdef CONFIG_SCHEDSTATS
+/*
+ * Called when a process is dequeued from the active array and given
+ * the cpu.  We should note that with the exception of interactive
+ * tasks, the expired queue will become the active queue after the active
+ * queue is empty, without explicitly dequeuing and requeuing tasks in the
+ * expired queue.  (Interactive tasks may be requeued directly to the
+ * active queue, thus delaying tasks in the expired queue from running;
+ * see scheduler_tick()).
+ *
+ * This function is only called from sched_info_arrive(), rather than
+ * dequeue_task(). Even though a task may be queued and dequeued multiple
+ * times as it is shuffled about, we're really interested in knowing how
+ * long it was from the *first* time it was queued to the time that it
+ * finally hit a cpu.
+ */
+static inline void sched_info_dequeued(task_t *t)
+{
+	t->sched_info.last_queued = 0;
+}
+
+/*
+ * Called when a task finally hits the cpu.  We can now calculate how
+ * long it was waiting to run.  We also note when it began so that we
+ * can keep stats on how long its timeslice is.
+ */
+static inline void sched_info_arrive(task_t *t)
+{
+	unsigned long now = jiffies, diff = 0;
+	struct runqueue *rq = task_rq(t);
+
+	if (t->sched_info.last_queued)
+		diff = now - t->sched_info.last_queued;
+	sched_info_dequeued(t);
+	t->sched_info.run_delay += diff;
+	t->sched_info.last_arrival = now;
+	t->sched_info.pcnt++;
+
+	if (!rq)
+		return;
+
+	rq->rq_sched_info.run_delay += diff;
+	rq->rq_sched_info.pcnt++;
+}
+
+/*
+ * Called when a process is queued into either the active or expired
+ * array.  The time is noted and later used to determine how long we
+ * had to wait for us to reach the cpu.  Since the expired queue will
+ * become the active queue after active queue is empty, without dequeuing
+ * and requeuing any tasks, we are interested in queuing to either. It
+ * is unusual but not impossible for tasks to be dequeued and immediately
+ * requeued in the same or another array: this can happen in sched_yield(),
+ * set_user_nice(), and even load_balance() as it moves tasks from runqueue
+ * to runqueue.
+ *
+ * This function is only called from enqueue_task(), but also only updates
+ * the timestamp if it is already not set.  It's assumed that
+ * sched_info_dequeued() will clear that stamp when appropriate.
+ */
+static inline void sched_info_queued(task_t *t)
+{
+	if (!t->sched_info.last_queued)
+		t->sched_info.last_queued = jiffies;
+}
+
+/*
+ * Called when a process ceases being the active-running process, either
+ * voluntarily or involuntarily.  Now we can calculate how long we ran.
+ */
+static inline void sched_info_depart(task_t *t)
+{
+	struct runqueue *rq = task_rq(t);
+	unsigned long diff = jiffies - t->sched_info.last_arrival;
+
+	t->sched_info.cpu_time += diff;
+
+	if (rq)
+		rq->rq_sched_info.cpu_time += diff;
+}
+
+/*
+ * Called when tasks are switched involuntarily due, typically, to expiring
+ * their time slice.  (This may also be called when switching to or from
+ * the idle task.)  We are only called when prev != next.
+ */
+static inline void sched_info_switch(task_t *prev, task_t *next)
+{
+	struct runqueue *rq = task_rq(prev);
+
+	/*
+	 * prev now departs the cpu.  It's not interesting to record
+	 * stats about how efficient we were at scheduling the idle
+	 * process, however.
+	 */
+	if (prev != rq->idle)
+		sched_info_depart(prev);
+
+	if (next != rq->idle)
+		sched_info_arrive(next);
+}
+#else
+#define sched_info_queued(t)		do { } while (0)
+#define sched_info_switch(t, next)	do { } while (0)
+#endif /* CONFIG_SCHEDSTATS */
+
 /*
  * Adding/removing a task to/from a priority array:
  */
@@ -311,6 +702,7 @@
 
 static void enqueue_task(struct task_struct *p, prio_array_t *array)
 {
+	sched_info_queued(p);
 	list_add_tail(&p->run_list, array->queue + p->prio);
 	__set_bit(p->prio, array->bitmap);
 	array->nr_active++;
@@ -399,7 +791,7 @@
 		if (p->mm && p->activated != -1 &&
 			sleep_time > INTERACTIVE_SLEEP(p)) {
 				p->sleep_avg = JIFFIES_TO_NS(MAX_SLEEP_AVG -
-						AVG_TIMESLICE);
+						DEF_TIMESLICE);
 				if (!HIGH_CREDIT(p))
 					p->interactive_credit++;
 		} else {
@@ -526,7 +918,8 @@
 {
 	int need_resched, nrpolling;
 
-	preempt_disable();
+	BUG_ON(!spin_is_locked(&task_rq(p)->lock));
+
 	/* minimise the chance of sending an interrupt to poll_idle() */
 	nrpolling = test_tsk_thread_flag(p,TIF_POLLING_NRFLAG);
 	need_resched = test_and_set_tsk_thread_flag(p,TIF_NEED_RESCHED);
@@ -534,7 +927,6 @@
 
 	if (!need_resched && !nrpolling && (task_cpu(p) != smp_processor_id()))
 		smp_send_reschedule(task_cpu(p));
-	preempt_enable();
 }
 #else
 static inline void resched_task(task_t *p)
@@ -740,6 +1132,7 @@
 #endif
 
 	rq = task_rq_lock(p, &flags);
+	schedstat_inc(rq, ttwu_cnt);
 	old_state = p->state;
 	if (!(old_state & state))
 		goto out;
@@ -787,23 +1180,35 @@
 		 */
 		imbalance = sd->imbalance_pct + (sd->imbalance_pct - 100) / 2;
 
-		if ( ((sd->flags & SD_WAKE_AFFINE) &&
-				!task_hot(p, rq->timestamp_last_tick, sd))
-			|| ((sd->flags & SD_WAKE_BALANCE) &&
-				imbalance*this_load <= 100*load) ) {
+		if ((sd->flags & SD_WAKE_AFFINE) &&
+				!task_hot(p, rq->timestamp_last_tick, sd)) {
+			/*
+			 * This domain has SD_WAKE_AFFINE and p is cache cold
+			 * in this domain.
+			 */
+			if (cpu_isset(cpu, sd->span)) {
+				schedstat_inc(sd, ttwu_wake_affine);
+				goto out_set_cpu;
+			}
+		} else if ((sd->flags & SD_WAKE_BALANCE) &&
+				imbalance*this_load <= 100*load) {
 			/*
-			 * Now sd has SD_WAKE_AFFINE and p is cache cold in sd
-			 * or sd has SD_WAKE_BALANCE and there is an imbalance
+			 * This domain has SD_WAKE_BALANCE and there is
+			 * an imbalance.
 			 */
-			if (cpu_isset(cpu, sd->span))
+			if (cpu_isset(cpu, sd->span)) {
+				schedstat_inc(sd, ttwu_wake_balance);
 				goto out_set_cpu;
+			}
 		}
 	}
 
 	new_cpu = cpu; /* Could not wake to this_cpu. Wake to cpu instead */
 out_set_cpu:
+	schedstat_inc(rq, ttwu_attempts);
 	new_cpu = wake_idle(new_cpu, p);
 	if (new_cpu != cpu && cpu_isset(new_cpu, p->cpus_allowed)) {
+		schedstat_inc(rq, ttwu_moved);
 		set_task_cpu(p, new_cpu);
 		task_rq_unlock(rq, &flags);
 		/* might preempt at this point */
@@ -854,7 +1259,7 @@
 
 int fastcall wake_up_process(task_t * p)
 {
-	return try_to_wake_up(p, TASK_STOPPED |
+	return try_to_wake_up(p, TASK_STOPPED | TASK_TRACED |
 		       		 TASK_INTERRUPTIBLE | TASK_UNINTERRUPTIBLE, 0);
 }
 
@@ -865,6 +1270,11 @@
 	return try_to_wake_up(p, state, 0);
 }
 
+#ifdef CONFIG_SMP
+static int find_idlest_cpu(struct task_struct *p, int this_cpu,
+			   struct sched_domain *sd);
+#endif
+
 /*
  * Perform scheduler related setup for a newly forked process p.
  * p is forked by current.
@@ -881,6 +1291,9 @@
 	INIT_LIST_HEAD(&p->run_list);
 	p->array = NULL;
 	spin_lock_init(&p->switch_lock);
+#ifdef CONFIG_SCHEDSTATS
+	memset(&p->sched_info, 0, sizeof(p->sched_info));
+#endif
 #ifdef CONFIG_PREEMPT
 	/*
 	 * During context-switch we hold precisely one spinlock, which
@@ -904,7 +1317,7 @@
 	p->first_time_slice = 1;
 	current->time_slice >>= 1;
 	p->timestamp = sched_clock();
-	if (!current->time_slice) {
+	if (unlikely(!current->time_slice)) {
 		/*
 		 * This case is rare, it happens when the parent has only
 		 * a single jiffy left from its timeslice. Taking the
@@ -920,44 +1333,89 @@
 }
 
 /*
- * wake_up_forked_process - wake up a freshly forked process.
+ * wake_up_new_task - wake up a newly created task for the first time.
  *
  * This function will do some initial scheduler statistics housekeeping
- * that must be done for every newly created process.
+ * that must be done for every newly created context, then puts the task
+ * on the runqueue and wakes it.
  */
-void fastcall wake_up_forked_process(task_t * p)
+void fastcall wake_up_new_task(task_t * p, unsigned long clone_flags)
 {
 	unsigned long flags;
-	runqueue_t *rq = task_rq_lock(current, &flags);
+	int this_cpu, cpu;
+	runqueue_t *rq, *this_rq;
+
+	rq = task_rq_lock(p, &flags);
+	cpu = task_cpu(p);
+	this_cpu = smp_processor_id();
 
 	BUG_ON(p->state != TASK_RUNNING);
 
+	schedstat_inc(rq, wunt_cnt);
 	/*
 	 * We decrease the sleep average of forking parents
 	 * and children as well, to keep max-interactive tasks
-	 * from forking tasks that are max-interactive.
+	 * from forking tasks that are max-interactive. The parent
+	 * (current) is done further down, under its lock.
 	 */
-	current->sleep_avg = JIFFIES_TO_NS(CURRENT_BONUS(current) *
-		PARENT_PENALTY / 100 * MAX_SLEEP_AVG / MAX_BONUS);
-
 	p->sleep_avg = JIFFIES_TO_NS(CURRENT_BONUS(p) *
 		CHILD_PENALTY / 100 * MAX_SLEEP_AVG / MAX_BONUS);
 
 	p->interactive_credit = 0;
 
 	p->prio = effective_prio(p);
-	set_task_cpu(p, smp_processor_id());
 
-	if (unlikely(!current->array))
+	if (likely(cpu == this_cpu)) {
+		if (!(clone_flags & CLONE_VM)) {
+			/*
+			 * The VM isn't cloned, so we're in a good position to
+			 * do child-runs-first in anticipation of an exec. This
+			 * usually avoids a lot of COW overhead.
+			 */
+			if (unlikely(!current->array))
+				__activate_task(p, rq);
+			else {
+				p->prio = current->prio;
+				list_add_tail(&p->run_list, &current->run_list);
+				p->array = current->array;
+				p->array->nr_active++;
+				rq->nr_running++;
+			}
+			set_need_resched();
+		} else
+			/* Run child last */
+			__activate_task(p, rq);
+		/*
+		 * We skip the following code due to cpu == this_cpu
+	 	 *
+		 *   task_rq_unlock(rq, &flags);
+		 *   this_rq = task_rq_lock(current, &flags);
+		 */
+		this_rq = rq;
+	} else {
+		this_rq = cpu_rq(this_cpu);
+
+		/*
+		 * Not the local CPU - must adjust timestamp. This should
+		 * get optimised away in the !CONFIG_SMP case.
+		 */
+		p->timestamp = (p->timestamp - this_rq->timestamp_last_tick)
+					+ rq->timestamp_last_tick;
 		__activate_task(p, rq);
-	else {
-		p->prio = current->prio;
-		list_add_tail(&p->run_list, &current->run_list);
-		p->array = current->array;
-		p->array->nr_active++;
-		rq->nr_running++;
+		if (TASK_PREEMPTS_CURR(p, rq))
+			resched_task(rq->curr);
+
+		schedstat_inc(rq, wunt_moved);
+		/*
+		 * Parent and child are on different CPUs, now get the
+		 * parent runqueue to update the parent's ->sleep_avg:
+		 */
+		task_rq_unlock(rq, &flags);
+		this_rq = task_rq_lock(current, &flags);
 	}
-	task_rq_unlock(rq, &flags);
+	current->sleep_avg = JIFFIES_TO_NS(CURRENT_BONUS(current) *
+		PARENT_PENALTY / 100 * MAX_SLEEP_AVG / MAX_BONUS);
+	task_rq_unlock(this_rq, &flags);
 }
 
 /*
@@ -974,18 +1432,16 @@
 	unsigned long flags;
 	runqueue_t *rq;
 
-	local_irq_save(flags);
-	if (p->first_time_slice) {
-		p->parent->time_slice += p->time_slice;
-		if (unlikely(p->parent->time_slice > MAX_TIMESLICE))
-			p->parent->time_slice = MAX_TIMESLICE;
-	}
-	local_irq_restore(flags);
 	/*
 	 * If the child was a (relative-) CPU hog then decrease
 	 * the sleep_avg of the parent as well.
 	 */
 	rq = task_rq_lock(p->parent, &flags);
+	if (p->first_time_slice) {
+		p->parent->time_slice += p->time_slice;
+		if (unlikely(p->parent->time_slice > task_timeslice(p)))
+			p->parent->time_slice = task_timeslice(p);
+	}
 	if (p->sleep_avg < p->parent->sleep_avg)
 		p->parent->sleep_avg = p->parent->sleep_avg /
 		(EXIT_WEIGHT + 1) * EXIT_WEIGHT + p->sleep_avg /
@@ -1085,7 +1541,7 @@
 {
 	unsigned long i, sum = 0;
 
-	for_each_cpu(i)
+	for_each_online_cpu(i)
 		sum += cpu_rq(i)->nr_running;
 
 	return sum;
@@ -1121,6 +1577,8 @@
 	return sum;
 }
 
+#ifdef CONFIG_SMP
+
 /*
  * double_rq_lock - safely lock two runqueues
  *
@@ -1155,14 +1613,20 @@
 		spin_unlock(&rq2->lock);
 }
 
-enum idle_type
+/*
+ * double_lock_balance - lock the busiest runqueue, this_rq is locked already.
+ */
+static void double_lock_balance(runqueue_t *this_rq, runqueue_t *busiest)
 {
-	IDLE,
-	NOT_IDLE,
-	NEWLY_IDLE,
-};
-
-#ifdef CONFIG_SMP
+	if (unlikely(!spin_trylock(&busiest->lock))) {
+		if (busiest < this_rq) {
+			spin_unlock(&this_rq->lock);
+			spin_lock(&busiest->lock);
+			spin_lock(&this_rq->lock);
+		} else
+			spin_lock(&busiest->lock);
+	}
+}
 
 /*
  * find_idlest_cpu - find the least busy runqueue.
@@ -1211,89 +1675,6 @@
 }
 
 /*
- * wake_up_forked_thread - wake up a freshly forked thread.
- *
- * This function will do some initial scheduler statistics housekeeping
- * that must be done for every newly created context, and it also does
- * runqueue balancing.
- */
-void fastcall wake_up_forked_thread(task_t * p)
-{
-	unsigned long flags;
-	int this_cpu = get_cpu(), cpu;
-	struct sched_domain *tmp, *sd = NULL;
-	runqueue_t *this_rq = cpu_rq(this_cpu), *rq;
-
-	/*
-	 * Find the largest domain that this CPU is part of that
-	 * is willing to balance on clone:
-	 */
-	for_each_domain(this_cpu, tmp)
-		if (tmp->flags & SD_BALANCE_CLONE)
-			sd = tmp;
-	if (sd)
-		cpu = find_idlest_cpu(p, this_cpu, sd);
-	else
-		cpu = this_cpu;
-
-	local_irq_save(flags);
-lock_again:
-	rq = cpu_rq(cpu);
-	double_rq_lock(this_rq, rq);
-
-	BUG_ON(p->state != TASK_RUNNING);
-
-	/*
-	 * We did find_idlest_cpu() unlocked, so in theory
-	 * the mask could have changed - just dont migrate
-	 * in this case:
-	 */
-	if (unlikely(!cpu_isset(cpu, p->cpus_allowed))) {
-		cpu = this_cpu;
-		double_rq_unlock(this_rq, rq);
-		goto lock_again;
-	}
-	/*
-	 * We decrease the sleep average of forking parents
-	 * and children as well, to keep max-interactive tasks
-	 * from forking tasks that are max-interactive.
-	 */
-	current->sleep_avg = JIFFIES_TO_NS(CURRENT_BONUS(current) *
-		PARENT_PENALTY / 100 * MAX_SLEEP_AVG / MAX_BONUS);
-
-	p->sleep_avg = JIFFIES_TO_NS(CURRENT_BONUS(p) *
-		CHILD_PENALTY / 100 * MAX_SLEEP_AVG / MAX_BONUS);
-
-	p->interactive_credit = 0;
-
-	p->prio = effective_prio(p);
-	set_task_cpu(p, cpu);
-
-	if (cpu == this_cpu) {
-		if (unlikely(!current->array))
-			__activate_task(p, rq);
-		else {
-			p->prio = current->prio;
-			list_add_tail(&p->run_list, &current->run_list);
-			p->array = current->array;
-			p->array->nr_active++;
-			rq->nr_running++;
-		}
-	} else {
-		/* Not the local CPU - must adjust timestamp */
-		p->timestamp = (p->timestamp - this_rq->timestamp_last_tick)
-					+ rq->timestamp_last_tick;
-		__activate_task(p, rq);
-		if (TASK_PREEMPTS_CURR(p, rq))
-			resched_task(rq->curr);
-	}
-
-	double_rq_unlock(this_rq, rq);
-	local_irq_restore(flags);
-	put_cpu();
-}
-
-/*
  * If dest_cpu is allowed for this process, migrate the task to it.
  * This is accomplished by forcing the cpu_allowed mask to only
  * allow dest_cpu, which will force the cpu onto dest_cpu.  Then
@@ -1310,6 +1691,7 @@
 	    || unlikely(cpu_is_offline(dest_cpu)))
 		goto out;
 
+	schedstat_inc(rq, smt_cnt);
 	/* force the process onto the specified CPU */
 	if (migrate_task(p, dest_cpu, &req)) {
 		/* Need to wait for migration thread (might exit: take ref). */
@@ -1326,17 +1708,18 @@
 }
 
 /*
- * sched_balance_exec(): find the highest-level, exec-balance-capable
+ * sched_exec(): find the highest-level, exec-balance-capable
  * domain and try to migrate the task to the least loaded CPU.
  *
  * execve() is a valuable balancing opportunity, because at this point
  * the task has the smallest effective memory and cache footprint.
  */
-void sched_balance_exec(void)
+void sched_exec(void)
 {
 	struct sched_domain *tmp, *sd = NULL;
 	int new_cpu, this_cpu = get_cpu();
 
+	schedstat_inc(this_rq(), sbe_cnt);
 	/* Prefer the current CPU if there's only this task running */
 	if (this_rq()->nr_running <= 1)
 		goto out;
@@ -1346,8 +1729,10 @@
 			sd = tmp;
 
 	if (sd) {
+		schedstat_inc(sd, sbe_attempts);
 		new_cpu = find_idlest_cpu(current, this_cpu, sd);
 		if (new_cpu != this_cpu) {
+			schedstat_inc(sd, sbe_pushed);
 			put_cpu();
 			sched_migrate_task(current, new_cpu);
 			return;
@@ -1358,21 +1743,6 @@
 }
 
 /*
- * double_lock_balance - lock the busiest runqueue, this_rq is locked already.
- */
-static void double_lock_balance(runqueue_t *this_rq, runqueue_t *busiest)
-{
-	if (unlikely(!spin_trylock(&busiest->lock))) {
-		if (busiest < this_rq) {
-			spin_unlock(&this_rq->lock);
-			spin_lock(&busiest->lock);
-			spin_lock(&this_rq->lock);
-		} else
-			spin_lock(&busiest->lock);
-	}
-}
-
-/*
  * pull_task - move a task from a remote runqueue to the local runqueue.
  * Both runqueues must be locked.
  */
@@ -1486,6 +1856,15 @@
 		idx++;
 		goto skip_bitmap;
 	}
+
+	/*
+	 * Right now, this is the only place pull_task() is called,
+	 * so we can safely collect pull_task() stats here rather than
+	 * inside pull_task().
+	 */
+	schedstat_inc(this_rq, pt_gained[idle]);
+	schedstat_inc(busiest, pt_lost[idle]);
+
 	pull_task(busiest, array, tmp, this_rq, dst_array, this_cpu);
 	pulled++;
 
@@ -1680,14 +2059,20 @@
 	int nr_moved;
 
 	spin_lock(&this_rq->lock);
+	schedstat_inc(sd, lb_cnt[idle]);
 
 	group = find_busiest_group(sd, this_cpu, &imbalance, idle);
-	if (!group)
+	if (!group) {
+		schedstat_inc(sd, lb_nobusyg[idle]);
 		goto out_balanced;
+	}
 
 	busiest = find_busiest_queue(group);
-	if (!busiest)
+	if (!busiest) {
+		schedstat_inc(sd, lb_nobusyq[idle]);
 		goto out_balanced;
+	}
+
 	/*
 	 * This should be "impossible", but since load
 	 * balancing is inherently racy and statistical,
@@ -1698,6 +2083,8 @@
 		goto out_balanced;
 	}
 
+	schedstat_add(sd, lb_imbalance[idle], imbalance);
+
 	nr_moved = 0;
 	if (busiest->nr_running > 1) {
 		/*
@@ -1714,6 +2101,7 @@
 	spin_unlock(&this_rq->lock);
 
 	if (!nr_moved) {
+		schedstat_inc(sd, lb_failed[idle]);
 		sd->nr_balance_failed++;
 
 		if (unlikely(sd->nr_balance_failed > sd->cache_nice_tries+2)) {
@@ -1768,19 +2156,27 @@
 	unsigned long imbalance;
 	int nr_moved = 0;
 
+	schedstat_inc(sd, lb_cnt[NEWLY_IDLE]);
 	group = find_busiest_group(sd, this_cpu, &imbalance, NEWLY_IDLE);
-	if (!group)
+	if (!group) {
+		schedstat_inc(sd, lb_nobusyg[NEWLY_IDLE]);
 		goto out;
+	}
 
 	busiest = find_busiest_queue(group);
-	if (!busiest || busiest == this_rq)
+	if (!busiest || busiest == this_rq) {
+		schedstat_inc(sd, lb_nobusyq[NEWLY_IDLE]);
 		goto out;
+	}
 
 	/* Attempt to move tasks */
 	double_lock_balance(this_rq, busiest);
 
+	schedstat_add(sd, lb_imbalance[NEWLY_IDLE], imbalance);
 	nr_moved = move_tasks(this_rq, this_cpu, busiest,
 					imbalance, sd, NEWLY_IDLE);
+	if (!nr_moved)
+		schedstat_inc(sd, lb_failed[NEWLY_IDLE]);
 
 	spin_unlock(&busiest->lock);
 
@@ -1820,40 +2216,39 @@
 	struct sched_group *group, *busy_group;
 	int i;
 
+	schedstat_inc(busiest, alb_cnt);
 	if (busiest->nr_running <= 1)
 		return;
 
 	for_each_domain(busiest_cpu, sd)
 		if (cpu_isset(busiest->push_cpu, sd->span))
 			break;
-	if (!sd) {
-		WARN_ON(1);
+	if (!sd)
 		return;
-	}
 
- 	group = sd->groups;
+	group = sd->groups;
 	while (!cpu_isset(busiest_cpu, group->cpumask))
- 		group = group->next;
- 	busy_group = group;
+		group = group->next;
+	busy_group = group;
 
- 	group = sd->groups;
- 	do {
+	group = sd->groups;
+	do {
 		cpumask_t tmp;
 		runqueue_t *rq;
 		int push_cpu = 0;
 
- 		if (group == busy_group)
- 			goto next_group;
+		if (group == busy_group)
+			goto next_group;
 
 		cpus_and(tmp, group->cpumask, cpu_online_map);
 		if (!cpus_weight(tmp))
 			goto next_group;
 
- 		for_each_cpu_mask(i, tmp) {
+		for_each_cpu_mask(i, tmp) {
 			if (!idle_cpu(i))
 				goto next_group;
- 			push_cpu = i;
- 		}
+			push_cpu = i;
+		}
 
 		rq = cpu_rq(push_cpu);
 
@@ -1866,7 +2261,12 @@
 		if (unlikely(busiest == rq))
 			goto next_group;
 		double_lock_balance(busiest, rq);
-		move_tasks(rq, push_cpu, busiest, 1, sd, IDLE);
+		if (move_tasks(rq, push_cpu, busiest, 1, sd, IDLE)) {
+			schedstat_inc(busiest, alb_lost);
+			schedstat_inc(rq, alb_gained);
+		} else {
+			schedstat_inc(busiest, alb_failed);
+		}
 		spin_unlock(&rq->lock);
 next_group:
 		group = group->next;
@@ -1938,17 +2338,20 @@
 
 static inline int wake_priority_sleeper(runqueue_t *rq)
 {
+	int ret = 0;
 #ifdef CONFIG_SCHED_SMT
+	spin_lock(&rq->lock);
 	/*
 	 * If an SMT sibling task has been put to sleep for priority
 	 * reasons reschedule the idle task to see if it can now run.
 	 */
 	if (rq->nr_running) {
 		resched_task(rq->idle);
-		return 1;
+		ret = 1;
 	}
+	spin_unlock(&rq->lock);
 #endif
-	return 0;
+	return ret;
 }
 
 DEFINE_PER_CPU(struct kernel_stat, kstat);
@@ -2028,7 +2431,7 @@
 	 * timeslice. This makes it possible for interactive tasks
 	 * to use up their timeslices at their highest priority levels.
 	 */
-	if (unlikely(rt_task(p))) {
+	if (rt_task(p)) {
 		/*
 		 * RR tasks need a special form of timeslice management.
 		 * FIFO tasks have no timeslices.
@@ -2094,23 +2497,34 @@
 }
 
 #ifdef CONFIG_SCHED_SMT
-static inline void wake_sleeping_dependent(int cpu, runqueue_t *rq)
+static inline void wake_sleeping_dependent(int this_cpu, runqueue_t *this_rq)
 {
-	int i;
-	struct sched_domain *sd = rq->sd;
+	struct sched_domain *sd = this_rq->sd;
 	cpumask_t sibling_map;
+	int i;
 
 	if (!(sd->flags & SD_SHARE_CPUPOWER))
 		return;
 
+	/*
+	 * Unlock the current runqueue because we have to lock in
+	 * CPU order to avoid deadlocks. Caller knows that we might
+	 * unlock. We keep IRQs disabled.
+	 */
+	spin_unlock(&this_rq->lock);
+
 	cpus_and(sibling_map, sd->span, cpu_online_map);
-	for_each_cpu_mask(i, sibling_map) {
-		runqueue_t *smt_rq;
 
-		if (i == cpu)
-			continue;
+	for_each_cpu_mask(i, sibling_map)
+		spin_lock(&cpu_rq(i)->lock);
+	/*
+	 * We clear this CPU from the mask. This both simplifies the
+	 * inner loop and keps this_rq locked when we exit:
+	 */
+	cpu_clear(this_cpu, sibling_map);
 
-		smt_rq = cpu_rq(i);
+	for_each_cpu_mask(i, sibling_map) {
+		runqueue_t *smt_rq = cpu_rq(i);
 
 		/*
 		 * If an SMT sibling task is sleeping due to priority
@@ -2119,27 +2533,53 @@
 		if (smt_rq->curr == smt_rq->idle && smt_rq->nr_running)
 			resched_task(smt_rq->idle);
 	}
+
+	for_each_cpu_mask(i, sibling_map)
+		spin_unlock(&cpu_rq(i)->lock);
+	/*
+	 * We exit with this_cpu's rq still held and IRQs
+	 * still disabled:
+	 */
 }
 
-static inline int dependent_sleeper(int cpu, runqueue_t *rq, task_t *p)
+static inline int dependent_sleeper(int this_cpu, runqueue_t *this_rq)
 {
-	struct sched_domain *sd = rq->sd;
+	struct sched_domain *sd = this_rq->sd;
 	cpumask_t sibling_map;
+	prio_array_t *array;
 	int ret = 0, i;
+	task_t *p;
 
 	if (!(sd->flags & SD_SHARE_CPUPOWER))
 		return 0;
 
+	/*
+	 * The same locking rules and details apply as for
+	 * wake_sleeping_dependent():
+	 */
+	spin_unlock(&this_rq->lock);
 	cpus_and(sibling_map, sd->span, cpu_online_map);
-	for_each_cpu_mask(i, sibling_map) {
-		runqueue_t *smt_rq;
-		task_t *smt_curr;
+	for_each_cpu_mask(i, sibling_map)
+		spin_lock(&cpu_rq(i)->lock);
+	cpu_clear(this_cpu, sibling_map);
 
-		if (i == cpu)
-			continue;
+	/*
+	 * Establish next task to be run - it might have gone away because
+	 * we released the runqueue lock above:
+	 */
+	if (!this_rq->nr_running)
+		goto out_unlock;
+	array = this_rq->active;
+	if (!array->nr_active)
+		array = this_rq->expired;
+	BUG_ON(!array->nr_active);
+
+	p = list_entry(array->queue[sched_find_first_bit(array->bitmap)].next,
+		task_t, run_list);
 
-		smt_rq = cpu_rq(i);
-		smt_curr = smt_rq->curr;
+	for_each_cpu_mask(i, sibling_map) {
+		runqueue_t *smt_rq = cpu_rq(i);
+		task_t *smt_curr = smt_rq->curr;
 
 		/*
 		 * If a user task with lower static priority than the
@@ -2165,14 +2605,17 @@
 			(smt_curr == smt_rq->idle && smt_rq->nr_running))
 				resched_task(smt_curr);
 	}
+out_unlock:
+	for_each_cpu_mask(i, sibling_map)
+		spin_unlock(&cpu_rq(i)->lock);
 	return ret;
 }
 #else
-static inline void wake_sleeping_dependent(int cpu, runqueue_t *rq)
+static inline void wake_sleeping_dependent(int this_cpu, runqueue_t *this_rq)
 {
 }
 
-static inline int dependent_sleeper(int cpu, runqueue_t *rq, task_t *p)
+static inline int dependent_sleeper(int this_cpu, runqueue_t *this_rq)
 {
 	return 0;
 }
@@ -2209,7 +2652,17 @@
 	prev = current;
 	rq = this_rq();
 
+	/*
+	 * The idle thread is not allowed to schedule!
+	 * Remove this check after it has been exercised a bit.
+	 */
+	if (unlikely(current == rq->idle) && current->state != TASK_RUNNING) {
+		printk(KERN_ERR "bad: scheduling from the idle thread!\n");
+		dump_stack();
+	}
+
 	release_kernel_lock(prev);
+	schedstat_inc(rq, sched_cnt);
 	now = sched_clock();
 	if (likely(now - prev->timestamp < NS_MAX_SLEEP_AVG))
 		run_time = now - prev->timestamp;
@@ -2242,13 +2695,33 @@
 
 	cpu = smp_processor_id();
 	if (unlikely(!rq->nr_running)) {
+go_idle:
 		idle_balance(cpu, rq);
 		if (!rq->nr_running) {
 			next = rq->idle;
 			rq->expired_timestamp = 0;
 			wake_sleeping_dependent(cpu, rq);
+			/*
+			 * wake_sleeping_dependent() might have released
+			 * the runqueue, so break out if we got new
+			 * tasks meanwhile:
+			 */
+			if (!rq->nr_running)
+				goto switch_tasks;
+		}
+	} else {
+		if (dependent_sleeper(cpu, rq)) {
+			schedstat_inc(rq, sched_goidle);
+			next = rq->idle;
 			goto switch_tasks;
 		}
+		/*
+		 * dependent_sleeper() releases and reacquires the runqueue
+		 * lock, hence go into the idle loop if the rq went
+		 * empty meanwhile:
+		 */
+		if (unlikely(!rq->nr_running))
+			goto go_idle;
 	}
 
 	array = rq->active;
@@ -2256,22 +2729,19 @@
 		/*
 		 * Switch the active and expired arrays.
 		 */
+		schedstat_inc(rq, sched_switch);
 		rq->active = rq->expired;
 		rq->expired = array;
 		array = rq->active;
 		rq->expired_timestamp = 0;
 		rq->best_expired_prio = MAX_PRIO;
-	}
+	} else
+		schedstat_inc(rq, sched_noswitch);
 
 	idx = sched_find_first_bit(array->bitmap);
 	queue = array->queue + idx;
 	next = list_entry(queue->next, task_t, run_list);
 
-	if (dependent_sleeper(cpu, rq, next)) {
-		next = rq->idle;
-		goto switch_tasks;
-	}
-
 	if (!rt_task(next) && next->activated > 0) {
 		unsigned long long delta = now - next->timestamp;
 
@@ -2287,7 +2757,7 @@
 switch_tasks:
 	prefetch(next);
 	clear_tsk_need_resched(prev);
-	RCU_qsctr(task_cpu(prev))++;
+	rcu_qsctr_inc(task_cpu(prev));
 
 	prev->sleep_avg -= run_time;
 	if ((long)prev->sleep_avg <= 0) {
@@ -2295,8 +2765,9 @@
 		if (!(HIGH_CREDIT(prev) || LOW_CREDIT(prev)))
 			prev->interactive_credit--;
 	}
-	prev->timestamp = now;
+	prev->timestamp = prev->last_ran = now;
 
+	sched_info_switch(prev, next);
 	if (likely(prev != next)) {
 		next->timestamp = now;
 		rq->nr_switches++;
@@ -2313,7 +2784,7 @@
 
 	reacquire_kernel_lock(current);
 	preempt_enable_no_resched();
-	if (test_thread_flag(TIF_NEED_RESCHED))
+	if (unlikely(test_thread_flag(TIF_NEED_RESCHED)))
 		goto need_resched;
 }
 
@@ -2751,6 +3222,7 @@
 				policy != SCHED_NORMAL)
 			goto out_unlock;
 	}
+	profile_hit(SCHED_PROFILING, __builtin_return_address(0));
 
 	/*
 	 * Valid priorities for SCHED_FIFO and SCHED_RR are
@@ -2891,24 +3363,10 @@
 	return retval;
 }
 
-/**
- * sys_sched_setaffinity - set the cpu affinity of a process
- * @pid: pid of the process
- * @len: length in bytes of the bitmask pointed to by user_mask_ptr
- * @user_mask_ptr: user-space pointer to the new cpu mask
- */
-asmlinkage long sys_sched_setaffinity(pid_t pid, unsigned int len,
-				      unsigned long __user *user_mask_ptr)
+long sched_setaffinity(pid_t pid, cpumask_t new_mask)
 {
-	cpumask_t new_mask;
-	int retval;
 	task_t *p;
-
-	if (len < sizeof(new_mask))
-		return -EINVAL;
-
-	if (copy_from_user(&new_mask, user_mask_ptr, sizeof(new_mask)))
-		return -EFAULT;
+	int retval;
 
 	lock_cpu_hotplug();
 	read_lock(&tasklist_lock);
@@ -2941,6 +3399,36 @@
 	return retval;
 }
 
+static int get_user_cpu_mask(unsigned long __user *user_mask_ptr, unsigned len,
+			     cpumask_t *new_mask)
+{
+	if (len < sizeof(cpumask_t)) {
+		memset(new_mask, 0, sizeof(cpumask_t));
+	} else if (len > sizeof(cpumask_t)) {
+		len = sizeof(cpumask_t);
+	}
+	return copy_from_user(new_mask, user_mask_ptr, len) ? -EFAULT : 0;
+}
+
+/**
+ * sys_sched_setaffinity - set the cpu affinity of a process
+ * @pid: pid of the process
+ * @len: length in bytes of the bitmask pointed to by user_mask_ptr
+ * @user_mask_ptr: user-space pointer to the new cpu mask
+ */
+asmlinkage long sys_sched_setaffinity(pid_t pid, unsigned int len,
+				      unsigned long __user *user_mask_ptr)
+{
+	cpumask_t new_mask;
+	int retval;
+
+	retval = get_user_cpu_mask(user_mask_ptr, len, &new_mask);
+	if (retval)
+		return retval;
+
+	return sched_setaffinity(pid, new_mask);
+}
+
 /*
  * Represents all cpu's present in the system
  * In systems capable of hotplug, this map could dynamically grow
@@ -2956,24 +3444,11 @@
 cpumask_t cpu_possible_map = CPU_MASK_ALL;
 #endif
 
-/**
- * sys_sched_getaffinity - get the cpu affinity of a process
- * @pid: pid of the process
- * @len: length in bytes of the bitmask pointed to by user_mask_ptr
- * @user_mask_ptr: user-space pointer to hold the current cpu mask
- */
-asmlinkage long sys_sched_getaffinity(pid_t pid, unsigned int len,
-				      unsigned long __user *user_mask_ptr)
+long sched_getaffinity(pid_t pid, cpumask_t *mask)
 {
-	unsigned int real_len;
-	cpumask_t mask;
 	int retval;
 	task_t *p;
 
-	real_len = sizeof(mask);
-	if (len < real_len)
-		return -EINVAL;
-
 	lock_cpu_hotplug();
 	read_lock(&tasklist_lock);
 
@@ -2983,16 +3458,40 @@
 		goto out_unlock;
 
 	retval = 0;
-	cpus_and(mask, p->cpus_allowed, cpu_possible_map);
+	cpus_and(*mask, p->cpus_allowed, cpu_possible_map);
 
 out_unlock:
 	read_unlock(&tasklist_lock);
 	unlock_cpu_hotplug();
 	if (retval)
 		return retval;
-	if (copy_to_user(user_mask_ptr, &mask, real_len))
+
+	return 0;
+}
+
+/**
+ * sys_sched_getaffinity - get the cpu affinity of a process
+ * @pid: pid of the process
+ * @len: length in bytes of the bitmask pointed to by user_mask_ptr
+ * @user_mask_ptr: user-space pointer to hold the current cpu mask
+ */
+asmlinkage long sys_sched_getaffinity(pid_t pid, unsigned int len,
+				      unsigned long __user *user_mask_ptr)
+{
+	int ret;
+	cpumask_t mask;
+
+	if (len < sizeof(cpumask_t))
+		return -EINVAL;
+
+	ret = sched_getaffinity(pid, &mask);
+	if (ret < 0)
+		return ret;
+
+	if (copy_to_user(user_mask_ptr, &mask, sizeof(cpumask_t)))
 		return -EFAULT;
-	return real_len;
+
+	return sizeof(cpumask_t);
 }
 
 /**
@@ -3008,6 +3507,7 @@
 	prio_array_t *array = current->array;
 	prio_array_t *target = rq->expired;
 
+	schedstat_inc(rq, yld_cnt);
 	/*
 	 * We implement yielding by moving the task into the expired
 	 * queue.
@@ -3015,9 +3515,16 @@
 	 * (special rule: RT tasks will just roundrobin in the active
 	 *  array.)
 	 */
-	if (unlikely(rt_task(current)))
+	if (rt_task(current))
 		target = rq->active;
 
+	if (current->array->nr_active == 1) {
+		schedstat_inc(rq, yld_act_empty);
+		if (!rq->expired->nr_active)
+			schedstat_inc(rq, yld_both_empty);
+	} else if (!rq->expired->nr_active)
+		schedstat_inc(rq, yld_exp_empty);
+
 	dequeue_task(current, array);
 	enqueue_task(current, target);
 
@@ -3191,7 +3698,7 @@
 	task_t *relative;
 	unsigned state;
 	unsigned long free = 0;
-	static const char *stat_nam[] = { "R", "S", "D", "T", "Z", "W" };
+	static const char *stat_nam[] = { "R", "S", "D", "T", "t", "Z", "X" };
 
 	printk("%-13.13s ", p->comm);
 	state = p->state ? __ffs(p->state) + 1 : 0;
@@ -3268,21 +3775,20 @@
 
 void __devinit init_idle(task_t *idle, int cpu)
 {
-	runqueue_t *idle_rq = cpu_rq(cpu), *rq = cpu_rq(task_cpu(idle));
+	runqueue_t *rq = cpu_rq(cpu);
 	unsigned long flags;
 
-	local_irq_save(flags);
-	double_rq_lock(idle_rq, rq);
-
-	idle_rq->curr = idle_rq->idle = idle;
-	deactivate_task(idle, rq);
+	idle->sleep_avg = 0;
+	idle->interactive_credit = 0;
 	idle->array = NULL;
 	idle->prio = MAX_PRIO;
 	idle->state = TASK_RUNNING;
 	set_task_cpu(idle, cpu);
-	double_rq_unlock(idle_rq, rq);
+
+	spin_lock_irqsave(&rq->lock, flags);
+	rq->curr = rq->idle = idle;
 	set_tsk_need_resched(idle);
-	local_irq_restore(flags);
+	spin_unlock_irqrestore(&rq->lock, flags);
 
 	/* Set the preempt count _outside_ the spinlocks! */
 #ifdef CONFIG_PREEMPT
@@ -3364,7 +3870,7 @@
  * Move (not current) task off this cpu, onto dest cpu.  We're doing
  * this because either it can't run here any more (set_cpus_allowed()
  * away from this CPU, or CPU going down), or because we're
- * attempting to rebalance this task on exec (sched_balance_exec).
+ * attempting to rebalance this task on exec (sched_exec).
  *
  * So we race with normal scheduler movements, but that's OK, as long
  * as the task is no longer on this CPU.
@@ -3376,7 +3882,7 @@
 	if (unlikely(cpu_is_offline(dest_cpu)))
 		return;
 
-	rq_src  = cpu_rq(src_cpu);
+	rq_src = cpu_rq(src_cpu);
 	rq_dest = cpu_rq(dest_cpu);
 
 	double_rq_lock(rq_src, rq_dest);
@@ -3481,49 +3987,52 @@
 }
 
 #ifdef CONFIG_HOTPLUG_CPU
-/* migrate_all_tasks - function to migrate all tasks from the dead cpu.  */
-static void migrate_all_tasks(int src_cpu)
+/* Figure out where task on dead CPU should go, use force if neccessary. */
+static void move_task_off_dead_cpu(int dead_cpu, struct task_struct *tsk)
 {
-	struct task_struct *tsk, *t;
 	int dest_cpu;
-	unsigned int node;
+	cpumask_t mask;
 
-	write_lock_irq(&tasklist_lock);
+	/* On same node? */
+	mask = node_to_cpumask(cpu_to_node(dead_cpu));
+	cpus_and(mask, mask, tsk->cpus_allowed);
+	dest_cpu = any_online_cpu(mask);
+
+	/* On any allowed CPU? */
+	if (dest_cpu == NR_CPUS)
+		dest_cpu = any_online_cpu(tsk->cpus_allowed);
+
+	/* No more Mr. Nice Guy. */
+	if (dest_cpu == NR_CPUS) {
+		cpus_setall(tsk->cpus_allowed);
+		dest_cpu = any_online_cpu(tsk->cpus_allowed);
 
-	/* watch out for per node tasks, let's stay on this node */
-	node = cpu_to_node(src_cpu);
+		/*
+		 * Don't tell them about moving exiting tasks or
+		 * kernel threads (both mm NULL), since they never
+		 * leave kernel.
+		 */
+		if (tsk->mm && printk_ratelimit())
+			printk(KERN_INFO "process %d (%s) no "
+			       "longer affine to cpu%d\n",
+			       tsk->pid, tsk->comm, dead_cpu);
+	}
+	__migrate_task(tsk, dead_cpu, dest_cpu);
+}
+
+/* Run through task list and migrate tasks from the dead cpu. */
+static void migrate_live_tasks(int src_cpu)
+{
+	struct task_struct *tsk, *t;
+
+	write_lock_irq(&tasklist_lock);
 
 	do_each_thread(t, tsk) {
-		cpumask_t mask;
 		if (tsk == current)
 			continue;
 
-		if (task_cpu(tsk) != src_cpu)
-			continue;
-
-		/* Figure out where this task should go (attempting to
-		 * keep it on-node), and check if it can be migrated
-		 * as-is.  NOTE that kernel threads bound to more than
-		 * one online cpu will be migrated. */
-		mask = node_to_cpumask(node);
-		cpus_and(mask, mask, tsk->cpus_allowed);
-		dest_cpu = any_online_cpu(mask);
-		if (dest_cpu == NR_CPUS)
-			dest_cpu = any_online_cpu(tsk->cpus_allowed);
-		if (dest_cpu == NR_CPUS) {
-			cpus_setall(tsk->cpus_allowed);
-			dest_cpu = any_online_cpu(tsk->cpus_allowed);
-
-			/* Don't tell them about moving exiting tasks
-			   or kernel threads (both mm NULL), since
-			   they never leave kernel. */
-			if (tsk->mm && printk_ratelimit())
-				printk(KERN_INFO "process %d (%s) no "
-				       "longer affine to cpu%d\n",
-				       tsk->pid, tsk->comm, src_cpu);
-		}
-
-		__migrate_task(tsk, src_cpu, dest_cpu);
+		if (task_cpu(tsk) == src_cpu)
+			move_task_off_dead_cpu(src_cpu, tsk);
 	} while_each_thread(t, tsk);
 
 	write_unlock_irq(&tasklist_lock);
@@ -3554,6 +4063,47 @@
 
 	spin_unlock_irqrestore(&rq->lock, flags);
 }
+
+static void migrate_dead(unsigned int dead_cpu, task_t *tsk)
+{
+	struct runqueue *rq = cpu_rq(dead_cpu);
+
+	/* Must be exiting, otherwise would be on tasklist. */
+	BUG_ON(tsk->state != TASK_ZOMBIE && tsk->state != TASK_DEAD);
+
+	/* Cannot have done final schedule yet: would have vanished. */
+	BUG_ON(tsk->flags & PF_DEAD);
+
+	get_task_struct(tsk);
+
+	/*
+	 * Drop lock around migration; if someone else moves it,
+	 * that's OK.  No task can be added to this CPU, so iteration is
+	 * fine.
+	 */
+	spin_unlock_irq(&rq->lock);
+	move_task_off_dead_cpu(dead_cpu, tsk);
+	spin_lock_irq(&rq->lock);
+
+	put_task_struct(tsk);
+}
+
+/* release_task() removes task from tasklist, so we won't find dead tasks. */
+static void migrate_dead_tasks(unsigned int dead_cpu)
+{
+	unsigned arr, i;
+	struct runqueue *rq = cpu_rq(dead_cpu);
+
+	for (arr = 0; arr < 2; arr++) {
+		for (i = 0; i < MAX_PRIO; i++) {
+			struct list_head *list = &rq->arrays[arr].queue[i];
+			while (!list_empty(list))
+				migrate_dead(dead_cpu,
+					     list_entry(list->next, task_t,
+							run_list));
+		}
+	}
+}
 #endif /* CONFIG_HOTPLUG_CPU */
 
 /*
@@ -3593,7 +4143,7 @@
 		cpu_rq(cpu)->migration_thread = NULL;
 		break;
 	case CPU_DEAD:
-		migrate_all_tasks(cpu);
+		migrate_live_tasks(cpu);
 		rq = cpu_rq(cpu);
 		kthread_stop(rq->migration_thread);
 		rq->migration_thread = NULL;
@@ -3602,8 +4152,9 @@
 		deactivate_task(rq->idle, rq);
 		rq->idle->static_prio = MAX_PRIO;
 		__setscheduler(rq->idle, SCHED_NORMAL, 0);
+		migrate_dead_tasks(cpu);
 		task_rq_unlock(rq, &flags);
- 		BUG_ON(rq->nr_running != 0);
+		BUG_ON(rq->nr_running != 0);
 
 		/* No need to migrate the tasks: it was best-effort if
 		 * they didn't do lock_cpu_hotplug().  Just wake up
@@ -3618,7 +4169,7 @@
 			complete(&req->done);
 		}
 		spin_unlock_irq(&rq->lock);
- 		break;
+		break;
 #endif
 	}
 	return NOTIFY_OK;
@@ -3660,7 +4211,7 @@
 
 #ifdef CONFIG_SMP
 /* Attach the domain 'sd' to 'cpu' as its base domain */
-void cpu_attach_domain(struct sched_domain *sd, int cpu)
+static void cpu_attach_domain(struct sched_domain *sd, int cpu)
 {
 	migration_req_t req;
 	unsigned long flags;
@@ -3691,124 +4242,343 @@
 	unlock_cpu_hotplug();
 }
 
-#ifdef ARCH_HAS_SCHED_DOMAIN
-extern void __init arch_init_sched_domains(void);
-#else
-static struct sched_group sched_group_cpus[NR_CPUS];
+/*
+ * To enable disjoint top-level NUMA domains, define SD_NODES_PER_DOMAIN
+ * in arch code. That defines the number of nearby nodes in a node's top
+ * level scheduling domain.
+ */
+#if defined(CONFIG_NUMA) && defined(SD_NODES_PER_DOMAIN)
+/**
+ * find_next_best_node - find the next node to include in a sched_domain
+ * @node: node whose sched_domain we're building
+ * @used_nodes: nodes already in the sched_domain
+ *
+ * Find the next node to include in a given scheduling domain.  Simply
+ * finds the closest node not already in the @used_nodes map.
+ *
+ * Should use nodemask_t.
+ */
+static int __init find_next_best_node(int node, unsigned long *used_nodes)
+{
+	int i, n, val, min_val, best_node = 0;
+
+	min_val = INT_MAX;
+
+	for (i = 0; i < numnodes; i++) {
+		/* Start at @node */
+		n = (node + i) % numnodes;
+
+		/* Skip already used nodes */
+		if (test_bit(n, used_nodes))
+			continue;
+
+		/* Simple min distance search */
+		val = node_distance(node, i);
+
+		if (val < min_val) {
+			min_val = val;
+			best_node = n;
+		}
+	}
+
+	set_bit(best_node, used_nodes);
+	return best_node;
+}
+
+/**
+ * sched_domain_node_span - get a cpumask for a node's sched_domain
+ * @node: node whose cpumask we're constructing
+ * @size: number of nodes to include in this span
+ *
+ * Given a node, construct a good cpumask for its sched_domain to span.  It
+ * should be one that prevents unnecessary balancing, but also spreads tasks
+ * out optimally.
+ */
+cpumask_t __init sched_domain_node_span(int node)
+{
+	int i;
+	cpumask_t span;
+	DECLARE_BITMAP(used_nodes, MAX_NUMNODES);
+
+	cpus_clear(span);
+	bitmap_zero(used_nodes, MAX_NUMNODES);
+
+	for (i = 0; i < SD_NODES_PER_DOMAIN; i++) {
+		int next_node = find_next_best_node(node, used_nodes);
+		cpumask_t  nodemask;
+
+		nodemask = node_to_cpumask(next_node);
+		cpus_or(span, span, nodemask);
+	}
+
+	return span;
+}
+#else /* CONFIG_NUMA && SD_NODES_PER_DOMAIN */
+cpumask_t __init sched_domain_node_span(int node)
+{
+	return cpu_possible_map;
+}
+#endif /* CONFIG_NUMA && SD_NODES_PER_DOMAIN */
+
+#ifdef CONFIG_SCHED_SMT
 static DEFINE_PER_CPU(struct sched_domain, cpu_domains);
+static struct sched_group sched_group_cpus[NR_CPUS];
+__init static int cpu_to_cpu_group(int cpu)
+{
+	return cpu;
+}
+#endif
+
+static DEFINE_PER_CPU(struct sched_domain, phys_domains);
+static struct sched_group sched_group_phys[NR_CPUS];
+__init static int cpu_to_phys_group(int cpu)
+{
+#ifdef CONFIG_SCHED_SMT
+	return first_cpu(cpu_sibling_map[cpu]);
+#else
+	return cpu;
+#endif
+}
+
 #ifdef CONFIG_NUMA
-static struct sched_group sched_group_nodes[MAX_NUMNODES];
+
 static DEFINE_PER_CPU(struct sched_domain, node_domains);
-static void __init arch_init_sched_domains(void)
+static struct sched_group sched_group_nodes[MAX_NUMNODES];
+__init static int cpu_to_node_group(int cpu)
 {
-	int i;
-	struct sched_group *first_node = NULL, *last_node = NULL;
+	return cpu_to_node(cpu);
+}
+#endif
 
-	/* Set up domains */
-	for_each_cpu(i) {
-		int node = cpu_to_node(i);
-		cpumask_t nodemask = node_to_cpumask(node);
-		struct sched_domain *node_sd = &per_cpu(node_domains, i);
-		struct sched_domain *cpu_sd = &per_cpu(cpu_domains, i);
-
-		*node_sd = SD_NODE_INIT;
-		node_sd->span = cpu_possible_map;
-		node_sd->groups = &sched_group_nodes[cpu_to_node(i)];
-
-		*cpu_sd = SD_CPU_INIT;
-		cpus_and(cpu_sd->span, nodemask, cpu_possible_map);
-		cpu_sd->groups = &sched_group_cpus[i];
-		cpu_sd->parent = node_sd;
-	}
+/* Groups for isolated scheduling domains */
+static struct sched_group sched_group_isolated[NR_CPUS];
 
-	/* Set up groups */
-	for (i = 0; i < MAX_NUMNODES; i++) {
-		cpumask_t tmp = node_to_cpumask(i);
-		cpumask_t nodemask;
-		struct sched_group *first_cpu = NULL, *last_cpu = NULL;
-		struct sched_group *node = &sched_group_nodes[i];
-		int j;
+/* cpus with isolated domains */
+cpumask_t __initdata cpu_isolated_map = CPU_MASK_NONE;
 
-		cpus_and(nodemask, tmp, cpu_possible_map);
+__init static int cpu_to_isolated_group(int cpu)
+{
+	return cpu;
+}
 
-		if (cpus_empty(nodemask))
-			continue;
+/* Setup the mask of cpus configured for isolated domains */
+static int __init isolated_cpu_setup(char *str)
+{
+	int ints[NR_CPUS], i;
 
-		node->cpumask = nodemask;
-		node->cpu_power = SCHED_LOAD_SCALE * cpus_weight(node->cpumask);
+	str = get_options(str, ARRAY_SIZE(ints), ints);
+	cpus_clear(cpu_isolated_map);
+	for (i = 1; i <= ints[0]; i++)
+		cpu_set(ints[i], cpu_isolated_map);
+	return 1;
+}
 
-		for_each_cpu_mask(j, node->cpumask) {
-			struct sched_group *cpu = &sched_group_cpus[j];
+__setup ("isolcpus=", isolated_cpu_setup);
 
-			cpus_clear(cpu->cpumask);
-			cpu_set(j, cpu->cpumask);
-			cpu->cpu_power = SCHED_LOAD_SCALE;
+/*
+ * init_sched_build_groups takes an array of groups, the cpumask we wish
+ * to span, and a pointer to a function which identifies what group a CPU
+ * belongs to. The return value of group_fn must be a valid index into the
+ * groups[] array, and must be >= 0 and < NR_CPUS (due to the fact that we
+ * keep track of groups covered with a cpumask_t).
+ *
+ * init_sched_build_groups will build a circular linked list of the groups
+ * covered by the given span, and will set each group's ->cpumask correctly,
+ * and ->cpu_power to 0.
+ */
+__init static void init_sched_build_groups(struct sched_group groups[],
+			cpumask_t span, int (*group_fn)(int cpu))
+{
+	struct sched_group *first = NULL, *last = NULL;
+	cpumask_t covered = CPU_MASK_NONE;
+	int i;
 
-			if (!first_cpu)
-				first_cpu = cpu;
-			if (last_cpu)
-				last_cpu->next = cpu;
-			last_cpu = cpu;
-		}
-		last_cpu->next = first_cpu;
+	for_each_cpu_mask(i, span) {
+		int group = group_fn(i);
+		struct sched_group *sg = &groups[group];
+		int j;
 
-		if (!first_node)
-			first_node = node;
-		if (last_node)
-			last_node->next = node;
-		last_node = node;
-	}
-	last_node->next = first_node;
+		if (cpu_isset(i, covered))
+			continue;
 
-	mb();
-	for_each_cpu(i) {
-		struct sched_domain *cpu_sd = &per_cpu(cpu_domains, i);
-		cpu_attach_domain(cpu_sd, i);
+		sg->cpumask = CPU_MASK_NONE;
+		sg->cpu_power = 0;
+
+		for_each_cpu_mask(j, span) {
+			if (group_fn(j) != group)
+				continue;
+
+			cpu_set(j, covered);
+			cpu_set(j, sg->cpumask);
+		}
+		if (!first)
+			first = sg;
+		if (last)
+			last->next = sg;
+		last = sg;
 	}
+	last->next = first;
 }
 
-#else /* !CONFIG_NUMA */
-static void __init arch_init_sched_domains(void)
+__init static void arch_init_sched_domains(void)
 {
 	int i;
-	struct sched_group *first_cpu = NULL, *last_cpu = NULL;
+	cpumask_t cpu_default_map;
+
+	/*
+	 * Setup mask for cpus without special case scheduling requirements.
+	 * For now this just excludes isolated cpus, but could be used to
+	 * exclude other special cases in the future.
+	 */
+	cpus_complement(cpu_default_map, cpu_isolated_map);
+	cpus_and(cpu_default_map, cpu_default_map, cpu_possible_map);
 
 	/* Set up domains */
 	for_each_cpu(i) {
-		struct sched_domain *cpu_sd = &per_cpu(cpu_domains, i);
+		int group;
+		struct sched_domain *sd = NULL, *p;
+		cpumask_t nodemask = node_to_cpumask(cpu_to_node(i));
+
+		cpus_and(nodemask, nodemask, cpu_default_map);
+
+		/*
+		 * Set up isolated domains.
+		 * Unlike those of other cpus, the domains and groups are
+		 * single level, and span a single cpu.
+		 */
+		if (cpu_isset(i, cpu_isolated_map)) {
+#ifdef CONFIG_SCHED_SMT
+			sd = &per_cpu(cpu_domains, i);
+#else
+			sd = &per_cpu(phys_domains, i);
+#endif
+			group = cpu_to_isolated_group(i);
+			*sd = SD_CPU_INIT;
+			cpu_set(i, sd->span);
+			sd->balance_interval = INT_MAX;	/* Don't balance */
+			sd->flags = 0;			/* Avoid WAKE_ */
+			sd->groups = &sched_group_isolated[group];
+			printk(KERN_INFO "Setting up cpu %d isolated.\n", i);
+			/* Single level, so continue with next cpu */
+			continue;
+		}
 
-		*cpu_sd = SD_CPU_INIT;
-		cpu_sd->span = cpu_possible_map;
-		cpu_sd->groups = &sched_group_cpus[i];
+#ifdef CONFIG_NUMA
+		sd = &per_cpu(node_domains, i);
+		group = cpu_to_node_group(i);
+		*sd = SD_NODE_INIT;
+		/* FIXME: should be multilevel, in arch code */
+		sd->span = sched_domain_node_span(i);
+		cpus_and(sd->span, sd->span, cpu_default_map);
+		sd->groups = &sched_group_nodes[group];
+#endif
+
+		p = sd;
+		sd = &per_cpu(phys_domains, i);
+		group = cpu_to_phys_group(i);
+		*sd = SD_CPU_INIT;
+#ifdef CONFIG_NUMA
+		sd->span = nodemask;
+#else
+		sd->span = cpu_possible_map;
+#endif
+		sd->parent = p;
+		sd->groups = &sched_group_phys[group];
+
+#ifdef CONFIG_SCHED_SMT
+		p = sd;
+		sd = &per_cpu(cpu_domains, i);
+		group = cpu_to_cpu_group(i);
+		*sd = SD_SIBLING_INIT;
+		sd->span = cpu_sibling_map[i];
+		cpus_and(sd->span, sd->span, cpu_default_map);
+		sd->parent = p;
+		sd->groups = &sched_group_cpus[group];
+#endif
+	}
+
+#ifdef CONFIG_SCHED_SMT
+	/* Set up CPU (sibling) groups */
+	for_each_cpu(i) {
+		cpumask_t this_sibling_map = cpu_sibling_map[i];
+		cpus_and(this_sibling_map, this_sibling_map, cpu_default_map);
+		if (i != first_cpu(this_sibling_map))
+			continue;
+
+		init_sched_build_groups(sched_group_cpus, this_sibling_map,
+						&cpu_to_cpu_group);
+	}
+#endif
+
+	/* Set up isolated groups */
+	for_each_cpu_mask(i, cpu_isolated_map) {
+		cpumask_t mask;
+		cpus_clear(mask);
+		cpu_set(i, mask);
+		init_sched_build_groups(sched_group_isolated, mask,
+						&cpu_to_isolated_group);
+	}
+
+#ifdef CONFIG_NUMA
+	/* Set up physical groups */
+	for (i = 0; i < MAX_NUMNODES; i++) {
+		cpumask_t nodemask = node_to_cpumask(i);
+
+		cpus_and(nodemask, nodemask, cpu_default_map);
+		if (cpus_empty(nodemask))
+			continue;
+
+		init_sched_build_groups(sched_group_phys, nodemask,
+						&cpu_to_phys_group);
 	}
+#else
+	init_sched_build_groups(sched_group_phys, cpu_possible_map,
+							&cpu_to_phys_group);
+#endif
 
-	/* Set up CPU groups */
-	for_each_cpu_mask(i, cpu_possible_map) {
-		struct sched_group *cpu = &sched_group_cpus[i];
+#ifdef CONFIG_NUMA
+	/* Set up node groups */
+	init_sched_build_groups(sched_group_nodes, cpu_default_map,
+					&cpu_to_node_group);
+#endif
 
-		cpus_clear(cpu->cpumask);
-		cpu_set(i, cpu->cpumask);
-		cpu->cpu_power = SCHED_LOAD_SCALE;
+	/* Calculate CPU power for physical packages and nodes */
+	for_each_cpu_mask(i, cpu_default_map) {
+		int power;
+		struct sched_domain *sd;
+#ifdef CONFIG_SCHED_SMT
+		sd = &per_cpu(cpu_domains, i);
+		power = SCHED_LOAD_SCALE;
+		sd->groups->cpu_power = power;
+#endif
 
-		if (!first_cpu)
-			first_cpu = cpu;
-		if (last_cpu)
-			last_cpu->next = cpu;
-		last_cpu = cpu;
+		sd = &per_cpu(phys_domains, i);
+		power = SCHED_LOAD_SCALE + SCHED_LOAD_SCALE *
+				(cpus_weight(sd->groups->cpumask)-1) / 10;
+		sd->groups->cpu_power = power;
+
+#ifdef CONFIG_NUMA
+		if (i == first_cpu(sd->groups->cpumask)) {
+			/* Only add "power" once for each physical package. */
+			sd = &per_cpu(node_domains, i);
+			sd->groups->cpu_power += power;
+		}
+#endif
 	}
-	last_cpu->next = first_cpu;
 
-	mb(); /* domains were modified outside the lock */
+	/* Attach the domains */
 	for_each_cpu(i) {
-		struct sched_domain *cpu_sd = &per_cpu(cpu_domains, i);
-		cpu_attach_domain(cpu_sd, i);
+		struct sched_domain *sd;
+#ifdef CONFIG_SCHED_SMT
+		sd = &per_cpu(cpu_domains, i);
+#else
+		sd = &per_cpu(phys_domains, i);
+#endif
+		cpu_attach_domain(sd, i);
 	}
 }
 
-#endif /* CONFIG_NUMA */
-#endif /* ARCH_HAS_SCHED_DOMAIN */
-
-#define SCHED_DOMAIN_DEBUG
+#undef SCHED_DOMAIN_DEBUG
 #ifdef SCHED_DOMAIN_DEBUG
 void sched_domain_debug(void)
 {
@@ -3903,8 +4673,9 @@
 {
 	/* Linker adds these: start and end of __sched functions */
 	extern char __sched_text_start[], __sched_text_end[];
-	return addr >= (unsigned long)__sched_text_start
-		&& addr < (unsigned long)__sched_text_end;
+	return in_lock_functions(addr) ||
+		(addr >= (unsigned long)__sched_text_start
+		&& addr < (unsigned long)__sched_text_end);
 }
 
 void __init sched_init(void)
@@ -3959,21 +4730,20 @@
 			__set_bit(MAX_PRIO, array->bitmap);
 		}
 	}
-	/*
-	 * We have to do a little magic to get the first
-	 * thread right in SMP mode.
-	 */
-	rq = this_rq();
-	rq->curr = current;
-	rq->idle = current;
-	set_task_cpu(current, smp_processor_id());
-	wake_up_forked_process(current);
 
 	/*
 	 * The boot idle thread does lazy MMU switching as well:
 	 */
 	atomic_inc(&init_mm.mm_count);
 	enter_lazy_tlb(&init_mm, current);
+
+	/*
+	 * Make us the idle thread. Technically, schedule() should not be
+	 * called from this thread, however somewhere below it might be,
+	 * but because we are the idle thread, we just pick up running again
+	 * when this runqueue becomes "idle".
+	 */
+	init_idle(current, smp_processor_id());
 }
 
 #ifdef CONFIG_DEBUG_SPINLOCK_SLEEP
@@ -3997,49 +4767,3 @@
 }
 EXPORT_SYMBOL(__might_sleep);
 #endif
-
-
-#if defined(CONFIG_SMP) && defined(CONFIG_PREEMPT)
-/*
- * This could be a long-held lock.  If another CPU holds it for a long time,
- * and that CPU is not asked to reschedule then *this* CPU will spin on the
- * lock for a long time, even if *this* CPU is asked to reschedule.
- *
- * So what we do here, in the slow (contended) path is to spin on the lock by
- * hand while permitting preemption.
- *
- * Called inside preempt_disable().
- */
-void __sched __preempt_spin_lock(spinlock_t *lock)
-{
-	if (preempt_count() > 1) {
-		_raw_spin_lock(lock);
-		return;
-	}
-	do {
-		preempt_enable();
-		while (spin_is_locked(lock))
-			cpu_relax();
-		preempt_disable();
-	} while (!_raw_spin_trylock(lock));
-}
-
-EXPORT_SYMBOL(__preempt_spin_lock);
-
-void __sched __preempt_write_lock(rwlock_t *lock)
-{
-	if (preempt_count() > 1) {
-		_raw_write_lock(lock);
-		return;
-	}
-
-	do {
-		preempt_enable();
-		while (rwlock_is_locked(lock))
-			cpu_relax();
-		preempt_disable();
-	} while (!_raw_write_trylock(lock));
-}
-
-EXPORT_SYMBOL(__preempt_write_lock);
-#endif /* defined(CONFIG_SMP) && defined(CONFIG_PREEMPT) */
diff -Nru a/kernel/signal.c b/kernel/signal.c
--- a/kernel/signal.c	2004-10-18 14:56:28 -07:00
+++ b/kernel/signal.c	2004-10-18 14:56:28 -07:00
@@ -26,6 +26,8 @@
 #include <asm/unistd.h>
 #include <asm/siginfo.h>
 
+extern void k_getrusage(struct task_struct *, int, struct rusage *);
+
 /*
  * SLAB caches for signal bits.
  */
@@ -367,6 +369,22 @@
 		if (tsk == sig->curr_target)
 			sig->curr_target = next_thread(tsk);
 		tsk->signal = NULL;
+		/*
+		 * Accumulate here the counters for all threads but the
+		 * group leader as they die, so they can be added into
+		 * the process-wide totals when those are taken.
+		 * The group leader stays around as a zombie as long
+		 * as there are other threads.  When it gets reaped,
+		 * the exit.c code will add its counts into these totals.
+		 * We won't ever get here for the group leader, since it
+		 * will have been the last reference on the signal_struct.
+		 */
+		sig->utime += tsk->utime;
+		sig->stime += tsk->stime;
+		sig->min_flt += tsk->min_flt;
+		sig->maj_flt += tsk->maj_flt;
+		sig->nvcsw += tsk->nvcsw;
+		sig->nivcsw += tsk->nivcsw;
 		spin_unlock(&sighand->siglock);
 		sig = NULL;	/* Marker for below.  */
 	}
@@ -618,7 +636,8 @@
 
 /* forward decl */
 static void do_notify_parent_cldstop(struct task_struct *tsk,
-				     struct task_struct *parent);
+				     struct task_struct *parent,
+				     int why);
 
 /*
  * Handle magic process-wide effects of stop/continue signals.
@@ -660,12 +679,17 @@
 			 * the SIGCHLD was pending on entry to this kill.
 			 */
 			p->signal->group_stop_count = 0;
+			p->signal->stop_state = 1;
+			spin_unlock(&p->sighand->siglock);
 			if (p->ptrace & PT_PTRACED)
-				do_notify_parent_cldstop(p, p->parent);
+				do_notify_parent_cldstop(p, p->parent,
+							 CLD_STOPPED);
 			else
 				do_notify_parent_cldstop(
 					p->group_leader,
-					p->group_leader->real_parent);
+					p->group_leader->real_parent,
+							 CLD_STOPPED);
+			spin_lock(&p->sighand->siglock);
 		}
 		rm_from_queue(SIG_KERNEL_STOP_MASK, &p->signal->shared_pending);
 		t = p;
@@ -696,6 +720,25 @@
 
 			t = next_thread(t);
 		} while (t != p);
+
+		if (p->signal->stop_state > 0) {
+			/*
+			 * We were in fact stopped, and are now continued.
+			 * Notify the parent with CLD_CONTINUED.
+			 */
+			p->signal->stop_state = -1;
+			p->signal->group_exit_code = 0;
+			spin_unlock(&p->sighand->siglock);
+			if (p->ptrace & PT_PTRACED)
+				do_notify_parent_cldstop(p, p->parent,
+							 CLD_CONTINUED);
+			else
+				do_notify_parent_cldstop(
+					p->group_leader,
+					p->group_leader->real_parent,
+							 CLD_CONTINUED);
+			spin_lock(&p->sighand->siglock);
+		}
 	}
 }
 
@@ -861,11 +904,20 @@
 
 
 static void
-__group_complete_signal(int sig, struct task_struct *p, unsigned int mask)
+__group_complete_signal(int sig, struct task_struct *p)
 {
+	unsigned int mask;
 	struct task_struct *t;
 
 	/*
+	 * Don't bother zombies and stopped tasks (but
+	 * SIGKILL will punch through stopped state)
+	 */
+	mask = TASK_DEAD | TASK_ZOMBIE | TASK_TRACED;
+	if (sig != SIGKILL)
+		mask |= TASK_STOPPED;
+
+	/*
 	 * Now find a thread we can wake up to take the signal off the queue.
 	 *
 	 * If the main thread wants the signal, it gets first crack.
@@ -966,7 +1018,6 @@
 static int
 __group_send_sig_info(int sig, struct siginfo *info, struct task_struct *p)
 {
-	unsigned int mask;
 	int ret = 0;
 
 #ifdef CONFIG_SMP
@@ -990,14 +1041,6 @@
 		return ret;
 
 	/*
-	 * Don't bother zombies and stopped tasks (but
-	 * SIGKILL will punch through stopped state)
-	 */
-	mask = TASK_DEAD | TASK_ZOMBIE;
-	if (sig != SIGKILL)
-		mask |= TASK_STOPPED;
-
-	/*
 	 * Put this signal on the shared-pending queue, or fail with EAGAIN.
 	 * We always use the shared queue for process-wide signals,
 	 * to avoid several races.
@@ -1006,7 +1049,7 @@
 	if (unlikely(ret))
 		return ret;
 
-	__group_complete_signal(sig, p, mask);
+	__group_complete_signal(sig, p);
 	return 0;
 }
 
@@ -1072,8 +1115,6 @@
 int __kill_pg_info(int sig, struct siginfo *info, pid_t pgrp)
 {
 	struct task_struct *p;
-	struct list_head *l;
-	struct pid *pid;
 	int retval, success;
 
 	if (pgrp <= 0)
@@ -1081,11 +1122,11 @@
 
 	success = 0;
 	retval = -ESRCH;
-	for_each_task_pid(pgrp, PIDTYPE_PGID, p, l, pid) {
+	do_each_task_pid(pgrp, PIDTYPE_PGID, p) {
 		int err = group_send_sig_info(sig, info, p);
 		success |= !err;
 		retval = err;
-	}
+	} while_each_task_pid(pgrp, PIDTYPE_PGID, p);
 	return success ? 0 : retval;
 }
 
@@ -1112,8 +1153,6 @@
 kill_sl_info(int sig, struct siginfo *info, pid_t sid)
 {
 	int err, retval = -EINVAL;
-	struct pid *pid;
-	struct list_head *l;
 	struct task_struct *p;
 
 	if (sid <= 0)
@@ -1121,13 +1160,13 @@
 
 	retval = -ESRCH;
 	read_lock(&tasklist_lock);
-	for_each_task_pid(sid, PIDTYPE_SID, p, l, pid) {
+	do_each_task_pid(sid, PIDTYPE_SID, p) {
 		if (!p->signal->leader)
 			continue;
 		err = group_send_sig_info(sig, info, p);
 		if (retval)
 			retval = err;
-	}
+	} while_each_task_pid(sid, PIDTYPE_SID, p);
 	read_unlock(&tasklist_lock);
 out:
 	return retval;
@@ -1243,6 +1282,25 @@
 	force_sig_info(sig, (void*)1L, p);
 }
 
+/*
+ * When things go south during signal handling, we
+ * will force a SIGSEGV. And if the signal that caused
+ * the problem was already a SIGSEGV, we'll want to
+ * make sure we don't even try to deliver the signal..
+ */
+int
+force_sigsegv(int sig, struct task_struct *p)
+{
+	if (sig == SIGSEGV) {
+		unsigned long flags;
+		spin_lock_irqsave(&p->sighand->siglock, flags);
+		p->sighand->action[sig - 1].sa.sa_handler = SIG_DFL;
+		spin_unlock_irqrestore(&p->sighand->siglock, flags);
+	}
+	force_sig(SIGSEGV, p);
+	return 0;
+}
+
 int
 kill_pg(pid_t pgrp, int sig, int priv)
 {
@@ -1348,7 +1406,6 @@
 send_group_sigqueue(int sig, struct sigqueue *q, struct task_struct *p)
 {
 	unsigned long flags;
-	unsigned int mask;
 	int ret = 0;
 
 	BUG_ON(!(q->flags & SIGQUEUE_PREALLOC));
@@ -1373,13 +1430,6 @@
 		q->info.si_overrun++;
 		goto out;
 	} 
-	/*
-	 * Don't bother zombies and stopped tasks (but
-	 * SIGKILL will punch through stopped state)
-	 */
-	mask = TASK_DEAD | TASK_ZOMBIE;
-	if (sig != SIGKILL)
-		mask |= TASK_STOPPED;
 
 	/*
 	 * Put this signal on the shared-pending queue.
@@ -1390,7 +1440,7 @@
 	list_add_tail(&q->list, &p->signal->shared_pending.list);
 	sigaddset(&p->signal->shared_pending.signal, sig);
 
-	__group_complete_signal(sig, p, mask);
+	__group_complete_signal(sig, p);
 out:
 	spin_unlock_irqrestore(&p->sighand->siglock, flags);
 	read_unlock(&tasklist_lock);
@@ -1423,21 +1473,24 @@
 }
 
 /*
- * Let a parent know about a status change of a child.
+ * Let a parent know about the death of a child.
+ * For a stopped/continued status change, use do_notify_parent_cldstop instead.
  */
 
 void do_notify_parent(struct task_struct *tsk, int sig)
 {
 	struct siginfo info;
 	unsigned long flags;
-	int why, status;
 	struct sighand_struct *psig;
 
 	if (sig == -1)
 		BUG();
 
-	BUG_ON(tsk->group_leader != tsk && tsk->group_leader->state != TASK_ZOMBIE && !tsk->ptrace);
-	BUG_ON(tsk->group_leader == tsk && !thread_group_empty(tsk) && !tsk->ptrace);
+ 	/* do_notify_parent_cldstop should have been called instead.  */
+ 	BUG_ON(tsk->state & (TASK_STOPPED|TASK_TRACED));
+
+	BUG_ON(!tsk->ptrace &&
+	       (tsk->group_leader != tsk || !thread_group_empty(tsk)));
 
 	info.si_signo = sig;
 	info.si_errno = 0;
@@ -1445,37 +1498,22 @@
 	info.si_uid = tsk->uid;
 
 	/* FIXME: find out whether or not this is supposed to be c*time. */
-	info.si_utime = tsk->utime;
-	info.si_stime = tsk->stime;
+	info.si_utime = tsk->utime + tsk->signal->utime;
+	info.si_stime = tsk->stime + tsk->signal->stime;
 
-	status = tsk->exit_code & 0x7f;
-	why = SI_KERNEL;	/* shouldn't happen */
-	switch (tsk->state) {
-	case TASK_STOPPED:
-		/* FIXME -- can we deduce CLD_TRAPPED or CLD_CONTINUED? */
-		if (tsk->ptrace & PT_PTRACED)
-			why = CLD_TRAPPED;
-		else
-			why = CLD_STOPPED;
-		break;
-
-	default:
-		if (tsk->exit_code & 0x80)
-			why = CLD_DUMPED;
-		else if (tsk->exit_code & 0x7f)
-			why = CLD_KILLED;
-		else {
-			why = CLD_EXITED;
-			status = tsk->exit_code >> 8;
-		}
-		break;
+	info.si_status = tsk->exit_code & 0x7f;
+	if (tsk->exit_code & 0x80)
+		info.si_code = CLD_DUMPED;
+	else if (tsk->exit_code & 0x7f)
+		info.si_code = CLD_KILLED;
+	else {
+		info.si_code = CLD_EXITED;
+		info.si_status = tsk->exit_code >> 8;
 	}
-	info.si_code = why;
-	info.si_status = status;
 
 	psig = tsk->parent->sighand;
 	spin_lock_irqsave(&psig->siglock, flags);
-	if (sig == SIGCHLD && tsk->state != TASK_STOPPED &&
+	if (sig == SIGCHLD &&
 	    (psig->action[SIGCHLD-1].sa.sa_handler == SIG_IGN ||
 	     (psig->action[SIGCHLD-1].sa.sa_flags & SA_NOCLDWAIT))) {
 		/*
@@ -1503,26 +1541,9 @@
 	spin_unlock_irqrestore(&psig->siglock, flags);
 }
 
-
-/*
- * We need the tasklist lock because it's the only
- * thing that protects out "parent" pointer.
- *
- * exit.c calls "do_notify_parent()" directly, because
- * it already has the tasklist lock.
- */
-void
-notify_parent(struct task_struct *tsk, int sig)
-{
-	if (sig != -1) {
-		read_lock(&tasklist_lock);
-		do_notify_parent(tsk, sig);
-		read_unlock(&tasklist_lock);
-	}
-}
-
 static void
-do_notify_parent_cldstop(struct task_struct *tsk, struct task_struct *parent)
+do_notify_parent_cldstop(struct task_struct *tsk, struct task_struct *parent,
+			 int why)
 {
 	struct siginfo info;
 	unsigned long flags;
@@ -1537,8 +1558,20 @@
 	info.si_utime = tsk->utime;
 	info.si_stime = tsk->stime;
 
-	info.si_status = tsk->exit_code & 0x7f;
-	info.si_code = CLD_STOPPED;
+ 	info.si_code = why;
+ 	switch (why) {
+ 	case CLD_CONTINUED:
+ 		info.si_status = SIGCONT;
+ 		break;
+ 	case CLD_STOPPED:
+ 		info.si_status = tsk->signal->group_exit_code & 0x7f;
+ 		break;
+ 	case CLD_TRAPPED:
+ 		info.si_status = tsk->exit_code & 0x7f;
+ 		break;
+ 	default:
+ 		BUG();
+ 	}
 
 	sighand = parent->sighand;
 	spin_lock_irqsave(&sighand->siglock, flags);
@@ -1552,6 +1585,68 @@
 	spin_unlock_irqrestore(&sighand->siglock, flags);
 }
 
+/*
+ * This must be called with current->sighand->siglock held.
+ *
+ * This should be the path for all ptrace stops.
+ * We always set current->last_siginfo while stopped here.
+ * That makes it a way to test a stopped process for
+ * being ptrace-stopped vs being job-control-stopped.
+ */
+static void ptrace_stop(int exit_code, siginfo_t *info)
+{
+	BUG_ON(!(current->ptrace & PT_PTRACED));
+
+	/*
+	 * If there is a group stop in progress,
+	 * we must participate in the bookkeeping.
+	 */
+	if (current->signal->group_stop_count > 0)
+		--current->signal->group_stop_count;
+
+	current->last_siginfo = info;
+	current->exit_code = exit_code;
+
+	/* Let the debugger run.  */
+	set_current_state(TASK_TRACED);
+	spin_unlock_irq(&current->sighand->siglock);
+	read_lock(&tasklist_lock);
+	do_notify_parent_cldstop(current, current->parent, CLD_TRAPPED);
+	read_unlock(&tasklist_lock);
+	schedule();
+
+	/*
+	 * We are back.  Now reacquire the siglock before touching
+	 * last_siginfo, so that we are sure to have synchronized with
+	 * any signal-sending on another CPU that wants to examine it.
+	 */
+	spin_lock_irq(&current->sighand->siglock);
+	current->last_siginfo = NULL;
+
+	/*
+	 * Queued signals ignored us while we were stopped for tracing.
+	 * So check for any that we should take before resuming user mode.
+	 */
+	recalc_sigpending();
+}
+
+void ptrace_notify(int exit_code)
+{
+	siginfo_t info;
+
+	BUG_ON((exit_code & (0x7f | ~0xffff)) != SIGTRAP);
+
+	memset(&info, 0, sizeof info);
+	info.si_signo = SIGTRAP;
+	info.si_code = exit_code;
+	info.si_pid = current->pid;
+	info.si_uid = current->uid;
+
+	/* Let the debugger run.  */
+	spin_lock_irq(&current->sighand->siglock);
+	ptrace_stop(exit_code, &info);
+	spin_unlock_irq(&current->sighand->siglock);
+}
 
 #ifndef HAVE_ARCH_GET_SIGNAL_TO_DELIVER
 
@@ -1565,13 +1660,15 @@
 	 */
 	if (stop_count < 0 || (current->ptrace & PT_PTRACED)) {
 		read_lock(&tasklist_lock);
-		do_notify_parent_cldstop(current, current->parent);
+		do_notify_parent_cldstop(current, current->parent,
+					 CLD_STOPPED);
 		read_unlock(&tasklist_lock);
 	}
 	else if (stop_count == 0) {
 		read_lock(&tasklist_lock);
 		do_notify_parent_cldstop(current->group_leader,
-					 current->group_leader->real_parent);
+					 current->group_leader->real_parent,
+					 CLD_STOPPED);
 		read_unlock(&tasklist_lock);
 	}
 
@@ -1604,14 +1701,17 @@
 		stop_count = --sig->group_stop_count;
 		current->exit_code = signr;
 		set_current_state(TASK_STOPPED);
+		if (stop_count == 0)
+			sig->stop_state = 1;
 		spin_unlock_irq(&sighand->siglock);
 	}
 	else if (thread_group_empty(current)) {
 		/*
 		 * Lock must be held through transition to stopped state.
 		 */
-		current->exit_code = signr;
+		current->exit_code = current->signal->group_exit_code = signr;
 		set_current_state(TASK_STOPPED);
+		sig->stop_state = 1;
 		spin_unlock_irq(&sighand->siglock);
 	}
 	else {
@@ -1677,6 +1777,8 @@
 
 		current->exit_code = signr;
 		set_current_state(TASK_STOPPED);
+		if (stop_count == 0)
+			sig->stop_state = 1;
 
 		spin_unlock_irq(&sighand->siglock);
 		read_unlock(&tasklist_lock);
@@ -1717,6 +1819,8 @@
 	 * without any associated signal being in our queue.
 	 */
 	stop_count = --current->signal->group_stop_count;
+	if (stop_count == 0)
+		current->signal->stop_state = 1;
 	current->exit_code = current->signal->group_exit_code;
 	set_current_state(TASK_STOPPED);
 	spin_unlock_irq(&current->sighand->siglock);
@@ -1724,7 +1828,8 @@
 	return 1;
 }
 
-int get_signal_to_deliver(siginfo_t *info, struct pt_regs *regs, void *cookie)
+int get_signal_to_deliver(siginfo_t *info, struct k_sigaction *return_ka,
+			  struct pt_regs *regs, void *cookie)
 {
 	sigset_t *mask = &current->blocked;
 	int signr = 0;
@@ -1746,25 +1851,10 @@
 		if ((current->ptrace & PT_PTRACED) && signr != SIGKILL) {
 			ptrace_signal_deliver(regs, cookie);
 
-			/*
-			 * If there is a group stop in progress,
-			 * we must participate in the bookkeeping.
-			 */
-			if (current->signal->group_stop_count > 0)
-				--current->signal->group_stop_count;
-
 			/* Let the debugger run.  */
-			current->exit_code = signr;
-			current->last_siginfo = info;
-			set_current_state(TASK_STOPPED);
-			spin_unlock_irq(&current->sighand->siglock);
-			notify_parent(current, SIGCHLD);
-			schedule();
-
-			current->last_siginfo = NULL;
+			ptrace_stop(signr, info);
 
 			/* We're back.  Did the debugger cancel the sig?  */
-			spin_lock_irq(&current->sighand->siglock);
 			signr = current->exit_code;
 			if (signr == 0)
 				continue;
@@ -1793,8 +1883,15 @@
 		ka = &current->sighand->action[signr-1];
 		if (ka->sa.sa_handler == SIG_IGN) /* Do nothing.  */
 			continue;
-		if (ka->sa.sa_handler != SIG_DFL) /* Run the handler.  */
+		if (ka->sa.sa_handler != SIG_DFL) {
+			/* Run the handler.  */
+			*return_ka = *ka;
+
+			if (ka->sa.sa_flags & SA_ONESHOT)
+				ka->sa.sa_handler = SIG_DFL;
+
 			break; /* will return non-zero "signr" value */
+		}
 
 		/*
 		 * Now we are doing the default action for this signal.
@@ -1888,7 +1985,7 @@
 EXPORT_SYMBOL(kill_proc_info);
 EXPORT_SYMBOL(kill_sl);
 EXPORT_SYMBOL(kill_sl_info);
-EXPORT_SYMBOL(notify_parent);
+EXPORT_SYMBOL(ptrace_notify);
 EXPORT_SYMBOL(send_sig);
 EXPORT_SYMBOL(send_sig_info);
 EXPORT_SYMBOL(send_group_sig_info);
diff -Nru a/kernel/softirq.c b/kernel/softirq.c
--- a/kernel/softirq.c	2004-10-18 14:56:20 -07:00
+++ b/kernel/softirq.c	2004-10-18 14:56:20 -07:00
@@ -15,6 +15,7 @@
 #include <linux/percpu.h>
 #include <linux/cpu.h>
 #include <linux/kthread.h>
+#include <linux/rcupdate.h>
 
 #include <asm/irq.h>
 /*
@@ -75,10 +76,12 @@
 	struct softirq_action *h;
 	__u32 pending;
 	int max_restart = MAX_SOFTIRQ_RESTART;
+	int cpu;
 
 	pending = local_softirq_pending();
 
 	local_bh_disable();
+	cpu = smp_processor_id();
 restart:
 	/* Reset the pending bitmask before enabling irqs */
 	local_softirq_pending() = 0;
@@ -88,8 +91,10 @@
 	h = softirq_vec;
 
 	do {
-		if (pending & 1)
+		if (pending & 1) {
 			h->action(h);
+			rcu_bh_qsctr_inc(cpu);
+		}
 		h++;
 		pending >>= 1;
 	} while (pending);
diff -Nru a/kernel/spinlock.c b/kernel/spinlock.c
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/kernel/spinlock.c	2004-10-18 14:57:21 -07:00
@@ -0,0 +1,308 @@
+/*
+ * Copyright (2004) Linus Torvalds
+ *
+ * Author: Zwane Mwaikambo <zwane@fsmlabs.com>
+ */
+
+#include <linux/config.h>
+#include <linux/linkage.h>
+#include <linux/preempt.h>
+#include <linux/spinlock.h>
+#include <linux/interrupt.h>
+#include <linux/module.h>
+
+int __lockfunc _spin_trylock(spinlock_t *lock)
+{
+	preempt_disable();
+	if (_raw_spin_trylock(lock))
+		return 1;
+	
+	preempt_enable();
+	return 0;
+}
+EXPORT_SYMBOL(_spin_trylock);
+
+int __lockfunc _write_trylock(rwlock_t *lock)
+{
+	preempt_disable();
+	if (_raw_write_trylock(lock))
+		return 1;
+
+	preempt_enable();
+	return 0;
+}
+EXPORT_SYMBOL(_write_trylock);
+
+#ifdef CONFIG_PREEMPT
+/*
+ * This could be a long-held lock.  If another CPU holds it for a long time,
+ * and that CPU is not asked to reschedule then *this* CPU will spin on the
+ * lock for a long time, even if *this* CPU is asked to reschedule.
+ *
+ * So what we do here, in the slow (contended) path is to spin on the lock by
+ * hand while permitting preemption.
+ *
+ * Called inside preempt_disable().
+ */
+static inline void __preempt_spin_lock(spinlock_t *lock)
+{
+	if (preempt_count() > 1) {
+		_raw_spin_lock(lock);
+		return;
+	}
+
+	do {
+		preempt_enable();
+		while (spin_is_locked(lock))
+			cpu_relax();
+		preempt_disable();
+	} while (!_raw_spin_trylock(lock));
+}
+
+void __lockfunc _spin_lock(spinlock_t *lock)
+{
+	preempt_disable();
+	if (unlikely(!_raw_spin_trylock(lock)))
+		__preempt_spin_lock(lock);
+}
+
+static inline void __preempt_write_lock(rwlock_t *lock)
+{
+	if (preempt_count() > 1) {
+		_raw_write_lock(lock);
+		return;
+	}
+
+	do {
+		preempt_enable();
+		while (rwlock_is_locked(lock))
+			cpu_relax();
+		preempt_disable();
+	} while (!_raw_write_trylock(lock));
+}
+
+void __lockfunc _write_lock(rwlock_t *lock)
+{
+	preempt_disable();
+	if (unlikely(!_raw_write_trylock(lock)))
+		__preempt_write_lock(lock);
+}
+#else
+void __lockfunc _spin_lock(spinlock_t *lock)
+{
+	preempt_disable();
+	_raw_spin_lock(lock);
+}
+
+void __lockfunc _write_lock(rwlock_t *lock)
+{
+	preempt_disable();
+	_raw_write_lock(lock);
+}
+#endif
+EXPORT_SYMBOL(_spin_lock);
+EXPORT_SYMBOL(_write_lock);
+
+void __lockfunc _read_lock(rwlock_t *lock)
+{
+	preempt_disable();
+	_raw_read_lock(lock);
+}
+EXPORT_SYMBOL(_read_lock);
+
+void __lockfunc _spin_unlock(spinlock_t *lock)
+{
+	_raw_spin_unlock(lock);
+	preempt_enable();
+}
+EXPORT_SYMBOL(_spin_unlock);
+
+void __lockfunc _write_unlock(rwlock_t *lock)
+{
+	_raw_write_unlock(lock);
+	preempt_enable();
+}
+EXPORT_SYMBOL(_write_unlock);
+
+void __lockfunc _read_unlock(rwlock_t *lock)
+{
+	_raw_read_unlock(lock);
+	preempt_enable();
+}
+EXPORT_SYMBOL(_read_unlock);
+
+unsigned long __lockfunc _spin_lock_irqsave(spinlock_t *lock)
+{
+	unsigned long flags;
+
+	local_irq_save(flags);
+	preempt_disable();
+	_raw_spin_lock_flags(lock, flags);
+	return flags;
+}
+EXPORT_SYMBOL(_spin_lock_irqsave);
+
+void __lockfunc _spin_lock_irq(spinlock_t *lock)
+{
+	local_irq_disable();
+	preempt_disable();
+	_raw_spin_lock(lock);
+}
+EXPORT_SYMBOL(_spin_lock_irq);
+
+void __lockfunc _spin_lock_bh(spinlock_t *lock)
+{
+	local_bh_disable();
+	preempt_disable();
+	_raw_spin_lock(lock);
+}
+EXPORT_SYMBOL(_spin_lock_bh);
+
+unsigned long __lockfunc _read_lock_irqsave(rwlock_t *lock)
+{
+	unsigned long flags;
+
+	local_irq_save(flags);
+	preempt_disable();
+	_raw_read_lock(lock);
+	return flags;
+}
+EXPORT_SYMBOL(_read_lock_irqsave);
+
+void __lockfunc _read_lock_irq(rwlock_t *lock)
+{
+	local_irq_disable();
+	preempt_disable();
+	_raw_read_lock(lock);
+}
+EXPORT_SYMBOL(_read_lock_irq);
+
+void __lockfunc _read_lock_bh(rwlock_t *lock)
+{
+	local_bh_disable();
+	preempt_disable();
+	_raw_read_lock(lock);
+}
+EXPORT_SYMBOL(_read_lock_bh);
+
+unsigned long __lockfunc _write_lock_irqsave(rwlock_t *lock)
+{
+	unsigned long flags;
+
+	local_irq_save(flags);
+	preempt_disable();
+	_raw_write_lock(lock);
+	return flags;
+}
+EXPORT_SYMBOL(_write_lock_irqsave);
+
+void __lockfunc _write_lock_irq(rwlock_t *lock)
+{
+	local_irq_disable();
+	preempt_disable();
+	_raw_write_lock(lock);
+}
+EXPORT_SYMBOL(_write_lock_irq);
+
+void __lockfunc _write_lock_bh(rwlock_t *lock)
+{
+	local_bh_disable();
+	preempt_disable();
+	_raw_write_lock(lock);
+}
+EXPORT_SYMBOL(_write_lock_bh);
+
+void __lockfunc _spin_unlock_irqrestore(spinlock_t *lock, unsigned long flags)
+{
+	_raw_spin_unlock(lock);
+	local_irq_restore(flags);
+	preempt_enable();
+}
+EXPORT_SYMBOL(_spin_unlock_irqrestore);
+
+void __lockfunc _spin_unlock_irq(spinlock_t *lock)
+{
+	_raw_spin_unlock(lock);
+	local_irq_enable();
+	preempt_enable();
+}
+EXPORT_SYMBOL(_spin_unlock_irq);
+
+void __lockfunc _spin_unlock_bh(spinlock_t *lock)
+{
+	_raw_spin_unlock(lock);
+	preempt_enable();
+	local_bh_enable();
+}
+EXPORT_SYMBOL(_spin_unlock_bh);
+
+void __lockfunc _read_unlock_irqrestore(rwlock_t *lock, unsigned long flags)
+{
+	_raw_read_unlock(lock);
+	local_irq_restore(flags);
+	preempt_enable();
+}
+EXPORT_SYMBOL(_read_unlock_irqrestore);
+
+void __lockfunc _read_unlock_irq(rwlock_t *lock)
+{
+	_raw_read_unlock(lock);
+	local_irq_enable();
+	preempt_enable();
+}
+EXPORT_SYMBOL(_read_unlock_irq);
+
+void __lockfunc _read_unlock_bh(rwlock_t *lock)
+{
+	_raw_read_unlock(lock);
+	preempt_enable();
+	local_bh_enable();
+}
+EXPORT_SYMBOL(_read_unlock_bh);
+
+void __lockfunc _write_unlock_irqrestore(rwlock_t *lock, unsigned long flags)
+{
+	_raw_write_unlock(lock);
+	local_irq_restore(flags);
+	preempt_enable();
+}
+EXPORT_SYMBOL(_write_unlock_irqrestore);
+
+void __lockfunc _write_unlock_irq(rwlock_t *lock)
+{
+	_raw_write_unlock(lock);
+	local_irq_enable();
+	preempt_enable();
+}
+EXPORT_SYMBOL(_write_unlock_irq);
+
+void __lockfunc _write_unlock_bh(rwlock_t *lock)
+{
+	_raw_write_unlock(lock);
+	preempt_enable();
+	local_bh_enable();
+}
+EXPORT_SYMBOL(_write_unlock_bh);
+
+int __lockfunc _spin_trylock_bh(spinlock_t *lock)
+{
+	local_bh_disable();
+	preempt_disable();
+	if (_raw_spin_trylock(lock))
+		return 1;
+
+	preempt_enable();
+	local_bh_enable();
+	return 0;
+}
+EXPORT_SYMBOL(_spin_trylock_bh);
+
+int in_lock_functions(unsigned long addr)
+{
+	/* Linker adds these: start and end of __lockfunc functions */
+	extern char __lock_text_start[], __lock_text_end[];
+
+	return addr >= (unsigned long)__lock_text_start
+	&& addr < (unsigned long)__lock_text_end;
+}
+EXPORT_SYMBOL(in_lock_functions);
diff -Nru a/kernel/sys.c b/kernel/sys.c
--- a/kernel/sys.c	2004-10-18 14:55:55 -07:00
+++ b/kernel/sys.c	2004-10-18 14:55:55 -07:00
@@ -274,7 +274,9 @@
 cond_syscall(sys_mbind)
 cond_syscall(sys_get_mempolicy)
 cond_syscall(sys_set_mempolicy)
+cond_syscall(compat_mbind)
 cond_syscall(compat_get_mempolicy)
+cond_syscall(compat_set_mempolicy)
 
 /* arch-specific weak syscall entries */
 cond_syscall(sys_pciconfig_read)
@@ -310,8 +312,6 @@
 {
 	struct task_struct *g, *p;
 	struct user_struct *user;
-	struct pid *pid;
-	struct list_head *l;
 	int error = -EINVAL;
 
 	if (which > 2 || which < 0)
@@ -336,8 +336,9 @@
 		case PRIO_PGRP:
 			if (!who)
 				who = process_group(current);
-			for_each_task_pid(who, PIDTYPE_PGID, p, l, pid)
+			do_each_task_pid(who, PIDTYPE_PGID, p) {
 				error = set_one_prio(p, niceval, error);
+			} while_each_task_pid(who, PIDTYPE_PGID, p);
 			break;
 		case PRIO_USER:
 			if (!who)
@@ -371,8 +372,6 @@
 asmlinkage long sys_getpriority(int which, int who)
 {
 	struct task_struct *g, *p;
-	struct list_head *l;
-	struct pid *pid;
 	struct user_struct *user;
 	long niceval, retval = -ESRCH;
 
@@ -394,11 +393,11 @@
 		case PRIO_PGRP:
 			if (!who)
 				who = process_group(current);
-			for_each_task_pid(who, PIDTYPE_PGID, p, l, pid) {
+			do_each_task_pid(who, PIDTYPE_PGID, p) {
 				niceval = 20 - task_nice(p);
 				if (niceval > retval)
 					retval = niceval;
-			}
+			} while_each_task_pid(who, PIDTYPE_PGID, p);
 			break;
 		case PRIO_USER:
 			if (!who)
@@ -947,10 +946,39 @@
 	 */
 	if (tbuf) {
 		struct tms tmp;
-		tmp.tms_utime = jiffies_to_clock_t(current->utime);
-		tmp.tms_stime = jiffies_to_clock_t(current->stime);
-		tmp.tms_cutime = jiffies_to_clock_t(current->cutime);
-		tmp.tms_cstime = jiffies_to_clock_t(current->cstime);
+		struct task_struct *tsk = current;
+		struct task_struct *t;
+		unsigned long utime, stime, cutime, cstime;
+
+		read_lock(&tasklist_lock);
+		utime = tsk->signal->utime;
+		stime = tsk->signal->stime;
+		t = tsk;
+		do {
+			utime += t->utime;
+			stime += t->stime;
+			t = next_thread(t);
+		} while (t != tsk);
+
+		/*
+		 * While we have tasklist_lock read-locked, no dying thread
+		 * can be updating current->signal->[us]time.  Instead,
+		 * we got their counts included in the live thread loop.
+		 * However, another thread can come in right now and
+		 * do a wait call that updates current->signal->c[us]time.
+		 * To make sure we always see that pair updated atomically,
+		 * we take the siglock around fetching them.
+		 */
+		spin_lock_irq(&tsk->sighand->siglock);
+		cutime = tsk->signal->cutime;
+		cstime = tsk->signal->cstime;
+		spin_unlock_irq(&tsk->sighand->siglock);
+		read_unlock(&tasklist_lock);
+
+		tmp.tms_utime = jiffies_to_clock_t(utime);
+		tmp.tms_stime = jiffies_to_clock_t(stime);
+		tmp.tms_cutime = jiffies_to_clock_t(cutime);
+		tmp.tms_cstime = jiffies_to_clock_t(cstime);
 		if (copy_to_user(tbuf, &tmp, sizeof(struct tms)))
 			return -EFAULT;
 	}
@@ -1015,12 +1043,11 @@
 
 	if (pgid != pid) {
 		struct task_struct *p;
-		struct pid *pid;
-		struct list_head *l;
 
-		for_each_task_pid(pgid, PIDTYPE_PGID, p, l, pid)
+		do_each_task_pid(pgid, PIDTYPE_PGID, p) {
 			if (p->signal->session == current->signal->session)
 				goto ok_pgid;
+		} while_each_task_pid(pgid, PIDTYPE_PGID, p);
 		goto out;
 	}
 
@@ -1533,44 +1560,86 @@
  * a lot simpler!  (Which we're not doing right now because we're not
  * measuring them yet).
  *
- * This is SMP safe.  Either we are called from sys_getrusage on ourselves
- * below (we know we aren't going to exit/disappear and only we change our
- * rusage counters), or we are called from wait4() on a process which is
- * either stopped or zombied.  In the zombied case the task won't get
- * reaped till shortly after the call to getrusage(), in both cases the
- * task being examined is in a frozen state so the counters won't change.
+ * This expects to be called with tasklist_lock read-locked or better,
+ * and the siglock not locked.  It may momentarily take the siglock.
+ *
+ * When sampling multiple threads for RUSAGE_SELF, under SMP we might have
+ * races with threads incrementing their own counters.  But since word
+ * reads are atomic, we either get new values or old values and we don't
+ * care which for the sums.  We always take the siglock to protect reading
+ * the c* fields from p->signal from races with exit.c updating those
+ * fields when reaping, so a sample either gets all the additions of a
+ * given child after it's reaped, or none so this sample is before reaping.
  */
-int getrusage(struct task_struct *p, int who, struct rusage __user *ru)
+
+void k_getrusage(struct task_struct *p, int who, struct rusage *r)
 {
-	struct rusage r;
+	struct task_struct *t;
+	unsigned long flags;
+	unsigned long utime, stime;
+
+	memset((char *) r, 0, sizeof *r);
+
+	if (unlikely(!p->signal))
+		return;
 
-	memset((char *) &r, 0, sizeof(r));
 	switch (who) {
-		case RUSAGE_SELF:
-			jiffies_to_timeval(p->utime, &r.ru_utime);
-			jiffies_to_timeval(p->stime, &r.ru_stime);
-			r.ru_nvcsw = p->nvcsw;
-			r.ru_nivcsw = p->nivcsw;
-			r.ru_minflt = p->min_flt;
-			r.ru_majflt = p->maj_flt;
-			break;
 		case RUSAGE_CHILDREN:
-			jiffies_to_timeval(p->cutime, &r.ru_utime);
-			jiffies_to_timeval(p->cstime, &r.ru_stime);
-			r.ru_nvcsw = p->cnvcsw;
-			r.ru_nivcsw = p->cnivcsw;
-			r.ru_minflt = p->cmin_flt;
-			r.ru_majflt = p->cmaj_flt;
+			spin_lock_irqsave(&p->sighand->siglock, flags);
+			utime = p->signal->cutime;
+			stime = p->signal->cstime;
+			r->ru_nvcsw = p->signal->cnvcsw;
+			r->ru_nivcsw = p->signal->cnivcsw;
+			r->ru_minflt = p->signal->cmin_flt;
+			r->ru_majflt = p->signal->cmaj_flt;
+			spin_unlock_irqrestore(&p->sighand->siglock, flags);
+			jiffies_to_timeval(utime, &r->ru_utime);
+			jiffies_to_timeval(stime, &r->ru_stime);
 			break;
-		default:
-			jiffies_to_timeval(p->utime + p->cutime, &r.ru_utime);
-			jiffies_to_timeval(p->stime + p->cstime, &r.ru_stime);
-			r.ru_nvcsw = p->nvcsw + p->cnvcsw;
-			r.ru_nivcsw = p->nivcsw + p->cnivcsw;
-			r.ru_minflt = p->min_flt + p->cmin_flt;
-			r.ru_majflt = p->maj_flt + p->cmaj_flt;
+		case RUSAGE_SELF:
+			spin_lock_irqsave(&p->sighand->siglock, flags);
+			utime = stime = 0;
+			goto sum_group;
+		case RUSAGE_BOTH:
+			spin_lock_irqsave(&p->sighand->siglock, flags);
+			utime = p->signal->cutime;
+			stime = p->signal->cstime;
+			r->ru_nvcsw = p->signal->cnvcsw;
+			r->ru_nivcsw = p->signal->cnivcsw;
+			r->ru_minflt = p->signal->cmin_flt;
+			r->ru_majflt = p->signal->cmaj_flt;
+		sum_group:
+			utime += p->signal->utime;
+			stime += p->signal->stime;
+			r->ru_nvcsw += p->signal->nvcsw;
+			r->ru_nivcsw += p->signal->nivcsw;
+			r->ru_minflt += p->signal->min_flt;
+			r->ru_majflt += p->signal->maj_flt;
+			t = p;
+			do {
+				utime += t->utime;
+				stime += t->stime;
+				r->ru_nvcsw += t->nvcsw;
+				r->ru_nivcsw += t->nivcsw;
+				r->ru_minflt += t->min_flt;
+				r->ru_majflt += t->maj_flt;
+				t = next_thread(t);
+			} while (t != p);
+			spin_unlock_irqrestore(&p->sighand->siglock, flags);
+			jiffies_to_timeval(utime, &r->ru_utime);
+			jiffies_to_timeval(stime, &r->ru_stime);
 			break;
+		default:
+			BUG();
 	}
+}
+
+int getrusage(struct task_struct *p, int who, struct rusage __user *ru)
+{
+	struct rusage r;
+	read_lock(&tasklist_lock);
+	k_getrusage(p, who, &r);
+	read_unlock(&tasklist_lock);
 	return copy_to_user(ru, &r, sizeof(r)) ? -EFAULT : 0;
 }
 
@@ -1660,6 +1729,17 @@
 			}
 			current->keep_capabilities = arg2;
 			break;
+		case PR_SET_NAME: {
+			struct task_struct *me = current;
+			unsigned char ncomm[sizeof(me->comm)];
+
+			ncomm[sizeof(me->comm)-1] = 0;
+			if (strncpy_from_user(ncomm, (char __user *)arg2,
+						sizeof(me->comm)-1) < 0)
+				return -EFAULT;
+			set_task_comm(me, ncomm);
+			return 0;
+		}
 		default:
 			error = -EINVAL;
 			break;
diff -Nru a/kernel/sysctl.c b/kernel/sysctl.c
--- a/kernel/sysctl.c	2004-10-18 14:55:54 -07:00
+++ b/kernel/sysctl.c	2004-10-18 14:55:54 -07:00
@@ -42,6 +42,7 @@
 #include <linux/dcache.h>
 
 #include <asm/uaccess.h>
+#include <asm/processor.h>
 
 #ifdef CONFIG_ROOT_NFS
 #include <linux/nfs_fs.h>
@@ -65,6 +66,12 @@
 extern int printk_ratelimit_jiffies;
 extern int printk_ratelimit_burst;
 
+#if defined(CONFIG_X86_LOCAL_APIC) && defined(__i386__)
+int unknown_nmi_panic;
+extern int proc_unknown_nmi_panic(ctl_table *, int, struct file *,
+				  void __user *, size_t *, loff_t *);
+#endif
+
 /* this is needed for the proc_dointvec_minmax for [fs_]overflow UID and GID */
 static int maxolduid = 65535;
 static int minolduid;
@@ -110,12 +117,6 @@
 
 extern int sysctl_hz_timer;
 
-#if defined(CONFIG_PPC32) && defined(CONFIG_6xx)
-extern unsigned long powersave_nap;
-int proc_dol2crvec(ctl_table *table, int write, struct file *filp,
-		  void __user *buffer, size_t *lenp, loff_t *ppos);
-#endif
-
 #ifdef CONFIG_BSD_PROCESS_ACCT
 extern int acct_parm[];
 #endif
@@ -143,6 +144,10 @@
 extern ctl_table pty_table[];
 #endif
 
+#ifdef HAVE_ARCH_PICK_MMAP_LAYOUT
+int sysctl_legacy_va_layout;
+#endif
+
 /* /proc declarations: */
 
 #ifdef CONFIG_PROC_FS
@@ -289,7 +294,7 @@
 		.procname	= "tainted",
 		.data		= &tainted,
 		.maxlen		= sizeof(int),
-		.mode		= 0644,
+		.mode		= 0444,
 		.proc_handler	= &proc_dointvec,
 	},
 	{
@@ -355,22 +360,6 @@
 		.proc_handler	= &proc_dointvec,
 	},
 #endif
-#if defined(CONFIG_PPC32) && defined(CONFIG_6xx)
-	{
-		.ctl_name	= KERN_PPC_POWERSAVE_NAP,
-		.procname	= "powersave-nap",
-		.data		= &powersave_nap,
-		.maxlen		= sizeof(int),
-		.mode		= 0644,
-		.proc_handler	= &proc_dointvec,
-	},
-	{
-		.ctl_name	= KERN_PPC_L2CR,
-		.procname	= "l2cr",
-		.mode		= 0644,
-		.proc_handler	= &proc_dol2crvec,
-	},
-#endif
 	{
 		.ctl_name	= KERN_CTLALTDEL,
 		.procname	= "ctrl-alt-del",
@@ -620,6 +609,16 @@
 		.mode		= 0444,
 		.proc_handler	= &proc_dointvec,
 	},
+#if defined(CONFIG_X86_LOCAL_APIC) && defined(__i386__)
+	{
+		.ctl_name       = KERN_UNKNOWN_NMI_PANIC,
+		.procname       = "unknown_nmi_panic",
+		.data           = &unknown_nmi_panic,
+		.maxlen         = sizeof (int),
+		.mode           = 0644,
+		.proc_handler   = &proc_unknown_nmi_panic,
+	},
+#endif
 	{ .ctl_name = 0 }
 };
 
@@ -789,6 +788,18 @@
 		.strategy	= &sysctl_intvec,
 		.extra1		= &zero,
 	},
+#ifdef HAVE_ARCH_PICK_MMAP_LAYOUT
+	{
+		.ctl_name	= VM_LEGACY_VA_LAYOUT,
+		.procname	= "legacy_va_layout",
+		.data		= &sysctl_legacy_va_layout,
+		.maxlen		= sizeof(sysctl_legacy_va_layout),
+		.mode		= 0644,
+		.proc_handler	= &proc_dointvec,
+		.strategy	= &sysctl_intvec,
+		.extra1		= &zero,
+	},
+#endif
 	{ .ctl_name = 0 }
 };
 
diff -Nru a/kernel/time.c b/kernel/time.c
--- a/kernel/time.c	2004-10-18 14:56:19 -07:00
+++ b/kernel/time.c	2004-10-18 14:56:19 -07:00
@@ -22,6 +22,9 @@
  *	"A Kernel Model for Precision Timekeeping" by Dave Mills
  *	Allow time_constant larger than MAXTC(6) for NTP v4 (MAXTC == 10)
  *	(Even though the technical memorandum forbids it)
+ * 2004-07-14	 Christoph Lameter
+ *	Added getnstimeofday to allow the posix timer functions to return
+ *	with nanosecond accuracy
  */
 
 #include <linux/module.h>
@@ -123,7 +126,7 @@
 	write_seqlock_irq(&xtime_lock);
 	wall_to_monotonic.tv_sec -= sys_tz.tz_minuteswest * 60;
 	xtime.tv_sec += sys_tz.tz_minuteswest * 60;
-	time_interpolator_update(sys_tz.tz_minuteswest * 60 * NSEC_PER_SEC);
+	time_interpolator_reset();
 	write_sequnlock_irq(&xtime_lock);
 	clock_was_set();
 }
@@ -420,6 +423,103 @@
 }
 
 EXPORT_SYMBOL(current_kernel_time);
+
+#ifdef CONFIG_TIME_INTERPOLATION
+void getnstimeofday (struct timespec *tv)
+{
+	unsigned long seq,sec,nsec;
+
+	do {
+		seq = read_seqbegin(&xtime_lock);
+		sec = xtime.tv_sec;
+		nsec = xtime.tv_nsec+time_interpolator_get_offset();
+	} while (unlikely(read_seqretry(&xtime_lock, seq)));
+
+	while (unlikely(nsec >= NSEC_PER_SEC)) {
+		nsec -= NSEC_PER_SEC;
+		++sec;
+	}
+	tv->tv_sec = sec;
+	tv->tv_nsec = nsec;
+}
+
+int do_settimeofday (struct timespec *tv)
+{
+	time_t wtm_sec, sec = tv->tv_sec;
+	long wtm_nsec, nsec = tv->tv_nsec;
+
+	if ((unsigned long)tv->tv_nsec >= NSEC_PER_SEC)
+		return -EINVAL;
+
+	write_seqlock_irq(&xtime_lock);
+	{
+		/*
+		 * This is revolting. We need to set "xtime" correctly. However, the value
+		 * in this location is the value at the most recent update of wall time.
+		 * Discover what correction gettimeofday would have done, and then undo
+		 * it!
+		 */
+		nsec -= time_interpolator_get_offset();
+
+		wtm_sec  = wall_to_monotonic.tv_sec + (xtime.tv_sec - sec);
+		wtm_nsec = wall_to_monotonic.tv_nsec + (xtime.tv_nsec - nsec);
+
+		set_normalized_timespec(&xtime, sec, nsec);
+		set_normalized_timespec(&wall_to_monotonic, wtm_sec, wtm_nsec);
+
+		time_adjust = 0;		/* stop active adjtime() */
+		time_status |= STA_UNSYNC;
+		time_maxerror = NTP_PHASE_LIMIT;
+		time_esterror = NTP_PHASE_LIMIT;
+		time_interpolator_reset();
+	}
+	write_sequnlock_irq(&xtime_lock);
+	clock_was_set();
+	return 0;
+}
+
+EXPORT_SYMBOL(do_settimeofday);
+
+void do_gettimeofday (struct timeval *tv)
+{
+	unsigned long seq, nsec, usec, sec, offset;
+	do {
+		seq = read_seqbegin(&xtime_lock);
+		offset = time_interpolator_get_offset();
+		sec = xtime.tv_sec;
+		nsec = xtime.tv_nsec;
+	} while (unlikely(read_seqretry(&xtime_lock, seq)));
+
+	usec = (nsec + offset) / 1000;
+
+	while (unlikely(usec >= USEC_PER_SEC)) {
+		usec -= USEC_PER_SEC;
+		++sec;
+	}
+
+	tv->tv_sec = sec;
+	tv->tv_usec = usec;
+}
+
+EXPORT_SYMBOL(do_gettimeofday);
+
+
+#else
+/*
+ * Simulate gettimeofday using do_gettimeofday which only allows a timeval
+ * and therefore only yields usec accuracy
+ */
+void getnstimeofday(struct timespec *tv)
+{
+	struct timeval x;
+
+	do_gettimeofday(&x);
+	tv->tv_sec = x.tv_sec;
+	tv->tv_nsec = x.tv_usec * NSEC_PER_USEC;
+}
+#endif
+
+EXPORT_SYMBOL(getnstimeofday);
 
 #if (BITS_PER_LONG < 64)
 u64 get_jiffies_64(void)
diff -Nru a/kernel/timer.c b/kernel/timer.c
--- a/kernel/timer.c	2004-10-18 14:56:49 -07:00
+++ b/kernel/timer.c	2004-10-18 14:56:49 -07:00
@@ -36,6 +36,13 @@
 #include <asm/unistd.h>
 #include <asm/div64.h>
 #include <asm/timex.h>
+#include <asm/io.h>
+
+#ifdef CONFIG_TIME_INTERPOLATION
+static void time_interpolator_update(long delta_nsec);
+#else
+#define time_interpolator_update(x)
+#endif
 
 /*
  * per-CPU timer vector definitions:
@@ -233,6 +240,8 @@
 	spin_unlock_irqrestore(&base->lock, flags);
 }
 
+EXPORT_SYMBOL(add_timer_on);
+
 /***
  * mod_timer - modify a timer's timeout
  * @timer: the timer to be modified
@@ -619,6 +628,9 @@
 	if (xtime.tv_sec % 86400 == 0) {
 	    xtime.tv_sec--;
 	    wall_to_monotonic.tv_sec++;
+	    /* The timer interpolator will make time change gradually instead
+	     * of an immediate jump by one second.
+	     */
 	    time_interpolator_update(-NSEC_PER_SEC);
 	    time_state = TIME_OOP;
 	    clock_was_set();
@@ -630,6 +642,7 @@
 	if ((xtime.tv_sec + 1) % 86400 == 0) {
 	    xtime.tv_sec++;
 	    wall_to_monotonic.tv_sec--;
+	    /* Use of time interpolator for a gradual change of time */
 	    time_interpolator_update(NSEC_PER_SEC);
 	    time_state = TIME_WAIT;
 	    clock_was_set();
@@ -1241,8 +1254,7 @@
 		 * too.
 		 */
 
-		do_gettimeofday((struct timeval *)&tp);
-		tp.tv_nsec *= NSEC_PER_USEC;
+		getnstimeofday(&tp);
 		tp.tv_sec += wall_to_monotonic.tv_sec;
 		tp.tv_nsec += wall_to_monotonic.tv_nsec;
 		if (tp.tv_nsec - NSEC_PER_SEC >= 0) {
@@ -1426,15 +1438,112 @@
 }
 
 #ifdef CONFIG_TIME_INTERPOLATION
-volatile unsigned long last_nsec_offset;
-#ifndef __HAVE_ARCH_CMPXCHG
-spinlock_t last_nsec_offset_lock = SPIN_LOCK_UNLOCKED;
-#endif
 
 struct time_interpolator *time_interpolator;
 static struct time_interpolator *time_interpolator_list;
 static spinlock_t time_interpolator_lock = SPIN_LOCK_UNLOCKED;
 
+static inline unsigned long time_interpolator_get_cycles(unsigned int src)
+{
+	unsigned long (*x)(void);
+
+	switch (src)
+	{
+		case TIME_SOURCE_FUNCTION:
+			x = time_interpolator->addr;
+			return x();
+
+		case TIME_SOURCE_MMIO64	:
+			return readq(time_interpolator->addr);
+
+		case TIME_SOURCE_MMIO32	:
+			return readl(time_interpolator->addr);
+		default: return get_cycles();
+	}
+}
+
+static inline unsigned long time_interpolator_get_counter(void)
+{
+	unsigned int src = time_interpolator->source;
+
+	if (time_interpolator->jitter)
+	{
+		unsigned long lcycle;
+		unsigned long now;
+
+		do {
+			lcycle = time_interpolator->last_cycle;
+			now = time_interpolator_get_cycles(src);
+			if (lcycle && time_after(lcycle, now)) return lcycle;
+			/* Keep track of the last timer value returned. The use of cmpxchg here
+			 * will cause contention in an SMP environment.
+			 */
+		} while (unlikely(cmpxchg(&time_interpolator->last_cycle, lcycle, now) != lcycle));
+		return now;
+	}
+	else
+		return time_interpolator_get_cycles(src);
+}
+
+void time_interpolator_reset(void)
+{
+	time_interpolator->offset = 0;
+	time_interpolator->last_counter = time_interpolator_get_counter();
+}
+
+unsigned long time_interpolator_resolution(void)
+{
+	if (time_interpolator->frequency < NSEC_PER_SEC)
+		return NSEC_PER_SEC / time_interpolator->frequency;
+	else
+		return 1;
+}
+
+#define GET_TI_NSECS(count,i) ((((count) - i->last_counter) * i->nsec_per_cyc) >> i->shift)
+
+unsigned long time_interpolator_get_offset(void)
+{
+	return time_interpolator->offset +
+		GET_TI_NSECS(time_interpolator_get_counter(), time_interpolator);
+}
+
+static void time_interpolator_update(long delta_nsec)
+{
+	unsigned long counter = time_interpolator_get_counter();
+	unsigned long offset = time_interpolator->offset + GET_TI_NSECS(counter, time_interpolator);
+
+	/* The interpolator compensates for late ticks by accumulating
+         * the late time in time_interpolator->offset. A tick earlier than
+	 * expected will lead to a reset of the offset and a corresponding
+	 * jump of the clock forward. Again this only works if the
+	 * interpolator clock is running slightly slower than the regular clock
+	 * and the tuning logic insures that.
+         */
+
+	if (delta_nsec < 0 || (unsigned long) delta_nsec < offset)
+		time_interpolator->offset = offset - delta_nsec;
+	else {
+		time_interpolator->skips++;
+		time_interpolator->ns_skipped += delta_nsec - offset;
+		time_interpolator->offset = 0;
+	}
+	time_interpolator->last_counter = counter;
+
+	/* Tuning logic for time interpolator invoked every minute or so.
+	 * Decrease interpolator clock speed if no skips occurred and an offset is carried.
+	 * Increase interpolator clock speed if we skip too much time.
+	 */
+	if (jiffies % INTERPOLATOR_ADJUST == 0)
+	{
+		if (time_interpolator->skips == 0 && time_interpolator->offset > TICK_NSEC)
+			time_interpolator->nsec_per_cyc--;
+		if (time_interpolator->ns_skipped > INTERPOLATOR_MAX_SKIP && time_interpolator->offset == 0)
+			time_interpolator->nsec_per_cyc++;
+		time_interpolator->skips = 0;
+		time_interpolator->ns_skipped = 0;
+	}
+}
+
 static inline int
 is_better_time_interpolator(struct time_interpolator *new)
 {
@@ -1447,11 +1556,16 @@
 void
 register_time_interpolator(struct time_interpolator *ti)
 {
+	unsigned long flags;
+
+	ti->nsec_per_cyc = (NSEC_PER_SEC << ti->shift) / ti->frequency;
 	spin_lock(&time_interpolator_lock);
-	write_seqlock_irq(&xtime_lock);
-	if (is_better_time_interpolator(ti))
+	write_seqlock_irqsave(&xtime_lock, flags);
+	if (is_better_time_interpolator(ti)) {
 		time_interpolator = ti;
-	write_sequnlock_irq(&xtime_lock);
+		time_interpolator_reset();
+	}
+	write_sequnlock_irqrestore(&xtime_lock, flags);
 
 	ti->next = time_interpolator_list;
 	time_interpolator_list = ti;
@@ -1462,6 +1576,7 @@
 unregister_time_interpolator(struct time_interpolator *ti)
 {
 	struct time_interpolator *curr, **prev;
+	unsigned long flags;
 
 	spin_lock(&time_interpolator_lock);
 	prev = &time_interpolator_list;
@@ -1473,7 +1588,7 @@
 		prev = &curr->next;
 	}
 
-	write_seqlock_irq(&xtime_lock);
+	write_seqlock_irqsave(&xtime_lock, flags);
 	if (ti == time_interpolator) {
 		/* we lost the best time-interpolator: */
 		time_interpolator = NULL;
@@ -1481,8 +1596,9 @@
 		for (curr = time_interpolator_list; curr; curr = curr->next)
 			if (is_better_time_interpolator(curr))
 				time_interpolator = curr;
+		time_interpolator_reset();
 	}
-	write_sequnlock_irq(&xtime_lock);
+	write_sequnlock_irqrestore(&xtime_lock, flags);
 	spin_unlock(&time_interpolator_lock);
 }
 #endif /* CONFIG_TIME_INTERPOLATION */
@@ -1503,3 +1619,19 @@
 
 EXPORT_SYMBOL(msleep);
 
+/**
+ * msleep_interruptible - sleep waiting for waitqueue interruptions
+ * @msecs: Time in milliseconds to sleep for
+ */
+unsigned long msleep_interruptible(unsigned int msecs)
+{
+	unsigned long timeout = msecs_to_jiffies(msecs);
+
+	while (timeout && !signal_pending(current)) {
+		set_current_state(TASK_INTERRUPTIBLE);
+		timeout = schedule_timeout(timeout);
+	}
+	return jiffies_to_msecs(timeout);
+}
+
+EXPORT_SYMBOL(msleep_interruptible);
diff -Nru a/kernel/user.c b/kernel/user.c
--- a/kernel/user.c	2004-10-18 14:56:28 -07:00
+++ b/kernel/user.c	2004-10-18 14:56:28 -07:00
@@ -32,7 +32,8 @@
 	.processes	= ATOMIC_INIT(1),
 	.files		= ATOMIC_INIT(0),
 	.sigpending	= ATOMIC_INIT(0),
-	.mq_bytes	= 0
+	.mq_bytes	= 0,
+	.locked_shm     = 0,
 };
 
 /*
@@ -113,6 +114,7 @@
 		atomic_set(&new->sigpending, 0);
 
 		new->mq_bytes = 0;
+		new->locked_shm = 0;
 
 		/*
 		 * Before adding this, check whether we raced
diff -Nru a/kernel/workqueue.c b/kernel/workqueue.c
--- a/kernel/workqueue.c	2004-10-18 14:57:04 -07:00
+++ b/kernel/workqueue.c	2004-10-18 14:57:04 -07:00
@@ -398,6 +398,26 @@
 	return queue_delayed_work(keventd_wq, work, delay);
 }
 
+int schedule_delayed_work_on(int cpu,
+			struct work_struct *work, unsigned long delay)
+{
+	int ret = 0;
+	struct timer_list *timer = &work->timer;
+
+	if (!test_and_set_bit(0, &work->pending)) {
+		BUG_ON(timer_pending(timer));
+		BUG_ON(!list_empty(&work->entry));
+		/* This stores keventd_wq for the moment, for the timer_fn */
+		work->wq_data = keventd_wq;
+		timer->expires = jiffies + delay;
+		timer->data = (unsigned long)work;
+		timer->function = delayed_work_timer_fn;
+		add_timer_on(timer, cpu);
+		ret = 1;
+	}
+	return ret;
+}
+
 void flush_scheduled_work(void)
 {
 	flush_workqueue(keventd_wq);
@@ -505,5 +525,5 @@
 
 EXPORT_SYMBOL(schedule_work);
 EXPORT_SYMBOL(schedule_delayed_work);
+EXPORT_SYMBOL(schedule_delayed_work_on);
 EXPORT_SYMBOL(flush_scheduled_work);
-
diff -Nru a/lib/Kconfig.debug b/lib/Kconfig.debug
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/lib/Kconfig.debug	2004-10-18 14:57:24 -07:00
@@ -0,0 +1,100 @@
+
+config DEBUG_KERNEL
+	bool "Kernel debugging"
+	depends on (ALPHA || ARM || CRIS || H8300 || X86 || IA64 || M68K || M68KNOMMU || MIPS || PARISC || PPC32 || PPC64 || ARCH_S390 || SUPERH || SUPERH64 || SPARC32 || SPARC64 || USERMODE || V850 || X86_64)
+	help
+	  Say Y here if you are developing drivers or trying to debug and
+	  identify kernel problems.
+
+config MAGIC_SYSRQ
+	bool "Magic SysRq key"
+	depends on DEBUG_KERNEL && (ALPHA || ARM || X86 || IA64 || M68K || MIPS || PARISC || PPC32 || PPC64 || ARCH_S390 || SUPERH || SUPERH64 || SPARC32 || SPARC64 || X86_64)
+	help
+	  If you say Y here, you will have some control over the system even
+	  if the system crashes for example during kernel debugging (e.g., you
+	  will be able to flush the buffer cache to disk, reboot the system
+	  immediately or dump some status information). This is accomplished
+	  by pressing various keys while holding SysRq (Alt+PrintScreen). It
+	  also works on a serial console (on PC hardware at least), if you
+	  send a BREAK and then within 5 seconds a command keypress. The
+	  keys are documented in <file:Documentation/sysrq.txt>. Don't say Y
+	  unless you really know what this hack does.
+
+config MAGIC_SYSRQ
+	bool "Magic SysRq key"
+	depends on DEBUG_KERNEL && (H8300 || M68KNOMMU || V850)
+	depends (USERMODE && MCONSOLE)
+	help
+	  Enables console device to interpret special characters as
+	  commands to dump state information.
+
+config DEBUG_SLAB
+	bool "Debug memory allocations"
+	depends on DEBUG_KERNEL && (ALPHA || ARM || X86 || IA64 || M68K || MIPS || PARISC || PPC32 || PPC64 || ARCH_S390 || SPARC32 || SPARC64 || USERMODE || X86_64)
+	help
+	  Say Y here to have the kernel do limited verification on memory
+	  allocation as well as poisoning memory on free to catch use of freed
+	  memory.
+
+config DEBUG_SPINLOCK
+	bool "Spinlock debugging"
+	depends on DEBUG_KERNEL && (ALPHA || ARM || X86 || IA64 || MIPS || PPC32 || (SUPERH && !SUPERH64) || SPARC32 || SPARC64 || USERMODE || X86_64)
+	help
+	  Say Y here and build SMP to catch missing spinlock initialization
+	  and certain other kinds of spinlock errors commonly made.  This is
+	  best used in conjunction with the NMI watchdog so that spinlock
+	  deadlocks are also debuggable.
+
+config DEBUG_SPINLOCK_SLEEP
+	bool "Sleep-inside-spinlock checking"
+	depends on DEBUG_KERNEL && (X86 || IA64 || MIPS || PPC32 || PPC64 || ARCH_S390 || SPARC32 || SPARC64)
+	help
+	  If you say Y here, various routines which may sleep will become very
+	  noisy if they are called with a spinlock held.
+
+config DEBUG_HIGHMEM
+	bool "Highmem debugging"
+	depends on DEBUG_KERNEL && HIGHMEM && (X86 || PPC32 || MIPS || SPARC32)
+	help
+	  This options enables addition error checking for high memory systems.
+	  Disable for production systems.
+
+config DEBUG_BUGVERBOSE
+	bool "Verbose BUG() reporting (adds 70K)"
+	depends on DEBUG_KERNEL && (ARM || ARM26 || M68K || SPARC32 || SPARC64)
+	help
+	  Say Y here to make BUG() panics output the file name and line number
+	  of the BUG call as well as the EIP and oops trace.  This aids
+	  debugging but costs about 70-100K of memory.
+
+config DEBUG_INFO
+	bool "Compile the kernel with debug info"
+	depends on DEBUG_KERNEL && (ALPHA || CRIS || X86 || IA64 || M68K || MIPS || PARISC || PPC32 || PPC64 || ARCH_S390 || (SUPERH && !SUPERH64) || SPARC64 || V850 || X86_64)
+	help
+          If you say Y here the resulting kernel image will include
+	  debugging info resulting in a larger kernel image.
+	  Say Y here only if you plan to use gdb to debug the kernel.
+	  If you don't debug the kernel, you can say N.
+
+config DEBUG_INFO
+	bool "Enable kernel debugging symbols"
+	depends on DEBUG_KERNEL && USERMODE
+	help
+        When this is enabled, the User-Mode Linux binary will include
+        debugging symbols.  This enlarges the binary by a few megabytes,
+        but aids in tracking down kernel problems in UML.  It is required
+        if you intend to do any kernel development.
+
+        If you're truly short on disk space or don't expect to report any
+        bugs back to the UML developers, say N, otherwise say Y.
+
+if !X86_64
+config FRAME_POINTER
+	bool "Compile the kernel with frame pointers"
+	depends on X86 || CRIS || M68KNOMMU || PARISC
+	help
+	  If you say Y here the resulting kernel image will be slightly larger
+	  and slower, but it will give very useful debugging information.
+	  If you don't debug the kernel, you can say N, but we may not be able
+	  to solve problems without frame pointers.
+endif
diff -Nru a/lib/Makefile b/lib/Makefile
--- a/lib/Makefile	2004-10-18 14:55:54 -07:00
+++ b/lib/Makefile	2004-10-18 14:55:54 -07:00
@@ -5,12 +5,9 @@
 
 lib-y := errno.o ctype.o string.o vsprintf.o cmdline.o \
 	 bust_spinlocks.o rbtree.o radix-tree.o dump_stack.o \
-	 kobject.o idr.o div64.o parser.o int_sqrt.o \
+	 kobject.o kref.o idr.o div64.o parser.o int_sqrt.o \
 	 bitmap.o extable.o
 
-# hack for now till some static code uses krefs, then it can move up above...
-obj-y += kref.o
-
 lib-$(CONFIG_RWSEM_GENERIC_SPINLOCK) += rwsem-spinlock.o
 lib-$(CONFIG_RWSEM_XCHGADD_ALGORITHM) += rwsem.o
 
@@ -21,11 +18,12 @@
 obj-$(CONFIG_CRC_CCITT)	+= crc-ccitt.o
 obj-$(CONFIG_CRC32)	+= crc32.o
 obj-$(CONFIG_LIBCRC32C)	+= libcrc32c.o
+obj-$(CONFIG_GENERIC_IOMAP) += iomap.o
 
 obj-$(CONFIG_ZLIB_INFLATE) += zlib_inflate/
 obj-$(CONFIG_ZLIB_DEFLATE) += zlib_deflate/
 
-host-progs	:= gen_crc32table
+hostprogs-y	:= gen_crc32table
 clean-files	:= crc32table.h
 
 $(obj)/crc32.o: $(obj)/crc32table.h
diff -Nru a/lib/bitmap.c b/lib/bitmap.c
--- a/lib/bitmap.c	2004-10-18 14:56:49 -07:00
+++ b/lib/bitmap.c	2004-10-18 14:56:49 -07:00
@@ -408,3 +408,85 @@
 	return 0;
 }
 EXPORT_SYMBOL(bitmap_parse);
+
+/**
+ *	bitmap_find_free_region - find a contiguous aligned mem region
+ *	@bitmap: an array of unsigned longs corresponding to the bitmap
+ *	@bits: number of bits in the bitmap
+ *	@order: region size to find (size is actually 1<<order)
+ *
+ * This is used to allocate a memory region from a bitmap.  The idea is
+ * that the region has to be 1<<order sized and 1<<order aligned (this
+ * makes the search algorithm much faster).
+ *
+ * The region is marked as set bits in the bitmap if a free one is
+ * found.
+ *
+ * Returns either beginning of region or negative error
+ */
+int bitmap_find_free_region(unsigned long *bitmap, int bits, int order)
+{
+	unsigned long mask;
+	int pages = 1 << order;
+	int i;
+
+	if(pages > BITS_PER_LONG)
+		return -EINVAL;
+
+	/* make a mask of the order */
+	mask = (1ul << (pages - 1));
+	mask += mask - 1;
+
+	/* run up the bitmap pages bits at a time */
+	for (i = 0; i < bits; i += pages) {
+		int index = i/BITS_PER_LONG;
+		int offset = i - (index * BITS_PER_LONG);
+		if((bitmap[index] & (mask << offset)) == 0) {
+			/* set region in bimap */
+			bitmap[index] |= (mask << offset);
+			return i;
+		}
+	}
+	return -ENOMEM;
+}
+EXPORT_SYMBOL(bitmap_find_free_region);
+
+/**
+ *	bitmap_release_region - release allocated bitmap region
+ *	@bitmap: a pointer to the bitmap
+ *	@pos: the beginning of the region
+ *	@order: the order of the bits to release (number is 1<<order)
+ *
+ * This is the complement to __bitmap_find_free_region and releases
+ * the found region (by clearing it in the bitmap).
+ */
+void bitmap_release_region(unsigned long *bitmap, int pos, int order)
+{
+	int pages = 1 << order;
+	unsigned long mask = (1ul << (pages - 1));
+	int index = pos/BITS_PER_LONG;
+	int offset = pos - (index * BITS_PER_LONG);
+	mask += mask - 1;
+	bitmap[index] &= ~(mask << offset);
+}
+EXPORT_SYMBOL(bitmap_release_region);
+
+int bitmap_allocate_region(unsigned long *bitmap, int pos, int order)
+{
+	int pages = 1 << order;
+	unsigned long mask = (1ul << (pages - 1));
+	int index = pos/BITS_PER_LONG;
+	int offset = pos - (index * BITS_PER_LONG);
+
+	/* We don't do regions of pages > BITS_PER_LONG.  The
+	 * algorithm would be a simple look for multiple zeros in the
+	 * array, but there's no driver today that needs this.  If you
+	 * trip this BUG(), you get to code it... */
+	BUG_ON(pages > BITS_PER_LONG);
+	mask += mask - 1;
+	if (bitmap[index] & (mask << offset))
+		return -EBUSY;
+	bitmap[index] |= (mask << offset);
+	return 0;
+}
+EXPORT_SYMBOL(bitmap_allocate_region);
diff -Nru a/lib/idr.c b/lib/idr.c
--- a/lib/idr.c	2004-10-18 14:57:19 -07:00
+++ b/lib/idr.c	2004-10-18 14:57:19 -07:00
@@ -1,21 +1,17 @@
 /*
- * linux/kernel/id.c
- *
  * 2002-10-18  written by Jim Houston jim.houston@ccur.com
  *	Copyright (C) 2002 by Concurrent Computer Corporation
  *	Distributed under the GNU GPL license version 2.
  *
+ * Modified by George Anzinger to reuse immediately and to use
+ * find bit instructions.  Also removed _irq on spinlocks.
+ *
  * Small id to pointer translation service.  
  *
  * It uses a radix tree like structure as a sparse array indexed 
  * by the id to obtain the pointer.  The bitmap makes allocating
  * a new id quick.  
-
- * Modified by George Anzinger to reuse immediately and to use
- * find bit instructions.  Also removed _irq on spinlocks.
-
- * So here is what this bit of code does:
-
+ *
  * You call it to allocate an id (an int) an associate with that id a
  * pointer or what ever, we treat it as a (void *).  You can pass this
  * id to a user for him to pass back at a later time.  You then pass
@@ -26,78 +22,8 @@
  * don't need to go to the memory "store" during an id allocate, just 
  * so you don't need to be too concerned about locking and conflicts
  * with the slab allocator.
-
- * What you need to do is, since we don't keep the counter as part of
- * id / ptr pair, to keep a copy of it in the pointed to structure
- * (or else where) so that when you ask for a ptr you can varify that
- * the returned ptr is correct by comparing the id it contains with the one
- * you asked for.  In other words, we only did half the reuse protection.
- * Since the code depends on your code doing this check, we ignore high
- * order bits in the id, not just the count, but bits that would, if used,
- * index outside of the allocated ids.  In other words, if the largest id
- * currently allocated is 32 a look up will only look at the low 5 bits of
- * the id.  Since you will want to keep this id in the structure anyway
- * (if for no other reason than to be able to eliminate the id when the
- * structure is found in some other way) this seems reasonable.  If you
- * really think otherwise, the code to check these bits here, it is just
- * disabled with a #if 0.
-
-
- * So here are the complete details:
-
- *  include <linux/idr.h>
-
- * void idr_init(struct idr *idp)
-
- *   This function is use to set up the handle (idp) that you will pass
- *   to the rest of the functions.  The structure is defined in the
- *   header.
-
- * int idr_pre_get(struct idr *idp, unsigned gfp_mask)
-
- *   This function should be called prior to locking and calling the
- *   following function.  It pre allocates enough memory to satisfy the
- *   worst possible allocation.  Unless gfp_mask is GFP_ATOMIC, it can
- *   sleep, so must not be called with any spinlocks held.  If the system is
- *   REALLY out of memory this function returns 0, other wise 1.
-
- * int idr_get_new(struct idr *idp, void *ptr, int *id);
- 
- *   This is the allocate id function.  It should be called with any
- *   required locks.  In fact, in the SMP case, you MUST lock prior to
- *   calling this function to avoid possible out of memory problems.
- *   If memory is required, it will return -EAGAIN, you should unlock
- *   and go back to the idr_pre_get() call.  If the idr is full, it
- *   will return a -ENOSPC.  ptr is the pointer you want associated
- *   with the id.  The value is returned in the "id" field.  idr_get_new()
- *   returns a value in the range 0 ... 0x7fffffff
-
- * int idr_get_new_above(struct idr *idp, void *ptr, int start_id, int *id);
-
- *   Like idr_get_new(), but the returned id is guaranteed to be at or
- *   above start_id.
-
- * void *idr_find(struct idr *idp, int id);
- 
- *   returns the "ptr", given the id.  A NULL return indicates that the
- *   id is not valid (or you passed NULL in the idr_get_new(), shame on
- *   you).  This function must be called with a spinlock that prevents
- *   calling either idr_get_new() or idr_remove() or idr_find() while it
- *   is working.
-
- * void idr_remove(struct idr *idp, int id);
-
- *   removes the given id, freeing that slot and any memory that may
- *   now be unused.  See idr_find() for locking restrictions.
-
- * int idr_full(struct idr *idp);
-
- *   Returns true if the idr is full and false if not.
-
  */
 
-
-
 #ifndef TEST                        // to test in user space...
 #include <linux/slab.h>
 #include <linux/init.h>
@@ -106,18 +32,17 @@
 #include <linux/string.h>
 #include <linux/idr.h>
 
-
 static kmem_cache_t *idr_layer_cache;
 
-
-
 static struct idr_layer *alloc_layer(struct idr *idp)
 {
 	struct idr_layer *p;
 
 	spin_lock(&idp->lock);
-	if (!(p = idp->id_free))
+	if (!(p = idp->id_free)) {
+		spin_unlock(&idp->lock);
 		return NULL;
+	}
 	idp->id_free = p->ary[0];
 	idp->id_free_cnt--;
 	p->ary[0] = NULL;
@@ -137,6 +62,18 @@
 	spin_unlock(&idp->lock);
 }
 
+/**
+ * idr_pre_get - reserver resources for idr allocation
+ * @idp:	idr handle
+ * @gfp_mask:	memory allocation flags
+ *
+ * This function should be called prior to locking and calling the
+ * following function.  It preallocates enough memory to satisfy
+ * the worst possible allocation.
+ *
+ * If the system is REALLY out of memory this function returns 0,
+ * otherwise 1.
+ */
 int idr_pre_get(struct idr *idp, unsigned gfp_mask)
 {
 	while (idp->id_free_cnt < IDR_FREE_MAX) {
@@ -271,6 +208,22 @@
 	return(v);
 }
 
+/**
+ * idr_get_new_above - allocate new idr entry above a start id
+ * @idp: idr handle
+ * @ptr: pointer you want associated with the ide
+ * @start_id: id to start search at
+ * @id: pointer to the allocated handle
+ *
+ * This is the allocate id function.  It should be called with any
+ * required locks.
+ *
+ * If memory is required, it will return -EAGAIN, you should unlock
+ * and go back to the idr_pre_get() call.  If the idr is full, it will
+ * return -ENOSPC.
+ *
+ * @id returns a value in the range 0 ... 0x7fffffff
+ */
 int idr_get_new_above(struct idr *idp, void *ptr, int starting_id, int *id)
 {
 	int rv;
@@ -290,6 +243,21 @@
 }
 EXPORT_SYMBOL(idr_get_new_above);
 
+/**
+ * idr_get_new - allocate new idr entry
+ * @idp: idr handle
+ * @ptr: pointer you want associated with the ide
+ * @id: pointer to the allocated handle
+ *
+ * This is the allocate id function.  It should be called with any
+ * required locks.
+ *
+ * If memory is required, it will return -EAGAIN, you should unlock
+ * and go back to the idr_pre_get() call.  If the idr is full, it will
+ * return -ENOSPC.
+ *
+ * @id returns a value in the range 0 ... 0x7fffffff
+ */
 int idr_get_new(struct idr *idp, void *ptr, int *id)
 {
 	int rv;
@@ -338,6 +306,11 @@
 	}
 }
 
+/**
+ * idr_remove - remove the given id and free it's slot
+ * idp: idr handle
+ * id: uniqueue key
+ */
 void idr_remove(struct idr *idp, int id)
 {
 	struct idr_layer *p;
@@ -365,6 +338,17 @@
 }
 EXPORT_SYMBOL(idr_remove);
 
+/**
+ * idr_find - return pointer for given id
+ * @idp: idr handle
+ * @id: lookup key
+ *
+ * Return the pointer given the id it has been registered with.  A %NULL
+ * return indicates that @id is not valid or you passed %NULL in
+ * idr_get_new().
+ *
+ * The caller must serialize idr_find() vs idr_get_new() and idr_remove().
+ */
 void *idr_find(struct idr *idp, int id)
 {
 	int n;
@@ -372,17 +356,13 @@
 
 	n = idp->layers * IDR_BITS;
 	p = idp->top;
-#if 0
-	/*
-	 * This tests to see if bits outside the current tree are
-	 * present.  If so, tain't one of ours!
-	 */
-	if ( unlikely( (id & ~(~0 << MAX_ID_SHIFT)) >> (n + IDR_BITS)))
-	     return NULL;
-#endif
+
 	/* Mask off upper bits we don't use for the search. */
 	id &= MAX_ID_MASK;
 
+	if (id >= (1 << n))
+		return NULL;
+
 	while (n > 0 && p) {
 		n -= IDR_BITS;
 		p = p->ary[(id >> n) & IDR_MASK];
@@ -405,6 +385,13 @@
 	return 0;
 }
 
+/**
+ * idr_init - initialize idr handle
+ * @idp:	idr handle
+ *
+ * This function is use to set up the handle (@idp) that you will pass
+ * to the rest of the functions.
+ */
 void idr_init(struct idr *idp)
 {
 	init_id_cache();
@@ -412,4 +399,3 @@
 	spin_lock_init(&idp->lock);
 }
 EXPORT_SYMBOL(idr_init);
-
diff -Nru a/lib/iomap.c b/lib/iomap.c
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/lib/iomap.c	2004-10-18 14:57:21 -07:00
@@ -0,0 +1,206 @@
+/*
+ * Implement the default iomap interfaces
+ */
+#include <linux/pci.h>
+#include <linux/module.h>
+#include <asm/io.h>
+
+/*
+ * Read/write from/to an (offsettable) iomem cookie. It might be a PIO
+ * access or a MMIO access, these functions don't care. The info is
+ * encoded in the hardware mapping set up by the mapping functions
+ * (or the cookie itself, depending on implementation and hw).
+ *
+ * The generic routines don't assume any hardware mappings, and just
+ * encode the PIO/MMIO as part of the cookie. They coldly assume that
+ * the MMIO IO mappings are not in the low address range.
+ *
+ * Architectures for which this is not true can't use this generic
+ * implementation and should do their own copy.
+ *
+ * We encode the physical PIO addresses (0-0xffff) into the
+ * pointer by offsetting them with a constant (0x10000) and
+ * assuming that all the low addresses are always PIO. That means
+ * we can do some sanity checks on the low bits, and don't
+ * need to just take things for granted.
+ */
+#define PIO_OFFSET	0x10000UL
+#define PIO_MASK	0x0ffffUL
+#define PIO_RESERVED	0x40000UL
+
+/*
+ * Ugly macros are a way of life.
+ */
+#define VERIFY_PIO(port) BUG_ON((port & ~PIO_MASK) != PIO_OFFSET)
+
+#define IO_COND(addr, is_pio, is_mmio) do {			\
+	unsigned long port = (unsigned long __force)addr;	\
+	if (port < PIO_RESERVED) {				\
+		VERIFY_PIO(port);				\
+		port &= PIO_MASK;				\
+		is_pio;						\
+	} else {						\
+		is_mmio;					\
+	}							\
+} while (0)
+
+unsigned int fastcall ioread8(void __iomem *addr)
+{
+	IO_COND(addr, return inb(port), return readb(addr));
+}
+unsigned int fastcall ioread16(void __iomem *addr)
+{
+	IO_COND(addr, return inw(port), return readw(addr));
+}
+unsigned int fastcall ioread32(void __iomem *addr)
+{
+	IO_COND(addr, return inl(port), return readl(addr));
+}
+EXPORT_SYMBOL(ioread8);
+EXPORT_SYMBOL(ioread16);
+EXPORT_SYMBOL(ioread32);
+
+void fastcall iowrite8(u8 val, void __iomem *addr)
+{
+	IO_COND(addr, outb(val,port), writeb(val, addr));
+}
+void fastcall iowrite16(u16 val, void __iomem *addr)
+{
+	IO_COND(addr, outw(val,port), writew(val, addr));
+}
+void fastcall iowrite32(u32 val, void __iomem *addr)
+{
+	IO_COND(addr, outl(val,port), writel(val, addr));
+}
+EXPORT_SYMBOL(iowrite8);
+EXPORT_SYMBOL(iowrite16);
+EXPORT_SYMBOL(iowrite32);
+
+/*
+ * These are the "repeat MMIO read/write" functions.
+ * Note the "__raw" accesses, since we don't want to
+ * convert to CPU byte order. We write in "IO byte
+ * order" (we also don't have IO barriers).
+ */
+static inline void mmio_insb(void __iomem *addr, u8 *dst, int count)
+{
+	while (--count >= 0) {
+		u8 data = __raw_readb(addr);
+		*dst = data;
+		dst++;
+	}
+}
+static inline void mmio_insw(void __iomem *addr, u16 *dst, int count)
+{
+	while (--count >= 0) {
+		u16 data = __raw_readw(addr);
+		*dst = data;
+		dst++;
+	}
+}
+static inline void mmio_insl(void __iomem *addr, u32 *dst, int count)
+{
+	while (--count >= 0) {
+		u32 data = __raw_readl(addr);
+		*dst = data;
+		dst++;
+	}
+}
+
+static inline void mmio_outsb(void __iomem *addr, const u8 *src, int count)
+{
+	while (--count >= 0) {
+		__raw_writeb(*src, addr);
+		src++;
+	}
+}
+static inline void mmio_outsw(void __iomem *addr, const u16 *src, int count)
+{
+	while (--count >= 0) {
+		__raw_writew(*src, addr);
+		src++;
+	}
+}
+static inline void mmio_outsl(void __iomem *addr, const u32 *src, int count)
+{
+	while (--count >= 0) {
+		__raw_writel(*src, addr);
+		src++;
+	}
+}
+
+void fastcall ioread8_rep(void __iomem *addr, void *dst, unsigned long count)
+{
+	IO_COND(addr, insb(port,dst,count), mmio_insb(addr, dst, count));
+}
+void fastcall ioread16_rep(void __iomem *addr, void *dst, unsigned long count)
+{
+	IO_COND(addr, insw(port,dst,count), mmio_insw(addr, dst, count));
+}
+void fastcall ioread32_rep(void __iomem *addr, void *dst, unsigned long count)
+{
+	IO_COND(addr, insl(port,dst,count), mmio_insl(addr, dst, count));
+}
+EXPORT_SYMBOL(ioread8_rep);
+EXPORT_SYMBOL(ioread16_rep);
+EXPORT_SYMBOL(ioread32_rep);
+
+void fastcall iowrite8_rep(void __iomem *addr, const void *src, unsigned long count)
+{
+	IO_COND(addr, outsb(port, src, count), mmio_outsb(addr, src, count));
+}
+void fastcall iowrite16_rep(void __iomem *addr, const void *src, unsigned long count)
+{
+	IO_COND(addr, outsw(port, src, count), mmio_outsw(addr, src, count));
+}
+void fastcall iowrite32_rep(void __iomem *addr, const void *src, unsigned long count)
+{
+	IO_COND(addr, outsl(port, src,count), mmio_outsl(addr, src, count));
+}
+EXPORT_SYMBOL(iowrite8_rep);
+EXPORT_SYMBOL(iowrite16_rep);
+EXPORT_SYMBOL(iowrite32_rep);
+
+/* Create a virtual mapping cookie for an IO port range */
+void __iomem *ioport_map(unsigned long port, unsigned int nr)
+{
+	if (port > PIO_MASK)
+		return NULL;
+	return (void __iomem *) (unsigned long) (port + PIO_OFFSET);
+}
+
+void ioport_unmap(void __iomem *addr)
+{
+	/* Nothing to do */
+}
+EXPORT_SYMBOL(ioport_map);
+EXPORT_SYMBOL(ioport_unmap);
+
+/* Create a virtual mapping cookie for a PCI BAR (memory or IO) */
+void __iomem *pci_iomap(struct pci_dev *dev, int bar, unsigned long maxlen)
+{
+	unsigned long start = pci_resource_start(dev, bar);
+	unsigned long len = pci_resource_len(dev, bar);
+	unsigned long flags = pci_resource_flags(dev, bar);
+
+	if (!len || !start)
+		return NULL;
+	if (maxlen && len > maxlen)
+		len = maxlen;
+	if (flags & IORESOURCE_IO)
+		return ioport_map(start, len);
+	if (flags & IORESOURCE_MEM) {
+		if (flags & IORESOURCE_CACHEABLE)
+			return ioremap(start, len);
+		return ioremap_nocache(start, len);
+	}
+	/* What? */
+	return NULL;
+}
+
+void pci_iounmap(struct pci_dev *dev, void __iomem * addr)
+{
+	IO_COND(addr, /* nothing */, iounmap(addr));
+}
+EXPORT_SYMBOL(pci_iomap);
+EXPORT_SYMBOL(pci_iounmap);
diff -Nru a/lib/kobject.c b/lib/kobject.c
--- a/lib/kobject.c	2004-10-18 14:57:03 -07:00
+++ b/lib/kobject.c	2004-10-18 14:57:03 -07:00
@@ -58,14 +58,11 @@
 	return error;
 }
 
-
 static inline struct kobject * to_kobj(struct list_head * entry)
 {
 	return container_of(entry,struct kobject,entry);
 }
 
-
-#ifdef CONFIG_HOTPLUG
 static int get_kobj_path_length(struct kset *kset, struct kobject *kobj)
 {
 	int length = 1;
@@ -98,6 +95,31 @@
 	pr_debug("%s: path = '%s'\n",__FUNCTION__,path);
 }
 
+/**
+ * kobject_get_path - generate and return the path associated with a given kobj
+ * and kset pair.  The result must be freed by the caller with kfree().
+ *
+ * @kset:	kset in question, with which to build the path
+ * @kobj:	kobject in question, with which to build the path
+ * @gfp_mask:	the allocation type used to allocate the path
+ */
+char * kobject_get_path(struct kset *kset, struct kobject *kobj, int gfp_mask)
+{
+	char *path;
+	int len;
+
+	len = get_kobj_path_length(kset, kobj);
+	path = kmalloc(len, gfp_mask);
+	if (!path)
+		return NULL;
+	memset(path, 0x00, len);
+	fill_kobj_path(kset, kobj, path, len);
+
+	return path;
+}
+
+#ifdef CONFIG_HOTPLUG
+
 #define BUFFER_SIZE	1024	/* should be enough memory for the env */
 #define NUM_ENVP	32	/* number of env pointers */
 static unsigned long sequence_num;
@@ -112,7 +134,6 @@
 	char *scratch;
 	int i = 0;
 	int retval;
-	int kobj_path_length;
 	char *kobj_path = NULL;
 	char *name = NULL;
 	unsigned long seq;
@@ -163,12 +184,9 @@
 	envp [i++] = scratch;
 	scratch += sprintf(scratch, "SEQNUM=%ld", seq) + 1;
 
-	kobj_path_length = get_kobj_path_length (kset, kobj);
-	kobj_path = kmalloc (kobj_path_length, GFP_KERNEL);
+	kobj_path = kobject_get_path(kset, kobj, GFP_KERNEL);
 	if (!kobj_path)
 		goto exit;
-	memset (kobj_path, 0x00, kobj_path_length);
-	fill_kobj_path (kset, kobj, kobj_path, kobj_path_length);
 
 	envp [i++] = scratch;
 	scratch += sprintf (scratch, "DEVPATH=%s", kobj_path) + 1;
@@ -225,10 +243,9 @@
  *	kobject_init - initialize object.
  *	@kobj:	object in question.
  */
-
 void kobject_init(struct kobject * kobj)
 {
-	atomic_set(&kobj->refcount,1);
+ 	kref_init(&kobj->kref);
 	INIT_LIST_HEAD(&kobj->entry);
 	kobj->kset = kset_get(kobj->kset);
 }
@@ -325,7 +342,7 @@
  *	@kobj:	object.
  *	@name:	name. 
  *
- *	If strlen(name) < KOBJ_NAME_LEN, then use a dynamically allocated
+ *	If strlen(name) >= KOBJ_NAME_LEN, then use a dynamically allocated
  *	string that @kobj->k_name points to. Otherwise, use the static 
  *	@kobj->name array.
  */
@@ -429,10 +446,8 @@
 
 struct kobject * kobject_get(struct kobject * kobj)
 {
-	if (kobj) {
-		WARN_ON(!atomic_read(&kobj->refcount));
-		atomic_inc(&kobj->refcount);
-	}
+	if (kobj)
+		kref_get(&kobj->kref);
 	return kobj;
 }
 
@@ -459,17 +474,21 @@
 		kobject_put(parent);
 }
 
+static void kobject_release(struct kref *kref)
+{
+	kobject_cleanup(container_of(kref, struct kobject, kref));
+}
+
 /**
  *	kobject_put - decrement refcount for object.
  *	@kobj:	object.
  *
  *	Decrement the refcount, and if 0, call kobject_cleanup().
  */
-
 void kobject_put(struct kobject * kobj)
 {
-	if (atomic_dec_and_test(&kobj->refcount))
-		kobject_cleanup(kobj);
+	if (kobj)
+		kref_put(&kobj->kref, kobject_release);
 }
 
 
@@ -626,7 +645,7 @@
 	}
 }
 
-
+EXPORT_SYMBOL(kobject_get_path);
 EXPORT_SYMBOL(kobject_init);
 EXPORT_SYMBOL(kobject_register);
 EXPORT_SYMBOL(kobject_unregister);
diff -Nru a/lib/kref.c b/lib/kref.c
--- a/lib/kref.c	2004-10-18 14:57:04 -07:00
+++ b/lib/kref.c	2004-10-18 14:57:04 -07:00
@@ -11,48 +11,45 @@
  *
  */
 
-/* #define DEBUG */
-
 #include <linux/kref.h>
 #include <linux/module.h>
 
 /**
  * kref_init - initialize object.
  * @kref: object in question.
- * @release: pointer to a function that will clean up the object
- *	     when the last reference to the object is released.
- *	     This pointer is required.
  */
-void kref_init(struct kref *kref, void (*release)(struct kref *kref))
+void kref_init(struct kref *kref)
 {
-	WARN_ON(release == NULL);
 	atomic_set(&kref->refcount,1);
-	kref->release = release;
 }
 
 /**
  * kref_get - increment refcount for object.
  * @kref: object.
  */
-struct kref *kref_get(struct kref *kref)
+void kref_get(struct kref *kref)
 {
 	WARN_ON(!atomic_read(&kref->refcount));
 	atomic_inc(&kref->refcount);
-	return kref;
 }
 
 /**
  * kref_put - decrement refcount for object.
  * @kref: object.
+ * @release: pointer to the function that will clean up the object when the
+ *	     last reference to the object is released.
+ *	     This pointer is required, and it is not acceptable to pass kfree
+ *	     in as this function.
  *
- * Decrement the refcount, and if 0, call kref->release().
+ * Decrement the refcount, and if 0, call release().
  */
-void kref_put(struct kref *kref)
+void kref_put(struct kref *kref, void (*release) (struct kref *kref))
 {
-	if (atomic_dec_and_test(&kref->refcount)) {
-		pr_debug("kref cleaning up\n");
-		kref->release(kref);
-	}
+	WARN_ON(release == NULL);
+	WARN_ON(release == (void (*)(struct kref *))kfree);
+
+	if (atomic_dec_and_test(&kref->refcount))
+		release(kref);
 }
 
 EXPORT_SYMBOL(kref_init);
diff -Nru a/lib/rbtree.c b/lib/rbtree.c
--- a/lib/rbtree.c	2004-10-18 14:56:33 -07:00
+++ b/lib/rbtree.c	2004-10-18 14:56:33 -07:00
@@ -312,6 +312,19 @@
 }
 EXPORT_SYMBOL(rb_first);
 
+struct rb_node *rb_last(struct rb_root *root)
+{
+	struct rb_node	*n;
+
+	n = root->rb_node;
+	if (!n)
+		return NULL;
+	while (n->rb_right)
+		n = n->rb_right;
+	return n;
+}
+EXPORT_SYMBOL(rb_last);
+
 struct rb_node *rb_next(struct rb_node *node)
 {
 	/* If we have a right-hand child, go down and then left as far
diff -Nru a/lib/rwsem.c b/lib/rwsem.c
--- a/lib/rwsem.c	2004-10-18 14:55:54 -07:00
+++ b/lib/rwsem.c	2004-10-18 14:55:54 -07:00
@@ -255,10 +255,10 @@
 	return sem;
 }
 
-EXPORT_SYMBOL_NOVERS(rwsem_down_read_failed);
-EXPORT_SYMBOL_NOVERS(rwsem_down_write_failed);
-EXPORT_SYMBOL_NOVERS(rwsem_wake);
-EXPORT_SYMBOL_NOVERS(rwsem_downgrade_wake);
+EXPORT_SYMBOL(rwsem_down_read_failed);
+EXPORT_SYMBOL(rwsem_down_write_failed);
+EXPORT_SYMBOL(rwsem_wake);
+EXPORT_SYMBOL(rwsem_downgrade_wake);
 #if RWSEM_DEBUG
 EXPORT_SYMBOL(rwsemtrace);
 #endif
diff -Nru a/lib/zlib_inflate/Makefile b/lib/zlib_inflate/Makefile
--- a/lib/zlib_inflate/Makefile	2004-10-18 14:56:49 -07:00
+++ b/lib/zlib_inflate/Makefile	2004-10-18 14:56:49 -07:00
@@ -16,4 +16,4 @@
 obj-$(CONFIG_ZLIB_INFLATE) += zlib_inflate.o
 
 zlib_inflate-objs := infblock.o infcodes.o inffast.o inflate.o \
-		     inftrees.o infutil.o inflate_syms.o
+		     inflate_sync.o inftrees.o infutil.o inflate_syms.o
diff -Nru a/lib/zlib_inflate/infblock.c b/lib/zlib_inflate/infblock.c
--- a/lib/zlib_inflate/infblock.c	2004-10-18 14:56:49 -07:00
+++ b/lib/zlib_inflate/infblock.c	2004-10-18 14:56:49 -07:00
@@ -139,7 +139,7 @@
             uInt bl, bd;
             inflate_huft *tl, *td;
 
-            zlib_inflate_trees_fixed(&bl, &bd, &tl, &td, z);
+            zlib_inflate_trees_fixed(&bl, &bd, &tl, &td, s->hufts, z);
             s->sub.decode.codes = zlib_inflate_codes_new(bl, bd, tl, td, z);
             if (s->sub.decode.codes == NULL)
             {
diff -Nru a/lib/zlib_inflate/inffixed.h b/lib/zlib_inflate/inffixed.h
--- a/lib/zlib_inflate/inffixed.h	2004-10-18 14:56:17 -07:00
+++ /dev/null	Wed Dec 31 16:00:00 196900
@@ -1,151 +0,0 @@
-/* inffixed.h -- table for decoding fixed codes
- * Generated automatically by the maketree.c program
- */
-
-/* WARNING: this file should *not* be used by applications. It is
-   part of the implementation of the compression library and is
-   subject to change. Applications should only use zlib.h.
- */
-
-static uInt fixed_bl = 9;
-static uInt fixed_bd = 5;
-static inflate_huft fixed_tl[] = {
-    {{{96,7}},256}, {{{0,8}},80}, {{{0,8}},16}, {{{84,8}},115},
-    {{{82,7}},31}, {{{0,8}},112}, {{{0,8}},48}, {{{0,9}},192},
-    {{{80,7}},10}, {{{0,8}},96}, {{{0,8}},32}, {{{0,9}},160},
-    {{{0,8}},0}, {{{0,8}},128}, {{{0,8}},64}, {{{0,9}},224},
-    {{{80,7}},6}, {{{0,8}},88}, {{{0,8}},24}, {{{0,9}},144},
-    {{{83,7}},59}, {{{0,8}},120}, {{{0,8}},56}, {{{0,9}},208},
-    {{{81,7}},17}, {{{0,8}},104}, {{{0,8}},40}, {{{0,9}},176},
-    {{{0,8}},8}, {{{0,8}},136}, {{{0,8}},72}, {{{0,9}},240},
-    {{{80,7}},4}, {{{0,8}},84}, {{{0,8}},20}, {{{85,8}},227},
-    {{{83,7}},43}, {{{0,8}},116}, {{{0,8}},52}, {{{0,9}},200},
-    {{{81,7}},13}, {{{0,8}},100}, {{{0,8}},36}, {{{0,9}},168},
-    {{{0,8}},4}, {{{0,8}},132}, {{{0,8}},68}, {{{0,9}},232},
-    {{{80,7}},8}, {{{0,8}},92}, {{{0,8}},28}, {{{0,9}},152},
-    {{{84,7}},83}, {{{0,8}},124}, {{{0,8}},60}, {{{0,9}},216},
-    {{{82,7}},23}, {{{0,8}},108}, {{{0,8}},44}, {{{0,9}},184},
-    {{{0,8}},12}, {{{0,8}},140}, {{{0,8}},76}, {{{0,9}},248},
-    {{{80,7}},3}, {{{0,8}},82}, {{{0,8}},18}, {{{85,8}},163},
-    {{{83,7}},35}, {{{0,8}},114}, {{{0,8}},50}, {{{0,9}},196},
-    {{{81,7}},11}, {{{0,8}},98}, {{{0,8}},34}, {{{0,9}},164},
-    {{{0,8}},2}, {{{0,8}},130}, {{{0,8}},66}, {{{0,9}},228},
-    {{{80,7}},7}, {{{0,8}},90}, {{{0,8}},26}, {{{0,9}},148},
-    {{{84,7}},67}, {{{0,8}},122}, {{{0,8}},58}, {{{0,9}},212},
-    {{{82,7}},19}, {{{0,8}},106}, {{{0,8}},42}, {{{0,9}},180},
-    {{{0,8}},10}, {{{0,8}},138}, {{{0,8}},74}, {{{0,9}},244},
-    {{{80,7}},5}, {{{0,8}},86}, {{{0,8}},22}, {{{192,8}},0},
-    {{{83,7}},51}, {{{0,8}},118}, {{{0,8}},54}, {{{0,9}},204},
-    {{{81,7}},15}, {{{0,8}},102}, {{{0,8}},38}, {{{0,9}},172},
-    {{{0,8}},6}, {{{0,8}},134}, {{{0,8}},70}, {{{0,9}},236},
-    {{{80,7}},9}, {{{0,8}},94}, {{{0,8}},30}, {{{0,9}},156},
-    {{{84,7}},99}, {{{0,8}},126}, {{{0,8}},62}, {{{0,9}},220},
-    {{{82,7}},27}, {{{0,8}},110}, {{{0,8}},46}, {{{0,9}},188},
-    {{{0,8}},14}, {{{0,8}},142}, {{{0,8}},78}, {{{0,9}},252},
-    {{{96,7}},256}, {{{0,8}},81}, {{{0,8}},17}, {{{85,8}},131},
-    {{{82,7}},31}, {{{0,8}},113}, {{{0,8}},49}, {{{0,9}},194},
-    {{{80,7}},10}, {{{0,8}},97}, {{{0,8}},33}, {{{0,9}},162},
-    {{{0,8}},1}, {{{0,8}},129}, {{{0,8}},65}, {{{0,9}},226},
-    {{{80,7}},6}, {{{0,8}},89}, {{{0,8}},25}, {{{0,9}},146},
-    {{{83,7}},59}, {{{0,8}},121}, {{{0,8}},57}, {{{0,9}},210},
-    {{{81,7}},17}, {{{0,8}},105}, {{{0,8}},41}, {{{0,9}},178},
-    {{{0,8}},9}, {{{0,8}},137}, {{{0,8}},73}, {{{0,9}},242},
-    {{{80,7}},4}, {{{0,8}},85}, {{{0,8}},21}, {{{80,8}},258},
-    {{{83,7}},43}, {{{0,8}},117}, {{{0,8}},53}, {{{0,9}},202},
-    {{{81,7}},13}, {{{0,8}},101}, {{{0,8}},37}, {{{0,9}},170},
-    {{{0,8}},5}, {{{0,8}},133}, {{{0,8}},69}, {{{0,9}},234},
-    {{{80,7}},8}, {{{0,8}},93}, {{{0,8}},29}, {{{0,9}},154},
-    {{{84,7}},83}, {{{0,8}},125}, {{{0,8}},61}, {{{0,9}},218},
-    {{{82,7}},23}, {{{0,8}},109}, {{{0,8}},45}, {{{0,9}},186},
-    {{{0,8}},13}, {{{0,8}},141}, {{{0,8}},77}, {{{0,9}},250},
-    {{{80,7}},3}, {{{0,8}},83}, {{{0,8}},19}, {{{85,8}},195},
-    {{{83,7}},35}, {{{0,8}},115}, {{{0,8}},51}, {{{0,9}},198},
-    {{{81,7}},11}, {{{0,8}},99}, {{{0,8}},35}, {{{0,9}},166},
-    {{{0,8}},3}, {{{0,8}},131}, {{{0,8}},67}, {{{0,9}},230},
-    {{{80,7}},7}, {{{0,8}},91}, {{{0,8}},27}, {{{0,9}},150},
-    {{{84,7}},67}, {{{0,8}},123}, {{{0,8}},59}, {{{0,9}},214},
-    {{{82,7}},19}, {{{0,8}},107}, {{{0,8}},43}, {{{0,9}},182},
-    {{{0,8}},11}, {{{0,8}},139}, {{{0,8}},75}, {{{0,9}},246},
-    {{{80,7}},5}, {{{0,8}},87}, {{{0,8}},23}, {{{192,8}},0},
-    {{{83,7}},51}, {{{0,8}},119}, {{{0,8}},55}, {{{0,9}},206},
-    {{{81,7}},15}, {{{0,8}},103}, {{{0,8}},39}, {{{0,9}},174},
-    {{{0,8}},7}, {{{0,8}},135}, {{{0,8}},71}, {{{0,9}},238},
-    {{{80,7}},9}, {{{0,8}},95}, {{{0,8}},31}, {{{0,9}},158},
-    {{{84,7}},99}, {{{0,8}},127}, {{{0,8}},63}, {{{0,9}},222},
-    {{{82,7}},27}, {{{0,8}},111}, {{{0,8}},47}, {{{0,9}},190},
-    {{{0,8}},15}, {{{0,8}},143}, {{{0,8}},79}, {{{0,9}},254},
-    {{{96,7}},256}, {{{0,8}},80}, {{{0,8}},16}, {{{84,8}},115},
-    {{{82,7}},31}, {{{0,8}},112}, {{{0,8}},48}, {{{0,9}},193},
-    {{{80,7}},10}, {{{0,8}},96}, {{{0,8}},32}, {{{0,9}},161},
-    {{{0,8}},0}, {{{0,8}},128}, {{{0,8}},64}, {{{0,9}},225},
-    {{{80,7}},6}, {{{0,8}},88}, {{{0,8}},24}, {{{0,9}},145},
-    {{{83,7}},59}, {{{0,8}},120}, {{{0,8}},56}, {{{0,9}},209},
-    {{{81,7}},17}, {{{0,8}},104}, {{{0,8}},40}, {{{0,9}},177},
-    {{{0,8}},8}, {{{0,8}},136}, {{{0,8}},72}, {{{0,9}},241},
-    {{{80,7}},4}, {{{0,8}},84}, {{{0,8}},20}, {{{85,8}},227},
-    {{{83,7}},43}, {{{0,8}},116}, {{{0,8}},52}, {{{0,9}},201},
-    {{{81,7}},13}, {{{0,8}},100}, {{{0,8}},36}, {{{0,9}},169},
-    {{{0,8}},4}, {{{0,8}},132}, {{{0,8}},68}, {{{0,9}},233},
-    {{{80,7}},8}, {{{0,8}},92}, {{{0,8}},28}, {{{0,9}},153},
-    {{{84,7}},83}, {{{0,8}},124}, {{{0,8}},60}, {{{0,9}},217},
-    {{{82,7}},23}, {{{0,8}},108}, {{{0,8}},44}, {{{0,9}},185},
-    {{{0,8}},12}, {{{0,8}},140}, {{{0,8}},76}, {{{0,9}},249},
-    {{{80,7}},3}, {{{0,8}},82}, {{{0,8}},18}, {{{85,8}},163},
-    {{{83,7}},35}, {{{0,8}},114}, {{{0,8}},50}, {{{0,9}},197},
-    {{{81,7}},11}, {{{0,8}},98}, {{{0,8}},34}, {{{0,9}},165},
-    {{{0,8}},2}, {{{0,8}},130}, {{{0,8}},66}, {{{0,9}},229},
-    {{{80,7}},7}, {{{0,8}},90}, {{{0,8}},26}, {{{0,9}},149},
-    {{{84,7}},67}, {{{0,8}},122}, {{{0,8}},58}, {{{0,9}},213},
-    {{{82,7}},19}, {{{0,8}},106}, {{{0,8}},42}, {{{0,9}},181},
-    {{{0,8}},10}, {{{0,8}},138}, {{{0,8}},74}, {{{0,9}},245},
-    {{{80,7}},5}, {{{0,8}},86}, {{{0,8}},22}, {{{192,8}},0},
-    {{{83,7}},51}, {{{0,8}},118}, {{{0,8}},54}, {{{0,9}},205},
-    {{{81,7}},15}, {{{0,8}},102}, {{{0,8}},38}, {{{0,9}},173},
-    {{{0,8}},6}, {{{0,8}},134}, {{{0,8}},70}, {{{0,9}},237},
-    {{{80,7}},9}, {{{0,8}},94}, {{{0,8}},30}, {{{0,9}},157},
-    {{{84,7}},99}, {{{0,8}},126}, {{{0,8}},62}, {{{0,9}},221},
-    {{{82,7}},27}, {{{0,8}},110}, {{{0,8}},46}, {{{0,9}},189},
-    {{{0,8}},14}, {{{0,8}},142}, {{{0,8}},78}, {{{0,9}},253},
-    {{{96,7}},256}, {{{0,8}},81}, {{{0,8}},17}, {{{85,8}},131},
-    {{{82,7}},31}, {{{0,8}},113}, {{{0,8}},49}, {{{0,9}},195},
-    {{{80,7}},10}, {{{0,8}},97}, {{{0,8}},33}, {{{0,9}},163},
-    {{{0,8}},1}, {{{0,8}},129}, {{{0,8}},65}, {{{0,9}},227},
-    {{{80,7}},6}, {{{0,8}},89}, {{{0,8}},25}, {{{0,9}},147},
-    {{{83,7}},59}, {{{0,8}},121}, {{{0,8}},57}, {{{0,9}},211},
-    {{{81,7}},17}, {{{0,8}},105}, {{{0,8}},41}, {{{0,9}},179},
-    {{{0,8}},9}, {{{0,8}},137}, {{{0,8}},73}, {{{0,9}},243},
-    {{{80,7}},4}, {{{0,8}},85}, {{{0,8}},21}, {{{80,8}},258},
-    {{{83,7}},43}, {{{0,8}},117}, {{{0,8}},53}, {{{0,9}},203},
-    {{{81,7}},13}, {{{0,8}},101}, {{{0,8}},37}, {{{0,9}},171},
-    {{{0,8}},5}, {{{0,8}},133}, {{{0,8}},69}, {{{0,9}},235},
-    {{{80,7}},8}, {{{0,8}},93}, {{{0,8}},29}, {{{0,9}},155},
-    {{{84,7}},83}, {{{0,8}},125}, {{{0,8}},61}, {{{0,9}},219},
-    {{{82,7}},23}, {{{0,8}},109}, {{{0,8}},45}, {{{0,9}},187},
-    {{{0,8}},13}, {{{0,8}},141}, {{{0,8}},77}, {{{0,9}},251},
-    {{{80,7}},3}, {{{0,8}},83}, {{{0,8}},19}, {{{85,8}},195},
-    {{{83,7}},35}, {{{0,8}},115}, {{{0,8}},51}, {{{0,9}},199},
-    {{{81,7}},11}, {{{0,8}},99}, {{{0,8}},35}, {{{0,9}},167},
-    {{{0,8}},3}, {{{0,8}},131}, {{{0,8}},67}, {{{0,9}},231},
-    {{{80,7}},7}, {{{0,8}},91}, {{{0,8}},27}, {{{0,9}},151},
-    {{{84,7}},67}, {{{0,8}},123}, {{{0,8}},59}, {{{0,9}},215},
-    {{{82,7}},19}, {{{0,8}},107}, {{{0,8}},43}, {{{0,9}},183},
-    {{{0,8}},11}, {{{0,8}},139}, {{{0,8}},75}, {{{0,9}},247},
-    {{{80,7}},5}, {{{0,8}},87}, {{{0,8}},23}, {{{192,8}},0},
-    {{{83,7}},51}, {{{0,8}},119}, {{{0,8}},55}, {{{0,9}},207},
-    {{{81,7}},15}, {{{0,8}},103}, {{{0,8}},39}, {{{0,9}},175},
-    {{{0,8}},7}, {{{0,8}},135}, {{{0,8}},71}, {{{0,9}},239},
-    {{{80,7}},9}, {{{0,8}},95}, {{{0,8}},31}, {{{0,9}},159},
-    {{{84,7}},99}, {{{0,8}},127}, {{{0,8}},63}, {{{0,9}},223},
-    {{{82,7}},27}, {{{0,8}},111}, {{{0,8}},47}, {{{0,9}},191},
-    {{{0,8}},15}, {{{0,8}},143}, {{{0,8}},79}, {{{0,9}},255}
-  };
-static inflate_huft fixed_td[] = {
-    {{{80,5}},1}, {{{87,5}},257}, {{{83,5}},17}, {{{91,5}},4097},
-    {{{81,5}},5}, {{{89,5}},1025}, {{{85,5}},65}, {{{93,5}},16385},
-    {{{80,5}},3}, {{{88,5}},513}, {{{84,5}},33}, {{{92,5}},8193},
-    {{{82,5}},9}, {{{90,5}},2049}, {{{86,5}},129}, {{{192,5}},24577},
-    {{{80,5}},2}, {{{87,5}},385}, {{{83,5}},25}, {{{91,5}},6145},
-    {{{81,5}},7}, {{{89,5}},1537}, {{{85,5}},97}, {{{93,5}},24577},
-    {{{80,5}},4}, {{{88,5}},769}, {{{84,5}},49}, {{{92,5}},12289},
-    {{{82,5}},13}, {{{90,5}},3073}, {{{86,5}},193}, {{{192,5}},24577}
-  };
diff -Nru a/lib/zlib_inflate/inflate.c b/lib/zlib_inflate/inflate.c
--- a/lib/zlib_inflate/inflate.c	2004-10-18 14:56:32 -07:00
+++ b/lib/zlib_inflate/inflate.c	2004-10-18 14:56:32 -07:00
@@ -53,8 +53,6 @@
       return Z_VERSION_ERROR;
 
   /* initialize state */
-  if (z == NULL)
-    return Z_STREAM_ERROR;
   z->msg = NULL;
   z->state = &WS(z)->internal_state;
   z->state->blocks = NULL;
@@ -247,145 +245,4 @@
   z->msg = (char *)"need more for packet flush";
   z->state->sub.marker = 0;       /* can try inflateSync */
   return Z_DATA_ERROR;
-}
-
-
-int zlib_inflateSync(
-	z_streamp z
-)
-{
-  uInt n;       /* number of bytes to look at */
-  Byte *p;      /* pointer to bytes */
-  uInt m;       /* number of marker bytes found in a row */
-  uLong r, w;   /* temporaries to save total_in and total_out */
-
-  /* set up */
-  if (z == NULL || z->state == NULL)
-    return Z_STREAM_ERROR;
-  if (z->state->mode != I_BAD)
-  {
-    z->state->mode = I_BAD;
-    z->state->sub.marker = 0;
-  }
-  if ((n = z->avail_in) == 0)
-    return Z_BUF_ERROR;
-  p = z->next_in;
-  m = z->state->sub.marker;
-
-  /* search */
-  while (n && m < 4)
-  {
-    static const Byte mark[4] = {0, 0, 0xff, 0xff};
-    if (*p == mark[m])
-      m++;
-    else if (*p)
-      m = 0;
-    else
-      m = 4 - m;
-    p++, n--;
-  }
-
-  /* restore */
-  z->total_in += p - z->next_in;
-  z->next_in = p;
-  z->avail_in = n;
-  z->state->sub.marker = m;
-
-  /* return no joy or set up to restart on a new block */
-  if (m != 4)
-    return Z_DATA_ERROR;
-  r = z->total_in;  w = z->total_out;
-  zlib_inflateReset(z);
-  z->total_in = r;  z->total_out = w;
-  z->state->mode = BLOCKS;
-  return Z_OK;
-}
-
-
-/* Returns true if inflate is currently at the end of a block generated
- * by Z_SYNC_FLUSH or Z_FULL_FLUSH. This function is used by one PPP
- * implementation to provide an additional safety check. PPP uses Z_SYNC_FLUSH
- * but removes the length bytes of the resulting empty stored block. When
- * decompressing, PPP checks that at the end of input packet, inflate is
- * waiting for these length bytes.
- */
-int zlib_inflateSyncPoint(
-	z_streamp z
-)
-{
-  if (z == NULL || z->state == NULL || z->state->blocks == NULL)
-    return Z_STREAM_ERROR;
-  return zlib_inflate_blocks_sync_point(z->state->blocks);
-}
-
-/*
- * This subroutine adds the data at next_in/avail_in to the output history
- * without performing any output.  The output buffer must be "caught up";
- * i.e. no pending output (hence s->read equals s->write), and the state must
- * be BLOCKS (i.e. we should be willing to see the start of a series of
- * BLOCKS).  On exit, the output will also be caught up, and the checksum
- * will have been updated if need be.
- */
-static int zlib_inflate_addhistory(inflate_blocks_statef *s,
-				      z_stream              *z)
-{
-    uLong b;              /* bit buffer */  /* NOT USED HERE */
-    uInt k;               /* bits in bit buffer */ /* NOT USED HERE */
-    uInt t;               /* temporary storage */
-    Byte *p;              /* input data pointer */
-    uInt n;               /* bytes available there */
-    Byte *q;              /* output window write pointer */
-    uInt m;               /* bytes to end of window or read pointer */
-
-    if (s->read != s->write)
-	return Z_STREAM_ERROR;
-    if (s->mode != TYPE)
-	return Z_DATA_ERROR;
-
-    /* we're ready to rock */
-    LOAD
-    /* while there is input ready, copy to output buffer, moving
-     * pointers as needed.
-     */
-    while (n) {
-	t = n;  /* how many to do */
-	/* is there room until end of buffer? */
-	if (t > m) t = m;
-	/* update check information */
-	if (s->checkfn != NULL)
-	    s->check = (*s->checkfn)(s->check, q, t);
-	memcpy(q, p, t);
-	q += t;
-	p += t;
-	n -= t;
-	z->total_out += t;
-	s->read = q;    /* drag read pointer forward */
-/*      WWRAP  */ 	/* expand WWRAP macro by hand to handle s->read */
-	if (q == s->end) {
-	    s->read = q = s->window;
-	    m = WAVAIL;
-	}
-    }
-    UPDATE
-    return Z_OK;
-}
-
-
-/*
- * This subroutine adds the data at next_in/avail_in to the output history
- * without performing any output.  The output buffer must be "caught up";
- * i.e. no pending output (hence s->read equals s->write), and the state must
- * be BLOCKS (i.e. we should be willing to see the start of a series of
- * BLOCKS).  On exit, the output will also be caught up, and the checksum
- * will have been updated if need be.
- */
-
-int zlib_inflateIncomp(
-	z_stream *z
-	
-)
-{
-    if (z->state->mode != BLOCKS)
-	return Z_DATA_ERROR;
-    return zlib_inflate_addhistory(z->state->blocks, z);
 }
diff -Nru a/lib/zlib_inflate/inflate_sync.c b/lib/zlib_inflate/inflate_sync.c
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/lib/zlib_inflate/inflate_sync.c	2004-10-18 14:57:22 -07:00
@@ -0,0 +1,148 @@
+/* inflate.c -- zlib interface to inflate modules
+ * Copyright (C) 1995-1998 Mark Adler
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+#include <linux/zutil.h>
+#include "infblock.h"
+#include "infutil.h"
+
+int zlib_inflateSync(
+	z_streamp z
+)
+{
+  uInt n;       /* number of bytes to look at */
+  Byte *p;      /* pointer to bytes */
+  uInt m;       /* number of marker bytes found in a row */
+  uLong r, w;   /* temporaries to save total_in and total_out */
+
+  /* set up */
+  if (z == NULL || z->state == NULL)
+    return Z_STREAM_ERROR;
+  if (z->state->mode != I_BAD)
+  {
+    z->state->mode = I_BAD;
+    z->state->sub.marker = 0;
+  }
+  if ((n = z->avail_in) == 0)
+    return Z_BUF_ERROR;
+  p = z->next_in;
+  m = z->state->sub.marker;
+
+  /* search */
+  while (n && m < 4)
+  {
+    static const Byte mark[4] = {0, 0, 0xff, 0xff};
+    if (*p == mark[m])
+      m++;
+    else if (*p)
+      m = 0;
+    else
+      m = 4 - m;
+    p++, n--;
+  }
+
+  /* restore */
+  z->total_in += p - z->next_in;
+  z->next_in = p;
+  z->avail_in = n;
+  z->state->sub.marker = m;
+
+  /* return no joy or set up to restart on a new block */
+  if (m != 4)
+    return Z_DATA_ERROR;
+  r = z->total_in;  w = z->total_out;
+  zlib_inflateReset(z);
+  z->total_in = r;  z->total_out = w;
+  z->state->mode = BLOCKS;
+  return Z_OK;
+}
+
+
+/* Returns true if inflate is currently at the end of a block generated
+ * by Z_SYNC_FLUSH or Z_FULL_FLUSH. This function is used by one PPP
+ * implementation to provide an additional safety check. PPP uses Z_SYNC_FLUSH
+ * but removes the length bytes of the resulting empty stored block. When
+ * decompressing, PPP checks that at the end of input packet, inflate is
+ * waiting for these length bytes.
+ */
+int zlib_inflateSyncPoint(
+	z_streamp z
+)
+{
+  if (z == NULL || z->state == NULL || z->state->blocks == NULL)
+    return Z_STREAM_ERROR;
+  return zlib_inflate_blocks_sync_point(z->state->blocks);
+}
+
+/*
+ * This subroutine adds the data at next_in/avail_in to the output history
+ * without performing any output.  The output buffer must be "caught up";
+ * i.e. no pending output (hence s->read equals s->write), and the state must
+ * be BLOCKS (i.e. we should be willing to see the start of a series of
+ * BLOCKS).  On exit, the output will also be caught up, and the checksum
+ * will have been updated if need be.
+ */
+static int zlib_inflate_addhistory(inflate_blocks_statef *s,
+				      z_stream              *z)
+{
+    uLong b;              /* bit buffer */  /* NOT USED HERE */
+    uInt k;               /* bits in bit buffer */ /* NOT USED HERE */
+    uInt t;               /* temporary storage */
+    Byte *p;              /* input data pointer */
+    uInt n;               /* bytes available there */
+    Byte *q;              /* output window write pointer */
+    uInt m;               /* bytes to end of window or read pointer */
+
+    if (s->read != s->write)
+	return Z_STREAM_ERROR;
+    if (s->mode != TYPE)
+	return Z_DATA_ERROR;
+
+    /* we're ready to rock */
+    LOAD
+    /* while there is input ready, copy to output buffer, moving
+     * pointers as needed.
+     */
+    while (n) {
+	t = n;  /* how many to do */
+	/* is there room until end of buffer? */
+	if (t > m) t = m;
+	/* update check information */
+	if (s->checkfn != NULL)
+	    s->check = (*s->checkfn)(s->check, q, t);
+	memcpy(q, p, t);
+	q += t;
+	p += t;
+	n -= t;
+	z->total_out += t;
+	s->read = q;    /* drag read pointer forward */
+/*      WWRAP  */ 	/* expand WWRAP macro by hand to handle s->read */
+	if (q == s->end) {
+	    s->read = q = s->window;
+	    m = WAVAIL;
+	}
+    }
+    UPDATE
+    return Z_OK;
+}
+
+
+/*
+ * This subroutine adds the data at next_in/avail_in to the output history
+ * without performing any output.  The output buffer must be "caught up";
+ * i.e. no pending output (hence s->read equals s->write), and the state must
+ * be BLOCKS (i.e. we should be willing to see the start of a series of
+ * BLOCKS).  On exit, the output will also be caught up, and the checksum
+ * will have been updated if need be.
+ */
+
+int zlib_inflateIncomp(
+	z_stream *z
+
+)
+{
+    if (z->state->mode != BLOCKS)
+	return Z_DATA_ERROR;
+    return zlib_inflate_addhistory(z->state->blocks, z);
+}
diff -Nru a/lib/zlib_inflate/inftrees.c b/lib/zlib_inflate/inftrees.c
--- a/lib/zlib_inflate/inftrees.c	2004-10-18 14:56:50 -07:00
+++ b/lib/zlib_inflate/inftrees.c	2004-10-18 14:56:50 -07:00
@@ -374,21 +374,39 @@
 }
 
 
-/* build fixed tables only once--keep them here */
-#include "inffixed.h"
-
-
 int zlib_inflate_trees_fixed(
 	uInt *bl,                /* literal desired/actual bit depth */
 	uInt *bd,                /* distance desired/actual bit depth */
 	inflate_huft **tl,       /* literal/length tree result */
 	inflate_huft **td,       /* distance tree result */
+	inflate_huft *hp,       /* space for trees */
 	z_streamp z              /* for memory allocation */
 )
 {
-  *bl = fixed_bl;
-  *bd = fixed_bd;
-  *tl = fixed_tl;
-  *td = fixed_td;
+  int i;                /* temporary variable */
+  unsigned l[288];      /* length list for huft_build */
+  uInt *v;              /* work area for huft_build */
+
+  /* set up literal table */
+  for (i = 0; i < 144; i++)
+    l[i] = 8;
+  for (; i < 256; i++)
+    l[i] = 9;
+  for (; i < 280; i++)
+    l[i] = 7;
+  for (; i < 288; i++)          /* make a complete, but wrong code set */
+    l[i] = 8;
+  *bl = 9;
+  v = WS(z)->tree_work_area_1;
+  if ((i = huft_build(l, 288, 257, cplens, cplext, tl, bl, hp,  &i, v)) != 0)
+    return i;
+
+  /* set up distance table */
+  for (i = 0; i < 30; i++)      /* make an incomplete code set */
+    l[i] = 5;
+  *bd = 5;
+  if ((i = huft_build(l, 30, 0, cpdist, cpdext, td, bd, hp, &i, v)) > 1)
+    return i;
+
   return Z_OK;
 }
diff -Nru a/lib/zlib_inflate/inftrees.h b/lib/zlib_inflate/inftrees.h
--- a/lib/zlib_inflate/inftrees.h	2004-10-18 14:57:05 -07:00
+++ b/lib/zlib_inflate/inftrees.h	2004-10-18 14:57:05 -07:00
@@ -58,6 +58,7 @@
     uInt *,                     /* distance desired/actual bit depth */
     inflate_huft **,            /* literal/length tree result */
     inflate_huft **,            /* distance tree result */
+    inflate_huft *,             /* space for trees */
     z_streamp);                 /* for memory allocation */
 
 #endif /* _INFTREES_H */
diff -Nru a/mm/Makefile b/mm/Makefile
--- a/mm/Makefile	2004-10-18 14:56:33 -07:00
+++ b/mm/Makefile	2004-10-18 14:56:33 -07:00
@@ -5,13 +5,16 @@
 mmu-y			:= nommu.o
 mmu-$(CONFIG_MMU)	:= fremap.o highmem.o madvise.o memory.o mincore.o \
 			   mlock.o mmap.o mprotect.o mremap.o msync.o rmap.o \
-			   shmem.o vmalloc.o
+			   vmalloc.o
 
 obj-y			:= bootmem.o filemap.o mempool.o oom_kill.o fadvise.o \
 			   page_alloc.o page-writeback.o pdflush.o prio_tree.o \
 			   readahead.o slab.o swap.o truncate.o vmscan.o \
 			   $(mmu-y)
 
-obj-$(CONFIG_SWAP)	+= page_io.o swap_state.o swapfile.o
+obj-$(CONFIG_SWAP)	+= page_io.o swap_state.o swapfile.o thrash.o
 obj-$(CONFIG_HUGETLBFS)	+= hugetlb.o
 obj-$(CONFIG_NUMA) 	+= mempolicy.o
+obj-$(CONFIG_SHMEM) += shmem.o
+obj-$(CONFIG_TINY_SHMEM) += tiny-shmem.o
+
diff -Nru a/mm/bootmem.c b/mm/bootmem.c
--- a/mm/bootmem.c	2004-10-18 14:56:28 -07:00
+++ b/mm/bootmem.c	2004-10-18 14:56:28 -07:00
@@ -259,6 +259,7 @@
 	unsigned long i, count, total = 0;
 	unsigned long idx;
 	unsigned long *map; 
+	int gofast = 0;
 
 	BUG_ON(!bdata->node_bootmem_map);
 
@@ -267,14 +268,32 @@
 	page = virt_to_page(phys_to_virt(bdata->node_boot_start));
 	idx = bdata->node_low_pfn - (bdata->node_boot_start >> PAGE_SHIFT);
 	map = bdata->node_bootmem_map;
+	/* Check physaddr is O(LOG2(BITS_PER_LONG)) page aligned */
+	if (bdata->node_boot_start == 0 ||
+	    ffs(bdata->node_boot_start) - PAGE_SHIFT > ffs(BITS_PER_LONG))
+		gofast = 1;
 	for (i = 0; i < idx; ) {
 		unsigned long v = ~map[i / BITS_PER_LONG];
-		if (v) {
+		if (gofast && v == ~0UL) {
+			int j;
+
+			count += BITS_PER_LONG;
+			__ClearPageReserved(page);
+			set_page_count(page, 1);
+			for (j = 1; j < BITS_PER_LONG; j++) {
+				if (j + 16 < BITS_PER_LONG)
+					prefetchw(page + j + 16);
+				__ClearPageReserved(page + j);
+			}
+			__free_pages(page, ffs(BITS_PER_LONG)-1);
+			i += BITS_PER_LONG;
+			page += BITS_PER_LONG;
+		} else if (v) {
 			unsigned long m;
 			for (m = 1; m && i < idx; m<<=1, page++, i++) {
 				if (v & m) {
 					count++;
-					ClearPageReserved(page);
+					__ClearPageReserved(page);
 					set_page_count(page, 1);
 					__free_page(page);
 				}
@@ -294,7 +313,7 @@
 	count = 0;
 	for (i = 0; i < ((bdata->node_low_pfn-(bdata->node_boot_start >> PAGE_SHIFT))/8 + PAGE_SIZE-1)/PAGE_SIZE; i++,page++) {
 		count++;
-		ClearPageReserved(page);
+		__ClearPageReserved(page);
 		set_page_count(page, 1);
 		__free_page(page);
 	}
diff -Nru a/mm/filemap.c b/mm/filemap.c
--- a/mm/filemap.c	2004-10-18 14:57:19 -07:00
+++ b/mm/filemap.c	2004-10-18 14:57:19 -07:00
@@ -60,7 +60,6 @@
  *      ->swap_list_lock
  *        ->swap_device_lock	(exclusive_swap_page, others)
  *          ->mapping->tree_lock
- *    ->page_map_lock()		(try_to_unmap_file)
  *
  *  ->i_sem
  *    ->i_mmap_lock		(truncate->unmap_mapping_range)
@@ -83,16 +82,20 @@
  *    ->sb_lock			(fs/fs-writeback.c)
  *    ->mapping->tree_lock	(__sync_single_inode)
  *
+ *  ->i_mmap_lock
+ *    ->anon_vma.lock		(vma_adjust)
+ *
+ *  ->anon_vma.lock
+ *    ->page_table_lock		(anon_vma_prepare and various)
+ *
  *  ->page_table_lock
  *    ->swap_device_lock	(try_to_unmap_one)
  *    ->private_lock		(try_to_unmap_one)
  *    ->tree_lock		(try_to_unmap_one)
  *    ->zone.lru_lock		(follow_page->mark_page_accessed)
- *    ->page_map_lock()		(page_add_anon_rmap)
- *      ->tree_lock		(page_remove_rmap->set_page_dirty)
- *      ->private_lock		(page_remove_rmap->set_page_dirty)
- *      ->inode_lock		(page_remove_rmap->set_page_dirty)
- *    ->anon_vma.lock		(anon_vma_prepare)
+ *    ->private_lock		(page_remove_rmap->set_page_dirty)
+ *    ->tree_lock		(page_remove_rmap->set_page_dirty)
+ *    ->inode_lock		(page_remove_rmap->set_page_dirty)
  *    ->inode_lock		(zap_pte_range->set_page_dirty)
  *    ->private_lock		(zap_pte_range->__set_page_dirty_buffers)
  *
@@ -142,20 +145,26 @@
 }
 
 /**
- * filemap_fdatawrite - start writeback against all of a mapping's dirty pages
+ * filemap_fdatawrite_range - start writeback against all of a mapping's
+ * dirty pages that lie within the byte offsets <start, end>
  * @mapping: address space structure to write
+ * @start: offset in bytes where the range starts
+ * @end : offset in bytes where the range ends
  *
  * If sync_mode is WB_SYNC_ALL then this is a "data integrity" operation, as
  * opposed to a regular memory * cleansing writeback.  The difference between
  * these two operations is that if a dirty page/buffer is encountered, it must
  * be waited upon, and not just skipped over.
  */
-static int __filemap_fdatawrite(struct address_space *mapping, int sync_mode)
+static int __filemap_fdatawrite_range(struct address_space *mapping,
+	loff_t start, loff_t end, int sync_mode)
 {
 	int ret;
 	struct writeback_control wbc = {
 		.sync_mode = sync_mode,
 		.nr_to_write = mapping->nrpages * 2,
+		.start = start,
+		.end = end,
 	};
 
 	if (mapping->backing_dev_info->memory_backed)
@@ -165,12 +174,25 @@
 	return ret;
 }
 
+static inline int __filemap_fdatawrite(struct address_space *mapping,
+	int sync_mode)
+{
+	return __filemap_fdatawrite_range(mapping, 0, 0, sync_mode);
+}
+
 int filemap_fdatawrite(struct address_space *mapping)
 {
 	return __filemap_fdatawrite(mapping, WB_SYNC_ALL);
 }
 EXPORT_SYMBOL(filemap_fdatawrite);
 
+int filemap_fdatawrite_range(struct address_space *mapping,
+	loff_t start, loff_t end)
+{
+	return __filemap_fdatawrite_range(mapping, start, end, WB_SYNC_ALL);
+}
+EXPORT_SYMBOL(filemap_fdatawrite_range);
+
 /*
  * This is a mostly non-blocking flush.  Not suitable for data-integrity
  * purposes - I/O may not be started against all dirty pages.
@@ -198,7 +220,8 @@
 
 	pagevec_init(&pvec, 0);
 	index = start;
-	while ((nr_pages = pagevec_lookup_tag(&pvec, mapping, &index,
+	while ((index <= end) &&
+			(nr_pages = pagevec_lookup_tag(&pvec, mapping, &index,
 			PAGECACHE_TAG_WRITEBACK,
 			min(end - index, (pgoff_t)PAGEVEC_SIZE-1) + 1)) != 0) {
 		unsigned i;
@@ -206,6 +229,10 @@
 		for (i = 0; i < nr_pages; i++) {
 			struct page *page = pvec.pages[i];
 
+			/* until radix tree lookup accepts end_index */
+			if (page->index > end)
+				continue;
+
 			wait_on_page_writeback(page);
 			if (PageError(page))
 				ret = -EIO;
@@ -223,6 +250,35 @@
 	return ret;
 }
 
+/*
+ * Write and wait upon all the pages in the passed range.  This is a "data
+ * integrity" operation.  It waits upon in-flight writeout before starting and
+ * waiting upon new writeout.  If there was an IO error, return it.
+ *
+ * We need to re-take i_sem during the generic_osync_inode list walk because
+ * it is otherwise livelockable.
+ */
+int sync_page_range(struct inode *inode, struct address_space *mapping,
+			loff_t pos, size_t count)
+{
+	pgoff_t start = pos >> PAGE_CACHE_SHIFT;
+	pgoff_t end = (pos + count - 1) >> PAGE_CACHE_SHIFT;
+	int ret;
+
+	if (mapping->backing_dev_info->memory_backed || !count)
+		return 0;
+	ret = filemap_fdatawrite_range(mapping, pos, pos + count - 1);
+	if (ret == 0) {
+		down(&inode->i_sem);
+		ret = generic_osync_inode(inode, mapping, OSYNC_METADATA);
+		up(&inode->i_sem);
+	}
+	if (ret == 0)
+		ret = wait_on_page_writeback_range(mapping, start, end);
+	return ret;
+}
+EXPORT_SYMBOL(sync_page_range);
+
 /**
  * filemap_fdatawait - walk the list of under-writeback pages of the given
  *     address space and wait for all of them.
@@ -231,9 +287,14 @@
  */
 int filemap_fdatawait(struct address_space *mapping)
 {
-	return wait_on_page_writeback_range(mapping, 0, -1);
-}
+	loff_t i_size = i_size_read(mapping->host);
+
+	if (i_size == 0)
+		return 0;
 
+	return wait_on_page_writeback_range(mapping, 0,
+				(i_size - 1) >> PAGE_CACHE_SHIFT);
+}
 EXPORT_SYMBOL(filemap_fdatawait);
 
 int filemap_write_and_wait(struct address_space *mapping)
@@ -644,13 +705,15 @@
  *
  * This is really ugly. But the goto's actually try to clarify some
  * of the logic when it comes to error handling etc.
- * - note the struct file * is only passed for the use of readpage
+ *
+ * Note the struct file* is only passed for the use of readpage.  It may be
+ * NULL.
  */
 void do_generic_mapping_read(struct address_space *mapping,
 			     struct file_ra_state *_ra,
-			     struct file * filp,
+			     struct file *filp,
 			     loff_t *ppos,
-			     read_descriptor_t * desc,
+			     read_descriptor_t *desc,
 			     read_actor_t actor)
 {
 	struct inode *inode = mapping->host;
@@ -665,14 +728,26 @@
 	offset = *ppos & ~PAGE_CACHE_MASK;
 
 	isize = i_size_read(inode);
-	end_index = isize >> PAGE_CACHE_SHIFT;
-	if (index > end_index)
+	if (!isize)
 		goto out;
 
+	end_index = (isize - 1) >> PAGE_CACHE_SHIFT;
 	for (;;) {
 		struct page *page;
 		unsigned long nr, ret;
 
+		/* nr is the maximum number of bytes to copy from this page */
+		nr = PAGE_CACHE_SIZE;
+		if (index >= end_index) {
+			if (index > end_index)
+				goto out;
+			nr = ((isize - 1) & ~PAGE_CACHE_MASK) + 1;
+			if (nr <= offset) {
+				goto out;
+			}
+		}
+		nr = nr - offset;
+
 		cond_resched();
 		page_cache_readahead(mapping, &ra, filp, index);
 
@@ -685,16 +760,6 @@
 		if (!PageUptodate(page))
 			goto page_not_up_to_date;
 page_ok:
-		/* nr is the maximum number of bytes to copy from this page */
-		nr = PAGE_CACHE_SIZE;
-		if (index == end_index) {
-			nr = isize & ~PAGE_CACHE_MASK;
-			if (nr <= offset) {
-				page_cache_release(page);
-				goto out;
-			}
-		}
-		nr = nr - offset;
 
 		/* If users can be writing to this page using arbitrary
 		 * virtual addresses, take care about potential aliasing
@@ -770,11 +835,22 @@
 		 * another truncate extends the file - this is desired though).
 		 */
 		isize = i_size_read(inode);
-		end_index = isize >> PAGE_CACHE_SHIFT;
-		if (index > end_index) {
+		end_index = (isize - 1) >> PAGE_CACHE_SHIFT;
+		if (unlikely(!isize || index > end_index)) {
 			page_cache_release(page);
 			goto out;
 		}
+
+		/* nr is the maximum number of bytes to copy from this page */
+		nr = PAGE_CACHE_SIZE;
+		if (index == end_index) {
+			nr = ((isize - 1) & ~PAGE_CACHE_MASK) + 1;
+			if (nr <= offset) {
+				page_cache_release(page);
+				goto out;
+			}
+		}
+		nr = nr - offset;
 		goto page_ok;
 
 readpage_error:
@@ -814,7 +890,8 @@
 	*ppos = ((loff_t) index << PAGE_CACHE_SHIFT) + offset;
 	if (cached_page)
 		page_cache_release(cached_page);
-	file_accessed(filp);
+	if (filp)
+		file_accessed(filp);
 }
 
 EXPORT_SYMBOL(do_generic_mapping_read);
@@ -834,7 +911,8 @@
 	 */
 	if (!fault_in_pages_writeable(desc->arg.buf, size)) {
 		kaddr = kmap_atomic(page, KM_USER0);
-		left = __copy_to_user(desc->arg.buf, kaddr + offset, size);
+		left = __copy_to_user_inatomic(desc->arg.buf,
+						kaddr + offset, size);
 		kunmap_atomic(kaddr, KM_USER0);
 		if (left == 0)
 			goto success;
@@ -1195,6 +1273,7 @@
 	 * effect.
 	 */
 	error = page_cache_read(file, pgoff);
+	grab_swap_token();
 
 	/*
 	 * The page we want has now been added to the page cache.
@@ -1431,7 +1510,7 @@
 	return 0;
 }
 
-static struct vm_operations_struct generic_file_vm_ops = {
+struct vm_operations_struct generic_file_vm_ops = {
 	.nopage		= filemap_nopage,
 	.populate	= filemap_populate,
 };
@@ -1630,7 +1709,7 @@
 	int left;
 
 	kaddr = kmap_atomic(page, KM_USER0);
-	left = __copy_from_user(kaddr + offset, buf, bytes);
+	left = __copy_from_user_inatomic(kaddr + offset, buf, bytes);
 	kunmap_atomic(kaddr, KM_USER0);
 
 	if (left != 0) {
@@ -1653,7 +1732,7 @@
 		int copy = min(bytes, iov->iov_len - base);
 
 		base = 0;
-		left = __copy_from_user(vaddr, buf, copy);
+		left = __copy_from_user_inatomic(vaddr, buf, copy);
 		copied += copy;
 		bytes -= copy;
 		vaddr += copy;
@@ -1802,116 +1881,64 @@
 
 EXPORT_SYMBOL(generic_write_checks);
 
-/*
- * Write to a file through the page cache. 
- * Called under i_sem for S_ISREG files.
- *
- * We put everything into the page cache prior to writing it. This is not a
- * problem when writing full pages. With partial pages, however, we first have
- * to read the data into the cache, then dirty the page, and finally schedule
- * it for writing by marking it dirty.
- *							okir@monad.swb.de
- */
 ssize_t
-generic_file_aio_write_nolock(struct kiocb *iocb, const struct iovec *iov,
-				unsigned long nr_segs, loff_t *ppos)
+generic_file_direct_write(struct kiocb *iocb, const struct iovec *iov,
+		unsigned long *nr_segs, loff_t pos, loff_t *ppos,
+		size_t count, size_t ocount)
+{
+	struct file	*file = iocb->ki_filp;
+	struct address_space *mapping = file->f_mapping;
+	struct inode	*inode = mapping->host;
+	ssize_t		written;
+
+	if (count != ocount)
+		*nr_segs = iov_shorten((struct iovec *)iov, *nr_segs, count);
+
+	written = generic_file_direct_IO(WRITE, iocb, iov, pos, *nr_segs);
+	if (written > 0) {
+		loff_t end = pos + written;
+		if (end > i_size_read(inode) && !S_ISBLK(inode->i_mode)) {
+			i_size_write(inode,  end);
+			mark_inode_dirty(inode);
+		}
+		*ppos = end;
+	}
+
+	/*
+	 * Sync the fs metadata but not the minor inode changes and
+	 * of course not the data as we did direct DMA for the IO.
+	 * i_sem is held, which protects generic_osync_inode() from
+	 * livelocking.
+	 */
+	if (written >= 0 && file->f_flags & O_SYNC)
+		generic_osync_inode(inode, mapping, OSYNC_METADATA);
+	if (written == count && !is_sync_kiocb(iocb))
+		written = -EIOCBQUEUED;
+	return written;
+}
+
+EXPORT_SYMBOL(generic_file_direct_write);
+
+ssize_t
+generic_file_buffered_write(struct kiocb *iocb, const struct iovec *iov,
+		unsigned long nr_segs, loff_t pos, loff_t *ppos,
+		size_t count, ssize_t written)
 {
 	struct file *file = iocb->ki_filp;
 	struct address_space * mapping = file->f_mapping;
 	struct address_space_operations *a_ops = mapping->a_ops;
-	size_t ocount;		/* original count */
-	size_t count;		/* after file limit checks */
 	struct inode 	*inode = mapping->host;
 	long		status = 0;
-	loff_t		pos;
 	struct page	*page;
 	struct page	*cached_page = NULL;
-	const int	isblk = S_ISBLK(inode->i_mode);
-	ssize_t		written;
-	ssize_t		err;
 	size_t		bytes;
 	struct pagevec	lru_pvec;
 	const struct iovec *cur_iov = iov; /* current iovec */
 	size_t		iov_base = 0;	   /* offset in the current iovec */
-	unsigned long	seg;
 	char __user	*buf;
 
-	ocount = 0;
-	for (seg = 0; seg < nr_segs; seg++) {
-		const struct iovec *iv = &iov[seg];
-
-		/*
-		 * If any segment has a negative length, or the cumulative
-		 * length ever wraps negative then return -EINVAL.
-		 */
-		ocount += iv->iov_len;
-		if (unlikely((ssize_t)(ocount|iv->iov_len) < 0))
-			return -EINVAL;
-		if (access_ok(VERIFY_READ, iv->iov_base, iv->iov_len))
-			continue;
-		if (seg == 0)
-			return -EFAULT;
-		nr_segs = seg;
-		ocount -= iv->iov_len;	/* This segment is no good */
-		break;
-	}
-
-	count = ocount;
-	pos = *ppos;
 	pagevec_init(&lru_pvec, 0);
 
-	/* We can write back this queue in page reclaim */
-	current->backing_dev_info = mapping->backing_dev_info;
-	written = 0;
-
-	err = generic_write_checks(file, &pos, &count, isblk);
-	if (err)
-		goto out;
-
-	if (count == 0)
-		goto out;
-
-	err = remove_suid(file->f_dentry);
-	if (err)
-		goto out;
-
-	inode_update_time(inode, 1);
-
-	/* coalesce the iovecs and go direct-to-BIO for O_DIRECT */
-	if (unlikely(file->f_flags & O_DIRECT)) {
-		if (count != ocount)
-			nr_segs = iov_shorten((struct iovec *)iov,
-						nr_segs, count);
-		written = generic_file_direct_IO(WRITE, iocb,
-					iov, pos, nr_segs);
-		if (written > 0) {
-			loff_t end = pos + written;
-			if (end > i_size_read(inode) && !isblk) {
-				i_size_write(inode,  end);
-				mark_inode_dirty(inode);
-			}
-			*ppos = end;
-		}
-		/*
-		 * Sync the fs metadata but not the minor inode changes and
-		 * of course not the data as we did direct DMA for the IO.
-		 * i_sem is held, which protects generic_osync_inode() from
-		 * livelocking.
-		 */
-		if (written >= 0 && file->f_flags & O_SYNC)
-			status = generic_osync_inode(inode, mapping, OSYNC_METADATA);
-		if (written == count && !is_sync_kiocb(iocb))
-			written = -EIOCBQUEUED;
-		if (written < 0 || written == count)
-			goto out_status;
-		/*
-		 * direct-io write to a hole: fall through to buffered I/O
-		 * for completing the rest of the request.
-		 */
-		pos += written;
-		count -= written;
-	}
-
 	buf = iov->iov_base + written;	/* handle partial DIO write */
 	do {
 		unsigned long index;
@@ -1992,11 +2019,13 @@
 	/*
 	 * For now, when the user asks for O_SYNC, we'll actually give O_DSYNC
 	 */
-	if (status >= 0) {
-		if ((file->f_flags & O_SYNC) || IS_SYNC(inode))
-			status = generic_osync_inode(inode, mapping,
-					OSYNC_METADATA|OSYNC_DATA);
-	}
+	if (likely(status >= 0)) {
+		if (unlikely((file->f_flags & O_SYNC) || IS_SYNC(inode))) {
+			if (!a_ops->writepage || !is_sync_kiocb(iocb))
+				status = generic_osync_inode(inode, mapping,
+						OSYNC_METADATA|OSYNC_DATA);
+		}
+  	}
 	
 	/*
 	 * If we get here for O_DIRECT writes then we must have fallen through
@@ -2006,12 +2035,85 @@
 	if (unlikely(file->f_flags & O_DIRECT) && written)
 		status = filemap_write_and_wait(mapping);
 
-out_status:	
-	err = written ? written : status;
-out:
 	pagevec_lru_add(&lru_pvec);
+	return written ? written : status;
+}
+
+EXPORT_SYMBOL(generic_file_buffered_write);
+
+ssize_t
+generic_file_aio_write_nolock(struct kiocb *iocb, const struct iovec *iov,
+				unsigned long nr_segs, loff_t *ppos)
+{
+	struct file *file = iocb->ki_filp;
+	struct address_space * mapping = file->f_mapping;
+	size_t ocount;		/* original count */
+	size_t count;		/* after file limit checks */
+	struct inode 	*inode = mapping->host;
+	unsigned long	seg;
+	loff_t		pos;
+	ssize_t		written;
+	ssize_t		err;
+
+	ocount = 0;
+	for (seg = 0; seg < nr_segs; seg++) {
+		const struct iovec *iv = &iov[seg];
+
+		/*
+		 * If any segment has a negative length, or the cumulative
+		 * length ever wraps negative then return -EINVAL.
+		 */
+		ocount += iv->iov_len;
+		if (unlikely((ssize_t)(ocount|iv->iov_len) < 0))
+			return -EINVAL;
+		if (access_ok(VERIFY_READ, iv->iov_base, iv->iov_len))
+			continue;
+		if (seg == 0)
+			return -EFAULT;
+		nr_segs = seg;
+		ocount -= iv->iov_len;	/* This segment is no good */
+		break;
+	}
+
+	count = ocount;
+	pos = *ppos;
+
+	/* We can write back this queue in page reclaim */
+	current->backing_dev_info = mapping->backing_dev_info;
+	written = 0;
+
+	err = generic_write_checks(file, &pos, &count, S_ISBLK(inode->i_mode));
+	if (err)
+		goto out;
+
+	if (count == 0)
+		goto out;
+
+	err = remove_suid(file->f_dentry);
+	if (err)
+		goto out;
+
+	inode_update_time(inode, 1);
+
+	/* coalesce the iovecs and go direct-to-BIO for O_DIRECT */
+	if (unlikely(file->f_flags & O_DIRECT)) {
+		written = generic_file_direct_write(iocb, iov,
+				&nr_segs, pos, ppos, count, ocount);
+		if (written < 0 || written == count)
+			goto out;
+		/*
+		 * direct-io write to a hole: fall through to buffered I/O
+		 * for completing the rest of the request.
+		 */
+		pos += written;
+		count -= written;
+	}
+
+	written = generic_file_buffered_write(iocb, iov, nr_segs,
+			pos, ppos, count, written);
+out:
 	current->backing_dev_info = NULL;
-	return err;
+	return written ? written : err;
 }
 
 EXPORT_SYMBOL(generic_file_aio_write_nolock);
@@ -2036,36 +2138,52 @@
 			       size_t count, loff_t pos)
 {
 	struct file *file = iocb->ki_filp;
-	struct inode *inode = file->f_mapping->host;
-	ssize_t err;
-	struct iovec local_iov = { .iov_base = (void __user *)buf, .iov_len = count };
+	struct address_space *mapping = file->f_mapping;
+	struct inode *inode = mapping->host;
+	ssize_t ret;
+	struct iovec local_iov = { .iov_base = (void __user *)buf,
+					.iov_len = count };
 
 	BUG_ON(iocb->ki_pos != pos);
 
 	down(&inode->i_sem);
-	err = generic_file_aio_write_nolock(iocb, &local_iov, 1, 
+	ret = generic_file_aio_write_nolock(iocb, &local_iov, 1,
 						&iocb->ki_pos);
 	up(&inode->i_sem);
 
-	return err;
-}
+	if (ret > 0 && ((file->f_flags & O_SYNC) || IS_SYNC(inode))) {
+		ssize_t err;
 
+		err = sync_page_range(inode, mapping, pos, ret);
+		if (err < 0)
+			ret = err;
+	}
+	return ret;
+}
 EXPORT_SYMBOL(generic_file_aio_write);
 
 ssize_t generic_file_write(struct file *file, const char __user *buf,
 			   size_t count, loff_t *ppos)
 {
-	struct inode	*inode = file->f_mapping->host;
-	ssize_t		err;
-	struct iovec local_iov = { .iov_base = (void __user *)buf, .iov_len = count };
+	struct address_space *mapping = file->f_mapping;
+	struct inode *inode = mapping->host;
+	ssize_t	ret;
+	struct iovec local_iov = { .iov_base = (void __user *)buf,
+					.iov_len = count };
 
 	down(&inode->i_sem);
-	err = generic_file_write_nolock(file, &local_iov, 1, ppos);
+	ret = generic_file_write_nolock(file, &local_iov, 1, ppos);
 	up(&inode->i_sem);
 
-	return err;
-}
+	if (ret > 0 && ((file->f_flags & O_SYNC) || IS_SYNC(inode))) {
+		ssize_t err;
 
+		err = sync_page_range(inode, mapping, *ppos - ret, ret);
+		if (err < 0)
+			ret = err;
+	}
+	return ret;
+}
 EXPORT_SYMBOL(generic_file_write);
 
 ssize_t generic_file_readv(struct file *filp, const struct iovec *iov,
@@ -2084,14 +2202,23 @@
 EXPORT_SYMBOL(generic_file_readv);
 
 ssize_t generic_file_writev(struct file *file, const struct iovec *iov,
-			unsigned long nr_segs, loff_t * ppos) 
+			unsigned long nr_segs, loff_t *ppos)
 {
-	struct inode *inode = file->f_mapping->host;
+	struct address_space *mapping = file->f_mapping;
+	struct inode *inode = mapping->host;
 	ssize_t ret;
 
 	down(&inode->i_sem);
 	ret = generic_file_write_nolock(file, iov, nr_segs, ppos);
 	up(&inode->i_sem);
+
+	if (ret > 0 && ((file->f_flags & O_SYNC) || IS_SYNC(inode))) {
+		int err;
+
+		err = sync_page_range(inode, mapping, *ppos - ret, ret);
+		if (err < 0)
+			ret = err;
+	}
 	return ret;
 }
 
diff -Nru a/mm/fremap.c b/mm/fremap.c
--- a/mm/fremap.c	2004-10-18 14:55:54 -07:00
+++ b/mm/fremap.c	2004-10-18 14:55:54 -07:00
@@ -220,9 +220,7 @@
 			flush_dcache_mmap_lock(mapping);
 			vma->vm_flags |= VM_NONLINEAR;
 			vma_prio_tree_remove(vma, &mapping->i_mmap);
-			vma_prio_tree_init(vma);
-			list_add_tail(&vma->shared.vm_set.list,
-					&mapping->i_mmap_nonlinear);
+			vma_nonlinear_insert(vma, &mapping->i_mmap_nonlinear);
 			flush_dcache_mmap_unlock(mapping);
 			spin_unlock(&mapping->i_mmap_lock);
 		}
diff -Nru a/mm/highmem.c b/mm/highmem.c
--- a/mm/highmem.c	2004-10-18 14:56:33 -07:00
+++ b/mm/highmem.c	2004-10-18 14:56:33 -07:00
@@ -284,7 +284,7 @@
 	struct bio_vec *tovec, *fromvec;
 	int i;
 
-	bio_for_each_segment(tovec, to, i) {
+	__bio_for_each_segment(tovec, to, i, 0) {
 		fromvec = from->bi_io_vec + i;
 
 		/*
@@ -300,6 +300,7 @@
 		 */
 		vfrom = page_address(fromvec->bv_page) + tovec->bv_offset;
 
+		flush_dcache_page(tovec->bv_page);
 		bounce_copy_vec(tovec, vfrom);
 	}
 }
@@ -316,7 +317,7 @@
 	/*
 	 * free up bounce indirect pages used
 	 */
-	bio_for_each_segment(bvec, bio, i) {
+	__bio_for_each_segment(bvec, bio, i, 0) {
 		org_vec = bio_orig->bi_io_vec + i;
 		if (bvec->bv_page == org_vec->bv_page)
 			continue;
@@ -406,6 +407,7 @@
 		if (rw == WRITE) {
 			char *vto, *vfrom;
 
+			flush_dcache_page(from->bv_page);
 			vto = page_address(to->bv_page) + to->bv_offset;
 			vfrom = kmap(from->bv_page) + from->bv_offset;
 			memcpy(vto, vfrom, to->bv_len);
diff -Nru a/mm/hugetlb.c b/mm/hugetlb.c
--- a/mm/hugetlb.c	2004-10-18 14:56:33 -07:00
+++ b/mm/hugetlb.c	2004-10-18 14:56:33 -07:00
@@ -21,7 +21,7 @@
 
 static void enqueue_huge_page(struct page *page)
 {
-	int nid = page_zone(page)->zone_pgdat->node_id;
+	int nid = page_to_nid(page);
 	list_add(&page->lru, &hugepage_freelists[nid]);
 	free_huge_pages++;
 	free_huge_pages_node[nid]++;
@@ -52,7 +52,7 @@
 {
 	static int nid = 0;
 	struct page *page;
-	page = alloc_pages_node(nid, GFP_HIGHUSER|__GFP_COMP,
+	page = alloc_pages_node(nid, GFP_HIGHUSER|__GFP_COMP|__GFP_NOWARN,
 					HUGETLB_PAGE_ORDER);
 	nid = (nid + 1) % numnodes;
 	if (page) {
@@ -123,6 +123,7 @@
 }
 __setup("hugepages=", hugetlb_setup);
 
+#ifdef CONFIG_SYSCTL
 static void update_and_free_page(struct page *page)
 {
 	int i;
@@ -188,7 +189,6 @@
 	return nr_huge_pages;
 }
 
-#ifdef CONFIG_SYSCTL
 int hugetlb_sysctl_handler(struct ctl_table *table, int write,
 			   struct file *file, void __user *buffer,
 			   size_t *length, loff_t *ppos)
diff -Nru a/mm/memory.c b/mm/memory.c
--- a/mm/memory.c	2004-10-18 14:56:29 -07:00
+++ b/mm/memory.c	2004-10-18 14:56:29 -07:00
@@ -1123,12 +1123,12 @@
 static inline void unmap_mapping_range_list(struct prio_tree_root *root,
 					    struct zap_details *details)
 {
-	struct vm_area_struct *vma = NULL;
+	struct vm_area_struct *vma;
 	struct prio_tree_iter iter;
 	pgoff_t vba, vea, zba, zea;
 
-	while ((vma = vma_prio_tree_next(vma, root, &iter,
-			details->first_index, details->last_index)) != NULL) {
+	vma_prio_tree_foreach(vma, &iter, root,
+			details->first_index, details->last_index) {
 		vba = vma->vm_pgoff;
 		vea = vba + ((vma->vm_end - vma->vm_start) >> PAGE_SHIFT) - 1;
 		/* Assume for now that PAGE_CACHE_SHIFT == PAGE_SHIFT */
@@ -1351,6 +1351,7 @@
 		/* Had to read the page from swap area: Major fault */
 		ret = VM_FAULT_MAJOR;
 		inc_page_state(pgmajfault);
+		grab_swap_token();
 	}
 
 	mark_page_accessed(page);
@@ -1743,6 +1744,8 @@
 	struct vm_area_struct * vma;
 
 	vma = find_vma(current->mm, addr);
+	if (!vma)
+		return -1;
 	write = (vma->vm_flags & VM_WRITE) != 0;
 	if (addr >= end)
 		BUG();
diff -Nru a/mm/mempolicy.c b/mm/mempolicy.c
--- a/mm/mempolicy.c	2004-10-18 14:57:04 -07:00
+++ b/mm/mempolicy.c	2004-10-18 14:57:04 -07:00
@@ -146,6 +146,8 @@
 	/* When the user specified more nodes than supported just check
 	   if the non supported part is all zero. */
 	if (nlongs > BITS_TO_LONGS(MAX_NUMNODES)) {
+		if (nlongs > PAGE_SIZE/sizeof(long))
+			return -EINVAL;
 		for (k = BITS_TO_LONGS(MAX_NUMNODES); k < nlongs; k++) {
 			unsigned long t;
 			if (get_user(t,  nmask + k))
@@ -438,7 +440,7 @@
 
 	err = get_user_pages(current, mm, addr & PAGE_MASK, 1, 0, 0, &p, NULL);
 	if (err >= 0) {
-		err = page_zone(p)->zone_pgdat->node_id;
+		err = page_to_nid(p);
 		put_page(p);
 	}
 	return err;
@@ -526,20 +528,82 @@
 }
 
 #ifdef CONFIG_COMPAT
-/* The other functions are compatible */
+
 asmlinkage long compat_get_mempolicy(int __user *policy,
-				  unsigned __user *nmask, unsigned  maxnode,
-				  unsigned addr, unsigned  flags)
+				     compat_ulong_t __user *nmask,
+				     compat_ulong_t maxnode,
+				     compat_ulong_t addr, compat_ulong_t flags)
 {
 	long err;
 	unsigned long __user *nm = NULL;
+	unsigned long nr_bits, alloc_size;
+	DECLARE_BITMAP(bm, MAX_NUMNODES);
+
+	nr_bits = min_t(unsigned long, maxnode-1, MAX_NUMNODES);
+	alloc_size = ALIGN(nr_bits, BITS_PER_LONG) / 8;
+
 	if (nmask)
-		nm = compat_alloc_user_space(ALIGN(maxnode-1, 64) / 8);
-	err = sys_get_mempolicy(policy, nm, maxnode, addr, flags);
-	if (!err && copy_in_user(nmask, nm, ALIGN(maxnode-1, 32)/8))
-		err = -EFAULT;
+		nm = compat_alloc_user_space(alloc_size);
+
+	err = sys_get_mempolicy(policy, nm, nr_bits+1, addr, flags);
+
+	if (!err && nmask) {
+		err = copy_from_user(bm, nm, alloc_size);
+		/* ensure entire bitmap is zeroed */
+		err |= clear_user(nmask, ALIGN(maxnode-1, 8) / 8);
+		err |= compat_put_bitmap(nmask, bm, nr_bits);
+	}
+
 	return err;
 }
+
+asmlinkage long compat_set_mempolicy(int mode, compat_ulong_t __user *nmask,
+				     compat_ulong_t maxnode)
+{
+	long err = 0;
+	unsigned long __user *nm = NULL;
+	unsigned long nr_bits, alloc_size;
+	DECLARE_BITMAP(bm, MAX_NUMNODES);
+
+	nr_bits = min_t(unsigned long, maxnode-1, MAX_NUMNODES);
+	alloc_size = ALIGN(nr_bits, BITS_PER_LONG) / 8;
+
+	if (nmask) {
+		err = compat_get_bitmap(bm, nmask, nr_bits);
+		nm = compat_alloc_user_space(alloc_size);
+		err |= copy_to_user(nm, bm, alloc_size);
+	}
+
+	if (err)
+		return -EFAULT;
+
+	return sys_set_mempolicy(mode, nm, nr_bits+1);
+}
+
+asmlinkage long compat_mbind(compat_ulong_t start, compat_ulong_t len,
+			     compat_ulong_t mode, compat_ulong_t __user *nmask,
+			     compat_ulong_t maxnode, compat_ulong_t flags)
+{
+	long err = 0;
+	unsigned long __user *nm = NULL;
+	unsigned long nr_bits, alloc_size;
+	DECLARE_BITMAP(bm, MAX_NUMNODES);
+
+	nr_bits = min_t(unsigned long, maxnode-1, MAX_NUMNODES);
+	alloc_size = ALIGN(nr_bits, BITS_PER_LONG) / 8;
+
+	if (nmask) {
+		err = compat_get_bitmap(bm, nmask, nr_bits);
+		nm = compat_alloc_user_space(alloc_size);
+		err |= copy_to_user(nm, bm, alloc_size);
+	}
+
+	if (err)
+		return -EFAULT;
+
+	return sys_mbind(start, len, mode, nm, nr_bits+1, flags);
+}
+
 #endif
 
 /* Return effective policy for a VMA */
diff -Nru a/mm/mempool.c b/mm/mempool.c
--- a/mm/mempool.c	2004-10-18 14:56:33 -07:00
+++ b/mm/mempool.c	2004-10-18 14:56:33 -07:00
@@ -194,6 +194,7 @@
 	DEFINE_WAIT(wait);
 	int gfp_nowait = gfp_mask & ~(__GFP_WAIT | __GFP_IO);
 
+	might_sleep_if(gfp_mask & __GFP_WAIT);
 repeat_alloc:
 	element = pool->alloc(gfp_nowait|__GFP_NOWARN, pool->pool_data);
 	if (likely(element != NULL))
diff -Nru a/mm/mlock.c b/mm/mlock.c
--- a/mm/mlock.c	2004-10-18 14:55:54 -07:00
+++ b/mm/mlock.c	2004-10-18 14:55:54 -07:00
@@ -60,8 +60,6 @@
 	struct vm_area_struct * vma, * next;
 	int error;
 
-	if (on && !capable(CAP_IPC_LOCK))
-		return -EPERM;
 	len = PAGE_ALIGN(len);
 	end = start + len;
 	if (end < start)
@@ -107,6 +105,9 @@
 	unsigned long lock_limit;
 	int error = -ENOMEM;
 
+	if (!can_do_mlock())
+		return -EPERM;
+
 	down_write(&current->mm->mmap_sem);
 	len = PAGE_ALIGN(len + (start & ~PAGE_MASK));
 	start &= PAGE_MASK;
@@ -118,7 +119,7 @@
 	lock_limit >>= PAGE_SHIFT;
 
 	/* check against resource limits */
-	if (locked <= lock_limit)
+	if ((locked <= lock_limit) || capable(CAP_IPC_LOCK))
 		error = do_mlock(start, len, 1);
 	up_write(&current->mm->mmap_sem);
 	return error;
@@ -138,19 +139,15 @@
 
 static int do_mlockall(int flags)
 {
-	int error;
-	unsigned int def_flags;
 	struct vm_area_struct * vma;
+	unsigned int def_flags = 0;
 
-	if (!capable(CAP_IPC_LOCK))
-		return -EPERM;
-
-	def_flags = 0;
 	if (flags & MCL_FUTURE)
 		def_flags = VM_LOCKED;
 	current->mm->def_flags = def_flags;
+	if (flags == MCL_FUTURE)
+		goto out;
 
-	error = 0;
 	for (vma = current->mm->mmap; vma ; vma = vma->vm_next) {
 		unsigned int newflags;
 
@@ -161,7 +158,8 @@
 		/* Ignore errors */
 		mlock_fixup(vma, vma->vm_start, vma->vm_end, newflags);
 	}
-	return error;
+out:
+	return 0;
 }
 
 asmlinkage long sys_mlockall(int flags)
@@ -169,18 +167,24 @@
 	unsigned long lock_limit;
 	int ret = -EINVAL;
 
-	down_write(&current->mm->mmap_sem);
 	if (!flags || (flags & ~(MCL_CURRENT | MCL_FUTURE)))
 		goto out;
 
+	ret = -EPERM;
+	if (!can_do_mlock())
+		goto out;
+
+	down_write(&current->mm->mmap_sem);
+
 	lock_limit = current->rlim[RLIMIT_MEMLOCK].rlim_cur;
 	lock_limit >>= PAGE_SHIFT;
 
 	ret = -ENOMEM;
-	if (current->mm->total_vm <= lock_limit)
+	if (!(flags & MCL_CURRENT) || (current->mm->total_vm <= lock_limit) ||
+	    capable(CAP_IPC_LOCK))
 		ret = do_mlockall(flags);
-out:
 	up_write(&current->mm->mmap_sem);
+out:
 	return ret;
 }
 
@@ -192,4 +196,37 @@
 	ret = do_mlockall(0);
 	up_write(&current->mm->mmap_sem);
 	return ret;
+}
+
+/*
+ * Objects with different lifetime than processes (SHM_LOCK and SHM_HUGETLB
+ * shm segments) get accounted against the user_struct instead.
+ */
+static spinlock_t shmlock_user_lock = SPIN_LOCK_UNLOCKED;
+
+int user_shm_lock(size_t size, struct user_struct *user)
+{
+	unsigned long lock_limit, locked;
+	int allowed = 0;
+
+	spin_lock(&shmlock_user_lock);
+	locked = size >> PAGE_SHIFT;
+	lock_limit = current->rlim[RLIMIT_MEMLOCK].rlim_cur;
+	lock_limit >>= PAGE_SHIFT;
+	if (locked + user->locked_shm > lock_limit && !capable(CAP_IPC_LOCK))
+		goto out;
+	get_uid(user);
+	user->locked_shm += locked;
+	allowed = 1;
+out:
+	spin_unlock(&shmlock_user_lock);
+	return allowed;
+}
+
+void user_shm_unlock(size_t size, struct user_struct *user)
+{
+	spin_lock(&shmlock_user_lock);
+	user->locked_shm -= (size >> PAGE_SHIFT);
+	spin_unlock(&shmlock_user_lock);
+	free_uid(user);
 }
diff -Nru a/mm/mmap.c b/mm/mmap.c
--- a/mm/mmap.c	2004-10-18 14:56:33 -07:00
+++ b/mm/mmap.c	2004-10-18 14:56:33 -07:00
@@ -54,7 +54,7 @@
 	__S000, __S001, __S010, __S011, __S100, __S101, __S110, __S111
 };
 
-int sysctl_overcommit_memory = 0;	/* default is heuristic overcommit */
+int sysctl_overcommit_memory = OVERCOMMIT_GUESS;  /* heuristic overcommit */
 int sysctl_overcommit_ratio = 50;	/* default is 50% */
 int sysctl_max_map_count = DEFAULT_MAX_MAP_COUNT;
 atomic_t vm_committed_space = ATOMIC_INIT(0);
@@ -90,6 +90,7 @@
 {
 	struct file *file = vma->vm_file;
 
+	might_sleep();
 	if (file) {
 		struct address_space *mapping = file->f_mapping;
 		spin_lock(&mapping->i_mmap_lock);
@@ -279,8 +280,7 @@
 
 		flush_dcache_mmap_lock(mapping);
 		if (unlikely(vma->vm_flags & VM_NONLINEAR))
-			list_add_tail(&vma->shared.vm_set.list,
-					&mapping->i_mmap_nonlinear);
+			vma_nonlinear_insert(vma, &mapping->i_mmap_nonlinear);
 		else
 			vma_prio_tree_insert(vma, &mapping->i_mmap);
 		flush_dcache_mmap_unlock(mapping);
@@ -449,11 +449,8 @@
 	}
 
 	if (root) {
-		if (adjust_next) {
-			vma_prio_tree_init(next);
+		if (adjust_next)
 			vma_prio_tree_insert(next, root);
-		}
-		vma_prio_tree_init(vma);
 		vma_prio_tree_insert(vma, root);
 		flush_dcache_mmap_unlock(mapping);
 	}
@@ -732,6 +729,32 @@
 	return NULL;
 }
 
+#ifdef CONFIG_PROC_FS
+void __vm_stat_account(struct mm_struct *mm, unsigned long flags,
+						struct file *file, long pages)
+{
+	const unsigned long stack_flags
+		= VM_STACK_FLAGS & (VM_GROWSUP|VM_GROWSDOWN);
+
+#ifdef CONFIG_HUGETLB
+	if (flags & VM_HUGETLB) {
+		if (!(flags & VM_DONTCOPY))
+			mm->shared_vm += pages;
+		return;
+	}
+#endif /* CONFIG_HUGETLB */
+
+	if (file)
+		mm->shared_vm += pages;
+	else if (flags & stack_flags)
+		mm->stack_vm += pages;
+	if (flags & VM_EXEC)
+		mm->exec_vm += pages;
+	if (flags & (VM_RESERVED|VM_IO))
+		mm->reserved_vm += pages;
+}
+#endif /* CONFIG_PROC_FS */
+
 /*
  * The caller must hold down_write(current->mm->mmap_sem).
  */
@@ -750,13 +773,6 @@
 	int accountable = 1;
 	unsigned long charged = 0;
 
-	/*
-	 * Does the application expect PROT_READ to imply PROT_EXEC:
-	 */
-	if (unlikely((prot & PROT_READ) &&
-			(current->personality & READ_IMPLIES_EXEC)))
-		prot |= PROT_EXEC;
-
 	if (file) {
 		if (is_file_hugepages(file))
 			accountable = 0;
@@ -768,6 +784,15 @@
 		    (file->f_vfsmnt->mnt_flags & MNT_NOEXEC))
 			return -EPERM;
 	}
+	/*
+	 * Does the application expect PROT_READ to imply PROT_EXEC?
+	 *
+	 * (the exception is when the underlying filesystem is noexec
+	 *  mounted, in which case we dont add PROT_EXEC.)
+	 */
+	if ((prot & PROT_READ) && (current->personality & READ_IMPLIES_EXEC))
+		if (!(file && (file->f_vfsmnt->mnt_flags & MNT_NOEXEC)))
+			prot |= PROT_EXEC;
 
 	if (!len)
 		return addr;
@@ -800,15 +825,17 @@
 			mm->def_flags | VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC;
 
 	if (flags & MAP_LOCKED) {
-		if (!capable(CAP_IPC_LOCK))
+		if (!can_do_mlock())
 			return -EPERM;
 		vm_flags |= VM_LOCKED;
 	}
 	/* mlock MCL_FUTURE? */
 	if (vm_flags & VM_LOCKED) {
-		unsigned long locked = mm->locked_vm << PAGE_SHIFT;
+		unsigned long locked, lock_limit;
+		locked = mm->locked_vm << PAGE_SHIFT;
+		lock_limit = current->rlim[RLIMIT_MEMLOCK].rlim_cur;
 		locked += len;
-		if (locked > current->rlim[RLIMIT_MEMLOCK].rlim_cur)
+		if (locked > lock_limit && !capable(CAP_IPC_LOCK))
 			return -EAGAIN;
 	}
 
@@ -882,7 +909,7 @@
 		return -ENOMEM;
 
 	if (accountable && (!(flags & MAP_NORESERVE) ||
-			sysctl_overcommit_memory > 1)) {
+			    sysctl_overcommit_memory == OVERCOMMIT_NEVER)) {
 		if (vm_flags & VM_SHARED) {
 			/* Check memory availability in shmem_file_setup? */
 			vm_flags |= VM_ACCOUNT;
@@ -988,6 +1015,7 @@
 					pgoff, flags & MAP_NONBLOCK);
 		down_write(&mm->mmap_sem);
 	}
+	__vm_stat_account(mm, vm_flags, file, len >> PAGE_SHIFT);
 	return addr;
 
 unmap_and_free_vma:
@@ -1020,7 +1048,7 @@
  * This function "knows" that -ENOMEM has the bits set.
  */
 #ifndef HAVE_ARCH_UNMAPPED_AREA
-static inline unsigned long
+unsigned long
 arch_get_unmapped_area(struct file *filp, unsigned long addr,
 		unsigned long len, unsigned long pgoff, unsigned long flags)
 {
@@ -1064,12 +1092,118 @@
 		addr = vma->vm_end;
 	}
 }
-#else
-extern unsigned long
-arch_get_unmapped_area(struct file *, unsigned long, unsigned long,
-			unsigned long, unsigned long);
 #endif	
 
+void arch_unmap_area(struct vm_area_struct *area)
+{
+	/*
+	 * Is this a new hole at the lowest possible address?
+	 */
+	if (area->vm_start >= TASK_UNMAPPED_BASE &&
+			area->vm_start < area->vm_mm->free_area_cache)
+		area->vm_mm->free_area_cache = area->vm_start;
+}
+
+/*
+ * This mmap-allocator allocates new areas top-down from below the
+ * stack's low limit (the base):
+ */
+#ifndef HAVE_ARCH_UNMAPPED_AREA_TOPDOWN
+unsigned long
+arch_get_unmapped_area_topdown(struct file *filp, const unsigned long addr0,
+			  const unsigned long len, const unsigned long pgoff,
+			  const unsigned long flags)
+{
+	struct vm_area_struct *vma, *prev_vma;
+	struct mm_struct *mm = current->mm;
+	unsigned long base = mm->mmap_base, addr = addr0;
+	int first_time = 1;
+
+	/* requested length too big for entire address space */
+	if (len > TASK_SIZE)
+		return -ENOMEM;
+
+	/* dont allow allocations above current base */
+	if (mm->free_area_cache > base)
+		mm->free_area_cache = base;
+
+	/* requesting a specific address */
+	if (addr) {
+		addr = PAGE_ALIGN(addr);
+		vma = find_vma(mm, addr);
+		if (TASK_SIZE - len >= addr &&
+				(!vma || addr + len <= vma->vm_start))
+			return addr;
+	}
+
+try_again:
+	/* make sure it can fit in the remaining address space */
+	if (mm->free_area_cache < len)
+		goto fail;
+
+	/* either no address requested or cant fit in requested address hole */
+	addr = (mm->free_area_cache - len) & PAGE_MASK;
+	do {
+		/*
+		 * Lookup failure means no vma is above this address,
+		 * i.e. return with success:
+		 */
+ 	 	if (!(vma = find_vma_prev(mm, addr, &prev_vma)))
+			return addr;
+
+		/*
+		 * new region fits between prev_vma->vm_end and
+		 * vma->vm_start, use it:
+		 */
+		if (addr+len <= vma->vm_start &&
+				(!prev_vma || (addr >= prev_vma->vm_end)))
+			/* remember the address as a hint for next time */
+			return (mm->free_area_cache = addr);
+		else
+			/* pull free_area_cache down to the first hole */
+			if (mm->free_area_cache == vma->vm_end)
+				mm->free_area_cache = vma->vm_start;
+
+		/* try just below the current vma->vm_start */
+		addr = vma->vm_start-len;
+	} while (len <= vma->vm_start);
+
+fail:
+	/*
+	 * if hint left us with no space for the requested
+	 * mapping then try again:
+	 */
+	if (first_time) {
+		mm->free_area_cache = base;
+		first_time = 0;
+		goto try_again;
+	}
+	/*
+	 * A failed mmap() very likely causes application failure,
+	 * so fall back to the bottom-up function here. This scenario
+	 * can happen with large stack limits and large mmap()
+	 * allocations.
+	 */
+	mm->free_area_cache = TASK_UNMAPPED_BASE;
+	addr = arch_get_unmapped_area(filp, addr0, len, pgoff, flags);
+	/*
+	 * Restore the topdown base:
+	 */
+	mm->free_area_cache = base;
+
+	return addr;
+}
+#endif
+
+void arch_unmap_area_topdown(struct vm_area_struct *area)
+{
+	/*
+	 * Is this a new hole at the highest possible address?
+	 */
+	if (area->vm_end > area->vm_mm->free_area_cache)
+		area->vm_mm->free_area_cache = area->vm_end;
+}
+
 unsigned long
 get_unmapped_area(struct file *file, unsigned long addr, unsigned long len,
 		unsigned long pgoff, unsigned long flags)
@@ -1104,7 +1238,7 @@
 		return file->f_op->get_unmapped_area(file, addr, len,
 						pgoff, flags);
 
-	return arch_get_unmapped_area(file, addr, len, pgoff, flags);
+	return current->mm->get_unmapped_area(file, addr, len, pgoff, flags);
 }
 
 EXPORT_SYMBOL(get_unmapped_area);
@@ -1227,6 +1361,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);
 	anon_vma_unlock(vma);
 	return 0;
 }
@@ -1289,6 +1424,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);
 	anon_vma_unlock(vma);
 	return 0;
 }
@@ -1394,13 +1530,8 @@
 	area->vm_mm->total_vm -= len >> PAGE_SHIFT;
 	if (area->vm_flags & VM_LOCKED)
 		area->vm_mm->locked_vm -= len >> PAGE_SHIFT;
-	/*
-	 * Is this a new hole at the lowest possible address?
-	 */
-	if (area->vm_start >= TASK_UNMAPPED_BASE &&
-				area->vm_start < area->vm_mm->free_area_cache)
-	      area->vm_mm->free_area_cache = area->vm_start;
-
+	vm_stat_unaccount(area);
+	area->vm_mm->unmap_area(area);
 	remove_vm_struct(area);
 }
 
@@ -1489,7 +1620,6 @@
 
 	/* most fields are the same, copy all, and then fixup */
 	*new = *vma;
-	vma_prio_tree_init(new);
 
 	if (new_below)
 		new->vm_end = addr;
@@ -1554,10 +1684,6 @@
 	if (mpnt->vm_start >= end)
 		return 0;
 
-	/* Something will probably happen, so notify. */
-	if (mpnt->vm_file && (mpnt->vm_flags & VM_EXEC))
-		profile_exec_unmap(mm);
- 
 	/*
 	 * If we need to split any vma, do it now to save pain later.
 	 *
@@ -1600,6 +1726,8 @@
 	int ret;
 	struct mm_struct *mm = current->mm;
 
+	profile_munmap(addr);
+
 	down_write(&mm->mmap_sem);
 	ret = do_munmap(mm, addr, len);
 	up_write(&mm->mmap_sem);
@@ -1630,9 +1758,11 @@
 	 * mlock MCL_FUTURE?
 	 */
 	if (mm->def_flags & VM_LOCKED) {
-		unsigned long locked = mm->locked_vm << PAGE_SHIFT;
+		unsigned long locked, lock_limit;
+		locked = mm->locked_vm << PAGE_SHIFT;
+		lock_limit = current->rlim[RLIMIT_MEMLOCK].rlim_cur;
 		locked += len;
-		if (locked > current->rlim[RLIMIT_MEMLOCK].rlim_cur)
+		if (locked > lock_limit && !capable(CAP_IPC_LOCK))
 			return -EAGAIN;
 	}
 
@@ -1700,8 +1830,6 @@
 	struct vm_area_struct *vma;
 	unsigned long nr_accounted = 0;
 
-	profile_exit_mmap(mm);
- 
 	lru_add_drain();
 
 	spin_lock(&mm->page_table_lock);
@@ -1802,7 +1930,6 @@
 		new_vma = kmem_cache_alloc(vm_area_cachep, SLAB_KERNEL);
 		if (new_vma) {
 			*new_vma = *vma;
-			vma_prio_tree_init(new_vma);
 			pol = mpol_copy(vma_policy(vma));
 			if (IS_ERR(pol)) {
 				kmem_cache_free(vm_area_cachep, new_vma);
diff -Nru a/mm/mprotect.c b/mm/mprotect.c
--- a/mm/mprotect.c	2004-10-18 14:57:19 -07:00
+++ b/mm/mprotect.c	2004-10-18 14:57:19 -07:00
@@ -175,9 +175,11 @@
 	 * vm_flags and vm_page_prot are protected by the mmap_sem
 	 * held in write mode.
 	 */
+	vm_stat_unaccount(vma);
 	vma->vm_flags = newflags;
 	vma->vm_page_prot = newprot;
 	change_protection(vma, start, end, newprot);
+	vm_stat_account(vma);
 	return 0;
 
 fail:
diff -Nru a/mm/mremap.c b/mm/mremap.c
--- a/mm/mremap.c	2004-10-18 14:56:32 -07:00
+++ b/mm/mremap.c	2004-10-18 14:56:32 -07:00
@@ -224,6 +224,7 @@
 	}
 
 	mm->total_vm += new_len >> PAGE_SHIFT;
+	__vm_stat_account(mm, vma->vm_flags, vma->vm_file, new_len>>PAGE_SHIFT);
 	if (vm_flags & VM_LOCKED) {
 		mm->locked_vm += new_len >> PAGE_SHIFT;
 		if (new_len > old_len)
@@ -324,10 +325,12 @@
 			goto out;
 	}
 	if (vma->vm_flags & VM_LOCKED) {
-		unsigned long locked = current->mm->locked_vm << PAGE_SHIFT;
+		unsigned long locked, lock_limit;
+		locked = current->mm->locked_vm << PAGE_SHIFT;
+		lock_limit = current->rlim[RLIMIT_MEMLOCK].rlim_cur;
 		locked += new_len - old_len;
 		ret = -EAGAIN;
-		if (locked > current->rlim[RLIMIT_MEMLOCK].rlim_cur)
+		if (locked > lock_limit && !capable(CAP_IPC_LOCK))
 			goto out;
 	}
 	ret = -ENOMEM;
@@ -358,6 +361,8 @@
 				addr + new_len, vma->vm_pgoff, NULL);
 
 			current->mm->total_vm += pages;
+			__vm_stat_account(vma->vm_mm, vma->vm_flags,
+							vma->vm_file, pages);
 			if (vma->vm_flags & VM_LOCKED) {
 				current->mm->locked_vm += pages;
 				make_pages_present(addr + old_len,
diff -Nru a/mm/nommu.c b/mm/nommu.c
--- a/mm/nommu.c	2004-10-18 14:56:50 -07:00
+++ b/mm/nommu.c	2004-10-18 14:56:50 -07:00
@@ -30,7 +30,7 @@
 unsigned long num_physpages;
 unsigned long askedalloc, realalloc;
 atomic_t vm_committed_space = ATOMIC_INIT(0);
-int sysctl_overcommit_memory; /* default is heuristic overcommit */
+int sysctl_overcommit_memory = OVERCOMMIT_GUESS; /* heuristic overcommit */
 int sysctl_overcommit_ratio = 50; /* default is 50% */
 
 int sysctl_max_map_count = DEFAULT_MAX_MAP_COUNT;
diff -Nru a/mm/oom_kill.c b/mm/oom_kill.c
--- a/mm/oom_kill.c	2004-10-18 14:56:32 -07:00
+++ b/mm/oom_kill.c	2004-10-18 14:56:32 -07:00
@@ -26,6 +26,7 @@
 /**
  * oom_badness - calculate a numeric value for how bad this task has been
  * @p: task struct of which task we should calculate
+ * @p: current uptime in seconds
  *
  * The formula used is relatively simple and documented inline in the
  * function. The main rationale is that we want to select a good task
@@ -41,9 +42,9 @@
  *    of least surprise ... (be careful when you change it)
  */
 
-static int badness(struct task_struct *p)
+static unsigned long badness(struct task_struct *p, unsigned long uptime)
 {
-	int points, cpu_time, run_time, s;
+	unsigned long points, cpu_time, run_time, s;
 
 	if (!p->mm)
 		return 0;
@@ -56,12 +57,16 @@
 	points = p->mm->total_vm;
 
 	/*
-	 * CPU time is in seconds and run time is in minutes. There is no
-	 * particular reason for this other than that it turned out to work
-	 * very well in practice.
+	 * CPU time is in tens of seconds and run time is in thousands
+         * of seconds. There is no particular reason for this other than
+         * that it turned out to work very well in practice.
 	 */
 	cpu_time = (p->utime + p->stime) >> (SHIFT_HZ + 3);
-	run_time = (get_jiffies_64() - p->start_time) >> (SHIFT_HZ + 10);
+
+	if (uptime >= p->start_time.tv_sec)
+		run_time = (uptime - p->start_time.tv_sec) >> 10;
+	else
+		run_time = 0;
 
 	s = int_sqrt(cpu_time);
 	if (s)
@@ -108,13 +113,15 @@
  */
 static struct task_struct * select_bad_process(void)
 {
-	int maxpoints = 0;
+	unsigned long maxpoints = 0;
 	struct task_struct *g, *p;
 	struct task_struct *chosen = NULL;
+	struct timespec uptime;
 
+	do_posix_clock_monotonic_gettime(&uptime);
 	do_each_thread(g, p)
 		if (p->pid) {
-			int points = badness(p);
+			unsigned long points = badness(p, uptime.tv_sec);
 			if (points > maxpoints) {
 				chosen = p;
 				maxpoints = points;
diff -Nru a/mm/page_alloc.c b/mm/page_alloc.c
--- a/mm/page_alloc.c	2004-10-18 14:55:54 -07:00
+++ b/mm/page_alloc.c	2004-10-18 14:55:54 -07:00
@@ -55,8 +55,8 @@
 static char *zone_names[MAX_NR_ZONES] = { "DMA", "Normal", "HighMem" };
 int min_free_kbytes = 1024;
 
-static unsigned long __initdata nr_kernel_pages;
-static unsigned long __initdata nr_all_pages;
+unsigned long __initdata nr_kernel_pages;
+unsigned long __initdata nr_all_pages;
 
 /*
  * Temporary debugging check for pages not lying within a given zone.
@@ -76,9 +76,9 @@
 {
 	printk(KERN_EMERG "Bad page state at %s (in process '%s', page %p)\n",
 		function, current->comm, page);
-	printk(KERN_EMERG "flags:0x%08lx mapping:%p mapcount:%d count:%d\n",
-		(unsigned long)page->flags, page->mapping,
-		(int)page->mapcount, page_count(page));
+	printk(KERN_EMERG "flags:0x%0*lx mapping:%p mapcount:%d count:%d\n",
+		(int)(2*sizeof(page_flags_t)), (unsigned long)page->flags,
+		page->mapping, page_mapcount(page), page_count(page));
 	printk(KERN_EMERG "Backtrace:\n");
 	dump_stack();
 	printk(KERN_EMERG "Trying to fix it up, but a reboot is needed\n");
@@ -87,13 +87,11 @@
 			1 << PG_lru	|
 			1 << PG_active	|
 			1 << PG_dirty	|
-			1 << PG_maplock |
-			1 << PG_anon    |
 			1 << PG_swapcache |
 			1 << PG_writeback);
 	set_page_count(page, 0);
+	reset_page_mapcount(page);
 	page->mapping = NULL;
-	page->mapcount = 0;
 }
 
 #ifndef CONFIG_HUGETLB_PAGE
@@ -229,8 +227,6 @@
 			1 << PG_active	|
 			1 << PG_reclaim	|
 			1 << PG_slab	|
-			1 << PG_maplock |
-			1 << PG_anon    |
 			1 << PG_swapcache |
 			1 << PG_writeback )))
 		bad_page(function, page);
@@ -279,6 +275,8 @@
 	LIST_HEAD(list);
 	int i;
 
+	arch_free_page(page, order);
+
 	mod_page_state(pgfree, 1 << order);
 	for (i = 0 ; i < (1 << order) ; ++i)
 		free_pages_check(__FUNCTION__, page + i);
@@ -350,8 +348,6 @@
 			1 << PG_active	|
 			1 << PG_dirty	|
 			1 << PG_reclaim	|
-			1 << PG_maplock |
-			1 << PG_anon    |
 			1 << PG_swapcache |
 			1 << PG_writeback )))
 		bad_page(__FUNCTION__, page);
@@ -509,8 +505,12 @@
 	struct per_cpu_pages *pcp;
 	unsigned long flags;
 
+	arch_free_page(page, 0);
+
 	kernel_map_pages(page, 1, 0);
 	inc_page_state(pgfree);
+	if (PageAnon(page))
+		page->mapping = NULL;
 	free_pages_check(__FUNCTION__, page);
 	pcp = &zone->pageset[get_cpu()].pcp[cold];
 	local_irq_save(flags);
@@ -600,83 +600,75 @@
 {
 	const int wait = gfp_mask & __GFP_WAIT;
 	unsigned long min;
-	struct zone **zones;
+	struct zone **zones, *z;
 	struct page *page;
 	struct reclaim_state reclaim_state;
 	struct task_struct *p = current;
 	int i;
 	int alloc_type;
 	int do_retry;
+	int can_try_harder;
 
 	might_sleep_if(wait);
 
+	/*
+	 * The caller may dip into page reserves a bit more if the caller
+	 * cannot run direct reclaim, or is the caller has realtime scheduling
+	 * policy
+	 */
+	can_try_harder = (unlikely(rt_task(p)) && !in_interrupt()) || !wait;
+
 	zones = zonelist->zones;  /* the list of zones suitable for gfp_mask */
-	if (zones[0] == NULL)     /* no zones in the zonelist */
+
+	if (unlikely(zones[0] == NULL)) {
+		/* Should this ever happen?? */
 		return NULL;
+	}
 
 	alloc_type = zone_idx(zones[0]);
 
 	/* Go through the zonelist once, looking for a zone with enough free */
-	for (i = 0; zones[i] != NULL; i++) {
-		struct zone *z = zones[i];
-
-		min = (1<<order) + z->protection[alloc_type];
+	for (i = 0; (z = zones[i]) != NULL; i++) {
+		min = z->pages_low + (1<<order) + z->protection[alloc_type];
 
-		/*
-		 * We let real-time tasks dip their real-time paws a little
-		 * deeper into reserves.
-		 */
-		if (rt_task(p))
-			min -= z->pages_low >> 1;
+		if (z->free_pages < min)
+			continue;
 
-		if (z->free_pages >= min ||
-				(!wait && z->free_pages >= z->pages_high)) {
-			page = buffered_rmqueue(z, order, gfp_mask);
-			if (page) {
-				zone_statistics(zonelist, z);
-				goto got_pg;
-			}
-		}
+		page = buffered_rmqueue(z, order, gfp_mask);
+		if (page)
+			goto got_pg;
 	}
 
-	/* we're somewhat low on memory, failed to find what we needed */
-	for (i = 0; zones[i] != NULL; i++)
-		wakeup_kswapd(zones[i]);
-
-	/* Go through the zonelist again, taking __GFP_HIGH into account */
-	for (i = 0; zones[i] != NULL; i++) {
-		struct zone *z = zones[i];
-
-		min = (1<<order) + z->protection[alloc_type];
+	for (i = 0; (z = zones[i]) != NULL; i++)
+		wakeup_kswapd(z);
 
+	/*
+	 * Go through the zonelist again. Let __GFP_HIGH and allocations
+	 * coming from realtime tasks to go deeper into reserves
+	 */
+	for (i = 0; (z = zones[i]) != NULL; i++) {
+		min = z->pages_min;
 		if (gfp_mask & __GFP_HIGH)
-			min -= z->pages_low >> 2;
-		if (rt_task(p))
-			min -= z->pages_low >> 1;
+			min /= 2;
+		if (can_try_harder)
+			min -= min / 4;
+		min += (1<<order) + z->protection[alloc_type];
 
-		if (z->free_pages >= min ||
-				(!wait && z->free_pages >= z->pages_high)) {
-			page = buffered_rmqueue(z, order, gfp_mask);
-			if (page) {
-				zone_statistics(zonelist, z);
-				goto got_pg;
-			}
-		}
-	}
+		if (z->free_pages < min)
+			continue;
 
-	/* here we're in the low on memory slow path */
+		page = buffered_rmqueue(z, order, gfp_mask);
+		if (page)
+			goto got_pg;
+	}
 
-rebalance:
+	/* This allocation should allow future memory freeing. */
 	if ((p->flags & (PF_MEMALLOC | PF_MEMDIE)) && !in_interrupt()) {
 		/* go through the zonelist yet again, ignoring mins */
-		for (i = 0; zones[i] != NULL; i++) {
-			struct zone *z = zones[i];
-
+		for (i = 0; (z = zones[i]) != NULL; i++) {
 			page = buffered_rmqueue(z, order, gfp_mask);
-			if (page) {
-				zone_statistics(zonelist, z);
+			if (page)
 				goto got_pg;
-			}
 		}
 		goto nopage;
 	}
@@ -685,6 +677,8 @@
 	if (!wait)
 		goto nopage;
 
+rebalance:
+	/* We now go into synchronous reclaim */
 	p->flags |= PF_MEMALLOC;
 	reclaim_state.reclaimed_slab = 0;
 	p->reclaim_state = &reclaim_state;
@@ -695,27 +689,28 @@
 	p->flags &= ~PF_MEMALLOC;
 
 	/* go through the zonelist yet one more time */
-	for (i = 0; zones[i] != NULL; i++) {
-		struct zone *z = zones[i];
+	for (i = 0; (z = zones[i]) != NULL; i++) {
+		min = z->pages_min;
+		if (gfp_mask & __GFP_HIGH)
+			min /= 2;
+		if (can_try_harder)
+			min -= min / 4;
+		min += (1<<order) + z->protection[alloc_type];
 
-		min = (1UL << order) + z->protection[alloc_type];
+		if (z->free_pages < min)
+			continue;
 
-		if (z->free_pages >= min ||
-				(!wait && z->free_pages >= z->pages_high)) {
-			page = buffered_rmqueue(z, order, gfp_mask);
-			if (page) {
- 				zone_statistics(zonelist, z);
-				goto got_pg;
-			}
-		}
+		page = buffered_rmqueue(z, order, gfp_mask);
+		if (page)
+			goto got_pg;
 	}
 
 	/*
 	 * Don't let big-order allocations loop unless the caller explicitly
 	 * requests that.  Wait for some write requests to complete then retry.
 	 *
-	 * In this implementation, __GFP_REPEAT means __GFP_NOFAIL, but that
-	 * may not be true in other implementations.
+	 * In this implementation, __GFP_REPEAT means __GFP_NOFAIL for order
+	 * <= 3, but that may not be true in other implementations.
 	 */
 	do_retry = 0;
 	if (!(gfp_mask & __GFP_NORETRY)) {
@@ -738,6 +733,7 @@
 	}
 	return NULL;
 got_pg:
+	zone_statistics(zonelist, z);
 	kernel_map_pages(page, 1 << order, 1);
 	return page;
 }
@@ -802,8 +798,8 @@
 fastcall void free_pages(unsigned long addr, unsigned int order)
 {
 	if (addr != 0) {
-		BUG_ON(!virt_addr_valid(addr));
-		__free_pages(virt_to_page(addr), order);
+		BUG_ON(!virt_addr_valid((void *)addr));
+		__free_pages(virt_to_page((void *)addr), order);
 	}
 }
 
@@ -965,18 +961,36 @@
 	return ret;
 }
 
+void __get_zone_counts(unsigned long *active, unsigned long *inactive,
+			unsigned long *free, struct pglist_data *pgdat)
+{
+	struct zone *zones = pgdat->node_zones;
+	int i;
+
+	*active = 0;
+	*inactive = 0;
+	*free = 0;
+	for (i = 0; i < MAX_NR_ZONES; i++) {
+		*active += zones[i].nr_active;
+		*inactive += zones[i].nr_inactive;
+		*free += zones[i].free_pages;
+	}
+}
+
 void get_zone_counts(unsigned long *active,
 		unsigned long *inactive, unsigned long *free)
 {
-	struct zone *zone;
+	struct pglist_data *pgdat;
 
 	*active = 0;
 	*inactive = 0;
 	*free = 0;
-	for_each_zone(zone) {
-		*active += zone->nr_active;
-		*inactive += zone->nr_inactive;
-		*free += zone->free_pages;
+	for_each_pgdat(pgdat) {
+		unsigned long l, m, n;
+		__get_zone_counts(&l, &m, &n, pgdat);
+		*active += l;
+		*inactive += m;
+		*free += n;
 	}
 }
 
@@ -1379,14 +1393,16 @@
  * up by free_all_bootmem() once the early boot process is
  * done. Non-atomic initialization, single-pass.
  */
-void __init memmap_init_zone(struct page *start, unsigned long size, int nid,
-		unsigned long zone, unsigned long start_pfn)
+void __init memmap_init_zone(unsigned long size, int nid, unsigned long zone,
+		unsigned long start_pfn)
 {
+	struct page *start = pfn_to_page(start_pfn);
 	struct page *page;
 
 	for (page = start; page < (start + size); page++) {
 		set_page_zone(page, NODEZONE(nid, zone));
 		set_page_count(page, 0);
+		reset_page_mapcount(page);
 		SetPageReserved(page);
 		INIT_LIST_HEAD(&page->lru);
 #ifdef WANT_PAGE_VIRTUAL
@@ -1398,9 +1414,55 @@
 	}
 }
 
+/*
+ * Page buddy system uses "index >> (i+1)", where "index" is
+ * at most "size-1".
+ *
+ * The extra "+3" is to round down to byte size (8 bits per byte
+ * assumption). Thus we get "(size-1) >> (i+4)" as the last byte
+ * we can access.
+ *
+ * The "+1" is because we want to round the byte allocation up
+ * rather than down. So we should have had a "+7" before we shifted
+ * down by three. Also, we have to add one as we actually _use_ the
+ * last bit (it's [0,n] inclusive, not [0,n[).
+ *
+ * So we actually had +7+1 before we shift down by 3. But
+ * (n+8) >> 3 == (n >> 3) + 1 (modulo overflows, which we do not have).
+ *
+ * Finally, we LONG_ALIGN because all bitmap operations are on longs.
+ */
+unsigned long pages_to_bitmap_size(unsigned long order, unsigned long nr_pages)
+{
+	unsigned long bitmap_size;
+
+	bitmap_size = (nr_pages-1) >> (order+4);
+	bitmap_size = LONG_ALIGN(bitmap_size+1);
+
+	return bitmap_size;
+}
+
+void zone_init_free_lists(struct pglist_data *pgdat, struct zone *zone, unsigned long size)
+{
+	int order;
+	for (order = 0; ; order++) {
+		unsigned long bitmap_size;
+
+		INIT_LIST_HEAD(&zone->free_area[order].free_list);
+		if (order == MAX_ORDER-1) {
+			zone->free_area[order].map = NULL;
+			break;
+		}
+
+		bitmap_size = pages_to_bitmap_size(order, size);
+		zone->free_area[order].map =
+		  (unsigned long *) alloc_bootmem_node(pgdat, bitmap_size);
+	}
+}
+
 #ifndef __HAVE_ARCH_MEMMAP_INIT
-#define memmap_init(start, size, nid, zone, start_pfn) \
-	memmap_init_zone((start), (size), (nid), (zone), (start_pfn))
+#define memmap_init(size, nid, zone, start_pfn) \
+	memmap_init_zone((size), (nid), (zone), (start_pfn))
 #endif
 
 /*
@@ -1415,7 +1477,6 @@
 	unsigned long i, j;
 	const unsigned long zone_required_alignment = 1UL << (MAX_ORDER-1);
 	int cpu, nid = pgdat->node_id;
-	struct page *lmem_map = pgdat->node_mem_map;
 	unsigned long zone_start_pfn = pgdat->node_start_pfn;
 
 	pgdat->nr_zones = 0;
@@ -1503,71 +1564,41 @@
 
 		pgdat->nr_zones = j+1;
 
-		zone->zone_mem_map = lmem_map;
+		zone->zone_mem_map = pfn_to_page(zone_start_pfn);
 		zone->zone_start_pfn = zone_start_pfn;
 
 		if ((zone_start_pfn) & (zone_required_alignment-1))
 			printk("BUG: wrong zone alignment, it will crash\n");
 
-		memmap_init(lmem_map, size, nid, j, zone_start_pfn);
+		memmap_init(size, nid, j, zone_start_pfn);
 
 		zone_start_pfn += size;
-		lmem_map += size;
-
-		for (i = 0; ; i++) {
-			unsigned long bitmap_size;
-
-			INIT_LIST_HEAD(&zone->free_area[i].free_list);
-			if (i == MAX_ORDER-1) {
-				zone->free_area[i].map = NULL;
-				break;
-			}
 
-			/*
-			 * Page buddy system uses "index >> (i+1)",
-			 * where "index" is at most "size-1".
-			 *
-			 * The extra "+3" is to round down to byte
-			 * size (8 bits per byte assumption). Thus
-			 * we get "(size-1) >> (i+4)" as the last byte
-			 * we can access.
-			 *
-			 * The "+1" is because we want to round the
-			 * byte allocation up rather than down. So
-			 * we should have had a "+7" before we shifted
-			 * down by three. Also, we have to add one as
-			 * we actually _use_ the last bit (it's [0,n]
-			 * inclusive, not [0,n[).
-			 *
-			 * So we actually had +7+1 before we shift
-			 * down by 3. But (n+8) >> 3 == (n >> 3) + 1
-			 * (modulo overflows, which we do not have).
-			 *
-			 * Finally, we LONG_ALIGN because all bitmap
-			 * operations are on longs.
-			 */
-			bitmap_size = (size-1) >> (i+4);
-			bitmap_size = LONG_ALIGN(bitmap_size+1);
-			zone->free_area[i].map = 
-			  (unsigned long *) alloc_bootmem_node(pgdat, bitmap_size);
-		}
+		zone_init_free_lists(pgdat, zone, zone->spanned_pages);
 	}
 }
 
-void __init free_area_init_node(int nid, struct pglist_data *pgdat,
-		struct page *node_mem_map, unsigned long *zones_size,
-		unsigned long node_start_pfn, unsigned long *zholes_size)
+void __init node_alloc_mem_map(struct pglist_data *pgdat)
 {
 	unsigned long size;
 
+	size = (pgdat->node_spanned_pages + 1) * sizeof(struct page);
+	pgdat->node_mem_map = alloc_bootmem_node(pgdat, size);
+#ifndef CONFIG_DISCONTIGMEM
+	mem_map = contig_page_data.node_mem_map;
+#endif
+}
+
+void __init free_area_init_node(int nid, struct pglist_data *pgdat,
+		unsigned long *zones_size, unsigned long node_start_pfn,
+		unsigned long *zholes_size)
+{
 	pgdat->node_id = nid;
 	pgdat->node_start_pfn = node_start_pfn;
 	calculate_zone_totalpages(pgdat, zones_size, zholes_size);
-	if (!node_mem_map) {
-		size = (pgdat->node_spanned_pages + 1) * sizeof(struct page);
-		node_mem_map = alloc_bootmem_node(pgdat, size);
-	}
-	pgdat->node_mem_map = node_mem_map;
+
+	if (!pfn_to_page(node_start_pfn))
+		node_alloc_mem_map(pgdat);
 
 	free_area_init_core(pgdat, zones_size, zholes_size);
 }
@@ -1580,9 +1611,8 @@
 
 void __init free_area_init(unsigned long *zones_size)
 {
-	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, NULL);
-	mem_map = contig_page_data.node_mem_map;
 }
 #endif
 
@@ -1841,11 +1871,11 @@
 				 * We never protect zones that don't have memory
 				 * in them (j>max_zone) or zones that aren't in
 				 * the zonelists for a certain type of
-				 * allocation (j>i).  We have to assign these to
-				 * zero because the lower zones take
+				 * allocation (j>=i).  We have to assign these
+				 * to zero because the lower zones take
 				 * contributions from the higher zones.
 				 */
-				if (j > max_zone || j > i) {
+				if (j > max_zone || j >= i) {
 					zone->protection[i] = 0;
 					continue;
 				}
@@ -1854,7 +1884,6 @@
 				 */
 				zone->protection[i] = higherzone_val(zone,
 								max_zone, i);
-				zone->protection[i] += zone->pages_low;
 			}
 		}
 	}
@@ -1989,41 +2018,40 @@
 				     unsigned int *_hash_shift,
 				     unsigned int *_hash_mask)
 {
-	unsigned long mem, max, log2qty, size;
+	unsigned long long max;
+	unsigned long log2qty, size;
 	void *table;
 
-	/* round applicable memory size up to nearest megabyte */
-	mem = consider_highmem ? nr_all_pages : nr_kernel_pages;
-	mem += (1UL << (20 - PAGE_SHIFT)) - 1;
-	mem >>= 20 - PAGE_SHIFT;
-	mem <<= 20 - PAGE_SHIFT;
-
-	/* limit to 1 bucket per 2^scale bytes of low memory (rounded up to
-	 * nearest power of 2 in size) */
-	if (scale > PAGE_SHIFT)
-		mem >>= (scale - PAGE_SHIFT);
-	else
-		mem <<= (PAGE_SHIFT - scale);
-
-	mem = 1UL << (long_log2(mem) + 1);
+	/* allow the kernel cmdline to have a say */
+	if (!numentries) {
+		/* round applicable memory size up to nearest megabyte */
+		numentries = consider_highmem ? nr_all_pages : nr_kernel_pages;
+		numentries += (1UL << (20 - PAGE_SHIFT)) - 1;
+		numentries >>= 20 - PAGE_SHIFT;
+		numentries <<= 20 - PAGE_SHIFT;
+
+		/* limit to 1 bucket per 2^scale bytes of low memory */
+		if (scale > PAGE_SHIFT)
+			numentries >>= (scale - PAGE_SHIFT);
+		else
+			numentries <<= (PAGE_SHIFT - scale);
+	}
+	/* rounded up to nearest power of 2 in size */
+	numentries = 1UL << (long_log2(numentries) + 1);
 
-	/* limit allocation size */
-	max = (1UL << (PAGE_SHIFT + MAX_SYS_HASH_TABLE_ORDER)) / bucketsize;
-	if (max > mem)
-		max = mem;
+	/* limit allocation size to 1/16 total memory */
+	max = ((unsigned long long)nr_all_pages << PAGE_SHIFT) >> 4;
+	do_div(max, bucketsize);
 
-	/* allow the kernel cmdline to have a say */
-	if (!numentries || numentries > max)
+	if (numentries > max)
 		numentries = max;
 
 	log2qty = long_log2(numentries);
 
 	do {
 		size = bucketsize << log2qty;
-
-		table = (void *) alloc_bootmem(size);
-
-	} while (!table && size > PAGE_SIZE);
+		table = alloc_bootmem(size);
+	} while (!table && size > PAGE_SIZE && --log2qty);
 
 	if (!table)
 		panic("Failed to allocate %s hash table\n", tablename);
diff -Nru a/mm/prio_tree.c b/mm/prio_tree.c
--- a/mm/prio_tree.c	2004-10-18 14:57:04 -07:00
+++ b/mm/prio_tree.c	2004-10-18 14:57:04 -07:00
@@ -81,6 +81,8 @@
 	return index_bits_to_maxindex[bits - 1];
 }
 
+static void prio_tree_remove(struct prio_tree_root *, struct prio_tree_node *);
+
 /*
  * Extend a priority search tree so that it can store a node with heap_index
  * max_heap_index. In the worst case, this algorithm takes O((log n)^2).
@@ -90,8 +92,6 @@
 static struct prio_tree_node *prio_tree_expand(struct prio_tree_root *root,
 		struct prio_tree_node *node, unsigned long max_heap_index)
 {
-	static void prio_tree_remove(struct prio_tree_root *,
-					struct prio_tree_node *);
 	struct prio_tree_node *first = NULL, *prev, *last = NULL;
 
 	if (max_heap_index > prio_tree_maxindex(root->index_bits))
@@ -312,9 +312,7 @@
  * 'm' is the number of prio_tree_nodes that overlap the interval X.
  */
 
-static struct prio_tree_node *prio_tree_left(
-		struct prio_tree_root *root, struct prio_tree_iter *iter,
-		unsigned long radix_index, unsigned long heap_index,
+static struct prio_tree_node *prio_tree_left(struct prio_tree_iter *iter,
 		unsigned long *r_index, unsigned long *h_index)
 {
 	if (prio_tree_left_empty(iter->cur))
@@ -322,7 +320,7 @@
 
 	GET_INDEX(iter->cur->left, *r_index, *h_index);
 
-	if (radix_index <= *h_index) {
+	if (iter->r_index <= *h_index) {
 		iter->cur = iter->cur->left;
 		iter->mask >>= 1;
 		if (iter->mask) {
@@ -336,7 +334,7 @@
 				iter->mask = ULONG_MAX;
 			} else {
 				iter->size_level = 1;
-				iter->mask = 1UL << (root->index_bits - 1);
+				iter->mask = 1UL << (iter->root->index_bits - 1);
 			}
 		}
 		return iter->cur;
@@ -345,9 +343,7 @@
 	return NULL;
 }
 
-static struct prio_tree_node *prio_tree_right(
-		struct prio_tree_root *root, struct prio_tree_iter *iter,
-		unsigned long radix_index, unsigned long heap_index,
+static struct prio_tree_node *prio_tree_right(struct prio_tree_iter *iter,
 		unsigned long *r_index, unsigned long *h_index)
 {
 	unsigned long value;
@@ -360,12 +356,12 @@
 	else
 		value = iter->value | iter->mask;
 
-	if (heap_index < value)
+	if (iter->h_index < value)
 		return NULL;
 
 	GET_INDEX(iter->cur->right, *r_index, *h_index);
 
-	if (radix_index <= *h_index) {
+	if (iter->r_index <= *h_index) {
 		iter->cur = iter->cur->right;
 		iter->mask >>= 1;
 		iter->value = value;
@@ -380,7 +376,7 @@
 				iter->mask = ULONG_MAX;
 			} else {
 				iter->size_level = 1;
-				iter->mask = 1UL << (root->index_bits - 1);
+				iter->mask = 1UL << (iter->root->index_bits - 1);
 			}
 		}
 		return iter->cur;
@@ -405,10 +401,10 @@
 	return iter->cur;
 }
 
-static inline int overlap(unsigned long radix_index, unsigned long heap_index,
+static inline int overlap(struct prio_tree_iter *iter,
 		unsigned long r_index, unsigned long h_index)
 {
-	return heap_index >= r_index && radix_index <= h_index;
+	return iter->h_index >= r_index && iter->r_index <= h_index;
 }
 
 /*
@@ -418,35 +414,33 @@
  * heap_index]. Note that always radix_index <= heap_index. We do a pre-order
  * traversal of the tree.
  */
-static struct prio_tree_node *prio_tree_first(struct prio_tree_root *root,
-		struct prio_tree_iter *iter, unsigned long radix_index,
-		unsigned long heap_index)
+static struct prio_tree_node *prio_tree_first(struct prio_tree_iter *iter)
 {
+	struct prio_tree_root *root;
 	unsigned long r_index, h_index;
 
 	INIT_PRIO_TREE_ITER(iter);
 
+	root = iter->root;
 	if (prio_tree_empty(root))
 		return NULL;
 
 	GET_INDEX(root->prio_tree_node, r_index, h_index);
 
-	if (radix_index > h_index)
+	if (iter->r_index > h_index)
 		return NULL;
 
 	iter->mask = 1UL << (root->index_bits - 1);
 	iter->cur = root->prio_tree_node;
 
 	while (1) {
-		if (overlap(radix_index, heap_index, r_index, h_index))
+		if (overlap(iter, r_index, h_index))
 			return iter->cur;
 
-		if (prio_tree_left(root, iter, radix_index, heap_index,
-					&r_index, &h_index))
+		if (prio_tree_left(iter, &r_index, &h_index))
 			continue;
 
-		if (prio_tree_right(root, iter, radix_index, heap_index,
-					&r_index, &h_index))
+		if (prio_tree_right(iter, &r_index, &h_index))
 			continue;
 
 		break;
@@ -459,21 +453,16 @@
  *
  * Get the next prio_tree_node that overlaps with the input interval in iter
  */
-static struct prio_tree_node *prio_tree_next(struct prio_tree_root *root,
-		struct prio_tree_iter *iter, unsigned long radix_index,
-		unsigned long heap_index)
+static struct prio_tree_node *prio_tree_next(struct prio_tree_iter *iter)
 {
 	unsigned long r_index, h_index;
 
 repeat:
-	while (prio_tree_left(root, iter, radix_index,
-				heap_index, &r_index, &h_index)) {
-		if (overlap(radix_index, heap_index, r_index, h_index))
+	while (prio_tree_left(iter, &r_index, &h_index))
+		if (overlap(iter, r_index, h_index))
 			return iter->cur;
-	}
 
-	while (!prio_tree_right(root, iter, radix_index,
-				heap_index, &r_index, &h_index)) {
+	while (!prio_tree_right(iter, &r_index, &h_index)) {
 	    	while (!prio_tree_root(iter->cur) &&
 				iter->cur->parent->right == iter->cur)
 			prio_tree_parent(iter);
@@ -484,7 +473,7 @@
 		prio_tree_parent(iter);
 	}
 
-	if (overlap(radix_index, heap_index, r_index, h_index))
+	if (overlap(iter, r_index, h_index))
 		return iter->cur;
 
 	goto repeat;
@@ -538,6 +527,9 @@
 	BUG_ON(RADIX_INDEX(vma) != RADIX_INDEX(old));
 	BUG_ON(HEAP_INDEX(vma) != HEAP_INDEX(old));
 
+	vma->shared.vm_set.head = NULL;
+	vma->shared.vm_set.parent = NULL;
+
 	if (!old->shared.vm_set.parent)
 		list_add(&vma->shared.vm_set.list,
 				&old->shared.vm_set.list);
@@ -557,6 +549,8 @@
 	struct prio_tree_node *ptr;
 	struct vm_area_struct *old;
 
+	vma->shared.vm_set.head = NULL;
+
 	ptr = prio_tree_insert(root, &vma->shared.prio_tree_node);
 	if (ptr != &vma->shared.prio_tree_node) {
 		old = prio_tree_entry(ptr, struct vm_area_struct,
@@ -617,8 +611,7 @@
  * page in the given range of contiguous file pages.
  */
 struct vm_area_struct *vma_prio_tree_next(struct vm_area_struct *vma,
-		struct prio_tree_root *root, struct prio_tree_iter *iter,
-		pgoff_t begin, pgoff_t end)
+					struct prio_tree_iter *iter)
 {
 	struct prio_tree_node *ptr;
 	struct vm_area_struct *next;
@@ -627,7 +620,7 @@
 		/*
 		 * First call is with NULL vma
 		 */
-		ptr = prio_tree_first(root, iter, begin, end);
+		ptr = prio_tree_first(iter);
 		if (ptr) {
 			next = prio_tree_entry(ptr, struct vm_area_struct,
 						shared.prio_tree_node);
@@ -652,7 +645,7 @@
 		}
 	}
 
-	ptr = prio_tree_next(root, iter, begin, end);
+	ptr = prio_tree_next(iter);
 	if (ptr) {
 		next = prio_tree_entry(ptr, struct vm_area_struct,
 					shared.prio_tree_node);
diff -Nru a/mm/readahead.c b/mm/readahead.c
--- a/mm/readahead.c	2004-10-18 14:55:54 -07:00
+++ b/mm/readahead.c	2004-10-18 14:55:54 -07:00
@@ -28,16 +28,15 @@
 EXPORT_SYMBOL_GPL(default_backing_dev_info);
 
 /*
- * Initialise a struct file's readahead state
+ * Initialise a struct file's readahead state.  Assumes that the caller has
+ * memset *ra to zero.
  */
 void
 file_ra_state_init(struct file_ra_state *ra, struct address_space *mapping)
 {
-	memset(ra, 0, sizeof(*ra));
 	ra->ra_pages = mapping->backing_dev_info->ra_pages;
 	ra->average = ra->ra_pages / 2;
 }
-EXPORT_SYMBOL(file_ra_state_init);
 
 /*
  * Return max readahead size for this inode in number-of-pages.
@@ -384,25 +383,10 @@
 		first_access=1;
 		ra->next_size = max / 2;
 		ra->prev_page = offset;
-		ra->serial_cnt++;
+		ra->currnt_wnd_hit++;
 		goto do_io;
 	}
 
-	if (offset == ra->prev_page + 1) {
-		if (ra->serial_cnt <= (max * 2))
-			ra->serial_cnt++;
-	} else {
-		/*
-		 * to avoid rounding errors, ensure that 'average'
-		 * tends towards the value of ra->serial_cnt.
-		 */
-		average = ra->average;
-		if (average < ra->serial_cnt) {
-			average++;
-		}
-		ra->average = (average + ra->serial_cnt) / 2;
-		ra->serial_cnt = 1;
-	}
 	ra->prev_page = offset;
 
 	if (offset >= ra->start && offset <= (ra->start + ra->size)) {
@@ -411,12 +395,22 @@
 		 * page beyond the end.  Expand the next readahead size.
 		 */
 		ra->next_size += 2;
+
+		if (ra->currnt_wnd_hit <= (max * 2))
+			ra->currnt_wnd_hit++;
 	} else {
 		/*
 		 * A miss - lseek, pagefault, pread, etc.  Shrink the readahead
 		 * window.
 		 */
 		ra->next_size -= 2;
+
+		average = ra->average;
+		if (average < ra->currnt_wnd_hit) {
+			average++;
+		}
+		ra->average = (average + ra->currnt_wnd_hit) / 2;
+		ra->currnt_wnd_hit = 1;
 	}
 
 	if ((long)ra->next_size > (long)max)
@@ -469,8 +463,8 @@
 			  * current window.
 			  */
 			average = ra->average;
-			if (ra->serial_cnt > average)
-				average = (ra->serial_cnt + ra->average + 1) / 2;
+			if (ra->currnt_wnd_hit > average)
+				average = (ra->currnt_wnd_hit + ra->average + 1) / 2;
 
 			ra->next_size = min(average , (unsigned long)max);
 		}
@@ -505,8 +499,8 @@
 			 * random. Hence don't bother to readahead.
 			 */
 			average = ra->average;
-			if (ra->serial_cnt > average)
-				average = (ra->serial_cnt + ra->average + 1) / 2;
+			if (ra->currnt_wnd_hit > average)
+				average = (ra->currnt_wnd_hit + ra->average + 1) / 2;
 
 			if (average > max) {
 				ra->ahead_start = ra->start + ra->size;
@@ -577,6 +571,6 @@
 	unsigned long inactive;
 	unsigned long free;
 
-	get_zone_counts(&active, &inactive, &free);
+	__get_zone_counts(&active, &inactive, &free, NODE_DATA(numa_node_id()));
 	return min(nr, (inactive + free) / 2);
 }
diff -Nru a/mm/rmap.c b/mm/rmap.c
--- a/mm/rmap.c	2004-10-18 14:57:03 -07:00
+++ b/mm/rmap.c	2004-10-18 14:57:03 -07:00
@@ -18,9 +18,30 @@
  */
 
 /*
- * Locking: see "Lock ordering" summary in filemap.c.
- * In swapout, page_map_lock is held on entry to page_referenced and
- * try_to_unmap, so they trylock for i_mmap_lock and page_table_lock.
+ * Lock ordering in mm:
+ *
+ * inode->i_sem	(while writing or truncating, not reading or faulting)
+ *   inode->i_alloc_sem
+ *
+ * When a page fault occurs in writing from user to file, down_read
+ * of mmap_sem nests within i_sem; in sys_msync, i_sem nests within
+ * down_read of mmap_sem; i_sem and down_write of mmap_sem are never
+ * taken together; in truncation, i_sem is taken outermost.
+ *
+ * mm->mmap_sem
+ *   page->flags PG_locked (lock_page)
+ *     mapping->i_mmap_lock
+ *       anon_vma->lock
+ *         mm->page_table_lock
+ *           zone->lru_lock (in mark_page_accessed)
+ *           swap_list_lock (in swap_free etc's swap_info_get)
+ *             swap_device_lock (in swap_duplicate, swap_info_get)
+ *             mapping->private_lock (in __set_page_dirty_buffers)
+ *             inode_lock (in set_page_dirty's __mark_inode_dirty)
+ *               sb_lock (within inode_lock in fs/fs-writeback.c)
+ *               mapping->tree_lock (widely used, in set_page_dirty,
+ *                         in arch-dependent flush_dcache_mmap_lock,
+ *                         within inode_lock in __sync_single_inode)
  */
 
 #include <linux/mm.h>
@@ -30,6 +51,7 @@
 #include <linux/slab.h>
 #include <linux/init.h>
 #include <linux/rmap.h>
+#include <linux/rcupdate.h>
 
 #include <asm/tlbflush.h>
 
@@ -63,28 +85,32 @@
 	might_sleep();
 	if (unlikely(!anon_vma)) {
 		struct mm_struct *mm = vma->vm_mm;
-		struct anon_vma *allocated = NULL;
+		struct anon_vma *allocated, *locked;
 
 		anon_vma = find_mergeable_anon_vma(vma);
-		if (!anon_vma) {
+		if (anon_vma) {
+			allocated = NULL;
+			locked = anon_vma;
+			spin_lock(&locked->lock);
+		} else {
 			anon_vma = anon_vma_alloc();
 			if (unlikely(!anon_vma))
 				return -ENOMEM;
 			allocated = anon_vma;
+			locked = NULL;
 		}
 
 		/* page_table_lock to protect against threads */
 		spin_lock(&mm->page_table_lock);
 		if (likely(!vma->anon_vma)) {
-			if (!allocated)
-				spin_lock(&anon_vma->lock);
 			vma->anon_vma = anon_vma;
 			list_add(&vma->anon_vma_node, &anon_vma->head);
-			if (!allocated)
-				spin_unlock(&anon_vma->lock);
 			allocated = NULL;
 		}
 		spin_unlock(&mm->page_table_lock);
+
+		if (locked)
+			spin_unlock(&locked->lock);
 		if (unlikely(allocated))
 			anon_vma_free(allocated);
 	}
@@ -159,16 +185,31 @@
 
 void __init anon_vma_init(void)
 {
-	anon_vma_cachep = kmem_cache_create("anon_vma",
-		sizeof(struct anon_vma), 0, SLAB_PANIC, anon_vma_ctor, NULL);
+	anon_vma_cachep = kmem_cache_create("anon_vma", sizeof(struct anon_vma),
+			0, SLAB_DESTROY_BY_RCU|SLAB_PANIC, anon_vma_ctor, NULL);
 }
 
-/* this needs the page->flags PG_maplock held */
-static inline void clear_page_anon(struct page *page)
+/*
+ * Getting a lock on a stable anon_vma from a page off the LRU is
+ * tricky: page_lock_anon_vma rely on RCU to guard against the races.
+ */
+static struct anon_vma *page_lock_anon_vma(struct page *page)
 {
-	BUG_ON(!page->mapping);
-	page->mapping = NULL;
-	ClearPageAnon(page);
+	struct anon_vma *anon_vma = NULL;
+	unsigned long anon_mapping;
+
+	rcu_read_lock();
+	anon_mapping = (unsigned long) page->mapping;
+	if (!(anon_mapping & PAGE_MAPPING_ANON))
+		goto out;
+	if (!page_mapped(page))
+		goto out;
+
+	anon_vma = (struct anon_vma *) (anon_mapping - PAGE_MAPPING_ANON);
+	spin_lock(&anon_vma->lock);
+out:
+	rcu_read_unlock();
+	return anon_vma;
 }
 
 /*
@@ -190,6 +231,24 @@
 }
 
 /*
+ * At what user virtual address is page expected in vma? checking that the
+ * page matches the vma: currently only used by unuse_process, on anon pages.
+ */
+unsigned long page_address_in_vma(struct page *page, struct vm_area_struct *vma)
+{
+	if (PageAnon(page)) {
+		if ((void *)vma->anon_vma !=
+		    (void *)page->mapping - PAGE_MAPPING_ANON)
+			return -EFAULT;
+	} else if (page->mapping && !(vma->vm_flags & VM_NONLINEAR)) {
+		if (vma->vm_file->f_mapping != page->mapping)
+			return -EFAULT;
+	} else
+		return -EFAULT;
+	return vma_address(page, vma);
+}
+
+/*
  * Subfunctions of page_referenced: page_referenced_one called
  * repeatedly from either page_referenced_anon or page_referenced_file.
  */
@@ -209,8 +268,7 @@
 	if (address == -EFAULT)
 		goto out;
 
-	if (!spin_trylock(&mm->page_table_lock))
-		goto out;
+	spin_lock(&mm->page_table_lock);
 
 	pgd = pgd_offset(mm, address);
 	if (!pgd_present(*pgd))
@@ -230,6 +288,9 @@
 	if (ptep_clear_flush_young(vma, address, pte))
 		referenced++;
 
+	if (mm != current->mm && has_swap_token(mm))
+		referenced++;
+
 	(*mapcount)--;
 
 out_unmap:
@@ -240,15 +301,18 @@
 	return referenced;
 }
 
-static inline int page_referenced_anon(struct page *page)
+static int page_referenced_anon(struct page *page)
 {
-	unsigned int mapcount = page->mapcount;
-	struct anon_vma *anon_vma = (struct anon_vma *) page->mapping;
+	unsigned int mapcount;
+	struct anon_vma *anon_vma;
 	struct vm_area_struct *vma;
 	int referenced = 0;
 
-	spin_lock(&anon_vma->lock);
-	BUG_ON(list_empty(&anon_vma->head));
+	anon_vma = page_lock_anon_vma(page);
+	if (!anon_vma)
+		return referenced;
+
+	mapcount = page_mapcount(page);
 	list_for_each_entry(vma, &anon_vma->head, anon_vma_node) {
 		referenced += page_referenced_one(page, vma, &mapcount);
 		if (!mapcount)
@@ -268,24 +332,40 @@
  * of references it found.
  *
  * This function is only called from page_referenced for object-based pages.
- *
- * The spinlock address_space->i_mmap_lock is tried.  If it can't be gotten,
- * assume a reference count of 0, so try_to_unmap will then have a go.
  */
-static inline int page_referenced_file(struct page *page)
+static int page_referenced_file(struct page *page)
 {
-	unsigned int mapcount = page->mapcount;
+	unsigned int mapcount;
 	struct address_space *mapping = page->mapping;
 	pgoff_t pgoff = page->index << (PAGE_CACHE_SHIFT - PAGE_SHIFT);
-	struct vm_area_struct *vma = NULL;
+	struct vm_area_struct *vma;
 	struct prio_tree_iter iter;
 	int referenced = 0;
 
-	if (!spin_trylock(&mapping->i_mmap_lock))
-		return 0;
+	/*
+	 * The caller's checks on page->mapping and !PageAnon have made
+	 * sure that this is a file page: the check for page->mapping
+	 * excludes the case just before it gets set on an anon page.
+	 */
+	BUG_ON(PageAnon(page));
 
-	while ((vma = vma_prio_tree_next(vma, &mapping->i_mmap,
-					&iter, pgoff, pgoff)) != NULL) {
+	/*
+	 * The page lock not only makes sure that page->mapping cannot
+	 * suddenly be NULLified by truncation, it makes sure that the
+	 * structure at mapping cannot be freed and reused yet,
+	 * so we can safely take mapping->i_mmap_lock.
+	 */
+	BUG_ON(!PageLocked(page));
+
+	spin_lock(&mapping->i_mmap_lock);
+
+	/*
+	 * i_mmap_lock does not stabilize mapcount at all, but mapcount
+	 * is more likely to be accurate if we note it after spinning.
+	 */
+	mapcount = page_mapcount(page);
+
+	vma_prio_tree_foreach(vma, &iter, &mapping->i_mmap, pgoff, pgoff) {
 		if ((vma->vm_flags & (VM_LOCKED|VM_MAYSHARE))
 				  == (VM_LOCKED|VM_MAYSHARE)) {
 			referenced++;
@@ -303,12 +383,12 @@
 /**
  * page_referenced - test if the page was referenced
  * @page: the page to test
+ * @is_locked: caller holds lock on the page
  *
  * Quick test_and_clear_referenced for all mappings to a page,
  * returns the number of ptes which referenced the page.
- * Caller needs to hold the rmap lock.
  */
-int page_referenced(struct page *page)
+int page_referenced(struct page *page, int is_locked)
 {
 	int referenced = 0;
 
@@ -318,11 +398,18 @@
 	if (TestClearPageReferenced(page))
 		referenced++;
 
-	if (page->mapcount && page->mapping) {
+	if (page_mapped(page) && page->mapping) {
 		if (PageAnon(page))
 			referenced += page_referenced_anon(page);
-		else
+		else if (is_locked)
 			referenced += page_referenced_file(page);
+		else if (TestSetPageLocked(page))
+			referenced++;
+		else {
+			if (page->mapping)
+				referenced += page_referenced_file(page);
+			unlock_page(page);
+		}
 	}
 	return referenced;
 }
@@ -344,36 +431,17 @@
 	BUG_ON(PageReserved(page));
 	BUG_ON(!anon_vma);
 
+	anon_vma = (void *) anon_vma + PAGE_MAPPING_ANON;
 	index = (address - vma->vm_start) >> PAGE_SHIFT;
 	index += vma->vm_pgoff;
 	index >>= PAGE_CACHE_SHIFT - PAGE_SHIFT;
 
-	/*
-	 * Setting and clearing PG_anon must always happen inside
-	 * page_map_lock to avoid races between mapping and
-	 * unmapping on different processes of the same
-	 * shared cow swapcache page. And while we take the
-	 * page_map_lock PG_anon cannot change from under us.
-	 * Actually PG_anon cannot change under fork either
-	 * since fork holds a reference on the page so it cannot
-	 * be unmapped under fork and in turn copy_page_range is
-	 * allowed to read PG_anon outside the page_map_lock.
-	 */
-	page_map_lock(page);
-	if (!page->mapcount) {
-		BUG_ON(PageAnon(page));
-		BUG_ON(page->mapping);
-		SetPageAnon(page);
+	if (atomic_inc_and_test(&page->_mapcount)) {
 		page->index = index;
 		page->mapping = (struct address_space *) anon_vma;
 		inc_page_state(nr_mapped);
-	} else {
-		BUG_ON(!PageAnon(page));
-		BUG_ON(page->index != index);
-		BUG_ON(page->mapping != (struct address_space *) anon_vma);
 	}
-	page->mapcount++;
-	page_map_unlock(page);
+	/* else checking page index and mapping is racy */
 }
 
 /**
@@ -388,11 +456,8 @@
 	if (!pfn_valid(page_to_pfn(page)) || PageReserved(page))
 		return;
 
-	page_map_lock(page);
-	if (!page->mapcount)
+	if (atomic_inc_and_test(&page->_mapcount))
 		inc_page_state(nr_mapped);
-	page->mapcount++;
-	page_map_unlock(page);
 }
 
 /**
@@ -404,18 +469,22 @@
 void page_remove_rmap(struct page *page)
 {
 	BUG_ON(PageReserved(page));
-	BUG_ON(!page->mapcount);
 
-	page_map_lock(page);
-	page->mapcount--;
-	if (!page->mapcount) {
+	if (atomic_add_negative(-1, &page->_mapcount)) {
+		BUG_ON(page_mapcount(page) < 0);
+		/*
+		 * It would be tidy to reset the PageAnon mapping here,
+		 * but that might overwrite a racing page_add_anon_rmap
+		 * which increments mapcount after us but sets mapping
+		 * before us: so leave the reset to free_hot_cold_page,
+		 * and remember that it's only reliable while mapped.
+		 * Leaving it set also helps swapoff to reinstate ptes
+		 * faster for those pages still in swapcache.
+		 */
 		if (page_test_and_clear_dirty(page))
 			set_page_dirty(page);
-		if (PageAnon(page))
-			clear_page_anon(page);
 		dec_page_state(nr_mapped);
 	}
-	page_map_unlock(page);
 }
 
 /*
@@ -442,8 +511,7 @@
 	 * We need the page_table_lock to protect us from page faults,
 	 * munmap, fork, etc...
 	 */
-	if (!spin_trylock(&mm->page_table_lock))
-		goto out;
+	spin_lock(&mm->page_table_lock);
 
 	pgd = pgd_offset(mm, address);
 	if (!pgd_present(*pgd))
@@ -487,7 +555,7 @@
 	 * ptes from being unmapped, so swapoff can make progress.
 	 */
 	if (PageSwapCache(page) &&
-	    page_count(page) != page->mapcount + 2) {
+	    page_count(page) != page_mapcount(page) + 2) {
 		ret = SWAP_FAIL;
 		goto out_unmap;
 	}
@@ -513,8 +581,7 @@
 	}
 
 	mm->rss--;
-	BUG_ON(!page->mapcount);
-	page->mapcount--;
+	page_remove_rmap(page);
 	page_cache_release(page);
 
 out_unmap:
@@ -547,7 +614,7 @@
 #define CLUSTER_SIZE	min(32*PAGE_SIZE, PMD_SIZE)
 #define CLUSTER_MASK	(~(CLUSTER_SIZE - 1))
 
-static int try_to_unmap_cluster(unsigned long cursor,
+static void try_to_unmap_cluster(unsigned long cursor,
 	unsigned int *mapcount, struct vm_area_struct *vma)
 {
 	struct mm_struct *mm = vma->vm_mm;
@@ -564,8 +631,7 @@
 	 * We need the page_table_lock to protect us from page faults,
 	 * munmap, fork, etc...
 	 */
-	if (!spin_trylock(&mm->page_table_lock))
-		return SWAP_FAIL;
+	spin_lock(&mm->page_table_lock);
 
 	address = (vma->vm_start + cursor) & CLUSTER_MASK;
 	end = address + CLUSTER_SIZE;
@@ -622,20 +688,21 @@
 
 out_unlock:
 	spin_unlock(&mm->page_table_lock);
-	return SWAP_AGAIN;
 }
 
-static inline int try_to_unmap_anon(struct page *page)
+static int try_to_unmap_anon(struct page *page)
 {
-	struct anon_vma *anon_vma = (struct anon_vma *) page->mapping;
+	struct anon_vma *anon_vma;
 	struct vm_area_struct *vma;
 	int ret = SWAP_AGAIN;
 
-	spin_lock(&anon_vma->lock);
-	BUG_ON(list_empty(&anon_vma->head));
+	anon_vma = page_lock_anon_vma(page);
+	if (!anon_vma)
+		return ret;
+
 	list_for_each_entry(vma, &anon_vma->head, anon_vma_node) {
 		ret = try_to_unmap_one(page, vma);
-		if (ret == SWAP_FAIL || !page->mapcount)
+		if (ret == SWAP_FAIL || !page_mapped(page))
 			break;
 	}
 	spin_unlock(&anon_vma->lock);
@@ -650,15 +717,12 @@
  * contained in the address_space struct it points to.
  *
  * This function is only called from try_to_unmap for object-based pages.
- *
- * The spinlock address_space->i_mmap_lock is tried.  If it can't be gotten,
- * return a temporary error.
  */
-static inline int try_to_unmap_file(struct page *page)
+static int try_to_unmap_file(struct page *page)
 {
 	struct address_space *mapping = page->mapping;
 	pgoff_t pgoff = page->index << (PAGE_CACHE_SHIFT - PAGE_SHIFT);
-	struct vm_area_struct *vma = NULL;
+	struct vm_area_struct *vma;
 	struct prio_tree_iter iter;
 	int ret = SWAP_AGAIN;
 	unsigned long cursor;
@@ -666,13 +730,10 @@
 	unsigned long max_nl_size = 0;
 	unsigned int mapcount;
 
-	if (!spin_trylock(&mapping->i_mmap_lock))
-		return ret;
-
-	while ((vma = vma_prio_tree_next(vma, &mapping->i_mmap,
-					&iter, pgoff, pgoff)) != NULL) {
+	spin_lock(&mapping->i_mmap_lock);
+	vma_prio_tree_foreach(vma, &iter, &mapping->i_mmap, pgoff, pgoff) {
 		ret = try_to_unmap_one(page, vma);
-		if (ret == SWAP_FAIL || !page->mapcount)
+		if (ret == SWAP_FAIL || !page_mapped(page))
 			goto out;
 	}
 
@@ -691,8 +752,10 @@
 			max_nl_size = cursor;
 	}
 
-	if (max_nl_size == 0)	/* any nonlinears locked or reserved */
+	if (max_nl_size == 0) {	/* any nonlinears locked or reserved */
+		ret = SWAP_FAIL;
 		goto out;
+	}
 
 	/*
 	 * We don't try to search for this page in the nonlinear vmas,
@@ -701,8 +764,9 @@
 	 * The mapcount of the page we came in with is irrelevant,
 	 * but even so use it as a guide to how hard we should try?
 	 */
-	mapcount = page->mapcount;
-	page_map_unlock(page);
+	mapcount = page_mapcount(page);
+	if (!mapcount)
+		goto out;
 	cond_resched_lock(&mapping->i_mmap_lock);
 
 	max_nl_size = (max_nl_size + CLUSTER_SIZE - 1) & CLUSTER_MASK;
@@ -718,19 +782,13 @@
 			while (vma->vm_mm->rss &&
 				cursor < max_nl_cursor &&
 				cursor < vma->vm_end - vma->vm_start) {
-				ret = try_to_unmap_cluster(
-						cursor, &mapcount, vma);
-				if (ret == SWAP_FAIL)
-					break;
+				try_to_unmap_cluster(cursor, &mapcount, vma);
 				cursor += CLUSTER_SIZE;
 				vma->vm_private_data = (void *) cursor;
 				if ((int)mapcount <= 0)
-					goto relock;
+					goto out;
 			}
-			if (ret != SWAP_FAIL)
-				vma->vm_private_data =
-					(void *) max_nl_cursor;
-			ret = SWAP_AGAIN;
+			vma->vm_private_data = (void *) max_nl_cursor;
 		}
 		cond_resched_lock(&mapping->i_mmap_lock);
 		max_nl_cursor += CLUSTER_SIZE;
@@ -746,8 +804,6 @@
 		if (!(vma->vm_flags & VM_RESERVED))
 			vma->vm_private_data = NULL;
 	}
-relock:
-	page_map_lock(page);
 out:
 	spin_unlock(&mapping->i_mmap_lock);
 	return ret;
@@ -758,11 +814,11 @@
  * @page: the page to get unmapped
  *
  * Tries to remove all the page table entries which are mapping this
- * page, used in the pageout path.  Caller must hold the page lock
- * and its rmap lock.  Return values are:
+ * page, used in the pageout path.  Caller must hold the page lock.
+ * Return values are:
  *
  * SWAP_SUCCESS	- we succeeded in removing all mappings
- * SWAP_AGAIN	- we missed a trylock, try again later
+ * SWAP_AGAIN	- we missed a mapping, try again later
  * SWAP_FAIL	- the page is unswappable
  */
 int try_to_unmap(struct page *page)
@@ -771,20 +827,13 @@
 
 	BUG_ON(PageReserved(page));
 	BUG_ON(!PageLocked(page));
-	BUG_ON(!page->mapcount);
 
 	if (PageAnon(page))
 		ret = try_to_unmap_anon(page);
 	else
 		ret = try_to_unmap_file(page);
 
-	if (!page->mapcount) {
-		if (page_test_and_clear_dirty(page))
-			set_page_dirty(page);
-		if (PageAnon(page))
-			clear_page_anon(page);
-		dec_page_state(nr_mapped);
+	if (!page_mapped(page))
 		ret = SWAP_SUCCESS;
-	}
 	return ret;
 }
diff -Nru a/mm/shmem.c b/mm/shmem.c
--- a/mm/shmem.c	2004-10-18 14:56:29 -07:00
+++ b/mm/shmem.c	2004-10-18 14:56:29 -07:00
@@ -6,8 +6,8 @@
  *		 2000-2001 Christoph Rohland
  *		 2000-2001 SAP AG
  *		 2002 Red Hat Inc.
- * Copyright (C) 2002-2003 Hugh Dickins.
- * Copyright (C) 2002-2003 VERITAS Software Corporation.
+ * Copyright (C) 2002-2004 Hugh Dickins.
+ * Copyright (C) 2002-2004 VERITAS Software Corporation.
  * Copyright (C) 2004 Andi Kleen, SuSE Labs
  *
  * This file is released under the GPL.
@@ -179,16 +179,18 @@
 	.unplug_io_fn = default_unplug_io_fn,
 };
 
-LIST_HEAD(shmem_inodes);
-static spinlock_t shmem_ilock = SPIN_LOCK_UNLOCKED;
+static LIST_HEAD(shmem_swaplist);
+static spinlock_t shmem_swaplist_lock = SPIN_LOCK_UNLOCKED;
 
 static void shmem_free_block(struct inode *inode)
 {
 	struct shmem_sb_info *sbinfo = SHMEM_SB(inode->i_sb);
-	spin_lock(&sbinfo->stat_lock);
-	sbinfo->free_blocks++;
-	inode->i_blocks -= BLOCKS_PER_PAGE;
-	spin_unlock(&sbinfo->stat_lock);
+	if (sbinfo) {
+		spin_lock(&sbinfo->stat_lock);
+		sbinfo->free_blocks++;
+		inode->i_blocks -= BLOCKS_PER_PAGE;
+		spin_unlock(&sbinfo->stat_lock);
+	}
 }
 
 /*
@@ -213,11 +215,13 @@
 	if (freed > 0) {
 		struct shmem_sb_info *sbinfo = SHMEM_SB(inode->i_sb);
 		info->alloced -= freed;
-		spin_lock(&sbinfo->stat_lock);
-		sbinfo->free_blocks += freed;
-		inode->i_blocks -= freed*BLOCKS_PER_PAGE;
-		spin_unlock(&sbinfo->stat_lock);
 		shmem_unacct_blocks(info->flags, freed);
+		if (sbinfo) {
+			spin_lock(&sbinfo->stat_lock);
+			sbinfo->free_blocks += freed;
+			inode->i_blocks -= freed*BLOCKS_PER_PAGE;
+			spin_unlock(&sbinfo->stat_lock);
+		}
 	}
 }
 
@@ -350,14 +354,16 @@
 		 * page (and perhaps indirect index pages) yet to allocate:
 		 * a waste to allocate index if we cannot allocate data.
 		 */
-		spin_lock(&sbinfo->stat_lock);
-		if (sbinfo->free_blocks <= 1) {
+		if (sbinfo) {
+			spin_lock(&sbinfo->stat_lock);
+			if (sbinfo->free_blocks <= 1) {
+				spin_unlock(&sbinfo->stat_lock);
+				return ERR_PTR(-ENOSPC);
+			}
+			sbinfo->free_blocks--;
+			inode->i_blocks += BLOCKS_PER_PAGE;
 			spin_unlock(&sbinfo->stat_lock);
-			return ERR_PTR(-ENOSPC);
 		}
-		sbinfo->free_blocks--;
-		inode->i_blocks += BLOCKS_PER_PAGE;
-		spin_unlock(&sbinfo->stat_lock);
 
 		spin_unlock(&info->lock);
 		page = shmem_dir_alloc(mapping_gfp_mask(inode->i_mapping));
@@ -598,17 +604,21 @@
 	struct shmem_inode_info *info = SHMEM_I(inode);
 
 	if (inode->i_op->truncate == shmem_truncate) {
-		spin_lock(&shmem_ilock);
-		list_del(&info->list);
-		spin_unlock(&shmem_ilock);
 		shmem_unacct_size(info->flags, inode->i_size);
 		inode->i_size = 0;
 		shmem_truncate(inode);
+		if (!list_empty(&info->swaplist)) {
+			spin_lock(&shmem_swaplist_lock);
+			list_del_init(&info->swaplist);
+			spin_unlock(&shmem_swaplist_lock);
+		}
+	}
+	if (sbinfo) {
+		BUG_ON(inode->i_blocks);
+		spin_lock(&sbinfo->stat_lock);
+		sbinfo->free_inodes++;
+		spin_unlock(&sbinfo->stat_lock);
 	}
-	BUG_ON(inode->i_blocks);
-	spin_lock(&sbinfo->stat_lock);
-	sbinfo->free_inodes++;
-	spin_unlock(&sbinfo->stat_lock);
 	clear_inode(inode);
 }
 
@@ -713,22 +723,23 @@
  */
 int shmem_unuse(swp_entry_t entry, struct page *page)
 {
-	struct list_head *p;
+	struct list_head *p, *next;
 	struct shmem_inode_info *info;
 	int found = 0;
 
-	spin_lock(&shmem_ilock);
-	list_for_each(p, &shmem_inodes) {
-		info = list_entry(p, struct shmem_inode_info, list);
-
-		if (info->swapped && shmem_unuse_inode(info, entry, page)) {
+	spin_lock(&shmem_swaplist_lock);
+	list_for_each_safe(p, next, &shmem_swaplist) {
+		info = list_entry(p, struct shmem_inode_info, swaplist);
+		if (!info->swapped)
+			list_del_init(&info->swaplist);
+		else if (shmem_unuse_inode(info, entry, page)) {
 			/* move head to start search for next from here */
-			list_move_tail(&shmem_inodes, &info->list);
+			list_move_tail(&shmem_swaplist, &info->swaplist);
 			found = 1;
 			break;
 		}
 	}
-	spin_unlock(&shmem_ilock);
+	spin_unlock(&shmem_swaplist_lock);
 	return found;
 }
 
@@ -770,6 +781,12 @@
 		shmem_swp_set(info, entry, swap.val);
 		shmem_swp_unmap(entry);
 		spin_unlock(&info->lock);
+		if (list_empty(&info->swaplist)) {
+			spin_lock(&shmem_swaplist_lock);
+			/* move instead of add in case we're racing */
+			list_move_tail(&info->swaplist, &shmem_swaplist);
+			spin_unlock(&shmem_swaplist_lock);
+		}
 		unlock_page(page);
 		return 0;
 	}
@@ -868,7 +885,7 @@
 	struct page *swappage;
 	swp_entry_t *entry;
 	swp_entry_t swap;
-	int error, majmin = VM_FAULT_MINOR;
+	int error;
 
 	if (idx >= SHMEM_MAX_INDEX)
 		return -EFBIG;
@@ -906,9 +923,10 @@
 			shmem_swp_unmap(entry);
 			spin_unlock(&info->lock);
 			/* here we actually do the io */
-			if (majmin == VM_FAULT_MINOR && type)
+			if (type && *type == VM_FAULT_MINOR) {
 				inc_page_state(pgmajfault);
-			majmin = VM_FAULT_MAJOR;
+				*type = VM_FAULT_MAJOR;
+			}
 			swappage = shmem_swapin(info, swap, idx);
 			if (!swappage) {
 				spin_lock(&info->lock);
@@ -1001,16 +1019,23 @@
 	} else {
 		shmem_swp_unmap(entry);
 		sbinfo = SHMEM_SB(inode->i_sb);
-		spin_lock(&sbinfo->stat_lock);
-		if (sbinfo->free_blocks == 0 || shmem_acct_block(info->flags)) {
+		if (sbinfo) {
+			spin_lock(&sbinfo->stat_lock);
+			if (sbinfo->free_blocks == 0 ||
+			    shmem_acct_block(info->flags)) {
+				spin_unlock(&sbinfo->stat_lock);
+				spin_unlock(&info->lock);
+				error = -ENOSPC;
+				goto failed;
+			}
+			sbinfo->free_blocks--;
+			inode->i_blocks += BLOCKS_PER_PAGE;
 			spin_unlock(&sbinfo->stat_lock);
+		} else if (shmem_acct_block(info->flags)) {
 			spin_unlock(&info->lock);
 			error = -ENOSPC;
 			goto failed;
 		}
-		sbinfo->free_blocks--;
-		inode->i_blocks += BLOCKS_PER_PAGE;
-		spin_unlock(&sbinfo->stat_lock);
 
 		if (!filepage) {
 			spin_unlock(&info->lock);
@@ -1053,15 +1078,10 @@
 		SetPageUptodate(filepage);
 	}
 done:
-	if (!*pagep) {
-		if (filepage) {
-			unlock_page(filepage);
-			*pagep = filepage;
-		} else
-			*pagep = ZERO_PAGE(0);
+	if (*pagep != filepage) {
+		unlock_page(filepage);
+		*pagep = filepage;
 	}
-	if (type)
-		*type = majmin;
 	return 0;
 
 failed:
@@ -1151,17 +1171,26 @@
 }
 #endif
 
-void shmem_lock(struct file *file, int lock)
+int shmem_lock(struct file *file, int lock, struct user_struct *user)
 {
 	struct inode *inode = file->f_dentry->d_inode;
 	struct shmem_inode_info *info = SHMEM_I(inode);
+	int retval = -ENOMEM;
 
 	spin_lock(&info->lock);
-	if (lock)
+	if (lock && !(info->flags & VM_LOCKED)) {
+		if (!user_shm_lock(inode->i_size, user))
+			goto out_nomem;
 		info->flags |= VM_LOCKED;
-	else
+	}
+	if (!lock && (info->flags & VM_LOCKED) && user) {
+		user_shm_unlock(inode->i_size, user);
 		info->flags &= ~VM_LOCKED;
+	}
+	retval = 0;
+out_nomem:
 	spin_unlock(&info->lock);
+	return retval;
 }
 
 static int shmem_mmap(struct file *file, struct vm_area_struct *vma)
@@ -1178,13 +1207,15 @@
 	struct shmem_inode_info *info;
 	struct shmem_sb_info *sbinfo = SHMEM_SB(sb);
 
-	spin_lock(&sbinfo->stat_lock);
-	if (!sbinfo->free_inodes) {
+	if (sbinfo) {
+		spin_lock(&sbinfo->stat_lock);
+		if (!sbinfo->free_inodes) {
+			spin_unlock(&sbinfo->stat_lock);
+			return NULL;
+		}
+		sbinfo->free_inodes--;
 		spin_unlock(&sbinfo->stat_lock);
-		return NULL;
 	}
-	sbinfo->free_inodes--;
-	spin_unlock(&sbinfo->stat_lock);
 
 	inode = new_inode(sb);
 	if (inode) {
@@ -1200,6 +1231,8 @@
 		memset(info, 0, (char *)inode - (char *)info);
 		spin_lock_init(&info->lock);
  		mpol_shared_policy_init(&info->policy);
+		INIT_LIST_HEAD(&info->swaplist);
+
 		switch (mode & S_IFMT) {
 		default:
 			init_special_inode(inode, mode, dev);
@@ -1207,9 +1240,6 @@
 		case S_IFREG:
 			inode->i_op = &shmem_inode_operations;
 			inode->i_fop = &shmem_file_operations;
-			spin_lock(&shmem_ilock);
-			list_add_tail(&info->list, &shmem_inodes);
-			spin_unlock(&shmem_ilock);
 			break;
 		case S_IFDIR:
 			inode->i_nlink++;
@@ -1225,32 +1255,32 @@
 	return inode;
 }
 
-static int shmem_set_size(struct shmem_sb_info *info,
+#ifdef CONFIG_TMPFS
+
+static int shmem_set_size(struct shmem_sb_info *sbinfo,
 			  unsigned long max_blocks, unsigned long max_inodes)
 {
 	int error;
 	unsigned long blocks, inodes;
 
-	spin_lock(&info->stat_lock);
-	blocks = info->max_blocks - info->free_blocks;
-	inodes = info->max_inodes - info->free_inodes;
+	spin_lock(&sbinfo->stat_lock);
+	blocks = sbinfo->max_blocks - sbinfo->free_blocks;
+	inodes = sbinfo->max_inodes - sbinfo->free_inodes;
 	error = -EINVAL;
 	if (max_blocks < blocks)
 		goto out;
 	if (max_inodes < inodes)
 		goto out;
 	error = 0;
-	info->max_blocks  = max_blocks;
-	info->free_blocks = max_blocks - blocks;
-	info->max_inodes  = max_inodes;
-	info->free_inodes = max_inodes - inodes;
+	sbinfo->max_blocks  = max_blocks;
+	sbinfo->free_blocks = max_blocks - blocks;
+	sbinfo->max_inodes  = max_inodes;
+	sbinfo->free_inodes = max_inodes - inodes;
 out:
-	spin_unlock(&info->stat_lock);
+	spin_unlock(&sbinfo->stat_lock);
 	return error;
 }
 
-#ifdef CONFIG_TMPFS
-
 static struct inode_operations shmem_symlink_inode_operations;
 static struct inode_operations shmem_symlink_inline_operations;
 
@@ -1271,7 +1301,7 @@
 	struct inode	*inode = file->f_dentry->d_inode;
 	loff_t		pos;
 	unsigned long	written;
-	int		err;
+	ssize_t		err;
 
 	if ((ssize_t) count < 0)
 		return -EINVAL;
@@ -1323,7 +1353,8 @@
 			__get_user(dummy, buf + bytes - 1);
 
 			kaddr = kmap_atomic(page, KM_USER0);
-			left = __copy_from_user(kaddr + offset, buf, bytes);
+			left = __copy_from_user_inatomic(kaddr + offset,
+							buf, bytes);
 			kunmap_atomic(kaddr, KM_USER0);
 		}
 		if (left) {
@@ -1407,13 +1438,14 @@
 		if (index == end_index) {
 			nr = i_size & ~PAGE_CACHE_MASK;
 			if (nr <= offset) {
-				page_cache_release(page);
+				if (page)
+					page_cache_release(page);
 				break;
 			}
 		}
 		nr -= offset;
 
-		if (page != ZERO_PAGE(0)) {
+		if (page) {
 			/*
 			 * If users can be writing to this page using arbitrary
 			 * virtual addresses, take care about potential aliasing
@@ -1426,7 +1458,8 @@
 			 */
 			if (!offset)
 				mark_page_accessed(page);
-		}
+		} else
+			page = ZERO_PAGE(0);
 
 		/*
 		 * Ok, we have the page, and it's up-to-date, so
@@ -1501,13 +1534,16 @@
 
 	buf->f_type = TMPFS_MAGIC;
 	buf->f_bsize = PAGE_CACHE_SIZE;
-	spin_lock(&sbinfo->stat_lock);
-	buf->f_blocks = sbinfo->max_blocks;
-	buf->f_bavail = buf->f_bfree = sbinfo->free_blocks;
-	buf->f_files = sbinfo->max_inodes;
-	buf->f_ffree = sbinfo->free_inodes;
-	spin_unlock(&sbinfo->stat_lock);
 	buf->f_namelen = NAME_MAX;
+	if (sbinfo) {
+		spin_lock(&sbinfo->stat_lock);
+		buf->f_blocks = sbinfo->max_blocks;
+		buf->f_bavail = buf->f_bfree = sbinfo->free_blocks;
+		buf->f_files = sbinfo->max_inodes;
+		buf->f_ffree = sbinfo->free_inodes;
+		spin_unlock(&sbinfo->stat_lock);
+	}
+	/* else leave those fields 0 like simple_statfs */
 	return 0;
 }
 
@@ -1557,6 +1593,22 @@
 static int shmem_link(struct dentry *old_dentry, struct inode *dir, struct dentry *dentry)
 {
 	struct inode *inode = old_dentry->d_inode;
+	struct shmem_sb_info *sbinfo = SHMEM_SB(inode->i_sb);
+
+	/*
+	 * No ordinary (disk based) filesystem counts links as inodes;
+	 * but each new link needs a new dentry, pinning lowmem, and
+	 * tmpfs dentries cannot be pruned until they are unlinked.
+	 */
+	if (sbinfo) {
+		spin_lock(&sbinfo->stat_lock);
+		if (!sbinfo->free_inodes) {
+			spin_unlock(&sbinfo->stat_lock);
+			return -ENOSPC;
+		}
+		sbinfo->free_inodes--;
+		spin_unlock(&sbinfo->stat_lock);
+	}
 
 	dir->i_size += BOGO_DIRENT_SIZE;
 	inode->i_ctime = dir->i_ctime = dir->i_mtime = CURRENT_TIME;
@@ -1571,6 +1623,15 @@
 {
 	struct inode *inode = dentry->d_inode;
 
+	if (inode->i_nlink > 1 && !S_ISDIR(inode->i_mode)) {
+		struct shmem_sb_info *sbinfo = SHMEM_SB(inode->i_sb);
+		if (sbinfo) {
+			spin_lock(&sbinfo->stat_lock);
+			sbinfo->free_inodes++;
+			spin_unlock(&sbinfo->stat_lock);
+		}
+	}
+
 	dir->i_size -= BOGO_DIRENT_SIZE;
 	inode->i_ctime = dir->i_ctime = dir->i_mtime = CURRENT_TIME;
 	inode->i_nlink--;
@@ -1648,9 +1709,6 @@
 			return error;
 		}
 		inode->i_op = &shmem_symlink_inode_operations;
-		spin_lock(&shmem_ilock);
-		list_add_tail(&info->list, &shmem_inodes);
-		spin_unlock(&shmem_ilock);
 		kaddr = kmap_atomic(page, KM_USER0);
 		memcpy(kaddr, symname, len);
 		kunmap_atomic(kaddr, KM_USER0);
@@ -1779,53 +1837,75 @@
 static int shmem_remount_fs(struct super_block *sb, int *flags, char *data)
 {
 	struct shmem_sb_info *sbinfo = SHMEM_SB(sb);
-	unsigned long max_blocks = sbinfo->max_blocks;
-	unsigned long max_inodes = sbinfo->max_inodes;
+	unsigned long max_blocks = 0;
+	unsigned long max_inodes = 0;
 
+	if (sbinfo) {
+		max_blocks = sbinfo->max_blocks;
+		max_inodes = sbinfo->max_inodes;
+	}
 	if (shmem_parse_options(data, NULL, NULL, NULL, &max_blocks, &max_inodes))
 		return -EINVAL;
+	/* Keep it simple: disallow limited <-> unlimited remount */
+	if ((max_blocks || max_inodes) == !sbinfo)
+		return -EINVAL;
+	/* But allow the pointless unlimited -> unlimited remount */
+	if (!sbinfo)
+		return 0;
 	return shmem_set_size(sbinfo, max_blocks, max_inodes);
 }
 #endif
 
+static void shmem_put_super(struct super_block *sb)
+{
+	kfree(sb->s_fs_info);
+	sb->s_fs_info = NULL;
+}
+
 static int shmem_fill_super(struct super_block *sb,
 			    void *data, int silent)
 {
 	struct inode *inode;
 	struct dentry *root;
-	unsigned long blocks, inodes;
 	int mode   = S_IRWXUGO | S_ISVTX;
 	uid_t uid = current->fsuid;
 	gid_t gid = current->fsgid;
-	struct shmem_sb_info *sbinfo;
 	int err = -ENOMEM;
 
-	sbinfo = kmalloc(sizeof(struct shmem_sb_info), GFP_KERNEL);
-	if (!sbinfo)
-		return -ENOMEM;
-	sb->s_fs_info = sbinfo;
-	memset(sbinfo, 0, sizeof(struct shmem_sb_info));
+#ifdef CONFIG_TMPFS
+	unsigned long blocks = 0;
+	unsigned long inodes = 0;
 
 	/*
 	 * Per default we only allow half of the physical ram per
-	 * tmpfs instance
+	 * tmpfs instance, limiting inodes to one per page of lowmem;
+	 * but the internal instance is left unlimited.
 	 */
-	blocks = inodes = totalram_pages / 2;
-
-#ifdef CONFIG_TMPFS
-	if (shmem_parse_options(data, &mode, &uid, &gid, &blocks, &inodes)) {
-		err = -EINVAL;
-		goto failed;
+	if (!(sb->s_flags & MS_NOUSER)) {
+		blocks = totalram_pages / 2;
+		inodes = totalram_pages - totalhigh_pages;
+		if (inodes > blocks)
+			inodes = blocks;
+
+		if (shmem_parse_options(data, &mode,
+					&uid, &gid, &blocks, &inodes))
+			return -EINVAL;
+	}
+
+	if (blocks || inodes) {
+		struct shmem_sb_info *sbinfo;
+		sbinfo = kmalloc(sizeof(struct shmem_sb_info), GFP_KERNEL);
+		if (!sbinfo)
+			return -ENOMEM;
+		sb->s_fs_info = sbinfo;
+		spin_lock_init(&sbinfo->stat_lock);
+		sbinfo->max_blocks = blocks;
+		sbinfo->free_blocks = blocks;
+		sbinfo->max_inodes = inodes;
+		sbinfo->free_inodes = inodes;
 	}
-#else
-	sb->s_flags |= MS_NOUSER;
 #endif
 
-	spin_lock_init(&sbinfo->stat_lock);
-	sbinfo->max_blocks = blocks;
-	sbinfo->free_blocks = blocks;
-	sbinfo->max_inodes = inodes;
-	sbinfo->free_inodes = inodes;
 	sb->s_maxbytes = SHMEM_MAX_BYTES;
 	sb->s_blocksize = PAGE_CACHE_SIZE;
 	sb->s_blocksize_bits = PAGE_CACHE_SHIFT;
@@ -1845,17 +1925,10 @@
 failed_iput:
 	iput(inode);
 failed:
-	kfree(sbinfo);
-	sb->s_fs_info = NULL;
+	shmem_put_super(sb);
 	return err;
 }
 
-static void shmem_put_super(struct super_block *sb)
-{
-	kfree(sb->s_fs_info);
-	sb->s_fs_info = NULL;
-}
-
 static kmem_cache_t *shmem_inode_cachep;
 
 static struct inode *shmem_alloc_inode(struct super_block *sb)
@@ -1887,8 +1960,7 @@
 {
 	shmem_inode_cachep = kmem_cache_create("shmem_inode_cache",
 				sizeof(struct shmem_inode_info),
-				0, SLAB_HWCACHE_ALIGN|SLAB_RECLAIM_ACCOUNT,
-				init_once, NULL);
+				0, 0, init_once, NULL);
 	if (shmem_inode_cachep == NULL)
 		return -ENOMEM;
 	return 0;
@@ -1990,15 +2062,13 @@
 #ifdef CONFIG_TMPFS
 	devfs_mk_dir("shm");
 #endif
-	shm_mnt = kern_mount(&tmpfs_fs_type);
+	shm_mnt = do_kern_mount(tmpfs_fs_type.name, MS_NOUSER,
+				tmpfs_fs_type.name, NULL);
 	if (IS_ERR(shm_mnt)) {
 		error = PTR_ERR(shm_mnt);
 		printk(KERN_ERR "Could not kern_mount tmpfs\n");
 		goto out1;
 	}
-
-	/* The internal instance should not do size checking */
-	shmem_set_size(SHMEM_SB(shm_mnt->mnt_sb), ULONG_MAX, ULONG_MAX);
 	return 0;
 
 out1:
@@ -2029,7 +2099,7 @@
 	if (IS_ERR(shm_mnt))
 		return (void *)shm_mnt;
 
-	if (size > SHMEM_MAX_BYTES)
+	if (size < 0 || size > SHMEM_MAX_BYTES)
 		return ERR_PTR(-EINVAL);
 
 	if (shmem_acct_size(flags, size))
@@ -2063,7 +2133,7 @@
 	file->f_mapping = inode->i_mapping;
 	file->f_op = &shmem_file_operations;
 	file->f_mode = FMODE_WRITE | FMODE_READ;
-	return(file);
+	return file;
 
 close_file:
 	put_filp(file);
diff -Nru a/mm/slab.c b/mm/slab.c
--- a/mm/slab.c	2004-10-18 14:57:21 -07:00
+++ b/mm/slab.c	2004-10-18 14:57:21 -07:00
@@ -91,10 +91,12 @@
 #include	<linux/cpu.h>
 #include	<linux/sysctl.h>
 #include	<linux/module.h>
+#include	<linux/rcupdate.h>
 
 #include	<asm/uaccess.h>
 #include	<asm/cacheflush.h>
 #include	<asm/tlbflush.h>
+#include	<asm/page.h>
 
 /*
  * DEBUG	- 1 for kmem_cache_create() to honour; SLAB_DEBUG_INITIAL,
@@ -139,11 +141,13 @@
 			 SLAB_POISON | SLAB_HWCACHE_ALIGN | \
 			 SLAB_NO_REAP | SLAB_CACHE_DMA | \
 			 SLAB_MUST_HWCACHE_ALIGN | SLAB_STORE_USER | \
-			 SLAB_RECLAIM_ACCOUNT | SLAB_PANIC)
+			 SLAB_RECLAIM_ACCOUNT | SLAB_PANIC | \
+			 SLAB_DESTROY_BY_RCU)
 #else
 # define CREATE_MASK	(SLAB_HWCACHE_ALIGN | SLAB_NO_REAP | \
 			 SLAB_CACHE_DMA | SLAB_MUST_HWCACHE_ALIGN | \
-			 SLAB_RECLAIM_ACCOUNT | SLAB_PANIC)
+			 SLAB_RECLAIM_ACCOUNT | SLAB_PANIC | \
+			 SLAB_DESTROY_BY_RCU)
 #endif
 
 /*
@@ -190,6 +194,28 @@
 };
 
 /*
+ * struct slab_rcu
+ *
+ * slab_destroy on a SLAB_DESTROY_BY_RCU cache uses this structure to
+ * arrange for kmem_freepages to be called via RCU.  This is useful if
+ * we need to approach a kernel structure obliquely, from its address
+ * obtained without the usual locking.  We can lock the structure to
+ * stabilize it and check it's still at the given address, only if we
+ * can be sure that the memory has not been meanwhile reused for some
+ * other kind of object (which our subsystem's lock might corrupt).
+ *
+ * rcu_read_lock before reading the address, then rcu_read_unlock after
+ * taking the spinlock within the structure expected at that address.
+ *
+ * We assume struct slab_rcu can overlay struct slab when destroying.
+ */
+struct slab_rcu {
+	struct rcu_head		head;
+	kmem_cache_t		*cachep;
+	void			*addr;
+};
+
+/*
  * struct array_cache
  *
  * Per cpu structures
@@ -478,8 +504,10 @@
 #undef CACHE
 };
 
-struct arraycache_init initarray_cache __initdata = { { 0, BOOT_CPUCACHE_ENTRIES, 1, 0} };
-struct arraycache_init initarray_generic __initdata = { { 0, BOOT_CPUCACHE_ENTRIES, 1, 0} };
+static struct arraycache_init initarray_cache __initdata =
+	{ { 0, BOOT_CPUCACHE_ENTRIES, 1, 0} };
+static struct arraycache_init initarray_generic __initdata =
+	{ { 0, BOOT_CPUCACHE_ENTRIES, 1, 0} };
 
 /* internal cache of cache description objs */
 static kmem_cache_t cache_cache = {
@@ -497,8 +525,7 @@
 
 /* Guard access to the cache-chain. */
 static struct semaphore	cache_chain_sem;
-
-struct list_head cache_chain;
+static struct list_head cache_chain;
 
 /*
  * vm_enough_memory() looks at this to determine how many
@@ -513,17 +540,17 @@
  * chicken and egg problem: delay the per-cpu array allocation
  * until the general caches are up.
  */
-enum {
+static enum {
 	NONE,
 	PARTIAL,
 	FULL
 } g_cpucache_up;
 
-static DEFINE_PER_CPU(struct timer_list, reap_timers);
+static DEFINE_PER_CPU(struct work_struct, reap_work);
 
-static void reap_timer_fnc(unsigned long data);
 static void free_block(kmem_cache_t* cachep, void** objpp, int len);
 static void enable_cpucache (kmem_cache_t *cachep);
+static void cache_reap (void *unused);
 
 static inline void ** ac_entry(struct array_cache *ac)
 {
@@ -535,6 +562,22 @@
 	return cachep->array[smp_processor_id()];
 }
 
+static kmem_cache_t * kmem_find_general_cachep (size_t size, int gfpflags)
+{
+	struct cache_sizes *csizep = malloc_sizes;
+
+	/* This function could be moved to the header file, and
+	 * made inline so consumers can quickly determine what
+	 * cache pointer they require.
+	 */
+	for ( ; csizep->cs_size; csizep++) {
+		if (size > csizep->cs_size)
+			continue;
+		break;
+	}
+	return (gfpflags & GFP_DMA) ? csizep->cs_dmacachep : csizep->cs_cachep;
+}
+
 /* Cal the num objs, wastage, and bytes left over for a given slab size. */
 static void cache_estimate (unsigned long gfporder, size_t size, size_t align,
 		 int flags, size_t *left_over, unsigned int *num)
@@ -573,35 +616,26 @@
 }
 
 /*
- * Start the reap timer running on the target CPU.  We run at around 1 to 2Hz.
- * Add the CPU number into the expiry time to minimize the possibility of the
- * CPUs getting into lockstep and contending for the global cache chain lock.
+ * Initiate the reap timer running on the target CPU.  We run at around 1 to 2Hz
+ * via the workqueue/eventd.
+ * Add the CPU number into the expiration time to minimize the possibility of
+ * the CPUs getting into lockstep and contending for the global cache chain
+ * lock.
  */
 static void __devinit start_cpu_timer(int cpu)
 {
-	struct timer_list *rt = &per_cpu(reap_timers, cpu);
-
-	if (rt->function == NULL) {
-		init_timer(rt);
-		rt->expires = jiffies + HZ + 3*cpu;
-		rt->data = cpu;
-		rt->function = reap_timer_fnc;
-		add_timer_on(rt, cpu);
-	}
-}
-
-#ifdef CONFIG_HOTPLUG_CPU
-static void stop_cpu_timer(int cpu)
-{
-	struct timer_list *rt = &per_cpu(reap_timers, cpu);
+	struct work_struct *reap_work = &per_cpu(reap_work, cpu);
 
-	if (rt->function) {
-		del_timer_sync(rt);
-		WARN_ON(timer_pending(rt));
-		rt->function = NULL;
+	/*
+	 * When this gets called from do_initcalls via cpucache_init(),
+	 * init_workqueues() has already run, so keventd will be setup
+	 * at that time.
+	 */
+	if (keventd_up() && reap_work->func == NULL) {
+		INIT_WORK(reap_work, cache_reap, NULL);
+		schedule_delayed_work_on(cpu, reap_work, HZ + 3 * cpu);
 	}
 }
-#endif
 
 static struct array_cache *alloc_arraycache(int cpu, int entries, int batchcount)
 {
@@ -654,7 +688,6 @@
 		break;
 #ifdef CONFIG_HOTPLUG_CPU
 	case CPU_DEAD:
-		stop_cpu_timer(cpu);
 		/* fall thru */
 	case CPU_UP_CANCELED:
 		down(&cache_chain_sem);
@@ -806,7 +839,7 @@
 	 */
 }
 
-int __init cpucache_init(void)
+static int __init cpucache_init(void)
 {
 	int cpu;
 
@@ -883,6 +916,16 @@
 		atomic_sub(1<<cachep->gfporder, &slab_reclaim_pages);
 }
 
+static void kmem_rcu_free(struct rcu_head *head)
+{
+	struct slab_rcu *slab_rcu = (struct slab_rcu *) head;
+	kmem_cache_t *cachep = slab_rcu->cachep;
+
+	kmem_freepages(cachep, slab_rcu->addr);
+	if (OFF_SLAB(cachep))
+		kmem_cache_free(cachep->slabp_cache, slab_rcu);
+}
+
 #if DEBUG
 
 #ifdef CONFIG_DEBUG_PAGEALLOC
@@ -938,9 +981,10 @@
 }
 #endif
 
+#if DEBUG
+
 static void print_objinfo(kmem_cache_t *cachep, void *objp, int lines)
 {
-#if DEBUG
 	int i, size;
 	char *realobj;
 
@@ -951,8 +995,10 @@
 	}
 
 	if (cachep->flags & SLAB_STORE_USER) {
-		printk(KERN_ERR "Last user: [<%p>]", *dbg_userword(cachep, objp));
-		print_symbol("(%s)", (unsigned long)*dbg_userword(cachep, objp));
+		printk(KERN_ERR "Last user: [<%p>]",
+				*dbg_userword(cachep, objp));
+		print_symbol("(%s)",
+				(unsigned long)*dbg_userword(cachep, objp));
 		printk("\n");
 	}
 	realobj = (char*)objp+obj_dbghead(cachep);
@@ -964,11 +1010,8 @@
 			limit = size-i;
 		dump_line(realobj, i, limit);
 	}
-#endif
 }
 
-#if DEBUG
-
 static void check_poison_obj(kmem_cache_t *cachep, void *objp)
 {
 	char *realobj;
@@ -1036,6 +1079,8 @@
  */
 static void slab_destroy (kmem_cache_t *cachep, struct slab *slabp)
 {
+	void *addr = slabp->s_mem - slabp->colouroff;
+
 #if DEBUG
 	int i;
 	for (i = 0; i < cachep->num; i++) {
@@ -1071,10 +1116,19 @@
 		}
 	}
 #endif
-	
-	kmem_freepages(cachep, slabp->s_mem-slabp->colouroff);
-	if (OFF_SLAB(cachep))
-		kmem_cache_free(cachep->slabp_cache, slabp);
+
+	if (unlikely(cachep->flags & SLAB_DESTROY_BY_RCU)) {
+		struct slab_rcu *slab_rcu;
+
+		slab_rcu = (struct slab_rcu *) slabp;
+		slab_rcu->cachep = cachep;
+		slab_rcu->addr = addr;
+		call_rcu(&slab_rcu->head, kmem_rcu_free);
+	} else {
+		kmem_freepages(cachep, addr);
+		if (OFF_SLAB(cachep))
+			kmem_cache_free(cachep->slabp_cache, slabp);
+	}
 }
 
 /**
@@ -1149,9 +1203,15 @@
 	 */
 	if ((size < 4096 || fls(size-1) == fls(size-1+3*BYTES_PER_WORD)))
 		flags |= SLAB_RED_ZONE|SLAB_STORE_USER;
-	flags |= SLAB_POISON;
+	if (!(flags & SLAB_DESTROY_BY_RCU))
+		flags |= SLAB_POISON;
 #endif
+	if (flags & SLAB_DESTROY_BY_RCU)
+		BUG_ON(flags & SLAB_POISON);
 #endif
+	if (flags & SLAB_DESTROY_BY_RCU)
+		BUG_ON(dtor);
+
 	/*
 	 * Always checks flags, a caller might be expecting debug
 	 * support which isn't available.
@@ -1563,6 +1623,9 @@
 		return 1;
 	}
 
+	if (unlikely(cachep->flags & SLAB_DESTROY_BY_RCU))
+		synchronize_kernel();
+
 	/* no cpu_online check required here since we clear the percpu
 	 * array on cpu offline and set this to NULL.
 	 */
@@ -2372,8 +2435,7 @@
 /**
  * __alloc_percpu - allocate one copy of the object for every present
  * cpu in the system, zeroing them.
- * Objects should be dereferenced using per_cpu_ptr/get_cpu_ptr
- * macros only.
+ * Objects should be dereferenced using the per_cpu_ptr macro only.
  *
  * @size: how many bytes of memory are required.
  * @align: the alignment, which can't be greater than SMP_CACHE_BYTES.
@@ -2434,6 +2496,27 @@
 EXPORT_SYMBOL(kmem_cache_free);
 
 /**
+ * kcalloc - allocate memory for an array. The memory is set to zero.
+ * @n: number of elements.
+ * @size: element size.
+ * @flags: the type of memory to allocate.
+ */
+void *kcalloc(size_t n, size_t size, int flags)
+{
+	void *ret = NULL;
+
+	if (n != 0 && size > INT_MAX / n)
+		return ret;
+
+	ret = kmalloc(n * size, flags);
+	if (ret)
+		memset(ret, 0, n * size);
+	return ret;
+}
+
+EXPORT_SYMBOL(kcalloc);
+
+/**
  * kfree - free previously allocated memory
  * @objp: pointer returned by kmalloc.
  *
@@ -2487,24 +2570,6 @@
 
 EXPORT_SYMBOL(kmem_cache_size);
 
-kmem_cache_t * kmem_find_general_cachep (size_t size, int gfpflags)
-{
-	struct cache_sizes *csizep = malloc_sizes;
-
-	/* This function could be moved to the header file, and
-	 * made inline so consumers can quickly determine what
-	 * cache pointer they require.
-	 */
-	for ( ; csizep->cs_size; csizep++) {
-		if (size > csizep->cs_size)
-			continue;
-		break;
-	}
-	return (gfpflags & GFP_DMA) ? csizep->cs_dmacachep : csizep->cs_cachep;
-}
-
-EXPORT_SYMBOL(kmem_find_general_cachep);
-
 struct ccupdate_struct {
 	kmem_cache_t *cachep;
 	struct array_cache *new[NR_CPUS];
@@ -2630,27 +2695,6 @@
 					cachep->name, -err);
 }
 
-static void drain_array(kmem_cache_t *cachep, struct array_cache *ac)
-{
-	int tofree;
-
-	check_irq_off();
-	if (ac->touched) {
-		ac->touched = 0;
-	} else if (ac->avail) {
-		tofree = (ac->limit+4)/5;
-		if (tofree > ac->avail) {
-			tofree = (ac->avail+1)/2;
-		}
-		spin_lock(&cachep->spinlock);
-		free_block(cachep, ac_entry(ac), tofree);
-		spin_unlock(&cachep->spinlock);
-		ac->avail -= tofree;
-		memmove(&ac_entry(ac)[0], &ac_entry(ac)[tofree],
-					sizeof(void*)*ac->avail);
-	}
-}
-
 static void drain_array_locked(kmem_cache_t *cachep,
 				struct array_cache *ac, int force)
 {
@@ -2674,24 +2718,23 @@
 /**
  * cache_reap - Reclaim memory from caches.
  *
- * Called from a timer, every few seconds
+ * Called from workqueue/eventd every few seconds.
  * Purpose:
  * - clear the per-cpu caches for this CPU.
  * - return freeable pages to the main free memory pool.
  *
  * If we cannot acquire the cache chain semaphore then just give up - we'll
- * try again next timer interrupt.
+ * try again on the next iteration.
  */
-static void cache_reap (void)
+static void cache_reap(void *unused)
 {
 	struct list_head *walk;
 
-#if DEBUG
-	BUG_ON(!in_interrupt());
-	BUG_ON(in_irq());
-#endif
-	if (down_trylock(&cache_chain_sem))
+	if (down_trylock(&cache_chain_sem)) {
+		/* Give up. Setup the next iteration. */
+		schedule_delayed_work(&__get_cpu_var(reap_work), REAPTIMEOUT_CPUC + smp_processor_id());
 		return;
+	}
 
 	list_for_each(walk, &cache_chain) {
 		kmem_cache_t *searchp;
@@ -2705,16 +2748,14 @@
 			goto next;
 
 		check_irq_on();
-		local_irq_disable();
-		drain_array(searchp, ac_data(searchp));
 
-		if(time_after(searchp->lists.next_reap, jiffies))
-			goto next_irqon;
+		spin_lock_irq(&searchp->spinlock);
 
-		spin_lock(&searchp->spinlock);
-		if(time_after(searchp->lists.next_reap, jiffies)) {
+		drain_array_locked(searchp, ac_data(searchp), 0);
+
+		if(time_after(searchp->lists.next_reap, jiffies))
 			goto next_unlock;
-		}
+
 		searchp->lists.next_reap = jiffies + REAPTIMEOUT_LIST3;
 
 		if (searchp->lists.shared)
@@ -2747,30 +2788,14 @@
 			spin_lock_irq(&searchp->spinlock);
 		} while(--tofree > 0);
 next_unlock:
-		spin_unlock(&searchp->spinlock);
-next_irqon:
-		local_irq_enable();
+		spin_unlock_irq(&searchp->spinlock);
 next:
 		;
 	}
 	check_irq_on();
 	up(&cache_chain_sem);
-}
-
-/*
- * This is a timer handler.  There is one per CPU.  It is called periodially
- * to shrink this CPU's caches.  Otherwise there could be memory tied up
- * for long periods (or for ever) due to load changes.
- */
-static void reap_timer_fnc(unsigned long cpu)
-{
-	struct timer_list *rt = &__get_cpu_var(reap_timers);
-
-	/* CPU hotplug can drag us off cpu: don't run on wrong CPU */
-	if (!cpu_is_offline(cpu)) {
-		cache_reap();
-		mod_timer(rt, jiffies + REAPTIMEOUT_CPUC + cpu);
-	}
+	/* Setup the next iteration */
+	schedule_delayed_work(&__get_cpu_var(reap_work), REAPTIMEOUT_CPUC + smp_processor_id());
 }
 
 #ifdef CONFIG_PROC_FS
@@ -2996,73 +3021,4 @@
 	}
 
 	return size;
-}
-
-void ptrinfo(unsigned long addr)
-{
-	struct page *page;
-
-	printk("Dumping data about address %p.\n", (void*)addr);
-	if (!virt_addr_valid((void*)addr)) {
-		printk("virt addr invalid.\n");
-		return;
-	}
-#ifdef CONFIG_MMU
-	do {
-		pgd_t *pgd = pgd_offset_k(addr);
-		pmd_t *pmd;
-		if (pgd_none(*pgd)) {
-			printk("No pgd.\n");
-			break;
-		}
-		pmd = pmd_offset(pgd, addr);
-		if (pmd_none(*pmd)) {
-			printk("No pmd.\n");
-			break;
-		}
-#ifdef CONFIG_X86
-		if (pmd_large(*pmd)) {
-			printk("Large page.\n");
-			break;
-		}
-#endif
-		printk("normal page, pte_val 0x%llx\n",
-		  (unsigned long long)pte_val(*pte_offset_kernel(pmd, addr)));
-	} while(0);
-#endif
-
-	page = virt_to_page((void*)addr);
-	printk("struct page at %p, flags %08lx\n",
-			page, (unsigned long)page->flags);
-	if (PageSlab(page)) {
-		kmem_cache_t *c;
-		struct slab *s;
-		unsigned long flags;
-		int objnr;
-		void *objp;
-
-		c = GET_PAGE_CACHE(page);
-		printk("belongs to cache %s.\n",c->name);
-
-		spin_lock_irqsave(&c->spinlock, flags);
-		s = GET_PAGE_SLAB(page);
-		printk("slabp %p with %d inuse objects (from %d).\n",
-			s, s->inuse, c->num);
-		check_slabp(c,s);
-
-		objnr = (addr-(unsigned long)s->s_mem)/c->objsize;
-		objp = s->s_mem+c->objsize*objnr;
-		printk("points into object no %d, starting at %p, len %d.\n",
-			objnr, objp, c->objsize);
-		if (objnr >= c->num) {
-			printk("Bad obj number.\n");
-		} else {
-			kernel_map_pages(virt_to_page(objp),
-					c->objsize/PAGE_SIZE, 1);
-
-			print_objinfo(c, objp, 2);
-		}
-		spin_unlock_irqrestore(&c->spinlock, flags);
-
-	}
 }
diff -Nru a/mm/swap_state.c b/mm/swap_state.c
--- a/mm/swap_state.c	2004-10-18 14:56:29 -07:00
+++ b/mm/swap_state.c	2004-10-18 14:56:29 -07:00
@@ -171,7 +171,7 @@
 		/*
 		 * Add it to the swap cache and mark it dirty
 		 */
-		err = __add_to_swap_cache(page, entry, GFP_ATOMIC);
+		err = __add_to_swap_cache(page, entry, GFP_ATOMIC|__GFP_NOWARN);
 
 		if (pf_flags & PF_MEMALLOC)
 			current->flags |= PF_MEMALLOC;
diff -Nru a/mm/swapfile.c b/mm/swapfile.c
--- a/mm/swapfile.c	2004-10-18 14:56:17 -07:00
+++ b/mm/swapfile.c	2004-10-18 14:56:17 -07:00
@@ -520,14 +520,24 @@
 }
 
 /* vma->vm_mm->page_table_lock is held */
-static unsigned long unuse_vma(struct vm_area_struct * vma, pgd_t *pgdir,
+static unsigned long unuse_vma(struct vm_area_struct * vma,
 	swp_entry_t entry, struct page *page)
 {
-	unsigned long start = vma->vm_start, end = vma->vm_end;
+	pgd_t *pgdir;
+	unsigned long start, end;
 	unsigned long foundaddr;
 
-	if (start >= end)
-		BUG();
+	if (page->mapping) {
+		start = page_address_in_vma(page, vma);
+		if (start == -EFAULT)
+			return 0;
+		else
+			end = start + PAGE_SIZE;
+	} else {
+		start = vma->vm_start;
+		end = vma->vm_end;
+	}
+	pgdir = pgd_offset(vma->vm_mm, start);
 	do {
 		foundaddr = unuse_pgd(vma, pgdir, start, end - start,
 						entry, page);
@@ -559,9 +569,8 @@
 	}
 	spin_lock(&mm->page_table_lock);
 	for (vma = mm->mmap; vma; vma = vma->vm_next) {
-		if (!is_vm_hugetlb_page(vma)) {
-			pgd_t * pgd = pgd_offset(mm, vma->vm_start);
-			foundaddr = unuse_vma(vma, pgd, entry, page);
+		if (vma->anon_vma) {
+			foundaddr = unuse_vma(vma, entry, page);
 			if (foundaddr)
 				break;
 		}
diff -Nru a/mm/thrash.c b/mm/thrash.c
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/mm/thrash.c	2004-10-18 14:57:22 -07:00
@@ -0,0 +1,98 @@
+/*
+ * mm/thrash.c
+ *
+ * Copyright (C) 2004, Red Hat, Inc.
+ * Copyright (C) 2004, Rik van Riel <riel@redhat.com>
+ * Released under the GPL, see the file COPYING for details.
+ *
+ * Simple token based thrashing protection, using the algorithm
+ * described in:  http://www.cs.wm.edu/~sjiang/token.pdf
+ */
+#include <linux/jiffies.h>
+#include <linux/mm.h>
+#include <linux/sched.h>
+#include <linux/swap.h>
+
+static spinlock_t swap_token_lock = SPIN_LOCK_UNLOCKED;
+static unsigned long swap_token_timeout;
+unsigned long swap_token_check;
+struct mm_struct * swap_token_mm = &init_mm;
+
+#define SWAP_TOKEN_CHECK_INTERVAL (HZ * 2)
+#define SWAP_TOKEN_TIMEOUT (HZ * 300)
+
+/*
+ * Take the token away if the process had no page faults
+ * in the last interval, or if it has held the token for
+ * too long.
+ */
+#define SWAP_TOKEN_ENOUGH_RSS 1
+#define SWAP_TOKEN_TIMED_OUT 2
+static int should_release_swap_token(struct mm_struct *mm)
+{
+	int ret = 0;
+	if (!mm->recent_pagein)
+		ret = SWAP_TOKEN_ENOUGH_RSS;
+	else if (time_after(jiffies, swap_token_timeout))
+		ret = SWAP_TOKEN_TIMED_OUT;
+	mm->recent_pagein = 0;
+	return ret;
+}
+
+/*
+ * Try to grab the swapout protection token.  We only try to
+ * grab it once every TOKEN_CHECK_INTERVAL, both to prevent
+ * SMP lock contention and to check that the process that held
+ * the token before is no longer thrashing.
+ */
+void grab_swap_token(void)
+{
+	struct mm_struct *mm;
+	int reason;
+
+	/* We have the token. Let others know we still need it. */
+	if (has_swap_token(current->mm)) {
+		current->mm->recent_pagein = 1;
+		return;
+	}
+
+	if (time_after(jiffies, swap_token_check)) {
+
+		/* Can't get swapout protection if we exceed our RSS limit. */
+		// if (current->mm->rss > current->mm->rlimit_rss)
+		//	return;
+
+		/* ... or if we recently held the token. */
+		if (time_before(jiffies, current->mm->swap_token_time))
+			return;
+
+		if (!spin_trylock(&swap_token_lock))
+			return;
+
+		swap_token_check = jiffies + SWAP_TOKEN_CHECK_INTERVAL;
+
+		mm = swap_token_mm;
+		if ((reason = should_release_swap_token(mm))) {
+			unsigned long eligible = jiffies;
+			if (reason == SWAP_TOKEN_TIMED_OUT) {
+				eligible += SWAP_TOKEN_TIMEOUT;
+			}
+			mm->swap_token_time = eligible;
+			swap_token_timeout = jiffies + SWAP_TOKEN_TIMEOUT;
+			swap_token_mm = current->mm;
+		}
+		spin_unlock(&swap_token_lock);
+	}
+	return;
+}
+
+/* Called on process exit. */
+void __put_swap_token(struct mm_struct *mm)
+{
+	spin_lock(&swap_token_lock);
+	if (likely(mm == swap_token_mm)) {
+		swap_token_mm = &init_mm;
+		swap_token_check = jiffies;
+	}
+	spin_unlock(&swap_token_lock);
+}
diff -Nru a/mm/tiny-shmem.c b/mm/tiny-shmem.c
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/mm/tiny-shmem.c	2004-10-18 14:57:24 -07:00
@@ -0,0 +1,124 @@
+/*
+ * tiny-shmem.c: simple shmemfs and tmpfs using ramfs code
+ *
+ * Matt Mackall <mpm@selenic.com> January, 2004
+ * derived from mm/shmem.c and fs/ramfs/inode.c
+ *
+ * This is intended for small system where the benefits of the full
+ * shmem code (swap-backed and resource-limited) are outweighed by
+ * their complexity. On systems without swap this code should be
+ * effectively equivalent, but much lighter weight.
+ */
+
+#include <linux/fs.h>
+#include <linux/init.h>
+#include <linux/devfs_fs_kernel.h>
+#include <linux/vfs.h>
+#include <linux/mount.h>
+#include <linux/file.h>
+#include <linux/mm.h>
+#include <linux/module.h>
+#include <linux/swap.h>
+#include <linux/ramfs.h>
+
+static struct file_system_type tmpfs_fs_type = {
+	.name		= "tmpfs",
+	.get_sb		= ramfs_get_sb,
+	.kill_sb	= kill_litter_super,
+};
+
+static struct vfsmount *shm_mnt;
+
+static int __init init_tmpfs(void)
+{
+	register_filesystem(&tmpfs_fs_type);
+#ifdef CONFIG_TMPFS
+	devfs_mk_dir("shm");
+#endif
+	shm_mnt = kern_mount(&tmpfs_fs_type);
+	return 0;
+}
+module_init(init_tmpfs)
+
+/*
+ * shmem_file_setup - get an unlinked file living in tmpfs
+ *
+ * @name: name for dentry (to be seen in /proc/<pid>/maps
+ * @size: size to be set for the file
+ *
+ */
+struct file *shmem_file_setup(char *name, loff_t size, unsigned long flags)
+{
+	int error;
+	struct file *file;
+	struct inode *inode;
+	struct dentry *dentry, *root;
+	struct qstr this;
+
+	if (IS_ERR(shm_mnt))
+		return (void *)shm_mnt;
+
+	error = -ENOMEM;
+	this.name = name;
+	this.len = strlen(name);
+	this.hash = 0; /* will go */
+	root = shm_mnt->mnt_root;
+	dentry = d_alloc(root, &this);
+	if (!dentry)
+		goto put_memory;
+
+	error = -ENFILE;
+	file = get_empty_filp();
+	if (!file)
+		goto put_dentry;
+
+	error = -ENOSPC;
+	inode = ramfs_get_inode(root->d_sb, S_IFREG | S_IRWXUGO, 0);
+	if (!inode)
+		goto close_file;
+
+	d_instantiate(dentry, inode);
+	inode->i_size = size;
+	inode->i_nlink = 0;	/* It is unlinked */
+	file->f_vfsmnt = mntget(shm_mnt);
+	file->f_dentry = dentry;
+	file->f_mapping = inode->i_mapping;
+	file->f_op = &ramfs_file_operations;
+	file->f_mode = FMODE_WRITE | FMODE_READ;
+	return file;
+
+close_file:
+	put_filp(file);
+put_dentry:
+	dput(dentry);
+put_memory:
+	return ERR_PTR(error);
+}
+
+/*
+ * shmem_zero_setup - setup a shared anonymous mapping
+ *
+ * @vma: the vma to be mmapped is prepared by do_mmap_pgoff
+ */
+int shmem_zero_setup(struct vm_area_struct *vma)
+{
+	struct file *file;
+	loff_t size = vma->vm_end - vma->vm_start;
+
+	file = shmem_file_setup("dev/zero", size, vma->vm_flags);
+	if (IS_ERR(file))
+		return PTR_ERR(file);
+
+	if (vma->vm_file)
+		fput(vma->vm_file);
+	vma->vm_file = file;
+	vma->vm_ops = &generic_file_vm_ops;
+	return 0;
+}
+
+int shmem_unuse(swp_entry_t entry, struct page *page)
+{
+	return 0;
+}
+
+EXPORT_SYMBOL(shmem_file_setup);
diff -Nru a/mm/truncate.c b/mm/truncate.c
--- a/mm/truncate.c	2004-10-18 14:57:04 -07:00
+++ b/mm/truncate.c	2004-10-18 14:57:04 -07:00
@@ -155,6 +155,7 @@
 
 	next = start;
 	for ( ; ; ) {
+		cond_resched();
 		if (!pagevec_lookup(&pvec, mapping, next, PAGEVEC_SIZE)) {
 			if (next == start)
 				break;
diff -Nru a/mm/vmalloc.c b/mm/vmalloc.c
--- a/mm/vmalloc.c	2004-10-18 14:56:33 -07:00
+++ b/mm/vmalloc.c	2004-10-18 14:56:33 -07:00
@@ -179,11 +179,26 @@
 	return err;
 }
 
+#define IOREMAP_MAX_ORDER	(7 + PAGE_SHIFT)	/* 128 pages */
+
 struct vm_struct *__get_vm_area(unsigned long size, unsigned long flags,
 				unsigned long start, unsigned long end)
 {
 	struct vm_struct **p, *tmp, *area;
-	unsigned long addr = start;
+	unsigned long align = 1;
+	unsigned long addr;
+
+	if (flags & VM_IOREMAP) {
+		int bit = fls(size);
+
+		if (bit > IOREMAP_MAX_ORDER)
+			bit = IOREMAP_MAX_ORDER;
+		else if (bit < PAGE_SHIFT)
+			bit = PAGE_SHIFT;
+
+		align = 1ul << bit;
+	}
+	addr = ALIGN(start, align);
 
 	area = kmalloc(sizeof(*area), GFP_KERNEL);
 	if (unlikely(!area))
@@ -200,13 +215,17 @@
 
 	write_lock(&vmlist_lock);
 	for (p = &vmlist; (tmp = *p) != NULL ;p = &tmp->next) {
-		if ((unsigned long)tmp->addr < addr)
+		if ((unsigned long)tmp->addr < addr) {
+			if((unsigned long)tmp->addr + tmp->size >= addr)
+				addr = ALIGN(tmp->size + 
+					     (unsigned long)tmp->addr, align);
 			continue;
+		}
 		if ((size + addr) < addr)
 			goto out;
 		if (size + addr <= (unsigned long)tmp->addr)
 			goto found;
-		addr = tmp->size + (unsigned long)tmp->addr;
+		addr = ALIGN(tmp->size + (unsigned long)tmp->addr, align);
 		if (addr > end - size)
 			goto out;
 	}
@@ -228,6 +247,8 @@
 out:
 	write_unlock(&vmlist_lock);
 	kfree(area);
+	if (printk_ratelimit())
+		printk(KERN_WARNING "allocation failed: out of vmalloc space - use vmalloc=<size> to increase size.\n");
 	return NULL;
 }
 
diff -Nru a/mm/vmscan.c b/mm/vmscan.c
--- a/mm/vmscan.c	2004-10-18 14:55:55 -07:00
+++ b/mm/vmscan.c	2004-10-18 14:55:55 -07:00
@@ -32,6 +32,7 @@
 #include <linux/topology.h>
 #include <linux/cpu.h>
 #include <linux/notifier.h>
+#include <linux/rwsem.h>
 
 #include <asm/tlbflush.h>
 #include <asm/div64.h>
@@ -122,7 +123,7 @@
 static long total_memory;
 
 static LIST_HEAD(shrinker_list);
-static DECLARE_MUTEX(shrinker_sem);
+static DECLARE_RWSEM(shrinker_rwsem);
 
 /*
  * Add a shrinker callback to be called from the vm
@@ -136,9 +137,9 @@
 	        shrinker->shrinker = theshrinker;
 	        shrinker->seeks = seeks;
 	        shrinker->nr = 0;
-	        down(&shrinker_sem);
+	        down_write(&shrinker_rwsem);
 	        list_add(&shrinker->list, &shrinker_list);
-	        up(&shrinker_sem);
+	        up_write(&shrinker_rwsem);
 	}
 	return shrinker;
 }
@@ -149,13 +150,13 @@
  */
 void remove_shrinker(struct shrinker *shrinker)
 {
-	down(&shrinker_sem);
+	down_write(&shrinker_rwsem);
 	list_del(&shrinker->list);
-	up(&shrinker_sem);
+	up_write(&shrinker_rwsem);
 	kfree(shrinker);
 }
 EXPORT_SYMBOL(remove_shrinker);
- 
+
 #define SHRINK_BATCH 128
 /*
  * Call the shrink functions to age shrinkable caches
@@ -179,11 +180,15 @@
 {
 	struct shrinker *shrinker;
 
-	if (down_trylock(&shrinker_sem))
+	if (scanned == 0)
+		scanned = SWAP_CLUSTER_MAX;
+
+	if (!down_read_trylock(&shrinker_rwsem))
 		return 0;
 
 	list_for_each_entry(shrinker, &shrinker_list, list) {
 		unsigned long long delta;
+		unsigned long total_scan;
 
 		delta = (4 * scanned) / shrinker->seeks;
 		delta *= (*shrinker->shrinker)(0, gfp_mask);
@@ -192,27 +197,29 @@
 		if (shrinker->nr < 0)
 			shrinker->nr = LONG_MAX;	/* It wrapped! */
 
-		if (shrinker->nr <= SHRINK_BATCH)
-			continue;
-		while (shrinker->nr) {
-			long this_scan = shrinker->nr;
+		total_scan = shrinker->nr;
+		shrinker->nr = 0;
+
+		while (total_scan >= SHRINK_BATCH) {
+			long this_scan = SHRINK_BATCH;
 			int shrink_ret;
 
-			if (this_scan > 128)
-				this_scan = 128;
 			shrink_ret = (*shrinker->shrinker)(this_scan, gfp_mask);
-			mod_page_state(slabs_scanned, this_scan);
-			shrinker->nr -= this_scan;
 			if (shrink_ret == -1)
 				break;
+			mod_page_state(slabs_scanned, this_scan);
+			total_scan -= this_scan;
+
 			cond_resched();
 		}
+
+		shrinker->nr += total_scan;
 	}
-	up(&shrinker_sem);
+	up_read(&shrinker_rwsem);
 	return 0;
 }
 
-/* Must be called with page's rmap lock held. */
+/* Called without lock on whether page is mapped, so answer is unstable */
 static inline int page_mapping_inuse(struct page *page)
 {
 	struct address_space *mapping;
@@ -370,26 +377,19 @@
 		if (page_mapped(page) || PageSwapCache(page))
 			sc->nr_scanned++;
 
-		page_map_lock(page);
-		referenced = page_referenced(page);
-		if (referenced && page_mapping_inuse(page)) {
-			/* In active use or really unfreeable.  Activate it. */
-			page_map_unlock(page);
+		referenced = page_referenced(page, 1);
+		/* In active use or really unfreeable?  Activate it. */
+		if (referenced && page_mapping_inuse(page))
 			goto activate_locked;
-		}
 
 #ifdef CONFIG_SWAP
 		/*
 		 * Anonymous process memory has backing store?
 		 * Try to allocate it some swap space here.
-		 *
-		 * XXX: implement swap clustering ?
 		 */
 		if (PageAnon(page) && !PageSwapCache(page)) {
-			page_map_unlock(page);
 			if (!add_to_swap(page))
 				goto activate_locked;
-			page_map_lock(page);
 		}
 #endif /* CONFIG_SWAP */
 
@@ -404,16 +404,13 @@
 		if (page_mapped(page) && mapping) {
 			switch (try_to_unmap(page)) {
 			case SWAP_FAIL:
-				page_map_unlock(page);
 				goto activate_locked;
 			case SWAP_AGAIN:
-				page_map_unlock(page);
 				goto keep_locked;
 			case SWAP_SUCCESS:
 				; /* try to free the page below */
 			}
 		}
-		page_map_unlock(page);
 
 		if (PageDirty(page)) {
 			if (referenced)
@@ -716,25 +713,12 @@
 		page = lru_to_page(&l_hold);
 		list_del(&page->lru);
 		if (page_mapped(page)) {
-			if (!reclaim_mapped) {
-				list_add(&page->lru, &l_active);
-				continue;
-			}
-			page_map_lock(page);
-			if (page_referenced(page)) {
-				page_map_unlock(page);
+			if (!reclaim_mapped ||
+			    (total_swap_pages == 0 && PageAnon(page)) ||
+			    page_referenced(page, 0)) {
 				list_add(&page->lru, &l_active);
 				continue;
 			}
-			page_map_unlock(page);
-		}
-		/*
-		 * FIXME: need to consider page_count(page) here if/when we
-		 * reap orphaned pages via the LRU (Daniel's locking stuff)
-		 */
-		if (total_swap_pages == 0 && PageAnon(page)) {
-			list_add(&page->lru, &l_active);
-			continue;
 		}
 		list_add(&page->lru, &l_inactive);
 	}
@@ -867,6 +851,9 @@
 	for (i = 0; zones[i] != NULL; i++) {
 		struct zone *zone = zones[i];
 
+		if (zone->present_pages == 0)
+			continue;
+
 		zone->temp_priority = sc->priority;
 		if (zone->prev_priority > sc->priority)
 			zone->prev_priority = sc->priority;
@@ -984,12 +971,16 @@
 static int balance_pgdat(pg_data_t *pgdat, int nr_pages)
 {
 	int to_free = nr_pages;
+	int all_zones_ok;
 	int priority;
 	int i;
-	int total_scanned = 0, total_reclaimed = 0;
+	int total_scanned, total_reclaimed;
 	struct reclaim_state *reclaim_state = current->reclaim_state;
 	struct scan_control sc;
 
+loop_again:
+	total_scanned = 0;
+	total_reclaimed = 0;
 	sc.gfp_mask = GFP_KERNEL;
 	sc.may_writepage = 0;
 	sc.nr_mapped = read_page_state(nr_mapped);
@@ -1003,10 +994,11 @@
 	}
 
 	for (priority = DEF_PRIORITY; priority >= 0; priority--) {
-		int all_zones_ok = 1;
 		int end_zone = 0;	/* Inclusive.  0 = ZONE_DMA */
 		unsigned long lru_pages = 0;
 
+		all_zones_ok = 1;
+
 		if (nr_pages == 0) {
 			/*
 			 * Scan in the highmem->dma direction for the highest
@@ -1015,6 +1007,9 @@
 			for (i = pgdat->nr_zones - 1; i >= 0; i--) {
 				struct zone *zone = pgdat->node_zones + i;
 
+				if (zone->present_pages == 0)
+					continue;
+
 				if (zone->all_unreclaimable &&
 						priority != DEF_PRIORITY)
 					continue;
@@ -1047,6 +1042,9 @@
 		for (i = 0; i <= end_zone; i++) {
 			struct zone *zone = pgdat->node_zones + i;
 
+			if (zone->present_pages == 0)
+				continue;
+
 			if (zone->all_unreclaimable && priority != DEF_PRIORITY)
 				continue;
 
@@ -1067,7 +1065,8 @@
 			total_reclaimed += sc.nr_reclaimed;
 			if (zone->all_unreclaimable)
 				continue;
-			if (zone->pages_scanned > zone->present_pages * 2)
+			if (zone->pages_scanned >= (zone->nr_active +
+							zone->nr_inactive) * 4)
 				zone->all_unreclaimable = 1;
 			/*
 			 * If we've done a decent amount of scanning and
@@ -1088,6 +1087,15 @@
 		 */
 		if (total_scanned && priority < DEF_PRIORITY - 2)
 			blk_congestion_wait(WRITE, HZ/10);
+
+		/*
+		 * We do this so kswapd doesn't build up large priorities for
+		 * example when it is freeing in parallel with allocators. It
+		 * matches the direct reclaim path behaviour in terms of impact
+		 * on zone->*_priority.
+		 */
+		if (total_reclaimed >= SWAP_CLUSTER_MAX)
+			break;
 	}
 out:
 	for (i = 0; i < pgdat->nr_zones; i++) {
@@ -1095,6 +1103,11 @@
 
 		zone->prev_priority = zone->temp_priority;
 	}
+	if (!all_zones_ok) {
+		cond_resched();
+		goto loop_again;
+	}
+
 	return total_reclaimed;
 }
 
@@ -1158,6 +1171,8 @@
  */
 void wakeup_kswapd(struct zone *zone)
 {
+	if (zone->present_pages == 0)
+		return;
 	if (zone->free_pages > zone->pages_low)
 		return;
 	if (!waitqueue_active(&zone->zone_pgdat->kswapd_wait))
diff -Nru a/net/8021q/vlan.c b/net/8021q/vlan.c
--- a/net/8021q/vlan.c	2004-10-18 14:56:49 -07:00
+++ b/net/8021q/vlan.c	2004-10-18 14:56:49 -07:00
@@ -537,7 +537,7 @@
 
 out_free_unregister:
 	unregister_netdev(new_dev);
-	goto out_put_dev;
+	goto out_unlock;
 
 out_free_newdev:
 	free_netdev(new_dev);
diff -Nru a/net/8021q/vlan_dev.c b/net/8021q/vlan_dev.c
--- a/net/8021q/vlan_dev.c	2004-10-18 14:57:03 -07:00
+++ b/net/8021q/vlan_dev.c	2004-10-18 14:57:03 -07:00
@@ -211,7 +211,7 @@
 		 * This allows the VLAN to have a different MAC than the underlying
 		 * device, and still route correctly.
 		 */
-		if (memcmp(skb->mac.ethernet->h_dest, skb->dev->dev_addr, ETH_ALEN) == 0) {
+		if (memcmp(eth_hdr(skb)->h_dest, skb->dev->dev_addr, ETH_ALEN) == 0) {
 			/* It is for our (changed) MAC-address! */
 			skb->pkt_type = PACKET_HOST;
 		}
@@ -244,7 +244,7 @@
 			/* TODO:  Add a more specific counter here. */
 			stats->rx_errors++;
 		}
-		rcu_read_lock();
+		rcu_read_unlock();
 		return 0;
 	}
 
@@ -772,7 +772,7 @@
 	case SIOCGMIIREG:
 	case SIOCSMIIREG:
 		if (real_dev->do_ioctl && netif_device_present(real_dev)) 
-			err = real_dev->do_ioctl(dev, &ifrr, cmd);
+			err = real_dev->do_ioctl(real_dev, &ifrr, cmd);
 		break;
 
 	case SIOCETHTOOL:
diff -Nru a/net/Kconfig b/net/Kconfig
--- a/net/Kconfig	2004-10-18 14:55:54 -07:00
+++ b/net/Kconfig	2004-10-18 14:55:54 -07:00
@@ -324,6 +324,19 @@
 
 config VLAN_8021Q
 	tristate "802.1Q VLAN Support"
+	---help---
+	  Select this and you will be able to create 802.1Q VLAN interfaces
+	  on your ethernet interfaces.  802.1Q VLAN supports almost
+	  everything a regular ethernet interface does, including
+	  firewalling, bridging, and of course IP traffic.  You will need
+	  the 'vconfig' tool from the VLAN project in order to effectively
+	  use VLANs.  See the VLAN web page for more information:
+	  <http://www.candelatech.com/~greear/vlan.html>
+
+	  To compile this code as a module, choose M here: the module
+	  will be called 8021q.
+
+	  If unsure, say N.
 
 config DECNET
 	tristate "DECnet Support"
diff -Nru a/net/Makefile b/net/Makefile
--- a/net/Makefile	2004-10-18 14:56:29 -07:00
+++ b/net/Makefile	2004-10-18 14:56:29 -07:00
@@ -9,7 +9,8 @@
 
 obj-$(CONFIG_NET)		:= socket.o core/
 
-obj-$(CONFIG_COMPAT)		+= compat.o
+tmp-$(CONFIG_COMPAT) 		:= compat.o
+obj-$(CONFIG_NET)		+= $(tmp-y)
 
 # LLC has to be linked before the files in net/802/
 obj-$(CONFIG_LLC)		+= llc/
diff -Nru a/net/appletalk/Makefile b/net/appletalk/Makefile
--- a/net/appletalk/Makefile	2004-10-18 14:56:33 -07:00
+++ b/net/appletalk/Makefile	2004-10-18 14:56:33 -07:00
@@ -4,5 +4,6 @@
 
 obj-$(CONFIG_ATALK) += appletalk.o
 
-appletalk-y			:= aarp.o ddp.o atalk_proc.o
+appletalk-y			:= aarp.o ddp.o
+appletalk-$(CONFIG_PROC_FS)	+= atalk_proc.o
 appletalk-$(CONFIG_SYSCTL)	+= sysctl_net_atalk.o
diff -Nru a/net/appletalk/atalk_proc.c b/net/appletalk/atalk_proc.c
--- a/net/appletalk/atalk_proc.c	2004-10-18 14:57:03 -07:00
+++ b/net/appletalk/atalk_proc.c	2004-10-18 14:57:03 -07:00
@@ -15,8 +15,6 @@
 #include <net/sock.h>
 #include <linux/atalk.h>
 
-#ifdef CONFIG_PROC_FS
-extern struct file_operations atalk_seq_arp_fops;
 
 static __inline__ struct atalk_iface *atalk_get_interface_idx(loff_t pos)
 {
@@ -321,14 +319,3 @@
 	remove_proc_entry("arp", atalk_proc_dir);
 	remove_proc_entry("atalk", proc_net);
 }
-
-#else /* CONFIG_PROC_FS */
-int __init atalk_proc_init(void)
-{
-	return 0;
-}
-
-void __exit atalk_proc_exit(void)
-{
-}
-#endif /* CONFIG_PROC_FS */
diff -Nru a/net/appletalk/ddp.c b/net/appletalk/ddp.c
--- a/net/appletalk/ddp.c	2004-10-18 14:57:04 -07:00
+++ b/net/appletalk/ddp.c	2004-10-18 14:57:04 -07:00
@@ -61,16 +61,6 @@
 #include <net/route.h>
 #include <linux/atalk.h>
 
-extern void aarp_cleanup_module(void);
-
-extern void aarp_probe_network(struct atalk_iface *atif);
-extern int  aarp_proxy_probe_network(struct atalk_iface *atif,
-				     struct atalk_addr *sa);
-extern void aarp_proxy_remove(struct net_device *dev, struct atalk_addr *sa);
-
-extern void atalk_register_sysctl(void);
-extern void atalk_unregister_sysctl(void);
-
 struct datalink_proto *ddp_dl, *aarp_dl;
 static struct proto_ops atalk_dgram_ops;
 
diff -Nru a/net/appletalk/sysctl_net_atalk.c b/net/appletalk/sysctl_net_atalk.c
--- a/net/appletalk/sysctl_net_atalk.c	2004-10-18 14:56:17 -07:00
+++ b/net/appletalk/sysctl_net_atalk.c	2004-10-18 14:56:17 -07:00
@@ -7,13 +7,9 @@
  */
 
 #include <linux/config.h>
-
-#ifdef CONFIG_SYSCTL
 #include <linux/sysctl.h>
-extern int sysctl_aarp_expiry_time;
-extern int sysctl_aarp_tick_time;
-extern int sysctl_aarp_retransmit_limit;
-extern int sysctl_aarp_resolve_time;
+#include <net/sock.h>
+#include <linux/atalk.h>
 
 static struct ctl_table atalk_table[] = {
 	{
@@ -85,13 +81,3 @@
 {
 	unregister_sysctl_table(atalk_table_header);
 }
-
-#else /* CONFIG_PROC_FS */
-void atalk_register_sysctl(void)
-{
-}
-
-void atalk_unregister_sysctl(void)
-{
-}
-#endif /* CONFIG_PROC_FS */ 
diff -Nru a/net/atm/br2684.c b/net/atm/br2684.c
--- a/net/atm/br2684.c	2004-10-18 14:57:19 -07:00
+++ b/net/atm/br2684.c	2004-10-18 14:57:19 -07:00
@@ -294,7 +294,7 @@
 {
 	struct ethhdr *eth;
 	unsigned char *rawp;
-	eth = skb->mac.ethernet;
+	eth = eth_hdr(skb);
 
 	if (*eth->h_dest & 1) {
 		if (memcmp(eth->h_dest, dev->broadcast, ETH_ALEN) == 0)
diff -Nru a/net/atm/clip.c b/net/atm/clip.c
--- a/net/atm/clip.c	2004-10-18 14:57:04 -07:00
+++ b/net/atm/clip.c	2004-10-18 14:57:04 -07:00
@@ -26,6 +26,8 @@
 #include <linux/bitops.h>
 #include <linux/proc_fs.h>
 #include <linux/seq_file.h>
+#include <linux/rcupdate.h>
+#include <linux/jhash.h>
 #include <net/route.h> /* for struct rtable and routing */
 #include <net/icmp.h> /* icmp_send */
 #include <asm/param.h> /* for HZ */
@@ -47,8 +49,8 @@
 #endif
 
 
-struct net_device *clip_devs = NULL;
-struct atm_vcc *atmarpd = NULL;
+static struct net_device *clip_devs;
+static struct atm_vcc *atmarpd;
 static struct neigh_table clip_tbl;
 static struct timer_list idle_timer;
 static int start_timer = 1;
@@ -109,7 +111,8 @@
 				goto out;
 			entry->expires = jiffies-1;
 				/* force resolution or expiration */
-			error = neigh_update(entry->neigh,NULL,NUD_NONE,0,0);
+			error = neigh_update(entry->neigh, NULL, NUD_NONE,
+					     NEIGH_UPDATE_F_ADMIN);
 			if (error)
 				printk(KERN_CRIT "unlink_clip_vcc: "
 				    "neigh_update failed with %d\n",error);
@@ -121,64 +124,49 @@
 	spin_unlock_bh(&entry->neigh->dev->xmit_lock);
 }
 
-
-static void idle_timer_check(unsigned long dummy)
+/* The neighbour entry n->lock is held. */
+static int neigh_check_cb(struct neighbour *n)
 {
-	int i;
+	struct atmarp_entry *entry = NEIGH2ENTRY(n);
+	struct clip_vcc *cv;
 
-	/*DPRINTK("idle_timer_check\n");*/
-	write_lock(&clip_tbl.lock);
-	for (i = 0; i <= NEIGH_HASHMASK; i++) {
-		struct neighbour **np;
-
-		for (np = &clip_tbl.hash_buckets[i]; *np;) {
-			struct neighbour *n = *np;
-			struct atmarp_entry *entry = NEIGH2ENTRY(n);
-			struct clip_vcc *clip_vcc;
-
-			write_lock(&n->lock);
-
-			for (clip_vcc = entry->vccs; clip_vcc;
-			    clip_vcc = clip_vcc->next)
-				if (clip_vcc->idle_timeout &&
-				    time_after(jiffies, clip_vcc->last_use+
-				    clip_vcc->idle_timeout)) {
-					DPRINTK("releasing vcc %p->%p of "
-					    "entry %p\n",clip_vcc,clip_vcc->vcc,
-					    entry);
-					vcc_release_async(clip_vcc->vcc,
-							  -ETIMEDOUT);
-				}
-			if (entry->vccs ||
-			    time_before(jiffies, entry->expires)) {
-				np = &n->next;
-				write_unlock(&n->lock);
-				continue;
-			}
-			if (atomic_read(&n->refcnt) > 1) {
-				struct sk_buff *skb;
+	for (cv = entry->vccs; cv; cv = cv->next) {
+		unsigned long exp = cv->last_use + cv->idle_timeout;
 
-				DPRINTK("destruction postponed with ref %d\n",
-				    atomic_read(&n->refcnt));
-				while ((skb = skb_dequeue(&n->arp_queue)) !=
-				     NULL) 
-					dev_kfree_skb(skb);
-				np = &n->next;
-				write_unlock(&n->lock);
-				continue;
-			}
-			*np = n->next;
-			DPRINTK("expired neigh %p\n",n);
-			n->dead = 1;
-			write_unlock(&n->lock);
-			neigh_release(n);
+		if (cv->idle_timeout && time_after(jiffies, exp)) {
+			DPRINTK("releasing vcc %p->%p of entry %p\n",
+				cv, cv->vcc, entry);
+			vcc_release_async(cv->vcc, -ETIMEDOUT);
 		}
 	}
+
+	if (entry->vccs || time_before(jiffies, entry->expires))
+		return 0;
+
+	if (atomic_read(&n->refcnt) > 1) {
+		struct sk_buff *skb;
+
+		DPRINTK("destruction postponed with ref %d\n",
+			atomic_read(&n->refcnt));
+
+		while ((skb = skb_dequeue(&n->arp_queue)) != NULL) 
+			dev_kfree_skb(skb);
+
+		return 0;
+	}
+
+	DPRINTK("expired neigh %p\n",n);
+	return 1;
+}
+
+static void idle_timer_check(unsigned long dummy)
+{
+	write_lock(&clip_tbl.lock);
+	__neigh_for_each_release(&clip_tbl, neigh_check_cb);
 	mod_timer(&idle_timer, jiffies+CLIP_CHECK_INTERVAL*HZ);
 	write_unlock(&clip_tbl.lock);
 }
 
-
 static int clip_arp_rcv(struct sk_buff *skb)
 {
 	struct atm_vcc *vcc;
@@ -311,13 +299,25 @@
 {
 	struct atmarp_entry *entry = NEIGH2ENTRY(neigh);
 	struct net_device *dev = neigh->dev;
-	struct in_device *in_dev = dev->ip_ptr;
+	struct in_device *in_dev;
+	struct neigh_parms *parms;
 
 	DPRINTK("clip_constructor (neigh %p, entry %p)\n",neigh,entry);
-	if (!in_dev) return -EINVAL;
 	neigh->type = inet_addr_type(entry->ip);
 	if (neigh->type != RTN_UNICAST) return -EINVAL;
-	if (in_dev->arp_parms) neigh->parms = in_dev->arp_parms;
+
+	rcu_read_lock();
+	in_dev = rcu_dereference(__in_dev_get(dev));
+	if (!in_dev) {
+		rcu_read_unlock();
+		return -EINVAL;
+	}
+
+	parms = in_dev->arp_parms;
+	__neigh_parms_put(neigh->parms);
+	neigh->parms = neigh_parms_clone(parms);
+	rcu_read_unlock();
+
 	neigh->ops = &clip_neigh_ops;
 	neigh->output = neigh->nud_state & NUD_VALID ?
 	    neigh->ops->connected_output : neigh->ops->output;
@@ -329,15 +329,7 @@
 
 static u32 clip_hash(const void *pkey, const struct net_device *dev)
 {
-	u32 hash_val;
-
-	hash_val = *(u32*)pkey;
-	hash_val ^= (hash_val>>16);
-	hash_val ^= hash_val>>8;
-	hash_val ^= hash_val>>3;
-	hash_val = (hash_val^dev->ifindex)&NEIGH_HASHMASK;
-
-	return hash_val;
+	return jhash_2words(*(u32 *)pkey, dev->ifindex, clip_tbl.hash_rnd);
 }
 
 static struct neigh_table clip_tbl = {
@@ -557,7 +549,8 @@
 		}
 		link_vcc(clip_vcc,entry);
 	}
-	error = neigh_update(neigh,llc_oui,NUD_PERMANENT,1,0);
+	error = neigh_update(neigh, llc_oui, NUD_PERMANENT, 
+			     NEIGH_UPDATE_F_OVERRIDE|NEIGH_UPDATE_F_ADMIN);
 	neigh_release(neigh);
 	return error;
 }
@@ -818,120 +811,126 @@
 	}
 }
 
+/* This means the neighbour entry has no attached VCC objects. */
+#define SEQ_NO_VCC_TOKEN	((void *) 2)
+
 static void atmarp_info(struct seq_file *seq, struct net_device *dev,
 			struct atmarp_entry *entry, struct clip_vcc *clip_vcc)
 {
+	unsigned long exp;
 	char buf[17];
-	int svc, off;
+	int svc, llc, off;
+
+	svc = ((clip_vcc == SEQ_NO_VCC_TOKEN) ||
+	       (clip_vcc->vcc->sk->sk_family == AF_ATMSVC));
+
+	llc = ((clip_vcc == SEQ_NO_VCC_TOKEN) ||
+	       clip_vcc->encap);
+
+	if (clip_vcc == SEQ_NO_VCC_TOKEN)
+		exp = entry->neigh->used;
+	else
+		exp = clip_vcc->last_use;
 
-	svc = !clip_vcc || clip_vcc->vcc->sk->sk_family == AF_ATMSVC;
-	seq_printf(seq, "%-6s%-4s%-4s%5ld ", dev->name, svc ? "SVC" : "PVC",
-	    !clip_vcc || clip_vcc->encap ? "LLC" : "NULL",
-	    (jiffies-(clip_vcc ? clip_vcc->last_use : entry->neigh->used))/HZ);
+	exp = (jiffies - exp) / HZ;
 
-	off = scnprintf(buf, sizeof(buf) - 1, "%d.%d.%d.%d", NIPQUAD(entry->ip));
+	seq_printf(seq, "%-6s%-4s%-4s%5ld ",
+		   dev->name,
+		   svc ? "SVC" : "PVC",
+		   llc ? "LLC" : "NULL",
+		   exp);
+
+	off = scnprintf(buf, sizeof(buf) - 1, "%d.%d.%d.%d",
+			NIPQUAD(entry->ip));
 	while (off < 16)
 		buf[off++] = ' ';
 	buf[off] = '\0';
 	seq_printf(seq, "%s", buf);
 
-	if (!clip_vcc) {
+	if (clip_vcc == SEQ_NO_VCC_TOKEN) {
 		if (time_before(jiffies, entry->expires))
 			seq_printf(seq, "(resolving)\n");
 		else
 			seq_printf(seq, "(expired, ref %d)\n",
 				   atomic_read(&entry->neigh->refcnt));
 	} else if (!svc) {
-		seq_printf(seq, "%d.%d.%d\n", clip_vcc->vcc->dev->number,
-			   clip_vcc->vcc->vpi, clip_vcc->vcc->vci);
+		seq_printf(seq, "%d.%d.%d\n",
+			   clip_vcc->vcc->dev->number,
+			   clip_vcc->vcc->vpi,
+			   clip_vcc->vcc->vci);
 	} else {
 		svc_addr(seq, &clip_vcc->vcc->remote);
 		seq_putc(seq, '\n');
 	}
 }
 
-struct arp_state {
-	int bucket;
-  	struct neighbour *n;
+struct clip_seq_state {
+	/* This member must be first. */
+	struct neigh_seq_state ns;
+
+	/* Local to clip specific iteration. */
 	struct clip_vcc *vcc;
 };
-  
-static void *arp_vcc_walk(struct arp_state *state,
-			  struct atmarp_entry *e, loff_t *l)
-{
-	struct clip_vcc *vcc = state->vcc;
 
-	if (!vcc)
-		vcc = e->vccs;
-	if (vcc == (void *)1) {
-		vcc = e->vccs;
-		--*l;
-  	}
-	for (; vcc; vcc = vcc->next) {
-		if (--*l < 0)
-			break;
-	}
-	state->vcc = vcc;
-	return (*l < 0) ? state : NULL;
-}
-  
-static void *arp_get_idx(struct arp_state *state, loff_t l)
+static struct clip_vcc *clip_seq_next_vcc(struct atmarp_entry *e,
+					  struct clip_vcc *curr)
 {
-	void *v = NULL;
-
-	for (; state->bucket <= NEIGH_HASHMASK; state->bucket++) {
-		for (; state->n; state->n = state->n->next) {
-			v = arp_vcc_walk(state, NEIGH2ENTRY(state->n), &l);
-			if (v)
-				goto done;
-  		}
-		state->n = clip_tbl.hash_buckets[state->bucket + 1];
+	if (!curr) {
+		curr = e->vccs;
+		if (!curr)
+			return SEQ_NO_VCC_TOKEN;
+		return curr;
 	}
-done:
-	return v;
+	if (curr == SEQ_NO_VCC_TOKEN)
+		return NULL;
+
+	curr = curr->next;
+
+	return curr;
 }
 
-static void *arp_seq_start(struct seq_file *seq, loff_t *pos)
+static void *clip_seq_vcc_walk(struct clip_seq_state *state,
+			       struct atmarp_entry *e, loff_t *pos)
 {
-	struct arp_state *state = seq->private;
-	void *ret = (void *)1;
+	struct clip_vcc *vcc = state->vcc;
 
-	read_lock_bh(&clip_tbl.lock);
-	state->bucket = 0;
-	state->n = clip_tbl.hash_buckets[0];
-	state->vcc = (void *)1;
-	if (*pos)
-		ret = arp_get_idx(state, *pos);
-	return ret;
-}
+	vcc = clip_seq_next_vcc(e, vcc);
+	if (vcc && pos != NULL) {
+		while (*pos) {
+			vcc = clip_seq_next_vcc(e, vcc);
+			if (!vcc)
+				break;
+			--(*pos);
+		}
+	}
+	state->vcc = vcc;
 
-static void arp_seq_stop(struct seq_file *seq, void *v)
+	return vcc;
+}
+  
+static void *clip_seq_sub_iter(struct neigh_seq_state *_state,
+			       struct neighbour *n, loff_t *pos)
 {
-	struct arp_state *state = seq->private;
+	struct clip_seq_state *state = (struct clip_seq_state *) _state;
 
-	if (state->bucket != -1)
-		read_unlock_bh(&clip_tbl.lock);
+	return clip_seq_vcc_walk(state, NEIGH2ENTRY(n), pos);
 }
 
-static void *arp_seq_next(struct seq_file *seq, void *v, loff_t *pos)
+static void *clip_seq_start(struct seq_file *seq, loff_t *pos)
 {
-	struct arp_state *state = seq->private;
-
-	v = arp_get_idx(state, 1);
-	*pos += !!PTR_ERR(v);
-	return v;
+	return neigh_seq_start(seq, pos, &clip_tbl, NEIGH_SEQ_NEIGH_ONLY);
 }
 
-static int arp_seq_show(struct seq_file *seq, void *v)
+static int clip_seq_show(struct seq_file *seq, void *v)
 {
 	static char atm_arp_banner[] = 
 		"IPitf TypeEncp Idle IP address      ATM address\n";
 
-	if (v == (void *)1)
+	if (v == SEQ_START_TOKEN) {
 		seq_puts(seq, atm_arp_banner);
-	else {
-		struct arp_state *state = seq->private;
-		struct neighbour *n = state->n;	
+	} else {
+		struct clip_seq_state *state = seq->private;
+		struct neighbour *n = v;
 		struct clip_vcc *vcc = state->vcc;
 
 		atmarp_info(seq, n->dev, NEIGH2ENTRY(n), vcc);
@@ -940,15 +939,15 @@
 }
 
 static struct seq_operations arp_seq_ops = {
-	.start	= arp_seq_start,
-	.next	= arp_seq_next,
-	.stop	= arp_seq_stop,
-	.show	= arp_seq_show,
+	.start	= clip_seq_start,
+	.next	= neigh_seq_next,
+	.stop	= neigh_seq_stop,
+	.show	= clip_seq_show,
 };
 
 static int arp_seq_open(struct inode *inode, struct file *file)
 {
-	struct arp_state *state;
+	struct clip_seq_state *state;
 	struct seq_file *seq;
 	int rc = -EAGAIN;
 
@@ -957,6 +956,8 @@
 		rc = -ENOMEM;
 		goto out_kfree;
 	}
+	memset(state, 0, sizeof(*state));
+	state->ns.neigh_sub_iter = clip_seq_sub_iter;
 
 	rc = seq_open(file, &arp_seq_ops);
 	if (rc)
@@ -972,35 +973,18 @@
 	goto out;
 }
 
-static int arp_seq_release(struct inode *inode, struct file *file)
-{
-	return seq_release_private(inode, file);
-}
-
 static struct file_operations arp_seq_fops = {
 	.open		= arp_seq_open,
 	.read		= seq_read,
 	.llseek		= seq_lseek,
-	.release	= arp_seq_release,
+	.release	= seq_release_private,
 	.owner		= THIS_MODULE
 };
 #endif
 
 static int __init atm_clip_init(void)
 {
-	/* we should use neigh_table_init() */
-	clip_tbl.lock = RW_LOCK_UNLOCKED;
-	clip_tbl.kmem_cachep = kmem_cache_create(clip_tbl.id,
-	    clip_tbl.entry_size, 0, SLAB_HWCACHE_ALIGN, NULL, NULL);
-
-	if (!clip_tbl.kmem_cachep)
-		return -ENOMEM;
-
-	/* so neigh_ifdown() doesn't complain */
-	clip_tbl.proxy_timer.data = 0;
-	clip_tbl.proxy_timer.function = NULL;
-	init_timer(&clip_tbl.proxy_timer);
-	skb_queue_head_init(&clip_tbl.proxy_queue);
+	neigh_table_init(&clip_tbl);
 
 	clip_tbl_hook = &clip_tbl;
 	register_atm_ioctl(&clip_ioctl_ops);
@@ -1026,7 +1010,18 @@
 
 	deregister_atm_ioctl(&clip_ioctl_ops);
 
+	/* First, stop the idle timer, so it stops banging
+	 * on the table.
+	 */
+	if (start_timer == 0)
+		del_timer(&idle_timer);
+
+	/* Next, purge the table, so that the device
+	 * unregister loop below does not hang due to
+	 * device references remaining in the table.
+	 */
 	neigh_ifdown(&clip_tbl, NULL);
+
 	dev = clip_devs;
 	while (dev) {
 		next = PRIV(dev)->next;
@@ -1034,9 +1029,9 @@
 		free_netdev(dev);
 		dev = next;
 	}
-	if (start_timer == 0) del_timer(&idle_timer);
 
-	kmem_cache_destroy(clip_tbl.kmem_cachep);
+	/* Now it is safe to fully shutdown whole table. */
+	neigh_table_clear(&clip_tbl);
 
 	clip_tbl_hook = NULL;
 }
diff -Nru a/net/atm/common.h b/net/atm/common.h
--- a/net/atm/common.h	2004-10-18 14:56:49 -07:00
+++ b/net/atm/common.h	2004-10-18 14:56:49 -07:00
@@ -24,11 +24,6 @@
 int vcc_getsockopt(struct socket *sock, int level, int optname,
 		   char __user *optval, int __user *optlen);
 
-void atm_shutdown_dev(struct atm_dev *dev);
-
-void pppoatm_ioctl_set(int (*hook)(struct atm_vcc *, unsigned int, unsigned long));
-void br2684_ioctl_set(int (*hook)(struct atm_vcc *, unsigned int, unsigned long));
-
 int atmpvc_init(void);
 void atmpvc_exit(void);
 int atmsvc_init(void);
@@ -50,12 +45,6 @@
 #endif /* CONFIG_PROC_FS */
 
 /* SVC */
-
-void svc_callback(struct atm_vcc *vcc);
 int svc_change_qos(struct atm_vcc *vcc,struct atm_qos *qos);
-
-/* p2mp */
-
-int create_leaf(struct socket *leaf,struct socket *session);
 
 #endif
diff -Nru a/net/atm/ipcommon.h b/net/atm/ipcommon.h
--- a/net/atm/ipcommon.h	2004-10-18 14:56:32 -07:00
+++ b/net/atm/ipcommon.h	2004-10-18 14:56:32 -07:00
@@ -12,9 +12,6 @@
 #include <linux/netdevice.h>
 #include <linux/atmdev.h>
 
-
-extern struct net_device *clip_devs;
-
 /*
  * Appends all skbs from "from" to "to". The operation is atomic with respect
  * to all other skb operations on "from" or "to".
diff -Nru a/net/atm/lec.h b/net/atm/lec.h
--- a/net/atm/lec.h	2004-10-18 14:56:28 -07:00
+++ b/net/atm/lec.h	2004-10-18 14:56:28 -07:00
@@ -151,7 +151,6 @@
 int lec_vcc_attach(struct atm_vcc *vcc, void __user *arg);
 int lec_mcast_attach(struct atm_vcc *vcc, int arg);
 struct net_device *get_dev_lec(int itf);
-int make_lec(struct atm_vcc *vcc);
 int send_to_lecd(struct lec_priv *priv,
                  atmlec_msg_type type, unsigned char *mac_addr,
                  unsigned char *atm_addr, struct sk_buff *data);
diff -Nru a/net/atm/mpoa_proc.c b/net/atm/mpoa_proc.c
--- a/net/atm/mpoa_proc.c	2004-10-18 14:57:20 -07:00
+++ b/net/atm/mpoa_proc.c	2004-10-18 14:57:20 -07:00
@@ -121,7 +121,7 @@
 /*
  * READING function - called when the /proc/atm/mpoa file is read from.
  */
-static ssize_t mpc_show(struct seq_file *m, void *v)
+static int mpc_show(struct seq_file *m, void *v)
 {
 	struct mpoa_client *mpc = v;
 	unsigned char *temp;
diff -Nru a/net/ax25/af_ax25.c b/net/ax25/af_ax25.c
--- a/net/ax25/af_ax25.c	2004-10-18 14:57:03 -07:00
+++ b/net/ax25/af_ax25.c	2004-10-18 14:57:03 -07:00
@@ -1176,13 +1176,16 @@
 		/* check if we can remove this feature. It is broken. */
 		printk(KERN_WARNING "ax25_connect(): %s uses autobind, please contact jreuter@yaina.de\n",
 			current->comm);
-		if ((err = ax25_rt_autobind(ax25, &fsa->fsa_ax25.sax25_call)) < 0)
+		if ((err = ax25_rt_autobind(ax25, &fsa->fsa_ax25.sax25_call)) < 0) {
+			kfree(digi);
 			goto out;
+		}
 
 		ax25_fillin_cb(ax25, ax25->ax25_dev);
 		ax25_cb_add(ax25);
 	} else {
 		if (ax25->ax25_dev == NULL) {
+			kfree(digi);
 			err = -EHOSTUNREACH;
 			goto out;
 		}
@@ -1191,8 +1194,7 @@
 	if (sk->sk_type == SOCK_SEQPACKET &&
 	    (ax25t=ax25_find_cb(&ax25->source_addr, &fsa->fsa_ax25.sax25_call, digi,
 		    	 ax25->ax25_dev->dev))) {
-		if (digi != NULL)
-			kfree(digi);
+		kfree(digi);
 		err = -EADDRINUSE;		/* Already such a connection */
 		ax25_cb_put(ax25t);
 		goto out;
@@ -1336,7 +1338,6 @@
 	remove_wait_queue(sk->sk_sleep, &wait);
 
 	newsk		 = skb->sk;
-	newsk->sk_pair	 = NULL;
 	newsk->sk_socket = newsock;
 	newsk->sk_sleep	 = &newsock->wait;
 
diff -Nru a/net/ax25/ax25_in.c b/net/ax25/ax25_in.c
--- a/net/ax25/ax25_in.c	2004-10-18 14:56:13 -07:00
+++ b/net/ax25/ax25_in.c	2004-10-18 14:56:13 -07:00
@@ -372,7 +372,6 @@
 		skb_queue_head(&sk->sk_receive_queue, skb);
 
 		make->sk_state = TCP_ESTABLISHED;
-		make->sk_pair  = sk;
 
 		sk->sk_ack_backlog++;
 		bh_unlock_sock(sk);
diff -Nru a/net/bluetooth/bnep/core.c b/net/bluetooth/bnep/core.c
--- a/net/bluetooth/bnep/core.c	2004-10-18 14:56:48 -07:00
+++ b/net/bluetooth/bnep/core.c	2004-10-18 14:56:48 -07:00
@@ -384,7 +384,7 @@
 	
 	s->stats.rx_packets++;
 	nskb->dev       = dev;
-	nskb->ip_summed = CHECKSUM_UNNECESSARY;
+	nskb->ip_summed = CHECKSUM_NONE;
 	nskb->protocol  = eth_type_trans(nskb, dev);
 	netif_rx_ni(nskb);
 	return 0;
diff -Nru a/net/bluetooth/l2cap.c b/net/bluetooth/l2cap.c
--- a/net/bluetooth/l2cap.c	2004-10-18 14:56:48 -07:00
+++ b/net/bluetooth/l2cap.c	2004-10-18 14:56:48 -07:00
@@ -57,7 +57,7 @@
 #define BT_DBG(D...)
 #endif
 
-#define VERSION "2.3"
+#define VERSION "2.4"
 
 static struct proto_ops l2cap_sock_ops;
 
@@ -1453,7 +1453,7 @@
 	BT_DBG("dcid 0x%4.4x scid 0x%4.4x result 0x%2.2x status 0x%2.2x", dcid, scid, result, status);
 
 	if (!(sk = l2cap_get_chan_by_scid(&conn->chan_list, scid)))
-		return -ENOENT;
+		return 0;
 
 	switch (result) {
 	case L2CAP_CR_SUCCESS:
@@ -1527,7 +1527,6 @@
 	struct l2cap_conf_rsp *rsp = (struct l2cap_conf_rsp *)data;
 	u16 scid, flags, result;
 	struct sock *sk;
-	int err = 0;
 
 	scid   = __le16_to_cpu(rsp->scid);
 	flags  = __le16_to_cpu(rsp->flags);
@@ -1536,7 +1535,7 @@
 	BT_DBG("scid 0x%4.4x flags 0x%2.2x result 0x%2.2x", scid, flags, result);
 
 	if (!(sk = l2cap_get_chan_by_scid(&conn->chan_list, scid)))
-		return -ENOENT;
+		return 0;
 
 	switch (result) {
 	case L2CAP_CONF_SUCCESS:
@@ -1581,7 +1580,7 @@
 
 done:
 	bh_unlock_sock(sk);
-	return err;
+	return 0;
 }
 
 static inline int l2cap_disconnect_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
@@ -1625,6 +1624,7 @@
 
 	if (!(sk = l2cap_get_chan_by_scid(&conn->chan_list, scid)))
 		return 0;
+
 	l2cap_chan_del(sk, 0);
 	bh_unlock_sock(sk);
 
@@ -1632,7 +1632,7 @@
 	return 0;
 }
 
-static inline int l2cap_info_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
+static inline int l2cap_information_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
 {
 	struct l2cap_info_req *req = (struct l2cap_info_req *) data;
 	struct l2cap_info_rsp rsp;
@@ -1645,10 +1645,11 @@
 	rsp.type   = __cpu_to_le16(type);
 	rsp.result = __cpu_to_le16(L2CAP_IR_NOTSUPP);
 	l2cap_send_rsp(conn, cmd->ident, L2CAP_INFO_RSP, sizeof(rsp), &rsp);
+
 	return 0;
 }
 
-static inline int l2cap_info_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
+static inline int l2cap_information_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
 {
 	struct l2cap_info_rsp *rsp = (struct l2cap_info_rsp *) data;
 	u16 type, result;
@@ -1721,11 +1722,11 @@
 			break;
 
 		case L2CAP_INFO_REQ:
-			err = l2cap_info_req(conn, &cmd, data);
+			err = l2cap_information_req(conn, &cmd, data);
 			break;
 
 		case L2CAP_INFO_RSP:
-			err = l2cap_info_rsp(conn, &cmd, data);
+			err = l2cap_information_rsp(conn, &cmd, data);
 			break;
 
 		default:
diff -Nru a/net/bridge/br_input.c b/net/bridge/br_input.c
--- a/net/bridge/br_input.c	2004-10-18 14:56:21 -07:00
+++ b/net/bridge/br_input.c	2004-10-18 14:56:21 -07:00
@@ -45,27 +45,15 @@
 			br_pass_frame_up_finish);
 }
 
+/* note: already called with rcu_read_lock (preempt_disabled) */
 int br_handle_frame_finish(struct sk_buff *skb)
 {
-	struct net_bridge *br;
-	unsigned char *dest;
+	const unsigned char *dest = eth_hdr(skb)->h_dest;
+	struct net_bridge_port *p = skb->dev->br_port;
+	struct net_bridge *br = p->br;
 	struct net_bridge_fdb_entry *dst;
-	struct net_bridge_port *p;
-	int passedup;
+	int passedup = 0;
 
-	dest = skb->mac.ethernet->h_dest;
-
-	rcu_read_lock();
-	p = skb->dev->br_port;
-	smp_read_barrier_depends();
-
-	if (p == NULL || p->state == BR_STATE_DISABLED) {
-		kfree_skb(skb);
-		goto out;
-	}
-
-	br = p->br;
-	passedup = 0;
 	if (br->dev->flags & IFF_PROMISC) {
 		struct sk_buff *skb2;
 
@@ -100,28 +88,29 @@
 	br_flood_forward(br, skb, 0);
 
 out:
-	rcu_read_unlock();
 	return 0;
 }
 
-int br_handle_frame(struct sk_buff *skb)
+/*
+ * Called via br_handle_frame_hook.
+ * Return 0 if *pskb should be processed furthur
+ *	  1 if *pskb is handled
+ * note: already called with rcu_read_lock (preempt_disabled) 
+ */
+int br_handle_frame(struct net_bridge_port *p, struct sk_buff **pskb)
 {
-	unsigned char *dest;
-	struct net_bridge_port *p;
-
-	dest = skb->mac.ethernet->h_dest;
+	struct sk_buff *skb = *pskb;
+	const unsigned char *dest = eth_hdr(skb)->h_dest;
 
-	rcu_read_lock();
-	p = skb->dev->br_port;
-	if (p == NULL || p->state == BR_STATE_DISABLED)
+	if (p->state == BR_STATE_DISABLED)
 		goto err;
 
-	if (skb->mac.ethernet->h_source[0] & 1)
+	if (eth_hdr(skb)->h_source[0] & 1)
 		goto err;
 
 	if (p->state == BR_STATE_LEARNING ||
 	    p->state == BR_STATE_FORWARDING)
-		br_fdb_insert(p->br, p, skb->mac.ethernet->h_source, 0);
+		br_fdb_insert(p->br, p, eth_hdr(skb)->h_source, 0);
 
 	if (p->br->stp_enabled &&
 	    !memcmp(dest, bridge_ula, 5) &&
@@ -129,15 +118,16 @@
 		if (!dest[5]) {
 			NF_HOOK(PF_BRIDGE, NF_BR_LOCAL_IN, skb, skb->dev, 
 				NULL, br_stp_handle_bpdu);
-			rcu_read_unlock();
-			return 0;
+			return 1;
 		}
 	}
 
 	else if (p->state == BR_STATE_FORWARDING) {
-		if (br_should_route_hook && br_should_route_hook(&skb)) {
-			rcu_read_unlock();
-			return -1;
+		if (br_should_route_hook) {
+			if (br_should_route_hook(pskb)) 
+				return 0;
+			skb = *pskb;
+			dest = eth_hdr(skb)->h_dest;
 		}
 
 		if (!memcmp(p->br->dev->dev_addr, dest, ETH_ALEN))
@@ -145,12 +135,10 @@
 
 		NF_HOOK(PF_BRIDGE, NF_BR_PRE_ROUTING, skb, skb->dev, NULL,
 			br_handle_frame_finish);
-		rcu_read_unlock();
-		return 0;
+		return 1;
 	}
 
 err:
-	rcu_read_unlock();
 	kfree_skb(skb);
-	return 0;
+	return 1;
 }
diff -Nru a/net/bridge/br_netfilter.c b/net/bridge/br_netfilter.c
--- a/net/bridge/br_netfilter.c	2004-10-18 14:57:04 -07:00
+++ b/net/bridge/br_netfilter.c	2004-10-18 14:57:04 -07:00
@@ -11,6 +11,7 @@
  *	Jun 19 2003: let arptables see bridged ARP traffic (bdschuym)
  *	Oct 06 2003: filter encapsulated IP/ARP VLAN traffic on untagged bridge
  *	             (bdschuym)
+ *	Sep 01 2004: add IPv6 filtering (bdschuym)
  *
  *	This program is free software; you can redistribute it and/or
  *	modify it under the terms of the GNU General Public License
@@ -29,9 +30,11 @@
 #include <linux/if_vlan.h>
 #include <linux/netfilter_bridge.h>
 #include <linux/netfilter_ipv4.h>
+#include <linux/netfilter_ipv6.h>
 #include <linux/netfilter_arp.h>
 #include <linux/in_route.h>
 #include <net/ip.h>
+#include <net/ipv6.h>
 #include <asm/uaccess.h>
 #include <asm/checksum.h>
 #include "br_private.h"
@@ -39,7 +42,6 @@
 #include <linux/sysctl.h>
 #endif
 
-
 #define skb_origaddr(skb)	 (((struct bridge_skb_cb *) \
 				 (skb->nf_bridge->data))->daddr.ipv4)
 #define store_orig_dstaddr(skb)	 (skb_origaddr(skb) = (skb)->nh.iph->daddr)
@@ -51,6 +53,7 @@
 #ifdef CONFIG_SYSCTL
 static struct ctl_table_header *brnf_sysctl_header;
 static int brnf_call_iptables = 1;
+static int brnf_call_ip6tables = 1;
 static int brnf_call_arptables = 1;
 static int brnf_filter_vlan_tagged = 1;
 #else
@@ -60,6 +63,9 @@
 #define IS_VLAN_IP (skb->protocol == __constant_htons(ETH_P_8021Q) &&    \
 	hdr->h_vlan_encapsulated_proto == __constant_htons(ETH_P_IP) &&  \
 	brnf_filter_vlan_tagged)
+#define IS_VLAN_IPV6 (skb->protocol == __constant_htons(ETH_P_8021Q) &&    \
+	hdr->h_vlan_encapsulated_proto == __constant_htons(ETH_P_IPV6) &&  \
+	brnf_filter_vlan_tagged)
 #define IS_VLAN_ARP (skb->protocol == __constant_htons(ETH_P_8021Q) &&   \
 	hdr->h_vlan_encapsulated_proto == __constant_htons(ETH_P_ARP) && \
 	brnf_filter_vlan_tagged)
@@ -71,8 +77,7 @@
  * Currently, we fill in the PMTU entry because netfilter
  * refragmentation needs it, and the rt_flags entry because
  * ipt_REJECT needs it.  Future netfilter modules might
- * require us to fill additional fields.
- */
+ * require us to fill additional fields. */
 static struct net_device __fake_net_device = {
 	.hard_header_len	= ETH_HLEN
 };
@@ -91,6 +96,36 @@
 
 
 /* PF_BRIDGE/PRE_ROUTING *********************************************/
+/* Undo the changes made for ip6tables PREROUTING and continue the
+ * bridge PRE_ROUTING hook. */
+static int br_nf_pre_routing_finish_ipv6(struct sk_buff *skb)
+{
+	struct nf_bridge_info *nf_bridge = skb->nf_bridge;
+
+#ifdef CONFIG_NETFILTER_DEBUG
+	skb->nf_debug ^= (1 << NF_BR_PRE_ROUTING);
+#endif
+
+	if (nf_bridge->mask & BRNF_PKT_TYPE) {
+		skb->pkt_type = PACKET_OTHERHOST;
+		nf_bridge->mask ^= BRNF_PKT_TYPE;
+	}
+	nf_bridge->mask ^= BRNF_NF_BRIDGE_PREROUTING;
+
+	skb->dst = (struct dst_entry *)&__fake_rtable;
+	dst_hold(skb->dst);
+
+	skb->dev = nf_bridge->physindev;
+	if (skb->protocol == __constant_htons(ETH_P_8021Q)) {
+		skb_push(skb, VLAN_HLEN);
+		skb->nh.raw -= VLAN_HLEN;
+	}
+	NF_HOOK_THRESH(PF_BRIDGE, NF_BR_PRE_ROUTING, skb, skb->dev, NULL,
+		       br_handle_frame_finish, 1);
+
+	return 0;
+}
+
 static void __br_dnat_complain(void)
 {
 	static unsigned long last_complaint;
@@ -102,7 +137,6 @@
 	}
 }
 
-
 /* This requires some explaining. If DNAT has taken place,
  * we will need to fix up the destination Ethernet address,
  * and this is a tricky process.
@@ -145,9 +179,7 @@
  *
  * --Lennert, 20020411
  * --Bart, 20020416 (updated)
- * --Bart, 20021007 (updated)
- */
-
+ * --Bart, 20021007 (updated) */
 static int br_nf_pre_routing_finish_bridge(struct sk_buff *skb)
 {
 #ifdef CONFIG_NETFILTER_DEBUG
@@ -195,8 +227,7 @@
 
 			if (!ip_route_output_key(&rt, &fl)) {
 				/* Bridged-and-DNAT'ed traffic doesn't
-				 * require ip_forwarding.
-				 */
+				 * require ip_forwarding. */
 				if (((struct dst_entry *)rt)->dev == dev) {
 					skb->dst = (struct dst_entry *)rt;
 					goto bridged_dnat;
@@ -210,8 +241,7 @@
 			if (skb->dst->dev == dev) {
 bridged_dnat:
 				/* Tell br_nf_local_out this is a
-				 * bridged frame
-				 */
+				 * bridged frame */
 				nf_bridge->mask |= BRNF_BRIDGED_DNAT;
 				skb->dev = nf_bridge->physindev;
 				if (skb->protocol ==
@@ -225,7 +255,7 @@
 					       1);
 				return 0;
 			}
-			memcpy(skb->mac.ethernet->h_dest, dev->dev_addr,
+			memcpy(eth_hdr(skb)->h_dest, dev->dev_addr,
 			       ETH_ALEN);
 			skb->pkt_type = PACKET_HOST;
 		}
@@ -245,12 +275,135 @@
 	return 0;
 }
 
-/* Replicate the checks that IPv4 does on packet reception.
+/* Some common code for IPv4/IPv6 */
+static void setup_pre_routing(struct sk_buff *skb)
+{
+	struct nf_bridge_info *nf_bridge = skb->nf_bridge;
+
+	if (skb->pkt_type == PACKET_OTHERHOST) {
+		skb->pkt_type = PACKET_HOST;
+		nf_bridge->mask |= BRNF_PKT_TYPE;
+	}
+
+	nf_bridge->mask |= BRNF_NF_BRIDGE_PREROUTING;
+	nf_bridge->physindev = skb->dev;
+	skb->dev = bridge_parent(skb->dev);
+}
+
+/* We only check the length. A bridge shouldn't do any hop-by-hop stuff anyway */
+static int check_hbh_len(struct sk_buff *skb)
+{
+	unsigned char *raw = (u8*)(skb->nh.ipv6h+1);
+	u32 pkt_len;
+	int off = raw - skb->nh.raw;
+	int len = (raw[1]+1)<<3;
+
+	if ((raw + len) - skb->data > skb_headlen(skb))
+		goto bad;
+
+	off += 2;
+	len -= 2;
+
+	while (len > 0) {
+		int optlen = raw[off+1]+2;
+
+		switch (skb->nh.raw[off]) {
+		case IPV6_TLV_PAD0:
+			optlen = 1;
+			break;
+
+		case IPV6_TLV_PADN:
+			break;
+
+		case IPV6_TLV_JUMBO:
+			if (skb->nh.raw[off+1] != 4 || (off&3) != 2)
+				goto bad;
+
+			pkt_len = ntohl(*(u32*)(skb->nh.raw+off+2));
+
+			if (pkt_len > skb->len - sizeof(struct ipv6hdr))
+				goto bad;
+			if (pkt_len + sizeof(struct ipv6hdr) < skb->len) {
+				if (__pskb_trim(skb,
+				    pkt_len + sizeof(struct ipv6hdr)))
+					goto bad;
+				if (skb->ip_summed == CHECKSUM_HW)
+					skb->ip_summed = CHECKSUM_NONE;
+			}
+			break;
+		default:
+			if (optlen > len)
+				goto bad;
+			break;
+		}
+		off += optlen;
+		len -= optlen;
+	}
+	if (len == 0)
+		return 0;
+bad:
+	return -1;
+
+}
+
+/* Replicate the checks that IPv6 does on packet reception and pass the packet
+ * to ip6tables, which doesn't support NAT, so things are fairly simple. */
+static unsigned int br_nf_pre_routing_ipv6(unsigned int hook,
+   struct sk_buff *skb, const struct net_device *in,
+   const struct net_device *out, int (*okfn)(struct sk_buff *))
+{
+	struct ipv6hdr *hdr;
+	u32 pkt_len;
+	struct nf_bridge_info *nf_bridge;
+
+	if (skb->len < sizeof(struct ipv6hdr))
+		goto inhdr_error;
+
+	if (!pskb_may_pull(skb, sizeof(struct ipv6hdr)))
+		goto inhdr_error;
+
+	hdr = skb->nh.ipv6h;
+
+	if (hdr->version != 6)
+		goto inhdr_error;
+
+	pkt_len = ntohs(hdr->payload_len);
+
+	if (pkt_len || hdr->nexthdr != NEXTHDR_HOP) {
+		if (pkt_len + sizeof(struct ipv6hdr) > skb->len)
+			goto inhdr_error;
+		if (pkt_len + sizeof(struct ipv6hdr) < skb->len) {
+			if (__pskb_trim(skb, pkt_len + sizeof(struct ipv6hdr)))
+				goto inhdr_error;
+			if (skb->ip_summed == CHECKSUM_HW)
+				skb->ip_summed = CHECKSUM_NONE;
+		}
+	}
+	if (hdr->nexthdr == NEXTHDR_HOP && check_hbh_len(skb))
+			goto inhdr_error;
+
+#ifdef CONFIG_NETFILTER_DEBUG
+	skb->nf_debug ^= (1 << NF_IP6_PRE_ROUTING);
+#endif
+	if ((nf_bridge = nf_bridge_alloc(skb)) == NULL)
+		return NF_DROP;
+	setup_pre_routing(skb);
+
+	NF_HOOK(PF_INET6, NF_IP6_PRE_ROUTING, skb, skb->dev, NULL,
+		br_nf_pre_routing_finish_ipv6);
+
+	return NF_STOLEN;
+
+inhdr_error:
+	return NF_DROP;
+}
+
+/* Direct IPv6 traffic to br_nf_pre_routing_ipv6.
+ * Replicate the checks that IPv4 does on packet reception.
  * Set skb->dev to the bridge device (i.e. parent of the
  * receiving device) to make netfilter happy, the REDIRECT
  * target in particular.  Save the original destination IP
- * address to be able to detect DNAT afterwards.
- */
+ * address to be able to detect DNAT afterwards. */
 static unsigned int br_nf_pre_routing(unsigned int hook, struct sk_buff **pskb,
    const struct net_device *in, const struct net_device *out,
    int (*okfn)(struct sk_buff *))
@@ -259,25 +412,38 @@
 	__u32 len;
 	struct sk_buff *skb = *pskb;
 	struct nf_bridge_info *nf_bridge;
+	struct vlan_ethhdr *hdr = vlan_eth_hdr(*pskb);
+
+	if (skb->protocol == __constant_htons(ETH_P_IPV6) || IS_VLAN_IPV6) {
+#ifdef CONFIG_SYSCTL
+		if (!brnf_call_ip6tables)
+			return NF_ACCEPT;
+#endif
+		if ((skb = skb_share_check(*pskb, GFP_ATOMIC)) == NULL)
+			goto out;
 
+		if (skb->protocol == __constant_htons(ETH_P_8021Q)) {
+			skb_pull(skb, VLAN_HLEN);
+			(skb)->nh.raw += VLAN_HLEN;
+		}
+		return br_nf_pre_routing_ipv6(hook, skb, in, out, okfn);
+	}
 #ifdef CONFIG_SYSCTL
 	if (!brnf_call_iptables)
 		return NF_ACCEPT;
 #endif
 
-	if (skb->protocol != __constant_htons(ETH_P_IP)) {
-		struct vlan_ethhdr *hdr = (struct vlan_ethhdr *)
-					  ((*pskb)->mac.ethernet);
+	if (skb->protocol != __constant_htons(ETH_P_IP) && !IS_VLAN_IP)
+		return NF_ACCEPT;
 
-		if (!IS_VLAN_IP)
-			return NF_ACCEPT;
-		if ((skb = skb_share_check(*pskb, GFP_ATOMIC)) == NULL)
-			goto out;
-		skb_pull(*pskb, VLAN_HLEN);
-		(*pskb)->nh.raw += VLAN_HLEN;
-	} else if ((skb = skb_share_check(*pskb, GFP_ATOMIC)) == NULL)
+	if ((skb = skb_share_check(*pskb, GFP_ATOMIC)) == NULL)
 		goto out;
 
+	if (skb->protocol == __constant_htons(ETH_P_8021Q)) {
+		skb_pull(skb, VLAN_HLEN);
+		(skb)->nh.raw += VLAN_HLEN;
+	}
+
 	if (!pskb_may_pull(skb, sizeof(struct iphdr)))
 		goto inhdr_error;
 
@@ -305,17 +471,9 @@
 #ifdef CONFIG_NETFILTER_DEBUG
 	skb->nf_debug ^= (1 << NF_IP_PRE_ROUTING);
 #endif
- 	if ((nf_bridge = nf_bridge_alloc(skb)) == NULL)
+	if ((nf_bridge = nf_bridge_alloc(skb)) == NULL)
 		return NF_DROP;
-
-	if (skb->pkt_type == PACKET_OTHERHOST) {
-		skb->pkt_type = PACKET_HOST;
-		nf_bridge->mask |= BRNF_PKT_TYPE;
-	}
-
-	nf_bridge->mask |= BRNF_NF_BRIDGE_PREROUTING;
-	nf_bridge->physindev = skb->dev;
-	skb->dev = bridge_parent(skb->dev);
+	setup_pre_routing(skb);
 	store_orig_dstaddr(skb);
 
 	NF_HOOK(PF_INET, NF_IP_PRE_ROUTING, skb, skb->dev, NULL,
@@ -336,8 +494,7 @@
  * packet would pass through PRE_ROUTING again (which already
  * took place when the packet entered the bridge), but we
  * register an IPv4 PRE_ROUTING 'sabotage' hook that will
- * prevent this from happening.
- */
+ * prevent this from happening. */
 static unsigned int br_nf_local_in(unsigned int hook, struct sk_buff **pskb,
    const struct net_device *in, const struct net_device *out,
    int (*okfn)(struct sk_buff *))
@@ -358,13 +515,13 @@
 {
 	struct nf_bridge_info *nf_bridge = skb->nf_bridge;
 	struct net_device *in;
-	struct vlan_ethhdr *hdr = (struct vlan_ethhdr *)(skb->mac.ethernet);
+	struct vlan_ethhdr *hdr = vlan_eth_hdr(skb);
 
 #ifdef CONFIG_NETFILTER_DEBUG
 	skb->nf_debug ^= (1 << NF_BR_FORWARD);
 #endif
 
-	if (skb->protocol == __constant_htons(ETH_P_IP) || IS_VLAN_IP) {
+	if (skb->protocol != __constant_htons(ETH_P_ARP) && !IS_VLAN_ARP) {
 		in = nf_bridge->physindev;
 		if (nf_bridge->mask & BRNF_PKT_TYPE) {
 			skb->pkt_type = PACKET_OTHERHOST;
@@ -385,25 +542,26 @@
 /* This is the 'purely bridged' case.  For IP, we pass the packet to
  * netfilter with indev and outdev set to the bridge device,
  * but we are still able to filter on the 'real' indev/outdev
- * because of the ipt_physdev.c module. For ARP, indev and outdev are the
- * bridge ports.
- */
+ * because of the physdev module. For ARP, indev and outdev are the
+ * bridge ports. */
 static unsigned int br_nf_forward_ip(unsigned int hook, struct sk_buff **pskb,
    const struct net_device *in, const struct net_device *out,
    int (*okfn)(struct sk_buff *))
 {
 	struct sk_buff *skb = *pskb;
 	struct nf_bridge_info *nf_bridge;
-	struct vlan_ethhdr *hdr = (struct vlan_ethhdr *)(skb->mac.ethernet);
+	struct vlan_ethhdr *hdr = vlan_eth_hdr(skb);
+	int pf;
 
-#ifdef CONFIG_SYSCTL
 	if (!skb->nf_bridge)
 		return NF_ACCEPT;
-#endif
 
-	if (skb->protocol != __constant_htons(ETH_P_IP)) {
-		if (!IS_VLAN_IP)
-			return NF_ACCEPT;
+	if (skb->protocol == __constant_htons(ETH_P_IP) || IS_VLAN_IP)
+		pf = PF_INET;
+	else
+		pf = PF_INET6;
+
+	if (skb->protocol == __constant_htons(ETH_P_8021Q)) {
 		skb_pull(*pskb, VLAN_HLEN);
 		(*pskb)->nh.raw += VLAN_HLEN;
 	}
@@ -421,7 +579,7 @@
 	nf_bridge->mask |= BRNF_BRIDGED;
 	nf_bridge->physoutdev = skb->dev;
 
-	NF_HOOK(PF_INET, NF_IP_FORWARD, skb, bridge_parent(in),
+	NF_HOOK(pf, NF_IP_FORWARD, skb, bridge_parent(in),
 		bridge_parent(out), br_nf_forward_finish);
 
 	return NF_STOLEN;
@@ -432,7 +590,7 @@
    int (*okfn)(struct sk_buff *))
 {
 	struct sk_buff *skb = *pskb;
-	struct vlan_ethhdr *hdr = (struct vlan_ethhdr *)(skb->mac.ethernet);
+	struct vlan_ethhdr *hdr = vlan_eth_hdr(skb);
 	struct net_device **d = (struct net_device **)(skb->cb);
 
 #ifdef CONFIG_SYSCTL
@@ -483,11 +641,10 @@
 	return 0;
 }
 
-
 /* This function sees both locally originated IP packets and forwarded
  * IP packets (in both cases the destination device is a bridge
  * device). It also sees bridged-and-DNAT'ed packets.
- * To be able to filter on the physical bridge devices (with the ipt_physdev.c
+ * To be able to filter on the physical bridge devices (with the physdev
  * module), we steal packets destined to a bridge device away from the
  * PF_INET/FORWARD and PF_INET/OUTPUT hook functions, and give them back later,
  * when we have determined the real output device. This is done in here.
@@ -501,45 +658,44 @@
  * this packet before, and so the packet was locally originated. We fake
  * the PF_INET/LOCAL_OUT hook.
  * Finally, if nf_bridge->physindev isn't NULL, then the packet was IP routed,
- * so we fake the PF_INET/FORWARD hook. ipv4_sabotage_out() makes sure
+ * so we fake the PF_INET/FORWARD hook. ip_sabotage_out() makes sure
  * even routed packets that didn't arrive on a bridge interface have their
- * nf_bridge->physindev set.
- */
-
+ * nf_bridge->physindev set. */
 static unsigned int br_nf_local_out(unsigned int hook, struct sk_buff **pskb,
    const struct net_device *in, const struct net_device *out,
-   int (*_okfn)(struct sk_buff *))
+   int (*okfn)(struct sk_buff *))
 {
-	int (*okfn)(struct sk_buff *skb);
-	struct net_device *realindev;
+	struct net_device *realindev, *realoutdev;
 	struct sk_buff *skb = *pskb;
 	struct nf_bridge_info *nf_bridge;
-	struct vlan_ethhdr *hdr = (struct vlan_ethhdr *)(skb->mac.ethernet);
+	struct vlan_ethhdr *hdr = vlan_eth_hdr(skb);
+	int pf;
 
-#ifdef CONFIG_SYSCTL
 	if (!skb->nf_bridge)
 		return NF_ACCEPT;
-#endif
 
-	if (skb->protocol != __constant_htons(ETH_P_IP) && !IS_VLAN_IP)
-		return NF_ACCEPT;
+	if (skb->protocol == __constant_htons(ETH_P_IP) || IS_VLAN_IP)
+		pf = PF_INET;
+	else
+		pf = PF_INET6;
 
+#ifdef CONFIG_NETFILTER_DEBUG
 	/* Sometimes we get packets with NULL ->dst here (for example,
-	 * running a dhcp client daemon triggers this).
-	 */
-	if (skb->dst == NULL)
+	 * running a dhcp client daemon triggers this). This should now
+	 * be fixed, but let's keep the check around. */
+	if (skb->dst == NULL) {
+		printk(KERN_CRIT "br_netfilter: skb->dst == NULL.");
 		return NF_ACCEPT;
+	}
+#endif
 
 	nf_bridge = skb->nf_bridge;
 	nf_bridge->physoutdev = skb->dev;
 	realindev = nf_bridge->physindev;
 
 	/* Bridged, take PF_BRIDGE/FORWARD.
-	 * (see big note in front of br_nf_pre_routing_finish)
-	 */
+	 * (see big note in front of br_nf_pre_routing_finish) */
 	if (nf_bridge->mask & BRNF_BRIDGED_DNAT) {
-		okfn = br_forward_finish;
-
 		if (nf_bridge->mask & BRNF_PKT_TYPE) {
 			skb->pkt_type = PACKET_OTHERHOST;
 			nf_bridge->mask ^= BRNF_PKT_TYPE;
@@ -550,41 +706,41 @@
 		}
 
 		NF_HOOK(PF_BRIDGE, NF_BR_FORWARD, skb, realindev,
-			skb->dev, okfn);
-	} else {
-		struct net_device *realoutdev = bridge_parent(skb->dev);
+			skb->dev, br_forward_finish);
+		goto out;
+	}
+	realoutdev = bridge_parent(skb->dev);
 
 #if defined(CONFIG_VLAN_8021Q) || defined(CONFIG_VLAN_8021Q_MODULE)
-		/* iptables should match -o br0.x */
-		if (nf_bridge->netoutdev)
-			realoutdev = nf_bridge->netoutdev;
+	/* iptables should match -o br0.x */
+	if (nf_bridge->netoutdev)
+		realoutdev = nf_bridge->netoutdev;
 #endif
-		okfn = br_nf_local_out_finish;
-		if (skb->protocol == __constant_htons(ETH_P_8021Q)) {
-			skb_pull(skb, VLAN_HLEN);
-			(*pskb)->nh.raw += VLAN_HLEN;
-		}
-		/* IP forwarded traffic has a physindev, locally
-		 * generated traffic hasn't.
-		 */
-		if (realindev != NULL) {
-			if (((nf_bridge->mask & BRNF_DONT_TAKE_PARENT) == 0) &&
-			    has_bridge_parent(realindev))
-				realindev = bridge_parent(realindev);
-			NF_HOOK_THRESH(PF_INET, NF_IP_FORWARD, skb, realindev,
-				       realoutdev, okfn,
-				       NF_IP_PRI_BRIDGE_SABOTAGE_FORWARD + 1);
-		} else {
+	if (skb->protocol == __constant_htons(ETH_P_8021Q)) {
+		skb_pull(skb, VLAN_HLEN);
+		(*pskb)->nh.raw += VLAN_HLEN;
+	}
+	/* IP forwarded traffic has a physindev, locally
+	 * generated traffic hasn't. */
+	if (realindev != NULL) {
+		if (!(nf_bridge->mask & BRNF_DONT_TAKE_PARENT) &&
+		    has_bridge_parent(realindev))
+			realindev = bridge_parent(realindev);
+
+		NF_HOOK_THRESH(pf, NF_IP_FORWARD, skb, realindev,
+			       realoutdev, br_nf_local_out_finish,
+			       NF_IP_PRI_BRIDGE_SABOTAGE_FORWARD + 1);
+	} else {
 #ifdef CONFIG_NETFILTER_DEBUG
-			skb->nf_debug ^= (1 << NF_IP_LOCAL_OUT);
+		skb->nf_debug ^= (1 << NF_IP_LOCAL_OUT);
 #endif
 
-			NF_HOOK_THRESH(PF_INET, NF_IP_LOCAL_OUT, skb, realindev,
-				       realoutdev, okfn,
-				       NF_IP_PRI_BRIDGE_SABOTAGE_LOCAL_OUT + 1);
-		}
+		NF_HOOK_THRESH(pf, NF_IP_LOCAL_OUT, skb, realindev,
+			       realoutdev, br_nf_local_out_finish,
+			       NF_IP_PRI_BRIDGE_SABOTAGE_LOCAL_OUT + 1);
 	}
 
+out:
 	return NF_STOLEN;
 }
 
@@ -596,8 +752,9 @@
 {
 	struct sk_buff *skb = *pskb;
 	struct nf_bridge_info *nf_bridge = (*pskb)->nf_bridge;
-	struct vlan_ethhdr *hdr = (struct vlan_ethhdr *)(skb->mac.ethernet);
+	struct vlan_ethhdr *hdr = vlan_eth_hdr(skb);
 	struct net_device *realoutdev = bridge_parent(skb->dev);
+	int pf;
 
 #ifdef CONFIG_NETFILTER_DEBUG
 	/* Be very paranoid. This probably won't happen anymore, but let's
@@ -609,19 +766,15 @@
 	}
 #endif
 
-#ifdef CONFIG_SYSCTL
 	if (!nf_bridge)
 		return NF_ACCEPT;
-#endif
 
-	if (skb->protocol != __constant_htons(ETH_P_IP) && !IS_VLAN_IP)
-		return NF_ACCEPT;
+	if (skb->protocol == __constant_htons(ETH_P_IP) || IS_VLAN_IP)
+		pf = PF_INET;
+	else
+		pf = PF_INET6;
 
 #ifdef CONFIG_NETFILTER_DEBUG
-	/* Sometimes we get packets with NULL ->dst here (for example,
-	 * running a dhcp client daemon triggers this). This should now
-	 * be fixed, but let's keep the check around.
-	 */
 	if (skb->dst == NULL) {
 		printk(KERN_CRIT "br_netfilter: skb->dst == NULL.");
 		goto print_error;
@@ -631,8 +784,7 @@
 #endif
 
 	/* We assume any code from br_dev_queue_push_xmit onwards doesn't care
-	 * about the value of skb->pkt_type.
-	 */
+	 * about the value of skb->pkt_type. */
 	if (skb->pkt_type == PACKET_OTHERHOST) {
 		skb->pkt_type = PACKET_HOST;
 		nf_bridge->mask |= BRNF_PKT_TYPE;
@@ -649,8 +801,8 @@
 	if (nf_bridge->netoutdev)
 		realoutdev = nf_bridge->netoutdev;
 #endif
-	NF_HOOK(PF_INET, NF_IP_POST_ROUTING, skb, NULL,
-		realoutdev, br_dev_queue_push_xmit);
+	NF_HOOK(pf, NF_IP_POST_ROUTING, skb, NULL, realoutdev,
+	        br_dev_queue_push_xmit);
 
 	return NF_STOLEN;
 
@@ -668,12 +820,10 @@
 }
 
 
-/* IPv4/SABOTAGE *****************************************************/
-
-/* Don't hand locally destined packets to PF_INET/PRE_ROUTING
- * for the second time.
- */
-static unsigned int ipv4_sabotage_in(unsigned int hook, struct sk_buff **pskb,
+/* IP/SABOTAGE *****************************************************/
+/* Don't hand locally destined packets to PF_INET(6)/PRE_ROUTING
+ * for the second time. */
+static unsigned int ip_sabotage_in(unsigned int hook, struct sk_buff **pskb,
    const struct net_device *in, const struct net_device *out,
    int (*okfn)(struct sk_buff *))
 {
@@ -686,19 +836,26 @@
 	return NF_ACCEPT;
 }
 
-/* Postpone execution of PF_INET/FORWARD, PF_INET/LOCAL_OUT
- * and PF_INET/POST_ROUTING until we have done the forwarding
- * decision in the bridge code and have determined skb->physoutdev.
- */
-static unsigned int ipv4_sabotage_out(unsigned int hook, struct sk_buff **pskb,
+/* Postpone execution of PF_INET(6)/FORWARD, PF_INET(6)/LOCAL_OUT
+ * and PF_INET(6)/POST_ROUTING until we have done the forwarding
+ * decision in the bridge code and have determined nf_bridge->physoutdev. */
+static unsigned int ip_sabotage_out(unsigned int hook, struct sk_buff **pskb,
    const struct net_device *in, const struct net_device *out,
    int (*okfn)(struct sk_buff *))
 {
 	struct sk_buff *skb = *pskb;
 
 #ifdef CONFIG_SYSCTL
-	if (!brnf_call_iptables && !skb->nf_bridge)
-		return NF_ACCEPT;
+	if (!skb->nf_bridge) {
+		struct vlan_ethhdr *hdr = vlan_eth_hdr(skb);
+
+		if (skb->protocol == __constant_htons(ETH_P_IP) ||
+		    IS_VLAN_IP) {
+			if (!brnf_call_iptables)
+				return NF_ACCEPT;
+		} else if (!brnf_call_ip6tables)
+			return NF_ACCEPT;
+	}
 #endif
 
 	if ((out->hard_start_xmit == br_dev_xmit &&
@@ -721,8 +878,7 @@
 		 * will need the indev then. For a brouter, the real indev
 		 * can be a bridge port, so we make sure br_nf_local_out()
 		 * doesn't use the bridge parent of the indev by using
-		 * the BRNF_DONT_TAKE_PARENT mask.
-		 */
+		 * the BRNF_DONT_TAKE_PARENT mask. */
 		if (hook == NF_IP_FORWARD && nf_bridge->physindev == NULL) {
 			nf_bridge->mask &= BRNF_DONT_TAKE_PARENT;
 			nf_bridge->physindev = (struct net_device *)in;
@@ -742,8 +898,7 @@
 /* For br_nf_local_out we need (prio = NF_BR_PRI_FIRST), to insure that innocent
  * PF_BRIDGE/NF_BR_LOCAL_OUT functions don't get bridged traffic as input.
  * For br_nf_post_routing, we need (prio = NF_BR_PRI_LAST), because
- * ip_refrag() can return NF_STOLEN.
- */
+ * ip_refrag() can return NF_STOLEN. */
 static struct nf_hook_ops br_nf_ops[] = {
 	{ .hook = br_nf_pre_routing, 
 	  .owner = THIS_MODULE, 
@@ -775,26 +930,46 @@
 	  .pf = PF_BRIDGE,
 	  .hooknum = NF_BR_POST_ROUTING,
 	  .priority = NF_BR_PRI_LAST, },
-	{ .hook = ipv4_sabotage_in,
+	{ .hook = ip_sabotage_in,
 	  .owner = THIS_MODULE,
 	  .pf = PF_INET,
 	  .hooknum = NF_IP_PRE_ROUTING,
 	  .priority = NF_IP_PRI_FIRST, },
-	{ .hook = ipv4_sabotage_out,
+	{ .hook = ip_sabotage_in,
+	  .owner = THIS_MODULE,
+	  .pf = PF_INET6,
+	  .hooknum = NF_IP6_PRE_ROUTING,
+	  .priority = NF_IP6_PRI_FIRST, },
+	{ .hook = ip_sabotage_out,
 	  .owner = THIS_MODULE,
 	  .pf = PF_INET,
 	  .hooknum = NF_IP_FORWARD,
 	  .priority = NF_IP_PRI_BRIDGE_SABOTAGE_FORWARD, },
-	{ .hook = ipv4_sabotage_out,
+	{ .hook = ip_sabotage_out,
+	  .owner = THIS_MODULE,
+	  .pf = PF_INET6,
+	  .hooknum = NF_IP6_FORWARD,
+	  .priority = NF_IP6_PRI_BRIDGE_SABOTAGE_FORWARD, },
+	{ .hook = ip_sabotage_out,
 	  .owner = THIS_MODULE,
 	  .pf = PF_INET,
 	  .hooknum = NF_IP_LOCAL_OUT,
 	  .priority = NF_IP_PRI_BRIDGE_SABOTAGE_LOCAL_OUT, },
-	{ .hook = ipv4_sabotage_out,
+	{ .hook = ip_sabotage_out,
+	  .owner = THIS_MODULE,
+	  .pf = PF_INET6,
+	  .hooknum = NF_IP6_LOCAL_OUT,
+	  .priority = NF_IP6_PRI_BRIDGE_SABOTAGE_LOCAL_OUT, },
+	{ .hook = ip_sabotage_out,
 	  .owner = THIS_MODULE,
 	  .pf = PF_INET,
 	  .hooknum = NF_IP_POST_ROUTING,
 	  .priority = NF_IP_PRI_FIRST, },
+	{ .hook = ip_sabotage_out,
+	  .owner = THIS_MODULE,
+	  .pf = PF_INET6,
+	  .hooknum = NF_IP6_POST_ROUTING,
+	  .priority = NF_IP6_PRI_FIRST, },
 };
 
 #ifdef CONFIG_SYSCTL
@@ -824,6 +999,14 @@
 		.ctl_name	= NET_BRIDGE_NF_CALL_IPTABLES,
 		.procname	= "bridge-nf-call-iptables",
 		.data		= &brnf_call_iptables,
+		.maxlen		= sizeof(int),
+		.mode		= 0644,
+		.proc_handler	= &brnf_sysctl_call_tables,
+	},
+	{
+		.ctl_name	= NET_BRIDGE_NF_CALL_IP6TABLES,
+		.procname	= "bridge-nf-call-ip6tables",
+		.data		= &brnf_call_ip6tables,
 		.maxlen		= sizeof(int),
 		.mode		= 0644,
 		.proc_handler	= &brnf_sysctl_call_tables,
diff -Nru a/net/bridge/br_notify.c b/net/bridge/br_notify.c
--- a/net/bridge/br_notify.c	2004-10-18 14:55:54 -07:00
+++ b/net/bridge/br_notify.c	2004-10-18 14:55:54 -07:00
@@ -76,10 +76,12 @@
 		break;
 
 	case NETDEV_UNREGISTER:
+		spin_unlock_bh(&br->lock);
 		br_del_if(br, dev);
-		break;
+		goto done;
 	} 
 	spin_unlock_bh(&br->lock);
 
+ done:
 	return NOTIFY_DONE;
 }
diff -Nru a/net/bridge/br_private.h b/net/bridge/br_private.h
--- a/net/bridge/br_private.h	2004-10-18 14:56:18 -07:00
+++ b/net/bridge/br_private.h	2004-10-18 14:56:18 -07:00
@@ -177,7 +177,7 @@
 
 /* br_input.c */
 extern int br_handle_frame_finish(struct sk_buff *skb);
-extern int br_handle_frame(struct sk_buff *skb);
+extern int br_handle_frame(struct net_bridge_port *p, struct sk_buff **pskb);
 
 /* br_ioctl.c */
 extern int br_dev_ioctl(struct net_device *dev, struct ifreq *rq, int cmd);
diff -Nru a/net/bridge/netfilter/ebt_802_3.c b/net/bridge/netfilter/ebt_802_3.c
--- a/net/bridge/netfilter/ebt_802_3.c	2004-10-18 14:56:33 -07:00
+++ b/net/bridge/netfilter/ebt_802_3.c	2004-10-18 14:56:33 -07:00
@@ -16,7 +16,7 @@
    const struct net_device *out, const void *data, unsigned int datalen)
 {
 	struct ebt_802_3_info *info = (struct ebt_802_3_info *)data;
-	struct ebt_802_3_hdr *hdr = (struct ebt_802_3_hdr *)skb->mac.ethernet;
+	struct ebt_802_3_hdr *hdr = ebt_802_3_hdr(skb);
 	uint16_t type = hdr->llc.ui.ctrl & IS_UI ? hdr->llc.ui.type : hdr->llc.ni.type;
 
 	if (info->bitmask & EBT_802_3_SAP) {
diff -Nru a/net/bridge/netfilter/ebt_among.c b/net/bridge/netfilter/ebt_among.c
--- a/net/bridge/netfilter/ebt_among.c	2004-10-18 14:56:49 -07:00
+++ b/net/bridge/netfilter/ebt_among.c	2004-10-18 14:56:49 -07:00
@@ -72,42 +72,55 @@
 
 static int get_ip_dst(const struct sk_buff *skb, uint32_t *addr)
 {
-	if (skb->mac.ethernet->h_proto == __constant_htons(ETH_P_IP)) {
-		struct iphdr iph;
+	if (eth_hdr(skb)->h_proto == htons(ETH_P_IP)) {
+		struct iphdr _iph, *ih;
 
-		if (skb_copy_bits(skb, 0, &iph, sizeof(iph)))
+		ih = skb_header_pointer(skb, 0, sizeof(_iph), &_iph);
+		if (ih == NULL)
 			return -1;
-		*addr = iph.daddr;
-	} else if (skb->mac.ethernet->h_proto == __constant_htons(ETH_P_ARP)) {
-		struct arphdr arph;
-
-		if (skb_copy_bits(skb, 0, &arph, sizeof(arph)) ||
-		    arph.ar_pln != sizeof(uint32_t) || arph.ar_hln != ETH_ALEN)
-			return -1;
-		if (skb_copy_bits(skb, sizeof(struct arphdr) +
-		    2 * ETH_ALEN + sizeof(uint32_t), addr, sizeof(uint32_t)))
+		*addr = ih->daddr;
+	} else if (eth_hdr(skb)->h_proto == htons(ETH_P_ARP)) {
+		struct arphdr _arph, *ah;
+		uint32_t buf, *bp;
+
+		ah = skb_header_pointer(skb, 0, sizeof(_arph), &_arph);
+		if (ah == NULL ||
+		    ah->ar_pln != sizeof(uint32_t) ||
+		    ah->ar_hln != ETH_ALEN)
+			return -1;
+		bp = skb_header_pointer(skb, sizeof(struct arphdr) +
+					2 * ETH_ALEN + sizeof(uint32_t),
+					sizeof(uint32_t), &buf);
+		if (bp == NULL)
 			return -1;
+		*addr = *bp;
 	}
 	return 0;
 }
 
 static int get_ip_src(const struct sk_buff *skb, uint32_t *addr)
 {
-	if (skb->mac.ethernet->h_proto == __constant_htons(ETH_P_IP)) {
-		struct iphdr iph;
-
-		if (skb_copy_bits(skb, 0, &iph, sizeof(iph)))
-			return -1;
-		*addr = iph.saddr;
-	} else if (skb->mac.ethernet->h_proto == __constant_htons(ETH_P_ARP)) {
-		struct arphdr arph;
+	if (eth_hdr(skb)->h_proto == htons(ETH_P_IP)) {
+		struct iphdr _iph, *ih;
 
-		if (skb_copy_bits(skb, 0, &arph, sizeof(arph)) ||
-		    arph.ar_pln != sizeof(uint32_t) || arph.ar_hln != ETH_ALEN)
+		ih = skb_header_pointer(skb, 0, sizeof(_iph), &_iph);
+		if (ih == NULL)
 			return -1;
-		if (skb_copy_bits(skb, sizeof(struct arphdr) +
-		    ETH_ALEN, addr, sizeof(uint32_t)))
+		*addr = ih->saddr;
+	} else if (eth_hdr(skb)->h_proto == htons(ETH_P_ARP)) {
+		struct arphdr _arph, *ah;
+		uint32_t buf, *bp;
+
+		ah = skb_header_pointer(skb, 0, sizeof(_arph), &_arph);
+		if (ah == NULL ||
+		    ah->ar_pln != sizeof(uint32_t) ||
+		    ah->ar_hln != ETH_ALEN)
+			return -1;
+		bp = skb_header_pointer(skb, sizeof(struct arphdr) +
+					ETH_ALEN, sizeof(uint32_t), &buf);
+		if (bp == NULL)
 			return -1;
+		*addr = *bp;
 	}
 	return 0;
 }
@@ -126,7 +139,7 @@
 	wh_src = ebt_among_wh_src(info);
 
 	if (wh_src) {
-		smac = skb->mac.ethernet->h_source;
+		smac = eth_hdr(skb)->h_source;
 		if (get_ip_src(skb, &sip))
 			return EBT_NOMATCH;
 		if (!(info->bitmask & EBT_AMONG_SRC_NEG)) {
@@ -141,7 +154,7 @@
 	}
 
 	if (wh_dst) {
-		dmac = skb->mac.ethernet->h_dest;
+		dmac = eth_hdr(skb)->h_dest;
 		if (get_ip_dst(skb, &dip))
 			return EBT_NOMATCH;
 		if (!(info->bitmask & EBT_AMONG_DST_NEG)) {
diff -Nru a/net/bridge/netfilter/ebt_arp.c b/net/bridge/netfilter/ebt_arp.c
--- a/net/bridge/netfilter/ebt_arp.c	2004-10-18 14:56:27 -07:00
+++ b/net/bridge/netfilter/ebt_arp.c	2004-10-18 14:56:27 -07:00
@@ -19,72 +19,79 @@
    const struct net_device *out, const void *data, unsigned int datalen)
 {
 	struct ebt_arp_info *info = (struct ebt_arp_info *)data;
-	struct arphdr arph;
+	struct arphdr _arph, *ah;
 
-	if (skb_copy_bits(skb, 0, &arph, sizeof(arph)))
+	ah = skb_header_pointer(skb, 0, sizeof(_arph), &_arph);
+	if (ah == NULL)
 		return EBT_NOMATCH;
 	if (info->bitmask & EBT_ARP_OPCODE && FWINV(info->opcode !=
-	   arph.ar_op, EBT_ARP_OPCODE))
+	   ah->ar_op, EBT_ARP_OPCODE))
 		return EBT_NOMATCH;
 	if (info->bitmask & EBT_ARP_HTYPE && FWINV(info->htype !=
-	   arph.ar_hrd, EBT_ARP_HTYPE))
+	   ah->ar_hrd, EBT_ARP_HTYPE))
 		return EBT_NOMATCH;
 	if (info->bitmask & EBT_ARP_PTYPE && FWINV(info->ptype !=
-	   arph.ar_pro, EBT_ARP_PTYPE))
+	   ah->ar_pro, EBT_ARP_PTYPE))
 		return EBT_NOMATCH;
 
 	if (info->bitmask & (EBT_ARP_SRC_IP | EBT_ARP_DST_IP)) {
-		uint32_t addr;
+		uint32_t _addr, *ap;
 
 		/* IPv4 addresses are always 4 bytes */
-		if (arph.ar_pln != sizeof(uint32_t))
+		if (ah->ar_pln != sizeof(uint32_t))
 			return EBT_NOMATCH;
 		if (info->bitmask & EBT_ARP_SRC_IP) {
-			if (skb_copy_bits(skb, sizeof(struct arphdr) +
-			    arph.ar_hln, &addr, sizeof(addr)))
+			ap = skb_header_pointer(skb, sizeof(struct arphdr) +
+						ah->ar_hln, sizeof(_addr),
+						&_addr);
+			if (ap == NULL)
 				return EBT_NOMATCH;
-			if (FWINV(info->saddr != (addr & info->smsk),
+			if (FWINV(info->saddr != (*ap & info->smsk),
 			   EBT_ARP_SRC_IP))
 				return EBT_NOMATCH;
 		}
 
 		if (info->bitmask & EBT_ARP_DST_IP) {
-			if (skb_copy_bits(skb, sizeof(struct arphdr) +
-			    2*arph.ar_hln + sizeof(uint32_t), &addr,
-			    sizeof(addr)))
+			ap = skb_header_pointer(skb, sizeof(struct arphdr) +
+						2*ah->ar_hln+sizeof(uint32_t),
+						sizeof(_addr), &_addr);
+			if (ap == NULL)
 				return EBT_NOMATCH;
-			if (FWINV(info->daddr != (addr & info->dmsk),
+			if (FWINV(info->daddr != (*ap & info->dmsk),
 			   EBT_ARP_DST_IP))
 				return EBT_NOMATCH;
 		}
 	}
 
 	if (info->bitmask & (EBT_ARP_SRC_MAC | EBT_ARP_DST_MAC)) {
-		unsigned char mac[ETH_ALEN];
+		unsigned char _mac[ETH_ALEN], *mp;
 		uint8_t verdict, i;
 
 		/* MAC addresses are 6 bytes */
-		if (arph.ar_hln != ETH_ALEN)
+		if (ah->ar_hln != ETH_ALEN)
 			return EBT_NOMATCH;
 		if (info->bitmask & EBT_ARP_SRC_MAC) {
-			if (skb_copy_bits(skb, sizeof(struct arphdr), &mac,
-			    ETH_ALEN))
+			mp = skb_header_pointer(skb, sizeof(struct arphdr),
+						sizeof(_mac), &_mac);
+			if (mp == NULL)
 				return EBT_NOMATCH;
 			verdict = 0;
 			for (i = 0; i < 6; i++)
-				verdict |= (mac[i] ^ info->smaddr[i]) &
+				verdict |= (mp[i] ^ info->smaddr[i]) &
 				       info->smmsk[i];
 			if (FWINV(verdict != 0, EBT_ARP_SRC_MAC))
 				return EBT_NOMATCH;
 		}
 
 		if (info->bitmask & EBT_ARP_DST_MAC) {
-			if (skb_copy_bits(skb, sizeof(struct arphdr) +
-			    arph.ar_hln + arph.ar_pln, &mac, ETH_ALEN))
+			mp = skb_header_pointer(skb, sizeof(struct arphdr) +
+						ah->ar_hln + ah->ar_pln,
+						sizeof(_mac), &_mac);
+			if (mp == NULL)
 				return EBT_NOMATCH;
 			verdict = 0;
 			for (i = 0; i < 6; i++)
-				verdict |= (mac[i] ^ info->dmaddr[i]) &
+				verdict |= (mp[i] ^ info->dmaddr[i]) &
 					info->dmmsk[i];
 			if (FWINV(verdict != 0, EBT_ARP_DST_MAC))
 				return EBT_NOMATCH;
@@ -101,8 +108,8 @@
 
 	if (datalen != EBT_ALIGN(sizeof(struct ebt_arp_info)))
 		return -EINVAL;
-	if ((e->ethproto != __constant_htons(ETH_P_ARP) &&
-	   e->ethproto != __constant_htons(ETH_P_RARP)) ||
+	if ((e->ethproto != htons(ETH_P_ARP) &&
+	   e->ethproto != htons(ETH_P_RARP)) ||
 	   e->invflags & EBT_IPROTO)
 		return -EINVAL;
 	if (info->bitmask & ~EBT_ARP_MASK || info->invflags & ~EBT_ARP_MASK)
diff -Nru a/net/bridge/netfilter/ebt_arpreply.c b/net/bridge/netfilter/ebt_arpreply.c
--- a/net/bridge/netfilter/ebt_arpreply.c	2004-10-18 14:55:53 -07:00
+++ b/net/bridge/netfilter/ebt_arpreply.c	2004-10-18 14:55:53 -07:00
@@ -20,30 +20,38 @@
    const void *data, unsigned int datalen)
 {
 	struct ebt_arpreply_info *info = (struct ebt_arpreply_info *)data;
-	u32 sip, dip;
-	struct arphdr ah;
-	unsigned char sha[ETH_ALEN];
+	u32 _sip, *siptr, _dip, *diptr;
+	struct arphdr _ah, *ap;
+	unsigned char _sha[ETH_ALEN], *shp;
 	struct sk_buff *skb = *pskb;
 
-	if (skb_copy_bits(skb, 0, &ah, sizeof(ah)))
+	ap = skb_header_pointer(skb, 0, sizeof(_ah), &_ah);
+	if (ap == NULL)
 		return EBT_DROP;
 
-	if (ah.ar_op != __constant_htons(ARPOP_REQUEST) || ah.ar_hln != ETH_ALEN
-	    || ah.ar_pro != __constant_htons(ETH_P_IP) || ah.ar_pln != 4)
+	if (ap->ar_op != htons(ARPOP_REQUEST) ||
+	    ap->ar_hln != ETH_ALEN ||
+	    ap->ar_pro != htons(ETH_P_IP) ||
+	    ap->ar_pln != 4)
 		return EBT_CONTINUE;
 
-	if (skb_copy_bits(skb, sizeof(ah), &sha, ETH_ALEN))
+	shp = skb_header_pointer(skb, sizeof(_ah), ETH_ALEN, &_sha);
+	if (shp == NULL)
 		return EBT_DROP;
 
-	if (skb_copy_bits(skb, sizeof(ah) + ETH_ALEN, &sip, sizeof(sip)))
+	siptr = skb_header_pointer(skb, sizeof(_ah) + ETH_ALEN,
+				   sizeof(_sip), &_sip);
+	if (siptr == NULL)
 		return EBT_DROP;
 
-	if (skb_copy_bits(skb, sizeof(ah) + 2 * ETH_ALEN + sizeof(sip),
-	    &dip, sizeof(dip)))
+	diptr = skb_header_pointer(skb,
+				   sizeof(_ah) + 2 * ETH_ALEN + sizeof(_sip),
+				   sizeof(_dip), &_dip);
+	if (diptr == NULL)
 		return EBT_DROP;
 
-	arp_send(ARPOP_REPLY, ETH_P_ARP, sip, (struct net_device *)in,
-	         dip, sha, info->mac, sha);
+	arp_send(ARPOP_REPLY, ETH_P_ARP, *siptr, (struct net_device *)in,
+	         *diptr, shp, info->mac, shp);
 
 	return info->target;
 }
@@ -57,7 +65,7 @@
 		return -EINVAL;
 	if (BASE_CHAIN && info->target == EBT_RETURN)
 		return -EINVAL;
-	if (e->ethproto != __constant_htons(ETH_P_ARP) ||
+	if (e->ethproto != htons(ETH_P_ARP) ||
 	    e->invflags & EBT_IPROTO)
 		return -EINVAL;
 	CLEAR_BASE_CHAIN_BIT;
diff -Nru a/net/bridge/netfilter/ebt_dnat.c b/net/bridge/netfilter/ebt_dnat.c
--- a/net/bridge/netfilter/ebt_dnat.c	2004-10-18 14:56:33 -07:00
+++ b/net/bridge/netfilter/ebt_dnat.c	2004-10-18 14:56:33 -07:00
@@ -30,8 +30,7 @@
 		kfree_skb(*pskb);
 		*pskb = nskb;
 	}
-	memcpy(((**pskb).mac.ethernet)->h_dest, info->mac,
-	   ETH_ALEN * sizeof(unsigned char));
+	memcpy(eth_hdr(*pskb)->h_dest, info->mac, ETH_ALEN);
 	return info->target;
 }
 
diff -Nru a/net/bridge/netfilter/ebt_ip.c b/net/bridge/netfilter/ebt_ip.c
--- a/net/bridge/netfilter/ebt_ip.c	2004-10-18 14:56:29 -07:00
+++ b/net/bridge/netfilter/ebt_ip.c	2004-10-18 14:56:29 -07:00
@@ -28,41 +28,44 @@
    unsigned int datalen)
 {
 	struct ebt_ip_info *info = (struct ebt_ip_info *)data;
-	union {struct iphdr iph; struct tcpudphdr ports;} u;
+	struct iphdr _iph, *ih;
+	struct tcpudphdr _ports, *pptr;
 
-	if (skb_copy_bits(skb, 0, &u.iph, sizeof(u.iph)))
+	ih = skb_header_pointer(skb, 0, sizeof(_iph), &_iph);
+	if (ih == NULL)
 		return EBT_NOMATCH;
 	if (info->bitmask & EBT_IP_TOS &&
-	   FWINV(info->tos != u.iph.tos, EBT_IP_TOS))
+	   FWINV(info->tos != ih->tos, EBT_IP_TOS))
 		return EBT_NOMATCH;
 	if (info->bitmask & EBT_IP_SOURCE &&
-	   FWINV((u.iph.saddr & info->smsk) !=
+	   FWINV((ih->saddr & info->smsk) !=
 	   info->saddr, EBT_IP_SOURCE))
 		return EBT_NOMATCH;
 	if ((info->bitmask & EBT_IP_DEST) &&
-	   FWINV((u.iph.daddr & info->dmsk) !=
+	   FWINV((ih->daddr & info->dmsk) !=
 	   info->daddr, EBT_IP_DEST))
 		return EBT_NOMATCH;
 	if (info->bitmask & EBT_IP_PROTO) {
-		if (FWINV(info->protocol != u.iph.protocol, EBT_IP_PROTO))
+		if (FWINV(info->protocol != ih->protocol, EBT_IP_PROTO))
 			return EBT_NOMATCH;
 		if (!(info->bitmask & EBT_IP_DPORT) &&
 		    !(info->bitmask & EBT_IP_SPORT))
 			return EBT_MATCH;
-		if (skb_copy_bits(skb, u.iph.ihl*4, &u.ports,
-		    sizeof(u.ports)))
+		pptr = skb_header_pointer(skb, ih->ihl*4,
+					  sizeof(_ports), &_ports);
+		if (pptr == NULL)
 			return EBT_NOMATCH;
 		if (info->bitmask & EBT_IP_DPORT) {
-			u.ports.dst = ntohs(u.ports.dst);
-			if (FWINV(u.ports.dst < info->dport[0] ||
-			          u.ports.dst > info->dport[1],
+			u32 dst = ntohs(pptr->dst);
+			if (FWINV(dst < info->dport[0] ||
+			          dst > info->dport[1],
 			          EBT_IP_DPORT))
 			return EBT_NOMATCH;
 		}
 		if (info->bitmask & EBT_IP_SPORT) {
-			u.ports.src = ntohs(u.ports.src);
-			if (FWINV(u.ports.src < info->sport[0] ||
-			          u.ports.src > info->sport[1],
+			u32 src = ntohs(pptr->src);
+			if (FWINV(src < info->sport[0] ||
+			          src > info->sport[1],
 			          EBT_IP_SPORT))
 			return EBT_NOMATCH;
 		}
@@ -77,7 +80,7 @@
 
 	if (datalen != EBT_ALIGN(sizeof(struct ebt_ip_info)))
 		return -EINVAL;
-	if (e->ethproto != __constant_htons(ETH_P_IP) ||
+	if (e->ethproto != htons(ETH_P_IP) ||
 	   e->invflags & EBT_IPROTO)
 		return -EINVAL;
 	if (info->bitmask & ~EBT_IP_MASK || info->invflags & ~EBT_IP_MASK)
diff -Nru a/net/bridge/netfilter/ebt_log.c b/net/bridge/netfilter/ebt_log.c
--- a/net/bridge/netfilter/ebt_log.c	2004-10-18 14:56:48 -07:00
+++ b/net/bridge/netfilter/ebt_log.c	2004-10-18 14:56:48 -07:00
@@ -70,64 +70,76 @@
 	   out ? out->name : "");
 
 	printk("MAC source = ");
-	print_MAC((skb->mac.ethernet)->h_source);
+	print_MAC(eth_hdr(skb)->h_source);
 	printk("MAC dest = ");
-	print_MAC((skb->mac.ethernet)->h_dest);
+	print_MAC(eth_hdr(skb)->h_dest);
 
-	printk("proto = 0x%04x", ntohs(((*skb).mac.ethernet)->h_proto));
+	printk("proto = 0x%04x", ntohs(eth_hdr(skb)->h_proto));
 
-	if ((info->bitmask & EBT_LOG_IP) && skb->mac.ethernet->h_proto ==
+	if ((info->bitmask & EBT_LOG_IP) && eth_hdr(skb)->h_proto ==
 	   htons(ETH_P_IP)){
-		if (skb_copy_bits(skb, 0, &u.iph, sizeof(u.iph))) {
+		struct iphdr _iph, *ih;
+
+		ih = skb_header_pointer(skb, 0, sizeof(_iph), &_iph);
+		if (ih == NULL) {
 			printk(" INCOMPLETE IP header");
 			goto out;
 		}
 		printk(" IP SRC=%u.%u.%u.%u IP DST=%u.%u.%u.%u,",
-		   NIPQUAD(u.iph.saddr), NIPQUAD(u.iph.daddr));
+		   NIPQUAD(ih->saddr), NIPQUAD(ih->daddr));
 		printk(" IP tos=0x%02X, IP proto=%d", u.iph.tos,
-		       u.iph.protocol);
-		if (u.iph.protocol == IPPROTO_TCP ||
-		    u.iph.protocol == IPPROTO_UDP) {
-			if (skb_copy_bits(skb, u.iph.ihl*4, &u.ports,
-			    sizeof(u.ports))) {
+		       ih->protocol);
+		if (ih->protocol == IPPROTO_TCP ||
+		    ih->protocol == IPPROTO_UDP) {
+			struct tcpudphdr _ports, *pptr;
+
+			pptr = skb_header_pointer(skb, ih->ihl*4,
+						  sizeof(_ports), &_ports);
+			if (pptr == NULL) {
 				printk(" INCOMPLETE TCP/UDP header");
 				goto out;
 			}
-			printk(" SPT=%u DPT=%u", ntohs(u.ports.src),
-			   ntohs(u.ports.dst));
+			printk(" SPT=%u DPT=%u", ntohs(pptr->src),
+			   ntohs(pptr->dst));
 		}
 		goto out;
 	}
 
 	if ((info->bitmask & EBT_LOG_ARP) &&
-	    ((skb->mac.ethernet->h_proto == __constant_htons(ETH_P_ARP)) ||
-	    (skb->mac.ethernet->h_proto == __constant_htons(ETH_P_RARP)))) {
-		if (skb_copy_bits(skb, 0, &u.arph, sizeof(u.arph))) {
+	    ((eth_hdr(skb)->h_proto == htons(ETH_P_ARP)) ||
+	     (eth_hdr(skb)->h_proto == htons(ETH_P_RARP)))) {
+		struct arphdr _arph, *ah;
+
+		ah = skb_header_pointer(skb, 0, sizeof(_arph), &_arph);
+		if (ah == NULL) {
 			printk(" INCOMPLETE ARP header");
 			goto out;
 		}
 		printk(" ARP HTYPE=%d, PTYPE=0x%04x, OPCODE=%d",
-		       ntohs(u.arph.ar_hrd), ntohs(u.arph.ar_pro),
-		       ntohs(u.arph.ar_op));
+		       ntohs(ah->ar_hrd), ntohs(ah->ar_pro),
+		       ntohs(ah->ar_op));
 
 		/* If it's for Ethernet and the lengths are OK,
 		 * then log the ARP payload */
-		if (u.arph.ar_hrd == __constant_htons(1) &&
-		    u.arph.ar_hln == ETH_ALEN &&
-		    u.arph.ar_pln == sizeof(uint32_t)) {
-			if (skb_copy_bits(skb, sizeof(u.arph), &u.arpp,
-			    sizeof(u.arpp))) {
+		if (ah->ar_hrd == htons(1) &&
+		    ah->ar_hln == ETH_ALEN &&
+		    ah->ar_pln == sizeof(uint32_t)) {
+			struct arppayload _arpp, *ap;
+
+			ap = skb_header_pointer(skb, sizeof(u.arph),
+						sizeof(_arpp), &_arpp);
+			if (ap == NULL) {
 				printk(" INCOMPLETE ARP payload");
 				goto out;
 			}
 			printk(" ARP MAC SRC=");
-			print_MAC(u.arpp.mac_src);
+			print_MAC(ap->mac_src);
 			printk(" ARP IP SRC=%u.%u.%u.%u",
-			       myNIPQUAD(u.arpp.ip_src));
+			       myNIPQUAD(ap->ip_src));
 			printk(" ARP MAC DST=");
-			print_MAC(u.arpp.mac_dst);
+			print_MAC(ap->mac_dst);
 			printk(" ARP IP DST=%u.%u.%u.%u",
-			       myNIPQUAD(u.arpp.ip_dst));
+			       myNIPQUAD(ap->ip_dst));
 		}
 	}
 out:
diff -Nru a/net/bridge/netfilter/ebt_redirect.c b/net/bridge/netfilter/ebt_redirect.c
--- a/net/bridge/netfilter/ebt_redirect.c	2004-10-18 14:56:49 -07:00
+++ b/net/bridge/netfilter/ebt_redirect.c	2004-10-18 14:56:49 -07:00
@@ -32,11 +32,10 @@
 		*pskb = nskb;
 	}
 	if (hooknr != NF_BR_BROUTING)
-		memcpy((**pskb).mac.ethernet->h_dest,
-		   in->br_port->br->dev->dev_addr, ETH_ALEN);
+		memcpy(eth_hdr(*pskb)->h_dest,
+		       in->br_port->br->dev->dev_addr, ETH_ALEN);
 	else
-		memcpy((**pskb).mac.ethernet->h_dest,
-		   in->dev_addr, ETH_ALEN);
+		memcpy(eth_hdr(*pskb)->h_dest, in->dev_addr, ETH_ALEN);
 	(*pskb)->pkt_type = PACKET_HOST;
 	return info->target;
 }
diff -Nru a/net/bridge/netfilter/ebt_snat.c b/net/bridge/netfilter/ebt_snat.c
--- a/net/bridge/netfilter/ebt_snat.c	2004-10-18 14:56:17 -07:00
+++ b/net/bridge/netfilter/ebt_snat.c	2004-10-18 14:56:17 -07:00
@@ -30,8 +30,7 @@
 		kfree_skb(*pskb);
 		*pskb = nskb;
 	}
-	memcpy(((**pskb).mac.ethernet)->h_source, info->mac,
-	   ETH_ALEN * sizeof(unsigned char));
+	memcpy(eth_hdr(*pskb)->h_source, info->mac, ETH_ALEN);
 	return info->target;
 }
 
diff -Nru a/net/bridge/netfilter/ebt_stp.c b/net/bridge/netfilter/ebt_stp.c
--- a/net/bridge/netfilter/ebt_stp.c	2004-10-18 14:55:55 -07:00
+++ b/net/bridge/netfilter/ebt_stp.c	2004-10-18 14:55:55 -07:00
@@ -122,26 +122,30 @@
    const struct net_device *out, const void *data, unsigned int datalen)
 {
 	struct ebt_stp_info *info = (struct ebt_stp_info *)data;
-	struct stp_header stph;
+	struct stp_header _stph, *sp;
 	uint8_t header[6] = {0x42, 0x42, 0x03, 0x00, 0x00, 0x00};
-	if (skb_copy_bits(skb, 0, &stph, sizeof(stph)))
+
+	sp = skb_header_pointer(skb, 0, sizeof(_stph), &_stph);
+	if (sp == NULL)
 		return EBT_NOMATCH;
 
 	/* The stp code only considers these */
-	if (memcmp(&stph, header, sizeof(header)))
+	if (memcmp(sp, header, sizeof(header)))
 		return EBT_NOMATCH;
 
 	if (info->bitmask & EBT_STP_TYPE
-	    && FWINV(info->type != stph.type, EBT_STP_TYPE))
+	    && FWINV(info->type != sp->type, EBT_STP_TYPE))
 		return EBT_NOMATCH;
 
-	if (stph.type == BPDU_TYPE_CONFIG &&
+	if (sp->type == BPDU_TYPE_CONFIG &&
 	    info->bitmask & EBT_STP_CONFIG_MASK) {
-		struct stp_config_pdu stpc;
+		struct stp_config_pdu _stpc, *st;
 
-		if (skb_copy_bits(skb, sizeof(stph), &stpc, sizeof(stpc)))
-		    return EBT_NOMATCH;
-		return ebt_filter_config(info, &stpc);
+		st = skb_header_pointer(skb, sizeof(_stph),
+					sizeof(_stpc), &_stpc);
+		if (st == NULL)
+			return EBT_NOMATCH;
+		return ebt_filter_config(info, st);
 	}
 	return EBT_MATCH;
 }
diff -Nru a/net/bridge/netfilter/ebt_vlan.c b/net/bridge/netfilter/ebt_vlan.c
--- a/net/bridge/netfilter/ebt_vlan.c	2004-10-18 14:56:32 -07:00
+++ b/net/bridge/netfilter/ebt_vlan.c	2004-10-18 14:56:32 -07:00
@@ -21,13 +21,14 @@
 #include <linux/if_ether.h>
 #include <linux/if_vlan.h>
 #include <linux/module.h>
+#include <linux/moduleparam.h>
 #include <linux/netfilter_bridge/ebtables.h>
 #include <linux/netfilter_bridge/ebt_vlan.h>
 
-static unsigned char debug;
+static int debug;
 #define MODULE_VERS "0.6"
 
-MODULE_PARM(debug, "0-1b");
+module_param(debug, int, 0);
 MODULE_PARM_DESC(debug, "debug=1 is turn on debug messages");
 MODULE_AUTHOR("Nick Fedchik <nick@fedchik.org.ua>");
 MODULE_DESCRIPTION("802.1Q match module (ebtables extension), v"
@@ -48,7 +49,7 @@
 		const void *data, unsigned int datalen)
 {
 	struct ebt_vlan_info *info = (struct ebt_vlan_info *) data;
-	struct vlan_hdr frame;
+	struct vlan_hdr _frame, *fp;
 
 	unsigned short TCI;	/* Whole TCI, given from parsed frame */
 	unsigned short id;	/* VLAN ID, given from frame TCI */
@@ -56,7 +57,8 @@
 	/* VLAN encapsulated Type/Length field, given from orig frame */
 	unsigned short encap;
 
-	if (skb_copy_bits(skb, 0, &frame, sizeof(frame)))
+	fp = skb_header_pointer(skb, 0, sizeof(_frame), &_frame);
+	if (fp == NULL)
 		return EBT_NOMATCH;
 
 	/* Tag Control Information (TCI) consists of the following elements:
@@ -66,10 +68,10 @@
 	 * (CFI) is a single bit flag value. Currently ignored.
 	 * - VLAN Identifier (VID). The VID is encoded as
 	 * an unsigned binary number. */
-	TCI = ntohs(frame.h_vlan_TCI);
+	TCI = ntohs(fp->h_vlan_TCI);
 	id = TCI & VLAN_VID_MASK;
 	prio = (TCI >> 13) & 0x7;
-	encap = frame.h_vlan_encapsulated_proto;
+	encap = fp->h_vlan_encapsulated_proto;
 
 	/* Checking VLAN Identifier (VID) */
 	if (GET_BITMASK(EBT_VLAN_ID))
@@ -102,7 +104,7 @@
 	}
 
 	/* Is it 802.1Q frame checked? */
-	if (e->ethproto != __constant_htons(ETH_P_8021Q)) {
+	if (e->ethproto != htons(ETH_P_8021Q)) {
 		DEBUG_MSG
 		    ("passed entry proto %2.4X is not 802.1Q (8100)\n",
 		     (unsigned short) ntohs(e->ethproto));
diff -Nru a/net/bridge/netfilter/ebtables.c b/net/bridge/netfilter/ebtables.c
--- a/net/bridge/netfilter/ebtables.c	2004-10-18 14:56:28 -07:00
+++ b/net/bridge/netfilter/ebtables.c	2004-10-18 14:56:28 -07:00
@@ -190,7 +190,7 @@
 	base = private->entries;
 	i = 0;
 	while (i < nentries) {
-		if (ebt_basic_match(point, (**pskb).mac.ethernet, in, out))
+		if (ebt_basic_match(point, eth_hdr(*pskb), in, out))
 			goto letscontinue;
 
 		if (EBT_MATCH_ITERATE(point, ebt_do_match, *pskb, in, out) != 0)
diff -Nru a/net/compat.c b/net/compat.c
--- a/net/compat.c	2004-10-18 14:56:33 -07:00
+++ b/net/compat.c	2004-10-18 14:56:33 -07:00
@@ -455,13 +455,15 @@
 asmlinkage long compat_sys_setsockopt(int fd, int level, int optname,
 				char __user *optval, int optlen)
 {
+	/* SO_SET_REPLACE seems to be the same in all levels */
 	if (optname == IPT_SO_SET_REPLACE)
 		return do_netfilter_replace(fd, level, optname,
 					    optval, optlen);
-	if (optname == SO_ATTACH_FILTER)
+	if (level == SOL_SOCKET && optname == SO_ATTACH_FILTER)
 		return do_set_attach_filter(fd, level, optname,
 					    optval, optlen);
-	if (optname == SO_RCVTIMEO || optname == SO_SNDTIMEO)
+	if (level == SOL_SOCKET &&
+	    (optname == SO_RCVTIMEO || optname == SO_SNDTIMEO))
 		return do_set_sock_timeout(fd, level, optname, optval, optlen);
 
 	return sys_setsockopt(fd, level, optname, optval, optlen);
diff -Nru a/net/core/Makefile b/net/core/Makefile
--- a/net/core/Makefile	2004-10-18 14:57:04 -07:00
+++ b/net/core/Makefile	2004-10-18 14:57:04 -07:00
@@ -2,7 +2,7 @@
 # Makefile for the Linux networking core.
 #
 
-obj-y := sock.o skbuff.o iovec.o datagram.o stream.o scm.o
+obj-y := sock.o skbuff.o iovec.o datagram.o stream.o scm.o gen_stats.o gen_estimator.o
 
 obj-$(CONFIG_SYSCTL) += sysctl_net_core.o
 
diff -Nru a/net/core/dev.c b/net/core/dev.c
--- a/net/core/dev.c	2004-10-18 14:56:32 -07:00
+++ b/net/core/dev.c	2004-10-18 14:56:32 -07:00
@@ -861,18 +861,6 @@
 }
 
 
-/*
- * Some old buggy device drivers change get_stats after registering
- * the device.  Try and trap them here.
- * This can be elimnated when all devices are known fixed.
- */
-static inline int get_stats_changed(struct net_device *dev)
-{
-	int changed = dev->last_stats != dev->get_stats;
-	dev->last_stats = dev->get_stats;
-	return changed;
-}
-
 /**
  *	dev_open	- prepare an interface for use.
  *	@dev:	device to open
@@ -897,14 +885,6 @@
 		return 0;
 
 	/*
-	 *	 Check for broken device drivers.
-	 */
-	if (get_stats_changed(dev) && net_ratelimit()) {
-		printk(KERN_ERR "%s: driver changed get_stats after register\n",
-		       dev->name);
-	}
-
-	/*
 	 *	Is it even present?
 	 */
 	if (!netif_device_present(dev))
@@ -920,14 +900,6 @@
 			clear_bit(__LINK_STATE_START, &dev->state);
 	}
 
-	/*
-	 * 	Check for more broken device drivers.
-	 */
-	if (get_stats_changed(dev) && net_ratelimit()) {
-		printk(KERN_ERR "%s: driver changed get_stats in open\n",
-		       dev->name);
-	}
-
  	/*
 	 *	If it went open OK then:
 	 */
@@ -1144,16 +1116,10 @@
 		goto out;
 	}
 
-	if (skb_shared(*pskb)  || skb_cloned(*pskb)) {
-		struct sk_buff *newskb = skb_copy(*pskb, GFP_ATOMIC);
-		if (!newskb) {
-			ret = -ENOMEM;
+	if (skb_cloned(*pskb)) {
+		ret = pskb_expand_head(*pskb, 0, 0, GFP_ATOMIC);
+		if (ret)
 			goto out;
-		}
-		if ((*pskb)->sk)
-			skb_set_owner_w(newskb, (*pskb)->sk);
-		kfree_skb(*pskb);
-		*pskb = newskb;
 	}
 
 	if (offset > (int)(*pskb)->len)
@@ -1255,17 +1221,17 @@
 	return 0;
 }
 
-#define HARD_TX_LOCK_BH(dev, cpu) {			\
+#define HARD_TX_LOCK(dev, cpu) {			\
 	if ((dev->features & NETIF_F_LLTX) == 0) {	\
-		spin_lock_bh(&dev->xmit_lock);		\
+		spin_lock(&dev->xmit_lock);		\
 		dev->xmit_lock_owner = cpu;		\
 	}						\
 }
 
-#define HARD_TX_UNLOCK_BH(dev) {			\
+#define HARD_TX_UNLOCK(dev) {				\
 	if ((dev->features & NETIF_F_LLTX) == 0) {	\
 		dev->xmit_lock_owner = -1;		\
-		spin_unlock_bh(&dev->xmit_lock);	\
+		spin_unlock(&dev->xmit_lock);		\
 	}						\
 }
 
@@ -1319,7 +1285,12 @@
 	      	if (skb_checksum_help(&skb, 0))
 	      		goto out_kfree_skb;
 
-	rcu_read_lock();
+
+	/* Disable soft irqs for various locks below. Also 
+	 * stops preemption for RCU. 
+	 */
+	local_bh_disable(); 
+
 	/* Updates of qdisc are serialized by queue_lock. 
 	 * The struct Qdisc which is pointed to by qdisc is now a 
 	 * rcu structure - it may be accessed without acquiring 
@@ -1332,25 +1303,22 @@
 	 * also serializes access to the device queue.
 	 */
 
-	q = dev->qdisc;
-	smp_read_barrier_depends();
+	q = rcu_dereference(dev->qdisc);
 #ifdef CONFIG_NET_CLS_ACT
 	skb->tc_verd = SET_TC_AT(skb->tc_verd,AT_EGRESS);
 #endif
 	if (q->enqueue) {
 		/* Grab device queue */
-		spin_lock_bh(&dev->queue_lock);
+		spin_lock(&dev->queue_lock);
 
 		rc = q->enqueue(skb, q);
 
 		qdisc_run(dev);
 
-		spin_unlock_bh(&dev->queue_lock);
-		rcu_read_unlock();
+		spin_unlock(&dev->queue_lock);
 		rc = rc == NET_XMIT_BYPASS ? NET_XMIT_SUCCESS : rc;
 		goto out;
 	}
-	rcu_read_unlock();
 
 	/* The device has no queue. Common case for software devices:
 	   loopback, all the sorts of tunnels...
@@ -1365,12 +1333,11 @@
 	   Either shot noqueue qdisc, it is even simpler 8)
 	 */
 	if (dev->flags & IFF_UP) {
-		int cpu = get_cpu();
+		int cpu = smp_processor_id(); /* ok because BHs are off */
 
 		if (dev->xmit_lock_owner != cpu) {
 
-			HARD_TX_LOCK_BH(dev, cpu);
-			put_cpu();
+			HARD_TX_LOCK(dev, cpu);
 
 			if (!netif_queue_stopped(dev)) {
 				if (netdev_nit)
@@ -1378,17 +1345,16 @@
 
 				rc = 0;
 				if (!dev->hard_start_xmit(skb, dev)) {
-					HARD_TX_UNLOCK_BH(dev);
+					HARD_TX_UNLOCK(dev);
 					goto out;
 				}
 			}
-			HARD_TX_UNLOCK_BH(dev);
+			HARD_TX_UNLOCK(dev);
 			if (net_ratelimit())
 				printk(KERN_CRIT "Virtual device %s asks to "
 				       "queue packet!\n", dev->name);
 			goto out_enetdown;
 		} else {
-			put_cpu();
 			/* Recursion is detected! It is possible,
 			 * unfortunately */
 			if (net_ratelimit())
@@ -1401,6 +1367,7 @@
 out_kfree_skb:
 	kfree_skb(skb);
 out:
+	local_bh_enable();
 	return rc;
 }
 
@@ -1558,7 +1525,7 @@
 	struct softnet_data *queue;
 	unsigned long flags;
 
-#ifdef CONFIG_NETPOLL_RX
+#ifdef CONFIG_NETPOLL
 	if (skb->dev->netpoll_rx && netpoll_rx(skb)) {
 		kfree_skb(skb);
 		return NET_RX_DROP;
@@ -1677,43 +1644,34 @@
 }
 
 static __inline__ int deliver_skb(struct sk_buff *skb,
-				  struct packet_type *pt_prev, int last)
+				  struct packet_type *pt_prev)
 {
 	atomic_inc(&skb->users);
 	return pt_prev->func(skb, skb->dev, pt_prev);
 }
 
-
 #if defined(CONFIG_BRIDGE) || defined (CONFIG_BRIDGE_MODULE)
-int (*br_handle_frame_hook)(struct sk_buff *skb);
+int (*br_handle_frame_hook)(struct net_bridge_port *p, struct sk_buff **pskb);
 
-static __inline__ int handle_bridge(struct sk_buff *skb,
-				     struct packet_type *pt_prev)
+static __inline__ int handle_bridge(struct sk_buff **pskb,
+				    struct packet_type **pt_prev, int *ret)
 {
-	int ret = NET_RX_DROP;
-	if (pt_prev)
-		ret = deliver_skb(skb, pt_prev, 0);
+	struct net_bridge_port *port;
 
-	return ret;
-}
-
-#endif
-
-static inline int __handle_bridge(struct sk_buff *skb,
-			struct packet_type **pt_prev, int *ret)
-{
-#if defined(CONFIG_BRIDGE) || defined(CONFIG_BRIDGE_MODULE)
-	if (skb->dev->br_port && skb->pkt_type != PACKET_LOOPBACK) {
-		*ret = handle_bridge(skb, *pt_prev);
-		if (br_handle_frame_hook(skb) == 0)
-			return 1;
+	if ((*pskb)->pkt_type == PACKET_LOOPBACK ||
+	    (port = rcu_dereference((*pskb)->dev->br_port)) == NULL)
+		return 0;
 
+	if (*pt_prev) {
+		*ret = deliver_skb(*pskb, *pt_prev);
 		*pt_prev = NULL;
-	}
-#endif
-	return 0;
+	} 
+	
+	return br_handle_frame_hook(port, pskb);
 }
-
+#else
+#define handle_bridge(skb, pt_prev, ret)	(0)
+#endif
 
 #ifdef CONFIG_NET_CLS_ACT
 /* TODO: Maybe we should just force sch_ingress to be compiled in
@@ -1762,7 +1720,7 @@
 	int ret = NET_RX_DROP;
 	unsigned short type;
 
-#ifdef CONFIG_NETPOLL_RX
+#ifdef CONFIG_NETPOLL
 	if (skb->dev->netpoll_rx && skb->dev->poll && netpoll_rx(skb)) {
 		kfree_skb(skb);
 		return NET_RX_DROP;
@@ -1780,27 +1738,27 @@
 	skb->mac_len = skb->nh.raw - skb->mac.raw;
 
 	pt_prev = NULL;
+
+	rcu_read_lock();
+
 #ifdef CONFIG_NET_CLS_ACT
 	if (skb->tc_verd & TC_NCLS) {
 		skb->tc_verd = CLR_TC_NCLS(skb->tc_verd);
-		rcu_read_lock();
 		goto ncls;
 	}
- #endif
+#endif
 
-	rcu_read_lock();
 	list_for_each_entry_rcu(ptype, &ptype_all, list) {
 		if (!ptype->dev || ptype->dev == skb->dev) {
 			if (pt_prev) 
-				ret = deliver_skb(skb, pt_prev, 0);
+				ret = deliver_skb(skb, pt_prev);
 			pt_prev = ptype;
 		}
 	}
 
 #ifdef CONFIG_NET_CLS_ACT
 	if (pt_prev) {
-		atomic_inc(&skb->users);
-		ret = pt_prev->func(skb, skb->dev, pt_prev);
+		ret = deliver_skb(skb, pt_prev);
 		pt_prev = NULL; /* noone else should process this after*/
 	} else {
 		skb->tc_verd = SET_TC_OK2MUNGE(skb->tc_verd);
@@ -1819,7 +1777,7 @@
 
 	handle_diverter(skb);
 
-	if (__handle_bridge(skb, &pt_prev, &ret))
+	if (handle_bridge(&skb, &pt_prev, &ret))
 		goto out;
 
 	type = skb->protocol;
@@ -1827,7 +1785,7 @@
 		if (ptype->type == type &&
 		    (!ptype->dev || ptype->dev == skb->dev)) {
 			if (pt_prev) 
-				ret = deliver_skb(skb, pt_prev, 0);
+				ret = deliver_skb(skb, pt_prev);
 			pt_prev = ptype;
 		}
 	}
@@ -3280,6 +3238,8 @@
 
 	BUG_ON(!dev_boot_phase);
 
+	net_random_init();
+
 	if (dev_proc_init())
 		goto out;
 
@@ -3359,6 +3319,7 @@
 EXPORT_SYMBOL(dev_set_allmulti);
 EXPORT_SYMBOL(dev_set_promiscuity);
 EXPORT_SYMBOL(dev_change_flags);
+EXPORT_SYMBOL(dev_change_name);
 EXPORT_SYMBOL(dev_set_mtu);
 EXPORT_SYMBOL(free_netdev);
 EXPORT_SYMBOL(netdev_boot_setup_check);
diff -Nru a/net/core/dv.c b/net/core/dv.c
--- a/net/core/dv.c	2004-10-18 14:56:29 -07:00
+++ b/net/core/dv.c	2004-10-18 14:56:29 -07:00
@@ -450,12 +450,12 @@
  */
 
 #define	ETH_DIVERT_FRAME(skb) \
-	memcpy(skb->mac.ethernet, skb->dev->dev_addr, ETH_ALEN); \
+	memcpy(eth_hdr(skb), skb->dev->dev_addr, ETH_ALEN); \
 	skb->pkt_type=PACKET_HOST
 		
 void divert_frame(struct sk_buff *skb)
 {
-	struct ethhdr			*eth = skb->mac.ethernet;
+	struct ethhdr			*eth = eth_hdr(skb);
 	struct iphdr			*iph;
 	struct tcphdr			*tcph;
 	struct udphdr			*udph;
@@ -553,6 +553,3 @@
 		break;
 	}
 }
-
-EXPORT_SYMBOL(alloc_divert_blk);
-EXPORT_SYMBOL(free_divert_blk);
diff -Nru a/net/core/filter.c b/net/core/filter.c
--- a/net/core/filter.c	2004-10-18 14:56:28 -07:00
+++ b/net/core/filter.c	2004-10-18 14:56:28 -07:00
@@ -183,9 +183,10 @@
 					continue;
 				}
 			} else {
-				u32 tmp;
-				if (!skb_copy_bits(skb, k, &tmp, 4)) {
-					A = ntohl(tmp);
+				u32 _tmp, *p;
+				p = skb_header_pointer(skb, k, 4, &_tmp);
+				if (p != NULL) {
+					A = ntohl(*p);
 					continue;
 				}
 			}
@@ -208,9 +209,10 @@
 					continue;
 				}
 			} else {
-				u16 tmp;
-				if (!skb_copy_bits(skb, k, &tmp, 2)) {
-					A = ntohs(tmp);
+				u16 _tmp, *p;
+				p = skb_header_pointer(skb, k, 2, &_tmp);
+				if (p != NULL) {
+					A = ntohs(*p);
 					continue;
 				}
 			}
@@ -233,9 +235,10 @@
 					continue;
 				}
 			} else {
-				u8 tmp;
-				if (!skb_copy_bits(skb, k, &tmp, 1)) {
-					A = tmp;
+				u8 _tmp, *p;
+				p = skb_header_pointer(skb, k, 1, &_tmp);
+				if (p != NULL) {
+					A = *p;
 					continue;
 				}
 			}
diff -Nru a/net/core/gen_estimator.c b/net/core/gen_estimator.c
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/net/core/gen_estimator.c	2004-10-18 14:57:23 -07:00
@@ -0,0 +1,204 @@
+/*
+ * net/sched/gen_estimator.c	Simple rate estimator.
+ *
+ *		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:	Alexey Kuznetsov, <kuznet@ms2.inr.ac.ru>
+ *
+ * Changes:
+ *              Jamal Hadi Salim - moved it to net/core and reshulfed
+ *              names to make it usable in general net subsystem.
+ */
+
+#include <asm/uaccess.h>
+#include <asm/system.h>
+#include <asm/bitops.h>
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/jiffies.h>
+#include <linux/string.h>
+#include <linux/mm.h>
+#include <linux/socket.h>
+#include <linux/sockios.h>
+#include <linux/in.h>
+#include <linux/errno.h>
+#include <linux/interrupt.h>
+#include <linux/netdevice.h>
+#include <linux/skbuff.h>
+#include <linux/rtnetlink.h>
+#include <linux/init.h>
+#include <net/sock.h>
+#include <net/gen_stats.h>
+
+/*
+   This code is NOT intended to be used for statistics collection,
+   its purpose is to provide a base for statistical multiplexing
+   for controlled load service.
+   If you need only statistics, run a user level daemon which
+   periodically reads byte counters.
+
+   Unfortunately, rate estimation is not a very easy task.
+   F.e. I did not find a simple way to estimate the current peak rate
+   and even failed to formulate the problem 8)8)
+
+   So I preferred not to built an estimator into the scheduler,
+   but run this task separately.
+   Ideally, it should be kernel thread(s), but for now it runs
+   from timers, which puts apparent top bounds on the number of rated
+   flows, has minimal overhead on small, but is enough
+   to handle controlled load service, sets of aggregates.
+
+   We measure rate over A=(1<<interval) seconds and evaluate EWMA:
+
+   avrate = avrate*(1-W) + rate*W
+
+   where W is chosen as negative power of 2: W = 2^(-ewma_log)
+
+   The resulting time constant is:
+
+   T = A/(-ln(1-W))
+
+
+   NOTES.
+
+   * The stored value for avbps is scaled by 2^5, so that maximal
+     rate is ~1Gbit, avpps is scaled by 2^10.
+
+   * Minimal interval is HZ/4=250msec (it is the greatest common divisor
+     for HZ=100 and HZ=1024 8)), maximal interval
+     is (HZ*2^EST_MAX_INTERVAL)/4 = 8sec. Shorter intervals
+     are too expensive, longer ones can be implemented
+     at user level painlessly.
+ */
+
+#define EST_MAX_INTERVAL	5
+
+struct gen_estimator
+{
+	struct gen_estimator	*next;
+	struct gnet_stats_basic	*bstats;
+	struct gnet_stats_rate_est	*rate_est;
+	spinlock_t		*stats_lock;
+	unsigned		interval;
+	int			ewma_log;
+	u64			last_bytes;
+	u32			last_packets;
+	u32			avpps;
+	u32			avbps;
+};
+
+struct gen_estimator_head
+{
+	struct timer_list	timer;
+	struct gen_estimator	*list;
+};
+
+static struct gen_estimator_head elist[EST_MAX_INTERVAL+1];
+
+/* Estimator array lock */
+static rwlock_t est_lock = RW_LOCK_UNLOCKED;
+
+static void est_timer(unsigned long arg)
+{
+	int idx = (int)arg;
+	struct gen_estimator *e;
+
+	read_lock(&est_lock);
+	for (e = elist[idx].list; e; e = e->next) {
+		u64 nbytes;
+		u32 npackets;
+		u32 rate;
+
+		spin_lock(e->stats_lock);
+		nbytes = e->bstats->bytes;
+		npackets = e->bstats->packets;
+		rate = (nbytes - e->last_bytes)<<(7 - idx);
+		e->last_bytes = nbytes;
+		e->avbps += ((long)rate - (long)e->avbps) >> e->ewma_log;
+		e->rate_est->bps = (e->avbps+0xF)>>5;
+
+		rate = (npackets - e->last_packets)<<(12 - idx);
+		e->last_packets = npackets;
+		e->avpps += ((long)rate - (long)e->avpps) >> e->ewma_log;
+		e->rate_est->pps = (e->avpps+0x1FF)>>10;
+		spin_unlock(e->stats_lock);
+	}
+
+	mod_timer(&elist[idx].timer, jiffies + ((HZ<<idx)/4));
+	read_unlock(&est_lock);
+}
+
+int gen_new_estimator(struct gnet_stats_basic *bstats,
+	struct gnet_stats_rate_est *rate_est, spinlock_t *stats_lock, struct rtattr *opt)
+{
+	struct gen_estimator *est;
+	struct gnet_estimator *parm = RTA_DATA(opt);
+
+	if (RTA_PAYLOAD(opt) < sizeof(*parm))
+		return -EINVAL;
+
+	if (parm->interval < -2 || parm->interval > 3)
+		return -EINVAL;
+
+	est = kmalloc(sizeof(*est), GFP_KERNEL);
+	if (est == NULL)
+		return -ENOBUFS;
+
+	memset(est, 0, sizeof(*est));
+	est->interval = parm->interval + 2;
+	est->bstats = bstats;
+	est->rate_est = rate_est;
+	est->stats_lock = stats_lock;
+	est->ewma_log = parm->ewma_log;
+	est->last_bytes = bstats->bytes;
+	est->avbps = rate_est->bps<<5;
+	est->last_packets = bstats->packets;
+	est->avpps = rate_est->pps<<10;
+
+	est->next = elist[est->interval].list;
+	if (est->next == NULL) {
+		init_timer(&elist[est->interval].timer);
+		elist[est->interval].timer.data = est->interval;
+		elist[est->interval].timer.expires = jiffies + ((HZ<<est->interval)/4);
+		elist[est->interval].timer.function = est_timer;
+		add_timer(&elist[est->interval].timer);
+	}
+	write_lock_bh(&est_lock);
+	elist[est->interval].list = est;
+	write_unlock_bh(&est_lock);
+	return 0;
+}
+
+void gen_kill_estimator(struct gnet_stats_basic *bstats,
+	struct gnet_stats_rate_est *rate_est)
+{
+	int idx;
+	struct gen_estimator *est, **pest;
+
+	for (idx=0; idx <= EST_MAX_INTERVAL; idx++) {
+		int killed = 0;
+		pest = &elist[idx].list;
+		while ((est=*pest) != NULL) {
+			if (est->rate_est != rate_est || est->bstats != bstats) {
+				pest = &est->next;
+				continue;
+			}
+
+			write_lock_bh(&est_lock);
+			*pest = est->next;
+			write_unlock_bh(&est_lock);
+
+			kfree(est);
+			killed++;
+		}
+		if (killed && elist[idx].list == NULL)
+			del_timer(&elist[idx].timer);
+	}
+}
+
+EXPORT_SYMBOL(gen_kill_estimator);
+EXPORT_SYMBOL(gen_new_estimator);
diff -Nru a/net/core/gen_stats.c b/net/core/gen_stats.c
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/net/core/gen_stats.c	2004-10-18 14:57:24 -07:00
@@ -0,0 +1,132 @@
+/*
+ * net/core/gen_stats.c
+ *
+ *             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:  Thomas Graf <tgraf@suug.ch>
+ *           Jamal Hadi Salim
+ *           Alexey Kuznetsov, <kuznet@ms2.inr.ac.ru>
+ *
+ * See Documentation/networking/gen_stats.txt
+ */
+
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/interrupt.h>
+#include <linux/socket.h>
+#include <linux/rtnetlink.h>
+#include <linux/gen_stats.h>
+#include <net/gen_stats.h>
+
+
+static inline int
+gnet_stats_copy(struct gnet_dump *d, int type, void *buf, int size)
+{
+	RTA_PUT(d->skb, type, size, buf);
+	return 0;
+
+rtattr_failure:
+	spin_unlock_bh(d->lock);
+	return -1;
+}
+
+int
+gnet_stats_start_copy_compat(struct sk_buff *skb, int type, int tc_stats_type,
+	int xstats_type, spinlock_t *lock, struct gnet_dump *d)
+{
+	spin_lock_bh(lock);
+	d->lock = lock;
+	d->tail = (struct rtattr *) skb->tail;
+	d->skb = skb;
+	d->compat_tc_stats = tc_stats_type;
+	d->compat_xstats = xstats_type;
+	d->xstats = NULL;
+
+	if (d->compat_tc_stats)
+		memset(&d->tc_stats, 0, sizeof(d->tc_stats));
+
+	return gnet_stats_copy(d, type, NULL, 0);
+}
+
+int
+gnet_stats_start_copy(struct sk_buff *skb, int type, spinlock_t *lock,
+	struct gnet_dump *d)
+{
+	return gnet_stats_start_copy_compat(skb, type, 0, 0, lock, d);
+}
+
+
+int
+gnet_stats_copy_basic(struct gnet_dump *d, struct gnet_stats_basic *b)
+{
+	if (d->compat_tc_stats) {
+		d->tc_stats.bytes = b->bytes;
+		d->tc_stats.packets = b->packets;
+	}
+	
+	return gnet_stats_copy(d, TCA_STATS_BASIC, b, sizeof(*b));
+}
+
+int
+gnet_stats_copy_rate_est(struct gnet_dump *d, struct gnet_stats_rate_est *r)
+{
+	if (d->compat_tc_stats) {
+		d->tc_stats.bps = r->bps;
+		d->tc_stats.pps = r->pps;
+	}
+
+	return gnet_stats_copy(d, TCA_STATS_RATE_EST, r, sizeof(*r));
+}
+
+int
+gnet_stats_copy_queue(struct gnet_dump *d, struct gnet_stats_queue *q)
+{
+	if (d->compat_tc_stats) {
+		d->tc_stats.drops = q->drops;
+		d->tc_stats.qlen = q->qlen;
+		d->tc_stats.backlog = q->backlog;
+		d->tc_stats.overlimits = q->overlimits;
+	}
+		
+	return gnet_stats_copy(d, TCA_STATS_QUEUE, q, sizeof(*q));
+}
+
+int
+gnet_stats_copy_app(struct gnet_dump *d, void *st, int len)
+{
+	if (d->compat_xstats)
+		d->xstats = (struct rtattr *) d->skb->tail;
+	return gnet_stats_copy(d, TCA_STATS_APP, st, len);
+}
+
+int
+gnet_stats_finish_copy(struct gnet_dump *d)
+{
+	d->tail->rta_len = d->skb->tail - (u8 *) d->tail;
+
+	if (d->compat_tc_stats)
+		if (gnet_stats_copy(d, d->compat_tc_stats, &d->tc_stats,
+			sizeof(d->tc_stats)) < 0)
+			return -1;
+
+	if (d->compat_xstats && d->xstats) {
+		if (gnet_stats_copy(d, d->compat_xstats, RTA_DATA(d->xstats),
+			RTA_PAYLOAD(d->xstats)) < 0)
+			return -1;
+	}
+
+	spin_unlock_bh(d->lock);
+	return 0;
+}
+
+
+EXPORT_SYMBOL(gnet_stats_start_copy);
+EXPORT_SYMBOL(gnet_stats_copy_basic);
+EXPORT_SYMBOL(gnet_stats_copy_rate_est);
+EXPORT_SYMBOL(gnet_stats_copy_queue);
+EXPORT_SYMBOL(gnet_stats_copy_app);
+EXPORT_SYMBOL(gnet_stats_finish_copy);
diff -Nru a/net/core/neighbour.c b/net/core/neighbour.c
--- a/net/core/neighbour.c	2004-10-18 14:55:54 -07:00
+++ b/net/core/neighbour.c	2004-10-18 14:55:54 -07:00
@@ -12,6 +12,7 @@
  *
  *	Fixes:
  *	Vitaly E. Lavrov	releasing NULL neighbor in neigh_add.
+ *	Harald Welte		Add neighbour cache statistics like rtstat
  */
 
 #include <linux/config.h>
@@ -21,6 +22,7 @@
 #include <linux/socket.h>
 #include <linux/sched.h>
 #include <linux/netdevice.h>
+#include <linux/proc_fs.h>
 #ifdef CONFIG_SYSCTL
 #include <linux/sysctl.h>
 #endif
@@ -29,6 +31,7 @@
 #include <net/dst.h>
 #include <net/sock.h>
 #include <linux/rtnetlink.h>
+#include <linux/random.h>
 
 #define NEIGH_DEBUG 1
 
@@ -47,6 +50,8 @@
 #define NEIGH_PRINTK2 NEIGH_PRINTK
 #endif
 
+#define PNEIGH_HASHMASK		0xF
+
 static void neigh_timer_handler(unsigned long arg);
 #ifdef CONFIG_ARPD
 static void neigh_app_notify(struct neighbour *n);
@@ -56,6 +61,7 @@
 
 static int neigh_glbl_allocs;
 static struct neigh_table *neigh_tables;
+static struct file_operations neigh_stat_seq_fops;
 
 /*
    Neighbour hash table buckets are protected with rwlock tbl->lock.
@@ -113,27 +119,21 @@
 	int shrunk = 0;
 	int i;
 
-	for (i = 0; i <= NEIGH_HASHMASK; i++) {
+	NEIGH_CACHE_STAT_INC(tbl, forced_gc_runs);
+
+	write_lock_bh(&tbl->lock);
+	for (i = 0; i <= tbl->hash_mask; i++) {
 		struct neighbour *n, **np;
 
 		np = &tbl->hash_buckets[i];
-		write_lock_bh(&tbl->lock);
 		while ((n = *np) != NULL) {
 			/* Neighbour record may be discarded if:
-			   - nobody refers to it.
-			   - it is not permanent
-			   - (NEW and probably wrong)
-			     INCOMPLETE entries are kept at least for
-			     n->parms->retrans_time, otherwise we could
-			     flood network with resolution requests.
-			     It is not clear, what is better table overflow
-			     or flooding.
+			 * - nobody refers to it.
+			 * - it is not permanent
 			 */
 			write_lock(&n->lock);
 			if (atomic_read(&n->refcnt) == 1 &&
-			    !(n->nud_state & NUD_PERMANENT) &&
-			    (n->nud_state != NUD_INCOMPLETE ||
-			     jiffies - n->used > n->parms->retrans_time)) {
+			    !(n->nud_state & NUD_PERMANENT)) {
 				*np	= n->next;
 				n->dead = 1;
 				shrunk	= 1;
@@ -144,10 +144,12 @@
 			write_unlock(&n->lock);
 			np = &n->next;
 		}
-		write_unlock_bh(&tbl->lock);
 	}
 
 	tbl->last_flush = jiffies;
+
+	write_unlock_bh(&tbl->lock);
+
 	return shrunk;
 }
 
@@ -177,7 +179,7 @@
 
 	write_lock_bh(&tbl->lock);
 
-	for (i=0; i <= NEIGH_HASHMASK; i++) {
+	for (i=0; i <= tbl->hash_mask; i++) {
 		struct neighbour *n, **np;
 
 		np = &tbl->hash_buckets[i];
@@ -204,7 +206,7 @@
 
 	write_lock_bh(&tbl->lock);
 
-	for (i = 0; i <= NEIGH_HASHMASK; i++) {
+	for (i = 0; i <= tbl->hash_mask; i++) {
 		struct neighbour *n, **np = &tbl->hash_buckets[i];
 
 		while ((n = *np) != NULL) {
@@ -227,7 +229,6 @@
 				   we must kill timers etc. and move
 				   it to safe state.
 				 */
-				n->parms = &tbl->parms;
 				skb_queue_purge(&n->arp_queue);
 				n->output = neigh_blackhole;
 				if (n->nud_state & NUD_VALID)
@@ -256,7 +257,7 @@
 
 	if (tbl->entries > tbl->gc_thresh3 ||
 	    (tbl->entries > tbl->gc_thresh2 &&
-	     now - tbl->last_flush > 5 * HZ)) {
+	     time_after(now, tbl->last_flush + 5 * HZ))) {
 		if (!neigh_forced_gc(tbl) &&
 		    tbl->entries > tbl->gc_thresh3)
 			goto out;
@@ -273,11 +274,12 @@
 	n->updated	  = n->used = now;
 	n->nud_state	  = NUD_NONE;
 	n->output	  = neigh_blackhole;
-	n->parms	  = &tbl->parms;
+	n->parms	  = neigh_parms_clone(&tbl->parms);
 	init_timer(&n->timer);
 	n->timer.function = neigh_timer_handler;
 	n->timer.data	  = (unsigned long)n;
-	tbl->stats.allocs++;
+
+	NEIGH_CACHE_STAT_INC(tbl, allocs);
 	neigh_glbl_allocs++;
 	tbl->entries++;
 	n->tbl		  = tbl;
@@ -287,17 +289,103 @@
 	return n;
 }
 
+static struct neighbour **neigh_hash_alloc(unsigned int entries)
+{
+	unsigned long size = entries * sizeof(struct neighbour *);
+	struct neighbour **ret;
+
+	if (size <= PAGE_SIZE) {
+		ret = kmalloc(size, GFP_ATOMIC);
+	} else {
+		ret = (struct neighbour **)
+			__get_free_pages(GFP_ATOMIC, get_order(size));
+	}
+	if (ret)
+		memset(ret, 0, size);
+
+	return ret;
+}
+
+static void neigh_hash_free(struct neighbour **hash, unsigned int entries)
+{
+	unsigned long size = entries * sizeof(struct neighbour *);
+
+	if (size <= PAGE_SIZE)
+		kfree(hash);
+	else
+		free_pages((unsigned long)hash, get_order(size));
+}
+
+static void neigh_hash_grow(struct neigh_table *tbl, unsigned long new_entries)
+{
+	struct neighbour **new_hash, **old_hash;
+	unsigned int i, new_hash_mask, old_entries;
+
+	NEIGH_CACHE_STAT_INC(tbl, hash_grows);
+
+	BUG_ON(new_entries & (new_entries - 1));
+	new_hash = neigh_hash_alloc(new_entries);
+	if (!new_hash)
+		return;
+
+	old_entries = tbl->hash_mask + 1;
+	new_hash_mask = new_entries - 1;
+	old_hash = tbl->hash_buckets;
+
+	get_random_bytes(&tbl->hash_rnd, sizeof(tbl->hash_rnd));
+	for (i = 0; i < old_entries; i++) {
+		struct neighbour *n, *next;
+
+		for (n = old_hash[i]; n; n = next) {
+			unsigned int hash_val = tbl->hash(n->primary_key, n->dev);
+
+			hash_val &= new_hash_mask;
+			next = n->next;
+
+			n->next = new_hash[hash_val];
+			new_hash[hash_val] = n;
+		}
+	}
+	tbl->hash_buckets = new_hash;
+	tbl->hash_mask = new_hash_mask;
+
+	neigh_hash_free(old_hash, old_entries);
+}
+
 struct neighbour *neigh_lookup(struct neigh_table *tbl, const void *pkey,
 			       struct net_device *dev)
 {
 	struct neighbour *n;
 	int key_len = tbl->key_len;
-	u32 hash_val = tbl->hash(pkey, dev);
+	u32 hash_val = tbl->hash(pkey, dev) & tbl->hash_mask;
+	
+	NEIGH_CACHE_STAT_INC(tbl, lookups);
 
 	read_lock_bh(&tbl->lock);
 	for (n = tbl->hash_buckets[hash_val]; n; n = n->next) {
 		if (dev == n->dev && !memcmp(n->primary_key, pkey, key_len)) {
 			neigh_hold(n);
+			NEIGH_CACHE_STAT_INC(tbl, hits);
+			break;
+		}
+	}
+	read_unlock_bh(&tbl->lock);
+	return n;
+}
+
+struct neighbour *neigh_lookup_nodev(struct neigh_table *tbl, const void *pkey)
+{
+	struct neighbour *n;
+	int key_len = tbl->key_len;
+	u32 hash_val = tbl->hash(pkey, NULL) & tbl->hash_mask;
+
+	NEIGH_CACHE_STAT_INC(tbl, lookups);
+
+	read_lock_bh(&tbl->lock);
+	for (n = tbl->hash_buckets[hash_val]; n; n = n->next) {
+		if (!memcmp(n->primary_key, pkey, key_len)) {
+			neigh_hold(n);
+			NEIGH_CACHE_STAT_INC(tbl, hits);
 			break;
 		}
 	}
@@ -337,15 +425,23 @@
 
 	n->confirmed = jiffies - (n->parms->base_reachable_time << 1);
 
-	hash_val = tbl->hash(pkey, dev);
-
 	write_lock_bh(&tbl->lock);
+
+	if (tbl->entries > (tbl->hash_mask + 1))
+		neigh_hash_grow(tbl, (tbl->hash_mask + 1) << 1);
+
+	hash_val = tbl->hash(pkey, dev) & tbl->hash_mask;
+
+	if (n->parms->dead) {
+		rc = ERR_PTR(-EINVAL);
+		goto out_tbl_unlock;
+	}
+
 	for (n1 = tbl->hash_buckets[hash_val]; n1; n1 = n1->next) {
 		if (dev == n1->dev && !memcmp(n1->primary_key, pkey, key_len)) {
 			neigh_hold(n1);
-			write_unlock_bh(&tbl->lock);
 			rc = n1;
-			goto out_neigh_release;
+			goto out_tbl_unlock;
 		}
 	}
 
@@ -358,6 +454,8 @@
 	rc = n;
 out:
 	return rc;
+out_tbl_unlock:
+	write_unlock_bh(&tbl->lock);
 out_neigh_release:
 	neigh_release(n);
 	goto out;
@@ -395,8 +493,12 @@
 
 	memcpy(n->key, pkey, key_len);
 	n->dev = dev;
+	if (dev)
+		dev_hold(dev);
 
 	if (tbl->pconstructor && tbl->pconstructor(n)) {
+		if (dev)
+			dev_put(dev);
 		kfree(n);
 		n = NULL;
 		goto out;
@@ -423,18 +525,21 @@
 	hash_val ^= hash_val >> 4;
 	hash_val &= PNEIGH_HASHMASK;
 
+	write_lock_bh(&tbl->lock);
 	for (np = &tbl->phash_buckets[hash_val]; (n = *np) != NULL;
 	     np = &n->next) {
 		if (!memcmp(n->key, pkey, key_len) && n->dev == dev) {
-			write_lock_bh(&tbl->lock);
 			*np = n->next;
 			write_unlock_bh(&tbl->lock);
 			if (tbl->pdestructor)
 				tbl->pdestructor(n);
+			if (n->dev)
+				dev_put(n->dev);
 			kfree(n);
 			return 0;
 		}
 	}
+	write_unlock_bh(&tbl->lock);
 	return -ENOENT;
 }
 
@@ -450,6 +555,8 @@
 				*np = n->next;
 				if (tbl->pdestructor)
 					tbl->pdestructor(n);
+				if (n->dev)
+					dev_put(n->dev);
 				kfree(n);
 				continue;
 			}
@@ -468,6 +575,8 @@
 {
 	struct hh_cache *hh;
 
+	NEIGH_CACHE_STAT_INC(neigh->tbl, destroys);
+
 	if (!neigh->dead) {
 		printk(KERN_WARNING
 		       "Destroying alive neighbour %p\n", neigh);
@@ -494,6 +603,7 @@
 	skb_queue_purge(&neigh->arp_queue);
 
 	dev_put(neigh->dev);
+	neigh_parms_put(neigh->parms);
 
 	NEIGH_PRINTK2("neigh %p is destroyed.\n", neigh);
 
@@ -536,46 +646,13 @@
 		hh->hh_output = neigh->ops->hh_output;
 }
 
-/*
-   Transitions NUD_STALE <-> NUD_REACHABLE do not occur
-   when fast path is built: we have no timers associated with
-   these states, we do not have time to check state when sending.
-   neigh_periodic_timer check periodically neigh->confirmed
-   time and moves NUD_REACHABLE -> NUD_STALE.
-
-   If a routine wants to know TRUE entry state, it calls
-   neigh_sync before checking state.
-
-   Called with write_locked neigh.
- */
-
-static void neigh_sync(struct neighbour *n)
-{
-	unsigned long now = jiffies;
-	u8 state = n->nud_state;
-
-	if (state & (NUD_NOARP | NUD_PERMANENT))
-		return;
-	if (state & NUD_REACHABLE) {
-		if (now - n->confirmed > n->parms->reachable_time) {
-			n->nud_state = NUD_STALE;
-			neigh_suspect(n);
-		}
-	} else if (state & NUD_VALID) {
-		if (now - n->confirmed < n->parms->reachable_time) {
-			neigh_del_timer(n);
-			n->nud_state = NUD_REACHABLE;
-			neigh_connect(n);
-		}
-	}
-}
-
 static void neigh_periodic_timer(unsigned long arg)
 {
 	struct neigh_table *tbl = (struct neigh_table *)arg;
-	unsigned long now = jiffies;
-	int i;
+	struct neighbour *n, **np;
+	unsigned long expire, now = jiffies;
 
+	NEIGH_CACHE_STAT_INC(tbl, periodic_gc_runs);
 
 	write_lock(&tbl->lock);
 
@@ -583,7 +660,7 @@
 	 *	periodically recompute ReachableTime from random function
 	 */
 
-	if (now - tbl->last_rand > 300 * HZ) {
+	if (time_after(now, tbl->last_rand + 300 * HZ)) {
 		struct neigh_parms *p;
 		tbl->last_rand = now;
 		for (p = &tbl->parms; p; p = p->next)
@@ -591,47 +668,49 @@
 				neigh_rand_reach_time(p->base_reachable_time);
 	}
 
-	for (i = 0; i <= NEIGH_HASHMASK; i++) {
-		struct neighbour *n, **np;
+	np = &tbl->hash_buckets[tbl->hash_chain_gc];
+	tbl->hash_chain_gc = ((tbl->hash_chain_gc + 1) & tbl->hash_mask);
 
-		np = &tbl->hash_buckets[i];
-		while ((n = *np) != NULL) {
-			unsigned state;
+	while ((n = *np) != NULL) {
+		unsigned int state;
 
-			write_lock(&n->lock);
+		write_lock(&n->lock);
 
-			state = n->nud_state;
-			if (state & (NUD_PERMANENT | NUD_IN_TIMER)) {
-				write_unlock(&n->lock);
-				goto next_elt;
-			}
+		state = n->nud_state;
+		if (state & (NUD_PERMANENT | NUD_IN_TIMER)) {
+			write_unlock(&n->lock);
+			goto next_elt;
+		}
 
-			if ((long)(n->used - n->confirmed) < 0)
-				n->used = n->confirmed;
+		if (time_before(n->used, n->confirmed))
+			n->used = n->confirmed;
 
-			if (atomic_read(&n->refcnt) == 1 &&
-			    (state == NUD_FAILED ||
-			     now - n->used > n->parms->gc_staletime)) {
-				*np = n->next;
-				n->dead = 1;
-				write_unlock(&n->lock);
-				neigh_release(n);
-				continue;
-			}
-
-			if (n->nud_state & NUD_REACHABLE &&
-			    now - n->confirmed > n->parms->reachable_time) {
-				n->nud_state = NUD_STALE;
-				neigh_suspect(n);
-			}
+		if (atomic_read(&n->refcnt) == 1 &&
+		    (state == NUD_FAILED ||
+		     time_after(now, n->used + n->parms->gc_staletime))) {
+			*np = n->next;
+			n->dead = 1;
 			write_unlock(&n->lock);
+			neigh_release(n);
+			continue;
+		}
+		write_unlock(&n->lock);
 
 next_elt:
-			np = &n->next;
-		}
+		np = &n->next;
 	}
 
-	mod_timer(&tbl->gc_timer, now + tbl->gc_interval);
+ 	/* Cycle through all hash buckets every base_reachable_time/2 ticks.
+ 	 * ARP entry timeouts range from 1/2 base_reachable_time to 3/2
+ 	 * base_reachable_time.
+	 */
+	expire = tbl->parms.base_reachable_time >> 1;
+	expire /= (tbl->hash_mask + 1);
+	if (!expire)
+		expire = 1;
+
+ 	mod_timer(&tbl->gc_timer, now + expire);
+
 	write_unlock(&tbl->lock);
 }
 
@@ -648,7 +727,7 @@
 
 static void neigh_timer_handler(unsigned long arg)
 {
-	unsigned long now = jiffies;
+	unsigned long now, next;
 	struct neighbour *neigh = (struct neighbour *)arg;
 	unsigned state;
 	int notify = 0;
@@ -656,6 +735,8 @@
 	write_lock(&neigh->lock);
 
 	state = neigh->nud_state;
+	now = jiffies;
+	next = now + HZ;
 
 	if (!(state & NUD_IN_TIMER)) {
 #ifndef CONFIG_SMP
@@ -664,25 +745,47 @@
 		goto out;
 	}
 
-	if ((state & NUD_VALID) &&
-	    now - neigh->confirmed < neigh->parms->reachable_time) {
-		neigh->nud_state = NUD_REACHABLE;
-		NEIGH_PRINTK2("neigh %p is still alive.\n", neigh);
-		neigh_connect(neigh);
-		goto out;
-	}
-	if (state == NUD_DELAY) {
-		NEIGH_PRINTK2("neigh %p is probed.\n", neigh);
-		neigh->nud_state = NUD_PROBE;
-		atomic_set(&neigh->probes, 0);
+	if (state & NUD_REACHABLE) {
+		if (time_before_eq(now, 
+				   neigh->confirmed + neigh->parms->reachable_time)) {
+			NEIGH_PRINTK2("neigh %p is still alive.\n", neigh);
+			next = neigh->confirmed + neigh->parms->reachable_time;
+		} else if (time_before_eq(now,
+					  neigh->used + neigh->parms->delay_probe_time)) {
+			NEIGH_PRINTK2("neigh %p is delayed.\n", neigh);
+			neigh->nud_state = NUD_DELAY;
+			neigh_suspect(neigh);
+			next = now + neigh->parms->delay_probe_time;
+		} else {
+			NEIGH_PRINTK2("neigh %p is suspected.\n", neigh);
+			neigh->nud_state = NUD_STALE;
+			neigh_suspect(neigh);
+		}
+	} else if (state & NUD_DELAY) {
+		if (time_before_eq(now, 
+				   neigh->confirmed + neigh->parms->delay_probe_time)) {
+			NEIGH_PRINTK2("neigh %p is now reachable.\n", neigh);
+			neigh->nud_state = NUD_REACHABLE;
+			neigh_connect(neigh);
+			next = neigh->confirmed + neigh->parms->reachable_time;
+		} else {
+			NEIGH_PRINTK2("neigh %p is probed.\n", neigh);
+			neigh->nud_state = NUD_PROBE;
+			atomic_set(&neigh->probes, 0);
+			next = now + neigh->parms->retrans_time;
+		}
+	} else {
+		/* NUD_PROBE|NUD_INCOMPLETE */
+		next = now + neigh->parms->retrans_time;
 	}
 
-	if (atomic_read(&neigh->probes) >= neigh_max_probes(neigh)) {
+	if ((neigh->nud_state & (NUD_INCOMPLETE | NUD_PROBE)) &&
+	    atomic_read(&neigh->probes) >= neigh_max_probes(neigh)) {
 		struct sk_buff *skb;
 
 		neigh->nud_state = NUD_FAILED;
 		notify = 1;
-		neigh->tbl->stats.res_failed++;
+		NEIGH_CACHE_STAT_INC(neigh->tbl, res_failed);
 		NEIGH_PRINTK2("neigh %p is failed.\n", neigh);
 
 		/* It is very thin place. report_unreachable is very complicated
@@ -697,19 +800,30 @@
 			write_lock(&neigh->lock);
 		}
 		skb_queue_purge(&neigh->arp_queue);
-		goto out;
 	}
 
-	neigh->timer.expires = now + neigh->parms->retrans_time;
-	add_timer(&neigh->timer);
-	write_unlock(&neigh->lock);
-
-	neigh->ops->solicit(neigh, skb_peek(&neigh->arp_queue));
-	atomic_inc(&neigh->probes);
-	return;
-
+	if (neigh->nud_state & NUD_IN_TIMER) {
+		neigh_hold(neigh);
+		if (time_before(next, jiffies + HZ/2))
+			next = jiffies + HZ/2;
+		neigh->timer.expires = next;
+		add_timer(&neigh->timer);
+	}
+	if (neigh->nud_state & (NUD_INCOMPLETE | NUD_PROBE)) {
+		struct sk_buff *skb = skb_peek(&neigh->arp_queue);
+		/* keep skb alive even if arp_queue overflows */
+		if (skb)
+			skb_get(skb);
+		write_unlock(&neigh->lock);
+		neigh->ops->solicit(neigh, skb);
+		atomic_inc(&neigh->probes);
+		if (skb)
+			kfree_skb(skb);
+	} else {
 out:
-	write_unlock(&neigh->lock);
+		write_unlock(&neigh->lock);
+	}
+
 #ifdef CONFIG_ARPD
 	if (notify && neigh->parms->app_probes)
 		neigh_app_notify(neigh);
@@ -720,6 +834,7 @@
 int __neigh_event_send(struct neighbour *neigh, struct sk_buff *skb)
 {
 	int rc;
+	unsigned long now;
 
 	write_lock_bh(&neigh->lock);
 
@@ -727,18 +842,15 @@
 	if (neigh->nud_state & (NUD_CONNECTED | NUD_DELAY | NUD_PROBE))
 		goto out_unlock_bh;
 
+	now = jiffies;
+	
 	if (!(neigh->nud_state & (NUD_STALE | NUD_INCOMPLETE))) {
 		if (neigh->parms->mcast_probes + neigh->parms->app_probes) {
 			atomic_set(&neigh->probes, neigh->parms->ucast_probes);
 			neigh->nud_state     = NUD_INCOMPLETE;
 			neigh_hold(neigh);
-			neigh->timer.expires = jiffies +
-					       neigh->parms->retrans_time;
+			neigh->timer.expires = now + 1;
 			add_timer(&neigh->timer);
-			write_unlock_bh(&neigh->lock);
-			neigh->ops->solicit(neigh, skb);
-			atomic_inc(&neigh->probes);
-			write_lock_bh(&neigh->lock);
 		} else {
 			neigh->nud_state = NUD_FAILED;
 			write_unlock_bh(&neigh->lock);
@@ -747,6 +859,12 @@
 				kfree_skb(skb);
 			return 1;
 		}
+	} else if (neigh->nud_state & NUD_STALE) {
+		NEIGH_PRINTK2("neigh %p is delayed.\n", neigh);
+		neigh_hold(neigh);
+		neigh->nud_state = NUD_DELAY;
+		neigh->timer.expires = jiffies + neigh->parms->delay_probe_time;
+		add_timer(&neigh->timer);
 	}
 
 	if (neigh->nud_state == NUD_INCOMPLETE) {
@@ -761,13 +879,6 @@
 			__skb_queue_tail(&neigh->arp_queue, skb);
 		}
 		rc = 1;
-	} else if (neigh->nud_state == NUD_STALE) {
-		NEIGH_PRINTK2("neigh %p is delayed.\n", neigh);
-		neigh_hold(neigh);
-		neigh->nud_state = NUD_DELAY;
-		neigh->timer.expires = jiffies + neigh->parms->delay_probe_time;
-		add_timer(&neigh->timer);
-		rc = 0;
 	}
 out_unlock_bh:
 	write_unlock_bh(&neigh->lock);
@@ -794,14 +905,26 @@
 /* Generic update routine.
    -- lladdr is new lladdr or NULL, if it is not supplied.
    -- new    is new state.
-   -- override == 1 allows to override existing lladdr, if it is different.
-   -- arp == 0 means that the change is administrative.
+   -- flags
+	NEIGH_UPDATE_F_OVERRIDE allows to override existing lladdr,
+				if it is different.
+	NEIGH_UPDATE_F_WEAK_OVERRIDE will suspect existing "connected"
+				lladdr instead of overriding it 
+				if it is different.
+				It also allows to retain current state
+				if lladdr is unchanged.
+	NEIGH_UPDATE_F_ADMIN	means that the change is administrative.
+
+	NEIGH_UPDATE_F_OVERRIDE_ISROUTER allows to override existing 
+				NTF_ROUTER flag.
+	NEIGH_UPDATE_F_ISROUTER	indicates if the neighbour is known as
+				a router.
 
    Caller MUST hold reference count on the entry.
  */
 
 int neigh_update(struct neighbour *neigh, const u8 *lladdr, u8 new,
-		 int override, int arp)
+		 u32 flags)
 {
 	u8 old;
 	int err;
@@ -809,6 +932,7 @@
 	int notify = 0;
 #endif
 	struct net_device *dev;
+	int update_isrouter = 0;
 
 	write_lock_bh(&neigh->lock);
 
@@ -816,7 +940,8 @@
 	old    = neigh->nud_state;
 	err    = -EPERM;
 
-	if (arp && (old & (NUD_NOARP | NUD_PERMANENT)))
+	if (!(flags & NEIGH_UPDATE_F_ADMIN) && 
+	    (old & (NUD_NOARP | NUD_PERMANENT)))
 		goto out;
 
 	if (!(new & NUD_VALID)) {
@@ -841,12 +966,9 @@
 		   - compare new & old
 		   - if they are different, check override flag
 		 */
-		if (old & NUD_VALID) {
-			if (!memcmp(lladdr, neigh->ha, dev->addr_len))
-				lladdr = neigh->ha;
-			else if (!override)
-				goto out;
-		}
+		if ((old & NUD_VALID) && 
+		    !memcmp(lladdr, neigh->ha, dev->addr_len))
+			lladdr = neigh->ha;
 	} else {
 		/* No address is supplied; if we know something,
 		   use it, otherwise discard the request.
@@ -857,8 +979,6 @@
 		lladdr = neigh->ha;
 	}
 
-	neigh_sync(neigh);
-	old = neigh->nud_state;
 	if (new & NUD_CONNECTED)
 		neigh->confirmed = jiffies;
 	neigh->updated = jiffies;
@@ -867,12 +987,37 @@
 	   do not change entry state, if new one is STALE.
 	 */
 	err = 0;
-	if ((old & NUD_VALID) && lladdr == neigh->ha &&
-	    (new == old || (new == NUD_STALE && (old & NUD_CONNECTED))))
-		goto out;
+	update_isrouter = flags & NEIGH_UPDATE_F_OVERRIDE_ISROUTER;
+	if (old & NUD_VALID) {
+		if (lladdr != neigh->ha && !(flags & NEIGH_UPDATE_F_OVERRIDE)) {
+			update_isrouter = 0;
+			if ((flags & NEIGH_UPDATE_F_WEAK_OVERRIDE) &&
+			    (old & NUD_CONNECTED)) {
+				lladdr = neigh->ha;
+				new = NUD_STALE;
+			} else
+				goto out;
+		} else {
+			if (lladdr == neigh->ha && new == NUD_STALE &&
+			    ((flags & NEIGH_UPDATE_F_WEAK_OVERRIDE) ||
+			     (old & NUD_CONNECTED))
+			    )
+				new = old;
+		}
+	}
+
+	if (new != old) {
+		neigh_del_timer(neigh);
+		if (new & NUD_IN_TIMER) {
+			neigh_hold(neigh);
+			neigh->timer.expires = jiffies + 
+						((new & NUD_REACHABLE) ? 
+						 neigh->parms->reachable_time : 0);
+			add_timer(&neigh->timer);
+		}
+		neigh->nud_state = new;
+	}
 
-	neigh_del_timer(neigh);
-	neigh->nud_state = new;
 	if (lladdr != neigh->ha) {
 		memcpy(&neigh->ha, lladdr, dev->addr_len);
 		neigh_update_hhs(neigh);
@@ -907,6 +1052,11 @@
 		skb_queue_purge(&neigh->arp_queue);
 	}
 out:
+	if (update_isrouter) {
+		neigh->flags = (flags & NEIGH_UPDATE_F_ISROUTER) ?
+			(neigh->flags | NTF_ROUTER) :
+			(neigh->flags & ~NTF_ROUTER);
+	}
 	write_unlock_bh(&neigh->lock);
 #ifdef CONFIG_ARPD
 	if (notify && neigh->parms->app_probes)
@@ -922,7 +1072,8 @@
 	struct neighbour *neigh = __neigh_lookup(tbl, saddr, dev,
 						 lladdr || !dev->addr_len);
 	if (neigh)
-		neigh_update(neigh, lladdr, NUD_STALE, 1, 1);
+		neigh_update(neigh, lladdr, NUD_STALE, 
+			     NEIGH_UPDATE_F_OVERRIDE);
 	return neigh;
 }
 
@@ -1088,26 +1239,25 @@
 		    struct sk_buff *skb)
 {
 	unsigned long now = jiffies;
-	long sched_next = net_random() % p->proxy_delay;
+	unsigned long sched_next = now + (net_random() % p->proxy_delay);
 
 	if (tbl->proxy_queue.qlen > p->proxy_qlen) {
 		kfree_skb(skb);
 		return;
 	}
 	skb->stamp.tv_sec  = LOCALLY_ENQUEUED;
-	skb->stamp.tv_usec = now + sched_next;
+	skb->stamp.tv_usec = sched_next;
 
 	spin_lock(&tbl->proxy_queue.lock);
 	if (del_timer(&tbl->proxy_timer)) {
-		long tval = tbl->proxy_timer.expires - now;
-		if (tval < sched_next)
-			sched_next = tval;
+		if (time_before(tbl->proxy_timer.expires, sched_next))
+			sched_next = tbl->proxy_timer.expires;
 	}
 	dst_release(skb->dst);
 	skb->dst = NULL;
 	dev_hold(skb->dev);
 	__skb_queue_tail(&tbl->proxy_queue, skb);
-	mod_timer(&tbl->proxy_timer, now + sched_next);
+	mod_timer(&tbl->proxy_timer, sched_next);
 	spin_unlock(&tbl->proxy_queue.lock);
 }
 
@@ -1120,6 +1270,8 @@
 	if (p) {
 		memcpy(p, &tbl->parms, sizeof(*p));
 		p->tbl		  = tbl;
+		atomic_set(&p->refcnt, 1);
+		INIT_RCU_HEAD(&p->rcu_head);
 		p->reachable_time =
 				neigh_rand_reach_time(p->base_reachable_time);
 		if (dev && dev->neigh_setup && dev->neigh_setup(dev, p)) {
@@ -1135,6 +1287,14 @@
 	return p;
 }
 
+static void neigh_rcu_free_parms(struct rcu_head *head)
+{
+	struct neigh_parms *parms =
+		container_of(head, struct neigh_parms, rcu_head);
+
+	neigh_parms_put(parms);
+}
+
 void neigh_parms_release(struct neigh_table *tbl, struct neigh_parms *parms)
 {
 	struct neigh_parms **p;
@@ -1145,8 +1305,9 @@
 	for (p = &tbl->parms.next; *p; p = &(*p)->next) {
 		if (*p == parms) {
 			*p = parms->next;
+			parms->dead = 1;
 			write_unlock_bh(&tbl->lock);
-			kfree(parms);
+			call_rcu(&parms->rcu_head, neigh_rcu_free_parms);
 			return;
 		}
 	}
@@ -1154,11 +1315,19 @@
 	NEIGH_PRINTK1("neigh_parms_release: not found\n");
 }
 
+void neigh_parms_destroy(struct neigh_parms *parms)
+{
+	kfree(parms);
+}
+
 
 void neigh_table_init(struct neigh_table *tbl)
 {
 	unsigned long now = jiffies;
+	unsigned long phsize;
 
+	atomic_set(&tbl->parms.refcnt, 1);
+	INIT_RCU_HEAD(&tbl->parms.rcu_head);
 	tbl->parms.reachable_time =
 			  neigh_rand_reach_time(tbl->parms.base_reachable_time);
 
@@ -1171,12 +1340,36 @@
 	if (!tbl->kmem_cachep)
 		panic("cannot create neighbour cache");
 
+	tbl->stats = alloc_percpu(struct neigh_statistics);
+	if (!tbl->stats)
+		panic("cannot create neighbour cache statistics");
+	
+#ifdef CONFIG_PROC_FS
+	tbl->pde = create_proc_entry(tbl->id, 0, proc_net_stat);
+	if (!tbl->pde) 
+		panic("cannot create neighbour proc dir entry");
+	tbl->pde->proc_fops = &neigh_stat_seq_fops;
+	tbl->pde->data = tbl;
+#endif
+
+	tbl->hash_mask = 1;
+	tbl->hash_buckets = neigh_hash_alloc(tbl->hash_mask + 1);
+
+	phsize = (PNEIGH_HASHMASK + 1) * sizeof(struct pneigh_entry *);
+	tbl->phash_buckets = kmalloc(phsize, GFP_KERNEL);
+
+	if (!tbl->hash_buckets || !tbl->phash_buckets)
+		panic("cannot allocate neighbour cache hashes");
+
+	memset(tbl->phash_buckets, 0, phsize);
+
+	get_random_bytes(&tbl->hash_rnd, sizeof(tbl->hash_rnd));
+
 	tbl->lock	       = RW_LOCK_UNLOCKED;
 	init_timer(&tbl->gc_timer);
 	tbl->gc_timer.data     = (unsigned long)tbl;
 	tbl->gc_timer.function = neigh_periodic_timer;
-	tbl->gc_timer.expires  = now + tbl->gc_interval +
-				 tbl->parms.reachable_time;
+	tbl->gc_timer.expires  = now + 1;
 	add_timer(&tbl->gc_timer);
 
 	init_timer(&tbl->proxy_timer);
@@ -1211,6 +1404,13 @@
 		}
 	}
 	write_unlock(&neigh_tbl_lock);
+
+	neigh_hash_free(tbl->hash_buckets, tbl->hash_mask + 1);
+	tbl->hash_buckets = NULL;
+
+	kfree(tbl->phash_buckets);
+	tbl->phash_buckets = NULL;
+
 	return 0;
 }
 
@@ -1250,7 +1450,9 @@
 
 		n = neigh_lookup(tbl, RTA_DATA(nda[NDA_DST - 1]), dev);
 		if (n) {
-			err = neigh_update(n, NULL, NUD_FAILED, 1, 0);
+			err = neigh_update(n, NULL, NUD_FAILED, 
+					   NEIGH_UPDATE_F_OVERRIDE|
+					   NEIGH_UPDATE_F_ADMIN);
 			neigh_release(n);
 		}
 		goto out_dev_put;
@@ -1323,7 +1525,8 @@
 						RTA_DATA(nda[NDA_LLADDR - 1]) :
 						NULL,
 					   ndm->ndm_state,
-					   override, 0);
+					   (override ? NEIGH_UPDATE_F_OVERRIDE : 0) |
+					   NEIGH_UPDATE_F_ADMIN);
 		}
 		if (n)
 			neigh_release(n);
@@ -1387,7 +1590,7 @@
 	int rc, h, s_h = cb->args[1];
 	int idx, s_idx = idx = cb->args[2];
 
-	for (h = 0; h <= NEIGH_HASHMASK; h++) {
+	for (h = 0; h <= tbl->hash_mask; h++) {
 		if (h < s_h)
 			continue;
 		if (h > s_h)
@@ -1437,6 +1640,366 @@
 	return skb->len;
 }
 
+void neigh_for_each(struct neigh_table *tbl, void (*cb)(struct neighbour *, void *), void *cookie)
+{
+	int chain;
+
+	read_lock_bh(&tbl->lock);
+	for (chain = 0; chain <= tbl->hash_mask; chain++) {
+		struct neighbour *n;
+
+		for (n = tbl->hash_buckets[chain]; n; n = n->next)
+			cb(n, cookie);
+	}
+	read_unlock_bh(&tbl->lock);
+}
+EXPORT_SYMBOL(neigh_for_each);
+
+/* The tbl->lock must be held as a writer and BH disabled. */
+void __neigh_for_each_release(struct neigh_table *tbl,
+			      int (*cb)(struct neighbour *))
+{
+	int chain;
+
+	for (chain = 0; chain <= tbl->hash_mask; chain++) {
+		struct neighbour *n, **np;
+
+		np = &tbl->hash_buckets[chain];
+		while ((n = *np) != NULL) {
+			int release;
+
+			write_lock(&n->lock);
+			release = cb(n);
+			if (release) {
+				*np = n->next;
+				n->dead = 1;
+			} else
+				np = &n->next;
+			write_unlock(&n->lock);
+			if (release)
+				neigh_release(n);
+		}
+	}
+}
+EXPORT_SYMBOL(__neigh_for_each_release);
+
+#ifdef CONFIG_PROC_FS
+
+static struct neighbour *neigh_get_first(struct seq_file *seq)
+{
+	struct neigh_seq_state *state = seq->private;
+	struct neigh_table *tbl = state->tbl;
+	struct neighbour *n = NULL;
+	int bucket = state->bucket;
+
+	state->flags &= ~NEIGH_SEQ_IS_PNEIGH;
+	for (bucket = 0; bucket <= tbl->hash_mask; bucket++) {
+		n = tbl->hash_buckets[bucket];
+
+		while (n) {
+			if (state->neigh_sub_iter) {
+				loff_t fakep = 0;
+				void *v;
+
+				v = state->neigh_sub_iter(state, n, &fakep);
+				if (!v)
+					goto next;
+			}
+			if (!(state->flags & NEIGH_SEQ_SKIP_NOARP))
+				break;
+			if (n->nud_state & ~NUD_NOARP)
+				break;
+		next:
+			n = n->next;
+		}
+
+		if (n)
+			break;
+	}
+	state->bucket = bucket;
+
+	return n;
+}
+
+static struct neighbour *neigh_get_next(struct seq_file *seq,
+					struct neighbour *n,
+					loff_t *pos)
+{
+	struct neigh_seq_state *state = seq->private;
+	struct neigh_table *tbl = state->tbl;
+
+	if (state->neigh_sub_iter) {
+		void *v = state->neigh_sub_iter(state, n, pos);
+		if (v)
+			return n;
+	}
+	n = n->next;
+
+	while (1) {
+		while (n) {
+			if (state->neigh_sub_iter) {
+				void *v = state->neigh_sub_iter(state, n, pos);
+				if (v)
+					return n;
+				goto next;
+			}
+			if (!(state->flags & NEIGH_SEQ_SKIP_NOARP))
+				break;
+
+			if (n->nud_state & ~NUD_NOARP)
+				break;
+		next:
+			n = n->next;
+		}
+
+		if (n)
+			break;
+
+		if (++state->bucket > tbl->hash_mask)
+			break;
+
+		n = tbl->hash_buckets[state->bucket];
+	}
+
+	if (n && pos)
+		--(*pos);
+	return n;
+}
+
+static struct neighbour *neigh_get_idx(struct seq_file *seq, loff_t *pos)
+{
+	struct neighbour *n = neigh_get_first(seq);
+
+	if (n) {
+		while (*pos) {
+			n = neigh_get_next(seq, n, pos);
+			if (!n)
+				break;
+		}
+	}
+	return *pos ? NULL : n;
+}
+
+static struct pneigh_entry *pneigh_get_first(struct seq_file *seq)
+{
+	struct neigh_seq_state *state = seq->private;
+	struct neigh_table *tbl = state->tbl;
+	struct pneigh_entry *pn = NULL;
+	int bucket = state->bucket;
+
+	state->flags |= NEIGH_SEQ_IS_PNEIGH;
+	for (bucket = 0; bucket <= PNEIGH_HASHMASK; bucket++) {
+		pn = tbl->phash_buckets[bucket];
+		if (pn)
+			break;
+	}
+	state->bucket = bucket;
+
+	return pn;
+}
+
+static struct pneigh_entry *pneigh_get_next(struct seq_file *seq,
+					    struct pneigh_entry *pn,
+					    loff_t *pos)
+{
+	struct neigh_seq_state *state = seq->private;
+	struct neigh_table *tbl = state->tbl;
+
+	pn = pn->next;
+	while (!pn) {
+		if (++state->bucket > PNEIGH_HASHMASK)
+			break;
+		pn = tbl->phash_buckets[state->bucket];
+		if (pn)
+			break;
+	}
+
+	if (pn && pos)
+		--(*pos);
+
+	return pn;
+}
+
+static struct pneigh_entry *pneigh_get_idx(struct seq_file *seq, loff_t *pos)
+{
+	struct pneigh_entry *pn = pneigh_get_first(seq);
+
+	if (pn) {
+		while (*pos) {
+			pn = pneigh_get_next(seq, pn, pos);
+			if (!pn)
+				break;
+		}
+	}
+	return *pos ? NULL : pn;
+}
+
+static void *neigh_get_idx_any(struct seq_file *seq, loff_t *pos)
+{
+	struct neigh_seq_state *state = seq->private;
+	void *rc;
+
+	rc = neigh_get_idx(seq, pos);
+	if (!rc && !(state->flags & NEIGH_SEQ_NEIGH_ONLY))
+		rc = pneigh_get_idx(seq, pos);
+
+	return rc;
+}
+
+void *neigh_seq_start(struct seq_file *seq, loff_t *pos, struct neigh_table *tbl, unsigned int neigh_seq_flags)
+{
+	struct neigh_seq_state *state = seq->private;
+	loff_t pos_minus_one;
+
+	state->tbl = tbl;
+	state->bucket = 0;
+	state->flags = (neigh_seq_flags & ~NEIGH_SEQ_IS_PNEIGH);
+
+	read_lock_bh(&tbl->lock);
+
+	pos_minus_one = *pos - 1;
+	return *pos ? neigh_get_idx_any(seq, &pos_minus_one) : SEQ_START_TOKEN;
+}
+EXPORT_SYMBOL(neigh_seq_start);
+
+void *neigh_seq_next(struct seq_file *seq, void *v, loff_t *pos)
+{
+	struct neigh_seq_state *state;
+	void *rc;
+
+	if (v == SEQ_START_TOKEN) {
+		rc = neigh_get_idx(seq, pos);
+		goto out;
+	}
+
+	state = seq->private;
+	if (!(state->flags & NEIGH_SEQ_IS_PNEIGH)) {
+		rc = neigh_get_next(seq, v, NULL);
+		if (rc)
+			goto out;
+		if (!(state->flags & NEIGH_SEQ_NEIGH_ONLY))
+			rc = pneigh_get_first(seq);
+	} else {
+		BUG_ON(state->flags & NEIGH_SEQ_NEIGH_ONLY);
+		rc = pneigh_get_next(seq, v, NULL);
+	}
+out:
+	++(*pos);
+	return rc;
+}
+EXPORT_SYMBOL(neigh_seq_next);
+
+void neigh_seq_stop(struct seq_file *seq, void *v)
+{
+	struct neigh_seq_state *state = seq->private;
+	struct neigh_table *tbl = state->tbl;
+
+	read_unlock_bh(&tbl->lock);
+}
+EXPORT_SYMBOL(neigh_seq_stop);
+
+/* statistics via seq_file */
+
+static void *neigh_stat_seq_start(struct seq_file *seq, loff_t *pos)
+{
+	struct proc_dir_entry *pde = seq->private;
+	struct neigh_table *tbl = pde->data;
+	int cpu;
+
+	if (*pos == 0)
+		return SEQ_START_TOKEN;
+	
+	for (cpu = *pos-1; cpu < NR_CPUS; ++cpu) {
+		if (!cpu_possible(cpu))
+			continue;
+		*pos = cpu+1;
+		return per_cpu_ptr(tbl->stats, cpu);
+	}
+	return NULL;
+}
+
+static void *neigh_stat_seq_next(struct seq_file *seq, void *v, loff_t *pos)
+{
+	struct proc_dir_entry *pde = seq->private;
+	struct neigh_table *tbl = pde->data;
+	int cpu;
+
+	for (cpu = *pos; cpu < NR_CPUS; ++cpu) {
+		if (!cpu_possible(cpu))
+			continue;
+		*pos = cpu+1;
+		return per_cpu_ptr(tbl->stats, cpu);
+	}
+	return NULL;
+}
+
+static void neigh_stat_seq_stop(struct seq_file *seq, void *v)
+{
+
+}
+
+static int neigh_stat_seq_show(struct seq_file *seq, void *v)
+{
+	struct proc_dir_entry *pde = seq->private;
+	struct neigh_table *tbl = pde->data;
+	struct neigh_statistics *st = v;
+
+	if (v == SEQ_START_TOKEN) {
+		seq_printf(seq, "entries  allocs destroys hash_grows  lookups hits  res_failed  rcv_probes_mcast rcv_probes_ucast  periodic_gc_runs forced_gc_runs forced_gc_goal_miss\n");
+		return 0;
+	}
+
+	seq_printf(seq, "%08x  %08lx %08lx %08lx  %08lx %08lx  %08lx  "
+			"%08lx %08lx  %08lx %08lx\n",
+		   tbl->entries,
+
+		   st->allocs,
+		   st->destroys,
+		   st->hash_grows,
+
+		   st->lookups,
+		   st->hits,
+
+		   st->res_failed,
+
+		   st->rcv_probes_mcast,
+		   st->rcv_probes_ucast,
+
+		   st->periodic_gc_runs,
+		   st->forced_gc_runs
+		   );
+
+	return 0;
+}
+
+static struct seq_operations neigh_stat_seq_ops = {
+	.start	= neigh_stat_seq_start,
+	.next	= neigh_stat_seq_next,
+	.stop	= neigh_stat_seq_stop,
+	.show	= neigh_stat_seq_show,
+};
+
+static int neigh_stat_seq_open(struct inode *inode, struct file *file)
+{
+	int ret = seq_open(file, &neigh_stat_seq_ops);
+
+	if (!ret) {
+		struct seq_file *sf = file->private_data;
+		sf->private = PDE(inode);
+	}
+	return ret;
+};
+
+static struct file_operations neigh_stat_seq_fops = {
+	.owner	 = THIS_MODULE,
+	.open 	 = neigh_stat_seq_open,
+	.read	 = seq_read,
+	.llseek	 = seq_lseek,
+	.release = seq_release,
+};
+
+#endif /* CONFIG_PROC_FS */
+
 #ifdef CONFIG_ARPD
 void neigh_app_ns(struct neighbour *n)
 {
@@ -1733,6 +2296,7 @@
 EXPORT_SYMBOL(neigh_event_ns);
 EXPORT_SYMBOL(neigh_ifdown);
 EXPORT_SYMBOL(neigh_lookup);
+EXPORT_SYMBOL(neigh_lookup_nodev);
 EXPORT_SYMBOL(neigh_parms_alloc);
 EXPORT_SYMBOL(neigh_parms_release);
 EXPORT_SYMBOL(neigh_rand_reach_time);
diff -Nru a/net/core/net-sysfs.c b/net/core/net-sysfs.c
--- a/net/core/net-sysfs.c	2004-10-18 14:57:03 -07:00
+++ b/net/core/net-sysfs.c	2004-10-18 14:57:03 -07:00
@@ -408,7 +408,6 @@
 
 	class_dev->class = &net_class;
 	class_dev->class_data = net;
-	net->last_stats = net->get_stats;
 
 	strlcpy(class_dev->class_id, net->name, BUS_ID_SIZE);
 	if ((ret = class_device_register(class_dev)))
diff -Nru a/net/core/netfilter.c b/net/core/netfilter.c
--- a/net/core/netfilter.c	2004-10-18 14:56:29 -07:00
+++ b/net/core/netfilter.c	2004-10-18 14:56:29 -07:00
@@ -695,11 +695,12 @@
 	/* DaveM says protocol headers are also modifiable. */
 	switch ((*pskb)->nh.iph->protocol) {
 	case IPPROTO_TCP: {
-		struct tcphdr hdr;
-		if (skb_copy_bits(*pskb, (*pskb)->nh.iph->ihl*4,
-				  &hdr, sizeof(hdr)) != 0)
+		struct tcphdr _hdr, *hp;
+		hp = skb_header_pointer(*pskb, (*pskb)->nh.iph->ihl*4,
+					sizeof(_hdr), &_hdr);
+		if (hp == NULL)
 			goto copy_skb;
-		if (writable_len <= (*pskb)->nh.iph->ihl*4 + hdr.doff*4)
+		if (writable_len <= (*pskb)->nh.iph->ihl*4 + hp->doff*4)
 			goto pull_skb;
 		goto copy_skb;
 	}
@@ -783,13 +784,12 @@
 	nf_logfn *logfn;
 	
 	rcu_read_lock();
-	logfn = nf_logging[pf];
+	logfn = rcu_dereference(nf_logging[pf]);
 	if (logfn) {
 		va_start(args, fmt);
 		vsnprintf(prefix, sizeof(prefix), fmt, args);
 		va_end(args);
 		/* We must read logging before nf_logfn[pf] */
-		smp_read_barrier_depends();
 		logfn(hooknum, skb, in, out, prefix);
 	} else if (!reported) {
 		printk(KERN_WARNING "nf_log_packet: can\'t log yet, "
@@ -806,7 +806,7 @@
    tracking in use: without this, connection may not be in hash table,
    and hence manufactured ICMP or RST packets will not be associated
    with it. */
-void (*ip_ct_attach)(struct sk_buff *, struct nf_ct_info *);
+void (*ip_ct_attach)(struct sk_buff *, struct sk_buff *);
 
 void __init netfilter_init(void)
 {
diff -Nru a/net/core/netpoll.c b/net/core/netpoll.c
--- a/net/core/netpoll.c	2004-10-18 14:57:04 -07:00
+++ b/net/core/netpoll.c	2004-10-18 14:57:04 -07:00
@@ -18,8 +18,10 @@
 #include <linux/interrupt.h>
 #include <linux/netpoll.h>
 #include <linux/sched.h>
+#include <linux/rcupdate.h>
 #include <net/tcp.h>
 #include <net/udp.h>
+#include <asm/unaligned.h>
 
 /*
  * We maintain a small pool of fully-sized skbs, to make sure the
@@ -36,7 +38,11 @@
 static spinlock_t rx_list_lock = SPIN_LOCK_UNLOCKED;
 static LIST_HEAD(rx_list);
 
-static int trapped;
+static atomic_t trapped;
+spinlock_t netpoll_poll_lock = SPIN_LOCK_UNLOCKED;
+
+#define NETPOLL_RX_ENABLED  1
+#define NETPOLL_RX_DROP     2
 
 #define MAX_SKB_SIZE \
 		(MAX_UDP_CHUNK + sizeof(struct udphdr) + \
@@ -61,7 +67,14 @@
 
 void netpoll_poll(struct netpoll *np)
 {
-	int budget = 1;
+	/*
+	 * In cases where there is bi-directional communications, reading
+	 * only one message at a time can lead to packets being dropped by
+	 * the network adapter, forcing superfluous retries and possibly
+	 * timeouts.  Thus, we set our budget to a more reasonable value.
+	 */
+	int budget = 16;
+	unsigned long flags;
 
 	if(!np->dev || !netif_running(np->dev) || !np->dev->poll_controller)
 		return;
@@ -70,9 +83,19 @@
 	np->dev->poll_controller(np->dev);
 
 	/* If scheduling is stopped, tickle NAPI bits */
-	if(trapped && np->dev->poll &&
-	   test_bit(__LINK_STATE_RX_SCHED, &np->dev->state))
+	spin_lock_irqsave(&netpoll_poll_lock, flags);
+	if (np->dev->poll &&
+	    test_bit(__LINK_STATE_RX_SCHED, &np->dev->state)) {
+		np->dev->netpoll_rx |= NETPOLL_RX_DROP;
+		atomic_inc(&trapped);
+
 		np->dev->poll(np->dev, &budget);
+
+		atomic_dec(&trapped);
+		np->dev->netpoll_rx &= ~NETPOLL_RX_DROP;
+	}
+	spin_unlock_irqrestore(&netpoll_poll_lock, flags);
+
 	zap_completion_queue();
 }
 
@@ -168,6 +191,18 @@
 	spin_lock(&np->dev->xmit_lock);
 	np->dev->xmit_lock_owner = smp_processor_id();
 
+	/*
+	 * network drivers do not expect to be called if the queue is
+	 * stopped.
+	 */
+	if (netif_queue_stopped(np->dev)) {
+		np->dev->xmit_lock_owner = -1;
+		spin_unlock(&np->dev->xmit_lock);
+
+		netpoll_poll(np);
+		goto repeat;
+	}
+
 	status = np->dev->hard_start_xmit(skb, np->dev);
 	np->dev->xmit_lock_owner = -1;
 	spin_unlock(&np->dev->xmit_lock);
@@ -206,17 +241,17 @@
 
 	iph = (struct iphdr *)skb_push(skb, sizeof(*iph));
 
-	iph->version  = 4;
-	iph->ihl      = 5;
+	/* iph->version = 4; iph->ihl = 5; */
+	put_unaligned(0x45, (unsigned char *)iph);
 	iph->tos      = 0;
-	iph->tot_len  = htons(ip_len);
+	put_unaligned(htons(ip_len), &(iph->tot_len));
 	iph->id       = 0;
 	iph->frag_off = 0;
 	iph->ttl      = 64;
 	iph->protocol = IPPROTO_UDP;
 	iph->check    = 0;
-	iph->saddr    = htonl(np->local_ip);
-	iph->daddr    = htonl(np->remote_ip);
+	put_unaligned(htonl(np->local_ip), &(iph->saddr));
+	put_unaligned(htonl(np->remote_ip), &(iph->daddr));
 	iph->check    = ip_fast_csum((unsigned char *)iph, iph->ihl);
 
 	eth = (struct ethhdr *) skb_push(skb, ETH_HLEN);
@@ -337,12 +372,13 @@
 		goto out;
 
 	/* check if netpoll clients need ARP */
-	if (skb->protocol == __constant_htons(ETH_P_ARP) && trapped) {
+	if (skb->protocol == __constant_htons(ETH_P_ARP) &&
+	    atomic_read(&trapped)) {
 		arp_reply(skb);
 		return 1;
 	}
 
-	proto = ntohs(skb->mac.ethernet->h_proto);
+	proto = ntohs(eth_hdr(skb)->h_proto);
 	if (proto != ETH_P_IP)
 		goto out;
 	if (skb->pkt_type == PACKET_OTHERHOST)
@@ -400,7 +436,7 @@
 	spin_unlock_irqrestore(&rx_list_lock, flags);
 
 out:
-	return trapped;
+	return atomic_read(&trapped);
 }
 
 int netpoll_parse_options(struct netpoll *np, char *opt)
@@ -572,16 +608,18 @@
 		memcpy(np->local_mac, ndev->dev_addr, 6);
 
 	if (!np->local_ip) {
-		in_dev = in_dev_get(ndev);
+		rcu_read_lock();
+		in_dev = __in_dev_get(ndev);
 
 		if (!in_dev) {
+			rcu_read_unlock();
 			printk(KERN_ERR "%s: no IP address for %s, aborting\n",
 			       np->name, np->dev_name);
 			goto release;
 		}
 
 		np->local_ip = ntohl(in_dev->ifa_list->ifa_local);
-		in_dev_put(in_dev);
+		rcu_read_unlock();
 		printk(KERN_INFO "%s: local IP %d.%d.%d.%d\n",
 		       np->name, HIPQUAD(np->local_ip));
 	}
@@ -591,9 +629,7 @@
 	if(np->rx_hook) {
 		unsigned long flags;
 
-#ifdef CONFIG_NETPOLL_RX
-		np->dev->netpoll_rx = 1;
-#endif
+		np->dev->netpoll_rx = NETPOLL_RX_ENABLED;
 
 		spin_lock_irqsave(&rx_list_lock, flags);
 		list_add(&np->rx_list, &rx_list);
@@ -608,29 +644,31 @@
 
 void netpoll_cleanup(struct netpoll *np)
 {
-	if(np->rx_hook) {
+	if (np->rx_hook) {
 		unsigned long flags;
 
 		spin_lock_irqsave(&rx_list_lock, flags);
 		list_del(&np->rx_list);
-#ifdef CONFIG_NETPOLL_RX
-		np->dev->netpoll_rx = 0;
-#endif
 		spin_unlock_irqrestore(&rx_list_lock, flags);
 	}
 
+	if (np->dev)
+		np->dev->netpoll_rx = 0;
 	dev_put(np->dev);
 	np->dev = NULL;
 }
 
 int netpoll_trap(void)
 {
-	return trapped;
+	return atomic_read(&trapped);
 }
 
 void netpoll_set_trap(int trap)
 {
-	trapped = trap;
+	if (trap)
+		atomic_inc(&trapped);
+	else
+		atomic_dec(&trapped);
 }
 
 EXPORT_SYMBOL(netpoll_set_trap);
diff -Nru a/net/core/pktgen.c b/net/core/pktgen.c
--- a/net/core/pktgen.c	2004-10-18 14:56:48 -07:00
+++ b/net/core/pktgen.c	2004-10-18 14:56:48 -07:00
@@ -52,6 +52,9 @@
  *
  * Fixed unaligned access on IA-64 Grant Grundler <grundler@parisc-linux.org>
  *
+ * New xmit() return, do_div and misc clean up by Stephen Hemminger 
+ * <shemminger@osdl.org> 040923
+ *
  * See Documentation/networking/pktgen.txt for how to use this.
  */
 
@@ -70,6 +73,7 @@
 #include <linux/delay.h>
 #include <linux/init.h>
 #include <linux/inet.h>
+#include <linux/rcupdate.h>
 #include <asm/byteorder.h>
 #include <asm/bitops.h>
 #include <asm/io.h>
@@ -93,7 +97,7 @@
 
 #define VERSION "pktgen version 1.32"
 static char version[] __initdata = 
-  "pktgen.c: v1.3: Packet Generator for packet performance testing.\n";
+  "pktgen.c: v1.4: Packet Generator for packet performance testing.\n";
 
 /* Used to help with determining the pkts on receive */
 
@@ -263,14 +267,17 @@
 	info->saddr_min = 0;
 	info->saddr_max = 0;
 	if (strlen(info->src_min) == 0) {
-		struct in_device *in_dev = in_dev_get(odev);
+		struct in_device *in_dev;
+
+		rcu_read_lock();
+		in_dev = __in_dev_get(odev);
 		if (in_dev) {
 			if (in_dev->ifa_list) {
 				info->saddr_min = in_dev->ifa_list->ifa_address;
 				info->saddr_max = info->saddr_min;
 			}
-			in_dev_put(in_dev);
 		}
+		rcu_read_unlock();
 	}
 	else {
 		info->saddr_min = in_aton(info->src_min);
@@ -580,15 +587,48 @@
 	return skb;
 }
 
+static void show_results(struct pktgen_info* info, int nr_frags)
+{
+	__u64 total, bps, mbps, pps;
+	unsigned long idle;
+	int size = info->pkt_size + 4; /* incl 32bit ethernet CRC */
+	char *p = info->result;
+
+	total = (info->stopped_at.tv_sec - info->started_at.tv_sec) * 1000000ull
+		+ info->stopped_at.tv_usec - info->started_at.tv_usec;
+
+	BUG_ON(cpu_speed == 0);
+
+	idle = info->idle_acc;
+	do_div(idle, cpu_speed);
+
+	p += sprintf(p, "OK: %llu(c%llu+d%lu) usec, %llu (%dbyte,%dfrags)\n",
+		     total, total - idle, idle,
+		     info->sofar, size, nr_frags);
+
+	pps = info->sofar * USEC_PER_SEC;
+	
+	while ((total >> 32) != 0) {
+		pps >>= 1;
+		total >>= 1;
+	}
+
+	do_div(pps, total);
+	
+	bps = pps * 8 * size;
+
+	mbps = bps;
+	do_div(mbps, 1000000);
+	p += sprintf(p, "  %llupps %lluMb/sec (%llubps) errors: %llu",
+		     pps, mbps, bps, info->errors);
+}
 
 static void inject(struct pktgen_info* info)
 {
-	struct net_device *odev = NULL;
+	struct net_device *odev;
 	struct sk_buff *skb = NULL;
-	__u64 total = 0;
-	__u64 idle = 0;
 	__u64 lcount = 0;
-	int nr_frags = 0;
+	int ret;
 	int last_ok = 1;	   /* Was last skb sent? 
 				    * Or a failed transmit of some sort?  This will keep
 				    * sequence numbers in order, for example.
@@ -628,35 +668,38 @@
 			}
 		}
 
-		nr_frags = skb_shinfo(skb)->nr_frags;
-		   
-		spin_lock_bh(&odev->xmit_lock);
+		if (!(odev->features & NETIF_F_LLTX))
+			spin_lock_bh(&odev->xmit_lock);
 		if (!netif_queue_stopped(odev)) {
 
 			atomic_inc(&skb->users);
 
-			if (odev->hard_start_xmit(skb, odev)) {
-
+		retry:
+			ret = odev->hard_start_xmit(skb, odev);
+			if (likely(ret == NETDEV_TX_OK)) {
+				last_ok = 1;	
+				info->sofar++;
+				info->seq_num++;
+			} else if (ret == NETDEV_TX_LOCKED 
+				   && (odev->features & NETIF_F_LLTX)) {
+				cpu_relax();
+				goto retry;
+			} else {
 				atomic_dec(&skb->users);
-				if (net_ratelimit()) {
+				if (debug && net_ratelimit()) {
 				   printk(KERN_INFO "Hard xmit error\n");
 				}
 				info->errors++;
 				last_ok = 0;
 			}
-			else {
-			   last_ok = 1;	
-			   info->sofar++;
-			   info->seq_num++;
-			}
 		}
 		else {
 			/* Re-try it next time */
 			last_ok = 0;
 		}
 		
-
-		spin_unlock_bh(&odev->xmit_lock);
+		if (!(odev->features & NETIF_F_LLTX))
+			spin_unlock_bh(&odev->xmit_lock);
 
 		if (info->ipg) {
 			/* Try not to busy-spin if we have larger sleep times.
@@ -720,38 +763,7 @@
 
 	do_gettimeofday(&(info->stopped_at));
 
-	total = (info->stopped_at.tv_sec - info->started_at.tv_sec) * 1000000 +
-		info->stopped_at.tv_usec - info->started_at.tv_usec;
-
-	idle = (__u32)(info->idle_acc)/(__u32)(cpu_speed);
-
-	{
-		char *p = info->result;
-		__u64 bps, pps = 0;
-
-		if (total > 1000)
-			pps = (__u32)(info->sofar * 1000) / ((__u32)(total) / 1000);
-		else if(total > 100)
-			pps = (__u32)(info->sofar * 10000) / ((__u32)(total) / 100);
-		else if(total > 10)
-			pps = (__u32)(info->sofar * 100000) / ((__u32)(total) / 10);
-		else if(total > 1)
-			pps = (__u32)(info->sofar * 1000000) / (__u32)total;
-
-		bps = pps * 8 * (info->pkt_size + 4); /* take 32bit ethernet CRC into account */
-		p += sprintf(p, "OK: %llu(c%llu+d%llu) usec, %llu (%dbyte,%dfrags) %llupps %lluMb/sec (%llubps)  errors: %llu",
-			     (unsigned long long) total,
-			     (unsigned long long) (total - idle),
-			     (unsigned long long) idle,
-			     (unsigned long long) info->sofar,
-			     skb->len + 4, /* Add 4 to account for the ethernet checksum */
-			     nr_frags,
-			     (unsigned long long) pps,
-			     (unsigned long long) (bps / (u64) 1024 / (u64) 1024),
-			     (unsigned long long) bps,
-			     (unsigned long long) info->errors
-			     );
-	}
+	show_results(info, skb_shinfo(skb)->nr_frags);
 
 	kfree_skb(skb);
 
diff -Nru a/net/core/rtnetlink.c b/net/core/rtnetlink.c
--- a/net/core/rtnetlink.c	2004-10-18 14:57:18 -07:00
+++ b/net/core/rtnetlink.c	2004-10-18 14:57:18 -07:00
@@ -166,31 +166,58 @@
 	r->ifi_family = AF_UNSPEC;
 	r->ifi_type = dev->type;
 	r->ifi_index = dev->ifindex;
-	r->ifi_flags = dev->flags;
+	r->ifi_flags = dev_get_flags(dev);
 	r->ifi_change = change;
 
-	if (!netif_running(dev) || !netif_carrier_ok(dev))
-		r->ifi_flags &= ~IFF_RUNNING;
-	else
-		r->ifi_flags |= IFF_RUNNING;
-
 	RTA_PUT(skb, IFLA_IFNAME, strlen(dev->name)+1, dev->name);
+
+	if (1) {
+		u32 txqlen = dev->tx_queue_len;
+		RTA_PUT(skb, IFLA_TXQLEN, sizeof(txqlen), &txqlen);
+	}
+
+	if (1) {
+		u32 weight = dev->weight;
+		RTA_PUT(skb, IFLA_WEIGHT, sizeof(weight), &weight);
+	}
+
+	if (1) {
+		struct rtnl_link_ifmap map = {
+			.mem_start   = dev->mem_start,
+			.mem_end     = dev->mem_end,
+			.base_addr   = dev->base_addr,
+			.irq         = dev->irq,
+			.dma         = dev->dma,
+			.port        = dev->if_port,
+		};
+		RTA_PUT(skb, IFLA_MAP, sizeof(map), &map);
+	}
+
 	if (dev->addr_len) {
 		RTA_PUT(skb, IFLA_ADDRESS, dev->addr_len, dev->dev_addr);
 		RTA_PUT(skb, IFLA_BROADCAST, dev->addr_len, dev->broadcast);
 	}
+
 	if (1) {
-		unsigned mtu = dev->mtu;
+		u32 mtu = dev->mtu;
 		RTA_PUT(skb, IFLA_MTU, sizeof(mtu), &mtu);
 	}
-	if (dev->ifindex != dev->iflink)
-		RTA_PUT(skb, IFLA_LINK, sizeof(int), &dev->iflink);
+
+	if (dev->ifindex != dev->iflink) {
+		u32 iflink = dev->iflink;
+		RTA_PUT(skb, IFLA_LINK, sizeof(iflink), &iflink);
+	}
+
 	if (dev->qdisc_sleeping)
 		RTA_PUT(skb, IFLA_QDISC,
 			strlen(dev->qdisc_sleeping->ops->id) + 1,
 			dev->qdisc_sleeping->ops->id);
-	if (dev->master)
-		RTA_PUT(skb, IFLA_MASTER, sizeof(int), &dev->master->ifindex);
+	
+	if (dev->master) {
+		u32 master = dev->master->ifindex;
+		RTA_PUT(skb, IFLA_MASTER, sizeof(master), &master);
+	}
+
 	if (dev->get_stats) {
 		unsigned long *stats = (unsigned long*)dev->get_stats(dev);
 		if (stats) {
@@ -238,7 +265,7 @@
 	struct ifinfomsg  *ifm = NLMSG_DATA(nlh);
 	struct rtattr    **ida = arg;
 	struct net_device *dev;
-	int err;
+	int err, send_addr_notify = 0;
 
 	dev = dev_get_by_index(ifm->ifi_index);
 	if (!dev)
@@ -246,6 +273,41 @@
 
 	err = -EINVAL;
 
+	if (ifm->ifi_flags)
+		dev_change_flags(dev, ifm->ifi_flags);
+
+	if (ida[IFLA_MAP - 1]) {
+		struct rtnl_link_ifmap *u_map;
+		struct ifmap k_map;
+
+		if (!dev->set_config) {
+			err = -EOPNOTSUPP;
+			goto out;
+		}
+
+		if (!netif_device_present(dev)) {
+			err = -ENODEV;
+			goto out;
+		}
+		
+		if (ida[IFLA_MAP - 1]->rta_len != RTA_LENGTH(sizeof(*u_map)))
+			goto out;
+
+		u_map = RTA_DATA(ida[IFLA_MAP - 1]);
+
+		k_map.mem_start = (unsigned long) u_map->mem_start;
+		k_map.mem_end = (unsigned long) u_map->mem_end;
+		k_map.base_addr = (unsigned short) u_map->base_addr;
+		k_map.irq = (unsigned char) u_map->irq;
+		k_map.dma = (unsigned char) u_map->dma;
+		k_map.port = (unsigned char) u_map->port;
+
+		err = dev->set_config(dev, &k_map);
+
+		if (err)
+			goto out;
+	}
+
 	if (ida[IFLA_ADDRESS - 1]) {
 		if (!dev->set_mac_address) {
 			err = -EOPNOTSUPP;
@@ -261,6 +323,7 @@
 		err = dev->set_mac_address(dev, RTA_DATA(ida[IFLA_ADDRESS - 1]));
 		if (err)
 			goto out;
+		send_addr_notify = 1;
 	}
 
 	if (ida[IFLA_BROADCAST - 1]) {
@@ -268,12 +331,54 @@
 			goto out;
 		memcpy(dev->broadcast, RTA_DATA(ida[IFLA_BROADCAST - 1]),
 		       dev->addr_len);
+		send_addr_notify = 1;
+	}
+
+	if (ida[IFLA_MTU - 1]) {
+		if (ida[IFLA_MTU - 1]->rta_len != RTA_LENGTH(sizeof(u32)))
+			goto out;
+		err = dev_set_mtu(dev, *((u32 *) RTA_DATA(ida[IFLA_MTU - 1])));
+
+		if (err)
+			goto out;
+
+	}
+
+	if (ida[IFLA_TXQLEN - 1]) {
+		if (ida[IFLA_TXQLEN - 1]->rta_len != RTA_LENGTH(sizeof(u32)))
+			goto out;
+
+		dev->tx_queue_len = *((u32 *) RTA_DATA(ida[IFLA_TXQLEN - 1]));
+	}
+
+	if (ida[IFLA_WEIGHT - 1]) {
+		if (ida[IFLA_WEIGHT - 1]->rta_len != RTA_LENGTH(sizeof(u32)))
+			goto out;
+
+		dev->weight = *((u32 *) RTA_DATA(ida[IFLA_WEIGHT - 1]));
+	}
+
+	if (ida[IFLA_IFNAME - 1]) {
+		char ifname[IFNAMSIZ];
+
+		if (ida[IFLA_IFNAME - 1]->rta_len > RTA_LENGTH(sizeof(ifname)))
+			goto out;
+
+		memset(ifname, 0, sizeof(ifname));
+		memcpy(ifname, RTA_DATA(ida[IFLA_IFNAME - 1]),
+			RTA_PAYLOAD(ida[IFLA_IFNAME - 1]));
+		ifname[IFNAMSIZ - 1] = '\0';
+
+		err = dev_change_name(dev, ifname);
+
+		if (err)
+			goto out;
 	}
 
 	err = 0;
 
 out:
-	if (!err)
+	if (send_addr_notify)
 		call_netdevice_notifiers(NETDEV_CHANGEADDR, dev);
 
 	dev_put(dev);
@@ -307,7 +412,9 @@
 void rtmsg_ifinfo(int type, struct net_device *dev, unsigned change)
 {
 	struct sk_buff *skb;
-	int size = NLMSG_GOODSIZE;
+	int size = NLMSG_SPACE(sizeof(struct ifinfomsg) +
+			       sizeof(struct rtnl_link_ifmap) +
+			       sizeof(struct rtnl_link_stats) + 128);
 
 	skb = alloc_skb(size, GFP_KERNEL);
 	if (!skb)
@@ -326,6 +433,10 @@
 	return 0;
 }
 
+/* Protected by RTNL sempahore.  */
+static struct rtattr **rta_buf;
+static int rtattr_max;
+
 /* Process one rtnetlink message. */
 
 static __inline__ int
@@ -333,8 +444,6 @@
 {
 	struct rtnetlink_link *link;
 	struct rtnetlink_link *link_tab;
-	struct rtattr	*rta[RTATTR_MAX];
-
 	int sz_idx, kind;
 	int min_len;
 	int family;
@@ -401,7 +510,7 @@
 		return -1;
 	}
 
-	memset(&rta, 0, sizeof(rta));
+	memset(rta_buf, 0, (rtattr_max * sizeof(struct rtattr *)));
 
 	min_len = rtm_min[sz_idx];
 	if (nlh->nlmsg_len < min_len)
@@ -416,7 +525,7 @@
 			if (flavor) {
 				if (flavor > rta_max[sz_idx])
 					goto err_inval;
-				rta[flavor-1] = attr;
+				rta_buf[flavor-1] = attr;
 			}
 			attr = RTA_NEXT(attr, attrlen);
 		}
@@ -426,7 +535,7 @@
 		link = &(rtnetlink_links[PF_UNSPEC][type]);
 	if (link->doit == NULL)
 		goto err_inval;
-	err = link->doit(skb, nlh, (void *)&rta);
+	err = link->doit(skb, nlh, (void *)&rta_buf[0]);
 
 	*errp = err;
 	return err;
@@ -546,6 +655,16 @@
 
 void __init rtnetlink_init(void)
 {
+	int i;
+
+	rtattr_max = 0;
+	for (i = 0; i < ARRAY_SIZE(rta_max); i++)
+		if (rta_max[i] > rtattr_max)
+			rtattr_max = rta_max[i];
+	rta_buf = kmalloc(rtattr_max * sizeof(struct rtattr *), GFP_KERNEL);
+	if (!rta_buf)
+		panic("rtnetlink_init: cannot allocate rta_buf\n");
+
 	rtnl = netlink_kernel_create(NETLINK_ROUTE, rtnetlink_rcv);
 	if (rtnl == NULL)
 		panic("rtnetlink_init: cannot initialize rtnetlink\n");
diff -Nru a/net/core/skbuff.c b/net/core/skbuff.c
--- a/net/core/skbuff.c	2004-10-18 14:56:48 -07:00
+++ b/net/core/skbuff.c	2004-10-18 14:56:48 -07:00
@@ -311,6 +311,7 @@
 	C(nfcache);
 	C(nfct);
 	nf_conntrack_get(skb->nfct);
+	C(nfctinfo);
 #ifdef CONFIG_NETFILTER_DEBUG
 	C(nf_debug);
 #endif
@@ -377,6 +378,7 @@
 	new->nfcache	= old->nfcache;
 	new->nfct	= old->nfct;
 	nf_conntrack_get(old->nfct);
+	new->nfctinfo	= old->nfctinfo;
 #ifdef CONFIG_NETFILTER_DEBUG
 	new->nf_debug	= old->nf_debug;
 #endif
diff -Nru a/net/core/sock.c b/net/core/sock.c
--- a/net/core/sock.c	2004-10-18 14:56:49 -07:00
+++ b/net/core/sock.c	2004-10-18 14:56:49 -07:00
@@ -1343,6 +1343,27 @@
 
 EXPORT_SYMBOL(sk_common_release);
 
+int sk_alloc_slab(struct proto *prot, char *name)
+{
+	prot->slab = kmem_cache_create(name,
+				       prot->slab_obj_size, 0,
+				       SLAB_HWCACHE_ALIGN, NULL, NULL);
+
+	return prot->slab != NULL ? 0 : -ENOBUFS;
+}
+
+EXPORT_SYMBOL(sk_alloc_slab);
+
+void sk_free_slab(struct proto *prot)
+{
+	if (prot->slab != NULL) {
+		kmem_cache_destroy(prot->slab);
+		prot->slab = NULL;
+	}
+}
+
+EXPORT_SYMBOL(sk_free_slab);
+
 EXPORT_SYMBOL(__lock_sock);
 EXPORT_SYMBOL(__release_sock);
 EXPORT_SYMBOL(sk_alloc);
diff -Nru a/net/core/utils.c b/net/core/utils.c
--- a/net/core/utils.c	2004-10-18 14:55:46 -07:00
+++ b/net/core/utils.c	2004-10-18 14:55:46 -07:00
@@ -19,23 +19,125 @@
 #include <linux/mm.h>
 #include <linux/string.h>
 #include <linux/types.h>
+#include <linux/random.h>
+#include <linux/percpu.h>
+#include <linux/init.h>
 
 #include <asm/system.h>
 #include <asm/uaccess.h>
 
-static unsigned long net_rand_seed = 152L;
+
+/*
+  This is a maximally equidistributed combined Tausworthe generator
+  based on code from GNU Scientific Library 1.5 (30 Jun 2004)
+
+   x_n = (s1_n ^ s2_n ^ s3_n) 
+
+   s1_{n+1} = (((s1_n & 4294967294) <<12) ^ (((s1_n <<13) ^ s1_n) >>19))
+   s2_{n+1} = (((s2_n & 4294967288) << 4) ^ (((s2_n << 2) ^ s2_n) >>25))
+   s3_{n+1} = (((s3_n & 4294967280) <<17) ^ (((s3_n << 3) ^ s3_n) >>11))
+
+   The period of this generator is about 2^88.
+
+   From: P. L'Ecuyer, "Maximally Equidistributed Combined Tausworthe
+   Generators", Mathematics of Computation, 65, 213 (1996), 203--213.
+
+   This is available on the net from L'Ecuyer's home page,
+
+   http://www.iro.umontreal.ca/~lecuyer/myftp/papers/tausme.ps
+   ftp://ftp.iro.umontreal.ca/pub/simulation/lecuyer/papers/tausme.ps 
+
+   There is an erratum in the paper "Tables of Maximally
+   Equidistributed Combined LFSR Generators", Mathematics of
+   Computation, 68, 225 (1999), 261--269:
+   http://www.iro.umontreal.ca/~lecuyer/myftp/papers/tausme2.ps
+
+        ... the k_j most significant bits of z_j must be non-
+        zero, for each j. (Note: this restriction also applies to the 
+        computer code given in [4], but was mistakenly not mentioned in
+        that paper.)
+   
+   This affects the seeding procedure by imposing the requirement
+   s1 > 1, s2 > 7, s3 > 15.
+
+*/
+struct nrnd_state {
+	u32 s1, s2, s3;
+};
+
+static DEFINE_PER_CPU(struct nrnd_state, net_rand_state);
+
+static u32 __net_random(struct nrnd_state *state)
+{
+#define TAUSWORTHE(s,a,b,c,d) ((s&c)<<d) ^ (((s <<a) ^ s)>>b)
+
+	state->s1 = TAUSWORTHE(state->s1, 13, 19, 4294967294UL, 12);
+	state->s2 = TAUSWORTHE(state->s2, 2, 25, 4294967288UL, 4);
+	state->s3 = TAUSWORTHE(state->s3, 3, 11, 4294967280UL, 17);
+
+	return (state->s1 ^ state->s2 ^ state->s3);
+}
+
+static void __net_srandom(struct nrnd_state *state, unsigned long s)
+{
+	if (s == 0)
+		s = 1;      /* default seed is 1 */
+
+#define LCG(n) (69069 * n)
+	state->s1 = LCG(s);
+	state->s2 = LCG(state->s1);
+	state->s3 = LCG(state->s2);
+
+	/* "warm it up" */
+	__net_random(state);
+	__net_random(state);
+	__net_random(state);
+	__net_random(state);
+	__net_random(state);
+	__net_random(state);
+}
+
 
 unsigned long net_random(void)
 {
-	net_rand_seed=net_rand_seed*69069L+1;
-        return net_rand_seed^jiffies;
+	unsigned long r;
+	struct nrnd_state *state = &get_cpu_var(net_rand_state);
+	r = __net_random(state);
+	put_cpu_var(state);
+	return r;
 }
 
+
 void net_srandom(unsigned long entropy)
 {
-	net_rand_seed ^= entropy;
-	net_random();
+	struct nrnd_state *state = &get_cpu_var(net_rand_state);
+	__net_srandom(state, state->s1^entropy);
+	put_cpu_var(state);
+}
+
+void __init net_random_init(void)
+{
+	int i;
+
+	for (i = 0; i < NR_CPUS; i++) {
+		struct nrnd_state *state = &per_cpu(net_rand_state,i);
+		__net_srandom(state, i+jiffies);
+	}
+}
+
+static int net_random_reseed(void)
+{
+	int i;
+	unsigned long seed[NR_CPUS];
+
+	get_random_bytes(seed, sizeof(seed));
+	for (i = 0; i < NR_CPUS; i++) {
+		struct nrnd_state *state = &per_cpu(net_rand_state,i);
+		__net_srandom(state, seed[i]);
+	}
+	return 0;
 }
+late_initcall(net_random_reseed);
 
 int net_msg_cost = 5*HZ;
 int net_msg_burst = 10;
diff -Nru a/net/decnet/dn_dev.c b/net/decnet/dn_dev.c
--- a/net/decnet/dn_dev.c	2004-10-18 14:56:28 -07:00
+++ b/net/decnet/dn_dev.c	2004-10-18 14:56:28 -07:00
@@ -41,6 +41,7 @@
 #include <linux/sysctl.h>
 #include <linux/notifier.h>
 #include <asm/uaccess.h>
+#include <asm/system.h>
 #include <net/neighbour.h>
 #include <net/dst.h>
 #include <net/flow.h>
@@ -247,21 +248,6 @@
 	}, {0}}
 };
 
-static inline __u16 mtu2blksize(struct net_device *dev)
-{
-	u32 blksize = dev->mtu;
-	if (blksize > 0xffff)
-		blksize = 0xffff;
-
-	if (dev->type == ARPHRD_ETHER ||
-	    dev->type == ARPHRD_PPP ||
-	    dev->type == ARPHRD_IPGRE ||
-	    dev->type == ARPHRD_LOOPBACK)
-		blksize -= 2;
-
-	return (__u16)blksize;
-}
-
 static void dn_dev_sysctl_register(struct net_device *dev, struct dn_dev_parms *parms)
 {
 	struct dn_dev_sysctl_table *t;
@@ -314,52 +300,6 @@
 	}
 }
 
-struct net_device *dn_dev_get_default(void)
-{
-	struct net_device *dev;
-	read_lock(&dndev_lock);
-	dev = decnet_default_device;
-	if (dev) {
-		if (dev->dn_ptr)
-			dev_hold(dev);
-		else
-			dev = NULL;
-	}
-	read_unlock(&dndev_lock);
-	return dev;
-}
-
-int dn_dev_set_default(struct net_device *dev, int force)
-{
-	struct net_device *old = NULL;
-	int rv = -EBUSY;
-	if (!dev->dn_ptr)
-		return -ENODEV;
-	write_lock(&dndev_lock);
-	if (force || decnet_default_device == NULL) {
-		old = decnet_default_device;
-		decnet_default_device = dev;
-		rv = 0;
-	}
-	write_unlock(&dndev_lock);
-	if (old)
-		dev_put(dev);
-	return rv;
-}
-
-static void dn_dev_check_default(struct net_device *dev)
-{
-	write_lock(&dndev_lock);
-	if (dev == decnet_default_device) {
-		decnet_default_device = NULL;
-	} else {
-		dev = NULL;
-	}
-	write_unlock(&dndev_lock);
-	if (dev)
-		dev_put(dev);
-}
-
 static int dn_forwarding_proc(ctl_table *table, int write, 
 				struct file *filep,
 				void __user *buffer,
@@ -454,6 +394,21 @@
 
 #endif /* CONFIG_SYSCTL */
 
+static inline __u16 mtu2blksize(struct net_device *dev)
+{
+	u32 blksize = dev->mtu;
+	if (blksize > 0xffff)
+		blksize = 0xffff;
+
+	if (dev->type == ARPHRD_ETHER ||
+	    dev->type == ARPHRD_PPP ||
+	    dev->type == ARPHRD_IPGRE ||
+	    dev->type == ARPHRD_LOOPBACK)
+		blksize -= 2;
+
+	return (__u16)blksize;
+}
+
 static struct dn_ifaddr *dn_dev_alloc_ifa(void)
 {
 	struct dn_ifaddr *ifa;
@@ -635,6 +590,52 @@
 	goto done;
 }
 
+struct net_device *dn_dev_get_default(void)
+{
+	struct net_device *dev;
+	read_lock(&dndev_lock);
+	dev = decnet_default_device;
+	if (dev) {
+		if (dev->dn_ptr)
+			dev_hold(dev);
+		else
+			dev = NULL;
+	}
+	read_unlock(&dndev_lock);
+	return dev;
+}
+
+int dn_dev_set_default(struct net_device *dev, int force)
+{
+	struct net_device *old = NULL;
+	int rv = -EBUSY;
+	if (!dev->dn_ptr)
+		return -ENODEV;
+	write_lock(&dndev_lock);
+	if (force || decnet_default_device == NULL) {
+		old = decnet_default_device;
+		decnet_default_device = dev;
+		rv = 0;
+	}
+	write_unlock(&dndev_lock);
+	if (old)
+		dev_put(dev);
+	return rv;
+}
+
+static void dn_dev_check_default(struct net_device *dev)
+{
+	write_lock(&dndev_lock);
+	if (dev == decnet_default_device) {
+		decnet_default_device = NULL;
+	} else {
+		dev = NULL;
+	}
+	write_unlock(&dndev_lock);
+	if (dev)
+		dev_put(dev);
+}
+
 static struct dn_dev *dn_dev_by_index(int ifindex)
 {
 	struct net_device *dev;
@@ -1108,6 +1109,7 @@
 
 	memset(dn_db, 0, sizeof(struct dn_dev));
 	memcpy(&dn_db->parms, p, sizeof(struct dn_dev_parms));
+	smp_wmb();
 	dev->dn_ptr = dn_db;
 	dn_db->dev = dev;
 	init_timer(&dn_db->timer);
@@ -1215,6 +1217,7 @@
 	dev->dn_ptr = NULL;
 
 	neigh_parms_release(&dn_neigh_table, dn_db->neigh_parms);
+	neigh_ifdown(&dn_neigh_table, dev);
 
 	if (dn_db->router)
 		neigh_release(dn_db->router);
diff -Nru a/net/decnet/dn_neigh.c b/net/decnet/dn_neigh.c
--- a/net/decnet/dn_neigh.c	2004-10-18 14:56:48 -07:00
+++ b/net/decnet/dn_neigh.c	2004-10-18 14:56:48 -07:00
@@ -35,6 +35,8 @@
 #include <linux/netfilter_decnet.h>
 #include <linux/spinlock.h>
 #include <linux/seq_file.h>
+#include <linux/rcupdate.h>
+#include <linux/jhash.h>
 #include <asm/atomic.h>
 #include <net/neighbour.h>
 #include <net/dst.h>
@@ -121,26 +123,32 @@
 
 static u32 dn_neigh_hash(const void *pkey, const struct net_device *dev)
 {
-	u32 hash_val;
-
-	hash_val = *(dn_address *)pkey;
-	hash_val ^= (hash_val >> 10);
-	hash_val ^= (hash_val >> 3);
-
-	return hash_val & NEIGH_HASHMASK;
+	return jhash_2words(*(dn_address *)pkey, 0, dn_neigh_table.hash_rnd);
 }
 
 static int dn_neigh_construct(struct neighbour *neigh)
 {
 	struct net_device *dev = neigh->dev;
 	struct dn_neigh *dn = (struct dn_neigh *)neigh;
-	struct dn_dev *dn_db = (struct dn_dev *)dev->dn_ptr;
+	struct dn_dev *dn_db;
+	struct neigh_parms *parms;
+
+	rcu_read_lock();
+	dn_db = rcu_dereference(dev->dn_ptr);
+	if (dn_db == NULL) {
+		rcu_read_unlock();
+		return -EINVAL;
+	}
 
-	if (dn_db == NULL)
+	parms = dn_db->neigh_parms;
+	if (!parms) {
+		rcu_read_unlock();
 		return -EINVAL;
+	}
 
-	if (dn_db->neigh_parms)
-		neigh->parms = dn_db->neigh_parms;
+	__neigh_parms_put(neigh->parms);
+	neigh->parms = neigh_parms_clone(parms);
+	rcu_read_unlock();
 
 	if (dn_db->use_long)
 		neigh->ops = &dn_long_ops;
@@ -346,27 +354,6 @@
  * basically does a neigh_lookup(), but without comparing the device
  * field. This is required for the On-Ethernet cache
  */
-struct neighbour *dn_neigh_lookup(struct neigh_table *tbl, const void *ptr)
-{
-	struct neighbour *neigh;
-	u32 hash_val;
-
-	hash_val = tbl->hash(ptr, NULL);
-
-	read_lock_bh(&tbl->lock);
-	for(neigh = tbl->hash_buckets[hash_val]; neigh != NULL; neigh = neigh->next) {
-		if (memcmp(neigh->primary_key, ptr, tbl->key_len) == 0) {
-			atomic_inc(&neigh->refcnt);
-			read_unlock_bh(&tbl->lock);
-			return neigh;
-		}
-	}
-	read_unlock_bh(&tbl->lock);
-
-	return NULL;
-}
-
-
 /*
  * Any traffic on a pointopoint link causes the timer to be reset
  * for the entry in the neighbour table.
@@ -412,7 +399,7 @@
 			neigh->updated = jiffies;
 
 			if (neigh->dev->type == ARPHRD_ETHER)
-				memcpy(neigh->ha, &skb->mac.ethernet->h_source, ETH_ALEN);
+				memcpy(neigh->ha, &eth_hdr(skb)->h_source, ETH_ALEN);
 
 			dn->blksize  = dn_ntohs(msg->blksize);
 			dn->priority = msg->priority;
@@ -468,7 +455,7 @@
 			neigh->updated = jiffies;
 
 			if (neigh->dev->type == ARPHRD_ETHER)
-				memcpy(neigh->ha, &skb->mac.ethernet->h_source, ETH_ALEN);
+				memcpy(neigh->ha, &eth_hdr(skb)->h_source, ETH_ALEN);
 			dn->flags   &= ~(DN_NDFLAG_R1 | DN_NDFLAG_R2);
 			dn->blksize  = dn_ntohs(msg->blksize);
 			dn->priority = 0;
@@ -501,141 +488,66 @@
 	return (*min < priority) ? (min - 6) : NULL;
 }
 
-int dn_neigh_elist(struct net_device *dev, unsigned char *ptr, int n)
-{
-	int t = 0;
-	int i;
-	struct neighbour *neigh;
-	struct dn_neigh *dn;
-	struct neigh_table *tbl = &dn_neigh_table;
-	unsigned char *rs = ptr;
-	struct dn_dev *dn_db = (struct dn_dev *)dev->dn_ptr;
-
-	read_lock_bh(&tbl->lock);
-
-	for(i = 0; i < NEIGH_HASHMASK; i++) {
-		for(neigh = tbl->hash_buckets[i]; neigh != NULL; neigh = neigh->next) {
-			if (neigh->dev != dev)
-				continue;
-			dn = (struct dn_neigh *)neigh;
-			if (!(dn->flags & (DN_NDFLAG_R1|DN_NDFLAG_R2)))
-				continue;
-			if (dn_db->parms.forwarding == 1 && (dn->flags & DN_NDFLAG_R2))
-				continue;
-			if (t == n)
-				rs = dn_find_slot(ptr, n, dn->priority);
-			else
-				t++;
-			if (rs == NULL)
-				continue;
-			dn_dn2eth(rs, dn->addr);
-			rs += 6;
-			*rs = neigh->nud_state & NUD_CONNECTED ? 0x80 : 0x0;
-			*rs |= dn->priority;
-			rs++;
-		}
-	}
-
-	read_unlock_bh(&tbl->lock);
-
-	return t;
-}
-
-
-#ifdef CONFIG_PROC_FS
-
-struct dn_neigh_iter_state {
-	int bucket;
+struct elist_cb_state {
+	struct net_device *dev;
+	unsigned char *ptr;
+	unsigned char *rs;
+	int t, n;
 };
 
-static struct neighbour *neigh_get_first(struct seq_file *seq)
+static void neigh_elist_cb(struct neighbour *neigh, void *_info)
 {
-	struct dn_neigh_iter_state *state = seq->private;
-	struct neighbour *n = NULL;
-
-	for(state->bucket = 0;
-	    state->bucket <= NEIGH_HASHMASK;
-	    ++state->bucket) {
-		n = dn_neigh_table.hash_buckets[state->bucket];
-		if (n)
-			break;
-	}
+	struct elist_cb_state *s = _info;
+	struct dn_dev *dn_db;
+	struct dn_neigh *dn;
 
-	return n;
-}
+	if (neigh->dev != s->dev)
+		return;
 
-static struct neighbour *neigh_get_next(struct seq_file *seq,
-					struct neighbour *n)
-{
-	struct dn_neigh_iter_state *state = seq->private;
+	dn = (struct dn_neigh *) neigh;
+	if (!(dn->flags & (DN_NDFLAG_R1|DN_NDFLAG_R2)))
+		return;
+
+	dn_db = (struct dn_dev *) s->dev->dn_ptr;
+	if (dn_db->parms.forwarding == 1 && (dn->flags & DN_NDFLAG_R2))
+		return;
 
-	n = n->next;
-try_again:
-	if (n)
-		goto out;
-	if (++state->bucket > NEIGH_HASHMASK)
-		goto out;
-	n = dn_neigh_table.hash_buckets[state->bucket];
-	goto try_again;
-out:
-	return n;
+	if (s->t == s->n)
+		s->rs = dn_find_slot(s->ptr, s->n, dn->priority);
+	else
+		s->t++;
+	if (s->rs == NULL)
+		return;
+
+	dn_dn2eth(s->rs, dn->addr);
+	s->rs += 6;
+	*(s->rs) = neigh->nud_state & NUD_CONNECTED ? 0x80 : 0x0;
+	*(s->rs) |= dn->priority;
+	s->rs++;
 }
 
-static struct neighbour *neigh_get_idx(struct seq_file *seq, loff_t *pos)
+int dn_neigh_elist(struct net_device *dev, unsigned char *ptr, int n)
 {
-	struct neighbour *n = neigh_get_first(seq);
+	struct elist_cb_state state;
 
-	if (n)
-		while(*pos && (n = neigh_get_next(seq, n)))
-			--*pos;
-	return *pos ? NULL : n;
-}
+	state.dev = dev;
+	state.t = 0;
+	state.n = n;
+	state.ptr = ptr;
+	state.rs = ptr;
 
-static void *dn_neigh_get_idx(struct seq_file *seq, loff_t pos)
-{
-	void *rc;
-	read_lock_bh(&dn_neigh_table.lock);
-	rc = neigh_get_idx(seq, &pos);
-	if (!rc) {
-		read_unlock_bh(&dn_neigh_table.lock);
-	}
-	return rc;
-}
+	neigh_for_each(&dn_neigh_table, neigh_elist_cb, &state);
 
-static void *dn_neigh_seq_start(struct seq_file *seq, loff_t *pos)
-{
-	return *pos ? dn_neigh_get_idx(seq, *pos - 1) : SEQ_START_TOKEN;
+	return state.t;
 }
 
-static void *dn_neigh_seq_next(struct seq_file *seq, void *v, loff_t *pos)
-{
-	void *rc;
 
-
-	if (v == SEQ_START_TOKEN) {
-		rc = dn_neigh_get_idx(seq, 0);
-		goto out;
-	}
-
-	rc = neigh_get_next(seq, v);
-	if (rc)
-		goto out;
-	read_unlock_bh(&dn_neigh_table.lock);
-out:
-	++*pos;
-	return rc;
-}
-
-static void dn_neigh_seq_stop(struct seq_file *seq, void *v)
-{
-	if (v && v != SEQ_START_TOKEN)
-		read_unlock_bh(&dn_neigh_table.lock);
-}
+#ifdef CONFIG_PROC_FS
 
 static inline void dn_neigh_format_entry(struct seq_file *seq,
 					 struct neighbour *n)
 {
-	struct dn_neigh *dn = (struct dn_neigh *)n;
+	struct dn_neigh *dn = (struct dn_neigh *) n;
 	char buf[DN_ASCBUF_LEN];
 
 	read_lock(&n->lock);
@@ -662,10 +574,16 @@
 	return 0;
 }
 
+static void *dn_neigh_seq_start(struct seq_file *seq, loff_t *pos)
+{
+	return neigh_seq_start(seq, pos, &dn_neigh_table,
+			       NEIGH_SEQ_NEIGH_ONLY);
+}
+
 static struct seq_operations dn_neigh_seq_ops = {
 	.start = dn_neigh_seq_start,
-	.next  = dn_neigh_seq_next,
-	.stop  = dn_neigh_seq_stop,
+	.next  = neigh_seq_next,
+	.stop  = neigh_seq_stop,
 	.show  = dn_neigh_seq_show,
 };
 
@@ -673,11 +591,12 @@
 {
 	struct seq_file *seq;
 	int rc = -ENOMEM;
-	struct dn_neigh_iter_state *s = kmalloc(sizeof(*s), GFP_KERNEL);
+	struct neigh_seq_state *s = kmalloc(sizeof(*s), GFP_KERNEL);
 
 	if (!s)
 		goto out;
 
+	memset(s, 0, sizeof(*s));
 	rc = seq_open(file, &dn_neigh_seq_ops);
 	if (rc)
 		goto out_kfree;
diff -Nru a/net/decnet/dn_route.c b/net/decnet/dn_route.c
--- a/net/decnet/dn_route.c	2004-10-18 14:57:04 -07:00
+++ b/net/decnet/dn_route.c	2004-10-18 14:57:04 -07:00
@@ -1,4 +1,3 @@
-
 /*
  * DECnet       An implementation of the DECnet protocol suite for the LINUX
  *              operating system.  DECnet is implemented using the  BSD Socket
@@ -146,14 +145,14 @@
 
 static inline void dnrt_free(struct dn_route *rt)
 {
-	call_rcu(&rt->u.dst.rcu_head, dst_rcu_free);
+	call_rcu_bh(&rt->u.dst.rcu_head, dst_rcu_free);
 }
 
 static inline void dnrt_drop(struct dn_route *rt)
 {
 	if (rt)
 		dst_release(&rt->u.dst);
-	call_rcu(&rt->u.dst.rcu_head, dst_rcu_free);
+	call_rcu_bh(&rt->u.dst.rcu_head, dst_rcu_free);
 }
 
 static void dn_dst_check_expire(unsigned long dummy)
@@ -997,7 +996,7 @@
 		 * here
 		 */
 		if (!try_hard) {
-			neigh = dn_neigh_lookup(&dn_neigh_table, &fl.fld_dst);
+			neigh = neigh_lookup_nodev(&dn_neigh_table, &fl.fld_dst);
 			if (neigh) {
 				if ((oldflp->oif && 
 				    (neigh->dev->ifindex != oldflp->oif)) ||
@@ -1174,9 +1173,9 @@
 	struct dn_route *rt = NULL;
 
 	if (!(flags & MSG_TRYHARD)) {
-		rcu_read_lock();
-		for(rt = dn_rt_hash_table[hash].chain; rt; rt = rt->u.rt_next) {
-			read_barrier_depends();
+		rcu_read_lock_bh();
+		for(rt = rcu_dereference(dn_rt_hash_table[hash].chain); rt;
+			rt = rcu_dereference(rt->u.rt_next)) {
 			if ((flp->fld_dst == rt->fl.fld_dst) &&
 			    (flp->fld_src == rt->fl.fld_src) &&
 #ifdef CONFIG_DECNET_ROUTE_FWMARK
@@ -1187,12 +1186,12 @@
 				rt->u.dst.lastuse = jiffies;
 				dst_hold(&rt->u.dst);
 				rt->u.dst.__use++;
-				rcu_read_unlock();
+				rcu_read_unlock_bh();
 				*pprt = &rt->u.dst;
 				return 0;
 			}
 		}
-		rcu_read_unlock();
+		rcu_read_unlock_bh();
 	}
 
 	return dn_route_output_slow(pprt, flp, flags);
@@ -1454,8 +1453,8 @@
 		return 0;
 
 	rcu_read_lock();
-	for(rt = dn_rt_hash_table[hash].chain; rt != NULL; rt = rt->u.rt_next) {
-		read_barrier_depends();
+	for(rt = rcu_dereference(dn_rt_hash_table[hash].chain); rt != NULL;
+	    rt = rcu_dereference(rt->u.rt_next)) {
 		if ((rt->fl.fld_src == cb->src) &&
 	 	    (rt->fl.fld_dst == cb->dst) &&
 		    (rt->fl.oif == 0) &&
@@ -1647,21 +1646,22 @@
 			continue;
 		if (h > s_h)
 			s_idx = 0;
-		rcu_read_lock();
-		for(rt = dn_rt_hash_table[h].chain, idx = 0; rt; rt = rt->u.rt_next, idx++) {
-			read_barrier_depends();
+		rcu_read_lock_bh();
+		for(rt = rcu_dereference(dn_rt_hash_table[h].chain), idx = 0;
+			rt;
+			rt = rcu_dereference(rt->u.rt_next), idx++) {
 			if (idx < s_idx)
 				continue;
 			skb->dst = dst_clone(&rt->u.dst);
 			if (dn_rt_fill_info(skb, NETLINK_CB(cb->skb).pid,
 					cb->nlh->nlmsg_seq, RTM_NEWROUTE, 1) <= 0) {
 				dst_release(xchg(&skb->dst, NULL));
-				rcu_read_unlock();
+				rcu_read_unlock_bh();
 				goto done;
 			}
 			dst_release(xchg(&skb->dst, NULL));
 		}
-		rcu_read_unlock();
+		rcu_read_unlock_bh();
 	}
 
 done:
@@ -1681,7 +1681,7 @@
 	struct dn_rt_cache_iter_state *s = seq->private;
 
 	for(s->bucket = dn_rt_hash_mask; s->bucket >= 0; --s->bucket) {
-		rcu_read_lock();
+		rcu_read_lock_bh();
 		rt = dn_rt_hash_table[s->bucket].chain;
 		if (rt)
 			break;
@@ -1692,15 +1692,14 @@
 
 static struct dn_route *dn_rt_cache_get_next(struct seq_file *seq, struct dn_route *rt)
 {
-	struct dn_rt_cache_iter_state *s = seq->private;
+	struct dn_rt_cache_iter_state *s = rcu_dereference(seq->private);
 
-	smp_read_barrier_depends();
 	rt = rt->u.rt_next;
 	while(!rt) {
-		rcu_read_unlock();
+		rcu_read_unlock_bh();
 		if (--s->bucket < 0)
 			break;
-		rcu_read_lock();
+		rcu_read_lock_bh();
 		rt = dn_rt_hash_table[s->bucket].chain;
 	}
 	return rt;
@@ -1727,7 +1726,7 @@
 static void dn_rt_cache_seq_stop(struct seq_file *seq, void *v)
 {
 	if (v)
-		rcu_read_unlock();
+		rcu_read_unlock_bh();
 }
 
 static int dn_rt_cache_seq_show(struct seq_file *seq, void *v)
diff -Nru a/net/econet/af_econet.c b/net/econet/af_econet.c
--- a/net/econet/af_econet.c	2004-10-18 14:56:31 -07:00
+++ b/net/econet/af_econet.c	2004-10-18 14:56:31 -07:00
@@ -39,6 +39,7 @@
 #include <net/udp.h>
 #include <net/ip.h>
 #include <linux/spinlock.h>
+#include <linux/rcupdate.h>
 
 #include <asm/uaccess.h>
 #include <asm/system.h>
@@ -401,16 +402,17 @@
 	   y.x maps to IP a.b.c.x.  This should be replaced with something
 	   more flexible and more aware of subnet masks.  */
 	{
-		struct in_device *idev = in_dev_get(dev);
+		struct in_device *idev;
 		unsigned long network = 0;
+
+		rcu_read_lock();
+		idev = __in_dev_get(dev);
 		if (idev) {
-			read_lock(&idev->lock);
 			if (idev->ifa_list)
 				network = ntohl(idev->ifa_list->ifa_address) & 
 					0xffffff00;		/* !!! */
-			read_unlock(&idev->lock);
-			in_dev_put(idev);
 		}
+		rcu_read_unlock();
 		udpdest.sin_addr.s_addr = htonl(network | addr.station);
 	}
 
diff -Nru a/net/ethernet/eth.c b/net/ethernet/eth.c
--- a/net/ethernet/eth.c	2004-10-18 14:56:32 -07:00
+++ b/net/ethernet/eth.c	2004-10-18 14:56:32 -07:00
@@ -163,10 +163,8 @@
 	
 	skb->mac.raw=skb->data;
 	skb_pull(skb,ETH_HLEN);
-	eth= skb->mac.ethernet;
-#ifdef CONFIG_NET_CLS_ACT
+	eth = eth_hdr(skb);
 	skb->input_dev = dev;
-#endif
 	
 	if(*eth->h_dest&1)
 	{
@@ -212,7 +210,7 @@
 
 int eth_header_parse(struct sk_buff *skb, unsigned char *haddr)
 {
-	struct ethhdr *eth = skb->mac.ethernet;
+	struct ethhdr *eth = eth_hdr(skb);
 	memcpy(haddr, eth->h_source, ETH_ALEN);
 	return ETH_ALEN;
 }
diff -Nru a/net/ipv4/Kconfig b/net/ipv4/Kconfig
--- a/net/ipv4/Kconfig	2004-10-18 14:56:49 -07:00
+++ b/net/ipv4/Kconfig	2004-10-18 14:56:49 -07:00
@@ -60,12 +60,8 @@
 	  Normally, a router decides what to do with a received packet based
 	  solely on the packet's final destination address. If you say Y here,
 	  the Linux router will also be able to take the packet's source
-	  address into account. Furthermore, if you also say Y to "Use TOS
-	  value as routing key" below, the TOS (Type-Of-Service) field of the
-	  packet can be used for routing decisions as well. In addition, if
-	  you say Y here and to "Fast network address translation" below,
-	  the router will also be able to modify source and destination
-	  addresses of forwarded packets.
+	  address into account. Furthermore, the TOS (Type-Of-Service) field
+	  of the packet can be used for routing decisions as well.
 
 	  If you are interested in this, please see the preliminary
 	  documentation at <http://www.compendium.com.ar/policy-routing.txt>
@@ -82,16 +78,6 @@
 	  If you say Y here, you will be able to specify different routes for
 	  packets with different mark values (see iptables(8), MARK target).
 
-config IP_ROUTE_NAT
-	bool "IP: fast network address translation"
-	depends on IP_MULTIPLE_TABLES
-	help
-	  If you say Y here, your router will be able to modify source and
-	  destination addresses of packets that pass through it, in a manner
-	  you specify.  General information about Network Address Translation
-	  can be gotten from the document
-	  <http://www.hasenstein.com/linux-ip-nat/diplom/nat.html>.
-
 config IP_ROUTE_MULTIPATH
 	bool "IP: equal cost multipath"
 	depends on IP_ADVANCED_ROUTER
@@ -104,16 +90,6 @@
 	  equal "cost" and chooses one of them in a non-deterministic fashion
 	  if a matching packet arrives.
 
-config IP_ROUTE_TOS
-	bool "IP: use TOS value as routing key"
-	depends on IP_ADVANCED_ROUTER
-	help
-	  The header of every IP packet carries a TOS (Type Of Service) value
-	  with which the packet requests a certain treatment, e.g. low
-	  latency (for interactive traffic), high throughput, or high
-	  reliability.  If you say Y here, you will be able to specify
-	  different routes for packets with different TOS values.
-
 config IP_ROUTE_VERBOSE
 	bool "IP: verbose route monitoring"
 	depends on IP_ADVANCED_ROUTER
@@ -187,7 +163,7 @@
 config NET_IPIP
 	tristate "IP: tunneling"
 	depends on INET
-	select XFRM
+	select INET_TUNNEL
 	---help---
 	  Tunneling means encapsulating data of one protocol type within
 	  another protocol and sending it over a channel that understands the
@@ -351,11 +327,21 @@
 config INET_IPCOMP
 	tristate "IP: IPComp transformation"
 	select XFRM
+	select INET_TUNNEL
 	select CRYPTO
 	select CRYPTO_DEFLATE
 	---help---
 	  Support for IP Paylod Compression (RFC3173), typically needed
 	  for IPsec.
+	  
+	  If unsure, say Y.
+
+config INET_TUNNEL
+	tristate "IP: tunnel transformation"
+	select XFRM
+	---help---
+	  Support for generic IP tunnel transformation, which is required by
+	  the IP tunneling module as well as tunnel mode IPComp.
 	  
 	  If unsure, say Y.
 
diff -Nru a/net/ipv4/Makefile b/net/ipv4/Makefile
--- a/net/ipv4/Makefile	2004-10-18 14:56:20 -07:00
+++ b/net/ipv4/Makefile	2004-10-18 14:56:20 -07:00
@@ -11,7 +11,6 @@
 
 obj-$(CONFIG_PROC_FS) += proc.o
 obj-$(CONFIG_IP_MULTIPLE_TABLES) += fib_rules.o
-obj-$(CONFIG_IP_ROUTE_NAT) += ip_nat_dumb.o
 obj-$(CONFIG_IP_MROUTE) += ipmr.o
 obj-$(CONFIG_NET_IPIP) += ipip.o
 obj-$(CONFIG_NET_IPGRE) += ip_gre.o
@@ -19,9 +18,10 @@
 obj-$(CONFIG_INET_AH) += ah4.o
 obj-$(CONFIG_INET_ESP) += esp4.o
 obj-$(CONFIG_INET_IPCOMP) += ipcomp.o
+obj-$(CONFIG_INET_TUNNEL) += xfrm4_tunnel.o 
 obj-$(CONFIG_IP_PNP) += ipconfig.o
 obj-$(CONFIG_NETFILTER)	+= netfilter/
 obj-$(CONFIG_IP_VS) += ipvs/
 
 obj-$(CONFIG_XFRM) += xfrm4_policy.o xfrm4_state.o xfrm4_input.o \
-		      xfrm4_tunnel.o xfrm4_output.o
+		      xfrm4_output.o
diff -Nru a/net/ipv4/af_inet.c b/net/ipv4/af_inet.c
--- a/net/ipv4/af_inet.c	2004-10-18 14:55:55 -07:00
+++ b/net/ipv4/af_inet.c	2004-10-18 14:55:55 -07:00
@@ -121,11 +121,6 @@
 
 extern void ip_mc_drop_socket(struct sock *sk);
 
-/* Per protocol sock slabcache */
-kmem_cache_t *tcp_sk_cachep;
-static kmem_cache_t *udp_sk_cachep;
-static kmem_cache_t *raw4_sk_cachep;
-
 /* The inetsw table contains everything that inet_create needs to
  * build a new socket.
  */
@@ -228,28 +223,6 @@
 	return err;
 }
 
-static __inline__ kmem_cache_t *inet_sk_slab(int protocol)
-{
-	kmem_cache_t* rc = tcp_sk_cachep;
-
-	if (protocol == IPPROTO_UDP)
-		rc = udp_sk_cachep;
-	else if (protocol == IPPROTO_RAW)
-		rc = raw4_sk_cachep;
-	return rc;
-}
-
-static __inline__ int inet_sk_size(int protocol)
-{
-	int rc = sizeof(struct tcp_sock);
-
-	if (protocol == IPPROTO_UDP)
-		rc = sizeof(struct udp_sock);
-	else if (protocol == IPPROTO_RAW)
-		rc = sizeof(struct raw_sock);
-	return rc;
-}
-
 /*
  *	Create an inet socket.
  */
@@ -260,13 +233,12 @@
 	struct list_head *p;
 	struct inet_protosw *answer;
 	struct inet_opt *inet;
-	int err = -ENOBUFS;
+	struct proto *answer_prot;
+	unsigned char answer_flags;
+	char answer_no_check;
+	int err;
 
 	sock->state = SS_UNCONNECTED;
-	sk = sk_alloc(PF_INET, GFP_KERNEL, inet_sk_size(protocol),
-		      inet_sk_slab(protocol));
-	if (!sk)
-		goto out;
 
 	/* Look for the requested type/protocol pair. */
 	answer = NULL;
@@ -292,21 +264,35 @@
 
 	err = -ESOCKTNOSUPPORT;
 	if (!answer)
-		goto out_sk_free;
+		goto out_rcu_unlock;
 	err = -EPERM;
 	if (answer->capability > 0 && !capable(answer->capability))
-		goto out_sk_free;
+		goto out_rcu_unlock;
 	err = -EPROTONOSUPPORT;
 	if (!protocol)
-		goto out_sk_free;
-	err = 0;
+		goto out_rcu_unlock;
+
 	sock->ops = answer->ops;
-	sk->sk_prot = answer->prot;
-	sk->sk_no_check = answer->no_check;
-	if (INET_PROTOSW_REUSE & answer->flags)
-		sk->sk_reuse = 1;
+	answer_prot = answer->prot;
+	answer_no_check = answer->no_check;
+	answer_flags = answer->flags;
 	rcu_read_unlock();
 
+	BUG_TRAP(answer_prot->slab != NULL);
+
+	err = -ENOBUFS;
+	sk = sk_alloc(PF_INET, GFP_KERNEL,
+		      answer_prot->slab_obj_size,
+		      answer_prot->slab);
+	if (sk == NULL)
+		goto out;
+
+	err = 0;
+	sk->sk_prot = answer_prot;
+	sk->sk_no_check = answer_no_check;
+	if (INET_PROTOSW_REUSE & answer_flags)
+		sk->sk_reuse = 1;
+
 	inet = inet_sk(sk);
 
 	if (SOCK_RAW == sock->type) {
@@ -326,7 +312,6 @@
 	sk_set_owner(sk, THIS_MODULE);
 
 	sk->sk_destruct	   = inet_sock_destruct;
-	sk->sk_zapped	   = 0;
 	sk->sk_family	   = PF_INET;
 	sk->sk_protocol	   = protocol;
 	sk->sk_backlog_rcv = sk->sk_prot->backlog_rcv;
@@ -359,9 +344,8 @@
 	}
 out:
 	return err;
-out_sk_free:
+out_rcu_unlock:
 	rcu_read_unlock();
-	sk_free(sk);
 	goto out;
 }
 
@@ -837,7 +821,7 @@
 	.sendpage =	inet_sendpage,
 };
 
-struct net_proto_family inet_family_ops = {
+static struct net_proto_family inet_family_ops = {
 	.family = PF_INET,
 	.create = inet_create,
 	.owner	= THIS_MODULE,
@@ -1010,24 +994,29 @@
 	struct sk_buff *dummy_skb;
 	struct inet_protosw *q;
 	struct list_head *r;
+	int rc = -EINVAL;
 
 	if (sizeof(struct inet_skb_parm) > sizeof(dummy_skb->cb)) {
 		printk(KERN_CRIT "%s: panic\n", __FUNCTION__);
-		return -EINVAL;
+		goto out;
+	}
+
+	rc = sk_alloc_slab(&tcp_prot, "tcp_sock");
+	if (rc) {
+		sk_alloc_slab_error(&tcp_prot);
+		goto out;
+	}
+	rc = sk_alloc_slab(&udp_prot, "udp_sock");
+	if (rc) {
+		sk_alloc_slab_error(&udp_prot);
+		goto out_tcp_free_slab;
+	}
+	rc = sk_alloc_slab(&raw_prot, "raw_sock");
+	if (rc) {
+		sk_alloc_slab_error(&raw_prot);
+		goto out_udp_free_slab;
 	}
 
-	tcp_sk_cachep = kmem_cache_create("tcp_sock",
-					  sizeof(struct tcp_sock), 0,
-					  SLAB_HWCACHE_ALIGN, NULL, NULL);
-	udp_sk_cachep = kmem_cache_create("udp_sock",
-					  sizeof(struct udp_sock), 0,
-					  SLAB_HWCACHE_ALIGN, NULL, NULL);
-	raw4_sk_cachep = kmem_cache_create("raw4_sock",
-					   sizeof(struct raw_sock), 0,
-					   SLAB_HWCACHE_ALIGN, NULL, NULL);
-	if (!tcp_sk_cachep || !udp_sk_cachep || !raw4_sk_cachep)
-		printk(KERN_CRIT
-		       "inet_init: Can't create protocol sock SLAB caches!\n");
 	/*
 	 *	Tell SOCKET that we are alive... 
 	 */
@@ -1097,7 +1086,14 @@
 
 	ipfrag_init();
 
-	return 0;
+	rc = 0;
+out:
+	return rc;
+out_tcp_free_slab:
+	sk_free_slab(&tcp_prot);
+out_udp_free_slab:
+	sk_free_slab(&udp_prot);
+	goto out;
 }
 
 module_init(inet_init);
@@ -1157,7 +1153,6 @@
 EXPORT_SYMBOL(inet_bind);
 EXPORT_SYMBOL(inet_dgram_connect);
 EXPORT_SYMBOL(inet_dgram_ops);
-EXPORT_SYMBOL(inet_family_ops);
 EXPORT_SYMBOL(inet_getname);
 EXPORT_SYMBOL(inet_ioctl);
 EXPORT_SYMBOL(inet_listen);
diff -Nru a/net/ipv4/ah4.c b/net/ipv4/ah4.c
--- a/net/ipv4/ah4.c	2004-10-18 14:56:50 -07:00
+++ b/net/ipv4/ah4.c	2004-10-18 14:56:50 -07:00
@@ -53,10 +53,10 @@
 	return 0;
 }
 
-static int ah_output(struct sk_buff **pskb)
+static int ah_output(struct sk_buff *skb)
 {
 	int err;
-	struct dst_entry *dst = (*pskb)->dst;
+	struct dst_entry *dst = skb->dst;
 	struct xfrm_state *x  = dst->xfrm;
 	struct iphdr *iph, *top_iph;
 	struct ip_auth_hdr *ah;
@@ -66,7 +66,7 @@
 		char 		buf[60];
 	} tmp_iph;
 
-	top_iph = (*pskb)->nh.iph;
+	top_iph = skb->nh.iph;
 	iph = &tmp_iph.iph;
 
 	iph->tos = top_iph->tos;
@@ -85,7 +85,7 @@
 	ah->nexthdr = top_iph->protocol;
 
 	top_iph->tos = 0;
-	top_iph->tot_len = htons((*pskb)->len);
+	top_iph->tot_len = htons(skb->len);
 	top_iph->frag_off = 0;
 	top_iph->ttl = 0;
 	top_iph->protocol = IPPROTO_AH;
@@ -98,7 +98,7 @@
 	ah->reserved = 0;
 	ah->spi = x->id.spi;
 	ah->seq_no = htonl(++x->replay.oseq);
-	ahp->icv(ahp, *pskb, ah->auth_data);
+	ahp->icv(ahp, skb, ah->auth_data);
 
 	top_iph->tos = iph->tos;
 	top_iph->ttl = iph->ttl;
@@ -116,7 +116,7 @@
 	return err;
 }
 
-int ah_input(struct xfrm_state *x, struct xfrm_decap_state *decap, struct sk_buff *skb)
+static int ah_input(struct xfrm_state *x, struct xfrm_decap_state *decap, struct sk_buff *skb)
 {
 	int ah_hlen;
 	struct iphdr *iph;
@@ -184,7 +184,7 @@
 	return -EINVAL;
 }
 
-void ah4_err(struct sk_buff *skb, u32 info)
+static void ah4_err(struct sk_buff *skb, u32 info)
 {
 	struct iphdr *iph = (struct iphdr*)skb->data;
 	struct ip_auth_hdr *ah = (struct ip_auth_hdr*)(skb->data+(iph->ihl<<2));
@@ -212,6 +212,9 @@
 
 	/* null auth can use a zero length key */
 	if (x->aalg->alg_key_len > 512)
+		goto error;
+
+	if (x->encap)
 		goto error;
 
 	ahp = kmalloc(sizeof(*ahp), GFP_KERNEL);
diff -Nru a/net/ipv4/arp.c b/net/ipv4/arp.c
--- a/net/ipv4/arp.c	2004-10-18 14:56:50 -07:00
+++ b/net/ipv4/arp.c	2004-10-18 14:56:50 -07:00
@@ -71,6 +71,7 @@
  *					arp_xmit so intermediate drivers like
  *					bonding can change the skb before
  *					sending (e.g. insert 8021q tag).
+ *		Harald Welte	:	convert to make use of jenkins hash
  */
 
 #include <linux/module.h>
@@ -96,6 +97,8 @@
 #include <linux/stat.h>
 #include <linux/init.h>
 #include <linux/net.h>
+#include <linux/rcupdate.h>
+#include <linux/jhash.h>
 #ifdef CONFIG_SYSCTL
 #include <linux/sysctl.h>
 #endif
@@ -222,31 +225,29 @@
 
 static u32 arp_hash(const void *pkey, const struct net_device *dev)
 {
-	u32 hash_val;
-
-	hash_val = *(u32*)pkey;
-	hash_val ^= (hash_val>>16);
-	hash_val ^= hash_val>>8;
-	hash_val ^= hash_val>>3;
-	hash_val = (hash_val^dev->ifindex)&NEIGH_HASHMASK;
-
-	return hash_val;
+	return jhash_2words(*(u32 *)pkey, dev->ifindex, arp_tbl.hash_rnd);
 }
 
 static int arp_constructor(struct neighbour *neigh)
 {
 	u32 addr = *(u32*)neigh->primary_key;
 	struct net_device *dev = neigh->dev;
-	struct in_device *in_dev = in_dev_get(dev);
-
-	if (in_dev == NULL)
-		return -EINVAL;
+	struct in_device *in_dev;
+	struct neigh_parms *parms;
 
 	neigh->type = inet_addr_type(addr);
-	if (in_dev->arp_parms)
-		neigh->parms = in_dev->arp_parms;
 
-	in_dev_put(in_dev);
+	rcu_read_lock();
+	in_dev = rcu_dereference(__in_dev_get(dev));
+	if (in_dev == NULL) {
+		rcu_read_unlock();
+		return -EINVAL;
+	}
+
+	parms = in_dev->arp_parms;
+	__neigh_parms_put(neigh->parms);
+	neigh->parms = neigh_parms_clone(parms);
+	rcu_read_unlock();
 
 	if (dev->hard_header == NULL) {
 		neigh->nud_state = NUD_NOARP;
@@ -695,6 +696,7 @@
 
 static void parp_redo(struct sk_buff *skb)
 {
+	nf_reset(skb);
 	arp_rcv(skb, skb->dev, NULL);
 }
 
@@ -906,7 +908,7 @@
 		if (arp->ar_op != htons(ARPOP_REPLY) ||
 		    skb->pkt_type != PACKET_HOST)
 			state = NUD_STALE;
-		neigh_update(n, sha, state, override, 1);
+		neigh_update(n, sha, state, override ? NEIGH_UPDATE_F_OVERRIDE : 0);
 		neigh_release(n);
 	}
 
@@ -1003,8 +1005,26 @@
 		if (!dev)
 			return -EINVAL;
 	}
-	if (r->arp_ha.sa_family != dev->type)	
-		return -EINVAL;
+	switch (dev->type) {
+#ifdef CONFIG_FDDI
+	case ARPHRD_FDDI:
+		/*
+		 * According to RFC 1390, FDDI devices should accept ARP
+		 * hardware types of 1 (Ethernet).  However, to be more
+		 * robust, we'll accept hardware types of either 1 (Ethernet)
+		 * or 6 (IEEE 802.2).
+		 */
+		if (r->arp_ha.sa_family != ARPHRD_FDDI &&
+		    r->arp_ha.sa_family != ARPHRD_ETHER &&
+		    r->arp_ha.sa_family != ARPHRD_IEEE802)
+			return -EINVAL;
+		break;
+#endif
+	default:
+		if (r->arp_ha.sa_family != dev->type)
+			return -EINVAL;
+		break;
+	}
 
 	neigh = __neigh_lookup_errno(&arp_tbl, &ip, dev);
 	err = PTR_ERR(neigh);
@@ -1013,7 +1033,9 @@
 		if (r->arp_flags & ATF_PERM)
 			state = NUD_PERMANENT;
 		err = neigh_update(neigh, (r->arp_flags&ATF_COM) ?
-				   r->arp_ha.sa_data : NULL, state, 1, 0);
+				   r->arp_ha.sa_data : NULL, state, 
+				   NEIGH_UPDATE_F_OVERRIDE|
+				   NEIGH_UPDATE_F_ADMIN);
 		neigh_release(neigh);
 	}
 	return err;
@@ -1093,7 +1115,9 @@
 	neigh = neigh_lookup(&arp_tbl, &ip, dev);
 	if (neigh) {
 		if (neigh->nud_state&~NUD_NOARP)
-			err = neigh_update(neigh, NULL, NUD_FAILED, 1, 0);
+			err = neigh_update(neigh, NULL, NUD_FAILED, 
+					   NEIGH_UPDATE_F_OVERRIDE|
+					   NEIGH_UPDATE_F_ADMIN);
 		neigh_release(neigh);
 	}
 	return err;
@@ -1257,162 +1281,10 @@
 }
 #endif /* CONFIG_AX25 */
 
-struct arp_iter_state {
-	int is_pneigh, bucket;
-};
-
-static struct neighbour *neigh_get_first(struct seq_file *seq)
-{
-	struct arp_iter_state* state = seq->private;
-	struct neighbour *n = NULL;
-
-	state->is_pneigh = 0;
-
-	for (state->bucket = 0;
-	     state->bucket <= NEIGH_HASHMASK;
-	     ++state->bucket) {
-		n = arp_tbl.hash_buckets[state->bucket];
-		while (n && !(n->nud_state & ~NUD_NOARP))
-			n = n->next;
-		if (n)
-			break;
-	}
-
-	return n;
-}
-
-static struct neighbour *neigh_get_next(struct seq_file *seq,
-					struct neighbour *n)
-{
-	struct arp_iter_state* state = seq->private;
-
-	do {
-		n = n->next;
-		/* Don't confuse "arp -a" w/ magic entries */
-try_again:
-		;
-	} while (n && !(n->nud_state & ~NUD_NOARP));
-
-	if (n)
-		goto out;
-	if (++state->bucket > NEIGH_HASHMASK)
-		goto out;
-	n = arp_tbl.hash_buckets[state->bucket];
-	goto try_again;
-out:
-	return n;
-}
-
-static struct neighbour *neigh_get_idx(struct seq_file *seq, loff_t *pos)
-{
-	struct neighbour *n = neigh_get_first(seq);
-
-	if (n)
-		while (*pos && (n = neigh_get_next(seq, n)))
-			--*pos;
-	return *pos ? NULL : n;
-}
-
-static struct pneigh_entry *pneigh_get_first(struct seq_file *seq)
-{
-	struct arp_iter_state* state = seq->private;
-	struct pneigh_entry *pn;
-
-	state->is_pneigh = 1;
-
-	for (state->bucket = 0;
-	     state->bucket <= PNEIGH_HASHMASK;
-	     ++state->bucket) {
-		pn = arp_tbl.phash_buckets[state->bucket];
-		if (pn)
-			break;
-	}
-	return pn;
-}
-
-static struct pneigh_entry *pneigh_get_next(struct seq_file *seq,
-					    struct pneigh_entry *pn)
-{
-	struct arp_iter_state* state = seq->private;
-
-	pn = pn->next;
-	while (!pn) {
-		if (++state->bucket > PNEIGH_HASHMASK)
-			break;
-		pn = arp_tbl.phash_buckets[state->bucket];
-	}
-	return pn;
-}
-
-static struct pneigh_entry *pneigh_get_idx(struct seq_file *seq, loff_t pos)
-{
-	struct pneigh_entry *pn = pneigh_get_first(seq);
-
-	if (pn)
-		while (pos && (pn = pneigh_get_next(seq, pn)))
-			--pos;
-	return pos ? NULL : pn;
-}
-
-static void *arp_get_idx(struct seq_file *seq, loff_t pos)
-{
-	void *rc;
-
-	read_lock_bh(&arp_tbl.lock);
-	rc = neigh_get_idx(seq, &pos);
-
-	if (!rc) {
-		read_unlock_bh(&arp_tbl.lock);
-		rc = pneigh_get_idx(seq, pos);
-	}
-	return rc;
-}
-
-static void *arp_seq_start(struct seq_file *seq, loff_t *pos)
-{
-	struct arp_iter_state* state = seq->private;
-
-	state->is_pneigh = 0;
-	state->bucket = 0;
-	return *pos ? arp_get_idx(seq, *pos - 1) : SEQ_START_TOKEN;
-}
-
-static void *arp_seq_next(struct seq_file *seq, void *v, loff_t *pos)
-{
-	void *rc;
-	struct arp_iter_state* state;
-
-	if (v == SEQ_START_TOKEN) {
-		rc = arp_get_idx(seq, 0);
-		goto out;
-	}
-
-	state = seq->private;
-	if (!state->is_pneigh) {
-		rc = neigh_get_next(seq, v);
-		if (rc)
-			goto out;
-		read_unlock_bh(&arp_tbl.lock);
-		rc = pneigh_get_first(seq);
-	} else
-		rc = pneigh_get_next(seq, v);
-out:
-	++*pos;
-	return rc;
-}
-
-static void arp_seq_stop(struct seq_file *seq, void *v)
-{
-	struct arp_iter_state* state = seq->private;
-
-	if (!state->is_pneigh && v != SEQ_START_TOKEN)
-		read_unlock_bh(&arp_tbl.lock);
-}
-
 #define HBUFFERLEN 30
 
-static __inline__ void arp_format_neigh_entry(struct seq_file *seq,
-					      struct neighbour *n)
+static void arp_format_neigh_entry(struct seq_file *seq,
+				   struct neighbour *n)
 {
 	char hbuffer[HBUFFERLEN];
 	const char hexbuf[] = "0123456789ABCDEF";
@@ -1443,8 +1315,8 @@
 	read_unlock(&n->lock);
 }
 
-static __inline__ void arp_format_pneigh_entry(struct seq_file *seq,
-					       struct pneigh_entry *n)
+static void arp_format_pneigh_entry(struct seq_file *seq,
+				    struct pneigh_entry *n)
 {
 	struct net_device *dev = n->dev;
 	int hatype = dev ? dev->type : 0;
@@ -1458,13 +1330,13 @@
 
 static int arp_seq_show(struct seq_file *seq, void *v)
 {
-	if (v == SEQ_START_TOKEN)
+	if (v == SEQ_START_TOKEN) {
 		seq_puts(seq, "IP address       HW type     Flags       "
 			      "HW address            Mask     Device\n");
-	else {
-		struct arp_iter_state* state = seq->private;
+	} else {
+		struct neigh_seq_state *state = seq->private;
 
-		if (state->is_pneigh)
+		if (state->flags & NEIGH_SEQ_IS_PNEIGH)
 			arp_format_pneigh_entry(seq, v);
 		else
 			arp_format_neigh_entry(seq, v);
@@ -1473,12 +1345,20 @@
 	return 0;
 }
 
+static void *arp_seq_start(struct seq_file *seq, loff_t *pos)
+{
+	/* Don't want to confuse "arp -a" w/ magic entries,
+	 * so we tell the generic iterator to skip NUD_NOARP.
+	 */
+	return neigh_seq_start(seq, pos, &arp_tbl, NEIGH_SEQ_SKIP_NOARP);
+}
+
 /* ------------------------------------------------------------------------ */
 
 static struct seq_operations arp_seq_ops = {
 	.start  = arp_seq_start,
-	.next   = arp_seq_next,
-	.stop   = arp_seq_stop,
+	.next   = neigh_seq_next,
+	.stop   = neigh_seq_stop,
 	.show   = arp_seq_show,
 };
 
@@ -1486,11 +1366,12 @@
 {
 	struct seq_file *seq;
 	int rc = -ENOMEM;
-	struct arp_iter_state *s = kmalloc(sizeof(*s), GFP_KERNEL);
+	struct neigh_seq_state *s = kmalloc(sizeof(*s), GFP_KERNEL);
        
 	if (!s)
 		goto out;
 
+	memset(s, 0, sizeof(*s));
 	rc = seq_open(file, &arp_seq_ops);
 	if (rc)
 		goto out_kfree;
diff -Nru a/net/ipv4/devinet.c b/net/ipv4/devinet.c
--- a/net/ipv4/devinet.c	2004-10-18 14:56:20 -07:00
+++ b/net/ipv4/devinet.c	2004-10-18 14:56:20 -07:00
@@ -88,31 +88,31 @@
 static void devinet_sysctl_unregister(struct ipv4_devconf *p);
 #endif
 
-int inet_ifa_count;
-int inet_dev_count;
-
 /* Locks all the inet devices. */
 
-rwlock_t inetdev_lock = RW_LOCK_UNLOCKED;
-
 static struct in_ifaddr *inet_alloc_ifa(void)
 {
 	struct in_ifaddr *ifa = kmalloc(sizeof(*ifa), GFP_KERNEL);
 
 	if (ifa) {
 		memset(ifa, 0, sizeof(*ifa));
-		inet_ifa_count++;
+		INIT_RCU_HEAD(&ifa->rcu_head);
 	}
 
 	return ifa;
 }
 
-static __inline__ void inet_free_ifa(struct in_ifaddr *ifa)
+static void inet_rcu_free_ifa(struct rcu_head *head)
 {
+	struct in_ifaddr *ifa = container_of(head, struct in_ifaddr, rcu_head);
 	if (ifa->ifa_dev)
-		__in_dev_put(ifa->ifa_dev);
+		in_dev_put(ifa->ifa_dev);
 	kfree(ifa);
-	inet_ifa_count--;
+}
+
+static inline void inet_free_ifa(struct in_ifaddr *ifa)
+{
+	call_rcu(&ifa->rcu_head, inet_rcu_free_ifa);
 }
 
 void in_dev_finish_destroy(struct in_device *idev)
@@ -129,7 +129,6 @@
 	if (!idev->dead)
 		printk("Freeing alive in_device %p\n", idev);
 	else {
-		inet_dev_count--;
 		kfree(idev);
 	}
 }
@@ -144,24 +143,24 @@
 	if (!in_dev)
 		goto out;
 	memset(in_dev, 0, sizeof(*in_dev));
-	in_dev->lock = RW_LOCK_UNLOCKED;
+	INIT_RCU_HEAD(&in_dev->rcu_head);
 	memcpy(&in_dev->cnf, &ipv4_devconf_dflt, sizeof(in_dev->cnf));
 	in_dev->cnf.sysctl = NULL;
 	in_dev->dev = dev;
 	if ((in_dev->arp_parms = neigh_parms_alloc(dev, &arp_tbl)) == NULL)
 		goto out_kfree;
-	inet_dev_count++;
 	/* Reference in_dev->dev */
 	dev_hold(dev);
 #ifdef CONFIG_SYSCTL
 	neigh_sysctl_register(dev, in_dev->arp_parms, NET_IPV4,
 			      NET_IPV4_NEIGH, "ipv4", NULL);
 #endif
-	write_lock_bh(&inetdev_lock);
-	dev->ip_ptr = in_dev;
+
 	/* Account for reference dev->ip_ptr */
 	in_dev_hold(in_dev);
-	write_unlock_bh(&inetdev_lock);
+	smp_wmb();
+	dev->ip_ptr = in_dev;
+
 #ifdef CONFIG_SYSCTL
 	devinet_sysctl_register(in_dev, &in_dev->cnf);
 #endif
@@ -176,9 +175,16 @@
 	goto out;
 }
 
+static void in_dev_rcu_put(struct rcu_head *head)
+{
+	struct in_device *idev = container_of(head, struct in_device, rcu_head);
+	in_dev_put(idev);
+}
+
 static void inetdev_destroy(struct in_device *in_dev)
 {
 	struct in_ifaddr *ifa;
+	struct net_device *dev;
 
 	ASSERT_RTNL();
 
@@ -194,30 +200,31 @@
 #ifdef CONFIG_SYSCTL
 	devinet_sysctl_unregister(&in_dev->cnf);
 #endif
-	write_lock_bh(&inetdev_lock);
-	in_dev->dev->ip_ptr = NULL;
-	/* in_dev_put following below will kill the in_device */
-	write_unlock_bh(&inetdev_lock);
+
+	dev = in_dev->dev;
+	dev->ip_ptr = NULL;
 
 #ifdef CONFIG_SYSCTL
 	neigh_sysctl_unregister(in_dev->arp_parms);
 #endif
 	neigh_parms_release(&arp_tbl, in_dev->arp_parms);
-	in_dev_put(in_dev);
+	arp_ifdown(dev);
+
+	call_rcu(&in_dev->rcu_head, in_dev_rcu_put);
 }
 
 int inet_addr_onlink(struct in_device *in_dev, u32 a, u32 b)
 {
-	read_lock(&in_dev->lock);
+	rcu_read_lock();
 	for_primary_ifa(in_dev) {
 		if (inet_ifa_match(a, ifa)) {
 			if (!b || inet_ifa_match(b, ifa)) {
-				read_unlock(&in_dev->lock);
+				rcu_read_unlock();
 				return 1;
 			}
 		}
 	} endfor_ifa(in_dev);
-	read_unlock(&in_dev->lock);
+	rcu_read_unlock();
 	return 0;
 }
 
@@ -241,9 +248,8 @@
 				ifap1 = &ifa->ifa_next;
 				continue;
 			}
-			write_lock_bh(&in_dev->lock);
+
 			*ifap1 = ifa->ifa_next;
-			write_unlock_bh(&in_dev->lock);
 
 			rtmsg_ifa(RTM_DELADDR, ifa);
 			notifier_call_chain(&inetaddr_chain, NETDEV_DOWN, ifa);
@@ -253,9 +259,7 @@
 
 	/* 2. Unlink it */
 
-	write_lock_bh(&in_dev->lock);
 	*ifap = ifa1->ifa_next;
-	write_unlock_bh(&in_dev->lock);
 
 	/* 3. Announce address deletion */
 
@@ -317,9 +321,7 @@
 	}
 
 	ifa->ifa_next = *ifap;
-	write_lock_bh(&in_dev->lock);
 	*ifap = ifa;
-	write_unlock_bh(&in_dev->lock);
 
 	/* Send message first, then call notifier.
 	   Notifier will trigger FIB update, so that
@@ -771,12 +773,11 @@
 	u32 addr = 0;
 	struct in_device *in_dev;
 
-	read_lock(&inetdev_lock);
+	rcu_read_lock();
 	in_dev = __in_dev_get(dev);
 	if (!in_dev)
-		goto out_unlock_inetdev;
+		goto no_in_dev;
 
-	read_lock(&in_dev->lock);
 	for_primary_ifa(in_dev) {
 		if (ifa->ifa_scope > scope)
 			continue;
@@ -787,8 +788,8 @@
 		if (!addr)
 			addr = ifa->ifa_local;
 	} endfor_ifa(in_dev);
-	read_unlock(&in_dev->lock);
-	read_unlock(&inetdev_lock);
+no_in_dev:
+	rcu_read_unlock();
 
 	if (addr)
 		goto out;
@@ -798,30 +799,24 @@
 	   in dev_base list.
 	 */
 	read_lock(&dev_base_lock);
-	read_lock(&inetdev_lock);
+	rcu_read_lock();
 	for (dev = dev_base; dev; dev = dev->next) {
 		if ((in_dev = __in_dev_get(dev)) == NULL)
 			continue;
 
-		read_lock(&in_dev->lock);
 		for_primary_ifa(in_dev) {
 			if (ifa->ifa_scope != RT_SCOPE_LINK &&
 			    ifa->ifa_scope <= scope) {
-				read_unlock(&in_dev->lock);
 				addr = ifa->ifa_local;
 				goto out_unlock_both;
 			}
 		} endfor_ifa(in_dev);
-		read_unlock(&in_dev->lock);
 	}
 out_unlock_both:
-	read_unlock(&inetdev_lock);
 	read_unlock(&dev_base_lock);
+	rcu_read_unlock();
 out:
 	return addr;
-out_unlock_inetdev:
-	read_unlock(&inetdev_lock);
-	goto out;
 }
 
 static u32 confirm_addr_indev(struct in_device *in_dev, u32 dst,
@@ -874,29 +869,24 @@
 	struct in_device *in_dev;
 
 	if (dev) {
-		read_lock(&inetdev_lock);
-		if ((in_dev = __in_dev_get(dev))) {
-			read_lock(&in_dev->lock);
+		rcu_read_lock();
+		if ((in_dev = __in_dev_get(dev)))
 			addr = confirm_addr_indev(in_dev, dst, local, scope);
-			read_unlock(&in_dev->lock);
-		}
-		read_unlock(&inetdev_lock);
+		rcu_read_unlock();
 
 		return addr;
 	}
 
 	read_lock(&dev_base_lock);
-	read_lock(&inetdev_lock);
+	rcu_read_lock();
 	for (dev = dev_base; dev; dev = dev->next) {
 		if ((in_dev = __in_dev_get(dev))) {
-			read_lock(&in_dev->lock);
 			addr = confirm_addr_indev(in_dev, dst, local, scope);
-			read_unlock(&in_dev->lock);
 			if (addr)
 				break;
 		}
 	}
-	read_unlock(&inetdev_lock);
+	rcu_read_unlock();
 	read_unlock(&dev_base_lock);
 
 	return addr;
@@ -1065,12 +1055,12 @@
 			continue;
 		if (idx > s_idx)
 			s_ip_idx = 0;
-		read_lock(&inetdev_lock);
+		rcu_read_lock();
 		if ((in_dev = __in_dev_get(dev)) == NULL) {
-			read_unlock(&inetdev_lock);
+			rcu_read_unlock();
 			continue;
 		}
-		read_lock(&in_dev->lock);
+
 		for (ifa = in_dev->ifa_list, ip_idx = 0; ifa;
 		     ifa = ifa->ifa_next, ip_idx++) {
 			if (ip_idx < s_ip_idx)
@@ -1078,13 +1068,11 @@
 			if (inet_fill_ifaddr(skb, ifa, NETLINK_CB(cb->skb).pid,
 					     cb->nlh->nlmsg_seq,
 					     RTM_NEWADDR) <= 0) {
-				read_unlock(&in_dev->lock);
-				read_unlock(&inetdev_lock);
+				rcu_read_unlock();
 				goto done;
 			}
 		}
-		read_unlock(&in_dev->lock);
-		read_unlock(&inetdev_lock);
+		rcu_read_unlock();
 	}
 
 done:
@@ -1138,11 +1126,11 @@
 	read_lock(&dev_base_lock);
 	for (dev = dev_base; dev; dev = dev->next) {
 		struct in_device *in_dev;
-		read_lock(&inetdev_lock);
+		rcu_read_lock();
 		in_dev = __in_dev_get(dev);
 		if (in_dev)
 			in_dev->cnf.forwarding = on;
-		read_unlock(&inetdev_lock);
+		rcu_read_unlock();
 	}
 	read_unlock(&dev_base_lock);
 
@@ -1508,6 +1496,5 @@
 EXPORT_SYMBOL(in_dev_finish_destroy);
 EXPORT_SYMBOL(inet_select_addr);
 EXPORT_SYMBOL(inetdev_by_index);
-EXPORT_SYMBOL(inetdev_lock);
 EXPORT_SYMBOL(register_inetaddr_notifier);
 EXPORT_SYMBOL(unregister_inetaddr_notifier);
diff -Nru a/net/ipv4/esp4.c b/net/ipv4/esp4.c
--- a/net/ipv4/esp4.c	2004-10-18 14:56:33 -07:00
+++ b/net/ipv4/esp4.c	2004-10-18 14:56:33 -07:00
@@ -17,10 +17,10 @@
 	__u8		proto;
 };
 
-int esp_output(struct sk_buff **pskb)
+static int esp_output(struct sk_buff *skb)
 {
 	int err;
-	struct dst_entry *dst = (*pskb)->dst;
+	struct dst_entry *dst = skb->dst;
 	struct xfrm_state *x  = dst->xfrm;
 	struct iphdr *top_iph;
 	struct ip_esp_hdr *esph;
@@ -33,13 +33,13 @@
 	int nfrags;
 
 	/* Strip IP+ESP header. */
-	__skb_pull(*pskb, (*pskb)->h.raw - (*pskb)->data);
+	__skb_pull(skb, skb->h.raw - skb->data);
 	/* Now skb is pure payload to encrypt */
 
 	err = -ENOMEM;
 
 	/* Round to block size */
-	clen = (*pskb)->len;
+	clen = skb->len;
 
 	esp = x->data;
 	alen = esp->auth.icv_trunc_len;
@@ -49,22 +49,22 @@
 	if (esp->conf.padlen)
 		clen = (clen + esp->conf.padlen-1)&~(esp->conf.padlen-1);
 
-	if ((nfrags = skb_cow_data(*pskb, clen-(*pskb)->len+alen, &trailer)) < 0)
+	if ((nfrags = skb_cow_data(skb, clen-skb->len+alen, &trailer)) < 0)
 		goto error;
 
 	/* Fill padding... */
 	do {
 		int i;
-		for (i=0; i<clen-(*pskb)->len - 2; i++)
+		for (i=0; i<clen-skb->len - 2; i++)
 			*(u8*)(trailer->tail + i) = i+1;
 	} while (0);
-	*(u8*)(trailer->tail + clen-(*pskb)->len - 2) = (clen - (*pskb)->len)-2;
-	pskb_put(*pskb, trailer, clen - (*pskb)->len);
+	*(u8*)(trailer->tail + clen-skb->len - 2) = (clen - skb->len)-2;
+	pskb_put(skb, trailer, clen - skb->len);
 
-	__skb_push(*pskb, (*pskb)->data - (*pskb)->nh.raw);
-	top_iph = (*pskb)->nh.iph;
-	esph = (struct ip_esp_hdr *)((*pskb)->nh.raw + top_iph->ihl*4);
-	top_iph->tot_len = htons((*pskb)->len + alen);
+	__skb_push(skb, skb->data - skb->nh.raw);
+	top_iph = skb->nh.iph;
+	esph = (struct ip_esp_hdr *)(skb->nh.raw + top_iph->ihl*4);
+	top_iph->tot_len = htons(skb->len + alen);
 	*(u8*)(trailer->tail - 1) = top_iph->protocol;
 
 	/* this is non-NULL only with UDP Encapsulation */
@@ -76,7 +76,7 @@
 		uh = (struct udphdr *)esph;
 		uh->source = encap->encap_sport;
 		uh->dest = encap->encap_dport;
-		uh->len = htons((*pskb)->len + alen - top_iph->ihl*4);
+		uh->len = htons(skb->len + alen - top_iph->ihl*4);
 		uh->check = 0;
 
 		switch (encap->encap_type) {
@@ -109,7 +109,7 @@
 			if (!sg)
 				goto error;
 		}
-		skb_to_sgvec(*pskb, sg, esph->enc_data+esp->conf.ivlen-(*pskb)->data, clen);
+		skb_to_sgvec(skb, sg, esph->enc_data+esp->conf.ivlen-skb->data, clen);
 		crypto_cipher_encrypt(tfm, sg, sg, clen);
 		if (unlikely(sg != &esp->sgbuf[0]))
 			kfree(sg);
@@ -121,9 +121,9 @@
 	}
 
 	if (esp->auth.icv_full_len) {
-		esp->auth.icv(esp, *pskb, (u8*)esph-(*pskb)->data,
+		esp->auth.icv(esp, skb, (u8*)esph-skb->data,
 		              sizeof(struct ip_esp_hdr) + esp->conf.ivlen+clen, trailer->tail);
-		pskb_put(*pskb, trailer, alen);
+		pskb_put(skb, trailer, alen);
 	}
 
 	ip_send_check(top_iph);
@@ -139,7 +139,7 @@
  * expensive, so we only support truncated data, which is the recommended
  * and common case.
  */
-int esp_input(struct xfrm_state *x, struct xfrm_decap_state *decap, struct sk_buff *skb)
+static int esp_input(struct xfrm_state *x, struct xfrm_decap_state *decap, struct sk_buff *skb)
 {
 	struct iphdr *iph;
 	struct ip_esp_hdr *esph;
@@ -246,7 +246,7 @@
 	return -EINVAL;
 }
 
-int esp_post_input(struct xfrm_state *x, struct xfrm_decap_state *decap, struct sk_buff *skb)
+static int esp_post_input(struct xfrm_state *x, struct xfrm_decap_state *decap, struct sk_buff *skb)
 {
   
 	if (x->encap) {
@@ -320,7 +320,7 @@
 	return mtu + x->props.header_len + esp->auth.icv_trunc_len;
 }
 
-void esp4_err(struct sk_buff *skb, u32 info)
+static void esp4_err(struct sk_buff *skb, u32 info)
 {
 	struct iphdr *iph = (struct iphdr*)skb->data;
 	struct ip_esp_hdr *esph = (struct ip_esp_hdr*)(skb->data+(iph->ihl<<2));
@@ -338,7 +338,7 @@
 	xfrm_state_put(x);
 }
 
-void esp_destroy(struct xfrm_state *x)
+static void esp_destroy(struct xfrm_state *x)
 {
 	struct esp_data *esp = x->data;
 
@@ -364,7 +364,7 @@
 	kfree(esp);
 }
 
-int esp_init_state(struct xfrm_state *x, void *args)
+static int esp_init_state(struct xfrm_state *x, void *args)
 {
 	struct esp_data *esp = NULL;
 
@@ -436,6 +436,7 @@
 
 		switch (encap->encap_type) {
 		default:
+			goto error;
 		case UDP_ENCAP_ESPINUDP:
 			x->props.header_len += sizeof(struct udphdr);
 			break;
@@ -449,15 +450,9 @@
 	return 0;
 
 error:
-	if (esp) {
-		if (esp->auth.tfm)
-			crypto_free_tfm(esp->auth.tfm);
-		if (esp->auth.work_icv)
-			kfree(esp->auth.work_icv);
-		if (esp->conf.tfm)
-			crypto_free_tfm(esp->conf.tfm);
-		kfree(esp);
-	}
+	x->data = esp;
+	esp_destroy(x);
+	x->data = NULL;
 	return -EINVAL;
 }
 
diff -Nru a/net/ipv4/fib_frontend.c b/net/ipv4/fib_frontend.c
--- a/net/ipv4/fib_frontend.c	2004-10-18 14:57:04 -07:00
+++ b/net/ipv4/fib_frontend.c	2004-10-18 14:57:04 -07:00
@@ -172,13 +172,13 @@
 	int ret;
 
 	no_addr = rpf = 0;
-	read_lock(&inetdev_lock);
+	rcu_read_lock();
 	in_dev = __in_dev_get(dev);
 	if (in_dev) {
 		no_addr = in_dev->ifa_list == NULL;
 		rpf = IN_DEV_RPFILTER(in_dev);
 	}
-	read_unlock(&inetdev_lock);
+	rcu_read_unlock();
 
 	if (in_dev == NULL)
 		goto e_inval;
diff -Nru a/net/ipv4/fib_hash.c b/net/ipv4/fib_hash.c
--- a/net/ipv4/fib_hash.c	2004-10-18 14:56:31 -07:00
+++ b/net/ipv4/fib_hash.c	2004-10-18 14:56:31 -07:00
@@ -43,159 +43,106 @@
 #include <net/sock.h>
 #include <net/ip_fib.h>
 
-#define FTprint(a...)
-/*
-   printk(KERN_DEBUG a)
- */
-
-static kmem_cache_t * fn_hash_kmem;
+#include "fib_lookup.h"
 
-/*
-   These bizarre types are just to force strict type checking.
-   When I reversed order of bytes and changed to natural mask lengths,
-   I forgot to make fixes in several places. Now I am lazy to return
-   it back.
- */
+static kmem_cache_t *fn_hash_kmem;
+static kmem_cache_t *fn_alias_kmem;
 
-typedef struct {
-	u32	datum;
-} fn_key_t;
-
-typedef struct {
-	u32	datum;
-} fn_hash_idx_t;
-
-struct fib_node
-{
-	struct fib_node		*fn_next;
-	struct fib_info		*fn_info;
-#define FIB_INFO(f)	((f)->fn_info)
-	fn_key_t		fn_key;
-	u8			fn_tos;
-	u8			fn_type;
-	u8			fn_scope;
-	u8			fn_state;
+struct fib_node {
+	struct hlist_node	fn_hash;
+	struct list_head	fn_alias;
+	u32			fn_key;
 };
 
-#define FN_S_ZOMBIE	1
-#define FN_S_ACCESSED	2
-
-static int fib_hash_zombies;
-
-struct fn_zone
-{
-	struct fn_zone	*fz_next;	/* Next not empty zone	*/
-	struct fib_node	**fz_hash;	/* Hash table pointer	*/
-	int		fz_nent;	/* Number of entries	*/
-
-	int		fz_divisor;	/* Hash divisor		*/
-	u32		fz_hashmask;	/* (fz_divisor - 1)	*/
-#define FZ_HASHMASK(fz)	((fz)->fz_hashmask)
-
-	int		fz_order;	/* Zone order		*/
-	u32		fz_mask;
-#define FZ_MASK(fz)	((fz)->fz_mask)
+struct fn_zone {
+	struct fn_zone		*fz_next;	/* Next not empty zone	*/
+	struct hlist_head	*fz_hash;	/* Hash table pointer	*/
+	int			fz_nent;	/* Number of entries	*/
+
+	int			fz_divisor;	/* Hash divisor		*/
+	u32			fz_hashmask;	/* (fz_divisor - 1)	*/
+#define FZ_HASHMASK(fz)		((fz)->fz_hashmask)
+
+	int			fz_order;	/* Zone order		*/
+	u32			fz_mask;
+#define FZ_MASK(fz)		((fz)->fz_mask)
 };
 
 /* NOTE. On fast computers evaluation of fz_hashmask and fz_mask
-   can be cheaper than memory lookup, so that FZ_* macros are used.
+ * can be cheaper than memory lookup, so that FZ_* macros are used.
  */
 
-struct fn_hash
-{
+struct fn_hash {
 	struct fn_zone	*fn_zones[33];
 	struct fn_zone	*fn_zone_list;
 };
 
-static __inline__ fn_hash_idx_t fn_hash(fn_key_t key, struct fn_zone *fz)
+static inline u32 fn_hash(u32 key, struct fn_zone *fz)
 {
-	u32 h = ntohl(key.datum)>>(32 - fz->fz_order);
+	u32 h = ntohl(key)>>(32 - fz->fz_order);
 	h ^= (h>>20);
 	h ^= (h>>10);
 	h ^= (h>>5);
 	h &= FZ_HASHMASK(fz);
-	return *(fn_hash_idx_t*)&h;
-}
-
-#define fz_key_0(key)		((key).datum = 0)
-#define fz_prefix(key,fz)	((key).datum)
-
-static __inline__ fn_key_t fz_key(u32 dst, struct fn_zone *fz)
-{
-	fn_key_t k;
-	k.datum = dst & FZ_MASK(fz);
-	return k;
-}
-
-static __inline__ struct fib_node ** fz_chain_p(fn_key_t key, struct fn_zone *fz)
-{
-	return &fz->fz_hash[fn_hash(key, fz).datum];
-}
-
-static __inline__ struct fib_node * fz_chain(fn_key_t key, struct fn_zone *fz)
-{
-	return fz->fz_hash[fn_hash(key, fz).datum];
-}
-
-static __inline__ int fn_key_eq(fn_key_t a, fn_key_t b)
-{
-	return a.datum == b.datum;
+	return h;
 }
 
-static __inline__ int fn_key_leq(fn_key_t a, fn_key_t b)
+static inline u32 fz_key(u32 dst, struct fn_zone *fz)
 {
-	return a.datum <= b.datum;
+	return dst & FZ_MASK(fz);
 }
 
 static rwlock_t fib_hash_lock = RW_LOCK_UNLOCKED;
 
-#define FZ_MAX_DIVISOR ((PAGE_SIZE<<MAX_ORDER) / sizeof(struct fib_node *))
+#define FZ_MAX_DIVISOR ((PAGE_SIZE<<MAX_ORDER) / sizeof(struct hlist_head))
 
-static struct fib_node **fz_hash_alloc(int divisor)
+static struct hlist_head *fz_hash_alloc(int divisor)
 {
-	unsigned long size = divisor * sizeof(struct fib_node *);
+	unsigned long size = divisor * sizeof(struct hlist_head);
 
-	if (divisor <= 1024) {
+	if (size <= PAGE_SIZE) {
 		return kmalloc(size, GFP_KERNEL);
 	} else {
-		return (struct fib_node **)
+		return (struct hlist_head *)
 			__get_free_pages(GFP_KERNEL, get_order(size));
 	}
 }
 
 /* The fib hash lock must be held when this is called. */
-static __inline__ void fn_rebuild_zone(struct fn_zone *fz,
-				       struct fib_node **old_ht,
-				       int old_divisor)
+static inline void fn_rebuild_zone(struct fn_zone *fz,
+				   struct hlist_head *old_ht,
+				   int old_divisor)
 {
 	int i;
-	struct fib_node *f, **fp, *next;
 
-	for (i=0; i<old_divisor; i++) {
-		for (f=old_ht[i]; f; f=next) {
-			next = f->fn_next;
-			for (fp = fz_chain_p(f->fn_key, fz);
-			     *fp && fn_key_leq((*fp)->fn_key, f->fn_key);
-			     fp = &(*fp)->fn_next)
-				/* NONE */;
-			f->fn_next = *fp;
-			*fp = f;
+	for (i = 0; i < old_divisor; i++) {
+		struct hlist_node *node, *n;
+		struct fib_node *f;
+
+		hlist_for_each_entry_safe(f, node, n, &old_ht[i], fn_hash) {
+			struct hlist_head *new_head;
+
+			hlist_del(&f->fn_hash);
+
+			new_head = &fz->fz_hash[fn_hash(f->fn_key, fz)];
+			hlist_add_head(&f->fn_hash, new_head);
 		}
 	}
 }
 
-static void fz_hash_free(struct fib_node **hash, int divisor)
+static void fz_hash_free(struct hlist_head *hash, int divisor)
 {
-	if (divisor <= 1024)
+	unsigned long size = divisor * sizeof(struct hlist_head);
+
+	if (size <= PAGE_SIZE)
 		kfree(hash);
 	else
-		free_pages((unsigned long) hash,
-			   get_order(divisor * sizeof(struct fib_node *)));
+		free_pages((unsigned long)hash, get_order(size));
 }
 
 static void fn_rehash_zone(struct fn_zone *fz)
 {
-	struct fib_node **ht, **old_ht;
+	struct hlist_head *ht, *old_ht;
 	int old_divisor, new_divisor;
 	u32 new_hashmask;
 		
@@ -226,7 +173,7 @@
 	ht = fz_hash_alloc(new_divisor);
 
 	if (ht)	{
-		memset(ht, 0, new_divisor*sizeof(struct fib_node*));
+		memset(ht, 0, new_divisor * sizeof(struct hlist_head));
 
 		write_lock_bh(&fib_hash_lock);
 		old_ht = fz->fz_hash;
@@ -240,12 +187,16 @@
 	}
 }
 
-static void fn_free_node(struct fib_node * f)
+static inline void fn_free_node(struct fib_node * f)
 {
-	fib_release_info(FIB_INFO(f));
 	kmem_cache_free(fn_hash_kmem, f);
 }
 
+static inline void fn_free_alias(struct fib_alias *fa)
+{
+	fib_release_info(fa->fa_info);
+	kmem_cache_free(fn_alias_kmem, fa);
+}
 
 static struct fn_zone *
 fn_new_zone(struct fn_hash *table, int z)
@@ -267,7 +218,7 @@
 		kfree(fz);
 		return NULL;
 	}
-	memset(fz->fz_hash, 0, fz->fz_divisor*sizeof(struct fib_node*));
+	memset(fz->fz_hash, 0, fz->fz_divisor * sizeof(struct hlist_head *));
 	fz->fz_order = z;
 	fz->fz_mask = inet_make_mask(z);
 
@@ -298,35 +249,20 @@
 
 	read_lock(&fib_hash_lock);
 	for (fz = t->fn_zone_list; fz; fz = fz->fz_next) {
+		struct hlist_head *head;
+		struct hlist_node *node;
 		struct fib_node *f;
-		fn_key_t k = fz_key(flp->fl4_dst, fz);
+		u32 k = fz_key(flp->fl4_dst, fz);
 
-		for (f = fz_chain(k, fz); f; f = f->fn_next) {
-			if (!fn_key_eq(k, f->fn_key)) {
-				if (fn_key_leq(k, f->fn_key))
-					break;
-				else
-					continue;
-			}
-#ifdef CONFIG_IP_ROUTE_TOS
-			if (f->fn_tos && f->fn_tos != flp->fl4_tos)
+		head = &fz->fz_hash[fn_hash(k, fz)];
+		hlist_for_each_entry(f, node, head, fn_hash) {
+			if (f->fn_key != k)
 				continue;
-#endif
-			f->fn_state |= FN_S_ACCESSED;
 
-			if (f->fn_state&FN_S_ZOMBIE)
-				continue;
-			if (f->fn_scope < flp->fl4_scope)
-				continue;
-
-			err = fib_semantic_match(f->fn_type, FIB_INFO(f), flp, res);
-			if (err == 0) {
-				res->type = f->fn_type;
-				res->scope = f->fn_scope;
-				res->prefixlen = fz->fz_order;
-				goto out;
-			}
-			if (err < 0)
+			err = fib_semantic_match(&f->fn_alias,
+						 flp, res,
+						 fz->fz_order);
+			if (err <= 0)
 				goto out;
 		}
 	}
@@ -365,6 +301,7 @@
 fn_hash_select_default(struct fib_table *tb, const struct flowi *flp, struct fib_result *res)
 {
 	int order, last_idx;
+	struct hlist_node *node;
 	struct fib_node *f;
 	struct fib_info *fi = NULL;
 	struct fib_info *last_resort;
@@ -379,36 +316,41 @@
 	order = -1;
 
 	read_lock(&fib_hash_lock);
-	for (f = fz->fz_hash[0]; f; f = f->fn_next) {
-		struct fib_info *next_fi = FIB_INFO(f);
+	hlist_for_each_entry(f, node, &fz->fz_hash[0], fn_hash) {
+		struct fib_alias *fa;
 
-		if ((f->fn_state&FN_S_ZOMBIE) ||
-		    f->fn_scope != res->scope ||
-		    f->fn_type != RTN_UNICAST)
-			continue;
+		list_for_each_entry(fa, &f->fn_alias, fa_list) {
+			struct fib_info *next_fi = fa->fa_info;
 
-		if (next_fi->fib_priority > res->fi->fib_priority)
-			break;
-		if (!next_fi->fib_nh[0].nh_gw || next_fi->fib_nh[0].nh_scope != RT_SCOPE_LINK)
-			continue;
-		f->fn_state |= FN_S_ACCESSED;
+			if (fa->fa_scope != res->scope ||
+			    fa->fa_type != RTN_UNICAST)
+				continue;
 
-		if (fi == NULL) {
-			if (next_fi != res->fi)
+			if (next_fi->fib_priority > res->fi->fib_priority)
 				break;
-		} else if (!fib_detect_death(fi, order, &last_resort, &last_idx)) {
-			if (res->fi)
-				fib_info_put(res->fi);
-			res->fi = fi;
-			atomic_inc(&fi->fib_clntref);
-			fn_hash_last_dflt = order;
-			goto out;
+			if (!next_fi->fib_nh[0].nh_gw ||
+			    next_fi->fib_nh[0].nh_scope != RT_SCOPE_LINK)
+				continue;
+			fa->fa_state |= FA_S_ACCESSED;
+
+			if (fi == NULL) {
+				if (next_fi != res->fi)
+					break;
+			} else if (!fib_detect_death(fi, order, &last_resort,
+						     &last_idx)) {
+				if (res->fi)
+					fib_info_put(res->fi);
+				res->fi = fi;
+				atomic_inc(&fi->fib_clntref);
+				fn_hash_last_dflt = order;
+				goto out;
+			}
+			fi = next_fi;
+			order++;
 		}
-		fi = next_fi;
-		order++;
 	}
 
-	if (order<=0 || fi==NULL) {
+	if (order <= 0 || fi == NULL) {
 		fn_hash_last_dflt = -1;
 		goto out;
 	}
@@ -434,52 +376,76 @@
 	read_unlock(&fib_hash_lock);
 }
 
-#define FIB_SCAN(f, fp) \
-for ( ; ((f) = *(fp)) != NULL; (fp) = &(f)->fn_next)
+static void rtmsg_fib(int, struct fib_node *, struct fib_alias *,
+		      int, int,
+		      struct nlmsghdr *n,
+		      struct netlink_skb_parms *);
 
-#define FIB_SCAN_KEY(f, fp, key) \
-for ( ; ((f) = *(fp)) != NULL && fn_key_eq((f)->fn_key, (key)); (fp) = &(f)->fn_next)
+/* Insert node F to FZ. */
+static inline void fib_insert_node(struct fn_zone *fz, struct fib_node *f)
+{
+	struct hlist_head *head = &fz->fz_hash[fn_hash(f->fn_key, fz)];
 
-#ifndef CONFIG_IP_ROUTE_TOS
-#define FIB_SCAN_TOS(f, fp, key, tos) FIB_SCAN_KEY(f, fp, key)
-#else
-#define FIB_SCAN_TOS(f, fp, key, tos) \
-for ( ; ((f) = *(fp)) != NULL && fn_key_eq((f)->fn_key, (key)) && \
-     (f)->fn_tos == (tos) ; (fp) = &(f)->fn_next)
-#endif
+	hlist_add_head(&f->fn_hash, head);
+}
 
+/* Return the node in FZ matching KEY. */
+static struct fib_node *fib_find_node(struct fn_zone *fz, u32 key)
+{
+	struct hlist_head *head = &fz->fz_hash[fn_hash(key, fz)];
+	struct hlist_node *node;
+	struct fib_node *f;
 
-static void rtmsg_fib(int, struct fib_node*, int, int,
-		      struct nlmsghdr *n,
-		      struct netlink_skb_parms *);
+	hlist_for_each_entry(f, node, head, fn_hash) {
+		if (f->fn_key == key)
+			return f;
+	}
+
+	return NULL;
+}
+
+/* Return the first fib alias matching TOS with
+ * priority less than or equal to PRIO.
+ */
+static struct fib_alias *fib_find_alias(struct fib_node *fn, u8 tos, u32 prio)
+{
+	if (fn) {
+		struct list_head *head = &fn->fn_alias;
+		struct fib_alias *fa;
+
+		list_for_each_entry(fa, head, fa_list) {
+			if (fa->fa_tos > tos)
+				continue;
+			if (fa->fa_info->fib_priority >= prio ||
+			    fa->fa_tos < tos)
+				return fa;
+		}
+	}
+	return NULL;
+}
 
 static int
 fn_hash_insert(struct fib_table *tb, struct rtmsg *r, struct kern_rta *rta,
-		struct nlmsghdr *n, struct netlink_skb_parms *req)
+	       struct nlmsghdr *n, struct netlink_skb_parms *req)
 {
-	struct fn_hash *table = (struct fn_hash*)tb->tb_data;
-	struct fib_node *new_f, *f, **fp, **del_fp;
+	struct fn_hash *table = (struct fn_hash *) tb->tb_data;
+	struct fib_node *new_f, *f;
+	struct fib_alias *fa, *new_fa;
 	struct fn_zone *fz;
 	struct fib_info *fi;
-
 	int z = r->rtm_dst_len;
 	int type = r->rtm_type;
-#ifdef CONFIG_IP_ROUTE_TOS
 	u8 tos = r->rtm_tos;
-#endif
-	fn_key_t key;
+	u32 key;
 	int err;
 
-FTprint("tb(%d)_insert: %d %08x/%d %d %08x\n", tb->tb_id, r->rtm_type, rta->rta_dst ?
-*(u32*)rta->rta_dst : 0, z, rta->rta_oif ? *rta->rta_oif : -1,
-rta->rta_prefsrc ? *(u32*)rta->rta_prefsrc : 0);
 	if (z > 32)
 		return -EINVAL;
 	fz = table->fn_zones[z];
 	if (!fz && !(fz = fn_new_zone(table, z)))
 		return -ENOBUFS;
 
-	fz_key_0(key);
+	key = 0;
 	if (rta->rta_dst) {
 		u32 dst;
 		memcpy(&dst, rta->rta_dst, 4);
@@ -496,136 +462,114 @@
 	    (z==32 || (1<<z) > fz->fz_divisor))
 		fn_rehash_zone(fz);
 
-	fp = fz_chain_p(key, fz);
-
-
-	/*
-	 * Scan list to find the first route with the same destination
-	 */
-	FIB_SCAN(f, fp) {
-		if (fn_key_leq(key,f->fn_key))
-			break;
-	}
-
-#ifdef CONFIG_IP_ROUTE_TOS
-	/*
-	 * Find route with the same destination and tos.
-	 */
-	FIB_SCAN_KEY(f, fp, key) {
-		if (f->fn_tos <= tos)
-			break;
-	}
-#endif
-
-	del_fp = NULL;
+	f = fib_find_node(fz, key);
+	fa = fib_find_alias(f, tos, fi->fib_priority);
 
-	if (f && (f->fn_state&FN_S_ZOMBIE) &&
-#ifdef CONFIG_IP_ROUTE_TOS
-	    f->fn_tos == tos &&
-#endif
-	    fn_key_eq(f->fn_key, key)) {
-		del_fp = fp;
-		fp = &f->fn_next;
-		f = *fp;
-		goto create;
-	}
-
-	FIB_SCAN_TOS(f, fp, key, tos) {
-		if (fi->fib_priority <= FIB_INFO(f)->fib_priority)
-			break;
-	}
-
-	/* Now f==*fp points to the first node with the same
-	   keys [prefix,tos,priority], if such key already
-	   exists or to the node, before which we will insert new one.
+	/* Now fa, if non-NULL, points to the first fib alias
+	 * with the same keys [prefix,tos,priority], if such key already
+	 * exists or to the node before which we will insert new one.
+	 *
+	 * If fa is NULL, we will need to allocate a new one and
+	 * insert to the head of f.
+	 *
+	 * If f is NULL, no fib node matched the destination key
+	 * and we need to allocate a new one of those as well.
 	 */
 
-	if (f && 
-#ifdef CONFIG_IP_ROUTE_TOS
-	    f->fn_tos == tos &&
-#endif
-	    fn_key_eq(f->fn_key, key) &&
-	    fi->fib_priority == FIB_INFO(f)->fib_priority) {
-		struct fib_node **ins_fp;
+	if (fa && fa->fa_tos == tos &&
+	    fa->fa_info->fib_priority == fi->fib_priority) {
+		struct fib_alias *fa_orig;
 
 		err = -EEXIST;
-		if (n->nlmsg_flags&NLM_F_EXCL)
+		if (n->nlmsg_flags & NLM_F_EXCL)
 			goto out;
 
-		if (n->nlmsg_flags&NLM_F_REPLACE) {
-			del_fp = fp;
-			fp = &f->fn_next;
-			f = *fp;
-			goto replace;
-		}
+		if (n->nlmsg_flags & NLM_F_REPLACE) {
+			struct fib_info *fi_drop;
+			u8 state;
 
-		ins_fp = fp;
-		err = -EEXIST;
+			write_lock_bh(&fib_hash_lock);
+			fi_drop = fa->fa_info;
+			fa->fa_info = fi;
+			fa->fa_type = type;
+			fa->fa_scope = r->rtm_scope;
+			state = fa->fa_state;
+			fa->fa_state &= ~FA_S_ACCESSED;
+			write_unlock_bh(&fib_hash_lock);
 
-		FIB_SCAN_TOS(f, fp, key, tos) {
-			if (fi->fib_priority != FIB_INFO(f)->fib_priority)
-				break;
-			if (f->fn_type == type && f->fn_scope == r->rtm_scope
-			    && FIB_INFO(f) == fi)
-				goto out;
+			fib_release_info(fi_drop);
+			if (state & FA_S_ACCESSED)
+				rt_cache_flush(-1);
+			return 0;
 		}
 
-		if (!(n->nlmsg_flags&NLM_F_APPEND)) {
-			fp = ins_fp;
-			f = *fp;
+		/* Error if we find a perfect match which
+		 * uses the same scope, type, and nexthop
+		 * information.
+		 */
+		fa_orig = fa;
+		fa = list_entry(fa->fa_list.prev, struct fib_alias, fa_list);
+		list_for_each_entry_continue(fa, &f->fn_alias, fa_list) {
+			if (fa->fa_tos != tos)
+				break;
+			if (fa->fa_info->fib_priority != fi->fib_priority)
+				break;
+			if (fa->fa_type == type &&
+			    fa->fa_scope == r->rtm_scope &&
+			    fa->fa_info == fi)
+				goto out;
 		}
+		if (!(n->nlmsg_flags & NLM_F_APPEND))
+			fa = fa_orig;
 	}
 
-create:
 	err = -ENOENT;
 	if (!(n->nlmsg_flags&NLM_F_CREATE))
 		goto out;
 
-replace:
 	err = -ENOBUFS;
-	new_f = kmem_cache_alloc(fn_hash_kmem, SLAB_KERNEL);
-	if (new_f == NULL)
+	new_fa = kmem_cache_alloc(fn_alias_kmem, SLAB_KERNEL);
+	if (new_fa == NULL)
 		goto out;
 
-	memset(new_f, 0, sizeof(struct fib_node));
-
-	new_f->fn_key = key;
-#ifdef CONFIG_IP_ROUTE_TOS
-	new_f->fn_tos = tos;
-#endif
-	new_f->fn_type = type;
-	new_f->fn_scope = r->rtm_scope;
-	FIB_INFO(new_f) = fi;
+	new_f = NULL;
+	if (!f) {
+		new_f = kmem_cache_alloc(fn_hash_kmem, SLAB_KERNEL);
+		if (new_f == NULL)
+			goto out_free_new_fa;
+
+		INIT_HLIST_NODE(&new_f->fn_hash);
+		INIT_LIST_HEAD(&new_f->fn_alias);
+		new_f->fn_key = key;
+		f = new_f;
+	}
+
+	new_fa->fa_info = fi;
+	new_fa->fa_tos = tos;
+	new_fa->fa_type = type;
+	new_fa->fa_scope = r->rtm_scope;
+	new_fa->fa_state = 0;
 
 	/*
 	 * Insert new entry to the list.
 	 */
 
-	new_f->fn_next = f;
 	write_lock_bh(&fib_hash_lock);
-	*fp = new_f;
+	if (new_f)
+		fib_insert_node(fz, new_f);
+	list_add_tail(&new_fa->fa_list,
+		 (fa ? &fa->fa_list : &f->fn_alias));
 	write_unlock_bh(&fib_hash_lock);
-	fz->fz_nent++;
 
-	if (del_fp) {
-		f = *del_fp;
-		/* Unlink replaced node */
-		write_lock_bh(&fib_hash_lock);
-		*del_fp = f->fn_next;
-		write_unlock_bh(&fib_hash_lock);
+	if (new_f)
+		fz->fz_nent++;
+	rt_cache_flush(-1);
 
-		if (!(f->fn_state&FN_S_ZOMBIE))
-			rtmsg_fib(RTM_DELROUTE, f, z, tb->tb_id, n, req);
-		if (f->fn_state&FN_S_ACCESSED)
-			rt_cache_flush(-1);
-		fn_free_node(f);
-		fz->fz_nent--;
-	} else {
-		rt_cache_flush(-1);
-	}
-	rtmsg_fib(RTM_NEWROUTE, new_f, z, tb->tb_id, n, req);
+	rtmsg_fib(RTM_NEWROUTE, f, new_fa, z, tb->tb_id, n, req);
 	return 0;
 
+out_free_new_fa:
+	kmem_cache_free(fn_alias_kmem, new_fa);
 out:
 	fib_release_info(fi);
 	return err;
@@ -634,26 +578,22 @@
 
 static int
 fn_hash_delete(struct fib_table *tb, struct rtmsg *r, struct kern_rta *rta,
-		struct nlmsghdr *n, struct netlink_skb_parms *req)
+	       struct nlmsghdr *n, struct netlink_skb_parms *req)
 {
 	struct fn_hash *table = (struct fn_hash*)tb->tb_data;
-	struct fib_node **fp, **del_fp, *f;
+	struct fib_node *f;
+	struct fib_alias *fa, *fa_to_delete;
 	int z = r->rtm_dst_len;
 	struct fn_zone *fz;
-	fn_key_t key;
-	int matched;
-#ifdef CONFIG_IP_ROUTE_TOS
+	u32 key;
 	u8 tos = r->rtm_tos;
-#endif
 
-FTprint("tb(%d)_delete: %d %08x/%d %d\n", tb->tb_id, r->rtm_type, rta->rta_dst ?
-       *(u32*)rta->rta_dst : 0, z, rta->rta_oif ? *rta->rta_oif : -1);
 	if (z > 32)
 		return -EINVAL;
 	if ((fz  = table->fn_zones[z]) == NULL)
 		return -ESRCH;
 
-	fz_key_0(key);
+	key = 0;
 	if (rta->rta_dst) {
 		u32 dst;
 		memcpy(&dst, rta->rta_dst, 4);
@@ -662,62 +602,52 @@
 		key = fz_key(dst, fz);
 	}
 
-	fp = fz_chain_p(key, fz);
+	f = fib_find_node(fz, key);
+	fa = fib_find_alias(f, tos, 0);
+	if (!fa)
+		return -ESRCH;
 
+	fa_to_delete = NULL;
+	fa = list_entry(fa->fa_list.prev, struct fib_alias, fa_list);
+	list_for_each_entry_continue(fa, &f->fn_alias, fa_list) {
+		struct fib_info *fi = fa->fa_info;
 
-	FIB_SCAN(f, fp) {
-		if (fn_key_eq(f->fn_key, key))
+		if (fa->fa_tos != tos)
 			break;
-		if (fn_key_leq(key, f->fn_key)) {
-			return -ESRCH;
-		}
-	}
-#ifdef CONFIG_IP_ROUTE_TOS
-	FIB_SCAN_KEY(f, fp, key) {
-		if (f->fn_tos == tos)
-			break;
-	}
-#endif
 
-	matched = 0;
-	del_fp = NULL;
-	FIB_SCAN_TOS(f, fp, key, tos) {
-		struct fib_info * fi = FIB_INFO(f);
-
-		if (f->fn_state&FN_S_ZOMBIE) {
-			return -ESRCH;
+		if ((!r->rtm_type ||
+		     fa->fa_type == r->rtm_type) &&
+		    (r->rtm_scope == RT_SCOPE_NOWHERE ||
+		     fa->fa_scope == r->rtm_scope) &&
+		    (!r->rtm_protocol ||
+		     fi->fib_protocol == r->rtm_protocol) &&
+		    fib_nh_match(r, n, rta, fi) == 0) {
+			fa_to_delete = fa;
+			break;
 		}
-		matched++;
-
-		if (del_fp == NULL &&
-		    (!r->rtm_type || f->fn_type == r->rtm_type) &&
-		    (r->rtm_scope == RT_SCOPE_NOWHERE || f->fn_scope == r->rtm_scope) &&
-		    (!r->rtm_protocol || fi->fib_protocol == r->rtm_protocol) &&
-		    fib_nh_match(r, n, rta, fi) == 0)
-			del_fp = fp;
 	}
 
-	if (del_fp) {
-		f = *del_fp;
-		rtmsg_fib(RTM_DELROUTE, f, z, tb->tb_id, n, req);
+	if (fa_to_delete) {
+		int kill_fn;
 
-		if (matched != 1) {
-			write_lock_bh(&fib_hash_lock);
-			*del_fp = f->fn_next;
-			write_unlock_bh(&fib_hash_lock);
+		fa = fa_to_delete;
+		rtmsg_fib(RTM_DELROUTE, f, fa, z, tb->tb_id, n, req);
 
-			if (f->fn_state&FN_S_ACCESSED)
-				rt_cache_flush(-1);
+		kill_fn = 0;
+		write_lock_bh(&fib_hash_lock);
+		list_del(&fa->fa_list);
+		if (list_empty(&f->fn_alias)) {
+			hlist_del(&f->fn_hash);
+			kill_fn = 1;
+		}
+		write_unlock_bh(&fib_hash_lock);
+
+		if (fa->fa_state & FA_S_ACCESSED)
+			rt_cache_flush(-1);
+		fn_free_alias(fa);
+		if (kill_fn) {
 			fn_free_node(f);
 			fz->fz_nent--;
-		} else {
-			f->fn_state |= FN_S_ZOMBIE;
-			if (f->fn_state&FN_S_ACCESSED) {
-				f->fn_state &= ~FN_S_ACCESSED;
-				rt_cache_flush(-1);
-			}
-			if (++fib_hash_zombies > 128)
-				fib_flush();
 		}
 
 		return 0;
@@ -725,74 +655,99 @@
 	return -ESRCH;
 }
 
-static __inline__ int
-fn_flush_list(struct fib_node ** fp, int z, struct fn_hash *table)
+static int fn_flush_list(struct fn_zone *fz, int idx)
 {
-	int found = 0;
+	struct hlist_head *head = &fz->fz_hash[idx];
+	struct hlist_node *node, *n;
 	struct fib_node *f;
+	int found = 0;
 
-	while ((f = *fp) != NULL) {
-		struct fib_info *fi = FIB_INFO(f);
-
-		if (fi && ((f->fn_state&FN_S_ZOMBIE) || (fi->fib_flags&RTNH_F_DEAD))) {
-			write_lock_bh(&fib_hash_lock);
-			*fp = f->fn_next;
-			write_unlock_bh(&fib_hash_lock);
+	hlist_for_each_entry_safe(f, node, n, head, fn_hash) {
+		struct fib_alias *fa, *fa_node;
+		int kill_f;
+
+		kill_f = 0;
+		list_for_each_entry_safe(fa, fa_node, &f->fn_alias, fa_list) {
+			struct fib_info *fi = fa->fa_info;
+
+			if (fi && (fi->fib_flags&RTNH_F_DEAD)) {
+				write_lock_bh(&fib_hash_lock);
+				list_del(&fa->fa_list);
+				if (list_empty(&f->fn_alias)) {
+					hlist_del(&f->fn_hash);
+					kill_f = 1;
+				}
+				write_unlock_bh(&fib_hash_lock);
 
+				fn_free_alias(fa);
+				found++;
+			}
+		}
+		if (kill_f) {
 			fn_free_node(f);
-			found++;
-			continue;
+			fz->fz_nent--;
 		}
-		fp = &f->fn_next;
 	}
 	return found;
 }
 
 static int fn_hash_flush(struct fib_table *tb)
 {
-	struct fn_hash *table = (struct fn_hash*)tb->tb_data;
+	struct fn_hash *table = (struct fn_hash *) tb->tb_data;
 	struct fn_zone *fz;
 	int found = 0;
 
-	fib_hash_zombies = 0;
 	for (fz = table->fn_zone_list; fz; fz = fz->fz_next) {
 		int i;
-		int tmp = 0;
-		for (i=fz->fz_divisor-1; i>=0; i--)
-			tmp += fn_flush_list(&fz->fz_hash[i], fz->fz_order, table);
-		fz->fz_nent -= tmp;
-		found += tmp;
+
+		for (i = fz->fz_divisor - 1; i >= 0; i--)
+			found += fn_flush_list(fz, i);
 	}
 	return found;
 }
 
 
-static __inline__ int
+static inline int
 fn_hash_dump_bucket(struct sk_buff *skb, struct netlink_callback *cb,
 		     struct fib_table *tb,
 		     struct fn_zone *fz,
-		     struct fib_node *f)
+		     struct hlist_head *head)
 {
+	struct hlist_node *node;
+	struct fib_node *f;
 	int i, s_i;
 
 	s_i = cb->args[3];
-	for (i=0; f; i++, f=f->fn_next) {
-		if (i < s_i) continue;
-		if (f->fn_state&FN_S_ZOMBIE) continue;
-		if (fib_dump_info(skb, NETLINK_CB(cb->skb).pid, cb->nlh->nlmsg_seq,
-				  RTM_NEWROUTE,
-				  tb->tb_id, (f->fn_state&FN_S_ZOMBIE) ? 0 : f->fn_type, f->fn_scope,
-				  &f->fn_key, fz->fz_order, f->fn_tos,
-				  f->fn_info) < 0) {
-			cb->args[3] = i;
-			return -1;
+	i = 0;
+	hlist_for_each_entry(f, node, head, fn_hash) {
+		struct fib_alias *fa;
+
+		list_for_each_entry(fa, &f->fn_alias, fa_list) {
+			if (i < s_i)
+				continue;
+
+			if (fib_dump_info(skb, NETLINK_CB(cb->skb).pid,
+					  cb->nlh->nlmsg_seq,
+					  RTM_NEWROUTE,
+					  tb->tb_id,
+					  fa->fa_type,
+					  fa->fa_scope,
+					  &f->fn_key,
+					  fz->fz_order,
+					  fa->fa_tos,
+					  fa->fa_info) < 0) {
+				cb->args[3] = i;
+				return -1;
+			}
+
+			i++;
 		}
 	}
 	cb->args[3] = i;
 	return skb->len;
 }
 
-static __inline__ int
+static inline int
 fn_hash_dump_zone(struct sk_buff *skb, struct netlink_callback *cb,
 		   struct fib_table *tb,
 		   struct fn_zone *fz)
@@ -803,10 +758,12 @@
 	for (h=0; h < fz->fz_divisor; h++) {
 		if (h < s_h) continue;
 		if (h > s_h)
-			memset(&cb->args[3], 0, sizeof(cb->args) - 3*sizeof(cb->args[0]));
-		if (fz->fz_hash == NULL || fz->fz_hash[h] == NULL)
+			memset(&cb->args[3], 0,
+			       sizeof(cb->args) - 3*sizeof(cb->args[0]));
+		if (fz->fz_hash == NULL ||
+		    hlist_empty(&fz->fz_hash[h]))
 			continue;
-		if (fn_hash_dump_bucket(skb, cb, tb, fz, fz->fz_hash[h]) < 0) {
+		if (fn_hash_dump_bucket(skb, cb, tb, fz, &fz->fz_hash[h])<0) {
 			cb->args[2] = h;
 			return -1;
 		}
@@ -826,7 +783,8 @@
 	for (fz = table->fn_zone_list, m=0; fz; fz = fz->fz_next, m++) {
 		if (m < s_m) continue;
 		if (m > s_m)
-			memset(&cb->args[2], 0, sizeof(cb->args) - 2*sizeof(cb->args[0]));
+			memset(&cb->args[2], 0,
+			       sizeof(cb->args) - 2*sizeof(cb->args[0]));
 		if (fn_hash_dump_zone(skb, cb, tb, fz) < 0) {
 			cb->args[1] = m;
 			read_unlock(&fib_hash_lock);
@@ -838,7 +796,8 @@
 	return skb->len;
 }
 
-static void rtmsg_fib(int event, struct fib_node* f, int z, int tb_id,
+static void rtmsg_fib(int event, struct fib_node *f, struct fib_alias *fa,
+		      int z, int tb_id,
 		      struct nlmsghdr *n, struct netlink_skb_parms *req)
 {
 	struct sk_buff *skb;
@@ -850,8 +809,9 @@
 		return;
 
 	if (fib_dump_info(skb, pid, n->nlmsg_seq, event, tb_id,
-			  f->fn_type, f->fn_scope, &f->fn_key, z, f->fn_tos,
-			  FIB_INFO(f)) < 0) {
+			  fa->fa_type, fa->fa_scope, &f->fn_key, z,
+			  fa->fa_tos,
+			  fa->fa_info) < 0) {
 		kfree_skb(skb);
 		return;
 	}
@@ -877,7 +837,14 @@
 						 0, SLAB_HWCACHE_ALIGN,
 						 NULL, NULL);
 
-	tb = kmalloc(sizeof(struct fib_table) + sizeof(struct fn_hash), GFP_KERNEL);
+	if (fn_alias_kmem == NULL)
+		fn_alias_kmem = kmem_cache_create("ip_fib_alias",
+						  sizeof(struct fib_alias),
+						  0, SLAB_HWCACHE_ALIGN,
+						  NULL, NULL);
+
+	tb = kmalloc(sizeof(struct fib_table) + sizeof(struct fn_hash),
+		     GFP_KERNEL);
 	if (tb == NULL)
 		return NULL;
 
@@ -898,64 +865,105 @@
 struct fib_iter_state {
 	struct fn_zone	*zone;
 	int		bucket;
-	struct fib_node **hash;
-	struct fib_node *node;
+	struct hlist_head *hash_head;
+	struct fib_node *fn;
+	struct fib_alias *fa;
 };
 
-static __inline__ struct fib_node *fib_get_first(struct seq_file *seq)
+static struct fib_alias *fib_get_first(struct seq_file *seq)
 {
-	struct fib_iter_state* iter = seq->private;
-	struct fn_hash *table = (struct fn_hash *)ip_fib_main_table->tb_data;
+	struct fib_iter_state *iter = seq->private;
+	struct fn_hash *table = (struct fn_hash *) ip_fib_main_table->tb_data;
 
-	iter->bucket = 0;
-	iter->hash   = NULL;
-	iter->node   = NULL;
+	iter->bucket    = 0;
+	iter->hash_head = NULL;
+	iter->fn        = NULL;
+	iter->fa        = NULL;
 
 	for (iter->zone = table->fn_zone_list; iter->zone;
 	     iter->zone = iter->zone->fz_next) {
 		int maxslot;
 
-		if (!iter->zone->fz_next)
+		if (!iter->zone->fz_nent)
 			continue;
 
-		iter->hash = iter->zone->fz_hash;
+		iter->hash_head = iter->zone->fz_hash;
 		maxslot = iter->zone->fz_divisor;
 
 		for (iter->bucket = 0; iter->bucket < maxslot;
-		     ++iter->bucket, ++iter->hash) {
-			iter->node = *iter->hash;
-
-			if (iter->node)
-				goto out;
+		     ++iter->bucket, ++iter->hash_head) {
+			struct hlist_node *node;
+			struct fib_node *fn;
+
+			hlist_for_each_entry(fn,node,iter->hash_head,fn_hash) {
+				struct fib_alias *fa;
+
+				list_for_each_entry(fa,&fn->fn_alias,fa_list) {
+					iter->fn = fn;
+					iter->fa = fa;
+					goto out;
+				}
+			}
 		}
 	}
 out:
-	return iter->node;
+	return iter->fa;
 }
 
-static __inline__ struct fib_node *fib_get_next(struct seq_file *seq)
+static struct fib_alias *fib_get_next(struct seq_file *seq)
 {
-	struct fib_iter_state* iter = seq->private;
+	struct fib_iter_state *iter = seq->private;
+	struct fib_node *fn;
+	struct fib_alias *fa;
+
+	/* Advance FA, if any. */
+	fn = iter->fn;
+	fa = iter->fa;
+	if (fa) {
+		BUG_ON(!fn);
+		list_for_each_entry_continue(fa, &fn->fn_alias, fa_list) {
+			iter->fa = fa;
+			goto out;
+		}
+	}
 
-	if (iter->node)
-		iter->node = iter->node->fn_next;
+	fa = iter->fa = NULL;
 
-	if (iter->node)
-		goto out;
+	/* Advance FN. */
+	if (fn) {
+		struct hlist_node *node = &fn->fn_hash;
+		hlist_for_each_entry_continue(fn, node, fn_hash) {
+			iter->fn = fn;
 
+			list_for_each_entry(fa, &fn->fn_alias, fa_list) {
+				iter->fa = fa;
+				goto out;
+			}
+		}
+	}
+
+	fn = iter->fn = NULL;
+
+	/* Advance hash chain. */
 	if (!iter->zone)
 		goto out;
 
 	for (;;) {
+		struct hlist_node *node;
 		int maxslot;
 
 		maxslot = iter->zone->fz_divisor;
 
 		while (++iter->bucket < maxslot) {
-			iter->node = *++iter->hash;
+			iter->hash_head++;
 
-			if (iter->node)
-				goto out;
+			hlist_for_each_entry(fn, node, iter->hash_head, fn_hash) {
+				list_for_each_entry(fa, &fn->fn_alias, fa_list) {
+					iter->fn = fn;
+					iter->fa = fa;
+					goto out;
+				}
+			}
 		}
 
 		iter->zone = iter->zone->fz_next;
@@ -963,14 +971,19 @@
 		if (!iter->zone)
 			goto out;
 		
-		iter->hash = iter->zone->fz_hash;
 		iter->bucket = 0;
-		iter->node = *iter->hash;
-		if (iter->node)
-			break;
+		iter->hash_head = iter->zone->fz_hash;
+
+		hlist_for_each_entry(fn, node, iter->hash_head, fn_hash) {
+			list_for_each_entry(fa, &fn->fn_alias, fa_list) {
+				iter->fn = fn;
+				iter->fa = fa;
+				goto out;
+			}
+		}
 	}
 out:
-	return iter->node;
+	return fa;
 }
 
 static void *fib_seq_start(struct seq_file *seq, loff_t *pos)
@@ -994,7 +1007,7 @@
 	read_unlock(&fib_hash_lock);
 }
 
-static unsigned fib_flag_trans(int type, int dead, u32 mask, struct fib_info *fi)
+static unsigned fib_flag_trans(int type, u32 mask, struct fib_info *fi)
 {
 	static unsigned type2flags[RTN_MAX + 1] = {
 		[7] = RTF_REJECT, [8] = RTF_REJECT,
@@ -1005,8 +1018,7 @@
 		flags |= RTF_GATEWAY;
 	if (mask == 0xFFFFFFFF)
 		flags |= RTF_HOST;
-	if (!dead)
-		flags |= RTF_UP;
+	flags |= RTF_UP;
 	return flags;
 }
 
@@ -1018,11 +1030,12 @@
  */
 static int fib_seq_show(struct seq_file *seq, void *v)
 {
-	struct fib_iter_state* iter;
+	struct fib_iter_state *iter;
 	char bf[128];
 	u32 prefix, mask;
 	unsigned flags;
 	struct fib_node *f;
+	struct fib_alias *fa;
 	struct fib_info *fi;
 
 	if (v == SEQ_START_TOKEN) {
@@ -1032,13 +1045,13 @@
 		goto out;
 	}
 
-	f	= v;
-	fi	= FIB_INFO(f);
 	iter	= seq->private;
-	prefix	= fz_prefix(f->fn_key, iter->zone);
+	f	= iter->fn;
+	fa	= iter->fa;
+	fi	= fa->fa_info;
+	prefix	= f->fn_key;
 	mask	= FZ_MASK(iter->zone);
-	flags	= fib_flag_trans(f->fn_type, f->fn_state & FN_S_ZOMBIE,
-				 mask, fi);
+	flags	= fib_flag_trans(fa->fa_type, mask, fi);
 	if (fi)
 		snprintf(bf, sizeof(bf),
 			 "%s\t%08X\t%08X\t%04X\t%d\t%u\t%d\t%08X\t%d\t%u\t%u",
diff -Nru a/net/ipv4/fib_lookup.h b/net/ipv4/fib_lookup.h
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/net/ipv4/fib_lookup.h	2004-10-18 14:57:23 -07:00
@@ -0,0 +1,34 @@
+#ifndef _FIB_LOOKUP_H
+#define _FIB_LOOKUP_H
+
+#include <linux/types.h>
+#include <linux/list.h>
+#include <net/ip_fib.h>
+
+struct fib_alias {
+	struct list_head	fa_list;
+	struct fib_info		*fa_info;
+	u8			fa_tos;
+	u8			fa_type;
+	u8			fa_scope;
+	u8			fa_state;
+};
+
+#define FA_S_ACCESSED	0x01
+
+/* Exported by fib_semantics.c */
+extern int fib_semantic_match(struct list_head *head,
+			      const struct flowi *flp,
+			      struct fib_result *res, int prefixlen);
+extern void fib_release_info(struct fib_info *);
+extern struct fib_info *fib_create_info(const struct rtmsg *r,
+					struct kern_rta *rta,
+					const struct nlmsghdr *,
+					int *err);
+extern int fib_nh_match(struct rtmsg *r, struct nlmsghdr *,
+			struct kern_rta *rta, struct fib_info *fi);
+extern int fib_dump_info(struct sk_buff *skb, u32 pid, u32 seq, int event,
+			 u8 tb_id, u8 type, u8 scope, void *dst,
+			 int dst_len, u8 tos, struct fib_info *fi);
+
+#endif /* _FIB_LOOKUP_H */
diff -Nru a/net/ipv4/fib_rules.c b/net/ipv4/fib_rules.c
--- a/net/ipv4/fib_rules.c	2004-10-18 14:56:33 -07:00
+++ b/net/ipv4/fib_rules.c	2004-10-18 14:56:33 -07:00
@@ -176,7 +176,7 @@
 	table_id = rtm->rtm_table;
 	if (table_id == RT_TABLE_UNSPEC) {
 		struct fib_table *table;
-		if (rtm->rtm_type == RTN_UNICAST || rtm->rtm_type == RTN_NAT) {
+		if (rtm->rtm_type == RTN_UNICAST) {
 			if ((table = fib_empty_table()) == NULL)
 				return -ENOBUFS;
 			table_id = table->tb_id;
@@ -251,26 +251,6 @@
 	return (daddr&~mask)|res->fi->fib_nh->nh_gw;
 }
 
-u32 fib_rules_policy(u32 saddr, struct fib_result *res, unsigned *flags)
-{
-	struct fib_rule *r = res->r;
-
-	if (r->r_action == RTN_NAT) {
-		int addrtype = inet_addr_type(r->r_srcmap);
-
-		if (addrtype == RTN_NAT) {
-			/* Packet is from  translated source; remember it */
-			saddr = (saddr&~r->r_srcmask)|r->r_srcmap;
-			*flags |= RTCF_SNAT;
-		} else if (addrtype == RTN_LOCAL || r->r_srcmap == 0) {
-			/* Packet is from masqueraded source; remember it */
-			saddr = r->r_srcmap;
-			*flags |= RTCF_MASQ;
-		}
-	}
-	return saddr;
-}
-
 #ifdef CONFIG_NET_CLS_ROUTE
 u32 fib_rules_tclass(struct fib_result *res)
 {
@@ -322,9 +302,7 @@
 	for (r = fib_rules; r; r=r->r_next) {
 		if (((saddr^r->r_src) & r->r_srcmask) ||
 		    ((daddr^r->r_dst) & r->r_dstmask) ||
-#ifdef CONFIG_IP_ROUTE_TOS
 		    (r->r_tos && r->r_tos != flp->fl4_tos) ||
-#endif
 #ifdef CONFIG_IP_ROUTE_FWMARK
 		    (r->r_fwmark && r->r_fwmark != flp->fl4_fwmark) ||
 #endif
@@ -334,7 +312,6 @@
 FRprintk("tb %d r %d ", r->r_table, r->r_action);
 		switch (r->r_action) {
 		case RTN_UNICAST:
-		case RTN_NAT:
 			policy = r;
 			break;
 		case RTN_UNREACHABLE:
diff -Nru a/net/ipv4/fib_semantics.c b/net/ipv4/fib_semantics.c
--- a/net/ipv4/fib_semantics.c	2004-10-18 14:56:17 -07:00
+++ b/net/ipv4/fib_semantics.c	2004-10-18 14:56:17 -07:00
@@ -43,16 +43,19 @@
 #include <net/sock.h>
 #include <net/ip_fib.h>
 
+#include "fib_lookup.h"
+
 #define FSprintk(a...)
 
-static struct fib_info 	*fib_info_list;
 static rwlock_t fib_info_lock = RW_LOCK_UNLOCKED;
-int fib_info_cnt;
-
-#define for_fib_info() { struct fib_info *fi; \
-	for (fi = fib_info_list; fi; fi = fi->fib_next)
-
-#define endfor_fib_info() }
+static struct hlist_head *fib_info_hash;
+static struct hlist_head *fib_info_laddrhash;
+static unsigned int fib_hash_size;
+static unsigned int fib_info_cnt;
+
+#define DEVINDEX_HASHBITS 8
+#define DEVINDEX_HASHSIZE (1U << DEVINDEX_HASHBITS)
+static struct hlist_head fib_info_devhash[DEVINDEX_HASHSIZE];
 
 #ifdef CONFIG_IP_ROUTE_MULTIPATH
 
@@ -124,17 +127,10 @@
 		.error	= -EAGAIN,
 		.scope	= RT_SCOPE_UNIVERSE,
 	},	/* RTN_THROW */
-#ifdef CONFIG_IP_ROUTE_NAT
-	{
-		.error	= 0,
-		.scope	= RT_SCOPE_HOST,
-	},	/* RTN_NAT */
-#else
 	{
 		.error	= -EINVAL,
 		.scope	= RT_SCOPE_NOWHERE,
 	},	/* RTN_NAT */
-#endif
 	{
 		.error	= -EINVAL,
 		.scope	= RT_SCOPE_NOWHERE,
@@ -163,12 +159,12 @@
 {
 	write_lock(&fib_info_lock);
 	if (fi && --fi->fib_treeref == 0) {
-		if (fi->fib_next)
-			fi->fib_next->fib_prev = fi->fib_prev;
-		if (fi->fib_prev)
-			fi->fib_prev->fib_next = fi->fib_next;
-		if (fi == fib_info_list)
-			fib_info_list = fi->fib_next;
+		hlist_del(&fi->fib_hash);
+		if (fi->fib_prefsrc)
+			hlist_del(&fi->fib_lhash);
+		change_nexthops(fi) {
+			hlist_del(&nh->nh_hash);
+		} endfor_nexthops(fi)
 		fi->fib_dead = 1;
 		fib_info_put(fi);
 	}
@@ -196,42 +192,79 @@
 	return 0;
 }
 
-static __inline__ struct fib_info * fib_find_info(const struct fib_info *nfi)
+static inline unsigned int fib_info_hashfn(const struct fib_info *fi)
+{
+	unsigned int mask = (fib_hash_size - 1);
+	unsigned int val = fi->fib_nhs;
+
+	val ^= fi->fib_protocol;
+	val ^= fi->fib_prefsrc;
+	val ^= fi->fib_priority;
+
+	return (val ^ (val >> 7) ^ (val >> 12)) & mask;
+}
+
+static struct fib_info *fib_find_info(const struct fib_info *nfi)
 {
-	for_fib_info() {
+	struct hlist_head *head;
+	struct hlist_node *node;
+	struct fib_info *fi;
+	unsigned int hash;
+
+	hash = fib_info_hashfn(nfi);
+	head = &fib_info_hash[hash];
+
+	hlist_for_each_entry(fi, node, head, fib_hash) {
 		if (fi->fib_nhs != nfi->fib_nhs)
 			continue;
 		if (nfi->fib_protocol == fi->fib_protocol &&
 		    nfi->fib_prefsrc == fi->fib_prefsrc &&
 		    nfi->fib_priority == fi->fib_priority &&
-		    memcmp(nfi->fib_metrics, fi->fib_metrics, sizeof(fi->fib_metrics)) == 0 &&
+		    memcmp(nfi->fib_metrics, fi->fib_metrics,
+			   sizeof(fi->fib_metrics)) == 0 &&
 		    ((nfi->fib_flags^fi->fib_flags)&~RTNH_F_DEAD) == 0 &&
 		    (nfi->fib_nhs == 0 || nh_comp(fi, nfi) == 0))
 			return fi;
-	} endfor_fib_info();
+	}
+
 	return NULL;
 }
 
+static inline unsigned int fib_devindex_hashfn(unsigned int val)
+{
+	unsigned int mask = DEVINDEX_HASHSIZE - 1;
+
+	return (val ^
+		(val >> DEVINDEX_HASHBITS) ^
+		(val >> (DEVINDEX_HASHBITS * 2))) & mask;
+}
+
 /* Check, that the gateway is already configured.
    Used only by redirect accept routine.
  */
 
 int ip_fib_check_default(u32 gw, struct net_device *dev)
 {
+	struct hlist_head *head;
+	struct hlist_node *node;
+	struct fib_nh *nh;
+	unsigned int hash;
+
 	read_lock(&fib_info_lock);
-	for_fib_info() {
-		if (fi->fib_flags & RTNH_F_DEAD)
-			continue;
-		for_nexthops(fi) {
-			if (nh->nh_dev == dev && nh->nh_gw == gw &&
-			    nh->nh_scope == RT_SCOPE_LINK &&
-			    !(nh->nh_flags&RTNH_F_DEAD)) {
-				read_unlock(&fib_info_lock);
-				return 0;
-			}
-		} endfor_nexthops(fi);
-	} endfor_fib_info();
+
+	hash = fib_devindex_hashfn(dev->ifindex);
+	head = &fib_info_devhash[hash];
+	hlist_for_each_entry(nh, node, head, nh_hash) {
+		if (nh->nh_dev == dev &&
+		    nh->nh_gw == gw &&
+		    !(nh->nh_flags&RTNH_F_DEAD)) {
+			read_unlock(&fib_info_lock);
+			return 0;
+		}
+	}
+
 	read_unlock(&fib_info_lock);
+
 	return -1;
 }
 
@@ -458,6 +491,82 @@
 	return 0;
 }
 
+static inline unsigned int fib_laddr_hashfn(u32 val)
+{
+	unsigned int mask = (fib_hash_size - 1);
+
+	return (val ^ (val >> 7) ^ (val >> 14)) & mask;
+}
+
+static struct hlist_head *fib_hash_alloc(int bytes)
+{
+	if (bytes <= PAGE_SIZE)
+		return kmalloc(bytes, GFP_KERNEL);
+	else
+		return (struct hlist_head *)
+			__get_free_pages(GFP_KERNEL, get_order(bytes));
+}
+
+static void fib_hash_free(struct hlist_head *hash, int bytes)
+{
+	if (!hash)
+		return;
+
+	if (bytes <= PAGE_SIZE)
+		kfree(hash);
+	else
+		free_pages((unsigned long) hash, get_order(bytes));
+}
+
+static void fib_hash_move(struct hlist_head *new_info_hash,
+			  struct hlist_head *new_laddrhash,
+			  unsigned int new_size)
+{
+	unsigned int old_size = fib_hash_size;
+	unsigned int i;
+
+	write_lock(&fib_info_lock);
+	fib_hash_size = new_size;
+
+	for (i = 0; i < old_size; i++) {
+		struct hlist_head *head = &fib_info_hash[i];
+		struct hlist_node *node, *n;
+		struct fib_info *fi;
+
+		hlist_for_each_entry_safe(fi, node, n, head, fib_hash) {
+			struct hlist_head *dest;
+			unsigned int new_hash;
+
+			hlist_del(&fi->fib_hash);
+
+			new_hash = fib_info_hashfn(fi);
+			dest = &new_info_hash[new_hash];
+			hlist_add_head(&fi->fib_hash, dest);
+		}
+	}
+	fib_info_hash = new_info_hash;
+
+	for (i = 0; i < old_size; i++) {
+		struct hlist_head *lhead = &fib_info_laddrhash[i];
+		struct hlist_node *node, *n;
+		struct fib_info *fi;
+
+		hlist_for_each_entry_safe(fi, node, n, lhead, fib_lhash) {
+			struct hlist_head *ldest;
+			unsigned int new_hash;
+
+			hlist_del(&fi->fib_lhash);
+
+			new_hash = fib_laddr_hashfn(fi->fib_prefsrc);
+			ldest = &new_laddrhash[new_hash];
+			hlist_add_head(&fi->fib_lhash, ldest);
+		}
+	}
+	fib_info_laddrhash = new_laddrhash;
+
+	write_unlock(&fib_info_lock);
+}
+
 struct fib_info *
 fib_create_info(const struct rtmsg *r, struct kern_rta *rta,
 		const struct nlmsghdr *nlh, int *errp)
@@ -483,15 +592,45 @@
 	}
 #endif
 
-	fi = kmalloc(sizeof(*fi)+nhs*sizeof(struct fib_nh), GFP_KERNEL);
 	err = -ENOBUFS;
+	if (fib_info_cnt >= fib_hash_size) {
+		unsigned int new_size = fib_hash_size << 1;
+		struct hlist_head *new_info_hash;
+		struct hlist_head *new_laddrhash;
+		unsigned int bytes;
+
+		if (!new_size)
+			new_size = 1;
+		bytes = new_size * sizeof(struct hlist_head *);
+		new_info_hash = fib_hash_alloc(bytes);
+		new_laddrhash = fib_hash_alloc(bytes);
+		if (!new_info_hash || !new_laddrhash) {
+			fib_hash_free(new_info_hash, bytes);
+			fib_hash_free(new_laddrhash, bytes);
+		} else {
+			memset(new_info_hash, 0, bytes);
+			memset(new_laddrhash, 0, bytes);
+
+			fib_hash_move(new_info_hash, new_laddrhash, new_size);
+		}
+
+		if (!fib_hash_size)
+			goto failure;
+	}
+
+	fi = kmalloc(sizeof(*fi)+nhs*sizeof(struct fib_nh), GFP_KERNEL);
 	if (fi == NULL)
 		goto failure;
 	fib_info_cnt++;
 	memset(fi, 0, sizeof(*fi)+nhs*sizeof(struct fib_nh));
 
 	fi->fib_protocol = r->rtm_protocol;
+
 	fi->fib_nhs = nhs;
+	change_nexthops(fi) {
+		nh->nh_parent = fi;
+	} endfor_nexthops(fi)
+
 	fi->fib_flags = r->rtm_flags;
 	if (rta->rta_priority)
 		fi->fib_priority = *rta->rta_priority;
@@ -543,15 +682,6 @@
 #endif
 	}
 
-#ifdef CONFIG_IP_ROUTE_NAT
-	if (r->rtm_type == RTN_NAT) {
-		if (rta->rta_gw == NULL || nhs != 1 || rta->rta_oif)
-			goto err_inval;
-		memcpy(&fi->fib_nh->nh_gw, rta->rta_gw, 4);
-		goto link_it;
-	}
-#endif
-
 	if (fib_props[r->rtm_type].error) {
 		if (rta->rta_gw || rta->rta_oif || rta->rta_mp)
 			goto err_inval;
@@ -597,11 +727,24 @@
 	fi->fib_treeref++;
 	atomic_inc(&fi->fib_clntref);
 	write_lock(&fib_info_lock);
-	fi->fib_next = fib_info_list;
-	fi->fib_prev = NULL;
-	if (fib_info_list)
-		fib_info_list->fib_prev = fi;
-	fib_info_list = fi;
+	hlist_add_head(&fi->fib_hash,
+		       &fib_info_hash[fib_info_hashfn(fi)]);
+	if (fi->fib_prefsrc) {
+		struct hlist_head *head;
+
+		head = &fib_info_laddrhash[fib_laddr_hashfn(fi->fib_prefsrc)];
+		hlist_add_head(&fi->fib_lhash, head);
+	}
+	change_nexthops(fi) {
+		struct hlist_head *head;
+		unsigned int hash;
+
+		if (!nh->nh_dev)
+			continue;
+		hash = fib_devindex_hashfn(nh->nh_dev->ifindex);
+		head = &fib_info_devhash[hash];
+		hlist_add_head(&nh->nh_hash, head);
+	} endfor_nexthops(fi)
 	write_unlock(&fib_info_lock);
 	return fi;
 
@@ -617,57 +760,73 @@
 	return NULL;
 }
 
-int 
-fib_semantic_match(int type, struct fib_info *fi, const struct flowi *flp, struct fib_result *res)
+int fib_semantic_match(struct list_head *head, const struct flowi *flp,
+		       struct fib_result *res, int prefixlen)
 {
-	int err = fib_props[type].error;
+	struct fib_alias *fa;
+	int nh_sel = 0;
 
-	if (err == 0) {
-		if (fi->fib_flags&RTNH_F_DEAD)
-			return 1;
+	list_for_each_entry(fa, head, fa_list) {
+		int err;
 
-		res->fi = fi;
+		if (fa->fa_tos &&
+		    fa->fa_tos != flp->fl4_tos)
+			continue;
 
-		switch (type) {
-#ifdef CONFIG_IP_ROUTE_NAT
-		case RTN_NAT:
-			FIB_RES_RESET(*res);
-			atomic_inc(&fi->fib_clntref);
-			return 0;
-#endif
-		case RTN_UNICAST:
-		case RTN_LOCAL:
-		case RTN_BROADCAST:
-		case RTN_ANYCAST:
-		case RTN_MULTICAST:
-			for_nexthops(fi) {
-				if (nh->nh_flags&RTNH_F_DEAD)
-					continue;
-				if (!flp->oif || flp->oif == nh->nh_oif)
-					break;
-			}
+		if (fa->fa_scope < flp->fl4_scope)
+			continue;
+
+		fa->fa_state |= FA_S_ACCESSED;
+
+		err = fib_props[fa->fa_type].error;
+		if (err == 0) {
+			struct fib_info *fi = fa->fa_info;
+
+			if (fi->fib_flags & RTNH_F_DEAD)
+				continue;
+
+			switch (fa->fa_type) {
+			case RTN_UNICAST:
+			case RTN_LOCAL:
+			case RTN_BROADCAST:
+			case RTN_ANYCAST:
+			case RTN_MULTICAST:
+				for_nexthops(fi) {
+					if (nh->nh_flags&RTNH_F_DEAD)
+						continue;
+					if (!flp->oif || flp->oif == nh->nh_oif)
+						break;
+				}
 #ifdef CONFIG_IP_ROUTE_MULTIPATH
-			if (nhsel < fi->fib_nhs) {
-				res->nh_sel = nhsel;
-				atomic_inc(&fi->fib_clntref);
-				return 0;
-			}
+				if (nhsel < fi->fib_nhs) {
+					nh_sel = nhsel;
+					goto out_fill_res;
+				}
 #else
-			if (nhsel < 1) {
-				atomic_inc(&fi->fib_clntref);
-				return 0;
-			}
+				if (nhsel < 1) {
+					goto out_fill_res;
+				}
 #endif
-			endfor_nexthops(fi);
-			res->fi = NULL;
-			return 1;
-		default:
-			res->fi = NULL;
-			printk(KERN_DEBUG "impossible 102\n");
-			return -EINVAL;
+				endfor_nexthops(fi);
+				continue;
+
+			default:
+				printk(KERN_DEBUG "impossible 102\n");
+				return -EINVAL;
+			};
 		}
+		return err;
 	}
-	return err;
+	return 1;
+
+out_fill_res:
+	res->prefixlen = prefixlen;
+	res->nh_sel = nh_sel;
+	res->type = fa->fa_type;
+	res->scope = fa->fa_scope;
+	res->fi = fa->fa_info;
+	atomic_inc(&res->fi->fib_clntref);
+	return 0;
 }
 
 /* Find appropriate source address to this destination */
@@ -906,13 +1065,36 @@
 	if (force)
 		scope = -1;
 
-	for_fib_info() {
-		if (local && fi->fib_prefsrc == local) {
-			fi->fib_flags |= RTNH_F_DEAD;
-			ret++;
-		} else if (dev && fi->fib_nhs) {
-			int dead = 0;
+	if (local && fib_info_laddrhash) {
+		unsigned int hash = fib_laddr_hashfn(local);
+		struct hlist_head *head = &fib_info_laddrhash[hash];
+		struct hlist_node *node;
+		struct fib_info *fi;
 
+		hlist_for_each_entry(fi, node, head, fib_lhash) {
+			if (fi->fib_prefsrc == local) {
+				fi->fib_flags |= RTNH_F_DEAD;
+				ret++;
+			}
+		}
+	}
+
+	if (dev) {
+		struct fib_info *prev_fi = NULL;
+		unsigned int hash = fib_devindex_hashfn(dev->ifindex);
+		struct hlist_head *head = &fib_info_devhash[hash];
+		struct hlist_node *node;
+		struct fib_nh *nh;
+
+		hlist_for_each_entry(nh, node, head, nh_hash) {
+			struct fib_info *fi = nh->nh_parent;
+			int dead;
+
+			BUG_ON(!fi->fib_nhs);
+			if (nh->nh_dev != dev || fi == prev_fi)
+				continue;
+			prev_fi = fi;
+			dead = 0;
 			change_nexthops(fi) {
 				if (nh->nh_flags&RTNH_F_DEAD)
 					dead++;
@@ -939,7 +1121,8 @@
 				ret++;
 			}
 		}
-	} endfor_fib_info();
+	}
+
 	return ret;
 }
 
@@ -952,14 +1135,31 @@
 
 int fib_sync_up(struct net_device *dev)
 {
-	int ret = 0;
+	struct fib_info *prev_fi;
+	unsigned int hash;
+	struct hlist_head *head;
+	struct hlist_node *node;
+	struct fib_nh *nh;
+	int ret;
 
 	if (!(dev->flags&IFF_UP))
 		return 0;
 
-	for_fib_info() {
-		int alive = 0;
+	prev_fi = NULL;
+	hash = fib_devindex_hashfn(dev->ifindex);
+	head = &fib_info_devhash[hash];
+	ret = 0;
+
+	hlist_for_each_entry(nh, node, head, nh_hash) {
+		struct fib_info *fi = nh->nh_parent;
+		int alive;
 
+		BUG_ON(!fi->fib_nhs);
+		if (nh->nh_dev != dev || fi == prev_fi)
+			continue;
+
+		prev_fi = fi;
+		alive = 0;
 		change_nexthops(fi) {
 			if (!(nh->nh_flags&RTNH_F_DEAD)) {
 				alive++;
@@ -980,7 +1180,8 @@
 			fi->fib_flags &= ~RTNH_F_DEAD;
 			ret++;
 		}
-	} endfor_fib_info();
+	}
+
 	return ret;
 }
 
diff -Nru a/net/ipv4/icmp.c b/net/ipv4/icmp.c
--- a/net/ipv4/icmp.c	2004-10-18 14:57:04 -07:00
+++ b/net/ipv4/icmp.c	2004-10-18 14:57:04 -07:00
@@ -478,20 +478,25 @@
 		 *	ICMP error
 		 */
 		if (iph->protocol == IPPROTO_ICMP) {
-			u8 inner_type;
+			u8 _inner_type, *itp;
 
-			if (skb_copy_bits(skb_in,
-					  skb_in->nh.raw + (iph->ihl << 2) +
-					  offsetof(struct icmphdr, type) -
-					  skb_in->data, &inner_type, 1))
+			itp = skb_header_pointer(skb_in,
+						 skb_in->nh.raw +
+						 (iph->ihl << 2) +
+						 offsetof(struct icmphdr,
+							  type) -
+						 skb_in->data,
+						 sizeof(_inner_type),
+						 &_inner_type);
+			if (itp == NULL)
 				goto out;
 
 			/*
 			 *	Assume any unknown ICMP type is an error. This
 			 *	isn't specified by the RFC, but think about it..
 			 */
-			if (inner_type > NR_ICMP_TYPES ||
-			    icmp_pointers[inner_type].error)
+			if (*itp > NR_ICMP_TYPES ||
+			    icmp_pointers[*itp].error)
 				goto out;
 		}
 	}
@@ -503,16 +508,6 @@
 	 *	Construct source address and options.
 	 */
 
-#ifdef CONFIG_IP_ROUTE_NAT
-	/*
-	 *	Restore original addresses if packet has been translated.
-	 */
-	if (rt->rt_flags & RTCF_NAT && IPCB(skb_in)->flags & IPSKB_TRANSLATED) {
-		iph->daddr = rt->fl.fl4_dst;
-		iph->saddr = rt->fl.fl4_src;
-	}
-#endif
-
 	saddr = iph->daddr;
 	if (!(rt->rt_flags & RTCF_LOCAL))
 		saddr = 0;
@@ -705,8 +700,7 @@
 	read_unlock(&raw_v4_lock);
 
 	rcu_read_lock();
-	ipprot = inet_protos[hash];
-	smp_read_barrier_depends();
+	ipprot = rcu_dereference(inet_protos[hash]);
 	if (ipprot && ipprot->err_handler)
 		ipprot->err_handler(skb, info);
 	rcu_read_unlock();
@@ -880,7 +874,6 @@
 	struct net_device *dev = skb->dev;
 	struct in_device *in_dev;
 	struct in_ifaddr *ifa;
-	u32 mask;
 
 	if (skb->len < 4 || !(rt->rt_flags&RTCF_DIRECTSRC))
 		goto out;
@@ -888,24 +881,27 @@
 	in_dev = in_dev_get(dev);
 	if (!in_dev)
 		goto out;
-	read_lock(&in_dev->lock);
+	rcu_read_lock();
 	if (in_dev->ifa_list &&
 	    IN_DEV_LOG_MARTIANS(in_dev) &&
 	    IN_DEV_FORWARD(in_dev)) {
-		if (skb_copy_bits(skb, 0, &mask, 4))
+		u32 _mask, *mp;
+
+		mp = skb_header_pointer(skb, 0, sizeof(_mask), &_mask);
+		if (mp == NULL)
 			BUG();
 		for (ifa = in_dev->ifa_list; ifa; ifa = ifa->ifa_next) {
-			if (mask == ifa->ifa_mask &&
+			if (*mp == ifa->ifa_mask &&
 			    inet_ifa_match(rt->rt_src, ifa))
 				break;
 		}
 		if (!ifa && net_ratelimit()) {
 			printk(KERN_INFO "Wrong address mask %u.%u.%u.%u from "
 					 "%s/%u.%u.%u.%u\n",
-			       NIPQUAD(mask), dev->name, NIPQUAD(rt->rt_src));
+			       NIPQUAD(*mp), dev->name, NIPQUAD(rt->rt_src));
 		}
 	}
-	read_unlock(&in_dev->lock);
+	rcu_read_unlock();
 	in_dev_put(in_dev);
 out:;
 }
diff -Nru a/net/ipv4/igmp.c b/net/ipv4/igmp.c
--- a/net/ipv4/igmp.c	2004-10-18 14:57:04 -07:00
+++ b/net/ipv4/igmp.c	2004-10-18 14:57:04 -07:00
@@ -487,7 +487,7 @@
 	int type;
 
 	if (!pmc) {
-		read_lock(&in_dev->lock);
+		read_lock(&in_dev->mc_list_lock);
 		for (pmc=in_dev->mc_list; pmc; pmc=pmc->next) {
 			if (pmc->multiaddr == IGMP_ALL_HOSTS)
 				continue;
@@ -499,7 +499,7 @@
 			skb = add_grec(skb, pmc, type, 0, 0);
 			spin_unlock_bh(&pmc->lock);
 		}
-		read_unlock(&in_dev->lock);
+		read_unlock(&in_dev->mc_list_lock);
 	} else {
 		spin_lock_bh(&pmc->lock);
 		if (pmc->sfcount[MCAST_EXCLUDE])
@@ -541,8 +541,8 @@
 	struct sk_buff *skb = NULL;
 	int type, dtype;
 
-	read_lock(&in_dev->lock);
-	write_lock_bh(&in_dev->mc_lock);
+	read_lock(&in_dev->mc_list_lock);
+	spin_lock_bh(&in_dev->mc_tomb_lock);
 
 	/* deleted MCA's */
 	pmc_prev = NULL;
@@ -575,7 +575,7 @@
 		} else
 			pmc_prev = pmc;
 	}
-	write_unlock_bh(&in_dev->mc_lock);
+	spin_unlock_bh(&in_dev->mc_tomb_lock);
 
 	/* change recs */
 	for (pmc=in_dev->mc_list; pmc; pmc=pmc->next) {
@@ -601,7 +601,8 @@
 		}
 		spin_unlock_bh(&pmc->lock);
 	}
-	read_unlock(&in_dev->lock);
+	read_unlock(&in_dev->mc_list_lock);
+
 	if (!skb)
 		return;
 	(void) igmpv3_sendpack(skb);
@@ -759,14 +760,14 @@
 	if (group == IGMP_ALL_HOSTS)
 		return;
 
-	read_lock(&in_dev->lock);
+	read_lock(&in_dev->mc_list_lock);
 	for (im=in_dev->mc_list; im!=NULL; im=im->next) {
 		if (im->multiaddr == group) {
 			igmp_stop_timer(im);
 			break;
 		}
 	}
-	read_unlock(&in_dev->lock);
+	read_unlock(&in_dev->mc_list_lock);
 }
 
 static void igmp_heard_query(struct in_device *in_dev, struct sk_buff *skb,
@@ -840,7 +841,7 @@
 	 * - Use the igmp->igmp_code field as the maximum
 	 *   delay possible
 	 */
-	read_lock(&in_dev->lock);
+	read_lock(&in_dev->mc_list_lock);
 	for (im=in_dev->mc_list; im!=NULL; im=im->next) {
 		if (group && group != im->multiaddr)
 			continue;
@@ -856,7 +857,7 @@
 		spin_unlock_bh(&im->lock);
 		igmp_mod_timer(im, max_delay);
 	}
-	read_unlock(&in_dev->lock);
+	read_unlock(&in_dev->mc_list_lock);
 }
 
 int igmp_rcv(struct sk_buff *skb)
@@ -982,10 +983,10 @@
 	}
 	spin_unlock_bh(&im->lock);
 
-	write_lock_bh(&in_dev->mc_lock);
+	spin_lock_bh(&in_dev->mc_tomb_lock);
 	pmc->next = in_dev->mc_tomb;
 	in_dev->mc_tomb = pmc;
-	write_unlock_bh(&in_dev->mc_lock);
+	spin_unlock_bh(&in_dev->mc_tomb_lock);
 }
 
 static void igmpv3_del_delrec(struct in_device *in_dev, __u32 multiaddr)
@@ -993,7 +994,7 @@
 	struct ip_mc_list *pmc, *pmc_prev;
 	struct ip_sf_list *psf, *psf_next;
 
-	write_lock_bh(&in_dev->mc_lock);
+	spin_lock_bh(&in_dev->mc_tomb_lock);
 	pmc_prev = NULL;
 	for (pmc=in_dev->mc_tomb; pmc; pmc=pmc->next) {
 		if (pmc->multiaddr == multiaddr)
@@ -1006,7 +1007,7 @@
 		else
 			in_dev->mc_tomb = pmc->next;
 	}
-	write_unlock_bh(&in_dev->mc_lock);
+	spin_unlock_bh(&in_dev->mc_tomb_lock);
 	if (pmc) {
 		for (psf=pmc->tomb; psf; psf=psf_next) {
 			psf_next = psf->sf_next;
@@ -1021,10 +1022,10 @@
 {
 	struct ip_mc_list *pmc, *nextpmc;
 
-	write_lock_bh(&in_dev->mc_lock);
+	spin_lock_bh(&in_dev->mc_tomb_lock);
 	pmc = in_dev->mc_tomb;
 	in_dev->mc_tomb = NULL;
-	write_unlock_bh(&in_dev->mc_lock);
+	spin_unlock_bh(&in_dev->mc_tomb_lock);
 
 	for (; pmc; pmc = nextpmc) {
 		nextpmc = pmc->next;
@@ -1033,7 +1034,7 @@
 		kfree(pmc);
 	}
 	/* clear dead sources, too */
-	read_lock(&in_dev->lock);
+	read_lock(&in_dev->mc_list_lock);
 	for (pmc=in_dev->mc_list; pmc; pmc=pmc->next) {
 		struct ip_sf_list *psf, *psf_next;
 
@@ -1046,7 +1047,7 @@
 			kfree(psf);
 		}
 	}
-	read_unlock(&in_dev->lock);
+	read_unlock(&in_dev->mc_list_lock);
 }
 #endif
 
@@ -1167,10 +1168,10 @@
 	im->gsquery = 0;
 #endif
 	im->loaded = 0;
-	write_lock_bh(&in_dev->lock);
+	write_lock_bh(&in_dev->mc_list_lock);
 	im->next=in_dev->mc_list;
 	in_dev->mc_list=im;
-	write_unlock_bh(&in_dev->lock);
+	write_unlock_bh(&in_dev->mc_list_lock);
 #ifdef CONFIG_IP_MULTICAST
 	igmpv3_del_delrec(in_dev, im->multiaddr);
 #endif
@@ -1194,9 +1195,9 @@
 	for (ip=&in_dev->mc_list; (i=*ip)!=NULL; ip=&i->next) {
 		if (i->multiaddr==addr) {
 			if (--i->users == 0) {
-				write_lock_bh(&in_dev->lock);
+				write_lock_bh(&in_dev->mc_list_lock);
 				*ip = i->next;
-				write_unlock_bh(&in_dev->lock);
+				write_unlock_bh(&in_dev->mc_list_lock);
 				igmp_group_dropped(i);
 
 				if (!in_dev->dead)
@@ -1251,7 +1252,8 @@
 	in_dev->mr_qrv = IGMP_Unsolicited_Report_Count;
 #endif
 
-	in_dev->mc_lock = RW_LOCK_UNLOCKED;
+	in_dev->mc_list_lock = RW_LOCK_UNLOCKED;
+	in_dev->mc_tomb_lock = SPIN_LOCK_UNLOCKED;
 }
 
 /* Device going up */
@@ -1281,17 +1283,17 @@
 	/* Deactivate timers */
 	ip_mc_down(in_dev);
 
-	write_lock_bh(&in_dev->lock);
+	write_lock_bh(&in_dev->mc_list_lock);
 	while ((i = in_dev->mc_list) != NULL) {
 		in_dev->mc_list = i->next;
-		write_unlock_bh(&in_dev->lock);
+		write_unlock_bh(&in_dev->mc_list_lock);
 
 		igmp_group_dropped(i);
 		ip_ma_put(i);
 
-		write_lock_bh(&in_dev->lock);
+		write_lock_bh(&in_dev->mc_list_lock);
 	}
-	write_unlock_bh(&in_dev->lock);
+	write_unlock_bh(&in_dev->mc_list_lock);
 }
 
 static struct in_device * ip_mc_find_dev(struct ip_mreqn *imr)
@@ -1391,18 +1393,18 @@
 
 	if (!in_dev)
 		return -ENODEV;
-	read_lock(&in_dev->lock);
+	read_lock(&in_dev->mc_list_lock);
 	for (pmc=in_dev->mc_list; pmc; pmc=pmc->next) {
 		if (*pmca == pmc->multiaddr)
 			break;
 	}
 	if (!pmc) {
 		/* MCA not found?? bug */
-		read_unlock(&in_dev->lock);
+		read_unlock(&in_dev->mc_list_lock);
 		return -ESRCH;
 	}
 	spin_lock_bh(&pmc->lock);
-	read_unlock(&in_dev->lock);
+	read_unlock(&in_dev->mc_list_lock);
 #ifdef CONFIG_IP_MULTICAST
 	sf_markstate(pmc);
 #endif
@@ -1527,18 +1529,18 @@
 
 	if (!in_dev)
 		return -ENODEV;
-	read_lock(&in_dev->lock);
+	read_lock(&in_dev->mc_list_lock);
 	for (pmc=in_dev->mc_list; pmc; pmc=pmc->next) {
 		if (*pmca == pmc->multiaddr)
 			break;
 	}
 	if (!pmc) {
 		/* MCA not found?? bug */
-		read_unlock(&in_dev->lock);
+		read_unlock(&in_dev->mc_list_lock);
 		return -ESRCH;
 	}
 	spin_lock_bh(&pmc->lock);
-	read_unlock(&in_dev->lock);
+	read_unlock(&in_dev->mc_list_lock);
 
 #ifdef CONFIG_IP_MULTICAST
 	sf_markstate(pmc);
@@ -2095,7 +2097,7 @@
 	struct ip_sf_list *psf;
 	int rv = 0;
 
-	read_lock(&in_dev->lock);
+	read_lock(&in_dev->mc_list_lock);
 	for (im=in_dev->mc_list; im; im=im->next) {
 		if (im->multiaddr == mc_addr)
 			break;
@@ -2117,7 +2119,7 @@
 		} else
 			rv = 1; /* unspecified source; tentatively allow */
 	}
-	read_unlock(&in_dev->lock);
+	read_unlock(&in_dev->mc_list_lock);
 	return rv;
 }
 
@@ -2141,13 +2143,13 @@
 		in_dev = in_dev_get(state->dev);
 		if (!in_dev)
 			continue;
-		read_lock(&in_dev->lock);
+		read_lock(&in_dev->mc_list_lock);
 		im = in_dev->mc_list;
 		if (im) {
 			state->in_dev = in_dev;
 			break;
 		}
-		read_unlock(&in_dev->lock);
+		read_unlock(&in_dev->mc_list_lock);
 		in_dev_put(in_dev);
 	}
 	return im;
@@ -2159,7 +2161,7 @@
 	im = im->next;
 	while (!im) {
 		if (likely(state->in_dev != NULL)) {
-			read_unlock(&state->in_dev->lock);
+			read_unlock(&state->in_dev->mc_list_lock);
 			in_dev_put(state->in_dev);
 		}
 		state->dev = state->dev->next;
@@ -2170,7 +2172,7 @@
 		state->in_dev = in_dev_get(state->dev);
 		if (!state->in_dev)
 			continue;
-		read_lock(&state->in_dev->lock);
+		read_lock(&state->in_dev->mc_list_lock);
 		im = state->in_dev->mc_list;
 	}
 	return im;
@@ -2206,7 +2208,7 @@
 {
 	struct igmp_mc_iter_state *state = igmp_mc_seq_private(seq);
 	if (likely(state->in_dev != NULL)) {
-		read_unlock(&state->in_dev->lock);
+		read_unlock(&state->in_dev->mc_list_lock);
 		in_dev_put(state->in_dev);
 		state->in_dev = NULL;
 	}
@@ -2304,7 +2306,7 @@
 		idev = in_dev_get(state->dev);
 		if (unlikely(idev == NULL))
 			continue;
-		read_lock_bh(&idev->lock);
+		read_lock(&idev->mc_list_lock);
 		im = idev->mc_list;
 		if (likely(im != NULL)) {
 			spin_lock_bh(&im->lock);
@@ -2316,7 +2318,7 @@
 			}
 			spin_unlock_bh(&im->lock);
 		}
-		read_unlock_bh(&idev->lock);
+		read_unlock(&idev->mc_list_lock);
 		in_dev_put(idev);
 	}
 	return psf;
@@ -2332,7 +2334,7 @@
 		state->im = state->im->next;
 		while (!state->im) {
 			if (likely(state->idev != NULL)) {
-				read_unlock_bh(&state->idev->lock);
+				read_unlock(&state->idev->mc_list_lock);
 				in_dev_put(state->idev);
 			}
 			state->dev = state->dev->next;
@@ -2343,7 +2345,7 @@
 			state->idev = in_dev_get(state->dev);
 			if (!state->idev)
 				continue;
-			read_lock_bh(&state->idev->lock);
+			read_lock(&state->idev->mc_list_lock);
 			state->im = state->idev->mc_list;
 		}
 		if (!state->im)
@@ -2389,7 +2391,7 @@
 		state->im = NULL;
 	}
 	if (likely(state->idev != NULL)) {
-		read_unlock_bh(&state->idev->lock);
+		read_unlock(&state->idev->mc_list_lock);
 		in_dev_put(state->idev);
 		state->idev = NULL;
 	}
diff -Nru a/net/ipv4/ip_fragment.c b/net/ipv4/ip_fragment.c
--- a/net/ipv4/ip_fragment.c	2004-10-18 14:56:27 -07:00
+++ b/net/ipv4/ip_fragment.c	2004-10-18 14:56:27 -07:00
@@ -169,14 +169,18 @@
 atomic_t ip_frag_mem = ATOMIC_INIT(0);	/* Memory used for fragments */
 
 /* Memory Tracking Functions. */
-static __inline__ void frag_kfree_skb(struct sk_buff *skb)
+static __inline__ void frag_kfree_skb(struct sk_buff *skb, int *work)
 {
+	if (work)
+		*work -= skb->truesize;
 	atomic_sub(skb->truesize, &ip_frag_mem);
 	kfree_skb(skb);
 }
 
-static __inline__ void frag_free_queue(struct ipq *qp)
+static __inline__ void frag_free_queue(struct ipq *qp, int *work)
 {
+	if (work)
+		*work -= sizeof(struct ipq);
 	atomic_sub(sizeof(struct ipq), &ip_frag_mem);
 	kfree(qp);
 }
@@ -195,7 +199,7 @@
 /* Destruction primitives. */
 
 /* Complete destruction of ipq. */
-static void ip_frag_destroy(struct ipq *qp)
+static void ip_frag_destroy(struct ipq *qp, int *work)
 {
 	struct sk_buff *fp;
 
@@ -207,18 +211,18 @@
 	while (fp) {
 		struct sk_buff *xp = fp->next;
 
-		frag_kfree_skb(fp);
+		frag_kfree_skb(fp, work);
 		fp = xp;
 	}
 
 	/* Finally, release the queue descriptor itself. */
-	frag_free_queue(qp);
+	frag_free_queue(qp, work);
 }
 
-static __inline__ void ipq_put(struct ipq *ipq)
+static __inline__ void ipq_put(struct ipq *ipq, int *work)
 {
 	if (atomic_dec_and_test(&ipq->refcnt))
-		ip_frag_destroy(ipq);
+		ip_frag_destroy(ipq, work);
 }
 
 /* Kill ipq entry. It is not destroyed immediately,
@@ -237,16 +241,19 @@
 }
 
 /* Memory limiting on fragments.  Evictor trashes the oldest 
- * fragment queue until we are back under the low threshold.
+ * fragment queue until we are back under the threshold.
  */
-static void ip_evictor(void)
+static void __ip_evictor(int threshold)
 {
 	struct ipq *qp;
 	struct list_head *tmp;
+	int work;
 
-	for(;;) {
-		if (atomic_read(&ip_frag_mem) <= sysctl_ipfrag_low_thresh)
-			return;
+	work = atomic_read(&ip_frag_mem) - threshold;
+	if (work <= 0)
+		return;
+
+	while (work > 0) {
 		read_lock(&ipfrag_lock);
 		if (list_empty(&ipq_lru_list)) {
 			read_unlock(&ipfrag_lock);
@@ -262,11 +269,16 @@
 			ipq_kill(qp);
 		spin_unlock(&qp->lock);
 
-		ipq_put(qp);
+		ipq_put(qp, &work);
 		IP_INC_STATS_BH(IPSTATS_MIB_REASMFAILS);
 	}
 }
 
+static inline void ip_evictor(void)
+{
+	__ip_evictor(sysctl_ipfrag_low_thresh);
+}
+
 /*
  * Oops, a fragment queue timed out.  Kill it and send an ICMP reply.
  */
@@ -294,7 +306,7 @@
 	}
 out:
 	spin_unlock(&qp->lock);
-	ipq_put(qp);
+	ipq_put(qp, NULL);
 }
 
 /* Creation primitives. */
@@ -317,7 +329,7 @@
 			atomic_inc(&qp->refcnt);
 			write_unlock(&ipfrag_lock);
 			qp_in->last_in |= COMPLETE;
-			ipq_put(qp_in);
+			ipq_put(qp_in, NULL);
 			return qp;
 		}
 	}
@@ -506,7 +518,7 @@
 				qp->fragments = next;
 
 			qp->meat -= free_it->len;
-			frag_kfree_skb(free_it);
+			frag_kfree_skb(free_it, NULL);
 		}
 	}
 
@@ -657,7 +669,7 @@
 			ret = ip_frag_reasm(qp, dev);
 
 		spin_unlock(&qp->lock);
-		ipq_put(qp);
+		ipq_put(qp, NULL);
 		return ret;
 	}
 
@@ -677,4 +689,10 @@
 	add_timer(&ipfrag_secret_timer);
 }
 
+void ipfrag_flush(void)
+{
+	__ip_evictor(0);
+}
+
 EXPORT_SYMBOL(ip_defrag);
+EXPORT_SYMBOL(ipfrag_flush);
diff -Nru a/net/ipv4/ip_gre.c b/net/ipv4/ip_gre.c
--- a/net/ipv4/ip_gre.c	2004-10-18 14:56:49 -07:00
+++ b/net/ipv4/ip_gre.c	2004-10-18 14:56:49 -07:00
@@ -36,6 +36,7 @@
 #include <net/ipip.h>
 #include <net/arp.h>
 #include <net/checksum.h>
+#include <net/dsfield.h>
 #include <net/inet_ecn.h>
 #include <net/xfrm.h>
 
@@ -533,11 +534,9 @@
 {
 	if (INET_ECN_is_ce(iph->tos)) {
 		if (skb->protocol == htons(ETH_P_IP)) {
-			if (INET_ECN_is_not_ce(skb->nh.iph->tos))
-				IP_ECN_set_ce(skb->nh.iph);
+			IP_ECN_set_ce(skb->nh.iph);
 		} else if (skb->protocol == htons(ETH_P_IPV6)) {
-			if (INET_ECN_is_not_ce(ip6_get_dsfield(skb->nh.ipv6h)))
-				IP6_ECN_set_ce(skb->nh.ipv6h);
+			IP6_ECN_set_ce(skb->nh.ipv6h);
 		}
 	}
 }
@@ -549,7 +548,7 @@
 	if (skb->protocol == htons(ETH_P_IP))
 		inner = old_iph->tos;
 	else if (skb->protocol == htons(ETH_P_IPV6))
-		inner = ip6_get_dsfield((struct ipv6hdr*)old_iph);
+		inner = ipv6_get_dsfield((struct ipv6hdr *)old_iph);
 	return INET_ECN_encapsulate(tos, inner);
 }
 
@@ -605,13 +604,24 @@
 	if ((tunnel = ipgre_tunnel_lookup(iph->saddr, iph->daddr, key)) != NULL) {
 		secpath_reset(skb);
 
+		skb->protocol = *(u16*)(h + 2);
+		/* WCCP version 1 and 2 protocol decoding.
+		 * - Change protocol to IP
+		 * - When dealing with WCCPv2, Skip extra 4 bytes in GRE header
+		 */
+		if (flags == 0 &&
+		    skb->protocol == __constant_htons(ETH_P_WCCP)) {
+			skb->protocol = __constant_htons(ETH_P_IP);
+			if ((*(h + offset) & 0xF0) != 0x40) 
+				offset += 4;
+		}
+
 		skb->mac.raw = skb->nh.raw;
 		skb->nh.raw = __pskb_pull(skb, offset);
 		memset(&(IPCB(skb)->opt), 0, sizeof(struct ip_options));
 		if (skb->ip_summed == CHECKSUM_HW)
 			skb->csum = csum_sub(skb->csum,
 					     csum_partial(skb->mac.raw, skb->nh.raw-skb->mac.raw, 0));
-		skb->protocol = *(u16*)(h + 2);
 		skb->pkt_type = PACKET_HOST;
 #ifdef CONFIG_NET_IPGRE_BROADCAST
 		if (MULTICAST(iph->daddr)) {
@@ -1240,7 +1250,7 @@
 
 static int __init ipgre_init(void)
 {
-	int err = -EINVAL;
+	int err;
 
 	printk(KERN_INFO "GRE over IPv4 tunneling driver\n");
 
@@ -1253,18 +1263,19 @@
 					   ipgre_tunnel_setup);
 	if (!ipgre_fb_tunnel_dev) {
 		err = -ENOMEM;
-		goto fail;
+		goto err1;
 	}
 
 	ipgre_fb_tunnel_dev->init = ipgre_fb_tunnel_init;
 
 	if ((err = register_netdev(ipgre_fb_tunnel_dev)))
-		goto fail;
+		goto err2;
 out:
 	return err;
-fail:
-	inet_del_protocol(&ipgre_protocol, IPPROTO_GRE);
+err2:
 	free_netdev(ipgre_fb_tunnel_dev);
+err1:
+	inet_del_protocol(&ipgre_protocol, IPPROTO_GRE);
 	goto out;
 }
 
diff -Nru a/net/ipv4/ip_input.c b/net/ipv4/ip_input.c
--- a/net/ipv4/ip_input.c	2004-10-18 14:55:54 -07:00
+++ b/net/ipv4/ip_input.c	2004-10-18 14:55:54 -07:00
@@ -231,10 +231,9 @@
 		if (raw_sk)
 			raw_v4_input(skb, skb->nh.iph, hash);
 
-		if ((ipprot = inet_protos[hash]) != NULL) {
+		if ((ipprot = rcu_dereference(inet_protos[hash])) != NULL) {
 			int ret;
 
-			smp_read_barrier_depends();
 			if (!ipprot->no_policy &&
 			    !xfrm4_policy_check(NULL, XFRM_POLICY_IN, skb)) {
 				kfree_skb(skb);
diff -Nru a/net/ipv4/ip_nat_dumb.c b/net/ipv4/ip_nat_dumb.c
--- a/net/ipv4/ip_nat_dumb.c	2004-10-18 14:56:49 -07:00
+++ /dev/null	Wed Dec 31 16:00:00 196900
@@ -1,166 +0,0 @@
-/*
- * INET		An implementation of the TCP/IP protocol suite for the LINUX
- *		operating system.  INET is implemented using the  BSD Socket
- *		interface as the means of communication with the user level.
- *
- *		Dumb Network Address Translation.
- *
- * Version:	$Id: ip_nat_dumb.c,v 1.11 2000/12/13 18:31:48 davem Exp $
- *
- * Authors:	Alexey Kuznetsov, <kuznet@ms2.inr.ac.ru>
- *
- *		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:
- *		Rani Assaf	:	A zero checksum is a special case
- *					only in UDP
- * 		Rani Assaf	:	Added ICMP messages rewriting
- * 		Rani Assaf	:	Repaired wrong changes, made by ANK.
- *
- *
- * NOTE:	It is just working model of real NAT.
- */
-
-#include <linux/config.h>
-#include <linux/types.h>
-#include <linux/mm.h>
-#include <linux/sched.h>
-#include <linux/skbuff.h>
-#include <linux/ip.h>
-#include <linux/icmp.h>
-#include <linux/netdevice.h>
-#include <net/sock.h>
-#include <net/ip.h>
-#include <net/icmp.h>
-#include <linux/tcp.h>
-#include <linux/udp.h>
-#include <net/checksum.h>
-#include <linux/route.h>
-#include <net/route.h>
-#include <net/ip_fib.h>
-
-
-int
-ip_do_nat(struct sk_buff *skb)
-{
-	struct rtable *rt = (struct rtable*)skb->dst;
-	struct iphdr *iph = skb->nh.iph;
-	u32 odaddr = iph->daddr;
-	u32 osaddr = iph->saddr;
-	u16	check;
-
-	IPCB(skb)->flags |= IPSKB_TRANSLATED;
-
-	/* Rewrite IP header */
-	iph->daddr = rt->rt_dst_map;
-	iph->saddr = rt->rt_src_map;
-	iph->check = 0;
-	iph->check = ip_fast_csum((unsigned char *)iph, iph->ihl);
-
-	/* If it is the first fragment, rewrite protocol headers */
-
-	if (!(iph->frag_off & htons(IP_OFFSET))) {
-		u16	*cksum;
-
-		switch(iph->protocol) {
-		case IPPROTO_TCP:
-			cksum  = (u16*)&((struct tcphdr*)(((char*)iph) + (iph->ihl<<2)))->check;
-			if ((u8*)(cksum+1) > skb->tail)
-				goto truncated;
-			check = *cksum;
-			if (skb->ip_summed != CHECKSUM_HW)
-				check = ~check;
-			check = csum_tcpudp_magic(iph->saddr, iph->daddr, 0, 0, check);
-			check = csum_tcpudp_magic(~osaddr, ~odaddr, 0, 0, ~check);
-			if (skb->ip_summed == CHECKSUM_HW)
-				check = ~check;
-			*cksum = check;
-			break;
-		case IPPROTO_UDP:
-			cksum  = (u16*)&((struct udphdr*)(((char*)iph) + (iph->ihl<<2)))->check;
-			if ((u8*)(cksum+1) > skb->tail)
-				goto truncated;
-			if ((check = *cksum) != 0) {
-				check = csum_tcpudp_magic(iph->saddr, iph->daddr, 0, 0, ~check);
-				check = csum_tcpudp_magic(~osaddr, ~odaddr, 0, 0, ~check);
-				*cksum = check ? : 0xFFFF;
-			}
-			break;
-		case IPPROTO_ICMP:
-		{
-			struct icmphdr *icmph = (struct icmphdr*)((char*)iph + (iph->ihl<<2));
-			struct   iphdr *ciph;
-			u32 idaddr, isaddr;
-			int updated;
-
-			if ((icmph->type != ICMP_DEST_UNREACH) &&
-			    (icmph->type != ICMP_TIME_EXCEEDED) &&
-			    (icmph->type != ICMP_PARAMETERPROB))
-				break;
-
-			ciph = (struct iphdr *) (icmph + 1);
-
-			if ((u8*)(ciph+1) > skb->tail)
-				goto truncated;
-
-			isaddr = ciph->saddr;
-			idaddr = ciph->daddr;
-			updated = 0;
-
-			if (rt->rt_flags&RTCF_DNAT && ciph->saddr == odaddr) {
-				ciph->saddr = iph->daddr;
-				updated = 1;
-			}
-			if (rt->rt_flags&RTCF_SNAT) {
-				if (ciph->daddr != osaddr) {
-					struct   fib_result res;
-					unsigned flags = 0;
-					struct flowi fl = {
-						.iif = skb->dev->ifindex,
-						.nl_u =
-						{ .ip4_u =
-						  { .daddr = ciph->saddr,
-						    .saddr = ciph->daddr,
-#ifdef CONFIG_IP_ROUTE_TOS
-						    .tos = RT_TOS(ciph->tos)
-#endif
-						  } },
-						.proto = ciph->protocol };
-
-					/* Use fib_lookup() until we get our own
-					 * hash table of NATed hosts -- Rani
-				 	 */
-					if (fib_lookup(&fl, &res) == 0) {
-						if (res.r) {
-							ciph->daddr = fib_rules_policy(ciph->daddr, &res, &flags);
-							if (ciph->daddr != idaddr)
-								updated = 1;
-						}
-						fib_res_put(&res);
-					}
-				} else {
-					ciph->daddr = iph->saddr;
-					updated = 1;
-				}
-			}
-			if (updated) {
-				cksum  = &icmph->checksum;
-				/* Using tcpudp primitive. Why not? */
-				check  = csum_tcpudp_magic(ciph->saddr, ciph->daddr, 0, 0, ~(*cksum));
-				*cksum = csum_tcpudp_magic(~isaddr, ~idaddr, 0, 0, ~check);
-			}
-			break;
-		}
-		default:
-			break;
-		}
-	}
-	return NET_RX_SUCCESS;
-
-truncated:
-	/* should be return NET_RX_BAD; */
-	return -EINVAL;
-}
diff -Nru a/net/ipv4/ip_output.c b/net/ipv4/ip_output.c
--- a/net/ipv4/ip_output.c	2004-10-18 14:57:04 -07:00
+++ b/net/ipv4/ip_output.c	2004-10-18 14:57:04 -07:00
@@ -78,6 +78,7 @@
 #include <net/raw.h>
 #include <net/checksum.h>
 #include <net/inetpeer.h>
+#include <net/checksum.h>
 #include <linux/igmp.h>
 #include <linux/netfilter_ipv4.h>
 #include <linux/netfilter_bridge.h>
@@ -304,7 +305,6 @@
 	struct ip_options *opt = inet->opt;
 	struct rtable *rt;
 	struct iphdr *iph;
-	u32 mtu;
 
 	/* Skip all of this if the packet is already routed,
 	 * f.e. by something like SCTP.
@@ -365,23 +365,11 @@
 	skb->nh.iph   = iph;
 	/* Transport layer set skb->h.foo itself. */
 
-	if(opt && opt->optlen) {
+	if (opt && opt->optlen) {
 		iph->ihl += opt->optlen >> 2;
 		ip_options_build(skb, opt, inet->daddr, rt, 0);
 	}
 
-	mtu = dst_pmtu(&rt->u.dst);
-	if (skb->len > mtu && (sk->sk_route_caps & NETIF_F_TSO)) {
-		unsigned int hlen;
-
-		/* Hack zone: all this must be done by TCP. */
-		hlen = ((skb->h.raw - skb->data) + (skb->h.th->doff << 2));
-		skb_shinfo(skb)->tso_size = mtu - hlen;
-		skb_shinfo(skb)->tso_segs =
-			(skb->len - hlen + skb_shinfo(skb)->tso_size - 1)/
-				skb_shinfo(skb)->tso_size - 1;
-	}
-
 	ip_select_ident_more(iph, &rt->u.dst, sk, skb_shinfo(skb)->tso_segs);
 
 	/* Add an IP checksum. */
@@ -421,6 +409,7 @@
 	nf_conntrack_put(to->nfct);
 	to->nfct = from->nfct;
 	nf_conntrack_get(to->nfct);
+	to->nfctinfo = from->nfctinfo;
 #ifdef CONFIG_BRIDGE_NETFILTER
 	nf_bridge_put(to->nf_bridge);
 	to->nf_bridge = from->nf_bridge;
@@ -712,7 +701,7 @@
 /*
  *	ip_append_data() and ip_append_page() can make one large IP datagram
  *	from many pieces of data. Each pieces will be holded on the socket
- *	until ip_push_pending_frames() is called. Eache pieces can be a page
+ *	until ip_push_pending_frames() is called. Each piece can be a page
  *	or non-page data.
  *	
  *	Not only UDP, other transport protocols - e.g. raw sockets - can use
@@ -780,7 +769,7 @@
 	hh_len = LL_RESERVED_SPACE(rt->u.dst.dev);
 
 	fragheaderlen = sizeof(struct iphdr) + (opt ? opt->optlen : 0);
-	maxfraglen = ((mtu-fragheaderlen) & ~7) + fragheaderlen;
+	maxfraglen = ((mtu - fragheaderlen) & ~7) + fragheaderlen;
 
 	if (inet->cork.length + length > 0xFFFF - fragheaderlen) {
 		ip_local_error(sk, EMSGSIZE, rt->rt_dst, inet->dport, mtu-exthdrlen);
@@ -792,7 +781,7 @@
 	 * it won't be fragmented in the future.
 	 */
 	if (transhdrlen &&
-	    length + fragheaderlen <= maxfraglen &&
+	    length + fragheaderlen <= mtu &&
 	    rt->u.dst.dev->features&(NETIF_F_IP_CSUM|NETIF_F_NO_CSUM|NETIF_F_HW_CSUM) &&
 	    !exthdrlen)
 		csummode = CHECKSUM_HW;
@@ -804,34 +793,42 @@
 	 * We use calculated fragment length to generate chained skb,
 	 * each of segments is IP fragment ready for sending to network after
 	 * adding appropriate IP header.
-	 *
-	 * Mistake is:
-	 *
-	 *    If mtu-fragheaderlen is not 0 modulo 8, we generate additional
-	 *    small fragment of length (mtu-fragheaderlen)%8, even though
-	 *    it is not necessary. Not a big bug, but needs a fix.
 	 */
 
 	if ((skb = skb_peek_tail(&sk->sk_write_queue)) == NULL)
 		goto alloc_new_skb;
 
 	while (length > 0) {
-		if ((copy = maxfraglen - skb->len) <= 0) {
+		/* Check if the remaining data fits into current packet. */
+		copy = mtu - skb->len;
+		if (copy < length)
+			copy = maxfraglen - skb->len;
+		if (copy <= 0) {
 			char *data;
 			unsigned int datalen;
 			unsigned int fraglen;
+			unsigned int fraggap;
 			unsigned int alloclen;
-			BUG_TRAP(copy == 0);
-
+			struct sk_buff *skb_prev;
 alloc_new_skb:
-			datalen = maxfraglen - fragheaderlen;
-			if (datalen > length)
-				datalen = length;
+			skb_prev = skb;
+			if (skb_prev)
+				fraggap = skb_prev->len - maxfraglen;
+			else
+				fraggap = 0;
 
+			/*
+			 * If remaining data exceeds the mtu,
+			 * we know we need more fragment(s).
+			 */
+			datalen = length + fraggap;
+			if (datalen > mtu - fragheaderlen)
+				datalen = maxfraglen - fragheaderlen;
 			fraglen = datalen + fragheaderlen;
+
 			if ((flags & MSG_MORE) && 
 			    !(rt->u.dst.dev->features&NETIF_F_SG))
-				alloclen = maxfraglen;
+				alloclen = mtu;
 			else
 				alloclen = datalen + fragheaderlen;
 
@@ -875,15 +872,25 @@
 			data += fragheaderlen;
 			skb->h.raw = data + exthdrlen;
 
-			copy = datalen - transhdrlen;
-			if (copy > 0 && getfrag(from, data + transhdrlen, offset, copy, 0, skb) < 0) {
+			if (fraggap) {
+				skb->csum = skb_copy_and_csum_bits(
+					skb_prev, maxfraglen,
+					data + transhdrlen, fraggap, 0);
+				skb_prev->csum = csum_sub(skb_prev->csum,
+							  skb->csum);
+				data += fraggap;
+				skb_trim(skb_prev, maxfraglen);
+			}
+
+			copy = datalen - transhdrlen - fraggap;
+			if (copy > 0 && getfrag(from, data + transhdrlen, offset, copy, fraggap, skb) < 0) {
 				err = -EFAULT;
 				kfree_skb(skb);
 				goto error;
 			}
 
 			offset += copy;
-			length -= datalen;
+			length -= datalen - fraggap;
 			transhdrlen = 0;
 			exthdrlen = 0;
 			csummode = CHECKSUM_NONE;
@@ -978,7 +985,7 @@
 	int mtu;
 	int len;
 	int err;
-	unsigned int maxfraglen, fragheaderlen;
+	unsigned int maxfraglen, fragheaderlen, fraggap;
 
 	if (inet->hdrincl)
 		return -EPERM;
@@ -1000,7 +1007,7 @@
 	mtu = inet->cork.fragsize;
 
 	fragheaderlen = sizeof(struct iphdr) + (opt ? opt->optlen : 0);
-	maxfraglen = ((mtu-fragheaderlen) & ~7) + fragheaderlen;
+	maxfraglen = ((mtu - fragheaderlen) & ~7) + fragheaderlen;
 
 	if (inet->cork.length + size > 0xFFFF - fragheaderlen) {
 		ip_local_error(sk, EMSGSIZE, rt->rt_dst, inet->dport, mtu);
@@ -1014,13 +1021,25 @@
 
 	while (size > 0) {
 		int i;
-		if ((len = maxfraglen - skb->len) <= 0) {
+
+		/* Check if the remaining data fits into current packet. */
+		len = mtu - skb->len;
+		if (len < size)
+			len = maxfraglen - skb->len;
+		if (len <= 0) {
+			struct sk_buff *skb_prev;
 			char *data;
 			struct iphdr *iph;
-			BUG_TRAP(len == 0);
+			int alloclen;
 
-			skb = sock_wmalloc(sk, fragheaderlen + hh_len + 15, 1,
-					   sk->sk_allocation);
+			skb_prev = skb;
+			if (skb_prev)
+				fraggap = skb_prev->len - maxfraglen;
+			else
+				fraggap = 0;
+
+			alloclen = fragheaderlen + hh_len + fraggap + 15;
+			skb = sock_wmalloc(sk, alloclen, 1, sk->sk_allocation);
 			if (unlikely(!skb)) {
 				err = -ENOBUFS;
 				goto error;
@@ -1036,10 +1055,19 @@
 			/*
 			 *	Find where to start putting bytes.
 			 */
-			data = skb_put(skb, fragheaderlen);
+			data = skb_put(skb, fragheaderlen + fraggap);
 			skb->nh.iph = iph = (struct iphdr *)data;
 			data += fragheaderlen;
 			skb->h.raw = data;
+
+			if (fraggap) {
+				skb->csum = skb_copy_and_csum_bits(
+					skb_prev, maxfraglen,
+					data, fraggap, 0);
+				skb_prev->csum = csum_sub(skb_prev->csum,
+							  skb->csum);
+				skb_trim(skb_prev, maxfraglen);
+			}
 
 			/*
 			 * Put the packet on the pending queue.
diff -Nru a/net/ipv4/ipcomp.c b/net/ipv4/ipcomp.c
--- a/net/ipv4/ipcomp.c	2004-10-18 14:56:50 -07:00
+++ b/net/ipv4/ipcomp.c	2004-10-18 14:56:50 -07:00
@@ -16,25 +16,48 @@
 #include <linux/config.h>
 #include <linux/module.h>
 #include <asm/scatterlist.h>
+#include <asm/semaphore.h>
 #include <linux/crypto.h>
 #include <linux/pfkeyv2.h>
+#include <linux/percpu.h>
+#include <linux/smp.h>
+#include <linux/list.h>
+#include <linux/vmalloc.h>
+#include <linux/rtnetlink.h>
 #include <net/ip.h>
 #include <net/xfrm.h>
 #include <net/icmp.h>
 #include <net/ipcomp.h>
 
+struct ipcomp_tfms {
+	struct list_head list;
+	struct crypto_tfm **tfms;
+	int users;
+};
+
+static DECLARE_MUTEX(ipcomp_resource_sem);
+static void **ipcomp_scratches;
+static int ipcomp_scratch_users;
+static LIST_HEAD(ipcomp_tfms_list);
+
 static int ipcomp_decompress(struct xfrm_state *x, struct sk_buff *skb)
 {
 	int err, plen, dlen;
 	struct iphdr *iph;
 	struct ipcomp_data *ipcd = x->data;
-	u8 *start, *scratch = ipcd->scratch;
+	u8 *start, *scratch;
+	struct crypto_tfm *tfm;
+	int cpu;
 	
 	plen = skb->len;
 	dlen = IPCOMP_SCRATCH_SIZE;
 	start = skb->data;
 
-	err = crypto_comp_decompress(ipcd->tfm, start, plen, scratch, &dlen);
+	cpu = get_cpu();
+	scratch = *per_cpu_ptr(ipcomp_scratches, cpu);
+	tfm = *per_cpu_ptr(ipcd->tfms, cpu);
+
+	err = crypto_comp_decompress(tfm, start, plen, scratch, &dlen);
 	if (err)
 		goto out;
 
@@ -52,6 +75,7 @@
 	iph = skb->nh.iph;
 	iph->tot_len = htons(dlen + iph->ihl * 4);
 out:	
+	put_cpu();
 	return err;
 }
 
@@ -97,14 +121,20 @@
 	int err, plen, dlen, ihlen;
 	struct iphdr *iph = skb->nh.iph;
 	struct ipcomp_data *ipcd = x->data;
-	u8 *start, *scratch = ipcd->scratch;
+	u8 *start, *scratch;
+	struct crypto_tfm *tfm;
+	int cpu;
 	
 	ihlen = iph->ihl * 4;
 	plen = skb->len - ihlen;
 	dlen = IPCOMP_SCRATCH_SIZE;
 	start = skb->data + ihlen;
 
-	err = crypto_comp_compress(ipcd->tfm, start, plen, scratch, &dlen);
+	cpu = get_cpu();
+	scratch = *per_cpu_ptr(ipcomp_scratches, cpu);
+	tfm = *per_cpu_ptr(ipcd->tfms, cpu);
+
+	err = crypto_comp_compress(tfm, start, plen, scratch, &dlen);
 	if (err)
 		goto out;
 
@@ -114,26 +144,30 @@
 	}
 	
 	memcpy(start + sizeof(struct ip_comp_hdr), scratch, dlen);
+	put_cpu();
+
 	pskb_trim(skb, ihlen + dlen + sizeof(struct ip_comp_hdr));
+	return 0;
 	
 out:	
+	put_cpu();
 	return err;
 }
 
-static int ipcomp_output(struct sk_buff **pskb)
+static int ipcomp_output(struct sk_buff *skb)
 {
 	int err;
-	struct dst_entry *dst = (*pskb)->dst;
+	struct dst_entry *dst = skb->dst;
 	struct xfrm_state *x = dst->xfrm;
 	struct iphdr *iph;
 	struct ip_comp_hdr *ipch;
 	struct ipcomp_data *ipcd = x->data;
 	int hdr_len = 0;
 
-	iph = (*pskb)->nh.iph;
-	iph->tot_len = htons((*pskb)->len);
+	iph = skb->nh.iph;
+	iph->tot_len = htons(skb->len);
 	hdr_len = iph->ihl * 4;
-	if (((*pskb)->len - hdr_len) < ipcd->threshold) {
+	if ((skb->len - hdr_len) < ipcd->threshold) {
 		/* Don't bother compressing */
 		if (x->props.mode) {
 			ip_send_check(iph);
@@ -141,17 +175,17 @@
 		goto out_ok;
 	}
 
-	if ((skb_is_nonlinear(*pskb) || skb_cloned(*pskb)) &&
-	    skb_linearize(*pskb, GFP_ATOMIC) != 0) {
+	if ((skb_is_nonlinear(skb) || skb_cloned(skb)) &&
+	    skb_linearize(skb, GFP_ATOMIC) != 0) {
 	    	err = -ENOMEM;
 	    	goto error;
 	}
 	
-	err = ipcomp_compress(x, *pskb);
+	err = ipcomp_compress(x, skb);
 	if (err) {
 		if (err == -EMSGSIZE) {
 			if (x->props.mode) {
-				iph = (*pskb)->nh.iph;
+				iph = skb->nh.iph;
 				ip_send_check(iph);
 			}
 			goto out_ok;
@@ -160,8 +194,8 @@
 	}
 
 	/* Install ipcomp header, convert into ipcomp datagram. */
-	iph = (*pskb)->nh.iph;
-	iph->tot_len = htons((*pskb)->len);
+	iph = skb->nh.iph;
+	iph->tot_len = htons(skb->len);
 	ipch = (struct ip_comp_hdr *)((char *)iph + iph->ihl * 4);
 	ipch->nexthdr = iph->protocol;
 	ipch->flags = 0;
@@ -260,12 +294,132 @@
 	return err;
 }
 
+static void ipcomp_free_scratches(void)
+{
+	int i;
+	void **scratches;
+
+	if (--ipcomp_scratch_users)
+		return;
+
+	scratches = ipcomp_scratches;
+	if (!scratches)
+		return;
+
+	for_each_cpu(i) {
+		void *scratch = *per_cpu_ptr(scratches, i);
+		if (scratch)
+			vfree(scratch);
+	}
+
+	free_percpu(scratches);
+}
+
+static void **ipcomp_alloc_scratches(void)
+{
+	int i;
+	void **scratches;
+
+	if (ipcomp_scratch_users++)
+		return ipcomp_scratches;
+
+	scratches = alloc_percpu(void *);
+	if (!scratches)
+		return NULL;
+
+	ipcomp_scratches = scratches;
+
+	for_each_cpu(i) {
+		void *scratch = vmalloc(IPCOMP_SCRATCH_SIZE);
+		if (!scratch)
+			return NULL;
+		*per_cpu_ptr(scratches, i) = scratch;
+	}
+
+	return scratches;
+}
+
+static void ipcomp_free_tfms(struct crypto_tfm **tfms)
+{
+	struct ipcomp_tfms *pos;
+	int cpu;
+
+	list_for_each_entry(pos, &ipcomp_tfms_list, list) {
+		if (pos->tfms == tfms)
+			break;
+	}
+
+	BUG_TRAP(pos);
+
+	if (--pos->users)
+		return;
+
+	list_del(&pos->list);
+	kfree(pos);
+
+	if (!tfms)
+		return;
+
+	for_each_cpu(cpu) {
+		struct crypto_tfm *tfm = *per_cpu_ptr(tfms, cpu);
+		if (tfm)
+			crypto_free_tfm(tfm);
+	}
+	free_percpu(tfms);
+}
+
+static struct crypto_tfm **ipcomp_alloc_tfms(const char *alg_name)
+{
+	struct ipcomp_tfms *pos;
+	struct crypto_tfm **tfms;
+	int cpu;
+
+	/* This can be any valid CPU ID so we don't need locking. */
+	cpu = smp_processor_id();
+
+	list_for_each_entry(pos, &ipcomp_tfms_list, list) {
+		struct crypto_tfm *tfm;
+
+		tfms = pos->tfms;
+		tfm = *per_cpu_ptr(tfms, cpu);
+
+		if (!strcmp(crypto_tfm_alg_name(tfm), alg_name)) {
+			pos->users++;
+			return tfms;
+		}
+	}
+
+	pos = kmalloc(sizeof(*pos), GFP_KERNEL);
+	if (!pos)
+		return NULL;
+
+	pos->users = 1;
+	INIT_LIST_HEAD(&pos->list);
+	list_add(&pos->list, &ipcomp_tfms_list);
+
+	pos->tfms = tfms = alloc_percpu(struct crypto_tfm *);
+	if (!tfms)
+		goto error;
+
+	for_each_cpu(cpu) {
+		struct crypto_tfm *tfm = crypto_alloc_tfm(alg_name, 0);
+		if (!tfm)
+			goto error;
+		*per_cpu_ptr(tfms, cpu) = tfm;
+	}
+
+	return tfms;
+
+error:
+	ipcomp_free_tfms(tfms);
+	return NULL;
+}
+
 static void ipcomp_free_data(struct ipcomp_data *ipcd)
 {
-	if (ipcd->tfm)
-		crypto_free_tfm(ipcd->tfm);
-	if (ipcd->scratch)
-		kfree(ipcd->scratch);	
+	if (ipcd->tfms)
+		ipcomp_free_tfms(ipcd->tfms);
+	ipcomp_free_scratches();
 }
 
 static void ipcomp_destroy(struct xfrm_state *x)
@@ -274,7 +428,9 @@
 	if (!ipcd)
 		return;
 	xfrm_state_delete_tunnel(x);
+	down(&ipcomp_resource_sem);
 	ipcomp_free_data(ipcd);
+	up(&ipcomp_resource_sem);
 	kfree(ipcd);
 }
 
@@ -288,28 +444,32 @@
 	if (!x->calg)
 		goto out;
 
+	if (x->encap)
+		goto out;
+
 	err = -ENOMEM;
 	ipcd = kmalloc(sizeof(*ipcd), GFP_KERNEL);
 	if (!ipcd)
-		goto error;
+		goto out;
 
 	memset(ipcd, 0, sizeof(*ipcd));
 	x->props.header_len = 0;
 	if (x->props.mode)
 		x->props.header_len += sizeof(struct iphdr);
 
-	ipcd->scratch = kmalloc(IPCOMP_SCRATCH_SIZE, GFP_KERNEL);
-	if (!ipcd->scratch)
+	down(&ipcomp_resource_sem);
+	if (!ipcomp_alloc_scratches())
 		goto error;
-	
-	ipcd->tfm = crypto_alloc_tfm(x->calg->alg_name, 0);
-	if (!ipcd->tfm)
+
+	ipcd->tfms = ipcomp_alloc_tfms(x->calg->alg_name);
+	if (!ipcd->tfms)
 		goto error;
+	up(&ipcomp_resource_sem);
 
 	if (x->props.mode) {
 		err = ipcomp_tunnel_attach(x);
 		if (err)
-			goto error;
+			goto error_tunnel;
 	}
 
 	calg_desc = xfrm_calg_get_byname(x->calg->alg_name);
@@ -320,11 +480,12 @@
 out:
 	return err;
 
+error_tunnel:
+	down(&ipcomp_resource_sem);
 error:
-	if (ipcd) {
-		ipcomp_free_data(ipcd);
-		kfree(ipcd);
-	}
+	ipcomp_free_data(ipcd);
+	up(&ipcomp_resource_sem);
+	kfree(ipcd);
 	goto out;
 }
 
diff -Nru a/net/ipv4/ipconfig.c b/net/ipv4/ipconfig.c
--- a/net/ipv4/ipconfig.c	2004-10-18 14:55:54 -07:00
+++ b/net/ipv4/ipconfig.c	2004-10-18 14:55:54 -07:00
@@ -720,6 +720,8 @@
 		b->htype = dev->type;
 	else if (dev->type == ARPHRD_IEEE802_TR) /* fix for token ring */
 		b->htype = ARPHRD_IEEE802;
+	else if (dev->type == ARPHRD_FDDI)
+		b->htype = ARPHRD_ETHER;
 	else {
 		printk("Unknown ARP type 0x%04x for device %s\n", dev->type, dev->name);
 		b->htype = dev->type; /* can cause undefined behavior */
@@ -966,6 +968,9 @@
 				break;
 
 			case DHCPACK:
+				if (memcmp(dev->dev_addr, b->hw_addr, dev->addr_len) != 0)
+					goto drop_unlock;
+
 				/* Yeah! */
 				break;
 
diff -Nru a/net/ipv4/ipip.c b/net/ipv4/ipip.c
--- a/net/ipv4/ipip.c	2004-10-18 14:57:18 -07:00
+++ b/net/ipv4/ipip.c	2004-10-18 14:57:18 -07:00
@@ -246,7 +246,6 @@
 	nt = dev->priv;
 	SET_MODULE_OWNER(dev);
 	dev->init = ipip_tunnel_init;
-	dev->destructor = free_netdev;
 	nt->parms = *parms;
 
 	if (register_netdevice(dev) < 0) {
@@ -461,8 +460,7 @@
 {
 	struct iphdr *inner_iph = skb->nh.iph;
 
-	if (INET_ECN_is_ce(outer_iph->tos) &&
-	    INET_ECN_is_not_ce(inner_iph->tos))
+	if (INET_ECN_is_ce(outer_iph->tos))
 		IP_ECN_set_ce(inner_iph);
 }
 
@@ -785,6 +783,7 @@
 	dev->get_stats		= ipip_tunnel_get_stats;
 	dev->do_ioctl		= ipip_tunnel_ioctl;
 	dev->change_mtu		= ipip_tunnel_change_mtu;
+	dev->destructor		= free_netdev;
 
 	dev->type		= ARPHRD_TUNNEL;
 	dev->hard_header_len 	= LL_MAX_HEADER + sizeof(struct iphdr);
@@ -877,18 +876,19 @@
 					   ipip_tunnel_setup);
 	if (!ipip_fb_tunnel_dev) {
 		err = -ENOMEM;
-		goto fail;
+		goto err1;
 	}
 
 	ipip_fb_tunnel_dev->init = ipip_fb_tunnel_init;
 
 	if ((err = register_netdev(ipip_fb_tunnel_dev)))
-	    goto fail;
+		goto err2;
  out:
 	return err;
- fail:
-	xfrm4_tunnel_deregister(&ipip_handler);
+ err2:
 	free_netdev(ipip_fb_tunnel_dev);
+ err1:
+	xfrm4_tunnel_deregister(&ipip_handler);
 	goto out;
 }
 
diff -Nru a/net/ipv4/ipvs/ip_vs_core.c b/net/ipv4/ipvs/ip_vs_core.c
--- a/net/ipv4/ipvs/ip_vs_core.c	2004-10-18 14:55:53 -07:00
+++ b/net/ipv4/ipvs/ip_vs_core.c	2004-10-18 14:55:53 -07:00
@@ -383,21 +383,23 @@
 	struct ip_vs_conn *cp = NULL;
 	struct iphdr *iph = skb->nh.iph;
 	struct ip_vs_dest *dest;
-	__u16 ports[2];
+	__u16 _ports[2], *pptr;
 
-	if (skb_copy_bits(skb, iph->ihl*4, ports, sizeof(ports)) < 0)
+	pptr = skb_header_pointer(skb, iph->ihl*4,
+				  sizeof(_ports), _ports);
+	if (pptr == NULL)
 		return NULL;
 
 	/*
 	 *    Persistent service
 	 */
 	if (svc->flags & IP_VS_SVC_F_PERSISTENT)
-		return ip_vs_sched_persist(svc, skb, ports);
+		return ip_vs_sched_persist(svc, skb, pptr);
 
 	/*
 	 *    Non-persistent service
 	 */
-	if (!svc->fwmark && ports[1] != svc->port) {
+	if (!svc->fwmark && pptr[1] != svc->port) {
 		if (!svc->port)
 			IP_VS_ERR("Schedule: port zero only supported "
 				  "in persistent services, "
@@ -415,9 +417,9 @@
 	 *    Create a connection entry.
 	 */
 	cp = ip_vs_conn_new(iph->protocol,
-			    iph->saddr, ports[0],
-			    iph->daddr, ports[1],
-			    dest->addr, dest->port?dest->port:ports[1],
+			    iph->saddr, pptr[0],
+			    iph->daddr, pptr[1],
+			    dest->addr, dest->port?dest->port:pptr[1],
 			    0,
 			    dest);
 	if (cp == NULL)
@@ -444,10 +446,12 @@
 int ip_vs_leave(struct ip_vs_service *svc, struct sk_buff *skb,
 		struct ip_vs_protocol *pp)
 {
-	__u16 ports[2];
+	__u16 _ports[2], *pptr;
 	struct iphdr *iph = skb->nh.iph;
 
-	if (skb_copy_bits(skb, iph->ihl*4, ports, sizeof(ports)) < 0) {
+	pptr = skb_header_pointer(skb, iph->ihl*4,
+				  sizeof(_ports), _ports);
+	if (pptr == NULL) {
 		ip_vs_service_put(svc);
 		return NF_DROP;
 	}
@@ -465,8 +469,8 @@
 		/* create a new connection entry */
 		IP_VS_DBG(6, "ip_vs_leave: create a cache_bypass entry\n");
 		cp = ip_vs_conn_new(iph->protocol,
-				    iph->saddr, ports[0],
-				    iph->daddr, ports[1],
+				    iph->saddr, pptr[0],
+				    iph->daddr, pptr[1],
 				    0, 0,
 				    IP_VS_CONN_F_BYPASS,
 				    NULL);
@@ -494,7 +498,7 @@
 	 * listed in the ipvs table), pass the packets, because it is
 	 * not ipvs job to decide to drop the packets.
 	 */
-	if ((svc->port == FTPPORT) && (ports[1] != FTPPORT)) {
+	if ((svc->port == FTPPORT) && (pptr[1] != FTPPORT)) {
 		ip_vs_service_put(svc);
 		return NF_ACCEPT;
 	}
@@ -607,8 +611,8 @@
 {
 	struct sk_buff *skb = *pskb;
 	struct iphdr *iph;
-	struct icmphdr	icmph;
-	struct iphdr	ciph;	/* The ip header contained within the ICMP */
+	struct icmphdr	_icmph, *ic;
+	struct iphdr	_ciph, *cih;	/* The ip header contained within the ICMP */
 	struct ip_vs_conn *cp;
 	struct ip_vs_protocol *pp;
 	unsigned int offset, ihl, verdict;
@@ -625,11 +629,12 @@
 
 	iph = skb->nh.iph;
 	offset = ihl = iph->ihl * 4;
-	if (skb_copy_bits(skb, offset, &icmph, sizeof(icmph)) < 0)
+	ic = skb_header_pointer(skb, offset, sizeof(_icmph), &_icmph);
+	if (ic == NULL)
 		return NF_DROP;
 
 	IP_VS_DBG(12, "Outgoing ICMP (%d,%d) %u.%u.%u.%u->%u.%u.%u.%u\n",
-		  icmph.type, ntohs(icmp_id(&icmph)),
+		  ic->type, ntohs(icmp_id(ic)),
 		  NIPQUAD(iph->saddr), NIPQUAD(iph->daddr));
 
 	/*
@@ -639,33 +644,34 @@
 	 * this means that some packets will manage to get a long way
 	 * down this stack and then be rejected, but that's life.
 	 */
-	if ((icmph.type != ICMP_DEST_UNREACH) &&
-	    (icmph.type != ICMP_SOURCE_QUENCH) &&
-	    (icmph.type != ICMP_TIME_EXCEEDED)) {
+	if ((ic->type != ICMP_DEST_UNREACH) &&
+	    (ic->type != ICMP_SOURCE_QUENCH) &&
+	    (ic->type != ICMP_TIME_EXCEEDED)) {
 		*related = 0;
 		return NF_ACCEPT;
 	}
 
 	/* Now find the contained IP header */
-	offset += sizeof(icmph);
-	if (skb_copy_bits(skb, offset, &ciph, sizeof(ciph)) < 0)
+	offset += sizeof(_icmph);
+	cih = skb_header_pointer(skb, offset, sizeof(_ciph), &_ciph);
+	if (cih == NULL)
 		return NF_ACCEPT; /* The packet looks wrong, ignore */
 
-	pp = ip_vs_proto_get(ciph.protocol);
+	pp = ip_vs_proto_get(cih->protocol);
 	if (!pp)
 		return NF_ACCEPT;
 
 	/* Is the embedded protocol header present? */
-	if (unlikely(ciph.frag_off & __constant_htons(IP_OFFSET) &&
+	if (unlikely(cih->frag_off & __constant_htons(IP_OFFSET) &&
 		     pp->dont_defrag))
 		return NF_ACCEPT;
 
 	IP_VS_DBG_PKT(11, pp, skb, offset, "Checking outgoing ICMP for");
 
-	offset += ciph.ihl * 4;
+	offset += cih->ihl * 4;
 
 	/* The embedded headers contain source and dest in reverse order */
-	cp = pp->conn_out_get(skb, pp, &ciph, offset, 1);
+	cp = pp->conn_out_get(skb, pp, cih, offset, 1);
 	if (!cp)
 		return NF_ACCEPT;
 
@@ -685,7 +691,7 @@
 		goto out;
 	}
 
-	if (IPPROTO_TCP == ciph.protocol || IPPROTO_UDP == ciph.protocol)
+	if (IPPROTO_TCP == cih->protocol || IPPROTO_UDP == cih->protocol)
 		offset += 2 * sizeof(__u16);
 	if (!ip_vs_make_skb_writable(pskb, offset))
 		goto out;
@@ -707,11 +713,13 @@
 
 static inline int is_tcp_reset(const struct sk_buff *skb)
 {
-	struct tcphdr tcph;
+	struct tcphdr _tcph, *th;
 
-	if (skb_copy_bits(skb, skb->nh.iph->ihl * 4, &tcph, sizeof(tcph)) < 0)
+	th = skb_header_pointer(skb, skb->nh.iph->ihl * 4,
+				sizeof(_tcph), &_tcph);
+	if (th == NULL)
 		return 0;
-	return tcph.rst;
+	return th->rst;
 }
 
 /*
@@ -735,13 +743,6 @@
 	if (skb->nfcache & NFC_IPVS_PROPERTY)
 		return NF_ACCEPT;
 
-	if (skb->ip_summed == CHECKSUM_HW) {
-		if (skb_checksum_help(pskb, (out == NULL)))
-			return NF_DROP;
-		if (skb != *pskb)
-			skb = *pskb;
-	}
-
 	iph = skb->nh.iph;
 	if (unlikely(iph->protocol == IPPROTO_ICMP)) {
 		int related, verdict = ip_vs_out_icmp(pskb, &related);
@@ -777,12 +778,14 @@
 		if (sysctl_ip_vs_nat_icmp_send &&
 		    (pp->protocol == IPPROTO_TCP ||
 		     pp->protocol == IPPROTO_UDP)) {
-			__u16 ports[2];
+			__u16 _ports[2], *pptr;
 
-			if (skb_copy_bits(skb, ihl, ports, sizeof(ports)) < 0)
+			pptr = skb_header_pointer(skb, ihl,
+						  sizeof(_ports), _ports);
+			if (pptr == NULL)
 				return NF_ACCEPT;	/* Not for me */
 			if (ip_vs_lookup_real_service(iph->protocol,
-						      iph->saddr, ports[0])) {
+						      iph->saddr, pptr[0])) {
 				/*
 				 * Notify the real server: there is no
 				 * existing entry if it is not RST
@@ -866,8 +869,8 @@
 {
 	struct sk_buff *skb = *pskb;
 	struct iphdr *iph;
-	struct icmphdr	icmph;
-	struct iphdr	ciph;	/* The ip header contained within the ICMP */
+	struct icmphdr	_icmph, *ic;
+	struct iphdr	_ciph, *cih;	/* The ip header contained within the ICMP */
 	struct ip_vs_conn *cp;
 	struct ip_vs_protocol *pp;
 	unsigned int offset, ihl, verdict;
@@ -884,11 +887,12 @@
 
 	iph = skb->nh.iph;
 	offset = ihl = iph->ihl * 4;
-	if (skb_copy_bits(skb, offset, &icmph, sizeof(icmph)) < 0)
+	ic = skb_header_pointer(skb, offset, sizeof(_icmph), &_icmph);
+	if (ic == NULL)
 		return NF_DROP;
 
 	IP_VS_DBG(12, "Incoming ICMP (%d,%d) %u.%u.%u.%u->%u.%u.%u.%u\n",
-		  icmph.type, ntohs(icmp_id(&icmph)),
+		  ic->type, ntohs(icmp_id(ic)),
 		  NIPQUAD(iph->saddr), NIPQUAD(iph->daddr));
 
 	/*
@@ -898,33 +902,34 @@
 	 * this means that some packets will manage to get a long way
 	 * down this stack and then be rejected, but that's life.
 	 */
-	if ((icmph.type != ICMP_DEST_UNREACH) &&
-	    (icmph.type != ICMP_SOURCE_QUENCH) &&
-	    (icmph.type != ICMP_TIME_EXCEEDED)) {
+	if ((ic->type != ICMP_DEST_UNREACH) &&
+	    (ic->type != ICMP_SOURCE_QUENCH) &&
+	    (ic->type != ICMP_TIME_EXCEEDED)) {
 		*related = 0;
 		return NF_ACCEPT;
 	}
 
 	/* Now find the contained IP header */
-	offset += sizeof(icmph);
-	if (skb_copy_bits(skb, offset, &ciph, sizeof(ciph)) < 0)
+	offset += sizeof(_icmph);
+	cih = skb_header_pointer(skb, offset, sizeof(_ciph), &_ciph);
+	if (cih == NULL)
 		return NF_ACCEPT; /* The packet looks wrong, ignore */
 
-	pp = ip_vs_proto_get(ciph.protocol);
+	pp = ip_vs_proto_get(cih->protocol);
 	if (!pp)
 		return NF_ACCEPT;
 
 	/* Is the embedded protocol header present? */
-	if (unlikely(ciph.frag_off & __constant_htons(IP_OFFSET) &&
+	if (unlikely(cih->frag_off & __constant_htons(IP_OFFSET) &&
 		     pp->dont_defrag))
 		return NF_ACCEPT;
 
 	IP_VS_DBG_PKT(11, pp, skb, offset, "Checking incoming ICMP for");
 
-	offset += ciph.ihl * 4;
+	offset += cih->ihl * 4;
 
 	/* The embedded headers contain source and dest in reverse order */
-	cp = pp->conn_in_get(skb, pp, &ciph, offset, 1);
+	cp = pp->conn_in_get(skb, pp, cih, offset, 1);
 	if (!cp)
 		return NF_ACCEPT;
 
@@ -941,7 +946,7 @@
 
 	/* do the statistics and put it back */
 	ip_vs_in_stats(cp, skb);
-	if (IPPROTO_TCP == ciph.protocol || IPPROTO_UDP == ciph.protocol)
+	if (IPPROTO_TCP == cih->protocol || IPPROTO_UDP == cih->protocol)
 		offset += 2 * sizeof(__u16);
 	verdict = ip_vs_icmp_xmit(skb, cp, pp, offset);
 	/* do not touch skb anymore */
@@ -979,13 +984,6 @@
 			  skb->nh.iph->protocol,
 			  NIPQUAD(skb->nh.iph->daddr));
 		return NF_ACCEPT;
-	}
-
-	if (skb->ip_summed == CHECKSUM_HW) {
-		if (skb_checksum_help(pskb, (out == NULL)))
-			return NF_DROP;
-		if (skb != *pskb)
-			skb = *pskb;
 	}
 
 	iph = skb->nh.iph;
diff -Nru a/net/ipv4/ipvs/ip_vs_proto.c b/net/ipv4/ipvs/ip_vs_proto.c
--- a/net/ipv4/ipvs/ip_vs_proto.c	2004-10-18 14:56:29 -07:00
+++ b/net/ipv4/ipvs/ip_vs_proto.c	2004-10-18 14:56:29 -07:00
@@ -166,27 +166,33 @@
 			  const char *msg)
 {
 	char buf[128];
-	__u16 ports[2];
-	struct iphdr iph;
+	struct iphdr _iph, *ih;
 
-	if (skb_copy_bits(skb, offset, &iph, sizeof(iph)) < 0)
+	ih = skb_header_pointer(skb, offset, sizeof(_iph), &_iph);
+	if (ih == NULL)
 		sprintf(buf, "%s TRUNCATED", pp->name);
-	else if (iph.frag_off & __constant_htons(IP_OFFSET))
+	else if (ih->frag_off & __constant_htons(IP_OFFSET))
 		sprintf(buf, "%s %u.%u.%u.%u->%u.%u.%u.%u frag",
-			pp->name, NIPQUAD(iph.saddr),
-			NIPQUAD(iph.daddr));
-	else if (skb_copy_bits(skb, offset + iph.ihl*4, ports, sizeof(ports)) < 0)
-		sprintf(buf, "%s TRUNCATED %u.%u.%u.%u->%u.%u.%u.%u",
-			pp->name,
-			NIPQUAD(iph.saddr),
-			NIPQUAD(iph.daddr));
-	else
-		sprintf(buf, "%s %u.%u.%u.%u:%u->%u.%u.%u.%u:%u",
-			pp->name,
-			NIPQUAD(iph.saddr),
-			ntohs(ports[0]),
-			NIPQUAD(iph.daddr),
-			ntohs(ports[1]));
+			pp->name, NIPQUAD(ih->saddr),
+			NIPQUAD(ih->daddr));
+	else {
+		__u16 _ports[2], *pptr
+;
+		pptr = skb_header_pointer(skb, offset + ih->ihl*4,
+					  sizeof(_ports), _ports);
+		if (pptr == NULL)
+			sprintf(buf, "%s TRUNCATED %u.%u.%u.%u->%u.%u.%u.%u",
+				pp->name,
+				NIPQUAD(ih->saddr),
+				NIPQUAD(ih->daddr));
+		else
+			sprintf(buf, "%s %u.%u.%u.%u:%u->%u.%u.%u.%u:%u",
+				pp->name,
+				NIPQUAD(ih->saddr),
+				ntohs(pptr[0]),
+				NIPQUAD(ih->daddr),
+				ntohs(pptr[1]));
+	}
 
 	printk(KERN_DEBUG "IPVS: %s: %s\n", msg, buf);
 }
diff -Nru a/net/ipv4/ipvs/ip_vs_proto_ah.c b/net/ipv4/ipvs/ip_vs_proto_ah.c
--- a/net/ipv4/ipvs/ip_vs_proto_ah.c	2004-10-18 14:56:48 -07:00
+++ b/net/ipv4/ipvs/ip_vs_proto_ah.c	2004-10-18 14:56:48 -07:00
@@ -129,14 +129,15 @@
 		int offset, const char *msg)
 {
 	char buf[256];
-	struct iphdr iph;
+	struct iphdr _iph, *ih;
 
-	if (skb_copy_bits(skb, offset, &iph, sizeof(iph)) < 0)
+	ih = skb_header_pointer(skb, offset, sizeof(_iph), &_iph);
+	if (ih == NULL)
 		sprintf(buf, "%s TRUNCATED", pp->name);
 	else
 		sprintf(buf, "%s %u.%u.%u.%u->%u.%u.%u.%u",
-			pp->name, NIPQUAD(iph.saddr),
-			NIPQUAD(iph.daddr));
+			pp->name, NIPQUAD(ih->saddr),
+			NIPQUAD(ih->daddr));
 
 	printk(KERN_DEBUG "IPVS: %s: %s\n", msg, buf);
 }
diff -Nru a/net/ipv4/ipvs/ip_vs_proto_esp.c b/net/ipv4/ipvs/ip_vs_proto_esp.c
--- a/net/ipv4/ipvs/ip_vs_proto_esp.c	2004-10-18 14:56:49 -07:00
+++ b/net/ipv4/ipvs/ip_vs_proto_esp.c	2004-10-18 14:56:49 -07:00
@@ -128,14 +128,15 @@
 		 int offset, const char *msg)
 {
 	char buf[256];
-	struct iphdr iph;
+	struct iphdr _iph, *ih;
 
-	if (skb_copy_bits(skb, offset, &iph, sizeof(iph)) < 0)
+	ih = skb_header_pointer(skb, offset, sizeof(_iph), &_iph);
+	if (ih == NULL)
 		sprintf(buf, "%s TRUNCATED", pp->name);
 	else
 		sprintf(buf, "%s %u.%u.%u.%u->%u.%u.%u.%u",
-			pp->name, NIPQUAD(iph.saddr),
-			NIPQUAD(iph.daddr));
+			pp->name, NIPQUAD(ih->saddr),
+			NIPQUAD(ih->daddr));
 
 	printk(KERN_DEBUG "IPVS: %s: %s\n", msg, buf);
 }
diff -Nru a/net/ipv4/ipvs/ip_vs_proto_icmp.c b/net/ipv4/ipvs/ip_vs_proto_icmp.c
--- a/net/ipv4/ipvs/ip_vs_proto_icmp.c	2004-10-18 14:55:54 -07:00
+++ b/net/ipv4/ipvs/ip_vs_proto_icmp.c	2004-10-18 14:55:54 -07:00
@@ -104,24 +104,29 @@
 		  const char *msg)
 {
 	char buf[256];
-	struct iphdr iph;
-	struct icmphdr icmph;
+	struct iphdr _iph, *ih;
 
-	if (skb_copy_bits(skb, offset, &iph, sizeof(iph)) < 0)
+	ih = skb_header_pointer(skb, offset, sizeof(_iph), &_iph);
+	if (ih == NULL)
 		sprintf(buf, "%s TRUNCATED", pp->name);
-	else if (iph.frag_off & __constant_htons(IP_OFFSET))
+	else if (ih->frag_off & __constant_htons(IP_OFFSET))
 		sprintf(buf, "%s %u.%u.%u.%u->%u.%u.%u.%u frag",
-			pp->name, NIPQUAD(iph.saddr),
-			NIPQUAD(iph.daddr));
-	else if (skb_copy_bits(skb, offset + iph.ihl*4, &icmph, sizeof(icmph)) < 0)
-		sprintf(buf, "%s TRUNCATED to %u bytes\n",
-			pp->name, skb->len - offset);
-	else
-		sprintf(buf, "%s %u.%u.%u.%u->%u.%u.%u.%u T:%d C:%d",
-			pp->name, NIPQUAD(iph.saddr),
-			NIPQUAD(iph.daddr),
-			icmph.type, icmph.code);
+			pp->name, NIPQUAD(ih->saddr),
+			NIPQUAD(ih->daddr));
+	else {
+		struct icmphdr _icmph, *ic;
 
+		ic = skb_header_pointer(skb, offset + ih->ihl*4,
+					sizeof(_icmph), &_icmph);
+		if (ic == NULL)
+			sprintf(buf, "%s TRUNCATED to %u bytes\n",
+				pp->name, skb->len - offset);
+		else
+			sprintf(buf, "%s %u.%u.%u.%u->%u.%u.%u.%u T:%d C:%d",
+				pp->name, NIPQUAD(ih->saddr),
+				NIPQUAD(ih->daddr),
+				ic->type, ic->code);
+	}
 	printk(KERN_DEBUG "IPVS: %s: %s\n", msg, buf);
 }
 
diff -Nru a/net/ipv4/ipvs/ip_vs_proto_tcp.c b/net/ipv4/ipvs/ip_vs_proto_tcp.c
--- a/net/ipv4/ipvs/ip_vs_proto_tcp.c	2004-10-18 14:56:27 -07:00
+++ b/net/ipv4/ipvs/ip_vs_proto_tcp.c	2004-10-18 14:56:27 -07:00
@@ -29,19 +29,20 @@
 tcp_conn_in_get(const struct sk_buff *skb, struct ip_vs_protocol *pp,
 		const struct iphdr *iph, unsigned int proto_off, int inverse)
 {
-	__u16 ports[2];
+	__u16 _ports[2], *pptr;
 
-	if (skb_copy_bits(skb, proto_off, ports, sizeof(ports)) < 0)
+	pptr = skb_header_pointer(skb, proto_off, sizeof(_ports), _ports);
+	if (pptr == NULL)
 		return NULL;
 
 	if (likely(!inverse)) {
 		return ip_vs_conn_in_get(iph->protocol,
-					 iph->saddr, ports[0],
-					 iph->daddr, ports[1]);
+					 iph->saddr, pptr[0],
+					 iph->daddr, pptr[1]);
 	} else {
 		return ip_vs_conn_in_get(iph->protocol,
-					 iph->daddr, ports[1],
-					 iph->saddr, ports[0]);
+					 iph->daddr, pptr[1],
+					 iph->saddr, pptr[0]);
 	}
 }
 
@@ -49,19 +50,20 @@
 tcp_conn_out_get(const struct sk_buff *skb, struct ip_vs_protocol *pp,
 		 const struct iphdr *iph, unsigned int proto_off, int inverse)
 {
-	__u16 ports[2];
+	__u16 _ports[2], *pptr;
 
-	if (skb_copy_bits(skb, proto_off, ports, sizeof(ports)) < 0)
+	pptr = skb_header_pointer(skb, proto_off, sizeof(_ports), _ports);
+	if (pptr == NULL)
 		return NULL;
 
 	if (likely(!inverse)) {
 		return ip_vs_conn_out_get(iph->protocol,
-					  iph->saddr, ports[0],
-					  iph->daddr, ports[1]);
+					  iph->saddr, pptr[0],
+					  iph->daddr, pptr[1]);
 	} else {
 		return ip_vs_conn_out_get(iph->protocol,
-					  iph->daddr, ports[1],
-					  iph->saddr, ports[0]);
+					  iph->daddr, pptr[1],
+					  iph->saddr, pptr[0]);
 	}
 }
 
@@ -72,16 +74,18 @@
 		  int *verdict, struct ip_vs_conn **cpp)
 {
 	struct ip_vs_service *svc;
-	struct tcphdr tcph;
+	struct tcphdr _tcph, *th;
 
-	if (skb_copy_bits(skb, skb->nh.iph->ihl*4, &tcph, sizeof(tcph)) < 0) {
+	th = skb_header_pointer(skb, skb->nh.iph->ihl*4,
+				sizeof(_tcph), &_tcph);
+	if (th == NULL) {
 		*verdict = NF_DROP;
 		return 0;
 	}
 
-	if (tcph.syn &&
+	if (th->syn &&
 	    (svc = ip_vs_service_get(skb->nfmark, skb->nh.iph->protocol,
-				     skb->nh.iph->daddr, tcph.dest))) {
+				     skb->nh.iph->daddr, th->dest))) {
 		if (ip_vs_todrop()) {
 			/*
 			 * It seems that we are very loaded.
@@ -483,13 +487,15 @@
 		     const struct sk_buff *skb,
 		     struct ip_vs_protocol *pp)
 {
-	struct tcphdr tcph;
+	struct tcphdr _tcph, *th;
 
-	if (skb_copy_bits(skb, skb->nh.iph->ihl*4, &tcph, sizeof(tcph)) < 0)
+	th = skb_header_pointer(skb, skb->nh.iph->ihl*4,
+				sizeof(_tcph), &_tcph);
+	if (th == NULL)
 		return 0;
 
 	spin_lock(&cp->lock);
-	set_tcp_state(pp, cp, direction, &tcph);
+	set_tcp_state(pp, cp, direction, th);
 	spin_unlock(&cp->lock);
 
 	return 1;
diff -Nru a/net/ipv4/ipvs/ip_vs_proto_udp.c b/net/ipv4/ipvs/ip_vs_proto_udp.c
--- a/net/ipv4/ipvs/ip_vs_proto_udp.c	2004-10-18 14:57:05 -07:00
+++ b/net/ipv4/ipvs/ip_vs_proto_udp.c	2004-10-18 14:57:05 -07:00
@@ -26,19 +26,20 @@
 		const struct iphdr *iph, unsigned int proto_off, int inverse)
 {
 	struct ip_vs_conn *cp;
-	__u16 ports[2];
+	__u16 _ports[2], *pptr;
 
-	if (skb_copy_bits(skb, proto_off, ports, sizeof(ports)) < 0)
+	pptr = skb_header_pointer(skb, proto_off, sizeof(_ports), _ports);
+	if (pptr == NULL)
 		return NULL;
 
 	if (likely(!inverse)) {
 		cp = ip_vs_conn_in_get(iph->protocol,
-				       iph->saddr, ports[0],
-				       iph->daddr, ports[1]);
+				       iph->saddr, pptr[0],
+				       iph->daddr, pptr[1]);
 	} else {
 		cp = ip_vs_conn_in_get(iph->protocol,
-				       iph->daddr, ports[1],
-				       iph->saddr, ports[0]);
+				       iph->daddr, pptr[1],
+				       iph->saddr, pptr[0]);
 	}
 
 	return cp;
@@ -50,19 +51,21 @@
 		 const struct iphdr *iph, unsigned int proto_off, int inverse)
 {
 	struct ip_vs_conn *cp;
-	__u16 ports[2];
+	__u16 _ports[2], *pptr;
 
-	if (skb_copy_bits(skb, skb->nh.iph->ihl*4, ports, sizeof(ports)) < 0)
+	pptr = skb_header_pointer(skb, skb->nh.iph->ihl*4,
+				  sizeof(_ports), _ports);
+	if (pptr == NULL)
 		return NULL;
 
 	if (likely(!inverse)) {
 		cp = ip_vs_conn_out_get(iph->protocol,
-					iph->saddr, ports[0],
-					iph->daddr, ports[1]);
+					iph->saddr, pptr[0],
+					iph->daddr, pptr[1]);
 	} else {
 		cp = ip_vs_conn_out_get(iph->protocol,
-					iph->daddr, ports[1],
-					iph->saddr, ports[0]);
+					iph->daddr, pptr[1],
+					iph->saddr, pptr[0]);
 	}
 
 	return cp;
@@ -74,15 +77,17 @@
 		  int *verdict, struct ip_vs_conn **cpp)
 {
 	struct ip_vs_service *svc;
-	struct udphdr udph;
+	struct udphdr _udph, *uh;
 
-	if (skb_copy_bits(skb, skb->nh.iph->ihl*4, &udph, sizeof(udph)) < 0) {
+	uh = skb_header_pointer(skb, skb->nh.iph->ihl*4,
+				sizeof(_udph), &_udph);
+	if (uh == NULL) {
 		*verdict = NF_DROP;
 		return 0;
 	}
 
 	if ((svc = ip_vs_service_get(skb->nfmark, skb->nh.iph->protocol,
-				     skb->nh.iph->daddr, udph.dest))) {
+				     skb->nh.iph->daddr, uh->dest))) {
 		if (ip_vs_todrop()) {
 			/*
 			 * It seems that we are very loaded.
@@ -230,13 +235,14 @@
 static int
 udp_csum_check(struct sk_buff *skb, struct ip_vs_protocol *pp)
 {
-	struct udphdr udph;
+	struct udphdr _udph, *uh;
 	unsigned int udphoff = skb->nh.iph->ihl*4;
 
-	if (skb_copy_bits(skb, udphoff, &udph, sizeof(udph)) < 0)
+	uh = skb_header_pointer(skb, udphoff, sizeof(_udph), &_udph);
+	if (uh == NULL)
 		return 0;
 
-	if (udph.check != 0) {
+	if (uh->check != 0) {
 		switch (skb->ip_summed) {
 		case CHECKSUM_NONE:
 			skb->csum = skb_checksum(skb, udphoff,
diff -Nru a/net/ipv4/ipvs/ip_vs_sync.c b/net/ipv4/ipvs/ip_vs_sync.c
--- a/net/ipv4/ipvs/ip_vs_sync.c	2004-10-18 14:55:53 -07:00
+++ b/net/ipv4/ipvs/ip_vs_sync.c	2004-10-18 14:55:53 -07:00
@@ -16,6 +16,7 @@
  *	Alexandre Cassen	:	Added master & backup support at a time.
  *	Alexandre Cassen	:	Added SyncID support for incoming sync
  *					messages filtering.
+ *	Justin Ossevoort	:	Fix endian problem on sync message size.
  */
 
 #include <linux/module.h>
@@ -279,6 +280,9 @@
 	char *p;
 	int i;
 
+	/* Convert size back to host byte order */
+	m->size = ntohs(m->size);
+
 	if (buflen != m->size) {
 		IP_VS_ERR("bogus message\n");
 		return;
@@ -569,6 +573,19 @@
 	return len;
 }
 
+static void
+ip_vs_send_sync_msg(struct socket *sock, struct ip_vs_sync_mesg *msg)
+{
+	int msize;
+
+	msize = msg->size;
+
+	/* Put size in network byte order */
+	msg->size = htons(msg->size);
+
+	if (ip_vs_send_async(sock, (char *)msg, msize) != msize)
+		IP_VS_ERR("ip_vs_send_async error\n");
+}
 
 static int
 ip_vs_receive(struct socket *sock, char *buffer, const size_t buflen)
@@ -605,7 +622,6 @@
 {
 	struct socket *sock;
 	struct ip_vs_sync_buff *sb;
-	struct ip_vs_sync_mesg *m;
 
 	/* create the sending multicast socket */
 	sock = make_send_sock();
@@ -618,19 +634,13 @@
 
 	for (;;) {
 		while ((sb=sb_dequeue())) {
-			m = sb->mesg;
-			if (ip_vs_send_async(sock, (char *)m,
-					     m->size) != m->size)
-				IP_VS_ERR("ip_vs_send_async error\n");
+			ip_vs_send_sync_msg(sock, sb->mesg);
 			ip_vs_sync_buff_release(sb);
 		}
 
 		/* check if entries stay in curr_sb for 2 seconds */
 		if ((sb = get_curr_sync_buff(2*HZ))) {
-			m = sb->mesg;
-			if (ip_vs_send_async(sock, (char *)m,
-					     m->size) != m->size)
-				IP_VS_ERR("ip_vs_send_async error\n");
+			ip_vs_send_sync_msg(sock, sb->mesg);
 			ip_vs_sync_buff_release(sb);
 		}
 
diff -Nru a/net/ipv4/ipvs/ip_vs_xmit.c b/net/ipv4/ipvs/ip_vs_xmit.c
--- a/net/ipv4/ipvs/ip_vs_xmit.c	2004-10-18 14:57:04 -07:00
+++ b/net/ipv4/ipvs/ip_vs_xmit.c	2004-10-18 14:57:04 -07:00
@@ -124,10 +124,11 @@
 	dst_release(old_dst);
 }
 
-
 #define IP_VS_XMIT(skb, rt)				\
 do {							\
+	nf_reset_debug(skb);				\
 	(skb)->nfcache |= NFC_IPVS_PROPERTY;		\
+	(skb)->ip_summed = CHECKSUM_NONE;		\
 	NF_HOOK(PF_INET, NF_IP_LOCAL_OUT, (skb), NULL,	\
 		(rt)->u.dst.dev, dst_output);		\
 } while (0)
@@ -201,9 +202,6 @@
 	/* Another hack: avoid icmp_send in ip_fragment */
 	skb->local_df = 1;
 
-#ifdef CONFIG_NETFILTER_DEBUG
-	skb->nf_debug = 0;
-#endif /* CONFIG_NETFILTER_DEBUG */
 	IP_VS_XMIT(skb, rt);
 
 	LeaveFunction(10);
@@ -234,11 +232,12 @@
 
 	/* check if it is a connection of no-client-port */
 	if (unlikely(cp->flags & IP_VS_CONN_F_NO_CPORT)) {
-		__u16 pt;
-		if (skb_copy_bits(skb, iph->ihl*4, &pt, sizeof(pt)) < 0)
+		__u16 _pt, *p;
+		p = skb_header_pointer(skb, iph->ihl*4, sizeof(_pt), &_pt);
+		if (p == NULL)
 			goto tx_error;
-		ip_vs_conn_fill_cport(cp, pt);
-		IP_VS_DBG(10, "filled cport=%d\n", ntohs(pt));
+		ip_vs_conn_fill_cport(cp, *p);
+		IP_VS_DBG(10, "filled cport=%d\n", ntohs(*p));
 	}
 
 	if (!(rt = __ip_vs_get_out_rt(cp, RT_TOS(iph->tos))))
@@ -279,9 +278,6 @@
 	/* Another hack: avoid icmp_send in ip_fragment */
 	skb->local_df = 1;
 
-#ifdef CONFIG_NETFILTER_DEBUG
-	skb->nf_debug = 0;
-#endif /* CONFIG_NETFILTER_DEBUG */
 	IP_VS_XMIT(skb, rt);
 
 	LeaveFunction(10);
@@ -412,15 +408,9 @@
 	ip_select_ident(iph, &rt->u.dst, NULL);
 	ip_send_check(iph);
 
-	skb->ip_summed = CHECKSUM_NONE;
-
 	/* Another hack: avoid icmp_send in ip_fragment */
 	skb->local_df = 1;
 
-#ifdef CONFIG_NETFILTER_DEBUG
-	skb->nf_debug = 0;
-#endif /* CONFIG_NETFILTER_DEBUG */
-
 	IP_VS_XMIT(skb, rt);
 
 	LeaveFunction(10);
@@ -479,9 +469,6 @@
 	/* Another hack: avoid icmp_send in ip_fragment */
 	skb->local_df = 1;
 
-#ifdef CONFIG_NETFILTER_DEBUG
-	skb->nf_debug = 0;
-#endif /* CONFIG_NETFILTER_DEBUG */
 	IP_VS_XMIT(skb, rt);
 
 	LeaveFunction(10);
@@ -556,9 +543,6 @@
 	/* Another hack: avoid icmp_send in ip_fragment */
 	skb->local_df = 1;
 
-#ifdef CONFIG_NETFILTER_DEBUG
-	skb->nf_debug = 0;
-#endif /* CONFIG_NETFILTER_DEBUG */
 	IP_VS_XMIT(skb, rt);
 
 	rc = NF_STOLEN;
diff -Nru a/net/ipv4/netfilter/Kconfig b/net/ipv4/netfilter/Kconfig
--- a/net/ipv4/netfilter/Kconfig	2004-10-18 14:56:49 -07:00
+++ b/net/ipv4/netfilter/Kconfig	2004-10-18 14:56:49 -07:00
@@ -5,6 +5,7 @@
 menu "IP: Netfilter Configuration"
 	depends on INET && NETFILTER
 
+# connection tracking, helpers and protocols
 config IP_NF_CONNTRACK
 	tristate "Connection tracking (required for masq/NAT)"
 	---help---
@@ -19,6 +20,28 @@
 
 	  To compile it as a module, choose M here.  If unsure, say N.
 
+config IP_NF_CT_ACCT
+	bool "Connection tracking flow accounting"
+	depends on IP_NF_CONNTRACK
+	help
+	  If this option is enabled, the connection tracking code will
+	  keep per-flow packet and byte counters.
+
+	  Those counters can be used for flow-based accounting or the
+	  `connbytes' match.
+
+	  If unsure, say `N'.
+
+config IP_NF_CT_PROTO_SCTP
+	tristate  'SCTP protocol connection tracking support (EXPERIMENTAL)'
+	depends on IP_NF_CONNTRACK && EXPERIMENTAL
+	help
+	  With this option enabled, the connection tracking code will
+	  be able to do state tracking on SCTP connections.
+
+	  If you want to compile it as a module, say M here and read
+	  Documentation/modules.txt.  If unsure, say `N'.
+
 config IP_NF_FTP
 	tristate "FTP protocol support"
 	depends on IP_NF_CONNTRACK
@@ -86,7 +109,7 @@
 
 	  To compile it as a module, choose M here.  If unsure, say N.
 
-# The simple matches.
+# The matches.
 config IP_NF_MATCH_LIMIT
 	tristate "limit match support"
 	depends on IP_NF_IPTABLES
@@ -274,7 +297,52 @@
 
 	  To compile it as a module, choose M here.  If unsure, say N.
 
-# The targets
+config IP_NF_MATCH_ADDRTYPE
+	tristate  'address type match support'
+	depends on IP_NF_IPTABLES
+	help
+	  This option allows you to match what routing thinks of an address,
+	  eg. UNICAST, LOCAL, BROADCAST, ...
+	
+	  If you want to compile it as a module, say M here and read
+	  Documentation/modules.txt.  If unsure, say `N'.
+
+config IP_NF_MATCH_REALM
+	tristate  'realm match support'
+	depends on IP_NF_IPTABLES
+	select NET_CLS_ROUTE
+	help
+	  This option adds a `realm' match, which allows you to use the realm
+	  key from the routing subsytem inside iptables.
+	
+	  This match pretty much resembles the CONFIG_NET_CLS_ROUTE4 option 
+	  in tc world.
+	
+	  If you want to compile it as a module, say M here and read
+	  Documentation/modules.txt.  If unsure, say `N'.
+
+config IP_NF_MATCH_SCTP
+	tristate  'SCTP protocol match support'
+	depends on IP_NF_IPTABLES
+	help
+	  With this option enabled, you will be able to use the iptables
+	  `sctp' match in order to match on SCTP source/destination ports
+	  and SCTP chunk types.
+
+	  If you want to compile it as a module, say M here and read
+	  Documentation/modules.txt.  If unsure, say `N'.
+
+config IP_NF_MATCH_COMMENT
+	tristate  'comment match support'
+	depends on IP_NF_IPTABLES
+	help
+	  This option adds a `comment' dummy-match, which allows you to put
+	  comments in your iptables ruleset.
+
+	  If you want to compile it as a module, say M here and read
+	  Documentation/modules.txt.  If unsure, say `N'.
+
+# `filter', generic and specific targets
 config IP_NF_FILTER
 	tristate "Packet filtering"
 	depends on IP_NF_IPTABLES
@@ -295,6 +363,56 @@
 
 	  To compile it as a module, choose M here.  If unsure, say N.
 
+config IP_NF_TARGET_LOG
+	tristate "LOG target support"
+	depends on IP_NF_IPTABLES
+	help
+	  This option adds a `LOG' target, which allows you to create rules in
+	  any iptables table which records the packet header to the syslog.
+
+	  To compile it as a module, choose M here.  If unsure, say N.
+
+config IP_NF_TARGET_ULOG
+	tristate "ULOG target support"
+	depends on IP_NF_IPTABLES
+	---help---
+	  This option adds a `ULOG' target, which allows you to create rules in
+	  any iptables table. The packet is passed to a userspace logging
+	  daemon using netlink multicast sockets; unlike the LOG target
+	  which can only be viewed through syslog.
+
+	  The apropriate userspace logging daemon (ulogd) may be obtained from
+	  <http://www.gnumonks.org/projects/ulogd/>
+
+	  To compile it as a module, choose M here.  If unsure, say N.
+
+config IP_NF_TARGET_TCPMSS
+	tristate "TCPMSS target support"
+	depends on IP_NF_IPTABLES
+	---help---
+	  This option adds a `TCPMSS' target, which allows you to alter the
+	  MSS value of TCP SYN packets, to control the maximum size for that
+	  connection (usually limiting it to your outgoing interface's MTU
+	  minus 40).
+
+	  This is used to overcome criminally braindead ISPs or servers which
+	  block ICMP Fragmentation Needed packets.  The symptoms of this
+	  problem are that everything works fine from your Linux
+	  firewall/router, but machines behind it can never exchange large
+	  packets:
+	  	1) Web browsers connect, then hang with no data received.
+	  	2) Small mail works fine, but large emails hang.
+	  	3) ssh works fine, but scp hangs after initial handshaking.
+
+	  Workaround: activate this option and add a rule to your firewall
+	  configuration like:
+
+	  iptables -A FORWARD -p tcp --tcp-flags SYN,RST SYN \
+	  		 -j TCPMSS --clamp-mss-to-pmtu
+
+	  To compile it as a module, choose M here.  If unsure, say N.
+
+# NAT + specific targets
 config IP_NF_NAT
 	tristate "Full NAT"
 	depends on IP_NF_IPTABLES && IP_NF_CONNTRACK
@@ -408,6 +526,7 @@
 	default IP_NF_NAT if IP_NF_AMANDA=y
 	default m if IP_NF_AMANDA=m
 
+# mangle + specific targets
 config IP_NF_MANGLE
 	tristate "Packet mangling"
 	depends on IP_NF_IPTABLES
@@ -478,55 +597,34 @@
 
 	  To compile it as a module, choose M here.  If unsure, say N.
 
-config IP_NF_TARGET_LOG
-	tristate "LOG target support"
+# raw + specific targets
+config IP_NF_RAW
+	tristate  'raw table support (required for NOTRACK/TRACE)'
 	depends on IP_NF_IPTABLES
 	help
-	  This option adds a `LOG' target, which allows you to create rules in
-	  any iptables table which records the packet header to the syslog.
-
-	  To compile it as a module, choose M here.  If unsure, say N.
-
-config IP_NF_TARGET_ULOG
-	tristate "ULOG target support"
-	depends on IP_NF_IPTABLES
-	---help---
-	  This option adds a `ULOG' target, which allows you to create rules in
-	  any iptables table. The packet is passed to a userspace logging
-	  daemon using netlink multicast sockets; unlike the LOG target
-	  which can only be viewed through syslog.
-
-	  The apropriate userspace logging daemon (ulogd) may be obtained from
-	  <http://www.gnumonks.org/projects/ulogd/>
-
-	  To compile it as a module, choose M here.  If unsure, say N.
-
-config IP_NF_TARGET_TCPMSS
-	tristate "TCPMSS target support"
-	depends on IP_NF_IPTABLES
-	---help---
-	  This option adds a `TCPMSS' target, which allows you to alter the
-	  MSS value of TCP SYN packets, to control the maximum size for that
-	  connection (usually limiting it to your outgoing interface's MTU
-	  minus 40).
-
-	  This is used to overcome criminally braindead ISPs or servers which
-	  block ICMP Fragmentation Needed packets.  The symptoms of this
-	  problem are that everything works fine from your Linux
-	  firewall/router, but machines behind it can never exchange large
-	  packets:
-	  	1) Web browsers connect, then hang with no data received.
-	  	2) Small mail works fine, but large emails hang.
-	  	3) ssh works fine, but scp hangs after initial handshaking.
-
-	  Workaround: activate this option and add a rule to your firewall
-	  configuration like:
+	  This option adds a `raw' table to iptables. This table is the very
+	  first in the netfilter framework and hooks in at the PREROUTING
+	  and OUTPUT chains.
+	
+	  If you want to compile it as a module, say M here and read
+	  <file:Documentation/modules.txt>.  If unsure, say `N'.
+	  help
 
-	  iptables -A FORWARD -p tcp --tcp-flags SYN,RST SYN \
-	  		 -j TCPMSS --clamp-mss-to-pmtu
+config IP_NF_TARGET_NOTRACK
+	tristate  'NOTRACK target support'
+	depends on IP_NF_RAW
+	depends on IP_NF_CONNTRACK
+	help
+	  The NOTRACK target allows a select rule to specify
+	  which packets *not* to enter the conntrack/NAT
+	  subsystem with all the consequences (no ICMP error tracking,
+	  no protocol helpers for the selected packets).
+	
+	  If you want to compile it as a module, say M here and read
+	  <file:Documentation/modules.txt>.  If unsure, say `N'.
 
-	  To compile it as a module, choose M here.  If unsure, say N.
 
+# ARP tables
 config IP_NF_ARPTABLES
 	tristate "ARP tables support"
 	help
@@ -578,55 +676,6 @@
 	  the ipfwadm tool exactly as in 2.0 kernels.
 
 	  To compile it as a module, choose M here.  If unsure, say N.
-
-config IP_NF_TARGET_NOTRACK
-	tristate  'NOTRACK target support'
-	depends on IP_NF_RAW
-	depends on IP_NF_CONNTRACK
-	help
-	  The NOTRACK target allows a select rule to specify
-	  which packets *not* to enter the conntrack/NAT
-	  subsystem with all the consequences (no ICMP error tracking,
-	  no protocol helpers for the selected packets).
-	
-	  If you want to compile it as a module, say M here and read
-	  <file:Documentation/modules.txt>.  If unsure, say `N'.
-
-config IP_NF_RAW
-	tristate  'raw table support (required for NOTRACK/TRACE)'
-	depends on IP_NF_IPTABLES
-	help
-	  This option adds a `raw' table to iptables. This table is the very
-	  first in the netfilter framework and hooks in at the PREROUTING
-	  and OUTPUT chains.
-	
-	  If you want to compile it as a module, say M here and read
-	  <file:Documentation/modules.txt>.  If unsure, say `N'.
-	  help
-
-config IP_NF_MATCH_ADDRTYPE
-	tristate  'address type match support'
-	depends on IP_NF_IPTABLES
-	help
-	  This option allows you to match what routing thinks of an address,
-	  eg. UNICAST, LOCAL, BROADCAST, ...
-	
-	  If you want to compile it as a module, say M here and read
-	  Documentation/modules.txt.  If unsure, say `N'.
-
-config IP_NF_MATCH_REALM
-	tristate  'realm match support'
-	depends on IP_NF_IPTABLES
-	select NET_CLS_ROUTE
-	help
-	  This option adds a `realm' match, which allows you to use the realm
-	  key from the routing subsytem inside iptables.
-	
-	  This match pretty much resembles the CONFIG_NET_CLS_ROUTE4 option 
-	  in tc world.
-	
-	  If you want to compile it as a module, say M here and read
-	  Documentation/modules.txt.  If unsure, say `N'.
 
 endmenu
 
diff -Nru a/net/ipv4/netfilter/Makefile b/net/ipv4/netfilter/Makefile
--- a/net/ipv4/netfilter/Makefile	2004-10-18 14:56:19 -07:00
+++ b/net/ipv4/netfilter/Makefile	2004-10-18 14:56:19 -07:00
@@ -19,6 +19,9 @@
 # connection tracking
 obj-$(CONFIG_IP_NF_CONNTRACK) += ip_conntrack.o
 
+# SCTP protocol connection tracking
+obj-$(CONFIG_IP_NF_CT_PROTO_SCTP) += ip_conntrack_proto_sctp.o
+
 # connection tracking helpers
 obj-$(CONFIG_IP_NF_AMANDA) += ip_conntrack_amanda.o
 obj-$(CONFIG_IP_NF_TFTP) += ip_conntrack_tftp.o
@@ -43,31 +46,27 @@
 # matches
 obj-$(CONFIG_IP_NF_MATCH_HELPER) += ipt_helper.o
 obj-$(CONFIG_IP_NF_MATCH_LIMIT) += ipt_limit.o
+obj-$(CONFIG_IP_NF_MATCH_SCTP) += ipt_sctp.o
 obj-$(CONFIG_IP_NF_MATCH_MARK) += ipt_mark.o
 obj-$(CONFIG_IP_NF_MATCH_MAC) += ipt_mac.o
 obj-$(CONFIG_IP_NF_MATCH_IPRANGE) += ipt_iprange.o
-
 obj-$(CONFIG_IP_NF_MATCH_PKTTYPE) += ipt_pkttype.o
 obj-$(CONFIG_IP_NF_MATCH_MULTIPORT) += ipt_multiport.o
 obj-$(CONFIG_IP_NF_MATCH_OWNER) += ipt_owner.o
 obj-$(CONFIG_IP_NF_MATCH_TOS) += ipt_tos.o
-
 obj-$(CONFIG_IP_NF_MATCH_RECENT) += ipt_recent.o
-
 obj-$(CONFIG_IP_NF_MATCH_ECN) += ipt_ecn.o
 obj-$(CONFIG_IP_NF_MATCH_DSCP) += ipt_dscp.o
 obj-$(CONFIG_IP_NF_MATCH_AH_ESP) += ipt_ah.o ipt_esp.o
-
 obj-$(CONFIG_IP_NF_MATCH_LENGTH) += ipt_length.o
-
 obj-$(CONFIG_IP_NF_MATCH_TTL) += ipt_ttl.o
 obj-$(CONFIG_IP_NF_MATCH_STATE) += ipt_state.o
 obj-$(CONFIG_IP_NF_MATCH_CONNTRACK) += ipt_conntrack.o
 obj-$(CONFIG_IP_NF_MATCH_TCPMSS) += ipt_tcpmss.o
 obj-$(CONFIG_IP_NF_MATCH_REALM) += ipt_realm.o
 obj-$(CONFIG_IP_NF_MATCH_ADDRTYPE) += ipt_addrtype.o
-
 obj-$(CONFIG_IP_NF_MATCH_PHYSDEV) += ipt_physdev.o
+obj-$(CONFIG_IP_NF_MATCH_COMMENT) += ipt_comment.o
 
 # targets
 obj-$(CONFIG_IP_NF_TARGET_REJECT) += ipt_REJECT.o
diff -Nru a/net/ipv4/netfilter/arp_tables.c b/net/ipv4/netfilter/arp_tables.c
--- a/net/ipv4/netfilter/arp_tables.c	2004-10-18 14:57:21 -07:00
+++ b/net/ipv4/netfilter/arp_tables.c	2004-10-18 14:57:21 -07:00
@@ -106,7 +106,7 @@
 {
 	char *arpptr = (char *)(arphdr + 1);
 	char *src_devaddr, *tgt_devaddr;
-	u32 *src_ipaddr, *tgt_ipaddr;
+	u32 src_ipaddr, tgt_ipaddr;
 	int i, ret;
 
 #define FWINV(bool,invflg) ((bool) ^ !!(arpinfo->invflags & invflg))
@@ -145,11 +145,11 @@
 
 	src_devaddr = arpptr;
 	arpptr += dev->addr_len;
-	src_ipaddr = (u32 *) arpptr;
+	memcpy(&src_ipaddr, arpptr, sizeof(u32));
 	arpptr += sizeof(u32);
 	tgt_devaddr = arpptr;
 	arpptr += dev->addr_len;
-	tgt_ipaddr = (u32 *) arpptr;
+	memcpy(&tgt_ipaddr, arpptr, sizeof(u32));
 
 	if (FWINV(arp_devaddr_compare(&arpinfo->src_devaddr, src_devaddr, dev->addr_len),
 		  ARPT_INV_SRCDEVADDR) ||
@@ -160,19 +160,19 @@
 		return 0;
 	}
 
-	if (FWINV(((*src_ipaddr) & arpinfo->smsk.s_addr) != arpinfo->src.s_addr,
+	if (FWINV((src_ipaddr & arpinfo->smsk.s_addr) != arpinfo->src.s_addr,
 		  ARPT_INV_SRCIP) ||
-	    FWINV((((*tgt_ipaddr) & arpinfo->tmsk.s_addr) != arpinfo->tgt.s_addr),
+	    FWINV(((tgt_ipaddr & arpinfo->tmsk.s_addr) != arpinfo->tgt.s_addr),
 		  ARPT_INV_TGTIP)) {
 		dprintf("Source or target IP address mismatch.\n");
 
 		dprintf("SRC: %u.%u.%u.%u. Mask: %u.%u.%u.%u. Target: %u.%u.%u.%u.%s\n",
-			NIPQUAD(*src_ipaddr),
+			NIPQUAD(src_ipaddr),
 			NIPQUAD(arpinfo->smsk.s_addr),
 			NIPQUAD(arpinfo->src.s_addr),
 			arpinfo->invflags & ARPT_INV_SRCIP ? " (INV)" : "");
 		dprintf("TGT: %u.%u.%u.%u Mask: %u.%u.%u.%u Target: %u.%u.%u.%u.%s\n",
-			NIPQUAD(*tgt_ipaddr),
+			NIPQUAD(tgt_ipaddr),
 			NIPQUAD(arpinfo->tmsk.s_addr),
 			NIPQUAD(arpinfo->tgt.s_addr),
 			arpinfo->invflags & ARPT_INV_TGTIP ? " (INV)" : "");
@@ -193,7 +193,10 @@
 	}
 
 	for (i = 0, ret = 0; i < IFNAMSIZ/sizeof(unsigned long); i++) {
-		ret |= (((const unsigned long *)outdev)[i]
+		unsigned long odev;
+		memcpy(&odev, outdev + i*sizeof(unsigned long),
+		       sizeof(unsigned long));
+		ret |= (odev
 			^ ((const unsigned long *)arpinfo->outiface)[i])
 			& ((const unsigned long *)arpinfo->outiface_mask)[i];
 	}
diff -Nru a/net/ipv4/netfilter/ip_conntrack_amanda.c b/net/ipv4/netfilter/ip_conntrack_amanda.c
--- a/net/ipv4/netfilter/ip_conntrack_amanda.c	2004-10-18 14:56:34 -07:00
+++ b/net/ipv4/netfilter/ip_conntrack_amanda.c	2004-10-18 14:56:34 -07:00
@@ -22,6 +22,7 @@
 #include <linux/module.h>
 #include <linux/netfilter.h>
 #include <linux/ip.h>
+#include <linux/moduleparam.h>
 #include <net/checksum.h>
 #include <net/udp.h>
 
@@ -34,7 +35,7 @@
 MODULE_AUTHOR("Brian J. Murrell <netfilter@interlinx.bc.ca>");
 MODULE_DESCRIPTION("Amanda connection tracking module");
 MODULE_LICENSE("GPL");
-MODULE_PARM(master_timeout, "i");
+module_param(master_timeout, int, 0600);
 MODULE_PARM_DESC(master_timeout, "timeout for the master connection");
 
 static char *conns[] = { "DATA ", "MESG ", "INDEX " };
@@ -48,7 +49,7 @@
 {
 	struct ip_conntrack_expect *exp;
 	struct ip_ct_amanda_expect *exp_amanda_info;
-	char *data, *data_limit, *tmp;
+	char *amp, *data, *data_limit, *tmp;
 	unsigned int dataoff, i;
 	u_int16_t port, len;
 
@@ -58,7 +59,7 @@
 
 	/* increase the UDP timeout of the master connection as replies from
 	 * Amanda clients to the server can be quite delayed */
-	ip_ct_refresh(ct, master_timeout * HZ);
+	ip_ct_refresh_acct(ct, ctinfo, NULL, master_timeout * HZ);
 
 	/* No data? */
 	dataoff = skb->nh.iph->ihl*4 + sizeof(struct udphdr);
@@ -69,9 +70,11 @@
 	}
 
 	LOCK_BH(&amanda_buffer_lock);
-	skb_copy_bits(skb, dataoff, amanda_buffer, skb->len - dataoff);
-	data = amanda_buffer;
-	data_limit = amanda_buffer + skb->len - dataoff;
+	amp = skb_header_pointer(skb, dataoff,
+				 skb->len - dataoff, amanda_buffer);
+	BUG_ON(amp == NULL);
+	data = amp;
+	data_limit = amp + skb->len - dataoff;
 	*data_limit = '\0';
 
 	/* Search for the CONNECT string */
@@ -107,7 +110,7 @@
 		exp->mask.dst.u.tcp.port = 0xFFFF;
 
 		exp_amanda_info = &exp->help.exp_amanda_info;
-		exp_amanda_info->offset = tmp - amanda_buffer;
+		exp_amanda_info->offset = tmp - amp;
 		exp_amanda_info->port   = port;
 		exp_amanda_info->len    = len;
 
diff -Nru a/net/ipv4/netfilter/ip_conntrack_core.c b/net/ipv4/netfilter/ip_conntrack_core.c
--- a/net/ipv4/netfilter/ip_conntrack_core.c	2004-10-18 14:55:46 -07:00
+++ b/net/ipv4/netfilter/ip_conntrack_core.c	2004-10-18 14:55:46 -07:00
@@ -34,8 +34,9 @@
 #include <linux/slab.h>
 #include <linux/random.h>
 #include <linux/jhash.h>
-/* For ERR_PTR().  Yeah, I know... --RR */
-#include <linux/fs.h>
+#include <linux/err.h>
+#include <linux/percpu.h>
+#include <linux/moduleparam.h>
 
 /* This rwlock protects the main hash table, protocol/helper/expected
    registrations, conntrack timers*/
@@ -59,56 +60,29 @@
 DECLARE_RWLOCK(ip_conntrack_lock);
 DECLARE_RWLOCK(ip_conntrack_expect_tuple_lock);
 
+/* ip_conntrack_standalone needs this */
+atomic_t ip_conntrack_count = ATOMIC_INIT(0);
+EXPORT_SYMBOL(ip_conntrack_count);
+
 void (*ip_conntrack_destroyed)(struct ip_conntrack *conntrack) = NULL;
 LIST_HEAD(ip_conntrack_expect_list);
-LIST_HEAD(protocol_list);
+struct ip_conntrack_protocol *ip_ct_protos[MAX_IP_CT_PROTO];
 static LIST_HEAD(helpers);
 unsigned int ip_conntrack_htable_size = 0;
 int ip_conntrack_max;
-static atomic_t ip_conntrack_count = ATOMIC_INIT(0);
 struct list_head *ip_conntrack_hash;
 static kmem_cache_t *ip_conntrack_cachep;
+static kmem_cache_t *ip_conntrack_expect_cachep;
 struct ip_conntrack ip_conntrack_untracked;
+unsigned int ip_ct_log_invalid;
 
-extern struct ip_conntrack_protocol ip_conntrack_generic_protocol;
-
-static inline int proto_cmpfn(const struct ip_conntrack_protocol *curr,
-			      u_int8_t protocol)
-{
-	return protocol == curr->proto;
-}
-
-struct ip_conntrack_protocol *__ip_ct_find_proto(u_int8_t protocol)
-{
-	struct ip_conntrack_protocol *p;
-
-	MUST_BE_READ_LOCKED(&ip_conntrack_lock);
-	p = LIST_FIND(&protocol_list, proto_cmpfn,
-		      struct ip_conntrack_protocol *, protocol);
-	if (!p)
-		p = &ip_conntrack_generic_protocol;
-
-	return p;
-}
-
-struct ip_conntrack_protocol *ip_ct_find_proto(u_int8_t protocol)
-{
-	struct ip_conntrack_protocol *p;
-
-	READ_LOCK(&ip_conntrack_lock);
-	p = __ip_ct_find_proto(protocol);
-	READ_UNLOCK(&ip_conntrack_lock);
-	return p;
-}
+DEFINE_PER_CPU(struct ip_conntrack_stat, ip_conntrack_stat);
 
 inline void 
 ip_conntrack_put(struct ip_conntrack *ct)
 {
 	IP_NF_ASSERT(ct);
-	IP_NF_ASSERT(ct->infos[0].master);
-	/* nf_conntrack_put wants to go via an info struct, so feed it
-           one at random. */
-	nf_conntrack_put(&ct->infos[0]);
+	nf_conntrack_put(&ct->ct_general);
 }
 
 static int ip_conntrack_hash_rnd_initted;
@@ -127,11 +101,11 @@
 }
 
 int
-get_tuple(const struct iphdr *iph,
-	  const struct sk_buff *skb,
-	  unsigned int dataoff,
-	  struct ip_conntrack_tuple *tuple,
-	  const struct ip_conntrack_protocol *protocol)
+ip_ct_get_tuple(const struct iphdr *iph,
+		const struct sk_buff *skb,
+		unsigned int dataoff,
+		struct ip_conntrack_tuple *tuple,
+		const struct ip_conntrack_protocol *protocol)
 {
 	/* Never happen */
 	if (iph->frag_off & htons(IP_OFFSET)) {
@@ -147,10 +121,10 @@
 	return protocol->pkt_to_tuple(skb, dataoff, tuple);
 }
 
-static int
-invert_tuple(struct ip_conntrack_tuple *inverse,
-	     const struct ip_conntrack_tuple *orig,
-	     const struct ip_conntrack_protocol *protocol)
+int
+ip_ct_invert_tuple(struct ip_conntrack_tuple *inverse,
+		   const struct ip_conntrack_tuple *orig,
+		   const struct ip_conntrack_protocol *protocol)
 {
 	inverse->src.ip = orig->dst.ip;
 	inverse->dst.ip = orig->src.ip;
@@ -177,7 +151,8 @@
 	IP_NF_ASSERT(atomic_read(&exp->use) == 0);
 	IP_NF_ASSERT(!timer_pending(&exp->timeout));
 
-	kfree(exp);
+	kmem_cache_free(ip_conntrack_expect_cachep, exp);
+	CONNTRACK_STAT_INC(expect_delete);
 }
 
 inline void ip_conntrack_expect_put(struct ip_conntrack_expect *exp)
@@ -336,7 +311,7 @@
 			list_del(&ct->master->expected_list);
 			master = ct->master->expectant;
 		}
-		kfree(ct->master);
+		kmem_cache_free(ip_conntrack_expect_cachep, ct->master);
 	}
 	WRITE_UNLOCK(&ip_conntrack_lock);
 
@@ -346,12 +321,15 @@
 	DEBUGP("destroy_conntrack: returning ct=%p to slab\n", ct);
 	kmem_cache_free(ip_conntrack_cachep, ct);
 	atomic_dec(&ip_conntrack_count);
+	CONNTRACK_STAT_INC(delete);
 }
 
 static void death_by_timeout(unsigned long ul_conntrack)
 {
 	struct ip_conntrack *ct = (void *)ul_conntrack;
 
+	CONNTRACK_STAT_INC(delete_list);
+
 	WRITE_LOCK(&ip_conntrack_lock);
 	clean_from_lists(ct);
 	WRITE_UNLOCK(&ip_conntrack_lock);
@@ -374,13 +352,19 @@
 {
 	struct ip_conntrack_tuple_hash *h;
 	unsigned int hash = hash_conntrack(tuple);
+	/* use per_cpu() to avoid multiple calls to smp_processor_id() */
+	unsigned int cpu = smp_processor_id();
 
 	MUST_BE_READ_LOCKED(&ip_conntrack_lock);
-	h = LIST_FIND(&ip_conntrack_hash[hash],
-		      conntrack_tuple_cmp,
-		      struct ip_conntrack_tuple_hash *,
-		      tuple, ignored_conntrack);
-	return h;
+	list_for_each_entry(h, &ip_conntrack_hash[hash], list) {
+		if (conntrack_tuple_cmp(h, tuple, ignored_conntrack)) {
+			per_cpu(ip_conntrack_stat, cpu).found++;
+			return h;
+		}
+		per_cpu(ip_conntrack_stat, cpu).searched++;
+	}
+
+	return NULL;
 }
 
 /* Find a connection corresponding to a tuple. */
@@ -399,36 +383,15 @@
 	return h;
 }
 
-static inline struct ip_conntrack *
-__ip_conntrack_get(struct nf_ct_info *nfct, enum ip_conntrack_info *ctinfo)
-{
-	struct ip_conntrack *ct
-		= (struct ip_conntrack *)nfct->master;
-
-	/* ctinfo is the index of the nfct inside the conntrack */
-	*ctinfo = nfct - ct->infos;
-	IP_NF_ASSERT(*ctinfo >= 0 && *ctinfo < IP_CT_NUMBER);
-	return ct;
-}
-
-/* Return conntrack and conntrack_info given skb->nfct->master */
-struct ip_conntrack *
-ip_conntrack_get(struct sk_buff *skb, enum ip_conntrack_info *ctinfo)
-{
-	if (skb->nfct) 
-		return __ip_conntrack_get(skb->nfct, ctinfo);
-	return NULL;
-}
-
-/* Confirm a connection given skb->nfct; places it in hash table */
+/* Confirm a connection given skb; places it in hash table */
 int
-__ip_conntrack_confirm(struct nf_ct_info *nfct)
+__ip_conntrack_confirm(struct sk_buff *skb)
 {
 	unsigned int hash, repl_hash;
 	struct ip_conntrack *ct;
 	enum ip_conntrack_info ctinfo;
 
-	ct = __ip_conntrack_get(nfct, &ctinfo);
+	ct = ip_conntrack_get(skb, &ctinfo);
 
 	/* ipt_REJECT uses ip_conntrack_attach to attach related
 	   ICMP/TCP RST packets in other direction.  Actual packet
@@ -474,10 +437,12 @@
 		atomic_inc(&ct->ct_general.use);
 		set_bit(IPS_CONFIRMED_BIT, &ct->status);
 		WRITE_UNLOCK(&ip_conntrack_lock);
+		CONNTRACK_STAT_INC(insert);
 		return NF_ACCEPT;
 	}
 
 	WRITE_UNLOCK(&ip_conntrack_lock);
+	CONNTRACK_STAT_INC(insert_failed);
 	return NF_DROP;
 }
 
@@ -496,83 +461,6 @@
 	return h != NULL;
 }
 
-/* Returns conntrack if it dealt with ICMP, and filled in skb fields */
-struct ip_conntrack *
-icmp_error_track(struct sk_buff *skb,
-		 enum ip_conntrack_info *ctinfo,
-		 unsigned int hooknum)
-{
-	struct ip_conntrack_tuple innertuple, origtuple;
-	struct {
-		struct icmphdr icmp;
-		struct iphdr ip;
-	} inside;
-	struct ip_conntrack_protocol *innerproto;
-	struct ip_conntrack_tuple_hash *h;
-	int dataoff;
-
-	IP_NF_ASSERT(skb->nfct == NULL);
-
-	/* Not enough header? */
-	if (skb_copy_bits(skb, skb->nh.iph->ihl*4, &inside, sizeof(inside))!=0)
-		return NULL;
-
-	if (inside.icmp.type != ICMP_DEST_UNREACH
-	    && inside.icmp.type != ICMP_SOURCE_QUENCH
-	    && inside.icmp.type != ICMP_TIME_EXCEEDED
-	    && inside.icmp.type != ICMP_PARAMETERPROB
-	    && inside.icmp.type != ICMP_REDIRECT)
-		return NULL;
-
-	/* Ignore ICMP's containing fragments (shouldn't happen) */
-	if (inside.ip.frag_off & htons(IP_OFFSET)) {
-		DEBUGP("icmp_error_track: fragment of proto %u\n",
-		       inside.ip.protocol);
-		return NULL;
-	}
-
-	innerproto = ip_ct_find_proto(inside.ip.protocol);
-	dataoff = skb->nh.iph->ihl*4 + sizeof(inside.icmp) + inside.ip.ihl*4;
-	/* Are they talking about one of our connections? */
-	if (!get_tuple(&inside.ip, skb, dataoff, &origtuple, innerproto)) {
-		DEBUGP("icmp_error: ! get_tuple p=%u", inside.ip.protocol);
-		return NULL;
-	}
-
-	/* Ordinarily, we'd expect the inverted tupleproto, but it's
-	   been preserved inside the ICMP. */
-	if (!invert_tuple(&innertuple, &origtuple, innerproto)) {
-		DEBUGP("icmp_error_track: Can't invert tuple\n");
-		return NULL;
-	}
-
-	*ctinfo = IP_CT_RELATED;
-
-	h = ip_conntrack_find_get(&innertuple, NULL);
-	if (!h) {
-		/* Locally generated ICMPs will match inverted if they
-		   haven't been SNAT'ed yet */
-		/* FIXME: NAT code has to handle half-done double NAT --RR */
-		if (hooknum == NF_IP_LOCAL_OUT)
-			h = ip_conntrack_find_get(&origtuple, NULL);
-
-		if (!h) {
-			DEBUGP("icmp_error_track: no match\n");
-			return NULL;
-		}
-		/* Reverse direction from that found */
-		if (DIRECTION(h) != IP_CT_DIR_REPLY)
-			*ctinfo += IP_CT_IS_REPLY;
-	} else {
-		if (DIRECTION(h) == IP_CT_DIR_REPLY)
-			*ctinfo += IP_CT_IS_REPLY;
-	}
-
-	/* Update skb to refer to this connection */
-	skb->nfct = &h->ctrack->infos[*ctinfo];
-	return h->ctrack;
-}
-
 /* There's a small race here where we may free a just-assured
    connection.  Too bad: we're in trouble anyway. */
 static inline int unreplied(const struct ip_conntrack_tuple_hash *i)
@@ -598,6 +486,7 @@
 	if (del_timer(&h->ctrack->timeout)) {
 		death_by_timeout((unsigned long)h->ctrack);
 		dropped = 1;
+		CONNTRACK_STAT_INC(early_drop);
 	}
 	ip_conntrack_put(h->ctrack);
 	return dropped;
@@ -627,8 +516,6 @@
 	struct ip_conntrack_tuple repl_tuple;
 	size_t hash;
 	struct ip_conntrack_expect *expected;
-	int i;
-	static unsigned int drop_next;
 
 	if (!ip_conntrack_hash_rnd_initted) {
 		get_random_bytes(&ip_conntrack_hash_rnd, 4);
@@ -637,15 +524,10 @@
 
 	hash = hash_conntrack(tuple);
 
-	if (ip_conntrack_max &&
-	    atomic_read(&ip_conntrack_count) >= ip_conntrack_max) {
-		/* Try dropping from random chain, or else from the
-                   chain about to put into (in case they're trying to
-                   bomb one hash chain). */
-		unsigned int next = (drop_next++)%ip_conntrack_htable_size;
-
-		if (!early_drop(&ip_conntrack_hash[next])
-		    && !early_drop(&ip_conntrack_hash[hash])) {
+	if (ip_conntrack_max
+	    && atomic_read(&ip_conntrack_count) >= ip_conntrack_max) {
+		/* Try dropping from this hash chain. */
+		if (!early_drop(&ip_conntrack_hash[hash])) {
 			if (net_ratelimit())
 				printk(KERN_WARNING
 				       "ip_conntrack: table full, dropping"
@@ -654,7 +536,7 @@
 		}
 	}
 
-	if (!invert_tuple(&repl_tuple, tuple, protocol)) {
+	if (!ip_ct_invert_tuple(&repl_tuple, tuple, protocol)) {
 		DEBUGP("Can't invert tuple.\n");
 		return NULL;
 	}
@@ -672,9 +554,6 @@
 	conntrack->tuplehash[IP_CT_DIR_ORIGINAL].ctrack = conntrack;
 	conntrack->tuplehash[IP_CT_DIR_REPLY].tuple = repl_tuple;
 	conntrack->tuplehash[IP_CT_DIR_REPLY].ctrack = conntrack;
-	for (i=0; i < IP_CT_NUMBER; i++)
-		conntrack->infos[i].master = &conntrack->ct_general;
-
 	if (!protocol->new(conntrack, skb)) {
 		kmem_cache_free(ip_conntrack_cachep, conntrack);
 		return NULL;
@@ -693,41 +572,53 @@
 			     struct ip_conntrack_expect *, tuple);
 	READ_UNLOCK(&ip_conntrack_expect_tuple_lock);
 
-	/* If master is not in hash table yet (ie. packet hasn't left
-	   this machine yet), how can other end know about expected?
-	   Hence these are not the droids you are looking for (if
-	   master ct never got confirmed, we'd hold a reference to it
-	   and weird things would happen to future packets). */
-	if (expected && !is_confirmed(expected->expectant))
-		expected = NULL;
-
-	/* Look up the conntrack helper for master connections only */
-	if (!expected)
-		conntrack->helper = ip_ct_find_helper(&repl_tuple);
+	if (expected) {
+		/* If master is not in hash table yet (ie. packet hasn't left
+		   this machine yet), how can other end know about expected?
+		   Hence these are not the droids you are looking for (if
+		   master ct never got confirmed, we'd hold a reference to it
+		   and weird things would happen to future packets). */
+		if (!is_confirmed(expected->expectant)) {
+			conntrack->helper = ip_ct_find_helper(&repl_tuple);
+			goto end;
+		}
 
-	/* If the expectation is dying, then this is a loser. */
-	if (expected
-	    && expected->expectant->helper->timeout
-	    && ! del_timer(&expected->timeout))
-		expected = NULL;
+		/* Expectation is dying... */
+		if (expected->expectant->helper->timeout
+		    && !del_timer(&expected->timeout))
+			goto end;	
 
-	if (expected) {
 		DEBUGP("conntrack: expectation arrives ct=%p exp=%p\n",
 			conntrack, expected);
 		/* Welcome, Mr. Bond.  We've been expecting you... */
+		IP_NF_ASSERT(expected->expectant);
 		__set_bit(IPS_EXPECTED_BIT, &conntrack->status);
 		conntrack->master = expected;
 		expected->sibling = conntrack;
 		LIST_DELETE(&ip_conntrack_expect_list, expected);
 		expected->expectant->expecting--;
-		nf_conntrack_get(&master_ct(conntrack)->infos[0]);
+		nf_conntrack_get(&master_ct(conntrack)->ct_general);
+
+		/* this is a braindead... --pablo */
+		atomic_inc(&ip_conntrack_count);
+		WRITE_UNLOCK(&ip_conntrack_lock);
+
+		if (expected->expectfn)
+			expected->expectfn(conntrack);
+	
+		CONNTRACK_STAT_INC(expect_new);
+
+		goto ret;
+	} else  {
+		conntrack->helper = ip_ct_find_helper(&repl_tuple);
+
+		CONNTRACK_STAT_INC(new);
 	}
-	atomic_inc(&ip_conntrack_count);
+
+end:	atomic_inc(&ip_conntrack_count);
 	WRITE_UNLOCK(&ip_conntrack_lock);
 
-	if (expected && expected->expectfn)
-		expected->expectfn(conntrack);
-	return &conntrack->tuplehash[IP_CT_DIR_ORIGINAL];
+ret:	return &conntrack->tuplehash[IP_CT_DIR_ORIGINAL];
 }
 
 /* On success, returns conntrack ptr, sets skb->nfct and ctinfo */
@@ -743,7 +634,8 @@
 
 	IP_NF_ASSERT((skb->nh.iph->frag_off & htons(IP_OFFSET)) == 0);
 
-	if (!get_tuple(skb->nh.iph, skb, skb->nh.iph->ihl*4, &tuple, proto))
+	if (!ip_ct_get_tuple(skb->nh.iph, skb, skb->nh.iph->ihl*4, 
+				&tuple,proto))
 		return NULL;
 
 	/* look for tuple match */
@@ -778,7 +670,8 @@
 		}
 		*set_reply = 0;
 	}
-	skb->nfct = &h->ctrack->infos[*ctinfo];
+	skb->nfct = &h->ctrack->ct_general;
+	skb->nfctinfo = *ctinfo;
 	return h->ctrack;
 }
 
@@ -795,6 +688,12 @@
 	int set_reply;
 	int ret;
 
+	/* Previously seen (loopback or untracked)?  Ignore. */
+	if ((*pskb)->nfct) {
+		CONNTRACK_STAT_INC(ignore);
+		return NF_ACCEPT;
+	}
+
 	/* Never happen */
 	if ((*pskb)->nh.iph->frag_off & htons(IP_OFFSET)) {
 		if (net_ratelimit()) {
@@ -822,39 +721,47 @@
 	}
 #endif
 
-	/* Previously seen (loopback or untracked)?  Ignore. */
-	if ((*pskb)->nfct)
-		return NF_ACCEPT;
-
 	proto = ip_ct_find_proto((*pskb)->nh.iph->protocol);
 
-	/* It may be an icmp error... */
-	if ((*pskb)->nh.iph->protocol == IPPROTO_ICMP 
-	    && icmp_error_track(*pskb, &ctinfo, hooknum))
-		return NF_ACCEPT;
+	/* It may be an special packet, error, unclean...
+	 * inverse of the return code tells to the netfilter
+	 * core what to do with the packet. */
+	if (proto->error != NULL 
+	    && (ret = proto->error(*pskb, &ctinfo, hooknum)) <= 0) {
+		CONNTRACK_STAT_INC(error);
+		CONNTRACK_STAT_INC(invalid);
+		return -ret;
+	}
 
-	if (!(ct = resolve_normal_ct(*pskb, proto,&set_reply,hooknum,&ctinfo)))
+	if (!(ct = resolve_normal_ct(*pskb, proto,&set_reply,hooknum,&ctinfo))) {
 		/* Not valid part of a connection */
+		CONNTRACK_STAT_INC(invalid);
 		return NF_ACCEPT;
+	}
 
-	if (IS_ERR(ct))
+	if (IS_ERR(ct)) {
 		/* Too stressed to deal. */
+		CONNTRACK_STAT_INC(drop);
 		return NF_DROP;
+	}
 
 	IP_NF_ASSERT((*pskb)->nfct);
 
 	ret = proto->packet(ct, *pskb, ctinfo);
-	if (ret == -1) {
-		/* Invalid */
+	if (ret < 0) {
+		/* Invalid: inverse of the return code tells
+		 * the netfilter core what to do*/
 		nf_conntrack_put((*pskb)->nfct);
 		(*pskb)->nfct = NULL;
-		return NF_ACCEPT;
+		CONNTRACK_STAT_INC(invalid);
+		return -ret;
 	}
 
 	if (ret != NF_DROP && ct->helper) {
 		ret = ct->helper->help(*pskb, ct, ctinfo);
 		if (ret == -1) {
 			/* Invalid */
+			CONNTRACK_STAT_INC(invalid);
 			nf_conntrack_put((*pskb)->nfct);
 			(*pskb)->nfct = NULL;
 			return NF_ACCEPT;
@@ -869,7 +776,8 @@
 int invert_tuplepr(struct ip_conntrack_tuple *inverse,
 		   const struct ip_conntrack_tuple *orig)
 {
-	return invert_tuple(inverse, orig, ip_ct_find_proto(orig->dst.protonum));
+	return ip_ct_invert_tuple(inverse, orig, 
+				  ip_ct_find_proto(orig->dst.protonum));
 }
 
 static inline int resent_expect(const struct ip_conntrack_expect *i,
@@ -923,9 +831,8 @@
 ip_conntrack_expect_alloc(void)
 {
 	struct ip_conntrack_expect *new;
-	
-	new = (struct ip_conntrack_expect *)
-		kmalloc(sizeof(struct ip_conntrack_expect), GFP_ATOMIC);
+
+	new = kmem_cache_alloc(ip_conntrack_expect_cachep, GFP_ATOMIC);
 	if (!new) {
 		DEBUGP("expect_related: OOM allocating expect\n");
 		return NULL;
@@ -933,6 +840,7 @@
 
 	/* tuple_cmp compares whole union, we have to initialized cleanly */
 	memset(new, 0, sizeof(struct ip_conntrack_expect));
+	atomic_set(&new->use, 1);
 
 	return new;
 }
@@ -944,7 +852,6 @@
 	DEBUGP("new expectation %p of conntrack %p\n", new, related_to);
 	new->expectant = related_to;
 	new->sibling = NULL;
-	atomic_set(&new->use, 1);
 
 	/* add to expected list for this connection */
 	list_add_tail(&new->expected_list, &related_to->sibling_list);
@@ -997,7 +904,8 @@
 		}
 
 		WRITE_UNLOCK(&ip_conntrack_lock);
-		kfree(expect);
+		/* This expectation is not inserted so no need to lock */
+		kmem_cache_free(ip_conntrack_expect_cachep, expect);
 		return -EEXIST;
 
 	} else if (related_to->helper->max_expected && 
@@ -1015,7 +923,7 @@
 				       related_to->helper->name,
  		    	       	       NIPQUAD(related_to->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip),
  		    	       	       NIPQUAD(related_to->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.ip));
-			kfree(expect);
+			kmem_cache_free(ip_conntrack_expect_cachep, expect);
 			return -EPERM;
 		}
 		DEBUGP("ip_conntrack: max number of expected "
@@ -1049,7 +957,7 @@
 		WRITE_UNLOCK(&ip_conntrack_lock);
 		DEBUGP("expect_related: busy!\n");
 
-		kfree(expect);
+		kmem_cache_free(ip_conntrack_expect_cachep, expect);
 		return -EBUSY;
 	}
 
@@ -1057,6 +965,8 @@
 
 	WRITE_UNLOCK(&ip_conntrack_lock);
 
+	CONNTRACK_STAT_INC(expect_create);
+
 	return ret;
 }
 
@@ -1164,25 +1074,45 @@
 	synchronize_net();
 }
 
-/* Refresh conntrack for this many jiffies. */
-void ip_ct_refresh(struct ip_conntrack *ct, unsigned long extra_jiffies)
+static inline void ct_add_counters(struct ip_conntrack *ct,
+				   enum ip_conntrack_info ctinfo,
+				   const struct sk_buff *skb)
+{
+#ifdef CONFIG_IP_NF_CT_ACCT
+	if (skb) {
+		ct->counters[CTINFO2DIR(ctinfo)].packets++;
+		ct->counters[CTINFO2DIR(ctinfo)].bytes += 
+					ntohs(skb->nh.iph->tot_len);
+	}
+#endif
+}
+
+/* Refresh conntrack for this many jiffies and do accounting (if skb != NULL) */
+void ip_ct_refresh_acct(struct ip_conntrack *ct, 
+		        enum ip_conntrack_info ctinfo,
+			const struct sk_buff *skb,
+			unsigned long extra_jiffies)
 {
 	IP_NF_ASSERT(ct->timeout.data == (unsigned long)ct);
 
 	/* If not in hash table, timer will not be active yet */
-	if (!is_confirmed(ct))
+	if (!is_confirmed(ct)) {
 		ct->timeout.expires = extra_jiffies;
-	else {
+		ct_add_counters(ct, ctinfo, skb);
+	} else {
 		WRITE_LOCK(&ip_conntrack_lock);
 		/* Need del_timer for race avoidance (may already be dying). */
 		if (del_timer(&ct->timeout)) {
 			ct->timeout.expires = jiffies + extra_jiffies;
 			add_timer(&ct->timeout);
 		}
+		ct_add_counters(ct, ctinfo, skb);
 		WRITE_UNLOCK(&ip_conntrack_lock);
 	}
 }
 
+int ip_ct_no_defrag;
+
 /* Returns new sk_buff, or NULL */
 struct sk_buff *
 ip_ct_gather_frags(struct sk_buff *skb)
@@ -1191,6 +1121,12 @@
 #ifdef CONFIG_NETFILTER_DEBUG
 	unsigned int olddebug = skb->nf_debug;
 #endif
+
+	if (unlikely(ip_ct_no_defrag)) {
+		kfree_skb(skb);
+		return NULL;
+	}
+
 	if (sk) {
 		sock_hold(sk);
 		skb_orphan(skb);
@@ -1221,23 +1157,23 @@
 }
 
 /* Used by ipt_REJECT. */
-static void ip_conntrack_attach(struct sk_buff *nskb, struct nf_ct_info *nfct)
+static void ip_conntrack_attach(struct sk_buff *nskb, struct sk_buff *skb)
 {
 	struct ip_conntrack *ct;
 	enum ip_conntrack_info ctinfo;
 
-	ct = __ip_conntrack_get(nfct, &ctinfo);
-
-	/* This ICMP is in reverse direction to the packet which
-           caused it */
+	/* This ICMP is in reverse direction to the packet which caused it */
+	ct = ip_conntrack_get(skb, &ctinfo);
+	
 	if (CTINFO2DIR(ctinfo) == IP_CT_DIR_ORIGINAL)
 		ctinfo = IP_CT_RELATED + IP_CT_IS_REPLY;
 	else
 		ctinfo = IP_CT_RELATED;
 
-	/* Attach new skbuff, and increment count */
-	nskb->nfct = &ct->infos[ctinfo];
-	atomic_inc(&ct->ct_general.use);
+	/* Attach to new skbuff, and increment count */
+	nskb->nfct = &ct->ct_general;
+	nskb->nfctinfo = ctinfo;
+	nf_conntrack_get(nskb->nfct);
 }
 
 static inline int
@@ -1368,12 +1304,13 @@
 	}
 
 	kmem_cache_destroy(ip_conntrack_cachep);
+	kmem_cache_destroy(ip_conntrack_expect_cachep);
 	vfree(ip_conntrack_hash);
 	nf_unregister_sockopt(&so_getorigdst);
 }
 
 static int hashsize;
-MODULE_PARM(hashsize, "i");
+module_param(hashsize, int, 0400);
 
 int __init ip_conntrack_init(void)
 {
@@ -1420,12 +1357,23 @@
 		printk(KERN_ERR "Unable to create ip_conntrack slab cache\n");
 		goto err_free_hash;
 	}
+
+	ip_conntrack_expect_cachep = kmem_cache_create("ip_conntrack_expect",
+					sizeof(struct ip_conntrack_expect),
+					0, SLAB_HWCACHE_ALIGN, NULL, NULL);
+	if (!ip_conntrack_expect_cachep) {
+		printk(KERN_ERR "Unable to create ip_expect slab cache\n");
+		goto err_free_conntrack_slab;
+	}
+
 	/* Don't NEED lock here, but good form anyway. */
 	WRITE_LOCK(&ip_conntrack_lock);
+	for (i = 0; i < MAX_IP_CT_PROTO; i++)
+		ip_ct_protos[i] = &ip_conntrack_generic_protocol;
 	/* Sew in builtin protocols. */
-	list_append(&protocol_list, &ip_conntrack_protocol_tcp);
-	list_append(&protocol_list, &ip_conntrack_protocol_udp);
-	list_append(&protocol_list, &ip_conntrack_protocol_icmp);
+	ip_ct_protos[IPPROTO_TCP] = &ip_conntrack_protocol_tcp;
+	ip_ct_protos[IPPROTO_UDP] = &ip_conntrack_protocol_udp;
+	ip_ct_protos[IPPROTO_ICMP] = &ip_conntrack_protocol_icmp;
 	WRITE_UNLOCK(&ip_conntrack_lock);
 
 	for (i = 0; i < ip_conntrack_htable_size; i++)
@@ -1439,14 +1387,11 @@
 	atomic_set(&ip_conntrack_untracked.ct_general.use, 1);
 	/*  - and look it like as a confirmed connection */
 	set_bit(IPS_CONFIRMED_BIT, &ip_conntrack_untracked.status);
-	/*  - and prepare the ctinfo field for REJECT & NAT. */
-	ip_conntrack_untracked.infos[IP_CT_NEW].master =
-	ip_conntrack_untracked.infos[IP_CT_RELATED].master =
-	ip_conntrack_untracked.infos[IP_CT_RELATED + IP_CT_IS_REPLY].master = 
-			&ip_conntrack_untracked.ct_general;
 
 	return ret;
 
+err_free_conntrack_slab:
+	kmem_cache_destroy(ip_conntrack_cachep);
 err_free_hash:
 	vfree(ip_conntrack_hash);
 err_unreg_sockopt:
diff -Nru a/net/ipv4/netfilter/ip_conntrack_ftp.c b/net/ipv4/netfilter/ip_conntrack_ftp.c
--- a/net/ipv4/netfilter/ip_conntrack_ftp.c	2004-10-18 14:57:21 -07:00
+++ b/net/ipv4/netfilter/ip_conntrack_ftp.c	2004-10-18 14:57:21 -07:00
@@ -19,6 +19,7 @@
 #include <linux/netfilter_ipv4/lockhelp.h>
 #include <linux/netfilter_ipv4/ip_conntrack_helper.h>
 #include <linux/netfilter_ipv4/ip_conntrack_ftp.h>
+#include <linux/moduleparam.h>
 
 MODULE_LICENSE("GPL");
 MODULE_AUTHOR("Rusty Russell <rusty@rustcorp.com.au>");
@@ -27,16 +28,16 @@
 /* This is slow, but it's simple. --RR */
 static char ftp_buffer[65536];
 
-DECLARE_LOCK(ip_ftp_lock);
+static DECLARE_LOCK(ip_ftp_lock);
 struct module *ip_conntrack_ftp = THIS_MODULE;
 
 #define MAX_PORTS 8
 static int ports[MAX_PORTS];
 static int ports_c;
-MODULE_PARM(ports, "1-" __MODULE_STRING(MAX_PORTS) "i");
+module_param_array(ports, int, ports_c, 0400);
 
 static int loose;
-MODULE_PARM(loose, "i");
+module_param(loose, int, 0600);
 
 #if 0
 #define DEBUGP printk
@@ -247,7 +248,8 @@
 		enum ip_conntrack_info ctinfo)
 {
 	unsigned int dataoff, datalen;
-	struct tcphdr tcph;
+	struct tcphdr _tcph, *th;
+	char *fb_ptr;
 	u_int32_t old_seq_aft_nl;
 	int old_seq_aft_nl_set, ret;
 	u_int32_t array[6] = { 0 };
@@ -267,10 +269,12 @@
 		return NF_ACCEPT;
 	}
 
-	if (skb_copy_bits(skb, skb->nh.iph->ihl*4, &tcph, sizeof(tcph)) != 0)
+	th = skb_header_pointer(skb, skb->nh.iph->ihl*4,
+				sizeof(_tcph), &_tcph);
+	if (th == NULL)
 		return NF_ACCEPT;
 
-	dataoff = skb->nh.iph->ihl*4 + tcph.doff*4;
+	dataoff = skb->nh.iph->ihl*4 + th->doff*4;
 	/* No data? */
 	if (dataoff >= skb->len) {
 		DEBUGP("ftp: skblen = %u\n", skb->len);
@@ -279,26 +283,28 @@
 	datalen = skb->len - dataoff;
 
 	LOCK_BH(&ip_ftp_lock);
-	skb_copy_bits(skb, dataoff, ftp_buffer, skb->len - dataoff);
+	fb_ptr = skb_header_pointer(skb, dataoff,
+				    skb->len - dataoff, ftp_buffer);
+	BUG_ON(fb_ptr == NULL);
 
 	old_seq_aft_nl_set = ct_ftp_info->seq_aft_nl_set[dir];
 	old_seq_aft_nl = ct_ftp_info->seq_aft_nl[dir];
 
 	DEBUGP("conntrack_ftp: datalen %u\n", datalen);
-	if (ftp_buffer[datalen - 1] == '\n') {
+	if (fb_ptr[datalen - 1] == '\n') {
 		DEBUGP("conntrack_ftp: datalen %u ends in \\n\n", datalen);
 		if (!old_seq_aft_nl_set
-		    || after(ntohl(tcph.seq) + datalen, old_seq_aft_nl)) {
+		    || after(ntohl(th->seq) + datalen, old_seq_aft_nl)) {
 			DEBUGP("conntrack_ftp: updating nl to %u\n",
-			       ntohl(tcph.seq) + datalen);
+			       ntohl(th->seq) + datalen);
 			ct_ftp_info->seq_aft_nl[dir] = 
-						ntohl(tcph.seq) + datalen;
+						ntohl(th->seq) + datalen;
 			ct_ftp_info->seq_aft_nl_set[dir] = 1;
 		}
 	}
 
 	if(!old_seq_aft_nl_set ||
-			(ntohl(tcph.seq) != old_seq_aft_nl)) {
+			(ntohl(th->seq) != old_seq_aft_nl)) {
 		DEBUGP("ip_conntrack_ftp_help: wrong seq pos %s(%u)\n",
 		       old_seq_aft_nl_set ? "":"(UNSET) ", old_seq_aft_nl);
 		ret = NF_ACCEPT;
@@ -315,7 +321,7 @@
 	for (i = 0; i < ARRAY_SIZE(search); i++) {
 		if (search[i].dir != dir) continue;
 
-		found = find_pattern(ftp_buffer, skb->len - dataoff,
+		found = find_pattern(fb_ptr, skb->len - dataoff,
 				     search[i].pattern,
 				     search[i].plen,
 				     search[i].skip,
@@ -333,7 +339,7 @@
 		if (net_ratelimit())
 			printk("conntrack_ftp: partial %s %u+%u\n",
 			       search[i].pattern,
-			       ntohl(tcph.seq), datalen);
+			       ntohl(th->seq), datalen);
 		ret = NF_DROP;
 		goto out;
 	} else if (found == 0) { /* No match */
@@ -343,7 +349,7 @@
 
 	DEBUGP("conntrack_ftp: match `%.*s' (%u bytes at %u)\n",
 	       (int)matchlen, data + matchoff,
-	       matchlen, ntohl(tcph.seq) + matchoff);
+	       matchlen, ntohl(th->seq) + matchoff);
 
 	/* Allocate expectation which will be inserted */
 	exp = ip_conntrack_expect_alloc();
@@ -357,7 +363,7 @@
 	/* Update the ftp info */
 	if (htonl((array[0] << 24) | (array[1] << 16) | (array[2] << 8) | array[3])
 	    == ct->tuplehash[dir].tuple.src.ip) {
-		exp->seq = ntohl(tcph.seq) + matchoff;
+		exp->seq = ntohl(th->seq) + matchoff;
 		exp_ftp_info->len = matchlen;
 		exp_ftp_info->ftptype = search[i].ftptype;
 		exp_ftp_info->port = array[4] << 8 | array[5];
@@ -420,10 +426,10 @@
 	int i, ret;
 	char *tmpname;
 
-	if (ports[0] == 0)
-		ports[0] = FTP_PORT;
+	if (ports_c == 0)
+		ports[ports_c++] = FTP_PORT;
 
-	for (i = 0; (i < MAX_PORTS) && ports[i]; i++) {
+	for (i = 0; i < ports_c; i++) {
 		ftp[i].tuple.src.u.tcp.port = htons(ports[i]);
 		ftp[i].tuple.dst.protonum = IPPROTO_TCP;
 		ftp[i].mask.src.u.tcp.port = 0xFFFF;
@@ -449,13 +455,11 @@
 			fini();
 			return ret;
 		}
-		ports_c++;
 	}
 	return 0;
 }
 
 PROVIDES_CONNTRACK(ftp);
-EXPORT_SYMBOL(ip_ftp_lock);
 
 module_init(init);
 module_exit(fini);
diff -Nru a/net/ipv4/netfilter/ip_conntrack_irc.c b/net/ipv4/netfilter/ip_conntrack_irc.c
--- a/net/ipv4/netfilter/ip_conntrack_irc.c	2004-10-18 14:56:49 -07:00
+++ b/net/ipv4/netfilter/ip_conntrack_irc.c	2004-10-18 14:56:49 -07:00
@@ -32,6 +32,7 @@
 #include <linux/netfilter_ipv4/lockhelp.h>
 #include <linux/netfilter_ipv4/ip_conntrack_helper.h>
 #include <linux/netfilter_ipv4/ip_conntrack_irc.h>
+#include <linux/moduleparam.h>
 
 #define MAX_PORTS 8
 static int ports[MAX_PORTS];
@@ -40,21 +41,21 @@
 static unsigned int dcc_timeout = 300;
 /* This is slow, but it's simple. --RR */
 static char irc_buffer[65536];
+static DECLARE_LOCK(irc_buffer_lock);
 
 MODULE_AUTHOR("Harald Welte <laforge@netfilter.org>");
 MODULE_DESCRIPTION("IRC (DCC) connection tracking helper");
 MODULE_LICENSE("GPL");
-MODULE_PARM(ports, "1-" __MODULE_STRING(MAX_PORTS) "i");
+module_param_array(ports, int, ports_c, 0400);
 MODULE_PARM_DESC(ports, "port numbers of IRC servers");
-MODULE_PARM(max_dcc_channels, "i");
+module_param(max_dcc_channels, int, 0400);
 MODULE_PARM_DESC(max_dcc_channels, "max number of expected DCC channels per IRC session");
-MODULE_PARM(dcc_timeout, "i");
+module_param(dcc_timeout, int, 0400);
 MODULE_PARM_DESC(dcc_timeout, "timeout on for unestablished DCC channels");
 
 static char *dccprotos[] = { "SEND ", "CHAT ", "MOVE ", "TSEND ", "SCHAT " };
 #define MINMATCHLEN	5
 
-DECLARE_LOCK(ip_irc_lock);
 struct module *ip_conntrack_irc = THIS_MODULE;
 
 #if 0
@@ -101,8 +102,8 @@
 		struct ip_conntrack *ct, enum ip_conntrack_info ctinfo)
 {
 	unsigned int dataoff;
-	struct tcphdr tcph;
-	char *data, *data_limit;
+	struct tcphdr _tcph, *th;
+	char *data, *data_limit, *ib_ptr;
 	int dir = CTINFO2DIR(ctinfo);
 	struct ip_conntrack_expect *exp;
 	struct ip_ct_irc_expect *exp_irc_info = NULL;
@@ -126,19 +127,23 @@
 	}
 
 	/* Not a full tcp header? */
-	if (skb_copy_bits(skb, skb->nh.iph->ihl*4, &tcph, sizeof(tcph)) != 0)
+	th = skb_header_pointer(skb, skb->nh.iph->ihl*4,
+				sizeof(_tcph), &_tcph);
+	if (th == NULL)
 		return NF_ACCEPT;
 
 	/* No data? */
-	dataoff = skb->nh.iph->ihl*4 + tcph.doff*4;
+	dataoff = skb->nh.iph->ihl*4 + th->doff*4;
 	if (dataoff >= skb->len)
 		return NF_ACCEPT;
 
-	LOCK_BH(&ip_irc_lock);
-	skb_copy_bits(skb, dataoff, irc_buffer, skb->len - dataoff);
+	LOCK_BH(&irc_buffer_lock);
+	ib_ptr = skb_header_pointer(skb, dataoff,
+				    skb->len - dataoff, irc_buffer);
+	BUG_ON(ib_ptr == NULL);
 
-	data = irc_buffer;
-	data_limit = irc_buffer + skb->len - dataoff;
+	data = ib_ptr;
+	data_limit = ib_ptr + skb->len - dataoff;
 
 	/* strlen("\1DCC SENT t AAAAAAAA P\1\n")=24
 	 * 5+MINMATCHLEN+strlen("t AAAAAAAA P\1\n")=14 */
@@ -152,8 +157,8 @@
 		/* we have at least (19+MINMATCHLEN)-5 bytes valid data left */
 
 		DEBUGP("DCC found in master %u.%u.%u.%u:%u %u.%u.%u.%u:%u...\n",
-			NIPQUAD(iph->saddr), ntohs(tcph.source),
-			NIPQUAD(iph->daddr), ntohs(tcph.dest));
+			NIPQUAD(iph->saddr), ntohs(th->source),
+			NIPQUAD(iph->daddr), ntohs(th->dest));
 
 		for (i = 0; i < ARRAY_SIZE(dccprotos); i++) {
 			if (memcmp(data, dccprotos[i], strlen(dccprotos[i]))) {
@@ -197,8 +202,8 @@
 
 			/* save position of address in dcc string,
 			 * necessary for NAT */
-			DEBUGP("tcph->seq = %u\n", tcph.seq);
-			exp->seq = ntohl(tcph.seq) + (addr_beg_p - irc_buffer);
+			DEBUGP("tcph->seq = %u\n", th->seq);
+			exp->seq = ntohl(th->seq) + (addr_beg_p - ib_ptr);
 			exp_irc_info->len = (addr_end_p - addr_beg_p);
 			exp_irc_info->port = dcc_port;
 			DEBUGP("wrote info seq=%u (ofs=%u), len=%d\n",
@@ -227,7 +232,7 @@
 	} /* while data < ... */
 
  out:
-	UNLOCK_BH(&ip_irc_lock);
+	UNLOCK_BH(&irc_buffer_lock);
 	return NF_ACCEPT;
 }
 
@@ -252,10 +257,10 @@
 	}
 	
 	/* If no port given, default to standard irc port */
-	if (ports[0] == 0)
-		ports[0] = IRC_PORT;
+	if (ports_c == 0)
+		ports[ports_c++] = IRC_PORT;
 
-	for (i = 0; (i < MAX_PORTS) && ports[i]; i++) {
+	for (i = 0; i < ports_c; i++) {
 		hlpr = &irc_helpers[i];
 		hlpr->tuple.src.u.tcp.port = htons(ports[i]);
 		hlpr->tuple.dst.protonum = IPPROTO_TCP;
@@ -284,7 +289,6 @@
 			fini();
 			return -EBUSY;
 		}
-		ports_c++;
 	}
 	return 0;
 }
@@ -302,7 +306,6 @@
 }
 
 PROVIDES_CONNTRACK(irc);
-EXPORT_SYMBOL(ip_irc_lock);
 
 module_init(init);
 module_exit(fini);
diff -Nru a/net/ipv4/netfilter/ip_conntrack_proto_generic.c b/net/ipv4/netfilter/ip_conntrack_proto_generic.c
--- a/net/ipv4/netfilter/ip_conntrack_proto_generic.c	2004-10-18 14:56:28 -07:00
+++ b/net/ipv4/netfilter/ip_conntrack_proto_generic.c	2004-10-18 14:56:28 -07:00
@@ -34,15 +34,15 @@
 }
 
 /* Print out the per-protocol part of the tuple. */
-static unsigned int generic_print_tuple(char *buffer,
-					const struct ip_conntrack_tuple *tuple)
+static int generic_print_tuple(struct seq_file *s,
+			       const struct ip_conntrack_tuple *tuple)
 {
 	return 0;
 }
 
 /* Print out the private part of the conntrack. */
-static unsigned int generic_print_conntrack(char *buffer,
-					    const struct ip_conntrack *state)
+static int generic_print_conntrack(struct seq_file *s,
+				   const struct ip_conntrack *state)
 {
 	return 0;
 }
@@ -50,9 +50,9 @@
 /* Returns verdict for packet, or -1 for invalid. */
 static int packet(struct ip_conntrack *conntrack,
 		  const struct sk_buff *skb,
-		  enum ip_conntrack_info conntrackinfo)
+		  enum ip_conntrack_info ctinfo)
 {
-	ip_ct_refresh(conntrack, ip_ct_generic_timeout);
+	ip_ct_refresh_acct(conntrack, ctinfo, skb, ip_ct_generic_timeout);
 	return NF_ACCEPT;
 }
 
@@ -62,8 +62,14 @@
 	return 1;
 }
 
-struct ip_conntrack_protocol ip_conntrack_generic_protocol
-= { { NULL, NULL }, 0, "unknown",
-    generic_pkt_to_tuple, generic_invert_tuple, generic_print_tuple,
-    generic_print_conntrack, packet, new, NULL, NULL, NULL };
-
+struct ip_conntrack_protocol ip_conntrack_generic_protocol =
+{
+	.proto			= 0,
+	.name			= "unknown",
+	.pkt_to_tuple		= generic_pkt_to_tuple,
+	.invert_tuple		= generic_invert_tuple,
+	.print_tuple		= generic_print_tuple,
+	.print_conntrack	= generic_print_conntrack,
+	.packet			= packet,
+	.new			= new,
+};
diff -Nru a/net/ipv4/netfilter/ip_conntrack_proto_icmp.c b/net/ipv4/netfilter/ip_conntrack_proto_icmp.c
--- a/net/ipv4/netfilter/ip_conntrack_proto_icmp.c	2004-10-18 14:55:54 -07:00
+++ b/net/ipv4/netfilter/ip_conntrack_proto_icmp.c	2004-10-18 14:55:54 -07:00
@@ -12,6 +12,13 @@
 #include <linux/netfilter.h>
 #include <linux/in.h>
 #include <linux/icmp.h>
+#include <linux/seq_file.h>
+#include <net/ip.h>
+#include <net/checksum.h>
+#include <linux/netfilter.h>
+#include <linux/netfilter_ipv4.h>
+#include <linux/netfilter_ipv4/ip_conntrack.h>
+#include <linux/netfilter_ipv4/ip_conntrack_core.h>
 #include <linux/netfilter_ipv4/ip_conntrack_protocol.h>
 
 unsigned long ip_ct_icmp_timeout = 30*HZ;
@@ -26,14 +33,15 @@
 			     unsigned int dataoff,
 			     struct ip_conntrack_tuple *tuple)
 {
-	struct icmphdr hdr;
+	struct icmphdr _hdr, *hp;
 
-	if (skb_copy_bits(skb, dataoff, &hdr, sizeof(hdr)) != 0)
+	hp = skb_header_pointer(skb, dataoff, sizeof(_hdr), &_hdr);
+	if (hp == NULL)
 		return 0;
 
-	tuple->dst.u.icmp.type = hdr.type;
-	tuple->src.u.icmp.id = hdr.un.echo.id;
-	tuple->dst.u.icmp.code = hdr.code;
+	tuple->dst.u.icmp.type = hp->type;
+	tuple->src.u.icmp.id = hp->un.echo.id;
+	tuple->dst.u.icmp.code = hp->code;
 
 	return 1;
 }
@@ -63,18 +71,18 @@
 }
 
 /* Print out the per-protocol part of the tuple. */
-static unsigned int icmp_print_tuple(char *buffer,
-				     const struct ip_conntrack_tuple *tuple)
+static int icmp_print_tuple(struct seq_file *s,
+			    const struct ip_conntrack_tuple *tuple)
 {
-	return sprintf(buffer, "type=%u code=%u id=%u ",
-		       tuple->dst.u.icmp.type,
-		       tuple->dst.u.icmp.code,
-		       ntohs(tuple->src.u.icmp.id));
+	return seq_printf(s, "type=%u code=%u id=%u ",
+			  tuple->dst.u.icmp.type,
+			  tuple->dst.u.icmp.code,
+			  ntohs(tuple->src.u.icmp.id));
 }
 
 /* Print out the private part of the conntrack. */
-static unsigned int icmp_print_conntrack(char *buffer,
-				     const struct ip_conntrack *conntrack)
+static int icmp_print_conntrack(struct seq_file *s,
+				const struct ip_conntrack *conntrack)
 {
 	return 0;
 }
@@ -94,7 +102,7 @@
 			ct->timeout.function((unsigned long)ct);
 	} else {
 		atomic_inc(&ct->proto.icmp.count);
-		ip_ct_refresh(ct, ip_ct_icmp_timeout);
+		ip_ct_refresh_acct(ct, ctinfo, skb, ip_ct_icmp_timeout);
 	}
 
 	return NF_ACCEPT;
@@ -122,7 +130,150 @@
 	return 1;
 }
 
-struct ip_conntrack_protocol ip_conntrack_protocol_icmp
-= { { NULL, NULL }, IPPROTO_ICMP, "icmp",
-    icmp_pkt_to_tuple, icmp_invert_tuple, icmp_print_tuple,
-    icmp_print_conntrack, icmp_packet, icmp_new, NULL, NULL, NULL };
+static int
+icmp_error_message(struct sk_buff *skb,
+		   enum ip_conntrack_info *ctinfo,
+		   unsigned int hooknum)
+{
+	struct ip_conntrack_tuple innertuple, origtuple;
+	struct {
+		struct icmphdr icmp;
+		struct iphdr ip;
+	} _in, *inside;
+	struct ip_conntrack_protocol *innerproto;
+	struct ip_conntrack_tuple_hash *h;
+	int dataoff;
+
+	IP_NF_ASSERT(skb->nfct == NULL);
+
+	/* Not enough header? */
+	inside = skb_header_pointer(skb, skb->nh.iph->ihl*4, sizeof(_in), &_in);
+	if (inside == NULL)
+		return NF_ACCEPT;
+
+	/* Ignore ICMP's containing fragments (shouldn't happen) */
+	if (inside->ip.frag_off & htons(IP_OFFSET)) {
+		DEBUGP("icmp_error_track: fragment of proto %u\n",
+		       inside->ip.protocol);
+		return NF_ACCEPT;
+	}
+
+	innerproto = ip_ct_find_proto(inside->ip.protocol);
+	dataoff = skb->nh.iph->ihl*4 + sizeof(inside->icmp) + inside->ip.ihl*4;
+	/* Are they talking about one of our connections? */
+	if (!ip_ct_get_tuple(&inside->ip, skb, dataoff, &origtuple, innerproto)) {
+		DEBUGP("icmp_error: ! get_tuple p=%u", inside->ip.protocol);
+		return NF_ACCEPT;
+	}
+
+	/* Ordinarily, we'd expect the inverted tupleproto, but it's
+	   been preserved inside the ICMP. */
+	if (!ip_ct_invert_tuple(&innertuple, &origtuple, innerproto)) {
+		DEBUGP("icmp_error_track: Can't invert tuple\n");
+		return NF_ACCEPT;
+	}
+
+	*ctinfo = IP_CT_RELATED;
+
+	h = ip_conntrack_find_get(&innertuple, NULL);
+	if (!h) {
+		/* Locally generated ICMPs will match inverted if they
+		   haven't been SNAT'ed yet */
+		/* FIXME: NAT code has to handle half-done double NAT --RR */
+		if (hooknum == NF_IP_LOCAL_OUT)
+			h = ip_conntrack_find_get(&origtuple, NULL);
+
+		if (!h) {
+			DEBUGP("icmp_error_track: no match\n");
+			return NF_ACCEPT;
+		}
+		/* Reverse direction from that found */
+		if (DIRECTION(h) != IP_CT_DIR_REPLY)
+			*ctinfo += IP_CT_IS_REPLY;
+	} else {
+		if (DIRECTION(h) == IP_CT_DIR_REPLY)
+			*ctinfo += IP_CT_IS_REPLY;
+	}
+
+	/* Update skb to refer to this connection */
+	skb->nfct = &h->ctrack->ct_general;
+	skb->nfctinfo = *ctinfo;
+	return -NF_ACCEPT;
+}
+
+/* Small and modified version of icmp_rcv */
+static int
+icmp_error(struct sk_buff *skb, enum ip_conntrack_info *ctinfo,
+	   unsigned int hooknum)
+{
+	struct icmphdr _ih, *icmph;
+
+	/* Not enough header? */
+	icmph = skb_header_pointer(skb, skb->nh.iph->ihl*4, sizeof(_ih), &_ih);
+	if (icmph == NULL) {
+		if (LOG_INVALID(IPPROTO_ICMP))
+			nf_log_packet(PF_INET, 0, skb, NULL, NULL,
+				      "ip_ct_icmp: short packet ");
+		return -NF_ACCEPT;
+	}
+
+	/* See ip_conntrack_proto_tcp.c */
+	if (hooknum != NF_IP_PRE_ROUTING)
+		goto checksum_skipped;
+
+	switch (skb->ip_summed) {
+	case CHECKSUM_HW:
+		if (!(u16)csum_fold(skb->csum)) 
+			break;
+		if (LOG_INVALID(IPPROTO_ICMP))
+			nf_log_packet(PF_INET, 0, skb, NULL, NULL, 
+				      "ip_ct_icmp: bad HW ICMP checksum ");
+		return -NF_ACCEPT;
+	case CHECKSUM_NONE:
+		if ((u16)csum_fold(skb_checksum(skb, 0, skb->len, 0))) {
+			if (LOG_INVALID(IPPROTO_ICMP))
+				nf_log_packet(PF_INET, 0, skb, NULL, NULL, 
+					      "ip_ct_icmp: bad ICMP checksum ");
+			return -NF_ACCEPT;
+		}
+	default:
+		break;
+	}
+
+checksum_skipped:
+	/*
+	 *	18 is the highest 'known' ICMP type. Anything else is a mystery
+	 *
+	 *	RFC 1122: 3.2.2  Unknown ICMP messages types MUST be silently
+	 *		  discarded.
+	 */
+	if (icmph->type > NR_ICMP_TYPES) {
+		if (LOG_INVALID(IPPROTO_ICMP))
+			nf_log_packet(PF_INET, 0, skb, NULL, NULL,
+				      "ip_ct_icmp: invalid ICMP type ");
+		return -NF_ACCEPT;
+	}
+
+	/* Need to track icmp error message? */
+	if (icmph->type != ICMP_DEST_UNREACH
+	    && icmph->type != ICMP_SOURCE_QUENCH
+	    && icmph->type != ICMP_TIME_EXCEEDED
+	    && icmph->type != ICMP_PARAMETERPROB
+	    && icmph->type != ICMP_REDIRECT)
+		return NF_ACCEPT;
+
+	return icmp_error_message(skb, ctinfo, hooknum);
+}
+
+struct ip_conntrack_protocol ip_conntrack_protocol_icmp =
+{
+	.proto 			= IPPROTO_ICMP,
+	.name 			= "icmp",
+	.pkt_to_tuple		= icmp_pkt_to_tuple,
+	.invert_tuple		= icmp_invert_tuple,
+	.print_tuple		= icmp_print_tuple,
+	.print_conntrack	= icmp_print_conntrack,
+	.packet			= icmp_packet,
+	.new			= icmp_new,
+	.error			= icmp_error,
+};
diff -Nru a/net/ipv4/netfilter/ip_conntrack_proto_sctp.c b/net/ipv4/netfilter/ip_conntrack_proto_sctp.c
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/net/ipv4/netfilter/ip_conntrack_proto_sctp.c	2004-10-18 14:57:24 -07:00
@@ -0,0 +1,656 @@
+/*
+ * Connection tracking protocol helper module for SCTP.
+ * 
+ * SCTP is defined in RFC 2960. References to various sections in this code 
+ * are to this RFC.
+ * 
+ * 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.
+ */
+
+/*
+ * Added support for proc manipulation of timeouts.
+ */
+
+#include <linux/types.h>
+#include <linux/sched.h>
+#include <linux/timer.h>
+#include <linux/netfilter.h>
+#include <linux/module.h>
+#include <linux/in.h>
+#include <linux/ip.h>
+#include <linux/sctp.h>
+#include <linux/string.h>
+#include <linux/seq_file.h>
+
+#include <linux/netfilter_ipv4/ip_conntrack.h>
+#include <linux/netfilter_ipv4/ip_conntrack_protocol.h>
+#include <linux/netfilter_ipv4/lockhelp.h>
+
+#if 0
+#define DEBUGP(format, ...) printk(format, ## __VA_ARGS__)
+#else
+#define DEBUGP(format, args...)
+#endif
+
+/* Protects conntrack->proto.sctp */
+static DECLARE_RWLOCK(sctp_lock);
+
+/* FIXME: Examine ipfilter's timeouts and conntrack transitions more
+   closely.  They're more complex. --RR 
+
+   And so for me for SCTP :D -Kiran */
+
+static const char *sctp_conntrack_names[] = {
+	"NONE",
+	"CLOSED",
+	"COOKIE_WAIT",
+	"COOKIE_ECHOED",
+	"ESTABLISHED",
+	"SHUTDOWN_SENT",
+	"SHUTDOWN_RECD",
+	"SHUTDOWN_ACK_SENT",
+};
+
+#define SECS  * HZ
+#define MINS  * 60 SECS
+#define HOURS * 60 MINS
+#define DAYS  * 24 HOURS
+
+unsigned long ip_ct_sctp_timeout_closed            =  10 SECS;
+unsigned long ip_ct_sctp_timeout_cookie_wait       =   3 SECS;
+unsigned long ip_ct_sctp_timeout_cookie_echoed     =   3 SECS;
+unsigned long ip_ct_sctp_timeout_established       =   5 DAYS;
+unsigned long ip_ct_sctp_timeout_shutdown_sent     = 300 SECS / 1000;
+unsigned long ip_ct_sctp_timeout_shutdown_recd     = 300 SECS / 1000;
+unsigned long ip_ct_sctp_timeout_shutdown_ack_sent =   3 SECS;
+
+static unsigned long * sctp_timeouts[]
+= { NULL,                                  /* SCTP_CONNTRACK_NONE  */
+    &ip_ct_sctp_timeout_closed,	           /* SCTP_CONNTRACK_CLOSED */
+    &ip_ct_sctp_timeout_cookie_wait,       /* SCTP_CONNTRACK_COOKIE_WAIT */
+    &ip_ct_sctp_timeout_cookie_echoed,     /* SCTP_CONNTRACK_COOKIE_ECHOED */
+    &ip_ct_sctp_timeout_established,       /* SCTP_CONNTRACK_ESTABLISHED */
+    &ip_ct_sctp_timeout_shutdown_sent,     /* SCTP_CONNTRACK_SHUTDOWN_SENT */
+    &ip_ct_sctp_timeout_shutdown_recd,     /* SCTP_CONNTRACK_SHUTDOWN_RECD */
+    &ip_ct_sctp_timeout_shutdown_ack_sent  /* SCTP_CONNTRACK_SHUTDOWN_ACK_SENT */
+ };
+
+#define sNO SCTP_CONNTRACK_NONE
+#define	sCL SCTP_CONNTRACK_CLOSED
+#define	sCW SCTP_CONNTRACK_COOKIE_WAIT
+#define	sCE SCTP_CONNTRACK_COOKIE_ECHOED
+#define	sES SCTP_CONNTRACK_ESTABLISHED
+#define	sSS SCTP_CONNTRACK_SHUTDOWN_SENT
+#define	sSR SCTP_CONNTRACK_SHUTDOWN_RECD
+#define	sSA SCTP_CONNTRACK_SHUTDOWN_ACK_SENT
+#define	sIV SCTP_CONNTRACK_MAX
+
+/* 
+	These are the descriptions of the states:
+
+NOTE: These state names are tantalizingly similar to the states of an 
+SCTP endpoint. But the interpretation of the states is a little different,
+considering that these are the states of the connection and not of an end 
+point. Please note the subtleties. -Kiran
+
+NONE              - Nothing so far.
+COOKIE WAIT       - We have seen an INIT chunk in the original direction, or also 
+                    an INIT_ACK chunk in the reply direction.
+COOKIE ECHOED     - We have seen a COOKIE_ECHO chunk in the original direction.
+ESTABLISHED       - We have seen a COOKIE_ACK in the reply direction.
+SHUTDOWN_SENT     - We have seen a SHUTDOWN chunk in the original direction.
+SHUTDOWN_RECD     - We have seen a SHUTDOWN chunk in the reply directoin.
+SHUTDOWN_ACK_SENT - We have seen a SHUTDOWN_ACK chunk in the direction opposite
+                    to that of the SHUTDOWN chunk.
+CLOSED            - We have seen a SHUTDOWN_COMPLETE chunk in the direction of 
+                    the SHUTDOWN chunk. Connection is closed.
+*/
+
+/* TODO
+ - I have assumed that the first INIT is in the original direction. 
+ This messes things when an INIT comes in the reply direction in CLOSED
+ state.
+ - Check the error type in the reply dir before transitioning from 
+cookie echoed to closed.
+ - Sec 5.2.4 of RFC 2960
+ - Multi Homing support.
+*/
+
+/* SCTP conntrack state transitions */
+static enum sctp_conntrack sctp_conntracks[2][9][SCTP_CONNTRACK_MAX] = {
+	{
+/*	ORIGINAL	*/
+/*                  sNO, sCL, sCW, sCE, sES, sSS, sSR, sSA */
+/* init         */ {sCW, sCW, sCW, sCE, sES, sSS, sSR, sSA},
+/* init_ack     */ {sCL, sCL, sCW, sCE, sES, sSS, sSR, sSA},
+/* abort        */ {sCL, sCL, sCL, sCL, sCL, sCL, sCL, sCL},
+/* shutdown     */ {sCL, sCL, sCW, sCE, sSS, sSS, sSR, sSA},
+/* shutdown_ack */ {sSA, sCL, sCW, sCE, sES, sSA, sSA, sSA},
+/* error        */ {sCL, sCL, sCW, sCE, sES, sSS, sSR, sSA},/* Cant have Stale cookie*/
+/* cookie_echo  */ {sCL, sCL, sCE, sCE, sES, sSS, sSR, sSA},/* 5.2.4 - Big TODO */
+/* cookie_ack   */ {sCL, sCL, sCW, sCE, sES, sSS, sSR, sSA},/* Cant come in orig dir */
+/* shutdown_comp*/ {sCL, sCL, sCW, sCE, sES, sSS, sSR, sCL}
+	},
+	{
+/*	REPLY	*/
+/*                  sNO, sCL, sCW, sCE, sES, sSS, sSR, sSA */
+/* init         */ {sIV, sCL, sCW, sCE, sES, sSS, sSR, sSA},/* INIT in sCL Big TODO */
+/* init_ack     */ {sIV, sCL, sCW, sCE, sES, sSS, sSR, sSA},
+/* abort        */ {sIV, sCL, sCL, sCL, sCL, sCL, sCL, sCL},
+/* shutdown     */ {sIV, sCL, sCW, sCE, sSR, sSS, sSR, sSA},
+/* shutdown_ack */ {sIV, sCL, sCW, sCE, sES, sSA, sSA, sSA},
+/* error        */ {sIV, sCL, sCW, sCL, sES, sSS, sSR, sSA},
+/* cookie_echo  */ {sIV, sCL, sCW, sCE, sES, sSS, sSR, sSA},/* Cant come in reply dir */
+/* cookie_ack   */ {sIV, sCL, sCW, sES, sES, sSS, sSR, sSA},
+/* shutdown_comp*/ {sIV, sCL, sCW, sCE, sES, sSS, sSR, sCL}
+	}
+};
+
+static int sctp_pkt_to_tuple(const struct sk_buff *skb,
+			     unsigned int dataoff,
+			     struct ip_conntrack_tuple *tuple)
+{
+	sctp_sctphdr_t _hdr, *hp;
+
+	DEBUGP(__FUNCTION__);
+	DEBUGP("\n");
+
+	/* Actually only need first 8 bytes. */
+	hp = skb_header_pointer(skb, dataoff, 8, &_hdr);
+	if (hp == NULL)
+		return 0;
+
+	tuple->src.u.sctp.port = hp->source;
+	tuple->dst.u.sctp.port = hp->dest;
+	return 1;
+}
+
+static int sctp_invert_tuple(struct ip_conntrack_tuple *tuple,
+			     const struct ip_conntrack_tuple *orig)
+{
+	DEBUGP(__FUNCTION__);
+	DEBUGP("\n");
+
+	tuple->src.u.sctp.port = orig->dst.u.sctp.port;
+	tuple->dst.u.sctp.port = orig->src.u.sctp.port;
+	return 1;
+}
+
+/* Print out the per-protocol part of the tuple. */
+static int sctp_print_tuple(struct seq_file *s,
+			    const struct ip_conntrack_tuple *tuple)
+{
+	DEBUGP(__FUNCTION__);
+	DEBUGP("\n");
+
+	return seq_printf(s, "sport=%hu dport=%hu ",
+			  ntohs(tuple->src.u.sctp.port),
+			  ntohs(tuple->dst.u.sctp.port));
+}
+
+/* Print out the private part of the conntrack. */
+static int sctp_print_conntrack(struct seq_file *s,
+				const struct ip_conntrack *conntrack)
+{
+	enum sctp_conntrack state;
+
+	DEBUGP(__FUNCTION__);
+	DEBUGP("\n");
+
+	READ_LOCK(&sctp_lock);
+	state = conntrack->proto.sctp.state;
+	READ_UNLOCK(&sctp_lock);
+
+	return seq_printf(s, "%s ", sctp_conntrack_names[state]);
+}
+
+#define for_each_sctp_chunk(skb, sch, _sch, offset, count)		\
+for (offset = skb->nh.iph->ihl * 4 + sizeof(sctp_sctphdr_t), count = 0;	\
+	offset < skb->len &&						\
+	(sch = skb_header_pointer(skb, offset, sizeof(_sch), &_sch));	\
+	offset += (htons(sch->length) + 3) & ~3, count++)
+
+/* Some validity checks to make sure the chunks are fine */
+static int do_basic_checks(struct ip_conntrack *conntrack,
+			   const struct sk_buff *skb,
+			   char *map)
+{
+	u_int32_t offset, count;
+	sctp_chunkhdr_t _sch, *sch;
+	int flag;
+
+	DEBUGP(__FUNCTION__);
+	DEBUGP("\n");
+
+	flag = 0;
+
+	for_each_sctp_chunk (skb, sch, _sch, offset, count) {
+		DEBUGP("Chunk Num: %d  Type: %d\n", count, sch->type);
+
+		if (sch->type == SCTP_CID_INIT 
+			|| sch->type == SCTP_CID_INIT_ACK
+			|| sch->type == SCTP_CID_SHUTDOWN_COMPLETE) {
+			flag = 1;
+		}
+
+		/* Cookie Ack/Echo chunks not the first OR 
+		   Init / Init Ack / Shutdown compl chunks not the only chunks */
+		if ((sch->type == SCTP_CID_COOKIE_ACK 
+			|| sch->type == SCTP_CID_COOKIE_ECHO
+			|| flag)
+		     && count !=0 ) {
+			DEBUGP("Basic checks failed\n");
+			return 1;
+		}
+
+		if (map) {
+			set_bit(sch->type, (void *)map);
+		}
+	}
+
+	DEBUGP("Basic checks passed\n");
+	return 0;
+}
+
+static int new_state(enum ip_conntrack_dir dir,
+		     enum sctp_conntrack cur_state,
+		     int chunk_type)
+{
+	int i;
+
+	DEBUGP(__FUNCTION__);
+	DEBUGP("\n");
+
+	DEBUGP("Chunk type: %d\n", chunk_type);
+
+	switch (chunk_type) {
+		case SCTP_CID_INIT: 
+			DEBUGP("SCTP_CID_INIT\n");
+			i = 0; break;
+		case SCTP_CID_INIT_ACK: 
+			DEBUGP("SCTP_CID_INIT_ACK\n");
+			i = 1; break;
+		case SCTP_CID_ABORT: 
+			DEBUGP("SCTP_CID_ABORT\n");
+			i = 2; break;
+		case SCTP_CID_SHUTDOWN: 
+			DEBUGP("SCTP_CID_SHUTDOWN\n");
+			i = 3; break;
+		case SCTP_CID_SHUTDOWN_ACK: 
+			DEBUGP("SCTP_CID_SHUTDOWN_ACK\n");
+			i = 4; break;
+		case SCTP_CID_ERROR: 
+			DEBUGP("SCTP_CID_ERROR\n");
+			i = 5; break;
+		case SCTP_CID_COOKIE_ECHO: 
+			DEBUGP("SCTP_CID_COOKIE_ECHO\n");
+			i = 6; break;
+		case SCTP_CID_COOKIE_ACK: 
+			DEBUGP("SCTP_CID_COOKIE_ACK\n");
+			i = 7; break;
+		case SCTP_CID_SHUTDOWN_COMPLETE: 
+			DEBUGP("SCTP_CID_SHUTDOWN_COMPLETE\n");
+			i = 8; break;
+		default:
+			/* Other chunks like DATA, SACK, HEARTBEAT and
+			its ACK do not cause a change in state */
+			DEBUGP("Unknown chunk type, Will stay in %s\n", 
+						sctp_conntrack_names[cur_state]);
+			return cur_state;
+	}
+
+	DEBUGP("dir: %d   cur_state: %s  chunk_type: %d  new_state: %s\n", 
+			dir, sctp_conntrack_names[cur_state], chunk_type,
+			sctp_conntrack_names[sctp_conntracks[dir][i][cur_state]]);
+
+	return sctp_conntracks[dir][i][cur_state];
+}
+
+/* Returns verdict for packet, or -1 for invalid. */
+static int sctp_packet(struct ip_conntrack *conntrack,
+		       const struct sk_buff *skb,
+		       enum ip_conntrack_info ctinfo)
+{
+	enum sctp_conntrack newconntrack, oldsctpstate;
+	struct iphdr *iph = skb->nh.iph;
+	sctp_sctphdr_t _sctph, *sh;
+	sctp_chunkhdr_t _sch, *sch;
+	u_int32_t offset, count;
+	char map[256 / sizeof (char)] = {0};
+
+	DEBUGP(__FUNCTION__);
+	DEBUGP("\n");
+
+	sh = skb_header_pointer(skb, iph->ihl * 4, sizeof(_sctph), &_sctph);
+	if (sh == NULL)
+		return -1;
+
+	if (do_basic_checks(conntrack, skb, map) != 0)
+		return -1;
+
+	/* Check the verification tag (Sec 8.5) */
+	if (!test_bit(SCTP_CID_INIT, (void *)map)
+		&& !test_bit(SCTP_CID_SHUTDOWN_COMPLETE, (void *)map)
+		&& !test_bit(SCTP_CID_COOKIE_ECHO, (void *)map)
+		&& !test_bit(SCTP_CID_ABORT, (void *)map)
+		&& !test_bit(SCTP_CID_SHUTDOWN_ACK, (void *)map)
+		&& (sh->vtag != conntrack->proto.sctp.vtag[CTINFO2DIR(ctinfo)])) {
+		DEBUGP("Verification tag check failed\n");
+		return -1;
+	}
+
+	oldsctpstate = newconntrack = SCTP_CONNTRACK_MAX;
+	for_each_sctp_chunk (skb, sch, _sch, offset, count) {
+		WRITE_LOCK(&sctp_lock);
+
+		/* Special cases of Verification tag check (Sec 8.5.1) */
+		if (sch->type == SCTP_CID_INIT) {
+			/* Sec 8.5.1 (A) */
+			if (sh->vtag != 0) {
+				WRITE_UNLOCK(&sctp_lock);
+				return -1;
+			}
+		} else if (sch->type == SCTP_CID_ABORT) {
+			/* Sec 8.5.1 (B) */
+			if (!(sh->vtag == conntrack->proto.sctp.vtag[CTINFO2DIR(ctinfo)])
+				&& !(sh->vtag == conntrack->proto.sctp.vtag
+							[1 - CTINFO2DIR(ctinfo)])) {
+				WRITE_UNLOCK(&sctp_lock);
+				return -1;
+			}
+		} else if (sch->type == SCTP_CID_SHUTDOWN_COMPLETE) {
+			/* Sec 8.5.1 (C) */
+			if (!(sh->vtag == conntrack->proto.sctp.vtag[CTINFO2DIR(ctinfo)])
+				&& !(sh->vtag == conntrack->proto.sctp.vtag
+							[1 - CTINFO2DIR(ctinfo)] 
+					&& (sch->flags & 1))) {
+				WRITE_UNLOCK(&sctp_lock);
+				return -1;
+			}
+		} else if (sch->type == SCTP_CID_COOKIE_ECHO) {
+			/* Sec 8.5.1 (D) */
+			if (!(sh->vtag == conntrack->proto.sctp.vtag[CTINFO2DIR(ctinfo)])) {
+				WRITE_UNLOCK(&sctp_lock);
+				return -1;
+			}
+		}
+
+		oldsctpstate = conntrack->proto.sctp.state;
+		newconntrack = new_state(CTINFO2DIR(ctinfo), oldsctpstate, sch->type);
+
+		/* Invalid */
+		if (newconntrack == SCTP_CONNTRACK_MAX) {
+			DEBUGP("ip_conntrack_sctp: Invalid dir=%i ctype=%u conntrack=%u\n",
+			       CTINFO2DIR(ctinfo), sch->type, oldsctpstate);
+			WRITE_UNLOCK(&sctp_lock);
+			return -1;
+		}
+
+		/* If it is an INIT or an INIT ACK note down the vtag */
+		if (sch->type == SCTP_CID_INIT 
+			|| sch->type == SCTP_CID_INIT_ACK) {
+			sctp_inithdr_t _inithdr, *ih;
+
+			ih = skb_header_pointer(skb, offset + sizeof(sctp_chunkhdr_t),
+			                        sizeof(_inithdr), &_inithdr);
+			if (ih == NULL) {
+					WRITE_UNLOCK(&sctp_lock);
+					return -1;
+			}
+			DEBUGP("Setting vtag %x for dir %d\n", 
+					ih->init_tag, CTINFO2DIR(ctinfo));
+			conntrack->proto.sctp.vtag[IP_CT_DIR_ORIGINAL] = ih->init_tag;
+		}
+
+		conntrack->proto.sctp.state = newconntrack;
+		WRITE_UNLOCK(&sctp_lock);
+	}
+
+	ip_ct_refresh_acct(conntrack, ctinfo, skb, *sctp_timeouts[newconntrack]);
+
+	if (oldsctpstate == SCTP_CONNTRACK_COOKIE_ECHOED
+		&& CTINFO2DIR(ctinfo) == IP_CT_DIR_REPLY
+		&& newconntrack == SCTP_CONNTRACK_ESTABLISHED) {
+		DEBUGP("Setting assured bit\n");
+		set_bit(IPS_ASSURED_BIT, &conntrack->status);
+	}
+
+	return NF_ACCEPT;
+}
+
+/* Called when a new connection for this protocol found. */
+static int sctp_new(struct ip_conntrack *conntrack, 
+		    const struct sk_buff *skb)
+{
+	enum sctp_conntrack newconntrack;
+	struct iphdr *iph = skb->nh.iph;
+	sctp_sctphdr_t _sctph, *sh;
+	sctp_chunkhdr_t _sch, *sch;
+	u_int32_t offset, count;
+	char map[256 / sizeof (char)] = {0};
+
+	DEBUGP(__FUNCTION__);
+	DEBUGP("\n");
+
+	sh = skb_header_pointer(skb, iph->ihl * 4, sizeof(_sctph), &_sctph);
+	if (sh == NULL)
+		return 0;
+
+	if (do_basic_checks(conntrack, skb, map) != 0)
+		return 0;
+
+	/* If an OOTB packet has any of these chunks discard (Sec 8.4) */
+	if ((test_bit (SCTP_CID_ABORT, (void *)map))
+		|| (test_bit (SCTP_CID_SHUTDOWN_COMPLETE, (void *)map))
+		|| (test_bit (SCTP_CID_COOKIE_ACK, (void *)map))) {
+		return 0;
+	}
+
+	newconntrack = SCTP_CONNTRACK_MAX;
+	for_each_sctp_chunk (skb, sch, _sch, offset, count) {
+		/* Don't need lock here: this conntrack not in circulation yet */
+		newconntrack = new_state (IP_CT_DIR_ORIGINAL, 
+						SCTP_CONNTRACK_NONE, sch->type);
+
+		/* Invalid: delete conntrack */
+		if (newconntrack == SCTP_CONNTRACK_MAX) {
+			DEBUGP("ip_conntrack_sctp: invalid new deleting.\n");
+			return 0;
+		}
+
+		/* Copy the vtag into the state info */
+		if (sch->type == SCTP_CID_INIT) {
+			if (sh->vtag == 0) {
+				sctp_inithdr_t _inithdr, *ih;
+
+				ih = skb_header_pointer(skb, offset + sizeof(sctp_chunkhdr_t),
+				                        sizeof(_inithdr), &_inithdr);
+				if (ih == NULL)
+					return 0;
+
+				DEBUGP("Setting vtag %x for new conn\n", 
+					ih->init_tag);
+
+				conntrack->proto.sctp.vtag[IP_CT_DIR_REPLY] = 
+								ih->init_tag;
+			} else {
+				/* Sec 8.5.1 (A) */
+				return 0;
+			}
+		}
+		/* If it is a shutdown ack OOTB packet, we expect a return
+		   shutdown complete, otherwise an ABORT Sec 8.4 (5) and (8) */
+		else {
+			DEBUGP("Setting vtag %x for new conn OOTB\n", 
+				sh->vtag);
+			conntrack->proto.sctp.vtag[IP_CT_DIR_REPLY] = sh->vtag;
+		}
+
+		conntrack->proto.sctp.state = newconntrack;
+	}
+
+	return 1;
+}
+
+static int sctp_exp_matches_pkt(struct ip_conntrack_expect *exp,
+				const struct sk_buff *skb)
+{
+	/* To be implemented */
+	return 0;
+}
+
+struct ip_conntrack_protocol ip_conntrack_protocol_sctp = { 
+	.proto 		 = IPPROTO_SCTP, 
+	.name 		 = "sctp",
+	.pkt_to_tuple 	 = sctp_pkt_to_tuple, 
+	.invert_tuple 	 = sctp_invert_tuple, 
+	.print_tuple 	 = sctp_print_tuple, 
+	.print_conntrack = sctp_print_conntrack,
+	.packet 	 = sctp_packet, 
+	.new 		 = sctp_new, 
+	.destroy 	 = NULL, 
+	.exp_matches_pkt = sctp_exp_matches_pkt, 
+	.me 		 = THIS_MODULE 
+};
+
+#ifdef CONFIG_SYSCTL
+static ctl_table ip_ct_sysctl_table[] = {
+	{
+		.ctl_name	= NET_IPV4_NF_CONNTRACK_SCTP_TIMEOUT_CLOSED,
+		.procname	= "ip_conntrack_sctp_timeout_closed",
+		.data		= &ip_ct_sctp_timeout_closed,
+		.maxlen		= sizeof(unsigned int),
+		.mode		= 0644,
+		.proc_handler	= &proc_dointvec_jiffies,
+	},
+	{
+		.ctl_name	= NET_IPV4_NF_CONNTRACK_SCTP_TIMEOUT_COOKIE_WAIT,
+		.procname	= "ip_conntrack_sctp_timeout_cookie_wait",
+		.data		= &ip_ct_sctp_timeout_cookie_wait,
+		.maxlen		= sizeof(unsigned int),
+		.mode		= 0644,
+		.proc_handler	= &proc_dointvec_jiffies,
+	},
+	{
+		.ctl_name	= NET_IPV4_NF_CONNTRACK_SCTP_TIMEOUT_COOKIE_ECHOED,
+		.procname	= "ip_conntrack_sctp_timeout_cookie_echoed",
+		.data		= &ip_ct_sctp_timeout_cookie_echoed,
+		.maxlen		= sizeof(unsigned int),
+		.mode		= 0644,
+		.proc_handler	= &proc_dointvec_jiffies,
+	},
+	{
+		.ctl_name	= NET_IPV4_NF_CONNTRACK_SCTP_TIMEOUT_ESTABLISHED,
+		.procname	= "ip_conntrack_sctp_timeout_established",
+		.data		= &ip_ct_sctp_timeout_established,
+		.maxlen		= sizeof(unsigned int),
+		.mode		= 0644,
+		.proc_handler	= &proc_dointvec_jiffies,
+	},
+	{
+		.ctl_name	= NET_IPV4_NF_CONNTRACK_SCTP_TIMEOUT_SHUTDOWN_SENT,
+		.procname	= "ip_conntrack_sctp_timeout_shutdown_sent",
+		.data		= &ip_ct_sctp_timeout_shutdown_sent,
+		.maxlen		= sizeof(unsigned int),
+		.mode		= 0644,
+		.proc_handler	= &proc_dointvec_jiffies,
+	},
+	{
+		.ctl_name	= NET_IPV4_NF_CONNTRACK_SCTP_TIMEOUT_SHUTDOWN_RECD,
+		.procname	= "ip_conntrack_sctp_timeout_shutdown_recd",
+		.data		= &ip_ct_sctp_timeout_shutdown_recd,
+		.maxlen		= sizeof(unsigned int),
+		.mode		= 0644,
+		.proc_handler	= &proc_dointvec_jiffies,
+	},
+	{
+		.ctl_name	= NET_IPV4_NF_CONNTRACK_SCTP_TIMEOUT_SHUTDOWN_ACK_SENT,
+		.procname	= "ip_conntrack_sctp_timeout_shutdown_ack_sent",
+		.data		= &ip_ct_sctp_timeout_shutdown_ack_sent,
+		.maxlen		= sizeof(unsigned int),
+		.mode		= 0644,
+		.proc_handler	= &proc_dointvec_jiffies,
+	},
+	{ .ctl_name = 0 }
+};
+
+static ctl_table ip_ct_netfilter_table[] = {
+	{
+		.ctl_name	= NET_IPV4_NETFILTER,
+		.procname	= "netfilter",
+		.mode		= 0555,
+		.child		= ip_ct_sysctl_table,
+	},
+	{ .ctl_name = 0 }
+};
+
+static ctl_table ip_ct_ipv4_table[] = {
+	{
+		.ctl_name	= NET_IPV4,
+		.procname	= "ipv4",
+		.mode		= 0555,
+		.child		= ip_ct_netfilter_table,
+	},
+	{ .ctl_name = 0 }
+};
+
+static ctl_table ip_ct_net_table[] = {
+	{
+		.ctl_name	= CTL_NET,
+		.procname	= "net",
+		.mode		= 0555, 
+		.child		= ip_ct_ipv4_table,
+	},
+	{ .ctl_name = 0 }
+};
+
+static struct ctl_table_header *ip_ct_sysctl_header;
+#endif
+
+int __init init(void)
+{
+	int ret;
+
+	ret = ip_conntrack_protocol_register(&ip_conntrack_protocol_sctp);
+	if (ret) {
+		printk("ip_conntrack_proto_sctp: protocol register failed\n");
+		goto out;
+	}
+
+#ifdef CONFIG_SYSCTL
+	ip_ct_sysctl_header = register_sysctl_table(ip_ct_net_table, 0);
+	if (ip_ct_sysctl_header == NULL) {
+		printk("ip_conntrack_proto_sctp: can't register to sysctl.\n");
+		goto cleanup;
+	}
+#endif
+
+	return ret;
+
+#ifdef CONFIG_SYSCTL
+ cleanup:
+	ip_conntrack_protocol_unregister(&ip_conntrack_protocol_sctp);
+#endif
+ out:
+	DEBUGP("SCTP conntrack module loading %s\n", 
+					ret ? "failed": "succeeded");
+	return ret;
+}
+
+void __exit fini(void)
+{
+	ip_conntrack_protocol_unregister(&ip_conntrack_protocol_sctp);
+#ifdef CONFIG_SYSCTL
+ 	unregister_sysctl_table(ip_ct_sysctl_header);
+#endif
+	DEBUGP("SCTP conntrack module unloaded\n");
+}
+
+module_init(init);
+module_exit(fini);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Kiran Kumar Immidi");
+MODULE_DESCRIPTION("Netfilter connection tracking protocol helper for SCTP");
diff -Nru a/net/ipv4/netfilter/ip_conntrack_proto_tcp.c b/net/ipv4/netfilter/ip_conntrack_proto_tcp.c
--- a/net/ipv4/netfilter/ip_conntrack_proto_tcp.c	2004-10-18 14:57:04 -07:00
+++ b/net/ipv4/netfilter/ip_conntrack_proto_tcp.c	2004-10-18 14:57:04 -07:00
@@ -4,8 +4,22 @@
  * 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.
+ *
+ * Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>:
+ *	- Real stateful connection tracking
+ *	- Modified state transitions table
+ *	- Window scaling support added
+ *	- SACK support added
+ *
+ * Willy Tarreau:
+ *	- State table bugfixes
+ *	- More robust state changes
+ *	- Tuning timer parameters
+ *
+ * version 2.2
  */
 
+#include <linux/config.h>
 #include <linux/types.h>
 #include <linux/sched.h>
 #include <linux/timer.h>
@@ -14,16 +28,19 @@
 #include <linux/in.h>
 #include <linux/ip.h>
 #include <linux/tcp.h>
-#include <linux/string.h>
+#include <linux/spinlock.h>
 
 #include <net/tcp.h>
 
+#include <linux/netfilter.h>
+#include <linux/netfilter_ipv4.h>
 #include <linux/netfilter_ipv4/ip_conntrack.h>
 #include <linux/netfilter_ipv4/ip_conntrack_protocol.h>
 #include <linux/netfilter_ipv4/lockhelp.h>
 
 #if 0
 #define DEBUGP printk
+#define DEBUGP_VARS
 #else
 #define DEBUGP(format, args...)
 #endif
@@ -31,28 +48,40 @@
 /* Protects conntrack->proto.tcp */
 static DECLARE_RWLOCK(tcp_lock);
 
-/* FIXME: Examine ipfilter's timeouts and conntrack transitions more
-   closely.  They're more complex. --RR */
+/* "Be conservative in what you do, 
+    be liberal in what you accept from others." 
+    If it's non-zero, we mark only out of window RST segments as INVALID. */
+int ip_ct_tcp_be_liberal = 0;
+
+/* When connection is picked up from the middle, how many packets are required
+   to pass in each direction when we assume we are in sync - if any side uses
+   window scaling, we lost the game. 
+   If it is set to zero, we disable picking up already established 
+   connections. */
+int ip_ct_tcp_loose = 3;
+
+/* Max number of the retransmitted packets without receiving an (acceptable) 
+   ACK from the destination. If this number is reached, a shorter timer 
+   will be started. */
+int ip_ct_tcp_max_retrans = 3;
 
-/* Actually, I believe that neither ipmasq (where this code is stolen
-   from) nor ipfilter do it exactly right.  A new conntrack machine taking
-   into account packet loss (which creates uncertainty as to exactly
-   the conntrack of the connection) is required.  RSN.  --RR */
+  /* FIXME: Examine ipfilter's timeouts and conntrack transitions more
+     closely.  They're more complex. --RR */
 
 static const char *tcp_conntrack_names[] = {
 	"NONE",
-	"ESTABLISHED",
 	"SYN_SENT",
 	"SYN_RECV",
+	"ESTABLISHED",
 	"FIN_WAIT",
-	"TIME_WAIT",
-	"CLOSE",
 	"CLOSE_WAIT",
 	"LAST_ACK",
+	"TIME_WAIT",
+	"CLOSE",
 	"LISTEN"
 };
-
-#define SECS *HZ
+  
+#define SECS * HZ
 #define MINS * 60 SECS
 #define HOURS * 60 MINS
 #define DAYS * 24 HOURS
@@ -66,64 +95,214 @@
 unsigned long ip_ct_tcp_timeout_time_wait =     2 MINS;
 unsigned long ip_ct_tcp_timeout_close =        10 SECS;
 
+/* RFC1122 says the R2 limit should be at least 100 seconds.
+   Linux uses 15 packets as limit, which corresponds 
+   to ~13-30min depending on RTO. */
+unsigned long ip_ct_tcp_timeout_max_retrans =     5 MINS;
+ 
 static unsigned long * tcp_timeouts[]
 = { NULL,                              /*      TCP_CONNTRACK_NONE */
-    &ip_ct_tcp_timeout_established,    /*      TCP_CONNTRACK_ESTABLISHED,      */
     &ip_ct_tcp_timeout_syn_sent,       /*      TCP_CONNTRACK_SYN_SENT, */
     &ip_ct_tcp_timeout_syn_recv,       /*      TCP_CONNTRACK_SYN_RECV, */
+    &ip_ct_tcp_timeout_established,    /*      TCP_CONNTRACK_ESTABLISHED,      */
     &ip_ct_tcp_timeout_fin_wait,       /*      TCP_CONNTRACK_FIN_WAIT, */
-    &ip_ct_tcp_timeout_time_wait,      /*      TCP_CONNTRACK_TIME_WAIT,        */
-    &ip_ct_tcp_timeout_close,          /*      TCP_CONNTRACK_CLOSE,    */
     &ip_ct_tcp_timeout_close_wait,     /*      TCP_CONNTRACK_CLOSE_WAIT,       */
     &ip_ct_tcp_timeout_last_ack,       /*      TCP_CONNTRACK_LAST_ACK, */
+    &ip_ct_tcp_timeout_time_wait,      /*      TCP_CONNTRACK_TIME_WAIT,        */
+    &ip_ct_tcp_timeout_close,          /*      TCP_CONNTRACK_CLOSE,    */
     NULL,                              /*      TCP_CONNTRACK_LISTEN */
  };
  
 #define sNO TCP_CONNTRACK_NONE
-#define sES TCP_CONNTRACK_ESTABLISHED
 #define sSS TCP_CONNTRACK_SYN_SENT
 #define sSR TCP_CONNTRACK_SYN_RECV
+#define sES TCP_CONNTRACK_ESTABLISHED
 #define sFW TCP_CONNTRACK_FIN_WAIT
-#define sTW TCP_CONNTRACK_TIME_WAIT
-#define sCL TCP_CONNTRACK_CLOSE
 #define sCW TCP_CONNTRACK_CLOSE_WAIT
 #define sLA TCP_CONNTRACK_LAST_ACK
+#define sTW TCP_CONNTRACK_TIME_WAIT
+#define sCL TCP_CONNTRACK_CLOSE
 #define sLI TCP_CONNTRACK_LISTEN
 #define sIV TCP_CONNTRACK_MAX
+#define sIG TCP_CONNTRACK_IGNORE
 
-static enum tcp_conntrack tcp_conntracks[2][5][TCP_CONNTRACK_MAX] = {
+/* What TCP flags are set from RST/SYN/FIN/ACK. */
+enum tcp_bit_set {
+	TCP_SYN_SET,
+	TCP_SYNACK_SET,
+	TCP_FIN_SET,
+	TCP_ACK_SET,
+	TCP_RST_SET,
+	TCP_NONE_SET,
+};
+  
+/*
+ * The TCP state transition table needs a few words...
+ *
+ * We are the man in the middle. All the packets go through us
+ * but might get lost in transit to the destination.
+ * It is assumed that the destinations can't receive segments 
+ * we haven't seen.
+ *
+ * The checked segment is in window, but our windows are *not*
+ * equivalent with the ones of the sender/receiver. We always
+ * try to guess the state of the current sender.
+ *
+ * The meaning of the states are:
+ *
+ * NONE:	initial state
+ * SYN_SENT:	SYN-only packet seen 
+ * SYN_RECV:	SYN-ACK packet seen
+ * ESTABLISHED:	ACK packet seen
+ * FIN_WAIT:	FIN packet seen
+ * CLOSE_WAIT:	ACK seen (after FIN) 
+ * LAST_ACK:	FIN seen (after FIN)
+ * TIME_WAIT:	last ACK seen
+ * CLOSE:	closed connection
+ *
+ * LISTEN state is not used.
+ *
+ * Packets marked as IGNORED (sIG):
+ *	if they may be either invalid or valid 
+ *	and the receiver may send back a connection 
+ *	closing RST or a SYN/ACK.
+ *
+ * Packets marked as INVALID (sIV):
+ *	if they are invalid
+ *	or we do not support the request (simultaneous open)
+ */
+static enum tcp_conntrack tcp_conntracks[2][6][TCP_CONNTRACK_MAX] = {
 	{
-/*	ORIGINAL */
-/* 	  sNO, sES, sSS, sSR, sFW, sTW, sCL, sCW, sLA, sLI 	*/
-/*syn*/	{sSS, sES, sSS, sSR, sSS, sSS, sSS, sSS, sSS, sLI },
-/*fin*/	{sTW, sFW, sSS, sTW, sFW, sTW, sCL, sTW, sLA, sLI },
-/*ack*/	{sES, sES, sSS, sES, sFW, sTW, sCL, sCW, sLA, sES },
-/*rst*/ {sCL, sCL, sSS, sCL, sCL, sTW, sCL, sCL, sCL, sCL },
-/*none*/{sIV, sIV, sIV, sIV, sIV, sIV, sIV, sIV, sIV, sIV }
+/* ORIGINAL */
+/* 	     sNO, sSS, sSR, sES, sFW, sCW, sLA, sTW, sCL, sLI	*/
+/*syn*/	   { sSS, sSS, sIG, sIG, sIG, sIG, sIG, sSS, sSS, sIV },
+/*
+ *	sNO -> sSS	Initialize a new connection
+ *	sSS -> sSS	Retransmitted SYN
+ *	sSR -> sIG	Late retransmitted SYN?
+ *	sES -> sIG	Error: SYNs in window outside the SYN_SENT state
+ *			are errors. Receiver will reply with RST 
+ *			and close the connection.
+ *			Or we are not in sync and hold a dead connection.
+ *	sFW -> sIG
+ *	sCW -> sIG
+ *	sLA -> sIG
+ *	sTW -> sSS	Reopened connection (RFC 1122).
+ *	sCL -> sSS
+ */
+/* 	     sNO, sSS, sSR, sES, sFW, sCW, sLA, sTW, sCL, sLI	*/
+/*synack*/ { sIV, sIV, sIV, sIV, sIV, sIV, sIV, sIV, sIV, sIV },
+/*
+ * A SYN/ACK from the client is always invalid:
+ *	- either it tries to set up a simultaneous open, which is 
+ *	  not supported;
+ *	- or the firewall has just been inserted between the two hosts
+ *	  during the session set-up. The SYN will be retransmitted 
+ *	  by the true client (or it'll time out).
+ */
+/* 	     sNO, sSS, sSR, sES, sFW, sCW, sLA, sTW, sCL, sLI	*/
+/*fin*/    { sIV, sIV, sFW, sFW, sLA, sLA, sLA, sTW, sCL, sIV },
+/*
+ *	sNO -> sIV	Too late and no reason to do anything...
+ *	sSS -> sIV	Client migth not send FIN in this state:
+ *			we enforce waiting for a SYN/ACK reply first.
+ *	sSR -> sFW	Close started.
+ *	sES -> sFW	
+ *	sFW -> sLA	FIN seen in both directions, waiting for
+ *			the last ACK. 
+ *			Migth be a retransmitted FIN as well...
+ *	sCW -> sLA
+ *	sLA -> sLA	Retransmitted FIN. Remain in the same state.
+ *	sTW -> sTW
+ *	sCL -> sCL
+ */
+/* 	     sNO, sSS, sSR, sES, sFW, sCW, sLA, sTW, sCL, sLI	*/
+/*ack*/	   { sES, sIV, sES, sES, sCW, sCW, sTW, sTW, sCL, sIV },
+/*
+ *	sNO -> sES	Assumed.
+ *	sSS -> sIV	ACK is invalid: we haven't seen a SYN/ACK yet.
+ *	sSR -> sES	Established state is reached.
+ *	sES -> sES	:-)
+ *	sFW -> sCW	Normal close request answered by ACK.
+ *	sCW -> sCW
+ *	sLA -> sTW	Last ACK detected.
+ *	sTW -> sTW	Retransmitted last ACK. Remain in the same state.
+ *	sCL -> sCL
+ */
+/* 	     sNO, sSS, sSR, sES, sFW, sCW, sLA, sTW, sCL, sLI	*/
+/*rst*/    { sIV, sCL, sCL, sCL, sCL, sCL, sCL, sCL, sCL, sIV },
+/*none*/   { sIV, sIV, sIV, sIV, sIV, sIV, sIV, sIV, sIV, sIV }
 	},
 	{
-/*	REPLY */
-/* 	  sNO, sES, sSS, sSR, sFW, sTW, sCL, sCW, sLA, sLI 	*/
-/*syn*/	{sSR, sES, sSR, sSR, sSR, sSR, sSR, sSR, sSR, sSR },
-/*fin*/	{sCL, sCW, sSS, sTW, sTW, sTW, sCL, sCW, sLA, sLI },
-/*ack*/	{sCL, sES, sSS, sSR, sFW, sTW, sCL, sCW, sCL, sLI },
-/*rst*/ {sCL, sCL, sCL, sCL, sCL, sCL, sCL, sCL, sLA, sLI },
-/*none*/{sIV, sIV, sIV, sIV, sIV, sIV, sIV, sIV, sIV, sIV }
-	}
+/* REPLY */
+/* 	     sNO, sSS, sSR, sES, sFW, sCW, sLA, sTW, sCL, sLI	*/
+/*syn*/	   { sIV, sIV, sIV, sIV, sIV, sIV, sIV, sIV, sIV, sIV },
+/*
+ *	sNO -> sIV	Never reached.
+ *	sSS -> sIV	Simultaneous open, not supported
+ *	sSR -> sIV	Simultaneous open, not supported.
+ *	sES -> sIV	Server may not initiate a connection.
+ *	sFW -> sIV
+ *	sCW -> sIV
+ *	sLA -> sIV
+ *	sTW -> sIV	Reopened connection, but server may not do it.
+ *	sCL -> sIV
+ */
+/* 	     sNO, sSS, sSR, sES, sFW, sCW, sLA, sTW, sCL, sLI	*/
+/*synack*/ { sIV, sSR, sSR, sIG, sIG, sIG, sIG, sIG, sIG, sIV },
+/*
+ *	sSS -> sSR	Standard open.
+ *	sSR -> sSR	Retransmitted SYN/ACK.
+ *	sES -> sIG	Late retransmitted SYN/ACK?
+ *	sFW -> sIG
+ *	sCW -> sIG
+ *	sLA -> sIG
+ *	sTW -> sIG
+ *	sCL -> sIG
+ */
+/* 	     sNO, sSS, sSR, sES, sFW, sCW, sLA, sTW, sCL, sLI	*/
+/*fin*/    { sIV, sIV, sFW, sFW, sLA, sLA, sLA, sTW, sCL, sIV },
+/*
+ *	sSS -> sIV	Server might not send FIN in this state.
+ *	sSR -> sFW	Close started.
+ *	sES -> sFW
+ *	sFW -> sLA	FIN seen in both directions.
+ *	sCW -> sLA
+ *	sLA -> sLA	Retransmitted FIN.
+ *	sTW -> sTW
+ *	sCL -> sCL
+ */
+/* 	     sNO, sSS, sSR, sES, sFW, sCW, sLA, sTW, sCL, sLI	*/
+/*ack*/	   { sIV, sIV, sIV, sES, sCW, sCW, sTW, sTW, sCL, sIV },
+/*
+ *	sSS -> sIV	ACK is invalid: we haven't seen a SYN/ACK yet.
+ *	sSR -> sIV	Simultaneous open.
+ *	sES -> sES	:-)
+ *	sFW -> sCW	Normal close request answered by ACK.
+ *	sCW -> sCW
+ *	sLA -> sTW	Last ACK detected.
+ *	sTW -> sTW	Retransmitted last ACK.
+ *	sCL -> sCL
+ */
+/* 	     sNO, sSS, sSR, sES, sFW, sCW, sLA, sTW, sCL, sLI	*/
+/*rst*/    { sIV, sCL, sCL, sCL, sCL, sCL, sCL, sCL, sCL, sIV },
+/*none*/   { sIV, sIV, sIV, sIV, sIV, sIV, sIV, sIV, sIV, sIV }
+  	}
 };
 
 static int tcp_pkt_to_tuple(const struct sk_buff *skb,
-			     unsigned int dataoff,
-			     struct ip_conntrack_tuple *tuple)
+			    unsigned int dataoff,
+			    struct ip_conntrack_tuple *tuple)
 {
-	struct tcphdr hdr;
+	struct tcphdr _hdr, *hp;
 
 	/* Actually only need first 8 bytes. */
-	if (skb_copy_bits(skb, dataoff, &hdr, 8) != 0)
+	hp = skb_header_pointer(skb, dataoff, 8, &_hdr);
+	if (hp == NULL)
 		return 0;
 
-	tuple->src.u.tcp.port = hdr.source;
-	tuple->dst.u.tcp.port = hdr.dest;
+	tuple->src.u.tcp.port = hp->source;
+	tuple->dst.u.tcp.port = hp->dest;
 
 	return 1;
 }
@@ -137,17 +316,17 @@
 }
 
 /* Print out the per-protocol part of the tuple. */
-static unsigned int tcp_print_tuple(char *buffer,
-				    const struct ip_conntrack_tuple *tuple)
+static int tcp_print_tuple(struct seq_file *s,
+			   const struct ip_conntrack_tuple *tuple)
 {
-	return sprintf(buffer, "sport=%hu dport=%hu ",
-		       ntohs(tuple->src.u.tcp.port),
-		       ntohs(tuple->dst.u.tcp.port));
+	return seq_printf(s, "sport=%hu dport=%hu ",
+			  ntohs(tuple->src.u.tcp.port),
+			  ntohs(tuple->dst.u.tcp.port));
 }
 
 /* Print out the private part of the conntrack. */
-static unsigned int tcp_print_conntrack(char *buffer,
-					const struct ip_conntrack *conntrack)
+static int tcp_print_conntrack(struct seq_file *s,
+			       const struct ip_conntrack *conntrack)
 {
 	enum tcp_conntrack state;
 
@@ -155,120 +334,754 @@
 	state = conntrack->proto.tcp.state;
 	READ_UNLOCK(&tcp_lock);
 
-	return sprintf(buffer, "%s ", tcp_conntrack_names[state]);
+	return seq_printf(s, "%s ", tcp_conntrack_names[state]);
 }
 
 static unsigned int get_conntrack_index(const struct tcphdr *tcph)
 {
-	if (tcph->rst) return 3;
-	else if (tcph->syn) return 0;
-	else if (tcph->fin) return 1;
-	else if (tcph->ack) return 2;
-	else return 4;
+	if (tcph->rst) return TCP_RST_SET;
+	else if (tcph->syn) return (tcph->ack ? TCP_SYNACK_SET : TCP_SYN_SET);
+	else if (tcph->fin) return TCP_FIN_SET;
+	else if (tcph->ack) return TCP_ACK_SET;
+	else return TCP_NONE_SET;
 }
 
-/* Returns verdict for packet, or -1 for invalid. */
-static int tcp_packet(struct ip_conntrack *conntrack,
-		      const struct sk_buff *skb,
-		      enum ip_conntrack_info ctinfo)
+/* TCP connection tracking based on 'Real Stateful TCP Packet Filtering
+   in IP Filter' by Guido van Rooij.
+   
+   http://www.nluug.nl/events/sane2000/papers.html
+   http://www.iae.nl/users/guido/papers/tcp_filtering.ps.gz
+   
+   The boundaries and the conditions are slightly changed:
+   
+   	td_maxend = max(sack + max(win,1)) seen in reply packets
+	td_maxwin = max(max(win, 1)) + (sack - ack) seen in sent packets
+	td_end    = max(seq + len) seen in sent packets
+   
+   I. 	Upper bound for valid data:	seq + len <= sender.td_maxend
+   II. 	Lower bound for valid data:	seq >= sender.td_end - receiver.td_maxwin
+   III.	Upper bound for valid ack:      sack <= receiver.td_end
+   IV.	Lower bound for valid ack:	ack >= receiver.td_end - MAXACKWINDOW
+   	
+   where sack is the highest right edge of sack block found in the packet.
+   	
+   The upper bound limit for a valid ack is not ignored - 
+   we doesn't have to deal with fragments. 
+*/
+
+static inline __u32 segment_seq_plus_len(__u32 seq,
+					 size_t len,
+					 struct iphdr *iph,
+					 struct tcphdr *tcph)
+  {
+	return (seq + len - (iph->ihl + tcph->doff)*4
+		+ (tcph->syn ? 1 : 0) + (tcph->fin ? 1 : 0));
+}
+  
+/* Fixme: what about big packets? */
+#define MAXACKWINCONST			66000
+#define MAXACKWINDOW(sender)						\
+	((sender)->td_maxwin > MAXACKWINCONST ? (sender)->td_maxwin	\
+					      : MAXACKWINCONST)
+  
+/*
+ * Simplified tcp_parse_options routine from tcp_input.c
+ */
+static void tcp_options(const struct sk_buff *skb,
+			struct iphdr *iph,
+			struct tcphdr *tcph, 
+			struct ip_ct_tcp_state *state)
 {
-	enum tcp_conntrack newconntrack, oldtcpstate;
-	struct tcphdr tcph;
-
-	if (skb_copy_bits(skb, skb->nh.iph->ihl * 4, &tcph, sizeof(tcph)) != 0)
-		return -1;
-	if (skb->len < skb->nh.iph->ihl * 4 + tcph.doff * 4)
-		return -1;
-
-	/* If only reply is a RST, we can consider ourselves not to
-	   have an established connection: this is a fairly common
-	   problem case, so we can delete the conntrack
-	   immediately.  --RR */
-	if (!test_bit(IPS_SEEN_REPLY_BIT, &conntrack->status) && tcph.rst) {
-		if (del_timer(&conntrack->timeout))
-			conntrack->timeout.function((unsigned long)conntrack);
-		return NF_ACCEPT;
+	unsigned char buff[(15 * 4) - sizeof(struct tcphdr)];
+	unsigned char *ptr;
+	int length = (tcph->doff*4) - sizeof(struct tcphdr);
+	
+	if (!length)
+		return;
+
+	ptr = skb_header_pointer(skb,
+				 (iph->ihl * 4) + sizeof(struct tcphdr),
+				 length, buff);
+	BUG_ON(ptr == NULL);
+
+	state->td_scale = 
+	state->flags = 0;
+	
+	while (length > 0) {
+		int opcode=*ptr++;
+		int opsize;
+		
+		switch (opcode) {
+		case TCPOPT_EOL:
+			return;
+		case TCPOPT_NOP:	/* Ref: RFC 793 section 3.1 */
+			length--;
+			continue;
+		default:
+			opsize=*ptr++;
+			if (opsize < 2) /* "silly options" */
+				return;
+			if (opsize > length)
+				break;	/* don't parse partial options */
+
+			if (opcode == TCPOPT_SACK_PERM 
+			    && opsize == TCPOLEN_SACK_PERM)
+				state->flags |= IP_CT_TCP_FLAG_SACK_PERM;
+			else if (opcode == TCPOPT_WINDOW
+				 && opsize == TCPOLEN_WINDOW) {
+				state->td_scale = *(u_int8_t *)ptr;
+				
+				if (state->td_scale > 14) {
+					/* See RFC1323 */
+					state->td_scale = 14;
+				}
+				state->flags |=
+					IP_CT_TCP_STATE_FLAG_WINDOW_SCALE;
+			}
+			ptr += opsize - 2;
+			length -= opsize;
+		}
 	}
+}
 
-	WRITE_LOCK(&tcp_lock);
-	oldtcpstate = conntrack->proto.tcp.state;
-	newconntrack
-		= tcp_conntracks
-		[CTINFO2DIR(ctinfo)]
-		[get_conntrack_index(&tcph)][oldtcpstate];
-
-	/* Invalid */
-	if (newconntrack == TCP_CONNTRACK_MAX) {
-		DEBUGP("ip_conntrack_tcp: Invalid dir=%i index=%u conntrack=%u\n",
-		       CTINFO2DIR(ctinfo), get_conntrack_index(&tcph),
-		       conntrack->proto.tcp.state);
-		WRITE_UNLOCK(&tcp_lock);
-		return -1;
+static void tcp_sack(struct tcphdr *tcph, __u32 *sack)
+{
+	__u32 tmp;
+	unsigned char *ptr;
+	int length = (tcph->doff*4) - sizeof(struct tcphdr);
+	
+	/* Fast path for timestamp-only option */
+	if (length == TCPOLEN_TSTAMP_ALIGNED*4
+	    && *(__u32 *)(tcph + 1) ==
+	        __constant_ntohl((TCPOPT_NOP << 24) 
+	        		 | (TCPOPT_NOP << 16)
+	        		 | (TCPOPT_TIMESTAMP << 8)
+	        		 | TCPOLEN_TIMESTAMP))
+		return;
+		
+	ptr = (unsigned char *)(tcph + 1);
+	while (length > 0) {
+		int opcode=*ptr++;
+		int opsize, i;
+		
+		switch (opcode) {
+		case TCPOPT_EOL:
+			return;
+		case TCPOPT_NOP:	/* Ref: RFC 793 section 3.1 */
+			length--;
+			continue;
+		default:
+			opsize=*ptr++;
+			if (opsize < 2) /* "silly options" */
+				return;
+			if (opsize > length)
+				break;	/* don't parse partial options */
+
+			if (opcode == TCPOPT_SACK 
+			    && opsize >= (TCPOLEN_SACK_BASE 
+			    		  + TCPOLEN_SACK_PERBLOCK)
+			    && !((opsize - TCPOLEN_SACK_BASE) 
+			    	 % TCPOLEN_SACK_PERBLOCK)) {
+			    	for (i = 0;
+			    	     i < (opsize - TCPOLEN_SACK_BASE);
+			    	     i += TCPOLEN_SACK_PERBLOCK) {
+					tmp = ntohl(*((u_int32_t *)(ptr+i)+1));
+					
+					if (after(tmp, *sack))
+						*sack = tmp;
+				}
+				return;
+			}
+			ptr += opsize - 2;
+			length -= opsize;
+		}
 	}
+}
 
-	conntrack->proto.tcp.state = newconntrack;
+static int tcp_in_window(struct ip_ct_tcp *state, 
+                         enum ip_conntrack_dir dir,
+                         unsigned int *index,
+                         const struct sk_buff *skb,
+                         struct iphdr *iph,
+                         struct tcphdr *tcph)
+{
+	struct ip_ct_tcp_state *sender = &state->seen[dir];
+	struct ip_ct_tcp_state *receiver = &state->seen[!dir];
+	__u32 seq, ack, sack, end, win, swin;
+	int res;
+	
+	/*
+	 * Get the required data from the packet.
+	 */
+	seq = ntohl(tcph->seq);
+	ack = sack = ntohl(tcph->ack_seq);
+	win = ntohs(tcph->window);
+	end = segment_seq_plus_len(seq, skb->len, iph, tcph);
+	
+	if (receiver->flags & IP_CT_TCP_FLAG_SACK_PERM)
+		tcp_sack(tcph, &sack);
+		
+	DEBUGP("tcp_in_window: START\n");
+	DEBUGP("tcp_in_window: src=%u.%u.%u.%u:%hu dst=%u.%u.%u.%u:%hu "
+	       "seq=%u ack=%u sack=%u win=%u end=%u\n",
+		NIPQUAD(iph->saddr), ntohs(tcph->source), 
+		NIPQUAD(iph->daddr), ntohs(tcph->dest),
+		seq, ack, sack, win, end);
+	DEBUGP("tcp_in_window: sender end=%u maxend=%u maxwin=%u scale=%i "
+	       "receiver end=%u maxend=%u maxwin=%u scale=%i\n",
+		sender->td_end, sender->td_maxend, sender->td_maxwin,
+		sender->td_scale, 
+		receiver->td_end, receiver->td_maxend, receiver->td_maxwin, 
+		receiver->td_scale);
+		
+	if (sender->td_end == 0) {
+		/*
+		 * Initialize sender data.
+		 */
+		if (tcph->syn && tcph->ack) {
+			/*
+			 * Outgoing SYN-ACK in reply to a SYN.
+			 */
+			sender->td_end = 
+			sender->td_maxend = end;
+			sender->td_maxwin = (win == 0 ? 1 : win);
+
+			tcp_options(skb, iph, tcph, sender);
+			/* 
+			 * RFC 1323:
+			 * Both sides must send the Window Scale option
+			 * to enable window scaling in either direction.
+			 */
+			if (!(sender->flags & IP_CT_TCP_STATE_FLAG_WINDOW_SCALE
+			      && receiver->flags & IP_CT_TCP_STATE_FLAG_WINDOW_SCALE))
+				sender->td_scale = 
+				receiver->td_scale = 0;
+		} else {
+			/*
+			 * We are in the middle of a connection,
+			 * its history is lost for us.
+			 * Let's try to use the data from the packet.
+		 	 */
+			sender->td_end = end;
+			sender->td_maxwin = (win == 0 ? 1 : win);
+			sender->td_maxend = end + sender->td_maxwin;
+		}
+	} else if (state->state == TCP_CONNTRACK_SYN_SENT
+		   && dir == IP_CT_DIR_ORIGINAL
+		   && after(end, sender->td_end)) {
+		/*
+		 * RFC 793: "if a TCP is reinitialized ... then it need
+		 * not wait at all; it must only be sure to use sequence 
+		 * numbers larger than those recently used."
+		 */
+		sender->td_end =
+		sender->td_maxend = end;
+		sender->td_maxwin = (win == 0 ? 1 : win);
 
-	/* Poor man's window tracking: record SYN/ACK for handshake check */
-	if (oldtcpstate == TCP_CONNTRACK_SYN_SENT
-	    && CTINFO2DIR(ctinfo) == IP_CT_DIR_REPLY
-	    && tcph.syn && tcph.ack) {
-		conntrack->proto.tcp.handshake_ack
-			= htonl(ntohl(tcph.seq) + 1);
-		goto out;
+		tcp_options(skb, iph, tcph, sender);
 	}
+	
+	if (!(tcph->ack)) {
+		/*
+		 * If there is no ACK, just pretend it was set and OK.
+		 */
+		ack = sack = receiver->td_end;
+	} else if (((tcp_flag_word(tcph) & (TCP_FLAG_ACK|TCP_FLAG_RST)) == 
+		    (TCP_FLAG_ACK|TCP_FLAG_RST)) 
+		   && (ack == 0)) {
+		/*
+		 * Broken TCP stacks, that set ACK in RST packets as well
+		 * with zero ack value.
+		 */
+		ack = sack = receiver->td_end;
+	}
+
+	if (seq == end)
+		/*
+		 * Packets contains no data: we assume it is valid
+		 * and check the ack value only.
+		 */
+		seq = end = sender->td_end;
+		
+	DEBUGP("tcp_in_window: src=%u.%u.%u.%u:%hu dst=%u.%u.%u.%u:%hu "
+	       "seq=%u ack=%u sack =%u win=%u end=%u trim=%u\n",
+		NIPQUAD(iph->saddr), ntohs(tcph->source),
+		NIPQUAD(iph->daddr), ntohs(tcph->dest),
+		seq, ack, sack, win, end, 
+		after(end, sender->td_maxend) && before(seq, sender->td_maxend)
+		? sender->td_maxend : end);
+	DEBUGP("tcp_in_window: sender end=%u maxend=%u maxwin=%u scale=%i "
+	       "receiver end=%u maxend=%u maxwin=%u scale=%i\n",
+		sender->td_end, sender->td_maxend, sender->td_maxwin,
+		sender->td_scale, 
+		receiver->td_end, receiver->td_maxend, receiver->td_maxwin,
+		receiver->td_scale);
+	
+	/* Ignore data over the right edge of the receiver's window. */
+	if (after(end, sender->td_maxend) &&
+	    before(seq, sender->td_maxend)) {
+		end = sender->td_maxend;
+		if (*index == TCP_FIN_SET)
+			*index = TCP_ACK_SET;
+	}
+	DEBUGP("tcp_in_window: I=%i II=%i III=%i IV=%i\n",
+		before(end, sender->td_maxend + 1) 
+		    || before(seq, sender->td_maxend + 1),
+	    	after(seq, sender->td_end - receiver->td_maxwin - 1) 
+	    	    || after(end, sender->td_end - receiver->td_maxwin - 1),
+	    	before(sack, receiver->td_end + 1),
+	    	after(ack, receiver->td_end - MAXACKWINDOW(sender)));
+	
+	if (sender->loose || receiver->loose ||
+	    (before(end, sender->td_maxend + 1) &&
+	     after(seq, sender->td_end - receiver->td_maxwin - 1) &&
+	     before(sack, receiver->td_end + 1) &&
+	     after(ack, receiver->td_end - MAXACKWINDOW(sender)))) {
+	    	/*
+		 * Take into account window scaling (RFC 1323).
+		 */
+		if (!tcph->syn)
+			win <<= sender->td_scale;
+		
+		/*
+		 * Update sender data.
+		 */
+		swin = win + (sack - ack);
+		if (sender->td_maxwin < swin)
+			sender->td_maxwin = swin;
+		if (after(end, sender->td_end))
+			sender->td_end = end;
+		if (after(sack + win, receiver->td_maxend - 1)) {
+			receiver->td_maxend = sack + win;
+			if (win == 0)
+				receiver->td_maxend++;
+		}
+
+		/* 
+		 * Check retransmissions.
+		 */
+		if (*index == TCP_ACK_SET) {
+			if (state->last_dir == dir
+			    && state->last_seq == seq
+			    && state->last_end == end)
+				state->retrans++;
+			else {
+				state->last_dir = dir;
+				state->last_seq = seq;
+				state->last_end = end;
+				state->retrans = 0;
+			}
+		}
+		/*
+		 * Close the window of disabled window tracking :-)
+		 */
+		if (sender->loose)
+			sender->loose--;
+		
+		res = 1;
+	} else {
+		if (LOG_INVALID(IPPROTO_TCP))
+			nf_log_packet(PF_INET, 0, skb, NULL, NULL,
+			"ip_ct_tcp: %s ",
+			before(end, sender->td_maxend + 1) ?
+			after(seq, sender->td_end - receiver->td_maxwin - 1) ?
+			before(ack, receiver->td_end + 1) ?
+			after(ack, receiver->td_end - MAXACKWINDOW(sender)) ? "BUG"
+			: "ACK is under the lower bound (possibly overly delayed ACK)"
+			: "ACK is over the upper bound (ACKed data has never seen yet)"
+			: "SEQ is under the lower bound (retransmitted already ACKed data)"
+			: "SEQ is over the upper bound (over the window of the receiver)");
+
+		res = ip_ct_tcp_be_liberal && !tcph->rst;
+  	}
+  
+	DEBUGP("tcp_in_window: res=%i sender end=%u maxend=%u maxwin=%u "
+	       "receiver end=%u maxend=%u maxwin=%u\n",
+		res, sender->td_end, sender->td_maxend, sender->td_maxwin, 
+		receiver->td_end, receiver->td_maxend, receiver->td_maxwin);
 
-	/* Set ASSURED if we see valid ack in ESTABLISHED after SYN_RECV */
-	if (oldtcpstate == TCP_CONNTRACK_SYN_RECV
-	    && CTINFO2DIR(ctinfo) == IP_CT_DIR_ORIGINAL
-	    && tcph.ack && !tcph.syn
-	    && tcph.ack_seq == conntrack->proto.tcp.handshake_ack)
-		set_bit(IPS_ASSURED_BIT, &conntrack->status);
+	return res;
+}
+
+#ifdef CONFIG_IP_NF_NAT_NEEDED
+/* Update sender->td_end after NAT successfully mangled the packet */
+int ip_conntrack_tcp_update(struct sk_buff *skb,
+			    struct ip_conntrack *conntrack, 
+			    int dir)
+{
+	struct iphdr *iph = skb->nh.iph;
+	struct tcphdr *tcph = (void *)skb->nh.iph + skb->nh.iph->ihl*4;
+	__u32 end;
+#ifdef DEBUGP_VARS
+	struct ip_ct_tcp_state *sender = &conntrack->proto.tcp.seen[dir];
+	struct ip_ct_tcp_state *receiver = &conntrack->proto.tcp.seen[!dir];
+#endif
 
-out:	WRITE_UNLOCK(&tcp_lock);
-	ip_ct_refresh(conntrack, *tcp_timeouts[newconntrack]);
+	end = segment_seq_plus_len(ntohl(tcph->seq), skb->len, iph, tcph);
+	
+	WRITE_LOCK(&tcp_lock);
+	/*
+	 * We have to worry for the ack in the reply packet only...
+	 */
+	if (after(end, conntrack->proto.tcp.seen[dir].td_end))
+		conntrack->proto.tcp.seen[dir].td_end = end;
+	conntrack->proto.tcp.last_end = end;
+	WRITE_UNLOCK(&tcp_lock);
+	DEBUGP("tcp_update: sender end=%u maxend=%u maxwin=%u scale=%i "
+	       "receiver end=%u maxend=%u maxwin=%u scale=%i\n",
+		sender->td_end, sender->td_maxend, sender->td_maxwin,
+		sender->td_scale, 
+		receiver->td_end, receiver->td_maxend, receiver->td_maxwin,
+		receiver->td_scale);
+		
+	return 1;
+}
+ 
+EXPORT_SYMBOL(ip_conntrack_tcp_update);
+#endif
+
+#define	TH_FIN	0x01
+#define	TH_SYN	0x02
+#define	TH_RST	0x04
+#define	TH_PUSH	0x08
+#define	TH_ACK	0x10
+#define	TH_URG	0x20
+#define	TH_ECE	0x40
+#define	TH_CWR	0x80
+
+/* table of valid flag combinations - ECE and CWR are always valid */
+static u8 tcp_valid_flags[(TH_FIN|TH_SYN|TH_RST|TH_PUSH|TH_ACK|TH_URG) + 1] =
+{
+	[TH_SYN]			= 1,
+	[TH_SYN|TH_ACK]			= 1,
+	[TH_RST]			= 1,
+	[TH_RST|TH_ACK]			= 1,
+	[TH_RST|TH_ACK|TH_PUSH]		= 1,
+	[TH_FIN|TH_ACK]			= 1,
+	[TH_ACK]			= 1,
+	[TH_ACK|TH_PUSH]		= 1,
+	[TH_ACK|TH_URG]			= 1,
+	[TH_ACK|TH_URG|TH_PUSH]		= 1,
+	[TH_FIN|TH_ACK|TH_PUSH]		= 1,
+	[TH_FIN|TH_ACK|TH_URG]		= 1,
+	[TH_FIN|TH_ACK|TH_URG|TH_PUSH]	= 1,
+};
+
+/* Protect conntrack agaist broken packets. Code taken from ipt_unclean.c.  */
+static int tcp_error(struct sk_buff *skb,
+		     enum ip_conntrack_info *ctinfo,
+		     unsigned int hooknum)
+{
+	struct iphdr *iph = skb->nh.iph;
+	struct tcphdr _tcph, *th;
+	unsigned int tcplen = skb->len - iph->ihl * 4;
+	u_int8_t tcpflags;
+
+	/* Smaller that minimal TCP header? */
+	th = skb_header_pointer(skb, iph->ihl * 4,
+				sizeof(_tcph), &_tcph);
+	if (th == NULL) {
+		if (LOG_INVALID(IPPROTO_TCP))
+			nf_log_packet(PF_INET, 0, skb, NULL, NULL, 
+				"ip_ct_tcp: short packet ");
+		return -NF_ACCEPT;
+  	}
+  
+	/* Not whole TCP header or malformed packet */
+	if (th->doff*4 < sizeof(struct tcphdr) || tcplen < th->doff*4) {
+		if (LOG_INVALID(IPPROTO_TCP))
+			nf_log_packet(PF_INET, 0, skb, NULL, NULL, 
+				"ip_ct_tcp: truncated/malformed packet ");
+		return -NF_ACCEPT;
+	}
+  
+	/* Checksum invalid? Ignore.
+	 * We skip checking packets on the outgoing path
+	 * because the semantic of CHECKSUM_HW is different there 
+	 * and moreover root might send raw packets.
+	 */
+	/* FIXME: Source route IP option packets --RR */
+	if (hooknum == NF_IP_PRE_ROUTING
+	    && csum_tcpudp_magic(iph->saddr, iph->daddr, tcplen, IPPROTO_TCP,
+			         skb->ip_summed == CHECKSUM_HW ? skb->csum
+			      	 : skb_checksum(skb, iph->ihl*4, tcplen, 0))) {
+		if (LOG_INVALID(IPPROTO_TCP))
+			nf_log_packet(PF_INET, 0, skb, NULL, NULL, 
+				  "ip_ct_tcp: bad TCP checksum ");
+		return -NF_ACCEPT;
+	}
+
+	/* Check TCP flags. */
+	tcpflags = (((u_int8_t *)th)[13] & ~(TH_ECE|TH_CWR));
+	if (!tcp_valid_flags[tcpflags]) {
+		if (LOG_INVALID(IPPROTO_TCP))
+			nf_log_packet(PF_INET, 0, skb, NULL, NULL, 
+				  "ip_ct_tcp: invalid TCP flag combination ");
+		return -NF_ACCEPT;
+	}
 
 	return NF_ACCEPT;
 }
 
-/* Called when a new connection for this protocol found. */
-static int tcp_new(struct ip_conntrack *conntrack, const struct sk_buff *skb)
+/* Returns verdict for packet, or -1 for invalid. */
+static int tcp_packet(struct ip_conntrack *conntrack,
+		      const struct sk_buff *skb,
+		      enum ip_conntrack_info ctinfo)
 {
-	enum tcp_conntrack newconntrack;
-	struct tcphdr tcph;
+	enum tcp_conntrack new_state, old_state;
+	enum ip_conntrack_dir dir;
+	struct iphdr *iph = skb->nh.iph;
+	struct tcphdr *th, _tcph;
+	unsigned long timeout;
+	unsigned int index;
+	
+	th = skb_header_pointer(skb, iph->ihl * 4,
+				sizeof(_tcph), &_tcph);
+	BUG_ON(th == NULL);
+	
+	WRITE_LOCK(&tcp_lock);
+	old_state = conntrack->proto.tcp.state;
+	dir = CTINFO2DIR(ctinfo);
+	index = get_conntrack_index(th);
+	new_state = tcp_conntracks[dir][index][old_state];
+
+	switch (new_state) {
+	case TCP_CONNTRACK_IGNORE:
+		/* Either SYN in ORIGINAL, or SYN/ACK in REPLY direction. */
+		if (index == TCP_SYNACK_SET
+		    && conntrack->proto.tcp.last_index == TCP_SYN_SET
+		    && conntrack->proto.tcp.last_dir != dir
+		    && after(ntohl(th->ack_seq),
+		    	     conntrack->proto.tcp.last_seq)) {
+			/* This SYN/ACK acknowledges a SYN that we earlier 
+			 * ignored as invalid. This means that the client and
+			 * the server are both in sync, while the firewall is
+			 * not. We kill this session and block the SYN/ACK so
+			 * that the client cannot but retransmit its SYN and 
+			 * thus initiate a clean new session.
+			 */
+		    	WRITE_UNLOCK(&tcp_lock);
+			if (LOG_INVALID(IPPROTO_TCP))
+				nf_log_packet(PF_INET, 0, skb, NULL, NULL, 
+					  "ip_ct_tcp: killing out of sync session ");
+		    	if (del_timer(&conntrack->timeout))
+		    		conntrack->timeout.function((unsigned long)
+		    					    conntrack);
+		    	return -NF_DROP;
+		}
+		conntrack->proto.tcp.last_index = index;
+		conntrack->proto.tcp.last_dir = dir;
+		conntrack->proto.tcp.last_seq = ntohl(th->seq);
+		
+		WRITE_UNLOCK(&tcp_lock);
+		if (LOG_INVALID(IPPROTO_TCP))
+			nf_log_packet(PF_INET, 0, skb, NULL, NULL, 
+				  "ip_ct_tcp: invalid SYN (ignored) ");
+		return NF_ACCEPT;
+	case TCP_CONNTRACK_MAX:
+		/* Invalid packet */
+		DEBUGP("ip_ct_tcp: Invalid dir=%i index=%u ostate=%u\n",
+		       dir, get_conntrack_index(th),
+		       old_state);
+		WRITE_UNLOCK(&tcp_lock);
+		if (LOG_INVALID(IPPROTO_TCP))
+			nf_log_packet(PF_INET, 0, skb, NULL, NULL, 
+				  "ip_ct_tcp: invalid state ");
+		return -NF_ACCEPT;
+	case TCP_CONNTRACK_SYN_SENT:
+		if (old_state >= TCP_CONNTRACK_TIME_WAIT) {	
+		    	/* Attempt to reopen a closed connection.
+		    	* Delete this connection and look up again. */
+		    	WRITE_UNLOCK(&tcp_lock);
+		    	if (del_timer(&conntrack->timeout))
+		    		conntrack->timeout.function((unsigned long)
+		    					    conntrack);
+		    	return -NF_REPEAT;
+		}
+		break;
+	case TCP_CONNTRACK_CLOSE:
+		if (index == TCP_RST_SET
+		    && test_bit(IPS_SEEN_REPLY_BIT, &conntrack->status)
+		    && conntrack->proto.tcp.last_index <= TCP_SYNACK_SET
+		    && after(ntohl(th->ack_seq),
+		    	     conntrack->proto.tcp.last_seq)) {
+			/* Ignore RST closing down invalid SYN 
+			   we had let trough. */ 
+		    	WRITE_UNLOCK(&tcp_lock);
+			if (LOG_INVALID(IPPROTO_TCP))
+				nf_log_packet(PF_INET, 0, skb, NULL, NULL, 
+					  "ip_ct_tcp: invalid RST (ignored) ");
+			return NF_ACCEPT;
+		}
+		/* Just fall trough */
+	default:
+		/* Keep compilers happy. */
+		break;
+	}
+
+	if (!tcp_in_window(&conntrack->proto.tcp, dir, &index, 
+			   skb, iph, th)) {
+		WRITE_UNLOCK(&tcp_lock);
+		return -NF_ACCEPT;
+	}
+	/* From now on we have got in-window packets */
+	
+	/* If FIN was trimmed off, we don't change state. */
+	conntrack->proto.tcp.last_index = index;
+	new_state = tcp_conntracks[dir][index][old_state];
+
+	DEBUGP("tcp_conntracks: src=%u.%u.%u.%u:%hu dst=%u.%u.%u.%u:%hu "
+	       "syn=%i ack=%i fin=%i rst=%i old=%i new=%i\n",
+		NIPQUAD(iph->saddr), ntohs(th->source),
+		NIPQUAD(iph->daddr), ntohs(th->dest),
+		(th->syn ? 1 : 0), (th->ack ? 1 : 0),
+		(th->fin ? 1 : 0), (th->rst ? 1 : 0),
+		old_state, new_state);
+
+	conntrack->proto.tcp.state = new_state;
+	timeout = conntrack->proto.tcp.retrans >= ip_ct_tcp_max_retrans
+		  && *tcp_timeouts[new_state] > ip_ct_tcp_timeout_max_retrans
+		  ? ip_ct_tcp_timeout_max_retrans : *tcp_timeouts[new_state];
+	WRITE_UNLOCK(&tcp_lock);
+
+	if (!test_bit(IPS_SEEN_REPLY_BIT, &conntrack->status)) {
+		/* If only reply is a RST, we can consider ourselves not to
+		   have an established connection: this is a fairly common
+		   problem case, so we can delete the conntrack
+		   immediately.  --RR */
+		if (th->rst) {
+			if (del_timer(&conntrack->timeout))
+				conntrack->timeout.function((unsigned long)
+							    conntrack);
+			return NF_ACCEPT;
+		}
+	} else if (!test_bit(IPS_ASSURED_BIT, &conntrack->status)
+		   && (old_state == TCP_CONNTRACK_SYN_RECV
+		       || old_state == TCP_CONNTRACK_ESTABLISHED)
+		   && new_state == TCP_CONNTRACK_ESTABLISHED) {
+		/* Set ASSURED if we see see valid ack in ESTABLISHED 
+		   after SYN_RECV or a valid answer for a picked up 
+		   connection. */
+			set_bit(IPS_ASSURED_BIT, &conntrack->status);
+	}
+	ip_ct_refresh_acct(conntrack, ctinfo, skb, timeout);
 
-	if (skb_copy_bits(skb, skb->nh.iph->ihl * 4, &tcph, sizeof(tcph)) != 0)
-		return -1;
+	return NF_ACCEPT;
+}
+ 
+  /* Called when a new connection for this protocol found. */
+static int tcp_new(struct ip_conntrack *conntrack,
+		   const struct sk_buff *skb)
+{
+	enum tcp_conntrack new_state;
+	struct iphdr *iph = skb->nh.iph;
+	struct tcphdr *th, _tcph;
+#ifdef DEBUGP_VARS
+	struct ip_ct_tcp_state *sender = &conntrack->proto.tcp.seen[0];
+	struct ip_ct_tcp_state *receiver = &conntrack->proto.tcp.seen[1];
+#endif
 
+	th = skb_header_pointer(skb, iph->ihl * 4,
+				sizeof(_tcph), &_tcph);
+	BUG_ON(th == NULL);
+	
 	/* Don't need lock here: this conntrack not in circulation yet */
-	newconntrack
-		= tcp_conntracks[0][get_conntrack_index(&tcph)]
+	new_state
+		= tcp_conntracks[0][get_conntrack_index(th)]
 		[TCP_CONNTRACK_NONE];
 
 	/* Invalid: delete conntrack */
-	if (newconntrack == TCP_CONNTRACK_MAX) {
-		DEBUGP("ip_conntrack_tcp: invalid new deleting.\n");
+	if (new_state >= TCP_CONNTRACK_MAX) {
+		DEBUGP("ip_ct_tcp: invalid new deleting.\n");
 		return 0;
 	}
 
-	conntrack->proto.tcp.state = newconntrack;
+	if (new_state == TCP_CONNTRACK_SYN_SENT) {
+		/* SYN packet */
+		conntrack->proto.tcp.seen[0].td_end =
+			segment_seq_plus_len(ntohl(th->seq), skb->len,
+					     iph, th);
+		conntrack->proto.tcp.seen[0].td_maxwin = ntohs(th->window);
+		if (conntrack->proto.tcp.seen[0].td_maxwin == 0)
+			conntrack->proto.tcp.seen[0].td_maxwin = 1;
+		conntrack->proto.tcp.seen[0].td_maxend =
+			conntrack->proto.tcp.seen[0].td_end;
+
+		tcp_options(skb, iph, th, &conntrack->proto.tcp.seen[0]);
+		conntrack->proto.tcp.seen[1].flags = 0;
+		conntrack->proto.tcp.seen[0].loose = 
+		conntrack->proto.tcp.seen[1].loose = 0;
+	} else if (ip_ct_tcp_loose == 0) {
+		/* Don't try to pick up connections. */
+		return 0;
+	} else {
+		/*
+		 * We are in the middle of a connection,
+		 * its history is lost for us.
+		 * Let's try to use the data from the packet.
+		 */
+		conntrack->proto.tcp.seen[0].td_end =
+			segment_seq_plus_len(ntohl(th->seq), skb->len,
+					     iph, th);
+		conntrack->proto.tcp.seen[0].td_maxwin = ntohs(th->window);
+		if (conntrack->proto.tcp.seen[0].td_maxwin == 0)
+			conntrack->proto.tcp.seen[0].td_maxwin = 1;
+		conntrack->proto.tcp.seen[0].td_maxend =
+			conntrack->proto.tcp.seen[0].td_end + 
+			conntrack->proto.tcp.seen[0].td_maxwin;
+		conntrack->proto.tcp.seen[0].td_scale = 0;
+
+		/* We assume SACK. Should we assume window scaling too? */
+		conntrack->proto.tcp.seen[0].flags =
+		conntrack->proto.tcp.seen[1].flags = IP_CT_TCP_FLAG_SACK_PERM;
+		conntrack->proto.tcp.seen[0].loose = 
+		conntrack->proto.tcp.seen[1].loose = ip_ct_tcp_loose;
+	}
+    
+	conntrack->proto.tcp.seen[1].td_end = 0;
+	conntrack->proto.tcp.seen[1].td_maxend = 0;
+	conntrack->proto.tcp.seen[1].td_maxwin = 1;
+	conntrack->proto.tcp.seen[1].td_scale = 0;      
+
+	/* tcp_packet will set them */
+	conntrack->proto.tcp.state = TCP_CONNTRACK_NONE;
+	conntrack->proto.tcp.last_index = TCP_NONE_SET;
+	 
+	DEBUGP("tcp_new: sender end=%u maxend=%u maxwin=%u scale=%i "
+	       "receiver end=%u maxend=%u maxwin=%u scale=%i\n",
+		sender->td_end, sender->td_maxend, sender->td_maxwin,
+		sender->td_scale, 
+		receiver->td_end, receiver->td_maxend, receiver->td_maxwin,
+		receiver->td_scale);
 	return 1;
 }
-
+  
 static int tcp_exp_matches_pkt(struct ip_conntrack_expect *exp,
 			       const struct sk_buff *skb)
 {
 	const struct iphdr *iph = skb->nh.iph;
-	struct tcphdr tcph;
+	struct tcphdr *th, _tcph;
 	unsigned int datalen;
 
-	if (skb_copy_bits(skb, skb->nh.iph->ihl * 4, &tcph, sizeof(tcph)) != 0)
+	th = skb_header_pointer(skb, iph->ihl * 4,
+				sizeof(_tcph), &_tcph);
+	if (th == NULL)
 		return 0;
-	datalen = skb->len - iph->ihl*4 - tcph.doff*4;
+	datalen = skb->len - iph->ihl*4 - th->doff*4;
 
-	return between(exp->seq, ntohl(tcph.seq), ntohl(tcph.seq) + datalen);
+	return between(exp->seq, ntohl(th->seq), ntohl(th->seq) + datalen);
 }
 
-struct ip_conntrack_protocol ip_conntrack_protocol_tcp
-= { { NULL, NULL }, IPPROTO_TCP, "tcp",
-    tcp_pkt_to_tuple, tcp_invert_tuple, tcp_print_tuple, tcp_print_conntrack,
-    tcp_packet, tcp_new, NULL, tcp_exp_matches_pkt, NULL };
+struct ip_conntrack_protocol ip_conntrack_protocol_tcp =
+{
+	.proto 			= IPPROTO_TCP,
+	.name 			= "tcp",
+	.pkt_to_tuple 		= tcp_pkt_to_tuple,
+	.invert_tuple 		= tcp_invert_tuple,
+	.print_tuple 		= tcp_print_tuple,
+	.print_conntrack 	= tcp_print_conntrack,
+	.packet 		= tcp_packet,
+	.new 			= tcp_new,
+	.exp_matches_pkt	= tcp_exp_matches_pkt,
+	.error			= tcp_error,
+};
diff -Nru a/net/ipv4/netfilter/ip_conntrack_proto_udp.c b/net/ipv4/netfilter/ip_conntrack_proto_udp.c
--- a/net/ipv4/netfilter/ip_conntrack_proto_udp.c	2004-10-18 14:55:46 -07:00
+++ b/net/ipv4/netfilter/ip_conntrack_proto_udp.c	2004-10-18 14:55:46 -07:00
@@ -12,6 +12,10 @@
 #include <linux/netfilter.h>
 #include <linux/in.h>
 #include <linux/udp.h>
+#include <linux/seq_file.h>
+#include <net/checksum.h>
+#include <linux/netfilter.h>
+#include <linux/netfilter_ipv4.h>
 #include <linux/netfilter_ipv4/ip_conntrack_protocol.h>
 
 unsigned long ip_ct_udp_timeout = 30*HZ;
@@ -21,14 +25,15 @@
 			     unsigned int dataoff,
 			     struct ip_conntrack_tuple *tuple)
 {
-	struct udphdr hdr;
+	struct udphdr _hdr, *hp;
 
 	/* Actually only need first 8 bytes. */
-	if (skb_copy_bits(skb, dataoff, &hdr, 8) != 0)
+	hp = skb_header_pointer(skb, dataoff, sizeof(_hdr), &_hdr);
+	if (hp == NULL)
 		return 0;
 
-	tuple->src.u.udp.port = hdr.source;
-	tuple->dst.u.udp.port = hdr.dest;
+	tuple->src.u.udp.port = hp->source;
+	tuple->dst.u.udp.port = hp->dest;
 
 	return 1;
 }
@@ -42,17 +47,17 @@
 }
 
 /* Print out the per-protocol part of the tuple. */
-static unsigned int udp_print_tuple(char *buffer,
-				    const struct ip_conntrack_tuple *tuple)
+static int udp_print_tuple(struct seq_file *s,
+			   const struct ip_conntrack_tuple *tuple)
 {
-	return sprintf(buffer, "sport=%hu dport=%hu ",
-		       ntohs(tuple->src.u.udp.port),
-		       ntohs(tuple->dst.u.udp.port));
+	return seq_printf(s, "sport=%hu dport=%hu ",
+			  ntohs(tuple->src.u.udp.port),
+			  ntohs(tuple->dst.u.udp.port));
 }
 
 /* Print out the private part of the conntrack. */
-static unsigned int udp_print_conntrack(char *buffer,
-					const struct ip_conntrack *conntrack)
+static int udp_print_conntrack(struct seq_file *s,
+			       const struct ip_conntrack *conntrack)
 {
 	return 0;
 }
@@ -60,16 +65,17 @@
 /* Returns verdict for packet, and may modify conntracktype */
 static int udp_packet(struct ip_conntrack *conntrack,
 		      const struct sk_buff *skb,
-		      enum ip_conntrack_info conntrackinfo)
+		      enum ip_conntrack_info ctinfo)
 {
 	/* If we've seen traffic both ways, this is some kind of UDP
 	   stream.  Extend timeout. */
 	if (test_bit(IPS_SEEN_REPLY_BIT, &conntrack->status)) {
-		ip_ct_refresh(conntrack, ip_ct_udp_timeout_stream);
+		ip_ct_refresh_acct(conntrack, ctinfo, skb, 
+				   ip_ct_udp_timeout_stream);
 		/* Also, more likely to be important, and not a probe */
 		set_bit(IPS_ASSURED_BIT, &conntrack->status);
 	} else
-		ip_ct_refresh(conntrack, ip_ct_udp_timeout);
+		ip_ct_refresh_acct(conntrack, ctinfo, skb, ip_ct_udp_timeout);
 
 	return NF_ACCEPT;
 }
@@ -80,7 +86,61 @@
 	return 1;
 }
 
-struct ip_conntrack_protocol ip_conntrack_protocol_udp
-= { { NULL, NULL }, IPPROTO_UDP, "udp",
-    udp_pkt_to_tuple, udp_invert_tuple, udp_print_tuple, udp_print_conntrack,
-    udp_packet, udp_new, NULL, NULL, NULL };
+static int udp_error(struct sk_buff *skb, enum ip_conntrack_info *ctinfo,
+		     unsigned int hooknum)
+{
+	struct iphdr *iph = skb->nh.iph;
+	unsigned int udplen = skb->len - iph->ihl * 4;
+	struct udphdr _hdr, *hdr;
+
+	/* Header is too small? */
+	hdr = skb_header_pointer(skb, iph->ihl*4, sizeof(_hdr), &_hdr);
+	if (hdr == NULL) {
+		if (LOG_INVALID(IPPROTO_UDP))
+			nf_log_packet(PF_INET, 0, skb, NULL, NULL, 
+				  "ip_ct_udp: short packet ");
+		return -NF_ACCEPT;
+	}
+	
+	/* Truncated/malformed packets */
+	if (ntohs(hdr->len) > udplen || ntohs(hdr->len) < sizeof(*hdr)) {
+		if (LOG_INVALID(IPPROTO_UDP))
+			nf_log_packet(PF_INET, 0, skb, NULL, NULL, 
+				  "ip_ct_udp: truncated/malformed packet ");
+		return -NF_ACCEPT;
+	}
+	
+	/* Packet with no checksum */
+	if (!hdr->check)
+		return NF_ACCEPT;
+
+	/* Checksum invalid? Ignore.
+	 * We skip checking packets on the outgoing path
+	 * because the semantic of CHECKSUM_HW is different there 
+	 * and moreover root might send raw packets.
+	 * FIXME: Source route IP option packets --RR */
+	if (hooknum == NF_IP_PRE_ROUTING
+	    && csum_tcpudp_magic(iph->saddr, iph->daddr, udplen, IPPROTO_UDP,
+			         skb->ip_summed == CHECKSUM_HW ? skb->csum
+			      	 : skb_checksum(skb, iph->ihl*4, udplen, 0))) {
+		if (LOG_INVALID(IPPROTO_UDP))
+			nf_log_packet(PF_INET, 0, skb, NULL, NULL, 
+				  "ip_ct_udp: bad UDP checksum ");
+		return -NF_ACCEPT;
+	}
+	
+	return NF_ACCEPT;
+}
+
+struct ip_conntrack_protocol ip_conntrack_protocol_udp =
+{
+	.proto 			= IPPROTO_UDP,
+	.name			= "udp",
+	.pkt_to_tuple		= udp_pkt_to_tuple,
+	.invert_tuple		= udp_invert_tuple,
+	.print_tuple		= udp_print_tuple,
+	.print_conntrack	= udp_print_conntrack,
+	.packet			= udp_packet,
+	.new			= udp_new,
+	.error			= udp_error,
+};
diff -Nru a/net/ipv4/netfilter/ip_conntrack_standalone.c b/net/ipv4/netfilter/ip_conntrack_standalone.c
--- a/net/ipv4/netfilter/ip_conntrack_standalone.c	2004-10-18 14:56:29 -07:00
+++ b/net/ipv4/netfilter/ip_conntrack_standalone.c	2004-10-18 14:56:29 -07:00
@@ -20,6 +20,8 @@
 #include <linux/module.h>
 #include <linux/skbuff.h>
 #include <linux/proc_fs.h>
+#include <linux/seq_file.h>
+#include <linux/percpu.h>
 #ifdef CONFIG_SYSCTL
 #include <linux/sysctl.h>
 #endif
@@ -43,148 +45,314 @@
 
 MODULE_LICENSE("GPL");
 
+extern atomic_t ip_conntrack_count;
+DECLARE_PER_CPU(struct ip_conntrack_stat, ip_conntrack_stat);
+
 static int kill_proto(const struct ip_conntrack *i, void *data)
 {
 	return (i->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.protonum == 
 			*((u_int8_t *) data));
 }
 
-static unsigned int
-print_tuple(char *buffer, const struct ip_conntrack_tuple *tuple,
+#ifdef CONFIG_PROC_FS
+static int
+print_tuple(struct seq_file *s, const struct ip_conntrack_tuple *tuple,
 	    struct ip_conntrack_protocol *proto)
 {
-	int len;
-
-	len = sprintf(buffer, "src=%u.%u.%u.%u dst=%u.%u.%u.%u ",
-		      NIPQUAD(tuple->src.ip), NIPQUAD(tuple->dst.ip));
-
-	len += proto->print_tuple(buffer + len, tuple);
-
-	return len;
+	seq_printf(s, "src=%u.%u.%u.%u dst=%u.%u.%u.%u ",
+		   NIPQUAD(tuple->src.ip), NIPQUAD(tuple->dst.ip));
+	return proto->print_tuple(s, tuple);
 }
 
-/* FIXME: Don't print source proto part. --RR */
+#ifdef CONFIG_IP_NF_CT_ACCT
 static unsigned int
-print_expect(char *buffer, const struct ip_conntrack_expect *expect)
+seq_print_counters(struct seq_file *s, struct ip_conntrack_counter *counter)
 {
-	unsigned int len;
+	return seq_printf(s, "packets=%llu bytes=%llu ",
+			  (unsigned long long)counter->packets,
+			  (unsigned long long)counter->bytes);
+}
+#else
+#define seq_print_counters(x, y)	0
+#endif
 
-	if (expect->expectant->helper->timeout)
-		len = sprintf(buffer, "EXPECTING: %lu ",
-			      timer_pending(&expect->timeout)
-			      ? (expect->timeout.expires - jiffies)/HZ : 0);
-	else
-		len = sprintf(buffer, "EXPECTING: - ");
-	len += sprintf(buffer + len, "use=%u proto=%u ",
-		      atomic_read(&expect->use), expect->tuple.dst.protonum);
-	len += print_tuple(buffer + len, &expect->tuple,
-			   __ip_ct_find_proto(expect->tuple.dst.protonum));
-	len += sprintf(buffer + len, "\n");
-	return len;
+static void *ct_seq_start(struct seq_file *s, loff_t *pos)
+{
+	if (*pos >= ip_conntrack_htable_size)
+		return NULL;
+	return &ip_conntrack_hash[*pos];
+}
+  
+static void ct_seq_stop(struct seq_file *s, void *v)
+{
 }
 
-static unsigned int
-print_conntrack(char *buffer, struct ip_conntrack *conntrack)
+static void *ct_seq_next(struct seq_file *s, void *v, loff_t *pos)
 {
-	unsigned int len;
-	struct ip_conntrack_protocol *proto
-		= __ip_ct_find_proto(conntrack->tuplehash[IP_CT_DIR_ORIGINAL]
+	(*pos)++;
+	if (*pos >= ip_conntrack_htable_size)
+		return NULL;
+	return &ip_conntrack_hash[*pos];
+}
+  
+/* return 0 on success, 1 in case of error */
+static int ct_seq_real_show(const struct ip_conntrack_tuple_hash *hash,
+			    struct seq_file *s)
+{
+	struct ip_conntrack *conntrack = hash->ctrack;
+	struct ip_conntrack_protocol *proto;
+
+	MUST_BE_READ_LOCKED(&ip_conntrack_lock);
+
+	IP_NF_ASSERT(conntrack);
+
+	/* we only want to print DIR_ORIGINAL */
+	if (DIRECTION(hash))
+		return 0;
+
+	proto = ip_ct_find_proto(conntrack->tuplehash[IP_CT_DIR_ORIGINAL]
 			       .tuple.dst.protonum);
+	IP_NF_ASSERT(proto);
 
-	len = sprintf(buffer, "%-8s %u %lu ",
+	if (seq_printf(s, "%-8s %u %lu ",
 		      proto->name,
-		      conntrack->tuplehash[IP_CT_DIR_ORIGINAL]
-		      .tuple.dst.protonum,
+		      conntrack->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.protonum,
 		      timer_pending(&conntrack->timeout)
-		      ? (conntrack->timeout.expires - jiffies)/HZ : 0);
+		      ? (conntrack->timeout.expires - jiffies)/HZ : 0) != 0)
+		return 1;
+
+	if (proto->print_conntrack(s, conntrack))
+		return 1;
+  
+	if (print_tuple(s, &conntrack->tuplehash[IP_CT_DIR_ORIGINAL].tuple,
+			proto))
+		return 1;
+
+ 	if (seq_print_counters(s, &conntrack->counters[IP_CT_DIR_ORIGINAL]))
+		return 1;
 
-	len += proto->print_conntrack(buffer + len, conntrack);
-	len += print_tuple(buffer + len,
-			   &conntrack->tuplehash[IP_CT_DIR_ORIGINAL].tuple,
-			   proto);
 	if (!(test_bit(IPS_SEEN_REPLY_BIT, &conntrack->status)))
-		len += sprintf(buffer + len, "[UNREPLIED] ");
-	len += print_tuple(buffer + len,
-			   &conntrack->tuplehash[IP_CT_DIR_REPLY].tuple,
-			   proto);
-	if (test_bit(IPS_ASSURED_BIT, &conntrack->status))
-		len += sprintf(buffer + len, "[ASSURED] ");
-	len += sprintf(buffer + len, "use=%u ",
-		       atomic_read(&conntrack->ct_general.use));
-	len += sprintf(buffer + len, "\n");
-
-	return len;
-}
-
-/* Returns true when finished. */
-static inline int
-conntrack_iterate(const struct ip_conntrack_tuple_hash *hash,
-		  char *buffer, off_t offset, off_t *upto,
-		  unsigned int *len, unsigned int maxlen)
-{
-	unsigned int newlen;
-	IP_NF_ASSERT(hash->ctrack);
+		if (seq_printf(s, "[UNREPLIED] "))
+			return 1;
 
-	MUST_BE_READ_LOCKED(&ip_conntrack_lock);
+	if (print_tuple(s, &conntrack->tuplehash[IP_CT_DIR_REPLY].tuple,
+			proto))
+		return 1;
 
-	/* Only count originals */
-	if (DIRECTION(hash))
-		return 0;
+ 	if (seq_print_counters(s, &conntrack->counters[IP_CT_DIR_REPLY]))
+		return 1;
 
-	if ((*upto)++ < offset)
-		return 0;
+	if (test_bit(IPS_ASSURED_BIT, &conntrack->status))
+		if (seq_printf(s, "[ASSURED] "))
+			return 1;
 
-	newlen = print_conntrack(buffer + *len, hash->ctrack);
-	if (*len + newlen > maxlen)
+	if (seq_printf(s, "use=%u\n", atomic_read(&conntrack->ct_general.use)))
 		return 1;
-	else *len += newlen;
 
 	return 0;
 }
 
-static int
-list_conntracks(char *buffer, char **start, off_t offset, int length)
+static int ct_seq_show(struct seq_file *s, void *v)
 {
-	unsigned int i;
-	unsigned int len = 0;
-	off_t upto = 0;
-	struct list_head *e;
+	struct list_head *list = v;
+	int ret = 0;
 
+	/* FIXME: Simply truncates if hash chain too long. */
 	READ_LOCK(&ip_conntrack_lock);
-	/* Traverse hash; print originals then reply. */
-	for (i = 0; i < ip_conntrack_htable_size; i++) {
-		if (LIST_FIND(&ip_conntrack_hash[i], conntrack_iterate,
-			      struct ip_conntrack_tuple_hash *,
-			      buffer, offset, &upto, &len, length))
-			goto finished;
-	}
+	if (LIST_FIND(list, ct_seq_real_show,
+		      struct ip_conntrack_tuple_hash *, s))
+		ret = -ENOSPC;
+	READ_UNLOCK(&ip_conntrack_lock);
+	return ret;
+}
+	
+static struct seq_operations ct_seq_ops = {
+	.start = ct_seq_start,
+	.next  = ct_seq_next,
+	.stop  = ct_seq_stop,
+	.show  = ct_seq_show
+};
+  
+static int ct_open(struct inode *inode, struct file *file)
+{
+	return seq_open(file, &ct_seq_ops);
+}
 
-	/* Now iterate through expecteds. */
+static struct file_operations ct_file_ops = {
+	.owner   = THIS_MODULE,
+	.open    = ct_open,
+	.read    = seq_read,
+	.llseek  = seq_lseek,
+	.release = seq_release
+};
+  
+/* expects */
+static void *exp_seq_start(struct seq_file *s, loff_t *pos)
+{
+	struct list_head *e = &ip_conntrack_expect_list;
+	loff_t i;
+
+	/* strange seq_file api calls stop even if we fail,
+	 * thus we need to grab lock since stop unlocks */
+	READ_LOCK(&ip_conntrack_lock);
 	READ_LOCK(&ip_conntrack_expect_tuple_lock);
-	list_for_each(e, &ip_conntrack_expect_list) {
-		unsigned int last_len;
-		struct ip_conntrack_expect *expect
-			= (struct ip_conntrack_expect *)e;
-		if (upto++ < offset) continue;
-
-		last_len = len;
-		len += print_expect(buffer + len, expect);
-		if (len > length) {
-			len = last_len;
-			goto finished_expects;
-		}
+
+	if (list_empty(e))
+		return NULL;
+
+	for (i = 0; i <= *pos; i++) {
+		e = e->next;
+		if (e == &ip_conntrack_expect_list)
+			return NULL;
 	}
+	return e;
+}
 
- finished_expects:
+static void *exp_seq_next(struct seq_file *s, void *v, loff_t *pos)
+{
+ 	struct list_head *e = v;
+
+	e = e->next;
+
+	if (e == &ip_conntrack_expect_list)
+		return NULL;
+
+	return e;
+}
+
+static void exp_seq_stop(struct seq_file *s, void *v)
+{
 	READ_UNLOCK(&ip_conntrack_expect_tuple_lock);
- finished:
 	READ_UNLOCK(&ip_conntrack_lock);
+}
+
+static int exp_seq_show(struct seq_file *s, void *v)
+{
+	struct ip_conntrack_expect *expect = v;
 
-	/* `start' hack - see fs/proc/generic.c line ~165 */
-	*start = (char *)((unsigned int)upto - offset);
-	return len;
+	if (expect->expectant->helper->timeout)
+		seq_printf(s, "%lu ", timer_pending(&expect->timeout)
+			   ? (expect->timeout.expires - jiffies)/HZ : 0);
+	else
+		seq_printf(s, "- ");
+
+	seq_printf(s, "use=%u proto=%u ", atomic_read(&expect->use),
+		   expect->tuple.dst.protonum);
+
+	print_tuple(s, &expect->tuple,
+		    ip_ct_find_proto(expect->tuple.dst.protonum));
+	return seq_putc(s, '\n');
 }
 
+static struct seq_operations exp_seq_ops = {
+	.start = exp_seq_start,
+	.next = exp_seq_next,
+	.stop = exp_seq_stop,
+	.show = exp_seq_show
+};
+
+static int exp_open(struct inode *inode, struct file *file)
+{
+	return seq_open(file, &exp_seq_ops);
+}
+  
+static struct file_operations exp_file_ops = {
+	.owner   = THIS_MODULE,
+	.open    = exp_open,
+	.read    = seq_read,
+	.llseek  = seq_lseek,
+	.release = seq_release
+};
+
+static void *ct_cpu_seq_start(struct seq_file *seq, loff_t *pos)
+{
+	int cpu;
+
+	if (*pos == 0)
+		return SEQ_START_TOKEN;
+
+	for (cpu = *pos-1; cpu < NR_CPUS; ++cpu) {
+		if (!cpu_possible(cpu))
+			continue;
+		*pos = cpu+1;
+		return &per_cpu(ip_conntrack_stat, cpu);
+	}
+
+	return NULL;
+}
+
+static void *ct_cpu_seq_next(struct seq_file *seq, void *v, loff_t *pos)
+{
+	int cpu;
+
+	for (cpu = *pos; cpu < NR_CPUS; ++cpu) {
+		if (!cpu_possible(cpu))
+			continue;
+		*pos = cpu+1;
+		return &per_cpu(ip_conntrack_stat, cpu);
+	}
+
+	return NULL;
+}
+
+static void ct_cpu_seq_stop(struct seq_file *seq, void *v)
+{
+}
+
+static int ct_cpu_seq_show(struct seq_file *seq, void *v)
+{
+	unsigned int nr_conntracks = atomic_read(&ip_conntrack_count);
+	struct ip_conntrack_stat *st = v;
+
+	if (v == SEQ_START_TOKEN) {
+		seq_printf(seq, "entries  searched found new invalid ignore delete delete_list insert insert_failed drop early_drop icmp_error  expect_new expect_create expect_delete\n");
+		return 0;
+	}
+
+	seq_printf(seq, "%08x  %08x %08x %08x %08x %08x %08x %08x "
+			"%08x %08x %08x %08x %08x  %08x %08x %08x \n",
+		   nr_conntracks,
+		   st->searched,
+		   st->found,
+		   st->new,
+		   st->invalid,
+		   st->ignore,
+		   st->delete,
+		   st->delete_list,
+		   st->insert,
+		   st->insert_failed,
+		   st->drop,
+		   st->early_drop,
+		   st->error,
+
+		   st->expect_new,
+		   st->expect_create,
+		   st->expect_delete
+		);
+	return 0;
+}
+
+static struct seq_operations ct_cpu_seq_ops = {
+	.start  = ct_cpu_seq_start,
+	.next   = ct_cpu_seq_next,
+	.stop   = ct_cpu_seq_stop,
+	.show   = ct_cpu_seq_show,
+};
+
+static int ct_cpu_seq_open(struct inode *inode, struct file *file)
+{
+	return seq_open(file, &ct_cpu_seq_ops);
+}
+
+static struct file_operations ct_cpu_seq_fops = {
+	.owner   = THIS_MODULE,
+	.open    = ct_cpu_seq_open,
+	.read    = seq_read,
+	.llseek  = seq_lseek,
+	.release = seq_release_private,
+};
+#endif
+
 static unsigned int ip_confirm(unsigned int hooknum,
 			       struct sk_buff **pskb,
 			       const struct net_device *in,
@@ -323,6 +491,10 @@
 extern unsigned long ip_ct_tcp_timeout_last_ack;
 extern unsigned long ip_ct_tcp_timeout_time_wait;
 extern unsigned long ip_ct_tcp_timeout_close;
+extern unsigned long ip_ct_tcp_timeout_max_retrans;
+extern int ip_ct_tcp_loose;
+extern int ip_ct_tcp_be_liberal;
+extern int ip_ct_tcp_max_retrans;
 
 /* From ip_conntrack_proto_udp.c */
 extern unsigned long ip_ct_udp_timeout;
@@ -334,6 +506,10 @@
 /* From ip_conntrack_proto_icmp.c */
 extern unsigned long ip_ct_generic_timeout;
 
+/* Log invalid packets of a given protocol */
+static int log_invalid_proto_min = 0;
+static int log_invalid_proto_max = 255;
+
 static struct ctl_table_header *ip_ct_sysctl_header;
 
 static ctl_table ip_ct_sysctl_table[] = {
@@ -346,6 +522,14 @@
 		.proc_handler	= &proc_dointvec,
 	},
 	{
+		.ctl_name	= NET_IPV4_NF_CONNTRACK_COUNT,
+		.procname	= "ip_conntrack_count",
+		.data		= &ip_conntrack_count,
+		.maxlen		= sizeof(int),
+		.mode		= 0444,
+		.proc_handler	= &proc_dointvec,
+	},
+	{
 		.ctl_name	= NET_IPV4_NF_CONNTRACK_BUCKETS,
 		.procname	= "ip_conntrack_buckets",
 		.data		= &ip_conntrack_htable_size,
@@ -449,6 +633,49 @@
 		.mode		= 0644,
 		.proc_handler	= &proc_dointvec_jiffies,
 	},
+	{
+		.ctl_name	= NET_IPV4_NF_CONNTRACK_LOG_INVALID,
+		.procname	= "ip_conntrack_log_invalid",
+		.data		= &ip_ct_log_invalid,
+		.maxlen		= sizeof(unsigned int),
+		.mode		= 0644,
+		.proc_handler	= &proc_dointvec_minmax,
+		.strategy	= &sysctl_intvec,
+		.extra1		= &log_invalid_proto_min,
+		.extra2		= &log_invalid_proto_max,
+	},
+	{
+		.ctl_name	= NET_IPV4_NF_CONNTRACK_TCP_TIMEOUT_MAX_RETRANS,
+		.procname	= "ip_conntrack_tcp_timeout_max_retrans",
+		.data		= &ip_ct_tcp_timeout_max_retrans,
+		.maxlen		= sizeof(unsigned int),
+		.mode		= 0644,
+		.proc_handler	= &proc_dointvec_jiffies,
+	},
+	{
+		.ctl_name	= NET_IPV4_NF_CONNTRACK_TCP_LOOSE,
+		.procname	= "ip_conntrack_tcp_loose",
+		.data		= &ip_ct_tcp_loose,
+		.maxlen		= sizeof(unsigned int),
+		.mode		= 0644,
+		.proc_handler	= &proc_dointvec,
+	},
+	{
+		.ctl_name	= NET_IPV4_NF_CONNTRACK_TCP_BE_LIBERAL,
+		.procname	= "ip_conntrack_tcp_be_liberal",
+		.data		= &ip_ct_tcp_be_liberal,
+		.maxlen		= sizeof(unsigned int),
+		.mode		= 0644,
+		.proc_handler	= &proc_dointvec,
+	},
+	{
+		.ctl_name	= NET_IPV4_NF_CONNTRACK_TCP_MAX_RETRANS,
+		.procname	= "ip_conntrack_tcp_max_retrans",
+		.data		= &ip_ct_tcp_max_retrans,
+		.maxlen		= sizeof(unsigned int),
+		.mode		= 0644,
+		.proc_handler	= &proc_dointvec,
+	},
 	{ .ctl_name = 0 }
 };
 
@@ -491,10 +718,15 @@
 	},
 	{ .ctl_name = 0 }
 };
-#endif
+
+EXPORT_SYMBOL(ip_ct_log_invalid);
+#endif /* CONFIG_SYSCTL */
+
 static int init_or_cleanup(int init)
 {
-	struct proc_dir_entry *proc;
+#ifdef CONFIG_PROC_FS
+	struct proc_dir_entry *proc, *proc_exp, *proc_stat;
+#endif
 	int ret = 0;
 
 	if (!init) goto cleanup;
@@ -503,14 +735,26 @@
 	if (ret < 0)
 		goto cleanup_nothing;
 
-	proc = proc_net_create("ip_conntrack", 0440, list_conntracks);
+#ifdef CONFIG_PROC_FS
+	proc = proc_net_fops_create("ip_conntrack", 0440, &ct_file_ops);
 	if (!proc) goto cleanup_init;
-	proc->owner = THIS_MODULE;
+
+	proc_exp = proc_net_fops_create("ip_conntrack_expect", 0440,
+					&exp_file_ops);
+	if (!proc_exp) goto cleanup_proc;
+
+	proc_stat = create_proc_entry("ip_conntrack", S_IRUGO, proc_net_stat);
+	if (!proc_stat)
+		goto cleanup_proc_exp;
+
+	proc_stat->proc_fops = &ct_cpu_seq_fops;
+	proc_stat->owner = THIS_MODULE;
+#endif
 
 	ret = nf_register_hook(&ip_conntrack_defrag_ops);
 	if (ret < 0) {
 		printk("ip_conntrack: can't register pre-routing defrag hook.\n");
-		goto cleanup_proc;
+		goto cleanup_proc_stat;
 	}
 	ret = nf_register_hook(&ip_conntrack_defrag_local_out_ops);
 	if (ret < 0) {
@@ -561,10 +805,22 @@
  cleanup_defraglocalops:
 	nf_unregister_hook(&ip_conntrack_defrag_local_out_ops);
  cleanup_defragops:
+	/* Frag queues may hold fragments with skb->dst == NULL */
+	ip_ct_no_defrag = 1;
+	synchronize_net();
+	local_bh_disable();
+	ipfrag_flush();
+	local_bh_enable();
 	nf_unregister_hook(&ip_conntrack_defrag_ops);
+ cleanup_proc_stat:
+#ifdef CONFIG_PROC_FS
+	proc_net_remove("ip_conntrack_stat");
+cleanup_proc_exp:
+	proc_net_remove("ip_conntrack_exp");
  cleanup_proc:
 	proc_net_remove("ip_conntrack");
  cleanup_init:
+#endif /* CONFIG_PROC_FS */
 	ip_conntrack_cleanup();
  cleanup_nothing:
 	return ret;
@@ -575,19 +831,13 @@
 int ip_conntrack_protocol_register(struct ip_conntrack_protocol *proto)
 {
 	int ret = 0;
-	struct list_head *i;
 
 	WRITE_LOCK(&ip_conntrack_lock);
-	list_for_each(i, &protocol_list) {
-		if (((struct ip_conntrack_protocol *)i)->proto
-		    == proto->proto) {
-			ret = -EBUSY;
-			goto out;
-		}
+	if (ip_ct_protos[proto->proto] != &ip_conntrack_generic_protocol) {
+		ret = -EBUSY;
+		goto out;
 	}
-
-	list_prepend(&protocol_list, proto);
-
+	ip_ct_protos[proto->proto] = proto;
  out:
 	WRITE_UNLOCK(&ip_conntrack_lock);
 	return ret;
@@ -596,10 +846,7 @@
 void ip_conntrack_protocol_unregister(struct ip_conntrack_protocol *proto)
 {
 	WRITE_LOCK(&ip_conntrack_lock);
-
-	/* ip_ct_find_proto() returns proto_generic in case there is no protocol 
-	 * helper. So this should be enough - HW */
-	LIST_DELETE(&protocol_list, proto);
+	ip_ct_protos[proto->proto] = &ip_conntrack_generic_protocol;
 	WRITE_UNLOCK(&ip_conntrack_lock);
 	
 	/* Somebody could be still looking at the proto in bh. */
@@ -633,14 +880,13 @@
 EXPORT_SYMBOL(invert_tuplepr);
 EXPORT_SYMBOL(ip_conntrack_alter_reply);
 EXPORT_SYMBOL(ip_conntrack_destroyed);
-EXPORT_SYMBOL(ip_conntrack_get);
 EXPORT_SYMBOL(need_ip_conntrack);
 EXPORT_SYMBOL(ip_conntrack_helper_register);
 EXPORT_SYMBOL(ip_conntrack_helper_unregister);
 EXPORT_SYMBOL(ip_ct_selective_cleanup);
-EXPORT_SYMBOL(ip_ct_refresh);
+EXPORT_SYMBOL(ip_ct_refresh_acct);
+EXPORT_SYMBOL(ip_ct_protos);
 EXPORT_SYMBOL(ip_ct_find_proto);
-EXPORT_SYMBOL(__ip_ct_find_proto);
 EXPORT_SYMBOL(ip_ct_find_helper);
 EXPORT_SYMBOL(ip_conntrack_expect_alloc);
 EXPORT_SYMBOL(ip_conntrack_expect_related);
diff -Nru a/net/ipv4/netfilter/ip_conntrack_tftp.c b/net/ipv4/netfilter/ip_conntrack_tftp.c
--- a/net/ipv4/netfilter/ip_conntrack_tftp.c	2004-10-18 14:56:28 -07:00
+++ b/net/ipv4/netfilter/ip_conntrack_tftp.c	2004-10-18 14:56:28 -07:00
@@ -19,6 +19,7 @@
 #include <linux/netfilter_ipv4/ip_tables.h>
 #include <linux/netfilter_ipv4/ip_conntrack_helper.h>
 #include <linux/netfilter_ipv4/ip_conntrack_tftp.h>
+#include <linux/moduleparam.h>
 
 MODULE_AUTHOR("Magnus Boden <mb@ozaba.mine.nu>");
 MODULE_DESCRIPTION("tftp connection tracking helper");
@@ -27,7 +28,7 @@
 #define MAX_PORTS 8
 static int ports[MAX_PORTS];
 static int ports_c;
-MODULE_PARM(ports, "1-" __MODULE_STRING(MAX_PORTS) "i");
+module_param_array(ports, int, ports_c, 0400);
 MODULE_PARM_DESC(ports, "port numbers of tftp servers");
 
 #if 0
@@ -41,14 +42,16 @@
 		     struct ip_conntrack *ct,
 		     enum ip_conntrack_info ctinfo)
 {
-	struct tftphdr tftph;
+	struct tftphdr _tftph, *tfh;
 	struct ip_conntrack_expect *exp;
 
-	if (skb_copy_bits(skb, skb->nh.iph->ihl * 4 + sizeof(struct udphdr),
-			  &tftph, sizeof(tftph)) != 0)
+	tfh = skb_header_pointer(skb,
+				 skb->nh.iph->ihl * 4 + sizeof(struct udphdr),
+				 sizeof(_tftph), &_tftph);
+	if (tfh == NULL)
 		return NF_ACCEPT;
 
-	switch (ntohs(tftph.opcode)) {
+	switch (ntohs(tfh->opcode)) {
 	/* RRQ and WRQ works the same way */
 	case TFTP_OPCODE_READ:
 	case TFTP_OPCODE_WRITE:
@@ -104,10 +107,10 @@
 	int i, ret;
 	char *tmpname;
 
-	if (!ports[0])
-		ports[0]=TFTP_PORT;
+	if (ports_c == 0)
+		ports[ports_c++] = TFTP_PORT;
 
-	for (i = 0 ; (i < MAX_PORTS) && ports[i] ; i++) {
+	for (i = 0; i < ports_c; i++) {
 		/* Create helper structure */
 		memset(&tftp[i], 0, sizeof(struct ip_conntrack_helper));
 
@@ -137,7 +140,6 @@
 			fini();
 			return(ret);
 		}
-		ports_c++;
 	}
 	return(0);
 }
diff -Nru a/net/ipv4/netfilter/ip_fw_compat_masq.c b/net/ipv4/netfilter/ip_fw_compat_masq.c
--- a/net/ipv4/netfilter/ip_fw_compat_masq.c	2004-10-18 14:56:49 -07:00
+++ b/net/ipv4/netfilter/ip_fw_compat_masq.c	2004-10-18 14:56:49 -07:00
@@ -31,6 +31,7 @@
 
 #include <linux/netfilter_ipv4/ip_conntrack.h>
 #include <linux/netfilter_ipv4/ip_conntrack_core.h>
+#include <linux/netfilter_ipv4/ip_conntrack_protocol.h>
 #include <linux/netfilter_ipv4/ip_nat.h>
 #include <linux/netfilter_ipv4/ip_nat_core.h>
 #include <linux/netfilter_ipv4/listhelp.h>
@@ -144,7 +145,8 @@
 	switch ((*pskb)->nh.iph->protocol) {
 	case IPPROTO_ICMP:
 		/* ICMP errors. */
-		ct = icmp_error_track(*pskb, &ctinfo, NF_IP_PRE_ROUTING);
+		protocol->error(*pskb, &ctinfo, NF_IP_PRE_ROUTING);
+		ct = (struct ip_conntrack *)(*pskb)->nfct;
 		if (ct) {
 			/* We only do SNAT in the compatibility layer.
 			   So we can manipulate ICMP errors from
@@ -165,7 +167,8 @@
 	case IPPROTO_UDP:
 		IP_NF_ASSERT(((*pskb)->nh.iph->frag_off & htons(IP_OFFSET)) == 0);
 
-		if (!get_tuple((*pskb)->nh.iph, *pskb, (*pskb)->nh.iph->ihl*4, &tuple, protocol)) {
+		if (!ip_ct_get_tuple((*pskb)->nh.iph, *pskb,
+				     (*pskb)->nh.iph->ihl*4, &tuple, protocol)) {
 			if (net_ratelimit())
 				printk("ip_fw_compat_masq: Can't get tuple\n");
 			return NF_ACCEPT;
@@ -184,7 +187,7 @@
 				      NULL, NULL, NULL);
 
 		/* Put back the reference gained from find_get */
-		nf_conntrack_put(&h->ctrack->infos[0]);
+		nf_conntrack_put(&h->ctrack->ct_general);
 		if (ret == NF_ACCEPT) {
 			struct ip_conntrack *ct;
 			ct = ip_conntrack_get(*pskb, &ctinfo);
@@ -203,7 +206,7 @@
 	} else {
 		if (h)
 			/* Put back the reference gained from find_get */
-			nf_conntrack_put(&h->ctrack->infos[0]);
+			nf_conntrack_put(&h->ctrack->ct_general);
 		ret = NF_ACCEPT;
 	}
 
diff -Nru a/net/ipv4/netfilter/ip_nat_core.c b/net/ipv4/netfilter/ip_nat_core.c
--- a/net/ipv4/netfilter/ip_nat_core.c	2004-10-18 14:56:11 -07:00
+++ b/net/ipv4/netfilter/ip_nat_core.c	2004-10-18 14:56:11 -07:00
@@ -48,10 +48,8 @@
 
 static struct list_head *bysource;
 static struct list_head *byipsproto;
-LIST_HEAD(protos);
-LIST_HEAD(helpers);
+struct ip_nat_protocol *ip_nat_protos[MAX_IP_NAT_PROTO];
 
-extern struct ip_nat_protocol unknown_nat_protocol;
 
 /* We keep extra hashes for each conntrack, for fast searching. */
 static inline size_t
@@ -78,9 +76,6 @@
 	if (!info->initialized)
 		return;
 
-	IP_NF_ASSERT(info->bysource.conntrack);
-	IP_NF_ASSERT(info->byipsproto.conntrack);
-
 	hs = hash_by_src(&conn->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src,
 	                 conn->tuplehash[IP_CT_DIR_ORIGINAL]
 	                 .tuple.dst.protonum);
@@ -91,8 +86,8 @@
 	                      .tuple.dst.protonum);
 
 	WRITE_LOCK(&ip_nat_lock);
-	LIST_DELETE(&bysource[hs], &info->bysource);
-	LIST_DELETE(&byipsproto[hp], &info->byipsproto);
+	list_del(&info->bysource);
+	list_del(&info->byipsproto);
 	WRITE_UNLOCK(&ip_nat_lock);
 }
 
@@ -107,23 +102,6 @@
 				      oldcheck^0xFFFF));
 }
 
-static inline int cmp_proto(const struct ip_nat_protocol *i, int proto)
-{
-	return i->protonum == proto;
-}
-
-struct ip_nat_protocol *
-find_nat_proto(u_int16_t protonum)
-{
-	struct ip_nat_protocol *i;
-
-	MUST_BE_READ_LOCKED(&ip_nat_lock);
-	i = LIST_FIND(&protos, cmp_proto, struct ip_nat_protocol *, protonum);
-	if (!i)
-		i = &unknown_nat_protocol;
-	return i;
-}
-
 /* Is this tuple already taken? (not by us) */
 int
 ip_nat_used_tuple(const struct ip_conntrack_tuple *tuple,
@@ -146,7 +124,7 @@
 	 const struct ip_conntrack_manip *manip,
 	 const struct ip_nat_multi_range *mr)
 {
-	struct ip_nat_protocol *proto = find_nat_proto(tuple->dst.protonum);
+	struct ip_nat_protocol *proto = ip_nat_find_proto(tuple->dst.protonum);
 	unsigned int i;
 	struct ip_conntrack_tuple newtuple = { *manip, tuple->dst };
 
@@ -172,20 +150,18 @@
 }
 
 static inline int
-src_cmp(const struct ip_nat_hash *i,
+src_cmp(const struct ip_conntrack *ct,
 	const struct ip_conntrack_tuple *tuple,
 	const struct ip_nat_multi_range *mr)
 {
-	return (i->conntrack->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.protonum
+	return (ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.protonum
 		== tuple->dst.protonum
-		&& i->conntrack->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip
+		&& ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip
 		== tuple->src.ip
-		&& i->conntrack->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.u.all
+		&& ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.u.all
 		== tuple->src.u.all
 		&& in_range(tuple,
-			    &i->conntrack->tuplehash[IP_CT_DIR_ORIGINAL]
-			    .tuple.src,
-			    mr));
+			    &ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src, mr));
 }
 
 /* Only called for SRC manip */
@@ -194,14 +170,13 @@
 		     const struct ip_nat_multi_range *mr)
 {
 	unsigned int h = hash_by_src(&tuple->src, tuple->dst.protonum);
-	struct ip_nat_hash *i;
+	struct ip_conntrack *ct;
 
 	MUST_BE_READ_LOCKED(&ip_nat_lock);
-	i = LIST_FIND(&bysource[h], src_cmp, struct ip_nat_hash *, tuple, mr);
-	if (i)
-		return &i->conntrack->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src;
-	else
-		return NULL;
+	list_for_each_entry(ct, &bysource[h], nat.info.bysource)
+		if (src_cmp(ct, tuple, mr))
+			return &ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src;
+	return NULL;
 }
 
 #ifdef CONFIG_IP_NF_NAT_LOCAL
@@ -227,19 +202,17 @@
 #endif
 
 /* Simple way to iterate through all. */
-static inline int fake_cmp(const struct ip_nat_hash *i,
+static inline int fake_cmp(const struct ip_conntrack *ct,
 			   u_int32_t src, u_int32_t dst, u_int16_t protonum,
-			   unsigned int *score,
-			   const struct ip_conntrack *conntrack)
+			   unsigned int *score, const struct ip_conntrack *ct2)
 {
 	/* Compare backwards: we're dealing with OUTGOING tuples, and
            inside the conntrack is the REPLY tuple.  Don't count this
            conntrack. */
-	if (i->conntrack != conntrack
-	    && i->conntrack->tuplehash[IP_CT_DIR_REPLY].tuple.src.ip == dst
-	    && i->conntrack->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip == src
-	    && (i->conntrack->tuplehash[IP_CT_DIR_REPLY].tuple.dst.protonum
-		== protonum))
+	if (ct != ct2
+	    && ct->tuplehash[IP_CT_DIR_REPLY].tuple.src.ip == dst
+	    && ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip == src
+	    && (ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.protonum == protonum))
 		(*score)++;
 	return 0;
 }
@@ -248,13 +221,14 @@
 count_maps(u_int32_t src, u_int32_t dst, u_int16_t protonum,
 	   const struct ip_conntrack *conntrack)
 {
+	struct ip_conntrack *ct;
 	unsigned int score = 0;
 	unsigned int h;
 
 	MUST_BE_READ_LOCKED(&ip_nat_lock);
 	h = hash_by_ipsproto(src, dst, protonum);
-	LIST_FIND(&byipsproto[h], fake_cmp, struct ip_nat_hash *,
-	          src, dst, protonum, &score, conntrack);
+	list_for_each_entry(ct, &byipsproto[h], nat.info.byipsproto)
+		fake_cmp(ct, src, dst, protonum, &score, conntrack);
 
 	return score;
 }
@@ -402,7 +376,7 @@
 		 unsigned int hooknum)
 {
 	struct ip_nat_protocol *proto
-		= find_nat_proto(orig_tuple->dst.protonum);
+		= ip_nat_find_proto(orig_tuple->dst.protonum);
 	struct ip_nat_range *rptr;
 	unsigned int i;
 	int ret;
@@ -498,13 +472,6 @@
 	return ret;
 }
 
-static inline int
-helper_cmp(const struct ip_nat_helper *helper,
-	   const struct ip_conntrack_tuple *tuple)
-{
-	return ip_ct_tuple_mask_cmp(tuple, &helper->tuple, &helper->mask);
-}
-
 /* Where to manip the reply packets (will be reverse manip). */
 static unsigned int opposite_hook[NF_IP_NUMHOOKS]
 = { [NF_IP_PRE_ROUTING] = NF_IP_POST_ROUTING,
@@ -643,18 +610,15 @@
 
 	/* If there's a helper, assign it; based on new tuple. */
 	if (!conntrack->master)
-		info->helper = LIST_FIND(&helpers, helper_cmp, struct ip_nat_helper *,
-					 &reply);
+		info->helper = __ip_nat_find_helper(&reply);
 
 	/* It's done. */
 	info->initialized |= (1 << HOOK2MANIP(hooknum));
 
-	if (in_hashes) {
-		IP_NF_ASSERT(info->bysource.conntrack);
+	if (in_hashes)
 		replace_in_hashes(conntrack, info);
-	} else {
+	else
 		place_in_hashes(conntrack, info);
-	}
 
 	return NF_ACCEPT;
 }
@@ -678,14 +642,9 @@
 				   conntrack->tuplehash[IP_CT_DIR_REPLY]
 				   .tuple.dst.protonum);
 
-	IP_NF_ASSERT(info->bysource.conntrack == conntrack);
 	MUST_BE_WRITE_LOCKED(&ip_nat_lock);
-
-	list_del(&info->bysource.list);
-	list_del(&info->byipsproto.list);
-
-	list_prepend(&bysource[srchash], &info->bysource);
-	list_prepend(&byipsproto[ipsprotohash], &info->byipsproto);
+	list_move(&info->bysource, &bysource[srchash]);
+	list_move(&info->byipsproto, &byipsproto[ipsprotohash]);
 }
 
 void place_in_hashes(struct ip_conntrack *conntrack,
@@ -706,14 +665,9 @@
 				   conntrack->tuplehash[IP_CT_DIR_REPLY]
 				   .tuple.dst.protonum);
 
-	IP_NF_ASSERT(!info->bysource.conntrack);
-
 	MUST_BE_WRITE_LOCKED(&ip_nat_lock);
-	info->byipsproto.conntrack = conntrack;
-	info->bysource.conntrack = conntrack;
-
-	list_prepend(&bysource[srchash], &info->bysource);
-	list_prepend(&byipsproto[ipsprotohash], &info->byipsproto);
+	list_add(&info->bysource, &bysource[srchash]);
+	list_add(&info->byipsproto, &byipsproto[ipsprotohash]);
 }
 
 /* Returns true if succeeded. */
@@ -733,9 +687,8 @@
 	iph = (void *)(*pskb)->data + iphdroff;
 
 	/* Manipulate protcol part. */
-	if (!find_nat_proto(proto)->manip_pkt(pskb,
-					      iphdroff + iph->ihl*4,
-					      manip, maniptype))
+	if (!ip_nat_find_proto(proto)->manip_pkt(pskb, iphdroff + iph->ihl*4,
+	                                         manip, maniptype))
 		return 0;
 
 	iph = (void *)(*pskb)->data + iphdroff;
@@ -759,7 +712,7 @@
 	int ret = 1;
 
 	MUST_BE_READ_LOCKED(&ip_conntrack_lock);
-	proto = __ip_ct_find_proto(skb->nh.iph->protocol);
+	proto = ip_ct_find_proto(skb->nh.iph->protocol);
 	if (proto->exp_matches_pkt)
 		ret = proto->exp_matches_pkt(exp, skb);
 
@@ -899,12 +852,8 @@
 	}
 
 	/* Must be RELATED */
-	IP_NF_ASSERT((*pskb)->nfct
-		     - ((struct ip_conntrack *)(*pskb)->nfct->master)->infos
-		     == IP_CT_RELATED
-		     || (*pskb)->nfct
-		     - ((struct ip_conntrack *)(*pskb)->nfct->master)->infos
-		     == IP_CT_RELATED+IP_CT_IS_REPLY);
+	IP_NF_ASSERT((*pskb)->nfctinfo == IP_CT_RELATED ||
+		     (*pskb)->nfctinfo == IP_CT_RELATED+IP_CT_IS_REPLY);
 
 	/* Redirects on non-null nats must be dropped, else they'll
            start talking to each other without our translation, and be
@@ -1004,9 +953,11 @@
 
 	/* Sew in builtin protocols. */
 	WRITE_LOCK(&ip_nat_lock);
-	list_append(&protos, &ip_nat_protocol_tcp);
-	list_append(&protos, &ip_nat_protocol_udp);
-	list_append(&protos, &ip_nat_protocol_icmp);
+	for (i = 0; i < MAX_IP_NAT_PROTO; i++)
+		ip_nat_protos[i] = &ip_nat_unknown_protocol;
+	ip_nat_protos[IPPROTO_TCP] = &ip_nat_protocol_tcp;
+	ip_nat_protos[IPPROTO_UDP] = &ip_nat_protocol_udp;
+	ip_nat_protos[IPPROTO_ICMP] = &ip_nat_protocol_icmp;
 	WRITE_UNLOCK(&ip_nat_lock);
 
 	for (i = 0; i < ip_nat_htable_size; i++) {
diff -Nru a/net/ipv4/netfilter/ip_nat_ftp.c b/net/ipv4/netfilter/ip_nat_ftp.c
--- a/net/ipv4/netfilter/ip_nat_ftp.c	2004-10-18 14:56:48 -07:00
+++ b/net/ipv4/netfilter/ip_nat_ftp.c	2004-10-18 14:56:48 -07:00
@@ -12,6 +12,7 @@
 #include <linux/netfilter_ipv4.h>
 #include <linux/ip.h>
 #include <linux/tcp.h>
+#include <linux/moduleparam.h>
 #include <net/tcp.h>
 #include <linux/netfilter_ipv4/ip_nat.h>
 #include <linux/netfilter_ipv4/ip_nat_helper.h>
@@ -33,9 +34,7 @@
 static int ports[MAX_PORTS];
 static int ports_c;
 
-MODULE_PARM(ports, "1-" __MODULE_STRING(MAX_PORTS) "i");
-
-DECLARE_LOCK_EXTERN(ip_ftp_lock);
+module_param_array(ports, int, ports_c, 0400);
 
 /* FIXME: Time out? --RR */
 
@@ -59,8 +58,6 @@
 	DEBUGP("nat_expected: We have a connection!\n");
 	exp_ftp_info = &ct->master->help.exp_ftp_info;
 
-	LOCK_BH(&ip_ftp_lock);
-
 	if (exp_ftp_info->ftptype == IP_CT_FTP_PORT
 	    || exp_ftp_info->ftptype == IP_CT_FTP_EPRT) {
 		/* PORT command: make connection go to the client. */
@@ -75,7 +72,6 @@
 		DEBUGP("nat_expected: PASV cmd. %u.%u.%u.%u->%u.%u.%u.%u\n",
 		       NIPQUAD(newsrcip), NIPQUAD(newdstip));
 	}
-	UNLOCK_BH(&ip_ftp_lock);
 
 	if (HOOK2MANIP(hooknum) == IP_NAT_MANIP_SRC)
 		newip = newsrcip;
@@ -111,8 +107,6 @@
 {
 	char buffer[sizeof("nnn,nnn,nnn,nnn,nnn,nnn")];
 
-	MUST_BE_LOCKED(&ip_ftp_lock);
-
 	sprintf(buffer, "%u,%u,%u,%u,%u,%u",
 		NIPQUAD(newip), port>>8, port&0xFF);
 
@@ -134,8 +128,6 @@
 {
 	char buffer[sizeof("|1|255.255.255.255|65535|")];
 
-	MUST_BE_LOCKED(&ip_ftp_lock);
-
 	sprintf(buffer, "|1|%u.%u.%u.%u|%u|", NIPQUAD(newip), port);
 
 	DEBUGP("calling ip_nat_mangle_tcp_packet\n");
@@ -156,8 +148,6 @@
 {
 	char buffer[sizeof("|||65535|")];
 
-	MUST_BE_LOCKED(&ip_ftp_lock);
-
 	sprintf(buffer, "|||%u|", port);
 
 	DEBUGP("calling ip_nat_mangle_tcp_packet\n");
@@ -177,7 +167,7 @@
     [IP_CT_FTP_EPSV] = mangle_epsv_packet
 };
 
-static int ftp_data_fixup(const struct ip_ct_ftp_expect *ct_ftp_info,
+static int ftp_data_fixup(const struct ip_ct_ftp_expect *exp_ftp_info,
 			  struct ip_conntrack *ct,
 			  struct sk_buff **pskb,
 			  enum ip_conntrack_info ctinfo,
@@ -189,15 +179,14 @@
 	u_int16_t port;
 	struct ip_conntrack_tuple newtuple;
 
-	MUST_BE_LOCKED(&ip_ftp_lock);
 	DEBUGP("FTP_NAT: seq %u + %u in %u\n",
-	       expect->seq, ct_ftp_info->len,
+	       expect->seq, exp_ftp_info->len,
 	       ntohl(tcph->seq));
 
 	/* Change address inside packet to match way we're mapping
 	   this connection. */
-	if (ct_ftp_info->ftptype == IP_CT_FTP_PASV
-	    || ct_ftp_info->ftptype == IP_CT_FTP_EPSV) {
+	if (exp_ftp_info->ftptype == IP_CT_FTP_PASV
+	    || exp_ftp_info->ftptype == IP_CT_FTP_EPSV) {
 		/* PASV/EPSV response: must be where client thinks server
 		   is */
 		newip = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.ip;
@@ -219,7 +208,7 @@
 	newtuple.src.u.tcp.port = expect->tuple.src.u.tcp.port;
 
 	/* Try to get same port: if not, try to change it. */
-	for (port = ct_ftp_info->port; port != 0; port++) {
+	for (port = exp_ftp_info->port; port != 0; port++) {
 		newtuple.dst.u.tcp.port = htons(port);
 
 		if (ip_conntrack_change_expect(expect, &newtuple) == 0)
@@ -228,9 +217,9 @@
 	if (port == 0)
 		return 0;
 
-	if (!mangle[ct_ftp_info->ftptype](pskb, newip, port,
+	if (!mangle[exp_ftp_info->ftptype](pskb, newip, port,
 					  expect->seq - ntohl(tcph->seq),
-					  ct_ftp_info->len, ct, ctinfo))
+					  exp_ftp_info->len, ct, ctinfo))
 		return 0;
 
 	return 1;
@@ -247,12 +236,12 @@
 	struct tcphdr *tcph = (void *)iph + iph->ihl*4;
 	unsigned int datalen;
 	int dir;
-	struct ip_ct_ftp_expect *ct_ftp_info;
+	struct ip_ct_ftp_expect *exp_ftp_info;
 
 	if (!exp)
 		DEBUGP("ip_nat_ftp: no exp!!");
 
-	ct_ftp_info = &exp->help.exp_ftp_info;
+	exp_ftp_info = &exp->help.exp_ftp_info;
 
 	/* Only mangle things once: original direction in POST_ROUTING
 	   and reply direction on PRE_ROUTING. */
@@ -268,29 +257,23 @@
 	}
 
 	datalen = (*pskb)->len - iph->ihl * 4 - tcph->doff * 4;
-	LOCK_BH(&ip_ftp_lock);
 	/* If it's in the right range... */
-	if (between(exp->seq + ct_ftp_info->len,
+	if (between(exp->seq + exp_ftp_info->len,
 		    ntohl(tcph->seq),
 		    ntohl(tcph->seq) + datalen)) {
-		if (!ftp_data_fixup(ct_ftp_info, ct, pskb, ctinfo, exp)) {
-			UNLOCK_BH(&ip_ftp_lock);
+		if (!ftp_data_fixup(exp_ftp_info, ct, pskb, ctinfo, exp))
 			return NF_DROP;
-		}
 	} else {
 		/* Half a match?  This means a partial retransmisison.
 		   It's a cracker being funky. */
 		if (net_ratelimit()) {
 			printk("FTP_NAT: partial packet %u/%u in %u/%u\n",
-			       exp->seq, ct_ftp_info->len,
+			       exp->seq, exp_ftp_info->len,
 			       ntohl(tcph->seq),
 			       ntohl(tcph->seq) + datalen);
 		}
-		UNLOCK_BH(&ip_ftp_lock);
 		return NF_DROP;
 	}
-	UNLOCK_BH(&ip_ftp_lock);
-
 	return NF_ACCEPT;
 }
 
@@ -313,10 +296,10 @@
 	int i, ret = 0;
 	char *tmpname;
 
-	if (ports[0] == 0)
-		ports[0] = FTP_PORT;
+	if (ports_c == 0)
+		ports[ports_c++] = FTP_PORT;
 
-	for (i = 0; (i < MAX_PORTS) && ports[i]; i++) {
+	for (i = 0; i < ports_c; i++) {
 		ftp[i].tuple.dst.protonum = IPPROTO_TCP;
 		ftp[i].tuple.src.u.tcp.port = htons(ports[i]);
 		ftp[i].mask.dst.protonum = 0xFFFF;
@@ -343,7 +326,6 @@
 			fini();
 			return ret;
 		}
-		ports_c++;
 	}
 
 	return ret;
diff -Nru a/net/ipv4/netfilter/ip_nat_helper.c b/net/ipv4/netfilter/ip_nat_helper.c
--- a/net/ipv4/netfilter/ip_nat_helper.c	2004-10-18 14:56:13 -07:00
+++ b/net/ipv4/netfilter/ip_nat_helper.c	2004-10-18 14:56:13 -07:00
@@ -47,6 +47,7 @@
 #define DUMP_OFFSET(x)
 #endif
 
+static LIST_HEAD(helpers);
 DECLARE_LOCK(ip_nat_seqofs_lock);
 
 /* Setup TCP sequence correction given this change at this sequence */
@@ -72,7 +73,7 @@
 
 	LOCK_BH(&ip_nat_seqofs_lock);
 
-	/* SYN adjust. If it's uninitialized, of this is after last
+	/* SYN adjust. If it's uninitialized, or this is after last
 	 * correction, record it: we don't handle more than one
 	 * adjustment in the window, but do deal with common case of a
 	 * retransmit */
@@ -346,7 +347,7 @@
 	return 1;
 }
 
-/* TCP sequence number adjustment.  Returns true or false.  */
+/* TCP sequence number adjustment.  Returns 1 on success, 0 on failure */
 int
 ip_nat_seq_adjust(struct sk_buff **pskb, 
 		  struct ip_conntrack *ct, 
@@ -395,7 +396,12 @@
 	tcph->seq = newseq;
 	tcph->ack_seq = newack;
 
-	return ip_nat_sack_adjust(pskb, tcph, ct, ctinfo);
+	if (!ip_nat_sack_adjust(pskb, tcph, ct, ctinfo))
+		return 0;
+
+	ip_conntrack_tcp_update(*pskb, ct, dir);
+
+	return 1;
 }
 
 static inline int
@@ -417,6 +423,24 @@
 	WRITE_UNLOCK(&ip_nat_lock);
 
 	return ret;
+}
+
+struct ip_nat_helper *
+__ip_nat_find_helper(const struct ip_conntrack_tuple *tuple)
+{
+	return LIST_FIND(&helpers, helper_cmp, struct ip_nat_helper *, tuple);
+}
+
+struct ip_nat_helper *
+ip_nat_find_helper(const struct ip_conntrack_tuple *tuple)
+{
+	struct ip_nat_helper *h;
+
+	READ_LOCK(&ip_nat_lock);
+	h = __ip_nat_find_helper(tuple);
+	READ_UNLOCK(&ip_nat_lock);
+
+	return h;
 }
 
 static int
diff -Nru a/net/ipv4/netfilter/ip_nat_irc.c b/net/ipv4/netfilter/ip_nat_irc.c
--- a/net/ipv4/netfilter/ip_nat_irc.c	2004-10-18 14:57:05 -07:00
+++ b/net/ipv4/netfilter/ip_nat_irc.c	2004-10-18 14:57:05 -07:00
@@ -27,6 +27,7 @@
 #include <linux/netfilter_ipv4/ip_nat_rule.h>
 #include <linux/netfilter_ipv4/ip_conntrack_irc.h>
 #include <linux/netfilter_ipv4/ip_conntrack_helper.h>
+#include <linux/moduleparam.h>
 
 #if 0
 #define DEBUGP printk
@@ -41,12 +42,9 @@
 MODULE_AUTHOR("Harald Welte <laforge@gnumonks.org>");
 MODULE_DESCRIPTION("IRC (DCC) NAT helper");
 MODULE_LICENSE("GPL");
-MODULE_PARM(ports, "1-" __MODULE_STRING(MAX_PORTS) "i");
+module_param_array(ports, int, ports_c, 0400);
 MODULE_PARM_DESC(ports, "port numbers of IRC servers");
 
-/* protects irc part of conntracks */
-DECLARE_LOCK_EXTERN(ip_irc_lock);
-
 /* FIXME: Time out? --RR */
 
 static unsigned int
@@ -87,7 +85,7 @@
 	return ip_nat_setup_info(ct, &mr, hooknum);
 }
 
-static int irc_data_fixup(const struct ip_ct_irc_expect *ct_irc_info,
+static int irc_data_fixup(const struct ip_ct_irc_expect *exp_irc_info,
 			  struct ip_conntrack *ct,
 			  struct sk_buff **pskb,
 			  enum ip_conntrack_info ctinfo,
@@ -102,23 +100,16 @@
 	/* "4294967296 65635 " */
 	char buffer[18];
 
-	MUST_BE_LOCKED(&ip_irc_lock);
-
 	DEBUGP("IRC_NAT: info (seq %u + %u) in %u\n",
-	       expect->seq, ct_irc_info->len,
+	       expect->seq, exp_irc_info->len,
 	       ntohl(tcph->seq));
 
 	newip = ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip;
 
 	/* Alter conntrack's expectations. */
-
-	/* We can read expect here without conntrack lock, since it's
-	   only set in ip_conntrack_irc, with ip_irc_lock held
-	   writable */
-
 	t = expect->tuple;
 	t.dst.ip = newip;
-	for (port = ct_irc_info->port; port != 0; port++) {
+	for (port = exp_irc_info->port; port != 0; port++) {
 		t.dst.u.tcp.port = htons(port);
 		if (ip_conntrack_change_expect(expect, &t) == 0) {
 			DEBUGP("using port %d", port);
@@ -148,7 +139,7 @@
 
 	return ip_nat_mangle_tcp_packet(pskb, ct, ctinfo, 
 					expect->seq - ntohl(tcph->seq),
-					ct_irc_info->len, buffer, 
+					exp_irc_info->len, buffer, 
 					strlen(buffer));
 }
 
@@ -163,12 +154,12 @@
 	struct tcphdr *tcph = (void *) iph + iph->ihl * 4;
 	unsigned int datalen;
 	int dir;
-	struct ip_ct_irc_expect *ct_irc_info;
+	struct ip_ct_irc_expect *exp_irc_info;
 
 	if (!exp)
 		DEBUGP("ip_nat_irc: no exp!!");
 		
-	ct_irc_info = &exp->help.exp_irc_info;
+	exp_irc_info = &exp->help.exp_irc_info;
 
 	/* Only mangle things once: original direction in POST_ROUTING
 	   and reply direction on PRE_ROUTING. */
@@ -185,30 +176,24 @@
 	DEBUGP("got beyond not touching\n");
 
 	datalen = (*pskb)->len - iph->ihl * 4 - tcph->doff * 4;
-	LOCK_BH(&ip_irc_lock);
 	/* Check whether the whole IP/address pattern is carried in the payload */
-	if (between(exp->seq + ct_irc_info->len,
+	if (between(exp->seq + exp_irc_info->len,
 		    ntohl(tcph->seq),
 		    ntohl(tcph->seq) + datalen)) {
-		if (!irc_data_fixup(ct_irc_info, ct, pskb, ctinfo, exp)) {
-			UNLOCK_BH(&ip_irc_lock);
+		if (!irc_data_fixup(exp_irc_info, ct, pskb, ctinfo, exp))
 			return NF_DROP;
-		}
 	} else { 
 		/* Half a match?  This means a partial retransmisison.
 		   It's a cracker being funky. */
 		if (net_ratelimit()) {
 			printk
 			    ("IRC_NAT: partial packet %u/%u in %u/%u\n",
-			     exp->seq, ct_irc_info->len,
+			     exp->seq, exp_irc_info->len,
 			     ntohl(tcph->seq),
 			     ntohl(tcph->seq) + datalen);
 		}
-		UNLOCK_BH(&ip_irc_lock);
 		return NF_DROP;
 	}
-	UNLOCK_BH(&ip_irc_lock);
-
 	return NF_ACCEPT;
 }
 
@@ -235,11 +220,10 @@
 	struct ip_nat_helper *hlpr;
 	char *tmpname;
 
-	if (ports[0] == 0) {
-		ports[0] = IRC_PORT;
-	}
+	if (ports_c == 0)
+		ports[ports_c++] = IRC_PORT;
 
-	for (i = 0; (i < MAX_PORTS) && ports[i] != 0; i++) {
+	for (i = 0; i < ports_c; i++) {
 		hlpr = &ip_nat_irc_helpers[i];
 		hlpr->tuple.dst.protonum = IPPROTO_TCP;
 		hlpr->tuple.src.u.tcp.port = htons(ports[i]);
@@ -269,7 +253,6 @@
 			fini();
 			return 1;
 		}
-		ports_c++;
 	}
 	return ret;
 }
diff -Nru a/net/ipv4/netfilter/ip_nat_proto_icmp.c b/net/ipv4/netfilter/ip_nat_proto_icmp.c
--- a/net/ipv4/netfilter/ip_nat_proto_icmp.c	2004-10-18 14:56:28 -07:00
+++ b/net/ipv4/netfilter/ip_nat_proto_icmp.c	2004-10-18 14:56:28 -07:00
@@ -104,7 +104,7 @@
 }
 
 struct ip_nat_protocol ip_nat_protocol_icmp
-= { { NULL, NULL }, "ICMP", IPPROTO_ICMP,
+= { "ICMP", IPPROTO_ICMP,
     icmp_manip_pkt,
     icmp_in_range,
     icmp_unique_tuple,
diff -Nru a/net/ipv4/netfilter/ip_nat_proto_tcp.c b/net/ipv4/netfilter/ip_nat_proto_tcp.c
--- a/net/ipv4/netfilter/ip_nat_proto_tcp.c	2004-10-18 14:55:54 -07:00
+++ b/net/ipv4/netfilter/ip_nat_proto_tcp.c	2004-10-18 14:55:54 -07:00
@@ -162,7 +162,7 @@
 }
 
 struct ip_nat_protocol ip_nat_protocol_tcp
-= { { NULL, NULL }, "TCP", IPPROTO_TCP,
+= { "TCP", IPPROTO_TCP,
     tcp_manip_pkt,
     tcp_in_range,
     tcp_unique_tuple,
diff -Nru a/net/ipv4/netfilter/ip_nat_proto_udp.c b/net/ipv4/netfilter/ip_nat_proto_udp.c
--- a/net/ipv4/netfilter/ip_nat_proto_udp.c	2004-10-18 14:56:17 -07:00
+++ b/net/ipv4/netfilter/ip_nat_proto_udp.c	2004-10-18 14:56:17 -07:00
@@ -148,7 +148,7 @@
 }
 
 struct ip_nat_protocol ip_nat_protocol_udp
-= { { NULL, NULL }, "UDP", IPPROTO_UDP,
+= { "UDP", IPPROTO_UDP,
     udp_manip_pkt,
     udp_in_range,
     udp_unique_tuple,
diff -Nru a/net/ipv4/netfilter/ip_nat_proto_unknown.c b/net/ipv4/netfilter/ip_nat_proto_unknown.c
--- a/net/ipv4/netfilter/ip_nat_proto_unknown.c	2004-10-18 14:56:32 -07:00
+++ b/net/ipv4/netfilter/ip_nat_proto_unknown.c	2004-10-18 14:56:32 -07:00
@@ -60,8 +60,8 @@
 	return 0;
 }
 
-struct ip_nat_protocol unknown_nat_protocol = {
-	{ NULL, NULL }, "unknown", 0,
+struct ip_nat_protocol ip_nat_unknown_protocol = {
+	"unknown", 0,
 	unknown_manip_pkt,
 	unknown_in_range,
 	unknown_unique_tuple,
diff -Nru a/net/ipv4/netfilter/ip_nat_rule.c b/net/ipv4/netfilter/ip_nat_rule.c
--- a/net/ipv4/netfilter/ip_nat_rule.c	2004-10-18 14:56:29 -07:00
+++ b/net/ipv4/netfilter/ip_nat_rule.c	2004-10-18 14:56:29 -07:00
@@ -132,7 +132,8 @@
 	ct = ip_conntrack_get(*pskb, &ctinfo);
 
 	/* Connection must be valid and new. */
-	IP_NF_ASSERT(ct && (ctinfo == IP_CT_NEW || ctinfo == IP_CT_RELATED));
+	IP_NF_ASSERT(ct && (ctinfo == IP_CT_NEW || ctinfo == IP_CT_RELATED
+	                    || ctinfo == IP_CT_RELATED + IP_CT_IS_REPLY));
 	IP_NF_ASSERT(out);
 
 	return ip_nat_setup_info(ct, targinfo, hooknum);
diff -Nru a/net/ipv4/netfilter/ip_nat_snmp_basic.c b/net/ipv4/netfilter/ip_nat_snmp_basic.c
--- a/net/ipv4/netfilter/ip_nat_snmp_basic.c	2004-10-18 14:56:49 -07:00
+++ b/net/ipv4/netfilter/ip_nat_snmp_basic.c	2004-10-18 14:56:49 -07:00
@@ -47,6 +47,7 @@
 #include <linux/module.h>
 #include <linux/types.h>
 #include <linux/kernel.h>
+#include <linux/moduleparam.h>
 #include <linux/netfilter_ipv4.h>
 #include <linux/netfilter_ipv4/ip_nat.h>
 #include <linux/netfilter_ipv4/ip_nat_helper.h>
@@ -1252,6 +1253,9 @@
 	int dir = CTINFO2DIR(ctinfo);
 	struct iphdr *iph = (*pskb)->nh.iph;
 	struct udphdr *udph = (struct udphdr *)((u_int32_t *)iph + iph->ihl);
+	
+	if (!skb_ip_make_writable(pskb, (*pskb)->len))
+		return NF_DROP;
 
 	spin_lock_bh(&snmp_lock);
 	
@@ -1357,4 +1361,4 @@
 module_init(init);
 module_exit(fini);
 
-MODULE_PARM(debug, "i");
+module_param(debug, bool, 0600);
diff -Nru a/net/ipv4/netfilter/ip_nat_standalone.c b/net/ipv4/netfilter/ip_nat_standalone.c
--- a/net/ipv4/netfilter/ip_nat_standalone.c	2004-10-18 14:56:49 -07:00
+++ b/net/ipv4/netfilter/ip_nat_standalone.c	2004-10-18 14:56:49 -07:00
@@ -99,11 +99,13 @@
                    hash table yet).  We must not let this through, in
                    case we're doing NAT to the same network. */
 		if ((*pskb)->nh.iph->protocol == IPPROTO_ICMP) {
-			struct icmphdr hdr;
+			struct icmphdr _hdr, *hp;
 
-			if (skb_copy_bits(*pskb, (*pskb)->nh.iph->ihl*4,
-					  &hdr, sizeof(hdr)) == 0
-			    && hdr.type == ICMP_REDIRECT)
+			hp = skb_header_pointer(*pskb,
+						(*pskb)->nh.iph->ihl*4,
+						sizeof(_hdr), &_hdr);
+			if (hp != NULL &&
+			    hp->type == ICMP_REDIRECT)
 				return NF_DROP;
 		}
 		return NF_ACCEPT;
@@ -281,18 +283,13 @@
 int ip_nat_protocol_register(struct ip_nat_protocol *proto)
 {
 	int ret = 0;
-	struct list_head *i;
 
 	WRITE_LOCK(&ip_nat_lock);
-	list_for_each(i, &protos) {
-		if (((struct ip_nat_protocol *)i)->protonum
-		    == proto->protonum) {
-			ret = -EBUSY;
-			goto out;
-		}
+	if (ip_nat_protos[proto->protonum] != &ip_nat_unknown_protocol) {
+		ret = -EBUSY;
+		goto out;
 	}
-
-	list_prepend(&protos, proto);
+	ip_nat_protos[proto->protonum] = proto;
  out:
 	WRITE_UNLOCK(&ip_nat_lock);
 	return ret;
@@ -302,7 +299,7 @@
 void ip_nat_protocol_unregister(struct ip_nat_protocol *proto)
 {
 	WRITE_LOCK(&ip_nat_lock);
-	LIST_DELETE(&protos, proto);
+	ip_nat_protos[proto->protonum] = &ip_nat_unknown_protocol;
 	WRITE_UNLOCK(&ip_nat_lock);
 
 	/* Someone could be still looking at the proto in a bh. */
@@ -392,4 +389,6 @@
 EXPORT_SYMBOL(ip_nat_mangle_tcp_packet);
 EXPORT_SYMBOL(ip_nat_mangle_udp_packet);
 EXPORT_SYMBOL(ip_nat_used_tuple);
+EXPORT_SYMBOL(ip_nat_find_helper);
+EXPORT_SYMBOL(__ip_nat_find_helper);
 MODULE_LICENSE("GPL");
diff -Nru a/net/ipv4/netfilter/ip_nat_tftp.c b/net/ipv4/netfilter/ip_nat_tftp.c
--- a/net/ipv4/netfilter/ip_nat_tftp.c	2004-10-18 14:56:28 -07:00
+++ b/net/ipv4/netfilter/ip_nat_tftp.c	2004-10-18 14:56:28 -07:00
@@ -32,6 +32,7 @@
 #include <linux/netfilter_ipv4/ip_conntrack_tftp.h>
 #include <linux/netfilter_ipv4/ip_nat_helper.h>
 #include <linux/netfilter_ipv4/ip_nat_rule.h>
+#include <linux/moduleparam.h>
 
 MODULE_AUTHOR("Magnus Boden <mb@ozaba.mine.nu>");
 MODULE_DESCRIPTION("tftp NAT helper");
@@ -41,7 +42,7 @@
 
 static int ports[MAX_PORTS];
 static int ports_c = 0;
-MODULE_PARM(ports,"1-" __MODULE_STRING(MAX_PORTS) "i");
+module_param_array(ports, int, ports_c, 0400);
 MODULE_PARM_DESC(ports, "port numbers of tftp servers");
 
 #if 0
@@ -59,7 +60,7 @@
 	      struct sk_buff **pskb)
 {
 	int dir = CTINFO2DIR(ctinfo);
-	struct tftphdr tftph;
+	struct tftphdr _tftph, *tfh;
 	struct ip_conntrack_tuple repl;
 
 	if (!((hooknum == NF_IP_POST_ROUTING && dir == IP_CT_DIR_ORIGINAL)
@@ -71,11 +72,13 @@
 		return NF_ACCEPT;
 	}
 
-	if (skb_copy_bits(*pskb, (*pskb)->nh.iph->ihl*4+sizeof(struct udphdr),
-			  &tftph, sizeof(tftph)) != 0)
+	tfh = skb_header_pointer(*pskb,
+				 (*pskb)->nh.iph->ihl*4+sizeof(struct udphdr),
+				 sizeof(_tftph), &_tftph);
+	if (tfh == NULL)
 		return NF_DROP;
 
-	switch (ntohs(tftph.opcode)) {
+	switch (ntohs(tfh->opcode)) {
 	/* RRQ and WRQ works the same way */
 	case TFTP_OPCODE_READ:
 	case TFTP_OPCODE_WRITE:
@@ -108,9 +111,12 @@
 #if 0
 	const struct ip_conntrack_tuple *repl =
 			&master->tuplehash[IP_CT_DIR_REPLY].tuple;
-	struct udphdr udph;
+	struct udphdr _udph, *uh;
 
-	if (skb_copy_bits(*pskb,(*pskb)->nh.iph->ihl*4,&udph,sizeof(udph))!=0)
+	uh = skb_header_pointer(*pskb,
+				(*pskb)->nh.iph->ihl*4,
+				sizeof(_udph), &_udph);
+	if (uh == NULL)
 		return NF_DROP;
 #endif
 
@@ -125,8 +131,8 @@
 		mr.range[0].min_ip = mr.range[0].max_ip = orig->dst.ip; 
 		DEBUGP("orig: %u.%u.%u.%u:%u <-> %u.%u.%u.%u:%u "
 			"newsrc: %u.%u.%u.%u\n",
-                        NIPQUAD((*pskb)->nh.iph->saddr), ntohs(udph.source),
- 			NIPQUAD((*pskb)->nh.iph->daddr), ntohs(udph.dest),
+                        NIPQUAD((*pskb)->nh.iph->saddr), ntohs(uh->source),
+ 			NIPQUAD((*pskb)->nh.iph->daddr), ntohs(uh->dest),
 			NIPQUAD(orig->dst.ip));
 	} else {
 		mr.range[0].min_ip = mr.range[0].max_ip = orig->src.ip;
@@ -136,8 +142,8 @@
 
 		DEBUGP("orig: %u.%u.%u.%u:%u <-> %u.%u.%u.%u:%u "
 			"newdst: %u.%u.%u.%u:%u\n",
-                        NIPQUAD((*pskb)->nh.iph->saddr), ntohs(udph.source),
-                        NIPQUAD((*pskb)->nh.iph->daddr), ntohs(udph.dest),
+                        NIPQUAD((*pskb)->nh.iph->saddr), ntohs(uh->source),
+                        NIPQUAD((*pskb)->nh.iph->daddr), ntohs(uh->dest),
                         NIPQUAD(orig->src.ip), ntohs(orig->src.u.udp.port));
 	}
 
@@ -162,10 +168,10 @@
 	int i, ret = 0;
 	char *tmpname;
 
-	if (!ports[0])
-		ports[0] = TFTP_PORT;
+	if (ports_c == 0)
+		ports[ports_c++] = TFTP_PORT;
 
-	for (i = 0 ; (i < MAX_PORTS) && ports[i] ; i++) {
+	for (i = 0; i < ports_c; i++) {
 		memset(&tftp[i], 0, sizeof(struct ip_nat_helper));
 
 		tftp[i].tuple.dst.protonum = IPPROTO_UDP;
@@ -194,7 +200,6 @@
 			fini();
 			return ret;
 		}
-		ports_c++;
 	}
 	return ret;
 }
diff -Nru a/net/ipv4/netfilter/ip_queue.c b/net/ipv4/netfilter/ip_queue.c
--- a/net/ipv4/netfilter/ip_queue.c	2004-10-18 14:57:19 -07:00
+++ b/net/ipv4/netfilter/ip_queue.c	2004-10-18 14:57:19 -07:00
@@ -619,6 +619,7 @@
 	{ .ctl_name = 0 }
 };
 
+#ifdef CONFIG_PROC_FS
 static int
 ipq_get_info(char *buffer, char **start, off_t offset, int length)
 {
@@ -648,6 +649,7 @@
 		len = 0;
 	return len;
 }
+#endif /* CONFIG_PROC_FS */
 
 static int
 init_or_cleanup(int init)
diff -Nru a/net/ipv4/netfilter/ip_tables.c b/net/ipv4/netfilter/ip_tables.c
--- a/net/ipv4/netfilter/ip_tables.c	2004-10-18 14:56:20 -07:00
+++ b/net/ipv4/netfilter/ip_tables.c	2004-10-18 14:56:20 -07:00
@@ -61,6 +61,8 @@
 #endif
 #define SMP_ALIGN(x) (((x) + SMP_CACHE_BYTES-1) & ~(SMP_CACHE_BYTES-1))
 
+static DECLARE_MUTEX(ipt_mutex);
+
 /* Must have mutex */
 #define ASSERT_READ_LOCK(x) IP_NF_ASSERT(down_trylock(&ipt_mutex) != 0)
 #define ASSERT_WRITE_LOCK(x) IP_NF_ASSERT(down_trylock(&ipt_mutex) != 0)
@@ -1458,21 +1460,27 @@
 		int *hotdrop)
 {
 	/* tcp.doff is only 4 bits, ie. max 15 * 4 bytes */
-	u_int8_t opt[60 - sizeof(struct tcphdr)];
+	u_int8_t _opt[60 - sizeof(struct tcphdr)], *op;
 	unsigned int i;
 
 	duprintf("tcp_match: finding option\n");
+
+	if (!optlen)
+		return invert;
+
 	/* If we don't have the whole header, drop packet. */
-	if (skb_copy_bits(skb, skb->nh.iph->ihl*4 + sizeof(struct tcphdr),
-			  opt, optlen) < 0) {
+	op = skb_header_pointer(skb,
+				skb->nh.iph->ihl*4 + sizeof(struct tcphdr),
+				optlen, _opt);
+	if (op == NULL) {
 		*hotdrop = 1;
 		return 0;
 	}
 
 	for (i = 0; i < optlen; ) {
-		if (opt[i] == option) return !invert;
-		if (opt[i] < 2) i++;
-		else i += opt[i+1]?:1;
+		if (op[i] == option) return !invert;
+		if (op[i] < 2) i++;
+		else i += op[i+1]?:1;
 	}
 
 	return invert;
@@ -1486,7 +1494,7 @@
 	  int offset,
 	  int *hotdrop)
 {
-	struct tcphdr tcph;
+	struct tcphdr _tcph, *th;
 	const struct ipt_tcp *tcpinfo = matchinfo;
 
 	if (offset) {
@@ -1506,7 +1514,9 @@
 
 #define FWINVTCP(bool,invflg) ((bool) ^ !!(tcpinfo->invflags & invflg))
 
-	if (skb_copy_bits(skb, skb->nh.iph->ihl*4, &tcph, sizeof(tcph)) < 0) {
+	th = skb_header_pointer(skb, skb->nh.iph->ihl*4,
+				sizeof(_tcph), &_tcph);
+	if (th == NULL) {
 		/* We've been asked to examine this packet, and we
 		   can't.  Hence, no choice but to drop. */
 		duprintf("Dropping evil TCP offset=0 tinygram.\n");
@@ -1515,23 +1525,24 @@
 	}
 
 	if (!port_match(tcpinfo->spts[0], tcpinfo->spts[1],
-			ntohs(tcph.source),
+			ntohs(th->source),
 			!!(tcpinfo->invflags & IPT_TCP_INV_SRCPT)))
 		return 0;
 	if (!port_match(tcpinfo->dpts[0], tcpinfo->dpts[1],
-			ntohs(tcph.dest),
+			ntohs(th->dest),
 			!!(tcpinfo->invflags & IPT_TCP_INV_DSTPT)))
 		return 0;
-	if (!FWINVTCP((((unsigned char *)&tcph)[13] & tcpinfo->flg_mask)
+	if (!FWINVTCP((((unsigned char *)th)[13] & tcpinfo->flg_mask)
 		      == tcpinfo->flg_cmp,
 		      IPT_TCP_INV_FLAGS))
 		return 0;
 	if (tcpinfo->option) {
-		if (tcph.doff * 4 < sizeof(tcph)) {
+		if (th->doff * 4 < sizeof(_tcph)) {
 			*hotdrop = 1;
 			return 0;
 		}
-		if (!tcp_find_option(tcpinfo->option, skb, tcph.doff*4 - sizeof(tcph),
+		if (!tcp_find_option(tcpinfo->option, skb,
+				     th->doff*4 - sizeof(_tcph),
 				     tcpinfo->invflags & IPT_TCP_INV_OPTION,
 				     hotdrop))
 			return 0;
@@ -1564,14 +1575,16 @@
 	  int offset,
 	  int *hotdrop)
 {
-	struct udphdr udph;
+	struct udphdr _udph, *uh;
 	const struct ipt_udp *udpinfo = matchinfo;
 
 	/* Must not be a fragment. */
 	if (offset)
 		return 0;
 
-	if (skb_copy_bits(skb, skb->nh.iph->ihl*4, &udph, sizeof(udph)) < 0) {
+	uh = skb_header_pointer(skb, skb->nh.iph->ihl*4,
+				sizeof(_udph), &_udph);
+	if (uh == NULL) {
 		/* We've been asked to examine this packet, and we
 		   can't.  Hence, no choice but to drop. */
 		duprintf("Dropping evil UDP tinygram.\n");
@@ -1580,10 +1593,10 @@
 	}
 
 	return port_match(udpinfo->spts[0], udpinfo->spts[1],
-			  ntohs(udph.source),
+			  ntohs(uh->source),
 			  !!(udpinfo->invflags & IPT_UDP_INV_SRCPT))
 		&& port_match(udpinfo->dpts[0], udpinfo->dpts[1],
-			      ntohs(udph.dest),
+			      ntohs(uh->dest),
 			      !!(udpinfo->invflags & IPT_UDP_INV_DSTPT));
 }
 
@@ -1635,16 +1648,19 @@
 	   int offset,
 	   int *hotdrop)
 {
-	struct icmphdr icmph;
+	struct icmphdr _icmph, *ic;
 	const struct ipt_icmp *icmpinfo = matchinfo;
 
 	/* Must not be a fragment. */
 	if (offset)
 		return 0;
 
-	if (skb_copy_bits(skb, skb->nh.iph->ihl*4, &icmph, sizeof(icmph)) < 0){
+	ic = skb_header_pointer(skb, skb->nh.iph->ihl*4,
+				sizeof(_icmph), &_icmph);
+	if (ic == NULL) {
 		/* We've been asked to examine this packet, and we
-		   can't.  Hence, no choice but to drop. */
+		 * can't.  Hence, no choice but to drop.
+		 */
 		duprintf("Dropping evil ICMP tinygram.\n");
 		*hotdrop = 1;
 		return 0;
@@ -1653,7 +1669,7 @@
 	return icmp_type_code_match(icmpinfo->type,
 				    icmpinfo->code[0],
 				    icmpinfo->code[1],
-				    icmph.type, icmph.code,
+				    ic->type, ic->code,
 				    !!(icmpinfo->invflags&IPT_ICMP_INV));
 }
 
diff -Nru a/net/ipv4/netfilter/ipchains_core.c b/net/ipv4/netfilter/ipchains_core.c
--- a/net/ipv4/netfilter/ipchains_core.c	2004-10-18 14:56:50 -07:00
+++ b/net/ipv4/netfilter/ipchains_core.c	2004-10-18 14:56:50 -07:00
@@ -1,3 +1,5 @@
+#warning ipchains is obsolete, and will be removed soon.
+
 /* Minor modifications to fit on compatibility framework:
    Rusty.Russell@rustcorp.com.au
 */
@@ -679,49 +681,53 @@
 		case IPPROTO_TCP:
 			dprintf("TCP ");
 			if (!offset) {
-				struct tcphdr tcph;
+				struct tcphdr _tcph, *th;
 
-				if (skb_copy_bits(*pskb,
-						  (*pskb)->nh.iph->ihl * 4,
-						  &tcph, sizeof(tcph)))
+				th = skb_header_pointer(*pskb,
+							(*pskb)->nh.iph->ihl*4,
+							sizeof(_tcph), &_tcph);
+				if (th == NULL)
 					return FW_BLOCK;
 
-				src_port = ntohs(tcph.source);
-				dst_port = ntohs(tcph.dest);
+				src_port = ntohs(th->source);
+				dst_port = ntohs(th->dest);
 
 				/* Connection initilisation can only
 				 * be made when the syn bit is set and
 				 * neither of the ack or reset is
 				 * set. */
-				if (tcph.syn && !(tcph.ack || tcph.rst))
+				if (th->syn && !(th->ack || th->rst))
 					tcpsyn = 1;
 			}
 			break;
 		case IPPROTO_UDP:
 			dprintf("UDP ");
 			if (!offset) {
-				struct udphdr udph;
+				struct udphdr _udph, *uh;
 
-				if (skb_copy_bits(*pskb,
-						  (*pskb)->nh.iph->ihl * 4,
-						  &udph, sizeof(udph)))
+				uh = skb_header_pointer(*pskb,
+							(*pskb)->nh.iph->ihl*4,
+							sizeof(_udph), &_udph);
+				if (uh == NULL)
 					return FW_BLOCK;
 
-				src_port = ntohs(udph.source);
-				dst_port = ntohs(udph.dest);
+				src_port = ntohs(uh->source);
+				dst_port = ntohs(uh->dest);
 			}
 			break;
 		case IPPROTO_ICMP:
 			if (!offset) {
-				struct icmphdr icmph;
+				struct icmphdr _icmph, *ic;
 
-				if (skb_copy_bits(*pskb,
-						  (*pskb)->nh.iph->ihl * 4,
-						  &icmph, sizeof(icmph)))
+				ic = skb_header_pointer(*pskb,
+							(*pskb)->nh.iph->ihl*4,
+							sizeof(_icmph),
+							&_icmph);
+				if (ic == NULL)
 					return FW_BLOCK;
 
-				src_port = (__u16) icmph.type;
-				dst_port = (__u16) icmph.code;
+				src_port = (__u16) ic->type;
+				dst_port = (__u16) ic->code;
 			}
 			dprintf("ICMP ");
 			break;
diff -Nru a/net/ipv4/netfilter/ipfwadm_core.c b/net/ipv4/netfilter/ipfwadm_core.c
--- a/net/ipv4/netfilter/ipfwadm_core.c	2004-10-18 14:56:29 -07:00
+++ b/net/ipv4/netfilter/ipfwadm_core.c	2004-10-18 14:56:29 -07:00
@@ -1,3 +1,5 @@
+#warning ipfwadm is obsolete, and will be removed soon.
+
 /* Minor modifications to fit on compatibility framework:
    Rusty.Russell@rustcorp.com.au
 */
@@ -410,20 +412,21 @@
 			dprintf1("TCP ");
 			/* ports stay 0xFFFF if it is not the first fragment */
 			if (!offset) {
-				struct tcphdr tcph;
+				struct tcphdr _tcph, *th;
 
-				if (skb_copy_bits(*pskb,
-						  (*pskb)->nh.iph->ihl * 4,
-						  &tcph, sizeof(tcph)))
+				th = skb_header_pointer(*pskb,
+							(*pskb)->nh.iph->ihl*4,
+							sizeof(_tcph), &_tcph);
+				if (th == NULL)
 					return FW_BLOCK;
 
-				src_port = ntohs(tcph.source);
-				dst_port = ntohs(tcph.dest);
+				src_port = ntohs(th->source);
+				dst_port = ntohs(th->dest);
 
-				if(!tcph.ack && !tcph.rst)
+				if(!th->ack && !th->rst)
 					/* We do NOT have ACK, value TRUE */
 					notcpack = 1;
-				if(!tcph.syn || !notcpack)
+				if(!th->syn || !notcpack)
 					/* We do NOT have SYN, value TRUE */
 					notcpsyn = 1;
 			}
@@ -433,29 +436,32 @@
 			dprintf1("UDP ");
 			/* ports stay 0xFFFF if it is not the first fragment */
 			if (!offset) {
-				struct udphdr udph;
+				struct udphdr _udph, *uh;
 
-				if (skb_copy_bits(*pskb,
-						  (*pskb)->nh.iph->ihl * 4,
-						  &udph, sizeof(udph)))
+				uh = skb_header_pointer(*pskb,
+							(*pskb)->nh.iph->ihl*4,
+							sizeof(_udph), &_udph);
+				if (uh == NULL)
 					return FW_BLOCK;
 
-				src_port = ntohs(udph.source);
-				dst_port = ntohs(udph.dest);
+				src_port = ntohs(uh->source);
+				dst_port = ntohs(uh->dest);
 			}
 			prt = IP_FW_F_UDP;
 			break;
 		case IPPROTO_ICMP:
 			/* icmp_type stays 255 if it is not the first fragment */
 			if (!offset) {
-				struct icmphdr icmph;
+				struct icmphdr _icmph, *ic;
 
-				if (skb_copy_bits(*pskb,
-						  (*pskb)->nh.iph->ihl * 4,
-						  &icmph, sizeof(icmph)))
+				ic = skb_header_pointer(*pskb,
+							(*pskb)->nh.iph->ihl*4,
+							sizeof(_icmph),
+							&_icmph);
+				if (ic == NULL)
 					return FW_BLOCK;
 
-				icmp_type = (__u16) icmph.type;
+				icmp_type = (__u16) ic->type;
 			}
 			dprintf2("ICMP:%d ", icmp_type);
 			prt = IP_FW_F_ICMP;
diff -Nru a/net/ipv4/netfilter/ipt_ECN.c b/net/ipv4/netfilter/ipt_ECN.c
--- a/net/ipv4/netfilter/ipt_ECN.c	2004-10-18 14:57:04 -07:00
+++ b/net/ipv4/netfilter/ipt_ECN.c	2004-10-18 14:57:04 -07:00
@@ -52,34 +52,39 @@
 static inline int
 set_ect_tcp(struct sk_buff **pskb, const struct ipt_ECN_info *einfo, int inward)
 {
-	struct tcphdr tcph;
+	struct tcphdr _tcph, *th;
 	u_int16_t diffs[2];
 
 	/* Not enought header? */
-	if (skb_copy_bits(*pskb, (*pskb)->nh.iph->ihl*4, &tcph, sizeof(tcph))
-	    < 0)
+	th = skb_header_pointer(*pskb, (*pskb)->nh.iph->ihl*4,
+				sizeof(_tcph), &_tcph);
+	if (th == NULL)
 		return 0;
 
-	diffs[0] = ((u_int16_t *)&tcph)[6];
+	diffs[0] = ((u_int16_t *)th)[6];
 	if (einfo->operation & IPT_ECN_OP_SET_ECE)
-		tcph.ece = einfo->proto.tcp.ece;
+		th->ece = einfo->proto.tcp.ece;
 
 	if (einfo->operation & IPT_ECN_OP_SET_CWR)
-		tcph.cwr = einfo->proto.tcp.cwr;
-	diffs[1] = ((u_int16_t *)&tcph)[6];
+		th->cwr = einfo->proto.tcp.cwr;
+	diffs[1] = ((u_int16_t *)&th)[6];
 
 	/* Only mangle if it's changed. */
 	if (diffs[0] != diffs[1]) {
 		diffs[0] = diffs[0] ^ 0xFFFF;
 		if (!skb_ip_make_writable(pskb,
-					  (*pskb)->nh.iph->ihl*4+sizeof(tcph)))
+					  (*pskb)->nh.iph->ihl*4+sizeof(_tcph)))
 			return 0;
+
+		if (th != &_tcph)
+			memcpy(&_tcph, th, sizeof(_tcph));
+
 		if ((*pskb)->ip_summed != CHECKSUM_HW)
-			tcph.check = csum_fold(csum_partial((char *)diffs,
-					       sizeof(diffs),
-					       tcph.check^0xFFFF));
+			_tcph.check = csum_fold(csum_partial((char *)diffs,
+							     sizeof(diffs),
+							     _tcph.check^0xFFFF));
 		memcpy((*pskb)->data + (*pskb)->nh.iph->ihl*4,
-		       &tcph, sizeof(tcph));
+		       &_tcph, sizeof(_tcph));
 		if ((*pskb)->ip_summed == CHECKSUM_HW)
 			if (skb_checksum_help(pskb, inward))
 				return 0;
diff -Nru a/net/ipv4/netfilter/ipt_LOG.c b/net/ipv4/netfilter/ipt_LOG.c
--- a/net/ipv4/netfilter/ipt_LOG.c	2004-10-18 14:56:50 -07:00
+++ b/net/ipv4/netfilter/ipt_LOG.c	2004-10-18 14:56:50 -07:00
@@ -28,7 +28,7 @@
 MODULE_DESCRIPTION("iptables syslog logging module");
 
 static unsigned int nflog = 1;
-MODULE_PARM(nflog, "i");
+module_param(nflog, int, 0400);
 MODULE_PARM_DESC(nflog, "register as internal netfilter logging module");
  
 #if 0
@@ -45,9 +45,10 @@
 			const struct sk_buff *skb,
 			unsigned int iphoff)
 {
-	struct iphdr iph;
+	struct iphdr _iph, *ih;
 
-	if (skb_copy_bits(skb, iphoff, &iph, sizeof(iph)) < 0) {
+	ih = skb_header_pointer(skb, iphoff, sizeof(_iph), &_iph);
+	if (ih == NULL) {
 		printk("TRUNCATED");
 		return;
 	}
@@ -56,32 +57,34 @@
 	 * TOS, len, DF/MF, fragment offset, TTL, src, dst, options. */
 	/* Max length: 40 "SRC=255.255.255.255 DST=255.255.255.255 " */
 	printk("SRC=%u.%u.%u.%u DST=%u.%u.%u.%u ",
-	       NIPQUAD(iph.saddr), NIPQUAD(iph.daddr));
+	       NIPQUAD(ih->saddr), NIPQUAD(ih->daddr));
 
 	/* Max length: 46 "LEN=65535 TOS=0xFF PREC=0xFF TTL=255 ID=65535 " */
 	printk("LEN=%u TOS=0x%02X PREC=0x%02X TTL=%u ID=%u ",
-	       ntohs(iph.tot_len), iph.tos & IPTOS_TOS_MASK,
-	       iph.tos & IPTOS_PREC_MASK, iph.ttl, ntohs(iph.id));
+	       ntohs(ih->tot_len), ih->tos & IPTOS_TOS_MASK,
+	       ih->tos & IPTOS_PREC_MASK, ih->ttl, ntohs(ih->id));
 
 	/* Max length: 6 "CE DF MF " */
-	if (ntohs(iph.frag_off) & IP_CE)
+	if (ntohs(ih->frag_off) & IP_CE)
 		printk("CE ");
-	if (ntohs(iph.frag_off) & IP_DF)
+	if (ntohs(ih->frag_off) & IP_DF)
 		printk("DF ");
-	if (ntohs(iph.frag_off) & IP_MF)
+	if (ntohs(ih->frag_off) & IP_MF)
 		printk("MF ");
 
 	/* Max length: 11 "FRAG:65535 " */
-	if (ntohs(iph.frag_off) & IP_OFFSET)
-		printk("FRAG:%u ", ntohs(iph.frag_off) & IP_OFFSET);
+	if (ntohs(ih->frag_off) & IP_OFFSET)
+		printk("FRAG:%u ", ntohs(ih->frag_off) & IP_OFFSET);
 
 	if ((info->logflags & IPT_LOG_IPOPT)
-	    && iph.ihl * 4 > sizeof(struct iphdr)) {
-		unsigned char opt[4 * 15 - sizeof(struct iphdr)];
+	    && ih->ihl * 4 > sizeof(struct iphdr)) {
+		unsigned char _opt[4 * 15 - sizeof(struct iphdr)], *op;
 		unsigned int i, optsize;
 
-		optsize = iph.ihl * 4 - sizeof(struct iphdr);
-		if (skb_copy_bits(skb, iphoff+sizeof(iph), opt, optsize) < 0) {
+		optsize = ih->ihl * 4 - sizeof(struct iphdr);
+		op = skb_header_pointer(skb, iphoff+sizeof(_iph),
+					optsize, _opt);
+		if (op == NULL) {
 			printk("TRUNCATED");
 			return;
 		}
@@ -89,67 +92,71 @@
 		/* Max length: 127 "OPT (" 15*4*2chars ") " */
 		printk("OPT (");
 		for (i = 0; i < optsize; i++)
-			printk("%02X", opt[i]);
+			printk("%02X", op[i]);
 		printk(") ");
 	}
 
-	switch (iph.protocol) {
+	switch (ih->protocol) {
 	case IPPROTO_TCP: {
-		struct tcphdr tcph;
+		struct tcphdr _tcph, *th;
 
 		/* Max length: 10 "PROTO=TCP " */
 		printk("PROTO=TCP ");
 
-		if (ntohs(iph.frag_off) & IP_OFFSET)
+		if (ntohs(ih->frag_off) & IP_OFFSET)
 			break;
 
 		/* Max length: 25 "INCOMPLETE [65535 bytes] " */
-		if (skb_copy_bits(skb, iphoff+iph.ihl*4, &tcph, sizeof(tcph))
-		    < 0) {
+		th = skb_header_pointer(skb, iphoff + ih->ihl * 4,
+					sizeof(_tcph), &_tcph);
+		if (th == NULL) {
 			printk("INCOMPLETE [%u bytes] ",
-			       skb->len - iphoff - iph.ihl*4);
+			       skb->len - iphoff - ih->ihl*4);
 			break;
 		}
 
 		/* Max length: 20 "SPT=65535 DPT=65535 " */
 		printk("SPT=%u DPT=%u ",
-		       ntohs(tcph.source), ntohs(tcph.dest));
+		       ntohs(th->source), ntohs(th->dest));
 		/* Max length: 30 "SEQ=4294967295 ACK=4294967295 " */
 		if (info->logflags & IPT_LOG_TCPSEQ)
 			printk("SEQ=%u ACK=%u ",
-			       ntohl(tcph.seq), ntohl(tcph.ack_seq));
+			       ntohl(th->seq), ntohl(th->ack_seq));
 		/* Max length: 13 "WINDOW=65535 " */
-		printk("WINDOW=%u ", ntohs(tcph.window));
+		printk("WINDOW=%u ", ntohs(th->window));
 		/* Max length: 9 "RES=0x3F " */
-		printk("RES=0x%02x ", (u8)(ntohl(tcp_flag_word(&tcph) & TCP_RESERVED_BITS) >> 22));
+		printk("RES=0x%02x ", (u8)(ntohl(tcp_flag_word(th) & TCP_RESERVED_BITS) >> 22));
 		/* Max length: 32 "CWR ECE URG ACK PSH RST SYN FIN " */
-		if (tcph.cwr)
+		if (th->cwr)
 			printk("CWR ");
-		if (tcph.ece)
+		if (th->ece)
 			printk("ECE ");
-		if (tcph.urg)
+		if (th->urg)
 			printk("URG ");
-		if (tcph.ack)
+		if (th->ack)
 			printk("ACK ");
-		if (tcph.psh)
+		if (th->psh)
 			printk("PSH ");
-		if (tcph.rst)
+		if (th->rst)
 			printk("RST ");
-		if (tcph.syn)
+		if (th->syn)
 			printk("SYN ");
-		if (tcph.fin)
+		if (th->fin)
 			printk("FIN ");
 		/* Max length: 11 "URGP=65535 " */
-		printk("URGP=%u ", ntohs(tcph.urg_ptr));
+		printk("URGP=%u ", ntohs(th->urg_ptr));
 
 		if ((info->logflags & IPT_LOG_TCPOPT)
-		    && tcph.doff * 4 > sizeof(struct tcphdr)) {
-			unsigned char opt[4 * 15 - sizeof(struct tcphdr)];
+		    && th->doff * 4 > sizeof(struct tcphdr)) {
+			unsigned char _opt[4 * 15 - sizeof(struct tcphdr)];
+			unsigned char *op;
 			unsigned int i, optsize;
 
-			optsize = tcph.doff * 4 - sizeof(struct tcphdr);
-			if (skb_copy_bits(skb, iphoff+iph.ihl*4 + sizeof(tcph),
-					  opt, optsize) < 0) {
+			optsize = th->doff * 4 - sizeof(struct tcphdr);
+			op = skb_header_pointer(skb,
+						iphoff+ih->ihl*4+sizeof(_tcph),
+						optsize, _opt);
+			if (op == NULL) {
 				printk("TRUNCATED");
 				return;
 			}
@@ -157,36 +164,37 @@
 			/* Max length: 127 "OPT (" 15*4*2chars ") " */
 			printk("OPT (");
 			for (i = 0; i < optsize; i++)
-				printk("%02X", opt[i]);
+				printk("%02X", op[i]);
 			printk(") ");
 		}
 		break;
 	}
 	case IPPROTO_UDP: {
-		struct udphdr udph;
+		struct udphdr _udph, *uh;
 
 		/* Max length: 10 "PROTO=UDP " */
 		printk("PROTO=UDP ");
 
-		if (ntohs(iph.frag_off) & IP_OFFSET)
+		if (ntohs(ih->frag_off) & IP_OFFSET)
 			break;
 
 		/* Max length: 25 "INCOMPLETE [65535 bytes] " */
-		if (skb_copy_bits(skb, iphoff+iph.ihl*4, &udph, sizeof(udph))
-		    < 0) {
+		uh = skb_header_pointer(skb, iphoff+ih->ihl*4,
+					sizeof(_udph), &_udph);
+		if (uh == NULL) {
 			printk("INCOMPLETE [%u bytes] ",
-			       skb->len - iphoff - iph.ihl*4);
+			       skb->len - iphoff - ih->ihl*4);
 			break;
 		}
 
 		/* Max length: 20 "SPT=65535 DPT=65535 " */
 		printk("SPT=%u DPT=%u LEN=%u ",
-		       ntohs(udph.source), ntohs(udph.dest),
-		       ntohs(udph.len));
+		       ntohs(uh->source), ntohs(uh->dest),
+		       ntohs(uh->len));
 		break;
 	}
 	case IPPROTO_ICMP: {
-		struct icmphdr icmph;
+		struct icmphdr _icmph, *ich;
 		static size_t required_len[NR_ICMP_TYPES+1]
 			= { [ICMP_ECHOREPLY] = 4,
 			    [ICMP_DEST_UNREACH]
@@ -208,47 +216,48 @@
 		/* Max length: 11 "PROTO=ICMP " */
 		printk("PROTO=ICMP ");
 
-		if (ntohs(iph.frag_off) & IP_OFFSET)
+		if (ntohs(ih->frag_off) & IP_OFFSET)
 			break;
 
 		/* Max length: 25 "INCOMPLETE [65535 bytes] " */
-		if (skb_copy_bits(skb, iphoff+iph.ihl*4, &icmph, sizeof(icmph))
-		    < 0) {
+		ich = skb_header_pointer(skb, iphoff + ih->ihl * 4,
+					 sizeof(_icmph), &_icmph);
+		if (ich == NULL) {
 			printk("INCOMPLETE [%u bytes] ",
-			       skb->len - iphoff - iph.ihl*4);
+			       skb->len - iphoff - ih->ihl*4);
 			break;
 		}
 
 		/* Max length: 18 "TYPE=255 CODE=255 " */
-		printk("TYPE=%u CODE=%u ", icmph.type, icmph.code);
+		printk("TYPE=%u CODE=%u ", ich->type, ich->code);
 
 		/* Max length: 25 "INCOMPLETE [65535 bytes] " */
-		if (icmph.type <= NR_ICMP_TYPES
-		    && required_len[icmph.type]
-		    && skb->len-iphoff-iph.ihl*4 < required_len[icmph.type]) {
+		if (ich->type <= NR_ICMP_TYPES
+		    && required_len[ich->type]
+		    && skb->len-iphoff-ih->ihl*4 < required_len[ich->type]) {
 			printk("INCOMPLETE [%u bytes] ",
-			       skb->len - iphoff - iph.ihl*4);
+			       skb->len - iphoff - ih->ihl*4);
 			break;
 		}
 
-		switch (icmph.type) {
+		switch (ich->type) {
 		case ICMP_ECHOREPLY:
 		case ICMP_ECHO:
 			/* Max length: 19 "ID=65535 SEQ=65535 " */
 			printk("ID=%u SEQ=%u ",
-			       ntohs(icmph.un.echo.id),
-			       ntohs(icmph.un.echo.sequence));
+			       ntohs(ich->un.echo.id),
+			       ntohs(ich->un.echo.sequence));
 			break;
 
 		case ICMP_PARAMETERPROB:
 			/* Max length: 14 "PARAMETER=255 " */
 			printk("PARAMETER=%u ",
-			       ntohl(icmph.un.gateway) >> 24);
+			       ntohl(ich->un.gateway) >> 24);
 			break;
 		case ICMP_REDIRECT:
 			/* Max length: 24 "GATEWAY=255.255.255.255 " */
 			printk("GATEWAY=%u.%u.%u.%u ",
-			       NIPQUAD(icmph.un.gateway));
+			       NIPQUAD(ich->un.gateway));
 			/* Fall through */
 		case ICMP_DEST_UNREACH:
 		case ICMP_SOURCE_QUENCH:
@@ -257,62 +266,65 @@
 			if (!iphoff) { /* Only recurse once. */
 				printk("[");
 				dump_packet(info, skb,
-					    iphoff + iph.ihl*4+sizeof(icmph));
+					    iphoff + ih->ihl*4+sizeof(_icmph));
 				printk("] ");
 			}
 
 			/* Max length: 10 "MTU=65535 " */
-			if (icmph.type == ICMP_DEST_UNREACH
-			    && icmph.code == ICMP_FRAG_NEEDED)
-				printk("MTU=%u ", ntohs(icmph.un.frag.mtu));
+			if (ich->type == ICMP_DEST_UNREACH
+			    && ich->code == ICMP_FRAG_NEEDED)
+				printk("MTU=%u ", ntohs(ich->un.frag.mtu));
 		}
 		break;
 	}
 	/* Max Length */
 	case IPPROTO_AH: {
-		struct ip_auth_hdr ah;
+		struct ip_auth_hdr _ahdr, *ah;
 
-		if (ntohs(iph.frag_off) & IP_OFFSET)
+		if (ntohs(ih->frag_off) & IP_OFFSET)
 			break;
 		
 		/* Max length: 9 "PROTO=AH " */
 		printk("PROTO=AH ");
 
 		/* Max length: 25 "INCOMPLETE [65535 bytes] " */
-		if (skb_copy_bits(skb, iphoff+iph.ihl*4, &ah, sizeof(ah)) < 0) {
+		ah = skb_header_pointer(skb, iphoff+ih->ihl*4,
+					sizeof(_ahdr), &_ahdr);
+		if (ah == NULL) {
 			printk("INCOMPLETE [%u bytes] ",
-			       skb->len - iphoff - iph.ihl*4);
+			       skb->len - iphoff - ih->ihl*4);
 			break;
 		}
 
 		/* Length: 15 "SPI=0xF1234567 " */
-		printk("SPI=0x%x ", ntohl(ah.spi));
+		printk("SPI=0x%x ", ntohl(ah->spi));
 		break;
 	}
 	case IPPROTO_ESP: {
-		struct ip_esp_hdr esph;
+		struct ip_esp_hdr _esph, *eh;
 
 		/* Max length: 10 "PROTO=ESP " */
 		printk("PROTO=ESP ");
 
-		if (ntohs(iph.frag_off) & IP_OFFSET)
+		if (ntohs(ih->frag_off) & IP_OFFSET)
 			break;
 
 		/* Max length: 25 "INCOMPLETE [65535 bytes] " */
-		if (skb_copy_bits(skb, iphoff+iph.ihl*4, &esph, sizeof(esph))
-		    < 0) {
+		eh = skb_header_pointer(skb, iphoff+ih->ihl*4,
+					sizeof(_esph), &_esph);
+		if (eh == NULL) {
 			printk("INCOMPLETE [%u bytes] ",
-			       skb->len - iphoff - iph.ihl*4);
+			       skb->len - iphoff - ih->ihl*4);
 			break;
 		}
 
 		/* Length: 15 "SPI=0xF1234567 " */
-		printk("SPI=0x%x ", ntohl(esph.spi));
+		printk("SPI=0x%x ", ntohl(eh->spi));
 		break;
 	}
 	/* Max length: 10 "PROTO 255 " */
 	default:
-		printk("PROTO=%u ", iph.protocol);
+		printk("PROTO=%u ", ih->protocol);
 	}
 
 	/* Proto    Max log string length */
diff -Nru a/net/ipv4/netfilter/ipt_MASQUERADE.c b/net/ipv4/netfilter/ipt_MASQUERADE.c
--- a/net/ipv4/netfilter/ipt_MASQUERADE.c	2004-10-18 14:56:33 -07:00
+++ b/net/ipv4/netfilter/ipt_MASQUERADE.c	2004-10-18 14:56:33 -07:00
@@ -92,8 +92,8 @@
 		return NF_ACCEPT;
 
 	ct = ip_conntrack_get(*pskb, &ctinfo);
-	IP_NF_ASSERT(ct && (ctinfo == IP_CT_NEW
-				  || ctinfo == IP_CT_RELATED));
+	IP_NF_ASSERT(ct && (ctinfo == IP_CT_NEW || ctinfo == IP_CT_RELATED
+	                    || ctinfo == IP_CT_RELATED + IP_CT_IS_REPLY));
 
 	mr = targinfo;
 
diff -Nru a/net/ipv4/netfilter/ipt_NOTRACK.c b/net/ipv4/netfilter/ipt_NOTRACK.c
--- a/net/ipv4/netfilter/ipt_NOTRACK.c	2004-10-18 14:55:54 -07:00
+++ b/net/ipv4/netfilter/ipt_NOTRACK.c	2004-10-18 14:55:54 -07:00
@@ -23,7 +23,8 @@
 	   If there is a real ct entry correspondig to this packet, 
 	   it'll hang aroun till timing out. We don't deal with it
 	   for performance reasons. JK */
-	(*pskb)->nfct = &ip_conntrack_untracked.infos[IP_CT_NEW];
+	(*pskb)->nfct = &ip_conntrack_untracked.ct_general;
+	(*pskb)->nfctinfo = IP_CT_NEW;
 	nf_conntrack_get((*pskb)->nfct);
 
 	return IPT_CONTINUE;
diff -Nru a/net/ipv4/netfilter/ipt_REJECT.c b/net/ipv4/netfilter/ipt_REJECT.c
--- a/net/ipv4/netfilter/ipt_REJECT.c	2004-10-18 14:56:49 -07:00
+++ b/net/ipv4/netfilter/ipt_REJECT.c	2004-10-18 14:56:49 -07:00
@@ -41,14 +41,14 @@
 /* If the original packet is part of a connection, but the connection
    is not confirmed, our manufactured reply will not be associated
    with it, so we need to do this manually. */
-static void connection_attach(struct sk_buff *new_skb, struct nf_ct_info *nfct)
+static void connection_attach(struct sk_buff *new_skb, struct sk_buff *skb)
 {
-	void (*attach)(struct sk_buff *, struct nf_ct_info *);
+	void (*attach)(struct sk_buff *, struct sk_buff *);
 
 	/* Avoid module unload race with ip_ct_attach being NULLed out */
-	if (nfct && (attach = ip_ct_attach) != NULL) {
+	if (skb->nfct && (attach = ip_ct_attach) != NULL) {
 		mb(); /* Just to be sure: must be read before executing this */
-		attach(new_skb, nfct);
+		attach(new_skb, skb);
 	}
 }
 
@@ -103,7 +103,7 @@
 static void send_reset(struct sk_buff *oldskb, int hook)
 {
 	struct sk_buff *nskb;
-	struct tcphdr otcph, *tcph;
+	struct tcphdr _otcph, *oth, *tcph;
 	struct rtable *rt;
 	u_int16_t tmp_port;
 	u_int32_t tmp_addr;
@@ -114,12 +114,13 @@
 	if (oldskb->nh.iph->frag_off & htons(IP_OFFSET))
 		return;
 
-	if (skb_copy_bits(oldskb, oldskb->nh.iph->ihl*4,
-			  &otcph, sizeof(otcph)) < 0)
+	oth = skb_header_pointer(oldskb, oldskb->nh.iph->ihl * 4,
+				 sizeof(_otcph), &_otcph);
+	if (oth == NULL)
  		return;
 
 	/* No RST for RST. */
-	if (otcph.rst)
+	if (oth->rst)
 		return;
 
 	/* FIXME: Check checksum --RR */
@@ -167,13 +168,13 @@
 
 	if (tcph->ack) {
 		needs_ack = 0;
-		tcph->seq = otcph.ack_seq;
+		tcph->seq = oth->ack_seq;
 		tcph->ack_seq = 0;
 	} else {
 		needs_ack = 1;
-		tcph->ack_seq = htonl(ntohl(otcph.seq) + otcph.syn + otcph.fin
+		tcph->ack_seq = htonl(ntohl(oth->seq) + oth->syn + oth->fin
 				      + oldskb->len - oldskb->nh.iph->ihl*4
-				      - (otcph.doff<<2));
+				      - (oth->doff<<2));
 		tcph->seq = 0;
 	}
 
@@ -208,7 +209,7 @@
 	if (nskb->len > dst_pmtu(nskb->dst))
 		goto free_nskb;
 
-	connection_attach(nskb, oldskb->nfct);
+	connection_attach(nskb, oldskb);
 
 	NF_HOOK(PF_INET, NF_IP_LOCAL_OUT, nskb, NULL, nskb->dst->dev,
 		ip_finish_output);
@@ -359,7 +360,7 @@
 	icmph->checksum = ip_compute_csum((unsigned char *)icmph,
 					  length - sizeof(struct iphdr));
 
-	connection_attach(nskb, skb_in->nfct);
+	connection_attach(nskb, skb_in);
 
 	NF_HOOK(PF_INET, NF_IP_LOCAL_OUT, nskb, NULL, nskb->dst->dev,
 		ip_finish_output);
diff -Nru a/net/ipv4/netfilter/ipt_ULOG.c b/net/ipv4/netfilter/ipt_ULOG.c
--- a/net/ipv4/netfilter/ipt_ULOG.c	2004-10-18 14:56:28 -07:00
+++ b/net/ipv4/netfilter/ipt_ULOG.c	2004-10-18 14:56:28 -07:00
@@ -34,8 +34,8 @@
  * by that factor.
  *
  * flushtimeout:
- *   Specify, after how many clock ticks (intel: 100 per second) the queue
- * should be flushed even if it is not full yet.
+ *   Specify, after how many hundredths of a second the queue should be
+ *   flushed even if it is not full yet.
  *
  * ipt_ULOG.c,v 1.22 2002/10/30 09:07:31 laforge Exp
  */
@@ -50,6 +50,7 @@
 #include <linux/netlink.h>
 #include <linux/netdevice.h>
 #include <linux/mm.h>
+#include <linux/moduleparam.h>
 #include <linux/netfilter.h>
 #include <linux/netfilter_ipv4/ip_tables.h>
 #include <linux/netfilter_ipv4/ipt_ULOG.h>
@@ -74,15 +75,15 @@
 #define PRINTR(format, args...) do { if (net_ratelimit()) printk(format , ## args); } while (0)
 
 static unsigned int nlbufsiz = 4096;
-MODULE_PARM(nlbufsiz, "i");
+module_param(nlbufsiz, uint, 0600); /* FIXME: Check size < 128k --RR */
 MODULE_PARM_DESC(nlbufsiz, "netlink buffer size");
 
-static unsigned int flushtimeout = 10 * HZ;
-MODULE_PARM(flushtimeout, "i");
-MODULE_PARM_DESC(flushtimeout, "buffer flush timeout");
+static unsigned int flushtimeout = 10;
+module_param(flushtimeout, int, 0600);
+MODULE_PARM_DESC(flushtimeout, "buffer flush timeout (hundredths of a second)");
 
 static unsigned int nflog = 1;
-MODULE_PARM(nflog, "i");
+module_param(nflog, int, 0400);
 MODULE_PARM_DESC(nflog, "register as internal netfilter logging module");
 
 /* global data structures */
@@ -97,7 +98,6 @@
 static ulog_buff_t ulog_buffers[ULOG_MAXNLGROUPS];	/* array of buffers */
 
 static struct sock *nflognl;	/* our socket */
-static size_t qlen;		/* current length of multipart-nlmsg */
 DECLARE_LOCK(ulog_lock);	/* spinlock */
 
 /* send one ulog_buff_t to userspace */
@@ -116,7 +116,7 @@
 
 	NETLINK_CB(ub->skb).dst_groups = (1 << nlgroupnum);
 	DEBUGP("ipt_ULOG: throwing %d packets to netlink mask %u\n",
-		ub->qlen, nlgroup);
+		ub->qlen, nlgroupnum);
 	netlink_broadcast(nflognl, ub->skb, 0, (1 << nlgroupnum), GFP_ATOMIC);
 
 	ub->qlen = 0;
@@ -126,7 +126,7 @@
 }
 
 
-/* timer function to flush queue in ULOG_FLUSH_INTERVAL time */
+/* timer function to flush queue in flushtimeout time */
 static void ulog_timer(unsigned long data)
 {
 	DEBUGP("ipt_ULOG: timer function called, calling ulog_send\n");
@@ -261,18 +261,19 @@
 		ub->lastnlh->nlmsg_flags |= NLM_F_MULTI;
 	}
 
-	/* if threshold is reached, send message to userspace */
-	if (qlen >= loginfo->qthreshold) {
-		if (loginfo->qthreshold > 1)
-			nlh->nlmsg_type = NLMSG_DONE;
-	}
-
 	ub->lastnlh = nlh;
 
 	/* if timer isn't already running, start it */
 	if (!timer_pending(&ub->timer)) {
-		ub->timer.expires = jiffies + flushtimeout;
+		ub->timer.expires = jiffies + flushtimeout * HZ / 100;
 		add_timer(&ub->timer);
+	}
+
+	/* if threshold is reached, send message to userspace */
+	if (ub->qlen >= loginfo->qthreshold) {
+		if (loginfo->qthreshold > 1)
+			nlh->nlmsg_type = NLMSG_DONE;
+		ulog_send(groupnum);
 	}
 
 	UNLOCK_BH(&ulog_lock);
diff -Nru a/net/ipv4/netfilter/ipt_ah.c b/net/ipv4/netfilter/ipt_ah.c
--- a/net/ipv4/netfilter/ipt_ah.c	2004-10-18 14:56:33 -07:00
+++ b/net/ipv4/netfilter/ipt_ah.c	2004-10-18 14:56:33 -07:00
@@ -43,23 +43,26 @@
       int offset,
       int *hotdrop)
 {
-	struct ip_auth_hdr ah;
+	struct ip_auth_hdr _ahdr, *ah;
 	const struct ipt_ah *ahinfo = matchinfo;
 
 	/* Must not be a fragment. */
 	if (offset)
 		return 0;
 
-	if (skb_copy_bits(skb, skb->nh.iph->ihl*4, &ah, sizeof(ah)) < 0) {
+	ah = skb_header_pointer(skb, skb->nh.iph->ihl * 4,
+				sizeof(_ahdr), &_ahdr);
+	if (ah == NULL) {
 		/* We've been asked to examine this packet, and we
-		   can't.  Hence, no choice but to drop. */
+		 * can't.  Hence, no choice but to drop.
+		 */
 		duprintf("Dropping evil AH tinygram.\n");
 		*hotdrop = 1;
 		return 0;
 	}
 
 	return spi_match(ahinfo->spis[0], ahinfo->spis[1],
-			 ntohl(ah.spi),
+			 ntohl(ah->spi),
 			 !!(ahinfo->invflags & IPT_AH_INV_SPI));
 }
 
diff -Nru a/net/ipv4/netfilter/ipt_comment.c b/net/ipv4/netfilter/ipt_comment.c
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/net/ipv4/netfilter/ipt_comment.c	2004-10-18 14:57:23 -07:00
@@ -0,0 +1,59 @@
+/*
+ * Implements a dummy match to allow attaching comments to rules
+ *
+ * 2003-05-13 Brad Fisher (brad@info-link.net)
+ */
+
+#include <linux/module.h>
+#include <linux/skbuff.h>
+#include <linux/netfilter_ipv4/ip_tables.h>
+#include <linux/netfilter_ipv4/ipt_comment.h>
+
+MODULE_AUTHOR("Brad Fisher <brad@info-link.net>");
+MODULE_DESCRIPTION("iptables comment match module");
+MODULE_LICENSE("GPL");
+
+static int
+match(const struct sk_buff *skb,
+      const struct net_device *in,
+      const struct net_device *out,
+      const void *matchinfo,
+      int offset,
+      int *hotdrop)
+{
+	/* We always match */
+	return 1;
+}
+
+static int
+checkentry(const char *tablename,
+           const struct ipt_ip *ip,
+           void *matchinfo,
+           unsigned int matchsize,
+           unsigned int hook_mask)
+{
+	/* Check the size */
+	if (matchsize != IPT_ALIGN(sizeof(struct ipt_comment_info)))
+		return 0;
+	return 1;
+}
+
+static struct ipt_match comment_match = {
+	.name		= "comment",
+	.match		= match,
+	.checkentry	= checkentry,
+	.me		= THIS_MODULE
+};
+
+static int __init init(void)
+{
+	return ipt_register_match(&comment_match);
+}
+
+static void __exit fini(void)
+{
+	ipt_unregister_match(&comment_match);
+}
+
+module_init(init);
+module_exit(fini);
diff -Nru a/net/ipv4/netfilter/ipt_conntrack.c b/net/ipv4/netfilter/ipt_conntrack.c
--- a/net/ipv4/netfilter/ipt_conntrack.c	2004-10-18 14:57:03 -07:00
+++ b/net/ipv4/netfilter/ipt_conntrack.c	2004-10-18 14:57:03 -07:00
@@ -35,7 +35,7 @@
 
 #define FWINV(bool,invflg) ((bool) ^ !!(sinfo->invflags & invflg))
 
-	if (skb->nfct == &ip_conntrack_untracked.infos[IP_CT_NEW])
+	if (ct == &ip_conntrack_untracked)
 		statebit = IPT_CONNTRACK_STATE_UNTRACKED;
 	else if (ct)
  		statebit = IPT_CONNTRACK_STATE_BIT(ctinfo);
diff -Nru a/net/ipv4/netfilter/ipt_ecn.c b/net/ipv4/netfilter/ipt_ecn.c
--- a/net/ipv4/netfilter/ipt_ecn.c	2004-10-18 14:56:29 -07:00
+++ b/net/ipv4/netfilter/ipt_ecn.c	2004-10-18 14:56:29 -07:00
@@ -30,31 +30,34 @@
 			    const struct ipt_ecn_info *einfo,
 			    int *hotdrop)
 {
-	struct tcphdr tcph;
+	struct tcphdr _tcph, *th;
 
 	/* In practice, TCP match does this, so can't fail.  But let's
-           be good citizens. */
-	if (skb_copy_bits(skb, skb->nh.iph->ihl*4, &tcph, sizeof(tcph)) < 0) {
+	 * be good citizens.
+	 */
+	th = skb_header_pointer(skb, skb->nh.iph->ihl * 4,
+				sizeof(_tcph), &_tcph);
+	if (th == NULL) {
 		*hotdrop = 0;
 		return 0;
 	}
 
 	if (einfo->operation & IPT_ECN_OP_MATCH_ECE) {
 		if (einfo->invert & IPT_ECN_OP_MATCH_ECE) {
-			if (tcph.ece == 1)
+			if (th->ece == 1)
 				return 0;
 		} else {
-			if (tcph.ece == 0)
+			if (th->ece == 0)
 				return 0;
 		}
 	}
 
 	if (einfo->operation & IPT_ECN_OP_MATCH_CWR) {
 		if (einfo->invert & IPT_ECN_OP_MATCH_CWR) {
-			if (tcph.cwr == 1)
+			if (th->cwr == 1)
 				return 0;
 		} else {
-			if (tcph.cwr == 0)
+			if (th->cwr == 0)
 				return 0;
 		}
 	}
diff -Nru a/net/ipv4/netfilter/ipt_esp.c b/net/ipv4/netfilter/ipt_esp.c
--- a/net/ipv4/netfilter/ipt_esp.c	2004-10-18 14:56:32 -07:00
+++ b/net/ipv4/netfilter/ipt_esp.c	2004-10-18 14:56:32 -07:00
@@ -44,23 +44,26 @@
       int offset,
       int *hotdrop)
 {
-	struct ip_esp_hdr esp;
+	struct ip_esp_hdr _esp, *eh;
 	const struct ipt_esp *espinfo = matchinfo;
 
 	/* Must not be a fragment. */
 	if (offset)
 		return 0;
 
-	if (skb_copy_bits(skb, skb->nh.iph->ihl*4, &esp, sizeof(esp)) < 0) {
+	eh = skb_header_pointer(skb, skb->nh.iph->ihl * 4,
+				sizeof(_esp), &_esp);
+	if (eh == NULL) {
 		/* We've been asked to examine this packet, and we
-		   can't.  Hence, no choice but to drop. */
+		 * can't.  Hence, no choice but to drop.
+		 */
 		duprintf("Dropping evil ESP tinygram.\n");
 		*hotdrop = 1;
 		return 0;
 	}
 
 	return spi_match(espinfo->spis[0], espinfo->spis[1],
-			 ntohl(esp.spi),
+			 ntohl(eh->spi),
 			 !!(espinfo->invflags & IPT_ESP_INV_SPI));
 }
 
diff -Nru a/net/ipv4/netfilter/ipt_helper.c b/net/ipv4/netfilter/ipt_helper.c
--- a/net/ipv4/netfilter/ipt_helper.c	2004-10-18 14:57:20 -07:00
+++ b/net/ipv4/netfilter/ipt_helper.c	2004-10-18 14:57:20 -07:00
@@ -107,6 +107,7 @@
 
 static int __init init(void)
 {
+	need_ip_conntrack();
 	return ipt_register_match(&helper_match);
 }
 
diff -Nru a/net/ipv4/netfilter/ipt_mac.c b/net/ipv4/netfilter/ipt_mac.c
--- a/net/ipv4/netfilter/ipt_mac.c	2004-10-18 14:55:54 -07:00
+++ b/net/ipv4/netfilter/ipt_mac.c	2004-10-18 14:55:54 -07:00
@@ -33,7 +33,7 @@
     return (skb->mac.raw >= skb->head
 	    && (skb->mac.raw + ETH_HLEN) <= skb->data
 	    /* If so, compare... */
-	    && ((memcmp(skb->mac.ethernet->h_source, info->srcaddr, ETH_ALEN)
+	    && ((memcmp(eth_hdr(skb)->h_source, info->srcaddr, ETH_ALEN)
 		== 0) ^ info->invert));
 }
 
diff -Nru a/net/ipv4/netfilter/ipt_multiport.c b/net/ipv4/netfilter/ipt_multiport.c
--- a/net/ipv4/netfilter/ipt_multiport.c	2004-10-18 14:56:16 -07:00
+++ b/net/ipv4/netfilter/ipt_multiport.c	2004-10-18 14:56:16 -07:00
@@ -54,7 +54,7 @@
       int offset,
       int *hotdrop)
 {
-	u16 ports[2];
+	u16 _ports[2], *pptr;
 	const struct ipt_multiport *multiinfo = matchinfo;
 
 	/* Must not be a fragment. */
@@ -63,18 +63,21 @@
 
 	/* Must be big enough to read ports (both UDP and TCP have
            them at the start). */
-	if (skb_copy_bits(skb, skb->nh.iph->ihl*4, ports, sizeof(ports)) < 0) {
+	pptr = skb_header_pointer(skb, skb->nh.iph->ihl * 4,
+				  sizeof(_ports), &_ports[0]);
+	if (pptr == NULL) {
 		/* We've been asked to examine this packet, and we
-		   can't.  Hence, no choice but to drop. */
-			duprintf("ipt_multiport:"
-				 " Dropping evil offset=0 tinygram.\n");
-			*hotdrop = 1;
-			return 0;
+		 * can't.  Hence, no choice but to drop.
+		 */
+		duprintf("ipt_multiport:"
+			 " Dropping evil offset=0 tinygram.\n");
+		*hotdrop = 1;
+		return 0;
 	}
 
 	return ports_match(multiinfo->ports,
 			   multiinfo->flags, multiinfo->count,
-			   ntohs(ports[0]), ntohs(ports[1]));
+			   ntohs(pptr[0]), ntohs(pptr[1]));
 }
 
 /* Called when user tries to insert an entry of this type. */
diff -Nru a/net/ipv4/netfilter/ipt_recent.c b/net/ipv4/netfilter/ipt_recent.c
--- a/net/ipv4/netfilter/ipt_recent.c	2004-10-18 14:55:55 -07:00
+++ b/net/ipv4/netfilter/ipt_recent.c	2004-10-18 14:55:55 -07:00
@@ -15,6 +15,7 @@
 #include <linux/ctype.h>
 #include <linux/ip.h>
 #include <linux/vmalloc.h>
+#include <linux/moduleparam.h>
 
 #include <linux/netfilter_ipv4/ip_tables.h>
 #include <linux/netfilter_ipv4/ipt_recent.h>
@@ -37,12 +38,12 @@
 MODULE_AUTHOR("Stephen Frost <sfrost@snowman.net>");
 MODULE_DESCRIPTION("IP tables recently seen matching module " RECENT_VER);
 MODULE_LICENSE("GPL");
-MODULE_PARM(ip_list_tot,"i");
-MODULE_PARM(ip_pkt_list_tot,"i");
-MODULE_PARM(ip_list_hash_size,"i");
-MODULE_PARM(ip_list_perms,"i");
+module_param(ip_list_tot, int, 0400);
+module_param(ip_pkt_list_tot, int, 0400);
+module_param(ip_list_hash_size, int, 0400);
+module_param(ip_list_perms, int, 0400);
 #ifdef DEBUG
-MODULE_PARM(debug,"i");
+module_param(debug, int, 0600);
 MODULE_PARM_DESC(debug,"debugging level, defaults to 1");
 #endif
 MODULE_PARM_DESC(ip_list_tot,"number of IPs to remember per list");
diff -Nru a/net/ipv4/netfilter/ipt_sctp.c b/net/ipv4/netfilter/ipt_sctp.c
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/net/ipv4/netfilter/ipt_sctp.c	2004-10-18 14:57:23 -07:00
@@ -0,0 +1,203 @@
+#include <linux/module.h>
+#include <linux/skbuff.h>
+#include <net/ip.h>
+#include <linux/sctp.h>
+
+#include <linux/netfilter_ipv4/ip_tables.h>
+#include <linux/netfilter_ipv4/ipt_sctp.h>
+
+#ifdef DEBUG_SCTP
+#define duprintf(format, args...) printk(format , ## args)
+#else
+#define duprintf(format, args...)
+#endif
+
+#define SCCHECK(cond, option, flag, invflag) (!((flag) & (option)) \
+					      || (!!((invflag) & (option)) ^ (cond)))
+
+static int
+match_flags(const struct ipt_sctp_flag_info *flag_info,
+	    const int flag_count,
+	    u_int8_t chunktype,
+	    u_int8_t chunkflags)
+{
+	int i;
+
+	for (i = 0; i < flag_count; i++) {
+		if (flag_info[i].chunktype == chunktype) {
+			return (chunkflags & flag_info[i].flag_mask) == flag_info[i].flag;
+		}
+	}
+
+	return 1;
+}
+
+static int
+match_packet(const struct sk_buff *skb,
+	     const u_int32_t *chunkmap,
+	     int chunk_match_type,
+	     const struct ipt_sctp_flag_info *flag_info,
+	     const int flag_count,
+	     int *hotdrop)
+{
+	int offset;
+	u_int32_t chunkmapcopy[256 / sizeof (u_int32_t)];
+	sctp_chunkhdr_t _sch, *sch;
+
+#ifdef DEBUG_SCTP
+	int i = 0;
+#endif
+
+	if (chunk_match_type == SCTP_CHUNK_MATCH_ALL) {
+		SCTP_CHUNKMAP_COPY(chunkmapcopy, chunkmap);
+	}
+
+	offset = skb->nh.iph->ihl * 4 + sizeof (sctp_sctphdr_t);
+	do {
+		sch = skb_header_pointer(skb, offset, sizeof(_sch), &_sch);
+		if (sch == NULL) {
+			duprintf("Dropping invalid SCTP packet.\n");
+			*hotdrop = 1;
+			return 0;
+        	}
+
+		duprintf("Chunk num: %d\toffset: %d\ttype: %d\tlength: %d\tflags: %x\n", 
+				++i, offset, sch->type, htons(sch->length), sch->flags);
+
+		offset += (htons(sch->length) + 3) & ~3;
+
+		duprintf("skb->len: %d\toffset: %d\n", skb->len, offset);
+
+		if (SCTP_CHUNKMAP_IS_SET(chunkmap, sch->type)) {
+			switch (chunk_match_type) {
+			case SCTP_CHUNK_MATCH_ANY:
+				if (match_flags(flag_info, flag_count, 
+					sch->type, sch->flags)) {
+					return 1;
+				}
+				break;
+
+			case SCTP_CHUNK_MATCH_ALL:
+				if (match_flags(flag_info, flag_count, 
+					sch->type, sch->flags)) {
+					SCTP_CHUNKMAP_CLEAR(chunkmapcopy, sch->type);
+				}
+				break;
+
+			case SCTP_CHUNK_MATCH_ONLY:
+				if (!match_flags(flag_info, flag_count, 
+					sch->type, sch->flags)) {
+					return 0;
+				}
+				break;
+			}
+		} else {
+			switch (chunk_match_type) {
+			case SCTP_CHUNK_MATCH_ONLY:
+				return 0;
+			}
+		}
+	} while (offset < skb->len);
+
+	switch (chunk_match_type) {
+	case SCTP_CHUNK_MATCH_ALL:
+		return SCTP_CHUNKMAP_IS_CLEAR(chunkmap);
+	case SCTP_CHUNK_MATCH_ANY:
+		return 0;
+	case SCTP_CHUNK_MATCH_ONLY:
+		return 1;
+	}
+
+	/* This will never be reached, but required to stop compiler whine */
+	return 0;
+}
+
+static int
+match(const struct sk_buff *skb,
+      const struct net_device *in,
+      const struct net_device *out,
+      const void *matchinfo,
+      int offset,
+      int *hotdrop)
+{
+	const struct ipt_sctp_info *info;
+	sctp_sctphdr_t _sh, *sh;
+
+	info = (const struct ipt_sctp_info *)matchinfo;
+
+	if (offset) {
+		duprintf("Dropping non-first fragment.. FIXME\n");
+		return 0;
+	}
+	
+	sh = skb_header_pointer(skb, skb->nh.iph->ihl*4, sizeof(_sh), &_sh);
+	if (sh == NULL) {
+		duprintf("Dropping evil TCP offset=0 tinygram.\n");
+		*hotdrop = 1;
+		return 0;
+       	}
+	duprintf("spt: %d\tdpt: %d\n", ntohs(sh->source), ntohs(sh->dest));
+
+	return  SCCHECK(((ntohs(sh->source) >= info->spts[0]) 
+			&& (ntohs(sh->source) <= info->spts[1])), 
+		   	IPT_SCTP_SRC_PORTS, info->flags, info->invflags)
+		&& SCCHECK(((ntohs(sh->dest) >= info->dpts[0]) 
+			&& (ntohs(sh->dest) <= info->dpts[1])), 
+			IPT_SCTP_DEST_PORTS, info->flags, info->invflags)
+		&& SCCHECK(match_packet(skb, info->chunkmap, info->chunk_match_type,
+ 					info->flag_info, info->flag_count, 
+					hotdrop),
+			   IPT_SCTP_CHUNK_TYPES, info->flags, info->invflags);
+}
+
+static int
+checkentry(const char *tablename,
+	   const struct ipt_ip *ip,
+	   void *matchinfo,
+	   unsigned int matchsize,
+	   unsigned int hook_mask)
+{
+	const struct ipt_sctp_info *info;
+
+	info = (const struct ipt_sctp_info *)matchinfo;
+
+	return ip->proto == IPPROTO_SCTP
+		&& !(ip->invflags & IPT_INV_PROTO)
+		&& matchsize == IPT_ALIGN(sizeof(struct ipt_sctp_info))
+		&& !(info->flags & ~IPT_SCTP_VALID_FLAGS)
+		&& !(info->invflags & ~IPT_SCTP_VALID_FLAGS)
+		&& !(info->invflags & ~info->flags)
+		&& ((!(info->flags & IPT_SCTP_CHUNK_TYPES)) || 
+			(info->chunk_match_type &
+				(SCTP_CHUNK_MATCH_ALL 
+				| SCTP_CHUNK_MATCH_ANY
+				| SCTP_CHUNK_MATCH_ONLY)));
+}
+
+static struct ipt_match sctp_match = 
+{ 
+	.list = { NULL, NULL},
+	.name = "sctp",
+	.match = &match,
+	.checkentry = &checkentry,
+	.destroy = NULL,
+	.me = THIS_MODULE
+};
+
+static int __init init(void)
+{
+	return ipt_register_match(&sctp_match);
+}
+
+static void __exit fini(void)
+{
+	ipt_unregister_match(&sctp_match);
+}
+
+module_init(init);
+module_exit(fini);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Kiran Kumar Immidi");
+MODULE_DESCRIPTION("Match for SCTP protocol packets");
+
diff -Nru a/net/ipv4/netfilter/ipt_state.c b/net/ipv4/netfilter/ipt_state.c
--- a/net/ipv4/netfilter/ipt_state.c	2004-10-18 14:57:05 -07:00
+++ b/net/ipv4/netfilter/ipt_state.c	2004-10-18 14:57:05 -07:00
@@ -30,9 +30,9 @@
 	enum ip_conntrack_info ctinfo;
 	unsigned int statebit;
 
-	if (skb->nfct == &ip_conntrack_untracked.infos[IP_CT_NEW])
+	if (skb->nfct == &ip_conntrack_untracked.ct_general)
 		statebit = IPT_STATE_UNTRACKED;
-	else if (!ip_conntrack_get((struct sk_buff *)skb, &ctinfo))
+	else if (!ip_conntrack_get(skb, &ctinfo))
 		statebit = IPT_STATE_INVALID;
 	else
 		statebit = IPT_STATE_BIT(ctinfo);
diff -Nru a/net/ipv4/netfilter/ipt_tcpmss.c b/net/ipv4/netfilter/ipt_tcpmss.c
--- a/net/ipv4/netfilter/ipt_tcpmss.c	2004-10-18 14:55:55 -07:00
+++ b/net/ipv4/netfilter/ipt_tcpmss.c	2004-10-18 14:55:55 -07:00
@@ -27,37 +27,45 @@
 		int invert,
 		int *hotdrop)
 {
-	struct tcphdr tcph;
+	struct tcphdr _tcph, *th;
 	/* tcp.doff is only 4 bits, ie. max 15 * 4 bytes */
-	u8 opt[15 * 4 - sizeof(tcph)];
+	u8 _opt[15 * 4 - sizeof(_tcph)], *op;
 	unsigned int i, optlen;
 
 	/* If we don't have the whole header, drop packet. */
-	if (skb_copy_bits(skb, skb->nh.iph->ihl*4, &tcph, sizeof(tcph)) < 0)
+	th = skb_header_pointer(skb, skb->nh.iph->ihl * 4,
+				sizeof(_tcph), &_tcph);
+	if (th == NULL)
 		goto dropit;
 
 	/* Malformed. */
-	if (tcph.doff*4 < sizeof(tcph))
+	if (th->doff*4 < sizeof(*th))
 		goto dropit;
 
-	optlen = tcph.doff*4 - sizeof(tcph);
+	optlen = th->doff*4 - sizeof(*th);
+	if (!optlen)
+		goto out;
+
 	/* Truncated options. */
-	if (skb_copy_bits(skb, skb->nh.iph->ihl*4+sizeof(tcph), opt, optlen)<0)
+	op = skb_header_pointer(skb, skb->nh.iph->ihl * 4 + sizeof(*th),
+				optlen, _opt);
+	if (op == NULL)
 		goto dropit;
 
 	for (i = 0; i < optlen; ) {
-		if (opt[i] == TCPOPT_MSS
+		if (op[i] == TCPOPT_MSS
 		    && (optlen - i) >= TCPOLEN_MSS
-		    && opt[i+1] == TCPOLEN_MSS) {
+		    && op[i+1] == TCPOLEN_MSS) {
 			u_int16_t mssval;
 
-			mssval = (opt[i+2] << 8) | opt[i+3];
+			mssval = (op[i+2] << 8) | op[i+3];
 			
 			return (mssval >= min && mssval <= max) ^ invert;
 		}
-		if (opt[i] < 2) i++;
-		else i += opt[i+1]?:1;
+		if (op[i] < 2) i++;
+		else i += op[i+1]?:1;
 	}
+out:
 	return invert;
 
  dropit:
diff -Nru a/net/ipv4/netfilter/iptable_filter.c b/net/ipv4/netfilter/iptable_filter.c
--- a/net/ipv4/netfilter/iptable_filter.c	2004-10-18 14:56:28 -07:00
+++ b/net/ipv4/netfilter/iptable_filter.c	2004-10-18 14:56:28 -07:00
@@ -11,6 +11,7 @@
  */
 
 #include <linux/module.h>
+#include <linux/moduleparam.h>
 #include <linux/netfilter_ipv4/ip_tables.h>
 
 MODULE_LICENSE("GPL");
@@ -155,7 +156,7 @@
 
 /* Default to forward because I got too much mail already. */
 static int forward = NF_ACCEPT;
-MODULE_PARM(forward, "i");
+module_param(forward, bool, 0000);
 
 static int __init init(void)
 {
diff -Nru a/net/ipv4/proc.c b/net/ipv4/proc.c
--- a/net/ipv4/proc.c	2004-10-18 14:55:54 -07:00
+++ b/net/ipv4/proc.c	2004-10-18 14:55:54 -07:00
@@ -330,7 +330,7 @@
 {
 	int i;
 
-	seq_puts(seq, "\nTcpExt:");
+	seq_puts(seq, "TcpExt:");
 	for (i = 0; snmp4_net_list[i].name != NULL; i++)
 		seq_printf(seq, " %s", snmp4_net_list[i].name);
 
diff -Nru a/net/ipv4/raw.c b/net/ipv4/raw.c
--- a/net/ipv4/raw.c	2004-10-18 14:56:32 -07:00
+++ b/net/ipv4/raw.c	2004-10-18 14:56:32 -07:00
@@ -323,6 +323,51 @@
 	return err; 
 }
 
+static void raw_probe_proto_opt(struct flowi *fl, struct msghdr *msg)
+{
+	struct iovec *iov;
+	u8 __user *type = NULL;
+	u8 __user *code = NULL;
+	int probed = 0;
+	int i;
+
+	if (!msg->msg_iov)
+		return;
+
+	for (i = 0; i < msg->msg_iovlen; i++) {
+		iov = &msg->msg_iov[i];
+		if (!iov)
+			continue;
+
+		switch (fl->proto) {
+		case IPPROTO_ICMP:
+			/* check if one-byte field is readable or not. */
+			if (iov->iov_base && iov->iov_len < 1)
+				break;
+
+			if (!type) {
+				type = iov->iov_base;
+				/* check if code field is readable or not. */
+				if (iov->iov_len > 1)
+					code = type + 1;
+			} else if (!code)
+				code = iov->iov_base;
+
+			if (type && code) {
+				get_user(fl->fl_icmp_type, type);
+				__get_user(fl->fl_icmp_code, code);
+				probed = 1;
+			}
+			break;
+		default:
+			probed = 1;
+			break;
+		}
+		if (probed)
+			break;
+	}
+}
+
 static int raw_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg,
 		       size_t len)
 {
@@ -429,6 +474,9 @@
 				    .proto = inet->hdrincl ? IPPROTO_RAW :
 					    		     sk->sk_protocol,
 				  };
+		if (!inet->hdrincl)
+			raw_probe_proto_opt(&fl, msg);
+
 		err = ip_route_output_flow(&rt, &fl, sk, !(msg->msg_flags&MSG_DONTWAIT));
 	}
 	if (err)
@@ -671,6 +719,7 @@
 	.backlog_rcv =	raw_rcv_skb,
 	.hash =		raw_v4_hash,
 	.unhash =	raw_v4_unhash,
+	.slab_obj_size = sizeof(struct raw_sock),
 };
 
 #ifdef CONFIG_PROC_FS
diff -Nru a/net/ipv4/route.c b/net/ipv4/route.c
--- a/net/ipv4/route.c	2004-10-18 14:57:04 -07:00
+++ b/net/ipv4/route.c	2004-10-18 14:57:04 -07:00
@@ -226,26 +226,25 @@
 	struct rt_cache_iter_state *st = seq->private;
 
 	for (st->bucket = rt_hash_mask; st->bucket >= 0; --st->bucket) {
-		rcu_read_lock();
+		rcu_read_lock_bh();
 		r = rt_hash_table[st->bucket].chain;
 		if (r)
 			break;
-		rcu_read_unlock();
+		rcu_read_unlock_bh();
 	}
 	return r;
 }
 
 static struct rtable *rt_cache_get_next(struct seq_file *seq, struct rtable *r)
 {
-	struct rt_cache_iter_state *st = seq->private;
+	struct rt_cache_iter_state *st = rcu_dereference(seq->private);
 
-	smp_read_barrier_depends();
 	r = r->u.rt_next;
 	while (!r) {
-		rcu_read_unlock();
+		rcu_read_unlock_bh();
 		if (--st->bucket < 0)
 			break;
-		rcu_read_lock();
+		rcu_read_lock_bh();
 		r = rt_hash_table[st->bucket].chain;
 	}
 	return r;
@@ -281,7 +280,7 @@
 static void rt_cache_seq_stop(struct seq_file *seq, void *v)
 {
 	if (v && v != SEQ_START_TOKEN)
-		rcu_read_unlock();
+		rcu_read_unlock_bh();
 }
 
 static int rt_cache_seq_show(struct seq_file *seq, void *v)
@@ -357,10 +356,13 @@
 {
 	int cpu;
 
-	for (cpu = *pos; cpu < NR_CPUS; ++cpu) {
+	if (*pos == 0)
+		return SEQ_START_TOKEN;
+
+	for (cpu = *pos-1; cpu < NR_CPUS; ++cpu) {
 		if (!cpu_possible(cpu))
 			continue;
-		*pos = cpu;
+		*pos = cpu+1;
 		return per_cpu_ptr(rt_cache_stat, cpu);
 	}
 	return NULL;
@@ -370,10 +372,10 @@
 {
 	int cpu;
 
-	for (cpu = *pos + 1; cpu < NR_CPUS; ++cpu) {
+	for (cpu = *pos; cpu < NR_CPUS; ++cpu) {
 		if (!cpu_possible(cpu))
 			continue;
-		*pos = cpu;
+		*pos = cpu+1;
 		return per_cpu_ptr(rt_cache_stat, cpu);
 	}
 	return NULL;
@@ -388,6 +390,11 @@
 static int rt_cpu_seq_show(struct seq_file *seq, void *v)
 {
 	struct rt_cache_stat *st = v;
+
+	if (v == SEQ_START_TOKEN) {
+		seq_printf(seq, "entries  in_hit in_slow_tot in_no_route in_brd in_martian_dst in_martian_src  out_hit out_slow_tot out_slow_mc  gc_total gc_ignored gc_goal_miss gc_dst_overflow in_hlist_search out_hlist_search\n");
+		return 0;
+	}
 	
 	seq_printf(seq,"%08x  %08x %08x %08x %08x %08x %08x %08x "
 		   " %08x %08x %08x %08x %08x %08x %08x %08x %08x \n",
@@ -439,13 +446,13 @@
   
 static __inline__ void rt_free(struct rtable *rt)
 {
-	call_rcu(&rt->u.dst.rcu_head, dst_rcu_free);
+	call_rcu_bh(&rt->u.dst.rcu_head, dst_rcu_free);
 }
 
 static __inline__ void rt_drop(struct rtable *rt)
 {
 	ip_rt_put(rt);
-	call_rcu(&rt->u.dst.rcu_head, dst_rcu_free);
+	call_rcu_bh(&rt->u.dst.rcu_head, dst_rcu_free);
 }
 
 static __inline__ int rt_fast_clean(struct rtable *rth)
@@ -1004,10 +1011,9 @@
 			rthp=&rt_hash_table[hash].chain;
 
 			rcu_read_lock();
-			while ((rth = *rthp) != NULL) {
+			while ((rth = rcu_dereference(*rthp)) != NULL) {
 				struct rtable *rt;
 
-				smp_read_barrier_depends();
 				if (rth->fl.fl4_dst != daddr ||
 				    rth->fl.fl4_src != skeys[i] ||
 				    rth->fl.fl4_tos != tos ||
@@ -1259,9 +1265,8 @@
 		unsigned hash = rt_hash_code(daddr, skeys[i], tos);
 
 		rcu_read_lock();
-		for (rth = rt_hash_table[hash].chain; rth;
-		     rth = rth->u.rt_next) {
-			smp_read_barrier_depends();
+		for (rth = rcu_dereference(rt_hash_table[hash].chain); rth;
+		     rth = rcu_dereference(rth->u.rt_next)) {
 			if (rth->fl.fl4_dst == daddr &&
 			    rth->fl.fl4_src == skeys[i] &&
 			    rth->rt_dst  == daddr &&
@@ -1342,9 +1347,12 @@
 {
 	struct rtable *rt = (struct rtable *) dst;
 	struct in_device *idev = rt->idev;
-	if (idev) {
-		rt->idev = NULL;
-		in_dev_put(idev);
+	if (idev && idev->dev != &loopback_dev) {
+		struct in_device *loopback_idev = in_dev_get(&loopback_dev);
+		if (loopback_idev) {
+			rt->idev = loopback_idev;
+			in_dev_put(idev);
+		}
 	}
 }
 
@@ -1387,13 +1395,7 @@
 	if (rt->fl.iif == 0)
 		src = rt->rt_src;
 	else if (fib_lookup(&rt->fl, &res) == 0) {
-#ifdef CONFIG_IP_ROUTE_NAT
-		if (res.type == RTN_NAT)
-			src = inet_select_addr(rt->u.dst.dev, rt->rt_gateway,
-						RT_SCOPE_UNIVERSE);
-		else
-#endif
-			src = FIB_RES_PREFSRC(res);
+		src = FIB_RES_PREFSRC(res);
 		fib_res_put(&res);
 	} else
 		src = inet_select_addr(rt->u.dst.dev, rt->rt_gateway,
@@ -1497,10 +1499,6 @@
 #endif
 	rth->fl.fl4_src	= saddr;
 	rth->rt_src	= saddr;
-#ifdef CONFIG_IP_ROUTE_NAT
-	rth->rt_dst_map	= daddr;
-	rth->rt_src_map	= saddr;
-#endif
 #ifdef CONFIG_NET_CLS_ROUTE
 	rth->u.dst.tclassid = itag;
 #endif
@@ -1610,31 +1608,6 @@
 
 	RT_CACHE_STAT_INC(in_slow_tot);
 
-#ifdef CONFIG_IP_ROUTE_NAT
-	/* Policy is applied before mapping destination,
-	   but rerouting after map should be made with old source.
-	 */
-
-	if (1) {
-		u32 src_map = saddr;
-		if (res.r)
-			src_map = fib_rules_policy(saddr, &res, &flags);
-
-		if (res.type == RTN_NAT) {
-			fl.fl4_dst = fib_rules_map_destination(daddr, &res);
-			fib_res_put(&res);
-			free_res = 0;
-			if (fib_lookup(&fl, &res))
-				goto e_inval;
-			free_res = 1;
-			if (res.type != RTN_UNICAST)
-				goto e_inval;
-			flags |= RTCF_DNAT;
-		}
-		fl.fl4_src = src_map;
-	}
-#endif
-
 	if (res.type == RTN_BROADCAST)
 		goto brd_input;
 
@@ -1708,12 +1681,6 @@
 	rth->fl.fl4_src	= saddr;
 	rth->rt_src	= saddr;
 	rth->rt_gateway	= daddr;
-#ifdef CONFIG_IP_ROUTE_NAT
-	rth->rt_src_map	= fl.fl4_src;
-	rth->rt_dst_map	= fl.fl4_dst;
-	if (flags&RTCF_DNAT)
-		rth->rt_gateway	= fl.fl4_dst;
-#endif
 	rth->rt_iif 	=
 	rth->fl.iif	= dev->ifindex;
 	rth->u.dst.dev	= out_dev->dev;
@@ -1776,10 +1743,6 @@
 #endif
 	rth->fl.fl4_src	= saddr;
 	rth->rt_src	= saddr;
-#ifdef CONFIG_IP_ROUTE_NAT
-	rth->rt_dst_map	= fl.fl4_dst;
-	rth->rt_src_map	= fl.fl4_src;
-#endif
 #ifdef CONFIG_NET_CLS_ROUTE
 	rth->u.dst.tclassid = itag;
 #endif
@@ -1864,8 +1827,8 @@
 	hash = rt_hash_code(daddr, saddr ^ (iif << 5), tos);
 
 	rcu_read_lock();
-	for (rth = rt_hash_table[hash].chain; rth; rth = rth->u.rt_next) {
-		smp_read_barrier_depends();
+	for (rth = rcu_dereference(rt_hash_table[hash].chain); rth;
+	     rth = rcu_dereference(rth->u.rt_next)) {
 		if (rth->fl.fl4_dst == daddr &&
 		    rth->fl.fl4_src == saddr &&
 		    rth->fl.iif == iif &&
@@ -1900,7 +1863,7 @@
 	if (MULTICAST(daddr)) {
 		struct in_device *in_dev;
 
-		read_lock(&inetdev_lock);
+		rcu_read_lock();
 		if ((in_dev = __in_dev_get(dev)) != NULL) {
 			int our = ip_check_mc(in_dev, daddr, saddr,
 				skb->nh.iph->protocol);
@@ -1909,12 +1872,12 @@
 			    || (!LOCAL_MCAST(daddr) && IN_DEV_MFORWARD(in_dev))
 #endif
 			    ) {
-				read_unlock(&inetdev_lock);
+				rcu_read_unlock();
 				return ip_route_input_mc(skb, daddr, saddr,
 							 tos, dev, our);
 			}
 		}
-		read_unlock(&inetdev_lock);
+		rcu_read_unlock();
 		return -EINVAL;
 	}
 	return ip_route_input_slow(skb, daddr, saddr, tos, dev);
@@ -2072,9 +2035,6 @@
 	}
 	free_res = 1;
 
-	if (res.type == RTN_NAT)
-		goto e_inval;
-
 	if (res.type == RTN_LOCAL) {
 		if (!fl.fl4_src)
 			fl.fl4_src = fl.fl4_dst;
@@ -2164,10 +2124,6 @@
 #endif
 	rth->rt_dst	= fl.fl4_dst;
 	rth->rt_src	= fl.fl4_src;
-#ifdef CONFIG_IP_ROUTE_NAT
-	rth->rt_dst_map	= fl.fl4_dst;
-	rth->rt_src_map	= fl.fl4_src;
-#endif
 	rth->rt_iif	= oldflp->oif ? : dev_out->ifindex;
 	rth->u.dst.dev	= dev_out;
 	dev_hold(dev_out);
@@ -2231,9 +2187,9 @@
 
 	hash = rt_hash_code(flp->fl4_dst, flp->fl4_src ^ (flp->oif << 5), flp->fl4_tos);
 
-	rcu_read_lock();
-	for (rth = rt_hash_table[hash].chain; rth; rth = rth->u.rt_next) {
-		smp_read_barrier_depends();
+	rcu_read_lock_bh();
+	for (rth = rcu_dereference(rt_hash_table[hash].chain); rth;
+		rth = rcu_dereference(rth->u.rt_next)) {
 		if (rth->fl.fl4_dst == flp->fl4_dst &&
 		    rth->fl.fl4_src == flp->fl4_src &&
 		    rth->fl.iif == 0 &&
@@ -2247,33 +2203,38 @@
 			dst_hold(&rth->u.dst);
 			rth->u.dst.__use++;
 			RT_CACHE_STAT_INC(out_hit);
-			rcu_read_unlock();
+			rcu_read_unlock_bh();
 			*rp = rth;
 			return 0;
 		}
 		RT_CACHE_STAT_INC(out_hlist_search);
 	}
-	rcu_read_unlock();
+	rcu_read_unlock_bh();
 
 	return ip_route_output_slow(rp, flp);
 }
 
-int ip_route_output_key(struct rtable **rp, struct flowi *flp)
+int ip_route_output_flow(struct rtable **rp, struct flowi *flp, struct sock *sk, int flags)
 {
 	int err;
 
 	if ((err = __ip_route_output_key(rp, flp)) != 0)
 		return err;
-	return flp->proto ? xfrm_lookup((struct dst_entry**)rp, flp, NULL, 0) : 0;
+
+	if (flp->proto) {
+		if (!flp->fl4_src)
+			flp->fl4_src = (*rp)->rt_src;
+		if (!flp->fl4_dst)
+			flp->fl4_dst = (*rp)->rt_dst;
+		return xfrm_lookup((struct dst_entry **)rp, flp, sk, flags);
+	}
+
+	return 0;
 }
 
-int ip_route_output_flow(struct rtable **rp, struct flowi *flp, struct sock *sk, int flags)
+int ip_route_output_key(struct rtable **rp, struct flowi *flp)
 {
-	int err;
-
-	if ((err = __ip_route_output_key(rp, flp)) != 0)
-		return err;
-	return flp->proto ? xfrm_lookup((struct dst_entry**)rp, flp, sk, flags) : 0;
+	return ip_route_output_flow(rp, flp, NULL, 0);
 }
 
 static int rt_fill_info(struct sk_buff *skb, u32 pid, u32 seq, int event,
@@ -2463,10 +2424,9 @@
 		if (h < s_h) continue;
 		if (h > s_h)
 			s_idx = 0;
-		rcu_read_lock();
-		for (rt = rt_hash_table[h].chain, idx = 0; rt;
-		     rt = rt->u.rt_next, idx++) {
-			smp_read_barrier_depends();
+		rcu_read_lock_bh();
+		for (rt = rcu_dereference(rt_hash_table[h].chain), idx = 0; rt;
+		     rt = rcu_dereference(rt->u.rt_next), idx++) {
 			if (idx < s_idx)
 				continue;
 			skb->dst = dst_clone(&rt->u.dst);
@@ -2474,12 +2434,12 @@
 					 cb->nlh->nlmsg_seq,
 					 RTM_NEWROUTE, 1) <= 0) {
 				dst_release(xchg(&skb->dst, NULL));
-				rcu_read_unlock();
+				rcu_read_unlock_bh();
 				goto done;
 			}
 			dst_release(xchg(&skb->dst, NULL));
 		}
-		rcu_read_unlock();
+		rcu_read_unlock_bh();
 	}
 
 done:
@@ -2831,12 +2791,16 @@
 	add_timer(&rt_secret_timer);
 
 #ifdef CONFIG_PROC_FS
+	{
+	struct proc_dir_entry *rtstat_pde = NULL; /* keep gcc happy */
 	if (!proc_net_fops_create("rt_cache", S_IRUGO, &rt_cache_seq_fops) ||
-	    !proc_net_fops_create("rt_cache_stat", S_IRUGO, &rt_cpu_seq_fops)) {
+	    !(rtstat_pde = create_proc_entry("rt_cache", S_IRUGO, 
+			    		     proc_net_stat))) {
 		free_percpu(rt_cache_stat);
 		return -ENOMEM;
 	}
-
+	rtstat_pde->proc_fops = &rt_cpu_seq_fops;
+	}
 #ifdef CONFIG_NET_CLS_ROUTE
 	create_proc_read_entry("rt_acct", 0, proc_net, ip_rt_acct_read, NULL);
 #endif
diff -Nru a/net/ipv4/sysctl_net_ipv4.c b/net/ipv4/sysctl_net_ipv4.c
--- a/net/ipv4/sysctl_net_ipv4.c	2004-10-18 14:56:49 -07:00
+++ b/net/ipv4/sysctl_net_ipv4.c	2004-10-18 14:56:49 -07:00
@@ -667,17 +667,17 @@
 		.proc_handler	= &proc_dointvec,
 	},
 	{
-		.ctl_name	= NET_TCP_DEFAULT_WIN_SCALE,
-		.procname	= "tcp_default_win_scale",
-		.data		= &sysctl_tcp_default_win_scale,
+		.ctl_name	= NET_TCP_MODERATE_RCVBUF,
+		.procname	= "tcp_moderate_rcvbuf",
+		.data		= &sysctl_tcp_moderate_rcvbuf,
 		.maxlen		= sizeof(int),
 		.mode		= 0644,
 		.proc_handler	= &proc_dointvec,
 	},
 	{
-		.ctl_name	= NET_TCP_MODERATE_RCVBUF,
-		.procname	= "tcp_moderate_rcvbuf",
-		.data		= &sysctl_tcp_moderate_rcvbuf,
+		.ctl_name	= NET_TCP_TSO_WIN_DIVISOR,
+		.procname	= "tcp_tso_win_divisor",
+		.data		= &sysctl_tcp_tso_win_divisor,
 		.maxlen		= sizeof(int),
 		.mode		= 0644,
 		.proc_handler	= &proc_dointvec,
diff -Nru a/net/ipv4/tcp.c b/net/ipv4/tcp.c
--- a/net/ipv4/tcp.c	2004-10-18 14:56:27 -07:00
+++ b/net/ipv4/tcp.c	2004-10-18 14:56:27 -07:00
@@ -276,8 +276,6 @@
 
 atomic_t tcp_orphan_count = ATOMIC_INIT(0);
 
-int sysctl_tcp_default_win_scale = 7;
-
 int sysctl_tcp_mem[3];
 int sysctl_tcp_wmem[3] = { 4 * 1024, 16 * 1024, 128 * 1024 };
 int sysctl_tcp_rmem[3] = { 4 * 1024, 87380, 87380 * 2 };
@@ -693,6 +691,7 @@
 		skb->ip_summed = CHECKSUM_HW;
 		tp->write_seq += copy;
 		TCP_SKB_CB(skb)->end_seq += copy;
+		skb_shinfo(skb)->tso_segs = 0;
 
 		if (!copied)
 			TCP_SKB_CB(skb)->flags &= ~TCPCB_FLAG_PSH;
@@ -939,6 +938,7 @@
 
 			tp->write_seq += copy;
 			TCP_SKB_CB(skb)->end_seq += copy;
+			skb_shinfo(skb)->tso_segs = 0;
 
 			from += copy;
 			copied += copy;
@@ -1593,14 +1593,6 @@
 	/* If it has not 0 inet_sk(sk)->num, it must be bound */
 	BUG_TRAP(!inet_sk(sk)->num || tcp_sk(sk)->bind_hash);
 
-#ifdef TCP_DEBUG
-	if (sk->sk_zapped) {
-		printk(KERN_DEBUG "TCP: double destroy sk=%p\n", sk);
-		sock_hold(sk);
-	}
-	sk->sk_zapped = 1;
-#endif
-
 	sk->sk_prot->destroy(sk);
 
 	sk_stream_kill_queues(sk);
@@ -1820,7 +1812,7 @@
 	tp->backoff = 0;
 	tp->snd_cwnd = 2;
 	tp->probes_out = 0;
-	tp->packets_out = 0;
+	tcp_set_pcount(&tp->packets_out, 0);
 	tp->snd_ssthresh = 0x7fffffff;
 	tp->snd_cwnd_cnt = 0;
 	tcp_set_ca_state(tp, TCP_CA_Open);
diff -Nru a/net/ipv4/tcp_diag.c b/net/ipv4/tcp_diag.c
--- a/net/ipv4/tcp_diag.c	2004-10-18 14:55:54 -07:00
+++ b/net/ipv4/tcp_diag.c	2004-10-18 14:55:54 -07:00
@@ -68,31 +68,31 @@
 	if (tp->ecn_flags&TCP_ECN_OK)
 		info->tcpi_options |= TCPI_OPT_ECN;
 
-	info->tcpi_rto = (1000000*tp->rto)/HZ;
-	info->tcpi_ato = (1000000*tp->ack.ato)/HZ;
-	info->tcpi_snd_mss = tp->mss_cache;
+	info->tcpi_rto = jiffies_to_usecs(tp->rto);
+	info->tcpi_ato = jiffies_to_usecs(tp->ack.ato);
+	info->tcpi_snd_mss = tp->mss_cache_std;
 	info->tcpi_rcv_mss = tp->ack.rcv_mss;
 
-	info->tcpi_unacked = tp->packets_out;
-	info->tcpi_sacked = tp->sacked_out;
-	info->tcpi_lost = tp->lost_out;
-	info->tcpi_retrans = tp->retrans_out;
-	info->tcpi_fackets = tp->fackets_out;
-
-	info->tcpi_last_data_sent = ((now - tp->lsndtime)*1000)/HZ;
-	info->tcpi_last_data_recv = ((now - tp->ack.lrcvtime)*1000)/HZ;
-	info->tcpi_last_ack_recv = ((now - tp->rcv_tstamp)*1000)/HZ;
+	info->tcpi_unacked = tcp_get_pcount(&tp->packets_out);
+	info->tcpi_sacked = tcp_get_pcount(&tp->sacked_out);
+	info->tcpi_lost = tcp_get_pcount(&tp->lost_out);
+	info->tcpi_retrans = tcp_get_pcount(&tp->retrans_out);
+	info->tcpi_fackets = tcp_get_pcount(&tp->fackets_out);
+
+	info->tcpi_last_data_sent = jiffies_to_msecs(now - tp->lsndtime);
+	info->tcpi_last_data_recv = jiffies_to_msecs(now - tp->ack.lrcvtime);
+	info->tcpi_last_ack_recv = jiffies_to_msecs(now - tp->rcv_tstamp);
 
 	info->tcpi_pmtu = tp->pmtu_cookie;
 	info->tcpi_rcv_ssthresh = tp->rcv_ssthresh;
-	info->tcpi_rtt = ((1000000*tp->srtt)/HZ)>>3;
-	info->tcpi_rttvar = ((1000000*tp->mdev)/HZ)>>2;
+	info->tcpi_rtt = jiffies_to_usecs(tp->srtt)>>3;
+	info->tcpi_rttvar = jiffies_to_usecs(tp->mdev)>>2;
 	info->tcpi_snd_ssthresh = tp->snd_ssthresh;
 	info->tcpi_snd_cwnd = tp->snd_cwnd;
 	info->tcpi_advmss = tp->advmss;
 	info->tcpi_reordering = tp->reordering;
 
-	info->tcpi_rcv_rtt = ((1000000*tp->rcv_rtt_est.rtt)/HZ)>>3;
+	info->tcpi_rcv_rtt = jiffies_to_usecs(tp->rcv_rtt_est.rtt)>>3;
 	info->tcpi_rcv_space = tp->rcvq_space.space;
 }
 
@@ -116,7 +116,8 @@
 		if (ext & (1<<(TCPDIAG_INFO-1)))
 			info = TCPDIAG_PUT(skb, TCPDIAG_INFO, sizeof(*info));
 		
-		if (tcp_is_vegas(tp) && (ext & (1<<(TCPDIAG_VEGASINFO-1))))
+		if ((tcp_is_westwood(tp) || tcp_is_vegas(tp))
+		    && (ext & (1<<(TCPDIAG_VEGASINFO-1))))
 			vinfo = TCPDIAG_PUT(skb, TCPDIAG_VEGASINFO, sizeof(*vinfo));
 	}
 	r->tcpdiag_family = sk->sk_family;
@@ -209,10 +210,17 @@
 		tcp_get_info(sk, info);
 
 	if (vinfo) {
-		vinfo->tcpv_enabled = tp->vegas.doing_vegas_now;
-		vinfo->tcpv_rttcnt = tp->vegas.cntRTT;
-		vinfo->tcpv_rtt = tp->vegas.baseRTT;
-		vinfo->tcpv_minrtt = tp->vegas.minRTT;
+		if (tcp_is_vegas(tp)) {
+			vinfo->tcpv_enabled = tp->vegas.doing_vegas_now;
+			vinfo->tcpv_rttcnt = tp->vegas.cntRTT;
+			vinfo->tcpv_rtt = jiffies_to_usecs(tp->vegas.baseRTT);
+			vinfo->tcpv_minrtt = jiffies_to_usecs(tp->vegas.minRTT);
+		} else {
+			vinfo->tcpv_enabled = 0;
+			vinfo->tcpv_rttcnt = 0;
+			vinfo->tcpv_rtt = jiffies_to_usecs(tp->westwood.rtt);
+			vinfo->tcpv_minrtt = jiffies_to_usecs(tp->westwood.rtt_min);
+		}
 	}
 
 	nlh->nlmsg_len = skb->tail - b;
@@ -487,21 +495,22 @@
 			sk_for_each(sk, node, &tcp_listening_hash[i]) {
 				struct inet_opt *inet = inet_sk(sk);
 				if (num < s_num)
-					continue;
+					goto next_listen;
 				if (!(r->tcpdiag_states&TCPF_LISTEN) ||
 				    r->id.tcpdiag_dport)
-					continue;
+					goto next_listen;
 				if (r->id.tcpdiag_sport != inet->sport &&
 				    r->id.tcpdiag_sport)
-					continue;
+					goto next_listen;
 				if (bc && !tcpdiag_bc_run(RTA_DATA(bc), RTA_PAYLOAD(bc), sk))
-					continue;
+					goto next_listen;
 				if (tcpdiag_fill(skb, sk, r->tcpdiag_ext,
 						 NETLINK_CB(cb->skb).pid,
 						 cb->nlh->nlmsg_seq) <= 0) {
 					tcp_listen_unlock();
 					goto done;
 				}
+next_listen:
 				++num;
 			}
 		}
@@ -529,22 +538,23 @@
 			struct inet_opt *inet = inet_sk(sk);
 
 			if (num < s_num)
-				continue;
+				goto next_normal;
 			if (!(r->tcpdiag_states & (1 << sk->sk_state)))
-				continue;
+				goto next_normal;
 			if (r->id.tcpdiag_sport != inet->sport &&
 			    r->id.tcpdiag_sport)
-				continue;
+				goto next_normal;
 			if (r->id.tcpdiag_dport != inet->dport && r->id.tcpdiag_dport)
-				continue;
+				goto next_normal;
 			if (bc && !tcpdiag_bc_run(RTA_DATA(bc), RTA_PAYLOAD(bc), sk))
-				continue;
+				goto next_normal;
 			if (tcpdiag_fill(skb, sk, r->tcpdiag_ext,
 					 NETLINK_CB(cb->skb).pid,
 					 cb->nlh->nlmsg_seq) <= 0) {
 				read_unlock_bh(&head->lock);
 				goto done;
 			}
+next_normal:
 			++num;
 		}
 
@@ -554,23 +564,22 @@
 				struct inet_opt *inet = inet_sk(sk);
 
 				if (num < s_num)
-					continue;
-				if (!(r->tcpdiag_states & (1 << sk->sk_zapped)))
-					continue;
+					goto next_dying;
 				if (r->id.tcpdiag_sport != inet->sport &&
 				    r->id.tcpdiag_sport)
-					continue;
+					goto next_dying;
 				if (r->id.tcpdiag_dport != inet->dport &&
 				    r->id.tcpdiag_dport)
-					continue;
+					goto next_dying;
 				if (bc && !tcpdiag_bc_run(RTA_DATA(bc), RTA_PAYLOAD(bc), sk))
-					continue;
+					goto next_dying;
 				if (tcpdiag_fill(skb, sk, r->tcpdiag_ext,
 						 NETLINK_CB(cb->skb).pid,
 						 cb->nlh->nlmsg_seq) <= 0) {
 					read_unlock_bh(&head->lock);
 					goto done;
 				}
+next_dying:
 				++num;
 			}
 		}
diff -Nru a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c
--- a/net/ipv4/tcp_input.c	2004-10-18 14:56:49 -07:00
+++ b/net/ipv4/tcp_input.c	2004-10-18 14:56:49 -07:00
@@ -555,17 +555,20 @@
 		tcp_grow_window(sk, tp, skb);
 }
 
-/* Set up a new TCP connection, depending on whether it should be
- * using Vegas or not.
- */    
-void tcp_vegas_init(struct tcp_opt *tp)
+/* When starting a new connection, pin down the current choice of 
+ * congestion algorithm.
+ */
+void tcp_ca_init(struct tcp_opt *tp)
 {
-	if (sysctl_tcp_vegas_cong_avoid) {
-		tp->vegas.do_vegas = 1;
+	if (sysctl_tcp_westwood) 
+		tp->adv_cong = TCP_WESTWOOD;
+	else if (sysctl_tcp_bic)
+		tp->adv_cong = TCP_BIC;
+	else if (sysctl_tcp_vegas_cong_avoid) {
+		tp->adv_cong = TCP_VEGAS;
 		tp->vegas.baseRTT = 0x7fffffff;
 		tcp_vegas_enable(tp);
-	} else 
-		tcp_vegas_disable(tp);
+	} 
 }
 
 /* Do RTT sampling needed for Vegas.
@@ -799,10 +802,10 @@
 	__u32 cwnd = (dst ? dst_metric(dst, RTAX_INITCWND) : 0);
 
 	if (!cwnd) {
-		if (tp->mss_cache > 1460)
+		if (tp->mss_cache_std > 1460)
 			cwnd = 2;
 		else
-			cwnd = (tp->mss_cache > 1095) ? 3 : 4;
+			cwnd = (tp->mss_cache_std > 1095) ? 3 : 4;
 	}
 	return min_t(__u32, cwnd, tp->snd_cwnd_clamp);
 }
@@ -852,8 +855,10 @@
 	 * to low value, and then abruptly stops to do it and starts to delay
 	 * ACKs, wait for troubles.
 	 */
-	if (dst_metric(dst, RTAX_RTT) > tp->srtt)
+	if (dst_metric(dst, RTAX_RTT) > tp->srtt) {
 		tp->srtt = dst_metric(dst, RTAX_RTT);
+		tp->rtt_seq = tp->snd_nxt;
+	}
 	if (dst_metric(dst, RTAX_RTTVAR) > tp->mdev) {
 		tp->mdev = dst_metric(dst, RTAX_RTTVAR);
 		tp->mdev_max = tp->rttvar = max(tp->mdev, TCP_RTO_MIN);
@@ -895,7 +900,9 @@
 #if FASTRETRANS_DEBUG > 1
 		printk(KERN_DEBUG "Disorder%d %d %u f%u s%u rr%d\n",
 		       tp->sack_ok, tp->ca_state,
-		       tp->reordering, tp->fackets_out, tp->sacked_out,
+		       tp->reordering,
+		       tcp_get_pcount(&tp->fackets_out),
+		       tcp_get_pcount(&tp->sacked_out),
 		       tp->undo_marker ? tp->undo_retrans : 0);
 #endif
 		/* Disable FACK yet. */
@@ -958,7 +965,7 @@
 	unsigned char *ptr = ack_skb->h.raw + TCP_SKB_CB(ack_skb)->sacked;
 	struct tcp_sack_block *sp = (struct tcp_sack_block *)(ptr+2);
 	int num_sacks = (ptr[1] - TCPOLEN_SACK_BASE)>>3;
-	int reord = tp->packets_out;
+	int reord = tcp_get_pcount(&tp->packets_out);
 	int prior_fackets;
 	u32 lost_retrans = 0;
 	int flag = 0;
@@ -972,9 +979,9 @@
 		tp->mss_cache = tp->mss_cache_std;
 	}
 
-	if (!tp->sacked_out)
-		tp->fackets_out = 0;
-	prior_fackets = tp->fackets_out;
+	if (!tcp_get_pcount(&tp->sacked_out))
+		tcp_set_pcount(&tp->fackets_out, 0);
+	prior_fackets = tcp_get_pcount(&tp->fackets_out);
 
 	for (i=0; i<num_sacks; i++, sp++) {
 		struct sk_buff *skb;
@@ -1028,7 +1035,7 @@
 			if(!before(TCP_SKB_CB(skb)->seq, end_seq))
 				break;
 
-			fack_count++;
+			fack_count += tcp_skb_pcount(skb);
 
 			in_sack = !after(start_seq, TCP_SKB_CB(skb)->seq) &&
 				!before(end_seq, TCP_SKB_CB(skb)->end_seq);
@@ -1072,8 +1079,8 @@
 					 */
 					if (sacked & TCPCB_LOST) {
 						TCP_SKB_CB(skb)->sacked &= ~(TCPCB_LOST|TCPCB_SACKED_RETRANS);
-						tp->lost_out--;
-						tp->retrans_out--;
+						tcp_dec_pcount(&tp->lost_out, skb);
+						tcp_dec_pcount(&tp->retrans_out, skb);
 					}
 				} else {
 					/* New sack for not retransmitted frame,
@@ -1085,16 +1092,16 @@
 
 					if (sacked & TCPCB_LOST) {
 						TCP_SKB_CB(skb)->sacked &= ~TCPCB_LOST;
-						tp->lost_out--;
+						tcp_dec_pcount(&tp->lost_out, skb);
 					}
 				}
 
 				TCP_SKB_CB(skb)->sacked |= TCPCB_SACKED_ACKED;
 				flag |= FLAG_DATA_SACKED;
-				tp->sacked_out++;
+				tcp_inc_pcount(&tp->sacked_out, skb);
 
-				if (fack_count > tp->fackets_out)
-					tp->fackets_out = fack_count;
+				if (fack_count > tcp_get_pcount(&tp->fackets_out))
+					tcp_set_pcount(&tp->fackets_out, fack_count);
 			} else {
 				if (dup_sack && (sacked&TCPCB_RETRANS))
 					reord = min(fack_count, reord);
@@ -1108,7 +1115,7 @@
 			if (dup_sack &&
 			    (TCP_SKB_CB(skb)->sacked&TCPCB_SACKED_RETRANS)) {
 				TCP_SKB_CB(skb)->sacked &= ~TCPCB_SACKED_RETRANS;
-				tp->retrans_out--;
+				tcp_dec_pcount(&tp->retrans_out, skb);
 			}
 		}
 	}
@@ -1132,12 +1139,12 @@
 			    (IsFack(tp) ||
 			     !before(lost_retrans,
 				     TCP_SKB_CB(skb)->ack_seq + tp->reordering *
-				     tp->mss_cache))) {
+				     tp->mss_cache_std))) {
 				TCP_SKB_CB(skb)->sacked &= ~TCPCB_SACKED_RETRANS;
-				tp->retrans_out--;
+				tcp_dec_pcount(&tp->retrans_out, skb);
 
 				if (!(TCP_SKB_CB(skb)->sacked&(TCPCB_LOST|TCPCB_SACKED_ACKED))) {
-					tp->lost_out++;
+					tcp_inc_pcount(&tp->lost_out, skb);
 					TCP_SKB_CB(skb)->sacked |= TCPCB_LOST;
 					flag |= FLAG_DATA_SACKED;
 					NET_INC_STATS_BH(LINUX_MIB_TCPLOSTRETRANSMIT);
@@ -1146,15 +1153,20 @@
 		}
 	}
 
-	tp->left_out = tp->sacked_out + tp->lost_out;
-
-	if (reord < tp->fackets_out && tp->ca_state != TCP_CA_Loss)
-		tcp_update_reordering(tp, (tp->fackets_out + 1) - reord, 0);
+	tcp_set_pcount(&tp->left_out,
+		       (tcp_get_pcount(&tp->sacked_out) +
+			tcp_get_pcount(&tp->lost_out)));
+
+	if ((reord < tcp_get_pcount(&tp->fackets_out)) &&
+	    tp->ca_state != TCP_CA_Loss)
+		tcp_update_reordering(tp,
+				      ((tcp_get_pcount(&tp->fackets_out) + 1) -
+				       reord), 0);
 
 #if FASTRETRANS_DEBUG > 0
-	BUG_TRAP((int)tp->sacked_out >= 0);
-	BUG_TRAP((int)tp->lost_out >= 0);
-	BUG_TRAP((int)tp->retrans_out >= 0);
+	BUG_TRAP((int)tcp_get_pcount(&tp->sacked_out) >= 0);
+	BUG_TRAP((int)tcp_get_pcount(&tp->lost_out) >= 0);
+	BUG_TRAP((int)tcp_get_pcount(&tp->retrans_out) >= 0);
 	BUG_TRAP((int)tcp_packets_in_flight(tp) >= 0);
 #endif
 	return flag;
@@ -1184,7 +1196,7 @@
 	 * If something was really lost, it is eventually caught up
 	 * in tcp_enter_frto_loss.
 	 */
-	tp->retrans_out = 0;
+	tcp_set_pcount(&tp->retrans_out, 0);
 	tp->undo_marker = tp->snd_una;
 	tp->undo_retrans = 0;
 
@@ -1207,26 +1219,26 @@
 	struct sk_buff *skb;
 	int cnt = 0;
 
-	tp->sacked_out = 0;
-	tp->lost_out = 0;
-	tp->fackets_out = 0;
+	tcp_set_pcount(&tp->sacked_out, 0);
+	tcp_set_pcount(&tp->lost_out, 0);
+	tcp_set_pcount(&tp->fackets_out, 0);
 
 	sk_stream_for_retrans_queue(skb, sk) {
-		cnt++;
+		cnt += tcp_skb_pcount(skb);
 		TCP_SKB_CB(skb)->sacked &= ~TCPCB_LOST;
 		if (!(TCP_SKB_CB(skb)->sacked&TCPCB_SACKED_ACKED)) {
 
 			/* Do not mark those segments lost that were
 			 * forward transmitted after RTO
 			 */
-			if(!after(TCP_SKB_CB(skb)->end_seq,
+			if (!after(TCP_SKB_CB(skb)->end_seq,
 				   tp->frto_highmark)) {
 				TCP_SKB_CB(skb)->sacked |= TCPCB_LOST;
-				tp->lost_out++;
+				tcp_inc_pcount(&tp->lost_out, skb);
 			}
 		} else {
-			tp->sacked_out++;
-			tp->fackets_out = cnt;
+			tcp_inc_pcount(&tp->sacked_out, skb);
+			tcp_set_pcount(&tp->fackets_out, cnt);
 		}
 	}
 	tcp_sync_left_out(tp);
@@ -1248,12 +1260,12 @@
 
 void tcp_clear_retrans(struct tcp_opt *tp)
 {
-	tp->left_out = 0;
-	tp->retrans_out = 0;
+	tcp_set_pcount(&tp->left_out, 0);
+	tcp_set_pcount(&tp->retrans_out, 0);
 
-	tp->fackets_out = 0;
-	tp->sacked_out = 0;
-	tp->lost_out = 0;
+	tcp_set_pcount(&tp->fackets_out, 0);
+	tcp_set_pcount(&tp->sacked_out, 0);
+	tcp_set_pcount(&tp->lost_out, 0);
 
 	tp->undo_marker = 0;
 	tp->undo_retrans = 0;
@@ -1287,17 +1299,17 @@
 		tp->undo_marker = tp->snd_una;
 
 	sk_stream_for_retrans_queue(skb, sk) {
-		cnt++;
+		cnt += tcp_skb_pcount(skb);
 		if (TCP_SKB_CB(skb)->sacked&TCPCB_RETRANS)
 			tp->undo_marker = 0;
 		TCP_SKB_CB(skb)->sacked &= (~TCPCB_TAGBITS)|TCPCB_SACKED_ACKED;
 		if (!(TCP_SKB_CB(skb)->sacked&TCPCB_SACKED_ACKED) || how) {
 			TCP_SKB_CB(skb)->sacked &= ~TCPCB_SACKED_ACKED;
 			TCP_SKB_CB(skb)->sacked |= TCPCB_LOST;
-			tp->lost_out++;
+			tcp_inc_pcount(&tp->lost_out, skb);
 		} else {
-			tp->sacked_out++;
-			tp->fackets_out = cnt;
+			tcp_inc_pcount(&tp->sacked_out, skb);
+			tcp_set_pcount(&tp->fackets_out, cnt);
 		}
 	}
 	tcp_sync_left_out(tp);
@@ -1334,7 +1346,8 @@
 
 static inline int tcp_fackets_out(struct tcp_opt *tp)
 {
-	return IsReno(tp) ? tp->sacked_out+1 : tp->fackets_out;
+	return IsReno(tp) ? tcp_get_pcount(&tp->sacked_out)+1 :
+		tcp_get_pcount(&tp->fackets_out);
 }
 
 static inline int tcp_skb_timedout(struct tcp_opt *tp, struct sk_buff *skb)
@@ -1344,7 +1357,7 @@
 
 static inline int tcp_head_timedout(struct sock *sk, struct tcp_opt *tp)
 {
-	return tp->packets_out &&
+	return tcp_get_pcount(&tp->packets_out) &&
 	       tcp_skb_timedout(tp, skb_peek(&sk->sk_write_queue));
 }
 
@@ -1444,8 +1457,10 @@
 static int
 tcp_time_to_recover(struct sock *sk, struct tcp_opt *tp)
 {
+	__u32 packets_out;
+
 	/* Trick#1: The loss is proven. */
-	if (tp->lost_out)
+	if (tcp_get_pcount(&tp->lost_out))
 		return 1;
 
 	/* Not-A-Trick#2 : Classic rule... */
@@ -1461,8 +1476,9 @@
 	/* Trick#4: It is still not OK... But will it be useful to delay
 	 * recovery more?
 	 */
-	if (tp->packets_out <= tp->reordering &&
-	    tp->sacked_out >= max_t(__u32, tp->packets_out/2, sysctl_tcp_reordering) &&
+	packets_out = tcp_get_pcount(&tp->packets_out);
+	if (packets_out <= tp->reordering &&
+	    tcp_get_pcount(&tp->sacked_out) >= max_t(__u32, packets_out/2, sysctl_tcp_reordering) &&
 	    !tcp_may_send_now(sk, tp)) {
 		/* We have nothing to send. This connection is limited
 		 * either by receiver window or by application.
@@ -1481,12 +1497,16 @@
 {
 	u32 holes;
 
-	holes = max(tp->lost_out, 1U);
-	holes = min(holes, tp->packets_out);
+	holes = max(tcp_get_pcount(&tp->lost_out), 1U);
+	holes = min(holes, tcp_get_pcount(&tp->packets_out));
 
-	if (tp->sacked_out + holes > tp->packets_out) {
-		tp->sacked_out = tp->packets_out - holes;
-		tcp_update_reordering(tp, tp->packets_out+addend, 0);
+	if ((tcp_get_pcount(&tp->sacked_out) + holes) >
+	    tcp_get_pcount(&tp->packets_out)) {
+		tcp_set_pcount(&tp->sacked_out,
+			       (tcp_get_pcount(&tp->packets_out) - holes));
+		tcp_update_reordering(tp,
+				      tcp_get_pcount(&tp->packets_out)+addend,
+				      0);
 	}
 }
 
@@ -1494,7 +1514,7 @@
 
 static void tcp_add_reno_sack(struct tcp_opt *tp)
 {
-	++tp->sacked_out;
+	tcp_inc_pcount_explicit(&tp->sacked_out, 1);
 	tcp_check_reno_reordering(tp, 0);
 	tcp_sync_left_out(tp);
 }
@@ -1505,10 +1525,10 @@
 {
 	if (acked > 0) {
 		/* One ACK acked hole. The rest eat duplicate ACKs. */
-		if (acked-1 >= tp->sacked_out)
-			tp->sacked_out = 0;
+		if (acked-1 >= tcp_get_pcount(&tp->sacked_out))
+			tcp_set_pcount(&tp->sacked_out, 0);
 		else
-			tp->sacked_out -= acked-1;
+			tcp_dec_pcount_explicit(&tp->sacked_out, acked-1);
 	}
 	tcp_check_reno_reordering(tp, acked);
 	tcp_sync_left_out(tp);
@@ -1516,8 +1536,8 @@
 
 static inline void tcp_reset_reno_sack(struct tcp_opt *tp)
 {
-	tp->sacked_out = 0;
-	tp->left_out = tp->lost_out;
+	tcp_set_pcount(&tp->sacked_out, 0);
+	tcp_set_pcount(&tp->left_out, tcp_get_pcount(&tp->lost_out));
 }
 
 /* Mark head of queue up as lost. */
@@ -1527,14 +1547,15 @@
 	struct sk_buff *skb;
 	int cnt = packets;
 
-	BUG_TRAP(cnt <= tp->packets_out);
+	BUG_TRAP(cnt <= tcp_get_pcount(&tp->packets_out));
 
 	sk_stream_for_retrans_queue(skb, sk) {
-		if (--cnt < 0 || after(TCP_SKB_CB(skb)->end_seq, high_seq))
+		cnt -= tcp_skb_pcount(skb);
+		if (cnt < 0 || after(TCP_SKB_CB(skb)->end_seq, high_seq))
 			break;
 		if (!(TCP_SKB_CB(skb)->sacked&TCPCB_TAGBITS)) {
 			TCP_SKB_CB(skb)->sacked |= TCPCB_LOST;
-			tp->lost_out++;
+			tcp_inc_pcount(&tp->lost_out, skb);
 		}
 	}
 	tcp_sync_left_out(tp);
@@ -1545,7 +1566,7 @@
 static void tcp_update_scoreboard(struct sock *sk, struct tcp_opt *tp)
 {
 	if (IsFack(tp)) {
-		int lost = tp->fackets_out - tp->reordering;
+		int lost = tcp_get_pcount(&tp->fackets_out) - tp->reordering;
 		if (lost <= 0)
 			lost = 1;
 		tcp_mark_head_lost(sk, tp, lost, tp->high_seq);
@@ -1565,7 +1586,7 @@
 			if (tcp_skb_timedout(tp, skb) &&
 			    !(TCP_SKB_CB(skb)->sacked&TCPCB_TAGBITS)) {
 				TCP_SKB_CB(skb)->sacked |= TCPCB_LOST;
-				tp->lost_out++;
+				tcp_inc_pcount(&tp->lost_out, skb);
 			}
 		}
 		tcp_sync_left_out(tp);
@@ -1630,8 +1651,9 @@
 	printk(KERN_DEBUG "Undo %s %u.%u.%u.%u/%u c%u l%u ss%u/%u p%u\n",
 	       msg,
 	       NIPQUAD(inet->daddr), ntohs(inet->dport),
-	       tp->snd_cwnd, tp->left_out,
-	       tp->snd_ssthresh, tp->prior_ssthresh, tp->packets_out);
+	       tp->snd_cwnd, tcp_get_pcount(&tp->left_out),
+	       tp->snd_ssthresh, tp->prior_ssthresh,
+	       tcp_get_pcount(&tp->packets_out));
 }
 #else
 #define DBGUNDO(x...) do { } while (0)
@@ -1701,13 +1723,13 @@
 static int tcp_try_undo_partial(struct sock *sk, struct tcp_opt *tp, int acked)
 {
 	/* Partial ACK arrived. Force Hoe's retransmit. */
-	int failed = IsReno(tp) || tp->fackets_out>tp->reordering;
+	int failed = IsReno(tp) || tcp_get_pcount(&tp->fackets_out)>tp->reordering;
 
 	if (tcp_may_undo(tp)) {
 		/* Plain luck! Hole if filled with delayed
 		 * packet, rather than with a retransmit.
 		 */
-		if (tp->retrans_out == 0)
+		if (tcp_get_pcount(&tp->retrans_out) == 0)
 			tp->retrans_stamp = 0;
 
 		tcp_update_reordering(tp, tcp_fackets_out(tp)+acked, 1);
@@ -1734,8 +1756,8 @@
 			TCP_SKB_CB(skb)->sacked &= ~TCPCB_LOST;
 		}
 		DBGUNDO(sk, tp, "partial loss");
-		tp->lost_out = 0;
-		tp->left_out = tp->sacked_out;
+		tcp_set_pcount(&tp->lost_out, 0);
+		tcp_set_pcount(&tp->left_out, tcp_get_pcount(&tp->sacked_out));
 		tcp_undo_cwr(tp, 1);
 		NET_INC_STATS_BH(LINUX_MIB_TCPLOSSUNDO);
 		tp->retransmits = 0;
@@ -1758,9 +1780,9 @@
 
 static void tcp_try_to_open(struct sock *sk, struct tcp_opt *tp, int flag)
 {
-	tp->left_out = tp->sacked_out;
+	tcp_set_pcount(&tp->left_out, tcp_get_pcount(&tp->sacked_out));
 
-	if (tp->retrans_out == 0)
+	if (tcp_get_pcount(&tp->retrans_out) == 0)
 		tp->retrans_stamp = 0;
 
 	if (flag&FLAG_ECE)
@@ -1769,8 +1791,8 @@
 	if (tp->ca_state != TCP_CA_CWR) {
 		int state = TCP_CA_Open;
 
-		if (tp->left_out ||
-		    tp->retrans_out ||
+		if (tcp_get_pcount(&tp->left_out) ||
+		    tcp_get_pcount(&tp->retrans_out) ||
 		    tp->undo_marker)
 			state = TCP_CA_Disorder;
 
@@ -1804,11 +1826,11 @@
 
 	/* Some technical things:
 	 * 1. Reno does not count dupacks (sacked_out) automatically. */
-	if (!tp->packets_out)
-		tp->sacked_out = 0;
+	if (!tcp_get_pcount(&tp->packets_out))
+		tcp_set_pcount(&tp->sacked_out, 0);
         /* 2. SACK counts snd_fack in packets inaccurately. */
-	if (tp->sacked_out == 0)
-		tp->fackets_out = 0;
+	if (tcp_get_pcount(&tp->sacked_out) == 0)
+		tcp_set_pcount(&tp->fackets_out, 0);
 
         /* Now state machine starts.
 	 * A. ECE, hence prohibit cwnd undoing, the reduction is required. */
@@ -1816,15 +1838,15 @@
 		tp->prior_ssthresh = 0;
 
 	/* B. In all the states check for reneging SACKs. */
-	if (tp->sacked_out && tcp_check_sack_reneging(sk, tp))
+	if (tcp_get_pcount(&tp->sacked_out) && tcp_check_sack_reneging(sk, tp))
 		return;
 
 	/* C. Process data loss notification, provided it is valid. */
 	if ((flag&FLAG_DATA_LOST) &&
 	    before(tp->snd_una, tp->high_seq) &&
 	    tp->ca_state != TCP_CA_Open &&
-	    tp->fackets_out > tp->reordering) {
-		tcp_mark_head_lost(sk, tp, tp->fackets_out-tp->reordering, tp->high_seq);
+	    tcp_get_pcount(&tp->fackets_out) > tp->reordering) {
+		tcp_mark_head_lost(sk, tp, tcp_get_pcount(&tp->fackets_out)-tp->reordering, tp->high_seq);
 		NET_INC_STATS_BH(LINUX_MIB_TCPLOSS);
 	}
 
@@ -1835,7 +1857,7 @@
 	 *    when high_seq is ACKed. */
 	if (tp->ca_state == TCP_CA_Open) {
 		if (!sysctl_tcp_frto)
-			BUG_TRAP(tp->retrans_out == 0);
+			BUG_TRAP(tcp_get_pcount(&tp->retrans_out) == 0);
 		tp->retrans_stamp = 0;
 	} else if (!before(tp->snd_una, tp->high_seq)) {
 		switch (tp->ca_state) {
@@ -1882,7 +1904,8 @@
 			if (IsReno(tp) && is_dupack)
 				tcp_add_reno_sack(tp);
 		} else {
-			int acked = prior_packets - tp->packets_out;
+			int acked = prior_packets -
+				tcp_get_pcount(&tp->packets_out);
 			if (IsReno(tp))
 				tcp_remove_reno_sacks(sk, tp, acked);
 			is_dupack = tcp_try_undo_partial(sk, tp, acked);
@@ -1925,7 +1948,7 @@
 		tp->high_seq = tp->snd_nxt;
 		tp->prior_ssthresh = 0;
 		tp->undo_marker = tp->snd_una;
-		tp->undo_retrans = tp->retrans_out;
+		tp->undo_retrans = tcp_get_pcount(&tp->retrans_out);
 
 		if (tp->ca_state < TCP_CA_CWR) {
 			if (!(flag&FLAG_ECE))
@@ -2019,7 +2042,7 @@
 static inline __u32 bictcp_cwnd(struct tcp_opt *tp)
 {
 	/* orignal Reno behaviour */
-	if (!sysctl_tcp_bic)
+	if (!tcp_is_bic(tp))
 		return tp->snd_cwnd;
 
 	if (tp->bictcp.last_cwnd == tp->snd_cwnd &&
@@ -2154,7 +2177,7 @@
 		 * is the cwnd during the previous RTT.
 		 */
 		old_wnd = (tp->vegas.beg_snd_nxt - tp->vegas.beg_snd_una) /
-			tp->mss_cache;
+			tp->mss_cache_std;
 		old_snd_cwnd = tp->vegas.beg_snd_cwnd;
 
 		/* Save the extent of the current window so we can use this
@@ -2325,13 +2348,89 @@
 
 static __inline__ void tcp_ack_packets_out(struct sock *sk, struct tcp_opt *tp)
 {
-	if (tp->packets_out==0) {
+	if (!tcp_get_pcount(&tp->packets_out)) {
 		tcp_clear_xmit_timer(sk, TCP_TIME_RETRANS);
 	} else {
 		tcp_reset_xmit_timer(sk, TCP_TIME_RETRANS, tp->rto);
 	}
 }
 
+/* There is one downside to this scheme.  Although we keep the
+ * ACK clock ticking, adjusting packet counters and advancing
+ * congestion window, we do not liberate socket send buffer
+ * space.
+ *
+ * Mucking with skb->truesize and sk->sk_wmem_alloc et al.
+ * then making a write space wakeup callback is a possible
+ * future enhancement.  WARNING: it is not trivial to make.
+ */
+static int tcp_tso_acked(struct sock *sk, struct sk_buff *skb,
+			 __u32 now, __s32 *seq_rtt)
+{
+	struct tcp_opt *tp = tcp_sk(sk);
+	struct tcp_skb_cb *scb = TCP_SKB_CB(skb); 
+	__u32 mss = tcp_skb_mss(skb);
+	__u32 snd_una = tp->snd_una;
+	__u32 orig_seq, seq;
+	__u32 packets_acked = 0;
+	int acked = 0;
+
+	/* If we get here, the whole TSO packet has not been
+	 * acked.
+	 */
+	BUG_ON(!after(scb->end_seq, snd_una));
+
+	seq = orig_seq = scb->seq;
+	while (!after(seq + mss, snd_una)) {
+		packets_acked++;
+		seq += mss;
+	}
+
+	if (tcp_trim_head(sk, skb, (seq - orig_seq)))
+		return 0;
+
+	if (packets_acked) {
+		__u8 sacked = scb->sacked;
+
+		acked |= FLAG_DATA_ACKED;
+		if (sacked) {
+			if (sacked & TCPCB_RETRANS) {
+				if (sacked & TCPCB_SACKED_RETRANS)
+					tcp_dec_pcount_explicit(&tp->retrans_out,
+								packets_acked);
+				acked |= FLAG_RETRANS_DATA_ACKED;
+				*seq_rtt = -1;
+			} else if (*seq_rtt < 0)
+				*seq_rtt = now - scb->when;
+			if (sacked & TCPCB_SACKED_ACKED)
+				tcp_dec_pcount_explicit(&tp->sacked_out,
+							packets_acked);
+			if (sacked & TCPCB_LOST)
+				tcp_dec_pcount_explicit(&tp->lost_out,
+							packets_acked);
+			if (sacked & TCPCB_URG) {
+				if (tp->urg_mode &&
+				    !before(seq, tp->snd_up))
+					tp->urg_mode = 0;
+			}
+		} else if (*seq_rtt < 0)
+			*seq_rtt = now - scb->when;
+
+		if (tcp_get_pcount(&tp->fackets_out)) {
+			__u32 dval = min(tcp_get_pcount(&tp->fackets_out),
+					 packets_acked);
+			tcp_dec_pcount_explicit(&tp->fackets_out, dval);
+		}
+		tcp_dec_pcount_explicit(&tp->packets_out, packets_acked);
+
+		BUG_ON(tcp_skb_pcount(skb) == 0);
+		BUG_ON(!before(scb->seq, scb->end_seq));
+	}
+
+	return acked;
+}
+
+
 /* Remove acknowledged frames from the retransmission queue. */
 static int tcp_clean_rtx_queue(struct sock *sk, __s32 *seq_rtt_p)
 {
@@ -2341,7 +2440,8 @@
 	int acked = 0;
 	__s32 seq_rtt = -1;
 
-	while ((skb = skb_peek(&sk->sk_write_queue)) && skb != sk->sk_send_head) {
+	while ((skb = skb_peek(&sk->sk_write_queue)) &&
+	       skb != sk->sk_send_head) {
 		struct tcp_skb_cb *scb = TCP_SKB_CB(skb); 
 		__u8 sacked = scb->sacked;
 
@@ -2349,8 +2449,12 @@
 		 * discard it as it's confirmed to have arrived at
 		 * the other end.
 		 */
-		if (after(scb->end_seq, tp->snd_una))
+		if (after(scb->end_seq, tp->snd_una)) {
+			if (tcp_skb_pcount(skb) > 1)
+				acked |= tcp_tso_acked(sk, skb,
+						       now, &seq_rtt);
 			break;
+		}
 
 		/* Initial outgoing SYN's get put onto the write_queue
 		 * just like anything else we transmit.  It is not
@@ -2359,7 +2463,7 @@
 		 * connection startup slow start one packet too
 		 * quickly.  This is severely frowned upon behavior.
 		 */
-		if(!(scb->flags & TCPCB_FLAG_SYN)) {
+		if (!(scb->flags & TCPCB_FLAG_SYN)) {
 			acked |= FLAG_DATA_ACKED;
 		} else {
 			acked |= FLAG_SYN_ACKED;
@@ -2367,27 +2471,26 @@
 		}
 
 		if (sacked) {
-			if(sacked & TCPCB_RETRANS) {
+			if (sacked & TCPCB_RETRANS) {
 				if(sacked & TCPCB_SACKED_RETRANS)
-					tp->retrans_out--;
+					tcp_dec_pcount(&tp->retrans_out, skb);
 				acked |= FLAG_RETRANS_DATA_ACKED;
 				seq_rtt = -1;
 			} else if (seq_rtt < 0)
 				seq_rtt = now - scb->when;
-			if(sacked & TCPCB_SACKED_ACKED)
-				tp->sacked_out--;
-			if(sacked & TCPCB_LOST)
-				tp->lost_out--;
-			if(sacked & TCPCB_URG) {
+			if (sacked & TCPCB_SACKED_ACKED)
+				tcp_dec_pcount(&tp->sacked_out, skb);
+			if (sacked & TCPCB_LOST)
+				tcp_dec_pcount(&tp->lost_out, skb);
+			if (sacked & TCPCB_URG) {
 				if (tp->urg_mode &&
 				    !before(scb->end_seq, tp->snd_up))
 					tp->urg_mode = 0;
 			}
 		} else if (seq_rtt < 0)
 			seq_rtt = now - scb->when;
-		if (tp->fackets_out)
-			tp->fackets_out--;
-		tp->packets_out--;
+		tcp_dec_pcount_approx(&tp->fackets_out, skb);
+		tcp_packets_out_dec(tp, skb);
 		__skb_unlink(skb, skb->list);
 		sk_stream_free_skb(sk, skb);
 	}
@@ -2398,24 +2501,27 @@
 	}
 
 #if FASTRETRANS_DEBUG > 0
-	BUG_TRAP((int)tp->sacked_out >= 0);
-	BUG_TRAP((int)tp->lost_out >= 0);
-	BUG_TRAP((int)tp->retrans_out >= 0);
-	if (!tp->packets_out && tp->sack_ok) {
-		if (tp->lost_out) {
-			printk(KERN_DEBUG "Leak l=%u %d\n", tp->lost_out,
-							    tp->ca_state);
-			tp->lost_out = 0;
-		}
-		if (tp->sacked_out) {
-			printk(KERN_DEBUG "Leak s=%u %d\n", tp->sacked_out,
-							    tp->ca_state);
-			tp->sacked_out = 0;
-		}
-		if (tp->retrans_out) {
-			printk(KERN_DEBUG "Leak r=%u %d\n", tp->retrans_out,
-							    tp->ca_state);
-			tp->retrans_out = 0;
+	BUG_TRAP((int)tcp_get_pcount(&tp->sacked_out) >= 0);
+	BUG_TRAP((int)tcp_get_pcount(&tp->lost_out) >= 0);
+	BUG_TRAP((int)tcp_get_pcount(&tp->retrans_out) >= 0);
+	if (!tcp_get_pcount(&tp->packets_out) && tp->sack_ok) {
+		if (tcp_get_pcount(&tp->lost_out)) {
+			printk(KERN_DEBUG "Leak l=%u %d\n",
+			       tcp_get_pcount(&tp->lost_out),
+			       tp->ca_state);
+			tcp_set_pcount(&tp->lost_out, 0);
+		}
+		if (tcp_get_pcount(&tp->sacked_out)) {
+			printk(KERN_DEBUG "Leak s=%u %d\n",
+			       tcp_get_pcount(&tp->sacked_out),
+			       tp->ca_state);
+			tcp_set_pcount(&tp->sacked_out, 0);
+		}
+		if (tcp_get_pcount(&tp->retrans_out)) {
+			printk(KERN_DEBUG "Leak r=%u %d\n",
+			       tcp_get_pcount(&tp->retrans_out),
+			       tp->ca_state);
+			tcp_set_pcount(&tp->retrans_out, 0);
 		}
 	}
 #endif
@@ -2594,18 +2700,16 @@
  * WESTWOOD_RTT_MIN minimum bound since we could be on a LAN!
  */
 
-static inline __u32 westwood_update_rttmin(struct sock *sk)
+static inline __u32 westwood_update_rttmin(const struct sock *sk)
 {
-	struct tcp_opt *tp = tcp_sk(sk);
+	const struct tcp_opt *tp = tcp_sk(sk);
 	__u32 rttmin = tp->westwood.rtt_min;
 
-	if (tp->westwood.rtt == 0)
-		return(rttmin);
-
-	if (tp->westwood.rtt < tp->westwood.rtt_min || !rttmin)
+	if (tp->westwood.rtt != 0 &&
+	    (tp->westwood.rtt < tp->westwood.rtt_min || !rttmin))
 		rttmin = tp->westwood.rtt;
 
-	return(rttmin);
+	return rttmin;
 }
 
 /*
@@ -2613,11 +2717,11 @@
  * Evaluate increases for dk. 
  */
 
-static inline __u32 westwood_acked(struct sock *sk)
+static inline __u32 westwood_acked(const struct sock *sk)
 {
-	struct tcp_opt *tp = tcp_sk(sk);
+	const struct tcp_opt *tp = tcp_sk(sk);
 
-	return ((tp->snd_una) - (tp->westwood.snd_una));
+	return tp->snd_una - tp->westwood.snd_una;
 }
 
 /*
@@ -2629,9 +2733,9 @@
  * window, 1 if the sample has to be considered in the next window.
  */
 
-static int westwood_new_window(struct sock *sk)
+static int westwood_new_window(const struct sock *sk)
 {
-	struct tcp_opt *tp = tcp_sk(sk);
+	const struct tcp_opt *tp = tcp_sk(sk);
 	__u32 left_bound;
 	__u32 rtt;
 	int ret = 0;
@@ -2665,14 +2769,13 @@
 	struct tcp_opt *tp = tcp_sk(sk);
 	__u32 delta = now - tp->westwood.rtt_win_sx;
 
-        if (!delta)
-                return;
-
-	if (tp->westwood.rtt)
-                westwood_filter(sk, delta);
+        if (delta) {
+		if (tp->westwood.rtt)
+			westwood_filter(sk, delta);
 
-        tp->westwood.bk = 0;
-        tp->westwood.rtt_win_sx = tcp_time_stamp;
+		tp->westwood.bk = 0;
+		tp->westwood.rtt_win_sx = tcp_time_stamp;
+	}
 }
 
 
@@ -2710,19 +2813,19 @@
 {
 	struct tcp_opt *tp = tcp_sk(sk);
 
-	tp->westwood.accounted += tp->mss_cache;
-	tp->westwood.cumul_ack = tp->mss_cache;
+	tp->westwood.accounted += tp->mss_cache_std;
+	tp->westwood.cumul_ack = tp->mss_cache_std;
 }
 
 static inline int westwood_may_change_cumul(struct tcp_opt *tp)
 {
-	return ((tp->westwood.cumul_ack) > tp->mss_cache);
+	return (tp->westwood.cumul_ack > tp->mss_cache_std);
 }
 
 static inline void westwood_partial_update(struct tcp_opt *tp)
 {
 	tp->westwood.accounted -= tp->westwood.cumul_ack;
-	tp->westwood.cumul_ack = tp->mss_cache;
+	tp->westwood.cumul_ack = tp->mss_cache_std;
 }
 
 static inline void westwood_complete_update(struct tcp_opt *tp)
@@ -2737,7 +2840,7 @@
  * delayed or partial acks.
  */
 
-static __u32 westwood_acked_count(struct sock *sk)
+static inline __u32 westwood_acked_count(struct sock *sk)
 {
 	struct tcp_opt *tp = tcp_sk(sk);
 
@@ -2751,7 +2854,7 @@
 
         if (westwood_may_change_cumul(tp)) {
 		/* Partial or delayed ack */
-		if ((tp->westwood.accounted) >= (tp->westwood.cumul_ack))
+		if (tp->westwood.accounted >= tp->westwood.cumul_ack)
 			westwood_partial_update(tp);
 		else
 			westwood_complete_update(tp);
@@ -2833,7 +2936,7 @@
 	 */
 	sk->sk_err_soft = 0;
 	tp->rcv_tstamp = tcp_time_stamp;
-	prior_packets = tp->packets_out;
+	prior_packets = tcp_get_pcount(&tp->packets_out);
 	if (!prior_packets)
 		goto no_queue;
 
@@ -3855,11 +3958,11 @@
 {
 	struct tcp_opt *tp = tcp_sk(sk);
 
-	if (tp->packets_out < tp->snd_cwnd &&
+	if (tcp_get_pcount(&tp->packets_out) < tp->snd_cwnd &&
 	    !(sk->sk_userlocks & SOCK_SNDBUF_LOCK) &&
 	    !tcp_memory_pressure &&
 	    atomic_read(&tcp_memory_allocated) < sysctl_tcp_mem[0]) {
- 		int sndmem = max_t(u32, tp->mss_clamp, tp->mss_cache) +
+ 		int sndmem = max_t(u32, tp->mss_clamp, tp->mss_cache_std) +
 			MAX_TCP_HEADER + 16 + sizeof(struct sk_buff),
 		    demanded = max_t(unsigned int, tp->snd_cwnd,
 						   tp->reordering + 1);
diff -Nru a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c
--- a/net/ipv4/tcp_ipv4.c	2004-10-18 14:56:28 -07:00
+++ b/net/ipv4/tcp_ipv4.c	2004-10-18 14:56:28 -07:00
@@ -1033,11 +1033,7 @@
 
 	switch (type) {
 	case ICMP_SOURCE_QUENCH:
-		/* This is deprecated, but if someone generated it,
-		 * we have no reasons to ignore it.
-		 */
-		if (!sock_owned_by_user(sk))
-			tcp_enter_cwr(tp);
+		/* Just silently ignore these. */
 		goto out;
 	case ICMP_PARAMETERPROB:
 		err = EPROTO;
@@ -2075,7 +2071,7 @@
 	 */
 	tp->snd_ssthresh = 0x7fffffff;	/* Infinity */
 	tp->snd_cwnd_clamp = ~0;
-	tp->mss_cache = 536;
+	tp->mss_cache_std = tp->mss_cache = 536;
 
 	tp->reordering = sysctl_tcp_reordering;
 
@@ -2179,8 +2175,14 @@
 		sk	  = sk_next(st->syn_wait_sk);
 		st->state = TCP_SEQ_STATE_LISTENING;
 		read_unlock_bh(&tp->syn_wait_lock);
-	} else
+	} else {
+	       	tp = tcp_sk(sk);
+		read_lock_bh(&tp->syn_wait_lock);
+		if (tp->listen_opt && tp->listen_opt->qlen)
+			goto start_req;
+		read_unlock_bh(&tp->syn_wait_lock);
 		sk = sk_next(sk);
+	}
 get_sk:
 	sk_for_each_from(sk, node) {
 		if (sk->sk_family == st->family) {
@@ -2190,6 +2192,7 @@
 	       	tp = tcp_sk(sk);
 		read_lock_bh(&tp->syn_wait_lock);
 		if (tp->listen_opt && tp->listen_opt->qlen) {
+start_req:
 			st->uid		= sock_i_uid(sk);
 			st->syn_wait_sk = sk;
 			st->state	= TCP_SEQ_STATE_OPENREQ;
@@ -2617,6 +2620,7 @@
 	.sysctl_wmem		= sysctl_tcp_wmem,
 	.sysctl_rmem		= sysctl_tcp_rmem,
 	.max_header		= MAX_TCP_HEADER,
+	.slab_obj_size		= sizeof(struct tcp_sock),
 };
 
 
diff -Nru a/net/ipv4/tcp_minisocks.c b/net/ipv4/tcp_minisocks.c
--- a/net/ipv4/tcp_minisocks.c	2004-10-18 14:56:49 -07:00
+++ b/net/ipv4/tcp_minisocks.c	2004-10-18 14:56:49 -07:00
@@ -687,7 +687,7 @@
 	/* allocate the newsk from the same slab of the master sock,
 	 * if not, at sk_free time we'll try to free it from the wrong
 	 * slabcache (i.e. is it TCPv4 or v6?) -acme */
-	struct sock *newsk = sk_alloc(PF_INET, GFP_ATOMIC, 0, sk->sk_slab);
+	struct sock *newsk = sk_alloc(PF_INET, GFP_ATOMIC, 0, sk->sk_prot->slab);
 
 	if(newsk != NULL) {
 		struct tcp_opt *newtp;
@@ -752,11 +752,11 @@
 		newtp->mdev = TCP_TIMEOUT_INIT;
 		newtp->rto = TCP_TIMEOUT_INIT;
 
-		newtp->packets_out = 0;
-		newtp->left_out = 0;
-		newtp->retrans_out = 0;
-		newtp->sacked_out = 0;
-		newtp->fackets_out = 0;
+		tcp_set_pcount(&newtp->packets_out, 0);
+		tcp_set_pcount(&newtp->left_out, 0);
+		tcp_set_pcount(&newtp->retrans_out, 0);
+		tcp_set_pcount(&newtp->sacked_out, 0);
+		tcp_set_pcount(&newtp->fackets_out, 0);
 		newtp->snd_ssthresh = 0x7fffffff;
 
 		/* So many TCP implementations out there (incorrectly) count the
@@ -841,7 +841,8 @@
 		if (newtp->ecn_flags&TCP_ECN_OK)
 			newsk->sk_no_largesend = 1;
 
-		tcp_vegas_init(newtp);
+		tcp_ca_init(newtp);
+
 		TCP_INC_STATS_BH(TCP_MIB_PASSIVEOPENS);
 	}
 	return newsk;
diff -Nru a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c
--- a/net/ipv4/tcp_output.c	2004-10-18 14:56:48 -07:00
+++ b/net/ipv4/tcp_output.c	2004-10-18 14:56:48 -07:00
@@ -45,6 +45,12 @@
 /* People can turn this off for buggy TCP's found in printers etc. */
 int sysctl_tcp_retrans_collapse = 1;
 
+/* This limits the percentage of the congestion window which we
+ * will allow a single TSO frame to consume.  Building TSO frames
+ * which are too large can cause TCP streams to be bursty.
+ */
+int sysctl_tcp_tso_win_divisor = 8;
+
 static __inline__
 void update_send_head(struct sock *sk, struct tcp_opt *tp, struct sk_buff *skb)
 {
@@ -52,8 +58,7 @@
 	if (sk->sk_send_head == (struct sk_buff *)&sk->sk_write_queue)
 		sk->sk_send_head = NULL;
 	tp->snd_nxt = TCP_SKB_CB(skb)->end_seq;
-	if (tp->packets_out++ == 0)
-		tcp_reset_xmit_timer(sk, TCP_TIME_RETRANS, tp->rto);
+	tcp_packets_out_inc(sk, tp, skb);
 }
 
 /* SND.NXT, if window was not shrunk.
@@ -123,7 +128,8 @@
 {
 	u32 now = tcp_time_stamp;
 
-	if (!tp->packets_out && (s32)(now - tp->lsndtime) > tp->rto)
+	if (!tcp_get_pcount(&tp->packets_out) &&
+	    (s32)(now - tp->lsndtime) > tp->rto)
 		tcp_cwnd_restart(tp, __sk_dst_get(sk));
 
 	tp->lsndtime = now;
@@ -143,6 +149,65 @@
 	tcp_clear_xmit_timer(sk, TCP_TIME_DACK);
 }
 
+/* Determine a window scaling and initial window to offer.
+ * Based on the assumption that the given amount of space
+ * will be offered. Store the results in the tp structure.
+ * NOTE: for smooth operation initial space offering should
+ * be a multiple of mss if possible. We assume here that mss >= 1.
+ * This MUST be enforced by all callers.
+ */
+void tcp_select_initial_window(int __space, __u32 mss,
+			       __u32 *rcv_wnd, __u32 *window_clamp,
+			       int wscale_ok, __u8 *rcv_wscale)
+{
+	unsigned int space = (__space < 0 ? 0 : __space);
+
+	/* If no clamp set the clamp to the max possible scaled window */
+	if (*window_clamp == 0)
+		(*window_clamp) = (65535 << 14);
+	space = min(*window_clamp, space);
+
+	/* Quantize space offering to a multiple of mss if possible. */
+	if (space > mss)
+		space = (space / mss) * mss;
+
+	/* NOTE: offering an initial window larger than 32767
+	 * will break some buggy TCP stacks. We try to be nice.
+	 * If we are not window scaling, then this truncates
+	 * our initial window offering to 32k. There should also
+	 * be a sysctl option to stop being nice.
+	 */
+	(*rcv_wnd) = min(space, MAX_TCP_WINDOW);
+	(*rcv_wscale) = 0;
+	if (wscale_ok) {
+		/* Set window scaling on max possible window
+		 * See RFC1323 for an explanation of the limit to 14 
+		 */
+		space = max_t(u32, sysctl_tcp_rmem[2], sysctl_rmem_max);
+		while (space > 65535 && (*rcv_wscale) < 14) {
+			space >>= 1;
+			(*rcv_wscale)++;
+		}
+	}
+
+	/* Set initial window to value enough for senders,
+	 * following RFC1414. Senders, not following this RFC,
+	 * will be satisfied with 2.
+	 */
+	if (mss > (1<<*rcv_wscale)) {
+		int init_cwnd = 4;
+		if (mss > 1460*3)
+			init_cwnd = 2;
+		else if (mss > 1460)
+			init_cwnd = 3;
+		if (*rcv_wnd > init_cwnd*mss)
+			*rcv_wnd = init_cwnd*mss;
+	}
+
+	/* Set the clamp no higher than max representable value */
+	(*window_clamp) = min(65535U << (*rcv_wscale), *window_clamp);
+}
+
 /* Chose a new window to advertise, update state in tcp_opt for the
  * socket, and return result with RFC1323 scaling applied.  The return
  * value can be stuffed directly into th->window for an outgoing
@@ -198,9 +263,9 @@
  * We are working here with either a clone of the original
  * SKB, or a fresh unique copy made by the retransmit engine.
  */
-int tcp_transmit_skb(struct sock *sk, struct sk_buff *skb)
+static int tcp_transmit_skb(struct sock *sk, struct sk_buff *skb)
 {
-	if(skb != NULL) {
+	if (skb != NULL) {
 		struct inet_opt *inet = inet_sk(sk);
 		struct tcp_opt *tp = tcp_sk(sk);
 		struct tcp_skb_cb *tcb = TCP_SKB_CB(skb);
@@ -209,6 +274,8 @@
 		int sysctl_flags;
 		int err;
 
+		BUG_ON(!tcp_skb_pcount(skb));
+
 #define SYSCTL_FLAG_TSTAMPS	0x1
 #define SYSCTL_FLAG_WSCALE	0x2
 #define SYSCTL_FLAG_SACK	0x4
@@ -355,13 +422,30 @@
 		if (!tcp_transmit_skb(sk, skb_clone(skb, sk->sk_allocation))) {
 			sk->sk_send_head = NULL;
 			tp->snd_nxt = TCP_SKB_CB(skb)->end_seq;
-			if (tp->packets_out++ == 0)
-				tcp_reset_xmit_timer(sk, TCP_TIME_RETRANS, tp->rto);
+			tcp_packets_out_inc(sk, tp, skb);
 			return;
 		}
 	}
 }
 
+void tcp_set_skb_tso_segs(struct sk_buff *skb, unsigned int mss_std)
+{
+	if (skb->len <= mss_std) {
+		/* Avoid the costly divide in the normal
+		 * non-TSO case.
+		 */
+		skb_shinfo(skb)->tso_segs = 1;
+		skb_shinfo(skb)->tso_size = 0;
+	} else {
+		unsigned int factor;
+
+		factor = skb->len + (mss_std - 1);
+		factor /= mss_std;
+		skb_shinfo(skb)->tso_segs = factor;
+		skb_shinfo(skb)->tso_size = mss_std;
+	}
+}
+
 /* Function to create two new TCP segments.  Shrinks the given segment
  * to the specified size and appends a new segment with the rest of the
  * packet to the list.  This won't be called frequently, I hope. 
@@ -394,11 +478,9 @@
 	flags = TCP_SKB_CB(skb)->flags;
 	TCP_SKB_CB(skb)->flags = flags & ~(TCPCB_FLAG_FIN|TCPCB_FLAG_PSH);
 	TCP_SKB_CB(buff)->flags = flags;
-	TCP_SKB_CB(buff)->sacked = TCP_SKB_CB(skb)->sacked&(TCPCB_LOST|TCPCB_EVER_RETRANS|TCPCB_AT_TAIL);
-	if (TCP_SKB_CB(buff)->sacked&TCPCB_LOST) {
-		tp->lost_out++;
-		tp->left_out++;
-	}
+	TCP_SKB_CB(buff)->sacked =
+		(TCP_SKB_CB(skb)->sacked &
+		 (TCPCB_LOST | TCPCB_EVER_RETRANS | TCPCB_AT_TAIL));
 	TCP_SKB_CB(skb)->sacked &= ~TCPCB_AT_TAIL;
 
 	if (!skb_shinfo(skb)->nr_frags && skb->ip_summed != CHECKSUM_HW) {
@@ -421,6 +503,25 @@
 	 */
 	TCP_SKB_CB(buff)->when = TCP_SKB_CB(skb)->when;
 
+	if (TCP_SKB_CB(skb)->sacked & TCPCB_LOST) {
+		tcp_dec_pcount(&tp->lost_out, skb);
+		tcp_dec_pcount(&tp->left_out, skb);
+	}
+
+	/* Fix up tso_factor for both original and new SKB.  */
+	tcp_set_skb_tso_segs(skb, tp->mss_cache_std);
+	tcp_set_skb_tso_segs(buff, tp->mss_cache_std);
+
+	if (TCP_SKB_CB(skb)->sacked & TCPCB_LOST) {
+		tcp_inc_pcount(&tp->lost_out, skb);
+		tcp_inc_pcount(&tp->left_out, skb);
+	}
+
+	if (TCP_SKB_CB(buff)->sacked&TCPCB_LOST) {
+		tcp_inc_pcount(&tp->lost_out, buff);
+		tcp_inc_pcount(&tp->left_out, buff);
+	}
+
 	/* Link BUFF into the send queue. */
 	__skb_append(skb, buff);
 
@@ -431,7 +532,7 @@
  * eventually). The difference is that pulled data not copied, but
  * immediately discarded.
  */
-unsigned char * __pskb_trim_head(struct sk_buff *skb, int len)
+static unsigned char *__pskb_trim_head(struct sk_buff *skb, int len)
 {
 	int i, k, eat;
 
@@ -459,8 +560,10 @@
 	return skb->tail;
 }
 
-static int tcp_trim_head(struct sock *sk, struct sk_buff *skb, u32 len)
+int tcp_trim_head(struct sock *sk, struct sk_buff *skb, u32 len)
 {
+	struct tcp_opt *tp = tcp_sk(sk);
+
 	if (skb_cloned(skb) &&
 	    pskb_expand_head(skb, 0, 0, GFP_ATOMIC))
 		return -ENOMEM;
@@ -474,6 +577,17 @@
 
 	TCP_SKB_CB(skb)->seq += len;
 	skb->ip_summed = CHECKSUM_HW;
+
+	skb->truesize	     -= len;
+	sk->sk_queue_shrunk   = 1;
+	sk->sk_wmem_queued   -= len;
+	sk->sk_forward_alloc += len;
+
+	/* Any change of skb->len requires recalculation of tso
+	 * factor and mss.
+	 */
+	tcp_set_skb_tso_segs(skb, tp->mss_cache_std);
+
 	return 0;
 }
 
@@ -500,7 +614,7 @@
    this function.			--ANK (980731)
  */
 
-int tcp_sync_mss(struct sock *sk, u32 pmtu)
+unsigned int tcp_sync_mss(struct sock *sk, u32 pmtu)
 {
 	struct tcp_opt *tp = tcp_sk(sk);
 	struct dst_entry *dst = __sk_dst_get(sk);
@@ -536,23 +650,71 @@
 	tp->pmtu_cookie = pmtu;
 	tp->mss_cache = tp->mss_cache_std = mss_now;
 
-	if (sk->sk_route_caps & NETIF_F_TSO) {
-		int large_mss;
+	return mss_now;
+}
+
+/* Compute the current effective MSS, taking SACKs and IP options,
+ * and even PMTU discovery events into account.
+ *
+ * LARGESEND note: !urg_mode is overkill, only frames up to snd_up
+ * cannot be large. However, taking into account rare use of URG, this
+ * is not a big flaw.
+ */
+
+unsigned int tcp_current_mss(struct sock *sk, int large)
+{
+	struct tcp_opt *tp = tcp_sk(sk);
+	struct dst_entry *dst = __sk_dst_get(sk);
+	unsigned int do_large, mss_now;
+
+	mss_now = tp->mss_cache_std;
+	if (dst) {
+		u32 mtu = dst_pmtu(dst);
+		if (mtu != tp->pmtu_cookie ||
+		    tp->ext2_header_len != dst->header_len)
+			mss_now = tcp_sync_mss(sk, mtu);
+	}
+
+	do_large = (large &&
+		    (sk->sk_route_caps & NETIF_F_TSO) &&
+		    !tp->urg_mode);
+
+	if (do_large) {
+		unsigned int large_mss, factor, limit;
 
 		large_mss = 65535 - tp->af_specific->net_header_len -
-			tp->ext_header_len - tp->ext2_header_len - tp->tcp_header_len;
+			tp->ext_header_len - tp->ext2_header_len -
+			tp->tcp_header_len;
 
 		if (tp->max_window && large_mss > (tp->max_window>>1))
-			large_mss = max((tp->max_window>>1), 68U - tp->tcp_header_len);
+			large_mss = max((tp->max_window>>1),
+					68U - tp->tcp_header_len);
+
+		factor = large_mss / mss_now;
 
-		/* Always keep large mss multiple of real mss. */
-		tp->mss_cache = mss_now*(large_mss/mss_now);
+		/* Always keep large mss multiple of real mss, but
+		 * do not exceed 1/tso_win_divisor of the congestion window
+		 * so we can keep the ACK clock ticking and minimize
+		 * bursting.
+		 */
+		limit = tp->snd_cwnd;
+		if (sysctl_tcp_tso_win_divisor)
+			limit /= sysctl_tcp_tso_win_divisor;
+		limit = max(1U, limit);
+		if (factor > limit)
+			factor = limit;
+
+		tp->mss_cache = mss_now * factor;
+
+		mss_now = tp->mss_cache;
 	}
 
+	if (tp->eff_sacks)
+		mss_now -= (TCPOLEN_SACK_BASE_ALIGNED +
+			    (tp->eff_sacks * TCPOLEN_SACK_PERBLOCK));
 	return mss_now;
 }
 
-
 /* This routine writes packets to the network.  It advances the
  * send_head.  This happens as incoming acks open up the remote
  * window for us.
@@ -592,8 +754,12 @@
 			TCP_SKB_CB(skb)->when = tcp_time_stamp;
 			if (tcp_transmit_skb(sk, skb_clone(skb, GFP_ATOMIC)))
 				break;
-			/* Advance the send_head.  This one is sent out. */
+
+			/* Advance the send_head.  This one is sent out.
+			 * This call will increment packets_out.
+			 */
 			update_send_head(sk, tp, skb);
+
 			tcp_minshall_update(tp, mss_now, skb);
 			sent_pkts = 1;
 		}
@@ -603,7 +769,7 @@
 			return 0;
 		}
 
-		return !tp->packets_out && sk->sk_send_head;
+		return !tcp_get_pcount(&tp->packets_out) && sk->sk_send_head;
 	}
 	return 0;
 }
@@ -729,7 +895,7 @@
 	/* The first test we must make is that neither of these two
 	 * SKB's are still referenced by someone else.
 	 */
-	if(!skb_cloned(skb) && !skb_cloned(next_skb)) {
+	if (!skb_cloned(skb) && !skb_cloned(next_skb)) {
 		int skb_size = skb->len, next_skb_size = next_skb->len;
 		u16 flags = TCP_SKB_CB(skb)->flags;
 
@@ -749,6 +915,9 @@
 		    ((skb_size + next_skb_size) > mss_now))
 			return;
 
+		BUG_ON(tcp_skb_pcount(skb) != 1 ||
+		       tcp_skb_pcount(next_skb) != 1);
+
 		/* Ok.  We will be able to collapse the packet. */
 		__skb_unlink(next_skb, next_skb->list);
 
@@ -772,24 +941,23 @@
 		 */
 		TCP_SKB_CB(skb)->sacked |= TCP_SKB_CB(next_skb)->sacked&(TCPCB_EVER_RETRANS|TCPCB_AT_TAIL);
 		if (TCP_SKB_CB(next_skb)->sacked&TCPCB_SACKED_RETRANS)
-			tp->retrans_out--;
+			tcp_dec_pcount(&tp->retrans_out, next_skb);
 		if (TCP_SKB_CB(next_skb)->sacked&TCPCB_LOST) {
-			tp->lost_out--;
-			tp->left_out--;
+			tcp_dec_pcount(&tp->lost_out, next_skb);
+			tcp_dec_pcount(&tp->left_out, next_skb);
 		}
 		/* Reno case is special. Sigh... */
-		if (!tp->sack_ok && tp->sacked_out) {
-			tp->sacked_out--;
-			tp->left_out--;
+		if (!tp->sack_ok && tcp_get_pcount(&tp->sacked_out)) {
+			tcp_dec_pcount_approx(&tp->sacked_out, next_skb);
+			tcp_dec_pcount(&tp->left_out, next_skb);
 		}
 
 		/* Not quite right: it can be > snd.fack, but
 		 * it is better to underestimate fackets.
 		 */
-		if (tp->fackets_out)
-			tp->fackets_out--;
+		tcp_dec_pcount_approx(&tp->fackets_out, next_skb);
+		tcp_packets_out_dec(tp, next_skb);
 		sk_stream_free_skb(sk, next_skb);
-		tp->packets_out--;
 	}
 }
 
@@ -809,11 +977,11 @@
 		    !(TCP_SKB_CB(skb)->sacked&TCPCB_SACKED_ACKED)) {
 			if (TCP_SKB_CB(skb)->sacked&TCPCB_SACKED_RETRANS) {
 				TCP_SKB_CB(skb)->sacked &= ~TCPCB_SACKED_RETRANS;
-				tp->retrans_out--;
+				tcp_dec_pcount(&tp->retrans_out, skb);
 			}
 			if (!(TCP_SKB_CB(skb)->sacked&TCPCB_LOST)) {
 				TCP_SKB_CB(skb)->sacked |= TCPCB_LOST;
-				tp->lost_out++;
+				tcp_inc_pcount(&tp->lost_out, skb);
 				lost = 1;
 			}
 		}
@@ -879,12 +1047,18 @@
 	    && TCP_SKB_CB(skb)->seq != tp->snd_una)
 		return -EAGAIN;
 
-	if(skb->len > cur_mss) {
-		if(tcp_fragment(sk, skb, cur_mss))
+	if (skb->len > cur_mss) {
+		int old_factor = tcp_skb_pcount(skb);
+		int new_factor;
+
+		if (tcp_fragment(sk, skb, cur_mss))
 			return -ENOMEM; /* We'll try again later. */
 
 		/* New SKB created, account for it. */
-		tp->packets_out++;
+		new_factor = tcp_skb_pcount(skb);
+		tcp_dec_pcount_explicit(&tp->packets_out,
+					old_factor - new_factor);
+		tcp_inc_pcount(&tp->packets_out, skb->next);
 	}
 
 	/* Collapse two adjacent packets if worthwhile and we can. */
@@ -908,6 +1082,8 @@
 	   tp->snd_una == (TCP_SKB_CB(skb)->end_seq - 1)) {
 		if (!pskb_trim(skb, 0)) {
 			TCP_SKB_CB(skb)->seq = TCP_SKB_CB(skb)->end_seq - 1;
+			skb_shinfo(skb)->tso_segs = 1;
+			skb_shinfo(skb)->tso_size = 0;
 			skb->ip_summed = CHECKSUM_NONE;
 			skb->csum = 0;
 		}
@@ -933,7 +1109,7 @@
 		}
 #endif
 		TCP_SKB_CB(skb)->sacked |= TCPCB_RETRANS;
-		tp->retrans_out++;
+		tcp_inc_pcount(&tp->retrans_out, skb);
 
 		/* Save stamp of the first retransmit. */
 		if (!tp->retrans_stamp)
@@ -961,13 +1137,20 @@
 {
 	struct tcp_opt *tp = tcp_sk(sk);
 	struct sk_buff *skb;
-	int packet_cnt = tp->lost_out;
+	int packet_cnt = tcp_get_pcount(&tp->lost_out);
 
 	/* First pass: retransmit lost packets. */
 	if (packet_cnt) {
 		sk_stream_for_retrans_queue(skb, sk) {
 			__u8 sacked = TCP_SKB_CB(skb)->sacked;
 
+			/* Assume this retransmit will generate
+			 * only one packet for congestion window
+			 * calculation purposes.  This works because
+			 * tcp_retransmit_skb() will chop up the
+			 * packet to be MSS sized and all the
+			 * packet counting works out.
+			 */
 			if (tcp_packets_in_flight(tp) >= tp->snd_cwnd)
 				return;
 
@@ -985,7 +1168,8 @@
 						tcp_reset_xmit_timer(sk, TCP_TIME_RETRANS, tp->rto);
 				}
 
-				if (--packet_cnt <= 0)
+				packet_cnt -= tcp_skb_pcount(skb);
+				if (packet_cnt <= 0)
 					break;
 			}
 		}
@@ -1004,7 +1188,7 @@
 	/* Yeah, we have to make difficult choice between forward transmission
 	 * and retransmission... Both ways have their merits...
 	 *
-	 * For now we do not retrnamsit anything, while we have some new
+	 * For now we do not retransmit anything, while we have some new
 	 * segments to send.
 	 */
 
@@ -1014,17 +1198,23 @@
 	packet_cnt = 0;
 
 	sk_stream_for_retrans_queue(skb, sk) {
-		if(++packet_cnt > tp->fackets_out)
+		/* Similar to the retransmit loop above we
+		 * can pretend that the retransmitted SKB
+		 * we send out here will be composed of one
+		 * real MSS sized packet because tcp_retransmit_skb()
+		 * will fragment it if necessary.
+		 */
+		if (++packet_cnt > tcp_get_pcount(&tp->fackets_out))
 			break;
 
 		if (tcp_packets_in_flight(tp) >= tp->snd_cwnd)
 			break;
 
-		if(TCP_SKB_CB(skb)->sacked & TCPCB_TAGBITS)
+		if (TCP_SKB_CB(skb)->sacked & TCPCB_TAGBITS)
 			continue;
 
 		/* Ok, retransmit it. */
-		if(tcp_retransmit_skb(sk, skb))
+		if (tcp_retransmit_skb(sk, skb))
 			break;
 
 		if (skb == skb_peek(&sk->sk_write_queue))
@@ -1042,13 +1232,13 @@
 {
 	struct tcp_opt *tp = tcp_sk(sk);	
 	struct sk_buff *skb = skb_peek_tail(&sk->sk_write_queue);
-	unsigned int mss_now;
+	int mss_now;
 	
 	/* Optimization, tack on the FIN if we have a queue of
 	 * unsent frames.  But be careful about outgoing SACKS
 	 * and IP options.
 	 */
-	mss_now = tcp_current_mss(sk, 1); 
+	mss_now = tcp_current_mss(sk, 1);
 
 	if (sk->sk_send_head != NULL) {
 		TCP_SKB_CB(skb)->flags |= TCPCB_FLAG_FIN;
@@ -1068,6 +1258,8 @@
 		skb->csum = 0;
 		TCP_SKB_CB(skb)->flags = (TCPCB_FLAG_ACK | TCPCB_FLAG_FIN);
 		TCP_SKB_CB(skb)->sacked = 0;
+		skb_shinfo(skb)->tso_segs = 1;
+		skb_shinfo(skb)->tso_size = 0;
 
 		/* FIN eats a sequence byte, write_seq advanced by tcp_queue_skb(). */
 		TCP_SKB_CB(skb)->seq = tp->write_seq;
@@ -1099,6 +1291,8 @@
 	skb->csum = 0;
 	TCP_SKB_CB(skb)->flags = (TCPCB_FLAG_ACK | TCPCB_FLAG_RST);
 	TCP_SKB_CB(skb)->sacked = 0;
+	skb_shinfo(skb)->tso_segs = 1;
+	skb_shinfo(skb)->tso_size = 0;
 
 	/* Send it off. */
 	TCP_SKB_CB(skb)->seq = tcp_acceptable_seq(sk, tp);
@@ -1178,6 +1372,9 @@
 	th->dest = req->rmt_port;
 	TCP_SKB_CB(skb)->seq = req->snt_isn;
 	TCP_SKB_CB(skb)->end_seq = TCP_SKB_CB(skb)->seq + 1;
+	TCP_SKB_CB(skb)->sacked = 0;
+	skb_shinfo(skb)->tso_segs = 1;
+	skb_shinfo(skb)->tso_size = 0;
 	th->seq = htonl(TCP_SKB_CB(skb)->seq);
 	th->ack_seq = htonl(req->rcv_isn + 1);
 	if (req->rcv_wnd == 0) { /* ignored for retransmitted syns */
@@ -1233,7 +1430,7 @@
 		tp->window_clamp = dst_metric(dst, RTAX_WINDOW);
 	tp->advmss = dst_metric(dst, RTAX_ADVMSS);
 	tcp_initialize_rcv_mss(sk);
-	tcp_vegas_init(tp);
+	tcp_ca_init(tp);
 
 	tcp_select_initial_window(tcp_full_space(sk),
 				  tp->advmss - (tp->ts_recent_stamp ? tp->tcp_header_len - sizeof(struct tcphdr) : 0),
@@ -1279,19 +1476,21 @@
 	TCP_SKB_CB(buff)->flags = TCPCB_FLAG_SYN;
 	TCP_ECN_send_syn(sk, tp, buff);
 	TCP_SKB_CB(buff)->sacked = 0;
+	skb_shinfo(buff)->tso_segs = 1;
+	skb_shinfo(buff)->tso_size = 0;
 	buff->csum = 0;
 	TCP_SKB_CB(buff)->seq = tp->write_seq++;
 	TCP_SKB_CB(buff)->end_seq = tp->write_seq;
 	tp->snd_nxt = tp->write_seq;
 	tp->pushed_seq = tp->write_seq;
-	tcp_vegas_init(tp);
+	tcp_ca_init(tp);
 
 	/* Send it off. */
 	TCP_SKB_CB(buff)->when = tcp_time_stamp;
 	tp->retrans_stamp = TCP_SKB_CB(buff)->when;
 	__skb_queue_tail(&sk->sk_write_queue, buff);
 	sk_charge_skb(sk, buff);
-	tp->packets_out++;
+	tcp_inc_pcount(&tp->packets_out, buff);
 	tcp_transmit_skb(sk, skb_clone(buff, GFP_KERNEL));
 	TCP_INC_STATS(TCP_MIB_ACTIVEOPENS);
 
@@ -1378,6 +1577,8 @@
 		buff->csum = 0;
 		TCP_SKB_CB(buff)->flags = TCPCB_FLAG_ACK;
 		TCP_SKB_CB(buff)->sacked = 0;
+		skb_shinfo(buff)->tso_segs = 1;
+		skb_shinfo(buff)->tso_size = 0;
 
 		/* Send it off, this clears delayed acks for us. */
 		TCP_SKB_CB(buff)->seq = TCP_SKB_CB(buff)->end_seq = tcp_acceptable_seq(sk, tp);
@@ -1412,6 +1613,8 @@
 	skb->csum = 0;
 	TCP_SKB_CB(skb)->flags = TCPCB_FLAG_ACK;
 	TCP_SKB_CB(skb)->sacked = urgent;
+	skb_shinfo(skb)->tso_segs = 1;
+	skb_shinfo(skb)->tso_size = 0;
 
 	/* Use a previous sequence.  This should cause the other
 	 * end to send an ack.  Don't queue or clone SKB, just
@@ -1432,8 +1635,8 @@
 		if ((skb = sk->sk_send_head) != NULL &&
 		    before(TCP_SKB_CB(skb)->seq, tp->snd_una+tp->snd_wnd)) {
 			int err;
-			int mss = tcp_current_mss(sk, 0);
-			int seg_size = tp->snd_una+tp->snd_wnd-TCP_SKB_CB(skb)->seq;
+			unsigned int mss = tcp_current_mss(sk, 0);
+			unsigned int seg_size = tp->snd_una+tp->snd_wnd-TCP_SKB_CB(skb)->seq;
 
 			if (before(tp->pushed_seq, TCP_SKB_CB(skb)->end_seq))
 				tp->pushed_seq = TCP_SKB_CB(skb)->end_seq;
@@ -1455,7 +1658,9 @@
 					sk->sk_route_caps &= ~NETIF_F_TSO;
 					tp->mss_cache = tp->mss_cache_std;
 				}
-			}
+			} else if (!tcp_skb_pcount(skb))
+				tcp_set_skb_tso_segs(skb, tp->mss_cache_std);
+
 			TCP_SKB_CB(skb)->flags |= TCPCB_FLAG_PSH;
 			TCP_SKB_CB(skb)->when = tcp_time_stamp;
 			err = tcp_transmit_skb(sk, skb_clone(skb, GFP_ATOMIC));
@@ -1483,7 +1688,7 @@
 
 	err = tcp_write_wakeup(sk);
 
-	if (tp->packets_out || !sk->sk_send_head) {
+	if (tcp_get_pcount(&tp->packets_out) || !sk->sk_send_head) {
 		/* Cancel probe timer, if it is not required. */
 		tp->probes_out = 0;
 		tp->backoff = 0;
@@ -1517,6 +1722,5 @@
 EXPORT_SYMBOL(tcp_send_synack);
 EXPORT_SYMBOL(tcp_simple_retransmit);
 EXPORT_SYMBOL(tcp_sync_mss);
-EXPORT_SYMBOL(tcp_transmit_skb);
 EXPORT_SYMBOL(tcp_write_wakeup);
 EXPORT_SYMBOL(tcp_write_xmit);
diff -Nru a/net/ipv4/tcp_timer.c b/net/ipv4/tcp_timer.c
--- a/net/ipv4/tcp_timer.c	2004-10-18 14:57:03 -07:00
+++ b/net/ipv4/tcp_timer.c	2004-10-18 14:57:03 -07:00
@@ -121,7 +121,7 @@
 		 *      1. Last segment was sent recently. */
 		if ((s32)(tcp_time_stamp - tp->lsndtime) <= TCP_TIMEWAIT_LEN ||
 		    /*  2. Window is closed. */
-		    (!tp->snd_wnd && !tp->packets_out))
+		    (!tp->snd_wnd && !tcp_get_pcount(&tp->packets_out)))
 			do_reset = 1;
 		if (do_reset)
 			tcp_send_active_reset(sk, GFP_ATOMIC);
@@ -269,7 +269,7 @@
 	struct tcp_opt *tp = tcp_sk(sk);
 	int max_probes;
 
-	if (tp->packets_out || !sk->sk_send_head) {
+	if (tcp_get_pcount(&tp->packets_out) || !sk->sk_send_head) {
 		tp->probes_out = 0;
 		return;
 	}
@@ -316,7 +316,7 @@
 {
 	struct tcp_opt *tp = tcp_sk(sk);
 
-	if (tp->packets_out == 0)
+	if (!tcp_get_pcount(&tp->packets_out))
 		goto out;
 
 	BUG_TRAP(!skb_queue_empty(&sk->sk_write_queue));
@@ -606,7 +606,7 @@
 	elapsed = keepalive_time_when(tp);
 
 	/* It is alive without keepalive 8) */
-	if (tp->packets_out || sk->sk_send_head)
+	if (tcp_get_pcount(&tp->packets_out) || sk->sk_send_head)
 		goto resched;
 
 	elapsed = tcp_time_stamp - tp->rcv_tstamp;
diff -Nru a/net/ipv4/udp.c b/net/ipv4/udp.c
--- a/net/ipv4/udp.c	2004-10-18 14:56:14 -07:00
+++ b/net/ipv4/udp.c	2004-10-18 14:56:14 -07:00
@@ -1320,6 +1320,7 @@
 	.hash =		udp_v4_hash,
 	.unhash =	udp_v4_unhash,
 	.get_port =	udp_v4_get_port,
+	.slab_obj_size = sizeof(struct udp_sock),
 };
 
 /* ------------------------------------------------------------------------ */
diff -Nru a/net/ipv4/xfrm4_input.c b/net/ipv4/xfrm4_input.c
--- a/net/ipv4/xfrm4_input.c	2004-10-18 14:55:55 -07:00
+++ b/net/ipv4/xfrm4_input.c	2004-10-18 14:55:55 -07:00
@@ -24,8 +24,7 @@
 	struct iphdr *outer_iph = skb->nh.iph;
 	struct iphdr *inner_iph = skb->h.ipiph;
 
-	if (INET_ECN_is_ce(outer_iph->tos) &&
-	    INET_ECN_is_not_ce(inner_iph->tos))
+	if (INET_ECN_is_ce(outer_iph->tos))
 		IP_ECN_set_ce(inner_iph);
 }
 
@@ -102,6 +101,8 @@
 			if (skb_cloned(skb) &&
 			    pskb_expand_head(skb, 0, 0, GFP_ATOMIC))
 				goto drop;
+			if (x->props.flags & XFRM_STATE_DECAP_DSCP)
+				ipv4_copy_dscp(iph, skb->h.ipiph);
 			if (!(x->props.flags & XFRM_STATE_NOECN))
 				ipip_ecn_decapsulate(skb);
 			skb->mac.raw = memmove(skb->data - skb->mac_len,
diff -Nru a/net/ipv4/xfrm4_output.c b/net/ipv4/xfrm4_output.c
--- a/net/ipv4/xfrm4_output.c	2004-10-18 14:56:27 -07:00
+++ b/net/ipv4/xfrm4_output.c	2004-10-18 14:56:27 -07:00
@@ -58,8 +58,7 @@
 	if (!top_iph->frag_off)
 		__ip_select_ident(top_iph, dst, 0);
 
-	/* TTL disclosed */
-	top_iph->ttl = iph->ttl;
+	top_iph->ttl = dst_path_metric(dst, RTAX_HOPLIMIT);
 
 	top_iph->saddr = x->props.saddr.a4;
 	top_iph->daddr = x->id.daddr.a4;
@@ -119,8 +118,7 @@
 
 	xfrm4_encap(skb);
 
-	err = x->type->output(pskb);
-	skb = *pskb;
+	err = x->type->output(skb);
 	if (err)
 		goto error;
 
diff -Nru a/net/ipv4/xfrm4_policy.c b/net/ipv4/xfrm4_policy.c
--- a/net/ipv4/xfrm4_policy.c	2004-10-18 14:56:49 -07:00
+++ b/net/ipv4/xfrm4_policy.c	2004-10-18 14:56:49 -07:00
@@ -12,8 +12,8 @@
 #include <net/xfrm.h>
 #include <net/ip.h>
 
-extern struct dst_ops xfrm4_dst_ops;
-extern struct xfrm_policy_afinfo xfrm4_policy_afinfo;
+static struct dst_ops xfrm4_dst_ops;
+static struct xfrm_policy_afinfo xfrm4_policy_afinfo;
 
 static struct xfrm_type_map xfrm4_type_map = { .lock = RW_LOCK_UNLOCKED };
 
@@ -183,6 +183,15 @@
 			}
 			break;
 
+		case IPPROTO_ICMP:
+			if (pskb_may_pull(skb, xprth + 2 - skb->data)) {
+				u8 *icmp = xprth;
+
+				fl->fl_icmp_type = icmp[0];
+				fl->fl_icmp_code = icmp[1];
+			}
+			break;
+
 		case IPPROTO_ESP:
 			if (pskb_may_pull(skb, xprth + 4 - skb->data)) {
 				u32 *ehdr = (u32 *)xprth;
@@ -234,7 +243,7 @@
 	path->ops->update_pmtu(path, mtu);
 }
 
-struct dst_ops xfrm4_dst_ops = {
+static struct dst_ops xfrm4_dst_ops = {
 	.family =		AF_INET,
 	.protocol =		__constant_htons(ETH_P_IP),
 	.gc =			xfrm4_garbage_collect,
@@ -243,7 +252,7 @@
 	.entry_size =		sizeof(struct xfrm_dst),
 };
 
-struct xfrm_policy_afinfo xfrm4_policy_afinfo = {
+static struct xfrm_policy_afinfo xfrm4_policy_afinfo = {
 	.family = 		AF_INET,
 	.lock = 		RW_LOCK_UNLOCKED,
 	.type_map = 		&xfrm4_type_map,
@@ -254,12 +263,12 @@
 	.decode_session =	_decode_session4,
 };
 
-void __init xfrm4_policy_init(void)
+static void __init xfrm4_policy_init(void)
 {
 	xfrm_policy_register_afinfo(&xfrm4_policy_afinfo);
 }
 
-void __exit xfrm4_policy_fini(void)
+static void __exit xfrm4_policy_fini(void)
 {
 	xfrm_policy_unregister_afinfo(&xfrm4_policy_afinfo);
 }
diff -Nru a/net/ipv4/xfrm4_tunnel.c b/net/ipv4/xfrm4_tunnel.c
--- a/net/ipv4/xfrm4_tunnel.c	2004-10-18 14:55:55 -07:00
+++ b/net/ipv4/xfrm4_tunnel.c	2004-10-18 14:55:55 -07:00
@@ -4,13 +4,13 @@
  */
 
 #include <linux/skbuff.h>
+#include <linux/module.h>
 #include <net/xfrm.h>
 #include <net/ip.h>
 #include <net/protocol.h>
 
-static int ipip_output(struct sk_buff **pskb)
+static int ipip_output(struct sk_buff *skb)
 {
-	struct sk_buff *skb = *pskb;
 	struct iphdr *iph;
 	
 	iph = skb->nh.iph;
@@ -43,6 +43,8 @@
 	return ret;
 }
 
+EXPORT_SYMBOL(xfrm4_tunnel_register);
+
 int xfrm4_tunnel_deregister(struct xfrm_tunnel *handler)
 {
 	int ret;
@@ -60,6 +62,8 @@
 	return ret;
 }
 
+EXPORT_SYMBOL(xfrm4_tunnel_deregister);
+
 static int ipip_rcv(struct sk_buff *skb)
 {
 	struct xfrm_tunnel *handler = ipip_handler;
@@ -68,7 +72,7 @@
 	if (handler && handler->handler(skb) == 0)
 		return 0;
 
-	return xfrm4_rcv_encap(skb, 0);
+	return xfrm4_rcv(skb);
 }
 
 static void ipip_err(struct sk_buff *skb, u32 info)
@@ -84,6 +88,10 @@
 {
 	if (!x->props.mode)
 		return -EINVAL;
+
+	if (x->encap)
+		return -EINVAL;
+
 	x->props.header_len = sizeof(struct iphdr);
 
 	return 0;
diff -Nru a/net/ipv6/Kconfig b/net/ipv6/Kconfig
--- a/net/ipv6/Kconfig	2004-10-18 14:56:32 -07:00
+++ b/net/ipv6/Kconfig	2004-10-18 14:56:32 -07:00
@@ -48,6 +48,7 @@
 	tristate "IPv6: IPComp transformation"
 	depends on IPV6
 	select XFRM
+	select INET6_TUNNEL
 	select CRYPTO
 	select CRYPTO_DEFLATE
 	---help---
@@ -56,9 +57,21 @@
 
 	  If unsure, say Y.
 
+config INET6_TUNNEL
+	tristate "IPv6: tunnel transformation"
+	depends on IPV6
+	select XFRM
+	---help---
+	  Support for generic IPv6-in-IPv6 tunnel transformation, which is
+	  required by the IPv6-in-IPv6 tunneling module as well as tunnel mode
+	  IPComp.
+	  
+	  If unsure, say Y.
+
 config IPV6_TUNNEL
 	tristate "IPv6: IPv6-in-IPv6 tunnel"
 	depends on IPV6
+	select INET6_TUNNEL
 	---help---
 	  Support for IPv6-in-IPv6 tunnels described in RFC 2473.
 
diff -Nru a/net/ipv6/Makefile b/net/ipv6/Makefile
--- a/net/ipv6/Makefile	2004-10-18 14:56:49 -07:00
+++ b/net/ipv6/Makefile	2004-10-18 14:56:49 -07:00
@@ -11,12 +11,13 @@
 		ip6_flowlabel.o ipv6_syms.o
 
 ipv6-$(CONFIG_XFRM) += xfrm6_policy.o xfrm6_state.o xfrm6_input.o \
-	xfrm6_tunnel.o xfrm6_output.o
+	xfrm6_output.o
 ipv6-objs += $(ipv6-y)
 
 obj-$(CONFIG_INET6_AH) += ah6.o
 obj-$(CONFIG_INET6_ESP) += esp6.o
 obj-$(CONFIG_INET6_IPCOMP) += ipcomp6.o
+obj-$(CONFIG_INET6_TUNNEL) += xfrm6_tunnel.o 
 obj-$(CONFIG_NETFILTER)	+= netfilter/
 
 obj-$(CONFIG_IPV6_TUNNEL) += ip6_tunnel.o
diff -Nru a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c
--- a/net/ipv6/addrconf.c	2004-10-18 14:57:04 -07:00
+++ b/net/ipv6/addrconf.c	2004-10-18 14:57:04 -07:00
@@ -128,6 +128,9 @@
 			TIMER_INITIALIZER(addrconf_verify, 0, 0);
 static spinlock_t addrconf_verify_lock = SPIN_LOCK_UNLOCKED;
 
+static void addrconf_join_anycast(struct inet6_ifaddr *ifp);
+static void addrconf_leave_anycast(struct inet6_ifaddr *ifp);
+
 static int addrconf_ifdown(struct net_device *dev, int how);
 
 static void addrconf_dad_start(struct inet6_ifaddr *ifp, int flags);
@@ -419,33 +422,28 @@
 			ipv6_dev_mc_dec(dev, &addr);
 	}
 	for (ifa=idev->addr_list; ifa; ifa=ifa->if_next) {
-		ipv6_addr_prefix(&addr, &ifa->addr, ifa->prefix_len);
-		if (ipv6_addr_any(&addr))
-			continue;
 		if (idev->cnf.forwarding)
-			ipv6_dev_ac_inc(idev->dev, &addr);
+			addrconf_join_anycast(ifa);
 		else
-			ipv6_dev_ac_dec(idev->dev, &addr);
+			addrconf_leave_anycast(ifa);
 	}
 }
 
 
-static void addrconf_forward_change(struct inet6_dev *idev)
+static void addrconf_forward_change(void)
 {
 	struct net_device *dev;
-
-	if (idev) {
-		dev_forward_change(idev);
-		return;
-	}
+	struct inet6_dev *idev;
 
 	read_lock(&dev_base_lock);
 	for (dev=dev_base; dev; dev=dev->next) {
 		read_lock(&addrconf_lock);
 		idev = __in6_dev_get(dev);
 		if (idev) {
+			int changed = (!idev->cnf.forwarding) ^ (!ipv6_devconf.forwarding);
 			idev->cnf.forwarding = ipv6_devconf.forwarding;
-			dev_forward_change(idev);
+			if (changed)
+				dev_forward_change(idev);
 		}
 		read_unlock(&addrconf_lock);
 	}
@@ -472,6 +470,8 @@
 		printk("Freeing alive inet6 address %p\n", ifp);
 		return;
 	}
+	dst_release(&ifp->rt->u.dst);
+
 	inet6_ifa_count--;
 	kfree(ifp);
 }
@@ -482,25 +482,33 @@
 ipv6_add_addr(struct inet6_dev *idev, const struct in6_addr *addr, int pfxlen,
 	      int scope, unsigned flags)
 {
-	struct inet6_ifaddr *ifa;
+	struct inet6_ifaddr *ifa = NULL;
+	struct rt6_info *rt;
 	int hash;
 	static spinlock_t lock = SPIN_LOCK_UNLOCKED;
+	int err = 0;
 
 	spin_lock_bh(&lock);
 
 	/* Ignore adding duplicate addresses on an interface */
 	if (ipv6_chk_same_addr(addr, idev->dev)) {
-		spin_unlock_bh(&lock);
 		ADBG(("ipv6_add_addr: already assigned\n"));
-		return ERR_PTR(-EEXIST);
+		err = -EEXIST;
+		goto out;
 	}
 
 	ifa = kmalloc(sizeof(struct inet6_ifaddr), GFP_ATOMIC);
 
 	if (ifa == NULL) {
-		spin_unlock_bh(&lock);
 		ADBG(("ipv6_add_addr: malloc failed\n"));
-		return ERR_PTR(-ENOBUFS);
+		err = -ENOBUFS;
+		goto out;
+	}
+
+	rt = addrconf_dst_alloc(idev, addr, 0);
+	if (IS_ERR(rt)) {
+		err = PTR_ERR(rt);
+		goto out;
 	}
 
 	memset(ifa, 0, sizeof(struct inet6_ifaddr));
@@ -517,9 +525,8 @@
 	read_lock(&addrconf_lock);
 	if (idev->dead) {
 		read_unlock(&addrconf_lock);
-		spin_unlock_bh(&lock);
-		kfree(ifa);
-		return ERR_PTR(-ENODEV);	/*XXX*/
+		err = -ENODEV;	/*XXX*/
+		goto out;
 	}
 
 	inet6_ifa_count++;
@@ -553,12 +560,20 @@
 	}
 #endif
 
+	ifa->rt = rt;
+
 	in6_ifa_hold(ifa);
 	write_unlock_bh(&idev->lock);
 	read_unlock(&addrconf_lock);
+out:
 	spin_unlock_bh(&lock);
 
-	notifier_call_chain(&inet6addr_chain,NETDEV_UP,ifa);
+	if (unlikely(err == 0))
+		notifier_call_chain(&inet6addr_chain, NETDEV_UP, ifa);
+	else {
+		kfree(ifa);
+		ifa = ERR_PTR(err);
+	}
 
 	return ifa;
 }
@@ -1045,17 +1060,34 @@
 	ipv6_dev_mc_inc(dev, &maddr);
 }
 
-void addrconf_leave_solict(struct net_device *dev, struct in6_addr *addr)
+void addrconf_leave_solict(struct inet6_dev *idev, struct in6_addr *addr)
 {
 	struct in6_addr maddr;
 
-	if (dev->flags&(IFF_LOOPBACK|IFF_NOARP))
+	if (idev->dev->flags&(IFF_LOOPBACK|IFF_NOARP))
 		return;
 
 	addrconf_addr_solict_mult(addr, &maddr);
-	ipv6_dev_mc_dec(dev, &maddr);
+	__ipv6_dev_mc_dec(idev, &maddr);
 }
 
+void addrconf_join_anycast(struct inet6_ifaddr *ifp)
+{
+	struct in6_addr addr;
+	ipv6_addr_prefix(&addr, &ifp->addr, ifp->prefix_len);
+	if (ipv6_addr_any(&addr))
+		return;
+	ipv6_dev_ac_inc(ifp->idev->dev, &addr);
+}
+
+void addrconf_leave_anycast(struct inet6_ifaddr *ifp)
+{
+	struct in6_addr addr;
+	ipv6_addr_prefix(&addr, &ifp->addr, ifp->prefix_len);
+	if (ipv6_addr_any(&addr))
+		return;
+	__ipv6_dev_ac_dec(ifp->idev, &addr);
+}
 
 static int ipv6_generate_eui64(u8 *eui, struct net_device *dev)
 {
@@ -1457,8 +1489,7 @@
 				spin_unlock(&ifp->lock);
 
 				if (!(flags&IFA_F_TENTATIVE))
-					ipv6_ifa_notify((flags&IFA_F_DEPRECATED) ?
-							0 : RTM_NEWADDR, ifp);
+					ipv6_ifa_notify(0, ifp);
 			} else
 				spin_unlock(&ifp->lock);
 
@@ -2056,6 +2087,7 @@
 		neigh_sysctl_unregister(idev->nd_parms);
 #endif
 		neigh_parms_release(&nd_tbl, idev->nd_parms);
+		neigh_ifdown(&nd_tbl, dev);
 		in6_dev_put(idev);
 	}
 	return 0;
@@ -2091,21 +2123,13 @@
 
 		ndisc_send_rs(ifp->idev->dev, &ifp->addr, &all_routers);
 	} else {
-		struct in6_rtmsg rtmsg;
-
 		spin_unlock(&ifp->lock);
-
+		/*
+		 * Note: we do not support deprecated "all on-link"
+		 * assumption any longer.
+		 */
 		printk(KERN_DEBUG "%s: no IPv6 routers present\n",
 		       ifp->idev->dev->name);
-
-		memset(&rtmsg, 0, sizeof(struct in6_rtmsg));
-		rtmsg.rtmsg_type = RTMSG_NEWROUTE;
-		rtmsg.rtmsg_metric = IP6_RT_PRIO_ADDRCONF;
-		rtmsg.rtmsg_flags = (RTF_ALLONLINK | RTF_DEFAULT | RTF_UP);
-
-		rtmsg.rtmsg_ifindex = ifp->idev->dev->ifindex;
-
-		ip6_route_add(&rtmsg, NULL, NULL);
 	}
 
 out:
@@ -2216,14 +2240,6 @@
 		addrconf_mod_timer(ifp, AC_RS, ifp->idev->cnf.rtr_solicit_interval);
 		spin_unlock_bh(&ifp->lock);
 	}
-
-	if (ifp->idev->cnf.forwarding) {
-		struct in6_addr addr;
-
-		ipv6_addr_prefix(&addr, &ifp->addr, ifp->prefix_len);
-		if (!ipv6_addr_any(&addr))
-			ipv6_dev_ac_inc(ifp->idev->dev, &addr);
-	}
 }
 
 #ifdef CONFIG_PROC_FS
@@ -2982,19 +2998,21 @@
 
 	switch (event) {
 	case RTM_NEWADDR:
-		ip6_rt_addr_add(&ifp->addr, ifp->idev->dev, 0);
+		dst_hold(&ifp->rt->u.dst);
+		if (ip6_ins_rt(ifp->rt, NULL, NULL))
+			dst_release(&ifp->rt->u.dst);
+		if (ifp->idev->cnf.forwarding)
+			addrconf_join_anycast(ifp);
 		break;
 	case RTM_DELADDR:
-		addrconf_leave_solict(ifp->idev->dev, &ifp->addr);
-		if (ifp->idev->cnf.forwarding) {
-			struct in6_addr addr;
-
-			ipv6_addr_prefix(&addr, &ifp->addr, ifp->prefix_len);
-			if (!ipv6_addr_any(&addr))
-				ipv6_dev_ac_dec(ifp->idev->dev, &addr);
-		}
-		if (!ipv6_chk_addr(&ifp->addr, ifp->idev->dev, 1))
-			ip6_rt_addr_del(&ifp->addr, ifp->idev->dev);
+		if (ifp->idev->cnf.forwarding)
+			addrconf_leave_anycast(ifp);
+		addrconf_leave_solict(ifp->idev, &ifp->addr);
+		dst_hold(&ifp->rt->u.dst);
+		if (ip6_del_rt(ifp->rt, NULL, NULL))
+			dst_free(&ifp->rt->u.dst);
+		else
+			dst_release(&ifp->rt->u.dst);
 		break;
 	}
 }
@@ -3011,18 +3029,18 @@
 
 	ret = proc_dointvec(ctl, write, filp, buffer, lenp, ppos);
 
-	if (write && *valp != val && valp != &ipv6_devconf_dflt.forwarding) {
-		struct inet6_dev *idev = NULL;
-
+	if (write && valp != &ipv6_devconf_dflt.forwarding) {
 		if (valp != &ipv6_devconf.forwarding) {
-			idev = (struct inet6_dev *)ctl->extra1;
-			if (idev == NULL)
-				return ret;
-		} else
+			if ((!*valp) ^ (!val)) {
+				struct inet6_dev *idev = (struct inet6_dev *)ctl->extra1;
+				if (idev == NULL)
+					return ret;
+				dev_forward_change(idev);
+			}
+		} else {
 			ipv6_devconf_dflt.forwarding = ipv6_devconf.forwarding;
-
-		addrconf_forward_change(idev);
-
+			addrconf_forward_change();
+		}
 		if (*valp)
 			rt6_purge_dflt_routers(0);
 	}
@@ -3063,15 +3081,19 @@
 	}
 
 	if (valp != &ipv6_devconf_dflt.forwarding) {
-		struct inet6_dev *idev;
 		if (valp != &ipv6_devconf.forwarding) {
-			idev = (struct inet6_dev *)table->extra1;
+			struct inet6_dev *idev = (struct inet6_dev *)table->extra1;
+			int changed;
 			if (unlikely(idev == NULL))
 				return -ENODEV;
-		} else
-			idev = NULL;
-		*valp = new;
-		addrconf_forward_change(idev);
+			changed = (!*valp) ^ (!new);
+			*valp = new;
+			if (changed)
+				dev_forward_change(idev);
+		} else {
+			*valp = new;
+			addrconf_forward_change();
+		}
 
 		if (*valp)
 			rt6_purge_dflt_routers(0);
diff -Nru a/net/ipv6/af_inet6.c b/net/ipv6/af_inet6.c
--- a/net/ipv6/af_inet6.c	2004-10-18 14:56:32 -07:00
+++ b/net/ipv6/af_inet6.c	2004-10-18 14:56:32 -07:00
@@ -90,11 +90,6 @@
 atomic_t inet6_sock_nr;
 #endif
 
-/* Per protocol sock slabcache */
-kmem_cache_t *tcp6_sk_cachep;
-kmem_cache_t *udp6_sk_cachep;
-kmem_cache_t *raw6_sk_cachep;
-
 /* The inetsw table contains everything that inet_create needs to
  * build a new socket.
  */
@@ -110,37 +105,11 @@
 #endif
 }
 
-static __inline__ kmem_cache_t *inet6_sk_slab(int protocol)
-{
-        kmem_cache_t* rc = tcp6_sk_cachep;
-
-        if (protocol == IPPROTO_UDP)
-                rc = udp6_sk_cachep;
-        else if (protocol == IPPROTO_RAW)
-                rc = raw6_sk_cachep;
-        return rc;
-}
-
-static __inline__ int inet6_sk_size(int protocol)
-{
-        int rc = sizeof(struct tcp6_sock);
-
-        if (protocol == IPPROTO_UDP)
-                rc = sizeof(struct udp6_sock);
-        else if (protocol == IPPROTO_RAW)
-                rc = sizeof(struct raw6_sock);
-        return rc;
-}
-
 static __inline__ struct ipv6_pinfo *inet6_sk_generic(struct sock *sk)
 {
-	struct ipv6_pinfo *rc = (&((struct tcp6_sock *)sk)->inet6);
+	const int offset = sk->sk_prot->slab_obj_size - sizeof(struct ipv6_pinfo);
 
-        if (sk->sk_protocol == IPPROTO_UDP)
-                rc = (&((struct udp6_sock *)sk)->inet6);
-        else if (sk->sk_protocol == IPPROTO_RAW)
-                rc = (&((struct raw6_sock *)sk)->inet6);
-        return rc;
+	return (struct ipv6_pinfo *)(((u8 *)sk) + offset);
 }
 
 static int inet6_create(struct socket *sock, int protocol)
@@ -151,11 +120,10 @@
 	struct tcp6_sock* tcp6sk;
 	struct list_head *p;
 	struct inet_protosw *answer;
-
-	sk = sk_alloc(PF_INET6, GFP_KERNEL, inet6_sk_size(protocol),
-		      inet6_sk_slab(protocol));
-	if (sk == NULL) 
-		goto do_oom;
+	struct proto *answer_prot;
+	unsigned char answer_flags;
+	char answer_no_check;
+	int rc;
 
 	/* Look for the requested type/protocol pair. */
 	answer = NULL;
@@ -179,22 +147,40 @@
 		answer = NULL;
 	}
 
+	rc = -ESOCKTNOSUPPORT;
 	if (!answer)
-		goto free_and_badtype;
+		goto out_rcu_unlock;
+	rc = -EPERM;
 	if (answer->capability > 0 && !capable(answer->capability))
-		goto free_and_badperm;
+		goto out_rcu_unlock;
+	rc = -EPROTONOSUPPORT;
 	if (!protocol)
-		goto free_and_noproto;
+		goto out_rcu_unlock;
 
 	sock->ops = answer->ops;
+
+	answer_prot = answer->prot;
+	answer_no_check = answer->no_check;
+	answer_flags = answer->flags;
+	rcu_read_unlock();
+
+	BUG_TRAP(answer_prot->slab != NULL);
+
+	rc = -ENOBUFS;
+	sk = sk_alloc(PF_INET6, GFP_KERNEL,
+		      answer_prot->slab_obj_size,
+		      answer_prot->slab);
+	if (sk == NULL)
+		goto out;
+
 	sock_init_data(sock, sk);
 	sk_set_owner(sk, THIS_MODULE);
 
-	sk->sk_prot = answer->prot;
-	sk->sk_no_check = answer->no_check;
-	if (INET_PROTOSW_REUSE & answer->flags)
+	rc = 0;
+	sk->sk_prot = answer_prot;
+	sk->sk_no_check = answer_no_check;
+	if (INET_PROTOSW_REUSE & answer_flags)
 		sk->sk_reuse = 1;
-	rcu_read_unlock();
 
 	inet = inet_sk(sk);
 
@@ -205,7 +191,6 @@
 	}
 
 	sk->sk_destruct		= inet6_sock_destruct;
-	sk->sk_zapped		= 0;
 	sk->sk_family		= PF_INET6;
 	sk->sk_protocol		= protocol;
 
@@ -248,28 +233,17 @@
 		sk->sk_prot->hash(sk);
 	}
 	if (sk->sk_prot->init) {
-		int err = sk->sk_prot->init(sk);
-		if (err != 0) {
+		rc = sk->sk_prot->init(sk);
+		if (rc) {
 			sk_common_release(sk);
-			return err;
+			goto out;
 		}
 	}
-	return 0;
-
-free_and_badtype:
-	rcu_read_unlock();
-	sk_free(sk);
-	return -ESOCKTNOSUPPORT;
-free_and_badperm:
-	rcu_read_unlock();
-	sk_free(sk);
-	return -EPERM;
-free_and_noproto:
+out:
+	return rc;
+out_rcu_unlock:
 	rcu_read_unlock();
-	sk_free(sk);
-	return -EPROTONOSUPPORT;
-do_oom:
-	return -ENOBUFS;
+	goto out;
 }
 
 
@@ -709,24 +683,26 @@
 #endif
 #endif
 
-	if (sizeof(struct inet6_skb_parm) > sizeof(dummy_skb->cb))
-	{
+	if (sizeof(struct inet6_skb_parm) > sizeof(dummy_skb->cb)) {
 		printk(KERN_CRIT "inet6_proto_init: size fault\n");
 		return -EINVAL;
 	}
-	/* allocate our sock slab caches */
-        tcp6_sk_cachep = kmem_cache_create("tcp6_sock",
-					   sizeof(struct tcp6_sock), 0,
-                                           SLAB_HWCACHE_ALIGN, NULL, NULL);
-        udp6_sk_cachep = kmem_cache_create("udp6_sock",
-					   sizeof(struct udp6_sock), 0,
-                                           SLAB_HWCACHE_ALIGN, NULL, NULL);
-        raw6_sk_cachep = kmem_cache_create("raw6_sock",
-					   sizeof(struct raw6_sock), 0,
-                                           SLAB_HWCACHE_ALIGN, NULL, NULL);
-        if (!tcp6_sk_cachep || !udp6_sk_cachep || !raw6_sk_cachep)
-                printk(KERN_CRIT "%s: Can't create protocol sock SLAB "
-		       "caches!\n", __FUNCTION__);
+
+	err = sk_alloc_slab(&tcpv6_prot, "tcpv6_sock");
+	if (err) {
+		sk_alloc_slab_error(&tcpv6_prot);
+		goto out;
+	}
+	err = sk_alloc_slab(&udpv6_prot, "udpv6_sock");
+	if (err) {
+		sk_alloc_slab_error(&udpv6_prot);
+		goto out_tcp_free_slab;
+	}
+	err = sk_alloc_slab(&rawv6_prot, "rawv6_sock");
+	if (err) {
+		sk_alloc_slab_error(&rawv6_prot);
+		goto out_udp_free_slab;
+	}
 
 	/* Register the socket-side information for inet6_create.  */
 	for(r = &inetsw6[0]; r < &inetsw6[SOCK_MAX]; ++r)
@@ -745,7 +721,7 @@
 	/* Initialise ipv6 mibs */
 	err = init_ipv6_mibs();
 	if (err)
-		goto init_mib_fail;
+		goto out_raw_free_slab;
 	
 	/*
 	 *	ipngwg API draft makes clear that the correct semantics
@@ -798,8 +774,9 @@
 	/* Init v6 transport protocols. */
 	udpv6_init();
 	tcpv6_init();
-
-	return 0;
+	err = 0;
+out:
+	return err;
 
 #ifdef CONFIG_PROC_FS
 proc_if6_fail:
@@ -824,8 +801,13 @@
 	ipv6_sysctl_unregister();
 #endif
 	cleanup_ipv6_mibs();
-init_mib_fail:
-	return err;
+out_raw_free_slab:
+	sk_free_slab(&rawv6_prot);
+out_udp_free_slab:
+	sk_free_slab(&udpv6_prot);
+out_tcp_free_slab:
+	sk_free_slab(&tcpv6_prot);
+	goto out;
 }
 module_init(inet6_init);
 
@@ -854,9 +836,9 @@
 	ipv6_sysctl_unregister();	
 #endif
 	cleanup_ipv6_mibs();
-	kmem_cache_destroy(tcp6_sk_cachep);
-	kmem_cache_destroy(udp6_sk_cachep);
-	kmem_cache_destroy(raw6_sk_cachep);
+	sk_free_slab(&rawv6_prot);
+	sk_free_slab(&udpv6_prot);
+	sk_free_slab(&tcpv6_prot);
 }
 module_exit(inet6_exit);
 
diff -Nru a/net/ipv6/ah6.c b/net/ipv6/ah6.c
--- a/net/ipv6/ah6.c	2004-10-18 14:56:48 -07:00
+++ b/net/ipv6/ah6.c	2004-10-18 14:56:48 -07:00
@@ -154,11 +154,11 @@
 	return 0;
 }
 
-int ah6_output(struct sk_buff **pskb)
+static int ah6_output(struct sk_buff *skb)
 {
 	int err;
 	int extlen;
-	struct dst_entry *dst = (*pskb)->dst;
+	struct dst_entry *dst = skb->dst;
 	struct xfrm_state *x  = dst->xfrm;
 	struct ipv6hdr *top_iph;
 	struct ip_auth_hdr *ah;
@@ -170,11 +170,11 @@
 		char hdrs[0];
 	} *tmp_ext;
 
-	top_iph = (struct ipv6hdr *)(*pskb)->data;
-	top_iph->payload_len = htons((*pskb)->len - sizeof(*top_iph));
+	top_iph = (struct ipv6hdr *)skb->data;
+	top_iph->payload_len = htons(skb->len - sizeof(*top_iph));
 
-	nexthdr = *(*pskb)->nh.raw;
-	*(*pskb)->nh.raw = IPPROTO_AH;
+	nexthdr = *skb->nh.raw;
+	*skb->nh.raw = IPPROTO_AH;
 
 	/* When there are no extension headers, we only need to save the first
 	 * 8 bytes of the base IP header.
@@ -182,7 +182,7 @@
 	memcpy(tmp_base, top_iph, sizeof(tmp_base));
 
 	tmp_ext = NULL;
-	extlen = (*pskb)->h.raw - (unsigned char *)(top_iph + 1);
+	extlen = skb->h.raw - (unsigned char *)(top_iph + 1);
 	if (extlen) {
 		extlen += sizeof(*tmp_ext);
 		tmp_ext = kmalloc(extlen, GFP_ATOMIC);
@@ -198,7 +198,7 @@
 			goto error_free_iph;
 	}
 
-	ah = (struct ip_auth_hdr *)(*pskb)->h.raw;
+	ah = (struct ip_auth_hdr *)skb->h.raw;
 	ah->nexthdr = nexthdr;
 
 	top_iph->priority    = 0;
@@ -214,7 +214,7 @@
 	ah->reserved = 0;
 	ah->spi = x->id.spi;
 	ah->seq_no = htonl(++x->replay.oseq);
-	ahp->icv(ahp, *pskb, ah->auth_data);
+	ahp->icv(ahp, skb, ah->auth_data);
 
 	err = 0;
 
@@ -229,7 +229,7 @@
 	return err;
 }
 
-int ah6_input(struct xfrm_state *x, struct xfrm_decap_state *decap, struct sk_buff *skb)
+static int ah6_input(struct xfrm_state *x, struct xfrm_decap_state *decap, struct sk_buff *skb)
 {
 	/*
 	 * Before process AH
@@ -319,8 +319,8 @@
 	return -EINVAL;
 }
 
-void ah6_err(struct sk_buff *skb, struct inet6_skb_parm *opt, 
-	 int type, int code, int offset, __u32 info)
+static void ah6_err(struct sk_buff *skb, struct inet6_skb_parm *opt, 
+                    int type, int code, int offset, __u32 info)
 {
 	struct ipv6hdr *iph = (struct ipv6hdr*)skb->data;
 	struct ip_auth_hdr *ah = (struct ip_auth_hdr*)(skb->data+offset);
@@ -353,6 +353,9 @@
 	if (x->aalg->alg_key_len > 512)
 		goto error;
 
+	if (x->encap)
+		goto error;
+
 	ahp = kmalloc(sizeof(*ahp), GFP_KERNEL);
 	if (ahp == NULL)
 		return -ENOMEM;
@@ -445,7 +448,7 @@
 	.flags		=	INET6_PROTO_NOPOLICY,
 };
 
-int __init ah6_init(void)
+static int __init ah6_init(void)
 {
 	if (xfrm_register_type(&ah6_type, AF_INET6) < 0) {
 		printk(KERN_INFO "ipv6 ah init: can't add xfrm type\n");
diff -Nru a/net/ipv6/anycast.c b/net/ipv6/anycast.c
--- a/net/ipv6/anycast.c	2004-10-18 14:55:54 -07:00
+++ b/net/ipv6/anycast.c	2004-10-18 14:55:54 -07:00
@@ -293,6 +293,7 @@
 {
 	if (atomic_dec_and_test(&ac->aca_refcnt)) {
 		in6_dev_put(ac->aca_idev);
+		dst_release(&ac->aca_rt->u.dst);
 		kfree(ac);
 	}
 }
@@ -304,6 +305,8 @@
 {
 	struct ifacaddr6 *aca;
 	struct inet6_dev *idev;
+	struct rt6_info *rt;
+	int err;
 
 	idev = in6_dev_get(dev);
 
@@ -312,17 +315,15 @@
 
 	write_lock_bh(&idev->lock);
 	if (idev->dead) {
-		write_unlock_bh(&idev->lock);
-		in6_dev_put(idev);
-		return -ENODEV;
+		err = -ENODEV;
+		goto out;
 	}
 
 	for (aca = idev->ac_list; aca; aca = aca->aca_next) {
 		if (ipv6_addr_cmp(&aca->aca_addr, addr) == 0) {
 			aca->aca_users++;
-			write_unlock_bh(&idev->lock);
-			in6_dev_put(idev);
-			return 0;
+			err = 0;
+			goto out;
 		}
 	}
 
@@ -333,15 +334,22 @@
 	aca = kmalloc(sizeof(struct ifacaddr6), GFP_ATOMIC);
 
 	if (aca == NULL) {
-		write_unlock_bh(&idev->lock);
-		in6_dev_put(idev);
-		return -ENOMEM;
+		err = -ENOMEM;
+		goto out;
+	}
+
+	rt = addrconf_dst_alloc(idev, addr, 1);
+	if (IS_ERR(rt)) {
+		kfree(aca);
+		err = PTR_ERR(rt);
+		goto out;
 	}
 
 	memset(aca, 0, sizeof(struct ifacaddr6));
 
 	ipv6_addr_copy(&aca->aca_addr, addr);
 	aca->aca_idev = idev;
+	aca->aca_rt = rt;
 	aca->aca_users = 1;
 	/* aca_tstamp should be updated upon changes */
 	aca->aca_cstamp = aca->aca_tstamp = jiffies;
@@ -352,26 +360,27 @@
 	idev->ac_list = aca;
 	write_unlock_bh(&idev->lock);
 
-	ip6_rt_addr_add(&aca->aca_addr, dev, 1);
+	dst_hold(&rt->u.dst);
+	if (ip6_ins_rt(rt, NULL, NULL))
+		dst_release(&rt->u.dst);
 
 	addrconf_join_solict(dev, &aca->aca_addr);
 
 	aca_put(aca);
 	return 0;
+out:
+	write_unlock_bh(&idev->lock);
+	in6_dev_put(idev);
+	return err;
 }
 
 /*
  *	device anycast group decrement
  */
-int ipv6_dev_ac_dec(struct net_device *dev, struct in6_addr *addr)
+int __ipv6_dev_ac_dec(struct inet6_dev *idev, struct in6_addr *addr)
 {
-	struct inet6_dev *idev;
 	struct ifacaddr6 *aca, *prev_aca;
 
-	idev = in6_dev_get(dev);
-	if (idev == NULL)
-		return -ENODEV;
-
 	write_lock_bh(&idev->lock);
 	prev_aca = NULL;
 	for (aca = idev->ac_list; aca; aca = aca->aca_next) {
@@ -381,12 +390,10 @@
 	}
 	if (!aca) {
 		write_unlock_bh(&idev->lock);
-		in6_dev_put(idev);
 		return -ENOENT;
 	}
 	if (--aca->aca_users > 0) {
 		write_unlock_bh(&idev->lock);
-		in6_dev_put(idev);
 		return 0;
 	}
 	if (prev_aca)
@@ -394,15 +401,29 @@
 	else
 		idev->ac_list = aca->aca_next;
 	write_unlock_bh(&idev->lock);
-	addrconf_leave_solict(dev, &aca->aca_addr);
+	addrconf_leave_solict(idev, &aca->aca_addr);
 
-	ip6_rt_addr_del(&aca->aca_addr, dev);
+	dst_hold(&aca->aca_rt->u.dst);
+	if (ip6_del_rt(aca->aca_rt, NULL, NULL))
+		dst_free(&aca->aca_rt->u.dst);
+	else
+		dst_release(&aca->aca_rt->u.dst);
 
 	aca_put(aca);
-	in6_dev_put(idev);
 	return 0;
 }
 
+int ipv6_dev_ac_dec(struct net_device *dev, struct in6_addr *addr)
+{
+	int ret;
+	struct inet6_dev *idev = in6_dev_get(dev);
+	if (idev == NULL)
+		return -ENODEV;
+	ret = __ipv6_dev_ac_dec(idev, addr);
+	in6_dev_put(idev);
+	return ret;
+}
+	
 /*
  *	check if the interface has this anycast address
  */
diff -Nru a/net/ipv6/datagram.c b/net/ipv6/datagram.c
--- a/net/ipv6/datagram.c	2004-10-18 14:55:54 -07:00
+++ b/net/ipv6/datagram.c	2004-10-18 14:55:54 -07:00
@@ -38,7 +38,7 @@
 	struct sockaddr_in6	*usin = (struct sockaddr_in6 *) uaddr;
 	struct inet_opt      	*inet = inet_sk(sk);
 	struct ipv6_pinfo      	*np = inet6_sk(sk);
-	struct in6_addr		*daddr;
+	struct in6_addr		*daddr, *final_p = NULL, final;
 	struct dst_entry	*dst;
 	struct flowi		fl;
 	struct ip6_flowlabel	*flowlabel = NULL;
@@ -157,16 +157,27 @@
 	if (flowlabel) {
 		if (flowlabel->opt && flowlabel->opt->srcrt) {
 			struct rt0_hdr *rt0 = (struct rt0_hdr *) flowlabel->opt->srcrt;
+			ipv6_addr_copy(&final, &fl.fl6_dst);
 			ipv6_addr_copy(&fl.fl6_dst, rt0->addr);
+			final_p = &final;
 		}
 	} else if (np->opt && np->opt->srcrt) {
 		struct rt0_hdr *rt0 = (struct rt0_hdr *)np->opt->srcrt;
+		ipv6_addr_copy(&final, &fl.fl6_dst);
 		ipv6_addr_copy(&fl.fl6_dst, rt0->addr);
+		final_p = &final;
 	}
 
 	err = ip6_dst_lookup(sk, &dst, &fl);
 	if (err)
 		goto out;
+	if (final_p)
+		ipv6_addr_copy(&fl.fl6_dst, final_p);
+
+	if ((err = xfrm_lookup(&dst, &fl, sk, 0)) < 0) {
+		dst_release(dst);
+		goto out;
+	}
 
 	/* source address lookup done in ip6_dst_lookup */
 
diff -Nru a/net/ipv6/esp6.c b/net/ipv6/esp6.c
--- a/net/ipv6/esp6.c	2004-10-18 14:56:33 -07:00
+++ b/net/ipv6/esp6.c	2004-10-18 14:56:33 -07:00
@@ -37,11 +37,11 @@
 #include <net/ipv6.h>
 #include <linux/icmpv6.h>
 
-int esp6_output(struct sk_buff **pskb)
+static int esp6_output(struct sk_buff *skb)
 {
 	int err;
 	int hdr_len;
-	struct dst_entry *dst = (*pskb)->dst;
+	struct dst_entry *dst = skb->dst;
 	struct xfrm_state *x  = dst->xfrm;
 	struct ipv6hdr *top_iph;
 	struct ipv6_esp_hdr *esph;
@@ -54,17 +54,17 @@
 	int nfrags;
 
 	esp = x->data;
-	hdr_len = (*pskb)->h.raw - (*pskb)->data +
+	hdr_len = skb->h.raw - skb->data +
 		  sizeof(*esph) + esp->conf.ivlen;
 
 	/* Strip IP+ESP header. */
-	__skb_pull(*pskb, hdr_len);
+	__skb_pull(skb, hdr_len);
 
 	/* Now skb is pure payload to encrypt */
 	err = -ENOMEM;
 
 	/* Round to block size */
-	clen = (*pskb)->len;
+	clen = skb->len;
 
 	alen = esp->auth.icv_trunc_len;
 	tfm = esp->conf.tfm;
@@ -73,24 +73,24 @@
 	if (esp->conf.padlen)
 		clen = (clen + esp->conf.padlen-1)&~(esp->conf.padlen-1);
 
-	if ((nfrags = skb_cow_data(*pskb, clen-(*pskb)->len+alen, &trailer)) < 0) {
+	if ((nfrags = skb_cow_data(skb, clen-skb->len+alen, &trailer)) < 0) {
 		goto error;
 	}
 
 	/* Fill padding... */
 	do {
 		int i;
-		for (i=0; i<clen-(*pskb)->len - 2; i++)
+		for (i=0; i<clen-skb->len - 2; i++)
 			*(u8*)(trailer->tail + i) = i+1;
 	} while (0);
-	*(u8*)(trailer->tail + clen-(*pskb)->len - 2) = (clen - (*pskb)->len)-2;
-	pskb_put(*pskb, trailer, clen - (*pskb)->len);
+	*(u8*)(trailer->tail + clen-skb->len - 2) = (clen - skb->len)-2;
+	pskb_put(skb, trailer, clen - skb->len);
 
-	top_iph = (struct ipv6hdr *)__skb_push(*pskb, hdr_len);
-	esph = (struct ipv6_esp_hdr *)(*pskb)->h.raw;
-	top_iph->payload_len = htons((*pskb)->len + alen - sizeof(*top_iph));
-	*(u8*)(trailer->tail - 1) = *(*pskb)->nh.raw;
-	*(*pskb)->nh.raw = IPPROTO_ESP;
+	top_iph = (struct ipv6hdr *)__skb_push(skb, hdr_len);
+	esph = (struct ipv6_esp_hdr *)skb->h.raw;
+	top_iph->payload_len = htons(skb->len + alen - sizeof(*top_iph));
+	*(u8*)(trailer->tail - 1) = *skb->nh.raw;
+	*skb->nh.raw = IPPROTO_ESP;
 
 	esph->spi = x->id.spi;
 	esph->seq_no = htonl(++x->replay.oseq);
@@ -106,7 +106,7 @@
 			if (!sg)
 				goto error;
 		}
-		skb_to_sgvec(*pskb, sg, esph->enc_data+esp->conf.ivlen-(*pskb)->data, clen);
+		skb_to_sgvec(skb, sg, esph->enc_data+esp->conf.ivlen-skb->data, clen);
 		crypto_cipher_encrypt(tfm, sg, sg, clen);
 		if (unlikely(sg != &esp->sgbuf[0]))
 			kfree(sg);
@@ -118,9 +118,9 @@
 	}
 
 	if (esp->auth.icv_full_len) {
-		esp->auth.icv(esp, *pskb, (u8*)esph-(*pskb)->data,
+		esp->auth.icv(esp, skb, (u8*)esph-skb->data,
 			sizeof(struct ipv6_esp_hdr) + esp->conf.ivlen+clen, trailer->tail);
-		pskb_put(*pskb, trailer, alen);
+		pskb_put(skb, trailer, alen);
 	}
 
 	err = 0;
@@ -129,7 +129,7 @@
 	return err;
 }
 
-int esp6_input(struct xfrm_state *x, struct xfrm_decap_state *decap, struct sk_buff *skb)
+static int esp6_input(struct xfrm_state *x, struct xfrm_decap_state *decap, struct sk_buff *skb)
 {
 	struct ipv6hdr *iph;
 	struct ipv6_esp_hdr *esph;
@@ -252,8 +252,8 @@
 	return mtu + x->props.header_len + esp->auth.icv_full_len;
 }
 
-void esp6_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
-		int type, int code, int offset, __u32 info)
+static void esp6_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
+                     int type, int code, int offset, __u32 info)
 {
 	struct ipv6hdr *iph = (struct ipv6hdr*)skb->data;
 	struct ipv6_esp_hdr *esph = (struct ipv6_esp_hdr*)(skb->data+offset);
@@ -272,7 +272,7 @@
 	xfrm_state_put(x);
 }
 
-void esp6_destroy(struct xfrm_state *x)
+static void esp6_destroy(struct xfrm_state *x)
 {
 	struct esp_data *esp = x->data;
 
@@ -298,17 +298,21 @@
 	kfree(esp);
 }
 
-int esp6_init_state(struct xfrm_state *x, void *args)
+static int esp6_init_state(struct xfrm_state *x, void *args)
 {
 	struct esp_data *esp = NULL;
 
+	/* null auth and encryption can have zero length keys */
 	if (x->aalg) {
-		if (x->aalg->alg_key_len == 0 || x->aalg->alg_key_len > 512)
+		if (x->aalg->alg_key_len > 512)
 			goto error;
 	}
 	if (x->ealg == NULL)
 		goto error;
 
+	if (x->encap)
+		goto error;
+
 	esp = kmalloc(sizeof(*esp), GFP_KERNEL);
 	if (esp == NULL)
 		return -ENOMEM;
@@ -398,7 +402,7 @@
 	.flags		=	INET6_PROTO_NOPOLICY,
 };
 
-int __init esp6_init(void)
+static int __init esp6_init(void)
 {
 	if (xfrm_register_type(&esp6_type, AF_INET6) < 0) {
 		printk(KERN_INFO "ipv6 esp init: can't add xfrm type\n");
diff -Nru a/net/ipv6/exthdrs.c b/net/ipv6/exthdrs.c
--- a/net/ipv6/exthdrs.c	2004-10-18 14:55:54 -07:00
+++ b/net/ipv6/exthdrs.c	2004-10-18 14:55:54 -07:00
@@ -314,9 +314,11 @@
 	dst_release(xchg(&skb->dst, NULL));
 	ip6_route_input(skb);
 	if (skb->dst->error) {
+		skb_push(skb, skb->data - skb->nh.raw);
 		dst_input(skb);
 		return -1;
 	}
+
 	if (skb->dst->dev->flags&IFF_LOOPBACK) {
 		if (skb->nh.ipv6h->hop_limit <= 1) {
 			IP6_INC_STATS_BH(IPSTATS_MIB_INHDRERRORS);
@@ -329,6 +331,7 @@
 		goto looped_back;
 	}
 
+	skb_push(skb, skb->data - skb->nh.raw);
 	dst_input(skb);
 	return -1;
 }
diff -Nru a/net/ipv6/exthdrs_core.c b/net/ipv6/exthdrs_core.c
--- a/net/ipv6/exthdrs_core.c	2004-10-18 14:56:33 -07:00
+++ b/net/ipv6/exthdrs_core.c	2004-10-18 14:56:33 -07:00
@@ -68,34 +68,35 @@
 	u8 nexthdr = *nexthdrp;
 
 	while (ipv6_ext_hdr(nexthdr)) {
-		struct ipv6_opt_hdr hdr;
+		struct ipv6_opt_hdr _hdr, *hp;
 		int hdrlen;
 
 		if (len < (int)sizeof(struct ipv6_opt_hdr))
 			return -1;
 		if (nexthdr == NEXTHDR_NONE)
 			return -1;
-		if (skb_copy_bits(skb, start, &hdr, sizeof(hdr)))
+		hp = skb_header_pointer(skb, start, sizeof(_hdr), &_hdr);
+		if (hp == NULL)
 			BUG();
 		if (nexthdr == NEXTHDR_FRAGMENT) {
-			unsigned short frag_off;
-			if (skb_copy_bits(skb,
-					  start+offsetof(struct frag_hdr,
-							 frag_off),
-					  &frag_off,
-					  sizeof(frag_off))) {
+			unsigned short _frag_off, *fp;
+			fp = skb_header_pointer(skb,
+						start+offsetof(struct frag_hdr,
+							       frag_off),
+						sizeof(_frag_off),
+						&_frag_off);
+			if (fp == NULL)
 				return -1;
-			}
 
-			if (ntohs(frag_off) & ~0x7)
+			if (ntohs(*fp) & ~0x7)
 				break;
 			hdrlen = 8;
 		} else if (nexthdr == NEXTHDR_AUTH)
-			hdrlen = (hdr.hdrlen+2)<<2; 
+			hdrlen = (hp->hdrlen+2)<<2; 
 		else
-			hdrlen = ipv6_optlen(&hdr); 
+			hdrlen = ipv6_optlen(hp); 
 
-		nexthdr = hdr.nexthdr;
+		nexthdr = hp->nexthdr;
 		len -= hdrlen;
 		start += hdrlen;
 	}
diff -Nru a/net/ipv6/icmp.c b/net/ipv6/icmp.c
--- a/net/ipv6/icmp.c	2004-10-18 14:56:27 -07:00
+++ b/net/ipv6/icmp.c	2004-10-18 14:56:27 -07:00
@@ -139,10 +139,12 @@
 	if (ptr < 0)
 		return 0;
 	if (nexthdr == IPPROTO_ICMPV6) {
-		u8 type;
-		if (skb_copy_bits(skb, ptr+offsetof(struct icmp6hdr, icmp6_type),
-				  &type, 1)
-		    || !(type & ICMPV6_INFOMSG_MASK))
+		u8 _type, *tp;
+		tp = skb_header_pointer(skb,
+			ptr+offsetof(struct icmp6hdr, icmp6_type),
+			sizeof(_type), &_type);
+		if (tp == NULL ||
+		    !(*tp & ICMPV6_INFOMSG_MASK))
 			return 1;
 	}
 	return 0;
@@ -200,12 +202,13 @@
 
 static __inline__ int opt_unrec(struct sk_buff *skb, __u32 offset)
 {
-	u8 optval;
+	u8 _optval, *op;
 
 	offset += skb->nh.raw - skb->data;
-	if (skb_copy_bits(skb, offset, &optval, 1))
+	op = skb_header_pointer(skb, offset, sizeof(_optval), &_optval);
+	if (op == NULL)
 		return 1;
-	return (optval&0xC0) == 0x80;
+	return (*op & 0xC0) == 0x80;
 }
 
 int icmpv6_push_pending_frames(struct sock *sk, struct flowi *fl, struct icmp6hdr *thdr, int len)
@@ -369,6 +372,8 @@
 	err = ip6_dst_lookup(sk, &dst, &fl);
 	if (err)
 		goto out;
+	if ((err = xfrm_lookup(&dst, &fl, sk, 0)) < 0)
+		goto out_dst_release;
 
 	if (hlimit < 0) {
 		if (ipv6_addr_is_multicast(&fl.fl6_dst))
@@ -455,6 +460,8 @@
 	err = ip6_dst_lookup(sk, &dst, &fl);
 	if (err)
 		goto out;
+	if ((err = xfrm_lookup(&dst, &fl, sk, 0)) < 0)
+		goto out_dst_release;
 
 	if (hlimit < 0) {
 		if (ipv6_addr_is_multicast(&fl.fl6_dst))
@@ -486,6 +493,7 @@
 out_put: 
 	if (likely(idev != NULL))
 		in6_dev_put(idev);
+out_dst_release:
 	dst_release(dst);
 out: 
 	icmpv6_xmit_unlock();
@@ -530,8 +538,7 @@
 	hash = nexthdr & (MAX_INET_PROTOS - 1);
 
 	rcu_read_lock();
-	ipprot = inet6_protos[hash];
-	smp_read_barrier_depends();
+	ipprot = rcu_dereference(inet6_protos[hash]);
 	if (ipprot && ipprot->err_handler)
 		ipprot->err_handler(skb, NULL, type, code, inner_offset, info);
 	rcu_read_unlock();
diff -Nru a/net/ipv6/ip6_fib.c b/net/ipv6/ip6_fib.c
--- a/net/ipv6/ip6_fib.c	2004-10-18 14:56:49 -07:00
+++ b/net/ipv6/ip6_fib.c	2004-10-18 14:56:49 -07:00
@@ -449,9 +449,10 @@
 			 *	Same priority level
 			 */
 
-			if ((iter->rt6i_dev == rt->rt6i_dev) &&
-			    (ipv6_addr_cmp(&iter->rt6i_gateway,
-					   &rt->rt6i_gateway) == 0)) {
+			if (iter->rt6i_dev == rt->rt6i_dev &&
+			    iter->rt6i_idev == rt->rt6i_idev &&
+			    ipv6_addr_cmp(&iter->rt6i_gateway,
+					   &rt->rt6i_gateway) == 0) {
 				if (!(iter->rt6i_flags&RTF_EXPIRES))
 					return -EEXIST;
 				iter->rt6i_expires = rt->rt6i_expires;
@@ -514,7 +515,7 @@
 	int err = -ENOMEM;
 
 	fn = fib6_add_1(root, &rt->rt6i_dst.addr, sizeof(struct in6_addr),
-			rt->rt6i_dst.plen, (u8*) &rt->rt6i_dst - (u8*) rt);
+			rt->rt6i_dst.plen, offsetof(struct rt6_info, rt6i_dst));
 
 	if (fn == NULL)
 		goto out;
@@ -550,7 +551,7 @@
 
 			sn = fib6_add_1(sfn, &rt->rt6i_src.addr,
 					sizeof(struct in6_addr), rt->rt6i_src.plen,
-					(u8*) &rt->rt6i_src - (u8*) rt);
+					offsetof(struct rt6_info, rt6i_src));
 
 			if (sn == NULL) {
 				/* If it is failed, discard just allocated
@@ -571,7 +572,7 @@
 		} else {
 			sn = fib6_add_1(fn->subtree, &rt->rt6i_src.addr,
 					sizeof(struct in6_addr), rt->rt6i_src.plen,
-					(u8*) &rt->rt6i_src - (u8*) rt);
+					offsetof(struct rt6_info, rt6i_src));
 
 			if (sn == NULL)
 				goto st_failure;
@@ -680,14 +681,13 @@
 			       struct in6_addr *saddr)
 {
 	struct lookup_args args[2];
-	struct rt6_info *rt = NULL;
 	struct fib6_node *fn;
 
-	args[0].offset = (u8*) &rt->rt6i_dst - (u8*) rt;
+	args[0].offset = offsetof(struct rt6_info, rt6i_dst);
 	args[0].addr = daddr;
 
 #ifdef CONFIG_IPV6_SUBTREES
-	args[1].offset = (u8*) &rt->rt6i_src - (u8*) rt;
+	args[1].offset = offsetof(struct rt6_info, rt6i_src);
 	args[1].addr = saddr;
 #endif
 
@@ -739,11 +739,10 @@
 			       struct in6_addr *daddr, int dst_len,
 			       struct in6_addr *saddr, int src_len)
 {
-	struct rt6_info *rt = NULL;
 	struct fib6_node *fn;
 
 	fn = fib6_locate_1(root, daddr, dst_len,
-			   (u8*) &rt->rt6i_dst - (u8*) rt);
+			   offsetof(struct rt6_info, rt6i_dst));
 
 #ifdef CONFIG_IPV6_SUBTREES
 	if (src_len) {
@@ -752,7 +751,7 @@
 			fn = fn->subtree;
 		if (fn)
 			fn = fib6_locate_1(fn, saddr, src_len,
-					   (u8*) &rt->rt6i_src - (u8*) rt);
+					   offsetof(struct rt6_info, rt6i_src));
 	}
 #endif
 
@@ -1185,6 +1184,7 @@
 	if (rt->rt6i_flags&RTF_EXPIRES && rt->rt6i_expires) {
 		if (time_after(now, rt->rt6i_expires)) {
 			RT6_TRACE("expiring %p\n", rt);
+			rt6_reset_dflt_pointer(rt);
 			return -1;
 		}
 		gc_args.more++;
@@ -1192,6 +1192,11 @@
 		if (atomic_read(&rt->u.dst.__refcnt) == 0 &&
 		    time_after_eq(now, rt->u.dst.lastuse + gc_args.timeout)) {
 			RT6_TRACE("aging clone %p\n", rt);
+			return -1;
+		} else if ((rt->rt6i_flags & RTF_GATEWAY) &&
+			   (!(rt->rt6i_nexthop->flags & NTF_ROUTER))) {
+			RT6_TRACE("purging route %p via non-router but gateway\n",
+				  rt);
 			return -1;
 		}
 		gc_args.more++;
diff -Nru a/net/ipv6/ip6_flowlabel.c b/net/ipv6/ip6_flowlabel.c
--- a/net/ipv6/ip6_flowlabel.c	2004-10-18 14:56:19 -07:00
+++ b/net/ipv6/ip6_flowlabel.c	2004-10-18 14:56:19 -07:00
@@ -538,7 +538,8 @@
 
 		/* Do not check for fault */
 		if (!freq.flr_label)
-			copy_to_user(optval + ((u8*)&freq.flr_label - (u8*)&freq), &fl->label, sizeof(fl->label));
+			copy_to_user(&((struct in6_flowlabel_req __user *) optval)->flr_label,
+				     &fl->label, sizeof(fl->label));
 
 		sfl1->fl = fl;
 		sfl1->next = np->ipv6_fl_list;
diff -Nru a/net/ipv6/ip6_input.c b/net/ipv6/ip6_input.c
--- a/net/ipv6/ip6_input.c	2004-10-18 14:56:49 -07:00
+++ b/net/ipv6/ip6_input.c	2004-10-18 14:56:49 -07:00
@@ -167,10 +167,9 @@
 		ipv6_raw_deliver(skb, nexthdr);
 
 	hash = nexthdr & (MAX_INET_PROTOS - 1);
-	if ((ipprot = inet6_protos[hash]) != NULL) {
+	if ((ipprot = rcu_dereference(inet6_protos[hash])) != NULL) {
 		int ret;
 		
-		smp_read_barrier_depends();
 		if (ipprot->flags & INET6_PROTO_FINAL) {
 			struct ipv6hdr *hdr;	
 
diff -Nru a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c
--- a/net/ipv6/ip6_output.c	2004-10-18 14:55:54 -07:00
+++ b/net/ipv6/ip6_output.c	2004-10-18 14:55:54 -07:00
@@ -54,6 +54,7 @@
 #include <net/rawv6.h>
 #include <net/icmp.h>
 #include <net/xfrm.h>
+#include <net/checksum.h>
 
 static int ip6_fragment(struct sk_buff **pskb, int (*output)(struct sk_buff**));
 
@@ -476,6 +477,7 @@
 	/* Connection association is same as pre-frag packet */
 	to->nfct = from->nfct;
 	nf_conntrack_get(to->nfct);
+	to->nfctinfo = from->nfctinfo;
 #ifdef CONFIG_BRIDGE_NETFILTER
 	nf_bridge_put(to->nf_bridge);
 	to->nf_bridge = from->nf_bridge;
@@ -796,10 +798,6 @@
 			goto out_err_release;
 		}
 	}
-	if ((err = xfrm_lookup(dst, fl, sk, 0)) < 0) {
-		err = -ENETUNREACH;
-		goto out_err_release;
-        }
 
 	return 0;
 
@@ -821,7 +819,7 @@
 	int exthdrlen;
 	int hh_len;
 	int mtu;
-	int copy = 0;
+	int copy;
 	int err;
 	int offset = 0;
 	int csummode = CHECKSUM_NONE;
@@ -879,29 +877,79 @@
 		}
 	}
 
+	/*
+	 * Let's try using as much space as possible.
+	 * Use MTU if total length of the message fits into the MTU.
+	 * Otherwise, we need to reserve fragment header and
+	 * fragment alignment (= 8-15 octects, in total).
+	 *
+	 * Note that we may need to "move" the data from the tail of
+	 * of the buffer to the new fragment when we split 
+	 * the message.
+	 *
+	 * FIXME: It may be fragmented into multiple chunks 
+	 *        at once if non-fragmentable extension headers
+	 *        are too large.
+	 * --yoshfuji 
+	 */
+
 	inet->cork.length += length;
 
 	if ((skb = skb_peek_tail(&sk->sk_write_queue)) == NULL)
 		goto alloc_new_skb;
 
 	while (length > 0) {
-		if ((copy = maxfraglen - skb->len) <= 0) {
+		/* Check if the remaining data fits into current packet. */
+		copy = mtu - skb->len;
+		if (copy < length)
+			copy = maxfraglen - skb->len;
+
+		if (copy <= 0) {
 			char *data;
 			unsigned int datalen;
 			unsigned int fraglen;
+			unsigned int fraggap;
 			unsigned int alloclen;
-			BUG_TRAP(copy == 0);
+			struct sk_buff *skb_prev;
 alloc_new_skb:
-			datalen = maxfraglen - fragheaderlen;
-			if (datalen > length)
-				datalen = length;
+			skb_prev = skb;
+
+			/* There's no room in the current skb */
+			if (skb_prev)
+				fraggap = skb_prev->len - maxfraglen;
+			else
+				fraggap = 0;
+
+			/*
+			 * If remaining data exceeds the mtu,
+			 * we know we need more fragment(s).
+			 */
+			datalen = length + fraggap;
+			if (datalen > mtu - fragheaderlen)
+				datalen = maxfraglen - fragheaderlen;
+
 			fraglen = datalen + fragheaderlen;
 			if ((flags & MSG_MORE) &&
 			    !(rt->u.dst.dev->features&NETIF_F_SG))
-				alloclen = maxfraglen;
+				alloclen = mtu;
 			else
-				alloclen = fraglen;
+				alloclen = datalen + fragheaderlen;
+
+			/*
+			 * The last fragment gets additional space at tail.
+			 * Note: we overallocate on fragments with MSG_MODE
+			 * because we have no idea if we're the last one.
+			 */
+			if (datalen == length + fraggap)
+				alloclen += rt->u.dst.trailer_len;
+
+			/*
+			 * We just reserve space for fragment header.
+			 * Note: this may be overallocation if the message 
+			 * (without MSG_MORE) fits into the MTU.
+			 */
 			alloclen += sizeof(struct frag_hdr);
+
 			if (transhdrlen) {
 				skb = sock_alloc_send_skb(sk,
 						alloclen + hh_len,
@@ -923,7 +971,7 @@
 			 */
 			skb->ip_summed = csummode;
 			skb->csum = 0;
-			/* reserve 8 byte for fragmentation */
+			/* reserve for fragmentation */
 			skb_reserve(skb, hh_len+sizeof(struct frag_hdr));
 
 			/*
@@ -933,15 +981,29 @@
 			skb->nh.raw = data + exthdrlen;
 			data += fragheaderlen;
 			skb->h.raw = data + exthdrlen;
-			copy = datalen - transhdrlen;
-			if (copy > 0 && getfrag(from, data + transhdrlen, offset, copy, 0, skb) < 0) {
+
+			if (fraggap) {
+				skb->csum = skb_copy_and_csum_bits(
+					skb_prev, maxfraglen,
+					data + transhdrlen, fraggap, 0);
+				skb_prev->csum = csum_sub(skb_prev->csum,
+							  skb->csum);
+				data += fraggap;
+				skb_trim(skb_prev, maxfraglen);
+			}
+			copy = datalen - transhdrlen - fraggap;
+			if (copy < 0) {
+				err = -EINVAL;
+				kfree_skb(skb);
+				goto error;
+			} else if (copy > 0 && getfrag(from, data + transhdrlen, offset, copy, fraggap, skb) < 0) {
 				err = -EFAULT;
 				kfree_skb(skb);
 				goto error;
 			}
 
 			offset += copy;
-			length -= datalen;
+			length -= datalen - fraggap;
 			transhdrlen = 0;
 			exthdrlen = 0;
 			csummode = CHECKSUM_NONE;
diff -Nru a/net/ipv6/ip6_tunnel.c b/net/ipv6/ip6_tunnel.c
--- a/net/ipv6/ip6_tunnel.c	2004-10-18 14:55:54 -07:00
+++ b/net/ipv6/ip6_tunnel.c	2004-10-18 14:55:54 -07:00
@@ -48,6 +48,8 @@
 #include <net/addrconf.h>
 #include <net/ip6_tunnel.h>
 #include <net/xfrm.h>
+#include <net/dsfield.h>
+#include <net/inet_ecn.h>
 
 MODULE_AUTHOR("Ville Nuorvala");
 MODULE_DESCRIPTION("IPv6-in-IPv6 tunnel");
@@ -490,6 +492,15 @@
 	read_unlock(&ip6ip6_lock);
 }
 
+static inline void ip6ip6_ecn_decapsulate(struct ipv6hdr *outer_iph,
+					  struct sk_buff *skb)
+{
+	struct ipv6hdr *inner_iph = skb->nh.ipv6h;
+
+	if (INET_ECN_is_ce(ipv6_get_dsfield(outer_iph)))
+		IP6_ECN_set_ce(inner_iph);
+}
+
 /**
  * ip6ip6_rcv - decapsulate IPv6 packet and retransmit it locally
  *   @skb: received socket buffer
@@ -531,6 +542,9 @@
 		skb->dev = t->dev;
 		dst_release(skb->dst);
 		skb->dst = NULL;
+		if (t->parms.flags & IP6_TNL_F_RCV_DSCP_COPY)
+			ipv6_copy_dscp(ipv6h, skb->nh.ipv6h);
+		ip6ip6_ecn_decapsulate(ipv6h, skb);
 		t->stat.rx_packets++;
 		t->stat.rx_bytes += skb->len;
 		netif_rx(skb);
@@ -621,6 +635,7 @@
 	u8 proto;
 	int err;
 	int pkt_len;
+	int dsfield;
 
 	if (t->recursion++) {
 		stats->collisions++;
@@ -646,6 +661,7 @@
 	memcpy(&fl, &t->fl, sizeof (fl));
 	proto = fl.proto;
 
+	dsfield = ipv6_get_dsfield(ipv6h);
 	if ((t->parms.flags & IP6_TNL_F_USE_ORIG_TCLASS))
 		fl.fl6_flowlabel |= (*(__u32 *) ipv6h & IPV6_TCLASS_MASK);
 	if ((t->parms.flags & IP6_TNL_F_USE_ORIG_FLOWLABEL))
@@ -717,6 +733,8 @@
 	skb->nh.raw = skb_push(skb, sizeof(struct ipv6hdr));
 	ipv6h = skb->nh.ipv6h;
 	*(u32*)ipv6h = fl.fl6_flowlabel | htonl(0x60000000);
+	dsfield = INET_ECN_encapsulate(0, dsfield);
+	ipv6_change_dsfield(ipv6h, ~INET_ECN_MASK, dsfield);
 	ipv6h->payload_len = htons(skb->len - sizeof(struct ipv6hdr));
 	ipv6h->hop_limit = t->parms.hop_limit;
 	ipv6h->nexthdr = proto;
diff -Nru a/net/ipv6/ipcomp6.c b/net/ipv6/ipcomp6.c
--- a/net/ipv6/ipcomp6.c	2004-10-18 14:56:32 -07:00
+++ b/net/ipv6/ipcomp6.c	2004-10-18 14:56:32 -07:00
@@ -36,14 +36,31 @@
 #include <net/xfrm.h>
 #include <net/ipcomp.h>
 #include <asm/scatterlist.h>
+#include <asm/semaphore.h>
 #include <linux/crypto.h>
 #include <linux/pfkeyv2.h>
 #include <linux/random.h>
+#include <linux/percpu.h>
+#include <linux/smp.h>
+#include <linux/list.h>
+#include <linux/vmalloc.h>
+#include <linux/rtnetlink.h>
 #include <net/icmp.h>
 #include <net/ipv6.h>
 #include <linux/ipv6.h>
 #include <linux/icmpv6.h>
 
+struct ipcomp6_tfms {
+	struct list_head list;
+	struct crypto_tfm **tfms;
+	int users;
+};
+
+static DECLARE_MUTEX(ipcomp6_resource_sem);
+static void **ipcomp6_scratches;
+static int ipcomp6_scratch_users;
+static LIST_HEAD(ipcomp6_tfms_list);
+
 static int ipcomp6_input(struct xfrm_state *x, struct xfrm_decap_state *decap, struct sk_buff *skb)
 {
 	int err = 0;
@@ -53,7 +70,9 @@
 	struct ipv6hdr *iph;
 	int plen, dlen;
 	struct ipcomp_data *ipcd = x->data;
-	u8 *start, *scratch = ipcd->scratch;
+	u8 *start, *scratch;
+	struct crypto_tfm *tfm;
+	int cpu;
 
 	if ((skb_is_nonlinear(skb) || skb_cloned(skb)) &&
 		skb_linearize(skb, GFP_ATOMIC) != 0) {
@@ -82,20 +101,24 @@
 	dlen = IPCOMP_SCRATCH_SIZE;
 	start = skb->data;
 
-	err = crypto_comp_decompress(ipcd->tfm, start, plen, scratch, &dlen);
+	cpu = get_cpu();
+	scratch = *per_cpu_ptr(ipcomp6_scratches, cpu);
+	tfm = *per_cpu_ptr(ipcd->tfms, cpu);
+
+	err = crypto_comp_decompress(tfm, start, plen, scratch, &dlen);
 	if (err) {
 		err = -EINVAL;
-		goto out;
+		goto out_put_cpu;
 	}
 
 	if (dlen < (plen + sizeof(struct ipv6_comp_hdr))) {
 		err = -EINVAL;
-		goto out;
+		goto out_put_cpu;
 	}
 
 	err = pskb_expand_head(skb, 0, dlen - plen, GFP_ATOMIC);
 	if (err) {
-		goto out;
+		goto out_put_cpu;
 	}
 
 	skb_put(skb, dlen - plen);
@@ -104,6 +127,8 @@
 	iph = skb->nh.ipv6h;
 	iph->payload_len = htons(skb->len);
 	
+out_put_cpu:
+	put_cpu();
 out:
 	if (tmp_hdr)
 		kfree(tmp_hdr);
@@ -114,56 +139,65 @@
 	return err;
 }
 
-static int ipcomp6_output(struct sk_buff **pskb)
+static int ipcomp6_output(struct sk_buff *skb)
 {
 	int err;
-	struct dst_entry *dst = (*pskb)->dst;
+	struct dst_entry *dst = skb->dst;
 	struct xfrm_state *x = dst->xfrm;
 	struct ipv6hdr *top_iph;
 	int hdr_len;
 	struct ipv6_comp_hdr *ipch;
 	struct ipcomp_data *ipcd = x->data;
 	int plen, dlen;
-	u8 *start, *scratch = ipcd->scratch;
+	u8 *start, *scratch;
+	struct crypto_tfm *tfm;
+	int cpu;
 
-	hdr_len = (*pskb)->h.raw - (*pskb)->data;
+	hdr_len = skb->h.raw - skb->data;
 
 	/* check whether datagram len is larger than threshold */
-	if (((*pskb)->len - hdr_len) < ipcd->threshold) {
+	if ((skb->len - hdr_len) < ipcd->threshold) {
 		goto out_ok;
 	}
 
-	if ((skb_is_nonlinear(*pskb) || skb_cloned(*pskb)) &&
-		skb_linearize(*pskb, GFP_ATOMIC) != 0) {
+	if ((skb_is_nonlinear(skb) || skb_cloned(skb)) &&
+		skb_linearize(skb, GFP_ATOMIC) != 0) {
 		err = -ENOMEM;
 		goto error;
 	}
 
 	/* compression */
-	plen = (*pskb)->len - hdr_len;
+	plen = skb->len - hdr_len;
 	dlen = IPCOMP_SCRATCH_SIZE;
-	start = (*pskb)->h.raw;
+	start = skb->h.raw;
+
+	cpu = get_cpu();
+	scratch = *per_cpu_ptr(ipcomp6_scratches, cpu);
+	tfm = *per_cpu_ptr(ipcd->tfms, cpu);
 
-	err = crypto_comp_compress(ipcd->tfm, start, plen, scratch, &dlen);
+	err = crypto_comp_compress(tfm, start, plen, scratch, &dlen);
 	if (err) {
+		put_cpu();
 		goto error;
 	}
 	if ((dlen + sizeof(struct ipv6_comp_hdr)) >= plen) {
+		put_cpu();
 		goto out_ok;
 	}
 	memcpy(start + sizeof(struct ip_comp_hdr), scratch, dlen);
-	pskb_trim(*pskb, hdr_len + dlen + sizeof(struct ip_comp_hdr));
+	put_cpu();
+	pskb_trim(skb, hdr_len + dlen + sizeof(struct ip_comp_hdr));
 
 	/* insert ipcomp header and replace datagram */
-	top_iph = (struct ipv6hdr *)(*pskb)->data;
+	top_iph = (struct ipv6hdr *)skb->data;
 
-	top_iph->payload_len = htons((*pskb)->len - sizeof(struct ipv6hdr));
+	top_iph->payload_len = htons(skb->len - sizeof(struct ipv6hdr));
 
 	ipch = (struct ipv6_comp_hdr *)start;
-	ipch->nexthdr = *(*pskb)->nh.raw;
+	ipch->nexthdr = *skb->nh.raw;
 	ipch->flags = 0;
 	ipch->cpi = htons((u16 )ntohl(x->id.spi));
-	*(*pskb)->nh.raw = IPPROTO_COMP;
+	*skb->nh.raw = IPPROTO_COMP;
 
 out_ok:
 	err = 0;
@@ -254,12 +288,132 @@
 	return err;
 }
 
+static void ipcomp6_free_scratches(void)
+{
+	int i;
+	void **scratches;
+
+	if (--ipcomp6_scratch_users)
+		return;
+
+	scratches = ipcomp6_scratches;
+	if (!scratches)
+		return;
+
+	for_each_cpu(i) {
+		void *scratch = *per_cpu_ptr(scratches, i);
+		if (scratch)
+			vfree(scratch);
+	}
+
+	free_percpu(scratches);
+}
+
+static void **ipcomp6_alloc_scratches(void)
+{
+	int i;
+	void **scratches;
+
+	if (ipcomp6_scratch_users++)
+		return ipcomp6_scratches;
+
+	scratches = alloc_percpu(void *);
+	if (!scratches)
+		return NULL;
+
+	ipcomp6_scratches = scratches;
+
+	for_each_cpu(i) {
+		void *scratch = vmalloc(IPCOMP_SCRATCH_SIZE);
+		if (!scratch)
+			return NULL;
+		*per_cpu_ptr(scratches, i) = scratch;
+	}
+
+	return scratches;
+}
+
+static void ipcomp6_free_tfms(struct crypto_tfm **tfms)
+{
+	struct ipcomp6_tfms *pos;
+	int cpu;
+
+	list_for_each_entry(pos, &ipcomp6_tfms_list, list) {
+		if (pos->tfms == tfms)
+			break;
+	}
+
+	BUG_TRAP(pos);
+
+	if (--pos->users)
+		return;
+
+	list_del(&pos->list);
+	kfree(pos);
+
+	if (!tfms)
+		return;
+
+	for_each_cpu(cpu) {
+		struct crypto_tfm *tfm = *per_cpu_ptr(tfms, cpu);
+		if (tfm)
+			crypto_free_tfm(tfm);
+	}
+	free_percpu(tfms);
+}
+
+static struct crypto_tfm **ipcomp6_alloc_tfms(const char *alg_name)
+{
+	struct ipcomp6_tfms *pos;
+	struct crypto_tfm **tfms;
+	int cpu;
+
+	/* This can be any valid CPU ID so we don't need locking. */
+	cpu = smp_processor_id();
+
+	list_for_each_entry(pos, &ipcomp6_tfms_list, list) {
+		struct crypto_tfm *tfm;
+
+		tfms = pos->tfms;
+		tfm = *per_cpu_ptr(tfms, cpu);
+
+		if (!strcmp(crypto_tfm_alg_name(tfm), alg_name)) {
+			pos->users++;
+			return tfms;
+		}
+	}
+
+	pos = kmalloc(sizeof(*pos), GFP_KERNEL);
+	if (!pos)
+		return NULL;
+
+	pos->users = 1;
+	INIT_LIST_HEAD(&pos->list);
+	list_add(&pos->list, &ipcomp6_tfms_list);
+
+	pos->tfms = tfms = alloc_percpu(struct crypto_tfm *);
+	if (!tfms)
+		goto error;
+
+	for_each_cpu(cpu) {
+		struct crypto_tfm *tfm = crypto_alloc_tfm(alg_name, 0);
+		if (!tfm)
+			goto error;
+		*per_cpu_ptr(tfms, cpu) = tfm;
+	}
+
+	return tfms;
+
+error:
+	ipcomp6_free_tfms(tfms);
+	return NULL;
+}
+
 static void ipcomp6_free_data(struct ipcomp_data *ipcd)
 {
-	if (ipcd->tfm)
-		crypto_free_tfm(ipcd->tfm);
-	if (ipcd->scratch)
-		kfree(ipcd->scratch);
+	if (ipcd->tfms)
+		ipcomp6_free_tfms(ipcd->tfms);
+	ipcomp6_free_scratches();
 }
 
 static void ipcomp6_destroy(struct xfrm_state *x)
@@ -268,7 +422,9 @@
 	if (!ipcd)
 		return;
 	xfrm_state_delete_tunnel(x);
+	down(&ipcomp6_resource_sem);
 	ipcomp6_free_data(ipcd);
+	up(&ipcomp6_resource_sem);
 	kfree(ipcd);
 
 	xfrm6_tunnel_free_spi((xfrm_address_t *)&x->props.saddr);
@@ -284,28 +440,32 @@
 	if (!x->calg)
 		goto out;
 
+	if (x->encap)
+		goto out;
+
 	err = -ENOMEM;
 	ipcd = kmalloc(sizeof(*ipcd), GFP_KERNEL);
 	if (!ipcd)
-		goto error;
+		goto out;
 
 	memset(ipcd, 0, sizeof(*ipcd));
 	x->props.header_len = 0;
 	if (x->props.mode)
 		x->props.header_len += sizeof(struct ipv6hdr);
 	
-	ipcd->scratch = kmalloc(IPCOMP_SCRATCH_SIZE, GFP_KERNEL);
-	if (!ipcd->scratch)
+	down(&ipcomp6_resource_sem);
+	if (!ipcomp6_alloc_scratches())
 		goto error;
 
-	ipcd->tfm = crypto_alloc_tfm(x->calg->alg_name, 0);
-	if (!ipcd->tfm)
+	ipcd->tfms = ipcomp6_alloc_tfms(x->calg->alg_name);
+	if (!ipcd->tfms)
 		goto error;
+	up(&ipcomp6_resource_sem);
 
 	if (x->props.mode) {
 		err = ipcomp6_tunnel_attach(x);
 		if (err)
-			goto error;
+			goto error_tunnel;
 	}
 
 	calg_desc = xfrm_calg_get_byname(x->calg->alg_name);
@@ -315,11 +475,12 @@
 	err = 0;
 out:
 	return err;
+error_tunnel:
+	down(&ipcomp6_resource_sem);
 error:
-	if (ipcd) {
-		ipcomp6_free_data(ipcd);
-		kfree(ipcd);
-	}
+	ipcomp6_free_data(ipcd);
+	up(&ipcomp6_resource_sem);
+	kfree(ipcd);
 
 	goto out;
 }
diff -Nru a/net/ipv6/mcast.c b/net/ipv6/mcast.c
--- a/net/ipv6/mcast.c	2004-10-18 14:56:50 -07:00
+++ b/net/ipv6/mcast.c	2004-10-18 14:56:50 -07:00
@@ -128,6 +128,8 @@
 
 static struct socket *igmp6_socket;
 
+int __ipv6_dev_mc_dec(struct inet6_dev *idev, struct in6_addr *addr);
+
 static void igmp6_join_group(struct ifmcaddr6 *ma);
 static void igmp6_leave_group(struct ifmcaddr6 *ma);
 static void igmp6_timer_handler(unsigned long data);
@@ -256,9 +258,9 @@
 
 				if (idev) {
 					(void) ip6_mc_leave_src(sk,mc_lst,idev);
+					__ipv6_dev_mc_dec(idev, &mc_lst->addr);
 					in6_dev_put(idev);
 				}
-				ipv6_dev_mc_dec(dev, &mc_lst->addr);
 				dev_put(dev);
 			}
 			sock_kfree_s(sk, mc_lst, sizeof(*mc_lst));
@@ -322,9 +324,9 @@
 
 			if (idev) {
 				(void) ip6_mc_leave_src(sk, mc_lst, idev);
+				__ipv6_dev_mc_dec(idev, &mc_lst->addr);
 				in6_dev_put(idev);
 			}
-			ipv6_dev_mc_dec(dev, &mc_lst->addr);
 			dev_put(dev);
 		}
 
@@ -870,7 +872,7 @@
 /*
  *	device multicast group del
  */
-static int __ipv6_dev_mc_dec(struct net_device *dev, struct inet6_dev *idev, struct in6_addr *addr)
+int __ipv6_dev_mc_dec(struct inet6_dev *idev, struct in6_addr *addr)
 {
 	struct ifmcaddr6 *ma, **map;
 
@@ -903,7 +905,7 @@
 	if (!idev)
 		return -ENODEV;
 
-	err = __ipv6_dev_mc_dec(dev, idev, addr);
+	err = __ipv6_dev_mc_dec(idev, addr);
 
 	in6_dev_put(idev);
 
@@ -2108,7 +2110,12 @@
 	 * addrconf.c has NULL'd out dev->ip6_ptr so in6_dev_get() will
 	 * fail.
 	 */
-	__ipv6_dev_mc_dec(idev->dev, idev, &maddr);
+	__ipv6_dev_mc_dec(idev, &maddr);
+
+	if (idev->cnf.forwarding) {
+		ipv6_addr_all_routers(&maddr);
+		__ipv6_dev_mc_dec(idev, &maddr);
+	}
 
 	write_lock_bh(&idev->lock);
 	while ((i = idev->mc_list) != NULL) {
diff -Nru a/net/ipv6/ndisc.c b/net/ipv6/ndisc.c
--- a/net/ipv6/ndisc.c	2004-10-18 14:56:33 -07:00
+++ b/net/ipv6/ndisc.c	2004-10-18 14:56:33 -07:00
@@ -58,6 +58,7 @@
 #include <linux/in6.h>
 #include <linux/route.h>
 #include <linux/init.h>
+#include <linux/rcupdate.h>
 #ifdef CONFIG_SYSCTL
 #include <linux/sysctl.h>
 #endif
@@ -65,6 +66,7 @@
 #include <linux/if_arp.h>
 #include <linux/ipv6.h>
 #include <linux/icmpv6.h>
+#include <linux/jhash.h>
 
 #include <net/sock.h>
 #include <net/snmp.h>
@@ -269,29 +271,35 @@
 
 static u32 ndisc_hash(const void *pkey, const struct net_device *dev)
 {
-	u32 hash_val;
+	const u32 *p32 = pkey;
+	u32 addr_hash, i;
 
-	hash_val = *(u32*)(pkey + sizeof(struct in6_addr) - 4);
-	hash_val ^= (hash_val>>16);
-	hash_val ^= hash_val>>8;
-	hash_val ^= hash_val>>3;
-	hash_val = (hash_val^dev->ifindex)&NEIGH_HASHMASK;
+	addr_hash = 0;
+	for (i = 0; i < (sizeof(struct in6_addr) / sizeof(u32)); i++)
+		addr_hash ^= *p32++;
 
-	return hash_val;
+	return jhash_2words(addr_hash, dev->ifindex, nd_tbl.hash_rnd);
 }
 
 static int ndisc_constructor(struct neighbour *neigh)
 {
 	struct in6_addr *addr = (struct in6_addr*)&neigh->primary_key;
 	struct net_device *dev = neigh->dev;
-	struct inet6_dev *in6_dev = in6_dev_get(dev);
+	struct inet6_dev *in6_dev;
+	struct neigh_parms *parms;
 	int is_multicast = ipv6_addr_is_multicast(addr);
 
-	if (in6_dev == NULL)
+	rcu_read_lock();
+	in6_dev = in6_dev_get(dev);
+	if (in6_dev == NULL) {
+		rcu_read_unlock();
 		return -EINVAL;
+	}
 
-	if (in6_dev->nd_parms)
-		neigh->parms = in6_dev->nd_parms;
+	parms = in6_dev->nd_parms;
+	__neigh_parms_put(neigh->parms);
+	neigh->parms = neigh_parms_clone(parms);
+	rcu_read_unlock();
 
 	neigh->type = is_multicast ? RTN_MULTICAST : RTN_UNICAST;
 	if (dev->hard_header == NULL) {
@@ -794,16 +802,20 @@
 	}
 
 	if (inc)
-		nd_tbl.stats.rcv_probes_mcast++;
+		NEIGH_CACHE_STAT_INC(&nd_tbl, rcv_probes_mcast);
 	else
-		nd_tbl.stats.rcv_probes_ucast++;
+		NEIGH_CACHE_STAT_INC(&nd_tbl, rcv_probes_ucast);
 
 	/* 
 	 *	update / create cache entry
 	 *	for the source address
 	 */
-	neigh = neigh_event_ns(&nd_tbl, lladdr, saddr, dev);
-
+	neigh = __neigh_lookup(&nd_tbl, saddr, dev,
+			       !inc || lladdr || !dev->addr_len);
+	if (neigh)
+		neigh_update(neigh, lladdr, NUD_STALE, 
+			     NEIGH_UPDATE_F_WEAK_OVERRIDE|
+			     NEIGH_UPDATE_F_OVERRIDE);
 	if (neigh || !dev->hard_header) {
 		ndisc_send_na(dev, neigh, saddr, &msg->target,
 			      idev->cnf.forwarding, 
@@ -886,24 +898,25 @@
 	neigh = neigh_lookup(&nd_tbl, &msg->target, dev);
 
 	if (neigh) {
-		if (neigh->flags & NTF_ROUTER) {
-			if (msg->icmph.icmp6_router == 0) {
-				/*
-				 *	Change: router to host
-				 */
-				struct rt6_info *rt;
-				rt = rt6_get_dflt_router(saddr, dev);
-				if (rt)
-					ip6_del_rt(rt, NULL, NULL);
-			}
-		} else {
-			if (msg->icmph.icmp6_router)
-				neigh->flags |= NTF_ROUTER;
-		}
+		u8 old_flags = neigh->flags;
 
 		neigh_update(neigh, lladdr,
 			     msg->icmph.icmp6_solicited ? NUD_REACHABLE : NUD_STALE,
-			     msg->icmph.icmp6_override, 1);
+			     NEIGH_UPDATE_F_WEAK_OVERRIDE|
+			     (msg->icmph.icmp6_override ? NEIGH_UPDATE_F_OVERRIDE : 0)|
+			     NEIGH_UPDATE_F_OVERRIDE_ISROUTER|
+			     (msg->icmph.icmp6_router ? NEIGH_UPDATE_F_ISROUTER : 0));
+
+		if ((old_flags & ~neigh->flags) & NTF_ROUTER) {
+			/*
+			 * Change: router to host
+			 */
+			struct rt6_info *rt;
+			rt = rt6_get_dflt_router(saddr, dev);
+			if (rt)
+				ip6_del_rt(rt, NULL, NULL);
+		}
+
 		neigh_release(neigh);
 	}
 }
@@ -1071,7 +1084,11 @@
 				goto out;
 			}
 		}
-		neigh_update(neigh, lladdr, NUD_STALE, 1, 1);
+		neigh_update(neigh, lladdr, NUD_STALE,
+			     NEIGH_UPDATE_F_WEAK_OVERRIDE|
+			     NEIGH_UPDATE_F_OVERRIDE|
+			     NEIGH_UPDATE_F_OVERRIDE_ISROUTER|
+			     NEIGH_UPDATE_F_ISROUTER);
 	}
 
 	if (ndopts.nd_opts_pi) {
@@ -1188,19 +1205,11 @@
 			return;
 		}
 	}
-	/* passed validation tests */
-
-	/*
-	   We install redirect only if nexthop state is valid.
-	 */
 
 	neigh = __neigh_lookup(&nd_tbl, target, skb->dev, 1);
 	if (neigh) {
-		neigh_update(neigh, lladdr, NUD_STALE, 1, 1);
-		if (neigh->nud_state&NUD_VALID)
-			rt6_redirect(dest, &skb->nh.ipv6h->saddr, neigh, on_link);
-		else
-			__neigh_event_send(neigh, NULL);
+		rt6_redirect(dest, &skb->nh.ipv6h->saddr, neigh, lladdr, 
+			     on_link);
 		neigh_release(neigh);
 	}
 	in6_dev_put(in6_dev);
diff -Nru a/net/ipv6/netfilter/Kconfig b/net/ipv6/netfilter/Kconfig
--- a/net/ipv6/netfilter/Kconfig	2004-10-18 14:56:50 -07:00
+++ b/net/ipv6/netfilter/Kconfig	2004-10-18 14:56:50 -07:00
@@ -158,6 +158,15 @@
 
 	  To compile it as a module, choose M here.  If unsure, say N.
 
+config IP6_NF_MATCH_PHYSDEV
+	tristate "Physdev match support"
+	depends on IP6_NF_IPTABLES && BRIDGE_NETFILTER
+	help
+	  Physdev packet matching matches against the physical bridge ports
+	  the IP packet arrived on or will leave by.
+
+	  To compile it as a module, choose M here.  If unsure, say N.
+
 #  dep_tristate '  Multiple port match support' CONFIG_IP6_NF_MATCH_MULTIPORT $CONFIG_IP6_NF_IPTABLES
 #  dep_tristate '  TOS match support' CONFIG_IP6_NF_MATCH_TOS $CONFIG_IP6_NF_IPTABLES
 #  if [ "$CONFIG_IP6_NF_CONNTRACK" != "n" ]; then
diff -Nru a/net/ipv6/netfilter/Makefile b/net/ipv6/netfilter/Makefile
--- a/net/ipv6/netfilter/Makefile	2004-10-18 14:56:33 -07:00
+++ b/net/ipv6/netfilter/Makefile	2004-10-18 14:56:33 -07:00
@@ -16,6 +16,7 @@
 obj-$(CONFIG_IP6_NF_MATCH_EUI64) += ip6t_eui64.o
 obj-$(CONFIG_IP6_NF_MATCH_MULTIPORT) += ip6t_multiport.o
 obj-$(CONFIG_IP6_NF_MATCH_OWNER) += ip6t_owner.o
+obj-$(CONFIG_IP6_NF_MATCH_PHYSDEV) += ip6t_physdev.o
 obj-$(CONFIG_IP6_NF_FILTER) += ip6table_filter.o
 obj-$(CONFIG_IP6_NF_MANGLE) += ip6table_mangle.o
 obj-$(CONFIG_IP6_NF_TARGET_MARK) += ip6t_MARK.o
diff -Nru a/net/ipv6/netfilter/ip6_tables.c b/net/ipv6/netfilter/ip6_tables.c
--- a/net/ipv6/netfilter/ip6_tables.c	2004-10-18 14:57:03 -07:00
+++ b/net/ipv6/netfilter/ip6_tables.c	2004-10-18 14:57:03 -07:00
@@ -66,6 +66,7 @@
 #endif
 #define SMP_ALIGN(x) (((x) + SMP_CACHE_BYTES-1) & ~(SMP_CACHE_BYTES-1))
 
+static DECLARE_MUTEX(ip6t_mutex);
 
 /* Must have mutex */
 #define ASSERT_READ_LOCK(x) IP_NF_ASSERT(down_trylock(&ip6t_mutex) != 0)
diff -Nru a/net/ipv6/netfilter/ip6t_LOG.c b/net/ipv6/netfilter/ip6t_LOG.c
--- a/net/ipv6/netfilter/ip6t_LOG.c	2004-10-18 14:56:28 -07:00
+++ b/net/ipv6/netfilter/ip6t_LOG.c	2004-10-18 14:56:28 -07:00
@@ -11,6 +11,7 @@
  */
 
 #include <linux/module.h>
+#include <linux/moduleparam.h>
 #include <linux/skbuff.h>
 #include <linux/ip.h>
 #include <linux/spinlock.h>
@@ -26,7 +27,7 @@
 MODULE_LICENSE("GPL");
 
 static unsigned int nflog = 1;
-MODULE_PARM(nflog, "i");
+module_param(nflog, int, 0400);
 MODULE_PARM_DESC(nflog, "register as internal netfilter logging module");
  
 struct in_device;
@@ -60,7 +61,7 @@
 		repeatedly...with a large stick...no, an even LARGER
 		stick...no, you're still not thinking big enough */
 			nexthdr = **hdrptr;
-			hdrlen = *hdrptr[1] * 4 + 8;
+			hdrlen = (*hdrptr)[1] * 4 + 8;
 			*hdrptr = *hdrptr + hdrlen;
 			break;
 		/*stupid rfc2402 */
@@ -68,7 +69,7 @@
 		case IPPROTO_ROUTING:
 		case IPPROTO_HOPOPTS:
 			nexthdr = **hdrptr;
-			hdrlen = *hdrptr[1] * 8 + 8;
+			hdrlen = (*hdrptr)[1] * 8 + 8;
 			*hdrptr = *hdrptr + hdrlen;
 			break;
 		case IPPROTO_FRAGMENT:
diff -Nru a/net/ipv6/netfilter/ip6t_eui64.c b/net/ipv6/netfilter/ip6t_eui64.c
--- a/net/ipv6/netfilter/ip6t_eui64.c	2004-10-18 14:55:54 -07:00
+++ b/net/ipv6/netfilter/ip6t_eui64.c	2004-10-18 14:55:54 -07:00
@@ -41,10 +41,10 @@
     
     memset(eui64, 0, sizeof(eui64));
 
-    if (skb->mac.ethernet->h_proto == ntohs(ETH_P_IPV6)) {
+    if (eth_hdr(skb)->h_proto == ntohs(ETH_P_IPV6)) {
       if (skb->nh.ipv6h->version == 0x6) { 
-         memcpy(eui64, skb->mac.ethernet->h_source, 3);
-         memcpy(eui64 + 5, skb->mac.ethernet->h_source + 3, 3);
+         memcpy(eui64, eth_hdr(skb)->h_source, 3);
+         memcpy(eui64 + 5, eth_hdr(skb)->h_source + 3, 3);
 	 eui64[3]=0xff;
 	 eui64[4]=0xfe;
 	 eui64[0] |= 0x02;
diff -Nru a/net/ipv6/netfilter/ip6t_mac.c b/net/ipv6/netfilter/ip6t_mac.c
--- a/net/ipv6/netfilter/ip6t_mac.c	2004-10-18 14:57:03 -07:00
+++ b/net/ipv6/netfilter/ip6t_mac.c	2004-10-18 14:57:03 -07:00
@@ -35,7 +35,7 @@
     return (skb->mac.raw >= skb->head
 	    && (skb->mac.raw + ETH_HLEN) <= skb->data
 	    /* If so, compare... */
-	    && ((memcmp(skb->mac.ethernet->h_source, info->srcaddr, ETH_ALEN)
+	    && ((memcmp(eth_hdr(skb)->h_source, info->srcaddr, ETH_ALEN)
 		== 0) ^ info->invert));
 }
 
diff -Nru a/net/ipv6/netfilter/ip6t_physdev.c b/net/ipv6/netfilter/ip6t_physdev.c
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/net/ipv6/netfilter/ip6t_physdev.c	2004-10-18 14:57:24 -07:00
@@ -0,0 +1,136 @@
+/* Kernel module to match the bridge port in and
+ * out device for IP packets coming into contact with a bridge. */
+
+/* (C) 2001-2003 Bart De Schuymer <bdschuym@pandora.be>
+ *
+ * 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/module.h>
+#include <linux/skbuff.h>
+#include <linux/netfilter_ipv6/ip6t_physdev.h>
+#include <linux/netfilter_ipv6/ip6_tables.h>
+#include <linux/netfilter_bridge.h>
+#define MATCH   1
+#define NOMATCH 0
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Bart De Schuymer <bdschuym@pandora.be>");
+MODULE_DESCRIPTION("iptables bridge physical device match module");
+
+static int
+match(const struct sk_buff *skb,
+      const struct net_device *in,
+      const struct net_device *out,
+      const void *matchinfo,
+      int offset,
+      const void *hdr,
+      u_int16_t datalen,
+      int *hotdrop)
+{
+	int i;
+	static const char nulldevname[IFNAMSIZ];
+	const struct ip6t_physdev_info *info = matchinfo;
+	unsigned int ret;
+	const char *indev, *outdev;
+	struct nf_bridge_info *nf_bridge;
+
+	/* Not a bridged IP packet or no info available yet:
+	 * LOCAL_OUT/mangle and LOCAL_OUT/nat don't know if
+	 * the destination device will be a bridge. */
+	if (!(nf_bridge = skb->nf_bridge)) {
+		/* Return MATCH if the invert flags of the used options are on */
+		if ((info->bitmask & IP6T_PHYSDEV_OP_BRIDGED) &&
+		    !(info->invert & IP6T_PHYSDEV_OP_BRIDGED))
+			return NOMATCH;
+		if ((info->bitmask & IP6T_PHYSDEV_OP_ISIN) &&
+		    !(info->invert & IP6T_PHYSDEV_OP_ISIN))
+			return NOMATCH;
+		if ((info->bitmask & IP6T_PHYSDEV_OP_ISOUT) &&
+		    !(info->invert & IP6T_PHYSDEV_OP_ISOUT))
+			return NOMATCH;
+		if ((info->bitmask & IP6T_PHYSDEV_OP_IN) &&
+		    !(info->invert & IP6T_PHYSDEV_OP_IN))
+			return NOMATCH;
+		if ((info->bitmask & IP6T_PHYSDEV_OP_OUT) &&
+		    !(info->invert & IP6T_PHYSDEV_OP_OUT))
+			return NOMATCH;
+		return MATCH;
+	}
+
+	/* This only makes sense in the FORWARD and POSTROUTING chains */
+	if ((info->bitmask & IP6T_PHYSDEV_OP_BRIDGED) &&
+	    (!!(nf_bridge->mask & BRNF_BRIDGED) ^
+	    !(info->invert & IP6T_PHYSDEV_OP_BRIDGED)))
+		return NOMATCH;
+
+	if ((info->bitmask & IP6T_PHYSDEV_OP_ISIN &&
+	    (!nf_bridge->physindev ^ !!(info->invert & IP6T_PHYSDEV_OP_ISIN))) ||
+	    (info->bitmask & IP6T_PHYSDEV_OP_ISOUT &&
+	    (!nf_bridge->physoutdev ^ !!(info->invert & IP6T_PHYSDEV_OP_ISOUT))))
+		return NOMATCH;
+
+	if (!(info->bitmask & IP6T_PHYSDEV_OP_IN))
+		goto match_outdev;
+	indev = nf_bridge->physindev ? nf_bridge->physindev->name : nulldevname;
+	for (i = 0, ret = 0; i < IFNAMSIZ/sizeof(unsigned int); i++) {
+		ret |= (((const unsigned int *)indev)[i]
+			^ ((const unsigned int *)info->physindev)[i])
+			& ((const unsigned int *)info->in_mask)[i];
+	}
+
+	if ((ret == 0) ^ !(info->invert & IP6T_PHYSDEV_OP_IN))
+		return NOMATCH;
+
+match_outdev:
+	if (!(info->bitmask & IP6T_PHYSDEV_OP_OUT))
+		return MATCH;
+	outdev = nf_bridge->physoutdev ?
+		 nf_bridge->physoutdev->name : nulldevname;
+	for (i = 0, ret = 0; i < IFNAMSIZ/sizeof(unsigned int); i++) {
+		ret |= (((const unsigned int *)outdev)[i]
+			^ ((const unsigned int *)info->physoutdev)[i])
+			& ((const unsigned int *)info->out_mask)[i];
+	}
+
+	return (ret != 0) ^ !(info->invert & IP6T_PHYSDEV_OP_OUT);
+}
+
+static int
+checkentry(const char *tablename,
+		       const struct ip6t_ip6 *ip,
+		       void *matchinfo,
+		       unsigned int matchsize,
+		       unsigned int hook_mask)
+{
+	const struct ip6t_physdev_info *info = matchinfo;
+
+	if (matchsize != IP6T_ALIGN(sizeof(struct ip6t_physdev_info)))
+		return 0;
+	if (!(info->bitmask & IP6T_PHYSDEV_OP_MASK) ||
+	    info->bitmask & ~IP6T_PHYSDEV_OP_MASK)
+		return 0;
+	return 1;
+}
+
+static struct ip6t_match physdev_match = {
+	.name		= "physdev",
+	.match		= &match,
+	.checkentry	= &checkentry,
+	.me		= THIS_MODULE,
+};
+
+static int __init init(void)
+{
+	return ip6t_register_match(&physdev_match);
+}
+
+static void __exit fini(void)
+{
+	ip6t_unregister_match(&physdev_match);
+}
+
+module_init(init);
+module_exit(fini);
diff -Nru a/net/ipv6/netfilter/ip6table_filter.c b/net/ipv6/netfilter/ip6table_filter.c
--- a/net/ipv6/netfilter/ip6table_filter.c	2004-10-18 14:55:54 -07:00
+++ b/net/ipv6/netfilter/ip6table_filter.c	2004-10-18 14:55:54 -07:00
@@ -10,6 +10,7 @@
  */
 
 #include <linux/module.h>
+#include <linux/moduleparam.h>
 #include <linux/netfilter_ipv6/ip6_tables.h>
 
 MODULE_LICENSE("GPL");
@@ -156,7 +157,7 @@
 
 /* Default to forward because I got too much mail already. */
 static int forward = NF_ACCEPT;
-MODULE_PARM(forward, "i");
+module_param(forward, bool, 0000);
 
 static int __init init(void)
 {
diff -Nru a/net/ipv6/raw.c b/net/ipv6/raw.c
--- a/net/ipv6/raw.c	2004-10-18 14:56:28 -07:00
+++ b/net/ipv6/raw.c	2004-10-18 14:56:28 -07:00
@@ -555,12 +555,58 @@
 	IP6_INC_STATS(IPSTATS_MIB_OUTDISCARDS);
 	return err; 
 }
+
+static void rawv6_probe_proto_opt(struct flowi *fl, struct msghdr *msg)
+{
+	struct iovec *iov;
+	u8 __user *type = NULL;
+	u8 __user *code = NULL;
+	int probed = 0;
+	int i;
+
+	if (!msg->msg_iov)
+		return;
+
+	for (i = 0; i < msg->msg_iovlen; i++) {
+		iov = &msg->msg_iov[i];
+		if (!iov)
+			continue;
+
+		switch (fl->proto) {
+		case IPPROTO_ICMPV6:
+			/* check if one-byte field is readable or not. */
+			if (iov->iov_base && iov->iov_len < 1)
+				break;
+
+			if (!type) {
+				type = iov->iov_base;
+				/* check if code field is readable or not. */
+				if (iov->iov_len > 1)
+					code = type + 1;
+			} else if (!code)
+				code = iov->iov_base;
+
+			if (type && code) {
+				get_user(fl->fl_icmp_type, type);
+				__get_user(fl->fl_icmp_code, code);
+				probed = 1;
+			}
+			break;
+		default:
+			probed = 1;
+			break;
+		}
+		if (probed)
+			break;
+	}
+}
+
 static int rawv6_sendmsg(struct kiocb *iocb, struct sock *sk,
 		   struct msghdr *msg, size_t len)
 {
 	struct ipv6_txoptions opt_space;
 	struct sockaddr_in6 * sin6 = (struct sockaddr_in6 *) msg->msg_name;
-	struct in6_addr *daddr;
+	struct in6_addr *daddr, *final_p = NULL, final;
 	struct inet_opt *inet = inet_sk(sk);
 	struct ipv6_pinfo *np = inet6_sk(sk);
 	struct raw6_opt *raw_opt = raw6_sk(sk);
@@ -674,6 +720,8 @@
 		opt = fl6_merge_options(&opt_space, flowlabel, opt);
 
 	fl.proto = proto;
+	rawv6_probe_proto_opt(&fl, msg);
+ 
 	ipv6_addr_copy(&fl.fl6_dst, daddr);
 	if (ipv6_addr_any(&fl.fl6_src) && !ipv6_addr_any(&np->saddr))
 		ipv6_addr_copy(&fl.fl6_src, &np->saddr);
@@ -681,7 +729,9 @@
 	/* merge ip6_build_xmit from ip6_output */
 	if (opt && opt->srcrt) {
 		struct rt0_hdr *rt0 = (struct rt0_hdr *) opt->srcrt;
+		ipv6_addr_copy(&final, &fl.fl6_dst);
 		ipv6_addr_copy(&fl.fl6_dst, rt0->addr);
+		final_p = &final;
 	}
 
 	if (!fl.oif && ipv6_addr_is_multicast(&fl.fl6_dst))
@@ -690,6 +740,13 @@
 	err = ip6_dst_lookup(sk, &dst, &fl);
 	if (err)
 		goto out;
+	if (final_p)
+		ipv6_addr_copy(&fl.fl6_dst, final_p);
+
+	if ((err = xfrm_lookup(&dst, &fl, sk, 0)) < 0) {
+		dst_release(dst);
+		goto out;
+	}
 
 	if (hlimit < 0) {
 		if (ipv6_addr_is_multicast(&fl.fl6_dst))
@@ -932,6 +989,7 @@
 	.backlog_rcv =	rawv6_rcv_skb,
 	.hash =		raw_v6_hash,
 	.unhash =	raw_v6_unhash,
+	.slab_obj_size = sizeof(struct raw6_sock),
 };
 
 #ifdef CONFIG_PROC_FS
diff -Nru a/net/ipv6/reassembly.c b/net/ipv6/reassembly.c
--- a/net/ipv6/reassembly.c	2004-10-18 14:56:28 -07:00
+++ b/net/ipv6/reassembly.c	2004-10-18 14:56:28 -07:00
@@ -195,14 +195,18 @@
 atomic_t ip6_frag_mem = ATOMIC_INIT(0);
 
 /* Memory Tracking Functions. */
-static inline void frag_kfree_skb(struct sk_buff *skb)
+static inline void frag_kfree_skb(struct sk_buff *skb, int *work)
 {
+	if (work)
+		*work -= skb->truesize;
 	atomic_sub(skb->truesize, &ip6_frag_mem);
 	kfree_skb(skb);
 }
 
-static inline void frag_free_queue(struct frag_queue *fq)
+static inline void frag_free_queue(struct frag_queue *fq, int *work)
 {
+	if (work)
+		*work -= sizeof(struct frag_queue);
 	atomic_sub(sizeof(struct frag_queue), &ip6_frag_mem);
 	kfree(fq);
 }
@@ -220,7 +224,7 @@
 /* Destruction primitives. */
 
 /* Complete destruction of fq. */
-static void ip6_frag_destroy(struct frag_queue *fq)
+static void ip6_frag_destroy(struct frag_queue *fq, int *work)
 {
 	struct sk_buff *fp;
 
@@ -232,17 +236,17 @@
 	while (fp) {
 		struct sk_buff *xp = fp->next;
 
-		frag_kfree_skb(fp);
+		frag_kfree_skb(fp, work);
 		fp = xp;
 	}
 
-	frag_free_queue(fq);
+	frag_free_queue(fq, work);
 }
 
-static __inline__ void fq_put(struct frag_queue *fq)
+static __inline__ void fq_put(struct frag_queue *fq, int *work)
 {
 	if (atomic_dec_and_test(&fq->refcnt))
-		ip6_frag_destroy(fq);
+		ip6_frag_destroy(fq, work);
 }
 
 /* Kill fq entry. It is not destroyed immediately,
@@ -264,10 +268,13 @@
 {
 	struct frag_queue *fq;
 	struct list_head *tmp;
+	int work;
 
-	for(;;) {
-		if (atomic_read(&ip6_frag_mem) <= sysctl_ip6frag_low_thresh)
-			return;
+	work = atomic_read(&ip6_frag_mem) - sysctl_ip6frag_low_thresh;
+	if (work <= 0)
+		return;
+
+	while(work > 0) {
 		read_lock(&ip6_frag_lock);
 		if (list_empty(&ip6_frag_lru_list)) {
 			read_unlock(&ip6_frag_lock);
@@ -283,7 +290,7 @@
 			fq_kill(fq);
 		spin_unlock(&fq->lock);
 
-		fq_put(fq);
+		fq_put(fq, &work);
 		IP6_INC_STATS_BH(IPSTATS_MIB_REASMFAILS);
 	}
 }
@@ -320,7 +327,7 @@
 	}
 out:
 	spin_unlock(&fq->lock);
-	fq_put(fq);
+	fq_put(fq, NULL);
 }
 
 /* Creation primitives. */
@@ -340,7 +347,7 @@
 			atomic_inc(&fq->refcnt);
 			write_unlock(&ip6_frag_lock);
 			fq_in->last_in |= COMPLETE;
-			fq_put(fq_in);
+			fq_put(fq_in, NULL);
 			return fq;
 		}
 	}
@@ -539,7 +546,7 @@
 				fq->fragments = next;
 
 			fq->meat -= free_it->len;
-			frag_kfree_skb(free_it);
+			frag_kfree_skb(free_it, NULL);
 		}
 	}
 
@@ -658,7 +665,7 @@
 	head->next = NULL;
 	head->dev = dev;
 	head->stamp = fq->stamp;
-	head->nh.ipv6h->payload_len = ntohs(payload_len);
+	head->nh.ipv6h->payload_len = htons(payload_len);
 
 	*skb_in = head;
 
@@ -734,7 +741,7 @@
 			ret = ip6_frag_reasm(fq, skbp, nhoffp, dev);
 
 		spin_unlock(&fq->lock);
-		fq_put(fq);
+		fq_put(fq, NULL);
 		return ret;
 	}
 
diff -Nru a/net/ipv6/route.c b/net/ipv6/route.c
--- a/net/ipv6/route.c	2004-10-18 14:56:49 -07:00
+++ b/net/ipv6/route.c	2004-10-18 14:56:49 -07:00
@@ -155,7 +155,16 @@
 
 static void ip6_dst_ifdown(struct dst_entry *dst, int how)
 {
-	ip6_dst_destroy(dst);
+	struct rt6_info *rt = (struct rt6_info *)dst;
+	struct inet6_dev *idev = rt->rt6i_idev;
+
+	if (idev != NULL && idev->dev != &loopback_dev) {
+		struct inet6_dev *loopback_idev = in6_dev_get(&loopback_dev);
+		if (loopback_idev != NULL) {
+			rt->rt6i_idev = loopback_idev;
+			in6_dev_put(idev);
+		}
+	}
 }
 
 /*
@@ -174,8 +183,17 @@
 			struct net_device *dev = sprt->rt6i_dev;
 			if (dev->ifindex == oif)
 				return sprt;
-			if (dev->flags&IFF_LOOPBACK)
+			if (dev->flags & IFF_LOOPBACK) {
+				if (sprt->rt6i_idev == NULL ||
+				    sprt->rt6i_idev->dev->ifindex != oif) {
+					if (strict && oif)
+						continue;
+					if (local && (!oif || 
+						      local->rt6i_idev->dev->ifindex == oif))
+						continue;
+				}
 				local = sprt;
+			}
 		}
 
 		if (local)
@@ -190,8 +208,18 @@
 /*
  *	pointer to the last default router chosen. BH is disabled locally.
  */
-static struct rt6_info *rt6_dflt_pointer;
-static spinlock_t rt6_dflt_lock = SPIN_LOCK_UNLOCKED;
+struct rt6_info *rt6_dflt_pointer;
+spinlock_t rt6_dflt_lock = SPIN_LOCK_UNLOCKED;
+
+void rt6_reset_dflt_pointer(struct rt6_info *rt)
+{
+	spin_lock_bh(&rt6_dflt_lock);
+	if (rt == NULL || rt == rt6_dflt_pointer) {
+		RT6_TRACE("reset default router: %p->NULL\n", rt6_dflt_pointer);
+		rt6_dflt_pointer = NULL;
+	}
+	spin_unlock_bh(&rt6_dflt_lock);
+}
 
 /* Default Router Selection (RFC 2461 6.3.6) */
 static struct rt6_info *rt6_best_dflt(struct rt6_info *rt, int oif)
@@ -209,6 +237,10 @@
 		     sprt->rt6i_dev->ifindex == oif))
 			m += 8;
 
+		if ((sprt->rt6i_flags & RTF_EXPIRES) &&
+		    time_after(jiffies, sprt->rt6i_expires))
+			continue;
+
 		if (sprt == rt6_dflt_pointer)
 			m += 4;
 
@@ -336,13 +368,13 @@
 	return NULL;
 }
 
-/* rt6_ins is called with FREE rt6_lock.
+/* ip6_ins_rt is called with FREE rt6_lock.
    It takes new route entry, the addition fails by any reason the
    route is freed. In any case, if caller does not hold it, it may
    be destroyed.
  */
 
-static int rt6_ins(struct rt6_info *rt, struct nlmsghdr *nlh, void *_rtattr)
+int ip6_ins_rt(struct rt6_info *rt, struct nlmsghdr *nlh, void *_rtattr)
 {
 	int err;
 
@@ -390,7 +422,7 @@
 
 		dst_hold(&rt->u.dst);
 
-		err = rt6_ins(rt, NULL, NULL);
+		err = ip6_ins_rt(rt, NULL, NULL);
 		if (err == 0)
 			return rt;
 
@@ -608,8 +640,13 @@
 				  struct in6_addr *addr,
 				  int (*output)(struct sk_buff **))
 {
-	struct rt6_info *rt = ip6_dst_alloc();
+	struct rt6_info *rt;
+	struct inet6_dev *idev = in6_dev_get(dev);
+
+	if (unlikely(idev == NULL))
+		return NULL;
 
+	rt = ip6_dst_alloc();
 	if (unlikely(rt == NULL))
 		goto out;
 
@@ -620,7 +657,7 @@
 		neigh = ndisc_get_neigh(dev, addr);
 
 	rt->rt6i_dev	  = dev;
-	rt->rt6i_idev     = in6_dev_get(dev);
+	rt->rt6i_idev     = idev;
 	rt->rt6i_nexthop  = neigh;
 	atomic_set(&rt->u.dst.__refcnt, 1);
 	rt->u.dst.metrics[RTAX_HOPLIMIT-1] = 255;
@@ -731,8 +768,9 @@
 	int err;
 	struct rtmsg *r;
 	struct rtattr **rta;
-	struct rt6_info *rt;
+	struct rt6_info *rt = NULL;
 	struct net_device *dev = NULL;
+	struct inet6_dev *idev = NULL;
 	int addr_type;
 
 	rta = (struct rtattr **) _rtattr;
@@ -744,9 +782,13 @@
 		return -EINVAL;
 #endif
 	if (rtmsg->rtmsg_ifindex) {
+		err = -ENODEV;
 		dev = dev_get_by_index(rtmsg->rtmsg_ifindex);
 		if (!dev)
-			return -ENODEV;
+			goto out;
+		idev = in6_dev_get(dev);
+		if (!idev)
+			goto out;
 	}
 
 	if (rtmsg->rtmsg_metric == 0)
@@ -793,10 +835,20 @@
 	 */
 	if ((rtmsg->rtmsg_flags&RTF_REJECT) ||
 	    (dev && (dev->flags&IFF_LOOPBACK) && !(addr_type&IPV6_ADDR_LOOPBACK))) {
-		if (dev)
-			dev_put(dev);
-		dev = &loopback_dev;
-		dev_hold(dev);
+		/* hold loopback dev/idev if we haven't done so. */
+		if (dev != &loopback_dev) {
+			if (dev) {
+				dev_put(dev);
+				in6_dev_put(idev);
+			}
+			dev = &loopback_dev;
+			dev_hold(dev);
+			idev = in6_dev_get(dev);
+			if (!idev) {
+				err = -ENODEV;
+				goto out;
+			}
+		}
 		rt->u.dst.output = ip6_pkt_discard_out;
 		rt->u.dst.input = ip6_pkt_discard;
 		rt->u.dst.error = -ENETUNREACH;
@@ -838,7 +890,9 @@
 				}
 			} else {
 				dev = grt->rt6i_dev;
+				idev = grt->rt6i_idev;
 				dev_hold(dev);
+				in6_dev_hold(grt->rt6i_idev);
 			}
 			if (!(grt->rt6i_flags&RTF_GATEWAY))
 				err = 0;
@@ -900,8 +954,8 @@
 	if (!rt->u.dst.metrics[RTAX_ADVMSS-1])
 		rt->u.dst.metrics[RTAX_ADVMSS-1] = ipv6_advmss(dst_pmtu(&rt->u.dst));
 	rt->u.dst.dev = dev;
-	rt->rt6i_idev = in6_dev_get(dev);
-	return rt6_ins(rt, nlh, _rtattr);
+	rt->rt6i_idev = idev;
+	return ip6_ins_rt(rt, nlh, _rtattr);
 
 out:
 	if (dev)
@@ -916,9 +970,7 @@
 
 	write_lock_bh(&rt6_lock);
 
-	spin_lock_bh(&rt6_dflt_lock);
-	rt6_dflt_pointer = NULL;
-	spin_unlock_bh(&rt6_dflt_lock);
+	rt6_reset_dflt_pointer(NULL);
 
 	dst_release(&rt->u.dst);
 
@@ -967,7 +1019,7 @@
  *	Handle redirects
  */
 void rt6_redirect(struct in6_addr *dest, struct in6_addr *saddr,
-		  struct neighbour *neigh, int on_link)
+		  struct neighbour *neigh, u8 *lladdr, int on_link)
 {
 	struct rt6_info *rt, *nrt;
 
@@ -980,22 +1032,13 @@
 	if (neigh->dev != rt->rt6i_dev)
 		goto out;
 
-	/* Redirect received -> path was valid.
-	   Look, redirects are sent only in response to data packets,
-	   so that this nexthop apparently is reachable. --ANK
-	 */
-	dst_confirm(&rt->u.dst);
-
-	/* Duplicate redirect: silently ignore. */
-	if (neigh == rt->u.dst.neighbour)
-		goto out;
-
-	/* Current route is on-link; redirect is always invalid.
-	   
-	   Seems, previous statement is not true. It could
-	   be node, which looks for us as on-link (f.e. proxy ndisc)
-	   But then router serving it might decide, that we should
-	   know truth 8)8) --ANK (980726).
+	/*
+	 * Current route is on-link; redirect is always invalid.
+	 * 
+	 * Seems, previous statement is not true. It could
+	 * be node, which looks for us as on-link (f.e. proxy ndisc)
+	 * But then router serving it might decide, that we should
+	 * know truth 8)8) --ANK (980726).
 	 */
 	if (!(rt->rt6i_flags&RTF_GATEWAY))
 		goto out;
@@ -1007,7 +1050,6 @@
 	 *	is a bit fuzzy and one might need to check all default
 	 *	routers.
 	 */
-
 	if (ipv6_addr_cmp(saddr, &rt->rt6i_gateway)) {
 		if (rt->rt6i_flags & RTF_DEFAULT) {
 			struct rt6_info *rt1;
@@ -1036,6 +1078,24 @@
 	 *	We have finally decided to accept it.
 	 */
 
+	neigh_update(neigh, lladdr, NUD_STALE, 
+		     NEIGH_UPDATE_F_WEAK_OVERRIDE|
+		     NEIGH_UPDATE_F_OVERRIDE|
+		     (on_link ? 0 : (NEIGH_UPDATE_F_OVERRIDE_ISROUTER|
+				     NEIGH_UPDATE_F_ISROUTER))
+		     );
+
+	/*
+	 * Redirect received -> path was valid.
+	 * Look, redirects are sent only in response to data packets,
+	 * so that this nexthop apparently is reachable. --ANK
+	 */
+	dst_confirm(&rt->u.dst);
+
+	/* Duplicate redirect: silently ignore. */
+	if (neigh == rt->u.dst.neighbour)
+		goto out;
+
 	nrt = ip6_rt_copy(rt);
 	if (nrt == NULL)
 		goto out;
@@ -1054,7 +1114,7 @@
 	nrt->u.dst.metrics[RTAX_MTU-1] = ipv6_get_mtu(neigh->dev);
 	nrt->u.dst.metrics[RTAX_ADVMSS-1] = ipv6_advmss(dst_pmtu(&nrt->u.dst));
 
-	if (rt6_ins(nrt, NULL, NULL))
+	if (ip6_ins_rt(nrt, NULL, NULL))
 		goto out;
 
 	if (rt->rt6i_flags&RTF_CACHE) {
@@ -1144,7 +1204,7 @@
 		dst_set_expires(&nrt->u.dst, ip6_rt_mtu_expires);
 		nrt->rt6i_flags |= RTF_DYNAMIC|RTF_CACHE|RTF_EXPIRES;
 		nrt->u.dst.metrics[RTAX_MTU-1] = pmtu;
-		rt6_ins(nrt, NULL, NULL);
+		ip6_ins_rt(nrt, NULL, NULL);
 	}
 
 out:
@@ -1213,7 +1273,7 @@
 	rtmsg.rtmsg_type = RTMSG_NEWROUTE;
 	ipv6_addr_copy(&rtmsg.rtmsg_gateway, gwaddr);
 	rtmsg.rtmsg_metric = 1024;
-	rtmsg.rtmsg_flags = RTF_GATEWAY | RTF_ADDRCONF | RTF_DEFAULT | RTF_UP;
+	rtmsg.rtmsg_flags = RTF_GATEWAY | RTF_ADDRCONF | RTF_DEFAULT | RTF_UP | RTF_EXPIRES;
 
 	rtmsg.rtmsg_ifindex = dev->ifindex;
 
@@ -1237,9 +1297,7 @@
 		if (rt->rt6i_flags & flags) {
 			dst_hold(&rt->u.dst);
 
-			spin_lock_bh(&rt6_dflt_lock);
-			rt6_dflt_pointer = NULL;
-			spin_unlock_bh(&rt6_dflt_lock);
+			rt6_reset_dflt_pointer(NULL);
 
 			read_unlock_bh(&rt6_lock);
 
@@ -1299,27 +1357,32 @@
 
 int ip6_pkt_discard_out(struct sk_buff **pskb)
 {
+	(*pskb)->dev = (*pskb)->dst->dev;
+	BUG_ON(!(*pskb)->dev);
 	return ip6_pkt_discard(*pskb);
 }
 
 /*
- *	Add address
+ *	Allocate a dst for local (unicast / anycast) address.
  */
 
-int ip6_rt_addr_add(struct in6_addr *addr, struct net_device *dev, int anycast)
+struct rt6_info *addrconf_dst_alloc(struct inet6_dev *idev,
+				    const struct in6_addr *addr,
+				    int anycast)
 {
 	struct rt6_info *rt = ip6_dst_alloc();
 
 	if (rt == NULL)
-		return -ENOMEM;
+		return ERR_PTR(-ENOMEM);
 
 	dev_hold(&loopback_dev);
+	in6_dev_hold(idev);
 
 	rt->u.dst.flags = DST_HOST;
 	rt->u.dst.input = ip6_input;
 	rt->u.dst.output = ip6_output;
 	rt->rt6i_dev = &loopback_dev;
-	rt->rt6i_idev = in6_dev_get(&loopback_dev);
+	rt->rt6i_idev = idev;
 	rt->u.dst.metrics[RTAX_MTU-1] = ipv6_get_mtu(rt->rt6i_dev);
 	rt->u.dst.metrics[RTAX_ADVMSS-1] = ipv6_advmss(dst_pmtu(&rt->u.dst));
 	rt->u.dst.metrics[RTAX_HOPLIMIT-1] = ipv6_get_hoplimit(rt->rt6i_dev);
@@ -1331,34 +1394,15 @@
 	rt->rt6i_nexthop = ndisc_get_neigh(rt->rt6i_dev, &rt->rt6i_gateway);
 	if (rt->rt6i_nexthop == NULL) {
 		dst_free((struct dst_entry *) rt);
-		return -ENOMEM;
+		return ERR_PTR(-ENOMEM);
 	}
 
 	ipv6_addr_copy(&rt->rt6i_dst.addr, addr);
 	rt->rt6i_dst.plen = 128;
-	rt6_ins(rt, NULL, NULL);
-
-	return 0;
-}
 
-/* Delete address. Warning: you should check that this address
-   disappeared before calling this function.
- */
-
-int ip6_rt_addr_del(struct in6_addr *addr, struct net_device *dev)
-{
-	struct rt6_info *rt;
-	int err = -ENOENT;
-
-	rt = rt6_lookup(addr, NULL, loopback_dev.ifindex, 1);
-	if (rt) {
-		if (rt->rt6i_dst.plen == 128)
-			err = ip6_del_rt(rt, NULL, NULL);
-		else
-			dst_release(&rt->u.dst);
-	}
+	atomic_set(&rt->u.dst.__refcnt, 1);
 
-	return err;
+	return rt;
 }
 
 static int fib6_ifdown(struct rt6_info *rt, void *arg)
diff -Nru a/net/ipv6/sit.c b/net/ipv6/sit.c
--- a/net/ipv6/sit.c	2004-10-18 14:57:03 -07:00
+++ b/net/ipv6/sit.c	2004-10-18 14:57:03 -07:00
@@ -50,6 +50,7 @@
 #include <net/ipip.h>
 #include <net/inet_ecn.h>
 #include <net/xfrm.h>
+#include <net/dsfield.h>
 
 /*
    This version of net/ipv6/sit.c is cloned of net/ipv4/ip_gre.c
@@ -360,8 +361,7 @@
 
 static inline void ipip6_ecn_decapsulate(struct iphdr *iph, struct sk_buff *skb)
 {
-	if (INET_ECN_is_ce(iph->tos) &&
-	    INET_ECN_is_not_ce(ip6_get_dsfield(skb->nh.ipv6h)))
+	if (INET_ECN_is_ce(iph->tos))
 		IP6_ECN_set_ce(skb->nh.ipv6h);
 }
 
@@ -487,6 +487,7 @@
 		}
 	}
 	if (rt->rt_type != RTN_UNICAST) {
+		ip_rt_put(rt);
 		tunnel->stat.tx_carrier_errors++;
 		goto tx_error_icmp;
 	}
@@ -567,7 +568,7 @@
 		iph->frag_off	=	0;
 
 	iph->protocol		=	IPPROTO_IPV6;
-	iph->tos		=	INET_ECN_encapsulate(tos, ip6_get_dsfield(iph6));
+	iph->tos		=	INET_ECN_encapsulate(tos, ipv6_get_dsfield(iph6));
 	iph->daddr		=	rt->rt_dst;
 	iph->saddr		=	rt->rt_src;
 
@@ -814,18 +815,19 @@
 					   ipip6_tunnel_setup);
 	if (!ipip6_fb_tunnel_dev) {
 		err = -ENOMEM;
-		goto fail;
+		goto err1;
 	}
 
 	ipip6_fb_tunnel_dev->init = ipip6_fb_tunnel_init;
 
 	if ((err =  register_netdev(ipip6_fb_tunnel_dev)))
-		goto fail;
+		goto err2;
 
  out:
 	return err;
- fail:
-	inet_del_protocol(&sit_protocol, IPPROTO_IPV6);
+ err2:
 	free_netdev(ipip6_fb_tunnel_dev);
+ err1:
+	inet_del_protocol(&sit_protocol, IPPROTO_IPV6);
 	goto out;
 }
diff -Nru a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c
--- a/net/ipv6/tcp_ipv6.c	2004-10-18 14:56:32 -07:00
+++ b/net/ipv6/tcp_ipv6.c	2004-10-18 14:56:32 -07:00
@@ -57,6 +57,7 @@
 #include <net/xfrm.h>
 #include <net/addrconf.h>
 #include <net/snmp.h>
+#include <net/dsfield.h>
 
 #include <asm/uaccess.h>
 
@@ -549,7 +550,7 @@
 	struct inet_opt *inet = inet_sk(sk);
 	struct ipv6_pinfo *np = inet6_sk(sk);
 	struct tcp_opt *tp = tcp_sk(sk);
-	struct in6_addr *saddr = NULL;
+	struct in6_addr *saddr = NULL, *final_p = NULL, final;
 	struct flowi fl;
 	struct dst_entry *dst;
 	int addr_type;
@@ -666,13 +667,21 @@
 
 	if (np->opt && np->opt->srcrt) {
 		struct rt0_hdr *rt0 = (struct rt0_hdr *)np->opt->srcrt;
+		ipv6_addr_copy(&final, &fl.fl6_dst);
 		ipv6_addr_copy(&fl.fl6_dst, rt0->addr);
+		final_p = &final;
 	}
 
 	err = ip6_dst_lookup(sk, &dst, &fl);
-
 	if (err)
 		goto failure;
+	if (final_p)
+		ipv6_addr_copy(&fl.fl6_dst, final_p);
+
+	if ((err = xfrm_lookup(&dst, &fl, sk, 0)) < 0) {
+		dst_release(dst);
+		goto failure;
+	}
 
 	if (saddr == NULL) {
 		saddr = &fl.fl6_src;
@@ -793,6 +802,12 @@
 				sk->sk_err_soft = -err;
 				goto out;
 			}
+
+			if ((err = xfrm_lookup(&dst, &fl, sk, 0)) < 0) {
+				sk->sk_err_soft = -err;
+				goto out;
+			}
+
 		} else
 			dst_hold(dst);
 
@@ -863,6 +878,7 @@
 	struct ipv6_pinfo *np = inet6_sk(sk);
 	struct sk_buff * skb;
 	struct ipv6_txoptions *opt = NULL;
+	struct in6_addr * final_p = NULL, final;
 	struct flowi fl;
 	int err = -1;
 
@@ -888,12 +904,18 @@
 
 		if (opt && opt->srcrt) {
 			struct rt0_hdr *rt0 = (struct rt0_hdr *) opt->srcrt;
+			ipv6_addr_copy(&final, &fl.fl6_dst);
 			ipv6_addr_copy(&fl.fl6_dst, rt0->addr);
+			final_p = &final;
 		}
 
 		err = ip6_dst_lookup(sk, &dst, &fl);
 		if (err)
 			goto done;
+		if (final_p)
+			ipv6_addr_copy(&fl.fl6_dst, final_p);
+		if ((err = xfrm_lookup(&dst, &fl, sk, 0)) < 0)
+			goto done;
 	}
 
 	skb = tcp_make_synack(sk, dst, req);
@@ -981,11 +1003,12 @@
 	 * and then put it into the queue to be sent.
 	 */
 
-	buff = alloc_skb(MAX_HEADER + sizeof(struct ipv6hdr), GFP_ATOMIC);
+	buff = alloc_skb(MAX_HEADER + sizeof(struct ipv6hdr) + sizeof(struct tcphdr),
+			 GFP_ATOMIC);
 	if (buff == NULL) 
 	  	return;
 
-	skb_reserve(buff, MAX_HEADER + sizeof(struct ipv6hdr));
+	skb_reserve(buff, MAX_HEADER + sizeof(struct ipv6hdr) + sizeof(struct tcphdr));
 
 	t1 = (struct tcphdr *) skb_push(buff,sizeof(struct tcphdr));
 
@@ -1021,6 +1044,12 @@
 
 	/* sk = NULL, but it is safe for now. RST socket required. */
 	if (!ip6_dst_lookup(NULL, &buff->dst, &fl)) {
+
+		if ((xfrm_lookup(&buff->dst, &fl, NULL, 0)) < 0) {
+			dst_release(buff->dst);
+			return;
+		}
+
 		ip6_xmit(NULL, buff, &fl, NULL, 0);
 		TCP_INC_STATS_BH(TCP_MIB_OUTSEGS);
 		TCP_INC_STATS_BH(TCP_MIB_OUTRSTS);
@@ -1037,14 +1066,15 @@
 	struct flowi fl;
 	int tot_len = sizeof(struct tcphdr);
 
-	buff = alloc_skb(MAX_HEADER + sizeof(struct ipv6hdr), GFP_ATOMIC);
+	if (ts)
+		tot_len += 3*4;
+
+	buff = alloc_skb(MAX_HEADER + sizeof(struct ipv6hdr) + tot_len,
+			 GFP_ATOMIC);
 	if (buff == NULL)
 		return;
 
-	skb_reserve(buff, MAX_HEADER + sizeof(struct ipv6hdr));
-
-	if (ts)
-		tot_len += 3*4;
+	skb_reserve(buff, MAX_HEADER + sizeof(struct ipv6hdr) + tot_len);
 
 	t1 = (struct tcphdr *) skb_push(buff,tot_len);
 
@@ -1082,6 +1112,10 @@
 	fl.fl_ip_sport = t1->source;
 
 	if (!ip6_dst_lookup(NULL, &buff->dst, &fl)) {
+		if ((xfrm_lookup(&buff->dst, &fl, NULL, 0)) < 0) {
+			dst_release(buff->dst);
+			return;
+		}
 		ip6_xmit(NULL, buff, &fl, NULL, 0);
 		TCP_INC_STATS_BH(TCP_MIB_OUTSEGS);
 		return;
@@ -1313,6 +1347,7 @@
 	}
 
 	if (dst == NULL) {
+		struct in6_addr *final_p = NULL, final;
 		struct flowi fl;
 
 		memset(&fl, 0, sizeof(fl));
@@ -1320,7 +1355,9 @@
 		ipv6_addr_copy(&fl.fl6_dst, &req->af.v6_req.rmt_addr);
 		if (opt && opt->srcrt) {
 			struct rt0_hdr *rt0 = (struct rt0_hdr *) opt->srcrt;
+			ipv6_addr_copy(&final, &fl.fl6_dst);
 			ipv6_addr_copy(&fl.fl6_dst, rt0->addr);
+			final_p = &final;
 		}
 		ipv6_addr_copy(&fl.fl6_src, &req->af.v6_req.loc_addr);
 		fl.oif = sk->sk_bound_dev_if;
@@ -1329,6 +1366,12 @@
 
 		if (ip6_dst_lookup(sk, &dst, &fl))
 			goto out;
+
+		if (final_p)
+			ipv6_addr_copy(&fl.fl6_dst, final_p);
+
+		if ((xfrm_lookup(&dst, &fl, sk, 0)) < 0)
+			goto out;
 	} 
 
 	newsk = tcp_create_openreq_child(sk, req, skb);
@@ -1606,7 +1649,7 @@
 				    skb->len - th->doff*4);
 	TCP_SKB_CB(skb)->ack_seq = ntohl(th->ack_seq);
 	TCP_SKB_CB(skb)->when = 0;
-	TCP_SKB_CB(skb)->flags = ip6_get_dsfield(skb->nh.ipv6h);
+	TCP_SKB_CB(skb)->flags = ipv6_get_dsfield(skb->nh.ipv6h);
 	TCP_SKB_CB(skb)->sacked = 0;
 
 	sk = __tcp_v6_lookup(&skb->nh.ipv6h->saddr, th->source,
@@ -1710,6 +1753,7 @@
 
 	if (dst == NULL) {
 		struct inet_opt *inet = inet_sk(sk);
+		struct in6_addr *final_p = NULL, final;
 		struct flowi fl;
 
 		memset(&fl, 0, sizeof(fl));
@@ -1723,15 +1767,24 @@
 
 		if (np->opt && np->opt->srcrt) {
 			struct rt0_hdr *rt0 = (struct rt0_hdr *) np->opt->srcrt;
+			ipv6_addr_copy(&final, &fl.fl6_dst);
 			ipv6_addr_copy(&fl.fl6_dst, rt0->addr);
+			final_p = &final;
 		}
 
 		err = ip6_dst_lookup(sk, &dst, &fl);
-
 		if (err) {
 			sk->sk_route_caps = 0;
 			return err;
 		}
+		if (final_p)
+			ipv6_addr_copy(&fl.fl6_dst, final_p);
+
+		if ((err = xfrm_lookup(&dst, &fl, sk, 0)) < 0) {
+			sk->sk_err_soft = -err;
+			dst_release(dst);
+			return err;
+		}
 
 		ip6_dst_store(sk, dst, NULL);
 		sk->sk_route_caps = dst->dev->features &
@@ -1775,6 +1828,12 @@
 			return err;
 		}
 
+		if ((err = xfrm_lookup(&dst, &fl, sk, 0)) < 0) {
+			sk->sk_route_caps = 0;
+			dst_release(dst);
+			return err;
+		}
+
 		ip6_dst_store(sk, dst, NULL);
 		sk->sk_route_caps = dst->dev->features &
 			~(NETIF_F_IP_CSUM | NETIF_F_TSO);
@@ -1873,7 +1932,7 @@
 	 */
 	tp->snd_ssthresh = 0x7fffffff;
 	tp->snd_cwnd_clamp = ~0;
-	tp->mss_cache = 536;
+	tp->mss_cache_std = tp->mss_cache = 536;
 
 	tp->reordering = sysctl_tcp_reordering;
 
@@ -2089,6 +2148,7 @@
 	.sysctl_wmem		= sysctl_tcp_wmem,
 	.sysctl_rmem		= sysctl_tcp_rmem,
 	.max_header		= MAX_TCP_HEADER,
+	.slab_obj_size		= sizeof(struct tcp6_sock),
 };
 
 static struct inet6_protocol tcpv6_protocol = {
diff -Nru a/net/ipv6/udp.c b/net/ipv6/udp.c
--- a/net/ipv6/udp.c	2004-10-18 14:56:49 -07:00
+++ b/net/ipv6/udp.c	2004-10-18 14:56:49 -07:00
@@ -627,7 +627,7 @@
 	struct inet_opt *inet = inet_sk(sk);
 	struct ipv6_pinfo *np = inet6_sk(sk);
 	struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *) msg->msg_name;
-	struct in6_addr *daddr;
+	struct in6_addr *daddr, *final_p = NULL, final;
 	struct ipv6_txoptions *opt = NULL;
 	struct ip6_flowlabel *flowlabel = NULL;
 	struct flowi *fl = &inet->cork.fl;
@@ -783,7 +783,9 @@
 	/* merge ip6_build_xmit from ip6_output */
 	if (opt && opt->srcrt) {
 		struct rt0_hdr *rt0 = (struct rt0_hdr *) opt->srcrt;
+		ipv6_addr_copy(&final, &fl->fl6_dst);
 		ipv6_addr_copy(&fl->fl6_dst, rt0->addr);
+		final_p = &final;
 	}
 
 	if (!fl->oif && ipv6_addr_is_multicast(&fl->fl6_dst))
@@ -792,6 +794,13 @@
 	err = ip6_dst_lookup(sk, &dst, fl);
 	if (err)
 		goto out;
+	if (final_p)
+		ipv6_addr_copy(&fl->fl6_dst, final_p);
+
+	if ((err = xfrm_lookup(&dst, fl, sk, 0)) < 0) {
+		dst_release(dst);
+		goto out;
+	}
 
 	if (hlimit < 0) {
 		if (ipv6_addr_is_multicast(&fl->fl6_dst))
@@ -1037,6 +1046,7 @@
 	.hash =		udp_v6_hash,
 	.unhash =	udp_v6_unhash,
 	.get_port =	udp_v6_get_port,
+	.slab_obj_size = sizeof(struct udp6_sock),
 };
 
 extern struct proto_ops inet6_dgram_ops;
diff -Nru a/net/ipv6/xfrm6_input.c b/net/ipv6/xfrm6_input.c
--- a/net/ipv6/xfrm6_input.c	2004-10-18 14:57:05 -07:00
+++ b/net/ipv6/xfrm6_input.c	2004-10-18 14:57:05 -07:00
@@ -9,7 +9,9 @@
  *		IPv6 support
  */
 
+#include <linux/module.h>
 #include <linux/string.h>
+#include <net/dsfield.h>
 #include <net/inet_ecn.h>
 #include <net/ip.h>
 #include <net/ipv6.h>
@@ -20,16 +22,15 @@
 	struct ipv6hdr *outer_iph = skb->nh.ipv6h;
 	struct ipv6hdr *inner_iph = skb->h.ipv6h;
 
-	if (INET_ECN_is_ce(ip6_get_dsfield(outer_iph)) &&
-	    INET_ECN_is_not_ce(ip6_get_dsfield(inner_iph)))
+	if (INET_ECN_is_ce(ipv6_get_dsfield(outer_iph)))
 		IP6_ECN_set_ce(inner_iph);
 }
 
-int xfrm6_rcv(struct sk_buff **pskb, unsigned int *nhoffp)
+int xfrm6_rcv_spi(struct sk_buff **pskb, unsigned int *nhoffp, u32 spi)
 {
 	struct sk_buff *skb = *pskb;
 	int err;
-	u32 spi, seq;
+	u32 seq;
 	struct sec_decap_state xfrm_vec[XFRM_MAX_DEPTH];
 	struct xfrm_state *x;
 	int xfrm_nr = 0;
@@ -40,7 +41,8 @@
 	nhoff = *nhoffp;
 	nexthdr = skb->nh.raw[nhoff];
 
-	if ((err = xfrm_parse_spi(skb, nexthdr, &spi, &seq)) != 0)
+	seq = 0;
+	if (!spi && (err = xfrm_parse_spi(skb, nexthdr, &spi, &seq)) != 0)
 		goto drop;
 	
 	do {
@@ -86,6 +88,8 @@
 			if (skb_cloned(skb) &&
 			    pskb_expand_head(skb, 0, 0, GFP_ATOMIC))
 				goto drop;
+			if (x->props.flags & XFRM_STATE_DECAP_DSCP)
+				ipv6_copy_dscp(skb->nh.ipv6h, skb->h.ipv6h);
 			if (!(x->props.flags & XFRM_STATE_NOECN))
 				ipip6_ecn_decapsulate(skb);
 			skb->mac.raw = memmove(skb->data - skb->mac_len,
@@ -136,4 +140,11 @@
 		xfrm_state_put(xfrm_vec[xfrm_nr].xvec);
 	kfree_skb(skb);
 	return -1;
+}
+
+EXPORT_SYMBOL(xfrm6_rcv_spi);
+
+int xfrm6_rcv(struct sk_buff **pskb, unsigned int *nhoffp)
+{
+	return xfrm6_rcv_spi(pskb, nhoffp, 0);
 }
diff -Nru a/net/ipv6/xfrm6_output.c b/net/ipv6/xfrm6_output.c
--- a/net/ipv6/xfrm6_output.c	2004-10-18 14:57:03 -07:00
+++ b/net/ipv6/xfrm6_output.c	2004-10-18 14:57:03 -07:00
@@ -12,6 +12,7 @@
 #include <linux/skbuff.h>
 #include <linux/spinlock.h>
 #include <linux/icmpv6.h>
+#include <net/dsfield.h>
 #include <net/inet_ecn.h>
 #include <net/ipv6.h>
 #include <net/xfrm.h>
@@ -36,6 +37,7 @@
 	struct dst_entry *dst = skb->dst;
 	struct xfrm_state *x = dst->xfrm;
 	struct ipv6hdr *iph, *top_iph;
+	int dsfield;
 
 	skb_push(skb, x->props.header_len);
 	iph = skb->nh.ipv6h;
@@ -58,13 +60,16 @@
 
 	top_iph->version = 6;
 	top_iph->priority = iph->priority;
-	if (x->props.flags & XFRM_STATE_NOECN)
-		IP6_ECN_clear(top_iph);
 	top_iph->flow_lbl[0] = iph->flow_lbl[0];
 	top_iph->flow_lbl[1] = iph->flow_lbl[1];
 	top_iph->flow_lbl[2] = iph->flow_lbl[2];
+	dsfield = ipv6_get_dsfield(top_iph);
+	dsfield = INET_ECN_encapsulate(dsfield, dsfield);
+	if (x->props.flags & XFRM_STATE_NOECN)
+		dsfield &= ~INET_ECN_MASK;
+	ipv6_change_dsfield(top_iph, 0, dsfield);
 	top_iph->nexthdr = IPPROTO_IPV6; 
-	top_iph->hop_limit = iph->hop_limit;
+	top_iph->hop_limit = dst_path_metric(dst, RTAX_HOPLIMIT);
 	ipv6_addr_copy(&top_iph->saddr, (struct in6_addr *)&x->props.saddr);
 	ipv6_addr_copy(&top_iph->daddr, (struct in6_addr *)&x->id.daddr);
 }
@@ -113,8 +118,7 @@
 
 	xfrm6_encap(skb);
 
-	err = x->type->output(pskb);
-	skb = *pskb;
+	err = x->type->output(skb);
 	if (err)
 		goto error;
 
diff -Nru a/net/ipv6/xfrm6_policy.c b/net/ipv6/xfrm6_policy.c
--- a/net/ipv6/xfrm6_policy.c	2004-10-18 14:56:18 -07:00
+++ b/net/ipv6/xfrm6_policy.c	2004-10-18 14:56:18 -07:00
@@ -17,12 +17,12 @@
 #include <net/ipv6.h>
 #include <net/ip6_route.h>
 
-extern struct dst_ops xfrm6_dst_ops;
-extern struct xfrm_policy_afinfo xfrm6_policy_afinfo;
+static struct dst_ops xfrm6_dst_ops;
+static struct xfrm_policy_afinfo xfrm6_policy_afinfo;
 
 static struct xfrm_type_map xfrm6_type_map = { .lock = RW_LOCK_UNLOCKED };
 
-int xfrm6_dst_lookup(struct xfrm_dst **dst, struct flowi *fl)
+static int xfrm6_dst_lookup(struct xfrm_dst **dst, struct flowi *fl)
 {
 	int err = 0;
 	*dst = (struct xfrm_dst*)ip6_route_output(NULL, fl);
@@ -213,6 +213,16 @@
 			fl->proto = nexthdr;
 			return;
 
+		case IPPROTO_ICMPV6:
+			if (pskb_may_pull(skb, skb->nh.raw + offset + 2 - skb->data)) {
+				u8 *icmp = (u8 *)exthdr;
+
+				fl->fl_icmp_type = icmp[0];
+				fl->fl_icmp_code = icmp[1];
+			}
+			fl->proto = nexthdr;
+			return;
+
 		/* XXX Why are there these headers? */
 		case IPPROTO_AH:
 		case IPPROTO_ESP:
@@ -243,7 +253,7 @@
 	return;
 }
 
-struct dst_ops xfrm6_dst_ops = {
+static struct dst_ops xfrm6_dst_ops = {
 	.family =		AF_INET6,
 	.protocol =		__constant_htons(ETH_P_IPV6),
 	.gc =			xfrm6_garbage_collect,
@@ -252,7 +262,7 @@
 	.entry_size =		sizeof(struct xfrm_dst),
 };
 
-struct xfrm_policy_afinfo xfrm6_policy_afinfo = {
+static struct xfrm_policy_afinfo xfrm6_policy_afinfo = {
 	.family =		AF_INET6,
 	.lock = 		RW_LOCK_UNLOCKED,
 	.type_map = 		&xfrm6_type_map,
@@ -263,12 +273,12 @@
 	.decode_session =	_decode_session6,
 };
 
-void __init xfrm6_policy_init(void)
+static void __init xfrm6_policy_init(void)
 {
 	xfrm_policy_register_afinfo(&xfrm6_policy_afinfo);
 }
 
-void __exit xfrm6_policy_fini(void)
+static void __exit xfrm6_policy_fini(void)
 {
 	xfrm_policy_unregister_afinfo(&xfrm6_policy_afinfo);
 }
@@ -277,12 +287,10 @@
 {
 	xfrm6_policy_init();
 	xfrm6_state_init();
-	xfrm6_tunnel_init();
 }
 
 void __exit xfrm6_fini(void)
 {
-	xfrm6_tunnel_fini();
 	//xfrm6_input_fini();
 	xfrm6_policy_fini();
 	xfrm6_state_fini();
diff -Nru a/net/ipv6/xfrm6_tunnel.c b/net/ipv6/xfrm6_tunnel.c
--- a/net/ipv6/xfrm6_tunnel.c	2004-10-18 14:56:48 -07:00
+++ b/net/ipv6/xfrm6_tunnel.c	2004-10-18 14:56:48 -07:00
@@ -343,9 +343,8 @@
 
 EXPORT_SYMBOL(xfrm6_tunnel_free_spi);
 
-static int xfrm6_tunnel_output(struct sk_buff **pskb)
+static int xfrm6_tunnel_output(struct sk_buff *skb)
 {
-	struct sk_buff *skb = *pskb;
 	struct ipv6hdr *top_iph;
 
 	top_iph = (struct ipv6hdr *)skb->data;
@@ -356,17 +355,6 @@
 
 static int xfrm6_tunnel_input(struct xfrm_state *x, struct xfrm_decap_state *decap, struct sk_buff *skb)
 {
-	if (!pskb_may_pull(skb, sizeof(struct ipv6hdr))) 
-		return -EINVAL;
-
-	skb->mac.raw = skb->nh.raw;
-	skb->nh.raw = skb->data;
-	dst_release(skb->dst);
-	skb->dst = NULL;
-	skb->protocol = htons(ETH_P_IPV6);
-	skb->pkt_type = PACKET_HOST;
-	netif_rx(skb);
-
 	return 0;
 }
 
@@ -413,49 +401,15 @@
 {
 	struct sk_buff *skb = *pskb;
 	struct xfrm6_tunnel *handler = xfrm6_tunnel_handler;
-	struct xfrm_state *x = NULL;
 	struct ipv6hdr *iph = skb->nh.ipv6h;
-	int err = 0;
 	u32 spi;
 
 	/* device-like_ip6ip6_handler() */
-	if (handler) {
-		err = handler->handler(pskb, nhoffp);
-		if (!err)
-			goto out;
-	}
+	if (handler && handler->handler(pskb, nhoffp) == 0)
+		return 0;
 
 	spi = xfrm6_tunnel_spi_lookup((xfrm_address_t *)&iph->saddr);
-	x = xfrm_state_lookup((xfrm_address_t *)&iph->daddr, 
-			spi,
-			IPPROTO_IPV6, AF_INET6);
-
-	if (!x)
-		goto drop;
-
-	spin_lock(&x->lock);
-
-	if (unlikely(x->km.state != XFRM_STATE_VALID))
-		goto drop_unlock;
-
-	err = xfrm6_tunnel_input(x, NULL, skb);
-	if (err)
-		goto drop_unlock;
-
-	x->curlft.bytes += skb->len;
-	x->curlft.packets++; 
-	spin_unlock(&x->lock); 
-	xfrm_state_put(x); 
-
-out:
-	return 0;
-
-drop_unlock:
-	spin_unlock(&x->lock);
-	xfrm_state_put(x);
-drop:
-	kfree_skb(skb);
-	return -1;
+	return xfrm6_rcv_spi(pskb, nhoffp, spi);
 }
 
 static void xfrm6_tunnel_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
@@ -517,6 +471,9 @@
 	if (!x->props.mode)
 		return -EINVAL;
 
+	if (x->encap)
+		return -EINVAL;
+
 	x->props.header_len = sizeof(struct ipv6hdr);
 
 	return 0;
@@ -543,31 +500,32 @@
 	.flags          = INET6_PROTO_NOPOLICY|INET6_PROTO_FINAL,
 };
 
-void __init xfrm6_tunnel_init(void)
+static int __init xfrm6_tunnel_init(void)
 {
 	X6TPRINTK3(KERN_DEBUG "%s()\n", __FUNCTION__);
 
 	if (xfrm_register_type(&xfrm6_tunnel_type, AF_INET6) < 0) {
 		X6TPRINTK1(KERN_ERR
 			   "xfrm6_tunnel init: can't add xfrm type\n");
-		return;
+		return -EAGAIN;
 	}
 	if (inet6_add_protocol(&xfrm6_tunnel_protocol, IPPROTO_IPV6) < 0) {
 		X6TPRINTK1(KERN_ERR
 			   "xfrm6_tunnel init(): can't add protocol\n");
 		xfrm_unregister_type(&xfrm6_tunnel_type, AF_INET6);
-		return;
+		return -EAGAIN;
 	}
 	if (xfrm6_tunnel_spi_init() < 0) {
 		X6TPRINTK1(KERN_ERR
 			   "xfrm6_tunnel init: failed to initialize spi\n");
 		inet6_del_protocol(&xfrm6_tunnel_protocol, IPPROTO_IPV6);
 		xfrm_unregister_type(&xfrm6_tunnel_type, AF_INET6);
-		return;
+		return -EAGAIN;
 	}
+	return 0;
 }
 
-void __exit xfrm6_tunnel_fini(void)
+static void __exit xfrm6_tunnel_fini(void)
 {
 	X6TPRINTK3(KERN_DEBUG "%s()\n", __FUNCTION__);
 
@@ -579,3 +537,7 @@
 		X6TPRINTK1(KERN_ERR
 			   "xfrm6_tunnel close: can't remove xfrm type\n");
 }
+
+module_init(xfrm6_tunnel_init);
+module_exit(xfrm6_tunnel_fini);
+MODULE_LICENSE("GPL");
diff -Nru a/net/ipx/af_ipx.c b/net/ipx/af_ipx.c
--- a/net/ipx/af_ipx.c	2004-10-18 14:56:15 -07:00
+++ b/net/ipx/af_ipx.c	2004-10-18 14:56:15 -07:00
@@ -1621,6 +1621,7 @@
 
 	sipx.sipx_family = AF_IPX;
 	sipx.sipx_type	 = ipxs->type;
+	sipx.sipx_zero	 = 0;
 	memcpy(uaddr, &sipx, sizeof(sipx));
 
 	rc = 0;
@@ -1808,6 +1809,7 @@
 		memcpy(sipx->sipx_node, ipx->ipx_source.node, IPX_NODE_LEN);
 		sipx->sipx_network	= IPX_SKB_CB(skb)->ipx_source_net;
 		sipx->sipx_type 	= ipx->ipx_type;
+		sipx->sipx_zero		= 0;
 	}
 	rc = copied;
 
diff -Nru a/net/irda/irlan/irlan_common.c b/net/irda/irlan/irlan_common.c
--- a/net/irda/irlan/irlan_common.c	2004-10-18 14:56:32 -07:00
+++ b/net/irda/irlan/irlan_common.c	2004-10-18 14:56:32 -07:00
@@ -36,6 +36,7 @@
 #include <linux/netdevice.h>
 #include <linux/etherdevice.h>
 #include <linux/rtnetlink.h>
+#include <linux/moduleparam.h>
 
 #include <asm/system.h>
 #include <asm/bitops.h>
@@ -1181,9 +1182,9 @@
 MODULE_DESCRIPTION("The Linux IrDA LAN protocol"); 
 MODULE_LICENSE("GPL");
 
-MODULE_PARM(eth, "i");
+module_param(eth, bool, 0);
 MODULE_PARM_DESC(eth, "Name devices ethX (0) or irlanX (1)");
-MODULE_PARM(access, "i");
+module_param(access, int, 0);
 MODULE_PARM_DESC(access, "Access type DIRECT=1, PEER=2, HOSTED=3");
 
 module_init(irlan_init);
diff -Nru a/net/irda/irlan/irlan_eth.c b/net/irda/irlan/irlan_eth.c
--- a/net/irda/irlan/irlan_eth.c	2004-10-18 14:56:27 -07:00
+++ b/net/irda/irlan/irlan_eth.c	2004-10-18 14:56:27 -07:00
@@ -303,10 +303,10 @@
 	 */
 #ifdef CONFIG_INET
 	IRDA_DEBUG(4, "IrLAN: Sending gratuitous ARP\n");
-	in_dev = in_dev_get(dev);
+	rcu_read_lock();
+	in_dev = __in_dev_get(dev);
 	if (in_dev == NULL)
-		return;
-	read_lock(&in_dev->lock);
+		goto out;
 	if (in_dev->ifa_list)
 		
 	arp_send(ARPOP_REQUEST, ETH_P_ARP, 
@@ -314,8 +314,8 @@
 		 dev, 
 		 in_dev->ifa_list->ifa_address,
 		 NULL, dev->dev_addr, NULL);
-	read_unlock(&in_dev->lock);
-	in_dev_put(in_dev);
+out:
+	rcu_read_unlock();
 #endif /* CONFIG_INET */
 }
 
diff -Nru a/net/irda/irqueue.c b/net/irda/irqueue.c
--- a/net/irda/irqueue.c	2004-10-18 14:56:11 -07:00
+++ b/net/irda/irqueue.c	2004-10-18 14:56:11 -07:00
@@ -663,8 +663,10 @@
 	} /* Default is no-lock  */
 
 	/* Check if valid and not already removed... */
-	if((entry->q_next == NULL) || (entry->q_prev == NULL))
-		return NULL;
+	if((entry->q_next == NULL) || (entry->q_prev == NULL)) {
+		entry = NULL;
+		goto out;
+	}
 
 	/*
 	 * Locate hashbin
@@ -687,7 +689,7 @@
 	 */
 	if ( entry == hashbin->hb_current)
 		hashbin->hb_current = NULL;
-
+out:
 	/* Release lock */
 	if ( hashbin->hb_type & HB_LOCK ) {
 		spin_unlock_irqrestore(&hashbin->hb_spinlock, flags);
diff -Nru a/net/key/af_key.c b/net/key/af_key.c
--- a/net/key/af_key.c	2004-10-18 14:57:19 -07:00
+++ b/net/key/af_key.c	2004-10-18 14:57:19 -07:00
@@ -683,6 +683,8 @@
 	sa->sadb_sa_flags = 0;
 	if (x->props.flags & XFRM_STATE_NOECN)
 		sa->sadb_sa_flags |= SADB_SAFLAGS_NOECN;
+	if (x->props.flags & XFRM_STATE_DECAP_DSCP)
+		sa->sadb_sa_flags |= SADB_SAFLAGS_DECAP_DSCP;
 
 	/* hard time */
 	if (hsc & 2) {
@@ -965,6 +967,8 @@
 	x->props.replay_window = sa->sadb_sa_replay;
 	if (sa->sadb_sa_flags & SADB_SAFLAGS_NOECN)
 		x->props.flags |= XFRM_STATE_NOECN;
+	if (sa->sadb_sa_flags & SADB_SAFLAGS_DECAP_DSCP)
+		x->props.flags |= XFRM_STATE_DECAP_DSCP;
 
 	lifetime = (struct sadb_lifetime*) ext_hdrs[SADB_EXT_LIFETIME_HARD-1];
 	if (lifetime != NULL) {
@@ -1075,15 +1079,6 @@
 		n_type = ext_hdrs[SADB_X_EXT_NAT_T_TYPE-1];
 		natt->encap_type = n_type->sadb_x_nat_t_type_type;
 
-		switch (natt->encap_type) {
-		case UDP_ENCAP_ESPINUDP:
-		case UDP_ENCAP_ESPINUDP_NON_IKE:
-			break;
-		default:
-			err = -ENOPROTOOPT;
-			goto out;
-		}
-
 		if (ext_hdrs[SADB_X_EXT_NAT_T_SPORT-1]) {
 			struct sadb_x_nat_t_port* n_port =
 				ext_hdrs[SADB_X_EXT_NAT_T_SPORT-1];
@@ -1165,7 +1160,16 @@
 		break;
 #endif
 	}
-	if (xdaddr)
+
+	if (hdr->sadb_msg_seq) {
+		x = xfrm_find_acq_byseq(hdr->sadb_msg_seq);
+		if (x && xfrm_addr_cmp(&x->id.daddr, xdaddr, family)) {
+			xfrm_state_put(x);
+			x = NULL;
+		}
+	}
+
+	if (!x)
 		x = xfrm_find_acq(mode, reqid, proto, xdaddr, xsaddr, 1, family);
 
 	if (x == NULL)
diff -Nru a/net/llc/af_llc.c b/net/llc/af_llc.c
--- a/net/llc/af_llc.c	2004-10-18 14:55:53 -07:00
+++ b/net/llc/af_llc.c	2004-10-18 14:55:53 -07:00
@@ -638,7 +638,6 @@
 	newsk = skb->sk;
 	/* attach connection to a new socket. */
 	llc_ui_sk_init(newsock, newsk);
-	newsk->sk_pair		= NULL;
 	newsk->sk_zapped	= 0;
 	newsk->sk_state		= TCP_ESTABLISHED;
 	newsock->state		= SS_CONNECTED;
diff -Nru a/net/llc/llc_input.c b/net/llc/llc_input.c
--- a/net/llc/llc_input.c	2004-10-18 14:56:49 -07:00
+++ b/net/llc/llc_input.c	2004-10-18 14:56:49 -07:00
@@ -111,7 +111,7 @@
 	skb->h.raw += llc_len;
 	skb_pull(skb, llc_len);
 	if (skb->protocol == htons(ETH_P_802_2)) {
-		u16 pdulen = ((struct ethhdr *)skb->mac.raw)->h_proto,
+		u16 pdulen = eth_hdr(skb)->h_proto,
 		    data_size = ntohs(pdulen) - llc_len;
 
 		skb_trim(skb, data_size);
diff -Nru a/net/llc/llc_output.c b/net/llc/llc_output.c
--- a/net/llc/llc_output.c	2004-10-18 14:56:49 -07:00
+++ b/net/llc/llc_output.c	2004-10-18 14:56:49 -07:00
@@ -40,7 +40,8 @@
 		struct net_device *dev = skb->dev;
 		struct trh_hdr *trh;
 		
-		trh = (struct trh_hdr *)skb_push(skb, sizeof(*trh));
+		skb->mac.raw = skb_push(skb, sizeof(*trh));
+		trh = tr_hdr(skb);
 		trh->ac = AC;
 		trh->fc = LLC_FRAME;
 		if (sa)
@@ -50,8 +51,8 @@
 		if (da) {
 			memcpy(trh->daddr, da, dev->addr_len);
 			tr_source_route(skb, trh, dev);
+			skb->mac.raw = skb->data;
 		}
-		skb->mac.raw = skb->data;
 		break;
 	}
 #endif
@@ -61,7 +62,7 @@
 		struct ethhdr *eth;
 
 		skb->mac.raw = skb_push(skb, sizeof(*eth));
-		eth = (struct ethhdr *)skb->mac.raw;
+		eth = eth_hdr(skb);
 		eth->h_proto = htons(len);
 		memcpy(eth->h_dest, da, ETH_ALEN);
 		memcpy(eth->h_source, sa, ETH_ALEN);
diff -Nru a/net/netlink/af_netlink.c b/net/netlink/af_netlink.c
--- a/net/netlink/af_netlink.c	2004-10-18 14:56:32 -07:00
+++ b/net/netlink/af_netlink.c	2004-10-18 14:56:32 -07:00
@@ -536,12 +536,31 @@
 	sock_put(sk);
 }
 
+static inline void netlink_trim(struct sk_buff *skb, int allocation)
+{
+	int delta = skb->end - skb->tail;
+
+	/* If the packet is charged to a socket, the modification
+	 * of truesize below is illegal and will corrupt socket
+	 * buffer accounting state.
+	 */
+	BUG_ON(skb->list != NULL);
+
+	if (delta * 2 < skb->truesize)
+		return;
+	if (pskb_expand_head(skb, 0, -delta, allocation))
+		return;
+	skb->truesize -= delta;
+}
+
 int netlink_unicast(struct sock *ssk, struct sk_buff *skb, u32 pid, int nonblock)
 {
 	struct sock *sk;
 	int err;
 	long timeo;
 
+	netlink_trim(skb, gfp_any());
+
 	timeo = sock_sndtimeo(ssk, nonblock);
 retry:
 	sk = netlink_getsockbypid(ssk, pid);
@@ -588,6 +607,8 @@
 	int protocol = ssk->sk_protocol;
 	int failure = 0, delivered = 0;
 
+	netlink_trim(skb, allocation);
+
 	/* While we sleep in clone, do not allow to change socket list */
 
 	netlink_lock_table();
@@ -1220,7 +1241,6 @@
 
 EXPORT_SYMBOL(netlink_ack);
 EXPORT_SYMBOL(netlink_broadcast);
-EXPORT_SYMBOL(netlink_broadcast_deliver);
 EXPORT_SYMBOL(netlink_dump_start);
 EXPORT_SYMBOL(netlink_kernel_create);
 EXPORT_SYMBOL(netlink_register_notifier);
diff -Nru a/net/netrom/af_netrom.c b/net/netrom/af_netrom.c
--- a/net/netrom/af_netrom.c	2004-10-18 14:56:31 -07:00
+++ b/net/netrom/af_netrom.c	2004-10-18 14:56:31 -07:00
@@ -801,7 +801,6 @@
 	remove_wait_queue(sk->sk_sleep, &wait);
 
 	newsk = skb->sk;
-	newsk->sk_pair = NULL;
 	newsk->sk_socket = newsock;
 	newsk->sk_sleep = &newsock->wait;
 
@@ -994,7 +993,6 @@
 	nr_make->vl        = 0;
 	nr_make->state     = NR_STATE_3;
 	sk->sk_ack_backlog++;
-	make->sk_pair = sk;
 
 	nr_insert_socket(make);
 
diff -Nru a/net/packet/af_packet.c b/net/packet/af_packet.c
--- a/net/packet/af_packet.c	2004-10-18 14:56:48 -07:00
+++ b/net/packet/af_packet.c	2004-10-18 14:56:48 -07:00
@@ -65,6 +65,8 @@
 #include <asm/system.h>
 #include <asm/uaccess.h>
 #include <asm/ioctls.h>
+#include <asm/page.h>
+#include <asm/io.h>
 #include <linux/proc_fs.h>
 #include <linux/seq_file.h>
 #include <linux/poll.h>
@@ -172,7 +174,7 @@
 {
 	struct tpacket_stats	stats;
 #ifdef CONFIG_PACKET_MMAP
-	unsigned long		*pg_vec;
+	char *			*pg_vec;
 	unsigned int		head;
 	unsigned int            frames_per_block;
 	unsigned int		frame_size;
@@ -197,15 +199,15 @@
 
 #ifdef CONFIG_PACKET_MMAP
 
-static inline unsigned long packet_lookup_frame(struct packet_opt *po, unsigned int position)
+static inline char *packet_lookup_frame(struct packet_opt *po, unsigned int position)
 {
 	unsigned int pg_vec_pos, frame_offset;
-	unsigned long frame;
+	char *frame;
 
 	pg_vec_pos = position / po->frames_per_block;
 	frame_offset = position % po->frames_per_block;
 
-	frame = (unsigned long) (po->pg_vec[pg_vec_pos] + (frame_offset * po->frame_size));
+	frame = po->pg_vec[pg_vec_pos] + (frame_offset * po->frame_size);
 	
 	return frame;
 }
@@ -784,11 +786,13 @@
 static int packet_release(struct socket *sock)
 {
 	struct sock *sk = sock->sk;
-	struct packet_opt *po = pkt_sk(sk);
+	struct packet_opt *po;
 
 	if (!sk)
 		return 0;
 
+	po = pkt_sk(sk);
+
 	write_lock_bh(&packet_sklist_lock);
 	sk_del_node_init(sk);
 	write_unlock_bh(&packet_sklist_lock);
@@ -1548,7 +1552,12 @@
 	.close =packet_mm_close,
 };
 
-static void free_pg_vec(unsigned long *pg_vec, unsigned order, unsigned len)
+static inline struct page *pg_vec_endpage(char *one_pg_vec, unsigned int order)
+{
+	return virt_to_page(one_pg_vec + (PAGE_SIZE << order) - 1);
+}
+
+static void free_pg_vec(char **pg_vec, unsigned order, unsigned len)
 {
 	int i;
 
@@ -1556,10 +1565,10 @@
 		if (pg_vec[i]) {
 			struct page *page, *pend;
 
-			pend = virt_to_page(pg_vec[i] + (PAGE_SIZE << order) - 1);
+			pend = pg_vec_endpage(pg_vec[i], order);
 			for (page = virt_to_page(pg_vec[i]); page <= pend; page++)
 				ClearPageReserved(page);
-			free_pages(pg_vec[i], order);
+			free_pages((unsigned long)pg_vec[i], order);
 		}
 	}
 	kfree(pg_vec);
@@ -1568,7 +1577,7 @@
 
 static int packet_set_ring(struct sock *sk, struct tpacket_req *req, int closing)
 {
-	unsigned long *pg_vec = NULL;
+	char **pg_vec = NULL;
 	struct packet_opt *po = pkt_sk(sk);
 	int was_running, num, order = 0;
 	int err = 0;
@@ -1603,18 +1612,18 @@
 
 		err = -ENOMEM;
 
-		pg_vec = kmalloc(req->tp_block_nr*sizeof(unsigned long*), GFP_KERNEL);
+		pg_vec = kmalloc(req->tp_block_nr*sizeof(char *), GFP_KERNEL);
 		if (pg_vec == NULL)
 			goto out;
-		memset(pg_vec, 0, req->tp_block_nr*sizeof(unsigned long*));
+		memset(pg_vec, 0, req->tp_block_nr*sizeof(char **));
 
 		for (i=0; i<req->tp_block_nr; i++) {
 			struct page *page, *pend;
-			pg_vec[i] = __get_free_pages(GFP_KERNEL, order);
+			pg_vec[i] = (char *)__get_free_pages(GFP_KERNEL, order);
 			if (!pg_vec[i])
 				goto out_free_pgvec;
 
-			pend = virt_to_page(pg_vec[i] + (PAGE_SIZE << order) - 1);
+			pend = pg_vec_endpage(pg_vec[i], order);
 			for (page = virt_to_page(pg_vec[i]); page <= pend; page++)
 				SetPageReserved(page);
 		}
@@ -1622,7 +1631,7 @@
 
 		l = 0;
 		for (i=0; i<req->tp_block_nr; i++) {
-			unsigned long ptr = pg_vec[i];
+			char *ptr = pg_vec[i];
 			struct tpacket_hdr *header;
 			int k;
 
diff -Nru a/net/rose/af_rose.c b/net/rose/af_rose.c
--- a/net/rose/af_rose.c	2004-10-18 14:56:31 -07:00
+++ b/net/rose/af_rose.c	2004-10-18 14:56:31 -07:00
@@ -882,7 +882,6 @@
 	remove_wait_queue(sk->sk_sleep, &wait);
 
 	newsk = skb->sk;
-	newsk->sk_pair = NULL;
 	newsk->sk_socket = newsock;
 	newsk->sk_sleep = &newsock->wait;
 
@@ -996,7 +995,6 @@
 	make_rose->vr        = 0;
 	make_rose->vl        = 0;
 	sk->sk_ack_backlog++;
-	make->sk_pair = sk;
 
 	rose_insert_socket(make);
 
diff -Nru a/net/rxrpc/call.c b/net/rxrpc/call.c
--- a/net/rxrpc/call.c	2004-10-18 14:56:50 -07:00
+++ b/net/rxrpc/call.c	2004-10-18 14:56:50 -07:00
@@ -472,7 +472,7 @@
 {
 	struct rxrpc_message *msg;
 	struct kvec diov[3];
-	unsigned aux[4];
+	__be32 aux[4];
 	int delta, ret;
 
 	/* ACKs default to DELAY */
@@ -840,7 +840,7 @@
 	struct rxrpc_message *msg;
 	struct kvec diov[1];
 	int ret;
-	u32 _error;
+	__be32 _error;
 
 	_enter("%p{%08x},%p{%d},%d",
 	       conn, ntohl(conn->conn_id), call, ntohl(call->call_id), errno);
@@ -929,7 +929,6 @@
 {
 	struct rxrpc_message *msg;
 	struct list_head *_p;
-	uint32_t data32;
 
 	_enter("%p", call);
 
@@ -986,22 +985,21 @@
 			break;
 
 			/* deal with abort packets */
-		case RXRPC_PACKET_TYPE_ABORT:
-			data32 = 0;
-			if (skb_copy_bits(msg->pkt, msg->offset,
-					  &data32, sizeof(data32)) < 0) {
+		case RXRPC_PACKET_TYPE_ABORT: {
+			__be32 _dbuf, *dp;
+
+			dp = skb_header_pointer(msg->pkt, msg->offset,
+						sizeof(_dbuf), &_dbuf);
+			if (dp == NULL)
 				printk("Rx Received short ABORT packet\n");
-			}
-			else {
-				data32 = ntohl(data32);
-			}
 
-			_proto("Rx Received Call ABORT { data=%d }", data32);
+			_proto("Rx Received Call ABORT { data=%d }",
+			       (dp ? ntohl(*dp) : 0));
 
 			spin_lock(&call->lock);
 			call->app_call_state	= RXRPC_CSTATE_ERROR;
 			call->app_err_state	= RXRPC_ESTATE_PEER_ABORT;
-			call->app_abort_code	= data32;
+			call->app_abort_code	= (dp ? ntohl(*dp) : 0);
 			call->app_errno		= -ECONNABORTED;
 			call->app_mark		= RXRPC_APP_MARK_EOF;
 			call->app_read_buf	= NULL;
@@ -1013,7 +1011,7 @@
 			spin_unlock(&call->lock);
 			call->app_error_func(call);
 			break;
-
+		}
 		default:
 			/* deal with other packet types */
 			_proto("Rx Unsupported packet type %u (#%u)",
@@ -1050,7 +1048,7 @@
 	struct rxrpc_message *pmsg;
 	struct list_head *_p;
 	int ret, lo, hi, rmtimo;
-	u32 opid;
+	__be32 opid;
 
 	_enter("%p{%u},%p{%u}", call, ntohl(call->call_id), msg, msg->seq);
 
@@ -1271,41 +1269,42 @@
 static void rxrpc_call_receive_ack_packet(struct rxrpc_call *call,
 					  struct rxrpc_message *msg)
 {
-	struct rxrpc_ackpacket ack;
-	rxrpc_serial_t serial;
+	struct rxrpc_ackpacket _ack, *ap;
+	rxrpc_serial_net_t serial;
 	rxrpc_seq_t seq;
 	int ret;
 
 	_enter("%p{%u},%p{%u}", call, ntohl(call->call_id), msg, msg->seq);
 
 	/* extract the basic ACK record */
-	if (skb_copy_bits(msg->pkt, msg->offset, &ack, sizeof(ack)) < 0) {
+	ap = skb_header_pointer(msg->pkt, msg->offset, sizeof(_ack), &_ack);
+	if (ap == NULL) {
 		printk("Rx Received short ACK packet\n");
 		return;
 	}
-	msg->offset += sizeof(ack);
+	msg->offset += sizeof(_ack);
 
-	serial = ack.serial;
-	seq = ntohl(ack.firstPacket);
+	serial = ap->serial;
+	seq = ntohl(ap->firstPacket);
 
 	_proto("Rx Received ACK %%%d { b=%hu m=%hu f=%u p=%u s=%u r=%s n=%u }",
 	       ntohl(msg->hdr.serial),
-	       ntohs(ack.bufferSpace),
-	       ntohs(ack.maxSkew),
+	       ntohs(ap->bufferSpace),
+	       ntohs(ap->maxSkew),
 	       seq,
-	       ntohl(ack.previousPacket),
+	       ntohl(ap->previousPacket),
 	       ntohl(serial),
-	       rxrpc_acks[ack.reason],
+	       rxrpc_acks[ap->reason],
 	       call->ackr.nAcks
 	       );
 
 	/* check the other side isn't ACK'ing a sequence number I haven't sent
 	 * yet */
-	if (ack.nAcks > 0 &&
+	if (ap->nAcks > 0 &&
 	    (seq > call->snd_seq_count ||
-	     seq + ack.nAcks - 1 > call->snd_seq_count)) {
+	     seq + ap->nAcks - 1 > call->snd_seq_count)) {
 		printk("Received ACK (#%u-#%u) for unsent packet\n",
-		       seq, seq + ack.nAcks - 1);
+		       seq, seq + ap->nAcks - 1);
 		rxrpc_call_abort(call, -EINVAL);
 		_leave("");
 		return;
@@ -1354,7 +1353,7 @@
 		}
 	}
 
-	switch (ack.reason) {
+	switch (ap->reason) {
 		/* deal with negative/positive acknowledgement of data
 		 * packets */
 	case RXRPC_ACK_REQUESTED:
@@ -1366,14 +1365,14 @@
 	case RXRPC_ACK_OUT_OF_SEQUENCE:
 	case RXRPC_ACK_EXCEEDS_WINDOW:
 		call->snd_resend_cnt = 0;
-		ret = rxrpc_call_record_ACK(call, msg, seq, ack.nAcks);
+		ret = rxrpc_call_record_ACK(call, msg, seq, ap->nAcks);
 		if (ret < 0)
 			rxrpc_call_abort(call, ret);
 		break;
 
 		/* respond to ping packets immediately */
 	case RXRPC_ACK_PING:
-		rxrpc_call_generate_ACK(call, &msg->hdr, &ack);
+		rxrpc_call_generate_ACK(call, &msg->hdr, ap);
 		break;
 
 		/* only record RTT on ping response packets */
@@ -1386,7 +1385,7 @@
 			rttmsg = NULL;
 			spin_lock(&call->lock);
 			if (call->snd_ping &&
-			    call->snd_ping->hdr.serial == ack.serial) {
+			    call->snd_ping->hdr.serial == ap->serial) {
 				rttmsg = call->snd_ping;
 				call->snd_ping = NULL;
 			}
@@ -1402,7 +1401,7 @@
 		break;
 
 	default:
-		printk("Unsupported ACK reason %u\n", ack.reason);
+		printk("Unsupported ACK reason %u\n", ap->reason);
 		break;
 	}
 
diff -Nru a/net/rxrpc/connection.c b/net/rxrpc/connection.c
--- a/net/rxrpc/connection.c	2004-10-18 14:56:33 -07:00
+++ b/net/rxrpc/connection.c	2004-10-18 14:56:33 -07:00
@@ -88,8 +88,8 @@
  * create a new connection record for outgoing connections
  */
 int rxrpc_create_connection(struct rxrpc_transport *trans,
-			    uint16_t port,
-			    uint32_t addr,
+			    __be16 port,
+			    __be32 addr,
 			    uint16_t service_id,
 			    void *security,
 			    struct rxrpc_connection **_conn)
@@ -97,7 +97,7 @@
 	struct rxrpc_connection *candidate, *conn;
 	struct rxrpc_peer *peer;
 	struct list_head *_p;
-	uint32_t connid;
+	__be32 connid;
 	int ret;
 
 	_enter("%p{%hu},%u,%hu", trans, trans->port, ntohs(port), service_id);
@@ -169,7 +169,7 @@
 	spin_unlock(&peer->conn_gylock);
 
 	/* pick the new candidate */
-	_debug("created connection: {%08x} [out]", htonl(candidate->conn_id));
+	_debug("created connection: {%08x} [out]", ntohl(candidate->conn_id));
 	atomic_inc(&peer->conn_count);
 	conn = candidate;
 	candidate = NULL;
@@ -199,7 +199,7 @@
 
 	/* handle resurrecting a connection from the graveyard */
  found_in_graveyard:
-	_debug("resurrecting connection: {%08x} [out]", htonl(conn->conn_id));
+	_debug("resurrecting connection: {%08x} [out]", ntohl(conn->conn_id));
 	rxrpc_get_connection(conn);
 	rxrpc_krxtimod_del_timer(&conn->timeout);
 	list_del_init(&conn->link);
@@ -219,8 +219,9 @@
 	struct rxrpc_connection *conn, *candidate = NULL;
 	struct list_head *_p;
 	int ret, fresh = 0;
-	u32 x_epoch, x_connid;
-	u16 x_port, x_secix, x_servid;
+	__be32 x_epoch, x_connid;
+	__be16 x_port, x_servid;
+	__u32 x_secix;
 	u8 x_clflag;
 
 	_enter("%p{{%hu}},%u,%hu",
@@ -310,7 +311,7 @@
 	}
 
 	/* we can now add the new candidate to the list */
-	_debug("created connection: {%08x} [in]", htonl(candidate->conn_id));
+	_debug("created connection: {%08x} [in]", ntohl(candidate->conn_id));
 	rxrpc_get_peer(peer);
 	conn = candidate;
 	candidate = NULL;
@@ -351,7 +352,7 @@
 
 	/* handle resurrecting a connection from the graveyard */
  found_in_graveyard:
-	_debug("resurrecting connection: {%08x} [in]", htonl(conn->conn_id));
+	_debug("resurrecting connection: {%08x} [in]", ntohl(conn->conn_id));
 	rxrpc_get_peer(peer);
 	rxrpc_get_connection(conn);
 	rxrpc_krxtimod_del_timer(&conn->timeout);
@@ -397,7 +398,7 @@
 	}
 
 	/* move to graveyard queue */
-	_debug("burying connection: {%08x}", htonl(conn->conn_id));
+	_debug("burying connection: {%08x}", ntohl(conn->conn_id));
 	list_del(&conn->link);
 	list_add_tail(&conn->link, &peer->conn_graveyard);
 
@@ -442,7 +443,7 @@
 	}
 
 	_debug("--- Destroying Connection %p{%08x} ---",
-	       conn, htonl(conn->conn_id));
+	       conn, ntohl(conn->conn_id));
 
 	down_write(&rxrpc_conns_sem);
 	list_del(&conn->proc_link);
@@ -640,8 +641,8 @@
 	_net("Sending message type %d of %Zd bytes to %08x:%d",
 	     msg->hdr.type,
 	     msg->dsize,
-	     htonl(conn->addr.sin_addr.s_addr),
-	     htons(conn->addr.sin_port));
+	     ntohl(conn->addr.sin_addr.s_addr),
+	     ntohs(conn->addr.sin_port));
 
 	/* send the message */
 	ret = kernel_sendmsg(conn->trans->socket, &msghdr,
@@ -699,11 +700,11 @@
 	}
 
 	_proto("Received packet %%%u [%u] on call %hu:%u:%u",
-	       htonl(msg->hdr.serial),
-	       htonl(msg->hdr.seq),
-	       htons(msg->hdr.serviceId),
-	       htonl(conn->conn_id),
-	       htonl(call->call_id));
+	       ntohl(msg->hdr.serial),
+	       ntohl(msg->hdr.seq),
+	       ntohs(msg->hdr.serviceId),
+	       ntohl(conn->conn_id),
+	       ntohl(call->call_id));
 
 	call->pkt_rcv_count++;
 
diff -Nru a/net/rxrpc/main.c b/net/rxrpc/main.c
--- a/net/rxrpc/main.c	2004-10-18 14:56:50 -07:00
+++ b/net/rxrpc/main.c	2004-10-18 14:56:50 -07:00
@@ -32,7 +32,7 @@
 MODULE_AUTHOR("Red Hat, Inc.");
 MODULE_LICENSE("GPL");
 
-uint32_t rxrpc_epoch;
+__be32 rxrpc_epoch;
 
 /*****************************************************************************/
 /*
diff -Nru a/net/rxrpc/peer.c b/net/rxrpc/peer.c
--- a/net/rxrpc/peer.c	2004-10-18 14:56:29 -07:00
+++ b/net/rxrpc/peer.c	2004-10-18 14:56:29 -07:00
@@ -48,7 +48,7 @@
 /*
  * create a peer record
  */
-static int __rxrpc_create_peer(struct rxrpc_transport *trans, uint32_t addr,
+static int __rxrpc_create_peer(struct rxrpc_transport *trans, __be32 addr,
 			       struct rxrpc_peer **_peer)
 {
 	struct rxrpc_peer *peer;
@@ -96,7 +96,7 @@
  * - returns (if successful) with peer record usage incremented
  * - resurrects it from the graveyard if found there
  */
-int rxrpc_peer_lookup(struct rxrpc_transport *trans, uint32_t addr,
+int rxrpc_peer_lookup(struct rxrpc_transport *trans, __be32 addr,
 		      struct rxrpc_peer **_peer)
 {
 	struct rxrpc_peer *peer, *candidate = NULL;
diff -Nru a/net/rxrpc/transport.c b/net/rxrpc/transport.c
--- a/net/rxrpc/transport.c	2004-10-18 14:56:49 -07:00
+++ b/net/rxrpc/transport.c	2004-10-18 14:56:49 -07:00
@@ -457,8 +457,8 @@
 	struct rxrpc_peer *peer;
 	struct sk_buff *pkt;
 	int ret;
-	u32 addr;
-	u16 port;
+	__be32 addr;
+	__be16 port;
 
 	LIST_HEAD(msgq);
 
@@ -612,7 +612,7 @@
 	struct sockaddr_in sin;
 	struct msghdr msghdr;
 	struct kvec iov[2];
-	uint32_t _error;
+	__be32 _error;
 	int len, ret;
 
 	_enter("%p,%p,%d", trans, msg, error);
@@ -655,8 +655,8 @@
 	_net("Sending message type %d of %d bytes to %08x:%d",
 	     ahdr.type,
 	     len,
-	     htonl(sin.sin_addr.s_addr),
-	     htons(sin.sin_port));
+	     ntohl(sin.sin_addr.s_addr),
+	     ntohs(sin.sin_port));
 
 	/* send the message */
 	ret = kernel_sendmsg(trans->socket, &msghdr, iov, 2, len);
@@ -678,7 +678,7 @@
 	struct list_head connq, *_p;
 	struct errormsg emsg;
 	struct msghdr msg;
-	uint16_t port;
+	__be16 port;
 	int local, err;
 
 	_enter("%p", trans);
diff -Nru a/net/sched/Kconfig b/net/sched/Kconfig
--- a/net/sched/Kconfig	2004-10-18 14:57:03 -07:00
+++ b/net/sched/Kconfig	2004-10-18 14:57:03 -07:00
@@ -317,7 +317,7 @@
 	  module will be called cls_u32.
 
 config CLS_U32_PERF
-	bool "     U32 classifier performance counters"
+	bool "U32 classifier performance counters"
 	depends on NET_CLS_U32
 	help
 	  gathers stats that could be used to tune u32 classifier performance.
@@ -364,7 +364,7 @@
 	  module will be called cls_rsvp6.
 
 config NET_CLS_ACT
-	bool '  Packet ACTION ' 
+	bool "Packet ACTION"
 	depends on EXPERIMENTAL && NET_CLS && NET_QOS
 	---help---
 	This option requires you have a new iproute2. It enables
@@ -373,7 +373,7 @@
 	  You MUST NOT turn this on if you dont have an update iproute2.
 
 config NET_ACT_POLICE
-	tristate '      Policing Actions' 
+	tristate "Policing Actions"
         depends on NET_CLS_ACT 
         ---help---
         If you are using a newer iproute2 select this one, otherwise use one
@@ -387,3 +387,15 @@
 	  Say Y to support traffic policing (bandwidth limits).  Needed for
 	  ingress and egress rate limiting.
 
+config NET_ACT_GACT
+        tristate "generic Actions"
+        depends on NET_CLS_ACT
+        ---help---
+        You must have new iproute2 to use this feature
+        This adds simple filtering actions like drop,accepet etc 
+                                                                                
+config GACT_PROB
+        bool "generic Actions probability"
+        depends on NET_ACT_GACT
+        ---help---
+        Allows generic actions to be randomly  or deterministically used
diff -Nru a/net/sched/Makefile b/net/sched/Makefile
--- a/net/sched/Makefile	2004-10-18 14:56:32 -07:00
+++ b/net/sched/Makefile	2004-10-18 14:56:32 -07:00
@@ -8,8 +8,9 @@
 obj-$(CONFIG_NET_ESTIMATOR)	+= estimator.o
 obj-$(CONFIG_NET_CLS)		+= cls_api.o
 obj-$(CONFIG_NET_CLS_ACT)       += act_api.o
-obj-$(CONFIG_NET_ACT_POLICE)    += police.o
-obj-$(CONFIG_NET_CLS_POLICE)    += police.o
+obj-$(CONFIG_NET_ACT_POLICE)	+= police.o
+obj-$(CONFIG_NET_CLS_POLICE)	+= police.o
+obj-$(CONFIG_NET_ACT_GACT)      += gact.o
 obj-$(CONFIG_NET_SCH_CBQ)	+= sch_cbq.o
 obj-$(CONFIG_NET_SCH_HTB)	+= sch_htb.o
 obj-$(CONFIG_NET_SCH_HPFQ)	+= sch_hpfq.o
diff -Nru a/net/sched/act_api.c b/net/sched/act_api.c
--- a/net/sched/act_api.c	2004-10-18 14:57:18 -07:00
+++ b/net/sched/act_api.c	2004-10-18 14:57:18 -07:00
@@ -155,7 +155,7 @@
 	return a;
 }
 
-int tcf_action_exec(struct sk_buff *skb,struct tc_action *act)
+int tcf_action_exec(struct sk_buff *skb,struct tc_action *act, struct tcf_result *res)
 {
 
 	struct tc_action *a;
@@ -164,7 +164,8 @@
 	if (skb->tc_verd & TC_NCLS) {
 		skb->tc_verd = CLR_TC_NCLS(skb->tc_verd);
 		D2PRINTK("(%p)tcf_action_exec: cleared TC_NCLS in %s out %s\n",skb,skb->input_dev?skb->input_dev->name:"xxx",skb->dev->name);
-		return TC_ACT_OK;
+		ret = TC_ACT_OK;
+		goto exec_done;
 	}
 	while ((a = act) != NULL) {
 repeat:
@@ -186,6 +187,11 @@
 	}
 
 exec_done:
+	if (skb->tc_classid > 0) {
+		res->classid = skb->tc_classid;
+		res->class = 0;
+		skb->tc_classid = 0;
+	}
 
 	return ret;
 }
diff -Nru a/net/sched/cls_api.c b/net/sched/cls_api.c
--- a/net/sched/cls_api.c	2004-10-18 14:56:19 -07:00
+++ b/net/sched/cls_api.c	2004-10-18 14:56:19 -07:00
@@ -139,7 +139,7 @@
 	struct tcf_proto_ops *tp_ops;
 	struct Qdisc_class_ops *cops;
 	unsigned long cl = 0;
-	unsigned long fh, fh_s;
+	unsigned long fh;
 	int err;
 
 	if (prio == 0) {
@@ -231,8 +231,12 @@
 		tp->classify = tp_ops->classify;
 		tp->classid = parent;
 		err = -EBUSY;
-		if (!try_module_get(tp_ops->owner) ||
-		    (err = tp_ops->init(tp)) != 0) {
+		if (!try_module_get(tp_ops->owner)) {
+			kfree(tp);
+			goto errout;
+		}
+		if ((err = tp_ops->init(tp)) != 0) {
+			module_put(tp_ops->owner);
 			kfree(tp);
 			goto errout;
 		}
@@ -245,7 +249,7 @@
 	} else if (tca[TCA_KIND-1] && rtattr_strcmp(tca[TCA_KIND-1], tp->ops->kind))
 		goto errout;
 
-	fh_s = fh = tp->ops->get(tp, t->tcm_handle);
+	fh = tp->ops->get(tp, t->tcm_handle);
 
 	if (fh == 0) {
 		if (n->nlmsg_type == RTM_DELTFILTER && t->tcm_handle == 0) {
@@ -253,7 +257,7 @@
 			*back = tp->next;
 			qdisc_unlock_tree(dev);
 
-			tfilter_notify(skb, n, tp, fh_s, RTM_DELTFILTER);
+			tfilter_notify(skb, n, tp, fh, RTM_DELTFILTER);
 			tcf_destroy(tp);
 			err = 0;
 			goto errout;
@@ -272,7 +276,7 @@
 		case RTM_DELTFILTER:
 			err = tp->ops->delete(tp, fh);
 			if (err == 0)
-				tfilter_notify(skb, n, tp, fh_s, RTM_DELTFILTER);
+				tfilter_notify(skb, n, tp, fh, RTM_DELTFILTER);
 			goto errout;
 		case RTM_GETTFILTER:
 			err = tfilter_notify(skb, n, tp, fh, RTM_NEWTFILTER);
diff -Nru a/net/sched/cls_fw.c b/net/sched/cls_fw.c
--- a/net/sched/cls_fw.c	2004-10-18 14:56:28 -07:00
+++ b/net/sched/cls_fw.c	2004-10-18 14:56:28 -07:00
@@ -102,7 +102,7 @@
 			}
 #endif
                                if (f->action) {
-                                       int pol_res = tcf_action_exec(skb, f->action);
+                                       int pol_res = tcf_action_exec(skb, f->action, res);
                                        if (pol_res >= 0)
                                                return pol_res;
                                } else
diff -Nru a/net/sched/cls_u32.c b/net/sched/cls_u32.c
--- a/net/sched/cls_u32.c	2004-10-18 14:56:27 -07:00
+++ b/net/sched/cls_u32.c	2004-10-18 14:56:27 -07:00
@@ -175,12 +175,7 @@
 #endif
 #ifdef CONFIG_NET_CLS_ACT
 				if (n->action) {
-					int pol_res = tcf_action_exec(skb, n->action);
-					if (skb->tc_classid > 0) {
-						res->classid = skb->tc_classid;
-						skb->tc_classid = 0;
-					}
-
+					int pol_res = tcf_action_exec(skb, n->action, res);
 					if (pol_res >= 0)
 						return pol_res;
 				} else
diff -Nru a/net/sched/estimator.c b/net/sched/estimator.c
--- a/net/sched/estimator.c	2004-10-18 14:55:55 -07:00
+++ b/net/sched/estimator.c	2004-10-18 14:55:55 -07:00
@@ -66,15 +66,11 @@
 
    * Minimal interval is HZ/4=250msec (it is the greatest common divisor
      for HZ=100 and HZ=1024 8)), maximal interval
-     is (HZ/4)*2^EST_MAX_INTERVAL = 8sec. Shorter intervals
+     is (HZ*2^EST_MAX_INTERVAL)/4 = 8sec. Shorter intervals
      are too expensive, longer ones can be implemented
      at user level painlessly.
  */
 
-#if (HZ%4) != 0
-#error Bad HZ value.
-#endif
-
 #define EST_MAX_INTERVAL	5
 
 struct qdisc_estimator
@@ -128,7 +124,7 @@
 		spin_unlock(e->stats_lock);
 	}
 
-	mod_timer(&elist[idx].timer, jiffies + ((HZ/4)<<idx));
+	mod_timer(&elist[idx].timer, jiffies + ((HZ<<idx)/4));
 	read_unlock(&est_lock);
 }
 
@@ -161,7 +157,7 @@
 	if (est->next == NULL) {
 		init_timer(&elist[est->interval].timer);
 		elist[est->interval].timer.data = est->interval;
-		elist[est->interval].timer.expires = jiffies + ((HZ/4)<<est->interval);
+		elist[est->interval].timer.expires = jiffies + ((HZ<<est->interval)/4);
 		elist[est->interval].timer.function = est_timer;
 		add_timer(&elist[est->interval].timer);
 	}
diff -Nru a/net/sched/gact.c b/net/sched/gact.c
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/net/sched/gact.c	2004-10-18 14:57:23 -07:00
@@ -0,0 +1,265 @@
+/*
+ * net/sched/gact.c	Generic actions
+ *
+ *		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.
+ *
+ * copyright 	Jamal Hadi Salim (2002-4)
+ *
+ */
+
+#include <asm/uaccess.h>
+#include <asm/system.h>
+#include <asm/bitops.h>
+#include <linux/config.h>
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/string.h>
+#include <linux/mm.h>
+#include <linux/socket.h>
+#include <linux/sockios.h>
+#include <linux/in.h>
+#include <linux/errno.h>
+#include <linux/interrupt.h>
+#include <linux/netdevice.h>
+#include <linux/skbuff.h>
+#include <linux/rtnetlink.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/proc_fs.h>
+#include <net/sock.h>
+#include <net/pkt_sched.h>
+#include <linux/tc_act/tc_gact.h>
+#include <net/tc_act/tc_gact.h>
+
+/* use generic hash table */
+#define MY_TAB_SIZE	16
+#define MY_TAB_MASK	15
+static u32 idx_gen;
+static struct tcf_gact *tcf_gact_ht[MY_TAB_SIZE];
+static rwlock_t gact_lock = RW_LOCK_UNLOCKED;
+
+/* ovewrride the defaults */
+#define tcf_st  tcf_gact
+#define tc_st  tc_gact
+#define tcf_t_lock   gact_lock
+#define tcf_ht tcf_gact_ht
+
+#define CONFIG_NET_ACT_INIT 1
+#include <net/pkt_act.h>
+
+#ifdef CONFIG_GACT_PROB
+typedef int (*g_rand)(struct tcf_gact *p);
+int
+gact_net_rand(struct tcf_gact *p) {
+	if (net_random()%p->pval)
+		return p->action;
+	return p->paction;
+}
+
+int
+gact_determ(struct tcf_gact *p) {
+	if (p->stats.packets%p->pval)
+		return p->action;
+	return p->paction;
+}
+
+
+g_rand gact_rand[MAX_RAND]= { NULL,gact_net_rand, gact_determ};
+
+#endif
+int
+tcf_gact_init(struct rtattr *rta, struct rtattr *est, struct tc_action *a,int ovr,int bind)
+{
+	struct rtattr *tb[TCA_GACT_MAX];
+	struct tc_gact *parm = NULL;
+#ifdef CONFIG_GACT_PROB
+	struct tc_gact_p *p_parm = NULL;
+#endif
+	struct tcf_gact *p = NULL;
+	int ret = 0;
+	int size = sizeof (*p);
+
+	if (rtattr_parse(tb, TCA_GACT_MAX, RTA_DATA(rta), RTA_PAYLOAD(rta)) < 0)
+		return -1;
+
+	if (NULL == a || NULL == tb[TCA_GACT_PARMS - 1]) {
+		printk("BUG: tcf_gact_init called with NULL params\n");
+		return -1;
+	}
+
+	parm = RTA_DATA(tb[TCA_GACT_PARMS - 1]);
+#ifdef CONFIG_GACT_PROB
+	if (NULL != tb[TCA_GACT_PROB - 1]) {
+		p_parm = RTA_DATA(tb[TCA_GACT_PROB - 1]);
+	}
+#endif
+
+	p = tcf_hash_check(parm, a, ovr, bind);
+
+	if (NULL == p) {
+		p = tcf_hash_create(parm,est,a,size,ovr, bind);
+
+		if (NULL == p) {
+			return -1;
+		} else {
+			p->refcnt = 1;
+			ret = 1;
+			goto override;
+		}
+	}
+
+	if (ovr) {
+override:
+		p->action = parm->action;
+#ifdef CONFIG_GACT_PROB
+		if (NULL != p_parm) {
+			p->paction = p_parm->paction;
+			p->pval = p_parm->pval;
+			p->ptype = p_parm->ptype;
+		} else {
+			p->paction = p->pval = p->ptype = 0;
+		}
+#endif
+	}
+
+	return ret;
+}
+
+int
+tcf_gact_cleanup(struct tc_action *a, int bind)
+{
+	struct tcf_gact *p;
+	p = PRIV(a,gact);
+	if (NULL != p)
+		return tcf_hash_release(p, bind);
+	return 0;
+}
+
+int
+tcf_gact(struct sk_buff **pskb, struct tc_action *a)
+{
+	struct tcf_gact *p;
+	struct sk_buff *skb = *pskb;
+	int action = TC_ACT_SHOT;
+
+	p = PRIV(a,gact);
+
+	if (NULL == p) {
+		if (net_ratelimit())
+			printk("BUG: tcf_gact called with NULL params\n");
+		return -1;
+	}
+
+	spin_lock(&p->lock);
+#ifdef CONFIG_GACT_PROB
+	if (p->ptype && NULL != gact_rand[p->ptype])
+		action = gact_rand[p->ptype](p);
+	else
+		action = p->action;
+#else
+	action = p->action;
+#endif
+	p->stats.bytes += skb->len;
+	p->stats.packets++;
+	if (TC_ACT_SHOT == action)
+		p->stats.drops++;
+	p->tm.lastuse = jiffies;
+	spin_unlock(&p->lock);
+
+	return action;
+}
+
+int
+tcf_gact_dump(struct sk_buff *skb, struct tc_action *a, int bind, int ref)
+{
+	unsigned char *b = skb->tail;
+	struct tc_gact opt;
+#ifdef CONFIG_GACT_PROB
+	struct tc_gact_p p_opt;
+#endif
+	struct tcf_gact *p;
+	struct tcf_t t;
+
+	p = PRIV(a,gact);
+	if (NULL == p) {
+		printk("BUG: tcf_gact_dump called with NULL params\n");
+		goto rtattr_failure;
+	}
+
+	opt.index = p->index;
+	opt.refcnt = p->refcnt - ref;
+	opt.bindcnt = p->bindcnt - bind;
+	opt.action = p->action;
+	RTA_PUT(skb, TCA_GACT_PARMS, sizeof (opt), &opt);
+#ifdef CONFIG_GACT_PROB
+	if (p->ptype) {
+		p_opt.paction = p->paction;
+		p_opt.pval = p->pval;
+		p_opt.ptype = p->ptype;
+		RTA_PUT(skb, TCA_GACT_PROB, sizeof (p_opt), &p_opt);
+	} 
+#endif
+	t.install = jiffies - p->tm.install;
+	t.lastuse = jiffies - p->tm.lastuse;
+	t.expires = p->tm.expires;
+	RTA_PUT(skb, TCA_GACT_TM, sizeof (t), &t);
+	return skb->len;
+
+      rtattr_failure:
+	skb_trim(skb, b - skb->data);
+	return -1;
+}
+
+int
+tcf_gact_stats(struct sk_buff *skb, struct tc_action *a)
+{
+	struct tcf_gact *p;
+	p = PRIV(a,gact);
+	if (NULL != p)
+		return qdisc_copy_stats(skb, &p->stats,p->stats_lock);
+
+	return 1;
+}
+
+struct tc_action_ops act_gact_ops = {
+	.next		=	NULL,
+	.kind		=	"gact",
+	.type		=	TCA_ACT_GACT,
+	.capab		=	TCA_CAP_NONE,
+	.owner		=	THIS_MODULE,
+	.act		=	tcf_gact,
+	.get_stats	=	tcf_gact_stats,
+	.dump		=	tcf_gact_dump,
+	.cleanup	=	tcf_gact_cleanup,
+	.lookup		=	tcf_hash_search,
+	.init		=	tcf_gact_init,
+	.walk		=	tcf_generic_walker
+};
+
+MODULE_AUTHOR("Jamal Hadi Salim(2002-4)");
+MODULE_DESCRIPTION("Generic Classifier actions");
+MODULE_LICENSE("GPL");
+
+static int __init
+gact_init_module(void)
+{
+#ifdef CONFIG_GACT_PROB
+	printk("GACT probability on\n");
+#else
+	printk("GACT probability NOT on\n");
+#endif
+	return tcf_register_action(&act_gact_ops);
+}
+
+static void __exit
+gact_cleanup_module(void)
+{
+	tcf_unregister_action(&act_gact_ops);
+}
+
+module_init(gact_init_module);
+module_exit(gact_cleanup_module);
diff -Nru a/net/sched/sch_api.c b/net/sched/sch_api.c
--- a/net/sched/sch_api.c	2004-10-18 14:56:29 -07:00
+++ b/net/sched/sch_api.c	2004-10-18 14:56:29 -07:00
@@ -371,6 +371,8 @@
 			unsigned long cl = cops->get(parent, classid);
 			if (cl) {
 				err = cops->graft(parent, cl, new, old);
+				if (new)
+					new->parent = classid;
 				cops->put(parent, cl);
 			}
 		}
@@ -389,7 +391,8 @@
 {
 	int err;
 	struct rtattr *kind = tca[TCA_KIND-1];
-	struct Qdisc *sch = NULL;
+	void *p = NULL;
+	struct Qdisc *sch;
 	struct Qdisc_ops *ops;
 	int size;
 
@@ -406,21 +409,22 @@
 	err = -EINVAL;
 	if (ops == NULL)
 		goto err_out;
-
-	size = sizeof(*sch) + ops->priv_size;
-
-	sch = kmalloc(size, GFP_KERNEL);
-	err = -ENOBUFS;
-	if (!sch)
+	err = -EBUSY;
+	if (!try_module_get(ops->owner))
 		goto err_out;
 
-	/* Grrr... Resolve race condition with module unload */
-
-	err = -EINVAL;
-	if (ops != qdisc_lookup_ops(kind))
-		goto err_out;
+	/* ensure that the Qdisc and the private data are 32-byte aligned */
+	size = ((sizeof(*sch) + QDISC_ALIGN_CONST) & ~QDISC_ALIGN_CONST);
+	size += ops->priv_size + QDISC_ALIGN_CONST;
 
-	memset(sch, 0, size);
+	p = kmalloc(size, GFP_KERNEL);
+	err = -ENOBUFS;
+	if (!p)
+		goto err_out2;
+	memset(p, 0, size);
+	sch = (struct Qdisc *)(((unsigned long)p + QDISC_ALIGN_CONST)
+	                       & ~QDISC_ALIGN_CONST);
+	sch->padded = (char *)sch - (char *)p;
 
 	INIT_LIST_HEAD(&sch->list);
 	skb_queue_head_init(&sch->q);
@@ -439,7 +443,7 @@
 		handle = qdisc_alloc_handle(dev);
 		err = -ENOMEM;
 		if (handle == 0)
-			goto err_out;
+			goto err_out3;
 	}
 
 	if (handle == TC_H_INGRESS)
@@ -447,10 +451,6 @@
         else
                 sch->handle = handle;
 
-	err = -EBUSY;
-	if (!try_module_get(ops->owner))
-		goto err_out;
-
 	/* enqueue is accessed locklessly - make sure it's visible
 	 * before we set a netdevice's qdisc pointer to sch */
 	smp_wmb();
@@ -466,12 +466,14 @@
 #endif
 		return sch;
 	}
+err_out3:
+	dev_put(dev);
+err_out2:
 	module_put(ops->owner);
-
 err_out:
 	*errp = err;
-	if (sch)
-		kfree(sch);
+	if (p)
+		kfree(p);
 	return NULL;
 }
 
@@ -821,7 +823,7 @@
 				q_idx++;
 				continue;
 			}
-			if (tc_fill_qdisc(skb, q, 0, NETLINK_CB(cb->skb).pid,
+			if (tc_fill_qdisc(skb, q, q->parent, NETLINK_CB(cb->skb).pid,
 					  cb->nlh->nlmsg_seq, NLM_F_MULTI, RTM_NEWQDISC) <= 0) {
 				read_unlock_bh(&qdisc_tree_lock);
 				goto done;
diff -Nru a/net/sched/sch_atm.c b/net/sched/sch_atm.c
--- a/net/sched/sch_atm.c	2004-10-18 14:56:29 -07:00
+++ b/net/sched/sch_atm.c	2004-10-18 14:56:29 -07:00
@@ -573,7 +573,6 @@
 	struct atm_qdisc_data *p = PRIV(sch);
 
 	DPRINTK("atm_tc_init(sch %p,[qdisc %p],opt %p)\n",sch,p,opt);
-	memset(p,0,sizeof(*p));
 	p->flows = &p->link;
 	if(!(p->link.q = qdisc_create_dflt(sch->dev,&pfifo_qdisc_ops)))
 		p->link.q = &noop_qdisc;
@@ -715,3 +714,4 @@
 
 module_init(atm_init)
 module_exit(atm_exit)
+MODULE_LICENSE("GPL");
diff -Nru a/net/sched/sch_cbq.c b/net/sched/sch_cbq.c
--- a/net/sched/sch_cbq.c	2004-10-18 14:55:54 -07:00
+++ b/net/sched/sch_cbq.c	2004-10-18 14:55:54 -07:00
@@ -1675,7 +1675,6 @@
 	cl->xstats.undertime = 0;
 	if (!PSCHED_IS_PASTPERFECT(cl->undertime))
 		cl->xstats.undertime = PSCHED_TDIFF(cl->undertime, q->now);
-	q->link.xstats.avgidle = q->link.avgidle;
 	if (cbq_copy_xstats(skb, &cl->xstats)) {
 		spin_unlock_bh(&sch->dev->queue_lock);
 		goto rtattr_failure;
@@ -1746,15 +1745,18 @@
 	}
 }
 
-static void cbq_destroy_class(struct cbq_class *cl)
+static void cbq_destroy_class(struct Qdisc *sch, struct cbq_class *cl)
 {
+	struct cbq_sched_data *q = qdisc_priv(sch);
+
 	cbq_destroy_filters(cl);
 	qdisc_destroy(cl->q);
 	qdisc_put_rtab(cl->R_tab);
 #ifdef CONFIG_NET_ESTIMATOR
 	qdisc_kill_estimator(&cl->stats);
 #endif
-	kfree(cl);
+	if (cl != &q->link)
+		kfree(cl);
 }
 
 static void
@@ -1767,22 +1769,15 @@
 #ifdef CONFIG_NET_CLS_POLICE
 	q->rx_class = NULL;
 #endif
-	for (h = 0; h < 16; h++) {
-		for (cl = q->classes[h]; cl; cl = cl->next)
-			cbq_destroy_filters(cl);
-	}
 
 	for (h = 0; h < 16; h++) {
 		struct cbq_class *next;
 
 		for (cl = q->classes[h]; cl; cl = next) {
 			next = cl->next;
-			if (cl != &q->link)
-				cbq_destroy_class(cl);
+			cbq_destroy_class(sch, cl);
 		}
 	}
-
-	qdisc_put_rtab(q->link.R_tab);
 }
 
 static void cbq_put(struct Qdisc *sch, unsigned long arg)
@@ -1799,7 +1794,7 @@
 		spin_unlock_bh(&sch->dev->queue_lock);
 #endif
 
-		cbq_destroy_class(cl);
+		cbq_destroy_class(sch, cl);
 	}
 }
 
@@ -2035,7 +2030,7 @@
 	sch_tree_unlock(sch);
 
 	if (--cl->refcnt == 0)
-		cbq_destroy_class(cl);
+		cbq_destroy_class(sch, cl);
 
 	return 0;
 }
diff -Nru a/net/sched/sch_dsmark.c b/net/sched/sch_dsmark.c
--- a/net/sched/sch_dsmark.c	2004-10-18 14:56:14 -07:00
+++ b/net/sched/sch_dsmark.c	2004-10-18 14:56:14 -07:00
@@ -331,8 +331,6 @@
 	    !tb[TCA_DSMARK_INDICES-1] ||
 	    RTA_PAYLOAD(tb[TCA_DSMARK_INDICES-1]) < sizeof(__u16))
                 return -EINVAL;
-	memset(p,0,sizeof(*p));
-	p->filter_list = NULL;
 	p->indices = *(__u16 *) RTA_DATA(tb[TCA_DSMARK_INDICES-1]);
 	if (!p->indices)
 		return -EINVAL;
diff -Nru a/net/sched/sch_generic.c b/net/sched/sch_generic.c
--- a/net/sched/sch_generic.c	2004-10-18 14:55:54 -07:00
+++ b/net/sched/sch_generic.c	2004-10-18 14:55:54 -07:00
@@ -97,46 +97,71 @@
 
 	/* Dequeue packet */
 	if ((skb = q->dequeue(q)) != NULL) {
-		if (spin_trylock(&dev->xmit_lock)) {
+		unsigned nolock = (dev->features & NETIF_F_LLTX);
+		/*
+		 * When the driver has LLTX set it does its own locking
+		 * in start_xmit. No need to add additional overhead by
+		 * locking again. These checks are worth it because
+		 * even uncongested locks can be quite expensive.
+		 * The driver can do trylock like here too, in case
+		 * of lock congestion it should return -1 and the packet
+		 * will be requeued.
+		 */
+		if (!nolock) {
+			if (!spin_trylock(&dev->xmit_lock)) {
+			collision:
+				/* So, someone grabbed the driver. */
+				
+				/* It may be transient configuration error,
+				   when hard_start_xmit() recurses. We detect
+				   it by checking xmit owner and drop the
+				   packet when deadloop is detected.
+				*/
+				if (dev->xmit_lock_owner == smp_processor_id()) {
+					kfree_skb(skb);
+					if (net_ratelimit())
+						printk(KERN_DEBUG "Dead loop on netdevice %s, fix it urgently!\n", dev->name);
+					return -1;
+				}
+				__get_cpu_var(netdev_rx_stat).cpu_collision++;
+				goto requeue;
+			}
 			/* Remember that the driver is grabbed by us. */
 			dev->xmit_lock_owner = smp_processor_id();
-
+		}
+		
+		{
 			/* And release queue */
 			spin_unlock(&dev->queue_lock);
 
 			if (!netif_queue_stopped(dev)) {
+				int ret;
 				if (netdev_nit)
 					dev_queue_xmit_nit(skb, dev);
 
-				if (dev->hard_start_xmit(skb, dev) == 0) {
-					dev->xmit_lock_owner = -1;
-					spin_unlock(&dev->xmit_lock);
-
+				ret = dev->hard_start_xmit(skb, dev);
+				if (ret == NETDEV_TX_OK) { 
+					if (!nolock) {
+						dev->xmit_lock_owner = -1;
+						spin_unlock(&dev->xmit_lock);
+					}
 					spin_lock(&dev->queue_lock);
 					return -1;
 				}
+				if (ret == NETDEV_TX_LOCKED && nolock) {
+					spin_lock(&dev->queue_lock);
+					goto collision; 
+				}
 			}
 
+			/* NETDEV_TX_BUSY - we need to requeue */
 			/* Release the driver */
-			dev->xmit_lock_owner = -1;
-			spin_unlock(&dev->xmit_lock);
+			if (!nolock) { 
+				dev->xmit_lock_owner = -1;
+				spin_unlock(&dev->xmit_lock);
+			} 
 			spin_lock(&dev->queue_lock);
 			q = dev->qdisc;
-		} else {
-			/* So, someone grabbed the driver. */
-
-			/* It may be transient configuration error,
-			   when hard_start_xmit() recurses. We detect
-			   it by checking xmit owner and drop the
-			   packet when deadloop is detected.
-			 */
-			if (dev->xmit_lock_owner == smp_processor_id()) {
-				kfree_skb(skb);
-				if (net_ratelimit())
-					printk(KERN_DEBUG "Dead loop on netdevice %s, fix it urgently!\n", dev->name);
-				return -1;
-			}
-			__get_cpu_var(netdev_rx_stat).cpu_collision++;
 		}
 
 		/* Device kicked us out :(
@@ -149,6 +174,7 @@
 		   3. device is buggy (ppp)
 		 */
 
+requeue:
 		q->ops->requeue(skb, q);
 		netif_schedule(dev);
 		return 1;
@@ -415,6 +441,7 @@
 	if (!ops->init || ops->init(sch, NULL) == 0)
 		return sch;
 
+	dev_put(dev);
 	kfree(p);
 	return NULL;
 }
diff -Nru a/net/sched/sch_hfsc.c b/net/sched/sch_hfsc.c
--- a/net/sched/sch_hfsc.c	2004-10-18 14:55:55 -07:00
+++ b/net/sched/sch_hfsc.c	2004-10-18 14:55:55 -07:00
@@ -62,6 +62,7 @@
 #include <linux/slab.h>
 #include <linux/timer.h>
 #include <linux/list.h>
+#include <linux/rbtree.h>
 #include <linux/init.h>
 #include <linux/netdevice.h>
 #include <linux/rtnetlink.h>
@@ -133,9 +134,11 @@
 	struct list_head children;	/* child classes */
 	struct Qdisc	*qdisc;		/* leaf qdisc */
 
-	struct list_head actlist;	/* active children list */
-	struct list_head alist;		/* active children list member */
-	struct list_head ellist;	/* eligible list member */
+	struct rb_node el_node;		/* qdisc's eligible tree member */
+	struct rb_root vt_tree;		/* active children sorted by cl_vt */
+	struct rb_node vt_node;		/* parent's vt_tree member */
+	struct rb_root cf_tree;		/* active children sorted by cl_f */
+	struct rb_node cf_node;		/* parent's cf_heap member */
 	struct list_head hlist;		/* hash list member */
 	struct list_head dlist;		/* drop list member */
 
@@ -161,6 +164,9 @@
 					   adjustment */
 	u64	cl_vtoff;		/* inter-period cumulative vt offset */
 	u64	cl_cvtmax;		/* max child's vt in the last period */
+	u64	cl_cvtoff;		/* cumulative cvtmax of all periods */
+	u64	cl_pcvtoff;		/* parent's cvtoff at initalization
+					   time */
 
 	struct internal_sc cl_rsc;	/* internal real-time service curve */
 	struct internal_sc cl_fsc;	/* internal fair service curve */
@@ -183,7 +189,7 @@
 	u16	defcls;				/* default class id */
 	struct hfsc_class root;			/* root class */
 	struct list_head clhash[HFSC_HSIZE];	/* class hash */
-	struct list_head eligible;		/* eligible list */
+	struct rb_root eligible;		/* eligible tree */
 	struct list_head droplist;		/* active leaf class list (for
 						   dropping) */
 	struct sk_buff_head requeue;		/* requeued packet */
@@ -219,82 +225,51 @@
 
 
 /*
- * eligible list holds backlogged classes being sorted by their eligible times.
- * there is one eligible list per hfsc instance.
+ * eligible tree holds backlogged classes being sorted by their eligible times.
+ * there is one eligible tree per hfsc instance.
  */
 
 static void
-ellist_insert(struct hfsc_class *cl)
+eltree_insert(struct hfsc_class *cl)
 {
-	struct list_head *head = &cl->sched->eligible;
-	struct hfsc_class *p;
-
-	/* check the last entry first */
-	if (list_empty(head) ||
-	    ((p = list_entry(head->prev, struct hfsc_class, ellist)) &&
-	     p->cl_e <= cl->cl_e)) {
-		list_add_tail(&cl->ellist, head);
-		return;
-	}
-
-	list_for_each_entry(p, head, ellist) {
-		if (cl->cl_e < p->cl_e) {
-			/* insert cl before p */
-			list_add_tail(&cl->ellist, &p->ellist);
-			return;
-		}
+	struct rb_node **p = &cl->sched->eligible.rb_node;
+	struct rb_node *parent = NULL;
+	struct hfsc_class *cl1;
+
+	while (*p != NULL) {
+		parent = *p;
+		cl1 = rb_entry(parent, struct hfsc_class, el_node);
+		if (cl->cl_e >= cl1->cl_e)
+			p = &parent->rb_right;
+		else
+			p = &parent->rb_left;
 	}
-	ASSERT(0); /* should not reach here */
+	rb_link_node(&cl->el_node, parent, p);
+	rb_insert_color(&cl->el_node, &cl->sched->eligible);
 }
 
 static inline void
-ellist_remove(struct hfsc_class *cl)
+eltree_remove(struct hfsc_class *cl)
 {
-	list_del(&cl->ellist);
+	rb_erase(&cl->el_node, &cl->sched->eligible);
 }
 
-static void
-ellist_update(struct hfsc_class *cl)
+static inline void
+eltree_update(struct hfsc_class *cl)
 {
-	struct list_head *head = &cl->sched->eligible;
-	struct hfsc_class *p, *last;
-
-	/*
-	 * the eligible time of a class increases monotonically.
-	 * if the next entry has a larger eligible time, nothing to do.
-	 */
-	if (cl->ellist.next == head ||
-	    ((p = list_entry(cl->ellist.next, struct hfsc_class, ellist)) &&
-	     cl->cl_e <= p->cl_e))
-		return;
-
-	/* check the last entry */
-	last = list_entry(head->prev, struct hfsc_class, ellist);
-	if (last->cl_e <= cl->cl_e) {
-		list_move_tail(&cl->ellist, head);
-		return;
-	}
-
-	/*
-	 * the new position must be between the next entry
-	 * and the last entry
-	 */
-	list_for_each_entry_continue(p, head, ellist) {
-		if (cl->cl_e < p->cl_e) {
-			list_move_tail(&cl->ellist, &p->ellist);
-			return;
-		}
-	}
-	ASSERT(0); /* should not reach here */
+	eltree_remove(cl);
+	eltree_insert(cl);
 }
 
 /* find the class with the minimum deadline among the eligible classes */
 static inline struct hfsc_class *
-ellist_get_mindl(struct list_head *head, u64 cur_time)
+eltree_get_mindl(struct hfsc_sched *q, u64 cur_time)
 {
 	struct hfsc_class *p, *cl = NULL;
+	struct rb_node *n;
 
-	list_for_each_entry(p, head, ellist) {
+	for (n = rb_first(&q->eligible); n != NULL; n = rb_next(n)) {
+		p = rb_entry(n, struct hfsc_class, el_node);
 		if (p->cl_e > cur_time)
 			break;
 		if (cl == NULL || p->cl_d < cl->cl_d)
@@ -305,92 +280,62 @@
 
 /* find the class with minimum eligible time among the eligible classes */
 static inline struct hfsc_class *
-ellist_get_minel(struct list_head *head)
+eltree_get_minel(struct hfsc_sched *q)
 {
-	if (list_empty(head))
+	struct rb_node *n;
+	
+	n = rb_first(&q->eligible);
+	if (n == NULL)
 		return NULL;
-	return list_entry(head->next, struct hfsc_class, ellist);
+	return rb_entry(n, struct hfsc_class, el_node);
 }
 
 /*
- * active children list holds backlogged child classes being sorted
- * by their virtual time. each intermediate class has one active
- * children list.
+ * vttree holds holds backlogged child classes being sorted by their virtual
+ * time. each intermediate class has one vttree.
  */
 static void
-actlist_insert(struct hfsc_class *cl)
+vttree_insert(struct hfsc_class *cl)
 {
-	struct list_head *head = &cl->cl_parent->actlist;
-	struct hfsc_class *p;
-
-	/* check the last entry first */
-	if (list_empty(head) ||
-	    ((p = list_entry(head->prev, struct hfsc_class, alist)) &&
-	     p->cl_vt <= cl->cl_vt)) {
-		list_add_tail(&cl->alist, head);
-		return;
-	}
-
-	list_for_each_entry(p, head, alist) {
-		if (cl->cl_vt < p->cl_vt) {
-			/* insert cl before p */
-			list_add_tail(&cl->alist, &p->alist);
-			return;
-		}
+	struct rb_node **p = &cl->cl_parent->vt_tree.rb_node;
+	struct rb_node *parent = NULL;
+	struct hfsc_class *cl1;
+
+	while (*p != NULL) {
+		parent = *p;
+		cl1 = rb_entry(parent, struct hfsc_class, vt_node);
+		if (cl->cl_vt >= cl1->cl_vt)
+			p = &parent->rb_right;
+		else
+			p = &parent->rb_left;
 	}
-	ASSERT(0); /* should not reach here */
+	rb_link_node(&cl->vt_node, parent, p);
+	rb_insert_color(&cl->vt_node, &cl->cl_parent->vt_tree);
 }
 
 static inline void
-actlist_remove(struct hfsc_class *cl)
+vttree_remove(struct hfsc_class *cl)
 {
-	list_del(&cl->alist);
+	rb_erase(&cl->vt_node, &cl->cl_parent->vt_tree);
 }
 
-static void
-actlist_update(struct hfsc_class *cl)
+static inline void
+vttree_update(struct hfsc_class *cl)
 {
-	struct list_head *head = &cl->cl_parent->actlist;
-	struct hfsc_class *p, *last;
-
-	/*
-	 * the virtual time of a class increases monotonically.
-	 * if the next entry has a larger virtual time, nothing to do.
-	 */
-	if (cl->alist.next == head ||
-	    ((p = list_entry(cl->alist.next, struct hfsc_class, alist)) &&
-	     cl->cl_vt <= p->cl_vt))
-		return;
-
-	/* check the last entry */
-	last = list_entry(head->prev, struct hfsc_class, alist);
-	if (last->cl_vt <= cl->cl_vt) {
-		list_move_tail(&cl->alist, head);
-		return;
-	}
-
-	/*
-	 * the new position must be between the next entry
-	 * and the last entry
-	 */
-	list_for_each_entry_continue(p, head, alist) {
-		if (cl->cl_vt < p->cl_vt) {
-			list_move_tail(&cl->alist, &p->alist);
-			return;
-		}
-	}
-	ASSERT(0); /* should not reach here */
+	vttree_remove(cl);
+	vttree_insert(cl);
 }
 
 static inline struct hfsc_class *
-actlist_firstfit(struct hfsc_class *cl, u64 cur_time)
+vttree_firstfit(struct hfsc_class *cl, u64 cur_time)
 {
 	struct hfsc_class *p;
+	struct rb_node *n;
 
-	list_for_each_entry(p, &cl->actlist, alist) {
-		if (p->cl_f <= cur_time) {
+	for (n = rb_first(&cl->vt_tree); n != NULL; n = rb_next(n)) {
+		p = rb_entry(n, struct hfsc_class, vt_node);
+		if (p->cl_f <= cur_time)
 			return p;
-		}
 	}
 	return NULL;
 }
@@ -399,14 +344,14 @@
  * get the leaf class with the minimum vt in the hierarchy
  */
 static struct hfsc_class *
-actlist_get_minvt(struct hfsc_class *cl, u64 cur_time)
+vttree_get_minvt(struct hfsc_class *cl, u64 cur_time)
 {
 	/* if root-class's cfmin is bigger than cur_time nothing to do */
 	if (cl->cl_cfmin > cur_time)
 		return NULL;
 
 	while (cl->level > 0) {
-		cl = actlist_firstfit(cl, cur_time);
+		cl = vttree_firstfit(cl, cur_time);
 		if (cl == NULL)
 			return NULL;
 		/*
@@ -418,6 +363,38 @@
 	return cl;
 }
 
+static void
+cftree_insert(struct hfsc_class *cl)
+{
+	struct rb_node **p = &cl->cl_parent->cf_tree.rb_node;
+	struct rb_node *parent = NULL;
+	struct hfsc_class *cl1;
+
+	while (*p != NULL) {
+		parent = *p;
+		cl1 = rb_entry(parent, struct hfsc_class, cf_node);
+		if (cl->cl_f >= cl1->cl_f)
+			p = &parent->rb_right;
+		else
+			p = &parent->rb_left;
+	}
+	rb_link_node(&cl->cf_node, parent, p);
+	rb_insert_color(&cl->cf_node, &cl->cl_parent->cf_tree);
+}
+
+static inline void
+cftree_remove(struct hfsc_class *cl)
+{
+	rb_erase(&cl->cf_node, &cl->cl_parent->cf_tree);
+}
+
+static inline void
+cftree_update(struct hfsc_class *cl)
+{
+	cftree_remove(cl);
+	cftree_insert(cl);
+}
+
 /*
  * service curve support functions
  *
@@ -711,7 +688,7 @@
 	cl->cl_e = rtsc_y2x(&cl->cl_eligible, cl->cl_cumul);
 	cl->cl_d = rtsc_y2x(&cl->cl_deadline, cl->cl_cumul + next_len);
 
-	ellist_insert(cl);
+	eltree_insert(cl);
 }
 
 static void
@@ -720,7 +697,7 @@
 	cl->cl_e = rtsc_y2x(&cl->cl_eligible, cl->cl_cumul);
 	cl->cl_d = rtsc_y2x(&cl->cl_deadline, cl->cl_cumul + next_len);
 
-	ellist_update(cl);
+	eltree_update(cl);
 }
 
 static inline void
@@ -729,32 +706,25 @@
 	cl->cl_d = rtsc_y2x(&cl->cl_deadline, cl->cl_cumul + next_len);
 }
 
-static void
+static inline void
 update_cfmin(struct hfsc_class *cl)
 {
+	struct rb_node *n = rb_first(&cl->cf_tree);
 	struct hfsc_class *p;
-	u64 cfmin;
 
-	if (list_empty(&cl->actlist)) {
+	if (n == NULL) {
 		cl->cl_cfmin = 0;
 		return;
 	}
-	cfmin = HT_INFINITY;
-	list_for_each_entry(p, &cl->actlist, alist) {
-		if (p->cl_f == 0) {
-			cl->cl_cfmin = 0;
-			return;
-		}
-		if (p->cl_f < cfmin)
-			cfmin = p->cl_f;
-	}
-	cl->cl_cfmin = cfmin;
+	p = rb_entry(n, struct hfsc_class, cf_node);
+	cl->cl_cfmin = p->cl_f;
 }
 
 static void
 init_vf(struct hfsc_class *cl, unsigned int len)
 {
-	struct hfsc_class *max_cl, *p;
+	struct hfsc_class *max_cl;
+	struct rb_node *n;
 	u64 vt, f, cur_time;
 	int go_active;
 
@@ -767,9 +737,9 @@
 			go_active = 0;
 
 		if (go_active) {
-			if (!list_empty(&cl->cl_parent->actlist)) {
-				max_cl = list_entry(cl->cl_parent->actlist.prev,
-				                    struct hfsc_class, alist);
+			n = rb_last(&cl->cl_parent->vt_tree);
+			if (n != NULL) {
+				max_cl = rb_entry(n, struct hfsc_class,vt_node);
 				/*
 				 * set vt to the average of the min and max
 				 * classes.  if the parent's period didn't
@@ -785,19 +755,20 @@
 			} else {
 				/*
 				 * first child for a new parent backlog period.
-				 * add parent's cvtmax to vtoff of children
-				 * to make a new vt (vtoff + vt) larger than
-				 * the vt in the last period for all children.
+				 * add parent's cvtmax to cvtoff to make a new
+				 * vt (vtoff + vt) larger than the vt in the
+				 * last period for all children.
 				 */
 				vt = cl->cl_parent->cl_cvtmax;
-				list_for_each_entry(p, &cl->cl_parent->children,
-				                                       siblings)
-					p->cl_vtoff += vt;
-				cl->cl_vt = 0;
+				cl->cl_parent->cl_cvtoff += vt;
 				cl->cl_parent->cl_cvtmax = 0;
 				cl->cl_parent->cl_cvtmin = 0;
+				cl->cl_vt = 0;
 			}
 
+			cl->cl_vtoff = cl->cl_parent->cl_cvtoff -
+							cl->cl_pcvtoff;
+
 			/* update the virtual curve */
 			vt = cl->cl_vt + cl->cl_vtoff;
 			rtsc_min(&cl->cl_virtual, &cl->cl_fsc, vt,
@@ -814,7 +785,8 @@
 				cl->cl_parentperiod++;
 			cl->cl_f = 0;
 
-			actlist_insert(cl);
+			vttree_insert(cl);
+			cftree_insert(cl);
 
 			if (cl->cl_flags & HFSC_USC) {
 				/* class has upper limit curve */
@@ -834,6 +806,7 @@
 		f = max(cl->cl_myf, cl->cl_cfmin);
 		if (f != cl->cl_f) {
 			cl->cl_f = f;
+			cftree_update(cl);
 			update_cfmin(cl->cl_parent);
 		}
 	}
@@ -866,9 +839,10 @@
 			if (cl->cl_vt > cl->cl_parent->cl_cvtmax)
 				cl->cl_parent->cl_cvtmax = cl->cl_vt;
 
-			/* remove this class from the vt list */
-			actlist_remove(cl);
+			/* remove this class from the vt tree */
+			vttree_remove(cl);
 
+			cftree_remove(cl);
 			update_cfmin(cl->cl_parent);
 
 			continue;
@@ -890,8 +864,8 @@
 			cl->cl_vt = cl->cl_parent->cl_cvtmin;
 		}
 
-		/* update the vt list */
-		actlist_update(cl);
+		/* update the vt tree */
+		vttree_update(cl);
 
 		if (cl->cl_flags & HFSC_USC) {
 			cl->cl_myf = cl->cl_myfadj + rtsc_y2x(&cl->cl_ulimit,
@@ -921,6 +895,7 @@
 		f = max(cl->cl_myf, cl->cl_cfmin);
 		if (f != cl->cl_f) {
 			cl->cl_f = f;
+			cftree_update(cl);
 			update_cfmin(cl->cl_parent);
 		}
 	}
@@ -941,13 +916,13 @@
 set_passive(struct hfsc_class *cl)
 {
 	if (cl->cl_flags & HFSC_RSC)
-		ellist_remove(cl);
+		eltree_remove(cl);
 
 	list_del(&cl->dlist);
 
 	/*
-	 * actlist is now handled in update_vf() so that update_vf(cl, 0, 0)
-	 * needs to be called explicitly to remove a class from actlist
+	 * vttree is now handled in update_vf() so that update_vf(cl, 0, 0)
+	 * needs to be called explicitly to remove a class from vttree.
 	 */
 }
 
@@ -1171,7 +1146,8 @@
 		cl->qdisc = &noop_qdisc;
 	cl->stats_lock = &sch->dev->queue_lock;
 	INIT_LIST_HEAD(&cl->children);
-	INIT_LIST_HEAD(&cl->actlist);
+	cl->vt_tree = RB_ROOT;
+	cl->cf_tree = RB_ROOT;
 
 	sch_tree_lock(sch);
 	list_add_tail(&cl->hlist, &q->clhash[hfsc_hash(classid)]);
@@ -1179,6 +1155,7 @@
 	if (parent->level == 0)
 		hfsc_purge_queue(sch, parent);
 	hfsc_adjust_levels(parent);
+	cl->cl_pcvtoff = parent->cl_cvtoff;
 	sch_tree_unlock(sch);
 
 #ifdef CONFIG_NET_ESTIMATOR
@@ -1528,7 +1505,7 @@
 	u64 next_time = 0;
 	long delay;
 
-	if ((cl = ellist_get_minel(&q->eligible)) != NULL)
+	if ((cl = eltree_get_minel(q)) != NULL)
 		next_time = cl->cl_e;
 	if (q->root.cl_cfmin != 0) {
 		if (next_time == 0 || next_time > q->root.cl_cfmin)
@@ -1553,13 +1530,12 @@
 		return -EINVAL;
 	qopt = RTA_DATA(opt);
 
-	memset(q, 0, sizeof(struct hfsc_sched));
 	sch->stats_lock = &sch->dev->queue_lock;
 
 	q->defcls = qopt->defcls;
 	for (i = 0; i < HFSC_HSIZE; i++)
 		INIT_LIST_HEAD(&q->clhash[i]);
-	INIT_LIST_HEAD(&q->eligible);
+	q->eligible = RB_ROOT;
 	INIT_LIST_HEAD(&q->droplist);
 	skb_queue_head_init(&q->requeue);
 
@@ -1571,7 +1547,8 @@
 		q->root.qdisc = &noop_qdisc;
 	q->root.stats_lock = &sch->dev->queue_lock;
 	INIT_LIST_HEAD(&q->root.children);
-	INIT_LIST_HEAD(&q->root.actlist);
+	q->root.vt_tree = RB_ROOT;
+	q->root.cf_tree = RB_ROOT;
 
 	list_add(&q->root.hlist, &q->clhash[hfsc_hash(q->root.classid)]);
 
@@ -1611,6 +1588,8 @@
 	cl->cl_vtoff        = 0;
 	cl->cl_cvtmin       = 0;
 	cl->cl_cvtmax       = 0;
+	cl->cl_cvtoff       = 0;
+	cl->cl_pcvtoff      = 0;
 	cl->cl_vtperiod     = 0;
 	cl->cl_parentperiod = 0;
 	cl->cl_f            = 0;
@@ -1618,7 +1597,9 @@
 	cl->cl_myfadj       = 0;
 	cl->cl_cfmin        = 0;
 	cl->cl_nactive      = 0;
-	INIT_LIST_HEAD(&cl->actlist);
+
+	cl->vt_tree = RB_ROOT;
+	cl->cf_tree = RB_ROOT;
 	qdisc_reset(cl->qdisc);
 
 	if (cl->cl_flags & HFSC_RSC)
@@ -1641,7 +1622,7 @@
 			hfsc_reset_class(cl);
 	}
 	__skb_queue_purge(&q->requeue);
-	INIT_LIST_HEAD(&q->eligible);
+	q->eligible = RB_ROOT;
 	INIT_LIST_HEAD(&q->droplist);
 	del_timer(&q->wd_timer);
 	sch->flags &= ~TCQ_F_THROTTLED;
@@ -1749,14 +1730,14 @@
 	 * find the class with the minimum deadline among
 	 * the eligible classes.
 	 */
-	if ((cl = ellist_get_mindl(&q->eligible, cur_time)) != NULL) {
+	if ((cl = eltree_get_mindl(q, cur_time)) != NULL) {
 		realtime = 1;
 	} else {
 		/*
 		 * use link-sharing criteria
 		 * get the class with the minimum vt in the hierarchy
 		 */
-		cl = actlist_get_minvt(&q->root, cur_time);
+		cl = vttree_get_minvt(&q->root, cur_time);
 		if (cl == NULL) {
 			sch->stats.overlimits++;
 			hfsc_schedule_watchdog(sch, cur_time);
diff -Nru a/net/sched/sch_htb.c b/net/sched/sch_htb.c
--- a/net/sched/sch_htb.c	2004-10-18 14:56:33 -07:00
+++ b/net/sched/sch_htb.c	2004-10-18 14:56:33 -07:00
@@ -1277,7 +1277,6 @@
 				HTB_VER >> 16,HTB_VER & 0xffff,gopt->version);
 		return -EINVAL;
 	}
-	memset(q,0,sizeof(*q));
 	q->debug = gopt->debug;
 	HTB_DBG(0,1,"htb_init sch=%p handle=%X r2q=%d\n",sch,sch->handle,gopt->rate2quantum);
 
diff -Nru a/net/sched/sch_ingress.c b/net/sched/sch_ingress.c
--- a/net/sched/sch_ingress.c	2004-10-18 14:57:20 -07:00
+++ b/net/sched/sch_ingress.c	2004-10-18 14:57:20 -07:00
@@ -283,21 +283,18 @@
 #ifndef CONFIG_NET_CLS_ACT
 #ifndef CONFIG_NETFILTER
 	printk("You MUST compile classifier actions into the kernel\n");
-	goto error;
+	return -EINVAL;
 #else
 	printk("Ingress scheduler: Classifier actions prefered over netfilter\n");
 #endif
 #endif
                                                                                 
-	if (NULL == p)
-		goto error;
-
 #ifndef CONFIG_NET_CLS_ACT
 #ifdef CONFIG_NETFILTER
 	if (!nf_registered) {
 		if (nf_register_hook(&ing_ops) < 0) {
 			printk("ingress qdisc registration error \n");
-			goto error;
+			return -EINVAL;
 		}
 		nf_registered++;
 	}
@@ -305,12 +302,8 @@
 #endif
 
 	DPRINTK("ingress_init(sch %p,[qdisc %p],opt %p)\n",sch,p,opt);
-	memset(p, 0, sizeof(*p));
-	p->filter_list = NULL;
 	p->q = &noop_qdisc;
 	return 0;
-error:
-	return -EINVAL;
 }
 
 
@@ -346,9 +339,6 @@
 		p->filter_list = tp->next;
 		tcf_destroy(tp);
 	}
-	memset(p, 0, sizeof(*p));
-	p->filter_list = NULL;
-
 #if 0
 /* for future use */
 	qdisc_destroy(p->q);
diff -Nru a/net/sched/sch_netem.c b/net/sched/sch_netem.c
--- a/net/sched/sch_netem.c	2004-10-18 14:57:04 -07:00
+++ b/net/sched/sch_netem.c	2004-10-18 14:57:04 -07:00
@@ -6,6 +6,9 @@
  * 		as published by the Free Software Foundation; either version
  * 		2 of the License, or (at your option) any later version.
  *
+ *  		Many of the algorithms and ideas for this came from
+ *		NIST Net which is not copyrighted. 
+ *
  * Authors:	Stephen Hemminger <shemminger@osdl.org>
  *		Catalin(ux aka Dino) BOIE <catab at umbrella dot ro>
  */
@@ -22,11 +25,31 @@
 
 #include <net/pkt_sched.h>
 
-/*	Network emulator
- *
- *	This scheduler can alters spacing and order
- *	Similar to NISTnet and BSD Dummynet.
- */
+/*	Network Emulation Queuing algorithm.
+	====================================
+
+	Sources: [1] Mark Carson, Darrin Santay, "NIST Net - A Linux-based
+		 Network Emulation Tool
+		 [2] Luigi Rizzo, DummyNet for FreeBSD
+
+	 ----------------------------------------------------------------
+
+	 This started out as a simple way to delay outgoing packets to
+	 test TCP but has grown to include most of the functionality
+	 of a full blown network emulator like NISTnet. It can delay
+	 packets and add random jitter (and correlation). The random
+	 distribution can be loaded from a table as well to provide
+	 normal, Pareto, or experimental curves. Packet loss,
+	 duplication, and reordering can also be emulated.
+
+	 This qdisc does not do classification that can be handled in
+	 layering other disciplines.  It does not need to do bandwidth
+	 control either since that can be handled by using token
+	 bucket or other rate control.
+
+	 The simulator is limited by the Linux timer resolution
+	 and will create packet bursts on the HZ boundary (1ms).
+*/
 
 struct netem_sched_data {
 	struct Qdisc	*qdisc;
@@ -39,6 +62,17 @@
 	u32 counter;
 	u32 gap;
 	u32 jitter;
+	u32 duplicate;
+
+	struct crndstate {
+		unsigned long last;
+		unsigned long rho;
+	} delay_cor, loss_cor, dup_cor;
+
+	struct disttable {
+		u32  size;
+		s16 table[0];
+	} *delay_dist;
 };
 
 /* Time stamp put into socket buffer control block */
@@ -46,576 +80,110 @@
 	psched_time_t	time_to_send;
 };
 
-/* This is the distribution table for the normal distribution produced
- * with NISTnet tools.
- * The entries represent a scaled inverse of the cumulative distribution
- * function.
+/* init_crandom - initialize correlated random number generator
+ * Use entropy source for initial seed.
  */
-#define TABLESIZE	2048
-#define TABLEFACTOR	8192
+static void init_crandom(struct crndstate *state, unsigned long rho)
+{
+	state->rho = rho;
+	state->last = net_random();
+}
 
-static const short disttable[TABLESIZE] = {
-	-31473,		-26739,		-25226,		-24269,
-	-23560,		-22993,		-22518,		-22109,
-	-21749,		-21426,		-21133,		-20865,
-	-20618,		-20389,		-20174,		-19972,
-	-19782,		-19601,		-19430,		-19267,
-	-19112,		-18962,		-18819,		-18681,
-	-18549,		-18421,		-18298,		-18178,
-	-18062,		-17950,		-17841,		-17735,
-	-17632,		-17532,		-17434,		-17339,
-	-17245,		-17155,		-17066,		-16979,
-	-16894,		-16811,		-16729,		-16649,
-	-16571,		-16494,		-16419,		-16345,
-	-16272,		-16201,		-16130,		-16061,
-	-15993,		-15926,		-15861,		-15796,
-	-15732,		-15669,		-15607,		-15546,
-	-15486,		-15426,		-15368,		-15310,
-	-15253,		-15196,		-15140,		-15086,
-	-15031,		-14977,		-14925,		-14872,
-	-14821,		-14769,		-14719,		-14669,
-	-14619,		-14570,		-14522,		-14473,
-	-14426,		-14379,		-14332,		-14286,
-	-14241,		-14196,		-14150,		-14106,
-	-14062,		-14019,		-13976,		-13933,
-	-13890,		-13848,		-13807,		-13765,
-	-13724,		-13684,		-13643,		-13604,
-	-13564,		-13525,		-13486,		-13447,
-	-13408,		-13370,		-13332,		-13295,
-	-13258,		-13221,		-13184,		-13147,
-	-13111,		-13075,		-13040,		-13004,
-	-12969,		-12934,		-12899,		-12865,
-	-12830,		-12796,		-12762,		-12729,
-	-12695,		-12662,		-12629,		-12596,
-	-12564,		-12531,		-12499,		-12467,
-	-12435,		-12404,		-12372,		-12341,
-	-12310,		-12279,		-12248,		-12218,
-	-12187,		-12157,		-12127,		-12097,
-	-12067,		-12038,		-12008,		-11979,
-	-11950,		-11921,		-11892,		-11863,
-	-11835,		-11806,		-11778,		-11750,
-	-11722,		-11694,		-11666,		-11639,
-	-11611,		-11584,		-11557,		-11530,
-	-11503,		-11476,		-11450,		-11423,
-	-11396,		-11370,		-11344,		-11318,
-	-11292,		-11266,		-11240,		-11214,
-	-11189,		-11164,		-11138,		-11113,
-	-11088,		-11063,		-11038,		-11013,
-	-10988,		-10964,		-10939,		-10915,
-	-10891,		-10866,		-10843,		-10818,
-	-10794,		-10770,		-10747,		-10723,
-	-10700,		-10676,		-10652,		-10630,
-	-10606,		-10583,		-10560,		-10537,
-	-10514,		-10491,		-10469,		-10446,
-	-10424,		-10401,		-10378,		-10356,
-	-10334,		-10312,		-10290,		-10267,
-	-10246,		-10224,		-10202,		-10180,
-	-10158,		-10137,		-10115,		-10094,
-	-10072,		-10051,		-10030,		-10009,
-	-9988,		-9967,		-9945,		-9925,
-	-9904,		-9883,		-9862,		-9842,
-	-9821,		-9800,		-9780,		-9760,
-	-9739,		-9719,		-9699,		-9678,
-	-9658,		-9638,		-9618,		-9599,
-	-9578,		-9559,		-9539,		-9519,
-	-9499,		-9480,		-9461,		-9441,
-	-9422,		-9402,		-9383,		-9363,
-	-9344,		-9325,		-9306,		-9287,
-	-9268,		-9249,		-9230,		-9211,
-	-9192,		-9173,		-9155,		-9136,
-	-9117,		-9098,		-9080,		-9062,
-	-9043,		-9025,		-9006,		-8988,
-	-8970,		-8951,		-8933,		-8915,
-	-8897,		-8879,		-8861,		-8843,
-	-8825,		-8807,		-8789,		-8772,
-	-8754,		-8736,		-8718,		-8701,
-	-8683,		-8665,		-8648,		-8630,
-	-8613,		-8595,		-8578,		-8561,
-	-8543,		-8526,		-8509,		-8492,
-	-8475,		-8458,		-8441,		-8423,
-	-8407,		-8390,		-8373,		-8356,
-	-8339,		-8322,		-8305,		-8289,
-	-8272,		-8255,		-8239,		-8222,
-	-8206,		-8189,		-8172,		-8156,
-	-8140,		-8123,		-8107,		-8090,
-	-8074,		-8058,		-8042,		-8025,
-	-8009,		-7993,		-7977,		-7961,
-	-7945,		-7929,		-7913,		-7897,
-	-7881,		-7865,		-7849,		-7833,
-	-7817,		-7802,		-7786,		-7770,
-	-7754,		-7739,		-7723,		-7707,
-	-7692,		-7676,		-7661,		-7645,
-	-7630,		-7614,		-7599,		-7583,
-	-7568,		-7553,		-7537,		-7522,
-	-7507,		-7492,		-7476,		-7461,
-	-7446,		-7431,		-7416,		-7401,
-	-7385,		-7370,		-7356,		-7340,
-	-7325,		-7311,		-7296,		-7281,
-	-7266,		-7251,		-7236,		-7221,
-	-7207,		-7192,		-7177,		-7162,
-	-7148,		-7133,		-7118,		-7104,
-	-7089,		-7075,		-7060,		-7046,
-	-7031,		-7016,		-7002,		-6988,
-	-6973,		-6959,		-6944,		-6930,
-	-6916,		-6901,		-6887,		-6873,
-	-6859,		-6844,		-6830,		-6816,
-	-6802,		-6788,		-6774,		-6760,
-	-6746,		-6731,		-6717,		-6704,
-	-6690,		-6675,		-6661,		-6647,
-	-6633,		-6620,		-6606,		-6592,
-	-6578,		-6564,		-6550,		-6537,
-	-6523,		-6509,		-6495,		-6482,
-	-6468,		-6454,		-6441,		-6427,
-	-6413,		-6400,		-6386,		-6373,
-	-6359,		-6346,		-6332,		-6318,
-	-6305,		-6291,		-6278,		-6264,
-	-6251,		-6238,		-6224,		-6211,
-	-6198,		-6184,		-6171,		-6158,
-	-6144,		-6131,		-6118,		-6105,
-	-6091,		-6078,		-6065,		-6052,
-	-6039,		-6025,		-6012,		-5999,
-	-5986,		-5973,		-5960,		-5947,
-	-5934,		-5921,		-5908,		-5895,
-	-5882,		-5869,		-5856,		-5843,
-	-5830,		-5817,		-5804,		-5791,
-	-5779,		-5766,		-5753,		-5740,
-	-5727,		-5714,		-5702,		-5689,
-	-5676,		-5663,		-5650,		-5638,
-	-5625,		-5612,		-5600,		-5587,
-	-5575,		-5562,		-5549,		-5537,
-	-5524,		-5512,		-5499,		-5486,
-	-5474,		-5461,		-5449,		-5436,
-	-5424,		-5411,		-5399,		-5386,
-	-5374,		-5362,		-5349,		-5337,
-	-5324,		-5312,		-5299,		-5287,
-	-5275,		-5263,		-5250,		-5238,
-	-5226,		-5213,		-5201,		-5189,
-	-5177,		-5164,		-5152,		-5140,
-	-5128,		-5115,		-5103,		-5091,
-	-5079,		-5067,		-5055,		-5043,
-	-5030,		-5018,		-5006,		-4994,
-	-4982,		-4970,		-4958,		-4946,
-	-4934,		-4922,		-4910,		-4898,
-	-4886,		-4874,		-4862,		-4850,
-	-4838,		-4826,		-4814,		-4803,
-	-4791,		-4778,		-4767,		-4755,
-	-4743,		-4731,		-4719,		-4708,
-	-4696,		-4684,		-4672,		-4660,
-	-4649,		-4637,		-4625,		-4613,
-	-4601,		-4590,		-4578,		-4566,
-	-4554,		-4543,		-4531,		-4520,
-	-4508,		-4496,		-4484,		-4473,
-	-4461,		-4449,		-4438,		-4427,
-	-4415,		-4403,		-4392,		-4380,
-	-4368,		-4357,		-4345,		-4334,
-	-4322,		-4311,		-4299,		-4288,
-	-4276,		-4265,		-4253,		-4242,
-	-4230,		-4219,		-4207,		-4196,
-	-4184,		-4173,		-4162,		-4150,
-	-4139,		-4128,		-4116,		-4105,
-	-4094,		-4082,		-4071,		-4060,
-	-4048,		-4037,		-4026,		-4014,
-	-4003,		-3992,		-3980,		-3969,
-	-3958,		-3946,		-3935,		-3924,
-	-3913,		-3901,		-3890,		-3879,
-	-3868,		-3857,		-3845,		-3834,
-	-3823,		-3812,		-3801,		-3790,
-	-3779,		-3767,		-3756,		-3745,
-	-3734,		-3723,		-3712,		-3700,
-	-3689,		-3678,		-3667,		-3656,
-	-3645,		-3634,		-3623,		-3612,
-	-3601,		-3590,		-3579,		-3568,
-	-3557,		-3545,		-3535,		-3524,
-	-3513,		-3502,		-3491,		-3480,
-	-3469,		-3458,		-3447,		-3436,
-	-3425,		-3414,		-3403,		-3392,
-	-3381,		-3370,		-3360,		-3348,
-	-3337,		-3327,		-3316,		-3305,
-	-3294,		-3283,		-3272,		-3262,
-	-3251,		-3240,		-3229,		-3218,
-	-3207,		-3197,		-3185,		-3175,
-	-3164,		-3153,		-3142,		-3132,
-	-3121,		-3110,		-3099,		-3088,
-	-3078,		-3067,		-3056,		-3045,
-	-3035,		-3024,		-3013,		-3003,
-	-2992,		-2981,		-2970,		-2960,
-	-2949,		-2938,		-2928,		-2917,
-	-2906,		-2895,		-2885,		-2874,
-	-2864,		-2853,		-2842,		-2832,
-	-2821,		-2810,		-2800,		-2789,
-	-2778,		-2768,		-2757,		-2747,
-	-2736,		-2725,		-2715,		-2704,
-	-2694,		-2683,		-2673,		-2662,
-	-2651,		-2641,		-2630,		-2620,
-	-2609,		-2599,		-2588,		-2578,
-	-2567,		-2556,		-2546,		-2535,
-	-2525,		-2515,		-2504,		-2493,
-	-2483,		-2472,		-2462,		-2451,
-	-2441,		-2431,		-2420,		-2410,
-	-2399,		-2389,		-2378,		-2367,
-	-2357,		-2347,		-2336,		-2326,
-	-2315,		-2305,		-2295,		-2284,
-	-2274,		-2263,		-2253,		-2243,
-	-2232,		-2222,		-2211,		-2201,
-	-2191,		-2180,		-2170,		-2159,
-	-2149,		-2139,		-2128,		-2118,
-	-2107,		-2097,		-2087,		-2076,
-	-2066,		-2056,		-2046,		-2035,
-	-2025,		-2014,		-2004,		-1994,
-	-1983,		-1973,		-1963,		-1953,
-	-1942,		-1932,		-1921,		-1911,
-	-1901,		-1891,		-1880,		-1870,
-	-1860,		-1849,		-1839,		-1829,
-	-1819,		-1808,		-1798,		-1788,
-	-1778,		-1767,		-1757,		-1747,
-	-1736,		-1726,		-1716,		-1706,
-	-1695,		-1685,		-1675,		-1665,
-	-1654,		-1644,		-1634,		-1624,
-	-1613,		-1603,		-1593,		-1583,
-	-1573,		-1563,		-1552,		-1542,
-	-1532,		-1522,		-1511,		-1501,
-	-1491,		-1481,		-1471,		-1461,
-	-1450,		-1440,		-1430,		-1420,
-	-1409,		-1400,		-1389,		-1379,
-	-1369,		-1359,		-1348,		-1339,
-	-1328,		-1318,		-1308,		-1298,
-	-1288,		-1278,		-1267,		-1257,
-	-1247,		-1237,		-1227,		-1217,
-	-1207,		-1196,		-1186,		-1176,
-	-1166,		-1156,		-1146,		-1135,
-	-1126,		-1115,		-1105,		-1095,
-	-1085,		-1075,		-1065,		-1055,
-	-1044,		-1034,		-1024,		-1014,
-	-1004,		-994,		-984,		-974,
-	-964,		-954,		-944,		-933,
-	-923,		-913,		-903,		-893,
-	-883,		-873,		-863,		-853,
-	-843,		-833,		-822,		-812,
-	-802,		-792,		-782,		-772,
-	-762,		-752,		-742,		-732,
-	-722,		-712,		-702,		-691,
-	-682,		-671,		-662,		-651,
-	-641,		-631,		-621,		-611,
-	-601,		-591,		-581,		-571,
-	-561,		-551,		-541,		-531,
-	-521,		-511,		-501,		-491,
-	-480,		-471,		-460,		-451,
-	-440,		-430,		-420,		-410,
-	-400,		-390,		-380,		-370,
-	-360,		-350,		-340,		-330,
-	-320,		-310,		-300,		-290,
-	-280,		-270,		-260,		-250,
-	-240,		-230,		-220,		-210,
-	-199,		-190,		-179,		-170,
-	-159,		-150,		-139,		-129,
-	-119,		-109,		-99,		-89,
-	-79,		-69,		-59,		-49,
-	-39,		-29,		-19,		-9,
-	1,		11,		21,		31,
-	41,		51,		61,		71,
-	81,		91,		101,		111,
-	121,		131,		141,		152,
-	161,		172,		181,		192,
-	202,		212,		222,		232,
-	242,		252,		262,		272,
-	282,		292,		302,		312,
-	322,		332,		342,		352,
-	362,		372,		382,		392,
-	402,		412,		422,		433,
-	442,		453,		462,		473,
-	483,		493,		503,		513,
-	523,		533,		543,		553,
-	563,		573,		583,		593,
-	603,		613,		623,		633,
-	643,		653,		664,		673,
-	684,		694,		704,		714,
-	724,		734,		744,		754,
-	764,		774,		784,		794,
-	804,		815,		825,		835,
-	845,		855,		865,		875,
-	885,		895,		905,		915,
-	925,		936,		946,		956,
-	966,		976,		986,		996,
-	1006,		1016,		1026,		1037,
-	1047,		1057,		1067,		1077,
-	1087,		1097,		1107,		1117,
-	1128,		1138,		1148,		1158,
-	1168,		1178,		1188,		1198,
-	1209,		1219,		1229,		1239,
-	1249,		1259,		1269,		1280,
-	1290,		1300,		1310,		1320,
-	1330,		1341,		1351,		1361,
-	1371,		1381,		1391,		1402,
-	1412,		1422,		1432,		1442,
-	1452,		1463,		1473,		1483,
-	1493,		1503,		1513,		1524,
-	1534,		1544,		1554,		1565,
-	1575,		1585,		1595,		1606,
-	1616,		1626,		1636,		1647,
-	1656,		1667,		1677,		1687,
-	1697,		1708,		1718,		1729,
-	1739,		1749,		1759,		1769,
-	1780,		1790,		1800,		1810,
-	1821,		1831,		1841,		1851,
-	1862,		1872,		1883,		1893,
-	1903,		1913,		1923,		1934,
-	1944,		1955,		1965,		1975,
-	1985,		1996,		2006,		2016,
-	2027,		2037,		2048,		2058,
-	2068,		2079,		2089,		2099,
-	2110,		2120,		2130,		2141,
-	2151,		2161,		2172,		2182,
-	2193,		2203,		2213,		2224,
-	2234,		2245,		2255,		2265,
-	2276,		2286,		2297,		2307,
-	2318,		2328,		2338,		2349,
-	2359,		2370,		2380,		2391,
-	2401,		2412,		2422,		2433,
-	2443,		2454,		2464,		2475,
-	2485,		2496,		2506,		2517,
-	2527,		2537,		2548,		2559,
-	2569,		2580,		2590,		2601,
-	2612,		2622,		2632,		2643,
-	2654,		2664,		2675,		2685,
-	2696,		2707,		2717,		2728,
-	2738,		2749,		2759,		2770,
-	2781,		2791,		2802,		2813,
-	2823,		2834,		2845,		2855,
-	2866,		2877,		2887,		2898,
-	2909,		2919,		2930,		2941,
-	2951,		2962,		2973,		2984,
-	2994,		3005,		3015,		3027,
-	3037,		3048,		3058,		3069,
-	3080,		3091,		3101,		3113,
-	3123,		3134,		3145,		3156,
-	3166,		3177,		3188,		3199,
-	3210,		3220,		3231,		3242,
-	3253,		3264,		3275,		3285,
-	3296,		3307,		3318,		3329,
-	3340,		3351,		3362,		3373,
-	3384,		3394,		3405,		3416,
-	3427,		3438,		3449,		3460,
-	3471,		3482,		3493,		3504,
-	3515,		3526,		3537,		3548,
-	3559,		3570,		3581,		3592,
-	3603,		3614,		3625,		3636,
-	3647,		3659,		3670,		3681,
-	3692,		3703,		3714,		3725,
-	3736,		3747,		3758,		3770,
-	3781,		3792,		3803,		3814,
-	3825,		3837,		3848,		3859,
-	3870,		3881,		3893,		3904,
-	3915,		3926,		3937,		3949,
-	3960,		3971,		3983,		3994,
-	4005,		4017,		4028,		4039,
-	4051,		4062,		4073,		4085,
-	4096,		4107,		4119,		4130,
-	4141,		4153,		4164,		4175,
-	4187,		4198,		4210,		4221,
-	4233,		4244,		4256,		4267,
-	4279,		4290,		4302,		4313,
-	4325,		4336,		4348,		4359,
-	4371,		4382,		4394,		4406,
-	4417,		4429,		4440,		4452,
-	4464,		4475,		4487,		4499,
-	4510,		4522,		4533,		4545,
-	4557,		4569,		4581,		4592,
-	4604,		4616,		4627,		4639,
-	4651,		4663,		4674,		4686,
-	4698,		4710,		4722,		4734,
-	4746,		4758,		4769,		4781,
-	4793,		4805,		4817,		4829,
-	4841,		4853,		4865,		4877,
-	4889,		4900,		4913,		4925,
-	4936,		4949,		4961,		4973,
-	4985,		4997,		5009,		5021,
-	5033,		5045,		5057,		5070,
-	5081,		5094,		5106,		5118,
-	5130,		5143,		5155,		5167,
-	5179,		5191,		5204,		5216,
-	5228,		5240,		5253,		5265,
-	5278,		5290,		5302,		5315,
-	5327,		5340,		5352,		5364,
-	5377,		5389,		5401,		5414,
-	5426,		5439,		5451,		5464,
-	5476,		5489,		5502,		5514,
-	5527,		5539,		5552,		5564,
-	5577,		5590,		5603,		5615,
-	5628,		5641,		5653,		5666,
-	5679,		5691,		5704,		5717,
-	5730,		5743,		5756,		5768,
-	5781,		5794,		5807,		5820,
-	5833,		5846,		5859,		5872,
-	5885,		5897,		5911,		5924,
-	5937,		5950,		5963,		5976,
-	5989,		6002,		6015,		6028,
-	6042,		6055,		6068,		6081,
-	6094,		6108,		6121,		6134,
-	6147,		6160,		6174,		6187,
-	6201,		6214,		6227,		6241,
-	6254,		6267,		6281,		6294,
-	6308,		6321,		6335,		6348,
-	6362,		6375,		6389,		6403,
-	6416,		6430,		6443,		6457,
-	6471,		6485,		6498,		6512,
-	6526,		6540,		6554,		6567,
-	6581,		6595,		6609,		6623,
-	6637,		6651,		6665,		6679,
-	6692,		6706,		6721,		6735,
-	6749,		6763,		6777,		6791,
-	6805,		6819,		6833,		6848,
-	6862,		6876,		6890,		6905,
-	6919,		6933,		6948,		6962,
-	6976,		6991,		7005,		7020,
-	7034,		7049,		7064,		7078,
-	7093,		7107,		7122,		7136,
-	7151,		7166,		7180,		7195,
-	7210,		7225,		7240,		7254,
-	7269,		7284,		7299,		7314,
-	7329,		7344,		7359,		7374,
-	7389,		7404,		7419,		7434,
-	7449,		7465,		7480,		7495,
-	7510,		7526,		7541,		7556,
-	7571,		7587,		7602,		7618,
-	7633,		7648,		7664,		7680,
-	7695,		7711,		7726,		7742,
-	7758,		7773,		7789,		7805,
-	7821,		7836,		7852,		7868,
-	7884,		7900,		7916,		7932,
-	7948,		7964,		7981,		7997,
-	8013,		8029,		8045,		8061,
-	8078,		8094,		8110,		8127,
-	8143,		8160,		8176,		8193,
-	8209,		8226,		8242,		8259,
-	8276,		8292,		8309,		8326,
-	8343,		8360,		8377,		8394,
-	8410,		8428,		8444,		8462,
-	8479,		8496,		8513,		8530,
-	8548,		8565,		8582,		8600,
-	8617,		8634,		8652,		8670,
-	8687,		8704,		8722,		8740,
-	8758,		8775,		8793,		8811,
-	8829,		8847,		8865,		8883,
-	8901,		8919,		8937,		8955,
-	8974,		8992,		9010,		9029,
-	9047,		9066,		9084,		9103,
-	9121,		9140,		9159,		9177,
-	9196,		9215,		9234,		9253,
-	9272,		9291,		9310,		9329,
-	9349,		9368,		9387,		9406,
-	9426,		9445,		9465,		9484,
-	9504,		9524,		9544,		9563,
-	9583,		9603,		9623,		9643,
-	9663,		9683,		9703,		9723,
-	9744,		9764,		9785,		9805,
-	9826,		9846,		9867,		9888,
-	9909,		9930,		9950,		9971,
-	9993,		10013,		10035,		10056,
-	10077,		10099,		10120,		10142,
-	10163,		10185,		10207,		10229,
-	10251,		10273,		10294,		10317,
-	10339,		10361,		10384,		10406,
-	10428,		10451,		10474,		10496,
-	10519,		10542,		10565,		10588,
-	10612,		10635,		10658,		10682,
-	10705,		10729,		10752,		10776,
-	10800,		10824,		10848,		10872,
-	10896,		10921,		10945,		10969,
-	10994,		11019,		11044,		11069,
-	11094,		11119,		11144,		11169,
-	11195,		11221,		11246,		11272,
-	11298,		11324,		11350,		11376,
-	11402,		11429,		11456,		11482,
-	11509,		11536,		11563,		11590,
-	11618,		11645,		11673,		11701,
-	11728,		11756,		11785,		11813,
-	11842,		11870,		11899,		11928,
-	11957,		11986,		12015,		12045,
-	12074,		12104,		12134,		12164,
-	12194,		12225,		12255,		12286,
-	12317,		12348,		12380,		12411,
-	12443,		12475,		12507,		12539,
-	12571,		12604,		12637,		12670,
-	12703,		12737,		12771,		12804,
-	12839,		12873,		12907,		12942,
-	12977,		13013,		13048,		13084,
-	13120,		13156,		13192,		13229,
-	13267,		13304,		13341,		13379,
-	13418,		13456,		13495,		13534,
-	13573,		13613,		13653,		13693,
-	13734,		13775,		13817,		13858,
-	13901,		13943,		13986,		14029,
-	14073,		14117,		14162,		14206,
-	14252,		14297,		14343,		14390,
-	14437,		14485,		14533,		14582,
-	14631,		14680,		14731,		14782,
-	14833,		14885,		14937,		14991,
-	15044,		15099,		15154,		15210,
-	15266,		15324,		15382,		15441,
-	15500,		15561,		15622,		15684,
-	15747,		15811,		15877,		15943,
-	16010,		16078,		16148,		16218,
-	16290,		16363,		16437,		16513,
-	16590,		16669,		16749,		16831,
-	16915,		17000,		17088,		17177,
-	17268,		17362,		17458,		17556,
-	17657,		17761,		17868,		17977,
-	18090,		18207,		18328,		18452,
-	18581,		18715,		18854,		18998,
-	19149,		19307,		19472,		19645,
-	19828,		20021,		20226,		20444,
-	20678,		20930,		21204,		21503,
-	21835,		22206,		22630,		23124,
-	23721,		24478,		25529,		27316,
-};
+/* get_crandom - correlated random number generator
+ * Next number depends on last value.
+ * rho is scaled to avoid floating point.
+ */
+static unsigned long get_crandom(struct crndstate *state)
+{
+	u64 value, rho;
+	unsigned long answer;
+
+	if (state->rho == 0)	/* no correllation */
+		return net_random();
+
+	value = net_random();
+	rho = (u64)state->rho + 1;
+	answer = (value * ((1ull<<32) - rho) + state->last * rho) >> 32;
+	state->last = answer;
+	return answer;
+}
 
 /* tabledist - return a pseudo-randomly distributed value with mean mu and
  * std deviation sigma.  Uses table lookup to approximate the desired
  * distribution, and a uniformly-distributed pseudo-random source.
  */
-static inline int tabledist(int mu, int sigma)
+static long tabledist(unsigned long mu, long sigma, 
+		      struct crndstate *state, const struct disttable *dist)
 {
-	int x;
-	int index;
-	int sigmamod, sigmadiv;
+	long t, x;
+	unsigned long rnd;
 
 	if (sigma == 0)
 		return mu;
 
-	index = (net_random() & (TABLESIZE-1));
-	sigmamod = sigma%TABLEFACTOR;
-	sigmadiv = sigma/TABLEFACTOR;
-	x = sigmamod*disttable[index];
+	rnd = get_crandom(state);
+
+	/* default uniform distribution */
+	if (dist == NULL) 
+		return (rnd % (2*sigma)) - sigma + mu;
 
+	t = dist->table[rnd % dist->size];
+	x = (sigma % NETEM_DIST_SCALE) * t;
 	if (x >= 0)
-		x += TABLEFACTOR/2;
+		x += NETEM_DIST_SCALE/2;
 	else
-		x -= TABLEFACTOR/2;
+		x -= NETEM_DIST_SCALE/2;
 
-	x /= TABLEFACTOR;
-	x += sigmadiv*disttable[index];
-	x += mu;
-	return x;
+	return  x / NETEM_DIST_SCALE + (sigma / NETEM_DIST_SCALE) * t + mu;
 }
 
-/* Enqueue packets with underlying discipline (fifo)
- * but mark them with current time first.
- */
-static int netem_enqueue(struct sk_buff *skb, struct Qdisc *sch)
+/* Put skb in the private delayed queue. */
+static int delay_skb(struct Qdisc *sch, struct sk_buff *skb)
 {
 	struct netem_sched_data *q = qdisc_priv(sch);
 	struct netem_skb_cb *cb = (struct netem_skb_cb *)skb->cb;
 	psched_time_t now;
-	long delay;
+	
+	PSCHED_GET_TIME(now);
+	PSCHED_TADD2(now, tabledist(q->latency, q->jitter, 
+				    &q->delay_cor, q->delay_dist),
+		     cb->time_to_send);
+	
+	/* Always queue at tail to keep packets in order */
+	if (likely(q->delayed.qlen < q->limit)) {
+		__skb_queue_tail(&q->delayed, skb);
+		sch->q.qlen++;
+		sch->stats.bytes += skb->len;
+		sch->stats.packets++;
+		return NET_XMIT_SUCCESS;
+	}
+
+	sch->stats.drops++;
+	kfree_skb(skb);
+	return NET_XMIT_DROP;
+}
+
+static int netem_enqueue(struct sk_buff *skb, struct Qdisc *sch)
+{
+	struct netem_sched_data *q = qdisc_priv(sch);
 
 	pr_debug("netem_enqueue skb=%p @%lu\n", skb, jiffies);
 
 	/* Random packet drop 0 => none, ~0 => all */
-	if (q->loss && q->loss >= net_random()) {
+	if (q->loss && q->loss >= get_crandom(&q->loss_cor)) {
+		pr_debug("netem_enqueue: random loss\n");
 		sch->stats.drops++;
 		return 0;	/* lie about loss so TCP doesn't know */
 	}
 
+	/* Random duplication */
+	if (q->duplicate && q->duplicate >= get_crandom(&q->dup_cor)) {
+		struct sk_buff *skb2 = skb_clone(skb, GFP_ATOMIC);
+
+		pr_debug("netem_enqueue: dup %p\n", skb2);
+		if (skb2)
+			delay_skb(sch, skb2);
+	}
 
 	/* If doing simple delay then gap == 0 so all packets
 	 * go into the delayed holding queue
@@ -633,27 +201,8 @@
 	}
 	
 	q->counter = 0;
-	
-	PSCHED_GET_TIME(now);
-	if (q->jitter) 
-		delay = tabledist(q->latency, q->jitter);
-	else
-		delay = q->latency;
 
-	PSCHED_TADD2(now, delay, cb->time_to_send);
-	
-	/* Always queue at tail to keep packets in order */
-	if (likely(q->delayed.qlen < q->limit)) {
-		__skb_queue_tail(&q->delayed, skb);
-		sch->q.qlen++;
-		sch->stats.bytes += skb->len;
-		sch->stats.packets++;
-		return 0;
-	}
-
-	sch->stats.drops++;
-	kfree_skb(skb);
-	return NET_XMIT_DROP;
+	return delay_skb(sch, skb);
 }
 
 /* Requeue packets but don't change time stamp */
@@ -752,39 +301,97 @@
 	return ret;
 }
 
-static int netem_change(struct Qdisc *sch, struct rtattr *opt)
+/*
+ * Distribution data is a variable size payload containing
+ * signed 16 bit values.
+ */
+static int get_dist_table(struct Qdisc *sch, const struct rtattr *attr)
 {
 	struct netem_sched_data *q = qdisc_priv(sch);
-	struct tc_netem_qopt *qopt = RTA_DATA(opt);
-	struct Qdisc *child;
-	int ret;
+	unsigned long n = RTA_PAYLOAD(attr)/sizeof(__s16);
+	const __s16 *data = RTA_DATA(attr);
+	struct disttable *d;
+	int i;
 
-	if (opt->rta_len < RTA_LENGTH(sizeof(*qopt)))
+	if (n > 65536)
 		return -EINVAL;
 
-	child = qdisc_create_dflt(sch->dev, &pfifo_qdisc_ops);
-	if (!child)
+	d = kmalloc(sizeof(*d) + n*sizeof(d->table[0]), GFP_KERNEL);
+	if (!d)
+		return -ENOMEM;
+
+	d->size = n;
+	for (i = 0; i < n; i++)
+		d->table[i] = data[i];
+	
+	spin_lock_bh(&sch->dev->queue_lock);
+	d = xchg(&q->delay_dist, d);
+	spin_unlock_bh(&sch->dev->queue_lock);
+
+	kfree(d);
+	return 0;
+}
+
+static int get_correlation(struct Qdisc *sch, const struct rtattr *attr)
+{
+	struct netem_sched_data *q = qdisc_priv(sch);
+	const struct tc_netem_corr *c = RTA_DATA(attr);
+
+	if (RTA_PAYLOAD(attr) != sizeof(*c))
 		return -EINVAL;
 
-	ret = set_fifo_limit(child, qopt->limit);
+	init_crandom(&q->delay_cor, c->delay_corr);
+	init_crandom(&q->loss_cor, c->loss_corr);
+	init_crandom(&q->dup_cor, c->dup_corr);
+	return 0;
+}
+
+static int netem_change(struct Qdisc *sch, struct rtattr *opt)
+{
+	struct netem_sched_data *q = qdisc_priv(sch);
+	struct tc_netem_qopt *qopt;
+	int ret;
+	
+	if (opt == NULL || RTA_PAYLOAD(opt) < sizeof(*qopt))
+		return -EINVAL;
+
+	qopt = RTA_DATA(opt);
+	ret = set_fifo_limit(q->qdisc, qopt->limit);
 	if (ret) {
-		qdisc_destroy(child);
+		pr_debug("netem: can't set fifo limit\n");
 		return ret;
 	}
-
-	sch_tree_lock(sch);
-	if (child) {
-		child = xchg(&q->qdisc, child);
-		if (child != &noop_qdisc)
-			qdisc_destroy(child);
 	
-		q->latency = qopt->latency;
-		q->jitter = qopt->jitter;
-		q->limit = qopt->limit;
-		q->gap = qopt->gap;
-		q->loss = qopt->loss;
+	q->latency = qopt->latency;
+	q->jitter = qopt->jitter;
+	q->limit = qopt->limit;
+	q->gap = qopt->gap;
+	q->loss = qopt->loss;
+	q->duplicate = qopt->duplicate;
+
+	/* Handle nested options after initial queue options.
+	 * Should have put all options in nested format but too late now.
+	 */ 
+	if (RTA_PAYLOAD(opt) > sizeof(*qopt)) {
+		struct rtattr *tb[TCA_NETEM_MAX];
+		if (rtattr_parse(tb, TCA_NETEM_MAX, 
+				 RTA_DATA(opt) + sizeof(*qopt),
+				 RTA_PAYLOAD(opt) - sizeof(*qopt)))
+			return -EINVAL;
+
+		if (tb[TCA_NETEM_CORR-1]) {
+			ret = get_correlation(sch, tb[TCA_NETEM_CORR-1]);
+			if (ret)
+				return ret;
+		}
+
+		if (tb[TCA_NETEM_DELAY_DIST-1]) {
+			ret = get_dist_table(sch, tb[TCA_NETEM_DELAY_DIST-1]);
+			if (ret)
+				return ret;
+		}
 	}
-	sch_tree_unlock(sch);
+
 
 	return 0;
 }
@@ -792,19 +399,29 @@
 static int netem_init(struct Qdisc *sch, struct rtattr *opt)
 {
 	struct netem_sched_data *q = qdisc_priv(sch);
+	int ret;
 
 	if (!opt)
 		return -EINVAL;
 
 	skb_queue_head_init(&q->delayed);
-	q->qdisc = &noop_qdisc;
-
 	init_timer(&q->timer);
 	q->timer.function = netem_watchdog;
 	q->timer.data = (unsigned long) sch;
 	q->counter = 0;
 
-	return netem_change(sch, opt);
+	q->qdisc = qdisc_create_dflt(sch->dev, &pfifo_qdisc_ops);
+	if (!q->qdisc) {
+		pr_debug("netem: qdisc create failed\n");
+		return -ENOMEM;
+	}
+
+	ret = netem_change(sch, opt);
+	if (ret) {
+		pr_debug("netem: change failed\n");
+		qdisc_destroy(q->qdisc);
+	}
+	return ret;
 }
 
 static void netem_destroy(struct Qdisc *sch)
@@ -813,21 +430,30 @@
 
 	del_timer_sync(&q->timer);
 	qdisc_destroy(q->qdisc);
+	kfree(q->delay_dist);
 }
 
 static int netem_dump(struct Qdisc *sch, struct sk_buff *skb)
 {
-	struct netem_sched_data *q = qdisc_priv(sch);
+	const struct netem_sched_data *q = qdisc_priv(sch);
 	unsigned char	 *b = skb->tail;
+	struct rtattr *rta = (struct rtattr *) b;
 	struct tc_netem_qopt qopt;
+	struct tc_netem_corr cor;
 
 	qopt.latency = q->latency;
 	qopt.jitter = q->jitter;
 	qopt.limit = q->limit;
 	qopt.loss = q->loss;
 	qopt.gap = q->gap;
-
+	qopt.duplicate = q->duplicate;
 	RTA_PUT(skb, TCA_OPTIONS, sizeof(qopt), &qopt);
+
+	cor.delay_corr = q->delay_cor.rho;
+	cor.loss_corr = q->loss_cor.rho;
+	cor.dup_corr = q->dup_cor.rho;
+	RTA_PUT(skb, TCA_NETEM_CORR, sizeof(cor), &cor);
+	rta->rta_len = skb->tail - b;
 
 	return skb->len;
 
diff -Nru a/net/sched/sch_red.c b/net/sched/sch_red.c
--- a/net/sched/sch_red.c	2004-10-18 14:57:04 -07:00
+++ b/net/sched/sch_red.c	2004-10-18 14:57:04 -07:00
@@ -40,6 +40,7 @@
 #include <net/sock.h>
 #include <net/pkt_sched.h>
 #include <net/inet_ecn.h>
+#include <net/dsfield.h>
 
 
 /*	Random Early Detection (RED) algorithm.
@@ -162,13 +163,12 @@
 
 	switch (skb->protocol) {
 	case __constant_htons(ETH_P_IP):
-		if (!INET_ECN_is_capable(skb->nh.iph->tos))
+		if (INET_ECN_is_not_ect(skb->nh.iph->tos))
 			return 0;
-		if (INET_ECN_is_not_ce(skb->nh.iph->tos))
-			IP_ECN_set_ce(skb->nh.iph);
+		IP_ECN_set_ce(skb->nh.iph);
 		return 1;
 	case __constant_htons(ETH_P_IPV6):
-		if (!INET_ECN_is_capable(ip6_get_dsfield(skb->nh.ipv6h)))
+		if (INET_ECN_is_not_ect(ipv6_get_dsfield(skb->nh.ipv6h)))
 			return 0;
 		IP6_ECN_set_ce(skb->nh.ipv6h);
 		return 1;
diff -Nru a/net/sched/sch_sfq.c b/net/sched/sch_sfq.c
--- a/net/sched/sch_sfq.c	2004-10-18 14:57:03 -07:00
+++ b/net/sched/sch_sfq.c	2004-10-18 14:57:03 -07:00
@@ -372,7 +372,6 @@
 	struct sfq_sched_data *q = qdisc_priv(sch);
 
 	q->perturbation = net_random()&0x1F;
-	q->perturb_timer.expires = jiffies + q->perturb_period;
 
 	if (q->perturb_period) {
 		q->perturb_timer.expires = jiffies + q->perturb_period;
diff -Nru a/net/sched/sch_teql.c b/net/sched/sch_teql.c
--- a/net/sched/sch_teql.c	2004-10-18 14:56:17 -07:00
+++ b/net/sched/sch_teql.c	2004-10-18 14:56:17 -07:00
@@ -31,6 +31,7 @@
 #include <net/ip.h>
 #include <net/route.h>
 #include <linux/skbuff.h>
+#include <linux/moduleparam.h>
 #include <net/sock.h>
 #include <net/pkt_sched.h>
 
@@ -449,7 +450,7 @@
 
 static LIST_HEAD(master_dev_list);
 static int max_equalizers = 1;
-MODULE_PARM(max_equalizers, "i");
+module_param(max_equalizers, int, 0);
 MODULE_PARM_DESC(max_equalizers, "Max number of link equalizers");
 
 static int __init teql_init(void)
diff -Nru a/net/sctp/ipv6.c b/net/sctp/ipv6.c
--- a/net/sctp/ipv6.c	2004-10-18 14:56:33 -07:00
+++ b/net/sctp/ipv6.c	2004-10-18 14:56:33 -07:00
@@ -583,8 +583,8 @@
 	struct ipv6_pinfo *newnp, *np = inet6_sk(sk);
 	struct sctp6_sock *newsctp6sk;
 
-	newsk = sk_alloc(PF_INET6, GFP_KERNEL, sizeof(struct sctp6_sock),
-			 sk->sk_slab);
+	newsk = sk_alloc(PF_INET6, GFP_KERNEL, sk->sk_prot->slab_obj_size,
+			 sk->sk_prot->slab);
 	if (!newsk)
 		goto out;
 
@@ -892,7 +892,7 @@
 static struct inet_protosw sctpv6_seqpacket_protosw = {
 	.type          = SOCK_SEQPACKET,
 	.protocol      = IPPROTO_SCTP,
-	.prot 	       = &sctp_prot,
+	.prot 	       = &sctpv6_prot,
 	.ops           = &inet6_seqpacket_ops,
 	.capability    = -1,
 	.no_check      = 0,
@@ -901,7 +901,7 @@
 static struct inet_protosw sctpv6_stream_protosw = {
 	.type          = SOCK_STREAM,
 	.protocol      = IPPROTO_SCTP,
-	.prot 	       = &sctp_prot,
+	.prot 	       = &sctpv6_prot,
 	.ops           = &inet6_seqpacket_ops,
 	.capability    = -1,
 	.no_check      = 0,
@@ -963,9 +963,14 @@
 /* Initialize IPv6 support and register with inet6 stack.  */
 int sctp_v6_init(void)
 {
+	int rc = sk_alloc_slab(&sctpv6_prot, "sctpv6_sock");
+
+	if (rc)
+		goto out;
 	/* Register inet6 protocol. */
+	rc = -EAGAIN;
 	if (inet6_add_protocol(&sctpv6_protocol, IPPROTO_SCTP) < 0)
-		return -EAGAIN;
+		goto out_sctp_free_slab;
 
 	/* Add SCTPv6(UDP and TCP style) to inetsw6 linked list. */
 	inet6_register_protosw(&sctpv6_seqpacket_protosw);
@@ -979,8 +984,12 @@
 
 	/* Register notifier for inet6 address additions/deletions. */
 	register_inet6addr_notifier(&sctp_inetaddr_notifier);
-
-	return 0;
+	rc = 0;
+out:
+	return rc;
+out_sctp_free_slab:
+	sk_free_slab(&sctpv6_prot);
+	goto out;
 }
 
 /* IPv6 specific exit support. */
@@ -991,4 +1000,5 @@
 	inet6_unregister_protosw(&sctpv6_seqpacket_protosw);
 	inet6_unregister_protosw(&sctpv6_stream_protosw);
 	unregister_inet6addr_notifier(&sctp_inetaddr_notifier);
+	sk_free_slab(&sctpv6_prot);
 }
diff -Nru a/net/sctp/protocol.c b/net/sctp/protocol.c
--- a/net/sctp/protocol.c	2004-10-18 14:56:33 -07:00
+++ b/net/sctp/protocol.c	2004-10-18 14:56:33 -07:00
@@ -81,8 +81,6 @@
 kmem_cache_t *sctp_chunk_cachep;
 kmem_cache_t *sctp_bucket_cachep;
 
-extern struct net_proto_family inet_family_ops;
-
 extern int sctp_snmp_proc_init(void);
 extern int sctp_snmp_proc_exit(void);
 extern int sctp_eps_proc_init(void);
@@ -148,13 +146,12 @@
 	struct in_ifaddr *ifa;
 	struct sctp_sockaddr_entry *addr;
 
-	read_lock(&inetdev_lock);
+	rcu_read_lock();
 	if ((in_dev = __in_dev_get(dev)) == NULL) {
-		read_unlock(&inetdev_lock);
+		rcu_read_unlock();
 		return;
 	}
 
-	read_lock(&in_dev->lock);
 	for (ifa = in_dev->ifa_list; ifa; ifa = ifa->ifa_next) {
 		/* Add the address to the local list.  */
 		addr = t_new(struct sctp_sockaddr_entry, GFP_ATOMIC);
@@ -166,8 +163,7 @@
 		}
 	}
 
-	read_unlock(&in_dev->lock);
-	read_unlock(&inetdev_lock);
+	rcu_read_unlock();
 }
 
 /* Extract our IP addresses from the system and stash them in the
@@ -558,8 +554,8 @@
 	struct inet_opt *inet = inet_sk(sk);
 	struct inet_opt *newinet;
 
-	newsk = sk_alloc(PF_INET, GFP_KERNEL, sizeof(struct sctp_sock),
-			 sk->sk_slab);
+	newsk = sk_alloc(PF_INET, GFP_KERNEL, sk->sk_prot->slab_obj_size,
+			 sk->sk_prot->slab);
 	if (!newsk)
 		goto out;
 
@@ -966,23 +962,29 @@
 __init int sctp_init(void)
 {
 	int i;
-	int status = 0;
+	int status = -EINVAL;
 	unsigned long goal;
 	int order;
 
 	/* SCTP_DEBUG sanity check. */
 	if (!sctp_sanity_check())
-		return -EINVAL;
+		goto out;
+
+	status = sk_alloc_slab(&sctp_prot, "sctp_sock");
+	if (status)
+		goto out;
 
 	/* Add SCTP to inet_protos hash table.  */
+	status = -EAGAIN;
 	if (inet_add_protocol(&sctp_protocol, IPPROTO_SCTP) < 0)
-		return -EAGAIN;
+		goto err_add_protocol;
 
 	/* Add SCTP(TCP and UDP style) to inetsw linked list.  */
 	inet_register_protosw(&sctp_seqpacket_protosw);
 	inet_register_protosw(&sctp_stream_protosw);
 
 	/* Allocate a cache pools. */
+	status = -ENOBUFS;
 	sctp_bucket_cachep = kmem_cache_create("sctp_bind_bucket",
 					       sizeof(struct sctp_bind_bucket),
 					       0, SLAB_HWCACHE_ALIGN,
@@ -1158,8 +1160,11 @@
 	sctp_get_local_addr_list();
 
 	__unsafe(THIS_MODULE);
-	return 0;
-
+	status = 0;
+out:
+	return status;
+err_add_protocol:
+	sk_free_slab(&sctp_prot);
 err_ctl_sock_init:
 	sctp_v6_exit();
 err_v6_init:
@@ -1187,7 +1192,7 @@
 	inet_del_protocol(&sctp_protocol, IPPROTO_SCTP);
 	inet_unregister_protosw(&sctp_seqpacket_protosw);
 	inet_unregister_protosw(&sctp_stream_protosw);
-	return status;
+	goto out;
 }
 
 /* Exit handler for the SCTP protocol.  */
@@ -1228,6 +1233,7 @@
 	inet_del_protocol(&sctp_protocol, IPPROTO_SCTP);
 	inet_unregister_protosw(&sctp_seqpacket_protosw);
 	inet_unregister_protosw(&sctp_stream_protosw);
+	sk_free_slab(&sctp_prot);
 }
 
 module_init(sctp_init);
diff -Nru a/net/sctp/socket.c b/net/sctp/socket.c
--- a/net/sctp/socket.c	2004-10-18 14:57:19 -07:00
+++ b/net/sctp/socket.c	2004-10-18 14:57:19 -07:00
@@ -108,7 +108,6 @@
 static char *sctp_hmac_alg = SCTP_COOKIE_HMAC_ALG;
 
 extern kmem_cache_t *sctp_bucket_cachep;
-extern int sctp_assoc_valid(struct sock *sk, struct sctp_association *asoc);
 
 /* Get the sndbuf space available at the time on the association.  */
 static inline int sctp_wspace(struct sctp_association *asoc)
@@ -4623,4 +4622,29 @@
 	.hash        =	sctp_hash,
 	.unhash      =	sctp_unhash,
 	.get_port    =	sctp_get_port,
+	.slab_obj_size = sizeof(struct sctp_sock),
 };
+
+#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
+struct proto sctpv6_prot = {
+	.name		= "SCTPv6",
+	.close		= sctp_close,
+	.connect	= sctp_connect,
+	.disconnect	= sctp_disconnect,
+	.accept		= sctp_accept,
+	.ioctl		= sctp_ioctl,
+	.init		= sctp_init_sock,
+	.destroy	= sctp_destroy_sock,
+	.shutdown	= sctp_shutdown,
+	.setsockopt	= sctp_setsockopt,
+	.getsockopt	= sctp_getsockopt,
+	.sendmsg	= sctp_sendmsg,
+	.recvmsg	= sctp_recvmsg,
+	.bind		= sctp_bind,
+	.backlog_rcv	= sctp_backlog_rcv,
+	.hash		= sctp_hash,
+	.unhash		= sctp_unhash,
+	.get_port	= sctp_get_port,
+	.slab_obj_size	= sizeof(struct sctp6_sock),
+};
+#endif /* defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) */
diff -Nru a/net/sunrpc/auth_gss/Makefile b/net/sunrpc/auth_gss/Makefile
--- a/net/sunrpc/auth_gss/Makefile	2004-10-18 14:56:29 -07:00
+++ b/net/sunrpc/auth_gss/Makefile	2004-10-18 14:56:29 -07:00
@@ -12,3 +12,7 @@
 rpcsec_gss_krb5-objs := gss_krb5_mech.o gss_krb5_seal.o gss_krb5_unseal.o \
 	gss_krb5_seqnum.o
 
+obj-$(CONFIG_RPCSEC_GSS_SPKM3) += rpcsec_gss_spkm3.o
+
+rpcsec_gss_spkm3-objs := gss_spkm3_mech.o gss_spkm3_seal.o gss_spkm3_unseal.o \
+	gss_spkm3_token.o
diff -Nru a/net/sunrpc/auth_gss/auth_gss.c b/net/sunrpc/auth_gss/auth_gss.c
--- a/net/sunrpc/auth_gss/auth_gss.c	2004-10-18 14:56:29 -07:00
+++ b/net/sunrpc/auth_gss/auth_gss.c	2004-10-18 14:56:29 -07:00
@@ -246,7 +246,7 @@
 	spin_lock_init(&ctx->gc_seq_lock);
 	atomic_set(&ctx->count,1);
 
-	if (simple_get_bytes(&p, end, uid, sizeof(uid)))
+	if (simple_get_bytes(&p, end, uid, sizeof(*uid)))
 		goto err_free_ctx;
 	/* FIXME: discarded timeout for now */
 	if (simple_get_bytes(&p, end, &timeout, sizeof(timeout)))
@@ -397,7 +397,7 @@
 		spin_unlock(&gss_auth->lock);
 	}
 	gss_release_msg(gss_msg);
-	dprintk("RPC: %4u gss_upcall for uid %u result %d", task->tk_pid,
+	dprintk("RPC: %4u gss_upcall for uid %u result %d\n", task->tk_pid,
 			uid, res);
 	return res;
 out_sleep:
diff -Nru a/net/sunrpc/auth_gss/gss_generic_token.c b/net/sunrpc/auth_gss/gss_generic_token.c
--- a/net/sunrpc/auth_gss/gss_generic_token.c	2004-10-18 14:56:28 -07:00
+++ b/net/sunrpc/auth_gss/gss_generic_token.c	2004-10-18 14:56:28 -07:00
@@ -179,7 +179,7 @@
  */
 u32
 g_verify_token_header(struct xdr_netobj *mech, int *body_size,
-		      unsigned char **buf_in, int tok_type, int toksize)
+		      unsigned char **buf_in, int toksize)
 {
 	unsigned char *buf = *buf_in;
 	int seqsize;
diff -Nru a/net/sunrpc/auth_gss/gss_krb5_unseal.c b/net/sunrpc/auth_gss/gss_krb5_unseal.c
--- a/net/sunrpc/auth_gss/gss_krb5_unseal.c	2004-10-18 14:56:49 -07:00
+++ b/net/sunrpc/auth_gss/gss_krb5_unseal.c	2004-10-18 14:56:49 -07:00
@@ -96,7 +96,7 @@
 
 	dprintk("RPC:      krb5_read_token\n");
 
-	if (g_verify_token_header(&ctx->mech_used, &bodysize, &ptr, toktype,
+	if (g_verify_token_header(&ctx->mech_used, &bodysize, &ptr,
 					read_token->len))
 		goto out;
 
diff -Nru a/net/sunrpc/auth_gss/gss_spkm3_mech.c b/net/sunrpc/auth_gss/gss_spkm3_mech.c
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/net/sunrpc/auth_gss/gss_spkm3_mech.c	2004-10-18 14:57:24 -07:00
@@ -0,0 +1,296 @@
+/*
+ *  linux/net/sunrpc/gss_spkm3_mech.c
+ *
+ *  Copyright (c) 2003 The Regents of the University of Michigan.
+ *  All rights reserved.
+ *
+ *  Andy Adamson <andros@umich.edu>
+ *  J. Bruce Fields <bfields@umich.edu>
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions
+ *  are met:
+ *
+ *  1. Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ *  2. Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in the
+ *     documentation and/or other materials provided with the distribution.
+ *  3. Neither the name of the University nor the names of its
+ *     contributors may be used to endorse or promote products derived
+ *     from this software without specific prior written permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ *  WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ *  DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ *  FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ *  CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ *  SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ *  BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ *  LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ *  NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ *  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/types.h>
+#include <linux/slab.h>
+#include <linux/sunrpc/auth.h>
+#include <linux/in.h>
+#include <linux/sunrpc/svcauth_gss.h>
+#include <linux/sunrpc/gss_spkm3.h>
+#include <linux/sunrpc/xdr.h>
+#include <linux/crypto.h>
+
+#ifdef RPC_DEBUG
+# define RPCDBG_FACILITY	RPCDBG_AUTH
+#endif
+
+struct xdr_netobj gss_mech_spkm3_oid =
+   {7, "\053\006\001\005\005\001\003"};
+
+static inline int
+get_bytes(char **ptr, const char *end, void *res, int len)
+{
+	char *p, *q;
+	p = *ptr;
+	q = p + len;
+	if (q > end || q < p)
+		return -1;
+	memcpy(res, p, len);
+	*ptr = q;
+	return 0;
+}
+
+static inline int
+get_netobj(char **ptr, const char *end, struct xdr_netobj *res)
+{
+	char *p, *q;
+	p = *ptr;
+	if (get_bytes(&p, end, &res->len, sizeof(res->len)))
+		return -1;
+	q = p + res->len;
+	if(res->len == 0)
+		goto out_nocopy;
+	if (q > end || q < p)
+		return -1;
+	if (!(res->data = kmalloc(res->len, GFP_KERNEL)))
+		return -1;
+	memcpy(res->data, p, res->len);
+out_nocopy:
+	*ptr = q;
+	return 0;
+}
+
+static inline int
+get_key(char **p, char *end, struct crypto_tfm **res, int *resalg)
+{
+	struct xdr_netobj	key = {
+		.len = 0,
+		.data = NULL,
+	};
+	int			alg_mode,setkey = 0;
+	char			*alg_name;
+
+	if (get_bytes(p, end, resalg, sizeof(int)))
+		goto out_err;
+	if ((get_netobj(p, end, &key)))
+		goto out_err;
+
+	switch (*resalg) {
+		case NID_des_cbc:
+			alg_name = "des";
+			alg_mode = CRYPTO_TFM_MODE_CBC;
+			setkey = 1;
+			break;
+		case NID_md5:
+			if (key.len == 0) {
+				dprintk("RPC: SPKM3 get_key: NID_md5 zero Key length\n");
+			}
+			alg_name = "md5";
+			alg_mode = 0;
+			setkey = 0;
+			break;
+		case NID_cast5_cbc:
+			dprintk("RPC: SPKM3 get_key: case cast5_cbc, UNSUPPORTED \n");
+			goto out_err;
+			break;
+		default:
+			dprintk("RPC: SPKM3 get_key: unsupported algorithm %d", *resalg);
+			goto out_err_free_key;
+	}
+	if (!(*res = crypto_alloc_tfm(alg_name, alg_mode)))
+		goto out_err_free_key;
+	if (setkey) {
+		if (crypto_cipher_setkey(*res, key.data, key.len))
+			goto out_err_free_tfm;
+	}
+
+	if(key.len > 0)
+		kfree(key.data);
+	return 0;
+
+out_err_free_tfm:
+	crypto_free_tfm(*res);
+out_err_free_key:
+	if(key.len > 0)
+		kfree(key.data);
+out_err:
+	return -1;
+}
+
+static u32
+gss_import_sec_context_spkm3(struct xdr_netobj *inbuf,
+				struct gss_ctx *ctx_id)
+{
+	char	*p = inbuf->data;
+	char	*end = inbuf->data + inbuf->len;
+	struct	spkm3_ctx *ctx;
+
+	if (!(ctx = kmalloc(sizeof(*ctx), GFP_KERNEL)))
+		goto out_err;
+	memset(ctx, 0, sizeof(*ctx));
+
+	if (get_netobj(&p, end, &ctx->ctx_id))
+		goto out_err_free_ctx;
+
+	if (get_bytes(&p, end, &ctx->qop, sizeof(ctx->qop)))
+		goto out_err_free_ctx_id;
+
+	if (get_netobj(&p, end, &ctx->mech_used))
+		goto out_err_free_mech;
+
+	if (get_bytes(&p, end, &ctx->ret_flags, sizeof(ctx->ret_flags)))
+		goto out_err_free_mech;
+
+	if (get_bytes(&p, end, &ctx->req_flags, sizeof(ctx->req_flags)))
+		goto out_err_free_mech;
+
+	if (get_netobj(&p, end, &ctx->share_key))
+		goto out_err_free_s_key;
+
+	if (get_key(&p, end, &ctx->derived_conf_key, &ctx->conf_alg)) {
+		dprintk("RPC: SPKM3 confidentiality key will be NULL\n");
+	}
+
+	if (get_key(&p, end, &ctx->derived_integ_key, &ctx->intg_alg)) {
+		dprintk("RPC: SPKM3 integrity key will be NULL\n");
+	}
+
+	if (get_bytes(&p, end, &ctx->owf_alg, sizeof(ctx->owf_alg)))
+		goto out_err_free_s_key;
+
+	if (get_bytes(&p, end, &ctx->owf_alg, sizeof(ctx->owf_alg)))
+		goto out_err_free_s_key;
+
+	if (p != end)
+		goto out_err_free_s_key;
+
+	ctx_id->internal_ctx_id = ctx;
+
+	dprintk("Succesfully imported new spkm context.\n");
+	return 0;
+
+out_err_free_s_key:
+	kfree(ctx->share_key.data);
+out_err_free_mech:
+	kfree(ctx->mech_used.data);
+out_err_free_ctx_id:
+	kfree(ctx->ctx_id.data);
+out_err_free_ctx:
+	kfree(ctx);
+out_err:
+	return GSS_S_FAILURE;
+}
+
+void
+gss_delete_sec_context_spkm3(void *internal_ctx) {
+	struct spkm3_ctx *sctx = internal_ctx;
+
+	if(sctx->derived_integ_key)
+		crypto_free_tfm(sctx->derived_integ_key);
+	if(sctx->derived_conf_key)
+		crypto_free_tfm(sctx->derived_conf_key);
+	if(sctx->share_key.data)
+		kfree(sctx->share_key.data);
+	if(sctx->mech_used.data)
+		kfree(sctx->mech_used.data);
+	kfree(sctx);
+}
+
+u32
+gss_verify_mic_spkm3(struct gss_ctx		*ctx,
+			struct xdr_buf		*signbuf,
+			struct xdr_netobj	*checksum,
+			u32		*qstate) {
+	u32 maj_stat = 0;
+	int qop_state = 0;
+	struct spkm3_ctx *sctx = ctx->internal_ctx_id;
+
+	dprintk("RPC: gss_verify_mic_spkm3 calling spkm3_read_token\n");
+	maj_stat = spkm3_read_token(sctx, checksum, signbuf, &qop_state,
+				   SPKM_MIC_TOK);
+
+	if (!maj_stat && qop_state)
+	    *qstate = qop_state;
+
+	dprintk("RPC: gss_verify_mic_spkm3 returning %d\n", maj_stat);
+	return maj_stat;
+}
+
+u32
+gss_get_mic_spkm3(struct gss_ctx	*ctx,
+		     u32		qop,
+		     struct xdr_buf	*message_buffer,
+		     struct xdr_netobj	*message_token) {
+	u32 err = 0;
+	struct spkm3_ctx *sctx = ctx->internal_ctx_id;
+
+	dprintk("RPC: gss_get_mic_spkm3\n");
+
+	err = spkm3_make_token(sctx, qop, message_buffer,
+			      message_token, SPKM_MIC_TOK);
+	return err;
+}
+
+static struct gss_api_ops gss_spkm3_ops = {
+	.gss_import_sec_context	= gss_import_sec_context_spkm3,
+	.gss_get_mic		= gss_get_mic_spkm3,
+	.gss_verify_mic		= gss_verify_mic_spkm3,
+	.gss_delete_sec_context	= gss_delete_sec_context_spkm3,
+};
+
+static struct pf_desc gss_spkm3_pfs[] = {
+	{RPC_AUTH_GSS_SPKM, 0, RPC_GSS_SVC_NONE, "spkm3"},
+	{RPC_AUTH_GSS_SPKMI, 0, RPC_GSS_SVC_INTEGRITY, "spkm3i"},
+};
+
+static struct gss_api_mech gss_spkm3_mech = {
+	.gm_name	= "spkm3",
+	.gm_owner	= THIS_MODULE,
+	.gm_ops		= &gss_spkm3_ops,
+	.gm_pf_num	= ARRAY_SIZE(gss_spkm3_pfs),
+	.gm_pfs		= gss_spkm3_pfs,
+};
+
+static int __init init_spkm3_module(void)
+{
+	int status;
+
+	status = gss_mech_register(&gss_spkm3_mech);
+	if (status)
+		printk("Failed to register spkm3 gss mechanism!\n");
+	return 0;
+}
+
+static void __exit cleanup_spkm3_module(void)
+{
+	gss_mech_unregister(&gss_spkm3_mech);
+}
+
+MODULE_LICENSE("GPL");
+module_init(init_spkm3_module);
+module_exit(cleanup_spkm3_module);
diff -Nru a/net/sunrpc/auth_gss/gss_spkm3_seal.c b/net/sunrpc/auth_gss/gss_spkm3_seal.c
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/net/sunrpc/auth_gss/gss_spkm3_seal.c	2004-10-18 14:57:23 -07:00
@@ -0,0 +1,132 @@
+/*
+ *  linux/net/sunrpc/gss_spkm3_seal.c
+ *
+ *  Copyright (c) 2003 The Regents of the University of Michigan.
+ *  All rights reserved.
+ *
+ *  Andy Adamson <andros@umich.edu>
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions
+ *  are met:
+ *
+ *  1. Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ *  2. Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in the
+ *     documentation and/or other materials provided with the distribution.
+ *  3. Neither the name of the University nor the names of its
+ *     contributors may be used to endorse or promote products derived
+ *     from this software without specific prior written permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ *  WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ *  DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ *  FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ *  CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ *  SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ *  BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ *  LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ *  NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ *  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#include <linux/types.h>
+#include <linux/slab.h>
+#include <linux/jiffies.h>
+#include <linux/sunrpc/gss_spkm3.h>
+#include <linux/random.h>
+#include <linux/crypto.h>
+
+#ifdef RPC_DEBUG
+# define RPCDBG_FACILITY        RPCDBG_AUTH
+#endif
+
+/*
+ * spkm3_make_token()
+ *
+ * Only SPKM_MIC_TOK with md5 intg-alg is supported
+ */
+
+u32
+spkm3_make_token(struct spkm3_ctx *ctx, int qop_req,
+		   struct xdr_buf * text, struct xdr_netobj * token,
+		   int toktype)
+{
+	s32			checksum_type;
+	char			tokhdrbuf[25];
+	struct xdr_netobj	md5cksum = {.len = 0, .data = NULL};
+	struct xdr_netobj	mic_hdr = {.len = 0, .data = tokhdrbuf};
+	int			tmsglen, tokenlen = 0;
+	unsigned char		*ptr;
+	s32			now;
+	int			ctxelen = 0, ctxzbit = 0;
+	int			md5elen = 0, md5zbit = 0;
+
+	dprintk("RPC: spkm3_make_token\n");
+
+	now = jiffies;
+	if (qop_req != 0)
+		goto out_err;
+
+	if (ctx->ctx_id.len != 16) {
+		dprintk("RPC: spkm3_make_token BAD ctx_id.len %d\n",
+			ctx->ctx_id.len);
+		goto out_err;
+	}
+		
+	switch (ctx->intg_alg) {
+		case NID_md5:
+			checksum_type = CKSUMTYPE_RSA_MD5;
+			break;
+		default:
+			dprintk("RPC: gss_spkm3_seal: ctx->signalg %d not"
+				" supported\n", ctx->intg_alg);
+			goto out_err;
+	}
+	/* XXX since we don't support WRAP, perhaps we don't care... */
+	if (ctx->conf_alg != NID_cast5_cbc) {
+		dprintk("RPC: gss_spkm3_seal: ctx->sealalg %d not supported\n",
+			ctx->conf_alg);
+		goto out_err;
+	}
+
+	if (toktype == SPKM_MIC_TOK) {
+		tmsglen = 0;
+		/* Calculate checksum over the mic-header */
+		asn1_bitstring_len(&ctx->ctx_id, &ctxelen, &ctxzbit);
+		spkm3_mic_header(&mic_hdr.data, &mic_hdr.len, ctx->ctx_id.data,
+		                         ctxelen, ctxzbit);
+
+		if (make_checksum(checksum_type, mic_hdr.data, mic_hdr.len, 
+		                             text, &md5cksum))
+			goto out_err;
+
+		asn1_bitstring_len(&md5cksum, &md5elen, &md5zbit);
+		tokenlen = 10 + ctxelen + 1 + 2 + md5elen + 1;
+
+		/* Create token header using generic routines */
+		token->len = g_token_size(&ctx->mech_used, tokenlen + tmsglen);
+
+		ptr = token->data;
+		g_make_token_header(&ctx->mech_used, tokenlen + tmsglen, &ptr);
+
+		spkm3_make_mic_token(&ptr, tokenlen, &mic_hdr, &md5cksum, md5elen, md5zbit);
+	} else if (toktype == SPKM_WRAP_TOK) { /* Not Supported */
+		dprintk("RPC: gss_spkm3_seal: SPKM_WRAP_TOK not supported\n");
+		goto out_err;
+	}
+	kfree(md5cksum.data);
+
+	/* XXX need to implement sequence numbers, and ctx->expired */
+
+	return  GSS_S_COMPLETE;
+out_err:
+	if (md5cksum.data) 
+		kfree(md5cksum.data);
+	token->data = NULL;
+	token->len = 0;
+	return GSS_S_FAILURE;
+}
diff -Nru a/net/sunrpc/auth_gss/gss_spkm3_token.c b/net/sunrpc/auth_gss/gss_spkm3_token.c
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/net/sunrpc/auth_gss/gss_spkm3_token.c	2004-10-18 14:57:24 -07:00
@@ -0,0 +1,266 @@
+/*
+ *  linux/net/sunrpc/gss_spkm3_token.c
+ *
+ *  Copyright (c) 2003 The Regents of the University of Michigan.
+ *  All rights reserved.
+ *
+ *  Andy Adamson <andros@umich.edu>
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions
+ *  are met:
+ *
+ *  1. Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ *  2. Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in the
+ *     documentation and/or other materials provided with the distribution.
+ *  3. Neither the name of the University nor the names of its
+ *     contributors may be used to endorse or promote products derived
+ *     from this software without specific prior written permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ *  WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ *  DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ *  FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ *  CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ *  SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ *  BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ *  LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ *  NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ *  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#include <linux/types.h>
+#include <linux/slab.h>
+#include <linux/jiffies.h>
+#include <linux/sunrpc/gss_spkm3.h>
+#include <linux/random.h>
+#include <linux/crypto.h>
+
+#ifdef RPC_DEBUG
+# define RPCDBG_FACILITY        RPCDBG_AUTH
+#endif
+
+/*
+ * asn1_bitstring_len()
+ *
+ * calculate the asn1 bitstring length of the xdr_netobject
+ */
+void
+asn1_bitstring_len(struct xdr_netobj *in, int *enclen, int *zerobits)
+{
+	int i, zbit = 0,elen = in->len;
+	char *ptr;
+
+	ptr = &in->data[in->len -1];
+
+	/* count trailing 0's */
+	for(i = in->len; i > 0; i--) {
+		if (*ptr == 0) { 
+			ptr--;
+			elen--;
+		} else
+			break;
+	}
+
+	/* count number of 0 bits in final octet */
+	ptr = &in->data[elen - 1];
+	for(i = 0; i < 8; i++) {
+		short mask = 0x01;
+
+		if (!((mask << i) & *ptr))
+			zbit++;
+		else
+			break;
+	}
+	*enclen = elen;
+	*zerobits = zbit;
+}
+
+/*
+ * decode_asn1_bitstring()
+ * 
+ * decode a bitstring into a buffer of the expected length.
+ * enclen = bit string length
+ * explen = expected length (define in rfc)
+ */
+int
+decode_asn1_bitstring(struct xdr_netobj *out, char *in, int enclen, int explen)
+{
+	if (!(out->data = kmalloc(explen,GFP_KERNEL)))
+		return 0;
+	out->len = explen;
+	memset(out->data, 0, explen);
+	memcpy(out->data, in, enclen);
+	return 1;
+}
+
+/* 
+ * SPKMInnerContextToken choice SPKM_MIC asn1 token layout
+ * 
+ * contextid is always 16 bytes plain data. max asn1 bitstring len = 17.
+ *
+ * tokenlen = pos[0] to end of token (max pos[45] with MD5 cksum)
+ *
+ * pos  value
+ * ----------
+ * [0]	a4  SPKM-MIC tag
+ * [1]	??  innertoken length  (max 44) 
+ * 
+ * 
+ * tok_hdr piece of checksum data starts here 
+ *
+ * the maximum mic-header len = 9 + 17 = 26 
+ *	mic-header
+ *	----------
+ * [2]	30      SEQUENCE tag  
+ * [3]	??	mic-header length: (max 23) = TokenID + ContextID 
+ *
+ *		TokenID  - all fields constant and can be hardcoded
+ *		-------
+ * [4]	  02	Type 2
+ * [5]	  02	Length 2 
+ * [6][7] 01 01	TokenID (SPKM_MIC_TOK)
+ *
+ *		ContextID  - encoded length not constant, calculated
+ *		---------
+ * [8]	03	Type 3
+ * [9]	??	encoded length
+ * [10]	??	ctxzbit
+ * [11]	 	contextid
+ *
+ * mic_header piece of checksum data ends here. 
+ *
+ *	int-cksum - encoded length not constant, calculated
+ *	---------
+ * [??]	03	Type 3
+ * [??]	??	encoded length 
+ * [??]	??	md5zbit		
+ * [??]	 	int-cksum (NID_md5 = 16)
+ *
+ * maximum SPKM-MIC innercontext token length = 
+ *	 10 + encoded contextid_size(17 max) + 2 + encoded  
+ *       cksum_size (17 maxfor NID_md5) = 46
+ */
+
+/*
+ * spkm3_mic_header()
+ *
+ * Prepare the SPKM_MIC_TOK mic-header for check-sum calculation
+ * elen: 16 byte context id asn1 bitstring encoded length
+ */
+void
+spkm3_mic_header(unsigned char **hdrbuf, unsigned int *hdrlen, unsigned char *ctxdata, int elen, int zbit)
+{
+	char *hptr = *hdrbuf;
+	char *top = *hdrbuf;
+
+	*(u8 *)hptr++ = 0x30;
+	*(u8 *)hptr++ = elen + 7;  /* on the wire header length */
+
+	/* tokenid */
+	*(u8 *)hptr++ = 0x02;
+	*(u8 *)hptr++ = 0x02;
+	*(u8 *)hptr++ = 0x01;
+	*(u8 *)hptr++ = 0x01;
+
+	/* coniextid */
+	*(u8 *)hptr++ = 0x03;
+	*(u8 *)hptr++ = elen + 1; /* add 1 to include zbit */
+	*(u8 *)hptr++ = zbit;
+	memcpy(hptr, ctxdata, elen);
+	hptr += elen;
+	*hdrlen = hptr - top; 
+}
+		
+/* 
+ * spkm3_mic_innercontext_token()
+ *
+ * *tokp points to the beginning of the SPKM_MIC token  described 
+ * in rfc 2025, section 3.2.1: 
+ *
+ */
+void
+spkm3_make_mic_token(unsigned char **tokp, int toklen, struct xdr_netobj *mic_hdr, struct xdr_netobj *md5cksum, int md5elen, int md5zbit)
+{
+	unsigned char *ict = *tokp;
+
+	*(u8 *)ict++ = 0xa4;
+	*(u8 *)ict++ = toklen - 2; 
+	memcpy(ict, mic_hdr->data, mic_hdr->len);
+	ict += mic_hdr->len;
+
+	*(u8 *)ict++ = 0x03;
+	*(u8 *)ict++ = md5elen + 1; /* add 1 to include zbit */
+	*(u8 *)ict++ = md5zbit;
+	memcpy(ict, md5cksum->data, md5elen);
+}
+
+u32
+spkm3_verify_mic_token(unsigned char **tokp, int *mic_hdrlen, unsigned char **cksum)
+{
+	struct xdr_netobj       spkm3_ctx_id = {.len =0, .data = NULL};
+	unsigned char 		*ptr = *tokp;
+	int 			ctxelen;
+	u32     		ret = GSS_S_DEFECTIVE_TOKEN;
+
+	/* spkm3 innercontext token preamble */
+	if ((ptr[0] != 0xa4) || (ptr[2] != 0x30)) {
+		dprintk("RPC: BAD SPKM ictoken preamble\n"); 
+		goto out;
+	}
+
+	*mic_hdrlen = ptr[3];
+
+	/* token type */
+	if ((ptr[4] != 0x02) || (ptr[5] != 0x02)) {
+		dprintk("RPC: BAD asn1 SPKM3 token type\n");
+		goto out;
+	}
+
+	/* only support SPKM_MIC_TOK */
+	if((ptr[6] != 0x01) || (ptr[7] != 0x01)) {
+		dprintk("RPC: ERROR unsupported SPKM3 token \n");
+		goto out;
+	}
+
+	/* contextid */
+	if (ptr[8] != 0x03) {
+		dprintk("RPC: BAD SPKM3 asn1 context-id type\n");
+		goto out;
+	}
+
+	ctxelen = ptr[9];
+	if (ctxelen > 17) {  /* length includes asn1 zbit octet */
+		dprintk("RPC: BAD SPKM3 contextid len %d\n", ctxelen);
+		goto out;
+	}
+
+	/* ignore ptr[10] */
+
+	if(!decode_asn1_bitstring(&spkm3_ctx_id, &ptr[11], ctxelen - 1, 16))
+		goto out;
+
+	/*
+	* in the current implementation: the optional int-alg is not present 
+	* so the default int-alg (md5) is used the optional snd-seq field is 
+	* also not present 
+	*/
+
+	if (*mic_hdrlen != 6 + ctxelen) {
+		dprintk("RPC: BAD SPKM_ MIC_TOK header len %d: we only support default int-alg (should be absent) and do not support snd-seq\n", *mic_hdrlen);
+		goto out;
+	}
+	/* checksum */
+        *cksum = (&ptr[10] + ctxelen); /* ctxelen includes ptr[10] */
+
+	ret = GSS_S_COMPLETE;
+out:
+	if (spkm3_ctx_id.data)
+		kfree(spkm3_ctx_id.data);
+	return ret;
+}
+
diff -Nru a/net/sunrpc/auth_gss/gss_spkm3_unseal.c b/net/sunrpc/auth_gss/gss_spkm3_unseal.c
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/net/sunrpc/auth_gss/gss_spkm3_unseal.c	2004-10-18 14:57:24 -07:00
@@ -0,0 +1,128 @@
+/*
+ *  linux/net/sunrpc/gss_spkm3_unseal.c
+ *
+ *  Copyright (c) 2003 The Regents of the University of Michigan.
+ *  All rights reserved.
+ *
+ *  Andy Adamson <andros@umich.edu>
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions
+ *  are met:
+ *
+ *  1. Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ *  2. Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in the
+ *     documentation and/or other materials provided with the distribution.
+ *  3. Neither the name of the University nor the names of its
+ *     contributors may be used to endorse or promote products derived
+ *     from this software without specific prior written permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ *  WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ *  DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ *  FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ *  CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ *  SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ *  BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ *  LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ *  NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ *  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#include <linux/types.h>
+#include <linux/slab.h>
+#include <linux/jiffies.h>
+#include <linux/sunrpc/gss_spkm3.h>
+#include <linux/crypto.h>
+
+#ifdef RPC_DEBUG
+# define RPCDBG_FACILITY        RPCDBG_AUTH
+#endif
+
+/*
+ * spkm3_read_token()
+ * 
+ * only SPKM_MIC_TOK with md5 intg-alg is supported
+ */
+u32
+spkm3_read_token(struct spkm3_ctx *ctx,
+		struct xdr_netobj *read_token,    /* checksum */
+		struct xdr_buf *message_buffer, /* signbuf */
+		int *qop_state, int toktype)
+{
+	s32			code;
+	struct xdr_netobj	wire_cksum = {.len =0, .data = NULL};
+	struct xdr_netobj	md5cksum = {.len = 0, .data = NULL};
+	unsigned char		*ptr = (unsigned char *)read_token->data;
+	unsigned char           *cksum;
+	int			bodysize, md5elen;
+	int			mic_hdrlen;
+	u32			ret = GSS_S_DEFECTIVE_TOKEN;
+
+	dprintk("RPC: spkm3_read_token read_token->len %d\n", read_token->len);
+
+	if (g_verify_token_header((struct xdr_netobj *) &ctx->mech_used,
+					&bodysize, &ptr, read_token->len))
+		goto out;
+
+	/* decode the token */
+
+	if (toktype == SPKM_MIC_TOK) {
+
+		if ((ret = spkm3_verify_mic_token(&ptr, &mic_hdrlen, &cksum))) 
+			goto out;
+
+		if (*cksum++ != 0x03) {
+			dprintk("RPC: spkm3_read_token BAD checksum type\n");
+			goto out;
+		}
+		md5elen = *cksum++; 
+		cksum++; 	/* move past the zbit */
+	
+		if(!decode_asn1_bitstring(&wire_cksum, cksum, md5elen - 1, 16))
+			goto out;
+
+		/* HARD CODED FOR MD5 */
+
+		/* compute the checksum of the message.
+		*  ptr + 2 = start of header piece of checksum
+		*  mic_hdrlen + 2 = length of header piece of checksum
+		*/
+		ret = GSS_S_DEFECTIVE_TOKEN;
+		code = make_checksum(CKSUMTYPE_RSA_MD5, ptr + 2, 
+					mic_hdrlen + 2, 
+		                        message_buffer, &md5cksum);
+
+		if (code)
+			goto out;
+
+		dprintk("RPC: spkm3_read_token: digest wire_cksum.len %d:\n", 
+			wire_cksum.len);
+		dprintk("          md5cksum.data\n");
+		print_hexl((u32 *) md5cksum.data, 16, 0);
+		dprintk("          cksum.data:\n");
+		print_hexl((u32 *) wire_cksum.data, wire_cksum.len, 0);
+
+		ret = GSS_S_BAD_SIG;
+		code = memcmp(md5cksum.data, wire_cksum.data, wire_cksum.len);
+		if (code)
+			goto out;
+
+	} else { 
+		dprintk("RPC: BAD or UNSUPPORTED SPKM3 token type: %d\n",toktype);
+		goto out;
+	}
+
+	/* XXX: need to add expiration and sequencing */
+	ret = GSS_S_COMPLETE;
+out:
+	if (md5cksum.data) 
+		kfree(md5cksum.data);
+	if (wire_cksum.data) 
+		kfree(wire_cksum.data);
+	return ret;
+}
diff -Nru a/net/sunrpc/auth_gss/svcauth_gss.c b/net/sunrpc/auth_gss/svcauth_gss.c
--- a/net/sunrpc/auth_gss/svcauth_gss.c	2004-10-18 14:56:29 -07:00
+++ b/net/sunrpc/auth_gss/svcauth_gss.c	2004-10-18 14:56:29 -07:00
@@ -643,7 +643,6 @@
 	if (!new)
 		goto out;
 	cache_init(&new->h.h);
-	atomic_inc(&new->h.h.refcnt);
 	new->h.name = kmalloc(strlen(name) + 1, GFP_KERNEL);
 	if (!new->h.name)
 		goto out_free_dom;
@@ -651,7 +650,6 @@
 	new->h.flavour = RPC_AUTH_GSS;
 	new->pseudoflavor = pseudoflavor;
 	new->h.h.expiry_time = NEVER;
-	new->h.h.flags = 0;
 
 	test = auth_domain_lookup(&new->h, 1);
 	if (test == &new->h) {
diff -Nru a/net/sunrpc/cache.c b/net/sunrpc/cache.c
--- a/net/sunrpc/cache.c	2004-10-18 14:56:33 -07:00
+++ b/net/sunrpc/cache.c	2004-10-18 14:56:33 -07:00
@@ -38,7 +38,7 @@
 	time_t now = get_seconds();
 	h->next = NULL;
 	h->flags = 0;
-	atomic_set(&h->refcnt, 0);
+	atomic_set(&h->refcnt, 1);
 	h->expiry_time = now + CACHE_NEW_EXPIRY;
 	h->last_refresh = now;
 }
@@ -400,9 +400,10 @@
 
 void cache_purge(struct cache_detail *detail)
 {
-	detail->flush_time = get_seconds()+1;
+	detail->flush_time = LONG_MAX;
 	detail->nextcheck = get_seconds();
 	cache_flush();
+	detail->flush_time = 1;
 }
 
 
diff -Nru a/net/sunrpc/clnt.c b/net/sunrpc/clnt.c
--- a/net/sunrpc/clnt.c	2004-10-18 14:56:28 -07:00
+++ b/net/sunrpc/clnt.c	2004-10-18 14:56:28 -07:00
@@ -196,7 +196,15 @@
 	memcpy(new, clnt, sizeof(*new));
 	atomic_set(&new->cl_count, 1);
 	atomic_set(&new->cl_users, 0);
-	atomic_inc(&new->cl_parent->cl_count);
+	new->cl_parent = clnt;
+	atomic_inc(&clnt->cl_count);
+	/* Duplicate portmapper */
+	rpc_init_wait_queue(&new->cl_pmap_default.pm_bindwait, "bindwait");
+	/* Turn off autobind on clones */
+	new->cl_autobind = 0;
+	new->cl_oneshot = 0;
+	new->cl_dead = 0;
+	rpc_init_rtt(&new->cl_rtt_default, clnt->cl_xprt->timeout.to_initval);
 	if (new->cl_auth)
 		atomic_inc(&new->cl_auth->au_count);
 	return new;
@@ -335,7 +343,7 @@
  */
 int rpc_call_sync(struct rpc_clnt *clnt, struct rpc_message *msg, int flags)
 {
-	struct rpc_task	my_task, *task = &my_task;
+	struct rpc_task	*task;
 	sigset_t	oldset;
 	int		status;
 
@@ -343,15 +351,15 @@
 	if (clnt->cl_dead) 
 		return -EIO;
 
-	if (flags & RPC_TASK_ASYNC) {
-		printk("rpc_call_sync: Illegal flag combination for synchronous task\n");
-		flags &= ~RPC_TASK_ASYNC;
-	}
+	BUG_ON(flags & RPC_TASK_ASYNC);
 
 	rpc_clnt_sigmask(clnt, &oldset);		
 
-	/* Create/initialize a new RPC task */
-	rpc_init_task(task, clnt, NULL, flags);
+	status = -ENOMEM;
+	task = rpc_new_task(clnt, NULL, flags);
+	if (task == NULL)
+		goto out;
+
 	rpc_call_setup(task, msg, 0);
 
 	/* Set up the call info struct and execute the task */
@@ -362,6 +370,7 @@
 		rpc_release_task(task);
 	}
 
+out:
 	rpc_clnt_sigunmask(clnt, &oldset);		
 
 	return status;
@@ -958,8 +967,12 @@
 static u32 *
 call_verify(struct rpc_task *task)
 {
-	u32	*p = task->tk_rqstp->rq_rcv_buf.head[0].iov_base, n;
+	struct kvec *iov = &task->tk_rqstp->rq_rcv_buf.head[0];
+	int len = task->tk_rqstp->rq_rcv_buf.len >> 2;
+	u32	*p = iov->iov_base, n;
 
+	if ((len -= 3) < 0)
+		goto garbage;
 	p += 1;	/* skip XID */
 
 	if ((n = ntohl(*p++)) != RPC_REPLY) {
@@ -969,9 +982,11 @@
 	if ((n = ntohl(*p++)) != RPC_MSG_ACCEPTED) {
 		int	error = -EACCES;
 
+		if (--len < 0)
+			goto garbage;
 		if ((n = ntohl(*p++)) != RPC_AUTH_ERROR) {
 			printk(KERN_WARNING "call_verify: RPC call rejected: %x\n", n);
-		} else
+		} else if (--len < 0)
 		switch ((n = ntohl(*p++))) {
 		case RPC_AUTH_REJECTEDCRED:
 		case RPC_AUTH_REJECTEDVERF:
@@ -1002,7 +1017,8 @@
 		default:
 			printk(KERN_WARNING "call_verify: unknown auth error: %x\n", n);
 			error = -EIO;
-		}
+		} else
+			goto garbage;
 		dprintk("RPC: %4d call_verify: call rejected %d\n",
 						task->tk_pid, n);
 		rpc_exit(task, error);
@@ -1012,6 +1028,9 @@
 		printk(KERN_WARNING "call_verify: auth check failed\n");
 		goto garbage;		/* bad verifier, retry */
 	}
+	len = p - (u32 *)iov->iov_base - 1;
+	if (len < 0)
+		goto garbage;
 	switch ((n = ntohl(*p++))) {
 	case RPC_SUCCESS:
 		return p;
diff -Nru a/net/sunrpc/sched.c b/net/sunrpc/sched.c
--- a/net/sunrpc/sched.c	2004-10-18 14:56:32 -07:00
+++ b/net/sunrpc/sched.c	2004-10-18 14:56:32 -07:00
@@ -698,7 +698,7 @@
 		if (current->pid == rpciod_pid)
 			printk(KERN_ERR "RPC: rpciod waiting on sync task!\n");
 
-		if (!task->tk_client->cl_intr) {
+		if (RPC_TASK_UNINTERRUPTIBLE(task)) {
 			__wait_event(task->tk_wait, !RPC_IS_SLEEPING(task));
 		} else {
 			__wait_event_interruptible(task->tk_wait, !RPC_IS_SLEEPING(task), status);
@@ -884,6 +884,8 @@
 		atomic_inc(&clnt->cl_users);
 		if (clnt->cl_softrtry)
 			task->tk_flags |= RPC_TASK_SOFT;
+		if (!clnt->cl_intr)
+			task->tk_flags |= RPC_TASK_NOINTR;
 	}
 
 #ifdef RPC_DEBUG
diff -Nru a/net/sunrpc/sunrpc_syms.c b/net/sunrpc/sunrpc_syms.c
--- a/net/sunrpc/sunrpc_syms.c	2004-10-18 14:56:50 -07:00
+++ b/net/sunrpc/sunrpc_syms.c	2004-10-18 14:56:50 -07:00
@@ -89,6 +89,7 @@
 EXPORT_SYMBOL(svc_reserve);
 EXPORT_SYMBOL(svc_auth_register);
 EXPORT_SYMBOL(auth_domain_lookup);
+EXPORT_SYMBOL(svc_authenticate);
 
 /* RPC statistics */
 #ifdef CONFIG_PROC_FS
diff -Nru a/net/sunrpc/svc.c b/net/sunrpc/svc.c
--- a/net/sunrpc/svc.c	2004-10-18 14:57:03 -07:00
+++ b/net/sunrpc/svc.c	2004-10-18 14:57:03 -07:00
@@ -263,6 +263,7 @@
 	u32			*statp;
 	u32			dir, prog, vers, proc,
 				auth_stat, rpc_stat;
+	int			auth_res;
 
 	rpc_stat = rpc_success;
 
@@ -304,12 +305,17 @@
 	rqstp->rq_vers = vers = ntohl(svc_getu32(argv));	/* version number */
 	rqstp->rq_proc = proc = ntohl(svc_getu32(argv));	/* procedure number */
 
+	progp = serv->sv_program;
 	/*
 	 * Decode auth data, and add verifier to reply buffer.
 	 * We do this before anything else in order to get a decent
 	 * auth verifier.
 	 */
-	switch (svc_authenticate(rqstp, &auth_stat)) {
+	if (progp->pg_authenticate != NULL)
+		auth_res = progp->pg_authenticate(rqstp, &auth_stat);
+	else
+		auth_res = svc_authenticate(rqstp, &auth_stat);
+	switch (auth_res) {
 	case SVC_OK:
 		break;
 	case SVC_GARBAGE:
@@ -326,7 +332,6 @@
 		goto sendit;
 	}
 		
-	progp = serv->sv_program;
 	if (prog != progp->pg_prog)
 		goto err_bad_prog;
 
diff -Nru a/net/sunrpc/svcauth.c b/net/sunrpc/svcauth.c
--- a/net/sunrpc/svcauth.c	2004-10-18 14:56:49 -07:00
+++ b/net/sunrpc/svcauth.c	2004-10-18 14:56:49 -07:00
@@ -156,25 +156,49 @@
 {
 	return strcmp(tmp->name, item->name) == 0;
 }
-DefineCacheLookup(struct auth_domain,
-		  h,
-		  auth_domain_lookup,
-		  (struct auth_domain *item, int set),
-		  /* no setup */,
-		  &auth_domain_cache,
-		  auth_domain_hash(item),
-		  auth_domain_match(tmp, item),
-		  kfree(new); if(!set) {
-			if (new)
-				write_unlock(&auth_domain_cache.hash_lock);
-			else
-				read_unlock(&auth_domain_cache.hash_lock);
-			return NULL;
-		  }
-		  new=item; atomic_inc(&new->h.refcnt),
-		  /* no update */,
-		  0 /* no inplace updates */
-		  )
+
+struct auth_domain *
+auth_domain_lookup(struct auth_domain *item, int set)
+{
+	struct auth_domain *tmp = NULL;
+	struct cache_head **hp, **head;
+	head = &auth_domain_cache.hash_table[auth_domain_hash(item)];
+
+	if (set)
+		write_lock(&auth_domain_cache.hash_lock);
+	else
+		read_lock(&auth_domain_cache.hash_lock);
+	for (hp=head; *hp != NULL; hp = &tmp->h.next) {
+		tmp = container_of(*hp, struct auth_domain, h);
+		if (!auth_domain_match(tmp, item))
+			continue;
+		cache_get(&tmp->h);
+		if (!set)
+			goto out_noset;
+		*hp = tmp->h.next;
+		tmp->h.next = NULL;
+		clear_bit(CACHE_HASHED, &tmp->h.flags);
+		auth_domain_drop(&tmp->h, &auth_domain_cache);
+		goto out_set;
+	}
+	/* Didn't find anything */
+	if (!set)
+		goto out_nada;
+	auth_domain_cache.entries++;
+out_set:
+	set_bit(CACHE_HASHED, &item->h.flags);
+	item->h.next = *head;
+	*head = &item->h;
+	write_unlock(&auth_domain_cache.hash_lock);
+	cache_fresh(&auth_domain_cache, &item->h, item->h.expiry_time);
+	cache_get(&item->h);
+	return item;
+out_nada:
+	tmp = NULL;
+out_noset:
+	read_unlock(&auth_domain_cache.hash_lock);
+	return tmp;
+}
 
 struct auth_domain *auth_domain_find(char *name)
 {
diff -Nru a/net/sunrpc/svcauth_unix.c b/net/sunrpc/svcauth_unix.c
--- a/net/sunrpc/svcauth_unix.c	2004-10-18 14:56:33 -07:00
+++ b/net/sunrpc/svcauth_unix.c	2004-10-18 14:56:33 -07:00
@@ -55,12 +55,10 @@
 	if (new == NULL)
 		return NULL;
 	cache_init(&new->h.h);
-	atomic_inc(&new->h.h.refcnt);
 	new->h.name = strdup(name);
 	new->h.flavour = RPC_AUTH_UNIX;
 	new->addr_changes = 0;
 	new->h.h.expiry_time = NEVER;
-	new->h.h.flags = 0;
 
 	rv = auth_domain_lookup(&new->h, 2);
 	if (rv == &new->h) {
@@ -92,7 +90,7 @@
 
 struct ip_map {
 	struct cache_head	h;
-	char			*m_class; /* e.g. "nfsd" */
+	char			m_class[8]; /* e.g. "nfsd" */
 	struct in_addr		m_addr;
 	struct unix_domain	*m_client;
 	int			m_add_change;
@@ -122,8 +120,7 @@
 }
 static inline void ip_map_init(struct ip_map *new, struct ip_map *item)
 {
-	new->m_class = item->m_class;
-	item->m_class = NULL;
+	strcpy(new->m_class, item->m_class);
 	new->m_addr.s_addr = item->m_addr.s_addr;
 }
 static inline void ip_map_update(struct ip_map *new, struct ip_map *item)
@@ -172,6 +169,8 @@
 	/* class */
 	len = qword_get(&mesg, class, 50);
 	if (len <= 0) return -EINVAL;
+	if (len >= sizeof(ipm.m_class))
+		return -EINVAL;
 
 	/* ip address */
 	len = qword_get(&mesg, buf, 50);
@@ -195,9 +194,7 @@
 	} else
 		dom = NULL;
 
-	ipm.m_class = strdup(class);
-	if (ipm.m_class == NULL)
-		return -ENOMEM;
+	strcpy(ipm.m_class, class);
 	ipm.m_addr.s_addr =
 		htonl((((((b1<<8)|b2)<<8)|b3)<<8)|b4);
 	ipm.h.flags = 0;
@@ -213,7 +210,6 @@
 		ip_map_put(&ipmp->h, &ip_map_cache);
 	if (dom)
 		auth_domain_put(dom);
-	if (ipm.m_class) kfree(ipm.m_class);
 	if (!ipmp)
 		return -ENOMEM;
 	cache_flush();
@@ -273,9 +269,7 @@
 	if (dom->flavour != RPC_AUTH_UNIX)
 		return -EINVAL;
 	udom = container_of(dom, struct unix_domain, h);
-	ip.m_class = strdup("nfsd");
-	if (!ip.m_class)
-		return -ENOMEM;
+	strcpy(ip.m_class, "nfsd");
 	ip.m_addr = addr;
 	ip.m_client = udom;
 	ip.m_add_change = udom->addr_changes+1;
@@ -283,7 +277,7 @@
 	ip.h.expiry_time = NEVER;
 	
 	ipmp = ip_map_lookup(&ip, 1);
-	if (ip.m_class) kfree(ip.m_class);
+
 	if (ipmp) {
 		ip_map_put(&ipmp->h, &ip_map_cache);
 		return 0;
@@ -307,7 +301,7 @@
 	struct ip_map key, *ipm;
 	struct auth_domain *rv;
 
-	key.m_class = "nfsd";
+	strcpy(key.m_class, "nfsd");
 	key.m_addr = addr;
 
 	ipm = ip_map_lookup(&key, 0);
@@ -318,7 +312,8 @@
 		return NULL;
 
 	if ((ipm->m_client->addr_changes - ipm->m_add_change) >0) {
-		set_bit(CACHE_NEGATIVE, &ipm->h.flags);
+		if (test_and_set_bit(CACHE_NEGATIVE, &ipm->h.flags) == 0)
+			auth_domain_put(&ipm->m_client->h);
 		rv = NULL;
 	} else {
 		rv = &ipm->m_client->h;
@@ -368,7 +363,7 @@
 	svc_putu32(resv, RPC_AUTH_NULL);
 	svc_putu32(resv, 0);
 
-	key.m_class = rqstp->rq_server->sv_program->pg_class;
+	strcpy(key.m_class, rqstp->rq_server->sv_program->pg_class);
 	key.m_addr = rqstp->rq_addr.sin_addr;
 
 	ipm = ip_map_lookup(&key, 0);
@@ -405,6 +400,9 @@
 	if (rqstp->rq_client)
 		auth_domain_put(rqstp->rq_client);
 	rqstp->rq_client = NULL;
+	if (rqstp->rq_cred.cr_group_info)
+		put_group_info(rqstp->rq_cred.cr_group_info);
+	rqstp->rq_cred.cr_group_info = NULL;
 
 	return 0; /* don't drop */
 }
@@ -461,7 +459,7 @@
 	}
 
 
-	key.m_class = rqstp->rq_server->sv_program->pg_class;
+	strcpy(key.m_class, rqstp->rq_server->sv_program->pg_class);
 	key.m_addr = rqstp->rq_addr.sin_addr;
 
 
diff -Nru a/net/sunrpc/xprt.c b/net/sunrpc/xprt.c
--- a/net/sunrpc/xprt.c	2004-10-18 14:56:48 -07:00
+++ b/net/sunrpc/xprt.c	2004-10-18 14:56:48 -07:00
@@ -753,7 +753,7 @@
 	struct rpc_rqst *rovr;
 	struct sk_buff	*skb;
 	int err, repsize, copied;
-	u32 xid;
+	u32 _xid, *xp;
 
 	read_lock(&sk->sk_callback_lock);
 	dprintk("RPC:      udp_data_ready...\n");
@@ -777,12 +777,14 @@
 	}
 
 	/* Copy the XID from the skb... */
-	if (skb_copy_bits(skb, sizeof(struct udphdr), &xid, sizeof(xid)) < 0)
+	xp = skb_header_pointer(skb, sizeof(struct udphdr),
+				sizeof(_xid), &_xid);
+	if (xp == NULL)
 		goto dropit;
 
 	/* Look up and lock the request corresponding to the given XID */
 	spin_lock(&xprt->sock_lock);
-	rovr = xprt_lookup_rqst(xprt, xid);
+	rovr = xprt_lookup_rqst(xprt, *xp);
 	if (!rovr)
 		goto out_unlock;
 	task = rovr->rq_task;
diff -Nru a/net/unix/af_unix.c b/net/unix/af_unix.c
--- a/net/unix/af_unix.c	2004-10-18 14:56:33 -07:00
+++ b/net/unix/af_unix.c	2004-10-18 14:56:33 -07:00
@@ -144,7 +144,7 @@
 	return hash&(UNIX_HASH_SIZE-1);
 }
 
-#define unix_peer(sk) ((sk)->sk_pair)
+#define unix_peer(sk) (unix_sk(sk)->peer)
 
 static inline int unix_our_peer(struct sock *sk, struct sock *osk)
 {
diff -Nru a/net/wanrouter/af_wanpipe.c b/net/wanrouter/af_wanpipe.c
--- a/net/wanrouter/af_wanpipe.c	2004-10-18 14:57:04 -07:00
+++ b/net/wanrouter/af_wanpipe.c	2004-10-18 14:57:04 -07:00
@@ -2423,7 +2423,6 @@
 	write_unlock(&wanpipe_sklist_lock);
 	clear_bit(1,&wanpipe_tx_critical);
 
-	newsk->sk_pair = NULL;
 	newsk->sk_socket = newsock;
 	newsk->sk_sleep = &newsock->wait;
 
diff -Nru a/net/x25/af_x25.c b/net/x25/af_x25.c
--- a/net/x25/af_x25.c	2004-10-18 14:57:04 -07:00
+++ b/net/x25/af_x25.c	2004-10-18 14:57:04 -07:00
@@ -769,7 +769,6 @@
 	if (!skb->sk)
 		goto out2;
 	newsk		 = skb->sk;
-	newsk->sk_pair   = NULL;
 	newsk->sk_socket = newsock;
 	newsk->sk_sleep  = &newsock->wait;
 
@@ -887,7 +886,6 @@
 	makex25->state = X25_STATE_3;
 
 	sk->sk_ack_backlog++;
-	make->sk_pair = sk;
 
 	x25_insert_socket(make);
 
diff -Nru a/net/xfrm/xfrm_export.c b/net/xfrm/xfrm_export.c
--- a/net/xfrm/xfrm_export.c	2004-10-18 14:56:32 -07:00
+++ b/net/xfrm/xfrm_export.c	2004-10-18 14:56:32 -07:00
@@ -33,8 +33,6 @@
 EXPORT_SYMBOL(xfrm_get_acqseq);
 EXPORT_SYMBOL(xfrm_parse_spi);
 EXPORT_SYMBOL(xfrm4_rcv);
-EXPORT_SYMBOL(xfrm4_tunnel_register);
-EXPORT_SYMBOL(xfrm4_tunnel_deregister);
 EXPORT_SYMBOL(xfrm_register_type);
 EXPORT_SYMBOL(xfrm_unregister_type);
 EXPORT_SYMBOL(xfrm_get_type);
diff -Nru a/net/xfrm/xfrm_policy.c b/net/xfrm/xfrm_policy.c
--- a/net/xfrm/xfrm_policy.c	2004-10-18 14:56:32 -07:00
+++ b/net/xfrm/xfrm_policy.c	2004-10-18 14:56:32 -07:00
@@ -711,25 +711,11 @@
 {
 	struct xfrm_policy *policy;
 	struct xfrm_state *xfrm[XFRM_MAX_DEPTH];
-	struct rtable *rt = (struct rtable*)*dst_p;
-	struct dst_entry *dst;
+	struct dst_entry *dst, *dst_orig = *dst_p;
 	int nx = 0;
 	int err;
 	u32 genid;
-	u16 family = (*dst_p)->ops->family;
-
-	switch (family) {
-	case AF_INET:
-		if (!fl->fl4_src)
-			fl->fl4_src = rt->rt_src;
-		if (!fl->fl4_dst)
-			fl->fl4_dst = rt->rt_dst;
-	case AF_INET6:
-		/* Still not clear... */
-	default:
-		/* nothing */;
-	}
-
+	u16 family = dst_orig->ops->family;
 restart:
 	genid = atomic_read(&flow_cache_genid);
 	policy = NULL;
@@ -738,7 +724,7 @@
 
 	if (!policy) {
 		/* To accelerate a bit...  */
-		if ((rt->u.dst.flags & DST_NOXFRM) || !xfrm_policy_list[XFRM_POLICY_OUT])
+		if ((dst_orig->flags & DST_NOXFRM) || !xfrm_policy_list[XFRM_POLICY_OUT])
 			return 0;
 
 		policy = flow_cache_lookup(fl, family,
@@ -813,7 +799,7 @@
 			return 0;
 		}
 
-		dst = &rt->u.dst;
+		dst = dst_orig;
 		err = xfrm_bundle_create(policy, xfrm, nx, fl, &dst, family);
 
 		if (unlikely(err)) {
@@ -843,12 +829,12 @@
 		write_unlock_bh(&policy->lock);
 	}
 	*dst_p = dst;
-	ip_rt_put(rt);
+	dst_release(dst_orig);
 	xfrm_pol_put(policy);
 	return 0;
 
 error:
-	ip_rt_put(rt);
+	dst_release(dst_orig);
 	xfrm_pol_put(policy);
 	*dst_p = NULL;
 	return err;
diff -Nru a/net/xfrm/xfrm_state.c b/net/xfrm/xfrm_state.c
--- a/net/xfrm/xfrm_state.c	2004-10-18 14:56:48 -07:00
+++ b/net/xfrm/xfrm_state.c	2004-10-18 14:56:49 -07:00
@@ -387,13 +387,17 @@
 	spin_unlock_bh(&xfrm_state_lock);
 }
 
+static struct xfrm_state *__xfrm_find_acq_byseq(u32 seq);
+
 int xfrm_state_add(struct xfrm_state *x)
 {
 	struct xfrm_state_afinfo *afinfo;
 	struct xfrm_state *x1;
+	int family;
 	int err;
 
-	afinfo = xfrm_state_get_afinfo(x->props.family);
+	family = x->props.family;
+	afinfo = xfrm_state_get_afinfo(family);
 	if (unlikely(afinfo == NULL))
 		return -EAFNOSUPPORT;
 
@@ -407,9 +411,18 @@
 		goto out;
 	}
 
-	x1 = afinfo->find_acq(
-		x->props.mode, x->props.reqid, x->id.proto,
-		&x->id.daddr, &x->props.saddr, 0);
+	if (x->km.seq) {
+		x1 = __xfrm_find_acq_byseq(x->km.seq);
+		if (x1 && xfrm_addr_cmp(&x1->id.daddr, &x->id.daddr, family)) {
+			xfrm_state_put(x1);
+			x1 = NULL;
+		}
+	}
+
+	if (!x1)
+		x1 = afinfo->find_acq(
+			x->props.mode, x->props.reqid, x->id.proto,
+			&x->id.daddr, &x->props.saddr, 0);
 
 	__xfrm_state_insert(x);
 	err = 0;
@@ -570,23 +583,30 @@
 
 /* Silly enough, but I'm lazy to build resolution list */
 
-struct xfrm_state * xfrm_find_acq_byseq(u32 seq)
+static struct xfrm_state *__xfrm_find_acq_byseq(u32 seq)
 {
 	int i;
 	struct xfrm_state *x;
 
-	spin_lock_bh(&xfrm_state_lock);
 	for (i = 0; i < XFRM_DST_HSIZE; i++) {
 		list_for_each_entry(x, xfrm_state_bydst+i, bydst) {
 			if (x->km.seq == seq) {
 				xfrm_state_hold(x);
-				spin_unlock_bh(&xfrm_state_lock);
 				return x;
 			}
 		}
 	}
-	spin_unlock_bh(&xfrm_state_lock);
 	return NULL;
+}
+
+struct xfrm_state *xfrm_find_acq_byseq(u32 seq)
+{
+	struct xfrm_state *x;
+
+	spin_lock_bh(&xfrm_state_lock);
+	x = __xfrm_find_acq_byseq(seq);
+	spin_unlock_bh(&xfrm_state_lock);
+	return x;
 }
  
 u32 xfrm_get_acqseq(void)
diff -Nru a/net/xfrm/xfrm_user.c b/net/xfrm/xfrm_user.c
--- a/net/xfrm/xfrm_user.c	2004-10-18 14:56:33 -07:00
+++ b/net/xfrm/xfrm_user.c	2004-10-18 14:56:33 -07:00
@@ -78,15 +78,6 @@
 	if ((rt->rta_len - sizeof(*rt)) < sizeof(*encap))
 		return -EINVAL;
 
-	encap = RTA_DATA(rt);
-	switch (encap->encap_type) {
-	case UDP_ENCAP_ESPINUDP:
-	case UDP_ENCAP_ESPINUDP_NON_IKE:
-		break;
-	default:
-		return -ENOPROTOOPT;
-	}
-
 	return 0;
 }
 
@@ -164,15 +155,24 @@
 	return err;
 }
 
-static int attach_one_algo(struct xfrm_algo **algpp, struct rtattr *u_arg)
+static int attach_one_algo(struct xfrm_algo **algpp, u8 *props,
+			   struct xfrm_algo_desc *(*get_byname)(char *),
+			   struct rtattr *u_arg)
 {
 	struct rtattr *rta = u_arg;
 	struct xfrm_algo *p, *ualg;
+	struct xfrm_algo_desc *algo;
 
 	if (!rta)
 		return 0;
 
 	ualg = RTA_DATA(rta);
+
+	algo = get_byname(ualg->alg_name);
+	if (!algo)
+		return -ENOSYS;
+	*props = algo->desc.sadb_alg_id;
+
 	p = kmalloc(sizeof(*ualg) + ualg->alg_key_len, GFP_KERNEL);
 	if (!p)
 		return -ENOMEM;
@@ -225,11 +225,17 @@
 
 	copy_from_user_state(x, p);
 
-	if ((err = attach_one_algo(&x->aalg, xfrma[XFRMA_ALG_AUTH-1])))
+	if ((err = attach_one_algo(&x->aalg, &x->props.aalgo,
+				   xfrm_aalg_get_byname,
+				   xfrma[XFRMA_ALG_AUTH-1])))
 		goto error;
-	if ((err = attach_one_algo(&x->ealg, xfrma[XFRMA_ALG_CRYPT-1])))
+	if ((err = attach_one_algo(&x->ealg, &x->props.ealgo,
+				   xfrm_ealg_get_byname,
+				   xfrma[XFRMA_ALG_CRYPT-1])))
 		goto error;
-	if ((err = attach_one_algo(&x->calg, xfrma[XFRMA_ALG_COMP-1])))
+	if ((err = attach_one_algo(&x->calg, &x->props.calgo,
+				   xfrm_calg_get_byname,
+				   xfrma[XFRMA_ALG_COMP-1])))
 		goto error;
 	if ((err = attach_encap_tmpl(&x->encap, xfrma[XFRMA_ENCAP-1])))
 		goto error;
@@ -464,16 +470,32 @@
 	struct xfrm_state *x;
 	struct xfrm_userspi_info *p;
 	struct sk_buff *resp_skb;
+	xfrm_address_t *daddr;
+	int family;
 	int err;
 
 	p = NLMSG_DATA(nlh);
 	err = verify_userspi_info(p);
 	if (err)
 		goto out_noput;
-	x = xfrm_find_acq(p->info.mode, p->info.reqid, p->info.id.proto,
-			  &p->info.id.daddr,
-			  &p->info.saddr, 1,
-			  p->info.family);
+
+	family = p->info.family;
+	daddr = &p->info.id.daddr;
+
+	x = NULL;
+	if (p->info.seq) {
+		x = xfrm_find_acq_byseq(p->info.seq);
+		if (x && xfrm_addr_cmp(&x->id.daddr, daddr, family)) {
+			xfrm_state_put(x);
+			x = NULL;
+		}
+	}
+
+	if (!x)
+		x = xfrm_find_acq(p->info.mode, p->info.reqid,
+				  p->info.id.proto, daddr,
+				  &p->info.saddr, 1,
+				  family);
 	err = -ENOENT;
 	if (x == NULL)
 		goto out_noput;
diff -Nru a/scripts/Makefile b/scripts/Makefile
--- a/scripts/Makefile	2004-10-18 14:56:32 -07:00
+++ b/scripts/Makefile	2004-10-18 14:56:32 -07:00
@@ -2,14 +2,21 @@
 # scripts contains sources for various helper programs used throughout
 # the kernel for the build process.
 # ---------------------------------------------------------------------------
-# docproc: 	 Preprocess .tmpl file in order to generate .sgml docs
+# kallsyms:      Find all symbols in vmlinux
+# pnmttologo:    Convert pnm files to logo files
+# conmakehash:   Create chartable
 # conmakehash:	 Create arrays for initializing the kernel console tables
 
-host-progs	:= conmakehash kallsyms pnmtologo bin2c
-always		:= $(host-progs)
+hostprogs-$(CONFIG_KALLSYMS)     += kallsyms
+hostprogs-$(CONFIG_LOGO)         += pnmtologo
+hostprogs-$(CONFIG_VT)           += conmakehash
+hostprogs-$(CONFIG_PROM_CONSOLE) += conmakehash
+hostprogs-$(CONFIG_IKCONFIG)     += bin2c
 
-subdir-$(CONFIG_MODVERSIONS)	+= genksyms
-subdir-y	+= mod
+always		:= $(hostprogs-y)
+
+subdir-$(CONFIG_MODVERSIONS) += genksyms
+subdir-$(CONFIG_MODULES)     += mod
 
 # Let clean descend into subdirs
 subdir-	+= basic lxdialog kconfig package
diff -Nru a/scripts/Makefile.build b/scripts/Makefile.build
--- a/scripts/Makefile.build	2004-10-18 14:56:49 -07:00
+++ b/scripts/Makefile.build	2004-10-18 14:56:49 -07:00
@@ -14,6 +14,18 @@
 
 include scripts/Makefile.lib
 
+ifdef host-progs
+ifneq ($(hostprogs-y),$(host-progs))
+$(warning kbuild: $(obj)/Makefile - Usage of host-progs is deprecated. Please replace with hostprogs-y!)
+hostprogs-y += $(host-progs)
+endif
+endif
+
+# Do not include host rules unles needed
+ifneq ($(hostprogs-y)$(hostprogs-m),)
+include scripts/Makefile.host
+endif
+
 ifneq ($(KBUILD_SRC),)
 # Create output directory if not already present
 _dummy := $(shell [ -d $(obj) ] || mkdir -p $(obj))
@@ -71,8 +83,13 @@
 
 # Linus' kernel sanity checking tool
 ifneq ($(KBUILD_CHECKSRC),0)
-quiet_cmd_checksrc = CHECK   $<
-      cmd_checksrc = $(CHECK) $(c_flags) $< ;
+  ifeq ($(KBUILD_CHECKSRC),2)
+    quiet_cmd_force_checksrc = CHECK   $<
+          cmd_force_checksrc = $(CHECK) $(CHECKFLAGS) $(c_flags) $< ;
+  else
+      quiet_cmd_checksrc     = CHECK   $<
+            cmd_checksrc     = $(CHECK) $(CHECKFLAGS) $(c_flags) $< ;
+  endif
 endif
 
 
@@ -143,9 +160,7 @@
 
 cmd_cc_o_c = $(CC) $(c_flags) -c -o $(@D)/.tmp_$(@F) $<
 cmd_modversions =							\
-	if ! $(OBJDUMP) -h $(@D)/.tmp_$(@F) | grep -q __ksymtab; then	\
-		mv $(@D)/.tmp_$(@F) $@;					\
-	else								\
+	if $(OBJDUMP) -h $(@D)/.tmp_$(@F) | grep -q __ksymtab; then	\
 		$(CPP) -D__GENKSYMS__ $(c_flags) $<			\
 		| $(GENKSYMS)						\
 		> $(@D)/.tmp_$(@F:.o=.ver);				\
@@ -153,6 +168,8 @@
 		$(LD) $(LDFLAGS) -r -o $@ $(@D)/.tmp_$(@F) 		\
 			-T $(@D)/.tmp_$(@F:.o=.ver);			\
 		rm -f $(@D)/.tmp_$(@F) $(@D)/.tmp_$(@F:.o=.ver);	\
+	else								\
+		mv $(@D)/.tmp_$(@F) $@;					\
 	fi;
 endif
 
@@ -170,11 +187,13 @@
 # Built-in and composite module parts
 
 %.o: %.c FORCE
+	$(call cmd,force_checksrc)
 	$(call if_changed_rule,cc_o_c)
 
 # Single-part modules are special since we need to mark them in $(MODVERDIR)
 
 $(single-used-m): %.o: %.c FORCE
+	$(call cmd,force_checksrc)
 	$(call if_changed_rule,cc_o_c)
 	@{ echo $(@:.o=.ko); echo $@; } > $(MODVERDIR)/$(@F:.o=.mod)
 
@@ -209,6 +228,14 @@
 targets += $(real-objs-y) $(real-objs-m) $(lib-y)
 targets += $(extra-y) $(MAKECMDGOALS) $(always)
 
+# Linker scripts preprocessor (.lds.S -> .lds)
+# ---------------------------------------------------------------------------
+quiet_cmd_cpp_lds_S = LDS     $@
+      cmd_cpp_lds_S = $(CPP) $(cpp_flags) -D__ASSEMBLY__ -o $@ $<
+
+%.lds: %.lds.S FORCE
+	$(call if_changed_dep,cpp_lds_S)
+
 # Build the compiled-in targets
 # ---------------------------------------------------------------------------
 
@@ -275,90 +302,6 @@
 
 targets += $(multi-used-y) $(multi-used-m)
 
-# Compile programs on the host
-# ===========================================================================
-# host-progs := bin2hex
-# Will compile bin2hex.c and create an executable named bin2hex
-#
-# host-progs    := lxdialog
-# lxdialog-objs := checklist.o lxdialog.o
-# Will compile lxdialog.c and checklist.c, and then link the executable
-# lxdialog, based on checklist.o and lxdialog.o
-#
-# host-progs      := qconf
-# qconf-cxxobjs   := qconf.o
-# qconf-objs      := menu.o
-# Will compile qconf as a C++ program, and menu as a C program.
-# They are linked as C++ code to the executable qconf
-
-# host-progs := conf
-# conf-objs  := conf.o libkconfig.so
-# libkconfig-objs := expr.o type.o
-# Will create a shared library named libkconfig.so that consist of
-# expr.o and type.o (they are both compiled as C code and the object file
-# are made as position independent code).
-# conf.c is compiled as a c program, and conf.o is linked together with
-# libkconfig.so as the executable conf.
-# Note: Shared libraries consisting of C++ files are not supported  
-#
-
-# Create executable from a single .c file
-# host-csingle -> Executable
-quiet_cmd_host-csingle 	= HOSTCC  $@
-      cmd_host-csingle	= $(HOSTCC) $(hostc_flags) $(HOST_LOADLIBES) -o $@ $<
-$(host-csingle): %: %.c FORCE
-	$(call if_changed_dep,host-csingle)
-
-# Link an executable based on list of .o files, all plain c
-# host-cmulti -> executable
-quiet_cmd_host-cmulti	= HOSTLD  $@
-      cmd_host-cmulti	= $(HOSTCC) $(HOSTLDFLAGS) -o $@ \
-			  $(addprefix $(obj)/,$($(@F)-objs)) \
-			  $(HOST_LOADLIBES) $(HOSTLOADLIBES_$(@F))
-$(host-cmulti): %: $(host-cobjs) $(host-cshlib) FORCE
-	$(call if_changed,host-cmulti)
-
-# Create .o file from a single .c file
-# host-cobjs -> .o
-quiet_cmd_host-cobjs	= HOSTCC  $@
-      cmd_host-cobjs	= $(HOSTCC) $(hostc_flags) -c -o $@ $<
-$(host-cobjs): %.o: %.c FORCE
-	$(call if_changed_dep,host-cobjs)
-
-# Link an executable based on list of .o files, a mixture of .c and .cc
-# host-cxxmulti -> executable
-quiet_cmd_host-cxxmulti	= HOSTLD  $@
-      cmd_host-cxxmulti	= $(HOSTCXX) $(HOSTLDFLAGS) -o $@ \
-			  $(foreach o,objs cxxobjs,\
-			  $(addprefix $(obj)/,$($(@F)-$(o)))) \
-			  $(HOST_LOADLIBES) $(HOSTLOADLIBES_$(@F))
-$(host-cxxmulti): %: $(host-cobjs) $(host-cxxobjs) $(host-cshlib) FORCE
-	$(call if_changed,host-cxxmulti)
-
-# Create .o file from a single .cc (C++) file
-quiet_cmd_host-cxxobjs	= HOSTCXX $@
-      cmd_host-cxxobjs	= $(HOSTCXX) $(hostcxx_flags) -c -o $@ $<
-$(host-cxxobjs): %.o: %.cc FORCE
-	$(call if_changed_dep,host-cxxobjs)
-
-# Compile .c file, create position independent .o file
-# host-cshobjs -> .o
-quiet_cmd_host-cshobjs	= HOSTCC  -fPIC $@
-      cmd_host-cshobjs	= $(HOSTCC) $(hostc_flags) -fPIC -c -o $@ $<
-$(host-cshobjs): %.o: %.c FORCE
-	$(call if_changed_dep,host-cshobjs)
-
-# Link a shared library, based on position independent .o files
-# *.o -> .so shared library (host-cshlib)
-quiet_cmd_host-cshlib	= HOSTLLD -shared $@
-      cmd_host-cshlib	= $(HOSTCC) $(HOSTLDFLAGS) -shared -o $@ \
-			  $(addprefix $(obj)/,$($(@F:.so=-objs))) \
-			  $(HOST_LOADLIBES) $(HOSTLOADLIBES_$(@F))
-$(host-cshlib): %: $(host-cshobjs) FORCE
-	$(call if_changed,host-cshlib)
-
-targets += $(host-csingle)  $(host-cmulti) $(host-cobjs)\
-	   $(host-cxxmulti) $(host-cxxobjs) $(host-cshlib) $(host-cshobjs) 
 
 # Descending
 # ---------------------------------------------------------------------------
diff -Nru a/scripts/Makefile.clean b/scripts/Makefile.clean
--- a/scripts/Makefile.clean	2004-10-18 14:55:46 -07:00
+++ b/scripts/Makefile.clean	2004-10-18 14:55:46 -07:00
@@ -29,21 +29,49 @@
 # Add subdir path
 
 subdir-ymn	:= $(addprefix $(obj)/,$(subdir-ymn))
-__clean-files	:= $(wildcard $(addprefix $(obj)/, \
-		   $(extra-y) $(EXTRA_TARGETS) $(always) $(host-progs) \
-		   $(targets) $(clean-files)))
+
+# build a list of files to remove, usually releative to the current
+# directory
+
+__clean-files	:= $(extra-y) $(EXTRA_TARGETS) $(always) \
+		   $(targets) $(clean-files)             \
+		   $(host-progs)                         \
+		   $(hostprogs-y) $(hostprogs-m) $(hostprogs-)
+
+# as clean-files is given relative to the current directory, this adds
+# a $(obj) prefix, except for absolute paths
+
+__clean-files   := $(wildcard                                               \
+                   $(addprefix $(obj)/, $(filter-out /%, $(__clean-files))) \
+		   $(filter /%, $(__clean-files)))
+
+# as clean-dirs is given relative to the current directory, this adds
+# a $(obj) prefix, except for absolute paths
+
+__clean-dirs    := $(wildcard                                               \
+                   $(addprefix $(obj)/, $(filter-out /%, $(clean-dirs)))    \
+		   $(filter /%, $(clean-dirs)))
 
 # ==========================================================================
 
-quiet_cmd_clean = CLEAN   $(obj)
-      cmd_clean = rm -f $(__clean-files); $(clean-rule)
+quiet_cmd_clean    = CLEAN   $(obj)
+      cmd_clean    = rm -f $(__clean-files)
+quiet_cmd_cleandir = CLEAN   $(__clean-dirs)
+      cmd_cleandir = rm -rf $(__clean-dirs)
+
 
 __clean: $(subdir-ymn)
-ifneq ($(strip $(__clean-files) $(clean-rule)),)
+ifneq ($(strip $(__clean-files)),)
 	+$(call cmd,clean)
-else
-	@:
 endif
+ifneq ($(strip $(__clean-dirs)),)
+	+$(call cmd,cleandir)
+endif
+ifneq ($(strip $(clean-rule)),)
+	+$(clean-rule)
+endif
+	@:
+
 
 # ===========================================================================
 # Generic stuff
diff -Nru a/scripts/Makefile.host b/scripts/Makefile.host
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/scripts/Makefile.host	2004-10-18 14:57:24 -07:00
@@ -0,0 +1,155 @@
+# ==========================================================================
+# Building binaries on the host system
+# Binaries are used during the compilation of the kernel, for example
+# to preprocess a data file.
+#
+# Both C and C++ is supported, but preferred language is C for such utilities.
+#
+# Samle syntax (see Documentation/kbuild/makefile.txt for reference)
+# hostprogs-y := bin2hex
+# Will compile bin2hex.c and create an executable named bin2hex
+#
+# hostprogs-y    := lxdialog
+# lxdialog-objs := checklist.o lxdialog.o
+# Will compile lxdialog.c and checklist.c, and then link the executable
+# lxdialog, based on checklist.o and lxdialog.o
+#
+# hostprogs-y      := qconf
+# qconf-cxxobjs   := qconf.o
+# qconf-objs      := menu.o
+# Will compile qconf as a C++ program, and menu as a C program.
+# They are linked as C++ code to the executable qconf
+
+# hostprogs-y := conf
+# conf-objs  := conf.o libkconfig.so
+# libkconfig-objs := expr.o type.o
+# Will create a shared library named libkconfig.so that consist of
+# expr.o and type.o (they are both compiled as C code and the object file
+# are made as position independent code).
+# conf.c is compiled as a c program, and conf.o is linked together with
+# libkconfig.so as the executable conf.
+# Note: Shared libraries consisting of C++ files are not supported
+
+__hostprogs := $(sort $(hostprogs-y)$(hostprogs-m))
+
+# hostprogs-y := tools/build may have been specified. Retreive directory
+obj-dirs += $(foreach f,$(__hostprogs), $(if $(dir $(f)),$(dir $(f))))
+obj-dirs := $(strip $(sort $(filter-out ./,$(obj-dirs))))
+
+
+# C code
+# Executables compiled from a single .c file
+host-csingle	:= $(foreach m,$(__hostprogs),$(if $($(m)-objs),,$(m)))
+
+# C executables linked based on several .o files
+host-cmulti	:= $(foreach m,$(__hostprogs),\
+		   $(if $($(m)-cxxobjs),,$(if $($(m)-objs),$(m))))
+
+# Object (.o) files compiled from .c files
+host-cobjs	:= $(sort $(foreach m,$(__hostprogs),$($(m)-objs)))
+
+# C++ code
+# C++ executables compiled from at least on .cc file
+# and zero or more .c files
+host-cxxmulti	:= $(foreach m,$(__hostprogs),$(if $($(m)-cxxobjs),$(m)))
+
+# C++ Object (.o) files compiled from .cc files
+host-cxxobjs	:= $(sort $(foreach m,$(host-cxxmulti),$($(m)-cxxobjs)))
+
+# Shared libaries (only .c supported)
+# Shared libraries (.so) - all .so files referenced in "xxx-objs"
+host-cshlib	:= $(sort $(filter %.so, $(host-cobjs)))
+# Remove .so files from "xxx-objs"
+host-cobjs	:= $(filter-out %.so,$(host-cobjs))
+
+#Object (.o) files used by the shared libaries
+host-cshobjs	:= $(sort $(foreach m,$(host-cshlib),$($(m:.so=-objs))))
+
+__hostprogs     := $(addprefix $(obj)/,$(__hostprogs))
+host-csingle	:= $(addprefix $(obj)/,$(host-csingle))
+host-cmulti	:= $(addprefix $(obj)/,$(host-cmulti))
+host-cobjs	:= $(addprefix $(obj)/,$(host-cobjs))
+host-cxxmulti	:= $(addprefix $(obj)/,$(host-cxxmulti))
+host-cxxobjs	:= $(addprefix $(obj)/,$(host-cxxobjs))
+host-cshlib	:= $(addprefix $(obj)/,$(host-cshlib))
+host-cshobjs	:= $(addprefix $(obj)/,$(host-cshobjs))
+obj-dirs        := $(addprefix $(obj)/,$(obj-dirs))
+
+#####
+# Handle options to gcc. Support building with separate output directory
+
+_hostc_flags   = $(HOSTCFLAGS)   $(HOST_EXTRACFLAGS)   $(HOSTCFLAGS_$(*F).o)
+_hostcxx_flags = $(HOSTCXXFLAGS) $(HOST_EXTRACXXFLAGS) $(HOSTCXXFLAGS_$(*F).o)
+
+ifeq ($(KBUILD_SRC),)
+__hostc_flags	= $(_hostc_flags)
+__hostcxx_flags	= $(_hostcxx_flags)
+else
+__hostc_flags	= -I$(obj) $(call flags,_hostc_flags)
+__hostcxx_flags	= -I$(obj) $(call flags,_hostcxx_flags)
+endif
+
+hostc_flags    = -Wp,-MD,$(depfile) $(__hostc_flags)
+hostcxx_flags  = -Wp,-MD,$(depfile) $(__hostcxx_flags)
+
+#####
+# Compile programs on the host
+
+# Create executable from a single .c file
+# host-csingle -> Executable
+quiet_cmd_host-csingle 	= HOSTCC  $@
+      cmd_host-csingle	= $(HOSTCC) $(hostc_flags) $(HOST_LOADLIBES) -o $@ $<
+$(host-csingle): %: %.c FORCE
+	$(call if_changed_dep,host-csingle)
+
+# Link an executable based on list of .o files, all plain c
+# host-cmulti -> executable
+quiet_cmd_host-cmulti	= HOSTLD  $@
+      cmd_host-cmulti	= $(HOSTCC) $(HOSTLDFLAGS) -o $@ \
+			  $(addprefix $(obj)/,$($(@F)-objs)) \
+			  $(HOST_LOADLIBES) $(HOSTLOADLIBES_$(@F))
+$(host-cmulti): %: $(host-cobjs) $(host-cshlib) FORCE
+	$(call if_changed,host-cmulti)
+
+# Create .o file from a single .c file
+# host-cobjs -> .o
+quiet_cmd_host-cobjs	= HOSTCC  $@
+      cmd_host-cobjs	= $(HOSTCC) $(hostc_flags) -c -o $@ $<
+$(host-cobjs): %.o: %.c FORCE
+	$(call if_changed_dep,host-cobjs)
+
+# Link an executable based on list of .o files, a mixture of .c and .cc
+# host-cxxmulti -> executable
+quiet_cmd_host-cxxmulti	= HOSTLD  $@
+      cmd_host-cxxmulti	= $(HOSTCXX) $(HOSTLDFLAGS) -o $@ \
+			  $(foreach o,objs cxxobjs,\
+			  $(addprefix $(obj)/,$($(@F)-$(o)))) \
+			  $(HOST_LOADLIBES) $(HOSTLOADLIBES_$(@F))
+$(host-cxxmulti): %: $(host-cobjs) $(host-cxxobjs) $(host-cshlib) FORCE
+	$(call if_changed,host-cxxmulti)
+
+# Create .o file from a single .cc (C++) file
+quiet_cmd_host-cxxobjs	= HOSTCXX $@
+      cmd_host-cxxobjs	= $(HOSTCXX) $(hostcxx_flags) -c -o $@ $<
+$(host-cxxobjs): %.o: %.cc FORCE
+	$(call if_changed_dep,host-cxxobjs)
+
+# Compile .c file, create position independent .o file
+# host-cshobjs -> .o
+quiet_cmd_host-cshobjs	= HOSTCC  -fPIC $@
+      cmd_host-cshobjs	= $(HOSTCC) $(hostc_flags) -fPIC -c -o $@ $<
+$(host-cshobjs): %.o: %.c FORCE
+	$(call if_changed_dep,host-cshobjs)
+
+# Link a shared library, based on position independent .o files
+# *.o -> .so shared library (host-cshlib)
+quiet_cmd_host-cshlib	= HOSTLLD -shared $@
+      cmd_host-cshlib	= $(HOSTCC) $(HOSTLDFLAGS) -shared -o $@ \
+			  $(addprefix $(obj)/,$($(@F:.so=-objs))) \
+			  $(HOST_LOADLIBES) $(HOSTLOADLIBES_$(@F))
+$(host-cshlib): %: $(host-cshobjs) FORCE
+	$(call if_changed,host-cshlib)
+
+targets += $(host-csingle)  $(host-cmulti) $(host-cobjs)\
+	   $(host-cxxmulti) $(host-cxxobjs) $(host-cshlib) $(host-cshobjs) 
+
diff -Nru a/scripts/Makefile.lib b/scripts/Makefile.lib
--- a/scripts/Makefile.lib	2004-10-18 14:56:32 -07:00
+++ b/scripts/Makefile.lib	2004-10-18 14:56:32 -07:00
@@ -60,41 +60,11 @@
 
 # $(obj-dirs) is a list of directories that contain object files
 obj-dirs := $(dir $(multi-objs) $(subdir-obj-y))
-obj-dirs += $(foreach f,$(host-progs), $(if $(dir $(f)),$(dir $(f))))
-obj-dirs := $(strip $(sort $(filter-out ./,$(obj-dirs))))
 
 # Replace multi-part objects by their individual parts, look at local dir only
 real-objs-y := $(foreach m, $(filter-out $(subdir-obj-y), $(obj-y)), $(if $(strip $($(m:.o=-objs)) $($(m:.o=-y))),$($(m:.o=-objs)) $($(m:.o=-y)),$(m))) $(extra-y)
 real-objs-m := $(foreach m, $(obj-m), $(if $(strip $($(m:.o=-objs)) $($(m:.o=-y))),$($(m:.o=-objs)) $($(m:.o=-y)),$(m)))
 
-# C code
-# Executables compiled from a single .c file
-host-csingle	:= $(foreach m,$(host-progs),$(if $($(m)-objs),,$(m)))
-
-# C executables linked based on several .o files
-host-cmulti	:= $(foreach m,$(host-progs),\
-		   $(if $($(m)-cxxobjs),,$(if $($(m)-objs),$(m))))
-
-# Object (.o) files compiled from .c files
-host-cobjs	:= $(sort $(foreach m,$(host-progs),$($(m)-objs)))
-
-# C++ code
-# C++ executables compiled from at least on .cc file
-# and zero or more .c files
-host-cxxmulti	:= $(foreach m,$(host-progs),$(if $($(m)-cxxobjs),$(m)))
-
-# C++ Object (.o) files compiled from .cc files
-host-cxxobjs	:= $(sort $(foreach m,$(host-cxxmulti),$($(m)-cxxobjs)))
-
-# Shared libaries (only .c supported)
-# Shared libraries (.so) - all .so files referenced in "xxx-objs"
-host-cshlib	:= $(sort $(filter %.so, $(host-cobjs)))
-# Remove .so files from "xxx-objs"
-host-cobjs	:= $(filter-out %.so,$(host-cobjs))
-
-#Object (.o) files used by the shared libaries
-host-cshobjs	:= $(sort $(foreach m,$(host-cshlib),$($(m:.so=-objs))))
-
 # Add subdir path
 
 extra-y		:= $(addprefix $(obj)/,$(extra-y))
@@ -113,14 +83,6 @@
 multi-objs-m	:= $(addprefix $(obj)/,$(multi-objs-m))
 subdir-ym	:= $(addprefix $(obj)/,$(subdir-ym))
 obj-dirs	:= $(addprefix $(obj)/,$(obj-dirs))
-host-progs      := $(addprefix $(obj)/,$(host-progs))
-host-csingle	:= $(addprefix $(obj)/,$(host-csingle))
-host-cmulti	:= $(addprefix $(obj)/,$(host-cmulti))
-host-cobjs	:= $(addprefix $(obj)/,$(host-cobjs))
-host-cxxmulti	:= $(addprefix $(obj)/,$(host-cxxmulti))
-host-cxxobjs	:= $(addprefix $(obj)/,$(host-cxxobjs))
-host-cshlib	:= $(addprefix $(obj)/,$(host-cshlib))
-host-cshobjs	:= $(addprefix $(obj)/,$(host-cshobjs))
 
 # The temporary file to save gcc -MD generated dependencies must not
 # contain a comma
@@ -136,12 +98,9 @@
 basename_flags = -DKBUILD_BASENAME=$(subst $(comma),_,$(subst -,_,$(*F)))
 modname_flags  = $(if $(filter 1,$(words $(modname))),-DKBUILD_MODNAME=$(subst $(comma),_,$(subst -,_,$(modname))))
 
-
 _c_flags       = $(CFLAGS) $(EXTRA_CFLAGS) $(CFLAGS_$(*F).o)
 _a_flags       = $(AFLAGS) $(EXTRA_AFLAGS) $(AFLAGS_$(*F).o)
-_hostc_flags   = $(HOSTCFLAGS)   $(HOST_EXTRACFLAGS)   $(HOSTCFLAGS_$(*F).o)
-_hostcxx_flags = $(HOSTCXXFLAGS) $(HOST_EXTRACXXFLAGS) $(HOSTCXXFLAGS_$(*F).o)
-
+_cpp_flags     = $(CPPFLAGS) $(EXTRA_CPPFLAGS) $(CPPFLAGS_$(@F))
 
 # If building the kernel in a separate objtree expand all occurrences
 # of -Idir to -I$(srctree)/dir except for absolute paths (starting with '/').
@@ -149,8 +108,7 @@
 ifeq ($(KBUILD_SRC),)
 __c_flags	= $(_c_flags)
 __a_flags	= $(_a_flags)
-__hostc_flags	= $(_hostc_flags)
-__hostcxx_flags	= $(_hostcxx_flags)
+__cpp_flags     = $(_cpp_flags)
 else
 
 # Prefix -I with $(srctree) if it is not an absolute path
@@ -164,8 +122,7 @@
 # FIXME: Replace both with specific CFLAGS* statements in the makefiles
 __c_flags	= $(call addtree,-I$(obj)) $(call flags,_c_flags)
 __a_flags	=                          $(call flags,_a_flags)
-__hostc_flags	= -I$(obj)                 $(call flags,_hostc_flags)
-__hostcxx_flags	= -I$(obj)                 $(call flags,_hostcxx_flags)
+__cpp_flags     =                          $(call flags,_cpp_flags)
 endif
 
 c_flags        = -Wp,-MD,$(depfile) $(NOSTDINC_FLAGS) $(CPPFLAGS) \
@@ -175,8 +132,7 @@
 a_flags        = -Wp,-MD,$(depfile) $(NOSTDINC_FLAGS) $(CPPFLAGS) \
 		 $(__a_flags) $(modkern_aflags)
 
-hostc_flags    = -Wp,-MD,$(depfile) $(__hostc_flags)
-hostcxx_flags  = -Wp,-MD,$(depfile) $(__hostcxx_flags)
+cpp_flags      = -Wp,-MD,$(depfile) $(NOSTDINC_FLAGS) $(__cpp_flags)
 
 ld_flags       = $(LDFLAGS) $(EXTRA_LDFLAGS)
 
diff -Nru a/scripts/Makefile.modinst b/scripts/Makefile.modinst
--- a/scripts/Makefile.modinst	2004-10-18 14:56:32 -07:00
+++ b/scripts/Makefile.modinst	2004-10-18 14:56:32 -07:00
@@ -9,7 +9,7 @@
 
 #
 
-__modules := $(sort $(shell head -q -n1 /dev/null $(wildcard $(MODVERDIR)/*.mod)))
+__modules := $(sort $(shell grep -h '\.ko' /dev/null $(wildcard $(MODVERDIR)/*.mod)))
 modules := $(patsubst %.o,%.ko,$(wildcard $(__modules:.ko=.o)))
 
 .PHONY: $(modules)
diff -Nru a/scripts/Makefile.modpost b/scripts/Makefile.modpost
--- a/scripts/Makefile.modpost	2004-10-18 14:56:32 -07:00
+++ b/scripts/Makefile.modpost	2004-10-18 14:56:32 -07:00
@@ -41,7 +41,7 @@
 symverfile := $(objtree)/Module.symvers
 
 # Step 1), find all modules listed in $(MODVERDIR)/
-__modules := $(sort $(shell head -q -n1 /dev/null $(wildcard $(MODVERDIR)/*.mod)))
+__modules := $(sort $(shell grep -h '\.ko' /dev/null $(wildcard $(MODVERDIR)/*.mod)))
 modules   := $(patsubst %.o,%.ko, $(wildcard $(__modules:.ko=.o)))
 
 _modpost: $(modules)
@@ -50,7 +50,8 @@
 # Step 2), invoke modpost
 #  Includes step 3,4
 quiet_cmd_modpost = MODPOST
-      cmd_modpost = scripts/mod/modpost \
+      cmd_modpost = scripts/mod/modpost            \
+        $(if $(CONFIG_MODVERSIONS),-m)             \
 	$(if $(KBUILD_EXTMOD),-i,-o) $(symverfile) \
 	$(filter-out FORCE,$^)
 
diff -Nru a/scripts/basic/Makefile b/scripts/basic/Makefile
--- a/scripts/basic/Makefile	2004-10-18 14:56:19 -07:00
+++ b/scripts/basic/Makefile	2004-10-18 14:56:19 -07:00
@@ -11,8 +11,8 @@
 #                include/config/...
 # docproc:	 Used in Documentation/docbook
 
-host-progs	:= fixdep split-include docproc
-always		:= $(host-progs)
+hostprogs-y	:= fixdep split-include docproc
+always		:= $(hostprogs-y)
 
 # fixdep is needed to compile other host programs
 $(addprefix $(obj)/,$(filter-out fixdep,$(always))): $(obj)/fixdep
diff -Nru a/scripts/basic/fixdep.c b/scripts/basic/fixdep.c
--- a/scripts/basic/fixdep.c	2004-10-18 14:56:31 -07:00
+++ b/scripts/basic/fixdep.c	2004-10-18 14:56:31 -07:00
@@ -93,6 +93,14 @@
  * (Note: it'd be easy to port over the complete mkdep state machine,
  *  but I don't think the added complexity is worth it)
  */
+/*
+ * Note 2: if somebody writes HELLO_CONFIG_BOOM in a file, it will depend onto
+ * CONFIG_BOOM. This could seem a bug (not too hard to fix), but please do not
+ * fix it! Some UserModeLinux files (look at arch/um/) call CONFIG_BOOM as
+ * UML_CONFIG_BOOM, to avoid conflicts with /usr/include/linux/autoconf.h,
+ * through arch/um/include/uml-config.h; this fixdep "bug" makes sure that
+ * those files will have correct dependencies.
+ */
 
 #include <sys/types.h>
 #include <sys/stat.h>
@@ -104,7 +112,7 @@
 #include <stdio.h>
 #include <limits.h>
 #include <ctype.h>
-#include <netinet/in.h>
+#include <arpa/inet.h>
 
 #define INT_CONF ntohl(0x434f4e46)
 #define INT_ONFI ntohl(0x4f4e4649)
@@ -310,6 +318,7 @@
 		}
 		memcpy(s, m, p-m); s[p-m] = 0;
 		if (strrcmp(s, "include/linux/autoconf.h") &&
+		    strrcmp(s, "arch/um/include/uml-config.h") &&
 		    strrcmp(s, ".ver")) {
 			printf("  %s \\\n", s);
 			do_config_file(s);
diff -Nru a/scripts/binoffset.c b/scripts/binoffset.c
--- a/scripts/binoffset.c	2004-10-18 14:56:33 -07:00
+++ b/scripts/binoffset.c	2004-10-18 14:56:33 -07:00
@@ -41,7 +41,7 @@
 char		*progname;
 char		*inputname;
 int		inputfd;
-int		bix;			/* buf index */
+unsigned int	bix;			/* buf index */
 unsigned char	patterns [PAT_SIZE] = {0}; /* byte-sized pattern array */
 int		pat_len;		/* actual number of pattern bytes */
 unsigned char	*madr;			/* mmap address */
@@ -58,7 +58,7 @@
 	exit (1);
 }
 
-int get_pattern (int pat_count, char *pats [])
+void get_pattern (int pat_count, char *pats [])
 {
 	int ix, err, tmp;
 
@@ -81,7 +81,7 @@
 	pat_len = pat_count;
 }
 
-int search_pattern (void)
+void search_pattern (void)
 {
 	for (bix = 0; bix < filesize; bix++) {
 		if (madr[bix] == patterns[0]) {
@@ -109,7 +109,7 @@
 	struct stat stat;
 
 	err = fstat (fd, &stat);
-	fprintf (stderr, "filesize: %d\n", err < 0 ? err : stat.st_size);
+	fprintf (stderr, "filesize: %ld\n", err < 0 ? (long)err : stat.st_size);
 	if (err < 0)
 		return err;
 	return (size_t) stat.st_size;
@@ -154,8 +154,8 @@
 	fprintf (stderr, "number of pattern matches = %d\n", num_matches);
 	if (num_matches == 0)
 		firstloc = ~0;
-	printf ("%d\n", firstloc);
-	fprintf (stderr, "%d\n", firstloc);
+	printf ("%ld\n", firstloc);
+	fprintf (stderr, "%ld\n", firstloc);
 
 	exit (num_matches ? 0 : 2);
 }
diff -Nru a/scripts/genksyms/Makefile b/scripts/genksyms/Makefile
--- a/scripts/genksyms/Makefile	2004-10-18 14:57:03 -07:00
+++ b/scripts/genksyms/Makefile	2004-10-18 14:57:03 -07:00
@@ -1,6 +1,6 @@
 
-host-progs	:= genksyms
-always		:= $(host-progs)
+hostprogs-y	:= genksyms
+always		:= $(hostprogs-y)
 
 genksyms-objs	:= genksyms.o parse.o lex.o
 
diff -Nru a/scripts/genksyms/genksyms.c b/scripts/genksyms/genksyms.c
--- a/scripts/genksyms/genksyms.c	2004-10-18 14:56:32 -07:00
+++ b/scripts/genksyms/genksyms.c	2004-10-18 14:56:32 -07:00
@@ -27,7 +27,9 @@
 #include <unistd.h>
 #include <assert.h>
 #include <stdarg.h>
+#ifdef __GNU_LIBRARY__
 #include <getopt.h>
+#endif /* __GNU_LIBRARY__ */
 
 #include "genksyms.h"
 
@@ -502,12 +504,21 @@
 	fputs("Usage:\n"
 	      "genksyms [-dDwqhV] > /path/to/.tmp_obj.ver\n"
 	      "\n"
+#ifdef __GNU_LIBRARY__
 	      "  -d, --debug           Increment the debug level (repeatable)\n"
 	      "  -D, --dump            Dump expanded symbol defs (for debugging only)\n"
 	      "  -w, --warnings        Enable warnings\n"
 	      "  -q, --quiet           Disable warnings (default)\n"
 	      "  -h, --help            Print this message\n"
 	      "  -V, --version         Print the release version\n"
+#else  /* __GNU_LIBRARY__ */
+             "  -d                    Increment the debug level (repeatable)\n"
+             "  -D                    Dump expanded symbol defs (for debugging only)\n"
+             "  -w                    Enable warnings\n"
+             "  -q                    Disable warnings (default)\n"
+             "  -h                    Print this message\n"
+             "  -V                    Print the release version\n"
+#endif /* __GNU_LIBRARY__ */
 	      , stderr);
 }
 
@@ -516,6 +527,7 @@
 {
   int o;
 
+#ifdef __GNU_LIBRARY__
   struct option long_opts[] = {
     {"debug", 0, 0, 'd'},
     {"warnings", 0, 0, 'w'},
@@ -528,6 +540,9 @@
 
   while ((o = getopt_long(argc, argv, "dwqVDk:p:",
 			  &long_opts[0], NULL)) != EOF)
+#else  /* __GNU_LIBRARY__ */
+  while ((o = getopt(argc, argv, "dwqVDk:p:")) != EOF)
+#endif /* __GNU_LIBRARY__ */
     switch (o)
       {
       case 'd':
diff -Nru a/scripts/kconfig/Makefile b/scripts/kconfig/Makefile
--- a/scripts/kconfig/Makefile	2004-10-18 14:57:04 -07:00
+++ b/scripts/kconfig/Makefile	2004-10-18 14:57:04 -07:00
@@ -67,7 +67,7 @@
 
 libkconfig-objs := zconf.tab.o
 
-host-progs	:= conf mconf qconf gconf
+hostprogs-y	:= conf mconf qconf gconf
 conf-objs	:= conf.o  libkconfig.so
 mconf-objs	:= mconf.o libkconfig.so
 
diff -Nru a/scripts/kconfig/confdata.c b/scripts/kconfig/confdata.c
--- a/scripts/kconfig/confdata.c	2004-10-18 14:57:04 -07:00
+++ b/scripts/kconfig/confdata.c	2004-10-18 14:57:04 -07:00
@@ -8,6 +8,7 @@
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
+#include <time.h>
 #include <unistd.h>
 
 #define LKC_DIRECT_LINK
@@ -268,6 +269,7 @@
 	char dirname[128], tmpname[128], newname[128];
 	int type, l;
 	const char *str;
+	time_t now;
 
 	dirname[0] = 0;
 	if (name && name[0]) {
@@ -301,14 +303,25 @@
 		if (!out_h)
 			return 1;
 	}
+	sym = sym_lookup("KERNELRELEASE", 0);
+	sym_calc_value(sym);
+	time(&now);
 	fprintf(out, "#\n"
 		     "# Automatically generated make config: don't edit\n"
-		     "#\n");
+		     "# Linux kernel version: %s\n"
+		     "# %s"
+		     "#\n",
+		     sym_get_string_value(sym),
+		     ctime(&now));
 	if (out_h)
 		fprintf(out_h, "/*\n"
 			       " * Automatically generated C config: don't edit\n"
+			       " * Linux kernel version: %s\n"
+			       " * %s"
 			       " */\n"
-			       "#define AUTOCONF_INCLUDED\n");
+			       "#define AUTOCONF_INCLUDED\n",
+			       sym_get_string_value(sym),
+			       ctime(&now));
 
 	if (!sym_change_count)
 		sym_clear_all_valid();
diff -Nru a/scripts/kconfig/gconf.c b/scripts/kconfig/gconf.c
--- a/scripts/kconfig/gconf.c	2004-10-18 14:57:04 -07:00
+++ b/scripts/kconfig/gconf.c	2004-10-18 14:57:04 -07:00
@@ -275,9 +275,8 @@
 					  /*"style", PANGO_STYLE_OBLIQUE, */
 					  NULL);
 
-	sprintf(title, "Linux Kernel v%s.%s.%s%s Configuration",
-		getenv("VERSION"), getenv("PATCHLEVEL"),
-		getenv("SUBLEVEL"), getenv("EXTRAVERSION"));
+	sprintf(title, "Linux Kernel v%s Configuration",
+		getenv("KERNELRELEASE"));
 	gtk_window_set_title(GTK_WINDOW(main_wnd), title);
 
 	gtk_widget_show(main_wnd);
diff -Nru a/scripts/kconfig/lkc.h b/scripts/kconfig/lkc.h
--- a/scripts/kconfig/lkc.h	2004-10-18 14:55:54 -07:00
+++ b/scripts/kconfig/lkc.h	2004-10-18 14:55:54 -07:00
@@ -59,9 +59,6 @@
 struct file *file_lookup(const char *name);
 int file_write_dep(const char *name);
 
-extern struct menu *current_entry;
-extern struct menu *current_menu;
-
 /* symbol.c */
 void sym_init(void);
 void sym_clear_all_valid(void);
diff -Nru a/scripts/kconfig/mconf.c b/scripts/kconfig/mconf.c
--- a/scripts/kconfig/mconf.c	2004-10-18 14:56:20 -07:00
+++ b/scripts/kconfig/mconf.c	2004-10-18 14:56:20 -07:00
@@ -18,6 +18,7 @@
 #include <string.h>
 #include <termios.h>
 #include <unistd.h>
+#include <regex.h>
 
 #define LKC_DIRECT_LINK
 #include "lkc.h"
@@ -28,7 +29,7 @@
 	"<Enter> selects submenus --->.  "
 	"Highlighted letters are hotkeys.  "
 	"Pressing <Y> includes, <N> excludes, <M> modularizes features.  "
-	"Press <Esc><Esc> to exit, <?> for Help.  "
+	"Press <Esc><Esc> to exit, <?> for Help, </> for Search.  "
 	"Legend: [*] built-in  [ ] excluded  <M> module  < > module capable",
 radiolist_instructions[] =
 	"Use the arrow keys to navigate this window or "
@@ -102,6 +103,10 @@
 static void show_helptext(const char *title, const char *text);
 static void show_help(struct menu *menu);
 static void show_readme(void);
+static void show_file(const char *filename, const char *title, int r, int c);
+static void show_expr(struct menu *menu, FILE *fp);
+static void search_conf(char *pattern);
+static int regex_match(const char *string, regex_t *re);
 
 static void cprint_init(void);
 static int cprint1(const char *fmt, ...);
@@ -274,6 +279,114 @@
 	return WEXITSTATUS(stat);
 }
 
+static int regex_match(const char *string, regex_t *re)
+{
+	int rc;
+
+	rc = regexec(re, string, (size_t) 0, NULL, 0);
+	if (rc)
+		return 0;
+	return 1;
+}
+
+static void show_expr(struct menu *menu, FILE *fp)
+{
+	bool hit = false;
+	fprintf(fp, "Depends:\n ");
+	if (menu->prompt->visible.expr) {
+		if (!hit)
+			hit = true;
+		expr_fprint(menu->prompt->visible.expr, fp);
+	}
+	if (!hit)
+		fprintf(fp, "None");
+	if (menu->sym) {
+		struct property *prop;
+		hit = false;
+		fprintf(fp, "\nSelects:\n ");
+		for_all_properties(menu->sym, prop, P_SELECT) {
+			if (!hit)
+				hit = true;
+			expr_fprint(prop->expr, fp);
+		}
+		if (!hit)
+			fprintf(fp, "None");
+		hit = false;
+		fprintf(fp, "\nSelected by:\n ");
+		if (menu->sym->rev_dep.expr) {
+			hit = true;
+			expr_fprint(menu->sym->rev_dep.expr, fp);
+		}
+		if (!hit)
+			fprintf(fp, "None");
+	}
+}
+
+static void search_conf(char *pattern)
+{
+	struct symbol *sym = NULL;
+	struct menu *menu[32] = { 0 };
+	struct property *prop = NULL;
+	FILE *fp = NULL;
+	bool hit = false;
+	int i, j, k, l;
+	regex_t re;
+
+	if (regcomp(&re, pattern, REG_EXTENDED|REG_NOSUB))
+		return;
+
+	fp = fopen(".search.tmp", "w");
+	if (fp == NULL) {
+		perror("fopen");
+		return;
+	}
+	for_all_symbols(i, sym) {
+		if (!sym->name)
+			continue;
+		if (!regex_match(sym->name, &re))
+			continue;
+		for_all_prompts(sym, prop) {
+			struct menu *submenu = prop->menu;
+			if (!submenu)
+				continue;
+			j = 0;
+			hit = false;
+			while (submenu) {
+				menu[j++] = submenu;
+				submenu = submenu->parent;
+			}
+			if (j > 0) {
+				if (!hit)
+					hit = true;
+				fprintf(fp, "%s (%s)\n", prop->text, sym->name);
+				fprintf(fp, "Location:\n");
+			}
+			for (k = j-2, l=1; k > 0; k--, l++) {
+				const char *prompt = menu_get_prompt(menu[k]);
+				if (menu[k]->sym)
+					fprintf(fp, "%*c-> %s (%s)\n",
+								l, ' ',
+								prompt,
+								menu[k]->sym->name);
+				else
+					fprintf(fp, "%*c-> %s\n",
+								l, ' ',
+								prompt);
+			}
+			if (hit) {
+				show_expr(menu[0], fp);
+				fprintf(fp, "\n\n\n");
+			}
+		}
+	}
+	if (!hit)
+		fprintf(fp, "No matches found.");
+	regfree(&re);
+	fclose(fp);
+	show_file(".search.tmp", "Search Results", rows, cols);
+	unlink(".search.tmp");
+}
+
 static void build_conf(struct menu *menu)
 {
 	struct symbol *sym;
@@ -463,6 +576,23 @@
 			cprint("    Save Configuration to an Alternate File");
 		}
 		stat = exec_conf();
+		if (stat == 26) {
+			char *pattern;
+
+			if (!strlen(input_buf))
+				continue;
+			pattern = malloc(sizeof(char)*sizeof(input_buf));
+			if (pattern == NULL) {
+				perror("malloc");
+				continue;
+			}
+			for (i = 0; input_buf[i]; i++)
+				pattern[i] = toupper(input_buf[i]);
+			pattern[i] = '\0';
+			search_conf(pattern);
+			free(pattern);
+			continue;
+		}
 		if (stat < 0)
 			continue;
 
@@ -550,17 +680,7 @@
 	fd = creat(".help.tmp", 0777);
 	write(fd, text, strlen(text));
 	close(fd);
-	do {
-		cprint_init();
-		if (title) {
-			cprint("--title");
-			cprint("%s", title);
-		}
-		cprint("--textbox");
-		cprint(".help.tmp");
-		cprint("%d", r);
-		cprint("%d", c);
-	} while (exec_conf() < 0);
+	show_file(".help.tmp", title, r, c);
 	unlink(".help.tmp");
 }
 
@@ -589,13 +709,22 @@
 
 static void show_readme(void)
 {
+	show_file("scripts/README.Menuconfig", NULL, rows, cols);
+}
+
+static void show_file(const char *filename, const char *title, int r, int c)
+{
 	do {
 		cprint_init();
+		if (title) {
+			cprint("--title");
+			cprint("%s", title);
+		}
 		cprint("--textbox");
-		cprint("scripts/README.Menuconfig");
-		cprint("%d", rows);
-		cprint("%d", cols);
-	} while (exec_conf() == -1);
+		cprint("%s", filename);
+		cprint("%d", r);
+		cprint("%d", c);
+	} while (exec_conf() < 0);
 }
 
 static void conf_choice(struct menu *menu)
diff -Nru a/scripts/kconfig/menu.c b/scripts/kconfig/menu.c
--- a/scripts/kconfig/menu.c	2004-10-18 14:57:03 -07:00
+++ b/scripts/kconfig/menu.c	2004-10-18 14:57:03 -07:00
@@ -10,7 +10,6 @@
 #include "lkc.h"
 
 struct menu rootmenu;
-struct menu *current_menu, *current_entry;
 static struct menu **last_entry_ptr;
 
 struct file *file_list;
diff -Nru a/scripts/kconfig/zconf.tab.c_shipped b/scripts/kconfig/zconf.tab.c_shipped
--- a/scripts/kconfig/zconf.tab.c_shipped	2004-10-18 14:56:50 -07:00
+++ b/scripts/kconfig/zconf.tab.c_shipped	2004-10-18 14:56:50 -07:00
@@ -175,6 +175,8 @@
 
 struct symbol *symbol_hash[257];
 
+static struct menu *current_menu, *current_entry;
+
 #define YYERROR_VERBOSE
 
 
diff -Nru a/scripts/kconfig/zconf.y b/scripts/kconfig/zconf.y
--- a/scripts/kconfig/zconf.y	2004-10-18 14:57:03 -07:00
+++ b/scripts/kconfig/zconf.y	2004-10-18 14:57:03 -07:00
@@ -25,6 +25,8 @@
 
 struct symbol *symbol_hash[257];
 
+static struct menu *current_menu, *current_entry;
+
 #define YYERROR_VERBOSE
 %}
 %expect 40
diff -Nru a/scripts/lxdialog/Makefile b/scripts/lxdialog/Makefile
--- a/scripts/lxdialog/Makefile	2004-10-18 14:56:49 -07:00
+++ b/scripts/lxdialog/Makefile	2004-10-18 14:56:49 -07:00
@@ -15,8 +15,8 @@
 endif
 endif
 
-host-progs	:= lxdialog
-always		:= ncurses $(host-progs)
+hostprogs-y	:= lxdialog
+always		:= ncurses $(hostprogs-y)
 
 lxdialog-objs := checklist.o menubox.o textbox.o yesno.o inputbox.o \
 		 util.o lxdialog.o msgbox.o
diff -Nru a/scripts/lxdialog/menubox.c b/scripts/lxdialog/menubox.c
--- a/scripts/lxdialog/menubox.c	2004-10-18 14:57:04 -07:00
+++ b/scripts/lxdialog/menubox.c	2004-10-18 14:57:04 -07:00
@@ -276,6 +276,15 @@
 
     while (key != ESC) {
 	key = wgetch(menu);
+	if ( key == '/' ) {
+		int ret = dialog_inputbox("Search Configuration Parameter",
+					"Enter Keyword", height, width,
+					(char *) NULL);
+		if (ret == 0) {
+			fprintf(stderr, "%s", dialog_input_result);
+			return 26;
+		}
+	}
 
 	if (key < 256 && isalpha(key)) key = tolower(key);
 
diff -Nru a/scripts/mksysmap b/scripts/mksysmap
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/scripts/mksysmap	2004-10-18 14:57:24 -07:00
@@ -0,0 +1,44 @@
+#!/bin/sh -x
+# Based on the vmlinux file create the System.map file
+# System.map is used by module-init tools and some debugging
+# tools to retreive the actual addresses of symbols in the kernel.
+#
+# Usage
+# mksysmap vmlinux System.map
+
+
+#####
+# Generate System.map (actual filename passed as second argument)
+
+# $NM produces the following output:
+# f0081e80 T alloc_vfsmnt
+
+#   The second row specify the type of the symbol:
+#   A = Absolute
+#   B = Uninitialised data (.bss)
+#   C = Comon symbol
+#   D = Initialised data
+#   G = Initialised data for small objects
+#   I = Indirect reference to another symbol
+#   N = Debugging symbol
+#   R = Read only
+#   S = Uninitialised data for small objects
+#   T = Text code symbol
+#   U = Undefined symbol
+#   V = Weak symbol
+#   W = Weak symbol
+#   Corresponding small letters are local symbols
+
+# For System.map filter away:
+#   a - local absolute symbols
+#   U - undefined global symbols
+#   w - local weak symbols
+
+# readprofile starts reading symbols when _stext is found, and
+# continue until it finds a symbol which is not either of 'T', 't',
+# 'W' or 'w'. __crc_ are 'A' and placed in the middle
+# so we just ignore them to let readprofile continue to work.
+# (At least sparc64 has __crc_ in the middle).
+
+$NM -n $1 | grep -v '\( [aUw] \)\|\(__crc_\)' > $2
+
diff -Nru a/scripts/mod/Makefile b/scripts/mod/Makefile
--- a/scripts/mod/Makefile	2004-10-18 14:55:54 -07:00
+++ b/scripts/mod/Makefile	2004-10-18 14:55:54 -07:00
@@ -1,5 +1,5 @@
-host-progs	:= modpost mk_elfconfig
-always		:= $(host-progs) empty.o
+hostprogs-y	:= modpost mk_elfconfig
+always		:= $(hostprogs-y) empty.o
 
 modpost-objs	:= modpost.o file2alias.o sumversion.o
 
diff -Nru a/scripts/mod/modpost.c b/scripts/mod/modpost.c
--- a/scripts/mod/modpost.c	2004-10-18 14:56:17 -07:00
+++ b/scripts/mod/modpost.c	2004-10-18 14:56:17 -07:00
@@ -343,7 +343,6 @@
 			crc = (unsigned int) sym->st_value;
 			add_exported_symbol(symname + strlen(CRC_PFX),
 					    mod, &crc);
-			modversions = 1;
 		}
 		break;
 	case SHN_UNDEF:
@@ -377,6 +376,10 @@
 			add_exported_symbol(symname + strlen(KSYMTAB_PFX),
 					    mod, NULL);
 		}
+		if (strcmp(symname, MODULE_SYMBOL_PREFIX "init_module") == 0)
+			mod->has_init = 1;
+		if (strcmp(symname, MODULE_SYMBOL_PREFIX "cleanup_module") == 0)
+			mod->has_cleanup = 1;
 		break;
 	}
 }
@@ -411,9 +414,6 @@
 	if (is_vmlinux(modname)) {
 		unsigned int fake_crc = 0;
 		have_vmlinux = 1;
-		/* May not have this if !CONFIG_MODULE_UNLOAD: fake it.
-		   If it appears, we'll get the real CRC. */
-		add_exported_symbol("cleanup_module", mod, &fake_crc);
 		add_exported_symbol("struct_module", mod, &fake_crc);
 		mod->skip = 1;
 	}
@@ -432,14 +432,8 @@
 	 * never passed as an argument to an exported function, so
 	 * the automatic versioning doesn't pick it up, but it's really
 	 * important anyhow */
-	if (modversions) {
+	if (modversions)
 		mod->unres = alloc_symbol("struct_module", mod->unres);
-
-		/* Always version init_module and cleanup_module, in
-		 * case module doesn't have its own. */
-		mod->unres = alloc_symbol("init_module", mod->unres);
-		mod->unres = alloc_symbol("cleanup_module", mod->unres);
-	}
 }
 
 #define SZ 500
@@ -480,7 +474,7 @@
 /* Header for the generated file */
 
 void
-add_header(struct buffer *b)
+add_header(struct buffer *b, struct module *mod)
 {
 	buf_printf(b, "#include <linux/module.h>\n");
 	buf_printf(b, "#include <linux/vermagic.h>\n");
@@ -492,10 +486,12 @@
 	buf_printf(b, "struct module __this_module\n");
 	buf_printf(b, "__attribute__((section(\".gnu.linkonce.this_module\"))) = {\n");
 	buf_printf(b, " .name = __stringify(KBUILD_MODNAME),\n");
-	buf_printf(b, " .init = init_module,\n");
-	buf_printf(b, "#ifdef CONFIG_MODULE_UNLOAD\n");
-	buf_printf(b, " .exit = cleanup_module,\n");
-	buf_printf(b, "#endif\n");
+	if (mod->has_init)
+		buf_printf(b, " .init = init_module,\n");
+	if (mod->has_cleanup)
+		buf_printf(b, "#ifdef CONFIG_MODULE_UNLOAD\n"
+			      " .exit = cleanup_module,\n"
+			      "#endif\n");
 	buf_printf(b, "};\n");
 }
 
@@ -649,7 +645,6 @@
 
 		if (!(mod = find_module(modname))) {
 			if (is_vmlinux(modname)) {
-				modversions = 1;
 				have_vmlinux = 1;
 			}
 			mod = new_module(NOFAIL(strdup(modname)));
@@ -696,11 +691,14 @@
 	char *dump_read = NULL, *dump_write = NULL;
 	int opt;
 
-	while ((opt = getopt(argc, argv, "i:o:")) != -1) {
+	while ((opt = getopt(argc, argv, "i:mo:")) != -1) {
 		switch(opt) {
 			case 'i':
 				dump_read = optarg;
 				break;
+			case 'm':
+				modversions = 1;
+				break;
 			case 'o':
 				dump_write = optarg;
 				break;
@@ -722,7 +720,7 @@
 
 		buf.pos = 0;
 
-		add_header(&buf);
+		add_header(&buf, mod);
 		add_versions(&buf, mod);
 		add_depends(&buf, mod, modules);
 		add_moddevtable(&buf, mod);
diff -Nru a/scripts/mod/modpost.h b/scripts/mod/modpost.h
--- a/scripts/mod/modpost.h	2004-10-18 14:55:46 -07:00
+++ b/scripts/mod/modpost.h	2004-10-18 14:55:46 -07:00
@@ -74,6 +74,8 @@
 	struct symbol *unres;
 	int seen;
 	int skip;
+	int has_init;
+	int has_cleanup;
 	struct buffer dev_table_buf;
 };
 
diff -Nru a/scripts/mod/sumversion.c b/scripts/mod/sumversion.c
--- a/scripts/mod/sumversion.c	2004-10-18 14:56:48 -07:00
+++ b/scripts/mod/sumversion.c	2004-10-18 14:56:48 -07:00
@@ -1,5 +1,9 @@
 #include <netinet/in.h>
+#ifdef __sun__
+#include <inttypes.h>
+#else
 #include <stdint.h>
+#endif
 #include <ctype.h>
 #include <errno.h>
 #include <string.h>
diff -Nru a/scripts/namespace.pl b/scripts/namespace.pl
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/scripts/namespace.pl	2004-10-18 14:57:23 -07:00
@@ -0,0 +1,449 @@
+#!/usr/bin/perl -w
+#
+#	namespace.pl.  Mon Aug 30 2004
+#
+#	Perform a name space analysis on the linux kernel.
+#
+#	Copyright Keith Owens <kaos@ocs.com.au>.  GPL.
+#
+#	Invoke by changing directory to the top of the kernel object
+#	tree then namespace.pl, no parameters.
+#
+#	Tuned for 2.1.x kernels with the new module handling, it will
+#	work with 2.0 kernels as well.
+#
+#	Last change 2.6.9-rc1, adding support for separate source and object
+#	trees.
+#
+#	The source must be compiled/assembled first, the object files
+#	are the primary input to this script.  Incomplete or missing
+#	objects will result in a flawed analysis.  Compile both vmlinux
+#	and modules.
+#
+#	Even with complete objects, treat the result of the analysis
+#	with caution.  Some external references are only used by
+#	certain architectures, others with certain combinations of
+#	configuration parameters.  Ideally the source should include
+#	something like
+#
+#	#ifndef CONFIG_...
+#	static
+#	#endif
+#	symbol_definition;
+#
+#	so the symbols are defined as static unless a particular
+#	CONFIG_... requires it to be external.
+#
+#	A symbol that is suffixed with '(export only)' has these properties
+#
+#	* It is global.
+#	* It is marked EXPORT_SYMBOL or EXPORT_SYMBOL_GPL, either in the same
+#	  source file or a different source file.
+#	* Given the current .config, nothing uses the symbol.
+#
+#	The symbol is a candidate for conversion to static, plus removal of the
+#	export.  But be careful that a different .config might use the symbol.
+#
+#
+#	Name space analysis and cleanup is an iterative process.  You cannot
+#	expect to find all the problems in a single pass.
+#
+#	* Identify possibly unnecessary global declarations, verify that they
+#	  really are unnecessary and change them to static.
+#	* Compile and fix up gcc warnings about static, removing dead symbols
+#	  as necessary.
+#	* make clean and rebuild with different configs (especially
+#	  CONFIG_MODULES=n) to see which symbols are being defined when the
+#	  config does not require them.  These symbols bloat the kernel object
+#	  for no good reason, which is frustrating for embedded systems.
+#	* Wrap config sensitive symbols in #ifdef CONFIG_foo, as long as the
+#	  code does not get too ugly.
+#	* Repeat the name space analysis until you can live with with the
+#	  result.
+#
+
+require 5;	# at least perl 5
+use strict;
+use File::Find;
+
+my $nm = "/usr/bin/nm -p";
+my $objdump = "/usr/bin/objdump -s -j .comment";
+my $srctree = "";
+my $objtree = "";
+$srctree = "$ENV{'srctree'}/" if (exists($ENV{'srctree'}));
+$objtree = "$ENV{'objtree'}/" if (exists($ENV{'objtree'}));
+
+if ($#ARGV != -1) {
+	print STDERR "usage: $0 takes no parameters\n";
+	die("giving up\n");
+}
+
+my %nmdata = ();	# nm data for each object
+my %def = ();		# all definitions for each name
+my %ksymtab = ();	# names that appear in __ksymtab_
+my %ref = ();		# $ref{$name} exists if there is a true external reference to $name
+my %export = ();	# $export{$name} exists if there is an EXPORT_... of $name
+
+&find(\&linux_objects, '.');	# find the objects and do_nm on them
+&list_multiply_defined();
+&resolve_external_references();
+&list_extra_externals();
+
+exit(0);
+
+sub linux_objects
+{
+	# Select objects, ignoring objects which are only created by
+	# merging other objects.  Also ignore all of modules, scripts
+	# and compressed.  Most conglomerate objects are handled by do_nm,
+	# this list only contains the special cases.  These include objects
+	# that are linked from just one other object and objects for which
+	# there is really no permanent source file.
+	my $basename = $_;
+	$_ = $File::Find::name;
+	s:^\./::;
+	if (/.*\.o$/ &&
+		! (
+		m:/built-in.o$:
+		|| m:arch/i386/kernel/vsyscall-syms.o$:
+		|| m:arch/ia64/ia32/ia32.o$:
+		|| m:arch/ia64/kernel/gate-syms.o$:
+		|| m:arch/ia64/lib/__divdi3.o$:
+		|| m:arch/ia64/lib/__divsi3.o$:
+		|| m:arch/ia64/lib/__moddi3.o$:
+		|| m:arch/ia64/lib/__modsi3.o$:
+		|| m:arch/ia64/lib/__udivdi3.o$:
+		|| m:arch/ia64/lib/__udivsi3.o$:
+		|| m:arch/ia64/lib/__umoddi3.o$:
+		|| m:arch/ia64/lib/__umodsi3.o$:
+		|| m:arch/ia64/scripts/check_gas_for_hint.o$:
+		|| m:arch/ia64/sn/kernel/xp.o$:
+		|| m:boot/bbootsect.o$:
+		|| m:boot/bsetup.o$:
+		|| m:/bootsect.o$:
+		|| m:/boot/setup.o$:
+		|| m:/compressed/:
+		|| m:drivers/cdrom/driver.o$:
+		|| m:drivers/char/drm/tdfx_drv.o$:
+		|| m:drivers/ide/ide-detect.o$:
+		|| m:drivers/ide/pci/idedriver-pci.o$:
+		|| m:drivers/media/media.o$:
+		|| m:drivers/scsi/sd_mod.o$:
+		|| m:drivers/video/video.o$:
+		|| m:fs/devpts/devpts.o$:
+		|| m:fs/exportfs/exportfs.o$:
+		|| m:fs/hugetlbfs/hugetlbfs.o$:
+		|| m:fs/msdos/msdos.o$:
+		|| m:fs/nls/nls.o$:
+		|| m:fs/ramfs/ramfs.o$:
+		|| m:fs/romfs/romfs.o$:
+		|| m:fs/vfat/vfat.o$:
+		|| m:init/mounts.o$:
+		|| m:^modules/:
+		|| m:net/netlink/netlink.o$:
+		|| m:net/sched/sched.o$:
+		|| m:/piggy.o$:
+		|| m:^scripts/:
+		|| m:sound/.*/snd-:
+		|| m:^.*/\.tmp_:
+		|| m:^\.tmp_:
+		|| m:/vmlinux-obj.o$:
+		)
+	) {
+		do_nm($basename, $_);
+	}
+	$_ = $basename;		# File::Find expects $_ untouched (undocumented)
+}
+
+sub do_nm
+{
+	my ($basename, $fullname) = @_;
+	my ($source, $type, $name);
+	if (! -e $basename) {
+		printf STDERR "$basename does not exist\n";
+		return;
+	}
+	if ($fullname !~ /\.o$/) {
+		printf STDERR "$fullname is not an object file\n";
+		return;
+	}
+	($source = $fullname) =~ s/\.o$//;
+	if (-e "$objtree$source.c" || -e "$objtree$source.S") {
+		$source = "$objtree$source";
+	} else {
+		$source = "$srctree$source";
+	}
+	if (! -e "$source.c" && ! -e "$source.S") {
+		# No obvious source, exclude the object if it is conglomerate
+		if (! open(OBJDUMPDATA, "$objdump $basename|")) {
+			printf STDERR "$objdump $fullname failed $!\n";
+			return;
+		}
+		my $comment;
+		while (<OBJDUMPDATA>) {
+			chomp();
+			if (/^In archive/) {
+				# Archives are always conglomerate
+				$comment = "GCC:GCC:";
+				last;
+			}
+			next if (! /^[ 0-9a-f]{5,} /);
+			$comment .= substr($_, 43);
+		}
+		close(OBJDUMPDATA);
+		if (!defined($comment) || $comment !~ /GCC\:.*GCC\:/m) {
+			printf STDERR "No source file found for $fullname\n";
+		}
+		return;
+	}
+	if (! open(NMDATA, "$nm $basename|")) {
+		printf STDERR "$nm $fullname failed $!\n";
+		return;
+	}
+	my @nmdata;
+	while (<NMDATA>) {
+		chop;
+		($type, $name) = (split(/ +/, $_, 3))[1..2];
+		# Expected types
+		# A absolute symbol
+		# B weak external reference to data that has been resolved
+		# C global variable, uninitialised
+		# D global variable, initialised
+		# G global variable, initialised, small data section
+		# R global array, initialised
+		# S global variable, uninitialised, small bss
+		# T global label/procedure
+		# U external reference
+		# W weak external reference to text that has been resolved
+		# a assembler equate
+		# b static variable, uninitialised
+		# d static variable, initialised
+		# g static variable, initialised, small data section
+		# r static array, initialised
+		# s static variable, uninitialised, small bss
+		# t static label/procedures
+		# w weak external reference to text that has not been resolved
+		# ? undefined type, used a lot by modules
+		if ($type !~ /^[ABCDGRSTUWabdgrstw?]$/) {
+			printf STDERR "nm output for $fullname contains unknown type '$_'\n";
+		}
+		elsif ($name =~ /\./) {
+			# name with '.' is local static
+		}
+		else {
+			$type = 'R' if ($type eq '?');	# binutils replaced ? with R at one point
+			# binutils keeps changing the type for exported symbols, force it to R
+			$type = 'R' if ($name =~ /^__ksymtab/ || $name =~ /^__kstrtab/);
+			$name =~ s/_R[a-f0-9]{8}$//;	# module versions adds this
+			if ($type =~ /[ABCDGRSTW]/ &&
+				$name ne 'init_module' &&
+				$name ne 'cleanup_module' &&
+				$name ne 'Using_Versions' &&
+				$name !~ /^Version_[0-9]+$/ &&
+				$name !~ /^__parm_/ &&
+				$name !~ /^__kstrtab/ &&
+				$name !~ /^__ksymtab/ &&
+				$name !~ /^__kcrctab_/ &&
+				$name !~ /^__exitcall_/ &&
+				$name !~ /^__initcall_/ &&
+				$name !~ /^__kdb_initcall_/ &&
+				$name !~ /^__kdb_exitcall_/ &&
+				$name !~ /^__module_/ &&
+				$name !~ /^__mod_/ &&
+				$name !~ /^__crc_/ &&
+				$name ne '__this_module' &&
+				$name ne 'kernel_version') {
+				if (!exists($def{$name})) {
+					$def{$name} = [];
+				}
+				push(@{$def{$name}}, $fullname);
+			}
+			push(@nmdata, "$type $name");
+			if ($name =~ /^__ksymtab_/) {
+				$name = substr($name, 10);
+				if (!exists($ksymtab{$name})) {
+					$ksymtab{$name} = [];
+				}
+				push(@{$ksymtab{$name}}, $fullname);
+			}
+		}
+	}
+	close(NMDATA);
+	if ($#nmdata < 0) {
+		if (
+			$fullname ne "lib/brlock.o"
+			&& $fullname ne "lib/dec_and_lock.o"
+			&& $fullname ne "fs/xfs/xfs_macros.o"
+			&& $fullname ne "drivers/ide/ide-probe-mini.o"
+			&& $fullname ne "usr/initramfs_data.o"
+			&& $fullname ne "drivers/acpi/executer/exdump.o"
+			&& $fullname ne "drivers/acpi/resources/rsdump.o"
+			&& $fullname ne "drivers/acpi/namespace/nsdumpdv.o"
+			&& $fullname ne "drivers/acpi/namespace/nsdump.o"
+			&& $fullname ne "arch/ia64/sn/kernel/sn2/io.o"
+			&& $fullname ne "arch/ia64/kernel/gate-data.o"
+			&& $fullname ne "drivers/ieee1394/oui.o"
+			&& $fullname ne "security/capability.o"
+			&& $fullname ne "sound/core/wrappers.o"
+			&& $fullname ne "fs/ntfs/sysctl.o"
+			&& $fullname ne "fs/jfs/jfs_debug.o"
+		) {
+			printf "No nm data for $fullname\n";
+		}
+		return;
+	}
+	$nmdata{$fullname} = \@nmdata;
+}
+
+sub drop_def
+{
+	my ($object, $name) = @_;
+	my $nmdata = $nmdata{$object};
+	my ($i, $j);
+	for ($i = 0; $i <= $#{$nmdata}; ++$i) {
+		if ($name eq (split(' ', $nmdata->[$i], 2))[1]) {
+			splice(@{$nmdata{$object}}, $i, 1);
+			my $def = $def{$name};
+			for ($j = 0; $j < $#{$def{$name}}; ++$j) {
+				if ($def{$name}[$j] eq $object) {
+					splice(@{$def{$name}}, $j, 1);
+				}
+			}
+			last;
+		}
+	}
+}
+
+sub list_multiply_defined
+{
+	my ($name, $module);
+	foreach $name (keys(%def)) {
+		if ($#{$def{$name}} > 0) {
+			# Special case for cond_syscall
+			if ($#{$def{$name}} == 1 && $name =~ /^sys_/ &&
+			    ($def{$name}[0] eq "kernel/sys.o" ||
+			     $def{$name}[1] eq "kernel/sys.o")) {
+				&drop_def("kernel/sys.o", $name);
+				next;
+			}
+			# Special case for i386 entry code
+			if ($#{$def{$name}} == 1 && $name =~ /^__kernel_/ &&
+			    $def{$name}[0] eq "arch/i386/kernel/vsyscall-int80.o" &&
+			    $def{$name}[1] eq "arch/i386/kernel/vsyscall-sysenter.o") {
+				&drop_def("arch/i386/kernel/vsyscall-sysenter.o", $name);
+				next;
+			}
+			printf "$name is multiply defined in :-\n";
+			foreach $module (@{$def{$name}}) {
+				printf "\t$module\n";
+			}
+		}
+	}
+}
+
+sub resolve_external_references
+{
+	my ($object, $type, $name, $i, $j, $kstrtab, $ksymtab, $export);
+	printf "\n";
+	foreach $object (keys(%nmdata)) {
+		my $nmdata = $nmdata{$object};
+		for ($i = 0; $i <= $#{$nmdata}; ++$i) {
+			($type, $name) = split(' ', $nmdata->[$i], 2);
+			if ($type eq "U" || $type eq "w") {
+				if (exists($def{$name}) || exists($ksymtab{$name})) {
+					# add the owning object to the nmdata
+					$nmdata->[$i] = "$type $name $object";
+					# only count as a reference if it is not EXPORT_...
+					$kstrtab = "R __kstrtab_$name";
+					$ksymtab = "R __ksymtab_$name";
+					$export = 0;
+					for ($j = 0; $j <= $#{$nmdata}; ++$j) {
+						if ($nmdata->[$j] eq $kstrtab ||
+						    $nmdata->[$j] eq $ksymtab) {
+							$export = 1;
+							last;
+						}
+					}
+					if ($export) {
+						$export{$name} = "";
+					}
+					else {
+						$ref{$name} = ""
+					}
+				}
+				elsif (    $name ne "mod_use_count_"
+					&& $name ne "__initramfs_end"
+					&& $name ne "__initramfs_start"
+					&& $name ne "_einittext"
+					&& $name ne "_sinittext"
+					&& $name ne "kallsyms_names"
+					&& $name ne "kallsyms_num_syms"
+					&& $name ne "kallsyms_addresses"
+					&& $name ne "__this_module"
+					&& $name ne "_etext"
+					&& $name ne "_edata"
+					&& $name ne "_end"
+					&& $name ne "__bss_start"
+					&& $name ne "_text"
+					&& $name ne "_stext"
+					&& $name ne "__gp"
+					&& $name ne "ia64_unw_start"
+					&& $name ne "ia64_unw_end"
+					&& $name ne "__init_begin"
+					&& $name ne "__init_end"
+					&& $name ne "__bss_stop"
+					&& $name ne "__nosave_begin"
+					&& $name ne "__nosave_end"
+					&& $name ne "pg0"
+					&& $name ne "__module_text_address"
+					&& $name !~ /^__sched_text_/
+					&& $name !~ /^__start_/
+					&& $name !~ /^__end_/
+					&& $name !~ /^__stop_/
+					&& $name !~ /^__scheduling_functions_.*_here/
+					&& $name !~ /^__.*initcall_/
+					&& $name !~ /^__.*per_cpu_start/
+					&& $name !~ /^__.*per_cpu_end/
+					&& $name !~ /^__alt_instructions/
+					&& $name !~ /^__setup_/
+				) {
+					printf "Cannot resolve ";
+					printf "weak " if ($type eq "w");
+					printf "reference to $name from $object\n";
+				}
+			}
+		}
+	}
+}
+
+sub list_extra_externals
+{
+	my %noref = ();
+	my ($name, @module, $module, $export);
+	foreach $name (keys(%def)) {
+		if (! exists($ref{$name})) {
+			@module = @{$def{$name}};
+			foreach $module (@module) {
+				if (! exists($noref{$module})) {
+					$noref{$module} = [];
+				}
+				push(@{$noref{$module}}, $name);
+			}
+		}
+	}
+	if (%noref) {
+		printf "\nExternally defined symbols with no external references\n";
+		foreach $module (sort(keys(%noref))) {
+			printf "  $module\n";
+			foreach (sort(@{$noref{$module}})) {
+				if (exists($export{$_})) {
+					$export = " (export only)";
+				}
+				else {
+					$export = "";
+				}
+				printf "    $_$export\n";
+			}
+		}
+	}
+}
diff -Nru a/scripts/package/Makefile b/scripts/package/Makefile
--- a/scripts/package/Makefile	2004-10-18 14:56:33 -07:00
+++ b/scripts/package/Makefile	2004-10-18 14:56:33 -07:00
@@ -51,7 +51,7 @@
 	$(RPM) --target $(UTS_MACHINE) -ta ../$(KERNELPATH).tar.gz
 	rm ../$(KERNELPATH).tar.gz
 
-clean-rule +=  rm -f $(objtree)/kernel.spec
+clean-files := $(objtree)/kernel.spec
 
 # binrpm-pkg
 .PHONY: binrpm-pkg
@@ -67,7 +67,7 @@
 
 	$(RPM) --define "_builddir $(srctree)" --target $(UTS_MACHINE) -bb $<
 
-clean-rule += rm -f $(objtree)/binkernel.spec
+clean-files += $(objtree)/binkernel.spec
 
 # Deb target
 # ---------------------------------------------------------------------------
@@ -77,7 +77,7 @@
 	$(MAKE)
 	$(CONFIG_SHELL) $(srctree)/scripts/package/builddeb
 
-clean-rule += && rm -rf $(objtree)/debian/
+clean-dirs += $(objtree)/debian/
 
 
 # Help text displayed when executing 'make help'
diff -Nru a/scripts/package/builddeb b/scripts/package/builddeb
--- a/scripts/package/builddeb	2004-10-18 14:56:28 -07:00
+++ b/scripts/package/builddeb	2004-10-18 14:56:28 -07:00
@@ -12,7 +12,7 @@
 set -e
 
 # Some variables and settings used throughout the script
-version="$VERSION.$PATCHLEVEL.$SUBLEVEL$EXTRAVERSION"
+version=$KERNELRELEASE
 tmpdir="$objtree/debian/tmp"
 
 # Setup the directory structure
diff -Nru a/scripts/package/mkspec b/scripts/package/mkspec
--- a/scripts/package/mkspec	2004-10-18 14:55:54 -07:00
+++ b/scripts/package/mkspec	2004-10-18 14:55:54 -07:00
@@ -21,11 +21,12 @@
 	PROVIDES=kernel-drm
 fi
 
-PROVIDES="$PROVIDES kernel-$VERSION.$PATCHLEVEL.$SUBLEVEL$EXTRAVERSION"
+PROVIDES="$PROVIDES kernel-$KERNELRELEASE"
+__KERNELRELEASE=`echo $KERNELRELEASE | sed -e "s/-//g"`
 
 echo "Name: kernel"
 echo "Summary: The Linux Kernel"
-echo "Version: "$VERSION.$PATCHLEVEL.$SUBLEVEL$EXTRAVERSION | sed -e "s/-//g"
+echo "Version: $__KERNELRELEASE"
 # we need to determine the NEXT version number so that uname and
 # rpm -q will agree
 echo "Release: `. $srctree/scripts/mkversion`"
@@ -35,8 +36,7 @@
 echo "URL: http://www.kernel.org"
 
 if ! $PREBUILT; then
-echo -n "Source: kernel-$VERSION.$PATCHLEVEL.$SUBLEVEL"
-echo "$EXTRAVERSION.tar.gz" | sed -e "s/-//g"
+echo "Source: kernel-$__KERNELRELEASE.tar.gz"
 fi
 
 echo "BuildRoot: /var/tmp/%{name}-%{PACKAGE_VERSION}-root"
@@ -57,19 +57,19 @@
 echo "%build"
 
 if ! $PREBUILT; then
-echo "make clean && make"
+echo "make clean && make %{_smp_mflags}"
 echo ""
 fi
 
 echo "%install"
 echo 'mkdir -p $RPM_BUILD_ROOT/boot $RPM_BUILD_ROOT/lib $RPM_BUILD_ROOT/lib/modules'
 
-echo 'INSTALL_MOD_PATH=$RPM_BUILD_ROOT make modules_install'
-echo 'cp $KBUILD_IMAGE $RPM_BUILD_ROOT'"/boot/vmlinuz-$VERSION.$PATCHLEVEL.$SUBLEVEL$EXTRAVERSION"
+echo 'INSTALL_MOD_PATH=$RPM_BUILD_ROOT make %{_smp_mflags} modules_install'
+echo 'cp $KBUILD_IMAGE $RPM_BUILD_ROOT'"/boot/vmlinuz-$KERNELRELEASE"
 
-echo 'cp System.map $RPM_BUILD_ROOT'"/boot/System.map-$VERSION.$PATCHLEVEL.$SUBLEVEL$EXTRAVERSION"
+echo 'cp System.map $RPM_BUILD_ROOT'"/boot/System.map-$KERNELRELEASE"
 
-echo 'cp .config $RPM_BUILD_ROOT'"/boot/config-$VERSION.$PATCHLEVEL.$SUBLEVEL$EXTRAVERSION"
+echo 'cp .config $RPM_BUILD_ROOT'"/boot/config-$KERNELRELEASE"
 echo ""
 echo "%clean"
 echo '#echo -rf $RPM_BUILD_ROOT'
@@ -77,6 +77,6 @@
 echo "%files"
 echo '%defattr (-, root, root)'
 echo "%dir /lib/modules"
-echo "/lib/modules/$VERSION.$PATCHLEVEL.$SUBLEVEL$EXTRAVERSION"
+echo "/lib/modules/$KERNELRELEASE"
 echo "/boot/*"
 echo ""
diff -Nru a/scripts/patch-kernel b/scripts/patch-kernel
--- a/scripts/patch-kernel	2004-10-18 14:56:27 -07:00
+++ b/scripts/patch-kernel	2004-10-18 14:56:27 -07:00
@@ -40,17 +40,24 @@
 #
 # Added -ac option, use -ac or -ac9 (say) to stop at a particular version
 #       Dave Gilbert <linux@treblig.org>, 29th September 2001.
+#
+# Add support for (use of) EXTRAVERSION (to support 2.6.8.x, e.g.);
+# update usage message;
+# fix some whitespace damage;
+# be smarter about stopping when current version is larger than requested;
+#	Randy Dunlap <rddunlap@osdl.org>, 2004-AUG-18.
 
 # Set directories from arguments, or use defaults.
 sourcedir=${1-/usr/src/linux}
 patchdir=${2-.}
-stopvers=${3-imnotaversion}
+stopvers=${3-default}
 
-if [ "$1" = -h -o "$1" = --help -o ! -r "$sourcedir/Makefile" ]; then
+if [ "$1" == -h -o "$1" == --help -o ! -r "$sourcedir/Makefile" ]; then
 cat << USAGE
 usage: patch-kernel [-h] [ sourcedir [ patchdir [ stopversion ] [ -acxx ] ] ]
-  The source directory defaults to /usr/src/linux, and
-  the patch directory defaults to the current directory.
+  source directory defaults to /usr/src/linux,
+  patch directory defaults to the current directory,
+  stopversion defaults to <all in patchdir>.
 USAGE
 exit 1
 fi
@@ -77,7 +84,7 @@
 		uncomp="gunzip -dc"
   elif [ -r ${filebase}.bz  ]; then
 		ext=".bz"
-    name="bzip"
+		name="bzip"
 		uncomp="bunzip -dc"
   elif [ -r ${filebase}.bz2 ]; then
 		ext=".bz2"
@@ -96,8 +103,8 @@
 		name="plaintext"
 		uncomp="cat"
   else
-	  return 1;
-	fi
+	return 1;
+  fi
 
   return 0;
 }
@@ -126,48 +133,100 @@
   return 0;
 }
 
-# set current VERSION, PATCHLEVEL, SUBLEVEL, EXTERVERSION
-eval `sed -n -e 's/^\([A-Z]*\) = \([0-9]*\)$/\1=\2/p' -e 's/^\([A-Z]*\) = \(-[-a-z0-9]*\)$/\1=\2/p' $sourcedir/Makefile`
+# set current VERSION, PATCHLEVEL, SUBLEVEL, EXTRAVERSION
+TMPFILE=`mktemp .tmpver.XXXXXX` || { echo "cannot make temp file" ; exit 1; }
+grep -E "^(VERSION|PATCHLEVEL|SUBLEVEL|EXTRAVERSION)" $sourcedir/Makefile > $TMPFILE
+tr -d [:blank:] < $TMPFILE > $TMPFILE.1
+source $TMPFILE.1
+rm -f $TMPFILE*
 if [ -z "$VERSION" -o -z "$PATCHLEVEL" -o -z "$SUBLEVEL" ]
 then
     echo "unable to determine current kernel version" >&2
     exit 1
 fi
 
-echo "Current kernel version is $VERSION.$PATCHLEVEL.$SUBLEVEL${EXTRAVERSION}"
+NAME=`grep ^NAME $sourcedir/Makefile`
+NAME=${NAME##*=}
+
+echo "Current kernel version is $VERSION.$PATCHLEVEL.$SUBLEVEL${EXTRAVERSION} ($NAME)"
 
+# strip EXTRAVERSION to just a number (drop leading '.' and trailing additions)
+EXTRAVER=
 if [ x$EXTRAVERSION != "x" ]
 then
-  echo "I'm sorry but patch-kernel can't work with a kernel source tree that is not a base version"
-	exit 1;
+	if [ ${EXTRAVERSION:0:1} == "." ]; then
+		EXTRAVER=${EXTRAVERSION:1}
+	else
+		EXTRAVER=$EXTRAVERSION
+	fi
+	EXTRAVER=${EXTRAVER%%[[:punct:]]*}
+	#echo "patch-kernel: changing EXTRAVERSION from $EXTRAVERSION to $EXTRAVER"
 fi
 
-while :
+#echo "stopvers=$stopvers"
+if [ $stopvers != "default" ]; then
+	STOPSUBLEVEL=`echo $stopvers | cut -d. -f3`
+	STOPEXTRA=`echo $stopvers | cut -d. -f4`
+	#echo "STOPSUBLEVEL=$STOPSUBLEVEL, STOPEXTRA=$STOPEXTRA"
+else
+	STOPSUBLEVEL=9999
+	STOPEXTRA=9999
+fi
+
+while :				# incrementing SUBLEVEL (s in v.p.s)
 do
-    CURRENTFULLVERSION="$VERSION.$PATCHLEVEL.$SUBLEVEL"
-    if [ $stopvers = $CURRENTFULLVERSION ]
-    then
-        echo "Stoping at $CURRENTFULLVERSION base as requested."
+    if [ x$EXTRAVER != "x" ]; then
+	CURRENTFULLVERSION="$VERSION.$PATCHLEVEL.$SUBLEVEL.$EXTRAVER"
+    else
+	CURRENTFULLVERSION="$VERSION.$PATCHLEVEL.$SUBLEVEL"
+    fi
+
+    if [ $stopvers == $CURRENTFULLVERSION ]; then
+        echo "Stopping at $CURRENTFULLVERSION base as requested."
         break
     fi
 
-    SUBLEVEL=`expr $SUBLEVEL + 1`
+    while :			# incrementing EXTRAVER (x in v.p.s.x)
+    do
+	EXTRAVER=$((EXTRAVER + 1))
+	FULLVERSION="$VERSION.$PATCHLEVEL.$SUBLEVEL.$EXTRAVER"
+	#echo "... trying $FULLVERSION ..."
+
+	patch=patch-$FULLVERSION
+
+	# See if the file exists and find extension
+	findFile $patchdir/${patch} || break
+
+	# Apply the patch and check all is OK
+	applyPatch $patch || break
+
+	continue 2
+    done
+
+    EXTRAVER=
+    SUBLEVEL=$((SUBLEVEL + 1))
     FULLVERSION="$VERSION.$PATCHLEVEL.$SUBLEVEL"
+    #echo "___ trying $FULLVERSION ___"
+
+    if [ $((SUBLEVEL)) -gt $((STOPSUBLEVEL)) ]; then
+	echo "Stopping since sublevel ($SUBLEVEL) is beyond stop-sublevel ($STOPSUBLEVEL)"
+	exit 1
+    fi
 
     patch=patch-$FULLVERSION
 
-		# See if the file exists and find extension
-		findFile $patchdir/${patch} || break
+    # See if the file exists and find extension
+    findFile $patchdir/${patch} || break
 
     # Apply the patch and check all is OK
     applyPatch $patch || break
 done
+#echo "base all done"
 
 if [ x$gotac != x ]; then
   # Out great user wants the -ac patches
 	# They could have done -ac (get latest) or -acxx where xx=version they want
-	if [ $gotac == "-ac" ]
-	then
+	if [ $gotac == "-ac" ]; then
 	  # They want the latest version
 		HIGHESTPATCH=0
 		for PATCHNAMES in $patchdir/patch-${CURRENTFULLVERSION}-ac*\.*
@@ -176,18 +235,16 @@
 			# Check it is actually a recognised patch type
 			findFile $patchdir/patch-${CURRENTFULLVERSION}-ac${ACVALUE} || break
 
-		  if [ $ACVALUE -gt $HIGHESTPATCH ]
-			then
+		  if [ $ACVALUE -gt $HIGHESTPATCH ]; then
 			  HIGHESTPATCH=$ACVALUE
 		  fi
 		done
 
-		if [ $HIGHESTPATCH -ne 0 ]
-		then
+		if [ $HIGHESTPATCH -ne 0 ]; then
 			findFile $patchdir/patch-${CURRENTFULLVERSION}-ac${HIGHESTPATCH} || break
 			applyPatch patch-${CURRENTFULLVERSION}-ac${HIGHESTPATCH}
 		else
-		  echo "No ac patches found"
+		  echo "No -ac patches found"
 		fi
 	else
 	  # They want an exact version
@@ -198,5 +255,3 @@
 		applyPatch patch-${CURRENTFULLVERSION}${gotac}
 	fi
 fi
-
-
diff -Nru a/scripts/ver_linux b/scripts/ver_linux
--- a/scripts/ver_linux	2004-10-18 14:56:33 -07:00
+++ b/scripts/ver_linux	2004-10-18 14:56:33 -07:00
@@ -37,8 +37,11 @@
 fsck.jfs -V 2>&1 | grep version | sed 's/,//' |  awk \
 'NR==1 {print "jfsutils              ", $3}'
 
-reiserfsck -V 2>&1 | grep reiserfsprogs | awk \
-'NR==1{print "reiserfsprogs         ", $NF}'
+reiserfsck -V 2>&1 | grep reiserfsck | awk \
+'NR==1{print "reiserfsprogs         ", $2}'
+
+fsck.reiser4 -V 2>&1 | grep fsck.reiser4 | awk \
+'NR==1{print "reiser4progs          ", $2}'
 
 xfs_db -V 2>&1 | grep version | awk \
 'NR==1{print "xfsprogs              ", $3}'
diff -Nru a/security/Kconfig b/security/Kconfig
--- a/security/Kconfig	2004-10-18 14:56:48 -07:00
+++ b/security/Kconfig	2004-10-18 14:56:48 -07:00
@@ -26,14 +26,14 @@
 
 config SECURITY_CAPABILITIES
 	tristate "Default Linux Capabilities"
-	depends on SECURITY!=n
+	depends on SECURITY
 	help
 	  This enables the "default" Linux capabilities functionality.
 	  If you are unsure how to answer this question, answer Y.
 
 config SECURITY_ROOTPLUG
 	tristate "Root Plug Support"
-	depends on USB && SECURITY!=n
+	depends on USB && SECURITY
 	help
 	  This is a sample LSM module that should only be used as such.
 	  It prevents any programs running with egid == 0 if a specific
diff -Nru a/security/commoncap.c b/security/commoncap.c
--- a/security/commoncap.c	2004-10-18 14:56:28 -07:00
+++ b/security/commoncap.c	2004-10-18 14:56:28 -07:00
@@ -314,10 +314,10 @@
 	/*
 	 * Sometimes we want to use more memory than we have
 	 */
-	if (sysctl_overcommit_memory == 1)
+	if (sysctl_overcommit_memory == OVERCOMMIT_ALWAYS)
 		return 0;
 
-	if (sysctl_overcommit_memory == 0) {
+	if (sysctl_overcommit_memory == OVERCOMMIT_GUESS) {
 		unsigned long n;
 
 		free = get_page_cache_size();
@@ -357,6 +357,11 @@
 
 	allowed = (totalram_pages - hugetlb_total_pages())
 	       	* sysctl_overcommit_ratio / 100;
+	/*
+	 * Leave the last 3% for root
+	 */
+	if (!capable(CAP_SYS_ADMIN))
+		allowed -= allowed / 32;
 	allowed += total_swap_pages;
 
 	if (atomic_read(&vm_committed_space) < allowed)
diff -Nru a/security/dummy.c b/security/dummy.c
--- a/security/dummy.c	2004-10-18 14:56:17 -07:00
+++ b/security/dummy.c	2004-10-18 14:56:17 -07:00
@@ -121,10 +121,10 @@
 	/*
 	 * Sometimes we want to use more memory than we have
 	 */
-	if (sysctl_overcommit_memory == 1)
+	if (sysctl_overcommit_memory == OVERCOMMIT_ALWAYS)
 		return 0;
 
-	if (sysctl_overcommit_memory == 0) {
+	if (sysctl_overcommit_memory == OVERCOMMIT_GUESS) {
 		free = get_page_cache_size();
 		free += nr_free_pages();
 		free += nr_swap_pages;
diff -Nru a/security/security.c b/security/security.c
--- a/security/security.c	2004-10-18 14:55:53 -07:00
+++ b/security/security.c	2004-10-18 14:55:53 -07:00
@@ -49,7 +49,7 @@
 }
 
 /**
- * security_scaffolding_startup - initialzes the security scaffolding framework
+ * security_scaffolding_startup - initializes the security scaffolding framework
  *
  * This should be called early in the kernel initialization sequence.
  */
@@ -183,7 +183,7 @@
  * capable - calls the currently loaded security module's capable() function with the specified capability
  * @cap: the requested capability level.
  *
- * This function calls the currently loaded security module's cabable()
+ * This function calls the currently loaded security module's capable()
  * function with a pointer to the current task and the specified @cap value.
  *
  * This allows the security module to implement the capable function call
diff -Nru a/security/selinux/Kconfig b/security/selinux/Kconfig
--- a/security/selinux/Kconfig	2004-10-18 14:55:54 -07:00
+++ b/security/selinux/Kconfig	2004-10-18 14:55:54 -07:00
@@ -24,6 +24,21 @@
 
 	  If you are unsure how to answer this question, answer N.
 
+config SECURITY_SELINUX_BOOTPARAM_VALUE
+	int "NSA SELinux boot parameter default value"
+	depends on SECURITY_SELINUX_BOOTPARAM
+	range 0 1
+	default 1
+	help
+	  This option sets the default value for the kernel parameter
+	  'selinux', which allows SELinux to be disabled at boot.  If this
+	  option is set to 0 (zero), the SELinux kernel parameter will
+	  default to 0, disabling SELinux at bootup.  If this option is
+	  set to 1 (one), the SELinux kernel paramater will default to 1,
+	  enabling SELinux at bootup.
+
+	  If you are unsure how to answer this question, answer 1.
+
 config SECURITY_SELINUX_DISABLE
 	bool "NSA SELinux runtime disable"
 	depends on SECURITY_SELINUX
diff -Nru a/security/selinux/hooks.c b/security/selinux/hooks.c
--- a/security/selinux/hooks.c	2004-10-18 14:57:04 -07:00
+++ b/security/selinux/hooks.c	2004-10-18 14:57:04 -07:00
@@ -43,6 +43,7 @@
 #include <linux/kd.h>
 #include <linux/netfilter_ipv4.h>
 #include <linux/netfilter_ipv6.h>
+#include <linux/tty.h>
 #include <net/icmp.h>
 #include <net/ip.h>		/* for sysctl_local_port_range[] */
 #include <net/tcp.h>		/* struct or_callable used in sock_rcv_skb */
@@ -62,7 +63,6 @@
 #include <linux/nfs_mount.h>
 #include <net/ipv6.h>
 #include <linux/hugetlb.h>
-#include <linux/major.h>
 #include <linux/personality.h>
 
 #include "avc.h"
@@ -87,7 +87,7 @@
 #endif
 
 #ifdef CONFIG_SECURITY_SELINUX_BOOTPARAM
-int selinux_enabled = 1;
+int selinux_enabled = CONFIG_SECURITY_SELINUX_BOOTPARAM_VALUE;
 
 static int __init selinux_enabled_setup(char *str)
 {
@@ -1266,6 +1266,12 @@
 int inode_security_set_sid(struct inode *inode, u32 sid)
 {
 	struct inode_security_struct *isec = inode->i_security;
+	struct superblock_security_struct *sbsec = inode->i_sb->s_security;
+
+	if (!sbsec->initialized) {
+		/* Defer initialization to selinux_complete_init. */
+		return 0;
+	}
 
 	down(&isec->sem);
 	isec->sclass = inode_mode_to_security_class(inode->i_mode);
@@ -1548,10 +1554,10 @@
         /*
 	 * Sometimes we want to use more memory than we have
 	 */
-	if (sysctl_overcommit_memory == 1)
+	if (sysctl_overcommit_memory == OVERCOMMIT_ALWAYS)
 		return 0;
 
-	if (sysctl_overcommit_memory == 0) {
+	if (sysctl_overcommit_memory == OVERCOMMIT_GUESS) {
 		free = get_page_cache_size();
 		free += nr_free_pages();
 		free += nr_swap_pages;
@@ -1726,72 +1732,40 @@
 	kfree(bsec);
 }
 
-/* Create an open file that refers to the null device.
-   Derived from the OpenWall LSM. */
-struct file *open_devnull(void)
-{
-	struct inode *inode;
-	struct dentry *dentry;
-	struct file *file = NULL;
-	struct inode_security_struct *isec;
-	dev_t dev;
-
-	inode = new_inode(current->fs->rootmnt->mnt_sb);
-	if (!inode)
-		goto out;
-
-	dentry = dget(d_alloc_root(inode));
-	if (!dentry)
-		goto out_iput;
-
-	file = get_empty_filp();
-	if (!file)
-		goto out_dput;
-
-	dev = MKDEV(MEM_MAJOR, 3); /* null device */
-
-	inode->i_uid = current->fsuid;
-	inode->i_gid = current->fsgid;
-	inode->i_blksize = PAGE_SIZE;
-	inode->i_blocks = 0;
-	inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME;
-	inode->i_state = I_DIRTY; /* so that mark_inode_dirty won't touch us */
-
-	isec = inode->i_security;
-	isec->sid = SECINITSID_DEVNULL;
-	isec->sclass = SECCLASS_CHR_FILE;
-	isec->initialized = 1;
-
-	file->f_flags = O_RDWR;
-	file->f_mode = FMODE_READ | FMODE_WRITE;
-	file->f_dentry = dentry;
-	file->f_vfsmnt = mntget(current->fs->rootmnt);
-	file->f_pos = 0;
-
-	init_special_inode(inode, S_IFCHR | S_IRUGO | S_IWUGO, dev);
-	if (inode->i_fop->open(inode, file))
-		goto out_fput;
-
-out:
-	return file;
-out_fput:
-	mntput(file->f_vfsmnt);
-	put_filp(file);
-out_dput:
-	dput(dentry);
-out_iput:
-	iput(inode);
-	file = NULL;
-	goto out;
-}
+extern struct vfsmount *selinuxfs_mount;
+extern struct dentry *selinux_null;
 
 /* Derived from fs/exec.c:flush_old_files. */
 static inline void flush_unauthorized_files(struct files_struct * files)
 {
 	struct avc_audit_data ad;
 	struct file *file, *devnull = NULL;
+	struct tty_struct *tty = current->signal->tty;
 	long j = -1;
 
+	if (tty) {
+		file_list_lock();
+		file = list_entry(tty->tty_files.next, typeof(*file), f_list);
+		if (file) {
+			/* Revalidate access to controlling tty.
+			   Use inode_has_perm on the tty inode directly rather
+			   than using file_has_perm, as this particular open
+			   file may belong to another process and we are only
+			   interested in the inode-based check here. */
+			struct inode *inode = file->f_dentry->d_inode;
+			if (inode_has_perm(current, inode,
+					   FILE__READ | FILE__WRITE,
+					   NULL, NULL)) {
+				/* Reset controlling tty. */
+				current->signal->tty = NULL;
+				current->signal->tty_old_pgrp = 0;
+			}
+		}
+		file_list_unlock();
+	}
+
+	/* Revalidate access to inherited open files. */
+
 	AVC_AUDIT_DATA_INIT(&ad,FS);
 
 	spin_lock(&files->file_lock);
@@ -1826,7 +1800,7 @@
 					if (devnull) {
 						atomic_inc(&devnull->f_count);
 					} else {
-						devnull = open_devnull();
+						devnull = dentry_open(dget(selinux_null), mntget(selinuxfs_mount), O_RDWR);
 						if (!devnull) {
 							put_unused_fd(fd);
 							fput(file);
@@ -2492,21 +2466,14 @@
 	return error;
 }
 
-static int selinux_file_mmap(struct file *file, unsigned long prot, unsigned long flags)
+static int file_map_prot_check(struct file *file, unsigned long prot, int shared)
 {
-	u32 av;
-	int rc;
-
-	rc = secondary_ops->file_mmap(file, prot, flags);
-	if (rc)
-		return rc;
-
 	if (file) {
 		/* read access is always possible with a mapping */
-		av = FILE__READ;
+		u32 av = FILE__READ;
 
 		/* write access only matters if the mapping is shared */
-		if ((flags & MAP_TYPE) == MAP_SHARED && (prot & PROT_WRITE))
+		if (shared && (prot & PROT_WRITE))
 			av |= FILE__WRITE;
 
 		if (prot & PROT_EXEC)
@@ -2517,6 +2484,18 @@
 	return 0;
 }
 
+static int selinux_file_mmap(struct file *file, unsigned long prot, unsigned long flags)
+{
+	int rc;
+
+	rc = secondary_ops->file_mmap(file, prot, flags);
+	if (rc)
+		return rc;
+
+	return file_map_prot_check(file, prot,
+				   (flags & MAP_TYPE) == MAP_SHARED);
+}
+
 static int selinux_file_mprotect(struct vm_area_struct *vma,
 				 unsigned long prot)
 {
@@ -2526,7 +2505,7 @@
 	if (rc)
 		return rc;
 
-	return selinux_file_mmap(vma->vm_file, prot, vma->vm_flags);
+	return file_map_prot_check(vma->vm_file, prot, vma->vm_flags&VM_SHARED);
 }
 
 static int selinux_file_lock(struct file *file, unsigned int cmd)
@@ -2651,6 +2630,11 @@
 	tsec2->exec_sid = tsec1->exec_sid;
 	tsec2->create_sid = tsec1->create_sid;
 
+	/* Retain ptracer SID across fork, if any.
+	   This will be reset by the ptrace hook upon any
+	   subsequent ptrace_attach operations. */
+	tsec2->ptrace_sid = tsec1->ptrace_sid;
+
 	return 0;
 }
 
@@ -2822,49 +2806,52 @@
 /* Returns error only if unable to parse addresses */
 static int selinux_parse_skb_ipv4(struct sk_buff *skb, struct avc_audit_data *ad)
 {
-	int offset, ihlen, ret;
-	struct iphdr iph;
+	int offset, ihlen, ret = -EINVAL;
+	struct iphdr _iph, *ih;
 
 	offset = skb->nh.raw - skb->data;
-	ret = skb_copy_bits(skb, offset, &iph, sizeof(iph));
-	if (ret)
+	ih = skb_header_pointer(skb, offset, sizeof(_iph), &_iph);
+	if (ih == NULL)
 		goto out;
 
-	ihlen = iph.ihl * 4;
-	if (ihlen < sizeof(iph))
+	ihlen = ih->ihl * 4;
+	if (ihlen < sizeof(_iph))
 		goto out;
 
-	ad->u.net.v4info.saddr = iph.saddr;
-	ad->u.net.v4info.daddr = iph.daddr;
+	ad->u.net.v4info.saddr = ih->saddr;
+	ad->u.net.v4info.daddr = ih->daddr;
+	ret = 0;
 
-	switch (iph.protocol) {
+	switch (ih->protocol) {
         case IPPROTO_TCP: {
-        	struct tcphdr tcph;
+        	struct tcphdr _tcph, *th;
 
-        	if (ntohs(iph.frag_off) & IP_OFFSET)
+        	if (ntohs(ih->frag_off) & IP_OFFSET)
         		break;
 
 		offset += ihlen;
-		if (skb_copy_bits(skb, offset, &tcph, sizeof(tcph)) < 0)
+		th = skb_header_pointer(skb, offset, sizeof(_tcph), &_tcph);
+		if (th == NULL)
 			break;
 
-		ad->u.net.sport = tcph.source;
-		ad->u.net.dport = tcph.dest;
+		ad->u.net.sport = th->source;
+		ad->u.net.dport = th->dest;
 		break;
         }
         
         case IPPROTO_UDP: {
-        	struct udphdr udph;
+        	struct udphdr _udph, *uh;
         	
-        	if (ntohs(iph.frag_off) & IP_OFFSET)
+        	if (ntohs(ih->frag_off) & IP_OFFSET)
         		break;
         		
 		offset += ihlen;
-        	if (skb_copy_bits(skb, offset, &udph, sizeof(udph)) < 0)
-        		break;	
+        	uh = skb_header_pointer(skb, offset, sizeof(_udph), &_udph);
+		if (uh == NULL)
+			break;	
 
-        	ad->u.net.sport = udph.source;
-        	ad->u.net.dport = udph.dest;
+        	ad->u.net.sport = uh->source;
+        	ad->u.net.dport = uh->dest;
         	break;
         }
 
@@ -2881,19 +2868,20 @@
 static int selinux_parse_skb_ipv6(struct sk_buff *skb, struct avc_audit_data *ad)
 {
 	u8 nexthdr;
-	int ret, offset;
-	struct ipv6hdr ipv6h;
+	int ret = -EINVAL, offset;
+	struct ipv6hdr _ipv6h, *ip6;
 
 	offset = skb->nh.raw - skb->data;
-	ret = skb_copy_bits(skb, offset, &ipv6h, sizeof(ipv6h));
-	if (ret)
+	ip6 = skb_header_pointer(skb, offset, sizeof(_ipv6h), &_ipv6h);
+	if (ip6 == NULL)
 		goto out;
 
-	ipv6_addr_copy(&ad->u.net.v6info.saddr, &ipv6h.saddr);
-	ipv6_addr_copy(&ad->u.net.v6info.daddr, &ipv6h.daddr);
+	ipv6_addr_copy(&ad->u.net.v6info.saddr, &ip6->saddr);
+	ipv6_addr_copy(&ad->u.net.v6info.daddr, &ip6->daddr);
+	ret = 0;
 
-	nexthdr = ipv6h.nexthdr;
-	offset += sizeof(ipv6h);
+	nexthdr = ip6->nexthdr;
+	offset += sizeof(_ipv6h);
 	offset = ipv6_skip_exthdr(skb, offset, &nexthdr,
 				  skb->tail - skb->head - offset);
 	if (offset < 0)
@@ -2901,24 +2889,26 @@
 
 	switch (nexthdr) {
 	case IPPROTO_TCP: {
-        	struct tcphdr tcph;
+        	struct tcphdr _tcph, *th;
 
-		if (skb_copy_bits(skb, offset, &tcph, sizeof(tcph)) < 0)
+		th = skb_header_pointer(skb, offset, sizeof(_tcph), &_tcph);
+		if (th == NULL)
 			break;
 
-		ad->u.net.sport = tcph.source;
-		ad->u.net.dport = tcph.dest;
+		ad->u.net.sport = th->source;
+		ad->u.net.dport = th->dest;
 		break;
 	}
 
 	case IPPROTO_UDP: {
-		struct udphdr udph;
+		struct udphdr _udph, *uh;
 
-		if (skb_copy_bits(skb, offset, &udph, sizeof(udph)) < 0)
+		uh = skb_header_pointer(skb, offset, sizeof(_udph), &_udph);
+		if (uh == NULL)
 			break;
 
-		ad->u.net.sport = udph.source;
-		ad->u.net.dport = udph.dest;
+		ad->u.net.sport = uh->source;
+		ad->u.net.dport = uh->dest;
 		break;
 	}
 
@@ -3078,6 +3068,7 @@
 				goto out;
 			AVC_AUDIT_DATA_INIT(&ad,NET);
 			ad.u.net.sport = htons(snum);
+			ad.u.net.family = family;
 			err = avc_has_perm(isec->sid, sid,
 					   isec->sclass,
 					   SOCKET__NAME_BIND, NULL, &ad);
diff -Nru a/security/selinux/include/avc.h b/security/selinux/include/avc.h
--- a/security/selinux/include/avc.h	2004-10-18 14:56:17 -07:00
+++ b/security/selinux/include/avc.h	2004-10-18 14:56:17 -07:00
@@ -111,7 +111,6 @@
 struct audit_buffer;
 void avc_dump_av(struct audit_buffer *ab, u16 tclass, u32 av);
 void avc_dump_query(struct audit_buffer *ab, u32 ssid, u32 tsid, u16 tclass);
-void avc_dump_cache(struct audit_buffer *ab, char *tag);
 
 /*
  * AVC operations
diff -Nru a/security/selinux/selinuxfs.c b/security/selinux/selinuxfs.c
--- a/security/selinux/selinuxfs.c	2004-10-18 14:57:18 -07:00
+++ b/security/selinux/selinuxfs.c	2004-10-18 14:57:18 -07:00
@@ -17,6 +17,7 @@
 #include <linux/init.h>
 #include <linux/string.h>
 #include <linux/security.h>
+#include <linux/major.h>
 #include <asm/uaccess.h>
 #include <asm/semaphore.h>
 
@@ -68,40 +69,15 @@
 	SEL_DISABLE	/* disable SELinux until next reboot */
 };
 
+#define TMPBUFLEN	12
 static ssize_t sel_read_enforce(struct file *filp, char __user *buf,
 				size_t count, loff_t *ppos)
 {
-	char *page;
+	char tmpbuf[TMPBUFLEN];
 	ssize_t length;
-	ssize_t end;
-
-	if (count < 0 || count > PAGE_SIZE)
-		return -EINVAL;
-	if (!(page = (char*)__get_free_page(GFP_KERNEL)))
-		return -ENOMEM;
-	memset(page, 0, PAGE_SIZE);
 
-	length = scnprintf(page, PAGE_SIZE, "%d", selinux_enforcing);
-	if (length < 0) {
-		free_page((unsigned long)page);
-		return length;
-	}
-
-	if (*ppos >= length) {
-		free_page((unsigned long)page);
-		return 0;
-	}
-	if (count + *ppos > length)
-		count = length - *ppos;
-	end = count + *ppos;
-	if (copy_to_user(buf, (char *) page + *ppos, count)) {
-		count = -EFAULT;
-		goto out;
-	}
-	*ppos = end;
-out:
-	free_page((unsigned long)page);
-	return count;
+	length = scnprintf(tmpbuf, TMPBUFLEN, "%d", selinux_enforcing);
+	return simple_read_from_buffer(buf, count, ppos, tmpbuf, length);
 }
 
 #ifdef CONFIG_SECURITY_SELINUX_DEVELOP
@@ -119,10 +95,9 @@
 		/* No partial writes. */
 		return -EINVAL;
 	}
-	page = (char*)__get_free_page(GFP_KERNEL);
+	page = (char*)get_zeroed_page(GFP_KERNEL);
 	if (!page)
 		return -ENOMEM;
-	memset(page, 0, PAGE_SIZE);
 	length = -EFAULT;
 	if (copy_from_user(page, buf, count))
 		goto out;
@@ -170,10 +145,9 @@
 		/* No partial writes. */
 		return -EINVAL;
 	}
-	page = (char*)__get_free_page(GFP_KERNEL);
+	page = (char*)get_zeroed_page(GFP_KERNEL);
 	if (!page)
 		return -ENOMEM;
-	memset(page, 0, PAGE_SIZE);
 	length = -EFAULT;
 	if (copy_from_user(page, buf, count))
 		goto out;
@@ -204,37 +178,11 @@
 static ssize_t sel_read_policyvers(struct file *filp, char __user *buf,
                                    size_t count, loff_t *ppos)
 {
-	char *page;
+	char tmpbuf[TMPBUFLEN];
 	ssize_t length;
-	ssize_t end;
 
-	if (count < 0 || count > PAGE_SIZE)
-		return -EINVAL;
-	if (!(page = (char*)__get_free_page(GFP_KERNEL)))
-		return -ENOMEM;
-	memset(page, 0, PAGE_SIZE);
-
-	length = scnprintf(page, PAGE_SIZE, "%u", POLICYDB_VERSION_MAX);
-	if (length < 0) {
-		free_page((unsigned long)page);
-		return length;
-	}
-
-	if (*ppos >= length) {
-		free_page((unsigned long)page);
-		return 0;
-	}
-	if (count + *ppos > length)
-		count = length - *ppos;
-	end = count + *ppos;
-	if (copy_to_user(buf, (char *) page + *ppos, count)) {
-		count = -EFAULT;
-		goto out;
-	}
-	*ppos = end;
-out:
-	free_page((unsigned long)page);
-	return count;
+	length = scnprintf(tmpbuf, TMPBUFLEN, "%u", POLICYDB_VERSION_MAX);
+	return simple_read_from_buffer(buf, count, ppos, tmpbuf, length);
 }
 
 static struct file_operations sel_policyvers_ops = {
@@ -247,37 +195,11 @@
 static ssize_t sel_read_mls(struct file *filp, char __user *buf,
 				size_t count, loff_t *ppos)
 {
-	char *page;
+	char tmpbuf[TMPBUFLEN];
 	ssize_t length;
-	ssize_t end;
-
-	if (count < 0 || count > PAGE_SIZE)
-		return -EINVAL;
-	if (!(page = (char*)__get_free_page(GFP_KERNEL)))
-		return -ENOMEM;
-	memset(page, 0, PAGE_SIZE);
 
-	length = scnprintf(page, PAGE_SIZE, "%d", selinux_mls_enabled);
-	if (length < 0) {
-		free_page((unsigned long)page);
-		return length;
-	}
-
-	if (*ppos >= length) {
-		free_page((unsigned long)page);
-		return 0;
-	}
-	if (count + *ppos > length)
-		count = length - *ppos;
-	end = count + *ppos;
-	if (copy_to_user(buf, (char *) page + *ppos, count)) {
-		count = -EFAULT;
-		goto out;
-	}
-	*ppos = end;
-out:
-	free_page((unsigned long)page);
-	return count;
+	length = scnprintf(tmpbuf, TMPBUFLEN, "%d", selinux_mls_enabled);
+	return simple_read_from_buffer(buf, count, ppos, tmpbuf, length);
 }
 
 static struct file_operations sel_mls_ops = {
@@ -352,10 +274,9 @@
 		/* No partial writes. */
 		return -EINVAL;
 	}
-	page = (char*)__get_free_page(GFP_KERNEL);
+	page = (char*)get_zeroed_page(GFP_KERNEL);
 	if (!page)
 		return -ENOMEM;
-	memset(page, 0, PAGE_SIZE);
 	length = -EFAULT;
 	if (copy_from_user(page, buf, count))
 		goto out;
@@ -390,103 +311,31 @@
 	[SEL_USER] = sel_write_user,
 };
 
-/* an argresp is stored in an allocated page and holds the
- * size of the argument or response, along with its content
- */
-struct argresp {
-	ssize_t size;
-	char data[0];
-};
-
-#define PAYLOAD_SIZE (PAGE_SIZE - sizeof(struct argresp))
-
-/*
- * transaction based IO methods.
- * The file expects a single write which triggers the transaction, and then
- * possibly a read which collects the result - which is stored in a
- * file-local buffer.
- */
-static ssize_t TA_write(struct file *file, const char __user *buf, size_t size, loff_t *pos)
+static ssize_t selinux_transaction_write(struct file *file, const char __user *buf, size_t size, loff_t *pos)
 {
 	ino_t ino =  file->f_dentry->d_inode->i_ino;
-	struct argresp *ar;
-	ssize_t rv = 0;
+	char *data;
+	ssize_t rv;
 
 	if (ino >= sizeof(write_op)/sizeof(write_op[0]) || !write_op[ino])
 		return -EINVAL;
-	if (file->private_data)
-		return -EINVAL; /* only one write allowed per open */
-	if (size > PAYLOAD_SIZE - 1) /* allow one byte for null terminator */
-		return -EFBIG;
 
-	ar = kmalloc(PAGE_SIZE, GFP_KERNEL);
-	if (!ar)
-		return -ENOMEM;
-	memset(ar, 0, PAGE_SIZE); /* clear buffer, particularly last byte */
-	ar->size = 0;
-	down(&file->f_dentry->d_inode->i_sem);
-	if (file->private_data)
-		rv = -EINVAL;
-	else
-		file->private_data = ar;
-	up(&file->f_dentry->d_inode->i_sem);
-	if (rv) {
-		kfree(ar);
-		return rv;
-	}
-	if (copy_from_user(ar->data, buf, size))
-		return -EFAULT;
+	data = simple_transaction_get(file, buf, size);
+	if (IS_ERR(data))
+		return PTR_ERR(data);
 
-	rv =  write_op[ino](file, ar->data, size);
+	rv =  write_op[ino](file, data, size);
 	if (rv>0) {
-		ar->size = rv;
+		simple_transaction_set(file, rv);
 		rv = size;
 	}
 	return rv;
 }
 
-static ssize_t TA_read(struct file *file, char __user *buf, size_t size, loff_t *pos)
-{
-	struct argresp *ar;
-	ssize_t rv = 0;
-
-	if (file->private_data == NULL)
-		rv = TA_write(file, buf, 0, pos);
-	if (rv < 0)
-		return rv;
-
-	ar = file->private_data;
-	if (!ar)
-		return 0;
-	if (*pos >= ar->size)
-		return 0;
-	if (*pos + size > ar->size)
-		size = ar->size - *pos;
-	if (copy_to_user(buf, ar->data + *pos, size))
-		return -EFAULT;
-	*pos += size;
-	return size;
-}
-
-static int TA_open(struct inode *inode, struct file *file)
-{
-	file->private_data = NULL;
-	return 0;
-}
-
-static int TA_release(struct inode *inode, struct file *file)
-{
-	void *p = file->private_data;
-	file->private_data = NULL;
-	kfree(p);
-	return 0;
-}
-
 static struct file_operations transaction_ops = {
-	.write		= TA_write,
-	.read		= TA_read,
-	.open		= TA_open,
-	.release	= TA_release,
+	.write		= selinux_transaction_write,
+	.read		= simple_transaction_read,
+	.release	= simple_transaction_release,
 };
 
 /*
@@ -534,7 +383,8 @@
 	if (length < 0)
 		goto out2;
 
-	length = scnprintf(buf, PAYLOAD_SIZE, "%x %x %x %x %u",
+	length = scnprintf(buf, SIMPLE_TRANSACTION_LIMIT,
+			  "%x %x %x %x %u",
 			  avd.allowed, avd.decided,
 			  avd.auditallow, avd.auditdeny,
 			  avd.seqno);
@@ -588,7 +438,7 @@
 	if (length < 0)
 		goto out2;
 
-	if (len > PAYLOAD_SIZE) {
+	if (len > SIMPLE_TRANSACTION_LIMIT) {
 		printk(KERN_ERR "%s:  context size (%u) exceeds payload "
 		       "max\n", __FUNCTION__, len);
 		length = -ERANGE;
@@ -649,7 +499,7 @@
 	if (length < 0)
 		goto out2;
 
-	if (len > PAYLOAD_SIZE) {
+	if (len > SIMPLE_TRANSACTION_LIMIT) {
 		length = -ERANGE;
 		goto out3;
 	}
@@ -709,7 +559,7 @@
 			length = rc;
 			goto out3;
 		}
-		if ((length + len) >= PAYLOAD_SIZE) {
+		if ((length + len) >= SIMPLE_TRANSACTION_LIMIT) {
 			kfree(newcon);
 			length = -ERANGE;
 			goto out3;
@@ -766,11 +616,10 @@
 		ret = -EINVAL;
 		goto out;
 	}
-	if (!(page = (char*)__get_free_page(GFP_KERNEL))) {
+	if (!(page = (char*)get_zeroed_page(GFP_KERNEL))) {
 		ret = -ENOMEM;
 		goto out;
 	}
-	memset(page, 0, PAGE_SIZE);
 
 	inode = filep->f_dentry->d_inode;
 	cur_enforcing = security_get_bool_value(inode->i_ino - BOOL_INO_OFFSET);
@@ -832,12 +681,11 @@
 		/* No partial writes. */
 		goto out;
 	}
-	page = (char*)__get_free_page(GFP_KERNEL);
+	page = (char*)get_zeroed_page(GFP_KERNEL);
 	if (!page) {
 		length = -ENOMEM;
 		goto out;
 	}
-	memset(page, 0, PAGE_SIZE);
 
 	if (copy_from_user(page, buf, count))
 		goto out;
@@ -891,14 +739,12 @@
 		/* No partial writes. */
 		goto out;
 	}
-	page = (char*)__get_free_page(GFP_KERNEL);
+	page = (char*)get_zeroed_page(GFP_KERNEL);
 	if (!page) {
 		length = -ENOMEM;
 		goto out;
 	}
 
-	memset(page, 0, PAGE_SIZE);
-
 	if (copy_from_user(page, buf, count))
 		goto out;
 
@@ -984,9 +830,8 @@
 
 	sel_remove_bools(dir);
 
-	if (!(page = (char*)__get_free_page(GFP_KERNEL)))
+	if (!(page = (char*)get_zeroed_page(GFP_KERNEL)))
 		return -ENOMEM;
-	memset(page, 0, PAGE_SIZE);
 
 	ret = security_get_bools(&num, &names, &values);
 	if (ret != 0)
@@ -1042,12 +887,17 @@
 	goto out;
 }
 
+#define NULL_FILE_NAME "null"
+
+struct dentry *selinux_null = NULL;
+
 static int sel_fill_super(struct super_block * sb, void * data, int silent)
 {
 	int ret;
 	struct dentry *dentry;
 	struct inode *inode;
 	struct qstr qname;
+	struct inode_security_struct *isec;
 
 	static struct tree_descr selinux_files[] = {
 		[SEL_LOAD] = {"load", &sel_load_ops, S_IRUSR|S_IWUSR},
@@ -1085,10 +935,29 @@
 	if (ret)
 		goto out;
 
+	qname.name = NULL_FILE_NAME;
+	qname.len = strlen(qname.name);
+	qname.hash = full_name_hash(qname.name, qname.len);
+	dentry = d_alloc(sb->s_root, &qname);
+	if (!dentry)
+		return -ENOMEM;
+
+	inode = sel_make_inode(sb, S_IFCHR | S_IRUGO | S_IWUGO);
+	if (!inode)
+		goto out;
+	isec = (struct inode_security_struct*)inode->i_security;
+	isec->sid = SECINITSID_DEVNULL;
+	isec->sclass = SECCLASS_CHR_FILE;
+	isec->initialized = 1;
+
+	init_special_inode(inode, S_IFCHR | S_IRUGO | S_IWUGO, MKDEV(MEM_MAJOR, 3));
+	d_add(dentry, inode);
+	selinux_null = dentry;
+
 	return 0;
 out:
 	dput(dentry);
-	printk(KERN_ERR "security:	error creating conditional out_dput\n");
+	printk(KERN_ERR "%s:  failed while creating inodes\n", __FUNCTION__);
 	return -ENOMEM;
 }
 
@@ -1104,9 +973,24 @@
 	.kill_sb	= kill_litter_super,
 };
 
+struct vfsmount *selinuxfs_mount;
+
 static int __init init_sel_fs(void)
 {
-	return selinux_enabled ? register_filesystem(&sel_fs_type) : 0;
+	int err;
+
+	if (!selinux_enabled)
+		return 0;
+	err = register_filesystem(&sel_fs_type);
+	if (!err) {
+		selinuxfs_mount = kern_mount(&sel_fs_type);
+		if (IS_ERR(selinuxfs_mount)) {
+			printk(KERN_ERR "selinuxfs:  could not mount!\n");
+			err = PTR_ERR(selinuxfs_mount);
+			selinuxfs_mount = NULL;
+		}
+	}
+	return err;
 }
 
 __initcall(init_sel_fs);
diff -Nru a/security/selinux/ss/avtab.c b/security/selinux/ss/avtab.c
--- a/security/selinux/ss/avtab.c	2004-10-18 14:56:49 -07:00
+++ b/security/selinux/ss/avtab.c	2004-10-18 14:56:49 -07:00
@@ -28,12 +28,14 @@
  (keyp->source_type << 9)) & \
  AVTAB_HASH_MASK)
 
+static kmem_cache_t *avtab_node_cachep;
+
 static struct avtab_node*
 avtab_insert_node(struct avtab *h, int hvalue, struct avtab_node * prev, struct avtab_node * cur,
 		  struct avtab_key *key, struct avtab_datum *datum)
 {
 	struct avtab_node * newnode;
-	newnode = (struct avtab_node *) kmalloc(sizeof(struct avtab_node),GFP_KERNEL);
+	newnode = kmem_cache_alloc(avtab_node_cachep, SLAB_KERNEL);
 	if (newnode == NULL)
 		return NULL;
 	memset(newnode, 0, sizeof(struct avtab_node));
@@ -226,7 +228,7 @@
 		while (cur != NULL) {
 			temp = cur;
 			cur = cur->next;
-			kfree(temp);
+			kmem_cache_free(avtab_node_cachep, temp);
 		}
 		h->htable[i] = NULL;
 	}
@@ -399,3 +401,9 @@
 	goto out;
 }
 
+void avtab_cache_init(void)
+{
+	avtab_node_cachep = kmem_cache_create("avtab_node",
+					      sizeof(struct avtab_node),
+					      0, SLAB_PANIC, NULL, NULL);
+}
diff -Nru a/security/selinux/ss/avtab.h b/security/selinux/ss/avtab.h
--- a/security/selinux/ss/avtab.h	2004-10-18 14:56:28 -07:00
+++ b/security/selinux/ss/avtab.h	2004-10-18 14:56:28 -07:00
@@ -78,6 +78,8 @@
 
 struct avtab_node *avtab_search_node_next(struct avtab_node *node, int specified);
 
+void avtab_cache_init(void);
+
 #define AVTAB_HASH_BITS 15
 #define AVTAB_HASH_BUCKETS (1 << AVTAB_HASH_BITS)
 #define AVTAB_HASH_MASK (AVTAB_HASH_BUCKETS-1)
diff -Nru a/security/selinux/ss/policydb.h b/security/selinux/ss/policydb.h
--- a/security/selinux/ss/policydb.h	2004-10-18 14:56:49 -07:00
+++ b/security/selinux/ss/policydb.h	2004-10-18 14:56:49 -07:00
@@ -251,7 +251,6 @@
 extern int policydb_init(struct policydb *p);
 extern int policydb_index_classes(struct policydb *p);
 extern int policydb_index_others(struct policydb *p);
-extern int constraint_expr_destroy(struct constraint_expr *expr);
 extern void policydb_destroy(struct policydb *p);
 extern int policydb_load_isids(struct policydb *p, struct sidtab *s);
 extern int policydb_context_isvalid(struct policydb *p, struct context *c);
diff -Nru a/security/selinux/ss/services.c b/security/selinux/ss/services.c
--- a/security/selinux/ss/services.c	2004-10-18 14:57:03 -07:00
+++ b/security/selinux/ss/services.c	2004-10-18 14:57:03 -07:00
@@ -1034,6 +1034,7 @@
 	LOAD_LOCK;
 
 	if (!ss_initialized) {
+		avtab_cache_init();
 		if (policydb_read(&policydb, fp)) {
 			LOAD_UNLOCK;
 			return -EINVAL;
diff -Nru a/sound/arm/sa11xx-uda1341.c b/sound/arm/sa11xx-uda1341.c
--- a/sound/arm/sa11xx-uda1341.c	2004-10-18 14:55:54 -07:00
+++ b/sound/arm/sa11xx-uda1341.c	2004-10-18 14:55:54 -07:00
@@ -21,7 +21,7 @@
  *                              merged HAL layer (patches from Brian)
  */
 
-/* $Id: sa11xx-uda1341.c,v 1.15 2004/05/03 17:36:50 tiwai Exp $ */
+/* $Id: sa11xx-uda1341.c,v 1.18 2004/07/20 15:54:09 cladisch Exp $ */
 
 /***************************************************************************************************
 *
@@ -108,16 +108,13 @@
 MODULE_AUTHOR("Tomas Kasparek <tomas.kasparek@seznam.cz>");
 MODULE_LICENSE("GPL");
 MODULE_DESCRIPTION("SA1100/SA1111 + UDA1341TS driver for ALSA");
-MODULE_CLASSES("{sound}");
-MODULE_DEVICES("{{UDA1341,iPAQ H3600 UDA1341TS}}");
+MODULE_SUPPORTED_DEVICE("{{UDA1341,iPAQ H3600 UDA1341TS}}");
 
 static char *id = NULL;	/* ID for this card */
 
 module_param(id, charp, 0444);
 MODULE_PARM_DESC(id, "ID string for SA1100/SA1111 + UDA1341TS soundcard.");
 
-#define chip_t sa11xx_uda1341_t
-
 typedef struct audio_stream {
 	char *id;		/* identification string */
 	int stream_id;		/* numeric identification */	
@@ -152,10 +149,8 @@
 	29400, 32000, 44100, 48000,
 };
 
-#define RATES sizeof(rates) / sizeof(rates[0])
-
 static snd_pcm_hw_constraint_list_t hw_constraints_rates = {
-	.count	= RATES,
+	.count	= ARRAY_SIZE(rates),
 	.list	= rates,
 	.mask	= 0,
 };
@@ -869,7 +864,7 @@
 
 static int snd_sa11xx_uda1341_suspend(snd_card_t *card, unsigned int state)
 {
-	sa11xx_uda1341_t *chip = snd_magic_cast(sa11x_uda1341_t, card->pm_private_data, return -EINVAL);
+	sa11xx_uda1341_t *chip = card->pm_private_data;
 
 	snd_pcm_suspend_all(chip->pcm);
 #ifdef HH_VERSION	
@@ -886,7 +881,7 @@
 
 static int snd_sa11xx_uda1341_resume(snd_card_t *card, unsigned int state)
 {
-	sa11xx_uda1341_t *chip = snd_magic_cast(sa11x_uda1341_t, card->pm_private_data, return -EINVAL);
+	sa11xx_uda1341_t *chip = card->pm_private_data;
 
 	sa11xx_uda1341_audio_init(chip);
 	l3_command(chip->uda1341, CMD_RESUME, NULL);
@@ -903,7 +898,7 @@
 
 void snd_sa11xx_uda1341_free(snd_card_t *card)
 {
-	sa11xx_uda1341_t *chip = snd_magic_cast(sa11xx_uda1341_t, card->private_data, return);
+	sa11xx_uda1341_t *chip = card->private_data;
 
 	audio_dma_free(&chip->s[SNDRV_PCM_STREAM_PLAYBACK]);
 	audio_dma_free(&chip->s[SNDRV_PCM_STREAM_CAPTURE]);
@@ -925,7 +920,7 @@
 	if (card == NULL)
 		return -ENOMEM;
 
-	sa11xx_uda1341 = snd_magic_kcalloc(sa11xx_uda1341_t, 0, GFP_KERNEL);
+	sa11xx_uda1341 = kcalloc(1, sizeof(*sa11xx_uda1341), GFP_KERNEL);
 	if (sa11xx_uda1341 == NULL)
 		return -ENOMEM;	
 	spin_lock_init(&chip->s[0].dma_lock);
diff -Nru a/sound/core/control.c b/sound/core/control.c
--- a/sound/core/control.c	2004-10-18 14:56:13 -07:00
+++ b/sound/core/control.c	2004-10-18 14:56:13 -07:00
@@ -22,6 +22,7 @@
 #include <sound/driver.h>
 #include <linux/threads.h>
 #include <linux/interrupt.h>
+#include <linux/smp_lock.h>
 #include <linux/slab.h>
 #include <linux/vmalloc.h>
 #include <linux/time.h>
@@ -62,7 +63,7 @@
 		err = -EFAULT;
 		goto __error2;
 	}
-	ctl = snd_magic_kcalloc(snd_ctl_file_t, 0, GFP_KERNEL);
+	ctl = kcalloc(1, sizeof(*ctl), GFP_KERNEL);
 	if (ctl == NULL) {
 		err = -ENOMEM;
 		goto __error;
@@ -108,7 +109,7 @@
 	snd_kcontrol_t *control;
 	unsigned int idx;
 
-	ctl = snd_magic_cast(snd_ctl_file_t, file->private_data, return -ENXIO);
+	ctl = file->private_data;
 	fasync_helper(-1, file, 0, &ctl->fasync);
 	file->private_data = NULL;
 	card = ctl->card;
@@ -124,7 +125,7 @@
 	}
 	up_write(&card->controls_rwsem);
 	snd_ctl_empty_read_queue(ctl);
-	snd_magic_kfree(ctl);
+	kfree(ctl);
 	module_put(card->module);
 	snd_card_file_remove(card, file);
 	return 0;
@@ -155,7 +156,7 @@
 				goto _found;
 			}
 		}
-		ev = snd_kcalloc(sizeof(*ev), GFP_ATOMIC);
+		ev = kcalloc(1, sizeof(*ev), GFP_ATOMIC);
 		if (ev) {
 			ev->id = *id;
 			ev->mask = mask;
@@ -188,9 +189,7 @@
 	
 	snd_runtime_check(control != NULL, return NULL);
 	snd_runtime_check(control->count > 0, return NULL);
-	kctl = (snd_kcontrol_t *)snd_magic_kcalloc(snd_kcontrol_t,
-						   sizeof(snd_kcontrol_volatile_t) * control->count,
-						   GFP_KERNEL);
+	kctl = kcalloc(1, sizeof(*kctl) + sizeof(snd_kcontrol_volatile_t) * control->count, GFP_KERNEL);
 	if (kctl == NULL)
 		return NULL;
 	*kctl = *control;
@@ -249,7 +248,7 @@
 	if (kcontrol) {
 		if (kcontrol->private_free)
 			kcontrol->private_free(kcontrol);
-		snd_magic_kfree(kcontrol);
+		kfree(kcontrol);
 	}
 }
 
@@ -927,7 +926,7 @@
 	if (!(info.access & SNDRV_CTL_ELEM_ACCESS_DINDIRECT))
 		for (idx = 0; idx < 4 && info.dimen.d[idx]; idx++)
 			dimen_size += sizeof(unsigned short);
-	ue = snd_kcalloc(sizeof(struct user_element) + dimen_size + private_size + extra_size, GFP_KERNEL);
+	ue = kcalloc(1, sizeof(struct user_element) + dimen_size + private_size + extra_size, GFP_KERNEL);
 	if (ue == NULL)
 		return -ENOMEM;
 	ue->type = info.type;
@@ -1022,8 +1021,8 @@
 }
 #endif
 
-static int snd_ctl_ioctl(struct inode *inode, struct file *file,
-			 unsigned int cmd, unsigned long arg)
+static inline int _snd_ctl_ioctl(struct inode *inode, struct file *file,
+				 unsigned int cmd, unsigned long arg)
 {
 	snd_ctl_file_t *ctl;
 	snd_card_t *card;
@@ -1033,7 +1032,7 @@
 	int __user *ip = argp;
 	int err;
 
-	ctl = snd_magic_cast(snd_ctl_file_t, file->private_data, return -ENXIO);
+	ctl = file->private_data;
 	card = ctl->card;
 	snd_assert(card != NULL, return -ENXIO);
 	switch (cmd) {
@@ -1096,13 +1095,24 @@
 	return -ENOTTY;
 }
 
+/* FIXME: need to unlock BKL to allow preemption */
+static int snd_ctl_ioctl(struct inode *inode, struct file *file,
+			 unsigned int cmd, unsigned long arg)
+{
+	int err;
+	unlock_kernel();
+	err = _snd_ctl_ioctl(inode, file, cmd, arg);
+	lock_kernel();
+	return err;
+}
+
 static ssize_t snd_ctl_read(struct file *file, char __user *buffer, size_t count, loff_t * offset)
 {
 	snd_ctl_file_t *ctl;
 	int err = 0;
 	ssize_t result = 0;
 
-	ctl = snd_magic_cast(snd_ctl_file_t, file->private_data, return -ENXIO);
+	ctl = file->private_data;
 	snd_assert(ctl != NULL && ctl->card != NULL, return -ENXIO);
 	if (!ctl->subscribed)
 		return -EBADFD;
@@ -1116,7 +1126,7 @@
 			wait_queue_t wait;
 			if ((file->f_flags & O_NONBLOCK) != 0 || result > 0) {
 				err = -EAGAIN;
-				goto __end;
+				goto __end_lock;
 			}
 			init_waitqueue_entry(&wait, current);
 			add_wait_queue(&ctl->change_sleep, &wait);
@@ -1137,16 +1147,16 @@
 		kfree(kev);
 		if (copy_to_user(buffer, &ev, sizeof(snd_ctl_event_t))) {
 			err = -EFAULT;
-			goto out;
+			goto __end;
 		}
 		spin_lock_irq(&ctl->read_lock);
 		buffer += sizeof(snd_ctl_event_t);
 		count -= sizeof(snd_ctl_event_t);
 		result += sizeof(snd_ctl_event_t);
 	}
-__end:
+      __end_lock:
 	spin_unlock_irq(&ctl->read_lock);
-out:
+      __end:
       	return result > 0 ? result : err;
 }
 
@@ -1155,7 +1165,7 @@
 	unsigned int mask;
 	snd_ctl_file_t *ctl;
 
-	ctl = snd_magic_cast(snd_ctl_file_t, file->private_data, return 0);
+	ctl = file->private_data;
 	if (!ctl->subscribed)
 		return 0;
 	poll_wait(file, &ctl->change_sleep, wait);
@@ -1175,8 +1185,7 @@
 {
 	snd_kctl_ioctl_t *pn;
 
-	pn = (snd_kctl_ioctl_t *)
-		snd_kcalloc(sizeof(snd_kctl_ioctl_t), GFP_KERNEL);
+	pn = kcalloc(1, sizeof(snd_kctl_ioctl_t), GFP_KERNEL);
 	if (pn == NULL)
 		return -ENOMEM;
 	pn->fioctl = fcn;
@@ -1214,7 +1223,7 @@
 {
 	snd_ctl_file_t *ctl;
 	int err;
-	ctl = snd_magic_cast(snd_ctl_file_t, file->private_data, return -ENXIO);
+	ctl = file->private_data;
 	err = fasync_helper(fd, file, on, &ctl->fasync);
 	if (err < 0)
 		return err;
diff -Nru a/sound/core/device.c b/sound/core/device.c
--- a/sound/core/device.c	2004-10-18 14:56:33 -07:00
+++ b/sound/core/device.c	2004-10-18 14:56:33 -07:00
@@ -47,7 +47,7 @@
 	snd_device_t *dev;
 
 	snd_assert(card != NULL && device_data != NULL && ops != NULL, return -ENXIO);
-	dev = (snd_device_t *) snd_magic_kcalloc(snd_device_t, 0, GFP_KERNEL);
+	dev = kcalloc(1, sizeof(*dev), GFP_KERNEL);
 	if (dev == NULL)
 		return -ENOMEM;
 	dev->card = card;
@@ -94,7 +94,7 @@
 					snd_printk(KERN_ERR "device free failure\n");
 			}
 		}
-		snd_magic_kfree(dev);
+		kfree(dev);
 		return 0;
 	}
 	snd_printd("device free %p (from %p), not found\n", device_data, __builtin_return_address(0));
diff -Nru a/sound/core/hwdep.c b/sound/core/hwdep.c
--- a/sound/core/hwdep.c	2004-10-18 14:55:54 -07:00
+++ b/sound/core/hwdep.c	2004-10-18 14:55:54 -07:00
@@ -22,6 +22,7 @@
 #include <sound/driver.h>
 #include <linux/major.h>
 #include <linux/init.h>
+#include <linux/smp_lock.h>
 #include <linux/slab.h>
 #include <linux/time.h>
 #include <sound/core.h>
@@ -49,7 +50,7 @@
 
 static loff_t snd_hwdep_llseek(struct file * file, loff_t offset, int orig)
 {
-	snd_hwdep_t *hw = snd_magic_cast(snd_hwdep_t, file->private_data, return -ENXIO);
+	snd_hwdep_t *hw = file->private_data;
 	if (hw->ops.llseek)
 		return hw->ops.llseek(hw, file, offset, orig);
 	return -ENXIO;
@@ -57,7 +58,7 @@
 
 static ssize_t snd_hwdep_read(struct file * file, char __user *buf, size_t count, loff_t *offset)
 {
-	snd_hwdep_t *hw = snd_magic_cast(snd_hwdep_t, file->private_data, return -ENXIO);
+	snd_hwdep_t *hw = file->private_data;
 	if (hw->ops.read)
 		return hw->ops.read(hw, buf, count, offset);
 	return -ENXIO;	
@@ -65,7 +66,7 @@
 
 static ssize_t snd_hwdep_write(struct file * file, const char __user *buf, size_t count, loff_t *offset)
 {
-	snd_hwdep_t *hw = snd_magic_cast(snd_hwdep_t, file->private_data, return -ENXIO);
+	snd_hwdep_t *hw = file->private_data;
 	if (hw->ops.write)
 		return hw->ops.write(hw, buf, count, offset);
 	return -ENXIO;	
@@ -157,7 +158,7 @@
 static int snd_hwdep_release(struct inode *inode, struct file * file)
 {
 	int err = -ENXIO;
-	snd_hwdep_t *hw = snd_magic_cast(snd_hwdep_t, file->private_data, return -ENXIO);
+	snd_hwdep_t *hw = file->private_data;
 	down(&hw->open_mutex);
 	if (hw->ops.release) {
 		err = hw->ops.release(hw, file);
@@ -173,7 +174,7 @@
 
 static unsigned int snd_hwdep_poll(struct file * file, poll_table * wait)
 {
-	snd_hwdep_t *hw = snd_magic_cast(snd_hwdep_t, file->private_data, return 0);
+	snd_hwdep_t *hw = file->private_data;
 	if (hw->ops.poll)
 		return hw->ops.poll(hw, file, wait);
 	return 0;
@@ -231,10 +232,10 @@
 	return 0;
 }
 
-static int snd_hwdep_ioctl(struct inode *inode, struct file * file,
-			   unsigned int cmd, unsigned long arg)
+static inline int _snd_hwdep_ioctl(struct inode *inode, struct file * file,
+				   unsigned int cmd, unsigned long arg)
 {
-	snd_hwdep_t *hw = snd_magic_cast(snd_hwdep_t, file->private_data, return -ENXIO);
+	snd_hwdep_t *hw = file->private_data;
 	void __user *argp = (void __user *)arg;
 	switch (cmd) {
 	case SNDRV_HWDEP_IOCTL_PVERSION:
@@ -251,9 +252,20 @@
 	return -ENOTTY;
 }
 
+/* FIXME: need to unlock BKL to allow preemption */
+static int snd_hwdep_ioctl(struct inode *inode, struct file * file,
+			   unsigned int cmd, unsigned long arg)
+{
+	int err;
+	unlock_kernel();
+	err = _snd_hwdep_ioctl(inode, file, cmd, arg);
+	lock_kernel();
+	return err;
+}
+
 static int snd_hwdep_mmap(struct file * file, struct vm_area_struct * vma)
 {
-	snd_hwdep_t *hw = snd_magic_cast(snd_hwdep_t, file->private_data, return -ENXIO);
+	snd_hwdep_t *hw = file->private_data;
 	if (hw->ops.mmap)
 		return hw->ops.mmap(hw, file, vma);
 	return -ENXIO;
@@ -352,7 +364,7 @@
 	snd_assert(rhwdep != NULL, return -EINVAL);
 	*rhwdep = NULL;
 	snd_assert(card != NULL, return -ENXIO);
-	hwdep = snd_magic_kcalloc(snd_hwdep_t, 0, GFP_KERNEL);
+	hwdep = kcalloc(1, sizeof(*hwdep), GFP_KERNEL);
 	if (hwdep == NULL)
 		return -ENOMEM;
 	hwdep->card = card;
@@ -378,19 +390,19 @@
 	snd_assert(hwdep != NULL, return -ENXIO);
 	if (hwdep->private_free)
 		hwdep->private_free(hwdep);
-	snd_magic_kfree(hwdep);
+	kfree(hwdep);
 	return 0;
 }
 
 static int snd_hwdep_dev_free(snd_device_t *device)
 {
-	snd_hwdep_t *hwdep = snd_magic_cast(snd_hwdep_t, device->device_data, return -ENXIO);
+	snd_hwdep_t *hwdep = device->device_data;
 	return snd_hwdep_free(hwdep);
 }
 
 static int snd_hwdep_dev_register(snd_device_t *device)
 {
-	snd_hwdep_t *hwdep = snd_magic_cast(snd_hwdep_t, device->device_data, return -ENXIO);
+	snd_hwdep_t *hwdep = device->device_data;
 	int idx, err;
 	char name[32];
 
@@ -433,7 +445,7 @@
 
 static int snd_hwdep_dev_unregister(snd_device_t *device)
 {
-	snd_hwdep_t *hwdep = snd_magic_cast(snd_hwdep_t, device->device_data, return -ENXIO);
+	snd_hwdep_t *hwdep = device->device_data;
 	int idx;
 
 	snd_assert(hwdep != NULL, return -ENXIO);
diff -Nru a/sound/core/info.c b/sound/core/info.c
--- a/sound/core/info.c	2004-10-18 14:57:04 -07:00
+++ b/sound/core/info.c	2004-10-18 14:57:04 -07:00
@@ -139,7 +139,7 @@
 	struct snd_info_entry *entry;
 	loff_t ret;
 
-	data = snd_magic_cast(snd_info_private_data_t, file->private_data, return -ENXIO);
+	data = file->private_data;
 	entry = data->entry;
 	lock_kernel();
 	switch (entry->content) {
@@ -183,7 +183,7 @@
 	size_t size = 0;
 	loff_t pos;
 
-	data = snd_magic_cast(snd_info_private_data_t, file->private_data, return -ENXIO);
+	data = file->private_data;
 	snd_assert(data != NULL, return -ENXIO);
 	pos = *offset;
 	if (pos < 0 || (long) pos != pos || (ssize_t) count < 0)
@@ -224,7 +224,7 @@
 	size_t size = 0;
 	loff_t pos;
 
-	data = snd_magic_cast(snd_info_private_data_t, file->private_data, return -ENXIO);
+	data = file->private_data;
 	snd_assert(data != NULL, return -ENXIO);
 	entry = data->entry;
 	pos = *offset;
@@ -296,7 +296,7 @@
 		    	goto __error;
 		}
 	}
-	data = snd_magic_kcalloc(snd_info_private_data_t, 0, GFP_KERNEL);
+	data = kcalloc(1, sizeof(*data), GFP_KERNEL);
 	if (data == NULL) {
 		err = -ENOMEM;
 		goto __error;
@@ -305,10 +305,9 @@
 	switch (entry->content) {
 	case SNDRV_INFO_CONTENT_TEXT:
 		if (mode == O_RDONLY || mode == O_RDWR) {
-			buffer = (snd_info_buffer_t *)
-				 	snd_kcalloc(sizeof(snd_info_buffer_t), GFP_KERNEL);
+			buffer = kcalloc(1, sizeof(*buffer), GFP_KERNEL);
 			if (buffer == NULL) {
-				snd_magic_kfree(data);
+				kfree(data);
 				err = -ENOMEM;
 				goto __error;
 			}
@@ -317,7 +316,7 @@
 			buffer->buffer = vmalloc(buffer->len);
 			if (buffer->buffer == NULL) {
 				kfree(buffer);
-				snd_magic_kfree(data);
+				kfree(data);
 				err = -ENOMEM;
 				goto __error;
 			}
@@ -325,14 +324,13 @@
 			data->rbuffer = buffer;
 		}
 		if (mode == O_WRONLY || mode == O_RDWR) {
-			buffer = (snd_info_buffer_t *)
-					snd_kcalloc(sizeof(snd_info_buffer_t), GFP_KERNEL);
+			buffer = kcalloc(1, sizeof(*buffer), GFP_KERNEL);
 			if (buffer == NULL) {
 				if (mode == O_RDWR) {
 					vfree(data->rbuffer->buffer);
 					kfree(data->rbuffer);
 				}
-				snd_magic_kfree(data);
+				kfree(data);
 				err = -ENOMEM;
 				goto __error;
 			}
@@ -345,7 +343,7 @@
 					kfree(data->rbuffer);
 				}
 				kfree(buffer);
-				snd_magic_kfree(data);
+				kfree(data);
 				err = -ENOMEM;
 				goto __error;
 			}
@@ -357,7 +355,7 @@
 		if (entry->c.ops->open) {
 			if ((err = entry->c.ops->open(entry, mode,
 						      &data->file_private_data)) < 0) {
-				snd_magic_kfree(data);
+				kfree(data);
 				goto __error;
 			}
 		}
@@ -389,7 +387,7 @@
 	int mode;
 
 	mode = file->f_flags & O_ACCMODE;
-	data = snd_magic_cast(snd_info_private_data_t, file->private_data, return -ENXIO);
+	data = file->private_data;
 	entry = data->entry;
 	switch (entry->content) {
 	case SNDRV_INFO_CONTENT_TEXT:
@@ -417,7 +415,7 @@
 		break;
 	}
 	module_put(entry->module);
-	snd_magic_kfree(data);
+	kfree(data);
 	return 0;
 }
 
@@ -427,7 +425,7 @@
 	struct snd_info_entry *entry;
 	unsigned int mask;
 
-	data = snd_magic_cast(snd_info_private_data_t, file->private_data, return -ENXIO);
+	data = file->private_data;
 	if (data == NULL)
 		return 0;
 	entry = data->entry;
@@ -447,13 +445,13 @@
 	return mask;
 }
 
-static int snd_info_entry_ioctl(struct inode *inode, struct file *file,
-				unsigned int cmd, unsigned long arg)
+static inline int _snd_info_entry_ioctl(struct inode *inode, struct file *file,
+					unsigned int cmd, unsigned long arg)
 {
 	snd_info_private_data_t *data;
 	struct snd_info_entry *entry;
 
-	data = snd_magic_cast(snd_info_private_data_t, file->private_data, return -ENXIO);
+	data = file->private_data;
 	if (data == NULL)
 		return 0;
 	entry = data->entry;
@@ -468,13 +466,24 @@
 	return -ENOTTY;
 }
 
+/* FIXME: need to unlock BKL to allow preemption */
+static int snd_info_entry_ioctl(struct inode *inode, struct file *file,
+				unsigned int cmd, unsigned long arg)
+{
+	int err;
+	unlock_kernel();
+	err = _snd_info_entry_ioctl(inode, file, cmd, arg);
+	lock_kernel();
+	return err;
+}
+
 static int snd_info_entry_mmap(struct file *file, struct vm_area_struct *vma)
 {
 	struct inode *inode = file->f_dentry->d_inode;
 	snd_info_private_data_t *data;
 	struct snd_info_entry *entry;
 
-	data = snd_magic_cast(snd_info_private_data_t, file->private_data, return -ENXIO);
+	data = file->private_data;
 	if (data == NULL)
 		return 0;
 	entry = data->entry;
@@ -744,12 +753,12 @@
 static snd_info_entry_t *snd_info_create_entry(const char *name)
 {
 	snd_info_entry_t *entry;
-	entry = snd_magic_kcalloc(snd_info_entry_t, 0, GFP_KERNEL);
+	entry = kcalloc(1, sizeof(*entry), GFP_KERNEL);
 	if (entry == NULL)
 		return NULL;
 	entry->name = snd_kmalloc_strdup(name, GFP_KERNEL);
 	if (entry->name == NULL) {
-		snd_magic_kfree(entry);
+		kfree(entry);
 		return NULL;
 	}
 	entry->mode = S_IFREG | S_IRUGO;
@@ -805,27 +814,27 @@
 
 static int snd_info_dev_free_entry(snd_device_t *device)
 {
-	snd_info_entry_t *entry = snd_magic_cast(snd_info_entry_t, device->device_data, return -ENXIO);
+	snd_info_entry_t *entry = device->device_data;
 	snd_info_free_entry(entry);
 	return 0;
 }
 
 static int snd_info_dev_register_entry(snd_device_t *device)
 {
-	snd_info_entry_t *entry = snd_magic_cast(snd_info_entry_t, device->device_data, return -ENXIO);
+	snd_info_entry_t *entry = device->device_data;
 	return snd_info_register(entry);
 }
 
 static int snd_info_dev_disconnect_entry(snd_device_t *device)
 {
-	snd_info_entry_t *entry = snd_magic_cast(snd_info_entry_t, device->device_data, return -ENXIO);
+	snd_info_entry_t *entry = device->device_data;
 	entry->disconnected = 1;
 	return 0;
 }
 
 static int snd_info_dev_unregister_entry(snd_device_t *device)
 {
-	snd_info_entry_t *entry = snd_magic_cast(snd_info_entry_t, device->device_data, return -ENXIO);
+	snd_info_entry_t *entry = device->device_data;
 	return snd_info_unregister(entry);
 }
 
@@ -887,7 +896,7 @@
 		kfree((char *)entry->name);
 	if (entry->private_free)
 		entry->private_free(entry);
-	snd_magic_kfree(entry);
+	kfree(entry);
 }
 
 /**
diff -Nru a/sound/core/info_oss.c b/sound/core/info_oss.c
--- a/sound/core/info_oss.c	2004-10-18 14:56:16 -07:00
+++ b/sound/core/info_oss.c	2004-10-18 14:56:16 -07:00
@@ -134,16 +134,4 @@
 	return 0;
 }
 
-#else
-
-int snd_info_minor_register(void)
-{
-	return 0;
-}
-
-int snd_info_minor_unregister(void)
-{
-	return 0;
-}
-
 #endif /* CONFIG_SND_OSSEMUL */
diff -Nru a/sound/core/init.c b/sound/core/init.c
--- a/sound/core/init.c	2004-10-18 14:56:17 -07:00
+++ b/sound/core/init.c	2004-10-18 14:56:17 -07:00
@@ -73,7 +73,7 @@
 
 	if (extra_size < 0)
 		extra_size = 0;
-	card = (snd_card_t *) snd_kcalloc(sizeof(snd_card_t) + extra_size, GFP_KERNEL);
+	card = kcalloc(1, sizeof(*card) + extra_size, GFP_KERNEL);
 	if (card == NULL)
 		return NULL;
 	if (xid) {
@@ -800,6 +800,8 @@
 		return 0;
 	if (card->power_state == SNDRV_CTL_POWER_D0)
 		return 0;
+	/* restore the PCI config space */
+	pci_restore_state(dev, dev->saved_config_space);
 	/* FIXME: correct state value? */
 	return card->pm_resume(card, 0);
 }
diff -Nru a/sound/core/ioctl32/ioctl32.c b/sound/core/ioctl32/ioctl32.c
--- a/sound/core/ioctl32/ioctl32.c	2004-10-18 14:55:55 -07:00
+++ b/sound/core/ioctl32/ioctl32.c	2004-10-18 14:55:55 -07:00
@@ -257,7 +257,7 @@
 	snd_ctl_elem_info_t info;
 	int err;
 
-	ctl = snd_magic_cast(snd_ctl_file_t, file->private_data, return -ENXIO);
+	ctl = file->private_data;
 
 	down_read(&ctl->card->controls_rwsem);
 	kctl = snd_ctl_find_id(ctl->card, id);
diff -Nru a/sound/core/ioctl32/pcm32.c b/sound/core/ioctl32/pcm32.c
--- a/sound/core/ioctl32/pcm32.c	2004-10-18 14:56:33 -07:00
+++ b/sound/core/ioctl32/pcm32.c	2004-10-18 14:56:33 -07:00
@@ -69,7 +69,7 @@
 	unsigned char reserved[64];
 } __attribute__((packed));
 
-#define numberof(array)  (sizeof(array)/sizeof(array[0]))
+#define numberof(array) ARRAY_SIZE(array)
 
 #define CVT_sndrv_pcm_hw_params()\
 {\
@@ -235,7 +235,7 @@
 
 	/* FIXME: need to check whether fop->ioctl is sane */
 
-	pcm_file = snd_magic_cast(snd_pcm_file_t, file->private_data, return -ENXIO);
+	pcm_file = file->private_data;
 	substream = pcm_file->substream;
 	snd_assert(substream != NULL && substream->runtime, return -ENXIO);
 
@@ -313,7 +313,7 @@
 
 	memset(params, 0, sizeof(*params));
 	params->flags = oparams->flags;
-	for (i = 0; i < sizeof(oparams->masks) / sizeof(unsigned int); i++)
+	for (i = 0; i < ARRAY_SIZE(oparams->masks); i++)
 		params->masks[i].bits[0] = oparams->masks[i];
 	memcpy(params->intervals, oparams->intervals, sizeof(oparams->intervals));
 	params->rmask = __OLD_TO_NEW_MASK(oparams->rmask);
@@ -331,7 +331,7 @@
 
 	memset(oparams, 0, sizeof(*oparams));
 	oparams->flags = params->flags;
-	for (i = 0; i < sizeof(oparams->masks) / sizeof(unsigned int); i++)
+	for (i = 0; i < ARRAY_SIZE(oparams->masks); i++)
 		oparams->masks[i] = params->masks[i].bits[0];
 	memcpy(oparams->intervals, params->intervals, sizeof(oparams->intervals));
 	oparams->rmask = __NEW_TO_OLD_MASK(params->rmask);
@@ -350,8 +350,8 @@
 	mm_segment_t oldseg;
 	int err;
 
-	data32 = snd_kcalloc(sizeof(*data32), GFP_KERNEL);
-	data = snd_kcalloc(sizeof(*data), GFP_KERNEL);
+	data32 = kcalloc(1, sizeof(*data32), GFP_KERNEL);
+	data = kcalloc(1, sizeof(*data), GFP_KERNEL);
 	if (data32 == NULL || data == NULL) {
 		err = -ENOMEM;
 		goto __end;
@@ -379,6 +379,45 @@
 	return err;
 }
 
+struct sndrv_pcm_mmap_status32 {
+	s32 state;
+	s32 pad1;
+	u32 hw_ptr;
+	struct compat_timespec tstamp;
+	s32 suspended_state;
+} __attribute__((packed));
+
+struct sndrv_pcm_mmap_control32 {
+	u32 appl_ptr;
+	u32 avail_min;
+} __attribute__((packed));
+
+struct sndrv_pcm_sync_ptr32 {
+	u32 flags;
+	union {
+		struct sndrv_pcm_mmap_status32 status;
+		unsigned char reserved[64];
+	} s;
+	union {
+		struct sndrv_pcm_mmap_control32 control;
+		unsigned char reserved[64];
+	} c;
+} __attribute__((packed));
+
+#define CVT_sndrv_pcm_sync_ptr()\
+{\
+	COPY(flags);\
+	COPY(s.status.state);\
+	COPY(s.status.pad1);\
+	COPY(s.status.hw_ptr);\
+	COPY(s.status.tstamp.tv_sec);\
+	COPY(s.status.tstamp.tv_nsec);\
+	COPY(s.status.suspended_state);\
+	COPY(c.control.appl_ptr);\
+	COPY(c.control.avail_min);\
+}
+
+DEFINE_ALSA_IOCTL_BIG(pcm_sync_ptr);
 
 /*
  */
@@ -396,6 +435,7 @@
 DEFINE_ALSA_IOCTL_ENTRY(pcm_writei, xferi, SNDRV_PCM_IOCTL_WRITEI_FRAMES);
 DEFINE_ALSA_IOCTL_ENTRY(pcm_readn, xfern, SNDRV_PCM_IOCTL_READN_FRAMES);
 DEFINE_ALSA_IOCTL_ENTRY(pcm_writen, xfern, SNDRV_PCM_IOCTL_WRITEN_FRAMES);
+DEFINE_ALSA_IOCTL_ENTRY(pcm_sync_ptr, pcm_sync_ptr, SNDRV_PCM_IOCTL_SYNC_PTR);
 
 
 /*
@@ -416,6 +456,7 @@
 	SNDRV_PCM_IOCTL_READN_FRAMES32 = _IOR('A', 0x53, struct sndrv_xfern32),
 	SNDRV_PCM_IOCTL_HW_REFINE_OLD32 = _IOWR('A', 0x10, struct sndrv_pcm_hw_params_old32),
 	SNDRV_PCM_IOCTL_HW_PARAMS_OLD32 = _IOWR('A', 0x11, struct sndrv_pcm_hw_params_old32),
+	SNDRV_PCM_IOCTL_SYNC_PTR32 = _IOWR('A', 0x23, struct sndrv_pcm_sync_ptr),
 
 };
 
@@ -431,6 +472,8 @@
 	{ SNDRV_PCM_IOCTL_SW_PARAMS32, AP(pcm_sw_params) },
 	{ SNDRV_PCM_IOCTL_STATUS32, AP(pcm_status) },
 	{ SNDRV_PCM_IOCTL_DELAY32, AP(pcm_delay) },
+	MAP_COMPAT(SNDRV_PCM_IOCTL_HWSYNC),
+	{ SNDRV_PCM_IOCTL_SYNC_PTR32, AP(pcm_sync_ptr) },
 	{ SNDRV_PCM_IOCTL_CHANNEL_INFO32, AP(pcm_channel_info) },
 	MAP_COMPAT(SNDRV_PCM_IOCTL_PREPARE),
 	MAP_COMPAT(SNDRV_PCM_IOCTL_RESET),
diff -Nru a/sound/core/memalloc.c b/sound/core/memalloc.c
--- a/sound/core/memalloc.c	2004-10-18 14:57:04 -07:00
+++ b/sound/core/memalloc.c	2004-10-18 14:57:04 -07:00
@@ -45,15 +45,19 @@
 #ifndef SNDRV_CARDS
 #define SNDRV_CARDS	8
 #endif
+
+/* FIXME: so far only some PCI devices have the preallocation table */
+#ifdef CONFIG_PCI
 static int enable[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS-1)] = 1};
 static int boot_devs;
 module_param_array(enable, bool, boot_devs, 0444);
 MODULE_PARM_DESC(enable, "Enable cards to allocate buffers.");
+#endif
 
 /*
  */
 
-void *snd_malloc_sgbuf_pages(const struct snd_dma_device *dev,
+void *snd_malloc_sgbuf_pages(struct device *device,
                              size_t size, struct snd_dma_buffer *dmab,
 			     size_t *res_size);
 int snd_free_sgbuf_pages(struct snd_dma_buffer *dmab);
@@ -66,9 +70,8 @@
 
 /* buffer preservation list */
 struct snd_mem_list {
-	struct snd_dma_device dev;
 	struct snd_dma_buffer buffer;
-	int used;
+	unsigned int id;
 	struct list_head list;
 };
 
@@ -148,6 +151,10 @@
 
 #endif /* arch */
 
+#if ! defined(__arm__)
+#define NEED_RESERVE_PAGES
+#endif
+
 /*
  *
  *  Generic memory allocators
@@ -156,22 +163,28 @@
 
 static long snd_allocated_pages; /* holding the number of allocated pages */
 
-static void mark_pages(void *res, int order)
+static inline void inc_snd_pages(int order)
+{
+	snd_allocated_pages += 1 << order;
+}
+
+static inline void dec_snd_pages(int order)
+{
+	snd_allocated_pages -= 1 << order;
+}
+
+static void mark_pages(struct page *page, int order)
 {
-	struct page *page = virt_to_page(res);
 	struct page *last_page = page + (1 << order);
 	while (page < last_page)
 		SetPageReserved(page++);
-	snd_allocated_pages += 1 << order;
 }
 
-static void unmark_pages(void *res, int order)
+static void unmark_pages(struct page *page, int order)
 {
-	struct page *page = virt_to_page(res);
 	struct page *last_page = page + (1 << order);
 	while (page < last_page)
 		ClearPageReserved(page++);
-	snd_allocated_pages -= 1 << order;
 }
 
 /**
@@ -190,43 +203,15 @@
 
 	snd_assert(size > 0, return NULL);
 	snd_assert(gfp_flags != 0, return NULL);
-	for (pg = 0; PAGE_SIZE * (1 << pg) < size; pg++);
+	pg = get_order(size);
 	if ((res = (void *) __get_free_pages(gfp_flags, pg)) != NULL) {
-		mark_pages(res, pg);
+		mark_pages(virt_to_page(res), pg);
+		inc_snd_pages(pg);
 	}
 	return res;
 }
 
 /**
- * snd_malloc_pages_fallback - allocate pages with the given size with fallback
- * @size: the requested size to allocate in bytes
- * @gfp_flags: the allocation conditions, GFP_XXX
- * @res_size: the pointer to store the size of buffer actually allocated
- *
- * Allocates the physically contiguous pages with the given request
- * size.  When no space is left, this function reduces the size and
- * tries to allocate again.  The size actually allocated is stored in
- * res_size argument.
- *
- * Returns the pointer of the buffer, or NULL if no enoguh memory.
- */            
-void *snd_malloc_pages_fallback(size_t size, unsigned int gfp_flags, size_t *res_size)
-{
-	void *res;
-
-	snd_assert(size > 0, return NULL);
-	snd_assert(res_size != NULL, return NULL);
-	do {
-		if ((res = snd_malloc_pages(size, gfp_flags)) != NULL) {
-			*res_size = size;
-			return res;
-		}
-		size >>= 1;
-	} while (size >= PAGE_SIZE);
-	return NULL;
-}
-
-/**
  * snd_free_pages - release the pages
  * @ptr: the buffer pointer to release
  * @size: the allocated buffer size
@@ -239,8 +224,9 @@
 
 	if (ptr == NULL)
 		return;
-	for (pg = 0; PAGE_SIZE * (1 << pg) < size; pg++);
-	unmark_pages(ptr, pg);
+	pg = get_order(size);
+	dec_snd_pages(pg);
+	unmark_pages(virt_to_page(ptr), pg);
 	free_pages((unsigned long) ptr, pg);
 }
 
@@ -250,6 +236,7 @@
  *
  */
 
+/* allocate the coherent DMA pages */
 static void *snd_malloc_dev_pages(struct device *dev, size_t size, dma_addr_t *dma)
 {
 	int pg;
@@ -263,28 +250,17 @@
 	if (pg > 0)
 		gfp_flags |= __GFP_NOWARN;
 	res = dma_alloc_coherent(dev, PAGE_SIZE << pg, dma, gfp_flags);
-	if (res != NULL)
-		mark_pages(res, pg);
+	if (res != NULL) {
+#ifdef NEED_RESERVE_PAGES
+		mark_pages(virt_to_page(res), pg); /* should be dma_to_page() */
+#endif
+		inc_snd_pages(pg);
+	}
 
 	return res;
 }
 
-static void *snd_malloc_dev_pages_fallback(struct device *dev, size_t size,
-					   dma_addr_t *dma, size_t *res_size)
-{
-	void *res;
-
-	snd_assert(res_size != NULL, return NULL);
-	do {
-		if ((res = snd_malloc_dev_pages(dev, size, dma)) != NULL) {
-			*res_size = size;
-			return res;
-		}
-		size >>= 1;
-	} while (size >= PAGE_SIZE);
-	return NULL;
-}
-
+/* free the coherent DMA pages */
 static void snd_free_dev_pages(struct device *dev, size_t size, void *ptr,
 			       dma_addr_t dma)
 {
@@ -293,7 +269,10 @@
 	if (ptr == NULL)
 		return;
 	pg = get_order(size);
-	unmark_pages(ptr, pg);
+	dec_snd_pages(pg);
+#ifdef NEED_RESERVE_PAGES
+	unmark_pages(virt_to_page(ptr), pg); /* should be dma_to_page() */
+#endif
 	dma_free_coherent(dev, PAGE_SIZE << pg, ptr, dma);
 }
 
@@ -308,30 +287,13 @@
 
 	snd_assert(size > 0, return NULL);
 	snd_assert(dma_addr != NULL, return NULL);
-	for (pg = 0; PAGE_SIZE * (1 << pg) < size; pg++);
+	pg = get_order(size);
 	res = sbus_alloc_consistent(sdev, PAGE_SIZE * (1 << pg), dma_addr);
-	if (res != NULL) {
-		mark_pages(res, pg);
-	}
+	if (res != NULL)
+		inc_snd_pages(pg);
 	return res;
 }
 
-static void *snd_malloc_sbus_pages_fallback(struct device *dev, size_t size,
-					    dma_addr_t *dma_addr, size_t *res_size)
-{
-	void *res;
-
-	snd_assert(res_size != NULL, return NULL);
-	do {
-		if ((res = snd_malloc_sbus_pages(dev, size, dma_addr)) != NULL) {
-			*res_size = size;
-			return res;
-		}
-		size >>= 1;
-	} while (size >= PAGE_SIZE);
-	return NULL;
-}
-
 static void snd_free_sbus_pages(struct device *dev, size_t size,
 				void *ptr, dma_addr_t dma_addr)
 {
@@ -340,8 +302,8 @@
 
 	if (ptr == NULL)
 		return;
-	for (pg = 0; PAGE_SIZE * (1 << pg) < size; pg++);
-	unmark_pages(ptr, pg);
+	pg = get_order(size);
+	dec_snd_pages(pg);
 	sbus_free_consistent(sdev, PAGE_SIZE * (1 << pg), ptr, dma_addr);
 }
 
@@ -354,24 +316,10 @@
  */
 
 
-/*
- * compare the two devices
- * returns non-zero if matched.
- */
-static int compare_device(const struct snd_dma_device *a, const struct snd_dma_device *b, int allow_unused)
-{
-	if (a->type != b->type)
-		return 0;
-	if (a->id != b->id) {
-		if (! allow_unused || (a->id != SNDRV_DMA_DEVICE_UNUSED && b->id != SNDRV_DMA_DEVICE_UNUSED))
-			return 0;
-	}
-	return a->dev == b->dev;
-}
-
 /**
  * snd_dma_alloc_pages - allocate the buffer area according to the given type
- * @dev: the buffer device info
+ * @type: the DMA buffer type
+ * @device: the device pointer
  * @size: the buffer size to allocate
  * @dmab: buffer allocation record to store the allocated data
  *
@@ -381,32 +329,33 @@
  * Returns zero if the buffer with the given size is allocated successfuly,
  * other a negative value at error.
  */
-int snd_dma_alloc_pages(const struct snd_dma_device *dev, size_t size,
+int snd_dma_alloc_pages(int type, struct device *device, size_t size,
 			struct snd_dma_buffer *dmab)
 {
-	snd_assert(dev != NULL, return -ENXIO);
 	snd_assert(size > 0, return -ENXIO);
 	snd_assert(dmab != NULL, return -ENXIO);
 
+	dmab->dev.type = type;
+	dmab->dev.dev = device;
 	dmab->bytes = 0;
-	switch (dev->type) {
+	switch (type) {
 	case SNDRV_DMA_TYPE_CONTINUOUS:
-		dmab->area = snd_malloc_pages(size, (unsigned long)dev->dev);
+		dmab->area = snd_malloc_pages(size, (unsigned long)device);
 		dmab->addr = 0;
 		break;
 #ifdef CONFIG_SBUS
 	case SNDRV_DMA_TYPE_SBUS:
-		dmab->area = snd_malloc_sbus_pages(dev->dev, size, &dmab->addr);
+		dmab->area = snd_malloc_sbus_pages(device, size, &dmab->addr);
 		break;
 #endif
 	case SNDRV_DMA_TYPE_DEV:
-		dmab->area = snd_malloc_dev_pages(dev->dev, size, &dmab->addr);
+		dmab->area = snd_malloc_dev_pages(device, size, &dmab->addr);
 		break;
 	case SNDRV_DMA_TYPE_DEV_SG:
-		snd_malloc_sgbuf_pages(dev, size, dmab, NULL);
+		snd_malloc_sgbuf_pages(device, size, dmab, NULL);
 		break;
 	default:
-		printk(KERN_ERR "snd-malloc: invalid device type %d\n", dev->type);
+		printk(KERN_ERR "snd-malloc: invalid device type %d\n", type);
 		dmab->area = NULL;
 		dmab->addr = 0;
 		return -ENXIO;
@@ -419,7 +368,8 @@
 
 /**
  * snd_dma_alloc_pages_fallback - allocate the buffer area according to the given type with fallback
- * @dev: the buffer device info
+ * @type: the DMA buffer type
+ * @device: the device pointer
  * @size: the buffer size to allocate
  * @dmab: buffer allocation record to store the allocated data
  *
@@ -431,35 +381,20 @@
  * Returns zero if the buffer with the given size is allocated successfuly,
  * other a negative value at error.
  */
-int snd_dma_alloc_pages_fallback(const struct snd_dma_device *dev, size_t size,
+int snd_dma_alloc_pages_fallback(int type, struct device *device, size_t size,
 				 struct snd_dma_buffer *dmab)
 {
-	snd_assert(dev != NULL, return -ENXIO);
+	int err;
+
 	snd_assert(size > 0, return -ENXIO);
 	snd_assert(dmab != NULL, return -ENXIO);
 
-	dmab->bytes = 0;
-	switch (dev->type) {
-	case SNDRV_DMA_TYPE_CONTINUOUS:
-		dmab->area = snd_malloc_pages_fallback(size, (unsigned long)dev->dev, &dmab->bytes);
-		dmab->addr = 0;
-		break;
-#ifdef CONFIG_SBUS
-	case SNDRV_DMA_TYPE_SBUS:
-		dmab->area = snd_malloc_sbus_pages_fallback(dev->dev, size, &dmab->addr, &dmab->bytes);
-		break;
-#endif
-	case SNDRV_DMA_TYPE_DEV:
-		dmab->area = snd_malloc_dev_pages_fallback(dev->dev, size, &dmab->addr, &dmab->bytes);
-		break;
-	case SNDRV_DMA_TYPE_DEV_SG:
-		snd_malloc_sgbuf_pages(dev, size, dmab, &dmab->bytes);
-		break;
-	default:
-		printk(KERN_ERR "snd-malloc: invalid device type %d\n", dev->type);
-		dmab->area = NULL;
-		dmab->addr = 0;
-		return -ENXIO;
+	while ((err = snd_dma_alloc_pages(type, device, size, dmab)) < 0) {
+		if (err != -ENOMEM)
+			return err;
+		size >>= 1;
+		if (size <= PAGE_SIZE)
+			return -ENOMEM;
 	}
 	if (! dmab->area)
 		return -ENOMEM;
@@ -469,152 +404,87 @@
 
 /**
  * snd_dma_free_pages - release the allocated buffer
- * @dev: the buffer device info
- * @dmbab: the buffer allocation record to release
+ * @dmab: the buffer allocation record to release
  *
  * Releases the allocated buffer via snd_dma_alloc_pages().
  */
-void snd_dma_free_pages(const struct snd_dma_device *dev, struct snd_dma_buffer *dmab)
+void snd_dma_free_pages(struct snd_dma_buffer *dmab)
 {
-	switch (dev->type) {
+	switch (dmab->dev.type) {
 	case SNDRV_DMA_TYPE_CONTINUOUS:
 		snd_free_pages(dmab->area, dmab->bytes);
 		break;
 #ifdef CONFIG_SBUS
 	case SNDRV_DMA_TYPE_SBUS:
-		snd_free_sbus_pages(dev->dev, dmab->bytes, dmab->area, dmab->addr);
+		snd_free_sbus_pages(dmab->dev.dev, dmab->bytes, dmab->area, dmab->addr);
 		break;
 #endif
 	case SNDRV_DMA_TYPE_DEV:
-		snd_free_dev_pages(dev->dev, dmab->bytes, dmab->area, dmab->addr);
+		snd_free_dev_pages(dmab->dev.dev, dmab->bytes, dmab->area, dmab->addr);
 		break;
 	case SNDRV_DMA_TYPE_DEV_SG:
 		snd_free_sgbuf_pages(dmab);
 		break;
 	default:
-		printk(KERN_ERR "snd-malloc: invalid device type %d\n", dev->type);
+		printk(KERN_ERR "snd-malloc: invalid device type %d\n", dmab->dev.type);
 	}
 }
 
 
-/*
- * search for the device
- */
-static struct snd_mem_list *mem_list_find(const struct snd_dma_device *dev, int search_empty)
-{
-	struct list_head *p;
-	struct snd_mem_list *mem;
-
-	list_for_each(p, &mem_list_head) {
-		mem = list_entry(p, struct snd_mem_list, list);
-		if (mem->used && search_empty)
-			continue;
-		if (compare_device(&mem->dev, dev, search_empty))
-			return mem;
-	}
-	return NULL;
-}
-
 /**
  * snd_dma_get_reserved - get the reserved buffer for the given device
- * @dev: the buffer device info
  * @dmab: the buffer allocation record to store
+ * @id: the buffer id
  *
  * Looks for the reserved-buffer list and re-uses if the same buffer
- * is found in the list.  When the buffer is found, it's marked as used.
- * For unmarking the buffer, call snd_dma_free_reserved().
+ * is found in the list.  When the buffer is found, it's removed from the free list.
  *
  * Returns the size of buffer if the buffer is found, or zero if not found.
  */
-size_t snd_dma_get_reserved(const struct snd_dma_device *dev, struct snd_dma_buffer *dmab)
+size_t snd_dma_get_reserved_buf(struct snd_dma_buffer *dmab, unsigned int id)
 {
+	struct list_head *p;
 	struct snd_mem_list *mem;
 
-	snd_assert(dev && dmab, return 0);
+	snd_assert(dmab, return 0);
 
 	down(&list_mutex);
-	mem = mem_list_find(dev, 1);
-	if (mem) {
-		mem->used = 1;
-		mem->dev = *dev;
-		*dmab = mem->buffer;
-		up(&list_mutex);
-		return dmab->bytes;
+	list_for_each(p, &mem_list_head) {
+		mem = list_entry(p, struct snd_mem_list, list);
+		if (mem->id == id &&
+		    ! memcmp(&mem->buffer.dev, &dmab->dev, sizeof(dmab->dev))) {
+			list_del(p);
+			*dmab = mem->buffer;
+			kfree(mem);
+			up(&list_mutex);
+			return dmab->bytes;
+		}
 	}
 	up(&list_mutex);
 	return 0;
 }
 
 /**
- * snd_dma_free_reserved - unmark the reserved buffer
- * @dev: the buffer device info
- *
- * Looks for the matching reserved buffer and erases the mark on it
- * if found.
- *
- * Returns zero.
- */
-int snd_dma_free_reserved(const struct snd_dma_device *dev)
-{
-	struct snd_mem_list *mem;
-
-	snd_assert(dev, return -EINVAL);
-	down(&list_mutex);
-	mem = mem_list_find(dev, 0);
-	if (mem)
-		mem->used = 0;
-	up(&list_mutex);
-	return 0;
-}
-
-/**
- * snd_dma_set_reserved - reserve the buffer
- * @dev: the buffer device info
+ * snd_dma_reserve_buf - reserve the buffer
  * @dmab: the buffer to reserve
+ * @id: the buffer id
  *
  * Reserves the given buffer as a reserved buffer.
- * When an old reserved buffer already exists, the old one is released
- * and replaced with the new one.
- *
- * When NULL buffer pointer or zero buffer size is given, the existing
- * buffer is released and the entry is removed.
  * 
  * Returns zero if successful, or a negative code at error.
  */
-int snd_dma_set_reserved(const struct snd_dma_device *dev, struct snd_dma_buffer *dmab)
+int snd_dma_reserve_buf(struct snd_dma_buffer *dmab, unsigned int id)
 {
 	struct snd_mem_list *mem;
 
-	snd_assert(dev, return -EINVAL);
+	snd_assert(dmab, return -EINVAL);
+	mem = kmalloc(sizeof(*mem), GFP_KERNEL);
+	if (! mem)
+		return -ENOMEM;
 	down(&list_mutex);
-	mem = mem_list_find(dev, 0);
-	if (mem) {
-		if (mem->used)
-			printk(KERN_WARNING "snd-page-alloc: releasing the used block (type=%d, id=0x%x\n", mem->dev.type, mem->dev.id);
-		snd_dma_free_pages(dev, &mem->buffer);
-		if (! dmab || ! dmab->bytes) {
-			/* remove the entry */
-			list_del(&mem->list);
-			kfree(mem);
-			up(&list_mutex);
-			return 0;
-		}
-	} else {
-		if (! dmab || ! dmab->bytes) {
-			up(&list_mutex);
-			return 0;
-		}
-		mem = kmalloc(sizeof(*mem), GFP_KERNEL);
-		if (! mem) {
-			up(&list_mutex);
-			return -ENOMEM;
-		}
-		mem->dev = *dev;
-		list_add_tail(&mem->list, &mem_list_head);
-	}
-	/* store the entry */
-	mem->used = 1;
 	mem->buffer = *dmab;
+	mem->id = id;
+	list_add_tail(&mem->list, &mem_list_head);
 	up(&list_mutex);
 	return 0;
 }
@@ -632,7 +502,7 @@
 		p = mem_list_head.next;
 		mem = list_entry(p, struct snd_mem_list, list);
 		list_del(p);
-		snd_dma_free_pages(&mem->dev, &mem->buffer);
+		snd_dma_free_pages(&mem->buffer);
 		kfree(mem);
 	}
 	up(&list_mutex);
@@ -654,7 +524,7 @@
 	unsigned int buffers;
 };
 
-#define HAMMERFALL_BUFFER_SIZE    (16*1024*4*(26+1))
+#define HAMMERFALL_BUFFER_SIZE    (16*1024*4*(26+1)+0x10000)
 
 static struct prealloc_dev prealloc_devices[] __initdata = {
 	{
@@ -676,17 +546,6 @@
 	{ }, /* terminator */
 };
 
-/*
- * compose a snd_dma_device struct for the PCI device
- */
-static inline void snd_dma_device_pci(struct snd_dma_device *dev, struct pci_dev *pci, unsigned int id)
-{
-	memset(dev, 0, sizeof(*dev));
-	dev->type = SNDRV_DMA_TYPE_DEV;
-	dev->dev = snd_dma_pci_data(pci);
-	dev->id = id;
-}
-
 static void __init preallocate_cards(void)
 {
 	struct pci_dev *pci = NULL;
@@ -716,22 +575,13 @@
 			continue;
 		}
 		for (i = 0; i < dev->buffers; i++) {
-			struct snd_mem_list *mem;
-			mem = kmalloc(sizeof(*mem), GFP_KERNEL);
-			if (! mem) {
-				printk(KERN_WARNING "snd-page-alloc: can't malloc memlist\n");
-				break;
-			}
-			memset(mem, 0, sizeof(*mem));
-			snd_dma_device_pci(&mem->dev, pci, SNDRV_DMA_DEVICE_UNUSED);
-			if (snd_dma_alloc_pages(&mem->dev, dev->size, &mem->buffer) < 0) {
+			struct snd_dma_buffer dmab;
+			memset(&dmab, 0, sizeof(dmab));
+			if (snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, snd_dma_pci_data(pci),
+						dev->size, &dmab) < 0)
 				printk(KERN_WARNING "snd-page-alloc: cannot allocate buffer pages (size = %d)\n", dev->size);
-				kfree(mem);
-			} else {
-				down(&list_mutex);
-				list_add_tail(&mem->list, &mem_list_head);
-				up(&list_mutex);
-			}
+			else
+				snd_dma_reserve_buf(&dmab, snd_dma_pci_buf_id(pci));
 		}
 	}
 }
@@ -752,48 +602,22 @@
 	struct list_head *p;
 	struct snd_mem_list *mem;
 	int devno;
+	static char *types[] = { "UNKNOWN", "CONT", "DEV", "DEV-SG", "SBUS" };
 
 	down(&list_mutex);
-	len += sprintf(page + len, "pages  : %li bytes (%li pages per %likB)\n",
-		       pages * PAGE_SIZE, pages, PAGE_SIZE / 1024);
+	len += snprintf(page + len, count - len,
+			"pages  : %li bytes (%li pages per %likB)\n",
+			pages * PAGE_SIZE, pages, PAGE_SIZE / 1024);
 	devno = 0;
 	list_for_each(p, &mem_list_head) {
 		mem = list_entry(p, struct snd_mem_list, list);
 		devno++;
-		len += sprintf(page + len, "buffer %d : ", devno);
-		if (mem->dev.id == SNDRV_DMA_DEVICE_UNUSED)
-			len += sprintf(page + len, "UNUSED");
-		else
-			len += sprintf(page + len, "ID %08x", mem->dev.id);
-		len += sprintf(page + len, " : type ");
-		switch (mem->dev.type) {
-		case SNDRV_DMA_TYPE_CONTINUOUS:
-			len += sprintf(page + len, "CONT [%p]", mem->dev.dev);
-			break;
-#ifdef CONFIG_SBUS
-		case SNDRV_DMA_TYPE_SBUS:
-			{
-				struct sbus_dev *sdev = (struct sbus_dev *)(mem->dev.dev);
-				len += sprintf(page + len, "SBUS [%x]", sdev->slot);
-			}
-			break;
-#endif
-		case SNDRV_DMA_TYPE_DEV:
-		case SNDRV_DMA_TYPE_DEV_SG:
-			if (mem->dev.dev) {
-				len += sprintf(page + len, "%s [%s]",
-					       mem->dev.type == SNDRV_DMA_TYPE_DEV_SG ? "DEV-SG" : "DEV",
-					       mem->dev.dev->bus_id);
-			} else
-				len += sprintf(page + len, "ISA");
-			break;
-		default:
-			len += sprintf(page + len, "UNKNOWN");
-			break;
-		}
-		len += sprintf(page + len, "\n  addr = 0x%lx, size = %d bytes, used = %s\n",
-			       (unsigned long)mem->buffer.addr, (int)mem->buffer.bytes,
-			       mem->used ? "yes" : "no");
+		len += snprintf(page + len, count - len,
+				"buffer %d : ID %08x : type %s\n",
+				devno, mem->id, types[mem->buffer.dev.type]);
+		len += snprintf(page + len, count - len,
+				"  addr = 0x%lx, size = %d bytes\n",
+				(unsigned long)mem->buffer.addr, (int)mem->buffer.bytes);
 	}
 	up(&list_mutex);
 	return len;
@@ -833,10 +657,8 @@
 EXPORT_SYMBOL(snd_dma_alloc_pages_fallback);
 EXPORT_SYMBOL(snd_dma_free_pages);
 
-EXPORT_SYMBOL(snd_dma_get_reserved);
-EXPORT_SYMBOL(snd_dma_free_reserved);
-EXPORT_SYMBOL(snd_dma_set_reserved);
+EXPORT_SYMBOL(snd_dma_get_reserved_buf);
+EXPORT_SYMBOL(snd_dma_reserve_buf);
 
 EXPORT_SYMBOL(snd_malloc_pages);
-EXPORT_SYMBOL(snd_malloc_pages_fallback);
 EXPORT_SYMBOL(snd_free_pages);
diff -Nru a/sound/core/memory.c b/sound/core/memory.c
--- a/sound/core/memory.c	2004-10-18 14:55:54 -07:00
+++ b/sound/core/memory.c	2004-10-18 14:55:54 -07:00
@@ -71,8 +71,7 @@
 		snd_printk(KERN_ERR "Not freed snd_alloc_kmalloc = %li\n", snd_alloc_kmalloc);
 	if (snd_alloc_vmalloc > 0)
 		snd_printk(KERN_ERR "Not freed snd_alloc_vmalloc = %li\n", snd_alloc_vmalloc);
-	for (head = snd_alloc_kmalloc_list.prev;
-	     head != &snd_alloc_kmalloc_list; head = head->prev) {
+	list_for_each_prev(head, &snd_alloc_kmalloc_list) {
 		t = list_entry(head, struct snd_alloc_track, list);
 		if (t->magic != KMALLOC_MAGIC) {
 			snd_printk(KERN_ERR "Corrupted kmalloc\n");
@@ -80,8 +79,7 @@
 		}
 		snd_printk(KERN_ERR "kmalloc(%ld) from %p not freed\n", (long) t->size, t->caller);
 	}
-	for (head = snd_alloc_vmalloc_list.prev;
-	     head != &snd_alloc_vmalloc_list; head = head->prev) {
+	list_for_each_prev(head, &snd_alloc_vmalloc_list) {
 		t = list_entry(head, struct snd_alloc_track, list);
 		if (t->magic != VMALLOC_MAGIC) {
 			snd_printk(KERN_ERR "Corrupted vmalloc\n");
@@ -118,6 +116,17 @@
 	return _snd_kmalloc(size, flags);
 }
 
+void *snd_hidden_kcalloc(size_t n, size_t size, int flags)
+{
+	void *ret = NULL;
+	if (n != 0 && size > INT_MAX / n)
+		return ret;
+	ret = _snd_kmalloc(n * size, flags);
+	if (ret)
+		memset(ret, 0, n * size);
+	return ret;
+}
+
 void snd_hidden_kfree(const void *obj)
 {
 	unsigned long flags;
@@ -140,46 +149,6 @@
 	snd_wrapper_kfree(obj);
 }
 
-void *_snd_magic_kcalloc(unsigned long magic, size_t size, int flags)
-{
-	unsigned long *ptr;
-	ptr = _snd_kmalloc(size + sizeof(unsigned long), flags);
-	if (ptr) {
-		*ptr++ = magic;
-		memset(ptr, 0, size);
-	}
-	return ptr;
-}
-
-void *_snd_magic_kmalloc(unsigned long magic, size_t size, int flags)
-{
-	unsigned long *ptr;
-	ptr = _snd_kmalloc(size + sizeof(unsigned long), flags);
-	if (ptr)
-		*ptr++ = magic;
-	return ptr;
-}
-
-void snd_magic_kfree(void *_ptr)
-{
-	unsigned long *ptr = _ptr;
-	if (ptr == NULL) {
-		snd_printk(KERN_WARNING "null snd_magic_kfree (called from %p)\n", __builtin_return_address(0));
-		return;
-	}
-	*--ptr = 0;
-	{
-		struct snd_alloc_track *t;
-		t = snd_alloc_track_entry(ptr);
-		if (t->magic != KMALLOC_MAGIC) {
-			snd_printk(KERN_ERR "bad snd_magic_kfree (called from %p)\n", __builtin_return_address(0));
-			return;
-		}
-	}
-	snd_hidden_kfree(ptr);
-	return;
-}
-
 void *snd_hidden_vmalloc(unsigned long size)
 {
 	void *ptr;
@@ -254,25 +223,6 @@
 #define _snd_kmalloc kmalloc
 
 #endif /* CONFIG_SND_DEBUG_MEMORY */
-
-/**
- * snd_kcalloc - memory allocation and zero-clear
- * @size: the size to allocate in bytes
- * @flags: allocation conditions, GFP_XXX
- *
- * Allocates a memory chunk via kmalloc() and initializes it to zero.
- *
- * Returns the pointer, or NULL if no enoguh memory.
- */
-void *snd_kcalloc(size_t size, int flags)
-{
-	void *ptr;
-	
-	ptr = _snd_kmalloc(size, flags);
-	if (ptr)
-		memset(ptr, 0, size);
-	return ptr;
-}
 
 /**
  * snd_kmalloc_strdup - copy the string
diff -Nru a/sound/core/oss/mixer_oss.c b/sound/core/oss/mixer_oss.c
--- a/sound/core/oss/mixer_oss.c	2004-10-18 14:56:33 -07:00
+++ b/sound/core/oss/mixer_oss.c	2004-10-18 14:56:33 -07:00
@@ -21,6 +21,7 @@
 
 #include <sound/driver.h>
 #include <linux/init.h>
+#include <linux/smp_lock.h>
 #include <linux/slab.h>
 #include <linux/time.h>
 #include <sound/core.h>
@@ -51,7 +52,7 @@
 	err = snd_card_file_add(card, file);
 	if (err < 0)
 		return err;
-	fmixer = (snd_mixer_oss_file_t *)snd_kcalloc(sizeof(*fmixer), GFP_KERNEL);
+	fmixer = kcalloc(1, sizeof(*fmixer), GFP_KERNEL);
 	if (fmixer == NULL) {
 		snd_card_file_remove(card, file);
 		return -ENOMEM;
@@ -358,10 +359,16 @@
 	return -ENXIO;
 }
 
+/* FIXME: need to unlock BKL to allow preemption */
 int snd_mixer_oss_ioctl(struct inode *inode, struct file *file,
 			unsigned int cmd, unsigned long arg)
 {
-	return snd_mixer_oss_ioctl1((snd_mixer_oss_file_t *) file->private_data, cmd, arg);
+	int err;
+	/* FIXME: need to unlock BKL to allow preemption */
+	unlock_kernel();
+	err = snd_mixer_oss_ioctl1((snd_mixer_oss_file_t *) file->private_data, cmd, arg);
+	lock_kernel();
+	return err;
 }
 
 int snd_mixer_oss_ioctl_card(snd_card_t *card, unsigned int cmd, unsigned long arg)
@@ -508,8 +515,8 @@
 		up_read(&card->controls_rwsem);
 		return;
 	}
-	uinfo = snd_kcalloc(sizeof(*uinfo), GFP_KERNEL);
-	uctl = snd_kcalloc(sizeof(*uctl), GFP_KERNEL);
+	uinfo = kcalloc(1, sizeof(*uinfo), GFP_KERNEL);
+	uctl = kcalloc(1, sizeof(*uctl), GFP_KERNEL);
 	if (uinfo == NULL || uctl == NULL)
 		goto __unalloc;
 	snd_runtime_check(!kctl->info(kctl, uinfo), goto __unalloc);
@@ -544,8 +551,8 @@
 		up_read(&card->controls_rwsem);
 		return;
 	}
-	uinfo = snd_kcalloc(sizeof(*uinfo), GFP_KERNEL);
-	uctl = snd_kcalloc(sizeof(*uctl), GFP_KERNEL);
+	uinfo = kcalloc(1, sizeof(*uinfo), GFP_KERNEL);
+	uctl = kcalloc(1, sizeof(*uctl), GFP_KERNEL);
 	if (uinfo == NULL || uctl == NULL)
 		goto __unalloc;
 	snd_runtime_check(!kctl->info(kctl, uinfo), goto __unalloc);
@@ -607,8 +614,8 @@
 	down_read(&card->controls_rwsem);
 	if ((kctl = snd_ctl_find_numid(card, numid)) == NULL)
 		return;
-	uinfo = snd_kcalloc(sizeof(*uinfo), GFP_KERNEL);
-	uctl = snd_kcalloc(sizeof(*uctl), GFP_KERNEL);
+	uinfo = kcalloc(1, sizeof(*uinfo), GFP_KERNEL);
+	uctl = kcalloc(1, sizeof(*uctl), GFP_KERNEL);
 	if (uinfo == NULL || uctl == NULL)
 		goto __unalloc;
 	snd_runtime_check(!kctl->info(kctl, uinfo), goto __unalloc);
@@ -646,8 +653,8 @@
 		up_read(&fmixer->card->controls_rwsem);
 		return;
 	}
-	uinfo = snd_kcalloc(sizeof(*uinfo), GFP_KERNEL);
-	uctl = snd_kcalloc(sizeof(*uctl), GFP_KERNEL);
+	uinfo = kcalloc(1, sizeof(*uinfo), GFP_KERNEL);
+	uctl = kcalloc(1, sizeof(*uctl), GFP_KERNEL);
 	if (uinfo == NULL || uctl == NULL)
 		goto __unalloc;
 	snd_runtime_check(!kctl->info(kctl, uinfo), goto __unalloc);
@@ -767,8 +774,8 @@
 	snd_ctl_elem_value_t *uctl;
 	int err, idx;
 	
-	uinfo = snd_kcalloc(sizeof(*uinfo), GFP_KERNEL);
-	uctl = snd_kcalloc(sizeof(*uctl), GFP_KERNEL);
+	uinfo = kcalloc(1, sizeof(*uinfo), GFP_KERNEL);
+	uctl = kcalloc(1, sizeof(*uctl), GFP_KERNEL);
 	if (uinfo == NULL || uctl == NULL) {
 		err = -ENOMEM;
 		goto __unlock;
@@ -814,8 +821,8 @@
 	int err;
 	unsigned int idx;
 
-	uinfo = snd_kcalloc(sizeof(*uinfo), GFP_KERNEL);
-	uctl = snd_kcalloc(sizeof(*uctl), GFP_KERNEL);
+	uinfo = kcalloc(1, sizeof(*uinfo), GFP_KERNEL);
+	uctl = kcalloc(1, sizeof(*uctl), GFP_KERNEL);
 	if (uinfo == NULL || uctl == NULL) {
 		err = -ENOMEM;
 		goto __unlock;
@@ -968,8 +975,10 @@
 		snd_ctl_elem_info_t uinfo;
 
 		memset(&uinfo, 0, sizeof(uinfo));
-		if (kctl->info(kctl, &uinfo))
+		if (kctl->info(kctl, &uinfo)) {
+			up_read(&mixer->card->controls_rwsem);
 			return 0;
+		}
 		strcpy(str, ptr->name);
 		if (!strcmp(str, "Master"))
 			strcpy(str, "Mix");
@@ -1060,7 +1069,7 @@
 static void snd_mixer_oss_proc_read(snd_info_entry_t *entry,
 				    snd_info_buffer_t * buffer)
 {
-	snd_mixer_oss_t *mixer = snd_magic_cast(snd_mixer_oss_t, entry->private_data, return);
+	snd_mixer_oss_t *mixer = entry->private_data;
 	int i;
 
 	down(&mixer->reg_mutex);
@@ -1084,7 +1093,7 @@
 static void snd_mixer_oss_proc_write(snd_info_entry_t *entry,
 				     snd_info_buffer_t * buffer)
 {
-	snd_mixer_oss_t *mixer = snd_magic_cast(snd_mixer_oss_t, entry->private_data, return);
+	snd_mixer_oss_t *mixer = entry->private_data;
 	char line[128], str[32], idxstr[16], *cptr;
 	int ch, idx;
 	struct snd_mixer_oss_assign_table *tbl;
@@ -1210,7 +1219,7 @@
 	};
 	unsigned int idx;
 	
-	for (idx = 0; idx < sizeof(table) / sizeof(struct snd_mixer_oss_assign_table); idx++)
+	for (idx = 0; idx < ARRAY_SIZE(table); idx++)
 		snd_mixer_oss_build_input(mixer, &table[idx], 0, 0);
 	if (mixer->mask_recsrc) {
 		mixer->get_recsrc = snd_mixer_oss_get_recsrc2;
@@ -1224,7 +1233,7 @@
 
 static int snd_mixer_oss_free1(void *private)
 {
-	snd_mixer_oss_t *mixer = snd_magic_cast(snd_mixer_oss_t, private, return -ENXIO);
+	snd_mixer_oss_t *mixer = private;
 	snd_card_t * card;
 	int idx;
  
@@ -1237,7 +1246,7 @@
 		if (chn->private_free)
 			chn->private_free(chn);
 	}
-	snd_magic_kfree(mixer);
+	kfree(mixer);
 	return 0;
 }
 
@@ -1249,7 +1258,7 @@
 		char name[128];
 		int idx, err;
 
-		mixer = snd_magic_kcalloc(snd_mixer_oss_t, sizeof(snd_mixer_oss_t), GFP_KERNEL);
+		mixer = kcalloc(2, sizeof(*mixer), GFP_KERNEL);
 		if (mixer == NULL)
 			return -ENOMEM;
 		init_MUTEX(&mixer->reg_mutex);
@@ -1259,7 +1268,7 @@
 						   &snd_mixer_oss_reg,
 						   name)) < 0) {
 			snd_printk("unable to register OSS mixer device %i:%i\n", card->number, 0);
-			snd_magic_kfree(mixer);
+			kfree(mixer);
 			return err;
 		}
 		mixer->oss_dev_alloc = 1;
diff -Nru a/sound/core/oss/pcm_oss.c b/sound/core/oss/pcm_oss.c
--- a/sound/core/oss/pcm_oss.c	2004-10-18 14:56:50 -07:00
+++ b/sound/core/oss/pcm_oss.c	2004-10-18 14:56:50 -07:00
@@ -28,6 +28,7 @@
 
 #include <sound/driver.h>
 #include <linux/init.h>
+#include <linux/smp_lock.h>
 #include <linux/slab.h>
 #include <linux/time.h>
 #include <linux/vmalloc.h>
@@ -53,13 +54,10 @@
 MODULE_LICENSE("GPL");
 module_param_array(dsp_map, int, boot_devs, 0444);
 MODULE_PARM_DESC(dsp_map, "PCM device number assigned to 1st OSS device.");
-MODULE_PARM_SYNTAX(dsp_map, "default:0,skill:advanced");
 module_param_array(adsp_map, int, boot_devs, 0444);
 MODULE_PARM_DESC(adsp_map, "PCM device number assigned to 2nd OSS device.");
-MODULE_PARM_SYNTAX(adsp_map, "default:1,skill:advanced");
 module_param(nonblock_open, bool, 0644);
 MODULE_PARM_DESC(nonblock_open, "Don't block opening busy PCM devices.");
-MODULE_PARM_SYNTAX(nonblock_open, "default:0,skill:advanced");
 MODULE_ALIAS_SNDRV_MINOR(SNDRV_MINOR_OSS_PCM);
 MODULE_ALIAS_SNDRV_MINOR(SNDRV_MINOR_OSS_PCM1);
 
@@ -1177,10 +1175,11 @@
 	snd_pcm_substream_t *substream;
 	int err;
 	int direct;
-	snd_pcm_hw_params_t params;
+	snd_pcm_hw_params_t *params;
 	unsigned int formats = 0;
 	snd_mask_t format_mask;
 	int fmt;
+
 	if ((err = snd_pcm_oss_get_active_substream(pcm_oss_file, &substream)) < 0)
 		return err;
 	if (atomic_read(&substream->runtime->mmap_count)) {
@@ -1194,10 +1193,14 @@
 		       AFMT_S16_LE | AFMT_S16_BE |
 		       AFMT_S8 | AFMT_U16_LE |
 		       AFMT_U16_BE;
-	_snd_pcm_hw_params_any(&params);
-	err = snd_pcm_hw_refine(substream, &params);
+	params = kmalloc(sizeof(*params), GFP_KERNEL);
+	if (!params)
+		return -ENOMEM;
+	_snd_pcm_hw_params_any(params);
+	err = snd_pcm_hw_refine(substream, params);
+	format_mask = *hw_param_mask(params, SNDRV_PCM_HW_PARAM_FORMAT); 
+	kfree(params);
 	snd_assert(err >= 0, return err);
-	format_mask = *hw_param_mask(&params, SNDRV_PCM_HW_PARAM_FORMAT); 
 	for (fmt = 0; fmt < 32; ++fmt) {
 		if (snd_mask_test(&format_mask, fmt)) {
 			int f = snd_pcm_oss_format_to(fmt);
@@ -1693,7 +1696,7 @@
 		snd_pcm_oss_release_substream(substream);
 		snd_pcm_release_substream(substream);
 	}
-	snd_magic_kfree(pcm_oss_file);
+	kfree(pcm_oss_file);
 	return 0;
 }
 
@@ -1712,7 +1715,7 @@
 	snd_assert(rpcm_oss_file != NULL, return -EINVAL);
 	*rpcm_oss_file = NULL;
 
-	pcm_oss_file = snd_magic_kcalloc(snd_pcm_oss_file_t, 0, GFP_KERNEL);
+	pcm_oss_file = kcalloc(1, sizeof(*pcm_oss_file), GFP_KERNEL);
 	if (pcm_oss_file == NULL)
 		return -ENOMEM;
 
@@ -1892,7 +1895,7 @@
 	snd_pcm_substream_t *substream;
 	snd_pcm_oss_file_t *pcm_oss_file;
 
-	pcm_oss_file = snd_magic_cast(snd_pcm_oss_file_t, file->private_data, return -ENXIO);
+	pcm_oss_file = file->private_data;
 	substream = pcm_oss_file->streams[SNDRV_PCM_STREAM_PLAYBACK];
 	if (substream == NULL)
 		substream = pcm_oss_file->streams[SNDRV_PCM_STREAM_CAPTURE];
@@ -1908,14 +1911,14 @@
 	return 0;
 }
 
-static int snd_pcm_oss_ioctl(struct inode *inode, struct file *file,
-                             unsigned int cmd, unsigned long arg)
+static inline int _snd_pcm_oss_ioctl(struct inode *inode, struct file *file,
+				     unsigned int cmd, unsigned long arg)
 {
 	snd_pcm_oss_file_t *pcm_oss_file;
 	int __user *p = (int __user *)arg;
 	int res;
 
-	pcm_oss_file = snd_magic_cast(snd_pcm_oss_file_t, file->private_data, return -ENXIO);
+	pcm_oss_file = file->private_data;
 	if (cmd == OSS_GETVERSION)
 		return put_user(SNDRV_OSS_VERSION, p);
 	if (cmd == OSS_ALSAEMULVER)
@@ -2068,12 +2071,23 @@
 	return -EINVAL;
 }
 
+/* FIXME: need to unlock BKL to allow preemption */
+static int snd_pcm_oss_ioctl(struct inode *inode, struct file *file,
+			     unsigned int cmd, unsigned long arg)
+{
+	int err;
+	unlock_kernel();
+	err = _snd_pcm_oss_ioctl(inode, file, cmd, arg);
+	lock_kernel();
+	return err;
+}
+
 static ssize_t snd_pcm_oss_read(struct file *file, char __user *buf, size_t count, loff_t *offset)
 {
 	snd_pcm_oss_file_t *pcm_oss_file;
 	snd_pcm_substream_t *substream;
 
-	pcm_oss_file = snd_magic_cast(snd_pcm_oss_file_t, file->private_data, return -ENXIO);
+	pcm_oss_file = file->private_data;
 	substream = pcm_oss_file->streams[SNDRV_PCM_STREAM_CAPTURE];
 	if (substream == NULL)
 		return -ENXIO;
@@ -2094,7 +2108,7 @@
 	snd_pcm_substream_t *substream;
 	long result;
 
-	pcm_oss_file = snd_magic_cast(snd_pcm_oss_file_t, file->private_data, return -ENXIO);
+	pcm_oss_file = file->private_data;
 	substream = pcm_oss_file->streams[SNDRV_PCM_STREAM_PLAYBACK];
 	if (substream == NULL)
 		return -ENXIO;
@@ -2131,7 +2145,7 @@
 	unsigned int mask;
 	snd_pcm_substream_t *psubstream = NULL, *csubstream = NULL;
 	
-	pcm_oss_file = snd_magic_cast(snd_pcm_oss_file_t, file->private_data, return 0);
+	pcm_oss_file = file->private_data;
 
 	psubstream = pcm_oss_file->streams[SNDRV_PCM_STREAM_PLAYBACK];
 	csubstream = pcm_oss_file->streams[SNDRV_PCM_STREAM_CAPTURE];
@@ -2178,7 +2192,7 @@
 #ifdef OSS_DEBUG
 	printk("pcm_oss: mmap begin\n");
 #endif
-	pcm_oss_file = snd_magic_cast(snd_pcm_oss_file_t, file->private_data, return -ENXIO);
+	pcm_oss_file = file->private_data;
 	switch ((area->vm_flags & (VM_READ | VM_WRITE))) {
 	case VM_READ | VM_WRITE:
 		substream = pcm_oss_file->streams[SNDRV_PCM_STREAM_PLAYBACK];
@@ -2280,7 +2294,7 @@
 				   snd_info_buffer_t * buffer)
 {
 	snd_pcm_str_t *pstr = (snd_pcm_str_t *)entry->private_data;
-	char line[512], str[32], task_name[32], *ptr;
+	char line[256], str[32], task_name[32], *ptr;
 	int idx1;
 	snd_pcm_oss_setup_t *setup, *setup1, template;
 
diff -Nru a/sound/core/oss/pcm_plugin.c b/sound/core/oss/pcm_plugin.c
--- a/sound/core/oss/pcm_plugin.c	2004-10-18 14:56:27 -07:00
+++ b/sound/core/oss/pcm_plugin.c	2004-10-18 14:56:27 -07:00
@@ -172,7 +172,7 @@
 	
 	snd_assert(plug != NULL, return -ENXIO);
 	snd_assert(src_format != NULL && dst_format != NULL, return -ENXIO);
-	plugin = (snd_pcm_plugin_t *)snd_kcalloc(sizeof(*plugin) + extra, GFP_KERNEL);
+	plugin = kcalloc(1, sizeof(*plugin) + extra, GFP_KERNEL);
 	if (plugin == NULL)
 		return -ENOMEM;
 	plugin->name = name;
@@ -189,7 +189,7 @@
 		channels = src_format->channels;
 	else
 		channels = dst_format->channels;
-	plugin->buf_channels = snd_kcalloc(channels * sizeof(*plugin->buf_channels), GFP_KERNEL);
+	plugin->buf_channels = kcalloc(channels, sizeof(*plugin->buf_channels), GFP_KERNEL);
 	if (plugin->buf_channels == NULL) {
 		snd_pcm_plugin_free(plugin);
 		return -ENOMEM;
@@ -370,7 +370,7 @@
 		unsigned int i;
 		switch (format) {
 		case SNDRV_PCM_FORMAT_MU_LAW:
-			for (i = 0; i < sizeof(preferred_formats) / sizeof(preferred_formats[0]); ++i) {
+			for (i = 0; i < ARRAY_SIZE(preferred_formats); ++i) {
 				int format1 = preferred_formats[i];
 				if (snd_mask_test(format_mask, format1))
 					return format1;
@@ -468,7 +468,7 @@
 	if (srcformat.channels > dstformat.channels) {
 		int sv = srcformat.channels;
 		int dv = dstformat.channels;
-		route_ttable_entry_t *ttable = snd_kcalloc(dv*sv*sizeof(*ttable), GFP_KERNEL);
+		route_ttable_entry_t *ttable = kcalloc(dv * sv, sizeof(*ttable), GFP_KERNEL);
 		if (ttable == NULL)
 			return -ENOMEM;
 #if 1
@@ -531,7 +531,7 @@
 	if (srcformat.channels < dstformat.channels) {
 		int sv = srcformat.channels;
 		int dv = dstformat.channels;
-		route_ttable_entry_t *ttable = snd_kcalloc(dv * sv * sizeof(*ttable), GFP_KERNEL);
+		route_ttable_entry_t *ttable = kcalloc(dv * sv, sizeof(*ttable), GFP_KERNEL);
 		if (ttable == NULL)
 			return -ENOMEM;
 #if 0
@@ -846,41 +846,31 @@
 			 size_t samples, int format)
 {
 	/* FIXME: sub byte resolution and odd dst_offset */
-	char *dst;
+	unsigned char *dst;
 	unsigned int dst_step;
 	int width;
-	u_int64_t silence;
+	const unsigned char *silence;
 	if (!dst_area->addr)
 		return 0;
 	dst = dst_area->addr + (dst_area->first + dst_area->step * dst_offset) / 8;
 	width = snd_pcm_format_physical_width(format);
+	if (width <= 0)
+		return -EINVAL;
+	if (dst_area->step == (unsigned int) width && width >= 8)
+		return snd_pcm_format_set_silence(format, dst, samples);
 	silence = snd_pcm_format_silence_64(format);
-	if (dst_area->step == (unsigned int) width) {
-		size_t dwords = samples * width / 64;
-		u_int64_t *dst64 = (u_int64_t *)dst;
-
-		samples -= dwords * 64 / width;
-		while (dwords-- > 0)
-			*dst64++ = silence;
-		if (samples == 0)
-			return 0;
-		dst = (char *)dst64;
-	}
+	if (! silence)
+		return -EINVAL;
 	dst_step = dst_area->step / 8;
-	switch (width) {
-	case 4: {
-		u_int8_t s0 = silence & 0xf0;
-		u_int8_t s1 = silence & 0x0f;
+	if (width == 4) {
+		/* Ima ADPCM */
 		int dstbit = dst_area->first % 8;
 		int dstbit_step = dst_area->step % 8;
 		while (samples-- > 0) {
-			if (dstbit) {
+			if (dstbit)
 				*dst &= 0xf0;
-				*dst |= s1;
-			} else {
+			else
 				*dst &= 0x0f;
-				*dst |= s0;
-			}
 			dst += dst_step;
 			dstbit += dstbit_step;
 			if (dstbit == 8) {
@@ -888,41 +878,12 @@
 				dstbit = 0;
 			}
 		}
-		break;
-	}
-	case 8: {
-		u_int8_t sil = silence;
-		while (samples-- > 0) {
-			*dst = sil;
-			dst += dst_step;
-		}
-		break;
-	}
-	case 16: {
-		u_int16_t sil = silence;
-		while (samples-- > 0) {
-			*(u_int16_t*)dst = sil;
-			dst += dst_step;
-		}
-		break;
-	}
-	case 32: {
-		u_int32_t sil = silence;
-		while (samples-- > 0) {
-			*(u_int32_t*)dst = sil;
-			dst += dst_step;
-		}
-		break;
-	}
-	case 64: {
+	} else {
+		width /= 8;
 		while (samples-- > 0) {
-			*(u_int64_t*)dst = silence;
+			memcpy(dst, silence, width);
 			dst += dst_step;
 		}
-		break;
-	}
-	default:
-		snd_BUG();
 	}
 	return 0;
 }
@@ -942,18 +903,18 @@
 	if (!dst_area->addr)
 		return 0;
 	width = snd_pcm_format_physical_width(format);
+	if (width <= 0)
+		return -EINVAL;
 	if (src_area->step == (unsigned int) width &&
-	    dst_area->step == (unsigned int) width) {
+	    dst_area->step == (unsigned int) width && width >= 8) {
 		size_t bytes = samples * width / 8;
-		samples -= bytes * 8 / width;
 		memcpy(dst, src, bytes);
-		if (samples == 0)
-			return 0;
+		return 0;
 	}
 	src_step = src_area->step / 8;
 	dst_step = dst_area->step / 8;
-	switch (width) {
-	case 4: {
+	if (width == 4) {
+		/* Ima ADPCM */
 		int srcbit = src_area->first % 8;
 		int srcbit_step = src_area->step % 8;
 		int dstbit = dst_area->first % 8;
@@ -963,12 +924,11 @@
 			if (srcbit)
 				srcval = *src & 0x0f;
 			else
-				srcval = *src & 0xf0;
+				srcval = (*src & 0xf0) >> 4;
 			if (dstbit)
-				*dst &= 0xf0;
+				*dst = (*dst & 0xf0) | srcval;
 			else
-				*dst &= 0x0f;
-			*dst |= srcval;
+				*dst = (*dst & 0x0f) | (srcval << 4);
 			src += src_step;
 			srcbit += srcbit_step;
 			if (srcbit == 8) {
@@ -982,42 +942,13 @@
 				dstbit = 0;
 			}
 		}
-		break;
-	}
-	case 8: {
-		while (samples-- > 0) {
-			*dst = *src;
-			src += src_step;
-			dst += dst_step;
-		}
-		break;
-	}
-	case 16: {
-		while (samples-- > 0) {
-			*(u_int16_t*)dst = *(u_int16_t*)src;
-			src += src_step;
-			dst += dst_step;
-		}
-		break;
-	}
-	case 32: {
-		while (samples-- > 0) {
-			*(u_int32_t*)dst = *(u_int32_t*)src;
-			src += src_step;
-			dst += dst_step;
-		}
-		break;
-	}
-	case 64: {
+	} else {
+		width /= 8;
 		while (samples-- > 0) {
-			*(u_int64_t*)dst = *(u_int64_t*)src;
+			memcpy(dst, src, width);
 			src += src_step;
 			dst += dst_step;
 		}
-		break;
-	}
-	default:
-		snd_BUG();
 	}
 	return 0;
 }
diff -Nru a/sound/core/oss/pcm_plugin.h b/sound/core/oss/pcm_plugin.h
--- a/sound/core/oss/pcm_plugin.h	2004-10-18 14:56:49 -07:00
+++ b/sound/core/oss/pcm_plugin.h	2004-10-18 14:56:49 -07:00
@@ -35,7 +35,7 @@
 
 static inline bitset_t *bitset_alloc(int nbits)
 {
-	return snd_kcalloc(bitset_size(nbits) * sizeof(bitset_t), GFP_KERNEL);
+	return kcalloc(bitset_size(nbits), sizeof(bitset_t), GFP_KERNEL);
 }
 	
 static inline void bitset_set(bitset_t *bitmap, unsigned int pos)
diff -Nru a/sound/core/oss/route.c b/sound/core/oss/route.c
--- a/sound/core/oss/route.c	2004-10-18 14:57:03 -07:00
+++ b/sound/core/oss/route.c	2004-10-18 14:57:03 -07:00
@@ -458,7 +458,7 @@
 			dptr->func = route_to_channel;
 		if (nsrcs > 0) {
                         int srcidx;
-			dptr->srcs = snd_kcalloc(nsrcs * sizeof(*srcs), GFP_KERNEL);
+			dptr->srcs = kcalloc(nsrcs, sizeof(*srcs), GFP_KERNEL);
                         for(srcidx = 0; srcidx < nsrcs; srcidx++)
 				dptr->srcs[srcidx] = srcs[srcidx];
 		} else
diff -Nru a/sound/core/pcm.c b/sound/core/pcm.c
--- a/sound/core/pcm.c	2004-10-18 14:57:05 -07:00
+++ b/sound/core/pcm.c	2004-10-18 14:57:05 -07:00
@@ -585,7 +585,7 @@
 	}
 	prev = NULL;
 	for (idx = 0, prev = NULL; idx < substream_count; idx++) {
-		substream = snd_magic_kcalloc(snd_pcm_substream_t, 0, GFP_KERNEL);
+		substream = kcalloc(1, sizeof(*substream), GFP_KERNEL);
 		if (substream == NULL)
 			return -ENOMEM;
 		substream->pcm = pcm;
@@ -600,7 +600,7 @@
 			prev->next = substream;
 		err = snd_pcm_substream_proc_init(substream);
 		if (err < 0) {
-			snd_magic_kfree(substream);
+			kfree(substream);
 			return err;
 		}
 		substream->group = &substream->self_group;
@@ -645,7 +645,7 @@
 	snd_assert(rpcm != NULL, return -EINVAL);
 	*rpcm = NULL;
 	snd_assert(card != NULL, return -ENXIO);
-	pcm = snd_magic_kcalloc(snd_pcm_t, 0, GFP_KERNEL);
+	pcm = kcalloc(1, sizeof(*pcm), GFP_KERNEL);
 	if (pcm == NULL)
 		return -ENOMEM;
 	pcm->card = card;
@@ -681,7 +681,7 @@
 	while (substream) {
 		substream_next = substream->next;
 		snd_pcm_substream_proc_done(substream);
-		snd_magic_kfree(substream);
+		kfree(substream);
 		substream = substream_next;
 	}
 	snd_pcm_stream_proc_done(pstr);
@@ -702,13 +702,13 @@
 	snd_pcm_lib_preallocate_free_for_all(pcm);
 	snd_pcm_free_stream(&pcm->streams[SNDRV_PCM_STREAM_PLAYBACK]);
 	snd_pcm_free_stream(&pcm->streams[SNDRV_PCM_STREAM_CAPTURE]);
-	snd_magic_kfree(pcm);
+	kfree(pcm);
 	return 0;
 }
 
 static int snd_pcm_dev_free(snd_device_t *device)
 {
-	snd_pcm_t *pcm = snd_magic_cast(snd_pcm_t, device->device_data, return -ENXIO);
+	snd_pcm_t *pcm = device->device_data;
 	return snd_pcm_free(pcm);
 }
 
@@ -783,7 +783,7 @@
 	if (substream == NULL)
 		return -EAGAIN;
 
-	runtime = snd_kcalloc(sizeof(snd_pcm_runtime_t), GFP_KERNEL);
+	runtime = kcalloc(1, sizeof(*runtime), GFP_KERNEL);
 	if (runtime == NULL)
 		return -ENOMEM;
 
@@ -843,7 +843,7 @@
 	snd_pcm_substream_t *substream;
 	struct list_head *list;
 	char str[16];
-	snd_pcm_t *pcm = snd_magic_cast(snd_pcm_t, device->device_data, return -ENXIO);
+	snd_pcm_t *pcm = device->device_data;
 
 	snd_assert(pcm != NULL && device != NULL, return -ENXIO);
 	down(&register_mutex);
@@ -888,7 +888,7 @@
 
 static int snd_pcm_dev_disconnect(snd_device_t *device)
 {
-	snd_pcm_t *pcm = snd_magic_cast(snd_pcm_t, device->device_data, return -ENXIO);
+	snd_pcm_t *pcm = device->device_data;
 	struct list_head *list;
 	snd_pcm_substream_t *substream;
 	int idx, cidx;
@@ -914,7 +914,7 @@
 	int idx, cidx, devtype;
 	snd_pcm_substream_t *substream;
 	struct list_head *list;
-	snd_pcm_t *pcm = snd_magic_cast(snd_pcm_t, device->device_data, return -ENXIO);
+	snd_pcm_t *pcm = device->device_data;
 
 	snd_assert(pcm != NULL, return -ENXIO);
 	down(&register_mutex);
@@ -1050,6 +1050,9 @@
 EXPORT_SYMBOL(snd_pcm_playback_poll);
 EXPORT_SYMBOL(snd_pcm_capture_poll);
 EXPORT_SYMBOL(snd_pcm_mmap_data);
+#if SNDRV_PCM_INFO_MMAP_IOMEM
+EXPORT_SYMBOL(snd_pcm_lib_mmap_iomem);
+#endif
  /* pcm_misc.c */
 EXPORT_SYMBOL(snd_pcm_format_signed);
 EXPORT_SYMBOL(snd_pcm_format_unsigned);
diff -Nru a/sound/core/pcm_lib.c b/sound/core/pcm_lib.c
--- a/sound/core/pcm_lib.c	2004-10-18 14:56:29 -07:00
+++ b/sound/core/pcm_lib.c	2004-10-18 14:56:29 -07:00
@@ -128,12 +128,29 @@
 	}
 }
 
+static void xrun(snd_pcm_substream_t *substream)
+{
+	snd_pcm_stop(substream, SNDRV_PCM_STATE_XRUN);
+#ifdef CONFIG_SND_DEBUG
+	if (substream->pstr->xrun_debug) {
+		snd_printd(KERN_DEBUG "XRUN: pcmC%dD%d%c\n",
+			   substream->pcm->card->number,
+			   substream->pcm->device,
+			   substream->stream ? 'c' : 'p');
+		if (substream->pstr->xrun_debug > 1)
+			dump_stack();
+	}
+#endif
+}
+
 static inline snd_pcm_uframes_t snd_pcm_update_hw_ptr_pos(snd_pcm_substream_t *substream,
 							  snd_pcm_runtime_t *runtime)
 {
 	snd_pcm_uframes_t pos;
 
 	pos = substream->ops->pointer(substream);
+	if (pos == SNDRV_PCM_POS_XRUN)
+		return pos; /* XRUN */
 	if (runtime->tstamp_mode & SNDRV_PCM_TSTAMP_MMAP)
 		snd_timestamp_now((snd_timestamp_t*)&runtime->status->tstamp, runtime->tstamp_timespec);
 #ifdef CONFIG_SND_DEBUG
@@ -158,19 +175,10 @@
 	if (avail > runtime->avail_max)
 		runtime->avail_max = avail;
 	if (avail >= runtime->stop_threshold) {
-		snd_pcm_stop(substream,
-			     runtime->status->state == SNDRV_PCM_STATE_DRAINING ?
-			     SNDRV_PCM_STATE_SETUP : SNDRV_PCM_STATE_XRUN);
-#ifdef CONFIG_SND_DEBUG
-		if (substream->pstr->xrun_debug) {
-			snd_printd(KERN_DEBUG "XRUN: pcmC%dD%d%c\n",
-				   substream->pcm->card->number,
-				   substream->pcm->device,
-				   substream->stream ? 'c' : 'p');
-			if (substream->pstr->xrun_debug > 1)
-				dump_stack();
-		}
-#endif
+		if (substream->runtime->status->state == SNDRV_PCM_STATE_DRAINING)
+			snd_pcm_stop(substream, SNDRV_PCM_STATE_SETUP);
+		else
+			xrun(substream);
 		return -EPIPE;
 	}
 	if (avail >= runtime->control->avail_min)
@@ -186,6 +194,10 @@
 	snd_pcm_sframes_t delta;
 
 	pos = snd_pcm_update_hw_ptr_pos(substream, runtime);
+	if (pos == SNDRV_PCM_POS_XRUN) {
+		xrun(substream);
+		return -EPIPE;
+	}
 	if (runtime->period_size == runtime->buffer_size)
 		goto __next_buf;
 	new_hw_ptr = runtime->hw_ptr_base + pos;
@@ -230,6 +242,10 @@
 
 	old_hw_ptr = runtime->status->hw_ptr;
 	pos = snd_pcm_update_hw_ptr_pos(substream, runtime);
+	if (pos == SNDRV_PCM_POS_XRUN) {
+		xrun(substream);
+		return -EPIPE;
+	}
 	new_hw_ptr = runtime->hw_ptr_base + pos;
 
 	delta = old_hw_ptr - new_hw_ptr;
@@ -887,22 +903,18 @@
 	va_list args;
 	va_start(args, dep);
 	if (constrs->rules_num >= constrs->rules_all) {
-		snd_pcm_hw_rule_t *old = constrs->rules;
-		if (constrs->rules_all == 0)
-			constrs->rules_all = 32;
-		else {
-			old = constrs->rules;
-			constrs->rules_all += 10;
-		}
-		constrs->rules = snd_kcalloc(constrs->rules_all * sizeof(*c),
-					     GFP_KERNEL);
-		if (!constrs->rules)
+		snd_pcm_hw_rule_t *new;
+		unsigned int new_rules = constrs->rules_all + 16;
+		new = kcalloc(new_rules, sizeof(*c), GFP_KERNEL);
+		if (!new)
 			return -ENOMEM;
-		if (old) {
-			memcpy(constrs->rules, old,
+		if (constrs->rules) {
+			memcpy(new, constrs->rules,
 			       constrs->rules_num * sizeof(*c));
-			kfree(old);
+			kfree(constrs->rules);
 		}
+		constrs->rules = new;
+		constrs->rules_all = new_rules;
 	}
 	c = &constrs->rules[constrs->rules_num];
 	c->cond = cond;
@@ -911,7 +923,7 @@
 	c->private = private;
 	k = 0;
 	while (1) {
-		snd_assert(k < sizeof(c->deps) / sizeof(c->deps[0]), return -EINVAL);
+		snd_assert(k < ARRAY_SIZE(c->deps), return -EINVAL);
 		c->deps[k++] = dep;
 		if (dep < 0)
 			break;
@@ -1109,7 +1121,7 @@
 		1<<24, 1<<25, 1<<26, 1<<27, 1<<28, 1<<29, 1<<30
 	};
 	return snd_interval_list(hw_param_interval(params, rule->var),
-				 sizeof(pow2_sizes)/sizeof(int), pow2_sizes, 0);
+				 ARRAY_SIZE(pow2_sizes), pow2_sizes, 0);
 }		
 
 /**
@@ -1769,12 +1781,14 @@
 				   void *arg)
 {
 	snd_pcm_runtime_t *runtime = substream->runtime;
+	unsigned long flags;
+	snd_pcm_stream_lock_irqsave(substream, flags);
 	if (snd_pcm_running(substream) &&
-	    snd_pcm_update_hw_ptr(substream) >= 0) {
+	    snd_pcm_update_hw_ptr(substream) >= 0)
 		runtime->status->hw_ptr %= runtime->buffer_size;
-		return 0;
-	}
-	runtime->status->hw_ptr = 0;
+	else
+		runtime->status->hw_ptr = 0;
+	snd_pcm_stream_unlock_irqrestore(substream, flags);
 	return 0;
 }
 
diff -Nru a/sound/core/pcm_memory.c b/sound/core/pcm_memory.c
--- a/sound/core/pcm_memory.c	2004-10-18 14:56:48 -07:00
+++ b/sound/core/pcm_memory.c	2004-10-18 14:56:48 -07:00
@@ -32,12 +32,10 @@
 static int preallocate_dma = 1;
 module_param(preallocate_dma, int, 0444);
 MODULE_PARM_DESC(preallocate_dma, "Preallocate DMA memory when the PCM devices are initialized.");
-MODULE_PARM_SYNTAX(preallocate_dma, SNDRV_BOOLEAN_TRUE_DESC);
 
 static int maximum_substreams = 4;
 module_param(maximum_substreams, int, 0444);
 MODULE_PARM_DESC(maximum_substreams, "Maximum substreams with preallocated DMA memory.");
-MODULE_PARM_SYNTAX(maximum_substreams, SNDRV_BOOLEAN_TRUE_DESC);
 
 const static size_t snd_minimum_buffer = 16384;
 
@@ -56,26 +54,21 @@
 	snd_assert(size > 0, return -EINVAL);
 
 	/* already reserved? */
-	if (snd_dma_get_reserved(&substream->dma_device, dmab) > 0) {
+	if (snd_dma_get_reserved_buf(dmab, substream->dma_buf_id) > 0) {
 		if (dmab->bytes >= size)
 			return 0; /* yes */
-		/* no, reset the reserved block */
-		/* if we can find bigger pages below, this block will be
-		 * automatically removed in snd_dma_set_reserved().
-		 */
-		snd_dma_free_reserved(&substream->dma_device);
+		/* no, free the reserved block */
+		snd_dma_free_pages(dmab);
 		dmab->bytes = 0;
 	}
 
 	do {
-		if ((err = snd_dma_alloc_pages(&substream->dma_device, size, dmab)) < 0) {
+		if ((err = snd_dma_alloc_pages(dmab->dev.type, dmab->dev.dev,
+					       size, dmab)) < 0) {
 			if (err != -ENOMEM)
 				return err; /* fatal error */
-		} else {
-			/* remember this one */
-			snd_dma_set_reserved(&substream->dma_device, dmab);
+		} else
 			return 0;
-		}
 		size >>= 1;
 	} while (size >= snd_minimum_buffer);
 	dmab->bytes = 0; /* tell error */
@@ -89,7 +82,10 @@
 {
 	if (substream->dma_buffer.area == NULL)
 		return;
-	snd_dma_free_reserved(&substream->dma_device);
+	if (substream->dma_buf_id)
+		snd_dma_reserve_buf(&substream->dma_buffer, substream->dma_buf_id);
+	else
+		snd_dma_free_pages(&substream->dma_buffer);
 	substream->dma_buffer.area = NULL;
 }
 
@@ -108,7 +104,6 @@
 		snd_info_unregister(substream->proc_prealloc_entry);
 		substream->proc_prealloc_entry = NULL;
 	}
-	substream->dma_device.type = SNDRV_DMA_TYPE_UNKNOWN;
 	return 0;
 }
 
@@ -170,18 +165,20 @@
 		if (substream->dma_buffer.bytes == size)
 			return;
 		memset(&new_dmab, 0, sizeof(new_dmab));
+		new_dmab.dev = substream->dma_buffer.dev;
 		if (size > 0) {
-
-			if (snd_dma_alloc_pages(&substream->dma_device, size, &new_dmab) < 0) {
+			if (snd_dma_alloc_pages(substream->dma_buffer.dev.type,
+						substream->dma_buffer.dev.dev,
+						size, &new_dmab) < 0) {
 				buffer->error = -ENOMEM;
 				return;
 			}
 			substream->buffer_bytes_max = size;
-			snd_dma_free_reserved(&substream->dma_device);
 		} else {
 			substream->buffer_bytes_max = UINT_MAX;
 		}
-		snd_dma_set_reserved(&substream->dma_device, &new_dmab);
+		if (substream->dma_buffer.area)
+			snd_dma_free_pages(&substream->dma_buffer);
 		substream->dma_buffer = new_dmab;
 	} else {
 		buffer->error = -EINVAL;
@@ -196,7 +193,6 @@
 {
 	snd_info_entry_t *entry;
 
-	memset(&substream->dma_buffer, 0, sizeof(substream->dma_buffer));
 	if (size > 0 && preallocate_dma && substream->number < maximum_substreams)
 		preallocate_pcm_pages(substream, size);
 
@@ -219,20 +215,6 @@
 }
 
 
-/*
- * set up the unique pcm id
- */
-static inline void setup_pcm_id(snd_pcm_substream_t *subs)
-{
-	if (! subs->dma_device.id) {
-		subs->dma_device.id = subs->pcm->device << 16 |
-			subs->stream << 8 | (subs->number + 1);
-		if (subs->dma_device.type == SNDRV_DMA_TYPE_CONTINUOUS ||
-		    subs->dma_device.dev == NULL)
-			subs->dma_device.id |= (subs->pcm->card->number + 1) << 24;
-	}
-}
-
 /**
  * snd_pcm_lib_preallocate_pages - pre-allocation for the given DMA type
  * @substream: the pcm substream instance
@@ -241,7 +223,12 @@
  * @size: the requested pre-allocation size in bytes
  * @max: the max. allowed pre-allocation size
  *
- * Do pre-allocation for the given DMA type.
+ * Do pre-allocation for the given DMA buffer type.
+ *
+ * When substream->dma_buf_id is set, the function tries to look for
+ * the reserved buffer, and the buffer is not freed but reserved at
+ * destruction time.  The dma_buf_id must be unique for all systems
+ * (in the same DMA buffer type) e.g. using snd_dma_pci_buf_id().
  *
  * Returns zero if successful, or a negative error code on failure.
  */
@@ -249,9 +236,8 @@
 				  int type, struct device *data,
 				  size_t size, size_t max)
 {
-	substream->dma_device.type = type;
-	substream->dma_device.dev = data;
-	setup_pcm_id(substream);
+	substream->dma_buffer.dev.type = type;
+	substream->dma_buffer.dev.dev = data;
 	return snd_pcm_lib_preallocate_pages1(substream, size, max);
 }
 
@@ -314,31 +300,38 @@
 int snd_pcm_lib_malloc_pages(snd_pcm_substream_t *substream, size_t size)
 {
 	snd_pcm_runtime_t *runtime;
-	struct snd_dma_buffer dmab;
+	struct snd_dma_buffer *dmab = NULL;
 
-	snd_assert(substream->dma_device.type != SNDRV_DMA_TYPE_UNKNOWN, return -EINVAL);
+	snd_assert(substream->dma_buffer.dev.type != SNDRV_DMA_TYPE_UNKNOWN, return -EINVAL);
 	snd_assert(substream != NULL, return -EINVAL);
 	runtime = substream->runtime;
-	snd_assert(runtime != NULL, return -EINVAL);	
+	snd_assert(runtime != NULL, return -EINVAL);
 
-	if (runtime->dma_area != NULL) {
+	if (runtime->dma_buffer_p) {
 		/* perphaps, we might free the large DMA memory region
 		   to save some space here, but the actual solution
 		   costs us less time */
-		if (runtime->dma_bytes >= size)
+		if (runtime->dma_buffer_p->bytes >= size) {
+			runtime->dma_bytes = size;
 			return 0;	/* ok, do not change */
+		}
 		snd_pcm_lib_free_pages(substream);
 	}
 	if (substream->dma_buffer.area != NULL && substream->dma_buffer.bytes >= size) {
-		dmab = substream->dma_buffer; /* use the pre-allocated buffer */
+		dmab = &substream->dma_buffer; /* use the pre-allocated buffer */
 	} else {
-		memset(&dmab, 0, sizeof(dmab)); /* allocate a new buffer */
-		if (snd_dma_alloc_pages(&substream->dma_device, size, &dmab) < 0)
+		dmab = kcalloc(1, sizeof(*dmab), GFP_KERNEL);
+		if (! dmab)
+			return -ENOMEM;
+		dmab->dev = substream->dma_buffer.dev;
+		if (snd_dma_alloc_pages(substream->dma_buffer.dev.type,
+					substream->dma_buffer.dev.dev,
+					size, dmab) < 0) {
+			kfree(dmab);
 			return -ENOMEM;
+		}
 	}
-	runtime->dma_area = dmab.area;
-	runtime->dma_addr = dmab.addr;
-	runtime->dma_private = dmab.private_data;
+	snd_pcm_set_runtime_buffer(substream, dmab);
 	runtime->dma_bytes = size;
 	return 1;			/* area was changed */
 }
@@ -360,34 +353,11 @@
 	snd_assert(runtime != NULL, return -EINVAL);
 	if (runtime->dma_area == NULL)
 		return 0;
-	if (runtime->dma_area != substream->dma_buffer.area) {
+	if (runtime->dma_buffer_p != &substream->dma_buffer) {
 		/* it's a newly allocated buffer.  release it now. */
-		struct snd_dma_buffer dmab;
-		memset(&dmab, 0, sizeof(dmab));
-		dmab.area = runtime->dma_area;
-		dmab.addr = runtime->dma_addr;
-		dmab.bytes = runtime->dma_bytes;
-		dmab.private_data = runtime->dma_private;
-		snd_dma_free_pages(&substream->dma_device, &dmab);
+		snd_dma_free_pages(runtime->dma_buffer_p);
+		kfree(runtime->dma_buffer_p);
 	}
-	runtime->dma_area = NULL;
-	runtime->dma_addr = 0UL;
-	runtime->dma_bytes = 0;
-	runtime->dma_private = NULL;
+	snd_pcm_set_runtime_buffer(substream, NULL);
 	return 0;
 }
-
-#ifndef MODULE
-
-/* format is: snd-pcm=preallocate_dma,maximum_substreams */
-
-static int __init alsa_pcm_setup(char *str)
-{
-	(void)(get_option(&str,&preallocate_dma) == 2 &&
-	       get_option(&str,&maximum_substreams) == 2);
-	return 1;
-}
-
-__setup("snd-pcm=", alsa_pcm_setup);
-
-#endif /* ifndef MODULE */
diff -Nru a/sound/core/pcm_misc.c b/sound/core/pcm_misc.c
--- a/sound/core/pcm_misc.c	2004-10-18 14:56:49 -07:00
+++ b/sound/core/pcm_misc.c	2004-10-18 14:56:49 -07:00
@@ -23,12 +23,169 @@
 #include <linux/time.h>
 #include <sound/core.h>
 #include <sound/pcm.h>
-#define bswap_16 swab16
-#define bswap_32 swab32
-#define bswap_64 swab64
 #define SND_PCM_FORMAT_UNKNOWN (-1)
-#define snd_enum_to_int(v) (v)
-#define snd_int_to_enum(v) (v)
+
+struct pcm_format_data {
+	char width;	/* bit width */
+	char phys;	/* physical bit width */
+	char le;	/* 0 = big-endian, 1 = little-endian, -1 = others */
+	char signd;	/* 0 = unsigned, 1 = signed, -1 = others */
+	unsigned char silence[8];	/* silence data to fill */
+};
+
+static struct pcm_format_data pcm_formats[SNDRV_PCM_FORMAT_LAST+1] = {
+	[SNDRV_PCM_FORMAT_S8] = {
+		.width = 8, .phys = 8, .le = -1, .signd = 1,
+		.silence = {},
+	},
+	[SNDRV_PCM_FORMAT_U8] = {
+		.width = 8, .phys = 8, .le = -1, .signd = 0,
+		.silence = { 0x80 },
+	},
+	[SNDRV_PCM_FORMAT_S16_LE] = {
+		.width = 16, .phys = 16, .le = 1, .signd = 1,
+		.silence = {},
+	},
+	[SNDRV_PCM_FORMAT_S16_BE] = {
+		.width = 16, .phys = 16, .le = 0, .signd = 1,
+		.silence = {},
+	},
+	[SNDRV_PCM_FORMAT_U16_LE] = {
+		.width = 16, .phys = 16, .le = 1, .signd = 0,
+		.silence = { 0x00, 0x80 },
+	},
+	[SNDRV_PCM_FORMAT_U16_BE] = {
+		.width = 16, .phys = 16, .le = 0, .signd = 0,
+		.silence = { 0x80, 0x00 },
+	},
+	[SNDRV_PCM_FORMAT_S24_LE] = {
+		.width = 24, .phys = 32, .le = 1, .signd = 1,
+		.silence = {},
+	},
+	[SNDRV_PCM_FORMAT_S24_BE] = {
+		.width = 24, .phys = 32, .le = 0, .signd = 1,
+		.silence = {},
+	},
+	[SNDRV_PCM_FORMAT_U24_LE] = {
+		.width = 24, .phys = 32, .le = 1, .signd = 0,
+		.silence = { 0x00, 0x00, 0x80 },
+	},
+	[SNDRV_PCM_FORMAT_U24_BE] = {
+		.width = 24, .phys = 32, .le = 0, .signd = 0,
+		.silence = { 0x80, 0x00, 0x00 },
+	},
+	[SNDRV_PCM_FORMAT_S32_LE] = {
+		.width = 32, .phys = 32, .le = 1, .signd = 1,
+		.silence = {},
+	},
+	[SNDRV_PCM_FORMAT_S32_BE] = {
+		.width = 32, .phys = 32, .le = 0, .signd = 1,
+		.silence = {},
+	},
+	[SNDRV_PCM_FORMAT_U32_LE] = {
+		.width = 32, .phys = 32, .le = 1, .signd = 0,
+		.silence = { 0x00, 0x00, 0x00, 0x80 },
+	},
+	[SNDRV_PCM_FORMAT_U32_BE] = {
+		.width = 32, .phys = 32, .le = 0, .signd = 0,
+		.silence = { 0x80, 0x00, 0x00, 0x00 },
+	},
+	[SNDRV_PCM_FORMAT_FLOAT_LE] = {
+		.width = 32, .phys = 32, .le = 1, .signd = -1,
+		.silence = {},
+	},
+	[SNDRV_PCM_FORMAT_FLOAT_BE] = {
+		.width = 32, .phys = 32, .le = 0, .signd = -1,
+		.silence = {},
+	},
+	[SNDRV_PCM_FORMAT_FLOAT64_LE] = {
+		.width = 64, .phys = 64, .le = 1, .signd = -1,
+		.silence = {},
+	},
+	[SNDRV_PCM_FORMAT_FLOAT64_BE] = {
+		.width = 64, .phys = 64, .le = 0, .signd = -1,
+		.silence = {},
+	},
+	[SNDRV_PCM_FORMAT_IEC958_SUBFRAME_LE] = {
+		.width = 32, .phys = 32, .le = 1, .signd = -1,
+		.silence = {},
+	},
+	[SNDRV_PCM_FORMAT_IEC958_SUBFRAME_BE] = {
+		.width = 32, .phys = 32, .le = 0, .signd = -1,
+		.silence = {},
+	},
+	[SNDRV_PCM_FORMAT_MU_LAW] = {
+		.width = 8, .phys = 8, .le = -1, .signd = -1,
+		.silence = { 0x7f },
+	},
+	[SNDRV_PCM_FORMAT_A_LAW] = {
+		.width = 8, .phys = 8, .le = -1, .signd = -1,
+		.silence = { 0x55 },
+	},
+	[SNDRV_PCM_FORMAT_IMA_ADPCM] = {
+		.width = 4, .phys = 4, .le = -1, .signd = -1,
+		.silence = {},
+	},
+	/* FIXME: the following three formats are not defined properly yet */
+	[SNDRV_PCM_FORMAT_MPEG] = {
+		.le = -1, .signd = -1,
+	},
+	[SNDRV_PCM_FORMAT_GSM] = {
+		.le = -1, .signd = -1,
+	},
+	[SNDRV_PCM_FORMAT_SPECIAL] = {
+		.le = -1, .signd = -1,
+	},
+	[SNDRV_PCM_FORMAT_S24_3LE] = {
+		.width = 24, .phys = 24, .le = 1, .signd = 1,
+		.silence = {},
+	},
+	[SNDRV_PCM_FORMAT_S24_3BE] = {
+		.width = 24, .phys = 24, .le = 0, .signd = 1,
+		.silence = {},
+	},
+	[SNDRV_PCM_FORMAT_U24_3LE] = {
+		.width = 24, .phys = 24, .le = 1, .signd = 0,
+		.silence = { 0x00, 0x00, 0x80 },
+	},
+	[SNDRV_PCM_FORMAT_U24_3BE] = {
+		.width = 24, .phys = 24, .le = 0, .signd = 0,
+		.silence = { 0x80, 0x00, 0x00 },
+	},
+	[SNDRV_PCM_FORMAT_S20_3LE] = {
+		.width = 20, .phys = 24, .le = 1, .signd = 1,
+		.silence = {},
+	},
+	[SNDRV_PCM_FORMAT_S20_3BE] = {
+		.width = 20, .phys = 24, .le = 0, .signd = 1,
+		.silence = {},
+	},
+	[SNDRV_PCM_FORMAT_U20_3LE] = {
+		.width = 20, .phys = 24, .le = 1, .signd = 0,
+		.silence = { 0x00, 0x00, 0x08 },
+	},
+	[SNDRV_PCM_FORMAT_U20_3BE] = {
+		.width = 20, .phys = 24, .le = 0, .signd = 0,
+		.silence = { 0x08, 0x00, 0x00 },
+	},
+	[SNDRV_PCM_FORMAT_S18_3LE] = {
+		.width = 18, .phys = 24, .le = 1, .signd = 1,
+		.silence = {},
+	},
+	[SNDRV_PCM_FORMAT_S18_3BE] = {
+		.width = 18, .phys = 24, .le = 0, .signd = 1,
+		.silence = {},
+	},
+	[SNDRV_PCM_FORMAT_U18_3LE] = {
+		.width = 18, .phys = 24, .le = 1, .signd = 0,
+		.silence = { 0x00, 0x00, 0x02 },
+	},
+	[SNDRV_PCM_FORMAT_U18_3BE] = {
+		.width = 18, .phys = 24, .le = 0, .signd = 0,
+		.silence = { 0x02, 0x00, 0x00 },
+	},
+};
+
 
 /**
  * snd_pcm_format_signed - Check the PCM format is signed linear
@@ -39,38 +196,12 @@
  */
 int snd_pcm_format_signed(snd_pcm_format_t format)
 {
-	switch (snd_enum_to_int(format)) {
-	case SNDRV_PCM_FORMAT_S8:
-	case SNDRV_PCM_FORMAT_S16_LE:
-	case SNDRV_PCM_FORMAT_S16_BE:
-	case SNDRV_PCM_FORMAT_S24_LE:
-	case SNDRV_PCM_FORMAT_S24_BE:
-	case SNDRV_PCM_FORMAT_S32_LE:
-	case SNDRV_PCM_FORMAT_S32_BE:
-	case SNDRV_PCM_FORMAT_S24_3LE:
-	case SNDRV_PCM_FORMAT_S24_3BE:
-	case SNDRV_PCM_FORMAT_S20_3LE:
-	case SNDRV_PCM_FORMAT_S20_3BE:
-	case SNDRV_PCM_FORMAT_S18_3LE:
-	case SNDRV_PCM_FORMAT_S18_3BE:
-		return 1;
-	case SNDRV_PCM_FORMAT_U8:
-	case SNDRV_PCM_FORMAT_U16_LE:
-	case SNDRV_PCM_FORMAT_U16_BE:
-	case SNDRV_PCM_FORMAT_U24_LE:
-	case SNDRV_PCM_FORMAT_U24_BE:
-	case SNDRV_PCM_FORMAT_U32_LE:
-	case SNDRV_PCM_FORMAT_U32_BE:
-	case SNDRV_PCM_FORMAT_U24_3LE:
-	case SNDRV_PCM_FORMAT_U24_3BE:
-	case SNDRV_PCM_FORMAT_U20_3LE:
-	case SNDRV_PCM_FORMAT_U20_3BE:
-	case SNDRV_PCM_FORMAT_U18_3LE:
-	case SNDRV_PCM_FORMAT_U18_3BE:
-		return 0;
-	default:
+	int val;
+	if (format < 0 || format > SNDRV_PCM_FORMAT_LAST)
 		return -EINVAL;
-	}
+	if ((val = pcm_formats[format].signd) < 0)
+		return -EINVAL;
+	return val;
 }
 
 /**
@@ -110,42 +241,12 @@
  */
 int snd_pcm_format_little_endian(snd_pcm_format_t format)
 {
-	switch (snd_enum_to_int(format)) {
-	case SNDRV_PCM_FORMAT_S16_LE:
-	case SNDRV_PCM_FORMAT_U16_LE:
-	case SNDRV_PCM_FORMAT_S24_LE:
-	case SNDRV_PCM_FORMAT_U24_LE:
-	case SNDRV_PCM_FORMAT_S32_LE:
-	case SNDRV_PCM_FORMAT_U32_LE:
-	case SNDRV_PCM_FORMAT_FLOAT_LE:
-	case SNDRV_PCM_FORMAT_FLOAT64_LE:
-	case SNDRV_PCM_FORMAT_IEC958_SUBFRAME_LE:
-	case SNDRV_PCM_FORMAT_S24_3LE:
-	case SNDRV_PCM_FORMAT_S20_3LE:
-	case SNDRV_PCM_FORMAT_S18_3LE:
-	case SNDRV_PCM_FORMAT_U24_3LE:
-	case SNDRV_PCM_FORMAT_U20_3LE:
-	case SNDRV_PCM_FORMAT_U18_3LE:
-		return 1;
-	case SNDRV_PCM_FORMAT_S16_BE:
-	case SNDRV_PCM_FORMAT_U16_BE:
-	case SNDRV_PCM_FORMAT_S24_BE:
-	case SNDRV_PCM_FORMAT_U24_BE:
-	case SNDRV_PCM_FORMAT_S32_BE:
-	case SNDRV_PCM_FORMAT_U32_BE:
-	case SNDRV_PCM_FORMAT_FLOAT_BE:
-	case SNDRV_PCM_FORMAT_FLOAT64_BE:
-	case SNDRV_PCM_FORMAT_IEC958_SUBFRAME_BE:
-	case SNDRV_PCM_FORMAT_S24_3BE:
-	case SNDRV_PCM_FORMAT_S20_3BE:
-	case SNDRV_PCM_FORMAT_S18_3BE:
-	case SNDRV_PCM_FORMAT_U24_3BE:
-	case SNDRV_PCM_FORMAT_U20_3BE:
-	case SNDRV_PCM_FORMAT_U18_3BE:
-		return 0;
-	default:
+	int val;
+	if (format < 0 || format > SNDRV_PCM_FORMAT_LAST)
 		return -EINVAL;
-	}
+	if ((val = pcm_formats[format].le) < 0)
+		return -EINVAL;
+	return val;
 }
 
 /**
@@ -190,55 +291,12 @@
  */
 int snd_pcm_format_width(snd_pcm_format_t format)
 {
-	switch (snd_enum_to_int(format)) {
-	case SNDRV_PCM_FORMAT_S8:
-	case SNDRV_PCM_FORMAT_U8:
-		return 8;
-	case SNDRV_PCM_FORMAT_S16_LE:
-	case SNDRV_PCM_FORMAT_S16_BE:
-	case SNDRV_PCM_FORMAT_U16_LE:
-	case SNDRV_PCM_FORMAT_U16_BE:
-		return 16;
-	case SNDRV_PCM_FORMAT_S18_3LE:
-	case SNDRV_PCM_FORMAT_S18_3BE:
-	case SNDRV_PCM_FORMAT_U18_3LE:
-	case SNDRV_PCM_FORMAT_U18_3BE:
-		return 18;
-	case SNDRV_PCM_FORMAT_S20_3LE:
-	case SNDRV_PCM_FORMAT_S20_3BE:
-	case SNDRV_PCM_FORMAT_U20_3LE:
-	case SNDRV_PCM_FORMAT_U20_3BE:
-		return 20;
-	case SNDRV_PCM_FORMAT_S24_LE:
-	case SNDRV_PCM_FORMAT_S24_BE:
-	case SNDRV_PCM_FORMAT_U24_LE:
-	case SNDRV_PCM_FORMAT_U24_BE:
-	case SNDRV_PCM_FORMAT_S24_3LE:
-	case SNDRV_PCM_FORMAT_S24_3BE:
-	case SNDRV_PCM_FORMAT_U24_3LE:
-	case SNDRV_PCM_FORMAT_U24_3BE:
-		return 24;
-	case SNDRV_PCM_FORMAT_S32_LE:
-	case SNDRV_PCM_FORMAT_S32_BE:
-	case SNDRV_PCM_FORMAT_U32_LE:
-	case SNDRV_PCM_FORMAT_U32_BE:
-	case SNDRV_PCM_FORMAT_FLOAT_LE:
-	case SNDRV_PCM_FORMAT_FLOAT_BE:
-		return 32;
-	case SNDRV_PCM_FORMAT_FLOAT64_LE:
-	case SNDRV_PCM_FORMAT_FLOAT64_BE:
-		return 64;
-	case SNDRV_PCM_FORMAT_IEC958_SUBFRAME_LE:
-	case SNDRV_PCM_FORMAT_IEC958_SUBFRAME_BE:
-		return 32;
-	case SNDRV_PCM_FORMAT_MU_LAW:
-	case SNDRV_PCM_FORMAT_A_LAW:
-		return 8;
-	case SNDRV_PCM_FORMAT_IMA_ADPCM:
-		return 4;
-	default:
+	int val;
+	if (format < 0 || format > SNDRV_PCM_FORMAT_LAST)
 		return -EINVAL;
-	}
+	if ((val = pcm_formats[format].width) == 0)
+		return -EINVAL;
+	return val;
 }
 
 /**
@@ -250,52 +308,12 @@
  */
 int snd_pcm_format_physical_width(snd_pcm_format_t format)
 {
-	switch (snd_enum_to_int(format)) {
-	case SNDRV_PCM_FORMAT_S8:
-	case SNDRV_PCM_FORMAT_U8:
-		return 8;
-	case SNDRV_PCM_FORMAT_S16_LE:
-	case SNDRV_PCM_FORMAT_S16_BE:
-	case SNDRV_PCM_FORMAT_U16_LE:
-	case SNDRV_PCM_FORMAT_U16_BE:
-		return 16;
-	case SNDRV_PCM_FORMAT_S18_3LE:
-	case SNDRV_PCM_FORMAT_S18_3BE:
-	case SNDRV_PCM_FORMAT_U18_3LE:
-	case SNDRV_PCM_FORMAT_U18_3BE:
-	case SNDRV_PCM_FORMAT_S20_3LE:
-	case SNDRV_PCM_FORMAT_S20_3BE:
-	case SNDRV_PCM_FORMAT_U20_3LE:
-	case SNDRV_PCM_FORMAT_U20_3BE:
-	case SNDRV_PCM_FORMAT_S24_3LE:
-	case SNDRV_PCM_FORMAT_S24_3BE:
-	case SNDRV_PCM_FORMAT_U24_3LE:
-	case SNDRV_PCM_FORMAT_U24_3BE:
-		return 24;
-	case SNDRV_PCM_FORMAT_S24_LE:
-	case SNDRV_PCM_FORMAT_S24_BE:
-	case SNDRV_PCM_FORMAT_U24_LE:
-	case SNDRV_PCM_FORMAT_U24_BE:
-	case SNDRV_PCM_FORMAT_S32_LE:
-	case SNDRV_PCM_FORMAT_S32_BE:
-	case SNDRV_PCM_FORMAT_U32_LE:
-	case SNDRV_PCM_FORMAT_U32_BE:
-	case SNDRV_PCM_FORMAT_FLOAT_LE:
-	case SNDRV_PCM_FORMAT_FLOAT_BE:
-	case SNDRV_PCM_FORMAT_IEC958_SUBFRAME_LE:
-	case SNDRV_PCM_FORMAT_IEC958_SUBFRAME_BE:
-		return 32;
-	case SNDRV_PCM_FORMAT_FLOAT64_LE:
-	case SNDRV_PCM_FORMAT_FLOAT64_BE:
-		return 64;
-	case SNDRV_PCM_FORMAT_MU_LAW:
-	case SNDRV_PCM_FORMAT_A_LAW:
-		return 8;
-	case SNDRV_PCM_FORMAT_IMA_ADPCM:
-		return 4;
-	default:
+	int val;
+	if (format < 0 || format > SNDRV_PCM_FORMAT_LAST)
 		return -EINVAL;
-	}
+	if ((val = pcm_formats[format].phys) == 0)
+		return -EINVAL;
+	return val;
 }
 
 /**
@@ -307,216 +325,25 @@
  */
 ssize_t snd_pcm_format_size(snd_pcm_format_t format, size_t samples)
 {
-	switch (snd_enum_to_int(format)) {
-	case SNDRV_PCM_FORMAT_S8:
-	case SNDRV_PCM_FORMAT_U8:
-		return samples;
-	case SNDRV_PCM_FORMAT_S16_LE:
-	case SNDRV_PCM_FORMAT_S16_BE:
-	case SNDRV_PCM_FORMAT_U16_LE:
-	case SNDRV_PCM_FORMAT_U16_BE:
-		return samples * 2;
-	case SNDRV_PCM_FORMAT_S18_3LE:
-	case SNDRV_PCM_FORMAT_S18_3BE:
-	case SNDRV_PCM_FORMAT_U18_3LE:
-	case SNDRV_PCM_FORMAT_U18_3BE:
-	case SNDRV_PCM_FORMAT_S20_3LE:
-	case SNDRV_PCM_FORMAT_S20_3BE:
-	case SNDRV_PCM_FORMAT_U20_3LE:
-	case SNDRV_PCM_FORMAT_U20_3BE:
-	case SNDRV_PCM_FORMAT_S24_3LE:
-	case SNDRV_PCM_FORMAT_S24_3BE:
-	case SNDRV_PCM_FORMAT_U24_3LE:
-	case SNDRV_PCM_FORMAT_U24_3BE:
-		return samples * 3;
-	case SNDRV_PCM_FORMAT_S24_LE:
-	case SNDRV_PCM_FORMAT_S24_BE:
-	case SNDRV_PCM_FORMAT_U24_LE:
-	case SNDRV_PCM_FORMAT_U24_BE:
-	case SNDRV_PCM_FORMAT_S32_LE:
-	case SNDRV_PCM_FORMAT_S32_BE:
-	case SNDRV_PCM_FORMAT_U32_LE:
-	case SNDRV_PCM_FORMAT_U32_BE:
-	case SNDRV_PCM_FORMAT_FLOAT_LE:
-	case SNDRV_PCM_FORMAT_FLOAT_BE:
-		return samples * 4;
-	case SNDRV_PCM_FORMAT_FLOAT64_LE:
-	case SNDRV_PCM_FORMAT_FLOAT64_BE:
-		return samples * 8;
-	case SNDRV_PCM_FORMAT_IEC958_SUBFRAME_LE:
-	case SNDRV_PCM_FORMAT_IEC958_SUBFRAME_BE:
-		return samples * 4;
-	case SNDRV_PCM_FORMAT_MU_LAW:
-	case SNDRV_PCM_FORMAT_A_LAW:
-		return samples;
-	case SNDRV_PCM_FORMAT_IMA_ADPCM:
-		if (samples & 1)
-			return -EINVAL;
-		return samples / 2;
-	default:
+	int phys_width = snd_pcm_format_physical_width(format);
+	if (phys_width < 0)
 		return -EINVAL;
-	}
+	return samples * phys_width / 8;
 }
 
 /**
- * snd_pcm_format_silence_64 - return the silent data in 64bit integer
+ * snd_pcm_format_silence_64 - return the silent data in 8 bytes array
  * @format: the format to check
  *
- * Returns the silent data in 64bit integer for the given format.
+ * Returns the format pattern to fill or NULL if error.
  */
-u_int64_t snd_pcm_format_silence_64(snd_pcm_format_t format)
+const unsigned char *snd_pcm_format_silence_64(snd_pcm_format_t format)
 {
-	switch (snd_enum_to_int(format)) {
-	case SNDRV_PCM_FORMAT_S8:
-	case SNDRV_PCM_FORMAT_S16_LE:
-	case SNDRV_PCM_FORMAT_S16_BE:
-	case SNDRV_PCM_FORMAT_S24_LE:
-	case SNDRV_PCM_FORMAT_S24_BE:
-	case SNDRV_PCM_FORMAT_S32_LE:
-	case SNDRV_PCM_FORMAT_S32_BE:
-	case SNDRV_PCM_FORMAT_S24_3LE:
-	case SNDRV_PCM_FORMAT_S24_3BE:
-	case SNDRV_PCM_FORMAT_S20_3LE:
-	case SNDRV_PCM_FORMAT_S20_3BE:
-	case SNDRV_PCM_FORMAT_S18_3LE:
-	case SNDRV_PCM_FORMAT_S18_3BE:
-		return 0;
-	case SNDRV_PCM_FORMAT_U8:
-		return 0x8080808080808080ULL;
-#ifdef SNDRV_LITTLE_ENDIAN
-	case SNDRV_PCM_FORMAT_U16_LE:
-		return 0x8000800080008000ULL;
-	case SNDRV_PCM_FORMAT_U24_LE:
-		return 0x0080000000800000ULL;
-	case SNDRV_PCM_FORMAT_U32_LE:
-		return 0x8000000080000000ULL;
-	case SNDRV_PCM_FORMAT_U16_BE:
-		return 0x0080008000800080ULL;
-	case SNDRV_PCM_FORMAT_U24_BE:
-		return 0x0000800000008000ULL;
-	case SNDRV_PCM_FORMAT_U32_BE:
-		return 0x0000008000000080ULL;
-	case SNDRV_PCM_FORMAT_U24_3LE:
-		return 0x0000800000800000ULL;
-	case SNDRV_PCM_FORMAT_U24_3BE:
-		return 0x0080000080000080ULL;
-	case SNDRV_PCM_FORMAT_U20_3LE:
-		return 0x0000080000080000ULL;
-	case SNDRV_PCM_FORMAT_U20_3BE:
-		return 0x0008000008000008ULL;
-	case SNDRV_PCM_FORMAT_U18_3LE:
-		return 0x0000020000020000ULL;
-	case SNDRV_PCM_FORMAT_U18_3BE:
-		return 0x0002000002000002ULL;
-#else
-	case SNDRV_PCM_FORMAT_U16_LE:
-		return 0x0080008000800080ULL;
-	case SNDRV_PCM_FORMAT_U24_LE:
-		return 0x0000800000008000ULL;
-	case SNDRV_PCM_FORMAT_U32_LE:
-		return 0x0000008000000080ULL;
-	case SNDRV_PCM_FORMAT_U16_BE:
-		return 0x8000800080008000ULL;
-	case SNDRV_PCM_FORMAT_U24_BE:
-		return 0x0080000000800000ULL;
-	case SNDRV_PCM_FORMAT_U32_BE:
-		return 0x8000000080000000ULL;
-	case SNDRV_PCM_FORMAT_U24_3LE:
-		return 0x0080000080000080ULL;
-	case SNDRV_PCM_FORMAT_U24_3BE:
-		return 0x0000800000800000ULL;
-	case SNDRV_PCM_FORMAT_U20_3LE:
-		return 0x0008000008000008ULL;
-	case SNDRV_PCM_FORMAT_U20_3BE:
-		return 0x0000080000080000ULL;
-	case SNDRV_PCM_FORMAT_U18_3LE:
-		return 0x0002000002000002ULL;
-	case SNDRV_PCM_FORMAT_U18_3BE:
-		return 0x0000020000020000ULL;
-#endif
-	case SNDRV_PCM_FORMAT_FLOAT_LE:
-	{
-		union {
-			float f;
-			u_int32_t i;
-		} u;
-		u.f = 0.0;
-#ifdef SNDRV_LITTLE_ENDIAN
-		return u.i;
-#else
-		return bswap_32(u.i);
-#endif
-	}
-	case SNDRV_PCM_FORMAT_FLOAT64_LE:
-	{
-		union {
-			double f;
-			u_int64_t i;
-		} u;
-		u.f = 0.0;
-#ifdef SNDRV_LITTLE_ENDIAN
-		return u.i;
-#else
-		return bswap_64(u.i);
-#endif
-	}
-	case SNDRV_PCM_FORMAT_FLOAT_BE:		
-	{
-		union {
-			float f;
-			u_int32_t i;
-		} u;
-		u.f = 0.0;
-#ifdef SNDRV_LITTLE_ENDIAN
-		return bswap_32(u.i);
-#else
-		return u.i;
-#endif
-	}
-	case SNDRV_PCM_FORMAT_FLOAT64_BE:
-	{
-		union {
-			double f;
-			u_int64_t i;
-		} u;
-		u.f = 0.0;
-#ifdef SNDRV_LITTLE_ENDIAN
-		return bswap_64(u.i);
-#else
-		return u.i;
-#endif
-	}
-	case SNDRV_PCM_FORMAT_IEC958_SUBFRAME_LE:
-	case SNDRV_PCM_FORMAT_IEC958_SUBFRAME_BE:
-		return 0;	
-	case SNDRV_PCM_FORMAT_MU_LAW:
-		return 0x7f7f7f7f7f7f7f7fULL;
-	case SNDRV_PCM_FORMAT_A_LAW:
-		return 0x5555555555555555ULL;
-	case SNDRV_PCM_FORMAT_IMA_ADPCM:	/* special case */
-	case SNDRV_PCM_FORMAT_MPEG:
-	case SNDRV_PCM_FORMAT_GSM:
-	case SNDRV_PCM_FORMAT_SPECIAL:
-		return 0;
-	default:
-		return -EINVAL;
-	}
-	return 0;
-}
-
-u_int32_t snd_pcm_format_silence_32(snd_pcm_format_t format)
-{
-	return (u_int32_t)snd_pcm_format_silence_64(format);
-}
-
-u_int16_t snd_pcm_format_silence_16(snd_pcm_format_t format)
-{
-	return (u_int16_t)snd_pcm_format_silence_64(format);
-}
-
-u_int8_t snd_pcm_format_silence(snd_pcm_format_t format)
-{
-	return (u_int8_t)snd_pcm_format_silence_64(format);
+	if (format < 0 || format > SNDRV_PCM_FORMAT_LAST)
+		return NULL;
+	if (! pcm_formats[format].phys)
+		return NULL;
+	return pcm_formats[format].silence;
 }
 
 /**
@@ -531,99 +358,73 @@
  */
 int snd_pcm_format_set_silence(snd_pcm_format_t format, void *data, unsigned int samples)
 {
+	int width;
+	unsigned char *dst, *pat;
+
+	if (format < 0 || format > SNDRV_PCM_FORMAT_LAST)
+		return -EINVAL;
 	if (samples == 0)
 		return 0;
-	switch (snd_pcm_format_width(format)) {
-	case 4: {
-		u_int8_t silence = snd_pcm_format_silence_64(format);
-		unsigned int samples1;
-		if (samples % 2 != 0)
-			return -EINVAL;
-		samples1 = samples / 2;
-		memset(data, silence, samples1);
-		break;
+	width = pcm_formats[format].phys; /* physical width */
+	pat = pcm_formats[format].silence;
+	if (! width)
+		return -EINVAL;
+	/* signed or 1 byte data */
+	if (pcm_formats[format].signd == 1 || width <= 8) {
+		unsigned int bytes = samples * width / 8;
+		memset(data, *pat, bytes);
+		return 0;
 	}
-	case 8: {
-		u_int8_t silence = snd_pcm_format_silence_64(format);
-		memset(data, silence, samples);
-		break;
+	/* non-zero samples, fill using a loop */
+	width /= 8;
+	dst = data;
+#if 0
+	while (samples--) {
+		memcpy(dst, pat, width);
+		dst += width;
 	}
-	case 16: {
-		u_int16_t silence = snd_pcm_format_silence_64(format);
-		if (! silence)
-			memset(data, 0, samples * 2);
-		else {
-			u_int16_t *data16 = data;
-			while (samples-- > 0)
-				*data16++ = silence;
+#else
+	/* a bit optimization for constant width */
+	switch (width) {
+	case 2:
+		while (samples--) {
+			memcpy(dst, pat, 2);
+			dst += 2;
 		}
 		break;
-	}
-	case 24: {
-		u_int32_t silence = snd_pcm_format_silence_64(format);
-		if (! silence)
-			memset(data, 0, samples * 3);
-		else {
-			while (samples-- > 0) {
-				u_int8_t *data8 = data;
-#ifdef SNDRV_LITTLE_ENDIAN
-				*data8++ = silence >> 0;
-				*data8++ = silence >> 8;
-				*data8++ = silence >> 16;
-#else
-				*data8++ = silence >> 16;
-				*data8++ = silence >> 8;
-				*data8++ = silence >> 0;
-#endif
-			}
+	case 3:
+		while (samples--) {
+			memcpy(dst, pat, 3);
+			dst += 3;
 		}
 		break;
-	}
-	case 32: {
-		u_int32_t silence = snd_pcm_format_silence_64(format);
-		if (! silence)
-			memset(data, 0, samples * 4);
-		else {
-			u_int32_t *data32 = data;
-			while (samples-- > 0)
-				*data32++ = silence;
+	case 4:
+		while (samples--) {
+			memcpy(dst, pat, 4);
+			dst += 4;
 		}
 		break;
-	}
-	case 64: {
-		u_int64_t silence = snd_pcm_format_silence_64(format);
-		if (! silence)
-			memset(data, 0, samples * 8);
-		else {
-			u_int64_t *data64 = data;
-			while (samples-- > 0)
-				*data64++ = silence;
+	case 8:
+		while (samples--) {
+			memcpy(dst, pat, 8);
+			dst += 8;
 		}
 		break;
 	}
-	default:
-		return -EINVAL;
-	}
+#endif
 	return 0;
 }
 
-static int linear_formats[4*2*2] = {
-	SNDRV_PCM_FORMAT_S8,
-	SNDRV_PCM_FORMAT_S8,
-	SNDRV_PCM_FORMAT_U8,
-	SNDRV_PCM_FORMAT_U8,
-	SNDRV_PCM_FORMAT_S16_LE,
-	SNDRV_PCM_FORMAT_S16_BE,
-	SNDRV_PCM_FORMAT_U16_LE,
-	SNDRV_PCM_FORMAT_U16_BE,
-	SNDRV_PCM_FORMAT_S24_LE,
-	SNDRV_PCM_FORMAT_S24_BE,
-	SNDRV_PCM_FORMAT_U24_LE,
-	SNDRV_PCM_FORMAT_U24_BE,
-	SNDRV_PCM_FORMAT_S32_LE,
-	SNDRV_PCM_FORMAT_S32_BE,
-	SNDRV_PCM_FORMAT_U32_LE,
-	SNDRV_PCM_FORMAT_U32_BE
+/* [width][unsigned][bigendian] */
+static int linear_formats[4][2][2] = {
+	{{ SNDRV_PCM_FORMAT_S8, SNDRV_PCM_FORMAT_S8},
+	 { SNDRV_PCM_FORMAT_U8, SNDRV_PCM_FORMAT_U8}},
+	{{SNDRV_PCM_FORMAT_S16_LE, SNDRV_PCM_FORMAT_S16_BE},
+	 {SNDRV_PCM_FORMAT_U16_LE, SNDRV_PCM_FORMAT_U16_BE}},
+	{{SNDRV_PCM_FORMAT_S24_LE, SNDRV_PCM_FORMAT_S24_BE},
+	 {SNDRV_PCM_FORMAT_U24_LE, SNDRV_PCM_FORMAT_U24_BE}},
+	{{SNDRV_PCM_FORMAT_S32_LE, SNDRV_PCM_FORMAT_S32_BE},
+	 {SNDRV_PCM_FORMAT_U32_LE, SNDRV_PCM_FORMAT_U32_BE}}
 };
 
 /**
@@ -636,23 +437,12 @@
  */
 snd_pcm_format_t snd_pcm_build_linear_format(int width, int unsignd, int big_endian)
 {
-	switch (width) {
-	case 8:
-		width = 0;
-		break;
-	case 16:
-		width = 1;
-		break;
-	case 24:
-		width = 2;
-		break;
-	case 32:
-		width = 3;
-		break;
-	default:
+	if (width & 7)
 		return SND_PCM_FORMAT_UNKNOWN;
-	}
-	return snd_int_to_enum(((int(*)[2][2])linear_formats)[width][!!unsignd][!!big_endian]);
+	width = (width / 8) - 1;
+	if (width < 0 || width >= 4)
+		return SND_PCM_FORMAT_UNKNOWN;
+	return linear_formats[width][!!unsignd][!!big_endian];
 }
 
 /**
diff -Nru a/sound/core/pcm_native.c b/sound/core/pcm_native.c
--- a/sound/core/pcm_native.c	2004-10-18 14:56:28 -07:00
+++ b/sound/core/pcm_native.c	2004-10-18 14:56:28 -07:00
@@ -21,6 +21,7 @@
 
 #include <sound/driver.h>
 #include <linux/mm.h>
+#include <linux/smp_lock.h>
 #include <linux/file.h>
 #include <linux/slab.h>
 #include <linux/time.h>
@@ -32,6 +33,7 @@
 #include <sound/pcm_params.h>
 #include <sound/timer.h>
 #include <sound/minors.h>
+#include <asm/io.h>
 
 /*
  *  Compatibility
@@ -64,6 +66,7 @@
  */
 
 rwlock_t snd_pcm_link_rwlock = RW_LOCK_UNLOCKED;
+static DECLARE_RWSEM(snd_pcm_link_rwsem);
 
 
 static inline mm_segment_t snd_enter_user(void)
@@ -304,13 +307,25 @@
 
 static int snd_pcm_hw_refine_user(snd_pcm_substream_t * substream, snd_pcm_hw_params_t __user * _params)
 {
-	snd_pcm_hw_params_t params;
+	snd_pcm_hw_params_t *params;
 	int err;
-	if (copy_from_user(&params, _params, sizeof(params)))
-		return -EFAULT;
-	err = snd_pcm_hw_refine(substream, &params);
-	if (copy_to_user(_params, &params, sizeof(params)))
-		return -EFAULT;
+
+	params = kmalloc(sizeof(*params), GFP_KERNEL);
+	if (!params) {
+		err = -ENOMEM;
+		goto out;
+	}
+	if (copy_from_user(params, _params, sizeof(*params))) {
+		err = -EFAULT;
+		goto out;
+	}
+	err = snd_pcm_hw_refine(substream, params);
+	if (copy_to_user(_params, params, sizeof(*params))) {
+		if (!err)
+			err = -EFAULT;
+	}
+out:
+	kfree(params);
 	return err;
 }
 
@@ -325,14 +340,17 @@
 	snd_assert(substream != NULL, return -ENXIO);
 	runtime = substream->runtime;
 	snd_assert(runtime != NULL, return -ENXIO);
+	snd_pcm_stream_lock_irq(substream);
 	switch (runtime->status->state) {
 	case SNDRV_PCM_STATE_OPEN:
 	case SNDRV_PCM_STATE_SETUP:
 	case SNDRV_PCM_STATE_PREPARED:
 		break;
 	default:
+		snd_pcm_stream_unlock_irq(substream);
 		return -EBADFD;
 	}
+	snd_pcm_stream_unlock_irq(substream);
 #if defined(CONFIG_SND_PCM_OSS) || defined(CONFIG_SND_PCM_OSS_MODULE)
 	if (!substream->oss.oss)
 #endif
@@ -408,13 +426,25 @@
 
 static int snd_pcm_hw_params_user(snd_pcm_substream_t * substream, snd_pcm_hw_params_t __user * _params)
 {
-	snd_pcm_hw_params_t params;
+	snd_pcm_hw_params_t *params;
 	int err;
-	if (copy_from_user(&params, _params, sizeof(params)))
-		return -EFAULT;
-	err = snd_pcm_hw_params(substream, &params);
-	if (copy_to_user(_params, &params, sizeof(params)))
-		return -EFAULT;
+
+	params = kmalloc(sizeof(*params), GFP_KERNEL);
+	if (!params) {
+		err = -ENOMEM;
+		goto out;
+	}
+	if (copy_from_user(params, _params, sizeof(*params))) {
+		err = -EFAULT;
+		goto out;
+	}
+	err = snd_pcm_hw_params(substream, params);
+	if (copy_to_user(_params, params, sizeof(*params))) {
+		if (!err)
+			err = -EFAULT;
+	}
+out:
+	kfree(params);
 	return err;
 }
 
@@ -426,13 +456,16 @@
 	snd_assert(substream != NULL, return -ENXIO);
 	runtime = substream->runtime;
 	snd_assert(runtime != NULL, return -ENXIO);
+	snd_pcm_stream_lock_irq(substream);
 	switch (runtime->status->state) {
 	case SNDRV_PCM_STATE_SETUP:
 	case SNDRV_PCM_STATE_PREPARED:
 		break;
 	default:
+		snd_pcm_stream_unlock_irq(substream);
 		return -EBADFD;
 	}
+	snd_pcm_stream_unlock_irq(substream);
 	if (atomic_read(&runtime->mmap_count))
 		return -EBADFD;
 	if (substream->ops->hw_free == NULL) {
@@ -447,11 +480,16 @@
 static int snd_pcm_sw_params(snd_pcm_substream_t * substream, snd_pcm_sw_params_t *params)
 {
 	snd_pcm_runtime_t *runtime;
+
 	snd_assert(substream != NULL, return -ENXIO);
 	runtime = substream->runtime;
 	snd_assert(runtime != NULL, return -ENXIO);
-	if (runtime->status->state == SNDRV_PCM_STATE_OPEN)
+	snd_pcm_stream_lock_irq(substream);
+	if (runtime->status->state == SNDRV_PCM_STATE_OPEN) {
+		snd_pcm_stream_unlock_irq(substream);
 		return -EBADFD;
+	}
+	snd_pcm_stream_unlock_irq(substream);
 
 	if (params->tstamp_mode > SNDRV_PCM_TSTAMP_LAST)
 		return -EINVAL;
@@ -579,8 +617,12 @@
 		return -EFAULT;
 	channel = info.channel;
 	runtime = substream->runtime;
-	if (runtime->status->state == SNDRV_PCM_STATE_OPEN)
+	snd_pcm_stream_lock_irq(substream);
+	if (runtime->status->state == SNDRV_PCM_STATE_OPEN) {
+		snd_pcm_stream_unlock_irq(substream);
 		return -EBADFD;
+	}
+	snd_pcm_stream_unlock_irq(substream);
 	if (channel >= runtime->channels)
 		return -EINVAL;
 	memset(&info, 0, sizeof(info));
@@ -620,7 +662,7 @@
  */
 static int snd_pcm_action_group(struct action_ops *ops,
 				snd_pcm_substream_t *substream,
-				int state, int atomic_only)
+				int state, int do_lock)
 {
 	struct list_head *pos;
 	snd_pcm_substream_t *s = NULL;
@@ -628,9 +670,7 @@
 
 	snd_pcm_group_for_each(pos, substream) {
 		s = snd_pcm_group_substream_entry(pos);
-		if (atomic_only && (s->pcm->info_flags & SNDRV_PCM_INFO_NONATOMIC_OPS))
-			continue;
-		if (s != substream)
+		if (do_lock && s != substream)
 			spin_lock(&s->self_group.lock);
 		res = ops->pre_action(s, state);
 		if (res < 0)
@@ -639,8 +679,6 @@
 	if (res >= 0) {
 		snd_pcm_group_for_each(pos, substream) {
 			s = snd_pcm_group_substream_entry(pos);
-			if (atomic_only && (s->pcm->info_flags & SNDRV_PCM_INFO_NONATOMIC_OPS))
-				continue;
 			err = ops->do_action(s, state);
 			if (err < 0) {
 				if (res == 0)
@@ -648,17 +686,15 @@
 			} else {
 				ops->post_action(s, state);
 			}
-			if (s != substream)
+			if (do_lock && s != substream)
 				spin_unlock(&s->self_group.lock);
 		}
-	} else {
+	} else if (do_lock) {
 		snd_pcm_substream_t *s1;
 		/* unlock all streams */
 		snd_pcm_group_for_each(pos, substream) {
 			s1 = snd_pcm_group_substream_entry(pos);
-			if (atomic_only && (s1->pcm->info_flags & SNDRV_PCM_INFO_NONATOMIC_OPS))
-				;
-			else if (s1 != substream)
+			if (s1 != substream)
 				spin_unlock(&s1->self_group.lock);
 			if (s1 == s)	/* end */
 				break;
@@ -688,8 +724,6 @@
 
 /*
  *  Note: call with stream lock
- *
- * NB2: this won't handle the non-atomic callbacks
  */
 static int snd_pcm_action(struct action_ops *ops,
 			  snd_pcm_substream_t *substream,
@@ -703,7 +737,7 @@
 			spin_lock(&substream->group->lock);
 			spin_lock(&substream->self_group.lock);
 		}
-		res = snd_pcm_action_group(ops, substream, state, 0);
+		res = snd_pcm_action_group(ops, substream, state, 1);
 		spin_unlock(&substream->group->lock);
 	} else {
 		res = snd_pcm_action_single(ops, substream, state);
@@ -713,14 +747,10 @@
 
 /*
  *  Note: don't use any locks before
- *
- * NB2: this can handle the non-atomic callbacks if allow_nonatomic = 1
- *      when the pcm->info_flags has NONATOMIC_OPS bit, it's handled
- *      ouside the lock to allow sleep in the callback.
  */
 static int snd_pcm_action_lock_irq(struct action_ops *ops,
 				   snd_pcm_substream_t *substream,
-				   int state, int allow_nonatomic)
+				   int state)
 {
 	int res;
 
@@ -728,43 +758,10 @@
 	if (snd_pcm_stream_linked(substream)) {
 		spin_lock(&substream->group->lock);
 		spin_lock(&substream->self_group.lock);
-		res = snd_pcm_action_group(ops, substream, state, allow_nonatomic);
+		res = snd_pcm_action_group(ops, substream, state, 1);
 		spin_unlock(&substream->self_group.lock);
 		spin_unlock(&substream->group->lock);
-		if (res >= 0 && allow_nonatomic) {
-			/* now process the non-atomic substreams separately
-			 * outside the lock
-			 */
-#define MAX_LINKED_STREAMS	16	/* FIXME: should be variable */
-
-			struct list_head *pos;
-			int i, num_s = 0;
-			snd_pcm_substream_t *s;
-			snd_pcm_substream_t *subs[MAX_LINKED_STREAMS];
-			snd_pcm_group_for_each(pos, substream) {
-				if (num_s >= MAX_LINKED_STREAMS) {
-					res = -ENOMEM;
-					num_s = 0; /* don't proceed */
-					break;
-				}
-				s = snd_pcm_group_substream_entry(pos);
-				if (s->pcm->info_flags & SNDRV_PCM_INFO_NONATOMIC_OPS)
-					subs[num_s++] = s;
-			}
-			if (num_s > 0) {
-				read_unlock_irq(&snd_pcm_link_rwlock);
-				for (i = 0; i < num_s && res >= 0; i++)
-					res = snd_pcm_action_single(ops, subs[i], state);
-				return res;
-			}
-		}
 	} else {
-		if (allow_nonatomic &&
-		    (substream->pcm->info_flags & SNDRV_PCM_INFO_NONATOMIC_OPS)) {
-			read_unlock_irq(&snd_pcm_link_rwlock);
-			/* process outside the lock */
-			return snd_pcm_action_single(ops, substream, state);
-		}
 		spin_lock(&substream->self_group.lock);
 		res = snd_pcm_action_single(ops, substream, state);
 		spin_unlock(&substream->self_group.lock);
@@ -773,6 +770,23 @@
 	return res;
 }
 
+/*
+ */
+static int snd_pcm_action_nonatomic(struct action_ops *ops,
+				    snd_pcm_substream_t *substream,
+				    int state)
+{
+	int res;
+
+	down_read(&snd_pcm_link_rwsem);
+	if (snd_pcm_stream_linked(substream))
+		res = snd_pcm_action_group(ops, substream, state, 0);
+	else
+		res = snd_pcm_action_single(ops, substream, state);
+	up_read(&snd_pcm_link_rwsem);
+	return res;
+}
+
 static int snd_pcm_pre_start(snd_pcm_substream_t *substream, int state)
 {
 	snd_pcm_runtime_t *runtime = substream->runtime;
@@ -1038,7 +1052,7 @@
 
 	snd_power_lock(card);
 	if ((res = snd_power_wait(card, SNDRV_CTL_POWER_D0, substream->ffile)) >= 0)
-		res = snd_pcm_action_lock_irq(&snd_pcm_action_resume, substream, 0, 0);
+		res = snd_pcm_action_lock_irq(&snd_pcm_action_resume, substream, 0);
 	snd_power_unlock(card);
 	return res;
 }
@@ -1128,7 +1142,7 @@
 
 static int snd_pcm_reset(snd_pcm_substream_t *substream)
 {
-	return snd_pcm_action_lock_irq(&snd_pcm_action_reset, substream, 0, 0);
+	return snd_pcm_action_nonatomic(&snd_pcm_action_reset, substream, 0);
 }
 
 static int snd_pcm_pre_prepare(snd_pcm_substream_t * substream, int state)
@@ -1176,7 +1190,7 @@
 
 	snd_power_lock(card);
 	if ((res = snd_power_wait(card, SNDRV_CTL_POWER_D0, substream->ffile)) >= 0)
-		res = snd_pcm_action_lock_irq(&snd_pcm_action_prepare, substream, 0, 1); /* allow sleep if specified */
+		res = snd_pcm_action_nonatomic(&snd_pcm_action_prepare, substream, 0);
 	snd_power_unlock(card);
 	return res;
 }
@@ -1498,13 +1512,18 @@
 	snd_pcm_file_t *pcm_file;
 	snd_pcm_substream_t *substream1;
 
-	if (substream->runtime->status->state == SNDRV_PCM_STATE_OPEN)
+	snd_pcm_stream_lock_irq(substream);
+	if (substream->runtime->status->state == SNDRV_PCM_STATE_OPEN) {
+		snd_pcm_stream_unlock_irq(substream);
 		return -EBADFD;
+	}
+	snd_pcm_stream_unlock_irq(substream);
 	file = snd_pcm_file_fd(fd);
 	if (!file)
 		return -EBADFD;
-	pcm_file = snd_magic_cast(snd_pcm_file_t, file->private_data, return -ENXIO);
+	pcm_file = file->private_data;
 	substream1 = pcm_file->substream;
+	down_write(&snd_pcm_link_rwsem);
 	write_lock_irq(&snd_pcm_link_rwlock);
 	if (substream->runtime->status->state != substream1->runtime->status->state) {
 		res = -EBADFD;
@@ -1528,6 +1547,7 @@
 	substream1->group = substream->group;
  _end:
 	write_unlock_irq(&snd_pcm_link_rwlock);
+	up_write(&snd_pcm_link_rwsem);
 	fput(file);
 	return res;
 }
@@ -1544,6 +1564,7 @@
 	struct list_head *pos;
 	int res = 0, count = 0;
 
+	down_write(&snd_pcm_link_rwsem);
 	write_lock_irq(&snd_pcm_link_rwlock);
 	if (!snd_pcm_stream_linked(substream)) {
 		res = -EALREADY;
@@ -1564,6 +1585,7 @@
 	relink_to_local(substream);
        _end:
 	write_unlock_irq(&snd_pcm_link_rwlock);
+	up_write(&snd_pcm_link_rwsem);
 	return res;
 }
 
@@ -1658,13 +1680,12 @@
 static unsigned int rates[] = { 5512, 8000, 11025, 16000, 22050, 32000, 44100,
                                  48000, 64000, 88200, 96000, 176400, 192000 };
 
-#define RATES (sizeof(rates) / sizeof(rates[0]))
-
 static int snd_pcm_hw_rule_rate(snd_pcm_hw_params_t *params,
 				snd_pcm_hw_rule_t *rule)
 {
 	snd_pcm_hardware_t *hw = rule->private;
-	return snd_interval_list(hw_param_interval(params, rule->var), RATES, rates, hw->rates);
+	return snd_interval_list(hw_param_interval(params, rule->var),
+				 ARRAY_SIZE(rates), rates, hw->rates);
 }		
 
 static int snd_pcm_hw_rule_buffer_bytes_max(snd_pcm_hw_params_t *params,
@@ -1923,7 +1944,7 @@
 	substream->ffile = NULL;
 	snd_pcm_remove_file(str, pcm_file);
 	snd_pcm_release_substream(substream);
-	snd_magic_kfree(pcm_file);
+	kfree(pcm_file);
 	return 0;
 }
 
@@ -1940,13 +1961,13 @@
 	snd_assert(rpcm_file != NULL, return -EINVAL);
 	*rpcm_file = NULL;
 
-	pcm_file = snd_magic_kcalloc(snd_pcm_file_t, 0, GFP_KERNEL);
+	pcm_file = kcalloc(1, sizeof(*pcm_file), GFP_KERNEL);
 	if (pcm_file == NULL) {
 		return -ENOMEM;
 	}
 
 	if ((err = snd_pcm_open_substream(pcm, stream, &substream)) < 0) {
-		snd_magic_kfree(pcm_file);
+		kfree(pcm_file);
 		return err;
 	}
 
@@ -2050,7 +2071,7 @@
 	snd_pcm_substream_t *substream;
 	snd_pcm_file_t *pcm_file;
 
-	pcm_file = snd_magic_cast(snd_pcm_file_t, file->private_data, return -ENXIO);
+	pcm_file = file->private_data;
 	substream = pcm_file->substream;
 	snd_assert(substream != NULL, return -ENXIO);
 	snd_assert(!atomic_read(&substream->runtime->mmap_count), );
@@ -2414,7 +2435,7 @@
 	case SNDRV_PCM_IOCTL_RESET:
 		return snd_pcm_reset(substream);
 	case SNDRV_PCM_IOCTL_START:
-		return snd_pcm_action_lock_irq(&snd_pcm_action_start, substream, 0, 0);
+		return snd_pcm_action_lock_irq(&snd_pcm_action_start, substream, 0);
 	case SNDRV_PCM_IOCTL_LINK:
 		return snd_pcm_link(substream, (int)(unsigned long) arg);
 	case SNDRV_PCM_IOCTL_UNLINK:
@@ -2616,26 +2637,36 @@
 				  unsigned int cmd, unsigned long arg)
 {
 	snd_pcm_file_t *pcm_file;
+	int err;
 
-	pcm_file = snd_magic_cast(snd_pcm_file_t, file->private_data, return -ENXIO);
+	pcm_file = file->private_data;
 
 	if (((cmd >> 8) & 0xff) != 'A')
 		return -ENOTTY;
 
-	return snd_pcm_playback_ioctl1(pcm_file->substream, cmd, (void __user *)arg);
+	/* FIXME: need to unlock BKL to allow preemption */
+	unlock_kernel();
+	err = snd_pcm_playback_ioctl1(pcm_file->substream, cmd, (void __user *)arg);
+	lock_kernel();
+	return err;
 }
 
 static int snd_pcm_capture_ioctl(struct inode *inode, struct file *file,
 				 unsigned int cmd, unsigned long arg)
 {
 	snd_pcm_file_t *pcm_file;
+	int err;
 
-	pcm_file = snd_magic_cast(snd_pcm_file_t, file->private_data, return -ENXIO);
+	pcm_file = file->private_data;
 
 	if (((cmd >> 8) & 0xff) != 'A')
 		return -ENOTTY;
 
-	return snd_pcm_capture_ioctl1(pcm_file->substream, cmd, (void __user *)arg);
+	/* FIXME: need to unlock BKL to allow preemption */
+	unlock_kernel();
+	err = snd_pcm_capture_ioctl1(pcm_file->substream, cmd, (void __user *)arg);
+	lock_kernel();
+	return err;
 }
 
 int snd_pcm_kernel_playback_ioctl(snd_pcm_substream_t *substream,
@@ -2682,7 +2713,7 @@
 	snd_pcm_runtime_t *runtime;
 	snd_pcm_sframes_t result;
 
-	pcm_file = snd_magic_cast(snd_pcm_file_t, file->private_data, return -ENXIO);
+	pcm_file = file->private_data;
 	substream = pcm_file->substream;
 	snd_assert(substream != NULL, return -ENXIO);
 	runtime = substream->runtime;
@@ -2704,7 +2735,7 @@
 	snd_pcm_runtime_t *runtime;
 	snd_pcm_sframes_t result;
 
-	pcm_file = snd_magic_cast(snd_pcm_file_t, file->private_data, result = -ENXIO; goto end);
+	pcm_file = file->private_data;
 	substream = pcm_file->substream;
 	snd_assert(substream != NULL, result = -ENXIO; goto end);
 	runtime = substream->runtime;
@@ -2736,7 +2767,7 @@
 	void __user **bufs;
 	snd_pcm_uframes_t frames;
 
-	pcm_file = snd_magic_cast(snd_pcm_file_t, file->private_data, return -ENXIO);
+	pcm_file = file->private_data;
 	substream = pcm_file->substream;
 	snd_assert(substream != NULL, return -ENXIO);
 	runtime = substream->runtime;
@@ -2770,7 +2801,7 @@
 	void __user **bufs;
 	snd_pcm_uframes_t frames;
 
-	pcm_file = snd_magic_cast(snd_pcm_file_t, file->private_data, result = -ENXIO; goto end);
+	pcm_file = file->private_data;
 	substream = pcm_file->substream;
 	snd_assert(substream != NULL, result = -ENXIO; goto end);
 	runtime = substream->runtime;
@@ -2805,7 +2836,7 @@
         unsigned int mask;
 	snd_pcm_uframes_t avail;
 
-	pcm_file = snd_magic_cast(snd_pcm_file_t, file->private_data, return 0);
+	pcm_file = file->private_data;
 
 	substream = pcm_file->substream;
 	snd_assert(substream != NULL, return -ENXIO);
@@ -2843,7 +2874,7 @@
         unsigned int mask;
 	snd_pcm_uframes_t avail;
 
-	pcm_file = snd_magic_cast(snd_pcm_file_t, file->private_data, return 0);
+	pcm_file = file->private_data;
 
 	substream = pcm_file->substream;
 	snd_assert(substream != NULL, return -ENXIO);
@@ -2877,6 +2908,18 @@
 	return mask;
 }
 
+/*
+ * mmap support
+ */
+
+/*
+ * Only on coherent architectures, we can mmap the status and the control records
+ * for effcient data transfer.  On others, we have to use HWSYNC ioctl...
+ */
+#if defined(CONFIG_X86) || defined(CONFIG_PPC) || defined(CONFIG_ALPHA)
+/*
+ * mmap status record
+ */
 static struct page * snd_pcm_mmap_status_nopage(struct vm_area_struct *area, unsigned long address, int *type)
 {
 	snd_pcm_substream_t *substream = (snd_pcm_substream_t *)area->vm_private_data;
@@ -2899,8 +2942,8 @@
 	.nopage =	snd_pcm_mmap_status_nopage,
 };
 
-int snd_pcm_mmap_status(snd_pcm_substream_t *substream, struct file *file,
-			struct vm_area_struct *area)
+static int snd_pcm_mmap_status(snd_pcm_substream_t *substream, struct file *file,
+			       struct vm_area_struct *area)
 {
 	snd_pcm_runtime_t *runtime;
 	long size;
@@ -2917,6 +2960,9 @@
 	return 0;
 }
 
+/*
+ * mmap control record
+ */
 static struct page * snd_pcm_mmap_control_nopage(struct vm_area_struct *area, unsigned long address, int *type)
 {
 	snd_pcm_substream_t *substream = (snd_pcm_substream_t *)area->vm_private_data;
@@ -2956,20 +3002,26 @@
 	area->vm_flags |= VM_RESERVED;
 	return 0;
 }
-
-static void snd_pcm_mmap_data_open(struct vm_area_struct *area)
+#else /* ! coherent mmap */
+/*
+ * don't support mmap for status and control records.
+ */
+static int snd_pcm_mmap_status(snd_pcm_substream_t *substream, struct file *file,
+			       struct vm_area_struct *area)
 {
-	snd_pcm_substream_t *substream = (snd_pcm_substream_t *)area->vm_private_data;
-	atomic_inc(&substream->runtime->mmap_count);
+	return -ENXIO;
 }
-
-static void snd_pcm_mmap_data_close(struct vm_area_struct *area)
+static int snd_pcm_mmap_control(snd_pcm_substream_t *substream, struct file *file,
+				struct vm_area_struct *area)
 {
-	snd_pcm_substream_t *substream = (snd_pcm_substream_t *)area->vm_private_data;
-	atomic_dec(&substream->runtime->mmap_count);
+	return -ENXIO;
 }
+#endif /* coherent mmap */
 
-static struct page * snd_pcm_mmap_data_nopage(struct vm_area_struct *area, unsigned long address, int *type)
+/*
+ * nopage callback for mmapping a RAM page
+ */
+static struct page *snd_pcm_mmap_data_nopage(struct vm_area_struct *area, unsigned long address, int *type)
 {
 	snd_pcm_substream_t *substream = (snd_pcm_substream_t *)area->vm_private_data;
 	snd_pcm_runtime_t *runtime;
@@ -3009,6 +3061,52 @@
 	.nopage =	snd_pcm_mmap_data_nopage,
 };
 
+/*
+ * mmap the DMA buffer on RAM
+ */
+static int snd_pcm_default_mmap(snd_pcm_substream_t *substream, struct vm_area_struct *area)
+{
+	area->vm_ops = &snd_pcm_vm_ops_data;
+	area->vm_private_data = substream;
+	area->vm_flags |= VM_RESERVED;
+	atomic_inc(&substream->runtime->mmap_count);
+	return 0;
+}
+
+/*
+ * mmap the DMA buffer on I/O memory area
+ */
+#if SNDRV_PCM_INFO_MMAP_IOMEM
+static struct vm_operations_struct snd_pcm_vm_ops_data_mmio =
+{
+	.open =		snd_pcm_mmap_data_open,
+	.close =	snd_pcm_mmap_data_close,
+};
+
+int snd_pcm_lib_mmap_iomem(snd_pcm_substream_t *substream, struct vm_area_struct *area)
+{
+	long size;
+	unsigned long offset;
+
+#ifdef pgprot_noncached
+	area->vm_page_prot = pgprot_noncached(area->vm_page_prot);
+#endif
+	area->vm_ops = &snd_pcm_vm_ops_data_mmio;
+	area->vm_flags |= VM_IO;
+	size = area->vm_end - area->vm_start;
+	offset = area->vm_pgoff << PAGE_SHIFT;
+	if (io_remap_page_range(area, area->vm_start,
+				substream->runtime->dma_addr + offset,
+				size, area->vm_page_prot))
+		return -EAGAIN;
+	atomic_inc(&substream->runtime->mmap_count);
+	return 0;
+}
+#endif /* SNDRV_PCM_INFO_MMAP */
+
+/*
+ * mmap DMA buffer
+ */
 int snd_pcm_mmap_data(snd_pcm_substream_t *substream, struct file *file,
 		      struct vm_area_struct *area)
 {
@@ -3041,11 +3139,10 @@
 	if (offset > dma_bytes - size)
 		return -EINVAL;
 
-	area->vm_ops = &snd_pcm_vm_ops_data;
-	area->vm_private_data = substream;
-	area->vm_flags |= VM_RESERVED;
-	atomic_inc(&runtime->mmap_count);
-	return 0;
+	if (substream->ops->mmap)
+		return substream->ops->mmap(substream, area);
+	else
+		return snd_pcm_default_mmap(substream, area);
 }
 
 static int snd_pcm_mmap(struct file *file, struct vm_area_struct *area)
@@ -3054,7 +3151,7 @@
 	snd_pcm_substream_t *substream;	
 	unsigned long offset;
 	
-	pcm_file = snd_magic_cast(snd_pcm_file_t, file->private_data, return -ENXIO);
+	pcm_file = file->private_data;
 	substream = pcm_file->substream;
 	snd_assert(substream != NULL, return -ENXIO);
 
@@ -3077,7 +3174,7 @@
 	snd_pcm_runtime_t *runtime;
 	int err;
 
-	pcm_file = snd_magic_cast(snd_pcm_file_t, file->private_data, return -ENXIO);
+	pcm_file = file->private_data;
 	substream = pcm_file->substream;
 	snd_assert(substream != NULL, return -ENXIO);
 	runtime = substream->runtime;
@@ -3101,7 +3198,7 @@
 
 	memset(params, 0, sizeof(*params));
 	params->flags = oparams->flags;
-	for (i = 0; i < sizeof(oparams->masks) / sizeof(unsigned int); i++)
+	for (i = 0; i < ARRAY_SIZE(oparams->masks); i++)
 		params->masks[i].bits[0] = oparams->masks[i];
 	memcpy(params->intervals, oparams->intervals, sizeof(oparams->intervals));
 	params->rmask = __OLD_TO_NEW_MASK(oparams->rmask);
@@ -3119,7 +3216,7 @@
 
 	memset(oparams, 0, sizeof(*oparams));
 	oparams->flags = params->flags;
-	for (i = 0; i < sizeof(oparams->masks) / sizeof(unsigned int); i++)
+	for (i = 0; i < ARRAY_SIZE(oparams->masks); i++)
 		oparams->masks[i] = params->masks[i].bits[0];
 	memcpy(oparams->intervals, params->intervals, sizeof(oparams->intervals));
 	oparams->rmask = __NEW_TO_OLD_MASK(params->rmask);
@@ -3133,31 +3230,68 @@
 
 static int snd_pcm_hw_refine_old_user(snd_pcm_substream_t * substream, struct sndrv_pcm_hw_params_old __user * _oparams)
 {
-	snd_pcm_hw_params_t params;
-	struct sndrv_pcm_hw_params_old oparams;
+	snd_pcm_hw_params_t *params;
+	struct sndrv_pcm_hw_params_old *oparams = NULL;
 	int err;
-	if (copy_from_user(&oparams, _oparams, sizeof(oparams)))
-		return -EFAULT;
-	snd_pcm_hw_convert_from_old_params(&params, &oparams);
-	err = snd_pcm_hw_refine(substream, &params);
-	snd_pcm_hw_convert_to_old_params(&oparams, &params);
-	if (copy_to_user(_oparams, &oparams, sizeof(oparams)))
-		return -EFAULT;
+
+	params = kmalloc(sizeof(*params), GFP_KERNEL);
+	if (!params) {
+		err = -ENOMEM;
+		goto out;
+	}
+	oparams = kmalloc(sizeof(*oparams), GFP_KERNEL);
+	if (!oparams) {
+		err = -ENOMEM;
+		goto out;
+	}
+
+	if (copy_from_user(oparams, _oparams, sizeof(*oparams))) {
+		err = -EFAULT;
+		goto out;
+	}
+	snd_pcm_hw_convert_from_old_params(params, oparams);
+	err = snd_pcm_hw_refine(substream, params);
+	snd_pcm_hw_convert_to_old_params(oparams, params);
+	if (copy_to_user(_oparams, oparams, sizeof(*oparams))) {
+		if (!err)
+			err = -EFAULT;
+	}
+out:
+	kfree(params);
+	kfree(oparams);
 	return err;
 }
 
 static int snd_pcm_hw_params_old_user(snd_pcm_substream_t * substream, struct sndrv_pcm_hw_params_old __user * _oparams)
 {
-	snd_pcm_hw_params_t params;
-	struct sndrv_pcm_hw_params_old oparams;
+	snd_pcm_hw_params_t *params;
+	struct sndrv_pcm_hw_params_old *oparams = NULL;
 	int err;
-	if (copy_from_user(&oparams, _oparams, sizeof(oparams)))
-		return -EFAULT;
-	snd_pcm_hw_convert_from_old_params(&params, &oparams);
-	err = snd_pcm_hw_params(substream, &params);
-	snd_pcm_hw_convert_to_old_params(&oparams, &params);
-	if (copy_to_user(_oparams, &oparams, sizeof(oparams)))
-		return -EFAULT;
+
+	params = kmalloc(sizeof(*params), GFP_KERNEL);
+	if (!params) {
+		err = -ENOMEM;
+		goto out;
+	}
+	oparams = kmalloc(sizeof(*oparams), GFP_KERNEL);
+	if (!oparams) {
+		err = -ENOMEM;
+		goto out;
+	}
+	if (copy_from_user(oparams, _oparams, sizeof(*oparams))) {
+		err = -EFAULT;
+		goto out;
+	}
+	snd_pcm_hw_convert_from_old_params(params, oparams);
+	err = snd_pcm_hw_params(substream, params);
+	snd_pcm_hw_convert_to_old_params(oparams, params);
+	if (copy_to_user(_oparams, oparams, sizeof(*oparams))) {
+		if (!err)
+			err = -EFAULT;
+	}
+out:
+	kfree(params);
+	kfree(oparams);
 	return err;
 }
 
diff -Nru a/sound/core/pcm_timer.c b/sound/core/pcm_timer.c
--- a/sound/core/pcm_timer.c	2004-10-18 14:57:04 -07:00
+++ b/sound/core/pcm_timer.c	2004-10-18 14:57:04 -07:00
@@ -25,8 +25,6 @@
 #include <sound/pcm.h>
 #include <sound/timer.h>
 
-#define chip_t snd_pcm_substream_t
-
 /*
  *  Timer functions
  */
@@ -49,7 +47,7 @@
 
 void snd_pcm_timer_resolution_change(snd_pcm_substream_t *substream)
 {
-	unsigned long rate, mult, fsize, l;
+	unsigned long rate, mult, fsize, l, post;
 	snd_pcm_runtime_t *runtime = substream->runtime;
 	
         mult = 1000000000;
@@ -63,23 +61,24 @@
 	l = gcd(rate, fsize);
 	rate /= l;
 	fsize /= l;
+	post = 1;
 	while ((mult * fsize) / fsize != mult) {
 		mult /= 2;
-		rate /= 2;
+		post *= 2;
 	}
 	if (rate == 0) {
 		snd_printk(KERN_ERR "pcm timer resolution out of range (rate = %u, period_size = %lu)\n", runtime->rate, runtime->period_size);
 		runtime->timer_resolution = -1;
 		return;
 	}
-	runtime->timer_resolution = mult * fsize / rate;
+	runtime->timer_resolution = (mult * fsize / rate) * post;
 }
 
 static unsigned long snd_pcm_timer_resolution(snd_timer_t * timer)
 {
 	snd_pcm_substream_t * substream;
 	
-	substream = snd_magic_cast(snd_pcm_substream_t, timer->private_data, return -ENXIO);
+	substream = timer->private_data;
 	return substream->runtime ? substream->runtime->timer_resolution : 0;
 }
 
@@ -123,7 +122,7 @@
 
 static void snd_pcm_timer_free(snd_timer_t *timer)
 {
-	snd_pcm_substream_t *substream = snd_magic_cast(snd_pcm_substream_t, timer->private_data, return);
+	snd_pcm_substream_t *substream = timer->private_data;
 	substream->timer = NULL;
 }
 
diff -Nru a/sound/core/rawmidi.c b/sound/core/rawmidi.c
--- a/sound/core/rawmidi.c	2004-10-18 14:56:13 -07:00
+++ b/sound/core/rawmidi.c	2004-10-18 14:56:13 -07:00
@@ -23,6 +23,7 @@
 #include <sound/core.h>
 #include <linux/major.h>
 #include <linux/init.h>
+#include <linux/smp_lock.h>
 #include <linux/sched.h>
 #include <linux/slab.h>
 #include <linux/time.h>
@@ -44,10 +45,8 @@
 static int boot_devs;
 module_param_array(midi_map, int, boot_devs, 0444);
 MODULE_PARM_DESC(midi_map, "Raw MIDI device number assigned to 1st OSS device.");
-MODULE_PARM_SYNTAX(midi_map, "default:0,skill:advanced");
 module_param_array(amidi_map, int, boot_devs, 0444);
 MODULE_PARM_DESC(amidi_map, "Raw MIDI device number assigned to 2nd OSS device.");
-MODULE_PARM_SYNTAX(amidi_map, "default:1,skill:advanced");
 #endif /* CONFIG_SND_OSSEMUL */
 
 static int snd_rawmidi_free(snd_rawmidi_t *rawmidi);
@@ -269,7 +268,7 @@
 		list2 = list2->next;
 	}
 	if (mode & SNDRV_RAWMIDI_LFLG_INPUT) {
-		input = snd_kcalloc(sizeof(snd_rawmidi_runtime_t), GFP_KERNEL);
+		input = kcalloc(1, sizeof(*input), GFP_KERNEL);
 		if (input == NULL) {
 			err = -ENOMEM;
 			goto __error;
@@ -291,7 +290,7 @@
 	if (mode & SNDRV_RAWMIDI_LFLG_OUTPUT) {
 		if (soutput->opened)
 			goto __skip_output;
-		output = snd_kcalloc(sizeof(snd_rawmidi_runtime_t), GFP_KERNEL);
+		output = kcalloc(1, sizeof(*output), GFP_KERNEL);
 		if (output == NULL) {
 			err = -ENOMEM;
 			goto __error;
@@ -398,7 +397,7 @@
 	if ((file->f_flags & O_APPEND) || maj != CONFIG_SND_MAJOR) /* OSS emul? */
 		fflags |= SNDRV_RAWMIDI_LFLG_APPEND;
 	fflags |= SNDRV_RAWMIDI_LFLG_NOOPENLOCK;
-	rawmidi_file = snd_magic_kmalloc(snd_rawmidi_file_t, 0, GFP_KERNEL);
+	rawmidi_file = kmalloc(sizeof(*rawmidi_file), GFP_KERNEL);
 	if (rawmidi_file == NULL) {
 		snd_card_file_remove(card, file);
 		return -ENOMEM;
@@ -447,7 +446,7 @@
 		file->private_data = rawmidi_file;
 	} else {
 		snd_card_file_remove(card, file);
-		snd_magic_kfree(rawmidi_file);
+		kfree(rawmidi_file);
 	}
 	up(&rmidi->open_mutex);
 	return err;
@@ -512,11 +511,11 @@
 	snd_rawmidi_t *rmidi;
 	int err;
 
-	rfile = snd_magic_cast(snd_rawmidi_file_t, file->private_data, return -ENXIO);
+	rfile = file->private_data;
 	err = snd_rawmidi_kernel_release(rfile);
 	rmidi = rfile->rmidi;
 	wake_up(&rmidi->open_wait);
-	snd_magic_kfree(rfile);
+	kfree(rfile);
 	snd_card_file_remove(rmidi->card, file);
 	return err;
 }
@@ -675,13 +674,13 @@
 	return 0;
 }
 
-static int snd_rawmidi_ioctl(struct inode *inode, struct file *file,
-			     unsigned int cmd, unsigned long arg)
+static inline int _snd_rawmidi_ioctl(struct inode *inode, struct file *file,
+				     unsigned int cmd, unsigned long arg)
 {
 	snd_rawmidi_file_t *rfile;
 	void __user *argp = (void __user *)arg;
 
-	rfile = snd_magic_cast(snd_rawmidi_file_t, file->private_data, return -ENXIO);
+	rfile = file->private_data;
 	if (((cmd >> 8) & 0xff) != 'W')
 		return -ENOTTY;
 	switch (cmd) {
@@ -786,6 +785,17 @@
 	return -ENOTTY;
 }
 
+/* FIXME: need to unlock BKL to allow preemption */
+static int snd_rawmidi_ioctl(struct inode *inode, struct file *file,
+			     unsigned int cmd, unsigned long arg)
+{
+	int err;
+	unlock_kernel();
+	err = _snd_rawmidi_ioctl(inode, file, cmd, arg);
+	lock_kernel();
+	return err;
+}
+
 int snd_rawmidi_control_ioctl(snd_card_t * card, snd_ctl_file_t * control,
 			      unsigned int cmd, unsigned long arg)
 {
@@ -944,7 +954,7 @@
 	snd_rawmidi_substream_t *substream;
 	snd_rawmidi_runtime_t *runtime;
 
-	rfile = snd_magic_cast(snd_rawmidi_file_t, file->private_data, return -ENXIO);
+	rfile = file->private_data;
 	substream = rfile->input;
 	if (substream == NULL)
 		return -EIO;
@@ -974,6 +984,8 @@
 		}
 		spin_unlock_irq(&runtime->lock);
 		count1 = snd_rawmidi_kernel_read1(substream, buf, count, 0);
+		if (count1 < 0)
+			return result > 0 ? result : count1;
 		result += count1;
 		buf += count1;
 		count -= count1;
@@ -1176,7 +1188,7 @@
 	snd_rawmidi_runtime_t *runtime;
 	snd_rawmidi_substream_t *substream;
 
-	rfile = snd_magic_cast(snd_rawmidi_file_t, file->private_data, return -ENXIO);
+	rfile = file->private_data;
 	substream = rfile->output;
 	runtime = substream->runtime;
 	/* we cannot put an atomic message to our buffer */
@@ -1206,14 +1218,14 @@
 		spin_unlock_irq(&runtime->lock);
 		count1 = snd_rawmidi_kernel_write1(substream, buf, count, 0);
 		if (count1 < 0)
-			continue;
+			return result > 0 ? result : count1;
 		result += count1;
 		buf += count1;
 		if ((size_t)count1 < count && (file->f_flags & O_NONBLOCK))
 			break;
 		count -= count1;
 	}
-	while (file->f_flags & O_SYNC) {
+	if (file->f_flags & O_SYNC) {
 		spin_lock_irq(&runtime->lock);
 		while (runtime->avail != runtime->buffer_size) {
 			wait_queue_t wait;
@@ -1241,7 +1253,7 @@
 	snd_rawmidi_runtime_t *runtime;
 	unsigned int mask;
 
-	rfile = snd_magic_cast(snd_rawmidi_file_t, file->private_data, return 0);
+	rfile = file->private_data;
 	if (rfile->input != NULL) {
 		runtime = rfile->input->runtime;
 		runtime->trigger = 1;
@@ -1276,7 +1288,7 @@
 	snd_rawmidi_runtime_t *runtime;
 	struct list_head *list;
 
-	rmidi = snd_magic_cast(snd_rawmidi_t, entry->private_data, return);
+	rmidi = entry->private_data;
 	snd_iprintf(buffer, "%s\n\n", rmidi->name);
 	down(&rmidi->open_mutex);
 	if (rmidi->info_flags & SNDRV_RAWMIDI_INFO_OUTPUT) {
@@ -1353,7 +1365,7 @@
 
 	INIT_LIST_HEAD(&stream->substreams);
 	for (idx = 0; idx < count; idx++) {
-		substream = snd_kcalloc(sizeof(snd_rawmidi_substream_t), GFP_KERNEL);
+		substream = kcalloc(1, sizeof(*substream), GFP_KERNEL);
 		if (substream == NULL)
 			return -ENOMEM;
 		substream->stream = direction;
@@ -1396,7 +1408,7 @@
 	snd_assert(rrawmidi != NULL, return -EINVAL);
 	*rrawmidi = NULL;
 	snd_assert(card != NULL, return -ENXIO);
-	rmidi = snd_magic_kcalloc(snd_rawmidi_t, 0, GFP_KERNEL);
+	rmidi = kcalloc(1, sizeof(*rmidi), GFP_KERNEL);
 	if (rmidi == NULL)
 		return -ENOMEM;
 	rmidi->card = card;
@@ -1439,20 +1451,20 @@
 	snd_rawmidi_free_substreams(&rmidi->streams[SNDRV_RAWMIDI_STREAM_OUTPUT]);
 	if (rmidi->private_free)
 		rmidi->private_free(rmidi);
-	snd_magic_kfree(rmidi);
+	kfree(rmidi);
 	return 0;
 }
 
 static int snd_rawmidi_dev_free(snd_device_t *device)
 {
-	snd_rawmidi_t *rmidi = snd_magic_cast(snd_rawmidi_t, device->device_data, return -ENXIO);
+	snd_rawmidi_t *rmidi = device->device_data;
 	return snd_rawmidi_free(rmidi);
 }
 
 #if defined(CONFIG_SND_SEQUENCER) || (defined(MODULE) && defined(CONFIG_SND_SEQUENCER_MODULE))
 static void snd_rawmidi_dev_seq_free(snd_seq_device_t *device)
 {
-	snd_rawmidi_t *rmidi = snd_magic_cast(snd_rawmidi_t, device->private_data, return);
+	snd_rawmidi_t *rmidi = device->private_data;
 	rmidi->seq_dev = NULL;
 }
 #endif
@@ -1462,7 +1474,7 @@
 	int idx, err;
 	snd_info_entry_t *entry;
 	char name[16];
-	snd_rawmidi_t *rmidi = snd_magic_cast(snd_rawmidi_t, device->device_data, return -ENXIO);
+	snd_rawmidi_t *rmidi = device->device_data;
 
 	if (rmidi->device >= SNDRV_RAWMIDI_DEVICES)
 		return -ENOMEM;
@@ -1539,7 +1551,7 @@
 
 static int snd_rawmidi_dev_disconnect(snd_device_t *device)
 {
-	snd_rawmidi_t *rmidi = snd_magic_cast(snd_rawmidi_t, device->device_data, return -ENXIO);
+	snd_rawmidi_t *rmidi = device->device_data;
 	int idx;
 
 	down(&register_mutex);
@@ -1552,7 +1564,7 @@
 static int snd_rawmidi_dev_unregister(snd_device_t *device)
 {
 	int idx;
-	snd_rawmidi_t *rmidi = snd_magic_cast(snd_rawmidi_t, device->device_data, return -ENXIO);
+	snd_rawmidi_t *rmidi = device->device_data;
 
 	snd_assert(rmidi != NULL, return -ENXIO);
 	down(&register_mutex);
diff -Nru a/sound/core/seq/Makefile b/sound/core/seq/Makefile
--- a/sound/core/seq/Makefile	2004-10-18 14:57:03 -07:00
+++ b/sound/core/seq/Makefile	2004-10-18 14:57:03 -07:00
@@ -19,9 +19,6 @@
 snd-seq-dummy-objs := seq_dummy.o
 snd-seq-virmidi-objs := seq_virmidi.o
 
-RAWMIDI_OBJS = snd-seq-midi.o snd-seq-midi-event.o
-OPL3_OBJS = snd-seq-midi-event.o snd-seq-midi-emul.o snd-seq-instr.o
-
 #
 # this function returns:
 #   "m" - CONFIG_SND_SEQUENCER is m
@@ -38,53 +35,8 @@
 
 # Toplevel Module Dependency
 obj-$(CONFIG_SND_VIRMIDI) += snd-seq-virmidi.o snd-seq-midi-event.o
-obj-$(call sequencer,$(CONFIG_SND_SERIAL_U16550)) += $(RAWMIDI_OBJS)
-obj-$(call sequencer,$(CONFIG_SND_MTPAV)) += $(RAWMIDI_OBJS)
-obj-$(call sequencer,$(CONFIG_SND_MPU401)) += $(RAWMIDI_OBJS)
-obj-$(call sequencer,$(CONFIG_SND_ALS100)) += $(RAWMIDI_OBJS) $(OPL3_OBJS)
-obj-$(call sequencer,$(CONFIG_SND_AZT2320)) += $(RAWMIDI_OBJS) $(OPL3_OBJS)
-obj-$(call sequencer,$(CONFIG_SND_AZT3328)) += $(RAWMIDI_OBJS) $(OPL3_OBJS)
-obj-$(call sequencer,$(CONFIG_SND_DT019X)) += $(RAWMIDI_OBJS) $(OPL3_OBJS)
-obj-$(call sequencer,$(CONFIG_SND_ES18XX)) += $(RAWMIDI_OBJS) $(OPL3_OBJS)
-obj-$(call sequencer,$(CONFIG_SND_OPL3SA2)) += $(RAWMIDI_OBJS) $(OPL3_OBJS)
-obj-$(call sequencer,$(CONFIG_SND_AD1816A)) += $(RAWMIDI_OBJS) $(OPL3_OBJS)
-obj-$(call sequencer,$(CONFIG_SND_CS4231)) += $(RAWMIDI_OBJS)
-obj-$(call sequencer,$(CONFIG_SND_CS4232)) += $(RAWMIDI_OBJS) $(OPL3_OBJS)
-obj-$(call sequencer,$(CONFIG_SND_CS4236)) += $(RAWMIDI_OBJS) $(OPL3_OBJS)
-obj-$(call sequencer,$(CONFIG_SND_ES1688)) += $(RAWMIDI_OBJS) $(OPL3_OBJS)
-obj-$(call sequencer,$(CONFIG_SND_GUSCLASSIC)) += $(RAWMIDI_OBJS) $(OPL3_OBJS)
-obj-$(call sequencer,$(CONFIG_SND_GUSMAX)) += $(RAWMIDI_OBJS) $(OPL3_OBJS)
-obj-$(call sequencer,$(CONFIG_SND_GUSEXTREME)) += $(RAWMIDI_OBJS) $(OPL3_OBJS)
-obj-$(call sequencer,$(CONFIG_SND_INTERWAVE)) += $(RAWMIDI_OBJS) $(OPL3_OBJS)
-obj-$(call sequencer,$(CONFIG_SND_INTERWAVE_STB)) += $(RAWMIDI_OBJS) $(OPL3_OBJS)
-obj-$(call sequencer,$(CONFIG_SND_OPTI92X_AD1848)) += $(RAWMIDI_OBJS) $(OPL3_OBJS)
-obj-$(call sequencer,$(CONFIG_SND_OPTI92X_CS4231)) += $(RAWMIDI_OBJS) $(OPL3_OBJS)
-obj-$(call sequencer,$(CONFIG_SND_OPTI93X)) += $(RAWMIDI_OBJS) $(OPL3_OBJS)
-obj-$(call sequencer,$(CONFIG_SND_SB8)) += $(RAWMIDI_OBJS) $(OPL3_OBJS)
-obj-$(call sequencer,$(CONFIG_SND_SB16)) += $(RAWMIDI_OBJS) $(OPL3_OBJS)
-obj-$(call sequencer,$(CONFIG_SND_SBAWE)) += $(RAWMIDI_OBJS) $(OPL3_OBJS) snd-seq-virmidi.o
-obj-$(call sequencer,$(CONFIG_SND_ES968)) += $(RAWMIDI_OBJS)
-obj-$(call sequencer,$(CONFIG_SND_WAVEFRONT)) += $(RAWMIDI_OBJS) $(OPL3_OBJS)
-obj-$(call sequencer,$(CONFIG_SND_SSCAPE)) += $(RAWMIDI_OBJS)
-obj-$(call sequencer,$(CONFIG_SND_ALS4000)) += $(RAWMIDI_OBJS) $(OPL3_OBJS)
-obj-$(call sequencer,$(CONFIG_SND_CMIPCI)) += $(RAWMIDI_OBJS) $(OPL3_OBJS)
-obj-$(call sequencer,$(CONFIG_SND_CS4281)) += $(RAWMIDI_OBJS) $(OPL3_OBJS)
-obj-$(call sequencer,$(CONFIG_SND_ENS1370)) += $(RAWMIDI_OBJS)
-obj-$(call sequencer,$(CONFIG_SND_ENS1371)) += $(RAWMIDI_OBJS)
-obj-$(call sequencer,$(CONFIG_SND_ES1938)) += $(RAWMIDI_OBJS) $(OPL3_OBJS)
-obj-$(call sequencer,$(CONFIG_SND_ES1968)) += $(RAWMIDI_OBJS)
-obj-$(call sequencer,$(CONFIG_SND_FM801)) += $(RAWMIDI_OBJS) $(OPL3_OBJS)
-obj-$(call sequencer,$(CONFIG_SND_ICE1712)) += $(RAWMIDI_OBJS)
-obj-$(call sequencer,$(CONFIG_SND_ICE1724)) += $(RAWMIDI_OBJS)
-obj-$(call sequencer,$(CONFIG_SND_INTEL8X0)) += $(RAWMIDI_OBJS)
-obj-$(call sequencer,$(CONFIG_SND_SONICVIBES)) += $(RAWMIDI_OBJS) $(OPL3_OBJS)
-obj-$(call sequencer,$(CONFIG_SND_VIA82XX)) += $(RAWMIDI_OBJS)
-obj-$(call sequencer,$(CONFIG_SND_ALI5451)) += $(RAWMIDI_OBJS)
-obj-$(call sequencer,$(CONFIG_SND_CS46XX)) += $(RAWMIDI_OBJS)
-obj-$(call sequencer,$(CONFIG_SND_EMU10K1)) += $(RAWMIDI_OBJS) snd-seq-midi-emul.o snd-seq-virmidi.o
-obj-$(call sequencer,$(CONFIG_SND_TRIDENT)) += $(RAWMIDI_OBJS) snd-seq-midi-emul.o snd-seq-instr.o
-obj-$(call sequencer,$(CONFIG_SND_YMFPCI)) += $(RAWMIDI_OBJS) $(OPL3_OBJS)
-obj-$(call sequencer,$(CONFIG_SND_USB_AUDIO)) += $(RAWMIDI_OBJS)
-obj-$(call sequencer,$(CONFIG_SND_HDSP)) += $(RAWMIDI_OBJS)
-
-obj-m := $(sort $(obj-m))
+obj-$(call sequencer,$(CONFIG_SND_RAWMIDI)) += snd-seq-midi.o snd-seq-midi-event.o
+obj-$(call sequencer,$(CONFIG_SND_OPL3_LIB)) += snd-seq-midi-event.o snd-seq-midi-emul.o snd-seq-instr.o
+obj-$(call sequencer,$(CONFIG_SND_SBAWE)) += snd-seq-midi-emul.o snd-seq-virmidi.o
+obj-$(call sequencer,$(CONFIG_SND_EMU10K1)) += snd-seq-midi-emul.o snd-seq-virmidi.o
+obj-$(call sequencer,$(CONFIG_SND_TRIDENT)) += snd-seq-midi-emul.o snd-seq-instr.o
diff -Nru a/sound/core/seq/instr/Makefile b/sound/core/seq/instr/Makefile
--- a/sound/core/seq/instr/Makefile	2004-10-18 14:56:49 -07:00
+++ b/sound/core/seq/instr/Makefile	2004-10-18 14:56:49 -07:00
@@ -17,35 +17,7 @@
 sequencer = $(if $(subst y,,$(CONFIG_SND_SEQUENCER)),$(if $(1),m),$(if $(CONFIG_SND_SEQUENCER),$(1)))
 
 # Toplevel Module Dependency
-obj-$(call sequencer,$(CONFIG_SND_ALS100)) += snd-ainstr-fm.o
-obj-$(call sequencer,$(CONFIG_SND_AZT2320)) += snd-ainstr-fm.o
-obj-$(call sequencer,$(CONFIG_SND_AZT3328)) += snd-ainstr-fm.o
-obj-$(call sequencer,$(CONFIG_SND_DT019X)) += snd-ainstr-fm.o
-obj-$(call sequencer,$(CONFIG_SND_ES18XX)) += snd-ainstr-fm.o
-obj-$(call sequencer,$(CONFIG_SND_OPL3SA2)) += snd-ainstr-fm.o
-obj-$(call sequencer,$(CONFIG_SND_AD1816A)) += snd-ainstr-fm.o
-obj-$(call sequencer,$(CONFIG_SND_CS4232)) += snd-ainstr-fm.o
-obj-$(call sequencer,$(CONFIG_SND_CS4236)) += snd-ainstr-fm.o
-obj-$(call sequencer,$(CONFIG_SND_ES1688)) += snd-ainstr-fm.o
-obj-$(call sequencer,$(CONFIG_SND_GUSCLASSIC)) += snd-ainstr-iw.o snd-ainstr-gf1.o snd-ainstr-simple.o
-obj-$(call sequencer,$(CONFIG_SND_GUSMAX)) += snd-ainstr-iw.o snd-ainstr-gf1.o snd-ainstr-simple.o
-obj-$(call sequencer,$(CONFIG_SND_GUSEXTREME)) += snd-ainstr-iw.o snd-ainstr-gf1.o snd-ainstr-simple.o snd-ainstr-fm.o
-obj-$(call sequencer,$(CONFIG_SND_INTERWAVE)) += snd-ainstr-iw.o snd-ainstr-gf1.o snd-ainstr-simple.o
-obj-$(call sequencer,$(CONFIG_SND_INTERWAVE_STB)) += snd-ainstr-iw.o snd-ainstr-gf1.o snd-ainstr-simple.o
-obj-$(call sequencer,$(CONFIG_SND_OPTI92X_AD1848)) += snd-ainstr-fm.o
-obj-$(call sequencer,$(CONFIG_SND_OPTI92X_CS4231)) += snd-ainstr-fm.o
-obj-$(call sequencer,$(CONFIG_SND_OPTI93X)) += snd-ainstr-fm.o
-obj-$(call sequencer,$(CONFIG_SND_SB8)) += snd-ainstr-fm.o
-obj-$(call sequencer,$(CONFIG_SND_SB16)) += snd-ainstr-fm.o
-obj-$(call sequencer,$(CONFIG_SND_SBAWE)) += snd-ainstr-fm.o
-obj-$(call sequencer,$(CONFIG_SND_WAVEFRONT)) += snd-ainstr-fm.o
-obj-$(call sequencer,$(CONFIG_SND_ALS4000)) += snd-ainstr-fm.o
-obj-$(call sequencer,$(CONFIG_SND_CMIPCI)) += snd-ainstr-fm.o
-obj-$(call sequencer,$(CONFIG_SND_CS4281)) += snd-ainstr-fm.o
-obj-$(call sequencer,$(CONFIG_SND_ES1938)) += snd-ainstr-fm.o
-obj-$(call sequencer,$(CONFIG_SND_FM801)) += snd-ainstr-fm.o
-obj-$(call sequencer,$(CONFIG_SND_SONICVIBES)) += snd-ainstr-fm.o
+obj-$(call sequencer,$(CONFIG_SND_OPL3_LIB)) += snd-ainstr-fm.o
+obj-$(call sequencer,$(CONFIG_SND_OPL4_LIB)) += snd-ainstr-fm.o
+obj-$(call sequencer,$(CONFIG_SND_GUS_SYNTH)) += snd-ainstr-gf1.o snd-ainstr-simple.o snd-ainstr-iw.o
 obj-$(call sequencer,$(CONFIG_SND_TRIDENT)) += snd-ainstr-simple.o
-obj-$(call sequencer,$(CONFIG_SND_YMFPCI)) += snd-ainstr-fm.o
-
-obj-m := $(sort $(obj-m))
diff -Nru a/sound/core/seq/instr/ainstr_fm.c b/sound/core/seq/instr/ainstr_fm.c
--- a/sound/core/seq/instr/ainstr_fm.c	2004-10-18 14:56:29 -07:00
+++ b/sound/core/seq/instr/ainstr_fm.c	2004-10-18 14:56:29 -07:00
@@ -29,8 +29,6 @@
 MODULE_AUTHOR("Uros Bizjak <uros@kss-loka.si>");
 MODULE_DESCRIPTION("Advanced Linux Sound Architecture FM Instrument support.");
 MODULE_LICENSE("GPL");
-MODULE_CLASSES("{sound}");
-MODULE_SUPPORTED_DEVICE("sound");
 
 char *snd_seq_fm_id = SNDRV_SEQ_INSTR_ID_OPL2_3;
 
diff -Nru a/sound/core/seq/instr/ainstr_gf1.c b/sound/core/seq/instr/ainstr_gf1.c
--- a/sound/core/seq/instr/ainstr_gf1.c	2004-10-18 14:56:48 -07:00
+++ b/sound/core/seq/instr/ainstr_gf1.c	2004-10-18 14:56:48 -07:00
@@ -30,8 +30,6 @@
 MODULE_AUTHOR("Jaroslav Kysela <perex@suse.cz>");
 MODULE_DESCRIPTION("Advanced Linux Sound Architecture GF1 (GUS) Patch support.");
 MODULE_LICENSE("GPL");
-MODULE_CLASSES("{sound}");
-MODULE_SUPPORTED_DEVICE("sound");
 
 char *snd_seq_gf1_id = SNDRV_SEQ_INSTR_ID_GUS_PATCH;
 
@@ -64,7 +62,7 @@
 		return -EFAULT;
 	*data += sizeof(xp);
 	*len -= sizeof(xp);
-	wp = (gf1_wave_t *)snd_kcalloc(sizeof(*wp), gfp_mask);
+	wp = kcalloc(1, sizeof(*wp), gfp_mask);
 	if (wp == NULL)
 		return -ENOMEM;
 	wp->share_id[0] = le32_to_cpu(xp.share_id[0]);
diff -Nru a/sound/core/seq/instr/ainstr_iw.c b/sound/core/seq/instr/ainstr_iw.c
--- a/sound/core/seq/instr/ainstr_iw.c	2004-10-18 14:56:31 -07:00
+++ b/sound/core/seq/instr/ainstr_iw.c	2004-10-18 14:56:31 -07:00
@@ -30,8 +30,6 @@
 MODULE_AUTHOR("Jaroslav Kysela <perex@suse.cz>");
 MODULE_DESCRIPTION("Advanced Linux Sound Architecture IWFFFF support.");
 MODULE_LICENSE("GPL");
-MODULE_CLASSES("{sound}");
-MODULE_SUPPORTED_DEVICE("sound");
 
 char *snd_seq_iwffff_id = SNDRV_SEQ_INSTR_ID_INTERWAVE;
 
@@ -96,7 +94,7 @@
 		points_size = (le16_to_cpu(rx.nattack) + le16_to_cpu(rx.nrelease)) * 2 * sizeof(__u16);
 		if (points_size > *len)
 			return -EINVAL;
-		rp = (iwffff_env_record_t *)snd_kcalloc(sizeof(*rp) + points_size, gfp_mask);
+		rp = kcalloc(1, sizeof(*rp) + points_size, gfp_mask);
 		if (rp == NULL)
 			return -ENOMEM;
 		rp->nattack = le16_to_cpu(rx.nattack);
@@ -142,7 +140,7 @@
 		return -EFAULT;
 	*data += sizeof(xp);
 	*len -= sizeof(xp);
-	wp = (iwffff_wave_t *)snd_kcalloc(sizeof(*wp), gfp_mask);
+	wp = kcalloc(1, sizeof(*wp), gfp_mask);
 	if (wp == NULL)
 		return -ENOMEM;
 	wp->share_id[0] = le32_to_cpu(xp.share_id[0]);
@@ -275,7 +273,7 @@
 			snd_seq_iwffff_instr_free(ops, ip, atomic);
 			return -EINVAL;
 		}
-		lp = (iwffff_layer_t *)snd_kcalloc(sizeof(*lp), gfp_mask);
+		lp = kcalloc(1, sizeof(*lp), gfp_mask);
 		if (lp == NULL) {
 			snd_seq_iwffff_instr_free(ops, ip, atomic);
 			return -ENOMEM;
diff -Nru a/sound/core/seq/instr/ainstr_simple.c b/sound/core/seq/instr/ainstr_simple.c
--- a/sound/core/seq/instr/ainstr_simple.c	2004-10-18 14:56:49 -07:00
+++ b/sound/core/seq/instr/ainstr_simple.c	2004-10-18 14:56:49 -07:00
@@ -30,8 +30,6 @@
 MODULE_AUTHOR("Jaroslav Kysela <perex@suse.cz>");
 MODULE_DESCRIPTION("Advanced Linux Sound Architecture Simple Instrument support.");
 MODULE_LICENSE("GPL");
-MODULE_CLASSES("{sound}");
-MODULE_SUPPORTED_DEVICE("sound");
 
 char *snd_seq_simple_id = SNDRV_SEQ_INSTR_ID_SIMPLE;
 
diff -Nru a/sound/core/seq/oss/seq_oss.c b/sound/core/seq/oss/seq_oss.c
--- a/sound/core/seq/oss/seq_oss.c	2004-10-18 14:56:49 -07:00
+++ b/sound/core/seq/oss/seq_oss.c	2004-10-18 14:56:49 -07:00
@@ -22,6 +22,7 @@
 
 #include <sound/driver.h>
 #include <linux/init.h>
+#include <linux/smp_lock.h>
 #include <linux/moduleparam.h>
 #include <sound/core.h>
 #include <sound/minors.h>
@@ -35,7 +36,6 @@
 MODULE_AUTHOR("Takashi Iwai <tiwai@suse.de>");
 MODULE_DESCRIPTION("OSS-compatible sequencer module");
 MODULE_LICENSE("GPL");
-MODULE_CLASSES("{sound}");
 /* Takashi says this is really only for sound-service-0-, but this is OK. */
 MODULE_ALIAS_SNDRV_MINOR(SNDRV_MINOR_OSS_SEQUENCER);
 MODULE_ALIAS_SNDRV_MINOR(SNDRV_MINOR_OSS_MUSIC);
@@ -177,9 +177,14 @@
 odev_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
 {
 	seq_oss_devinfo_t *dp;
+	int err;
 	dp = file->private_data;
 	snd_assert(dp != NULL, return -EIO);
-	return snd_seq_oss_ioctl(dp, cmd, arg);
+	/* FIXME: need to unlock BKL to allow preemption */
+	unlock_kernel();
+	err = snd_seq_oss_ioctl(dp, cmd, arg);
+	lock_kernel();
+	return err;
 }
 
 
diff -Nru a/sound/core/seq/oss/seq_oss_init.c b/sound/core/seq/oss/seq_oss_init.c
--- a/sound/core/seq/oss/seq_oss_init.c	2004-10-18 14:55:54 -07:00
+++ b/sound/core/seq/oss/seq_oss_init.c	2004-10-18 14:55:54 -07:00
@@ -183,7 +183,7 @@
 	int i, rc;
 	seq_oss_devinfo_t *dp;
 
-	if ((dp = snd_kcalloc(sizeof(*dp), GFP_KERNEL)) == NULL) {
+	if ((dp = kcalloc(1, sizeof(*dp), GFP_KERNEL)) == NULL) {
 		snd_printk(KERN_ERR "can't malloc device info\n");
 		return -ENOMEM;
 	}
@@ -211,7 +211,7 @@
 	snd_seq_oss_midi_setup(dp);
 
 	if (dp->synth_opened == 0 && dp->max_mididev == 0) {
-		snd_printk(KERN_ERR "no device found\n");
+		/* snd_printk(KERN_ERR "no device found\n"); */
 		rc = -ENODEV;
 		goto _error;
 	}
diff -Nru a/sound/core/seq/oss/seq_oss_ioctl.c b/sound/core/seq/oss/seq_oss_ioctl.c
--- a/sound/core/seq/oss/seq_oss_ioctl.c	2004-10-18 14:55:54 -07:00
+++ b/sound/core/seq/oss/seq_oss_ioctl.c	2004-10-18 14:55:54 -07:00
@@ -28,16 +28,54 @@
 #include "seq_oss_midi.h"
 #include "seq_oss_event.h"
 
+static int snd_seq_oss_synth_info_user(seq_oss_devinfo_t *dp, void __user *arg)
+{
+	struct synth_info info;
+
+	if (copy_from_user(&info, arg, sizeof(info)))
+		return -EFAULT;
+	if (snd_seq_oss_synth_make_info(dp, info.device, &info) < 0)
+		return -EINVAL;
+	if (copy_to_user(arg, &info, sizeof(info)))
+		return -EFAULT;
+	return 0;
+}
+
+static int snd_seq_oss_midi_info_user(seq_oss_devinfo_t *dp, void __user *arg)
+{
+	struct midi_info info;
+
+	if (copy_from_user(&info, arg, sizeof(info)))
+		return -EFAULT;
+	if (snd_seq_oss_midi_make_info(dp, info.device, &info) < 0)
+		return -EINVAL;
+	if (copy_to_user(arg, &info, sizeof(info)))
+		return -EFAULT;
+	return 0;
+}
+
+static int snd_seq_oss_oob_user(seq_oss_devinfo_t *dp, void __user *arg)
+{
+	unsigned char ev[8];
+	snd_seq_event_t tmpev;
+
+	if (copy_from_user(ev, arg, 8))
+		return -EFAULT;
+	memset(&tmpev, 0, sizeof(tmpev));
+	snd_seq_oss_fill_addr(dp, &tmpev, dp->addr.port, dp->addr.client);
+	tmpev.time.tick = 0;
+	if (! snd_seq_oss_process_event(dp, (evrec_t*)ev, &tmpev)) {
+		snd_seq_oss_dispatch(dp, &tmpev, 0, 0);
+	}
+	return 0;
+}
+
 int
 snd_seq_oss_ioctl(seq_oss_devinfo_t *dp, unsigned int cmd, unsigned long carg)
 {
 	int dev, val;
-	struct synth_info inf;
-	struct midi_info minf;
-	unsigned char ev[8];
 	void __user *arg = (void __user *)carg;
 	int __user *p = arg;
-	snd_seq_event_t tmpev;
 
 	switch (cmd) {
 	case SNDCTL_TMR_TIMEBASE:
@@ -124,35 +162,15 @@
 	case SNDCTL_SYNTH_INFO:
 	case SNDCTL_SYNTH_ID:
 		debug_printk(("synth info\n"));
-		if (copy_from_user(&inf, arg, sizeof(inf)))
-			return -EFAULT;
-		if (snd_seq_oss_synth_make_info(dp, inf.device, &inf) < 0)
-			return -EINVAL;
-		if (copy_to_user(arg, &inf, sizeof(inf)))
-			return -EFAULT;
-		return 0;
+		return snd_seq_oss_synth_info_user(dp, arg);
 
 	case SNDCTL_SEQ_OUTOFBAND:
-		debug_printk(("out of bound\n"));
-		if (copy_from_user(ev, arg, 8))
-			return -EFAULT;
-		memset(&tmpev, 0, sizeof(tmpev));
-		snd_seq_oss_fill_addr(dp, &tmpev, dp->addr.port, dp->addr.client);
-		tmpev.time.tick = 0;
-		if (! snd_seq_oss_process_event(dp, (evrec_t*)ev, &tmpev)) {
-			snd_seq_oss_dispatch(dp, &tmpev, 0, 0);
-		}
-		return 0;
+		debug_printk(("out of band\n"));
+		return snd_seq_oss_oob_user(dp, arg);
 
 	case SNDCTL_MIDI_INFO:
 		debug_printk(("midi info\n"));
-		if (copy_from_user(&minf, arg, sizeof(minf)))
-			return -EFAULT;
-		if (snd_seq_oss_midi_make_info(dp, minf.device, &minf) < 0)
-			return -EINVAL;
-		if (copy_to_user(arg, &minf, sizeof(minf)))
-			return -EFAULT;
-		return 0;
+		return snd_seq_oss_midi_info_user(dp, arg);
 
 	case SNDCTL_SEQ_THRESHOLD:
 		debug_printk(("threshold\n"));
diff -Nru a/sound/core/seq/oss/seq_oss_midi.c b/sound/core/seq/oss/seq_oss_midi.c
--- a/sound/core/seq/oss/seq_oss_midi.c	2004-10-18 14:55:53 -07:00
+++ b/sound/core/seq/oss/seq_oss_midi.c	2004-10-18 14:55:53 -07:00
@@ -171,7 +171,7 @@
 	/*
 	 * allocate midi info record
 	 */
-	if ((mdev = snd_kcalloc(sizeof(*mdev), GFP_KERNEL)) == NULL) {
+	if ((mdev = kcalloc(1, sizeof(*mdev), GFP_KERNEL)) == NULL) {
 		snd_printk(KERN_ERR "can't malloc midi info\n");
 		return -ENOMEM;
 	}
diff -Nru a/sound/core/seq/oss/seq_oss_readq.c b/sound/core/seq/oss/seq_oss_readq.c
--- a/sound/core/seq/oss/seq_oss_readq.c	2004-10-18 14:56:20 -07:00
+++ b/sound/core/seq/oss/seq_oss_readq.c	2004-10-18 14:56:20 -07:00
@@ -45,12 +45,12 @@
 {
 	seq_oss_readq_t *q;
 
-	if ((q = snd_kcalloc(sizeof(*q), GFP_KERNEL)) == NULL) {
+	if ((q = kcalloc(1, sizeof(*q), GFP_KERNEL)) == NULL) {
 		snd_printk(KERN_ERR "can't malloc read queue\n");
 		return NULL;
 	}
 
-	if ((q->q = snd_kcalloc(sizeof(evrec_t) * maxlen, GFP_KERNEL)) == NULL) {
+	if ((q->q = kcalloc(maxlen, sizeof(evrec_t), GFP_KERNEL)) == NULL) {
 		snd_printk(KERN_ERR "can't malloc read queue buffer\n");
 		kfree(q);
 		return NULL;
@@ -74,7 +74,6 @@
 snd_seq_oss_readq_delete(seq_oss_readq_t *q)
 {
 	if (q) {
-		snd_seq_oss_readq_clear(q);	/* to be sure */
 		if (q->q)
 			kfree(q->q);
 		kfree(q);
@@ -106,9 +105,9 @@
 	evrec_t rec;
 	int result;
 
+	memset(&rec, 0, sizeof(rec));
 	rec.c[0] = SEQ_MIDIPUTC;
 	rec.c[2] = dev;
-	rec.c[3] = 0;
 
 	while (len-- > 0) {
 		rec.c[1] = *data++;
@@ -134,7 +133,7 @@
 		return -ENOMEM;
 	}
 
-	memcpy(&q->q[q->tail], ev, ev_length(ev));
+	memcpy(&q->q[q->tail], ev, sizeof(*ev));
 	q->tail = (q->tail + 1) % q->maxlen;
 	q->qlen++;
 
@@ -150,50 +149,37 @@
 
 /*
  * pop queue
+ * caller must hold lock
  */
-evrec_t *
-snd_seq_oss_readq_pick(seq_oss_readq_t *q, int blocking, unsigned long *rflags)
+int
+snd_seq_oss_readq_pick(seq_oss_readq_t *q, evrec_t *rec)
 {
-	evrec_t *p;
-
-	spin_lock_irqsave(&q->lock, *rflags);
-	if (q->qlen == 0) {
-		if (blocking) {
-			spin_unlock(&q->lock);
-			interruptible_sleep_on_timeout(&q->midi_sleep,
-						       q->pre_event_timeout);
-			spin_lock(&q->lock);
-		}
-		if (q->qlen == 0) {
-			spin_unlock_irqrestore(&q->lock, *rflags);
-			return NULL;
-		}
-	}
-	p = q->q + q->head;
-
-	return p;
+	if (q->qlen == 0)
+		return -EAGAIN;
+	memcpy(rec, &q->q[q->head], sizeof(*rec));
+	return 0;
 }
 
 /*
- * unlock queue
+ * sleep until ready
  */
 void
-snd_seq_oss_readq_unlock(seq_oss_readq_t *q, unsigned long flags)
+snd_seq_oss_readq_wait(seq_oss_readq_t *q)
 {
-	spin_unlock_irqrestore(&q->lock, flags);
+	interruptible_sleep_on_timeout(&q->midi_sleep, q->pre_event_timeout);
 }
 
 /*
- * drain one record and unlock queue
+ * drain one record
+ * caller must hold lock
  */
 void
-snd_seq_oss_readq_free(seq_oss_readq_t *q, unsigned long flags)
+snd_seq_oss_readq_free(seq_oss_readq_t *q)
 {
 	if (q->qlen > 0) {
 		q->head = (q->head + 1) % q->maxlen;
 		q->qlen--;
 	}
-	spin_unlock_irqrestore(&q->lock, flags);
 }
 
 /*
@@ -215,6 +201,7 @@
 {
 	if (curt != q->input_time) {
 		evrec_t rec;
+		memset(&rec, 0, sizeof(rec));
 		switch (seq_mode) {
 		case SNDRV_SEQ_OSS_MODE_SYNTH:
 			rec.echo = (curt << 8) | SEQ_WAIT;
diff -Nru a/sound/core/seq/oss/seq_oss_readq.h b/sound/core/seq/oss/seq_oss_readq.h
--- a/sound/core/seq/oss/seq_oss_readq.h	2004-10-18 14:56:17 -07:00
+++ b/sound/core/seq/oss/seq_oss_readq.h	2004-10-18 14:56:17 -07:00
@@ -46,8 +46,11 @@
 int snd_seq_oss_readq_puts(seq_oss_readq_t *readq, int dev, unsigned char *data, int len);
 int snd_seq_oss_readq_put_event(seq_oss_readq_t *readq, evrec_t *ev);
 int snd_seq_oss_readq_put_timestamp(seq_oss_readq_t *readq, unsigned long curt, int seq_mode);
-evrec_t *snd_seq_oss_readq_pick(seq_oss_readq_t *q, int blocking, unsigned long *rflags);
-void snd_seq_oss_readq_unlock(seq_oss_readq_t *q, unsigned long flags);
-void snd_seq_oss_readq_free(seq_oss_readq_t *q, unsigned long flags);
+int snd_seq_oss_readq_pick(seq_oss_readq_t *q, evrec_t *rec);
+void snd_seq_oss_readq_wait(seq_oss_readq_t *q);
+void snd_seq_oss_readq_free(seq_oss_readq_t *q);
+
+#define snd_seq_oss_readq_lock(q, flags) spin_lock_irqsave(&(q)->lock, flags)
+#define snd_seq_oss_readq_unlock(q, flags) spin_unlock_irqrestore(&(q)->lock, flags)
 
 #endif
diff -Nru a/sound/core/seq/oss/seq_oss_rw.c b/sound/core/seq/oss/seq_oss_rw.c
--- a/sound/core/seq/oss/seq_oss_rw.c	2004-10-18 14:55:54 -07:00
+++ b/sound/core/seq/oss/seq_oss_rw.c	2004-10-18 14:55:54 -07:00
@@ -44,35 +44,47 @@
 snd_seq_oss_read(seq_oss_devinfo_t *dp, char __user *buf, int count)
 {
 	seq_oss_readq_t *readq = dp->readq;
-	int cnt, pos;
-	evrec_t *q;
+	int result = 0, err = 0;
+	int ev_len;
+	evrec_t rec;
 	unsigned long flags;
 
 	if (readq == NULL || ! is_read_mode(dp->file_mode))
-		return -EIO;
+		return -ENXIO;
 
-	/* copy queued events to read buffer */
-	cnt = count;
-	pos = 0;
-	q = snd_seq_oss_readq_pick(readq, !is_nonblock_mode(dp->file_mode), &flags);
-	if (q == NULL)
-		return 0;
-	do {
-		int ev_len;
-		/* tansfer the data */
-		ev_len = ev_length(q);
-		if (copy_to_user(buf + pos, q, ev_len)) {
+	while (count >= SHORT_EVENT_SIZE) {
+		snd_seq_oss_readq_lock(readq, flags);
+		err = snd_seq_oss_readq_pick(readq, &rec);
+		if (err == -EAGAIN &&
+		    !is_nonblock_mode(dp->file_mode) && result == 0) {
+			snd_seq_oss_readq_unlock(readq, flags);
+			snd_seq_oss_readq_wait(readq);
+			snd_seq_oss_readq_lock(readq, flags);
+			if (signal_pending(current))
+				err = -ERESTARTSYS;
+			else
+				err = snd_seq_oss_readq_pick(readq, &rec);
+		}
+		if (err < 0) {
 			snd_seq_oss_readq_unlock(readq, flags);
 			break;
 		}
-		snd_seq_oss_readq_free(readq, flags);
-		pos += ev_len;
-		cnt -= ev_len;
-		if (cnt < ev_len)
+		ev_len = ev_length(&rec);
+		if (ev_len < count) {
+			snd_seq_oss_readq_unlock(readq, flags);
 			break;
-	} while ((q = snd_seq_oss_readq_pick(readq, 0, &flags)) != NULL);
-
-	return count - cnt;
+		}
+		snd_seq_oss_readq_free(readq);
+		snd_seq_oss_readq_unlock(readq, flags);
+		if (copy_to_user(buf, &rec, ev_len)) {
+			err = -EFAULT;
+			break;
+		}
+		result += ev_len;
+		buf += ev_len;
+		count -= ev_len;
+	}
+	return result > 0 ? result : err;
 }
 
 
@@ -83,56 +95,64 @@
 int
 snd_seq_oss_write(seq_oss_devinfo_t *dp, const char __user *buf, int count, struct file *opt)
 {
-	int rc, c, p, ev_size;
+	int result = 0, err = 0;
+	int ev_size, fmt;
 	evrec_t rec;
 
 	if (! is_write_mode(dp->file_mode) || dp->writeq == NULL)
-		return -EIO;
+		return -ENXIO;
 
-	c = count;
-	p = 0;
-	while (c >= SHORT_EVENT_SIZE) {
-		if (copy_from_user(rec.c, buf + p, SHORT_EVENT_SIZE))
+	while (count >= SHORT_EVENT_SIZE) {
+		if (copy_from_user(&rec, buf, SHORT_EVENT_SIZE)) {
+			err = -EFAULT;
 			break;
-		p += SHORT_EVENT_SIZE;
-
+		}
 		if (rec.s.code == SEQ_FULLSIZE) {
 			/* load patch */
-			int fmt = (*(unsigned short *)rec.c) & 0xffff;
-			return snd_seq_oss_synth_load_patch(dp, rec.s.dev, fmt, buf, p, c);
-
+			if (result > 0) {
+				err = -EINVAL;
+				break;
+			}
+			fmt = (*(unsigned short *)rec.c) & 0xffff;
+			/* FIXME the return value isn't correct */
+			return snd_seq_oss_synth_load_patch(dp, rec.s.dev,
+							    fmt, buf, 0, count);
 		}
 		if (ev_is_long(&rec)) {
 			/* extended code */
 			if (rec.s.code == SEQ_EXTENDED &&
-			    dp->seq_mode == SNDRV_SEQ_OSS_MODE_MUSIC)
-				return -EINVAL;
+			    dp->seq_mode == SNDRV_SEQ_OSS_MODE_MUSIC) {
+				err = -EINVAL;
+				break;
+			}
 			ev_size = LONG_EVENT_SIZE;
-			if (c < ev_size)
+			if (count < ev_size)
 				break;
 			/* copy the reset 4 bytes */
-			if (copy_from_user(rec.c + SHORT_EVENT_SIZE, buf + p,
-					   LONG_EVENT_SIZE - SHORT_EVENT_SIZE))
+			if (copy_from_user(rec.c + SHORT_EVENT_SIZE,
+					   buf + SHORT_EVENT_SIZE,
+					   LONG_EVENT_SIZE - SHORT_EVENT_SIZE)) {
+				err = -EFAULT;
 				break;
-			p += LONG_EVENT_SIZE - SHORT_EVENT_SIZE;
-
+			}
 		} else {
 			/* old-type code */
-			if (dp->seq_mode == SNDRV_SEQ_OSS_MODE_MUSIC)
-				return -EINVAL;
+			if (dp->seq_mode == SNDRV_SEQ_OSS_MODE_MUSIC) {
+				err = -EINVAL;
+				break;
+			}
 			ev_size = SHORT_EVENT_SIZE;
 		}
 
 		/* insert queue */
-		if ((rc = insert_queue(dp, &rec, opt)) < 0)
+		if ((err = insert_queue(dp, &rec, opt)) < 0)
 			break;
 
-		c -= ev_size;
+		result += ev_size;
+		buf += ev_size;
+		count -= ev_size;
 	}
-
-	if (count == c && is_nonblock_mode(dp->file_mode))
-		return -EAGAIN;
-	return count - c;
+	return result > 0 ? result : err;
 }
 
 
diff -Nru a/sound/core/seq/oss/seq_oss_synth.c b/sound/core/seq/oss/seq_oss_synth.c
--- a/sound/core/seq/oss/seq_oss_synth.c	2004-10-18 14:55:54 -07:00
+++ b/sound/core/seq/oss/seq_oss_synth.c	2004-10-18 14:55:54 -07:00
@@ -103,7 +103,7 @@
 	snd_seq_oss_reg_t *reg = SNDRV_SEQ_DEVICE_ARGPTR(dev);
 	unsigned long flags;
 
-	if ((rec = snd_kcalloc(sizeof(*rec), GFP_KERNEL)) == NULL) {
+	if ((rec = kcalloc(1, sizeof(*rec), GFP_KERNEL)) == NULL) {
 		snd_printk(KERN_ERR "can't malloc synth info\n");
 		return -ENOMEM;
 	}
@@ -244,7 +244,9 @@
 		}
 		info->nr_voices = rec->nr_voices;
 		if (info->nr_voices > 0) {
-			info->ch = snd_kcalloc(sizeof(seq_oss_chinfo_t) * info->nr_voices, GFP_KERNEL);
+			info->ch = kcalloc(info->nr_voices, sizeof(seq_oss_chinfo_t), GFP_KERNEL);
+			if (!info->ch)
+				BUG();
 			reset_channels(info);
 		}
 		debug_printk(("synth %d assigned\n", i));
@@ -505,7 +507,7 @@
 
 	sysex = dp->synths[dev].sysex;
 	if (sysex == NULL) {
-		sysex = snd_kcalloc(sizeof(*sysex), GFP_KERNEL);
+		sysex = kcalloc(1, sizeof(*sysex), GFP_KERNEL);
 		if (sysex == NULL)
 			return -ENOMEM;
 		dp->synths[dev].sysex = sysex;
diff -Nru a/sound/core/seq/oss/seq_oss_timer.c b/sound/core/seq/oss/seq_oss_timer.c
--- a/sound/core/seq/oss/seq_oss_timer.c	2004-10-18 14:56:20 -07:00
+++ b/sound/core/seq/oss/seq_oss_timer.c	2004-10-18 14:56:20 -07:00
@@ -46,7 +46,7 @@
 {
 	seq_oss_timer_t *rec;
 
-	rec = snd_kcalloc(sizeof(*rec), GFP_KERNEL);
+	rec = kcalloc(1, sizeof(*rec), GFP_KERNEL);
 	if (rec == NULL)
 		return NULL;
 
@@ -168,7 +168,7 @@
 	tmprec.queue = dp->queue;
 	tmprec.ppq = timer->ppq;
 	tmprec.tempo = timer->tempo;
-	snd_seq_kernel_client_ctl(dp->cseq, SNDRV_SEQ_IOCTL_SET_QUEUE_TEMPO, &tmprec);
+	snd_seq_set_queue_tempo(dp->cseq, &tmprec);
 
 	send_timer_event(dp, SNDRV_SEQ_EVENT_START, 0);
 	timer->running = 1;
diff -Nru a/sound/core/seq/oss/seq_oss_writeq.c b/sound/core/seq/oss/seq_oss_writeq.c
--- a/sound/core/seq/oss/seq_oss_writeq.c	2004-10-18 14:56:49 -07:00
+++ b/sound/core/seq/oss/seq_oss_writeq.c	2004-10-18 14:56:49 -07:00
@@ -37,7 +37,7 @@
 	seq_oss_writeq_t *q;
 	snd_seq_client_pool_t pool;
 
-	if ((q = snd_kcalloc(sizeof(*q), GFP_KERNEL)) == NULL)
+	if ((q = kcalloc(1, sizeof(*q), GFP_KERNEL)) == NULL)
 		return NULL;
 	q->dp = dp;
 	q->maxlen = maxlen;
diff -Nru a/sound/core/seq/seq.c b/sound/core/seq/seq.c
--- a/sound/core/seq/seq.c	2004-10-18 14:56:49 -07:00
+++ b/sound/core/seq/seq.c	2004-10-18 14:56:49 -07:00
@@ -50,8 +50,6 @@
 MODULE_AUTHOR("Frank van de Pol <fvdpol@coil.demon.nl>, Jaroslav Kysela <perex@suse.cz>");
 MODULE_DESCRIPTION("Advanced Linux Sound Architecture sequencer.");
 MODULE_LICENSE("GPL");
-MODULE_CLASSES("{sound}");
-MODULE_SUPPORTED_DEVICE("sound");
 
 static int boot_devs;
 module_param_array(seq_client_load, int, boot_devs, 0444);
@@ -133,6 +131,7 @@
 EXPORT_SYMBOL(snd_seq_kernel_client_dispatch);
 EXPORT_SYMBOL(snd_seq_kernel_client_ctl);
 EXPORT_SYMBOL(snd_seq_kernel_client_write_poll);
+EXPORT_SYMBOL(snd_seq_set_queue_tempo);
   /* seq_memory.c */
 EXPORT_SYMBOL(snd_seq_expand_var_event);
 EXPORT_SYMBOL(snd_seq_dump_var_event);
diff -Nru a/sound/core/seq/seq_clientmgr.c b/sound/core/seq/seq_clientmgr.c
--- a/sound/core/seq/seq_clientmgr.c	2004-10-18 14:55:55 -07:00
+++ b/sound/core/seq/seq_clientmgr.c	2004-10-18 14:55:55 -07:00
@@ -23,6 +23,7 @@
 
 #include <sound/driver.h>
 #include <linux/init.h>
+#include <linux/smp_lock.h>
 #include <linux/slab.h>
 #include <sound/core.h>
 #include <sound/minors.h>
@@ -202,7 +203,7 @@
 	client_t *client;
 
 	/* init client data */
-	client = snd_kcalloc(sizeof(client_t), GFP_KERNEL);
+	client = kcalloc(1, sizeof(*client), GFP_KERNEL);
 	if (client == NULL)
 		return NULL;
 	client->pool = snd_seq_pool_new(poolsize);
@@ -547,36 +548,6 @@
 
 
 /*
- * expand a quoted event.
- */
-static int expand_quoted_event(snd_seq_event_t *event)
-{
-	snd_seq_event_t *quoted;
-
-	quoted = event->data.quote.event;
-	if (quoted == NULL) {
-		snd_printd("seq: quoted event is NULL\n");
-		return -EINVAL;
-	}
-
-	event->type = quoted->type;
-	event->tag = quoted->tag;
-	event->source = quoted->source;
-	/* don't use quoted destination */
-	event->data = quoted->data;
-	/* use quoted timestamp only if subscription/port didn't update it */
-	if (event->queue == SNDRV_SEQ_QUEUE_DIRECT) {
-		event->flags = quoted->flags;
-		event->queue = quoted->queue;
-		event->time = quoted->time;
-	} else {
-		event->flags = (event->flags & SNDRV_SEQ_TIME_STAMP_MASK)
-			| (quoted->flags & ~SNDRV_SEQ_TIME_STAMP_MASK);
-	}
-	return 0;
-}
-
-/*
  * deliver an event to the specified destination.
  * if filter is non-zero, client filter bitmap is tested.
  *
@@ -590,7 +561,7 @@
 	client_t *dest = NULL;
 	client_port_t *dest_port = NULL;
 	int result = -ENOENT;
-	int direct, quoted = 0;
+	int direct;
 
 	direct = snd_seq_ev_is_direct(event);
 
@@ -611,14 +582,6 @@
 		update_timestamp_of_queue(event, dest_port->time_queue,
 					  dest_port->time_real);
 
-	if (event->type == SNDRV_SEQ_EVENT_KERNEL_QUOTE) {
-		quoted = 1;
-		if (expand_quoted_event(event) < 0) {
-			result = 0; /* do not send bounce error */
-			goto __skip;
-		}
-	}
-
 	switch (dest->type) {
 	case USER_CLIENT:
 		if (dest->data.user.fifo)
@@ -641,14 +604,7 @@
 		snd_seq_client_unlock(dest);
 
 	if (result < 0 && !direct) {
-		if (quoted) {
-			/* return directly to the original source */
-			dest = snd_seq_client_use_ptr(event->source.client);
-			result = bounce_error_event(dest, event, result, atomic, hop);
-			snd_seq_client_unlock(dest);
-		} else {
-			result = bounce_error_event(client, event, result, atomic, hop);
-		}
+		result = bounce_error_event(client, event, result, atomic, hop);
 	}
 	return result;
 }
@@ -1694,6 +1650,13 @@
 
 
 /* SET_QUEUE_TEMPO ioctl() */
+int snd_seq_set_queue_tempo(int client, snd_seq_queue_tempo_t *tempo)
+{
+	if (!snd_seq_queue_check_access(tempo->queue, client))
+		return -EPERM;
+	return snd_seq_queue_timer_set_tempo(tempo->queue, client, tempo);
+}
+
 static int snd_seq_ioctl_set_queue_tempo(client_t * client, void __user *arg)
 {
 	int result;
@@ -1702,15 +1665,8 @@
 	if (copy_from_user(&tempo, arg, sizeof(tempo)))
 		return -EFAULT;
 
-	if (snd_seq_queue_check_access(tempo.queue, client->number)) {
-		result = snd_seq_queue_timer_set_tempo(tempo.queue, client->number, &tempo);
-		if (result < 0)
-			return result;
-	} else {
-		return -EPERM;
-	}	
-
-	return 0;
+	result = snd_seq_set_queue_tempo(client->number, &tempo);
+	return result < 0 ? result : 0;
 }
 
 
@@ -2176,10 +2132,15 @@
 			 unsigned int cmd, unsigned long arg)
 {
 	client_t *client = (client_t *) file->private_data;
+	int err;
 
 	snd_assert(client != NULL, return -ENXIO);
 		
-	return snd_seq_do_ioctl(client, cmd, (void __user *) arg);
+	/* FIXME: need to unlock BKL to allow preemption */
+	unlock_kernel();
+	err = snd_seq_do_ioctl(client, cmd, (void __user *) arg);
+	lock_kernel();
+	return err;
 }
 
 
@@ -2261,8 +2222,7 @@
 
 	if (ev->type == SNDRV_SEQ_EVENT_NONE)
 		return 0; /* ignore this */
-	if (ev->type == SNDRV_SEQ_EVENT_KERNEL_ERROR ||
-	    ev->type == SNDRV_SEQ_EVENT_KERNEL_QUOTE)
+	if (ev->type == SNDRV_SEQ_EVENT_KERNEL_ERROR)
 		return -EINVAL; /* quoted events can't be enqueued */
 
 	/* fill in client number */
diff -Nru a/sound/core/seq/seq_device.c b/sound/core/seq/seq_device.c
--- a/sound/core/seq/seq_device.c	2004-10-18 14:56:18 -07:00
+++ b/sound/core/seq/seq_device.c	2004-10-18 14:56:18 -07:00
@@ -48,8 +48,6 @@
 MODULE_AUTHOR("Takashi Iwai <tiwai@suse.de>");
 MODULE_DESCRIPTION("ALSA sequencer device management");
 MODULE_LICENSE("GPL");
-MODULE_CLASSES("{sound}");
-MODULE_SUPPORTED_DEVICE("sound");
 
 /*
  * driver list
@@ -181,7 +179,7 @@
 	if (ops == NULL)
 		return -ENOMEM;
 
-	dev = snd_magic_kcalloc(snd_seq_device_t, sizeof(*dev) + argsize, GFP_KERNEL);
+	dev = kcalloc(1, sizeof(*dev)*2 + argsize, GFP_KERNEL);
 	if (dev == NULL) {
 		unlock_driver(ops);
 		return -ENOMEM;
@@ -235,7 +233,7 @@
 	free_device(dev, ops);
 	if (dev->private_free)
 		dev->private_free(dev);
-	snd_magic_kfree(dev);
+	kfree(dev);
 
 	unlock_driver(ops);
 
@@ -244,7 +242,7 @@
 
 static int snd_seq_device_dev_free(snd_device_t *device)
 {
-	snd_seq_device_t *dev = snd_magic_cast(snd_seq_device_t, device->device_data, return -ENXIO);
+	snd_seq_device_t *dev = device->device_data;
 	return snd_seq_device_free(dev);
 }
 
@@ -253,7 +251,7 @@
  */
 static int snd_seq_device_dev_register(snd_device_t *device)
 {
-	snd_seq_device_t *dev = snd_magic_cast(snd_seq_device_t, device->device_data, return -ENXIO);
+	snd_seq_device_t *dev = device->device_data;
 	ops_list_t *ops;
 
 	ops = find_driver(dev->id, 0);
@@ -275,7 +273,7 @@
  */
 static int snd_seq_device_dev_disconnect(snd_device_t *device)
 {
-	snd_seq_device_t *dev = snd_magic_cast(snd_seq_device_t, device->device_data, return -ENXIO);
+	snd_seq_device_t *dev = device->device_data;
 	ops_list_t *ops;
 
 	ops = find_driver(dev->id, 0);
@@ -293,7 +291,7 @@
  */
 static int snd_seq_device_dev_unregister(snd_device_t *device)
 {
-	snd_seq_device_t *dev = snd_magic_cast(snd_seq_device_t, device->device_data, return -ENXIO);
+	snd_seq_device_t *dev = device->device_data;
 	return snd_seq_device_free(dev);
 }
 
diff -Nru a/sound/core/seq/seq_dummy.c b/sound/core/seq/seq_dummy.c
--- a/sound/core/seq/seq_dummy.c	2004-10-18 14:56:32 -07:00
+++ b/sound/core/seq/seq_dummy.c	2004-10-18 14:56:32 -07:00
@@ -63,8 +63,6 @@
 MODULE_AUTHOR("Takashi Iwai <tiwai@suse.de>");
 MODULE_DESCRIPTION("ALSA sequencer MIDI-through client");
 MODULE_LICENSE("GPL");
-MODULE_CLASSES("{sound}");
-MODULE_SUPPORTED_DEVICE("sound");
 
 static int ports = 1;
 static int duplex = 0;
@@ -95,7 +93,7 @@
 	int i;
 	snd_seq_event_t ev;
 
-	p = snd_magic_cast(snd_seq_dummy_port_t, private_data, return -EINVAL);
+	p = private_data;
 	memset(&ev, 0, sizeof(ev));
 	if (p->duplex)
 		ev.source.port = p->connect;
@@ -122,18 +120,11 @@
 	snd_seq_dummy_port_t *p;
 	snd_seq_event_t tmpev;
 
-	p = snd_magic_cast(snd_seq_dummy_port_t, private_data, return -EINVAL);
+	p = private_data;
 	if (ev->source.client == SNDRV_SEQ_CLIENT_SYSTEM ||
 	    ev->type == SNDRV_SEQ_EVENT_KERNEL_ERROR)
 		return 0; /* ignore system messages */
-	/* save the original sender */
-	tmpev.type = SNDRV_SEQ_EVENT_KERNEL_QUOTE;
-	tmpev.flags = (ev->flags & ~SNDRV_SEQ_EVENT_LENGTH_MASK)
-		| SNDRV_SEQ_EVENT_LENGTH_FIXED;
-	tmpev.tag = ev->tag;
-	tmpev.time = ev->time;
-	tmpev.data.quote.origin = ev->source;
-	tmpev.data.quote.event = ev;
+	tmpev = *ev;
 	if (p->duplex)
 		tmpev.source.port = p->connect;
 	else
@@ -150,8 +141,8 @@
 {
 	snd_seq_dummy_port_t *p;
 
-	p = snd_magic_cast(snd_seq_dummy_port_t, private_data, return);
-	snd_magic_kfree(p);
+	p = private_data;
+	kfree(p);
 }
 
 /*
@@ -164,7 +155,7 @@
 	snd_seq_port_callback_t pcb;
 	snd_seq_dummy_port_t *rec;
 
-	if ((rec = snd_magic_kcalloc(snd_seq_dummy_port_t, 0, GFP_KERNEL)) == NULL)
+	if ((rec = kcalloc(1, sizeof(*rec), GFP_KERNEL)) == NULL)
 		return NULL;
 
 	rec->client = my_client;
@@ -190,7 +181,7 @@
 	pcb.private_data = rec;
 	pinfo.kernel = &pcb;
 	if (snd_seq_kernel_client_ctl(my_client, SNDRV_SEQ_IOCTL_CREATE_PORT, &pinfo) < 0) {
-		snd_magic_kfree(rec);
+		kfree(rec);
 		return NULL;
 	}
 	rec->port = pinfo.addr.port;
diff -Nru a/sound/core/seq/seq_fifo.c b/sound/core/seq/seq_fifo.c
--- a/sound/core/seq/seq_fifo.c	2004-10-18 14:56:29 -07:00
+++ b/sound/core/seq/seq_fifo.c	2004-10-18 14:56:29 -07:00
@@ -33,7 +33,7 @@
 {
 	fifo_t *f;
 
-	f = snd_kcalloc(sizeof(fifo_t), GFP_KERNEL);
+	f = kcalloc(1, sizeof(*f), GFP_KERNEL);
 	if (f == NULL) {
 		snd_printd("malloc failed for snd_seq_fifo_new() \n");
 		return NULL;
diff -Nru a/sound/core/seq/seq_instr.c b/sound/core/seq/seq_instr.c
--- a/sound/core/seq/seq_instr.c	2004-10-18 14:56:28 -07:00
+++ b/sound/core/seq/seq_instr.c	2004-10-18 14:56:28 -07:00
@@ -29,8 +29,6 @@
 MODULE_AUTHOR("Jaroslav Kysela <perex@suse.cz>");
 MODULE_DESCRIPTION("Advanced Linux Sound Architecture sequencer instrument library.");
 MODULE_LICENSE("GPL");
-MODULE_CLASSES("{sound}");
-MODULE_SUPPORTED_DEVICE("sound");
 
 
 static void snd_instr_lock_ops(snd_seq_kinstr_list_t *list)
@@ -53,10 +51,7 @@
 
 snd_seq_kcluster_t *snd_seq_cluster_new(int atomic)
 {
-	snd_seq_kcluster_t *cluster;
-	
-	cluster = (snd_seq_kcluster_t *) snd_kcalloc(sizeof(snd_seq_kcluster_t), atomic ? GFP_ATOMIC : GFP_KERNEL);
-	return cluster;
+	return kcalloc(1, sizeof(snd_seq_kcluster_t), atomic ? GFP_ATOMIC : GFP_KERNEL);
 }
 
 void snd_seq_cluster_free(snd_seq_kcluster_t *cluster, int atomic)
@@ -70,7 +65,7 @@
 {
 	snd_seq_kinstr_t *instr;
 	
-	instr = (snd_seq_kinstr_t *) snd_kcalloc(sizeof(snd_seq_kinstr_t) + add_len, atomic ? GFP_ATOMIC : GFP_KERNEL);
+	instr = kcalloc(1, sizeof(snd_seq_kinstr_t) + add_len, atomic ? GFP_ATOMIC : GFP_KERNEL);
 	if (instr == NULL)
 		return NULL;
 	instr->add_len = add_len;
@@ -94,7 +89,7 @@
 {
 	snd_seq_kinstr_list_t *list;
 
-	list = (snd_seq_kinstr_list_t *) snd_kcalloc(sizeof(snd_seq_kinstr_list_t), GFP_KERNEL);
+	list = kcalloc(1, sizeof(snd_seq_kinstr_list_t), GFP_KERNEL);
 	if (list == NULL)
 		return NULL;
 	spin_lock_init(&list->lock);
diff -Nru a/sound/core/seq/seq_memory.c b/sound/core/seq/seq_memory.c
--- a/sound/core/seq/seq_memory.c	2004-10-18 14:55:55 -07:00
+++ b/sound/core/seq/seq_memory.c	2004-10-18 14:55:55 -07:00
@@ -95,7 +95,7 @@
 			int size = sizeof(buf);
 			if (len < size)
 				size = len;
-			if (copy_from_user(buf, curptr, size) < 0)
+			if (copy_from_user(buf, curptr, size))
 				return -EFAULT;
 			err = func(private_data, buf, size);
 			if (err < 0)
@@ -158,7 +158,7 @@
 	if (event->data.ext.len & SNDRV_SEQ_EXT_USRPTR) {
 		if (! in_kernel)
 			return -EINVAL;
-		if (copy_from_user(buf, event->data.ext.ptr, len) < 0)
+		if (copy_from_user(buf, event->data.ext.ptr, len))
 			return -EFAULT;
 		return newlen;
 	}
@@ -453,7 +453,7 @@
 	pool_t *pool;
 
 	/* create pool block */
-	pool = snd_kcalloc(sizeof(pool_t), GFP_KERNEL);
+	pool = kcalloc(1, sizeof(*pool), GFP_KERNEL);
 	if (pool == NULL) {
 		snd_printd("seq: malloc failed for pool\n");
 		return NULL;
diff -Nru a/sound/core/seq/seq_midi.c b/sound/core/seq/seq_midi.c
--- a/sound/core/seq/seq_midi.c	2004-10-18 14:56:50 -07:00
+++ b/sound/core/seq/seq_midi.c	2004-10-18 14:56:50 -07:00
@@ -43,8 +43,6 @@
 MODULE_AUTHOR("Frank van de Pol <fvdpol@coil.demon.nl>, Jaroslav Kysela <perex@suse.cz>");
 MODULE_DESCRIPTION("Advanced Linux Sound Architecture sequencer MIDI synth.");
 MODULE_LICENSE("GPL");
-MODULE_CLASSES("{sound}");
-MODULE_SUPPORTED_DEVICE("sound");
 int output_buffer_size = PAGE_SIZE;
 module_param(output_buffer_size, int, 0644);
 MODULE_PARM_DESC(output_buffer_size, "Output buffer size in bytes.");
@@ -323,7 +321,7 @@
 	client = synths[card->number];
 	if (client == NULL) {
 		newclient = 1;
-		client = snd_kcalloc(sizeof(seq_midisynth_client_t), GFP_KERNEL);
+		client = kcalloc(1, sizeof(*client), GFP_KERNEL);
 		if (client == NULL) {
 			up(&register_mutex);
 			return -ENOMEM;
@@ -341,7 +339,7 @@
 	} else if (device == 0)
 		set_client_name(client, card, &info); /* use the first device's name */
 
-	msynth = snd_kcalloc(sizeof(seq_midisynth_t) * ports, GFP_KERNEL);
+	msynth = kcalloc(ports, sizeof(seq_midisynth_t), GFP_KERNEL);
 	if (msynth == NULL)
 		goto __nomem;
 
diff -Nru a/sound/core/seq/seq_midi_emul.c b/sound/core/seq/seq_midi_emul.c
--- a/sound/core/seq/seq_midi_emul.c	2004-10-18 14:57:03 -07:00
+++ b/sound/core/seq/seq_midi_emul.c	2004-10-18 14:57:03 -07:00
@@ -42,8 +42,6 @@
 MODULE_AUTHOR("Takashi Iwai / Steve Ratcliffe");
 MODULE_DESCRIPTION("Advanced Linux Sound Architecture sequencer MIDI emulation.");
 MODULE_LICENSE("GPL");
-MODULE_CLASSES("{sound}");
-MODULE_SUPPORTED_DEVICE("sound");
 
 /* Prototypes for static functions */
 static void note_off(snd_midi_op_t *ops, void *drv, snd_midi_channel_t *chan, int note, int vel);
diff -Nru a/sound/core/seq/seq_midi_event.c b/sound/core/seq/seq_midi_event.c
--- a/sound/core/seq/seq_midi_event.c	2004-10-18 14:55:54 -07:00
+++ b/sound/core/seq/seq_midi_event.c	2004-10-18 14:55:54 -07:00
@@ -118,7 +118,7 @@
 	snd_midi_event_t *dev;
 
 	*rdev = NULL;
-	dev = (snd_midi_event_t *)snd_kcalloc(sizeof(snd_midi_event_t), GFP_KERNEL);
+	dev = kcalloc(1, sizeof(*dev), GFP_KERNEL);
 	if (dev == NULL)
 		return -ENOMEM;
 	if (bufsize > 0) {
diff -Nru a/sound/core/seq/seq_ports.c b/sound/core/seq/seq_ports.c
--- a/sound/core/seq/seq_ports.c	2004-10-18 14:56:48 -07:00
+++ b/sound/core/seq/seq_ports.c	2004-10-18 14:56:48 -07:00
@@ -141,7 +141,7 @@
 	}
 
 	/* create a new port */
-	new_port = snd_kcalloc(sizeof(client_port_t), GFP_KERNEL);
+	new_port = kcalloc(1, sizeof(*new_port), GFP_KERNEL);
 	if (! new_port) {
 		snd_printd("malloc failed for registering client port\n");
 		return NULL;	/* failure, out of memory */
@@ -488,7 +488,7 @@
 	unsigned long flags;
 	int exclusive;
 
-	subs = snd_kcalloc(sizeof(*subs), GFP_KERNEL);
+	subs = kcalloc(1, sizeof(*subs), GFP_KERNEL);
 	if (! subs)
 		return -ENOMEM;
 
diff -Nru a/sound/core/seq/seq_prioq.c b/sound/core/seq/seq_prioq.c
--- a/sound/core/seq/seq_prioq.c	2004-10-18 14:55:54 -07:00
+++ b/sound/core/seq/seq_prioq.c	2004-10-18 14:55:54 -07:00
@@ -59,7 +59,7 @@
 {
 	prioq_t *f;
 
-	f = snd_kcalloc(sizeof(prioq_t), GFP_KERNEL);
+	f = kcalloc(1, sizeof(*f), GFP_KERNEL);
 	if (f == NULL) {
 		snd_printd("oops: malloc failed for snd_seq_prioq_new()\n");
 		return NULL;
diff -Nru a/sound/core/seq/seq_queue.c b/sound/core/seq/seq_queue.c
--- a/sound/core/seq/seq_queue.c	2004-10-18 14:56:49 -07:00
+++ b/sound/core/seq/seq_queue.c	2004-10-18 14:56:49 -07:00
@@ -111,7 +111,7 @@
 {
 	queue_t *q;
 
-	q = snd_kcalloc(sizeof(queue_t), GFP_KERNEL);
+	q = kcalloc(1, sizeof(*q), GFP_KERNEL);
 	if (q == NULL) {
 		snd_printd("malloc failed for snd_seq_queue_new()\n");
 		return NULL;
diff -Nru a/sound/core/seq/seq_timer.c b/sound/core/seq/seq_timer.c
--- a/sound/core/seq/seq_timer.c	2004-10-18 14:56:49 -07:00
+++ b/sound/core/seq/seq_timer.c	2004-10-18 14:56:49 -07:00
@@ -59,7 +59,7 @@
 {
 	seq_timer_t *tmr;
 	
-	tmr = snd_kcalloc(sizeof(seq_timer_t), GFP_KERNEL);
+	tmr = kcalloc(1, sizeof(*tmr), GFP_KERNEL);
 	if (tmr == NULL) {
 		snd_printd("malloc failed for snd_seq_timer_new() \n");
 		return NULL;
diff -Nru a/sound/core/seq/seq_virmidi.c b/sound/core/seq/seq_virmidi.c
--- a/sound/core/seq/seq_virmidi.c	2004-10-18 14:56:33 -07:00
+++ b/sound/core/seq/seq_virmidi.c	2004-10-18 14:56:33 -07:00
@@ -115,7 +115,7 @@
 {
 	snd_virmidi_dev_t *rdev;
 
-	rdev = snd_magic_cast(snd_virmidi_dev_t, rmidi->private_data, return -EINVAL);
+	rdev = rmidi->private_data;
 	return snd_virmidi_dev_receive_event(rdev, ev);
 }
 
@@ -127,7 +127,7 @@
 {
 	snd_virmidi_dev_t *rdev;
 
-	rdev = snd_magic_cast(snd_virmidi_dev_t, private_data, return -EINVAL);
+	rdev = private_data;
 	if (!(rdev->flags & SNDRV_VIRMIDI_USE))
 		return 0; /* ignored */
 	return snd_virmidi_dev_receive_event(rdev, ev);
@@ -138,7 +138,7 @@
  */
 static void snd_virmidi_input_trigger(snd_rawmidi_substream_t * substream, int up)
 {
-	snd_virmidi_t *vmidi = snd_magic_cast(snd_virmidi_t, substream->runtime->private_data, return);
+	snd_virmidi_t *vmidi = substream->runtime->private_data;
 
 	if (up) {
 		vmidi->trigger = 1;
@@ -152,7 +152,7 @@
  */
 static void snd_virmidi_output_trigger(snd_rawmidi_substream_t * substream, int up)
 {
-	snd_virmidi_t *vmidi = snd_magic_cast(snd_virmidi_t, substream->runtime->private_data, return);
+	snd_virmidi_t *vmidi = substream->runtime->private_data;
 	int count, res;
 	unsigned char buf[32], *pbuf;
 
@@ -199,17 +199,17 @@
  */
 static int snd_virmidi_input_open(snd_rawmidi_substream_t * substream)
 {
-	snd_virmidi_dev_t *rdev = snd_magic_cast(snd_virmidi_dev_t, substream->rmidi->private_data, return -EINVAL);
+	snd_virmidi_dev_t *rdev = substream->rmidi->private_data;
 	snd_rawmidi_runtime_t *runtime = substream->runtime;
 	snd_virmidi_t *vmidi;
 	unsigned long flags;
 
-	vmidi = snd_magic_kcalloc(snd_virmidi_t, 0, GFP_KERNEL);
+	vmidi = kcalloc(1, sizeof(*vmidi), GFP_KERNEL);
 	if (vmidi == NULL)
 		return -ENOMEM;
 	vmidi->substream = substream;
 	if (snd_midi_event_new(0, &vmidi->parser) < 0) {
-		snd_magic_kfree(vmidi);
+		kfree(vmidi);
 		return -ENOMEM;
 	}
 	vmidi->seq_mode = rdev->seq_mode;
@@ -228,16 +228,16 @@
  */
 static int snd_virmidi_output_open(snd_rawmidi_substream_t * substream)
 {
-	snd_virmidi_dev_t *rdev = snd_magic_cast(snd_virmidi_dev_t, substream->rmidi->private_data, return -EINVAL);
+	snd_virmidi_dev_t *rdev = substream->rmidi->private_data;
 	snd_rawmidi_runtime_t *runtime = substream->runtime;
 	snd_virmidi_t *vmidi;
 
-	vmidi = snd_magic_kcalloc(snd_virmidi_t, 0, GFP_KERNEL);
+	vmidi = kcalloc(1, sizeof(*vmidi), GFP_KERNEL);
 	if (vmidi == NULL)
 		return -ENOMEM;
 	vmidi->substream = substream;
 	if (snd_midi_event_new(MAX_MIDI_EVENT_BUF, &vmidi->parser) < 0) {
-		snd_magic_kfree(vmidi);
+		kfree(vmidi);
 		return -ENOMEM;
 	}
 	vmidi->seq_mode = rdev->seq_mode;
@@ -254,11 +254,11 @@
  */
 static int snd_virmidi_input_close(snd_rawmidi_substream_t * substream)
 {
-	snd_virmidi_t *vmidi = snd_magic_cast(snd_virmidi_t, substream->runtime->private_data, return -EINVAL);
+	snd_virmidi_t *vmidi = substream->runtime->private_data;
 	snd_midi_event_free(vmidi->parser);
 	list_del(&vmidi->list);
 	substream->runtime->private_data = NULL;
-	snd_magic_kfree(vmidi);
+	kfree(vmidi);
 	return 0;
 }
 
@@ -267,10 +267,10 @@
  */
 static int snd_virmidi_output_close(snd_rawmidi_substream_t * substream)
 {
-	snd_virmidi_t *vmidi = snd_magic_cast(snd_virmidi_t, substream->runtime->private_data, return -EINVAL);
+	snd_virmidi_t *vmidi = substream->runtime->private_data;
 	snd_midi_event_free(vmidi->parser);
 	substream->runtime->private_data = NULL;
-	snd_magic_kfree(vmidi);
+	kfree(vmidi);
 	return 0;
 }
 
@@ -281,7 +281,7 @@
 {
 	snd_virmidi_dev_t *rdev;
 
-	rdev = snd_magic_cast(snd_virmidi_dev_t, private_data, return -EINVAL);
+	rdev = private_data;
 	if (!try_module_get(rdev->card->module))
 		return -EFAULT;
 	rdev->flags |= SNDRV_VIRMIDI_SUBSCRIBE;
@@ -295,7 +295,7 @@
 {
 	snd_virmidi_dev_t *rdev;
 
-	rdev = snd_magic_cast(snd_virmidi_dev_t, private_data, return -EINVAL);
+	rdev = private_data;
 	rdev->flags &= ~SNDRV_VIRMIDI_SUBSCRIBE;
 	module_put(rdev->card->module);
 	return 0;
@@ -309,7 +309,7 @@
 {
 	snd_virmidi_dev_t *rdev;
 
-	rdev = snd_magic_cast(snd_virmidi_dev_t, private_data, return -EINVAL);
+	rdev = private_data;
 	if (!try_module_get(rdev->card->module))
 		return -EFAULT;
 	rdev->flags |= SNDRV_VIRMIDI_USE;
@@ -323,7 +323,7 @@
 {
 	snd_virmidi_dev_t *rdev;
 
-	rdev = snd_magic_cast(snd_virmidi_dev_t, private_data, return -EINVAL);
+	rdev = private_data;
 	rdev->flags &= ~SNDRV_VIRMIDI_USE;
 	module_put(rdev->card->module);
 	return 0;
@@ -424,7 +424,7 @@
  */
 static int snd_virmidi_dev_register(snd_rawmidi_t *rmidi)
 {
-	snd_virmidi_dev_t *rdev = snd_magic_cast(snd_virmidi_dev_t, rmidi->private_data, return -ENXIO);
+	snd_virmidi_dev_t *rdev = rmidi->private_data;
 	int err;
 
 	switch (rdev->seq_mode) {
@@ -451,7 +451,7 @@
  */
 static int snd_virmidi_dev_unregister(snd_rawmidi_t *rmidi)
 {
-	snd_virmidi_dev_t *rdev = snd_magic_cast(snd_virmidi_dev_t, rmidi->private_data, return -ENXIO);
+	snd_virmidi_dev_t *rdev = rmidi->private_data;
 
 	if (rdev->seq_mode == SNDRV_VIRMIDI_SEQ_DISPATCH)
 		snd_virmidi_dev_detach_seq(rdev);
@@ -471,8 +471,8 @@
  */
 static void snd_virmidi_free(snd_rawmidi_t *rmidi)
 {
-	snd_virmidi_dev_t *rdev = snd_magic_cast(snd_virmidi_dev_t, rmidi->private_data, return);
-	snd_magic_kfree(rdev);
+	snd_virmidi_dev_t *rdev = rmidi->private_data;
+	kfree(rdev);
 }
 
 /*
@@ -493,7 +493,7 @@
 				   &rmidi)) < 0)
 		return err;
 	strcpy(rmidi->name, rmidi->id);
-	rdev = snd_magic_kcalloc(snd_virmidi_dev_t, 0, GFP_KERNEL);
+	rdev = kcalloc(1, sizeof(*rdev), GFP_KERNEL);
 	if (rdev == NULL) {
 		snd_device_free(card, rmidi);
 		return -ENOMEM;
diff -Nru a/sound/core/sgbuf.c b/sound/core/sgbuf.c
--- a/sound/core/sgbuf.c	2004-10-18 14:56:48 -07:00
+++ b/sound/core/sgbuf.c	2004-10-18 14:56:48 -07:00
@@ -39,11 +39,13 @@
 	if (! sgbuf)
 		return -EINVAL;
 
+	tmpb.dev.type = SNDRV_DMA_TYPE_DEV;
+	tmpb.dev.dev = sgbuf->dev;
 	for (i = 0; i < sgbuf->pages; i++) {
 		tmpb.area = sgbuf->table[i].buf;
 		tmpb.addr = sgbuf->table[i].addr;
 		tmpb.bytes = PAGE_SIZE;
-		snd_dma_free_pages(&sgbuf->dev, &tmpb);
+		snd_dma_free_pages(&tmpb);
 	}
 	if (dmab->area)
 		vunmap(dmab->area);
@@ -59,7 +61,7 @@
 	return 0;
 }
 
-void *snd_malloc_sgbuf_pages(const struct snd_dma_device *dev,
+void *snd_malloc_sgbuf_pages(struct device *device,
 			     size_t size, struct snd_dma_buffer *dmab,
 			     size_t *res_size)
 {
@@ -73,8 +75,7 @@
 	if (! sgbuf)
 		return NULL;
 	memset(sgbuf, 0, sizeof(*sgbuf));
-	sgbuf->dev = *dev;
-	sgbuf->dev.type = SNDRV_DMA_TYPE_DEV;
+	sgbuf->dev = device;
 	pages = snd_sgbuf_aligned_pages(size);
 	sgbuf->tblsize = sgbuf_align_table(pages);
 	sgbuf->table = kmalloc(sizeof(*sgbuf->table) * sgbuf->tblsize, GFP_KERNEL);
@@ -88,7 +89,7 @@
 
 	/* allocate each page */
 	for (i = 0; i < pages; i++) {
-		if (snd_dma_alloc_pages(&sgbuf->dev, PAGE_SIZE, &tmpb) < 0) {
+		if (snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, device, PAGE_SIZE, &tmpb) < 0) {
 			if (res_size == NULL)
 				goto _failed;
 			*res_size = size = sgbuf->pages * PAGE_SIZE;
diff -Nru a/sound/core/sound.c b/sound/core/sound.c
--- a/sound/core/sound.c	2004-10-18 14:56:48 -07:00
+++ b/sound/core/sound.c	2004-10-18 14:56:48 -07:00
@@ -44,19 +44,14 @@
 MODULE_AUTHOR("Jaroslav Kysela <perex@suse.cz>");
 MODULE_DESCRIPTION("Advanced Linux Sound Architecture driver for soundcards.");
 MODULE_LICENSE("GPL");
-MODULE_CLASSES("{sound}");
-MODULE_SUPPORTED_DEVICE("sound");
 module_param(major, int, 0444);
 MODULE_PARM_DESC(major, "Major # for sound driver.");
-MODULE_PARM_SYNTAX(major, "default:116,skill:devel");
 module_param(cards_limit, int, 0444);
 MODULE_PARM_DESC(cards_limit, "Count of auto-loadable soundcards.");
-MODULE_PARM_SYNTAX(cards_limit, "default:8,skill:advanced");
 MODULE_ALIAS_CHARDEV_MAJOR(CONFIG_SND_MAJOR);
 #ifdef CONFIG_DEVFS_FS
 module_param(device_mode, int, 0444);
 MODULE_PARM_DESC(device_mode, "Device file permission mask for devfs.");
-MODULE_PARM_SYNTAX(device_mode, "default:0666,base:8");
 #endif
 MODULE_ALIAS_CHARDEV_MAJOR(CONFIG_SND_MAJOR);
 
@@ -339,39 +334,29 @@
 static int __init alsa_sound_init(void)
 {
 	short controlnum;
-#ifdef CONFIG_SND_OSSEMUL
 	int err;
-#endif
 	int card;
 
 	snd_major = major;
 	snd_ecards_limit = cards_limit;
 	for (card = 0; card < SNDRV_CARDS; card++)
 		INIT_LIST_HEAD(&snd_minors_hash[card]);
-#ifdef CONFIG_SND_OSSEMUL
 	if ((err = snd_oss_init_module()) < 0)
 		return err;
-#endif
 	devfs_mk_dir("snd");
 	if (register_chrdev(major, "alsa", &snd_fops)) {
 		snd_printk(KERN_ERR "unable to register native major device number %d\n", major);
 		devfs_remove("snd");
 		return -EIO;
 	}
-#ifdef CONFIG_SND_DEBUG_MEMORY
 	snd_memory_init();
-#endif
 	if (snd_info_init() < 0) {
-#ifdef CONFIG_SND_DEBUG_MEMORY
 		snd_memory_done();
-#endif
 		unregister_chrdev(major, "alsa");
 		devfs_remove("snd");
 		return -ENOMEM;
 	}
-#ifdef CONFIG_SND_OSSEMUL
 	snd_info_minor_register();
-#endif
 	for (controlnum = 0; controlnum < cards_limit; controlnum++) {
 		devfs_mk_cdev(MKDEV(major, controlnum<<5), S_IFCHR | device_mode, "snd/controlC%d", controlnum);
 		class_simple_device_add(sound_class, MKDEV(major, controlnum<<5), NULL, "controlC%d", controlnum);
@@ -391,13 +376,9 @@
 		class_simple_device_remove(MKDEV(major, controlnum<<5));
 	}
 
-#ifdef CONFIG_SND_OSSEMUL
 	snd_info_minor_unregister();
-#endif
 	snd_info_done();
-#ifdef CONFIG_SND_DEBUG_MEMORY
 	snd_memory_done();
-#endif
 	if (unregister_chrdev(major, "alsa") != 0)
 		snd_printk(KERN_ERR "unable to unregister major device number %d\n", major);
 	devfs_remove("snd");
@@ -406,24 +387,6 @@
 module_init(alsa_sound_init)
 module_exit(alsa_sound_exit)
 
-#ifndef MODULE
-
-/* format is: snd=major,cards_limit[,device_mode] */
-
-static int __init alsa_sound_setup(char *str)
-{
-	(void)(get_option(&str,&major) == 2 &&
-	       get_option(&str,&cards_limit) == 2);
-#ifdef CONFIG_DEVFS_FS
-	(void)(get_option(&str,&device_mode) == 2);
-#endif
-	return 1;
-}
-
-__setup("snd=", alsa_sound_setup);
-
-#endif /* ifndef MODULE */
-
   /* sound.c */
 EXPORT_SYMBOL(snd_major);
 EXPORT_SYMBOL(snd_ecards_limit);
@@ -439,14 +402,11 @@
   /* memory.c */
 #ifdef CONFIG_SND_DEBUG_MEMORY
 EXPORT_SYMBOL(snd_hidden_kmalloc);
+EXPORT_SYMBOL(snd_hidden_kcalloc);
 EXPORT_SYMBOL(snd_hidden_kfree);
 EXPORT_SYMBOL(snd_hidden_vmalloc);
 EXPORT_SYMBOL(snd_hidden_vfree);
-EXPORT_SYMBOL(_snd_magic_kmalloc);
-EXPORT_SYMBOL(_snd_magic_kcalloc);
-EXPORT_SYMBOL(snd_magic_kfree);
 #endif
-EXPORT_SYMBOL(snd_kcalloc);
 EXPORT_SYMBOL(snd_kmalloc_strdup);
 EXPORT_SYMBOL(copy_to_user_fromio);
 EXPORT_SYMBOL(copy_from_user_toio);
diff -Nru a/sound/core/timer.c b/sound/core/timer.c
--- a/sound/core/timer.c	2004-10-18 14:56:33 -07:00
+++ b/sound/core/timer.c	2004-10-18 14:56:33 -07:00
@@ -22,6 +22,7 @@
 #include <sound/driver.h>
 #include <linux/delay.h>
 #include <linux/init.h>
+#include <linux/smp_lock.h>
 #include <linux/slab.h>
 #include <linux/time.h>
 #include <linux/moduleparam.h>
@@ -46,7 +47,6 @@
 MODULE_AUTHOR("Jaroslav Kysela <perex@suse.cz>, Takashi Iwai <tiwai@suse.de>");
 MODULE_DESCRIPTION("ALSA timer interface");
 MODULE_LICENSE("GPL");
-MODULE_CLASSES("{sound}");
 module_param(timer_limit, int, 0444);
 MODULE_PARM_DESC(timer_limit, "Maximum global timers in system.");
 
@@ -94,7 +94,7 @@
 static snd_timer_instance_t *snd_timer_instance_new(char *owner, snd_timer_t *timer)
 {
 	snd_timer_instance_t *timeri;
-	timeri = snd_kcalloc(sizeof(snd_timer_instance_t), GFP_KERNEL);
+	timeri = kcalloc(1, sizeof(*timeri), GFP_KERNEL);
 	if (timeri == NULL)
 		return NULL;
 	timeri->owner = snd_kmalloc_strdup(owner, GFP_KERNEL);
@@ -761,7 +761,7 @@
 	snd_assert(tid != NULL, return -EINVAL);
 	snd_assert(rtimer != NULL, return -EINVAL);
 	*rtimer = NULL;
-	timer = snd_magic_kcalloc(snd_timer_t, 0, GFP_KERNEL);
+	timer = kcalloc(1, sizeof(*timer), GFP_KERNEL);
 	if (timer == NULL)
 		return -ENOMEM;
 	timer->tmr_class = tid->dev_class;
@@ -792,19 +792,19 @@
 	snd_assert(timer != NULL, return -ENXIO);
 	if (timer->private_free)
 		timer->private_free(timer);
-	snd_magic_kfree(timer);
+	kfree(timer);
 	return 0;
 }
 
 int snd_timer_dev_free(snd_device_t *device)
 {
-	snd_timer_t *timer = snd_magic_cast(snd_timer_t, device->device_data, return -ENXIO);
+	snd_timer_t *timer = device->device_data;
 	return snd_timer_free(timer);
 }
 
 int snd_timer_dev_register(snd_device_t *dev)
 {
-	snd_timer_t *timer = snd_magic_cast(snd_timer_t, dev->device_data, return -ENXIO);
+	snd_timer_t *timer = dev->device_data;
 	snd_timer_t *timer1;
 	struct list_head *p;
 
@@ -865,7 +865,7 @@
 
 static int snd_timer_dev_unregister(snd_device_t *device)
 {
-	snd_timer_t *timer = snd_magic_cast(snd_timer_t, device->device_data, return -ENXIO);
+	snd_timer_t *timer = device->device_data;
 	return snd_timer_unregister(timer);
 }
 
@@ -1018,7 +1018,7 @@
 		return err;
 	strcpy(timer->name, "system timer");
 	timer->hw = snd_timer_system;
-	priv = (struct snd_timer_system_private *) snd_kcalloc(sizeof(struct snd_timer_system_private), GFP_KERNEL);
+	priv = kcalloc(1, sizeof(*priv), GFP_KERNEL);
 	if (priv == NULL) {
 		snd_timer_free(timer);
 		return -ENOMEM;
@@ -1086,7 +1086,7 @@
 				     unsigned long resolution,
 				     unsigned long ticks)
 {
-	snd_timer_user_t *tu = snd_magic_cast(snd_timer_user_t, timeri->callback_data, return);
+	snd_timer_user_t *tu = timeri->callback_data;
 	snd_timer_read_t *r;
 	int prev;
 	
@@ -1129,7 +1129,7 @@
 				     struct timespec *tstamp,
 				     unsigned long resolution)
 {
-	snd_timer_user_t *tu = snd_magic_cast(snd_timer_user_t, timeri->callback_data, return);
+	snd_timer_user_t *tu = timeri->callback_data;
 	snd_timer_tread_t r1;
 
 	if (event >= SNDRV_TIMER_EVENT_START && event <= SNDRV_TIMER_EVENT_PAUSE)
@@ -1148,7 +1148,7 @@
 				      unsigned long resolution,
 				      unsigned long ticks)
 {
-	snd_timer_user_t *tu = snd_magic_cast(snd_timer_user_t, timeri->callback_data, return);
+	snd_timer_user_t *tu = timeri->callback_data;
 	snd_timer_tread_t *r, r1;
 	struct timespec tstamp;
 	int prev, append = 0;
@@ -1200,7 +1200,7 @@
 {
 	snd_timer_user_t *tu;
 	
-	tu = snd_magic_kcalloc(snd_timer_user_t, 0, GFP_KERNEL);
+	tu = kcalloc(1, sizeof(*tu), GFP_KERNEL);
 	if (tu == NULL)
 		return -ENOMEM;
 	spin_lock_init(&tu->qlock);
@@ -1209,7 +1209,7 @@
 	tu->queue_size = 128;
 	tu->queue = (snd_timer_read_t *)kmalloc(tu->queue_size * sizeof(snd_timer_read_t), GFP_KERNEL);
 	if (tu->queue == NULL) {
-		snd_magic_kfree(tu);
+		kfree(tu);
 		return -ENOMEM;
 	}
 	file->private_data = tu;
@@ -1221,7 +1221,7 @@
 	snd_timer_user_t *tu;
 
 	if (file->private_data) {
-		tu = snd_magic_cast(snd_timer_user_t, file->private_data, return -ENXIO);
+		tu = file->private_data;
 		file->private_data = NULL;
 		fasync_helper(-1, file, 0, &tu->fasync);
 		if (tu->timeri)
@@ -1230,7 +1230,7 @@
 			kfree(tu->queue);
 		if (tu->tqueue)
 			kfree(tu->tqueue);
-		snd_magic_kfree(tu);
+		kfree(tu);
 	}
 	return 0;
 }
@@ -1449,7 +1449,7 @@
 	char str[32];
 	int err;
 	
-	tu = snd_magic_cast(snd_timer_user_t, file->private_data, return -ENXIO);
+	tu = file->private_data;
 	if (tu->timeri)
 		snd_timer_close(tu->timeri);
 	if (copy_from_user(&tselect, _tselect, sizeof(tselect)))
@@ -1495,7 +1495,7 @@
 	snd_timer_info_t info;
 	snd_timer_t *t;
 
-	tu = snd_magic_cast(snd_timer_user_t, file->private_data, return -ENXIO);
+	tu = file->private_data;
 	snd_assert(tu->timeri != NULL, return -ENXIO);
 	t = tu->timeri->timer;
 	snd_assert(t != NULL, return -ENXIO);
@@ -1520,7 +1520,7 @@
 	snd_timer_tread_t *ttr;
 	int err;
 	
-	tu = snd_magic_cast(snd_timer_user_t, file->private_data, return -ENXIO);
+	tu = file->private_data;
 	snd_assert(tu->timeri != NULL, return -ENXIO);
 	t = tu->timeri->timer;
 	snd_assert(t != NULL, return -ENXIO);
@@ -1608,7 +1608,7 @@
 	snd_timer_user_t *tu;
 	snd_timer_status_t status;
 	
-	tu = snd_magic_cast(snd_timer_user_t, file->private_data, return -ENXIO);
+	tu = file->private_data;
 	snd_assert(tu->timeri != NULL, return -ENXIO);
 	memset(&status, 0, sizeof(status));
 	status.tstamp = tu->tstamp;
@@ -1628,7 +1628,7 @@
 	int err;
 	snd_timer_user_t *tu;
 		
-	tu = snd_magic_cast(snd_timer_user_t, file->private_data, return -ENXIO);
+	tu = file->private_data;
 	snd_assert(tu->timeri != NULL, return -ENXIO);
 	snd_timer_stop(tu->timeri);
 	tu->timeri->lost = 0;
@@ -1641,7 +1641,7 @@
 	int err;
 	snd_timer_user_t *tu;
 		
-	tu = snd_magic_cast(snd_timer_user_t, file->private_data, return -ENXIO);
+	tu = file->private_data;
 	snd_assert(tu->timeri != NULL, return -ENXIO);
 	return (err = snd_timer_stop(tu->timeri)) < 0 ? err : 0;
 }
@@ -1651,20 +1651,20 @@
 	int err;
 	snd_timer_user_t *tu;
 		
-	tu = snd_magic_cast(snd_timer_user_t, file->private_data, return -ENXIO);
+	tu = file->private_data;
 	snd_assert(tu->timeri != NULL, return -ENXIO);
 	tu->timeri->lost = 0;
 	return (err = snd_timer_continue(tu->timeri)) < 0 ? err : 0;
 }
 
-static int snd_timer_user_ioctl(struct inode *inode, struct file *file,
-				unsigned int cmd, unsigned long arg)
+static inline int _snd_timer_user_ioctl(struct inode *inode, struct file *file,
+					unsigned int cmd, unsigned long arg)
 {
 	snd_timer_user_t *tu;
 	void __user *argp = (void __user *)arg;
 	int __user *p = argp;
 	
-	tu = snd_magic_cast(snd_timer_user_t, file->private_data, return -ENXIO);
+	tu = file->private_data;
 	switch (cmd) {
 	case SNDRV_TIMER_IOCTL_PVERSION:
 		return put_user(SNDRV_TIMER_VERSION, p) ? -EFAULT : 0;
@@ -1705,12 +1705,23 @@
 	return -ENOTTY;
 }
 
+/* FIXME: need to unlock BKL to allow preemption */
+static int snd_timer_user_ioctl(struct inode *inode, struct file * file,
+				unsigned int cmd, unsigned long arg)
+{
+	int err;
+	unlock_kernel();
+	err = _snd_timer_user_ioctl(inode, file, cmd, arg);
+	lock_kernel();
+	return err;
+}
+
 static int snd_timer_user_fasync(int fd, struct file * file, int on)
 {
 	snd_timer_user_t *tu;
 	int err;
 	
-	tu = snd_magic_cast(snd_timer_user_t, file->private_data, return -ENXIO);
+	tu = file->private_data;
 	err = fasync_helper(fd, file, on, &tu->fasync);
         if (err < 0)
 		return err;
@@ -1723,7 +1734,7 @@
 	long result = 0, unit;
 	int err = 0;
 	
-	tu = snd_magic_cast(snd_timer_user_t, file->private_data, return -ENXIO);
+	tu = file->private_data;
 	unit = tu->tread ? sizeof(snd_timer_tread_t) : sizeof(snd_timer_read_t);
 	spin_lock_irq(&tu->qlock);
 	while ((long)count - result >= unit) {
@@ -1785,7 +1796,7 @@
         unsigned int mask;
         snd_timer_user_t *tu;
 
-        tu = snd_magic_cast(snd_timer_user_t, file->private_data, return 0);
+        tu = file->private_data;
 
         poll_wait(file, &tu->qchange_sleep, wait);
 	
diff -Nru a/sound/drivers/dummy.c b/sound/drivers/dummy.c
--- a/sound/drivers/dummy.c	2004-10-18 14:57:03 -07:00
+++ b/sound/drivers/dummy.c	2004-10-18 14:57:03 -07:00
@@ -34,8 +34,7 @@
 MODULE_AUTHOR("Jaroslav Kysela <perex@suse.cz>");
 MODULE_DESCRIPTION("Dummy soundcard (/dev/null)");
 MODULE_LICENSE("GPL");
-MODULE_CLASSES("{sound}");
-MODULE_DEVICES("{{ALSA,Dummy soundcard}}");
+MODULE_SUPPORTED_DEVICE("{{ALSA,Dummy soundcard}}");
 
 #define MAX_PCM_DEVICES		4
 #define MAX_PCM_SUBSTREAMS	16
@@ -133,22 +132,16 @@
 
 module_param_array(index, int, boot_devs, 0444);
 MODULE_PARM_DESC(index, "Index value for dummy soundcard.");
-MODULE_PARM_SYNTAX(index, SNDRV_INDEX_DESC);
 module_param_array(id, charp, boot_devs, 0444);
 MODULE_PARM_DESC(id, "ID string for dummy soundcard.");
-MODULE_PARM_SYNTAX(id, SNDRV_ID_DESC);
 module_param_array(enable, bool, boot_devs, 0444);
 MODULE_PARM_DESC(enable, "Enable this dummy soundcard.");
-MODULE_PARM_SYNTAX(enable, SNDRV_ENABLE_DESC);
 module_param_array(pcm_devs, int, boot_devs, 0444);
 MODULE_PARM_DESC(pcm_devs, "PCM devices # (0-4) for dummy driver.");
-MODULE_PARM_SYNTAX(pcm_devs, SNDRV_ENABLED ",allows:{{0,4}},default:1,dialog:list");
 module_param_array(pcm_substreams, int, boot_devs, 0444);
 MODULE_PARM_DESC(pcm_substreams, "PCM substreams # (1-16) for dummy driver.");
-MODULE_PARM_SYNTAX(pcm_substreams, SNDRV_ENABLED ",allows:{{1,16}},default:8,dialog:list");
 //module_param_array(midi_devs, int, boot_devs, 0444);
 //MODULE_PARM_DESC(midi_devs, "MIDI devices # (0-2) for dummy driver.");
-//MODULE_PARM_SYNTAX(midi_devs, SNDRV_ENABLED ",allows:{{0,2}},default:8,dialog:list");
 
 #define MIXER_ADDR_MASTER	0
 #define MIXER_ADDR_LINE		1
@@ -180,24 +173,10 @@
 static snd_card_t *snd_dummy_cards[SNDRV_CARDS] = SNDRV_DEFAULT_PTR;
 
 
-static int snd_card_dummy_playback_ioctl(snd_pcm_substream_t * substream,
-				         unsigned int cmd,
-				         void *arg)
-{
-	return snd_pcm_lib_ioctl(substream, cmd, arg);
-}
-
-static int snd_card_dummy_capture_ioctl(snd_pcm_substream_t * substream,
-					unsigned int cmd,
-					void *arg)
-{
-	return snd_pcm_lib_ioctl(substream, cmd, arg);
-}
-
 static void snd_card_dummy_pcm_timer_start(snd_pcm_substream_t * substream)
 {
 	snd_pcm_runtime_t *runtime = substream->runtime;
-	snd_card_dummy_pcm_t *dpcm = snd_magic_cast(snd_card_dummy_pcm_t, runtime->private_data, return);
+	snd_card_dummy_pcm_t *dpcm = runtime->private_data;
 
 	dpcm->timer.expires = 1 + jiffies;
 	add_timer(&dpcm->timer);
@@ -206,7 +185,7 @@
 static void snd_card_dummy_pcm_timer_stop(snd_pcm_substream_t * substream)
 {
 	snd_pcm_runtime_t *runtime = substream->runtime;
-	snd_card_dummy_pcm_t *dpcm = snd_magic_cast(snd_card_dummy_pcm_t, runtime->private_data, return);
+	snd_card_dummy_pcm_t *dpcm = runtime->private_data;
 
 	del_timer(&dpcm->timer);
 }
@@ -240,7 +219,7 @@
 static int snd_card_dummy_pcm_prepare(snd_pcm_substream_t * substream)
 {
 	snd_pcm_runtime_t *runtime = substream->runtime;
-	snd_card_dummy_pcm_t *dpcm = snd_magic_cast(snd_card_dummy_pcm_t, runtime->private_data, return -ENXIO);
+	snd_card_dummy_pcm_t *dpcm = runtime->private_data;
 	unsigned int bps;
 
 	bps = runtime->rate * runtime->channels;
@@ -269,7 +248,7 @@
 
 static void snd_card_dummy_pcm_timer_function(unsigned long data)
 {
-	snd_card_dummy_pcm_t *dpcm = snd_magic_cast(snd_card_dummy_pcm_t, (void *)data, return);
+	snd_card_dummy_pcm_t *dpcm = (snd_card_dummy_pcm_t *)data;
 	
 	dpcm->timer.expires = 1 + jiffies;
 	add_timer(&dpcm->timer);
@@ -287,7 +266,7 @@
 static snd_pcm_uframes_t snd_card_dummy_playback_pointer(snd_pcm_substream_t * substream)
 {
 	snd_pcm_runtime_t *runtime = substream->runtime;
-	snd_card_dummy_pcm_t *dpcm = snd_magic_cast(snd_card_dummy_pcm_t, runtime->private_data, return -ENXIO);
+	snd_card_dummy_pcm_t *dpcm = runtime->private_data;
 
 	return bytes_to_frames(runtime, dpcm->pcm_buf_pos);
 }
@@ -295,7 +274,7 @@
 static snd_pcm_uframes_t snd_card_dummy_capture_pointer(snd_pcm_substream_t * substream)
 {
 	snd_pcm_runtime_t *runtime = substream->runtime;
-	snd_card_dummy_pcm_t *dpcm = snd_magic_cast(snd_card_dummy_pcm_t, runtime->private_data, return -ENXIO);
+	snd_card_dummy_pcm_t *dpcm = runtime->private_data;
 
 	return bytes_to_frames(runtime, dpcm->pcm_buf_pos);
 }
@@ -338,8 +317,19 @@
 
 static void snd_card_dummy_runtime_free(snd_pcm_runtime_t *runtime)
 {
-	snd_card_dummy_pcm_t *dpcm = snd_magic_cast(snd_card_dummy_pcm_t, runtime->private_data, return);
-	snd_magic_kfree(dpcm);
+	snd_card_dummy_pcm_t *dpcm = runtime->private_data;
+	kfree(dpcm);
+}
+
+static int snd_card_dummy_hw_params(snd_pcm_substream_t * substream,
+				    snd_pcm_hw_params_t * hw_params)
+{
+	return snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(hw_params));
+}
+
+static int snd_card_dummy_hw_free(snd_pcm_substream_t * substream)
+{
+	return snd_pcm_lib_free_pages(substream);
 }
 
 static int snd_card_dummy_playback_open(snd_pcm_substream_t * substream)
@@ -348,13 +338,9 @@
 	snd_card_dummy_pcm_t *dpcm;
 	int err;
 
-	dpcm = snd_magic_kcalloc(snd_card_dummy_pcm_t, 0, GFP_KERNEL);
+	dpcm = kcalloc(1, sizeof(*dpcm), GFP_KERNEL);
 	if (dpcm == NULL)
 		return -ENOMEM;
-	if ((runtime->dma_area = snd_malloc_pages_fallback(MAX_BUFFER_SIZE, GFP_KERNEL, &runtime->dma_bytes)) == NULL) {
-		snd_magic_kfree(dpcm);
-		return -ENOMEM;
-	}
 	init_timer(&dpcm->timer);
 	dpcm->timer.data = (unsigned long) dpcm;
 	dpcm->timer.function = snd_card_dummy_pcm_timer_function;
@@ -370,7 +356,7 @@
 	if (substream->pcm->device & 2)
 		runtime->hw.info &= ~(SNDRV_PCM_INFO_MMAP|SNDRV_PCM_INFO_MMAP_VALID);
 	if ((err = add_playback_constraints(runtime)) < 0) {
-		snd_magic_kfree(dpcm);
+		kfree(dpcm);
 		return err;
 	}
 
@@ -383,14 +369,9 @@
 	snd_card_dummy_pcm_t *dpcm;
 	int err;
 
-	dpcm = snd_magic_kcalloc(snd_card_dummy_pcm_t, 0, GFP_KERNEL);
+	dpcm = kcalloc(1, sizeof(*dpcm), GFP_KERNEL);
 	if (dpcm == NULL)
 		return -ENOMEM;
-	if ((runtime->dma_area = snd_malloc_pages_fallback(MAX_BUFFER_SIZE, GFP_KERNEL, &runtime->dma_bytes)) == NULL) {
-		snd_magic_kfree(dpcm);
-		return -ENOMEM;
-	}
-	memset(runtime->dma_area, 0, runtime->dma_bytes);
 	init_timer(&dpcm->timer);
 	dpcm->timer.data = (unsigned long) dpcm;
 	dpcm->timer.function = snd_card_dummy_pcm_timer_function;
@@ -406,7 +387,7 @@
 	if (substream->pcm->device & 2)
 		runtime->hw.info &= ~(SNDRV_PCM_INFO_MMAP|SNDRV_PCM_INFO_MMAP_VALID);
 	if ((err = add_capture_constraints(runtime)) < 0) {
-		snd_magic_kfree(dpcm);
+		kfree(dpcm);
 		return err;
 	}
 
@@ -415,24 +396,20 @@
 
 static int snd_card_dummy_playback_close(snd_pcm_substream_t * substream)
 {
-	snd_pcm_runtime_t *runtime = substream->runtime;
-
-	snd_free_pages(runtime->dma_area, runtime->dma_bytes);
 	return 0;
 }
 
 static int snd_card_dummy_capture_close(snd_pcm_substream_t * substream)
 {
-	snd_pcm_runtime_t *runtime = substream->runtime;
-
-	snd_free_pages(runtime->dma_area, runtime->dma_bytes);
 	return 0;
 }
 
 static snd_pcm_ops_t snd_card_dummy_playback_ops = {
 	.open =			snd_card_dummy_playback_open,
 	.close =		snd_card_dummy_playback_close,
-	.ioctl =		snd_card_dummy_playback_ioctl,
+	.ioctl =		snd_pcm_lib_ioctl,
+	.hw_params =		snd_card_dummy_hw_params,
+	.hw_free =		snd_card_dummy_hw_free,
 	.prepare =		snd_card_dummy_playback_prepare,
 	.trigger =		snd_card_dummy_playback_trigger,
 	.pointer =		snd_card_dummy_playback_pointer,
@@ -441,7 +418,9 @@
 static snd_pcm_ops_t snd_card_dummy_capture_ops = {
 	.open =			snd_card_dummy_capture_open,
 	.close =		snd_card_dummy_capture_close,
-	.ioctl =		snd_card_dummy_capture_ioctl,
+	.ioctl =		snd_pcm_lib_ioctl,
+	.hw_params =		snd_card_dummy_hw_params,
+	.hw_free =		snd_card_dummy_hw_free,
 	.prepare =		snd_card_dummy_capture_prepare,
 	.trigger =		snd_card_dummy_capture_trigger,
 	.pointer =		snd_card_dummy_capture_pointer,
@@ -459,6 +438,9 @@
 	pcm->private_data = dummy;
 	pcm->info_flags = 0;
 	strcpy(pcm->name, "Dummy PCM");
+	snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_CONTINUOUS,
+					      snd_dma_continuous_data(GFP_KERNEL),
+					      0, 64*1024);
 	return 0;
 }
 
@@ -479,7 +461,7 @@
  
 static int snd_dummy_volume_get(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
 {
-	snd_card_dummy_t *dummy = _snd_kcontrol_chip(kcontrol);
+	snd_card_dummy_t *dummy = snd_kcontrol_chip(kcontrol);
 	unsigned long flags;
 	int addr = kcontrol->private_value;
 
@@ -488,11 +470,11 @@
 	ucontrol->value.integer.value[1] = dummy->mixer_volume[addr][1];
 	spin_unlock_irqrestore(&dummy->mixer_lock, flags);
 	return 0;
-}                                                                                                                                                                                                                                                                                                            
+}
 
 static int snd_dummy_volume_put(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
 {
-	snd_card_dummy_t *dummy = _snd_kcontrol_chip(kcontrol);
+	snd_card_dummy_t *dummy = snd_kcontrol_chip(kcontrol);
 	unsigned long flags;
 	int change, addr = kcontrol->private_value;
 	int left, right;
@@ -514,7 +496,7 @@
 	dummy->mixer_volume[addr][1] = right;
 	spin_unlock_irqrestore(&dummy->mixer_lock, flags);
 	return change;
-}                                                                                                                                                                                                                                                                                                            
+}
 
 #define DUMMY_CAPSRC(xname, xindex, addr) \
 { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xindex, \
@@ -533,7 +515,7 @@
  
 static int snd_dummy_capsrc_get(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
 {
-	snd_card_dummy_t *dummy = _snd_kcontrol_chip(kcontrol);
+	snd_card_dummy_t *dummy = snd_kcontrol_chip(kcontrol);
 	unsigned long flags;
 	int addr = kcontrol->private_value;
 
@@ -546,7 +528,7 @@
 
 static int snd_dummy_capsrc_put(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
 {
-	snd_card_dummy_t *dummy = _snd_kcontrol_chip(kcontrol);
+	snd_card_dummy_t *dummy = snd_kcontrol_chip(kcontrol);
 	unsigned long flags;
 	int change, addr = kcontrol->private_value;
 	int left, right;
@@ -560,9 +542,7 @@
 	dummy->capture_source[addr][1] = right;
 	spin_unlock_irqrestore(&dummy->mixer_lock, flags);
 	return change;
-}                                                                                                                                                                                                                                                                                                            
-
-#define DUMMY_CONTROLS (sizeof(snd_dummy_controls)/sizeof(snd_kcontrol_new_t))
+}
 
 static snd_kcontrol_new_t snd_dummy_controls[] = {
 DUMMY_VOLUME("Master Volume", 0, MIXER_ADDR_MASTER),
@@ -587,7 +567,7 @@
 	spin_lock_init(&dummy->mixer_lock);
 	strcpy(card->mixername, "Dummy Mixer");
 
-	for (idx = 0; idx < DUMMY_CONTROLS; idx++) {
+	for (idx = 0; idx < ARRAY_SIZE(snd_dummy_controls); idx++) {
 		if ((err = snd_ctl_add(card, snd_ctl_new1(&snd_dummy_controls[idx], dummy))) < 0)
 			return err;
 	}
diff -Nru a/sound/drivers/mpu401/mpu401.c b/sound/drivers/mpu401/mpu401.c
--- a/sound/drivers/mpu401/mpu401.c	2004-10-18 14:56:48 -07:00
+++ b/sound/drivers/mpu401/mpu401.c	2004-10-18 14:56:48 -07:00
@@ -28,7 +28,7 @@
 #include <sound/driver.h>
 #include <linux/init.h>
 #ifdef CONFIG_ACPI_BUS
-#include <acpi/acpi_bus.h>
+#include <linux/acpi.h>
 #endif
 #include <linux/moduleparam.h>
 #include <sound/core.h>
@@ -42,7 +42,6 @@
 MODULE_AUTHOR("Jaroslav Kysela <perex@suse.cz>");
 MODULE_DESCRIPTION("MPU-401 UART");
 MODULE_LICENSE("GPL");
-MODULE_CLASSES("{sound}");
 
 static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX;	/* Index 0-MAX */
 static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR;	/* ID for this card */
@@ -56,24 +55,18 @@
 
 module_param_array(index, int, boot_devs, 0444);
 MODULE_PARM_DESC(index, "Index value for MPU-401 device.");
-MODULE_PARM_SYNTAX(index, SNDRV_INDEX_DESC);
 module_param_array(id, charp, boot_devs, 0444);
 MODULE_PARM_DESC(id, "ID string for MPU-401 device.");
-MODULE_PARM_SYNTAX(id, SNDRV_ID_DESC);
 module_param_array(enable, bool, boot_devs, 0444);
 MODULE_PARM_DESC(enable, "Enable MPU-401 device.");
-MODULE_PARM_SYNTAX(enable, SNDRV_ENABLE_DESC);
 #ifdef USE_ACPI_PNP
 module_param_array(acpipnp, bool, boot_devs, 0444);
 MODULE_PARM_DESC(acpipnp, "ACPI PnP detection for MPU-401 device.");
-MODULE_PARM_SYNTAX(acpipnp, SNDRV_ENABLED "," SNDRV_BOOLEAN_TRUE_DESC);
 #endif
 module_param_array(port, long, boot_devs, 0444);
 MODULE_PARM_DESC(port, "Port # for MPU-401 device.");
-MODULE_PARM_SYNTAX(port, SNDRV_PORT12_DESC);
 module_param_array(irq, int, boot_devs, 0444);
 MODULE_PARM_DESC(irq, "IRQ # for MPU-401 device.");
-MODULE_PARM_SYNTAX(irq, SNDRV_IRQ_DESC);
 
 #ifndef CONFIG_ACPI_BUS
 struct acpi_device;
@@ -98,13 +91,9 @@
 
 	if (res->id == ACPI_RSTYPE_IRQ) {
 		if (res->data.irq.number_of_interrupts > 0) {
-#ifdef CONFIG_IA64
-			resources->irq = acpi_register_irq(res->data.irq.interrupts[0],
-							   res->data.irq.active_high_low,
-							   res->data.irq.edge_level);
-#else
-			resources->irq = res->data.irq.interrupts[0];
-#endif
+			resources->irq = acpi_register_gsi(res->data.irq.interrupts[0],
+							   res->data.irq.edge_level,
+							   res->data.irq.active_high_low);
 		}
 	} else if (res->id == ACPI_RSTYPE_IO) {
 		if (res->data.io.range_length >= 2) {
@@ -175,7 +164,7 @@
 	}
 #ifdef USE_ACPI_PNP
 	if (device) {
-		strcat(card->longname, ", bus id ");
+		strcat(card->longname, ", ACPI id ");
 		strlcat(card->longname, acpi_device_bid(device), sizeof(card->longname));
 	}
 #endif
diff -Nru a/sound/drivers/mpu401/mpu401_uart.c b/sound/drivers/mpu401/mpu401_uart.c
--- a/sound/drivers/mpu401/mpu401_uart.c	2004-10-18 14:56:28 -07:00
+++ b/sound/drivers/mpu401/mpu401_uart.c	2004-10-18 14:56:28 -07:00
@@ -123,7 +123,7 @@
  */
 irqreturn_t snd_mpu401_uart_interrupt(int irq, void *dev_id, struct pt_regs *regs)
 {
-	mpu401_t *mpu = snd_magic_cast(mpu401_t, dev_id, return IRQ_NONE);
+	mpu401_t *mpu = dev_id;
 	
 	if (mpu == NULL)
 		return IRQ_NONE;
@@ -137,7 +137,7 @@
  */
 static void snd_mpu401_uart_timer(unsigned long data)
 {
-	mpu401_t *mpu = snd_magic_cast(mpu401_t, (void *)data, return);
+	mpu401_t *mpu = (mpu401_t *)data;
 
 	spin_lock(&mpu->timer_lock);
 	/*mpu->mode |= MPU401_MODE_TIMER;*/
@@ -235,7 +235,7 @@
 	mpu401_t *mpu;
 	int err;
 
-	mpu = snd_magic_cast(mpu401_t, substream->rmidi->private_data, return -ENXIO);
+	mpu = substream->rmidi->private_data;
 	if (mpu->open_input && (err = mpu->open_input(mpu)) < 0)
 		return err;
 	if (! test_bit(MPU401_MODE_BIT_OUTPUT, &mpu->mode)) {
@@ -253,7 +253,7 @@
 	mpu401_t *mpu;
 	int err;
 
-	mpu = snd_magic_cast(mpu401_t, substream->rmidi->private_data, return -ENXIO);
+	mpu = substream->rmidi->private_data;
 	if (mpu->open_output && (err = mpu->open_output(mpu)) < 0)
 		return err;
 	if (! test_bit(MPU401_MODE_BIT_INPUT, &mpu->mode)) {
@@ -270,7 +270,7 @@
 {
 	mpu401_t *mpu;
 
-	mpu = snd_magic_cast(mpu401_t, substream->rmidi->private_data, return -ENXIO);
+	mpu = substream->rmidi->private_data;
 	clear_bit(MPU401_MODE_BIT_INPUT, &mpu->mode);
 	mpu->substream_input = NULL;
 	if (! test_bit(MPU401_MODE_BIT_OUTPUT, &mpu->mode))
@@ -284,7 +284,7 @@
 {
 	mpu401_t *mpu;
 
-	mpu = snd_magic_cast(mpu401_t, substream->rmidi->private_data, return -ENXIO);
+	mpu = substream->rmidi->private_data;
 	clear_bit(MPU401_MODE_BIT_OUTPUT, &mpu->mode);
 	mpu->substream_output = NULL;
 	if (! test_bit(MPU401_MODE_BIT_INPUT, &mpu->mode))
@@ -303,7 +303,7 @@
 	mpu401_t *mpu;
 	int max = 64;
 
-	mpu = snd_magic_cast(mpu401_t, substream->rmidi->private_data, return);
+	mpu = substream->rmidi->private_data;
 	if (up) {
 		if (! test_and_set_bit(MPU401_MODE_BIT_INPUT_TRIGGER, &mpu->mode)) {
 			/* first time - flush FIFO */
@@ -394,7 +394,7 @@
 	unsigned long flags;
 	mpu401_t *mpu;
 
-	mpu = snd_magic_cast(mpu401_t, substream->rmidi->private_data, return);
+	mpu = substream->rmidi->private_data;
 	if (up) {
 		set_bit(MPU401_MODE_BIT_OUTPUT_TRIGGER, &mpu->mode);
 
@@ -441,14 +441,14 @@
 
 static void snd_mpu401_uart_free(snd_rawmidi_t *rmidi)
 {
-	mpu401_t *mpu = snd_magic_cast(mpu401_t, rmidi->private_data, return);
+	mpu401_t *mpu = rmidi->private_data;
 	if (mpu->irq_flags && mpu->irq >= 0)
 		free_irq(mpu->irq, (void *) mpu);
 	if (mpu->res) {
 		release_resource(mpu->res);
 		kfree_nocheck(mpu->res);
 	}
-	snd_magic_kfree(mpu);
+	kfree(mpu);
 }
 
 /**
@@ -484,7 +484,7 @@
 		*rrawmidi = NULL;
 	if ((err = snd_rawmidi_new(card, "MPU-401U", device, 1, 1, &rmidi)) < 0)
 		return err;
-	mpu = snd_magic_kcalloc(mpu401_t, 0, GFP_KERNEL);
+	mpu = kcalloc(1, sizeof(*mpu), GFP_KERNEL);
 	if (mpu == NULL) {
 		snd_device_free(card, rmidi);
 		return -ENOMEM;
diff -Nru a/sound/drivers/mtpav.c b/sound/drivers/mtpav.c
--- a/sound/drivers/mtpav.c	2004-10-18 14:56:49 -07:00
+++ b/sound/drivers/mtpav.c	2004-10-18 14:56:49 -07:00
@@ -69,8 +69,7 @@
 MODULE_AUTHOR("Michael T. Mayers");
 MODULE_DESCRIPTION("MOTU MidiTimePiece AV multiport MIDI");
 MODULE_LICENSE("GPL");
-MODULE_CLASSES("{sound}");
-MODULE_DEVICES("{{MOTU,MidiTimePiece AV multiport MIDI}}");
+MODULE_SUPPORTED_DEVICE("{{MOTU,MidiTimePiece AV multiport MIDI}}");
 
 // io resources
 #define MTPAV_IOBASE		0x378
@@ -85,19 +84,14 @@
 
 module_param(index, int, 0444);
 MODULE_PARM_DESC(index, "Index value for MotuMTPAV MIDI.");
-MODULE_PARM_SYNTAX(index, SNDRV_INDEX_DESC);
 module_param(id, charp, 0444);
 MODULE_PARM_DESC(id, "ID string for MotuMTPAV MIDI.");
-MODULE_PARM_SYNTAX(id, SNDRV_ID_DESC);
 module_param(port, long, 0444);
 MODULE_PARM_DESC(port, "Parallel port # for MotuMTPAV MIDI.");
-MODULE_PARM_SYNTAX(port, SNDRV_ENABLED ",allows:{{0x378},{0x278}},dialog:list");
 module_param(irq, int, 0444);
 MODULE_PARM_DESC(irq, "Parallel IRQ # for MotuMTPAV MIDI.");
-MODULE_PARM_SYNTAX(irq,  SNDRV_ENABLED ",allows:{{7},{5}},dialog:list");
 module_param(hwports, int, 0444);
 MODULE_PARM_DESC(hwports, "Hardware ports # for MotuMTPAV MIDI.");
-MODULE_PARM_SYNTAX(hwports, SNDRV_ENABLED ",allows:{{1,8}},dialog:list");
 
 /*
  *      defines
@@ -419,7 +413,7 @@
 
 static void snd_mtpav_output_timer(unsigned long data)
 {
-	mtpav_t *chip = snd_magic_cast(mtpav_t, (void *)data, return);
+	mtpav_t *chip = (mtpav_t *)data;
 	int p;
 
 	spin_lock(&chip->spinlock);
@@ -587,7 +581,7 @@
 
 static irqreturn_t snd_mtpav_irqh(int irq, void *dev_id, struct pt_regs *regs)
 {
-	mtpav_t *mcard = snd_magic_cast(mtpav_t, dev_id, return IRQ_NONE);
+	mtpav_t *mcard = dev_id;
 
 	//printk("irqh()\n");
 	spin_lock(&mcard->spinlock);
@@ -695,7 +689,7 @@
 
 static mtpav_t *new_mtpav(void)
 {
-	mtpav_t *ncrd = (mtpav_t *) snd_magic_kcalloc(mtpav_t, 0, GFP_KERNEL);
+	mtpav_t *ncrd = kcalloc(1, sizeof(*ncrd), GFP_KERNEL);
 	if (ncrd != NULL) {
 		spin_lock_init(&ncrd->spinlock);
 
@@ -728,7 +722,7 @@
 		release_resource(crd->res_port);
 		kfree_nocheck(crd->res_port);
 	}
-	snd_magic_kfree(crd);
+	kfree(crd);
 }
 
 /*
diff -Nru a/sound/drivers/opl3/opl3_lib.c b/sound/drivers/opl3/opl3_lib.c
--- a/sound/drivers/opl3/opl3_lib.c	2004-10-18 14:56:17 -07:00
+++ b/sound/drivers/opl3/opl3_lib.c	2004-10-18 14:56:17 -07:00
@@ -35,8 +35,6 @@
 MODULE_DESCRIPTION("Routines for control of AdLib FM cards (OPL2/OPL3/OPL4 chips)");
 MODULE_LICENSE("GPL");
 
-#define chip_t opl3_t
-
 extern char snd_opl3_regmap[MAX_OPL2_VOICES][4];
 
 void snd_opl2_command(opl3_t * opl3, unsigned short cmd, unsigned char val)
@@ -322,7 +320,7 @@
 	if (hw == NULL)
 		return;
 
-	opl3 = snd_magic_cast(opl3_t, hw->private_data, return);
+	opl3 = hw->private_data;
 	status = inb(opl3->l_port);
 #if 0
 	snd_printk("AdLib IRQ status = 0x%x\n", status);
@@ -354,13 +352,13 @@
 		release_resource(opl3->res_r_port);
 		kfree_nocheck(opl3->res_r_port);
 	}
-	snd_magic_kfree(opl3);
+	kfree(opl3);
 	return 0;
 }
 
 static int snd_opl3_dev_free(snd_device_t *device)
 {
-	opl3_t *opl3 = snd_magic_cast(opl3_t, device->device_data, return -ENXIO);
+	opl3_t *opl3 = device->device_data;
 	return snd_opl3_free(opl3);
 }
 
@@ -379,7 +377,7 @@
 
 	*ropl3 = NULL;
 
-	opl3 = snd_magic_kcalloc(opl3_t, 0, GFP_KERNEL);
+	opl3 = kcalloc(1, sizeof(*opl3), GFP_KERNEL);
 	if (opl3 == NULL)
 		return -ENOMEM;
 
diff -Nru a/sound/drivers/opl3/opl3_midi.c b/sound/drivers/opl3/opl3_midi.c
--- a/sound/drivers/opl3/opl3_midi.c	2004-10-18 14:56:33 -07:00
+++ b/sound/drivers/opl3/opl3_midi.c	2004-10-18 14:56:33 -07:00
@@ -313,7 +313,7 @@
 	fm_instrument_t *fm;
 	unsigned long flags;
 
-	opl3 = snd_magic_cast(opl3_t, p, return);
+	opl3 = p;
 
 #ifdef DEBUG_MIDI
 	snd_printk("Note on, ch %i, inst %i, note %i, vel %i\n",
@@ -672,7 +672,7 @@
 
 	unsigned long flags;
 
-	opl3 = snd_magic_cast(opl3_t, p, return);
+	opl3 = p;
 
 #ifdef DEBUG_MIDI
 	snd_printk("Note off, ch %i, inst %i, note %i\n",
@@ -712,7 +712,7 @@
 {
   	opl3_t *opl3;
 
-	opl3 = snd_magic_cast(opl3_t, p, return);
+	opl3 = p;
 #ifdef DEBUG_MIDI
 	snd_printk("Key pressure, ch#: %i, inst#: %i\n",
 		   chan->number, chan->midi_program);
@@ -726,7 +726,7 @@
 {
   	opl3_t *opl3;
 
-	opl3 = snd_magic_cast(opl3_t, p, return);
+	opl3 = p;
 #ifdef DEBUG_MIDI
 	snd_printk("Terminate note, ch#: %i, inst#: %i\n",
 		   chan->number, chan->midi_program);
@@ -814,7 +814,7 @@
 {
   	opl3_t *opl3;
 
-	opl3 = snd_magic_cast(opl3_t, p, return);
+	opl3 = p;
 #ifdef DEBUG_MIDI
 	snd_printk("Controller, TYPE = %i, ch#: %i, inst#: %i\n",
 		   type, chan->number, chan->midi_program);
@@ -851,7 +851,7 @@
 {
   	opl3_t *opl3;
 
-	opl3 = snd_magic_cast(opl3_t, p, return);
+	opl3 = p;
 #ifdef DEBUG_MIDI
 	snd_printk("NRPN, ch#: %i, inst#: %i\n",
 		   chan->number, chan->midi_program);
@@ -866,7 +866,7 @@
 {
   	opl3_t *opl3;
 
-	opl3 = snd_magic_cast(opl3_t, p, return);
+	opl3 = p;
 #ifdef DEBUG_MIDI
 	snd_printk("SYSEX\n");
 #endif
diff -Nru a/sound/drivers/opl3/opl3_oss.c b/sound/drivers/opl3/opl3_oss.c
--- a/sound/drivers/opl3/opl3_oss.c	2004-10-18 14:55:54 -07:00
+++ b/sound/drivers/opl3/opl3_oss.c	2004-10-18 14:55:54 -07:00
@@ -57,7 +57,7 @@
 static int snd_opl3_oss_event_input(snd_seq_event_t *ev, int direct,
 				    void *private_data, int atomic, int hop)
 {
-	opl3_t *opl3 = snd_magic_cast(opl3_t, private_data, return -EINVAL);
+	opl3_t *opl3 = private_data;
 
 	if (ev->type != SNDRV_SEQ_EVENT_OSS)
 		snd_midi_process_event(&opl3_ops, ev, opl3->oss_chset);
@@ -68,7 +68,7 @@
 
 static void snd_opl3_oss_free_port(void *private_data)
 {
-	opl3_t *opl3 = snd_magic_cast(opl3_t, private_data, return);
+	opl3_t *opl3 = private_data;
 
 	snd_midi_channel_free_set(opl3->oss_chset);
 }
@@ -156,7 +156,7 @@
 /* open OSS sequencer */
 static int snd_opl3_open_seq_oss(snd_seq_oss_arg_t *arg, void *closure)
 {
-	opl3_t *opl3 = snd_magic_cast(opl3_t, closure, return -EINVAL);
+	opl3_t *opl3 = closure;
 	int err;
 
 	snd_assert(arg != NULL, return -ENXIO);
@@ -182,7 +182,7 @@
 	opl3_t *opl3;
 
 	snd_assert(arg != NULL, return -ENXIO);
-	opl3 = snd_magic_cast(opl3_t, arg->private_data, return -EINVAL);
+	opl3 = arg->private_data;
 
 	snd_opl3_synth_cleanup(opl3);
 
@@ -213,7 +213,7 @@
 	int err = -EINVAL;
 
 	snd_assert(arg != NULL, return -ENXIO);
-	opl3 = snd_magic_cast(opl3_t, arg->private_data, return -EINVAL);
+	opl3 = arg->private_data;
 
 	if ((format == FM_PATCH) || (format == OPL3_PATCH)) {
 		struct sbi_instrument sbi;
@@ -241,7 +241,7 @@
 		}
 
 		size = sizeof(*put) + sizeof(fm_xinstrument_t);
-		put = (snd_seq_instr_header_t *)snd_kcalloc(size, GFP_KERNEL);
+		put = kcalloc(1, size, GFP_KERNEL);
 		if (put == NULL)
 			return -ENOMEM;
 		/* build header */
@@ -325,7 +325,7 @@
 	opl3_t *opl3;
 
 	snd_assert(arg != NULL, return -ENXIO);
-	opl3 = snd_magic_cast(opl3_t, arg->private_data, return -EINVAL);
+	opl3 = arg->private_data;
 	switch (cmd) {
 		case SNDCTL_FM_LOAD_INSTR:
 			snd_printk("OPL3: Obsolete ioctl(SNDCTL_FM_LOAD_INSTR) used. Fix the program.\n");
@@ -350,7 +350,7 @@
 	opl3_t *opl3;
 
 	snd_assert(arg != NULL, return -ENXIO);
-	opl3 = snd_magic_cast(opl3_t, arg->private_data, return -EINVAL);
+	opl3 = arg->private_data;
 
 	return 0;
 }
diff -Nru a/sound/drivers/opl3/opl3_seq.c b/sound/drivers/opl3/opl3_seq.c
--- a/sound/drivers/opl3/opl3_seq.c	2004-10-18 14:56:33 -07:00
+++ b/sound/drivers/opl3/opl3_seq.c	2004-10-18 14:56:33 -07:00
@@ -30,7 +30,6 @@
 MODULE_AUTHOR("Uros Bizjak <uros@kss-loka.si>");
 MODULE_LICENSE("GPL");
 MODULE_DESCRIPTION("ALSA driver for OPL3 FM synth");
-MODULE_CLASSES("{sound}");
 
 int use_internal_drums = 0;
 module_param(use_internal_drums, bool, 0444);
@@ -99,7 +98,7 @@
 
 int snd_opl3_synth_use(void *private_data, snd_seq_port_subscribe_t * info)
 {
-	opl3_t *opl3 = snd_magic_cast(opl3_t, private_data, return -ENXIO);
+	opl3_t *opl3 = private_data;
 	int err;
 
 	if ((err = snd_opl3_synth_setup(opl3)) < 0)
@@ -126,7 +125,7 @@
 
 int snd_opl3_synth_unuse(void *private_data, snd_seq_port_subscribe_t * info)
 {
-	opl3_t *opl3 = snd_magic_cast(opl3_t, private_data, return -ENXIO);
+	opl3_t *opl3 = private_data;
 
 	snd_opl3_synth_cleanup(opl3);
 
@@ -151,7 +150,7 @@
 static int snd_opl3_synth_event_input(snd_seq_event_t * ev, int direct,
 				      void *private_data, int atomic, int hop)
 {
-	opl3_t *opl3 = snd_magic_cast(opl3_t, private_data, return -EINVAL);
+	opl3_t *opl3 = private_data;
 
 	if (ev->type >= SNDRV_SEQ_EVENT_INSTR_BEGIN &&
 	    ev->type <= SNDRV_SEQ_EVENT_INSTR_CHANGE) {
@@ -169,7 +168,7 @@
 
 static void snd_opl3_synth_free_port(void *private_data)
 {
-	opl3_t *opl3 = snd_magic_cast(opl3_t, private_data, return);
+	opl3_t *opl3 = private_data;
 
 	snd_midi_channel_free_set(opl3->chset);
 }
diff -Nru a/sound/drivers/opl3/opl3_synth.c b/sound/drivers/opl3/opl3_synth.c
--- a/sound/drivers/opl3/opl3_synth.c	2004-10-18 14:57:19 -07:00
+++ b/sound/drivers/opl3/opl3_synth.c	2004-10-18 14:57:19 -07:00
@@ -74,7 +74,7 @@
  */
 int snd_opl3_open(snd_hwdep_t * hw, struct file *file)
 {
-	opl3_t *opl3 = snd_magic_cast(opl3_t, hw->private_data, return -ENXIO);
+	opl3_t *opl3 = hw->private_data;
 
 	down(&opl3->access_mutex);
 	if (opl3->used) {
@@ -93,7 +93,7 @@
 int snd_opl3_ioctl(snd_hwdep_t * hw, struct file *file,
 		   unsigned int cmd, unsigned long arg)
 {
-	opl3_t *opl3 = snd_magic_cast(opl3_t, hw->private_data, return -ENXIO);
+	opl3_t *opl3 = hw->private_data;
 	void __user *argp = (void __user *)arg;
 
 	snd_assert(opl3 != NULL, return -EINVAL);
@@ -176,7 +176,7 @@
  */
 int snd_opl3_release(snd_hwdep_t * hw, struct file *file)
 {
-	opl3_t *opl3 = snd_magic_cast(opl3_t, hw->private_data, return -ENXIO);
+	opl3_t *opl3 = hw->private_data;
 
 	snd_opl3_reset(opl3);
 	down(&opl3->access_mutex);
diff -Nru a/sound/drivers/opl4/Makefile b/sound/drivers/opl4/Makefile
--- a/sound/drivers/opl4/Makefile	2004-10-18 14:56:50 -07:00
+++ b/sound/drivers/opl4/Makefile	2004-10-18 14:56:50 -07:00
@@ -15,4 +15,4 @@
 sequencer = $(if $(subst y,,$(CONFIG_SND_SEQUENCER)),$(if $(1),m),$(if $(CONFIG_SND_SEQUENCER),$(1)))
 
 obj-$(CONFIG_SND_OPL4_LIB) += snd-opl4-lib.o
-obj-$(call sequencer,$(CONFIG_SND_OPL4_LIB)) += snd-opl4-synth.o
\ No newline at end of file
+obj-$(call sequencer,$(CONFIG_SND_OPL4_LIB)) += snd-opl4-synth.o
diff -Nru a/sound/drivers/opl4/opl4_lib.c b/sound/drivers/opl4/opl4_lib.c
--- a/sound/drivers/opl4/opl4_lib.c	2004-10-18 14:57:03 -07:00
+++ b/sound/drivers/opl4/opl4_lib.c	2004-10-18 14:57:03 -07:00
@@ -26,7 +26,6 @@
 MODULE_AUTHOR("Clemens Ladisch <clemens@ladisch.de>");
 MODULE_DESCRIPTION("OPL4 driver");
 MODULE_LICENSE("GPL");
-MODULE_CLASSES("{sound}");
 
 static void inline snd_opl4_wait(opl4_t *opl4)
 {
@@ -37,62 +36,68 @@
 
 void snd_opl4_write(opl4_t *opl4, u8 reg, u8 value)
 {
-	unsigned long flags;
-
-	spin_lock_irqsave(&opl4->reg_lock, flags);
-
 	snd_opl4_wait(opl4);
 	outb(reg, opl4->pcm_port);
 
 	snd_opl4_wait(opl4);
 	outb(value, opl4->pcm_port + 1);
-
-	spin_unlock_irqrestore(&opl4->reg_lock, flags);
 }
 
 u8 snd_opl4_read(opl4_t *opl4, u8 reg)
 {
-	unsigned long flags;
-	u8 value;
-
-	spin_lock_irqsave(&opl4->reg_lock, flags);
-
 	snd_opl4_wait(opl4);
 	outb(reg, opl4->pcm_port);
 
 	snd_opl4_wait(opl4);
-	value = inb(opl4->pcm_port + 1);
-
-	spin_unlock_irqrestore(&opl4->reg_lock, flags);
-	return value;
+	return inb(opl4->pcm_port + 1);
 }
 
 void snd_opl4_read_memory(opl4_t *opl4, char *buf, int offset, int size)
 {
-	u8 memcfg = snd_opl4_read(opl4, OPL4_REG_MEMORY_CONFIGURATION);
+	unsigned long flags;
+	u8 memcfg;
+
+	spin_lock_irqsave(&opl4->reg_lock, flags);
+
+	memcfg = snd_opl4_read(opl4, OPL4_REG_MEMORY_CONFIGURATION);
 	snd_opl4_write(opl4, OPL4_REG_MEMORY_CONFIGURATION, memcfg | OPL4_MODE_BIT);
 
 	snd_opl4_write(opl4, OPL4_REG_MEMORY_ADDRESS_HIGH, offset >> 16);
 	snd_opl4_write(opl4, OPL4_REG_MEMORY_ADDRESS_MID, offset >> 8);
 	snd_opl4_write(opl4, OPL4_REG_MEMORY_ADDRESS_LOW, offset);
-	for (; size > 0; size--)
-		*buf++ = snd_opl4_read(opl4, OPL4_REG_MEMORY_DATA);
+
+	snd_opl4_wait(opl4);
+	outb(OPL4_REG_MEMORY_DATA, opl4->pcm_port);
+	snd_opl4_wait(opl4);
+	insb(opl4->pcm_port + 1, buf, size);
 
 	snd_opl4_write(opl4, OPL4_REG_MEMORY_CONFIGURATION, memcfg);
+
+	spin_unlock_irqrestore(&opl4->reg_lock, flags);
 }
 
 void snd_opl4_write_memory(opl4_t *opl4, const char *buf, int offset, int size)
 {
-	u8 memcfg = snd_opl4_read(opl4, OPL4_REG_MEMORY_CONFIGURATION);
+	unsigned long flags;
+	u8 memcfg;
+
+	spin_lock_irqsave(&opl4->reg_lock, flags);
+
+	memcfg = snd_opl4_read(opl4, OPL4_REG_MEMORY_CONFIGURATION);
 	snd_opl4_write(opl4, OPL4_REG_MEMORY_CONFIGURATION, memcfg | OPL4_MODE_BIT);
 
 	snd_opl4_write(opl4, OPL4_REG_MEMORY_ADDRESS_HIGH, offset >> 16);
 	snd_opl4_write(opl4, OPL4_REG_MEMORY_ADDRESS_MID, offset >> 8);
 	snd_opl4_write(opl4, OPL4_REG_MEMORY_ADDRESS_LOW, offset);
-	for (; size > 0; size--)
-		snd_opl4_write(opl4, OPL4_REG_MEMORY_DATA, *buf++);
+
+	snd_opl4_wait(opl4);
+	outb(OPL4_REG_MEMORY_DATA, opl4->pcm_port);
+	snd_opl4_wait(opl4);
+	outsb(opl4->pcm_port + 1, buf, size);
 
 	snd_opl4_write(opl4, OPL4_REG_MEMORY_CONFIGURATION, memcfg);
+
+	spin_unlock_irqrestore(&opl4->reg_lock, flags);
 }
 
 static void snd_opl4_enable_opl4(opl4_t *opl4)
@@ -141,7 +146,7 @@
 #if defined(CONFIG_SND_SEQUENCER) || (defined(MODULE) && defined(CONFIG_SND_SEQUENCER_MODULE))
 static void snd_opl4_seq_dev_free(snd_seq_device_t *seq_dev)
 {
-	opl4_t *opl4 = snd_magic_cast(opl4_t, seq_dev->private_data, return);
+	opl4_t *opl4 = seq_dev->private_data;
 	opl4->seq_dev = NULL;
 }
 
@@ -172,12 +177,12 @@
 		release_resource(opl4->res_pcm_port);
 		kfree_nocheck(opl4->res_pcm_port);
 	}
-	snd_magic_kfree(opl4);
+	kfree(opl4);
 }
 
 static int snd_opl4_dev_free(snd_device_t *device)
 {
-	opl4_t *opl4 = snd_magic_cast(opl4_t, device->device_data, return -ENXIO);
+	opl4_t *opl4 = device->device_data;
 	snd_opl4_free(opl4);
 	return 0;
 }
@@ -199,7 +204,7 @@
 	if (ropl4)
 		*ropl4 = NULL;
 
-	opl4 = snd_magic_kcalloc(opl4_t, 0, GFP_KERNEL);
+	opl4 = kcalloc(1, sizeof(*opl4), GFP_KERNEL);
 	if (!opl4)
 		return -ENOMEM;
 
@@ -231,7 +236,7 @@
 	}
 
 	/* opl3 initialization disabled opl4, so reenable */
-	snd_opl4_enable_opl4(opl4); 
+	snd_opl4_enable_opl4(opl4);
 
 	err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, opl4, &ops);
 	if (err < 0) {
diff -Nru a/sound/drivers/opl4/opl4_local.h b/sound/drivers/opl4/opl4_local.h
--- a/sound/drivers/opl4/opl4_local.h	2004-10-18 14:56:31 -07:00
+++ b/sound/drivers/opl4/opl4_local.h	2004-10-18 14:56:31 -07:00
@@ -195,7 +195,6 @@
 	opl4_voice_t voices[OPL4_MAX_VOICES];
 	struct list_head off_voices;
 	struct list_head on_voices;
-	spinlock_t voices_lock;
 #endif
 };
 
diff -Nru a/sound/drivers/opl4/opl4_mixer.c b/sound/drivers/opl4/opl4_mixer.c
--- a/sound/drivers/opl4/opl4_mixer.c	2004-10-18 14:56:27 -07:00
+++ b/sound/drivers/opl4/opl4_mixer.c	2004-10-18 14:56:27 -07:00
@@ -20,8 +20,6 @@
 #include "opl4_local.h"
 #include <sound/control.h>
 
-#define chip_t opl4_t
-
 static int snd_opl4_ctl_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo)
 {
 	uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
@@ -34,10 +32,13 @@
 static int snd_opl4_ctl_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
 {
 	opl4_t *opl4 = snd_kcontrol_chip(kcontrol);
+	unsigned long flags;
 	u8 reg = kcontrol->private_value;
 	u8 value;
 
+	spin_lock_irqsave(&opl4->reg_lock, flags);
 	value = snd_opl4_read(opl4, reg);
+	spin_unlock_irqrestore(&opl4->reg_lock, flags);
 	ucontrol->value.integer.value[0] = 7 - (value & 7);
 	ucontrol->value.integer.value[1] = 7 - ((value >> 3) & 7);
 	return 0;
@@ -46,13 +47,16 @@
 static int snd_opl4_ctl_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
 {
 	opl4_t *opl4 = snd_kcontrol_chip(kcontrol);
+	unsigned long flags;
 	u8 reg = kcontrol->private_value;
 	u8 value, old_value;
 
 	value = (7 - (ucontrol->value.integer.value[0] & 7)) |
 		((7 - (ucontrol->value.integer.value[1] & 7)) << 3);
+	spin_lock_irqsave(&opl4->reg_lock, flags);
 	old_value = snd_opl4_read(opl4, reg);
 	snd_opl4_write(opl4, reg, value);
+	spin_unlock_irqrestore(&opl4->reg_lock, flags);
 	return value != old_value;
 }
 
@@ -80,9 +84,7 @@
 	snd_card_t *card = opl4->card;
 	int i, err;
 
-#if 0	/* already set by the codec driver */
-	strcpy(card->mixername, "OPL4 Mixer");
-#endif
+	strcat(card->mixername, ",OPL4");
 
 	for (i = 0; i < 2; ++i) {
 		err = snd_ctl_add(card, snd_ctl_new1(&snd_opl4_controls[i], opl4));
diff -Nru a/sound/drivers/opl4/opl4_proc.c b/sound/drivers/opl4/opl4_proc.c
--- a/sound/drivers/opl4/opl4_proc.c	2004-10-18 14:57:03 -07:00
+++ b/sound/drivers/opl4/opl4_proc.c	2004-10-18 14:57:03 -07:00
@@ -26,7 +26,7 @@
 static int snd_opl4_mem_proc_open(snd_info_entry_t *entry,
 				  unsigned short mode, void **file_private_data)
 {
-	opl4_t *opl4 = snd_magic_cast(opl4_t, entry->private_data, return -ENXIO);
+	opl4_t *opl4 = entry->private_data;
 
 	down(&opl4->access_mutex);
 	if (opl4->memory_access) {
@@ -41,7 +41,7 @@
 static int snd_opl4_mem_proc_release(snd_info_entry_t *entry,
 				     unsigned short mode, void *file_private_data)
 {
-	opl4_t *opl4 = snd_magic_cast(opl4_t, entry->private_data, return -ENXIO);
+	opl4_t *opl4 = entry->private_data;
 
 	down(&opl4->access_mutex);
 	opl4->memory_access--;
@@ -53,7 +53,7 @@
 				   struct file *file, char __user *_buf,
 				   unsigned long count, unsigned long pos)
 {
-	opl4_t *opl4 = snd_magic_cast(opl4_t, entry->private_data, return -ENXIO);
+	opl4_t *opl4 = entry->private_data;
 	long size;
 	char* buf;
 
@@ -79,7 +79,7 @@
 				    struct file *file, const char __user *_buf,
 				    unsigned long count, unsigned long pos)
 {
-	opl4_t *opl4 = snd_magic_cast(opl4_t, entry->private_data, return -ENXIO);
+	opl4_t *opl4 = entry->private_data;
 	long size;
 	char *buf;
 
diff -Nru a/sound/drivers/opl4/opl4_seq.c b/sound/drivers/opl4/opl4_seq.c
--- a/sound/drivers/opl4/opl4_seq.c	2004-10-18 14:56:32 -07:00
+++ b/sound/drivers/opl4/opl4_seq.c	2004-10-18 14:56:32 -07:00
@@ -39,13 +39,11 @@
 MODULE_AUTHOR("Clemens Ladisch <clemens@ladisch.de>");
 MODULE_DESCRIPTION("OPL4 wavetable synth driver");
 MODULE_LICENSE("Dual BSD/GPL");
-MODULE_CLASSES("{sound}");
 
 int volume_boost = 8;
 
 module_param(volume_boost, int, 0644);
 MODULE_PARM_DESC(volume_boost, "Additional volume for OPL4 wavetable sounds.");
-MODULE_PARM_SYNTAX(volume_boost, "default:8");
 
 static int snd_opl4_seq_use_inc(opl4_t *opl4)
 {
@@ -61,7 +59,7 @@
 
 static int snd_opl4_seq_use(void *private_data, snd_seq_port_subscribe_t *info)
 {
-	opl4_t *opl4 = snd_magic_cast(opl4_t, private_data, return -ENXIO);
+	opl4_t *opl4 = private_data;
 	int err;
 
 	down(&opl4->access_mutex);
@@ -88,7 +86,7 @@
 
 static int snd_opl4_seq_unuse(void *private_data, snd_seq_port_subscribe_t *info)
 {
-	opl4_t *opl4 = snd_magic_cast(opl4_t, private_data, return -ENXIO);
+	opl4_t *opl4 = private_data;
 
 	snd_opl4_synth_shutdown(opl4);
 
@@ -112,7 +110,7 @@
 static int snd_opl4_seq_event_input(snd_seq_event_t *ev, int direct,
 				    void *private_data, int atomic, int hop)
 {
-	opl4_t *opl4 = snd_magic_cast(opl4_t, private_data, return -ENXIO);
+	opl4_t *opl4 = private_data;
 
 	snd_midi_process_event(&opl4_ops, ev, opl4->chset);
 	return 0;
@@ -120,7 +118,7 @@
 
 static void snd_opl4_seq_free_port(void *private_data)
 {
-	opl4_t *opl4 = snd_magic_cast(opl4_t, private_data, return);
+	opl4_t *opl4 = private_data;
 
 	snd_midi_channel_free_set(opl4->chset);
 }
diff -Nru a/sound/drivers/opl4/opl4_synth.c b/sound/drivers/opl4/opl4_synth.c
--- a/sound/drivers/opl4/opl4_synth.c	2004-10-18 14:56:31 -07:00
+++ b/sound/drivers/opl4/opl4_synth.c	2004-10-18 14:56:31 -07:00
@@ -272,12 +272,14 @@
  */
 void snd_opl4_synth_reset(opl4_t *opl4)
 {
+	unsigned long flags;
 	int i;
 
+	spin_lock_irqsave(&opl4->reg_lock, flags);
 	for (i = 0; i < OPL4_MAX_VOICES; i++)
 		snd_opl4_write(opl4, OPL4_REG_MISC + i, OPL4_DAMP_BIT);
+	spin_unlock_irqrestore(&opl4->reg_lock, flags);
 
-	spin_lock_init(&opl4->voices_lock);
 	INIT_LIST_HEAD(&opl4->off_voices);
 	INIT_LIST_HEAD(&opl4->on_voices);
 	memset(opl4->voices, 0, sizeof(opl4->voices));
@@ -294,11 +296,14 @@
  */
 void snd_opl4_synth_shutdown(opl4_t *opl4)
 {
+	unsigned long flags;
 	int i;
 
+	spin_lock_irqsave(&opl4->reg_lock, flags);
 	for (i = 0; i < OPL4_MAX_VOICES; i++)
 		snd_opl4_write(opl4, OPL4_REG_MISC + i,
 			       opl4->voices[i].reg_misc & ~OPL4_KEY_ON_BIT);
+	spin_unlock_irqrestore(&opl4->reg_lock, flags);
 }
 
 /*
@@ -311,14 +316,14 @@
 	unsigned long flags;
 	opl4_voice_t *voice;
 
-	spin_lock_irqsave(&opl4->voices_lock, flags);
+	spin_lock_irqsave(&opl4->reg_lock, flags);
 	for (i = 0; i < OPL4_MAX_VOICES; i++) {
 		voice = &opl4->voices[i];
 		if (voice->chan == chan && voice->note == note) {
 			func(opl4, voice);
 		}
 	}
-	spin_unlock_irqrestore(&opl4->voices_lock, flags);
+	spin_unlock_irqrestore(&opl4->reg_lock, flags);
 }
 
 /*
@@ -331,14 +336,14 @@
 	unsigned long flags;
 	opl4_voice_t *voice;
 
-	spin_lock_irqsave(&opl4->voices_lock, flags);
+	spin_lock_irqsave(&opl4->reg_lock, flags);
 	for (i = 0; i < OPL4_MAX_VOICES; i++) {
 		voice = &opl4->voices[i];
 		if (voice->chan == chan) {
 			func(opl4, voice);
 		}
 	}
-	spin_unlock_irqrestore(&opl4->voices_lock, flags);
+	spin_unlock_irqrestore(&opl4->reg_lock, flags);
 }
 
 /*
@@ -351,13 +356,13 @@
 	unsigned long flags;
 	opl4_voice_t *voice;
 
-	spin_lock_irqsave(&opl4->voices_lock, flags);
+	spin_lock_irqsave(&opl4->reg_lock, flags);
 	for (i = 0; i < OPL4_MAX_VOICES; i++) {
 		voice = &opl4->voices[i];
 		if (voice->chan)
 			func(opl4, voice);
 	}
-	spin_unlock_irqrestore(&opl4->voices_lock, flags);
+	spin_unlock_irqrestore(&opl4->reg_lock, flags);
 }
 
 static void snd_opl4_update_volume(opl4_t *opl4, opl4_voice_t *voice)
@@ -472,7 +477,7 @@
 
 void snd_opl4_note_on(void *private_data, int note, int vel, snd_midi_channel_t *chan)
 {
-	opl4_t *opl4 = snd_magic_cast(opl4_t, private_data, return);
+	opl4_t *opl4 = private_data;
 	const opl4_region_ptr_t *regions;
 	opl4_voice_t *voice[2];
 	const opl4_sound_t *sound[2];
@@ -492,7 +497,7 @@
 	}
 
 	/* allocate and initialize the needed voices */
-	spin_lock_irqsave(&opl4->voices_lock, flags);
+	spin_lock_irqsave(&opl4->reg_lock, flags);
 	for (i = 0; i < voices; i++) {
 		voice[i] = snd_opl4_get_voice(opl4);
 		list_del(&voice[i]->list);
@@ -502,7 +507,6 @@
 		voice[i]->velocity = vel & 0x7f;
 		voice[i]->sound = sound[i];
 	}
-	spin_unlock_irqrestore(&opl4->voices_lock, flags);
 
 	/* set tone number (triggers header loading) */
 	for (i = 0; i < voices; i++) {
@@ -522,11 +526,13 @@
 		voice[i]->level_direct = OPL4_LEVEL_DIRECT_BIT;
 		snd_opl4_update_volume(opl4, voice[i]);
 	}
+	spin_unlock_irqrestore(&opl4->reg_lock, flags);
 
 	/* wait for completion of loading */
 	snd_opl4_wait_for_wave_headers(opl4);
 
 	/* set remaining parameters */
+	spin_lock_irqsave(&opl4->reg_lock, flags);
 	for (i = 0; i < voices; i++) {
 		snd_opl4_update_tone_parameters(opl4, voice[i]);
 		voice[i]->reg_lfo_vibrato = voice[i]->sound->reg_lfo_vibrato;
@@ -540,6 +546,7 @@
 		snd_opl4_write(opl4, OPL4_REG_MISC + voice[i]->number,
 			       voice[i]->reg_misc);
 	}
+	spin_unlock_irqrestore(&opl4->reg_lock, flags);
 }
 
 static void snd_opl4_voice_off(opl4_t *opl4, opl4_voice_t *voice)
@@ -553,7 +560,7 @@
 
 void snd_opl4_note_off(void *private_data, int note, int vel, snd_midi_channel_t *chan)
 {
-	opl4_t *opl4 = snd_magic_cast(opl4_t, private_data, return);
+	opl4_t *opl4 = private_data;
 
 	snd_opl4_do_for_note(opl4, note, chan, snd_opl4_voice_off);
 }
@@ -569,14 +576,14 @@
 
 void snd_opl4_terminate_note(void *private_data, int note, snd_midi_channel_t *chan)
 {
-	opl4_t *opl4 = snd_magic_cast(opl4_t, private_data, return);
+	opl4_t *opl4 = private_data;
 
 	snd_opl4_do_for_note(opl4, note, chan, snd_opl4_terminate_voice);
 }
 
 void snd_opl4_control(void *private_data, int type, snd_midi_channel_t *chan)
 {
-	opl4_t *opl4 = snd_magic_cast(opl4_t, private_data, return);
+	opl4_t *opl4 = private_data;
 
 	switch (type) {
 	case MIDI_CTL_MSB_MODWHEEL:
@@ -616,7 +623,7 @@
 void snd_opl4_sysex(void *private_data, unsigned char *buf, int len,
 		    int parsed, snd_midi_channel_set_t *chset)
 {
-	opl4_t *opl4 = snd_magic_cast(opl4_t, private_data, return);
+	opl4_t *opl4 = private_data;
 
 	if (parsed == SNDRV_MIDI_SYSEX_GS_MASTER_VOLUME)
 		snd_opl4_do_for_all(opl4, snd_opl4_update_volume);
diff -Nru a/sound/drivers/serial-u16550.c b/sound/drivers/serial-u16550.c
--- a/sound/drivers/serial-u16550.c	2004-10-18 14:55:54 -07:00
+++ b/sound/drivers/serial-u16550.c	2004-10-18 14:55:54 -07:00
@@ -46,8 +46,7 @@
 
 MODULE_DESCRIPTION("MIDI serial u16550");
 MODULE_LICENSE("GPL");
-MODULE_CLASSES("{sound}");
-MODULE_DEVICES("{{ALSA, MIDI serial u16550}}");
+MODULE_SUPPORTED_DEVICE("{{ALSA, MIDI serial u16550}}");
 
 #define SNDRV_SERIAL_SOUNDCANVAS 0 /* Roland Soundcanvas; F5 NN selects part */
 #define SNDRV_SERIAL_MS124T 1      /* Midiator MS-124T */
@@ -81,38 +80,27 @@
 
 module_param_array(index, int, boot_devs, 0444);
 MODULE_PARM_DESC(index, "Index value for Serial MIDI.");
-MODULE_PARM_SYNTAX(index, SNDRV_INDEX_DESC);
 module_param_array(id, charp, boot_devs, 0444);
 MODULE_PARM_DESC(id, "ID string for Serial MIDI.");
-MODULE_PARM_SYNTAX(id, SNDRV_ID_DESC);
 module_param_array(enable, bool, boot_devs, 0444);
 MODULE_PARM_DESC(enable, "Enable UART16550A chip.");
-MODULE_PARM_SYNTAX(enable, SNDRV_ENABLE_DESC);
 module_param_array(port, long, boot_devs, 0444);
 MODULE_PARM_DESC(port, "Port # for UART16550A chip.");
-MODULE_PARM_SYNTAX(port, SNDRV_PORT12_DESC);
 module_param_array(irq, int, boot_devs, 0444);
 MODULE_PARM_DESC(irq, "IRQ # for UART16550A chip.");
-MODULE_PARM_SYNTAX(irq, SNDRV_IRQ_DESC);
 module_param_array(speed, int, boot_devs, 0444);
 MODULE_PARM_DESC(speed, "Speed in bauds.");
-MODULE_PARM_SYNTAX(speed, SNDRV_ENABLED ",allows:{9600,19200,38400,57600,115200},dialog:list");
 module_param_array(base, int, boot_devs, 0444);
 MODULE_PARM_DESC(base, "Base for divisor in bauds.");
-MODULE_PARM_SYNTAX(base, SNDRV_ENABLED ",allows:{57600,115200,230400,460800},dialog:list");
 module_param_array(outs, int, boot_devs, 0444);
 MODULE_PARM_DESC(outs, "Number of MIDI outputs.");
 module_param_array(ins, int, boot_devs, 0444);
 MODULE_PARM_DESC(ins, "Number of MIDI inputs.");
 module_param_array(droponfull, bool, boot_devs, 0444);
 MODULE_PARM_DESC(droponfull, "Flag to enable drop-on-full buffer mode");
-MODULE_PARM_SYNTAX(droponfull, SNDRV_ENABLED "," SNDRV_BOOLEAN_FALSE_DESC);
 
-MODULE_PARM_SYNTAX(outs, SNDRV_ENABLED ",allows:{{1,16}},dialog:list");
-MODULE_PARM_SYNTAX(ins, SNDRV_ENABLED ",allows:{{1,16}},dialog:list");
 module_param_array(adaptor, int, boot_devs, 0444);
 MODULE_PARM_DESC(adaptor, "Type of adaptor.");
-MODULE_PARM_SYNTAX(adaptor, SNDRV_ENABLED ",allows:{{0=Soundcanvas,1=MS-124T,2=MS-124W S/A,3=MS-124W M/B,4=Generic}},dialog:list");
 
 /*#define SNDRV_SERIAL_MS124W_MB_NOCOMBO 1*/  /* Address outs as 0-3 instead of bitmap */
 
@@ -524,7 +512,7 @@
 static int snd_uart16550_input_open(snd_rawmidi_substream_t * substream)
 {
 	unsigned long flags;
-	snd_uart16550_t *uart = snd_magic_cast(snd_uart16550_t, substream->rmidi->private_data, return -ENXIO);
+	snd_uart16550_t *uart = substream->rmidi->private_data;
 
 	spin_lock_irqsave(&uart->open_lock, flags);
 	if (uart->filemode == SERIAL_MODE_NOT_OPENED)
@@ -538,7 +526,7 @@
 static int snd_uart16550_input_close(snd_rawmidi_substream_t * substream)
 {
 	unsigned long flags;
-	snd_uart16550_t *uart = snd_magic_cast(snd_uart16550_t, substream->rmidi->private_data, return -ENXIO);
+	snd_uart16550_t *uart = substream->rmidi->private_data;
 
 	spin_lock_irqsave(&uart->open_lock, flags);
 	uart->filemode &= ~SERIAL_MODE_INPUT_OPEN;
@@ -552,7 +540,7 @@
 static void snd_uart16550_input_trigger(snd_rawmidi_substream_t * substream, int up)
 {
 	unsigned long flags;
-	snd_uart16550_t *uart = snd_magic_cast(snd_uart16550_t, substream->rmidi->private_data, return);
+	snd_uart16550_t *uart = substream->rmidi->private_data;
 
 	spin_lock_irqsave(&uart->open_lock, flags);
 	if (up) {
@@ -566,7 +554,7 @@
 static int snd_uart16550_output_open(snd_rawmidi_substream_t * substream)
 {
 	unsigned long flags;
-	snd_uart16550_t *uart = snd_magic_cast(snd_uart16550_t, substream->rmidi->private_data, return -ENXIO);
+	snd_uart16550_t *uart = substream->rmidi->private_data;
 
 	spin_lock_irqsave(&uart->open_lock, flags);
 	if (uart->filemode == SERIAL_MODE_NOT_OPENED)
@@ -580,7 +568,7 @@
 static int snd_uart16550_output_close(snd_rawmidi_substream_t * substream)
 {
 	unsigned long flags;
-	snd_uart16550_t *uart = snd_magic_cast(snd_uart16550_t, substream->rmidi->private_data, return -ENXIO);
+	snd_uart16550_t *uart = substream->rmidi->private_data;
 
 	spin_lock_irqsave(&uart->open_lock, flags);
 	uart->filemode &= ~SERIAL_MODE_OUTPUT_OPEN;
@@ -652,7 +640,7 @@
 {
 	unsigned long flags;
 	unsigned char midi_byte, addr_byte;
-	snd_uart16550_t *uart = snd_magic_cast(snd_uart16550_t, substream->rmidi->private_data, return);
+	snd_uart16550_t *uart = substream->rmidi->private_data;
 	char first;
 	static unsigned long lasttime=0;
 	
@@ -730,7 +718,7 @@
 static void snd_uart16550_output_trigger(snd_rawmidi_substream_t * substream, int up)
 {
 	unsigned long flags;
-	snd_uart16550_t *uart = snd_magic_cast(snd_uart16550_t, substream->rmidi->private_data, return);
+	snd_uart16550_t *uart = substream->rmidi->private_data;
 
 	spin_lock_irqsave(&uart->open_lock, flags);
 	if (up) {
@@ -765,13 +753,13 @@
 		release_resource(uart->res_base);
 		kfree_nocheck(uart->res_base);
 	}
-	snd_magic_kfree(uart);
+	kfree(uart);
 	return 0;
 };
 
 static int snd_uart16550_dev_free(snd_device_t *device)
 {
-	snd_uart16550_t *uart = snd_magic_cast(snd_uart16550_t, device->device_data, return -ENXIO);
+	snd_uart16550_t *uart = device->device_data;
 	return snd_uart16550_free(uart);
 }
 
@@ -791,7 +779,7 @@
 	int err;
 
 
-	if ((uart = snd_magic_kcalloc(snd_uart16550_t, 0, GFP_KERNEL)) == NULL)
+	if ((uart = kcalloc(1, sizeof(*uart), GFP_KERNEL)) == NULL)
 		return -ENOMEM;
 	uart->adaptor = adaptor;
 	uart->card = card;
diff -Nru a/sound/drivers/virmidi.c b/sound/drivers/virmidi.c
--- a/sound/drivers/virmidi.c	2004-10-18 14:56:20 -07:00
+++ b/sound/drivers/virmidi.c	2004-10-18 14:56:20 -07:00
@@ -57,8 +57,7 @@
 MODULE_AUTHOR("Takashi Iwai <tiwai@suse.de>");
 MODULE_DESCRIPTION("Dummy soundcard for virtual rawmidi devices");
 MODULE_LICENSE("GPL");
-MODULE_CLASSES("{sound}");
-MODULE_DEVICES("{{ALSA,Virtual rawmidi device}}");
+MODULE_SUPPORTED_DEVICE("{{ALSA,Virtual rawmidi device}}");
 
 #define MAX_MIDI_DEVICES	8
 
@@ -70,16 +69,12 @@
 
 module_param_array(index, int, boot_devs, 0444);
 MODULE_PARM_DESC(index, "Index value for virmidi soundcard.");
-MODULE_PARM_SYNTAX(index, SNDRV_INDEX_DESC);
 module_param_array(id, charp, boot_devs, 0444);
 MODULE_PARM_DESC(id, "ID string for virmidi soundcard.");
-MODULE_PARM_SYNTAX(id, SNDRV_ID_DESC);
 module_param_array(enable, bool, boot_devs, 0444);
 MODULE_PARM_DESC(enable, "Enable this soundcard.");
-MODULE_PARM_SYNTAX(enable, SNDRV_ENABLE_DESC);
 module_param_array(midi_devs, int, boot_devs, 0444);
 MODULE_PARM_DESC(midi_devs, "MIDI devices # (1-8)");
-MODULE_PARM_SYNTAX(midi_devs, SNDRV_ENABLED ",allows:{{1,8}}");
 
 typedef struct snd_card_virmidi {
 	snd_card_t *card;
@@ -113,7 +108,7 @@
 		snd_virmidi_dev_t *rdev;
 		if ((err = snd_virmidi_new(card, idx, &rmidi)) < 0)
 			goto __nodev;
-		rdev = snd_magic_cast(snd_virmidi_dev_t, rmidi->private_data, continue);
+		rdev = rmidi->private_data;
 		vmidi->midi[idx] = rmidi;
 		strcpy(rmidi->name, "Virtual Raw MIDI");
 		rdev->seq_mode = SNDRV_VIRMIDI_SEQ_DISPATCH;
diff -Nru a/sound/drivers/vx/vx_core.c b/sound/drivers/vx/vx_core.c
--- a/sound/drivers/vx/vx_core.c	2004-10-18 14:57:03 -07:00
+++ b/sound/drivers/vx/vx_core.c	2004-10-18 14:57:03 -07:00
@@ -506,7 +506,7 @@
  */
 static void vx_interrupt(unsigned long private_data)
 {
-	vx_core_t *chip = snd_magic_cast(vx_core_t, (void*)private_data, return);
+	vx_core_t *chip = (vx_core_t *) private_data;
 	unsigned int events;
 		
 	if (chip->chip_status & VX_STAT_IS_STALE)
@@ -550,7 +550,7 @@
  */
 irqreturn_t snd_vx_irq_handler(int irq, void *dev, struct pt_regs *regs)
 {
-	vx_core_t *chip = snd_magic_cast(vx_core_t, dev, return IRQ_NONE);
+	vx_core_t *chip = dev;
 
 	if (! (chip->chip_status & VX_STAT_CHIP_INIT) ||
 	    (chip->chip_status & VX_STAT_IS_STALE))
@@ -572,6 +572,7 @@
 	if (cold_reset) {
 		chip->audio_source_target = chip->audio_source;
 		chip->clock_source = INTERNAL_QUARTZ;
+		chip->clock_mode = VX_CLOCK_MODE_AUTO;
 		chip->freq = 48000;
 		chip->uer_detected = VX_UER_MODE_NOT_PRESENT;
 		chip->uer_bits = SNDRV_PCM_DEFAULT_CON_SPDIF;
@@ -603,9 +604,10 @@
 
 static void vx_proc_read(snd_info_entry_t *entry, snd_info_buffer_t *buffer)
 {
-	vx_core_t *chip = snd_magic_cast(vx_core_t, entry->private_data, return);
+	vx_core_t *chip = entry->private_data;
 	static char *audio_src_vxp[] = { "Line", "Mic", "Digital" };
 	static char *audio_src_vx2[] = { "Analog", "Analog", "Digital" };
+	static char *clock_mode[] = { "Auto", "Internal", "External" };
 	static char *clock_src[] = { "Internal", "External" };
 	static char *uer_type[] = { "Consumer", "Professional", "Not Present" };
 	
@@ -629,6 +631,7 @@
 	snd_iprintf(buffer, "Input Source: %s\n", vx_is_pcmcia(chip) ?
 		    audio_src_vxp[chip->audio_source] :
 		    audio_src_vx2[chip->audio_source]);
+	snd_iprintf(buffer, "Clock Mode: %s\n", clock_mode[chip->clock_mode]);
 	snd_iprintf(buffer, "Clock Source: %s\n", clock_src[chip->clock_source]);
 	snd_iprintf(buffer, "Frequency: %d\n", chip->freq);
 	snd_iprintf(buffer, "Detected Frequency: %d\n", chip->freq_detected);
@@ -731,7 +734,7 @@
 
 	snd_assert(card && hw && ops, return NULL);
 
-	chip = snd_magic_kcalloc(vx_core_t, extra_size, GFP_KERNEL);
+	chip = kcalloc(1, sizeof(chip) + extra_size, GFP_KERNEL);
 	if (! chip) {
 		snd_printk(KERN_ERR "vx_core: no memory\n");
 		return NULL;
diff -Nru a/sound/drivers/vx/vx_hwdep.c b/sound/drivers/vx/vx_hwdep.c
--- a/sound/drivers/vx/vx_hwdep.c	2004-10-18 14:56:28 -07:00
+++ b/sound/drivers/vx/vx_hwdep.c	2004-10-18 14:56:28 -07:00
@@ -44,7 +44,7 @@
 		[VX_TYPE_VXPOCKET] = "vxpocket",
 		[VX_TYPE_VXP440] = "vxp440",
 	};
-	vx_core_t *vx = snd_magic_cast(vx_core_t, hw->private_data, return -ENXIO);
+	vx_core_t *vx = hw->private_data;
 
 	snd_assert(type_ids[vx->type], return -EINVAL);
 	strcpy(info->id, type_ids[vx->type]);
@@ -60,7 +60,7 @@
 
 static int vx_hwdep_dsp_load(snd_hwdep_t *hw, snd_hwdep_dsp_image_t *dsp)
 {
-	vx_core_t *vx = snd_magic_cast(vx_core_t, hw->private_data, return -ENXIO);
+	vx_core_t *vx = hw->private_data;
 	int index, err;
 
 	snd_assert(vx->ops->load_dsp, return -ENXIO);
diff -Nru a/sound/drivers/vx/vx_mixer.c b/sound/drivers/vx/vx_mixer.c
--- a/sound/drivers/vx/vx_mixer.c	2004-10-18 14:56:27 -07:00
+++ b/sound/drivers/vx/vx_mixer.c	2004-10-18 14:56:27 -07:00
@@ -26,8 +26,6 @@
 #include <sound/vx_core.h>
 #include "vx_cmd.h"
 
-#define chip_t vx_core_t
-
 
 /*
  * write a codec data (24bit)
@@ -524,6 +522,54 @@
 };
 
 /*
+ * clock mode selection
+ */
+static int vx_clock_mode_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo)
+{
+	static char *texts[3] = {
+		"Auto", "Internal", "External"
+	};
+
+	uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
+	uinfo->count = 1;
+	uinfo->value.enumerated.items = 3;
+	if (uinfo->value.enumerated.item > 2)
+		uinfo->value.enumerated.item = 2;
+	strcpy(uinfo->value.enumerated.name,
+	       texts[uinfo->value.enumerated.item]);
+	return 0;
+}
+
+static int vx_clock_mode_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+{
+	vx_core_t *chip = snd_kcontrol_chip(kcontrol);
+	ucontrol->value.enumerated.item[0] = chip->clock_mode;
+	return 0;
+}
+
+static int vx_clock_mode_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+{
+	vx_core_t *chip = snd_kcontrol_chip(kcontrol);
+	down(&chip->mixer_mutex);
+	if (chip->clock_mode != ucontrol->value.enumerated.item[0]) {
+		chip->clock_mode = ucontrol->value.enumerated.item[0];
+		vx_set_clock(chip, chip->freq);
+		up(&chip->mixer_mutex);
+		return 1;
+	}
+	up(&chip->mixer_mutex);
+	return 0;
+}
+
+static snd_kcontrol_new_t vx_control_clock_mode = {
+	.iface =	SNDRV_CTL_ELEM_IFACE_MIXER,
+	.name =		"Clock Mode",
+	.info =		vx_clock_mode_info,
+	.get =		vx_clock_mode_get,
+	.put =		vx_clock_mode_put,
+};
+
+/*
  * Audio Gain
  */
 static int vx_audio_gain_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo)
@@ -912,6 +958,9 @@
 
 	/* Audio source */
 	if ((err = snd_ctl_add(card, snd_ctl_new1(&vx_control_audio_src, chip))) < 0)
+		return err;
+	/* clock mode */
+	if ((err = snd_ctl_add(card, snd_ctl_new1(&vx_control_clock_mode, chip))) < 0)
 		return err;
 	/* IEC958 controls */
 	if ((err = snd_ctl_add(card, snd_ctl_new1(&vx_control_iec958_mask, chip))) < 0)
diff -Nru a/sound/drivers/vx/vx_pcm.c b/sound/drivers/vx/vx_pcm.c
--- a/sound/drivers/vx/vx_pcm.c	2004-10-18 14:55:54 -07:00
+++ b/sound/drivers/vx/vx_pcm.c	2004-10-18 14:55:54 -07:00
@@ -48,14 +48,13 @@
 #include <sound/driver.h>
 #include <linux/slab.h>
 #include <linux/vmalloc.h>
+#include <linux/delay.h>
 #include <sound/core.h>
 #include <sound/asoundef.h>
 #include <sound/pcm.h>
 #include <sound/vx_core.h>
 #include "vx_cmd.h"
 
-#define chip_t	vx_core_t
-
 
 /*
  * we use a vmalloc'ed (sg-)buffer
@@ -381,7 +380,7 @@
  */
 static int vx_toggle_pipe(vx_core_t *chip, vx_pipe_t *pipe, int state)
 {
-	int err, i, cur_state, delay;
+	int err, i, cur_state;
 
 	/* Check the pipe is not already in the requested state */
 	if (vx_get_pipe_state(chip, pipe, &cur_state) < 0)
@@ -394,17 +393,14 @@
 	 * enough sound buffer for this pipe)
 	 */
 	if (state) {
-		int delay = CAN_START_DELAY;
 		for (i = 0 ; i < MAX_WAIT_FOR_DSP; i++) {
-			snd_vx_delay(chip, delay);
 			err = vx_pipe_can_start(chip, pipe);
 			if (err > 0)
 				break;
 			/* Wait for a few, before asking again
 			 * to avoid flooding the DSP with our requests
 			 */
-			if ((i % 4 ) == 0)
-				delay <<= 1;
+			mdelay(1);
 		}
 	}
     
@@ -418,15 +414,12 @@
 	 * reaching the expected state before returning
 	 * Check one pipe only (since they are synchronous)
 	 */
-	delay = WAIT_STATE_DELAY;
 	for (i = 0; i < MAX_WAIT_FOR_DSP; i++) {
-		snd_vx_delay(chip, delay);
 		err = vx_get_pipe_state(chip, pipe, &cur_state);
 		if (err < 0 || cur_state == state)
 			break;
 		err = -EIO;
-		if ((i % 4 ) == 0)
-			delay <<= 1;
+		mdelay(1);
 	}
 	return err < 0 ? -EIO : 0;
 }
@@ -480,7 +473,7 @@
 		return err;
 
 	/* initialize the pipe record */
-	pipe = snd_magic_kcalloc(vx_pipe_t, 0, GFP_KERNEL);
+	pipe = kcalloc(1, sizeof(*pipe), GFP_KERNEL);
 	if (! pipe) {
 		/* release the pipe */
 		vx_init_rmh(&rmh, CMD_FREE_PIPE);
@@ -514,7 +507,7 @@
 	vx_set_pipe_cmd_params(&rmh, pipe->is_capture, pipe->number, 0);
 	vx_send_msg(chip, &rmh);
 
-	snd_magic_kfree(pipe);
+	kfree(pipe);
 	return 0;
 }
 
@@ -629,7 +622,7 @@
 	if (! subs->runtime->private_data)
 		return -EINVAL;
 
-	pipe = snd_magic_cast(vx_pipe_t, subs->runtime->private_data, return -EINVAL);
+	pipe = subs->runtime->private_data;
 
 	if (--pipe->references == 0) {
 		chip->playback_pipes[pipe->number] = NULL;
@@ -778,8 +771,8 @@
 static void vx_pcm_delayed_start(unsigned long arg)
 {
 	snd_pcm_substream_t *subs = (snd_pcm_substream_t *)arg;
-	vx_core_t *chip = snd_magic_cast(vx_core_t, subs->pcm->private_data, return);
-	vx_pipe_t *pipe = snd_magic_cast(vx_pipe_t, subs->runtime->private_data, return);
+	vx_core_t *chip = subs->pcm->private_data;
+	vx_pipe_t *pipe = subs->runtime->private_data;
 	int err;
 
 	/*  printk( KERN_DEBUG "DDDD tasklet delayed start jiffies = %ld\n", jiffies);*/
@@ -801,7 +794,7 @@
 static int vx_pcm_trigger(snd_pcm_substream_t *subs, int cmd)
 {
 	vx_core_t *chip = snd_pcm_substream_chip(subs);
-	vx_pipe_t *pipe = snd_magic_cast(vx_pipe_t, subs->runtime->private_data, return -EINVAL);
+	vx_pipe_t *pipe = subs->runtime->private_data;
 	int err;
 
 	if (chip->chip_status & VX_STAT_IS_STALE)
@@ -846,7 +839,7 @@
 static snd_pcm_uframes_t vx_pcm_playback_pointer(snd_pcm_substream_t *subs)
 {
 	snd_pcm_runtime_t *runtime = subs->runtime;
-	vx_pipe_t *pipe = snd_magic_cast(vx_pipe_t, runtime->private_data, return -EINVAL);
+	vx_pipe_t *pipe = runtime->private_data;
 	return pipe->position;
 }
 
@@ -874,7 +867,7 @@
 {
 	vx_core_t *chip = snd_pcm_substream_chip(subs);
 	snd_pcm_runtime_t *runtime = subs->runtime;
-	vx_pipe_t *pipe = snd_magic_cast(vx_pipe_t, runtime->private_data, return -EINVAL);
+	vx_pipe_t *pipe = runtime->private_data;
 	int err, data_mode;
 	// int max_size, nchunks;
 
@@ -1037,7 +1030,7 @@
 	
 	if (! subs->runtime->private_data)
 		return -EINVAL;
-	pipe = snd_magic_cast(vx_pipe_t, subs->runtime->private_data, return -EINVAL);
+	pipe = subs->runtime->private_data;
 	chip->capture_pipes[pipe->number] = NULL;
 
 	pipe_out_monitoring = pipe->monitoring_pipe;
@@ -1141,7 +1134,7 @@
 static snd_pcm_uframes_t vx_pcm_capture_pointer(snd_pcm_substream_t *subs)
 {
 	snd_pcm_runtime_t *runtime = subs->runtime;
-	vx_pipe_t *pipe = snd_magic_cast(vx_pipe_t, runtime->private_data, return -EINVAL);
+	vx_pipe_t *pipe = runtime->private_data;
 	return bytes_to_frames(runtime, pipe->hw_ptr);
 }
 
@@ -1265,7 +1258,7 @@
  */
 static void snd_vx_pcm_free(snd_pcm_t *pcm)
 {
-	vx_core_t *chip = snd_magic_cast(vx_core_t, pcm->private_data, return);
+	vx_core_t *chip = pcm->private_data;
 	chip->pcm[pcm->device] = NULL;
 	if (chip->playback_pipes) {
 		kfree(chip->playback_pipes);
diff -Nru a/sound/drivers/vx/vx_uer.c b/sound/drivers/vx/vx_uer.c
--- a/sound/drivers/vx/vx_uer.c	2004-10-18 14:56:27 -07:00
+++ b/sound/drivers/vx/vx_uer.c	2004-10-18 14:56:27 -07:00
@@ -263,17 +263,17 @@
 	/* change the audio source if possible */
 	vx_sync_audio_source(chip);
 
-	switch (chip->audio_source) {
-	case VX_AUDIO_SRC_DIGITAL:
+	if (chip->clock_mode == VX_CLOCK_MODE_EXTERNAL ||
+	    (chip->clock_mode == VX_CLOCK_MODE_AUTO &&
+	     chip->audio_source == VX_AUDIO_SRC_DIGITAL)) {
 		if (chip->clock_source != UER_SYNC) {
 			vx_change_clock_source(chip, UER_SYNC);
 			mdelay(6);
 			src_changed = 1;
 		}
-		if (chip->freq == freq)
-			return 0;
-		break;
-	default:
+	} else if (chip->clock_mode == VX_CLOCK_MODE_INTERNAL ||
+		   (chip->clock_mode == VX_CLOCK_MODE_AUTO &&
+		    chip->audio_source != VX_AUDIO_SRC_DIGITAL)) {
 		if (chip->clock_source != INTERNAL_QUARTZ) {
 			vx_change_clock_source(chip, INTERNAL_QUARTZ);
 			src_changed = 1;
@@ -283,8 +283,9 @@
 		vx_set_internal_clock(chip, freq);
 		if (src_changed)
 			vx_modify_board_inputs(chip);
-		break;
 	}
+	if (chip->freq == freq)
+		return 0;
 	chip->freq = freq;
 	vx_modify_board_clock(chip, 1);
 	return 0;
diff -Nru a/sound/i2c/cs8427.c b/sound/i2c/cs8427.c
--- a/sound/i2c/cs8427.c	2004-10-18 14:55:54 -07:00
+++ b/sound/i2c/cs8427.c	2004-10-18 14:55:54 -07:00
@@ -34,8 +34,6 @@
 MODULE_DESCRIPTION("IEC958 (S/PDIF) receiver & transmitter by Cirrus Logic");
 MODULE_LICENSE("GPL");
 
-#define chip_t snd_i2c_device_t
-
 #define CS8427_ADDR			(0x20>>1) /* fixed address */
 
 typedef struct {
@@ -109,7 +107,7 @@
 
 static int snd_cs8427_select_corudata(snd_i2c_device_t *device, int udata)
 {
-	cs8427_t *chip = snd_magic_cast(cs8427_t, device->private_data, return -ENXIO);
+	cs8427_t *chip = device->private_data;
 	int err;
 
 	udata = udata ? CS8427_BSEL : 0;
@@ -128,7 +126,7 @@
 				    unsigned char *ndata,
 				    int count)
 {
-	cs8427_t *chip = snd_magic_cast(cs8427_t, device->private_data, return -ENXIO);
+	cs8427_t *chip = device->private_data;
 	char *hw_data = udata ? chip->playback.hw_udata : chip->playback.hw_status;
 	char data[32];
 	int err, idx;
@@ -159,7 +157,7 @@
 static void snd_cs8427_free(snd_i2c_device_t *device)
 {
 	if (device->private_data)
-		snd_magic_kfree(device->private_data);
+		kfree(device->private_data);
 }
 
 int snd_cs8427_create(snd_i2c_bus_t *bus,
@@ -211,7 +209,7 @@
 
 	if ((err = snd_i2c_device_create(bus, "CS8427", CS8427_ADDR | (addr & 7), &device)) < 0)
 		return err;
-	chip = device->private_data = snd_magic_kcalloc(cs8427_t, 0, GFP_KERNEL);
+	chip = device->private_data = kcalloc(1, sizeof(*chip), GFP_KERNEL);
 	if (chip == NULL) {
 	      	snd_i2c_device_free(device);
 		return -ENOMEM;
@@ -297,7 +295,7 @@
 	int data;
 
 	snd_assert(cs8427, return);
-	chip = snd_magic_cast(cs8427_t, cs8427->private_data, return);
+	chip = cs8427->private_data;
 	snd_i2c_lock(cs8427->bus);
 	chip->regmap[CS8427_REG_CLOCKSOURCE] &= ~(CS8427_RUN | CS8427_RXDMASK);
 	snd_cs8427_reg_write(cs8427, CS8427_REG_CLOCKSOURCE, chip->regmap[CS8427_REG_CLOCKSOURCE]);
@@ -389,7 +387,7 @@
 				snd_ctl_elem_value_t * ucontrol)
 {
 	snd_i2c_device_t *device = snd_kcontrol_chip(kcontrol);
-	cs8427_t *chip = snd_magic_cast(cs8427_t, device->private_data, return -ENXIO);
+	cs8427_t *chip = device->private_data;
 	
 	snd_i2c_lock(device->bus);
 	memcpy(ucontrol->value.iec958.status, chip->playback.def_status, 24);
@@ -401,7 +399,7 @@
 				snd_ctl_elem_value_t * ucontrol)
 {
 	snd_i2c_device_t *device = snd_kcontrol_chip(kcontrol);
-	cs8427_t *chip = snd_magic_cast(cs8427_t, device->private_data, return -ENXIO);
+	cs8427_t *chip = device->private_data;
 	unsigned char *status = kcontrol->private_value ? chip->playback.pcm_status : chip->playback.def_status;
 	snd_pcm_runtime_t *runtime = chip->playback.substream ? chip->playback.substream->runtime : NULL;
 	int err, change;
@@ -432,8 +430,6 @@
 	return 0;
 }
 
-#define CONTROLS (sizeof(snd_cs8427_iec958_controls)/sizeof(snd_kcontrol_new_t))
-
 static snd_kcontrol_new_t snd_cs8427_iec958_controls[] = {
 {
 	.iface =	SNDRV_CTL_ELEM_IFACE_PCM,
@@ -487,13 +483,13 @@
 			    snd_pcm_substream_t *play_substream,
 			    snd_pcm_substream_t *cap_substream)
 {
-	cs8427_t *chip = snd_magic_cast(cs8427_t, cs8427->private_data, return -ENXIO);
+	cs8427_t *chip = cs8427->private_data;
 	snd_kcontrol_t *kctl;
 	unsigned int idx;
 	int err;
 
 	snd_assert(play_substream && cap_substream, return -EINVAL);
-	for (idx = 0; idx < CONTROLS; idx++) {
+	for (idx = 0; idx < ARRAY_SIZE(snd_cs8427_iec958_controls); idx++) {
 		kctl = snd_ctl_new1(&snd_cs8427_iec958_controls[idx], cs8427);
 		if (kctl == NULL)
 			return -ENOMEM;
@@ -517,7 +513,7 @@
 	cs8427_t *chip;
 
 	snd_assert(cs8427, return -ENXIO);
-	chip = snd_magic_cast(cs8427_t, cs8427->private_data, return -ENXIO);
+	chip = cs8427->private_data;
 	if (active)
 		memcpy(chip->playback.pcm_status, chip->playback.def_status, 24);
 	chip->playback.pcm_ctl->vd[0].access &= ~SNDRV_CTL_ELEM_ACCESS_INACTIVE;
@@ -533,7 +529,7 @@
 	int err, reset;
 
 	snd_assert(cs8427, return -ENXIO);
-	chip = snd_magic_cast(cs8427_t, cs8427->private_data, return -ENXIO);
+	chip = cs8427->private_data;
 	status = chip->playback.pcm_status;
 	snd_i2c_lock(cs8427->bus);
 	if (status[0] & IEC958_AES0_PROFESSIONAL) {
diff -Nru a/sound/i2c/i2c.c b/sound/i2c/i2c.c
--- a/sound/i2c/i2c.c	2004-10-18 14:56:29 -07:00
+++ b/sound/i2c/i2c.c	2004-10-18 14:56:29 -07:00
@@ -62,13 +62,13 @@
 	}
 	if (bus->private_free)
 		bus->private_free(bus);
-	snd_magic_kfree(bus);
+	kfree(bus);
 	return 0;
 }
 
 static int snd_i2c_bus_dev_free(snd_device_t *device)
 {
-	snd_i2c_bus_t *bus = snd_magic_cast(snd_i2c_bus_t, device->device_data, return -ENXIO);
+	snd_i2c_bus_t *bus = device->device_data;
 	return snd_i2c_bus_free(bus);
 }
 
@@ -81,7 +81,7 @@
 	};
 
 	*ri2c = NULL;
-	bus = (snd_i2c_bus_t *)snd_magic_kcalloc(snd_i2c_bus_t, 0, GFP_KERNEL);
+	bus = kcalloc(1, sizeof(*bus), GFP_KERNEL);
 	if (bus == NULL)
 		return -ENOMEM;
 	init_MUTEX(&bus->lock_mutex);
@@ -108,7 +108,7 @@
 
 	*rdevice = NULL;
 	snd_assert(bus != NULL, return -EINVAL);
-	device = (snd_i2c_device_t *)snd_magic_kcalloc(snd_i2c_device_t, 0, GFP_KERNEL);
+	device = kcalloc(1, sizeof(*device), GFP_KERNEL);
 	if (device == NULL)
 		return -ENOMEM;
 	device->addr = addr;
@@ -125,7 +125,7 @@
 		list_del(&device->list);
 	if (device->private_free)
 		device->private_free(device);
-	snd_magic_kfree(device);
+	kfree(device);
 	return 0;
 }
 
diff -Nru a/sound/i2c/l3/uda1341.c b/sound/i2c/l3/uda1341.c
--- a/sound/i2c/l3/uda1341.c	2004-10-18 14:56:32 -07:00
+++ b/sound/i2c/l3/uda1341.c	2004-10-18 14:56:32 -07:00
@@ -17,7 +17,7 @@
  * 2002-05-12   Tomas Kasparek  another code cleanup
  */
 
-/* $Id: uda1341.c,v 1.10 2003/10/23 14:34:52 perex Exp $ */
+/* $Id: uda1341.c,v 1.13 2004/07/20 15:54:13 cladisch Exp $ */
 
 #include <sound/driver.h>
 #include <linux/module.h>
@@ -131,7 +131,6 @@
 
 //hack for ALSA magic casting
 typedef struct l3_client l3_client_t;
-#define chip_t l3_client_t      
 
 /* transfer 8bit integer into string with binary representation */
 void int2str_bin8(uint8_t val, char *buf){
@@ -332,7 +331,7 @@
 static void snd_uda1341_proc_read(snd_info_entry_t *entry, 
 				  snd_info_buffer_t * buffer)
 {
-	struct l3_client *clnt = snd_magic_cast(l3_client_t, entry->private_data, return);
+	struct l3_client *clnt = entry->private_data;
 	struct uda1341 *uda = clnt->driver_data;
 	int peak;
 
@@ -397,7 +396,7 @@
 static void snd_uda1341_proc_regs_read(snd_info_entry_t *entry, 
 				       snd_info_buffer_t * buffer)
 {
-	struct l3_client *clnt = snd_magic_cast(l3_client_t, entry->private_data, return);
+	struct l3_client *clnt = entry->private_data;
 	struct uda1341 *uda = clnt->driver_data;		
 	int reg;
 	char buf[12];
@@ -618,8 +617,6 @@
 
 /* }}} */
   
-#define UDA1341_CONTROLS (sizeof(snd_uda1341_controls)/sizeof(snd_kcontrol_new_t))
-
 static snd_kcontrol_new_t snd_uda1341_controls[] = {
 	UDA1341_SINGLE("Master Playback Switch", CMD_MUTE, data0_2, 2, 1, 1),
 	UDA1341_SINGLE("Master Playback Volume", CMD_VOLUME, data0_0, 0, 63, 1),
@@ -653,12 +650,12 @@
 static void uda1341_free(struct l3_client *uda1341)
 {
 	l3_detach_client(uda1341); // calls kfree for driver_data (uda1341_t)
-	snd_magic_kfree(uda1341);
+	kfree(uda1341);
 }
 
 static int uda1341_dev_free(snd_device_t *device)
 {
-	struct l3_client *clnt = snd_magic_cast(l3_client_t, device->device_data, return);
+	struct l3_client *clnt = device->device_data;
 	uda1341_free(clnt);
 	return 0;
 }
@@ -673,7 +670,7 @@
 
 	snd_assert(card != NULL, return -EINVAL);
 
-	uda1341 = snd_magic_kcalloc(l3_client_t, 0, GFP_KERNEL);
+	uda1341 = kcalloc(1, sizeof(*uda1341), GFP_KERNEL);
 	if (uda1341 == NULL)
 		return -ENOMEM;
          
@@ -688,7 +685,7 @@
 		return err;
 	}
 
-	for (idx = 0; idx < UDA1341_CONTROLS; idx++) {
+	for (idx = 0; idx < ARRAY_SIZE(snd_uda1341_controls); idx++) {
 		if ((err = snd_ctl_add(card, snd_ctl_new1(&snd_uda1341_controls[idx], uda1341))) < 0)
 			return err;
 	}
@@ -710,7 +707,7 @@
 {
 	struct uda1341 *uda;
 
-	uda = snd_magic_kcalloc(uda1341_t, 0, GFP_KERNEL);
+	uda = kcalloc(1, sizeof(*uda), 0, GFP_KERNEL);
 	if (!uda)
 		return -ENOMEM;
 
@@ -734,7 +731,7 @@
 static void uda1341_detach(struct l3_client *clnt)
 {
 	if (clnt->driver_data)
-		snd_magic_kfree(clnt->driver_data);
+		kfree(clnt->driver_data);
 }
 
 static int
@@ -821,8 +818,7 @@
 MODULE_AUTHOR("Tomas Kasparek <tomas.kasparek@seznam.cz>");
 MODULE_LICENSE("GPL");
 MODULE_DESCRIPTION("Philips UDA1341 CODEC driver for ALSA");
-MODULE_CLASSES("{sound}");
-MODULE_DEVICES("{{UDA1341,UDA1341TS}}");
+MODULE_SUPPORTED_DEVICE("{{UDA1341,UDA1341TS}}");
 
 EXPORT_SYMBOL(snd_chip_uda1341_mixer_new);
 
diff -Nru a/sound/i2c/other/ak4117.c b/sound/i2c/other/ak4117.c
--- a/sound/i2c/other/ak4117.c	2004-10-18 14:56:33 -07:00
+++ b/sound/i2c/other/ak4117.c	2004-10-18 14:56:33 -07:00
@@ -33,8 +33,6 @@
 MODULE_DESCRIPTION("AK4117 IEC958 (S/PDIF) receiver by Asahi Kasei");
 MODULE_LICENSE("GPL");
 
-#define chip_t ak4117_t
-
 #define AK4117_ADDR			0x00 /* fixed address */
 
 static void snd_ak4117_timer(unsigned long data);
@@ -65,12 +63,12 @@
 static void snd_ak4117_free(ak4117_t *chip)
 {
 	del_timer(&chip->timer);
-	snd_magic_kfree(chip);
+	kfree(chip);
 }
 
 static int snd_ak4117_dev_free(snd_device_t *device)
 {
-	ak4117_t *chip = snd_magic_cast(ak4117_t, device->device_data, return -ENXIO);
+	ak4117_t *chip = device->device_data;
 	snd_ak4117_free(chip);
 	return 0;
 }
@@ -85,7 +83,7 @@
 		.dev_free =     snd_ak4117_dev_free,
 	};
 
-	chip = (ak4117_t *)snd_magic_kcalloc(ak4117_t, 0, GFP_KERNEL);
+	chip = kcalloc(1, sizeof(*chip), GFP_KERNEL);
 	if (chip == NULL)
 		return -ENOMEM;
 	spin_lock_init(&chip->lock);
@@ -544,7 +542,7 @@
 
 static void snd_ak4117_timer(unsigned long data)
 {
-	ak4117_t *chip = snd_magic_cast(ak4117_t, (void *)data, return);
+	ak4117_t *chip = (ak4117_t *)data;
 
 	if (chip->init)
 		return;
diff -Nru a/sound/i2c/other/ak4xxx-adda.c b/sound/i2c/other/ak4xxx-adda.c
--- a/sound/i2c/other/ak4xxx-adda.c	2004-10-18 14:57:04 -07:00
+++ b/sound/i2c/other/ak4xxx-adda.c	2004-10-18 14:57:04 -07:00
@@ -237,7 +237,7 @@
 
 static int snd_akm4xxx_volume_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
 {
-	akm4xxx_t *ak = _snd_kcontrol_chip(kcontrol);
+	akm4xxx_t *ak = snd_kcontrol_chip(kcontrol);
 	int chip = AK_GET_CHIP(kcontrol->private_value);
 	int addr = AK_GET_ADDR(kcontrol->private_value);
 	int invert = AK_GET_INVERT(kcontrol->private_value);
@@ -250,7 +250,7 @@
 
 static int snd_akm4xxx_volume_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
 {
-	akm4xxx_t *ak = _snd_kcontrol_chip(kcontrol);
+	akm4xxx_t *ak = snd_kcontrol_chip(kcontrol);
 	int chip = AK_GET_CHIP(kcontrol->private_value);
 	int addr = AK_GET_ADDR(kcontrol->private_value);
 	int invert = AK_GET_INVERT(kcontrol->private_value);
@@ -277,7 +277,7 @@
 
 static int snd_akm4xxx_ipga_gain_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
 {
-	akm4xxx_t *ak = _snd_kcontrol_chip(kcontrol);
+	akm4xxx_t *ak = snd_kcontrol_chip(kcontrol);
 	int chip = AK_GET_CHIP(kcontrol->private_value);
 	int addr = AK_GET_ADDR(kcontrol->private_value);
 	ucontrol->value.integer.value[0] = snd_akm4xxx_get_ipga(ak, chip, addr) & 0x7f;
@@ -286,7 +286,7 @@
 
 static int snd_akm4xxx_ipga_gain_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
 {
-	akm4xxx_t *ak = _snd_kcontrol_chip(kcontrol);
+	akm4xxx_t *ak = snd_kcontrol_chip(kcontrol);
 	int chip = AK_GET_CHIP(kcontrol->private_value);
 	int addr = AK_GET_ADDR(kcontrol->private_value);
 	unsigned char nval = (ucontrol->value.integer.value[0] % 37) | 0x80;
@@ -312,7 +312,7 @@
 
 static int snd_akm4xxx_deemphasis_get(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t *ucontrol)
 {
-	akm4xxx_t *ak = _snd_kcontrol_chip(kcontrol);
+	akm4xxx_t *ak = snd_kcontrol_chip(kcontrol);
 	int chip = AK_GET_CHIP(kcontrol->private_value);
 	int addr = AK_GET_ADDR(kcontrol->private_value);
 	int shift = AK_GET_SHIFT(kcontrol->private_value);
@@ -322,7 +322,7 @@
 
 static int snd_akm4xxx_deemphasis_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
 {
-	akm4xxx_t *ak = _snd_kcontrol_chip(kcontrol);
+	akm4xxx_t *ak = snd_kcontrol_chip(kcontrol);
 	int chip = AK_GET_CHIP(kcontrol->private_value);
 	int addr = AK_GET_ADDR(kcontrol->private_value);
 	int shift = AK_GET_SHIFT(kcontrol->private_value);
diff -Nru a/sound/i2c/tea6330t.c b/sound/i2c/tea6330t.c
--- a/sound/i2c/tea6330t.c	2004-10-18 14:56:31 -07:00
+++ b/sound/i2c/tea6330t.c	2004-10-18 14:56:31 -07:00
@@ -30,8 +30,6 @@
 MODULE_DESCRIPTION("Routines for control of the TEA6330T circuit via i2c bus");
 MODULE_LICENSE("GPL");
 
-#define chip_t tea6330t_t
-
 #define TEA6330T_ADDR			(0x80>>1) /* fixed address */
 
 #define TEA6330T_SADDR_VOLUME_LEFT	0x00	/* volume left */
@@ -259,8 +257,6 @@
 	return change;
 }
 
-#define TEA6330T_CONTROLS (sizeof(snd_tea6330t_controls)/sizeof(snd_kcontrol_new_t))
-
 static snd_kcontrol_new_t snd_tea6330t_controls[] = {
 TEA6330T_MASTER_SWITCH("Master Playback Switch", 0),
 TEA6330T_MASTER_VOLUME("Master Playback Volume", 0),
@@ -270,8 +266,8 @@
 
 static void snd_tea6330_free(snd_i2c_device_t *device)
 {
-	tea6330t_t *tea = snd_magic_cast(tea6330t_t, device->private_data, return);
-	snd_magic_kfree(tea);
+	tea6330t_t *tea = device->private_data;
+	kfree(tea);
 }
                                         
 int snd_tea6330t_update_mixer(snd_card_t * card,
@@ -286,11 +282,11 @@
 	u8 default_treble, default_bass;
 	unsigned char bytes[7];
 
-	tea = snd_magic_kcalloc(tea6330t_t, 0, GFP_KERNEL);
+	tea = kcalloc(1, sizeof(*tea), GFP_KERNEL);
 	if (tea == NULL)
 		return -ENOMEM;
 	if ((err = snd_i2c_device_create(bus, "TEA6330T", TEA6330T_ADDR, &device)) < 0) {
-		snd_magic_kfree(tea);
+		kfree(tea);
 		return err;
 	}
 	tea->device = device;
@@ -336,7 +332,7 @@
 	if ((err = snd_component_add(card, "TEA6330T")) < 0)
 		goto __error;
 
-	for (idx = 0; idx < TEA6330T_CONTROLS; idx++) {
+	for (idx = 0; idx < ARRAY_SIZE(snd_tea6330t_controls); idx++) {
 		knew = &snd_tea6330t_controls[idx];
 		if (tea->treble == 0 && !strcmp(knew->name, "Tone Control - Treble"))
 			continue;
diff -Nru a/sound/isa/Kconfig b/sound/isa/Kconfig
--- a/sound/isa/Kconfig	2004-10-18 14:56:50 -07:00
+++ b/sound/isa/Kconfig	2004-10-18 14:56:50 -07:00
@@ -77,11 +77,15 @@
 	help
 	  Say 'Y' or 'M' to include support for ESS AudioDrive ES18xx chips.
 
+config SND_GUS_SYNTH
+	tristate
+
 config SND_GUSCLASSIC
 	tristate "Gravis UltraSound Classic"
 	depends on SND
 	select SND_RAWMIDI
 	select SND_PCM
+	select SND_GUS_SYNTH
 	help
 	  Say 'Y' or 'M' to include support for Gravis UltraSound Classic soundcard.
 
@@ -91,6 +95,7 @@
 	select SND_HWDEP
 	select SND_MPU401_UART
 	select SND_PCM
+	select SND_GUS_SYNTH
 	help
 	  Say 'Y' or 'M' to include support for Gravis UltraSound Extreme soundcard.
 
@@ -99,6 +104,7 @@
 	depends on SND
 	select SND_RAWMIDI
 	select SND_PCM
+	select SND_GUS_SYNTH
 	help
 	  Say 'Y' or 'M' to include support for Gravis UltraSound MAX soundcard.
 
@@ -107,6 +113,7 @@
 	depends on SND
 	select SND_RAWMIDI
 	select SND_PCM
+	select SND_GUS_SYNTH
 	help
 	  Say 'Y' or 'M' to include support for AMD InterWave based soundcards
 	  (Gravis UltraSound Plug & Play, STB SoundRage32, MED3210, Dynasonic Pro,
@@ -117,6 +124,7 @@
 	depends on SND
 	select SND_RAWMIDI
 	select SND_PCM
+	select SND_GUS_SYNTH
 	help
 	  Say 'Y' or 'M' to include support for AMD InterWave based soundcards
 	  with TEA6330T bass and treble regulator (UltraSound 32-Pro).
diff -Nru a/sound/isa/ad1816a/ad1816a.c b/sound/isa/ad1816a/ad1816a.c
--- a/sound/isa/ad1816a/ad1816a.c	2004-10-18 14:56:20 -07:00
+++ b/sound/isa/ad1816a/ad1816a.c	2004-10-18 14:56:20 -07:00
@@ -30,15 +30,12 @@
 #include <sound/mpu401.h>
 #include <sound/opl3.h>
 
-#define chip_t ad1816a_t
-
 #define PFX "ad1816a: "
 
 MODULE_AUTHOR("Massimo Piccioni <dafastidio@libero.it>");
 MODULE_DESCRIPTION("AD1816A, AD1815");
 MODULE_LICENSE("GPL");
-MODULE_CLASSES("{sound}");
-MODULE_DEVICES("{{Highscreen,Sound-Boostar 16 3D},"
+MODULE_SUPPORTED_DEVICE("{{Highscreen,Sound-Boostar 16 3D},"
 		"{Analog Devices,AD1815},"
 		"{Analog Devices,AD1816A},"
 		"{TerraTec,Base 64},"
@@ -60,34 +57,24 @@
 
 module_param_array(index, int, boot_devs, 0444);
 MODULE_PARM_DESC(index, "Index value for ad1816a based soundcard.");
-MODULE_PARM_SYNTAX(index, SNDRV_INDEX_DESC);
 module_param_array(id, charp, boot_devs, 0444);
 MODULE_PARM_DESC(id, "ID string for ad1816a based soundcard.");
-MODULE_PARM_SYNTAX(id, SNDRV_ID_DESC);
 module_param_array(enable, bool, boot_devs, 0444);
 MODULE_PARM_DESC(enable, "Enable ad1816a based soundcard.");
-MODULE_PARM_SYNTAX(enable, SNDRV_ENABLE_DESC);
 module_param_array(port, long, boot_devs, 0444);
 MODULE_PARM_DESC(port, "Port # for ad1816a driver.");
-MODULE_PARM_SYNTAX(port, SNDRV_PORT12_DESC);
 module_param_array(mpu_port, long, boot_devs, 0444);
 MODULE_PARM_DESC(mpu_port, "MPU-401 port # for ad1816a driver.");
-MODULE_PARM_SYNTAX(mpu_port, SNDRV_PORT12_DESC);
 module_param_array(fm_port, long, boot_devs, 0444);
 MODULE_PARM_DESC(fm_port, "FM port # for ad1816a driver.");
-MODULE_PARM_SYNTAX(fm_port, SNDRV_PORT12_DESC);
 module_param_array(irq, int, boot_devs, 0444);
 MODULE_PARM_DESC(irq, "IRQ # for ad1816a driver.");
-MODULE_PARM_SYNTAX(irq, SNDRV_IRQ_DESC);
 module_param_array(mpu_irq, int, boot_devs, 0444);
 MODULE_PARM_DESC(mpu_irq, "MPU-401 IRQ # for ad1816a driver.");
-MODULE_PARM_SYNTAX(mpu_irq, SNDRV_IRQ_DESC);
 module_param_array(dma1, int, boot_devs, 0444);
 MODULE_PARM_DESC(dma1, "1st DMA # for ad1816a driver.");
-MODULE_PARM_SYNTAX(dma1, SNDRV_DMA_DESC);
 module_param_array(dma2, int, boot_devs, 0444);
 MODULE_PARM_DESC(dma2, "2nd DMA # for ad1816a driver.");
-MODULE_PARM_SYNTAX(dma2, SNDRV_DMA_DESC);
 
 struct snd_card_ad1816a {
 	struct pnp_dev *dev;
diff -Nru a/sound/isa/ad1816a/ad1816a_lib.c b/sound/isa/ad1816a/ad1816a_lib.c
--- a/sound/isa/ad1816a/ad1816a_lib.c	2004-10-18 14:56:33 -07:00
+++ b/sound/isa/ad1816a/ad1816a_lib.c	2004-10-18 14:56:33 -07:00
@@ -34,8 +34,6 @@
 MODULE_DESCRIPTION("lowlevel code for Analog Devices AD1816A chip");
 MODULE_LICENSE("GPL");
 
-#define chip_t ad1816a_t
-
 static inline int snd_ad1816a_busy_wait(ad1816a_t *chip)
 {
 	int timeout;
@@ -313,7 +311,7 @@
 
 static irqreturn_t snd_ad1816a_interrupt(int irq, void *dev_id, struct pt_regs *regs)
 {
-	ad1816a_t *chip = snd_magic_cast(ad1816a_t, dev_id, return IRQ_NONE);
+	ad1816a_t *chip = dev_id;
 	unsigned char status;
 
 	spin_lock(&chip->lock);
@@ -550,13 +548,13 @@
 		snd_dma_disable(chip->dma2);
 		free_dma(chip->dma2);
 	}
-	snd_magic_kfree(chip);
+	kfree(chip);
 	return 0;
 }
 
 static int snd_ad1816a_dev_free(snd_device_t *device)
 {
-	ad1816a_t *chip = snd_magic_cast(ad1816a_t, device->device_data, return -ENXIO);
+	ad1816a_t *chip = device->device_data;
 	return snd_ad1816a_free(chip);
 }
 
@@ -585,7 +583,7 @@
 
 	*rchip = NULL;
 
-	chip = snd_magic_kcalloc(ad1816a_t, 0, GFP_KERNEL);
+	chip = kcalloc(1, sizeof(*chip), GFP_KERNEL);
 	if (chip == NULL)
 		return -ENOMEM;
 	chip->irq = -1;
@@ -661,7 +659,7 @@
 
 static void snd_ad1816a_pcm_free(snd_pcm_t *pcm)
 {
-	ad1816a_t *chip = snd_magic_cast(ad1816a_t, pcm->private_data, return);
+	ad1816a_t *chip = pcm->private_data;
 	chip->pcm = NULL;
 	snd_pcm_lib_preallocate_free_for_all(pcm);
 }
@@ -696,7 +694,7 @@
 
 static void snd_ad1816a_timer_free(snd_timer_t *timer)
 {
-	ad1816a_t *chip = snd_magic_cast(ad1816a_t, timer->private_data, return);
+	ad1816a_t *chip = timer->private_data;
 	chip->timer = NULL;
 }
 
@@ -901,8 +899,6 @@
 	return change;
 }
 
-#define AD1816A_CONTROLS (sizeof(snd_ad1816a_controls)/sizeof(snd_kcontrol_new_t))
-
 static snd_kcontrol_new_t snd_ad1816a_controls[] = {
 AD1816A_DOUBLE("Master Playback Switch", AD1816A_MASTER_ATT, 15, 7, 1, 1),
 AD1816A_DOUBLE("Master Playback Volume", AD1816A_MASTER_ATT, 8, 0, 31, 1),
@@ -950,7 +946,7 @@
 
 	strcpy(card->mixername, snd_ad1816a_chip_id(chip));
 
-	for (idx = 0; idx < AD1816A_CONTROLS; idx++) {
+	for (idx = 0; idx < ARRAY_SIZE(snd_ad1816a_controls); idx++) {
 		if ((err = snd_ctl_add(card, snd_ctl_new1(&snd_ad1816a_controls[idx], chip))) < 0)
 			return err;
 	}
diff -Nru a/sound/isa/ad1848/ad1848.c b/sound/isa/ad1848/ad1848.c
--- a/sound/isa/ad1848/ad1848.c	2004-10-18 14:56:32 -07:00
+++ b/sound/isa/ad1848/ad1848.c	2004-10-18 14:56:32 -07:00
@@ -30,13 +30,10 @@
 #include <sound/ad1848.h>
 #include <sound/initval.h>
 
-#define chip_t ad1848_t
-
 MODULE_AUTHOR("Tugrul Galatali <galatalt@stuy.edu>, Jaroslav Kysela <perex@suse.cz>");
 MODULE_DESCRIPTION("AD1848/AD1847/CS4248");
 MODULE_LICENSE("GPL");
-MODULE_CLASSES("{sound}");
-MODULE_DEVICES("{{Analog Devices,AD1848},"
+MODULE_SUPPORTED_DEVICE("{{Analog Devices,AD1848},"
 	        "{Analog Devices,AD1847},"
 		"{Crystal Semiconductors,CS4248}}");
 
@@ -51,25 +48,18 @@
 
 module_param_array(index, int, boot_devs, 0444);
 MODULE_PARM_DESC(index, "Index value for AD1848 soundcard.");
-MODULE_PARM_SYNTAX(index, SNDRV_INDEX_DESC);
 module_param_array(id, charp, boot_devs, 0444);
 MODULE_PARM_DESC(id, "ID string for AD1848 soundcard.");
-MODULE_PARM_SYNTAX(id, SNDRV_ID_DESC);
 module_param_array(enable, bool, boot_devs, 0444);
 MODULE_PARM_DESC(enable, "Enable AD1848 soundcard.");
-MODULE_PARM_SYNTAX(enable, SNDRV_ENABLE_DESC);
 module_param_array(port, long, boot_devs, 0444);
 MODULE_PARM_DESC(port, "Port # for AD1848 driver.");
-MODULE_PARM_SYNTAX(port, SNDRV_PORT12_DESC);
 module_param_array(irq, int, boot_devs, 0444);
 MODULE_PARM_DESC(irq, "IRQ # for AD1848 driver.");
-MODULE_PARM_SYNTAX(irq, SNDRV_IRQ_DESC);
 module_param_array(dma1, int, boot_devs, 0444);
 MODULE_PARM_DESC(dma1, "DMA1 # for AD1848 driver.");
-MODULE_PARM_SYNTAX(dma1, SNDRV_DMA_DESC);
 module_param_array(thinkpad, bool, boot_devs, 0444);
 MODULE_PARM_DESC(thinkpad, "Enable only for the onboard CS4248 of IBM Thinkpad 360/750/755 series.");
-MODULE_PARM_SYNTAX(thinkpad,  SNDRV_ENABLED "," SNDRV_BOOLEAN_FALSE_DESC);
 
 static snd_card_t *snd_ad1848_cards[SNDRV_CARDS] = SNDRV_DEFAULT_PTR;
 
diff -Nru a/sound/isa/ad1848/ad1848_lib.c b/sound/isa/ad1848/ad1848_lib.c
--- a/sound/isa/ad1848/ad1848_lib.c	2004-10-18 14:57:04 -07:00
+++ b/sound/isa/ad1848/ad1848_lib.c	2004-10-18 14:57:04 -07:00
@@ -39,8 +39,6 @@
 MODULE_DESCRIPTION("Routines for control of AD1848/AD1847/CS4248");
 MODULE_LICENSE("GPL");
 
-#define chip_t ad1848_t
-
 #if 0
 #define SNDRV_DEBUG_MCE
 #endif
@@ -588,7 +586,7 @@
 
 irqreturn_t snd_ad1848_interrupt(int irq, void *dev_id, struct pt_regs *regs)
 {
-	ad1848_t *chip = snd_magic_cast(ad1848_t, dev_id, return IRQ_NONE);
+	ad1848_t *chip = dev_id;
 
 	if ((chip->mode & AD1848_MODE_PLAY) && chip->playback_substream &&
 	    (chip->mode & AD1848_MODE_RUNNING))
@@ -649,7 +647,7 @@
 #ifdef CONFIG_PM
 static int snd_ad1848_suspend(snd_card_t *card, unsigned int state)
 {
-	ad1848_t *chip = snd_magic_cast(ad1848_t, card->pm_private_data, return -EINVAL);
+	ad1848_t *chip = card->pm_private_data;
 
 	if (card->power_state == SNDRV_CTL_POWER_D3hot)
 		return 0;
@@ -666,7 +664,7 @@
 
 static int snd_ad1848_resume(snd_card_t *card, unsigned int state)
 {
-	ad1848_t *chip = snd_magic_cast(ad1848_t, card->pm_private_data, return -EINVAL);
+	ad1848_t *chip = card->pm_private_data;
 
 	if (card->power_state == SNDRV_CTL_POWER_D0)
 		return 0;
@@ -867,13 +865,13 @@
 		snd_dma_disable(chip->dma);
 		free_dma(chip->dma);
 	}
-	snd_magic_kfree(chip);
+	kfree(chip);
 	return 0;
 }
 
 static int snd_ad1848_dev_free(snd_device_t *device)
 {
-	ad1848_t *chip = snd_magic_cast(ad1848_t, device->device_data, return -ENXIO);
+	ad1848_t *chip = device->device_data;
 	return snd_ad1848_free(chip);
 }
 
@@ -901,7 +899,7 @@
 	int err;
 
 	*rchip = NULL;
-	chip = snd_magic_kcalloc(ad1848_t, 0, GFP_KERNEL);
+	chip = kcalloc(1, sizeof(*chip), GFP_KERNEL);
 	if (chip == NULL)
 		return -ENOMEM;
 	spin_lock_init(&chip->reg_lock);
@@ -977,7 +975,7 @@
 
 static void snd_ad1848_pcm_free(snd_pcm_t *pcm)
 {
-	ad1848_t *chip = snd_magic_cast(ad1848_t, pcm->private_data, return);
+	ad1848_t *chip = pcm->private_data;
 	chip->pcm = NULL;
 	snd_pcm_lib_preallocate_free_for_all(pcm);
 }
diff -Nru a/sound/isa/als100.c b/sound/isa/als100.c
--- a/sound/isa/als100.c	2004-10-18 14:55:54 -07:00
+++ b/sound/isa/als100.c	2004-10-18 14:55:54 -07:00
@@ -32,15 +32,12 @@
 #include <sound/opl3.h>
 #include <sound/sb.h>
 
-#define chip_t sb_t
-
 #define PFX "als100: "
 
 MODULE_AUTHOR("Massimo Piccioni <dafastidio@libero.it>");
 MODULE_DESCRIPTION("Avance Logic ALS1X0");
 MODULE_LICENSE("GPL");
-MODULE_CLASSES("{sound}");
-MODULE_DEVICES("{{Avance Logic,ALS100 - PRO16PNP},"
+MODULE_SUPPORTED_DEVICE("{{Avance Logic,ALS100 - PRO16PNP},"
 	        "{Avance Logic,ALS110},"
 	        "{Avance Logic,ALS120},"
 	        "{Avance Logic,ALS200},"
@@ -63,34 +60,24 @@
 
 module_param_array(index, int, boot_devs, 0444);
 MODULE_PARM_DESC(index, "Index value for als100 based soundcard.");
-MODULE_PARM_SYNTAX(index, SNDRV_INDEX_DESC);
 module_param_array(id, charp, boot_devs, 0444);
 MODULE_PARM_DESC(id, "ID string for als100 based soundcard.");
-MODULE_PARM_SYNTAX(id, SNDRV_ID_DESC);
 module_param_array(enable, bool, boot_devs, 0444);
 MODULE_PARM_DESC(enable, "Enable als100 based soundcard.");
-MODULE_PARM_SYNTAX(enable, SNDRV_ENABLE_DESC);
 module_param_array(port, long, boot_devs, 0444);
 MODULE_PARM_DESC(port, "Port # for als100 driver.");
-MODULE_PARM_SYNTAX(port, SNDRV_PORT12_DESC);
 module_param_array(mpu_port, long, boot_devs, 0444);
 MODULE_PARM_DESC(mpu_port, "MPU-401 port # for als100 driver.");
-MODULE_PARM_SYNTAX(mpu_port, SNDRV_PORT12_DESC);
 module_param_array(fm_port, long, boot_devs, 0444);
 MODULE_PARM_DESC(fm_port, "FM port # for als100 driver.");
-MODULE_PARM_SYNTAX(fm_port, SNDRV_PORT12_DESC);
 module_param_array(irq, int, boot_devs, 0444);
 MODULE_PARM_DESC(irq, "IRQ # for als100 driver.");
-MODULE_PARM_SYNTAX(irq, SNDRV_IRQ_DESC);
 module_param_array(mpu_irq, int, boot_devs, 0444);
 MODULE_PARM_DESC(mpu_irq, "MPU-401 IRQ # for als100 driver.");
-MODULE_PARM_SYNTAX(mpu_irq, SNDRV_IRQ_DESC);
 module_param_array(dma8, int, boot_devs, 0444);
 MODULE_PARM_DESC(dma8, "8-bit DMA # for als100 driver.");
-MODULE_PARM_SYNTAX(dma8, SNDRV_DMA8_DESC);
 module_param_array(dma16, int, boot_devs, 0444);
 MODULE_PARM_DESC(dma16, "16-bit DMA # for als100 driver.");
-MODULE_PARM_SYNTAX(dma16, SNDRV_DMA16_DESC);
 
 struct snd_card_als100 {
 	int dev_no;
diff -Nru a/sound/isa/azt2320.c b/sound/isa/azt2320.c
--- a/sound/isa/azt2320.c	2004-10-18 14:57:04 -07:00
+++ b/sound/isa/azt2320.c	2004-10-18 14:57:04 -07:00
@@ -43,15 +43,12 @@
 #include <sound/mpu401.h>
 #include <sound/opl3.h>
 
-#define chip_t cs4231_t
-
 #define PFX "azt2320: "
 
 MODULE_AUTHOR("Massimo Piccioni <dafastidio@libero.it>");
 MODULE_DESCRIPTION("Aztech Systems AZT2320");
 MODULE_LICENSE("GPL");
-MODULE_CLASSES("{sound}");
-MODULE_DEVICES("{{Aztech Systems,PRO16V},"
+MODULE_SUPPORTED_DEVICE("{{Aztech Systems,PRO16V},"
 		"{Aztech Systems,AZT2320},"
 		"{Aztech Systems,AZT3300},"
 		"{Aztech Systems,AZT2320},"
@@ -72,37 +69,26 @@
 
 module_param_array(index, int, boot_devs, 0444);
 MODULE_PARM_DESC(index, "Index value for azt2320 based soundcard.");
-MODULE_PARM_SYNTAX(index, SNDRV_INDEX_DESC);
 module_param_array(id, charp, boot_devs, 0444);
 MODULE_PARM_DESC(id, "ID string for azt2320 based soundcard.");
-MODULE_PARM_SYNTAX(id, SNDRV_ID_DESC);
 module_param_array(enable, bool, boot_devs, 0444);
 MODULE_PARM_DESC(enable, "Enable azt2320 based soundcard.");
-MODULE_PARM_SYNTAX(enable, SNDRV_ENABLE_DESC);
 module_param_array(port, long, boot_devs, 0444);
 MODULE_PARM_DESC(port, "Port # for azt2320 driver.");
-MODULE_PARM_SYNTAX(port, SNDRV_PORT12_DESC);
 module_param_array(wss_port, long, boot_devs, 0444);
 MODULE_PARM_DESC(wss_port, "WSS Port # for azt2320 driver.");
-MODULE_PARM_SYNTAX(wss_port, SNDRV_PORT12_DESC);
 module_param_array(mpu_port, long, boot_devs, 0444);
 MODULE_PARM_DESC(mpu_port, "MPU-401 port # for azt2320 driver.");
-MODULE_PARM_SYNTAX(mpu_port, SNDRV_PORT12_DESC);
 module_param_array(fm_port, long, boot_devs, 0444);
 MODULE_PARM_DESC(fm_port, "FM port # for azt2320 driver.");
-MODULE_PARM_SYNTAX(fm_port, SNDRV_PORT12_DESC);
 module_param_array(irq, int, boot_devs, 0444);
 MODULE_PARM_DESC(irq, "IRQ # for azt2320 driver.");
-MODULE_PARM_SYNTAX(irq, SNDRV_IRQ_DESC);
 module_param_array(mpu_irq, int, boot_devs, 0444);
 MODULE_PARM_DESC(mpu_irq, "MPU-401 IRQ # for azt2320 driver.");
-MODULE_PARM_SYNTAX(mpu_irq, SNDRV_IRQ_DESC);
 module_param_array(dma1, int, boot_devs, 0444);
 MODULE_PARM_DESC(dma1, "1st DMA # for azt2320 driver.");
-MODULE_PARM_SYNTAX(dma1, SNDRV_DMA_DESC);
 module_param_array(dma2, int, boot_devs, 0444);
 MODULE_PARM_DESC(dma2, "2nd DMA # for azt2320 driver.");
-MODULE_PARM_SYNTAX(dma2, SNDRV_DMA_DESC);
 
 struct snd_card_azt2320 {
 	int dev_no;
diff -Nru a/sound/isa/cmi8330.c b/sound/isa/cmi8330.c
--- a/sound/isa/cmi8330.c	2004-10-18 14:57:19 -07:00
+++ b/sound/isa/cmi8330.c	2004-10-18 14:57:19 -07:00
@@ -63,8 +63,7 @@
 MODULE_AUTHOR("George Talusan <gstalusan@uwaterloo.ca>");
 MODULE_DESCRIPTION("C-Media CMI8330");
 MODULE_LICENSE("GPL");
-MODULE_CLASSES("{sound}");
-MODULE_DEVICES("{{C-Media,CMI8330,isapnp:{CMI0001,@@@0001,@X@0001}}}");
+MODULE_SUPPORTED_DEVICE("{{C-Media,CMI8330,isapnp:{CMI0001,@@@0001,@X@0001}}}");
 
 static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX;
 static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR;
@@ -83,41 +82,30 @@
 
 module_param_array(index, int, boot_devs, 0444);
 MODULE_PARM_DESC(index, "Index value for CMI8330 soundcard.");
-MODULE_PARM_SYNTAX(index, SNDRV_INDEX_DESC);
 module_param_array(id, charp, boot_devs, 0444);
 MODULE_PARM_DESC(id, "ID string  for CMI8330 soundcard.");
-MODULE_PARM_SYNTAX(id, SNDRV_ID_DESC);
 module_param_array(enable, bool, boot_devs, 0444);
 MODULE_PARM_DESC(enable, "Enable CMI8330 soundcard.");
-MODULE_PARM_SYNTAX(enable, SNDRV_ENABLE_DESC);
 #ifdef CONFIG_PNP
 module_param_array(isapnp, bool, boot_devs, 0444);
 MODULE_PARM_DESC(isapnp, "PnP detection for specified soundcard.");
-MODULE_PARM_SYNTAX(isapnp, SNDRV_ISAPNP_DESC);
 #endif
 
 module_param_array(sbport, long, boot_devs, 0444);
 MODULE_PARM_DESC(sbport, "Port # for CMI8330 SB driver.");
-MODULE_PARM_SYNTAX(sbport, SNDRV_ENABLED ",allows:{{0x220,0x280,0x20}},prefers:{0x220},base:16,dialog:list");
 module_param_array(sbirq, int, boot_devs, 0444);
 MODULE_PARM_DESC(sbirq, "IRQ # for CMI8330 SB driver.");
-MODULE_PARM_SYNTAX(sbirq, SNDRV_ENABLED ",allows:{{5},{7},{9},{10},{11},{12}},prefers:{5},dialog:list");
 module_param_array(sbdma8, int, boot_devs, 0444);
 MODULE_PARM_DESC(sbdma8, "DMA8 for CMI8330 SB driver.");
-MODULE_PARM_SYNTAX(sbdma8, SNDRV_DMA8_DESC ",prefers:{1}");
 module_param_array(sbdma16, int, boot_devs, 0444);
 MODULE_PARM_DESC(sbdma16, "DMA16 for CMI8330 SB driver.");
-MODULE_PARM_SYNTAX(sbdma16, SNDRV_ENABLED ",allows:{{5},{7}},prefers:{5},dialog:list");
 
 module_param_array(wssport, long, boot_devs, 0444);
 MODULE_PARM_DESC(wssport, "Port # for CMI8330 WSS driver.");
-MODULE_PARM_SYNTAX(wssport, SNDRV_ENABLED ",allows:{{0x530},{0xe80,0xf40,0xc0}},prefers:{0x530},base:16,dialog:list");
 module_param_array(wssirq, int, boot_devs, 0444);
 MODULE_PARM_DESC(wssirq, "IRQ # for CMI8330 WSS driver.");
-MODULE_PARM_SYNTAX(wssirq, SNDRV_ENABLED ",allows:{{5},{7},{9},{10},{11},{12}},prefers:{11},dialog:list");
 module_param_array(wssdma, int, boot_devs, 0444);
 MODULE_PARM_DESC(wssdma, "DMA for CMI8330 WSS driver.");
-MODULE_PARM_SYNTAX(wssdma, SNDRV_DMA8_DESC ",prefers:{0}");
 
 #define CMI8330_RMUX3D    16
 #define CMI8330_MUTEMUX   17
@@ -385,7 +373,7 @@
 
 static int snd_cmi8330_playback_open(snd_pcm_substream_t * substream)
 {
-	struct snd_cmi8330 *chip = (struct snd_cmi8330 *)_snd_pcm_substream_chip(substream);
+	struct snd_cmi8330 *chip = snd_pcm_substream_chip(substream);
 
 	/* replace the private_data and call the original open callback */
 	substream->private_data = chip->streams[SNDRV_PCM_STREAM_PLAYBACK].private_data;
@@ -394,7 +382,7 @@
 
 static int snd_cmi8330_capture_open(snd_pcm_substream_t * substream)
 {
-	struct snd_cmi8330 *chip = (struct snd_cmi8330 *)_snd_pcm_substream_chip(substream);
+	struct snd_cmi8330 *chip = snd_pcm_substream_chip(substream);
 
 	/* replace the private_data and call the original open callback */
 	substream->private_data = chip->streams[SNDRV_PCM_STREAM_CAPTURE].private_data;
diff -Nru a/sound/isa/cs423x/cs4231.c b/sound/isa/cs423x/cs4231.c
--- a/sound/isa/cs423x/cs4231.c	2004-10-18 14:55:54 -07:00
+++ b/sound/isa/cs423x/cs4231.c	2004-10-18 14:55:54 -07:00
@@ -30,13 +30,10 @@
 #include <sound/mpu401.h>
 #include <sound/initval.h>
 
-#define chip_t cs4231_t
-
 MODULE_AUTHOR("Jaroslav Kysela <perex@suse.cz>");
 MODULE_DESCRIPTION("Generic CS4231");
 MODULE_LICENSE("GPL");
-MODULE_CLASSES("{sound}");
-MODULE_DEVICES("{{Crystal Semiconductors,CS4231}}");
+MODULE_SUPPORTED_DEVICE("{{Crystal Semiconductors,CS4231}}");
 
 static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX;	/* Index 0-MAX */
 static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR;	/* ID for this card */
@@ -51,31 +48,22 @@
 
 module_param_array(index, int, boot_devs, 0444);
 MODULE_PARM_DESC(index, "Index value for CS4231 soundcard.");
-MODULE_PARM_SYNTAX(index, SNDRV_INDEX_DESC);
 module_param_array(id, charp, boot_devs, 0444);
 MODULE_PARM_DESC(id, "ID string for CS4231 soundcard.");
-MODULE_PARM_SYNTAX(id, SNDRV_ID_DESC);
 module_param_array(enable, bool, boot_devs, 0444);
 MODULE_PARM_DESC(enable, "Enable CS4231 soundcard.");
-MODULE_PARM_SYNTAX(enable, SNDRV_ENABLE_DESC);
 module_param_array(port, long, boot_devs, 0444);
 MODULE_PARM_DESC(port, "Port # for CS4231 driver.");
-MODULE_PARM_SYNTAX(port, SNDRV_PORT12_DESC);
 module_param_array(mpu_port, long, boot_devs, 0444);
 MODULE_PARM_DESC(mpu_port, "MPU-401 port # for CS4231 driver.");
-MODULE_PARM_SYNTAX(mpu_port, SNDRV_PORT12_DESC);
 module_param_array(irq, int, boot_devs, 0444);
 MODULE_PARM_DESC(irq, "IRQ # for CS4231 driver.");
-MODULE_PARM_SYNTAX(irq, SNDRV_IRQ_DESC);
 module_param_array(mpu_irq, int, boot_devs, 0444);
 MODULE_PARM_DESC(mpu_irq, "MPU-401 IRQ # for CS4231 driver.");
-MODULE_PARM_SYNTAX(mpu_irq, SNDRV_IRQ_DESC);
 module_param_array(dma1, int, boot_devs, 0444);
 MODULE_PARM_DESC(dma1, "DMA1 # for CS4231 driver.");
-MODULE_PARM_SYNTAX(dma1, SNDRV_DMA_DESC);
 module_param_array(dma2, int, boot_devs, 0444);
 MODULE_PARM_DESC(dma2, "DMA2 # for CS4231 driver.");
-MODULE_PARM_SYNTAX(dma2, SNDRV_DMA_DESC);
 
 static snd_card_t *snd_cs4231_cards[SNDRV_CARDS] = SNDRV_DEFAULT_PTR;
 
diff -Nru a/sound/isa/cs423x/cs4231_lib.c b/sound/isa/cs423x/cs4231_lib.c
--- a/sound/isa/cs423x/cs4231_lib.c	2004-10-18 14:56:17 -07:00
+++ b/sound/isa/cs423x/cs4231_lib.c	2004-10-18 14:56:17 -07:00
@@ -43,8 +43,6 @@
 MODULE_DESCRIPTION("Routines for control of CS4231(A)/CS4232/InterWave & compatible chips");
 MODULE_LICENSE("GPL");
 
-#define chip_t cs4231_t
-
 #if 0
 #define SNDRV_DEBUG_MCE
 #endif
@@ -969,7 +967,7 @@
 
 irqreturn_t snd_cs4231_interrupt(int irq, void *dev_id, struct pt_regs *regs)
 {
-	cs4231_t *chip = snd_magic_cast(cs4231_t, dev_id, return IRQ_NONE);
+	cs4231_t *chip = dev_id;
 	unsigned char status;
 
 	status = snd_cs4231_in(chip, CS4231_IRQ_STATUS);
@@ -1407,7 +1405,7 @@
 
 static int snd_cs4231_pm_suspend(snd_card_t *card, unsigned int state)
 {
-	cs4231_t *chip = snd_magic_cast(cs4231_t, card->pm_private_data, return -EINVAL);
+	cs4231_t *chip = card->pm_private_data;
 	if (chip->suspend) {
 		chip->suspend(chip);
 		snd_power_change_state(card, SNDRV_CTL_POWER_D3hot);
@@ -1417,7 +1415,7 @@
 
 static int snd_cs4231_pm_resume(snd_card_t *card, unsigned int state)
 {
-	cs4231_t *chip = snd_magic_cast(cs4231_t, card->pm_private_data, return -EINVAL);
+	cs4231_t *chip = card->pm_private_data;
 	if (chip->resume) {
 		chip->resume(chip);
 		snd_power_change_state(card, SNDRV_CTL_POWER_D0);
@@ -1453,13 +1451,13 @@
 	}
 	if (chip->timer)
 		snd_device_free(chip->card, chip->timer);
-	snd_magic_kfree(chip);
+	kfree(chip);
 	return 0;
 }
 
 static int snd_cs4231_dev_free(snd_device_t *device)
 {
-	cs4231_t *chip = snd_magic_cast(cs4231_t, device->device_data, return -ENXIO);
+	cs4231_t *chip = device->device_data;
 	return snd_cs4231_free(chip);	
 }
 
@@ -1493,7 +1491,7 @@
 	cs4231_t *chip;
 
 	*rchip = NULL;
-	chip = snd_magic_kcalloc(cs4231_t, 0, GFP_KERNEL);
+	chip = kcalloc(1, sizeof(*chip), GFP_KERNEL);
 	if (chip == NULL)
 		return -ENOMEM;
 	chip->hardware = hardware;
@@ -1626,7 +1624,7 @@
 
 static void snd_cs4231_pcm_free(snd_pcm_t *pcm)
 {
-	cs4231_t *chip = snd_magic_cast(cs4231_t, pcm->private_data, return);
+	cs4231_t *chip = pcm->private_data;
 	chip->pcm = NULL;
 	snd_pcm_lib_preallocate_free_for_all(pcm);
 }
@@ -1686,7 +1684,7 @@
 
 static void snd_cs4231_timer_free(snd_timer_t *timer)
 {
-	cs4231_t *chip = snd_magic_cast(cs4231_t, timer->private_data, return);
+	cs4231_t *chip = timer->private_data;
 	chip->timer = NULL;
 }
 
@@ -1898,8 +1896,6 @@
 	return change;
 }
 
-#define CS4231_CONTROLS (sizeof(snd_cs4231_controls)/sizeof(snd_kcontrol_new_t))
-
 static snd_kcontrol_new_t snd_cs4231_controls[] = {
 CS4231_DOUBLE("PCM Playback Switch", 0, CS4231_LEFT_OUTPUT, CS4231_RIGHT_OUTPUT, 7, 7, 1, 1),
 CS4231_DOUBLE("PCM Playback Volume", 0, CS4231_LEFT_OUTPUT, CS4231_RIGHT_OUTPUT, 0, 0, 63, 1),
@@ -1938,7 +1934,7 @@
 
 	strcpy(card->mixername, chip->pcm->name);
 
-	for (idx = 0; idx < CS4231_CONTROLS; idx++) {
+	for (idx = 0; idx < ARRAY_SIZE(snd_cs4231_controls); idx++) {
 		if ((err = snd_ctl_add(card, snd_ctl_new1(&snd_cs4231_controls[idx], chip))) < 0)
 			return err;
 	}
diff -Nru a/sound/isa/cs423x/cs4236.c b/sound/isa/cs423x/cs4236.c
--- a/sound/isa/cs423x/cs4236.c	2004-10-18 14:55:55 -07:00
+++ b/sound/isa/cs423x/cs4236.c	2004-10-18 14:55:55 -07:00
@@ -30,14 +30,11 @@
 #include <sound/opl3.h>
 #include <sound/initval.h>
 
-#define chip_t cs4231_t
-
 MODULE_AUTHOR("Jaroslav Kysela <perex@suse.cz>");
 MODULE_LICENSE("GPL");
-MODULE_CLASSES("{sound}");
 #ifdef CS4232
 MODULE_DESCRIPTION("Cirrus Logic CS4232");
-MODULE_DEVICES("{{Turtle Beach,TBS-2000},"
+MODULE_SUPPORTED_DEVICE("{{Turtle Beach,TBS-2000},"
 		"{Turtle Beach,Tropez Plus},"
 		"{SIC CrystalWave 32},"
 		"{Hewlett Packard,Omnibook 5500},"
@@ -45,7 +42,7 @@
 		"{Philips,PCA70PS}}");
 #else
 MODULE_DESCRIPTION("Cirrus Logic CS4235-9");
-MODULE_DEVICES("{{Crystal Semiconductors,CS4235},"
+MODULE_SUPPORTED_DEVICE("{{Crystal Semiconductors,CS4235},"
 		"{Crystal Semiconductors,CS4236},"
 		"{Crystal Semiconductors,CS4237},"
 		"{Crystal Semiconductors,CS4238},"
@@ -99,45 +96,32 @@
 
 module_param_array(index, int, boot_devs, 0444);
 MODULE_PARM_DESC(index, "Index value for " IDENT " soundcard.");
-MODULE_PARM_SYNTAX(index, SNDRV_INDEX_DESC);
 module_param_array(id, charp, boot_devs, 0444);
 MODULE_PARM_DESC(id, "ID string for " IDENT " soundcard.");
-MODULE_PARM_SYNTAX(id, SNDRV_ID_DESC);
 module_param_array(enable, bool, boot_devs, 0444);
 MODULE_PARM_DESC(enable, "Enable " IDENT " soundcard.");
-MODULE_PARM_SYNTAX(enable, SNDRV_ENABLE_DESC);
 #ifdef CONFIG_PNP
 module_param_array(isapnp, bool, boot_devs, 0444);
 MODULE_PARM_DESC(isapnp, "ISA PnP detection for specified soundcard.");
-MODULE_PARM_SYNTAX(isapnp, SNDRV_ISAPNP_DESC);
 #endif
 module_param_array(port, long, boot_devs, 0444);
 MODULE_PARM_DESC(port, "Port # for " IDENT " driver.");
-MODULE_PARM_SYNTAX(port, SNDRV_PORT12_DESC);
 module_param_array(cport, long, boot_devs, 0444);
 MODULE_PARM_DESC(cport, "Control port # for " IDENT " driver.");
-MODULE_PARM_SYNTAX(cport, SNDRV_PORT12_DESC);
 module_param_array(mpu_port, long, boot_devs, 0444);
 MODULE_PARM_DESC(mpu_port, "MPU-401 port # for " IDENT " driver.");
-MODULE_PARM_SYNTAX(mpu_port, SNDRV_PORT12_DESC);
 module_param_array(fm_port, long, boot_devs, 0444);
 MODULE_PARM_DESC(fm_port, "FM port # for " IDENT " driver.");
-MODULE_PARM_SYNTAX(fm_port, SNDRV_PORT12_DESC);
 module_param_array(sb_port, long, boot_devs, 0444);
 MODULE_PARM_DESC(sb_port, "SB port # for " IDENT " driver (optional).");
-MODULE_PARM_SYNTAX(sb_port, SNDRV_PORT12_DESC);
 module_param_array(irq, int, boot_devs, 0444);
 MODULE_PARM_DESC(irq, "IRQ # for " IDENT " driver.");
-MODULE_PARM_SYNTAX(irq, SNDRV_IRQ_DESC);
 module_param_array(mpu_irq, int, boot_devs, 0444);
 MODULE_PARM_DESC(mpu_irq, "MPU-401 IRQ # for " IDENT " driver.");
-MODULE_PARM_SYNTAX(mpu_irq, SNDRV_IRQ_DESC);
 module_param_array(dma1, int, boot_devs, 0444);
 MODULE_PARM_DESC(dma1, "DMA1 # for " IDENT " driver.");
-MODULE_PARM_SYNTAX(dma1, SNDRV_DMA_DESC);
 module_param_array(dma2, int, boot_devs, 0444);
 MODULE_PARM_DESC(dma2, "DMA2 # for " IDENT " driver.");
-MODULE_PARM_SYNTAX(dma2, SNDRV_DMA_DESC);
 
 struct snd_card_cs4236 {
 	struct resource *res_sb_port;
diff -Nru a/sound/isa/cs423x/cs4236_lib.c b/sound/isa/cs423x/cs4236_lib.c
--- a/sound/isa/cs423x/cs4236_lib.c	2004-10-18 14:56:28 -07:00
+++ b/sound/isa/cs423x/cs4236_lib.c	2004-10-18 14:56:28 -07:00
@@ -93,8 +93,6 @@
 MODULE_DESCRIPTION("Routines for control of CS4235/4236B/4237B/4238B/4239 chips");
 MODULE_LICENSE("GPL");
 
-#define chip_t cs4231_t
-
 /*
  *
  */
@@ -707,8 +705,6 @@
 	return change;
 }
 
-#define CS4236_CONTROLS (sizeof(snd_cs4236_controls)/sizeof(snd_kcontrol_new_t))
-
 static snd_kcontrol_new_t snd_cs4236_controls[] = {
 
 CS4236_DOUBLE("Master Digital Playback Switch", 0, CS4236_LEFT_MASTER, CS4236_RIGHT_MASTER, 7, 7, 1, 1),
@@ -760,8 +756,6 @@
 CS4236_DOUBLE1("Digital Loopback Playback Volume", 0, CS4231_LOOPBACK, CS4236_RIGHT_LOOPBACK, 2, 0, 63, 1)
 };
 
-#define CS4235_CONTROLS (sizeof(snd_cs4235_controls)/sizeof(snd_kcontrol_new_t))
-
 static snd_kcontrol_new_t snd_cs4235_controls[] = {
 
 CS4231_DOUBLE("Master Switch", 0, CS4235_LEFT_MASTER, CS4235_RIGHT_MASTER, 7, 7, 1, 1),
@@ -871,8 +865,6 @@
 	return change;
 }
 
-#define CS4236_IEC958_CONTROLS (sizeof(snd_cs4236_iec958_controls)/sizeof(snd_kcontrol_new_t))
-
 static snd_kcontrol_new_t snd_cs4236_iec958_controls[] = {
 CS4236_IEC958_ENABLE("IEC958 Output Enable", 0),
 CS4236_SINGLEC("IEC958 Output Validity", 0, 4, 4, 1, 0),
@@ -882,15 +874,11 @@
 CS4236_SINGLEC("IEC958 Output Channel Status High", 0, 6, 0, 255, 0)
 };
 
-#define CS4236_3D_CONTROLS_CS4235 (sizeof(snd_cs4236_3d_controls_cs4235)/sizeof(snd_kcontrol_new_t))
-
 static snd_kcontrol_new_t snd_cs4236_3d_controls_cs4235[] = {
 CS4236_SINGLEC("3D Control - Switch", 0, 3, 4, 1, 0),
 CS4236_SINGLEC("3D Control - Space", 0, 2, 4, 15, 1)
 };
 
-#define CS4236_3D_CONTROLS_CS4237 (sizeof(snd_cs4236_3d_controls_cs4237)/sizeof(snd_kcontrol_new_t))
-
 static snd_kcontrol_new_t snd_cs4236_3d_controls_cs4237[] = {
 CS4236_SINGLEC("3D Control - Switch", 0, 3, 7, 1, 0),
 CS4236_SINGLEC("3D Control - Space", 0, 2, 4, 15, 1),
@@ -899,8 +887,6 @@
 CS4236_SINGLEC("3D Control - IEC958", 0, 3, 5, 1, 0)
 };
 
-#define CS4236_3D_CONTROLS_CS4238 (sizeof(snd_cs4236_3d_controls_cs4238)/sizeof(snd_kcontrol_new_t))
-
 static snd_kcontrol_new_t snd_cs4236_3d_controls_cs4238[] = {
 CS4236_SINGLEC("3D Control - Switch", 0, 3, 4, 1, 0),
 CS4236_SINGLEC("3D Control - Space", 0, 2, 4, 15, 1),
@@ -921,12 +907,12 @@
 
 	if (chip->hardware == CS4231_HW_CS4235 ||
 	    chip->hardware == CS4231_HW_CS4239) {
-		for (idx = 0; idx < CS4235_CONTROLS; idx++) {
+		for (idx = 0; idx < ARRAY_SIZE(snd_cs4235_controls); idx++) {
 			if ((err = snd_ctl_add(card, snd_ctl_new1(&snd_cs4235_controls[idx], chip))) < 0)
 				return err;
 		}
 	} else {
-		for (idx = 0; idx < CS4236_CONTROLS; idx++) {
+		for (idx = 0; idx < ARRAY_SIZE(snd_cs4236_controls); idx++) {
 			if ((err = snd_ctl_add(card, snd_ctl_new1(&snd_cs4236_controls[idx], chip))) < 0)
 				return err;
 		}
@@ -934,15 +920,15 @@
 	switch (chip->hardware) {
 	case CS4231_HW_CS4235:
 	case CS4231_HW_CS4239:
-		count = CS4236_3D_CONTROLS_CS4235;
+		count = ARRAY_SIZE(snd_cs4236_3d_controls_cs4235);
 		kcontrol = snd_cs4236_3d_controls_cs4235;
 		break;
 	case CS4231_HW_CS4237B:
-		count = CS4236_3D_CONTROLS_CS4237;
+		count = ARRAY_SIZE(snd_cs4236_3d_controls_cs4237);
 		kcontrol = snd_cs4236_3d_controls_cs4237;
 		break;
 	case CS4231_HW_CS4238B:
-		count = CS4236_3D_CONTROLS_CS4238;
+		count = ARRAY_SIZE(snd_cs4236_3d_controls_cs4238);
 		kcontrol = snd_cs4236_3d_controls_cs4238;
 		break;
 	default:
@@ -955,7 +941,7 @@
 	}
 	if (chip->hardware == CS4231_HW_CS4237B ||
 	    chip->hardware == CS4231_HW_CS4238B) {
-		for (idx = 0; idx < CS4236_IEC958_CONTROLS; idx++) {
+		for (idx = 0; idx < ARRAY_SIZE(snd_cs4236_iec958_controls); idx++) {
 			if ((err = snd_ctl_add(card, snd_ctl_new1(&snd_cs4236_iec958_controls[idx], chip))) < 0)
 				return err;
 		}
diff -Nru a/sound/isa/dt019x.c b/sound/isa/dt019x.c
--- a/sound/isa/dt019x.c	2004-10-18 14:56:28 -07:00
+++ b/sound/isa/dt019x.c	2004-10-18 14:56:28 -07:00
@@ -33,15 +33,12 @@
 #include <sound/opl3.h>
 #include <sound/sb.h>
 
-#define chip_t sb_t
-
 #define PFX "dt019x: "
 
 MODULE_AUTHOR("Massimo Piccioni <dafastidio@libero.it>");
 MODULE_DESCRIPTION("Diamond Technologies DT-019X / Avance Logic ALS-007");
 MODULE_LICENSE("GPL");
-MODULE_CLASSES("{sound}");
-MODULE_DEVICES("{{Diamond Technologies DT-019X},"
+MODULE_SUPPORTED_DEVICE("{{Diamond Technologies DT-019X},"
 	       "{Avance Logic ALS-007}}");
 
 static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX;	/* Index 0-MAX */
@@ -57,31 +54,22 @@
 
 module_param_array(index, int, boot_devs, 0444);
 MODULE_PARM_DESC(index, "Index value for DT-019X based soundcard.");
-MODULE_PARM_SYNTAX(index, SNDRV_INDEX_DESC);
 module_param_array(id, charp, boot_devs, 0444);
 MODULE_PARM_DESC(id, "ID string for DT-019X based soundcard.");
-MODULE_PARM_SYNTAX(id, SNDRV_ID_DESC);
 module_param_array(enable, bool, boot_devs, 0444);
 MODULE_PARM_DESC(enable, "Enable DT-019X based soundcard.");
-MODULE_PARM_SYNTAX(enable, SNDRV_ENABLE_DESC);
 module_param_array(port, long, boot_devs, 0444);
 MODULE_PARM_DESC(port, "Port # for dt019x driver.");
-MODULE_PARM_SYNTAX(port, SNDRV_PORT12_DESC);
 module_param_array(mpu_port, long, boot_devs, 0444);
 MODULE_PARM_DESC(mpu_port, "MPU-401 port # for dt019x driver.");
-MODULE_PARM_SYNTAX(mpu_port, SNDRV_PORT12_DESC);
 module_param_array(fm_port, long, boot_devs, 0444);
 MODULE_PARM_DESC(fm_port, "FM port # for dt019x driver.");
-MODULE_PARM_SYNTAX(fm_port, SNDRV_PORT12_DESC);
 module_param_array(irq, int, boot_devs, 0444);
 MODULE_PARM_DESC(irq, "IRQ # for dt019x driver.");
-MODULE_PARM_SYNTAX(irq, SNDRV_IRQ_DESC);
 module_param_array(mpu_irq, int, boot_devs, 0444);
 MODULE_PARM_DESC(mpu_irq, "MPU-401 IRQ # for dt019x driver.");
-MODULE_PARM_SYNTAX(mpu_irq, SNDRV_IRQ_DESC);
 module_param_array(dma8, int, boot_devs, 0444);
 MODULE_PARM_DESC(dma8, "8-bit DMA # for dt019x driver.");
-MODULE_PARM_SYNTAX(dma8, SNDRV_DMA8_DESC);
 
 struct snd_card_dt019x {
 	struct pnp_dev *dev;
diff -Nru a/sound/isa/es1688/es1688.c b/sound/isa/es1688/es1688.c
--- a/sound/isa/es1688/es1688.c	2004-10-18 14:56:28 -07:00
+++ b/sound/isa/es1688/es1688.c	2004-10-18 14:56:28 -07:00
@@ -37,8 +37,7 @@
 MODULE_AUTHOR("Jaroslav Kysela <perex@suse.cz>");
 MODULE_DESCRIPTION("ESS ESx688 AudioDrive");
 MODULE_LICENSE("GPL");
-MODULE_CLASSES("{sound}");
-MODULE_DEVICES("{{ESS,ES688 PnP AudioDrive,pnp:ESS0100},"
+MODULE_SUPPORTED_DEVICE("{{ESS,ES688 PnP AudioDrive,pnp:ESS0100},"
 	        "{ESS,ES1688 PnP AudioDrive,pnp:ESS0102},"
 	        "{ESS,ES688 AudioDrive,pnp:ESS6881},"
 	        "{ESS,ES1688 AudioDrive,pnp:ESS1681}}");
@@ -55,28 +54,20 @@
 
 module_param_array(index, int, boot_devs, 0444);
 MODULE_PARM_DESC(index, "Index value for ESx688 soundcard.");
-MODULE_PARM_SYNTAX(index, SNDRV_INDEX_DESC);
 module_param_array(id, charp, boot_devs, 0444);
 MODULE_PARM_DESC(id, "ID string for ESx688 soundcard.");
-MODULE_PARM_SYNTAX(id, SNDRV_ID_DESC);
 module_param_array(enable, bool, boot_devs, 0444);
 MODULE_PARM_DESC(enable, "Enable ESx688 soundcard.");
-MODULE_PARM_SYNTAX(enable, SNDRV_ENABLE_DESC);
 module_param_array(port, long, boot_devs, 0444);
 MODULE_PARM_DESC(port, "Port # for ESx688 driver.");
-MODULE_PARM_SYNTAX(port, SNDRV_PORT12_DESC);
 module_param_array(mpu_port, long, boot_devs, 0444);
 MODULE_PARM_DESC(mpu_port, "MPU-401 port # for ESx688 driver.");
-MODULE_PARM_SYNTAX(mpu_port, SNDRV_PORT12_DESC);
 module_param_array(irq, int, boot_devs, 0444);
 MODULE_PARM_DESC(irq, "IRQ # for ESx688 driver.");
-MODULE_PARM_SYNTAX(irq, SNDRV_IRQ_DESC);
 module_param_array(mpu_irq, int, boot_devs, 0444);
 MODULE_PARM_DESC(mpu_irq, "MPU-401 IRQ # for ESx688 driver.");
-MODULE_PARM_SYNTAX(mpu_irq, SNDRV_IRQ_DESC);
 module_param_array(dma8, int, boot_devs, 0444);
 MODULE_PARM_DESC(dma8, "8-bit DMA # for ESx688 driver.");
-MODULE_PARM_SYNTAX(dma8, SNDRV_DMA8_DESC);
 
 static snd_card_t *snd_audiodrive_cards[SNDRV_CARDS] = SNDRV_DEFAULT_PTR;
 
diff -Nru a/sound/isa/es1688/es1688_lib.c b/sound/isa/es1688/es1688_lib.c
--- a/sound/isa/es1688/es1688_lib.c	2004-10-18 14:56:33 -07:00
+++ b/sound/isa/es1688/es1688_lib.c	2004-10-18 14:56:33 -07:00
@@ -34,7 +34,6 @@
 
 MODULE_AUTHOR("Jaroslav Kysela <perex@suse.cz>");
 MODULE_DESCRIPTION("ESS ESx688 lowlevel module");
-MODULE_CLASSES("{sound}");
 MODULE_LICENSE("GPL");
 
 static int snd_es1688_dsp_command(es1688_t *chip, unsigned char val)
@@ -482,7 +481,7 @@
 
 irqreturn_t snd_es1688_interrupt(int irq, void *dev_id, struct pt_regs *regs)
 {
-	es1688_t *chip = snd_magic_cast(es1688_t, dev_id, return IRQ_NONE);
+	es1688_t *chip = dev_id;
 
 	if (chip->trigger_value == 0x05)	/* ok.. playback is active */
 		snd_pcm_period_elapsed(chip->playback_substream);
@@ -616,13 +615,13 @@
 		disable_dma(chip->dma8);
 		free_dma(chip->dma8);
 	}
-	snd_magic_kfree(chip);
+	kfree(chip);
 	return 0;
 }
 
 static int snd_es1688_dev_free(snd_device_t *device)
 {
-	es1688_t *chip = snd_magic_cast(es1688_t, device->device_data, return -ENXIO);
+	es1688_t *chip = device->device_data;
 	return snd_es1688_free(chip);
 }
 
@@ -650,7 +649,7 @@
 	int err;
 
 	*rchip = NULL;
-	chip = snd_magic_kcalloc(es1688_t, 0, GFP_KERNEL);
+	chip = kcalloc(1, sizeof(*chip), GFP_KERNEL);
 	if (chip == NULL)
 		return -ENOMEM;
 	chip->irq = -1;
@@ -728,7 +727,7 @@
 
 static void snd_es1688_pcm_free(snd_pcm_t *pcm)
 {
-	es1688_t *chip = snd_magic_cast(es1688_t, pcm->private_data, return);
+	es1688_t *chip = pcm->private_data;
 	chip->pcm = NULL;
 	snd_pcm_lib_preallocate_free_for_all(pcm);
 }
@@ -978,8 +977,6 @@
 	return change;
 }
 
-#define ES1688_CONTROLS (sizeof(snd_es1688_controls)/sizeof(snd_kcontrol_new_t))
-
 static snd_kcontrol_new_t snd_es1688_controls[] = {
 ES1688_DOUBLE("Master Playback Volume", 0, ES1688_MASTER_DEV, ES1688_MASTER_DEV, 4, 0, 15, 0),
 ES1688_DOUBLE("PCM Playback Volume", 0, ES1688_PCM_DEV, ES1688_PCM_DEV, 4, 0, 15, 0),
@@ -1028,7 +1025,7 @@
 
 	strcpy(card->mixername, snd_es1688_chip_id(chip));
 
-	for (idx = 0; idx < ES1688_CONTROLS; idx++) {
+	for (idx = 0; idx < ARRAY_SIZE(snd_es1688_controls); idx++) {
 		if ((err = snd_ctl_add(card, snd_ctl_new1(&snd_es1688_controls[idx], chip))) < 0)
 			return err;
 	}
diff -Nru a/sound/isa/es18xx.c b/sound/isa/es18xx.c
--- a/sound/isa/es18xx.c	2004-10-18 14:56:29 -07:00
+++ b/sound/isa/es18xx.c	2004-10-18 14:56:29 -07:00
@@ -157,8 +157,6 @@
 
 typedef struct _snd_es18xx es18xx_t;
 
-#define chip_t es18xx_t
-
 /* Lowlevel */
 
 #define DAC1 0x01
@@ -728,7 +726,7 @@
 
 static irqreturn_t snd_es18xx_interrupt(int irq, void *dev_id, struct pt_regs *regs)
 {
-	es18xx_t *chip = snd_magic_cast(es18xx_t, dev_id, return IRQ_NONE);
+	es18xx_t *chip = dev_id;
 	unsigned char status;
 
 	if (chip->caps & ES18XX_CONTROL) {
@@ -1027,7 +1025,7 @@
 
 static void snd_es18xx_hwv_free(snd_kcontrol_t *kcontrol)
 {
-	es18xx_t *chip = snd_magic_cast(es18xx_t, _snd_kcontrol_chip(kcontrol), return);
+	es18xx_t *chip = snd_kcontrol_chip(kcontrol);
 	chip->master_volume = NULL;
 	chip->master_switch = NULL;
 	chip->hw_volume = NULL;
@@ -1561,7 +1559,7 @@
 
 static void snd_es18xx_pcm_free(snd_pcm_t *pcm)
 {
-	es18xx_t *codec = snd_magic_cast(es18xx_t, pcm->private_data, return);
+	es18xx_t *codec = pcm->private_data;
 	codec->pcm = NULL;
 	snd_pcm_lib_preallocate_free_for_all(pcm);
 }
@@ -1611,7 +1609,7 @@
 #ifdef CONFIG_PM
 static int snd_es18xx_suspend(snd_card_t *card, unsigned int state)
 {
-	es18xx_t *chip = snd_magic_cast(es18xx_t, card->pm_private_data, return -EINVAL);
+	es18xx_t *chip = card->pm_private_data;
 
 	snd_pcm_suspend_all(chip->pcm);
 
@@ -1627,7 +1625,7 @@
 
 static int snd_es18xx_resume(snd_card_t *card, unsigned int state)
 {
-	es18xx_t *chip = snd_magic_cast(es18xx_t, card->pm_private_data, return -EINVAL);
+	es18xx_t *chip = card->pm_private_data;
 
 	/* restore PM register, we won't wake till (not 0x07) i/o activity though */
 	snd_es18xx_write(chip, ES18XX_PM, chip->pm_reg ^= ES18XX_PM_FM);
@@ -1661,13 +1659,13 @@
 		disable_dma(chip->dma2);
 		free_dma(chip->dma2);
 	}
-	snd_magic_kfree(chip);
+	kfree(chip);
 	return 0;
 }
 
 static int snd_es18xx_dev_free(snd_device_t *device)
 {
-	es18xx_t *chip = snd_magic_cast(es18xx_t, device->device_data, return -ENXIO);
+	es18xx_t *chip = device->device_data;
 	return snd_es18xx_free(chip);
 }
 
@@ -1685,7 +1683,7 @@
 	int err;
 
 	*rchip = NULL;
-        chip = snd_magic_kcalloc(es18xx_t, 0, GFP_KERNEL);
+        chip = kcalloc(1, sizeof(*chip), GFP_KERNEL);
 	if (chip == NULL)
 		return -ENOMEM;
 	spin_lock_init(&chip->reg_lock);
@@ -1830,8 +1828,7 @@
 MODULE_AUTHOR("Christian Fischbach <fishbach@pool.informatik.rwth-aachen.de>, Abramo Bagnara <abramo@alsa-project.org>");  
 MODULE_DESCRIPTION("ESS ES18xx AudioDrive");
 MODULE_LICENSE("GPL");
-MODULE_CLASSES("{sound}");
-MODULE_DEVICES("{{ESS,ES1868 PnP AudioDrive},"
+MODULE_SUPPORTED_DEVICE("{{ESS,ES1868 PnP AudioDrive},"
 		"{ESS,ES1869 PnP AudioDrive},"
 		"{ESS,ES1878 PnP AudioDrive},"
 		"{ESS,ES1879 PnP AudioDrive},"
@@ -1860,36 +1857,26 @@
 
 module_param_array(index, int, boot_devs, 0444);
 MODULE_PARM_DESC(index, "Index value for ES18xx soundcard.");
-MODULE_PARM_SYNTAX(index, SNDRV_INDEX_DESC);
 module_param_array(id, charp, boot_devs, 0444);
 MODULE_PARM_DESC(id, "ID string for ES18xx soundcard.");
-MODULE_PARM_SYNTAX(id, SNDRV_ID_DESC);
 module_param_array(enable, bool, boot_devs, 0444);
 MODULE_PARM_DESC(enable, "Enable ES18xx soundcard.");
-MODULE_PARM_SYNTAX(enable, SNDRV_ENABLE_DESC);
 #ifdef CONFIG_PNP
 module_param_array(isapnp, bool, boot_devs, 0444);
 MODULE_PARM_DESC(isapnp, "PnP detection for specified soundcard.");
-MODULE_PARM_SYNTAX(isapnp, SNDRV_ISAPNP_DESC);
 #endif
 module_param_array(port, long, boot_devs, 0444);
 MODULE_PARM_DESC(port, "Port # for ES18xx driver.");
-MODULE_PARM_SYNTAX(port, SNDRV_ENABLED ",allows:{{0x220,0x280,0x20}},prefers:{0x220},base:16,dialog:list");
 module_param_array(mpu_port, long, boot_devs, 0444);
 MODULE_PARM_DESC(mpu_port, "MPU-401 port # for ES18xx driver.");
-MODULE_PARM_SYNTAX(mpu_port, SNDRV_ENABLED ",allows:{{0x300,0x330,0x30},{0x800,0xffe,0x2}},prefers:{0x330,0x300},base:16,dialog:combo");
 module_param_array(fm_port, long, boot_devs, 0444);
 MODULE_PARM_DESC(fm_port, "FM port # for ES18xx driver.");
-MODULE_PARM_SYNTAX(fm_port, SNDRV_ENABLED ",allows:{{0x388},{0x800,0xffc,0x4}},prefers:{0x388},base:16,dialog:combo");
 module_param_array(irq, int, boot_devs, 0444);
 MODULE_PARM_DESC(irq, "IRQ # for ES18xx driver.");
-MODULE_PARM_SYNTAX(irq, SNDRV_IRQ_DESC ",prefers:{5}");
 module_param_array(dma1, int, boot_devs, 0444);
 MODULE_PARM_DESC(dma1, "DMA 1 # for ES18xx driver.");
-MODULE_PARM_SYNTAX(dma1, SNDRV_DMA8_DESC ",prefers:{1}");
 module_param_array(dma2, int, boot_devs, 0444);
 MODULE_PARM_DESC(dma2, "DMA 2 # for ES18xx driver.");
-MODULE_PARM_SYNTAX(dma2, SNDRV_ENABLED ",allows:{{0},{1},{3},{5}},dialog:list,prefers:{0}");
 
 struct snd_audiodrive {
 #ifdef CONFIG_PNP
diff -Nru a/sound/isa/gus/Makefile b/sound/isa/gus/Makefile
--- a/sound/isa/gus/Makefile	2004-10-18 14:57:04 -07:00
+++ b/sound/isa/gus/Makefile	2004-10-18 14:57:04 -07:00
@@ -27,14 +27,10 @@
 
 # Toplevel Module Dependency
 obj-$(CONFIG_SND_GUSCLASSIC) += snd-gusclassic.o snd-gus-lib.o
-obj-$(call sequencer,$(CONFIG_SND_GUSCLASSIC)) += snd-gus-synth.o
 obj-$(CONFIG_SND_GUSMAX) += snd-gusmax.o snd-gus-lib.o
-obj-$(call sequencer,$(CONFIG_SND_GUSMAX)) += snd-gus-synth.o
 obj-$(CONFIG_SND_GUSEXTREME) += snd-gusextreme.o snd-gus-lib.o
-obj-$(call sequencer,$(CONFIG_SND_GUSEXTREME)) += snd-gus-synth.o
 obj-$(CONFIG_SND_INTERWAVE) += snd-interwave.o snd-gus-lib.o
-obj-$(call sequencer,$(CONFIG_SND_INTERWAVE)) += snd-gus-synth.o
 obj-$(CONFIG_SND_INTERWAVE_STB) += snd-interwave-stb.o snd-gus-lib.o
-obj-$(call sequencer,$(CONFIG_SND_INTERWAVE_STB)) += snd-gus-synth.o
+obj-$(call sequencer,$(CONFIG_SND_GUS_SYNTH)) += snd-gus-synth.o
 
 obj-m := $(sort $(obj-m))
diff -Nru a/sound/isa/gus/gus_dram.c b/sound/isa/gus/gus_dram.c
--- a/sound/isa/gus/gus_dram.c	2004-10-18 14:57:05 -07:00
+++ b/sound/isa/gus/gus_dram.c	2004-10-18 14:57:05 -07:00
@@ -31,12 +31,12 @@
 {
 	unsigned long flags;
 	unsigned int size1, size2;
-	char buffer[512], *pbuffer;
+	char buffer[256], *pbuffer;
 
 	while (size > 0) {
-		if (copy_from_user(buffer, _buffer, 512))
+		size1 = size > sizeof(buffer) ? sizeof(buffer) : size;
+		if (copy_from_user(buffer, _buffer, size1))
 			return -EFAULT;
-		size1 = size > 512 ? 512 : size;
 		if (gus->interwave) {
 			spin_lock_irqsave(&gus->reg_lock, flags);
 			snd_gf1_write8(gus, SNDRV_GF1_GB_MEMORY_CONTROL, 0x01);
@@ -69,10 +69,10 @@
 {
 	unsigned long flags;
 	unsigned int size1, size2;
-	char buffer[512], *pbuffer;
+	char buffer[256], *pbuffer;
 
 	while (size > 0) {
-		size1 = size > 512 ? 512 : size;
+		size1 = size > sizeof(buffer) ? sizeof(buffer) : size;
 		if (gus->interwave) {
 			spin_lock_irqsave(&gus->reg_lock, flags);
 			snd_gf1_write8(gus, SNDRV_GF1_GB_MEMORY_CONTROL, rom ? 0x03 : 0x01);
diff -Nru a/sound/isa/gus/gus_instr.c b/sound/isa/gus/gus_instr.c
--- a/sound/isa/gus/gus_instr.c	2004-10-18 14:57:18 -07:00
+++ b/sound/isa/gus/gus_instr.c	2004-10-18 14:57:18 -07:00
@@ -31,7 +31,7 @@
 int snd_gus_iwffff_put_sample(void *private_data, iwffff_wave_t *wave,
 			      char __user *data, long len, int atomic)
 {
-	snd_gus_card_t *gus = snd_magic_cast(snd_gus_card_t, private_data, return -ENXIO);
+	snd_gus_card_t *gus = private_data;
 	snd_gf1_mem_block_t *block;
 	int err;
 
@@ -61,7 +61,7 @@
 int snd_gus_iwffff_get_sample(void *private_data, iwffff_wave_t *wave,
 			      char __user *data, long len, int atomic)
 {
-	snd_gus_card_t *gus = snd_magic_cast(snd_gus_card_t, private_data, return -ENXIO);
+	snd_gus_card_t *gus = private_data;
 
 	return snd_gus_dram_read(gus, data, wave->address.memory, wave->size,
 				 wave->format & IWFFFF_WAVE_ROM ? 1 : 0);
@@ -70,7 +70,7 @@
 int snd_gus_iwffff_remove_sample(void *private_data, iwffff_wave_t *wave,
 				 int atomic)
 {
-	snd_gus_card_t *gus = snd_magic_cast(snd_gus_card_t, private_data, return -ENXIO);
+	snd_gus_card_t *gus = private_data;
 
 	if (wave->format & IWFFFF_WAVE_ROM)
 		return 0;	/* it's probably ok - verify the address? */	
@@ -84,7 +84,7 @@
 int snd_gus_gf1_put_sample(void *private_data, gf1_wave_t *wave,
 			   char __user *data, long len, int atomic)
 {
-	snd_gus_card_t *gus = snd_magic_cast(snd_gus_card_t, private_data, return -ENXIO);
+	snd_gus_card_t *gus = private_data;
 	snd_gf1_mem_block_t *block;
 	int err;
 
@@ -112,7 +112,7 @@
 int snd_gus_gf1_get_sample(void *private_data, gf1_wave_t *wave,
 			   char __user *data, long len, int atomic)
 {
-	snd_gus_card_t *gus = snd_magic_cast(snd_gus_card_t, private_data, return -ENXIO);
+	snd_gus_card_t *gus = private_data;
 
 	return snd_gus_dram_read(gus, data, wave->address.memory, wave->size, 0);
 }
@@ -120,7 +120,7 @@
 int snd_gus_gf1_remove_sample(void *private_data, gf1_wave_t *wave,
 			      int atomic)
 {
-	snd_gus_card_t *gus = snd_magic_cast(snd_gus_card_t, private_data, return -ENXIO);
+	snd_gus_card_t *gus = private_data;
 
 	return snd_gf1_mem_free(&gus->gf1.mem_alloc, wave->address.memory);
 }
@@ -132,7 +132,7 @@
 int snd_gus_simple_put_sample(void *private_data, simple_instrument_t *instr,
 			      char __user *data, long len, int atomic)
 {
-	snd_gus_card_t *gus = snd_magic_cast(snd_gus_card_t, private_data, return -ENXIO);
+	snd_gus_card_t *gus = private_data;
 	snd_gf1_mem_block_t *block;
 	int err;
 
@@ -159,7 +159,7 @@
 int snd_gus_simple_get_sample(void *private_data, simple_instrument_t *instr,
 			      char __user *data, long len, int atomic)
 {
-	snd_gus_card_t *gus = snd_magic_cast(snd_gus_card_t, private_data, return -ENXIO);
+	snd_gus_card_t *gus = private_data;
 
 	return snd_gus_dram_read(gus, data, instr->address.memory, instr->size, 0);
 }
@@ -167,7 +167,7 @@
 int snd_gus_simple_remove_sample(void *private_data, simple_instrument_t *instr,
 			         int atomic)
 {
-	snd_gus_card_t *gus = snd_magic_cast(snd_gus_card_t, private_data, return -ENXIO);
+	snd_gus_card_t *gus = private_data;
 
 	return snd_gf1_mem_free(&gus->gf1.mem_alloc, instr->address.memory);
 }
diff -Nru a/sound/isa/gus/gus_irq.c b/sound/isa/gus/gus_irq.c
--- a/sound/isa/gus/gus_irq.c	2004-10-18 14:57:03 -07:00
+++ b/sound/isa/gus/gus_irq.c	2004-10-18 14:57:03 -07:00
@@ -32,7 +32,7 @@
 
 irqreturn_t snd_gus_interrupt(int irq, void *dev_id, struct pt_regs *regs)
 {
-	snd_gus_card_t * gus = snd_magic_cast(snd_gus_card_t, dev_id, return IRQ_NONE);
+	snd_gus_card_t * gus = dev_id;
 	unsigned char status;
 	int loop = 100;
 	int handled = 0;
@@ -114,7 +114,7 @@
 	snd_gus_voice_t *pvoice;
 	int idx;
 
-	gus = snd_magic_cast(snd_gus_card_t, entry->private_data, return);
+	gus = entry->private_data;
 	snd_iprintf(buffer, "midi out = %u\n", gus->gf1.interrupt_stat_midi_out);
 	snd_iprintf(buffer, "midi in = %u\n", gus->gf1.interrupt_stat_midi_in);
 	snd_iprintf(buffer, "timer1 = %u\n", gus->gf1.interrupt_stat_timer1);
diff -Nru a/sound/isa/gus/gus_main.c b/sound/isa/gus/gus_main.c
--- a/sound/isa/gus/gus_main.c	2004-10-18 14:55:54 -07:00
+++ b/sound/isa/gus/gus_main.c	2004-10-18 14:55:54 -07:00
@@ -35,8 +35,6 @@
 MODULE_DESCRIPTION("Routines for Gravis UltraSound soundcards");
 MODULE_LICENSE("GPL");
 
-#define chip_t snd_gus_card_t
-
 static int snd_gus_init_dma_irq(snd_gus_card_t * gus, int latches);
 
 int snd_gus_use_inc(snd_gus_card_t * gus)
@@ -133,13 +131,13 @@
 		disable_dma(gus->gf1.dma2);
 		free_dma(gus->gf1.dma2);
 	}
-	snd_magic_kfree(gus);
+	kfree(gus);
 	return 0;
 }
 
 static int snd_gus_dev_free(snd_device_t *device)
 {
-	snd_gus_card_t *gus = snd_magic_cast(snd_gus_card_t, device->device_data, return -ENXIO);
+	snd_gus_card_t *gus = device->device_data;
 	return snd_gus_free(gus);
 }
 
@@ -159,7 +157,7 @@
 	};
 
 	*rgus = NULL;
-	gus = snd_magic_kcalloc(snd_gus_card_t, 0, GFP_KERNEL);
+	gus = kcalloc(1, sizeof(*gus), GFP_KERNEL);
 	if (gus == NULL)
 		return -ENOMEM;
 	gus->gf1.irq = -1;
@@ -421,7 +419,7 @@
 
 static void snd_gus_seq_dev_free(snd_seq_device_t *seq_dev)
 {
-	snd_gus_card_t *gus = snd_magic_cast(snd_gus_card_t, seq_dev->private_data, return);
+	snd_gus_card_t *gus = seq_dev->private_data;
 	gus->seq_dev = NULL;
 }
 
diff -Nru a/sound/isa/gus/gus_mem.c b/sound/isa/gus/gus_mem.c
--- a/sound/isa/gus/gus_mem.c	2004-10-18 14:56:29 -07:00
+++ b/sound/isa/gus/gus_mem.c	2004-10-18 14:56:29 -07:00
@@ -297,7 +297,7 @@
 	unsigned int total, used;
 	int i;
 
-	gus = snd_magic_cast(snd_gus_card_t, entry->private_data, return);
+	gus = entry->private_data;
 	alloc = &gus->gf1.mem_alloc;
 	down(&alloc->memory_mutex);
 	snd_iprintf(buffer, "8-bit banks       : \n    ");
diff -Nru a/sound/isa/gus/gus_mem_proc.c b/sound/isa/gus/gus_mem_proc.c
--- a/sound/isa/gus/gus_mem_proc.c	2004-10-18 14:56:33 -07:00
+++ b/sound/isa/gus/gus_mem_proc.c	2004-10-18 14:56:33 -07:00
@@ -37,7 +37,7 @@
 			          unsigned long count, unsigned long pos)
 {
 	long size;
-	gus_proc_private_t *priv = snd_magic_cast(gus_proc_private_t, entry->private_data, return -ENXIO);
+	gus_proc_private_t *priv = entry->private_data;
 	snd_gus_card_t *gus = priv->gus;
 	int err;
 
@@ -58,7 +58,7 @@
 					long long offset,
 					int orig)
 {
-	gus_proc_private_t *priv = snd_magic_cast(gus_proc_private_t, entry->private_data, return -ENXIO);
+	gus_proc_private_t *priv = entry->private_data;
 
 	switch (orig) {
 	case 0:	/* SEEK_SET */
@@ -80,8 +80,8 @@
 
 static void snd_gf1_mem_proc_free(snd_info_entry_t *entry)
 {
-	gus_proc_private_t *priv = snd_magic_cast(gus_proc_private_t, entry->private_data, return);
-	snd_magic_kfree(priv);
+	gus_proc_private_t *priv = entry->private_data;
+	kfree(priv);
 }
 
 static struct snd_info_entry_ops snd_gf1_mem_proc_ops = {
@@ -98,7 +98,7 @@
 
 	for (idx = 0; idx < 4; idx++) {
 		if (gus->gf1.mem_alloc.banks_8[idx].size > 0) {
-			priv = snd_magic_kcalloc(gus_proc_private_t, 0, GFP_KERNEL);
+			priv = kcalloc(1, sizeof(*priv), GFP_KERNEL);
 			if (priv == NULL)
 				return -ENOMEM;
 			priv->gus = gus;
@@ -115,7 +115,7 @@
 	}
 	for (idx = 0; idx < 4; idx++) {
 		if (gus->gf1.rom_present & (1 << idx)) {
-			priv = snd_magic_kcalloc(gus_proc_private_t, 0, GFP_KERNEL);
+			priv = kcalloc(1, sizeof(*priv), GFP_KERNEL);
 			if (priv == NULL)
 				return -ENOMEM;
 			priv->rom = 1;
diff -Nru a/sound/isa/gus/gus_mixer.c b/sound/isa/gus/gus_mixer.c
--- a/sound/isa/gus/gus_mixer.c	2004-10-18 14:55:54 -07:00
+++ b/sound/isa/gus/gus_mixer.c	2004-10-18 14:55:54 -07:00
@@ -26,8 +26,6 @@
 #include <sound/control.h>
 #include <sound/gus.h>
 
-#define chip_t snd_gus_card_t
-
 /*
  *
  */
@@ -148,16 +146,12 @@
 	return change;
 }
 
-#define GF1_CONTROLS (sizeof(snd_gf1_controls)/sizeof(snd_kcontrol_new_t))
-
 static snd_kcontrol_new_t snd_gf1_controls[] = {
 GF1_SINGLE("Master Playback Switch", 0, 1, 1),
 GF1_SINGLE("Line Switch", 0, 0, 1),
 GF1_SINGLE("Mic Switch", 0, 2, 0)
 };
 
-#define ICS_CONTROLS (sizeof(snd_ics_controls)/sizeof(snd_kcontrol_new_t))
-
 static snd_kcontrol_new_t snd_ics_controls[] = {
 GF1_SINGLE("Master Playback Switch", 0, 1, 1),
 ICS_DOUBLE("Master Playback Volume", 0, SNDRV_ICS_MASTER_DEV),
@@ -190,13 +184,13 @@
 	}
 
 	if (!gus->ics_flag) {
-		max = gus->ess_flag ? 1 : GF1_CONTROLS;
+		max = gus->ess_flag ? 1 : ARRAY_SIZE(snd_gf1_controls);
 		for (idx = 0; idx < max; idx++) {
 			if ((err = snd_ctl_add(card, snd_ctl_new1(&snd_gf1_controls[idx], gus))) < 0)
 				return err;
 		}
 	} else {
-		for (idx = 0; idx < ICS_CONTROLS; idx++) {
+		for (idx = 0; idx < ARRAY_SIZE(snd_ics_controls); idx++) {
 			if ((err = snd_ctl_add(card, snd_ctl_new1(&snd_ics_controls[idx], gus))) < 0)
 				return err;
 		}
diff -Nru a/sound/isa/gus/gus_pcm.c b/sound/isa/gus/gus_pcm.c
--- a/sound/isa/gus/gus_pcm.c	2004-10-18 14:56:29 -07:00
+++ b/sound/isa/gus/gus_pcm.c	2004-10-18 14:56:29 -07:00
@@ -34,8 +34,6 @@
 #include <sound/pcm_params.h>
 #include "gus_tables.h"
 
-#define chip_t snd_gus_card_t
-
 /* maximum rate */
 
 #define SNDRV_GF1_PCM_RATE		48000
@@ -66,7 +64,7 @@
 
 static void snd_gf1_pcm_block_change_ack(snd_gus_card_t * gus, void *private_data)
 {
-	gus_pcm_private_t *pcmp = snd_magic_cast(gus_pcm_private_t, private_data, return);
+	gus_pcm_private_t *pcmp = private_data;
 
 	if (pcmp) {
 		atomic_dec(&pcmp->dma_count);
@@ -81,7 +79,7 @@
 {
 	snd_gf1_dma_block_t block;
 	snd_pcm_runtime_t *runtime = substream->runtime;
-	gus_pcm_private_t *pcmp = snd_magic_cast(gus_pcm_private_t, runtime->private_data, return -ENXIO);
+	gus_pcm_private_t *pcmp = runtime->private_data;
 
 	count += offset & 31;
 	offset &= ~31;
@@ -106,7 +104,7 @@
 static void snd_gf1_pcm_trigger_up(snd_pcm_substream_t * substream)
 {
 	snd_pcm_runtime_t *runtime = substream->runtime;
-	gus_pcm_private_t *pcmp = snd_magic_cast(gus_pcm_private_t, runtime->private_data, return);
+	gus_pcm_private_t *pcmp = runtime->private_data;
 	snd_gus_card_t * gus = pcmp->gus;
 	unsigned long flags;
 	unsigned char voice_ctrl, ramp_ctrl;
@@ -194,7 +192,7 @@
 		snd_gf1_smart_stop_voice(gus, pvoice->number);
 		return;
 	}
-	pcmp = snd_magic_cast(gus_pcm_private_t, pvoice->private_data, return);
+	pcmp = pvoice->private_data;
 	if (pcmp == NULL) {
 		snd_printd("snd_gf1_pcm: unknown wave irq?\n");
 		snd_gf1_smart_stop_voice(gus, pvoice->number);
@@ -267,7 +265,7 @@
 {
 	unsigned short vol;
 	int cvoice;
-	gus_pcm_private_t *pcmp = snd_magic_cast(gus_pcm_private_t, pvoice->private_data, return);
+	gus_pcm_private_t *pcmp = pvoice->private_data;
 
 	/* stop ramp, but leave rollover bit untouched */
 	spin_lock(&gus->reg_lock);
@@ -350,7 +348,7 @@
 				     snd_pcm_uframes_t count)
 {
 	snd_pcm_runtime_t *runtime = substream->runtime;
-	gus_pcm_private_t *pcmp = snd_magic_cast(gus_pcm_private_t, runtime->private_data, return -ENXIO);
+	gus_pcm_private_t *pcmp = runtime->private_data;
 	unsigned int bpos, len;
 	
 	bpos = samples_to_bytes(runtime, pos) + (voice * (pcmp->dma_size / 2));
@@ -379,7 +377,7 @@
 					snd_pcm_uframes_t count)
 {
 	snd_pcm_runtime_t *runtime = substream->runtime;
-	gus_pcm_private_t *pcmp = snd_magic_cast(gus_pcm_private_t, runtime->private_data, return -ENXIO);
+	gus_pcm_private_t *pcmp = runtime->private_data;
 	unsigned int bpos, len;
 	
 	bpos = samples_to_bytes(runtime, pos) + (voice * (pcmp->dma_size / 2));
@@ -406,7 +404,7 @@
 {
 	snd_gus_card_t *gus = snd_pcm_substream_chip(substream);
 	snd_pcm_runtime_t *runtime = substream->runtime;
-	gus_pcm_private_t *pcmp = snd_magic_cast(gus_pcm_private_t, runtime->private_data, return -ENXIO);
+	gus_pcm_private_t *pcmp = runtime->private_data;
 	int err;
 	
 	if ((err = snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(hw_params))) < 0)
@@ -453,7 +451,7 @@
 static int snd_gf1_pcm_playback_hw_free(snd_pcm_substream_t * substream)
 {
 	snd_pcm_runtime_t *runtime = substream->runtime;
-	gus_pcm_private_t *pcmp = snd_magic_cast(gus_pcm_private_t, runtime->private_data, return -ENXIO);
+	gus_pcm_private_t *pcmp = runtime->private_data;
 
 	snd_pcm_lib_free_pages(substream);
 	if (pcmp->pvoices[0]) {
@@ -474,7 +472,7 @@
 static int snd_gf1_pcm_playback_prepare(snd_pcm_substream_t * substream)
 {
 	snd_pcm_runtime_t *runtime = substream->runtime;
-	gus_pcm_private_t *pcmp = snd_magic_cast(gus_pcm_private_t, runtime->private_data, return -ENXIO);
+	gus_pcm_private_t *pcmp = runtime->private_data;
 
 	pcmp->bpos = 0;
 	pcmp->dma_size = snd_pcm_lib_buffer_bytes(substream);
@@ -488,7 +486,7 @@
 {
 	snd_gus_card_t *gus = snd_pcm_substream_chip(substream);
 	snd_pcm_runtime_t *runtime = substream->runtime;
-	gus_pcm_private_t *pcmp = snd_magic_cast(gus_pcm_private_t, runtime->private_data, return -ENXIO);
+	gus_pcm_private_t *pcmp = runtime->private_data;
 	int voice;
 
 	if (cmd == SNDRV_PCM_TRIGGER_START) {
@@ -513,7 +511,7 @@
 {
 	snd_gus_card_t *gus = snd_pcm_substream_chip(substream);
 	snd_pcm_runtime_t *runtime = substream->runtime;
-	gus_pcm_private_t *pcmp = snd_magic_cast(gus_pcm_private_t, runtime->private_data, return -ENXIO);
+	gus_pcm_private_t *pcmp = runtime->private_data;
 	unsigned int pos;
 	unsigned char voice_ctrl;
 
@@ -657,8 +655,8 @@
 
 static void snd_gf1_pcm_playback_free(snd_pcm_runtime_t *runtime)
 {
-	gus_pcm_private_t * pcmp = snd_magic_cast(gus_pcm_private_t, runtime->private_data, return);
-	snd_magic_kfree(pcmp);
+	gus_pcm_private_t * pcmp = runtime->private_data;
+	kfree(pcmp);
 }
 
 static int snd_gf1_pcm_playback_open(snd_pcm_substream_t *substream)
@@ -668,7 +666,7 @@
 	snd_pcm_runtime_t *runtime = substream->runtime;
 	int err;
 
-	pcmp = snd_magic_kcalloc(gus_pcm_private_t, 0, GFP_KERNEL);
+	pcmp = kcalloc(1, sizeof(*pcmp), GFP_KERNEL);
 	if (pcmp == NULL)
 		return -ENOMEM;
 	pcmp->gus = gus;
@@ -697,7 +695,7 @@
 {
 	snd_gus_card_t *gus = snd_pcm_substream_chip(substream);
 	snd_pcm_runtime_t *runtime = substream->runtime;
-	gus_pcm_private_t *pcmp = snd_magic_cast(gus_pcm_private_t, runtime->private_data, return -ENXIO);
+	gus_pcm_private_t *pcmp = runtime->private_data;
 	unsigned long jiffies_old;
 
 	jiffies_old = jiffies;
@@ -738,7 +736,7 @@
 
 static void snd_gf1_pcm_free(snd_pcm_t *pcm)
 {
-	snd_gus_card_t *gus = snd_magic_cast(snd_gus_card_t, pcm->private_data, return);
+	snd_gus_card_t *gus = pcm->private_data;
 	gus->pcm = NULL;
 	snd_pcm_lib_preallocate_free_for_all(pcm);
 }
@@ -790,7 +788,7 @@
 		pvoice = &gus->gf1.voices[idx];
 		if (!pvoice->pcm)
 			continue;
-		pcmp = snd_magic_cast(gus_pcm_private_t, pvoice->private_data, return -ENXIO);
+		pcmp = pvoice->private_data;
 		if (!(pcmp->flags & SNDRV_GF1_PCM_PFLG_ACTIVE))
 			continue;
 		/* load real volume - better precision */
diff -Nru a/sound/isa/gus/gus_synth.c b/sound/isa/gus/gus_synth.c
--- a/sound/isa/gus/gus_synth.c	2004-10-18 14:56:32 -07:00
+++ b/sound/isa/gus/gus_synth.c	2004-10-18 14:56:32 -07:00
@@ -134,7 +134,7 @@
 				       int what)
 {
 	unsigned int idx;
-	snd_gus_card_t *gus = snd_magic_cast(snd_gus_card_t, private_data, return);
+	snd_gus_card_t *gus = private_data;
 	snd_gus_voice_t *pvoice;
 	unsigned long flags;
 	
diff -Nru a/sound/isa/gus/gus_timer.c b/sound/isa/gus/gus_timer.c
--- a/sound/isa/gus/gus_timer.c	2004-10-18 14:56:28 -07:00
+++ b/sound/isa/gus/gus_timer.c	2004-10-18 14:56:28 -07:00
@@ -26,8 +26,6 @@
 #include <sound/core.h>
 #include <sound/gus.h>
 
-#define chip_t snd_gus_card_t
-
 /*
  *  Timer 1 - 80us
  */
@@ -146,13 +144,13 @@
 
 static void snd_gf1_timer1_free(snd_timer_t *timer)
 {
-	snd_gus_card_t *gus = snd_magic_cast(snd_gus_card_t, timer->private_data, return);
+	snd_gus_card_t *gus = timer->private_data;
 	gus->gf1.timer1 = NULL;
 }
 
 static void snd_gf1_timer2_free(snd_timer_t *timer)
 {
-	snd_gus_card_t *gus = snd_magic_cast(snd_gus_card_t, timer->private_data, return);
+	snd_gus_card_t *gus = timer->private_data;
 	gus->gf1.timer2 = NULL;
 }
 
diff -Nru a/sound/isa/gus/gus_uart.c b/sound/isa/gus/gus_uart.c
--- a/sound/isa/gus/gus_uart.c	2004-10-18 14:56:20 -07:00
+++ b/sound/isa/gus/gus_uart.c	2004-10-18 14:56:20 -07:00
@@ -95,7 +95,7 @@
 	unsigned long flags;
 	snd_gus_card_t *gus;
 
-	gus = snd_magic_cast(snd_gus_card_t, substream->rmidi->private_data, return -ENXIO);
+	gus = substream->rmidi->private_data;
 	spin_lock_irqsave(&gus->uart_cmd_lock, flags);
 	if (!(gus->gf1.uart_cmd & 0x80)) {	/* input active? */
 		snd_gf1_uart_reset(gus, 0);
@@ -115,7 +115,7 @@
 	snd_gus_card_t *gus;
 	int i;
 
-	gus = snd_magic_cast(snd_gus_card_t, substream->rmidi->private_data, return -ENXIO);
+	gus = substream->rmidi->private_data;
 	spin_lock_irqsave(&gus->uart_cmd_lock, flags);
 	if (gus->gf1.interrupt_handler_midi_out != snd_gf1_interrupt_midi_out) {
 		snd_gf1_uart_reset(gus, 0);
@@ -141,7 +141,7 @@
 	unsigned long flags;
 	snd_gus_card_t *gus;
 
-	gus = snd_magic_cast(snd_gus_card_t, substream->rmidi->private_data, return -ENXIO);
+	gus = substream->rmidi->private_data;
 	spin_lock_irqsave(&gus->uart_cmd_lock, flags);
 	if (gus->gf1.interrupt_handler_midi_in != snd_gf1_interrupt_midi_in)
 		snd_gf1_uart_reset(gus, 1);
@@ -156,7 +156,7 @@
 	unsigned long flags;
 	snd_gus_card_t *gus;
 
-	gus = snd_magic_cast(snd_gus_card_t, substream->rmidi->private_data, return -ENXIO);
+	gus = substream->rmidi->private_data;
 	spin_lock_irqsave(&gus->uart_cmd_lock, flags);
 	if (gus->gf1.interrupt_handler_midi_out != snd_gf1_interrupt_midi_out)
 		snd_gf1_uart_reset(gus, 1);
@@ -171,7 +171,7 @@
 	snd_gus_card_t *gus;
 	unsigned long flags;
 
-	gus = snd_magic_cast(snd_gus_card_t, substream->rmidi->private_data, return);
+	gus = substream->rmidi->private_data;
 
 	spin_lock_irqsave(&gus->uart_cmd_lock, flags);
 	if (up) {
@@ -191,7 +191,7 @@
 	char byte;
 	int timeout;
 
-	gus = snd_magic_cast(snd_gus_card_t, substream->rmidi->private_data, return);
+	gus = substream->rmidi->private_data;
 
 	spin_lock_irqsave(&gus->uart_cmd_lock, flags);
 	if (up) {
diff -Nru a/sound/isa/gus/gusclassic.c b/sound/isa/gus/gusclassic.c
--- a/sound/isa/gus/gusclassic.c	2004-10-18 14:57:05 -07:00
+++ b/sound/isa/gus/gusclassic.c	2004-10-18 14:57:05 -07:00
@@ -35,8 +35,7 @@
 MODULE_AUTHOR("Jaroslav Kysela <perex@suse.cz>");
 MODULE_DESCRIPTION("Gravis UltraSound Classic");
 MODULE_LICENSE("GPL");
-MODULE_CLASSES("{sound}");
-MODULE_DEVICES("{{Gravis,UltraSound Classic}}");
+MODULE_SUPPORTED_DEVICE("{{Gravis,UltraSound Classic}}");
 
 static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX;	/* Index 0-MAX */
 static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR;	/* ID for this card */
@@ -53,34 +52,24 @@
 
 module_param_array(index, int, boot_devs, 0444);
 MODULE_PARM_DESC(index, "Index value for GUS Classic soundcard.");
-MODULE_PARM_SYNTAX(index, SNDRV_INDEX_DESC);
 module_param_array(id, charp, boot_devs, 0444);
 MODULE_PARM_DESC(id, "ID string for GUS Classic soundcard.");
-MODULE_PARM_SYNTAX(id, SNDRV_ID_DESC);
 module_param_array(enable, bool, boot_devs, 0444);
 MODULE_PARM_DESC(enable, "Enable GUS Classic soundcard.");
-MODULE_PARM_SYNTAX(enable, SNDRV_ENABLE_DESC);
 module_param_array(port, long, boot_devs, 0444);
 MODULE_PARM_DESC(port, "Port # for GUS Classic driver.");
-MODULE_PARM_SYNTAX(port, SNDRV_ENABLED ",allows:{{0x220,0x260,0x10}},dialog:list");
 module_param_array(irq, int, boot_devs, 0444);
 MODULE_PARM_DESC(irq, "IRQ # for GUS Classic driver.");
-MODULE_PARM_SYNTAX(irq, SNDRV_ENABLED ",allows:{{3},{5},{9},{11},{12},{15}},dialog:list");
 module_param_array(dma1, int, boot_devs, 0444);
 MODULE_PARM_DESC(dma1, "DMA1 # for GUS Classic driver.");
-MODULE_PARM_SYNTAX(dma1, SNDRV_ENABLED ",allows:{{1},{3},{5},{6},{7}},dialog:list");
 module_param_array(dma2, int, boot_devs, 0444);
 MODULE_PARM_DESC(dma2, "DMA2 # for GUS Classic driver.");
-MODULE_PARM_SYNTAX(dma2, SNDRV_ENABLED ",allows:{{1},{3},{5},{6},{7}},dialog:list");
 module_param_array(joystick_dac, int, boot_devs, 0444);
 MODULE_PARM_DESC(joystick_dac, "Joystick DAC level 0.59V-4.52V or 0.389V-2.98V for GUS Classic driver.");
-MODULE_PARM_SYNTAX(joystick_dac, SNDRV_ENABLED ",allows:{{0,31}}");
 module_param_array(channels, int, boot_devs, 0444);
 MODULE_PARM_DESC(channels, "GF1 channels for GUS Classic driver.");
-MODULE_PARM_SYNTAX(channels,  SNDRV_ENABLED ",allows:{{14,32}}");
 module_param_array(pcm_channels, int, boot_devs, 0444);
 MODULE_PARM_DESC(pcm_channels, "Reserved PCM channels for GUS Classic driver.");
-MODULE_PARM_SYNTAX(pcm_channels, SNDRV_ENABLED ",allows:{{2,16}}");
 
 static snd_card_t *snd_gusclassic_cards[SNDRV_CARDS] = SNDRV_DEFAULT_PTR;
 
diff -Nru a/sound/isa/gus/gusextreme.c b/sound/isa/gus/gusextreme.c
--- a/sound/isa/gus/gusextreme.c	2004-10-18 14:56:48 -07:00
+++ b/sound/isa/gus/gusextreme.c	2004-10-18 14:56:48 -07:00
@@ -38,8 +38,7 @@
 MODULE_AUTHOR("Jaroslav Kysela <perex@suse.cz>");
 MODULE_DESCRIPTION("Gravis UltraSound Extreme");
 MODULE_LICENSE("GPL");
-MODULE_CLASSES("{sound}");
-MODULE_DEVICES("{{Gravis,UltraSound Extreme}}");
+MODULE_SUPPORTED_DEVICE("{{Gravis,UltraSound Extreme}}");
 
 static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX;	/* Index 0-MAX */
 static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR;	/* ID for this card */
@@ -60,46 +59,32 @@
 
 module_param_array(index, int, boot_devs, 0444);
 MODULE_PARM_DESC(index, "Index value for GUS Extreme soundcard.");
-MODULE_PARM_SYNTAX(index, SNDRV_INDEX_DESC);
 module_param_array(id, charp, boot_devs, 0444);
 MODULE_PARM_DESC(id, "ID string for GUS Extreme soundcard.");
-MODULE_PARM_SYNTAX(id, SNDRV_ID_DESC);
 module_param_array(enable, bool, boot_devs, 0444);
 MODULE_PARM_DESC(enable, "Enable GUS Extreme soundcard.");
-MODULE_PARM_SYNTAX(enable, SNDRV_ENABLE_DESC);
 module_param_array(port, long, boot_devs, 0444);
 MODULE_PARM_DESC(port, "Port # for GUS Extreme driver.");
-MODULE_PARM_SYNTAX(port, SNDRV_ENABLED ",allows:{{0x220,0x260,0x20}},dialog:list");
 module_param_array(gf1_port, long, boot_devs, 0444);
 MODULE_PARM_DESC(gf1_port, "GF1 port # for GUS Extreme driver (optional).");
-MODULE_PARM_SYNTAX(gf1_port, SNDRV_ENABLED ",allows:{{0x210,0x270,0x10}},dialog:list");
 module_param_array(mpu_port, long, boot_devs, 0444);
 MODULE_PARM_DESC(mpu_port, "MPU-401 port # for GUS Extreme driver.");
-MODULE_PARM_SYNTAX(mpu_port, SNDRV_ENABLED ",allows:{{0x300,0x320,0x10}},dialog:list");
 module_param_array(irq, int, boot_devs, 0444);
 MODULE_PARM_DESC(irq, "IRQ # for GUS Extreme driver.");
-MODULE_PARM_SYNTAX(irq, SNDRV_ENABLED ",allows:{{5},{7},{9},{10}},dialog:list");
 module_param_array(mpu_irq, int, boot_devs, 0444);
 MODULE_PARM_DESC(mpu_irq, "MPU-401 IRQ # for GUS Extreme driver.");
-MODULE_PARM_SYNTAX(mpu_irq, SNDRV_ENABLED ",allows:{{5},{7},{9},{10}},dialog:list");
 module_param_array(gf1_irq, int, boot_devs, 0444);
 MODULE_PARM_DESC(gf1_irq, "GF1 IRQ # for GUS Extreme driver.");
-MODULE_PARM_SYNTAX(gf1_irq, SNDRV_ENABLED ",allows:{{2},{3},{5},{9},{11},{12},{15}},dialog:list");
 module_param_array(dma8, int, boot_devs, 0444);
 MODULE_PARM_DESC(dma8, "8-bit DMA # for GUS Extreme driver.");
-MODULE_PARM_SYNTAX(dma8, SNDRV_DMA8_DESC);
 module_param_array(dma1, int, boot_devs, 0444);
 MODULE_PARM_DESC(dma1, "GF1 DMA # for GUS Extreme driver.");
-MODULE_PARM_SYNTAX(dma1, SNDRV_DMA_DESC);
 module_param_array(joystick_dac, int, boot_devs, 0444);
 MODULE_PARM_DESC(joystick_dac, "Joystick DAC level 0.59V-4.52V or 0.389V-2.98V for GUS Extreme driver.");
-MODULE_PARM_SYNTAX(joystick_dac, SNDRV_ENABLED ",allows:{{0,31}}");
 module_param_array(channels, int, boot_devs, 0444);
 MODULE_PARM_DESC(channels, "GF1 channels for GUS Extreme driver.");
-MODULE_PARM_SYNTAX(channels, SNDRV_ENABLED ",allows:{{14,32}}");
 module_param_array(pcm_channels, int, boot_devs, 0444);
 MODULE_PARM_DESC(pcm_channels, "Reserved PCM channels for GUS Extreme driver.");
-MODULE_PARM_SYNTAX(pcm_channels, SNDRV_ENABLED ",allows:{{2,16}}");
 
 static snd_card_t *snd_gusextreme_cards[SNDRV_CARDS] = SNDRV_DEFAULT_PTR;
 
diff -Nru a/sound/isa/gus/gusmax.c b/sound/isa/gus/gusmax.c
--- a/sound/isa/gus/gusmax.c	2004-10-18 14:56:33 -07:00
+++ b/sound/isa/gus/gusmax.c	2004-10-18 14:56:33 -07:00
@@ -36,8 +36,7 @@
 MODULE_AUTHOR("Jaroslav Kysela <perex@suse.cz>");
 MODULE_DESCRIPTION("Gravis UltraSound MAX");
 MODULE_LICENSE("GPL");
-MODULE_CLASSES("{sound}");
-MODULE_DEVICES("{{Gravis,UltraSound MAX}}");
+MODULE_SUPPORTED_DEVICE("{{Gravis,UltraSound MAX}}");
 
 static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX;	/* Index 0-MAX */
 static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR;	/* ID for this card */
@@ -54,34 +53,24 @@
 
 module_param_array(index, int, boot_devs, 0444);
 MODULE_PARM_DESC(index, "Index value for GUS MAX soundcard.");
-MODULE_PARM_SYNTAX(index, SNDRV_INDEX_DESC);
 module_param_array(id, charp, boot_devs, 0444);
 MODULE_PARM_DESC(id, "ID string for GUS MAX soundcard.");
-MODULE_PARM_SYNTAX(id, SNDRV_ID_DESC);
 module_param_array(enable, bool, boot_devs, 0444);
 MODULE_PARM_DESC(enable, "Enable GUS MAX soundcard.");
-MODULE_PARM_SYNTAX(enable, SNDRV_ENABLE_DESC);
 module_param_array(port, long, boot_devs, 0444);
 MODULE_PARM_DESC(port, "Port # for GUS MAX driver.");
-MODULE_PARM_SYNTAX(port, SNDRV_ENABLED ",allows:{{0x220},{0x230},{0x240},{0x250},{0x260}},dialog:list");
 module_param_array(irq, int, boot_devs, 0444);
 MODULE_PARM_DESC(irq, "IRQ # for GUS MAX driver.");
-MODULE_PARM_SYNTAX(irq, SNDRV_ENABLED ",allows:{{3},{5},{9},{11},{12},{15}},dialog:list");
 module_param_array(dma1, int, boot_devs, 0444);
 MODULE_PARM_DESC(dma1, "DMA1 # for GUS MAX driver.");
-MODULE_PARM_SYNTAX(dma1, SNDRV_DMA_DESC);
 module_param_array(dma2, int, boot_devs, 0444);
 MODULE_PARM_DESC(dma2, "DMA2 # for GUS MAX driver.");
-MODULE_PARM_SYNTAX(dma2, SNDRV_DMA_DESC);
 module_param_array(joystick_dac, int, boot_devs, 0444);
 MODULE_PARM_DESC(joystick_dac, "Joystick DAC level 0.59V-4.52V or 0.389V-2.98V for GUS MAX driver.");
-MODULE_PARM_SYNTAX(joystick_dac, SNDRV_ENABLED ",allows:{{0,31}}");
 module_param_array(channels, int, boot_devs, 0444);
 MODULE_PARM_DESC(channels, "Used GF1 channels for GUS MAX driver.");
-MODULE_PARM_SYNTAX(channels, SNDRV_ENABLED ",allows:{{14,32}}");
 module_param_array(pcm_channels, int, boot_devs, 0444);
 MODULE_PARM_DESC(pcm_channels, "Reserved PCM channels for GUS MAX driver.");
-MODULE_PARM_SYNTAX(pcm_channels, SNDRV_ENABLED ",allows:{{2,16}}");
 
 struct snd_gusmax {
 	int irq;
diff -Nru a/sound/isa/gus/interwave.c b/sound/isa/gus/interwave.c
--- a/sound/isa/gus/interwave.c	2004-10-18 14:56:32 -07:00
+++ b/sound/isa/gus/interwave.c	2004-10-18 14:56:32 -07:00
@@ -41,18 +41,17 @@
 #include <sound/initval.h>
 
 MODULE_AUTHOR("Jaroslav Kysela <perex@suse.cz>");
-MODULE_CLASSES("{sound}");
 MODULE_LICENSE("GPL");
 #ifndef SNDRV_STB
 MODULE_DESCRIPTION("AMD InterWave");
-MODULE_DEVICES("{{Gravis,UltraSound Plug & Play},"
+MODULE_SUPPORTED_DEVICE("{{Gravis,UltraSound Plug & Play},"
 		"{STB,SoundRage32},"
 		"{MED,MED3210},"
 		"{Dynasonix,Dynasonix Pro},"
 		"{Panasonic,PCA761AW}}");
 #else
 MODULE_DESCRIPTION("AMD InterWave STB with TEA6330T");
-MODULE_DEVICES("{{AMD,InterWave STB with TEA6330T}}");
+MODULE_SUPPORTED_DEVICE("{{AMD,InterWave STB with TEA6330T}}");
 #endif
 
 static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX;	/* Index 0-MAX */
@@ -77,47 +76,32 @@
 
 module_param_array(index, int, boot_devs, 0444);
 MODULE_PARM_DESC(index, "Index value for InterWave soundcard.");
-MODULE_PARM_SYNTAX(index, SNDRV_INDEX_DESC);
 module_param_array(id, charp, boot_devs, 0444);
 MODULE_PARM_DESC(id, "ID string for InterWave soundcard.");
-MODULE_PARM_SYNTAX(id, SNDRV_ID_DESC);
 module_param_array(enable, bool, boot_devs, 0444);
 MODULE_PARM_DESC(enable, "Enable InterWave soundcard.");
-MODULE_PARM_SYNTAX(enable, SNDRV_ENABLE_DESC);
-#ifdef CONFIG_PNP
 module_param_array(isapnp, bool, boot_devs, 0444);
 MODULE_PARM_DESC(isapnp, "ISA PnP detection for specified soundcard.");
-MODULE_PARM_SYNTAX(isapnp, SNDRV_ISAPNP_DESC);
-#endif
 module_param_array(port, long, boot_devs, 0444);
 MODULE_PARM_DESC(port, "Port # for InterWave driver.");
-MODULE_PARM_SYNTAX(port, SNDRV_ENABLED ",allows:{{0x210,0x260,0x10}},dialog:list");
 #ifdef SNDRV_STB
 module_param_array(port_tc, long, boot_devs, 0444);
 MODULE_PARM_DESC(port_tc, "Tone control (TEA6330T - i2c bus) port # for InterWave driver.");
-MODULE_PARM_SYNTAX(port_tc, SNDRV_ENABLED ",allows:{{0x350,0x380,0x10}},dialog:list");
 #endif
 module_param_array(irq, int, boot_devs, 0444);
 MODULE_PARM_DESC(irq, "IRQ # for InterWave driver.");
-MODULE_PARM_SYNTAX(irq, SNDRV_ENABLED ",allows:{{3},{5},{9},{11},{12},{15}},dialog:list");
 module_param_array(dma1, int, boot_devs, 0444);
 MODULE_PARM_DESC(dma1, "DMA1 # for InterWave driver.");
-MODULE_PARM_SYNTAX(dma1, SNDRV_DMA_DESC);
 module_param_array(dma2, int, boot_devs, 0444);
 MODULE_PARM_DESC(dma2, "DMA2 # for InterWave driver.");
-MODULE_PARM_SYNTAX(dma2, SNDRV_DMA_DESC);
 module_param_array(joystick_dac, int, boot_devs, 0444);
 MODULE_PARM_DESC(joystick_dac, "Joystick DAC level 0.59V-4.52V or 0.389V-2.98V for InterWave driver.");
-MODULE_PARM_SYNTAX(joystick_dac, SNDRV_ENABLED ",allows:{{0,31}}");
 module_param_array(midi, int, boot_devs, 0444);
 MODULE_PARM_DESC(midi, "MIDI UART enable for InterWave driver.");
-MODULE_PARM_SYNTAX(midi, SNDRV_ENABLED "," SNDRV_ENABLE_DESC);
 module_param_array(pcm_channels, int, boot_devs, 0444);
 MODULE_PARM_DESC(pcm_channels, "Reserved PCM channels for InterWave driver.");
-MODULE_PARM_SYNTAX(pcm_channels, SNDRV_ENABLED ",allows:{{2,16}}");
 module_param_array(effect, int, boot_devs, 0444);
 MODULE_PARM_DESC(effect, "Effects enable for InterWave driver.");
-MODULE_PARM_SYNTAX(effect, SNDRV_ENABLED "," SNDRV_ENABLE_DESC);
 
 struct snd_interwave {
 	int irq;
@@ -411,8 +395,8 @@
 	int bank_pos, pages;
 	unsigned int i, lmct;
 	int psizes[4];
+	unsigned char iwave[8];
 	unsigned char csum;
-	struct rom_hdr romh;
 
 	snd_interwave_reset(gus);
 	snd_gf1_write8(gus, SNDRV_GF1_GB_GLOBAL_MODE, snd_gf1_read8(gus, SNDRV_GF1_GB_GLOBAL_MODE) | 0x01);		/* enhanced mode */
@@ -434,7 +418,7 @@
 #if 0
 		printk("lmct = 0x%08x\n", lmct);
 #endif
-		for (i = 0; i < sizeof(lmc) / sizeof(unsigned int); i++)
+		for (i = 0; i < ARRAY_SIZE(lmc); i++)
 			if (lmct == lmc[i]) {
 #if 0
 				printk("found !!! %i\n", i);
@@ -443,7 +427,7 @@
 				snd_interwave_bank_sizes(gus, psizes);
 				break;
 			}
-		if (i >= sizeof(lmc) / sizeof(unsigned int) && !gus->gf1.enh_mode)
+		if (i >= ARRAY_SIZE(lmc) && !gus->gf1.enh_mode)
 			 snd_gf1_write16(gus, SNDRV_GF1_GW_MEMORY_CONFIG, (snd_gf1_look16(gus, SNDRV_GF1_GW_MEMORY_CONFIG) & 0xfff0) | 2);
 		for (i = 0; i < 4; i++) {
 			gus->gf1.mem_alloc.banks_8[i].address =
@@ -461,33 +445,29 @@
 	gus->gf1.rom_banks = 0;
 	gus->gf1.rom_memory = 0;
 	for (bank_pos = 0; bank_pos < 16L * 1024L * 1024L; bank_pos += 4L * 1024L * 1024L) {
-		for (i = 0; i < sizeof(struct rom_hdr); i++)
-			*(((unsigned char *) &romh) + i) = snd_gf1_peek(gus, i + bank_pos);
+		for (i = 0; i < 8; ++i)
+			iwave[i] = snd_gf1_peek(gus, bank_pos + i);
 #ifdef CONFIG_SND_DEBUG_ROM
 		printk("ROM at 0x%06x = %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n", bank_pos,
-		       romh.iwave[0], romh.iwave[1], romh.iwave[2], romh.iwave[3],
-		       romh.iwave[4], romh.iwave[5], romh.iwave[6], romh.iwave[7]);
+		       iwave[0], iwave[1], iwave[2], iwave[3],
+		       iwave[4], iwave[5], iwave[6], iwave[7]);
 #endif
-		if (strncmp(romh.iwave, "INTRWAVE", 8))
+		if (strncmp(iwave, "INTRWAVE", 8))
 			continue;	/* first check */
 		csum = 0;
-		for (i = 0; i < sizeof(struct rom_hdr) - 1; i++)
-			csum += *(((unsigned char *) &romh) + i);
+		for (i = 0; i < sizeof(struct rom_hdr); i++)
+			csum += snd_gf1_peek(gus, bank_pos + i);
 #ifdef CONFIG_SND_DEBUG_ROM
-		printk("ROM checksum = 0x%x == 0x%x (computed)\n", romh.csum, (unsigned char) (256 - csum));
+		printk("ROM checksum = 0x%x (computed)\n", csum);
 #endif
-		if (256 - csum != romh.csum)
+		if (csum != 0)
 			continue;	/* not valid rom */
 		gus->gf1.rom_banks++;
 		gus->gf1.rom_present |= 1 << (bank_pos >> 22);
-#ifdef SNDRV_LITTLE_ENDIAN
-		gus->gf1.rom_memory = romh.rom_size;
-#else
-		gus->gf1.rom_memory = ((romh.rom_size >> 24) & 0x000000ff) |
-				      ((romh.rom_size >>  8) & 0x0000ff00) |
-				      ((romh.rom_size <<  8) & 0x00ff0000) |
-				      ((romh.rom_size << 24) & 0xff000000);
-#endif
+		gus->gf1.rom_memory = snd_gf1_peek(gus, bank_pos + 40) |
+				     (snd_gf1_peek(gus, bank_pos + 41) << 8) |
+				     (snd_gf1_peek(gus, bank_pos + 42) << 16) |
+				     (snd_gf1_peek(gus, bank_pos + 43) << 24);
 	}
 #if 0
 	if (gus->gf1.rom_memory > 0) {
@@ -523,8 +503,6 @@
 
 }
 
-#define INTERWAVE_CONTROLS (sizeof(snd_interwave_controls)/sizeof(snd_kcontrol_new_t))
-
 static snd_kcontrol_new_t snd_interwave_controls[] = {
 CS4231_DOUBLE("Master Playback Switch", 0, CS4231_LINE_LEFT_OUTPUT, CS4231_LINE_RIGHT_OUTPUT, 7, 7, 1, 1),
 CS4231_DOUBLE("Master Playback Volume", 0, CS4231_LINE_LEFT_OUTPUT, CS4231_LINE_RIGHT_OUTPUT, 0, 0, 31, 1),
@@ -552,7 +530,7 @@
 		return err;
 #endif
 	/* add new master and mic controls */
-	for (idx = 0; idx < INTERWAVE_CONTROLS; idx++)
+	for (idx = 0; idx < ARRAY_SIZE(snd_interwave_controls); idx++)
 		if ((err = snd_ctl_add(card, snd_ctl_new1(&snd_interwave_controls[idx], chip))) < 0)
 			return err;
 	snd_cs4231_out(chip, CS4231_LINE_LEFT_OUTPUT, 0x9f);
diff -Nru a/sound/isa/opl3sa2.c b/sound/isa/opl3sa2.c
--- a/sound/isa/opl3sa2.c	2004-10-18 14:57:04 -07:00
+++ b/sound/isa/opl3sa2.c	2004-10-18 14:57:04 -07:00
@@ -37,8 +37,7 @@
 MODULE_AUTHOR("Jaroslav Kysela <perex@suse.cz>");
 MODULE_DESCRIPTION("Yamaha OPL3SA2+");
 MODULE_LICENSE("GPL");
-MODULE_CLASSES("{sound}");
-MODULE_DEVICES("{{Yamaha,YMF719E-S},"
+MODULE_SUPPORTED_DEVICE("{{Yamaha,YMF719E-S},"
 		"{Genius,Sound Maker 3DX},"
 		"{Yamaha,OPL3SA3},"
 		"{Intel,AL440LX sound},"
@@ -63,45 +62,32 @@
 
 module_param_array(index, int, boot_devs, 0444);
 MODULE_PARM_DESC(index, "Index value for OPL3-SA soundcard.");
-MODULE_PARM_SYNTAX(index, SNDRV_INDEX_DESC);
 module_param_array(id, charp, boot_devs, 0444);
 MODULE_PARM_DESC(id, "ID string for OPL3-SA soundcard.");
-MODULE_PARM_SYNTAX(id, SNDRV_ID_DESC);
 module_param_array(enable, bool, boot_devs, 0444);
 MODULE_PARM_DESC(enable, "Enable OPL3-SA soundcard.");
-MODULE_PARM_SYNTAX(enable, SNDRV_ENABLE_DESC);
 #ifdef CONFIG_PNP
 module_param_array(isapnp, bool, boot_devs, 0444);
 MODULE_PARM_DESC(isapnp, "PnP detection for specified soundcard.");
-MODULE_PARM_SYNTAX(isapnp, SNDRV_ISAPNP_DESC);
 #endif
 module_param_array(port, long, boot_devs, 0444);
 MODULE_PARM_DESC(port, "Port # for OPL3-SA driver.");
-MODULE_PARM_SYNTAX(port, SNDRV_ENABLED ",allows:{{0xf86},{0x370},{0x100}},dialog:list");
 module_param_array(sb_port, long, boot_devs, 0444);
 MODULE_PARM_DESC(sb_port, "SB port # for OPL3-SA driver.");
-MODULE_PARM_SYNTAX(sb_port, SNDRV_ENABLED ",allows:{{0x220},{0x240},{0x260}},dialog:list");
 module_param_array(wss_port, long, boot_devs, 0444);
 MODULE_PARM_DESC(wss_port, "WSS port # for OPL3-SA driver.");
-MODULE_PARM_SYNTAX(wss_port, SNDRV_ENABLED ",allows:{{0x530},{0xe80},{0xf40},{0x604}},dialog:list");
 module_param_array(fm_port, long, boot_devs, 0444);
 MODULE_PARM_DESC(fm_port, "FM port # for OPL3-SA driver.");
-MODULE_PARM_SYNTAX(fm_port, SNDRV_ENABLED ",allows:{{0x388}},dialog:list");
 module_param_array(midi_port, long, boot_devs, 0444);
 MODULE_PARM_DESC(midi_port, "MIDI port # for OPL3-SA driver.");
-MODULE_PARM_SYNTAX(midi_port, SNDRV_ENABLED ",allows:{{0x330},{0x300}},dialog:list");
 module_param_array(irq, int, boot_devs, 0444);
 MODULE_PARM_DESC(irq, "IRQ # for OPL3-SA driver.");
-MODULE_PARM_SYNTAX(irq, SNDRV_ENABLED ",allows:{{0},{1},{3},{5},{9},{11},{12},{15}},dialog:list");
 module_param_array(dma1, int, boot_devs, 0444);
 MODULE_PARM_DESC(dma1, "DMA1 # for OPL3-SA driver.");
-MODULE_PARM_SYNTAX(dma1, SNDRV_ENABLED ",allows:{{1},{3},{5},{6},{7}},dialog:list");
 module_param_array(dma2, int, boot_devs, 0444);
 MODULE_PARM_DESC(dma2, "DMA2 # for OPL3-SA driver.");
-MODULE_PARM_SYNTAX(dma2, SNDRV_ENABLED ",allows:{{1},{3},{5},{6},{7}},dialog:list");
 module_param_array(opl3sa3_ymode, int, boot_devs, 0444);
 MODULE_PARM_DESC(opl3sa3_ymode, "Speaker size selection for 3D Enhancement mode: Desktop/Large Notebook/Small Notebook/HiFi.");
-MODULE_PARM_SYNTAX(opl3sa3_ymode, SNDRV_ENABLED ",allows:{{0,3}},dialog:list");  /* SL Added */
 
 /* control ports */
 #define OPL3SA2_PM_CTRL		0x01
@@ -131,7 +117,6 @@
 #define OPL3SA2_PM_D3	(OPL3SA2_PM_ADOWN|OPL3SA2_PM_PSV|OPL3SA2_PM_PDN|OPL3SA2_PM_PDX)
 
 typedef struct snd_opl3sa2 opl3sa2_t;
-#define chip_t opl3sa2_t
 
 struct snd_opl3sa2 {
 	snd_card_t *card;
@@ -304,7 +289,7 @@
 static irqreturn_t snd_opl3sa2_interrupt(int irq, void *dev_id, struct pt_regs *regs)
 {
 	unsigned short status;
-	opl3sa2_t *chip = snd_magic_cast(opl3sa2_t, dev_id, return IRQ_NONE);
+	opl3sa2_t *chip = dev_id;
 	int handled = 0;
 
 	if (chip == NULL || chip->card == NULL)
@@ -477,8 +462,6 @@
 	return change;
 }
 
-#define OPL3SA2_CONTROLS (sizeof(snd_opl3sa2_controls)/sizeof(snd_kcontrol_new_t))
-
 static snd_kcontrol_new_t snd_opl3sa2_controls[] = {
 OPL3SA2_DOUBLE("Master Playback Switch", 0, 0x07, 0x08, 7, 7, 1, 1),
 OPL3SA2_DOUBLE("Master Playback Volume", 0, 0x07, 0x08, 0, 0, 15, 1),
@@ -486,8 +469,6 @@
 OPL3SA2_SINGLE("Mic Playback Volume", 0, 0x09, 0, 31, 1)
 };
 
-#define OPL3SA2_TONE_CONTROLS (sizeof(snd_opl3sa2_tone_controls)/sizeof(snd_kcontrol_new_t))
-
 static snd_kcontrol_new_t snd_opl3sa2_tone_controls[] = {
 OPL3SA2_DOUBLE("3D Control - Wide", 0, 0x14, 0x14, 4, 0, 7, 0),
 OPL3SA2_DOUBLE("Tone Control - Bass", 0, 0x15, 0x15, 4, 0, 7, 0),
@@ -496,7 +477,7 @@
 
 static void snd_opl3sa2_master_free(snd_kcontrol_t *kcontrol)
 {
-	opl3sa2_t *chip = snd_magic_cast(opl3sa2_t, _snd_kcontrol_chip(kcontrol), return);
+	opl3sa2_t *chip = snd_kcontrol_chip(kcontrol);
 	chip->master_switch = NULL;
 	chip->master_volume = NULL;
 }
@@ -531,7 +512,7 @@
         if ((err = snd_ctl_rename_id(card, &id1, &id2)) < 0)
                 return err;
 	/* add OPL3SA2 controls */
-	for (idx = 0; idx < OPL3SA2_CONTROLS; idx++) {
+	for (idx = 0; idx < ARRAY_SIZE(snd_opl3sa2_controls); idx++) {
 		if ((err = snd_ctl_add(card, kctl = snd_ctl_new1(&snd_opl3sa2_controls[idx], chip))) < 0)
 			return err;
 		switch (idx) {
@@ -540,7 +521,7 @@
 		}
 	}
 	if (chip->version > 2) {
-		for (idx = 0; idx < OPL3SA2_TONE_CONTROLS; idx++)
+		for (idx = 0; idx < ARRAY_SIZE(snd_opl3sa2_tone_controls); idx++)
 			if ((err = snd_ctl_add(card, snd_ctl_new1(&snd_opl3sa2_tone_controls[idx], chip))) < 0)
 				return err;
 	}
@@ -551,7 +532,7 @@
 #ifdef CONFIG_PM
 static int snd_opl3sa2_suspend(snd_card_t *card, unsigned int state)
 {
-	opl3sa2_t *chip = snd_magic_cast(opl3sa2_t, card->pm_private_data, return -EINVAL);
+	opl3sa2_t *chip = card->pm_private_data;
 
 	snd_pcm_suspend_all(chip->cs4231->pcm); /* stop before saving regs */
 	chip->cs4231_suspend(chip->cs4231);
@@ -565,7 +546,7 @@
 
 static int snd_opl3sa2_resume(snd_card_t *card, unsigned int state)
 {
-	opl3sa2_t *chip = snd_magic_cast(opl3sa2_t, card->pm_private_data, return -EINVAL);
+	opl3sa2_t *chip = card->pm_private_data;
 	int i;
 
 	/* power up */
@@ -656,13 +637,13 @@
 		release_resource(chip->res_port);
 		kfree_nocheck(chip->res_port);
 	}
-	snd_magic_kfree(chip);
+	kfree(chip);
 	return 0;
 }
 
 static int snd_opl3sa2_dev_free(snd_device_t *device)
 {
-	opl3sa2_t *chip = snd_magic_cast(opl3sa2_t, device->device_data, return -ENXIO);
+	opl3sa2_t *chip = device->device_data;
 	return snd_opl3sa2_free(chip);
 }
 
@@ -707,7 +688,7 @@
 		return -ENOMEM;
 	strcpy(card->driver, "OPL3SA2");
 	strcpy(card->shortname, "Yamaha OPL3-SA2");
-	chip = snd_magic_kcalloc(opl3sa2_t, 0, GFP_KERNEL);
+	chip = kcalloc(1, sizeof(*chip), GFP_KERNEL);
 	if (chip == NULL) {
 		err = -ENOMEM;
 		goto __error;
diff -Nru a/sound/isa/opti9xx/opti92x-ad1848.c b/sound/isa/opti9xx/opti92x-ad1848.c
--- a/sound/isa/opti9xx/opti92x-ad1848.c	2004-10-18 14:56:15 -07:00
+++ b/sound/isa/opti9xx/opti92x-ad1848.c	2004-10-18 14:56:15 -07:00
@@ -52,19 +52,18 @@
 #include <sound/initval.h>
 
 MODULE_AUTHOR("Massimo Piccioni <dafastidio@libero.it>");
-MODULE_CLASSES("{sound}");
 MODULE_LICENSE("GPL");
 #ifdef OPTi93X
 MODULE_DESCRIPTION("OPTi93X");
-MODULE_DEVICES("{{OPTi,82C931/3}}");
+MODULE_SUPPORTED_DEVICE("{{OPTi,82C931/3}}");
 #else	/* OPTi93X */
 #ifdef CS4231
 MODULE_DESCRIPTION("OPTi92X - CS4231");
-MODULE_DEVICES("{{OPTi,82C924 (CS4231)},"
+MODULE_SUPPORTED_DEVICE("{{OPTi,82C924 (CS4231)},"
 		"{OPTi,82C925 (CS4231)}}");
 #else	/* CS4231 */
 MODULE_DESCRIPTION("OPTi92X - AD1848");
-MODULE_DEVICES("{{OPTi,82C924 (AD1848)},"
+MODULE_SUPPORTED_DEVICE("{{OPTi,82C924 (AD1848)},"
 		"{OPTi,82C925 (AD1848)},"
 	        "{OAK,Mozart}}");
 #endif	/* CS4231 */
@@ -86,38 +85,27 @@
 
 module_param(index, int, 0444);
 MODULE_PARM_DESC(index, "Index value for opti9xx based soundcard.");
-MODULE_PARM_SYNTAX(index, SNDRV_INDEX_DESC);
 module_param(id, charp, 0444);
 MODULE_PARM_DESC(id, "ID string for opti9xx based soundcard.");
-MODULE_PARM_SYNTAX(id, SNDRV_ID_DESC);
 //module_param(enable, bool, 0444);
 //MODULE_PARM_DESC(enable, "Enable opti9xx soundcard.");
-//MODULE_PARM_SYNTAX(enable, SNDRV_ENABLE_DESC);
 module_param(isapnp, bool, 0444);
 MODULE_PARM_DESC(isapnp, "Enable ISA PnP detection for specified soundcard.");
-MODULE_PARM_SYNTAX(isapnp, SNDRV_ISAPNP_DESC);
 module_param(port, long, 0444);
 MODULE_PARM_DESC(port, "WSS port # for opti9xx driver.");
-MODULE_PARM_SYNTAX(port, SNDRV_PORT_DESC);
 module_param(mpu_port, long, 0444);
 MODULE_PARM_DESC(mpu_port, "MPU-401 port # for opti9xx driver.");
-MODULE_PARM_SYNTAX(mpu_port, SNDRV_PORT_DESC);
 module_param(fm_port, long, 0444);
 MODULE_PARM_DESC(fm_port, "FM port # for opti9xx driver.");
-MODULE_PARM_SYNTAX(fm_port, SNDRV_PORT_DESC);
 module_param(irq, int, 0444);
 MODULE_PARM_DESC(irq, "WSS irq # for opti9xx driver.");
-MODULE_PARM_SYNTAX(irq, SNDRV_IRQ_DESC);
 module_param(mpu_irq, int, 0444);
 MODULE_PARM_DESC(mpu_irq, "MPU-401 irq # for opti9xx driver.");
-MODULE_PARM_SYNTAX(mpu_irq, SNDRV_IRQ_DESC);
 module_param(dma1, int, 0444);
 MODULE_PARM_DESC(dma1, "1st dma # for opti9xx driver.");
-MODULE_PARM_SYNTAX(dma1, SNDRV_DMA_DESC);
 #if defined(CS4231) || defined(OPTi93X)
 module_param(dma2, int, 0444);
 MODULE_PARM_DESC(dma2, "2nd dma # for opti9xx driver.");
-MODULE_PARM_SYNTAX(dma2, SNDRV_DMA_DESC);
 #endif	/* CS4231 || OPTi93X */
 
 #define OPTi9XX_HW_DETECT	0
@@ -474,7 +462,6 @@
 	unsigned char dma_bits;
 	unsigned char mpu_port_bits = 0;
 	unsigned char mpu_irq_bits;
-	unsigned long flags;
 
 	switch (chip->hardware) {
 #ifndef OPTi93X
@@ -601,13 +588,11 @@
 	dma_bits |= 0x04;
 #endif	/* CS4231 || OPTi93X */
 
-	spin_lock_irqsave(&chip->lock, flags);
 #ifndef OPTi93X
 	 outb(irq_bits << 3 | dma_bits, chip->wss_base);
 #else /* OPTi93X */
 	snd_opti9xx_write(chip, OPTi9XX_MC_REG(3), (irq_bits << 3 | dma_bits));
 #endif /* OPTi93X */
-	spin_unlock_irqrestore(&chip->lock, flags);
 
 __skip_resources:
 	if (chip->hardware > OPTi9XX_HW_82C928) {
@@ -664,8 +649,6 @@
 
 #ifdef OPTi93X
 
-#define chip_t opti93x_t
-
 static unsigned char snd_opti93x_default_image[32] =
 {
 	0x00,		/* 00/00 - l_mixout_outctrl */
@@ -767,15 +750,10 @@
 
 static void snd_opti93x_mute(opti93x_t *chip, int mute)
 {
-	unsigned long flags;
-
-	spin_lock_irqsave(&chip->lock, flags);
-
 	mute = mute ? 1 : 0;
-	if (chip->mute == mute) {
-		spin_unlock_irqrestore(&chip->lock, flags);
+	if (chip->mute == mute)
 		return;
-	}
+
 	chip->mute = mute;
 
 	snd_opti93x_mute_reg(chip, OPTi93X_CD_LEFT_INPUT, mute);
@@ -800,8 +778,6 @@
 	snd_opti93x_mute_reg(chip, OPTi93X_MIC_RIGHT_INPUT, mute);
 	snd_opti93x_mute_reg(chip, OPTi93X_OUT_LEFT, mute);
 	snd_opti93x_mute_reg(chip, OPTi93X_OUT_RIGHT, mute);
-
-	spin_unlock_irqrestore(&chip->lock, flags);
 }
 
 
@@ -822,7 +798,7 @@
 static unsigned int rates[] = {  5512,  6615,  8000,  9600, 11025, 16000, 
 				18900, 22050, 27428, 32000, 33075, 37800,
 				44100, 48000 };
-#define RATES sizeof(rates) / sizeof(rates[0])
+#define RATES ARRAY_SIZE(rates)
 
 static snd_pcm_hw_constraint_list_t hw_constraints_rates = {
 	.count = RATES,
@@ -873,10 +849,8 @@
 
 static void snd_opti93x_playback_format(opti93x_t *chip, unsigned char fmt)
 {
-	unsigned long flags;
 	unsigned char mask;
 
-	spin_lock_irqsave(&chip->lock, flags);
 	snd_opti93x_mute(chip, 1);
 
 	snd_opti93x_mce_up(chip);
@@ -885,14 +859,10 @@
 	snd_opti93x_mce_down(chip);
 
 	snd_opti93x_mute(chip, 0);
-	spin_unlock_irqrestore(&chip->lock, flags);
 }
 
 static void snd_opti93x_capture_format(opti93x_t *chip, unsigned char fmt)
 {
-	unsigned long flags;
-
-	spin_lock_irqsave(&chip->lock, flags);
 	snd_opti93x_mute(chip, 1);
 
 	snd_opti93x_mce_up(chip);
@@ -904,7 +874,6 @@
 	snd_opti93x_mce_down(chip);
 
 	snd_opti93x_mute(chip, 0);
-	spin_unlock_irqrestore(&chip->lock, flags);
 }
 
 
@@ -1128,7 +1097,7 @@
 
 irqreturn_t snd_opti93x_interrupt(int irq, void *dev_id, struct pt_regs *regs)
 {
-	opti93x_t *codec = snd_magic_cast(opti93x_t, dev_id, return IRQ_NONE);
+	opti93x_t *codec = dev_id;
 	unsigned char status;
 
 	status = snd_opti9xx_read(codec->chip, OPTi9XX_MC_REG(11));
@@ -1274,13 +1243,13 @@
 	if (chip->irq >= 0) {
 	  free_irq(chip->irq, chip);
 	}
-	snd_magic_kfree(chip);
+	kfree(chip);
 	return 0;
 }
 
 static int snd_opti93x_dev_free(snd_device_t *device)
 {
-	opti93x_t *chip = snd_magic_cast(opti93x_t, device->device_data, return -ENXIO);
+	opti93x_t *chip = device->device_data;
 	return snd_opti93x_free(chip);
 }
 
@@ -1305,7 +1274,7 @@
 	opti93x_t *codec;
 
 	*rcodec = NULL;
-	codec = snd_magic_kcalloc(opti93x_t, 0, GFP_KERNEL);
+	codec = kcalloc(1, sizeof(*codec), GFP_KERNEL);
 	if (codec == NULL)
 		return -ENOMEM;
 	codec->irq = -1;
@@ -1385,7 +1354,7 @@
 
 static void snd_opti93x_pcm_free(snd_pcm_t *pcm)
 {
-	opti93x_t *codec = snd_magic_cast(opti93x_t, pcm->private_data, return);
+	opti93x_t *codec = pcm->private_data;
 	codec->pcm = NULL;
 	snd_pcm_lib_preallocate_free_for_all(pcm);
 }
@@ -1608,8 +1577,6 @@
 	return change;
 }
 
-#define OPTi93X_CONTROLS (sizeof(snd_opti93x_controls)/sizeof(snd_kcontrol_new_t))
-
 static snd_kcontrol_new_t snd_opti93x_controls[] = {
 OPTi93X_DOUBLE("Master Playback Switch", 0, OPTi93X_OUT_LEFT, OPTi93X_OUT_RIGHT, 7, 7, 1, 1),
 OPTi93X_DOUBLE("Master Playback Volume", 0, OPTi93X_OUT_LEFT, OPTi93X_OUT_RIGHT, 1, 1, 31, 1), 
@@ -1649,7 +1616,7 @@
 
 	strcpy(card->mixername, snd_opti93x_chip_id(chip));
 
-	for (idx = 0; idx < OPTi93X_CONTROLS; idx++) {
+	for (idx = 0; idx < ARRAY_SIZE(snd_opti93x_controls); idx++) {
 		knew = snd_opti93x_controls[idx];
 		if (chip->hardware == OPTi9XX_HW_82C930) {
 			if (strstr(knew.name, "FM"))	/* skip FM controls */
diff -Nru a/sound/isa/sb/emu8000.c b/sound/isa/sb/emu8000.c
--- a/sound/isa/sb/emu8000.c	2004-10-18 14:56:28 -07:00
+++ b/sound/isa/sb/emu8000.c	2004-10-18 14:56:28 -07:00
@@ -345,8 +345,6 @@
 		EMU8000_INIT4_WRITE(emu, i, *p);
 }
 
-#define NELEM(arr) (sizeof(arr)/sizeof((arr)[0]))
-
 
 /*
  * Send initialization arrays to start up, this just follows the
@@ -355,18 +353,18 @@
 static void __init
 init_arrays(emu8000_t *emu)
 {
-	send_array(emu, init1, NELEM(init1)/4);
+	send_array(emu, init1, ARRAY_SIZE(init1)/4);
 
 	set_current_state(TASK_INTERRUPTIBLE);
 	schedule_timeout((HZ * (44099 + 1024)) / 44100); /* wait for 1024 clocks */
-	send_array(emu, init2, NELEM(init2)/4);
-	send_array(emu, init3, NELEM(init3)/4);
+	send_array(emu, init2, ARRAY_SIZE(init2)/4);
+	send_array(emu, init3, ARRAY_SIZE(init3)/4);
 
 	EMU8000_HWCF4_WRITE(emu, 0);
 	EMU8000_HWCF5_WRITE(emu, 0x83);
 	EMU8000_HWCF6_WRITE(emu, 0x8000);
 
-	send_array(emu, init4, NELEM(init4)/4);
+	send_array(emu, init4, ARRAY_SIZE(init4)/4);
 }
 
 
@@ -821,8 +819,6 @@
  * mixer interface
  *----------------------------------------------------------------*/
 
-#define chip_t	emu8000_t
-
 /*
  * bass/treble
  */
@@ -1070,7 +1066,7 @@
 		release_resource(hw->res_port3);
 		kfree_nocheck(hw->res_port3);
 	}
-	snd_magic_kfree(hw);
+	kfree(hw);
 	return 0;
 }
 
@@ -1078,7 +1074,7 @@
  */
 static int snd_emu8000_dev_free(snd_device_t *device)
 {
-	emu8000_t *hw = snd_magic_cast(emu8000_t, device->device_data, return -ENXIO);
+	emu8000_t *hw = device->device_data;
 	return snd_emu8000_free(hw);
 }
 
@@ -1101,7 +1097,7 @@
 	if (seq_ports <= 0)
 		return 0;
 
-	hw = snd_magic_kcalloc(emu8000_t, 0, GFP_KERNEL);
+	hw = kcalloc(1, sizeof(*hw), GFP_KERNEL);
 	if (hw == NULL)
 		return -ENOMEM;
 	spin_lock_init(&hw->reg_lock);
diff -Nru a/sound/isa/sb/emu8000_callback.c b/sound/isa/sb/emu8000_callback.c
--- a/sound/isa/sb/emu8000_callback.c	2004-10-18 14:56:28 -07:00
+++ b/sound/isa/sb/emu8000_callback.c	2004-10-18 14:56:28 -07:00
@@ -94,7 +94,7 @@
 	int dcysusv;
 	emu8000_t *hw;
 
-	hw = snd_magic_cast(emu8000_t, vp->hw, return);
+	hw = vp->hw;
 	dcysusv = 0x8000 | (unsigned char)vp->reg.parm.modrelease;
 	EMU8000_DCYSUS_WRITE(hw, vp->ch, dcysusv);
 	dcysusv = 0x8000 | (unsigned char)vp->reg.parm.volrelease;
@@ -109,7 +109,7 @@
 {
 	emu8000_t *hw; 
 
-	hw = snd_magic_cast(emu8000_t, vp->hw, return);
+	hw = vp->hw;
 	EMU8000_DCYSUSV_WRITE(hw, vp->ch, 0x807F);
 }
 
@@ -121,7 +121,7 @@
 {
 	emu8000_t *hw;
 
-	hw = snd_magic_cast(emu8000_t, vp->hw, return);
+	hw = vp->hw;
 	if (update & SNDRV_EMUX_UPDATE_VOLUME)
 		set_volume(hw, vp);
 	if (update & SNDRV_EMUX_UPDATE_PITCH)
@@ -168,7 +168,7 @@
 	} best[END];
 	struct best *bp;
 
-	hw = snd_magic_cast(emu8000_t, emu->hw, return NULL);
+	hw = emu->hw;
 
 	for (i = 0; i < END; i++) {
 		best[i].time = (unsigned int)(-1); /* XXX MAX_?INT really */;
@@ -235,7 +235,7 @@
 	snd_midi_channel_t *chan;
 	emu8000_t *hw;
 
-	hw = snd_magic_cast(emu8000_t, vp->hw, return -EINVAL);
+	hw = vp->hw;
 	ch = vp->ch;
 	chan = vp->chan;
 
@@ -313,7 +313,7 @@
 	unsigned int temp;
 	emu8000_t *hw;
 
-	hw = snd_magic_cast(emu8000_t, vp->hw, return);
+	hw = vp->hw;
 
 	/* set reverb and pitch target */
 	temp = vp->reg.parm.reverb;
@@ -333,7 +333,7 @@
 {
 	emu8000_t *hw;
 
-	hw = snd_magic_cast(emu8000_t, emu->hw, return);
+	hw = emu->hw;
 	EMU8000_DCYSUSV_WRITE(hw, ch, 0x807F);
 	snd_emu8000_tweak_voice(hw, ch);
 }
@@ -457,7 +457,7 @@
 {
 	emu8000_t *hw;
 
-	hw = snd_magic_cast(emu8000_t, emu->hw, return);
+	hw = emu->hw;
 
 	switch (parsed) {
 	case SNDRV_MIDI_SYSEX_GS_CHORUS_MODE:
@@ -482,7 +482,7 @@
 {
 	emu8000_t *hw;
 
-	hw = snd_magic_cast(emu8000_t, emu->hw, return -EINVAL);
+	hw = emu->hw;
 
 	switch (cmd) {
 	case _EMUX_OSS_REVERB_MODE:
@@ -526,7 +526,7 @@
 load_fx(snd_emux_t *emu, int type, int mode, const void __user *buf, long len)
 {
 	emu8000_t *hw;
-	hw = snd_magic_cast(emu8000_t, emu->hw, return -EINVAL);
+	hw = emu->hw;
 
 	switch (type) {
 	case SNDRV_EMU8000_LOAD_CHORUS_FX:
diff -Nru a/sound/isa/sb/emu8000_local.h b/sound/isa/sb/emu8000_local.h
--- a/sound/isa/sb/emu8000_local.h	2004-10-18 14:56:32 -07:00
+++ b/sound/isa/sb/emu8000_local.h	2004-10-18 14:56:32 -07:00
@@ -29,8 +29,6 @@
 #include <sound/emu8000.h>
 #include <sound/emu8000_reg.h>
 
-#define NELEM(arr) (sizeof(arr)/sizeof((arr)[0]))
-
 /* emu8000_patch.c */
 int snd_emu8000_sample_new(snd_emux_t *rec, snd_sf_sample_t *sp, snd_util_memhdr_t *hdr, const void __user *data, long count);
 int snd_emu8000_sample_free(snd_emux_t *rec, snd_sf_sample_t *sp, snd_util_memhdr_t *hdr);
diff -Nru a/sound/isa/sb/emu8000_patch.c b/sound/isa/sb/emu8000_patch.c
--- a/sound/isa/sb/emu8000_patch.c	2004-10-18 14:56:11 -07:00
+++ b/sound/isa/sb/emu8000_patch.c	2004-10-18 14:56:11 -07:00
@@ -155,7 +155,7 @@
 	int  dram_offset, dram_start;
 	emu8000_t *emu;
 
-	emu = snd_magic_cast(emu8000_t, rec->hw, return -EINVAL);
+	emu = rec->hw;
 	snd_assert(sp != NULL, return -EINVAL);
 
 	if (sp->v.size == 0)
diff -Nru a/sound/isa/sb/emu8000_pcm.c b/sound/isa/sb/emu8000_pcm.c
--- a/sound/isa/sb/emu8000_pcm.c	2004-10-18 14:57:04 -07:00
+++ b/sound/isa/sb/emu8000_pcm.c	2004-10-18 14:57:04 -07:00
@@ -23,8 +23,6 @@
 #include <sound/initval.h>
 #include <sound/pcm.h>
 
-#define chip_t emu8000_t
-
 /*
  * define the following if you want to use this pcm with non-interleaved mode
  */
@@ -235,7 +233,7 @@
 	emu8k_pcm_t *rec;
 	snd_pcm_runtime_t *runtime = subs->runtime;
 
-	rec = snd_kcalloc(sizeof(*rec), GFP_KERNEL);
+	rec = kcalloc(1, sizeof(*rec), GFP_KERNEL);
 	if (! rec)
 		return -ENOMEM;
 
diff -Nru a/sound/isa/sb/emu8000_synth.c b/sound/isa/sb/emu8000_synth.c
--- a/sound/isa/sb/emu8000_synth.c	2004-10-18 14:57:20 -07:00
+++ b/sound/isa/sb/emu8000_synth.c	2004-10-18 14:57:20 -07:00
@@ -27,7 +27,6 @@
 MODULE_AUTHOR("Takashi Iwai, Steve Ratcliffe");
 MODULE_DESCRIPTION("Emu8000 synth plug-in routine");
 MODULE_LICENSE("GPL");
-MODULE_CLASSES("{sound}");
 
 /*----------------------------------------------------------------*/
 
diff -Nru a/sound/isa/sb/es968.c b/sound/isa/sb/es968.c
--- a/sound/isa/sb/es968.c	2004-10-18 14:56:31 -07:00
+++ b/sound/isa/sb/es968.c	2004-10-18 14:56:31 -07:00
@@ -29,15 +29,12 @@
 #include <sound/initval.h>
 #include <sound/sb.h>
 
-#define chip_t sb_t
-
 #define PFX "es968: "
 
 MODULE_AUTHOR("Massimo Piccioni <dafastidio@libero.it>");
 MODULE_DESCRIPTION("ESS AudioDrive ES968");
 MODULE_LICENSE("GPL");
-MODULE_CLASSES("{sound}");
-MODULE_DEVICES("{{ESS,AudioDrive ES968}}");
+MODULE_SUPPORTED_DEVICE("{{ESS,AudioDrive ES968}}");
 
 static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX;	/* Index 0-MAX */
 static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR;	/* ID for this card */
@@ -49,22 +46,16 @@
 
 module_param_array(index, int, boot_devs, 0444);
 MODULE_PARM_DESC(index, "Index value for es968 based soundcard.");
-MODULE_PARM_SYNTAX(index, SNDRV_INDEX_DESC);
 module_param_array(id, charp, boot_devs, 0444);
 MODULE_PARM_DESC(id, "ID string for es968 based soundcard.");
-MODULE_PARM_SYNTAX(id, SNDRV_ID_DESC);
 module_param_array(enable, bool, boot_devs, 0444);
 MODULE_PARM_DESC(enable, "Enable es968 based soundcard.");
-MODULE_PARM_SYNTAX(enable, SNDRV_ENABLE_DESC);
 module_param_array(port, long, boot_devs, 0444);
 MODULE_PARM_DESC(port, "Port # for es968 driver.");
-MODULE_PARM_SYNTAX(port, SNDRV_PORT12_DESC);
 module_param_array(irq, int, boot_devs, 0444);
 MODULE_PARM_DESC(irq, "IRQ # for es968 driver.");
-MODULE_PARM_SYNTAX(irq, SNDRV_IRQ_DESC);
 module_param_array(dma8, int, boot_devs, 0444);
 MODULE_PARM_DESC(dma8, "8-bit DMA # for es968 driver.");
-MODULE_PARM_SYNTAX(dma8, SNDRV_DMA8_DESC);
 
 struct snd_card_es968 {
 	struct pnp_dev *dev;
@@ -82,7 +73,7 @@
 static irqreturn_t snd_card_es968_interrupt(int irq, void *dev_id,
 					    struct pt_regs *regs)
 {
-	sb_t *chip = snd_magic_cast(sb_t, dev_id, return IRQ_NONE);
+	sb_t *chip = dev_id;
 
 	if (chip->open & SB_OPEN_PCM) {
 		return snd_sb8dsp_interrupt(chip);
diff -Nru a/sound/isa/sb/sb16.c b/sound/isa/sb/sb16.c
--- a/sound/isa/sb/sb16.c	2004-10-18 14:56:49 -07:00
+++ b/sound/isa/sb/sb16.c	2004-10-18 14:56:49 -07:00
@@ -37,8 +37,6 @@
 #define SNDRV_LEGACY_FIND_FREE_DMA
 #include <sound/initval.h>
 
-#define chip_t sb_t
-
 #ifdef SNDRV_SBAWE
 #define PFX "sbawe: "
 #else
@@ -47,17 +45,16 @@
 
 MODULE_AUTHOR("Jaroslav Kysela <perex@suse.cz>");
 MODULE_LICENSE("GPL");
-MODULE_CLASSES("{sound}");
 #ifndef SNDRV_SBAWE
 MODULE_DESCRIPTION("Sound Blaster 16");
-MODULE_DEVICES("{{Creative Labs,SB 16},"
+MODULE_SUPPORTED_DEVICE("{{Creative Labs,SB 16},"
 		"{Creative Labs,SB Vibra16S},"
 		"{Creative Labs,SB Vibra16C},"
 		"{Creative Labs,SB Vibra16CL},"
 		"{Creative Labs,SB Vibra16X}}");
 #else
 MODULE_DESCRIPTION("Sound Blaster AWE");
-MODULE_DEVICES("{{Creative Labs,SB AWE 32},"
+MODULE_SUPPORTED_DEVICE("{{Creative Labs,SB AWE 32},"
 		"{Creative Labs,SB AWE 64},"
 		"{Creative Labs,SB AWE 64 Gold}}");
 #endif
@@ -96,53 +93,39 @@
 
 module_param_array(index, int, boot_devs, 0444);
 MODULE_PARM_DESC(index, "Index value for SoundBlaster 16 soundcard.");
-MODULE_PARM_SYNTAX(index, SNDRV_INDEX_DESC);
 module_param_array(id, charp, boot_devs, 0444);
 MODULE_PARM_DESC(id, "ID string for SoundBlaster 16 soundcard.");
-MODULE_PARM_SYNTAX(id, SNDRV_ID_DESC);
 module_param_array(enable, bool, boot_devs, 0444);
 MODULE_PARM_DESC(enable, "Enable SoundBlaster 16 soundcard.");
-MODULE_PARM_SYNTAX(enable, SNDRV_ENABLE_DESC);
 #ifdef CONFIG_PNP
 module_param_array(isapnp, bool, boot_devs, 0444);
 MODULE_PARM_DESC(isapnp, "PnP detection for specified soundcard.");
-MODULE_PARM_SYNTAX(isapnp, SNDRV_ISAPNP_DESC);
 #endif
 module_param_array(port, long, boot_devs, 0444);
 MODULE_PARM_DESC(port, "Port # for SB16 driver.");
-MODULE_PARM_SYNTAX(port, SNDRV_ENABLED ",allows:{{0x220},{0x240},{0x260},{0x280}},dialog:list");
 module_param_array(mpu_port, long, boot_devs, 0444);
 MODULE_PARM_DESC(mpu_port, "MPU-401 port # for SB16 driver.");
-MODULE_PARM_SYNTAX(mpu_port, SNDRV_ENABLED ",allows:{{0x330},{0x300}},dialog:list");
 module_param_array(fm_port, long, boot_devs, 0444);
 MODULE_PARM_DESC(fm_port, "FM port # for SB16 PnP driver.");
-MODULE_PARM_SYNTAX(fm_port, SNDRV_ENABLED ",allows:{{0x388},{0x38c},{0x390},{0x394}},dialog:list");
 #ifdef SNDRV_SBAWE_EMU8000
 module_param_array(awe_port, long, boot_devs, 0444);
 MODULE_PARM_DESC(awe_port, "AWE port # for SB16 PnP driver.");
-MODULE_PARM_SYNTAX(awe_port, SNDRV_ENABLED ",allows:{{0x620},{0x640},{0x660},{0x680}},dialog:list");
 #endif
 module_param_array(irq, int, boot_devs, 0444);
 MODULE_PARM_DESC(irq, "IRQ # for SB16 driver.");
-MODULE_PARM_SYNTAX(irq, SNDRV_IRQ_DESC);
 module_param_array(dma8, int, boot_devs, 0444);
 MODULE_PARM_DESC(dma8, "8-bit DMA # for SB16 driver.");
-MODULE_PARM_SYNTAX(dma8, SNDRV_DMA8_DESC);
 module_param_array(dma16, int, boot_devs, 0444);
 MODULE_PARM_DESC(dma16, "16-bit DMA # for SB16 driver.");
-MODULE_PARM_SYNTAX(dma16, SNDRV_DMA16_DESC);
 module_param_array(mic_agc, int, boot_devs, 0444);
 MODULE_PARM_DESC(mic_agc, "Mic Auto-Gain-Control switch.");
-MODULE_PARM_SYNTAX(mic_agc, SNDRV_ENABLED "," SNDRV_BOOLEAN_TRUE_DESC);
 #ifdef CONFIG_SND_SB16_CSP
 module_param_array(csp, int, boot_devs, 0444);
 MODULE_PARM_DESC(csp, "ASP/CSP chip support.");
-MODULE_PARM_SYNTAX(csp, SNDRV_ENABLED "," SNDRV_ENABLE_DESC);
 #endif
 #ifdef SNDRV_SBAWE_EMU8000
 module_param_array(seq_ports, int, boot_devs, 0444);
 MODULE_PARM_DESC(seq_ports, "Number of sequencer ports for WaveTable synth.");
-MODULE_PARM_SYNTAX(seq_ports, SNDRV_ENABLED ",allows:{{0,8}},skill:advanced");
 #endif
 
 struct snd_card_sb16 {
diff -Nru a/sound/isa/sb/sb16_csp.c b/sound/isa/sb/sb16_csp.c
--- a/sound/isa/sb/sb16_csp.c	2004-10-18 14:57:04 -07:00
+++ b/sound/isa/sb/sb16_csp.c	2004-10-18 14:57:04 -07:00
@@ -33,12 +33,9 @@
 #include <sound/sb16_csp.h>
 #include <sound/initval.h>
 
-#define chip_t snd_sb_csp_t
-
 MODULE_AUTHOR("Uros Bizjak <uros@kss-loka.si>");
 MODULE_DESCRIPTION("ALSA driver for SB16 Creative Signal Processor");
 MODULE_LICENSE("GPL");
-MODULE_CLASSES("{sound}");
 
 #ifdef SNDRV_LITTLE_ENDIAN
 #define CSP_HDR_VALUE(a,b,c,d)	((a) | ((b)<<8) | ((c)<<16) | ((d)<<24))
@@ -127,7 +124,7 @@
 	if ((err = snd_hwdep_new(chip->card, "SB16-CSP", device, &hw)) < 0)
 		return err;
 
-	if ((p = snd_magic_kcalloc(snd_sb_csp_t, 0, GFP_KERNEL)) == NULL) {
+	if ((p = kcalloc(1, sizeof(*p), GFP_KERNEL)) == NULL) {
 		snd_device_free(chip->card, hw);
 		return -ENOMEM;
 	}
@@ -165,11 +162,11 @@
  */
 static void snd_sb_csp_free(snd_hwdep_t *hwdep)
 {
-	snd_sb_csp_t *p = snd_magic_cast(snd_sb_csp_t, hwdep->private_data, return);
+	snd_sb_csp_t *p = hwdep->private_data;
 	if (p) {
 		if (p->running & SNDRV_SB_CSP_ST_RUNNING)
 			snd_sb_csp_stop(p);
-		snd_magic_kfree(p);
+		kfree(p);
 	}
 }
 
@@ -180,7 +177,7 @@
  */
 static int snd_sb_csp_open(snd_hwdep_t * hw, struct file *file)
 {
-	snd_sb_csp_t *p = snd_magic_cast(snd_sb_csp_t, hw->private_data, return -ENXIO);
+	snd_sb_csp_t *p = hw->private_data;
 	return (snd_sb_csp_use(p));
 }
 
@@ -189,7 +186,7 @@
  */
 static int snd_sb_csp_ioctl(snd_hwdep_t * hw, struct file *file, unsigned int cmd, unsigned long arg)
 {
-	snd_sb_csp_t *p = snd_magic_cast(snd_sb_csp_t, hw->private_data, return -ENXIO);
+	snd_sb_csp_t *p = hw->private_data;
 	snd_sb_csp_info_t info;
 	snd_sb_csp_start_t start_info;
 	int err;
@@ -258,7 +255,7 @@
  */
 static int snd_sb_csp_release(snd_hwdep_t * hw, struct file *file)
 {
-	snd_sb_csp_t *p = snd_magic_cast(snd_sb_csp_t, hw->private_data, return -ENXIO);
+	snd_sb_csp_t *p = hw->private_data;
 	return (snd_sb_csp_unuse(p));
 }
 
@@ -1110,7 +1107,7 @@
 
 static void info_read(snd_info_entry_t *entry, snd_info_buffer_t * buffer)
 {
-	snd_sb_csp_t *p = snd_magic_cast(snd_sb_csp_t, entry->private_data, return);
+	snd_sb_csp_t *p = entry->private_data;
 
 	snd_iprintf(buffer, "Creative Signal Processor [v%d.%d]\n", (p->version >> 4), (p->version & 0x0f));
 	snd_iprintf(buffer, "State: %cx%c%c%c\n", ((p->running & SNDRV_SB_CSP_ST_QSOUND) ? 'Q' : '-'),
diff -Nru a/sound/isa/sb/sb16_main.c b/sound/isa/sb/sb16_main.c
--- a/sound/isa/sb/sb16_main.c	2004-10-18 14:56:29 -07:00
+++ b/sound/isa/sb/sb16_main.c	2004-10-18 14:56:29 -07:00
@@ -49,13 +49,11 @@
 MODULE_DESCRIPTION("Routines for control of 16-bit SoundBlaster cards and clones");
 MODULE_LICENSE("GPL");
 
-#define chip_t sb_t
-
 #ifdef CONFIG_SND_SB16_CSP
 static void snd_sb16_csp_playback_prepare(sb_t *chip, snd_pcm_runtime_t *runtime)
 {
 	if (chip->hardware == SB_HW_16CSP) {
-		snd_sb_csp_t *csp = snd_magic_cast(snd_sb_csp_t, chip->csp, return);
+		snd_sb_csp_t *csp = chip->csp;
 
 		if (csp->running & SNDRV_SB_CSP_ST_LOADED) {
 			/* manually loaded codec */
@@ -103,7 +101,7 @@
 static void snd_sb16_csp_capture_prepare(sb_t *chip, snd_pcm_runtime_t *runtime)
 {
 	if (chip->hardware == SB_HW_16CSP) {
-		snd_sb_csp_t *csp = snd_magic_cast(snd_sb_csp_t, chip->csp, return);
+		snd_sb_csp_t *csp = chip->csp;
 
 		if (csp->running & SNDRV_SB_CSP_ST_LOADED) {
 			/* manually loaded codec */
@@ -141,7 +139,7 @@
 static void snd_sb16_csp_update(sb_t *chip)
 {
 	if (chip->hardware == SB_HW_16CSP) {
-		snd_sb_csp_t *csp = snd_magic_cast(snd_sb_csp_t, chip->csp, return);
+		snd_sb_csp_t *csp = chip->csp;
 
 		if (csp->qpos_changed) {
 			spin_lock(&chip->reg_lock);
@@ -155,7 +153,7 @@
 {
 	/* CSP decoders (QSound excluded) support only 16bit transfers */
 	if (chip->hardware == SB_HW_16CSP) {
-		snd_sb_csp_t *csp = snd_magic_cast(snd_sb_csp_t, chip->csp, return);
+		snd_sb_csp_t *csp = chip->csp;
 
 		if (csp->running & SNDRV_SB_CSP_ST_LOADED) {
 			/* manually loaded codec */
@@ -173,7 +171,7 @@
 static void snd_sb16_csp_playback_close(sb_t *chip)
 {
 	if ((chip->hardware == SB_HW_16CSP) && (chip->open == SNDRV_SB_CSP_MODE_DSP_WRITE)) {
-		snd_sb_csp_t *csp = snd_magic_cast(snd_sb_csp_t, chip->csp, return);
+		snd_sb_csp_t *csp = chip->csp;
 
 		if (csp->ops.csp_stop(csp) == 0) {
 			csp->ops.csp_unuse(csp);
@@ -186,7 +184,7 @@
 {
 	/* CSP coders support only 16bit transfers */
 	if (chip->hardware == SB_HW_16CSP) {
-		snd_sb_csp_t *csp = snd_magic_cast(snd_sb_csp_t, chip->csp, return);
+		snd_sb_csp_t *csp = chip->csp;
 
 		if (csp->running & SNDRV_SB_CSP_ST_LOADED) {
 			/* manually loaded codec */
@@ -204,7 +202,7 @@
 static void snd_sb16_csp_capture_close(sb_t *chip)
 {
 	if ((chip->hardware == SB_HW_16CSP) && (chip->open == SNDRV_SB_CSP_MODE_DSP_READ)) {
-		snd_sb_csp_t *csp = snd_magic_cast(snd_sb_csp_t, chip->csp, return);
+		snd_sb_csp_t *csp = chip->csp;
 
 		if (csp->ops.csp_stop(csp) == 0) {
 			csp->ops.csp_unuse(csp);
@@ -395,7 +393,7 @@
 
 irqreturn_t snd_sb16dsp_interrupt(int irq, void *dev_id, struct pt_regs *regs)
 {
-	sb_t *chip = snd_magic_cast(sb_t, dev_id, return IRQ_NONE);
+	sb_t *chip = dev_id;
 	unsigned char status;
 	int ok;
 
diff -Nru a/sound/isa/sb/sb8.c b/sound/isa/sb/sb8.c
--- a/sound/isa/sb/sb8.c	2004-10-18 14:56:33 -07:00
+++ b/sound/isa/sb/sb8.c	2004-10-18 14:56:33 -07:00
@@ -30,13 +30,10 @@
 #define SNDRV_LEGACY_AUTO_PROBE
 #include <sound/initval.h>
 
-#define chip_t sb_t
-
 MODULE_AUTHOR("Jaroslav Kysela <perex@suse.cz>");
 MODULE_DESCRIPTION("Sound Blaster 1.0/2.0/Pro");
 MODULE_LICENSE("GPL");
-MODULE_CLASSES("{sound}");
-MODULE_DEVICES("{{Creative Labs,SB 1.0/SB 2.0/SB Pro}}");
+MODULE_SUPPORTED_DEVICE("{{Creative Labs,SB 1.0/SB 2.0/SB Pro}}");
 
 static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX;	/* Index 0-MAX */
 static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR;	/* ID for this card */
@@ -48,22 +45,16 @@
 
 module_param_array(index, int, boot_devs, 0444);
 MODULE_PARM_DESC(index, "Index value for Sound Blaster soundcard.");
-MODULE_PARM_SYNTAX(index, SNDRV_INDEX_DESC);
 module_param_array(id, charp, boot_devs, 0444);
 MODULE_PARM_DESC(id, "ID string for Sound Blaster soundcard.");
-MODULE_PARM_SYNTAX(id, SNDRV_ID_DESC);
 module_param_array(enable, bool, boot_devs, 0444);
 MODULE_PARM_DESC(enable, "Enable Sound Blaster soundcard.");
-MODULE_PARM_SYNTAX(enable, SNDRV_ENABLE_DESC);
 module_param_array(port, long, boot_devs, 0444);
 MODULE_PARM_DESC(port, "Port # for SB8 driver.");
-MODULE_PARM_SYNTAX(port, SNDRV_PORT12_DESC);
 module_param_array(irq, int, boot_devs, 0444);
 MODULE_PARM_DESC(irq, "IRQ # for SB8 driver.");
-MODULE_PARM_SYNTAX(irq, SNDRV_IRQ_DESC);
 module_param_array(dma8, int, boot_devs, 0444);
 MODULE_PARM_DESC(dma8, "8-bit DMA # for SB8 driver.");
-MODULE_PARM_SYNTAX(dma8, SNDRV_DMA8_DESC);
 
 struct snd_sb8 {
 	struct resource *fm_res;	/* used to block FM i/o region for legacy cards */
@@ -73,7 +64,7 @@
 
 static irqreturn_t snd_sb8_interrupt(int irq, void *dev_id, struct pt_regs *regs)
 {
-	sb_t *chip = snd_magic_cast(sb_t, dev_id, return IRQ_NONE);
+	sb_t *chip = dev_id;
 
 	if (chip->open & SB_OPEN_PCM) {
 		return snd_sb8dsp_interrupt(chip);
diff -Nru a/sound/isa/sb/sb8_main.c b/sound/isa/sb/sb8_main.c
--- a/sound/isa/sb/sb8_main.c	2004-10-18 14:56:29 -07:00
+++ b/sound/isa/sb/sb8_main.c	2004-10-18 14:56:29 -07:00
@@ -42,8 +42,6 @@
 MODULE_DESCRIPTION("Routines for control of 8-bit SoundBlaster cards and clones");
 MODULE_LICENSE("GPL");
 
-#define chip_t sb_t
-
 #define SB8_CLOCK	1000000
 #define SB8_DEN(v)	((SB8_CLOCK + (v) / 2) / (v))
 #define SB8_RATE(v)	(SB8_CLOCK / SB8_DEN(v))
diff -Nru a/sound/isa/sb/sb8_midi.c b/sound/isa/sb/sb8_midi.c
--- a/sound/isa/sb/sb8_midi.c	2004-10-18 14:55:54 -07:00
+++ b/sound/isa/sb/sb8_midi.c	2004-10-18 14:55:54 -07:00
@@ -73,7 +73,7 @@
 	sb_t *chip;
 	unsigned int valid_open_flags;
 
-	chip = snd_magic_cast(sb_t, substream->rmidi->private_data, return -ENXIO);
+	chip = substream->rmidi->private_data;
 	valid_open_flags = chip->hardware >= SB_HW_20
 		? SB_OPEN_MIDI_OUTPUT | SB_OPEN_MIDI_OUTPUT_TRIGGER : 0;
 	spin_lock_irqsave(&chip->open_lock, flags);
@@ -100,7 +100,7 @@
 	sb_t *chip;
 	unsigned int valid_open_flags;
 
-	chip = snd_magic_cast(sb_t, substream->rmidi->private_data, return -ENXIO);
+	chip = substream->rmidi->private_data;
 	valid_open_flags = chip->hardware >= SB_HW_20
 		? SB_OPEN_MIDI_INPUT | SB_OPEN_MIDI_INPUT_TRIGGER : 0;
 	spin_lock_irqsave(&chip->open_lock, flags);
@@ -126,7 +126,7 @@
 	unsigned long flags;
 	sb_t *chip;
 
-	chip = snd_magic_cast(sb_t, substream->rmidi->private_data, return -ENXIO);
+	chip = substream->rmidi->private_data;
 	spin_lock_irqsave(&chip->open_lock, flags);
 	chip->open &= ~(SB_OPEN_MIDI_INPUT | SB_OPEN_MIDI_INPUT_TRIGGER);
 	chip->midi_substream_input = NULL;
@@ -144,7 +144,7 @@
 	unsigned long flags;
 	sb_t *chip;
 
-	chip = snd_magic_cast(sb_t, substream->rmidi->private_data, return -ENXIO);
+	chip = substream->rmidi->private_data;
 	spin_lock_irqsave(&chip->open_lock, flags);
 	chip->open &= ~(SB_OPEN_MIDI_OUTPUT | SB_OPEN_MIDI_OUTPUT_TRIGGER);
 	chip->midi_substream_output = NULL;
@@ -162,7 +162,7 @@
 	unsigned long flags;
 	sb_t *chip;
 
-	chip = snd_magic_cast(sb_t, substream->rmidi->private_data, return);
+	chip = substream->rmidi->private_data;
 	spin_lock_irqsave(&chip->open_lock, flags);
 	if (up) {
 		if (!(chip->open & SB_OPEN_MIDI_INPUT_TRIGGER)) {
@@ -188,7 +188,7 @@
 	int max = 32;
 
 	/* how big is Tx FIFO? */
-	chip = snd_magic_cast(sb_t, substream->rmidi->private_data, return);
+	chip = substream->rmidi->private_data;
 	while (max-- > 0) {
 		spin_lock_irqsave(&chip->open_lock, flags);
 		if (snd_rawmidi_transmit_peek(substream, &byte, 1) != 1) {
@@ -219,7 +219,7 @@
 static void snd_sb8dsp_midi_output_timer(unsigned long data)
 {
 	snd_rawmidi_substream_t * substream = (snd_rawmidi_substream_t *) data;
-	sb_t * chip = snd_magic_cast(sb_t, substream->rmidi->private_data, return);
+	sb_t * chip = substream->rmidi->private_data;
 	unsigned long flags;
 
 	spin_lock_irqsave(&chip->open_lock, flags);
@@ -234,7 +234,7 @@
 	unsigned long flags;
 	sb_t *chip;
 
-	chip = snd_magic_cast(sb_t, substream->rmidi->private_data, return);
+	chip = substream->rmidi->private_data;
 	spin_lock_irqsave(&chip->open_lock, flags);
 	if (up) {
 		if (!(chip->open & SB_OPEN_MIDI_OUTPUT_TRIGGER)) {
diff -Nru a/sound/isa/sb/sb_common.c b/sound/isa/sb/sb_common.c
--- a/sound/isa/sb/sb_common.c	2004-10-18 14:57:04 -07:00
+++ b/sound/isa/sb/sb_common.c	2004-10-18 14:57:04 -07:00
@@ -33,12 +33,9 @@
 #include <asm/io.h>
 #include <asm/dma.h>
 
-#define chip_t sb_t
-
 MODULE_AUTHOR("Jaroslav Kysela <perex@suse.cz>");
 MODULE_DESCRIPTION("ALSA lowlevel driver for Sound Blaster cards");
 MODULE_LICENSE("GPL");
-MODULE_CLASSES("{sound}");
 
 #define BUSY_LOOPS 100000
 
@@ -197,13 +194,13 @@
 		free_dma(chip->dma16);
 	}
 #endif
-	snd_magic_kfree(chip);
+	kfree(chip);
 	return 0;
 }
 
 static int snd_sbdsp_dev_free(snd_device_t *device)
 {
-	sb_t *chip = snd_magic_cast(sb_t, device->device_data, return -ENXIO);
+	sb_t *chip = device->device_data;
 	return snd_sbdsp_free(chip);
 }
 
@@ -224,7 +221,7 @@
 
 	snd_assert(r_chip != NULL, return -EINVAL);
 	*r_chip = NULL;
-	chip = snd_magic_kcalloc(sb_t, 0, GFP_KERNEL);
+	chip = kcalloc(1, sizeof(*chip), GFP_KERNEL);
 	if (chip == NULL)
 		return -ENOMEM;
 	spin_lock_init(&chip->reg_lock);
diff -Nru a/sound/isa/sb/sb_mixer.c b/sound/isa/sb/sb_mixer.c
--- a/sound/isa/sb/sb_mixer.c	2004-10-18 14:56:29 -07:00
+++ b/sound/isa/sb/sb_mixer.c	2004-10-18 14:56:29 -07:00
@@ -27,8 +27,6 @@
 #include <sound/sb.h>
 #include <sound/control.h>
 
-#define chip_t sb_t
-
 #undef IO_DEBUG
 
 void snd_sbmixer_write(sb_t *chip, unsigned char reg, unsigned char data)
diff -Nru a/sound/isa/sgalaxy.c b/sound/isa/sgalaxy.c
--- a/sound/isa/sgalaxy.c	2004-10-18 14:57:19 -07:00
+++ b/sound/isa/sgalaxy.c	2004-10-18 14:57:19 -07:00
@@ -39,8 +39,7 @@
 MODULE_AUTHOR("Christopher Butler <chrisb@sandy.force9.co.uk>");
 MODULE_DESCRIPTION("Aztech Sound Galaxy");
 MODULE_LICENSE("GPL");
-MODULE_CLASSES("{sound}");
-MODULE_DEVICES("{{Aztech Systems,Sound Galaxy}}");
+MODULE_SUPPORTED_DEVICE("{{Aztech Systems,Sound Galaxy}}");
 
 static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX;	/* Index 0-MAX */
 static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR;	/* ID for this card */
@@ -53,22 +52,16 @@
 
 module_param_array(index, int, boot_devs, 0444);
 MODULE_PARM_DESC(index, "Index value for Sound Galaxy soundcard.");
-MODULE_PARM_SYNTAX(index, SNDRV_INDEX_DESC);
 module_param_array(id, charp, boot_devs, 0444);
 MODULE_PARM_DESC(id, "ID string for Sound Galaxy soundcard.");
-MODULE_PARM_SYNTAX(id, SNDRV_ID_DESC);
 module_param_array(sbport, long, boot_devs, 0444);
 MODULE_PARM_DESC(sbport, "Port # for Sound Galaxy SB driver.");
-MODULE_PARM_SYNTAX(sbport, SNDRV_ENABLED ",allows:{{0x220},{0x240}},dialog:list");
 module_param_array(wssport, long, boot_devs, 0444);
 MODULE_PARM_DESC(wssport, "Port # for Sound Galaxy WSS driver.");
-MODULE_PARM_SYNTAX(wssport, SNDRV_ENABLED ",allows:{{0x530},{0xe80},{0xf40},{0x604}},dialog:list");
 module_param_array(irq, int, boot_devs, 0444);
 MODULE_PARM_DESC(irq, "IRQ # for Sound Galaxy driver.");
-MODULE_PARM_SYNTAX(irq, SNDRV_ENABLED ",allows:{{7},{9},{10},{11}},dialog:list");
 module_param_array(dma1, int, boot_devs, 0444);
 MODULE_PARM_DESC(dma1, "DMA1 # for Sound Galaxy driver.");
-MODULE_PARM_SYNTAX(dma1, SNDRV_DMA8_DESC);
 
 #define SGALAXY_AUXC_LEFT 18
 #define SGALAXY_AUXC_RIGHT 19
diff -Nru a/sound/isa/sscape.c b/sound/isa/sscape.c
--- a/sound/isa/sscape.c	2004-10-18 14:55:55 -07:00
+++ b/sound/isa/sscape.c	2004-10-18 14:55:55 -07:00
@@ -36,8 +36,6 @@
 
 #include <sound/sscape_ioctl.h>
 
-#define chip_t cs4231_t
-
 
 MODULE_AUTHOR("Chris Rankin");
 MODULE_DESCRIPTION("ENSONIQ SoundScape PnP driver");
@@ -53,27 +51,21 @@
 
 module_param_array(index, int, boot_devs, 0444);
 MODULE_PARM_DESC(index, "Index number for SoundScape soundcard");
-MODULE_PARM_SYNTAX(index, SNDRV_INDEX_DESC);
 
 module_param_array(id, charp, boot_devs, 0444);
 MODULE_PARM_DESC(id, "Description for SoundScape card");
-MODULE_PARM_SYNTAX(id, SNDRV_ID_DESC);
 
 module_param_array(port, long, boot_devs, 0444);
 MODULE_PARM_DESC(port, "Port # for SoundScape driver.");
-MODULE_PARM_SYNTAX(port, SNDRV_ENABLED);
 
 module_param_array(irq, int, boot_devs, 0444);
 MODULE_PARM_DESC(irq, "IRQ # for SoundScape driver.");
-MODULE_PARM_SYNTAX(irq, SNDRV_IRQ_DESC);
 
 module_param_array(mpu_irq, int, boot_devs, 0444);
 MODULE_PARM_DESC(mpu_irq, "MPU401 IRQ # for SoundScape driver.");
-MODULE_PARM_SYNTAX(mpu_irq, SNDRV_IRQ_DESC);
 
 module_param_array(dma, int, boot_devs, 0444);
 MODULE_PARM_DESC(dma, "DMA # for SoundScape driver.");
-MODULE_PARM_SYNTAX(dma, SNDRV_DMA8_DESC);
   
 #ifdef CONFIG_PNP
 static struct pnp_card_device_id sscape_pnpids[] = {
@@ -177,11 +169,8 @@
 static struct snd_dma_buffer *get_dmabuf(struct snd_dma_buffer *buf, unsigned long size)
 {
 	if (buf) {
-		struct snd_dma_device dev;
-		memset(&dev, 0, sizeof(dev));
-		dev.type = SNDRV_DMA_TYPE_DEV;
-		dev.dev = snd_dma_isa_data();
-		if (snd_dma_alloc_pages_fallback(&dev, size, buf) < 0) {
+		if (snd_dma_alloc_pages_fallback(SNDRV_DMA_TYPE_DEV, snd_dma_isa_data(),
+						 size, buf) < 0) {
 			snd_printk(KERN_ERR "sscape: Failed to allocate %lu bytes for DMA\n", size);
 			return NULL;
 		}
@@ -195,13 +184,8 @@
  */
 static void free_dmabuf(struct snd_dma_buffer *buf)
 {
-	if (buf && buf->area) {
-		struct snd_dma_device dev;
-		memset(&dev, 0, sizeof(dev));
-		dev.type = SNDRV_DMA_TYPE_DEV;
-		dev.dev = snd_dma_isa_data();
-		snd_dma_free_pages(&dev, buf);
-	}
+	if (buf && buf->area)
+		snd_dma_free_pages(buf);
 }
 
 
diff -Nru a/sound/isa/wavefront/wavefront.c b/sound/isa/wavefront/wavefront.c
--- a/sound/isa/wavefront/wavefront.c	2004-10-18 14:56:49 -07:00
+++ b/sound/isa/wavefront/wavefront.c	2004-10-18 14:56:49 -07:00
@@ -30,13 +30,10 @@
 #include <sound/opl3.h>
 #include <sound/snd_wavefront.h>
 
-#define chip_t cs4231_t
-
 MODULE_AUTHOR("Paul Barton-Davis <pbd@op.net>");
 MODULE_DESCRIPTION("Turtle Beach Wavefront");
 MODULE_LICENSE("GPL");
-MODULE_CLASSES("{sound}");
-MODULE_DEVICES("{{Turtle Beach,Maui/Tropez/Tropez+}}");
+MODULE_SUPPORTED_DEVICE("{{Turtle Beach,Maui/Tropez/Tropez+}}");
 
 static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX;	    /* Index 0-MAX */
 static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR;	    /* ID for this card */
@@ -56,48 +53,34 @@
 
 module_param_array(index, int, boot_devs, 0444);
 MODULE_PARM_DESC(index, "Index value for WaveFront soundcard.");
-MODULE_PARM_SYNTAX(index, SNDRV_INDEX_DESC);
 module_param_array(id, charp, boot_devs, 0444);
 MODULE_PARM_DESC(id, "ID string for WaveFront soundcard.");
-MODULE_PARM_SYNTAX(id, SNDRV_ID_DESC);
 module_param_array(enable, bool, boot_devs, 0444);
 MODULE_PARM_DESC(enable, "Enable WaveFront soundcard.");
-MODULE_PARM_SYNTAX(enable, SNDRV_ENABLE_DESC);
 #ifdef CONFIG_PNP
 module_param_array(isapnp, bool, boot_devs, 0444);
 MODULE_PARM_DESC(isapnp, "ISA PnP detection for WaveFront soundcards.");
-MODULE_PARM_SYNTAX(isapnp, SNDRV_ISAPNP_DESC);
 #endif
 module_param_array(cs4232_pcm_port, long, boot_devs, 0444);
 MODULE_PARM_DESC(cs4232_pcm_port, "Port # for CS4232 PCM interface.");
-MODULE_PARM_SYNTAX(cs4232_pcm_port, SNDRV_PORT12_DESC);
 module_param_array(cs4232_pcm_irq, int, boot_devs, 0444);
 MODULE_PARM_DESC(cs4232_pcm_irq, "IRQ # for CS4232 PCM interface.");
-MODULE_PARM_SYNTAX(cs4232_pcm_irq, SNDRV_ENABLED ",allows:{{5},{7},{9},{11},{12},{15}},dialog:list");
 module_param_array(dma1, int, boot_devs, 0444);
 MODULE_PARM_DESC(dma1, "DMA1 # for CS4232 PCM interface.");
-MODULE_PARM_SYNTAX(dma1, SNDRV_DMA_DESC);
 module_param_array(dma2, int, boot_devs, 0444);
 MODULE_PARM_DESC(dma2, "DMA2 # for CS4232 PCM interface.");
-MODULE_PARM_SYNTAX(dma2, SNDRV_DMA_DESC);
 module_param_array(cs4232_mpu_port, long, boot_devs, 0444);
 MODULE_PARM_DESC(cs4232_mpu_port, "port # for CS4232 MPU-401 interface.");
-MODULE_PARM_SYNTAX(cs4232_mpu_port, SNDRV_PORT12_DESC);
 module_param_array(cs4232_mpu_irq, int, boot_devs, 0444);
 MODULE_PARM_DESC(cs4232_mpu_irq, "IRQ # for CS4232 MPU-401 interface.");
-MODULE_PARM_SYNTAX(cs4232_mpu_irq, SNDRV_ENABLED ",allows:{{9},{11},{12},{15}},dialog:list");
 module_param_array(ics2115_irq, int, boot_devs, 0444);
 MODULE_PARM_DESC(ics2115_irq, "IRQ # for ICS2115.");
-MODULE_PARM_SYNTAX(ics2115_irq, SNDRV_ENABLED ",allows:{{9},{11},{12},{15}},dialog:list");
 module_param_array(ics2115_port, long, boot_devs, 0444);
 MODULE_PARM_DESC(ics2115_port, "Port # for ICS2115.");
-MODULE_PARM_SYNTAX(ics2115_port, SNDRV_PORT12_DESC);
 module_param_array(fm_port, long, boot_devs, 0444);
 MODULE_PARM_DESC(fm_port, "FM port #.");
-MODULE_PARM_SYNTAX(fm_port, SNDRV_PORT12_DESC);
 module_param_array(use_cs4232_midi, bool, boot_devs, 0444);
 MODULE_PARM_DESC(use_cs4232_midi, "Use CS4232 MPU-401 interface (inaccessibly located inside your computer)");
-MODULE_PARM_SYNTAX(use_cs4232_midi, SNDRV_ENABLED "," SNDRV_BOOLEAN_FALSE_DESC);
 
 static snd_card_t *snd_wavefront_legacy[SNDRV_CARDS] = SNDRV_DEFAULT_PTR;
 
diff -Nru a/sound/isa/wavefront/wavefront_fx.c b/sound/isa/wavefront/wavefront_fx.c
--- a/sound/isa/wavefront/wavefront_fx.c	2004-10-18 14:56:33 -07:00
+++ b/sound/isa/wavefront/wavefront_fx.c	2004-10-18 14:56:33 -07:00
@@ -34,7 +34,7 @@
 
 /* weird stuff, derived from port I/O tracing with dosemu */
 
-static unsigned char page_zero[] __initdata = {
+unsigned char page_zero[] __initdata = {
 0x01, 0x7c, 0x00, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf5, 0x00,
 0x11, 0x00, 0x20, 0x00, 0x32, 0x00, 0x40, 0x00, 0x13, 0x00, 0x00,
 0x00, 0x14, 0x02, 0x76, 0x00, 0x60, 0x00, 0x80, 0x02, 0x00, 0x00,
@@ -61,7 +61,7 @@
 0x1d, 0x02, 0xdf
 };
 
-static unsigned char page_one[] __initdata = {
+unsigned char page_one[] __initdata = {
 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x19, 0x00,
 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xd8, 0x00, 0x00,
 0x02, 0x20, 0x00, 0x19, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x01,
@@ -88,7 +88,7 @@
 0x60, 0x00, 0x1b
 };
 
-static unsigned char page_two[] __initdata = {
+unsigned char page_two[] __initdata = {
 0xc4, 0x00, 0x44, 0x07, 0x44, 0x00, 0x40, 0x25, 0x01, 0x06, 0xc4,
 0x07, 0x40, 0x25, 0x01, 0x00, 0x46, 0x46, 0x00, 0x00, 0x00, 0x00,
 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
@@ -103,7 +103,7 @@
 0x46, 0x05, 0x46, 0x07, 0x46, 0x07, 0x44
 };
 
-static unsigned char page_three[] __initdata = {
+unsigned char page_three[] __initdata = {
 0x07, 0x40, 0x00, 0x00, 0x00, 0x47, 0x00, 0x40, 0x00, 0x40, 0x06,
 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
@@ -118,7 +118,7 @@
 0x02, 0x00, 0x42, 0x00, 0xc0, 0x00, 0x40
 };
 
-static unsigned char page_four[] __initdata = {
+unsigned char page_four[] __initdata = {
 0x63, 0x03, 0x26, 0x02, 0x2c, 0x00, 0x24, 0x00, 0x2e, 0x02, 0x02,
 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
@@ -133,7 +133,7 @@
 0x02, 0x62, 0x02, 0x20, 0x01, 0x21, 0x01
 };
 
-static unsigned char page_six[] __initdata = {
+unsigned char page_six[] __initdata = {
 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x04, 0x00, 0x00, 0x06, 0x00,
 0x00, 0x08, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x0e,
 0x00, 0x00, 0x10, 0x00, 0x00, 0x12, 0x00, 0x00, 0x14, 0x00, 0x00,
@@ -154,7 +154,7 @@
 0x80, 0x00, 0x7e, 0x80, 0x80
 };
 
-static unsigned char page_seven[] __initdata = {
+unsigned char page_seven[] __initdata = {
 0x0f, 0xff, 0x00, 0x00, 0x08, 0x00, 0x08, 0x00, 0x02, 0x00, 0x00,
 0x00, 0x00, 0x00, 0x0f, 0xff, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00,
 0x08, 0x00, 0x00, 0x00, 0x0f, 0xff, 0x00, 0x00, 0x00, 0x00, 0x0f,
@@ -181,7 +181,7 @@
 0x00, 0x02, 0x00
 };
 
-static unsigned char page_zero_v2[] __initdata = {
+unsigned char page_zero_v2[] __initdata = {
 0x00, 0x00, 0x00, 0x00, 0x02, 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,
@@ -193,7 +193,7 @@
 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
 };
 
-static unsigned char page_one_v2[] __initdata = {
+unsigned char page_one_v2[] __initdata = {
 0x01, 0xc0, 0x01, 0xfa, 0x00, 0x1a, 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,
@@ -205,21 +205,21 @@
 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
 };
 
-static unsigned char page_two_v2[] __initdata = {
+unsigned char page_two_v2[] __initdata = {
 0x46, 0x46, 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,
 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 0x00, 0x00, 0x00, 0x00
 };
-static unsigned char page_three_v2[] __initdata = {
+unsigned char page_three_v2[] __initdata = {
 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, 0x00, 0x00,
 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 0x00, 0x00, 0x00, 0x00
 };
-static unsigned char page_four_v2[] __initdata = {
+unsigned char page_four_v2[] __initdata = {
 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, 0x00, 0x00,
@@ -227,7 +227,7 @@
 0x00, 0x00, 0x00, 0x00
 };
 
-static unsigned char page_seven_v2[] __initdata = {
+unsigned char page_seven_v2[] __initdata = {
 0x0f, 0xff, 0x0f, 0xff, 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,
@@ -239,7 +239,7 @@
 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
 };
 
-static unsigned char mod_v2[] __initdata = {
+unsigned char mod_v2[] __initdata = {
 0x01, 0x00, 0x02, 0x00, 0x01, 0x01, 0x02, 0x00, 0x01, 0x02, 0x02,
 0x00, 0x01, 0x03, 0x02, 0x00, 0x01, 0x04, 0x02, 0x00, 0x01, 0x05,
 0x02, 0x00, 0x01, 0x06, 0x02, 0x00, 0x01, 0x07, 0x02, 0x00, 0xb0,
@@ -269,7 +269,7 @@
 0x02, 0x01, 0x01, 0x04, 0x02, 0x01, 0x01, 0x05, 0x02, 0x01, 0x01,
 0x06, 0x02, 0x01, 0x01, 0x07, 0x02, 0x01
 };
-static unsigned char coefficients[] __initdata = {
+unsigned char coefficients[] __initdata = {
 0x07, 0x46, 0x00, 0x00, 0x07, 0x49, 0x00, 0x00, 0x00, 0x4b, 0x03,
 0x11, 0x00, 0x4d, 0x01, 0x32, 0x07, 0x46, 0x00, 0x00, 0x07, 0x49,
 0x00, 0x00, 0x07, 0x40, 0x00, 0x00, 0x07, 0x41, 0x00, 0x00, 0x01,
@@ -305,14 +305,14 @@
 0x06, 0x6c, 0x4c, 0x6c, 0x06, 0x50, 0x52, 0xe2, 0x06, 0x42, 0x02,
 0xba
 };
-static unsigned char coefficients2[] __initdata = {
+unsigned char coefficients2[] __initdata = {
 0x07, 0x46, 0x00, 0x00, 0x07, 0x49, 0x00, 0x00, 0x07, 0x45, 0x0f,
 0xff, 0x07, 0x48, 0x0f, 0xff, 0x07, 0x7b, 0x04, 0xcc, 0x07, 0x7d,
 0x04, 0xcc, 0x07, 0x7c, 0x00, 0x00, 0x07, 0x7e, 0x00, 0x00, 0x07,
 0x46, 0x00, 0x00, 0x07, 0x49, 0x00, 0x00, 0x07, 0x47, 0x00, 0x00,
 0x07, 0x4a, 0x00, 0x00, 0x07, 0x4c, 0x00, 0x00, 0x07, 0x4e, 0x00, 0x00
 };
-static unsigned char coefficients3[] __initdata = {
+unsigned char coefficients3[] __initdata = {
 0x00, 0x00, 0x00, 0x00, 0x00, 0x28, 0x00, 0x28, 0x00, 0x51, 0x00,
 0x51, 0x00, 0x7a, 0x00, 0x7a, 0x00, 0xa3, 0x00, 0xa3, 0x00, 0xcc,
 0x00, 0xcc, 0x00, 0xf5, 0x00, 0xf5, 0x01, 0x1e, 0x01, 0x1e, 0x01,
@@ -486,8 +486,9 @@
 	snd_wavefront_card_t *acard;
 	snd_wavefront_t *dev;
 	wavefront_fx_info r;
-	unsigned short page_data[256];
+	unsigned short *page_data = NULL;
 	unsigned short *pd;
+	int err = 0;
 
 	snd_assert(sdev->card != NULL, return -ENODEV);
 	
@@ -514,23 +515,30 @@
 		} else if (r.data[2] == 1) {
 			pd = (unsigned short *) &r.data[3];
 		} else {
-			if (r.data[2] > (long)sizeof (page_data)) {
+			if (r.data[2] > 256) {
 				snd_printk ("cannot write "
-					    "> 255 bytes to FX\n");
+					    "> 512 bytes to FX\n");
 				return -EIO;
 			}
+			page_data = kmalloc(r.data[2] * sizeof(short), GFP_KERNEL);
+			if (!page_data)
+				return -ENOMEM;
 			if (copy_from_user (page_data,
 					    (unsigned char __user *) r.data[3],
-					    r.data[2]))
+					    r.data[2] * sizeof(short))) {
+				kfree(page_data);
 				return -EFAULT;
+			}
 			pd = page_data;
 		}
 
-		wavefront_fx_memset (dev,
+		err = wavefront_fx_memset (dev,
 			     r.data[0], /* page */
 			     r.data[1], /* addr */
 			     r.data[2], /* cnt */
 			     pd);
+		if (page_data)
+			kfree(page_data);
 		break;
 
 	default:
@@ -538,7 +546,7 @@
 			    r.request);
 		return -ENOTTY;
 	}
-	return 0;
+	return err;
 }
 
 /* YSS225 initialization.
diff -Nru a/sound/isa/wavefront/wavefront_synth.c b/sound/isa/wavefront/wavefront_synth.c
--- a/sound/isa/wavefront/wavefront_synth.c	2004-10-18 14:56:28 -07:00
+++ b/sound/isa/wavefront/wavefront_synth.c	2004-10-18 14:56:28 -07:00
@@ -1961,6 +1961,12 @@
 			break;
 		}
 
+		if (section_length < 0 || section_length > WF_SECTION_MAX) {
+			snd_printk ("invalid firmware section length %d\n",
+				    section_length);
+			goto failure;
+		}
+
 		if (sys_read (fd, section, section_length) != section_length) {
 			snd_printk ("firmware section "
 				"read error.\n");
diff -Nru a/sound/oss/Kconfig b/sound/oss/Kconfig
--- a/sound/oss/Kconfig	2004-10-18 14:56:49 -07:00
+++ b/sound/oss/Kconfig	2004-10-18 14:56:49 -07:00
@@ -127,8 +127,8 @@
 	  <file:Documentation/sound/oss/es1371>.
 
 config SOUND_ESSSOLO1
-	tristate "ESS Technology Solo1"
-	depends on SOUND_PRIME!=n && SOUND && SOUND_GAMEPORT
+	tristate "ESS Technology Solo1" 
+	depends on SOUND_PRIME!=n && SOUND && SOUND_GAMEPORT && PCI
 	help
 	  Say Y or M if you have a PCI sound card utilizing the ESS Technology
 	  Solo1 chip. To find out if your sound card uses a
@@ -139,7 +139,7 @@
 
 config SOUND_MAESTRO
 	tristate "ESS Maestro, Maestro2, Maestro2E driver"
-	depends on SOUND_PRIME!=n && SOUND
+	depends on SOUND_PRIME!=n && SOUND && PCI
 	help
 	  Say Y or M if you have a sound system driven by ESS's Maestro line
 	  of PCI sound chips.  These include the Maestro 1, Maestro 2, and
@@ -162,7 +162,10 @@
 
 config SOUND_HARMONY
 	tristate "PA Harmony audio driver"
-	depends on GSC_LASI && SOUND
+	depends on GSC_LASI && SOUND_PRIME!=n
+	help
+	  Say 'Y' or 'M' to include support for Harmony soundchip
+	  on HP 712, 715/new and many other GSC based machines.
 
 config SOUND_SONICVIBES
 	tristate "S3 SonicVibes"
diff -Nru a/sound/oss/Makefile b/sound/oss/Makefile
--- a/sound/oss/Makefile	2004-10-18 14:56:27 -07:00
+++ b/sound/oss/Makefile	2004-10-18 14:56:27 -07:00
@@ -103,7 +103,7 @@
 vidc_mod-objs	:= vidc.o vidc_fill.o
 wavefront-objs  := wavfront.o wf_midi.o yss225.o
 
-host-progs	:= bin2hex hex2hex
+hostprogs-y	:= bin2hex hex2hex
 
 # Files generated that shall be removed upon make clean
 clean-files := maui_boot.h msndperm.c msndinit.c pndsperm.c pndspini.c \
diff -Nru a/sound/oss/ad1848.c b/sound/oss/ad1848.c
--- a/sound/oss/ad1848.c	2004-10-18 14:56:33 -07:00
+++ b/sound/oss/ad1848.c	2004-10-18 14:56:33 -07:00
@@ -1538,7 +1538,7 @@
 	ad1848_mixer_reset(devc);
 }
 
-int ad1848_detect(int io_base, int *ad_flags, int *osp)
+int ad1848_detect(struct resource *ports, int *ad_flags, int *osp)
 {
 	unsigned char tmp;
 	ad1848_info *devc = &adev_info[nr_ad1848_devs];
@@ -1548,6 +1548,7 @@
 	int ad1847_flag = 0;
 	int cs4248_flag = 0;
 	int sscape_flag = 0;
+	int io_base = ports->start;
 
 	int i;
 
@@ -1578,11 +1579,6 @@
 		printk(KERN_ERR "ad1848 - Too many audio devices\n");
 		return 0;
 	}
-	if (check_region(io_base, 4))
-	{
-		printk(KERN_ERR "ad1848.c: Port %x not free.\n", io_base);
-		return 0;
-	}
 	spin_lock_init(&devc->lock);
 	devc->base = io_base;
 	devc->irq_ok = 0;
@@ -1951,7 +1947,7 @@
 	return 1;
 }
 
-int ad1848_init (char *name, int io_base, int irq, int dma_playback,
+int ad1848_init (char *name, struct resource *ports, int irq, int dma_playback,
 		int dma_capture, int share_dma, int *osp, struct module *owner)
 {
 	/*
@@ -1986,8 +1982,7 @@
 		sprintf(dev_name,
 			"Generic audio codec (%s)", devc->chip_name);
 
-	if (!request_region(devc->base, 4, devc->name))
-		return -1;
+	rename_region(ports, devc->name);
 
 	conf_printf2(dev_name, devc->base, devc->irq, dma_playback, dma_capture);
 
@@ -2522,21 +2517,16 @@
 	return 1;
 }
 
-int probe_ms_sound(struct address_info *hw_config)
+int probe_ms_sound(struct address_info *hw_config, struct resource *ports)
 {
 	unsigned char   tmp;
 
 	DDB(printk("Entered probe_ms_sound(%x, %d)\n", hw_config->io_base, hw_config->card_subtype));
 
-	if (check_region(hw_config->io_base, 8))
-	{
-		printk(KERN_ERR "MSS: I/O port conflict\n");
-		return 0;
-	}
 	if (hw_config->card_subtype == 1)	/* Has no IRQ/DMA registers */
 	{
 		/* check_opl3(0x388, hw_config); */
-		return ad1848_detect(hw_config->io_base + 4, NULL, hw_config->osp);
+		return ad1848_detect(ports, NULL, hw_config->osp);
 	}
 
 	if (deskpro_xl && hw_config->card_subtype == 2)	/* Compaq Deskpro XL */
@@ -2562,7 +2552,7 @@
 		  int             ret;
 
 		  DDB(printk("I/O address is inactive (%x)\n", tmp));
-		  if (!(ret = ad1848_detect(hw_config->io_base + 4, NULL, hw_config->osp)))
+		  if (!(ret = ad1848_detect(ports, NULL, hw_config->osp)))
 			  return 0;
 		  return 1;
 	}
@@ -2575,7 +2565,7 @@
 
 		MDB(printk(KERN_ERR "No MSS signature detected on port 0x%x (0x%x)\n", hw_config->io_base, (int) inb(hw_config->io_base + 3)));
 		DDB(printk("Trying to detect codec anyway but IRQ/DMA may not work\n"));
-		if (!(ret = ad1848_detect(hw_config->io_base + 4, NULL, hw_config->osp)))
+		if (!(ret = ad1848_detect(ports, NULL, hw_config->osp)))
 			return 0;
 
 		hw_config->card_subtype = 1;
@@ -2610,10 +2600,10 @@
 		printk(KERN_ERR "MSS: Can't use IRQ%d with a 8 bit card/slot\n", hw_config->irq);
 		return 0;
 	}
-	return ad1848_detect(hw_config->io_base + 4, NULL, hw_config->osp);
+	return ad1848_detect(ports, NULL, hw_config->osp);
 }
 
-void attach_ms_sound(struct address_info *hw_config, struct module *owner)
+void attach_ms_sound(struct address_info *hw_config, struct resource *ports, struct module *owner)
 {
 	static signed char interrupt_bits[12] =
 	{
@@ -2634,13 +2624,12 @@
 
 	if (hw_config->card_subtype == 1)	/* Has no IRQ/DMA registers */
 	{
-		hw_config->slots[0] = ad1848_init("MS Sound System", hw_config->io_base + 4,
+		hw_config->slots[0] = ad1848_init("MS Sound System", ports,
 						    hw_config->irq,
 						    hw_config->dma,
 						    hw_config->dma2, 0, 
 						    hw_config->osp,
 						    owner);
-		request_region(hw_config->io_base, 4, "WSS config");
 		return;
 	}
 	/*
@@ -2651,6 +2640,8 @@
 	if (bits == -1)
 	{
 		printk(KERN_ERR "MSS: Bad IRQ %d\n", hw_config->irq);
+		release_region(ports->start, 4);
+		release_region(ports->start - 4, 4);
 		return;
 	}
 	outb((bits | 0x40), config_port);
@@ -2694,12 +2685,11 @@
 
 	outb((bits | dma_bits[dma] | dma2_bit), config_port);	/* Write IRQ+DMA setup */
 
-	hw_config->slots[0] = ad1848_init("MS Sound System", hw_config->io_base + 4,
+	hw_config->slots[0] = ad1848_init("MS Sound System", ports,
 					  hw_config->irq,
 					  dma, dma2, 0,
 					  hw_config->osp,
 					  THIS_MODULE);
-	request_region(hw_config->io_base, 4, "WSS config");
 }
 
 void unload_ms_sound(struct address_info *hw_config)
@@ -3095,6 +3085,7 @@
 #endif
 
 	if(io != -1) {
+		struct resource *ports;
 	        if( isapnp == 0 )
 	        {
 			if(irq == -1 || dma == -1) {
@@ -3109,9 +3100,22 @@
 			cfg.card_subtype = type;
 	        }
 
-		if(!probe_ms_sound(&cfg))
+		ports = request_region(io + 4, 4, "ad1848");
+
+		if (!ports)
+			return -EBUSY;
+
+		if (!request_region(io, 4, "WSS config")) {
+			release_region(io + 4, 4);
+			return -EBUSY;
+		}
+
+		if (!probe_ms_sound(&cfg, ports)) {
+			release_region(io + 4, 4);
+			release_region(io, 4);
 			return -ENODEV;
-		attach_ms_sound(&cfg, THIS_MODULE);
+		}
+		attach_ms_sound(&cfg, ports, THIS_MODULE);
 		loaded = 1;
 	}
 	return 0;
diff -Nru a/sound/oss/ad1848.h b/sound/oss/ad1848.h
--- a/sound/oss/ad1848.h	2004-10-18 14:55:53 -07:00
+++ b/sound/oss/ad1848.h	2004-10-18 14:55:53 -07:00
@@ -11,15 +11,15 @@
                 ad1848_control(AD1848_MIXER_REROUTE, ((oldctl)<<8)|(newctl))
 		
 
-int ad1848_init(char *name, int io_base, int irq, int dma_playback,
+int ad1848_init(char *name, struct resource *ports, int irq, int dma_playback,
 	int dma_capture, int share_dma, int *osp, struct module *owner);
 void ad1848_unload (int io_base, int irq, int dma_playback, int dma_capture, int share_dma);
 
-int ad1848_detect (int io_base, int *flags, int *osp);
+int ad1848_detect (struct resource *ports, int *flags, int *osp);
 int ad1848_control(int cmd, int arg);
 
 irqreturn_t adintr(int irq, void *dev_id, struct pt_regs * dummy);
-void attach_ms_sound(struct address_info * hw_config, struct module * owner);
+void attach_ms_sound(struct address_info * hw_config, struct resource *ports, struct module * owner);
 
-int probe_ms_sound(struct address_info *hw_config);
+int probe_ms_sound(struct address_info *hw_config, struct resource *ports);
 void unload_ms_sound(struct address_info *hw_info);
diff -Nru a/sound/oss/ad1889.c b/sound/oss/ad1889.c
--- a/sound/oss/ad1889.c	2004-10-18 14:56:28 -07:00
+++ b/sound/oss/ad1889.c	2004-10-18 14:56:28 -07:00
@@ -1,5 +1,5 @@
 /*
- *  Copyright 2001 Randolph Chung <tausq@debian.org>
+ *  Copyright 2001-2004 Randolph Chung <tausq@debian.org>
  *
  *  Analog Devices 1889 PCI audio driver (AD1819 AC97-compatible codec)
  *
@@ -61,6 +61,7 @@
 #define AD1889_WRITEL(dev,reg,val) writel((val), dev->regbase + reg)
 
 //now 100ms
+/* #define WAIT_10MS()	schedule_timeout(HZ/10) */
 #define WAIT_10MS()	do { int __i; for (__i = 0; __i < 100; __i++) udelay(1000); } while(0)
 
 /* currently only support a single device */
@@ -69,25 +70,43 @@
 /************************* helper routines ***************************** */
 static inline void ad1889_set_wav_rate(ad1889_dev_t *dev, int rate)
 {
+	struct ac97_codec *ac97_codec = dev->ac97_codec;
+
+	DBG("Setting WAV rate to %d\n", rate);
 	dev->state[AD_WAV_STATE].dmabuf.rate = rate;
 	AD1889_WRITEW(dev, AD_DSWAS, rate);
+
+	/* Cycle the DAC to enable the new rate */
+	ac97_codec->codec_write(dev->ac97_codec, AC97_POWER_CONTROL, 0x0200);
+	WAIT_10MS();
+	ac97_codec->codec_write(dev->ac97_codec, AC97_POWER_CONTROL, 0);
 }
 
 static inline void ad1889_set_adc_rate(ad1889_dev_t *dev, int rate)
 {
+	struct ac97_codec *ac97_codec = dev->ac97_codec;
+
+	DBG("Setting ADC rate to %d\n", rate);
 	dev->state[AD_ADC_STATE].dmabuf.rate = rate;
 	AD1889_WRITEW(dev, AD_DSRES, rate);
+
+	/* Cycle the ADC to enable the new rate */
+	ac97_codec->codec_write(dev->ac97_codec, AC97_POWER_CONTROL, 0x0100);
+	WAIT_10MS();
+	ac97_codec->codec_write(dev->ac97_codec, AC97_POWER_CONTROL, 0);
 }
 
 static inline void ad1889_set_wav_fmt(ad1889_dev_t *dev, int fmt)
 {
 	u16 tmp;
 
+	DBG("Setting WAV format to 0x%x\n", fmt);
+
 	tmp = AD1889_READW(ad1889_dev, AD_DSWSMC);
-	if (fmt == AFMT_S16_LE) {
+	if (fmt & AFMT_S16_LE) {
 		//tmp |= 0x0100; /* set WA16 */
 		tmp |= 0x0300; /* set WA16 stereo */
-	} else if (fmt == AFMT_U8) {
+	} else if (fmt & AFMT_U8) {
 		tmp &= ~0x0100; /* clear WA16 */
 	} 
 	AD1889_WRITEW(ad1889_dev, AD_DSWSMC, tmp);
@@ -97,10 +116,12 @@
 {
 	u16 tmp;
 
+	DBG("Setting ADC format to 0x%x\n", fmt);
+
 	tmp = AD1889_READW(ad1889_dev, AD_DSRAMC);
-	if (fmt == AFMT_S16_LE) {
+	if (fmt & AFMT_S16_LE) {
 		tmp |= 0x0100; /* set WA16 */
-	} else if (fmt == AFMT_U8) {
+	} else if (fmt & AFMT_U8) {
 		tmp &= ~0x0100; /* clear WA16 */
 	} 
 	AD1889_WRITEW(ad1889_dev, AD_DSRAMC, tmp);
@@ -133,6 +154,9 @@
 	dmabuf->dma_len = cnt;
 	dmabuf->ready = 1;
 
+	DBG("Starting playback at 0x%p for %ld bytes\n", dmabuf->rawbuf +
+	    dmabuf->rd_ptr, dmabuf->dma_len);
+
         /* load up the current register set */
 	AD1889_WRITEL(ad1889_dev, AD_DMAWAVCC, cnt);
 	AD1889_WRITEL(ad1889_dev, AD_DMAWAVICC, cnt);
@@ -243,7 +267,7 @@
 		dmabuf->dma_handle = 0;
 		dmabuf->rd_ptr = dmabuf->wr_ptr = dmabuf->dma_len = 0UL;
 		dmabuf->ready = 0;
-		dmabuf->rate = 44100;
+		dmabuf->rate = 48000;
 	}
 	return dev;
 
@@ -472,7 +496,6 @@
 		long cnt = count;
 		unsigned long flags;
 
-
 		for (;;) {
 			long used_bytes;
 			long timeout;	/* max time for DMA in jiffies */
@@ -498,17 +521,11 @@
 			}
 
 			set_current_state(TASK_INTERRUPTIBLE);
-			if (!schedule_timeout(timeout + 1))
-				printk(KERN_WARNING "AD1889 timeout(%ld) r/w %lx/%lx len %lx\n",
-				    timeout+1,
-				    dmabuf->rd_ptr, dmabuf->wr_ptr,
-				    dmabuf->dma_len);
-
+			schedule_timeout(timeout + 1);
 			if (signal_pending(current)) {
 				ret = -ERESTARTSYS;
 				goto err2;
 			}
-
 		}
 
 		/* watch out for wrapping around static buffer */
@@ -616,6 +633,8 @@
 	audio_buf_info abinfo;
 	int __user *p = (int __user *)arg;
 
+	DBG("ad1889_ioctl cmd 0x%x arg %lu\n", cmd, arg);
+
 	switch (cmd)
 	{
 	case OSS_GETVERSION:
@@ -674,11 +693,15 @@
 		if (get_user(val, p))
 			return -EFAULT;
 
-		if (file->f_mode & FMODE_READ) 
-			ad1889_set_adc_fmt(dev, val);
+		if (val == 0) {
+			if (file->f_mode & FMODE_READ) 
+				ad1889_set_adc_fmt(dev, val);
 
-		if (file->f_mode & FMODE_WRITE) 
-			ad1889_set_wav_fmt(dev, val);
+			if (file->f_mode & FMODE_WRITE) 
+				ad1889_set_wav_fmt(dev, val);
+		} else {
+			val = AFMT_S16_LE | AFMT_U8;
+		}
 
 		return put_user(val, p);
 
@@ -758,7 +781,7 @@
 	
 	file->private_data = ad1889_dev;
 
-	ad1889_set_wav_rate(ad1889_dev, 44100);
+	ad1889_set_wav_rate(ad1889_dev, 48000);
 	ad1889_set_wav_fmt(ad1889_dev, AFMT_S16_LE);
 	AD1889_WRITEW(ad1889_dev, AD_DSWADA, 0x0404); /* attenuation */
 	return nonseekable_open(inode, file);
@@ -938,7 +961,6 @@
 			ad1889_stop_wav(&dev->state[AD_WAV_STATE]);	/* clean up */
 			ad1889_start_wav(&dev->state[AD_WAV_STATE]);	/* start new */
 		}
-
 	}
 
 	if ((stat & 0x2) && dev->state[AD_ADC_STATE].dmabuf.ready) { /* ADCI */
@@ -952,18 +974,19 @@
 
 static void ad1889_initcfg(ad1889_dev_t *dev)
 {
-	u16 tmp;
+	u16 tmp16;
+	u32 tmp32;
 
 	/* make sure the interrupt bits are setup the way we want */
-	tmp = AD1889_READW(dev, AD_DMAWAVCTRL);
-	tmp &= ~0x00ff; /* flat dma, no sg, mask out the intr bits */
-	tmp |= 0x0004;  /* intr on count, loop */
-	AD1889_WRITEW(dev, AD_DMAWAVCTRL, tmp);
+	tmp32 = AD1889_READL(dev, AD_DMAWAVCTRL);
+	tmp32 &= ~0xff; /* flat dma, no sg, mask out the intr bits */
+	tmp32 |= 0x6;  /* intr on count, loop */
+	AD1889_WRITEL(dev, AD_DMAWAVCTRL, tmp32);
 
 	/* unmute... */
-	tmp = AD1889_READW(dev, AD_DSWADA);
-	tmp &= ~0x8080;
-	AD1889_WRITEW(dev, AD_DSWADA, tmp);
+	tmp16 = AD1889_READW(dev, AD_DSWADA);
+	tmp16 &= ~0x8080;
+	AD1889_WRITEW(dev, AD_DSWADA, tmp16);
 }
 
 static int __devinit ad1889_probe(struct pci_dev *pcidev, const struct pci_device_id *ent)
diff -Nru a/sound/oss/ad1889.h b/sound/oss/ad1889.h
--- a/sound/oss/ad1889.h	2004-10-18 14:56:48 -07:00
+++ b/sound/oss/ad1889.h	2004-10-18 14:56:48 -07:00
@@ -34,9 +34,9 @@
 #define AD_DMAWAVICC	0x98	/* WAV interrupt current count */
 #define AD_DMAWAVIBC	0x9c	/* WAV interrupt base count */
 #define AD_DMARESCTRL	0xa0	/* RES PCI control/status */
-#define AD_DMAADCCTRL	0xa8	/* RES PCI control/status */
-#define AD_DMASYNCTRL	0xb0	/* RES PCI control/status */
-#define AD_DMAWAVCTRL	0xb8	/* RES PCI control/status */
+#define AD_DMAADCCTRL	0xa8	/* ADC PCI control/status */
+#define AD_DMASYNCTRL	0xb0	/* SYN PCI control/status */
+#define AD_DMAWAVCTRL	0xb8	/* WAV PCI control/status */
 #define AD_DMADISR	0xc0	/* PCI DMA intr status */
 #define AD_DMACHSS	0xc4	/* PCI DMA channel stop status */
 
diff -Nru a/sound/oss/ali5455.c b/sound/oss/ali5455.c
--- a/sound/oss/ali5455.c	2004-10-18 14:56:49 -07:00
+++ b/sound/oss/ali5455.c	2004-10-18 14:56:49 -07:00
@@ -65,7 +65,6 @@
 #include <linux/ac97_codec.h>
 #include <linux/interrupt.h>
 #include <asm/uaccess.h>
-#include <asm/hardirq.h>
 
 #ifndef PCI_DEVICE_ID_ALI_5455
 #define PCI_DEVICE_ID_ALI_5455	0x5455
diff -Nru a/sound/oss/au1000.c b/sound/oss/au1000.c
--- a/sound/oss/au1000.c	2004-10-18 14:56:33 -07:00
+++ b/sound/oss/au1000.c	2004-10-18 14:56:33 -07:00
@@ -67,9 +67,9 @@
 #include <linux/smp_lock.h>
 #include <linux/ac97_codec.h>
 #include <linux/wrapper.h>
+#include <linux/interrupt.h>
 #include <asm/io.h>
 #include <asm/uaccess.h>
-#include <asm/hardirq.h>
 #include <asm/au1000.h>
 #include <asm/au1000_dma.h>
 
diff -Nru a/sound/oss/awe_wave.c b/sound/oss/awe_wave.c
--- a/sound/oss/awe_wave.c	2004-10-18 14:56:28 -07:00
+++ b/sound/oss/awe_wave.c	2004-10-18 14:56:28 -07:00
@@ -4130,7 +4130,7 @@
 	}
 }
 
-static void __exit unload_mixer(void)
+static void unload_mixer(void)
 {
 	if (my_mixerdev >= 0)
 		sound_unload_mixerdev(my_mixerdev);
@@ -4968,7 +4968,7 @@
 		midi_devs[my_mididev] = &awe_midi_operations;
 }
 
-static void __exit unload_midiemu(void)
+static void unload_midiemu(void)
 {
 	if (my_mididev >= 0)
 		sound_unload_mididev(my_mididev);
diff -Nru a/sound/oss/btaudio.c b/sound/oss/btaudio.c
--- a/sound/oss/btaudio.c	2004-10-18 14:56:20 -07:00
+++ b/sound/oss/btaudio.c	2004-10-18 14:56:20 -07:00
@@ -961,7 +961,7 @@
 	/* init hw */
         btwrite(0, REG_GPIO_DMA_CTL);
         btwrite(0, REG_INT_MASK);
-        btwrite(~0x0UL, REG_INT_STAT);
+        btwrite(~0U, REG_INT_STAT);
 	pci_set_master(pci_dev);
 
 	if ((rc = request_irq(bta->irq, btaudio_irq, SA_SHIRQ|SA_INTERRUPT,
@@ -1033,7 +1033,7 @@
 	/* turn off all DMA / IRQs */
         btand(~15, REG_GPIO_DMA_CTL);
         btwrite(0, REG_INT_MASK);
-        btwrite(~0x0UL, REG_INT_STAT);
+        btwrite(~0U, REG_INT_STAT);
 
 	/* unregister devices */
 	if (digital) {
diff -Nru a/sound/oss/cmpci.c b/sound/oss/cmpci.c
--- a/sound/oss/cmpci.c	2004-10-18 14:56:32 -07:00
+++ b/sound/oss/cmpci.c	2004-10-18 14:56:32 -07:00
@@ -3000,6 +3000,8 @@
 	mm_segment_t fs;
 	int i, val, ret;
 	unsigned char reg_mask;
+	int timeout;
+	struct resource *ports;
 	struct {
 		unsigned short	deviceid;
 		char		*devicename;
@@ -3184,54 +3186,55 @@
 	}
 #endif
 #ifdef CONFIG_SOUND_CMPCI_MIDI
+	switch (s->iomidi) {
+	    case 0x330:
+		reg_mask = 0;
+		break;
+	    case 0x320:
+		reg_mask = 0x20;
+		break;
+	    case 0x310:
+		reg_mask = 0x40;
+		break;
+	    case 0x300:
+		reg_mask = 0x60;
+		break;
+	    default:
+		s->iomidi = 0;
+		goto skip_mpu;
+	}
+	ports = request_region(s->iomidi, 2, "mpu401");
+	if (!ports)
+		goto skip_mpu;
 	/* disable MPU-401 */
 	maskb(s->iobase + CODEC_CMI_FUNCTRL1, ~0x04, 0);
 	s->mpu_data.name = "cmpci mpu";
 	s->mpu_data.io_base = s->iomidi;
 	s->mpu_data.irq = -s->irq;	// tell mpu401 to share irq
-	if (probe_mpu401(&s->mpu_data))
+	if (probe_mpu401(&s->mpu_data, ports)) {
+		release_region(s->iomidi, 2);
 		s->iomidi = 0;
-	if (s->iomidi) {
-		/* set IO based at 0x330 */
-		switch (s->iomidi) {
-		    case 0x330:
-			reg_mask = 0;
-			break;
-		    case 0x320:
-			reg_mask = 0x20;
-			break;
-		    case 0x310:
-			reg_mask = 0x40;
-			break;
-		    case 0x300:
-			reg_mask = 0x60;
-			break;
-		    default:
-			s->iomidi = 0;
+		goto skip_mpu;
+	}
+	maskb(s->iobase + CODEC_CMI_LEGACY_CTRL + 3, ~0x60, reg_mask);
+	/* enable MPU-401 */
+	maskb(s->iobase + CODEC_CMI_FUNCTRL1, ~0, 0x04);
+	/* clear all previously received interrupt */
+	for (timeout = 900000; timeout > 0; timeout--) {
+		if ((inb(s->iomidi + 1) && 0x80) == 0)
+			inb(s->iomidi);
+		else
 			break;
-		}
-		maskb(s->iobase + CODEC_CMI_LEGACY_CTRL + 3, ~0x60, reg_mask);
-		/* enable MPU-401 */
-		if (s->iomidi) {
-			int timeout;
-
-			maskb(s->iobase + CODEC_CMI_FUNCTRL1, ~0, 0x04);
-			/* clear all previously received interrupt */
-			for (timeout = 900000; timeout > 0; timeout--) {
-				if ((inb(s->iomidi + 1) && 0x80) == 0)
-					inb(s->iomidi);
-				else
-					break;
-			}
-	    		if (!probe_mpu401(&s->mpu_data)) {
-				s->iomidi = 0;
-				maskb(s->iobase + CODEC_CMI_FUNCTRL1, ~0, 0x04);
-			} else {
-				attach_mpu401(&s->mpu_data, THIS_MODULE);
-				s->midi_devc = s->mpu_data.slots[1];
-			}
-		}
 	}
+	if (!probe_mpu401(&s->mpu_data, ports)) {
+		release_region(s->iomidi, 2);
+		s->iomidi = 0;
+		maskb(s->iobase + CODEC_CMI_FUNCTRL1, ~0, 0x04);
+	} else {
+		attach_mpu401(&s->mpu_data, THIS_MODULE);
+		s->midi_devc = s->mpu_data.slots[1];
+	}
+skip_mpu:
 #endif
 #ifdef CONFIG_SOUND_CMPCI_JOYSTICK
 	/* enable joystick */
diff -Nru a/sound/oss/cs4232.c b/sound/oss/cs4232.c
--- a/sound/oss/cs4232.c	2004-10-18 14:56:33 -07:00
+++ b/sound/oss/cs4232.c	2004-10-18 14:56:33 -07:00
@@ -128,27 +128,33 @@
         outb(((unsigned char) (ENABLE_PINS | regd)), baseio + INDEX_DATA );
 }
 
-int __init probe_cs4232(struct address_info *hw_config, int isapnp_configured)
+static int __init probe_cs4232(struct address_info *hw_config, int isapnp_configured)
 {
 	int i, n;
 	int base = hw_config->io_base, irq = hw_config->irq;
 	int dma1 = hw_config->dma, dma2 = hw_config->dma2;
+	struct resource *ports;
+
+	if (base == -1 || irq == -1 || dma1 == -1) {
+		printk(KERN_ERR "cs4232: dma, irq and io must be set.\n");
+		return 0;
+	}
 
 	/*
 	 * Verify that the I/O port range is free.
 	 */
 
-	if (check_region(base, 4))
-	{
+	ports = request_region(base, 4, "ad1848");
+	if (!ports) {
 		printk(KERN_ERR "cs4232.c: I/O port 0x%03x not free\n", base);
 		return 0;
 	}
-	if (ad1848_detect(hw_config->io_base, NULL, hw_config->osp)) {
-		return 1;	/* The card is already active */
+	if (ad1848_detect(ports, NULL, hw_config->osp)) {
+		goto got_it;	/* The card is already active */
 	}
 	if (isapnp_configured) {
 		printk(KERN_ERR "cs4232.c: ISA PnP configured, but not detected?\n");
-		return 0;
+		goto fail;
 	}
 
 	/*
@@ -241,30 +247,20 @@
 		 * Then try to detect the codec part of the chip
 		 */
 
-		if (ad1848_detect(hw_config->io_base, NULL, hw_config->osp))
-			return 1;
+		if (ad1848_detect(ports, NULL, hw_config->osp))
+			goto got_it;
 		
 		sleep(HZ);
 	}
+fail:
+	release_region(base, 4);
 	return 0;
-}
-
-void __init attach_cs4232(struct address_info *hw_config)
-{
-	int base = hw_config->io_base,
-		irq = hw_config->irq,
-		dma1 = hw_config->dma,
-		dma2 = hw_config->dma2;
-
-	if (base == -1 || irq == -1 || dma1 == -1) {
-		printk(KERN_ERR "cs4232: dma, irq and io must be set.\n");
-		return;
-	}
 
+got_it:
 	if (dma2 == -1)
 		dma2 = dma1;
 
-	hw_config->slots[0] = ad1848_init("Crystal audio controller", base,
+	hw_config->slots[0] = ad1848_init("Crystal audio controller", ports,
 					  irq,
 					  dma1,		/* Playback DMA */
 					  dma2,		/* Capture DMA */
@@ -308,9 +304,9 @@
 	}
 	
 	if (bss)
-	{
         	enable_xctrl(base);
-	}
+
+	return 1;
 }
 
 static void __devexit unload_cs4232(struct address_info *hw_config)
@@ -423,7 +419,6 @@
 		kfree(isapnpcfg);
 		return -ENODEV;
 	}
-	attach_cs4232(isapnpcfg);
 	pnp_set_drvdata(dev,isapnpcfg);
 	return 0;
 }
@@ -486,7 +481,6 @@
 
 	if (probe_cs4232(&cfg,FALSE) == 0)
 		return -ENODEV;
-	attach_cs4232(&cfg);
 
 	return 0;
 }
diff -Nru a/sound/oss/cs4232.h b/sound/oss/cs4232.h
--- a/sound/oss/cs4232.h	2004-10-18 14:56:17 -07:00
+++ b/sound/oss/cs4232.h	2004-10-18 14:56:17 -07:00
@@ -1,5 +1,3 @@
 
-int probe_cs4232 (struct address_info *hw_config,int useisapnp);
-void attach_cs4232 (struct address_info *hw_config);
 int probe_cs4232_mpu (struct address_info *hw_config);
 void attach_cs4232_mpu (struct address_info *hw_config);
diff -Nru a/sound/oss/cs46xx.c b/sound/oss/cs46xx.c
--- a/sound/oss/cs46xx.c	2004-10-18 14:55:53 -07:00
+++ b/sound/oss/cs46xx.c	2004-10-18 14:55:53 -07:00
@@ -94,7 +94,6 @@
 #include <asm/io.h>
 #include <asm/dma.h>
 #include <asm/uaccess.h>
-#include <asm/hardirq.h>
 
 #include "cs46xxpm-24.h"
 #include "cs46xx_wrapper-24.h"
@@ -2096,7 +2095,7 @@
 	unsigned copied=0;
 
 	CS_DBGOUT(CS_WAVE_READ | CS_FUNCTION, 4, 
-		printk("cs46xx: cs_read()+ %d\n",count) );
+		printk("cs46xx: cs_read()+ %zd\n",count) );
 	state = (struct cs_state *)card->states[0];
 	if(!state)
 		return -ENODEV;
@@ -2157,9 +2156,9 @@
 		}
 
 		CS_DBGOUT(CS_WAVE_READ, 2, printk(KERN_INFO 
-			"_read() copy_to cnt=%d count=%d ", cnt,count) );
+			"_read() copy_to cnt=%d count=%zd ", cnt,count) );
 		CS_DBGOUT(CS_WAVE_READ, 8, printk(KERN_INFO 
-			" .dmasize=%d .count=%d buffer=%p ret=%d\n",
+			" .dmasize=%d .count=%d buffer=%p ret=%zd\n",
 			dmabuf->dmasize,dmabuf->count,buffer,ret) );
 
                 if (cs_copy_to_user(state, buffer, 
@@ -2184,7 +2183,7 @@
 	up(&state->sem);
 	set_current_state(TASK_RUNNING);
 	CS_DBGOUT(CS_WAVE_READ | CS_FUNCTION, 4, 
-		printk("cs46xx: cs_read()- %d\n",ret) );
+		printk("cs46xx: cs_read()- %zd\n",ret) );
 	return ret;
 }
 
@@ -2202,7 +2201,7 @@
 	int cnt;
 
 	CS_DBGOUT(CS_WAVE_WRITE | CS_FUNCTION, 4,
-		printk("cs46xx: cs_write called, count = %d\n", count) );
+		printk("cs46xx: cs_write called, count = %zd\n", count) );
 	state = (struct cs_state *)card->states[1];
 	if(!state)
 		return -ENODEV;
@@ -2309,7 +2308,7 @@
 	set_current_state(TASK_RUNNING);
 
 	CS_DBGOUT(CS_WAVE_WRITE | CS_FUNCTION, 2, 
-		printk("cs46xx: cs_write()- ret=0x%x\n", ret) );
+		printk("cs46xx: cs_write()- ret=%zd\n", ret) );
 	return ret;
 }
 
diff -Nru a/sound/oss/dmasound/Kconfig b/sound/oss/dmasound/Kconfig
--- a/sound/oss/dmasound/Kconfig	2004-10-18 14:56:31 -07:00
+++ b/sound/oss/dmasound/Kconfig	2004-10-18 14:56:31 -07:00
@@ -14,7 +14,7 @@
 
 config DMASOUND_PMAC
 	tristate "PowerMac DMA sound support"
-	depends on PPC_PMAC && SOUND && I2C
+	depends on PPC32 && PPC_PMAC && SOUND && I2C
  	select DMASOUND
 	help
 	  If you want to use the internal audio of your PowerMac in Linux,
diff -Nru a/sound/oss/emu10k1/midi.c b/sound/oss/emu10k1/midi.c
--- a/sound/oss/emu10k1/midi.c	2004-10-18 14:57:05 -07:00
+++ b/sound/oss/emu10k1/midi.c	2004-10-18 14:57:05 -07:00
@@ -320,7 +320,6 @@
 {
 	struct emu10k1_mididevice *midi_dev = (struct emu10k1_mididevice *) file->private_data;
 	struct midi_hdr *midihdr;
-	ssize_t ret = 0;
 	unsigned long flags;
 
 	DPD(4, "emu10k1_midi_write(), count=%#x\n", (u32) count);
@@ -344,7 +343,7 @@
 	if (copy_from_user(midihdr->data, buffer, count)) {
 		kfree(midihdr->data);
 		kfree(midihdr);
-		return ret ? ret : -EFAULT;
+		return -EFAULT;
 	}
 
 	spin_lock_irqsave(&midi_spinlock, flags);
diff -Nru a/sound/oss/forte.c b/sound/oss/forte.c
--- a/sound/oss/forte.c	2004-10-18 14:56:28 -07:00
+++ b/sound/oss/forte.c	2004-10-18 14:56:28 -07:00
@@ -45,7 +45,6 @@
 #include <linux/proc_fs.h>
 
 #include <asm/uaccess.h>
-#include <asm/hardirq.h>
 #include <asm/io.h>
 
 #define DRIVER_NAME	"forte"
diff -Nru a/sound/oss/gus_card.c b/sound/oss/gus_card.c
--- a/sound/oss/gus_card.c	2004-10-18 14:55:46 -07:00
+++ b/sound/oss/gus_card.c	2004-10-18 14:55:46 -07:00
@@ -160,22 +160,29 @@
 
 #ifdef CONFIG_SOUND_GUS16
 
-static int __init probe_gus_db16(struct address_info *hw_config)
+static int __init init_gus_db16(struct address_info *hw_config)
 {
-	return ad1848_detect(hw_config->io_base, NULL, hw_config->osp);
-}
+	struct resource *ports;
+
+	ports = request_region(hw_config->io_base, 4, "ad1848");
+	if (!ports)
+		return 0;
+
+	if (!ad1848_detect(ports, NULL, hw_config->osp)) {
+		release_region(hw_config->io_base, 4);
+		return 0;
+	}
 
-static void __init attach_gus_db16(struct address_info *hw_config)
-{
 	gus_pcm_volume = 100;
 	gus_wave_volume = 90;
 
-	hw_config->slots[3] = ad1848_init("GUS 16 bit sampling", hw_config->io_base,
+	hw_config->slots[3] = ad1848_init("GUS 16 bit sampling", ports,
 					  hw_config->irq,
 					  hw_config->dma,
 					  hw_config->dma, 0,
 					  hw_config->osp,
 					  THIS_MODULE);
+	return 1;
 }
 
 static void __exit unload_gus_db16(struct address_info *hw_config)
@@ -244,11 +251,8 @@
 	}
 
 #ifdef CONFIG_SOUND_GUS16
-	if (probe_gus_db16(&cfg) && gus16) {
-		/* FIXME: This can't work, can it ? -- Christoph */
-		attach_gus_db16(&cfg);
+	if (gus16 && init_gus_db16(&cfg))
 		db16 = 1;
-	}	
 #endif
 	if (!probe_gus(&cfg))
 		return -ENODEV;
diff -Nru a/sound/oss/gus_wave.c b/sound/oss/gus_wave.c
--- a/sound/oss/gus_wave.c	2004-10-18 14:57:19 -07:00
+++ b/sound/oss/gus_wave.c	2004-10-18 14:57:19 -07:00
@@ -2942,6 +2942,8 @@
 		}
 		else
 		{
+			struct resource *ports;
+			ports = request_region(gus_base + 0x10c, 4, "ad1848");
 			model_num = "MAX";
 			gus_type = 0x40;
 			mixer_type = CS4231;
@@ -2963,7 +2965,10 @@
 				outb((max_config), gus_base + 0x106);	/* UltraMax control */
 			}
 
-			if (ad1848_detect(gus_base + 0x10c, &ad_flags, hw_config->osp))
+			if (!ports)
+				goto no_cs4231;
+
+			if (ad1848_detect(ports, &ad_flags, hw_config->osp))
 			{
 				char           *name = "GUS MAX";
 				int             old_num_mixers = num_mixers;
@@ -2977,7 +2982,7 @@
 				if (hw_config->name)
 					name = hw_config->name;
 
-				hw_config->slots[1] = ad1848_init(name, gus_base + 0x10c,
+				hw_config->slots[1] = ad1848_init(name, ports,
 							-irq, gus_dma2,	/* Playback DMA */
 							gus_dma,	/* Capture DMA */
 							1,		/* Share DMA channels with GF1 */
@@ -2992,8 +2997,11 @@
 					AD1848_REROUTE(SOUND_MIXER_LINE3, SOUND_MIXER_LINE);
 				}
 			}
-			else
+			else {
+				release_region(gus_base + 0x10c, 4);
+			no_cs4231:
 				printk(KERN_WARNING "GUS: No CS4231 ??");
+			}
 #else
 			printk(KERN_ERR "GUS MAX found, but not compiled in\n");
 #endif
diff -Nru a/sound/oss/harmony.c b/sound/oss/harmony.c
--- a/sound/oss/harmony.c	2004-10-18 14:56:49 -07:00
+++ b/sound/oss/harmony.c	2004-10-18 14:56:49 -07:00
@@ -8,10 +8,11 @@
 	On older 715 machines you'll find the technically identical chip 
 	called 'Vivace'. Both Harmony and Vicace are supported by this driver.
 
-	Copyright 2000 (c) Linuxcare Canada, Alex deVries <alex@linuxcare.com>
+	Copyright 2000 (c) Linuxcare Canada, Alex deVries <alex@onefishtwo.ca>
 	Copyright 2000-2003 (c) Helge Deller <deller@gmx.de>
 	Copyright 2001 (c) Matthieu Delahaye <delahaym@esiee.fr>
 	Copyright 2001 (c) Jean-Christophe Vaugeois <vaugeoij@esiee.fr>
+	Copyright 2004 (c) Stuart Brady <sdbrady@ntlworld.com>
 
 				
 TODO:
@@ -124,9 +125,17 @@
 #define GAIN_RO_MASK    ( 0x3f << GAIN_RO_SHIFT) 
 
 
-#define MAX_OUTPUT_LEVEL (GAIN_RO_MASK >> GAIN_RO_SHIFT)
-#define MAX_INPUT_LEVEL  (GAIN_RI_MASK >> GAIN_RI_SHIFT)
-#define MAX_VOLUME_LEVEL (GAIN_MA_MASK >> GAIN_MA_SHIFT)
+#define MAX_OUTPUT_LEVEL  (GAIN_RO_MASK >> GAIN_RO_SHIFT)
+#define MAX_INPUT_LEVEL   (GAIN_RI_MASK >> GAIN_RI_SHIFT)
+#define MAX_MONITOR_LEVEL (GAIN_MA_MASK >> GAIN_MA_SHIFT)
+
+#define MIXER_INTERNAL   SOUND_MIXER_LINE1
+#define MIXER_LINEOUT    SOUND_MIXER_LINE2
+#define MIXER_HEADPHONES SOUND_MIXER_LINE3
+
+#define MASK_INTERNAL   SOUND_MASK_LINE1
+#define MASK_LINEOUT    SOUND_MASK_LINE2
+#define MASK_HEADPHONES SOUND_MASK_LINE3
 
 /*
  * Channels Mask in mixer register
@@ -543,6 +552,7 @@
 	int count = 0;
 	int frame_size;
 	int buf_to_fill;
+	int fresh_buffer;
 
 	if (!harmony.format_initialized) {
 		if (harmony_format_auto_detect(buffer, total_count))
@@ -564,12 +574,16 @@
 		
 		
 		buf_to_fill = (harmony.first_filled_play+harmony.nb_filled_play); 
-		if (harmony.play_offset)
+		if (harmony.play_offset) {
 			buf_to_fill--;
+			buf_to_fill += MAX_BUFS;
+		}
 		buf_to_fill %= MAX_BUFS;
-
+		
+		fresh_buffer = (harmony.play_offset == 0);
+		
 		/* Figure out the size of the frame */
-		if ((total_count-count) > HARMONY_BUF_SIZE - harmony.play_offset) {
+		if ((total_count-count) >= HARMONY_BUF_SIZE - harmony.play_offset) {
 			frame_size = HARMONY_BUF_SIZE - harmony.play_offset;
 		} else {
 			frame_size = total_count - count;
@@ -587,7 +601,7 @@
 		CHECK_WBACK_INV_OFFSET(played_buf, (HARMONY_BUF_SIZE*buf_to_fill + harmony.play_offset), 
 				frame_size);
 	
-		if (!harmony.play_offset)
+		if (fresh_buffer)
 			harmony.nb_filled_play++;
 		
 		count += frame_size;
@@ -650,18 +664,17 @@
 			switch (ival) {
 			case AFMT_MU_LAW:	new_format = HARMONY_DF_8BIT_ULAW; break;
 			case AFMT_A_LAW:	new_format = HARMONY_DF_8BIT_ALAW; break;
-			case AFMT_S16_LE:	/* fall through, but not really supported */
-			case AFMT_S16_BE:	new_format = HARMONY_DF_16BIT_LINEAR;
-						ival = AFMT_S16_BE;
-						break; 
+			case AFMT_S16_BE:	new_format = HARMONY_DF_16BIT_LINEAR; break;
 			default: {
 				DPRINTK(KERN_WARNING PFX 
 					"unsupported sound format 0x%04x requested.\n",
 					ival);
-				return -EINVAL;
+				ival = AFMT_S16_BE;
+				return put_user(ival, (int *) arg);
 			}
 			}
 			harmony_set_format(new_format);
+			return 0;
 		} else {
 			switch (harmony.data_format) {
 			case HARMONY_DF_8BIT_ULAW:	ival = AFMT_MU_LAW; break;
@@ -669,8 +682,8 @@
 			case HARMONY_DF_16BIT_LINEAR:	ival = AFMT_U16_BE; break;
 			default: ival = 0;
 			}
+			return put_user(ival, (int *) arg);
 		}
-		return put_user(ival, (int *) arg);
 
 	case SOUND_PCM_READ_RATE:
 		ival = harmony.dac_rate;
@@ -689,7 +702,17 @@
 		if (ival != 0 && ival != 1)
 			return -EINVAL;
 		harmony_set_stereo(ival);
-		return put_user(ival, (int *) arg);
+ 		return 0;
+ 
+ 	case SNDCTL_DSP_CHANNELS:
+ 		if (get_user(ival, (int *) arg))
+ 			return -EFAULT;
+ 		if (ival != 1 && ival != 2) {
+ 			ival = harmony.stereo_select == HARMONY_SS_MONO ? 1 : 2;
+ 			return put_user(ival, (int *) arg);
+ 		}
+ 		harmony_set_stereo(ival-1);
+ 		return 0;
 
 	case SNDCTL_DSP_GETBLKSIZE:
 		ival = HARMONY_BUF_SIZE;
@@ -887,7 +910,7 @@
 	int right_level;
 
 	switch (channel) {
-		case SOUND_MIXER_OGAIN:
+		case SOUND_MIXER_VOLUME:
 			left_level  = (harmony.current_gain & GAIN_LO_MASK) >> GAIN_LO_SHIFT;
 			right_level = (harmony.current_gain & GAIN_RO_MASK) >> GAIN_RO_SHIFT;
 			left_level  = to_oss_level(MAX_OUTPUT_LEVEL - left_level, MAX_OUTPUT_LEVEL);
@@ -901,10 +924,10 @@
 			right_level= to_oss_level(right_level, MAX_INPUT_LEVEL);
 			return (right_level << 8)+left_level;
 			
-		case SOUND_MIXER_VOLUME:
+		case SOUND_MIXER_MONITOR:
 			left_level = (harmony.current_gain & GAIN_MA_MASK) >> GAIN_MA_SHIFT;
-			left_level = to_oss_level(MAX_VOLUME_LEVEL-left_level, MAX_VOLUME_LEVEL);
-			return left_level;
+			left_level = to_oss_level(MAX_MONITOR_LEVEL-left_level, MAX_MONITOR_LEVEL);
+			return (left_level << 8)+left_level;
 	}
 	return -EINVAL;
 }
@@ -926,9 +949,11 @@
 
 	right_level = (value & 0x0000ff00) >> 8;
 	left_level = value & 0x000000ff;
+	if (right_level > 100) right_level = 100;
+	if (left_level > 100) left_level = 100;
   
 	switch (channel) {
-		case SOUND_MIXER_OGAIN:
+		case SOUND_MIXER_VOLUME:
 			right_level = to_harmony_level(100-right_level, MAX_OUTPUT_LEVEL);
 			left_level  = to_harmony_level(100-left_level, MAX_OUTPUT_LEVEL);
 			new_right_level = to_oss_level(MAX_OUTPUT_LEVEL - right_level, MAX_OUTPUT_LEVEL);
@@ -948,12 +973,12 @@
 			harmony_mixer_set_gain();
 			return (new_right_level << 8) + new_left_level;
 	
-		case SOUND_MIXER_VOLUME:
-			left_level = to_harmony_level(100-left_level, MAX_VOLUME_LEVEL);
-			new_left_level = to_oss_level(MAX_VOLUME_LEVEL-left_level, MAX_VOLUME_LEVEL);
-			harmony.current_gain = (harmony.current_gain & ~GAIN_MA_MASK)| (left_level << GAIN_MA_SHIFT);
+		case SOUND_MIXER_MONITOR:
+			left_level = to_harmony_level(100-left_level, MAX_MONITOR_LEVEL);
+			new_left_level = to_oss_level(MAX_MONITOR_LEVEL-left_level, MAX_MONITOR_LEVEL);
+			harmony.current_gain = (harmony.current_gain & ~GAIN_MA_MASK) | (left_level << GAIN_MA_SHIFT);
 			harmony_mixer_set_gain();
-			return new_left_level;
+			return (new_left_level << 8) + new_left_level;
 	}
 
 	return -EINVAL;
@@ -986,11 +1011,15 @@
 {
 	int new_input_line;
 	int new_input_mask;
-
-	if ((recmask & SOUND_MASK_LINE)) {
+	int current_input_line;
+	
+	current_input_line = (harmony.current_gain & GAIN_IS_MASK)
+				    >> GAIN_IS_SHIFT;
+	if ((current_input_line && ((recmask & SOUND_MASK_LINE) || !(recmask & SOUND_MASK_MIC))) ||
+		(!current_input_line && ((recmask & SOUND_MASK_LINE) && !(recmask & SOUND_MASK_MIC)))) {
 		new_input_line = 0;
 		new_input_mask = SOUND_MASK_LINE;
-	} else  {
+	} else {
 		new_input_line = 1;
 		new_input_mask = SOUND_MASK_MIC;
 	}
@@ -1009,9 +1038,9 @@
 {
 	int outmask = 0;
 	
-	if (harmony.current_gain & GAIN_HE_MASK) outmask |=SOUND_MASK_PHONEOUT;
-	if (harmony.current_gain & GAIN_LE_MASK) outmask |=SOUND_MASK_LINE;
-	if (harmony.current_gain & GAIN_SE_MASK) outmask |=SOUND_MASK_SPEAKER;
+	if (harmony.current_gain & GAIN_SE_MASK) outmask |= MASK_INTERNAL;
+	if (harmony.current_gain & GAIN_LE_MASK) outmask |= MASK_LINEOUT;
+	if (harmony.current_gain & GAIN_HE_MASK) outmask |= MASK_HEADPHONES;
 	
 	return outmask;
 }
@@ -1019,24 +1048,24 @@
 
 static int harmony_mixer_set_outmask(int outmask)
 {
-	if (outmask & SOUND_MASK_PHONEOUT) 
-		harmony.current_gain |= GAIN_HE_MASK; 
+	if (outmask & MASK_INTERNAL) 
+		harmony.current_gain |= GAIN_SE_MASK;
 	else 
-		harmony.current_gain &= ~GAIN_HE_MASK;
+		harmony.current_gain &= ~GAIN_SE_MASK;
 	
-	if (outmask & SOUND_MASK_LINE) 
+	if (outmask & MASK_LINEOUT) 
 		harmony.current_gain |= GAIN_LE_MASK;
 	else 
 		harmony.current_gain &= ~GAIN_LE_MASK;
 	
-	if (outmask & SOUND_MASK_SPEAKER) 
-		harmony.current_gain |= GAIN_SE_MASK;
+	if (outmask & MASK_HEADPHONES) 
+		harmony.current_gain |= GAIN_HE_MASK; 
 	else 
-		harmony.current_gain &= ~GAIN_SE_MASK;
+		harmony.current_gain &= ~GAIN_HE_MASK;
 	
 	harmony_mixer_set_gain();
 
-	return (outmask & (SOUND_MASK_PHONEOUT | SOUND_MASK_LINE | SOUND_MASK_SPEAKER));
+	return (outmask & (MASK_INTERNAL | MASK_LINEOUT | MASK_HEADPHONES));
 }
 
 /*
@@ -1074,19 +1103,19 @@
 		ret = SOUND_CAP_EXCL_INPUT;
 		break;
 	case MIXER_READ(SOUND_MIXER_STEREODEVS):
-		ret = SOUND_MASK_IGAIN | SOUND_MASK_OGAIN;
+		ret = SOUND_MASK_VOLUME | SOUND_MASK_IGAIN;
 		break;
 		
 	case MIXER_READ(SOUND_MIXER_RECMASK):
 		ret = SOUND_MASK_MIC | SOUND_MASK_LINE;
 		break;
 	case MIXER_READ(SOUND_MIXER_DEVMASK):
-		ret = SOUND_MASK_OGAIN | SOUND_MASK_IGAIN |
-			SOUND_MASK_VOLUME;
+		ret = SOUND_MASK_VOLUME | SOUND_MASK_IGAIN |
+			SOUND_MASK_MONITOR;
 		break;
 	case MIXER_READ(SOUND_MIXER_OUTMASK):
-		ret = SOUND_MASK_SPEAKER | SOUND_MASK_LINE |
-			SOUND_MASK_PHONEOUT;
+		ret = MASK_INTERNAL | MASK_LINEOUT |
+			MASK_HEADPHONES;
 		break;
 		
 	case MIXER_WRITE(SOUND_MIXER_RECSRC):
@@ -1103,15 +1132,15 @@
 		ret = harmony_mixer_get_outmask();
 		break;
 	
-	case MIXER_WRITE(SOUND_MIXER_OGAIN):
-	case MIXER_WRITE(SOUND_MIXER_IGAIN):
 	case MIXER_WRITE(SOUND_MIXER_VOLUME):
+	case MIXER_WRITE(SOUND_MIXER_IGAIN):
+	case MIXER_WRITE(SOUND_MIXER_MONITOR):
 		ret = harmony_mixer_set_level(cmd & 0xff, val);
 		break;
 
-	case MIXER_READ(SOUND_MIXER_OGAIN):
-	case MIXER_READ(SOUND_MIXER_IGAIN):
 	case MIXER_READ(SOUND_MIXER_VOLUME):
+	case MIXER_READ(SOUND_MIXER_IGAIN):
+	case MIXER_READ(SOUND_MIXER_MONITOR):
 		ret = harmony_mixer_get_level(cmd & 0xff);
 		break;
 
@@ -1201,16 +1230,15 @@
 		return -EBUSY;
 	}
 
-	harmony.dev = dev;
-
-	/* Set the HPA of harmony */
-	harmony.hpa = (struct harmony_hpa *)dev->hpa;
-
-	if (!harmony.dev->irq) {
+	if (!dev->irq) {
 		printk(KERN_ERR PFX "no irq found\n");
 		return -ENODEV;
 	}
 
+	/* Set the HPA of harmony */
+	harmony.hpa = (struct harmony_hpa *)dev->hpa;
+	harmony.dev = dev;
+
 	/* Grab the ID and revision from the device */
 	id = gsc_readb(&harmony.hpa->id);
 	if ((id | 1) != 0x15) {
@@ -1293,7 +1321,7 @@
 }
 
 
-MODULE_AUTHOR("Alex DeVries <alex@linuxcare.com>");
+MODULE_AUTHOR("Alex DeVries <alex@onefishtwo.ca>");
 MODULE_DESCRIPTION("Harmony sound driver");
 MODULE_LICENSE("GPL");
 
diff -Nru a/sound/oss/i810_audio.c b/sound/oss/i810_audio.c
--- a/sound/oss/i810_audio.c	2004-10-18 14:56:49 -07:00
+++ b/sound/oss/i810_audio.c	2004-10-18 14:56:49 -07:00
@@ -101,7 +101,6 @@
 #include <linux/ac97_codec.h>
 #include <linux/bitops.h>
 #include <asm/uaccess.h>
-#include <asm/hardirq.h>
 
 #define DRIVER_VERSION "1.01"
 
@@ -3216,8 +3215,14 @@
 	}
 
 	/* claim our iospace and irq */
-	request_region(card->iobase, 64, card_names[pci_id->driver_data]);
-	request_region(card->ac97base, 256, card_names[pci_id->driver_data]);
+	if (!request_region(card->iobase, 64, card_names[pci_id->driver_data])) {
+		printk(KERN_ERR "i810_audio: unable to allocate region %lx\n", card->iobase);
+		goto out_region1;
+	}
+	if (!request_region(card->ac97base, 256, card_names[pci_id->driver_data])) {
+		printk(KERN_ERR "i810_audio: unable to allocate region %lx\n", card->ac97base);
+		goto out_region2;
+	}
 
 	if (request_irq(card->irq, &i810_interrupt, SA_SHIRQ,
 			card_names[pci_id->driver_data], card)) {
@@ -3291,7 +3296,9 @@
 	}
 out_pio:	
 	release_region(card->iobase, 64);
+out_region2:
 	release_region(card->ac97base, 256);
+out_region1:
 	pci_free_consistent(pci_dev, sizeof(struct i810_channel)*NR_HW_CH,
 	    card->channel, card->chandma);
 out_mem:
diff -Nru a/sound/oss/ite8172.c b/sound/oss/ite8172.c
--- a/sound/oss/ite8172.c	2004-10-18 14:56:17 -07:00
+++ b/sound/oss/ite8172.c	2004-10-18 14:56:17 -07:00
@@ -70,10 +70,10 @@
 #include <linux/spinlock.h>
 #include <linux/smp_lock.h>
 #include <linux/ac97_codec.h>
+#include <linux/interrupt.h>
 #include <asm/io.h>
 #include <asm/dma.h>
 #include <asm/uaccess.h>
-#include <asm/hardirq.h>
 #include <asm/it8172/it8172.h>
 
 /* --------------------------------------------------------------------- */
diff -Nru a/sound/oss/kahlua.c b/sound/oss/kahlua.c
--- a/sound/oss/kahlua.c	2004-10-18 14:57:03 -07:00
+++ b/sound/oss/kahlua.c	2004-10-18 14:57:03 -07:00
@@ -156,10 +156,14 @@
 	hw_config->dma2 = dma16;
 	hw_config->name = "Cyrix XpressAudio";
 	hw_config->driver_use_1 = SB_NO_MIDI | SB_PCI_IRQ;
+
+	if (!request_region(io, 16, "soundblaster"))
+		goto err_out_free;
 	
 	if(sb_dsp_detect(hw_config, 0, 0, NULL)==0)
 	{
 		printk(KERN_ERR "kahlua: audio not responding.\n");
+		release_region(io, 16);
 		goto err_out_free;
 	}
 
diff -Nru a/sound/oss/mad16.c b/sound/oss/mad16.c
--- a/sound/oss/mad16.c	2004-10-18 14:56:49 -07:00
+++ b/sound/oss/mad16.c	2004-10-18 14:56:49 -07:00
@@ -54,7 +54,6 @@
 static int      mad16_cdsel;
 static struct gameport gameport;
 static spinlock_t lock=SPIN_LOCK_UNLOCKED;
-static int      already_initialized;
 
 #define C928	1
 #define MOZART	2
@@ -313,19 +312,6 @@
 
 static int __init wss_init(struct address_info *hw_config)
 {
-	int ad_flags = 0;
-
-	/*
-	 *    Verify the WSS parameters
-	 */
-
-	if (check_region(hw_config->io_base, 8))
-	{
-		printk(KERN_ERR "MSS: I/O port conflict\n");
-		return 0;
-	}
-	if (!ad1848_detect(hw_config->io_base + 4, &ad_flags, mad16_osp))
-		return 0;
 	/*
 	 * Check if the IO port returns valid signature. The original MS Sound
 	 * system returns 0x04 while some cards (AudioTrix Pro for example)
@@ -338,31 +324,20 @@
 		DDB(printk("No MSS signature detected on port 0x%x (0x%x)\n", hw_config->io_base, inb(hw_config->io_base + 3)));
 		return 0;
 	}
-	if (hw_config->irq > 11)
-	{
-		printk(KERN_ERR "MSS: Bad IRQ %d\n", hw_config->irq);
-		return 0;
-	}
-	if (hw_config->dma != 0 && hw_config->dma != 1 && hw_config->dma != 3)
-	{
-		printk(KERN_ERR "MSS: Bad DMA %d\n", hw_config->dma);
-		return 0;
-	}
 	/*
 	 * Check that DMA0 is not in use with a 8 bit board.
 	 */
-
 	if (hw_config->dma == 0 && inb(hw_config->io_base + 3) & 0x80)
 	{
 		printk("MSS: Can't use DMA0 with a 8 bit card/slot\n");
 		return 0;
 	}
-	if (hw_config->irq > 7 && hw_config->irq != 9 && inb(hw_config->io_base + 3) & 0x80)
+	if (hw_config->irq > 9 && inb(hw_config->io_base + 3) & 0x80)
 		printk(KERN_ERR "MSS: Can't use IRQ%d with a 8 bit card/slot\n", hw_config->irq);
 	return 1;
 }
 
-static int __init init_c930(struct address_info *hw_config)
+static void __init init_c930(struct address_info *hw_config, int base)
 {
 	unsigned char cfg = 0;
 
@@ -376,25 +351,7 @@
 		   somewhere else. */
 		cfg =  (cfg & 0x09) ^ 0x07;
 	}
-
-	switch (hw_config->io_base)
-	{
-		case 0x530:
-			cfg |= 0x00;
-			break;
-		case 0xe80:
-			cfg |= 0x10;
-			break;
-		case 0xf40:
-			cfg |= 0x20;
-			break;
-		case 0x604:
-			cfg |= 0x30;
-			break;
-		default:
-			printk(KERN_ERR "MAD16: Invalid codec port %x\n", hw_config->io_base);
-			return 0;
-	}
+	cfg |= base << 4;
 	mad_write(MC1_PORT, cfg);
 
 	/* MC2 is CD configuration. Don't touch it. */
@@ -414,8 +371,6 @@
 	mad_write(MC6_PORT, 0x02);	/* Enable WSS, Disable MPU and SB */
 	mad_write(MC7_PORT, 0xCB);
 	mad_write(MC10_PORT, 0x11);
-
-	return wss_init(hw_config);
 }
 
 static int __init chip_detect(void)
@@ -508,20 +463,48 @@
 static int __init probe_mad16(struct address_info *hw_config)
 {
 	int i;
-	static int valid_ports[] = 
-	{
-		0x530, 0xe80, 0xf40, 0x604
-	};
 	unsigned char tmp;
 	unsigned char cs4231_mode = 0;
 
 	int ad_flags = 0;
 
-	if (already_initialized)
-		return 0;
+	signed char bits;
+
+	static char     dma_bits[4] = {
+		1, 2, 0, 3
+	};
+
+	int config_port = hw_config->io_base + 0, version_port = hw_config->io_base + 3;
+	int dma = hw_config->dma, dma2 = hw_config->dma2;
+	unsigned char dma2_bit = 0;
+	int base;
+	struct resource *ports;
 
 	mad16_osp = hw_config->osp;
 
+	switch (hw_config->io_base) {
+	case 0x530:
+		base = 0;
+		break;
+	case 0xe80:
+		base = 1;
+		break;
+	case 0xf40:
+		base = 2;
+		break;
+	case 0x604:
+		base = 3;
+		break;
+	default:
+		printk(KERN_ERR "MAD16/Mozart: Bad WSS base address 0x%x\n", hw_config->io_base);
+		return 0;
+	}
+
+	if (dma != 0 && dma != 1 && dma != 3) {
+		printk(KERN_ERR "MSS: Bad DMA %d\n", dma);
+		return 0;
+	}
+
 	/*
 	 *    Check that all ports return 0xff (bus float) when no password
 	 *      is written to the password register.
@@ -531,9 +514,44 @@
 	if (!chip_detect())
 		return 0;
 
-	if (board_type == C930)
-		return init_c930(hw_config);
+	switch (hw_config->irq) {
+	case 7:
+		bits = 8;
+		break;
+	case 9:
+		bits = 0x10;
+		break;
+	case 10:
+		bits = 0x18;
+		break;
+	case 12:
+		bits = 0x20;
+		break;
+	case 5:	/* Also IRQ5 is possible on C930 */
+		if (board_type == C930 || c924pnp) {
+			bits = 0x28;
+			break;
+		}
+	default:
+		printk(KERN_ERR "MAD16/Mozart: Bad IRQ %d\n", hw_config->irq);
+		return 0;
+	}
+
+	ports = request_region(hw_config->io_base + 4, 4, "ad1848");
+	if (!ports) {
+		printk(KERN_ERR "MSS: I/O port conflict\n");
+		return 0;
+	}
+	if (!request_region(hw_config->io_base, 4, "mad16 WSS config")) {
+		release_region(hw_config->io_base + 4, 4);
+		printk(KERN_ERR "MSS: I/O port conflict\n");
+		return 0;
+	}
 
+	if (board_type == C930) {
+		init_c930(hw_config, base);
+		goto got_it;
+	}
 
 	for (i = 0xf8d; i <= 0xf93; i++) {
 		if (!c924pnp)
@@ -547,20 +565,7 @@
  */
 
 	tmp = (mad_read(MC1_PORT) & 0x0f) | 0x80;	/* Enable WSS, Disable SB */
-
-	for (i = 0; i < 5; i++)
-	{
-		if (i > 3)	/* Not a valid port */
-		{
-			printk(KERN_ERR "MAD16/Mozart: Bad WSS base address 0x%x\n", hw_config->io_base);
-			return 0;
-		}
-		if (valid_ports[i] == hw_config->io_base)
-		{
-			tmp |= i << 4;	/* WSS port select bits */
-			break;
-		}
-	}
+	tmp |= base << 4;	/* WSS port select bits */
 
 	/*
 	 * Set optional CD-ROM and joystick settings.
@@ -580,8 +585,8 @@
 		mad_write(MC5_PORT, 0x05);
 		mad_write(MC6_PORT, 0x03);
 	}
-	if (!ad1848_detect(hw_config->io_base + 4, &ad_flags, mad16_osp))
-		return 0;
+	if (!ad1848_detect(ports, &ad_flags, mad16_osp))
+		goto fail;
 
 	if (ad_flags & (AD_F_CS4231 | AD_F_CS4248))
 		cs4231_mode = 0x02;	/* CS4248/CS4231 sync delay switch */
@@ -604,43 +609,19 @@
 		else
 			DDB(printk("port %03x after init = %02x\n", i-0x80, mad_read(i)));
 	}
-	wss_init(hw_config);
 
-	return 1;
-}
+got_it:
+	ad_flags = 0;
+	if (!ad1848_detect(ports, &ad_flags, mad16_osp))
+		goto fail;
 
-static void __init attach_mad16(struct address_info *hw_config)
-{
-
-	static signed char     interrupt_bits[12] = {
-		-1, -1, -1, -1, -1, -1, -1, 0x08, -1, 0x10, 0x18, 0x20
-	};
-	signed char bits;
-
-	static char     dma_bits[4] = {
-		1, 2, 0, 3
-	};
-
-	int config_port = hw_config->io_base + 0, version_port = hw_config->io_base + 3;
-	int ad_flags = 0, dma = hw_config->dma, dma2 = hw_config->dma2;
-	unsigned char dma2_bit = 0;
-
-	already_initialized = 1;
-
-	if (!ad1848_detect(hw_config->io_base + 4, &ad_flags, mad16_osp))
-		return;
+	if (!wss_init(hw_config))
+		goto fail;
 
 	/*
 	 * Set the IRQ and DMA addresses.
 	 */
 	
-	if (board_type == C930 || c924pnp)
-		interrupt_bits[5] = 0x28;	/* Also IRQ5 is possible on C930 */
-
-	bits = interrupt_bits[hw_config->irq];
-	if (bits == -1)
-		return;
-
 	outb((bits | 0x40), config_port);
 	if ((inb(version_port) & 0x40) == 0)
 		printk(KERN_ERR "[IRQ Conflict?]\n");
@@ -675,27 +656,24 @@
 
 	outb((bits | dma_bits[dma] | dma2_bit), config_port);	/* Write IRQ+DMA setup */
 
-	hw_config->slots[0] = ad1848_init("mad16 WSS", hw_config->io_base + 4,
+	hw_config->slots[0] = ad1848_init("mad16 WSS", ports,
 					  hw_config->irq,
 					  dma,
 					  dma2, 0,
 					  hw_config->osp,
 					  THIS_MODULE);
-	request_region(hw_config->io_base, 4, "mad16 WSS config");
+	return 1;
+
+fail:
+	release_region(hw_config->io_base + 4, 4);
+	release_region(hw_config->io_base, 4);
+	return 0;
 }
 
 static int __init probe_mad16_mpu(struct address_info *hw_config)
 {
-	static int mpu_attached;
 	unsigned char tmp;
 
-	if (!already_initialized)	/* The MSS port must be initialized first */
-		return 0;
-
-	if (mpu_attached)		/* Don't let them call this twice */
-		return 0;
-	mpu_attached = 1;
-
 	if (board_type < C929)	/* Early chip. No MPU support. Just SB MIDI */
 	{
 
@@ -732,8 +710,12 @@
 
 		mad_write(MC3_PORT, tmp | 0x04);
 		hw_config->driver_use_1 = SB_MIDI_ONLY;
-		if (!sb_dsp_detect(hw_config, 0, 0, NULL))
+		if (!request_region(hw_config->io_base, 16, "soundblaster"))
+			return 0;
+		if (!sb_dsp_detect(hw_config, 0, 0, NULL)) {
+			release_region(hw_config->io_base, 16);
 			return 0;
+		}
 
 		if (mad_read(MC1_PORT) & 0x20)
 			hw_config->io_base = 0x240;
@@ -1031,15 +1013,18 @@
 		printk(KERN_ERR "I/O, DMA and irq are mandatory\n");
 		return -EINVAL;
 	}
-	
-	if (!probe_mad16(&cfg))
+
+	if (!request_region(MC0_PORT, 12, "mad16"))
+		return -EBUSY;
+
+	if (!probe_mad16(&cfg)) {
+		release_region(MC0_PORT, 12);
 		return -ENODEV;
+	}
 
 	cfg_mpu.io_base = mpu_io;
 	cfg_mpu.irq = mpu_irq;
 
-	attach_mad16(&cfg);
-
 	found_mpu = probe_mad16_mpu(&cfg_mpu);
 
 	if (joystick == 1) {
@@ -1067,6 +1052,7 @@
 		release_region(0x201, 1);
 	}
 	unload_mad16(&cfg);
+	release_region(MC0_PORT, 12);
 }
 
 module_init(init_mad16);
diff -Nru a/sound/oss/maui.c b/sound/oss/maui.c
--- a/sound/oss/maui.c	2004-10-18 14:56:49 -07:00
+++ b/sound/oss/maui.c	2004-10-18 14:56:49 -07:00
@@ -301,17 +301,23 @@
 
 static int __init probe_maui(struct address_info *hw_config)
 {
+	struct resource *ports;
+	int this_dev;
 	int i;
 	int tmp1, tmp2, ret;
 
-	if (check_region(hw_config->io_base, 8))
+	ports = request_region(hw_config->io_base, 2, "mpu401");
+	if (!ports)
 		return 0;
 
+	if (!request_region(hw_config->io_base + 2, 6, "Maui"))
+		goto out;
+
 	maui_base = hw_config->io_base;
 	maui_osp = hw_config->osp;
 
 	if (request_irq(hw_config->irq, mauiintr, 0, "Maui", NULL) < 0)
-		return 0;
+		goto out2;
 
 	/*
 	 * Initialize the processor if necessary
@@ -322,36 +328,30 @@
 			!maui_write(0x9F) ||	/* Report firmware version */
 			!maui_short_wait(STAT_RX_AVAIL) ||
 			maui_read() == -1 || maui_read() == -1)
-			if (!maui_init(hw_config->irq)) {
-				free_irq(hw_config->irq, NULL);
-				return 0;
-			}
+			if (!maui_init(hw_config->irq))
+				goto out3;
 	}
 	if (!maui_write(0xCF))	/* Report hardware version */ {
 		printk(KERN_ERR "No WaveFront firmware detected (card uninitialized?)\n");
-		free_irq(hw_config->irq, NULL);
-		return 0;
+		goto out3;
 	}
 	if ((tmp1 = maui_read()) == -1 || (tmp2 = maui_read()) == -1) {
 		printk(KERN_ERR "No WaveFront firmware detected (card uninitialized?)\n");
-		free_irq(hw_config->irq, NULL);
-		return 0;
-	}
-	if (tmp1 == 0xff || tmp2 == 0xff) {
-		free_irq(hw_config->irq, NULL);
-		return 0;
+		goto out3;
 	}
+	if (tmp1 == 0xff || tmp2 == 0xff)
+		goto out3;
 	printk(KERN_DEBUG "WaveFront hardware version %d.%d\n", tmp1, tmp2);
 
 	if (!maui_write(0x9F))	/* Report firmware version */
-		return 0;
+		goto out3;
 	if ((tmp1 = maui_read()) == -1 || (tmp2 = maui_read()) == -1)
-		return 0;
+		goto out3;
 
 	printk(KERN_DEBUG "WaveFront firmware version %d.%d\n", tmp1, tmp2);
 
 	if (!maui_write(0x85))	/* Report free DRAM */
-		return 0;
+		goto out3;
 	tmp1 = 0;
 	for (i = 0; i < 4; i++) {
 		tmp1 |= maui_read() << (7 * i);
@@ -359,20 +359,12 @@
 	printk(KERN_DEBUG "Available DRAM %dk\n", tmp1 / 1024);
 
 	for (i = 0; i < 1000; i++)
-		if (probe_mpu401(hw_config))
+		if (probe_mpu401(hw_config, ports))
 			break;
 
-	ret = probe_mpu401(hw_config);
-
-	if (ret)
-		request_region(hw_config->io_base + 2, 6, "Maui");
-
-	return ret;
-}
-
-static void __init attach_maui(struct address_info *hw_config)
-{
-	int this_dev;
+	ret = probe_mpu401(hw_config, ports);
+	if (!ret)
+		goto out3;
 
 	conf_printf("Maui", hw_config);
 
@@ -391,14 +383,22 @@
 		 */
 
 		synth = midi_devs[this_dev]->converter;
-		synth->id = "MAUI";
-
 		if (synth != NULL) {
+			synth->id = "MAUI";
 			orig_load_patch = synth->load_patch;
 			synth->load_patch = &maui_load_patch;
 		} else
 			printk(KERN_ERR "Maui: Can't install patch loader\n");
 	}
+	return 1;
+
+out3:
+	free_irq(hw_config->irq, NULL);
+out2:
+	release_region(hw_config->io_base + 2, 6);
+out:
+	release_region(hw_config->io_base, 2);
+	return 0;
 }
 
 static void __exit unload_maui(struct address_info *hw_config)
@@ -445,7 +445,6 @@
 	}
 	if (probe_maui(&cfg) == 0)
 		return -ENODEV;
-	attach_maui(&cfg);
 
 	return 0;
 }
diff -Nru a/sound/oss/mpu401.c b/sound/oss/mpu401.c
--- a/sound/oss/mpu401.c	2004-10-18 14:57:03 -07:00
+++ b/sound/oss/mpu401.c	2004-10-18 14:57:03 -07:00
@@ -1026,12 +1026,6 @@
 			spin_unlock_irqrestore(&devc->lock,flags);
 	}
 
-	if (!request_region(hw_config->io_base, 2, "mpu401"))
-	{
-		ret = -ENOMEM;
-		goto out_irq;
-	}	
-
 	if (devc->version != 0)
 		if (mpu_cmd(m, 0xC5, 0) >= 0)	/* Set timebase OK */
 			if (mpu_cmd(m, 0xE0, 120) >= 0)		/* Set tempo OK */
@@ -1044,7 +1038,7 @@
 	{
 		printk(KERN_ERR "mpu401: Can't allocate memory\n");
 		ret = -ENOMEM;
-		goto out_resource;
+		goto out_irq;
 	}
 	if (!(devc->capabilities & MPU_CAP_INTLG))	/* No intelligent mode */
 	{
@@ -1126,13 +1120,12 @@
 	
 	return 0;
 
-out_resource:
-	release_region(hw_config->io_base, 2);
 out_irq:
 	free_irq(devc->irq, (void *)m);
 out_mididev:
 	sound_unload_mididev(m);
 out_err:
+	release_region(hw_config->io_base, 2);
 	return ret;
 }
 
@@ -1207,16 +1200,11 @@
 
 }
 
-int probe_mpu401(struct address_info *hw_config)
+int probe_mpu401(struct address_info *hw_config, struct resource *ports)
 {
 	int ok = 0;
 	struct mpu_config tmp_devc;
 
-	if (check_region(hw_config->io_base, 2))
-	{
-		printk(KERN_ERR "mpu401: I/O port %x already in use\n\n", hw_config->io_base);
-		return 0;
-	}
 	tmp_devc.base = hw_config->io_base;
 	tmp_devc.irq = hw_config->irq;
 	tmp_devc.initialized = 0;
@@ -1791,10 +1779,16 @@
 	/* Can be loaded either for module use or to provide functions
 	   to others */
 	if (io != -1 && irq != -1) {
+		struct resource *ports;
 	        cfg.irq = irq;
 		cfg.io_base = io;
-		if (probe_mpu401(&cfg) == 0)
+		ports = request_region(io, 2, "mpu401");
+		if (!ports)
+			return -EBUSY;
+		if (probe_mpu401(&cfg, ports) == 0) {
+			release_region(io, 2);
 			return -ENODEV;
+		}
 		if ((ret = attach_mpu401(&cfg, THIS_MODULE)))
 			return ret;
 	}
diff -Nru a/sound/oss/mpu401.h b/sound/oss/mpu401.h
--- a/sound/oss/mpu401.h	2004-10-18 14:56:29 -07:00
+++ b/sound/oss/mpu401.h	2004-10-18 14:56:29 -07:00
@@ -6,7 +6,7 @@
 irqreturn_t uart401intr (int irq, void *dev_id, struct pt_regs * dummy);
 
 /*	From mpu401.c */
-int probe_mpu401(struct address_info *hw_config);
+int probe_mpu401(struct address_info *hw_config, struct resource *ports);
 int attach_mpu401(struct address_info * hw_config, struct module *owner);
 void unload_mpu401(struct address_info *hw_info);
 
diff -Nru a/sound/oss/msnd.c b/sound/oss/msnd.c
--- a/sound/oss/msnd.c	2004-10-18 14:56:28 -07:00
+++ b/sound/oss/msnd.c	2004-10-18 14:56:28 -07:00
@@ -207,7 +207,7 @@
 	register int timeout = 1000;
     
 	while(timeout-- > 0)
-		if (inb(io + HP_ISR) & HPISR_TXDE)
+		if (msnd_inb(io + HP_ISR) & HPISR_TXDE)
 			return 0;
 
 	return -EIO;
@@ -219,7 +219,7 @@
 	register int timeout = 1000;
 
 	while(timeout-- > 0)
-		if (!(inb(io + HP_CVR) & HPCVR_HC))
+		if (!(msnd_inb(io + HP_CVR) & HPCVR_HC))
 			return 0;
 
 	return -EIO;
@@ -231,7 +231,7 @@
 
 	spin_lock_irqsave(&dev->lock, flags);
 	if (msnd_wait_HC0(dev) == 0) {
-		outb(cmd, dev->io + HP_CVR);
+		msnd_outb(cmd, dev->io + HP_CVR);
 		spin_unlock_irqrestore(&dev->lock, flags);
 		return 0;
 	}
@@ -248,9 +248,9 @@
 	register unsigned int io = dev->io;
 
 	if (msnd_wait_TXDE(dev) == 0) {
-		outb(high, io + HP_TXH);
-		outb(mid, io + HP_TXM);
-		outb(low, io + HP_TXL);
+		msnd_outb(high, io + HP_TXH);
+		msnd_outb(mid, io + HP_TXM);
+		msnd_outb(low, io + HP_TXL);
 		return 0;
 	}
 
@@ -272,8 +272,8 @@
 		if (msnd_send_word(dev, bin[i], bin[i + 1], bin[i + 2]) != 0)
 			return -EIO;
 
-	inb(dev->io + HP_RXL);
-	inb(dev->io + HP_CVR);
+	msnd_inb(dev->io + HP_RXL);
+	msnd_inb(dev->io + HP_CVR);
 
 	return 0;
 }
@@ -289,11 +289,11 @@
 
 	spin_lock_irqsave(&dev->lock, flags);
 	if (msnd_wait_TXDE(dev) == 0) {
-		outb(inb(dev->io + HP_ICR) | HPICR_TREQ, dev->io + HP_ICR);
+		msnd_outb(msnd_inb(dev->io + HP_ICR) | HPICR_TREQ, dev->io + HP_ICR);
 		if (dev->type == msndClassic)
-			outb(dev->irqid, dev->io + HP_IRQM);
-		outb(inb(dev->io + HP_ICR) & ~HPICR_TREQ, dev->io + HP_ICR);
-		outb(inb(dev->io + HP_ICR) | HPICR_RREQ, dev->io + HP_ICR);
+			msnd_outb(dev->irqid, dev->io + HP_IRQM);
+		msnd_outb(msnd_inb(dev->io + HP_ICR) & ~HPICR_TREQ, dev->io + HP_ICR);
+		msnd_outb(msnd_inb(dev->io + HP_ICR) | HPICR_RREQ, dev->io + HP_ICR);
 		enable_irq(dev->irq);
 		msnd_init_queue(dev->DSPQ, dev->dspq_data_buff, dev->dspq_buff_size);
 		spin_unlock_irqrestore(&dev->lock, flags);
@@ -320,9 +320,9 @@
 
 	spin_lock_irqsave(&dev->lock, flags);
 	if (msnd_wait_TXDE(dev) == 0) {
-		outb(inb(dev->io + HP_ICR) & ~HPICR_RREQ, dev->io + HP_ICR);
+		msnd_outb(msnd_inb(dev->io + HP_ICR) & ~HPICR_RREQ, dev->io + HP_ICR);
 		if (dev->type == msndClassic)
-			outb(HPIRQ_NONE, dev->io + HP_IRQM);
+			msnd_outb(HPIRQ_NONE, dev->io + HP_IRQM);
 		disable_irq(dev->irq);
 		spin_unlock_irqrestore(&dev->lock, flags);
 		return 0;
diff -Nru a/sound/oss/msnd.h b/sound/oss/msnd.h
--- a/sound/oss/msnd.h	2004-10-18 14:56:32 -07:00
+++ b/sound/oss/msnd.h	2004-10-18 14:56:32 -07:00
@@ -154,10 +154,11 @@
 #define DSPTOPC_BASED(w)	(((w) - DSP_BASE_ADDR) * 2)
 
 #ifdef SLOWIO
-#  undef outb
-#  undef inb
-#  define outb			outb_p
-#  define inb			inb_p
+#define msnd_outb			outb_p
+#define msnd_inb			inb_p
+#else
+#define msnd_outb			outb
+#define msnd_inb			inb
 #endif
 
 /* JobQueueStruct */
diff -Nru a/sound/oss/msnd_pinnacle.c b/sound/oss/msnd_pinnacle.c
--- a/sound/oss/msnd_pinnacle.c	2004-10-18 14:56:33 -07:00
+++ b/sound/oss/msnd_pinnacle.c	2004-10-18 14:56:33 -07:00
@@ -136,9 +136,9 @@
 
 	/* Critical section: bank 1 access */
 	spin_lock_irqsave(&dev.lock, flags);
-	outb(HPBLKSEL_1, dev.io + HP_BLKS);
+	msnd_outb(HPBLKSEL_1, dev.io + HP_BLKS);
 	isa_memset_io(dev.base, 0, DAR_BUFF_SIZE * 3);
-	outb(HPBLKSEL_0, dev.io + HP_BLKS);
+	msnd_outb(HPBLKSEL_0, dev.io + HP_BLKS);
 	spin_unlock_irqrestore(&dev.lock, flags);
 
 	for (n = 0, lpDAQ = dev.base + DARQ_DATA_BUFF; n < 3; ++n, lpDAQ += DAQDS__size) {
@@ -830,12 +830,12 @@
 
 	/* Read data from the head (unprotected bank 1 access okay
            since this is only called inside an interrupt) */
-	outb(HPBLKSEL_1, dev.io + HP_BLKS);
+	msnd_outb(HPBLKSEL_1, dev.io + HP_BLKS);
 	msnd_fifo_write(
 		&dev.DARF,
 		(char *)(dev.base + bank * DAR_BUFF_SIZE),
 		size);
-	outb(HPBLKSEL_0, dev.io + HP_BLKS);
+	msnd_outb(HPBLKSEL_0, dev.io + HP_BLKS);
 
 	return 1;
 }
@@ -1091,7 +1091,7 @@
 static irqreturn_t intr(int irq, void *dev_id, struct pt_regs *regs)
 {
 	/* Send ack to DSP */
-	inb(dev.io + HP_RXL);
+	msnd_inb(dev.io + HP_RXL);
 
 	/* Evaluate queued DSP messages */
 	while (isa_readw(dev.DSPQ + JQS_wTail) != isa_readw(dev.DSPQ + JQS_wHead)) {
@@ -1120,15 +1120,15 @@
 {
 	int timeout = 100;
 
-	outb(HPDSPRESET_ON, dev.io + HP_DSPR);
+	msnd_outb(HPDSPRESET_ON, dev.io + HP_DSPR);
 	mdelay(1);
 #ifndef MSND_CLASSIC
-	dev.info = inb(dev.io + HP_INFO);
+	dev.info = msnd_inb(dev.io + HP_INFO);
 #endif
-	outb(HPDSPRESET_OFF, dev.io + HP_DSPR);
+	msnd_outb(HPDSPRESET_OFF, dev.io + HP_DSPR);
 	mdelay(1);
 	while (timeout-- > 0) {
-		if (inb(dev.io + HP_CVR) == HP_CVR_DEF)
+		if (msnd_inb(dev.io + HP_CVR) == HP_CVR_DEF)
 			return 0;
 		mdelay(1);
 	}
@@ -1202,9 +1202,9 @@
 	unsigned long flags;
 
 #ifdef MSND_CLASSIC
-	outb(dev.memid, dev.io + HP_MEMM);
+	msnd_outb(dev.memid, dev.io + HP_MEMM);
 #endif
-	outb(HPBLKSEL_0, dev.io + HP_BLKS);
+	msnd_outb(HPBLKSEL_0, dev.io + HP_BLKS);
 	if (initted) {
 		mastVolLeft = isa_readw(dev.SMA + SMA_wCurrMastVolLeft);
 		mastVolRight = isa_readw(dev.SMA + SMA_wCurrMastVolRight);
@@ -1214,9 +1214,9 @@
 
 	/* Critical section: bank 1 access */
 	spin_lock_irqsave(&dev.lock, flags);
-	outb(HPBLKSEL_1, dev.io + HP_BLKS);
+	msnd_outb(HPBLKSEL_1, dev.io + HP_BLKS);
 	isa_memset_io(dev.base, 0, 0x8000);
-	outb(HPBLKSEL_0, dev.io + HP_BLKS);
+	msnd_outb(HPBLKSEL_0, dev.io + HP_BLKS);
 	spin_unlock_irqrestore(&dev.lock, flags);
 
 	dev.pwDSPQData = (dev.base + DSPQ_DATA_BUFF);
@@ -1289,7 +1289,7 @@
 
 static int upload_dsp_code(void)
 {
-	outb(HPBLKSEL_0, dev.io + HP_BLKS);
+	msnd_outb(HPBLKSEL_0, dev.io + HP_BLKS);
 #ifndef HAVE_DSPCODEH
 	INITCODESIZE = mod_firmware_load(INITCODEFILE, &INITCODE);
 	if (!INITCODE) {
@@ -1326,9 +1326,9 @@
 #ifdef MSND_CLASSIC
 static void reset_proteus(void)
 {
-	outb(HPPRORESET_ON, dev.io + HP_PROR);
+	msnd_outb(HPPRORESET_ON, dev.io + HP_PROR);
 	mdelay(TIME_PRO_RESET);
-	outb(HPPRORESET_OFF, dev.io + HP_PROR);
+	msnd_outb(HPPRORESET_OFF, dev.io + HP_PROR);
 	mdelay(TIME_PRO_RESET_DONE);
 }
 #endif
@@ -1338,8 +1338,8 @@
 	int err, timeout;
 
 #ifdef MSND_CLASSIC
-	outb(HPWAITSTATE_0, dev.io + HP_WAIT);
-	outb(HPBITMODE_16, dev.io + HP_BITM);
+	msnd_outb(HPWAITSTATE_0, dev.io + HP_WAIT);
+	msnd_outb(HPBITMODE_16, dev.io + HP_BITM);
 
 	reset_proteus();
 #endif
@@ -1455,9 +1455,9 @@
 
 static int __init msnd_write_cfg(int cfg, int reg, int value)
 {
-	outb(reg, cfg);
-	outb(value, cfg + 1);
-	if (value != inb(cfg + 1)) {
+	msnd_outb(reg, cfg);
+	msnd_outb(value, cfg + 1);
+	if (value != msnd_inb(cfg + 1)) {
 		printk(KERN_ERR LOGNAME ": msnd_write_cfg: I/O error\n");
 		return -EIO;
 	}
diff -Nru a/sound/oss/nec_vrc5477.c b/sound/oss/nec_vrc5477.c
--- a/sound/oss/nec_vrc5477.c	2004-10-18 14:56:49 -07:00
+++ b/sound/oss/nec_vrc5477.c	2004-10-18 14:56:49 -07:00
@@ -82,7 +82,6 @@
 #include <asm/io.h>
 #include <asm/dma.h>
 #include <asm/uaccess.h>
-#include <asm/hardirq.h>
 
 /* -------------------debug macros -------------------------------------- */
 /* #undef VRC5477_AC97_DEBUG */
diff -Nru a/sound/oss/opl3sa.c b/sound/oss/opl3sa.c
--- a/sound/oss/opl3sa.c	2004-10-18 14:56:49 -07:00
+++ b/sound/oss/opl3sa.c	2004-10-18 14:56:49 -07:00
@@ -36,10 +36,7 @@
 static int sb_initialized;
 #endif
 
-static int kilroy_was_here;	/* Don't detect twice */
-static int mpu_initialized;
 static spinlock_t lock=SPIN_LOCK_UNLOCKED;
-static int *opl3sa_osp;
 
 static unsigned char opl3sa_read(int addr)
 {
@@ -106,26 +103,16 @@
  *     OPL3-SA
  */
 
-static int __init probe_opl3sa_wss(struct address_info *hw_config)
+static int __init probe_opl3sa_wss(struct address_info *hw_config, struct resource *ports)
 {
-	int ret;
 	unsigned char tmp = 0x24;	/* WSS enable */
 
-	if (check_region(0xf86, 2))	/* Control port is busy */
-		return 0;
 	/*
 	 * Check if the IO port returns valid signature. The original MS Sound
 	 * system returns 0x04 while some cards (OPL3-SA for example)
 	 * return 0x00.
 	 */
 
-	if (check_region(hw_config->io_base, 8))
-	{
-		printk(KERN_ERR "OPL3-SA: MSS I/O port conflict (%x)\n", hw_config->io_base);
-		return 0;
-	}
-	opl3sa_osp = hw_config->osp;
-
 	if (!opl3sa_detect())
 	{
 		printk(KERN_ERR "OSS: OPL3-SA chip not found\n");
@@ -152,21 +139,16 @@
 	}
 
 	opl3sa_write(0x01, tmp);	/* WSS setup register */
-	kilroy_was_here = 1;
 
-	ret = probe_ms_sound(hw_config);
-	if (ret)
-		request_region(0xf86, 2, "OPL3-SA");
-
-	return ret;
+	return probe_ms_sound(hw_config, ports);
 }
 
-static void __init attach_opl3sa_wss(struct address_info *hw_config)
+static void __init attach_opl3sa_wss(struct address_info *hw_config, struct resource *ports)
 {
 	int nm = num_mixers;
 
 	/* FIXME */
-	attach_ms_sound(hw_config, THIS_MODULE);
+	attach_ms_sound(hw_config, ports, THIS_MODULE);
 	if (num_mixers > nm)	/* A mixer was installed */
 	{
 		AD1848_REROUTE(SOUND_MIXER_LINE1, SOUND_MIXER_CD);
@@ -183,14 +165,6 @@
 		-1, -1, -1, -1, -1, 1, -1, 2, -1, 3, 4
 	};
 
-	if (!kilroy_was_here)
-		return 0;	/* OPL3-SA has not been detected earlier */
-
-	if (mpu_initialized)
-	{
-		DDB(printk("OPL3-SA: MPU mode already initialized\n"));
-		return 0;
-	}
 	if (hw_config->irq > 10)
 	{
 		printk(KERN_ERR "OPL3-SA: Bad MPU IRQ %d\n", hw_config->irq);
@@ -224,7 +198,6 @@
 
 	opl3sa_write(0x03, conf);
 
-	mpu_initialized = 1;
 	hw_config->name = "OPL3-SA (MPU401)";
 
 	return probe_uart401(hw_config, THIS_MODULE);
@@ -281,6 +254,7 @@
 
 static int __init init_opl3sa(void)
 {
+	struct resource *ports;
 	if (io == -1 || irq == -1 || dma == -1) {
 		printk(KERN_ERR "opl3sa: dma, irq and io must be set.\n");
 		return -EINVAL;
@@ -294,12 +268,31 @@
 	cfg_mpu.io_base = mpu_io;
 	cfg_mpu.irq = mpu_irq;
 
-	if (probe_opl3sa_wss(&cfg) == 0)
+	ports = request_region(io + 4, 4, "ad1848");
+	if (!ports)
+		return -EBUSY;
+
+	if (!request_region(0xf86, 2, "OPL3-SA"))/* Control port is busy */ {
+		release_region(io + 4, 4);
+		return 0;
+	}
+
+	if (!request_region(io, 4, "WSS config")) {
+		release_region(0x86, 2);
+		release_region(io + 4, 4);
+		return 0;
+	}
+
+	if (probe_opl3sa_wss(&cfg, ports) == 0) {
+		release_region(0xf86, 2);
+		release_region(io, 4);
+		release_region(io + 4, 4);
 		return -ENODEV;
+	}
 
 	found_mpu=probe_opl3sa_mpu(&cfg_mpu);
 
-	attach_opl3sa_wss(&cfg);
+	attach_opl3sa_wss(&cfg, ports);
 	return 0;
 }
 
diff -Nru a/sound/oss/opl3sa2.c b/sound/oss/opl3sa2.c
--- a/sound/oss/opl3sa2.c	2004-10-18 14:55:53 -07:00
+++ b/sound/oss/opl3sa2.c	2004-10-18 14:55:53 -07:00
@@ -539,36 +539,18 @@
  * Component probe, attach, unload functions
  */
 
-static inline int __init probe_opl3sa2_mpu(struct address_info* hw_config)
-{
-	return probe_mpu401(hw_config);
-}
-
-
-static inline int __init attach_opl3sa2_mpu(struct address_info* hw_config)
-{
-	return attach_mpu401(hw_config, THIS_MODULE);
-}
-
-
 static inline void __exit unload_opl3sa2_mpu(struct address_info *hw_config)
 {
 	unload_mpu401(hw_config);
 }
 
 
-static inline int __init probe_opl3sa2_mss(struct address_info* hw_config)
-{
-	return probe_ms_sound(hw_config);
-}
-
-
-static void __init attach_opl3sa2_mss(struct address_info* hw_config)
+static void __init attach_opl3sa2_mss(struct address_info* hw_config, struct resource *ports)
 {
 	int initial_mixers;
 
 	initial_mixers = num_mixers;
-	attach_ms_sound(hw_config, THIS_MODULE);	/* Slot 0 */
+	attach_ms_sound(hw_config, ports, THIS_MODULE);	/* Slot 0 */
 	if (hw_config->slots[0] != -1) {
 		/* Did the MSS driver install? */
 		if(num_mixers == (initial_mixers + 1)) {
@@ -957,6 +939,8 @@
 
 	for (card = 0; card < max; card++) {
 		/* If a user wants an I/O then assume they meant it */
+		struct resource *ports;
+		int base;
 		
 		if (!isapnp) {
 			if (io == -1 || irq == -1 || dma == -1 ||
@@ -995,17 +979,30 @@
 			opl3sa2_clear_slots(&opl3sa2_state[card].cfg_mpu);
 		}
 
+		/* FIXME: leak */
 		if (probe_opl3sa2(&opl3sa2_state[card].cfg, card))
 			return -ENODEV;
 
+		base = opl3sa2_state[card].cfg_mss.io_base;
 
-		if (!probe_opl3sa2_mss(&opl3sa2_state[card].cfg_mss)) {
+		if (!request_region(base, 4, "WSS config"))
+			goto failed;
+
+		ports = request_region(base + 4, 4, "ad1848");
+		if (!ports)
+			goto failed2;
+
+		if (!probe_ms_sound(&opl3sa2_state[card].cfg_mss, ports)) {
 			/*
 			 * If one or more cards are already registered, don't
 			 * return an error but print a warning.  Note, this
 			 * should never really happen unless the hardware or
 			 * ISA PnP screwed up.
 			 */
+			release_region(base + 4, 4);
+		failed2:
+			release_region(base, 4);
+		failed:
 			release_region(opl3sa2_state[card].cfg.io_base, 2);
 
 			if (opl3sa2_cards_num) {
@@ -1021,7 +1018,7 @@
 		attach_opl3sa2(&opl3sa2_state[card].cfg, card);
 		conf_printf(opl3sa2_state[card].chipset_name, &opl3sa2_state[card].cfg);
 		attach_opl3sa2_mixer(&opl3sa2_state[card].cfg, card);
-		attach_opl3sa2_mss(&opl3sa2_state[card].cfg_mss);
+		attach_opl3sa2_mss(&opl3sa2_state[card].cfg_mss, ports);
 
 		/* ewww =) */
 		opl3sa2_state[card].card = card;
@@ -1054,15 +1051,23 @@
 		
 		/* Attach MPU if we've been asked to do so, failure isn't fatal */
 		if (opl3sa2_state[card].cfg_mpu.io_base != -1) {
-			if (probe_opl3sa2_mpu(&opl3sa2_state[card].cfg_mpu)) {
-				if (attach_opl3sa2_mpu(&opl3sa2_state[card].cfg_mpu)) {
-					printk(KERN_ERR PFX "failed to attach MPU401\n");
-					opl3sa2_state[card].cfg_mpu.slots[1] = -1;
-				}
+			int base = opl3sa2_state[card].cfg_mpu.io_base;
+			struct resource *ports;
+			ports = request_region(base, 2, "mpu401");
+			if (!ports)
+				goto out;
+			if (!probe_mpu401(&opl3sa2_state[card].cfg_mpu, ports)) {
+				release_region(base, 2);
+				goto out;
+			}
+			if (attach_mpu401(&opl3sa2_state[card].cfg_mpu, THIS_MODULE)) {
+				printk(KERN_ERR PFX "failed to attach MPU401\n");
+				opl3sa2_state[card].cfg_mpu.slots[1] = -1;
 			}
 		}
 	}
 
+out:
 	if (isapnp) {
 		printk(KERN_NOTICE PFX "%d PnP card(s) found.\n", opl3sa2_cards_num);
 	}
diff -Nru a/sound/oss/pss.c b/sound/oss/pss.c
--- a/sound/oss/pss.c	2004-10-18 14:57:05 -07:00
+++ b/sound/oss/pss.c	2004-10-18 14:57:05 -07:00
@@ -149,6 +149,7 @@
 static int      nonstandard_microcode;
 static int	pss_cdrom_port = -1;	/* Parameter for the PSS cdrom port */
 static int	pss_enable_joystick;    /* Parameter for enabling the joystick */
+static coproc_operations pss_coproc_operations;
 
 static void pss_write(pss_confdata *devc, int data)
 {
@@ -174,7 +175,7 @@
  	printk(KERN_WARNING "PSS: DSP Command (%04x) Timeout.\n", data);
 }
 
-int __init probe_pss(struct address_info *hw_config)
+static int __init probe_pss(struct address_info *hw_config)
 {
 	unsigned short id;
 	int irq, dma;
@@ -188,13 +189,19 @@
 		if (devc->base != 0x230 && devc->base != 0x250)		/* Some cards use these */
 			return 0;
 
-	if (check_region(devc->base, 0x19 /*16*/)) { 
+	if (!request_region(devc->base, 0x10, "PSS mixer, SB emulation")) {
 		printk(KERN_ERR "PSS: I/O port conflict\n");
 		return 0;
 	}
 	id = inw(REG(PSS_ID));
 	if ((id >> 8) != 'E') {
 		printk(KERN_ERR "No PSS signature detected at 0x%x (0x%x)\n",  devc->base,  id); 
+		release_region(devc->base, 0x10);
+		return 0;
+	}
+	if (!request_region(devc->base + 0x10, 0x9, "PSS config")) {
+		printk(KERN_ERR "PSS: I/O port conflict\n");
+		release_region(devc->base, 0x10);
 		return 0;
 	}
 	return 1;
@@ -685,7 +692,7 @@
 	}
 }
 
-void __init attach_pss(struct address_info *hw_config)
+static int __init attach_pss(struct address_info *hw_config)
 {
 	unsigned short  id;
 	char tmp[100];
@@ -697,10 +704,7 @@
 	devc->ad_mixer_dev = NO_WSS_MIXER;
 
 	if (!probe_pss(hw_config))
-		return;
-
-	request_region(hw_config->io_base, 0x10, "PSS mixer, SB emulation");
-	request_region(hw_config->io_base + 0x10, 0x9, "PSS config");
+		return 0;
 
 	id = inw(REG(PSS_ID)) & 0x00ff;
 
@@ -714,17 +718,23 @@
 	if (sound_alloc_dma(hw_config->dma, "PSS"))
 	{
 		printk("pss.c: Can't allocate DMA channel.\n");
-		return;
+		release_region(hw_config->io_base, 0x10);
+		release_region(hw_config->io_base+0x10, 0x9);
+		return 0;
 	}
 	if (!set_irq(devc, CONF_PSS, devc->irq))
 	{
 		printk("PSS: IRQ allocation error.\n");
-		return;
+		release_region(hw_config->io_base, 0x10);
+		release_region(hw_config->io_base+0x10, 0x9);
+		return 0;
 	}
 	if (!set_dma(devc, CONF_PSS, devc->dma))
 	{
 		printk(KERN_ERR "PSS: DMA allocation error\n");
-		return;
+		release_region(hw_config->io_base, 0x10);
+		release_region(hw_config->io_base+0x10, 0x9);
+		return 0;
 	}
 #endif
 
@@ -732,39 +742,38 @@
 	pss_initialized = 1;
 	sprintf(tmp, "ECHO-PSS  Rev. %d", id);
 	conf_printf(tmp, hw_config);
+	return 1;
 }
 
-int __init probe_pss_mpu(struct address_info *hw_config)
+static int __init probe_pss_mpu(struct address_info *hw_config)
 {
+	struct resource *ports;
 	int timeout;
 
 	if (!pss_initialized)
 		return 0;
 
-	if (check_region(hw_config->io_base, 2))
-	{
+	ports = request_region(hw_config->io_base, 2, "mpu401");
+
+	if (!ports) {
 		printk(KERN_ERR "PSS: MPU I/O port conflict\n");
 		return 0;
 	}
-	if (!set_io_base(devc, CONF_MIDI, hw_config->io_base))
-	{
-		  printk(KERN_ERR "PSS: MIDI base could not be set.\n");
-		  return 0;
+	if (!set_io_base(devc, CONF_MIDI, hw_config->io_base)) {
+		printk(KERN_ERR "PSS: MIDI base could not be set.\n");
+		goto fail;
+	}
+	if (!set_irq(devc, CONF_MIDI, hw_config->irq)) {
+		printk(KERN_ERR "PSS: MIDI IRQ allocation error.\n");
+		goto fail;
 	}
-	if (!set_irq(devc, CONF_MIDI, hw_config->irq))
-	{
-		  printk(KERN_ERR "PSS: MIDI IRQ allocation error.\n");
-		  return 0;
-	}
-	if (!pss_synthLen)
-	{
+	if (!pss_synthLen) {
 		printk(KERN_ERR "PSS: Can't enable MPU. MIDI synth microcode not available.\n");
-		return 0;
+		goto fail;
 	}
-	if (!pss_download_boot(devc, pss_synth, pss_synthLen, CPF_FIRST | CPF_LAST))
-	{
+	if (!pss_download_boot(devc, pss_synth, pss_synthLen, CPF_FIRST | CPF_LAST)) {
 		printk(KERN_ERR "PSS: Unable to load MIDI synth microcode to DSP.\n");
-		return 0;
+		goto fail;
 	}
 
 	/*
@@ -780,7 +789,16 @@
 			break;	/* No more input */
 	}
 
-	return probe_mpu401(hw_config);
+	if (!probe_mpu401(hw_config, ports))
+		goto fail;
+
+	attach_mpu401(hw_config, THIS_MODULE);	/* Slot 1 */
+	if (hw_config->slots[1] != -1)	/* The MPU driver installed itself */
+		midi_devs[hw_config->slots[1]]->coproc = &pss_coproc_operations;
+	return 1;
+fail:
+	release_region(hw_config->io_base, 2);
+	return 0;
 }
 
 static int pss_coproc_open(void *dev_info, int sub_device)
@@ -1021,39 +1039,36 @@
 	&pss_data
 };
 
-static void __init attach_pss_mpu(struct address_info *hw_config)
-{
-	attach_mpu401(hw_config, THIS_MODULE);	/* Slot 1 */
-	if (hw_config->slots[1] != -1)	/* The MPU driver installed itself */
-		midi_devs[hw_config->slots[1]]->coproc = &pss_coproc_operations;
-}
-
 static int __init probe_pss_mss(struct address_info *hw_config)
 {
 	volatile int timeout;
+	struct resource *ports;
+	int        my_mix = -999;	/* gcc shut up */
 
 	if (!pss_initialized)
 		return 0;
 
-	if (check_region(hw_config->io_base, 8))
-	{
-		  printk(KERN_ERR "PSS: WSS I/O port conflicts.\n");
-		  return 0;
+	if (!request_region(hw_config->io_base, 4, "WSS config")) {
+		printk(KERN_ERR "PSS: WSS I/O port conflicts.\n");
+		return 0;
 	}
-	if (!set_io_base(devc, CONF_WSS, hw_config->io_base))
-	{
-		printk("PSS: WSS base not settable.\n");
+	ports = request_region(hw_config->io_base + 4, 4, "ad1848");
+	if (!ports) {
+		printk(KERN_ERR "PSS: WSS I/O port conflicts.\n");
+		release_region(hw_config->io_base, 4);
 		return 0;
 	}
-	if (!set_irq(devc, CONF_WSS, hw_config->irq))
-	{
+	if (!set_io_base(devc, CONF_WSS, hw_config->io_base)) {
+		printk("PSS: WSS base not settable.\n");
+		goto fail;
+	}
+	if (!set_irq(devc, CONF_WSS, hw_config->irq)) {
 		printk("PSS: WSS IRQ allocation error.\n");
-		return 0;
+		goto fail;
 	}
-	if (!set_dma(devc, CONF_WSS, hw_config->dma))
-	{
+	if (!set_dma(devc, CONF_WSS, hw_config->dma)) {
 		printk(KERN_ERR "PSS: WSS DMA allocation error\n");
-		return 0;
+		goto fail;
 	}
 	/*
 	 * For some reason the card returns 0xff in the WSS status register
@@ -1071,13 +1086,9 @@
 	  (timeout < 100000); timeout++)
 		;
 
-	return probe_ms_sound(hw_config);
-}
+	if (!probe_ms_sound(hw_config, ports))
+		goto fail;
 
-static void __init attach_pss_mss(struct address_info *hw_config)
-{
-	int        my_mix = -999;	/* gcc shut up */
-	
 	devc->ad_mixer_dev = NO_WSS_MIXER;
 	if (pss_mixer) 
 	{
@@ -1088,11 +1099,11 @@
 			devc)) < 0) 
 		{
 			printk(KERN_ERR "Could not install PSS mixer\n");
-			return;
+			goto fail;
 		}
 	}
 	pss_mixer_reset(devc);
-	attach_ms_sound(hw_config, THIS_MODULE);	/* Slot 0 */
+	attach_ms_sound(hw_config, ports, THIS_MODULE);	/* Slot 0 */
 
 	if (hw_config->slots[0] != -1)
 	{
@@ -1104,6 +1115,11 @@
 			devc->ad_mixer_dev = audio_devs[hw_config->slots[0]]->mixer_dev;
 		}
 	}
+	return 1;
+fail:
+	release_region(hw_config->io_base + 4, 4);
+	release_region(hw_config->io_base, 4);
+	return 0;
 }
 
 static inline void __exit unload_pss(struct address_info *hw_config)
@@ -1185,6 +1201,8 @@
 		printk(KERN_INFO "PSS: loading in no sound mode.\n");
 		disable_all_emulations();
 		configure_nonsound_components();
+		release_region(pss_io, 0x10);
+		release_region(pss_io + 0x10, 0x9);
 		return 0;
 	}
 
@@ -1206,20 +1224,16 @@
 		fw_load = 1;
 		pss_synthLen = mod_firmware_load(pss_firmware, (void *) &pss_synth);
 	}
-	if (!probe_pss(&cfg))
+	if (!attach_pss(&cfg))
 		return -ENODEV;
-	attach_pss(&cfg);
 	/*
 	 *    Attach stuff
 	 */
-	if (probe_pss_mpu(&cfg_mpu)) {
+	if (probe_pss_mpu(&cfg_mpu))
 		pssmpu = 1;
-		attach_pss_mpu(&cfg_mpu);
-	}
-	if (probe_pss_mss(&cfg2)) {
+
+	if (probe_pss_mss(&cfg2))
 		pssmss = 1;
-		attach_pss_mss(&cfg2);
-	}
 
 	return 0;
 }
diff -Nru a/sound/oss/rme96xx.c b/sound/oss/rme96xx.c
--- a/sound/oss/rme96xx.c	2004-10-18 14:56:28 -07:00
+++ b/sound/oss/rme96xx.c	2004-10-18 14:56:28 -07:00
@@ -54,7 +54,7 @@
 #include <linux/smp_lock.h>
 #include <linux/delay.h>
 #include <linux/slab.h>
-#include <asm/hardirq.h>
+#include <linux/interrupt.h>
 #include <linux/init.h>
 #include <linux/interrupt.h>
 #include <linux/poll.h>
diff -Nru a/sound/oss/sb_card.c b/sound/oss/sb_card.c
--- a/sound/oss/sb_card.c	2004-10-18 14:56:33 -07:00
+++ b/sound/oss/sb_card.c	2004-10-18 14:56:33 -07:00
@@ -100,7 +100,14 @@
 /* OSS subsystem card registration shared by PnP and legacy routines */
 static int sb_register_oss(struct sb_card_config *scc, struct sb_module_options *sbmo)
 {
-	if(!sb_dsp_detect(&scc->conf, 0, 0, sbmo)) {
+	if (!request_region(scc->conf.io_base, 16, "soundblaster")) {
+		printk(KERN_ERR "sb: ports busy.\n");
+		kfree(scc);
+		return -EBUSY;
+	}
+
+	if (!sb_dsp_detect(&scc->conf, 0, 0, sbmo)) {
+		release_region(scc->conf.io_base, 16);
 		printk(KERN_ERR "sb: Failed DSP Detect.\n");
 		kfree(scc);
 		return -ENODEV;
diff -Nru a/sound/oss/sb_common.c b/sound/oss/sb_common.c
--- a/sound/oss/sb_common.c	2004-10-18 14:55:54 -07:00
+++ b/sound/oss/sb_common.c	2004-10-18 14:55:54 -07:00
@@ -520,13 +520,6 @@
 	 */
 	
 	DDB(printk("sb_dsp_detect(%x) entered\n", hw_config->io_base));
-	if (check_region(hw_config->io_base, 16))
-	{
-#ifdef MODULE
-		printk(KERN_INFO "sb: I/O region in use.\n");
-#endif
-		return 0;
-	}
 
 	devc->lock = SPIN_LOCK_UNLOCKED;
 	devc->type = hw_config->card_subtype;
@@ -668,6 +661,7 @@
 	if (devc->base != hw_config->io_base)
 	{
 		DDB(printk("I/O port mismatch\n"));
+		release_region(devc->base, 16);
 		return 0;
 	}
 	/*
@@ -689,6 +683,7 @@
 		if (request_irq(hw_config->irq, sbintr, i, "soundblaster", devc) < 0)
 		{
 			printk(KERN_ERR "SB: Can't allocate IRQ%d\n", hw_config->irq);
+			release_region(devc->base, 16);
 			return 0;
 		}
 		devc->irq_ok = 0;
@@ -697,6 +692,7 @@
 			if (!sb16_set_irq_hw(devc, devc->irq))	/* Unsupported IRQ */
 			{
 				free_irq(devc->irq, devc);
+				release_region(devc->base, 16);
 				return 0;
 			}
 		if ((devc->type == 0 || devc->type == MDL_ESS) &&
@@ -735,7 +731,6 @@
 			}
 		}
 	}			/* IRQ setup */
-	request_region(hw_config->io_base, 16, "soundblaster");
 
 	last_sb = devc;
 	
@@ -1224,17 +1219,22 @@
 #if defined(CONFIG_SOUND_MPU401)
 	if (devc->model == MDL_ESS)
 	{
-		if (check_region(hw_config->io_base, 2))
-		{
+		struct resource *ports;
+		ports = request_region(hw_config->io_base, 2, "mpu401");
+		if (!ports) {
 			printk(KERN_ERR "sbmpu: I/O port conflict (%x)\n", hw_config->io_base);
 			return 0;
 		}
-		if (!ess_midi_init(devc, hw_config))
+		if (!ess_midi_init(devc, hw_config)) {
+			release_region(hw_config->io_base, 2);
 			return 0;
+		}
 		hw_config->name = "ESS1xxx MPU";
 		devc->midi_irq_cookie = NULL;
-		if (!probe_mpu401(hw_config))
+		if (!probe_mpu401(hw_config, ports)) {
+			release_region(hw_config->io_base, 2);
 			return 0;
+		}
 		attach_mpu401(hw_config, owner);
 		if (last_sb->irq == -hw_config->irq)
 			last_sb->midi_irq_cookie=(void *)hw_config->slots[1];
diff -Nru a/sound/oss/sgalaxy.c b/sound/oss/sgalaxy.c
--- a/sound/oss/sgalaxy.c	2004-10-18 14:56:48 -07:00
+++ b/sound/oss/sgalaxy.c	2004-10-18 14:56:48 -07:00
@@ -86,19 +86,31 @@
 
 static int __init probe_sgalaxy( struct address_info *ai )
 {
-	if ( check_region( ai->io_base, 8 ) ) {
+	struct resource *ports;
+	int n;
+
+	if (!request_region(ai->io_base, 4, "WSS config")) {
 		printk(KERN_ERR "sgalaxy: WSS IO port 0x%03x not available\n", ai->io_base);
 		return 0;
 	}
-        
-	if ( ad1848_detect( ai->io_base+4, NULL, ai->osp ) )
-		return probe_ms_sound(ai);  /* The card is already active, check irq etc... */
 
-	if ( check_region( ai->ai_sgbase, 0x10 ) ) {
+	ports = request_region(ai->io_base + 4, 4, "ad1848");
+	if (!ports) {
+		printk(KERN_ERR "sgalaxy: WSS IO port 0x%03x not available\n", ai->io_base);
+		release_region(ai->io_base, 4);
+		return 0;
+	}
+
+	if (!request_region( ai->ai_sgbase, 0x10, "SoundGalaxy SB")) {
 		printk(KERN_ERR "sgalaxy: SB IO port 0x%03x not available\n", ai->ai_sgbase);
+		release_region(ai->io_base + 4, 4);
+		release_region(ai->io_base, 4);
 		return 0;
 	}
         
+	if (ad1848_detect(ports, NULL, ai->osp))
+		goto out;  /* The card is already active, check irq etc... */
+        
 	/* switch to MSS/WSS mode */
    
 	sb_rst( ai->ai_sgbase );
@@ -108,16 +120,15 @@
 
 	sleep( HZ/10 );
 
-      	return probe_ms_sound(ai);
-}
+out:
+      	if (!probe_ms_sound(ai, ports)) {
+		release_region(ai->io_base + 4, 4);
+		release_region(ai->io_base, 4);
+		release_region(ai->ai_sgbase, 0x10);
+		return 0;
+	}
 
-static void __init attach_sgalaxy( struct address_info *ai )
-{
-	int n;
-	
-	request_region( ai->ai_sgbase, 0x10, "SoundGalaxy SB" );
- 
-	attach_ms_sound(ai, THIS_MODULE);
+	attach_ms_sound(ai, ports, THIS_MODULE);
 	n=ai->slots[0];
 	
 	if (n!=-1 && audio_devs[n]->mixer_dev != -1 ) {
@@ -125,6 +136,7 @@
 		AD1848_REROUTE( SOUND_MIXER_LINE2, SOUND_MIXER_SYNTH );  /* FM+Wavetable*/
 		AD1848_REROUTE( SOUND_MIXER_LINE3, SOUND_MIXER_CD );     /* CD */
 	}
+	return 1;
 }
 
 static void __exit unload_sgalaxy( struct address_info *ai )
@@ -162,8 +174,6 @@
 
 	if ( probe_sgalaxy(&cfg) == 0 )
 		return -ENODEV;
-
-	attach_sgalaxy(&cfg);
 
 	return 0;
 }
diff -Nru a/sound/oss/sscape.c b/sound/oss/sscape.c
--- a/sound/oss/sscape.c	2004-10-18 14:56:33 -07:00
+++ b/sound/oss/sscape.c	2004-10-18 14:56:33 -07:00
@@ -600,10 +600,10 @@
 	&adev_info
 };
 
-static int sscape_detected;
+static struct resource *sscape_ports;
 static int sscape_is_pnp;
 
-void __init attach_sscape(struct address_info *hw_config)
+static void __init attach_sscape(struct address_info *hw_config)
 {
 #ifndef SSCAPE_REGS
 	/*
@@ -638,10 +638,6 @@
 
 	int i, irq_bits = 0xff;
 
-	if (sscape_detected != hw_config->io_base)
-		return;
-
-	request_region(devc->base + 2, 6, "SoundScape");
 	if (old_hardware)
 	{
 		valid_interrupts = valid_interrupts_old;
@@ -650,7 +646,7 @@
 	else
 		conf_printf("Ensoniq SoundScape", hw_config);
 
-	for (i = 0; i < sizeof(valid_interrupts); i++)
+	for (i = 0; i < 4; i++)
 	{
 		if (hw_config->irq == valid_interrupts[i])
 		{
@@ -661,45 +657,32 @@
 	if (hw_config->irq > 15 || (regs[4] = irq_bits == 0xff))
 	{
 		printk(KERN_ERR "Invalid IRQ%d\n", hw_config->irq);
+		release_region(devc->base, 2);
+		release_region(devc->base + 2, 6);
+		if (sscape_is_pnp)
+			release_region(devc->codec, 2);
 		return;
 	}
 	
 	if (!sscape_is_pnp) {
 	
 		spin_lock_irqsave(&devc->lock,flags);
-	    for (i = 1; i < 10; i++)
-	    {
-		switch (i)
-		{
-			case 1:	/* Host interrupt enable */
-				sscape_write(devc, i, 0xf0);	/* All interrupts enabled */
-				break;
-
-			case 2:	/* DMA A status/trigger register */
-			case 3:	/* DMA B status/trigger register */
-				sscape_write(devc, i, 0x20);	/* DMA channel disabled */
-				break;
-
-			case 4:	/* Host interrupt config reg */
-				sscape_write(devc, i, 0xf0 | (irq_bits << 2) | irq_bits);
-				break;
-
-			case 5:	/* Don't destroy CD-ROM DMA config bits (0xc0) */
-				sscape_write(devc, i, (regs[i] & 0x3f) | (sscape_read(devc, i) & 0xc0));
-				break;
-
-			case 6:	/* CD-ROM config (WSS codec actually) */
-				sscape_write(devc, i, regs[i]);
-				break;
-
-			case 9:	/* Master control reg. Don't modify CR-ROM bits. Disable SB emul */
-				sscape_write(devc, i, (sscape_read(devc, i) & 0xf0) | 0x08);
-				break;
-
-			default:
-				sscape_write(devc, i, regs[i]);
-		}
-	    }
+		/* Host interrupt enable */
+		sscape_write(devc, 1, 0xf0);	/* All interrupts enabled */
+		/* DMA A status/trigger register */
+		sscape_write(devc, 2, 0x20);	/* DMA channel disabled */
+		/* DMA B status/trigger register */
+		sscape_write(devc, 3, 0x20);	/* DMA channel disabled */
+		/* Host interrupt config reg */
+		sscape_write(devc, 4, 0xf0 | (irq_bits << 2) | irq_bits);
+		/* Don't destroy CD-ROM DMA config bits (0xc0) */
+		sscape_write(devc, 5, (regs[5] & 0x3f) | (sscape_read(devc, 5) & 0xc0));
+		/* CD-ROM config (WSS codec actually) */
+		sscape_write(devc, 6, regs[6]);
+		sscape_write(devc, 7, regs[7]);
+		sscape_write(devc, 8, regs[8]);
+		/* Master control reg. Don't modify CR-ROM bits. Disable SB emul */
+		sscape_write(devc, 9, (sscape_read(devc, 9) & 0xf0) | 0x08);
 		spin_unlock_irqrestore(&devc->lock,flags);
 	}
 #ifdef SSCAPE_DEBUG2
@@ -715,7 +698,7 @@
 	}
 #endif
 
-	if (probe_mpu401(hw_config))
+	if (probe_mpu401(hw_config, sscape_ports))
 		hw_config->always_detect = 1;
 	hw_config->name = "SoundScape";
 
@@ -739,9 +722,6 @@
 
 	DDB(printk("Entered Soundscape detect_ga(%x)\n", devc->base));
 
-	if (check_region(devc->base, 8))
-		return 0;
-
 	/*
 	 * First check that the address register of "ODIE" is
 	 * there and that it has exactly 4 writable bits.
@@ -1115,9 +1095,9 @@
 		sscape_write( devc, 9, i | 3 );
 		sscape_write( devc, 3, 0x40);
 
-		if (check_region(0x228, 1)) {
-		    	    outb(0, 0x228);
-			    release_region(0x228,1);
+		if (request_region(0x228, 1, "sscape setup junk")) {
+			outb(0, 0x228);
+			release_region(0x228,1);
 		}
 		sscape_write( devc, 3, (devc -> dma << 4) | 0x80);
 		sscape_write( devc, 9, i );
@@ -1134,50 +1114,46 @@
 
 	DDB(printk("Entered detect_sscape_pnp(%x)\n", devc->base));
 
-	if (check_region(devc->base, 8)) {
-		printk(KERN_ERR "detect_sscape_pnp: port %x is not free\n", devc->base);	
-		return 0;
-	}
-		
-	if (check_region(devc->codec, 2)) {
+	if (!request_region(devc->codec, 2, "sscape codec")) {
 		printk(KERN_ERR "detect_sscape_pnp: port %x is not free\n", devc->codec);	
 		return 0;
 	}
 
-	if ( (inb( devc -> base + 2) & 0x78) != 0) return 0;
+	if ((inb(devc->base + 2) & 0x78) != 0)
+		goto fail;
 
 	d = inb ( devc -> base + 4) & 0xF0;
-	if (  (d & 0x80) != 0)  return 0;
+	if (d & 0x80)
+		goto fail;
 	
 	if (d == 0) {
-			devc->codec_type = 1;
-			devc->ic_type = IC_ODIE;
-	}
-	else if ( (d & 0x60) != 0) {
-			devc->codec_type = 2;
-			devc->ic_type = IC_OPUS;
-	}
-	else if ( (d & 0x40) != 0) {
-			devc->codec_type = 2;
-			devc->ic_type = IC_ODIE;
-	} 
-	else return 0;
+		devc->codec_type = 1;
+		devc->ic_type = IC_ODIE;
+	} else if ( (d & 0x60) != 0) {
+		devc->codec_type = 2;
+		devc->ic_type = IC_OPUS;
+	} else if ( (d & 0x40) != 0) {	/* WTF? */
+		devc->codec_type = 2;
+		devc->ic_type = IC_ODIE;
+	} else
+		goto fail;
 	
 	sscape_is_pnp = 1;
 		
 	outb(0xFA, devc -> base+4);
 	if  ((inb( devc -> base+4) & 0x9F) != 0x0A)
-		return 0;
+		goto fail;
 	outb(0xFE, devc -> base+4);
 	if  ( (inb(devc -> base+4) & 0x9F) != 0x0E)
-		return 0;
+		goto fail;
 	if  ( (inb(devc -> base+5) & 0x9F) != 0x0E)
-		return 0;
+		goto fail;
 
 	if (devc->codec_type == 2) {
-		if (devc -> codec != devc -> base + 8)
+		if (devc->codec != devc->base + 8) {
 			printk("soundscape warning: incorrect codec port specified\n");
-		devc -> codec = devc -> base + 8;
+			goto fail;
+		}
 		d = 0x10 | (sscape_read(devc, 9)  & 0xCF);
 		sscape_write(devc, 9, d);
 		sscape_write(devc, 6, 0x80);
@@ -1193,9 +1169,9 @@
 
 	d = inb(devc -> codec);
 	if (d & 0x80)
-		return 0;
+		goto fail;
 	if ( inb(devc -> codec + 2) == 0xFF)
-		return 0;
+		goto fail;
 
 	sscape_write(devc, 9, sscape_read(devc, 9)  & 0x3F );
 
@@ -1217,7 +1193,7 @@
 		
 	sscape_pnp_init_hw(devc);
 
-	for (i = 0; i < sizeof(valid_interrupts); i++)
+	for (i = 0; i < 4; i++)
 	{
 		if (devc->codec_irq == valid_interrupts[i]) {
 			irq_bits = i;
@@ -1234,15 +1210,14 @@
 	sscape_pnp_write_codec( devc, 0, sscape_pnp_read_codec( devc, 0) | 0x20);
 	sscape_pnp_write_codec( devc, 0, sscape_pnp_read_codec( devc, 1) | 0x20);
 
-	return 1;	
+	return 1;
+fail:
+	release_region(devc->codec, 2);
+	return 0;
 }
 
 static int __init probe_sscape(struct address_info *hw_config)
 {
-
-	if (sscape_detected != 0 && sscape_detected != hw_config->io_base)
-		return 0;
-
 	devc->base = hw_config->io_base;
 	devc->irq = hw_config->irq;
 	devc->dma = hw_config->dma;
@@ -1262,12 +1237,21 @@
 #endif
 	devc->failed = 1;
 
+	sscape_ports = request_region(devc->base, 2, "mpu401");
+	if (!sscape_ports)
+		return 0;
+
+	if (!request_region(devc->base + 2, 6, "SoundScape")) {
+		release_region(devc->base, 2);
+		return 0;
+	}
+
 	if (!detect_ga(devc)) {
-		if (detect_sscape_pnp(devc)) {		        
-			sscape_detected = hw_config->io_base;
+		if (detect_sscape_pnp(devc))
 			return 1;
-		} 
-		else return 0;
+		release_region(devc->base, 2);
+		release_region(devc->base + 2, 6);
+		return 0;
 	}
 
 	if (old_hardware)	/* Check that it's really an old Spea/Reveal card. */
@@ -1282,14 +1266,14 @@
 				inb(devc->base + ODIE_ADDR);
 		}
 	}
-	sscape_detected = hw_config->io_base;
 	return 1;
 }
 
-static int __init probe_ss_ms_sound(struct address_info *hw_config)
+static int __init init_ss_ms_sound(struct address_info *hw_config)
 {
 	int i, irq_bits = 0xff;
 	int ad_flags = 0;
+	struct resource *ports;
 	
 	if (devc->failed)
 	{
@@ -1301,7 +1285,7 @@
 		printk(KERN_ERR "soundscape: Invalid initialization order.\n");
 		return 0;
 	}
-	for (i = 0; i < sizeof(valid_interrupts); i++)
+	for (i = 0; i < 4; i++)
 	{
 		if (hw_config->irq == valid_interrupts[i])
 		{
@@ -1309,37 +1293,27 @@
 			break;
 		}
 	}
-	if (hw_config->irq > 15 || irq_bits == 0xff)
-	{
+	if (irq_bits == 0xff) {
 		printk(KERN_ERR "soundscape: Invalid MSS IRQ%d\n", hw_config->irq);
 		return 0;
 	}
 	
-	if (!sscape_is_pnp) {
-		if (old_hardware)
-			ad_flags = 0x12345677;	/* Tell that we may have a CS4248 chip (Spea-V7 Media FX) */
-		return ad1848_detect(hw_config->io_base, &ad_flags, hw_config->osp);
-	} 
-	else {
-		if (old_hardware)
-			ad_flags = 0x12345677;	/* Tell that we may have a CS4248 chip (Spea-V7 Media FX) */
-		else
-			ad_flags = 0x87654321;  /* Tell that we have a soundscape pnp with 1845 chip */
-		return ad1848_detect(hw_config->io_base, &ad_flags, hw_config->osp);
-	}
-}
+	if (old_hardware)
+		ad_flags = 0x12345677;	/* Tell that we may have a CS4248 chip (Spea-V7 Media FX) */
+	else if (sscape_is_pnp)
+		ad_flags = 0x87654321;  /* Tell that we have a soundscape pnp with 1845 chip */
 
-static void __init attach_ss_ms_sound(struct address_info *hw_config)
-{
-	/*
-	 * This routine configures the SoundScape card for use with the
-	 * Win Sound System driver. The AD1848 codec interface uses the CD-ROM
-	 * config registers of the "ODIE".
-	 */
+	ports = request_region(hw_config->io_base, 4, "ad1848");
+	if (!ports) {
+		printk(KERN_ERR "soundscape: ports busy\n");
+		return 0;
+	}
 
-	int i, irq_bits = 0xff;
+	if (!ad1848_detect(ports, &ad_flags, hw_config->osp)) {
+		release_region(hw_config->io_base, 4);
+		return 0;
+	}
 
- 		
  	if (!sscape_is_pnp)  /*pnp is already setup*/
  	{
  		/*
@@ -1355,14 +1329,6 @@
  		/*
  		 * Init the AD1848 (CD-ROM) config reg.
  		 */
- 		for (i = 0; i < sizeof(valid_interrupts); i++)
- 		{
- 			if (hw_config->irq == valid_interrupts[i])
- 			{
- 				irq_bits = i;
- 				break;
- 			}
- 		}	
  		sscape_write(devc, GA_CDCFG_REG, 0x89 | (hw_config->dma << 4) | (irq_bits << 1));
  	}
  	
@@ -1371,7 +1337,7 @@
  				
 	hw_config->slots[0] = ad1848_init(
 			sscape_is_pnp ? "SoundScape" : "SoundScape PNP",
-			hw_config->io_base,
+			ports,
 			hw_config->irq,
 			hw_config->dma,
 			hw_config->dma,
@@ -1402,13 +1368,15 @@
 			printk("I%d = %02x\n", i, sscape_read(devc, i));
 	}
 #endif
-
+	return 1;
 }
 
 static void __exit unload_sscape(struct address_info *hw_config)
 {
 	release_region(devc->base + 2, 6);
 	unload_mpu401(hw_config);
+	if (sscape_is_pnp)
+		release_region(devc->codec, 2);
 }
 
 static void __exit unload_ss_ms_sound(struct address_info *hw_config)
@@ -1480,10 +1448,7 @@
 
 	attach_sscape(&cfg_mpu);
 	
-	mss = probe_ss_ms_sound(&cfg);
-
-	if (mss)
-		attach_ss_ms_sound(&cfg);
+	mss = init_ss_ms_sound(&cfg);
 
 	return 0;
 }
diff -Nru a/sound/oss/swarm_cs4297a.c b/sound/oss/swarm_cs4297a.c
--- a/sound/oss/swarm_cs4297a.c	2004-10-18 14:56:32 -07:00
+++ b/sound/oss/swarm_cs4297a.c	2004-10-18 14:56:32 -07:00
@@ -70,6 +70,7 @@
 #include <linux/ac97_codec.h>
 #include <linux/pci.h>
 #include <linux/bitops.h>
+#include <linux/interrupt.h>
 #include <asm/io.h>
 #include <asm/dma.h>
 #include <linux/init.h>
@@ -77,7 +78,6 @@
 #include <linux/smp_lock.h>
 #include <linux/wrapper.h>
 #include <asm/uaccess.h>
-#include <asm/hardirq.h>
 
 #include <asm/sibyte/sb1250_regs.h>
 #include <asm/sibyte/sb1250_int.h>
diff -Nru a/sound/oss/trident.c b/sound/oss/trident.c
--- a/sound/oss/trident.c	2004-10-18 14:56:49 -07:00
+++ b/sound/oss/trident.c	2004-10-18 14:56:49 -07:00
@@ -217,7 +217,6 @@
 #include <linux/gameport.h>
 #include <linux/kernel.h>
 #include <asm/uaccess.h>
-#include <asm/hardirq.h>
 #include <asm/io.h>
 #include <asm/dma.h>
 
diff -Nru a/sound/oss/trix.c b/sound/oss/trix.c
--- a/sound/oss/trix.c	2004-10-18 14:55:54 -07:00
+++ b/sound/oss/trix.c	2004-10-18 14:55:54 -07:00
@@ -29,12 +29,6 @@
 
 #include "trix_boot.h"
 
-static int kilroy_was_here;	/* Don't detect twice */
-static int sb_initialized;
-static int mpu_initialized;
-
-static int *trix_osp;
-
 static int mpu;
 
 static int joystick;
@@ -82,20 +76,11 @@
 {
 	unsigned char   addr_bits;
 
-	if (check_region(0x390, 2))
-	{
-		printk(KERN_ERR "AudioTrix: Config port I/O conflict\n");
-		return 0;
-	}
-	if (kilroy_was_here)	/* Already initialized */
-		return 0;
-
 	if (trix_read(0x15) != 0x71)	/* No ASIC signature */
 	{
 		MDB(printk(KERN_ERR "No AudioTrix ASIC signature found\n"));
 		return 0;
 	}
-	kilroy_was_here = 1;
 
 	/*
 	 * Reset some registers.
@@ -135,107 +120,114 @@
  *      AudioTrix Pro
  */
 
-static int __init probe_trix_wss(struct address_info *hw_config)
+static int __init init_trix_wss(struct address_info *hw_config)
 {
+	static unsigned char dma_bits[4] = {
+		1, 2, 0, 3
+	};
+	struct resource *ports;
+	int config_port = hw_config->io_base + 0;
+	int dma1 = hw_config->dma, dma2 = hw_config->dma2;
+	int old_num_mixers = num_mixers;
+	u8 config, bits;
 	int ret;
+ 
+	switch(hw_config->irq) {
+	case 7:
+		bits = 8;
+		break;
+	case 9:
+		bits = 0x10;
+		break;
+	case 10:
+		bits = 0x18;
+		break;
+	case 11:
+		bits = 0x20;
+		break;
+	default:
+		printk(KERN_ERR "AudioTrix: Bad WSS IRQ %d\n", hw_config->irq);
+		return 0;
+	}
+
+	switch (dma1) {
+	case 0:
+	case 1:
+	case 3:
+		break;
+	default:
+		printk(KERN_ERR "AudioTrix: Bad WSS DMA %d\n", dma1);
+		return 0;
+	}
+
+	switch (dma2) {
+	case -1:
+	case 0:
+	case 1:
+	case 3:
+		break;
+	default:
+		printk(KERN_ERR "AudioTrix: Bad capture DMA %d\n", dma2);
+		return 0;
+	}
 
 	/*
 	 * Check if the IO port returns valid signature. The original MS Sound
 	 * system returns 0x04 while some cards (AudioTrix Pro for example)
 	 * return 0x00.
 	 */
-	if (check_region(hw_config->io_base, 8))
-	{
+	ports = request_region(hw_config->io_base + 4, 4, "ad1848");
+	if (!ports) {
 		printk(KERN_ERR "AudioTrix: MSS I/O port conflict (%x)\n", hw_config->io_base);
 		return 0;
 	}
-	trix_osp = hw_config->osp;
 
-	if (!trix_set_wss_port(hw_config))
+	if (!request_region(hw_config->io_base, 4, "MSS config")) {
+		printk(KERN_ERR "AudioTrix: MSS I/O port conflict (%x)\n", hw_config->io_base);
+		release_region(hw_config->io_base + 4, 4);
 		return 0;
+	}
+
+	if (!trix_set_wss_port(hw_config))
+		goto fail;
 
-	if ((inb(hw_config->io_base + 3) & 0x3f) != 0x00)
+	config = inb(hw_config->io_base + 3);
+
+	if ((config & 0x3f) != 0x00)
 	{
 		MDB(printk(KERN_ERR "No MSS signature detected on port 0x%x\n", hw_config->io_base));
-		return 0;
-	}
-	if (hw_config->irq > 11)
-	{
-		printk(KERN_ERR "AudioTrix: Bad WSS IRQ %d\n", hw_config->irq);
-		return 0;
-	}
-	if (hw_config->dma != 0 && hw_config->dma != 1 && hw_config->dma != 3)
-	{
-		printk(KERN_ERR "AudioTrix: Bad WSS DMA %d\n", hw_config->dma);
-		return 0;
+		goto fail;
 	}
-	if (hw_config->dma2 != -1 && hw_config->dma2 != hw_config->dma)
-		if (hw_config->dma2 != 0 && hw_config->dma2 != 1 && hw_config->dma2 != 3)
-		{
-			  printk(KERN_ERR "AudioTrix: Bad capture DMA %d\n", hw_config->dma2);
-			  return 0;
-		}
+
 	/*
 	 * Check that DMA0 is not in use with a 8 bit board.
 	 */
 
-	if (hw_config->dma == 0 && inb(hw_config->io_base + 3) & 0x80)
+	if (dma1 == 0 && config & 0x80)
 	{
 		printk(KERN_ERR "AudioTrix: Can't use DMA0 with a 8 bit card slot\n");
-		return 0;
+		goto fail;
 	}
-	if (hw_config->irq > 7 && hw_config->irq != 9 && inb(hw_config->io_base + 3) & 0x80)
+	if (hw_config->irq > 9 && config & 0x80)
 	{
 		printk(KERN_ERR "AudioTrix: Can't use IRQ%d with a 8 bit card slot\n", hw_config->irq);
-		return 0;
-	}
-	ret = ad1848_detect(hw_config->io_base + 4, NULL, hw_config->osp);
-
-	if (ret)
-	{
-		if(joystick==1)
-			trix_write(0x15, 0x80);
-		request_region(0x390, 2, "AudioTrix");
+		goto fail;
 	}
-	return ret;
-}
 
-static void __init attach_trix_wss(struct address_info *hw_config)
-{
-	static unsigned char interrupt_bits[12] = {
-		0, 0, 0, 0, 0, 0, 0, 0x08, 0, 0x10, 0x18, 0x20
-	};
-	char bits;
+	ret = ad1848_detect(ports, NULL, hw_config->osp);
+	if (!ret)
+		goto fail;
 
-	static unsigned char dma_bits[4] = {
-		1, 2, 0, 3
-	};
+	if (joystick==1)
+		trix_write(0x15, 0x80);
 
-	int config_port = hw_config->io_base + 0;
-	int dma1 = hw_config->dma, dma2 = hw_config->dma2;
-	int old_num_mixers = num_mixers;
-
-	trix_osp = hw_config->osp;
-
-	if (!kilroy_was_here)
-	{
-		DDB(printk("AudioTrix: Attach called but not probed yet???\n"));
-		return;
-	}
-	
 	/*
 	 * Set the IRQ and DMA addresses.
 	 */
 
-	bits = interrupt_bits[hw_config->irq];
-	if (bits == 0)
-	{
-		printk("AudioTrix: Bad IRQ (%d)\n", hw_config->irq);
-		return;
-	}
 	outb((bits | 0x40), config_port);
 
-	if (hw_config->dma2 == -1 || hw_config->dma2 == hw_config->dma)
+	if (dma2 == -1 || dma2 == dma1)
 	{
 		  bits |= dma_bits[dma1];
 		  dma2 = dma1;
@@ -253,14 +245,13 @@
 
 	outb((bits), config_port);	/* Write IRQ+DMA setup */
 
-	hw_config->slots[0] = ad1848_init("AudioTrix Pro", hw_config->io_base + 4,
+	hw_config->slots[0] = ad1848_init("AudioTrix Pro", ports,
 					  hw_config->irq,
 					  dma1,
 					  dma2,
 					  0,
 					  hw_config->osp,
 					  THIS_MODULE);
-	request_region(hw_config->io_base, 4, "MSS config");
 
 	if (num_mixers > old_num_mixers)	/* Mixer got installed */
 	{
@@ -269,6 +260,12 @@
 		AD1848_REROUTE(SOUND_MIXER_LINE3, SOUND_MIXER_SYNTH);		/* OPL4 */
 		AD1848_REROUTE(SOUND_MIXER_SPEAKER, SOUND_MIXER_ALTPCM);	/* SB */
 	}
+	return 1;
+
+fail:
+	release_region(hw_config->io_base, 4);
+	release_region(hw_config->io_base + 4, 4);
+	return 0;
 }
 
 static int __init probe_trix_sb(struct address_info *hw_config)
@@ -276,6 +273,8 @@
 
 	int tmp;
 	unsigned char conf;
+	extern int sb_be_quiet;
+	int old_quiet;
 	static signed char irq_translate[] = {
 		-1, -1, -1, 0, 1, 2, -1, 3
 	};
@@ -283,17 +282,6 @@
 	if (trix_boot_len == 0)
 		return 0;	/* No boot code -> no fun */
 
-	if (!kilroy_was_here)
-		return 0;	/* AudioTrix Pro has not been detected earlier */
-
-	if (sb_initialized)
-		return 0;
-
-	if (check_region(hw_config->io_base, 16))
-	{
-		printk(KERN_ERR "AudioTrix: SB I/O port conflict (%x)\n", hw_config->io_base);
-		return 0;
-	}
 	if ((hw_config->io_base & 0xffffff8f) != 0x200)
 		return 0;
 
@@ -307,6 +295,11 @@
 	if (tmp != 1 && tmp != 3)
 		return 0;
 
+	if (!request_region(hw_config->io_base, 16, "soundblaster")) {
+		printk(KERN_ERR "AudioTrix: SB I/O port conflict (%x)\n", hw_config->io_base);
+		return 0;
+	}
+
 	conf = 0x84;		/* DMA and IRQ enable */
 	conf |= hw_config->io_base & 0x70;	/* I/O address bits */
 	conf |= irq_translate[hw_config->irq];
@@ -315,16 +308,12 @@
 	trix_write(0x1b, conf);
 
 	download_boot(hw_config->io_base);
-	sb_initialized = 1;
 
 	hw_config->name = "AudioTrix SB";
-	return sb_dsp_detect(hw_config, 0, 0, NULL);
-}
-
-static void __init attach_trix_sb(struct address_info *hw_config)
-{
-	extern int sb_be_quiet;
-	int old_quiet;
+	if (!sb_dsp_detect(hw_config, 0, 0, NULL)) {
+		release_region(hw_config->io_base, 16);
+		return 0;
+	}
 
 	hw_config->driver_use_1 = SB_NO_MIDI | SB_NO_MIXER | SB_NO_RECORDING;
 
@@ -335,6 +324,7 @@
 	sb_dsp_init(hw_config, THIS_MODULE);
 
 	sb_be_quiet = old_quiet;
+	return 1;
 }
 
 static int __init probe_trix_mpu(struct address_info *hw_config)
@@ -344,21 +334,6 @@
 		-1, -1, -1, 1, 2, 3, -1, 4, -1, 5
 	};
 
-	if (!kilroy_was_here)
-	{
-		DDB(printk("Trix: WSS and SB modes must be initialized before MPU\n"));
-		return 0;	/* AudioTrix Pro has not been detected earlier */
-	}
-	if (!sb_initialized)
-	{
-		DDB(printk("Trix: SB mode must be initialized before MPU\n"));
-		return 0;
-	}
-	if (mpu_initialized)
-	{
-		DDB(printk("Trix: MPU mode already initialized\n"));
-		return 0;
-	}
 	if (hw_config->irq > 9)
 	{
 		printk(KERN_ERR "AudioTrix: Bad MPU IRQ %d\n", hw_config->irq);
@@ -389,7 +364,6 @@
 
 	conf |= irq_bits[hw_config->irq] << 4;
 	trix_write(0x19, (trix_read(0x19) & 0x83) | conf);
-	mpu_initialized = 1;
 	hw_config->name = "AudioTrix Pro";
 	return probe_uart401(hw_config, THIS_MODULE);
 }
@@ -485,9 +459,16 @@
 		trix_boot_len = mod_firmware_load("/etc/sound/trxpro.bin",
 						    (char **) &trix_boot);
 	}
-	if (!probe_trix_wss(&cfg))
+
+	if (!request_region(0x390, 2, "AudioTrix")) {
+		printk(KERN_ERR "AudioTrix: Config port I/O conflict\n");
+		return -ENODEV;
+	}
+
+	if (!init_trix_wss(&cfg)) {
+		release_region(0x390, 2);
 		return -ENODEV;
-	attach_trix_wss(&cfg);
+	}
 
 	/*
 	 *    We must attach in the right order to get the firmware
@@ -496,8 +477,6 @@
 
 	if (cfg2.io_base != -1) {
 		sb = probe_trix_sb(&cfg2);
-		if (sb)
-			attach_trix_sb(&cfg2);
 	}
 	
 	if (cfg_mpu.io_base != -1)
diff -Nru a/sound/oss/v_midi.c b/sound/oss/v_midi.c
--- a/sound/oss/v_midi.c	2004-10-18 14:56:17 -07:00
+++ b/sound/oss/v_midi.c	2004-10-18 14:56:17 -07:00
@@ -90,11 +90,12 @@
 static int v_midi_out (int dev, unsigned char midi_byte)
 {
 	vmidi_devc *devc = midi_devs[dev]->devc;
-	vmidi_devc *pdevc = midi_devs[devc->pair_mididev]->devc;
+	vmidi_devc *pdevc;
 
 	if (devc == NULL)
-		return -(ENXIO);
+		return -ENXIO;
 
+	pdevc = midi_devs[devc->pair_mididev]->devc;
 	if (pdevc->input_opened > 0){
 		if (MIDIbuf_avail(pdevc->my_mididev) > 500)
 			return 0;
diff -Nru a/sound/oss/waveartist.c b/sound/oss/waveartist.c
--- a/sound/oss/waveartist.c	2004-10-18 14:57:19 -07:00
+++ b/sound/oss/waveartist.c	2004-10-18 14:57:19 -07:00
@@ -1346,18 +1346,20 @@
 		return 0;
 	}
 
-	if (check_region(hw_config->io_base, 15))  {
+	if (!request_region(hw_config->io_base, 15, hw_config->name))  {
 		printk(KERN_WARNING "WaveArtist: I/O port conflict\n");
 		return 0;
 	}
 
 	if (hw_config->irq > 15 || hw_config->irq < 0) {
+		release_region(hw_config->io_base, 15);
 		printk(KERN_WARNING "WaveArtist: Bad IRQ %d\n",
 		       hw_config->irq);
 		return 0;
 	}
 
 	if (hw_config->dma != 3) {
+		release_region(hw_config->io_base, 15);
 		printk(KERN_WARNING "WaveArtist: Bad DMA %d\n",
 		       hw_config->dma);
 		return 0;
@@ -1391,8 +1393,6 @@
 
 	if (hw->dma != hw->dma2 && hw->dma2 != NO_DMA)
 		devc->audio_flags |= DMA_DUPLEX;
-
-	request_region(hw->io_base, 15, devc->hw.name);
 
 	devc->mix = mix;
 	devc->dev_no = waveartist_init(devc);
diff -Nru a/sound/oss/wavfront.c b/sound/oss/wavfront.c
--- a/sound/oss/wavfront.c	2004-10-18 14:56:32 -07:00
+++ b/sound/oss/wavfront.c	2004-10-18 14:56:32 -07:00
@@ -1402,7 +1402,7 @@
 	num_samples = (1 << log_ns[0]);
     
 	for (i = 0; i < num_samples; i++) {
-		char d[2];
+		s8 d[2];
 	
 		if ((d[0] = wavefront_read ()) == -1) {
 			printk (KERN_ERR LOGNAME "upload multisample failed "
@@ -2961,8 +2961,8 @@
 		if (i != cnt) {
 			printk (KERN_WARNING LOGNAME
 				"FX memset "
-				"(0x%x, 0x%x, 0x%x, %d) incomplete\n",
-				page, addr, (int) data, cnt);
+				"(0x%x, 0x%x, %p, %d) incomplete\n",
+				page, addr, data, cnt);
 			return -(EIO);
 		}
 	}
diff -Nru a/sound/oss/wf_midi.c b/sound/oss/wf_midi.c
--- a/sound/oss/wf_midi.c	2004-10-18 14:55:55 -07:00
+++ b/sound/oss/wf_midi.c	2004-10-18 14:55:55 -07:00
@@ -784,7 +784,7 @@
 
 int __init detect_wf_mpu (int irq, int io_base)
 {
-	if (check_region (io_base, 2)) {
+	if (!request_region(io_base, 2, "wavefront midi")) {
 		printk (KERN_WARNING "WF-MPU: I/O port %x already in use.\n",
 			io_base);
 		return -1;
@@ -803,11 +803,10 @@
 	if ((phys_dev->devno = sound_alloc_mididev()) < 0){
 
 		printk (KERN_ERR "WF-MPU: Too many MIDI devices detected.\n");
+		release_region(phys_dev->base, 2);
 		return -1;
-
 	}
 
-	request_region (phys_dev->base, 2, "wavefront midi");
 	phys_dev->isvirtual = 0;
 
 	if (config_wf_mpu (phys_dev)) {
diff -Nru a/sound/parisc/harmony.c b/sound/parisc/harmony.c
--- a/sound/parisc/harmony.c	2004-10-18 14:56:28 -07:00
+++ b/sound/parisc/harmony.c	2004-10-18 14:56:28 -07:00
@@ -6,7 +6,7 @@
  *
  *	Harmony is found in HP 712s, 715/new and many other GSC based machines.
  *	On older 715 machines you'll find the technically identical chip 
- *	called 'Vivace'. Both Harmony and Vicace are supported by this driver.
+ *	called 'Vivace'. Both Harmony and Vivace are supported by this driver.
  *
  *  this ALSA driver is based on OSS driver by:
  *	Copyright 2000 (c) Linuxcare Canada, Alex deVries <alex@linuxcare.com>
@@ -43,7 +43,7 @@
  * to be recorded is put in RNXTADD. There is 2 read-only registers, PCURADD and 
  * RCURADD that provides adress of current page.
  * 
- * Harmony has no way to controll full duplex or half duplex mode. It means
+ * Harmony has no way to control full duplex or half duplex mode. It means
  * that we always need to provide adresses of playback and capture data, even
  * when this is not needed. That's why we statically alloc one graveyard
  * buffer (to put recorded data in play-only mode) and a silence buffer.
@@ -80,8 +80,7 @@
 MODULE_AUTHOR("Laurent Canet <canetl@esiee.fr>");
 MODULE_DESCRIPTION("ALSA Harmony sound driver");
 MODULE_LICENSE("GPL");
-MODULE_CLASSES("{sound}");
-MODULE_DEVICES("{{ALSA,Harmony soundcard}}");
+MODULE_SUPPORTED_DEVICE("{{ALSA,Harmony soundcard}}");
 
 #undef DEBUG
 #ifdef DEBUG
@@ -138,13 +137,10 @@
 
 module_param_array(index, int, boot_devs, 0444);
 MODULE_PARM_DESC(index, "Index value for Sun CS4231 soundcard.");
-MODULE_PARM_SYNTAX(index, SNDRV_INDEX_DESC);
 module_param_array(id, charp, boot_devs, 0444);
 MODULE_PARM_DESC(id, "ID string for Sun CS4231 soundcard.");
-MODULE_PARM_SYNTAX(id, SNDRV_ID_DESC);
 module_param_array(enable, bool, boot_devs, 0444);
 MODULE_PARM_DESC(enable, "Enable Sun CS4231 soundcard.");
-MODULE_PARM_SYNTAX(enable, SNDRV_ENABLE_DESC);
 
 /* Register offset (from base hpa) */
 #define REG_ID		0x00
@@ -216,7 +212,6 @@
 	snd_pcm_substream_t *capture_substream;
 	snd_info_entry_t *proc_entry;
 } snd_card_harmony_t;
-#define chip_t snd_card_harmony_t
 
 static snd_card_t *snd_harmony_cards[SNDRV_CARDS] = SNDRV_DEFAULT_PTR;
 
@@ -243,10 +238,8 @@
 	44100, 48000
 };
 
-#define RATES sizeof(snd_card_harmony_rates) / sizeof(snd_card_harmony_rates[0])
-
 static snd_pcm_hw_constraint_list_t hw_constraint_rates = {
-	.count = RATES,
+	.count = ARRAY_SIZE(snd_card_harmony_rates),
 	.list = snd_card_harmony_rates,
 	.mask = 0,
 };
@@ -283,7 +276,7 @@
 {
 	unsigned int idx;
 	
-	for (idx = 0; idx <= RATES; idx++)
+	for (idx = 0; idx <= ARRAY_SIZE(snd_card_harmony_rates); idx++)
 		if (snd_card_harmony_rates[idx] == rate)
 			return rate_bits[idx];
 	return HARMONY_SR_44KHZ; /* fallback */
@@ -556,7 +549,7 @@
 	harmony->sample_rate = snd_card_harmony_rate_bits(runtime->rate);
 
 	/* data format */
-	harmony->data_format = snd_harmony_set_data_format(haromny, runtime->format);
+	harmony->data_format = snd_harmony_set_data_format(harmony, runtime->format);
 
 	/* number of channels */
 	if (runtime->channels == 2)
@@ -587,7 +580,7 @@
 	harmony->sample_rate = snd_card_harmony_rate_bits(runtime->rate);
 	
 	/* data format */
-	harmony->data_format = snd_harmony_set_data_format(haromny, runtime->format);
+	harmony->data_format = snd_harmony_set_data_format(harmony, runtime->format);
 	
 	/* number of channels */
 	if (runtime->channels == 1)
@@ -751,6 +744,8 @@
 	int err;
 	
 	err = snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(hw_params));
+	if (err > 0 && substream->dma_device.type == SNDRV_DMA_TYPE_CONTINUOUS)
+		substream->runtime->dma_addr = __pa(substream->runtime->dma_area);
 	DPRINTK(KERN_INFO PFX "HW Params returned %d, dma_addr %lx\n", err,
 			(unsigned long)substream->runtime->dma_addr);
 	return err;
@@ -784,7 +779,7 @@
 	.pointer =		snd_card_harmony_capture_pointer,
 };
 
-static int snd_card_harmony_pcm_init(snd_card_harmony_t *harmony, int device)
+static int snd_card_harmony_pcm_init(snd_card_harmony_t *harmony)
 {
 	snd_pcm_t *pcm;
 	int err;
@@ -797,7 +792,7 @@
 	
 	snd_harmony_disable_interrupts(harmony);
 	
-   	if ((err = snd_pcm_new(harmony->card, "Harmony", device, 1, 1, &pcm)) < 0)
+   	if ((err = snd_pcm_new(harmony->card, "Harmony", 0, 1, 1, &pcm)) < 0)
 		return err;
 	
 	snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_card_harmony_playback_ops);
@@ -811,28 +806,54 @@
 	/* initialize graveyard buffer */
 	harmony->dma_dev.type = SNDRV_DMA_TYPE_DEV;
 	harmony->dma_dev.dev = &harmony->pa_dev->dev;
-	err = snd_dma_alloc_pages(&harmony->dma_dev, HARMONY_BUF_SIZE*GRAVEYARD_BUFS,
+	err = snd_dma_alloc_pages(harmony->dma_dev.type,
+				  harmony->dma_dev.dev,
+				  HARMONY_BUF_SIZE*GRAVEYARD_BUFS,
 				  &harmony->graveyard_dma);
-	if (err < 0)
+	if (err == -ENOMEM) {
+		/* use continuous buffers */
+		harmony->dma_dev.type = SNDRV_DMA_TYPE_CONTINUOUS;
+		harmony->dma_dev.dev = snd_dma_continuous_data(GFP_KERNEL);
+		err = snd_dma_alloc_pages(harmony->dma_dev.type,
+					  harmony->dma_dev.dev,
+					  HARMONY_BUF_SIZE*GRAVEYARD_BUFS,
+					  &harmony->graveyard_dma);
+	}
+	if (err < 0) {
+		printk(KERN_ERR PFX "can't allocate graveyard buffer\n");
 		return err;
+	}
 	harmony->graveyard_count = 0;
 	
 	/* initialize silence buffers */
-	err = snd_dma_alloc_pages(&harmony->dma_dev, HARMONY_BUF_SIZE*SILENCE_BUFS,
+	err = snd_dma_alloc_pages(harmony->dma_dev.type,
+				  harmony->dma_dev.dev,
+				  HARMONY_BUF_SIZE*SILENCE_BUFS,
 				  &harmony->silence_dma);
-	if (err < 0)
+	if (err < 0) {
+		printk(KERN_ERR PFX "can't allocate silence buffer\n");
 		return err;
+	}
 	harmony->silence_count = 0;
 
+	if (harmony->dma_dev.type == SNDRV_DMA_TYPE_CONTINUOUS) {
+		harmony->graveyard_dma.addr = __pa(harmony->graveyard_dma.area);
+		harmony->silence_dma.addr = __pa(harmony->silence_dma.area);
+	}
+
 	harmony->ply_stopped = harmony->cap_stopped = 1;
 	
 	harmony->playback_substream = NULL;
 	harmony->capture_substream = NULL;
 	harmony->graveyard_count = 0;
-	
-	snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV,
-					      &harmony->pa_dev->dev,
-					      MAX_BUFFER_SIZE, MAX_BUFFER_SIZE);
+
+	err = snd_pcm_lib_preallocate_pages_for_all(pcm, harmony->dma_dev.type,
+						    harmony->dma_dev.dev,
+						    MAX_BUFFER_SIZE, MAX_BUFFER_SIZE);
+	if (err < 0) {
+		printk(KERN_ERR PFX "buffer allocation error %d\n", err);
+		// return err;
+	}
 
 	return 0;
 }
@@ -871,7 +892,7 @@
  
 static int snd_harmony_volume_get(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
 {
-	snd_card_harmony_t *harmony = _snd_kcontrol_chip(kcontrol);
+	snd_card_harmony_t *harmony = snd_kcontrol_chip(kcontrol);
 	int shift_left = (kcontrol->private_value) & 0xff;
 	int shift_right = (kcontrol->private_value >> 8) & 0xff;
 	int mask = (kcontrol->private_value >> 16) & 0xff;
@@ -896,7 +917,7 @@
 
 static int snd_harmony_volume_put(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
 {
-	snd_card_harmony_t *harmony = _snd_kcontrol_chip(kcontrol);
+	snd_card_harmony_t *harmony = snd_kcontrol_chip(kcontrol);
 	int shift_left = (kcontrol->private_value) & 0xff;
 	int shift_right = (kcontrol->private_value >> 8) & 0xff;
 	int mask = (kcontrol->private_value >> 16) & 0xff;
@@ -1037,7 +1058,7 @@
 		snd_card_free(card);
 		return err;
 	}
-	if ((err = snd_card_harmony_pcm_init(chip, dev)) < 0) {
+	if ((err = snd_card_harmony_pcm_init(chip)) < 0) {
 		printk(KERN_ERR PFX "PCM Init failed\n");
 		snd_card_free(card);
 		return err;
diff -Nru a/sound/pci/Kconfig b/sound/pci/Kconfig
--- a/sound/pci/Kconfig	2004-10-18 14:56:28 -07:00
+++ b/sound/pci/Kconfig	2004-10-18 14:56:28 -07:00
@@ -22,6 +22,14 @@
 	help
 	  Say 'Y' or 'M' to include support for ATI IXP 150/200/250/300 AC97 controller.
 
+config SND_ATIIXP_MODEM
+	tristate "ATI IXP 150/200/250 Modem"
+	depends on SND
+	select SND_AC97_CODEC
+	help
+	  Say 'Y' or 'M' to include support for ATI IXP 150/200/250 AC97 modem
+	  controller.
+
 config SND_AU8810
         tristate "Aureal Advantage"
         depends on SND
@@ -290,12 +298,12 @@
 	  SiS 7012, AMD768/8111, NVidia NForce and ALi 5455 chips.
 
 config SND_INTEL8X0M
-	tristate "Intel i8x0/MX440; AMD768/8111 modems (EXPERIMENTAL)"
+	tristate "Intel i8x0/MX440; SiS 7013; NForce; AMD768/8111 modems (EXPERIMENTAL)"
 	depends on SND && EXPERIMENTAL
 	select SND_AC97_CODEC
 	help
-	  Say 'Y' or 'M' to include support for Intel8x0 and AMD768/8111 based
-	  modems.
+	  Say 'Y' or 'M' to include support for Intel8x0, SiS 7013, NVidia NForce
+          and AMD768/8111 based modems.
 
 config SND_SONICVIBES
 	tristate "S3 SonicVibes"
diff -Nru a/sound/pci/Makefile b/sound/pci/Makefile
--- a/sound/pci/Makefile	2004-10-18 14:55:54 -07:00
+++ b/sound/pci/Makefile	2004-10-18 14:55:54 -07:00
@@ -5,6 +5,7 @@
 
 snd-als4000-objs := als4000.o
 snd-atiixp-objs := atiixp.o
+snd-atiixp-modem-objs := atiixp_modem.o
 snd-azt3328-objs := azt3328.o
 snd-bt87x-objs := bt87x.o
 snd-cmipci-objs := cmipci.o
@@ -25,6 +26,7 @@
 # Toplevel Module Dependency
 obj-$(CONFIG_SND_ALS4000) += snd-als4000.o
 obj-$(CONFIG_SND_ATIIXP) += snd-atiixp.o
+obj-$(CONFIG_SND_ATIIXP_MODEM) += snd-atiixp-modem.o
 obj-$(CONFIG_SND_AZT3328) += snd-azt3328.o
 obj-$(CONFIG_SND_BT87X) += snd-bt87x.o
 obj-$(CONFIG_SND_CMIPCI) += snd-cmipci.o
diff -Nru a/sound/pci/ac97/ac97_codec.c b/sound/pci/ac97/ac97_codec.c
--- a/sound/pci/ac97/ac97_codec.c	2004-10-18 14:56:28 -07:00
+++ b/sound/pci/ac97/ac97_codec.c	2004-10-18 14:56:28 -07:00
@@ -45,9 +45,6 @@
 
 module_param(enable_loopback, bool, 0444);
 MODULE_PARM_DESC(enable_loopback, "Enable AC97 ADC/DAC Loopback Control");
-MODULE_PARM_SYNTAX(enable_loopback, SNDRV_BOOLEAN_FALSE_DESC);
-
-#define chip_t ac97_t
 
 /*
 
@@ -108,12 +105,13 @@
 { 0x41445375, 0xffffffff, "AD1985",		patch_ad1985,	NULL },
 { 0x414c4300, 0xffffff00, "ALC100/100P", 	NULL,		NULL },
 { 0x414c4710, 0xfffffff0, "ALC200/200P",	NULL,		NULL },
+{ 0x414c4721, 0xffffffff, "ALC650D",		NULL,	NULL }, /* already patched */
+{ 0x414c4722, 0xffffffff, "ALC650E",		NULL,	NULL }, /* already patched */
+{ 0x414c4723, 0xffffffff, "ALC650F",		NULL,	NULL }, /* already patched */
 { 0x414c4720, 0xfffffff0, "ALC650",		patch_alc650,	NULL },
-{ 0x414c4721, 0xfffffff0, "ALC650D",		patch_alc650,	NULL },
-{ 0x414c4722, 0xfffffff0, "ALC650E",		patch_alc650,	NULL },
-{ 0x414c4723, 0xfffffff0, "ALC650F",		patch_alc650,	NULL },
 { 0x414c4760, 0xfffffff0, "ALC655",		patch_alc655,	NULL },
 { 0x414c4780, 0xfffffff0, "ALC658",		patch_alc655,	NULL },
+{ 0x414c4790, 0xfffffff0, "ALC850",		patch_alc850,	NULL },
 { 0x414c4730, 0xffffffff, "ALC101",		NULL,		NULL },
 { 0x414c4740, 0xfffffff0, "ALC202",		NULL,		NULL },
 { 0x414c4750, 0xfffffff0, "ALC250",		NULL,		NULL },
@@ -214,6 +212,13 @@
 };
 
 /*
+ * Shared AC97 controllers (ICH, ATIIXP...)
+ */
+static DECLARE_MUTEX(shared_codec_mutex);
+static ac97_t *shared_codec[AC97_SHARED_TYPES][4];
+
+
+/*
  *  I/O routines
  */
 
@@ -274,12 +279,12 @@
 {
 	if (!snd_ac97_valid_reg(ac97, reg))
 		return;
-	if ((ac97->id & 0xffffff00) == 0x414c4300) {
+	if ((ac97->id & 0xffffff00) == AC97_ID_ALC100) {
 		/* Fix H/W bug of ALC100/100P */
 		if (reg == AC97_MASTER || reg == AC97_HEADPHONE)
-			ac97->bus->write(ac97, AC97_RESET, 0);	/* reset audio codec */
+			ac97->bus->ops->write(ac97, AC97_RESET, 0);	/* reset audio codec */
 	}
-	ac97->bus->write(ac97, reg, value);
+	ac97->bus->ops->write(ac97, reg, value);
 }
 
 /**
@@ -297,14 +302,14 @@
 {
 	if (!snd_ac97_valid_reg(ac97, reg))
 		return 0;
-	return ac97->bus->read(ac97, reg);
+	return ac97->bus->ops->read(ac97, reg);
 }
 
 /* read a register - return the cached value if already read */
 static inline unsigned short snd_ac97_read_cache(ac97_t *ac97, unsigned short reg)
 {
 	if (! test_bit(reg, ac97->reg_accessed)) {
-		ac97->regs[reg] = ac97->bus->read(ac97, reg);
+		ac97->regs[reg] = ac97->bus->ops->read(ac97, reg);
 		// set_bit(reg, ac97->reg_accessed);
 	}
 	return ac97->regs[reg];
@@ -327,7 +332,7 @@
 	spin_lock(&ac97->reg_lock);
 	ac97->regs[reg] = value;
 	spin_unlock(&ac97->reg_lock);
-	ac97->bus->write(ac97, reg, value);
+	ac97->bus->ops->write(ac97, reg, value);
 	set_bit(reg, ac97->reg_accessed);
 }
 
@@ -354,7 +359,7 @@
 	if (change) {
 		ac97->regs[reg] = value;
 		spin_unlock(&ac97->reg_lock);
-		ac97->bus->write(ac97, reg, value);
+		ac97->bus->ops->write(ac97, reg, value);
 	} else
 		spin_unlock(&ac97->reg_lock);
 	return change;
@@ -387,7 +392,7 @@
 	if (change) {
 		ac97->regs[reg] = new;
 		spin_unlock(&ac97->reg_lock);
-		ac97->bus->write(ac97, reg, new);
+		ac97->bus->ops->write(ac97, reg, new);
 	} else
 		spin_unlock(&ac97->reg_lock);
 	return change;
@@ -398,7 +403,7 @@
 	int change;
 	unsigned short old, new, cfg;
 
-	down(&ac97->spec.ad18xx.mutex);
+	down(&ac97->mutex);
 	spin_lock(&ac97->reg_lock);
 	old = ac97->spec.ad18xx.pcmreg[codec];
 	new = (old & ~mask) | value;
@@ -408,17 +413,17 @@
 		ac97->spec.ad18xx.pcmreg[codec] = new;
 		spin_unlock(&ac97->reg_lock);
 		/* select single codec */
-		ac97->bus->write(ac97, AC97_AD_SERIAL_CFG,
+		ac97->bus->ops->write(ac97, AC97_AD_SERIAL_CFG,
 				 (cfg & ~0x7000) |
 				 ac97->spec.ad18xx.unchained[codec] | ac97->spec.ad18xx.chained[codec]);
 		/* update PCM bits */
-		ac97->bus->write(ac97, AC97_PCM, new);
+		ac97->bus->ops->write(ac97, AC97_PCM, new);
 		/* select all codecs */
-		ac97->bus->write(ac97, AC97_AD_SERIAL_CFG,
+		ac97->bus->ops->write(ac97, AC97_AD_SERIAL_CFG,
 				 cfg | 0x7000);
 	} else
 		spin_unlock(&ac97->reg_lock);
-	up(&ac97->spec.ad18xx.mutex);
+	up(&ac97->mutex);
 	return change;
 }
 
@@ -545,7 +550,7 @@
 	int reg = kcontrol->private_value & 0xff;
 	int shift = (kcontrol->private_value >> 8) & 0xff;
 	int mask = (kcontrol->private_value >> 16) & 0xff;
-	int invert = (kcontrol->private_value >> 24) & 0xff;
+	int invert = (kcontrol->private_value >> 24) & 0x01;
 	
 	ucontrol->value.integer.value[0] = (snd_ac97_read_cache(ac97, reg) >> shift) & mask;
 	if (invert)
@@ -559,7 +564,7 @@
 	int reg = kcontrol->private_value & 0xff;
 	int shift = (kcontrol->private_value >> 8) & 0xff;
 	int mask = (kcontrol->private_value >> 16) & 0xff;
-	int invert = (kcontrol->private_value >> 24) & 0xff;
+	int invert = (kcontrol->private_value >> 24) & 0x01;
 	unsigned short val;
 	
 	val = (ucontrol->value.integer.value[0] & mask);
@@ -625,6 +630,40 @@
 				    (val1 << shift_left) | (val2 << shift_right));
 }
 
+int snd_ac97_getput_page(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol,
+			 int (*func)(snd_kcontrol_t *, snd_ctl_elem_value_t *))
+{
+	ac97_t *ac97 = snd_kcontrol_chip(kcontrol);
+	int reg = kcontrol->private_value & 0xff;
+	int err;
+
+	if ((ac97->ext_id & AC97_EI_REV_MASK) >= AC97_EI_REV_23 &&
+	    (reg >= 0x60 && reg < 0x70)) {
+		unsigned short page_save;
+		unsigned short page = (kcontrol->private_value >> 25) & 0x0f;
+		down(&ac97->mutex); /* lock paging */
+		page_save = snd_ac97_read(ac97, AC97_INT_PAGING) & AC97_PAGE_MASK;
+		snd_ac97_update_bits(ac97, AC97_INT_PAGING, AC97_PAGE_MASK, page);
+		err = func(kcontrol, ucontrol);
+		snd_ac97_update_bits(ac97, AC97_INT_PAGING, AC97_PAGE_MASK, page_save);
+		up(&ac97->mutex); /* unlock paging */
+	} else
+		err = func(kcontrol, ucontrol);
+	return err;
+}
+
+/* for rev2.3 paging */
+int snd_ac97_page_get_single(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+{
+	return snd_ac97_getput_page(kcontrol, ucontrol, snd_ac97_get_single);
+}
+
+/* for rev2.3 paging */
+int snd_ac97_page_put_single(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+{
+	return snd_ac97_getput_page(kcontrol, ucontrol, snd_ac97_put_single);
+}
+
 static const snd_kcontrol_new_t snd_ac97_controls_master_mono[2] = {
 AC97_SINGLE("Master Mono Playback Switch", AC97_MASTER_MONO, 15, 1, 1),
 AC97_SINGLE("Master Mono Playback Volume", AC97_MASTER_MONO, 0, 31, 1)
@@ -1009,14 +1048,14 @@
 			kfree(bus->pcms);
 		if (bus->private_free)
 			bus->private_free(bus);
-		snd_magic_kfree(bus);
+		kfree(bus);
 	}
 	return 0;
 }
 
 static int snd_ac97_bus_dev_free(snd_device_t *device)
 {
-	ac97_bus_t *bus = snd_magic_cast(ac97_bus_t, device->device_data, return -ENXIO);
+	ac97_bus_t *bus = device->device_data;
 	return snd_ac97_bus_free(bus);
 }
 
@@ -1024,18 +1063,24 @@
 {
 	if (ac97) {
 		snd_ac97_proc_done(ac97);
-		if (ac97->bus)
+		if (ac97->bus) {
 			ac97->bus->codec[ac97->num] = NULL;
+			if (ac97->bus->shared_type) {
+				down(&shared_codec_mutex);
+				shared_codec[ac97->bus->shared_type-1][ac97->num] = NULL;
+				up(&shared_codec_mutex);
+			}
+		}
 		if (ac97->private_free)
 			ac97->private_free(ac97);
-		snd_magic_kfree(ac97);
+		kfree(ac97);
 	}
 	return 0;
 }
 
 static int snd_ac97_dev_free(snd_device_t *device)
 {
-	ac97_t *ac97 = snd_magic_cast(ac97_t, device->device_data, return -ENXIO);
+	ac97_t *ac97 = device->device_data;
 	snd_ac97_powerdown(ac97); /* for avoiding click noises during shut down */
 	return snd_ac97_free(ac97);
 }
@@ -1120,6 +1165,7 @@
 	snd_ac97_write_cache(ac97, reg, 0x8000);
 }
 
+/* check the volume resolution of center/lfe */
 static void snd_ac97_change_volume_params2(ac97_t * ac97, int reg, int shift, unsigned char *max)
 {
 	unsigned short val, val1;
@@ -1135,6 +1181,7 @@
 	snd_ac97_write_cache(ac97, reg, 0x8080);
 }
 
+/* check whether the volume resolution is 4 or 5 bits */
 static void snd_ac97_change_volume_params3(ac97_t * ac97, int reg, unsigned char *max)
 {
 	unsigned short val, val1;
@@ -1150,6 +1197,18 @@
 	snd_ac97_write_cache(ac97, reg, 0x8000);
 }
 
+/* check whether the volume is mono or stereo */
+static int snd_ac97_is_stereo_vol(ac97_t *ac97, int reg)
+{
+	unsigned short val, val1, val2;
+	val = snd_ac97_read(ac97, reg);
+	val1 = val | 0x8000 | (0x01 << 8);
+	snd_ac97_write(ac97, reg, val1);
+	val2 = snd_ac97_read(ac97, reg);
+	snd_ac97_write(ac97, reg, val); /* restore */
+	return val1 == val2;
+}
+
 static inline int printable(unsigned int x)
 {
 	x &= 0xff;
@@ -1178,6 +1237,9 @@
 	snd_kcontrol_t *kctl;
 	int stereo = 0;
 
+	if (! snd_ac97_valid_reg(ac97, reg))
+		return 0;
+
 	if (ac97->flags & AC97_STEREO_MUTES) {
 		/* check whether both mute bits work */
 		unsigned short val, val1;
@@ -1208,6 +1270,9 @@
 	int err;
 	snd_kcontrol_new_t tmp = AC97_DOUBLE(name, reg, 8, 0, (unsigned int)max, 1);
 	tmp.index = ac97->num;
+
+	if (! snd_ac97_valid_reg(ac97, reg))
+		return 0;
 	if ((err = snd_ctl_add(card, snd_ctl_new1(&tmp, ac97))) < 0)
 		return err;
 	snd_ac97_write_cache(ac97, reg,
@@ -1225,6 +1290,9 @@
 	char name[44];
 	unsigned char max;
 
+	if (! snd_ac97_valid_reg(ac97, reg))
+		return 0;
+
 	sprintf(name, "%s Switch", pfx);
 	if ((err = snd_ac97_cmute_new(card, name, reg, ac97)) < 0)
 		return err;
@@ -1239,6 +1307,8 @@
 }
 
 
+static unsigned int snd_ac97_determine_spdif_rates(ac97_t *ac97);
+
 static int snd_ac97_mixer_build(ac97_t * ac97)
 {
 	snd_card_t *card = ac97->bus->card;
@@ -1293,11 +1363,8 @@
 	}
 
 	/* build headphone controls */
-	if (snd_ac97_try_volume_mix(ac97, AC97_HEADPHONE) || ac97->id == AC97_ID_STAC9708) {
-		const char *name = ac97->id == AC97_ID_STAC9708 ? 
-			"Sigmatel Surround Playback" :
-			"Headphone Playback";
-		if ((err = snd_ac97_cmix_new(card, name, AC97_HEADPHONE, 1, ac97)) < 0)
+	if (snd_ac97_try_volume_mix(ac97, AC97_HEADPHONE)) {
+		if ((err = snd_ac97_cmix_new(card, "Headphone Playback", AC97_HEADPHONE, 1, ac97)) < 0)
 			return err;
 	}
 	
@@ -1332,7 +1399,8 @@
 		for (idx = 0; idx < 2; idx++)
 			if ((err = snd_ctl_add(card, snd_ac97_cnew(&snd_ac97_controls_pc_beep[idx], ac97))) < 0)
 				return err;
-		snd_ac97_write_cache(ac97, AC97_PC_BEEP, 0x801e);
+		snd_ac97_write_cache(ac97, AC97_PC_BEEP,
+				     snd_ac97_read(ac97, AC97_PC_BEEP) | 0x801e);
 	}
 	
 	/* build Phone controls */
@@ -1349,15 +1417,26 @@
 	
 	/* build MIC controls */
 	snd_ac97_change_volume_params3(ac97, AC97_MIC, &max);
-	for (idx = 0; idx < 3; idx++) {
-		if ((err = snd_ctl_add(card, kctl = snd_ac97_cnew(&snd_ac97_controls_mic[idx], ac97))) < 0)
+	if (snd_ac97_is_stereo_vol(ac97, AC97_MIC)) {
+		/* build stereo mic */
+		if ((err = snd_ac97_cmute_new(card, "Mic Playback Switch", AC97_MIC, ac97)) < 0)
 			return err;
-		if (idx == 1) {		// volume
-			kctl->private_value &= ~(0xff << 16);
-			kctl->private_value |= (int)max << 16;
+		if ((err = snd_ac97_cvol_new(card, "Mic Playback Volume", AC97_MIC, max, ac97)) < 0)
+			return err;
+		if ((err = snd_ctl_add(card, snd_ac97_cnew(&snd_ac97_controls_mic[2], ac97))) < 0)
+			return err;
+	} else {
+		/* build mono mic */
+		for (idx = 0; idx < 3; idx++) {
+			if ((err = snd_ctl_add(card, kctl = snd_ac97_cnew(&snd_ac97_controls_mic[idx], ac97))) < 0)
+				return err;
+			if (idx == 1) {		// volume
+				kctl->private_value &= ~(0xff << 16);
+				kctl->private_value |= (int)max << 16;
+			}
 		}
+		snd_ac97_write_cache(ac97, AC97_MIC, 0x8000 | max);
 	}
-	snd_ac97_write_cache(ac97, AC97_MIC, 0x8000 | max);
 
 	/* build Line controls */
 	if ((err = snd_ac97_cmix_new(card, "Line Playback", AC97_LINE, 0, ac97)) < 0)
@@ -1410,9 +1489,7 @@
 		if ((err = snd_ac97_cmute_new(card, "PCM Playback Switch", AC97_PCM, ac97)) < 0)
 			return err;
 		/* FIXME: C-Media chips have no PCM volume!! */
-		if (/*ac97->id == 0x434d4941 ||*/
-		    ac97->id == 0x434d4942 ||
-		    ac97->id == 0x434d4961)
+		if (ac97->id == AC97_ID_CM9739)
 			snd_ac97_write_cache(ac97, AC97_PCM, 0x9f1f);
 		else {
 			if ((err = snd_ac97_cvol_new(card, "PCM Playback Volume", AC97_PCM, 31, ac97)) < 0)
@@ -1423,8 +1500,10 @@
 	/* build Capture controls */
 	if ((err = snd_ctl_add(card, snd_ac97_cnew(&snd_ac97_control_capture_src, ac97))) < 0)
 		return err;
-	if ((err = snd_ac97_cmute_new(card, "Capture Switch", AC97_REC_GAIN, ac97)) < 0)
-		return err;
+	if (snd_ac97_try_bit(ac97, AC97_REC_GAIN, 15)) {
+		if ((err = snd_ac97_cmute_new(card, "Capture Switch", AC97_REC_GAIN, ac97)) < 0)
+			return err;
+	}
 	if ((err = snd_ctl_add(card, snd_ac97_cnew(&snd_ac97_control_capture_vol, ac97))) < 0)
 		return err;
 	snd_ac97_write_cache(ac97, AC97_REC_SEL, 0x0000);
@@ -1520,6 +1599,7 @@
 			/* set default PCM S/PDIF params */
 			/* consumer,PCM audio,no copyright,no preemphasis,PCM coder,original,48000Hz */
 			snd_ac97_write_cache(ac97, AC97_SPDIF, 0x2a20);
+			ac97->rates[AC97_RATES_SPDIF] = snd_ac97_determine_spdif_rates(ac97);
 		}
 		ac97->spdif_status = SNDRV_PCM_DEFAULT_CON_SPDIF;
 	}
@@ -1672,10 +1752,10 @@
 		 */
 		/* test if we can write to the record gain volume register */
 		snd_ac97_write_cache(ac97, AC97_REC_GAIN, 0x8a05);
-		if (snd_ac97_read(ac97, AC97_REC_GAIN) == 0x8a05)
+		if ((snd_ac97_read(ac97, AC97_REC_GAIN) & 0x7fff) == 0x0a05)
 			return 0;
 		set_current_state(TASK_UNINTERRUPTIBLE);
-		schedule_timeout(HZ/100);
+		schedule_timeout(1);
 	} while (time_after_eq(end_time, jiffies));
 	return -ENODEV;
 }
@@ -1683,45 +1763,47 @@
 /**
  * snd_ac97_bus - create an AC97 bus component
  * @card: the card instance
- * @_bus: the template of AC97 bus, callbacks and
- *         the private data.
+ * @num: the bus number
+ * @ops: the bus callbacks table
+ * @private_data: private data pointer for the new instance
  * @rbus: the pointer to store the new AC97 bus instance.
  *
  * Creates an AC97 bus component.  An ac97_bus_t instance is newly
- * allocated and initialized from the template (_bus).
+ * allocated and initialized.
  *
- * The template must include the valid callbacks (at least read and
- * write), the bus number (num), and the private data (private_data).
- * The other callbacks, wait and reset, are not mandatory.
+ * The ops table must include valid callbacks (at least read and
+ * write).  The other callbacks, wait and reset, are not mandatory.
  * 
  * The clock is set to 48000.  If another clock is needed, set
- * bus->clock manually.
+ * (*rbus)->clock manually.
  *
  * The AC97 bus instance is registered as a low-level device, so you don't
  * have to release it manually.
  *
  * Returns zero if successful, or a negative error code on failure.
  */
-int snd_ac97_bus(snd_card_t * card, ac97_bus_t * _bus, ac97_bus_t ** rbus)
+int snd_ac97_bus(snd_card_t *card, int num, ac97_bus_ops_t *ops,
+		 void *private_data, ac97_bus_t **rbus)
 {
 	int err;
 	ac97_bus_t *bus;
-	static snd_device_ops_t ops = {
+	static snd_device_ops_t dev_ops = {
 		.dev_free =	snd_ac97_bus_dev_free,
 	};
 
 	snd_assert(card != NULL, return -EINVAL);
-	snd_assert(_bus != NULL && rbus != NULL, return -EINVAL);
-	bus = snd_magic_kmalloc(ac97_bus_t, 0, GFP_KERNEL);
+	snd_assert(rbus != NULL, return -EINVAL);
+	bus = kcalloc(1, sizeof(*bus), GFP_KERNEL);
 	if (bus == NULL)
 		return -ENOMEM;
-	*bus = *_bus;
 	bus->card = card;
-	if (bus->clock == 0)
-		bus->clock = 48000;
+	bus->num = num;
+	bus->ops = ops;
+	bus->private_data = private_data;
+	bus->clock = 48000;
 	spin_lock_init(&bus->bus_lock);
 	snd_ac97_bus_proc_init(bus);
-	if ((err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, bus, &ops)) < 0) {
+	if ((err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, bus, &dev_ops)) < 0) {
 		snd_ac97_bus_free(bus);
 		return err;
 	}
@@ -1732,25 +1814,23 @@
 /**
  * snd_ac97_mixer - create an Codec97 component
  * @bus: the AC97 bus which codec is attached to
- * @_ac97: the template of ac97, including index, callbacks and
+ * @template: the template of ac97, including index, callbacks and
  *         the private data.
  * @rac97: the pointer to store the new ac97 instance.
  *
  * Creates an Codec97 component.  An ac97_t instance is newly
- * allocated and initialized from the template (_ac97).  The codec
+ * allocated and initialized from the template.  The codec
  * is then initialized by the standard procedure.
  *
- * The template must include the valid callbacks (at least read and
- * write), the codec number (num) and address (addr), and the private
- * data (private_data).  The other callbacks, wait and reset, are not
- * mandatory.
+ * The template must include the codec number (num) and address (addr),
+ * and the private data (private_data).
  * 
  * The ac97 instance is registered as a low-level device, so you don't
  * have to release it manually.
  *
  * Returns zero if successful, or a negative error code on failure.
  */
-int snd_ac97_mixer(ac97_bus_t * bus, ac97_t * _ac97, ac97_t ** rac97)
+int snd_ac97_mixer(ac97_bus_t *bus, ac97_template_t *template, ac97_t **rac97)
 {
 	int err;
 	ac97_t *ac97;
@@ -1764,33 +1844,63 @@
 
 	snd_assert(rac97 != NULL, return -EINVAL);
 	*rac97 = NULL;
-	snd_assert(bus != NULL && _ac97 != NULL, return -EINVAL);
-	snd_assert(_ac97->num < 4 && bus->codec[_ac97->num] == NULL, return -EINVAL);
+	snd_assert(bus != NULL && template != NULL, return -EINVAL);
+	snd_assert(template->num < 4 && bus->codec[template->num] == NULL, return -EINVAL);
+
+	snd_assert(bus->shared_type <= AC97_SHARED_TYPES, return -EINVAL);
+	if (bus->shared_type) {
+		/* already shared? */
+		down(&shared_codec_mutex);
+		ac97 = shared_codec[bus->shared_type-1][template->num];
+		if (ac97) {
+			if ((ac97_is_audio(ac97) && (template->scaps & AC97_SCAP_SKIP_AUDIO)) ||
+			    (ac97_is_modem(ac97) && (template->scaps & AC97_SCAP_SKIP_MODEM))) {
+				up(&shared_codec_mutex);
+				return -EACCES; /* skip this */
+			}
+		}
+		up(&shared_codec_mutex);
+	}
+
 	card = bus->card;
-	ac97 = snd_magic_kmalloc(ac97_t, 0, GFP_KERNEL);
+	ac97 = kcalloc(1, sizeof(*ac97), GFP_KERNEL);
 	if (ac97 == NULL)
 		return -ENOMEM;
-	*ac97 = *_ac97;
+	ac97->private_data = template->private_data;
+	ac97->private_free = template->private_free;
 	ac97->bus = bus;
+	ac97->pci = template->pci;
+	ac97->num = template->num;
+	ac97->addr = template->addr;
+	ac97->scaps = template->scaps;
+	ac97->limited_regs = template->limited_regs;
+	memcpy(ac97->reg_accessed, template->reg_accessed, sizeof(ac97->reg_accessed));
 	bus->codec[ac97->num] = ac97;
 	spin_lock_init(&ac97->reg_lock);
+	init_MUTEX(&ac97->mutex);
 
 	if (ac97->pci) {
 		pci_read_config_word(ac97->pci, PCI_SUBSYSTEM_VENDOR_ID, &ac97->subsystem_vendor);
 		pci_read_config_word(ac97->pci, PCI_SUBSYSTEM_ID, &ac97->subsystem_device);
 	}
-	if (bus->reset) {
-		bus->reset(ac97);
+	if (bus->ops->reset) {
+		bus->ops->reset(ac97);
 		goto __access_ok;
 	}
 
 	snd_ac97_write(ac97, AC97_RESET, 0);	/* reset to defaults */
-	if (bus->wait)
-		bus->wait(ac97);
+	if (bus->ops->wait)
+		bus->ops->wait(ac97);
 	else {
 		udelay(50);
-		if (ac97_reset_wait(ac97, HZ/2, 0) < 0 &&
-		    ac97_reset_wait(ac97, HZ/2, 1) < 0) {
+		if (ac97->scaps & AC97_SCAP_SKIP_AUDIO)
+			err = ac97_reset_wait(ac97, HZ/2, 1);
+		else {
+			err = ac97_reset_wait(ac97, HZ/2, 0);
+			if (err < 0)
+				err = ac97_reset_wait(ac97, HZ/2, 1);
+		}
+		if (err < 0) {
 			snd_printk(KERN_WARNING "AC'97 %d does not respond - RESET\n", ac97->num);
 			/* proceed anyway - it's often non-critical */
 		}
@@ -1803,26 +1913,12 @@
 		snd_ac97_free(ac97);
 		return -EIO;
 	}
-	/* AC97 audio codec chip revision detection. */
-	/* Currently only Realtek ALC650 detection implemented. */
-	switch(ac97->id & 0xfffffff0) {
-	case 0x414c4720:        /* ALC650 */
-		reg = snd_ac97_read(ac97, AC97_ALC650_REVISION);
-		if (((reg & 0x3f) >= 0) && ((reg & 0x3f) < 3))
-			ac97->id = 0x414c4720;          /* Old version */
-		else if (((reg & 0x3f) >= 3) && ((reg & 0x3f) < 0x10))
-			ac97->id = 0x414c4721;          /* D version */
-		else if ((reg&0x30) == 0x10)
-			ac97->id = 0x414c4722;          /* E version */
-		else if ((reg&0x30) == 0x20)
-			ac97->id = 0x414c4723;          /* F version */
-        }
 	
 	/* test for AC'97 */
 	if (!(ac97->scaps & AC97_SCAP_SKIP_AUDIO) && !(ac97->scaps & AC97_SCAP_AUDIO)) {
 		/* test if we can write to the record gain volume register */
 		snd_ac97_write_cache(ac97, AC97_REC_GAIN, 0x8a06);
-		if ((err = snd_ac97_read(ac97, AC97_REC_GAIN)) == 0x8a06)
+		if (((err = snd_ac97_read(ac97, AC97_REC_GAIN)) & 0x7fff) == 0x0a06)
 			ac97->scaps |= AC97_SCAP_AUDIO;
 	}
 	if (ac97->scaps & AC97_SCAP_AUDIO) {
@@ -1848,7 +1944,7 @@
 		return -EACCES;
 	}
 
-	if (bus->reset) // FIXME: always skipping?
+	if (bus->ops->reset) // FIXME: always skipping?
 		goto __ready_ok;
 
 	/* FIXME: add powerdown control */
@@ -1865,9 +1961,9 @@
 			if ((snd_ac97_read(ac97, AC97_POWERDOWN) & 0x0f) == 0x0f)
 				goto __ready_ok;
 			set_current_state(TASK_UNINTERRUPTIBLE);
-			schedule_timeout(HZ/10);
+			schedule_timeout(1);
 		} while (time_after_eq(end_time, jiffies));
-		snd_printk(KERN_ERR "AC'97 %d analog subsections not ready\n", ac97->num);
+		snd_printk(KERN_WARNING "AC'97 %d analog subsections not ready\n", ac97->num);
 	}
 
 	/* FIXME: add powerdown control */
@@ -1898,9 +1994,9 @@
 			if ((snd_ac97_read(ac97, AC97_EXTENDED_MSTATUS) & tmp) == tmp)
 				goto __ready_ok;
 			set_current_state(TASK_UNINTERRUPTIBLE);
-			schedule_timeout(HZ/10);
+			schedule_timeout(1);
 		} while (time_after_eq(end_time, jiffies));
-		snd_printk(KERN_ERR "MC'97 %d converters and GPIO not ready (0x%x)\n", ac97->num, snd_ac97_read(ac97, AC97_EXTENDED_MSTATUS));
+		snd_printk(KERN_WARNING "MC'97 %d converters and GPIO not ready (0x%x)\n", ac97->num, snd_ac97_read(ac97, AC97_EXTENDED_MSTATUS));
 	}
 	
       __ready_ok:
@@ -1919,12 +2015,7 @@
 	}
 	if (ac97->ext_id & AC97_EI_SPDIF) {
 		/* codec specific code (patch) should override these values */
-		if (ac97->flags & AC97_CS_SPDIF)
-			ac97->rates[AC97_RATES_SPDIF] = SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_44100;
-		else if (ac97->id == AC97_ID_CM9739)
-			ac97->rates[AC97_RATES_SPDIF] = SNDRV_PCM_RATE_48000;
-		else
-			ac97->rates[AC97_RATES_SPDIF] = snd_ac97_determine_spdif_rates(ac97);
+		ac97->rates[AC97_RATES_SPDIF] = SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_32000;
 	}
 	if (ac97->ext_id & AC97_EI_VRM) {	/* MIC VRA support */
 		snd_ac97_determine_rates(ac97, AC97_PCM_MIC_ADC_RATE, 0, &ac97->rates[AC97_RATES_MIC_ADC]);
@@ -1940,10 +2031,10 @@
 		ac97->scaps |= AC97_SCAP_CENTER_LFE_DAC;
 	}
 	/* additional initializations */
-	if (bus->init)
-		bus->init(ac97);
-	snd_ac97_get_name(ac97, ac97->id, name, 0);
-	snd_ac97_get_name(NULL, ac97->id, name, 0);  // ac97->id might be changed in the special setup code
+	if (bus->ops->init)
+		bus->ops->init(ac97);
+	snd_ac97_get_name(ac97, ac97->id, name, !ac97_is_audio(ac97));
+	snd_ac97_get_name(NULL, ac97->id, name, !ac97_is_audio(ac97));  // ac97->id might be changed in the special setup code
 	if (ac97_is_audio(ac97)) {
 		if (card->mixername[0] == '\0') {
 			strcpy(card->mixername, name);
@@ -1995,6 +2086,13 @@
 		return err;
 	}
 	*rac97 = ac97;
+
+	if (bus->shared_type) {
+		down(&shared_codec_mutex);
+		shared_codec[bus->shared_type-1][ac97->num] = ac97;
+		up(&shared_codec_mutex);
+	}
+
 	return 0;
 }
 
@@ -2054,8 +2152,8 @@
 {
 	int i, is_ad18xx, codec;
 
-	if (ac97->bus->reset) {
-		ac97->bus->reset(ac97);
+	if (ac97->bus->ops->reset) {
+		ac97->bus->ops->reset(ac97);
 		goto  __reset_ready;
 	}
 
@@ -2066,23 +2164,33 @@
 	snd_ac97_write(ac97, AC97_GENERAL_PURPOSE, 0);
 
 	snd_ac97_write(ac97, AC97_POWERDOWN, ac97->regs[AC97_POWERDOWN]);
-	ac97->bus->write(ac97, AC97_MASTER, 0x8101);
-	for (i = 0; i < 10; i++) {
-		if (snd_ac97_read(ac97, AC97_MASTER) == 0x8101)
-			break;
-		set_current_state(TASK_UNINTERRUPTIBLE);
-		schedule_timeout(1);
-	}
-	/* FIXME: extra delay */
-	ac97->bus->write(ac97, AC97_MASTER, 0x8000);
-	if (snd_ac97_read(ac97, AC97_MASTER) != 0x8000) {
-		set_current_state(TASK_UNINTERRUPTIBLE);
-		schedule_timeout(HZ/4);
+	if (ac97_is_audio(ac97)) {
+		ac97->bus->ops->write(ac97, AC97_MASTER, 0x8101);
+		for (i = HZ/10; i >= 0; i--) {
+			if (snd_ac97_read(ac97, AC97_MASTER) == 0x8101)
+				break;
+			set_current_state(TASK_UNINTERRUPTIBLE);
+			schedule_timeout(1);
+		}
+		/* FIXME: extra delay */
+		ac97->bus->ops->write(ac97, AC97_MASTER, 0x8000);
+		if (snd_ac97_read(ac97, AC97_MASTER) != 0x8000) {
+			set_current_state(TASK_UNINTERRUPTIBLE);
+			schedule_timeout(HZ/4);
+		}
+	} else {
+		for (i = HZ/10; i >= 0; i--) {
+			unsigned short val = snd_ac97_read(ac97, AC97_EXTENDED_MID);
+			if (val != 0xffff && (val & 1) != 0)
+				break;
+			set_current_state(TASK_UNINTERRUPTIBLE);
+			schedule_timeout(1);
+		}
 	}
 __reset_ready:
 
-	if (ac97->bus->init)
-		ac97->bus->init(ac97);
+	if (ac97->bus->ops->init)
+		ac97->bus->ops->init(ac97);
 
 	is_ad18xx = (ac97->flags & AC97_AD_MULTI);
 	if (is_ad18xx) {
@@ -2093,7 +2201,7 @@
 			/* select single codec */
 			snd_ac97_update_bits(ac97, AC97_AD_SERIAL_CFG, 0x7000,
 					     ac97->spec.ad18xx.unchained[codec] | ac97->spec.ad18xx.chained[codec]);
-			ac97->bus->write(ac97, AC97_AD_CODEC_CFG, ac97->spec.ad18xx.codec_cfg[codec]);
+			ac97->bus->ops->write(ac97, AC97_AD_CODEC_CFG, ac97->spec.ad18xx.codec_cfg[codec]);
 		}
 		/* select all codecs */
 		snd_ac97_update_bits(ac97, AC97_AD_SERIAL_CFG, 0x7000, 0x7000);
@@ -2118,7 +2226,7 @@
 						snd_ac97_update_bits(ac97, AC97_AD_SERIAL_CFG, 0x7000,
 								     ac97->spec.ad18xx.unchained[codec] | ac97->spec.ad18xx.chained[codec]);
 						/* update PCM bits */
-						ac97->bus->write(ac97, AC97_PCM, ac97->spec.ad18xx.pcmreg[codec]);
+						ac97->bus->ops->write(ac97, AC97_PCM, ac97->spec.ad18xx.pcmreg[codec]);
 					}
 					/* select all codecs */
 					snd_ac97_update_bits(ac97, AC97_AD_SERIAL_CFG, 0x7000, 0x7000);
@@ -2151,42 +2259,57 @@
 
 /*
  */
-int snd_ac97_remove_ctl(ac97_t *ac97, const char *name)
+static void set_ctl_name(char *dst, const char *src, const char *suffix)
+{
+	if (suffix)
+		sprintf(dst, "%s %s", src, suffix);
+	else
+		strcpy(dst, src);
+}	
+
+int snd_ac97_remove_ctl(ac97_t *ac97, const char *name, const char *suffix)
 {
 	snd_ctl_elem_id_t id;
 	memset(&id, 0, sizeof(id));
-	strcpy(id.name, name);
+	set_ctl_name(id.name, name, suffix);
 	id.iface = SNDRV_CTL_ELEM_IFACE_MIXER;
 	return snd_ctl_remove_id(ac97->bus->card, &id);
 }
 
-static snd_kcontrol_t *ctl_find(ac97_t *ac97, const char *name)
+static snd_kcontrol_t *ctl_find(ac97_t *ac97, const char *name, const char *suffix)
 {
 	snd_ctl_elem_id_t sid;
 	memset(&sid, 0, sizeof(sid));
-	strcpy(sid.name, name);
+	set_ctl_name(sid.name, name, suffix);
 	sid.iface = SNDRV_CTL_ELEM_IFACE_MIXER;
 	return snd_ctl_find_id(ac97->bus->card, &sid);
 }
 
-int snd_ac97_rename_ctl(ac97_t *ac97, const char *src, const char *dst)
+int snd_ac97_rename_ctl(ac97_t *ac97, const char *src, const char *dst, const char *suffix)
 {
-	snd_kcontrol_t *kctl = ctl_find(ac97, src);
+	snd_kcontrol_t *kctl = ctl_find(ac97, src, suffix);
 	if (kctl) {
-		strcpy(kctl->id.name, dst);
+		set_ctl_name(kctl->id.name, dst, suffix);
 		return 0;
 	}
 	return -ENOENT;
 }
 
-int snd_ac97_swap_ctl(ac97_t *ac97, const char *s1, const char *s2)
+/* rename both Volume and Switch controls - don't check the return value */
+void snd_ac97_rename_vol_ctl(ac97_t *ac97, const char *src, const char *dst)
+{
+	snd_ac97_rename_ctl(ac97, src, dst, "Switch");
+	snd_ac97_rename_ctl(ac97, src, dst, "Volume");
+}
+
+int snd_ac97_swap_ctl(ac97_t *ac97, const char *s1, const char *s2, const char *suffix)
 {
 	snd_kcontrol_t *kctl1, *kctl2;
-	kctl1 = ctl_find(ac97, s1);
-	kctl2 = ctl_find(ac97, s2);
+	kctl1 = ctl_find(ac97, s1, suffix);
+	kctl2 = ctl_find(ac97, s2, suffix);
 	if (kctl1 && kctl2) {
-		strcpy(kctl1->id.name, s2);
-		strcpy(kctl2->id.name, s1);
+		set_ctl_name(kctl1->id.name, s2, suffix);
+		set_ctl_name(kctl2->id.name, s1, suffix);
 		return 0;
 	}
 	return -ENOENT;
@@ -2194,26 +2317,22 @@
 
 static int swap_headphone(ac97_t *ac97, int remove_master)
 {
-	/* FIXME: error checks.. */
 	if (remove_master) {
-		if (ctl_find(ac97, "Headphone Playback Switch") == NULL)
+		if (ctl_find(ac97, "Headphone Playback Switch", NULL) == NULL)
 			return 0;
-		snd_ac97_remove_ctl(ac97, "Master Playback Switch");
-		snd_ac97_remove_ctl(ac97, "Master Playback Volume");
-	} else {
-		snd_ac97_rename_ctl(ac97, "Master Playback Switch", "Line-Out Playback Switch");
-		snd_ac97_rename_ctl(ac97, "Master Playback Volume", "Line-Out Playback Volume");
-	}
-	snd_ac97_rename_ctl(ac97, "Headphone Playback Switch", "Master Playback Switch");
-	snd_ac97_rename_ctl(ac97, "Headphone Playback Volume", "Master Playback Volume");
+		snd_ac97_remove_ctl(ac97, "Master Playback", "Switch");
+		snd_ac97_remove_ctl(ac97, "Master Playback", "Volume");
+	} else
+		snd_ac97_rename_vol_ctl(ac97, "Master Playback", "Line-Out Playback");
+	snd_ac97_rename_vol_ctl(ac97, "Headphone Playback", "Master Playback");
 	return 0;
 }
 
 static int swap_surround(ac97_t *ac97)
 {
 	/* FIXME: error checks.. */
-	snd_ac97_swap_ctl(ac97, "Master Playback Switch", "Surround Playback Switch");
-	snd_ac97_swap_ctl(ac97, "Master Playback Volume", "Surround Playback Volume");
+	snd_ac97_swap_ctl(ac97, "Master Playback", "Surround Playback", "Switch");
+	snd_ac97_swap_ctl(ac97, "Master Playback", "Surround Playback", "Volume");
 	return 0;
 }
 
diff -Nru a/sound/pci/ac97/ac97_id.h b/sound/pci/ac97/ac97_id.h
--- a/sound/pci/ac97/ac97_id.h	2004-10-18 14:57:04 -07:00
+++ b/sound/pci/ac97/ac97_id.h	2004-10-18 14:57:04 -07:00
@@ -45,7 +45,14 @@
 #define AC97_ID_CS4201		0x43525948
 #define AC97_ID_CS4205		0x43525958
 #define AC97_ID_CS_MASK		0xfffffff8	/* bit 0-2: rev */
+#define AC97_ID_ALC100		0x414c4300
 #define AC97_ID_ALC650		0x414c4720
+#define AC97_ID_ALC650D		0x414c4721
+#define AC97_ID_ALC650E		0x414c4722
+#define AC97_ID_ALC650F		0x414c4723
+#define AC97_ID_ALC655		0x414c4760
+#define AC97_ID_ALC658		0x414c4780
+#define AC97_ID_ALC850		0x414c4790
 #define AC97_ID_YMF753		0x594d4803
 #define AC97_ID_VT1616		0x49434551
 #define AC97_ID_CM9738		0x434d4941
diff -Nru a/sound/pci/ac97/ac97_local.h b/sound/pci/ac97/ac97_local.h
--- a/sound/pci/ac97/ac97_local.h	2004-10-18 14:56:28 -07:00
+++ b/sound/pci/ac97/ac97_local.h	2004-10-18 14:56:28 -07:00
@@ -23,10 +23,15 @@
  */
 
 #define AC97_SINGLE_VALUE(reg,shift,mask,invert) ((reg) | ((shift) << 8) | ((mask) << 16) | ((invert) << 24))
+#define AC97_PAGE_SINGLE_VALUE(reg,shift,mask,invert,page) ((reg) | ((shift) << 8) | ((mask) << 16) | ((invert) << 24) | ((page) << 25))
 #define AC97_SINGLE(xname, reg, shift, mask, invert) \
 { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .info = snd_ac97_info_single, \
   .get = snd_ac97_get_single, .put = snd_ac97_put_single, \
   .private_value =  AC97_SINGLE_VALUE(reg, shift, mask, invert) }
+#define AC97_PAGE_SINGLE(xname, reg, shift, mask, invert, page)		\
+{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .info = snd_ac97_info_single, \
+  .get = snd_ac97_page_get_single, .put = snd_ac97_page_put_single, \
+  .private_value =  AC97_PAGE_SINGLE_VALUE(reg, shift, mask, invert, page) }
 
 /* ac97_codec.c */
 extern const char *snd_ac97_stereo_enhancements[];
@@ -37,10 +42,13 @@
 int snd_ac97_info_single(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo);
 int snd_ac97_get_single(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol);
 int snd_ac97_put_single(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol);
+int snd_ac97_page_get_single(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol);
+int snd_ac97_page_put_single(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol);
 int snd_ac97_try_bit(ac97_t * ac97, int reg, int bit);
-int snd_ac97_remove_ctl(ac97_t *ac97, const char *name);
-int snd_ac97_rename_ctl(ac97_t *ac97, const char *src, const char *dst);
-int snd_ac97_swap_ctl(ac97_t *ac97, const char *s1, const char *s2);
+int snd_ac97_remove_ctl(ac97_t *ac97, const char *name, const char *suffix);
+int snd_ac97_rename_ctl(ac97_t *ac97, const char *src, const char *dst, const char *suffix);
+int snd_ac97_swap_ctl(ac97_t *ac97, const char *s1, const char *s2, const char *suffix);
+void snd_ac97_rename_vol_ctl(ac97_t *ac97, const char *src, const char *dst);
 
 /* ac97_proc.c */
 void snd_ac97_bus_proc_init(ac97_bus_t * ac97);
diff -Nru a/sound/pci/ac97/ac97_patch.c b/sound/pci/ac97/ac97_patch.c
--- a/sound/pci/ac97/ac97_patch.c	2004-10-18 14:57:03 -07:00
+++ b/sound/pci/ac97/ac97_patch.c	2004-10-18 14:57:03 -07:00
@@ -35,8 +35,6 @@
 #include "ac97_id.h"
 #include "ac97_local.h"
 
-#define chip_t ac97_t
-
 /*
  *  Chip specific initialization
  */
@@ -51,6 +49,21 @@
 	return 0;
 }
 
+/* set to the page, update bits and restore the page */
+static int ac97_update_bits_page(ac97_t *ac97, unsigned short reg, unsigned short mask, unsigned short value, unsigned short page)
+{
+	unsigned short page_save;
+	int ret;
+
+	down(&ac97->mutex);
+	page_save = snd_ac97_read(ac97, AC97_INT_PAGING) & AC97_PAGE_MASK;
+	snd_ac97_update_bits(ac97, AC97_INT_PAGING, AC97_PAGE_MASK, page);
+	ret = snd_ac97_update_bits(ac97, reg, mask, value);
+	snd_ac97_update_bits(ac97, AC97_INT_PAGING, AC97_PAGE_MASK, page_save);
+	up(&ac97->mutex); /* unlock paging */
+	return ret;
+}
+
 /* The following snd_ac97_ymf753_... items added by David Shust (dshust@shustring.com) */
 
 /* It is possible to indicate to the Yamaha YMF753 the type of speakers being used. */
@@ -204,7 +217,7 @@
 	if ((err = snd_ctl_add(ac97->bus->card, kctl = snd_ac97_cnew(&snd_ac97_controls_3d[0], ac97))) < 0)
 		return err;
 	strcpy(kctl->id.name, "3D Control - Wide");
-	kctl->private_value = AC97_3D_CONTROL | (9 << 8) | (7 << 16);
+	kctl->private_value = AC97_SINGLE_VALUE(AC97_3D_CONTROL, 9, 7, 0);
 	snd_ac97_write_cache(ac97, AC97_3D_CONTROL, 0x0000);
 	if ((err = snd_ctl_add(ac97->bus->card, snd_ac97_cnew(&snd_ac97_ymf753_controls_speaker, ac97))) < 0)
 		return err;
@@ -315,7 +328,7 @@
 	if ((err = snd_ctl_add(ac97->bus->card, kctl = snd_ac97_cnew(&snd_ac97_controls_3d[0], ac97))) < 0)
 		return err;
 	strcpy(kctl->id.name, "3D Control Sigmatel - Depth");
-	kctl->private_value = AC97_3D_CONTROL | (3 << 16);
+	kctl->private_value = AC97_SINGLE_VALUE(AC97_3D_CONTROL, 2, 3, 0);
 	snd_ac97_write_cache(ac97, AC97_3D_CONTROL, 0x0000);
 	return 0;
 }
@@ -328,11 +341,11 @@
 	if ((err = snd_ctl_add(ac97->bus->card, kctl = snd_ac97_cnew(&snd_ac97_controls_3d[0], ac97))) < 0)
 		return err;
 	strcpy(kctl->id.name, "3D Control Sigmatel - Depth");
-	kctl->private_value = AC97_3D_CONTROL | (3 << 16);
+	kctl->private_value = AC97_SINGLE_VALUE(AC97_3D_CONTROL, 0, 3, 0);
 	if ((err = snd_ctl_add(ac97->bus->card, kctl = snd_ac97_cnew(&snd_ac97_controls_3d[0], ac97))) < 0)
 		return err;
 	strcpy(kctl->id.name, "3D Control Sigmatel - Rear Depth");
-	kctl->private_value = AC97_3D_CONTROL | (2 << 8) | (3 << 16);
+	kctl->private_value = AC97_SINGLE_VALUE(AC97_3D_CONTROL, 2, 3, 0);
 	snd_ac97_write_cache(ac97, AC97_3D_CONTROL, 0x0000);
 	return 0;
 }
@@ -373,22 +386,29 @@
 	.build_specific	= patch_sigmatel_stac97xx_specific
 };
 
-static struct snd_ac97_build_ops patch_sigmatel_stac9708_ops = {
-	.build_3d	= patch_sigmatel_stac9708_3d,
-	.build_specific	= patch_sigmatel_stac97xx_specific
-};
-
 int patch_sigmatel_stac9700(ac97_t * ac97)
 {
 	ac97->build_ops = &patch_sigmatel_stac9700_ops;
 	return 0;
 }
 
+static int patch_sigmatel_stac9708_specific(ac97_t *ac97)
+{
+	snd_ac97_rename_vol_ctl(ac97, "Headphone Playback", "Sigmatel Surround Playback");
+	return patch_sigmatel_stac97xx_specific(ac97);
+}
+
+static struct snd_ac97_build_ops patch_sigmatel_stac9708_ops = {
+	.build_3d	= patch_sigmatel_stac9708_3d,
+	.build_specific	= patch_sigmatel_stac9708_specific
+};
+
 int patch_sigmatel_stac9708(ac97_t * ac97)
 {
 	unsigned int codec72, codec6c;
 
 	ac97->build_ops = &patch_sigmatel_stac9708_ops;
+	ac97->caps |= 0x10;	/* HP (sigmatel surround) support */
 
 	codec72 = snd_ac97_read(ac97, AC97_SIGMATEL_BIAS2) & 0x8000;
 	codec6c = snd_ac97_read(ac97, AC97_SIGMATEL_ANALOG);
@@ -467,11 +487,11 @@
 	int shift = kcontrol->private_value;
 	unsigned short val;
 
-	val = ac97->regs[AC97_SIGMATEL_OUTSEL];
-	if (!((val >> shift) & 4))
+	val = ac97->regs[AC97_SIGMATEL_OUTSEL] >> shift;
+	if (!(val & 4))
 		ucontrol->value.enumerated.item[0] = 0;
 	else
-		ucontrol->value.enumerated.item[0] = 1 + ((val >> shift) & 3);
+		ucontrol->value.enumerated.item[0] = 1 + (val & 3);
 	return 0;
 }
 
@@ -487,8 +507,8 @@
 		val = 0;
 	else
 		val = 4 | (ucontrol->value.enumerated.item[0] - 1);
-	return snd_ac97_update_bits(ac97, AC97_SIGMATEL_OUTSEL,
-				    7 << shift, val << shift);
+	return ac97_update_bits_page(ac97, AC97_SIGMATEL_OUTSEL,
+				     7 << shift, val << shift, 0);
 }
 
 static int snd_ac97_stac9758_input_jack_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo)
@@ -521,8 +541,8 @@
 	ac97_t *ac97 = snd_kcontrol_chip(kcontrol);
 	int shift = kcontrol->private_value;
 
-	return snd_ac97_update_bits(ac97, AC97_SIGMATEL_INSEL, 7 << shift,
-				    ucontrol->value.enumerated.item[0] << shift);
+	return ac97_update_bits_page(ac97, AC97_SIGMATEL_INSEL, 7 << shift,
+				     ucontrol->value.enumerated.item[0] << shift, 0);
 }
 
 static int snd_ac97_stac9758_phonesel_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo)
@@ -550,8 +570,8 @@
 {
 	ac97_t *ac97 = snd_kcontrol_chip(kcontrol);
 
-	return snd_ac97_update_bits(ac97, AC97_SIGMATEL_IOMISC, 3,
-				    ucontrol->value.enumerated.item[0]);
+	return ac97_update_bits_page(ac97, AC97_SIGMATEL_IOMISC, 3,
+				     ucontrol->value.enumerated.item[0], 0);
 }
 
 #define STAC9758_OUTPUT_JACK(xname, shift) \
@@ -596,6 +616,14 @@
 				   ARRAY_SIZE(snd_ac97_sigmatel_stac9758_controls));
 	if (err < 0)
 		return err;
+	/* DAC-A direct */
+	snd_ac97_rename_vol_ctl(ac97, "Headphone Playback", "Front Playback");
+	/* DAC-A to Mix = PCM */
+	/* DAC-B direct = Surround */
+	/* DAC-B to Mix */
+	snd_ac97_rename_vol_ctl(ac97, "Video Playback", "Surround Mix Playback");
+	/* DAC-C direct = Center/LFE */
+
 	return 0;
 }
 
@@ -613,16 +641,16 @@
 		AC97_SIGMATEL_VARIOUS
 	};
 	static unsigned short def_regs[4] = {
-		/* OUTSEL */ 0xd794,
+		/* OUTSEL */ 0xd794, /* CL:CL, SR:SR, LO:MX, LI:DS, MI:DS */
 		/* IOMISC */ 0x2001,
-		/* INSEL */ 0x0201,
+		/* INSEL */ 0x0201, /* LI:LI, MI:M1 */
 		/* VARIOUS */ 0x0040
 	};
 	static unsigned short m675_regs[4] = {
-		/* OUTSEL */ 0x9040,
-		/* IOMISC */ 0x2102,
-		/* INSEL */ 0x0203,
-		/* VARIOUS */ 0x0041
+		/* OUTSEL */ 0xfc70, /* CL:MX, SR:MX, LO:DS, LI:MX, MI:DS */
+		/* IOMISC */ 0x2102, /* HP amp on */
+		/* INSEL */ 0x0203, /* LI:LI, MI:FR */
+		/* VARIOUS */ 0x0041 /* stereo mic */
 	};
 	unsigned short *pregs = def_regs;
 	int i;
@@ -635,6 +663,8 @@
 
 	// patch for SigmaTel
 	ac97->build_ops = &patch_sigmatel_stac9758_ops;
+	/* FIXME: assume only page 0 for writing cache */
+	snd_ac97_update_bits(ac97, AC97_INT_PAGING, AC97_PAGE_MASK, AC97_PAGE_VENDOR);
 	for (i = 0; i < 4; i++)
 		snd_ac97_write_cache(ac97, regs[i], pregs[i]);
 
@@ -654,8 +684,10 @@
 {
 	int err;
 
+	/* con mask, pro mask, default */
 	if ((err = patch_build_controls(ac97, &snd_ac97_controls_spdif[0], 3)) < 0)
 		return err;
+	/* switch, spsa */
 	if ((err = patch_build_controls(ac97, &snd_ac97_cirrus_controls_spdif[0], 1)) < 0)
 		return err;
 	switch (ac97->id & AC97_ID_CS_MASK) {
@@ -714,8 +746,10 @@
 {
 	int err;
 
+	/* con mask, pro mask, default */
 	if ((err = patch_build_controls(ac97, &snd_ac97_controls_spdif[0], 3)) < 0)
 		return err;
+	/* switch */
 	if ((err = patch_build_controls(ac97, &snd_ac97_conexant_controls_spdif[0], 1)) < 0)
 		return err;
 	/* set default PCM S/PDIF params */
@@ -734,6 +768,7 @@
 	ac97->build_ops = &patch_conexant_ops;
 	ac97->flags |= AC97_CX_SPDIF;
         ac97->ext_id |= AC97_EI_SPDIF;	/* force the detection of spdif */
+	ac97->rates[AC97_RATES_SPDIF] = SNDRV_PCM_RATE_48000; /* 48k only */
 	return 0;
 }
 
@@ -821,8 +856,6 @@
 	unsigned short val;
 	int idx, num;
 
-	init_MUTEX(&ac97->spec.ad18xx.mutex);
-
 	val = snd_ac97_read(ac97, AC97_AD_SERIAL_CFG);
 	snd_ac97_write_cache(ac97, AC97_AD_SERIAL_CFG, val);
 	codecs[0] = patch_ad1881_unchained(ac97, 0, (1<<12));
@@ -872,6 +905,8 @@
 	/* AC97_SINGLE("Digital Audio Mode", AC97_AD_MISC, 12, 1, 0), */ /* seems problematic */
 	AC97_SINGLE("Low Power Mixer", AC97_AD_MISC, 14, 1, 0),
 	AC97_SINGLE("Zero Fill DAC", AC97_AD_MISC, 15, 1, 0),
+	AC97_SINGLE("Headphone Jack Sense", AC97_AD_JACK_SPDIF, 9, 1, 1), /* inverted */
+	AC97_SINGLE("Line Jack Sense", AC97_AD_JACK_SPDIF, 8, 1, 1), /* inverted */
 };
 
 static int patch_ad1885_specific(ac97_t * ac97)
@@ -889,16 +924,10 @@
 
 int patch_ad1885(ac97_t * ac97)
 {
-	unsigned short jack;
-
 	patch_ad1881(ac97);
 	/* This is required to deal with the Intel D815EEAL2 */
 	/* i.e. Line out is actually headphone out from codec */
 
-	/* turn off jack sense bits D8 & D9 */
-	jack = snd_ac97_read(ac97, AC97_AD_JACK_SPDIF);
-	snd_ac97_write_cache(ac97, AC97_AD_JACK_SPDIF, jack | 0x0300);
-
 	/* set default */
 	snd_ac97_write_cache(ac97, AC97_AD_MISC, 0x0404);
 
@@ -1114,10 +1143,8 @@
 static int patch_ad1888_specific(ac97_t *ac97)
 {
 	/* rename 0x04 as "Master" and 0x02 as "Master Surround" */
-	snd_ac97_rename_ctl(ac97, "Master Playback Switch", "Master Surround Playback Switch");
-	snd_ac97_rename_ctl(ac97, "Master Playback Volume", "Master Surround Playback Volume");
-	snd_ac97_rename_ctl(ac97, "Headphone Playback Switch", "Master Playback Switch");
-	snd_ac97_rename_ctl(ac97, "Headphone Playback Volume", "Master Playback Volume");
+	snd_ac97_rename_vol_ctl(ac97, "Master Playback", "Master Surround Playback");
+	snd_ac97_rename_vol_ctl(ac97, "Headphone Playback", "Master Playback");
 	return patch_build_controls(ac97, snd_ac97_ad1888_controls, ARRAY_SIZE(snd_ac97_ad1888_controls));
 }
 
@@ -1213,7 +1240,7 @@
 }
 
 /*
- * realtek ALC65x codecs
+ * realtek ALC65x/850 codecs
  */
 static int snd_ac97_alc650_mic_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t * ucontrol)
 {
@@ -1303,6 +1330,17 @@
 
 	ac97->build_ops = &patch_alc650_ops;
 
+	/* determine the revision */
+	val = snd_ac97_read(ac97, AC97_ALC650_REVISION) & 0x3f;
+	if (val < 3)
+		ac97->id = 0x414c4720;          /* Old version */
+	else if (val < 0x10)
+		ac97->id = 0x414c4721;          /* D version */
+	else if (val < 0x20)
+		ac97->id = 0x414c4722;          /* E version */
+	else if (val < 0x30)
+		ac97->id = 0x414c4723;          /* F version */
+
 	/* revision E or F */
 	/* FIXME: what about revision D ? */
 	ac97->spec.dev_flags = (ac97->id == 0x414c4722 ||
@@ -1351,20 +1389,19 @@
 static int snd_ac97_alc655_mic_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t * ucontrol)
 {
         ac97_t *ac97 = snd_kcontrol_chip(kcontrol);
-        int change;
 
 	/* misc control; vrefout disable */
 	snd_ac97_update_bits(ac97, AC97_ALC650_CLOCK, 1 << 12,
 			     ucontrol->value.integer.value[0] ? (1 << 12) : 0);
-	change = snd_ac97_update_bits(ac97, AC97_ALC650_MULTICH, 1 << 10,
-				      ucontrol->value.integer.value[0] ? (1 << 10) : 0);
-	return change;
+	return ac97_update_bits_page(ac97, AC97_ALC650_MULTICH, 1 << 10,
+				     ucontrol->value.integer.value[0] ? (1 << 10) : 0,
+				     0);
 }
 
 
 static const snd_kcontrol_new_t snd_ac97_controls_alc655[] = {
-	AC97_SINGLE("Duplicate Front", AC97_ALC650_MULTICH, 0, 1, 0),
-	AC97_SINGLE("Line-In As Surround", AC97_ALC650_MULTICH, 9, 1, 0),
+	AC97_PAGE_SINGLE("Duplicate Front", AC97_ALC650_MULTICH, 0, 1, 0, 0),
+	AC97_PAGE_SINGLE("Line-In As Surround", AC97_ALC650_MULTICH, 9, 1, 0, 0),
 	{
 		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
 		.name = "Mic As Center/LFE",
@@ -1391,7 +1428,6 @@
 	       texts_658[uinfo->value.enumerated.item] :
 	       texts_655[uinfo->value.enumerated.item]);
 	return 0;
-
 }
 
 static int alc655_iec958_route_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
@@ -1410,13 +1446,15 @@
 static int alc655_iec958_route_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
 {
 	ac97_t *ac97 = snd_kcontrol_chip(kcontrol);
-	return snd_ac97_update_bits(ac97, AC97_ALC650_MULTICH, 3 << 12,
-				    (unsigned short)ucontrol->value.enumerated.item[0]);
+
+	return ac97_update_bits_page(ac97, AC97_ALC650_MULTICH, 3 << 12,
+				     (unsigned short)ucontrol->value.enumerated.item[0],
+				     0);
 }
 
 static const snd_kcontrol_new_t snd_ac97_spdif_controls_alc655[] = {
-        AC97_SINGLE("IEC958 Capture Switch", AC97_ALC650_MULTICH, 11, 1, 0),
-        AC97_SINGLE("IEC958 Input Monitor", AC97_ALC650_MULTICH, 14, 1, 0),
+        AC97_PAGE_SINGLE("IEC958 Capture Switch", AC97_ALC650_MULTICH, 11, 1, 0, 0),
+        AC97_PAGE_SINGLE("IEC958 Input Monitor", AC97_ALC650_MULTICH, 14, 1, 0, 0),
 	{
 		.iface  = SNDRV_CTL_ELEM_IFACE_MIXER,
 		.name   = "IEC958 Playback Route",
@@ -1451,6 +1489,9 @@
 
 	ac97->build_ops = &patch_alc655_ops;
 
+	/* assume only page 0 for writing cache */
+	snd_ac97_update_bits(ac97, AC97_INT_PAGING, AC97_PAGE_MASK, AC97_PAGE_VENDOR);
+
 	/* adjust default values */
 	val = snd_ac97_read(ac97, 0x7a); /* misc control */
 	val |= (1 << 1); /* spdif input pin */
@@ -1469,6 +1510,120 @@
 	return 0;
 }
 
+
+#define AC97_ALC850_JACK_SELECT	0x76
+#define AC97_ALC850_MISC1	0x7a
+
+static int ac97_alc850_surround_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t * ucontrol)
+{
+        ac97_t *ac97 = snd_kcontrol_chip(kcontrol);
+        ucontrol->value.integer.value[0] = ((ac97->regs[AC97_ALC850_JACK_SELECT] >> 12) & 7) == 2;
+        return 0;
+}
+
+static int ac97_alc850_surround_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t * ucontrol)
+{
+        ac97_t *ac97 = snd_kcontrol_chip(kcontrol);
+
+	/* SURR 1kOhm (bit4), Amp (bit5) */
+	snd_ac97_update_bits(ac97, AC97_ALC850_MISC1, (1<<4)|(1<<5),
+			     ucontrol->value.integer.value[0] ? (1<<5) : (1<<4));
+	/* LINE-IN = 0, SURROUND = 2 */
+	return snd_ac97_update_bits(ac97, AC97_ALC850_JACK_SELECT, 7 << 12,
+				    ucontrol->value.integer.value[0] ? (2<<12) : (0<<12));
+}
+
+static int ac97_alc850_mic_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t * ucontrol)
+{
+        ac97_t *ac97 = snd_kcontrol_chip(kcontrol);
+        ucontrol->value.integer.value[0] = ((ac97->regs[AC97_ALC850_JACK_SELECT] >> 4) & 7) == 2;
+        return 0;
+}
+
+static int ac97_alc850_mic_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t * ucontrol)
+{
+        ac97_t *ac97 = snd_kcontrol_chip(kcontrol);
+
+	/* Vref disable (bit12), 1kOhm (bit13) */
+	snd_ac97_update_bits(ac97, AC97_ALC850_MISC1, (1<<12)|(1<<13),
+			     ucontrol->value.integer.value[0] ? (1<<12) : (1<<13));
+	/* MIC-IN = 1, CENTER-LFE = 2 */
+	return snd_ac97_update_bits(ac97, AC97_ALC850_JACK_SELECT, 7 << 4,
+				    ucontrol->value.integer.value[0] ? (2<<4) : (1<<4));
+}
+
+static const snd_kcontrol_new_t snd_ac97_controls_alc850[] = {
+	AC97_PAGE_SINGLE("Duplicate Front", AC97_ALC650_MULTICH, 0, 1, 0, 0),
+	{
+		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+		.name = "Line-In As Surround",
+		.info = snd_ac97_info_single,
+		.get = ac97_alc850_surround_get,
+		.put = ac97_alc850_surround_put,
+		.private_value = AC97_SINGLE_VALUE(0, 0, 1, 0) /* only mask needed */
+	},
+	{
+		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+		.name = "Mic As Center/LFE",
+		.info = snd_ac97_info_single,
+		.get = ac97_alc850_mic_get,
+		.put = ac97_alc850_mic_put,
+		.private_value = AC97_SINGLE_VALUE(0, 0, 1, 0) /* only mask needed */
+	},
+
+};
+
+static int patch_alc850_specific(ac97_t *ac97)
+{
+	int err;
+
+	if ((err = patch_build_controls(ac97, snd_ac97_controls_alc850, ARRAY_SIZE(snd_ac97_controls_alc850))) < 0)
+		return err;
+	if (ac97->ext_id & AC97_EI_SPDIF) {
+		if ((err = patch_build_controls(ac97, snd_ac97_spdif_controls_alc655, ARRAY_SIZE(snd_ac97_spdif_controls_alc655))) < 0)
+			return err;
+	}
+	return 0;
+}
+
+static struct snd_ac97_build_ops patch_alc850_ops = {
+	.build_specific	= patch_alc850_specific
+};
+
+int patch_alc850(ac97_t *ac97)
+{
+	ac97->build_ops = &patch_alc850_ops;
+
+	ac97->spec.dev_flags = 0; /* for IEC958 playback route - ALC655 compatible */
+
+	/* assume only page 0 for writing cache */
+	snd_ac97_update_bits(ac97, AC97_INT_PAGING, AC97_PAGE_MASK, AC97_PAGE_VENDOR);
+
+	/* adjust default values */
+	/* set default: spdif-in enabled,
+	   spdif-in monitor off, spdif-in PCM off
+	   center on mic off, surround on line-in off
+	   duplicate front off
+	*/
+	snd_ac97_write_cache(ac97, AC97_ALC650_MULTICH, 1<<15);
+	/* SURR_OUT: on, Surr 1kOhm: on, Surr Amp: off, Front 1kOhm: off
+	 * Front Amp: on, Vref: enable, Center 1kOhm: on, Mix: on
+	 */
+	snd_ac97_write_cache(ac97, 0x7a, (1<<1)|(1<<4)|(0<<5)|(1<<6)|
+			     (1<<7)|(0<<12)|(1<<13)|(0<<14));
+	/* detection UIO2,3: all path floating, UIO3: MIC, Vref2: disable,
+	 * UIO1: FRONT, Vref3: disable, UIO3: LINE, Front-Mic: mute
+	 */
+	snd_ac97_write_cache(ac97, 0x76, (0<<0)|(0<<2)|(1<<4)|(1<<7)|(2<<8)|
+			     (1<<11)|(0<<12)|(1<<15));
+
+	/* full DAC volume */
+	snd_ac97_write_cache(ac97, AC97_ALC650_SURR_DAC_VOL, 0x0808);
+	snd_ac97_write_cache(ac97, AC97_ALC650_LFE_DAC_VOL, 0x0808);
+	return 0;
+}
+
+
 /*
  * C-Media CM97xx codecs
  */
@@ -1599,8 +1754,10 @@
 		/* enable spdif in */
 		snd_ac97_write_cache(ac97, AC97_CM9739_SPDIF_CTRL,
 				     snd_ac97_read(ac97, AC97_CM9739_SPDIF_CTRL) | 0x01);
+		ac97->rates[AC97_RATES_SPDIF] = SNDRV_PCM_RATE_48000; /* 48k only */
 	} else {
 		ac97->ext_id &= ~AC97_EI_SPDIF; /* disable extended-id */
+		ac97->rates[AC97_RATES_SPDIF] = 0;
 	}
 
 	/* set-up multi channel */
diff -Nru a/sound/pci/ac97/ac97_patch.h b/sound/pci/ac97/ac97_patch.h
--- a/sound/pci/ac97/ac97_patch.h	2004-10-18 14:55:54 -07:00
+++ b/sound/pci/ac97/ac97_patch.h	2004-10-18 14:55:54 -07:00
@@ -49,6 +49,7 @@
 int patch_ad1985(ac97_t * ac97);
 int patch_alc650(ac97_t * ac97);
 int patch_alc655(ac97_t * ac97);
+int patch_alc850(ac97_t * ac97);
 int patch_cm9738(ac97_t * ac97);
 int patch_cm9739(ac97_t * ac97);
 int patch_vt1616(ac97_t * ac97);
diff -Nru a/sound/pci/ac97/ac97_pcm.c b/sound/pci/ac97/ac97_pcm.c
--- a/sound/pci/ac97/ac97_pcm.c	2004-10-18 14:55:55 -07:00
+++ b/sound/pci/ac97/ac97_pcm.c	2004-10-18 14:55:55 -07:00
@@ -36,8 +36,6 @@
 #include "ac97_id.h"
 #include "ac97_local.h"
 
-#define chip_t ac97_t
-
 /*
  *  PCM support
  */
@@ -430,7 +428,7 @@
 	unsigned int rates;
 	ac97_t *codec;
 
-	rpcms = snd_kcalloc(sizeof(struct ac97_pcm) * pcms_count, GFP_KERNEL);
+	rpcms = kcalloc(pcms_count, sizeof(struct ac97_pcm), GFP_KERNEL);
 	if (rpcms == NULL)
 		return -ENOMEM;
 	memset(avail_slots, 0, sizeof(avail_slots));
@@ -489,7 +487,10 @@
 				rpcm->r[0].rslots[j] = tmp;
 				rpcm->r[0].codec[j] = bus->codec[j];
 				rpcm->r[0].rate_table[j] = rate_table[pcm->stream][j];
-				rates = get_rates(rpcm, j, tmp, 0);
+				if (bus->no_vra)
+					rates = SNDRV_PCM_RATE_48000;
+				else
+					rates = get_rates(rpcm, j, tmp, 0);
 				if (pcm->exclusive)
 					avail_slots[pcm->stream][j] &= ~tmp;
 			}
diff -Nru a/sound/pci/ac97/ac97_proc.c b/sound/pci/ac97/ac97_proc.c
--- a/sound/pci/ac97/ac97_proc.c	2004-10-18 14:57:05 -07:00
+++ b/sound/pci/ac97/ac97_proc.c	2004-10-18 14:57:05 -07:00
@@ -290,11 +290,11 @@
 
 static void snd_ac97_proc_read(snd_info_entry_t *entry, snd_info_buffer_t * buffer)
 {
-	ac97_t *ac97 = snd_magic_cast(ac97_t, entry->private_data, return);
+	ac97_t *ac97 = entry->private_data;
 	
+	down(&ac97->mutex);
 	if ((ac97->id & 0xffffff40) == AC97_ID_AD1881) {	// Analog Devices AD1881/85/86
 		int idx;
-		down(&ac97->spec.ad18xx.mutex);
 		for (idx = 0; idx < 3; idx++)
 			if (ac97->spec.ad18xx.id[idx]) {
 				/* select single codec */
@@ -305,7 +305,6 @@
 			}
 		/* select all codecs */
 		snd_ac97_update_bits(ac97, AC97_AD_SERIAL_CFG, 0x7000, 0x7000);
-		up(&ac97->spec.ad18xx.mutex);
 		
 		snd_iprintf(buffer, "\nAD18XX configuration\n");
 		snd_iprintf(buffer, "Unchained        : 0x%04x,0x%04x,0x%04x\n",
@@ -319,22 +318,25 @@
 	} else {
 		snd_ac97_proc_read_main(ac97, buffer, 0);
 	}
+	up(&ac97->mutex);
 }
 
 #ifdef CONFIG_SND_DEBUG
 /* direct register write for debugging */
 static void snd_ac97_proc_regs_write(snd_info_entry_t *entry, snd_info_buffer_t *buffer)
 {
-	ac97_t *ac97 = snd_magic_cast(ac97_t, entry->private_data, return);
+	ac97_t *ac97 = entry->private_data;
 	char line[64];
 	unsigned int reg, val;
+	down(&ac97->mutex);
 	while (!snd_info_get_line(buffer, line, sizeof(line))) {
 		if (sscanf(line, "%x %x", &reg, &val) != 2)
 			continue;
-		/* register must be odd */
+		/* register must be even */
 		if (reg < 0x80 && (reg & 1) == 0 && val <= 0xffff)
 			snd_ac97_write_cache(ac97, reg, val);
 	}
+	up(&ac97->mutex);
 }
 #endif
 
@@ -351,12 +353,12 @@
 static void snd_ac97_proc_regs_read(snd_info_entry_t *entry, 
 				    snd_info_buffer_t * buffer)
 {
-	ac97_t *ac97 = snd_magic_cast(ac97_t, entry->private_data, return);
+	ac97_t *ac97 = entry->private_data;
 
+	down(&ac97->mutex);
 	if ((ac97->id & 0xffffff40) == AC97_ID_AD1881) {	// Analog Devices AD1881/85/86
 
 		int idx;
-		down(&ac97->spec.ad18xx.mutex);
 		for (idx = 0; idx < 3; idx++)
 			if (ac97->spec.ad18xx.id[idx]) {
 				/* select single codec */
@@ -366,10 +368,10 @@
 			}
 		/* select all codecs */
 		snd_ac97_update_bits(ac97, AC97_AD_SERIAL_CFG, 0x7000, 0x7000);
-		up(&ac97->spec.ad18xx.mutex);
 	} else {
 		snd_ac97_proc_regs_read_main(ac97, buffer, 0);
 	}	
+	up(&ac97->mutex);
 }
 
 void snd_ac97_proc_init(ac97_t * ac97)
diff -Nru a/sound/pci/ac97/ak4531_codec.c b/sound/pci/ac97/ak4531_codec.c
--- a/sound/pci/ac97/ak4531_codec.c	2004-10-18 14:55:55 -07:00
+++ b/sound/pci/ac97/ak4531_codec.c	2004-10-18 14:55:55 -07:00
@@ -30,8 +30,6 @@
 MODULE_DESCRIPTION("Universal routines for AK4531 codec");
 MODULE_LICENSE("GPL");
 
-#define chip_t ak4531_t
-
 static void snd_ak4531_proc_init(snd_card_t * card, ak4531_t * ak4531);
 
 /*
@@ -89,7 +87,7 @@
 	}
 	ucontrol->value.integer.value[0] = val;
 	return 0;
-}                                                                                                                                                                                                                                                                                                            
+}
 
 static int snd_ak4531_put_single(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
 {
@@ -113,7 +111,7 @@
 	ak4531->write(ak4531, reg, ak4531->regs[reg] = val);
 	spin_unlock_irqrestore(&ak4531->reg_lock, flags);
 	return change;
-}                                                                                                                                                                                                                                                                                                            
+}
 
 #define AK4531_DOUBLE(xname, xindex, left_reg, right_reg, left_shift, right_shift, mask, invert) \
 { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xindex, \
@@ -155,7 +153,7 @@
 	ucontrol->value.integer.value[0] = left;
 	ucontrol->value.integer.value[1] = right;
 	return 0;
-}                                                                                                                                                                                                                                                                                                            
+}
 
 static int snd_ak4531_put_double(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
 {
@@ -192,7 +190,7 @@
 	}
 	spin_unlock_irqrestore(&ak4531->reg_lock, flags);
 	return change;
-}                                                                                                                                                                                                                                                                                                            
+}
 
 #define AK4531_INPUT_SW(xname, xindex, reg1, reg2, left_shift, right_shift) \
 { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xindex, \
@@ -225,7 +223,7 @@
 	ucontrol->value.integer.value[3] = (ak4531->regs[reg2] >> right_shift) & 1;
 	spin_unlock_irqrestore(&ak4531->reg_lock, flags);
 	return 0;
-}                                                                                                                                                                                                                                                                                                            
+}
 
 static int snd_ak4531_put_input_sw(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
 {
@@ -250,9 +248,7 @@
 	ak4531->write(ak4531, reg2, ak4531->regs[reg2] = val2);
 	spin_unlock_irqrestore(&ak4531->reg_lock, flags);
 	return change;
-}                                                                                                                                                                                                                                                                                                            
-
-#define AK4531_CONTROLS (sizeof(snd_ak4531_controls)/sizeof(snd_kcontrol_new_t))
+}
 
 static snd_kcontrol_new_t snd_ak4531_controls[] = {
 
@@ -315,14 +311,14 @@
 	if (ak4531) {
 		if (ak4531->private_free)
 			ak4531->private_free(ak4531);
-		snd_magic_kfree(ak4531);
+		kfree(ak4531);
 	}
 	return 0;
 }
 
 static int snd_ak4531_dev_free(snd_device_t *device)
 {
-	ak4531_t *ak4531 = snd_magic_cast(ak4531_t, device->device_data, return -ENXIO);
+	ak4531_t *ak4531 = device->device_data;
 	return snd_ak4531_free(ak4531);
 }
 
@@ -367,7 +363,7 @@
 	snd_assert(rak4531 != NULL, return -EINVAL);
 	*rak4531 = NULL;
 	snd_assert(card != NULL && _ak4531 != NULL, return -EINVAL);
-	ak4531 = snd_magic_kcalloc(ak4531_t, 0, GFP_KERNEL);
+	ak4531 = kcalloc(1, sizeof(*ak4531), GFP_KERNEL);
 	if (ak4531 == NULL)
 		return -ENOMEM;
 	*ak4531 = *_ak4531;
@@ -385,7 +381,7 @@
 			continue;
 		ak4531->write(ak4531, idx, ak4531->regs[idx] = snd_ak4531_initial_map[idx]);	/* recording source is mixer */
 	}
-	for (idx = 0; idx < AK4531_CONTROLS; idx++) {
+	for (idx = 0; idx < ARRAY_SIZE(snd_ak4531_controls); idx++) {
 		if ((err = snd_ctl_add(card, snd_ctl_new1(&snd_ak4531_controls[idx], ak4531))) < 0) {
 			snd_ak4531_free(ak4531);
 			return err;
@@ -411,7 +407,7 @@
 static void snd_ak4531_proc_read(snd_info_entry_t *entry, 
 				 snd_info_buffer_t * buffer)
 {
-	ak4531_t *ak4531 = snd_magic_cast(ak4531_t, entry->private_data, return);
+	ak4531_t *ak4531 = entry->private_data;
 
 	snd_iprintf(buffer, "Asahi Kasei AK4531\n\n");
 	snd_iprintf(buffer, "Recording source   : %s\n"
diff -Nru a/sound/pci/ali5451/ali5451.c b/sound/pci/ali5451/ali5451.c
--- a/sound/pci/ali5451/ali5451.c	2004-10-18 14:57:04 -07:00
+++ b/sound/pci/ali5451/ali5451.c	2004-10-18 14:57:04 -07:00
@@ -43,8 +43,7 @@
 MODULE_AUTHOR("Matt Wu <Matt_Wu@acersoftech.com.cn>");
 MODULE_DESCRIPTION("ALI M5451");
 MODULE_LICENSE("GPL");
-MODULE_CLASSES("{sound}");
-MODULE_DEVICES("{{ALI,M5451,pci},{ALI,M5451}}");
+MODULE_SUPPORTED_DEVICE("{{ALI,M5451,pci},{ALI,M5451}}");
 
 static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX;	/* Index 0-MAX */
 static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR;	/* ID for this card */
@@ -55,19 +54,14 @@
 
 module_param_array(index, int, boot_devs, 0444);
 MODULE_PARM_DESC(index, "Index value for ALI M5451 PCI Audio.");
-MODULE_PARM_SYNTAX(index, SNDRV_INDEX_DESC);
 module_param_array(id, charp, boot_devs, 0444);
 MODULE_PARM_DESC(id, "ID string for ALI M5451 PCI Audio.");
-MODULE_PARM_SYNTAX(id, SNDRV_ID_DESC);
 module_param_array(enable, bool, boot_devs, 0444);
 MODULE_PARM_DESC(enable, "Enable ALI 5451 PCI Audio.");
-MODULE_PARM_SYNTAX(enable, SNDRV_ENABLE_DESC);
 module_param_array(pcm_channels, int, boot_devs, 0444);
 MODULE_PARM_DESC(pcm_channels, "PCM Channels");
-MODULE_PARM_SYNTAX(pcm_channels, SNDRV_ENABLED ",default:32,allows:{{1,32}}");
 module_param_array(spdif, bool, boot_devs, 0444);
 MODULE_PARM_DESC(spdif, "Support SPDIF I/O");
-MODULE_PARM_SYNTAX(spdif, SNDRV_ENABLED "," SNDRV_BOOLEAN_FALSE_DESC);
 
 /*
  *  Debug part definitions
@@ -171,7 +165,6 @@
 
 typedef struct snd_stru_ali ali_t;
 typedef struct snd_ali_stru_voice snd_ali_voice_t;
-#define chip_t ali_t
 
 typedef struct snd_ali_channel_control {
 	// register data
@@ -247,7 +240,6 @@
 
 	unsigned int hw_initialized: 1;
 	unsigned int spdif_support: 1;
-	struct resource *res_port;
 
 	struct pci_dev	*pci;
 	struct pci_dev	*pci_m1533;
@@ -495,7 +487,7 @@
 				unsigned short reg,
 				unsigned short val )
 {
-	ali_t *codec = snd_magic_cast(ali_t, ac97->private_data, return);
+	ali_t *codec = ac97->private_data;
 
 	snd_ali_printk("codec_write: reg=%xh data=%xh.\n", reg, val);
 	snd_ali_codec_poke(codec, 0, reg, val);
@@ -505,7 +497,7 @@
 
 static unsigned short snd_ali_codec_read(ac97_t *ac97, unsigned short reg)
 {
-	ali_t *codec = snd_magic_cast(ali_t, ac97->private_data, return -ENXIO);
+	ali_t *codec = ac97->private_data;
 
 	snd_ali_printk("codec_read reg=%xh.\n", reg);
 	return (snd_ali_codec_peek(codec, 0, reg));
@@ -1051,7 +1043,7 @@
 				   void *dev_id,
 				   struct pt_regs *regs)
 {
-	ali_t 	*codec = snd_magic_cast(ali_t, dev_id, return IRQ_NONE);
+	ali_t 	*codec = dev_id;
 
 	if (codec == NULL)
 		return IRQ_NONE;
@@ -1247,7 +1239,7 @@
 	what = whati = capture_flag = 0;
 	snd_pcm_group_for_each(pos, substream) {
 		s = snd_pcm_group_substream_entry(pos);
-		if ((ali_t *) _snd_pcm_chip(s->pcm) == codec) {
+		if ((ali_t *) snd_pcm_substream_chip(s) == codec) {
 			pvoice = (snd_ali_voice_t *) s->runtime->private_data;
 			evoice = pvoice->extra;
 			what |= 1 << (pvoice->number & 0x1f);
@@ -1528,16 +1520,15 @@
 	snd_pcm_runtime_t *runtime = substream->runtime;
 	snd_ali_voice_t *pvoice = (snd_ali_voice_t *) runtime->private_data;
 	unsigned int cso;
-	unsigned long flags;
 
-	spin_lock_irqsave(&codec->reg_lock, flags);
+	spin_lock(&codec->reg_lock);
 	if (!pvoice->running) {
-		spin_unlock_irqrestore(&codec->reg_lock, flags);
+		spin_unlock(&codec->reg_lock);
 		return 0;
 	}
 	outb(pvoice->number, ALI_REG(codec, ALI_GC_CIR));
 	cso = inw(ALI_REG(codec, ALI_CSO_ALPHA_FMS + 2));
-	spin_unlock_irqrestore(&codec->reg_lock, flags);
+	spin_unlock(&codec->reg_lock);
 	snd_ali_printk("playback pointer returned cso=%xh.\n", cso);
 
 	return cso;
@@ -1720,7 +1711,7 @@
 
 static void snd_ali_pcm_free(snd_pcm_t *pcm)
 {
-	ali_t *codec = snd_magic_cast(ali_t, pcm->private_data, return);
+	ali_t *codec = pcm->private_data;
 	codec->pcm = NULL;
 }
 
@@ -1769,7 +1760,7 @@
 static int snd_ali5451_spdif_get(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
 {
 	unsigned long flags;
-	ali_t *codec = snd_magic_cast(ali_t, kcontrol->private_data, -ENXIO);
+	ali_t *codec = kcontrol->private_data;
 	unsigned int enable;
 
 	enable = ucontrol->value.integer.value[0] ? 1 : 0;
@@ -1796,7 +1787,7 @@
 static int snd_ali5451_spdif_put(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
 {
 	unsigned long flags;
-	ali_t *codec = snd_magic_cast(ali_t, kcontrol->private_data, -ENXIO);
+	ali_t *codec = kcontrol->private_data;
 	unsigned int change = 0, enable = 0;
 
 	enable = ucontrol->value.integer.value[0] ? 1 : 0;
@@ -1863,30 +1854,29 @@
 
 static void snd_ali_mixer_free_ac97_bus(ac97_bus_t *bus)
 {
-	ali_t *codec = snd_magic_cast(ali_t, bus->private_data, return);
+	ali_t *codec = bus->private_data;
 	codec->ac97_bus = NULL;
 }
 
 static void snd_ali_mixer_free_ac97(ac97_t *ac97)
 {
-	ali_t *codec = snd_magic_cast(ali_t, ac97->private_data, return);
+	ali_t *codec = ac97->private_data;
 	codec->ac97 = NULL;
 }
 
 static int __devinit snd_ali_mixer(ali_t * codec)
 {
-	ac97_bus_t bus;
-	ac97_t ac97;
+	ac97_template_t ac97;
 	unsigned int idx;
 	int err;
+	static ac97_bus_ops_t ops = {
+		.write = snd_ali_codec_write,
+		.read = snd_ali_codec_read,
+	};
 
-	memset(&bus, 0, sizeof(bus));
-	bus.write = snd_ali_codec_write;
-	bus.read = snd_ali_codec_read;
-	bus.private_data = codec;
-	bus.private_free = snd_ali_mixer_free_ac97_bus;
-	if ((err = snd_ac97_bus(codec->card, &bus, &codec->ac97_bus)) < 0)
+	if ((err = snd_ac97_bus(codec->card, 0, &ops, codec, &codec->ac97_bus)) < 0)
 		return err;
+	codec->ac97_bus->private_free = snd_ali_mixer_free_ac97_bus;
 
 	memset(&ac97, 0, sizeof(ac97));
 	ac97.private_data = codec;
@@ -1907,7 +1897,7 @@
 #ifdef CONFIG_PM
 static int ali_suspend(snd_card_t *card, unsigned int state)
 {
-	ali_t *chip = snd_magic_cast(ali_t, card->pm_private_data, return -EINVAL);
+	ali_t *chip = card->pm_private_data;
 	ali_image_t *im;
 	int i, j;
 
@@ -1943,12 +1933,13 @@
 	outl(0xffffffff, ALI_REG(chip, ALI_STOP));
 
 	spin_unlock_irq(&chip->reg_lock);
+	snd_power_change_state(card, SNDRV_CTL_POWER_D3hot);
 	return 0;
 }
 
 static int ali_resume(snd_card_t *card, unsigned int state)
 {
-	ali_t *chip = snd_magic_cast(ali_t, card->pm_private_data, return -EINVAL);
+	ali_t *chip = card->pm_private_data;
 	ali_image_t *im;
 	int i, j;
 
@@ -1980,6 +1971,7 @@
 	spin_unlock_irq(&chip->reg_lock);
 
 	snd_ac97_resume(chip->ac97);
+	snd_power_change_state(card, SNDRV_CTL_POWER_D0);
 	
 	return 0;
 }
@@ -1993,15 +1985,13 @@
 		synchronize_irq(codec->irq);
 		free_irq(codec->irq, (void *)codec);
 	}
-	if (codec->res_port) {
-		release_resource(codec->res_port);
-		kfree_nocheck(codec->res_port);
-	}
+	if (codec->port)
+		pci_release_regions(codec->pci);
 #ifdef CONFIG_PM
 	if (codec->image)
 		kfree(codec->image);
 #endif
-	snd_magic_kfree(codec);
+	kfree(codec);
 	return 0;
 }
 
@@ -2055,11 +2045,12 @@
 
 static int __devinit snd_ali_resources(ali_t *codec)
 {
+	int err;
+
 	snd_ali_printk("resouces allocation ...\n");
-	if ((codec->res_port = request_region(codec->port, 0x100, "ALI 5451")) == NULL) {
-		snd_printk("Unalbe to request io ports.\n");
-		return -EBUSY;
-	}
+	if ((err = pci_request_regions(codec->pci, "ALI 5451")) < 0)
+		return err;
+	codec->port = pci_resource_start(codec->pci, 0);
 
 	if (request_irq(codec->pci->irq, snd_ali_card_interrupt, SA_INTERRUPT|SA_SHIRQ, "ALI 5451", (void *)codec)) {
 		snd_printk("Unable to request irq.\n");
@@ -2071,7 +2062,7 @@
 }
 static int snd_ali_dev_free(snd_device_t *device) 
 {
-	ali_t *codec=snd_magic_cast(ali_t, device->device_data, return -ENXIO);
+	ali_t *codec=device->device_data;
 	snd_ali_free(codec);
 	return 0;
 }
@@ -2106,7 +2097,7 @@
 		return -ENXIO;
 	}
 
-	if ((codec = snd_magic_kcalloc(ali_t, 0, GFP_KERNEL)) == NULL)
+	if ((codec = kcalloc(1, sizeof(*codec), GFP_KERNEL)) == NULL)
 		return -ENOMEM;
 
 	spin_lock_init(&codec->reg_lock);
@@ -2115,7 +2106,6 @@
 	codec->card = card;
 	codec->pci = pci;
 	codec->irq = -1;
-	codec->port = pci_resource_start(pci, 0);
 	pci_read_config_byte(pci, PCI_REVISION_ID, &codec->revision);
 	codec->spdif_support = spdif_support;
 
diff -Nru a/sound/pci/als4000.c b/sound/pci/als4000.c
--- a/sound/pci/als4000.c	2004-10-18 14:57:04 -07:00
+++ b/sound/pci/als4000.c	2004-10-18 14:57:04 -07:00
@@ -76,8 +76,7 @@
 MODULE_AUTHOR("Bart Hartgers <bart@etpmod.phys.tue.nl>");
 MODULE_DESCRIPTION("Avance Logic ALS4000");
 MODULE_LICENSE("GPL");
-MODULE_CLASSES("{sound}");
-MODULE_DEVICES("{{Avance Logic,ALS4000}}");
+MODULE_SUPPORTED_DEVICE("{{Avance Logic,ALS4000}}");
 
 #if defined(CONFIG_GAMEPORT) || (defined(MODULE) && defined(CONFIG_GAMEPORT_MODULE))
 #define SUPPORT_JOYSTICK 1
@@ -93,24 +92,18 @@
 
 module_param_array(index, int, boot_devs, 0444);
 MODULE_PARM_DESC(index, "Index value for ALS4000 soundcard.");
-MODULE_PARM_SYNTAX(index, SNDRV_INDEX_DESC);
 module_param_array(id, charp, boot_devs, 0444);
 MODULE_PARM_DESC(id, "ID string for ALS4000 soundcard.");
-MODULE_PARM_SYNTAX(id, SNDRV_ID_DESC);
 module_param_array(enable, bool, boot_devs, 0444);
 MODULE_PARM_DESC(enable, "Enable ALS4000 soundcard.");
-MODULE_PARM_SYNTAX(enable, SNDRV_INDEX_DESC);
 #ifdef SUPPORT_JOYSTICK
 module_param_array(joystick_port, int, boot_devs, 0444);
 MODULE_PARM_DESC(joystick_port, "Joystick port address for ALS4000 soundcard. (0 = disabled)");
-MODULE_PARM_SYNTAX(joystick_port, SNDRV_ENABLED);
 #endif
 
-#define chip_t sb_t
-
 typedef struct {
+	struct pci_dev *pci;
 	unsigned long gcr;
-	struct resource *res_gcr;
 #ifdef SUPPORT_JOYSTICK
 	struct gameport gameport;
 	struct resource *res_joystick;
@@ -304,11 +297,10 @@
 
 static int snd_als4000_capture_trigger(snd_pcm_substream_t * substream, int cmd)
 {
-	unsigned long flags;
 	sb_t *chip = snd_pcm_substream_chip(substream);
 	int result = 0;
 	
-	spin_lock_irqsave(&chip->mixer_lock, flags);
+	spin_lock(&chip->mixer_lock);
 	if (cmd == SNDRV_PCM_TRIGGER_START) {
 		chip->mode |= SB_RATE_LOCK_CAPTURE;
 		snd_sbmixer_write(chip, 0xde, capture_cmd(chip));
@@ -318,17 +310,16 @@
 	} else {
 		result = -EINVAL;
 	}
-	spin_unlock_irqrestore(&chip->mixer_lock, flags);
+	spin_unlock(&chip->mixer_lock);
 	return result;
 }
 
 static int snd_als4000_playback_trigger(snd_pcm_substream_t * substream, int cmd)
 {
-	unsigned long flags;
 	sb_t *chip = snd_pcm_substream_chip(substream);
 	int result = 0;
 
-	spin_lock_irqsave(&chip->reg_lock, flags);
+	spin_lock(&chip->reg_lock);
 	if (cmd == SNDRV_PCM_TRIGGER_START) {
 		chip->mode |= SB_RATE_LOCK_PLAYBACK;
 		snd_sbdsp_command(chip, playback_cmd(chip).dma_on);
@@ -338,38 +329,35 @@
 	} else {
 		result = -EINVAL;
 	}
-	spin_unlock_irqrestore(&chip->reg_lock, flags);
+	spin_unlock(&chip->reg_lock);
 	return result;
 }
 
 static snd_pcm_uframes_t snd_als4000_capture_pointer(snd_pcm_substream_t * substream)
 {
-	unsigned long flags;
 	sb_t *chip = snd_pcm_substream_chip(substream);
 	unsigned int result;
 
-	spin_lock_irqsave(&chip->reg_lock, flags);	
+	spin_lock(&chip->reg_lock);	
 	result = snd_als4000_gcr_read(chip, 0xa4) & 0xffff;
-	spin_unlock_irqrestore(&chip->reg_lock, flags);
+	spin_unlock(&chip->reg_lock);
 	return bytes_to_frames( substream->runtime, result );
 }
 
 static snd_pcm_uframes_t snd_als4000_playback_pointer(snd_pcm_substream_t * substream)
 {
-	unsigned long flags;
 	sb_t *chip = snd_pcm_substream_chip(substream);
 	unsigned result;
 
-	spin_lock_irqsave(&chip->reg_lock, flags);	
+	spin_lock(&chip->reg_lock);	
 	result = snd_als4000_gcr_read(chip, 0xa0) & 0xffff;
-	spin_unlock_irqrestore(&chip->reg_lock, flags);
+	spin_unlock(&chip->reg_lock);
 	return bytes_to_frames( substream->runtime, result );
 }
 
 static irqreturn_t snd_als4000_interrupt(int irq, void *dev_id, struct pt_regs *regs)
 {
-	sb_t *chip = snd_magic_cast(sb_t, dev_id, return IRQ_NONE);
-	unsigned long flags;
+	sb_t *chip = dev_id;
 	unsigned gcr_status;
 	unsigned sb_status;
 
@@ -385,9 +373,9 @@
 	/* release the gcr */
 	outb(gcr_status, chip->alt_port + 0xe);
 	
-	spin_lock_irqsave(&chip->mixer_lock, flags);
+	spin_lock(&chip->mixer_lock);
 	sb_status = snd_sbmixer_read(chip, SB_DSP4_IRQSTATUS);
-	spin_unlock_irqrestore(&chip->mixer_lock, flags);
+	spin_unlock(&chip->mixer_lock);
 	
 	if (sb_status & SB_IRQTYPE_8BIT) 
 		snd_sb_ack_8bit(chip);
@@ -506,7 +494,7 @@
 
 static void snd_als4000_pcm_free(snd_pcm_t *pcm)
 {
-	sb_t *chip = snd_magic_cast(sb_t, pcm->private_data, return);
+	sb_t *chip = pcm->private_data;
 	chip->pcm = NULL;
 	snd_pcm_lib_preallocate_free_for_all(pcm);
 }
@@ -557,27 +545,26 @@
 
 static void __devinit snd_als4000_configure(sb_t *chip)
 {
-	unsigned long flags;
 	unsigned tmp;
 	int i;
 
 	/* do some more configuration */
-	spin_lock_irqsave(&chip->mixer_lock, flags);
+	spin_lock_irq(&chip->mixer_lock);
 	tmp = snd_sbmixer_read(chip, 0xc0);
 	snd_sbmixer_write(chip, 0xc0, tmp|0x80);
 	/* always select DMA channel 0, since we do not actually use DMA */
 	snd_sbmixer_write(chip, SB_DSP4_DMASETUP, SB_DMASETUP_DMA0);
 	snd_sbmixer_write(chip, 0xc0, tmp&0x7f);
-	spin_unlock_irqrestore(&chip->mixer_lock, flags);
+	spin_unlock_irq(&chip->mixer_lock);
 	
-	spin_lock_irqsave(&chip->reg_lock,flags);
+	spin_lock_irq(&chip->reg_lock);
 	/* magic number. Enables interrupts(?) */
 	snd_als4000_gcr_write(chip, 0x8c, 0x28000);
 	for(i = 0x91; i <= 0x96; ++i)
 		snd_als4000_gcr_write(chip, i, 0);
 	
 	snd_als4000_gcr_write(chip, 0x99, snd_als4000_gcr_read(chip, 0x99));
-	spin_unlock_irqrestore(&chip->reg_lock,flags);
+	spin_unlock_irq(&chip->reg_lock);
 }
 
 static void snd_card_als4000_free( snd_card_t *card )
@@ -595,8 +582,7 @@
 		kfree_nocheck(acard->res_joystick);
 	}
 #endif
-	release_resource(acard->res_gcr);
-	kfree_nocheck(acard->res_gcr);
+	pci_release_regions(acard->pci);
 }
 
 static int __devinit snd_card_als4000_probe(struct pci_dev *pci,
@@ -606,7 +592,6 @@
 	snd_card_t *card;
 	snd_card_als4000_t *acard;
 	unsigned long gcr;
-	struct resource *res_gcr_port;
 	sb_t *chip;
 	opl3_t *opl3;
 	unsigned short word;
@@ -631,11 +616,9 @@
 		return -ENXIO;
 	}
 
+	if ((err = pci_request_regions(pci, "ALS4000")) < 0)
+		return err;
 	gcr = pci_resource_start(pci, 0);
-	if ((res_gcr_port = request_region(gcr, 0x40, "ALS4000")) == NULL) {
-		snd_printk("unable to grab region 0x%lx-0x%lx\n", gcr, gcr + 0x40 - 1);
-		return -EBUSY;
-	}
 
 	pci_read_config_word(pci, PCI_COMMAND, &word);
 	pci_write_config_word(pci, PCI_COMMAND, word | PCI_COMMAND_IO);
@@ -644,14 +627,13 @@
 	card = snd_card_new(index[dev], id[dev], THIS_MODULE, 
 			    sizeof( snd_card_als4000_t ) );
 	if (card == NULL) {
-		release_resource(res_gcr_port);
-		kfree_nocheck(res_gcr_port);
+		pci_release_regions(pci);
 		return -ENOMEM;
 	}
 
 	acard = (snd_card_als4000_t *)card->private_data;
+	acard->pci = pci;
 	acard->gcr = gcr;
-	acard->res_gcr = res_gcr_port;
 	card->private_free = snd_card_als4000_free;
 
 	/* disable all legacy ISA stuff except for joystick */
diff -Nru a/sound/pci/atiixp.c b/sound/pci/atiixp.c
--- a/sound/pci/atiixp.c	2004-10-18 14:56:32 -07:00
+++ b/sound/pci/atiixp.c	2004-10-18 14:56:32 -07:00
@@ -1,5 +1,5 @@
 /*
- *   ALSA driver for ATI IXP 150/200/250 AC97 controllers
+ *   ALSA driver for ATI IXP 150/200/250/300 AC97 controllers
  *
  *	Copyright (c) 2004 Takashi Iwai <tiwai@suse.de>
  *
@@ -37,8 +37,7 @@
 MODULE_AUTHOR("Takashi Iwai <tiwai@suse.de>");
 MODULE_DESCRIPTION("ATI IXP AC97 controller");
 MODULE_LICENSE("GPL");
-MODULE_CLASSES("{sound}");
-MODULE_DEVICES("{{ATI,IXP150/200/250/300}}");
+MODULE_SUPPORTED_DEVICE("{{ATI,IXP150/200/250/300/400}}");
 
 static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX;	/* Index 0-MAX */
 static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR;	/* ID for this card */
@@ -49,19 +48,14 @@
 
 module_param_array(index, int, boot_devs, 0444);
 MODULE_PARM_DESC(index, "Index value for ATI IXP controller.");
-MODULE_PARM_SYNTAX(index, SNDRV_INDEX_DESC);
 module_param_array(id, charp, boot_devs, 0444);
 MODULE_PARM_DESC(id, "ID string for ATI IXP controller.");
-MODULE_PARM_SYNTAX(id, SNDRV_ID_DESC);
 module_param_array(enable, bool, boot_devs, 0444);
 MODULE_PARM_DESC(enable, "Enable audio part of ATI IXP controller.");
-MODULE_PARM_SYNTAX(enable, SNDRV_ENABLE_DESC);
 module_param_array(ac97_clock, int, boot_devs, 0444);
 MODULE_PARM_DESC(ac97_clock, "AC'97 codec clock (default 48000Hz).");
-MODULE_PARM_SYNTAX(ac97_clock, SNDRV_ENABLED ",default:48000");
 module_param_array(spdif_aclink, bool, boot_devs, 0444);
 MODULE_PARM_DESC(spdif_aclink, "S/PDIF over AC-link.");
-MODULE_PARM_SYNTAX(spdif_aclink, SNDRV_ENABLED "," SNDRV_BOOLEAN_TRUE_DESC);
 
 
 /*
@@ -197,7 +191,6 @@
 #define  ATI_REG_DMA_STATE		(7U<<26)
 
 
-#define ATI_MEM_REGION		256	/* i/o memory size */
 #define ATI_MAX_DESCRIPTORS	256	/* max number of descriptor packets */
 
 
@@ -207,7 +200,6 @@
 typedef struct snd_atiixp atiixp_t;
 typedef struct snd_atiixp_dma atiixp_dma_t;
 typedef struct snd_atiixp_dma_ops atiixp_dma_ops_t;
-#define chip_t atiixp_t
 
 
 /*
@@ -248,7 +240,6 @@
  */
 struct snd_atiixp_dma {
 	const atiixp_dma_ops_t *ops;
-	struct snd_dma_device desc_dev;
 	struct snd_dma_buffer desc_buf;
 	snd_pcm_substream_t *substream;	/* assigned PCM substream */
 	unsigned int buf_addr, buf_bytes;	/* DMA buffer address, bytes */
@@ -266,9 +257,8 @@
 	snd_card_t *card;
 	struct pci_dev *pci;
 
-	struct resource *res;		/* memory i/o */
 	unsigned long addr;
-	unsigned long remap_addr;
+	void __iomem *remap_addr;
 	int irq;
 	
 	ac97_bus_t *ac97_bus;
@@ -287,10 +277,6 @@
 
 	int spdif_over_aclink;		/* passed from the module option */
 	struct semaphore open_mutex;	/* playback open mutex */
-
-#ifdef CONFIG_PM
-	u32 pci_state[16];
-#endif
 };
 
 
@@ -299,6 +285,7 @@
 static struct pci_device_id snd_atiixp_ids[] = {
 	{ 0x1002, 0x4341, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, /* SB200 */
 	{ 0x1002, 0x4361, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, /* SB300 */
+	{ 0x1002, 0x4370, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, /* SB400 */
 	{ 0, }
 };
 
@@ -316,7 +303,7 @@
 static int snd_atiixp_update_bits(atiixp_t *chip, unsigned int reg,
 				 unsigned int mask, unsigned int value)
 {
-	unsigned long addr = chip->remap_addr + reg;
+	void __iomem *addr = chip->remap_addr + reg;
 	unsigned int data, old_data;
 	old_data = data = readl(addr);
 	data &= ~mask;
@@ -376,15 +363,13 @@
 		return -ENOMEM;
 
 	if (dma->desc_buf.area == NULL) {
-		memset(&dma->desc_dev, 0, sizeof(dma->desc_dev));
-		dma->desc_dev.type = SNDRV_DMA_TYPE_DEV;
-		dma->desc_dev.dev = snd_dma_pci_data(chip->pci);
-		if (snd_dma_alloc_pages(&dma->desc_dev, ATI_DESC_LIST_SIZE, &dma->desc_buf) < 0)
+		if (snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, snd_dma_pci_data(chip->pci),
+					ATI_DESC_LIST_SIZE, &dma->desc_buf) < 0)
 			return -ENOMEM;
 		dma->period_bytes = dma->periods = 0; /* clear */
 	}
 
-	if (dma->periods == dma->periods && dma->period_bytes == period_bytes)
+	if (dma->periods == periods && dma->period_bytes == period_bytes)
 		return 0;
 
 	/* reset DMA before changing the descriptor table */
@@ -426,7 +411,7 @@
 {
 	if (dma->desc_buf.area) {
 		writel(0, chip->remap_addr + dma->ops->llp_offset);
-		snd_dma_free_pages(&dma->desc_dev, &dma->desc_buf);
+		snd_dma_free_pages(&dma->desc_buf);
 		dma->desc_buf.area = NULL;
 	}
 }
@@ -491,7 +476,7 @@
 
 static unsigned short snd_atiixp_ac97_read(ac97_t *ac97, unsigned short reg)
 {
-	atiixp_t *chip = snd_magic_cast(atiixp_t, ac97->private_data, return 0xffff);
+	atiixp_t *chip = ac97->private_data;
 	unsigned short data;
 	spin_lock(&chip->ac97_lock);
 	data = snd_atiixp_codec_read(chip, ac97->num, reg);
@@ -502,7 +487,7 @@
 
 static void snd_atiixp_ac97_write(ac97_t *ac97, unsigned short reg, unsigned short val)
 {
-	atiixp_t *chip = snd_magic_cast(atiixp_t, ac97->private_data, return);
+	atiixp_t *chip = ac97->private_data;
 	spin_lock(&chip->ac97_lock);
 	snd_atiixp_codec_write(chip, ac97->num, reg, val);
 	spin_unlock(&chip->ac97_lock);
@@ -653,9 +638,8 @@
 	snd_pcm_runtime_t *runtime = substream->runtime;
 	atiixp_dma_t *dma = (atiixp_dma_t *)runtime->private_data;
 	unsigned int curptr;
-	unsigned long flags;
 
-	spin_lock_irqsave(&chip->reg_lock, flags);
+	spin_lock(&chip->reg_lock);
 	curptr = readl(chip->remap_addr + dma->ops->dt_cur);
 	if (curptr < dma->buf_addr) {
 		snd_printdd("curptr = %x, base = %x\n", curptr, dma->buf_addr);
@@ -667,7 +651,7 @@
 			curptr = 0;
 		}
 	}
-	spin_unlock_irqrestore(&chip->reg_lock, flags);
+	spin_unlock(&chip->reg_lock);
 	return bytes_to_frames(runtime, curptr);
 }
 
@@ -852,7 +836,7 @@
 {
 	atiixp_t *chip = snd_pcm_substream_chip(substream);
 
-	spin_lock(&chip->reg_lock);
+	spin_lock_irq(&chip->reg_lock);
 	if (chip->spdif_over_aclink) {
 		unsigned int data;
 		/* enable slots 10/11 */
@@ -870,7 +854,7 @@
 		atiixp_update(chip, CMD, ATI_REG_CMD_SPDF_CONFIG_MASK, 0);
 		atiixp_update(chip, CMD, ATI_REG_CMD_INTERLEAVE_SPDF, 0);
 	}
-	spin_unlock(&chip->reg_lock);
+	spin_unlock_irq(&chip->reg_lock);
 	return 0;
 }
 
@@ -880,7 +864,7 @@
 	atiixp_t *chip = snd_pcm_substream_chip(substream);
 	unsigned int data;
 
-	spin_lock(&chip->reg_lock);
+	spin_lock_irq(&chip->reg_lock);
 	data = atiixp_read(chip, OUT_DMA_SLOT) & ~ATI_REG_OUT_DMA_SLOT_MASK;
 	switch (substream->runtime->channels) {
 	case 8:
@@ -915,7 +899,7 @@
 	atiixp_update(chip, 6CH_REORDER, ATI_REG_6CH_REORDER_EN,
 		      substream->runtime->channels >= 6 ? ATI_REG_6CH_REORDER_EN: 0);
     
-	spin_unlock(&chip->reg_lock);
+	spin_unlock_irq(&chip->reg_lock);
 	return 0;
 }
 
@@ -924,11 +908,11 @@
 {
 	atiixp_t *chip = snd_pcm_substream_chip(substream);
 
-	spin_lock(&chip->reg_lock);
+	spin_lock_irq(&chip->reg_lock);
 	atiixp_update(chip, CMD, ATI_REG_CMD_INTERLEAVE_IN,
 		      substream->runtime->format == SNDRV_PCM_FORMAT_S16_LE ?
 		      ATI_REG_CMD_INTERLEAVE_IN : 0);
-	spin_unlock(&chip->reg_lock);
+	spin_unlock_irq(&chip->reg_lock);
 	return 0;
 }
 
@@ -996,6 +980,7 @@
 {
 	.info =			(SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED |
 				 SNDRV_PCM_INFO_BLOCK_TRANSFER |
+				 SNDRV_PCM_INFO_RESUME |
 				 SNDRV_PCM_INFO_MMAP_VALID),
 	.formats =		SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S32_LE,
 	.rates =		SNDRV_PCM_RATE_48000,
@@ -1014,7 +999,6 @@
 {
 	atiixp_t *chip = snd_pcm_substream_chip(substream);
 	snd_pcm_runtime_t *runtime = substream->runtime;
-	unsigned long flags;
 	int err;
 
 	snd_assert(dma->ops && dma->ops->enable_dma, return -EINVAL);
@@ -1036,9 +1020,9 @@
 	runtime->private_data = dma;
 
 	/* enable DMA bits */
-	spin_lock_irqsave(&chip->reg_lock, flags);
+	spin_lock_irq(&chip->reg_lock);
 	dma->ops->enable_dma(chip, 1);
-	spin_unlock_irqrestore(&chip->reg_lock, flags);
+	spin_unlock_irq(&chip->reg_lock);
 	dma->opened = 1;
 
 	return 0;
@@ -1308,7 +1292,7 @@
  */
 static irqreturn_t snd_atiixp_interrupt(int irq, void *dev_id, struct pt_regs *regs)
 {
-	atiixp_t *chip = snd_magic_cast(atiixp_t, dev_id, return IRQ_NONE);
+	atiixp_t *chip = dev_id;
 	unsigned int status;
 
 	status = atiixp_read(chip, ISR);
@@ -1355,10 +1339,14 @@
 
 static int __devinit snd_atiixp_mixer_new(atiixp_t *chip, int clock)
 {
-	ac97_bus_t bus, *pbus;
-	ac97_t ac97;
+	ac97_bus_t *pbus;
+	ac97_template_t ac97;
 	int i, err;
 	int codec_count;
+	static ac97_bus_ops_t ops = {
+		.write = snd_atiixp_ac97_write,
+		.read = snd_atiixp_ac97_read,
+	};
 	static unsigned int codec_skip[NUM_ATI_CODECS] = {
 		ATI_REG_ISR_CODEC0_NOT_READY,
 		ATI_REG_ISR_CODEC1_NOT_READY,
@@ -1368,13 +1356,10 @@
 	if (snd_atiixp_codec_detect(chip) < 0)
 		return -ENXIO;
 
-	memset(&bus, 0, sizeof(bus));
-	bus.write = snd_atiixp_ac97_write;
-	bus.read = snd_atiixp_ac97_read;
-	bus.private_data = chip;
-	bus.clock = clock;
-	if ((err = snd_ac97_bus(chip->card, &bus, &pbus)) < 0)
+	if ((err = snd_ac97_bus(chip->card, 0, &ops, chip, &pbus)) < 0)
 		return err;
+	pbus->clock = clock;
+	pbus->shared_type = AC97_SHARED_TYPE_ATIIXP;	/* shared with modem driver */
 	chip->ac97_bus = pbus;
 
 	codec_count = 0;
@@ -1387,17 +1372,9 @@
 		ac97.num = i;
 		ac97.scaps = AC97_SCAP_SKIP_MODEM;
 		if ((err = snd_ac97_mixer(pbus, &ac97, &chip->ac97[i])) < 0) {
-			if (chip->codec_not_ready_bits)
-				/* codec(s) was detected but not available.
-				 * return the error
-				 */
-				return err;
-			else {
-				/* codec(s) was NOT detected, so just ignore here */
-				chip->ac97[i] = NULL; /* to be sure */
-				snd_printd("atiixp: codec %d not found\n", i);
-				continue;
-			}
+			chip->ac97[i] = NULL; /* to be sure */
+			snd_printdd("atiixp: codec %d not available for audio\n", i);
+			continue;
 		}
 		codec_count++;
 	}
@@ -1419,7 +1396,7 @@
  */
 static int snd_atiixp_suspend(snd_card_t *card, unsigned int state)
 {
-	atiixp_t *chip = snd_magic_cast(atiixp_t, card->pm_private_data, return -EINVAL);
+	atiixp_t *chip = card->pm_private_data;
 	int i;
 
 	for (i = 0; i < NUM_ATI_PCMDEVS; i++)
@@ -1431,7 +1408,6 @@
 	snd_atiixp_aclink_down(chip);
 	snd_atiixp_chip_stop(chip);
 
-	pci_save_state(chip->pci, chip->pci_state);
 	pci_set_power_state(chip->pci, 3);
 	pci_disable_device(chip->pci);
 	snd_power_change_state(card, SNDRV_CTL_POWER_D3hot);
@@ -1440,11 +1416,10 @@
 
 static int snd_atiixp_resume(snd_card_t *card, unsigned int state)
 {
-	atiixp_t *chip = snd_magic_cast(atiixp_t, card->pm_private_data, return -EINVAL);
+	atiixp_t *chip = card->pm_private_data;
 	int i;
 
 	pci_enable_device(chip->pci);
-	pci_restore_state(chip->pci, chip->pci_state);
 	pci_set_power_state(chip->pci, 0);
 
 	snd_atiixp_aclink_reset(chip);
@@ -1466,7 +1441,7 @@
 
 static void snd_atiixp_proc_read(snd_info_entry_t *entry, snd_info_buffer_t *buffer)
 {
-	atiixp_t *chip = snd_magic_cast(atiixp_t, entry->private_data, return);
+	atiixp_t *chip = entry->private_data;
 	int i;
 
 	for (i = 0; i < 256; i += 4)
@@ -1494,21 +1469,18 @@
 	snd_atiixp_chip_stop(chip);
 	synchronize_irq(chip->irq);
       __hw_end:
-	if (chip->remap_addr)
-		iounmap((void *) chip->remap_addr);
-	if (chip->res) {
-		release_resource(chip->res);
-		kfree_nocheck(chip->res);
-	}
 	if (chip->irq >= 0)
 		free_irq(chip->irq, (void *)chip);
-	snd_magic_kfree(chip);
+	if (chip->remap_addr)
+		iounmap(chip->remap_addr);
+	pci_release_regions(chip->pci);
+	kfree(chip);
 	return 0;
 }
 
 static int snd_atiixp_dev_free(snd_device_t *device)
 {
-	atiixp_t *chip = snd_magic_cast(atiixp_t, device->device_data, return -ENXIO);
+	atiixp_t *chip = device->device_data;
 	return snd_atiixp_free(chip);
 }
 
@@ -1528,7 +1500,7 @@
 	if ((err = pci_enable_device(pci)) < 0)
 		return err;
 
-	chip = snd_magic_kcalloc(atiixp_t, 0, GFP_KERNEL);
+	chip = kcalloc(1, sizeof(*chip), GFP_KERNEL);
 	if (chip == NULL)
 		return -ENOMEM;
 
@@ -1538,13 +1510,12 @@
 	chip->card = card;
 	chip->pci = pci;
 	chip->irq = -1;
-	chip->addr = pci_resource_start(pci, 0);
-	if ((chip->res = request_mem_region(chip->addr, ATI_MEM_REGION, "ATI IXP AC97")) == NULL) {
-		snd_printk(KERN_ERR "unable to grab I/O memory 0x%lx\n", chip->addr);
-		snd_atiixp_free(chip);
-		return -EBUSY;
+	if ((err = pci_request_regions(pci, "ATI IXP AC97")) < 0) {
+		kfree(chip);
+		return err;
 	}
-	chip->remap_addr = (unsigned long) ioremap_nocache(chip->addr, ATI_MEM_REGION);
+	chip->addr = pci_resource_start(pci, 0);
+	chip->remap_addr = ioremap_nocache(chip->addr, pci_resource_len(pci, 0));
 	if (chip->remap_addr == 0) {
 		snd_printk(KERN_ERR "AC'97 space ioremap problem\n");
 		snd_atiixp_free(chip);
diff -Nru a/sound/pci/atiixp_modem.c b/sound/pci/atiixp_modem.c
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/sound/pci/atiixp_modem.c	2004-10-18 14:57:24 -07:00
@@ -0,0 +1,1351 @@
+/*
+ *   ALSA driver for ATI IXP 150/200/250 AC97 modem controllers
+ *
+ *	Copyright (c) 2004 Takashi Iwai <tiwai@suse.de>
+ *
+ *   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
+ *
+ */
+
+#include <sound/driver.h>
+#include <asm/io.h>
+#include <linux/delay.h>
+#include <linux/interrupt.h>
+#include <linux/init.h>
+#include <linux/pci.h>
+#include <linux/slab.h>
+#include <linux/moduleparam.h>
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+#include <sound/info.h>
+#include <sound/ac97_codec.h>
+#include <sound/initval.h>
+
+MODULE_AUTHOR("Takashi Iwai <tiwai@suse.de>");
+MODULE_DESCRIPTION("ATI IXP MC97 controller");
+MODULE_LICENSE("GPL");
+MODULE_SUPPORTED_DEVICE("{{ATI,IXP150/200/250}}");
+
+static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX;	/* Index 0-MAX */
+static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR;	/* ID for this card */
+static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP;	/* Enable this card */
+static int ac97_clock[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 48000};
+static int boot_devs;
+
+module_param_array(index, int, boot_devs, 0444);
+MODULE_PARM_DESC(index, "Index value for ATI IXP controller.");
+module_param_array(id, charp, boot_devs, 0444);
+MODULE_PARM_DESC(id, "ID string for ATI IXP controller.");
+module_param_array(enable, bool, boot_devs, 0444);
+MODULE_PARM_DESC(enable, "Enable audio part of ATI IXP controller.");
+module_param_array(ac97_clock, int, boot_devs, 0444);
+MODULE_PARM_DESC(ac97_clock, "AC'97 codec clock (default 48000Hz).");
+
+
+/*
+ */
+
+#define ATI_REG_ISR			0x00	/* interrupt source */
+#define  ATI_REG_ISR_MODEM_IN_XRUN	(1U<<0)
+#define  ATI_REG_ISR_MODEM_IN_STATUS	(1U<<1)
+#define  ATI_REG_ISR_MODEM_OUT1_XRUN	(1U<<2)
+#define  ATI_REG_ISR_MODEM_OUT1_STATUS	(1U<<3)
+#define  ATI_REG_ISR_MODEM_OUT2_XRUN	(1U<<4)
+#define  ATI_REG_ISR_MODEM_OUT2_STATUS	(1U<<5)
+#define  ATI_REG_ISR_MODEM_OUT3_XRUN	(1U<<6)
+#define  ATI_REG_ISR_MODEM_OUT3_STATUS	(1U<<7)
+#define  ATI_REG_ISR_PHYS_INTR		(1U<<8)
+#define  ATI_REG_ISR_PHYS_MISMATCH	(1U<<9)
+#define  ATI_REG_ISR_CODEC0_NOT_READY	(1U<<10)
+#define  ATI_REG_ISR_CODEC1_NOT_READY	(1U<<11)
+#define  ATI_REG_ISR_CODEC2_NOT_READY	(1U<<12)
+#define  ATI_REG_ISR_NEW_FRAME		(1U<<13)
+#define  ATI_REG_ISR_MODEM_GPIO_DATA	(1U<<14)
+
+#define ATI_REG_IER			0x04	/* interrupt enable */
+#define  ATI_REG_IER_MODEM_IN_XRUN_EN	(1U<<0)
+#define  ATI_REG_IER_MODEM_STATUS_EN	(1U<<1)
+#define  ATI_REG_IER_MODEM_OUT1_XRUN_EN	(1U<<2)
+#define  ATI_REG_IER_MODEM_OUT2_XRUN_EN	(1U<<4)
+#define  ATI_REG_IER_MODEM_OUT3_XRUN_EN	(1U<<6)
+#define  ATI_REG_IER_PHYS_INTR_EN	(1U<<8)
+#define  ATI_REG_IER_PHYS_MISMATCH_EN	(1U<<9)
+#define  ATI_REG_IER_CODEC0_INTR_EN	(1U<<10)
+#define  ATI_REG_IER_CODEC1_INTR_EN	(1U<<11)
+#define  ATI_REG_IER_CODEC2_INTR_EN	(1U<<12)
+#define  ATI_REG_IER_NEW_FRAME_EN	(1U<<13)	/* (RO */
+#define  ATI_REG_IER_MODEM_GPIO_DATA_EN	(1U<<14)	/* (WO) modem is running */
+#define  ATI_REG_IER_MODEM_SET_BUS_BUSY	(1U<<15)
+
+#define ATI_REG_CMD			0x08	/* command */
+#define  ATI_REG_CMD_POWERDOWN	(1U<<0)
+#define  ATI_REG_CMD_MODEM_RECEIVE_EN	(1U<<1)	/* modem only */
+#define  ATI_REG_CMD_MODEM_SEND1_EN	(1U<<2)	/* modem only */
+#define  ATI_REG_CMD_MODEM_SEND2_EN	(1U<<3)	/* modem only */
+#define  ATI_REG_CMD_MODEM_SEND3_EN	(1U<<4)	/* modem only */
+#define  ATI_REG_CMD_MODEM_STATUS_MEM	(1U<<5)	/* modem only */
+#define  ATI_REG_CMD_MODEM_IN_DMA_EN	(1U<<8)	/* modem only */
+#define  ATI_REG_CMD_MODEM_OUT_DMA1_EN	(1U<<9)	/* modem only */
+#define  ATI_REG_CMD_MODEM_OUT_DMA2_EN	(1U<<10)	/* modem only */
+#define  ATI_REG_CMD_MODEM_OUT_DMA3_EN	(1U<<11)	/* modem only */
+#define  ATI_REG_CMD_AUDIO_PRESENT	(1U<<20)
+#define  ATI_REG_CMD_MODEM_GPIO_THRU_DMA	(1U<<22)	/* modem only */
+#define  ATI_REG_CMD_LOOPBACK_EN	(1U<<23)
+#define  ATI_REG_CMD_PACKED_DIS		(1U<<24)
+#define  ATI_REG_CMD_BURST_EN		(1U<<25)
+#define  ATI_REG_CMD_PANIC_EN		(1U<<26)
+#define  ATI_REG_CMD_MODEM_PRESENT	(1U<<27)
+#define  ATI_REG_CMD_ACLINK_ACTIVE	(1U<<28)
+#define  ATI_REG_CMD_AC_SOFT_RESET	(1U<<29)
+#define  ATI_REG_CMD_AC_SYNC		(1U<<30)
+#define  ATI_REG_CMD_AC_RESET		(1U<<31)
+
+#define ATI_REG_PHYS_OUT_ADDR		0x0c
+#define  ATI_REG_PHYS_OUT_CODEC_MASK	(3U<<0)
+#define  ATI_REG_PHYS_OUT_RW		(1U<<2)
+#define  ATI_REG_PHYS_OUT_ADDR_EN	(1U<<8)
+#define  ATI_REG_PHYS_OUT_ADDR_SHIFT	9
+#define  ATI_REG_PHYS_OUT_DATA_SHIFT	16
+
+#define ATI_REG_PHYS_IN_ADDR		0x10
+#define  ATI_REG_PHYS_IN_READ_FLAG	(1U<<8)
+#define  ATI_REG_PHYS_IN_ADDR_SHIFT	9
+#define  ATI_REG_PHYS_IN_DATA_SHIFT	16
+
+#define ATI_REG_SLOTREQ			0x14
+
+#define ATI_REG_COUNTER			0x18
+#define  ATI_REG_COUNTER_SLOT		(3U<<0)	/* slot # */
+#define  ATI_REG_COUNTER_BITCLOCK	(31U<<8)
+
+#define ATI_REG_IN_FIFO_THRESHOLD	0x1c
+
+#define ATI_REG_MODEM_IN_DMA_LINKPTR	0x20
+#define ATI_REG_MODEM_IN_DMA_DT_START	0x24	/* RO */
+#define ATI_REG_MODEM_IN_DMA_DT_NEXT	0x28	/* RO */
+#define ATI_REG_MODEM_IN_DMA_DT_CUR	0x2c	/* RO */
+#define ATI_REG_MODEM_IN_DMA_DT_SIZE	0x30
+#define ATI_REG_MODEM_OUT_FIFO		0x34	/* output threshold */
+#define  ATI_REG_MODEM_OUT1_DMA_THRESHOLD_MASK	(0xf<<16)
+#define  ATI_REG_MODEM_OUT1_DMA_THRESHOLD_SHIFT	16
+#define ATI_REG_MODEM_OUT_DMA1_LINKPTR	0x38
+#define ATI_REG_MODEM_OUT_DMA2_LINKPTR	0x3c
+#define ATI_REG_MODEM_OUT_DMA3_LINKPTR	0x40
+#define ATI_REG_MODEM_OUT_DMA1_DT_START	0x44
+#define ATI_REG_MODEM_OUT_DMA1_DT_NEXT	0x48
+#define ATI_REG_MODEM_OUT_DMA1_DT_CUR	0x4c
+#define ATI_REG_MODEM_OUT_DMA2_DT_START	0x50
+#define ATI_REG_MODEM_OUT_DMA2_DT_NEXT	0x54
+#define ATI_REG_MODEM_OUT_DMA2_DT_CUR	0x58
+#define ATI_REG_MODEM_OUT_DMA3_DT_START	0x5c
+#define ATI_REG_MODEM_OUT_DMA3_DT_NEXT	0x60
+#define ATI_REG_MODEM_OUT_DMA3_DT_CUR	0x64
+#define ATI_REG_MODEM_OUT_DMA12_DT_SIZE	0x68
+#define ATI_REG_MODEM_OUT_DMA3_DT_SIZE	0x6c
+#define ATI_REG_MODEM_OUT_FIFO_USED     0x70
+#define ATI_REG_MODEM_OUT_GPIO		0x74
+#define  ATI_REG_MODEM_OUT_GPIO_EN	   1
+#define  ATI_REG_MODEM_OUT_GPIO_DATA_SHIFT 5
+#define ATI_REG_MODEM_IN_GPIO		0x78
+
+#define ATI_REG_MODEM_MIRROR		0x7c
+#define ATI_REG_AUDIO_MIRROR		0x80
+
+#define ATI_REG_MODEM_FIFO_FLUSH	0x88
+#define  ATI_REG_MODEM_FIFO_OUT1_FLUSH	(1U<<0)
+#define  ATI_REG_MODEM_FIFO_OUT2_FLUSH	(1U<<1)
+#define  ATI_REG_MODEM_FIFO_OUT3_FLUSH	(1U<<2)
+#define  ATI_REG_MODEM_FIFO_IN_FLUSH	(1U<<3)
+
+/* LINKPTR */
+#define  ATI_REG_LINKPTR_EN		(1U<<0)
+
+#define ATI_MAX_DESCRIPTORS	256	/* max number of descriptor packets */
+
+
+/*
+ */
+
+typedef struct snd_atiixp atiixp_t;
+typedef struct snd_atiixp_dma atiixp_dma_t;
+typedef struct snd_atiixp_dma_ops atiixp_dma_ops_t;
+
+
+/*
+ * DMA packate descriptor
+ */
+
+typedef struct atiixp_dma_desc {
+	u32 addr;	/* DMA buffer address */
+	u16 status;	/* status bits */
+	u16 size;	/* size of the packet in dwords */
+	u32 next;	/* address of the next packet descriptor */
+} atiixp_dma_desc_t;
+
+/*
+ * stream enum
+ */
+enum { ATI_DMA_PLAYBACK, ATI_DMA_CAPTURE, NUM_ATI_DMAS }; /* DMAs */
+enum { ATI_PCM_OUT, ATI_PCM_IN, NUM_ATI_PCMS }; /* AC97 pcm slots */
+enum { ATI_PCMDEV_ANALOG, NUM_ATI_PCMDEVS }; /* pcm devices */
+
+#define NUM_ATI_CODECS	3
+
+
+/*
+ * constants and callbacks for each DMA type
+ */
+struct snd_atiixp_dma_ops {
+	int type;			/* ATI_DMA_XXX */
+	unsigned int llp_offset;	/* LINKPTR offset */
+	unsigned int dt_cur;		/* DT_CUR offset */
+	void (*enable_dma)(atiixp_t *chip, int on);	/* called from open callback */
+	void (*enable_transfer)(atiixp_t *chip, int on); /* called from trigger (START/STOP) */
+	void (*flush_dma)(atiixp_t *chip);		/* called from trigger (STOP only) */
+};
+
+/*
+ * DMA stream
+ */
+struct snd_atiixp_dma {
+	const atiixp_dma_ops_t *ops;
+	struct snd_dma_buffer desc_buf;
+	snd_pcm_substream_t *substream;	/* assigned PCM substream */
+	unsigned int buf_addr, buf_bytes;	/* DMA buffer address, bytes */
+	unsigned int period_bytes, periods;
+	int opened;
+	int running;
+	int pcm_open_flag;
+	int ac97_pcm_type;	/* index # of ac97_pcm to access, -1 = not used */
+};
+
+/*
+ * ATI IXP chip
+ */
+struct snd_atiixp {
+	snd_card_t *card;
+	struct pci_dev *pci;
+
+	struct resource *res;		/* memory i/o */
+	unsigned long addr;
+	void __iomem *remap_addr;
+	int irq;
+	
+	ac97_bus_t *ac97_bus;
+	ac97_t *ac97[NUM_ATI_CODECS];
+
+	spinlock_t reg_lock;
+	spinlock_t ac97_lock;
+
+	atiixp_dma_t dmas[NUM_ATI_DMAS];
+	struct ac97_pcm *pcms[NUM_ATI_PCMS];
+	snd_pcm_t *pcmdevs[NUM_ATI_PCMDEVS];
+
+	int max_channels;		/* max. channels for PCM out */
+
+	unsigned int codec_not_ready_bits;	/* for codec detection */
+
+	int spdif_over_aclink;		/* passed from the module option */
+	struct semaphore open_mutex;	/* playback open mutex */
+};
+
+
+/*
+ */
+static struct pci_device_id snd_atiixp_ids[] = {
+	{ 0x1002, 0x434d, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, /* SB200 */
+	{ 0, }
+};
+
+MODULE_DEVICE_TABLE(pci, snd_atiixp_ids);
+
+
+/*
+ * lowlevel functions
+ */
+
+/*
+ * update the bits of the given register.
+ * return 1 if the bits changed.
+ */
+static int snd_atiixp_update_bits(atiixp_t *chip, unsigned int reg,
+				 unsigned int mask, unsigned int value)
+{
+	void __iomem *addr = chip->remap_addr + reg;
+	unsigned int data, old_data;
+	old_data = data = readl(addr);
+	data &= ~mask;
+	data |= value;
+	if (old_data == data)
+		return 0;
+	writel(data, addr);
+	return 1;
+}
+
+/*
+ * macros for easy use
+ */
+#define atiixp_write(chip,reg,value) \
+	writel(value, chip->remap_addr + ATI_REG_##reg)
+#define atiixp_read(chip,reg) \
+	readl(chip->remap_addr + ATI_REG_##reg)
+#define atiixp_update(chip,reg,mask,val) \
+	snd_atiixp_update_bits(chip, ATI_REG_##reg, mask, val)
+
+/* delay for one tick */
+#define do_delay() do { \
+	set_current_state(TASK_UNINTERRUPTIBLE); \
+	schedule_timeout(1); \
+} while (0)
+
+
+/*
+ * handling DMA packets
+ *
+ * we allocate a linear buffer for the DMA, and split it to  each packet.
+ * in a future version, a scatter-gather buffer should be implemented.
+ */
+
+#define ATI_DESC_LIST_SIZE \
+	PAGE_ALIGN(ATI_MAX_DESCRIPTORS * sizeof(atiixp_dma_desc_t))
+
+/*
+ * build packets ring for the given buffer size.
+ *
+ * IXP handles the buffer descriptors, which are connected as a linked
+ * list.  although we can change the list dynamically, in this version,
+ * a static RING of buffer descriptors is used.
+ *
+ * the ring is built in this function, and is set up to the hardware. 
+ */
+static int atiixp_build_dma_packets(atiixp_t *chip, atiixp_dma_t *dma,
+				   snd_pcm_substream_t *substream,
+				   unsigned int periods,
+				   unsigned int period_bytes)
+{
+	unsigned int i;
+	u32 addr, desc_addr;
+	unsigned long flags;
+
+	if (periods > ATI_MAX_DESCRIPTORS)
+		return -ENOMEM;
+
+	if (dma->desc_buf.area == NULL) {
+		if (snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, snd_dma_pci_data(chip->pci),
+					ATI_DESC_LIST_SIZE, &dma->desc_buf) < 0)
+			return -ENOMEM;
+		dma->period_bytes = dma->periods = 0; /* clear */
+	}
+
+	if (dma->periods == periods && dma->period_bytes == period_bytes)
+		return 0;
+
+	/* reset DMA before changing the descriptor table */
+	spin_lock_irqsave(&chip->reg_lock, flags);
+	writel(0, chip->remap_addr + dma->ops->llp_offset);
+	dma->ops->enable_dma(chip, 0);
+	dma->ops->enable_dma(chip, 1);
+	spin_unlock_irqrestore(&chip->reg_lock, flags);
+
+	/* fill the entries */
+	addr = (u32)substream->runtime->dma_addr;
+	desc_addr = (u32)dma->desc_buf.addr;
+	for (i = 0; i < periods; i++) {
+		atiixp_dma_desc_t *desc = &((atiixp_dma_desc_t *)dma->desc_buf.area)[i];
+		desc->addr = cpu_to_le32(addr);
+		desc->status = 0;
+		desc->size = period_bytes >> 2; /* in dwords */
+		desc_addr += sizeof(atiixp_dma_desc_t);
+		if (i == periods - 1)
+			desc->next = cpu_to_le32((u32)dma->desc_buf.addr);
+		else
+			desc->next = cpu_to_le32(desc_addr);
+		addr += period_bytes;
+	}
+
+	writel((u32)dma->desc_buf.addr | ATI_REG_LINKPTR_EN,
+	       chip->remap_addr + dma->ops->llp_offset);
+
+	dma->period_bytes = period_bytes;
+	dma->periods = periods;
+
+	return 0;
+}
+
+/*
+ * remove the ring buffer and release it if assigned
+ */
+static void atiixp_clear_dma_packets(atiixp_t *chip, atiixp_dma_t *dma, snd_pcm_substream_t *substream)
+{
+	if (dma->desc_buf.area) {
+		writel(0, chip->remap_addr + dma->ops->llp_offset);
+		snd_dma_free_pages(&dma->desc_buf);
+		dma->desc_buf.area = NULL;
+	}
+}
+
+/*
+ * AC97 interface
+ */
+static int snd_atiixp_acquire_codec(atiixp_t *chip)
+{
+	int timeout = 1000;
+
+	while (atiixp_read(chip, PHYS_OUT_ADDR) & ATI_REG_PHYS_OUT_ADDR_EN) {
+		if (! timeout--) {
+			snd_printk(KERN_WARNING "atiixp: codec acquire timeout\n");
+			return -EBUSY;
+		}
+		udelay(1);
+	}
+	return 0;
+}
+
+static unsigned short snd_atiixp_codec_read(atiixp_t *chip, unsigned short codec, unsigned short reg)
+{
+	unsigned int data;
+	int timeout;
+
+	if (snd_atiixp_acquire_codec(chip) < 0)
+		return 0xffff;
+	data = (reg << ATI_REG_PHYS_OUT_ADDR_SHIFT) |
+		ATI_REG_PHYS_OUT_ADDR_EN |
+		ATI_REG_PHYS_OUT_RW |
+		codec;
+	atiixp_write(chip, PHYS_OUT_ADDR, data);
+	if (snd_atiixp_acquire_codec(chip) < 0)
+		return 0xffff;
+	timeout = 1000;
+	do {
+		data = atiixp_read(chip, PHYS_IN_ADDR);
+		if (data & ATI_REG_PHYS_IN_READ_FLAG)
+			return data >> ATI_REG_PHYS_IN_DATA_SHIFT;
+		udelay(1);
+	} while (--timeout);
+	/* time out may happen during reset */
+	if (reg < 0x7c)
+		snd_printk(KERN_WARNING "atiixp: codec read timeout (reg %x)\n", reg);
+	return 0xffff;
+}
+
+
+static void snd_atiixp_codec_write(atiixp_t *chip, unsigned short codec, unsigned short reg, unsigned short val)
+{
+	unsigned int data;
+    
+	if (snd_atiixp_acquire_codec(chip) < 0)
+		return;
+	data = ((unsigned int)val << ATI_REG_PHYS_OUT_DATA_SHIFT) |
+		((unsigned int)reg << ATI_REG_PHYS_OUT_ADDR_SHIFT) |
+		ATI_REG_PHYS_OUT_ADDR_EN | codec;
+	atiixp_write(chip, PHYS_OUT_ADDR, data);
+}
+
+
+static unsigned short snd_atiixp_ac97_read(ac97_t *ac97, unsigned short reg)
+{
+	atiixp_t *chip = ac97->private_data;
+	unsigned short data;
+	spin_lock(&chip->ac97_lock);
+	data = snd_atiixp_codec_read(chip, ac97->num, reg);
+	spin_unlock(&chip->ac97_lock);
+	return data;
+    
+}
+
+static void snd_atiixp_ac97_write(ac97_t *ac97, unsigned short reg, unsigned short val)
+{
+	atiixp_t *chip = ac97->private_data;
+	spin_lock(&chip->ac97_lock);
+	snd_atiixp_codec_write(chip, ac97->num, reg, val);
+	spin_unlock(&chip->ac97_lock);
+}
+
+/*
+ * reset AC link
+ */
+static int snd_atiixp_aclink_reset(atiixp_t *chip)
+{
+	int timeout;
+
+	/* reset powerdoewn */
+	if (atiixp_update(chip, CMD, ATI_REG_CMD_POWERDOWN, 0))
+		udelay(10);
+
+	/* perform a software reset */
+	atiixp_update(chip, CMD, ATI_REG_CMD_AC_SOFT_RESET, ATI_REG_CMD_AC_SOFT_RESET);
+	atiixp_read(chip, CMD);
+	udelay(10);
+	atiixp_update(chip, CMD, ATI_REG_CMD_AC_SOFT_RESET, 0);
+    
+	timeout = 10;
+	while (! (atiixp_read(chip, CMD) & ATI_REG_CMD_ACLINK_ACTIVE)) {
+		/* do a hard reset */
+		atiixp_update(chip, CMD, ATI_REG_CMD_AC_SYNC|ATI_REG_CMD_AC_RESET,
+			      ATI_REG_CMD_AC_SYNC);
+		atiixp_read(chip, CMD);
+		do_delay();
+		atiixp_update(chip, CMD, ATI_REG_CMD_AC_RESET, ATI_REG_CMD_AC_RESET);
+		if (--timeout) {
+			snd_printk(KERN_ERR "atiixp: codec reset timeout\n");
+			break;
+		}
+	}
+
+	/* deassert RESET and assert SYNC to make sure */
+	atiixp_update(chip, CMD, ATI_REG_CMD_AC_SYNC|ATI_REG_CMD_AC_RESET,
+		      ATI_REG_CMD_AC_SYNC|ATI_REG_CMD_AC_RESET);
+
+	return 0;
+}
+
+#ifdef CONFIG_PM
+static int snd_atiixp_aclink_down(atiixp_t *chip)
+{
+	// if (atiixp_read(chip, MODEM_MIRROR) & 0x1) /* modem running, too? */
+	//	return -EBUSY;
+	atiixp_update(chip, CMD,
+		     ATI_REG_CMD_POWERDOWN | ATI_REG_CMD_AC_RESET,
+		     ATI_REG_CMD_POWERDOWN);
+	return 0;
+}
+#endif
+
+/*
+ * auto-detection of codecs
+ *
+ * the IXP chip can generate interrupts for the non-existing codecs.
+ * NEW_FRAME interrupt is used to make sure that the interrupt is generated
+ * even if all three codecs are connected.
+ */
+
+#define ALL_CODEC_NOT_READY \
+	    (ATI_REG_ISR_CODEC0_NOT_READY |\
+	     ATI_REG_ISR_CODEC1_NOT_READY |\
+	     ATI_REG_ISR_CODEC2_NOT_READY)
+#define CODEC_CHECK_BITS (ALL_CODEC_NOT_READY|ATI_REG_ISR_NEW_FRAME)
+
+static int snd_atiixp_codec_detect(atiixp_t *chip)
+{
+	int timeout;
+
+	chip->codec_not_ready_bits = 0;
+	atiixp_write(chip, IER, CODEC_CHECK_BITS);
+	/* wait for the interrupts */
+	timeout = HZ / 10;
+	while (timeout-- > 0) {
+		do_delay();
+		if (chip->codec_not_ready_bits)
+			break;
+	}
+	atiixp_write(chip, IER, 0); /* disable irqs */
+
+	if ((chip->codec_not_ready_bits & ALL_CODEC_NOT_READY) == ALL_CODEC_NOT_READY) {
+		snd_printk(KERN_ERR "atiixp: no codec detected!\n");
+		return -ENXIO;
+	}
+	return 0;
+}
+
+
+/*
+ * enable DMA and irqs
+ */
+static int snd_atiixp_chip_start(atiixp_t *chip)
+{
+	unsigned int reg;
+
+	/* set up spdif, enable burst mode */
+	reg = atiixp_read(chip, CMD);
+	reg |= ATI_REG_CMD_BURST_EN;
+	if(!(reg & ATI_REG_CMD_MODEM_PRESENT))
+		reg |= ATI_REG_CMD_MODEM_PRESENT;
+	atiixp_write(chip, CMD, reg);
+
+	/* clear all interrupt source */
+	atiixp_write(chip, ISR, 0xffffffff);
+	/* enable irqs */
+	atiixp_write(chip, IER,
+		     ATI_REG_IER_MODEM_STATUS_EN |
+		     ATI_REG_IER_MODEM_IN_XRUN_EN |
+		     ATI_REG_IER_MODEM_OUT1_XRUN_EN);
+	return 0;
+}
+
+
+/*
+ * disable DMA and IRQs
+ */
+static int snd_atiixp_chip_stop(atiixp_t *chip)
+{
+	/* clear interrupt source */
+	atiixp_write(chip, ISR, atiixp_read(chip, ISR));
+	/* disable irqs */
+	atiixp_write(chip, IER, 0);
+	return 0;
+}
+
+
+/*
+ * PCM section
+ */
+
+/*
+ * pointer callback simplly reads XXX_DMA_DT_CUR register as the current
+ * position.  when SG-buffer is implemented, the offset must be calculated
+ * correctly...
+ */
+static snd_pcm_uframes_t snd_atiixp_pcm_pointer(snd_pcm_substream_t *substream)
+{
+	atiixp_t *chip = snd_pcm_substream_chip(substream);
+	snd_pcm_runtime_t *runtime = substream->runtime;
+	atiixp_dma_t *dma = (atiixp_dma_t *)runtime->private_data;
+	unsigned int curptr;
+
+	spin_lock(&chip->reg_lock);
+	curptr = readl(chip->remap_addr + dma->ops->dt_cur);
+	if (curptr < dma->buf_addr) {
+		snd_printdd("curptr = %x, base = %x\n", curptr, dma->buf_addr);
+		curptr = 0;
+	} else {
+		curptr -= dma->buf_addr;
+		if (curptr >= dma->buf_bytes) {
+			snd_printdd("curptr = %x, size = %x\n", curptr, dma->buf_bytes);
+			curptr = 0;
+		}
+	}
+	spin_unlock(&chip->reg_lock);
+	return bytes_to_frames(runtime, curptr);
+}
+
+/*
+ * XRUN detected, and stop the PCM substream
+ */
+static void snd_atiixp_xrun_dma(atiixp_t *chip, atiixp_dma_t *dma)
+{
+	if (! dma->substream || ! dma->running)
+		return;
+	snd_printdd("atiixp: XRUN detected (DMA %d)\n", dma->ops->type);
+	snd_pcm_stop(dma->substream, SNDRV_PCM_STATE_XRUN);
+}
+
+/*
+ * the period ack.  update the substream.
+ */
+static void snd_atiixp_update_dma(atiixp_t *chip, atiixp_dma_t *dma)
+{
+	if (! dma->substream || ! dma->running)
+		return;
+	snd_pcm_period_elapsed(dma->substream);
+}
+
+/* set BUS_BUSY interrupt bit if any DMA is running */
+/* call with spinlock held */
+static void snd_atiixp_check_bus_busy(atiixp_t *chip)
+{
+	unsigned int bus_busy;
+	if (atiixp_read(chip, CMD) & (ATI_REG_CMD_MODEM_SEND1_EN |
+				      ATI_REG_CMD_MODEM_RECEIVE_EN))
+		bus_busy = ATI_REG_IER_MODEM_SET_BUS_BUSY;
+	else
+		bus_busy = 0;
+	atiixp_update(chip, IER, ATI_REG_IER_MODEM_SET_BUS_BUSY, bus_busy);
+}
+
+/* common trigger callback
+ * calling the lowlevel callbacks in it
+ */
+static int snd_atiixp_pcm_trigger(snd_pcm_substream_t *substream, int cmd)
+{
+	atiixp_t *chip = snd_pcm_substream_chip(substream);
+	atiixp_dma_t *dma = (atiixp_dma_t *)substream->runtime->private_data;
+	unsigned int reg = 0;
+	int i;
+
+	snd_assert(dma->ops->enable_transfer && dma->ops->flush_dma, return -EINVAL);
+
+	if (cmd != SNDRV_PCM_TRIGGER_START && cmd != SNDRV_PCM_TRIGGER_STOP)
+		return -EINVAL;
+
+	spin_lock(&chip->reg_lock);
+
+	/* hook off/on: via GPIO_OUT */
+	for (i = 0; i < NUM_ATI_CODECS; i++) {
+		if (chip->ac97[i]) {
+			reg = snd_ac97_read(chip->ac97[i], AC97_GPIO_STATUS);
+			break;
+	}
+	}
+	if(cmd == SNDRV_PCM_TRIGGER_START)
+		reg |= AC97_GPIO_LINE1_OH;
+	else
+		reg &= ~AC97_GPIO_LINE1_OH;
+	reg = (reg << ATI_REG_MODEM_OUT_GPIO_DATA_SHIFT) | ATI_REG_MODEM_OUT_GPIO_EN ;
+	atiixp_write(chip, MODEM_OUT_GPIO, reg);
+
+	if (cmd == SNDRV_PCM_TRIGGER_START) {
+		dma->ops->enable_transfer(chip, 1);
+		dma->running = 1;
+	} else {
+		dma->ops->enable_transfer(chip, 0);
+		dma->running = 0;
+	}
+	snd_atiixp_check_bus_busy(chip);
+	if (cmd == SNDRV_PCM_TRIGGER_STOP) {
+		dma->ops->flush_dma(chip);
+		snd_atiixp_check_bus_busy(chip);
+	}
+	spin_unlock(&chip->reg_lock);
+	return 0;
+}
+
+
+/*
+ * lowlevel callbacks for each DMA type
+ *
+ * every callback is supposed to be called in chip->reg_lock spinlock
+ */
+
+/* flush FIFO of analog OUT DMA */
+static void atiixp_out_flush_dma(atiixp_t *chip)
+{
+	atiixp_write(chip, MODEM_FIFO_FLUSH, ATI_REG_MODEM_FIFO_OUT1_FLUSH);
+}
+
+/* enable/disable analog OUT DMA */
+static void atiixp_out_enable_dma(atiixp_t *chip, int on)
+{
+	unsigned int data;
+	data = atiixp_read(chip, CMD);
+	if (on) {
+		if (data & ATI_REG_CMD_MODEM_OUT_DMA1_EN)
+			return;
+		atiixp_out_flush_dma(chip);
+		data |= ATI_REG_CMD_MODEM_OUT_DMA1_EN;
+	} else
+		data &= ~ATI_REG_CMD_MODEM_OUT_DMA1_EN;
+	atiixp_write(chip, CMD, data);
+}
+
+/* start/stop transfer over OUT DMA */
+static void atiixp_out_enable_transfer(atiixp_t *chip, int on)
+{
+	atiixp_update(chip, CMD, ATI_REG_CMD_MODEM_SEND1_EN,
+		      on ? ATI_REG_CMD_MODEM_SEND1_EN : 0);
+}
+
+/* enable/disable analog IN DMA */
+static void atiixp_in_enable_dma(atiixp_t *chip, int on)
+{
+	atiixp_update(chip, CMD, ATI_REG_CMD_MODEM_IN_DMA_EN,
+		      on ? ATI_REG_CMD_MODEM_IN_DMA_EN : 0);
+}
+
+/* start/stop analog IN DMA */
+static void atiixp_in_enable_transfer(atiixp_t *chip, int on)
+{
+	if (on) {
+		unsigned int data = atiixp_read(chip, CMD);
+		if (! (data & ATI_REG_CMD_MODEM_RECEIVE_EN)) {
+			data |= ATI_REG_CMD_MODEM_RECEIVE_EN;
+			atiixp_write(chip, CMD, data);
+		}
+	} else
+		atiixp_update(chip, CMD, ATI_REG_CMD_MODEM_RECEIVE_EN, 0);
+}
+
+/* flush FIFO of analog IN DMA */
+static void atiixp_in_flush_dma(atiixp_t *chip)
+{
+	atiixp_write(chip, MODEM_FIFO_FLUSH, ATI_REG_MODEM_FIFO_IN_FLUSH);
+}
+
+/* set up slots and formats for analog OUT */
+static int snd_atiixp_playback_prepare(snd_pcm_substream_t *substream)
+{
+	atiixp_t *chip = snd_pcm_substream_chip(substream);
+	unsigned int data;
+
+	spin_lock_irq(&chip->reg_lock);
+	/* set output threshold */
+	data = atiixp_read(chip, MODEM_OUT_FIFO);
+	data &= ~ATI_REG_MODEM_OUT1_DMA_THRESHOLD_MASK;
+	data |= 0x04 << ATI_REG_MODEM_OUT1_DMA_THRESHOLD_SHIFT;
+	atiixp_write(chip, MODEM_OUT_FIFO, data);
+	spin_unlock_irq(&chip->reg_lock);
+	return 0;
+}
+
+/* set up slots and formats for analog IN */
+static int snd_atiixp_capture_prepare(snd_pcm_substream_t *substream)
+{
+	return 0;
+}
+
+/*
+ * hw_params - allocate the buffer and set up buffer descriptors
+ */
+static int snd_atiixp_pcm_hw_params(snd_pcm_substream_t *substream,
+				   snd_pcm_hw_params_t *hw_params)
+{
+	atiixp_t *chip = snd_pcm_substream_chip(substream);
+	atiixp_dma_t *dma = (atiixp_dma_t *)substream->runtime->private_data;
+	int err;
+	int i;
+
+	err = snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(hw_params));
+	if (err < 0)
+		return err;
+	dma->buf_addr = substream->runtime->dma_addr;
+	dma->buf_bytes = params_buffer_bytes(hw_params);
+
+	err = atiixp_build_dma_packets(chip, dma, substream,
+				       params_periods(hw_params),
+				       params_period_bytes(hw_params));
+	if (err < 0)
+		return err;
+
+	/* set up modem rate */
+	for (i = 0; i < NUM_ATI_CODECS; i++) {
+		if (! chip->ac97[i])
+			continue;
+		snd_ac97_write(chip->ac97[i], AC97_LINE1_RATE, params_rate(hw_params));
+		snd_ac97_write(chip->ac97[i], AC97_LINE1_LEVEL, 0);
+	}
+
+	return err;
+}
+
+static int snd_atiixp_pcm_hw_free(snd_pcm_substream_t * substream)
+{
+	atiixp_t *chip = snd_pcm_substream_chip(substream);
+	atiixp_dma_t *dma = (atiixp_dma_t *)substream->runtime->private_data;
+
+	atiixp_clear_dma_packets(chip, dma, substream);
+	snd_pcm_lib_free_pages(substream);
+	return 0;
+}
+
+
+/*
+ * pcm hardware definition, identical for all DMA types
+ */
+static snd_pcm_hardware_t snd_atiixp_pcm_hw =
+{
+	.info =			(SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED |
+				 SNDRV_PCM_INFO_BLOCK_TRANSFER |
+				 SNDRV_PCM_INFO_MMAP_VALID),
+	.formats =		SNDRV_PCM_FMTBIT_S16_LE,
+	.rates =		SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000 | SNDRV_PCM_RATE_KNOT,
+	.rate_min =		8000,
+	.rate_max =		16000,
+	.channels_min =		2,
+	.channels_max =		2,
+	.buffer_bytes_max =	256 * 1024,
+	.period_bytes_min =	32,
+	.period_bytes_max =	128 * 1024,
+	.periods_min =		2,
+	.periods_max =		ATI_MAX_DESCRIPTORS,
+};
+
+static int snd_atiixp_pcm_open(snd_pcm_substream_t *substream, atiixp_dma_t *dma, int pcm_type)
+{
+	atiixp_t *chip = snd_pcm_substream_chip(substream);
+	snd_pcm_runtime_t *runtime = substream->runtime;
+	int err;
+	static unsigned int rates[] = { 8000,  9600, 12000, 16000 };
+	static snd_pcm_hw_constraint_list_t hw_constraints_rates = {
+		.count = ARRAY_SIZE(rates),
+		.list = rates,
+		.mask = 0,
+	};
+
+	snd_assert(dma->ops && dma->ops->enable_dma, return -EINVAL);
+
+	if (dma->opened)
+		return -EBUSY;
+	dma->substream = substream;
+	runtime->hw = snd_atiixp_pcm_hw;
+	dma->ac97_pcm_type = pcm_type;
+	if ((err = snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_RATE, &hw_constraints_rates)) < 0)
+		return err;
+	if ((err = snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIODS)) < 0)
+		return err;
+	runtime->private_data = dma;
+
+	/* enable DMA bits */
+	spin_lock_irq(&chip->reg_lock);
+	dma->ops->enable_dma(chip, 1);
+	spin_unlock_irq(&chip->reg_lock);
+	dma->opened = 1;
+
+	return 0;
+}
+
+static int snd_atiixp_pcm_close(snd_pcm_substream_t *substream, atiixp_dma_t *dma)
+{
+	atiixp_t *chip = snd_pcm_substream_chip(substream);
+	/* disable DMA bits */
+	snd_assert(dma->ops && dma->ops->enable_dma, return -EINVAL);
+	spin_lock_irq(&chip->reg_lock);
+	dma->ops->enable_dma(chip, 0);
+	spin_unlock_irq(&chip->reg_lock);
+	dma->substream = NULL;
+	dma->opened = 0;
+	return 0;
+}
+
+/*
+ */
+static int snd_atiixp_playback_open(snd_pcm_substream_t *substream)
+{
+	atiixp_t *chip = snd_pcm_substream_chip(substream);
+	int err;
+
+	down(&chip->open_mutex);
+	err = snd_atiixp_pcm_open(substream, &chip->dmas[ATI_DMA_PLAYBACK], 0);
+	up(&chip->open_mutex);
+	if (err < 0)
+		return err;
+	return 0;
+}
+
+static int snd_atiixp_playback_close(snd_pcm_substream_t *substream)
+{
+	atiixp_t *chip = snd_pcm_substream_chip(substream);
+	int err;
+	down(&chip->open_mutex);
+	err = snd_atiixp_pcm_close(substream, &chip->dmas[ATI_DMA_PLAYBACK]);
+	up(&chip->open_mutex);
+	return err;
+}
+
+static int snd_atiixp_capture_open(snd_pcm_substream_t *substream)
+{
+	atiixp_t *chip = snd_pcm_substream_chip(substream);
+	return snd_atiixp_pcm_open(substream, &chip->dmas[ATI_DMA_CAPTURE], 1);
+}
+
+static int snd_atiixp_capture_close(snd_pcm_substream_t *substream)
+{
+	atiixp_t *chip = snd_pcm_substream_chip(substream);
+	return snd_atiixp_pcm_close(substream, &chip->dmas[ATI_DMA_CAPTURE]);
+}
+
+
+/* AC97 playback */
+static snd_pcm_ops_t snd_atiixp_playback_ops = {
+	.open =		snd_atiixp_playback_open,
+	.close =	snd_atiixp_playback_close,
+	.ioctl =	snd_pcm_lib_ioctl,
+	.hw_params =	snd_atiixp_pcm_hw_params,
+	.hw_free =	snd_atiixp_pcm_hw_free,
+	.prepare =	snd_atiixp_playback_prepare,
+	.trigger =	snd_atiixp_pcm_trigger,
+	.pointer =	snd_atiixp_pcm_pointer,
+};
+
+/* AC97 capture */
+static snd_pcm_ops_t snd_atiixp_capture_ops = {
+	.open =		snd_atiixp_capture_open,
+	.close =	snd_atiixp_capture_close,
+	.ioctl =	snd_pcm_lib_ioctl,
+	.hw_params =	snd_atiixp_pcm_hw_params,
+	.hw_free =	snd_atiixp_pcm_hw_free,
+	.prepare =	snd_atiixp_capture_prepare,
+	.trigger =	snd_atiixp_pcm_trigger,
+	.pointer =	snd_atiixp_pcm_pointer,
+};
+
+static atiixp_dma_ops_t snd_atiixp_playback_dma_ops = {
+	.type = ATI_DMA_PLAYBACK,
+	.llp_offset = ATI_REG_MODEM_OUT_DMA1_LINKPTR,
+	.dt_cur = ATI_REG_MODEM_OUT_DMA1_DT_CUR,
+	.enable_dma = atiixp_out_enable_dma,
+	.enable_transfer = atiixp_out_enable_transfer,
+	.flush_dma = atiixp_out_flush_dma,
+};
+	
+static atiixp_dma_ops_t snd_atiixp_capture_dma_ops = {
+	.type = ATI_DMA_CAPTURE,
+	.llp_offset = ATI_REG_MODEM_IN_DMA_LINKPTR,
+	.dt_cur = ATI_REG_MODEM_IN_DMA_DT_CUR,
+	.enable_dma = atiixp_in_enable_dma,
+	.enable_transfer = atiixp_in_enable_transfer,
+	.flush_dma = atiixp_in_flush_dma,
+};
+
+static int __devinit snd_atiixp_pcm_new(atiixp_t *chip)
+{
+	snd_pcm_t *pcm;
+	int err;
+
+	/* initialize constants */
+	chip->dmas[ATI_DMA_PLAYBACK].ops = &snd_atiixp_playback_dma_ops;
+	chip->dmas[ATI_DMA_CAPTURE].ops = &snd_atiixp_capture_dma_ops;
+
+	/* PCM #0: analog I/O */
+	err = snd_pcm_new(chip->card, "ATI IXP MC97", ATI_PCMDEV_ANALOG, 1, 1, &pcm);
+	if (err < 0)
+		return err;
+	snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_atiixp_playback_ops);
+	snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_atiixp_capture_ops);
+	pcm->private_data = chip;
+	strcpy(pcm->name, "ATI IXP MC97");
+	chip->pcmdevs[ATI_PCMDEV_ANALOG] = pcm;
+
+	snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV,
+					      snd_dma_pci_data(chip->pci), 64*1024, 128*1024);
+
+	return 0;
+}
+
+
+
+/*
+ * interrupt handler
+ */
+static irqreturn_t snd_atiixp_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+{
+	atiixp_t *chip = dev_id;
+	unsigned int status;
+
+	status = atiixp_read(chip, ISR);
+
+	if (! status)
+		return IRQ_NONE;
+
+	/* process audio DMA */
+	if (status & ATI_REG_ISR_MODEM_OUT1_XRUN)
+		snd_atiixp_xrun_dma(chip,  &chip->dmas[ATI_DMA_PLAYBACK]);
+	else if (status & ATI_REG_ISR_MODEM_OUT1_STATUS)
+		snd_atiixp_update_dma(chip, &chip->dmas[ATI_DMA_PLAYBACK]);
+	if (status & ATI_REG_ISR_MODEM_IN_XRUN)
+		snd_atiixp_xrun_dma(chip,  &chip->dmas[ATI_DMA_CAPTURE]);
+	else if (status & ATI_REG_ISR_MODEM_IN_STATUS)
+		snd_atiixp_update_dma(chip, &chip->dmas[ATI_DMA_CAPTURE]);
+
+	/* for codec detection */
+	if (status & CODEC_CHECK_BITS) {
+		unsigned int detected;
+		detected = status & CODEC_CHECK_BITS;
+		spin_lock(&chip->reg_lock);
+		chip->codec_not_ready_bits |= detected;
+		atiixp_update(chip, IER, detected, 0); /* disable the detected irqs */
+		spin_unlock(&chip->reg_lock);
+	}
+
+	/* ack */
+	atiixp_write(chip, ISR, status);
+
+	return IRQ_HANDLED;
+}
+
+
+/*
+ * ac97 mixer section
+ */
+
+static int __devinit snd_atiixp_mixer_new(atiixp_t *chip, int clock)
+{
+	ac97_bus_t *pbus;
+	ac97_template_t ac97;
+	int i, err;
+	int codec_count;
+	static ac97_bus_ops_t ops = {
+		.write = snd_atiixp_ac97_write,
+		.read = snd_atiixp_ac97_read,
+	};
+	static unsigned int codec_skip[NUM_ATI_CODECS] = {
+		ATI_REG_ISR_CODEC0_NOT_READY,
+		ATI_REG_ISR_CODEC1_NOT_READY,
+		ATI_REG_ISR_CODEC2_NOT_READY,
+	};
+
+	if (snd_atiixp_codec_detect(chip) < 0)
+		return -ENXIO;
+
+	if ((err = snd_ac97_bus(chip->card, 0, &ops, chip, &pbus)) < 0)
+		return err;
+	pbus->clock = clock;
+	pbus->shared_type = AC97_SHARED_TYPE_ATIIXP;	/* shared with audio driver */
+	chip->ac97_bus = pbus;
+
+	codec_count = 0;
+	for (i = 0; i < NUM_ATI_CODECS; i++) {
+		if (chip->codec_not_ready_bits & codec_skip[i])
+			continue;
+		memset(&ac97, 0, sizeof(ac97));
+		ac97.private_data = chip;
+		ac97.pci = chip->pci;
+		ac97.num = i;
+		ac97.scaps = AC97_SCAP_SKIP_AUDIO;
+		if ((err = snd_ac97_mixer(pbus, &ac97, &chip->ac97[i])) < 0) {
+			chip->ac97[i] = NULL; /* to be sure */
+			snd_printdd("atiixp: codec %d not available for modem\n", i);
+			continue;
+		}
+		codec_count++;
+	}
+
+	if (! codec_count) {
+		snd_printk(KERN_ERR "atiixp: no codec available\n");
+		return -ENODEV;
+	}
+
+	/* snd_ac97_tune_hardware(chip->ac97, ac97_quirks); */
+
+	return 0;
+}
+
+
+#ifdef CONFIG_PM
+/*
+ * power management
+ */
+static int snd_atiixp_suspend(snd_card_t *card, unsigned int state)
+{
+	atiixp_t *chip = card->pm_private_data;
+	int i;
+
+	for (i = 0; i < NUM_ATI_PCMDEVS; i++)
+		if (chip->pcmdevs[i])
+			snd_pcm_suspend_all(chip->pcmdevs[i]);
+	for (i = 0; i < NUM_ATI_CODECS; i++)
+		if (chip->ac97[i])
+			snd_ac97_suspend(chip->ac97[i]);
+	snd_atiixp_aclink_down(chip);
+	snd_atiixp_chip_stop(chip);
+
+	pci_set_power_state(chip->pci, 3);
+	pci_disable_device(chip->pci);
+	snd_power_change_state(card, SNDRV_CTL_POWER_D3hot);
+	return 0;
+}
+
+static int snd_atiixp_resume(snd_card_t *card, unsigned int state)
+{
+	atiixp_t *chip = card->pm_private_data;
+	int i;
+
+	pci_enable_device(chip->pci);
+	pci_set_power_state(chip->pci, 0);
+
+	snd_atiixp_aclink_reset(chip);
+	snd_atiixp_chip_start(chip);
+
+	for (i = 0; i < NUM_ATI_CODECS; i++)
+		if (chip->ac97[i])
+			snd_ac97_resume(chip->ac97[i]);
+
+	snd_power_change_state(card, SNDRV_CTL_POWER_D0);
+	return 0;
+}
+#endif /* CONFIG_PM */
+
+
+/*
+ * proc interface for register dump
+ */
+
+static void snd_atiixp_proc_read(snd_info_entry_t *entry, snd_info_buffer_t *buffer)
+{
+	atiixp_t *chip = entry->private_data;
+	int i;
+
+	for (i = 0; i < 256; i += 4)
+		snd_iprintf(buffer, "%02x: %08x\n", i, readl(chip->remap_addr + i));
+}
+
+static void __devinit snd_atiixp_proc_init(atiixp_t *chip)
+{
+	snd_info_entry_t *entry;
+
+	if (! snd_card_proc_new(chip->card, "atiixp", &entry))
+		snd_info_set_text_ops(entry, chip, 1024, snd_atiixp_proc_read);
+}
+
+
+
+/*
+ * destructor
+ */
+
+static int snd_atiixp_free(atiixp_t *chip)
+{
+	if (chip->irq < 0)
+		goto __hw_end;
+	snd_atiixp_chip_stop(chip);
+	synchronize_irq(chip->irq);
+      __hw_end:
+	if (chip->irq >= 0)
+		free_irq(chip->irq, (void *)chip);
+	if (chip->remap_addr)
+		iounmap(chip->remap_addr);
+	pci_release_regions(chip->pci);
+	kfree(chip);
+	return 0;
+}
+
+static int snd_atiixp_dev_free(snd_device_t *device)
+{
+	atiixp_t *chip = device->device_data;
+	return snd_atiixp_free(chip);
+}
+
+/*
+ * constructor for chip instance
+ */
+static int __devinit snd_atiixp_create(snd_card_t *card,
+				      struct pci_dev *pci,
+				      atiixp_t **r_chip)
+{
+	static snd_device_ops_t ops = {
+		.dev_free =	snd_atiixp_dev_free,
+	};
+	atiixp_t *chip;
+	int err;
+
+	if ((err = pci_enable_device(pci)) < 0)
+		return err;
+
+	chip = kcalloc(1, sizeof(*chip), GFP_KERNEL);
+	if (chip == NULL)
+		return -ENOMEM;
+
+	spin_lock_init(&chip->reg_lock);
+	spin_lock_init(&chip->ac97_lock);
+	init_MUTEX(&chip->open_mutex);
+	chip->card = card;
+	chip->pci = pci;
+	chip->irq = -1;
+	if ((err = pci_request_regions(pci, "ATI IXP MC97")) < 0) {
+		kfree(chip);
+		return err;
+	}
+	chip->addr = pci_resource_start(pci, 0);
+	chip->remap_addr = ioremap_nocache(chip->addr, pci_resource_len(pci, 0));
+	if (chip->remap_addr == 0) {
+		snd_printk(KERN_ERR "AC'97 space ioremap problem\n");
+		snd_atiixp_free(chip);
+		return -EIO;
+	}
+
+	if (request_irq(pci->irq, snd_atiixp_interrupt, SA_INTERRUPT|SA_SHIRQ, card->shortname, (void *)chip)) {
+		snd_printk(KERN_ERR "unable to grab IRQ %d\n", pci->irq);
+		snd_atiixp_free(chip);
+		return -EBUSY;
+	}
+	chip->irq = pci->irq;
+	pci_set_master(pci);
+	synchronize_irq(chip->irq);
+
+	if ((err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops)) < 0) {
+		snd_atiixp_free(chip);
+		return err;
+	}
+
+	snd_card_set_dev(card, &pci->dev);
+
+	*r_chip = chip;
+	return 0;
+}
+
+
+static int __devinit snd_atiixp_probe(struct pci_dev *pci,
+				      const struct pci_device_id *pci_id)
+{
+	static int dev;
+	snd_card_t *card;
+	atiixp_t *chip;
+	unsigned char revision;
+	int err;
+
+	if (dev >= SNDRV_CARDS)
+		return -ENODEV;
+	if (!enable[dev]) {
+		dev++;
+		return -ENOENT;
+	}
+
+	card = snd_card_new(index[dev], id[dev], THIS_MODULE, 0);
+	if (card == NULL)
+		return -ENOMEM;
+
+	pci_read_config_byte(pci, PCI_REVISION_ID, &revision);
+
+	strcpy(card->driver, "ATIIXP-MODEM");
+	strcpy(card->shortname, "ATI IXP Modem");
+	if ((err = snd_atiixp_create(card, pci, &chip)) < 0)
+		goto __error;
+
+	if ((err = snd_atiixp_aclink_reset(chip)) < 0)
+		goto __error;
+
+	if ((err = snd_atiixp_mixer_new(chip, ac97_clock[dev])) < 0)
+		goto __error;
+
+	if ((err = snd_atiixp_pcm_new(chip)) < 0)
+		goto __error;
+	
+	snd_atiixp_proc_init(chip);
+
+	snd_atiixp_chip_start(chip);
+
+	sprintf(card->longname, "%s rev %x at 0x%lx, irq %i",
+		card->shortname, revision, chip->addr, chip->irq);
+
+	snd_card_set_pm_callback(card, snd_atiixp_suspend, snd_atiixp_resume, chip);
+
+	if ((err = snd_card_register(card)) < 0)
+		goto __error;
+
+	pci_set_drvdata(pci, card);
+	dev++;
+	return 0;
+
+ __error:
+	snd_card_free(card);
+	return err;
+}
+
+static void __devexit snd_atiixp_remove(struct pci_dev *pci)
+{
+	snd_card_free(pci_get_drvdata(pci));
+	pci_set_drvdata(pci, NULL);
+}
+
+static struct pci_driver driver = {
+	.name = "ATI IXP MC97 controller",
+	.id_table = snd_atiixp_ids,
+	.probe = snd_atiixp_probe,
+	.remove = __devexit_p(snd_atiixp_remove),
+	SND_PCI_PM_CALLBACKS
+};
+
+
+static int __init alsa_card_atiixp_init(void)
+{
+	return pci_module_init(&driver);
+}
+
+static void __exit alsa_card_atiixp_exit(void)
+{
+	pci_unregister_driver(&driver);
+}
+
+module_init(alsa_card_atiixp_init)
+module_exit(alsa_card_atiixp_exit)
diff -Nru a/sound/pci/au88x0/au88x0.c b/sound/pci/au88x0/au88x0.c
--- a/sound/pci/au88x0/au88x0.c	2004-10-18 14:56:32 -07:00
+++ b/sound/pci/au88x0/au88x0.c	2004-10-18 14:56:32 -07:00
@@ -31,23 +31,16 @@
 
 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);
 module_param_array(pcifix, int, boot_devs, 0444);
 MODULE_PARM_DESC(pcifix, "Enable VIA-workaround for " CARD_NAME " soundcard.");
-MODULE_PARM_SYNTAX(pcifix,
-		   SNDRV_ENABLED
-		   ",allows:{{0,Disabled},{1,Latency},{2,Bridge},{3,Both},{255,Auto}},default:4,dialog:check");
 
 MODULE_DESCRIPTION("Aureal vortex");
-MODULE_CLASSES("{sound}");
 MODULE_LICENSE("GPL");
-MODULE_DEVICES("{{Aureal Semiconductor Inc., Aureal Vortex Sound Processor}}");
+MODULE_SUPPORTED_DEVICE("{{Aureal Semiconductor Inc., Aureal Vortex Sound Processor}}");
 
 MODULE_DEVICE_TABLE(pci, snd_vortex_ids);
 
@@ -122,8 +115,7 @@
 // (see "Management of Cards and Components")
 static int snd_vortex_dev_free(snd_device_t * device)
 {
-	vortex_t *vortex = snd_magic_cast(vortex_t, device->device_data,
-					  return -ENXIO);
+	vortex_t *vortex = device->device_data;
 
 	vortex_gameport_unregister(vortex);
 	vortex_core_shutdown(vortex);
@@ -132,7 +124,7 @@
 	free_irq(vortex->irq, vortex);
 	pci_release_regions(vortex->pci_dev);
 	pci_disable_device(vortex->pci_dev);
-	snd_magic_kfree(vortex);
+	kfree(vortex);
 
 	return 0;
 }
@@ -159,7 +151,7 @@
 	}
 	pci_set_dma_mask(pci, VORTEX_DMA_MASK);
 
-	chip = snd_magic_kcalloc(vortex_t, 0, GFP_KERNEL);
+	chip = kcalloc(1, sizeof(*chip), GFP_KERNEL);
 	if (chip == NULL)
 		return -ENOMEM;
 
diff -Nru a/sound/pci/au88x0/au88x0.h b/sound/pci/au88x0/au88x0.h
--- a/sound/pci/au88x0/au88x0.h	2004-10-18 14:56:33 -07:00
+++ b/sound/pci/au88x0/au88x0.h	2004-10-18 14:56:33 -07:00
@@ -180,8 +180,6 @@
 	u8 rev;
 };
 
-#define chip_t vortex_t
-
 /* Functions. */
 
 /* SRC */
diff -Nru a/sound/pci/au88x0/au88x0_a3d.c b/sound/pci/au88x0/au88x0_a3d.c
--- a/sound/pci/au88x0/au88x0_a3d.c	2004-10-18 14:56:32 -07:00
+++ b/sound/pci/au88x0/au88x0_a3d.c	2004-10-18 14:56:32 -07:00
@@ -567,7 +567,7 @@
 	v->xt_mode = mode;	/* this_14 */
 
 	vortex_XtalkHw_init(v);
-	vortex_XtalkHw_SetGains(v, asXtalkGainsAllChan);
+	vortex_XtalkHw_SetGainsAllChan(v);
 	switch (v->xt_mode) {
 	case XT_SPEAKER0:
 		vortex_XtalkHw_ProgramXtalkNarrow(v);
@@ -862,9 +862,8 @@
 	/* HRTF controls. */
 	for (i = 0; i < NR_A3D; i++) {
 		if ((kcontrol =
-		     snd_ctl_new1(&vortex_a3d_kcontrol, vortex)) == NULL)
+		     snd_ctl_new1(&vortex_a3d_kcontrol, &vortex->a3d[i])) == NULL)
 			return -ENOMEM;
-		kcontrol->private_data = &vortex->a3d[i];
 		kcontrol->id.numid = CTRLID_HRTF;
 		kcontrol->info = snd_vortex_a3d_hrtf_info;
 		kcontrol->put = snd_vortex_a3d_hrtf_put;
@@ -874,9 +873,8 @@
 	/* ITD controls. */
 	for (i = 0; i < NR_A3D; i++) {
 		if ((kcontrol =
-		     snd_ctl_new1(&vortex_a3d_kcontrol, vortex)) == NULL)
+		     snd_ctl_new1(&vortex_a3d_kcontrol, &vortex->a3d[i])) == NULL)
 			return -ENOMEM;
-		kcontrol->private_data = &vortex->a3d[i];
 		kcontrol->id.numid = CTRLID_ITD;
 		kcontrol->info = snd_vortex_a3d_itd_info;
 		kcontrol->put = snd_vortex_a3d_itd_put;
@@ -886,9 +884,8 @@
 	/* ILD (gains) controls. */
 	for (i = 0; i < NR_A3D; i++) {
 		if ((kcontrol =
-		     snd_ctl_new1(&vortex_a3d_kcontrol, vortex)) == NULL)
+		     snd_ctl_new1(&vortex_a3d_kcontrol, &vortex->a3d[i])) == NULL)
 			return -ENOMEM;
-		kcontrol->private_data = &vortex->a3d[i];
 		kcontrol->id.numid = CTRLID_GAINS;
 		kcontrol->info = snd_vortex_a3d_ild_info;
 		kcontrol->put = snd_vortex_a3d_ild_put;
@@ -898,9 +895,8 @@
 	/* Filter controls. */
 	for (i = 0; i < NR_A3D; i++) {
 		if ((kcontrol =
-		     snd_ctl_new1(&vortex_a3d_kcontrol, vortex)) == NULL)
+		     snd_ctl_new1(&vortex_a3d_kcontrol, &vortex->a3d[i])) == NULL)
 			return -ENOMEM;
-		kcontrol->private_data = &vortex->a3d[i];
 		kcontrol->id.numid = CTRLID_FILTER;
 		kcontrol->info = snd_vortex_a3d_filter_info;
 		kcontrol->put = snd_vortex_a3d_filter_put;
diff -Nru a/sound/pci/au88x0/au88x0_core.c b/sound/pci/au88x0/au88x0_core.c
--- a/sound/pci/au88x0/au88x0_core.c	2004-10-18 14:57:03 -07:00
+++ b/sound/pci/au88x0/au88x0_core.c	2004-10-18 14:57:03 -07:00
@@ -2362,7 +2362,7 @@
 
 static irqreturn_t vortex_interrupt(int irq, void *dev_id, struct pt_regs *regs)
 {
-	vortex_t *vortex = snd_magic_cast(vortex_t, dev_id, return IRQ_NONE);
+	vortex_t *vortex = dev_id;
 	int i, handled;
 	u32 source;
 
diff -Nru a/sound/pci/au88x0/au88x0_eq.c b/sound/pci/au88x0/au88x0_eq.c
--- a/sound/pci/au88x0/au88x0_eq.c	2004-10-18 14:57:03 -07:00
+++ b/sound/pci/au88x0/au88x0_eq.c	2004-10-18 14:57:03 -07:00
@@ -40,135 +40,120 @@
 #include "au88x0_eq.h"
 #include "au88x0_eqdata.c"
 
+#define VORTEX_EQ_BASE	 0x2b000
+#define VORTEX_EQ_DEST   (VORTEX_EQ_BASE + 0x410)
+#define VORTEX_EQ_SOURCE (VORTEX_EQ_BASE + 0x430)
+#define VORTEX_EQ_CTRL   (VORTEX_EQ_BASE + 0x440)
+
 /* CEqHw.s */
-static void vortex_EqHw_SetTimeConsts(vortex_t * vortex, u16 a, u16 b)
+static void vortex_EqHw_SetTimeConsts(vortex_t * vortex, u16 gain, u16 level)
 {
-	hwwrite(vortex->mmio, 0x2b3c4, a);
-	hwwrite(vortex->mmio, 0x2b3c8, b);
+	hwwrite(vortex->mmio, 0x2b3c4, gain);
+	hwwrite(vortex->mmio, 0x2b3c8, level);
 }
 
-static void vortex_EqHw_SetLeftCoefs(vortex_t * vortex, u16 a[])
+static void vortex_EqHw_SetLeftCoefs(vortex_t * vortex, u16 coefs[])
 {
 	eqhw_t *eqhw = &(vortex->eq.this04);
-	int eax, i = 0, n /*esp2c */  = 0;
-
-	if (eqhw->this04 <= n)
-		return;
+	int eax, i = 0, n /*esp2c */;
 
-	do {
-		hwwrite(vortex->mmio, 0x2b000 + n * 0x30, a[i + 0]);
-		hwwrite(vortex->mmio, 0x2b004 + n * 0x30, a[i + 1]);
+	for (n = 0; n < eqhw->this04; n++) {
+		hwwrite(vortex->mmio, 0x2b000 + n * 0x30, coefs[i + 0]);
+		hwwrite(vortex->mmio, 0x2b004 + n * 0x30, coefs[i + 1]);
 
 		if (eqhw->this08 == 0) {
-			hwwrite(vortex->mmio, 0x2b008 + n * 0x30, a[i + 2]);
-			hwwrite(vortex->mmio, 0x2b00c + n * 0x30, a[i + 3]);
-			eax = a[i + 4];	//esp24;
+			hwwrite(vortex->mmio, 0x2b008 + n * 0x30, coefs[i + 2]);
+			hwwrite(vortex->mmio, 0x2b00c + n * 0x30, coefs[i + 3]);
+			eax = coefs[i + 4];	//esp24;
 		} else {
-			if (a[2 + i] == 0x8000)
+			if (coefs[2 + i] == 0x8000)
 				eax = 0x7fff;
 			else
-				eax = ~a[2 + i];
+				eax = ~coefs[2 + i];
 			hwwrite(vortex->mmio, 0x2b008 + n * 0x30, eax & 0xffff);
-			if (a[3 + i] == 0x8000)
+			if (coefs[3 + i] == 0x8000)
 				eax = 0x7fff;
 			else
-				eax = ~a[3 + i];
+				eax = ~coefs[3 + i];
 			hwwrite(vortex->mmio, 0x2b00c + n * 0x30, eax & 0xffff);
-			if (a[4 + i] == 0x8000)
+			if (coefs[4 + i] == 0x8000)
 				eax = 0x7fff;
 			else
-				eax = ~a[4 + i];
+				eax = ~coefs[4 + i];
 		}
 		hwwrite(vortex->mmio, 0x2b010 + n * 0x30, eax);
 
-		n++;
 		i += 5;
 	}
-	while (n < eqhw->this04);
 }
 
-static void vortex_EqHw_SetRightCoefs(vortex_t * vortex, u16 a[])
+static void vortex_EqHw_SetRightCoefs(vortex_t * vortex, u16 coefs[])
 {
 	eqhw_t *eqhw = &(vortex->eq.this04);
-	int i = 0, n /*esp2c */  = 0, eax;
+	int i = 0, n /*esp2c */, eax;
 
-	if (eqhw->this04 <= n)
-		return;
-
-	do {
-		hwwrite(vortex->mmio, 0x2b1e0 + n * 0x30, a[0 + i]);
-		hwwrite(vortex->mmio, 0x2b1e4 + n * 0x30, a[1 + i]);
+	for (n = 0; n < eqhw->this04; n++) {
+		hwwrite(vortex->mmio, 0x2b1e0 + n * 0x30, coefs[0 + i]);
+		hwwrite(vortex->mmio, 0x2b1e4 + n * 0x30, coefs[1 + i]);
 
 		if (eqhw->this08 == 0) {
-			hwwrite(vortex->mmio, 0x2b1e8 + n * 0x30, a[2 + i]);
-			hwwrite(vortex->mmio, 0x2b1ec + n * 0x30, a[3 + i]);
-			eax = a[4 + i];	//*esp24;
+			hwwrite(vortex->mmio, 0x2b1e8 + n * 0x30, coefs[2 + i]);
+			hwwrite(vortex->mmio, 0x2b1ec + n * 0x30, coefs[3 + i]);
+			eax = coefs[4 + i];	//*esp24;
 		} else {
-			if (a[2 + i] == 0x8000)
+			if (coefs[2 + i] == 0x8000)
 				eax = 0x7fff;
 			else
-				eax = ~(a[2 + i]);
+				eax = ~(coefs[2 + i]);
 			hwwrite(vortex->mmio, 0x2b1e8 + n * 0x30, eax & 0xffff);
-			if (a[3 + i] == 0x8000)
+			if (coefs[3 + i] == 0x8000)
 				eax = 0x7fff;
 			else
-				eax = ~a[3 + i];
+				eax = ~coefs[3 + i];
 			hwwrite(vortex->mmio, 0x2b1ec + n * 0x30, eax & 0xffff);
-			if (a[4 + i] == 0x8000)
+			if (coefs[4 + i] == 0x8000)
 				eax = 0x7fff;
 			else
-				eax = ~a[4 + i];
+				eax = ~coefs[4 + i];
 		}
 		hwwrite(vortex->mmio, 0x2b1f0 + n * 0x30, eax);
 		i += 5;
-		n++;
 	}
-	while (n < eqhw->this04);
 
 }
 
 static void vortex_EqHw_SetLeftStates(vortex_t * vortex, u16 a[], u16 b[])
 {
 	eqhw_t *eqhw = &(vortex->eq.this04);
-	int i = 0, ebx = 0;
+	int i = 0, ebx;
 
 	hwwrite(vortex->mmio, 0x2b3fc, a[0]);
 	hwwrite(vortex->mmio, 0x2b400, a[1]);
 
-	if (eqhw->this04 < 0)
-		return;
-
-	do {
+	for (ebx = 0; ebx < eqhw->this04; ebx++) {
 		hwwrite(vortex->mmio, 0x2b014 + (i * 0xc), b[i]);
 		hwwrite(vortex->mmio, 0x2b018 + (i * 0xc), b[1 + i]);
 		hwwrite(vortex->mmio, 0x2b01c + (i * 0xc), b[2 + i]);
 		hwwrite(vortex->mmio, 0x2b020 + (i * 0xc), b[3 + i]);
 		i += 4;
-		ebx++;
 	}
-	while (eqhw->this04 > ebx);
 }
 
 static void vortex_EqHw_SetRightStates(vortex_t * vortex, u16 a[], u16 b[])
 {
 	eqhw_t *eqhw = &(vortex->eq.this04);
-	int i = 0, ebx = 0;
+	int i = 0, ebx;
 
 	hwwrite(vortex->mmio, 0x2b404, a[0]);
 	hwwrite(vortex->mmio, 0x2b408, a[1]);
 
-	if (eqhw->this04 < 0)
-		return;
-
-	do {
+	for (ebx = 0; ebx < eqhw->this04; ebx++) {
 		hwwrite(vortex->mmio, 0x2b1f4 + (i * 0xc), b[i]);
 		hwwrite(vortex->mmio, 0x2b1f8 + (i * 0xc), b[1 + i]);
 		hwwrite(vortex->mmio, 0x2b1fc + (i * 0xc), b[2 + i]);
 		hwwrite(vortex->mmio, 0x2b200 + (i * 0xc), b[3 + i]);
 		i += 4;
-		ebx++;
 	}
-	while (ebx < eqhw->this04);
 }
 
 #if 0
@@ -260,60 +245,41 @@
 static void vortex_EqHw_SetLeftGainsTarget(vortex_t * vortex, u16 a[])
 {
 	eqhw_t *eqhw = &(vortex->eq.this04);
-	int ebx = 0;
+	int ebx;
 
-	if (eqhw->this04 < 0)
-		return;
-	do {
+	for (ebx = 0; ebx < eqhw->this04; ebx++) {
 		hwwrite(vortex->mmio, 0x2b02c + ebx * 0x30, a[ebx]);
-		ebx++;
 	}
-	while (ebx < eqhw->this04);
 }
 
 static void vortex_EqHw_SetRightGainsTarget(vortex_t * vortex, u16 a[])
 {
 	eqhw_t *eqhw = &(vortex->eq.this04);
-	int ebx = 0;
-
-	if (eqhw->this04 < 0)
-		return;
+	int ebx;
 
-	do {
+	for (ebx = 0; ebx < eqhw->this04; ebx++) {
 		hwwrite(vortex->mmio, 0x2b20c + ebx * 0x30, a[ebx]);
-		ebx++;
 	}
-	while (ebx < eqhw->this04);
 }
 
 static void vortex_EqHw_SetLeftGainsCurrent(vortex_t * vortex, u16 a[])
 {
 	eqhw_t *eqhw = &(vortex->eq.this04);
-	int ebx = 0;
-
-	if (eqhw->this04 < 0)
-		return;
+	int ebx;
 
-	do {
+	for (ebx = 0; ebx < eqhw->this04; ebx++) {
 		hwwrite(vortex->mmio, 0x2b028 + ebx * 0x30, a[ebx]);
-		ebx++;
 	}
-	while (ebx < eqhw->this04);
 }
 
 static void vortex_EqHw_SetRightGainsCurrent(vortex_t * vortex, u16 a[])
 {
 	eqhw_t *eqhw = &(vortex->eq.this04);
-	int ebx = 0;
-
-	if (eqhw->this04 < 0)
-		return;
+	int ebx;
 
-	do {
+	for (ebx = 0; ebx < eqhw->this04; ebx++) {
 		hwwrite(vortex->mmio, 0x2b208 + ebx * 0x30, a[ebx]);
-		ebx++;
 	}
-	while (ebx < eqhw->this04);
 }
 
 #if 0
@@ -384,26 +350,17 @@
 	eqhw_t *eqhw = &(vortex->eq.this04);
 	int ebx;
 
-	if (eqhw->this04 < 0)
-		return;
-
-	ebx = 0;
-	do {
+	for (ebx = 0; ebx < eqhw->this04; ebx++) {
 		hwwrite(vortex->mmio, 0x2b024 + ebx * 0x30, a[ebx]);
-		ebx++;
 	}
-	while (ebx < eqhw->this04);
 
 	hwwrite(vortex->mmio, 0x2b3cc, a[eqhw->this04]);
 	hwwrite(vortex->mmio, 0x2b3d8, a[eqhw->this04 + 1]);
 
-	ebx = 0;
-	do {
+	for (ebx = 0; ebx < eqhw->this04; ebx++) {
 		hwwrite(vortex->mmio, 0x2b204 + ebx * 0x30,
 			a[ebx + (eqhw->this04 + 2)]);
-		ebx++;
 	}
-	while (ebx < eqhw->this04);
 
 	hwwrite(vortex->mmio, 0x2b3e4, a[2 + (eqhw->this04 * 2)]);
 	hwwrite(vortex->mmio, 0x2b3f0, a[3 + (eqhw->this04 * 2)]);
@@ -466,12 +423,12 @@
 #endif
 static void vortex_EqHw_Enable(vortex_t * vortex)
 {
-	hwwrite(vortex->mmio, 0x2b440, 0xf001);
+	hwwrite(vortex->mmio, VORTEX_EQ_CTRL, 0xf001);
 }
 
 static void vortex_EqHw_Disable(vortex_t * vortex)
 {
-	hwwrite(vortex->mmio, 0x2b440, 0xf000);
+	hwwrite(vortex->mmio, VORTEX_EQ_CTRL, 0xf000);
 }
 
 /* Reset (zero) buffers */
@@ -479,16 +436,16 @@
 {
 	int i;
 	for (i = 0; i < 0x8; i++)
-		hwwrite(vortex->mmio, 0x2b410 + (i << 2), 0x0);
+		hwwrite(vortex->mmio, VORTEX_EQ_DEST + (i << 2), 0x0);
 	for (i = 0; i < 0x4; i++)
-		hwwrite(vortex->mmio, 0x2b430 + (i << 2), 0x0);
+		hwwrite(vortex->mmio, VORTEX_EQ_SOURCE + (i << 2), 0x0);
 }
 
 static void vortex_EqHw_ZeroA3DIO(vortex_t * vortex)
 {
 	int i;
 	for (i = 0; i < 0x4; i++)
-		hwwrite(vortex->mmio, 0x2b410 + (i << 2), 0x0);
+		hwwrite(vortex->mmio, VORTEX_EQ_DEST + (i << 2), 0x0);
 }
 
 static void vortex_EqHw_ZeroState(vortex_t * vortex)
@@ -659,11 +616,10 @@
 	if (((eq->this10) * 2 != count) || (eq->this28 == 0))
 		return 1;
 
-	if (0 < count) {
-		for (i = 0; i < count; i++) {
-			eq->this130[i] = gains[i];
-		}
+	for (i = 0; i < count; i++) {
+		eq->this130[i] = gains[i];
 	}
+	
 	if (eq->this54)
 		return 0;
 	return vortex_Eqlzr_SetAllBandsFromActiveCoeffSet(vortex);
diff -Nru a/sound/pci/au88x0/au88x0_game.c b/sound/pci/au88x0/au88x0_game.c
--- a/sound/pci/au88x0/au88x0_game.c	2004-10-18 14:55:55 -07:00
+++ b/sound/pci/au88x0/au88x0_game.c	2004-10-18 14:55:55 -07:00
@@ -96,7 +96,7 @@
 
 static int vortex_gameport_register(vortex_t * vortex)
 {
-	if ((vortex->gameport = snd_kcalloc(sizeof(struct gameport), GFP_KERNEL)) == NULL) {
+	if ((vortex->gameport = kcalloc(1, sizeof(struct gameport), GFP_KERNEL)) == NULL) {
 		return -1;
 	};
 	
diff -Nru a/sound/pci/au88x0/au88x0_mixer.c b/sound/pci/au88x0/au88x0_mixer.c
--- a/sound/pci/au88x0/au88x0_mixer.c	2004-10-18 14:56:17 -07:00
+++ b/sound/pci/au88x0/au88x0_mixer.c	2004-10-18 14:56:17 -07:00
@@ -13,14 +13,15 @@
 
 static int __devinit snd_vortex_mixer(vortex_t * vortex)
 {
-	ac97_bus_t bus, *pbus;
-	ac97_t ac97;
+	ac97_bus_t *pbus;
+	ac97_template_t ac97;
 	int err;
+	static ac97_bus_ops_t ops = {
+		.write = vortex_codec_write,
+		.read = vortex_codec_read,
+	};
 
-	memset(&bus, 0, sizeof(bus));
-	bus.write = vortex_codec_write;
-	bus.read = vortex_codec_read;
-	if ((err = snd_ac97_bus(vortex->card, &bus, &pbus)) < 0)
+	if ((err = snd_ac97_bus(vortex->card, 0, &ops, NULL, &pbus)) < 0)
 		return err;
 	memset(&ac97, 0, sizeof(ac97));
 	// Intialize AC97 codec stuff.
diff -Nru a/sound/pci/au88x0/au88x0_mpu401.c b/sound/pci/au88x0/au88x0_mpu401.c
--- a/sound/pci/au88x0/au88x0_mpu401.c	2004-10-18 14:56:48 -07:00
+++ b/sound/pci/au88x0/au88x0_mpu401.c	2004-10-18 14:56:48 -07:00
@@ -104,7 +104,7 @@
 			 ~CTRL_MIDI_PORT) & ~CTRL_MIDI_EN);
 		return temp;
 	}
-	mpu = snd_magic_cast(mpu401_t, rmidi->private_data, return -ENOMEM);
+	mpu = rmidi->private_data;
 	mpu->cport = (unsigned long)(vortex->mmio + (VORTEX_MIDI_CMD >> 2));
 #endif
 	vortex->rmidi = rmidi;
diff -Nru a/sound/pci/au88x0/au88x0_pcm.c b/sound/pci/au88x0/au88x0_pcm.c
--- a/sound/pci/au88x0/au88x0_pcm.c	2004-10-18 14:56:31 -07:00
+++ b/sound/pci/au88x0/au88x0_pcm.c	2004-10-18 14:56:31 -07:00
@@ -28,7 +28,6 @@
 #include <sound/pcm_params.h>
 #include "au88x0.h"
 
-#define chip_t vortex_t
 #define VORTEX_PCM_TYPE(x) (x->name[40])
 
 /* hardware definition */
@@ -189,7 +188,7 @@
 snd_vortex_pcm_hw_params(snd_pcm_substream_t * substream,
 			 snd_pcm_hw_params_t * hw_params)
 {
-	chip_t *chip = snd_pcm_substream_chip(substream);
+	vortex_t *chip = snd_pcm_substream_chip(substream);
 	stream_t *stream = (stream_t *) (substream->runtime->private_data);
 	snd_pcm_sgbuf_t *sgbuf;
 	int err;
@@ -250,7 +249,7 @@
 /* hw_free callback */
 static int snd_vortex_pcm_hw_free(snd_pcm_substream_t * substream)
 {
-	chip_t *chip = snd_pcm_substream_chip(substream);
+	vortex_t *chip = snd_pcm_substream_chip(substream);
 	stream_t *stream = (stream_t *) (substream->runtime->private_data);
 
 	// Delete audio routes.
@@ -305,7 +304,7 @@
 /* trigger callback */
 static int snd_vortex_pcm_trigger(snd_pcm_substream_t * substream, int cmd)
 {
-	chip_t *chip = snd_pcm_substream_chip(substream);
+	vortex_t *chip = snd_pcm_substream_chip(substream);
 	stream_t *stream = (stream_t *) substream->runtime->private_data;
 	int dma = stream->dma;
 
diff -Nru a/sound/pci/au88x0/au88x0_xtalk.c b/sound/pci/au88x0/au88x0_xtalk.c
--- a/sound/pci/au88x0/au88x0_xtalk.c	2004-10-18 14:57:20 -07:00
+++ b/sound/pci/au88x0/au88x0_xtalk.c	2004-10-18 14:57:20 -07:00
@@ -540,6 +540,12 @@
 	}
 }
 
+static void
+vortex_XtalkHw_SetGainsAllChan(vortex_t * vortex)
+{
+	vortex_XtalkHw_SetGains(vortex, asXtalkGainsAllChan);
+}
+
 #if 0
 static void vortex_XtalkHw_GetGains(vortex_t * vortex, xtalk_gains_t gains)
 {
diff -Nru a/sound/pci/au88x0/au88x0_xtalk.h b/sound/pci/au88x0/au88x0_xtalk.h
--- a/sound/pci/au88x0/au88x0_xtalk.h	2004-10-18 14:56:28 -07:00
+++ b/sound/pci/au88x0/au88x0_xtalk.h	2004-10-18 14:56:28 -07:00
@@ -45,10 +45,9 @@
 typedef short xtalk_coefs_t[5][5];
 typedef short xtalk_state_t[5][4];
 
-extern xtalk_gains_t const asXtalkGainsAllChan;
-
 static void vortex_XtalkHw_SetGains(vortex_t * vortex,
 				    xtalk_gains_t const gains);
+static void vortex_XtalkHw_SetGainsAllChan(vortex_t * vortex);
 static void vortex_XtalkHw_SetSampleRate(vortex_t * vortex, int sr);
 static void vortex_XtalkHw_ProgramPipe(vortex_t * vortex);
 static void vortex_XtalkHw_ProgramPipe(vortex_t * vortex);
diff -Nru a/sound/pci/azt3328.c b/sound/pci/azt3328.c
--- a/sound/pci/azt3328.c	2004-10-18 14:56:33 -07:00
+++ b/sound/pci/azt3328.c	2004-10-18 14:56:33 -07:00
@@ -111,8 +111,7 @@
 MODULE_AUTHOR("Andreas Mohr <hw7oshyuv3001@sneakemail.com>");
 MODULE_DESCRIPTION("Aztech AZF3328 (PCI168)");
 MODULE_LICENSE("GPL");
-MODULE_CLASSES("{sound}");
-MODULE_DEVICES("{{Aztech,AZF3328}}");
+MODULE_SUPPORTED_DEVICE("{{Aztech,AZF3328}}");
 
 #if defined(CONFIG_GAMEPORT) || (defined(MODULE) && defined(CONFIG_GAMEPORT_MODULE))
 #define SUPPORT_JOYSTICK 1
@@ -170,35 +169,25 @@
 
 module_param_array(index, int, boot_devs, 0444);
 MODULE_PARM_DESC(index, "Index value for AZF3328 soundcard.");
-MODULE_PARM_SYNTAX(index, SNDRV_INDEX_DESC);
 module_param_array(id, charp, boot_devs, 0444);
 MODULE_PARM_DESC(id, "ID string for AZF3328 soundcard.");
-MODULE_PARM_SYNTAX(id, SNDRV_ID_DESC);
 module_param_array(enable, bool, boot_devs, 0444);
 MODULE_PARM_DESC(enable, "Enable AZF3328 soundcard.");
-MODULE_PARM_SYNTAX(enable, SNDRV_INDEX_DESC);
 #ifdef SUPPORT_JOYSTICK
 module_param_array(joystick, bool, boot_devs, 0444);
 MODULE_PARM_DESC(joystick, "Enable joystick for AZF3328 soundcard.");
-MODULE_PARM_SYNTAX(joystick, SNDRV_BOOLEAN_FALSE_DESC);
 #endif
 
 typedef struct _snd_azf3328 azf3328_t;
-#define chip_t azf3328_t
 
 struct _snd_azf3328 {
 	int irq;
 
 	unsigned long codec_port;
-	struct resource *res_codec_port;
 	unsigned long io2_port;
-	struct resource *res_io2_port;
 	unsigned long mpu_port;
-	struct resource *res_mpu_port;
 	unsigned long synth_port;
-	struct resource *res_synth_port;
 	unsigned long mixer_port;
-	struct resource *res_mixer_port;
 
 #ifdef SUPPORT_JOYSTICK
 	struct gameport gameport;
@@ -553,8 +542,6 @@
 	return (nreg != oreg);
 }
 
-#define NUM_CONTROLS(ary) (sizeof(ary) / sizeof(snd_kcontrol_new_t))
-
 static snd_kcontrol_new_t snd_azf3328_mixer_controls[] __devinitdata = {
 	AZF3328_MIXER_SWITCH("Master Playback Switch", IDX_MIXER_PLAY_MASTER, 15, 1),
 	AZF3328_MIXER_VOL_STEREO("Master Playback Volume", IDX_MIXER_PLAY_MASTER, 0x1f, 1),
@@ -650,7 +637,7 @@
 	
 	/* add mixer controls */
 	sw = snd_azf3328_mixer_controls;
-	for (idx = 0; idx < NUM_CONTROLS(snd_azf3328_mixer_controls); idx++, sw++) {
+	for (idx = 0; idx < ARRAY_SIZE(snd_azf3328_mixer_controls); idx++, sw++) {
 		if ((err = snd_ctl_add(chip->card, snd_ctl_new1(sw, chip))) < 0)
 			return err;
 	}
@@ -813,7 +800,6 @@
 
 static int snd_azf3328_playback_trigger(snd_pcm_substream_t * substream, int cmd)
 {
-	unsigned long flags;
 	azf3328_t *chip = snd_pcm_substream_chip(substream);
 	snd_pcm_runtime_t *runtime = substream->runtime;
 	int result = 0;
@@ -830,7 +816,7 @@
 
 		snd_azf3328_setfmt(chip, IDX_IO_PLAY_SOUNDFORMAT, runtime->rate, snd_pcm_format_width(runtime->format), runtime->channels);
 
-		spin_lock_irqsave(&chip->reg_lock, flags);
+		spin_lock(&chip->reg_lock);
 		/* stop playback */
 		status1 = inw(chip->codec_port+IDX_IO_PLAY_FLAGS);
 		status1 &= ~DMA_RESUME;
@@ -838,11 +824,11 @@
 	    
 		/* FIXME: clear interrupts or what??? */
 		outw(0xffff, chip->codec_port+IDX_IO_PLAY_IRQMASK);
-		spin_unlock_irqrestore(&chip->reg_lock, flags);
+		spin_unlock(&chip->reg_lock);
 
 		snd_azf3328_setdmaa(chip, runtime->dma_addr, snd_pcm_lib_period_bytes(substream), snd_pcm_lib_buffer_bytes(substream), 0);
 
-		spin_lock_irqsave(&chip->reg_lock, flags);
+		spin_lock(&chip->reg_lock);
 #ifdef WIN9X
 		/* FIXME: enable playback/recording??? */
 		status1 |= DMA_PLAY_SOMETHING1 | DMA_PLAY_SOMETHING2;
@@ -858,7 +844,7 @@
 		outw(DMA_PLAY_SOMETHING1|DMA_PLAY_SOMETHING2, chip->codec_port+IDX_IO_PLAY_FLAGS);
 		outw(DMA_RESUME|SOMETHING_ALMOST_ALWAYS_SET|DMA_EPILOGUE_SOMETHING|DMA_SOMETHING_ELSE, chip->codec_port+IDX_IO_PLAY_FLAGS);
 #endif
-		spin_unlock_irqrestore(&chip->reg_lock, flags);
+		spin_unlock(&chip->reg_lock);
 
 		/* now unmute WaveOut */
 		snd_azf3328_mixer_set_mute(chip, IDX_MIXER_WAVEOUT, 0);
@@ -870,7 +856,7 @@
 		/* mute WaveOut */
 		snd_azf3328_mixer_set_mute(chip, IDX_MIXER_WAVEOUT, 1);
 
-		spin_lock_irqsave(&chip->reg_lock, flags);
+		spin_lock(&chip->reg_lock);
 		/* stop playback */
 		status1 = inw(chip->codec_port+IDX_IO_PLAY_FLAGS);
 
@@ -882,7 +868,7 @@
 
 		status1 &= ~DMA_PLAY_SOMETHING1;
 		outw(status1, chip->codec_port+IDX_IO_PLAY_FLAGS);
-		spin_unlock_irqrestore(&chip->reg_lock, flags);
+		spin_unlock(&chip->reg_lock);
 	    
 		/* now unmute WaveOut */
 		snd_azf3328_mixer_set_mute(chip, IDX_MIXER_WAVEOUT, 0);
@@ -906,7 +892,6 @@
  * should actually be triggered like that */
 static int snd_azf3328_capture_trigger(snd_pcm_substream_t * substream, int cmd)
 {
-	unsigned long flags;
 	azf3328_t *chip = snd_pcm_substream_chip(substream);
 	snd_pcm_runtime_t *runtime = substream->runtime;
 	int result = 0;
@@ -920,7 +905,7 @@
 
 		snd_azf3328_setfmt(chip, IDX_IO_REC_SOUNDFORMAT, runtime->rate, snd_pcm_format_width(runtime->format), runtime->channels);
 
-		spin_lock_irqsave(&chip->reg_lock, flags);
+		spin_lock(&chip->reg_lock);
 		/* stop recording */
 		status1 = inw(chip->codec_port+IDX_IO_REC_FLAGS);
 		status1 &= ~DMA_RESUME;
@@ -928,11 +913,11 @@
 	    
 		/* FIXME: clear interrupts or what??? */
 		outw(0xffff, chip->codec_port+IDX_IO_REC_IRQMASK);
-		spin_unlock_irqrestore(&chip->reg_lock, flags);
+		spin_unlock(&chip->reg_lock);
 
 		snd_azf3328_setdmaa(chip, runtime->dma_addr, snd_pcm_lib_period_bytes(substream), snd_pcm_lib_buffer_bytes(substream), 1);
 
-		spin_lock_irqsave(&chip->reg_lock, flags);
+		spin_lock(&chip->reg_lock);
 #ifdef WIN9X
 		/* FIXME: enable playback/recording??? */
 		status1 |= DMA_PLAY_SOMETHING1 | DMA_PLAY_SOMETHING2;
@@ -948,13 +933,13 @@
 		outw(DMA_PLAY_SOMETHING1|DMA_PLAY_SOMETHING2, chip->codec_port+IDX_IO_REC_FLAGS);
 		outw(DMA_RESUME|SOMETHING_ALMOST_ALWAYS_SET|DMA_EPILOGUE_SOMETHING|DMA_SOMETHING_ELSE, chip->codec_port+IDX_IO_REC_FLAGS);
 #endif
-		spin_unlock_irqrestore(&chip->reg_lock, flags);
+		spin_unlock(&chip->reg_lock);
 
 		snd_azf3328_dbgio(chip, "trigger2");
 		chip->is_playing = 1;
 		break;
         case SNDRV_PCM_TRIGGER_STOP:
-		spin_lock_irqsave(&chip->reg_lock, flags);
+		spin_lock(&chip->reg_lock);
 		/* stop recording */
 		status1 = inw(chip->codec_port+IDX_IO_REC_FLAGS);
 
@@ -966,7 +951,7 @@
 
 		status1 &= ~DMA_PLAY_SOMETHING1;
 		outw(status1, chip->codec_port+IDX_IO_REC_FLAGS);
-		spin_unlock_irqrestore(&chip->reg_lock, flags);
+		spin_unlock(&chip->reg_lock);
 	    
 		chip->is_playing = 0;
 		break;
@@ -990,16 +975,13 @@
 	unsigned long bufptr, playptr;
 	unsigned long result;
 	snd_pcm_uframes_t frmres;
-	unsigned long flags;
 
-	spin_lock_irqsave(&chip->reg_lock, flags);
 #ifdef QUERY_HARDWARE
 	bufptr = inl(chip->codec_port+IDX_IO_PLAY_DMA_START_1);
 #else
 	bufptr = substream->runtime->dma_addr;
 #endif
 	playptr = inl(chip->codec_port+IDX_IO_PLAY_DMA_CURRPOS);
-	spin_unlock_irqrestore(&chip->reg_lock, flags);
 
 	result = playptr - bufptr;
 	frmres = bytes_to_frames( substream->runtime, result );
@@ -1013,16 +995,13 @@
 	unsigned long bufptr, recptr;
 	unsigned long result;
 	snd_pcm_uframes_t frmres;
-	unsigned long flags;
 
-	spin_lock_irqsave(&chip->reg_lock, flags);
 #ifdef QUERY_HARDWARE
 	bufptr = inl(chip->codec_port+IDX_IO_REC_DMA_START_1);
 #else
 	bufptr = substream->runtime->dma_addr;
 #endif
 	recptr = inl(chip->codec_port+IDX_IO_REC_DMA_CURRPOS);
-	spin_unlock_irqrestore(&chip->reg_lock, flags);
 
 	result = recptr - bufptr;
 	frmres = bytes_to_frames( substream->runtime, result );
@@ -1032,7 +1011,7 @@
 
 static irqreturn_t snd_azf3328_interrupt(int irq, void *dev_id, struct pt_regs *regs)
 {
-	azf3328_t *chip = snd_magic_cast(azf3328_t, dev_id, return IRQ_NONE);
+	azf3328_t *chip = dev_id;
 	unsigned int status, which;
 	static unsigned long count;
 
@@ -1232,7 +1211,7 @@
 
 static void snd_azf3328_pcm_free(snd_pcm_t *pcm)
 {
-	azf3328_t *chip = snd_magic_cast(azf3328_t, pcm->private_data, return);
+	azf3328_t *chip = pcm->private_data;
 	chip->pcm = NULL;
 	snd_pcm_lib_preallocate_free_for_all(pcm);
 }
@@ -1287,36 +1266,17 @@
 		kfree_nocheck(chip->res_joystick);
 	}
 #endif
-        if (chip->res_codec_port) {
-		release_resource(chip->res_codec_port);
-		kfree_nocheck(chip->res_codec_port);
-	}
-        if (chip->res_io2_port) {
-		release_resource(chip->res_io2_port);
-		kfree_nocheck(chip->res_io2_port);
-	}
-        if (chip->res_mpu_port) {
-		release_resource(chip->res_mpu_port);
-		kfree_nocheck(chip->res_mpu_port);
-	}
-        if (chip->res_synth_port) {
-		release_resource(chip->res_synth_port);
-		kfree_nocheck(chip->res_synth_port);
-	}
-        if (chip->res_mixer_port) {
-		release_resource(chip->res_mixer_port);
-		kfree_nocheck(chip->res_mixer_port);
-	}
         if (chip->irq >= 0)
 		free_irq(chip->irq, (void *)chip);
+	pci_release_regions(chip->pci);
 
-        snd_magic_kfree(chip);
+        kfree(chip);
         return 0;
 }
 
 static int snd_azf3328_dev_free(snd_device_t *device)
 {
-	azf3328_t *chip = snd_magic_cast(azf3328_t, device->device_data, return -ENXIO);
+	azf3328_t *chip = device->device_data;
 	return snd_azf3328_free(chip);
 }
 
@@ -1345,7 +1305,6 @@
                                          unsigned long device_type,
                                          azf3328_t ** rchip)
 {
-	unsigned long flags;
 	azf3328_t *chip;
 	int err;
 	static snd_device_ops_t ops = {
@@ -1358,7 +1317,7 @@
 	if ((err = pci_enable_device(pci)) < 0)
 		return err;
 
-	chip = snd_magic_kcalloc(azf3328_t, 0, GFP_KERNEL);
+	chip = kcalloc(1, sizeof(*chip), GFP_KERNEL);
 	if (chip == NULL)
 		return -ENOMEM;
 	spin_lock_init(&chip->reg_lock);
@@ -1373,36 +1332,16 @@
 		return -ENXIO;
 	}
 
-	chip->codec_port = pci_resource_start(pci, 0);
-	if ((chip->res_codec_port = request_region(chip->codec_port, 0x80, "Aztech AZF3328 I/O")) == NULL) {
-		snd_printk("unable to grab I/O port at 0x%lx-0x%lx\n", chip->codec_port, chip->codec_port + 0x80 - 1);
-		snd_azf3328_free(chip);
-		return -EBUSY;
+	if ((err = pci_request_regions(pci, "Aztech AZF3328")) < 0) {
+		kfree(chip);
+		return err;
 	}
+
+	chip->codec_port = pci_resource_start(pci, 0);
 	chip->io2_port = pci_resource_start(pci, 1);
-	if ((chip->res_io2_port = request_region(chip->io2_port, 0x08, "Aztech AZF3328 I/O 2")) == NULL) {
-		snd_printk("unable to grab I/O 2 port at 0x%lx-0x%lx\n", chip->io2_port, chip->io2_port + 0x08 - 1);
-		snd_azf3328_free(chip);
-		return -EBUSY;
-	}
 	chip->mpu_port = pci_resource_start(pci, 2);
-	if ((chip->res_mpu_port = request_region(chip->mpu_port, 0x04, "Aztech AZF3328 MPU401")) == NULL) {
-		snd_printk("unable to grab MPU401 port at 0x%lx-0x%lx\n", chip->mpu_port, chip->mpu_port + 0x04 - 1);
-		snd_azf3328_free(chip);
-		return -EBUSY;
-	}
 	chip->synth_port = pci_resource_start(pci, 3);
-	if ((chip->res_synth_port = request_region(chip->synth_port, 0x08, "Aztech AZF3328 OPL3")) == NULL) {
-		snd_printk("unable to grab OPL3 port at 0x%lx-0x%lx\n", chip->synth_port, chip->synth_port + 0x08 - 1);
-		snd_azf3328_free(chip);
-		return -EBUSY;
-	}
 	chip->mixer_port = pci_resource_start(pci, 4);
-	if ((chip->res_mixer_port = request_region(chip->mixer_port, 0x40, "Aztech AZF3328 Mixer")) == NULL) {
-                snd_printk("unable to grab mixer port at 0x%lx-0x%lx\n", chip->mixer_port, chip->mixer_port + 0x40 - 1);
-		snd_azf3328_free(chip);
-		return -EBUSY;
-	}
 
 	if (request_irq(pci->irq, snd_azf3328_interrupt, SA_INTERRUPT|SA_SHIRQ, card->shortname, (void *)chip)) {
 		snd_printk("unable to grab IRQ %d\n", pci->irq);
@@ -1435,13 +1374,13 @@
 #endif
 
 	/* standard chip init stuff */
-	spin_lock_irqsave(&chip->reg_lock, flags);
+	spin_lock_irq(&chip->reg_lock);
 	outb(DMA_PLAY_SOMETHING2|DMA_EPILOGUE_SOMETHING|DMA_SOMETHING_ELSE, chip->codec_port + IDX_IO_PLAY_FLAGS);
 	outb(DMA_PLAY_SOMETHING2|DMA_EPILOGUE_SOMETHING|DMA_SOMETHING_ELSE, chip->codec_port + IDX_IO_SOMETHING_FLAGS);
 	outb(DMA_PLAY_SOMETHING2|DMA_EPILOGUE_SOMETHING|DMA_SOMETHING_ELSE, chip->codec_port + IDX_IO_REC_FLAGS);
 	outb(0x0, chip->codec_port + IDX_IO_IRQ63H);
 
-	spin_unlock_irqrestore(&chip->reg_lock, flags);
+	spin_unlock_irq(&chip->reg_lock);
 
 	snd_card_set_dev(card, &pci->dev);
 
diff -Nru a/sound/pci/bt87x.c b/sound/pci/bt87x.c
--- a/sound/pci/bt87x.c	2004-10-18 14:56:32 -07:00
+++ b/sound/pci/bt87x.c	2004-10-18 14:56:32 -07:00
@@ -38,8 +38,7 @@
 MODULE_AUTHOR("Clemens Ladisch <clemens@ladisch.de>");
 MODULE_DESCRIPTION("Brooktree Bt87x audio driver");
 MODULE_LICENSE("GPL");
-MODULE_CLASSES("{sound}");
-MODULE_DEVICES("{{Brooktree,Bt878},"
+MODULE_SUPPORTED_DEVICE("{{Brooktree,Bt878},"
 		"{Brooktree,Bt879}}");
 
 static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX;	/* Index 0-MAX */
@@ -50,16 +49,12 @@
 
 module_param_array(index, int, boot_devs, 0444);
 MODULE_PARM_DESC(index, "Index value for Bt87x soundcard");
-MODULE_PARM_SYNTAX(index, SNDRV_INDEX_DESC);
 module_param_array(id, charp, boot_devs, 0444);
 MODULE_PARM_DESC(id, "ID string for Bt87x soundcard");
-MODULE_PARM_SYNTAX(id, SNDRV_ID_DESC);
 module_param_array(enable, bool, boot_devs, 0444);
 MODULE_PARM_DESC(enable, "Enable Bt87x soundcard");
-MODULE_PARM_SYNTAX(enable, SNDRV_ENABLE_DESC);
 module_param_array(digital_rate, int, boot_devs, 0444);
 MODULE_PARM_DESC(digital_rate, "Digital input rate for Bt87x soundcard");
-MODULE_PARM_SYNTAX(digital_rate, SNDRV_ENABLED);
 
 
 #ifndef PCI_VENDOR_ID_BROOKTREE
@@ -152,14 +147,12 @@
 /* SYNC, one WRITE per line, one extra WRITE per page boundary, SYNC, JUMP */
 #define MAX_RISC_SIZE ((1 + 255 + (PAGE_ALIGN(255 * 4092) / PAGE_SIZE - 1) + 1 + 1) * 8)
 
-#define chip_t bt87x_t
 typedef struct snd_bt87x bt87x_t;
 struct snd_bt87x {
 	snd_card_t *card;
 	struct pci_dev *pci;
 
 	void *mmio;
-	struct resource *res_mmio;
 	int irq;
 
 	int dig_rate;
@@ -168,7 +161,6 @@
 	long opened;
 	snd_pcm_substream_t *substream;
 
-	struct snd_dma_device dma_dev;
 	struct snd_dma_buffer dma_risc;
 	unsigned int line_bytes;
 	unsigned int lines;
@@ -197,10 +189,8 @@
 	u32 *risc;
 
 	if (chip->dma_risc.area == NULL) {
-		memset(&chip->dma_dev, 0, sizeof(chip->dma_dev));
-		chip->dma_dev.type = SNDRV_DMA_TYPE_DEV;
-		chip->dma_dev.dev = snd_dma_pci_data(chip->pci);
-		if (snd_dma_alloc_pages(&chip->dma_dev, PAGE_ALIGN(MAX_RISC_SIZE), &chip->dma_risc) < 0)
+		if (snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, snd_dma_pci_data(chip->pci),
+					PAGE_ALIGN(MAX_RISC_SIZE), &chip->dma_risc) < 0)
 			return -ENOMEM;
 	}
 	risc = (u32 *)chip->dma_risc.area;
@@ -244,14 +234,14 @@
 static void snd_bt87x_free_risc(bt87x_t *chip)
 {
 	if (chip->dma_risc.area) {
-		snd_dma_free_pages(&chip->dma_dev, &chip->dma_risc);
+		snd_dma_free_pages(&chip->dma_risc);
 		chip->dma_risc.area = NULL;
 	}
 }
 
 static irqreturn_t snd_bt87x_interrupt(int irq, void *dev_id, struct pt_regs *regs)
 {
-	bt87x_t *chip = snd_magic_cast(bt87x_t, dev_id, return IRQ_NONE);
+	bt87x_t *chip = dev_id;
 	unsigned int status;
 
 	status = snd_bt87x_readl(chip, REG_INT_STAT);
@@ -314,7 +304,7 @@
 		SNDRV_PCM_INFO_MMAP_VALID,
 	.formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S8,
 	.rates = SNDRV_PCM_RATE_KNOT,
-	.rate_min = 119467,
+	.rate_min = 119466,
 	.rate_max = 448000,
 	.channels_min = 1,
 	.channels_max = 1,
@@ -356,20 +346,21 @@
 
 static int snd_bt87x_set_analog_hw(bt87x_t *chip, snd_pcm_runtime_t *runtime)
 {
-	static unsigned int rates[] = {
-		119467, 128000, 137846, 149333, 162909, 179200,
-		199111, 224000, 256000, 298667, 358400, 448000
+	static ratnum_t analog_clock = {
+		.num = 1792000,
+		.den_min = 4,
+		.den_max = 15,
+		.den_step = 1
 	};
-	static snd_pcm_hw_constraint_list_t constraint_rates = {
-		.count = ARRAY_SIZE(rates),
-		.list = rates,
-		.mask = 0,
+	static snd_pcm_hw_constraint_ratnums_t constraint_rates = {
+		.nrats = 1,
+		.rats = &analog_clock
 	};
 
 	chip->reg_control &= ~CTL_DA_IOM_DA;
 	runtime->hw = snd_bt87x_analog_hw;
-	return snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_RATE,
-					  &constraint_rates);
+	return snd_pcm_hw_constraint_ratnums(runtime, 0, SNDRV_PCM_HW_PARAM_RATE,
+					     &constraint_rates);
 }
 
 static int snd_bt87x_pcm_open(snd_pcm_substream_t *substream)
@@ -439,25 +430,22 @@
 {
 	bt87x_t *chip = snd_pcm_substream_chip(substream);
 	snd_pcm_runtime_t *runtime = substream->runtime;
-	unsigned long flags;
 	int decimation;
 
-	spin_lock_irqsave(&chip->reg_lock, flags);
+	spin_lock_irq(&chip->reg_lock);
 	chip->reg_control &= ~(CTL_DA_SDR_MASK | CTL_DA_SBR);
-	decimation = (1792000 + 5) / runtime->rate;
+	decimation = (1792000 + runtime->rate / 4) / runtime->rate;
 	chip->reg_control |= decimation << CTL_DA_SDR_SHIFT;
 	if (runtime->format == SNDRV_PCM_FORMAT_S8)
 		chip->reg_control |= CTL_DA_SBR;
 	snd_bt87x_writel(chip, REG_GPIO_DMA_CTL, chip->reg_control);
-	spin_unlock_irqrestore(&chip->reg_lock, flags);
+	spin_unlock_irq(&chip->reg_lock);
 	return 0;
 }
 
 static int snd_bt87x_start(bt87x_t *chip)
 {
-	unsigned long flags;
-
-	spin_lock_irqsave(&chip->reg_lock, flags);
+	spin_lock(&chip->reg_lock);
 	chip->current_line = 0;
 	chip->reg_control |= CTL_FIFO_ENABLE | CTL_RISC_ENABLE | CTL_ACAP_EN;
 	snd_bt87x_writel(chip, REG_RISC_STRT_ADD, chip->dma_risc.addr);
@@ -465,20 +453,18 @@
 			 chip->line_bytes | (chip->lines << 16));
 	snd_bt87x_writel(chip, REG_INT_MASK, MY_INTERRUPTS);
 	snd_bt87x_writel(chip, REG_GPIO_DMA_CTL, chip->reg_control);
-	spin_unlock_irqrestore(&chip->reg_lock, flags);
+	spin_unlock(&chip->reg_lock);
 	return 0;
 }
 
 static int snd_bt87x_stop(bt87x_t *chip)
 {
-	unsigned long flags;
-
-	spin_lock_irqsave(&chip->reg_lock, flags);
+	spin_lock(&chip->reg_lock);
 	chip->reg_control &= ~(CTL_FIFO_ENABLE | CTL_RISC_ENABLE | CTL_ACAP_EN);
 	snd_bt87x_writel(chip, REG_GPIO_DMA_CTL, chip->reg_control);
 	snd_bt87x_writel(chip, REG_INT_MASK, 0);
 	snd_bt87x_writel(chip, REG_INT_STAT, MY_INTERRUPTS);
-	spin_unlock_irqrestore(&chip->reg_lock, flags);
+	spin_unlock(&chip->reg_lock);
 	return 0;
 }
 
@@ -536,17 +522,16 @@
 static int snd_bt87x_capture_volume_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *value)
 {
 	bt87x_t *chip = snd_kcontrol_chip(kcontrol);
-	unsigned long flags;
 	u32 old_control;
 	int changed;
 
-	spin_lock_irqsave(&chip->reg_lock, flags);
+	spin_lock_irq(&chip->reg_lock);
 	old_control = chip->reg_control;
 	chip->reg_control = (chip->reg_control & ~CTL_A_GAIN_MASK)
 		| (value->value.integer.value[0] << CTL_A_GAIN_SHIFT);
 	snd_bt87x_writel(chip, REG_GPIO_DMA_CTL, chip->reg_control);
 	changed = old_control != chip->reg_control;
-	spin_unlock_irqrestore(&chip->reg_lock, flags);
+	spin_unlock_irq(&chip->reg_lock);
 	return changed;
 }
 
@@ -578,17 +563,16 @@
 static int snd_bt87x_capture_boost_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *value)
 {
 	bt87x_t *chip = snd_kcontrol_chip(kcontrol);
-	unsigned long flags;
 	u32 old_control;
 	int changed;
 
-	spin_lock_irqsave(&chip->reg_lock, flags);
+	spin_lock_irq(&chip->reg_lock);
 	old_control = chip->reg_control;
 	chip->reg_control = (chip->reg_control & ~CTL_A_G2X)
 		| (value->value.integer.value[0] ? CTL_A_G2X : 0);
 	snd_bt87x_writel(chip, REG_GPIO_DMA_CTL, chip->reg_control);
 	changed = chip->reg_control != old_control;
-	spin_unlock_irqrestore(&chip->reg_lock, flags);
+	spin_unlock_irq(&chip->reg_lock);
 	return changed;
 }
 
@@ -624,17 +608,16 @@
 static int snd_bt87x_capture_source_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *value)
 {
 	bt87x_t *chip = snd_kcontrol_chip(kcontrol);
-	unsigned long flags;
 	u32 old_control;
 	int changed;
 
-	spin_lock_irqsave(&chip->reg_lock, flags);
+	spin_lock_irq(&chip->reg_lock);
 	old_control = chip->reg_control;
 	chip->reg_control = (chip->reg_control & ~CTL_A_SEL_MASK)
 		| (value->value.enumerated.item[0] << CTL_A_SEL_SHIFT);
 	snd_bt87x_writel(chip, REG_GPIO_DMA_CTL, chip->reg_control);
 	changed = chip->reg_control != old_control;
-	spin_unlock_irqrestore(&chip->reg_lock, flags);
+	spin_unlock_irq(&chip->reg_lock);
 	return changed;
 }
 
@@ -655,19 +638,16 @@
 
 		iounmap(chip->mmio);
 	}
-	if (chip->res_mmio) {
-		release_resource(chip->res_mmio);
-		kfree_nocheck(chip->res_mmio);
-	}
 	if (chip->irq >= 0)
 		free_irq(chip->irq, chip);
-	snd_magic_kfree(chip);
+	pci_release_regions(chip->pci);
+	kfree(chip);
 	return 0;
 }
 
 static int snd_bt87x_dev_free(snd_device_t *device)
 {
-	bt87x_t *chip = snd_magic_cast(bt87x_t, device->device_data, return -ENXIO);
+	bt87x_t *chip = device->device_data;
 	return snd_bt87x_free(chip);
 }
 
@@ -705,7 +685,7 @@
 	if (err < 0)
 		return err;
 
-	chip = snd_magic_kcalloc(bt87x_t, 0, GFP_KERNEL);
+	chip = kcalloc(1, sizeof(*chip), GFP_KERNEL);
 	if (!chip)
 		return -ENOMEM;
 	chip->card = card;
@@ -713,13 +693,9 @@
 	chip->irq = -1;
 	spin_lock_init(&chip->reg_lock);
 
-	chip->res_mmio = request_mem_region(pci_resource_start(pci, 0),
-					    pci_resource_len(pci, 0),
-					    "Bt87x audio");
-	if (!chip->res_mmio) {
-		snd_bt87x_free(chip);
-		snd_printk(KERN_ERR "cannot allocate io memory\n");
-		return -EBUSY;
+	if ((err = pci_request_regions(pci, "Bt87x audio")) < 0) {
+		kfree(chip);
+		return err;
 	}
 	chip->mmio = ioremap_nocache(pci_resource_start(pci, 0),
 				     pci_resource_len(pci, 0));
diff -Nru a/sound/pci/cmipci.c b/sound/pci/cmipci.c
--- a/sound/pci/cmipci.c	2004-10-18 14:56:48 -07:00
+++ b/sound/pci/cmipci.c	2004-10-18 14:56:48 -07:00
@@ -43,8 +43,7 @@
 MODULE_AUTHOR("Takashi Iwai <tiwai@suse.de>");
 MODULE_DESCRIPTION("C-Media CMI8x38 PCI");
 MODULE_LICENSE("GPL");
-MODULE_CLASSES("{sound}");
-MODULE_DEVICES("{{C-Media,CMI8738},"
+MODULE_SUPPORTED_DEVICE("{{C-Media,CMI8738},"
 		"{C-Media,CMI8738B},"
 		"{C-Media,CMI8338A},"
 		"{C-Media,CMI8338B}}");
@@ -66,25 +65,19 @@
 
 module_param_array(index, int, boot_devs, 0444);
 MODULE_PARM_DESC(index, "Index value for C-Media PCI soundcard.");
-MODULE_PARM_SYNTAX(index, SNDRV_INDEX_DESC);
 module_param_array(id, charp, boot_devs, 0444);
 MODULE_PARM_DESC(id, "ID string for C-Media PCI soundcard.");
-MODULE_PARM_SYNTAX(id, SNDRV_ID_DESC);
 module_param_array(enable, bool, boot_devs, 0444);
 MODULE_PARM_DESC(enable, "Enable C-Media PCI soundcard.");
-MODULE_PARM_SYNTAX(enable, SNDRV_ENABLE_DESC);
 module_param_array(mpu_port, long, boot_devs, 0444);
 MODULE_PARM_DESC(mpu_port, "MPU-401 port.");
-MODULE_PARM_SYNTAX(mpu_port, SNDRV_ENABLED ",allows:{{0},{0x330},{0x320},{0x310},{0x300}},dialog:list");
 module_param_array(fm_port, long, boot_devs, 0444);
 MODULE_PARM_DESC(fm_port, "FM port.");
-MODULE_PARM_SYNTAX(fm_port, SNDRV_ENABLED ",allows:{{0},{0x388},{0x3c8},{0x3e0},{0x3e8}},dialog:list");
 module_param_array(soft_ac3, bool, boot_devs, 0444);
 MODULE_PARM_DESC(soft_ac3, "Sofware-conversion of raw SPDIF packets (model 033 only).");
 #ifdef SUPPORT_JOYSTICK
 module_param_array(joystick_port, int, boot_devs, 0444);
 MODULE_PARM_DESC(joystick_port, "Joystick port address.");
-MODULE_PARM_SYNTAX(joystick_port, SNDRV_ENABLED ",allows:{{0},{1},{0x200},{0x201}},dialog:list");
 #endif
 
 #ifndef PCI_DEVICE_ID_CMEDIA_CM8738
@@ -405,8 +398,6 @@
 typedef struct snd_stru_cmipci cmipci_t;
 typedef struct snd_stru_cmipci_pcm cmipci_pcm_t;
 
-#define chip_t cmipci_t
-
 struct snd_stru_cmipci_pcm {
 	snd_pcm_substream_t *substream;
 	int running;		/* dac/adc running? */
@@ -442,7 +433,6 @@
 	int irq;
 
 	unsigned long iobase;
-	struct resource *res_iobase;
 	unsigned int ctrl;	/* FUNCTRL0 current value */
 
 	snd_pcm_t *pcm;		/* DAC/ADC PCM */
@@ -699,15 +689,13 @@
 
 static int set_dac_channels(cmipci_t *cm, cmipci_pcm_t *rec, int channels)
 {
-	unsigned long flags;
-
 	if (channels > 2) {
 		if (! cm->can_multi_ch)
 			return -EINVAL;
 		if (rec->fmt != 0x03) /* stereo 16bit only */
 			return -EINVAL;
 
-		spin_lock_irqsave(&cm->reg_lock, flags);
+		spin_lock_irq(&cm->reg_lock);
 		snd_cmipci_set_bit(cm, CM_REG_LEGACY_CTRL, CM_NXCHG);
 		snd_cmipci_set_bit(cm, CM_REG_MISC_CTRL, CM_XCHGDAC);
 		if (channels > 4) {
@@ -724,18 +712,18 @@
 			snd_cmipci_clear_bit(cm, CM_REG_LEGACY_CTRL, CM_CHB3D6C);
 			snd_cmipci_clear_bit(cm, CM_REG_MISC_CTRL, CM_ENCENTER);
 		}
-		spin_unlock_irqrestore(&cm->reg_lock, flags);
+		spin_unlock_irq(&cm->reg_lock);
 
 	} else {
 		if (cm->can_multi_ch) {
-			spin_lock_irqsave(&cm->reg_lock, flags);
+			spin_lock_irq(&cm->reg_lock);
 			snd_cmipci_clear_bit(cm, CM_REG_LEGACY_CTRL, CM_NXCHG);
 			snd_cmipci_clear_bit(cm, CM_REG_CHFORMAT, CM_CHB3D);
 			snd_cmipci_clear_bit(cm, CM_REG_CHFORMAT, CM_CHB3D5C);
 			snd_cmipci_clear_bit(cm, CM_REG_LEGACY_CTRL, CM_CHB3D6C);
 			snd_cmipci_clear_bit(cm, CM_REG_MISC_CTRL, CM_ENCENTER);
 			snd_cmipci_clear_bit(cm, CM_REG_MISC_CTRL, CM_XCHGDAC);
-			spin_unlock_irqrestore(&cm->reg_lock, flags);
+			spin_unlock_irq(&cm->reg_lock);
 		}
 	}
 	return 0;
@@ -749,7 +737,6 @@
 static int snd_cmipci_pcm_prepare(cmipci_t *cm, cmipci_pcm_t *rec,
 				 snd_pcm_substream_t *substream)
 {
-	unsigned long flags;
 	unsigned int reg, freq, val;
 	snd_pcm_runtime_t *runtime = substream->runtime;
 
@@ -777,7 +764,7 @@
 		rec->period_size = (rec->period_size * runtime->channels) / 2;
 	}
 
-	spin_lock_irqsave(&cm->reg_lock, flags);
+	spin_lock_irq(&cm->reg_lock);
 
 	/* set buffer address */
 	reg = rec->ch ? CM_REG_CH1_FRAME1 : CM_REG_CH0_FRAME1;
@@ -822,7 +809,7 @@
 	//snd_printd("cmipci: chformat = %08x\n", val);
 
 	rec->running = 0;
-	spin_unlock_irqrestore(&cm->reg_lock, flags);
+	spin_unlock_irq(&cm->reg_lock);
 
 	return 0;
 }
@@ -954,13 +941,12 @@
 					snd_ctl_elem_value_t *ucontrol)
 {
 	cmipci_t *chip = snd_kcontrol_chip(kcontrol);
-	unsigned long flags;
 	int i;
 
-	spin_lock_irqsave(&chip->reg_lock, flags);
+	spin_lock_irq(&chip->reg_lock);
 	for (i = 0; i < 4; i++)
 		ucontrol->value.iec958.status[i] = (chip->dig_status >> (i * 8)) & 0xff;
-	spin_unlock_irqrestore(&chip->reg_lock, flags);
+	spin_unlock_irq(&chip->reg_lock);
 	return 0;
 }
 
@@ -968,17 +954,16 @@
 					 snd_ctl_elem_value_t * ucontrol)
 {
 	cmipci_t *chip = snd_kcontrol_chip(kcontrol);
-	unsigned long flags;
 	int i, change;
 	unsigned int val;
 
 	val = 0;
-	spin_lock_irqsave(&chip->reg_lock, flags);
+	spin_lock_irq(&chip->reg_lock);
 	for (i = 0; i < 4; i++)
 		val |= (unsigned int)ucontrol->value.iec958.status[i] << (i * 8);
 	change = val != chip->dig_status;
 	chip->dig_status = val;
-	spin_unlock_irqrestore(&chip->reg_lock, flags);
+	spin_unlock_irq(&chip->reg_lock);
 	return change;
 }
 
@@ -1030,13 +1015,12 @@
 				       snd_ctl_elem_value_t *ucontrol)
 {
 	cmipci_t *chip = snd_kcontrol_chip(kcontrol);
-	unsigned long flags;
 	int i;
 
-	spin_lock_irqsave(&chip->reg_lock, flags);
+	spin_lock_irq(&chip->reg_lock);
 	for (i = 0; i < 4; i++)
 		ucontrol->value.iec958.status[i] = (chip->dig_pcm_status >> (i * 8)) & 0xff;
-	spin_unlock_irqrestore(&chip->reg_lock, flags);
+	spin_unlock_irq(&chip->reg_lock);
 	return 0;
 }
 
@@ -1044,17 +1028,16 @@
 				       snd_ctl_elem_value_t *ucontrol)
 {
 	cmipci_t *chip = snd_kcontrol_chip(kcontrol);
-	unsigned long flags;
 	int i, change;
 	unsigned int val;
 
 	val = 0;
-	spin_lock_irqsave(&chip->reg_lock, flags);
+	spin_lock_irq(&chip->reg_lock);
 	for (i = 0; i < 4; i++)
 		val |= (unsigned int)ucontrol->value.iec958.status[i] << (i * 8);
 	change = val != chip->dig_pcm_status;
 	chip->dig_pcm_status = val;
-	spin_unlock_irqrestore(&chip->reg_lock, flags);
+	spin_unlock_irq(&chip->reg_lock);
 	return change;
 }
 
@@ -1072,30 +1055,36 @@
  */
 
 /* save mixer setting and mute for AC3 playback */
-static void save_mixer_state(cmipci_t *cm)
+static int save_mixer_state(cmipci_t *cm)
 {
 	if (! cm->mixer_insensitive) {
+		snd_ctl_elem_value_t *val;
 		unsigned int i;
+
+		val = kmalloc(sizeof(*val), GFP_ATOMIC);
+		if (!val)
+			return -ENOMEM;
 		for (i = 0; i < CM_SAVED_MIXERS; i++) {
 			snd_kcontrol_t *ctl = cm->mixer_res_ctl[i];
 			if (ctl) {
-				snd_ctl_elem_value_t val;
 				int event;
-				memset(&val, 0, sizeof(val));
-				ctl->get(ctl, &val);
-				cm->mixer_res_status[i] = val.value.integer.value[0];
-				val.value.integer.value[0] = cm_saved_mixer[i].toggle_on;
+				memset(val, 0, sizeof(*val));
+				ctl->get(ctl, val);
+				cm->mixer_res_status[i] = val->value.integer.value[0];
+				val->value.integer.value[0] = cm_saved_mixer[i].toggle_on;
 				event = SNDRV_CTL_EVENT_MASK_INFO;
-				if (cm->mixer_res_status[i] != val.value.integer.value[0]) {
-					ctl->put(ctl, &val); /* toggle */
+				if (cm->mixer_res_status[i] != val->value.integer.value[0]) {
+					ctl->put(ctl, val); /* toggle */
 					event |= SNDRV_CTL_EVENT_MASK_VALUE;
 				}
 				ctl->vd[0].access |= SNDRV_CTL_ELEM_ACCESS_INACTIVE;
 				snd_ctl_notify(cm->card, event, &ctl->id);
 			}
 		}
+		kfree(val);
 		cm->mixer_insensitive = 1;
 	}
+	return 0;
 }
 
 
@@ -1103,27 +1092,32 @@
 static void restore_mixer_state(cmipci_t *cm)
 {
 	if (cm->mixer_insensitive) {
+		snd_ctl_elem_value_t *val;
 		unsigned int i;
+
+		val = kmalloc(sizeof(*val), GFP_KERNEL);
+		if (!val)
+			return;
 		cm->mixer_insensitive = 0; /* at first clear this;
 					      otherwise the changes will be ignored */
 		for (i = 0; i < CM_SAVED_MIXERS; i++) {
 			snd_kcontrol_t *ctl = cm->mixer_res_ctl[i];
 			if (ctl) {
-				snd_ctl_elem_value_t val;
 				int event;
 
-				memset(&val, 0, sizeof(val));
+				memset(val, 0, sizeof(*val));
 				ctl->vd[0].access &= ~SNDRV_CTL_ELEM_ACCESS_INACTIVE;
-				ctl->get(ctl, &val);
+				ctl->get(ctl, val);
 				event = SNDRV_CTL_EVENT_MASK_INFO;
-				if (val.value.integer.value[0] != cm->mixer_res_status[i]) {
-					val.value.integer.value[0] = cm->mixer_res_status[i];
-					ctl->put(ctl, &val);
+				if (val->value.integer.value[0] != cm->mixer_res_status[i]) {
+					val->value.integer.value[0] = cm->mixer_res_status[i];
+					ctl->put(ctl, val);
 					event |= SNDRV_CTL_EVENT_MASK_VALUE;
 				}
 				snd_ctl_notify(cm->card, event, &ctl->id);
 			}
 		}
+		kfree(val);
 	}
 }
 
@@ -1175,17 +1169,17 @@
 	}
 }
 
-static void setup_spdif_playback(cmipci_t *cm, snd_pcm_substream_t *subs, int up, int do_ac3)
+static int setup_spdif_playback(cmipci_t *cm, snd_pcm_substream_t *subs, int up, int do_ac3)
 {
-	int rate;
-	unsigned long flags;
+	int rate, err;
 
 	rate = subs->runtime->rate;
 
 	if (up && do_ac3)
-		save_mixer_state(cm);
+		if ((err = save_mixer_state(cm)) < 0)
+			return err;
 
-	spin_lock_irqsave(&cm->reg_lock, flags);
+	spin_lock_irq(&cm->reg_lock);
 	cm->spdif_playback_avail = up;
 	if (up) {
 		/* they are controlled via "IEC958 Output Switch" */
@@ -1207,7 +1201,8 @@
 		snd_cmipci_clear_bit(cm, CM_REG_FUNCTRL1, CM_PLAYBACK_SPDF);
 		setup_ac3(cm, subs, 0, 0);
 	}
-	spin_unlock_irqrestore(&cm->reg_lock, flags);
+	spin_unlock_irq(&cm->reg_lock);
+	return 0;
 }
 
 
@@ -1220,13 +1215,15 @@
 {
 	cmipci_t *cm = snd_pcm_substream_chip(substream);
 	int rate = substream->runtime->rate;
-	int do_spdif, do_ac3 = 0;
+	int err, do_spdif, do_ac3 = 0;
+
 	do_spdif = ((rate == 44100 || rate == 48000) &&
 		    substream->runtime->format == SNDRV_PCM_FORMAT_S16_LE &&
 		    substream->runtime->channels == 2);
 	if (do_spdif && cm->can_ac3_hw) 
 		do_ac3 = cm->dig_pcm_status & IEC958_AES0_NONAUDIO;
-	setup_spdif_playback(cm, substream, do_spdif, do_ac3);
+	if ((err = setup_spdif_playback(cm, substream, do_spdif, do_ac3)) < 0)
+		return err;
 	return snd_cmipci_pcm_prepare(cm, &cm->channel[CM_CH_PLAY], substream);
 }
 
@@ -1234,12 +1231,14 @@
 static int snd_cmipci_playback_spdif_prepare(snd_pcm_substream_t *substream)
 {
 	cmipci_t *cm = snd_pcm_substream_chip(substream);
-	int do_ac3;
+	int err, do_ac3;
+
 	if (cm->can_ac3_hw) 
 		do_ac3 = cm->dig_pcm_status & IEC958_AES0_NONAUDIO;
 	else
 		do_ac3 = 1; /* doesn't matter */
-	setup_spdif_playback(cm, substream, 1, do_ac3);
+	if ((err = setup_spdif_playback(cm, substream, 1, do_ac3)) < 0)
+		return err;
 	return snd_cmipci_pcm_prepare(cm, &cm->channel[CM_CH_PLAY], substream);
 }
 
@@ -1262,11 +1261,10 @@
 static int snd_cmipci_capture_spdif_prepare(snd_pcm_substream_t *substream)
 {
 	cmipci_t *cm = snd_pcm_substream_chip(substream);
-	unsigned long flags;
 
-	spin_lock_irqsave(&cm->reg_lock, flags);
+	spin_lock_irq(&cm->reg_lock);
 	snd_cmipci_set_bit(cm, CM_REG_FUNCTRL1, CM_CAPTURE_SPDF);
-	spin_unlock_irqrestore(&cm->reg_lock, flags);
+	spin_unlock_irq(&cm->reg_lock);
 
 	return snd_cmipci_pcm_prepare(cm, &cm->channel[CM_CH_CAPT], substream);
 }
@@ -1274,11 +1272,10 @@
 static int snd_cmipci_capture_spdif_hw_free(snd_pcm_substream_t *subs)
 {
 	cmipci_t *cm = snd_pcm_substream_chip(subs);
-	unsigned long flags;
 
-	spin_lock_irqsave(&cm->reg_lock, flags);
+	spin_lock_irq(&cm->reg_lock);
 	snd_cmipci_clear_bit(cm, CM_REG_FUNCTRL1, CM_CAPTURE_SPDF);
-	spin_unlock_irqrestore(&cm->reg_lock, flags);
+	spin_unlock_irq(&cm->reg_lock);
 
 	return snd_cmipci_hw_free(subs);
 }
@@ -1289,7 +1286,7 @@
  */
 static irqreturn_t snd_cmipci_interrupt(int irq, void *dev_id, struct pt_regs *regs)
 {
-	cmipci_t *cm = snd_magic_cast(cmipci_t, dev_id, return IRQ_NONE);
+	cmipci_t *cm = dev_id;
 	unsigned int status, mask = 0;
 	
 	/* fastpath out, to ease interrupt sharing */
@@ -1448,7 +1445,6 @@
  */
 static int open_device_check(cmipci_t *cm, int mode, snd_pcm_substream_t *subs)
 {
-	unsigned long flags;
 	int ch = mode & CM_OPEN_CH_MASK;
 
 	/* FIXME: a file should wait until the device becomes free
@@ -1466,9 +1462,9 @@
 	if (! (mode & CM_OPEN_DAC)) {
 		/* disable dual DAC mode */
 		cm->channel[ch].is_dac = 0;
-		spin_lock_irqsave(&cm->reg_lock, flags);
+		spin_lock_irq(&cm->reg_lock);
 		snd_cmipci_clear_bit(cm, CM_REG_MISC_CTRL, CM_ENDBDAC);
-		spin_unlock_irqrestore(&cm->reg_lock, flags);
+		spin_unlock_irq(&cm->reg_lock);
 	}
 	up(&cm->open_mutex);
 	return 0;
@@ -1476,7 +1472,6 @@
 
 static void close_device_check(cmipci_t *cm, int mode)
 {
-	unsigned long flags;
 	int ch = mode & CM_OPEN_CH_MASK;
 
 	down(&cm->open_mutex);
@@ -1490,9 +1485,9 @@
 		if (! cm->channel[ch].is_dac) {
 			/* enable dual DAC mode again */
 			cm->channel[ch].is_dac = 1;
-			spin_lock_irqsave(&cm->reg_lock, flags);
+			spin_lock_irq(&cm->reg_lock);
 			snd_cmipci_set_bit(cm, CM_REG_MISC_CTRL, CM_ENDBDAC);
-			spin_unlock_irqrestore(&cm->reg_lock, flags);
+			spin_unlock_irq(&cm->reg_lock);
 		}
 	}
 	up(&cm->open_mutex);
@@ -1840,12 +1835,11 @@
 static int snd_cmipci_get_volume(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
 {
 	cmipci_t *cm = snd_kcontrol_chip(kcontrol);
-	unsigned long flags;
 	cmipci_sb_reg_t reg;
 	int val;
 
 	cmipci_sb_reg_decode(&reg, kcontrol->private_value);
-	spin_lock_irqsave(&cm->reg_lock, flags);
+	spin_lock_irq(&cm->reg_lock);
 	val = (snd_cmipci_mixer_read(cm, reg.left_reg) >> reg.left_shift) & reg.mask;
 	if (reg.invert)
 		val = reg.mask - val;
@@ -1856,14 +1850,13 @@
 			val = reg.mask - val;
 		 ucontrol->value.integer.value[1] = val;
 	}
-	spin_unlock_irqrestore(&cm->reg_lock, flags);
+	spin_unlock_irq(&cm->reg_lock);
 	return 0;
 }
 
 static int snd_cmipci_put_volume(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
 {
 	cmipci_t *cm = snd_kcontrol_chip(kcontrol);
-	unsigned long flags;
 	cmipci_sb_reg_t reg;
 	int change;
 	int left, right, oleft, oright;
@@ -1880,7 +1873,7 @@
 		right <<= reg.right_shift;
 	} else
 		right = 0;
-	spin_lock_irqsave(&cm->reg_lock, flags);
+	spin_lock_irq(&cm->reg_lock);
 	oleft = snd_cmipci_mixer_read(cm, reg.left_reg);
 	left |= oleft & ~(reg.mask << reg.left_shift);
 	change = left != oleft;
@@ -1895,7 +1888,7 @@
 		snd_cmipci_mixer_write(cm, reg.right_reg, right);
 	} else
 		snd_cmipci_mixer_write(cm, reg.left_reg, left);
-	spin_unlock_irqrestore(&cm->reg_lock, flags);
+	spin_unlock_irq(&cm->reg_lock);
 	return change;
 }
 
@@ -1921,15 +1914,14 @@
 static int snd_cmipci_get_input_sw(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
 {
 	cmipci_t *cm = snd_kcontrol_chip(kcontrol);
-	unsigned long flags;
 	cmipci_sb_reg_t reg;
 	int val1, val2;
 
 	cmipci_sb_reg_decode(&reg, kcontrol->private_value);
-	spin_lock_irqsave(&cm->reg_lock, flags);
+	spin_lock_irq(&cm->reg_lock);
 	val1 = snd_cmipci_mixer_read(cm, reg.left_reg);
 	val2 = snd_cmipci_mixer_read(cm, reg.right_reg);
-	spin_unlock_irqrestore(&cm->reg_lock, flags);
+	spin_unlock_irq(&cm->reg_lock);
 	ucontrol->value.integer.value[0] = (val1 >> reg.left_shift) & 1;
 	ucontrol->value.integer.value[1] = (val2 >> reg.left_shift) & 1;
 	ucontrol->value.integer.value[2] = (val1 >> reg.right_shift) & 1;
@@ -1940,13 +1932,12 @@
 static int snd_cmipci_put_input_sw(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
 {
 	cmipci_t *cm = snd_kcontrol_chip(kcontrol);
-	unsigned long flags;
 	cmipci_sb_reg_t reg;
 	int change;
 	int val1, val2, oval1, oval2;
 
 	cmipci_sb_reg_decode(&reg, kcontrol->private_value);
-	spin_lock_irqsave(&cm->reg_lock, flags);
+	spin_lock_irq(&cm->reg_lock);
 	oval1 = snd_cmipci_mixer_read(cm, reg.left_reg);
 	oval2 = snd_cmipci_mixer_read(cm, reg.right_reg);
 	val1 = oval1 & ~((1 << reg.left_shift) | (1 << reg.right_shift));
@@ -1958,7 +1949,7 @@
 	change = val1 != oval1 || val2 != oval2;
 	snd_cmipci_mixer_write(cm, reg.left_reg, val1);
 	snd_cmipci_mixer_write(cm, reg.right_reg, val2);
-	spin_unlock_irqrestore(&cm->reg_lock, flags);
+	spin_unlock_irq(&cm->reg_lock);
 	return change;
 }
 
@@ -2011,11 +2002,10 @@
 {
 	cmipci_t *cm = snd_kcontrol_chip(kcontrol);
 	cmipci_sb_reg_t reg;
-	unsigned long flags;
 	unsigned char oreg, val;
 
 	cmipci_sb_reg_decode(&reg, kcontrol->private_value);
-	spin_lock_irqsave(&cm->reg_lock, flags);
+	spin_lock_irq(&cm->reg_lock);
 	oreg = inb(cm->iobase + reg.left_reg);
 	val = (oreg >> reg.left_shift) & reg.mask;
 	if (reg.invert)
@@ -2027,7 +2017,7 @@
 			val = reg.mask - val;
 		ucontrol->value.integer.value[1] = val;
 	}
-	spin_unlock_irqrestore(&cm->reg_lock, flags);
+	spin_unlock_irq(&cm->reg_lock);
 	return 0;
 }
 
@@ -2035,11 +2025,10 @@
 {
 	cmipci_t *cm = snd_kcontrol_chip(kcontrol);
 	cmipci_sb_reg_t reg;
-	unsigned long flags;
 	unsigned char oreg, nreg, val;
 
 	cmipci_sb_reg_decode(&reg, kcontrol->private_value);
-	spin_lock_irqsave(&cm->reg_lock, flags);
+	spin_lock_irq(&cm->reg_lock);
 	oreg = inb(cm->iobase + reg.left_reg);
 	val = ucontrol->value.integer.value[0] & reg.mask;
 	if (reg.invert)
@@ -2054,7 +2043,7 @@
 		nreg |= (val << reg.right_shift);
 	}
 	outb(nreg, cm->iobase + reg.left_reg);
-	spin_unlock_irqrestore(&cm->reg_lock, flags);
+	spin_unlock_irq(&cm->reg_lock);
 	return (nreg != oreg);
 }
 
@@ -2078,8 +2067,6 @@
 }
 
 
-#define num_controls(ary) (sizeof(ary) / sizeof(snd_kcontrol_new_t))
-
 static snd_kcontrol_new_t snd_cmipci_mixers[] __devinitdata = {
 	CMIPCI_SB_VOL_STEREO("Master Playback Volume", SB_DSP4_MASTER_DEV, 3, 31),
 	CMIPCI_MIXER_SW_MONO("3D Control - Switch", CM_REG_MIXER1, CM_X3DEN_SHIFT, 0),
@@ -2137,14 +2124,13 @@
 
 static int _snd_cmipci_uswitch_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol, snd_cmipci_switch_args_t *args)
 {
-	unsigned long flags;
 	unsigned int val;
 	cmipci_t *cm = snd_kcontrol_chip(kcontrol);
 
-	spin_lock_irqsave(&cm->reg_lock, flags);
+	spin_lock_irq(&cm->reg_lock);
 	if (args->ac3_sensitive && cm->mixer_insensitive) {
 		ucontrol->value.integer.value[0] = 0;
-		spin_unlock_irqrestore(&cm->reg_lock, flags);
+		spin_unlock_irq(&cm->reg_lock);
 		return 0;
 	}
 	if (args->is_byte)
@@ -2152,7 +2138,7 @@
 	else
 		val = snd_cmipci_read(cm, args->reg);
 	ucontrol->value.integer.value[0] = ((val & args->mask) == args->mask_on) ? 1 : 0;
-	spin_unlock_irqrestore(&cm->reg_lock, flags);
+	spin_unlock_irq(&cm->reg_lock);
 	return 0;
 }
 
@@ -2165,15 +2151,14 @@
 
 static int _snd_cmipci_uswitch_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol, snd_cmipci_switch_args_t *args)
 {
-	unsigned long flags;
 	unsigned int val;
 	int change;
 	cmipci_t *cm = snd_kcontrol_chip(kcontrol);
 
-	spin_lock_irqsave(&cm->reg_lock, flags);
+	spin_lock_irq(&cm->reg_lock);
 	if (args->ac3_sensitive && cm->mixer_insensitive) {
 		/* ignored */
-		spin_unlock_irqrestore(&cm->reg_lock, flags);
+		spin_unlock_irq(&cm->reg_lock);
 		return 0;
 	}
 	if (args->is_byte)
@@ -2192,7 +2177,7 @@
 		else
 			snd_cmipci_write(cm, args->reg, val);
 	}
-	spin_unlock_irqrestore(&cm->reg_lock, flags);
+	spin_unlock_irq(&cm->reg_lock);
 	return change;
 }
 
@@ -2345,7 +2330,6 @@
 
 static int __devinit snd_cmipci_mixer_new(cmipci_t *cm, int pcm_spdif_device)
 {
-	unsigned long flags;
 	snd_card_t *card;
 	snd_kcontrol_new_t *sw;
 	snd_kcontrol_t *kctl;
@@ -2358,18 +2342,18 @@
 
 	strcpy(card->mixername, "CMedia PCI");
 
-	spin_lock_irqsave(&cm->reg_lock, flags);
+	spin_lock_irq(&cm->reg_lock);
 	snd_cmipci_mixer_write(cm, 0x00, 0x00);		/* mixer reset */
-	spin_unlock_irqrestore(&cm->reg_lock, flags);
+	spin_unlock_irq(&cm->reg_lock);
 
-	for (idx = 0; idx < num_controls(snd_cmipci_mixers); idx++) {
+	for (idx = 0; idx < ARRAY_SIZE(snd_cmipci_mixers); idx++) {
 		if ((err = snd_ctl_add(card, snd_ctl_new1(&snd_cmipci_mixers[idx], cm))) < 0)
 			return err;
 	}
 
 	/* mixer switches */
 	sw = snd_cmipci_mixer_switches;
-	for (idx = 0; idx < num_controls(snd_cmipci_mixer_switches); idx++, sw++) {
+	for (idx = 0; idx < ARRAY_SIZE(snd_cmipci_mixer_switches); idx++, sw++) {
 		err = snd_ctl_add(cm->card, snd_ctl_new1(sw, cm));
 		if (err < 0)
 			return err;
@@ -2382,7 +2366,7 @@
 	if (cm->device == PCI_DEVICE_ID_CMEDIA_CM8738 ||
 	    cm->device == PCI_DEVICE_ID_CMEDIA_CM8738B) {
 		sw = snd_cmipci_8738_mixer_switches;
-		for (idx = 0; idx < num_controls(snd_cmipci_8738_mixer_switches); idx++, sw++) {
+		for (idx = 0; idx < ARRAY_SIZE(snd_cmipci_8738_mixer_switches); idx++, sw++) {
 			err = snd_ctl_add(cm->card, snd_ctl_new1(sw, cm));
 			if (err < 0)
 				return err;
@@ -2400,7 +2384,7 @@
 		}
 		if (cm->chip_version <= 37) {
 			sw = snd_cmipci_old_mixer_switches;
-			for (idx = 0; idx < num_controls(snd_cmipci_old_mixer_switches); idx++, sw++) {
+			for (idx = 0; idx < ARRAY_SIZE(snd_cmipci_old_mixer_switches); idx++, sw++) {
 				err = snd_ctl_add(cm->card, snd_ctl_new1(sw, cm));
 				if (err < 0)
 					return err;
@@ -2409,7 +2393,7 @@
 	}
 	if (cm->chip_version >= 39) {
 		sw = snd_cmipci_extra_mixer_switches;
-		for (idx = 0; idx < num_controls(snd_cmipci_extra_mixer_switches); idx++, sw++) {
+		for (idx = 0; idx < ARRAY_SIZE(snd_cmipci_extra_mixer_switches); idx++, sw++) {
 			err = snd_ctl_add(cm->card, snd_ctl_new1(sw, cm));
 			if (err < 0)
 				return err;
@@ -2418,7 +2402,7 @@
 
 	/* card switches */
 	sw = snd_cmipci_control_switches;
-	for (idx = 0; idx < num_controls(snd_cmipci_control_switches); idx++, sw++) {
+	for (idx = 0; idx < ARRAY_SIZE(snd_cmipci_control_switches); idx++, sw++) {
 		err = snd_ctl_add(cm->card, snd_ctl_new1(sw, cm));
 		if (err < 0)
 			return err;
@@ -2446,7 +2430,7 @@
 static void snd_cmipci_proc_read(snd_info_entry_t *entry, 
 				 snd_info_buffer_t *buffer)
 {
-	cmipci_t *cm = snd_magic_cast(cmipci_t, entry->private_data, return);
+	cmipci_t *cm = entry->private_data;
 	int i;
 	
 	snd_iprintf(buffer, "%s\n\n", cm->card->longname);
@@ -2566,17 +2550,14 @@
 		kfree_nocheck(cm->res_joystick);
 	}
 #endif
-	if (cm->res_iobase) {
-		release_resource(cm->res_iobase);
-		kfree_nocheck(cm->res_iobase);
-	}
-	snd_magic_kfree(cm);
+	pci_release_regions(cm->pci);
+	kfree(cm);
 	return 0;
 }
 
 static int snd_cmipci_dev_free(snd_device_t *device)
 {
-	cmipci_t *cm = snd_magic_cast(cmipci_t, device->device_data, return -ENXIO);
+	cmipci_t *cm = device->device_data;
 	return snd_cmipci_free(cm);
 }
 
@@ -2598,7 +2579,7 @@
 	if ((err = pci_enable_device(pci)) < 0)
 		return err;
 
-	cm = snd_magic_kcalloc(cmipci_t, 0, GFP_KERNEL);
+	cm = kcalloc(1, sizeof(*cm), GFP_KERNEL);
 	if (cm == NULL)
 		return -ENOMEM;
 
@@ -2608,16 +2589,16 @@
 	cm->card = card;
 	cm->pci = pci;
 	cm->irq = -1;
-	cm->iobase = pci_resource_start(pci, 0);
 	cm->channel[0].ch = 0;
 	cm->channel[1].ch = 1;
 	cm->channel[0].is_dac = cm->channel[1].is_dac = 1; /* dual DAC mode */
 
-	if ((cm->res_iobase = request_region(cm->iobase, CM_EXTENT_CODEC, card->driver)) == NULL) {
-		snd_printk("unable to grab ports 0x%lx-0x%lx\n", cm->iobase, cm->iobase + CM_EXTENT_CODEC - 1);
-		err = -EBUSY;
-		goto __error;
+	if ((err = pci_request_regions(pci, card->driver)) < 0) {
+		kfree(cm);
+		return err;
 	}
+	cm->iobase = pci_resource_start(pci, 0);
+
 	if (request_irq(pci->irq, snd_cmipci_interrupt, SA_INTERRUPT|SA_SHIRQ, card->driver, (void *)cm)) {
 		snd_printk("unable to grab IRQ %d\n", pci->irq);
 		err = -EBUSY;
@@ -2776,12 +2757,12 @@
 			int i;
 			for (i = 0; ports[i]; i++) {
 				joystick_port[dev] = ports[i];
-				cm->res_joystick = request_region(ports[i], 8, "CMIPCI gameport");
+				cm->res_joystick = request_region(ports[i], 1, "CMIPCI gameport");
 				if (cm->res_joystick)
 					break;
 			}
 		} else {
-			cm->res_joystick = request_region(joystick_port[dev], 8, "CMIPCI gameport");
+			cm->res_joystick = request_region(joystick_port[dev], 1, "CMIPCI gameport");
 		}
 	}
 	if (cm->res_joystick) {
diff -Nru a/sound/pci/cs4281.c b/sound/pci/cs4281.c
--- a/sound/pci/cs4281.c	2004-10-18 14:57:04 -07:00
+++ b/sound/pci/cs4281.c	2004-10-18 14:57:04 -07:00
@@ -40,8 +40,7 @@
 MODULE_AUTHOR("Jaroslav Kysela <perex@suse.cz>");
 MODULE_DESCRIPTION("Cirrus Logic CS4281");
 MODULE_LICENSE("GPL");
-MODULE_CLASSES("{sound}");
-MODULE_DEVICES("{{Cirrus Logic,CS4281}}");
+MODULE_SUPPORTED_DEVICE("{{Cirrus Logic,CS4281}}");
 
 static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX;	/* Index 0-MAX */
 static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR;	/* ID for this card */
@@ -51,16 +50,12 @@
 
 module_param_array(index, int, boot_devs, 0444);
 MODULE_PARM_DESC(index, "Index value for CS4281 soundcard.");
-MODULE_PARM_SYNTAX(index, SNDRV_INDEX_DESC);
 module_param_array(id, charp, boot_devs, 0444);
 MODULE_PARM_DESC(id, "ID string for CS4281 soundcard.");
-MODULE_PARM_SYNTAX(id, SNDRV_ID_DESC);
 module_param_array(enable, bool, boot_devs, 0444);
 MODULE_PARM_DESC(enable, "Enable CS4281 soundcard.");
-MODULE_PARM_SYNTAX(enable, SNDRV_ENABLE_DESC);
 module_param_array(dual_codec, bool, boot_devs, 0444);
 MODULE_PARM_DESC(dual_codec, "Secondary Codec ID (0 = disabled).");
-MODULE_PARM_SYNTAX(dual_codec, SNDRV_ENABLED ",allows:{{0,3}}");
 
 /*
  *
@@ -441,8 +436,6 @@
  *
  */
 
-#define chip_t cs4281_t
-
 typedef struct snd_cs4281 cs4281_t;
 typedef struct snd_cs4281_dma cs4281_dma_t;
 
@@ -475,8 +468,6 @@
 	unsigned long ba1;		/* virtual (accessible) address */
 	unsigned long ba0_addr;
 	unsigned long ba1_addr;
-	struct resource *ba0_res;
-	struct resource *ba1_res;
 
 	int dual_codec;
 
@@ -575,7 +566,7 @@
 	 *  4. Read ACCTL = 460h, DCV should be reset by now and 460h = 07h
 	 *  5. if DCV not cleared, break and return error
 	 */
-	cs4281_t *chip = snd_magic_cast(cs4281_t, ac97->private_data, return);
+	cs4281_t *chip = ac97->private_data;
 	int count;
 
 	/*
@@ -613,7 +604,7 @@
 static unsigned short snd_cs4281_ac97_read(ac97_t *ac97,
 					   unsigned short reg)
 {
-	cs4281_t *chip = snd_magic_cast(cs4281_t, ac97->private_data, return -ENXIO);
+	cs4281_t *chip = ac97->private_data;
 	int count;
 	unsigned short result;
 	// FIXME: volatile is necessary in the following due to a bug of
@@ -709,9 +700,8 @@
 {
 	cs4281_dma_t *dma = (cs4281_dma_t *)substream->runtime->private_data;
 	cs4281_t *chip = snd_pcm_substream_chip(substream);
-	unsigned long flags;
 
-	spin_lock_irqsave(&chip->reg_lock, flags);
+	spin_lock(&chip->reg_lock);
 	switch (cmd) {
 	case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
 		dma->valDCR |= BA0_DCR_MSK;
@@ -738,13 +728,13 @@
 			dma->valFCR &= ~BA0_FCR_FEN;
 		break;
 	default:
-		spin_unlock_irqrestore(&chip->reg_lock, flags);
+		spin_unlock(&chip->reg_lock);
 		return -EINVAL;
 	}
 	snd_cs4281_pokeBA0(chip, dma->regDMR, dma->valDMR);
 	snd_cs4281_pokeBA0(chip, dma->regFCR, dma->valFCR);
 	snd_cs4281_pokeBA0(chip, dma->regDCR, dma->valDCR);
-	spin_unlock_irqrestore(&chip->reg_lock, flags);
+	spin_unlock(&chip->reg_lock);
 	return 0;
 }
 
@@ -851,11 +841,10 @@
 	snd_pcm_runtime_t *runtime = substream->runtime;
 	cs4281_dma_t *dma = (cs4281_dma_t *)runtime->private_data;
 	cs4281_t *chip = snd_pcm_substream_chip(substream);
-	unsigned long flags;
 
-	spin_lock_irqsave(&chip->reg_lock, flags);
+	spin_lock_irq(&chip->reg_lock);
 	snd_cs4281_mode(chip, dma, runtime, 0, 1);
-	spin_unlock_irqrestore(&chip->reg_lock, flags);
+	spin_unlock_irq(&chip->reg_lock);
 	return 0;
 }
 
@@ -864,11 +853,10 @@
 	snd_pcm_runtime_t *runtime = substream->runtime;
 	cs4281_dma_t *dma = (cs4281_dma_t *)runtime->private_data;
 	cs4281_t *chip = snd_pcm_substream_chip(substream);
-	unsigned long flags;
 
-	spin_lock_irqsave(&chip->reg_lock, flags);
+	spin_lock_irq(&chip->reg_lock);
 	snd_cs4281_mode(chip, dma, runtime, 1, 1);
-	spin_unlock_irqrestore(&chip->reg_lock, flags);
+	spin_unlock_irq(&chip->reg_lock);
 	return 0;
 }
 
@@ -1015,7 +1003,7 @@
 
 static void snd_cs4281_pcm_free(snd_pcm_t *pcm)
 {
-	cs4281_t *chip = snd_magic_cast(cs4281_t, pcm->private_data, return);
+	cs4281_t *chip = pcm->private_data;
 	chip->pcm = NULL;
 	snd_pcm_lib_preallocate_free_for_all(pcm);
 }
@@ -1124,13 +1112,13 @@
 
 static void snd_cs4281_mixer_free_ac97_bus(ac97_bus_t *bus)
 {
-	cs4281_t *chip = snd_magic_cast(cs4281_t, bus->private_data, return);
+	cs4281_t *chip = bus->private_data;
 	chip->ac97_bus = NULL;
 }
 
 static void snd_cs4281_mixer_free_ac97(ac97_t *ac97)
 {
-	cs4281_t *chip = snd_magic_cast(cs4281_t, ac97->private_data, return);
+	cs4281_t *chip = ac97->private_data;
 	if (ac97->num)
 		chip->ac97_secondary = NULL;
 	else
@@ -1140,17 +1128,16 @@
 static int __devinit snd_cs4281_mixer(cs4281_t * chip)
 {
 	snd_card_t *card = chip->card;
-	ac97_bus_t bus;
-	ac97_t ac97;
+	ac97_template_t ac97;
 	int err;
+	static ac97_bus_ops_t ops = {
+		.write = snd_cs4281_ac97_write,
+		.read = snd_cs4281_ac97_read,
+	};
 
-	memset(&bus, 0, sizeof(bus));
-	bus.write = snd_cs4281_ac97_write;
-	bus.read = snd_cs4281_ac97_read;
-	bus.private_data = chip;
-	bus.private_free = snd_cs4281_mixer_free_ac97_bus;
-	if ((err = snd_ac97_bus(card, &bus, &chip->ac97_bus)) < 0)
+	if ((err = snd_ac97_bus(card, 0, &ops, chip, &chip->ac97_bus)) < 0)
 		return err;
+	chip->ac97_bus->private_free = snd_cs4281_mixer_free_ac97_bus;
 
 	memset(&ac97, 0, sizeof(ac97));
 	ac97.private_data = chip;
@@ -1177,7 +1164,7 @@
 static void snd_cs4281_proc_read(snd_info_entry_t *entry, 
 				  snd_info_buffer_t * buffer)
 {
-	cs4281_t *chip = snd_magic_cast(cs4281_t, entry->private_data, return);
+	cs4281_t *chip = entry->private_data;
 
 	snd_iprintf(buffer, "Cirrus Logic CS4281\n\n");
 	snd_iprintf(buffer, "Spurious half IRQs   : %u\n", chip->spurious_dhtc_irq);
@@ -1189,7 +1176,7 @@
 				unsigned long count, unsigned long pos)
 {
 	long size;
-	cs4281_t *chip = snd_magic_cast(cs4281_t, entry->private_data, return -ENXIO);
+	cs4281_t *chip = entry->private_data;
 	
 	size = count;
 	if (pos + size > CS4281_BA0_SIZE)
@@ -1206,7 +1193,7 @@
 				unsigned long count, unsigned long pos)
 {
 	long size;
-	cs4281_t *chip = snd_magic_cast(cs4281_t, entry->private_data, return -ENXIO);
+	cs4281_t *chip = entry->private_data;
 	
 	size = count;
 	if (pos + size > CS4281_BA1_SIZE)
@@ -1262,7 +1249,7 @@
 	cs4281_gameport_t *gp = (cs4281_gameport_t *)gameport;
 	cs4281_t *chip;
 	snd_assert(gp, return);
-	chip = snd_magic_cast(cs4281_t, gp->chip, return);
+	chip = gp->chip;
 	snd_cs4281_pokeBA0(chip, BA0_JSPT, 0xff);
 }
 
@@ -1271,7 +1258,7 @@
 	cs4281_gameport_t *gp = (cs4281_gameport_t *)gameport;
 	cs4281_t *chip;
 	snd_assert(gp, return 0);
-	chip = snd_magic_cast(cs4281_t, gp->chip, return 0);
+	chip = gp->chip;
 	return snd_cs4281_peekBA0(chip, BA0_JSPT);
 }
 
@@ -1283,7 +1270,7 @@
 	unsigned js1, js2, jst;
 	
 	snd_assert(gp, return 0);
-	chip = snd_magic_cast(cs4281_t, gp->chip, return 0);
+	chip = gp->chip;
 
 	js1 = snd_cs4281_peekBA0(chip, BA0_JSC1);
 	js2 = snd_cs4281_peekBA0(chip, BA0_JSC2);
@@ -1369,28 +1356,21 @@
 	/* PCI interface - D3 state */
 	pci_set_power_state(chip->pci, 3);
 
+	if (chip->irq >= 0)
+		free_irq(chip->irq, (void *)chip);
 	if (chip->ba0)
 		iounmap((void *) chip->ba0);
 	if (chip->ba1)
 		iounmap((void *) chip->ba1);
-	if (chip->ba0_res) {
-		release_resource(chip->ba0_res);
-		kfree_nocheck(chip->ba0_res);
-	}
-	if (chip->ba1_res) {
-		release_resource(chip->ba1_res);
-		kfree_nocheck(chip->ba1_res);
-	}
-	if (chip->irq >= 0)
-		free_irq(chip->irq, (void *)chip);
+	pci_release_regions(chip->pci);
 
-	snd_magic_kfree(chip);
+	kfree(chip);
 	return 0;
 }
 
 static int snd_cs4281_dev_free(snd_device_t *device)
 {
-	cs4281_t *chip = snd_magic_cast(cs4281_t, device->device_data, return -ENXIO);
+	cs4281_t *chip = device->device_data;
 	return snd_cs4281_free(chip);
 }
 
@@ -1415,15 +1395,13 @@
 	*rchip = NULL;
 	if ((err = pci_enable_device(pci)) < 0)
 		return err;
-	chip = snd_magic_kcalloc(cs4281_t, 0, GFP_KERNEL);
+	chip = kcalloc(1, sizeof(*chip), GFP_KERNEL);
 	if (chip == NULL)
 		return -ENOMEM;
 	spin_lock_init(&chip->reg_lock);
 	chip->card = card;
 	chip->pci = pci;
 	chip->irq = -1;
-	chip->ba0_addr = pci_resource_start(pci, 0);
-	chip->ba1_addr = pci_resource_start(pci, 1);
 	pci_set_master(pci);
 	if (dual_codec < 0 || dual_codec > 3) {
 		snd_printk(KERN_ERR "invalid dual_codec option %d\n", dual_codec);
@@ -1431,16 +1409,13 @@
 	}
 	chip->dual_codec = dual_codec;
 
-	if ((chip->ba0_res = request_mem_region(chip->ba0_addr, CS4281_BA0_SIZE, "CS4281 BA0")) == NULL) {
-		snd_printk(KERN_ERR "unable to grab memory region 0x%lx-0x%lx\n", chip->ba0_addr, chip->ba0_addr + CS4281_BA0_SIZE - 1);
-		snd_cs4281_free(chip);
-		return -ENOMEM;
-	}
-	if ((chip->ba1_res = request_mem_region(chip->ba1_addr, CS4281_BA1_SIZE, "CS4281 BA1")) == NULL) {
-		snd_printk(KERN_ERR "unable to grab memory region 0x%lx-0x%lx\n", chip->ba1_addr, chip->ba1_addr + CS4281_BA1_SIZE - 1);
-		snd_cs4281_free(chip);
-		return -ENOMEM;
+	if ((err = pci_request_regions(pci, "CS4281")) < 0) {
+		kfree(chip);
+		return err;
 	}
+	chip->ba0_addr = pci_resource_start(pci, 0);
+	chip->ba1_addr = pci_resource_start(pci, 1);
+
 	if (request_irq(pci->irq, snd_cs4281_interrupt, SA_INTERRUPT|SA_SHIRQ, "CS4281", (void *)chip)) {
 		snd_printk(KERN_ERR "unable to grab IRQ %d\n", pci->irq);
 		snd_cs4281_free(chip);
@@ -1448,8 +1423,8 @@
 	}
 	chip->irq = pci->irq;
 
-	chip->ba0 = (unsigned long) ioremap_nocache(chip->ba0_addr, CS4281_BA0_SIZE);
-	chip->ba1 = (unsigned long) ioremap_nocache(chip->ba1_addr, CS4281_BA1_SIZE);
+	chip->ba0 = (unsigned long) ioremap_nocache(chip->ba0_addr, pci_resource_len(pci, 0));
+	chip->ba1 = (unsigned long) ioremap_nocache(chip->ba1_addr, pci_resource_len(pci, 1));
 	if (!chip->ba0 || !chip->ba1) {
 		snd_cs4281_free(chip);
 		return -ENOMEM;
@@ -1713,10 +1688,9 @@
 
 static int snd_cs4281_midi_input_open(snd_rawmidi_substream_t * substream)
 {
-	unsigned long flags;
-	cs4281_t *chip = snd_magic_cast(cs4281_t, substream->rmidi->private_data, return -ENXIO);
+	cs4281_t *chip = substream->rmidi->private_data;
 
-	spin_lock_irqsave(&chip->reg_lock, flags);
+	spin_lock_irq(&chip->reg_lock);
  	chip->midcr |= BA0_MIDCR_RXE;
 	chip->midi_input = substream;
 	if (!(chip->uartm & CS4281_MODE_OUTPUT)) {
@@ -1724,16 +1698,15 @@
 	} else {
 		snd_cs4281_pokeBA0(chip, BA0_MIDCR, chip->midcr);
 	}
-	spin_unlock_irqrestore(&chip->reg_lock, flags);
+	spin_unlock_irq(&chip->reg_lock);
 	return 0;
 }
 
 static int snd_cs4281_midi_input_close(snd_rawmidi_substream_t * substream)
 {
-	unsigned long flags;
-	cs4281_t *chip = snd_magic_cast(cs4281_t, substream->rmidi->private_data, return -ENXIO);
+	cs4281_t *chip = substream->rmidi->private_data;
 
-	spin_lock_irqsave(&chip->reg_lock, flags);
+	spin_lock_irq(&chip->reg_lock);
 	chip->midcr &= ~(BA0_MIDCR_RXE | BA0_MIDCR_RIE);
 	chip->midi_input = NULL;
 	if (!(chip->uartm & CS4281_MODE_OUTPUT)) {
@@ -1742,16 +1715,15 @@
 		snd_cs4281_pokeBA0(chip, BA0_MIDCR, chip->midcr);
 	}
 	chip->uartm &= ~CS4281_MODE_INPUT;
-	spin_unlock_irqrestore(&chip->reg_lock, flags);
+	spin_unlock_irq(&chip->reg_lock);
 	return 0;
 }
 
 static int snd_cs4281_midi_output_open(snd_rawmidi_substream_t * substream)
 {
-	unsigned long flags;
-	cs4281_t *chip = snd_magic_cast(cs4281_t, substream->rmidi->private_data, return -ENXIO);
+	cs4281_t *chip = substream->rmidi->private_data;
 
-	spin_lock_irqsave(&chip->reg_lock, flags);
+	spin_lock_irq(&chip->reg_lock);
 	chip->uartm |= CS4281_MODE_OUTPUT;
 	chip->midcr |= BA0_MIDCR_TXE;
 	chip->midi_output = substream;
@@ -1760,16 +1732,15 @@
 	} else {
 		snd_cs4281_pokeBA0(chip, BA0_MIDCR, chip->midcr);
 	}
-	spin_unlock_irqrestore(&chip->reg_lock, flags);
+	spin_unlock_irq(&chip->reg_lock);
 	return 0;
 }
 
 static int snd_cs4281_midi_output_close(snd_rawmidi_substream_t * substream)
 {
-	unsigned long flags;
-	cs4281_t *chip = snd_magic_cast(cs4281_t, substream->rmidi->private_data, return -ENXIO);
+	cs4281_t *chip = substream->rmidi->private_data;
 
-	spin_lock_irqsave(&chip->reg_lock, flags);
+	spin_lock_irq(&chip->reg_lock);
 	chip->midcr &= ~(BA0_MIDCR_TXE | BA0_MIDCR_TIE);
 	chip->midi_output = NULL;
 	if (!(chip->uartm & CS4281_MODE_INPUT)) {
@@ -1778,14 +1749,14 @@
 		snd_cs4281_pokeBA0(chip, BA0_MIDCR, chip->midcr);
 	}
 	chip->uartm &= ~CS4281_MODE_OUTPUT;
-	spin_unlock_irqrestore(&chip->reg_lock, flags);
+	spin_unlock_irq(&chip->reg_lock);
 	return 0;
 }
 
 static void snd_cs4281_midi_input_trigger(snd_rawmidi_substream_t * substream, int up)
 {
 	unsigned long flags;
-	cs4281_t *chip = snd_magic_cast(cs4281_t, substream->rmidi->private_data, return);
+	cs4281_t *chip = substream->rmidi->private_data;
 
 	spin_lock_irqsave(&chip->reg_lock, flags);
 	if (up) {
@@ -1805,7 +1776,7 @@
 static void snd_cs4281_midi_output_trigger(snd_rawmidi_substream_t * substream, int up)
 {
 	unsigned long flags;
-	cs4281_t *chip = snd_magic_cast(cs4281_t, substream->rmidi->private_data, return);
+	cs4281_t *chip = substream->rmidi->private_data;
 	unsigned char byte;
 
 	spin_lock_irqsave(&chip->reg_lock, flags);
@@ -1872,7 +1843,7 @@
 
 static irqreturn_t snd_cs4281_interrupt(int irq, void *dev_id, struct pt_regs *regs)
 {
-	cs4281_t *chip = snd_magic_cast(cs4281_t, dev_id, return IRQ_NONE);
+	cs4281_t *chip = dev_id;
 	unsigned int status, dma, val;
 	cs4281_dma_t *cdma;
 
@@ -1919,7 +1890,9 @@
 			c = snd_cs4281_peekBA0(chip, BA0_MIDRP);
 			if ((chip->midcr & BA0_MIDCR_RIE) == 0)
 				continue;
+			spin_unlock(&chip->reg_lock);
 			snd_rawmidi_receive(chip->midi_input, &c, 1);
+			spin_lock(&chip->reg_lock);
 		}
 		while ((snd_cs4281_peekBA0(chip, BA0_MIDSR) & BA0_MIDSR_TBF) == 0) {
 			if ((chip->midcr & BA0_MIDCR_TIE) == 0)
@@ -2034,13 +2007,11 @@
 	BA0_PPRVC,
 };
 
-#define number_of(array)	(sizeof(array) / sizeof(array[0]))
-
 #define CLKCR1_CKRA                             0x00010000L
 
 static int cs4281_suspend(snd_card_t *card, unsigned int state)
 {
-	cs4281_t *chip = snd_magic_cast(cs4281_t, card->pm_private_data, return -EINVAL);
+	cs4281_t *chip = card->pm_private_data;
 	u32 ulCLK;
 	unsigned int i;
 
@@ -2059,7 +2030,7 @@
 	snd_cs4281_pokeBA0(chip, BA0_HICR, BA0_HICR_CHGM);
 
 	/* remember the status registers */
-	for (i = 0; i < number_of(saved_regs); i++)
+	for (i = 0; i < ARRAY_SIZE(saved_regs); i++)
 		if (saved_regs[i])
 			chip->suspend_regs[i] = snd_cs4281_peekBA0(chip, saved_regs[i]);
 
@@ -2085,7 +2056,7 @@
 
 static int cs4281_resume(snd_card_t *card, unsigned int state)
 {
-	cs4281_t *chip = snd_magic_cast(cs4281_t, card->pm_private_data, return -EINVAL);
+	cs4281_t *chip = card->pm_private_data;
 	unsigned int i;
 	u32 ulCLK;
 
@@ -2098,7 +2069,7 @@
 	snd_cs4281_chip_init(chip);
 
 	/* restore the status registers */
-	for (i = 0; i < number_of(saved_regs); i++)
+	for (i = 0; i < ARRAY_SIZE(saved_regs); i++)
 		if (saved_regs[i])
 			snd_cs4281_pokeBA0(chip, saved_regs[i], chip->suspend_regs[i]);
 
diff -Nru a/sound/pci/cs46xx/cs46xx.c b/sound/pci/cs46xx/cs46xx.c
--- a/sound/pci/cs46xx/cs46xx.c	2004-10-18 14:57:04 -07:00
+++ b/sound/pci/cs46xx/cs46xx.c	2004-10-18 14:57:04 -07:00
@@ -37,8 +37,7 @@
 MODULE_AUTHOR("Jaroslav Kysela <perex@suse.cz>");
 MODULE_DESCRIPTION("Cirrus Logic Sound Fusion CS46XX");
 MODULE_LICENSE("GPL");
-MODULE_CLASSES("{sound}");
-MODULE_DEVICES("{{Cirrus Logic,Sound Fusion (CS4280)},"
+MODULE_SUPPORTED_DEVICE("{{Cirrus Logic,Sound Fusion (CS4280)},"
 		"{Cirrus Logic,Sound Fusion (CS4610)},"
 		"{Cirrus Logic,Sound Fusion (CS4612)},"
 		"{Cirrus Logic,Sound Fusion (CS4615)},"
@@ -56,22 +55,16 @@
 
 module_param_array(index, int, boot_devs, 0444);
 MODULE_PARM_DESC(index, "Index value for the CS46xx soundcard.");
-MODULE_PARM_SYNTAX(index, SNDRV_INDEX_DESC);
 module_param_array(id, charp, boot_devs, 0444);
 MODULE_PARM_DESC(id, "ID string for the CS46xx soundcard.");
-MODULE_PARM_SYNTAX(id, SNDRV_ID_DESC);
 module_param_array(enable, bool, boot_devs, 0444);
 MODULE_PARM_DESC(enable, "Enable CS46xx soundcard.");
-MODULE_PARM_SYNTAX(enable, SNDRV_ENABLE_DESC);
 module_param_array(external_amp, bool, boot_devs, 0444);
 MODULE_PARM_DESC(external_amp, "Force to enable external amplifer.");
-MODULE_PARM_SYNTAX(external_amp, SNDRV_ENABLED "," SNDRV_BOOLEAN_FALSE_DESC);
 module_param_array(thinkpad, bool, boot_devs, 0444);
 MODULE_PARM_DESC(thinkpad, "Force to enable Thinkpad's CLKRUN control.");
-MODULE_PARM_SYNTAX(thinkpad, SNDRV_ENABLED "," SNDRV_BOOLEAN_FALSE_DESC);
 module_param_array(mmap_valid, bool, boot_devs, 0444);
 MODULE_PARM_DESC(mmap_valid, "Support OSS mmap.");
-MODULE_PARM_SYNTAX(mmap_valid, SNDRV_ENABLED "," SNDRV_BOOLEAN_TRUE_DESC);
 
 static struct pci_device_id snd_cs46xx_ids[] = {
         { 0x1013, 0x6001, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, },   /* CS4280 */
diff -Nru a/sound/pci/cs46xx/cs46xx_lib.c b/sound/pci/cs46xx/cs46xx_lib.c
--- a/sound/pci/cs46xx/cs46xx_lib.c	2004-10-18 14:55:54 -07:00
+++ b/sound/pci/cs46xx/cs46xx_lib.c	2004-10-18 14:55:54 -07:00
@@ -79,6 +79,8 @@
 		     (codec_index == CS46XX_SECONDARY_CODEC_INDEX),
 		     return -EINVAL);
 
+	chip->active_ctrl(chip, 1);
+
 	if (codec_index == CS46XX_SECONDARY_CODEC_INDEX)
 		offset = CS46XX_SECONDARY_CODEC_OFFSET;
 
@@ -184,27 +186,22 @@
 	//snd_cs46xx_peekBA0(chip, BA0_ACCAD);
 	result = snd_cs46xx_peekBA0(chip, BA0_ACSDA + offset);
  end:
+	chip->active_ctrl(chip, -1);
 	return result;
 }
 
 static unsigned short snd_cs46xx_ac97_read(ac97_t * ac97,
 					    unsigned short reg)
 {
-	cs46xx_t *chip = snd_magic_cast(cs46xx_t, ac97->private_data, return -ENXIO);
+	cs46xx_t *chip = ac97->private_data;
 	unsigned short val;
-	int codec_index = -1;
+	int codec_index = ac97->num;
+
+	snd_assert(codec_index == CS46XX_PRIMARY_CODEC_INDEX ||
+		   codec_index == CS46XX_SECONDARY_CODEC_INDEX,
+		   return 0xffff);
 
-	/* UGGLY: nr_ac97_codecs == 0 primery codec detection is in progress */
-	if (ac97 == chip->ac97[CS46XX_PRIMARY_CODEC_INDEX] || chip->nr_ac97_codecs == 0)
-		codec_index = CS46XX_PRIMARY_CODEC_INDEX;
-	/* UGGLY: nr_ac97_codecs == 1 secondary codec detection is in progress */
-	else if (ac97 == chip->ac97[CS46XX_SECONDARY_CODEC_INDEX] || chip->nr_ac97_codecs == 1)
-		codec_index = CS46XX_SECONDARY_CODEC_INDEX;
-	else
-		snd_assert(0, return 0xffff);
-	chip->active_ctrl(chip, 1);
 	val = snd_cs46xx_codec_read(chip, reg, codec_index);
-	chip->active_ctrl(chip, -1);
 
 	/* HACK: voyetra uses EAPD bit in the reverse way.
 	 * we flip the bit to show the mixer status correctly
@@ -227,6 +224,8 @@
 		    (codec_index == CS46XX_SECONDARY_CODEC_INDEX),
 		    return);
 
+	chip->active_ctrl(chip, 1);
+
 	/*
 	 *  1. Write ACCAD = Command Address Register = 46Ch for AC97 register address
 	 *  2. Write ACCDA = Command Data Register = 470h    for data to write to AC97
@@ -271,27 +270,24 @@
 		 *  ACCTL = 460h, DCV should be reset by now and 460h = 07h
 		 */
 		if (!(snd_cs46xx_peekBA0(chip, BA0_ACCTL) & ACCTL_DCV)) {
-			return;
+			goto end;
 		}
 	}
 	snd_printk("AC'97 write problem, codec_index = %d, reg = 0x%x, val = 0x%x\n", codec_index, reg, val);
+ end:
+	chip->active_ctrl(chip, -1);
 }
 
 static void snd_cs46xx_ac97_write(ac97_t *ac97,
 				   unsigned short reg,
 				   unsigned short val)
 {
-	cs46xx_t *chip = snd_magic_cast(cs46xx_t, ac97->private_data, return);
-	int codec_index = -1;
+	cs46xx_t *chip = ac97->private_data;
+	int codec_index = ac97->num;
 
-	/* UGGLY: nr_ac97_codecs == 0 primery codec detection is in progress */
-	if (ac97 == chip->ac97[CS46XX_PRIMARY_CODEC_INDEX] || chip->nr_ac97_codecs == 0)
-		codec_index = CS46XX_PRIMARY_CODEC_INDEX;
-	/* UGGLY: nr_ac97_codecs == 1 secondary codec detection is in progress */
-	else  if (ac97 == chip->ac97[CS46XX_SECONDARY_CODEC_INDEX] || chip->nr_ac97_codecs == 1)
-		codec_index = CS46XX_SECONDARY_CODEC_INDEX;
-	else
-		snd_assert(0,return);
+	snd_assert(codec_index == CS46XX_PRIMARY_CODEC_INDEX ||
+		   codec_index == CS46XX_SECONDARY_CODEC_INDEX,
+		   return);
 
 	/* HACK: voyetra uses EAPD bit in the reverse way.
 	 * we flip the bit to show the mixer status correctly
@@ -299,9 +295,7 @@
 	if (reg == AC97_POWERDOWN && chip->amplifier_ctrl == amp_voyetra)
 		val ^= 0x8000;
 
-	chip->active_ctrl(chip, 1);
 	snd_cs46xx_codec_write(chip, reg, val, codec_index);
-	chip->active_ctrl(chip, -1);
 }
 
 
@@ -688,84 +682,35 @@
  *  PCM part
  */
 
+static void snd_cs46xx_pb_trans_copy(snd_pcm_substream_t *substream,
+				     snd_pcm_indirect_t *rec, size_t bytes)
+{
+	snd_pcm_runtime_t *runtime = substream->runtime;
+	cs46xx_pcm_t * cpcm = runtime->private_data;
+	memcpy(cpcm->hw_buf.area + rec->hw_data, runtime->dma_area + rec->sw_data, bytes);
+}
+
 static int snd_cs46xx_playback_transfer(snd_pcm_substream_t *substream)
 {
-	/* cs46xx_t *chip = snd_pcm_substream_chip(substream); */
 	snd_pcm_runtime_t *runtime = substream->runtime;
-	cs46xx_pcm_t * cpcm = snd_magic_cast(cs46xx_pcm_t, runtime->private_data, return -ENXIO);
-	snd_pcm_uframes_t appl_ptr = runtime->control->appl_ptr;
-	snd_pcm_sframes_t diff = appl_ptr - cpcm->appl_ptr;
-	int buffer_size = runtime->period_size * CS46XX_FRAGS << cpcm->shift;
-
-	if (diff) {
-		if (diff < -(snd_pcm_sframes_t) (runtime->boundary / 2))
-			diff += runtime->boundary;
-		cpcm->sw_ready += diff * (1 << cpcm->shift);
-		cpcm->appl_ptr = appl_ptr;
-	}
-	while (cpcm->hw_ready < buffer_size && 
-	       cpcm->sw_ready > 0) {
-		size_t hw_to_end = buffer_size - cpcm->hw_data;
-		size_t sw_to_end = cpcm->sw_bufsize - cpcm->sw_data;
-		size_t bytes = buffer_size - cpcm->hw_ready;
-		if (cpcm->sw_ready < (int)bytes)
-			bytes = cpcm->sw_ready;
-		if (hw_to_end < bytes)
-			bytes = hw_to_end;
-		if (sw_to_end < bytes)
-			bytes = sw_to_end;
-		memcpy(cpcm->hw_buf.area + cpcm->hw_data,
-		       runtime->dma_area + cpcm->sw_data,
-		       bytes);
-		cpcm->hw_data += bytes;
-		if ((int)cpcm->hw_data == buffer_size)
-			cpcm->hw_data = 0;
-		cpcm->sw_data += bytes;
-		if (cpcm->sw_data == cpcm->sw_bufsize)
-			cpcm->sw_data = 0;
-		cpcm->hw_ready += bytes;
-		cpcm->sw_ready -= bytes;
-	}
+	cs46xx_pcm_t * cpcm = runtime->private_data;
+	snd_pcm_indirect_playback_transfer(substream, &cpcm->pcm_rec, snd_cs46xx_pb_trans_copy);
 	return 0;
 }
 
-static int snd_cs46xx_capture_transfer(snd_pcm_substream_t *substream)
+static void snd_cs46xx_cp_trans_copy(snd_pcm_substream_t *substream,
+				     snd_pcm_indirect_t *rec, size_t bytes)
 {
 	cs46xx_t *chip = snd_pcm_substream_chip(substream);
 	snd_pcm_runtime_t *runtime = substream->runtime;
-	snd_pcm_uframes_t appl_ptr = runtime->control->appl_ptr;
-	snd_pcm_sframes_t diff = appl_ptr - chip->capt.appl_ptr;
-	int buffer_size = runtime->period_size * CS46XX_FRAGS << chip->capt.shift;
-
-	if (diff) {
-		if (diff < -(snd_pcm_sframes_t) (runtime->boundary / 2))
-			diff += runtime->boundary;
-		chip->capt.sw_ready -= diff * (1 << chip->capt.shift);
-		chip->capt.appl_ptr = appl_ptr;
-	}
-	while (chip->capt.hw_ready > 0 && 
-	       chip->capt.sw_ready < (int)chip->capt.sw_bufsize) {
-		size_t hw_to_end = buffer_size - chip->capt.hw_data;
-		size_t sw_to_end = chip->capt.sw_bufsize - chip->capt.sw_data;
-		size_t bytes = chip->capt.sw_bufsize - chip->capt.sw_ready;
-		if (chip->capt.hw_ready < (int)bytes)
-			bytes = chip->capt.hw_ready;
-		if (hw_to_end < bytes)
-			bytes = hw_to_end;
-		if (sw_to_end < bytes)
-			bytes = sw_to_end;
-		memcpy(runtime->dma_area + chip->capt.sw_data,
-		       chip->capt.hw_buf.area + chip->capt.hw_data,
-		       bytes);
-		chip->capt.hw_data += bytes;
-		if ((int)chip->capt.hw_data == buffer_size)
-			chip->capt.hw_data = 0;
-		chip->capt.sw_data += bytes;
-		if (chip->capt.sw_data == chip->capt.sw_bufsize)
-			chip->capt.sw_data = 0;
-		chip->capt.hw_ready -= bytes;
-		chip->capt.sw_ready += bytes;
-	}
+	memcpy(runtime->dma_area + rec->sw_data,
+	       chip->capt.hw_buf.area + rec->hw_data, bytes);
+}
+
+static int snd_cs46xx_capture_transfer(snd_pcm_substream_t *substream)
+{
+	cs46xx_t *chip = snd_pcm_substream_chip(substream);
+	snd_pcm_indirect_capture_transfer(substream, &chip->capt.pcm_rec, snd_cs46xx_cp_trans_copy);
 	return 0;
 }
 
@@ -773,7 +718,7 @@
 {
 	cs46xx_t *chip = snd_pcm_substream_chip(substream);
 	size_t ptr;
-	cs46xx_pcm_t *cpcm = snd_magic_cast(cs46xx_pcm_t, substream->runtime->private_data, return -ENXIO);
+	cs46xx_pcm_t *cpcm = substream->runtime->private_data;
 	snd_assert (cpcm->pcm_channel,return -ENXIO);
 
 #ifdef CONFIG_SND_CS46XX_NEW_DSP
@@ -789,9 +734,7 @@
 {
 	cs46xx_t *chip = snd_pcm_substream_chip(substream);
 	size_t ptr;
-	cs46xx_pcm_t *cpcm = snd_magic_cast(cs46xx_pcm_t, substream->runtime->private_data, return -ENXIO);
-	ssize_t bytes;
-	int buffer_size = substream->runtime->period_size * CS46XX_FRAGS << cpcm->shift;
+	cs46xx_pcm_t *cpcm = substream->runtime->private_data;
 
 #ifdef CONFIG_SND_CS46XX_NEW_DSP
 	snd_assert (cpcm->pcm_channel,return -ENXIO);
@@ -800,18 +743,7 @@
 	ptr = snd_cs46xx_peek(chip, BA1_PBA);
 #endif
 	ptr -= cpcm->hw_buf.addr;
-
-	bytes = ptr - cpcm->hw_io;
-
-	if (bytes < 0)
-		bytes += buffer_size;
-	cpcm->hw_io = ptr;
-	cpcm->hw_ready -= bytes;
-	cpcm->sw_io += bytes;
-	if (cpcm->sw_io >= cpcm->sw_bufsize)
-		cpcm->sw_io -= cpcm->sw_bufsize;
-	snd_cs46xx_playback_transfer(substream);
-	return cpcm->sw_io >> cpcm->shift;
+	return snd_pcm_indirect_playback_pointer(substream, &cpcm->pcm_rec, ptr);
 }
 
 static snd_pcm_uframes_t snd_cs46xx_capture_direct_pointer(snd_pcm_substream_t * substream)
@@ -825,18 +757,7 @@
 {
 	cs46xx_t *chip = snd_pcm_substream_chip(substream);
 	size_t ptr = snd_cs46xx_peek(chip, BA1_CBA) - chip->capt.hw_buf.addr;
-	ssize_t bytes = ptr - chip->capt.hw_io;
-	int buffer_size = substream->runtime->period_size * CS46XX_FRAGS << chip->capt.shift;
-
-	if (bytes < 0)
-		bytes += buffer_size;
-	chip->capt.hw_io = ptr;
-	chip->capt.hw_ready += bytes;
-	chip->capt.sw_io += bytes;
-	if (chip->capt.sw_io >= chip->capt.sw_bufsize)
-		chip->capt.sw_io -= chip->capt.sw_bufsize;
-	snd_cs46xx_capture_transfer(substream);
-	return chip->capt.sw_io >> chip->capt.shift;
+	return snd_pcm_indirect_capture_pointer(substream, &chip->capt.pcm_rec, ptr);
 }
 
 static int snd_cs46xx_playback_trigger(snd_pcm_substream_t * substream,
@@ -847,13 +768,7 @@
 	int result = 0;
 
 #ifdef CONFIG_SND_CS46XX_NEW_DSP
-	cs46xx_pcm_t *cpcm = snd_magic_cast(cs46xx_pcm_t, substream->runtime->private_data, return -ENXIO);
-#else
-	spin_lock(&chip->reg_lock);
-#endif
-
-#ifdef CONFIG_SND_CS46XX_NEW_DSP
-
+	cs46xx_pcm_t *cpcm = substream->runtime->private_data;
 	if (! cpcm->pcm_channel) {
 		return -ENXIO;
 	}
@@ -872,6 +787,7 @@
 		if (substream->runtime->periods != CS46XX_FRAGS)
 			snd_cs46xx_playback_transfer(substream);
 #else
+		spin_lock(&chip->reg_lock);
 		if (substream->runtime->periods != CS46XX_FRAGS)
 			snd_cs46xx_playback_transfer(substream);
 		{ unsigned int tmp;
@@ -879,6 +795,7 @@
 		tmp &= 0x0000ffff;
 		snd_cs46xx_poke(chip, BA1_PCTL, chip->play_ctl | tmp);
 		}
+		spin_unlock(&chip->reg_lock);
 #endif
 		break;
 	case SNDRV_PCM_TRIGGER_STOP:
@@ -891,11 +808,13 @@
 		if (!cpcm->pcm_channel->unlinked)
 			cs46xx_dsp_pcm_unlink(chip,cpcm->pcm_channel);
 #else
+		spin_lock(&chip->reg_lock);
 		{ unsigned int tmp;
 		tmp = snd_cs46xx_peek(chip, BA1_PCTL);
 		tmp &= 0x0000ffff;
 		snd_cs46xx_poke(chip, BA1_PCTL, tmp);
 		}
+		spin_unlock(&chip->reg_lock);
 #endif
 		break;
 	default:
@@ -903,10 +822,6 @@
 		break;
 	}
 
-#ifndef CONFIG_SND_CS46XX_NEW_DSP
-	spin_unlock(&chip->reg_lock);
-#endif
-
 	return result;
 }
 
@@ -987,7 +902,7 @@
 	int sample_rate = params_rate(hw_params);
 	int period_size = params_period_bytes(hw_params);
 #endif
-	cpcm = snd_magic_cast(cs46xx_pcm_t, runtime->private_data, return -ENXIO);
+	cpcm = runtime->private_data;
 
 #ifdef CONFIG_SND_CS46XX_NEW_DSP
 	snd_assert (sample_rate != 0, return -ENXIO);
@@ -1084,7 +999,7 @@
 	snd_pcm_runtime_t *runtime = substream->runtime;
 	cs46xx_pcm_t *cpcm;
 
-	cpcm = snd_magic_cast(cs46xx_pcm_t, runtime->private_data, return -ENXIO);
+	cpcm = runtime->private_data;
 
 	/* if play_back open fails, then this function
 	   is called and cpcm can actually be NULL here */
@@ -1108,7 +1023,7 @@
 	snd_pcm_runtime_t *runtime = substream->runtime;
 	cs46xx_pcm_t *cpcm;
 
-	cpcm = snd_magic_cast(cs46xx_pcm_t, runtime->private_data, return -ENXIO);
+	cpcm = runtime->private_data;
 
 #ifdef CONFIG_SND_CS46XX_NEW_DSP
     snd_assert (cpcm->pcm_channel != NULL, return -ENXIO);
@@ -1143,10 +1058,9 @@
 			pfie |= 0x00004000;
 	}
 	
-	cpcm->sw_bufsize = snd_pcm_lib_buffer_bytes(substream);
-	cpcm->sw_data = cpcm->sw_io = cpcm->sw_ready = 0;
-	cpcm->hw_data = cpcm->hw_io = cpcm->hw_ready = 0;
-	cpcm->appl_ptr = 0;
+	memset(&cpcm->pcm_rec, 0, sizeof(cpcm->pcm_rec));
+	cpcm->pcm_rec.sw_buffer_size = snd_pcm_lib_buffer_bytes(substream);
+	cpcm->pcm_rec.hw_buffer_size = runtime->period_size * CS46XX_FRAGS << cpcm->shift;
 
 #ifdef CONFIG_SND_CS46XX_NEW_DSP
 
@@ -1223,10 +1137,9 @@
 
 	snd_cs46xx_poke(chip, BA1_CBA, chip->capt.hw_buf.addr);
 	chip->capt.shift = 2;
-	chip->capt.sw_bufsize = snd_pcm_lib_buffer_bytes(substream);
-	chip->capt.sw_data = chip->capt.sw_io = chip->capt.sw_ready = 0;
-	chip->capt.hw_data = chip->capt.hw_io = chip->capt.hw_ready = 0;
-	chip->capt.appl_ptr = 0;
+	memset(&chip->capt.pcm_rec, 0, sizeof(chip->capt.pcm_rec));
+	chip->capt.pcm_rec.sw_buffer_size = snd_pcm_lib_buffer_bytes(substream);
+	chip->capt.pcm_rec.hw_buffer_size = runtime->period_size * CS46XX_FRAGS << 2;
 	snd_cs46xx_set_capture_sample_rate(chip, runtime->rate);
 
 	return 0;
@@ -1234,7 +1147,7 @@
 
 static irqreturn_t snd_cs46xx_interrupt(int irq, void *dev_id, struct pt_regs *regs)
 {
-	cs46xx_t *chip = snd_magic_cast(cs46xx_t, dev_id, return IRQ_NONE);
+	cs46xx_t *chip = dev_id;
 	u32 status1;
 #ifdef CONFIG_SND_CS46XX_NEW_DSP
 	dsp_spos_instance_t * ins = chip->dsp_spos_instance;
@@ -1265,7 +1178,7 @@
 					if (ins->pcm_channels[i].active &&
 					    ins->pcm_channels[i].private_data &&
 					    !ins->pcm_channels[i].unlinked) {
-						cpcm = snd_magic_cast(cs46xx_pcm_t, ins->pcm_channels[i].private_data, continue);
+						cpcm = ins->pcm_channels[i].private_data;
 						snd_pcm_period_elapsed(cpcm->substream);
 					}
 				}
@@ -1275,7 +1188,7 @@
 				if (ins->pcm_channels[i].active && 
 				    ins->pcm_channels[i].private_data &&
 				    !ins->pcm_channels[i].unlinked) {
-					cpcm = snd_magic_cast(cs46xx_pcm_t, ins->pcm_channels[i].private_data, continue);
+					cpcm = ins->pcm_channels[i].private_data;
 					snd_pcm_period_elapsed(cpcm->substream);
 				}
 			}
@@ -1302,7 +1215,9 @@
 			c = snd_cs46xx_peekBA0(chip, BA0_MIDRP);
 			if ((chip->midcr & MIDCR_RIE) == 0)
 				continue;
+			spin_unlock(&chip->reg_lock);
 			snd_rawmidi_receive(chip->midi_input, &c, 1);
+			spin_lock(&chip->reg_lock);
 		}
 		while ((snd_cs46xx_peekBA0(chip, BA0_MIDSR) & MIDSR_TBF) == 0) {
 			if ((chip->midcr & MIDCR_TIE) == 0)
@@ -1370,10 +1285,8 @@
 
 static unsigned int period_sizes[] = { 32, 64, 128, 256, 512, 1024, 2048 };
 
-#define PERIOD_SIZES sizeof(period_sizes) / sizeof(period_sizes[0])
-
 static snd_pcm_hw_constraint_list_t hw_constraints_period_sizes = {
-	.count = PERIOD_SIZES,
+	.count = ARRAY_SIZE(period_sizes),
 	.list = period_sizes,
 	.mask = 0
 };
@@ -1382,10 +1295,8 @@
 
 static void snd_cs46xx_pcm_free_substream(snd_pcm_runtime_t *runtime)
 {
-	cs46xx_pcm_t * cpcm = snd_magic_cast(cs46xx_pcm_t, runtime->private_data, return);
-	
-	if (cpcm)
-		snd_magic_kfree(cpcm);
+	cs46xx_pcm_t * cpcm = runtime->private_data;
+	kfree(cpcm);
 }
 
 static int _cs46xx_playback_open_channel (snd_pcm_substream_t * substream,int pcm_channel_id)
@@ -1394,11 +1305,12 @@
 	cs46xx_pcm_t * cpcm;
 	snd_pcm_runtime_t *runtime = substream->runtime;
 
-	cpcm = snd_magic_kcalloc(cs46xx_pcm_t, 0, GFP_KERNEL);
+	cpcm = kcalloc(1, sizeof(*cpcm), GFP_KERNEL);
 	if (cpcm == NULL)
 		return -ENOMEM;
-	if (snd_dma_alloc_pages(&chip->dma_dev, PAGE_SIZE, &cpcm->hw_buf) < 0) {
-		snd_magic_kfree(cpcm);
+	if (snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, snd_dma_pci_data(chip->pci),
+				PAGE_SIZE, &cpcm->hw_buf) < 0) {
+		kfree(cpcm);
 		return -ENOMEM;
 	}
 
@@ -1486,7 +1398,8 @@
 {
 	cs46xx_t *chip = snd_pcm_substream_chip(substream);
 
-	if (snd_dma_alloc_pages(&chip->dma_dev, PAGE_SIZE, &chip->capt.hw_buf) < 0)
+	if (snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, snd_dma_pci_data(chip->pci),
+				PAGE_SIZE, &chip->capt.hw_buf) < 0)
 		return -ENOMEM;
 	chip->capt.substream = substream;
 	substream->runtime->hw = snd_cs46xx_capture;
@@ -1510,7 +1423,7 @@
 	snd_pcm_runtime_t *runtime = substream->runtime;
 	cs46xx_pcm_t * cpcm;
 
-	cpcm = snd_magic_cast(cs46xx_pcm_t, runtime->private_data, return -ENXIO);
+	cpcm = runtime->private_data;
 
 	/* when playback_open fails, then cpcm can be NULL */
 	if (!cpcm) return -ENXIO;
@@ -1527,7 +1440,7 @@
 #endif
 
 	cpcm->substream = NULL;
-	snd_dma_free_pages(&chip->dma_dev, &cpcm->hw_buf);
+	snd_dma_free_pages(&cpcm->hw_buf);
 	chip->active_ctrl(chip, -1);
 
 	return 0;
@@ -1538,7 +1451,7 @@
 	cs46xx_t *chip = snd_pcm_substream_chip(substream);
 
 	chip->capt.substream = NULL;
-	snd_dma_free_pages(&chip->dma_dev, &chip->capt.hw_buf);
+	snd_dma_free_pages(&chip->capt.hw_buf);
 	chip->active_ctrl(chip, -1);
 
 	return 0;
@@ -1664,7 +1577,7 @@
 
 static void snd_cs46xx_pcm_free(snd_pcm_t *pcm)
 {
-	cs46xx_t *chip = snd_magic_cast(cs46xx_t, pcm->private_data, return);
+	cs46xx_t *chip = pcm->private_data;
 	chip->pcm = NULL;
 	snd_pcm_lib_preallocate_free_for_all(pcm);
 }
@@ -1672,21 +1585,21 @@
 #ifdef CONFIG_SND_CS46XX_NEW_DSP
 static void snd_cs46xx_pcm_rear_free(snd_pcm_t *pcm)
 {
-	cs46xx_t *chip = snd_magic_cast(cs46xx_t, pcm->private_data, return);
+	cs46xx_t *chip = pcm->private_data;
 	chip->pcm_rear = NULL;
 	snd_pcm_lib_preallocate_free_for_all(pcm);
 }
 
 static void snd_cs46xx_pcm_center_lfe_free(snd_pcm_t *pcm)
 {
-	cs46xx_t *chip = snd_magic_cast(cs46xx_t, pcm->private_data, return);
+	cs46xx_t *chip = pcm->private_data;
 	chip->pcm_center_lfe = NULL;
 	snd_pcm_lib_preallocate_free_for_all(pcm);
 }
 
 static void snd_cs46xx_pcm_iec958_free(snd_pcm_t *pcm)
 {
-	cs46xx_t *chip = snd_magic_cast(cs46xx_t, pcm->private_data, return);
+	cs46xx_t *chip = pcm->private_data;
 	chip->pcm_iec958 = NULL;
 	snd_pcm_lib_preallocate_free_for_all(pcm);
 }
@@ -1824,14 +1737,14 @@
  */
 static void snd_cs46xx_mixer_free_ac97_bus(ac97_bus_t *bus)
 {
-	cs46xx_t *chip = snd_magic_cast(cs46xx_t, bus->private_data, return);
+	cs46xx_t *chip = bus->private_data;
 
 	chip->ac97_bus = NULL;
 }
 
 static void snd_cs46xx_mixer_free_ac97(ac97_t *ac97)
 {
-	cs46xx_t *chip = snd_magic_cast(cs46xx_t, ac97->private_data, return);
+	cs46xx_t *chip = ac97->private_data;
 
 	snd_assert ((ac97 == chip->ac97[CS46XX_PRIMARY_CODEC_INDEX]) ||
 		    (ac97 == chip->ac97[CS46XX_SECONDARY_CODEC_INDEX]),
@@ -2420,7 +2333,7 @@
 {
 	unsigned long end_time;
 	int err;
-	cs46xx_t * chip = snd_magic_cast(cs46xx_t,ac97->private_data,return /* -ENXIO */);
+	cs46xx_t * chip = ac97->private_data;
 
 	/* reset to defaults */
 	snd_ac97_write(ac97, AC97_RESET, 0);	
@@ -2470,39 +2383,38 @@
 int __devinit snd_cs46xx_mixer(cs46xx_t *chip)
 {
 	snd_card_t *card = chip->card;
-	ac97_bus_t bus;
-	ac97_t ac97;
+	ac97_template_t ac97;
 	snd_ctl_elem_id_t id;
 	int err;
 	unsigned int idx;
+	static ac97_bus_ops_t ops = {
+#ifdef CONFIG_SND_CS46XX_NEW_DSP
+		.reset = snd_cs46xx_codec_reset,
+#endif
+		.write = snd_cs46xx_ac97_write,
+		.read = snd_cs46xx_ac97_read,
+	};
 
 	/* detect primary codec */
 	chip->nr_ac97_codecs = 0;
 	snd_printdd("snd_cs46xx: detecting primary codec\n");
-	memset(&bus, 0, sizeof(bus));
-	bus.write = snd_cs46xx_ac97_write;
-	bus.read = snd_cs46xx_ac97_read;
-#ifdef CONFIG_SND_CS46XX_NEW_DSP
-	bus.reset = snd_cs46xx_codec_reset;
-#endif
-	bus.private_data = chip;
-	bus.private_free = snd_cs46xx_mixer_free_ac97_bus;
-	if ((err = snd_ac97_bus(card, &bus, &chip->ac97_bus)) < 0)
+	if ((err = snd_ac97_bus(card, 0, &ops, chip, &chip->ac97_bus)) < 0)
 		return err;
+	chip->ac97_bus->private_free = snd_cs46xx_mixer_free_ac97_bus;
 
 	memset(&ac97, 0, sizeof(ac97));
 	ac97.private_data = chip;
 	ac97.private_free = snd_cs46xx_mixer_free_ac97;
-	chip->ac97[CS46XX_PRIMARY_CODEC_INDEX] = &ac97;
 
-	snd_cs46xx_ac97_write(&ac97, AC97_MASTER, 0x8000);
+	snd_cs46xx_codec_write(chip, AC97_MASTER, 0x8000,
+			       CS46XX_PRIMARY_CODEC_INDEX);
 	for (idx = 0; idx < 100; ++idx) {
-		if (snd_cs46xx_ac97_read(&ac97, AC97_MASTER) == 0x8000)
+		if (snd_cs46xx_codec_read(chip, AC97_MASTER,
+					  CS46XX_PRIMARY_CODEC_INDEX) == 0x8000)
 			goto _ok;
 		set_current_state(TASK_INTERRUPTIBLE);
 		schedule_timeout(HZ/100);
 	}
-	chip->ac97[CS46XX_PRIMARY_CODEC_INDEX] = NULL;
 	return -ENXIO;
 
  _ok:
@@ -2519,18 +2431,21 @@
 	ac97.private_free = snd_cs46xx_mixer_free_ac97;
 	ac97.num = CS46XX_SECONDARY_CODEC_INDEX;
 
-	snd_cs46xx_ac97_write(&ac97, AC97_RESET, 0);
+	snd_cs46xx_codec_write(chip, AC97_RESET, 0,
+			       CS46XX_SECONDARY_CODEC_INDEX);
 	udelay(10);
 
-	if (snd_cs46xx_ac97_read(&ac97, AC97_RESET) & 0x8000) {
+	if (snd_cs46xx_codec_read(chip, AC97_RESET,
+				  CS46XX_SECONDARY_CODEC_INDEX) & 0x8000) {
 		snd_printdd("snd_cs46xx: seconadry codec not present\n");
 		goto _no_sec_codec;
 	}
 
-	chip->ac97[CS46XX_SECONDARY_CODEC_INDEX] = &ac97;
-	snd_cs46xx_ac97_write(&ac97, AC97_MASTER, 0x8000);
+	snd_cs46xx_codec_write(chip, AC97_MASTER, 0x8000,
+			       CS46XX_SECONDARY_CODEC_INDEX);
 	for (idx = 0; idx < 100; ++idx) {
-		if (snd_cs46xx_ac97_read(&ac97, AC97_MASTER) == 0x8000) {
+		if (snd_cs46xx_codec_read(chip, AC97_MASTER,
+					  CS46XX_SECONDARY_CODEC_INDEX) == 0x8000) {
 			goto _ok2;
 		}
 		set_current_state(TASK_INTERRUPTIBLE);
@@ -2540,7 +2455,6 @@
  _no_sec_codec:
 	snd_printdd("snd_cs46xx: secondary codec did not respond ...\n");
 
-	chip->ac97[CS46XX_SECONDARY_CODEC_INDEX] = NULL;
 	chip->nr_ac97_codecs = 1;
     
 	/* well, one codec only ... */
@@ -2605,11 +2519,10 @@
 
 static int snd_cs46xx_midi_input_open(snd_rawmidi_substream_t * substream)
 {
-	unsigned long flags;
-	cs46xx_t *chip = snd_magic_cast(cs46xx_t, substream->rmidi->private_data, return -ENXIO);
+	cs46xx_t *chip = substream->rmidi->private_data;
 
 	chip->active_ctrl(chip, 1);
-	spin_lock_irqsave(&chip->reg_lock, flags);
+	spin_lock_irq(&chip->reg_lock);
 	chip->uartm |= CS46XX_MODE_INPUT;
 	chip->midcr |= MIDCR_RXE;
 	chip->midi_input = substream;
@@ -2618,16 +2531,15 @@
 	} else {
 		snd_cs46xx_pokeBA0(chip, BA0_MIDCR, chip->midcr);
 	}
-	spin_unlock_irqrestore(&chip->reg_lock, flags);
+	spin_unlock_irq(&chip->reg_lock);
 	return 0;
 }
 
 static int snd_cs46xx_midi_input_close(snd_rawmidi_substream_t * substream)
 {
-	unsigned long flags;
-	cs46xx_t *chip = snd_magic_cast(cs46xx_t, substream->rmidi->private_data, return -ENXIO);
+	cs46xx_t *chip = substream->rmidi->private_data;
 
-	spin_lock_irqsave(&chip->reg_lock, flags);
+	spin_lock_irq(&chip->reg_lock);
 	chip->midcr &= ~(MIDCR_RXE | MIDCR_RIE);
 	chip->midi_input = NULL;
 	if (!(chip->uartm & CS46XX_MODE_OUTPUT)) {
@@ -2636,19 +2548,18 @@
 		snd_cs46xx_pokeBA0(chip, BA0_MIDCR, chip->midcr);
 	}
 	chip->uartm &= ~CS46XX_MODE_INPUT;
-	spin_unlock_irqrestore(&chip->reg_lock, flags);
+	spin_unlock_irq(&chip->reg_lock);
 	chip->active_ctrl(chip, -1);
 	return 0;
 }
 
 static int snd_cs46xx_midi_output_open(snd_rawmidi_substream_t * substream)
 {
-	unsigned long flags;
-	cs46xx_t *chip = snd_magic_cast(cs46xx_t, substream->rmidi->private_data, return -ENXIO);
+	cs46xx_t *chip = substream->rmidi->private_data;
 
 	chip->active_ctrl(chip, 1);
 
-	spin_lock_irqsave(&chip->reg_lock, flags);
+	spin_lock_irq(&chip->reg_lock);
 	chip->uartm |= CS46XX_MODE_OUTPUT;
 	chip->midcr |= MIDCR_TXE;
 	chip->midi_output = substream;
@@ -2657,16 +2568,15 @@
 	} else {
 		snd_cs46xx_pokeBA0(chip, BA0_MIDCR, chip->midcr);
 	}
-	spin_unlock_irqrestore(&chip->reg_lock, flags);
+	spin_unlock_irq(&chip->reg_lock);
 	return 0;
 }
 
 static int snd_cs46xx_midi_output_close(snd_rawmidi_substream_t * substream)
 {
-	unsigned long flags;
-	cs46xx_t *chip = snd_magic_cast(cs46xx_t, substream->rmidi->private_data, return -ENXIO);
+	cs46xx_t *chip = substream->rmidi->private_data;
 
-	spin_lock_irqsave(&chip->reg_lock, flags);
+	spin_lock_irq(&chip->reg_lock);
 	chip->midcr &= ~(MIDCR_TXE | MIDCR_TIE);
 	chip->midi_output = NULL;
 	if (!(chip->uartm & CS46XX_MODE_INPUT)) {
@@ -2675,7 +2585,7 @@
 		snd_cs46xx_pokeBA0(chip, BA0_MIDCR, chip->midcr);
 	}
 	chip->uartm &= ~CS46XX_MODE_OUTPUT;
-	spin_unlock_irqrestore(&chip->reg_lock, flags);
+	spin_unlock_irq(&chip->reg_lock);
 	chip->active_ctrl(chip, -1);
 	return 0;
 }
@@ -2683,7 +2593,7 @@
 static void snd_cs46xx_midi_input_trigger(snd_rawmidi_substream_t * substream, int up)
 {
 	unsigned long flags;
-	cs46xx_t *chip = snd_magic_cast(cs46xx_t, substream->rmidi->private_data, return);
+	cs46xx_t *chip = substream->rmidi->private_data;
 
 	spin_lock_irqsave(&chip->reg_lock, flags);
 	if (up) {
@@ -2703,7 +2613,7 @@
 static void snd_cs46xx_midi_output_trigger(snd_rawmidi_substream_t * substream, int up)
 {
 	unsigned long flags;
-	cs46xx_t *chip = snd_magic_cast(cs46xx_t, substream->rmidi->private_data, return);
+	cs46xx_t *chip = substream->rmidi->private_data;
 	unsigned char byte;
 
 	spin_lock_irqsave(&chip->reg_lock, flags);
@@ -2781,7 +2691,7 @@
 	cs46xx_gameport_t *gp = (cs46xx_gameport_t *)gameport;
 	cs46xx_t *chip;
 	snd_assert(gp, return);
-	chip = snd_magic_cast(cs46xx_t, gp->chip, return);
+	chip = gp->chip;
 	snd_cs46xx_pokeBA0(chip, BA0_JSPT, 0xFF);  //outb(gameport->io, 0xFF);
 }
 
@@ -2790,7 +2700,7 @@
 	cs46xx_gameport_t *gp = (cs46xx_gameport_t *)gameport;
 	cs46xx_t *chip;
 	snd_assert(gp, return 0);
-	chip = snd_magic_cast(cs46xx_t, gp->chip, return 0);
+	chip = gp->chip;
 	return snd_cs46xx_peekBA0(chip, BA0_JSPT); //inb(gameport->io);
 }
 
@@ -2801,7 +2711,7 @@
 	unsigned js1, js2, jst;
 	
 	snd_assert(gp, return 0);
-	chip = snd_magic_cast(cs46xx_t, gp->chip, return 0);
+	chip = gp->chip;
 
 	js1 = snd_cs46xx_peekBA0(chip, BA0_JSC1);
 	js2 = snd_cs46xx_peekBA0(chip, BA0_JSC2);
@@ -3011,13 +2921,13 @@
 	}
 #endif
 	
-	snd_magic_kfree(chip);
+	kfree(chip);
 	return 0;
 }
 
 static int snd_cs46xx_dev_free(snd_device_t *device)
 {
-	cs46xx_t *chip = snd_magic_cast(cs46xx_t, device->device_data, return -ENXIO);
+	cs46xx_t *chip = device->device_data;
 	return snd_cs46xx_free(chip);
 }
 
@@ -3786,7 +3696,7 @@
 #ifdef CONFIG_PM
 static int snd_cs46xx_suspend(snd_card_t *card, unsigned int state)
 {
-	cs46xx_t *chip = snd_magic_cast(cs46xx_t, card->pm_private_data, return -EINVAL);
+	cs46xx_t *chip = card->pm_private_data;
 	int amp_saved;
 
 	snd_pcm_suspend_all(chip->pcm);
@@ -3810,7 +3720,7 @@
 
 static int snd_cs46xx_resume(snd_card_t *card, unsigned int state)
 {
-	cs46xx_t *chip = snd_magic_cast(cs46xx_t, card->pm_private_data, return -EINVAL);
+	cs46xx_t *chip = card->pm_private_data;
 	int amp_saved;
 
 	pci_enable_device(chip->pci);
@@ -3869,7 +3779,7 @@
 	if ((err = pci_enable_device(pci)) < 0)
 		return err;
 
-	chip = snd_magic_kcalloc(cs46xx_t, 0, GFP_KERNEL);
+	chip = kcalloc(1, sizeof(*chip), GFP_KERNEL);
 	if (chip == NULL)
 		return -ENOMEM;
 	spin_lock_init(&chip->reg_lock);
@@ -3912,10 +3822,6 @@
 	strcpy(region->name, "CS46xx_BA1_reg");
 	region->base = chip->ba1_addr + BA1_SP_REG;
 	region->size = CS46XX_BA1_REG_SIZE;
-
-	memset(&chip->dma_dev, 0, sizeof(chip->dma_dev));
-	chip->dma_dev.type = SNDRV_DMA_TYPE_DEV;
-	chip->dma_dev.dev = snd_dma_pci_data(pci);
 
 	/* set up amp and clkrun hack */
 	pci_read_config_word(pci, PCI_SUBSYSTEM_VENDOR_ID, &ss_vendor);
diff -Nru a/sound/pci/cs46xx/cs46xx_lib.h b/sound/pci/cs46xx/cs46xx_lib.h
--- a/sound/pci/cs46xx/cs46xx_lib.h	2004-10-18 14:56:11 -07:00
+++ b/sound/pci/cs46xx/cs46xx_lib.h	2004-10-18 14:56:11 -07:00
@@ -22,8 +22,6 @@
 #ifndef __CS46XX_LIB_H__
 #define __CS46XX_LIB_H__
 
-#define chip_t cs46xx_t
-
 /*
  *  constants
  */
diff -Nru a/sound/pci/cs46xx/dsp_spos.c b/sound/pci/cs46xx/dsp_spos.c
--- a/sound/pci/cs46xx/dsp_spos.c	2004-10-18 14:56:50 -07:00
+++ b/sound/pci/cs46xx/dsp_spos.c	2004-10-18 14:56:50 -07:00
@@ -74,7 +74,7 @@
 			    (mop_operands & WIDE_LADD_INSTR_MASK) == 0 &&
 			    (mop_operands & WIDE_INSTR_MASK) != 0) {
 				wide_op = loval & 0x7f;
-				for (j = 0;j < sizeof(wide_opcodes) / sizeof(wide_opcode_t); ++j) {
+				for (j = 0;j < ARRAY_SIZE(wide_opcodes); ++j) {
 					if (wide_opcodes[j] == wide_op) {
 						/* need to reallocate instruction */
 						address  = (hival & 0x00FFF) << 5;
@@ -462,7 +462,7 @@
 
 static void cs46xx_dsp_proc_symbol_table_read (snd_info_entry_t *entry, snd_info_buffer_t * buffer)
 {
-	cs46xx_t *chip = snd_magic_cast(cs46xx_t, entry->private_data, return);
+	cs46xx_t *chip = entry->private_data;
 	dsp_spos_instance_t * ins = chip->dsp_spos_instance;
 	int i;
 
@@ -489,7 +489,7 @@
 
 static void cs46xx_dsp_proc_modules_read (snd_info_entry_t *entry, snd_info_buffer_t * buffer)
 {
-	cs46xx_t *chip = snd_magic_cast(cs46xx_t, entry->private_data, return);
+	cs46xx_t *chip = entry->private_data;
 	dsp_spos_instance_t * ins = chip->dsp_spos_instance;
 	int i,j;
 
@@ -511,7 +511,7 @@
 
 static void cs46xx_dsp_proc_task_tree_read (snd_info_entry_t *entry, snd_info_buffer_t * buffer)
 {
-	cs46xx_t *chip = snd_magic_cast(cs46xx_t, entry->private_data, return);
+	cs46xx_t *chip = entry->private_data;
 	dsp_spos_instance_t * ins = chip->dsp_spos_instance;
 	int i,j,col;
 	unsigned long dst = chip->region.idx[1].remap_addr + DSP_PARAMETER_BYTE_OFFSET;
@@ -538,7 +538,7 @@
 
 static void cs46xx_dsp_proc_scb_read (snd_info_entry_t *entry, snd_info_buffer_t * buffer)
 {
-	cs46xx_t *chip = snd_magic_cast(cs46xx_t, entry->private_data, return);
+	cs46xx_t *chip = entry->private_data;
 	dsp_spos_instance_t * ins = chip->dsp_spos_instance;
 	int i;
 
@@ -570,7 +570,7 @@
 
 static void cs46xx_dsp_proc_parameter_dump_read (snd_info_entry_t *entry, snd_info_buffer_t * buffer)
 {
-	cs46xx_t *chip = snd_magic_cast(cs46xx_t, entry->private_data, return);
+	cs46xx_t *chip = entry->private_data;
 	/*dsp_spos_instance_t * ins = chip->dsp_spos_instance; */
 	unsigned int i,col = 0;
 	unsigned long dst = chip->region.idx[1].remap_addr + DSP_PARAMETER_BYTE_OFFSET;
@@ -597,7 +597,7 @@
 
 static void cs46xx_dsp_proc_sample_dump_read (snd_info_entry_t *entry, snd_info_buffer_t * buffer)
 {
-	cs46xx_t *chip = snd_magic_cast(cs46xx_t, entry->private_data, return);
+	cs46xx_t *chip = entry->private_data;
 	int i,col = 0;
 	unsigned long dst = chip->region.idx[2].remap_addr;
 
@@ -1057,7 +1057,7 @@
 	
 	int fifo_addr,fifo_span,valid_slots;
 
-	spos_control_block_t sposcb = {
+	static spos_control_block_t sposcb = {
 		/* 0 */ HFG_TREE_SCB,HFG_STACK,
 		/* 1 */ SPOSCB_ADDR,BG_TREE_SCB_ADDR,
 		/* 2 */ DSP_SPOS_DC,0,
@@ -1110,18 +1110,18 @@
   
 	{
 		/* create the null SCB */
-		generic_scb_t null_scb = {
+		static generic_scb_t null_scb = {
 			{ 0, 0, 0, 0 },
 			{ 0, 0, 0, 0, 0 },
 			NULL_SCB_ADDR, NULL_SCB_ADDR,
-			null_algorithm->address, 0,
-			0,0,0,
+			0, 0, 0, 0, 0,
 			{
 				0,0,
 				0,0,
 			}
 		};
 
+		null_scb.entry_point = null_algorithm->address;
 		ins->the_null_scb = cs46xx_dsp_create_scb(chip, "nullSCB", (u32 *)&null_scb, NULL_SCB_ADDR);
 		ins->the_null_scb->task_entry = null_algorithm;
 		ins->the_null_scb->sub_list_ptr = ins->the_null_scb;
@@ -1132,7 +1132,7 @@
 
 	{
 		/* setup foreground task tree */
-		task_tree_control_block_t fg_task_tree_hdr =  {
+		static task_tree_control_block_t fg_task_tree_hdr =  {
 			{ FG_TASK_HEADER_ADDR | (DSP_SPOS_DC << 0x10),
 			  DSP_SPOS_DC_DC,
 			  DSP_SPOS_DC_DC,
@@ -1145,7 +1145,7 @@
     
 			{
 				BG_TREE_SCB_ADDR,TIMINGMASTER_SCB_ADDR, 
-				fg_task_tree_header_code->address,
+				0,
 				FG_TASK_HEADER_ADDR + TCBData,                  
 			},
 
@@ -1158,7 +1158,7 @@
 			},
 
 			{
-				DSP_SPOS_DC,task_tree_thread->address,
+				DSP_SPOS_DC,0,
 				DSP_SPOS_DC,DSP_SPOS_DC,
 				DSP_SPOS_DC,DSP_SPOS_DC,
 				DSP_SPOS_DC,DSP_SPOS_DC,
@@ -1200,13 +1200,15 @@
 			}
 		};
 
+		fg_task_tree_hdr.links.entry_point = fg_task_tree_header_code->address;
+		fg_task_tree_hdr.context_blk.stack0 = task_tree_thread->address;
 		cs46xx_dsp_create_task_tree(chip,"FGtaskTreeHdr",(u32 *)&fg_task_tree_hdr,FG_TASK_HEADER_ADDR,0x35);
 	}
 
 
 	{
 		/* setup foreground task tree */
-		task_tree_control_block_t bg_task_tree_hdr =  {
+		static task_tree_control_block_t bg_task_tree_hdr =  {
 			{ DSP_SPOS_DC_DC,
 			  DSP_SPOS_DC_DC,
 			  DSP_SPOS_DC_DC,
@@ -1219,7 +1221,7 @@
     
 			{
 				NULL_SCB_ADDR,NULL_SCB_ADDR,  /* Set up the background to do nothing */
-				task_tree_header_code->address,
+				0,
 				BG_TREE_SCB_ADDR + TCBData,
 			},
 
@@ -1232,7 +1234,7 @@
 			},
 
 			{
-				DSP_SPOS_DC,task_tree_thread->address,
+				DSP_SPOS_DC,0,
 				DSP_SPOS_DC,DSP_SPOS_DC,
 				DSP_SPOS_DC,DSP_SPOS_DC,
 				DSP_SPOS_DC,DSP_SPOS_DC,
@@ -1273,6 +1275,9 @@
 				0,0
 			}
 		};
+
+		bg_task_tree_hdr.links.entry_point = task_tree_header_code->address;
+		bg_task_tree_hdr.context_blk.stack0 = task_tree_thread->address;
 		cs46xx_dsp_create_task_tree(chip,"BGtaskTreeHdr",(u32 *)&bg_task_tree_hdr,BG_TREE_SCB_ADDR,0x35);
 	}
 
@@ -1312,7 +1317,7 @@
 	if (!write_back_scb) goto _fail_end;
 
 	{
-		mix2_ostream_spb_t mix2_ostream_spb = {
+		static mix2_ostream_spb_t mix2_ostream_spb = {
 			0x00020000,
 			0x0000ffff
 		};
diff -Nru a/sound/pci/cs46xx/dsp_spos_scb_lib.c b/sound/pci/cs46xx/dsp_spos_scb_lib.c
--- a/sound/pci/cs46xx/dsp_spos_scb_lib.c	2004-10-18 14:57:03 -07:00
+++ b/sound/pci/cs46xx/dsp_spos_scb_lib.c	2004-10-18 14:57:03 -07:00
@@ -69,7 +69,7 @@
 	proc_scb_info_t * scb_info  = (proc_scb_info_t *)entry->private_data;
 	dsp_scb_descriptor_t * scb = scb_info->scb_desc;
 	dsp_spos_instance_t * ins;
-	cs46xx_t *chip = snd_magic_cast(cs46xx_t, scb_info->chip, return);
+	cs46xx_t *chip = scb_info->chip;
 	int j,col;
 	unsigned long dst = chip->region.idx[1].remap_addr + DSP_PARAMETER_BYTE_OFFSET;
 
diff -Nru a/sound/pci/emu10k1/emu10k1.c b/sound/pci/emu10k1/emu10k1.c
--- a/sound/pci/emu10k1/emu10k1.c	2004-10-18 14:55:53 -07:00
+++ b/sound/pci/emu10k1/emu10k1.c	2004-10-18 14:55:53 -07:00
@@ -31,8 +31,7 @@
 MODULE_AUTHOR("Jaroslav Kysela <perex@suse.cz>");
 MODULE_DESCRIPTION("EMU10K1");
 MODULE_LICENSE("GPL");
-MODULE_CLASSES("{sound}");
-MODULE_DEVICES("{{Creative Labs,SB Live!/PCI512/E-mu APS},"
+MODULE_SUPPORTED_DEVICE("{{Creative Labs,SB Live!/PCI512/E-mu APS},"
 	       "{Creative Labs,SB Audigy}}");
 
 #if defined(CONFIG_SND_SEQUENCER) || (defined(MODULE) && defined(CONFIG_SND_SEQUENCER_MODULE))
@@ -53,37 +52,25 @@
 
 module_param_array(index, int, boot_devs, 0444);
 MODULE_PARM_DESC(index, "Index value for the EMU10K1 soundcard.");
-MODULE_PARM_SYNTAX(index, SNDRV_INDEX_DESC);
 module_param_array(id, charp, boot_devs, 0444);
 MODULE_PARM_DESC(id, "ID string for the EMU10K1 soundcard.");
-MODULE_PARM_SYNTAX(id, SNDRV_ID_DESC);
 module_param_array(enable, bool, boot_devs, 0444);
 MODULE_PARM_DESC(enable, "Enable the EMU10K1 soundcard.");
-MODULE_PARM_SYNTAX(enable, SNDRV_ENABLE_DESC);
 module_param_array(extin, int, boot_devs, 0444);
 MODULE_PARM_DESC(extin, "Available external inputs for FX8010. Zero=default.");
-MODULE_PARM_SYNTAX(extin, SNDRV_ENABLED "allows:{{0,0x0ffff}},base:16");
 module_param_array(extout, int, boot_devs, 0444);
 MODULE_PARM_DESC(extout, "Available external outputs for FX8010. Zero=default.");
-MODULE_PARM_SYNTAX(extout, SNDRV_ENABLED "allows:{{0,0x0ffff}},base:16");
 module_param_array(seq_ports, int, boot_devs, 0444);
 MODULE_PARM_DESC(seq_ports, "Allocated sequencer ports for internal synthesizer.");
-MODULE_PARM_SYNTAX(seq_ports, SNDRV_ENABLED "allows:{{0,32}}");
 module_param_array(max_synth_voices, int, boot_devs, 0444);
 MODULE_PARM_DESC(max_synth_voices, "Maximum number of voices for WaveTable.");
-MODULE_PARM_SYNTAX(max_synth_voices, SNDRV_ENABLED);
 module_param_array(max_buffer_size, int, boot_devs, 0444);
 MODULE_PARM_DESC(max_buffer_size, "Maximum sample buffer size in MB.");
-MODULE_PARM_SYNTAX(max_buffer_size, SNDRV_ENABLED);
 module_param_array(enable_ir, bool, boot_devs, 0444);
 MODULE_PARM_DESC(enable_ir, "Enable IR.");
-MODULE_PARM_SYNTAX(enable_ir, SNDRV_ENABLE_DESC);
 
 static struct pci_device_id snd_emu10k1_ids[] = {
 	{ 0x1102, 0x0002, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },	/* EMU10K1 */
-#if 0 /* FIXME: not working! */
-	{ 0x1102, 0x0006, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },	/* Dell OEM version (EMU10K1) */
-#endif
 	{ 0x1102, 0x0004, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 1 },	/* Audigy */
 	{ 0, }
 };
@@ -131,10 +118,6 @@
 		return err;
 	}		
 	if ((err = snd_emu10k1_pcm_efx(emu, 2, NULL)) < 0) {
-		snd_card_free(card);
-		return err;
-	}		
-	if ((err = snd_emu10k1_fx8010_pcm(emu, 3, NULL)) < 0) {
 		snd_card_free(card);
 		return err;
 	}		
diff -Nru a/sound/pci/emu10k1/emu10k1_callback.c b/sound/pci/emu10k1/emu10k1_callback.c
--- a/sound/pci/emu10k1/emu10k1_callback.c	2004-10-18 14:56:28 -07:00
+++ b/sound/pci/emu10k1/emu10k1_callback.c	2004-10-18 14:56:28 -07:00
@@ -93,7 +93,7 @@
 	unsigned long flags;
 	int i;
 
-	emu = snd_magic_cast(snd_emux_t, hw->synth, return -EINVAL);
+	emu = hw->synth;
 
 	spin_lock_irqsave(&emu->voice_lock, flags);
 	lookup_voices(emu, hw, best, 1); /* no OFF voices */
@@ -128,7 +128,7 @@
 	int dcysusv;
 	emu10k1_t *hw;
 	
-	hw = snd_magic_cast(emu10k1_t, vp->hw, return);
+	hw = vp->hw;
 	dcysusv = 0x8000 | (unsigned char)vp->reg.parm.modrelease;
 	snd_emu10k1_ptr_write(hw, DCYSUSM, vp->ch, dcysusv);
 	dcysusv = 0x8000 | (unsigned char)vp->reg.parm.volrelease | DCYSUSV_CHANNELENABLE_MASK;
@@ -145,7 +145,7 @@
 	emu10k1_t *hw;
 	
 	snd_assert(vp, return);
-	hw = snd_magic_cast(emu10k1_t, vp->hw, return);
+	hw = vp->hw;
 	snd_emu10k1_ptr_write(hw, DCYSUSV, vp->ch, 0x807f | DCYSUSV_CHANNELENABLE_MASK);
 	if (vp->block) {
 		emu10k1_memblk_t *emem;
@@ -163,7 +163,7 @@
 {
 	emu10k1_t *hw;
 	
-	hw = snd_magic_cast(emu10k1_t, vp->hw, return);
+	hw = vp->hw;
 	if (vp->ch >= 0) {
 		snd_emu10k1_ptr_write(hw, IFATN, vp->ch, 0xff00);
 		snd_emu10k1_ptr_write(hw, DCYSUSV, vp->ch, 0x807f | DCYSUSV_CHANNELENABLE_MASK);
@@ -185,7 +185,7 @@
 {
 	emu10k1_t *hw;
 	
-	hw = snd_magic_cast(emu10k1_t, vp->hw, return);
+	hw = vp->hw;
 	if (update & SNDRV_EMUX_UPDATE_VOLUME)
 		snd_emu10k1_ptr_write(hw, IFATN_ATTENUATION, vp->ch, vp->avol);
 	if (update & SNDRV_EMUX_UPDATE_PITCH)
@@ -282,7 +282,7 @@
 	best_voice_t best[V_END];
 	int i;
 
-	hw = snd_magic_cast(emu10k1_t, emu->hw, return NULL);
+	hw = emu->hw;
 
 	lookup_voices(emu, hw, best, 0);
 	for (i = 0; i < V_END; i++) {
@@ -317,7 +317,7 @@
 	emu10k1_t *hw;
 	emu10k1_memblk_t *emem;
 	
-	hw = snd_magic_cast(emu10k1_t, vp->hw, return -EINVAL);
+	hw = vp->hw;
 	ch = vp->ch;
 	snd_assert(ch >= 0, return -EINVAL);
 	chan = vp->chan;
@@ -469,7 +469,7 @@
 	emu10k1_t *hw;
 	emu10k1_memblk_t *emem;
 	
-	hw = snd_magic_cast(emu10k1_t, vp->hw, return);
+	hw = vp->hw;
 
 	emem = (emu10k1_memblk_t *)vp->block;
 	if (! emem || emem->mapped_page < 0)
diff -Nru a/sound/pci/emu10k1/emu10k1_main.c b/sound/pci/emu10k1/emu10k1_main.c
--- a/sound/pci/emu10k1/emu10k1_main.c	2004-10-18 14:57:04 -07:00
+++ b/sound/pci/emu10k1/emu10k1_main.c	2004-10-18 14:57:04 -07:00
@@ -119,8 +119,10 @@
 	snd_emu10k1_ptr_write(emu, SOLEH, 0, 0);
 
 	if (emu->audigy){
-		snd_emu10k1_ptr_write(emu, 0x5e, 0, 0xf00); /* ?? */
-		snd_emu10k1_ptr_write(emu, 0x5f, 0, 0x3); /* ?? */
+		/* set SPDIF bypass mode */
+		snd_emu10k1_ptr_write(emu, SPBYPASS, 0, SPBYPASS_FORMAT);
+		/* enable rear left + rear right AC97 slots */
+		snd_emu10k1_ptr_write(emu, AC97SLOT, 0, AC97SLOT_REAR_RIGHT | AC97SLOT_REAR_LEFT);
 	}
 
 	/* init envelope engine */
@@ -329,7 +331,7 @@
 	if (emu->audigy)
 		snd_emu10k1_ptr_write(emu, A_DBG, 0, A_DBG_SINGLE_STEP);
 	else
-		snd_emu10k1_ptr_write(emu, DBG, 0, 0x8000);
+		snd_emu10k1_ptr_write(emu, DBG, 0, EMU10K1_DBG_SINGLE_STEP);
 
 	/* disable channel interrupt */
 	snd_emu10k1_ptr_write(emu, CLIEL, 0, 0);
@@ -541,33 +543,31 @@
 
 static int snd_emu10k1_free(emu10k1_t *emu)
 {
-	if (emu->res_port != NULL) {	/* avoid access to already used hardware */
+	if (emu->port) {	/* avoid access to already used hardware */
 	       	snd_emu10k1_fx8010_tram_setup(emu, 0);
 		snd_emu10k1_done(emu);
        	}
 	if (emu->memhdr)
 		snd_util_memhdr_free(emu->memhdr);
 	if (emu->silent_page.area)
-		snd_dma_free_pages(&emu->dma_dev, &emu->silent_page);
+		snd_dma_free_pages(&emu->silent_page);
 	if (emu->ptb_pages.area)
-		snd_dma_free_pages(&emu->dma_dev, &emu->ptb_pages);
+		snd_dma_free_pages(&emu->ptb_pages);
 	if (emu->page_ptr_table)
 		vfree(emu->page_ptr_table);
 	if (emu->page_addr_table)
 		vfree(emu->page_addr_table);
-	if (emu->res_port) {
-		release_resource(emu->res_port);
-		kfree_nocheck(emu->res_port);
-	}
 	if (emu->irq >= 0)
 		free_irq(emu->irq, (void *)emu);
-	snd_magic_kfree(emu);
+	if (emu->port)
+		pci_release_regions(emu->pci);
+	kfree(emu);
 	return 0;
 }
 
 static int snd_emu10k1_dev_free(snd_device_t *device)
 {
-	emu10k1_t *emu = snd_magic_cast(emu10k1_t, device->device_data, return -ENXIO);
+	emu10k1_t *emu = device->device_data;
 	return snd_emu10k1_free(emu);
 }
 
@@ -595,7 +595,7 @@
 	if ((err = pci_enable_device(pci)) < 0)
 		return err;
 
-	emu = snd_magic_kcalloc(emu10k1_t, 0, GFP_KERNEL);
+	emu = kcalloc(1, sizeof(*emu), GFP_KERNEL);
 	if (emu == NULL)
 		return -ENOMEM;
 	/* set the DMA transfer mask */
@@ -603,7 +603,7 @@
 	if (pci_set_dma_mask(pci, emu->dma_mask) < 0 ||
 	    pci_set_consistent_dma_mask(pci, emu->dma_mask) < 0) {
 		snd_printk(KERN_ERR "architecture does not support PCI busmaster DMA with mask 0x%lx\n", emu->dma_mask);
-		snd_magic_kfree(emu);
+		kfree(emu);
 		return -ENXIO;
 	}
 	emu->card = card;
@@ -620,7 +620,6 @@
 	emu->irq = -1;
 	emu->synth = NULL;
 	emu->get_synth_voice = NULL;
-	emu->port = pci_resource_start(pci, 0);
 
 	emu->audigy = is_audigy;
 	if (is_audigy)
@@ -628,10 +627,11 @@
 	else
 		emu->gpr_base = FXGPREGBASE;
 
-	if ((emu->res_port = request_region(emu->port, 0x20, "EMU10K1")) == NULL) {
-		snd_emu10k1_free(emu);
-		return -EBUSY;
+	if ((err = pci_request_regions(pci, "EMU10K1")) < 0) {
+		kfree(emu);
+		return err;
 	}
+	emu->port = pci_resource_start(pci, 0);
 
 	if (request_irq(pci->irq, snd_emu10k1_interrupt, SA_INTERRUPT|SA_SHIRQ, "EMU10K1", (void *)emu)) {
 		snd_emu10k1_free(emu);
@@ -639,12 +639,9 @@
 	}
 	emu->irq = pci->irq;
 
-	memset(&emu->dma_dev, 0, sizeof(emu->dma_dev));
-	emu->dma_dev.type = SNDRV_DMA_TYPE_DEV;
-	emu->dma_dev.dev = snd_dma_pci_data(pci);
-
 	emu->max_cache_pages = max_cache_bytes >> PAGE_SHIFT;
-	if (snd_dma_alloc_pages(&emu->dma_dev, 32 * 1024, &emu->ptb_pages) < 0) {
+	if (snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, snd_dma_pci_data(pci),
+				32 * 1024, &emu->ptb_pages) < 0) {
 		snd_emu10k1_free(emu);
 		return -ENOMEM;
 	}
@@ -656,7 +653,8 @@
 		return -ENOMEM;
 	}
 
-	if (snd_dma_alloc_pages(&emu->dma_dev, EMUPAGESIZE, &emu->silent_page) < 0) {
+	if (snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, snd_dma_pci_data(pci),
+				EMUPAGESIZE, &emu->silent_page) < 0) {
 		snd_emu10k1_free(emu);
 		return -ENOMEM;
 	}
@@ -682,9 +680,16 @@
 		/* Audigy 2 EX has apparently no effective AC97 controls
 		 * (for both input and output), so we skip the AC97 detections
 		 */
-		snd_printdd(KERN_INFO "Audigy2 EX is detected. skpping ac97.\n");
-		emu->no_ac97 = 1;
+		snd_printdd(KERN_INFO "Audigy2 EX is detected. skipping ac97.\n");
+		emu->no_ac97 = 1;	
 	}
+	
+	if (emu->revision == 4 && emu->model == 0x2002) {
+		/* Audigy 2 ZS */
+		snd_printdd(KERN_INFO "Audigy2 ZS is detected. setting 7.1 mode.\n");
+		emu->spk71 = 1;
+	}
+	
 	
 	emu->fx8010.fxbus_mask = 0x303f;
 	if (extin_mask == 0)
diff -Nru a/sound/pci/emu10k1/emu10k1_patch.c b/sound/pci/emu10k1/emu10k1_patch.c
--- a/sound/pci/emu10k1/emu10k1_patch.c	2004-10-18 14:56:28 -07:00
+++ b/sound/pci/emu10k1/emu10k1_patch.c	2004-10-18 14:56:28 -07:00
@@ -44,7 +44,7 @@
 	unsigned int start_addr;
 	emu10k1_t *emu;
 
-	emu = snd_magic_cast(emu10k1_t, rec->hw, return -ENXIO);
+	emu = rec->hw;
 	snd_assert(sp != NULL, return -EINVAL);
 	snd_assert(hdr != NULL, return -EINVAL);
 
@@ -210,7 +210,7 @@
 {
 	emu10k1_t *emu;
 
-	emu = snd_magic_cast(emu10k1_t, rec->hw, return -ENXIO);
+	emu = rec->hw;
 	snd_assert(sp != NULL, return -EINVAL);
 	snd_assert(hdr != NULL, return -EINVAL);
 
diff -Nru a/sound/pci/emu10k1/emu10k1_synth.c b/sound/pci/emu10k1/emu10k1_synth.c
--- a/sound/pci/emu10k1/emu10k1_synth.c	2004-10-18 14:56:20 -07:00
+++ b/sound/pci/emu10k1/emu10k1_synth.c	2004-10-18 14:56:20 -07:00
@@ -85,9 +85,9 @@
 	if (dev->driver_data == NULL)
 		return 0; /* not registered actually */
 
-	emu = snd_magic_cast(snd_emux_t, dev->driver_data, return -EINVAL);
+	emu = dev->driver_data;
 
-	hw = snd_magic_cast(emu10k1_t, emu->hw, return -EINVAL);
+	hw = emu->hw;
 	spin_lock_irqsave(&hw->voice_lock, flags);
 	hw->synth = NULL;
 	hw->get_synth_voice = NULL;
diff -Nru a/sound/pci/emu10k1/emufx.c b/sound/pci/emu10k1/emufx.c
--- a/sound/pci/emu10k1/emufx.c	2004-10-18 14:56:32 -07:00
+++ b/sound/pci/emu10k1/emufx.c	2004-10-18 14:56:32 -07:00
@@ -33,8 +33,6 @@
 #include <sound/core.h>
 #include <sound/emu10k1.h>
 
-#define chip_t emu10k1_t
-
 #if 0		/* for testing purposes - digital out -> capture */
 #define EMU10K1_CAPTURE_DIGITAL_OUT
 #endif
@@ -405,7 +403,7 @@
 	}
 }
 
-static int snd_emu10k1_fx8010_register_irq_handler(emu10k1_t *emu,
+int snd_emu10k1_fx8010_register_irq_handler(emu10k1_t *emu,
 						   snd_fx8010_irq_handler_t *handler,
 						   unsigned char gpr_running,
 						   void *private_data,
@@ -438,7 +436,7 @@
 	return 0;
 }
 
-static int snd_emu10k1_fx8010_unregister_irq_handler(emu10k1_t *emu,
+int snd_emu10k1_fx8010_unregister_irq_handler(emu10k1_t *emu,
 						     snd_emu10k1_fx8010_irq_t *irq)
 {
 	snd_emu10k1_fx8010_irq_t *tmp;
@@ -463,312 +461,6 @@
 	return 0;
 }
 
-/*
- *   PCM streams
- */
-
-#define INITIAL_TRAM_SHIFT     14
-#define INITIAL_TRAM_POS(size) ((((size) / 2) - INITIAL_TRAM_SHIFT) - 1)
-
-static void snd_emu10k1_fx8010_playback_irq(emu10k1_t *emu, void *private_data)
-{
-	snd_pcm_substream_t *substream = snd_magic_cast(snd_pcm_substream_t, private_data, return);
-	snd_pcm_period_elapsed(substream);
-}
-
-static void snd_emu10k1_fx8010_playback_tram_poke1(unsigned short *dst_left,
-						   unsigned short *dst_right,
-						   unsigned short *src,
-						   unsigned int count,
-						   unsigned int tram_shift)
-{
-	// printk("tram_poke1: dst_left = 0x%p, dst_right = 0x%p, src = 0x%p, count = 0x%x\n", dst_left, dst_right, src, count);
-	if ((tram_shift & 1) == 0) {
-		while (count--) {
-			*dst_left-- = *src++;
-			*dst_right-- = *src++;
-		}
-	} else {
-		while (count--) {
-			*dst_right-- = *src++;
-			*dst_left-- = *src++;
-		}
-	}
-}
-
-static void snd_emu10k1_fx8010_playback_tram_poke(emu10k1_t *emu,
-						  unsigned int *tram_pos,
-						  unsigned int *tram_shift,
-						  unsigned int tram_size,
-						  unsigned short *src,
-						  unsigned int frames)
-{
-	unsigned int count;
-
-	while (frames > *tram_pos) {
-		count = *tram_pos + 1;
-		snd_emu10k1_fx8010_playback_tram_poke1((unsigned short *)emu->fx8010.etram_pages.area + *tram_pos,
-						       (unsigned short *)emu->fx8010.etram_pages.area + *tram_pos + tram_size / 2,
-						       src, count, *tram_shift);
-		src += count * 2;
-		frames -= count;
-		*tram_pos = (tram_size / 2) - 1;
-		(*tram_shift)++;
-	}
-	snd_emu10k1_fx8010_playback_tram_poke1((unsigned short *)emu->fx8010.etram_pages.area + *tram_pos,
-					       (unsigned short *)emu->fx8010.etram_pages.area + *tram_pos + tram_size / 2,
-					       src, frames, *tram_shift++);
-	*tram_pos -= frames;
-}
-
-static int snd_emu10k1_fx8010_playback_transfer(snd_pcm_substream_t *substream)
-{
-	emu10k1_t *emu = snd_pcm_substream_chip(substream);
-	snd_pcm_runtime_t *runtime = substream->runtime;
-	snd_emu10k1_fx8010_pcm_t *pcm = &emu->fx8010.pcm[substream->number];
-	snd_pcm_uframes_t appl_ptr = runtime->control->appl_ptr;
-	snd_pcm_sframes_t diff = appl_ptr - pcm->appl_ptr;
-	snd_pcm_uframes_t buffer_size = pcm->buffer_size / 2;
-
-	if (diff) {
-		if (diff < -(snd_pcm_sframes_t) (runtime->boundary / 2))
-			diff += runtime->boundary;
-		pcm->sw_ready += diff;
-		pcm->appl_ptr = appl_ptr;
-	}
-	while (pcm->hw_ready < buffer_size &&
-	       pcm->sw_ready > 0) {
-	       	size_t hw_to_end = buffer_size - pcm->hw_data;
-	       	size_t sw_to_end = (runtime->buffer_size << 2) - pcm->sw_data;
-	       	size_t tframes = buffer_size - pcm->hw_ready;
-	       	if (pcm->sw_ready < tframes)
-	       		tframes = pcm->sw_ready;
-	       	if (hw_to_end < tframes)
-	       		tframes = hw_to_end;
-	       	if (sw_to_end < tframes)
-	       		tframes = sw_to_end;
-	       	snd_emu10k1_fx8010_playback_tram_poke(emu, &pcm->tram_pos, &pcm->tram_shift,
-	       					      pcm->buffer_size,
-	       					      (unsigned short *)(runtime->dma_area + (pcm->sw_data << 2)),
-	       					      tframes);
-		pcm->hw_data += tframes;
-		if (pcm->hw_data == buffer_size)
-			pcm->hw_data = 0;
-		pcm->sw_data += tframes;
-		if (pcm->sw_data == runtime->buffer_size)
-			pcm->sw_data = 0;
-		pcm->hw_ready += tframes;
-		pcm->sw_ready -= tframes;
-	}
-	return 0;
-}
-
-static int snd_emu10k1_fx8010_playback_hw_params(snd_pcm_substream_t * substream,
-						 snd_pcm_hw_params_t * hw_params)
-{
-	return snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(hw_params));
-}
-
-static int snd_emu10k1_fx8010_playback_hw_free(snd_pcm_substream_t * substream)
-{
-	emu10k1_t *emu = snd_pcm_substream_chip(substream);
-	snd_emu10k1_fx8010_pcm_t *pcm = &emu->fx8010.pcm[substream->number];
-	unsigned int i;
-
-	for (i = 0; i < pcm->channels; i++)
-		snd_emu10k1_ptr_write(emu, TANKMEMADDRREGBASE + 0x80 + pcm->etram[i], 0, 0);
-	snd_pcm_lib_free_pages(substream);
-	return 0;
-}
-
-static int snd_emu10k1_fx8010_playback_prepare(snd_pcm_substream_t * substream)
-{
-	emu10k1_t *emu = snd_pcm_substream_chip(substream);
-	snd_pcm_runtime_t *runtime = substream->runtime;
-	snd_emu10k1_fx8010_pcm_t *pcm = &emu->fx8010.pcm[substream->number];
-	unsigned int i;
-	
-	// printk("prepare: etram_pages = 0x%p, dma_area = 0x%x, buffer_size = 0x%x (0x%x)\n", emu->fx8010.etram_pages, runtime->dma_area, runtime->buffer_size, runtime->buffer_size << 2);
-	pcm->sw_data = pcm->sw_io = pcm->sw_ready = 0;
-	pcm->hw_data = pcm->hw_io = pcm->hw_ready = 0;
-	pcm->tram_pos = INITIAL_TRAM_POS(pcm->buffer_size);
-	pcm->tram_shift = 0;
-	pcm->appl_ptr = 0;
-	snd_emu10k1_ptr_write(emu, emu->gpr_base + pcm->gpr_running, 0, 0);	/* reset */
-	snd_emu10k1_ptr_write(emu, emu->gpr_base + pcm->gpr_trigger, 0, 0);	/* reset */
-	snd_emu10k1_ptr_write(emu, emu->gpr_base + pcm->gpr_size, 0, runtime->buffer_size);
-	snd_emu10k1_ptr_write(emu, emu->gpr_base + pcm->gpr_ptr, 0, 0);		/* reset ptr number */
-	snd_emu10k1_ptr_write(emu, emu->gpr_base + pcm->gpr_count, 0, runtime->period_size);
-	snd_emu10k1_ptr_write(emu, emu->gpr_base + pcm->gpr_tmpcount, 0, runtime->period_size);
-	for (i = 0; i < pcm->channels; i++)
-		snd_emu10k1_ptr_write(emu, TANKMEMADDRREGBASE + 0x80 + pcm->etram[i], 0, (TANKMEMADDRREG_READ|TANKMEMADDRREG_ALIGN) + i * (runtime->buffer_size / pcm->channels));
-	return 0;
-}
-
-static int snd_emu10k1_fx8010_playback_trigger(snd_pcm_substream_t * substream, int cmd)
-{
-	emu10k1_t *emu = snd_pcm_substream_chip(substream);
-	snd_emu10k1_fx8010_pcm_t *pcm = &emu->fx8010.pcm[substream->number];
-	unsigned long flags;
-	int result = 0;
-
-	spin_lock_irqsave(&emu->reg_lock, flags);
-	switch (cmd) {
-	case SNDRV_PCM_TRIGGER_START:
-		/* follow thru */
-	case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
-#ifdef EMU10K1_SET_AC3_IEC958
-	{
-		int i;
-		for (i = 0; i < 3; i++) {
-			unsigned int bits;
-			bits = SPCS_CLKACCY_1000PPM | SPCS_SAMPLERATE_48 |
-			       SPCS_CHANNELNUM_LEFT | SPCS_SOURCENUM_UNSPEC | SPCS_GENERATIONSTATUS |
-			       0x00001200 | SPCS_EMPHASIS_NONE | SPCS_COPYRIGHT | SPCS_NOTAUDIODATA;
-			snd_emu10k1_ptr_write(emu, SPCS0 + i, 0, bits);
-		}
-	}
-#endif
-		result = snd_emu10k1_fx8010_register_irq_handler(emu, snd_emu10k1_fx8010_playback_irq, pcm->gpr_running, substream, &pcm->irq);
-		if (result < 0)
-			goto __err;
-		snd_emu10k1_fx8010_playback_transfer(substream);	/* roll the ball */
-		snd_emu10k1_ptr_write(emu, emu->gpr_base + pcm->gpr_trigger, 0, 1);
-		break;
-	case SNDRV_PCM_TRIGGER_STOP:
-	case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
-		snd_emu10k1_fx8010_unregister_irq_handler(emu, pcm->irq); pcm->irq = NULL;
-		snd_emu10k1_ptr_write(emu, emu->gpr_base + pcm->gpr_trigger, 0, 0);
-		pcm->tram_pos = INITIAL_TRAM_POS(pcm->buffer_size);
-		pcm->tram_shift = 0;
-		break;
-	default:
-		result = -EINVAL;
-		break;
-	}
-      __err:
-	spin_unlock_irqrestore(&emu->reg_lock, flags);
-	return result;
-}
-
-static snd_pcm_uframes_t snd_emu10k1_fx8010_playback_pointer(snd_pcm_substream_t * substream)
-{
-	emu10k1_t *emu = snd_pcm_substream_chip(substream);
-	snd_pcm_runtime_t *runtime = substream->runtime;
-	snd_emu10k1_fx8010_pcm_t *pcm = &emu->fx8010.pcm[substream->number];
-	size_t ptr;
-	snd_pcm_sframes_t frames;
-
-	if (!snd_emu10k1_ptr_read(emu, emu->gpr_base + pcm->gpr_trigger, 0))
-		return 0;
-	ptr = snd_emu10k1_ptr_read(emu, emu->gpr_base + pcm->gpr_ptr, 0);
-	frames = ptr - pcm->hw_io;
-	if (frames < 0)
-		frames += runtime->buffer_size;
-	pcm->hw_io = ptr;
-	pcm->hw_ready -= frames;
-	pcm->sw_io += frames;
-	if (pcm->sw_io >= runtime->buffer_size)
-		pcm->sw_io -= runtime->buffer_size;
-	snd_emu10k1_fx8010_playback_transfer(substream);
-	return pcm->sw_io;
-}
-
-static snd_pcm_hardware_t snd_emu10k1_fx8010_playback =
-{
-	.info =			(SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED |
-				 /* SNDRV_PCM_INFO_MMAP_VALID | */ SNDRV_PCM_INFO_PAUSE),
-	.formats =		SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S16_LE,
-	.rates =		SNDRV_PCM_RATE_48000,
-	.rate_min =		48000,
-	.rate_max =		48000,
-	.channels_min =		1,
-	.channels_max =		1,
-	.buffer_bytes_max =	(128*1024),
-	.period_bytes_min =	1024,
-	.period_bytes_max =	(128*1024),
-	.periods_min =		1,
-	.periods_max =		1024,
-	.fifo_size =		0,
-};
-
-static int snd_emu10k1_fx8010_playback_open(snd_pcm_substream_t * substream)
-{
-	emu10k1_t *emu = snd_pcm_substream_chip(substream);
-	snd_pcm_runtime_t *runtime = substream->runtime;
-	snd_emu10k1_fx8010_pcm_t *pcm = &emu->fx8010.pcm[substream->number];
-
-	runtime->hw = snd_emu10k1_fx8010_playback;
-	runtime->hw.channels_min = runtime->hw.channels_max = pcm->channels;
-	runtime->hw.period_bytes_max = (pcm->buffer_size * 2) / 2;
-	spin_lock(&emu->reg_lock);
-	if (pcm->valid == 0) {
-		spin_unlock(&emu->reg_lock);
-		return -ENODEV;
-	}
-	pcm->opened = 1;
-	spin_unlock(&emu->reg_lock);
-	return 0;
-}
-
-static int snd_emu10k1_fx8010_playback_close(snd_pcm_substream_t * substream)
-{
-	emu10k1_t *emu = snd_pcm_substream_chip(substream);
-	snd_emu10k1_fx8010_pcm_t *pcm = &emu->fx8010.pcm[substream->number];
-
-	spin_lock(&emu->reg_lock);
-	pcm->opened = 0;
-	spin_unlock(&emu->reg_lock);
-	return 0;
-}
-
-static snd_pcm_ops_t snd_emu10k1_fx8010_playback_ops = {
-	.open =			snd_emu10k1_fx8010_playback_open,
-	.close =		snd_emu10k1_fx8010_playback_close,
-	.ioctl =		snd_pcm_lib_ioctl,
-	.hw_params =		snd_emu10k1_fx8010_playback_hw_params,
-	.hw_free =		snd_emu10k1_fx8010_playback_hw_free,
-	.prepare =		snd_emu10k1_fx8010_playback_prepare,
-	.trigger =		snd_emu10k1_fx8010_playback_trigger,
-	.pointer =		snd_emu10k1_fx8010_playback_pointer,
-	.ack =			snd_emu10k1_fx8010_playback_transfer,
-};
-
-static void snd_emu10k1_fx8010_pcm_free(snd_pcm_t *pcm)
-{
-	emu10k1_t *emu = snd_magic_cast(emu10k1_t, pcm->private_data, return);
-	emu->pcm_fx8010 = NULL;
-	snd_pcm_lib_preallocate_free_for_all(pcm);
-}
-
-int snd_emu10k1_fx8010_pcm(emu10k1_t * emu, int device, snd_pcm_t ** rpcm)
-{
-	snd_pcm_t *pcm;
-	int err;
-
-	if (rpcm)
-		*rpcm = NULL;
-
-	if ((err = snd_pcm_new(emu->card, "emu10k1", device, 8, 0, &pcm)) < 0)
-		return err;
-
-	pcm->private_data = emu;
-	pcm->private_free = snd_emu10k1_fx8010_pcm_free;
-
-	snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_emu10k1_fx8010_playback_ops);
-
-	pcm->info_flags = 0;
-	strcpy(pcm->name, "EMU10K1 FX8010");
-	emu->pcm_fx8010 = pcm;
-	
-	snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV, snd_dma_pci_data(emu->pci), 64*1024, 0);
-
-	if (rpcm)
-		*rpcm = pcm;
-
-	return 0;
-}
-
 /*************************************************************************
  * EMU10K1 effect manager
  *************************************************************************/
@@ -1193,7 +885,7 @@
 
 #define SND_EMU10K1_GPR_CONTROLS	41
 #define SND_EMU10K1_INPUTS		10
-#define SND_EMU10K1_PLAYBACK_CHANNELS	6
+#define SND_EMU10K1_PLAYBACK_CHANNELS	8
 #define SND_EMU10K1_CAPTURE_CHANNELS	4
 
 static void __devinit snd_emu10k1_init_mono_control(emu10k1_fx8010_control_gpr_t *ctl, const char *name, int gpr, int defval)
@@ -1262,9 +954,9 @@
 	spin_lock_init(&emu->fx8010.irq_lock);
 	INIT_LIST_HEAD(&emu->fx8010.gpr_ctl);
 
-	if ((icode = snd_kcalloc(sizeof(emu10k1_fx8010_code_t), GFP_KERNEL)) == NULL)
+	if ((icode = kcalloc(1, sizeof(*icode), GFP_KERNEL)) == NULL)
 		return -ENOMEM;
-	if ((controls = snd_kcalloc(sizeof(emu10k1_fx8010_control_gpr_t) * SND_EMU10K1_GPR_CONTROLS, GFP_KERNEL)) == NULL) {
+	if ((controls = kcalloc(SND_EMU10K1_GPR_CONTROLS, sizeof(*controls), GFP_KERNEL)) == NULL) {
 		kfree(icode);
 		return -ENOMEM;
 	}
@@ -1292,6 +984,14 @@
 	A_OP(icode, &ptr, iMAC0, A_GPR(playback+3), A_C_00000000, A_GPR(gpr+1), A_FXBUS(FXBUS_PCM_RIGHT_REAR));
 	snd_emu10k1_init_stereo_control(&controls[nctl++], "PCM Surround Playback Volume", gpr, 100);
 	gpr += 2;
+	
+	/* PCM Side Playback (independent from stereo mix) */
+	if (emu->spk71) {
+		A_OP(icode, &ptr, iMAC0, A_GPR(playback+6), A_C_00000000, A_GPR(gpr), A_FXBUS(FXBUS_PCM_LEFT_SIDE));
+		A_OP(icode, &ptr, iMAC0, A_GPR(playback+7), A_C_00000000, A_GPR(gpr+1), A_FXBUS(FXBUS_PCM_RIGHT_SIDE));
+		snd_emu10k1_init_stereo_control(&controls[nctl++], "PCM Side Playback Volume", gpr, 100);
+		gpr += 2;
+	}
 
 	/* PCM Center Playback (independent from stereo mix) */
 	A_OP(icode, &ptr, iMAC0, A_GPR(playback+4), A_C_00000000, A_GPR(gpr), A_FXBUS(FXBUS_PCM_CENTER));
@@ -1440,6 +1140,14 @@
 	A_OP(icode, &ptr, iMAC0, A_GPR(playback+5), A_GPR(playback+5), A_GPR(gpr), A_GPR(tmp));
 	snd_emu10k1_init_mono_control(&controls[nctl++], "LFE Playback Volume", gpr, 0);
 	gpr++;
+	
+	if (emu->spk71) {
+		/* Stereo Mix Side Playback */
+		A_OP(icode, &ptr, iMAC0, A_GPR(playback+6), A_GPR(playback+6), A_GPR(gpr), A_GPR(stereo_mix));
+		A_OP(icode, &ptr, iMAC0, A_GPR(playback+7), A_GPR(playback+7), A_GPR(gpr+1), A_GPR(stereo_mix+1));
+		snd_emu10k1_init_stereo_control(&controls[nctl++], "Side Playback Volume", gpr, 0);
+		gpr += 2;
+	}
 
 	/*
 	 * outputs
@@ -1467,6 +1175,11 @@
 	A_OP(icode, &ptr, iACC3, A_GPR(playback + SND_EMU10K1_PLAYBACK_CHANNELS + 3), A_GPR(playback + 3), A_C_00000000, A_C_00000000); /* rear right */
 	A_OP(icode, &ptr, iACC3, A_GPR(playback + SND_EMU10K1_PLAYBACK_CHANNELS + 4), A_GPR(playback + 4), A_C_00000000, A_C_00000000); /* center */
 	A_OP(icode, &ptr, iACC3, A_GPR(playback + SND_EMU10K1_PLAYBACK_CHANNELS + 5), A_GPR(playback + 5), A_C_00000000, A_C_00000000); /* LFE */
+	if (emu->spk71) {
+		A_OP(icode, &ptr, iACC3, A_GPR(playback + SND_EMU10K1_PLAYBACK_CHANNELS + 6), A_GPR(playback + 6), A_C_00000000, A_C_00000000); /* side left */
+		A_OP(icode, &ptr, iACC3, A_GPR(playback + SND_EMU10K1_PLAYBACK_CHANNELS + 7), A_GPR(playback + 7), A_C_00000000, A_C_00000000); /* side right */
+	}
+	
 
 	ctl = &controls[nctl + 0];
 	ctl->id.iface = SNDRV_CTL_ELEM_IFACE_MIXER;
@@ -1497,7 +1210,7 @@
 			controls[nctl + 1].gpr[z * 2 + j] = TREBLE_GPR + z * 2 + j;
 		}
 	}
-	for (z = 0; z < 3; z++) {		/* front/rear/center-lfe */
+	for (z = 0; z < 4; z++) {		/* front/rear/center-lfe/side */
 		int j, k, l, d;
 		for (j = 0; j < 2; j++) {	/* left/right */
 			k = 0xb0 + (z * 8) + (j * 4);
@@ -1529,7 +1242,7 @@
 #undef BASS_GPR
 #undef TREBLE_GPR
 
-	for (z = 0; z < 6; z++) {
+	for (z = 0; z < 8; z++) {
 		A_SWITCH(icode, &ptr, tmp + 0, playback + SND_EMU10K1_PLAYBACK_CHANNELS + z, gpr + 0);
 		A_SWITCH_NEG(icode, &ptr, tmp + 1, gpr + 0);
 		A_SWITCH(icode, &ptr, tmp + 1, playback + z, tmp + 1);
@@ -1540,12 +1253,14 @@
 
 	/* Master volume (will be renamed later) */
 	A_OP(icode, &ptr, iMAC0, A_GPR(playback+0+SND_EMU10K1_PLAYBACK_CHANNELS), A_C_00000000, A_GPR(gpr), A_GPR(playback+0+SND_EMU10K1_PLAYBACK_CHANNELS));
-	A_OP(icode, &ptr, iMAC0, A_GPR(playback+1+SND_EMU10K1_PLAYBACK_CHANNELS), A_C_00000000, A_GPR(gpr+1), A_GPR(playback+1+SND_EMU10K1_PLAYBACK_CHANNELS));
-	A_OP(icode, &ptr, iMAC0, A_GPR(playback+2+SND_EMU10K1_PLAYBACK_CHANNELS), A_C_00000000, A_GPR(gpr+1), A_GPR(playback+2+SND_EMU10K1_PLAYBACK_CHANNELS));
-	A_OP(icode, &ptr, iMAC0, A_GPR(playback+3+SND_EMU10K1_PLAYBACK_CHANNELS), A_C_00000000, A_GPR(gpr+1), A_GPR(playback+3+SND_EMU10K1_PLAYBACK_CHANNELS));
-	A_OP(icode, &ptr, iMAC0, A_GPR(playback+4+SND_EMU10K1_PLAYBACK_CHANNELS), A_C_00000000, A_GPR(gpr+1), A_GPR(playback+4+SND_EMU10K1_PLAYBACK_CHANNELS));
-	A_OP(icode, &ptr, iMAC0, A_GPR(playback+5+SND_EMU10K1_PLAYBACK_CHANNELS), A_C_00000000, A_GPR(gpr+1), A_GPR(playback+5+SND_EMU10K1_PLAYBACK_CHANNELS));
-	snd_emu10k1_init_stereo_control(&controls[nctl++], "Wave Master Playback Volume", gpr, 0);
+	A_OP(icode, &ptr, iMAC0, A_GPR(playback+1+SND_EMU10K1_PLAYBACK_CHANNELS), A_C_00000000, A_GPR(gpr), A_GPR(playback+1+SND_EMU10K1_PLAYBACK_CHANNELS));
+	A_OP(icode, &ptr, iMAC0, A_GPR(playback+2+SND_EMU10K1_PLAYBACK_CHANNELS), A_C_00000000, A_GPR(gpr), A_GPR(playback+2+SND_EMU10K1_PLAYBACK_CHANNELS));
+	A_OP(icode, &ptr, iMAC0, A_GPR(playback+3+SND_EMU10K1_PLAYBACK_CHANNELS), A_C_00000000, A_GPR(gpr), A_GPR(playback+3+SND_EMU10K1_PLAYBACK_CHANNELS));
+	A_OP(icode, &ptr, iMAC0, A_GPR(playback+4+SND_EMU10K1_PLAYBACK_CHANNELS), A_C_00000000, A_GPR(gpr), A_GPR(playback+4+SND_EMU10K1_PLAYBACK_CHANNELS));
+	A_OP(icode, &ptr, iMAC0, A_GPR(playback+5+SND_EMU10K1_PLAYBACK_CHANNELS), A_C_00000000, A_GPR(gpr), A_GPR(playback+5+SND_EMU10K1_PLAYBACK_CHANNELS));
+	A_OP(icode, &ptr, iMAC0, A_GPR(playback+6+SND_EMU10K1_PLAYBACK_CHANNELS), A_C_00000000, A_GPR(gpr), A_GPR(playback+6+SND_EMU10K1_PLAYBACK_CHANNELS));
+	A_OP(icode, &ptr, iMAC0, A_GPR(playback+7+SND_EMU10K1_PLAYBACK_CHANNELS), A_C_00000000, A_GPR(gpr), A_GPR(playback+7+SND_EMU10K1_PLAYBACK_CHANNELS));
+	snd_emu10k1_init_mono_control(&controls[nctl++], "Wave Master Playback Volume", gpr, 0);
 	gpr += 2;
 
 	/* analog speakers */
@@ -1553,6 +1268,8 @@
 	A_PUT_STEREO_OUTPUT(A_EXTOUT_AREAR_L, A_EXTOUT_AREAR_R, playback+2 + SND_EMU10K1_PLAYBACK_CHANNELS);
 	A_PUT_OUTPUT(A_EXTOUT_ACENTER, playback+4 + SND_EMU10K1_PLAYBACK_CHANNELS);
 	A_PUT_OUTPUT(A_EXTOUT_ALFE, playback+5 + SND_EMU10K1_PLAYBACK_CHANNELS);
+	if (emu->spk71)
+		A_PUT_STEREO_OUTPUT(A_EXTOUT_ASIDE_L, A_EXTOUT_ASIDE_R, playback+6 + SND_EMU10K1_PLAYBACK_CHANNELS);
 
 	/* headphone */
 	A_PUT_STEREO_OUTPUT(A_EXTOUT_HEADPHONE_L, A_EXTOUT_HEADPHONE_R, playback + SND_EMU10K1_PLAYBACK_CHANNELS);
@@ -1674,13 +1391,13 @@
 	spin_lock_init(&emu->fx8010.irq_lock);
 	INIT_LIST_HEAD(&emu->fx8010.gpr_ctl);
 
-	if ((icode = snd_kcalloc(sizeof(emu10k1_fx8010_code_t), GFP_KERNEL)) == NULL)
+	if ((icode = kcalloc(1, sizeof(*icode), GFP_KERNEL)) == NULL)
 		return -ENOMEM;
-	if ((controls = snd_kcalloc(sizeof(emu10k1_fx8010_control_gpr_t) * SND_EMU10K1_GPR_CONTROLS, GFP_KERNEL)) == NULL) {
+	if ((controls = kcalloc(SND_EMU10K1_GPR_CONTROLS, sizeof(emu10k1_fx8010_control_gpr_t), GFP_KERNEL)) == NULL) {
 		kfree(icode);
 		return -ENOMEM;
 	}
-	if ((ipcm = snd_kcalloc(sizeof(emu10k1_fx8010_pcm_t), GFP_KERNEL)) == NULL) {
+	if ((ipcm = kcalloc(1, sizeof(*ipcm), GFP_KERNEL)) == NULL) {
 		kfree(controls);
 		kfree(icode);
 		return -ENOMEM;
@@ -2236,13 +1953,14 @@
 	snd_emu10k1_ptr_write(emu, TCB, 0, 0);
 	snd_emu10k1_ptr_write(emu, TCBS, 0, 0);
 	if (emu->fx8010.etram_pages.area != NULL) {
-		snd_dma_free_pages(&emu->dma_dev, &emu->fx8010.etram_pages);
+		snd_dma_free_pages(&emu->fx8010.etram_pages);
 		emu->fx8010.etram_pages.area = NULL;
 		emu->fx8010.etram_pages.bytes = 0;
 	}
 
 	if (size > 0) {
-		if (snd_dma_alloc_pages(&emu->dma_dev, size * 2, &emu->fx8010.etram_pages) < 0)
+		if (snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, snd_dma_pci_data(emu->pci),
+					size * 2, &emu->fx8010.etram_pages) < 0)
 			return -ENOMEM;
 		memset(emu->fx8010.etram_pages.area, 0, size * 2);
 		snd_emu10k1_ptr_write(emu, TCB, 0, emu->fx8010.etram_pages.addr);
@@ -2297,7 +2015,7 @@
 
 static int snd_emu10k1_fx8010_ioctl(snd_hwdep_t * hw, struct file *file, unsigned int cmd, unsigned long arg)
 {
-	emu10k1_t *emu = snd_magic_cast(emu10k1_t, hw->private_data, return -ENXIO);
+	emu10k1_t *emu = hw->private_data;
 	emu10k1_fx8010_info_t *info;
 	emu10k1_fx8010_code_t *icode;
 	emu10k1_fx8010_pcm_t *ipcm;
@@ -2364,7 +2082,7 @@
 	case SNDRV_EMU10K1_IOCTL_PCM_PEEK:
 		if (emu->audigy)
 			return -EINVAL;
-		ipcm = (emu10k1_fx8010_pcm_t *)snd_kcalloc(sizeof(*ipcm), GFP_KERNEL);
+		ipcm = kcalloc(1, sizeof(*ipcm), GFP_KERNEL);
 		if (ipcm == NULL)
 			return -ENOMEM;
 		if (copy_from_user(ipcm, argp, sizeof(*ipcm))) {
diff -Nru a/sound/pci/emu10k1/emumixer.c b/sound/pci/emu10k1/emumixer.c
--- a/sound/pci/emu10k1/emumixer.c	2004-10-18 14:56:50 -07:00
+++ b/sound/pci/emu10k1/emumixer.c	2004-10-18 14:56:50 -07:00
@@ -32,8 +32,6 @@
 #include <sound/core.h>
 #include <sound/emu10k1.h>
 
-#define chip_t emu10k1_t
-
 #define AC97_ID_STAC9758	0x83847658
 
 static int snd_emu10k1_spdif_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)
@@ -421,7 +419,7 @@
  */
 static void snd_emu10k1_mixer_free_ac97(ac97_t *ac97)
 {
-	emu10k1_t *emu = snd_magic_cast(emu10k1_t, ac97->private_data, return);
+	emu10k1_t *emu = ac97->private_data;
 	emu->ac97 = NULL;
 }
 
@@ -512,13 +510,14 @@
 	};
 
 	if (!emu->no_ac97) {
-		ac97_bus_t bus, *pbus;
-		ac97_t ac97;
+		ac97_bus_t *pbus;
+		ac97_template_t ac97;
+		static ac97_bus_ops_t ops = {
+			.write = snd_emu10k1_ac97_write,
+			.read = snd_emu10k1_ac97_read,
+		};
 
-		memset(&bus, 0, sizeof(bus));
-		bus.write = snd_emu10k1_ac97_write;
-		bus.read = snd_emu10k1_ac97_read;
-		if ((err = snd_ac97_bus(emu->card, &bus, &pbus)) < 0)
+		if ((err = snd_ac97_bus(emu->card, 0, &ops, NULL, &pbus)) < 0)
 			return err;
 		
 		memset(&ac97, 0, sizeof(ac97));
@@ -528,7 +527,7 @@
 			return err;
 		if (emu->audigy) {
 			/* set master volume to 0 dB */
-			snd_ac97_write(emu->ac97, AC97_MASTER, 0x0202);
+			snd_ac97_write(emu->ac97, AC97_MASTER, 0x0000);
 			/* set capture source to mic */
 			snd_ac97_write(emu->ac97, AC97_REC_SEL, 0x0000);
 			c = audigy_remove_ctls;
diff -Nru a/sound/pci/emu10k1/emupcm.c b/sound/pci/emu10k1/emupcm.c
--- a/sound/pci/emu10k1/emupcm.c	2004-10-18 14:55:54 -07:00
+++ b/sound/pci/emu10k1/emupcm.c	2004-10-18 14:55:54 -07:00
@@ -34,8 +34,6 @@
 #include <sound/core.h>
 #include <sound/emu10k1.h>
 
-#define chip_t emu10k1_t
-
 static void snd_emu10k1_pcm_interrupt(emu10k1_t *emu, emu10k1_voice_t *voice)
 {
 	emu10k1_pcm_t *epcm;
@@ -354,7 +352,7 @@
 {
 	emu10k1_t *emu = snd_pcm_substream_chip(substream);
 	snd_pcm_runtime_t *runtime = substream->runtime;
-	emu10k1_pcm_t *epcm = snd_magic_cast(emu10k1_pcm_t, runtime->private_data, return -ENXIO);
+	emu10k1_pcm_t *epcm = runtime->private_data;
 	int err;
 
 	if ((err = snd_emu10k1_pcm_channel_alloc(epcm, params_channels(hw_params))) < 0)
@@ -383,7 +381,7 @@
 
 	if (runtime->private_data == NULL)
 		return 0;
-	epcm = snd_magic_cast(emu10k1_pcm_t, runtime->private_data, return -ENXIO);
+	epcm = runtime->private_data;
 	if (epcm->extra) {
 		snd_emu10k1_voice_free(epcm->emu, epcm->extra);
 		epcm->extra = NULL;
@@ -409,7 +407,7 @@
 {
 	emu10k1_t *emu = snd_pcm_substream_chip(substream);
 	snd_pcm_runtime_t *runtime = substream->runtime;
-	emu10k1_pcm_t *epcm = snd_magic_cast(emu10k1_pcm_t, runtime->private_data, return -ENXIO);
+	emu10k1_pcm_t *epcm = runtime->private_data;
 	unsigned int start_addr, end_addr;
 
 	start_addr = epcm->start_addr;
@@ -443,7 +441,7 @@
 {
 	emu10k1_t *emu = snd_pcm_substream_chip(substream);
 	snd_pcm_runtime_t *runtime = substream->runtime;
-	emu10k1_pcm_t *epcm = snd_magic_cast(emu10k1_pcm_t, runtime->private_data, return -ENXIO);
+	emu10k1_pcm_t *epcm = runtime->private_data;
 	int idx;
 
 	snd_emu10k1_ptr_write(emu, epcm->capture_bs_reg, 0, 0);
@@ -452,7 +450,11 @@
 		snd_emu10k1_ptr_write(emu, ADCCR, 0, 0);
 		break;
 	case CAPTURE_EFX:
-		snd_emu10k1_ptr_write(emu, FXWC, 0, 0);
+		if (emu->audigy) {
+			snd_emu10k1_ptr_write(emu, A_FXWC1, 0, 0);
+			snd_emu10k1_ptr_write(emu, A_FXWC2, 0, 0);
+		} else
+			snd_emu10k1_ptr_write(emu, FXWC, 0, 0);
 		break;
 	default:
 		break;
@@ -565,12 +567,11 @@
 {
 	emu10k1_t *emu = snd_pcm_substream_chip(substream);
 	snd_pcm_runtime_t *runtime = substream->runtime;
-	emu10k1_pcm_t *epcm = snd_magic_cast(emu10k1_pcm_t, runtime->private_data, return -ENXIO);
-	unsigned long flags;
+	emu10k1_pcm_t *epcm = runtime->private_data;
 	int result = 0;
 
 	// printk("trigger - emu10k1 = 0x%x, cmd = %i, pointer = %i\n", (int)emu, cmd, substream->ops->pointer(substream));
-	spin_lock_irqsave(&emu->reg_lock, flags);
+	spin_lock(&emu->reg_lock);
 	switch (cmd) {
 	case SNDRV_PCM_TRIGGER_START:
 		snd_emu10k1_playback_invalidate_cache(emu, epcm->extra);	/* do we need this? */
@@ -593,7 +594,7 @@
 		result = -EINVAL;
 		break;
 	}
-	spin_unlock_irqrestore(&emu->reg_lock, flags);
+	spin_unlock(&emu->reg_lock);
 	return result;
 }
 
@@ -602,12 +603,11 @@
 {
 	emu10k1_t *emu = snd_pcm_substream_chip(substream);
 	snd_pcm_runtime_t *runtime = substream->runtime;
-	emu10k1_pcm_t *epcm = snd_magic_cast(emu10k1_pcm_t, runtime->private_data, return -ENXIO);
-	unsigned long flags;
+	emu10k1_pcm_t *epcm = runtime->private_data;
 	int result = 0;
 
 	// printk("trigger - emu10k1 = %p, cmd = %i, pointer = %i\n", emu, cmd, substream->ops->pointer(substream));
-	spin_lock_irqsave(&emu->reg_lock, flags);
+	spin_lock(&emu->reg_lock);
 	switch (cmd) {
 	case SNDRV_PCM_TRIGGER_START:
 		outl(epcm->capture_ipr, emu->port + IPR);
@@ -618,7 +618,11 @@
 			snd_emu10k1_ptr_write(emu, ADCCR, 0, epcm->capture_cr_val);
 			break;
 		case CAPTURE_EFX:
-			snd_emu10k1_ptr_write(emu, FXWC, 0, epcm->capture_cr_val);
+			if (emu->audigy) {
+				snd_emu10k1_ptr_write(emu, A_FXWC1, 0, epcm->capture_cr_val);
+				snd_emu10k1_ptr_write(emu, A_FXWC2, 0, epcm->capture_cr_val2);
+			} else
+				snd_emu10k1_ptr_write(emu, FXWC, 0, epcm->capture_cr_val);
 			break;
 		default:	
 			break;
@@ -637,7 +641,11 @@
 			snd_emu10k1_ptr_write(emu, ADCCR, 0, 0);
 			break;
 		case CAPTURE_EFX:
-			snd_emu10k1_ptr_write(emu, FXWC, 0, 0);
+			if (emu->audigy) {
+				snd_emu10k1_ptr_write(emu, A_FXWC1, 0, 0);
+				snd_emu10k1_ptr_write(emu, A_FXWC2, 0, 0);
+			} else
+				snd_emu10k1_ptr_write(emu, FXWC, 0, 0);
 			break;
 		default:
 			break;
@@ -646,7 +654,7 @@
 	default:
 		result = -EINVAL;
 	}
-	spin_unlock_irqrestore(&emu->reg_lock, flags);
+	spin_unlock(&emu->reg_lock);
 	return result;
 }
 
@@ -654,7 +662,7 @@
 {
 	emu10k1_t *emu = snd_pcm_substream_chip(substream);
 	snd_pcm_runtime_t *runtime = substream->runtime;
-	emu10k1_pcm_t *epcm = snd_magic_cast(emu10k1_pcm_t, runtime->private_data, return -ENXIO);
+	emu10k1_pcm_t *epcm = runtime->private_data;
 	unsigned int ptr;
 
 	if (!epcm->running)
@@ -681,7 +689,7 @@
 {
 	emu10k1_t *emu = snd_pcm_substream_chip(substream);
 	snd_pcm_runtime_t *runtime = substream->runtime;
-	emu10k1_pcm_t *epcm = snd_magic_cast(emu10k1_pcm_t, runtime->private_data, return -ENXIO);
+	emu10k1_pcm_t *epcm = runtime->private_data;
 	unsigned int ptr;
 
 	if (!epcm->running)
@@ -767,10 +775,10 @@
 
 static void snd_emu10k1_pcm_free_substream(snd_pcm_runtime_t *runtime)
 {
-	emu10k1_pcm_t *epcm = snd_magic_cast(emu10k1_pcm_t, runtime->private_data, return);
+	emu10k1_pcm_t *epcm = runtime->private_data;
 
 	if (epcm)
-		snd_magic_kfree(epcm);
+		kfree(epcm);
 }
 
 static int snd_emu10k1_playback_open(snd_pcm_substream_t * substream)
@@ -781,7 +789,7 @@
 	snd_pcm_runtime_t *runtime = substream->runtime;
 	int i, err;
 
-	epcm = snd_magic_kcalloc(emu10k1_pcm_t, 0, GFP_KERNEL);
+	epcm = kcalloc(1, sizeof(*epcm), GFP_KERNEL);
 	if (epcm == NULL)
 		return -ENOMEM;
 	epcm->emu = emu;
@@ -791,11 +799,11 @@
 	runtime->private_free = snd_emu10k1_pcm_free_substream;
 	runtime->hw = snd_emu10k1_playback;
 	if ((err = snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIODS)) < 0) {
-		snd_magic_kfree(epcm);
+		kfree(epcm);
 		return err;
 	}
 	if ((err = snd_pcm_hw_constraint_minmax(runtime, SNDRV_PCM_HW_PARAM_BUFFER_BYTES, 256, UINT_MAX)) < 0) {
-		snd_magic_kfree(epcm);
+		kfree(epcm);
 		return err;
 	}
 	mix = &emu->pcm_mixer[substream->number];
@@ -826,7 +834,7 @@
 	snd_pcm_runtime_t *runtime = substream->runtime;
 	emu10k1_pcm_t *epcm;
 
-	epcm = snd_magic_kcalloc(emu10k1_pcm_t, 0, GFP_KERNEL);
+	epcm = kcalloc(1, sizeof(*epcm), GFP_KERNEL);
 	if (epcm == NULL)
 		return -ENOMEM;
 	epcm->emu = emu;
@@ -842,7 +850,7 @@
 	runtime->hw = snd_emu10k1_capture;
 	emu->capture_interrupt = snd_emu10k1_pcm_ac97adc_interrupt;
 	emu->pcm_capture_substream = substream;
-	snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_PERIOD_SIZE, &hw_constraints_capture_period_sizes);
+	snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_PERIOD_BYTES, &hw_constraints_capture_period_sizes);
 	snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_RATE, &hw_constraints_capture_rates);
 	return 0;
 }
@@ -862,7 +870,7 @@
 	emu10k1_pcm_t *epcm;
 	snd_pcm_runtime_t *runtime = substream->runtime;
 
-	epcm = snd_magic_kcalloc(emu10k1_pcm_t, 0, GFP_KERNEL);
+	epcm = kcalloc(1, sizeof(*epcm), GFP_KERNEL);
 	if (epcm == NULL)
 		return -ENOMEM;
 	epcm->emu = emu;
@@ -881,7 +889,7 @@
 	runtime->hw.channels_min = 1;
 	emu->capture_mic_interrupt = snd_emu10k1_pcm_ac97mic_interrupt;
 	emu->pcm_capture_mic_substream = substream;
-	snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_PERIOD_SIZE, &hw_constraints_capture_period_sizes);
+	snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_PERIOD_BYTES, &hw_constraints_capture_period_sizes);
 	return 0;
 }
 
@@ -899,11 +907,10 @@
 	emu10k1_t *emu = snd_pcm_substream_chip(substream);
 	emu10k1_pcm_t *epcm;
 	snd_pcm_runtime_t *runtime = substream->runtime;
-	unsigned long flags;
 	int nefx = emu->audigy ? 64 : 32;
 	int idx;
 
-	epcm = snd_magic_kcalloc(emu10k1_pcm_t, 0, GFP_KERNEL);
+	epcm = kcalloc(1, sizeof(*epcm), GFP_KERNEL);
 	if (epcm == NULL)
 		return -ENOMEM;
 	epcm->emu = emu;
@@ -919,7 +926,7 @@
 	runtime->hw = snd_emu10k1_capture;
 	runtime->hw.rates = SNDRV_PCM_RATE_48000;
 	runtime->hw.rate_min = runtime->hw.rate_max = 48000;
-	spin_lock_irqsave(&emu->reg_lock, flags);
+	spin_lock_irq(&emu->reg_lock);
 	runtime->hw.channels_min = runtime->hw.channels_max = 0;
 	for (idx = 0; idx < nefx; idx++) {
 		if (emu->efx_voices_mask[idx/32] & (1 << (idx%32))) {
@@ -929,10 +936,10 @@
 	}
 	epcm->capture_cr_val = emu->efx_voices_mask[0];
 	epcm->capture_cr_val2 = emu->efx_voices_mask[1];
-	spin_unlock_irqrestore(&emu->reg_lock, flags);
+	spin_unlock_irq(&emu->reg_lock);
 	emu->capture_efx_interrupt = snd_emu10k1_pcm_efx_interrupt;
 	emu->pcm_capture_efx_substream = substream;
-	snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_PERIOD_SIZE, &hw_constraints_capture_period_sizes);
+	snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_PERIOD_BYTES, &hw_constraints_capture_period_sizes);
 	return 0;
 }
 
@@ -970,7 +977,7 @@
 
 static void snd_emu10k1_pcm_free(snd_pcm_t *pcm)
 {
-	emu10k1_t *emu = snd_magic_cast(emu10k1_t, pcm->private_data, return);
+	emu10k1_t *emu = pcm->private_data;
 	emu->pcm = NULL;
 	snd_pcm_lib_preallocate_free_for_all(pcm);
 }
@@ -1024,7 +1031,7 @@
 
 static void snd_emu10k1_pcm_mic_free(snd_pcm_t *pcm)
 {
-	emu10k1_t *emu = snd_magic_cast(emu10k1_t, pcm->private_data, return);
+	emu10k1_t *emu = pcm->private_data;
 	emu->pcm_mic = NULL;
 	snd_pcm_lib_preallocate_free_for_all(pcm);
 }
@@ -1070,21 +1077,19 @@
 static int snd_emu10k1_pcm_efx_voices_mask_get(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
 {
 	emu10k1_t *emu = snd_kcontrol_chip(kcontrol);
-	unsigned long flags;
 	int nefx = emu->audigy ? 64 : 32;
 	int idx;
 	
-	spin_lock_irqsave(&emu->reg_lock, flags);
+	spin_lock_irq(&emu->reg_lock);
 	for (idx = 0; idx < nefx; idx++)
 		ucontrol->value.integer.value[idx] = (emu->efx_voices_mask[idx / 32] & (1 << (idx % 32))) ? 1 : 0;
-	spin_unlock_irqrestore(&emu->reg_lock, flags);
+	spin_unlock_irq(&emu->reg_lock);
 	return 0;
 }
 
 static int snd_emu10k1_pcm_efx_voices_mask_put(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
 {
 	emu10k1_t *emu = snd_kcontrol_chip(kcontrol);
-	unsigned long flags;
 	unsigned int nval[2], bits;
 	int nefx = emu->audigy ? 64 : 32;
 	int change, idx;
@@ -1097,12 +1102,12 @@
 		}
 	if (bits != 1 && bits != 2 && bits != 4 && bits != 8)
 		return -EINVAL;
-	spin_lock_irqsave(&emu->reg_lock, flags);
+	spin_lock_irq(&emu->reg_lock);
 	change = (nval[0] != emu->efx_voices_mask[0]) ||
 		(nval[1] != emu->efx_voices_mask[1]);
 	emu->efx_voices_mask[0] = nval[0];
 	emu->efx_voices_mask[1] = nval[1];
-	spin_unlock_irqrestore(&emu->reg_lock, flags);
+	spin_unlock_irq(&emu->reg_lock);
 	return change;
 }
 
@@ -1125,9 +1130,238 @@
 	.pointer =		snd_emu10k1_capture_pointer,
 };
 
+
+/* EFX playback */
+
+#define INITIAL_TRAM_SHIFT     14
+#define INITIAL_TRAM_POS(size) ((((size) / 2) - INITIAL_TRAM_SHIFT) - 1)
+
+static void snd_emu10k1_fx8010_playback_irq(emu10k1_t *emu, void *private_data)
+{
+	snd_pcm_substream_t *substream = private_data;
+	snd_pcm_period_elapsed(substream);
+}
+
+static void snd_emu10k1_fx8010_playback_tram_poke1(unsigned short *dst_left,
+						   unsigned short *dst_right,
+						   unsigned short *src,
+						   unsigned int count,
+						   unsigned int tram_shift)
+{
+	// printk("tram_poke1: dst_left = 0x%p, dst_right = 0x%p, src = 0x%p, count = 0x%x\n", dst_left, dst_right, src, count);
+	if ((tram_shift & 1) == 0) {
+		while (count--) {
+			*dst_left-- = *src++;
+			*dst_right-- = *src++;
+		}
+	} else {
+		while (count--) {
+			*dst_right-- = *src++;
+			*dst_left-- = *src++;
+		}
+	}
+}
+
+static void fx8010_pb_trans_copy(snd_pcm_substream_t *substream,
+				 snd_pcm_indirect_t *rec, size_t bytes)
+{
+	emu10k1_t *emu = snd_pcm_substream_chip(substream);
+	snd_emu10k1_fx8010_pcm_t *pcm = &emu->fx8010.pcm[substream->number];
+	unsigned int tram_size = pcm->buffer_size;
+	unsigned short *src = (unsigned short *)(substream->runtime->dma_area + rec->sw_data);
+	unsigned int frames = bytes >> 2, count;
+	unsigned int tram_pos = pcm->tram_pos;
+	unsigned int tram_shift = pcm->tram_shift;
+
+	while (frames > tram_pos) {
+		count = tram_pos + 1;
+		snd_emu10k1_fx8010_playback_tram_poke1((unsigned short *)emu->fx8010.etram_pages.area + tram_pos,
+						       (unsigned short *)emu->fx8010.etram_pages.area + tram_pos + tram_size / 2,
+						       src, count, tram_shift);
+		src += count * 2;
+		frames -= count;
+		tram_pos = (tram_size / 2) - 1;
+		tram_shift++;
+	}
+	snd_emu10k1_fx8010_playback_tram_poke1((unsigned short *)emu->fx8010.etram_pages.area + tram_pos,
+					       (unsigned short *)emu->fx8010.etram_pages.area + tram_pos + tram_size / 2,
+					       src, frames, tram_shift++);
+	tram_pos -= frames;
+	pcm->tram_pos = tram_pos;
+	pcm->tram_shift = tram_shift;
+}
+
+static int snd_emu10k1_fx8010_playback_transfer(snd_pcm_substream_t *substream)
+{
+	emu10k1_t *emu = snd_pcm_substream_chip(substream);
+	snd_emu10k1_fx8010_pcm_t *pcm = &emu->fx8010.pcm[substream->number];
+
+	snd_pcm_indirect_playback_transfer(substream, &pcm->pcm_rec, fx8010_pb_trans_copy);
+	return 0;
+}
+
+static int snd_emu10k1_fx8010_playback_hw_params(snd_pcm_substream_t * substream,
+						 snd_pcm_hw_params_t * hw_params)
+{
+	return snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(hw_params));
+}
+
+static int snd_emu10k1_fx8010_playback_hw_free(snd_pcm_substream_t * substream)
+{
+	emu10k1_t *emu = snd_pcm_substream_chip(substream);
+	snd_emu10k1_fx8010_pcm_t *pcm = &emu->fx8010.pcm[substream->number];
+	unsigned int i;
+
+	for (i = 0; i < pcm->channels; i++)
+		snd_emu10k1_ptr_write(emu, TANKMEMADDRREGBASE + 0x80 + pcm->etram[i], 0, 0);
+	snd_pcm_lib_free_pages(substream);
+	return 0;
+}
+
+static int snd_emu10k1_fx8010_playback_prepare(snd_pcm_substream_t * substream)
+{
+	emu10k1_t *emu = snd_pcm_substream_chip(substream);
+	snd_pcm_runtime_t *runtime = substream->runtime;
+	snd_emu10k1_fx8010_pcm_t *pcm = &emu->fx8010.pcm[substream->number];
+	unsigned int i;
+	
+	// printk("prepare: etram_pages = 0x%p, dma_area = 0x%x, buffer_size = 0x%x (0x%x)\n", emu->fx8010.etram_pages, runtime->dma_area, runtime->buffer_size, runtime->buffer_size << 2);
+	memset(&pcm->pcm_rec, 0, sizeof(pcm->pcm_rec));
+	pcm->pcm_rec.hw_buffer_size = pcm->buffer_size * 2; /* byte size */
+	pcm->pcm_rec.sw_buffer_size = snd_pcm_lib_buffer_bytes(substream);
+	pcm->tram_pos = INITIAL_TRAM_POS(pcm->buffer_size);
+	pcm->tram_shift = 0;
+	snd_emu10k1_ptr_write(emu, emu->gpr_base + pcm->gpr_running, 0, 0);	/* reset */
+	snd_emu10k1_ptr_write(emu, emu->gpr_base + pcm->gpr_trigger, 0, 0);	/* reset */
+	snd_emu10k1_ptr_write(emu, emu->gpr_base + pcm->gpr_size, 0, runtime->buffer_size);
+	snd_emu10k1_ptr_write(emu, emu->gpr_base + pcm->gpr_ptr, 0, 0);		/* reset ptr number */
+	snd_emu10k1_ptr_write(emu, emu->gpr_base + pcm->gpr_count, 0, runtime->period_size);
+	snd_emu10k1_ptr_write(emu, emu->gpr_base + pcm->gpr_tmpcount, 0, runtime->period_size);
+	for (i = 0; i < pcm->channels; i++)
+		snd_emu10k1_ptr_write(emu, TANKMEMADDRREGBASE + 0x80 + pcm->etram[i], 0, (TANKMEMADDRREG_READ|TANKMEMADDRREG_ALIGN) + i * (runtime->buffer_size / pcm->channels));
+	return 0;
+}
+
+static int snd_emu10k1_fx8010_playback_trigger(snd_pcm_substream_t * substream, int cmd)
+{
+	emu10k1_t *emu = snd_pcm_substream_chip(substream);
+	snd_emu10k1_fx8010_pcm_t *pcm = &emu->fx8010.pcm[substream->number];
+	int result = 0;
+
+	spin_lock(&emu->reg_lock);
+	switch (cmd) {
+	case SNDRV_PCM_TRIGGER_START:
+		/* follow thru */
+	case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
+#ifdef EMU10K1_SET_AC3_IEC958
+	{
+		int i;
+		for (i = 0; i < 3; i++) {
+			unsigned int bits;
+			bits = SPCS_CLKACCY_1000PPM | SPCS_SAMPLERATE_48 |
+			       SPCS_CHANNELNUM_LEFT | SPCS_SOURCENUM_UNSPEC | SPCS_GENERATIONSTATUS |
+			       0x00001200 | SPCS_EMPHASIS_NONE | SPCS_COPYRIGHT | SPCS_NOTAUDIODATA;
+			snd_emu10k1_ptr_write(emu, SPCS0 + i, 0, bits);
+		}
+	}
+#endif
+		result = snd_emu10k1_fx8010_register_irq_handler(emu, snd_emu10k1_fx8010_playback_irq, pcm->gpr_running, substream, &pcm->irq);
+		if (result < 0)
+			goto __err;
+		snd_emu10k1_fx8010_playback_transfer(substream);	/* roll the ball */
+		snd_emu10k1_ptr_write(emu, emu->gpr_base + pcm->gpr_trigger, 0, 1);
+		break;
+	case SNDRV_PCM_TRIGGER_STOP:
+	case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
+		snd_emu10k1_fx8010_unregister_irq_handler(emu, pcm->irq); pcm->irq = NULL;
+		snd_emu10k1_ptr_write(emu, emu->gpr_base + pcm->gpr_trigger, 0, 0);
+		pcm->tram_pos = INITIAL_TRAM_POS(pcm->buffer_size);
+		pcm->tram_shift = 0;
+		break;
+	default:
+		result = -EINVAL;
+		break;
+	}
+      __err:
+	spin_unlock(&emu->reg_lock);
+	return result;
+}
+
+static snd_pcm_uframes_t snd_emu10k1_fx8010_playback_pointer(snd_pcm_substream_t * substream)
+{
+	emu10k1_t *emu = snd_pcm_substream_chip(substream);
+	snd_emu10k1_fx8010_pcm_t *pcm = &emu->fx8010.pcm[substream->number];
+	size_t ptr; /* byte pointer */
+
+	if (!snd_emu10k1_ptr_read(emu, emu->gpr_base + pcm->gpr_trigger, 0))
+		return 0;
+	ptr = snd_emu10k1_ptr_read(emu, emu->gpr_base + pcm->gpr_ptr, 0) << 2;
+	return snd_pcm_indirect_playback_pointer(substream, &pcm->pcm_rec, ptr);
+}
+
+static snd_pcm_hardware_t snd_emu10k1_fx8010_playback =
+{
+	.info =			(SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED |
+				 /* SNDRV_PCM_INFO_MMAP_VALID | */ SNDRV_PCM_INFO_PAUSE),
+	.formats =		SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S16_LE,
+	.rates =		SNDRV_PCM_RATE_48000,
+	.rate_min =		48000,
+	.rate_max =		48000,
+	.channels_min =		1,
+	.channels_max =		1,
+	.buffer_bytes_max =	(128*1024),
+	.period_bytes_min =	1024,
+	.period_bytes_max =	(128*1024),
+	.periods_min =		1,
+	.periods_max =		1024,
+	.fifo_size =		0,
+};
+
+static int snd_emu10k1_fx8010_playback_open(snd_pcm_substream_t * substream)
+{
+	emu10k1_t *emu = snd_pcm_substream_chip(substream);
+	snd_pcm_runtime_t *runtime = substream->runtime;
+	snd_emu10k1_fx8010_pcm_t *pcm = &emu->fx8010.pcm[substream->number];
+
+	runtime->hw = snd_emu10k1_fx8010_playback;
+	runtime->hw.channels_min = runtime->hw.channels_max = pcm->channels;
+	runtime->hw.period_bytes_max = (pcm->buffer_size * 2) / 2;
+	spin_lock_irq(&emu->reg_lock);
+	if (pcm->valid == 0) {
+		spin_unlock_irq(&emu->reg_lock);
+		return -ENODEV;
+	}
+	pcm->opened = 1;
+	spin_unlock_irq(&emu->reg_lock);
+	return 0;
+}
+
+static int snd_emu10k1_fx8010_playback_close(snd_pcm_substream_t * substream)
+{
+	emu10k1_t *emu = snd_pcm_substream_chip(substream);
+	snd_emu10k1_fx8010_pcm_t *pcm = &emu->fx8010.pcm[substream->number];
+
+	spin_lock_irq(&emu->reg_lock);
+	pcm->opened = 0;
+	spin_unlock_irq(&emu->reg_lock);
+	return 0;
+}
+
+static snd_pcm_ops_t snd_emu10k1_fx8010_playback_ops = {
+	.open =			snd_emu10k1_fx8010_playback_open,
+	.close =		snd_emu10k1_fx8010_playback_close,
+	.ioctl =		snd_pcm_lib_ioctl,
+	.hw_params =		snd_emu10k1_fx8010_playback_hw_params,
+	.hw_free =		snd_emu10k1_fx8010_playback_hw_free,
+	.prepare =		snd_emu10k1_fx8010_playback_prepare,
+	.trigger =		snd_emu10k1_fx8010_playback_trigger,
+	.pointer =		snd_emu10k1_fx8010_playback_pointer,
+	.ack =			snd_emu10k1_fx8010_playback_transfer,
+};
+
 static void snd_emu10k1_pcm_efx_free(snd_pcm_t *pcm)
 {
-	emu10k1_t *emu = snd_magic_cast(emu10k1_t, pcm->private_data, return);
+	emu10k1_t *emu = pcm->private_data;
 	emu->pcm_efx = NULL;
 	snd_pcm_lib_preallocate_free_for_all(pcm);
 }
@@ -1140,12 +1374,13 @@
 	if (rpcm)
 		*rpcm = NULL;
 
-	if ((err = snd_pcm_new(emu->card, "emu10k1 efx", device, 0, 1, &pcm)) < 0)
+	if ((err = snd_pcm_new(emu->card, "emu10k1 efx", device, 8, 1, &pcm)) < 0)
 		return err;
 
 	pcm->private_data = emu;
 	pcm->private_free = snd_emu10k1_pcm_efx_free;
 
+	snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_emu10k1_fx8010_playback_ops);
 	snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_emu10k1_capture_efx_ops);
 
 	pcm->info_flags = 0;
diff -Nru a/sound/pci/emu10k1/emuproc.c b/sound/pci/emu10k1/emuproc.c
--- a/sound/pci/emu10k1/emuproc.c	2004-10-18 14:56:28 -07:00
+++ b/sound/pci/emu10k1/emuproc.c	2004-10-18 14:56:28 -07:00
@@ -71,31 +71,32 @@
 static void snd_emu10k1_proc_read(snd_info_entry_t *entry, 
 				  snd_info_buffer_t * buffer)
 {
-	static char *outputs[32] = {
-		/* 00 */ "PCM Left",
-		/* 01 */ "PCM Right",
-		/* 02 */ "PCM Surround Left",
-		/* 03 */ "PCM Surround Right",
-		/* 04 */ "MIDI Left",
-		/* 05 */ "MIDI Right",
-		/* 06 */ "PCM Center",
-		/* 07 */ "PCM LFE",
-		/* 08 */ "???",
-		/* 09 */ "???",
-		/* 10 */ "???",
-		/* 11 */ "???",
-		/* 12 */ "MIDI Reverb",
-		/* 13 */ "MIDI Chorus",
-		/* 14 */ "???",
+	/* FIXME - output names are in emufx.c too */
+	static char *creative_outs[32] = {
+		/* 00 */ "AC97 Left",
+		/* 01 */ "AC97 Right",
+		/* 02 */ "Optical IEC958 Left",
+		/* 03 */ "Optical IEC958 Right",
+		/* 04 */ "Center",
+		/* 05 */ "LFE",
+		/* 06 */ "Headphone Left",
+		/* 07 */ "Headphone Right",
+		/* 08 */ "Surround Left",
+		/* 09 */ "Surround Right",
+		/* 10 */ "PCM Capture Left",
+		/* 11 */ "PCM Capture Right",
+		/* 12 */ "MIC Capture",
+		/* 13 */ "AC97 Surround Left",
+		/* 14 */ "AC97 Surround Right",
 		/* 15 */ "???",
 		/* 16 */ "???",
-		/* 17 */ "???",
-		/* 18 */ "ADC Left / CDROM S/PDIF Left",
-		/* 19 */ "ADC Right / CDROM S/PDIF Right",
-		/* 20 */ "MIC / Zoom Video Left",
-		/* 21 */ "Zoom Video Right",
-		/* 22 */ "S/PDIF Left",
-		/* 23 */ "S/PDIF Right",
+		/* 17 */ "Analog Center",
+		/* 18 */ "Analog LFE",
+		/* 19 */ "???",
+		/* 20 */ "???",
+		/* 21 */ "???",
+		/* 22 */ "???",
+		/* 23 */ "???",
 		/* 24 */ "???",
 		/* 25 */ "???",
 		/* 26 */ "???",
@@ -105,9 +106,78 @@
 		/* 30 */ "???",
 		/* 31 */ "???"
 	};
-	emu10k1_t *emu = snd_magic_cast(emu10k1_t, entry->private_data, return);
+
+	static char *audigy_outs[64] = {
+		/* 00 */ "Digital Front Left",
+		/* 01 */ "Digital Front Right",
+		/* 02 */ "Digital Center",
+		/* 03 */ "Digital LEF",
+		/* 04 */ "Headphone Left",
+		/* 05 */ "Headphone Right",
+		/* 06 */ "Digital Rear Left",
+		/* 07 */ "Digital Rear Right",
+		/* 08 */ "Front Left",
+		/* 09 */ "Front Right",
+		/* 10 */ "Center",
+		/* 11 */ "LFE",
+		/* 12 */ "???",
+		/* 13 */ "???",
+		/* 14 */ "Rear Left",
+		/* 15 */ "Rear Right",
+		/* 16 */ "AC97 Front Left",
+		/* 17 */ "AC97 Front Right",
+		/* 18 */ "ADC Caputre Left",
+		/* 19 */ "ADC Capture Right",
+		/* 20 */ "???",
+		/* 21 */ "???",
+		/* 22 */ "???",
+		/* 23 */ "???",
+		/* 24 */ "???",
+		/* 25 */ "???",
+		/* 26 */ "???",
+		/* 27 */ "???",
+		/* 28 */ "???",
+		/* 29 */ "???",
+		/* 30 */ "???",
+		/* 31 */ "???",
+		/* 32 */ "???",
+		/* 33 */ "???",
+		/* 34 */ "???",
+		/* 35 */ "???",
+		/* 36 */ "???",
+		/* 37 */ "???",
+		/* 38 */ "???",
+		/* 39 */ "???",
+		/* 40 */ "???",
+		/* 41 */ "???",
+		/* 42 */ "???",
+		/* 43 */ "???",
+		/* 44 */ "???",
+		/* 45 */ "???",
+		/* 46 */ "???",
+		/* 47 */ "???",
+		/* 48 */ "???",
+		/* 49 */ "???",
+		/* 50 */ "???",
+		/* 51 */ "???",
+		/* 52 */ "???",
+		/* 53 */ "???",
+		/* 54 */ "???",
+		/* 55 */ "???",
+		/* 56 */ "???",
+		/* 57 */ "???",
+		/* 58 */ "???",
+		/* 59 */ "???",
+		/* 60 */ "???",
+		/* 61 */ "???",
+		/* 62 */ "???",
+		/* 33 */ "???"
+	};
+
+	emu10k1_t *emu = entry->private_data;
 	unsigned int val;
 	int nefx = emu->audigy ? 64 : 32;
+	char **outputs = emu->audigy ? audigy_outs : creative_outs;
 	int idx;
 	
 	snd_iprintf(buffer, "EMU10K1\n\n");
@@ -117,7 +187,7 @@
 	snd_iprintf(buffer, "Card                  : %s\n",
 		    emu->audigy ? "Audigy" : (emu->APS ? "EMU APS" : "Creative"));
 	snd_iprintf(buffer, "Internal TRAM (words) : 0x%x\n", emu->fx8010.itram_size);
-	snd_iprintf(buffer, "External TRAM (words) : 0x%x\n", emu->fx8010.etram_pages.bytes);
+	snd_iprintf(buffer, "External TRAM (words) : 0x%x\n", (int)emu->fx8010.etram_pages.bytes);
 	snd_iprintf(buffer, "\n");
 	if (emu->audigy) {
 		snd_iprintf(buffer, "Effect Send Routing   : A=%i, B=%i, C=%i, D=%i\n",
@@ -135,7 +205,7 @@
 	snd_iprintf(buffer, "\nCaptured FX Outputs   :\n");
 	for (idx = 0; idx < nefx; idx++) {
 		if (emu->efx_voices_mask[idx/32] & (1 << (idx%32)))
-			snd_iprintf(buffer, "  Output %02i [%s]\n", idx, outputs[idx%32]);
+			snd_iprintf(buffer, "  Output %02i [%s]\n", idx, outputs[idx]);
 	}
 	snd_iprintf(buffer, "\nAll FX Outputs        :\n");
 	for (idx = 0; idx < 32; idx++)
@@ -155,7 +225,7 @@
 				        snd_info_buffer_t * buffer)
 {
 	u32 pc;
-	emu10k1_t *emu = snd_magic_cast(emu10k1_t, entry->private_data, return);
+	emu10k1_t *emu = entry->private_data;
 
 	snd_iprintf(buffer, "FX8010 Instruction List '%s'\n", emu->fx8010.name);
 	snd_iprintf(buffer, "  Code dump      :\n");
@@ -195,7 +265,7 @@
 				    unsigned long count, unsigned long pos)
 {
 	long size;
-	emu10k1_t *emu = snd_magic_cast(emu10k1_t, entry->private_data, return -ENXIO);
+	emu10k1_t *emu = entry->private_data;
 	unsigned int offset;
 	
 	if (!strcmp(entry->name, "fx8010_tram_addr")) {
diff -Nru a/sound/pci/emu10k1/io.c b/sound/pci/emu10k1/io.c
--- a/sound/pci/emu10k1/io.c	2004-10-18 14:56:28 -07:00
+++ b/sound/pci/emu10k1/io.c	2004-10-18 14:56:28 -07:00
@@ -231,7 +231,7 @@
 
 unsigned short snd_emu10k1_ac97_read(ac97_t *ac97, unsigned short reg)
 {
-	emu10k1_t *emu = snd_magic_cast(emu10k1_t, ac97->private_data, return -ENXIO);
+	emu10k1_t *emu = ac97->private_data;
 	unsigned long flags;
 	unsigned short val;
 
@@ -244,7 +244,7 @@
 
 void snd_emu10k1_ac97_write(ac97_t *ac97, unsigned short reg, unsigned short data)
 {
-	emu10k1_t *emu = snd_magic_cast(emu10k1_t, ac97->private_data, return);
+	emu10k1_t *emu = ac97->private_data;
 	unsigned long flags;
 
 	spin_lock_irqsave(&emu->emu_lock, flags);
diff -Nru a/sound/pci/emu10k1/irq.c b/sound/pci/emu10k1/irq.c
--- a/sound/pci/emu10k1/irq.c	2004-10-18 14:56:49 -07:00
+++ b/sound/pci/emu10k1/irq.c	2004-10-18 14:56:49 -07:00
@@ -32,7 +32,7 @@
 
 irqreturn_t snd_emu10k1_interrupt(int irq, void *dev_id, struct pt_regs *regs)
 {
-	emu10k1_t *emu = snd_magic_cast(emu10k1_t, dev_id, return IRQ_NONE);
+	emu10k1_t *emu = dev_id;
 	unsigned int status, orig_status;
 	int handled = 0;
 
diff -Nru a/sound/pci/emu10k1/memory.c b/sound/pci/emu10k1/memory.c
--- a/sound/pci/emu10k1/memory.c	2004-10-18 14:57:03 -07:00
+++ b/sound/pci/emu10k1/memory.c	2004-10-18 14:57:03 -07:00
@@ -22,6 +22,7 @@
  */
 
 #include <sound/driver.h>
+#include <linux/pci.h>
 #include <linux/time.h>
 #include <sound/core.h>
 #include <sound/emu10k1.h>
@@ -291,7 +292,7 @@
 snd_emu10k1_alloc_pages(emu10k1_t *emu, snd_pcm_substream_t *substream)
 {
 	snd_pcm_runtime_t *runtime = substream->runtime;
-	struct snd_sg_buf *sgbuf = runtime->dma_private;
+	struct snd_sg_buf *sgbuf = snd_pcm_substream_sgbuf(substream);
 	snd_util_memhdr_t *hdr;
 	emu10k1_memblk_t *blk;
 	int page, err, idx;
@@ -441,10 +442,11 @@
 	get_single_page_range(emu->memhdr, blk, &first_page, &last_page);
 	/* allocate kernel pages */
 	for (page = first_page; page <= last_page; page++) {
-		if (snd_dma_alloc_pages(&emu->dma_dev, PAGE_SIZE, &dmab) < 0)
+		if (snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, snd_dma_pci_data(emu->pci),
+					PAGE_SIZE, &dmab) < 0)
 			goto __fail;
 		if (! is_valid_page(emu, dmab.addr)) {
-			snd_dma_free_pages(&emu->dma_dev, &dmab);
+			snd_dma_free_pages(&dmab);
 			goto __fail;
 		}
 		emu->page_addr_table[page] = dmab.addr;
@@ -459,7 +461,7 @@
 		dmab.area = emu->page_ptr_table[page];
 		dmab.addr = emu->page_addr_table[page];
 		dmab.bytes = PAGE_SIZE;
-		snd_dma_free_pages(&emu->dma_dev, &dmab);
+		snd_dma_free_pages(&dmab);
 		emu->page_addr_table[page] = 0;
 		emu->page_ptr_table[page] = NULL;
 	}
@@ -476,13 +478,15 @@
 	struct snd_dma_buffer dmab;
 
 	get_single_page_range(emu->memhdr, blk, &first_page, &last_page);
+	dmab.dev.type = SNDRV_DMA_TYPE_DEV;
+	dmab.dev.dev = snd_dma_pci_data(emu->pci);
 	for (page = first_page; page <= last_page; page++) {
 		if (emu->page_ptr_table[page] == NULL)
 			continue;
 		dmab.area = emu->page_ptr_table[page];
 		dmab.addr = emu->page_addr_table[page];
 		dmab.bytes = PAGE_SIZE;
-		snd_dma_free_pages(&emu->dma_dev, &dmab);
+		snd_dma_free_pages(&dmab);
 		emu->page_addr_table[page] = 0;
 		emu->page_ptr_table[page] = NULL;
 	}
diff -Nru a/sound/pci/ens1370.c b/sound/pci/ens1370.c
--- a/sound/pci/ens1370.c	2004-10-18 14:56:49 -07:00
+++ b/sound/pci/ens1370.c	2004-10-18 14:56:49 -07:00
@@ -40,8 +40,6 @@
 #include <sound/initval.h>
 #include <sound/asoundef.h>
 
-#define chip_t ensoniq_t
-
 #ifndef CHIP1371
 #undef CHIP1370
 #define CHIP1370
@@ -56,15 +54,14 @@
 
 MODULE_AUTHOR("Jaroslav Kysela <perex@suse.cz>, Thomas Sailer <sailer@ife.ee.ethz.ch>");
 MODULE_LICENSE("GPL");
-MODULE_CLASSES("{sound}");
 #ifdef CHIP1370
 MODULE_DESCRIPTION("Ensoniq AudioPCI ES1370");
-MODULE_DEVICES("{{Ensoniq,AudioPCI-97 ES1370},"
+MODULE_SUPPORTED_DEVICE("{{Ensoniq,AudioPCI-97 ES1370},"
 	        "{Creative Labs,SB PCI64/128 (ES1370)}}");
 #endif
 #ifdef CHIP1371
 MODULE_DESCRIPTION("Ensoniq/Creative AudioPCI ES1371+");
-MODULE_DEVICES("{{Ensoniq,AudioPCI ES1371/73},"
+MODULE_SUPPORTED_DEVICE("{{Ensoniq,AudioPCI ES1371/73},"
 		"{Ensoniq,AudioPCI ES1373},"
 		"{Creative Labs,Ectiva EV1938},"
 		"{Creative Labs,SB PCI64/128 (ES1371/73)},"
@@ -90,22 +87,17 @@
 
 module_param_array(index, int, boot_devs, 0444);
 MODULE_PARM_DESC(index, "Index value for Ensoniq AudioPCI soundcard.");
-MODULE_PARM_SYNTAX(index, SNDRV_INDEX_DESC);
 module_param_array(id, charp, boot_devs, 0444);
 MODULE_PARM_DESC(id, "ID string for Ensoniq AudioPCI soundcard.");
-MODULE_PARM_SYNTAX(id, SNDRV_ID_DESC);
 module_param_array(enable, bool, boot_devs, 0444);
 MODULE_PARM_DESC(enable, "Enable Ensoniq AudioPCI soundcard.");
-MODULE_PARM_SYNTAX(enable, SNDRV_ENABLE_DESC);
 #ifdef SUPPORT_JOYSTICK
 #ifdef CHIP1371
 module_param_array(joystick_port, int, boot_devs, 0444);
 MODULE_PARM_DESC(joystick_port, "Joystick port address.");
-MODULE_PARM_SYNTAX(joystick_port, SNDRV_ENABLED ",allows:{{0},{1},{0x200},{0x208},{0x210},{0x218}},dialog:list");
 #else
 module_param_array(joystick, bool, boot_devs, 0444);
 MODULE_PARM_DESC(joystick, "Enable joystick.");
-MODULE_PARM_SYNTAX(joystick, SNDRV_ENABLED "," SNDRV_BOOLEAN_FALSE_DESC);
 #endif
 #endif /* SUPPORT_JOYSTICK */
 
@@ -388,7 +380,6 @@
 	unsigned long capture3size;
 
 	unsigned long port;
-	struct resource *res_port;
 	unsigned int mode;
 	unsigned int uartm;	/* UART mode */
 
@@ -435,7 +426,6 @@
 	unsigned int spdif_stream;
 
 #ifdef CHIP1370
-	struct snd_dma_device dma_dev;
 	struct snd_dma_buffer dma_bug;
 #endif
 
@@ -581,7 +571,7 @@
 static void snd_es1370_codec_write(ak4531_t *ak4531,
 				   unsigned short reg, unsigned short val)
 {
-	ensoniq_t *ensoniq = snd_magic_cast(ensoniq_t, ak4531->private_data, return);
+	ensoniq_t *ensoniq = ak4531->private_data;
 	unsigned long flags;
 	unsigned long end_time = jiffies + HZ / 10;
 
@@ -611,7 +601,7 @@
 static void snd_es1371_codec_write(ac97_t *ac97,
 				   unsigned short reg, unsigned short val)
 {
-	ensoniq_t *ensoniq = snd_magic_cast(ensoniq_t, ac97->private_data, return);
+	ensoniq_t *ensoniq = ac97->private_data;
 	unsigned long flags;
 	unsigned int t, x;
 
@@ -649,7 +639,7 @@
 static unsigned short snd_es1371_codec_read(ac97_t *ac97,
 					    unsigned short reg)
 {
-	ensoniq_t *ensoniq = snd_magic_cast(ensoniq_t, ac97->private_data, return -ENXIO);
+	ensoniq_t *ensoniq = ac97->private_data;
 	unsigned long flags;
 	unsigned int t, x, fail = 0;
 
@@ -844,7 +834,6 @@
 
 static int snd_ensoniq_playback1_prepare(snd_pcm_substream_t * substream)
 {
-	unsigned long flags;
 	ensoniq_t *ensoniq = snd_pcm_substream_chip(substream);
 	snd_pcm_runtime_t *runtime = substream->runtime;
 	unsigned int mode = 0;
@@ -855,7 +844,7 @@
 		mode |= 0x02;
 	if (runtime->channels > 1)
 		mode |= 0x01;
-	spin_lock_irqsave(&ensoniq->reg_lock, flags);
+	spin_lock_irq(&ensoniq->reg_lock);
 	ensoniq->ctrl &= ~ES_DAC1_EN;
 	outl(ensoniq->ctrl, ES_REG(ensoniq, CONTROL));
 	outl(ES_MEM_PAGEO(ES_PAGE_DAC), ES_REG(ensoniq, MEM_PAGE));
@@ -878,13 +867,12 @@
 	snd_es1371_dac1_rate(ensoniq, runtime->rate);
 #endif
 	outl(ensoniq->ctrl, ES_REG(ensoniq, CONTROL));
-	spin_unlock_irqrestore(&ensoniq->reg_lock, flags);
+	spin_unlock_irq(&ensoniq->reg_lock);
 	return 0;
 }
 
 static int snd_ensoniq_playback2_prepare(snd_pcm_substream_t * substream)
 {
-	unsigned long flags;
 	ensoniq_t *ensoniq = snd_pcm_substream_chip(substream);
 	snd_pcm_runtime_t *runtime = substream->runtime;
 	unsigned int mode = 0;
@@ -895,7 +883,7 @@
 		mode |= 0x02;
 	if (runtime->channels > 1)
 		mode |= 0x01;
-	spin_lock_irqsave(&ensoniq->reg_lock, flags);
+	spin_lock_irq(&ensoniq->reg_lock);
 	ensoniq->ctrl &= ~ES_DAC2_EN;
 	outl(ensoniq->ctrl, ES_REG(ensoniq, CONTROL));
 	outl(ES_MEM_PAGEO(ES_PAGE_DAC), ES_REG(ensoniq, MEM_PAGE));
@@ -917,13 +905,12 @@
 	snd_es1371_dac2_rate(ensoniq, runtime->rate);
 #endif
 	outl(ensoniq->ctrl, ES_REG(ensoniq, CONTROL));
-	spin_unlock_irqrestore(&ensoniq->reg_lock, flags);
+	spin_unlock_irq(&ensoniq->reg_lock);
 	return 0;
 }
 
 static int snd_ensoniq_capture_prepare(snd_pcm_substream_t * substream)
 {
-	unsigned long flags;
 	ensoniq_t *ensoniq = snd_pcm_substream_chip(substream);
 	snd_pcm_runtime_t *runtime = substream->runtime;
 	unsigned int mode = 0;
@@ -934,7 +921,7 @@
 		mode |= 0x02;
 	if (runtime->channels > 1)
 		mode |= 0x01;
-	spin_lock_irqsave(&ensoniq->reg_lock, flags);
+	spin_lock_irq(&ensoniq->reg_lock);
 	ensoniq->ctrl &= ~ES_ADC_EN;
 	outl(ensoniq->ctrl, ES_REG(ensoniq, CONTROL));
 	outl(ES_MEM_PAGEO(ES_PAGE_ADC), ES_REG(ensoniq, MEM_PAGE));
@@ -954,7 +941,7 @@
 	snd_es1371_adc_rate(ensoniq, runtime->rate);
 #endif
 	outl(ensoniq->ctrl, ES_REG(ensoniq, CONTROL));
-	spin_unlock_irqrestore(&ensoniq->reg_lock, flags);
+	spin_unlock_irq(&ensoniq->reg_lock);
 	return 0;
 }
 
@@ -1151,31 +1138,29 @@
 
 static int snd_ensoniq_playback2_close(snd_pcm_substream_t * substream)
 {
-	unsigned long flags;
 	ensoniq_t *ensoniq = snd_pcm_substream_chip(substream);
 
 	ensoniq->playback2_substream = NULL;
-	spin_lock_irqsave(&ensoniq->reg_lock, flags);
+	spin_lock_irq(&ensoniq->reg_lock);
 #ifdef CHIP1370
 	ensoniq->u.es1370.pclkdiv_lock &= ~ES_MODE_PLAY2;
 #endif
 	ensoniq->mode &= ~ES_MODE_PLAY2;
-	spin_unlock_irqrestore(&ensoniq->reg_lock, flags);
+	spin_unlock_irq(&ensoniq->reg_lock);
 	return 0;
 }
 
 static int snd_ensoniq_capture_close(snd_pcm_substream_t * substream)
 {
-	unsigned long flags;
 	ensoniq_t *ensoniq = snd_pcm_substream_chip(substream);
 
 	ensoniq->capture_substream = NULL;
-	spin_lock_irqsave(&ensoniq->reg_lock, flags);
+	spin_lock_irq(&ensoniq->reg_lock);
 #ifdef CHIP1370
 	ensoniq->u.es1370.pclkdiv_lock &= ~ES_MODE_CAPTURE;
 #endif
 	ensoniq->mode &= ~ES_MODE_CAPTURE;
-	spin_unlock_irqrestore(&ensoniq->reg_lock, flags);
+	spin_unlock_irq(&ensoniq->reg_lock);
 	return 0;
 }
 
@@ -1214,7 +1199,7 @@
 
 static void snd_ensoniq_pcm_free(snd_pcm_t *pcm)
 {
-	ensoniq_t *ensoniq = snd_magic_cast(ensoniq_t, pcm->private_data, return);
+	ensoniq_t *ensoniq = pcm->private_data;
 	ensoniq->pcm1 = NULL;
 	snd_pcm_lib_preallocate_free_for_all(pcm);
 }
@@ -1261,7 +1246,7 @@
 
 static void snd_ensoniq_pcm_free2(snd_pcm_t *pcm)
 {
-	ensoniq_t *ensoniq = snd_magic_cast(ensoniq_t, pcm->private_data, return);
+	ensoniq_t *ensoniq = pcm->private_data;
 	ensoniq->pcm2 = NULL;
 	snd_pcm_lib_preallocate_free_for_all(pcm);
 }
@@ -1565,7 +1550,7 @@
 
 static void snd_ensoniq_mixer_free_ac97(ac97_t *ac97)
 {
-	ensoniq_t *ensoniq = snd_magic_cast(ensoniq_t, ac97->private_data, return);
+	ensoniq_t *ensoniq = ac97->private_data;
 	ensoniq->u.es1371.ac97 = NULL;
 }
 
@@ -1585,14 +1570,15 @@
 static int snd_ensoniq_1371_mixer(ensoniq_t * ensoniq)
 {
 	snd_card_t *card = ensoniq->card;
-	ac97_bus_t bus, *pbus;
-	ac97_t ac97;
+	ac97_bus_t *pbus;
+	ac97_template_t ac97;
 	int err, idx;
+	static ac97_bus_ops_t ops = {
+		.write = snd_es1371_codec_write,
+		.read = snd_es1371_codec_read,
+	};
 
-	memset(&bus, 0, sizeof(bus));
-	bus.write = snd_es1371_codec_write;
-	bus.read = snd_es1371_codec_read;
-	if ((err = snd_ac97_bus(card, &bus, &pbus)) < 0)
+	if ((err = snd_ac97_bus(card, 0, &ops, NULL, &pbus)) < 0)
 		return err;
 
 	memset(&ac97, 0, sizeof(ac97));
@@ -1663,30 +1649,28 @@
 static int snd_ensoniq_control_get(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
 {
 	ensoniq_t *ensoniq = snd_kcontrol_chip(kcontrol);
-	unsigned long flags;
 	int mask = kcontrol->private_value;
 	
-	spin_lock_irqsave(&ensoniq->reg_lock, flags);
+	spin_lock_irq(&ensoniq->reg_lock);
 	ucontrol->value.integer.value[0] = ensoniq->ctrl & mask ? 1 : 0;
-	spin_unlock_irqrestore(&ensoniq->reg_lock, flags);
+	spin_unlock_irq(&ensoniq->reg_lock);
 	return 0;
 }
 
 static int snd_ensoniq_control_put(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
 {
 	ensoniq_t *ensoniq = snd_kcontrol_chip(kcontrol);
-	unsigned long flags;
 	int mask = kcontrol->private_value;
 	unsigned int nval;
 	int change;
 	
 	nval = ucontrol->value.integer.value[0] ? mask : 0;
-	spin_lock_irqsave(&ensoniq->reg_lock, flags);
+	spin_lock_irq(&ensoniq->reg_lock);
 	change = (ensoniq->ctrl & mask) != nval;
 	ensoniq->ctrl &= ~mask;
 	ensoniq->ctrl |= nval;
 	outl(ensoniq->ctrl, ES_REG(ensoniq, CONTROL));
-	spin_unlock_irqrestore(&ensoniq->reg_lock, flags);
+	spin_unlock_irq(&ensoniq->reg_lock);
 	return change;
 }
 
@@ -1703,7 +1687,7 @@
 
 static void snd_ensoniq_mixer_free_ak4531(ak4531_t *ak4531)
 {
-	ensoniq_t *ensoniq = snd_magic_cast(ensoniq_t, ak4531->private_data, return);
+	ensoniq_t *ensoniq = ak4531->private_data;
 	ensoniq->u.es1370.ak4531 = NULL;
 }
 
@@ -1785,7 +1769,7 @@
 static void snd_ensoniq_proc_read(snd_info_entry_t *entry, 
 				  snd_info_buffer_t * buffer)
 {
-	ensoniq_t *ensoniq = snd_magic_cast(ensoniq_t, entry->private_data, return);
+	ensoniq_t *ensoniq = entry->private_data;
 
 #ifdef CHIP1370
 	snd_iprintf(buffer, "Ensoniq AudioPCI ES1370\n\n");
@@ -1833,21 +1817,18 @@
       __hw_end:
 #ifdef CHIP1370
 	if (ensoniq->dma_bug.area)
-		snd_dma_free_pages(&ensoniq->dma_dev, &ensoniq->dma_bug);
+		snd_dma_free_pages(&ensoniq->dma_bug);
 #endif
-	if (ensoniq->res_port) {
-		release_resource(ensoniq->res_port);
-		kfree_nocheck(ensoniq->res_port);
-	}
 	if (ensoniq->irq >= 0)
 		free_irq(ensoniq->irq, (void *)ensoniq);
-	snd_magic_kfree(ensoniq);
+	pci_release_regions(ensoniq->pci);
+	kfree(ensoniq);
 	return 0;
 }
 
 static int snd_ensoniq_dev_free(snd_device_t *device)
 {
-	ensoniq_t *ensoniq = snd_magic_cast(ensoniq_t, device->device_data, return -ENXIO);
+	ensoniq_t *ensoniq = device->device_data;
 	return snd_ensoniq_free(ensoniq);
 }
 
@@ -1894,19 +1875,18 @@
 	*rensoniq = NULL;
 	if ((err = pci_enable_device(pci)) < 0)
 		return err;
-	ensoniq = snd_magic_kcalloc(ensoniq_t, 0, GFP_KERNEL);
+	ensoniq = kcalloc(1, sizeof(*ensoniq), GFP_KERNEL);
 	if (ensoniq == NULL)
 		return -ENOMEM;
 	spin_lock_init(&ensoniq->reg_lock);
 	ensoniq->card = card;
 	ensoniq->pci = pci;
 	ensoniq->irq = -1;
-	ensoniq->port = pci_resource_start(pci, 0);
-	if ((ensoniq->res_port = request_region(ensoniq->port, 0x40, "Ensoniq AudioPCI")) == NULL) {
-		snd_printk("unable to grab ports 0x%lx-0x%lx\n", ensoniq->port, ensoniq->port + 0x40 - 1);
-		snd_ensoniq_free(ensoniq);
-		return -EBUSY;
+	if ((err = pci_request_regions(pci, "Ensoniq AudioPCI")) < 0) {
+		kfree(ensoniq);
+		return err;
 	}
+	ensoniq->port = pci_resource_start(pci, 0);
 	if (request_irq(pci->irq, snd_audiopci_interrupt, SA_INTERRUPT|SA_SHIRQ, "Ensoniq AudioPCI", (void *)ensoniq)) {
 		snd_printk("unable to grab IRQ %d\n", pci->irq);
 		snd_ensoniq_free(ensoniq);
@@ -1914,10 +1894,8 @@
 	}
 	ensoniq->irq = pci->irq;
 #ifdef CHIP1370
-	memset(&ensoniq->dma_dev, 0, sizeof(ensoniq->dma_dev));
-	ensoniq->dma_dev.type = SNDRV_DMA_TYPE_DEV;
-	ensoniq->dma_dev.dev = snd_dma_pci_data(pci);
-	if (snd_dma_alloc_pages(&ensoniq->dma_dev, 16, &ensoniq->dma_bug) < 0) {
+	if (snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, snd_dma_pci_data(pci),
+				16, &ensoniq->dma_bug) < 0) {
 		snd_printk("unable to allocate space for phantom area - dma_bug\n");
 		snd_ensoniq_free(ensoniq);
 		return -EBUSY;
@@ -2074,10 +2052,9 @@
 
 static int snd_ensoniq_midi_input_open(snd_rawmidi_substream_t * substream)
 {
-	unsigned long flags;
-	ensoniq_t *ensoniq = snd_magic_cast(ensoniq_t, substream->rmidi->private_data, return -ENXIO);
+	ensoniq_t *ensoniq = substream->rmidi->private_data;
 
-	spin_lock_irqsave(&ensoniq->reg_lock, flags);
+	spin_lock_irq(&ensoniq->reg_lock);
 	ensoniq->uartm |= ES_MODE_INPUT;
 	ensoniq->midi_input = substream;
 	if (!(ensoniq->uartm & ES_MODE_OUTPUT)) {
@@ -2085,16 +2062,15 @@
 		outb(ensoniq->uartc = 0, ES_REG(ensoniq, UART_CONTROL));
 		outl(ensoniq->ctrl |= ES_UART_EN, ES_REG(ensoniq, CONTROL));
 	}
-	spin_unlock_irqrestore(&ensoniq->reg_lock, flags);
+	spin_unlock_irq(&ensoniq->reg_lock);
 	return 0;
 }
 
 static int snd_ensoniq_midi_input_close(snd_rawmidi_substream_t * substream)
 {
-	unsigned long flags;
-	ensoniq_t *ensoniq = snd_magic_cast(ensoniq_t, substream->rmidi->private_data, return -ENXIO);
+	ensoniq_t *ensoniq = substream->rmidi->private_data;
 
-	spin_lock_irqsave(&ensoniq->reg_lock, flags);
+	spin_lock_irq(&ensoniq->reg_lock);
 	if (!(ensoniq->uartm & ES_MODE_OUTPUT)) {
 		outb(ensoniq->uartc = 0, ES_REG(ensoniq, UART_CONTROL));
 		outl(ensoniq->ctrl &= ~ES_UART_EN, ES_REG(ensoniq, CONTROL));
@@ -2103,16 +2079,15 @@
 	}
 	ensoniq->midi_input = NULL;
 	ensoniq->uartm &= ~ES_MODE_INPUT;
-	spin_unlock_irqrestore(&ensoniq->reg_lock, flags);
+	spin_unlock_irq(&ensoniq->reg_lock);
 	return 0;
 }
 
 static int snd_ensoniq_midi_output_open(snd_rawmidi_substream_t * substream)
 {
-	unsigned long flags;
-	ensoniq_t *ensoniq = snd_magic_cast(ensoniq_t, substream->rmidi->private_data, return -ENXIO);
+	ensoniq_t *ensoniq = substream->rmidi->private_data;
 
-	spin_lock_irqsave(&ensoniq->reg_lock, flags);
+	spin_lock_irq(&ensoniq->reg_lock);
 	ensoniq->uartm |= ES_MODE_OUTPUT;
 	ensoniq->midi_output = substream;
 	if (!(ensoniq->uartm & ES_MODE_INPUT)) {
@@ -2120,16 +2095,15 @@
 		outb(ensoniq->uartc = 0, ES_REG(ensoniq, UART_CONTROL));
 		outl(ensoniq->ctrl |= ES_UART_EN, ES_REG(ensoniq, CONTROL));
 	}
-	spin_unlock_irqrestore(&ensoniq->reg_lock, flags);
+	spin_unlock_irq(&ensoniq->reg_lock);
 	return 0;
 }
 
 static int snd_ensoniq_midi_output_close(snd_rawmidi_substream_t * substream)
 {
-	unsigned long flags;
-	ensoniq_t *ensoniq = snd_magic_cast(ensoniq_t, substream->rmidi->private_data, return -ENXIO);
+	ensoniq_t *ensoniq = substream->rmidi->private_data;
 
-	spin_lock_irqsave(&ensoniq->reg_lock, flags);
+	spin_lock_irq(&ensoniq->reg_lock);
 	if (!(ensoniq->uartm & ES_MODE_INPUT)) {
 		outb(ensoniq->uartc = 0, ES_REG(ensoniq, UART_CONTROL));
 		outl(ensoniq->ctrl &= ~ES_UART_EN, ES_REG(ensoniq, CONTROL));
@@ -2138,14 +2112,14 @@
 	}
 	ensoniq->midi_output = NULL;
 	ensoniq->uartm &= ~ES_MODE_OUTPUT;
-	spin_unlock_irqrestore(&ensoniq->reg_lock, flags);
+	spin_unlock_irq(&ensoniq->reg_lock);
 	return 0;
 }
 
 static void snd_ensoniq_midi_input_trigger(snd_rawmidi_substream_t * substream, int up)
 {
 	unsigned long flags;
-	ensoniq_t *ensoniq = snd_magic_cast(ensoniq_t, substream->rmidi->private_data, return);
+	ensoniq_t *ensoniq = substream->rmidi->private_data;
 	int idx;
 
 	spin_lock_irqsave(&ensoniq->reg_lock, flags);
@@ -2169,7 +2143,7 @@
 static void snd_ensoniq_midi_output_trigger(snd_rawmidi_substream_t * substream, int up)
 {
 	unsigned long flags;
-	ensoniq_t *ensoniq = snd_magic_cast(ensoniq_t, substream->rmidi->private_data, return);
+	ensoniq_t *ensoniq = substream->rmidi->private_data;
 	unsigned char byte;
 
 	spin_lock_irqsave(&ensoniq->reg_lock, flags);
@@ -2240,7 +2214,7 @@
 
 static irqreturn_t snd_audiopci_interrupt(int irq, void *dev_id, struct pt_regs *regs)
 {
-	ensoniq_t *ensoniq = snd_magic_cast(ensoniq_t, dev_id, return IRQ_NONE);
+	ensoniq_t *ensoniq = dev_id;
 	unsigned int status, sctrl;
 
 	if (ensoniq == NULL)
diff -Nru a/sound/pci/es1938.c b/sound/pci/es1938.c
--- a/sound/pci/es1938.c	2004-10-18 14:56:48 -07:00
+++ b/sound/pci/es1938.c	2004-10-18 14:56:48 -07:00
@@ -54,6 +54,7 @@
 #include <linux/slab.h>
 #include <linux/gameport.h>
 #include <linux/moduleparam.h>
+#include <linux/delay.h>
 #include <sound/core.h>
 #include <sound/control.h>
 #include <sound/pcm.h>
@@ -63,13 +64,10 @@
 
 #include <asm/io.h>
 
-#define chip_t es1938_t
-
 MODULE_AUTHOR("Jaromir Koutek <miri@punknet.cz>");
 MODULE_DESCRIPTION("ESS Solo-1");
 MODULE_LICENSE("GPL");
-MODULE_CLASSES("{sound}");
-MODULE_DEVICES("{{ESS,ES1938},"
+MODULE_SUPPORTED_DEVICE("{{ESS,ES1938},"
                 "{ESS,ES1946},"
                 "{ESS,ES1969},"
 		"{TerraTec,128i PCI}}");
@@ -88,13 +86,10 @@
 
 module_param_array(index, int, boot_devs, 0444);
 MODULE_PARM_DESC(index, "Index value for ESS Solo-1 soundcard.");
-MODULE_PARM_SYNTAX(index, SNDRV_INDEX_DESC);
 module_param_array(id, charp, boot_devs, 0444);
 MODULE_PARM_DESC(id, "ID string for ESS Solo-1 soundcard.");
-MODULE_PARM_SYNTAX(id, SNDRV_ID_DESC);
 module_param_array(enable, bool, boot_devs, 0444);
 MODULE_PARM_DESC(enable, "Enable ESS Solo-1 soundcard.");
-MODULE_PARM_SYNTAX(enable, SNDRV_ENABLE_DESC);
 
 #define SLIO_REG(chip, x) ((chip)->io_port + ESSIO_REG_##x)
 
@@ -202,19 +197,16 @@
 
 typedef struct _snd_es1938 es1938_t;
 
+#define SAVED_REG_SIZE	32 /* max. number of registers to save */
+
 struct _snd_es1938 {
 	int irq;
 
 	unsigned long io_port;
-	struct resource *res_io_port;
 	unsigned long sb_port;
-	struct resource *res_sb_port;
 	unsigned long vc_port;
-	struct resource *res_vc_port;
 	unsigned long mpu_port;
-	struct resource *res_mpu_port;
 	unsigned long game_port;
-	struct resource *res_game_port;
 	unsigned long ddma_port;
 
 	unsigned char irqmask;
@@ -227,6 +219,7 @@
 
 	struct pci_dev *pci;
 	snd_card_t *card;
+	snd_pcm_t *pcm;
 	snd_pcm_substream_t *capture_substream;
 	snd_pcm_substream_t *playback1_substream;
 	snd_pcm_substream_t *playback2_substream;
@@ -248,6 +241,9 @@
 #if defined(CONFIG_GAMEPORT) || (defined(MODULE) && defined(CONFIG_GAMEPORT_MODULE))
 	struct gameport gameport;
 #endif
+#ifdef CONFIG_PM
+	unsigned char saved_regs[SAVED_REG_SIZE];
+#endif
 };
 
 static irqreturn_t snd_es1938_interrupt(int irq, void *dev_id, struct pt_regs *regs);
@@ -573,7 +569,12 @@
 	case SNDRV_PCM_TRIGGER_START:
 		/* According to the documentation this should be:
 		   0x13 but that value may randomly swap stereo channels */
+                snd_es1938_mixer_write(chip, ESSSB_IREG_AUDIO2CONTROL1, 0x92);
+                udelay(10);
 		snd_es1938_mixer_write(chip, ESSSB_IREG_AUDIO2CONTROL1, 0x93);
+                /* This two stage init gives the FIFO -> DAC connection time to
+                 * settle before first data from DMA flows in.  This should ensure
+                 * no swapping of stereo channels.  Report a bug if otherwise :-) */
 		outb(0x0a, SLIO_REG(chip, AUDIO2MODE));
 		chip->active |= DAC2;
 		break;
@@ -690,6 +691,8 @@
 
 	chip->dma2_shift = 2 - mono - is8;
 
+        snd_es1938_reset_fifo(chip);
+
 	/* set clock and counters */
         snd_es1938_rate_set(chip, substream, DAC2);
 
@@ -874,9 +877,9 @@
 	.rate_max =		48000,
 	.channels_min =		1,
 	.channels_max =		2,
-	.buffer_bytes_max =	65536,
+        .buffer_bytes_max =	0x8000,       /* DMA controller screws on higher values */
 	.period_bytes_min =	64,
-	.period_bytes_max =	65536,
+	.period_bytes_max =	0x8000,
 	.periods_min =		1,
 	.periods_max =		1024,
 	.fifo_size =		256,
@@ -896,9 +899,9 @@
 	.rate_max =		48000,
 	.channels_min =		1,
 	.channels_max =		2,
-	.buffer_bytes_max =	65536,
+        .buffer_bytes_max =	0x8000,       /* DMA controller screws on higher values */
 	.period_bytes_min =	64,
-	.period_bytes_max =	65536,
+	.period_bytes_max =	0x8000,
 	.periods_min =		1,
 	.periods_max =		1024,
 	.fifo_size =		256,
@@ -998,13 +1001,11 @@
 	snd_pcm_lib_preallocate_free_for_all(pcm);
 }
 
-static int __devinit snd_es1938_new_pcm(es1938_t *chip, int device, snd_pcm_t ** rpcm)
+static int __devinit snd_es1938_new_pcm(es1938_t *chip, int device)
 {
 	snd_pcm_t *pcm;
 	int err;
 
-	if (rpcm)
-		*rpcm = NULL;
 	if ((err = snd_pcm_new(chip->card, "es-1938-1946", device, 2, 1, &pcm)) < 0)
 		return err;
 	snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_es1938_playback_ops);
@@ -1018,8 +1019,7 @@
 	snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV,
 					      snd_dma_pci_data(chip->pci), 64*1024, 64*1024);
 
-	if (rpcm)
-		*rpcm = pcm;
+	chip->pcm = pcm;
 	return 0;
 }
 
@@ -1129,7 +1129,7 @@
 
 static void snd_es1938_hwv_free(snd_kcontrol_t *kcontrol)
 {
-	es1938_t *chip = snd_magic_cast(es1938_t, _snd_kcontrol_chip(kcontrol), return);
+	es1938_t *chip = snd_kcontrol_chip(kcontrol);
 	chip->master_volume = NULL;
 	chip->master_switch = NULL;
 	chip->hw_volume = NULL;
@@ -1340,43 +1340,106 @@
 /* ---------------------------------------------------------------------------- */
 /* ---------------------------------------------------------------------------- */
 
+/*
+ * initialize the chip - used by resume callback, too
+ */
+static void snd_es1938_chip_init(es1938_t *chip)
+{
+	/* reset chip */
+	snd_es1938_reset(chip);
+
+	/* configure native mode */
+
+	/* enable bus master */
+	pci_set_master(chip->pci);
+
+	/* disable legacy audio */
+	pci_write_config_word(chip->pci, SL_PCI_LEGACYCONTROL, 0x805f);
+
+	/* set DDMA base */
+	pci_write_config_word(chip->pci, SL_PCI_DDMACONTROL, chip->ddma_port | 1);
+
+	/* set DMA/IRQ policy */
+	pci_write_config_dword(chip->pci, SL_PCI_CONFIG, 0);
+
+	/* enable Audio 1, Audio 2, MPU401 IRQ and HW volume IRQ*/
+	outb(0xf0, SLIO_REG(chip, IRQCONTROL));
+
+	/* reset DMA */
+	outb(0, SLDM_REG(chip, DMACLEAR));
+}
+
+#ifdef CONFIG_PM
+/*
+ * PM support
+ */
+
+static unsigned char saved_regs[SAVED_REG_SIZE+1] = {
+	0x14, 0x1a, 0x1c, 0x3a, 0x3c, 0x3e, 0x36, 0x38,
+	0x50, 0x52, 0x60, 0x61, 0x62, 0x63, 0x64, 0x68,
+	0x69, 0x6a, 0x6b, 0x6d, 0x6e, 0x6f, 0x7c, 0x7d,
+	0xa8, 0xb4,
+};
+
+
+static int es1938_suspend(snd_card_t *card, unsigned int state)
+{
+	es1938_t *chip = card->pm_private_data;
+	unsigned char *s, *d;
+
+	snd_pcm_suspend_all(chip->pcm);
+
+	/* save mixer-related registers */
+	for (s = saved_regs, d = chip->saved_regs; *s; s++, d++)
+		*d = snd_es1938_reg_read(chip, *s);
+
+	outb(0x00, SLIO_REG(chip, IRQCONTROL)); /* disable irqs */
+
+	snd_power_change_state(card, SNDRV_CTL_POWER_D3hot);
+	return 0;
+}
+
+static int es1938_resume(snd_card_t *card, unsigned int state)
+{
+	es1938_t *chip = card->pm_private_data;
+	unsigned char *s, *d;
+
+	pci_enable_device(chip->pci);
+	snd_es1938_chip_init(chip);
+
+	/* restore mixer-related registers */
+	for (s = saved_regs, d = chip->saved_regs; *s; s++, d++) {
+		if (*s < 0xa0)
+			snd_es1938_mixer_write(chip, *s, *d);
+		else
+			snd_es1938_write(chip, *s, *d);
+	}
+
+	snd_power_change_state(card, SNDRV_CTL_POWER_D0);
+	return 0;
+}
+#endif /* CONFIG_PM */
+
 static int snd_es1938_free(es1938_t *chip)
 {
+	/* disable irqs */
+	outb(0x00, SLIO_REG(chip, IRQCONTROL));
 	/*if (chip->rmidi)
 	  snd_es1938_mixer_bits(chip, ESSSB_IREG_MPU401CONTROL, 0x40, 0);*/
 #if defined(CONFIG_GAMEPORT) || (defined(MODULE) && defined(CONFIG_GAMEPORT_MODULE))
 	if (chip->gameport.io)
 		gameport_unregister_port(&chip->gameport);
 #endif
-	if (chip->res_io_port) {
-		release_resource(chip->res_io_port);
-		kfree_nocheck(chip->res_io_port);
-	}
-	if (chip->res_sb_port) {
-		release_resource(chip->res_sb_port);
-		kfree_nocheck(chip->res_sb_port);
-	}
-	if (chip->res_vc_port) {
-		release_resource(chip->res_vc_port);
-		kfree_nocheck(chip->res_vc_port);
-	}
-	if (chip->res_mpu_port) {
-		release_resource(chip->res_mpu_port);
-		kfree_nocheck(chip->res_mpu_port);
-	}
-	if (chip->res_game_port) {
-		release_resource(chip->res_game_port);
-		kfree_nocheck(chip->res_game_port);
-	}
 	if (chip->irq >= 0)
 		free_irq(chip->irq, (void *)chip);
-	snd_magic_kfree(chip);
+	pci_release_regions(chip->pci);
+	kfree(chip);
 	return 0;
 }
 
 static int snd_es1938_dev_free(snd_device_t *device)
 {
-	es1938_t *chip = snd_magic_cast(es1938_t, device->device_data, return -ENXIO);
+	es1938_t *chip = device->device_data;
 	return snd_es1938_free(chip);
 }
 
@@ -1402,43 +1465,22 @@
                 return -ENXIO;
         }
 
-	chip = snd_magic_kcalloc(es1938_t, 0, GFP_KERNEL);
+	chip = kcalloc(1, sizeof(*chip), GFP_KERNEL);
 	if (chip == NULL)
 		return -ENOMEM;
 	spin_lock_init(&chip->reg_lock);
 	spin_lock_init(&chip->mixer_lock);
 	chip->card = card;
 	chip->pci = pci;
-	chip->io_port = pci_resource_start(pci, 0);
-	if ((chip->res_io_port = request_region(chip->io_port, 8, "ESS Solo-1")) == NULL) {
-		snd_printk("unable to grab region 0x%lx-0x%lx\n", chip->io_port, chip->io_port + 8 - 1);
-		snd_es1938_free(chip);
-		return -EBUSY;
+	if ((err = pci_request_regions(pci, "ESS Solo-1")) < 0) {
+		kfree(chip);
+		return err;
 	}
+	chip->io_port = pci_resource_start(pci, 0);
 	chip->sb_port = pci_resource_start(pci, 1);
-	if ((chip->res_sb_port = request_region(chip->sb_port, 0x10, "ESS Solo-1 SB")) == NULL) {
-		snd_printk("unable to grab SB region 0x%lx-0x%lx\n", chip->sb_port, chip->sb_port + 0x10 - 1);
-		snd_es1938_free(chip);
-		return -EBUSY;
-	}
 	chip->vc_port = pci_resource_start(pci, 2);
-	if ((chip->res_vc_port = request_region(chip->vc_port, 0x10, "ESS Solo-1 VC (DMA)")) == NULL) {
-		snd_printk("unable to grab VC (DMA) region 0x%lx-0x%lx\n", chip->vc_port, chip->vc_port + 0x10 - 1);
-		snd_es1938_free(chip);
-		return -EBUSY;
-	}
 	chip->mpu_port = pci_resource_start(pci, 3);
-	if ((chip->res_mpu_port = request_region(chip->mpu_port, 4, "ESS Solo-1 MIDI")) == NULL) {
-		snd_printk("unable to grab MIDI region 0x%lx-0x%lx\n", chip->mpu_port, chip->mpu_port + 4 - 1);
-		snd_es1938_free(chip);
-		return -EBUSY;
-	}
 	chip->game_port = pci_resource_start(pci, 4);
-	if ((chip->res_game_port = request_region(chip->game_port, 4, "ESS Solo-1 GAME")) == NULL) {
-		snd_printk("unable to grab GAME region 0x%lx-0x%lx\n", chip->game_port, chip->game_port + 4 - 1);
-		snd_es1938_free(chip);
-		return -EBUSY;
-	}
 	if (request_irq(pci->irq, snd_es1938_interrupt, SA_INTERRUPT|SA_SHIRQ, "ES1938", (void *)chip)) {
 		snd_printk("unable to grab IRQ %d\n", pci->irq);
 		snd_es1938_free(chip);
@@ -1449,32 +1491,12 @@
 	snd_printk("create: io: 0x%lx, sb: 0x%lx, vc: 0x%lx, mpu: 0x%lx, game: 0x%lx\n",
 		   chip->io_port, chip->sb_port, chip->vc_port, chip->mpu_port, chip->game_port);
 #endif
-	/* reset chip */
-	snd_es1938_reset(chip);
-
-	/* configure native mode */
-
-	/* enable bus master */
-	pci_set_master(pci);
-
-	/* disable legacy audio */
-	pci_write_config_word(pci, SL_PCI_LEGACYCONTROL, 0x805f);
 
-	/* set DDMA base */
 	chip->ddma_port = chip->vc_port + 0x00;		/* fix from Thomas Sailer */
-	pci_write_config_word(pci, SL_PCI_DDMACONTROL, chip->ddma_port | 1);
 
-	/* set DMA/IRQ policy */
-	pci_write_config_dword(pci, SL_PCI_CONFIG, 0);
+	snd_es1938_chip_init(chip);
 
-	/* enable Audio 1, Audio 2, MPU401 IRQ and HW volume IRQ*/
-	outb(0xf0, SLIO_REG(chip, IRQCONTROL));
-
-	/* reset DMA */
-	outb(0, SLDM_REG(chip, DMACLEAR));
-
-	/* enable bus mastering */
-	pci_set_master(pci);
+	snd_card_set_pm_callback(card, es1938_suspend, es1938_resume, chip);
 
 	if ((err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops)) < 0) {
 		snd_es1938_free(chip);
@@ -1492,7 +1514,7 @@
  * -------------------------------------------------------------------- */
 static irqreturn_t snd_es1938_interrupt(int irq, void *dev_id, struct pt_regs *regs)
 {
-	es1938_t *chip = snd_magic_cast(es1938_t, dev_id, return IRQ_NONE);
+	es1938_t *chip = dev_id;
 	unsigned char status, audiostatus;
 	int handled = 0;
 
@@ -1560,19 +1582,15 @@
 
 #define ES1938_DMA_SIZE 64
 
-static int __devinit snd_es1938_mixer(snd_pcm_t *pcm)
+static int __devinit snd_es1938_mixer(es1938_t *chip)
 {
 	snd_card_t *card;
-	es1938_t *chip;
 	unsigned int idx;
 	int err;
 
-	snd_assert(pcm != NULL && pcm->card != NULL, return -EINVAL);
+	card = chip->card;
 
-	card = pcm->card;
-	chip = snd_pcm_chip(pcm);
-
-	strcpy(card->mixername, pcm->name);
+	strcpy(card->mixername, "ESS Solo-1");
 
 	for (idx = 0; idx < ARRAY_SIZE(snd_es1938_controls); idx++) {
 		snd_kcontrol_t *kctl;
@@ -1608,7 +1626,6 @@
 	static int dev;
 	snd_card_t *card;
 	es1938_t *chip;
-	snd_pcm_t *pcm;
 	opl3_t *opl3;
 	int idx, err;
 
@@ -1641,11 +1658,11 @@
 		chip->revision,
 		chip->irq);
 
-	if ((err = snd_es1938_new_pcm(chip, 0, &pcm)) < 0) {
+	if ((err = snd_es1938_new_pcm(chip, 0)) < 0) {
 		snd_card_free(card);
 		return err;
 	}
-	if ((err = snd_es1938_mixer(pcm)) < 0) {
+	if ((err = snd_es1938_mixer(chip)) < 0) {
 		snd_card_free(card);
 		return err;
 	}
@@ -1697,6 +1714,7 @@
 	.id_table = snd_es1938_ids,
 	.probe = snd_es1938_probe,
 	.remove = __devexit_p(snd_es1938_remove),
+	SND_PCI_PM_CALLBACKS
 };
 
 static int __init alsa_card_es1938_init(void)
diff -Nru a/sound/pci/es1968.c b/sound/pci/es1968.c
--- a/sound/pci/es1968.c	2004-10-18 14:56:48 -07:00
+++ b/sound/pci/es1968.c	2004-10-18 14:56:48 -07:00
@@ -109,15 +109,12 @@
 #include <sound/ac97_codec.h>
 #include <sound/initval.h>
 
-#define chip_t es1968_t
-
 #define CARD_NAME "ESS Maestro1/2"
 #define DRIVER_NAME "ES1968"
 
 MODULE_DESCRIPTION("ESS Maestro");
-MODULE_CLASSES("{sound}");
 MODULE_LICENSE("GPL");
-MODULE_DEVICES("{{ESS,Maestro 2e},"
+MODULE_SUPPORTED_DEVICE("{{ESS,Maestro 2e},"
 		"{ESS,Maestro 2},"
 		"{ESS,Maestro 1},"
 		"{TerraTec,DMX}}");
@@ -142,35 +139,25 @@
 
 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);
 module_param_array(total_bufsize, int, boot_devs, 0444);
 MODULE_PARM_DESC(total_bufsize, "Total buffer size in kB.");
-MODULE_PARM_SYNTAX(total_bufsize, SNDRV_ENABLED ",allows:{{1,4096}},skill:advanced");
 module_param_array(pcm_substreams_p, int, boot_devs, 0444);
 MODULE_PARM_DESC(pcm_substreams_p, "PCM Playback substreams for " CARD_NAME " soundcard.");
-MODULE_PARM_SYNTAX(pcm_substreams_p, SNDRV_ENABLED ",allows:{{1,8}}");
 module_param_array(pcm_substreams_c, int, boot_devs, 0444);
 MODULE_PARM_DESC(pcm_substreams_c, "PCM Capture substreams for " CARD_NAME " soundcard.");
-MODULE_PARM_SYNTAX(pcm_substreams_c, SNDRV_ENABLED ",allows:{{0,8}}");
 module_param_array(clock, int, boot_devs, 0444);
 MODULE_PARM_DESC(clock, "Clock on " CARD_NAME " soundcard.  (0 = auto-detect)");
-MODULE_PARM_SYNTAX(clock, SNDRV_ENABLED);
 module_param_array(use_pm, int, boot_devs, 0444);
 MODULE_PARM_DESC(use_pm, "Toggle power-management.  (0 = off, 1 = on, 2 = auto)");
-MODULE_PARM_SYNTAX(use_pm, SNDRV_ENABLED ",allows:{{0,1,2}},default:2,skill:advanced");
 module_param_array(enable_mpu, int, boot_devs, 0444);
 MODULE_PARM_DESC(enable_mpu, "Enable MPU401.  (0 = off, 1 = on, 2 = auto)");
-MODULE_PARM_SYNTAX(enable_mpu, SNDRV_ENABLED ",allows:{{0,2}},default:2");
 #ifdef SUPPORT_JOYSTICK
 module_param_array(joystick, bool, boot_devs, 0444);
 MODULE_PARM_DESC(joystick, "Enable joystick.");
-MODULE_PARM_SYNTAX(joystick, SNDRV_ENABLED "," SNDRV_BOOLEAN_FALSE_DESC);
 #endif
 
 
@@ -522,9 +509,7 @@
 
 /* DMA Hack! */
 struct snd_esm_memory {
-	char *buf;
-	unsigned long addr;
-	int size;
+	struct snd_dma_buffer buf;
 	int empty;	/* status */
 	struct list_head list;
 };
@@ -573,13 +558,11 @@
 	unsigned int clock;		/* clock */
 
 	/* buffer */
-	struct snd_dma_device dma_dev;
 	struct snd_dma_buffer dma;
 
 	/* Resources... */
 	int irq;
 	unsigned long io_port;
-	struct resource *res_io_port;
 	int type;
 	struct pci_dev *pci;
 	snd_card_t *card;
@@ -696,7 +679,7 @@
 
 static void snd_es1968_ac97_write(ac97_t *ac97, unsigned short reg, unsigned short val)
 {
-	es1968_t *chip = snd_magic_cast(es1968_t, ac97->private_data, return);
+	es1968_t *chip = ac97->private_data;
 	unsigned long flags;
 
 	spin_lock_irqsave(&chip->reg_lock, flags);
@@ -715,7 +698,7 @@
 static unsigned short snd_es1968_ac97_read(ac97_t *ac97, unsigned short reg)
 {
 	u16 data = 0;
-	es1968_t *chip = snd_magic_cast(es1968_t, ac97->private_data, return 0);
+	es1968_t *chip = ac97->private_data;
 	unsigned long flags;
 
 	spin_lock_irqsave(&chip->reg_lock, flags);
@@ -1078,10 +1061,10 @@
 	for (channel = 0; channel <= high_apu; channel++) {
 		apu = es->apu[channel];
 
-		snd_es1968_program_wavecache(chip, es, channel, es->memory->addr, 0);
+		snd_es1968_program_wavecache(chip, es, channel, es->memory->buf.addr, 0);
 
 		/* Offset to PCMBAR */
-		pa = es->memory->addr;
+		pa = es->memory->buf.addr;
 		pa -= chip->dma.addr;
 		pa >>= 1;	/* words */
 
@@ -1230,20 +1213,20 @@
 	/* input mixer (left/mono) */
 	/* parallel in crap, see maestro reg 0xC [8-11] */
 	init_capture_apu(chip, es, 2,
-			 es->mixbuf->addr, ESM_MIXBUF_SIZE/4, /* in words */
+			 es->mixbuf->buf.addr, ESM_MIXBUF_SIZE/4, /* in words */
 			 ESM_APU_INPUTMIXER, 0x14);
 	/* SRC (left/mono); get input from inputing apu */
-	init_capture_apu(chip, es, 0, es->memory->addr, size,
+	init_capture_apu(chip, es, 0, es->memory->buf.addr, size,
 			 ESM_APU_SRCONVERTOR, es->apu[2]);
 	if (es->fmt & ESS_FMT_STEREO) {
 		/* input mixer (right) */
 		init_capture_apu(chip, es, 3,
-				 es->mixbuf->addr + ESM_MIXBUF_SIZE/2,
+				 es->mixbuf->buf.addr + ESM_MIXBUF_SIZE/2,
 				 ESM_MIXBUF_SIZE/4, /* in words */
 				 ESM_APU_INPUTMIXER, 0x15);
 		/* SRC (right) */
 		init_capture_apu(chip, es, 1,
-				 es->memory->addr + size*2, size,
+				 es->memory->buf.addr + size*2, size,
 				 ESM_APU_SRCONVERTOR, es->apu[3]);
 	}
 
@@ -1281,7 +1264,7 @@
 {
 	es1968_t *chip = snd_pcm_substream_chip(substream);
 	snd_pcm_runtime_t *runtime = substream->runtime;
-	esschan_t *es = snd_magic_cast(esschan_t, runtime->private_data, return -ENXIO);
+	esschan_t *es = runtime->private_data;
 
 	es->dma_size = snd_pcm_lib_buffer_bytes(substream);
 	es->frag_size = snd_pcm_lib_period_bytes(substream);
@@ -1312,10 +1295,9 @@
 static int snd_es1968_pcm_trigger(snd_pcm_substream_t *substream, int cmd)
 {
 	es1968_t *chip = snd_pcm_substream_chip(substream);
-	esschan_t *es = snd_magic_cast(esschan_t, substream->runtime->private_data, return -ENXIO);
-	unsigned long flags;
+	esschan_t *es = substream->runtime->private_data;
 
-	spin_lock_irqsave(&chip->substream_lock, flags);
+	spin_lock(&chip->substream_lock);
 	switch (cmd) {
 	case SNDRV_PCM_TRIGGER_START:
 	case SNDRV_PCM_TRIGGER_RESUME:
@@ -1336,14 +1318,14 @@
 		snd_es1968_bob_dec(chip);
 		break;
 	}
-	spin_unlock_irqrestore(&chip->substream_lock, flags);
+	spin_unlock(&chip->substream_lock);
 	return 0;
 }
 
 static snd_pcm_uframes_t snd_es1968_pcm_pointer(snd_pcm_substream_t *substream)
 {
 	es1968_t *chip = snd_pcm_substream_chip(substream);
-	esschan_t *es = snd_magic_cast(esschan_t, substream->runtime->private_data, return -ENXIO);
+	esschan_t *es = substream->runtime->private_data;
 	unsigned int ptr;
 
 	ptr = snd_es1968_get_dma_ptr(chip, es) << es->wav_shift;
@@ -1408,8 +1390,8 @@
 	down(&chip->memory_mutex);
 	list_for_each(p, &chip->buf_list) {
 		esm_memory_t *buf = list_entry(p, esm_memory_t, list);
-		if (buf->empty && buf->size > max_size)
-			max_size = buf->size;
+		if (buf->empty && buf->buf.bytes > max_size)
+			max_size = buf->buf.bytes;
 	}
 	up(&chip->memory_mutex);
 	if (max_size >= 128*1024)
@@ -1427,24 +1409,25 @@
 	down(&chip->memory_mutex);
 	list_for_each(p, &chip->buf_list) {
 		buf = list_entry(p, esm_memory_t, list);
-		if (buf->empty && buf->size >= size)
+		if (buf->empty && buf->buf.bytes >= size)
 			goto __found;
 	}
 	up(&chip->memory_mutex);
 	return NULL;
 
 __found:
-	if (buf->size > size) {
+	if (buf->buf.bytes > size) {
 		esm_memory_t *chunk = kmalloc(sizeof(*chunk), GFP_KERNEL);
 		if (chunk == NULL) {
 			up(&chip->memory_mutex);
 			return NULL;
 		}
-		chunk->size = buf->size - size;
-		chunk->buf = buf->buf + size;
-		chunk->addr = buf->addr + size;
+		chunk->buf = buf->buf;
+		chunk->buf.bytes -= size;
+		chunk->buf.area += size;
+		chunk->buf.addr += size;
 		chunk->empty = 1;
-		buf->size = size;
+		buf->buf.bytes = size;
 		list_add(&chunk->list, &buf->list);
 	}
 	buf->empty = 0;
@@ -1462,7 +1445,7 @@
 	if (buf->list.prev != &chip->buf_list) {
 		chunk = list_entry(buf->list.prev, esm_memory_t, list);
 		if (chunk->empty) {
-			chunk->size += buf->size;
+			chunk->buf.bytes += buf->buf.bytes;
 			list_del(&buf->list);
 			kfree(buf);
 			buf = chunk;
@@ -1471,7 +1454,7 @@
 	if (buf->list.next != &chip->buf_list) {
 		chunk = list_entry(buf->list.next, esm_memory_t, list);
 		if (chunk->empty) {
-			buf->size += chunk->size;
+			buf->buf.bytes += chunk->buf.bytes;
 			list_del(&chunk->list);
 			kfree(chunk);
 		}
@@ -1485,7 +1468,7 @@
 
 	if (! chip->dma.area)
 		return;
-	snd_dma_free_reserved(&chip->dma_dev);
+	snd_dma_reserve_buf(&chip->dma, snd_dma_pci_buf_id(chip->pci));
 	while ((p = chip->buf_list.next) != &chip->buf_list) {
 		esm_memory_t *chunk = list_entry(p, esm_memory_t, list);
 		list_del(p);
@@ -1499,22 +1482,22 @@
 	int err;
 	esm_memory_t *chunk;
 
-	chip->dma_dev.type = SNDRV_DMA_TYPE_DEV;
-	chip->dma_dev.dev = snd_dma_pci_data(chip->pci);
-	chip->dma_dev.id = 0;
-	if (! snd_dma_get_reserved(&chip->dma_dev, &chip->dma)) {
-		err = snd_dma_alloc_pages_fallback(&chip->dma_dev, chip->total_bufsize, &chip->dma);
+	chip->dma.dev.type = SNDRV_DMA_TYPE_DEV;
+	chip->dma.dev.dev = snd_dma_pci_data(chip->pci);
+	if (! snd_dma_get_reserved_buf(&chip->dma, snd_dma_pci_buf_id(chip->pci))) {
+		err = snd_dma_alloc_pages_fallback(SNDRV_DMA_TYPE_DEV,
+						   snd_dma_pci_data(chip->pci),
+						   chip->total_bufsize, &chip->dma);
 		if (err < 0 || ! chip->dma.area) {
 			snd_printk("es1968: can't allocate dma pages for size %d\n",
 				   chip->total_bufsize);
 			return -ENOMEM;
 		}
 		if ((chip->dma.addr + chip->dma.bytes - 1) & ~((1 << 28) - 1)) {
-			snd_dma_free_pages(&chip->dma_dev, &chip->dma);
+			snd_dma_free_pages(&chip->dma);
 			snd_printk("es1968: DMA buffer beyond 256MB.\n");
 			return -ENOMEM;
 		}
-		snd_dma_set_reserved(&chip->dma_dev, &chip->dma);
 	}
 
 	INIT_LIST_HEAD(&chip->buf_list);
@@ -1525,9 +1508,10 @@
 		return -ENOMEM;
 	}
 	memset(chip->dma.area, 0, ESM_MEM_ALIGN);
-	chunk->buf = chip->dma.area + ESM_MEM_ALIGN;
-	chunk->addr = chip->dma.addr + ESM_MEM_ALIGN;
-	chunk->size = chip->dma.bytes - ESM_MEM_ALIGN;
+	chunk->buf = chip->dma;
+	chunk->buf.area += ESM_MEM_ALIGN;
+	chunk->buf.addr += ESM_MEM_ALIGN;
+	chunk->buf.bytes -= ESM_MEM_ALIGN;
 	chunk->empty = 1;
 	list_add(&chunk->list, &chip->buf_list);
 
@@ -1541,11 +1525,11 @@
 {
 	es1968_t *chip = snd_pcm_substream_chip(substream);
 	snd_pcm_runtime_t *runtime = substream->runtime;
-	esschan_t *chan = snd_magic_cast(esschan_t, runtime->private_data, return -ENXIO);
+	esschan_t *chan = runtime->private_data;
 	int size = params_buffer_bytes(hw_params);
 
 	if (chan->memory) {
-		if (chan->memory->size >= size) {
+		if (chan->memory->buf.bytes >= size) {
 			runtime->dma_bytes = size;
 			return 0;
 		}
@@ -1556,9 +1540,7 @@
 		// snd_printd("cannot allocate dma buffer: size = %d\n", size);
 		return -ENOMEM;
 	}
-	runtime->dma_bytes = size;
-	runtime->dma_area = chan->memory->buf;
-	runtime->dma_addr = chan->memory->addr;
+	snd_pcm_set_runtime_buffer(substream, &chan->memory->buf);
 	return 1; /* area was changed */
 }
 
@@ -1571,7 +1553,7 @@
 	
 	if (runtime->private_data == NULL)
 		return 0;
-	chan = snd_magic_cast(esschan_t, runtime->private_data, return -ENXIO);
+	chan = runtime->private_data;
 	if (chan->memory) {
 		snd_es1968_free_memory(chip, chan->memory);
 		chan->memory = NULL;
@@ -1616,14 +1598,13 @@
 	snd_pcm_runtime_t *runtime = substream->runtime;
 	esschan_t *es;
 	int apu1;
-	unsigned long flags;
 
 	/* search 2 APUs */
 	apu1 = snd_es1968_alloc_apu_pair(chip, ESM_APU_PCM_PLAY);
 	if (apu1 < 0)
 		return apu1;
 
-	es = snd_magic_kcalloc(esschan_t, 0, GFP_KERNEL);
+	es = kcalloc(1, sizeof(*es), GFP_KERNEL);
 	if (!es) {
 		snd_es1968_free_apu_pair(chip, apu1);
 		return -ENOMEM;
@@ -1645,9 +1626,9 @@
 	snd_pcm_hw_constraint_step(runtime, 0, SNDRV_PCM_HW_PARAM_BUFFER_BYTES,
 				   1024);
 #endif
-	spin_lock_irqsave(&chip->substream_lock, flags);
+	spin_lock_irq(&chip->substream_lock);
 	list_add(&es->list, &chip->substream_list);
-	spin_unlock_irqrestore(&chip->substream_lock, flags);
+	spin_unlock_irq(&chip->substream_lock);
 
 	return 0;
 }
@@ -1658,7 +1639,6 @@
 	es1968_t *chip = snd_pcm_substream_chip(substream);
 	esschan_t *es;
 	int apu1, apu2;
-	unsigned long flags;
 
 	apu1 = snd_es1968_alloc_apu_pair(chip, ESM_APU_PCM_CAPTURE);
 	if (apu1 < 0)
@@ -1669,7 +1649,7 @@
 		return apu2;
 	}
 	
-	es = snd_magic_kcalloc(esschan_t, 0, GFP_KERNEL);
+	es = kcalloc(1, sizeof(*es), GFP_KERNEL);
 	if (!es) {
 		snd_es1968_free_apu_pair(chip, apu1);
 		snd_es1968_free_apu_pair(chip, apu2);
@@ -1692,10 +1672,10 @@
 	if ((es->mixbuf = snd_es1968_new_memory(chip, ESM_MIXBUF_SIZE)) == NULL) {
 		snd_es1968_free_apu_pair(chip, apu1);
 		snd_es1968_free_apu_pair(chip, apu2);
-		snd_magic_kfree(es);
+		kfree(es);
                 return -ENOMEM;
         }
-	memset(es->mixbuf->buf, 0, ESM_MIXBUF_SIZE);
+	memset(es->mixbuf->buf.area, 0, ESM_MIXBUF_SIZE);
 
 	runtime->private_data = es;
 	runtime->hw = snd_es1968_capture;
@@ -1705,9 +1685,9 @@
 	snd_pcm_hw_constraint_step(runtime, 0, SNDRV_PCM_HW_PARAM_BUFFER_BYTES,
 				   1024);
 #endif
-	spin_lock_irqsave(&chip->substream_lock, flags);
+	spin_lock_irq(&chip->substream_lock);
 	list_add(&es->list, &chip->substream_list);
-	spin_unlock_irqrestore(&chip->substream_lock, flags);
+	spin_unlock_irq(&chip->substream_lock);
 
 	return 0;
 }
@@ -1716,16 +1696,15 @@
 {
 	es1968_t *chip = snd_pcm_substream_chip(substream);
 	esschan_t *es;
-	unsigned long flags;
 
 	if (substream->runtime->private_data == NULL)
 		return 0;
-	es = snd_magic_cast(esschan_t, substream->runtime->private_data, return -ENXIO);
-	spin_lock_irqsave(&chip->substream_lock, flags);
+	es = substream->runtime->private_data;
+	spin_lock_irq(&chip->substream_lock);
 	list_del(&es->list);
-	spin_unlock_irqrestore(&chip->substream_lock, flags);
+	spin_unlock_irq(&chip->substream_lock);
 	snd_es1968_free_apu_pair(chip, es->apu[0]);
-	snd_magic_kfree(es);
+	kfree(es);
 
 	return 0;
 }
@@ -1734,18 +1713,17 @@
 {
 	es1968_t *chip = snd_pcm_substream_chip(substream);
 	esschan_t *es;
-	unsigned long flags;
 
 	if (substream->runtime->private_data == NULL)
 		return 0;
-	es = snd_magic_cast(esschan_t, substream->runtime->private_data, return -ENXIO);
-	spin_lock_irqsave(&chip->substream_lock, flags);
+	es = substream->runtime->private_data;
+	spin_lock_irq(&chip->substream_lock);
 	list_del(&es->list);
-	spin_unlock_irqrestore(&chip->substream_lock, flags);
+	spin_unlock_irq(&chip->substream_lock);
 	snd_es1968_free_memory(chip, es->mixbuf);
 	snd_es1968_free_apu_pair(chip, es->apu[0]);
 	snd_es1968_free_apu_pair(chip, es->apu[2]);
-	snd_magic_kfree(es);
+	kfree(es);
 
 	return 0;
 }
@@ -1783,7 +1761,6 @@
 	int i, apu;
 	unsigned int pa, offset, t;
 	esm_memory_t *memory;
-	unsigned long flags;
 	struct timeval start_time, stop_time;
 
 	if (chip->clock == 0)
@@ -1800,11 +1777,11 @@
 		return;
 	}
 
-	memset(memory->buf, 0, CLOCK_MEASURE_BUFSIZE);
+	memset(memory->buf.area, 0, CLOCK_MEASURE_BUFSIZE);
 
-	wave_set_register(chip, apu << 3, (memory->addr - 0x10) & 0xfff8);
+	wave_set_register(chip, apu << 3, (memory->buf.addr - 0x10) & 0xfff8);
 
-	pa = (unsigned int)((memory->addr - chip->dma.addr) >> 1);
+	pa = (unsigned int)((memory->buf.addr - chip->dma.addr) >> 1);
 	pa |= 0x00400000;	/* System RAM (Bit 22) */
 
 	/* initialize apu */
@@ -1820,18 +1797,18 @@
 	apu_set_register(chip, apu, 9, 0xD000);
 	apu_set_register(chip, apu, 10, 0x8F08);
 	apu_set_register(chip, apu, 11, 0x0000);
-	spin_lock_irqsave(&chip->reg_lock, flags);
+	spin_lock_irq(&chip->reg_lock);
 	outw(1, chip->io_port + 0x04); /* clear WP interrupts */
 	outw(inw(chip->io_port + ESM_PORT_HOST_IRQ) | ESM_HIRQ_DSIE, chip->io_port + ESM_PORT_HOST_IRQ); /* enable WP ints */
-	spin_unlock_irqrestore(&chip->reg_lock, flags);
+	spin_unlock_irq(&chip->reg_lock);
 
 	snd_es1968_apu_set_freq(chip, apu, ((unsigned int)48000 << 16) / chip->clock); /* 48000 Hz */
 
-	spin_lock_irqsave(&chip->reg_lock, flags);
+	spin_lock_irq(&chip->reg_lock);
 	__apu_set_register(chip, apu, 5, pa & 0xffff);
 	snd_es1968_trigger_apu(chip, apu, ESM_APU_16BITLINEAR);
 	do_gettimeofday(&start_time);
-	spin_unlock_irqrestore(&chip->reg_lock, flags);
+	spin_unlock_irq(&chip->reg_lock);
 #if 0
 	set_current_state(TASK_UNINTERRUPTIBLE);
 	schedule_timeout(HZ / 20); /* 50 msec */
@@ -1842,11 +1819,11 @@
 	 */
 	mdelay(50);
 #endif
-	spin_lock_irqsave(&chip->reg_lock, flags);
+	spin_lock_irq(&chip->reg_lock);
 	offset = __apu_get_register(chip, apu, 5);
 	do_gettimeofday(&stop_time);
 	snd_es1968_trigger_apu(chip, apu, 0); /* stop */
-	spin_unlock_irqrestore(&chip->reg_lock, flags);
+	spin_unlock_irq(&chip->reg_lock);
 
 	/* check the current position */
 	offset -= (pa & 0xffff);
@@ -1879,7 +1856,7 @@
 
 static void snd_es1968_pcm_free(snd_pcm_t *pcm)
 {
-	es1968_t *esm = snd_magic_cast(es1968_t, pcm->private_data, return);
+	es1968_t *esm = pcm->private_data;
 	snd_es1968_free_dmabuf(esm);
 	esm->pcm = NULL;
 }
@@ -1952,7 +1929,7 @@
  */
 static void es1968_update_hw_volume(unsigned long private_data)
 {
-	es1968_t *chip = snd_magic_cast(es1968_t, (void*)private_data, return);
+	es1968_t *chip = (es1968_t *) private_data;
 	int x, val;
 
 	/* Figure out which volume control button was pushed,
@@ -1990,8 +1967,6 @@
 			if ((val & 0xff00) < 0x1f00)
 				val += 0x0100;
 		}
-		if (val == 0x1f1f)
-			val |= 0x8000;
 		snd_ac97_write_cache(chip->ac97, AC97_MASTER, val);
 		snd_ctl_notify(chip->card, SNDRV_CTL_EVENT_MASK_VALUE,
 			       &chip->master_volume->id);
@@ -2003,7 +1978,7 @@
  */
 static irqreturn_t snd_es1968_interrupt(int irq, void *dev_id, struct pt_regs *regs)
 {
-	es1968_t *chip = snd_magic_cast(es1968_t, dev_id, return IRQ_NONE);
+	es1968_t *chip = dev_id;
 	u32 event;
 
 	if (!(event = inb(chip->io_port + 0x1A)))
@@ -2042,15 +2017,16 @@
 static int __devinit
 snd_es1968_mixer(es1968_t *chip)
 {
-	ac97_bus_t bus, *pbus;
-	ac97_t ac97;
+	ac97_bus_t *pbus;
+	ac97_template_t ac97;
 	snd_ctl_elem_id_t id;
 	int err;
+	static ac97_bus_ops_t ops = {
+		.write = snd_es1968_ac97_write,
+		.read = snd_es1968_ac97_read,
+	};
 
-	memset(&bus, 0, sizeof(bus));
-	bus.write = snd_es1968_ac97_write;
-	bus.read = snd_es1968_ac97_read;
-	if ((err = snd_ac97_bus(chip->card, &bus, &pbus)) < 0)
+	if ((err = snd_ac97_bus(chip->card, 0, &ops, NULL, &pbus)) < 0)
 		return err;
 
 	memset(&ac97, 0, sizeof(ac97));
@@ -2420,7 +2396,7 @@
  */
 static int es1968_suspend(snd_card_t *card, unsigned int state)
 {
-	es1968_t *chip = snd_magic_cast(es1968_t, card->pm_private_data, return -EINVAL);
+	es1968_t *chip = card->pm_private_data;
 
 	if (! chip->do_pm)
 		return 0;
@@ -2435,7 +2411,7 @@
 
 static int es1968_resume(snd_card_t *card, unsigned int state)
 {
-	es1968_t *chip = snd_magic_cast(es1968_t, card->pm_private_data, return -EINVAL);
+	es1968_t *chip = card->pm_private_data;
 
 	if (! chip->do_pm)
 		return 0;
@@ -2466,12 +2442,14 @@
 
 static int snd_es1968_free(es1968_t *chip)
 {
-	if (chip->res_io_port) {
+	if (chip->io_port) {
 		synchronize_irq(chip->irq);
 		outw(1, chip->io_port + 0x04); /* clear WP interrupts */
 		outw(0, chip->io_port + ESM_PORT_HOST_IRQ); /* disable IRQ */
 	}
 
+	if (chip->irq >= 0)
+		free_irq(chip->irq, (void *)chip);
 #ifdef SUPPORT_JOYSTICK
 	if (chip->res_joystick) {
 		gameport_unregister_port(&chip->gameport);
@@ -2482,19 +2460,14 @@
 	snd_es1968_set_acpi(chip, ACPI_D3);
 	chip->master_switch = NULL;
 	chip->master_volume = NULL;
-	if (chip->res_io_port) {
-		release_resource(chip->res_io_port);
-		kfree_nocheck(chip->res_io_port);
-	}
-	if (chip->irq >= 0)
-		free_irq(chip->irq, (void *)chip);
-	snd_magic_kfree(chip);
+	pci_release_regions(chip->pci);
+	kfree(chip);
 	return 0;
 }
 
 static int snd_es1968_dev_free(snd_device_t *device)
 {
-	es1968_t *chip = snd_magic_cast(es1968_t, device->device_data, return -ENXIO);
+	es1968_t *chip = device->device_data;
 	return snd_es1968_free(chip);
 }
 
@@ -2542,7 +2515,7 @@
 		return -ENXIO;
 	}
 
-	chip = (es1968_t *) snd_magic_kcalloc(es1968_t, 0, GFP_KERNEL);
+	chip = kcalloc(1, sizeof(*chip), GFP_KERNEL);
 	if (! chip)
 		return -ENOMEM;
 
@@ -2561,12 +2534,11 @@
 	chip->playback_streams = play_streams;
 	chip->capture_streams = capt_streams;
 
-	chip->io_port = pci_resource_start(pci, 0);
-	if ((chip->res_io_port = request_region(chip->io_port, 0x100, "ESS Maestro")) == NULL) {
-		snd_printk("unable to grab region 0x%lx-0x%lx\n", chip->io_port, chip->io_port + 0x100 - 1);
-		snd_es1968_free(chip);
-		return -EBUSY;
+	if ((err = pci_request_regions(pci, "ESS Maestro")) < 0) {
+		kfree(chip);
+		return err;
 	}
+	chip->io_port = pci_resource_start(pci, 0);
 	if (request_irq(pci->irq, snd_es1968_interrupt, SA_INTERRUPT|SA_SHIRQ,
 			"ESS Maestro", (void*)chip)) {
 		snd_printk("unable to grab IRQ %d\n", pci->irq);
diff -Nru a/sound/pci/fm801.c b/sound/pci/fm801.c
--- a/sound/pci/fm801.c	2004-10-18 14:56:49 -07:00
+++ b/sound/pci/fm801.c	2004-10-18 14:56:49 -07:00
@@ -40,13 +40,10 @@
 #define TEA575X_RADIO 1
 #endif
 
-#define chip_t fm801_t
-
 MODULE_AUTHOR("Jaroslav Kysela <perex@suse.cz>");
 MODULE_DESCRIPTION("ForteMedia FM801");
 MODULE_LICENSE("GPL");
-MODULE_CLASSES("{sound}");
-MODULE_DEVICES("{{ForteMedia,FM801},"
+MODULE_SUPPORTED_DEVICE("{{ForteMedia,FM801},"
 		"{Genius,SoundMaker Live 5.1}}");
 
 static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX;	/* Index 0-MAX */
@@ -64,16 +61,12 @@
 
 module_param_array(index, int, boot_devs, 0444);
 MODULE_PARM_DESC(index, "Index value for the FM801 soundcard.");
-MODULE_PARM_SYNTAX(index, SNDRV_INDEX_DESC);
 module_param_array(id, charp, boot_devs, 0444);
 MODULE_PARM_DESC(id, "ID string for the FM801 soundcard.");
-MODULE_PARM_SYNTAX(id, SNDRV_ID_DESC);
 module_param_array(enable, bool, boot_devs, 0444);
 MODULE_PARM_DESC(enable, "Enable FM801 soundcard.");
-MODULE_PARM_SYNTAX(enable, SNDRV_ENABLE_DESC);
 module_param_array(tea575x_tuner, bool, boot_devs, 0444);
 MODULE_PARM_DESC(tea575x_tuner, "Enable TEA575x tuner.");
-MODULE_PARM_SYNTAX(tea575x_tuner, SNDRV_ENABLE_DESC);
 
 /*
  *  Direct registers
@@ -161,7 +154,6 @@
 	int irq;
 
 	unsigned long port;	/* I/O port number */
-	struct resource *res_port;
 	unsigned int multichannel: 1,	/* multichannel support */
 		     secondary: 1;	/* secondary codec */
 	unsigned char secondary_addr;	/* address of the secondary codec */
@@ -233,7 +225,7 @@
 				  unsigned short reg,
 				  unsigned short val)
 {
-	fm801_t *chip = snd_magic_cast(fm801_t, ac97->private_data, return);
+	fm801_t *chip = ac97->private_data;
 	int idx;
 
 	/*
@@ -264,7 +256,7 @@
 
 static unsigned short snd_fm801_codec_read(ac97_t *ac97, unsigned short reg)
 {
-	fm801_t *chip = snd_magic_cast(fm801_t, ac97->private_data, return -ENXIO);
+	fm801_t *chip = ac97->private_data;
 	int idx;
 
 	/*
@@ -308,10 +300,8 @@
   38400, 44100, 48000
 };
 
-#define RATES sizeof(rates) / sizeof(rates[0])
-
 static snd_pcm_hw_constraint_list_t hw_constraints_rates = {
-	.count = RATES,
+	.count = ARRAY_SIZE(rates),
 	.list = rates,
 	.mask = 0,
 };
@@ -336,11 +326,11 @@
 {
 	unsigned int idx;
 
-	for (idx = 0; idx < 11; idx++)
+	for (idx = 0; idx < ARRAY_SIZE(rates); idx++)
 		if (rates[idx] == rate)
 			return idx;
 	snd_BUG();
-	return RATES - 1;
+	return ARRAY_SIZE(rates) - 1;
 }
 
 /*
@@ -487,42 +477,40 @@
 static snd_pcm_uframes_t snd_fm801_playback_pointer(snd_pcm_substream_t * substream)
 {
 	fm801_t *chip = snd_pcm_substream_chip(substream);
-	unsigned long flags;
 	size_t ptr;
 
 	if (!(chip->ply_ctrl & FM801_START))
 		return 0;
-	spin_lock_irqsave(&chip->reg_lock, flags);
+	spin_lock(&chip->reg_lock);
 	ptr = chip->ply_pos + (chip->ply_count - 1) - inw(FM801_REG(chip, PLY_COUNT));
 	if (inw(FM801_REG(chip, IRQ_STATUS)) & FM801_IRQ_PLAYBACK) {
 		ptr += chip->ply_count;
 		ptr %= chip->ply_size;
 	}
-	spin_unlock_irqrestore(&chip->reg_lock, flags);
+	spin_unlock(&chip->reg_lock);
 	return bytes_to_frames(substream->runtime, ptr);
 }
 
 static snd_pcm_uframes_t snd_fm801_capture_pointer(snd_pcm_substream_t * substream)
 {
 	fm801_t *chip = snd_pcm_substream_chip(substream);
-	unsigned long flags;
 	size_t ptr;
 
 	if (!(chip->cap_ctrl & FM801_START))
 		return 0;
-	spin_lock_irqsave(&chip->reg_lock, flags);
+	spin_lock(&chip->reg_lock);
 	ptr = chip->cap_pos + (chip->cap_count - 1) - inw(FM801_REG(chip, CAP_COUNT));
 	if (inw(FM801_REG(chip, IRQ_STATUS)) & FM801_IRQ_CAPTURE) {
 		ptr += chip->cap_count;
 		ptr %= chip->cap_size;
 	}
-	spin_unlock_irqrestore(&chip->reg_lock, flags);
+	spin_unlock(&chip->reg_lock);
 	return bytes_to_frames(substream->runtime, ptr);
 }
 
 static irqreturn_t snd_fm801_interrupt(int irq, void *dev_id, struct pt_regs *regs)
 {
-	fm801_t *chip = snd_magic_cast(fm801_t, dev_id, return IRQ_NONE);
+	fm801_t *chip = dev_id;
 	unsigned short status;
 	unsigned int tmp;
 
@@ -680,7 +668,7 @@
 
 static void snd_fm801_pcm_free(snd_pcm_t *pcm)
 {
-	fm801_t *chip = snd_magic_cast(fm801_t, pcm->private_data, return);
+	fm801_t *chip = pcm->private_data;
 	chip->pcm = NULL;
 	snd_pcm_lib_preallocate_free_for_all(pcm);
 }
@@ -1076,10 +1064,10 @@
 	int mask = (kcontrol->private_value >> 16) & 0xff;
 	int invert = (kcontrol->private_value >> 24) & 0xff;
 
-	spin_lock(&chip->reg_lock);
+	spin_lock_irq(&chip->reg_lock);
 	ucontrol->value.integer.value[0] = (inw(chip->port + reg) >> shift_left) & mask;
 	ucontrol->value.integer.value[1] = (inw(chip->port + reg) >> shift_right) & mask;
-	spin_unlock(&chip->reg_lock);
+	spin_unlock_irq(&chip->reg_lock);
 	if (invert) {
 		ucontrol->value.integer.value[0] = mask - ucontrol->value.integer.value[0];
 		ucontrol->value.integer.value[1] = mask - ucontrol->value.integer.value[1];
@@ -1176,13 +1164,13 @@
 
 static void snd_fm801_mixer_free_ac97_bus(ac97_bus_t *bus)
 {
-	fm801_t *chip = snd_magic_cast(fm801_t, bus->private_data, return);
+	fm801_t *chip = bus->private_data;
 	chip->ac97_bus = NULL;
 }
 
 static void snd_fm801_mixer_free_ac97(ac97_t *ac97)
 {
-	fm801_t *chip = snd_magic_cast(fm801_t, ac97->private_data, return);
+	fm801_t *chip = ac97->private_data;
 	if (ac97->num == 0) {
 		chip->ac97 = NULL;
 	} else {
@@ -1192,18 +1180,17 @@
 
 static int __devinit snd_fm801_mixer(fm801_t *chip)
 {
-	ac97_bus_t bus;
-	ac97_t ac97;
+	ac97_template_t ac97;
 	unsigned int i;
 	int err;
+	static ac97_bus_ops_t ops = {
+		.write = snd_fm801_codec_write,
+		.read = snd_fm801_codec_read,
+	};
 
-	memset(&bus, 0, sizeof(bus));
-	bus.write = snd_fm801_codec_write;
-	bus.read = snd_fm801_codec_read;
-	bus.private_data = chip;
-	bus.private_free = snd_fm801_mixer_free_ac97_bus;
-	if ((err = snd_ac97_bus(chip->card, &bus, &chip->ac97_bus)) < 0)
+	if ((err = snd_ac97_bus(chip->card, 0, &ops, chip, &chip->ac97_bus)) < 0)
 		return err;
+	chip->ac97_bus->private_free = snd_fm801_mixer_free_ac97_bus;
 
 	memset(&ac97, 0, sizeof(ac97));
 	ac97.private_data = chip;
@@ -1245,20 +1232,17 @@
 #ifdef TEA575X_RADIO
 	snd_tea575x_exit(&chip->tea);
 #endif
-	if (chip->res_port) {
-		release_resource(chip->res_port);
-		kfree_nocheck(chip->res_port);
-	}
 	if (chip->irq >= 0)
 		free_irq(chip->irq, (void *)chip);
+	pci_release_regions(chip->pci);
 
-	snd_magic_kfree(chip);
+	kfree(chip);
 	return 0;
 }
 
 static int snd_fm801_dev_free(snd_device_t *device)
 {
-	fm801_t *chip = snd_magic_cast(fm801_t, device->device_data, return -ENXIO);
+	fm801_t *chip = device->device_data;
 	return snd_fm801_free(chip);
 }
 
@@ -1279,19 +1263,18 @@
 	*rchip = NULL;
 	if ((err = pci_enable_device(pci)) < 0)
 		return err;
-	chip = snd_magic_kcalloc(fm801_t, 0, GFP_KERNEL);
+	chip = kcalloc(1, sizeof(*chip), GFP_KERNEL);
 	if (chip == NULL)
 		return -ENOMEM;
 	spin_lock_init(&chip->reg_lock);
 	chip->card = card;
 	chip->pci = pci;
 	chip->irq = -1;
-	chip->port = pci_resource_start(pci, 0);
-	if ((chip->res_port = request_region(chip->port, 0x80, "FM801")) == NULL) {
-		snd_printk("unable to grab region 0x%lx-0x%lx\n", chip->port, chip->port + 0x80 - 1);
-		snd_fm801_free(chip);
-		return -EBUSY;
+	if ((err = pci_request_regions(pci, "FM801")) < 0) {
+		kfree(chip);
+		return err;
 	}
+	chip->port = pci_resource_start(pci, 0);
 	if (request_irq(pci->irq, snd_fm801_interrupt, SA_INTERRUPT|SA_SHIRQ, "FM801", (void *)chip)) {
 		snd_printk("unable to grab IRQ %d\n", chip->irq);
 		snd_fm801_free(chip);
diff -Nru a/sound/pci/ice1712/Makefile b/sound/pci/ice1712/Makefile
--- a/sound/pci/ice1712/Makefile	2004-10-18 14:56:28 -07:00
+++ b/sound/pci/ice1712/Makefile	2004-10-18 14:56:28 -07:00
@@ -5,7 +5,7 @@
 
 snd-ice17xx-ak4xxx-objs := ak4xxx.o
 snd-ice1712-objs := ice1712.o delta.o hoontech.o ews.o
-snd-ice1724-objs := ice1724.o amp.o revo.o aureon.o
+snd-ice1724-objs := ice1724.o amp.o revo.o aureon.o vt1720_mobo.o pontis.o
 
 # Toplevel Module Dependency
 obj-$(CONFIG_SND_ICE1712) += snd-ice1712.o snd-ice17xx-ak4xxx.o
diff -Nru a/sound/pci/ice1712/ak4xxx.c b/sound/pci/ice1712/ak4xxx.c
--- a/sound/pci/ice1712/ak4xxx.c	2004-10-18 14:55:53 -07:00
+++ b/sound/pci/ice1712/ak4xxx.c	2004-10-18 14:55:53 -07:00
@@ -33,7 +33,6 @@
 MODULE_AUTHOR("Jaroslav Kysela <perex@suse.cz>");
 MODULE_DESCRIPTION("ICEnsemble ICE17xx <-> AK4xxx AD/DA chip interface");
 MODULE_LICENSE("GPL");
-MODULE_CLASSES("{sound}");
 
 static void snd_ice1712_akm4xxx_lock(akm4xxx_t *ak, int chip)
 {
diff -Nru a/sound/pci/ice1712/aureon.c b/sound/pci/ice1712/aureon.c
--- a/sound/pci/ice1712/aureon.c	2004-10-18 14:57:19 -07:00
+++ b/sound/pci/ice1712/aureon.c	2004-10-18 14:57:19 -07:00
@@ -75,7 +75,7 @@
 #define WM_DAC_ATTEN		0x00	/* DAC1-8 analog attenuation */
 #define WM_DAC_MASTER_ATTEN	0x08	/* DAC master analog attenuation */
 #define WM_DAC_DIG_ATTEN	0x09	/* DAC1-8 digital attenuation */
-#define WM_DAC_DIG_MATER_ATTEN	0x11	/* DAC master digital attenuation */
+#define WM_DAC_DIG_MASTER_ATTEN	0x11	/* DAC master digital attenuation */
 #define WM_PHASE_SWAP		0x12	/* DAC phase */
 #define WM_DAC_CTRL1		0x13	/* DAC control bits */
 #define WM_MUTE			0x14	/* mute controls */
@@ -149,20 +149,27 @@
 }
 
 /*
+ * set the register value of WM codec
+ */
+static void wm_put_nocache(ice1712_t *ice, int reg, unsigned short val)
+{
+	aureon_spi_write(ice, AUREON_WM_CS, (reg << 9) | (val & 0x1ff), 16);
+}
+
+/*
  * set the register value of WM codec and remember it
  */
 static void wm_put(ice1712_t *ice, int reg, unsigned short val)
 {
-	aureon_spi_write(ice, AUREON_WM_CS, (reg << 9) | (val & 0x1ff), 16);
+	wm_put_nocache(ice, reg, val);
 	reg <<= 1;
 	ice->akm[0].images[reg] = val >> 8;
 	ice->akm[0].images[reg + 1] = val;
 }
 
 /*
- * DAC mute control
  */
-static int wm_dac_mute_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)
+static int aureon_mono_bool_info(snd_kcontrol_t *k, snd_ctl_elem_info_t *uinfo)
 {
 	uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
 	uinfo->count = 1;
@@ -171,6 +178,11 @@
 	return 0;
 }
 
+/*
+ * DAC mute control
+ */
+#define wm_dac_mute_info	aureon_mono_bool_info
+
 static int wm_dac_mute_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
 {
 	ice1712_t *ice = snd_kcontrol_chip(kcontrol);
@@ -205,9 +217,10 @@
  */
 static int wm_dac_vol_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo)
 {
+	int voices = kcontrol->private_value >> 8;
 	uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
-	uinfo->count = 1;
-	uinfo->value.integer.min = 0;		/* mute */
+	uinfo->count = voices;
+	uinfo->value.integer.min = 0;		/* mute (-101dB) */
 	uinfo->value.integer.max = 101;		/* 0dB */
 	return 0;
 }
@@ -215,19 +228,20 @@
 static int wm_dac_vol_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
 {
 	ice1712_t *ice = snd_kcontrol_chip(kcontrol);
-	int idx;
+	int i, idx, ofs, voices;
 	unsigned short vol;
 
+	voices = kcontrol->private_value >> 8;
+	ofs = kcontrol->private_value & 0xff;
 	down(&ice->gpio_mutex);
-	if (kcontrol->private_value)
-		idx = WM_DAC_MASTER_ATTEN;
-	else
-		idx  = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id) + WM_DAC_ATTEN;
-	vol = wm_get(ice, idx) & 0x7f;
-	if (vol <= 0x1a)
-		ucontrol->value.integer.value[0] = 0;
-	else
-		ucontrol->value.integer.value[0] = vol - 0x1a;
+	for (i = 0; i < voices; i++) {
+		idx  = WM_DAC_ATTEN + ofs + i;
+		vol = wm_get(ice, idx) & 0x7f;
+		if (vol <= 0x1a)
+			ucontrol->value.integer.value[i] = 0;
+		else
+			ucontrol->value.integer.value[i] = vol - 0x1a;
+	}
 	up(&ice->gpio_mutex);
 	return 0;
 }
@@ -235,23 +249,69 @@
 static int wm_dac_vol_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
 {
 	ice1712_t *ice = snd_kcontrol_chip(kcontrol);
-	int idx;
+	int i, idx, ofs, voices;
 	unsigned short ovol, nvol;
-	int change;
+	int change = 0;
 
+	voices = kcontrol->private_value >> 8;
+	ofs = kcontrol->private_value & 0xff;
 	snd_ice1712_save_gpio_status(ice);
-	if (kcontrol->private_value)
-		idx = WM_DAC_MASTER_ATTEN;
-	else
-		idx  = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id) + WM_DAC_ATTEN;
-	nvol = ucontrol->value.integer.value[0] + 0x1a;
-	ovol = wm_get(ice, idx) & 0x7f;
-	change = (ovol != nvol);
-	if (change) {
-		if (nvol <= 0x1a && ovol <= 0x1a)
-			change = 0;
-		else
-			wm_put(ice, idx, nvol | 0x180); /* update on zero detect */
+	for (i = 0; i < voices; i++) {
+		idx  = WM_DAC_ATTEN + ofs + i;
+		nvol = ucontrol->value.integer.value[i] + 0x1a;
+		ovol = wm_get(ice, idx) & 0x7f;
+		if (ovol != nvol) {
+			if (nvol <= 0x1a && ovol <= 0x1a)
+				continue;
+			wm_put(ice, idx, nvol | 0x80); /* zero-detect, prelatch */
+			wm_put_nocache(ice, idx, nvol | 0x180); /* update */
+			change = 1;
+		}
+	}
+	snd_ice1712_restore_gpio_status(ice);
+	return change;
+}
+
+/* digital master volume */
+#define MASTER_0dB 0xff
+#define MASTER_RES 128	/* -64dB */
+#define MASTER_MIN (MASTER_0dB - MASTER_RES)
+static int wm_master_vol_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo)
+{
+	uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
+	uinfo->count = 1;
+	uinfo->value.integer.min = 0;		/* mute (-64dB) */
+	uinfo->value.integer.max = MASTER_RES;	/* 0dB */
+	return 0;
+}
+
+static int wm_master_vol_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+{
+	ice1712_t *ice = snd_kcontrol_chip(kcontrol);
+	unsigned short val;
+
+	down(&ice->gpio_mutex);
+	val = wm_get(ice, WM_DAC_DIG_MASTER_ATTEN) & 0xff;
+	val = val > MASTER_MIN ? (val - MASTER_MIN) : 0;
+	ucontrol->value.integer.value[0] = val;
+	up(&ice->gpio_mutex);
+	return 0;
+}
+
+static int wm_master_vol_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+{
+	ice1712_t *ice = snd_kcontrol_chip(kcontrol);
+	unsigned short ovol, nvol;
+	int change = 0;
+
+	snd_ice1712_save_gpio_status(ice);
+	nvol = ucontrol->value.integer.value[0];
+	nvol = (nvol ? (nvol + MASTER_MIN) : 0) & 0xff;
+	ovol = wm_get(ice, WM_DAC_DIG_MASTER_ATTEN) & 0xff;
+	if (ovol != nvol) {
+		wm_put(ice, WM_DAC_DIG_MASTER_ATTEN, nvol); /* prelatch */
+		wm_put_nocache(ice, WM_DAC_DIG_MASTER_ATTEN, nvol | 0x100); /* update */
+		change = 1;
 	}
 	snd_ice1712_restore_gpio_status(ice);
 	return change;
@@ -260,10 +320,10 @@
 /*
  * ADC mute control
  */
-static int wm_adc_mute_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)
+static int wm_adc_mute_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo)
 {
 	uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
-	uinfo->count = 1;
+	uinfo->count = 2;
 	uinfo->value.integer.min = 0;
 	uinfo->value.integer.max = 1;
 	return 0;
@@ -273,10 +333,13 @@
 {
 	ice1712_t *ice = snd_kcontrol_chip(kcontrol);
 	unsigned short val;
+	int i;
 
 	down(&ice->gpio_mutex);
-	val = wm_get(ice, snd_ctl_get_ioffidx(kcontrol, &ucontrol->id)+WM_ADC_GAIN);
-	ucontrol->value.integer.value[0] = ~val>>5 & 0x1;
+	for (i = 0; i < 2; i++) {
+		val = wm_get(ice, WM_ADC_GAIN + i);
+		ucontrol->value.integer.value[i] = ~val>>5 & 0x1;
+	}
 	up(&ice->gpio_mutex);
 	return 0;
 }
@@ -285,14 +348,17 @@
 {
 	ice1712_t *ice = snd_kcontrol_chip(kcontrol);
 	unsigned short new, old;
-	int change;
+	int i, change = 0;
 
 	snd_ice1712_save_gpio_status(ice);
-	old = wm_get(ice, snd_ctl_get_ioffidx(kcontrol, &ucontrol->id)+WM_ADC_GAIN);
-	new = (~ucontrol->value.integer.value[0]<<5&0x20) | (old&~0x20);
-	change = (new != old);
-	if (change)
-		wm_put(ice, snd_ctl_get_ioffidx(kcontrol, &ucontrol->id)+WM_ADC_GAIN, new);
+	for (i = 0; i < 2; i++) {
+		old = wm_get(ice, WM_ADC_GAIN + i);
+		new = (~ucontrol->value.integer.value[i]<<5&0x20) | (old&~0x20);
+		if (new != old) {
+			wm_put(ice, snd_ctl_get_ioffidx(kcontrol, &ucontrol->id)+WM_ADC_GAIN, new);
+			change = 1;
+		}
+	}
 	snd_ice1712_restore_gpio_status(ice);
 
 	return change;
@@ -304,7 +370,7 @@
 static int wm_adc_vol_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo)
 {
 	uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
-	uinfo->count = 1;
+	uinfo->count = 2;
 	uinfo->value.integer.min = 0;		/* -12dB */
 	uinfo->value.integer.max = 0x1f;	/* 19dB */
 	return 0;
@@ -313,13 +379,15 @@
 static int wm_adc_vol_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
 {
 	ice1712_t *ice = snd_kcontrol_chip(kcontrol);
-	int idx;
+	int i, idx;
 	unsigned short vol;
 
 	down(&ice->gpio_mutex);
-	idx  = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id) + WM_ADC_GAIN;
-	vol = wm_get(ice, idx) & 0x1f;
-	ucontrol->value.integer.value[0] = vol;
+	for (i = 0; i < 2; i++) {
+		idx = WM_ADC_GAIN + i;
+		vol = wm_get(ice, idx) & 0x1f;
+		ucontrol->value.integer.value[i] = vol;
+	}
 	up(&ice->gpio_mutex);
 	return 0;
 }
@@ -327,17 +395,20 @@
 static int wm_adc_vol_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
 {
 	ice1712_t *ice = snd_kcontrol_chip(kcontrol);
-	int idx;
+	int i, idx;
 	unsigned short ovol, nvol;
-	int change;
+	int change = 0;
 
 	snd_ice1712_save_gpio_status(ice);
-	idx  = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id) + WM_ADC_GAIN;
-	nvol = ucontrol->value.integer.value[0];
-	ovol = wm_get(ice, idx);
-	change = ((ovol & 0x1f)  != nvol);
-	if (change)
-		wm_put(ice, idx, nvol | (ovol & ~0x1f));
+	for (i = 0; i < 2; i++) {
+		idx  = WM_ADC_GAIN + i;
+		nvol = ucontrol->value.integer.value[i];
+		ovol = wm_get(ice, idx);
+		if ((ovol & 0x1f) != nvol) {
+			wm_put(ice, idx, nvol | (ovol & ~0x1f));
+			change = 1;
+		}
+	}
 	snd_ice1712_restore_gpio_status(ice);
 	return change;
 }
@@ -355,7 +426,7 @@
 		"AC97"		//AIN5
 	};
 	uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
-	uinfo->count = 1;
+	uinfo->count = 2;
 	uinfo->value.enumerated.items = 5;
 	if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
 		uinfo->value.enumerated.item = uinfo->value.enumerated.items - 1;
@@ -420,14 +491,7 @@
 	return ( tmp & AUREON_HP_SEL )!= 0;
 }
 
-static int aureon_bool_info(snd_kcontrol_t *k, snd_ctl_elem_info_t *uinfo)
-{
-	uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
-	uinfo->count = 1;
-	uinfo->value.integer.min = 0;
-	uinfo->value.integer.max = 1;
-	return 0;
-}
+#define aureon_hpamp_info	aureon_mono_bool_info
 
 static int aureon_hpamp_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
 {
@@ -448,6 +512,9 @@
 /*
  * Deemphasis
  */
+
+#define aureon_deemp_info	aureon_mono_bool_info
+
 static int aureon_deemp_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
 {
 	ice1712_t *ice = snd_kcontrol_chip(kcontrol);
@@ -519,44 +586,67 @@
  * mixers
  */
 
-static snd_kcontrol_new_t aureon51_dac_control __devinitdata = {
-	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
-	.name = "DAC Volume",
-	.count = 6,
-	.info = wm_dac_vol_info,
-	.get = wm_dac_vol_get,
-	.put = wm_dac_vol_put,
-};
-
-static snd_kcontrol_new_t aureon71_dac_control __devinitdata = {
-	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
-	.name = "DAC Volume",
-	.count = 8,
-	.info = wm_dac_vol_info,
-	.get = wm_dac_vol_get,
-	.put = wm_dac_vol_put,
-};
-
-static snd_kcontrol_new_t wm_controls[] __devinitdata = {
+static snd_kcontrol_new_t aureon_dac_controls[] __devinitdata = {
 	{
 		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
-		.name = "Master Playback Switch",
-		.info = wm_dac_mute_info,
-		.get = wm_dac_mute_get,
-		.put = wm_dac_mute_put,
+		.name = "Front Playback Volume",
+		.info = wm_dac_vol_info,
+		.get = wm_dac_vol_get,
+		.put = wm_dac_vol_put,
+		.private_value = (2 << 8) | 0
 	},
 	{
 		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
-		.name = "Master Playback Volume",
+		.name = "Rear Playback Volume",
 		.info = wm_dac_vol_info,
 		.get = wm_dac_vol_get,
 		.put = wm_dac_vol_put,
-		.private_value = 1,
+		.private_value = (2 << 8) | 2
 	},
 	{
 		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
-		.name = "ADC Switch",
-		.count = 2,
+		.name = "Center Playback Volume",
+		.info = wm_dac_vol_info,
+		.get = wm_dac_vol_get,
+		.put = wm_dac_vol_put,
+		.private_value = (1 << 8) | 4
+	},
+	{
+		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+		.name = "LFE Playback Volume",
+		.info = wm_dac_vol_info,
+		.get = wm_dac_vol_get,
+		.put = wm_dac_vol_put,
+		.private_value = (1 << 8) | 5
+	},
+	{
+		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+		.name = "Side Playback Volume",
+		.info = wm_dac_vol_info,
+		.get = wm_dac_vol_get,
+		.put = wm_dac_vol_put,
+		.private_value = (2 << 8) | 6
+	}
+};
+
+static snd_kcontrol_new_t wm_controls[] __devinitdata = {
+ 	{
+ 		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+		.name = "Master Playback Switch",
+		.info = wm_dac_mute_info,
+		.get = wm_dac_mute_get,
+		.put = wm_dac_mute_put,
+ 	},
+ 	{
+ 		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+		.name = "Master Playback Volume",
+		.info = wm_master_vol_info,
+		.get = wm_master_vol_get,
+		.put = wm_master_vol_put,
+ 	},
+	{
+		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+		.name = "Capture Switch",
 		.info = wm_adc_mute_info,
 		.get = wm_adc_mute_get,
 		.put = wm_adc_mute_put,
@@ -564,15 +654,14 @@
 	},
 	{
 		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
-		.name = "ADC Volume",
-		.count = 2,
+		.name = "Capture Volume",
 		.info = wm_adc_vol_info,
 		.get = wm_adc_vol_get,
 		.put = wm_adc_vol_put,
 	},
 	{
 		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
-		.name = "Capture Route",
+		.name = "Capture Source",
 		.info = wm_adc_mux_info,
 		.get = wm_adc_mux_get,
 		.put = wm_adc_mux_put,
@@ -580,14 +669,14 @@
 	{
 		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
 		.name = "Headphone Amplifier Switch",
-		.info = aureon_bool_info,
+		.info = aureon_hpamp_info,
 		.get = aureon_hpamp_get,
 		.put = aureon_hpamp_put
 	},
 	{
 		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
 		.name = "DAC Deemphasis Switch",
-		.info = aureon_bool_info,
+		.info = aureon_deemp_info,
 		.get = aureon_deemp_get,
 		.put = aureon_deemp_put
 	},
@@ -603,15 +692,17 @@
 
 static int __devinit aureon_add_controls(ice1712_t *ice)
 {
-	unsigned int i;
+	unsigned int i, counts;
 	int err;
 
+	counts = ARRAY_SIZE(aureon_dac_controls);
 	if (ice->eeprom.subvendor == VT1724_SUBDEVICE_AUREON51_SKY)
-		err = snd_ctl_add(ice->card, snd_ctl_new1(&aureon51_dac_control, ice));
-	else
-		err = snd_ctl_add(ice->card, snd_ctl_new1(&aureon71_dac_control, ice));
-	if (err < 0)
-		return err;
+		counts--; /* no side */
+	for (i = 0; i < counts; i++) {
+		err = snd_ctl_add(ice->card, snd_ctl_new1(&aureon_dac_controls[i], ice));
+		if (err < 0)
+			return err;
+	}
 
 	for (i = 0; i < ARRAY_SIZE(wm_controls); i++) {
 		err = snd_ctl_add(ice->card, snd_ctl_new1(&wm_controls[i], ice));
@@ -718,15 +809,15 @@
 
 	if (ice->eeprom.subvendor == VT1724_SUBDEVICE_AUREON51_SKY) {
 		ice->num_total_dacs = 6;
-		ice->num_total_adcs = 6;
+		ice->num_total_adcs = 2;
 	} else {
 		/* aureon 7.1 and prodigy 7.1 */
 		ice->num_total_dacs = 8;
-		ice->num_total_adcs = 8;
+		ice->num_total_adcs = 2;
 	}
 
 	/* to remeber the register values */
-	ice->akm = snd_kcalloc(sizeof(akm4xxx_t), GFP_KERNEL);
+	ice->akm = kcalloc(1, sizeof(akm4xxx_t), GFP_KERNEL);
 	if (! ice->akm)
 		return -ENOMEM;
 	ice->akm_codecs = 1;
@@ -780,7 +871,7 @@
  */
 
 static unsigned char aureon51_eeprom[] __devinitdata = {
-	0x2a,	/* SYSCONF: clock 512, mpu401, spdif-in/ADC, 3DACs */
+	0x0a,	/* SYSCONF: clock 512, spdif-in/ADC, 3DACs */
 	0x80,	/* ACLINK: I2S */
 	0xf8,	/* I2S: vol, 96k, 24bit, 192k */
 	0xc3,	/* SPDIF: out-en, out-int, spdif-in */
@@ -796,7 +887,7 @@
 };
 
 static unsigned char aureon71_eeprom[] __devinitdata = {
-	0x2b,	/* SYSCONF: clock 512, mpu401, spdif-in/ADC, 4DACs */
+	0x0b,	/* SYSCONF: clock 512, spdif-in/ADC, 4DACs */
 	0x80,	/* ACLINK: I2S */
 	0xf8,	/* I2S: vol, 96k, 24bit, 192k */
 	0xc3,	/* SPDIF: out-en, out-int, spdif-in */
@@ -812,7 +903,7 @@
 };
 
 static unsigned char prodigy71_eeprom[] __devinitdata = {
-	0x2b,	/* SYSCONF: clock 512, mpu401, spdif-in/ADC, 4DACs */
+	0x0b,	/* SYSCONF: clock 512, spdif-in/ADC, 4DACs */
 	0x80,	/* ACLINK: I2S */
 	0xf8,	/* I2S: vol, 96k, 24bit, 192k */
 	0xc3,	/* SPDIF: out-en, out-int, spdif-in */
@@ -837,6 +928,7 @@
 		.build_controls = aureon_add_controls,
 		.eeprom_size = sizeof(aureon51_eeprom),
 		.eeprom_data = aureon51_eeprom,
+		.driver = "Aureon51",
 	},
 	{
 		.subvendor = VT1724_SUBDEVICE_AUREON71_SPACE,
@@ -846,6 +938,7 @@
 		.build_controls = aureon_add_controls,
 		.eeprom_size = sizeof(aureon71_eeprom),
 		.eeprom_data = aureon71_eeprom,
+		.driver = "Aureon71",
 	},
  	{
  		.subvendor = VT1724_SUBDEVICE_AUREON71_UNIVERSE,
@@ -855,6 +948,7 @@
  		.build_controls = aureon_add_controls,
  		.eeprom_size = sizeof(aureon71_eeprom),
  		.eeprom_data = aureon71_eeprom,
+		.driver = "Aureon71",
 	},
 	{
 		.subvendor = VT1724_SUBDEVICE_PRODIGY71,
@@ -864,6 +958,7 @@
 		.build_controls = aureon_add_controls,
 		.eeprom_size = sizeof(prodigy71_eeprom),
 		.eeprom_data = prodigy71_eeprom,
+		.driver = "Prodigy71", /* should be identical with Aureon71 */
 	},
 	{ } /* terminator */
 };
diff -Nru a/sound/pci/ice1712/delta.c b/sound/pci/ice1712/delta.c
--- a/sound/pci/ice1712/delta.c	2004-10-18 14:55:54 -07:00
+++ b/sound/pci/ice1712/delta.c	2004-10-18 14:55:54 -07:00
@@ -126,7 +126,7 @@
 /* sequential write */
 static int ap_cs8427_sendbytes(snd_i2c_device_t *device, unsigned char *bytes, int count)
 {
-	ice1712_t *ice = snd_magic_cast(ice1712_t, device->bus->private_data, return -EIO);
+	ice1712_t *ice = device->bus->private_data;
 	int res = count;
 	unsigned char tmp;
 
@@ -143,7 +143,7 @@
 /* sequential read */
 static int ap_cs8427_readbytes(snd_i2c_device_t *device, unsigned char *bytes, int count)
 {
-	ice1712_t *ice = snd_magic_cast(ice1712_t, device->bus->private_data, return -EIO);
+	ice1712_t *ice = device->bus->private_data;
 	int res = count;
 	unsigned char tmp;
 	
diff -Nru a/sound/pci/ice1712/ews.c b/sound/pci/ice1712/ews.c
--- a/sound/pci/ice1712/ews.c	2004-10-18 14:56:20 -07:00
+++ b/sound/pci/ice1712/ews.c	2004-10-18 14:56:20 -07:00
@@ -45,7 +45,7 @@
 /* send SDA and SCL */
 static void ewx_i2c_setlines(snd_i2c_bus_t *bus, int clk, int data)
 {
-	ice1712_t *ice = snd_magic_cast(ice1712_t, bus->private_data, return);
+	ice1712_t *ice = bus->private_data;
 	unsigned char tmp = 0;
 	if (clk)
 		tmp |= ICE1712_EWX2496_SERIAL_CLOCK;
@@ -57,13 +57,13 @@
 
 static int ewx_i2c_getclock(snd_i2c_bus_t *bus)
 {
-	ice1712_t *ice = snd_magic_cast(ice1712_t, bus->private_data, return -EIO);
+	ice1712_t *ice = bus->private_data;
 	return snd_ice1712_read(ice, ICE1712_IREG_GPIO_DATA) & ICE1712_EWX2496_SERIAL_CLOCK ? 1 : 0;
 }
 
 static int ewx_i2c_getdata(snd_i2c_bus_t *bus, int ack)
 {
-	ice1712_t *ice = snd_magic_cast(ice1712_t, bus->private_data, return -EIO);
+	ice1712_t *ice = bus->private_data;
 	int bit;
 	/* set RW pin to low */
 	snd_ice1712_write(ice, ICE1712_IREG_GPIO_WRITE_MASK, ~ICE1712_EWX2496_RW);
@@ -80,7 +80,7 @@
 
 static void ewx_i2c_start(snd_i2c_bus_t *bus)
 {
-	ice1712_t *ice = snd_magic_cast(ice1712_t, bus->private_data, return);
+	ice1712_t *ice = bus->private_data;
 	unsigned char mask;
 
 	snd_ice1712_save_gpio_status(ice);
@@ -99,13 +99,13 @@
 
 static void ewx_i2c_stop(snd_i2c_bus_t *bus)
 {
-	ice1712_t *ice = snd_magic_cast(ice1712_t, bus->private_data, return);
+	ice1712_t *ice = bus->private_data;
 	snd_ice1712_restore_gpio_status(ice);
 }
 
 static void ewx_i2c_direction(snd_i2c_bus_t *bus, int clock, int data)
 {
-	ice1712_t *ice = snd_magic_cast(ice1712_t, bus->private_data, return);
+	ice1712_t *ice = bus->private_data;
 	unsigned char mask = 0;
 
 	if (clock)
@@ -223,6 +223,7 @@
 	switch (ice->eeprom.subvendor) {
 	case ICE1712_SUBDEVICE_EWS88MT:
 	case ICE1712_SUBDEVICE_EWS88MT_NEW:
+	case ICE1712_SUBDEVICE_PHASE88:
 		snd_runtime_check(snd_i2c_sendbytes(ice->cs8404, &bits, 1) == 1, goto _error);
 		break;
 	case ICE1712_SUBDEVICE_EWS88D:
@@ -410,6 +411,7 @@
 		break;	
 	case ICE1712_SUBDEVICE_EWS88MT:
 	case ICE1712_SUBDEVICE_EWS88MT_NEW:
+	case ICE1712_SUBDEVICE_PHASE88:
 		ice->num_total_dacs = 8;
 		ice->num_total_adcs = 8;
 		break;
@@ -440,6 +442,7 @@
 		break;
 	case ICE1712_SUBDEVICE_EWS88MT:
 	case ICE1712_SUBDEVICE_EWS88MT_NEW:
+	case ICE1712_SUBDEVICE_PHASE88:
 		if ((err = snd_i2c_device_create(ice->i2c, "CS8404", ICE1712_EWS88MT_CS8404_ADDR, &ice->cs8404)) < 0)
 			return err;
 		if ((err = snd_i2c_device_create(ice->i2c, "PCF8574 (1st)", ICE1712_EWS88MT_INPUT_ADDR, &ice->i2cdevs[0])) < 0)
@@ -470,6 +473,7 @@
 		break;
 	case ICE1712_SUBDEVICE_EWS88MT:
 	case ICE1712_SUBDEVICE_EWS88MT_NEW:
+	case ICE1712_SUBDEVICE_PHASE88:
 	case ICE1712_SUBDEVICE_EWS88D:
 		/* set up CS8404 */
 		ice->spdif.ops.open = ews88_open_spdif;
@@ -498,6 +502,7 @@
 	switch (ice->eeprom.subvendor) {
 	case ICE1712_SUBDEVICE_EWS88MT:
 	case ICE1712_SUBDEVICE_EWS88MT_NEW:
+	case ICE1712_SUBDEVICE_PHASE88:
 		err = snd_ice1712_akm4xxx_init(ak, &akm_ews88mt, &akm_ews88mt_priv, ice);
 		break;
 	case ICE1712_SUBDEVICE_EWX2496:
@@ -924,6 +929,7 @@
 	case ICE1712_SUBDEVICE_EWX2496:
 	case ICE1712_SUBDEVICE_EWS88MT:
 	case ICE1712_SUBDEVICE_EWS88MT_NEW:
+	case ICE1712_SUBDEVICE_PHASE88:
 	case ICE1712_SUBDEVICE_DMX6FIRE:
 		err = snd_ice1712_akm4xxx_build_controls(ice);
 		if (err < 0)
@@ -942,6 +948,7 @@
 		break;
 	case ICE1712_SUBDEVICE_EWS88MT:
 	case ICE1712_SUBDEVICE_EWS88MT_NEW:
+	case ICE1712_SUBDEVICE_PHASE88:
 		err = snd_ctl_add(ice->card, snd_ctl_new1(&snd_ice1712_ews88mt_input_sense, ice));
 		if (err < 0)
 			return err;
@@ -988,6 +995,13 @@
 		.subvendor = ICE1712_SUBDEVICE_EWS88MT_NEW,
 		.name = "TerraTec EWS88MT",
 		.model = "ews88mt_new",
+		.chip_init = snd_ice1712_ews_init,
+		.build_controls = snd_ice1712_ews_add_controls,
+	},
+	{
+		.subvendor = ICE1712_SUBDEVICE_PHASE88,
+		.name = "TerraTec Phase88",
+		.model = "phase88",
 		.chip_init = snd_ice1712_ews_init,
 		.build_controls = snd_ice1712_ews_add_controls,
 	},
diff -Nru a/sound/pci/ice1712/ews.h b/sound/pci/ice1712/ews.h
--- a/sound/pci/ice1712/ews.h	2004-10-18 14:56:50 -07:00
+++ b/sound/pci/ice1712/ews.h	2004-10-18 14:56:50 -07:00
@@ -29,13 +29,15 @@
 		"{TerraTec,EWX 24/96},"\
 		"{TerraTec,EWS 88MT},"\
 		"{TerraTec,EWS 88D},"\
-		"{TerraTec,DMX 6Fire},"
+		"{TerraTec,DMX 6Fire},"\
+		"{TerraTec,Phase 88},"
 
 #define ICE1712_SUBDEVICE_EWX2496	0x3b153011
 #define ICE1712_SUBDEVICE_EWS88MT	0x3b151511
 #define ICE1712_SUBDEVICE_EWS88MT_NEW	0x3b152511
 #define ICE1712_SUBDEVICE_EWS88D	0x3b152b11
 #define ICE1712_SUBDEVICE_DMX6FIRE	0x3b153811
+#define ICE1712_SUBDEVICE_PHASE88	0x3b155111
 
 /* entry point */
 extern struct snd_ice1712_card_info snd_ice1712_ews_cards[];
diff -Nru a/sound/pci/ice1712/ice1712.c b/sound/pci/ice1712/ice1712.c
--- a/sound/pci/ice1712/ice1712.c	2004-10-18 14:56:28 -07:00
+++ b/sound/pci/ice1712/ice1712.c	2004-10-18 14:56:28 -07:00
@@ -73,8 +73,7 @@
 MODULE_AUTHOR("Jaroslav Kysela <perex@suse.cz>");
 MODULE_DESCRIPTION("ICEnsemble ICE1712 (Envy24)");
 MODULE_LICENSE("GPL");
-MODULE_CLASSES("{sound}");
-MODULE_DEVICES("{"
+MODULE_SUPPORTED_DEVICE("{"
 	       HOONTECH_DEVICE_DESC
 	       DELTA_DEVICE_DESC
 	       EWS_DEVICE_DESC
@@ -91,19 +90,14 @@
 
 module_param_array(index, int, boot_devs, 0444);
 MODULE_PARM_DESC(index, "Index value for ICE1712 soundcard.");
-MODULE_PARM_SYNTAX(index, SNDRV_INDEX_DESC);
 module_param_array(id, charp, boot_devs, 0444);
 MODULE_PARM_DESC(id, "ID string for ICE1712 soundcard.");
-MODULE_PARM_SYNTAX(id, SNDRV_ID_DESC);
 module_param_array(enable, bool, boot_devs, 0444);
 MODULE_PARM_DESC(enable, "Enable ICE1712 soundcard.");
-MODULE_PARM_SYNTAX(enable, SNDRV_ENABLE_DESC);
 module_param_array(omni, bool, boot_devs, 0444);
 MODULE_PARM_DESC(omni, "Enable Midiman M-Audio Delta Omni I/O support.");
-MODULE_PARM_SYNTAX(omni, SNDRV_ENABLED "," SNDRV_ENABLE_DESC);
 module_param_array(cs8427_timeout, int, boot_devs, 0444);
 MODULE_PARM_DESC(cs8427_timeout, "Define reset timeout for cs8427 chip in msec resolution.");
-MODULE_PARM_SYNTAX(cs8427_timeout, SNDRV_ENABLED ", allows:{{1,1000}},default=500,skill:advanced");
 module_param_array(model, charp, boot_devs, 0444);
 MODULE_PARM_DESC(model, "Use the given board model.");
 
@@ -416,7 +410,7 @@
 
 static irqreturn_t snd_ice1712_interrupt(int irq, void *dev_id, struct pt_regs *regs)
 {
-	ice1712_t *ice = snd_magic_cast(ice1712_t, dev_id, return IRQ_NONE);
+	ice1712_t *ice = dev_id;
 	unsigned char status;
 	int handled = 0;
 
@@ -590,7 +584,7 @@
 	rate = (runtime->rate * 8192) / 375;
 	if (rate > 0x000fffff)
 		rate = 0x000fffff;
-	spin_lock(&ice->reg_lock);
+	spin_lock_irq(&ice->reg_lock);
 	outb(0, ice->ddma_port + 15);
 	outb(ICE1712_DMA_MODE_WRITE | ICE1712_DMA_AUTOINIT, ice->ddma_port + 0x0b);
 	outl(runtime->dma_addr, ice->ddma_port + 0);
@@ -603,7 +597,7 @@
 	snd_ice1712_write(ice, ICE1712_IREG_PBK_COUNT_HI, period_size >> 8);
 	snd_ice1712_write(ice, ICE1712_IREG_PBK_LEFT, 0);
 	snd_ice1712_write(ice, ICE1712_IREG_PBK_RIGHT, 0);
-	spin_unlock(&ice->reg_lock);
+	spin_unlock_irq(&ice->reg_lock);
 	return 0;
 }
 
@@ -626,7 +620,7 @@
 	ice->playback_con_active_buf[substream->number] = 0;
 	ice->playback_con_virt_addr[substream->number] = runtime->dma_addr;
 	chn = substream->number * 2;
-	spin_lock(&ice->reg_lock);
+	spin_lock_irq(&ice->reg_lock);
 	snd_ice1712_ds_write(ice, chn, ICE1712_DSC_ADDR0, runtime->dma_addr);
 	snd_ice1712_ds_write(ice, chn, ICE1712_DSC_COUNT0, period_size);
 	snd_ice1712_ds_write(ice, chn, ICE1712_DSC_ADDR1, runtime->dma_addr + (runtime->periods > 1 ? period_size + 1 : 0));
@@ -638,7 +632,7 @@
 		snd_ice1712_ds_write(ice, chn + 1, ICE1712_DSC_RATE, rate);
 		snd_ice1712_ds_write(ice, chn + 1, ICE1712_DSC_VOLUME, 0);
 	}
-	spin_unlock(&ice->reg_lock);
+	spin_unlock_irq(&ice->reg_lock);
 	return 0;
 }
 
@@ -656,13 +650,13 @@
 		tmp &= ~0x04;
 	if (runtime->channels == 2)
 		tmp &= ~0x02;
-	spin_lock(&ice->reg_lock);
+	spin_lock_irq(&ice->reg_lock);
 	outl(ice->capture_con_virt_addr = runtime->dma_addr, ICEREG(ice, CONCAP_ADDR));
 	outw(buf_size, ICEREG(ice, CONCAP_COUNT));
 	snd_ice1712_write(ice, ICE1712_IREG_CAP_COUNT_HI, period_size >> 8);
 	snd_ice1712_write(ice, ICE1712_IREG_CAP_COUNT_LO, period_size & 0xff);
 	snd_ice1712_write(ice, ICE1712_IREG_CAP_CTRL, tmp);
-	spin_unlock(&ice->reg_lock);
+	spin_unlock_irq(&ice->reg_lock);
 	snd_ac97_set_rate(ice->ac97, AC97_PCM_LR_ADC_RATE, runtime->rate);
 	return 0;
 }
@@ -874,7 +868,7 @@
 
 static void snd_ice1712_pcm_free(snd_pcm_t *pcm)
 {
-	ice1712_t *ice = snd_magic_cast(ice1712_t, pcm->private_data, return);
+	ice1712_t *ice = pcm->private_data;
 	ice->pcm = NULL;
 	snd_pcm_lib_preallocate_free_for_all(pcm);
 }
@@ -912,7 +906,7 @@
 
 static void snd_ice1712_pcm_free_ds(snd_pcm_t *pcm)
 {
-	ice1712_t *ice = snd_magic_cast(ice1712_t, pcm->private_data, return);
+	ice1712_t *ice = pcm->private_data;
 	ice->pcm_ds = NULL;
 	snd_pcm_lib_preallocate_free_for_all(pcm);
 }
@@ -952,10 +946,8 @@
 static unsigned int rates[] = { 8000, 9600, 11025, 12000, 16000, 22050, 24000,
 				32000, 44100, 48000, 64000, 88200, 96000 };
 
-#define RATES sizeof(rates) / sizeof(rates[0])
-
 static snd_pcm_hw_constraint_list_t hw_constraints_rates = {
-	.count = RATES,
+	.count = ARRAY_SIZE(rates),
 	.list = rates,
 	.mask = 0,
 };
@@ -1077,11 +1069,11 @@
 	ice1712_t *ice = snd_pcm_substream_chip(substream);
 
 	ice->playback_pro_size = snd_pcm_lib_buffer_bytes(substream);
-	spin_lock(&ice->reg_lock);
+	spin_lock_irq(&ice->reg_lock);
 	outl(substream->runtime->dma_addr, ICEMT(ice, PLAYBACK_ADDR));
 	outw((ice->playback_pro_size >> 2) - 1, ICEMT(ice, PLAYBACK_SIZE));
 	outw((snd_pcm_lib_period_bytes(substream) >> 2) - 1, ICEMT(ice, PLAYBACK_COUNT));
-	spin_unlock(&ice->reg_lock);
+	spin_unlock_irq(&ice->reg_lock);
 
 	return 0;
 }
@@ -1100,11 +1092,11 @@
 	ice1712_t *ice = snd_pcm_substream_chip(substream);
 
 	ice->capture_pro_size = snd_pcm_lib_buffer_bytes(substream);
-	spin_lock(&ice->reg_lock);
+	spin_lock_irq(&ice->reg_lock);
 	outl(substream->runtime->dma_addr, ICEMT(ice, CAPTURE_ADDR));
 	outw((ice->capture_pro_size >> 2) - 1, ICEMT(ice, CAPTURE_SIZE));
 	outw((snd_pcm_lib_period_bytes(substream) >> 2) - 1, ICEMT(ice, CAPTURE_COUNT));
-	spin_unlock(&ice->reg_lock);
+	spin_unlock_irq(&ice->reg_lock);
 	return 0;
 }
 
@@ -1238,7 +1230,7 @@
 
 static void snd_ice1712_pcm_profi_free(snd_pcm_t *pcm)
 {
-	ice1712_t *ice = snd_magic_cast(ice1712_t, pcm->private_data, return);
+	ice1712_t *ice = pcm->private_data;
 	ice->pcm_pro = NULL;
 	snd_pcm_lib_preallocate_free_for_all(pcm);
 }
@@ -1511,21 +1503,26 @@
 
 static void snd_ice1712_mixer_free_ac97(ac97_t *ac97)
 {
-	ice1712_t *ice = snd_magic_cast(ice1712_t, ac97->private_data, return);
+	ice1712_t *ice = ac97->private_data;
 	ice->ac97 = NULL;
 }
 
 static int __devinit snd_ice1712_ac97_mixer(ice1712_t * ice)
 {
-	int err;
-	ac97_t ac97;
-	ac97_bus_t bus, *pbus;
+	int err, bus_num = 0;
+	ac97_template_t ac97;
+	ac97_bus_t *pbus;
+	static ac97_bus_ops_t con_ops = {
+		.write = snd_ice1712_ac97_write,
+		.read = snd_ice1712_ac97_read,
+	};
+	static ac97_bus_ops_t pro_ops = {
+		.write = snd_ice1712_pro_ac97_write,
+		.read = snd_ice1712_pro_ac97_read,
+	};
 
 	if (ice_has_con_ac97(ice)) {
-		memset(&bus, 0, sizeof(bus));
-		bus.write = snd_ice1712_ac97_write;
-		bus.read = snd_ice1712_ac97_read;
-		if ((err = snd_ac97_bus(ice->card, &bus, &pbus)) < 0)
+		if ((err = snd_ac97_bus(ice->card, bus_num++, &con_ops, NULL, &pbus)) < 0)
 			return err;
 		memset(&ac97, 0, sizeof(ac97));
 		ac97.private_data = ice;
@@ -1540,10 +1537,7 @@
 	}
 
 	if (! (ice->eeprom.data[ICE_EEP1_ACLINK] & ICE1712_CFG_PRO_I2S)) {
-		memset(&bus, 0, sizeof(bus));
-		bus.write = snd_ice1712_pro_ac97_write;
-		bus.read = snd_ice1712_pro_ac97_read;
-		if ((err = snd_ac97_bus(ice->card, &bus, &pbus)) < 0)
+		if ((err = snd_ac97_bus(ice->card, bus_num, &pro_ops, NULL, &pbus)) < 0)
 			return err;
 		memset(&ac97, 0, sizeof(ac97));
 		ac97.private_data = ice;
@@ -1570,7 +1564,7 @@
 static void snd_ice1712_proc_read(snd_info_entry_t *entry, 
 				  snd_info_buffer_t * buffer)
 {
-	ice1712_t *ice = snd_magic_cast(ice1712_t, entry->private_data, return);
+	ice1712_t *ice = entry->private_data;
 	unsigned int idx;
 
 	snd_iprintf(buffer, "%s\n\n", ice->card->longname);
@@ -2468,7 +2462,7 @@
 
 static int snd_ice1712_free(ice1712_t *ice)
 {
-	if (ice->res_port == NULL)
+	if (! ice->port)
 		goto __hw_end;
 	/* mask all interrupts */
 	outb(0xc0, ICEMT(ice, IRQ));
@@ -2479,30 +2473,16 @@
 		synchronize_irq(ice->irq);
 		free_irq(ice->irq, (void *) ice);
 	}
-	if (ice->res_port) {
-		release_resource(ice->res_port);
-		kfree_nocheck(ice->res_port);
-	}
-	if (ice->res_ddma_port) {
-		release_resource(ice->res_ddma_port);
-		kfree_nocheck(ice->res_ddma_port);
-	}
-	if (ice->res_dmapath_port) {
-		release_resource(ice->res_dmapath_port);
-		kfree_nocheck(ice->res_dmapath_port);
-	}
-	if (ice->res_profi_port) {
-		release_resource(ice->res_profi_port);
-		kfree_nocheck(ice->res_profi_port);
-	}
+	if (ice->port)
+		pci_release_regions(ice->pci);
 	snd_ice1712_akm4xxx_free(ice);
-	snd_magic_kfree(ice);
+	kfree(ice);
 	return 0;
 }
 
 static int snd_ice1712_dev_free(snd_device_t *device)
 {
-	ice1712_t *ice = snd_magic_cast(ice1712_t, device->device_data, return -ENXIO);
+	ice1712_t *ice = device->device_data;
 	return snd_ice1712_free(ice);
 }
 
@@ -2531,7 +2511,7 @@
 		return -ENXIO;
 	}
 
-	ice = snd_magic_kcalloc(ice1712_t, 0, GFP_KERNEL);
+	ice = kcalloc(1, sizeof(*ice), GFP_KERNEL);
 	if (ice == NULL)
 		return -ENOMEM;
 	ice->omni = omni ? 1 : 0;
@@ -2555,36 +2535,21 @@
 	ice->card = card;
 	ice->pci = pci;
 	ice->irq = -1;
-	ice->port = pci_resource_start(pci, 0);
-	ice->ddma_port = pci_resource_start(pci, 1);
-	ice->dmapath_port = pci_resource_start(pci, 2);
-	ice->profi_port = pci_resource_start(pci, 3);
 	pci_set_master(pci);
 	pci_write_config_word(ice->pci, 0x40, 0x807f);
 	pci_write_config_word(ice->pci, 0x42, 0x0006);
 	snd_ice1712_proc_init(ice);
 	synchronize_irq(pci->irq);
 
-	if ((ice->res_port = request_region(ice->port, 32, "ICE1712 - Controller")) == NULL) {
-		snd_printk("unable to grab ports 0x%lx-0x%lx\n", ice->port, ice->port + 32 - 1);
-		snd_ice1712_free(ice);
-		return -EIO;
-	}
-	if ((ice->res_ddma_port = request_region(ice->ddma_port, 16, "ICE1712 - DDMA")) == NULL) {
-		snd_printk("unable to grab ports 0x%lx-0x%lx\n", ice->ddma_port, ice->ddma_port + 16 - 1);
-		snd_ice1712_free(ice);
-		return -EIO;
-	}
-	if ((ice->res_dmapath_port = request_region(ice->dmapath_port, 16, "ICE1712 - DMA path")) == NULL) {
-		snd_printk("unable to grab ports 0x%lx-0x%lx\n", ice->dmapath_port, ice->dmapath_port + 16 - 1);
-		snd_ice1712_free(ice);
-		return -EIO;
-	}
-	if ((ice->res_profi_port = request_region(ice->profi_port, 64, "ICE1712 - Professional")) == NULL) {
-		snd_printk("unable to grab ports 0x%lx-0x%lx\n", ice->profi_port, ice->profi_port + 16 - 1);
-		snd_ice1712_free(ice);
-		return -EIO;
+	if ((err = pci_request_regions(pci, "ICE1712")) < 0) {
+		kfree(ice);
+		return err;
 	}
+	ice->port = pci_resource_start(pci, 0);
+	ice->ddma_port = pci_resource_start(pci, 1);
+	ice->dmapath_port = pci_resource_start(pci, 2);
+	ice->profi_port = pci_resource_start(pci, 3);
+
 	if (request_irq(pci->irq, snd_ice1712_interrupt, SA_INTERRUPT|SA_SHIRQ, "ICE1712", (void *) ice)) {
 		snd_printk("unable to grab IRQ %d\n", pci->irq);
 		snd_ice1712_free(ice);
diff -Nru a/sound/pci/ice1712/ice1712.h b/sound/pci/ice1712/ice1712.h
--- a/sound/pci/ice1712/ice1712.h	2004-10-18 14:55:54 -07:00
+++ b/sound/pci/ice1712/ice1712.h	2004-10-18 14:55:54 -07:00
@@ -294,13 +294,9 @@
 	int irq;
 
 	unsigned long port;
-	struct resource *res_port;
 	unsigned long ddma_port;
-	struct resource *res_ddma_port;
 	unsigned long dmapath_port;
-	struct resource *res_dmapath_port;
 	unsigned long profi_port;
-	struct resource *res_profi_port;
 
 	struct pci_dev *pci;
 	snd_card_t *card;
@@ -367,8 +363,6 @@
 	} gpio;
 	struct semaphore gpio_mutex;
 };
-
-#define chip_t ice1712_t
 
 
 /*
diff -Nru a/sound/pci/ice1712/ice1724.c b/sound/pci/ice1712/ice1724.c
--- a/sound/pci/ice1712/ice1724.c	2004-10-18 14:56:29 -07:00
+++ b/sound/pci/ice1712/ice1724.c	2004-10-18 14:56:29 -07:00
@@ -44,16 +44,19 @@
 #include "amp.h"
 #include "revo.h"
 #include "aureon.h"
+#include "vt1720_mobo.h"
+#include "pontis.h"
 
 
 MODULE_AUTHOR("Jaroslav Kysela <perex@suse.cz>");
 MODULE_DESCRIPTION("VIA ICEnsemble ICE1724/1720 (Envy24HT/PT)");
 MODULE_LICENSE("GPL");
-MODULE_CLASSES("{sound}");
-MODULE_DEVICES("{"
+MODULE_SUPPORTED_DEVICE("{"
 	       REVO_DEVICE_DESC
 	       AMP_AUDIO2000_DEVICE_DESC
 	       AUREON_DEVICE_DESC
+	       VT1720_MOBO_DEVICE_DESC
+	       PONTIS_DEVICE_DESC
 		"{VIA,VT1720},"
 		"{VIA,VT1724},"
 		"{ICEnsemble,Generic ICE1724},"
@@ -68,13 +71,10 @@
 
 module_param_array(index, int, boot_devs, 0444);
 MODULE_PARM_DESC(index, "Index value for ICE1724 soundcard.");
-MODULE_PARM_SYNTAX(index, SNDRV_INDEX_DESC);
 module_param_array(id, charp, boot_devs, 0444);
 MODULE_PARM_DESC(id, "ID string for ICE1724 soundcard.");
-MODULE_PARM_SYNTAX(id, SNDRV_ID_DESC);
 module_param_array(enable, bool, boot_devs, 0444);
 MODULE_PARM_DESC(enable, "Enable ICE1724 soundcard.");
-MODULE_PARM_SYNTAX(enable, SNDRV_ENABLE_DESC);
 module_param_array(model, charp, boot_devs, 0444);
 MODULE_PARM_DESC(model, "Use the given board model.");
 
@@ -190,21 +190,26 @@
 static void snd_vt1724_set_gpio_mask(ice1712_t *ice, unsigned int data)
 {
 	outw(data, ICEREG1724(ice, GPIO_WRITE_MASK));
-	outb((data >> 16) & 0xff, ICEREG1724(ice, GPIO_WRITE_MASK_22));
+	if (! ice->vt1720) /* VT1720 supports only 16 GPIO bits */
+		outb((data >> 16) & 0xff, ICEREG1724(ice, GPIO_WRITE_MASK_22));
 	inw(ICEREG1724(ice, GPIO_WRITE_MASK)); /* dummy read for pci-posting */
 }
 
 static void snd_vt1724_set_gpio_data(ice1712_t *ice, unsigned int data)
 {
 	outw(data, ICEREG1724(ice, GPIO_DATA));
-	outb(data >> 16, ICEREG1724(ice, GPIO_DATA_22));
+	if (! ice->vt1720)
+		outb(data >> 16, ICEREG1724(ice, GPIO_DATA_22));
 	inw(ICEREG1724(ice, GPIO_DATA)); /* dummy read for pci-posting */
 }
 
 static unsigned int snd_vt1724_get_gpio_data(ice1712_t *ice)
 {
 	unsigned int data;
-	data = (unsigned int)inb(ICEREG1724(ice, GPIO_DATA_22));
+	if (! ice->vt1720)
+		data = (unsigned int)inb(ICEREG1724(ice, GPIO_DATA_22));
+	else
+		data = 0;
 	data = (data << 16) | inw(ICEREG1724(ice, GPIO_DATA));
 	return data;
 }
@@ -215,7 +220,7 @@
 
 static irqreturn_t snd_vt1724_interrupt(int irq, void *dev_id, struct pt_regs *regs)
 {
-	ice1712_t *ice = snd_magic_cast(ice1712_t, dev_id, return IRQ_NONE);
+	ice1712_t *ice = dev_id;
 	unsigned char status;
 	int handled = 0;
 
@@ -230,7 +235,7 @@
 		if ((status & VT1724_IRQ_MPU_RX)||(status & VT1724_IRQ_MPU_TX)) {
 			if (ice->rmidi[0])
 				snd_mpu401_uart_interrupt(irq, ice->rmidi[0]->private_data, regs);
-			outb(VT1724_IRQ_MPU_RX|VT1724_IRQ_MPU_TX, ICEREG1724(ice, IRQSTAT));
+			outb(status & (VT1724_IRQ_MPU_RX|VT1724_IRQ_MPU_TX), ICEREG1724(ice, IRQSTAT));
 			status &= ~(VT1724_IRQ_MPU_RX|VT1724_IRQ_MPU_TX);
 		}
 		if (status & VT1724_IRQ_MTPCM) {
@@ -317,6 +322,13 @@
 	.mask = 0,
 };
 
+struct vt1724_pcm_reg {
+	unsigned int addr;	/* ADDR register offset */
+	unsigned int size;	/* SIZE register offset */
+	unsigned int count;	/* COUNT register offset */
+	unsigned int start;	/* start & pause bit */
+};
+
 static int snd_vt1724_pcm_trigger(snd_pcm_substream_t *substream, int cmd)
 {
 	ice1712_t *ice = snd_pcm_substream_chip(substream);
@@ -327,8 +339,10 @@
 
 	what = 0;
 	snd_pcm_group_for_each(pos, substream) {
+		struct vt1724_pcm_reg *reg;
 		s = snd_pcm_group_substream_entry(pos);
-		what |= (unsigned long)(s->runtime->private_data);
+		reg = s->runtime->private_data;
+		what |= reg->start;
 		snd_pcm_trigger_done(s, substream);
 	}
 
@@ -371,12 +385,26 @@
 #define DMA_PAUSES	(VT1724_RDMA0_PAUSE|VT1724_PDMA0_PAUSE|VT1724_RDMA1_PAUSE|\
 	VT1724_PDMA1_PAUSE|VT1724_PDMA2_PAUSE|VT1724_PDMA3_PAUSE|VT1724_PDMA4_PAUSE)
 
+static int get_max_rate(ice1712_t *ice)
+{
+	if (ice->eeprom.data[ICE_EEP2_ACLINK] & VT1724_CFG_PRO_I2S) {
+		if ((ice->eeprom.data[ICE_EEP2_I2S] & 0x08) && !ice->vt1720)
+			return 192000;
+		else
+			return 96000;
+	} else
+		return 48000;
+}
+
 static void snd_vt1724_set_pro_rate(ice1712_t *ice, unsigned int rate, int force)
 {
 	unsigned long flags;
 	unsigned char val, old;
 	unsigned int i;
 
+	if (rate > get_max_rate(ice))
+		return;
+
 	spin_lock_irqsave(&ice->reg_lock, flags);
 	if ((inb(ICEMT1724(ice, DMA_CONTROL)) & DMA_STARTS) || 
 	    (inb(ICEMT1724(ice, DMA_PAUSE)) & DMA_PAUSES)) {
@@ -410,8 +438,10 @@
 		val = 0;
 		break;
 	}
-	outb(val, ICEMT1724(ice, RATE));
-	if (rate == ice->cur_rate) {
+	old = inb(ICEMT1724(ice, RATE));
+	if (old != val)
+		outb(val, ICEMT1724(ice, RATE));
+	else if (rate == ice->cur_rate) {
 		spin_unlock_irqrestore(&ice->reg_lock, flags);
 		return;
 	}
@@ -419,7 +449,7 @@
 	ice->cur_rate = rate;
 
 	/* check MT02 */
-	if (ice->eeprom.data[ICE_EEP2_ACLINK] & 0x80) {
+	if (ice->eeprom.data[ICE_EEP2_ACLINK] & VT1724_CFG_PRO_I2S) {
 		val = old = inb(ICEMT1724(ice, I2S_FORMAT));
 		if (rate > 96000)
 			val |= VT1724_MT_I2S_MCLK_128X; /* 128x MCLK */
@@ -446,15 +476,6 @@
 		if (ice->akm[i].ops.set_rate_val)
 			ice->akm[i].ops.set_rate_val(&ice->akm[i], rate);
 	}
-
-	/* set up AC97 registers if needed */
-	if (! (ice->eeprom.data[ICE_EEP2_ACLINK] & 0x80) && ice->ac97) {
-		snd_ac97_set_rate(ice->ac97, AC97_PCM_FRONT_DAC_RATE, rate);
-		snd_ac97_set_rate(ice->ac97, AC97_PCM_SURR_DAC_RATE, rate);
-		snd_ac97_set_rate(ice->ac97, AC97_PCM_LFE_DAC_RATE, rate);
-		snd_ac97_set_rate(ice->ac97, AC97_SPDIF, rate);
-		snd_ac97_set_rate(ice->ac97, AC97_PCM_LR_ADC_RATE, rate);
-	}
 }
 
 static int snd_vt1724_pcm_hw_params(snd_pcm_substream_t * substream,
@@ -518,7 +539,7 @@
 	unsigned char val;
 	unsigned int size;
 
-	spin_lock(&ice->reg_lock);
+	spin_lock_irq(&ice->reg_lock);
 	val = (8 - substream->runtime->channels) >> 1;
 	outb(val, ICEMT1724(ice, BURST));
 
@@ -533,7 +554,7 @@
 	outw(size, ICEMT1724(ice, PLAYBACK_COUNT));
 	outb(size >> 16, ICEMT1724(ice, PLAYBACK_COUNT) + 2);
 
-	spin_unlock(&ice->reg_lock);
+	spin_unlock_irq(&ice->reg_lock);
 
 	// printk("pro prepare: ch = %d, addr = 0x%x, buffer = 0x%x, period = 0x%x\n", substream->runtime->channels, (unsigned int)substream->runtime->dma_addr, snd_pcm_lib_buffer_bytes(substream), snd_pcm_lib_period_bytes(substream));
 	return 0;
@@ -562,7 +583,9 @@
 	ptr = inl(ICEMT1724(ice, PLAYBACK_SIZE)) & 0xffffff;
 	ptr = (ptr + 1) << 2;
 	ptr = bytes_to_frames(substream->runtime, ptr);
-	if (ptr <= substream->runtime->buffer_size)
+	if (! ptr)
+		;
+	else if (ptr <= substream->runtime->buffer_size)
 		ptr = substream->runtime->buffer_size - ptr;
 	else {
 		snd_printd("ice1724: invalid ptr %d (size=%d)\n", (int)ptr, (int)substream->runtime->buffer_size);
@@ -572,29 +595,23 @@
 	return ptr;
 }
 
-struct vt1724_pcm_reg {
-	unsigned int addr;	/* ADDR register offset */
-	unsigned int size;	/* SIZE register offset */
-	unsigned int count;	/* COUNT register offset */
-	unsigned int start;	/* start bit */
-	unsigned int pause;	/* pause bit */
-};
-
-static int snd_vt1724_pcm_prepare(snd_pcm_substream_t *substream, const struct vt1724_pcm_reg *reg)
+static int snd_vt1724_pcm_prepare(snd_pcm_substream_t *substream)
 {
 	ice1712_t *ice = snd_pcm_substream_chip(substream);
+	struct vt1724_pcm_reg *reg = substream->runtime->private_data;
 
-	spin_lock(&ice->reg_lock);
+	spin_lock_irq(&ice->reg_lock);
 	outl(substream->runtime->dma_addr, ice->profi_port + reg->addr);
 	outw((snd_pcm_lib_buffer_bytes(substream) >> 2) - 1, ice->profi_port + reg->size);
 	outw((snd_pcm_lib_period_bytes(substream) >> 2) - 1, ice->profi_port + reg->count);
-	spin_unlock(&ice->reg_lock);
+	spin_unlock_irq(&ice->reg_lock);
 	return 0;
 }
 
-static snd_pcm_uframes_t snd_vt1724_pcm_pointer(snd_pcm_substream_t *substream, const struct vt1724_pcm_reg *reg)
+static snd_pcm_uframes_t snd_vt1724_pcm_pointer(snd_pcm_substream_t *substream)
 {
 	ice1712_t *ice = snd_pcm_substream_chip(substream);
+	struct vt1724_pcm_reg *reg = substream->runtime->private_data;
 	size_t ptr;
 
 	if (!(inl(ICEMT1724(ice, DMA_CONTROL)) & reg->start))
@@ -607,7 +624,9 @@
 	ptr = inw(ice->profi_port + reg->size);
 	ptr = (ptr + 1) << 2;
 	ptr = bytes_to_frames(substream->runtime, ptr);
-	if (ptr <= substream->runtime->buffer_size)
+	if (! ptr)
+		;
+	else if (ptr <= substream->runtime->buffer_size)
 		ptr = substream->runtime->buffer_size - ptr;
 	else {
 		snd_printd("ice1724: invalid ptr %d (size=%d)\n", (int)ptr, (int)substream->runtime->buffer_size);
@@ -617,24 +636,20 @@
 #endif
 }
 
-const static struct vt1724_pcm_reg vt1724_capture_pro_reg = {
+static struct vt1724_pcm_reg vt1724_playback_pro_reg = {
+	.addr = VT1724_MT_PLAYBACK_ADDR,
+	.size = VT1724_MT_PLAYBACK_SIZE,
+	.count = VT1724_MT_PLAYBACK_COUNT,
+	.start = VT1724_PDMA0_START,
+};
+
+static struct vt1724_pcm_reg vt1724_capture_pro_reg = {
 	.addr = VT1724_MT_CAPTURE_ADDR,
 	.size = VT1724_MT_CAPTURE_SIZE,
 	.count = VT1724_MT_CAPTURE_COUNT,
 	.start = VT1724_RDMA0_START,
-	.pause = VT1724_RDMA0_PAUSE,
 };
 
-static int snd_vt1724_capture_pro_prepare(snd_pcm_substream_t * substream)
-{
-	return snd_vt1724_pcm_prepare(substream, &vt1724_capture_pro_reg);
-}
-
-static snd_pcm_uframes_t snd_vt1724_capture_pro_pointer(snd_pcm_substream_t * substream)
-{
-	return snd_vt1724_pcm_pointer(substream, &vt1724_capture_pro_reg);
-}
-
 static snd_pcm_hardware_t snd_vt1724_playback_pro =
 {
 	.info =			(SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED |
@@ -698,9 +713,10 @@
 static int set_rate_constraints(ice1712_t *ice, snd_pcm_substream_t *substream)
 {
 	snd_pcm_runtime_t *runtime = substream->runtime;
-	if (ice->eeprom.data[ICE_EEP2_ACLINK] & 0x80) {
+	if (ice->eeprom.data[ICE_EEP2_ACLINK] & VT1724_CFG_PRO_I2S) {
 		/* I2S */
-		if (ice->eeprom.data[ICE_EEP2_I2S] & 0x08)
+		/* VT1720 doesn't support more than 96kHz */
+		if ((ice->eeprom.data[ICE_EEP2_I2S] & 0x08) && !ice->vt1720)
 			return snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_RATE, &hw_constraints_rates_192);
 		else {
 			runtime->hw.rates = SNDRV_PCM_RATE_KNOT | SNDRV_PCM_RATE_8000_96000;
@@ -709,25 +725,14 @@
 		}
 	} else if (ice->ac97) {
 		/* ACLINK */
-		int ratec;
-		if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
-			ratec = AC97_RATES_FRONT_DAC;
-		else
-			ratec = AC97_RATES_ADC;
-		runtime->hw.rates = ice->ac97->rates[ratec];
 		runtime->hw.rate_max = 48000;
-		if (runtime->hw.rates == SNDRV_PCM_RATE_48000) {
-			runtime->hw.rate_min = 48000;
-			return 0;
-		} else {
-			runtime->hw.rates = SNDRV_PCM_RATE_KNOT | SNDRV_PCM_RATE_8000_48000;
-			return snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_RATE, &hw_constraints_rates_48);
-		}
+		runtime->hw.rates = SNDRV_PCM_RATE_KNOT | SNDRV_PCM_RATE_8000_48000;
+		return snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_RATE, &hw_constraints_rates_48);
 	}
 	return 0;
 }
 
-/* multi-channel playback needs alignment 8x32bit regarless of the channels
+/* multi-channel playback needs alignment 8x32bit regardless of the channels
  * actually used
  */
 #define VT1724_BUFFER_ALIGN	0x20
@@ -738,7 +743,7 @@
 	ice1712_t *ice = snd_pcm_substream_chip(substream);
 	int chs;
 
-	runtime->private_data = (void*)VT1724_PDMA0_START; /* irq/status/trigger bit */
+	runtime->private_data = &vt1724_playback_pro_reg;
 	ice->playback_pro_substream = substream;
 	runtime->hw = snd_vt1724_playback_pro;
 	snd_pcm_set_sync(substream);
@@ -767,12 +772,16 @@
 	ice1712_t *ice = snd_pcm_substream_chip(substream);
 	snd_pcm_runtime_t *runtime = substream->runtime;
 
-	runtime->private_data = (void*)VT1724_RDMA0_START; /* irq/status/trigger bit */
+	runtime->private_data = &vt1724_capture_pro_reg;
 	ice->capture_pro_substream = substream;
 	runtime->hw = snd_vt1724_2ch_stereo;
 	snd_pcm_set_sync(substream);
 	snd_pcm_hw_constraint_msbits(runtime, 0, 32, 24);
 	set_rate_constraints(ice, substream);
+	snd_pcm_hw_constraint_step(runtime, 0, SNDRV_PCM_HW_PARAM_PERIOD_BYTES,
+				   VT1724_BUFFER_ALIGN);
+	snd_pcm_hw_constraint_step(runtime, 0, SNDRV_PCM_HW_PARAM_BUFFER_BYTES,
+				   VT1724_BUFFER_ALIGN);
 	return 0;
 }
 
@@ -814,9 +823,9 @@
 	.ioctl =	snd_pcm_lib_ioctl,
 	.hw_params =	snd_vt1724_pcm_hw_params,
 	.hw_free =	snd_vt1724_pcm_hw_free,
-	.prepare =	snd_vt1724_capture_pro_prepare,
+	.prepare =	snd_vt1724_pcm_prepare,
 	.trigger =	snd_vt1724_pcm_trigger,
-	.pointer =	snd_vt1724_capture_pro_pointer,
+	.pointer =	snd_vt1724_pcm_pointer,
 };
 
 static int __devinit snd_vt1724_pcm_profi(ice1712_t * ice, int device)
@@ -848,40 +857,60 @@
  * SPDIF PCM
  */
 
-const static struct vt1724_pcm_reg vt1724_playback_spdif_reg = {
+static struct vt1724_pcm_reg vt1724_playback_spdif_reg = {
 	.addr = VT1724_MT_PDMA4_ADDR,
 	.size = VT1724_MT_PDMA4_SIZE,
 	.count = VT1724_MT_PDMA4_COUNT,
 	.start = VT1724_PDMA4_START,
-	.pause = VT1724_PDMA4_PAUSE,
 };
 
-const static struct vt1724_pcm_reg vt1724_capture_spdif_reg = {
+static struct vt1724_pcm_reg vt1724_capture_spdif_reg = {
 	.addr = VT1724_MT_RDMA1_ADDR,
 	.size = VT1724_MT_RDMA1_SIZE,
 	.count = VT1724_MT_RDMA1_COUNT,
 	.start = VT1724_RDMA1_START,
-	.pause = VT1724_RDMA1_PAUSE,
 };
 
-static int snd_vt1724_playback_spdif_prepare(snd_pcm_substream_t * substream)
+/* update spdif control bits; call with reg_lock */
+static void update_spdif_bits(ice1712_t *ice, unsigned int val)
 {
-	return snd_vt1724_pcm_prepare(substream, &vt1724_playback_spdif_reg);
-}
+	unsigned char cbit, disabled;
 
-static snd_pcm_uframes_t snd_vt1724_playback_spdif_pointer(snd_pcm_substream_t * substream)
-{
-	return snd_vt1724_pcm_pointer(substream, &vt1724_playback_spdif_reg);
+	cbit = inb(ICEREG1724(ice, SPDIF_CFG));
+	disabled = cbit & ~VT1724_CFG_SPDIF_OUT_EN;
+	if (cbit != disabled)
+		outb(disabled, ICEREG1724(ice, SPDIF_CFG));
+	outw(val, ICEMT1724(ice, SPDIF_CTRL));
+	if (cbit != disabled)
+		outb(cbit, ICEREG1724(ice, SPDIF_CFG));
+	outw(val, ICEMT1724(ice, SPDIF_CTRL));
 }
 
-static int snd_vt1724_capture_spdif_prepare(snd_pcm_substream_t * substream)
+/* update SPDIF control bits according to the given rate */
+static void update_spdif_rate(ice1712_t *ice, unsigned int rate)
 {
-	return snd_vt1724_pcm_prepare(substream, &vt1724_capture_spdif_reg);
+	unsigned int val, nval;
+	unsigned long flags;
+
+	spin_lock_irqsave(&ice->reg_lock, flags);
+	nval = val = inw(ICEMT1724(ice, SPDIF_CTRL));
+	nval &= ~(7 << 12);
+	switch (rate) {
+	case 44100: break;
+	case 48000: nval |= 2 << 12; break;
+	case 32000: nval |= 3 << 12; break;
+	}
+	if (val != nval)
+		update_spdif_bits(ice, nval);
+	spin_unlock_irqrestore(&ice->reg_lock, flags);
 }
 
-static snd_pcm_uframes_t snd_vt1724_capture_spdif_pointer(snd_pcm_substream_t * substream)
+static int snd_vt1724_playback_spdif_prepare(snd_pcm_substream_t * substream)
 {
-	return snd_vt1724_pcm_pointer(substream, &vt1724_capture_spdif_reg);
+	ice1712_t *ice = snd_pcm_substream_chip(substream);
+	if (! ice->force_pdma4)
+		update_spdif_rate(ice, substream->runtime->rate);
+	return snd_vt1724_pcm_prepare(substream);
 }
 
 static int snd_vt1724_playback_spdif_open(snd_pcm_substream_t *substream)
@@ -889,7 +918,7 @@
 	ice1712_t *ice = snd_pcm_substream_chip(substream);
 	snd_pcm_runtime_t *runtime = substream->runtime;
 
-	runtime->private_data = (void*)VT1724_PDMA4_START; /* irq/status/trigger bit */
+	runtime->private_data = &vt1724_playback_spdif_reg;
 	ice->playback_con_substream = substream;
 	if (ice->force_pdma4) {
 		runtime->hw = snd_vt1724_2ch_stereo;
@@ -898,6 +927,10 @@
 		runtime->hw = snd_vt1724_spdif;
 	snd_pcm_set_sync(substream);
 	snd_pcm_hw_constraint_msbits(runtime, 0, 32, 24);
+	snd_pcm_hw_constraint_step(runtime, 0, SNDRV_PCM_HW_PARAM_PERIOD_BYTES,
+				   VT1724_BUFFER_ALIGN);
+	snd_pcm_hw_constraint_step(runtime, 0, SNDRV_PCM_HW_PARAM_BUFFER_BYTES,
+				   VT1724_BUFFER_ALIGN);
 	return 0;
 }
 
@@ -917,7 +950,7 @@
 	ice1712_t *ice = snd_pcm_substream_chip(substream);
 	snd_pcm_runtime_t *runtime = substream->runtime;
 
-	runtime->private_data = (void*)VT1724_RDMA1_START; /* irq/status/trigger bit */
+	runtime->private_data = &vt1724_capture_spdif_reg;
 	ice->capture_con_substream = substream;
 	if (ice->force_rdma1) {
 		runtime->hw = snd_vt1724_2ch_stereo;
@@ -926,6 +959,10 @@
 		runtime->hw = snd_vt1724_spdif;
 	snd_pcm_set_sync(substream);
 	snd_pcm_hw_constraint_msbits(runtime, 0, 32, 24);
+	snd_pcm_hw_constraint_step(runtime, 0, SNDRV_PCM_HW_PARAM_PERIOD_BYTES,
+				   VT1724_BUFFER_ALIGN);
+	snd_pcm_hw_constraint_step(runtime, 0, SNDRV_PCM_HW_PARAM_BUFFER_BYTES,
+				   VT1724_BUFFER_ALIGN);
 	return 0;
 }
 
@@ -948,7 +985,7 @@
 	.hw_free =	snd_vt1724_pcm_hw_free,
 	.prepare =	snd_vt1724_playback_spdif_prepare,
 	.trigger =	snd_vt1724_pcm_trigger,
-	.pointer =	snd_vt1724_playback_spdif_pointer,
+	.pointer =	snd_vt1724_pcm_pointer,
 };
 
 static snd_pcm_ops_t snd_vt1724_capture_spdif_ops = {
@@ -957,9 +994,9 @@
 	.ioctl =	snd_pcm_lib_ioctl,
 	.hw_params =	snd_vt1724_pcm_hw_params,
 	.hw_free =	snd_vt1724_pcm_hw_free,
-	.prepare =	snd_vt1724_capture_spdif_prepare,
+	.prepare =	snd_vt1724_pcm_prepare,
 	.trigger =	snd_vt1724_pcm_trigger,
-	.pointer =	snd_vt1724_capture_spdif_pointer,
+	.pointer =	snd_vt1724_pcm_pointer,
 };
 
 
@@ -1017,27 +1054,24 @@
  * independent surround PCMs
  */
 
-const static struct vt1724_pcm_reg vt1724_playback_dma_regs[3] = {
+static struct vt1724_pcm_reg vt1724_playback_dma_regs[3] = {
 	{
 		.addr = VT1724_MT_PDMA1_ADDR,
 		.size = VT1724_MT_PDMA1_SIZE,
 		.count = VT1724_MT_PDMA1_COUNT,
 		.start = VT1724_PDMA1_START,
-		.pause = VT1724_PDMA1_PAUSE,
 	},
 	{
 		.addr = VT1724_MT_PDMA2_ADDR,
 		.size = VT1724_MT_PDMA2_SIZE,
 		.count = VT1724_MT_PDMA2_COUNT,
 		.start = VT1724_PDMA2_START,
-		.pause = VT1724_PDMA2_PAUSE,
 	},
 	{
 		.addr = VT1724_MT_PDMA3_ADDR,
 		.size = VT1724_MT_PDMA3_SIZE,
 		.count = VT1724_MT_PDMA3_COUNT,
 		.start = VT1724_PDMA3_START,
-		.pause = VT1724_PDMA3_PAUSE,
 	},
 };
 
@@ -1046,17 +1080,12 @@
 	ice1712_t *ice = snd_pcm_substream_chip(substream);
 	unsigned char val;
 
-	spin_lock(&ice->reg_lock);
+	spin_lock_irq(&ice->reg_lock);
 	val = 3 - substream->number;
 	if (inb(ICEMT1724(ice, BURST)) < val)
 		outb(val, ICEMT1724(ice, BURST));
-	spin_unlock(&ice->reg_lock);
-	return snd_vt1724_pcm_prepare(substream, &vt1724_playback_dma_regs[substream->number]);
-}
-
-static snd_pcm_uframes_t snd_vt1724_playback_indep_pointer(snd_pcm_substream_t * substream)
-{
-	return snd_vt1724_pcm_pointer(substream, &vt1724_playback_dma_regs[substream->number]);
+	spin_unlock_irq(&ice->reg_lock);
+	return snd_vt1724_pcm_prepare(substream);
 }
 
 static int snd_vt1724_playback_indep_open(snd_pcm_substream_t *substream)
@@ -1071,7 +1100,7 @@
 		return -EBUSY; /* FIXME: should handle blocking mode properly */
 	}
 	up(&ice->open_mutex);
-	runtime->private_data = (void*)(1UL << (substream->number + 4));
+	runtime->private_data = &vt1724_playback_dma_regs[substream->number];
 	ice->playback_con_substream_ds[substream->number] = substream;
 	runtime->hw = snd_vt1724_2ch_stereo;
 	snd_pcm_set_sync(substream);
@@ -1100,7 +1129,7 @@
 	.hw_free =	snd_vt1724_pcm_hw_free,
 	.prepare =	snd_vt1724_playback_indep_prepare,
 	.trigger =	snd_vt1724_pcm_trigger,
-	.pointer =	snd_vt1724_playback_indep_pointer,
+	.pointer =	snd_vt1724_pcm_pointer,
 };
 
 
@@ -1143,17 +1172,19 @@
 	int err;
 
 	if (! (ice->eeprom.data[ICE_EEP2_ACLINK] & VT1724_CFG_PRO_I2S)) {
-		ac97_bus_t bus, *pbus;
-		ac97_t ac97;
+		ac97_bus_t *pbus;
+		ac97_template_t ac97;
+		static ac97_bus_ops_t ops = {
+			.write = snd_vt1724_ac97_write,
+			.read = snd_vt1724_ac97_read,
+		};
+
 		/* cold reset */
 		outb(inb(ICEMT1724(ice, AC97_CMD)) | 0x80, ICEMT1724(ice, AC97_CMD));
 		mdelay(5); /* FIXME */
 		outb(inb(ICEMT1724(ice, AC97_CMD)) & ~0x80, ICEMT1724(ice, AC97_CMD));
 
-		memset(&bus, 0, sizeof(bus));
-		bus.write = snd_vt1724_ac97_write;
-		bus.read = snd_vt1724_ac97_read;
-		if ((err = snd_ac97_bus(ice->card, &bus, &pbus)) < 0)
+		if ((err = snd_ac97_bus(ice->card, 0, &ops, NULL, &pbus)) < 0)
 			return err;
 		memset(&ac97, 0, sizeof(ac97));
 		ac97.private_data = ice;
@@ -1181,7 +1212,7 @@
 static void snd_vt1724_proc_read(snd_info_entry_t *entry, 
 				 snd_info_buffer_t * buffer)
 {
-	ice1712_t *ice = snd_magic_cast(ice1712_t, entry->private_data, return);
+	ice1712_t *ice = entry->private_data;
 	unsigned int idx;
 
 	snd_iprintf(buffer, "%s\n\n", ice->card->longname);
@@ -1274,7 +1305,7 @@
 		}
 	} else {
 		/* consumer */
-		val |= diga->status[0] & 0x04; /* copyright */
+		val |= diga->status[1] & 0x04; /* copyright */
 		if ((diga->status[0] & IEC958_AES0_CON_EMPHASIS)== IEC958_AES0_CON_EMPHASIS_5015)
 			val |= 1U << 3;
 		val |= (unsigned int)(diga->status[1] & 0x3f) << 4; /* category */
@@ -1326,22 +1357,13 @@
 {
 	ice1712_t *ice = snd_kcontrol_chip(kcontrol);
 	unsigned int val, old;
-	unsigned long flags;
 
 	val = encode_spdif_bits(&ucontrol->value.iec958);
-	spin_lock_irqsave(&ice->reg_lock, flags);
+	spin_lock_irq(&ice->reg_lock);
 	old = inw(ICEMT1724(ice, SPDIF_CTRL));
-	if (val != old) {
-		unsigned char cbit, disabled;
-		cbit = inb(ICEREG1724(ice, SPDIF_CFG));
-		disabled = cbit & ~VT1724_CFG_SPDIF_OUT_EN;
-		if (cbit != disabled)
-			outb(disabled, ICEREG1724(ice, SPDIF_CFG));
-		outw(val, ICEMT1724(ice, SPDIF_CTRL));
-		if (cbit != disabled)
-			outb(cbit, ICEREG1724(ice, SPDIF_CFG));
-	}
-	spin_unlock_irqrestore(&ice->reg_lock, flags);
+	if (val != old)
+		update_spdif_bits(ice, val);
+	spin_unlock_irq(&ice->reg_lock);
 	return (val != old);
 }
 
@@ -1415,15 +1437,15 @@
 {
 	ice1712_t *ice = snd_kcontrol_chip(kcontrol);
 	unsigned char old, val;
-	unsigned long flags;
-	spin_lock_irqsave(&ice->reg_lock, flags);
+
+	spin_lock_irq(&ice->reg_lock);
 	old = val = inb(ICEREG1724(ice, SPDIF_CFG));
 	val &= ~VT1724_CFG_SPDIF_OUT_EN;
 	if (ucontrol->value.integer.value[0])
 		val |= VT1724_CFG_SPDIF_OUT_EN;
 	if (old != val)
 		outb(val, ICEREG1724(ice, SPDIF_CFG));
-	spin_unlock_irqrestore(&ice->reg_lock, flags);
+	spin_unlock_irq(&ice->reg_lock);
 	return old != val;
 }
 
@@ -1490,7 +1512,7 @@
  */
 static int snd_vt1724_pro_internal_clock_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)
 {
-	static char *texts[] = {
+	static char *texts_1724[] = {
 		"8000",		/* 0: 6 */
 		"9600",		/* 1: 3 */
 		"11025",	/* 2: 10 */
@@ -1508,12 +1530,32 @@
 		"192000",	/* 14: 14 */
 		"IEC958 Input",	/* 15: -- */
 	};
+	static char *texts_1720[] = {
+		"8000",		/* 0: 6 */
+		"9600",		/* 1: 3 */
+		"11025",	/* 2: 10 */
+		"12000",	/* 3: 2 */
+		"16000",	/* 4: 5 */
+		"22050",	/* 5: 9 */
+		"24000",	/* 6: 1 */
+		"32000",	/* 7: 4 */
+		"44100",	/* 8: 8 */
+		"48000",	/* 9: 0 */
+		"64000",	/* 10: 15 */
+		"88200",	/* 11: 11 */
+		"96000",	/* 12: 7 */
+		"IEC958 Input",	/* 13: -- */
+	};
+	ice1712_t *ice = snd_kcontrol_chip(kcontrol);
+
 	uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
 	uinfo->count = 1;
-	uinfo->value.enumerated.items = 16;
+	uinfo->value.enumerated.items = ice->vt1720 ? 14 : 16;
 	if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
 		uinfo->value.enumerated.item = uinfo->value.enumerated.items - 1;
-	strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]);
+	strcpy(uinfo->value.enumerated.name,
+	       ice->vt1720 ? texts_1720[uinfo->value.enumerated.item] :
+	       texts_1724[uinfo->value.enumerated.item]);
 	return 0;
 }
 
@@ -1527,7 +1569,7 @@
 	
 	spin_lock_irq(&ice->reg_lock);
 	if (is_spdif_master(ice)) {
-		ucontrol->value.enumerated.item[0] = 15;
+		ucontrol->value.enumerated.item[0] = ice->vt1720 ? 13 : 15;
 	} else {
 		val = xlate[inb(ICEMT1724(ice, RATE)) & 15];
 		if (val == 255) {
@@ -1544,17 +1586,22 @@
 {
 	ice1712_t *ice = snd_kcontrol_chip(kcontrol);
 	unsigned char oval;
+	int rate;
 	int change = 0;
+	int spdif = ice->vt1720 ? 13 : 15;
 
 	spin_lock_irq(&ice->reg_lock);
 	oval = inb(ICEMT1724(ice, RATE));
-	if (ucontrol->value.enumerated.item[0] == 15) {
+	if (ucontrol->value.enumerated.item[0] == spdif) {
 		outb(oval | VT1724_SPDIF_MASTER, ICEMT1724(ice, RATE));
 	} else {
-		PRO_RATE_DEFAULT = rates[ucontrol->value.integer.value[0] % 15];
-		spin_unlock_irq(&ice->reg_lock);
-		snd_vt1724_set_pro_rate(ice, PRO_RATE_DEFAULT, 1);
-		spin_lock_irq(&ice->reg_lock);
+		rate = rates[ucontrol->value.integer.value[0] % 15];
+		if (rate <= get_max_rate(ice)) {
+			PRO_RATE_DEFAULT = rate;
+			spin_unlock_irq(&ice->reg_lock);
+			snd_vt1724_set_pro_rate(ice, PRO_RATE_DEFAULT, 1);
+			spin_lock_irq(&ice->reg_lock);
+		}
 	}
 	change = inb(ICEMT1724(ice, RATE)) != oval;
 	spin_unlock_irq(&ice->reg_lock);
@@ -1815,6 +1862,8 @@
 	snd_vt1724_revo_cards,
 	snd_vt1724_amp_cards, 
 	snd_vt1724_aureon_cards,
+	snd_vt1720_mobo_cards,
+	snd_vt1720_pontis_cards,
 	NULL,
 };
 
@@ -1822,24 +1871,28 @@
 /*
  */
 
-unsigned char snd_vt1724_read_i2c(ice1712_t *ice, unsigned char dev, unsigned char addr)
+static void wait_i2c_busy(ice1712_t *ice)
 {
-	long t = 0x10000;
+	int t = 0x10000;
+	while ((inb(ICEREG1724(ice, I2C_CTRL)) & VT1724_I2C_BUSY) && t--)
+		;
+}
 
+unsigned char snd_vt1724_read_i2c(ice1712_t *ice, unsigned char dev, unsigned char addr)
+{
 	outb(addr, ICEREG1724(ice, I2C_BYTE_ADDR));
 	outb(dev & ~VT1724_I2C_WRITE, ICEREG1724(ice, I2C_DEV_ADDR));
-	while (t-- > 0 && (inb(ICEREG1724(ice, I2C_CTRL)) & VT1724_I2C_BUSY)) ;
+	wait_i2c_busy(ice);
 	return inb(ICEREG1724(ice, I2C_DATA));
 }
 
 void snd_vt1724_write_i2c(ice1712_t *ice, unsigned char dev, unsigned char addr, unsigned char data)
 {
-	long t = 0x10000;
-
+	wait_i2c_busy(ice);
 	outb(addr, ICEREG1724(ice, I2C_BYTE_ADDR));
 	outb(data, ICEREG1724(ice, I2C_DATA));
 	outb(dev | VT1724_I2C_WRITE, ICEREG1724(ice, I2C_DEV_ADDR));
-	while (t-- > 0 && (inb(ICEREG1724(ice, I2C_CTRL)) & VT1724_I2C_BUSY)) ;
+	wait_i2c_busy(ice);
 }
 
 static int __devinit snd_vt1724_read_eeprom(ice1712_t *ice, const char *modelname)
@@ -1930,9 +1983,6 @@
 
 	outb(0, ICEREG1724(ice, POWERDOWN));
 
-	/* read back to check the availability of SPDIF out */
-	ice->eeprom.data[ICE_EEP2_SPDIF] = inb(ICEREG1724(ice, SPDIF_CFG));
-
 	return 0;
 }
 
@@ -1994,10 +2044,9 @@
 
 	if (ice->num_total_dacs > 0) {
 		snd_kcontrol_new_t tmp = snd_vt1724_mixer_pro_analog_route;
-		if (ice->vt1720)
+		tmp.count = ice->num_total_dacs;
+		if (ice->vt1720 && tmp.count > 2)
 			tmp.count = 2;
-		else
-			tmp.count = ice->num_total_dacs;
 		err = snd_ctl_add(ice->card, snd_ctl_new1(&tmp, ice));
 		if (err < 0)
 			return err;
@@ -2012,7 +2061,7 @@
 
 static int snd_vt1724_free(ice1712_t *ice)
 {
-	if (ice->res_port == NULL)
+	if (! ice->port)
 		goto __hw_end;
 	/* mask all interrupts */
 	outb(0xff, ICEMT1724(ice, DMA_INT_MASK));
@@ -2023,22 +2072,15 @@
 		synchronize_irq(ice->irq);
 		free_irq(ice->irq, (void *) ice);
 	}
-	if (ice->res_port) {
-		release_resource(ice->res_port);
-		kfree_nocheck(ice->res_port);
-	}
-	if (ice->res_profi_port) {
-		release_resource(ice->res_profi_port);
-		kfree_nocheck(ice->res_profi_port);
-	}
+	pci_release_regions(ice->pci);
 	snd_ice1712_akm4xxx_free(ice);
-	snd_magic_kfree(ice);
+	kfree(ice);
 	return 0;
 }
 
 static int snd_vt1724_dev_free(snd_device_t *device)
 {
-	ice1712_t *ice = snd_magic_cast(ice1712_t, device->device_data, return -ENXIO);
+	ice1712_t *ice = device->device_data;
 	return snd_vt1724_free(ice);
 }
 
@@ -2060,7 +2102,7 @@
 	if ((err = pci_enable_device(pci)) < 0)
 		return err;
 
-	ice = snd_magic_kcalloc(ice1712_t, 0, GFP_KERNEL);
+	ice = kcalloc(1, sizeof(*ice), GFP_KERNEL);
 	if (ice == NULL)
 		return -ENOMEM;
 	ice->vt1724 = 1;
@@ -2074,24 +2116,17 @@
 	ice->card = card;
 	ice->pci = pci;
 	ice->irq = -1;
-	ice->port = pci_resource_start(pci, 0);
-	ice->profi_port = pci_resource_start(pci, 1);
 	pci_set_master(pci);
 	snd_vt1724_proc_init(ice);
 	synchronize_irq(pci->irq);
 
-	if ((ice->res_port = request_region(ice->port, 32, "ICE1724 - Controller")) == NULL) {
-		snd_printk("unable to grab ports 0x%lx-0x%lx\n", ice->port, ice->port + 32 - 1);
-		snd_vt1724_free(ice);
-		return -EIO;
+	if ((err = pci_request_regions(pci, "ICE1724")) < 0) {
+		kfree(ice);
+		return err;
 	}
+	ice->port = pci_resource_start(pci, 0);
+	ice->profi_port = pci_resource_start(pci, 1);
 
-	if ((ice->res_profi_port = request_region(ice->profi_port, 128, "ICE1724 - Professional")) == NULL) {
-		snd_printk("unable to grab ports 0x%lx-0x%lx\n", ice->profi_port, ice->profi_port + 16 - 1);
-		snd_vt1724_free(ice);
-		return -EIO;
-	}
-		
 	if (request_irq(pci->irq, snd_vt1724_interrupt, SA_INTERRUPT|SA_SHIRQ, "ICE1724", (void *) ice)) {
 		snd_printk("unable to grab IRQ %d\n", pci->irq);
 		snd_vt1724_free(ice);
diff -Nru a/sound/pci/ice1712/pontis.c b/sound/pci/ice1712/pontis.c
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/sound/pci/ice1712/pontis.c	2004-10-18 14:57:23 -07:00
@@ -0,0 +1,849 @@
+/*
+ *   ALSA driver for ICEnsemble VT1724 (Envy24HT)
+ *
+ *   Lowlevel functions for Pontis MS300
+ *
+ *	Copyright (c) 2004 Takashi Iwai <tiwai@suse.de>
+ *
+ *   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
+ *
+ */
+
+#include <sound/driver.h>
+#include <asm/io.h>
+#include <linux/delay.h>
+#include <linux/interrupt.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <sound/core.h>
+#include <sound/info.h>
+
+#include "ice1712.h"
+#include "envy24ht.h"
+#include "pontis.h"
+
+/* I2C addresses */
+#define WM_DEV		0x34
+#define CS_DEV		0x20
+
+/* WM8776 registers */
+#define WM_HP_ATTEN_L		0x00	/* headphone left attenuation */
+#define WM_HP_ATTEN_R		0x01	/* headphone left attenuation */
+#define WM_HP_MASTER		0x02	/* headphone master (both channels), override LLR */
+#define WM_DAC_ATTEN_L		0x03	/* digital left attenuation */
+#define WM_DAC_ATTEN_R		0x04
+#define WM_DAC_MASTER		0x05
+#define WM_PHASE_SWAP		0x06	/* DAC phase swap */
+#define WM_DAC_CTRL1		0x07
+#define WM_DAC_MUTE		0x08
+#define WM_DAC_CTRL2		0x09
+#define WM_DAC_INT		0x0a
+#define WM_ADC_INT		0x0b
+#define WM_MASTER_CTRL		0x0c
+#define WM_POWERDOWN		0x0d
+#define WM_ADC_ATTEN_L		0x0e
+#define WM_ADC_ATTEN_R		0x0f
+#define WM_ALC_CTRL1		0x10
+#define WM_ALC_CTRL2		0x11
+#define WM_ALC_CTRL3		0x12
+#define WM_NOISE_GATE		0x13
+#define WM_LIMITER		0x14
+#define WM_ADC_MUX		0x15
+#define WM_OUT_MUX		0x16
+#define WM_RESET		0x17
+
+/*
+ * GPIO
+ */
+#define PONTIS_CS_CS		(1<<4)	/* CS */
+#define PONTIS_CS_CLK		(1<<5)	/* CLK */
+#define PONTIS_CS_RDATA		(1<<6)	/* CS8416 -> VT1720 */
+#define PONTIS_CS_WDATA		(1<<7)	/* VT1720 -> CS8416 */
+
+
+/*
+ * get the current register value of WM codec
+ */
+static unsigned short wm_get(ice1712_t *ice, int reg)
+{
+	reg <<= 1;
+	return ((unsigned short)ice->akm[0].images[reg] << 8) |
+		ice->akm[0].images[reg + 1];
+}
+
+/*
+ * set the register value of WM codec and remember it
+ */
+static void wm_put_nocache(ice1712_t *ice, int reg, unsigned short val)
+{
+	unsigned short cval;
+	cval = (reg << 9) | val;
+	snd_vt1724_write_i2c(ice, WM_DEV, cval >> 8, cval & 0xff);
+}
+
+static void wm_put(ice1712_t *ice, int reg, unsigned short val)
+{
+	wm_put_nocache(ice, reg, val);
+	reg <<= 1;
+	ice->akm[0].images[reg] = val >> 8;
+	ice->akm[0].images[reg + 1] = val;
+}
+
+/*
+ * DAC volume attenuation mixer control (-64dB to 0dB)
+ */
+
+#define DAC_0dB	0xff
+#define DAC_RES	128
+#define DAC_MIN	(DAC_0dB - DAC_RES)
+
+static int wm_dac_vol_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo)
+{
+	uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
+	uinfo->count = 2;
+	uinfo->value.integer.min = 0;	/* mute */
+	uinfo->value.integer.max = DAC_RES;	/* 0dB, 0.5dB step */
+	return 0;
+}
+
+static int wm_dac_vol_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+{
+	ice1712_t *ice = snd_kcontrol_chip(kcontrol);
+	unsigned short val;
+	int i;
+
+	down(&ice->gpio_mutex);
+	for (i = 0; i < 2; i++) {
+		val = wm_get(ice, WM_DAC_ATTEN_L + i) & 0xff;
+		val = val > DAC_MIN ? (val - DAC_MIN) : 0;
+		ucontrol->value.integer.value[i] = val;
+	}
+	up(&ice->gpio_mutex);
+	return 0;
+}
+
+static int wm_dac_vol_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+{
+	ice1712_t *ice = snd_kcontrol_chip(kcontrol);
+	unsigned short oval, nval;
+	int i, idx, change = 0;
+
+	down(&ice->gpio_mutex);
+	for (i = 0; i < 2; i++) {
+		nval = ucontrol->value.integer.value[i];
+		nval = (nval ? (nval + DAC_MIN) : 0) & 0xff;
+		idx = WM_DAC_ATTEN_L + i;
+		oval = wm_get(ice, idx) & 0xff;
+		if (oval != nval) {
+			wm_put(ice, idx, nval);
+			wm_put_nocache(ice, idx, nval | 0x100);
+			change = 1;
+		}
+	}
+	up(&ice->gpio_mutex);
+	return change;
+}
+
+/*
+ * ADC gain mixer control (-64dB to 0dB)
+ */
+
+#define ADC_0dB	0xcf
+#define ADC_RES	128
+#define ADC_MIN	(ADC_0dB - ADC_RES)
+
+static int wm_adc_vol_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo)
+{
+	uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
+	uinfo->count = 2;
+	uinfo->value.integer.min = 0;	/* mute (-64dB) */
+	uinfo->value.integer.max = ADC_RES;	/* 0dB, 0.5dB step */
+	return 0;
+}
+
+static int wm_adc_vol_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+{
+	ice1712_t *ice = snd_kcontrol_chip(kcontrol);
+	unsigned short val;
+	int i;
+
+	down(&ice->gpio_mutex);
+	for (i = 0; i < 2; i++) {
+		val = wm_get(ice, WM_ADC_ATTEN_L + i) & 0xff;
+		val = val > ADC_MIN ? (val - ADC_MIN) : 0;
+		ucontrol->value.integer.value[i] = val;
+	}
+	up(&ice->gpio_mutex);
+	return 0;
+}
+
+static int wm_adc_vol_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+{
+	ice1712_t *ice = snd_kcontrol_chip(kcontrol);
+	unsigned short ovol, nvol;
+	int i, idx, change = 0;
+
+	down(&ice->gpio_mutex);
+	for (i = 0; i < 2; i++) {
+		nvol = ucontrol->value.integer.value[i];
+		nvol = nvol ? (nvol + ADC_MIN) : 0;
+		idx  = WM_ADC_ATTEN_L + i;
+		ovol = wm_get(ice, idx) & 0xff;
+		if (ovol != nvol) {
+			wm_put(ice, idx, nvol);
+			change = 1;
+		}
+	}
+	up(&ice->gpio_mutex);
+	return change;
+}
+
+/*
+ * ADC input mux mixer control
+ */
+static int wm_adc_mux_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo)
+{
+	uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
+	uinfo->count = 1;
+	uinfo->value.integer.min = 0;
+	uinfo->value.integer.max = 1;
+	return 0;
+}
+
+static int wm_adc_mux_get(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t *ucontrol)
+{
+	ice1712_t *ice = snd_kcontrol_chip(kcontrol);
+	int bit = kcontrol->private_value;
+
+	down(&ice->gpio_mutex);
+	ucontrol->value.integer.value[0] = (wm_get(ice, WM_ADC_MUX) & (1 << bit)) ? 1 : 0;
+	up(&ice->gpio_mutex);
+	return 0;
+}
+
+static int wm_adc_mux_put(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t *ucontrol)
+{
+	ice1712_t *ice = snd_kcontrol_chip(kcontrol);
+	int bit = kcontrol->private_value;
+	unsigned short oval, nval;
+	int change;
+
+	down(&ice->gpio_mutex);
+	nval = oval = wm_get(ice, WM_ADC_MUX);
+	if (ucontrol->value.integer.value[0])
+		nval |= (1 << bit);
+	else
+		nval &= ~(1 << bit);
+	change = nval != oval;
+	if (change) {
+		wm_put(ice, WM_ADC_MUX, nval);
+	}
+	up(&ice->gpio_mutex);
+	return 0;
+}
+
+/*
+ * Analog bypass (In -> Out)
+ */
+static int wm_bypass_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo)
+{
+	uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
+	uinfo->count = 1;
+	uinfo->value.integer.min = 0;
+	uinfo->value.integer.max = 1;
+	return 0;
+}
+
+static int wm_bypass_get(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t *ucontrol)
+{
+	ice1712_t *ice = snd_kcontrol_chip(kcontrol);
+
+	down(&ice->gpio_mutex);
+	ucontrol->value.integer.value[0] = (wm_get(ice, WM_OUT_MUX) & 0x04) ? 1 : 0;
+	up(&ice->gpio_mutex);
+	return 0;
+}
+
+static int wm_bypass_put(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t *ucontrol)
+{
+	ice1712_t *ice = snd_kcontrol_chip(kcontrol);
+	unsigned short val, oval;
+	int change = 0;
+
+	down(&ice->gpio_mutex);
+	val = oval = wm_get(ice, WM_OUT_MUX);
+	if (ucontrol->value.integer.value[0])
+		val |= 0x04;
+	else
+		val &= ~0x04;
+	if (val != oval) {
+		wm_put(ice, WM_OUT_MUX, val);
+		change = 1;
+	}
+	up(&ice->gpio_mutex);
+	return change;
+}
+
+/*
+ * Left/Right swap
+ */
+static int wm_chswap_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo)
+{
+	uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
+	uinfo->count = 1;
+	uinfo->value.integer.min = 0;
+	uinfo->value.integer.max = 1;
+	return 0;
+}
+
+static int wm_chswap_get(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t *ucontrol)
+{
+	ice1712_t *ice = snd_kcontrol_chip(kcontrol);
+
+	down(&ice->gpio_mutex);
+	ucontrol->value.integer.value[0] = (wm_get(ice, WM_DAC_CTRL1) & 0xf0) != 0x90;
+	up(&ice->gpio_mutex);
+	return 0;
+}
+
+static int wm_chswap_put(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t *ucontrol)
+{
+	ice1712_t *ice = snd_kcontrol_chip(kcontrol);
+	unsigned short val, oval;
+	int change = 0;
+
+	down(&ice->gpio_mutex);
+	oval = wm_get(ice, WM_DAC_CTRL1);
+	val = oval & 0x0f;
+	if (ucontrol->value.integer.value[0])
+		val |= 0x60;
+	else
+		val |= 0x90;
+	if (val != oval) {
+		wm_put(ice, WM_DAC_CTRL1, val);
+		wm_put_nocache(ice, WM_DAC_CTRL1, val);
+		change = 1;
+	}
+	up(&ice->gpio_mutex);
+	return change;
+}
+
+/*
+ * write data in the SPI mode
+ */
+static void set_gpio_bit(ice1712_t *ice, unsigned int bit, int val)
+{
+	unsigned int tmp = snd_ice1712_gpio_read(ice);
+	if (val)
+		tmp |= bit;
+	else
+		tmp &= ~bit;
+	snd_ice1712_gpio_write(ice, tmp);
+}
+
+static void spi_send_byte(ice1712_t *ice, unsigned char data)
+{
+	int i;
+	for (i = 0; i < 8; i++) {
+		set_gpio_bit(ice, PONTIS_CS_CLK, 0);
+		udelay(1);
+		set_gpio_bit(ice, PONTIS_CS_WDATA, data & 0x80);
+		udelay(1);
+		set_gpio_bit(ice, PONTIS_CS_CLK, 1);
+		udelay(1);
+		data <<= 1;
+	}
+}
+
+static unsigned int spi_read_byte(ice1712_t *ice)
+{
+	int i;
+	unsigned int val = 0;
+
+	for (i = 0; i < 8; i++) {
+		val <<= 1;
+		set_gpio_bit(ice, PONTIS_CS_CLK, 0);
+		udelay(1);
+		if (snd_ice1712_gpio_read(ice) & PONTIS_CS_RDATA)
+			val |= 1;
+		udelay(1);
+		set_gpio_bit(ice, PONTIS_CS_CLK, 1);
+		udelay(1);
+	}
+	return val;
+}
+
+
+static void spi_write(ice1712_t *ice, unsigned int dev, unsigned int reg, unsigned int data)
+{
+	snd_ice1712_gpio_set_dir(ice, PONTIS_CS_CS|PONTIS_CS_WDATA|PONTIS_CS_CLK);
+	snd_ice1712_gpio_set_mask(ice, ~(PONTIS_CS_CS|PONTIS_CS_WDATA|PONTIS_CS_CLK));
+	set_gpio_bit(ice, PONTIS_CS_CS, 0);
+	spi_send_byte(ice, dev & ~1); /* WRITE */
+	spi_send_byte(ice, reg); /* MAP */
+	spi_send_byte(ice, data); /* DATA */
+	/* trigger */
+	set_gpio_bit(ice, PONTIS_CS_CS, 1);
+	udelay(1);
+	/* restore */
+	snd_ice1712_gpio_set_mask(ice, ice->gpio.write_mask);
+	snd_ice1712_gpio_set_dir(ice, ice->gpio.direction);
+}
+
+static unsigned int spi_read(ice1712_t *ice, unsigned int dev, unsigned int reg)
+{
+	unsigned int val;
+	snd_ice1712_gpio_set_dir(ice, PONTIS_CS_CS|PONTIS_CS_WDATA|PONTIS_CS_CLK);
+	snd_ice1712_gpio_set_mask(ice, ~(PONTIS_CS_CS|PONTIS_CS_WDATA|PONTIS_CS_CLK));
+	set_gpio_bit(ice, PONTIS_CS_CS, 0);
+	spi_send_byte(ice, dev & ~1); /* WRITE */
+	spi_send_byte(ice, reg); /* MAP */
+	/* trigger */
+	set_gpio_bit(ice, PONTIS_CS_CS, 1);
+	udelay(1);
+	set_gpio_bit(ice, PONTIS_CS_CS, 0);
+	spi_send_byte(ice, dev | 1); /* READ */
+	val = spi_read_byte(ice);
+	/* trigger */
+	set_gpio_bit(ice, PONTIS_CS_CS, 1);
+	udelay(1);
+	/* restore */
+	snd_ice1712_gpio_set_mask(ice, ice->gpio.write_mask);
+	snd_ice1712_gpio_set_dir(ice, ice->gpio.direction);
+	return val;
+}
+
+
+/*
+ * SPDIF input source
+ */
+static int cs_source_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo)
+{
+	static char *texts[] = {
+		"Coax",		/* RXP0 */
+		"Optical",	/* RXP1 */
+		"CD",		/* RXP2 */
+	};
+	uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
+	uinfo->count = 1;
+	uinfo->value.enumerated.items = 3;
+	if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
+		uinfo->value.enumerated.item = uinfo->value.enumerated.items - 1;
+	strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]);
+	return 0;
+}
+
+static int cs_source_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+{
+	ice1712_t *ice = snd_kcontrol_chip(kcontrol);
+
+	down(&ice->gpio_mutex);
+	ucontrol->value.enumerated.item[0] = ice->gpio.saved[0];
+	up(&ice->gpio_mutex);
+	return 0;
+}
+
+static int cs_source_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+{
+	ice1712_t *ice = snd_kcontrol_chip(kcontrol);
+	unsigned char val;
+	int change = 0;
+
+	down(&ice->gpio_mutex);
+	if (ucontrol->value.enumerated.item[0] != ice->gpio.saved[0]) {
+		ice->gpio.saved[0] = ucontrol->value.enumerated.item[0] & 3;
+		val = 0x80 | (ice->gpio.saved[0] << 3);
+		spi_write(ice, CS_DEV, 0x04, val);
+		change = 1;
+	}
+	up(&ice->gpio_mutex);
+	return 0;
+}
+
+
+/*
+ * GPIO controls
+ */
+static int pontis_gpio_mask_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo)
+{
+	uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
+	uinfo->count = 1;
+	uinfo->value.integer.min = 0;
+	uinfo->value.integer.max = 0xffff; /* 16bit */
+	return 0;
+}
+
+static int pontis_gpio_mask_get(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t *ucontrol)
+{
+	ice1712_t *ice = snd_kcontrol_chip(kcontrol);
+	down(&ice->gpio_mutex);
+	/* 4-7 reserved */
+	ucontrol->value.integer.value[0] = (~ice->gpio.write_mask & 0xffff) | 0x00f0;
+	up(&ice->gpio_mutex);
+	return 0;
+}
+	
+static int pontis_gpio_mask_put(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t *ucontrol)
+{
+	ice1712_t *ice = snd_kcontrol_chip(kcontrol);
+	unsigned int val;
+	int changed;
+	down(&ice->gpio_mutex);
+	/* 4-7 reserved */
+	val = (~ucontrol->value.integer.value[0] & 0xffff) | 0x00f0;
+	changed = val != ice->gpio.write_mask;
+	ice->gpio.write_mask = val;
+	up(&ice->gpio_mutex);
+	return changed;
+}
+
+static int pontis_gpio_dir_get(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t *ucontrol)
+{
+	ice1712_t *ice = snd_kcontrol_chip(kcontrol);
+	down(&ice->gpio_mutex);
+	/* 4-7 reserved */
+	ucontrol->value.integer.value[0] = ice->gpio.direction & 0xff0f;
+	up(&ice->gpio_mutex);
+	return 0;
+}
+	
+static int pontis_gpio_dir_put(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t *ucontrol)
+{
+	ice1712_t *ice = snd_kcontrol_chip(kcontrol);
+	unsigned int val;
+	int changed;
+	down(&ice->gpio_mutex);
+	/* 4-7 reserved */
+	val = ucontrol->value.integer.value[0] & 0xff0f;
+	changed = (val != ice->gpio.direction);
+	ice->gpio.direction = val;
+	up(&ice->gpio_mutex);
+	return changed;
+}
+
+static int pontis_gpio_data_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+{
+	ice1712_t *ice = snd_kcontrol_chip(kcontrol);
+	down(&ice->gpio_mutex);
+	snd_ice1712_gpio_set_dir(ice, ice->gpio.direction);
+	snd_ice1712_gpio_set_mask(ice, ice->gpio.write_mask);
+	ucontrol->value.integer.value[0] = snd_ice1712_gpio_read(ice) & 0xffff;
+	up(&ice->gpio_mutex);
+	return 0;
+}
+
+static int pontis_gpio_data_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+{
+	ice1712_t *ice = snd_kcontrol_chip(kcontrol);
+	unsigned int val, nval;
+	int changed = 0;
+	down(&ice->gpio_mutex);
+	snd_ice1712_gpio_set_dir(ice, ice->gpio.direction);
+	snd_ice1712_gpio_set_mask(ice, ice->gpio.write_mask);
+	val = snd_ice1712_gpio_read(ice) & 0xffff;
+	nval = ucontrol->value.integer.value[0] & 0xffff;
+	if (val != nval) {
+		snd_ice1712_gpio_write(ice, nval);
+		changed = 1;
+	}
+	up(&ice->gpio_mutex);
+	return changed;
+}
+
+/*
+ * mixers
+ */
+
+static snd_kcontrol_new_t pontis_controls[] __devinitdata = {
+	{
+		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+		.name = "PCM Playback Volume",
+		.info = wm_dac_vol_info,
+		.get = wm_dac_vol_get,
+		.put = wm_dac_vol_put,
+	},
+	{
+		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+		.name = "Capture Volume",
+		.info = wm_adc_vol_info,
+		.get = wm_adc_vol_get,
+		.put = wm_adc_vol_put,
+	},
+	{
+		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+		.name = "CD Capture Switch",
+		.info = wm_adc_mux_info,
+		.get = wm_adc_mux_get,
+		.put = wm_adc_mux_put,
+		.private_value = 0,
+	},
+	{
+		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+		.name = "Line Capture Switch",
+		.info = wm_adc_mux_info,
+		.get = wm_adc_mux_get,
+		.put = wm_adc_mux_put,
+		.private_value = 1,
+	},
+	{
+		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+		.name = "Analog Bypass Switch",
+		.info = wm_bypass_info,
+		.get = wm_bypass_get,
+		.put = wm_bypass_put,
+	},
+	{
+		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+		.name = "Swap Output Channels",
+		.info = wm_chswap_info,
+		.get = wm_chswap_get,
+		.put = wm_chswap_put,
+	},
+	{
+		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+		.name = "IEC958 Input Source",
+		.info = cs_source_info,
+		.get = cs_source_get,
+		.put = cs_source_put,
+	},
+	/* FIXME: which interface? */
+	{
+		.iface = SNDRV_CTL_ELEM_IFACE_CARD,
+		.name = "GPIO Mask",
+		.info = pontis_gpio_mask_info,
+		.get = pontis_gpio_mask_get,
+		.put = pontis_gpio_mask_put,
+	},
+	{
+		.iface = SNDRV_CTL_ELEM_IFACE_CARD,
+		.name = "GPIO Direction",
+		.info = pontis_gpio_mask_info,
+		.get = pontis_gpio_dir_get,
+		.put = pontis_gpio_dir_put,
+	},
+	{
+		.iface = SNDRV_CTL_ELEM_IFACE_CARD,
+		.name = "GPIO Data",
+		.info = pontis_gpio_mask_info,
+		.get = pontis_gpio_data_get,
+		.put = pontis_gpio_data_put,
+	},
+};
+
+
+/*
+ * WM codec registers
+ */
+static void wm_proc_regs_write(snd_info_entry_t *entry, snd_info_buffer_t *buffer)
+{
+	ice1712_t *ice = (ice1712_t *)entry->private_data;
+	char line[64];
+	unsigned int reg, val;
+	down(&ice->gpio_mutex);
+	while (!snd_info_get_line(buffer, line, sizeof(line))) {
+		if (sscanf(line, "%x %x", &reg, &val) != 2)
+			continue;
+		if (reg <= 0x17 && val <= 0xffff)
+			wm_put(ice, reg, val);
+	}
+	up(&ice->gpio_mutex);
+}
+
+static void wm_proc_regs_read(snd_info_entry_t *entry, snd_info_buffer_t *buffer)
+{
+	ice1712_t *ice = (ice1712_t *)entry->private_data;
+	int reg, val;
+
+	down(&ice->gpio_mutex);
+	for (reg = 0; reg <= 0x17; reg++) {
+		val = wm_get(ice, reg);
+		snd_iprintf(buffer, "%02x = %04x\n", reg, val);
+	}
+	up(&ice->gpio_mutex);
+}
+
+static void wm_proc_init(ice1712_t *ice)
+{
+	snd_info_entry_t *entry;
+	if (! snd_card_proc_new(ice->card, "wm_codec", &entry)) {
+		snd_info_set_text_ops(entry, ice, 1024, wm_proc_regs_read);
+		entry->mode |= S_IWUSR;
+		entry->c.text.write_size = 1024;
+		entry->c.text.write = wm_proc_regs_write;
+	}
+}
+
+static void cs_proc_regs_read(snd_info_entry_t *entry, snd_info_buffer_t *buffer)
+{
+	ice1712_t *ice = (ice1712_t *)entry->private_data;
+	int reg, val;
+
+	down(&ice->gpio_mutex);
+	for (reg = 0; reg <= 0x26; reg++) {
+		val = spi_read(ice, CS_DEV, reg);
+		snd_iprintf(buffer, "%02x = %02x\n", reg, val);
+	}
+	val = spi_read(ice, CS_DEV, 0x7f);
+	snd_iprintf(buffer, "%02x = %02x\n", 0x7f, val);
+	up(&ice->gpio_mutex);
+}
+
+static void cs_proc_init(ice1712_t *ice)
+{
+	snd_info_entry_t *entry;
+	if (! snd_card_proc_new(ice->card, "cs_codec", &entry)) {
+		snd_info_set_text_ops(entry, ice, 1024, cs_proc_regs_read);
+	}
+}
+
+
+static int __devinit pontis_add_controls(ice1712_t *ice)
+{
+	unsigned int i;
+	int err;
+
+	for (i = 0; i < ARRAY_SIZE(pontis_controls); i++) {
+		err = snd_ctl_add(ice->card, snd_ctl_new1(&pontis_controls[i], ice));
+		if (err < 0)
+			return err;
+	}
+
+	wm_proc_init(ice);
+	cs_proc_init(ice);
+
+	return 0;
+}
+
+
+/*
+ * initialize the chip
+ */
+static int __devinit pontis_init(ice1712_t *ice)
+{
+	static unsigned short wm_inits[] = {
+		/* These come first to reduce init pop noise */
+		WM_ADC_MUX,	0x00c0,	/* ADC mute */
+		WM_DAC_MUTE,	0x0001,	/* DAC softmute */
+		WM_DAC_CTRL1,	0x0000,	/* DAC mute */
+
+		WM_POWERDOWN,	0x0008,	/* All power-up except HP */
+		WM_RESET,	0x0000,	/* reset */
+	};
+	static unsigned short wm_inits2[] = {
+		WM_MASTER_CTRL,	0x0022,	/* 256fs, slave mode */
+		WM_DAC_INT,	0x0022,	/* I2S, normal polarity, 24bit */
+		WM_ADC_INT,	0x0022,	/* I2S, normal polarity, 24bit */
+		WM_DAC_CTRL1,	0x0090,	/* DAC L/R */
+		WM_OUT_MUX,	0x0001,	/* OUT DAC */
+		WM_HP_ATTEN_L,	0x0179,	/* HP 0dB */
+		WM_HP_ATTEN_R,	0x0179,	/* HP 0dB */
+		WM_DAC_ATTEN_L,	0x0000,	/* DAC 0dB */
+		WM_DAC_ATTEN_L,	0x0100,	/* DAC 0dB */
+		WM_DAC_ATTEN_R,	0x0000,	/* DAC 0dB */
+		WM_DAC_ATTEN_R,	0x0100,	/* DAC 0dB */
+		// WM_DAC_MASTER,	0x0100,	/* DAC master muted */
+		WM_PHASE_SWAP,	0x0000,	/* phase normal */
+		WM_DAC_CTRL2,	0x0000,	/* no deemphasis, no ZFLG */
+		WM_ADC_ATTEN_L,	0x0000,	/* ADC muted */
+		WM_ADC_ATTEN_R,	0x0000,	/* ADC muted */
+#if 0
+		WM_ALC_CTRL1,	0x007b,	/* */
+		WM_ALC_CTRL2,	0x0000,	/* */
+		WM_ALC_CTRL3,	0x0000,	/* */
+		WM_NOISE_GATE,	0x0000,	/* */
+#endif
+		WM_DAC_MUTE,	0x0000,	/* DAC unmute */
+		WM_ADC_MUX,	0x0003,	/* ADC unmute, both CD/Line On */
+	};
+	static unsigned char cs_inits[] = {
+		0x04,	0x80,	/* RUN, RXP0 */
+		0x05,	0x05,	/* slave, 24bit */
+		0x01,	0x00,
+		0x02,	0x00,
+		0x03,	0x00,
+	};
+	unsigned int i;
+
+	ice->vt1720 = 1;
+	ice->num_total_dacs = 2;
+	ice->num_total_adcs = 2;
+
+	/* to remeber the register values */
+	ice->akm = kcalloc(1, sizeof(akm4xxx_t), GFP_KERNEL);
+	if (! ice->akm)
+		return -ENOMEM;
+	ice->akm_codecs = 1;
+
+	/* HACK - use this as the SPDIF source.
+	 * don't call snd_ice1712_gpio_get/put(), otherwise it's overwritten
+	 */
+	ice->gpio.saved[0] = 0;
+
+	/* initialize WM8776 codec */
+	for (i = 0; i < ARRAY_SIZE(wm_inits); i += 2)
+		wm_put(ice, wm_inits[i], wm_inits[i+1]);
+	set_current_state(TASK_UNINTERRUPTIBLE);
+	schedule_timeout(1);
+	for (i = 0; i < ARRAY_SIZE(wm_inits2); i += 2)
+		wm_put(ice, wm_inits2[i], wm_inits2[i+1]);
+
+	/* initialize CS8416 codec */
+	/* assert PRST#; MT05 bit 7 */
+	outb(inb(ICEMT1724(ice, AC97_CMD)) | 0x80, ICEMT1724(ice, AC97_CMD));
+	mdelay(5);
+	/* deassert PRST# */
+	outb(inb(ICEMT1724(ice, AC97_CMD)) & ~0x80, ICEMT1724(ice, AC97_CMD));
+
+	for (i = 0; i < ARRAY_SIZE(cs_inits); i += 2)
+		spi_write(ice, CS_DEV, cs_inits[i], cs_inits[i+1]);
+
+	return 0;
+}
+
+
+/*
+ * Pontis boards don't provide the EEPROM data at all.
+ * hence the driver needs to sets up it properly.
+ */
+
+static unsigned char pontis_eeprom[] __devinitdata = {
+	0x08,	/* SYSCONF: clock 256, mpu401, spdif-in/ADC, 1DAC */
+	0x80,	/* ACLINK: I2S */
+	0xf8,	/* I2S: vol, 96k, 24bit, 192k */
+	0xc3,	/* SPDIF: out-en, out-int, spdif-in */
+	0x07,	/* GPIO_DIR */
+	0x00,	/* GPIO_DIR1 */
+	0x00,	/* GPIO_DIR2 (ignored) */
+	0x0f,	/* GPIO_MASK (4-7 reserved for CS8416) */
+	0xff,	/* GPIO_MASK1 */
+	0x00,	/* GPIO_MASK2 (ignored) */
+	0x06,	/* GPIO_STATE (0-low, 1-high, 2-high) */
+	0x00,	/* GPIO_STATE1 */
+	0x00,	/* GPIO_STATE2 (ignored) */
+};
+
+/* entry point */
+struct snd_ice1712_card_info snd_vt1720_pontis_cards[] __devinitdata = {
+	{
+		.subvendor = VT1720_SUBDEVICE_PONTIS_MS300,
+		.name = "Pontis MS300",
+		.model = "ms300",
+		.chip_init = pontis_init,
+		.build_controls = pontis_add_controls,
+		.eeprom_size = sizeof(pontis_eeprom),
+		.eeprom_data = pontis_eeprom,
+	},
+	{ } /* terminator */
+};
diff -Nru a/sound/pci/ice1712/pontis.h b/sound/pci/ice1712/pontis.h
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/sound/pci/ice1712/pontis.h	2004-10-18 14:57:22 -07:00
@@ -0,0 +1,33 @@
+#ifndef __SOUND_PONTIS_H
+#define __SOUND_PONTIS_H
+
+/*
+ *   ALSA driver for VIA VT1724 (Envy24HT)
+ *
+ *   Lowlevel functions for Pontis MS300 boards
+ *
+ *	Copyright (c) 2004 Takashi Iwai <tiwai@suse.de>
+ *
+ *   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
+ *
+ */      
+
+#define PONTIS_DEVICE_DESC 	       "{Pontis,MS300},"
+
+#define VT1720_SUBDEVICE_PONTIS_MS300	0x00020002	/* a dummy id for MS300 */
+
+extern struct snd_ice1712_card_info  snd_vt1720_pontis_cards[];
+
+#endif /* __SOUND_PONTIS_H */
diff -Nru a/sound/pci/ice1712/revo.c b/sound/pci/ice1712/revo.c
--- a/sound/pci/ice1712/revo.c	2004-10-18 14:56:33 -07:00
+++ b/sound/pci/ice1712/revo.c	2004-10-18 14:56:33 -07:00
@@ -128,7 +128,7 @@
 	switch (ice->eeprom.subvendor) {
 	case VT1724_SUBDEVICE_REVOLUTION71:
 		ice->num_total_dacs = 8;
-		ice->num_total_adcs = 4;
+		ice->num_total_adcs = 2;
 		break;
 	default:
 		snd_BUG();
@@ -136,7 +136,7 @@
 	}
 
 	/* second stage of initialization, analog parts and others */
-	ak = ice->akm = snd_kcalloc(sizeof(akm4xxx_t) * 2, GFP_KERNEL);
+	ak = ice->akm = kcalloc(2, sizeof(akm4xxx_t), GFP_KERNEL);
 	if (! ak)
 		return -ENOMEM;
 	ice->akm_codecs = 2;
diff -Nru a/sound/pci/ice1712/vt1720_mobo.c b/sound/pci/ice1712/vt1720_mobo.c
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/sound/pci/ice1712/vt1720_mobo.c	2004-10-18 14:57:21 -07:00
@@ -0,0 +1,106 @@
+/*
+ *   ALSA driver for VT1720/VT1724 (Envy24PT/Envy24HT)
+ *
+ *   Lowlevel functions for VT1720-based motherboards
+ *
+ *	Copyright (c) 2004 Takashi Iwai <tiwai@suse.de>
+ *
+ *   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
+ *
+ */      
+
+#include <sound/driver.h>
+#include <asm/io.h>
+#include <linux/delay.h>
+#include <linux/interrupt.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <sound/core.h>
+
+#include "ice1712.h"
+#include "vt1720_mobo.h"
+
+
+static int __devinit k8x800_init(ice1712_t *ice)
+{
+	ice->vt1720 = 1;
+
+	/* VT1616 codec */
+	ice->num_total_dacs = 6;
+	ice->num_total_adcs = 2;
+
+	/* WM8728 codec */
+	/* FIXME: TODO */
+
+	return 0;
+}
+
+static int __devinit k8x800_add_controls(ice1712_t *ice)
+{
+	/* FIXME: needs some quirks for VT1616? */
+	return 0;
+}
+
+/* EEPROM image */
+
+static unsigned char k8x800_eeprom[] __devinitdata = {
+	0x01,	/* SYSCONF: clock 256, 1ADC, 2DACs */
+	0x02,	/* ACLINK: ACLINK, packed */
+	0x00,	/* I2S: - */
+	0x00,	/* SPDIF: - */
+	0xff,	/* GPIO_DIR */
+	0xff,	/* GPIO_DIR1 */
+	0x00,	/* - */
+	0xff,	/* GPIO_MASK */
+	0xff,	/* GPIO_MASK1 */
+	0x00,	/* - */
+	0x00,	/* GPIO_STATE */
+	0x00,	/* GPIO_STATE1 */
+	0x00,	/* - */
+};
+
+
+/* entry point */
+struct snd_ice1712_card_info snd_vt1720_mobo_cards[] __devinitdata = {
+	{
+		.subvendor = VT1720_SUBDEVICE_K8X800,
+		.name = "Albatron K8X800 Pro II",
+		.model = "k8x800",
+		.chip_init = k8x800_init,
+		.build_controls = k8x800_add_controls,
+		.eeprom_size = sizeof(k8x800_eeprom),
+		.eeprom_data = k8x800_eeprom,
+	},
+	{
+		.subvendor = VT1720_SUBDEVICE_ZNF3_150,
+		.name = "Chaintech ZNF3-150",
+		/* identical with k8x800 */
+		.chip_init = k8x800_init,
+		.build_controls = k8x800_add_controls,
+		.eeprom_size = sizeof(k8x800_eeprom),
+		.eeprom_data = k8x800_eeprom,
+	},
+	{
+		.subvendor = VT1720_SUBDEVICE_ZNF3_250,
+		.name = "Chaintech ZNF3-250",
+		/* identical with k8x800 */
+		.chip_init = k8x800_init,
+		.build_controls = k8x800_add_controls,
+		.eeprom_size = sizeof(k8x800_eeprom),
+		.eeprom_data = k8x800_eeprom,
+	},
+	{ } /* terminator */
+};
+
diff -Nru a/sound/pci/ice1712/vt1720_mobo.h b/sound/pci/ice1712/vt1720_mobo.h
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/sound/pci/ice1712/vt1720_mobo.h	2004-10-18 14:57:23 -07:00
@@ -0,0 +1,37 @@
+#ifndef __SOUND_VT1720_MOBO_H
+#define __SOUND_VT1720_MOBO_H
+
+/*
+ *   ALSA driver for VT1720/VT1724 (Envy24PT/Envy24HT)
+ *
+ *   Lowlevel functions for VT1720-based motherboards
+ *
+ *	Copyright (c) 2004 Takashi Iwai <tiwai@suse.de>
+ *
+ *   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
+ *
+ */      
+
+#define VT1720_MOBO_DEVICE_DESC        "{Albatron,K8X800 Pro II},"\
+				       "{Chaintech,ZNF3-150},"\
+				       "{Chaintech,ZNF3-250},"
+
+#define VT1720_SUBDEVICE_K8X800		0xf217052c
+#define VT1720_SUBDEVICE_ZNF3_150	0x0f2741f6
+#define VT1720_SUBDEVICE_ZNF3_250	0x0f2745f6
+
+extern struct snd_ice1712_card_info  snd_vt1720_mobo_cards[];
+
+#endif /* __SOUND_VT1720_MOBO_H */
diff -Nru a/sound/pci/intel8x0.c b/sound/pci/intel8x0.c
--- a/sound/pci/intel8x0.c	2004-10-18 14:56:33 -07:00
+++ b/sound/pci/intel8x0.c	2004-10-18 14:56:33 -07:00
@@ -48,8 +48,7 @@
 MODULE_AUTHOR("Jaroslav Kysela <perex@suse.cz>");
 MODULE_DESCRIPTION("Intel 82801AA,82901AB,i810,i820,i830,i840,i845,MX440; SiS 7012; Ali 5455");
 MODULE_LICENSE("GPL");
-MODULE_CLASSES("{sound}");
-MODULE_DEVICES("{{Intel,82801AA-ICH},"
+MODULE_SUPPORTED_DEVICE("{{Intel,82801AA-ICH},"
 		"{Intel,82901AB-ICH0},"
 		"{Intel,82801BA-ICH2},"
 		"{Intel,82801CA-ICH3},"
@@ -75,6 +74,7 @@
 static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP;	/* Enable this card */
 static int ac97_clock[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 0};
 static int ac97_quirk[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = AC97_TUNE_DEFAULT};
+static int buggy_irq[SNDRV_CARDS];
 #ifdef SUPPORT_JOYSTICK
 static int joystick[SNDRV_CARDS];
 #endif
@@ -85,28 +85,23 @@
 
 module_param_array(index, int, boot_devs, 0444);
 MODULE_PARM_DESC(index, "Index value for Intel i8x0 soundcard.");
-MODULE_PARM_SYNTAX(index, SNDRV_INDEX_DESC);
 module_param_array(id, charp, boot_devs, 0444);
 MODULE_PARM_DESC(id, "ID string for Intel i8x0 soundcard.");
-MODULE_PARM_SYNTAX(id, SNDRV_ID_DESC);
 module_param_array(enable, bool, boot_devs, 0444);
 MODULE_PARM_DESC(enable, "Enable Intel i8x0 soundcard.");
-MODULE_PARM_SYNTAX(enable, SNDRV_ENABLE_DESC);
 module_param_array(ac97_clock, int, boot_devs, 0444);
 MODULE_PARM_DESC(ac97_clock, "AC'97 codec clock (0 = auto-detect).");
-MODULE_PARM_SYNTAX(ac97_clock, SNDRV_ENABLED ",default:0");
 module_param_array(ac97_quirk, int, boot_devs, 0444);
 MODULE_PARM_DESC(ac97_quirk, "AC'97 workaround for strange hardware.");
-MODULE_PARM_SYNTAX(ac97_quirk, SNDRV_ENABLED ",allows:{{-1,4}},dialog:list,default:-1");
+module_param_array(buggy_irq, bool, boot_devs, 0444);
+MODULE_PARM_DESC(buggy_irq, "Enable workaround for buggy interrupts on some motherboards.");
 #ifdef SUPPORT_JOYSTICK
 module_param_array(joystick, bool, boot_devs, 0444);
 MODULE_PARM_DESC(joystick, "Enable joystick for Intel i8x0 soundcard.");
-MODULE_PARM_SYNTAX(joystick, SNDRV_ENABLED "," SNDRV_BOOLEAN_FALSE_DESC);
 #endif
 #ifdef SUPPORT_MIDI
 module_param_array(mpu_port, int, boot_devs, 0444);
 MODULE_PARM_DESC(mpu_port, "MPU401 port # for Intel i8x0 driver.");
-MODULE_PARM_SYNTAX(mpu_port, SNDRV_ENABLED ",allows:{{0},{0x330},{0x300}},dialog:list");
 #endif
 
 /*
@@ -146,9 +141,15 @@
 #ifndef PCI_DEVICE_ID_NVIDIA_MCP_AUDIO
 #define PCI_DEVICE_ID_NVIDIA_MCP_AUDIO	0x01b1
 #endif
+#ifndef PCI_DEVICE_ID_NVIDIA_CK804_AUDIO
+#define PCI_DEVICE_ID_NVIDIA_CK804_AUDIO 0x0059
+#endif
 #ifndef PCI_DEVICE_ID_NVIDIA_MCP2_AUDIO
 #define PCI_DEVICE_ID_NVIDIA_MCP2_AUDIO	0x006a
 #endif
+#ifndef PCI_DEVICE_ID_NVIDIA_CK8_AUDIO
+#define PCI_DEVICE_ID_NVIDIA_CK8_AUDIO	0x008a
+#endif
 #ifndef PCI_DEVICE_ID_NVIDIA_MCP3_AUDIO
 #define PCI_DEVICE_ID_NVIDIA_MCP3_AUDIO	0x00da
 #endif
@@ -397,25 +398,18 @@
 } ichdev_t;
 
 typedef struct _snd_intel8x0 intel8x0_t;
-#define chip_t intel8x0_t
 
 struct _snd_intel8x0 {
 	unsigned int device_type;
-	char ac97_name[32];
-	char ctrl_name[32];
 
 	int irq;
 
 	unsigned int mmio;
 	unsigned long addr;
-	unsigned long remap_addr;
-	struct resource *res;
+	void __iomem * remap_addr;
 	unsigned int bm_mmio;
 	unsigned long bmaddr;
-	unsigned long remap_bmaddr;
-	struct resource *res_bm;
-
-	struct snd_dma_device dma_dev;
+	void __iomem * remap_bmaddr;
 
 	struct pci_dev *pci;
 	snd_card_t *card;
@@ -424,12 +418,13 @@
 	snd_pcm_t *pcm[6];
 	ichdev_t ichd[6];
 
-	int multi4: 1,
-	    multi6: 1,
-	    smp20bit: 1;
-	int in_ac97_init: 1,
-	    in_sdin_init: 1;
-	int fix_nocache: 1; /* workaround for 440MX */
+	unsigned multi4: 1,
+		 multi6: 1,
+		 smp20bit: 1;
+	unsigned in_ac97_init: 1,
+		 in_sdin_init: 1;
+	unsigned fix_nocache: 1; /* workaround for 440MX */
+	unsigned buggy_irq: 1; /* workaround for buggy mobos */
 
 	ac97_bus_t *ac97_bus;
 	ac97_t *ac97[3];
@@ -444,10 +439,6 @@
 	struct snd_dma_buffer bdbars;
 	u32 int_sta_reg;		/* interrupt status register */
 	u32 int_sta_mask;		/* interrupt status mask */
-
-#ifdef CONFIG_PM
-	u32 pci_state[64 / sizeof(u32)];
-#endif
 };
 
 static struct pci_device_id snd_intel8x0_ids[] = {
@@ -462,7 +453,10 @@
 	{ 0x8086, 0x7195, PCI_ANY_ID, PCI_ANY_ID, 0, 0, DEVICE_INTEL },	/* 440MX */
 	{ 0x1039, 0x7012, PCI_ANY_ID, PCI_ANY_ID, 0, 0, DEVICE_SIS },	/* SI7012 */
 	{ 0x10de, 0x01b1, PCI_ANY_ID, PCI_ANY_ID, 0, 0, DEVICE_NFORCE },	/* NFORCE */
+	{ 0x10de, 0x003a, PCI_ANY_ID, PCI_ANY_ID, 0, 0, DEVICE_NFORCE },	/* MCP04 */
 	{ 0x10de, 0x006a, PCI_ANY_ID, PCI_ANY_ID, 0, 0, DEVICE_NFORCE },	/* NFORCE2 */
+	{ 0x10de, 0x0059, PCI_ANY_ID, PCI_ANY_ID, 0, 0, DEVICE_NFORCE },	/* CK804 */
+	{ 0x10de, 0x008a, PCI_ANY_ID, PCI_ANY_ID, 0, 0, DEVICE_NFORCE },	/* CK8 */
 	{ 0x10de, 0x00da, PCI_ANY_ID, PCI_ANY_ID, 0, 0, DEVICE_NFORCE },	/* NFORCE3 */
 	{ 0x10de, 0x00ea, PCI_ANY_ID, PCI_ANY_ID, 0, 0, DEVICE_NFORCE },	/* CK8S */
 	{ 0x1022, 0x746d, PCI_ANY_ID, PCI_ANY_ID, 0, 0, DEVICE_INTEL },	/* AMD8111 */
@@ -605,7 +599,7 @@
 				     unsigned short reg,
 				     unsigned short val)
 {
-	intel8x0_t *chip = snd_magic_cast(intel8x0_t, ac97->private_data, return);
+	intel8x0_t *chip = ac97->private_data;
 	
 	spin_lock(&chip->ac97_lock);
 	if (snd_intel8x0_codec_semaphore(chip, ac97->num) < 0) {
@@ -619,7 +613,7 @@
 static unsigned short snd_intel8x0_codec_read(ac97_t *ac97,
 					      unsigned short reg)
 {
-	intel8x0_t *chip = snd_magic_cast(intel8x0_t, ac97->private_data, return ~0);
+	intel8x0_t *chip = ac97->private_data;
 	unsigned short res;
 	unsigned int tmp;
 
@@ -642,6 +636,21 @@
 	return res;
 }
 
+static void snd_intel8x0_codec_read_test(intel8x0_t *chip, unsigned int codec)
+{
+	unsigned int tmp;
+
+	spin_lock(&chip->ac97_lock);
+	if (snd_intel8x0_codec_semaphore(chip, codec) >= 0) {
+		iagetword(chip, codec * 0x80);
+		if ((tmp = igetdword(chip, ICHREG(GLOB_STA))) & ICH_RCS) {
+			/* reset RCS and preserve other R/WC bits */
+			iputdword(chip, ICHREG(GLOB_STA), tmp & ~(ICH_SRI|ICH_PRI|ICH_TRI|ICH_GSCI));
+		}
+	}
+	spin_unlock(&chip->ac97_lock);
+}
+
 /*
  * access to AC97 for Ali5455
  */
@@ -669,7 +678,7 @@
 
 static unsigned short snd_intel8x0_ali_codec_read(ac97_t *ac97, unsigned short reg)
 {
-	intel8x0_t *chip = snd_magic_cast(intel8x0_t, ac97->private_data, return ~0);
+	intel8x0_t *chip = ac97->private_data;
 	unsigned short data = 0xffff;
 
 	spin_lock(&chip->ac97_lock);
@@ -689,7 +698,7 @@
 
 static void snd_intel8x0_ali_codec_write(ac97_t *ac97, unsigned short reg, unsigned short val)
 {
-	intel8x0_t *chip = snd_magic_cast(intel8x0_t, ac97->private_data, return);
+	intel8x0_t *chip = ac97->private_data;
 
 	spin_lock(&chip->ac97_lock);
 	if (snd_intel8x0_ali_codec_semaphore(chip)) {
@@ -778,6 +787,7 @@
 	int status, civ, i, step;
 	int ack = 0;
 
+	spin_lock(&chip->reg_lock);
 	status = igetbyte(chip, port + ichdev->roff_sr);
 	civ = igetbyte(chip, port + ICH_REG_OFF_CIV);
 	if (!(status & ICH_BCIS)) {
@@ -811,10 +821,9 @@
 			ack = 1;
 		}
 	}
+	spin_unlock(&chip->reg_lock);
 	if (ack && ichdev->substream) {
-		spin_unlock(&chip->reg_lock);
 		snd_pcm_period_elapsed(ichdev->substream);
-		spin_lock(&chip->reg_lock);
 	}
 	iputbyte(chip, port + ichdev->roff_sr,
 		 status & (ICH_FIFOE | ICH_BCIS | ICH_LVBCI));
@@ -822,24 +831,22 @@
 
 static irqreturn_t snd_intel8x0_interrupt(int irq, void *dev_id, struct pt_regs *regs)
 {
-	intel8x0_t *chip = snd_magic_cast(intel8x0_t, dev_id, return IRQ_NONE);
+	intel8x0_t *chip = dev_id;
 	ichdev_t *ichdev;
 	unsigned int status;
 	unsigned int i;
 
-	spin_lock(&chip->reg_lock);
 	status = igetdword(chip, chip->int_sta_reg);
+	if (status == 0xffffffff)	/* we are not yet resumed */
+		return IRQ_NONE;
+
 	if ((status & chip->int_sta_mask) == 0) {
 		if (status) {
 			/* ack */
 			iputdword(chip, chip->int_sta_reg, status);
-			/* some Nforce[2] boards have problems when
-			   IRQ_NONE is returned here.
-			*/
-			if (chip->device_type != DEVICE_NFORCE)
+			if (! chip->buggy_irq)
 				status = 0;
 		}
-		spin_unlock(&chip->reg_lock);
 		return IRQ_RETVAL(status);
 	}
 
@@ -851,7 +858,6 @@
 
 	/* ack them */
 	iputdword(chip, chip->int_sta_reg, status & chip->int_sta_mask);
-	spin_unlock(&chip->reg_lock);
 	
 	return IRQ_HANDLED;
 }
@@ -1021,8 +1027,10 @@
 			/* reset to 2ch once to keep the 6 channel data in alignment,
 			 * to start from Front Left always
 			 */
-			iputdword(chip, ICHREG(GLOB_CNT), (cnt & 0xcfffff));
-			mdelay(50); /* grrr... */
+			if (cnt & ICH_PCM_246_MASK) {
+				iputdword(chip, ICHREG(GLOB_CNT), cnt & ~ICH_PCM_246_MASK);
+				msleep(50); /* grrr... */
+			}
 		} else if (chip->device_type == DEVICE_INTEL_ICH4) {
 			if (sample_bits > 16)
 				cnt |= ICH_PCM_20BIT;
@@ -1041,16 +1049,16 @@
 	ichdev->physbuf = runtime->dma_addr;
 	ichdev->size = snd_pcm_lib_buffer_bytes(substream);
 	ichdev->fragsize = snd_pcm_lib_period_bytes(substream);
+	spin_lock_irq(&chip->reg_lock);
 	if (ichdev->ichd == ICHD_PCMOUT) {
-		spin_lock(&chip->reg_lock);
 		snd_intel8x0_setup_pcm_out(chip, runtime->channels,
 					   runtime->sample_bits);
-		spin_unlock(&chip->reg_lock);
 		if (chip->device_type == DEVICE_INTEL_ICH4) {
 			ichdev->pos_shift = (runtime->sample_bits > 16) ? 2 : 1;
 		}
 	}
 	snd_intel8x0_setup_periods(chip, ichdev);
+	spin_unlock_irq(&chip->reg_lock);
 	return 0;
 }
 
@@ -1058,17 +1066,25 @@
 {
 	intel8x0_t *chip = snd_pcm_substream_chip(substream);
 	ichdev_t *ichdev = get_ichdev(substream);
-	unsigned long flags;
 	size_t ptr1, ptr;
+	int civ, timeout = 10;
+	unsigned int position;
 
-	ptr1 = igetword(chip, ichdev->reg_offset + ichdev->roff_picb) << ichdev->pos_shift;
-	if (ptr1 != 0)
-		ptr = ichdev->fragsize1 - ptr1;
-	else
-		ptr = 0;
-	spin_lock_irqsave(&chip->reg_lock, flags);
-	ptr += ichdev->position;
-	spin_unlock_irqrestore(&chip->reg_lock, flags);
+	spin_lock(&chip->reg_lock);
+	do {
+		civ = igetbyte(chip, ichdev->reg_offset + ICH_REG_OFF_CIV);
+		ptr1 = igetword(chip, ichdev->reg_offset + ichdev->roff_picb);
+		position = ichdev->position;
+		if (ptr1 == 0)
+			udelay(1);
+		if (civ == igetbyte(chip, ichdev->reg_offset + ICH_REG_OFF_CIV) &&
+		    ptr1 == igetword(chip, ichdev->reg_offset + ichdev->roff_picb))
+			break;
+	} while (timeout--);
+	ptr1 <<= ichdev->pos_shift;
+	ptr = ichdev->fragsize1 - ptr1;
+	ptr += position;
+	spin_unlock(&chip->reg_lock);
 	if (ptr >= ichdev->size)
 		return 0;
 	return bytes_to_frames(substream->runtime, ptr);
@@ -1099,10 +1115,8 @@
 	2, 4,
 };
 
-#define CHANNELS4 sizeof(channels4) / sizeof(channels4[0])
-
 static snd_pcm_hw_constraint_list_t hw_constraints_channels4 = {
-	.count = CHANNELS4,
+	.count = ARRAY_SIZE(channels4),
 	.list = channels4,
 	.mask = 0,
 };
@@ -1111,10 +1125,8 @@
 	2, 4, 6,
 };
 
-#define CHANNELS6 sizeof(channels6) / sizeof(channels6[0])
-
 static snd_pcm_hw_constraint_list_t hw_constraints_channels6 = {
-	.count = CHANNELS6,
+	.count = ARRAY_SIZE(channels6),
 	.list = channels6,
 	.mask = 0,
 };
@@ -1156,8 +1168,10 @@
 		runtime->hw.channels_max = 4;
 		snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS, &hw_constraints_channels4);
 	}
-	if (chip->smp20bit)
+	if (chip->smp20bit) {
 		runtime->hw.formats |= SNDRV_PCM_FMTBIT_S32_LE;
+		snd_pcm_hw_constraint_msbits(runtime, 0, 32, 20);
+	}
 	return 0;
 }
 
@@ -1249,14 +1263,14 @@
 static int snd_intel8x0_ali_ac97spdifout_open(snd_pcm_substream_t * substream)
 {
 	intel8x0_t *chip = snd_pcm_substream_chip(substream);
-	unsigned long flags;
 	unsigned int val;
 
-	spin_lock_irqsave(&chip->reg_lock, flags);
+	spin_lock_irq(&chip->reg_lock);
 	val = igetdword(chip, ICHREG(ALI_INTERFACECR));
 	val |= ICH_ALI_IF_AC97SP;
+	iputdword(chip, ICHREG(ALI_INTERFACECR), val);
 	/* also needs to set ALI_SC_CODEC_SPDF correctly */
-	spin_unlock_irqrestore(&chip->reg_lock, flags);
+	spin_unlock_irq(&chip->reg_lock);
 
 	return snd_intel8x0_pcm_open(substream, &chip->ichd[ALID_AC97SPDIFOUT]);
 }
@@ -1264,14 +1278,14 @@
 static int snd_intel8x0_ali_ac97spdifout_close(snd_pcm_substream_t * substream)
 {
 	intel8x0_t *chip = snd_pcm_substream_chip(substream);
-	unsigned long flags;
 	unsigned int val;
 
 	chip->ichd[ALID_AC97SPDIFOUT].substream = NULL;
-	spin_lock_irqsave(&chip->reg_lock, flags);
+	spin_lock_irq(&chip->reg_lock);
 	val = igetdword(chip, ICHREG(ALI_INTERFACECR));
 	val &= ~ICH_ALI_IF_AC97SP;
-	spin_unlock_irqrestore(&chip->reg_lock, flags);
+	iputdword(chip, ICHREG(ALI_INTERFACECR), val);
+	spin_unlock_irq(&chip->reg_lock);
 
 	return 0;
 }
@@ -1627,13 +1641,13 @@
 
 static void snd_intel8x0_mixer_free_ac97_bus(ac97_bus_t *bus)
 {
-	intel8x0_t *chip = snd_magic_cast(intel8x0_t, bus->private_data, return);
+	intel8x0_t *chip = bus->private_data;
 	chip->ac97_bus = NULL;
 }
 
 static void snd_intel8x0_mixer_free_ac97(ac97_t *ac97)
 {
-	intel8x0_t *chip = snd_magic_cast(intel8x0_t, ac97->private_data, return);
+	intel8x0_t *chip = ac97->private_data;
 	chip->ac97[ac97->num] = NULL;
 }
 
@@ -1726,12 +1740,30 @@
 		.name = "Dell Optiplex GX260",	/* AD1981A */
 		.type = AC97_TUNE_HP_ONLY
 	},
+	{
+		.vendor = 0x1028,
+		.device = 0x012d,
+		.name = "Dell Precision 450",	/* AD1981B*/
+		.type = AC97_TUNE_HP_ONLY
+	},
 	{	/* FIXME: which codec? */
 		.vendor = 0x103c,
 		.device = 0x00c3,
 		.name = "Hewlett-Packard onboard",
 		.type = AC97_TUNE_HP_ONLY
 	},
+	{
+		.vendor = 0x103c,
+		.device = 0x12f1,
+		.name = "HP xw8200",	/* AD1981B*/
+		.type = AC97_TUNE_HP_ONLY
+	},
+	{
+		.vendor = 0x103c,
+		.device = 0x3008,
+		.name = "HP xw4200",	/* AD1981B*/
+		.type = AC97_TUNE_HP_ONLY
+	},
  	{
 		.vendor = 0x1043,
 		.device = 0x80f3,
@@ -1802,6 +1834,12 @@
 	},
 	{
 		.vendor = 0x8086,
+		.device = 0x4d56,
+		.name = "Intel ICH/AD1885",
+		.type = AC97_TUNE_HP_ONLY
+	},
+	{
+		.vendor = 0x8086,
 		.device = 0x6000,
 		.mask = 0xfff0,
 		.name = "Intel ICH5/AD1985",
@@ -1828,12 +1866,21 @@
 
 static int __devinit snd_intel8x0_mixer(intel8x0_t *chip, int ac97_clock, int ac97_quirk)
 {
-	ac97_bus_t bus, *pbus;
-	ac97_t ac97, *x97;
+	ac97_bus_t *pbus;
+	ac97_template_t ac97;
 	int err;
 	unsigned int i, codecs;
 	unsigned int glob_sta = 0;
 	int spdif_idx = -1; /* disabled */
+	ac97_bus_ops_t *ops;
+	static ac97_bus_ops_t standard_bus_ops = {
+		.write = snd_intel8x0_codec_write,
+		.read = snd_intel8x0_codec_read,
+	};
+	static ac97_bus_ops_t ali_bus_ops = {
+		.write = snd_intel8x0_ali_codec_write,
+		.read = snd_intel8x0_ali_codec_read,
+	};
 
 	switch (chip->device_type) {
 	case DEVICE_NFORCE:
@@ -1849,13 +1896,6 @@
 	};
 
 	chip->in_ac97_init = 1;
-	memset(&bus, 0, sizeof(bus));
-	bus.private_data = chip;
-	bus.private_free = snd_intel8x0_mixer_free_ac97_bus;
-	if (ac97_clock >= 8000 && ac97_clock <= 48000)
-		bus.clock = ac97_clock;
-	else
-		bus.clock = 48000;
 	
 	memset(&ac97, 0, sizeof(ac97));
 	ac97.private_data = chip;
@@ -1863,8 +1903,7 @@
 	ac97.scaps = AC97_SCAP_SKIP_MODEM;
 	if (chip->device_type != DEVICE_ALI) {
 		glob_sta = igetdword(chip, ICHREG(GLOB_STA));
-		bus.write = snd_intel8x0_codec_write;
-		bus.read = snd_intel8x0_codec_read;
+		ops = &standard_bus_ops;
 		if (chip->device_type == DEVICE_INTEL_ICH4) {
 			codecs = 0;
 			if (glob_sta & ICH_PCR)
@@ -1875,19 +1914,15 @@
 				codecs++;
 			chip->in_sdin_init = 1;
 			for (i = 0; i < codecs; i++) {
-				ac97.num = i;
-				snd_intel8x0_codec_read(&ac97, 0);
+				snd_intel8x0_codec_read_test(chip, i);
 				chip->ac97_sdin[i] = igetbyte(chip, ICHREG(SDM)) & ICH_LDI_MASK;
 			}
-			ac97.num = 0;
 			chip->in_sdin_init = 0;
 		} else {
 			codecs = glob_sta & ICH_SCR ? 2 : 1;
 		}
-		bus.vra = 1;
 	} else {
-		bus.write = snd_intel8x0_ali_codec_write;
-		bus.read = snd_intel8x0_ali_codec_read;
+		ops = &ali_bus_ops;
 		codecs = 1;
 		/* detect the secondary codec */
 		for (i = 0; i < 100; i++) {
@@ -1899,23 +1934,28 @@
 			iputdword(chip, ICHREG(ALI_RTSR), reg | 0x40);
 			udelay(1);
 		}
-		/* FIXME: my test board doens't work well with VRA... */
-		bus.vra = 0;
 	}
-	if ((err = snd_ac97_bus(chip->card, &bus, &pbus)) < 0)
+	if ((err = snd_ac97_bus(chip->card, 0, ops, chip, &pbus)) < 0)
 		goto __err;
+	pbus->private_free = snd_intel8x0_mixer_free_ac97_bus;
+	pbus->shared_type = AC97_SHARED_TYPE_ICH;	/* shared with modem driver */
+	if (ac97_clock >= 8000 && ac97_clock <= 48000)
+		pbus->clock = ac97_clock;
+	/* FIXME: my test board doesn't work well with VRA... */
+	if (chip->device_type == DEVICE_ALI)
+		pbus->no_vra = 1;
 	chip->ac97_bus = pbus;
+
 	ac97.pci = chip->pci;
 	for (i = 0; i < codecs; i++) {
 		ac97.num = i;
-		if ((err = snd_ac97_mixer(pbus, &ac97, &x97)) < 0) {
+		if ((err = snd_ac97_mixer(pbus, &ac97, &chip->ac97[i])) < 0) {
 			if (err != -EACCES)
 				snd_printk(KERN_ERR "Unable to initialize codec #%d\n", i);
 			if (i == 0)
 				goto __err;
 			continue;
 		}
-		chip->ac97[i] = x97;
 	}
 	/* tune up the primary codec */
 	snd_ac97_tune_hardware(chip->ac97[0], ac97_quirks, ac97_quirk);
@@ -2179,26 +2219,19 @@
 	/* --- */
 	synchronize_irq(chip->irq);
       __hw_end:
+	if (chip->irq >= 0)
+		free_irq(chip->irq, (void *)chip);
 	if (chip->bdbars.area) {
 		if (chip->fix_nocache)
 			fill_nocache(chip->bdbars.area, chip->bdbars.bytes, 0);
-		snd_dma_free_pages(&chip->dma_dev, &chip->bdbars);
+		snd_dma_free_pages(&chip->bdbars);
 	}
 	if (chip->remap_addr)
-		iounmap((void *) chip->remap_addr);
+		iounmap(chip->remap_addr);
 	if (chip->remap_bmaddr)
-		iounmap((void *) chip->remap_bmaddr);
-	if (chip->res) {
-		release_resource(chip->res);
-		kfree_nocheck(chip->res);
-	}
-	if (chip->res_bm) {
-		release_resource(chip->res_bm);
-		kfree_nocheck(chip->res_bm);
-	}
-	if (chip->irq >= 0)
-		free_irq(chip->irq, (void *)chip);
-	snd_magic_kfree(chip);
+		iounmap(chip->remap_bmaddr);
+	pci_release_regions(chip->pci);
+	kfree(chip);
 	return 0;
 }
 
@@ -2208,7 +2241,7 @@
  */
 static int intel8x0_suspend(snd_card_t *card, unsigned int state)
 {
-	intel8x0_t *chip = snd_magic_cast(intel8x0_t, card->pm_private_data, return -EINVAL);
+	intel8x0_t *chip = card->pm_private_data;
 	int i;
 
 	for (i = 0; i < chip->pcm_devs; i++)
@@ -2216,17 +2249,15 @@
 	for (i = 0; i < 3; i++)
 		if (chip->ac97[i])
 			snd_ac97_suspend(chip->ac97[i]);
-	pci_save_state(chip->pci, chip->pci_state);
 	snd_power_change_state(card, SNDRV_CTL_POWER_D3hot);
 	return 0;
 }
 
 static int intel8x0_resume(snd_card_t *card, unsigned int state)
 {
-	intel8x0_t *chip = snd_magic_cast(intel8x0_t, card->pm_private_data, return -EINVAL);
+	intel8x0_t *chip = card->pm_private_data;
 	int i;
 
-	pci_restore_state(chip->pci, chip->pci_state);
 	pci_enable_device(chip->pci);
 	pci_set_master(chip->pci);
 	snd_intel8x0_chip_init(chip, 0);
@@ -2264,7 +2295,6 @@
 	ichdev_t *ichdev;
 	unsigned long port;
 	unsigned long pos, t;
-	unsigned long flags;
 	struct timeval start_time, stop_time;
 
 	if (chip->ac97_bus->clock != 48000)
@@ -2287,7 +2317,7 @@
 	}
 	snd_intel8x0_setup_periods(chip, ichdev);
 	port = ichdev->reg_offset;
-	spin_lock_irqsave(&chip->reg_lock, flags);
+	spin_lock_irq(&chip->reg_lock);
 	/* trigger */
 	if (chip->device_type != DEVICE_ALI)
 		iputbyte(chip, port + ICH_REG_OFF_CR, ICH_IOCE | ICH_STARTBM);
@@ -2296,7 +2326,7 @@
 		iputdword(chip, ICHREG(ALI_DMACR), 1 << ichdev->ali_slot);
 	}
 	do_gettimeofday(&start_time);
-	spin_unlock_irqrestore(&chip->reg_lock, flags);
+	spin_unlock_irq(&chip->reg_lock);
 #if 0
 	set_current_state(TASK_UNINTERRUPTIBLE);
 	schedule_timeout(HZ / 20);
@@ -2304,7 +2334,7 @@
 	/* FIXME: schedule() can take too long time and overlap the boundary.. */
 	mdelay(50);
 #endif
-	spin_lock_irqsave(&chip->reg_lock, flags);
+	spin_lock_irq(&chip->reg_lock);
 	/* check the position */
 	pos = ichdev->fragsize1;
 	pos -= igetword(chip, ichdev->reg_offset + ichdev->roff_picb) << ichdev->pos_shift;
@@ -2322,7 +2352,7 @@
 			;
 	}
 	iputbyte(chip, port + ICH_REG_OFF_CR, ICH_RESETREGS);
-	spin_unlock_irqrestore(&chip->reg_lock, flags);
+	spin_unlock_irq(&chip->reg_lock);
 
 	t = stop_time.tv_sec - start_time.tv_sec;
 	t *= 1000000;
@@ -2346,7 +2376,7 @@
 static void snd_intel8x0_proc_read(snd_info_entry_t * entry,
 				   snd_info_buffer_t * buffer)
 {
-	intel8x0_t *chip = snd_magic_cast(intel8x0_t, entry->private_data, return);
+	intel8x0_t *chip = entry->private_data;
 	unsigned int tmp;
 
 	snd_iprintf(buffer, "Intel8x0\n\n");
@@ -2379,7 +2409,7 @@
 
 static int snd_intel8x0_dev_free(snd_device_t *device)
 {
-	intel8x0_t *chip = snd_magic_cast(intel8x0_t, device->device_data, return -ENXIO);
+	intel8x0_t *chip = device->device_data;
 	return snd_intel8x0_free(chip);
 }
 
@@ -2438,7 +2468,7 @@
 	if ((err = pci_enable_device(pci)) < 0)
 		return err;
 
-	chip = snd_magic_kcalloc(intel8x0_t, 0, GFP_KERNEL);
+	chip = kcalloc(1, sizeof(*chip), GFP_KERNEL);
 	if (chip == NULL)
 		return -ENOMEM;
 	spin_lock_init(&chip->reg_lock);
@@ -2447,66 +2477,51 @@
 	chip->card = card;
 	chip->pci = pci;
 	chip->irq = -1;
-	snd_intel8x0_proc_init(chip);
-	sprintf(chip->ac97_name, "%s - AC'97", card->shortname);
-	sprintf(chip->ctrl_name, "%s - Controller", card->shortname);
+
 	if (pci->vendor == PCI_VENDOR_ID_INTEL &&
 	    pci->device == PCI_DEVICE_ID_INTEL_440MX)
 		chip->fix_nocache = 1; /* enable workaround */
+
+	/* some Nforce[2] and ICH boards have problems with IRQ handling.
+	 * Needs to return IRQ_HANDLED for unknown irqs.
+	 */
+	if (device_type == DEVICE_NFORCE)
+		chip->buggy_irq = 1;
+
+	if ((err = pci_request_regions(pci, card->shortname)) < 0) {
+		kfree(chip);
+		return err;
+	}
+
 	if (device_type == DEVICE_ALI) {
 		/* ALI5455 has no ac97 region */
 		chip->bmaddr = pci_resource_start(pci, 0);
-		if ((chip->res_bm = request_region(chip->bmaddr, 256, chip->ctrl_name)) == NULL) {
-			snd_printk("unable to grab ports 0x%lx-0x%lx\n", chip->bmaddr, chip->bmaddr + 64 - 1);
-			snd_intel8x0_free(chip);
-			return -EBUSY;
-		}
 		goto port_inited;
 	}
 
 	if (pci_resource_flags(pci, 2) & IORESOURCE_MEM) {	/* ICH4 and Nforce */
 		chip->mmio = 1;
 		chip->addr = pci_resource_start(pci, 2);
-		if ((chip->res = request_mem_region(chip->addr, 512, chip->ac97_name)) == NULL) {
-			snd_printk("unable to grab I/O memory 0x%lx-0x%lx\n", chip->addr, chip->addr + 512 - 1);
-			snd_intel8x0_free(chip);
-			return -EBUSY;
-		}
-		chip->remap_addr = (unsigned long) ioremap_nocache(chip->addr, 512);
-		if (chip->remap_addr == 0) {
+		chip->remap_addr = ioremap_nocache(chip->addr, pci_resource_len(pci, 2));
+		if (!chip->remap_addr) {
 			snd_printk("AC'97 space ioremap problem\n");
 			snd_intel8x0_free(chip);
 			return -EIO;
 		}
 	} else {
 		chip->addr = pci_resource_start(pci, 0);
-		if ((chip->res = request_region(chip->addr, 256, chip->ac97_name)) == NULL) {
-			snd_printk("unable to grab ports 0x%lx-0x%lx\n", chip->addr, chip->addr + 256 - 1);
-			snd_intel8x0_free(chip);
-			return -EBUSY;
-		}
 	}
 	if (pci_resource_flags(pci, 3) & IORESOURCE_MEM) {	/* ICH4 */
 		chip->bm_mmio = 1;
 		chip->bmaddr = pci_resource_start(pci, 3);
-		if ((chip->res_bm = request_mem_region(chip->bmaddr, 256, chip->ctrl_name)) == NULL) {
-			snd_printk("unable to grab I/O memory 0x%lx-0x%lx\n", chip->bmaddr, chip->bmaddr + 512 - 1);
-			snd_intel8x0_free(chip);
-			return -EBUSY;
-		}
-		chip->remap_bmaddr = (unsigned long) ioremap_nocache(chip->bmaddr, 256);
-		if (chip->remap_bmaddr == 0) {
+		chip->remap_bmaddr = ioremap_nocache(chip->bmaddr, pci_resource_len(pci, 3));
+		if (!chip->remap_bmaddr) {
 			snd_printk("Controller space ioremap problem\n");
 			snd_intel8x0_free(chip);
 			return -EIO;
 		}
 	} else {
 		chip->bmaddr = pci_resource_start(pci, 1);
-		if ((chip->res_bm = request_region(chip->bmaddr, 64, chip->ctrl_name)) == NULL) {
-			snd_printk("unable to grab ports 0x%lx-0x%lx\n", chip->bmaddr, chip->bmaddr + 64 - 1);
-			snd_intel8x0_free(chip);
-			return -EBUSY;
-		}
 	}
 
  port_inited:
@@ -2552,13 +2567,11 @@
 		ichdev->pos_shift = (device_type == DEVICE_SIS) ? 0 : 1;
 	}
 
-	memset(&chip->dma_dev, 0, sizeof(chip->dma_dev));
-	chip->dma_dev.type = SNDRV_DMA_TYPE_DEV;
-	chip->dma_dev.dev = snd_dma_pci_data(pci);
-
 	/* allocate buffer descriptor lists */
 	/* the start of each lists must be aligned to 8 bytes */
-	if (snd_dma_alloc_pages(&chip->dma_dev, chip->bdbars_count * sizeof(u32) * ICH_MAX_FRAGS * 2, &chip->bdbars) < 0) {
+	if (snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, snd_dma_pci_data(pci),
+				chip->bdbars_count * sizeof(u32) * ICH_MAX_FRAGS * 2,
+				&chip->bdbars) < 0) {
 		snd_intel8x0_free(chip);
 		snd_printk(KERN_ERR "intel8x0: cannot allocate buffer descriptors\n");
 		return -ENOMEM;
@@ -2614,6 +2627,9 @@
 	{ PCI_DEVICE_ID_NVIDIA_MCP2_AUDIO, "NVidia nForce2" },
 	{ PCI_DEVICE_ID_NVIDIA_MCP3_AUDIO, "NVidia nForce3" },
 	{ PCI_DEVICE_ID_NVIDIA_CK8S_AUDIO, "NVidia CK8S" },
+	{ PCI_DEVICE_ID_NVIDIA_CK804_AUDIO, "NVidia CK804" },
+	{ PCI_DEVICE_ID_NVIDIA_CK8_AUDIO, "NVidia CK8" },
+	{ 0x003a, "NVidia MCP04" },
 	{ 0x746d, "AMD AMD8111" },
 	{ 0x7445, "AMD AMD768" },
 	{ 0x5455, "ALi M5455" },
@@ -2661,6 +2677,8 @@
 		snd_card_free(card);
 		return err;
 	}
+	if (buggy_irq[dev])
+		chip->buggy_irq = 1;
 
 	if ((err = snd_intel8x0_mixer(chip, ac97_clock[dev], ac97_quirk[dev])) < 0) {
 		snd_card_free(card);
@@ -2680,6 +2698,8 @@
 		}
 	} else
 		mpu_port[dev] = 0;
+
+	snd_intel8x0_proc_init(chip);
 
 	sprintf(card->longname, "%s at 0x%lx, irq %i",
 		card->shortname, chip->addr, chip->irq);
diff -Nru a/sound/pci/intel8x0m.c b/sound/pci/intel8x0m.c
--- a/sound/pci/intel8x0m.c	2004-10-18 14:56:32 -07:00
+++ b/sound/pci/intel8x0m.c	2004-10-18 14:56:32 -07:00
@@ -40,10 +40,9 @@
 #include <sound/initval.h>
 
 MODULE_AUTHOR("Jaroslav Kysela <perex@suse.cz>");
-MODULE_DESCRIPTION("Intel 82801AA,82901AB,i810,i820,i830,i840,i845,MX440 modem");
+MODULE_DESCRIPTION("Intel 82801AA,82901AB,i810,i820,i830,i840,i845,MX440; SiS 7013; NVidia MCP/2/2S/3 modems");
 MODULE_LICENSE("GPL");
-MODULE_CLASSES("{sound}");
-MODULE_DEVICES("{{Intel,82801AA-ICH},"
+MODULE_SUPPORTED_DEVICE("{{Intel,82801AA-ICH},"
 		"{Intel,82901AB-ICH0},"
 		"{Intel,82801BA-ICH2},"
 		"{Intel,82801CA-ICH3},"
@@ -60,16 +59,12 @@
 
 module_param_array(index, int, boot_devs, 0444);
 MODULE_PARM_DESC(index, "Index value for Intel i8x0 modemcard.");
-MODULE_PARM_SYNTAX(index, SNDRV_INDEX_DESC);
 module_param_array(id, charp, boot_devs, 0444);
 MODULE_PARM_DESC(id, "ID string for Intel i8x0 modemcard.");
-MODULE_PARM_SYNTAX(id, SNDRV_ID_DESC);
 module_param_array(enable, bool, boot_devs, 0444);
 MODULE_PARM_DESC(enable, "Enable Intel i8x0 modemcard.");
-MODULE_PARM_SYNTAX(enable, SNDRV_ENABLE_DESC);
 module_param_array(ac97_clock, int, boot_devs, 0444);
 MODULE_PARM_DESC(ac97_clock, "AC'97 codec clock (0 = auto-detect).");
-MODULE_PARM_SYNTAX(ac97_clock, SNDRV_ENABLED ",default:0");
 
 /*
  *  Direct registers
@@ -99,18 +94,20 @@
 #ifndef PCI_DEVICE_ID_SI_7013
 #define PCI_DEVICE_ID_SI_7013		0x7013
 #endif
-#if 0
-#ifndef PCI_DEVICE_ID_NVIDIA_MCP_AUDIO
-#define PCI_DEVICE_ID_NVIDIA_MCP_AUDIO	0x01b1
+#ifndef PCI_DEVICE_ID_NVIDIA_MCP_MODEM
+#define PCI_DEVICE_ID_NVIDIA_MCP_MODEM	0x01c1
 #endif
-#ifndef PCI_DEVICE_ID_NVIDIA_MCP2_AUDIO
-#define PCI_DEVICE_ID_NVIDIA_MCP2_AUDIO	0x006a
+#ifndef PCI_DEVICE_ID_NVIDIA_MCP2_MODEM
+#define PCI_DEVICE_ID_NVIDIA_MCP2_MODEM	0x0069
 #endif
-#ifndef PCI_DEVICE_ID_NVIDIA_MCP3_AUDIO
-#define PCI_DEVICE_ID_NVIDIA_MCP3_AUDIO	0x00da
+#ifndef PCI_DEVICE_ID_NVIDIA_MCP2S_MODEM
+#define PCI_DEVICE_ID_NVIDIA_MCP2S_MODEM 0x0089
 #endif
+#ifndef PCI_DEVICE_ID_NVIDIA_MCP3_MODEM
+#define PCI_DEVICE_ID_NVIDIA_MCP3_MODEM	0x00d9
 #endif
 
+
 enum { DEVICE_INTEL, DEVICE_SIS, DEVICE_ALI, DEVICE_NFORCE };
 
 #define ICHREG(x) ICH_REG_##x
@@ -228,23 +225,18 @@
 } ichdev_t;
 
 typedef struct _snd_intel8x0m intel8x0_t;
-#define chip_t intel8x0_t
 
 struct _snd_intel8x0m {
 	unsigned int device_type;
-	char ac97_name[64];
-	char ctrl_name[64];
 
 	int irq;
 
 	unsigned int mmio;
 	unsigned long addr;
 	unsigned long remap_addr;
-	struct resource *res;
 	unsigned int bm_mmio;
 	unsigned long bmaddr;
 	unsigned long remap_bmaddr;
-	struct resource *res_bm;
 
 	struct pci_dev *pci;
 	snd_card_t *card;
@@ -261,7 +253,6 @@
 	spinlock_t reg_lock;
 	spinlock_t ac97_lock;
 	
-	struct snd_dma_device dma_dev;
 	struct snd_dma_buffer bdbars;
 	u32 bdbars_count;
 	u32 int_sta_reg;		/* interrupt status register */
@@ -278,12 +269,12 @@
 	{ 0x8086, 0x24d6, PCI_ANY_ID, PCI_ANY_ID, 0, 0, DEVICE_INTEL }, /* ICH5 */
 	{ 0x8086, 0x7196, PCI_ANY_ID, PCI_ANY_ID, 0, 0, DEVICE_INTEL },	/* 440MX */
 	{ 0x1022, 0x7446, PCI_ANY_ID, PCI_ANY_ID, 0, 0, DEVICE_INTEL },	/* AMD768 */
-#if 0
-	/* TODO: support needed */
 	{ 0x1039, 0x7013, PCI_ANY_ID, PCI_ANY_ID, 0, 0, DEVICE_SIS },	/* SI7013 */
-	{ 0x10de, 0x01b1, PCI_ANY_ID, PCI_ANY_ID, 0, 0, DEVICE_NFORCE },	/* NFORCE */
-	{ 0x10de, 0x006a, PCI_ANY_ID, PCI_ANY_ID, 0, 0, DEVICE_NFORCE },	/* NFORCE2 */
-	{ 0x10de, 0x00da, PCI_ANY_ID, PCI_ANY_ID, 0, 0, DEVICE_NFORCE },	/* NFORCE3 */
+	{ 0x10de, 0x01c1, PCI_ANY_ID, PCI_ANY_ID, 0, 0, DEVICE_NFORCE }, /* NFORCE */
+	{ 0x10de, 0x0069, PCI_ANY_ID, PCI_ANY_ID, 0, 0, DEVICE_NFORCE }, /* NFORCE2 */
+	{ 0x10de, 0x0089, PCI_ANY_ID, PCI_ANY_ID, 0, 0, DEVICE_NFORCE }, /* NFORCE2s */
+	{ 0x10de, 0x00d9, PCI_ANY_ID, PCI_ANY_ID, 0, 0, DEVICE_NFORCE }, /* NFORCE3 */
+#if 0
 	{ 0x1022, 0x746d, PCI_ANY_ID, PCI_ANY_ID, 0, 0, DEVICE_INTEL },	/* AMD8111 */
 	{ 0x10b9, 0x5455, PCI_ANY_ID, PCI_ANY_ID, 0, 0, DEVICE_ALI },   /* Ali5455 */
 #endif
@@ -328,6 +319,14 @@
 		outb(val, chip->bmaddr + offset);
 }
 
+static void iputword(intel8x0_t *chip, u32 offset, u16 val)
+{
+	if (chip->bm_mmio)
+		writew(val, chip->remap_bmaddr + offset);
+	else
+		outw(val, chip->bmaddr + offset);
+}
+
 static void iputdword(intel8x0_t *chip, u32 offset, u32 val)
 {
 	if (chip->bm_mmio)
@@ -408,7 +407,7 @@
 				     unsigned short reg,
 				     unsigned short val)
 {
-	intel8x0_t *chip = snd_magic_cast(intel8x0_t, ac97->private_data, return);
+	intel8x0_t *chip = ac97->private_data;
 	
 	spin_lock(&chip->ac97_lock);
 	if (snd_intel8x0m_codec_semaphore(chip, ac97->num) < 0) {
@@ -422,7 +421,7 @@
 static unsigned short snd_intel8x0_codec_read(ac97_t *ac97,
 					      unsigned short reg)
 {
-	intel8x0_t *chip = snd_magic_cast(intel8x0_t, ac97->private_data, return ~0);
+	intel8x0_t *chip = ac97->private_data;
 	unsigned short res;
 	unsigned int tmp;
 
@@ -542,13 +541,17 @@
 
 static irqreturn_t snd_intel8x0_interrupt(int irq, void *dev_id, struct pt_regs *regs)
 {
-	intel8x0_t *chip = snd_magic_cast(intel8x0_t, dev_id, return IRQ_NONE);
+	intel8x0_t *chip = dev_id;
 	ichdev_t *ichdev;
 	unsigned int status;
 	unsigned int i;
 
 	spin_lock(&chip->reg_lock);
 	status = igetdword(chip, chip->int_sta_reg);
+	if (status == 0xffffffff) { /* we are not yet resumed */
+		spin_unlock(&chip->reg_lock);
+		return IRQ_NONE;
+	}
 	if ((status & chip->int_sta_mask) == 0) {
 		if (status)
 			iputdword(chip, chip->int_sta_reg, status);
@@ -684,9 +687,9 @@
 	.rate_max =		16000,
 	.channels_min =		1,
 	.channels_max =		1,
-	.buffer_bytes_max =	32 * 1024,
+	.buffer_bytes_max =	64 * 1024,
 	.period_bytes_min =	32,
-	.period_bytes_max =	32 * 1024,
+	.period_bytes_max =	64 * 1024,
 	.periods_min =		1,
 	.periods_max =		1024,
 	.fifo_size =		0,
@@ -818,8 +821,8 @@
 		.suffix = "Modem",
 		.playback_ops = &snd_intel8x0m_playback_ops,
 		.capture_ops = &snd_intel8x0m_capture_ops,
-		.prealloc_size = 4 * 1024,
-		.prealloc_max_size = 16 * 1024,
+		.prealloc_size = 32 * 1024,
+		.prealloc_max_size = 64 * 1024,
 	},
 };
 
@@ -872,32 +875,30 @@
 
 static void snd_intel8x0_mixer_free_ac97_bus(ac97_bus_t *bus)
 {
-	intel8x0_t *chip = snd_magic_cast(intel8x0_t, bus->private_data, return);
+	intel8x0_t *chip = bus->private_data;
 	chip->ac97_bus = NULL;
 }
 
 static void snd_intel8x0_mixer_free_ac97(ac97_t *ac97)
 {
-	intel8x0_t *chip = snd_magic_cast(intel8x0_t, ac97->private_data, return);
+	intel8x0_t *chip = ac97->private_data;
 	chip->ac97 = NULL;
 }
 
 
 static int __devinit snd_intel8x0_mixer(intel8x0_t *chip, int ac97_clock)
 {
-	ac97_bus_t bus, *pbus;
-	ac97_t ac97, *x97;
+	ac97_bus_t *pbus;
+	ac97_template_t ac97;
+	ac97_t *x97;
 	int err;
 	unsigned int glob_sta = 0;
+	static ac97_bus_ops_t ops = {
+		.write = snd_intel8x0_codec_write,
+		.read = snd_intel8x0_codec_read,
+	};
 
 	chip->in_ac97_init = 1;
-	memset(&bus, 0, sizeof(bus));
-	bus.private_data = chip;
-	bus.private_free = snd_intel8x0_mixer_free_ac97_bus;
-	if (ac97_clock >= 8000 && ac97_clock <= 48000)
-		bus.clock = ac97_clock;
-	else
-		bus.clock = 48000;
 	
 	memset(&ac97, 0, sizeof(ac97));
 	ac97.private_data = chip;
@@ -905,13 +906,15 @@
 	ac97.scaps = AC97_SCAP_SKIP_AUDIO;
 
 	glob_sta = igetdword(chip, ICHREG(GLOB_STA));
-	bus.write = snd_intel8x0_codec_write;
-	bus.read = snd_intel8x0_codec_read;
-	bus.vra = 1;
 
-	if ((err = snd_ac97_bus(chip->card, &bus, &pbus)) < 0)
+	if ((err = snd_ac97_bus(chip->card, 0, &ops, chip, &pbus)) < 0)
 		goto __err;
+	pbus->private_free = snd_intel8x0_mixer_free_ac97_bus;
+	pbus->shared_type = AC97_SHARED_TYPE_ICH;	/* shared with audio driver */
+	if (ac97_clock >= 8000 && ac97_clock <= 48000)
+		pbus->clock = ac97_clock;
 	chip->ac97_bus = pbus;
+
 	ac97.pci = chip->pci;
 	ac97.num = glob_sta & ICH_SCR ? 1 : 0;
 	if ((err = snd_ac97_mixer(pbus, &ac97, &x97)) < 0) {
@@ -1016,6 +1019,11 @@
 		} while (time_after_eq(end_time, jiffies));
 	}
 
+	if (chip->device_type == DEVICE_SIS) {
+		/* unmute the output on SIS7012 */
+		iputword(chip, 0x4c, igetword(chip, 0x4c) | 1);
+	}
+
       	return 0;
 }
 
@@ -1056,22 +1064,15 @@
 	synchronize_irq(chip->irq);
       __hw_end:
 	if (chip->bdbars.area)
-		snd_dma_free_pages(&chip->dma_dev, &chip->bdbars);
+		snd_dma_free_pages(&chip->bdbars);
 	if (chip->remap_addr)
 		iounmap((void *) chip->remap_addr);
 	if (chip->remap_bmaddr)
 		iounmap((void *) chip->remap_bmaddr);
-	if (chip->res) {
-		release_resource(chip->res);
-		kfree_nocheck(chip->res);
-	}
-	if (chip->res_bm) {
-		release_resource(chip->res_bm);
-		kfree_nocheck(chip->res_bm);
-	}
 	if (chip->irq >= 0)
 		free_irq(chip->irq, (void *)chip);
-	snd_magic_kfree(chip);
+	pci_release_regions(chip->pci);
+	kfree(chip);
 	return 0;
 }
 
@@ -1081,7 +1082,7 @@
  */
 static int intel8x0m_suspend(snd_card_t *card, unsigned int state)
 {
-	intel8x0_t *chip = snd_magic_cast(intel8x0_t, card->pm_private_data, return -EINVAL);
+	intel8x0_t *chip = card->pm_private_data;
 	int i;
 
 	for (i = 0; i < chip->pcm_devs; i++)
@@ -1094,7 +1095,7 @@
 
 static int intel8x0m_resume(snd_card_t *card, unsigned int state)
 {
-	intel8x0_t *chip = snd_magic_cast(intel8x0_t, card->pm_private_data, return -EINVAL);
+	intel8x0_t *chip = card->pm_private_data;
 	pci_enable_device(chip->pci);
 	pci_set_master(chip->pci);
 	snd_intel8x0_chip_init(chip, 0);
@@ -1109,7 +1110,7 @@
 static void snd_intel8x0m_proc_read(snd_info_entry_t * entry,
 				   snd_info_buffer_t * buffer)
 {
-	intel8x0_t *chip = snd_magic_cast(intel8x0_t, entry->private_data, return);
+	intel8x0_t *chip = entry->private_data;
 	unsigned int tmp;
 
 	snd_iprintf(buffer, "Intel8x0m\n\n");
@@ -1135,7 +1136,7 @@
 
 static int snd_intel8x0_dev_free(snd_device_t *device)
 {
-	intel8x0_t *chip = snd_magic_cast(intel8x0_t, device->device_data, return -ENXIO);
+	intel8x0_t *chip = device->device_data;
 	return snd_intel8x0_free(chip);
 }
 
@@ -1168,7 +1169,7 @@
 	if ((err = pci_enable_device(pci)) < 0)
 		return err;
 
-	chip = snd_magic_kcalloc(intel8x0_t, 0, GFP_KERNEL);
+	chip = kcalloc(1, sizeof(*chip), GFP_KERNEL);
 	if (chip == NULL)
 		return -ENOMEM;
 	spin_lock_init(&chip->reg_lock);
@@ -1177,29 +1178,23 @@
 	chip->card = card;
 	chip->pci = pci;
 	chip->irq = -1;
-	snd_intel8x0m_proc_init(chip);
-	sprintf(chip->ac97_name, "%s - AC'97", card->shortname);
-	sprintf(chip->ctrl_name, "%s - Controller", card->shortname);
+
+	if ((err = pci_request_regions(pci, card->shortname)) < 0) {
+		kfree(chip);
+		return err;
+	}
+
 	if (device_type == DEVICE_ALI) {
 		/* ALI5455 has no ac97 region */
 		chip->bmaddr = pci_resource_start(pci, 0);
-		if ((chip->res_bm = request_region(chip->bmaddr, 256, chip->ctrl_name)) == NULL) {
-			snd_printk("unable to grab ports 0x%lx-0x%lx\n", chip->bmaddr, chip->bmaddr + 256 - 1);
-			snd_intel8x0_free(chip);
-			return -EBUSY;
-		}
 		goto port_inited;
 	}
 
 	if (pci_resource_flags(pci, 2) & IORESOURCE_MEM) {	/* ICH4 and Nforce */
 		chip->mmio = 1;
 		chip->addr = pci_resource_start(pci, 2);
-		if ((chip->res = request_mem_region(chip->addr, 512, chip->ac97_name)) == NULL) {
-			snd_printk("unable to grab I/O memory 0x%lx-0x%lx\n", chip->addr, chip->addr + 512 - 1);
-			snd_intel8x0_free(chip);
-			return -EBUSY;
-		}
-		chip->remap_addr = (unsigned long) ioremap_nocache(chip->addr, 512);
+		chip->remap_addr = (unsigned long) ioremap_nocache(chip->addr,
+								   pci_resource_len(pci, 2));
 		if (chip->remap_addr == 0) {
 			snd_printk("AC'97 space ioremap problem\n");
 			snd_intel8x0_free(chip);
@@ -1207,21 +1202,12 @@
 		}
 	} else {
 		chip->addr = pci_resource_start(pci, 0);
-		if ((chip->res = request_region(chip->addr, 256, chip->ac97_name)) == NULL) {
-			snd_printk("unable to grab ports 0x%lx-0x%lx\n", chip->addr, chip->addr + 256 - 1);
-			snd_intel8x0_free(chip);
-			return -EBUSY;
-		}
 	}
 	if (pci_resource_flags(pci, 3) & IORESOURCE_MEM) {	/* ICH4 */
 		chip->bm_mmio = 1;
 		chip->bmaddr = pci_resource_start(pci, 3);
-		if ((chip->res_bm = request_mem_region(chip->bmaddr, 256, chip->ctrl_name)) == NULL) {
-			snd_printk("unable to grab I/O memory 0x%lx-0x%lx\n", chip->bmaddr, chip->bmaddr + 512 - 1);
-			snd_intel8x0_free(chip);
-			return -EBUSY;
-		}
-		chip->remap_bmaddr = (unsigned long) ioremap_nocache(chip->bmaddr, 256);
+		chip->remap_bmaddr = (unsigned long) ioremap_nocache(chip->bmaddr,
+								     pci_resource_len(pci, 3));
 		if (chip->remap_bmaddr == 0) {
 			snd_printk("Controller space ioremap problem\n");
 			snd_intel8x0_free(chip);
@@ -1229,11 +1215,6 @@
 		}
 	} else {
 		chip->bmaddr = pci_resource_start(pci, 1);
-		if ((chip->res_bm = request_region(chip->bmaddr, 128, chip->ctrl_name)) == NULL) {
-			snd_printk("unable to grab ports 0x%lx-0x%lx\n", chip->bmaddr, chip->bmaddr + 128 - 1);
-			snd_intel8x0_free(chip);
-			return -EBUSY;
-		}
 	}
 
  port_inited:
@@ -1271,10 +1252,9 @@
 
 	/* allocate buffer descriptor lists */
 	/* the start of each lists must be aligned to 8 bytes */
-	memset(&chip->dma_dev, 0, sizeof(chip->dma_dev));
-	chip->dma_dev.type = SNDRV_DMA_TYPE_DEV;
-	chip->dma_dev.dev = snd_dma_pci_data(pci);
-	if (snd_dma_alloc_pages(&chip->dma_dev, chip->bdbars_count * sizeof(u32) * ICH_MAX_FRAGS * 2, &chip->bdbars) < 0) {
+	if (snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, snd_dma_pci_data(pci),
+				chip->bdbars_count * sizeof(u32) * ICH_MAX_FRAGS * 2,
+				&chip->bdbars) < 0) {
 		snd_intel8x0_free(chip);
 		return -ENOMEM;
 	}
@@ -1320,11 +1300,12 @@
 	{ PCI_DEVICE_ID_INTEL_ICH4_6, "Intel 82801DB-ICH4" },
 	{ PCI_DEVICE_ID_INTEL_ICH5_6, "Intel ICH5" },
 	{ 0x7446, "AMD AMD768" },
-#if 0
 	{ PCI_DEVICE_ID_SI_7013, "SiS SI7013" },
-	{ PCI_DEVICE_ID_NVIDIA_MCP_AUDIO, "NVidia nForce" },
-	{ PCI_DEVICE_ID_NVIDIA_MCP2_AUDIO, "NVidia nForce2" },
-	{ PCI_DEVICE_ID_NVIDIA_MCP3_AUDIO, "NVidia nForce3" },
+	{ PCI_DEVICE_ID_NVIDIA_MCP_MODEM, "NVidia nForce" },
+	{ PCI_DEVICE_ID_NVIDIA_MCP2_MODEM, "NVidia nForce2" },
+	{ PCI_DEVICE_ID_NVIDIA_MCP2S_MODEM, "NVidia nForce2s" },
+	{ PCI_DEVICE_ID_NVIDIA_MCP3_MODEM, "NVidia nForce3" },
+#if 0
 	{ 0x5455, "ALi M5455" },
 	{ 0x746d, "AMD AMD8111" },
 #endif
@@ -1353,10 +1334,10 @@
 
 	switch (pci_id->driver_data) {
 	case DEVICE_NFORCE:
-		strcpy(card->driver, "NFORCE");
+		strcpy(card->driver, "NFORCE-MODEM");
 		break;
 	default:
-		strcpy(card->driver, "ICH");
+		strcpy(card->driver, "ICH-MODEM");
 		break;
 	}
 
@@ -1383,6 +1364,8 @@
 		return err;
 	}
 	
+	snd_intel8x0m_proc_init(chip);
+
 	sprintf(card->longname, "%s at 0x%lx, irq %i",
 		card->shortname, chip->addr, chip->irq);
 
diff -Nru a/sound/pci/korg1212/korg1212.c b/sound/pci/korg1212/korg1212.c
--- a/sound/pci/korg1212/korg1212.c	2004-10-18 14:55:54 -07:00
+++ b/sound/pci/korg1212/korg1212.c	2004-10-18 14:55:54 -07:00
@@ -343,12 +343,6 @@
         unsigned long inIRQ;
         unsigned long iobase;
 
-	struct resource *res_iomem;
-	struct resource *res_ioport;
-	struct resource *res_iomem2;
-
-	struct snd_dma_device dma_dev;
-
 	struct snd_dma_buffer dma_dsp;
         struct snd_dma_buffer dma_play;
         struct snd_dma_buffer dma_rec;
@@ -411,8 +405,7 @@
 
 MODULE_DESCRIPTION("korg1212");
 MODULE_LICENSE("GPL");
-MODULE_CLASSES("{sound}");
-MODULE_DEVICES("{{KORG,korg1212}}");
+MODULE_SUPPORTED_DEVICE("{{KORG,korg1212}}");
 
 static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX;     /* Index 0-MAX */
 static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR;	   /* ID for this card */
@@ -421,13 +414,10 @@
 
 module_param_array(index, int, boot_devs, 0444);
 MODULE_PARM_DESC(index, "Index value for Korg 1212 soundcard.");
-MODULE_PARM_SYNTAX(index, SNDRV_INDEX_DESC);
 module_param_array(id, charp, boot_devs, 0444);
 MODULE_PARM_DESC(id, "ID string for Korg 1212 soundcard.");
-MODULE_PARM_SYNTAX(id, SNDRV_ID_DESC);
 module_param_array(enable, bool, boot_devs, 0444);
 MODULE_PARM_DESC(enable, "Enable Korg 1212 soundcard.");
-MODULE_PARM_SYNTAX(enable, SNDRV_ENABLE_DESC);
 MODULE_AUTHOR("Haroldo Gamal <gamal@alternex.com.br>");
 
 static struct pci_device_id snd_korg1212_ids[] = {
@@ -637,7 +627,7 @@
 /* timer callback for checking the ack of stop request */
 static void snd_korg1212_timer_func(unsigned long data)
 {
-        korg1212_t *korg1212 = snd_magic_cast(korg1212_t, (void*)data, return);
+        korg1212_t *korg1212 = (korg1212_t *) data;
 	
 	spin_lock(&korg1212->lock);
 	if (readl(&korg1212->sharedBufferPtr->cardCommand) == 0) {
@@ -1143,7 +1133,7 @@
 static irqreturn_t snd_korg1212_interrupt(int irq, void *dev_id, struct pt_regs *regs)
 {
         u32 doorbellValue;
-        korg1212_t *korg1212 = snd_magic_cast(korg1212_t, dev_id, return IRQ_NONE);
+        korg1212_t *korg1212 = dev_id;
 
 	if(irq != korg1212->irq)
 		return IRQ_NONE;
@@ -1407,7 +1397,7 @@
 static int snd_korg1212_playback_open(snd_pcm_substream_t *substream)
 {
         unsigned long flags;
-        korg1212_t *korg1212 = _snd_pcm_substream_chip(substream);
+        korg1212_t *korg1212 = snd_pcm_substream_chip(substream);
         snd_pcm_runtime_t *runtime = substream->runtime;
 
 #if K1212_DEBUG_LEVEL > 0
@@ -1419,8 +1409,7 @@
 	snd_korg1212_OpenCard(korg1212);
 
         runtime->hw = snd_korg1212_playback_info;
-	runtime->dma_area = (char *) korg1212->playDataBufsPtr;
-	runtime->dma_bytes = K1212_BUF_SIZE;
+	snd_pcm_set_runtime_buffer(substream, &korg1212->dma_play);
 
         spin_lock_irqsave(&korg1212->lock, flags);
 
@@ -1438,7 +1427,7 @@
 static int snd_korg1212_capture_open(snd_pcm_substream_t *substream)
 {
         unsigned long flags;
-        korg1212_t *korg1212 = _snd_pcm_substream_chip(substream);
+        korg1212_t *korg1212 = snd_pcm_substream_chip(substream);
         snd_pcm_runtime_t *runtime = substream->runtime;
 
 #if K1212_DEBUG_LEVEL > 0
@@ -1450,8 +1439,7 @@
 	snd_korg1212_OpenCard(korg1212);
 
         runtime->hw = snd_korg1212_capture_info;
-	runtime->dma_area = (char *) korg1212->recordDataBufsPtr;
-	runtime->dma_bytes = K1212_BUF_SIZE;
+	snd_pcm_set_runtime_buffer(substream, &korg1212->dma_rec);
 
         spin_lock_irqsave(&korg1212->lock, flags);
 
@@ -1468,7 +1456,7 @@
 static int snd_korg1212_playback_close(snd_pcm_substream_t *substream)
 {
         unsigned long flags;
-        korg1212_t *korg1212 = _snd_pcm_substream_chip(substream);
+        korg1212_t *korg1212 = snd_pcm_substream_chip(substream);
 
 #if K1212_DEBUG_LEVEL > 0
 		K1212_DEBUG_PRINTK("K1212_DEBUG: snd_korg1212_playback_close [%s]\n", stateName[korg1212->cardState]);
@@ -1490,7 +1478,7 @@
 static int snd_korg1212_capture_close(snd_pcm_substream_t *substream)
 {
         unsigned long flags;
-        korg1212_t *korg1212 = _snd_pcm_substream_chip(substream);
+        korg1212_t *korg1212 = snd_pcm_substream_chip(substream);
 
 #if K1212_DEBUG_LEVEL > 0
 		K1212_DEBUG_PRINTK("K1212_DEBUG: snd_korg1212_capture_close [%s]\n", stateName[korg1212->cardState]);
@@ -1532,7 +1520,7 @@
                              snd_pcm_hw_params_t *params)
 {
         unsigned long flags;
-        korg1212_t *korg1212 = _snd_pcm_substream_chip(substream);
+        korg1212_t *korg1212 = snd_pcm_substream_chip(substream);
         int err;
 
 #if K1212_DEBUG_LEVEL > 0
@@ -1560,21 +1548,21 @@
 
 static int snd_korg1212_prepare(snd_pcm_substream_t *substream)
 {
-        korg1212_t *korg1212 = _snd_pcm_substream_chip(substream);
+        korg1212_t *korg1212 = snd_pcm_substream_chip(substream);
 	int rc;
 
 #if K1212_DEBUG_LEVEL > 0
 		K1212_DEBUG_PRINTK("K1212_DEBUG: snd_korg1212_prepare [%s]\n", stateName[korg1212->cardState]);
 #endif
 
-        spin_lock(&korg1212->lock);
+	spin_lock_irq(&korg1212->lock);
 
 	/* FIXME: we should wait for ack! */
 	if (korg1212->stop_pending_cnt > 0) {
 #if K1212_DEBUG_LEVEL > 0
 		K1212_DEBUG_PRINTK("K1212_DEBUG: snd_korg1212_prepare - Stop is pending... [%s]\n", stateName[korg1212->cardState]);
 #endif
-        	spin_unlock(&korg1212->lock);
+        	spin_unlock_irq(&korg1212->lock);
 		return -EAGAIN;
 		/*
 		writel(0, &korg1212->sharedBufferPtr->cardCommand);
@@ -1587,7 +1575,7 @@
 
         korg1212->currentBuffer = 0;
 
-        spin_unlock(&korg1212->lock);
+        spin_unlock_irq(&korg1212->lock);
 
 	return rc ? -EINVAL : 0;
 }
@@ -1595,7 +1583,7 @@
 static int snd_korg1212_trigger(snd_pcm_substream_t *substream,
                            int cmd)
 {
-        korg1212_t *korg1212 = _snd_pcm_substream_chip(substream);
+        korg1212_t *korg1212 = snd_pcm_substream_chip(substream);
 	int rc;
 
 #if K1212_DEBUG_LEVEL > 0
@@ -1640,7 +1628,7 @@
 
 static snd_pcm_uframes_t snd_korg1212_playback_pointer(snd_pcm_substream_t *substream)
 {
-        korg1212_t *korg1212 = _snd_pcm_substream_chip(substream);
+        korg1212_t *korg1212 = snd_pcm_substream_chip(substream);
         snd_pcm_uframes_t pos;
 
 	pos = korg1212->currentBuffer * kPlayBufferFrames;
@@ -1655,7 +1643,7 @@
 
 static snd_pcm_uframes_t snd_korg1212_capture_pointer(snd_pcm_substream_t *substream)
 {
-        korg1212_t *korg1212 = _snd_pcm_substream_chip(substream);
+        korg1212_t *korg1212 = snd_pcm_substream_chip(substream);
         snd_pcm_uframes_t pos;
 
 	pos = korg1212->currentBuffer * kPlayBufferFrames;
@@ -1674,7 +1662,7 @@
                         void __user *src,
                         snd_pcm_uframes_t count)
 {
-        korg1212_t *korg1212 = _snd_pcm_substream_chip(substream);
+        korg1212_t *korg1212 = snd_pcm_substream_chip(substream);
 
 #if K1212_DEBUG_LEVEL > 2
 		K1212_DEBUG_PRINTK("K1212_DEBUG: snd_korg1212_playback_copy [%s] %ld %ld\n", stateName[korg1212->cardState], pos, count);
@@ -1689,7 +1677,7 @@
                            snd_pcm_uframes_t pos,
                            snd_pcm_uframes_t count)
 {
-        korg1212_t *korg1212 = _snd_pcm_substream_chip(substream);
+        korg1212_t *korg1212 = snd_pcm_substream_chip(substream);
 
 #if K1212_DEBUG_LEVEL > 0
 		K1212_DEBUG_PRINTK("K1212_DEBUG: snd_korg1212_playback_silence [%s]\n", stateName[korg1212->cardState]);
@@ -1704,7 +1692,7 @@
                         void __user *dst,
                         snd_pcm_uframes_t count)
 {
-        korg1212_t *korg1212 = _snd_pcm_substream_chip(substream);
+        korg1212_t *korg1212 = snd_pcm_substream_chip(substream);
 
 #if K1212_DEBUG_LEVEL > 2
 		K1212_DEBUG_PRINTK("K1212_DEBUG: snd_korg1212_capture_copy [%s] %ld %ld\n", stateName[korg1212->cardState], pos, count);
@@ -1749,30 +1737,28 @@
 
 static int snd_korg1212_control_phase_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *u)
 {
-	korg1212_t *korg1212 = _snd_kcontrol_chip(kcontrol);
-	unsigned long flags;
+	korg1212_t *korg1212 = snd_kcontrol_chip(kcontrol);
 	int i = kcontrol->private_value;
 
-	spin_lock_irqsave(&korg1212->lock, flags);
+	spin_lock_irq(&korg1212->lock);
 
         u->value.integer.value[0] = korg1212->volumePhase[i];
 
 	if (i >= 8)
         	u->value.integer.value[1] = korg1212->volumePhase[i+1];
 
-        spin_unlock_irqrestore(&korg1212->lock, flags);
+	spin_unlock_irq(&korg1212->lock);
 
         return 0;
 }
 
 static int snd_korg1212_control_phase_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *u)
 {
-	korg1212_t *korg1212 = _snd_kcontrol_chip(kcontrol);
-	unsigned long flags;
+	korg1212_t *korg1212 = snd_kcontrol_chip(kcontrol);
         int change = 0;
         int i, val;
 
-	spin_lock_irqsave(&korg1212->lock, flags);
+	spin_lock_irq(&korg1212->lock);
 
 	i = kcontrol->private_value;
 
@@ -1798,7 +1784,7 @@
 		}
 	}
 
-	spin_unlock_irqrestore(&korg1212->lock, flags);
+	spin_unlock_irq(&korg1212->lock);
 
         return change;
 }
@@ -1814,11 +1800,10 @@
 
 static int snd_korg1212_control_volume_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *u)
 {
-	korg1212_t *korg1212 = _snd_kcontrol_chip(kcontrol);
-	unsigned long flags;
+	korg1212_t *korg1212 = snd_kcontrol_chip(kcontrol);
         int i;
 
-	spin_lock_irqsave(&korg1212->lock, flags);
+	spin_lock_irq(&korg1212->lock);
 
 	i = kcontrol->private_value;
         u->value.integer.value[0] = abs(korg1212->sharedBufferPtr->volumeData[i]);
@@ -1826,20 +1811,19 @@
 	if (i >= 8) 
                 u->value.integer.value[1] = abs(korg1212->sharedBufferPtr->volumeData[i+1]);
 
-        spin_unlock_irqrestore(&korg1212->lock, flags);
+        spin_unlock_irq(&korg1212->lock);
 
         return 0;
 }
 
 static int snd_korg1212_control_volume_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *u)
 {
-	korg1212_t *korg1212 = _snd_kcontrol_chip(kcontrol);
-	unsigned long flags;
+	korg1212_t *korg1212 = snd_kcontrol_chip(kcontrol);
         int change = 0;
         int i;
 	int val;
 
-	spin_lock_irqsave(&korg1212->lock, flags);
+	spin_lock_irq(&korg1212->lock);
 
 	i = kcontrol->private_value;
 
@@ -1859,7 +1843,7 @@
 		}
 	}
 
-	spin_unlock_irqrestore(&korg1212->lock, flags);
+	spin_unlock_irq(&korg1212->lock);
 
         return change;
 }
@@ -1878,11 +1862,10 @@
 
 static int snd_korg1212_control_route_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *u)
 {
-	korg1212_t *korg1212 = _snd_kcontrol_chip(kcontrol);
-	unsigned long flags;
+	korg1212_t *korg1212 = snd_kcontrol_chip(kcontrol);
         int i;
 
-	spin_lock_irqsave(&korg1212->lock, flags);
+	spin_lock_irq(&korg1212->lock);
 
 	i = kcontrol->private_value;
 	u->value.enumerated.item[0] = korg1212->sharedBufferPtr->routeData[i];
@@ -1890,18 +1873,17 @@
 	if (i >= 8) 
 		u->value.enumerated.item[1] = korg1212->sharedBufferPtr->routeData[i+1];
 
-        spin_unlock_irqrestore(&korg1212->lock, flags);
+        spin_unlock_irq(&korg1212->lock);
 
         return 0;
 }
 
 static int snd_korg1212_control_route_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *u)
 {
-	korg1212_t *korg1212 = _snd_kcontrol_chip(kcontrol);
-	unsigned long flags;
+	korg1212_t *korg1212 = snd_kcontrol_chip(kcontrol);
         int change = 0, i;
 
-	spin_lock_irqsave(&korg1212->lock, flags);
+	spin_lock_irq(&korg1212->lock);
 
 	i = kcontrol->private_value;
 
@@ -1917,7 +1899,7 @@
 		}
 	}
 
-	spin_unlock_irqrestore(&korg1212->lock, flags);
+	spin_unlock_irq(&korg1212->lock);
 
         return change;
 }
@@ -1933,26 +1915,24 @@
 
 static int snd_korg1212_control_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *u)
 {
-	korg1212_t *korg1212 = _snd_kcontrol_chip(kcontrol);
-	unsigned long flags;
+	korg1212_t *korg1212 = snd_kcontrol_chip(kcontrol);
 
-	spin_lock_irqsave(&korg1212->lock, flags);
+	spin_lock_irq(&korg1212->lock);
 
         u->value.integer.value[0] = korg1212->leftADCInSens;
         u->value.integer.value[1] = korg1212->rightADCInSens;
 
-        spin_unlock_irqrestore(&korg1212->lock, flags);
+	spin_unlock_irq(&korg1212->lock);
 
         return 0;
 }
 
 static int snd_korg1212_control_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *u)
 {
-	korg1212_t *korg1212 = _snd_kcontrol_chip(kcontrol);
-	unsigned long flags;
+	korg1212_t *korg1212 = snd_kcontrol_chip(kcontrol);
         int change = 0;
 
-	spin_lock_irqsave(&korg1212->lock, flags);
+	spin_lock_irq(&korg1212->lock);
 
         if (u->value.integer.value[0] != korg1212->leftADCInSens) {
                 korg1212->leftADCInSens = u->value.integer.value[0];
@@ -1963,7 +1943,7 @@
                 change = 1;
         }
 
-	spin_unlock_irqrestore(&korg1212->lock, flags);
+	spin_unlock_irq(&korg1212->lock);
 
         if (change)
                 snd_korg1212_WriteADCSensitivity(korg1212);
@@ -1985,29 +1965,27 @@
 
 static int snd_korg1212_control_sync_get(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
 {
-	korg1212_t *korg1212 = _snd_kcontrol_chip(kcontrol);
-	unsigned long flags;
+	korg1212_t *korg1212 = snd_kcontrol_chip(kcontrol);
 
-	spin_lock_irqsave(&korg1212->lock, flags);
+	spin_lock_irq(&korg1212->lock);
 
 	ucontrol->value.enumerated.item[0] = korg1212->clkSource;
 
-	spin_unlock_irqrestore(&korg1212->lock, flags);
+	spin_unlock_irq(&korg1212->lock);
 	return 0;
 }
 
 static int snd_korg1212_control_sync_put(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
 {
-	korg1212_t *korg1212 = _snd_kcontrol_chip(kcontrol);
-	unsigned long flags;
+	korg1212_t *korg1212 = snd_kcontrol_chip(kcontrol);
 	unsigned int val;
 	int change;
 
 	val = ucontrol->value.enumerated.item[0] % 3;
-	spin_lock_irqsave(&korg1212->lock, flags);
+	spin_lock_irq(&korg1212->lock);
 	change = val != korg1212->clkSource;
         snd_korg1212_SetClockSource(korg1212, val);
-	spin_unlock_irqrestore(&korg1212->lock, flags);
+	spin_unlock_irq(&korg1212->lock);
 	return change;
 }
 
@@ -2063,8 +2041,6 @@
         }
 };
 
-#define K1212_CONTROL_ELEMENTS (sizeof(snd_korg1212_controls) / sizeof(snd_korg1212_controls[0]))
-
 /*
  * proc interface
  */
@@ -2120,29 +2096,13 @@
                 korg1212->iobase = 0;
         }
         
-        if (korg1212->res_iomem != NULL) {
-                release_resource(korg1212->res_iomem);
-                kfree_nocheck(korg1212->res_iomem);
-                korg1212->res_iomem = NULL;
-        }
-        
-        if (korg1212->res_ioport != NULL) {
-                release_resource(korg1212->res_ioport);
-                kfree_nocheck(korg1212->res_ioport);
-                korg1212->res_ioport = NULL;
-        }
-        
-        if (korg1212->res_iomem2 != NULL) {
-                release_resource(korg1212->res_iomem2);
-                kfree_nocheck(korg1212->res_iomem2);
-                korg1212->res_iomem2 = NULL;
-        }
+	pci_release_regions(korg1212->pci);
 
         // ----------------------------------------------------
         // free up memory resources used for the DSP download.
         // ----------------------------------------------------
         if (korg1212->dma_dsp.area) {
-        	snd_dma_free_pages(&korg1212->dma_dev, &korg1212->dma_dsp);
+        	snd_dma_free_pages(&korg1212->dma_dsp);
         	korg1212->dma_dsp.area = NULL;
         }
 
@@ -2152,12 +2112,12 @@
         // free up memory resources used for the Play/Rec Buffers
         // ------------------------------------------------------
 	if (korg1212->dma_play.area) {
-		snd_dma_free_pages(&korg1212->dma_dev, &korg1212->dma_play);
+		snd_dma_free_pages(&korg1212->dma_play);
 		korg1212->dma_play.area = NULL;
         }
 
 	if (korg1212->dma_rec.area) {
-		snd_dma_free_pages(&korg1212->dma_dev, &korg1212->dma_rec);
+		snd_dma_free_pages(&korg1212->dma_rec);
 		korg1212->dma_rec.area = NULL;
         }
 
@@ -2167,17 +2127,17 @@
         // free up memory resources used for the Shared Buffers
         // ----------------------------------------------------
 	if (korg1212->dma_shared.area) {
-		snd_dma_free_pages(&korg1212->dma_dev, &korg1212->dma_shared);
+		snd_dma_free_pages(&korg1212->dma_shared);
 		korg1212->dma_shared.area = NULL;
         }
         
-        snd_magic_kfree(korg1212);
+        kfree(korg1212);
         return 0;
 }
 
 static int snd_korg1212_dev_free(snd_device_t *device)
 {
-        korg1212_t *korg1212 = snd_magic_cast(korg1212_t, device->device_data, return -ENXIO);
+        korg1212_t *korg1212 = device->device_data;
 #if K1212_DEBUG_LEVEL > 0
         K1212_DEBUG_PRINTK("K1212_DEBUG: Freeing device\n");
 #endif
@@ -2201,7 +2161,7 @@
         if ((err = pci_enable_device(pci)) < 0)
                 return err;
 
-        korg1212 = snd_magic_kcalloc(korg1212_t, 0, GFP_KERNEL);
+        korg1212 = kcalloc(1, sizeof(*korg1212), GFP_KERNEL);
         if (korg1212 == NULL)
                 return -ENOMEM;
 
@@ -2232,6 +2192,11 @@
         for (i=0; i<kAudioChannels; i++)
                 korg1212->volumePhase[i] = 0;
 
+	if ((err = pci_request_regions(pci, "korg1212")) < 0) {
+		kfree(korg1212);
+		return err;
+	}
+
         korg1212->iomem = pci_resource_start(korg1212->pci, 0);
         korg1212->ioport = pci_resource_start(korg1212->pci, 1);
         korg1212->iomem2 = pci_resource_start(korg1212->pci, 2);
@@ -2252,27 +2217,6 @@
 		   stateName[korg1212->cardState]);
 #endif
 
-        korg1212->res_iomem = request_mem_region(korg1212->iomem, iomem_size, "korg1212");
-        if (korg1212->res_iomem == NULL) {
-		snd_printk(KERN_ERR "unable to grab region 0x%lx-0x%lx\n",
-                           korg1212->iomem, korg1212->iomem + iomem_size - 1);
-                return -EBUSY;
-        }
-
-        korg1212->res_ioport = request_region(korg1212->ioport, ioport_size, "korg1212");
-        if (korg1212->res_ioport == NULL) {
-		snd_printk(KERN_ERR "unable to grab region 0x%lx-0x%lx\n",
-                           korg1212->ioport, korg1212->ioport + ioport_size - 1);
-                return -EBUSY;
-        }
-
-        korg1212->res_iomem2 = request_mem_region(korg1212->iomem2, iomem2_size, "korg1212");
-        if (korg1212->res_iomem2 == NULL) {
-		snd_printk(KERN_ERR "unable to grab region 0x%lx-0x%lx\n",
-                           korg1212->iomem2, korg1212->iomem2 + iomem2_size - 1);
-                return -EBUSY;
-        }
-
         if ((korg1212->iobase = (unsigned long) ioremap(korg1212->iomem, iomem_size)) == 0) {
 		snd_printk(KERN_ERR "unable to remap memory region 0x%lx-0x%lx\n", korg1212->iobase,
                            korg1212->iobase + iomem_size - 1);
@@ -2329,11 +2273,8 @@
 		   stateName[korg1212->cardState]);
 #endif
 
-	memset(&korg1212->dma_dev, 0, sizeof(korg1212->dma_dev));
-	korg1212->dma_dev.type = SNDRV_DMA_TYPE_DEV;
-	korg1212->dma_dev.dev = snd_dma_pci_data(korg1212->pci);
-
-	if (snd_dma_alloc_pages(&korg1212->dma_dev, sizeof(KorgSharedBuffer), &korg1212->dma_shared) < 0) {
+	if (snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, snd_dma_pci_data(pci),
+				sizeof(KorgSharedBuffer), &korg1212->dma_shared) < 0) {
 		snd_printk(KERN_ERR "can not allocate shared buffer memory (%Zd bytes)\n", sizeof(KorgSharedBuffer));
                 return -ENOMEM;
         }
@@ -2348,7 +2289,8 @@
 
         korg1212->DataBufsSize = sizeof(KorgAudioBuffer) * kNumBuffers;
 
-	if (snd_dma_alloc_pages(&korg1212->dma_dev, korg1212->DataBufsSize, &korg1212->dma_play) < 0) {
+	if (snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, snd_dma_pci_data(pci),
+				korg1212->DataBufsSize, &korg1212->dma_play) < 0) {
 		snd_printk(KERN_ERR "can not allocate play data buffer memory (%d bytes)\n", korg1212->DataBufsSize);
                 return -ENOMEM;
         }
@@ -2360,7 +2302,8 @@
 		korg1212->playDataBufsPtr, korg1212->PlayDataPhy, korg1212->DataBufsSize);
 #endif
 
-	if (snd_dma_alloc_pages(&korg1212->dma_dev, korg1212->DataBufsSize, &korg1212->dma_rec) < 0) {
+	if (snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, snd_dma_pci_data(pci),
+				korg1212->DataBufsSize, &korg1212->dma_rec) < 0) {
 		snd_printk(KERN_ERR "can not allocate record data buffer memory (%d bytes)\n", korg1212->DataBufsSize);
                 return -ENOMEM;
         }
@@ -2390,7 +2333,8 @@
         korg1212->AdatTimeCodePhy = korg1212->sharedBufferPhy +
 		offsetof(KorgSharedBuffer, AdatTimeCode);
 
-	if (snd_dma_alloc_pages(&korg1212->dma_dev, korg1212->dspCodeSize, &korg1212->dma_dsp) < 0) {
+	if (snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, snd_dma_pci_data(pci),
+				korg1212->dspCodeSize, &korg1212->dma_dsp) < 0) {
 		snd_printk(KERN_ERR "can not allocate dsp code memory (%d bytes)\n", korg1212->dspCodeSize);
                 return -ENOMEM;
         }
@@ -2420,7 +2364,7 @@
                "VolumeTablePhy  = %08x L[%08x]\n"
                "RoutingTablePhy = %08x L[%08x]\n"
                "AdatTimeCodePhy = %08x L[%08x]\n",
-	       korg1212->dma_dsp.addr,    UpperWordSwap(korg1212->dma_dsp.addr),
+	       (int)korg1212->dma_dsp.addr,    UpperWordSwap(korg1212->dma_dsp.addr),
                korg1212->PlayDataPhy,     LowerWordSwap(korg1212->PlayDataPhy),
                korg1212->RecDataPhy,      LowerWordSwap(korg1212->RecDataPhy),
                korg1212->VolumeTablePhy,  LowerWordSwap(korg1212->VolumeTablePhy),
@@ -2443,7 +2387,7 @@
 	//snd_pcm_lib_preallocate_pages_for_all(korg1212->pcm,
 	//			K1212_MAX_BUF_SIZE, K1212_MAX_BUF_SIZE, GFP_KERNEL);
 
-        for (i = 0; i < K1212_CONTROL_ELEMENTS; i++) {
+        for (i = 0; i < ARRAY_SIZE(snd_korg1212_controls); i++) {
                 err = snd_ctl_add(korg1212->card, snd_ctl_new1(&snd_korg1212_controls[i], korg1212));
                 if (err < 0)
                         return err;
diff -Nru a/sound/pci/maestro3.c b/sound/pci/maestro3.c
--- a/sound/pci/maestro3.c	2004-10-18 14:56:33 -07:00
+++ b/sound/pci/maestro3.c	2004-10-18 14:56:33 -07:00
@@ -51,8 +51,7 @@
 MODULE_AUTHOR("Zach Brown <zab@zabbo.net>, Takashi Iwai <tiwai@suse.de>");
 MODULE_DESCRIPTION("ESS Maestro3 PCI");
 MODULE_LICENSE("GPL");
-MODULE_CLASSES("{sound}");
-MODULE_DEVICES("{{ESS,Maestro3 PCI},"
+MODULE_SUPPORTED_DEVICE("{{ESS,Maestro3 PCI},"
 		"{ESS,ES1988},"
 		"{ESS,Allegro PCI},"
 		"{ESS,Allegro-1 PCI},"
@@ -67,19 +66,14 @@
 
 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 this soundcard.");
-MODULE_PARM_SYNTAX(enable, SNDRV_ENABLE_DESC);
 module_param_array(external_amp, bool, boot_devs, 0444);
 MODULE_PARM_DESC(external_amp, "Enable external amp for " CARD_NAME " soundcard.");
-MODULE_PARM_SYNTAX(external_amp, SNDRV_ENABLED "," SNDRV_BOOLEAN_TRUE_DESC);
 module_param_array(amp_gpio, int, boot_devs, 0444);
 MODULE_PARM_DESC(amp_gpio, "GPIO pin number for external amp. (default = -1)");
-MODULE_PARM_SYNTAX(amp_gpio, SNDRV_ENABLED);
 
 #define MAX_PLAYBACKS	2
 #define MAX_CAPTURES	1
@@ -776,8 +770,6 @@
 
 typedef struct snd_m3_dma m3_dma_t;
 typedef struct snd_m3 m3_t;
-#define chip_t m3_t
-
 
 /* quirk lists */
 struct m3_quirk {
@@ -827,7 +819,6 @@
 	snd_card_t *card;
 
 	unsigned long iobase;
-	struct resource *iobase_res;
 
 	int irq;
 	int allegro_flag : 1;
@@ -1165,12 +1156,11 @@
 {
 	m3_t *chip = snd_pcm_substream_chip(subs);
 	m3_dma_t *s = (m3_dma_t*)subs->runtime->private_data;
-	unsigned long flags;
 	int err = -EINVAL;
 
 	snd_assert(s != NULL, return -ENXIO);
 
-	spin_lock_irqsave(&chip->reg_lock, flags);
+	spin_lock(&chip->reg_lock);
 	switch (cmd) {
 	case SNDRV_PCM_TRIGGER_START:
 	case SNDRV_PCM_TRIGGER_RESUME:
@@ -1191,7 +1181,7 @@
 		}
 		break;
 	}
-	spin_unlock_irqrestore(&chip->reg_lock, flags);
+	spin_unlock(&chip->reg_lock);
 	return err;
 }
 
@@ -1477,7 +1467,6 @@
 	m3_t *chip = snd_pcm_substream_chip(subs);
 	snd_pcm_runtime_t *runtime = subs->runtime;
 	m3_dma_t *s = (m3_dma_t*)runtime->private_data;
-	unsigned long flags;
 
 	snd_assert(s != NULL, return -ENXIO);
 
@@ -1488,7 +1477,7 @@
 	    runtime->rate < 8000)
 		return -EINVAL;
 
-	spin_lock_irqsave(&chip->reg_lock, flags);
+	spin_lock_irq(&chip->reg_lock);
 
 	snd_m3_pcm_setup1(chip, s, subs);
 
@@ -1499,7 +1488,7 @@
 
 	snd_m3_pcm_setup2(chip, s, runtime);
 
-	spin_unlock_irqrestore(&chip->reg_lock, flags);
+	spin_unlock_irq(&chip->reg_lock);
 
 	return 0;
 }
@@ -1573,7 +1562,7 @@
 static irqreturn_t
 snd_m3_interrupt(int irq, void *dev_id, struct pt_regs *regs)
 {
-	m3_t *chip = snd_magic_cast(m3_t, dev_id, );
+	m3_t *chip = dev_id;
 	u8 status;
 	int i;
 
@@ -1670,20 +1659,19 @@
 {
 	int i;
 	m3_dma_t *s;
-	unsigned long flags;
 
-	spin_lock_irqsave(&chip->reg_lock, flags);
+	spin_lock_irq(&chip->reg_lock);
 	for (i = 0; i < chip->num_substreams; i++) {
 		s = &chip->substreams[i];
 		if (! s->opened)
 			goto __found;
 	}
-	spin_unlock_irqrestore(&chip->reg_lock, flags);
+	spin_unlock_irq(&chip->reg_lock);
 	return -ENOMEM;
 __found:
 	s->opened = 1;
 	s->running = 0;
-	spin_unlock_irqrestore(&chip->reg_lock, flags);
+	spin_unlock_irq(&chip->reg_lock);
 
 	subs->runtime->private_data = s;
 	s->substream = subs;
@@ -1703,12 +1691,11 @@
 snd_m3_substream_close(m3_t *chip, snd_pcm_substream_t *subs)
 {
 	m3_dma_t *s = (m3_dma_t*) subs->runtime->private_data;
-	unsigned long flags;
 
 	if (s == NULL)
 		return; /* not opened properly */
 
-	spin_lock_irqsave(&chip->reg_lock, flags);
+	spin_lock_irq(&chip->reg_lock);
 	if (s->substream && s->running)
 		snd_m3_pcm_stop(chip, s, s->substream); /* does this happen? */
 	if (s->in_lists) {
@@ -1719,7 +1706,7 @@
 	}
 	s->running = 0;
 	s->opened = 0;
-	spin_unlock_irqrestore(&chip->reg_lock, flags);
+	spin_unlock_irq(&chip->reg_lock);
 }
 
 static int
@@ -1848,7 +1835,7 @@
 static unsigned short
 snd_m3_ac97_read(ac97_t *ac97, unsigned short reg)
 {
-	m3_t *chip = snd_magic_cast(m3_t, ac97->private_data, return -ENXIO);
+	m3_t *chip = ac97->private_data;
 	unsigned short ret = 0;
 	unsigned long flags;
 
@@ -1867,7 +1854,7 @@
 static void
 snd_m3_ac97_write(ac97_t *ac97, unsigned short reg, unsigned short val)
 {
-	m3_t *chip = snd_magic_cast(m3_t, ac97->private_data, return);
+	m3_t *chip = ac97->private_data;
 	unsigned long flags;
 
 	spin_lock_irqsave(&chip->reg_lock, flags);
@@ -1983,14 +1970,15 @@
 
 static int __devinit snd_m3_mixer(m3_t *chip)
 {
-	ac97_bus_t bus, *pbus;
-	ac97_t ac97;
+	ac97_bus_t *pbus;
+	ac97_template_t ac97;
 	int err;
+	static ac97_bus_ops_t ops = {
+		.write = snd_m3_ac97_write,
+		.read = snd_m3_ac97_read,
+	};
 
-	memset(&bus, 0, sizeof(bus));
-	bus.write = snd_m3_ac97_write;
-	bus.read = snd_m3_ac97_read;
-	if ((err = snd_ac97_bus(chip->card, &bus, &pbus)) < 0)
+	if ((err = snd_ac97_bus(chip->card, 0, &ops, NULL, &pbus)) < 0)
 		return err;
 	
 	memset(&ac97, 0, sizeof(ac97));
@@ -2167,7 +2155,7 @@
 			  KDATA_DMA_XFER0);
 
 	/* write kernel into code memory.. */
-	for (i = 0 ; i < sizeof(assp_kernel_image) / 2; i++) {
+	for (i = 0 ; i < ARRAY_SIZE(assp_kernel_image); i++) {
 		snd_m3_assp_write(chip, MEMTYPE_INTERNAL_CODE, 
 				  REV_B_CODE_MEMORY_BEGIN + i, 
 				  assp_kernel_image[i]);
@@ -2179,7 +2167,7 @@
 	 * drop it there.  It seems that the minisrc doesn't
 	 * need vectors, so we won't bother with them..
 	 */
-	for (i = 0; i < sizeof(assp_minisrc_image) / 2; i++) {
+	for (i = 0; i < ARRAY_SIZE(assp_minisrc_image); i++) {
 		snd_m3_assp_write(chip, MEMTYPE_INTERNAL_CODE, 
 				  0x400 + i, 
 				  assp_minisrc_image[i]);
@@ -2368,22 +2356,21 @@
 
 static int snd_m3_free(m3_t *chip)
 {
-	unsigned long flags;
 	m3_dma_t *s;
 	int i;
 
 	if (chip->substreams) {
-		spin_lock_irqsave(&chip->reg_lock, flags);
+		spin_lock_irq(&chip->reg_lock);
 		for (i = 0; i < chip->num_substreams; i++) {
 			s = &chip->substreams[i];
 			/* check surviving pcms; this should not happen though.. */
 			if (s->substream && s->running)
 				snd_m3_pcm_stop(chip, s, s->substream);
 		}
-		spin_unlock_irqrestore(&chip->reg_lock, flags);
+		spin_unlock_irq(&chip->reg_lock);
 		kfree(chip->substreams);
 	}
-	if (chip->iobase_res) {
+	if (chip->iobase) {
 		snd_m3_outw(chip, HOST_INT_CTRL, 0); /* disable ints */
 	}
 
@@ -2392,17 +2379,15 @@
 		vfree(chip->suspend_mem);
 #endif
 
-	if (chip->irq >= 0)
+	if (chip->irq >= 0) {
 		synchronize_irq(chip->irq);
-
-	if (chip->iobase_res) {
-		release_resource(chip->iobase_res);
-		kfree_nocheck(chip->iobase_res);
-	}
-	if (chip->irq >= 0)
 		free_irq(chip->irq, (void *)chip);
+	}
+
+	if (chip->iobase)
+		pci_release_regions(chip->pci);
 
-	snd_magic_kfree(chip);
+	kfree(chip);
 	return 0;
 }
 
@@ -2413,7 +2398,7 @@
 #ifdef CONFIG_PM
 static int m3_suspend(snd_card_t *card, unsigned int state)
 {
-	m3_t *chip = snd_magic_cast(m3_t, card->pm_private_data, return -EINVAL);
+	m3_t *chip = card->pm_private_data;
 	int i, index;
 
 	if (chip->suspend_mem == NULL)
@@ -2444,12 +2429,14 @@
 
 static int m3_resume(snd_card_t *card, unsigned int state)
 {
-	m3_t *chip = snd_magic_cast(m3_t, card->pm_private_data, return -EINVAL);
+	m3_t *chip = card->pm_private_data;
 	int i, index;
 
 	if (chip->suspend_mem == NULL)
 		return 0;
 
+	pci_set_master(chip->pci);
+
 	/* first lets just bring everything back. .*/
 	snd_m3_outw(chip, 0, 0x54);
 	snd_m3_outw(chip, 0, 0x56);
@@ -2489,7 +2476,7 @@
 
 static int snd_m3_dev_free(snd_device_t *device)
 {
-	m3_t *chip = snd_magic_cast(m3_t, device->device_data, return -ENXIO);
+	m3_t *chip = device->device_data;
 	return snd_m3_free(chip);
 }
 
@@ -2519,7 +2506,7 @@
 		return -ENXIO;
 	}
 
-	chip = snd_magic_kcalloc(m3_t, 0, GFP_KERNEL);
+	chip = kcalloc(1, sizeof(*chip), GFP_KERNEL);
 	if (chip == NULL)
 		return -ENOMEM;
 
@@ -2562,18 +2549,16 @@
 	chip->num_substreams = NR_DSPS;
 	chip->substreams = kmalloc(sizeof(m3_dma_t) * chip->num_substreams, GFP_KERNEL);
 	if (chip->substreams == NULL) {
-		snd_magic_kfree(chip);
+		kfree(chip);
 		return -ENOMEM;
 	}
 	memset(chip->substreams, 0, sizeof(m3_dma_t) * chip->num_substreams);
 
-	chip->iobase = pci_resource_start(pci, 0);
-	if ((chip->iobase_res = request_region(chip->iobase, 256,
-					       card->driver)) == NULL) {
-		snd_printk("unable to grab i/o ports %ld\n", chip->iobase);
+	if ((err = pci_request_regions(pci, card->driver)) < 0) {
 		snd_m3_free(chip);
-		return -EBUSY;
+		return err;
 	}
+	chip->iobase = pci_resource_start(pci, 0);
 	
 	/* just to be sure */
 	pci_set_master(pci);
diff -Nru a/sound/pci/mixart/mixart.c b/sound/pci/mixart/mixart.c
--- a/sound/pci/mixart/mixart.c	2004-10-18 14:56:48 -07:00
+++ b/sound/pci/mixart/mixart.c	2004-10-18 14:56:48 -07:00
@@ -42,25 +42,19 @@
 MODULE_AUTHOR("Digigram <alsa@digigram.com>");
 MODULE_DESCRIPTION("Digigram " CARD_NAME);
 MODULE_LICENSE("GPL");
-MODULE_CLASSES("{sound}");
-MODULE_DEVICES("{{Digigram," CARD_NAME "}}");
+MODULE_SUPPORTED_DEVICE("{{Digigram," CARD_NAME "}}");
 
 static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX;             /* Index 0-MAX */
 static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR;              /* ID for this card */
 static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP;     /* Enable this card */
 static int boot_devs;
 
-#define chip_t mixart_t
-
 module_param_array(index, int, boot_devs, 0444);
 MODULE_PARM_DESC(index, "Index value for Digigram " 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 Digigram " CARD_NAME " soundcard.");
-MODULE_PARM_SYNTAX(id, SNDRV_ID_DESC);
 module_param_array(enable, bool, boot_devs, 0444);
 MODULE_PARM_DESC(enable, "Enable Digigram " CARD_NAME " soundcard.");
-MODULE_PARM_SYNTAX(enable, SNDRV_ENABLE_DESC);
 
 /*
  */
@@ -247,21 +241,27 @@
 	/* pipe is not yet defined */
 	if( pipe->status == PIPE_UNDEFINED ) {
 		int err, i;
-		mixart_streaming_group_t streaming_group_resp;
-		mixart_streaming_group_req_t streaming_group_req;
+		struct {
+			mixart_streaming_group_req_t sgroup_req;
+			mixart_streaming_group_t sgroup_resp;
+		} *buf;
 
 		snd_printdd("add_ref_pipe audio chip(%d) pcm(%d)\n", chip->chip_idx, pcm_number);
 
+		buf = kmalloc(sizeof(*buf), GFP_KERNEL);
+		if (!buf)
+			return NULL;
+
 		request.uid = (mixart_uid_t){0,0};      /* should be StreamManagerUID, but zero is OK if there is only one ! */
-		request.data = &streaming_group_req;
-		request.size = sizeof(streaming_group_req);
+		request.data = &buf->sgroup_req;
+		request.size = sizeof(buf->sgroup_req);
 
-		memset(&streaming_group_req, 0, sizeof(streaming_group_req));
+		memset(&buf->sgroup_req, 0, sizeof(buf->sgroup_req));
 
-		streaming_group_req.stream_count = stream_count;
-		streaming_group_req.channel_count = 2;
-		streaming_group_req.latency = 256;
-		streaming_group_req.connector = pipe->uid_left_connector;  /* the left connector */
+		buf->sgroup_req.stream_count = stream_count;
+		buf->sgroup_req.channel_count = 2;
+		buf->sgroup_req.latency = 256;
+		buf->sgroup_req.connector = pipe->uid_left_connector;  /* the left connector */
 
 		for (i=0; i<stream_count; i++) {
 			int j;
@@ -269,15 +269,15 @@
 			struct mixart_bufferinfo *bufferinfo;
 			
 			/* we don't yet know the format, so config 16 bit pcm audio for instance */
-			streaming_group_req.stream_info[i].size_max_byte_frame = 1024;
-			streaming_group_req.stream_info[i].size_max_sample_frame = 256;
-			streaming_group_req.stream_info[i].nb_bytes_max_per_sample = MIXART_FLOAT_P__4_0_TO_HEX; /* is 4.0f */
+			buf->sgroup_req.stream_info[i].size_max_byte_frame = 1024;
+			buf->sgroup_req.stream_info[i].size_max_sample_frame = 256;
+			buf->sgroup_req.stream_info[i].nb_bytes_max_per_sample = MIXART_FLOAT_P__4_0_TO_HEX; /* is 4.0f */
 
 			/* find the right bufferinfo_array */
 			j = (chip->chip_idx * MIXART_MAX_STREAM_PER_CARD) + (pcm_number * (MIXART_PLAYBACK_STREAMS + MIXART_CAPTURE_STREAMS)) + i;
 			if(capture) j += MIXART_PLAYBACK_STREAMS; /* in the array capture is behind playback */
 
-			streaming_group_req.flow_entry[i] = j;
+			buf->sgroup_req.flow_entry[i] = j;
 
 			flowinfo = (struct mixart_flowinfo *)chip->mgr->flowinfo.area;
 			flowinfo[j].bufferinfo_array_phy_address = (u32)chip->mgr->bufferinfo.addr + (j * sizeof(mixart_bufferinfo_t));
@@ -294,17 +294,19 @@
 			}
 		}
 
-		err = snd_mixart_send_msg(chip->mgr, &request, sizeof(streaming_group_resp), &streaming_group_resp);
-		if((err < 0) || (streaming_group_resp.status != 0)) {
-			snd_printk(KERN_ERR "error MSG_STREAM_ADD_**PUT_GROUP err=%x stat=%x !\n", err, streaming_group_resp.status);
+		err = snd_mixart_send_msg(chip->mgr, &request, sizeof(buf->sgroup_resp), &buf->sgroup_resp);
+		if((err < 0) || (buf->sgroup_resp.status != 0)) {
+			snd_printk(KERN_ERR "error MSG_STREAM_ADD_**PUT_GROUP err=%x stat=%x !\n", err, buf->sgroup_resp.status);
+			kfree(buf);
 			return NULL;
 		}
 
-		pipe->group_uid = streaming_group_resp.group;     /* id of the pipe, as returned by embedded */
-		pipe->stream_count = streaming_group_resp.stream_count;
-		/* pipe->stream_uid[i] = streaming_group_resp.stream[i].stream_uid; */
+		pipe->group_uid = buf->sgroup_resp.group;     /* id of the pipe, as returned by embedded */
+		pipe->stream_count = buf->sgroup_resp.stream_count;
+		/* pipe->stream_uid[i] = buf->sgroup_resp.stream[i].stream_uid; */
 
 		pipe->status = PIPE_STOPPED;
+		kfree(buf);
 	}
 
 	if(monitoring)	pipe->monitoring = 1;
@@ -458,8 +460,6 @@
 
 /*
  *  prepare callback for all pcms
- *
- *  NOTE: this callback is non-atomic (pcm->info_flags |= SNDRV_PCM_INFO_NONATOMIC_OPS)
  */
 static int snd_mixart_prepare(snd_pcm_substream_t *subs)
 {
@@ -620,7 +620,10 @@
 		bufferinfo[i].available_length = subs->runtime->dma_bytes;
 		/* bufferinfo[i].buffer_id  is already defined */
 
-		snd_printdd("snd_mixart_hw_params(pcm %d) : dma_addr(%x) dma_bytes(%x) subs-number(%d)\n", i, subs->runtime->dma_addr, subs->runtime->dma_bytes, subs->number);
+		snd_printdd("snd_mixart_hw_params(pcm %d) : dma_addr(%x) dma_bytes(%x) subs-number(%d)\n", i,
+				bufferinfo[i].buffer_address,
+				bufferinfo[i].available_length,
+				subs->number);
 	}
 	up(&mgr->setup_mutex);
 
@@ -901,6 +904,7 @@
 
 static void preallocate_buffers(mixart_t *chip, snd_pcm_t *pcm)
 {
+#if 0
 	snd_pcm_substream_t *subs;
 	int stream;
 
@@ -912,6 +916,7 @@
 				subs->stream << 8 | (subs->number + 1) |
 				(chip->chip_idx + 1) << 24;
 	}
+#endif
 	snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV,
 					      snd_dma_pci_data(chip->mgr->pci), 32*1024, 32*1024);
 }
@@ -937,7 +942,7 @@
 	snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_mixart_playback_ops);
 	snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_mixart_capture_ops);
 
-	pcm->info_flags = SNDRV_PCM_INFO_NONATOMIC_OPS;
+	pcm->info_flags = 0;
 	strcpy(pcm->name, name);
 
 	preallocate_buffers(chip, pcm);
@@ -968,7 +973,7 @@
 	snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_mixart_playback_ops);
 	snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_mixart_capture_ops);
 
-	pcm->info_flags = SNDRV_PCM_INFO_NONATOMIC_OPS;
+	pcm->info_flags = 0;
 	strcpy(pcm->name, name);
 
 	preallocate_buffers(chip, pcm);
@@ -979,13 +984,13 @@
 
 static int snd_mixart_chip_free(mixart_t *chip)
 {
-	snd_magic_kfree(chip);
+	kfree(chip);
 	return 0;
 }
 
 static int snd_mixart_chip_dev_free(snd_device_t *device)
 {
-	mixart_t *chip = snd_magic_cast(mixart_t, device->device_data, return -ENXIO);
+	mixart_t *chip = device->device_data;
 	return snd_mixart_chip_free(chip);
 }
 
@@ -1000,7 +1005,7 @@
 		.dev_free = snd_mixart_chip_dev_free,
 	};
 
-	mgr->chip[idx] = chip = snd_magic_kcalloc(mixart_t, 0, GFP_KERNEL);
+	mgr->chip[idx] = chip = kcalloc(1, sizeof(*chip), GFP_KERNEL);
 	if (! chip) {
 		snd_printk(KERN_ERR "cannot allocate chip\n");
 		return -ENOMEM;
@@ -1074,24 +1079,21 @@
 	for (i = 0; i < 2; i++) {
 		if (mgr->mem[i].virt)
 			iounmap((void *)mgr->mem[i].virt);
-		if (mgr->mem[i].res) {
-			release_resource(mgr->mem[i].res);
-			kfree_nocheck(mgr->mem[i].res);
-		}
 	}
+	pci_release_regions(mgr->pci);
 
 	/* free flowarray */
 	if(mgr->flowinfo.area) {
-		snd_dma_free_pages(&mgr->dma_dev, &mgr->flowinfo);
+		snd_dma_free_pages(&mgr->flowinfo);
 		mgr->flowinfo.area = NULL;
 	}
 	/* free bufferarray */
 	if(mgr->bufferinfo.area) {
-		snd_dma_free_pages(&mgr->dma_dev, &mgr->bufferinfo);
+		snd_dma_free_pages(&mgr->bufferinfo);
 		mgr->bufferinfo.area = NULL;
 	}
 
-	snd_magic_kfree(mgr);
+	kfree(mgr);
 	return 0;
 }
 
@@ -1157,7 +1159,7 @@
 				struct file *file, char __user *buf,
 				unsigned long count, unsigned long pos)
 {
-	mixart_mgr_t *mgr = snd_magic_cast(mixart_mgr_t, entry->private_data, return -ENXIO);
+	mixart_mgr_t *mgr = entry->private_data;
 
 	count = count & ~3; /* make sure the read size is a multiple of 4 bytes */
 	if(count <= 0)
@@ -1176,7 +1178,7 @@
 				struct file *file, char __user *buf,
 				unsigned long count, unsigned long pos)
 {
-	mixart_mgr_t *mgr = snd_magic_cast(mixart_mgr_t, entry->private_data, return -ENXIO);
+	mixart_mgr_t *mgr = entry->private_data;
 
 	count = count & ~3; /* make sure the read size is a multiple of 4 bytes */
 	if(count <= 0)
@@ -1202,7 +1204,7 @@
 static void snd_mixart_proc_read(snd_info_entry_t *entry, 
                                  snd_info_buffer_t * buffer)
 {
-	mixart_t *chip = snd_magic_cast(mixart_t, entry->private_data, return);        
+	mixart_t *chip = entry->private_data;        
 	u32 ref; 
 
 	snd_iprintf(buffer, "Digigram miXart (alsa card %d)\n\n", chip->chip_idx);
@@ -1289,15 +1291,14 @@
 	pci_set_master(pci);
 
 	/* check if we can restrict PCI DMA transfers to 32 bits */
-	if (!pci_dma_supported(pci, 0xffffffff)) {
+	if (pci_set_dma_mask(pci, 0xffffffff) < 0) {
 		snd_printk(KERN_ERR "architecture does not support 32bit PCI busmaster DMA\n");
 		return -ENXIO;
 	}
-	pci_set_dma_mask(pci, 0xffffffff);
 
 	/*
 	 */
-	mgr = snd_magic_kcalloc(mixart_mgr_t, 0, GFP_KERNEL);
+	mgr = kcalloc(1, sizeof(*mgr), GFP_KERNEL);
 	if (! mgr)
 		return -ENOMEM;
 
@@ -1305,19 +1306,14 @@
 	mgr->irq = -1;
 
 	/* resource assignment */
+	if ((err = pci_request_regions(pci, CARD_NAME)) < 0) {
+		kfree(mgr);
+		return err;
+	}
 	for (i = 0; i < 2; i++) {
-		static int memory_sizes[2] = {
-			MIXART_BA0_SIZE, /* 16M */	  
-			MIXART_BA1_SIZE  /* 4 k */
-		};
 		mgr->mem[i].phys = pci_resource_start(pci, i);
-		mgr->mem[i].res = request_mem_region(mgr->mem[i].phys, memory_sizes[i], CARD_NAME);
-		if (! mgr->mem[i].res) {
-			snd_printk(KERN_ERR "unable to grab memory 0x%lx\n", mgr->mem[i].phys);
-			snd_mixart_free(mgr);
-			return -EBUSY;
-		}
-		mgr->mem[i].virt = (unsigned long)ioremap_nocache(mgr->mem[i].phys, memory_sizes[i]);
+		mgr->mem[i].virt = (unsigned long)ioremap_nocache(mgr->mem[i].phys,
+								  pci_resource_len(pci, i));
 	}
 
 	if (request_irq(pci->irq, snd_mixart_interrupt, SA_INTERRUPT|SA_SHIRQ, CARD_NAME, (void *)mgr)) {
@@ -1331,13 +1327,13 @@
 	sprintf(mgr->longname, "%s at 0x%lx & 0x%lx, irq %i", mgr->shortname, mgr->mem[0].phys, mgr->mem[1].phys, mgr->irq);
 
 	/* ISR spinlock  */
-	mgr->lock = SPIN_LOCK_UNLOCKED;
+	spin_lock_init(&mgr->lock);
 
 	/* init mailbox  */
 	mgr->msg_fifo_readptr = 0;
 	mgr->msg_fifo_writeptr = 0;
 
-	mgr->msg_lock = SPIN_LOCK_UNLOCKED;
+	spin_lock_init(&mgr->msg_lock);
 	init_MUTEX(&mgr->msg_mutex);
 	init_waitqueue_head(&mgr->msg_sleep);
 	atomic_set(&mgr->msg_processed, 0);
@@ -1391,13 +1387,10 @@
 	/* init firmware status (mgr->hwdep->dsp_loaded reset in hwdep_new) */
 	mgr->board_type = MIXART_DAUGHTER_TYPE_NONE;
 
-	memset(&mgr->dma_dev, 0, sizeof(mgr->dma_dev));
-	mgr->dma_dev.type = SNDRV_DMA_TYPE_DEV;
-	mgr->dma_dev.dev = snd_dma_pci_data(mgr->pci);
-
 	/* create array of streaminfo */
 	size = PAGE_ALIGN( (MIXART_MAX_STREAM_PER_CARD * MIXART_MAX_CARDS * sizeof(mixart_flowinfo_t)) );
-	if (snd_dma_alloc_pages(&mgr->dma_dev, size, &mgr->flowinfo) < 0) {
+	if (snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, snd_dma_pci_data(pci),
+				size, &mgr->flowinfo) < 0) {
 		snd_mixart_free(mgr);
 		return -ENOMEM;
 	}
@@ -1406,7 +1399,8 @@
 
 	/* create array of bufferinfo */
 	size = PAGE_ALIGN( (MIXART_MAX_STREAM_PER_CARD * MIXART_MAX_CARDS * sizeof(mixart_bufferinfo_t)) );
-	if (snd_dma_alloc_pages(&mgr->dma_dev, size, &mgr->bufferinfo) < 0) {
+	if (snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, snd_dma_pci_data(pci),
+				size, &mgr->bufferinfo) < 0) {
 		snd_mixart_free(mgr);
 		return -ENOMEM;
 	}
diff -Nru a/sound/pci/mixart/mixart.h b/sound/pci/mixart/mixart.h
--- a/sound/pci/mixart/mixart.h	2004-10-18 14:55:54 -07:00
+++ b/sound/pci/mixart/mixart.h	2004-10-18 14:55:54 -07:00
@@ -115,7 +115,6 @@
 	snd_hwdep_t *hwdep;
 	unsigned int board_type;      /* read from embedded once elf file is loaded, 250 = miXart8, 251 = with AES, 252 = with Cobranet */
 
-	struct snd_dma_device dma_dev;
 	struct snd_dma_buffer flowinfo;
 	struct snd_dma_buffer bufferinfo;
 
diff -Nru a/sound/pci/mixart/mixart_core.c b/sound/pci/mixart/mixart_core.c
--- a/sound/pci/mixart/mixart_core.c	2004-10-18 14:57:04 -07:00
+++ b/sound/pci/mixart/mixart_core.c	2004-10-18 14:57:04 -07:00
@@ -379,7 +379,7 @@
 					snd_printk(KERN_ERR "tasklet : error MSG_STREAM_ST***_***PUT_STAGE_PACKET status=%x\n", mixart_msg_data[0]);
 				break;
 			default:
-				snd_printdd("tasklet received mf(%x) : msg_id(%x) uid(%x, %x) size(%d)\n",
+				snd_printdd("tasklet received mf(%x) : msg_id(%x) uid(%x, %x) size(%zd)\n",
 					   msg, resp.message_id, resp.uid.object_id, resp.uid.desc, resp.size);
 				break;
 			}
@@ -403,7 +403,7 @@
 
 irqreturn_t snd_mixart_interrupt(int irq, void *dev_id, struct pt_regs *regs)
 {
-	mixart_mgr_t *mgr = snd_magic_cast(mixart_mgr_t, dev_id, return IRQ_NONE);
+	mixart_mgr_t *mgr = dev_id;
 	int err;
 	mixart_msg_t resp;
 
diff -Nru a/sound/pci/mixart/mixart_hwdep.c b/sound/pci/mixart/mixart_hwdep.c
--- a/sound/pci/mixart/mixart_hwdep.c	2004-10-18 14:57:18 -07:00
+++ b/sound/pci/mixart/mixart_hwdep.c	2004-10-18 14:57:18 -07:00
@@ -146,7 +146,7 @@
 
 static int mixart_hwdep_dsp_status(snd_hwdep_t *hw, snd_hwdep_dsp_status_t *info)
 {
-	mixart_mgr_t *mgr = snd_magic_cast(mixart_mgr_t, hw->private_data, return -ENXIO);
+	mixart_mgr_t *mgr = hw->private_data;
 
 	strcpy(info->id, "miXart");
         info->num_dsps = MIXART_HARDW_FILES_MAX_INDEX;
@@ -346,7 +346,7 @@
 
 static int mixart_hwdep_dsp_load(snd_hwdep_t *hw, snd_hwdep_dsp_image_t *dsp)
 {
-	mixart_mgr_t* mgr = snd_magic_cast(mixart_mgr_t, hw->private_data, return -ENXIO);
+	mixart_mgr_t* mgr = hw->private_data;
 	int           err, card_index;
 	u32           status_xilinx, status_elf, status_daught;
 	u32           val;
diff -Nru a/sound/pci/mixart/mixart_mixer.c b/sound/pci/mixart/mixart_mixer.c
--- a/sound/pci/mixart/mixart_mixer.c	2004-10-18 14:56:29 -07:00
+++ b/sound/pci/mixart/mixart_mixer.c	2004-10-18 14:56:29 -07:00
@@ -31,8 +31,6 @@
 #include <sound/control.h>
 #include "mixart_mixer.h"
 
-#define chip_t mixart_t
-
 static u32 mixart_analog_level[256] = {
 	0xc2c00000,		/* [000] -96.0 dB */
 	0xc2bf0000,		/* [001] -95.5 dB */
diff -Nru a/sound/pci/nm256/nm256.c b/sound/pci/nm256/nm256.c
--- a/sound/pci/nm256/nm256.c	2004-10-18 14:56:50 -07:00
+++ b/sound/pci/nm256/nm256.c	2004-10-18 14:56:50 -07:00
@@ -45,8 +45,7 @@
 MODULE_AUTHOR("Takashi Iwai <tiwai@suse.de>");
 MODULE_DESCRIPTION("NeoMagic NM256AV/ZX");
 MODULE_LICENSE("GPL");
-MODULE_CLASSES("{sound}");
-MODULE_DEVICES("{{NeoMagic,NM256AV},"
+MODULE_SUPPORTED_DEVICE("{{NeoMagic,NM256AV},"
 		"{NeoMagic,NM256ZX}}");
 
 /*
@@ -66,31 +65,22 @@
 
 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 this soundcard.");
-MODULE_PARM_SYNTAX(enable, SNDRV_ENABLE_DESC);
 module_param_array(playback_bufsize, int, boot_devs, 0444);
 MODULE_PARM_DESC(playback_bufsize, "DAC frame size in kB for " CARD_NAME " soundcard.");
-MODULE_PARM_SYNTAX(playback_bufsize, SNDRV_ENABLED);
 module_param_array(capture_bufsize, int, boot_devs, 0444);
 MODULE_PARM_DESC(capture_bufsize, "ADC frame size in kB for " CARD_NAME " soundcard.");
-MODULE_PARM_SYNTAX(capture_bufsize, SNDRV_ENABLED);
 module_param_array(force_ac97, bool, boot_devs, 0444);
 MODULE_PARM_DESC(force_ac97, "Force to use AC97 codec for " CARD_NAME " soundcard.");
-MODULE_PARM_SYNTAX(force_ac97, SNDRV_ENABLED "," SNDRV_BOOLEAN_FALSE_DESC);
 module_param_array(buffer_top, int, boot_devs, 0444);
 MODULE_PARM_DESC(buffer_top, "Set the top address of audio buffer for " CARD_NAME " soundcard.");
-MODULE_PARM_SYNTAX(buffer_top, SNDRV_ENABLED);
 module_param_array(use_cache, bool, boot_devs, 0444);
 MODULE_PARM_DESC(use_cache, "Enable the cache for coefficient table access.");
-MODULE_PARM_SYNTAX(use_cache, SNDRV_ENABLED "," SNDRV_BOOLEAN_FALSE_DESC);
 module_param_array(vaio_hack, bool, boot_devs, 0444);
 MODULE_PARM_DESC(vaio_hack, "Enable workaround for Sony VAIO notebooks.");
-MODULE_PARM_SYNTAX(vaio_hack, SNDRV_ENABLED "," SNDRV_BOOLEAN_FALSE_DESC);
 
 /*
  * hw definitions
@@ -191,7 +181,6 @@
 
 typedef struct snd_nm256 nm256_t;
 typedef struct snd_nm256_stream nm256_stream_t;
-#define chip_t nm256_t
 
 struct snd_nm256_stream {
 
@@ -414,9 +403,8 @@
 static unsigned int samplerates[8] = {
 	8000, 11025, 16000, 22050, 24000, 32000, 44100, 48000,
 };
-#define NUM_SAMPLERATES (sizeof(samplerates) / sizeof(samplerates[0]))
 static snd_pcm_hw_constraint_list_t constraints_rates = {
-	.count = NUM_SAMPLERATES, 
+	.count = ARRAY_SIZE(samplerates), 
 	.list = samplerates,
 	.mask = 0,
 };
@@ -428,7 +416,7 @@
 snd_nm256_fixed_rate(unsigned int rate)
 {
 	unsigned int i;
-	for (i = 0; i < NUM_SAMPLERATES; i++) {
+	for (i = 0; i < ARRAY_SIZE(samplerates); i++) {
 		if (rate == samplerates[i])
 			return i;
 	}
@@ -542,12 +530,11 @@
 {
 	nm256_t *chip = snd_pcm_substream_chip(substream);
 	nm256_stream_t *s = (nm256_stream_t*)substream->runtime->private_data;
-	unsigned long flags;
 	int err = 0;
 
 	snd_assert(s != NULL, return -ENXIO);
 
-	spin_lock_irqsave(&chip->reg_lock, flags);
+	spin_lock(&chip->reg_lock);
 	switch (cmd) {
 	case SNDRV_PCM_TRIGGER_START:
 	case SNDRV_PCM_TRIGGER_RESUME:
@@ -567,7 +554,7 @@
 		err = -EINVAL;
 		break;
 	}
-	spin_unlock_irqrestore(&chip->reg_lock, flags);
+	spin_unlock(&chip->reg_lock);
 	return err;
 }
 
@@ -576,12 +563,11 @@
 {
 	nm256_t *chip = snd_pcm_substream_chip(substream);
 	nm256_stream_t *s = (nm256_stream_t*)substream->runtime->private_data;
-	unsigned long flags;
 	int err = 0;
 
 	snd_assert(s != NULL, return -ENXIO);
 
-	spin_lock_irqsave(&chip->reg_lock, flags);
+	spin_lock(&chip->reg_lock);
 	switch (cmd) {
 	case SNDRV_PCM_TRIGGER_START:
 	case SNDRV_PCM_TRIGGER_RESUME:
@@ -601,7 +587,7 @@
 		err = -EINVAL;
 		break;
 	}
-	spin_unlock_irqrestore(&chip->reg_lock, flags);
+	spin_unlock(&chip->reg_lock);
 	return err;
 }
 
@@ -614,7 +600,6 @@
 	nm256_t *chip = snd_pcm_substream_chip(substream);
 	snd_pcm_runtime_t *runtime = substream->runtime;
 	nm256_stream_t *s = (nm256_stream_t*)runtime->private_data;
-	unsigned long flags;
 
 	snd_assert(s, return -ENXIO);
 	s->dma_size = frames_to_bytes(runtime, substream->runtime->buffer_size);
@@ -622,10 +607,10 @@
 	s->periods = substream->runtime->periods;
 	s->cur_period = 0;
 
-	spin_lock_irqsave(&chip->reg_lock, flags);
+	spin_lock_irq(&chip->reg_lock);
 	s->running = 0;
 	snd_nm256_set_format(chip, s, substream);
-	spin_unlock_irqrestore(&chip->reg_lock, flags);
+	spin_unlock_irq(&chip->reg_lock);
 
 	return 0;
 }
@@ -660,9 +645,9 @@
 	return bytes_to_frames(substream->runtime, curp);
 }
 
+/* Remapped I/O space can be accessible as pointer on i386 */
+/* This might be changed in the future */
 #ifndef __i386__
-/* FIXME: I/O space is not accessible via pointers on all architectures */
-
 /*
  * silence / copy for playback
  */
@@ -757,10 +742,7 @@
  */
 static snd_pcm_hardware_t snd_nm256_playback =
 {
-	.info =
-#ifdef __i386__
-				SNDRV_PCM_INFO_MMAP|SNDRV_PCM_INFO_MMAP_VALID|
-#endif
+	.info =			SNDRV_PCM_INFO_MMAP_IOMEM |SNDRV_PCM_INFO_MMAP_VALID |
 				SNDRV_PCM_INFO_INTERLEAVED |
 				/*SNDRV_PCM_INFO_PAUSE |*/
 				SNDRV_PCM_INFO_RESUME,
@@ -779,10 +761,7 @@
 
 static snd_pcm_hardware_t snd_nm256_capture =
 {
-	.info =
-#ifdef __i386__
-				SNDRV_PCM_INFO_MMAP|SNDRV_PCM_INFO_MMAP_VALID|
-#endif
+	.info =			SNDRV_PCM_INFO_MMAP_IOMEM | SNDRV_PCM_INFO_MMAP_VALID |
 				SNDRV_PCM_INFO_INTERLEAVED |
 				/*SNDRV_PCM_INFO_PAUSE |*/
 				SNDRV_PCM_INFO_RESUME,
@@ -883,6 +862,7 @@
 	.copy =		snd_nm256_playback_copy,
 	.silence =	snd_nm256_playback_silence,
 #endif
+	.mmap =		snd_pcm_lib_mmap_iomem,
 };
 
 static snd_pcm_ops_t snd_nm256_capture_ops = {
@@ -896,6 +876,7 @@
 #ifndef __i386__
 	.copy =		snd_nm256_capture_copy,
 #endif
+	.mmap =		snd_pcm_lib_mmap_iomem,
 };
 
 static int __devinit
@@ -932,16 +913,14 @@
 static void
 snd_nm256_init_chip(nm256_t *chip)
 {
-	unsigned long flags;
-
-	spin_lock_irqsave(&chip->reg_lock, flags);
+	spin_lock_irq(&chip->reg_lock);
 	/* Reset everything. */
 	snd_nm256_writeb(chip, 0x0, 0x11);
 	snd_nm256_writew(chip, 0x214, 0);
 	/* stop sounds.. */
 	//snd_nm256_playback_stop(chip);
 	//snd_nm256_capture_stop(chip);
-	spin_unlock_irqrestore(&chip->reg_lock, flags);
+	spin_unlock_irq(&chip->reg_lock);
 }
 
 
@@ -981,7 +960,7 @@
 static irqreturn_t
 snd_nm256_interrupt(int irq, void *dev_id, struct pt_regs *dummy)
 {
-	nm256_t *chip = snd_magic_cast(nm256_t, dev_id, return IRQ_NONE);
+	nm256_t *chip = dev_id;
 	u16 status;
 	u8 cbyte;
 
@@ -1048,7 +1027,7 @@
 static irqreturn_t
 snd_nm256_interrupt_zx(int irq, void *dev_id, struct pt_regs *dummy)
 {
-	nm256_t *chip = snd_magic_cast(nm256_t, dev_id, return IRQ_NONE);
+	nm256_t *chip = dev_id;
 	u32 status;
 	u8 cbyte;
 
@@ -1139,7 +1118,7 @@
 static unsigned short
 snd_nm256_ac97_read(ac97_t *ac97, unsigned short reg)
 {
-	nm256_t *chip = snd_magic_cast(nm256_t, ac97->private_data, return -ENXIO);
+	nm256_t *chip = ac97->private_data;
 	int res;
 
 	if (reg >= 128)
@@ -1159,7 +1138,7 @@
 snd_nm256_ac97_write(ac97_t *ac97,
 		     unsigned short reg, unsigned short val)
 {
-	nm256_t *chip = snd_magic_cast(nm256_t, ac97->private_data, return);
+	nm256_t *chip = ac97->private_data;
 	int tries = 2;
 	u32 base;
 
@@ -1181,10 +1160,9 @@
 static void
 snd_nm256_ac97_reset(ac97_t *ac97)
 {
-	nm256_t *chip = snd_magic_cast(nm256_t, ac97->private_data, return);
-	unsigned long flags;
+	nm256_t *chip = ac97->private_data;
 
-	spin_lock_irqsave(&chip->reg_lock, flags);
+	spin_lock(&chip->reg_lock);
 	/* Reset the mixer.  'Tis magic!  */
 	snd_nm256_writeb(chip, 0x6c0, 1);
 	if (chip->latitude_workaround) {
@@ -1193,20 +1171,25 @@
 	}
 	snd_nm256_writeb(chip, 0x6cc, 0x80);
 	snd_nm256_writeb(chip, 0x6cc, 0x0);
-	spin_unlock_irqrestore(&chip->reg_lock, flags);
+	spin_unlock(&chip->reg_lock);
 }
 
 /* create an ac97 mixer interface */
 static int __devinit
 snd_nm256_mixer(nm256_t *chip)
 {
-	ac97_bus_t bus, *pbus;
-	ac97_t ac97;
+	ac97_bus_t *pbus;
+	ac97_template_t ac97;
 	int i, err;
+	static ac97_bus_ops_t ops = {
+		.reset = snd_nm256_ac97_reset,
+		.write = snd_nm256_ac97_write,
+		.read = snd_nm256_ac97_read,
+	};
 	/* looks like nm256 hangs up when unexpected registers are touched... */
 	static int mixer_regs[] = {
 		AC97_MASTER, AC97_HEADPHONE, AC97_MASTER_MONO,
-		AC97_PC_BEEP, AC97_PHONE, AC97_MIC, AC97_LINE,
+		AC97_PC_BEEP, AC97_PHONE, AC97_MIC, AC97_LINE, AC97_CD,
 		AC97_VIDEO, AC97_AUX, AC97_PCM, AC97_REC_SEL,
 		AC97_REC_GAIN, AC97_GENERAL_PURPOSE, AC97_3D_CONTROL,
 		AC97_EXTENDED_ID,
@@ -1214,11 +1197,7 @@
 		-1
 	};
 
-	memset(&bus, 0, sizeof(bus));
-	bus.reset = snd_nm256_ac97_reset;
-	bus.write = snd_nm256_ac97_write;
-	bus.read = snd_nm256_ac97_read;
-	if ((err = snd_ac97_bus(chip->card, &bus, &pbus)) < 0)
+	if ((err = snd_ac97_bus(chip->card, 0, &ops, NULL, &pbus)) < 0)
 		return err;
 
 	memset(&ac97, 0, sizeof(ac97));
@@ -1290,7 +1269,7 @@
  */
 static int nm256_suspend(snd_card_t *card, unsigned int state)
 {
-	nm256_t *chip = snd_magic_cast(nm256_t, card->pm_private_data, return -EINVAL);
+	nm256_t *chip = card->pm_private_data;
 
 	snd_pcm_suspend_all(chip->pcm);
 	snd_ac97_suspend(chip->ac97);
@@ -1301,7 +1280,7 @@
 
 static int nm256_resume(snd_card_t *card, unsigned int state)
 {
-	nm256_t *chip = snd_magic_cast(nm256_t, card->pm_private_data, return -EINVAL);
+	nm256_t *chip = card->pm_private_data;
 
 	/* Perform a full reset on the hardware */
 	pci_enable_device(chip->pci);
@@ -1340,13 +1319,13 @@
 	if (chip->irq >= 0)
 		free_irq(chip->irq, (void*)chip);
 
-	snd_magic_kfree(chip);
+	kfree(chip);
 	return 0;
 }
 
 static int snd_nm256_dev_free(snd_device_t *device)
 {
-	nm256_t *chip = snd_magic_cast(nm256_t, device->device_data, return -ENXIO);
+	nm256_t *chip = device->device_data;
 	return snd_nm256_free(chip);
 }
 
@@ -1368,7 +1347,7 @@
 
 	*chip_ret = NULL;
 
-	chip = snd_magic_kcalloc(nm256_t, 0, GFP_KERNEL);
+	chip = kcalloc(1, sizeof(*chip), GFP_KERNEL);
 	if (chip == NULL)
 		return -ENOMEM;
 
diff -Nru a/sound/pci/rme32.c b/sound/pci/rme32.c
--- a/sound/pci/rme32.c	2004-10-18 14:57:04 -07:00
+++ b/sound/pci/rme32.c	2004-10-18 14:57:04 -07:00
@@ -1,7 +1,8 @@
 /*
  *   ALSA driver for RME Digi32, Digi32/8 and Digi32 PRO audio interfaces
  *
- *	Copyright (c) 2002, 2003 Martin Langer <martin-langer@gmx.de>
+ *      Copyright (c) 2002-2004 Martin Langer <martin-langer@gmx.de>,
+ *                              Pilo Chambert <pilo.c@wanadoo.fr>
  *
  *      Thanks to :        Anders Torger <torger@ludd.luth.se>,
  *                         Henk Hesselink <henk@anda.nl>
@@ -52,6 +53,19 @@
  * patch would be welcome!
  * 
  * ****************************************************************************
+ *
+ * "The story after the long seeking" -- tiwai
+ *
+ * Ok, the situation regarding the full duplex is now improved a bit.
+ * In the fullduplex mode (given by the module parameter), the hardware buffer
+ * is split to halves for read and write directions at the DMA pointer.
+ * That is, the half above the current DMA pointer is used for write, and
+ * the half below is used for read.  To mangle this strange behavior, an
+ * software intermediate buffer is introduced.  This is, of course, not good
+ * from the viewpoint of the data transfer efficiency.  However, this allows
+ * you to use arbitrary buffer sizes, instead of the fixed I/O buffer size.
+ *
+ * ****************************************************************************
  */
 
 
@@ -68,6 +82,7 @@
 #include <sound/control.h>
 #include <sound/pcm.h>
 #include <sound/pcm_params.h>
+#include <sound/pcm-indirect.h>
 #include <sound/asoundef.h>
 #include <sound/initval.h>
 
@@ -76,22 +91,21 @@
 static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX;	/* Index 0-MAX */
 static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR;	/* ID for this card */
 static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP;	/* Enable this card */
+static int fullduplex[SNDRV_CARDS]; // = {[0 ... (SNDRV_CARDS - 1)] = 1};
 static int boot_devs;
 
 module_param_array(index, int, boot_devs, 0444);
 MODULE_PARM_DESC(index, "Index value for RME Digi32 soundcard.");
-MODULE_PARM_SYNTAX(index, SNDRV_INDEX_DESC);
 module_param_array(id, charp, boot_devs, 0444);
 MODULE_PARM_DESC(id, "ID string for RME Digi32 soundcard.");
-MODULE_PARM_SYNTAX(id, SNDRV_ID_DESC);
 module_param_array(enable, bool, boot_devs, 0444);
 MODULE_PARM_DESC(enable, "Enable RME Digi32 soundcard.");
-MODULE_PARM_SYNTAX(enable, SNDRV_ENABLE_DESC);
-MODULE_AUTHOR("Martin Langer <martin-langer@gmx.de>");
+module_param_array(fullduplex, bool, boot_devs, 0444);
+MODULE_PARM_DESC(fullduplex, "Support full-duplex mode.");
+MODULE_AUTHOR("Martin Langer <martin-langer@gmx.de>, Pilo Chambert <pilo.c@wanadoo.fr>");
 MODULE_DESCRIPTION("RME Digi32, Digi32/8, Digi32 PRO");
 MODULE_LICENSE("GPL");
-MODULE_CLASSES("{sound}");
-MODULE_DEVICES("{{RME,Digi32}," "{RME,Digi32/8}," "{RME,Digi32 PRO}}");
+MODULE_SUPPORTED_DEVICE("{{RME,Digi32}," "{RME,Digi32/8}," "{RME,Digi32 PRO}}");
 
 /* Defines for RME Digi32 series */
 #define RME32_SPDIF_NCHANNELS 2
@@ -140,7 +154,7 @@
 #define RME32_WCR_BITPOS_INP_1 7
 
 /* Read control register bits */
-#define RME32_RCR_AUDIO_ADDR_MASK 0x10001
+#define RME32_RCR_AUDIO_ADDR_MASK 0x1ffff
 #define RME32_RCR_LOCK      (1 << 23)   /* 1=locked, 0=not locked */
 #define RME32_RCR_ERF       (1 << 26)   /* 1=Error, 0=no Error */
 #define RME32_RCR_FREQ_0    (1 << 27)   /* CS841x frequency (record) */
@@ -168,6 +182,9 @@
 /* Block sizes in bytes */
 #define RME32_BLOCK_SIZE 8192
 
+/* Software intermediate buffer (max) size */
+#define RME32_MID_BUFFER_SIZE (1024*1024)
+
 /* Hardware revisions */
 #define RME32_32_REVISION 192
 #define RME32_328_REVISION_OLD 100
@@ -194,7 +211,6 @@
 	spinlock_t lock;
 	int irq;
 	unsigned long port;
-	struct resource *res_port;
 	unsigned long iobase;
 
 	u32 wcreg;		/* cached write control register value */
@@ -213,9 +229,11 @@
 	size_t playback_periodsize;	/* in bytes, zero if not used */
 	size_t capture_periodsize;	/* in bytes, zero if not used */
 
-	snd_pcm_uframes_t playback_last_appl_ptr;
-	size_t playback_ptr;
-	size_t capture_ptr;
+	unsigned int fullduplex_mode;
+	int running;
+
+	snd_pcm_indirect_t playback_pcm;
+	snd_pcm_indirect_t capture_pcm;
 
 	snd_card_t *card;
 	snd_pcm_t *spdif_pcm;
@@ -243,33 +261,16 @@
 
 static int snd_rme32_capture_prepare(snd_pcm_substream_t * substream);
 
-static int
-snd_rme32_playback_trigger(snd_pcm_substream_t * substream, int cmd);
-
-static int
-snd_rme32_capture_trigger(snd_pcm_substream_t * substream, int cmd);
-
-static snd_pcm_uframes_t
-snd_rme32_playback_pointer(snd_pcm_substream_t * substream);
-
-static snd_pcm_uframes_t
-snd_rme32_capture_pointer(snd_pcm_substream_t * substream);
+static int snd_rme32_pcm_trigger(snd_pcm_substream_t * substream, int cmd);
 
 static void snd_rme32_proc_init(rme32_t * rme32);
 
 static int snd_rme32_create_switches(snd_card_t * card, rme32_t * rme32);
 
-static inline unsigned int snd_rme32_playback_ptr(rme32_t * rme32)
-{
-
-	return (readl(rme32->iobase + RME32_IO_GET_POS)
-		& RME32_RCR_AUDIO_ADDR_MASK) >> rme32->playback_frlog;
-}
-
-static inline unsigned int snd_rme32_capture_ptr(rme32_t * rme32)
+static inline unsigned int snd_rme32_pcm_byteptr(rme32_t * rme32)
 {
 	return (readl(rme32->iobase + RME32_IO_GET_POS)
-		& RME32_RCR_AUDIO_ADDR_MASK) >> rme32->capture_frlog;
+		& RME32_RCR_AUDIO_ADDR_MASK);
 }
 
 static int snd_rme32_ratecode(int rate)
@@ -285,22 +286,24 @@
 	return 0;
 }
 
+/* silence callback for halfduplex mode */
 static int snd_rme32_playback_silence(snd_pcm_substream_t * substream, int channel,	/* not used (interleaved data) */
 				      snd_pcm_uframes_t pos,
 				      snd_pcm_uframes_t count)
 {
-	rme32_t *rme32 = _snd_pcm_substream_chip(substream);
+	rme32_t *rme32 = snd_pcm_substream_chip(substream);
 	count <<= rme32->playback_frlog;
 	pos <<= rme32->playback_frlog;
 	memset_io(rme32->iobase + RME32_IO_DATA_BUFFER + pos, 0, count);
 	return 0;
 }
 
+/* copy callback for halfduplex mode */
 static int snd_rme32_playback_copy(snd_pcm_substream_t * substream, int channel,	/* not used (interleaved data) */
 				   snd_pcm_uframes_t pos,
 				   void __user *src, snd_pcm_uframes_t count)
 {
-	rme32_t *rme32 = _snd_pcm_substream_chip(substream);
+	rme32_t *rme32 = snd_pcm_substream_chip(substream);
 	count <<= rme32->playback_frlog;
 	pos <<= rme32->playback_frlog;
 	if (copy_from_user_toio(rme32->iobase + RME32_IO_DATA_BUFFER + pos,
@@ -309,11 +312,12 @@
 	return 0;
 }
 
+/* copy callback for halfduplex mode */
 static int snd_rme32_capture_copy(snd_pcm_substream_t * substream, int channel,	/* not used (interleaved data) */
 				  snd_pcm_uframes_t pos,
 				  void __user *dst, snd_pcm_uframes_t count)
 {
-	rme32_t *rme32 = _snd_pcm_substream_chip(substream);
+	rme32_t *rme32 = snd_pcm_substream_chip(substream);
 	count <<= rme32->capture_frlog;
 	pos <<= rme32->capture_frlog;
 	if (copy_to_user_fromio(dst,
@@ -324,13 +328,14 @@
 }
 
 /*
- * Digital output capabilites (S/PDIF)
+ * SPDIF I/O capabilites (half-duplex mode)
  */
-static snd_pcm_hardware_t snd_rme32_playback_spdif_info = {
-	.info =		(SNDRV_PCM_INFO_MMAP |
+static snd_pcm_hardware_t snd_rme32_spdif_info = {
+	.info =		(SNDRV_PCM_INFO_MMAP_IOMEM |
 			 SNDRV_PCM_INFO_MMAP_VALID |
 			 SNDRV_PCM_INFO_INTERLEAVED | 
-			 SNDRV_PCM_INFO_PAUSE),
+			 SNDRV_PCM_INFO_PAUSE |
+			 SNDRV_PCM_INFO_SYNC_START),
 	.formats =	(SNDRV_PCM_FMTBIT_S16_LE | 
 			 SNDRV_PCM_FMTBIT_S32_LE),
 	.rates =	(SNDRV_PCM_RATE_32000 |
@@ -349,13 +354,39 @@
 };
 
 /*
- * Digital input capabilites (S/PDIF)
+ * ADAT I/O capabilites (half-duplex mode)
+ */
+static snd_pcm_hardware_t snd_rme32_adat_info =
+{
+	.info =		     (SNDRV_PCM_INFO_MMAP_IOMEM |
+			      SNDRV_PCM_INFO_MMAP_VALID |
+			      SNDRV_PCM_INFO_INTERLEAVED |
+			      SNDRV_PCM_INFO_PAUSE |
+			      SNDRV_PCM_INFO_SYNC_START),
+	.formats=            SNDRV_PCM_FMTBIT_S16_LE,
+	.rates =             (SNDRV_PCM_RATE_44100 | 
+			      SNDRV_PCM_RATE_48000),
+	.rate_min =          44100,
+	.rate_max =          48000,
+	.channels_min =      8,
+	.channels_max =	     8,
+	.buffer_bytes_max =  RME32_BUFFER_SIZE,
+	.period_bytes_min =  RME32_BLOCK_SIZE,
+	.period_bytes_max =  RME32_BLOCK_SIZE,
+	.periods_min =	    RME32_BUFFER_SIZE / RME32_BLOCK_SIZE,
+	.periods_max =	    RME32_BUFFER_SIZE / RME32_BLOCK_SIZE,
+	.fifo_size =	    0,
+};
+
+/*
+ * SPDIF I/O capabilites (full-duplex mode)
  */
-static snd_pcm_hardware_t snd_rme32_capture_spdif_info = {
+static snd_pcm_hardware_t snd_rme32_spdif_fd_info = {
 	.info =		(SNDRV_PCM_INFO_MMAP |
 			 SNDRV_PCM_INFO_MMAP_VALID |
 			 SNDRV_PCM_INFO_INTERLEAVED | 
-			 SNDRV_PCM_INFO_PAUSE),
+			 SNDRV_PCM_INFO_PAUSE |
+			 SNDRV_PCM_INFO_SYNC_START),
 	.formats =	(SNDRV_PCM_FMTBIT_S16_LE | 
 			 SNDRV_PCM_FMTBIT_S32_LE),
 	.rates =	(SNDRV_PCM_RATE_32000 |
@@ -365,23 +396,24 @@
 	.rate_max =	48000,
 	.channels_min =	2,
 	.channels_max =	2,
-	.buffer_bytes_max = RME32_BUFFER_SIZE,
+	.buffer_bytes_max = RME32_MID_BUFFER_SIZE,
 	.period_bytes_min = RME32_BLOCK_SIZE,
 	.period_bytes_max = RME32_BLOCK_SIZE,
-	.periods_min =	RME32_BUFFER_SIZE / RME32_BLOCK_SIZE,
-	.periods_max =	RME32_BUFFER_SIZE / RME32_BLOCK_SIZE,
+	.periods_min =	2,
+	.periods_max =	RME32_MID_BUFFER_SIZE / RME32_BLOCK_SIZE,
 	.fifo_size =	0,
 };
 
 /*
- * Digital output capabilites (ADAT)
+ * ADAT I/O capabilites (full-duplex mode)
  */
-static snd_pcm_hardware_t snd_rme32_playback_adat_info =
+static snd_pcm_hardware_t snd_rme32_adat_fd_info =
 {
 	.info =		     (SNDRV_PCM_INFO_MMAP |
 			      SNDRV_PCM_INFO_MMAP_VALID |
 			      SNDRV_PCM_INFO_INTERLEAVED |
-			      SNDRV_PCM_INFO_PAUSE),
+			      SNDRV_PCM_INFO_PAUSE |
+			      SNDRV_PCM_INFO_SYNC_START),
 	.formats=            SNDRV_PCM_FMTBIT_S16_LE,
 	.rates =             (SNDRV_PCM_RATE_44100 | 
 			      SNDRV_PCM_RATE_48000),
@@ -389,38 +421,14 @@
 	.rate_max =          48000,
 	.channels_min =      8,
 	.channels_max =	     8,
-	.buffer_bytes_max =  RME32_BUFFER_SIZE,
+	.buffer_bytes_max =  RME32_MID_BUFFER_SIZE,
 	.period_bytes_min =  RME32_BLOCK_SIZE,
 	.period_bytes_max =  RME32_BLOCK_SIZE,
-	.periods_min =	    RME32_BUFFER_SIZE / RME32_BLOCK_SIZE,
-	.periods_max =	    RME32_BUFFER_SIZE / RME32_BLOCK_SIZE,
+	.periods_min =	    2,
+	.periods_max =	    RME32_MID_BUFFER_SIZE / RME32_BLOCK_SIZE,
 	.fifo_size =	    0,
 };
 
-/*
- * Digital input capabilites (ADAT)
- */
-static snd_pcm_hardware_t snd_rme32_capture_adat_info =
-{
-	.info =		     (SNDRV_PCM_INFO_MMAP |
-			      SNDRV_PCM_INFO_MMAP_VALID |
-			      SNDRV_PCM_INFO_INTERLEAVED |
-			      SNDRV_PCM_INFO_PAUSE),
-	.formats =           SNDRV_PCM_FMTBIT_S16_LE,
-	.rates =             (SNDRV_PCM_RATE_44100 | 
-			      SNDRV_PCM_RATE_48000),
-	.rate_min =          44100,
-	.rate_max =          48000,
-	.channels_min =	     8,
-	.channels_max =	     8,
-	.buffer_bytes_max =  RME32_BUFFER_SIZE,
-	.period_bytes_min =  RME32_BLOCK_SIZE,
-	.period_bytes_max =  RME32_BLOCK_SIZE,
-	.periods_min =	     RME32_BUFFER_SIZE / RME32_BLOCK_SIZE,
-	.periods_max =	     RME32_BUFFER_SIZE / RME32_BLOCK_SIZE,
-	.fifo_size =         0,
-};
-
 static void snd_rme32_reset_dac(rme32_t *rme32)
 {
         writel(rme32->wcreg | RME32_WCR_PD,
@@ -677,11 +685,19 @@
 			     snd_pcm_hw_params_t * params)
 {
 	int err, rate, dummy;
-	rme32_t *rme32 = _snd_pcm_substream_chip(substream);
+	rme32_t *rme32 = snd_pcm_substream_chip(substream);
+	snd_pcm_runtime_t *runtime = substream->runtime;
+
+	if (rme32->fullduplex_mode) {
+		err = snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(params));
+		if (err < 0)
+			return err;
+	} else {
+		runtime->dma_area = (void *)(rme32->iobase + RME32_IO_DATA_BUFFER);
+		runtime->dma_addr = rme32->port + RME32_IO_DATA_BUFFER;
+		runtime->dma_bytes = RME32_BUFFER_SIZE;
+	}
 
-	if ((err = snd_pcm_lib_malloc_pages(substream,
-				      params_buffer_bytes(params))) < 0)
-		return err;
 	spin_lock_irq(&rme32->lock);
 	if ((rme32->rcreg & RME32_RCR_KMODE) &&
 	    (rate = snd_rme32_capture_getrate(rme32, &dummy)) > 0) {
@@ -719,45 +735,45 @@
 	return 0;
 }
 
-static int snd_rme32_playback_hw_free(snd_pcm_substream_t * substream)
-{
-	snd_pcm_lib_free_pages(substream);
-	return 0;
-}
-
 static int
 snd_rme32_capture_hw_params(snd_pcm_substream_t * substream,
 			    snd_pcm_hw_params_t * params)
 {
-	unsigned long flags;
 	int err, isadat, rate;
-	rme32_t *rme32 = _snd_pcm_substream_chip(substream);
+	rme32_t *rme32 = snd_pcm_substream_chip(substream);
 	snd_pcm_runtime_t *runtime = substream->runtime;
 
-	if ((err = snd_pcm_lib_malloc_pages(substream,
-				      params_buffer_bytes(params))) < 0)
-		return err;
-	spin_lock_irqsave(&rme32->lock, flags);
+	if (rme32->fullduplex_mode) {
+		err = snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(params));
+		if (err < 0)
+			return err;
+	} else {
+		runtime->dma_area = (void *)rme32->iobase + RME32_IO_DATA_BUFFER;
+		runtime->dma_addr = rme32->port + RME32_IO_DATA_BUFFER;
+		runtime->dma_bytes = RME32_BUFFER_SIZE;
+	}
+
+	spin_lock_irq(&rme32->lock);
 	/* enable AutoSync for record-preparing */
 	rme32->wcreg |= RME32_WCR_AUTOSYNC;
 	writel(rme32->wcreg, rme32->iobase + RME32_IO_CONTROL_REGISTER);
 
 	if ((err = snd_rme32_setformat(rme32, params_format(params))) < 0) {
-		spin_unlock_irqrestore(&rme32->lock, flags);
+		spin_unlock_irq(&rme32->lock);
 		return err;
 	}
 	if ((err = snd_rme32_playback_setrate(rme32, params_rate(params))) < 0) {
-		spin_unlock_irqrestore(&rme32->lock, flags);
+		spin_unlock_irq(&rme32->lock);
 		return err;
 	}
 	if ((rate = snd_rme32_capture_getrate(rme32, &isadat)) > 0) {
                 if ((int)params_rate(params) != rate) {
-                        spin_unlock_irqrestore(&rme32->lock, flags);
+			spin_unlock_irq(&rme32->lock);
                         return -EIO;                    
                 }
                 if ((isadat && runtime->hw.channels_min == 2) ||
                     (!isadat && runtime->hw.channels_min == 8)) {
-                        spin_unlock_irqrestore(&rme32->lock, flags);
+			spin_unlock_irq(&rme32->lock);
                         return -EIO;
                 }
 	}
@@ -769,36 +785,26 @@
 	if (rme32->playback_periodsize != 0) {
 		if (params_period_size(params) << rme32->capture_frlog !=
 		    rme32->playback_periodsize) {
-			spin_unlock_irqrestore(&rme32->lock, flags);
+			spin_unlock_irq(&rme32->lock);
 			return -EBUSY;
 		}
 	}
 	rme32->capture_periodsize =
 	    params_period_size(params) << rme32->capture_frlog;
-	spin_unlock_irqrestore(&rme32->lock, flags);
-
-	return 0;
-}
+	spin_unlock_irq(&rme32->lock);
 
-static int snd_rme32_capture_hw_free(snd_pcm_substream_t * substream)
-{
-	snd_pcm_lib_free_pages(substream);
 	return 0;
 }
 
-static void snd_rme32_playback_start(rme32_t * rme32, int from_pause)
+static int snd_rme32_pcm_hw_free(snd_pcm_substream_t * substream)
 {
-	if (!from_pause) {
-		writel(0, rme32->iobase + RME32_IO_RESET_POS);
-		rme32->playback_last_appl_ptr = 0;
-		rme32->playback_ptr = 0;
-	}
-
-	rme32->wcreg |= RME32_WCR_START;
-	writel(rme32->wcreg, rme32->iobase + RME32_IO_CONTROL_REGISTER);
+	rme32_t *rme32 = snd_pcm_substream_chip(substream);
+	if (! rme32->fullduplex_mode)
+		return 0;
+	return snd_pcm_lib_free_pages(substream);
 }
 
-static void snd_rme32_capture_start(rme32_t * rme32, int from_pause)
+static void snd_rme32_pcm_start(rme32_t * rme32, int from_pause)
 {
 	if (!from_pause) {
 		writel(0, rme32->iobase + RME32_IO_RESET_POS);
@@ -808,7 +814,7 @@
 	writel(rme32->wcreg, rme32->iobase + RME32_IO_CONTROL_REGISTER);
 }
 
-static void snd_rme32_playback_stop(rme32_t * rme32)
+static void snd_rme32_pcm_stop(rme32_t * rme32, int to_pause)
 {
 	/*
 	 * Check if there is an unconfirmed IRQ, if so confirm it, or else
@@ -822,16 +828,8 @@
 	if (rme32->wcreg & RME32_WCR_SEL)
 		rme32->wcreg |= RME32_WCR_MUTE;
 	writel(rme32->wcreg, rme32->iobase + RME32_IO_CONTROL_REGISTER);
-}
-
-static void snd_rme32_capture_stop(rme32_t * rme32)
-{
-	rme32->rcreg = readl(rme32->iobase + RME32_IO_CONTROL_REGISTER);
-	if (rme32->rcreg & RME32_RCR_IRQ) {
-		writel(0, rme32->iobase + RME32_IO_CONFIRM_ACTION_IRQ);
-	}
-	rme32->wcreg &= ~RME32_WCR_START;
-	writel(rme32->wcreg, rme32->iobase + RME32_IO_CONTROL_REGISTER);
+	if (! to_pause)
+		writel(0, rme32->iobase + RME32_IO_RESET_POS);
 }
 
 static irqreturn_t
@@ -857,36 +855,46 @@
 static unsigned int period_bytes[] = { RME32_BLOCK_SIZE };
 
 
-#define PERIOD_BYTES sizeof(period_bytes) / sizeof(period_bytes[0])
-
 static snd_pcm_hw_constraint_list_t hw_constraints_period_bytes = {
-	.count = PERIOD_BYTES,
+	.count = ARRAY_SIZE(period_bytes),
 	.list = period_bytes,
 	.mask = 0
 };
 
+static void snd_rme32_set_buffer_constraint(rme32_t *rme32, snd_pcm_runtime_t *runtime)
+{
+	if (! rme32->fullduplex_mode) {
+		snd_pcm_hw_constraint_minmax(runtime,
+					     SNDRV_PCM_HW_PARAM_BUFFER_BYTES,
+					     RME32_BUFFER_SIZE, RME32_BUFFER_SIZE);
+		snd_pcm_hw_constraint_list(runtime, 0,
+					   SNDRV_PCM_HW_PARAM_PERIOD_BYTES,
+					   &hw_constraints_period_bytes);
+	}
+}
+
 static int snd_rme32_playback_spdif_open(snd_pcm_substream_t * substream)
 {
-	unsigned long flags;
 	int rate, dummy;
-	rme32_t *rme32 = _snd_pcm_substream_chip(substream);
+	rme32_t *rme32 = snd_pcm_substream_chip(substream);
 	snd_pcm_runtime_t *runtime = substream->runtime;
 
 	snd_pcm_set_sync(substream);
 
-	spin_lock_irqsave(&rme32->lock, flags);
+	spin_lock_irq(&rme32->lock);
 	if (rme32->playback_substream != NULL) {
-		spin_unlock_irqrestore(&rme32->lock, flags);
+		spin_unlock_irq(&rme32->lock);
 		return -EBUSY;
 	}
 	rme32->wcreg &= ~RME32_WCR_ADAT;
 	writel(rme32->wcreg, rme32->iobase + RME32_IO_CONTROL_REGISTER);
 	rme32->playback_substream = substream;
-	rme32->playback_last_appl_ptr = 0;
-	rme32->playback_ptr = 0;
-	spin_unlock_irqrestore(&rme32->lock, flags);
+	spin_unlock_irq(&rme32->lock);
 
-	runtime->hw = snd_rme32_playback_spdif_info;
+	if (rme32->fullduplex_mode)
+		runtime->hw = snd_rme32_spdif_fd_info;
+	else
+		runtime->hw = snd_rme32_spdif_info;
 	if (rme32->pci->device == PCI_DEVICE_ID_DIGI32_PRO) {
 		runtime->hw.rates |= SNDRV_PCM_RATE_64000 | SNDRV_PCM_RATE_88200 | SNDRV_PCM_RATE_96000;
 		runtime->hw.rate_max = 96000;
@@ -898,12 +906,8 @@
 		runtime->hw.rate_min = rate;
 		runtime->hw.rate_max = rate;
 	}       
-	snd_pcm_hw_constraint_minmax(runtime,
-				     SNDRV_PCM_HW_PARAM_BUFFER_BYTES,
-				     RME32_BUFFER_SIZE, RME32_BUFFER_SIZE);
-	snd_pcm_hw_constraint_list(runtime, 0,
-				   SNDRV_PCM_HW_PARAM_PERIOD_BYTES,
-				   &hw_constraints_period_bytes);
+
+	snd_rme32_set_buffer_constraint(rme32, runtime);
 
 	rme32->wcreg_spdif_stream = rme32->wcreg_spdif;
 	rme32->spdif_ctl->vd[0].access &= ~SNDRV_CTL_ELEM_ACCESS_INACTIVE;
@@ -914,23 +918,24 @@
 
 static int snd_rme32_capture_spdif_open(snd_pcm_substream_t * substream)
 {
-	unsigned long flags;
 	int isadat, rate;
-	rme32_t *rme32 = _snd_pcm_substream_chip(substream);
+	rme32_t *rme32 = snd_pcm_substream_chip(substream);
 	snd_pcm_runtime_t *runtime = substream->runtime;
 
 	snd_pcm_set_sync(substream);
 
-	spin_lock_irqsave(&rme32->lock, flags);
+	spin_lock_irq(&rme32->lock);
         if (rme32->capture_substream != NULL) {
-	        spin_unlock_irqrestore(&rme32->lock, flags);
+		spin_unlock_irq(&rme32->lock);
                 return -EBUSY;
         }
 	rme32->capture_substream = substream;
-	rme32->capture_ptr = 0;
-	spin_unlock_irqrestore(&rme32->lock, flags);
+	spin_unlock_irq(&rme32->lock);
 
-	runtime->hw = snd_rme32_capture_spdif_info;
+	if (rme32->fullduplex_mode)
+		runtime->hw = snd_rme32_spdif_fd_info;
+	else
+		runtime->hw = snd_rme32_spdif_info;
 	if (RME32_PRO_WITH_8414(rme32)) {
 		runtime->hw.rates |= SNDRV_PCM_RATE_88200 | SNDRV_PCM_RATE_96000;
 		runtime->hw.rate_max = 96000;
@@ -944,12 +949,7 @@
 		runtime->hw.rate_max = rate;
 	}
 
-	snd_pcm_hw_constraint_minmax(runtime,
-				     SNDRV_PCM_HW_PARAM_BUFFER_BYTES,
-				     RME32_BUFFER_SIZE, RME32_BUFFER_SIZE);
-	snd_pcm_hw_constraint_list(runtime, 0,
-				   SNDRV_PCM_HW_PARAM_PERIOD_BYTES,
-				   &hw_constraints_period_bytes);
+	snd_rme32_set_buffer_constraint(rme32, runtime);
 
 	return 0;
 }
@@ -957,26 +957,26 @@
 static int
 snd_rme32_playback_adat_open(snd_pcm_substream_t *substream)
 {
-	unsigned long flags;
 	int rate, dummy;
-	rme32_t *rme32 = _snd_pcm_substream_chip(substream);
+	rme32_t *rme32 = snd_pcm_substream_chip(substream);
 	snd_pcm_runtime_t *runtime = substream->runtime;
 	
 	snd_pcm_set_sync(substream);
 
-	spin_lock_irqsave(&rme32->lock, flags);	
+	spin_lock_irq(&rme32->lock);	
         if (rme32->playback_substream != NULL) {
-	        spin_unlock_irqrestore(&rme32->lock, flags);
+		spin_unlock_irq(&rme32->lock);
                 return -EBUSY;
         }
 	rme32->wcreg |= RME32_WCR_ADAT;
 	writel(rme32->wcreg, rme32->iobase + RME32_IO_CONTROL_REGISTER);
 	rme32->playback_substream = substream;
-	rme32->playback_last_appl_ptr = 0;
-	rme32->playback_ptr = 0;
-	spin_unlock_irqrestore(&rme32->lock, flags);
+	spin_unlock_irq(&rme32->lock);
 	
-	runtime->hw = snd_rme32_playback_adat_info;
+	if (rme32->fullduplex_mode)
+		runtime->hw = snd_rme32_adat_fd_info;
+	else
+		runtime->hw = snd_rme32_adat_info;
 	if ((rme32->rcreg & RME32_RCR_KMODE) &&
 	    (rate = snd_rme32_capture_getrate(rme32, &dummy)) > 0) {
                 /* AutoSync */
@@ -984,22 +984,22 @@
                 runtime->hw.rate_min = rate;
                 runtime->hw.rate_max = rate;
 	}        
-	snd_pcm_hw_constraint_minmax(runtime, SNDRV_PCM_HW_PARAM_BUFFER_BYTES,
-				     RME32_BUFFER_SIZE, RME32_BUFFER_SIZE);
-	snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_PERIOD_BYTES,
-				   &hw_constraints_period_bytes);
+
+	snd_rme32_set_buffer_constraint(rme32, runtime);
 	return 0;
 }
 
 static int
 snd_rme32_capture_adat_open(snd_pcm_substream_t *substream)
 {
-	unsigned long flags;
 	int isadat, rate;
-	rme32_t *rme32 = _snd_pcm_substream_chip(substream);
+	rme32_t *rme32 = snd_pcm_substream_chip(substream);
 	snd_pcm_runtime_t *runtime = substream->runtime;
 
-	runtime->hw = snd_rme32_capture_adat_info;
+	if (rme32->fullduplex_mode)
+		runtime->hw = snd_rme32_adat_fd_info;
+	else
+		runtime->hw = snd_rme32_adat_info;
 	if ((rate = snd_rme32_capture_getrate(rme32, &isadat)) > 0) {
 		if (!isadat) {
 			return -EIO;
@@ -1011,33 +1011,28 @@
 
 	snd_pcm_set_sync(substream);
         
-	spin_lock_irqsave(&rme32->lock, flags);	
+	spin_lock_irq(&rme32->lock);	
 	if (rme32->capture_substream != NULL) {
-		spin_unlock_irqrestore(&rme32->lock, flags);
+		spin_unlock_irq(&rme32->lock);
 		return -EBUSY;
         }
 	rme32->capture_substream = substream;
-	rme32->capture_ptr = 0;
-	spin_unlock_irqrestore(&rme32->lock, flags);
+	spin_unlock_irq(&rme32->lock);
 
-	snd_pcm_hw_constraint_minmax(runtime, SNDRV_PCM_HW_PARAM_BUFFER_BYTES,
-				     RME32_BUFFER_SIZE, RME32_BUFFER_SIZE);
-	snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_PERIOD_BYTES,
-				   &hw_constraints_period_bytes);
+	snd_rme32_set_buffer_constraint(rme32, runtime);
 	return 0;
 }
 
 static int snd_rme32_playback_close(snd_pcm_substream_t * substream)
 {
-	unsigned long flags;
-	rme32_t *rme32 = _snd_pcm_substream_chip(substream);
+	rme32_t *rme32 = snd_pcm_substream_chip(substream);
 	int spdif = 0;
 
-	spin_lock_irqsave(&rme32->lock, flags);
+	spin_lock_irq(&rme32->lock);
 	rme32->playback_substream = NULL;
 	rme32->playback_periodsize = 0;
 	spdif = (rme32->wcreg & RME32_WCR_ADAT) == 0;
-	spin_unlock_irqrestore(&rme32->lock, flags);
+	spin_unlock_irq(&rme32->lock);
 	if (spdif) {
 		rme32->spdif_ctl->vd[0].access |= SNDRV_CTL_ELEM_ACCESS_INACTIVE;
 		snd_ctl_notify(rme32->card, SNDRV_CTL_EVENT_MASK_VALUE |
@@ -1049,210 +1044,207 @@
 
 static int snd_rme32_capture_close(snd_pcm_substream_t * substream)
 {
-	unsigned long flags;
-	rme32_t *rme32 = _snd_pcm_substream_chip(substream);
+	rme32_t *rme32 = snd_pcm_substream_chip(substream);
 
-	spin_lock_irqsave(&rme32->lock, flags);
+	spin_lock_irq(&rme32->lock);
 	rme32->capture_substream = NULL;
 	rme32->capture_periodsize = 0;
-	spin_unlock_irqrestore(&rme32->lock, flags);
+	spin_unlock(&rme32->lock);
 	return 0;
 }
 
 static int snd_rme32_playback_prepare(snd_pcm_substream_t * substream)
 {
-	rme32_t *rme32 = _snd_pcm_substream_chip(substream);
-	unsigned long flags;
+	rme32_t *rme32 = snd_pcm_substream_chip(substream);
 
-	spin_lock_irqsave(&rme32->lock, flags);
-	if (RME32_ISWORKING(rme32)) {
-		snd_rme32_playback_stop(rme32);
+	spin_lock_irq(&rme32->lock);
+	if (rme32->fullduplex_mode) {
+		memset(&rme32->playback_pcm, 0, sizeof(rme32->playback_pcm));
+		rme32->playback_pcm.hw_buffer_size = RME32_BUFFER_SIZE;
+		rme32->playback_pcm.sw_buffer_size = snd_pcm_lib_buffer_bytes(substream);
+	} else {
+		writel(0, rme32->iobase + RME32_IO_RESET_POS);
 	}
-	writel(0, rme32->iobase + RME32_IO_RESET_POS);
 	if (rme32->wcreg & RME32_WCR_SEL)
 		rme32->wcreg &= ~RME32_WCR_MUTE;
 	writel(rme32->wcreg, rme32->iobase + RME32_IO_CONTROL_REGISTER);
-	spin_unlock_irqrestore(&rme32->lock, flags);
+	spin_unlock_irq(&rme32->lock);
 	return 0;
 }
 
 static int snd_rme32_capture_prepare(snd_pcm_substream_t * substream)
 {
-	rme32_t *rme32 = _snd_pcm_substream_chip(substream);
-	unsigned long flags;
+	rme32_t *rme32 = snd_pcm_substream_chip(substream);
 
-	spin_lock_irqsave(&rme32->lock, flags);
-	if (RME32_ISWORKING(rme32)) {
-		snd_rme32_capture_stop(rme32);
+	spin_lock_irq(&rme32->lock);
+	if (rme32->fullduplex_mode) {
+		memset(&rme32->capture_pcm, 0, sizeof(rme32->capture_pcm));
+		rme32->capture_pcm.hw_buffer_size = RME32_BUFFER_SIZE;
+		rme32->capture_pcm.hw_queue_size = RME32_BUFFER_SIZE / 2;
+		rme32->capture_pcm.sw_buffer_size = snd_pcm_lib_buffer_bytes(substream);
+	} else {
+		writel(0, rme32->iobase + RME32_IO_RESET_POS);
 	}
-	writel(0, rme32->iobase + RME32_IO_RESET_POS);
-	spin_unlock_irqrestore(&rme32->lock, flags);
+	spin_unlock_irq(&rme32->lock);
 	return 0;
 }
 
 static int
-snd_rme32_playback_trigger(snd_pcm_substream_t * substream, int cmd)
+snd_rme32_pcm_trigger(snd_pcm_substream_t * substream, int cmd)
 {
-	rme32_t *rme32 = _snd_pcm_substream_chip(substream);
-	switch (cmd) {
-	case SNDRV_PCM_TRIGGER_START:
-		if (!RME32_ISWORKING(rme32)) {
-			if (substream != rme32->playback_substream) {
-				return -EBUSY;
+	rme32_t *rme32 = snd_pcm_substream_chip(substream);
+	struct list_head *pos;
+	snd_pcm_substream_t *s;
+
+	spin_lock(&rme32->lock);
+	snd_pcm_group_for_each(pos, substream) {
+		s = snd_pcm_group_substream_entry(pos);
+		if (s != rme32->playback_substream &&
+		    s != rme32->capture_substream)
+			continue;
+		switch (cmd) {
+		case SNDRV_PCM_TRIGGER_START:
+			rme32->running |= (1 << s->stream);
+			if (rme32->fullduplex_mode) {
+				/* remember the current DMA position */
+				if (s == rme32->playback_substream) {
+					rme32->playback_pcm.hw_io =
+					rme32->playback_pcm.hw_data = snd_rme32_pcm_byteptr(rme32);
+				} else {
+					rme32->capture_pcm.hw_io =
+					rme32->capture_pcm.hw_data = snd_rme32_pcm_byteptr(rme32);
+				}
 			}
-			snd_rme32_playback_start(rme32, 0);
+			break;
+		case SNDRV_PCM_TRIGGER_STOP:
+			rme32->running &= ~(1 << s->stream);
+			break;
 		}
-		break;
-
-	case SNDRV_PCM_TRIGGER_STOP:
-		if (RME32_ISWORKING(rme32)) {
-			if (substream != rme32->playback_substream) {
-				return -EBUSY;
+		snd_pcm_trigger_done(s, substream);
+	}
+	
+	/* prefill playback buffer */
+	if (cmd == SNDRV_PCM_TRIGGER_START) {
+		snd_pcm_group_for_each(pos, substream) {
+			s = snd_pcm_group_substream_entry(pos);
+			if (s == rme32->playback_substream) {
+				s->ops->ack(s);
+				break;
 			}
-			snd_rme32_playback_stop(rme32);
-		}
-		break;
-
-	case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
-		if (RME32_ISWORKING(rme32)) {
-			snd_rme32_playback_stop(rme32);
-		}
-		break;
-
-	case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
-		if (!RME32_ISWORKING(rme32)) {
-			snd_rme32_playback_start(rme32, 1);
 		}
-		break;
-
-	default:
-		return -EINVAL;
 	}
-	return 0;
-}
-
-static int
-snd_rme32_capture_trigger(snd_pcm_substream_t * substream, int cmd)
-{
-	rme32_t *rme32 = _snd_pcm_substream_chip(substream);
 
 	switch (cmd) {
 	case SNDRV_PCM_TRIGGER_START:
-		if (!RME32_ISWORKING(rme32)) {
-			if (substream != rme32->capture_substream) {
-				return -EBUSY;
-			}
-			snd_rme32_capture_start(rme32, 0);
-		}
+		if (rme32->running && ! RME32_ISWORKING(rme32))
+			snd_rme32_pcm_start(rme32, 0);
 		break;
-
 	case SNDRV_PCM_TRIGGER_STOP:
-		if (RME32_ISWORKING(rme32)) {
-			if (substream != rme32->capture_substream) {
-				return -EBUSY;
-			}
-			snd_rme32_capture_stop(rme32);
-		}
+		if (! rme32->running && RME32_ISWORKING(rme32))
+			snd_rme32_pcm_stop(rme32, 0);
 		break;
-
 	case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
-		if (RME32_ISWORKING(rme32)) {
-			snd_rme32_capture_stop(rme32);
-		}
+		if (rme32->running && RME32_ISWORKING(rme32))
+			snd_rme32_pcm_stop(rme32, 1);
 		break;
-
 	case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
-		if (!RME32_ISWORKING(rme32)) {
-			snd_rme32_capture_start(rme32, 1);
-		}
+		if (rme32->running && ! RME32_ISWORKING(rme32))
+			snd_rme32_pcm_start(rme32, 1);
 		break;
-
-	default:
-		return -EINVAL;
 	}
-
+	spin_unlock(&rme32->lock);
 	return 0;
 }
 
+/* pointer callback for halfduplex mode */
 static snd_pcm_uframes_t
 snd_rme32_playback_pointer(snd_pcm_substream_t * substream)
 {
-	rme32_t *rme32 = _snd_pcm_substream_chip(substream);
-	snd_pcm_runtime_t *runtime = substream->runtime;
-	snd_pcm_sframes_t diff;
-	size_t bytes;
+	rme32_t *rme32 = snd_pcm_substream_chip(substream);
+	return snd_rme32_pcm_byteptr(rme32) >> rme32->playback_frlog;
+}
 
+static snd_pcm_uframes_t
+snd_rme32_capture_pointer(snd_pcm_substream_t * substream)
+{
+	rme32_t *rme32 = snd_pcm_substream_chip(substream);
+	return snd_rme32_pcm_byteptr(rme32) >> rme32->capture_frlog;
+}
 
-	if (runtime->access == SNDRV_PCM_ACCESS_MMAP_INTERLEAVED) {
-		diff = runtime->control->appl_ptr -
-		       rme32->playback_last_appl_ptr;
-		rme32->playback_last_appl_ptr = runtime->control->appl_ptr;
-		if (diff != 0 && diff < -(snd_pcm_sframes_t) (runtime->boundary >> 1)) {
-			diff += runtime->boundary;
-		}
-		bytes = diff << rme32->playback_frlog;
-		if (bytes > RME32_BUFFER_SIZE - rme32->playback_ptr) {
-			memcpy_toio((void *)(rme32->iobase + RME32_IO_DATA_BUFFER + rme32->playback_ptr),
-				    runtime->dma_area + rme32->playback_ptr,
-				    RME32_BUFFER_SIZE - rme32->playback_ptr);
-			bytes -= RME32_BUFFER_SIZE - rme32->playback_ptr;
-			if (bytes > RME32_BUFFER_SIZE) {
-				bytes = RME32_BUFFER_SIZE;
-			}
-			memcpy_toio((void *)(rme32->iobase + RME32_IO_DATA_BUFFER),
-				    runtime->dma_area, bytes);
-			rme32->playback_ptr = bytes;
-		} else if (bytes != 0) {
-			memcpy_toio((void *)(rme32->iobase + RME32_IO_DATA_BUFFER + rme32->playback_ptr),
-				    runtime->dma_area + rme32->playback_ptr, bytes);
-			rme32->playback_ptr += bytes;
-		}
-	}
-	return snd_rme32_playback_ptr(rme32);
+
+/* ack and pointer callbacks for fullduplex mode */
+static void snd_rme32_pb_trans_copy(snd_pcm_substream_t *substream,
+				    snd_pcm_indirect_t *rec, size_t bytes)
+{
+	rme32_t *rme32 = snd_pcm_substream_chip(substream);
+	memcpy_toio(rme32->iobase + RME32_IO_DATA_BUFFER + rec->hw_data,
+		    substream->runtime->dma_area + rec->sw_data, bytes);
+}
+
+static int snd_rme32_playback_fd_ack(snd_pcm_substream_t *substream)
+{
+	rme32_t *rme32 = snd_pcm_substream_chip(substream);
+	snd_pcm_indirect_t *rec, *cprec;
+	unsigned long flags;
+
+	rec = &rme32->playback_pcm;
+	cprec = &rme32->capture_pcm;
+	spin_lock_irqsave(&rme32->lock, flags);
+	rec->hw_queue_size = RME32_BUFFER_SIZE;
+	if (rme32->running & (1 << SNDRV_PCM_STREAM_CAPTURE))
+		rec->hw_queue_size -= cprec->hw_ready;
+	spin_unlock_irqrestore(&rme32->lock, flags);
+	snd_pcm_indirect_playback_transfer(substream, rec,
+					   snd_rme32_pb_trans_copy);
+	return 0;
+}
+
+static void snd_rme32_cp_trans_copy(snd_pcm_substream_t *substream,
+				    snd_pcm_indirect_t *rec, size_t bytes)
+{
+	rme32_t *rme32 = snd_pcm_substream_chip(substream);
+	memcpy_fromio(substream->runtime->dma_area + rec->sw_data,
+		      rme32->iobase + RME32_IO_DATA_BUFFER + rec->hw_data,
+		      bytes);
+}
+
+static int snd_rme32_capture_fd_ack(snd_pcm_substream_t *substream)
+{
+	rme32_t *rme32 = snd_pcm_substream_chip(substream);
+	snd_pcm_indirect_capture_transfer(substream, &rme32->capture_pcm,
+					  snd_rme32_cp_trans_copy);
+	return 0;
 }
 
 static snd_pcm_uframes_t
-snd_rme32_capture_pointer(snd_pcm_substream_t * substream)
+snd_rme32_playback_fd_pointer(snd_pcm_substream_t * substream)
 {
-	rme32_t *rme32 = _snd_pcm_substream_chip(substream);
-	snd_pcm_runtime_t *runtime = substream->runtime;
-	snd_pcm_uframes_t frameptr;
-	size_t ptr;
+	rme32_t *rme32 = snd_pcm_substream_chip(substream);
+	return snd_pcm_indirect_playback_pointer(substream, &rme32->playback_pcm,
+						 snd_rme32_pcm_byteptr(rme32));
+}
 
-	frameptr = snd_rme32_capture_ptr(rme32);
-	if (runtime->access == SNDRV_PCM_ACCESS_MMAP_INTERLEAVED) {
-		ptr = frameptr << rme32->capture_frlog;
-		if (ptr > rme32->capture_ptr) {
-			memcpy_fromio(runtime->dma_area + rme32->capture_ptr,
-				      (void *)(rme32->iobase + RME32_IO_DATA_BUFFER +
-					       rme32->capture_ptr),
-				      ptr - rme32->capture_ptr);
-			rme32->capture_ptr += ptr - rme32->capture_ptr;
-		} else if (ptr < rme32->capture_ptr) {
-			memcpy_fromio(runtime->dma_area + rme32->capture_ptr,
-				      (void *)(rme32->iobase + RME32_IO_DATA_BUFFER +
-					       rme32->capture_ptr),
-				      RME32_BUFFER_SIZE - rme32->capture_ptr);
-			memcpy_fromio(runtime->dma_area,
-				      (void *)(rme32->iobase + RME32_IO_DATA_BUFFER),
-				      ptr);
-			rme32->capture_ptr = ptr;
-		}
-	}
-	return frameptr;
+static snd_pcm_uframes_t
+snd_rme32_capture_fd_pointer(snd_pcm_substream_t * substream)
+{
+	rme32_t *rme32 = snd_pcm_substream_chip(substream);
+	return snd_pcm_indirect_capture_pointer(substream, &rme32->capture_pcm,
+						snd_rme32_pcm_byteptr(rme32));
 }
 
+/* for halfduplex mode */
 static snd_pcm_ops_t snd_rme32_playback_spdif_ops = {
 	.open =		snd_rme32_playback_spdif_open,
 	.close =	snd_rme32_playback_close,
 	.ioctl =	snd_pcm_lib_ioctl,
 	.hw_params =	snd_rme32_playback_hw_params,
-	.hw_free =	snd_rme32_playback_hw_free,
+	.hw_free =	snd_rme32_pcm_hw_free,
 	.prepare =	snd_rme32_playback_prepare,
-	.trigger =	snd_rme32_playback_trigger,
+	.trigger =	snd_rme32_pcm_trigger,
 	.pointer =	snd_rme32_playback_pointer,
 	.copy =		snd_rme32_playback_copy,
 	.silence =	snd_rme32_playback_silence,
+	.mmap =		snd_pcm_lib_mmap_iomem,
 };
 
 static snd_pcm_ops_t snd_rme32_capture_spdif_ops = {
@@ -1260,11 +1252,12 @@
 	.close =	snd_rme32_capture_close,
 	.ioctl =	snd_pcm_lib_ioctl,
 	.hw_params =	snd_rme32_capture_hw_params,
-	.hw_free =	snd_rme32_capture_hw_free,
+	.hw_free =	snd_rme32_pcm_hw_free,
 	.prepare =	snd_rme32_capture_prepare,
-	.trigger =	snd_rme32_capture_trigger,
+	.trigger =	snd_rme32_pcm_trigger,
 	.pointer =	snd_rme32_capture_pointer,
 	.copy =		snd_rme32_capture_copy,
+	.mmap =		snd_pcm_lib_mmap_iomem,
 };
 
 static snd_pcm_ops_t snd_rme32_playback_adat_ops = {
@@ -1272,12 +1265,12 @@
 	.close =	snd_rme32_playback_close,
 	.ioctl =	snd_pcm_lib_ioctl,
 	.hw_params =	snd_rme32_playback_hw_params,
-	.hw_free =	snd_rme32_playback_hw_free,
 	.prepare =	snd_rme32_playback_prepare,
-	.trigger =	snd_rme32_playback_trigger,
+	.trigger =	snd_rme32_pcm_trigger,
 	.pointer =	snd_rme32_playback_pointer,
 	.copy =		snd_rme32_playback_copy,
 	.silence =	snd_rme32_playback_silence,
+	.mmap =		snd_pcm_lib_mmap_iomem,
 };
 
 static snd_pcm_ops_t snd_rme32_capture_adat_ops = {
@@ -1285,11 +1278,58 @@
 	.close =	snd_rme32_capture_close,
 	.ioctl =	snd_pcm_lib_ioctl,
 	.hw_params =	snd_rme32_capture_hw_params,
-	.hw_free =	snd_rme32_capture_hw_free,
 	.prepare =	snd_rme32_capture_prepare,
-	.trigger =	snd_rme32_capture_trigger,
+	.trigger =	snd_rme32_pcm_trigger,
 	.pointer =	snd_rme32_capture_pointer,
 	.copy =		snd_rme32_capture_copy,
+	.mmap =		snd_pcm_lib_mmap_iomem,
+};
+
+/* for fullduplex mode */
+static snd_pcm_ops_t snd_rme32_playback_spdif_fd_ops = {
+	.open =		snd_rme32_playback_spdif_open,
+	.close =	snd_rme32_playback_close,
+	.ioctl =	snd_pcm_lib_ioctl,
+	.hw_params =	snd_rme32_playback_hw_params,
+	.hw_free =	snd_rme32_pcm_hw_free,
+	.prepare =	snd_rme32_playback_prepare,
+	.trigger =	snd_rme32_pcm_trigger,
+	.pointer =	snd_rme32_playback_fd_pointer,
+	.ack =		snd_rme32_playback_fd_ack,
+};
+
+static snd_pcm_ops_t snd_rme32_capture_spdif_fd_ops = {
+	.open =		snd_rme32_capture_spdif_open,
+	.close =	snd_rme32_capture_close,
+	.ioctl =	snd_pcm_lib_ioctl,
+	.hw_params =	snd_rme32_capture_hw_params,
+	.hw_free =	snd_rme32_pcm_hw_free,
+	.prepare =	snd_rme32_capture_prepare,
+	.trigger =	snd_rme32_pcm_trigger,
+	.pointer =	snd_rme32_capture_fd_pointer,
+	.ack =		snd_rme32_capture_fd_ack,
+};
+
+static snd_pcm_ops_t snd_rme32_playback_adat_fd_ops = {
+	.open =		snd_rme32_playback_adat_open,
+	.close =	snd_rme32_playback_close,
+	.ioctl =	snd_pcm_lib_ioctl,
+	.hw_params =	snd_rme32_playback_hw_params,
+	.prepare =	snd_rme32_playback_prepare,
+	.trigger =	snd_rme32_pcm_trigger,
+	.pointer =	snd_rme32_playback_fd_pointer,
+	.ack =		snd_rme32_playback_fd_ack,
+};
+
+static snd_pcm_ops_t snd_rme32_capture_adat_fd_ops = {
+	.open =		snd_rme32_capture_adat_open,
+	.close =	snd_rme32_capture_close,
+	.ioctl =	snd_pcm_lib_ioctl,
+	.hw_params =	snd_rme32_capture_hw_params,
+	.prepare =	snd_rme32_capture_prepare,
+	.trigger =	snd_rme32_pcm_trigger,
+	.pointer =	snd_rme32_capture_fd_pointer,
+	.ack =		snd_rme32_capture_fd_ack,
 };
 
 static void snd_rme32_free(void *private_data)
@@ -1300,8 +1340,7 @@
 		return;
 	}
 	if (rme32->irq >= 0) {
-		snd_rme32_playback_stop(rme32);
-		snd_rme32_capture_stop(rme32);
+		snd_rme32_pcm_stop(rme32, 0);
 		free_irq(rme32->irq, (void *) rme32);
 		rme32->irq = -1;
 	}
@@ -1309,9 +1348,9 @@
 		iounmap((void *) rme32->iobase);
 		rme32->iobase = 0;
 	}
-	if (rme32->res_port != NULL) {
-		release_resource(rme32->res_port);
-		rme32->res_port = NULL;
+	if (rme32->port) {
+		pci_release_regions(rme32->pci);
+		rme32->port = 0;
 	}
 }
 
@@ -1319,7 +1358,6 @@
 {
 	rme32_t *rme32 = (rme32_t *) pcm->private_data;
 	rme32->spdif_pcm = NULL;
-	snd_pcm_lib_preallocate_free_for_all(pcm);
 }
 
 static void
@@ -1327,7 +1365,6 @@
 {
 	rme32_t *rme32 = (rme32_t *) pcm->private_data;
 	rme32->adat_pcm = NULL;
-	snd_pcm_lib_preallocate_free_for_all(pcm);
 }
 
 static int __devinit snd_rme32_create(rme32_t * rme32)
@@ -1336,25 +1373,21 @@
 	int err;
 
 	rme32->irq = -1;
+	spin_lock_init(&rme32->lock);
 
 	if ((err = pci_enable_device(pci)) < 0)
 		return err;
 
+	if ((err = pci_request_regions(pci, "RME32")) < 0)
+		return err;
 	rme32->port = pci_resource_start(rme32->pci, 0);
 
-	if ((rme32->res_port = request_mem_region(rme32->port, RME32_IO_SIZE, "RME32")) == NULL) {
-		snd_printk("unable to grab memory region 0x%lx-0x%lx\n",
-			   rme32->port, rme32->port + RME32_IO_SIZE - 1);
-		return -EBUSY;
-	}
-
 	if (request_irq(pci->irq, snd_rme32_interrupt, SA_INTERRUPT | SA_SHIRQ, "RME32", (void *) rme32)) {
 		snd_printk("unable to grab IRQ %d\n", pci->irq);
 		return -EBUSY;
 	}
 	rme32->irq = pci->irq;
 
-	spin_lock_init(&rme32->lock);
 	if ((rme32->iobase = (unsigned long) ioremap_nocache(rme32->port, RME32_IO_SIZE)) == 0) {
 		snd_printk("unable to remap memory region 0x%lx-0x%lx\n",
 			   rme32->port, rme32->port + RME32_IO_SIZE - 1);
@@ -1371,18 +1404,22 @@
 	rme32->spdif_pcm->private_data = rme32;
 	rme32->spdif_pcm->private_free = snd_rme32_free_spdif_pcm;
 	strcpy(rme32->spdif_pcm->name, "Digi32 IEC958");
-	snd_pcm_set_ops(rme32->spdif_pcm, SNDRV_PCM_STREAM_PLAYBACK,
-			&snd_rme32_playback_spdif_ops);
-	snd_pcm_set_ops(rme32->spdif_pcm, SNDRV_PCM_STREAM_CAPTURE,
-			&snd_rme32_capture_spdif_ops);
-
-	rme32->spdif_pcm->info_flags = 0;
-
-	snd_pcm_lib_preallocate_pages_for_all(rme32->spdif_pcm,
-					      SNDRV_DMA_TYPE_CONTINUOUS,
-					      snd_dma_continuous_data(GFP_KERNEL),
-					      RME32_BUFFER_SIZE,
-					      RME32_BUFFER_SIZE);
+	if (rme32->fullduplex_mode) {
+		snd_pcm_set_ops(rme32->spdif_pcm, SNDRV_PCM_STREAM_PLAYBACK,
+				&snd_rme32_playback_spdif_fd_ops);
+		snd_pcm_set_ops(rme32->spdif_pcm, SNDRV_PCM_STREAM_CAPTURE,
+				&snd_rme32_capture_spdif_fd_ops);
+		snd_pcm_lib_preallocate_pages_for_all(rme32->spdif_pcm, SNDRV_DMA_TYPE_CONTINUOUS,
+						      snd_dma_continuous_data(GFP_KERNEL),
+						      0, RME32_MID_BUFFER_SIZE);
+		rme32->spdif_pcm->info_flags = SNDRV_PCM_INFO_JOINT_DUPLEX;
+	} else {
+		snd_pcm_set_ops(rme32->spdif_pcm, SNDRV_PCM_STREAM_PLAYBACK,
+				&snd_rme32_playback_spdif_ops);
+		snd_pcm_set_ops(rme32->spdif_pcm, SNDRV_PCM_STREAM_CAPTURE,
+				&snd_rme32_capture_spdif_ops);
+		rme32->spdif_pcm->info_flags = SNDRV_PCM_INFO_HALF_DUPLEX;
+	}
 
 	/* set up ALSA pcm device for ADAT */
 	if ((pci->device == PCI_DEVICE_ID_DIGI32) ||
@@ -1399,18 +1436,22 @@
 		rme32->adat_pcm->private_data = rme32;
 		rme32->adat_pcm->private_free = snd_rme32_free_adat_pcm;
 		strcpy(rme32->adat_pcm->name, "Digi32 ADAT");
-		snd_pcm_set_ops(rme32->adat_pcm, SNDRV_PCM_STREAM_PLAYBACK, 
-				&snd_rme32_playback_adat_ops);
-		snd_pcm_set_ops(rme32->adat_pcm, SNDRV_PCM_STREAM_CAPTURE, 
-				&snd_rme32_capture_adat_ops);
-		
-		rme32->adat_pcm->info_flags = 0;
-
-		snd_pcm_lib_preallocate_pages_for_all(rme32->adat_pcm, 
-						      SNDRV_DMA_TYPE_CONTINUOUS,
-						      snd_dma_continuous_data(GFP_KERNEL),
-						      RME32_BUFFER_SIZE, 
-						      RME32_BUFFER_SIZE);
+		if (rme32->fullduplex_mode) {
+			snd_pcm_set_ops(rme32->adat_pcm, SNDRV_PCM_STREAM_PLAYBACK, 
+					&snd_rme32_playback_adat_fd_ops);
+			snd_pcm_set_ops(rme32->adat_pcm, SNDRV_PCM_STREAM_CAPTURE, 
+					&snd_rme32_capture_adat_fd_ops);
+			snd_pcm_lib_preallocate_pages_for_all(rme32->adat_pcm, SNDRV_DMA_TYPE_CONTINUOUS,
+							      snd_dma_continuous_data(GFP_KERNEL),
+							      0, RME32_MID_BUFFER_SIZE);
+			rme32->adat_pcm->info_flags = SNDRV_PCM_INFO_JOINT_DUPLEX;
+		} else {
+			snd_pcm_set_ops(rme32->adat_pcm, SNDRV_PCM_STREAM_PLAYBACK, 
+					&snd_rme32_playback_adat_ops);
+			snd_pcm_set_ops(rme32->adat_pcm, SNDRV_PCM_STREAM_CAPTURE, 
+					&snd_rme32_capture_adat_ops);
+			rme32->adat_pcm->info_flags = SNDRV_PCM_INFO_HALF_DUPLEX;
+		}
 	}
 
 
@@ -1418,8 +1459,7 @@
 	rme32->capture_periodsize = 0;
 
 	/* make sure playback/capture is stopped, if by some reason active */
-	snd_rme32_playback_stop(rme32);
-	snd_rme32_capture_stop(rme32);
+	snd_rme32_pcm_stop(rme32, 0);
 
         /* reset DAC */
         snd_rme32_reset_dac(rme32);
@@ -1464,6 +1504,10 @@
 	snd_iprintf(buffer, " (index #%d)\n", rme32->card->number + 1);
 
 	snd_iprintf(buffer, "\nGeneral settings\n");
+	if (rme32->fullduplex_mode)
+		snd_iprintf(buffer, "  Full-duplex mode\n");
+	else
+		snd_iprintf(buffer, "  Half-duplex mode\n");
 	if (RME32_PRO_WITH_8414(rme32)) {
 		snd_iprintf(buffer, "  receiver: CS8414\n");
 	} else {
@@ -1569,26 +1613,24 @@
 snd_rme32_get_loopback_control(snd_kcontrol_t * kcontrol,
 			       snd_ctl_elem_value_t * ucontrol)
 {
-	rme32_t *rme32 = _snd_kcontrol_chip(kcontrol);
-	unsigned long flags;
+	rme32_t *rme32 = snd_kcontrol_chip(kcontrol);
 
-	spin_lock_irqsave(&rme32->lock, flags);
+	spin_lock_irq(&rme32->lock);
 	ucontrol->value.integer.value[0] =
 	    rme32->wcreg & RME32_WCR_SEL ? 0 : 1;
-	spin_unlock_irqrestore(&rme32->lock, flags);
+	spin_unlock_irq(&rme32->lock);
 	return 0;
 }
 static int
 snd_rme32_put_loopback_control(snd_kcontrol_t * kcontrol,
 			       snd_ctl_elem_value_t * ucontrol)
 {
-	rme32_t *rme32 = _snd_kcontrol_chip(kcontrol);
-	unsigned long flags;
+	rme32_t *rme32 = snd_kcontrol_chip(kcontrol);
 	unsigned int val;
 	int change;
 
 	val = ucontrol->value.integer.value[0] ? 0 : RME32_WCR_SEL;
-	spin_lock_irqsave(&rme32->lock, flags);
+	spin_lock_irq(&rme32->lock);
 	val = (rme32->wcreg & ~RME32_WCR_SEL) | val;
 	change = val != rme32->wcreg;
 	if (ucontrol->value.integer.value[0])
@@ -1597,7 +1639,7 @@
 		val |= RME32_WCR_MUTE;
 	writel(rme32->wcreg =
 	       val, rme32->iobase + RME32_IO_CONTROL_REGISTER);
-	spin_unlock_irqrestore(&rme32->lock, flags);
+	spin_unlock_irq(&rme32->lock);
 	return change;
 }
 
@@ -1605,7 +1647,7 @@
 snd_rme32_info_inputtype_control(snd_kcontrol_t * kcontrol,
 				 snd_ctl_elem_info_t * uinfo)
 {
-	rme32_t *rme32 = _snd_kcontrol_chip(kcontrol);
+	rme32_t *rme32 = snd_kcontrol_chip(kcontrol);
 	static char *texts[4] = { "Optical", "Coaxial", "Internal", "XLR" };
 
 	uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
@@ -1635,11 +1677,10 @@
 snd_rme32_get_inputtype_control(snd_kcontrol_t * kcontrol,
 				snd_ctl_elem_value_t * ucontrol)
 {
-	rme32_t *rme32 = _snd_kcontrol_chip(kcontrol);
-	unsigned long flags;
+	rme32_t *rme32 = snd_kcontrol_chip(kcontrol);
 	unsigned int items = 3;
 
-	spin_lock_irqsave(&rme32->lock, flags);
+	spin_lock_irq(&rme32->lock);
 	ucontrol->value.enumerated.item[0] = snd_rme32_getinputtype(rme32);
 
 	switch (rme32->pci->device) {
@@ -1658,15 +1699,14 @@
 		ucontrol->value.enumerated.item[0] = items - 1;
 	}
 
-	spin_unlock_irqrestore(&rme32->lock, flags);
+	spin_unlock_irq(&rme32->lock);
 	return 0;
 }
 static int
 snd_rme32_put_inputtype_control(snd_kcontrol_t * kcontrol,
 				snd_ctl_elem_value_t * ucontrol)
 {
-	rme32_t *rme32 = _snd_kcontrol_chip(kcontrol);
-	unsigned long flags;
+	rme32_t *rme32 = snd_kcontrol_chip(kcontrol);
 	unsigned int val;
 	int change, items = 3;
 
@@ -1684,10 +1724,10 @@
 	}
 	val = ucontrol->value.enumerated.item[0] % items;
 
-	spin_lock_irqsave(&rme32->lock, flags);
+	spin_lock_irq(&rme32->lock);
 	change = val != (unsigned int)snd_rme32_getinputtype(rme32);
 	snd_rme32_setinputtype(rme32, val);
-	spin_unlock_irqrestore(&rme32->lock, flags);
+	spin_unlock_irq(&rme32->lock);
 	return change;
 }
 
@@ -1714,28 +1754,26 @@
 snd_rme32_get_clockmode_control(snd_kcontrol_t * kcontrol,
 				snd_ctl_elem_value_t * ucontrol)
 {
-	rme32_t *rme32 = _snd_kcontrol_chip(kcontrol);
-	unsigned long flags;
+	rme32_t *rme32 = snd_kcontrol_chip(kcontrol);
 
-	spin_lock_irqsave(&rme32->lock, flags);
+	spin_lock_irq(&rme32->lock);
 	ucontrol->value.enumerated.item[0] = snd_rme32_getclockmode(rme32);
-	spin_unlock_irqrestore(&rme32->lock, flags);
+	spin_unlock_irq(&rme32->lock);
 	return 0;
 }
 static int
 snd_rme32_put_clockmode_control(snd_kcontrol_t * kcontrol,
 				snd_ctl_elem_value_t * ucontrol)
 {
-	rme32_t *rme32 = _snd_kcontrol_chip(kcontrol);
-	unsigned long flags;
+	rme32_t *rme32 = snd_kcontrol_chip(kcontrol);
 	unsigned int val;
 	int change;
 
 	val = ucontrol->value.enumerated.item[0] % 3;
-	spin_lock_irqsave(&rme32->lock, flags);
+	spin_lock_irq(&rme32->lock);
 	change = val != (unsigned int)snd_rme32_getclockmode(rme32);
 	snd_rme32_setclockmode(rme32, val);
-	spin_unlock_irqrestore(&rme32->lock, flags);
+	spin_unlock_irq(&rme32->lock);
 	return change;
 }
 
@@ -1770,7 +1808,7 @@
 static int snd_rme32_control_spdif_get(snd_kcontrol_t * kcontrol,
 				       snd_ctl_elem_value_t * ucontrol)
 {
-	rme32_t *rme32 = _snd_kcontrol_chip(kcontrol);
+	rme32_t *rme32 = snd_kcontrol_chip(kcontrol);
 
 	snd_rme32_convert_to_aes(&ucontrol->value.iec958,
 				 rme32->wcreg_spdif);
@@ -1780,16 +1818,15 @@
 static int snd_rme32_control_spdif_put(snd_kcontrol_t * kcontrol,
 				       snd_ctl_elem_value_t * ucontrol)
 {
-	rme32_t *rme32 = _snd_kcontrol_chip(kcontrol);
-	unsigned long flags;
+	rme32_t *rme32 = snd_kcontrol_chip(kcontrol);
 	int change;
 	u32 val;
 
 	val = snd_rme32_convert_from_aes(&ucontrol->value.iec958);
-	spin_lock_irqsave(&rme32->lock, flags);
+	spin_lock_irq(&rme32->lock);
 	change = val != rme32->wcreg_spdif;
 	rme32->wcreg_spdif = val;
-	spin_unlock_irqrestore(&rme32->lock, flags);
+	spin_unlock_irq(&rme32->lock);
 	return change;
 }
 
@@ -1805,7 +1842,7 @@
 					      snd_ctl_elem_value_t *
 					      ucontrol)
 {
-	rme32_t *rme32 = _snd_kcontrol_chip(kcontrol);
+	rme32_t *rme32 = snd_kcontrol_chip(kcontrol);
 
 	snd_rme32_convert_to_aes(&ucontrol->value.iec958,
 				 rme32->wcreg_spdif_stream);
@@ -1816,18 +1853,17 @@
 					      snd_ctl_elem_value_t *
 					      ucontrol)
 {
-	rme32_t *rme32 = _snd_kcontrol_chip(kcontrol);
-	unsigned long flags;
+	rme32_t *rme32 = snd_kcontrol_chip(kcontrol);
 	int change;
 	u32 val;
 
 	val = snd_rme32_convert_from_aes(&ucontrol->value.iec958);
-	spin_lock_irqsave(&rme32->lock, flags);
+	spin_lock_irq(&rme32->lock);
 	change = val != rme32->wcreg_spdif_stream;
 	rme32->wcreg_spdif_stream = val;
 	rme32->wcreg &= ~(RME32_WCR_PRO | RME32_WCR_EMP);
 	writel(rme32->wcreg |= val, rme32->iobase + RME32_IO_CONTROL_REGISTER);
-	spin_unlock_irqrestore(&rme32->lock, flags);
+	spin_unlock_irq(&rme32->lock);
 	return change;
 }
 
@@ -1907,7 +1943,7 @@
 	int idx, err;
 	snd_kcontrol_t *kctl;
 
-	for (idx = 0; idx < 7; idx++) {
+	for (idx = 0; idx < (int)ARRAY_SIZE(snd_rme32_controls); idx++) {
 		if ((err = snd_ctl_add(card, kctl = snd_ctl_new1(&snd_rme32_controls[idx], rme32))) < 0)
 			return err;
 		if (idx == 1)	/* IEC958 (S/PDIF) Stream */
@@ -1952,6 +1988,8 @@
 	rme32->card = card;
 	rme32->pci = pci;
 	snd_card_set_dev(card, &pci->dev);
+        if (fullduplex[dev])
+		rme32->fullduplex_mode = 1;
 	if ((err = snd_rme32_create(rme32)) < 0) {
 		snd_card_free(card);
 		return err;
diff -Nru a/sound/pci/rme96.c b/sound/pci/rme96.c
--- a/sound/pci/rme96.c	2004-10-18 14:56:28 -07:00
+++ b/sound/pci/rme96.c	2004-10-18 14:56:28 -07:00
@@ -47,8 +47,7 @@
 MODULE_DESCRIPTION("RME Digi96, Digi96/8, Digi96/8 PRO, Digi96/8 PST, "
 		   "Digi96/8 PAD");
 MODULE_LICENSE("GPL");
-MODULE_CLASSES("{sound}");
-MODULE_DEVICES("{{RME,Digi96},"
+MODULE_SUPPORTED_DEVICE("{{RME,Digi96},"
 		"{RME,Digi96/8},"
 		"{RME,Digi96/8 PRO},"
 		"{RME,Digi96/8 PST},"
@@ -61,13 +60,10 @@
 
 module_param_array(index, int, boot_devs, 0444);
 MODULE_PARM_DESC(index, "Index value for RME Digi96 soundcard.");
-MODULE_PARM_SYNTAX(index, SNDRV_INDEX_DESC);
 module_param_array(id, charp, boot_devs, 0444);
 MODULE_PARM_DESC(id, "ID string for RME Digi96 soundcard.");
-MODULE_PARM_SYNTAX(id, SNDRV_ID_DESC);
 module_param_array(enable, bool, boot_devs, 0444);
 MODULE_PARM_DESC(enable, "Enable RME Digi96 soundcard.");
-MODULE_PARM_SYNTAX(enable, SNDRV_ENABLE_DESC);
 
 /*
  * Defines for RME Digi96 series, from internal RME reference documents
@@ -229,7 +225,6 @@
 	spinlock_t    lock;
 	int irq;
 	unsigned long port;
-	struct resource *res_port;
 	unsigned long iobase;
 	
 	u32 wcreg;    /* cached write control register value */
@@ -250,10 +245,6 @@
         size_t playback_periodsize; /* in bytes, zero if not used */
 	size_t capture_periodsize; /* in bytes, zero if not used */
 
-        snd_pcm_uframes_t playback_last_appl_ptr;
-	size_t playback_ptr;
-	size_t capture_ptr;
-
 	snd_card_t         *card;
 	snd_pcm_t          *spdif_pcm;
 	snd_pcm_t          *adat_pcm; 
@@ -349,7 +340,7 @@
 			   snd_pcm_uframes_t pos,
 			   snd_pcm_uframes_t count)
 {
-	rme96_t *rme96 = _snd_pcm_substream_chip(substream);
+	rme96_t *rme96 = snd_pcm_substream_chip(substream);
 	count <<= rme96->playback_frlog;
 	pos <<= rme96->playback_frlog;
 	memset_io(rme96->iobase + RME96_IO_PLAY_BUFFER + pos,
@@ -364,7 +355,7 @@
 			void __user *src,
 			snd_pcm_uframes_t count)
 {
-	rme96_t *rme96 = _snd_pcm_substream_chip(substream);
+	rme96_t *rme96 = snd_pcm_substream_chip(substream);
 	count <<= rme96->playback_frlog;
 	pos <<= rme96->playback_frlog;
 	copy_from_user_toio(rme96->iobase + RME96_IO_PLAY_BUFFER + pos, src,
@@ -379,7 +370,7 @@
 		       void __user *dst,
 		       snd_pcm_uframes_t count)
 {
-	rme96_t *rme96 = _snd_pcm_substream_chip(substream);
+	rme96_t *rme96 = snd_pcm_substream_chip(substream);
 	count <<= rme96->capture_frlog;
 	pos <<= rme96->capture_frlog;
 	copy_to_user_fromio(dst, rme96->iobase + RME96_IO_REC_BUFFER + pos,
@@ -392,7 +383,7 @@
  */
 static snd_pcm_hardware_t snd_rme96_playback_spdif_info =
 {
-	.info =		     (SNDRV_PCM_INFO_MMAP |
+	.info =		     (SNDRV_PCM_INFO_MMAP_IOMEM |
 			      SNDRV_PCM_INFO_MMAP_VALID |
 			      SNDRV_PCM_INFO_INTERLEAVED |
 			      SNDRV_PCM_INFO_PAUSE),
@@ -421,7 +412,7 @@
  */
 static snd_pcm_hardware_t snd_rme96_capture_spdif_info =
 {
-	.info =		     (SNDRV_PCM_INFO_MMAP |
+	.info =		     (SNDRV_PCM_INFO_MMAP_IOMEM |
 			      SNDRV_PCM_INFO_MMAP_VALID |
 			      SNDRV_PCM_INFO_INTERLEAVED |
 			      SNDRV_PCM_INFO_PAUSE),
@@ -450,7 +441,7 @@
  */
 static snd_pcm_hardware_t snd_rme96_playback_adat_info =
 {
-	.info =		     (SNDRV_PCM_INFO_MMAP |
+	.info =		     (SNDRV_PCM_INFO_MMAP_IOMEM |
 			      SNDRV_PCM_INFO_MMAP_VALID |
 			      SNDRV_PCM_INFO_INTERLEAVED |
 			      SNDRV_PCM_INFO_PAUSE),
@@ -475,7 +466,7 @@
  */
 static snd_pcm_hardware_t snd_rme96_capture_adat_info =
 {
-	.info =		     (SNDRV_PCM_INFO_MMAP |
+	.info =		     (SNDRV_PCM_INFO_MMAP_IOMEM |
 			      SNDRV_PCM_INFO_MMAP_VALID |
 			      SNDRV_PCM_INFO_INTERLEAVED |
 			      SNDRV_PCM_INFO_PAUSE),
@@ -991,28 +982,30 @@
 snd_rme96_playback_hw_params(snd_pcm_substream_t *substream,
 			     snd_pcm_hw_params_t *params)
 {
-	unsigned long flags;        
-	rme96_t *rme96 = _snd_pcm_substream_chip(substream);
+	rme96_t *rme96 = snd_pcm_substream_chip(substream);
+	snd_pcm_runtime_t *runtime = substream->runtime;
 	int err, rate, dummy;
 
-	if ((err = snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(params))) < 0)
-		return err;
-	spin_lock_irqsave(&rme96->lock, flags);
+	runtime->dma_area = (void *)(rme96->iobase + RME96_IO_PLAY_BUFFER);
+	runtime->dma_addr = rme96->port + RME96_IO_PLAY_BUFFER;
+	runtime->dma_bytes = RME96_BUFFER_SIZE;
+
+	spin_lock_irq(&rme96->lock);
 	if (!(rme96->wcreg & RME96_WCR_MASTER) &&
             snd_rme96_getinputtype(rme96) != RME96_INPUT_ANALOG &&
 	    (rate = snd_rme96_capture_getrate(rme96, &dummy)) > 0)
 	{
                 /* slave clock */
                 if ((int)params_rate(params) != rate) {
-		        spin_unlock_irqrestore(&rme96->lock, flags);
+			spin_unlock_irq(&rme96->lock);
 			return -EIO;                    
                 }
 	} else if ((err = snd_rme96_playback_setrate(rme96, params_rate(params))) < 0) {
-		spin_unlock_irqrestore(&rme96->lock, flags);
+		spin_unlock_irq(&rme96->lock);
 		return err;
 	}
 	if ((err = snd_rme96_playback_setformat(rme96, params_format(params))) < 0) {
-		spin_unlock_irqrestore(&rme96->lock, flags);
+		spin_unlock_irq(&rme96->lock);
 		return err;
 	}
 	snd_rme96_setframelog(rme96, params_channels(params), 1);
@@ -1020,7 +1013,7 @@
 		if (params_period_size(params) << rme96->playback_frlog !=
 		    rme96->capture_periodsize)
 		{
-			spin_unlock_irqrestore(&rme96->lock, flags);
+			spin_unlock_irq(&rme96->lock);
 			return -EBUSY;
 		}
 	}
@@ -1032,50 +1025,44 @@
 		rme96->wcreg &= ~(RME96_WCR_PRO | RME96_WCR_DOLBY | RME96_WCR_EMP);
 		writel(rme96->wcreg |= rme96->wcreg_spdif_stream, rme96->iobase + RME96_IO_CONTROL_REGISTER);
 	}
-	spin_unlock_irqrestore(&rme96->lock, flags);
+	spin_unlock_irq(&rme96->lock);
 		
 	return 0;
 }
 
 static int
-snd_rme96_playback_hw_free(snd_pcm_substream_t *substream)
-{
-	snd_pcm_lib_free_pages(substream);
-	return 0;
-}
-
-static int
 snd_rme96_capture_hw_params(snd_pcm_substream_t *substream,
 			    snd_pcm_hw_params_t *params)
 {
-	unsigned long flags;
-	rme96_t *rme96 = _snd_pcm_substream_chip(substream);
+	rme96_t *rme96 = snd_pcm_substream_chip(substream);
 	snd_pcm_runtime_t *runtime = substream->runtime;
 	int err, isadat, rate;
 	
-	if ((err = snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(params))) < 0)
-		return err;
-	spin_lock_irqsave(&rme96->lock, flags);
+	runtime->dma_area = (void *)(rme96->iobase + RME96_IO_REC_BUFFER);
+	runtime->dma_addr = rme96->port + RME96_IO_REC_BUFFER;
+	runtime->dma_bytes = RME96_BUFFER_SIZE;
+
+	spin_lock_irq(&rme96->lock);
 	if ((err = snd_rme96_capture_setformat(rme96, params_format(params))) < 0) {
-		spin_unlock_irqrestore(&rme96->lock, flags);
+		spin_unlock_irq(&rme96->lock);
 		return err;
 	}
 	if (snd_rme96_getinputtype(rme96) == RME96_INPUT_ANALOG) {
 		if ((err = snd_rme96_capture_analog_setrate(rme96,
 							    params_rate(params))) < 0)
 		{
-			spin_unlock_irqrestore(&rme96->lock, flags);
+			spin_unlock_irq(&rme96->lock);
 			return err;
 		}
 	} else if ((rate = snd_rme96_capture_getrate(rme96, &isadat)) > 0) {
                 if ((int)params_rate(params) != rate) {
-			spin_unlock_irqrestore(&rme96->lock, flags);
+			spin_unlock_irq(&rme96->lock);
 			return -EIO;                    
                 }
                 if ((isadat && runtime->hw.channels_min == 2) ||
                     (!isadat && runtime->hw.channels_min == 8))
                 {
-			spin_unlock_irqrestore(&rme96->lock, flags);
+			spin_unlock_irq(&rme96->lock);
 			return -EIO;
                 }
         }
@@ -1084,33 +1071,24 @@
 		if (params_period_size(params) << rme96->capture_frlog !=
 		    rme96->playback_periodsize)
 		{
-			spin_unlock_irqrestore(&rme96->lock, flags);
+			spin_unlock_irq(&rme96->lock);
 			return -EBUSY;
 		}
 	}
 	rme96->capture_periodsize =
 		params_period_size(params) << rme96->capture_frlog;
 	snd_rme96_set_period_properties(rme96, rme96->capture_periodsize);
-	spin_unlock_irqrestore(&rme96->lock, flags);
+	spin_unlock_irq(&rme96->lock);
 
 	return 0;
 }
 
-static int
-snd_rme96_capture_hw_free(snd_pcm_substream_t *substream)
-{
-	snd_pcm_lib_free_pages(substream);
-	return 0;
-}
-
 static void
 snd_rme96_playback_start(rme96_t *rme96,
 			 int from_pause)
 {
 	if (!from_pause) {
 		writel(0, rme96->iobase + RME96_IO_RESET_PLAY_POS);
-		rme96->playback_last_appl_ptr = 0;
-		rme96->playback_ptr = 0;
 	}
 
 	rme96->wcreg |= RME96_WCR_START;
@@ -1123,7 +1101,6 @@
 {
 	if (!from_pause) {
 		writel(0, rme96->iobase + RME96_IO_RESET_REC_POS);
-		rme96->capture_ptr = 0;
 	}
 
 	rme96->wcreg |= RME96_WCR_START_2;
@@ -1186,10 +1163,8 @@
 
 static unsigned int period_bytes[] = { RME96_SMALL_BLOCK_SIZE, RME96_LARGE_BLOCK_SIZE };
 
-#define PERIOD_BYTES sizeof(period_bytes) / sizeof(period_bytes[0])
-
 static snd_pcm_hw_constraint_list_t hw_constraints_period_bytes = {
-	.count = PERIOD_BYTES,
+	.count = ARRAY_SIZE(period_bytes),
 	.list = period_bytes,
 	.mask = 0
 };
@@ -1197,24 +1172,21 @@
 static int
 snd_rme96_playback_spdif_open(snd_pcm_substream_t *substream)
 {
-	unsigned long flags;
         int rate, dummy;
-	rme96_t *rme96 = _snd_pcm_substream_chip(substream);
+	rme96_t *rme96 = snd_pcm_substream_chip(substream);
 	snd_pcm_runtime_t *runtime = substream->runtime;
 
 	snd_pcm_set_sync(substream);
 
-	spin_lock_irqsave(&rme96->lock, flags);	
+	spin_lock_irq(&rme96->lock);	
         if (rme96->playback_substream != NULL) {
-	        spin_unlock_irqrestore(&rme96->lock, flags);
+		spin_unlock_irq(&rme96->lock);
                 return -EBUSY;
         }
 	rme96->wcreg &= ~RME96_WCR_ADAT;
 	writel(rme96->wcreg, rme96->iobase + RME96_IO_CONTROL_REGISTER);
 	rme96->playback_substream = substream;
-	rme96->playback_last_appl_ptr = 0;
-	rme96->playback_ptr = 0;
-	spin_unlock_irqrestore(&rme96->lock, flags);
+	spin_unlock_irq(&rme96->lock);
 
 	runtime->hw = snd_rme96_playback_spdif_info;
 	if (!(rme96->wcreg & RME96_WCR_MASTER) &&
@@ -1239,9 +1211,8 @@
 static int
 snd_rme96_capture_spdif_open(snd_pcm_substream_t *substream)
 {
-	unsigned long flags;
         int isadat, rate;
-	rme96_t *rme96 = _snd_pcm_substream_chip(substream);
+	rme96_t *rme96 = snd_pcm_substream_chip(substream);
 	snd_pcm_runtime_t *runtime = substream->runtime;
 
 	snd_pcm_set_sync(substream);
@@ -1258,14 +1229,13 @@
                 runtime->hw.rate_max = rate;
         }
         
-	spin_lock_irqsave(&rme96->lock, flags);
+	spin_lock_irq(&rme96->lock);
         if (rme96->capture_substream != NULL) {
-	        spin_unlock_irqrestore(&rme96->lock, flags);
+		spin_unlock_irq(&rme96->lock);
                 return -EBUSY;
         }
 	rme96->capture_substream = substream;
-	rme96->capture_ptr = 0;
-	spin_unlock_irqrestore(&rme96->lock, flags);
+	spin_unlock_irq(&rme96->lock);
 	
 	snd_pcm_hw_constraint_minmax(runtime, SNDRV_PCM_HW_PARAM_BUFFER_BYTES, RME96_BUFFER_SIZE, RME96_BUFFER_SIZE);
 	snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_PERIOD_BYTES, &hw_constraints_period_bytes);
@@ -1276,24 +1246,21 @@
 static int
 snd_rme96_playback_adat_open(snd_pcm_substream_t *substream)
 {
-	unsigned long flags;
         int rate, dummy;
-	rme96_t *rme96 = _snd_pcm_substream_chip(substream);
+	rme96_t *rme96 = snd_pcm_substream_chip(substream);
 	snd_pcm_runtime_t *runtime = substream->runtime;        
 	
 	snd_pcm_set_sync(substream);
 
-	spin_lock_irqsave(&rme96->lock, flags);	
+	spin_lock_irq(&rme96->lock);	
         if (rme96->playback_substream != NULL) {
-	        spin_unlock_irqrestore(&rme96->lock, flags);
+		spin_unlock_irq(&rme96->lock);
                 return -EBUSY;
         }
 	rme96->wcreg |= RME96_WCR_ADAT;
 	writel(rme96->wcreg, rme96->iobase + RME96_IO_CONTROL_REGISTER);
 	rme96->playback_substream = substream;
-	rme96->playback_last_appl_ptr = 0;
-	rme96->playback_ptr = 0;
-	spin_unlock_irqrestore(&rme96->lock, flags);
+	spin_unlock_irq(&rme96->lock);
 	
 	runtime->hw = snd_rme96_playback_adat_info;
 	if (!(rme96->wcreg & RME96_WCR_MASTER) &&
@@ -1313,9 +1280,8 @@
 static int
 snd_rme96_capture_adat_open(snd_pcm_substream_t *substream)
 {
-	unsigned long flags;
         int isadat, rate;
-	rme96_t *rme96 = _snd_pcm_substream_chip(substream);
+	rme96_t *rme96 = snd_pcm_substream_chip(substream);
 	snd_pcm_runtime_t *runtime = substream->runtime;
 
 	snd_pcm_set_sync(substream);
@@ -1335,14 +1301,13 @@
                 runtime->hw.rate_max = rate;
         }
         
-	spin_lock_irqsave(&rme96->lock, flags);	
+	spin_lock_irq(&rme96->lock);	
         if (rme96->capture_substream != NULL) {
-	        spin_unlock_irqrestore(&rme96->lock, flags);
+		spin_unlock_irq(&rme96->lock);
                 return -EBUSY;
         }
 	rme96->capture_substream = substream;
-	rme96->capture_ptr = 0;
-	spin_unlock_irqrestore(&rme96->lock, flags);
+	spin_unlock_irq(&rme96->lock);
 
 	snd_pcm_hw_constraint_minmax(runtime, SNDRV_PCM_HW_PARAM_BUFFER_BYTES, RME96_BUFFER_SIZE, RME96_BUFFER_SIZE);
 	snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_PERIOD_BYTES, &hw_constraints_period_bytes);
@@ -1352,18 +1317,17 @@
 static int
 snd_rme96_playback_close(snd_pcm_substream_t *substream)
 {
-	unsigned long flags;
-	rme96_t *rme96 = _snd_pcm_substream_chip(substream);
+	rme96_t *rme96 = snd_pcm_substream_chip(substream);
 	int spdif = 0;
 
-	spin_lock_irqsave(&rme96->lock, flags);	
+	spin_lock_irq(&rme96->lock);	
 	if (RME96_ISPLAYING(rme96)) {
 		snd_rme96_playback_stop(rme96);
 	}
 	rme96->playback_substream = NULL;
 	rme96->playback_periodsize = 0;
 	spdif = (rme96->wcreg & RME96_WCR_ADAT) == 0;
-	spin_unlock_irqrestore(&rme96->lock, flags);
+	spin_unlock_irq(&rme96->lock);
 	if (spdif) {
 		rme96->spdif_ctl->vd[0].access |= SNDRV_CTL_ELEM_ACCESS_INACTIVE;
 		snd_ctl_notify(rme96->card, SNDRV_CTL_EVENT_MASK_VALUE |
@@ -1375,46 +1339,43 @@
 static int
 snd_rme96_capture_close(snd_pcm_substream_t *substream)
 {
-	unsigned long flags;
-	rme96_t *rme96 = _snd_pcm_substream_chip(substream);
+	rme96_t *rme96 = snd_pcm_substream_chip(substream);
 	
-	spin_lock_irqsave(&rme96->lock, flags);	
+	spin_lock_irq(&rme96->lock);	
 	if (RME96_ISRECORDING(rme96)) {
 		snd_rme96_capture_stop(rme96);
 	}
 	rme96->capture_substream = NULL;
 	rme96->capture_periodsize = 0;
-	spin_unlock_irqrestore(&rme96->lock, flags);
+	spin_unlock_irq(&rme96->lock);
 	return 0;
 }
 
 static int
 snd_rme96_playback_prepare(snd_pcm_substream_t *substream)
 {
-	rme96_t *rme96 = _snd_pcm_substream_chip(substream);
-	unsigned long flags;
+	rme96_t *rme96 = snd_pcm_substream_chip(substream);
 	
-	spin_lock_irqsave(&rme96->lock, flags);	
+	spin_lock_irq(&rme96->lock);	
 	if (RME96_ISPLAYING(rme96)) {
 		snd_rme96_playback_stop(rme96);
 	}
 	writel(0, rme96->iobase + RME96_IO_RESET_PLAY_POS);
-	spin_unlock_irqrestore(&rme96->lock, flags);
+	spin_unlock_irq(&rme96->lock);
 	return 0;
 }
 
 static int
 snd_rme96_capture_prepare(snd_pcm_substream_t *substream)
 {
-	rme96_t *rme96 = _snd_pcm_substream_chip(substream);
-	unsigned long flags;
+	rme96_t *rme96 = snd_pcm_substream_chip(substream);
 	
-	spin_lock_irqsave(&rme96->lock, flags);	
+	spin_lock_irq(&rme96->lock);	
 	if (RME96_ISRECORDING(rme96)) {
 		snd_rme96_capture_stop(rme96);
 	}
 	writel(0, rme96->iobase + RME96_IO_RESET_REC_POS);
-	spin_unlock_irqrestore(&rme96->lock, flags);
+	spin_unlock_irq(&rme96->lock);
 	return 0;
 }
 
@@ -1422,7 +1383,7 @@
 snd_rme96_playback_trigger(snd_pcm_substream_t *substream, 
 			   int cmd)
 {
-	rme96_t *rme96 = _snd_pcm_substream_chip(substream);
+	rme96_t *rme96 = snd_pcm_substream_chip(substream);
 
 	switch (cmd) {
 	case SNDRV_PCM_TRIGGER_START:
@@ -1465,7 +1426,7 @@
 snd_rme96_capture_trigger(snd_pcm_substream_t *substream, 
 			  int cmd)
 {
-	rme96_t *rme96 = _snd_pcm_substream_chip(substream);
+	rme96_t *rme96 = snd_pcm_substream_chip(substream);
 
 	switch (cmd) {
 	case SNDRV_PCM_TRIGGER_START:
@@ -1508,75 +1469,15 @@
 static snd_pcm_uframes_t
 snd_rme96_playback_pointer(snd_pcm_substream_t *substream)
 {
-	rme96_t *rme96 = _snd_pcm_substream_chip(substream);
-	snd_pcm_runtime_t *runtime = substream->runtime;
-	snd_pcm_sframes_t diff;
-	size_t bytes;
-	
-	if (runtime->access == SNDRV_PCM_ACCESS_MMAP_INTERLEAVED) {
-		diff = runtime->control->appl_ptr -
-		    rme96->playback_last_appl_ptr;
- 	        rme96->playback_last_appl_ptr = runtime->control->appl_ptr;
-	        if (diff != 0 &&
-		    diff < -(snd_pcm_sframes_t)(runtime->boundary >> 1))
-		{
-		        diff += runtime->boundary;
-		}
-		bytes = diff << rme96->playback_frlog;
-		
-		if (bytes > RME96_BUFFER_SIZE - rme96->playback_ptr) {
-			memcpy_toio((void *)(rme96->iobase + RME96_IO_PLAY_BUFFER +
-					     rme96->playback_ptr),
-				    runtime->dma_area + rme96->playback_ptr,
-				    RME96_BUFFER_SIZE - rme96->playback_ptr);
-		        bytes -= RME96_BUFFER_SIZE - rme96->playback_ptr;
-			if (bytes > RME96_BUFFER_SIZE) {
-			        bytes = RME96_BUFFER_SIZE;
-			}
-			memcpy_toio((void *)(rme96->iobase + RME96_IO_PLAY_BUFFER),
-				    runtime->dma_area,
-				    bytes);
-			rme96->playback_ptr = bytes;
-		} else if (bytes != 0) {
-			memcpy_toio((void *)(rme96->iobase + RME96_IO_PLAY_BUFFER +
-					     rme96->playback_ptr),
-				    runtime->dma_area + rme96->playback_ptr,
-				    bytes);
-			rme96->playback_ptr += bytes;
-		}
-	}
+	rme96_t *rme96 = snd_pcm_substream_chip(substream);
 	return snd_rme96_playback_ptr(rme96);
 }
 
 static snd_pcm_uframes_t
 snd_rme96_capture_pointer(snd_pcm_substream_t *substream)
 {
-	rme96_t *rme96 = _snd_pcm_substream_chip(substream);
-	snd_pcm_runtime_t *runtime = substream->runtime;
-	snd_pcm_uframes_t frameptr;
-	size_t ptr;
-
-	frameptr = snd_rme96_capture_ptr(rme96);
-	if (runtime->access == SNDRV_PCM_ACCESS_MMAP_INTERLEAVED) {
-		ptr = frameptr << rme96->capture_frlog;
-		if (ptr > rme96->capture_ptr) {
-			memcpy_fromio(runtime->dma_area + rme96->capture_ptr,
-				      (void *)(rme96->iobase + RME96_IO_REC_BUFFER +
-					       rme96->capture_ptr),
-				      ptr - rme96->capture_ptr);
-			rme96->capture_ptr += ptr - rme96->capture_ptr;
-		} else if (ptr < rme96->capture_ptr) {
-			memcpy_fromio(runtime->dma_area + rme96->capture_ptr,
-				      (void *)(rme96->iobase + RME96_IO_REC_BUFFER +
-					       rme96->capture_ptr),
-				      RME96_BUFFER_SIZE - rme96->capture_ptr);
-			memcpy_fromio(runtime->dma_area,
-				      (void *)(rme96->iobase + RME96_IO_REC_BUFFER),
-				      ptr);
-			rme96->capture_ptr = ptr;
-		}
-	}
-	return frameptr;
+	rme96_t *rme96 = snd_pcm_substream_chip(substream);
+	return snd_rme96_capture_ptr(rme96);
 }
 
 static snd_pcm_ops_t snd_rme96_playback_spdif_ops = {
@@ -1584,12 +1485,12 @@
 	.close =	snd_rme96_playback_close,
 	.ioctl =	snd_pcm_lib_ioctl,
 	.hw_params =	snd_rme96_playback_hw_params,
-	.hw_free =	snd_rme96_playback_hw_free,
 	.prepare =	snd_rme96_playback_prepare,
 	.trigger =	snd_rme96_playback_trigger,
 	.pointer =	snd_rme96_playback_pointer,
 	.copy =		snd_rme96_playback_copy,
 	.silence =	snd_rme96_playback_silence,
+	.mmap =		snd_pcm_lib_mmap_iomem,
 };
 
 static snd_pcm_ops_t snd_rme96_capture_spdif_ops = {
@@ -1597,11 +1498,11 @@
 	.close =	snd_rme96_capture_close,
 	.ioctl =	snd_pcm_lib_ioctl,
 	.hw_params =	snd_rme96_capture_hw_params,
-	.hw_free =	snd_rme96_capture_hw_free,
 	.prepare =	snd_rme96_capture_prepare,
 	.trigger =	snd_rme96_capture_trigger,
 	.pointer =	snd_rme96_capture_pointer,
 	.copy =		snd_rme96_capture_copy,
+	.mmap =		snd_pcm_lib_mmap_iomem,
 };
 
 static snd_pcm_ops_t snd_rme96_playback_adat_ops = {
@@ -1609,12 +1510,12 @@
 	.close =	snd_rme96_playback_close,
 	.ioctl =	snd_pcm_lib_ioctl,
 	.hw_params =	snd_rme96_playback_hw_params,
-	.hw_free =	snd_rme96_playback_hw_free,
 	.prepare =	snd_rme96_playback_prepare,
 	.trigger =	snd_rme96_playback_trigger,
 	.pointer =	snd_rme96_playback_pointer,
 	.copy =		snd_rme96_playback_copy,
 	.silence =	snd_rme96_playback_silence,
+	.mmap =		snd_pcm_lib_mmap_iomem,
 };
 
 static snd_pcm_ops_t snd_rme96_capture_adat_ops = {
@@ -1622,11 +1523,11 @@
 	.close =	snd_rme96_capture_close,
 	.ioctl =	snd_pcm_lib_ioctl,
 	.hw_params =	snd_rme96_capture_hw_params,
-	.hw_free =	snd_rme96_capture_hw_free,
 	.prepare =	snd_rme96_capture_prepare,
 	.trigger =	snd_rme96_capture_trigger,
 	.pointer =	snd_rme96_capture_pointer,
 	.copy =		snd_rme96_capture_copy,
+	.mmap =		snd_pcm_lib_mmap_iomem,
 };
 
 static void
@@ -1649,10 +1550,9 @@
 		iounmap((void *)rme96->iobase);
 		rme96->iobase = 0;
 	}
-	if (rme96->res_port != NULL) {
-		release_resource(rme96->res_port);
-		kfree_nocheck(rme96->res_port);
-		rme96->res_port = NULL;
+	if (rme96->port) {
+		pci_release_regions(rme96->pci);
+		rme96->port = 0;
 	}
 }
 
@@ -1661,7 +1561,6 @@
 {
 	rme96_t *rme96 = (rme96_t *) pcm->private_data;
 	rme96->spdif_pcm = NULL;
-	snd_pcm_lib_preallocate_free_for_all(pcm);
 }
 
 static void
@@ -1669,7 +1568,6 @@
 {
 	rme96_t *rme96 = (rme96_t *) pcm->private_data;
 	rme96->adat_pcm = NULL;
-	snd_pcm_lib_preallocate_free_for_all(pcm);
 }
 
 static int __devinit
@@ -1679,24 +1577,21 @@
 	int err;
 
 	rme96->irq = -1;
+	spin_lock_init(&rme96->lock);
 
 	if ((err = pci_enable_device(pci)) < 0)
 		return err;
 
+	if ((err = pci_request_regions(pci, "RME96")) < 0)
+		return err;
 	rme96->port = pci_resource_start(rme96->pci, 0);
 
-	if ((rme96->res_port = request_mem_region(rme96->port, RME96_IO_SIZE, "RME96")) == NULL) {
-		snd_printk("unable to grab memory region 0x%lx-0x%lx\n", rme96->port, rme96->port + RME96_IO_SIZE - 1);
-		return -EBUSY;
-	}
-
 	if (request_irq(pci->irq, snd_rme96_interrupt, SA_INTERRUPT|SA_SHIRQ, "RME96", (void *)rme96)) {
 		snd_printk("unable to grab IRQ %d\n", pci->irq);
 		return -EBUSY;
 	}
 	rme96->irq = pci->irq;
 
-	spin_lock_init(&rme96->lock);
 	if ((rme96->iobase = (unsigned long) ioremap_nocache(rme96->port, RME96_IO_SIZE)) == 0) {
 		snd_printk("unable to remap memory region 0x%lx-0x%lx\n", rme96->port, rme96->port + RME96_IO_SIZE - 1);
 		return -ENOMEM;
@@ -1719,12 +1614,6 @@
 
 	rme96->spdif_pcm->info_flags = 0;
 
-	snd_pcm_lib_preallocate_pages_for_all(rme96->spdif_pcm,
-					      SNDRV_DMA_TYPE_CONTINUOUS,
-					      snd_dma_continuous_data(GFP_KERNEL),
-					      RME96_BUFFER_SIZE,
-					      RME96_BUFFER_SIZE);
-
 	/* set up ALSA pcm device for ADAT */
 	if (pci->device == PCI_DEVICE_ID_DIGI96) {
 		/* ADAT is not available on the base model */
@@ -1742,12 +1631,6 @@
 		snd_pcm_set_ops(rme96->adat_pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_rme96_capture_adat_ops);
 		
 		rme96->adat_pcm->info_flags = 0;
-
-		snd_pcm_lib_preallocate_pages_for_all(rme96->adat_pcm,
-						      SNDRV_DMA_TYPE_CONTINUOUS,
-						      snd_dma_continuous_data(GFP_KERNEL),
-						      RME96_BUFFER_SIZE,
-						      RME96_BUFFER_SIZE);
 	}
 
 	rme96->playback_periodsize = 0;
@@ -1958,28 +1841,26 @@
 static int
 snd_rme96_get_loopback_control(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
 {
-	rme96_t *rme96 = _snd_kcontrol_chip(kcontrol);
-	unsigned long flags;
+	rme96_t *rme96 = snd_kcontrol_chip(kcontrol);
 	
-	spin_lock_irqsave(&rme96->lock, flags);
+	spin_lock_irq(&rme96->lock);
 	ucontrol->value.integer.value[0] = rme96->wcreg & RME96_WCR_SEL ? 0 : 1;
-	spin_unlock_irqrestore(&rme96->lock, flags);
+	spin_unlock_irq(&rme96->lock);
 	return 0;
 }
 static int
 snd_rme96_put_loopback_control(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
 {
-	rme96_t *rme96 = _snd_kcontrol_chip(kcontrol);
-	unsigned long flags;
+	rme96_t *rme96 = snd_kcontrol_chip(kcontrol);
 	unsigned int val;
 	int change;
 	
 	val = ucontrol->value.integer.value[0] ? 0 : RME96_WCR_SEL;
-	spin_lock_irqsave(&rme96->lock, flags);
+	spin_lock_irq(&rme96->lock);
 	val = (rme96->wcreg & ~RME96_WCR_SEL) | val;
 	change = val != rme96->wcreg;
 	writel(rme96->wcreg = val, rme96->iobase + RME96_IO_CONTROL_REGISTER);
-	spin_unlock_irqrestore(&rme96->lock, flags);
+	spin_unlock_irq(&rme96->lock);
 	return change;
 }
 
@@ -1987,7 +1868,7 @@
 snd_rme96_info_inputtype_control(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)
 {
 	static char *_texts[5] = { "Optical", "Coaxial", "Internal", "XLR", "Analog" };
-	rme96_t *rme96 = _snd_kcontrol_chip(kcontrol);
+	rme96_t *rme96 = snd_kcontrol_chip(kcontrol);
 	char *texts[5] = { _texts[0], _texts[1], _texts[2], _texts[3], _texts[4] };
 	
 	uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
@@ -2023,11 +1904,10 @@
 static int
 snd_rme96_get_inputtype_control(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
 {
-	rme96_t *rme96 = _snd_kcontrol_chip(kcontrol);
-	unsigned long flags;
+	rme96_t *rme96 = snd_kcontrol_chip(kcontrol);
 	unsigned int items = 3;
 	
-	spin_lock_irqsave(&rme96->lock, flags);
+	spin_lock_irq(&rme96->lock);
 	ucontrol->value.enumerated.item[0] = snd_rme96_getinputtype(rme96);
 	
 	switch (rme96->pci->device) {
@@ -2057,14 +1937,13 @@
 		ucontrol->value.enumerated.item[0] = items - 1;
 	}
 	
-	spin_unlock_irqrestore(&rme96->lock, flags);
+	spin_unlock_irq(&rme96->lock);
 	return 0;
 }
 static int
 snd_rme96_put_inputtype_control(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
 {
-	rme96_t *rme96 = _snd_kcontrol_chip(kcontrol);
-	unsigned long flags;
+	rme96_t *rme96 = snd_kcontrol_chip(kcontrol);
 	unsigned int val;
 	int change, items = 3;
 	
@@ -2096,10 +1975,10 @@
 		}
 	}
 	
-	spin_lock_irqsave(&rme96->lock, flags);
+	spin_lock_irq(&rme96->lock);
 	change = (int)val != snd_rme96_getinputtype(rme96);
 	snd_rme96_setinputtype(rme96, val);
-	spin_unlock_irqrestore(&rme96->lock, flags);
+	spin_unlock_irq(&rme96->lock);
 	return change;
 }
 
@@ -2120,27 +1999,25 @@
 static int
 snd_rme96_get_clockmode_control(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
 {
-	rme96_t *rme96 = _snd_kcontrol_chip(kcontrol);
-	unsigned long flags;
+	rme96_t *rme96 = snd_kcontrol_chip(kcontrol);
 	
-	spin_lock_irqsave(&rme96->lock, flags);
+	spin_lock_irq(&rme96->lock);
 	ucontrol->value.enumerated.item[0] = snd_rme96_getclockmode(rme96);
-	spin_unlock_irqrestore(&rme96->lock, flags);
+	spin_unlock_irq(&rme96->lock);
 	return 0;
 }
 static int
 snd_rme96_put_clockmode_control(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
 {
-	rme96_t *rme96 = _snd_kcontrol_chip(kcontrol);
-	unsigned long flags;
+	rme96_t *rme96 = snd_kcontrol_chip(kcontrol);
 	unsigned int val;
 	int change;
 	
 	val = ucontrol->value.enumerated.item[0] % 3;
-	spin_lock_irqsave(&rme96->lock, flags);
+	spin_lock_irq(&rme96->lock);
 	change = (int)val != snd_rme96_getclockmode(rme96);
 	snd_rme96_setclockmode(rme96, val);
-	spin_unlock_irqrestore(&rme96->lock, flags);
+	spin_unlock_irq(&rme96->lock);
 	return change;
 }
 
@@ -2161,28 +2038,26 @@
 static int
 snd_rme96_get_attenuation_control(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
 {
-	rme96_t *rme96 = _snd_kcontrol_chip(kcontrol);
-	unsigned long flags;
+	rme96_t *rme96 = snd_kcontrol_chip(kcontrol);
 	
-	spin_lock_irqsave(&rme96->lock, flags);
+	spin_lock_irq(&rme96->lock);
 	ucontrol->value.enumerated.item[0] = snd_rme96_getattenuation(rme96);
-	spin_unlock_irqrestore(&rme96->lock, flags);
+	spin_unlock_irq(&rme96->lock);
 	return 0;
 }
 static int
 snd_rme96_put_attenuation_control(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
 {
-	rme96_t *rme96 = _snd_kcontrol_chip(kcontrol);
-	unsigned long flags;
+	rme96_t *rme96 = snd_kcontrol_chip(kcontrol);
 	unsigned int val;
 	int change;
 	
 	val = ucontrol->value.enumerated.item[0] % 4;
-	spin_lock_irqsave(&rme96->lock, flags);
+	spin_lock_irq(&rme96->lock);
 
 	change = (int)val != snd_rme96_getattenuation(rme96);
 	snd_rme96_setattenuation(rme96, val);
-	spin_unlock_irqrestore(&rme96->lock, flags);
+	spin_unlock_irq(&rme96->lock);
 	return change;
 }
 
@@ -2203,27 +2078,25 @@
 static int
 snd_rme96_get_montracks_control(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
 {
-	rme96_t *rme96 = _snd_kcontrol_chip(kcontrol);
-	unsigned long flags;
+	rme96_t *rme96 = snd_kcontrol_chip(kcontrol);
 	
-	spin_lock_irqsave(&rme96->lock, flags);
+	spin_lock_irq(&rme96->lock);
 	ucontrol->value.enumerated.item[0] = snd_rme96_getmontracks(rme96);
-	spin_unlock_irqrestore(&rme96->lock, flags);
+	spin_unlock_irq(&rme96->lock);
 	return 0;
 }
 static int
 snd_rme96_put_montracks_control(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
 {
-	rme96_t *rme96 = _snd_kcontrol_chip(kcontrol);
-	unsigned long flags;
+	rme96_t *rme96 = snd_kcontrol_chip(kcontrol);
 	unsigned int val;
 	int change;
 	
 	val = ucontrol->value.enumerated.item[0] % 4;
-	spin_lock_irqsave(&rme96->lock, flags);
+	spin_lock_irq(&rme96->lock);
 	change = (int)val != snd_rme96_getmontracks(rme96);
 	snd_rme96_setmontracks(rme96, val);
-	spin_unlock_irqrestore(&rme96->lock, flags);
+	spin_unlock_irq(&rme96->lock);
 	return change;
 }
 
@@ -2258,7 +2131,7 @@
 
 static int snd_rme96_control_spdif_get(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
 {
-	rme96_t *rme96 = _snd_kcontrol_chip(kcontrol);
+	rme96_t *rme96 = snd_kcontrol_chip(kcontrol);
 	
 	snd_rme96_convert_to_aes(&ucontrol->value.iec958, rme96->wcreg_spdif);
 	return 0;
@@ -2266,16 +2139,15 @@
 
 static int snd_rme96_control_spdif_put(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
 {
-	rme96_t *rme96 = _snd_kcontrol_chip(kcontrol);
-	unsigned long flags;
+	rme96_t *rme96 = snd_kcontrol_chip(kcontrol);
 	int change;
 	u32 val;
 	
 	val = snd_rme96_convert_from_aes(&ucontrol->value.iec958);
-	spin_lock_irqsave(&rme96->lock, flags);
+	spin_lock_irq(&rme96->lock);
 	change = val != rme96->wcreg_spdif;
 	rme96->wcreg_spdif = val;
-	spin_unlock_irqrestore(&rme96->lock, flags);
+	spin_unlock_irq(&rme96->lock);
 	return change;
 }
 
@@ -2288,7 +2160,7 @@
 
 static int snd_rme96_control_spdif_stream_get(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
 {
-	rme96_t *rme96 = _snd_kcontrol_chip(kcontrol);
+	rme96_t *rme96 = snd_kcontrol_chip(kcontrol);
 	
 	snd_rme96_convert_to_aes(&ucontrol->value.iec958, rme96->wcreg_spdif_stream);
 	return 0;
@@ -2296,18 +2168,17 @@
 
 static int snd_rme96_control_spdif_stream_put(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
 {
-	rme96_t *rme96 = _snd_kcontrol_chip(kcontrol);
-	unsigned long flags;
+	rme96_t *rme96 = snd_kcontrol_chip(kcontrol);
 	int change;
 	u32 val;
 	
 	val = snd_rme96_convert_from_aes(&ucontrol->value.iec958);
-	spin_lock_irqsave(&rme96->lock, flags);
+	spin_lock_irq(&rme96->lock);
 	change = val != rme96->wcreg_spdif_stream;
 	rme96->wcreg_spdif_stream = val;
 	rme96->wcreg &= ~(RME96_WCR_PRO | RME96_WCR_DOLBY | RME96_WCR_EMP);
 	writel(rme96->wcreg |= val, rme96->iobase + RME96_IO_CONTROL_REGISTER);
-	spin_unlock_irqrestore(&rme96->lock, flags);
+	spin_unlock_irq(&rme96->lock);
 	return change;
 }
 
@@ -2327,7 +2198,7 @@
 static int
 snd_rme96_dac_volume_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)
 {
-	rme96_t *rme96 = _snd_kcontrol_chip(kcontrol);
+	rme96_t *rme96 = snd_kcontrol_chip(kcontrol);
 	
         uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
         uinfo->count = 2;
@@ -2339,13 +2210,12 @@
 static int
 snd_rme96_dac_volume_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *u)
 {
-	rme96_t *rme96 = _snd_kcontrol_chip(kcontrol);
-	unsigned long flags;
+	rme96_t *rme96 = snd_kcontrol_chip(kcontrol);
 
-	spin_lock_irqsave(&rme96->lock, flags);
+	spin_lock_irq(&rme96->lock);
         u->value.integer.value[0] = rme96->vol[0];
         u->value.integer.value[1] = rme96->vol[1];
-	spin_unlock_irqrestore(&rme96->lock, flags);
+	spin_unlock_irq(&rme96->lock);
 
         return 0;
 }
@@ -2353,14 +2223,13 @@
 static int
 snd_rme96_dac_volume_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *u)
 {
-	rme96_t *rme96 = _snd_kcontrol_chip(kcontrol);
-	unsigned long flags;
+	rme96_t *rme96 = snd_kcontrol_chip(kcontrol);
         int change = 0;
 
 	if (!RME96_HAS_ANALOG_OUT(rme96)) {
 		return -EINVAL;
 	}
-	spin_lock_irqsave(&rme96->lock, flags);
+	spin_lock_irq(&rme96->lock);
         if (u->value.integer.value[0] != rme96->vol[0]) {
 		rme96->vol[0] = u->value.integer.value[0];
                 change = 1;
@@ -2372,7 +2241,7 @@
 	if (change) {
 		snd_rme96_apply_dac_volume(rme96);
 	}
-	spin_unlock_irqrestore(&rme96->lock, flags);
+	spin_unlock_irq(&rme96->lock);
 
         return change;
 }
diff -Nru a/sound/pci/rme9652/hdsp.c b/sound/pci/rme9652/hdsp.c
--- a/sound/pci/rme9652/hdsp.c	2004-10-18 14:56:28 -07:00
+++ b/sound/pci/rme9652/hdsp.c	2004-10-18 14:56:28 -07:00
@@ -52,24 +52,18 @@
 
 module_param_array(index, int, boot_devs, 0444);
 MODULE_PARM_DESC(index, "Index value for RME Hammerfall DSP interface.");
-MODULE_PARM_SYNTAX(index, SNDRV_INDEX_DESC);
 module_param_array(id, charp, boot_devs, 0444);
 MODULE_PARM_DESC(id, "ID string for RME Hammerfall DSP interface.");
-MODULE_PARM_SYNTAX(id, SNDRV_ID_DESC);
 module_param_array(enable, bool, boot_devs, 0444);
 MODULE_PARM_DESC(enable, "Enable/disable specific Hammerfall DSP soundcards.");
-MODULE_PARM_SYNTAX(enable, SNDRV_ENABLE_DESC);
 module_param_array(precise_ptr, bool, boot_devs, 0444);
 MODULE_PARM_DESC(precise_ptr, "Enable precise pointer (doesn't work reliably).");
-MODULE_PARM_SYNTAX(precise_ptr, SNDRV_ENABLED "," SNDRV_BOOLEAN_FALSE_DESC);
 module_param_array(line_outs_monitor, bool, boot_devs, 0444);
 MODULE_PARM_DESC(line_outs_monitor, "Send all input and playback streams to line outs by default.");
-MODULE_PARM_SYNTAX(line_outs_monitor, SNDRV_ENABLED "," SNDRV_BOOLEAN_FALSE_DESC);
 MODULE_AUTHOR("Paul Davis <paul@linuxaudiosystems.com>, Marcus Andersson, Thomas Charbonnel <thomas@undata.org>");
 MODULE_DESCRIPTION("RME Hammerfall DSP");
 MODULE_LICENSE("GPL");
-MODULE_CLASSES("{sound}");
-MODULE_DEVICES("{{RME Hammerfall-DSP},"
+MODULE_SUPPORTED_DEVICE("{{RME Hammerfall-DSP},"
 	        "{RME HDSP-9652},"
 		"{RME HDSP-9632}}");
 
@@ -462,12 +456,12 @@
 	unsigned char	      qs_out_channels;	    
 	unsigned char         ds_out_channels;
 	unsigned char         ss_out_channels;
-	void                 *capture_buffer_unaligned;	 /* original buffer addresses */
-	void                 *playback_buffer_unaligned; /* original buffer addresses */
+
+	struct snd_dma_buffer capture_dma_buf;
+	struct snd_dma_buffer playback_dma_buf;
 	unsigned char        *capture_buffer;	    /* suitably aligned address */
 	unsigned char        *playback_buffer;	    /* suitably aligned address */
-	dma_addr_t            capture_buffer_addr;
-	dma_addr_t            playback_buffer_addr;
+
 	pid_t                 capture_pid;
 	pid_t                 playback_pid;
 	int                   running;
@@ -477,7 +471,6 @@
 	int                   dev;
 	int                   irq;
 	unsigned long         port;
-	struct resource      *res_port;
         unsigned long         iobase;
 	snd_card_t           *card;
 	snd_pcm_t            *pcm;
@@ -561,50 +554,24 @@
 	-1, -1
 };
 
-#define HDSP_PREALLOCATE_MEMORY	/* via module snd-hdsp_mem */
-
-#ifdef HDSP_PREALLOCATE_MEMORY
-static void *snd_hammerfall_get_buffer(struct pci_dev *pci, size_t size, dma_addr_t *addrp, int capture)
+static int snd_hammerfall_get_buffer(struct pci_dev *pci, struct snd_dma_buffer *dmab, size_t size)
 {
-	struct snd_dma_device pdev;
-	struct snd_dma_buffer dmbuf;
-
-	memset(&pdev, 0, sizeof(pdev));
-	pdev.type = SNDRV_DMA_TYPE_DEV;
-	pdev.dev = snd_dma_pci_data(pci);
-	pdev.id = capture;
-	dmbuf.bytes = 0;
-	if (! snd_dma_get_reserved(&pdev, &dmbuf)) {
-		if (snd_dma_alloc_pages(&pdev, size, &dmbuf) < 0)
-			return NULL;
-		snd_dma_set_reserved(&pdev, &dmbuf);
+	dmab->dev.type = SNDRV_DMA_TYPE_DEV;
+	dmab->dev.dev = snd_dma_pci_data(pci);
+	if (! snd_dma_get_reserved_buf(dmab, snd_dma_pci_buf_id(pci))) {
+		if (snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, snd_dma_pci_data(pci),
+					size, dmab) < 0)
+			return -ENOMEM;
 	}
-	*addrp = dmbuf.addr;
-	return dmbuf.area;
+	return 0;
 }
 
-static void snd_hammerfall_free_buffer(struct pci_dev *pci, size_t size, void *ptr, dma_addr_t addr, int capture)
+static void snd_hammerfall_free_buffer(struct snd_dma_buffer *dmab, struct pci_dev *pci)
 {
-	struct snd_dma_device pdev;
-
-	memset(&pdev, 0, sizeof(pdev));
-	pdev.type = SNDRV_DMA_TYPE_DEV;
-	pdev.dev = snd_dma_pci_data(pci);
-	pdev.id = capture;
-	snd_dma_free_reserved(&pdev);
+	if (dmab->area)
+		snd_dma_reserve_buf(dmab, snd_dma_pci_buf_id(pci));
 }
 
-#else
-static void *snd_hammerfall_get_buffer(struct pci_dev *pci, size_t size, dma_addr_t *addrp, int capture)
-{
-	return snd_malloc_pci_pages(pci, size, addrp);
-}
-
-static void snd_hammerfall_free_buffer(struct pci_dev *pci, size_t size, void *ptr, dma_addr_t addr, int capture)
-{
-	snd_free_pci_pages(pci, size, ptr, addr);
-}
-#endif
 
 static struct pci_device_id snd_hdsp_ids[] = {
 	{
@@ -621,15 +588,15 @@
 /* prototypes */
 static int __devinit snd_hdsp_create_alsa_devices(snd_card_t *card, hdsp_t *hdsp);
 static int __devinit snd_hdsp_create_pcm(snd_card_t *card, hdsp_t *hdsp);
-static inline int snd_hdsp_enable_io (hdsp_t *hdsp);
-static inline void snd_hdsp_initialize_midi_flush (hdsp_t *hdsp);
-static inline void snd_hdsp_initialize_channels (hdsp_t *hdsp);
-static inline int hdsp_fifo_wait(hdsp_t *hdsp, int count, int timeout);
+static int snd_hdsp_enable_io (hdsp_t *hdsp);
+static void snd_hdsp_initialize_midi_flush (hdsp_t *hdsp);
+static void snd_hdsp_initialize_channels (hdsp_t *hdsp);
+static int hdsp_fifo_wait(hdsp_t *hdsp, int count, int timeout);
 static int hdsp_autosync_ref(hdsp_t *hdsp);
 static int snd_hdsp_set_defaults(hdsp_t *hdsp);
-static inline void snd_hdsp_9652_enable_mixer (hdsp_t *hdsp);
+static void snd_hdsp_9652_enable_mixer (hdsp_t *hdsp);
 
-static inline int hdsp_playback_to_output_key (hdsp_t *hdsp, int in, int out)
+static int hdsp_playback_to_output_key (hdsp_t *hdsp, int in, int out)
 {
 	switch (hdsp->firmware_rev) {
 	case 0xa:
@@ -642,7 +609,7 @@
 	}
 }
 
-static inline int hdsp_input_to_output_key (hdsp_t *hdsp, int in, int out)
+static int hdsp_input_to_output_key (hdsp_t *hdsp, int in, int out)
 {
 	switch (hdsp->firmware_rev) {
 	case 0xa:
@@ -655,17 +622,17 @@
 	}
 }
 
-static inline void hdsp_write(hdsp_t *hdsp, int reg, int val)
+static void hdsp_write(hdsp_t *hdsp, int reg, int val)
 {
 	writel(val, hdsp->iobase + reg);
 }
 
-static inline unsigned int hdsp_read(hdsp_t *hdsp, int reg)
+static unsigned int hdsp_read(hdsp_t *hdsp, int reg)
 {
 	return readl (hdsp->iobase + reg);
 }
 
-static inline int hdsp_check_for_iobox (hdsp_t *hdsp)
+static int hdsp_check_for_iobox (hdsp_t *hdsp)
 {
 
 	if (hdsp->io_type == H9652 || hdsp->io_type == H9632) return 0;
@@ -738,7 +705,7 @@
 	return 0;
 }
 
-static inline int hdsp_get_iobox_version (hdsp_t *hdsp)
+static int hdsp_get_iobox_version (hdsp_t *hdsp)
 {
 	int err;
 	
@@ -781,7 +748,7 @@
 }
 
 
-static inline int hdsp_check_for_firmware (hdsp_t *hdsp)
+static int hdsp_check_for_firmware (hdsp_t *hdsp)
 {
 	if (hdsp->io_type == H9652 || hdsp->io_type == H9632) return 0;
 	if ((hdsp_read (hdsp, HDSP_statusRegister) & HDSP_DllError) != 0) {
@@ -793,7 +760,7 @@
 }
 
 
-static inline int hdsp_fifo_wait(hdsp_t *hdsp, int count, int timeout)
+static int hdsp_fifo_wait(hdsp_t *hdsp, int count, int timeout)
 {    
 	int i;
 
@@ -818,7 +785,7 @@
 	return -1;
 }
 
-static inline int hdsp_read_gain (hdsp_t *hdsp, unsigned int addr)
+static int hdsp_read_gain (hdsp_t *hdsp, unsigned int addr)
 {
 	if (addr >= HDSP_MATRIX_MIXER_SIZE) {
 		return 0;
@@ -826,7 +793,7 @@
 	return hdsp->mixer_matrix[addr];
 }
 
-static inline int hdsp_write_gain(hdsp_t *hdsp, unsigned int addr, unsigned short data)
+static int hdsp_write_gain(hdsp_t *hdsp, unsigned int addr, unsigned short data)
 {
 	unsigned int ad;
 
@@ -835,7 +802,7 @@
 	
 	if (hdsp->io_type == H9652 || hdsp->io_type == H9632) {
 
-		/* from martin björnsen:
+		/* from martin bjĂ¶rnsen:
 		   
 		   "You can only write dwords to the
 		   mixer memory which contain two
@@ -889,7 +856,7 @@
 	return 0;
 }
 
-static inline int snd_hdsp_use_is_exclusive(hdsp_t *hdsp)
+static int snd_hdsp_use_is_exclusive(hdsp_t *hdsp)
 {
 	unsigned long flags;
 	int ret = 1;
@@ -903,7 +870,7 @@
 	return ret;
 }
 
-static inline int hdsp_external_sample_rate (hdsp_t *hdsp)
+static int hdsp_external_sample_rate (hdsp_t *hdsp)
 {
 	unsigned int status2 = hdsp_read(hdsp, HDSP_status2Register);
 	unsigned int rate_bits = status2 & HDSP_systemFrequencyMask;
@@ -920,7 +887,7 @@
 	}
 }
 
-static inline int hdsp_spdif_sample_rate(hdsp_t *hdsp)
+static int hdsp_spdif_sample_rate(hdsp_t *hdsp)
 {
 	unsigned int status = hdsp_read(hdsp, HDSP_statusRegister);
 	unsigned int rate_bits = (status & HDSP_spdifFrequencyMask);
@@ -952,7 +919,7 @@
 	return 0;
 }
 
-static inline void hdsp_compute_period_size(hdsp_t *hdsp)
+static void hdsp_compute_period_size(hdsp_t *hdsp)
 {
 	hdsp->period_bytes = 1 << ((hdsp_decode_latency(hdsp->control_register) + 8));
 }
@@ -974,24 +941,24 @@
 	return position;
 }
 
-static inline void hdsp_reset_hw_pointer(hdsp_t *hdsp)
+static void hdsp_reset_hw_pointer(hdsp_t *hdsp)
 {
 	hdsp_write (hdsp, HDSP_resetPointer, 0);
 }
 
-static inline void hdsp_start_audio(hdsp_t *s)
+static void hdsp_start_audio(hdsp_t *s)
 {
 	s->control_register |= (HDSP_AudioInterruptEnable | HDSP_Start);
 	hdsp_write(s, HDSP_controlRegister, s->control_register);
 }
 
-static inline void hdsp_stop_audio(hdsp_t *s)
+static void hdsp_stop_audio(hdsp_t *s)
 {
 	s->control_register &= ~(HDSP_Start | HDSP_AudioInterruptEnable);
 	hdsp_write(s, HDSP_controlRegister, s->control_register);
 }
 
-static inline void hdsp_silence_playback(hdsp_t *hdsp)
+static void hdsp_silence_playback(hdsp_t *hdsp)
 {
 	memset(hdsp->playback_buffer, 0, HDSP_DMA_AREA_BYTES);
 }
@@ -1236,7 +1203,7 @@
    MIDI
   ----------------------------------------------------------------------------*/
 
-static inline unsigned char snd_hdsp_midi_read_byte (hdsp_t *hdsp, int id)
+static unsigned char snd_hdsp_midi_read_byte (hdsp_t *hdsp, int id)
 {
 	/* the hardware already does the relevant bit-mask with 0xff */
 	if (id) {
@@ -1246,7 +1213,7 @@
 	}
 }
 
-static inline void snd_hdsp_midi_write_byte (hdsp_t *hdsp, int id, int val)
+static void snd_hdsp_midi_write_byte (hdsp_t *hdsp, int id, int val)
 {
 	/* the hardware already does the relevant bit-mask with 0xff */
 	if (id) {
@@ -1256,7 +1223,7 @@
 	}
 }
 
-static inline int snd_hdsp_midi_input_available (hdsp_t *hdsp, int id)
+static int snd_hdsp_midi_input_available (hdsp_t *hdsp, int id)
 {
 	if (id) {
 		return (hdsp_read(hdsp, HDSP_midiStatusIn1) & 0xff);
@@ -1265,7 +1232,7 @@
 	}
 }
 
-static inline int snd_hdsp_midi_output_possible (hdsp_t *hdsp, int id)
+static int snd_hdsp_midi_output_possible (hdsp_t *hdsp, int id)
 {
 	int fifo_bytes_used;
 
@@ -1282,7 +1249,7 @@
 	}
 }
 
-static inline void snd_hdsp_flush_midi_input (hdsp_t *hdsp, int id)
+static void snd_hdsp_flush_midi_input (hdsp_t *hdsp, int id)
 {
 	while (snd_hdsp_midi_input_available (hdsp, id)) {
 		snd_hdsp_midi_read_byte (hdsp, id);
@@ -1429,13 +1396,12 @@
 static int snd_hdsp_midi_input_open(snd_rawmidi_substream_t * substream)
 {
 	hdsp_midi_t *hmidi;
-	unsigned long flags;
 
 	hmidi = (hdsp_midi_t *) substream->rmidi->private_data;
-	spin_lock_irqsave (&hmidi->lock, flags);
+	spin_lock_irq (&hmidi->lock);
 	snd_hdsp_flush_midi_input (hmidi->hdsp, hmidi->id);
 	hmidi->input = substream;
-	spin_unlock_irqrestore (&hmidi->lock, flags);
+	spin_unlock_irq (&hmidi->lock);
 
 	return 0;
 }
@@ -1443,12 +1409,11 @@
 static int snd_hdsp_midi_output_open(snd_rawmidi_substream_t * substream)
 {
 	hdsp_midi_t *hmidi;
-	unsigned long flags;
 
 	hmidi = (hdsp_midi_t *) substream->rmidi->private_data;
-	spin_lock_irqsave (&hmidi->lock, flags);
+	spin_lock_irq (&hmidi->lock);
 	hmidi->output = substream;
-	spin_unlock_irqrestore (&hmidi->lock, flags);
+	spin_unlock_irq (&hmidi->lock);
 
 	return 0;
 }
@@ -1456,14 +1421,13 @@
 static int snd_hdsp_midi_input_close(snd_rawmidi_substream_t * substream)
 {
 	hdsp_midi_t *hmidi;
-	unsigned long flags;
 
 	snd_hdsp_midi_input_trigger (substream, 0);
 
 	hmidi = (hdsp_midi_t *) substream->rmidi->private_data;
-	spin_lock_irqsave (&hmidi->lock, flags);
+	spin_lock_irq (&hmidi->lock);
 	hmidi->input = NULL;
-	spin_unlock_irqrestore (&hmidi->lock, flags);
+	spin_unlock_irq (&hmidi->lock);
 
 	return 0;
 }
@@ -1471,14 +1435,13 @@
 static int snd_hdsp_midi_output_close(snd_rawmidi_substream_t * substream)
 {
 	hdsp_midi_t *hmidi;
-	unsigned long flags;
 
 	snd_hdsp_midi_output_trigger (substream, 0);
 
 	hmidi = (hdsp_midi_t *) substream->rmidi->private_data;
-	spin_lock_irqsave (&hmidi->lock, flags);
+	spin_lock_irq (&hmidi->lock);
 	hmidi->output = NULL;
-	spin_unlock_irqrestore (&hmidi->lock, flags);
+	spin_unlock_irq (&hmidi->lock);
 
 	return 0;
 }
@@ -1563,7 +1526,7 @@
 
 static int snd_hdsp_control_spdif_get(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
 {
-	hdsp_t *hdsp = _snd_kcontrol_chip(kcontrol);
+	hdsp_t *hdsp = snd_kcontrol_chip(kcontrol);
 	
 	snd_hdsp_convert_to_aes(&ucontrol->value.iec958, hdsp->creg_spdif);
 	return 0;
@@ -1571,16 +1534,15 @@
 
 static int snd_hdsp_control_spdif_put(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
 {
-	hdsp_t *hdsp = _snd_kcontrol_chip(kcontrol);
-	unsigned long flags;
+	hdsp_t *hdsp = snd_kcontrol_chip(kcontrol);
 	int change;
 	u32 val;
 	
 	val = snd_hdsp_convert_from_aes(&ucontrol->value.iec958);
-	spin_lock_irqsave(&hdsp->lock, flags);
+	spin_lock_irq(&hdsp->lock);
 	change = val != hdsp->creg_spdif;
 	hdsp->creg_spdif = val;
-	spin_unlock_irqrestore(&hdsp->lock, flags);
+	spin_unlock_irq(&hdsp->lock);
 	return change;
 }
 
@@ -1593,7 +1555,7 @@
 
 static int snd_hdsp_control_spdif_stream_get(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
 {
-	hdsp_t *hdsp = _snd_kcontrol_chip(kcontrol);
+	hdsp_t *hdsp = snd_kcontrol_chip(kcontrol);
 	
 	snd_hdsp_convert_to_aes(&ucontrol->value.iec958, hdsp->creg_spdif_stream);
 	return 0;
@@ -1601,18 +1563,17 @@
 
 static int snd_hdsp_control_spdif_stream_put(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
 {
-	hdsp_t *hdsp = _snd_kcontrol_chip(kcontrol);
-	unsigned long flags;
+	hdsp_t *hdsp = snd_kcontrol_chip(kcontrol);
 	int change;
 	u32 val;
 	
 	val = snd_hdsp_convert_from_aes(&ucontrol->value.iec958);
-	spin_lock_irqsave(&hdsp->lock, flags);
+	spin_lock_irq(&hdsp->lock);
 	change = val != hdsp->creg_spdif_stream;
 	hdsp->creg_spdif_stream = val;
 	hdsp->control_register &= ~(HDSP_SPDIFProfessional | HDSP_SPDIFNonAudio | HDSP_SPDIFEmphasis);
 	hdsp_write(hdsp, HDSP_controlRegister, hdsp->control_register |= val);
-	spin_unlock_irqrestore(&hdsp->lock, flags);
+	spin_unlock_irq(&hdsp->lock);
 	return change;
 }
 
@@ -1653,7 +1614,7 @@
 static int snd_hdsp_info_spdif_in(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)
 {
 	static char *texts[4] = {"Optical", "Coaxial", "Internal", "AES"};
-	hdsp_t *hdsp = _snd_kcontrol_chip(kcontrol);
+	hdsp_t *hdsp = snd_kcontrol_chip(kcontrol);
 
 	uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
 	uinfo->count = 1;
@@ -1666,7 +1627,7 @@
 
 static int snd_hdsp_get_spdif_in(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
 {
-	hdsp_t *hdsp = _snd_kcontrol_chip(kcontrol);
+	hdsp_t *hdsp = snd_kcontrol_chip(kcontrol);
 	
 	ucontrol->value.enumerated.item[0] = hdsp_spdif_in(hdsp);
 	return 0;
@@ -1674,19 +1635,18 @@
 
 static int snd_hdsp_put_spdif_in(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
 {
-	hdsp_t *hdsp = _snd_kcontrol_chip(kcontrol);
-	unsigned long flags;
+	hdsp_t *hdsp = snd_kcontrol_chip(kcontrol);
 	int change;
 	unsigned int val;
 	
 	if (!snd_hdsp_use_is_exclusive(hdsp))
 		return -EBUSY;
 	val = ucontrol->value.enumerated.item[0] % ((hdsp->io_type == H9632) ? 4 : 3);
-	spin_lock_irqsave(&hdsp->lock, flags);
+	spin_lock_irq(&hdsp->lock);
 	change = val != hdsp_spdif_in(hdsp);
 	if (change)
 		hdsp_set_spdif_input(hdsp, val);
-	spin_unlock_irqrestore(&hdsp->lock, flags);
+	spin_unlock_irq(&hdsp->lock);
 	return change;
 }
 
@@ -1722,7 +1682,7 @@
 
 static int snd_hdsp_get_spdif_out(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
 {
-	hdsp_t *hdsp = _snd_kcontrol_chip(kcontrol);
+	hdsp_t *hdsp = snd_kcontrol_chip(kcontrol);
 	
 	ucontrol->value.integer.value[0] = hdsp_spdif_out(hdsp);
 	return 0;
@@ -1730,18 +1690,17 @@
 
 static int snd_hdsp_put_spdif_out(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
 {
-	hdsp_t *hdsp = _snd_kcontrol_chip(kcontrol);
-	unsigned long flags;
+	hdsp_t *hdsp = snd_kcontrol_chip(kcontrol);
 	int change;
 	unsigned int val;
 	
 	if (!snd_hdsp_use_is_exclusive(hdsp))
 		return -EBUSY;
 	val = ucontrol->value.integer.value[0] & 1;
-	spin_lock_irqsave(&hdsp->lock, flags);
+	spin_lock_irq(&hdsp->lock);
 	change = (int)val != hdsp_spdif_out(hdsp);
 	hdsp_set_spdif_output(hdsp, val);
-	spin_unlock_irqrestore(&hdsp->lock, flags);
+	spin_unlock_irq(&hdsp->lock);
 	return change;
 }
 
@@ -1768,7 +1727,7 @@
 
 static int snd_hdsp_get_spdif_professional(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
 {
-	hdsp_t *hdsp = _snd_kcontrol_chip(kcontrol);
+	hdsp_t *hdsp = snd_kcontrol_chip(kcontrol);
 	
 	ucontrol->value.integer.value[0] = hdsp_spdif_professional(hdsp);
 	return 0;
@@ -1776,18 +1735,17 @@
 
 static int snd_hdsp_put_spdif_professional(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
 {
-	hdsp_t *hdsp = _snd_kcontrol_chip(kcontrol);
-	unsigned long flags;
+	hdsp_t *hdsp = snd_kcontrol_chip(kcontrol);
 	int change;
 	unsigned int val;
 	
 	if (!snd_hdsp_use_is_exclusive(hdsp))
 		return -EBUSY;
 	val = ucontrol->value.integer.value[0] & 1;
-	spin_lock_irqsave(&hdsp->lock, flags);
+	spin_lock_irq(&hdsp->lock);
 	change = (int)val != hdsp_spdif_professional(hdsp);
 	hdsp_set_spdif_professional(hdsp, val);
-	spin_unlock_irqrestore(&hdsp->lock, flags);
+	spin_unlock_irq(&hdsp->lock);
 	return change;
 }
 
@@ -1814,7 +1772,7 @@
 
 static int snd_hdsp_get_spdif_emphasis(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
 {
-	hdsp_t *hdsp = _snd_kcontrol_chip(kcontrol);
+	hdsp_t *hdsp = snd_kcontrol_chip(kcontrol);
 	
 	ucontrol->value.integer.value[0] = hdsp_spdif_emphasis(hdsp);
 	return 0;
@@ -1822,18 +1780,17 @@
 
 static int snd_hdsp_put_spdif_emphasis(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
 {
-	hdsp_t *hdsp = _snd_kcontrol_chip(kcontrol);
-	unsigned long flags;
+	hdsp_t *hdsp = snd_kcontrol_chip(kcontrol);
 	int change;
 	unsigned int val;
 	
 	if (!snd_hdsp_use_is_exclusive(hdsp))
 		return -EBUSY;
 	val = ucontrol->value.integer.value[0] & 1;
-	spin_lock_irqsave(&hdsp->lock, flags);
+	spin_lock_irq(&hdsp->lock);
 	change = (int)val != hdsp_spdif_emphasis(hdsp);
 	hdsp_set_spdif_emphasis(hdsp, val);
-	spin_unlock_irqrestore(&hdsp->lock, flags);
+	spin_unlock_irq(&hdsp->lock);
 	return change;
 }
 
@@ -1860,7 +1817,7 @@
 
 static int snd_hdsp_get_spdif_nonaudio(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
 {
-	hdsp_t *hdsp = _snd_kcontrol_chip(kcontrol);
+	hdsp_t *hdsp = snd_kcontrol_chip(kcontrol);
 	
 	ucontrol->value.integer.value[0] = hdsp_spdif_nonaudio(hdsp);
 	return 0;
@@ -1868,18 +1825,17 @@
 
 static int snd_hdsp_put_spdif_nonaudio(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
 {
-	hdsp_t *hdsp = _snd_kcontrol_chip(kcontrol);
-	unsigned long flags;
+	hdsp_t *hdsp = snd_kcontrol_chip(kcontrol);
 	int change;
 	unsigned int val;
 	
 	if (!snd_hdsp_use_is_exclusive(hdsp))
 		return -EBUSY;
 	val = ucontrol->value.integer.value[0] & 1;
-	spin_lock_irqsave(&hdsp->lock, flags);
+	spin_lock_irq(&hdsp->lock);
 	change = (int)val != hdsp_spdif_nonaudio(hdsp);
 	hdsp_set_spdif_nonaudio(hdsp, val);
-	spin_unlock_irqrestore(&hdsp->lock, flags);
+	spin_unlock_irq(&hdsp->lock);
 	return change;
 }
 
@@ -1895,7 +1851,7 @@
 static int snd_hdsp_info_spdif_sample_rate(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)
 {
 	static char *texts[] = {"32000", "44100", "48000", "64000", "88200", "96000", "None", "128000", "176400", "192000"};
-	hdsp_t *hdsp = _snd_kcontrol_chip(kcontrol);
+	hdsp_t *hdsp = snd_kcontrol_chip(kcontrol);
 
 	uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
 	uinfo->count = 1;
@@ -1908,7 +1864,7 @@
 
 static int snd_hdsp_get_spdif_sample_rate(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
 {
-	hdsp_t *hdsp = _snd_kcontrol_chip(kcontrol);
+	hdsp_t *hdsp = snd_kcontrol_chip(kcontrol);
 	
 	switch (hdsp_spdif_sample_rate(hdsp)) {
 	case 32000:
@@ -1962,7 +1918,7 @@
 
 static int snd_hdsp_get_system_sample_rate(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
 {
-	hdsp_t *hdsp = _snd_kcontrol_chip(kcontrol);
+	hdsp_t *hdsp = snd_kcontrol_chip(kcontrol);
 	
 	ucontrol->value.enumerated.item[0] = hdsp->system_sample_rate;
 	return 0;
@@ -1979,7 +1935,7 @@
 
 static int snd_hdsp_info_autosync_sample_rate(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)
 {
-	hdsp_t *hdsp = _snd_kcontrol_chip(kcontrol);
+	hdsp_t *hdsp = snd_kcontrol_chip(kcontrol);
 	static char *texts[] = {"32000", "44100", "48000", "64000", "88200", "96000", "None", "128000", "176400", "192000"};	
 	uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
 	uinfo->count = 1;
@@ -1992,7 +1948,7 @@
 
 static int snd_hdsp_get_autosync_sample_rate(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
 {
-	hdsp_t *hdsp = _snd_kcontrol_chip(kcontrol);
+	hdsp_t *hdsp = snd_kcontrol_chip(kcontrol);
 	
 	switch (hdsp_external_sample_rate(hdsp)) {
 	case 32000:
@@ -2062,7 +2018,7 @@
 
 static int snd_hdsp_get_system_clock_mode(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
 {
-	hdsp_t *hdsp = _snd_kcontrol_chip(kcontrol);
+	hdsp_t *hdsp = snd_kcontrol_chip(kcontrol);
 	
 	ucontrol->value.enumerated.item[0] = hdsp_system_clock_mode(hdsp);
 	return 0;
@@ -2159,7 +2115,7 @@
 static int snd_hdsp_info_clock_source(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)
 {
 	static char *texts[] = {"AutoSync", "Internal 32.0 kHz", "Internal 44.1 kHz", "Internal 48.0 kHz", "Internal 64.0 kHz", "Internal 88.2 kHz", "Internal 96.0 kHz", "Internal 128 kHz", "Internal 176.4 kHz", "Internal 192.0 KHz" };
-	hdsp_t *hdsp = _snd_kcontrol_chip(kcontrol);
+	hdsp_t *hdsp = snd_kcontrol_chip(kcontrol);
 	
 	uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
 	uinfo->count = 1;
@@ -2175,7 +2131,7 @@
 
 static int snd_hdsp_get_clock_source(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
 {
-	hdsp_t *hdsp = _snd_kcontrol_chip(kcontrol);
+	hdsp_t *hdsp = snd_kcontrol_chip(kcontrol);
 	
 	ucontrol->value.enumerated.item[0] = hdsp_clock_source(hdsp);
 	return 0;
@@ -2183,8 +2139,7 @@
 
 static int snd_hdsp_put_clock_source(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
 {
-	hdsp_t *hdsp = _snd_kcontrol_chip(kcontrol);
-	unsigned long flags;
+	hdsp_t *hdsp = snd_kcontrol_chip(kcontrol);
 	int change;
 	int val;
 	
@@ -2197,13 +2152,13 @@
 	} else {
 	    if (val > 6) val = 6;
 	}
-	spin_lock_irqsave(&hdsp->lock, flags);
+	spin_lock_irq(&hdsp->lock);
 	if (val != hdsp_clock_source(hdsp)) {
 		change = (hdsp_set_clock_source(hdsp, val) == 0) ? 1 : 0;
 	} else {
 		change = 0;
 	}
-	spin_unlock_irqrestore(&hdsp->lock, flags);
+	spin_unlock_irq(&hdsp->lock);
 	return change;
 }
 
@@ -2266,7 +2221,7 @@
 
 static int snd_hdsp_get_da_gain(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
 {
-	hdsp_t *hdsp = _snd_kcontrol_chip(kcontrol);
+	hdsp_t *hdsp = snd_kcontrol_chip(kcontrol);
 	
 	ucontrol->value.enumerated.item[0] = hdsp_da_gain(hdsp);
 	return 0;
@@ -2274,8 +2229,7 @@
 
 static int snd_hdsp_put_da_gain(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
 {
-	hdsp_t *hdsp = _snd_kcontrol_chip(kcontrol);
-	unsigned long flags;
+	hdsp_t *hdsp = snd_kcontrol_chip(kcontrol);
 	int change;
 	int val;
 	
@@ -2284,13 +2238,13 @@
 	val = ucontrol->value.enumerated.item[0];
 	if (val < 0) val = 0;
 	if (val > 2) val = 2;
-	spin_lock_irqsave(&hdsp->lock, flags);
+	spin_lock_irq(&hdsp->lock);
 	if (val != hdsp_da_gain(hdsp)) {
 		change = (hdsp_set_da_gain(hdsp, val) == 0) ? 1 : 0;
 	} else {
 		change = 0;
 	}
-	spin_unlock_irqrestore(&hdsp->lock, flags);
+	spin_unlock_irq(&hdsp->lock);
 	return change;
 }
 
@@ -2353,7 +2307,7 @@
 
 static int snd_hdsp_get_ad_gain(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
 {
-	hdsp_t *hdsp = _snd_kcontrol_chip(kcontrol);
+	hdsp_t *hdsp = snd_kcontrol_chip(kcontrol);
 	
 	ucontrol->value.enumerated.item[0] = hdsp_ad_gain(hdsp);
 	return 0;
@@ -2361,8 +2315,7 @@
 
 static int snd_hdsp_put_ad_gain(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
 {
-	hdsp_t *hdsp = _snd_kcontrol_chip(kcontrol);
-	unsigned long flags;
+	hdsp_t *hdsp = snd_kcontrol_chip(kcontrol);
 	int change;
 	int val;
 	
@@ -2371,13 +2324,13 @@
 	val = ucontrol->value.enumerated.item[0];
 	if (val < 0) val = 0;
 	if (val > 2) val = 2;
-	spin_lock_irqsave(&hdsp->lock, flags);
+	spin_lock_irq(&hdsp->lock);
 	if (val != hdsp_ad_gain(hdsp)) {
 		change = (hdsp_set_ad_gain(hdsp, val) == 0) ? 1 : 0;
 	} else {
 		change = 0;
 	}
-	spin_unlock_irqrestore(&hdsp->lock, flags);
+	spin_unlock_irq(&hdsp->lock);
 	return change;
 }
 
@@ -2440,7 +2393,7 @@
 
 static int snd_hdsp_get_phone_gain(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
 {
-	hdsp_t *hdsp = _snd_kcontrol_chip(kcontrol);
+	hdsp_t *hdsp = snd_kcontrol_chip(kcontrol);
 	
 	ucontrol->value.enumerated.item[0] = hdsp_phone_gain(hdsp);
 	return 0;
@@ -2448,8 +2401,7 @@
 
 static int snd_hdsp_put_phone_gain(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
 {
-	hdsp_t *hdsp = _snd_kcontrol_chip(kcontrol);
-	unsigned long flags;
+	hdsp_t *hdsp = snd_kcontrol_chip(kcontrol);
 	int change;
 	int val;
 	
@@ -2458,13 +2410,13 @@
 	val = ucontrol->value.enumerated.item[0];
 	if (val < 0) val = 0;
 	if (val > 2) val = 2;
-	spin_lock_irqsave(&hdsp->lock, flags);
+	spin_lock_irq(&hdsp->lock);
 	if (val != hdsp_phone_gain(hdsp)) {
 		change = (hdsp_set_phone_gain(hdsp, val) == 0) ? 1 : 0;
 	} else {
 		change = 0;
 	}
-	spin_unlock_irqrestore(&hdsp->lock, flags);
+	spin_unlock_irq(&hdsp->lock);
 	return change;
 }
 
@@ -2507,7 +2459,7 @@
 
 static int snd_hdsp_get_xlr_breakout_cable(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
 {
-	hdsp_t *hdsp = _snd_kcontrol_chip(kcontrol);
+	hdsp_t *hdsp = snd_kcontrol_chip(kcontrol);
 	
 	ucontrol->value.enumerated.item[0] = hdsp_xlr_breakout_cable(hdsp);
 	return 0;
@@ -2515,18 +2467,17 @@
 
 static int snd_hdsp_put_xlr_breakout_cable(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
 {
-	hdsp_t *hdsp = _snd_kcontrol_chip(kcontrol);
-	unsigned long flags;
+	hdsp_t *hdsp = snd_kcontrol_chip(kcontrol);
 	int change;
 	int val;
 	
 	if (!snd_hdsp_use_is_exclusive(hdsp))
 		return -EBUSY;
 	val = ucontrol->value.integer.value[0] & 1;
-	spin_lock_irqsave(&hdsp->lock, flags);
+	spin_lock_irq(&hdsp->lock);
 	change = (int)val != hdsp_xlr_breakout_cable(hdsp);
 	hdsp_set_xlr_breakout_cable(hdsp, val);
-	spin_unlock_irqrestore(&hdsp->lock, flags);
+	spin_unlock_irq(&hdsp->lock);
 	return change;
 }
 
@@ -2573,7 +2524,7 @@
 
 static int snd_hdsp_get_aeb(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
 {
-	hdsp_t *hdsp = _snd_kcontrol_chip(kcontrol);
+	hdsp_t *hdsp = snd_kcontrol_chip(kcontrol);
 	
 	ucontrol->value.enumerated.item[0] = hdsp_aeb(hdsp);
 	return 0;
@@ -2581,18 +2532,17 @@
 
 static int snd_hdsp_put_aeb(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
 {
-	hdsp_t *hdsp = _snd_kcontrol_chip(kcontrol);
-	unsigned long flags;
+	hdsp_t *hdsp = snd_kcontrol_chip(kcontrol);
 	int change;
 	int val;
 	
 	if (!snd_hdsp_use_is_exclusive(hdsp))
 		return -EBUSY;
 	val = ucontrol->value.integer.value[0] & 1;
-	spin_lock_irqsave(&hdsp->lock, flags);
+	spin_lock_irq(&hdsp->lock);
 	change = (int)val != hdsp_aeb(hdsp);
 	hdsp_set_aeb(hdsp, val);
-	spin_unlock_irqrestore(&hdsp->lock, flags);
+	spin_unlock_irq(&hdsp->lock);
 	return change;
 }
 
@@ -2662,7 +2612,7 @@
 static int snd_hdsp_info_pref_sync_ref(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)
 {
 	static char *texts[] = {"Word", "IEC958", "ADAT1", "ADAT Sync", "ADAT2", "ADAT3" };
-	hdsp_t *hdsp = _snd_kcontrol_chip(kcontrol);
+	hdsp_t *hdsp = snd_kcontrol_chip(kcontrol);
 	
 	uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
 	uinfo->count = 1;
@@ -2691,7 +2641,7 @@
 
 static int snd_hdsp_get_pref_sync_ref(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
 {
-	hdsp_t *hdsp = _snd_kcontrol_chip(kcontrol);
+	hdsp_t *hdsp = snd_kcontrol_chip(kcontrol);
 	
 	ucontrol->value.enumerated.item[0] = hdsp_pref_sync_ref(hdsp);
 	return 0;
@@ -2699,8 +2649,7 @@
 
 static int snd_hdsp_put_pref_sync_ref(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
 {
-	hdsp_t *hdsp = _snd_kcontrol_chip(kcontrol);
-	unsigned long flags;
+	hdsp_t *hdsp = snd_kcontrol_chip(kcontrol);
 	int change, max;
 	unsigned int val;
 	
@@ -2723,10 +2672,10 @@
 	}
 
 	val = ucontrol->value.enumerated.item[0] % max;
-	spin_lock_irqsave(&hdsp->lock, flags);
+	spin_lock_irq(&hdsp->lock);
 	change = (int)val != hdsp_pref_sync_ref(hdsp);
 	hdsp_set_pref_sync_ref(hdsp, val);
-	spin_unlock_irqrestore(&hdsp->lock, flags);
+	spin_unlock_irq(&hdsp->lock);
 	return change;
 }
 
@@ -2780,7 +2729,7 @@
 
 static int snd_hdsp_get_autosync_ref(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
 {
-	hdsp_t *hdsp = _snd_kcontrol_chip(kcontrol);
+	hdsp_t *hdsp = snd_kcontrol_chip(kcontrol);
 	
 	ucontrol->value.enumerated.item[0] = hdsp_pref_sync_ref(hdsp);
 	return 0;
@@ -2806,19 +2755,17 @@
 
 static int snd_hdsp_get_passthru(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
 {
-	hdsp_t *hdsp = _snd_kcontrol_chip(kcontrol);
-	unsigned long flags;
+	hdsp_t *hdsp = snd_kcontrol_chip(kcontrol);
 
-	spin_lock_irqsave(&hdsp->lock, flags);
+	spin_lock_irq(&hdsp->lock);
 	ucontrol->value.integer.value[0] = hdsp->passthru;
-	spin_unlock_irqrestore(&hdsp->lock, flags);
+	spin_unlock_irq(&hdsp->lock);
 	return 0;
 }
 
 static int snd_hdsp_put_passthru(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
 {
-	hdsp_t *hdsp = _snd_kcontrol_chip(kcontrol);
-	unsigned long flags;
+	hdsp_t *hdsp = snd_kcontrol_chip(kcontrol);
 	int change;
 	unsigned int val;
 	int err = 0;
@@ -2827,11 +2774,11 @@
 		return -EBUSY;
 
 	val = ucontrol->value.integer.value[0] & 1;
-	spin_lock_irqsave(&hdsp->lock, flags);
+	spin_lock_irq(&hdsp->lock);
 	change = (ucontrol->value.integer.value[0] != hdsp->passthru);
 	if (change)
 		err = hdsp_set_passthru(hdsp, val);
-	spin_unlock_irqrestore(&hdsp->lock, flags);
+	spin_unlock_irq(&hdsp->lock);
 	return err ? err : change;
 }
 
@@ -2871,29 +2818,27 @@
 
 static int snd_hdsp_get_line_out(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
 {
-	hdsp_t *hdsp = _snd_kcontrol_chip(kcontrol);
-	unsigned long flags;
+	hdsp_t *hdsp = snd_kcontrol_chip(kcontrol);
 	
-	spin_lock_irqsave(&hdsp->lock, flags);
+	spin_lock_irq(&hdsp->lock);
 	ucontrol->value.integer.value[0] = hdsp_line_out(hdsp);
-	spin_unlock_irqrestore(&hdsp->lock, flags);
+	spin_unlock_irq(&hdsp->lock);
 	return 0;
 }
 
 static int snd_hdsp_put_line_out(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
 {
-	hdsp_t *hdsp = _snd_kcontrol_chip(kcontrol);
-	unsigned long flags;
+	hdsp_t *hdsp = snd_kcontrol_chip(kcontrol);
 	int change;
 	unsigned int val;
 	
 	if (!snd_hdsp_use_is_exclusive(hdsp))
 		return -EBUSY;
 	val = ucontrol->value.integer.value[0] & 1;
-	spin_lock_irqsave(&hdsp->lock, flags);
+	spin_lock_irq(&hdsp->lock);
 	change = (int)val != hdsp_line_out(hdsp);
 	hdsp_set_line_output(hdsp, val);
-	spin_unlock_irqrestore(&hdsp->lock, flags);
+	spin_unlock_irq(&hdsp->lock);
 	return change;
 }
 
@@ -2920,8 +2865,7 @@
 
 static int snd_hdsp_get_mixer(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
 {
-	hdsp_t *hdsp = _snd_kcontrol_chip(kcontrol);
-	unsigned long flags;
+	hdsp_t *hdsp = snd_kcontrol_chip(kcontrol);
 	int source;
 	int destination;
 	int addr;
@@ -2935,16 +2879,15 @@
 		addr = hdsp_input_to_output_key(hdsp,source, destination);
 	}
 	
-	spin_lock_irqsave(&hdsp->lock, flags);
+	spin_lock_irq(&hdsp->lock);
 	ucontrol->value.integer.value[2] = hdsp_read_gain (hdsp, addr);
-	spin_unlock_irqrestore(&hdsp->lock, flags);
+	spin_unlock_irq(&hdsp->lock);
 	return 0;
 }
 
 static int snd_hdsp_put_mixer(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
 {
-	hdsp_t *hdsp = _snd_kcontrol_chip(kcontrol);
-	unsigned long flags;
+	hdsp_t *hdsp = snd_kcontrol_chip(kcontrol);
 	int change;
 	int source;
 	int destination;
@@ -2965,11 +2908,11 @@
 
 	gain = ucontrol->value.integer.value[2];
 
-	spin_lock_irqsave(&hdsp->lock, flags);
+	spin_lock_irq(&hdsp->lock);
 	change = gain != hdsp_read_gain(hdsp, addr);
 	if (change)
 		hdsp_write_gain(hdsp, addr, gain);
-	spin_unlock_irqrestore(&hdsp->lock, flags);
+	spin_unlock_irq(&hdsp->lock);
 	return change;
 }
 
@@ -3011,7 +2954,7 @@
 
 static int snd_hdsp_get_wc_sync_check(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
 {
-	hdsp_t *hdsp = _snd_kcontrol_chip(kcontrol);
+	hdsp_t *hdsp = snd_kcontrol_chip(kcontrol);
 
 	ucontrol->value.enumerated.item[0] = hdsp_wc_sync_check(hdsp);
 	return 0;
@@ -3043,7 +2986,7 @@
 
 static int snd_hdsp_get_spdif_sync_check(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
 {
-	hdsp_t *hdsp = _snd_kcontrol_chip(kcontrol);
+	hdsp_t *hdsp = snd_kcontrol_chip(kcontrol);
 
 	ucontrol->value.enumerated.item[0] = hdsp_spdif_sync_check(hdsp);
 	return 0;
@@ -3074,7 +3017,7 @@
 
 static int snd_hdsp_get_adatsync_sync_check(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
 {
-	hdsp_t *hdsp = _snd_kcontrol_chip(kcontrol);
+	hdsp_t *hdsp = snd_kcontrol_chip(kcontrol);
 
 	ucontrol->value.enumerated.item[0] = hdsp_adatsync_sync_check(hdsp);
 	return 0;
@@ -3105,7 +3048,7 @@
 static int snd_hdsp_get_adat_sync_check(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
 {
 	int offset;
-	hdsp_t *hdsp = _snd_kcontrol_chip(kcontrol);
+	hdsp_t *hdsp = snd_kcontrol_chip(kcontrol);
 
 	offset = ucontrol->id.index - 1;
 	snd_assert(offset >= 0);
@@ -3194,10 +3137,6 @@
 HDSP_LINE_OUT("Line Out", 0),
 };
 
-#define HDSP_CONTROLS (sizeof(snd_hdsp_controls)/sizeof(snd_kcontrol_new_t))
-
-#define HDSP_9632_CONTROLS (sizeof(snd_hdsp_9632_controls)/sizeof(snd_kcontrol_new_t))
-
 static snd_kcontrol_new_t snd_hdsp_96xx_aeb = HDSP_AEB("Analog Extension Board", 0);
 static snd_kcontrol_new_t snd_hdsp_adat_sync_check = HDSP_ADAT_SYNC_CHECK;
 
@@ -3207,7 +3146,7 @@
 	int err;
 	snd_kcontrol_t *kctl;
 
-	for (idx = 0; idx < HDSP_CONTROLS; idx++) {
+	for (idx = 0; idx < ARRAY_SIZE(snd_hdsp_controls); idx++) {
 		if ((err = snd_ctl_add(card, kctl = snd_ctl_new1(&snd_hdsp_controls[idx], hdsp))) < 0) {
 			return err;
 		}
@@ -3232,7 +3171,7 @@
 	
 	/* DA, AD and Phone gain and XLR breakout cable controls for H9632 cards */
 	if (hdsp->io_type == H9632) {
-		for (idx = 0; idx < HDSP_9632_CONTROLS; idx++) {
+		for (idx = 0; idx < ARRAY_SIZE(snd_hdsp_9632_controls); idx++) {
 			if ((err = snd_ctl_add(card, kctl = snd_ctl_new1(&snd_hdsp_9632_controls[idx], hdsp))) < 0) {
 				return err;
 			}
@@ -3583,59 +3522,34 @@
 
 static void snd_hdsp_free_buffers(hdsp_t *hdsp)
 {
-	if (hdsp->capture_buffer_unaligned) {
-		snd_hammerfall_free_buffer(hdsp->pci, HDSP_DMA_AREA_BYTES,
-					   hdsp->capture_buffer_unaligned,
-					   hdsp->capture_buffer_addr, 1);
-	}
-
-	if (hdsp->playback_buffer_unaligned) {
-		snd_hammerfall_free_buffer(hdsp->pci, HDSP_DMA_AREA_BYTES,
-					   hdsp->playback_buffer_unaligned,
-					   hdsp->playback_buffer_addr, 0);
-	}
+	snd_hammerfall_free_buffer(&hdsp->capture_dma_buf, hdsp->pci);
+	snd_hammerfall_free_buffer(&hdsp->playback_dma_buf, hdsp->pci);
 }
 
 static int __devinit snd_hdsp_initialize_memory(hdsp_t *hdsp)
 {
-	void *pb, *cb;
-	dma_addr_t pb_addr, cb_addr;
 	unsigned long pb_bus, cb_bus;
 
-	cb = snd_hammerfall_get_buffer(hdsp->pci, HDSP_DMA_AREA_BYTES, &cb_addr, 1);
-	pb = snd_hammerfall_get_buffer(hdsp->pci, HDSP_DMA_AREA_BYTES, &pb_addr, 0);
-
-	if (cb == 0 || pb == 0) {
-		if (cb) {
-			snd_hammerfall_free_buffer(hdsp->pci, HDSP_DMA_AREA_BYTES, cb, cb_addr, 1);
-		}
-		if (pb) {
-			snd_hammerfall_free_buffer(hdsp->pci, HDSP_DMA_AREA_BYTES, pb, pb_addr, 0);
-		}
-
+	if (snd_hammerfall_get_buffer(hdsp->pci, &hdsp->capture_dma_buf, HDSP_DMA_AREA_BYTES) < 0 ||
+	    snd_hammerfall_get_buffer(hdsp->pci, &hdsp->playback_dma_buf, HDSP_DMA_AREA_BYTES) < 0) {
+		if (hdsp->capture_dma_buf.area)
+			snd_dma_free_pages(&hdsp->capture_dma_buf);
 		printk(KERN_ERR "%s: no buffers available\n", hdsp->card_name);
 		return -ENOMEM;
 	}
 
-	/* save raw addresses for use when freeing memory later */
-
-	hdsp->capture_buffer_unaligned = cb;
-	hdsp->playback_buffer_unaligned = pb;
-	hdsp->capture_buffer_addr = cb_addr;
-	hdsp->playback_buffer_addr = pb_addr;
-
 	/* Align to bus-space 64K boundary */
 
-	cb_bus = (cb_addr + 0xFFFF) & ~0xFFFFl;
-	pb_bus = (pb_addr + 0xFFFF) & ~0xFFFFl;
+	cb_bus = (hdsp->capture_dma_buf.addr + 0xFFFF) & ~0xFFFFl;
+	pb_bus = (hdsp->playback_dma_buf.addr + 0xFFFF) & ~0xFFFFl;
 
 	/* Tell the card where it is */
 
 	hdsp_write(hdsp, HDSP_inputBufferAddress, cb_bus);
 	hdsp_write(hdsp, HDSP_outputBufferAddress, pb_bus);
 
-	hdsp->capture_buffer = cb + (cb_bus - cb_addr);
-	hdsp->playback_buffer = pb + (pb_bus - pb_addr);
+	hdsp->capture_buffer = hdsp->capture_dma_buf.area + (cb_bus - hdsp->capture_dma_buf.addr);
+	hdsp->playback_buffer = hdsp->playback_dma_buf.area + (pb_bus - hdsp->playback_dma_buf.addr);
 
 	return 0;
 }
@@ -3809,7 +3723,7 @@
 
 static snd_pcm_uframes_t snd_hdsp_hw_pointer(snd_pcm_substream_t *substream)
 {
-	hdsp_t *hdsp = _snd_pcm_substream_chip(substream);
+	hdsp_t *hdsp = snd_pcm_substream_chip(substream);
 	return hdsp_hw_pointer(hdsp);
 }
 
@@ -3836,7 +3750,7 @@
 static int snd_hdsp_playback_copy(snd_pcm_substream_t *substream, int channel,
 				  snd_pcm_uframes_t pos, void __user *src, snd_pcm_uframes_t count)
 {
-	hdsp_t *hdsp = _snd_pcm_substream_chip(substream);
+	hdsp_t *hdsp = snd_pcm_substream_chip(substream);
 	char *channel_buf;
 
 	snd_assert(pos + count <= HDSP_CHANNEL_BUFFER_BYTES / 4, return -EINVAL);
@@ -3851,7 +3765,7 @@
 static int snd_hdsp_capture_copy(snd_pcm_substream_t *substream, int channel,
 				 snd_pcm_uframes_t pos, void __user *dst, snd_pcm_uframes_t count)
 {
-	hdsp_t *hdsp = _snd_pcm_substream_chip(substream);
+	hdsp_t *hdsp = snd_pcm_substream_chip(substream);
 	char *channel_buf;
 
 	snd_assert(pos + count <= HDSP_CHANNEL_BUFFER_BYTES / 4, return -EINVAL);
@@ -3866,7 +3780,7 @@
 static int snd_hdsp_hw_silence(snd_pcm_substream_t *substream, int channel,
 				  snd_pcm_uframes_t pos, snd_pcm_uframes_t count)
 {
-	hdsp_t *hdsp = _snd_pcm_substream_chip(substream);
+	hdsp_t *hdsp = snd_pcm_substream_chip(substream);
 	char *channel_buf;
 
 	channel_buf = hdsp_channel_buffer_location (hdsp, substream->pstr->stream, channel);
@@ -3878,7 +3792,7 @@
 static int snd_hdsp_reset(snd_pcm_substream_t *substream)
 {
 	snd_pcm_runtime_t *runtime = substream->runtime;
-	hdsp_t *hdsp = _snd_pcm_substream_chip(substream);
+	hdsp_t *hdsp = snd_pcm_substream_chip(substream);
 	snd_pcm_substream_t *other;
 	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
 		other = hdsp->capture_substream;
@@ -3906,7 +3820,7 @@
 static int snd_hdsp_hw_params(snd_pcm_substream_t *substream,
 				 snd_pcm_hw_params_t *params)
 {
-	hdsp_t *hdsp = _snd_pcm_substream_chip(substream);
+	hdsp_t *hdsp = snd_pcm_substream_chip(substream);
 	int err;
 	pid_t this_pid;
 	pid_t other_pid;
@@ -3989,7 +3903,7 @@
 static int snd_hdsp_channel_info(snd_pcm_substream_t *substream,
 				    snd_pcm_channel_info_t *info)
 {
-	hdsp_t *hdsp = _snd_pcm_substream_chip(substream);
+	hdsp_t *hdsp = snd_pcm_substream_chip(substream);
 	int mapped_channel;
 
 	snd_assert(info->channel < hdsp->max_channels, return -EINVAL);
@@ -4026,7 +3940,7 @@
 
 static int snd_hdsp_trigger(snd_pcm_substream_t *substream, int cmd)
 {
-	hdsp_t *hdsp = _snd_pcm_substream_chip(substream);
+	hdsp_t *hdsp = snd_pcm_substream_chip(substream);
 	snd_pcm_substream_t *other;
 	int running;
 	
@@ -4105,7 +4019,7 @@
 
 static int snd_hdsp_prepare(snd_pcm_substream_t *substream)
 {
-	hdsp_t *hdsp = _snd_pcm_substream_chip(substream);
+	hdsp_t *hdsp = snd_pcm_substream_chip(substream);
 	int result = 0;
 
 	if (hdsp_check_for_iobox (hdsp)) {
@@ -4123,10 +4037,10 @@
 		return -EIO;
 	}
 
-	spin_lock(&hdsp->lock);
+	spin_lock_irq(&hdsp->lock);
 	if (!hdsp->running)
 		hdsp_reset_hw_pointer(hdsp);
-	spin_unlock(&hdsp->lock);
+	spin_unlock_irq(&hdsp->lock);
 	return result;
 }
 
@@ -4183,20 +4097,16 @@
 
 static unsigned int hdsp_period_sizes[] = { 64, 128, 256, 512, 1024, 2048, 4096, 8192 };
 
-#define HDSP_PERIOD_SIZES sizeof(hdsp_period_sizes) / sizeof(hdsp_period_sizes[0])
-
 static snd_pcm_hw_constraint_list_t hdsp_hw_constraints_period_sizes = {
-	.count = HDSP_PERIOD_SIZES,
+	.count = ARRAY_SIZE(hdsp_period_sizes),
 	.list = hdsp_period_sizes,
 	.mask = 0
 };
 
 static unsigned int hdsp_9632_sample_rates[] = { 32000, 44100, 48000, 64000, 88200, 96000, 128000, 176400, 192000 };
 
-#define HDSP_9632_SAMPLE_RATES sizeof(hdsp_9632_sample_rates) / sizeof(hdsp_9632_sample_rates[0])
-
 static snd_pcm_hw_constraint_list_t hdsp_hw_constraints_9632_sample_rates = {
-	.count = HDSP_9632_SAMPLE_RATES,
+	.count = ARRAY_SIZE(hdsp_9632_sample_rates),
 	.list = hdsp_9632_sample_rates,
 	.mask = 0
 };
@@ -4364,8 +4274,7 @@
 
 static int snd_hdsp_playback_open(snd_pcm_substream_t *substream)
 {
-	hdsp_t *hdsp = _snd_pcm_substream_chip(substream);
-	unsigned long flags;
+	hdsp_t *hdsp = snd_pcm_substream_chip(substream);
 	snd_pcm_runtime_t *runtime = substream->runtime;
 
 	if (hdsp_check_for_iobox (hdsp)) {
@@ -4383,7 +4292,7 @@
 		return -EIO;
 	}
 
-	spin_lock_irqsave(&hdsp->lock, flags);
+	spin_lock_irq(&hdsp->lock);
 
 	snd_pcm_set_sync(substream);
 
@@ -4399,7 +4308,7 @@
 	hdsp->playback_pid = current->pid;
 	hdsp->playback_substream = substream;
 
-	spin_unlock_irqrestore(&hdsp->lock, flags);
+	spin_unlock_irq(&hdsp->lock);
 
 	snd_pcm_hw_constraint_msbits(runtime, 0, 32, 24);
 	snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_PERIOD_SIZE, &hdsp_hw_constraints_period_sizes);
@@ -4430,15 +4339,14 @@
 
 static int snd_hdsp_playback_release(snd_pcm_substream_t *substream)
 {
-	hdsp_t *hdsp = _snd_pcm_substream_chip(substream);
-	unsigned long flags;
+	hdsp_t *hdsp = snd_pcm_substream_chip(substream);
 
-	spin_lock_irqsave(&hdsp->lock, flags);
+	spin_lock_irq(&hdsp->lock);
 
 	hdsp->playback_pid = -1;
 	hdsp->playback_substream = NULL;
 
-	spin_unlock_irqrestore(&hdsp->lock, flags);
+	spin_unlock_irq(&hdsp->lock);
 
 	hdsp->spdif_ctl->vd[0].access |= SNDRV_CTL_ELEM_ACCESS_INACTIVE;
 	snd_ctl_notify(hdsp->card, SNDRV_CTL_EVENT_MASK_VALUE |
@@ -4449,8 +4357,7 @@
 
 static int snd_hdsp_capture_open(snd_pcm_substream_t *substream)
 {
-	hdsp_t *hdsp = _snd_pcm_substream_chip(substream);
-	unsigned long flags;
+	hdsp_t *hdsp = snd_pcm_substream_chip(substream);
 	snd_pcm_runtime_t *runtime = substream->runtime;
 
 	if (hdsp_check_for_iobox (hdsp)) {
@@ -4468,7 +4375,7 @@
 		return -EIO;
 	}
 
-	spin_lock_irqsave(&hdsp->lock, flags);
+	spin_lock_irq(&hdsp->lock);
 
 	snd_pcm_set_sync(substream);
 
@@ -4484,7 +4391,7 @@
 	hdsp->capture_pid = current->pid;
 	hdsp->capture_substream = substream;
 
-	spin_unlock_irqrestore(&hdsp->lock, flags);
+	spin_unlock_irq(&hdsp->lock);
 
 	snd_pcm_hw_constraint_msbits(runtime, 0, 32, 24);
 	snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_PERIOD_SIZE, &hdsp_hw_constraints_period_sizes);
@@ -4509,15 +4416,14 @@
 
 static int snd_hdsp_capture_release(snd_pcm_substream_t *substream)
 {
-	hdsp_t *hdsp = _snd_pcm_substream_chip(substream);
-	unsigned long flags;
+	hdsp_t *hdsp = snd_pcm_substream_chip(substream);
 
-	spin_lock_irqsave(&hdsp->lock, flags);
+	spin_lock_irq(&hdsp->lock);
 
 	hdsp->capture_pid = -1;
 	hdsp->capture_substream = NULL;
 
-	spin_unlock_irqrestore(&hdsp->lock, flags);
+	spin_unlock_irq(&hdsp->lock);
 	return 0;
 }
 
@@ -4830,19 +4736,13 @@
 	return 0;
 }
 
-static inline void snd_hdsp_9652_enable_mixer (hdsp_t *hdsp)
+static void snd_hdsp_9652_enable_mixer (hdsp_t *hdsp)
 {
         hdsp->control2_register |= HDSP_9652_ENABLE_MIXER;
 	hdsp_write (hdsp, HDSP_control2Reg, hdsp->control2_register);
 }
 
-static inline void snd_hdsp_9652_disable_mixer (hdsp_t *hdsp)
-{
-        hdsp->control2_register &= ~HDSP_9652_ENABLE_MIXER;
-	hdsp_write (hdsp, HDSP_control2Reg, hdsp->control2_register);
-}
-
-static inline int snd_hdsp_enable_io (hdsp_t *hdsp)
+static int snd_hdsp_enable_io (hdsp_t *hdsp)
 {
 	int i;
 	
@@ -4858,7 +4758,7 @@
 	return 0;
 }
 
-static inline void snd_hdsp_initialize_channels(hdsp_t *hdsp)
+static void snd_hdsp_initialize_channels(hdsp_t *hdsp)
 {
 	int status, aebi_channels, aebo_channels;
 	
@@ -4901,7 +4801,7 @@
 	}
 }
 
-static inline void snd_hdsp_initialize_midi_flush (hdsp_t *hdsp)
+static void snd_hdsp_initialize_midi_flush (hdsp_t *hdsp)
 {
 	snd_hdsp_flush_midi_input (hdsp, 0);
 	snd_hdsp_flush_midi_input (hdsp, 1);
@@ -4980,7 +4880,6 @@
 	spin_lock_init(&hdsp->midi[0].lock);
 	spin_lock_init(&hdsp->midi[1].lock);
 	hdsp->iobase = 0;
-	hdsp->res_port = NULL;
 	hdsp->control_register = 0;
 	hdsp->control2_register = 0;
 	hdsp->io_type = Undefined;
@@ -5035,13 +4934,9 @@
 
 	pci_set_master(hdsp->pci);
 
+	if ((err = pci_request_regions(pci, "hdsp")) < 0)
+		return err;
 	hdsp->port = pci_resource_start(pci, 0);
-
-	if ((hdsp->res_port = request_mem_region(hdsp->port, HDSP_IO_EXTENT, "hdsp")) == NULL) {
-		snd_printk("unable to grab memory region 0x%lx-0x%lx\n", hdsp->port, hdsp->port + HDSP_IO_EXTENT - 1);
-		return -EBUSY;
-	}
-
 	if ((hdsp->iobase = (unsigned long) ioremap_nocache(hdsp->port, HDSP_IO_EXTENT)) == 0) {
 		snd_printk("unable to remap region 0x%lx-0x%lx\n", hdsp->port, hdsp->port + HDSP_IO_EXTENT - 1);
 		return -EBUSY;
@@ -5114,7 +5009,7 @@
 
 static int snd_hdsp_free(hdsp_t *hdsp)
 {
-	if (hdsp->res_port) {
+	if (hdsp->port) {
 		/* stop the audio, and cancel all interrupts */
 		hdsp->control_register &= ~(HDSP_Start|HDSP_AudioInterruptEnable|HDSP_Midi0InterruptEnable|HDSP_Midi1InterruptEnable);
 		hdsp_write (hdsp, HDSP_controlRegister, hdsp->control_register);
@@ -5128,10 +5023,8 @@
 	if (hdsp->iobase)
 		iounmap((void *) hdsp->iobase);
 
-	if (hdsp->res_port) {
-		release_resource(hdsp->res_port);
-		kfree_nocheck(hdsp->res_port);
-	}
+	if (hdsp->port)
+		pci_release_regions(hdsp->pci);
 		
 	return 0;
 }
diff -Nru a/sound/pci/rme9652/rme9652.c b/sound/pci/rme9652/rme9652.c
--- a/sound/pci/rme9652/rme9652.c	2004-10-18 14:56:29 -07:00
+++ b/sound/pci/rme9652/rme9652.c	2004-10-18 14:56:29 -07:00
@@ -46,21 +46,16 @@
 
 module_param_array(index, int, boot_devs, 0444);
 MODULE_PARM_DESC(index, "Index value for RME Digi9652 (Hammerfall) soundcard.");
-MODULE_PARM_SYNTAX(index, SNDRV_INDEX_DESC);
 module_param_array(id, charp, boot_devs, 0444);
 MODULE_PARM_DESC(id, "ID string for RME Digi9652 (Hammerfall) soundcard.");
-MODULE_PARM_SYNTAX(id, SNDRV_ID_DESC);
 module_param_array(enable, bool, boot_devs, 0444);
 MODULE_PARM_DESC(enable, "Enable/disable specific RME96{52,36} soundcards.");
-MODULE_PARM_SYNTAX(enable, SNDRV_ENABLE_DESC);
 module_param_array(precise_ptr, bool, boot_devs, 0444);
 MODULE_PARM_DESC(precise_ptr, "Enable precise pointer (doesn't work reliably).");
-MODULE_PARM_SYNTAX(precise_ptr, SNDRV_ENABLED "," SNDRV_BOOLEAN_FALSE_DESC);
 MODULE_AUTHOR("Paul Davis <pbd@op.net>, Winfried Ritsch");
 MODULE_DESCRIPTION("RME Digi9652/Digi9636");
 MODULE_LICENSE("GPL");
-MODULE_CLASSES("{sound}");
-MODULE_DEVICES("{{RME,Hammerfall},"
+MODULE_SUPPORTED_DEVICE("{{RME,Hammerfall},"
 		"{RME,Hammerfall-Light}}");
 
 /* The Hammerfall has two sets of 24 ADAT + 2 S/PDIF channels, one for
@@ -217,7 +212,6 @@
 	spinlock_t lock;
 	int irq;
 	unsigned long port;
-	struct resource *res_port;
 	unsigned long iobase;
 	
 	int precise_ptr;
@@ -239,12 +233,11 @@
 	unsigned char ds_channels;
 	unsigned char ss_channels;	/* different for hammerfall/hammerfall-light */
 
-	void *capture_buffer_unaligned;	/* original buffer addresses */
-	void *playback_buffer_unaligned;	/* original buffer addresses */
+	struct snd_dma_buffer playback_dma_buf;
+	struct snd_dma_buffer capture_dma_buf;
+
 	unsigned char *capture_buffer;	/* suitably aligned address */
 	unsigned char *playback_buffer;	/* suitably aligned address */
-	dma_addr_t capture_buffer_addr;
-	dma_addr_t playback_buffer_addr;
 
 	pid_t capture_pid;
 	pid_t playback_pid;
@@ -307,50 +300,24 @@
 	-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1
 };
 
-#define RME9652_PREALLOCATE_MEMORY	/* via module snd-hammerfall-mem */
-
-#ifdef RME9652_PREALLOCATE_MEMORY
-static void *snd_hammerfall_get_buffer(struct pci_dev *pci, size_t size, dma_addr_t *addrp, int capture)
+static int snd_hammerfall_get_buffer(struct pci_dev *pci, struct snd_dma_buffer *dmab, size_t size)
 {
-	struct snd_dma_device pdev;
-	struct snd_dma_buffer dmbuf;
-
-	memset(&pdev, 0, sizeof(pdev));
-	pdev.type = SNDRV_DMA_TYPE_DEV;
-	pdev.dev = snd_dma_pci_data(pci);
-	pdev.id = capture;
-	dmbuf.bytes = 0;
-	if (! snd_dma_get_reserved(&pdev, &dmbuf)) {
-		if (snd_dma_alloc_pages(&pdev, size, &dmbuf) < 0)
-			return NULL;
-		snd_dma_set_reserved(&pdev, &dmbuf);
+	dmab->dev.type = SNDRV_DMA_TYPE_DEV;
+	dmab->dev.dev = snd_dma_pci_data(pci);
+	if (! snd_dma_get_reserved_buf(dmab, snd_dma_pci_buf_id(pci))) {
+		if (snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, snd_dma_pci_data(pci),
+					size, dmab) < 0)
+			return -ENOMEM;
 	}
-	*addrp = dmbuf.addr;
-	return dmbuf.area;
-}
-
-static void snd_hammerfall_free_buffer(struct pci_dev *pci, size_t size, void *ptr, dma_addr_t addr, int capture)
-{
-	struct snd_dma_device pdev;
-
-	memset(&pdev, 0, sizeof(pdev));
-	pdev.type = SNDRV_DMA_TYPE_DEV;
-	pdev.dev = snd_dma_pci_data(pci);
-	pdev.id = capture;
-	snd_dma_free_reserved(&pdev);
+	return 0;
 }
 
-#else
-static void *snd_hammerfall_get_buffer(struct pci_dev *pci, size_t size, dma_addr_t *addrp, int capture)
+static void snd_hammerfall_free_buffer(struct snd_dma_buffer *dmab, struct pci_dev *pci)
 {
-	return snd_malloc_pci_pages(pci, size, addrp);
+	if (dmab->area)
+		snd_dma_reserve_buf(dmab, snd_dma_pci_buf_id(pci));
 }
 
-static void snd_hammerfall_free_buffer(struct pci_dev *pci, size_t size, void *ptr, dma_addr_t addr, int capture)
-{
-	snd_free_pci_pages(pci, size, ptr, addr);
-}
-#endif
 
 static struct pci_device_id snd_rme9652_ids[] = {
 	{
@@ -858,7 +825,7 @@
 
 static int snd_rme9652_control_spdif_get(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
 {
-	rme9652_t *rme9652 = _snd_kcontrol_chip(kcontrol);
+	rme9652_t *rme9652 = snd_kcontrol_chip(kcontrol);
 	
 	snd_rme9652_convert_to_aes(&ucontrol->value.iec958, rme9652->creg_spdif);
 	return 0;
@@ -866,16 +833,15 @@
 
 static int snd_rme9652_control_spdif_put(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
 {
-	rme9652_t *rme9652 = _snd_kcontrol_chip(kcontrol);
-	unsigned long flags;
+	rme9652_t *rme9652 = snd_kcontrol_chip(kcontrol);
 	int change;
 	u32 val;
 	
 	val = snd_rme9652_convert_from_aes(&ucontrol->value.iec958);
-	spin_lock_irqsave(&rme9652->lock, flags);
+	spin_lock_irq(&rme9652->lock);
 	change = val != rme9652->creg_spdif;
 	rme9652->creg_spdif = val;
-	spin_unlock_irqrestore(&rme9652->lock, flags);
+	spin_unlock_irq(&rme9652->lock);
 	return change;
 }
 
@@ -888,7 +854,7 @@
 
 static int snd_rme9652_control_spdif_stream_get(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
 {
-	rme9652_t *rme9652 = _snd_kcontrol_chip(kcontrol);
+	rme9652_t *rme9652 = snd_kcontrol_chip(kcontrol);
 	
 	snd_rme9652_convert_to_aes(&ucontrol->value.iec958, rme9652->creg_spdif_stream);
 	return 0;
@@ -896,18 +862,17 @@
 
 static int snd_rme9652_control_spdif_stream_put(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
 {
-	rme9652_t *rme9652 = _snd_kcontrol_chip(kcontrol);
-	unsigned long flags;
+	rme9652_t *rme9652 = snd_kcontrol_chip(kcontrol);
 	int change;
 	u32 val;
 	
 	val = snd_rme9652_convert_from_aes(&ucontrol->value.iec958);
-	spin_lock_irqsave(&rme9652->lock, flags);
+	spin_lock_irq(&rme9652->lock);
 	change = val != rme9652->creg_spdif_stream;
 	rme9652->creg_spdif_stream = val;
 	rme9652->control_register &= ~(RME9652_PRO | RME9652_Dolby | RME9652_EMP);
 	rme9652_write(rme9652, RME9652_control_register, rme9652->control_register |= val);
-	spin_unlock_irqrestore(&rme9652->lock, flags);
+	spin_unlock_irq(&rme9652->lock);
 	return change;
 }
 
@@ -977,30 +942,28 @@
 
 static int snd_rme9652_get_adat1_in(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
 {
-	rme9652_t *rme9652 = _snd_kcontrol_chip(kcontrol);
-	unsigned long flags;
+	rme9652_t *rme9652 = snd_kcontrol_chip(kcontrol);
 	
-	spin_lock_irqsave(&rme9652->lock, flags);
+	spin_lock_irq(&rme9652->lock);
 	ucontrol->value.enumerated.item[0] = rme9652_adat1_in(rme9652);
-	spin_unlock_irqrestore(&rme9652->lock, flags);
+	spin_unlock_irq(&rme9652->lock);
 	return 0;
 }
 
 static int snd_rme9652_put_adat1_in(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
 {
-	rme9652_t *rme9652 = _snd_kcontrol_chip(kcontrol);
-	unsigned long flags;
+	rme9652_t *rme9652 = snd_kcontrol_chip(kcontrol);
 	int change;
 	unsigned int val;
 	
 	if (!snd_rme9652_use_is_exclusive(rme9652))
 		return -EBUSY;
 	val = ucontrol->value.enumerated.item[0] % 2;
-	spin_lock_irqsave(&rme9652->lock, flags);
+	spin_lock_irq(&rme9652->lock);
 	change = val != rme9652_adat1_in(rme9652);
 	if (change)
 		rme9652_set_adat1_input(rme9652, val);
-	spin_unlock_irqrestore(&rme9652->lock, flags);
+	spin_unlock_irq(&rme9652->lock);
 	return change;
 }
 
@@ -1050,30 +1013,28 @@
 
 static int snd_rme9652_get_spdif_in(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
 {
-	rme9652_t *rme9652 = _snd_kcontrol_chip(kcontrol);
-	unsigned long flags;
+	rme9652_t *rme9652 = snd_kcontrol_chip(kcontrol);
 	
-	spin_lock_irqsave(&rme9652->lock, flags);
+	spin_lock_irq(&rme9652->lock);
 	ucontrol->value.enumerated.item[0] = rme9652_spdif_in(rme9652);
-	spin_unlock_irqrestore(&rme9652->lock, flags);
+	spin_unlock_irq(&rme9652->lock);
 	return 0;
 }
 
 static int snd_rme9652_put_spdif_in(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
 {
-	rme9652_t *rme9652 = _snd_kcontrol_chip(kcontrol);
-	unsigned long flags;
+	rme9652_t *rme9652 = snd_kcontrol_chip(kcontrol);
 	int change;
 	unsigned int val;
 	
 	if (!snd_rme9652_use_is_exclusive(rme9652))
 		return -EBUSY;
 	val = ucontrol->value.enumerated.item[0] % 3;
-	spin_lock_irqsave(&rme9652->lock, flags);
+	spin_lock_irq(&rme9652->lock);
 	change = val != rme9652_spdif_in(rme9652);
 	if (change)
 		rme9652_set_spdif_input(rme9652, val);
-	spin_unlock_irqrestore(&rme9652->lock, flags);
+	spin_unlock_irq(&rme9652->lock);
 	return change;
 }
 
@@ -1121,29 +1082,27 @@
 
 static int snd_rme9652_get_spdif_out(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
 {
-	rme9652_t *rme9652 = _snd_kcontrol_chip(kcontrol);
-	unsigned long flags;
+	rme9652_t *rme9652 = snd_kcontrol_chip(kcontrol);
 	
-	spin_lock_irqsave(&rme9652->lock, flags);
+	spin_lock_irq(&rme9652->lock);
 	ucontrol->value.integer.value[0] = rme9652_spdif_out(rme9652);
-	spin_unlock_irqrestore(&rme9652->lock, flags);
+	spin_unlock_irq(&rme9652->lock);
 	return 0;
 }
 
 static int snd_rme9652_put_spdif_out(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
 {
-	rme9652_t *rme9652 = _snd_kcontrol_chip(kcontrol);
-	unsigned long flags;
+	rme9652_t *rme9652 = snd_kcontrol_chip(kcontrol);
 	int change;
 	unsigned int val;
 	
 	if (!snd_rme9652_use_is_exclusive(rme9652))
 		return -EBUSY;
 	val = ucontrol->value.integer.value[0] & 1;
-	spin_lock_irqsave(&rme9652->lock, flags);
+	spin_lock_irq(&rme9652->lock);
 	change = (int)val != rme9652_spdif_out(rme9652);
 	rme9652_set_spdif_output(rme9652, val);
-	spin_unlock_irqrestore(&rme9652->lock, flags);
+	spin_unlock_irq(&rme9652->lock);
 	return change;
 }
 
@@ -1210,27 +1169,25 @@
 
 static int snd_rme9652_get_sync_mode(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
 {
-	rme9652_t *rme9652 = _snd_kcontrol_chip(kcontrol);
-	unsigned long flags;
+	rme9652_t *rme9652 = snd_kcontrol_chip(kcontrol);
 	
-	spin_lock_irqsave(&rme9652->lock, flags);
+	spin_lock_irq(&rme9652->lock);
 	ucontrol->value.enumerated.item[0] = rme9652_sync_mode(rme9652);
-	spin_unlock_irqrestore(&rme9652->lock, flags);
+	spin_unlock_irq(&rme9652->lock);
 	return 0;
 }
 
 static int snd_rme9652_put_sync_mode(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
 {
-	rme9652_t *rme9652 = _snd_kcontrol_chip(kcontrol);
-	unsigned long flags;
+	rme9652_t *rme9652 = snd_kcontrol_chip(kcontrol);
 	int change;
 	unsigned int val;
 	
 	val = ucontrol->value.enumerated.item[0] % 3;
-	spin_lock_irqsave(&rme9652->lock, flags);
+	spin_lock_irq(&rme9652->lock);
 	change = (int)val != rme9652_sync_mode(rme9652);
 	rme9652_set_sync_mode(rme9652, val);
-	spin_unlock_irqrestore(&rme9652->lock, flags);
+	spin_unlock_irq(&rme9652->lock);
 	return change;
 }
 
@@ -1291,7 +1248,7 @@
 static int snd_rme9652_info_sync_pref(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)
 {
 	static char *texts[4] = {"IEC958 In", "ADAT1 In", "ADAT2 In", "ADAT3 In"};
-	rme9652_t *rme9652 = _snd_kcontrol_chip(kcontrol);
+	rme9652_t *rme9652 = snd_kcontrol_chip(kcontrol);
 
 	uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
 	uinfo->count = 1;
@@ -1304,19 +1261,17 @@
 
 static int snd_rme9652_get_sync_pref(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
 {
-	rme9652_t *rme9652 = _snd_kcontrol_chip(kcontrol);
-	unsigned long flags;
+	rme9652_t *rme9652 = snd_kcontrol_chip(kcontrol);
 	
-	spin_lock_irqsave(&rme9652->lock, flags);
+	spin_lock_irq(&rme9652->lock);
 	ucontrol->value.enumerated.item[0] = rme9652_sync_pref(rme9652);
-	spin_unlock_irqrestore(&rme9652->lock, flags);
+	spin_unlock_irq(&rme9652->lock);
 	return 0;
 }
 
 static int snd_rme9652_put_sync_pref(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
 {
-	rme9652_t *rme9652 = _snd_kcontrol_chip(kcontrol);
-	unsigned long flags;
+	rme9652_t *rme9652 = snd_kcontrol_chip(kcontrol);
 	int change, max;
 	unsigned int val;
 	
@@ -1324,16 +1279,16 @@
 		return -EBUSY;
 	max = rme9652->ss_channels == RME9652_NCHANNELS ? 4 : 3;
 	val = ucontrol->value.enumerated.item[0] % max;
-	spin_lock_irqsave(&rme9652->lock, flags);
+	spin_lock_irq(&rme9652->lock);
 	change = (int)val != rme9652_sync_pref(rme9652);
 	rme9652_set_sync_pref(rme9652, val);
-	spin_unlock_irqrestore(&rme9652->lock, flags);
+	spin_unlock_irq(&rme9652->lock);
 	return change;
 }
 
 static int snd_rme9652_info_thru(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)
 {
-	rme9652_t *rme9652 = _snd_kcontrol_chip(kcontrol);
+	rme9652_t *rme9652 = snd_kcontrol_chip(kcontrol);
 	uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
 	uinfo->count = rme9652->ss_channels;
 	uinfo->value.integer.min = 0;
@@ -1343,7 +1298,7 @@
 
 static int snd_rme9652_get_thru(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
 {
-	rme9652_t *rme9652 = _snd_kcontrol_chip(kcontrol);
+	rme9652_t *rme9652 = snd_kcontrol_chip(kcontrol);
 	unsigned int k;
 	u32 thru_bits = rme9652->thru_bits;
 
@@ -1355,8 +1310,7 @@
 
 static int snd_rme9652_put_thru(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
 {
-	rme9652_t *rme9652 = _snd_kcontrol_chip(kcontrol);
-	unsigned long flags;
+	rme9652_t *rme9652 = snd_kcontrol_chip(kcontrol);
 	int change;
 	unsigned int chn;
 	u32 thru_bits = 0;
@@ -1369,7 +1323,7 @@
 			thru_bits |= 1 << chn;
 	}
 	
-	spin_lock_irqsave(&rme9652->lock, flags);
+	spin_lock_irq(&rme9652->lock);
 	change = thru_bits ^ rme9652->thru_bits;
 	if (change) {
 		for (chn = 0; chn < rme9652->ss_channels; ++chn) {
@@ -1378,7 +1332,7 @@
 			rme9652_set_thru(rme9652,chn,thru_bits&(1<<chn));
 		}
 	}
-	spin_unlock_irqrestore(&rme9652->lock, flags);
+	spin_unlock_irq(&rme9652->lock);
 	return !!change;
 }
 
@@ -1399,19 +1353,17 @@
 
 static int snd_rme9652_get_passthru(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
 {
-	rme9652_t *rme9652 = _snd_kcontrol_chip(kcontrol);
-	unsigned long flags;
+	rme9652_t *rme9652 = snd_kcontrol_chip(kcontrol);
 
-	spin_lock_irqsave(&rme9652->lock, flags);
+	spin_lock_irq(&rme9652->lock);
 	ucontrol->value.integer.value[0] = rme9652->passthru;
-	spin_unlock_irqrestore(&rme9652->lock, flags);
+	spin_unlock_irq(&rme9652->lock);
 	return 0;
 }
 
 static int snd_rme9652_put_passthru(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
 {
-	rme9652_t *rme9652 = _snd_kcontrol_chip(kcontrol);
-	unsigned long flags;
+	rme9652_t *rme9652 = snd_kcontrol_chip(kcontrol);
 	int change;
 	unsigned int val;
 	int err = 0;
@@ -1420,11 +1372,11 @@
 		return -EBUSY;
 
 	val = ucontrol->value.integer.value[0] & 1;
-	spin_lock_irqsave(&rme9652->lock, flags);
+	spin_lock_irq(&rme9652->lock);
 	change = (ucontrol->value.integer.value[0] != rme9652->passthru);
 	if (change)
 		err = rme9652_set_passthru(rme9652, val);
-	spin_unlock_irqrestore(&rme9652->lock, flags);
+	spin_unlock_irq(&rme9652->lock);
 	return err ? err : change;
 }
 
@@ -1447,12 +1399,11 @@
 
 static int snd_rme9652_get_spdif_rate(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
 {
-	rme9652_t *rme9652 = _snd_kcontrol_chip(kcontrol);
-	unsigned long flags;
+	rme9652_t *rme9652 = snd_kcontrol_chip(kcontrol);
 	
-	spin_lock_irqsave(&rme9652->lock, flags);
+	spin_lock_irq(&rme9652->lock);
 	ucontrol->value.integer.value[0] = rme9652_spdif_sample_rate(rme9652);
-	spin_unlock_irqrestore(&rme9652->lock, flags);
+	spin_unlock_irq(&rme9652->lock);
 	return 0;
 }
 
@@ -1477,7 +1428,7 @@
 
 static int snd_rme9652_get_adat_sync(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
 {
-	rme9652_t *rme9652 = _snd_kcontrol_chip(kcontrol);
+	rme9652_t *rme9652 = snd_kcontrol_chip(kcontrol);
 	unsigned int mask1, mask2, val;
 	
 	switch (kcontrol->private_value) {
@@ -1509,7 +1460,7 @@
 
 static int snd_rme9652_get_tc_valid(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
 {
-	rme9652_t *rme9652 = _snd_kcontrol_chip(kcontrol);
+	rme9652_t *rme9652 = snd_kcontrol_chip(kcontrol);
 	
 	ucontrol->value.integer.value[0] = 
 		(rme9652_read(rme9652, RME9652_status_register) & RME9652_tc_valid) ? 1 : 0;
@@ -1573,8 +1524,6 @@
 
 #endif				/* ALSA_HAS_STANDARD_WAY_OF_RETURNING_TIMECODE */
 
-#define RME9652_CONTROLS (sizeof(snd_rme9652_controls)/sizeof(snd_kcontrol_new_t))
-
 static snd_kcontrol_new_t snd_rme9652_controls[] = {
 {
 	.iface =	SNDRV_CTL_ELEM_IFACE_PCM,
@@ -1642,7 +1591,7 @@
 	int err;
 	snd_kcontrol_t *kctl;
 
-	for (idx = 0; idx < RME9652_CONTROLS; idx++) {
+	for (idx = 0; idx < ARRAY_SIZE(snd_rme9652_controls); idx++) {
 		if ((err = snd_ctl_add(card, kctl = snd_ctl_new1(&snd_rme9652_controls[idx], rme9652))) < 0)
 			return err;
 		if (idx == 1)	/* IEC958 (S/PDIF) Stream */
@@ -1847,17 +1796,8 @@
 
 static void snd_rme9652_free_buffers(rme9652_t *rme9652)
 {
-	if (rme9652->capture_buffer_unaligned) {
-		snd_hammerfall_free_buffer(rme9652->pci, RME9652_DMA_AREA_BYTES,
-					   rme9652->capture_buffer_unaligned,
-					   rme9652->capture_buffer_addr, 1);
-	}
-
-	if (rme9652->playback_buffer_unaligned) {
-		snd_hammerfall_free_buffer(rme9652->pci, RME9652_DMA_AREA_BYTES,
-					   rme9652->playback_buffer_unaligned,
-					   rme9652->playback_buffer_addr, 0);
-	}
+	snd_hammerfall_free_buffer(&rme9652->capture_dma_buf, rme9652->pci);
+	snd_hammerfall_free_buffer(&rme9652->playback_dma_buf, rme9652->pci);
 }
 
 static int snd_rme9652_free(rme9652_t *rme9652)
@@ -1866,57 +1806,40 @@
 		rme9652_stop(rme9652);
 	snd_rme9652_free_buffers(rme9652);
 
-	if (rme9652->iobase)
-		iounmap((void *) rme9652->iobase);
-	if (rme9652->res_port) {
-		release_resource(rme9652->res_port);
-		kfree_nocheck(rme9652->res_port);
-	}
 	if (rme9652->irq >= 0)
 		free_irq(rme9652->irq, (void *)rme9652);
+	if (rme9652->iobase)
+		iounmap((void *) rme9652->iobase);
+	if (rme9652->port)
+		pci_release_regions(rme9652->pci);
+
 	return 0;
 }
 
 static int __devinit snd_rme9652_initialize_memory(rme9652_t *rme9652)
 {
-	void *pb, *cb;
-	dma_addr_t pb_addr, cb_addr;
 	unsigned long pb_bus, cb_bus;
 
-	cb = snd_hammerfall_get_buffer(rme9652->pci, RME9652_DMA_AREA_BYTES, &cb_addr, 1);
-	pb = snd_hammerfall_get_buffer(rme9652->pci, RME9652_DMA_AREA_BYTES, &pb_addr, 0);
-
-	if (cb == 0 || pb == 0) {
-		if (cb) {
-			snd_hammerfall_free_buffer(rme9652->pci, RME9652_DMA_AREA_BYTES, cb, cb_addr, 1);
-		}
-		if (pb) {
-			snd_hammerfall_free_buffer(rme9652->pci, RME9652_DMA_AREA_BYTES, pb, pb_addr, 0);
-		}
-
+	if (snd_hammerfall_get_buffer(rme9652->pci, &rme9652->capture_dma_buf, RME9652_DMA_AREA_BYTES) < 0 ||
+	    snd_hammerfall_get_buffer(rme9652->pci, &rme9652->playback_dma_buf, RME9652_DMA_AREA_BYTES) < 0) {
+		if (rme9652->capture_dma_buf.area)
+			snd_dma_free_pages(&rme9652->capture_dma_buf);
 		printk(KERN_ERR "%s: no buffers available\n", rme9652->card_name);
 		return -ENOMEM;
 	}
 
-	/* save raw addresses for use when freeing memory later */
-
-	rme9652->capture_buffer_unaligned = cb;
-	rme9652->playback_buffer_unaligned = pb;
-	rme9652->capture_buffer_addr = cb_addr;
-	rme9652->playback_buffer_addr = pb_addr;
-
 	/* Align to bus-space 64K boundary */
 
-	cb_bus = (cb_addr + 0xFFFF) & ~0xFFFFl;
-	pb_bus = (pb_addr + 0xFFFF) & ~0xFFFFl;
+	cb_bus = (rme9652->capture_dma_buf.addr + 0xFFFF) & ~0xFFFFl;
+	pb_bus = (rme9652->playback_dma_buf.addr + 0xFFFF) & ~0xFFFFl;
 
 	/* Tell the card where it is */
 
 	rme9652_write(rme9652, RME9652_rec_buffer, cb_bus);
 	rme9652_write(rme9652, RME9652_play_buffer, pb_bus);
 
-	rme9652->capture_buffer = cb + (cb_bus - cb_addr);
-	rme9652->playback_buffer = pb + (pb_bus - pb_addr);
+	rme9652->capture_buffer = rme9652->capture_dma_buf.area + (cb_bus - rme9652->capture_dma_buf.addr);
+	rme9652->playback_buffer = rme9652->playback_dma_buf.area + (pb_bus - rme9652->playback_dma_buf.addr);
 
 	return 0;
 }
@@ -1984,7 +1907,7 @@
 
 static snd_pcm_uframes_t snd_rme9652_hw_pointer(snd_pcm_substream_t *substream)
 {
-	rme9652_t *rme9652 = _snd_pcm_substream_chip(substream);
+	rme9652_t *rme9652 = snd_pcm_substream_chip(substream);
 	return rme9652_hw_pointer(rme9652);
 }
 
@@ -2013,7 +1936,7 @@
 static int snd_rme9652_playback_copy(snd_pcm_substream_t *substream, int channel,
 				     snd_pcm_uframes_t pos, void __user *src, snd_pcm_uframes_t count)
 {
-	rme9652_t *rme9652 = _snd_pcm_substream_chip(substream);
+	rme9652_t *rme9652 = snd_pcm_substream_chip(substream);
 	char *channel_buf;
 
 	snd_assert(pos + count <= RME9652_CHANNEL_BUFFER_BYTES / 4, return -EINVAL);
@@ -2030,7 +1953,7 @@
 static int snd_rme9652_capture_copy(snd_pcm_substream_t *substream, int channel,
 				    snd_pcm_uframes_t pos, void __user *dst, snd_pcm_uframes_t count)
 {
-	rme9652_t *rme9652 = _snd_pcm_substream_chip(substream);
+	rme9652_t *rme9652 = snd_pcm_substream_chip(substream);
 	char *channel_buf;
 
 	snd_assert(pos + count <= RME9652_CHANNEL_BUFFER_BYTES / 4, return -EINVAL);
@@ -2047,7 +1970,7 @@
 static int snd_rme9652_hw_silence(snd_pcm_substream_t *substream, int channel,
 				  snd_pcm_uframes_t pos, snd_pcm_uframes_t count)
 {
-	rme9652_t *rme9652 = _snd_pcm_substream_chip(substream);
+	rme9652_t *rme9652 = snd_pcm_substream_chip(substream);
 	char *channel_buf;
 
 	channel_buf = rme9652_channel_buffer_location (rme9652,
@@ -2061,7 +1984,7 @@
 static int snd_rme9652_reset(snd_pcm_substream_t *substream)
 {
 	snd_pcm_runtime_t *runtime = substream->runtime;
-	rme9652_t *rme9652 = _snd_pcm_substream_chip(substream);
+	rme9652_t *rme9652 = snd_pcm_substream_chip(substream);
 	snd_pcm_substream_t *other;
 	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
 		other = rme9652->capture_substream;
@@ -2089,7 +2012,7 @@
 static int snd_rme9652_hw_params(snd_pcm_substream_t *substream,
 				 snd_pcm_hw_params_t *params)
 {
-	rme9652_t *rme9652 = _snd_pcm_substream_chip(substream);
+	rme9652_t *rme9652 = snd_pcm_substream_chip(substream);
 	int err;
 	pid_t this_pid;
 	pid_t other_pid;
@@ -2154,7 +2077,7 @@
 static int snd_rme9652_channel_info(snd_pcm_substream_t *substream,
 				    snd_pcm_channel_info_t *info)
 {
-	rme9652_t *rme9652 = _snd_pcm_substream_chip(substream);
+	rme9652_t *rme9652 = snd_pcm_substream_chip(substream);
 	int chn;
 
 	snd_assert(info->channel < RME9652_NCHANNELS, return -EINVAL);
@@ -2197,7 +2120,7 @@
 static int snd_rme9652_trigger(snd_pcm_substream_t *substream,
 			       int cmd)
 {
-	rme9652_t *rme9652 = _snd_pcm_substream_chip(substream);
+	rme9652_t *rme9652 = snd_pcm_substream_chip(substream);
 	snd_pcm_substream_t *other;
 	int running;
 	spin_lock(&rme9652->lock);
@@ -2260,13 +2183,14 @@
 
 static int snd_rme9652_prepare(snd_pcm_substream_t *substream)
 {
-	rme9652_t *rme9652 = _snd_pcm_substream_chip(substream);
+	rme9652_t *rme9652 = snd_pcm_substream_chip(substream);
+	unsigned long flags;
 	int result = 0;
 
-	spin_lock(&rme9652->lock);
+	spin_lock_irqsave(&rme9652->lock, flags);
 	if (!rme9652->running)
 		rme9652_reset_hw_pointer(rme9652);
-	spin_unlock(&rme9652->lock);
+	spin_unlock_irqrestore(&rme9652->lock, flags);
 	return result;
 }
 
@@ -2319,10 +2243,8 @@
 
 static unsigned int period_sizes[] = { 64, 128, 256, 512, 1024, 2048, 4096, 8192 };
 
-#define PERIOD_SIZES sizeof(period_sizes) / sizeof(period_sizes[0])
-
 static snd_pcm_hw_constraint_list_t hw_constraints_period_sizes = {
-	.count = PERIOD_SIZES,
+	.count = ARRAY_SIZE(period_sizes),
 	.list = period_sizes,
 	.mask = 0
 };
@@ -2386,11 +2308,10 @@
 
 static int snd_rme9652_playback_open(snd_pcm_substream_t *substream)
 {
-	rme9652_t *rme9652 = _snd_pcm_substream_chip(substream);
-	unsigned long flags;
+	rme9652_t *rme9652 = snd_pcm_substream_chip(substream);
 	snd_pcm_runtime_t *runtime = substream->runtime;
 
-	spin_lock_irqsave(&rme9652->lock, flags);
+	spin_lock_irq(&rme9652->lock);
 
 	snd_pcm_set_sync(substream);
 
@@ -2406,7 +2327,7 @@
 	rme9652->playback_pid = current->pid;
 	rme9652->playback_substream = substream;
 
-	spin_unlock_irqrestore(&rme9652->lock, flags);
+	spin_unlock_irq(&rme9652->lock);
 
 	snd_pcm_hw_constraint_msbits(runtime, 0, 32, 24);
 	snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_PERIOD_SIZE, &hw_constraints_period_sizes);
@@ -2429,15 +2350,14 @@
 
 static int snd_rme9652_playback_release(snd_pcm_substream_t *substream)
 {
-	rme9652_t *rme9652 = _snd_pcm_substream_chip(substream);
-	unsigned long flags;
+	rme9652_t *rme9652 = snd_pcm_substream_chip(substream);
 
-	spin_lock_irqsave(&rme9652->lock, flags);
+	spin_lock_irq(&rme9652->lock);
 
 	rme9652->playback_pid = -1;
 	rme9652->playback_substream = NULL;
 
-	spin_unlock_irqrestore(&rme9652->lock, flags);
+	spin_unlock_irq(&rme9652->lock);
 
 	rme9652->spdif_ctl->vd[0].access |= SNDRV_CTL_ELEM_ACCESS_INACTIVE;
 	snd_ctl_notify(rme9652->card, SNDRV_CTL_EVENT_MASK_VALUE |
@@ -2448,11 +2368,10 @@
 
 static int snd_rme9652_capture_open(snd_pcm_substream_t *substream)
 {
-	rme9652_t *rme9652 = _snd_pcm_substream_chip(substream);
-	unsigned long flags;
+	rme9652_t *rme9652 = snd_pcm_substream_chip(substream);
 	snd_pcm_runtime_t *runtime = substream->runtime;
 
-	spin_lock_irqsave(&rme9652->lock, flags);
+	spin_lock_irq(&rme9652->lock);
 
 	snd_pcm_set_sync(substream);
 
@@ -2468,7 +2387,7 @@
 	rme9652->capture_pid = current->pid;
 	rme9652->capture_substream = substream;
 
-	spin_unlock_irqrestore(&rme9652->lock, flags);
+	spin_unlock_irq(&rme9652->lock);
 
 	snd_pcm_hw_constraint_msbits(runtime, 0, 32, 24);
 	snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_PERIOD_SIZE, &hw_constraints_period_sizes);
@@ -2486,15 +2405,14 @@
 
 static int snd_rme9652_capture_release(snd_pcm_substream_t *substream)
 {
-	rme9652_t *rme9652 = _snd_pcm_substream_chip(substream);
-	unsigned long flags;
+	rme9652_t *rme9652 = snd_pcm_substream_chip(substream);
 
-	spin_lock_irqsave(&rme9652->lock, flags);
+	spin_lock_irq(&rme9652->lock);
 
 	rme9652->capture_pid = -1;
 	rme9652->capture_substream = NULL;
 
-	spin_unlock_irqrestore(&rme9652->lock, flags);
+	spin_unlock_irq(&rme9652->lock);
 	return 0;
 }
 
@@ -2576,12 +2494,9 @@
 
 	spin_lock_init(&rme9652->lock);
 
+	if ((err = pci_request_regions(pci, "rme9652")) < 0)
+		return err;
 	rme9652->port = pci_resource_start(pci, 0);
-	if ((rme9652->res_port = request_mem_region(rme9652->port, RME9652_IO_EXTENT, "rme9652")) == NULL) {
-		snd_printk("unable to grab memory region 0x%lx-0x%lx\n", rme9652->port, rme9652->port + RME9652_IO_EXTENT - 1);
-		return -EBUSY;
-	}
-
 	rme9652->iobase = (unsigned long) ioremap_nocache(rme9652->port, RME9652_IO_EXTENT);
 	if (rme9652->iobase == 0) {
 		snd_printk("unable to remap region 0x%lx-0x%lx\n", rme9652->port, rme9652->port + RME9652_IO_EXTENT - 1);
diff -Nru a/sound/pci/sonicvibes.c b/sound/pci/sonicvibes.c
--- a/sound/pci/sonicvibes.c	2004-10-18 14:56:48 -07:00
+++ b/sound/pci/sonicvibes.c	2004-10-18 14:56:48 -07:00
@@ -44,8 +44,7 @@
 MODULE_AUTHOR("Jaroslav Kysela <perex@suse.cz>");
 MODULE_DESCRIPTION("S3 SonicVibes PCI");
 MODULE_LICENSE("GPL");
-MODULE_CLASSES("{sound}");
-MODULE_DEVICES("{{S3,SonicVibes PCI}}");
+MODULE_SUPPORTED_DEVICE("{{S3,SonicVibes PCI}}");
 
 #ifndef PCI_VENDOR_ID_S3
 #define PCI_VENDOR_ID_S3             0x5333
@@ -64,22 +63,16 @@
 
 module_param_array(index, int, boot_devs, 0444);
 MODULE_PARM_DESC(index, "Index value for S3 SonicVibes soundcard.");
-MODULE_PARM_SYNTAX(index, SNDRV_INDEX_DESC);
 module_param_array(id, charp, boot_devs, 0444);
 MODULE_PARM_DESC(id, "ID string for S3 SonicVibes soundcard.");
-MODULE_PARM_SYNTAX(id, SNDRV_ID_DESC);
 module_param_array(enable, bool, boot_devs, 0444);
 MODULE_PARM_DESC(enable, "Enable S3 SonicVibes soundcard.");
-MODULE_PARM_SYNTAX(enable, SNDRV_ENABLE_DESC);
 module_param_array(reverb, bool, boot_devs, 0444);
 MODULE_PARM_DESC(reverb, "Enable reverb (SRAM is present) for S3 SonicVibes soundcard.");
-MODULE_PARM_SYNTAX(reverb, SNDRV_ENABLED "," SNDRV_ENABLE_DESC);
 module_param_array(mge, bool, boot_devs, 0444);
 MODULE_PARM_DESC(mge, "MIC Gain Enable for S3 SonicVibes soundcard.");
-MODULE_PARM_SYNTAX(mge, SNDRV_ENABLED "," SNDRV_ENABLE_DESC);
 module_param(dmaio, uint, 0444);
 MODULE_PARM_DESC(dmaio, "DDMA i/o base address for S3 SonicVibes soundcard.");
-MODULE_PARM_SYNTAX(dmaio, "global," SNDRV_PORT_DESC);
 
 /*
  * Enhanced port direct registers
@@ -207,7 +200,6 @@
  */
 
 typedef struct _snd_sonicvibes sonicvibes_t;
-#define chip_t sonicvibes_t
 
 struct _snd_sonicvibes {
 	unsigned long dma1size;
@@ -215,13 +207,9 @@
 	int irq;
 
 	unsigned long sb_port;
-	struct resource *res_sb_port;
 	unsigned long enh_port;
-	struct resource *res_enh_port;
 	unsigned long synth_port;
-	struct resource *res_synth_port;
 	unsigned long midi_port;
-	struct resource *res_midi_port;
 	unsigned long game_port;
 	unsigned int dmaa_port;
 	struct resource *res_dmaa;
@@ -599,7 +587,7 @@
 
 static irqreturn_t snd_sonicvibes_interrupt(int irq, void *dev_id, struct pt_regs *regs)
 {
-	sonicvibes_t *sonic = snd_magic_cast(sonicvibes_t, dev_id, return IRQ_NONE);
+	sonicvibes_t *sonic = dev_id;
 	unsigned char status;
 
 	status = inb(SV_REG(sonic, STATUS));
@@ -689,7 +677,6 @@
 
 static int snd_sonicvibes_playback_prepare(snd_pcm_substream_t * substream)
 {
-	unsigned long flags;
 	sonicvibes_t *sonic = snd_pcm_substream_chip(substream);
 	snd_pcm_runtime_t *runtime = substream->runtime;
 	unsigned char fmt = 0;
@@ -704,17 +691,16 @@
 		fmt |= 2;
 	snd_sonicvibes_setfmt(sonic, ~3, fmt);
 	snd_sonicvibes_set_dac_rate(sonic, runtime->rate);
-	spin_lock_irqsave(&sonic->reg_lock, flags);
+	spin_lock_irq(&sonic->reg_lock);
 	snd_sonicvibes_setdmaa(sonic, runtime->dma_addr, size);
 	snd_sonicvibes_out1(sonic, SV_IREG_DMA_A_UPPER, count >> 8);
 	snd_sonicvibes_out1(sonic, SV_IREG_DMA_A_LOWER, count);
-	spin_unlock_irqrestore(&sonic->reg_lock, flags);
+	spin_unlock_irq(&sonic->reg_lock);
 	return 0;
 }
 
 static int snd_sonicvibes_capture_prepare(snd_pcm_substream_t * substream)
 {
-	unsigned long flags;
 	sonicvibes_t *sonic = snd_pcm_substream_chip(substream);
 	snd_pcm_runtime_t *runtime = substream->runtime;
 	unsigned char fmt = 0;
@@ -730,11 +716,11 @@
 		fmt |= 0x20;
 	snd_sonicvibes_setfmt(sonic, ~0x30, fmt);
 	snd_sonicvibes_set_adc_rate(sonic, runtime->rate);
-	spin_lock_irqsave(&sonic->reg_lock, flags);
+	spin_lock_irq(&sonic->reg_lock);
 	snd_sonicvibes_setdmac(sonic, runtime->dma_addr, size);
 	snd_sonicvibes_out1(sonic, SV_IREG_DMA_C_UPPER, count >> 8);
 	snd_sonicvibes_out1(sonic, SV_IREG_DMA_C_LOWER, count);
-	spin_unlock_irqrestore(&sonic->reg_lock, flags);
+	spin_unlock_irq(&sonic->reg_lock);
 	return 0;
 }
 
@@ -864,7 +850,7 @@
 
 static void snd_sonicvibes_pcm_free(snd_pcm_t *pcm)
 {
-	sonicvibes_t *sonic = snd_magic_cast(sonicvibes_t, pcm->private_data, return);
+	sonicvibes_t *sonic = pcm->private_data;
 	sonic->pcm = NULL;
 	snd_pcm_lib_preallocate_free_for_all(pcm);
 }
@@ -922,19 +908,17 @@
 static int snd_sonicvibes_get_mux(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
 {
 	sonicvibes_t *sonic = snd_kcontrol_chip(kcontrol);
-	unsigned long flags;
 	
-	spin_lock_irqsave(&sonic->reg_lock, flags);
+	spin_lock_irq(&sonic->reg_lock);
 	ucontrol->value.enumerated.item[0] = ((snd_sonicvibes_in1(sonic, SV_IREG_LEFT_ADC) & SV_RECSRC_OUT) >> 5) - 1;
 	ucontrol->value.enumerated.item[1] = ((snd_sonicvibes_in1(sonic, SV_IREG_RIGHT_ADC) & SV_RECSRC_OUT) >> 5) - 1;
-	spin_unlock_irqrestore(&sonic->reg_lock, flags);
+	spin_unlock_irq(&sonic->reg_lock);
 	return 0;
 }
 
 static int snd_sonicvibes_put_mux(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
 {
 	sonicvibes_t *sonic = snd_kcontrol_chip(kcontrol);
-	unsigned long flags;
 	unsigned short left, right, oval1, oval2;
 	int change;
 	
@@ -943,7 +927,7 @@
 		return -EINVAL;
 	left = (ucontrol->value.enumerated.item[0] + 1) << 5;
 	right = (ucontrol->value.enumerated.item[1] + 1) << 5;
-	spin_lock_irqsave(&sonic->reg_lock, flags);
+	spin_lock_irq(&sonic->reg_lock);
 	oval1 = snd_sonicvibes_in1(sonic, SV_IREG_LEFT_ADC);
 	oval2 = snd_sonicvibes_in1(sonic, SV_IREG_RIGHT_ADC);
 	left = (oval1 & ~SV_RECSRC_OUT) | left;
@@ -951,7 +935,7 @@
 	change = left != oval1 || right != oval2;
 	snd_sonicvibes_out1(sonic, SV_IREG_LEFT_ADC, left);
 	snd_sonicvibes_out1(sonic, SV_IREG_RIGHT_ADC, right);
-	spin_unlock_irqrestore(&sonic->reg_lock, flags);
+	spin_unlock_irq(&sonic->reg_lock);
 	return change;
 }
 
@@ -975,15 +959,14 @@
 static int snd_sonicvibes_get_single(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
 {
 	sonicvibes_t *sonic = snd_kcontrol_chip(kcontrol);
-	unsigned long flags;
 	int reg = kcontrol->private_value & 0xff;
 	int shift = (kcontrol->private_value >> 8) & 0xff;
 	int mask = (kcontrol->private_value >> 16) & 0xff;
 	int invert = (kcontrol->private_value >> 24) & 0xff;
 	
-	spin_lock_irqsave(&sonic->reg_lock, flags);
+	spin_lock_irq(&sonic->reg_lock);
 	ucontrol->value.integer.value[0] = (snd_sonicvibes_in1(sonic, reg)>> shift) & mask;
-	spin_unlock_irqrestore(&sonic->reg_lock, flags);
+	spin_unlock_irq(&sonic->reg_lock);
 	if (invert)
 		ucontrol->value.integer.value[0] = mask - ucontrol->value.integer.value[0];
 	return 0;
@@ -992,7 +975,6 @@
 static int snd_sonicvibes_put_single(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
 {
 	sonicvibes_t *sonic = snd_kcontrol_chip(kcontrol);
-	unsigned long flags;
 	int reg = kcontrol->private_value & 0xff;
 	int shift = (kcontrol->private_value >> 8) & 0xff;
 	int mask = (kcontrol->private_value >> 16) & 0xff;
@@ -1004,12 +986,12 @@
 	if (invert)
 		val = mask - val;
 	val <<= shift;
-	spin_lock_irqsave(&sonic->reg_lock, flags);
+	spin_lock_irq(&sonic->reg_lock);
 	oval = snd_sonicvibes_in1(sonic, reg);
 	val = (oval & ~(mask << shift)) | val;
 	change = val != oval;
 	snd_sonicvibes_out1(sonic, reg, val);
-	spin_unlock_irqrestore(&sonic->reg_lock, flags);
+	spin_unlock_irq(&sonic->reg_lock);
 	return change;
 }
 
@@ -1033,7 +1015,6 @@
 static int snd_sonicvibes_get_double(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
 {
 	sonicvibes_t *sonic = snd_kcontrol_chip(kcontrol);
-	unsigned long flags;
 	int left_reg = kcontrol->private_value & 0xff;
 	int right_reg = (kcontrol->private_value >> 8) & 0xff;
 	int shift_left = (kcontrol->private_value >> 16) & 0x07;
@@ -1041,10 +1022,10 @@
 	int mask = (kcontrol->private_value >> 24) & 0xff;
 	int invert = (kcontrol->private_value >> 22) & 1;
 	
-	spin_lock_irqsave(&sonic->reg_lock, flags);
+	spin_lock_irq(&sonic->reg_lock);
 	ucontrol->value.integer.value[0] = (snd_sonicvibes_in1(sonic, left_reg) >> shift_left) & mask;
 	ucontrol->value.integer.value[1] = (snd_sonicvibes_in1(sonic, right_reg) >> shift_right) & mask;
-	spin_unlock_irqrestore(&sonic->reg_lock, flags);
+	spin_unlock_irq(&sonic->reg_lock);
 	if (invert) {
 		ucontrol->value.integer.value[0] = mask - ucontrol->value.integer.value[0];
 		ucontrol->value.integer.value[1] = mask - ucontrol->value.integer.value[1];
@@ -1055,7 +1036,6 @@
 static int snd_sonicvibes_put_double(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
 {
 	sonicvibes_t *sonic = snd_kcontrol_chip(kcontrol);
-	unsigned long flags;
 	int left_reg = kcontrol->private_value & 0xff;
 	int right_reg = (kcontrol->private_value >> 8) & 0xff;
 	int shift_left = (kcontrol->private_value >> 16) & 0x07;
@@ -1073,7 +1053,7 @@
 	}
 	val1 <<= shift_left;
 	val2 <<= shift_right;
-	spin_lock_irqsave(&sonic->reg_lock, flags);
+	spin_lock_irq(&sonic->reg_lock);
 	oval1 = snd_sonicvibes_in1(sonic, left_reg);
 	oval2 = snd_sonicvibes_in1(sonic, right_reg);
 	val1 = (oval1 & ~(mask << shift_left)) | val1;
@@ -1081,12 +1061,10 @@
 	change = val1 != oval1 || val2 != oval2;
 	snd_sonicvibes_out1(sonic, left_reg, val1);
 	snd_sonicvibes_out1(sonic, right_reg, val2);
-	spin_unlock_irqrestore(&sonic->reg_lock, flags);
+	spin_unlock_irq(&sonic->reg_lock);
 	return change;
 }
 
-#define SONICVIBES_CONTROLS (sizeof(snd_sonicvibes_controls)/sizeof(snd_kcontrol_new_t))
-
 static snd_kcontrol_new_t snd_sonicvibes_controls[] __devinitdata = {
 SONICVIBES_DOUBLE("Capture Volume", 0, SV_IREG_LEFT_ADC, SV_IREG_RIGHT_ADC, 0, 0, 15, 0),
 SONICVIBES_DOUBLE("Aux Playback Switch", 0, SV_IREG_LEFT_AUX1, SV_IREG_RIGHT_AUX1, 7, 7, 1, 1),
@@ -1113,7 +1091,7 @@
 
 static void snd_sonicvibes_master_free(snd_kcontrol_t *kcontrol)
 {
-	sonicvibes_t *sonic = snd_magic_cast(sonicvibes_t, _snd_kcontrol_chip(kcontrol), return);
+	sonicvibes_t *sonic = snd_kcontrol_chip(kcontrol);
 	sonic->master_mute = NULL;
 	sonic->master_volume = NULL;
 }
@@ -1129,7 +1107,7 @@
 	card = sonic->card;
 	strcpy(card->mixername, "S3 SonicVibes");
 
-	for (idx = 0; idx < SONICVIBES_CONTROLS; idx++) {
+	for (idx = 0; idx < ARRAY_SIZE(snd_sonicvibes_controls); idx++) {
 		if ((err = snd_ctl_add(card, kctl = snd_ctl_new1(&snd_sonicvibes_controls[idx], sonic))) < 0)
 			return err;
 		switch (idx) {
@@ -1147,7 +1125,7 @@
 static void snd_sonicvibes_proc_read(snd_info_entry_t *entry, 
 				     snd_info_buffer_t * buffer)
 {
-	sonicvibes_t *sonic = snd_magic_cast(sonicvibes_t, entry->private_data, return);
+	sonicvibes_t *sonic = entry->private_data;
 	unsigned char tmp;
 
 	tmp = sonic->srs_space & 0x0f;
@@ -1197,22 +1175,8 @@
 #endif
 	pci_write_config_dword(sonic->pci, 0x40, sonic->dmaa_port);
 	pci_write_config_dword(sonic->pci, 0x48, sonic->dmac_port);
-	if (sonic->res_sb_port) {
-		release_resource(sonic->res_sb_port);
-		kfree_nocheck(sonic->res_sb_port);
-	}
-	if (sonic->res_enh_port) {
-		release_resource(sonic->res_enh_port);
-		kfree_nocheck(sonic->res_enh_port);
-	}
-	if (sonic->res_synth_port) {
-		release_resource(sonic->res_synth_port);
-		kfree_nocheck(sonic->res_synth_port);
-	}
-	if (sonic->res_midi_port) {
-		release_resource(sonic->res_midi_port);
-		kfree_nocheck(sonic->res_midi_port);
-	}
+	if (sonic->irq >= 0)
+		free_irq(sonic->irq, (void *)sonic);
 	if (sonic->res_dmaa) {
 		release_resource(sonic->res_dmaa);
 		kfree_nocheck(sonic->res_dmaa);
@@ -1221,15 +1185,14 @@
 		release_resource(sonic->res_dmac);
 		kfree_nocheck(sonic->res_dmac);
 	}
-	if (sonic->irq >= 0)
-		free_irq(sonic->irq, (void *)sonic);
-	snd_magic_kfree(sonic);
+	pci_release_regions(sonic->pci);
+	kfree(sonic);
 	return 0;
 }
 
 static int snd_sonicvibes_dev_free(snd_device_t *device)
 {
-	sonicvibes_t *sonic = snd_magic_cast(sonicvibes_t, device->device_data, return -ENXIO);
+	sonicvibes_t *sonic = device->device_data;
 	return snd_sonicvibes_free(sonic);
 }
 
@@ -1257,38 +1220,25 @@
                 return -ENXIO;
         }
 
-	sonic = snd_magic_kcalloc(sonicvibes_t, 0, GFP_KERNEL);
+	sonic = kcalloc(1, sizeof(*sonic), GFP_KERNEL);
 	if (sonic == NULL)
 		return -ENOMEM;
 	spin_lock_init(&sonic->reg_lock);
 	sonic->card = card;
 	sonic->pci = pci;
 	sonic->irq = -1;
-	sonic->sb_port = pci_resource_start(pci, 0);
-	if ((sonic->res_sb_port = request_region(sonic->sb_port, 0x10, "S3 SonicVibes SB")) == NULL) {
-		snd_printk("unable to grab SB port at 0x%lx-0x%lx\n", sonic->sb_port, sonic->sb_port + 0x10 - 1);
-		snd_sonicvibes_free(sonic);
-		return -EBUSY;
+
+	if ((err = pci_request_regions(pci, "S3 SonicVibes")) < 0) {
+		kfree(sonic);
+		return err;
 	}
+
+	sonic->sb_port = pci_resource_start(pci, 0);
 	sonic->enh_port = pci_resource_start(pci, 1);
-	if ((sonic->res_enh_port = request_region(sonic->enh_port, 0x10, "S3 SonicVibes Enhanced")) == NULL) {
-		snd_printk("unable to grab PCM port at 0x%lx-0x%lx\n", sonic->enh_port, sonic->enh_port + 0x10 - 1);
-		snd_sonicvibes_free(sonic);
-		return -EBUSY;
-	}
 	sonic->synth_port = pci_resource_start(pci, 2);
-	if ((sonic->res_synth_port = request_region(sonic->synth_port, 4, "S3 SonicVibes Synth")) == NULL) {
-		snd_printk("unable to grab synth port at 0x%lx-0x%lx\n", sonic->synth_port, sonic->synth_port + 4 - 1);
-		snd_sonicvibes_free(sonic);
-		return -EBUSY;
-	}
 	sonic->midi_port = pci_resource_start(pci, 3);
-	if ((sonic->res_midi_port = request_region(sonic->midi_port, 4, "S3 SonicVibes Midi")) == NULL) {
-		snd_printk("unable to grab MIDI port at 0x%lx-0x%lx\n", sonic->midi_port, sonic->midi_port + 4 - 1);
-		snd_sonicvibes_free(sonic);
-		return -EBUSY;
-	}
 	sonic->game_port = pci_resource_start(pci, 4);
+
 	if (request_irq(pci->irq, snd_sonicvibes_interrupt, SA_INTERRUPT|SA_SHIRQ, "S3 SonicVibes", (void *)sonic)) {
 		snd_printk("unable to grab IRQ %d\n", pci->irq);
 		snd_sonicvibes_free(sonic);
@@ -1396,8 +1346,6 @@
  *  MIDI section
  */
 
-#define SONICVIBES_MIDI_CONTROLS (sizeof(snd_sonicvibes_midi_controls)/sizeof(snd_kcontrol_new_t))
-
 static snd_kcontrol_new_t snd_sonicvibes_midi_controls[] __devinitdata = {
 SONICVIBES_SINGLE("SonicVibes Wave Source RAM", 0, SV_IREG_WAVE_SOURCE, 0, 1, 0),
 SONICVIBES_SINGLE("SonicVibes Wave Source RAM+ROM", 0, SV_IREG_WAVE_SOURCE, 1, 1, 0),
@@ -1408,20 +1356,20 @@
 
 static int snd_sonicvibes_midi_input_open(mpu401_t * mpu)
 {
-	sonicvibes_t *sonic = snd_magic_cast(sonicvibes_t, mpu->private_data, return -EIO);
+	sonicvibes_t *sonic = mpu->private_data;
 	outb(sonic->irqmask &= ~SV_MIDI_MASK, SV_REG(sonic, IRQMASK));
 	return 0;
 }
 
 static void snd_sonicvibes_midi_input_close(mpu401_t * mpu)
 {
-	sonicvibes_t *sonic = snd_magic_cast(sonicvibes_t, mpu->private_data, return);
+	sonicvibes_t *sonic = mpu->private_data;
 	outb(sonic->irqmask |= SV_MIDI_MASK, SV_REG(sonic, IRQMASK));
 }
 
 static int __devinit snd_sonicvibes_midi(sonicvibes_t * sonic, snd_rawmidi_t * rmidi)
 {
-	mpu401_t * mpu = snd_magic_cast(mpu401_t, rmidi->private_data, return -ENXIO);
+	mpu401_t * mpu = rmidi->private_data;
 	snd_card_t *card = sonic->card;
 	snd_rawmidi_str_t *dir;
 	unsigned int idx;
@@ -1431,7 +1379,7 @@
 	mpu->open_input = snd_sonicvibes_midi_input_open;
 	mpu->close_input = snd_sonicvibes_midi_input_close;
 	dir = &rmidi->streams[SNDRV_RAWMIDI_STREAM_OUTPUT];
-	for (idx = 0; idx < SONICVIBES_MIDI_CONTROLS; idx++)
+	for (idx = 0; idx < ARRAY_SIZE(snd_sonicvibes_midi_controls); idx++)
 		if ((err = snd_ctl_add(card, snd_ctl_new1(&snd_sonicvibes_midi_controls[idx], sonic))) < 0)
 			return err;
 	return 0;
diff -Nru a/sound/pci/trident/trident.c b/sound/pci/trident/trident.c
--- a/sound/pci/trident/trident.c	2004-10-18 14:55:46 -07:00
+++ b/sound/pci/trident/trident.c	2004-10-18 14:55:46 -07:00
@@ -33,8 +33,7 @@
 MODULE_AUTHOR("Jaroslav Kysela <perex@suse.cz>, <audio@tridentmicro.com>");
 MODULE_DESCRIPTION("Trident 4D-WaveDX/NX & SiS SI7018");
 MODULE_LICENSE("GPL");
-MODULE_CLASSES("{sound}");
-MODULE_DEVICES("{{Trident,4DWave DX},"
+MODULE_SUPPORTED_DEVICE("{{Trident,4DWave DX},"
 		"{Trident,4DWave NX},"
 		"{SiS,SI7018 PCI Audio},"
 		"{Best Union,Miss Melody 4DWave PCI},"
@@ -56,19 +55,14 @@
 
 module_param_array(index, int, boot_devs, 0444);
 MODULE_PARM_DESC(index, "Index value for Trident 4DWave PCI soundcard.");
-MODULE_PARM_SYNTAX(index, SNDRV_INDEX_DESC);
 module_param_array(id, charp, boot_devs, 0444);
 MODULE_PARM_DESC(id, "ID string for Trident 4DWave PCI soundcard.");
-MODULE_PARM_SYNTAX(id, SNDRV_ID_DESC);
 module_param_array(enable, bool, boot_devs, 0444);
 MODULE_PARM_DESC(enable, "Enable Trident 4DWave PCI soundcard.");
-MODULE_PARM_SYNTAX(enable, SNDRV_ENABLE_DESC);
 module_param_array(pcm_channels, int, boot_devs, 0444);
 MODULE_PARM_DESC(pcm_channels, "Number of hardware channels assigned for PCM.");
-MODULE_PARM_SYNTAX(pcm_channels, SNDRV_ENABLED ",default:32,allows:{{1,32}}");
 module_param_array(wavetable_size, int, boot_devs, 0444);
 MODULE_PARM_DESC(wavetable_size, "Maximum memory size in kB for wavetable synth.");
-MODULE_PARM_SYNTAX(wavetable_size, SNDRV_ENABLED ",default:8192,skill:advanced");
 
 static struct pci_device_id snd_trident_ids[] = {
 	{ 0x1023, 0x2000, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, },	/* Trident 4DWave DX PCI Audio */
diff -Nru a/sound/pci/trident/trident_main.c b/sound/pci/trident/trident_main.c
--- a/sound/pci/trident/trident_main.c	2004-10-18 14:56:33 -07:00
+++ b/sound/pci/trident/trident_main.c	2004-10-18 14:56:33 -07:00
@@ -44,8 +44,6 @@
 
 #include <asm/io.h>
 
-#define chip_t trident_t
-
 static int snd_trident_pcm_mixer_build(trident_t *trident, snd_trident_voice_t * voice, snd_pcm_substream_t *substream);
 static int snd_trident_pcm_mixer_free(trident_t *trident, snd_trident_voice_t * voice, snd_pcm_substream_t *substream);
 static irqreturn_t snd_trident_interrupt(int irq, void *dev_id, struct pt_regs *regs);
@@ -119,7 +117,7 @@
 	unsigned int data = 0, treg;
 	unsigned short count = 0xffff;
 	unsigned long flags;
-	trident_t *trident = snd_magic_cast(trident_t, ac97->private_data, return -ENXIO);
+	trident_t *trident = ac97->private_data;
 
 	spin_lock_irqsave(&trident->reg_lock, flags);
 	if (trident->device == TRIDENT_DEVICE_ID_DX) {
@@ -178,7 +176,7 @@
 	unsigned int address, data;
 	unsigned short count = 0xffff;
 	unsigned long flags;
-	trident_t *trident = snd_magic_cast(trident_t, ac97->private_data, return);
+	trident_t *trident = ac97->private_data;
 
 	data = ((unsigned long) wdata) << 16;
 
@@ -908,7 +906,7 @@
 	snd_trident_voice_t *evoice = voice->extra;
 	snd_trident_pcm_mixer_t *mix = &trident->pcm_mixer[substream->number];
 
-	spin_lock(&trident->reg_lock);	
+	spin_lock_irq(&trident->reg_lock);	
 
 	/* set delta (rate) value */
 	voice->Delta = snd_trident_convert_rate(runtime->rate);
@@ -969,7 +967,7 @@
 		evoice->ESO = (runtime->period_size * 2) - 1;
 	}
 
-	spin_unlock(&trident->reg_lock);
+	spin_unlock_irq(&trident->reg_lock);
 
 	return 0;
 }
@@ -1010,7 +1008,7 @@
 	snd_trident_voice_t *voice = (snd_trident_voice_t *) runtime->private_data;
 	unsigned int val, ESO_bytes;
 
-	spin_lock(&trident->reg_lock);
+	spin_lock_irq(&trident->reg_lock);
 
 	// Initilize the channel and set channel Mode
 	outb(0, TRID_REG(trident, LEGACY_DMAR15));
@@ -1079,7 +1077,7 @@
 
 	snd_trident_write_voice_regs(trident, voice);
 
-	spin_unlock(&trident->reg_lock);
+	spin_unlock_irq(&trident->reg_lock);
 	return 0;
 }
 
@@ -1150,7 +1148,7 @@
 	snd_trident_voice_t *voice = (snd_trident_voice_t *) runtime->private_data;
 	snd_trident_voice_t *evoice = voice->extra;
 
-	spin_lock(&trident->reg_lock);
+	spin_lock_irq(&trident->reg_lock);
 
 	voice->LBA = runtime->dma_addr;
 	voice->Delta = snd_trident_convert_adc_rate(runtime->rate);
@@ -1199,7 +1197,7 @@
 		evoice->ESO = (runtime->period_size * 2) - 1;
 	}
 	
-	spin_unlock(&trident->reg_lock);
+	spin_unlock_irq(&trident->reg_lock);
 	return 0;
 }
 
@@ -1221,7 +1219,7 @@
 	snd_trident_voice_t *voice = (snd_trident_voice_t *) runtime->private_data;
 	snd_trident_voice_t *evoice = voice->extra;
 
-	spin_lock(&trident->reg_lock);
+	spin_lock_irq(&trident->reg_lock);
 
 	/* Set channel buffer Address */
 	if (voice->memblk)
@@ -1276,7 +1274,7 @@
 		evoice->ESO = (runtime->period_size * 2) - 1;
 	}
 
-	spin_unlock(&trident->reg_lock);
+	spin_unlock_irq(&trident->reg_lock);
 	return 0;
 }
 
@@ -1367,7 +1365,7 @@
 	unsigned int RESO, LBAO;
 	unsigned int temp;
 
-	spin_lock(&trident->reg_lock);
+	spin_lock_irq(&trident->reg_lock);
 
 	if (trident->device != TRIDENT_DEVICE_ID_SI7018) {
 
@@ -1479,7 +1477,7 @@
 		outl(temp, TRID_REG(trident, SI_SERIAL_INTF_CTRL));
 	}
 
-	spin_unlock(&trident->reg_lock);
+	spin_unlock_irq(&trident->reg_lock);
 
 	return 0;
 }
@@ -1526,7 +1524,7 @@
 	val = inl(TRID_REG(trident, T4D_STIMER)) & 0x00ffffff;
 	snd_pcm_group_for_each(pos, substream) {
 		s = snd_pcm_group_substream_entry(pos);
-		if ((trident_t *) _snd_pcm_chip(s->pcm) == trident) {
+		if ((trident_t *) snd_pcm_substream_chip(s) == trident) {
 			voice = (snd_trident_voice_t *) s->runtime->private_data;
 			evoice = voice->extra;
 			what |= 1 << (voice->number & 0x1f);
@@ -2127,21 +2125,21 @@
   ---------------------------------------------------------------------------*/
 static void snd_trident_pcm_free(snd_pcm_t *pcm)
 {
-	trident_t *trident = snd_magic_cast(trident_t, pcm->private_data, return);
+	trident_t *trident = pcm->private_data;
 	trident->pcm = NULL;
 	snd_pcm_lib_preallocate_free_for_all(pcm);
 }
 
 static void snd_trident_foldback_pcm_free(snd_pcm_t *pcm)
 {
-	trident_t *trident = snd_magic_cast(trident_t, pcm->private_data, return);
+	trident_t *trident = pcm->private_data;
 	trident->foldback = NULL;
 	snd_pcm_lib_preallocate_free_for_all(pcm);
 }
 
 static void snd_trident_spdif_pcm_free(snd_pcm_t *pcm)
 {
-	trident_t *trident = snd_magic_cast(trident_t, pcm->private_data, return);
+	trident_t *trident = pcm->private_data;
 	trident->spdif = NULL;
 	snd_pcm_lib_preallocate_free_for_all(pcm);
 }
@@ -2324,13 +2322,12 @@
 					 snd_ctl_elem_value_t * ucontrol)
 {
 	trident_t *trident = snd_kcontrol_chip(kcontrol);
-	unsigned long flags;
 	unsigned char val;
 
-	spin_lock_irqsave(&trident->reg_lock, flags);
+	spin_lock_irq(&trident->reg_lock);
 	val = trident->spdif_ctrl;
 	ucontrol->value.integer.value[0] = val == kcontrol->private_value;
-	spin_unlock_irqrestore(&trident->reg_lock, flags);
+	spin_unlock_irq(&trident->reg_lock);
 	return 0;
 }
 
@@ -2338,12 +2335,11 @@
 					 snd_ctl_elem_value_t * ucontrol)
 {
 	trident_t *trident = snd_kcontrol_chip(kcontrol);
-	unsigned long flags;
 	unsigned char val;
 	int change;
 
 	val = ucontrol->value.integer.value[0] ? (unsigned char) kcontrol->private_value : 0x00;
-	spin_lock_irqsave(&trident->reg_lock, flags);
+	spin_lock_irq(&trident->reg_lock);
 	/* S/PDIF C Channel bits 0-31 : 48khz, SCMS disabled */
 	change = trident->spdif_ctrl != val;
 	trident->spdif_ctrl = val;
@@ -2362,7 +2358,7 @@
 			outl(temp, TRID_REG(trident, SI_SERIAL_INTF_CTRL));
 		}
 	}
-	spin_unlock_irqrestore(&trident->reg_lock, flags);
+	spin_unlock_irq(&trident->reg_lock);
 	return change;
 }
 
@@ -2393,14 +2389,13 @@
 					 snd_ctl_elem_value_t * ucontrol)
 {
 	trident_t *trident = snd_kcontrol_chip(kcontrol);
-	unsigned long flags;
 
-	spin_lock_irqsave(&trident->reg_lock, flags);
+	spin_lock_irq(&trident->reg_lock);
 	ucontrol->value.iec958.status[0] = (trident->spdif_bits >> 0) & 0xff;
 	ucontrol->value.iec958.status[1] = (trident->spdif_bits >> 8) & 0xff;
 	ucontrol->value.iec958.status[2] = (trident->spdif_bits >> 16) & 0xff;
 	ucontrol->value.iec958.status[3] = (trident->spdif_bits >> 24) & 0xff;
-	spin_unlock_irqrestore(&trident->reg_lock, flags);
+	spin_unlock_irq(&trident->reg_lock);
 	return 0;
 }
 
@@ -2408,7 +2403,6 @@
 					 snd_ctl_elem_value_t * ucontrol)
 {
 	trident_t *trident = snd_kcontrol_chip(kcontrol);
-	unsigned long flags;
 	unsigned int val;
 	int change;
 
@@ -2416,7 +2410,7 @@
 	      (ucontrol->value.iec958.status[1] << 8) |
 	      (ucontrol->value.iec958.status[2] << 16) |
 	      (ucontrol->value.iec958.status[3] << 24);
-	spin_lock_irqsave(&trident->reg_lock, flags);
+	spin_lock_irq(&trident->reg_lock);
 	change = trident->spdif_bits != val;
 	trident->spdif_bits = val;
 	if (trident->device != TRIDENT_DEVICE_ID_SI7018) {
@@ -2426,7 +2420,7 @@
 		if (trident->spdif == NULL)
 			outl(trident->spdif_bits, TRID_REG(trident, SI_SPDIF_CS));
 	}
-	spin_unlock_irqrestore(&trident->reg_lock, flags);
+	spin_unlock_irq(&trident->reg_lock);
 	return change;
 }
 
@@ -2488,14 +2482,13 @@
 					snd_ctl_elem_value_t * ucontrol)
 {
 	trident_t *trident = snd_kcontrol_chip(kcontrol);
-	unsigned long flags;
 
-	spin_lock_irqsave(&trident->reg_lock, flags);
+	spin_lock_irq(&trident->reg_lock);
 	ucontrol->value.iec958.status[0] = (trident->spdif_pcm_bits >> 0) & 0xff;
 	ucontrol->value.iec958.status[1] = (trident->spdif_pcm_bits >> 8) & 0xff;
 	ucontrol->value.iec958.status[2] = (trident->spdif_pcm_bits >> 16) & 0xff;
 	ucontrol->value.iec958.status[3] = (trident->spdif_pcm_bits >> 24) & 0xff;
-	spin_unlock_irqrestore(&trident->reg_lock, flags);
+	spin_unlock_irq(&trident->reg_lock);
 	return 0;
 }
 
@@ -2503,7 +2496,6 @@
 					snd_ctl_elem_value_t * ucontrol)
 {
 	trident_t *trident = snd_kcontrol_chip(kcontrol);
-	unsigned long flags;
 	unsigned int val;
 	int change;
 
@@ -2511,7 +2503,7 @@
 	      (ucontrol->value.iec958.status[1] << 8) |
 	      (ucontrol->value.iec958.status[2] << 16) |
 	      (ucontrol->value.iec958.status[3] << 24);
-	spin_lock_irqsave(&trident->reg_lock, flags);
+	spin_lock_irq(&trident->reg_lock);
 	change = trident->spdif_pcm_bits != val;
 	trident->spdif_pcm_bits = val;
 	if (trident->spdif != NULL) {
@@ -2521,7 +2513,7 @@
 			outl(trident->spdif_bits, TRID_REG(trident, SI_SPDIF_CS));
 		}
 	}
-	spin_unlock_irqrestore(&trident->reg_lock, flags);
+	spin_unlock_irq(&trident->reg_lock);
 	return change;
 }
 
@@ -2554,13 +2546,12 @@
 					snd_ctl_elem_value_t * ucontrol)
 {
 	trident_t *trident = snd_kcontrol_chip(kcontrol);
-	unsigned long flags;
 	unsigned char val;
 
-	spin_lock_irqsave(&trident->reg_lock, flags);
+	spin_lock_irq(&trident->reg_lock);
 	val = trident->ac97_ctrl = inl(TRID_REG(trident, NX_ACR0_AC97_COM_STAT));
 	ucontrol->value.integer.value[0] = (val & (1 << kcontrol->private_value)) ? 1 : 0;
-	spin_unlock_irqrestore(&trident->reg_lock, flags);
+	spin_unlock_irq(&trident->reg_lock);
 	return 0;
 }
 
@@ -2568,11 +2559,10 @@
 					snd_ctl_elem_value_t * ucontrol)
 {
 	trident_t *trident = snd_kcontrol_chip(kcontrol);
-	unsigned long flags;
 	unsigned char val;
 	int change = 0;
 
-	spin_lock_irqsave(&trident->reg_lock, flags);
+	spin_lock_irq(&trident->reg_lock);
 	val = trident->ac97_ctrl = inl(TRID_REG(trident, NX_ACR0_AC97_COM_STAT));
 	val &= ~(1 << kcontrol->private_value);
 	if (ucontrol->value.integer.value[0])
@@ -2580,7 +2570,7 @@
 	change = val != trident->ac97_ctrl;
 	trident->ac97_ctrl = val;
 	outl(trident->ac97_ctrl = val, TRID_REG(trident, NX_ACR0_AC97_COM_STAT));
-	spin_unlock_irqrestore(&trident->reg_lock, flags);
+	spin_unlock_irq(&trident->reg_lock);
 	return change;
 }
 
@@ -2624,19 +2614,18 @@
 static int snd_trident_vol_control_put(snd_kcontrol_t * kcontrol,
 				       snd_ctl_elem_value_t * ucontrol)
 {
-	unsigned long flags;
 	trident_t *trident = snd_kcontrol_chip(kcontrol);
 	unsigned int val;
 	int change = 0;
 
-	spin_lock_irqsave(&trident->reg_lock, flags);
+	spin_lock_irq(&trident->reg_lock);
 	val = trident->musicvol_wavevol;
 	val &= ~(0xffff << kcontrol->private_value);
 	val |= ((255 - (ucontrol->value.integer.value[0] & 0xff)) |
 	        ((255 - (ucontrol->value.integer.value[1] & 0xff)) << 8)) << kcontrol->private_value;
 	change = val != trident->musicvol_wavevol;
 	outl(trident->musicvol_wavevol = val, TRID_REG(trident, T4D_MUSICVOL_WAVEVOL));
-	spin_unlock_irqrestore(&trident->reg_lock, flags);
+	spin_unlock_irq(&trident->reg_lock);
 	return change;
 }
 
@@ -2696,7 +2685,6 @@
 static int snd_trident_pcm_vol_control_put(snd_kcontrol_t * kcontrol,
 					   snd_ctl_elem_value_t * ucontrol)
 {
-	unsigned long flags;
 	trident_t *trident = snd_kcontrol_chip(kcontrol);
 	snd_trident_pcm_mixer_t *mix = &trident->pcm_mixer[snd_ctl_get_ioffnum(kcontrol, &ucontrol->id)];
 	unsigned int val;
@@ -2707,12 +2695,12 @@
 	} else {
 		val = (255 - (ucontrol->value.integer.value[0] & 255)) << 2;
 	}
-	spin_lock_irqsave(&trident->reg_lock, flags);
+	spin_lock_irq(&trident->reg_lock);
 	change = val != mix->vol;
 	mix->vol = val;
 	if (mix->voice != NULL)
 		snd_trident_write_vol_reg(trident, mix->voice, val);
-	spin_unlock_irqrestore(&trident->reg_lock, flags);
+	spin_unlock_irq(&trident->reg_lock);
 	return change;
 }
 
@@ -2760,7 +2748,6 @@
 static int snd_trident_pcm_pan_control_put(snd_kcontrol_t * kcontrol,
 					   snd_ctl_elem_value_t * ucontrol)
 {
-	unsigned long flags;
 	trident_t *trident = snd_kcontrol_chip(kcontrol);
 	snd_trident_pcm_mixer_t *mix = &trident->pcm_mixer[snd_ctl_get_ioffnum(kcontrol, &ucontrol->id)];
 	unsigned char val;
@@ -2770,12 +2757,12 @@
 		val = ucontrol->value.integer.value[0] & 0x3f;
 	else
 		val = (0x3f - (ucontrol->value.integer.value[0] & 0x3f)) | 0x40;
-	spin_lock_irqsave(&trident->reg_lock, flags);
+	spin_lock_irq(&trident->reg_lock);
 	change = val != mix->pan;
 	mix->pan = val;
 	if (mix->voice != NULL)
 		snd_trident_write_pan_reg(trident, mix->voice, val);
-	spin_unlock_irqrestore(&trident->reg_lock, flags);
+	spin_unlock_irq(&trident->reg_lock);
 	return change;
 }
 
@@ -2818,19 +2805,18 @@
 static int snd_trident_pcm_rvol_control_put(snd_kcontrol_t * kcontrol,
 					    snd_ctl_elem_value_t * ucontrol)
 {
-	unsigned long flags;
 	trident_t *trident = snd_kcontrol_chip(kcontrol);
 	snd_trident_pcm_mixer_t *mix = &trident->pcm_mixer[snd_ctl_get_ioffnum(kcontrol, &ucontrol->id)];
 	unsigned short val;
 	int change = 0;
 
 	val = 0x7f - (ucontrol->value.integer.value[0] & 0x7f);
-	spin_lock_irqsave(&trident->reg_lock, flags);
+	spin_lock_irq(&trident->reg_lock);
 	change = val != mix->rvol;
 	mix->rvol = val;
 	if (mix->voice != NULL)
 		snd_trident_write_rvol_reg(trident, mix->voice, val);
-	spin_unlock_irqrestore(&trident->reg_lock, flags);
+	spin_unlock_irq(&trident->reg_lock);
 	return change;
 }
 
@@ -2873,19 +2859,18 @@
 static int snd_trident_pcm_cvol_control_put(snd_kcontrol_t * kcontrol,
 					    snd_ctl_elem_value_t * ucontrol)
 {
-	unsigned long flags;
 	trident_t *trident = snd_kcontrol_chip(kcontrol);
 	snd_trident_pcm_mixer_t *mix = &trident->pcm_mixer[snd_ctl_get_ioffnum(kcontrol, &ucontrol->id)];
 	unsigned short val;
 	int change = 0;
 
 	val = 0x7f - (ucontrol->value.integer.value[0] & 0x7f);
-	spin_lock_irqsave(&trident->reg_lock, flags);
+	spin_lock_irq(&trident->reg_lock);
 	change = val != mix->cvol;
 	mix->cvol = val;
 	if (mix->voice != NULL)
 		snd_trident_write_cvol_reg(trident, mix->voice, val);
-	spin_unlock_irqrestore(&trident->reg_lock, flags);
+	spin_unlock_irq(&trident->reg_lock);
 	return change;
 }
 
@@ -2961,21 +2946,21 @@
 
 static int __devinit snd_trident_mixer(trident_t * trident, int pcm_spdif_device)
 {
-	ac97_bus_t _bus;
-	ac97_t _ac97;
+	ac97_template_t _ac97;
 	snd_card_t * card = trident->card;
 	snd_kcontrol_t *kctl;
 	snd_ctl_elem_value_t *uctl;
 	int idx, err, retries = 2;
+	static ac97_bus_ops_t ops = {
+		.write = snd_trident_codec_write,
+		.read = snd_trident_codec_read,
+	};
 
-	uctl = (snd_ctl_elem_value_t *)snd_kcalloc(sizeof(*uctl), GFP_KERNEL);
+	uctl = kcalloc(1, sizeof(*uctl), GFP_KERNEL);
 	if (!uctl)
 		return -ENOMEM;
 
-	memset(&_bus, 0, sizeof(_bus));
-	_bus.write = snd_trident_codec_write;
-	_bus.read = snd_trident_codec_read;
-	if ((err = snd_ac97_bus(trident->card, &_bus, &trident->ac97_bus)) < 0)
+	if ((err = snd_ac97_bus(trident->card, 0, &ops, NULL, &trident->ac97_bus)) < 0)
 		goto __out;
 
 	memset(&_ac97, 0, sizeof(_ac97));
@@ -3132,7 +3117,7 @@
 	trident_gameport_t *gp = (trident_gameport_t *)gameport;
 	trident_t *chip;
 	snd_assert(gp, return 0);
-	chip = snd_magic_cast(trident_t, gp->chip, return 0);
+	chip = gp->chip;
 	return inb(TRID_REG(chip, GAMEPORT_LEGACY));
 }
 
@@ -3141,7 +3126,7 @@
 	trident_gameport_t *gp = (trident_gameport_t *)gameport;
 	trident_t *chip;
 	snd_assert(gp, return);
-	chip = snd_magic_cast(trident_t, gp->chip, return);
+	chip = gp->chip;
 	outb(0xff, TRID_REG(chip, GAMEPORT_LEGACY));
 }
 
@@ -3152,7 +3137,7 @@
 	int i;
 
 	snd_assert(gp, return 0);
-	chip = snd_magic_cast(trident_t, gp->chip, return 0);
+	chip = gp->chip;
 
 	*buttons = (~inb(TRID_REG(chip, GAMEPORT_LEGACY)) >> 4) & 0xf;
 
@@ -3169,7 +3154,7 @@
 	trident_gameport_t *gp = (trident_gameport_t *)gameport;
 	trident_t *chip;
 	snd_assert(gp, return -1);
-	chip = snd_magic_cast(trident_t, gp->chip, return -1);
+	chip = gp->chip;
 
 	switch (mode) {
 		case GAMEPORT_MODE_COOKED:
@@ -3280,7 +3265,7 @@
 static void snd_trident_proc_read(snd_info_entry_t *entry, 
 				  snd_info_buffer_t * buffer)
 {
-	trident_t *trident = snd_magic_cast(trident_t, entry->private_data, return);
+	trident_t *trident = entry->private_data;
 	char *s;
 
 	switch (trident->device) {
@@ -3331,7 +3316,7 @@
 
 static int snd_trident_dev_free(snd_device_t *device)
 {
-	trident_t *trident = snd_magic_cast(trident_t, device->device_data, return -ENXIO);
+	trident_t *trident = device->device_data;
 	return snd_trident_free(trident);
 }
 
@@ -3354,7 +3339,8 @@
 	/* TLB array must be aligned to 16kB !!! so we allocate
 	   32kB region and correct offset when necessary */
 
-	if (snd_dma_alloc_pages(&trident->dma_dev, 2 * SNDRV_TRIDENT_MAX_PAGES * 4, &trident->tlb.buffer) < 0) {
+	if (snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, snd_dma_pci_data(trident->pci),
+				2 * SNDRV_TRIDENT_MAX_PAGES * 4, &trident->tlb.buffer) < 0) {
 		snd_printk(KERN_ERR "trident: unable to allocate TLB buffer\n");
 		return -ENOMEM;
 	}
@@ -3367,7 +3353,8 @@
 		return -ENOMEM;
 	}
 	/* allocate and setup silent page and initialise TLB entries */
-	if (snd_dma_alloc_pages(&trident->dma_dev, SNDRV_TRIDENT_PAGE_SIZE, &trident->tlb.silent_page) < 0) {
+	if (snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, snd_dma_pci_data(trident->pci),
+				SNDRV_TRIDENT_PAGE_SIZE, &trident->tlb.silent_page) < 0) {
 		snd_printk(KERN_ERR "trident: unable to allocate silent page\n");
 		return -ENOMEM;
 	}
@@ -3553,7 +3540,7 @@
 		return -ENXIO;
 	}
 	
-	trident = snd_magic_kcalloc(trident_t, 0, GFP_KERNEL);
+	trident = kcalloc(1, sizeof(*trident), GFP_KERNEL);
 	if (trident == NULL)
 		return -ENOMEM;
 	trident->device = (pci->vendor << 16) | pci->device;
@@ -3570,18 +3557,17 @@
 	if (max_wavetable_size < 0 )
 		max_wavetable_size = 0;
 	trident->synth.max_size = max_wavetable_size * 1024;
-	trident->port = pci_resource_start(pci, 0);
 	trident->irq = -1;
 
 	trident->midi_port = TRID_REG(trident, T4D_MPU401_BASE);
 	pci_set_master(pci);
-	trident->port = pci_resource_start(pci, 0);
 
-	if ((trident->res_port = request_region(trident->port, 0x100, "Trident Audio")) == NULL) {
-		snd_printk("unable to grab I/O region 0x%lx-0x%lx\n", trident->port, trident->port + 0x100 - 1);
-		snd_trident_free(trident);
-		return -EBUSY;
+	if ((err = pci_request_regions(pci, "Trident Audio")) < 0) {
+		kfree(trident);
+		return err;
 	}
+	trident->port = pci_resource_start(pci, 0);
+
 	if (request_irq(pci->irq, snd_trident_interrupt, SA_INTERRUPT|SA_SHIRQ, "Trident Audio", (void *) trident)) {
 		snd_printk("unable to grab IRQ %d\n", pci->irq);
 		snd_trident_free(trident);
@@ -3589,10 +3575,6 @@
 	}
 	trident->irq = pci->irq;
 
-	memset(&trident->dma_dev, 0, sizeof(trident->dma_dev));
-	trident->dma_dev.type = SNDRV_DMA_TYPE_DEV;
-	trident->dma_dev.dev = snd_dma_pci_data(pci);
-
 	/* allocate 16k-aligned TLB for NX cards */
 	trident->tlb.entries = NULL;
 	trident->tlb.buffer.area = NULL;
@@ -3692,18 +3674,15 @@
 		if (trident->tlb.memhdr)
 			snd_util_memhdr_free(trident->tlb.memhdr);
 		if (trident->tlb.silent_page.area)
-			snd_dma_free_pages(&trident->dma_dev, &trident->tlb.silent_page);
+			snd_dma_free_pages(&trident->tlb.silent_page);
 		if (trident->tlb.shadow_entries)
 			vfree(trident->tlb.shadow_entries);
-		snd_dma_free_pages(&trident->dma_dev, &trident->tlb.buffer);
+		snd_dma_free_pages(&trident->tlb.buffer);
 	}
 	if (trident->irq >= 0)
 		free_irq(trident->irq, (void *)trident);
-	if (trident->res_port) {
-		release_resource(trident->res_port);
-		kfree_nocheck(trident->res_port);
-	}
-	snd_magic_kfree(trident);
+	pci_release_regions(trident->pci);
+	kfree(trident);
 	return 0;
 }
 
@@ -3727,7 +3706,7 @@
 
 static irqreturn_t snd_trident_interrupt(int irq, void *dev_id, struct pt_regs *regs)
 {
-	trident_t *trident = snd_magic_cast(trident_t, dev_id, return IRQ_NONE);
+	trident_t *trident = dev_id;
 	unsigned int audio_int, chn_int, stimer, channel, mask, tmp;
 	int delta;
 	snd_trident_voice_t *voice;
@@ -3950,7 +3929,7 @@
 #ifdef CONFIG_PM
 static int snd_trident_suspend(snd_card_t *card, unsigned int state)
 {
-	trident_t *trident = snd_magic_cast(trident_t, card->pm_private_data, return -EINVAL);
+	trident_t *trident = card->pm_private_data;
 
 	trident->in_suspend = 1;
 	snd_pcm_suspend_all(trident->pcm);
@@ -3976,7 +3955,7 @@
 
 static int snd_trident_resume(snd_card_t *card, unsigned int state)
 {
-	trident_t *trident = snd_magic_cast(trident_t, card->pm_private_data, return -EINVAL);
+	trident_t *trident = card->pm_private_data;
 
 	pci_enable_device(trident->pci);
 	if (pci_set_dma_mask(trident->pci, 0x3fffffff) < 0 ||
diff -Nru a/sound/pci/trident/trident_memory.c b/sound/pci/trident/trident_memory.c
--- a/sound/pci/trident/trident_memory.c	2004-10-18 14:56:48 -07:00
+++ b/sound/pci/trident/trident_memory.c	2004-10-18 14:56:48 -07:00
@@ -25,6 +25,7 @@
 
 #include <sound/driver.h>
 #include <asm/io.h>
+#include <linux/pci.h>
 #include <linux/time.h>
 #include <sound/core.h>
 #include <sound/trident.h>
@@ -189,7 +190,7 @@
 	snd_util_memblk_t *blk;
 	snd_pcm_runtime_t *runtime = substream->runtime;
 	int idx, page;
-	struct snd_sg_buf *sgbuf = runtime->dma_private;
+	struct snd_sg_buf *sgbuf = snd_pcm_substream_sgbuf(substream);
 
 	snd_assert(runtime->dma_bytes > 0 && runtime->dma_bytes <= SNDRV_TRIDENT_MAX_PAGES * SNDRV_TRIDENT_PAGE_SIZE, return NULL);
 	hdr = trident->tlb.memhdr;
@@ -274,7 +275,7 @@
 {
 	snd_assert(trident != NULL, return NULL);
 	snd_assert(substream != NULL, return NULL);
-	if (substream->dma_device.type == SNDRV_DMA_TYPE_DEV_SG)
+	if (substream->dma_buffer.dev.type == SNDRV_DMA_TYPE_DEV_SG)
 		return snd_trident_alloc_sg_pages(trident, substream);
 	else
 		return snd_trident_alloc_cont_pages(trident, substream);
@@ -367,10 +368,12 @@
 	set_silent_tlb(trident, page);
 	if (ptr) {
 		struct snd_dma_buffer dmab;
+		dmab.dev.type = SNDRV_DMA_TYPE_DEV;
+		dmab.dev.dev = snd_dma_pci_data(trident->pci);
 		dmab.area = ptr;
 		dmab.addr = addr;
 		dmab.bytes = ALIGN_PAGE_SIZE;
-		snd_dma_free_pages(&trident->dma_dev, &dmab);
+		snd_dma_free_pages(&dmab);
 	}
 }
 
@@ -412,10 +415,11 @@
 	 * fortunately Trident page size and kernel PAGE_SIZE is identical!
 	 */
 	for (page = first_page; page <= last_page; page++) {
-		if (snd_dma_alloc_pages(&hw->dma_dev, ALIGN_PAGE_SIZE, &dmab) < 0)
+		if (snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, snd_dma_pci_data(hw->pci),
+					ALIGN_PAGE_SIZE, &dmab) < 0)
 			goto __fail;
 		if (! is_valid_page(dmab.addr)) {
-			snd_dma_free_pages(&hw->dma_dev, &dmab);
+			snd_dma_free_pages(&dmab);
 			goto __fail;
 		}
 		set_tlb_bus(hw, page, (unsigned long)dmab.area, dmab.addr);
diff -Nru a/sound/pci/trident/trident_synth.c b/sound/pci/trident/trident_synth.c
--- a/sound/pci/trident/trident_synth.c	2004-10-18 14:56:29 -07:00
+++ b/sound/pci/trident/trident_synth.c	2004-10-18 14:56:29 -07:00
@@ -23,6 +23,7 @@
 #include <asm/io.h>
 #include <linux/init.h>
 #include <linux/slab.h>
+#include <linux/pci.h>
 #include <sound/core.h>
 #include <sound/trident.h>
 #include <sound/seq_device.h>
@@ -506,7 +507,7 @@
 static int snd_trident_simple_put_sample(void *private_data, simple_instrument_t * instr,
 					 char __user *data, long len, int atomic)
 {
-	trident_t *trident = snd_magic_cast(trident_t, private_data, return -ENXIO);
+	trident_t *trident = private_data;
 	int size = instr->size;
 	int shift = 0;
 
@@ -540,12 +541,12 @@
 		instr->address.memory = memblk->offset;
 	} else {
 		struct snd_dma_buffer dmab;
-
-		if (snd_dma_alloc_pages(&trident->dma_dev, size, &dmab) < 0)
+		if (snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, snd_dma_pci_data(trident->pci),
+					size, &dmab) < 0)
 			return -ENOMEM;
 
 		if (copy_from_user(dmab.area, data, size)) {
-			snd_dma_free_pages(&trident->dma_dev, &dmab);
+			snd_dma_free_pages(&dmab);
 			return -EFAULT;
 		}
 		instr->address.ptr = dmab.area;
@@ -559,7 +560,7 @@
 static int snd_trident_simple_get_sample(void *private_data, simple_instrument_t * instr,
 					 char __user *data, long len, int atomic)
 {
-	//trident_t *trident = snd_magic_cast(trident_t, private_data, return -ENXIO);
+	//trident_t *trident = private_data;
 	int size = instr->size;
 	int shift = 0;
 
@@ -580,9 +581,14 @@
 static int snd_trident_simple_remove_sample(void *private_data, simple_instrument_t * instr,
 					    int atomic)
 {
-	trident_t *trident = snd_magic_cast(trident_t, private_data, return -ENXIO);
+	trident_t *trident = private_data;
 	int size = instr->size;
 
+	if (instr->format & SIMPLE_WAVE_16BIT)
+		size <<= 1;
+	if (instr->format & SIMPLE_WAVE_STEREO)
+		size <<= 1;
+
 	if (trident->tlb.entries) {
 		snd_util_memblk_t *memblk = (snd_util_memblk_t*)instr->address.ptr;
 		if (memblk)
@@ -590,14 +596,15 @@
 		else
 			return -EFAULT;
 	} else {
-		kfree(instr->address.ptr);
+		struct snd_dma_buffer dmab;
+		dmab.dev.type = SNDRV_DMA_TYPE_DEV;
+		dmab.dev.dev = snd_dma_pci_data(trident->pci);
+		dmab.area = instr->address.ptr;
+		dmab.addr = instr->address.memory;
+		dmab.bytes = size;
+		snd_dma_free_pages(&dmab);
 	}
 
-	if (instr->format & SIMPLE_WAVE_16BIT)
-		size <<= 1;
-	if (instr->format & SIMPLE_WAVE_STEREO)
-		size <<= 1;
-
 	trident->synth.current_size -= size;
 	if (trident->synth.current_size < 0)	/* shouldn't need this check... */
 		trident->synth.current_size = 0;
@@ -838,7 +845,7 @@
 					   int what)
 {
 	int idx;
-	trident_t *trident = snd_magic_cast(trident_t, private_data, return);
+	trident_t *trident = private_data;
 	snd_trident_voice_t *pvoice;
 	unsigned long flags;
 
diff -Nru a/sound/pci/via82xx.c b/sound/pci/via82xx.c
--- a/sound/pci/via82xx.c	2004-10-18 14:56:50 -07:00
+++ b/sound/pci/via82xx.c	2004-10-18 14:56:50 -07:00
@@ -67,8 +67,7 @@
 MODULE_AUTHOR("Jaroslav Kysela <perex@suse.cz>");
 MODULE_DESCRIPTION("VIA VT82xx audio");
 MODULE_LICENSE("GPL");
-MODULE_CLASSES("{sound}");
-MODULE_DEVICES("{{VIA,VT82C686A/B/C,pci},{VIA,VT8233A/C,8235}}");
+MODULE_SUPPORTED_DEVICE("{{VIA,VT82C686A/B/C,pci},{VIA,VT8233A/C,8235}}");
 
 #if defined(CONFIG_GAMEPORT) || (defined(MODULE) && defined(CONFIG_GAMEPORT_MODULE))
 #define SUPPORT_JOYSTICK 1
@@ -88,30 +87,22 @@
 
 module_param_array(index, int, boot_devs, 0444);
 MODULE_PARM_DESC(index, "Index value for VIA 82xx bridge.");
-MODULE_PARM_SYNTAX(index, SNDRV_INDEX_DESC);
 module_param_array(id, charp, boot_devs, 0444);
 MODULE_PARM_DESC(id, "ID string for VIA 82xx bridge.");
-MODULE_PARM_SYNTAX(id, SNDRV_ID_DESC);
 module_param_array(enable, bool, boot_devs, 0444);
 MODULE_PARM_DESC(enable, "Enable audio part of VIA 82xx bridge.");
-MODULE_PARM_SYNTAX(enable, SNDRV_ENABLE_DESC);
 module_param_array(mpu_port, long, boot_devs, 0444);
 MODULE_PARM_DESC(mpu_port, "MPU-401 port. (VT82C686x only)");
-MODULE_PARM_SYNTAX(mpu_port, SNDRV_PORT_DESC);
 #ifdef SUPPORT_JOYSTICK
 module_param_array(joystick, bool, boot_devs, 0444);
 MODULE_PARM_DESC(joystick, "Enable joystick. (VT82C686x only)");
-MODULE_PARM_SYNTAX(joystick, SNDRV_ENABLE_DESC "," SNDRV_BOOLEAN_FALSE_DESC);
 #endif
 module_param_array(ac97_clock, int, boot_devs, 0444);
 MODULE_PARM_DESC(ac97_clock, "AC'97 codec clock (default 48000Hz).");
-MODULE_PARM_SYNTAX(ac97_clock, SNDRV_ENABLED ",default:48000");
 module_param_array(ac97_quirk, int, boot_devs, 0444);
 MODULE_PARM_DESC(ac97_quirk, "AC'97 workaround for strange hardware.");
-MODULE_PARM_SYNTAX(ac97_quirk, SNDRV_ENABLED ",allows:{{-1,4}},dialog:list,default:-1");
 module_param_array(dxs_support, int, boot_devs, 0444);
 MODULE_PARM_DESC(dxs_support, "Support for DXS channels (0 = auto, 1 = enable, 2 = disable, 3 = 48k only, 4 = no VRA)");
-MODULE_PARM_SYNTAX(dxs_support, SNDRV_ENABLED ",allows:{{0,4}},dialog:list");
 
 
 /* pci ids */
@@ -318,7 +309,6 @@
 
 typedef struct _snd_via82xx via82xx_t;
 typedef struct via_dev viadev_t;
-#define chip_t via82xx_t
 
 /*
  * pcm stream
@@ -362,7 +352,6 @@
 	int irq;
 
 	unsigned long port;
-	struct resource *res_port;
 	struct resource *mpu_res;
 	int chip_type;
 	unsigned char revision;
@@ -375,7 +364,6 @@
 	unsigned char spdif_ctrl_saved;
 	unsigned char capture_src_saved[2];
 	unsigned int mpu_port_saved;
-	u32 pci_state[16];
 #endif
 
 	unsigned char playback_volume[4][2]; /* for VIA8233/C/8235; default = 0 */
@@ -405,8 +393,6 @@
 	spinlock_t ac97_lock;
 	snd_info_entry_t *proc_entry;
 
-	struct snd_dma_device dma_dev;
-
 #ifdef SUPPORT_JOYSTICK
 	struct gameport gameport;
 	struct resource *res_joystick;
@@ -441,7 +427,9 @@
 		/* the start of each lists must be aligned to 8 bytes,
 		 * but the kernel pages are much bigger, so we don't care
 		 */
-		if (snd_dma_alloc_pages(&chip->dma_dev, PAGE_ALIGN(VIA_TABLE_SIZE * 2 * 8), &dev->table) < 0)
+		if (snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, snd_dma_pci_data(chip->pci),
+					PAGE_ALIGN(VIA_TABLE_SIZE * 2 * 8),
+					&dev->table) < 0)
 			return -ENOMEM;
 	}
 	if (! dev->idx_table) {
@@ -497,9 +485,8 @@
 static int clean_via_table(viadev_t *dev, snd_pcm_substream_t *substream,
 			   struct pci_dev *pci)
 {
-	via82xx_t *chip = snd_pcm_substream_chip(substream);
 	if (dev->table.area) {
-		snd_dma_free_pages(&chip->dma_dev, &dev->table);
+		snd_dma_free_pages(&dev->table);
 		dev->table.area = NULL;
 	}
 	if (dev->idx_table) {
@@ -556,7 +543,7 @@
  
 static void snd_via82xx_codec_wait(ac97_t *ac97)
 {
-	via82xx_t *chip = snd_magic_cast(via82xx_t, ac97->private_data, return);
+	via82xx_t *chip = ac97->private_data;
 	int err;
 	err = snd_via82xx_codec_ready(chip, ac97->num);
 	/* here we need to wait fairly for long time.. */
@@ -568,7 +555,7 @@
 				    unsigned short reg,
 				    unsigned short val)
 {
-	via82xx_t *chip = snd_magic_cast(via82xx_t, ac97->private_data, return);
+	via82xx_t *chip = ac97->private_data;
 	unsigned int xval;
 	
 	xval = !ac97->num ? VIA_REG_AC97_CODEC_ID_PRIMARY : VIA_REG_AC97_CODEC_ID_SECONDARY;
@@ -583,7 +570,7 @@
 
 static unsigned short snd_via82xx_codec_read(ac97_t *ac97, unsigned short reg)
 {
-	via82xx_t *chip = snd_magic_cast(via82xx_t, ac97->private_data, return ~0);
+	via82xx_t *chip = ac97->private_data;
 	unsigned int xval, val = 0xffff;
 	int again = 0;
 
@@ -632,11 +619,10 @@
 
 static irqreturn_t snd_via82xx_interrupt(int irq, void *dev_id, struct pt_regs *regs)
 {
-	via82xx_t *chip = snd_magic_cast(via82xx_t, dev_id, return IRQ_NONE);
+	via82xx_t *chip = dev_id;
 	unsigned int status;
 	unsigned int i;
 
-	spin_lock(&chip->reg_lock);
 #if 0
 	/* FIXME: does it work on via823x? */
 	if (chip->chip_type != TYPE_VIA686)
@@ -644,7 +630,6 @@
 #endif
 	status = inl(VIAREG(chip, SGD_SHADOW));
 	if (! (status & chip->intr_mask)) {
-		spin_unlock(&chip->reg_lock);
 		if (chip->rmidi)
 			/* check mpu401 interrupt */
 			return snd_mpu401_uart_interrupt(irq, chip->rmidi->private_data, regs);
@@ -653,6 +638,7 @@
 // _skip_sgd:
 
 	/* check status for each stream */
+	spin_lock(&chip->reg_lock);
 	for (i = 0; i < chip->num_devs; i++) {
 		viadev_t *viadev = &chip->devs[i];
 		unsigned char c_status = inb(VIADEV_REG(viadev, OFFSET_STATUS));
@@ -720,6 +706,10 @@
 /*
  * calculate the linear position at the given sg-buffer index and the rest count
  */
+
+#define check_invalid_pos(viadev,pos) \
+	((pos) < viadev->lastpos && ((pos) >= viadev->bufsize2 || viadev->lastpos < viadev->bufsize2))
+
 static inline unsigned int calc_linear_pos(viadev_t *viadev, unsigned int idx, unsigned int count)
 {
 	unsigned int size, res;
@@ -728,17 +718,24 @@
 	res = viadev->idx_table[idx].offset + size - count;
 
 	/* check the validity of the calculated position */
-	if (size < count || (res < viadev->lastpos && (res >= viadev->bufsize2 || viadev->lastpos < viadev->bufsize2))) {
+	if (size < count) {
+		snd_printd(KERN_ERR "invalid via82xx_cur_ptr (size = %d, count = %d)\n", (int)size, (int)count);
+		res = viadev->lastpos;
+	} else if (check_invalid_pos(viadev, res)) {
 #ifdef POINTER_DEBUG
 		printk("fail: idx = %i/%i, lastpos = 0x%x, bufsize2 = 0x%x, offsize = 0x%x, size = 0x%x, count = 0x%x\n", idx, viadev->tbl_entries, viadev->lastpos, viadev->bufsize2, viadev->idx_table[idx].offset, viadev->idx_table[idx].size, count);
 #endif
-		/* count register returns full size when end of buffer is reached */
-		if (size != count) {
+		if (count && size < count) {
 			snd_printd(KERN_ERR "invalid via82xx_cur_ptr, using last valid pointer\n");
 			res = viadev->lastpos;
 		} else {
-			res = viadev->idx_table[idx].offset + size;
-			if (res < viadev->lastpos && (res >= viadev->bufsize2 || viadev->lastpos < viadev->bufsize2)) {
+			if (! count)
+				/* bogus count 0 on the DMA boundary? */
+				res = viadev->idx_table[idx].offset;
+			else
+				/* count register returns full size when end of buffer is reached */
+				res = viadev->idx_table[idx].offset + size;
+			if (check_invalid_pos(viadev, res)) {
 				snd_printd(KERN_ERR "invalid via82xx_cur_ptr (2), using last valid pointer\n");
 				res = viadev->lastpos;
 			}
@@ -904,7 +901,7 @@
 {
 	int changed = 0;
 
-	spin_lock(&rec->lock);
+	spin_lock_irq(&rec->lock);
 	if (rec->rate != rate) {
 		if (rec->rate && rec->used > 1) /* already set */
 			changed = -EINVAL;
@@ -913,7 +910,7 @@
 			changed = 1;
 		}
 	}
-	spin_unlock(&rec->lock);
+	spin_unlock_irq(&rec->lock);
 	return changed;
 }
 
@@ -1035,6 +1032,7 @@
 	.info =			(SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED |
 				 SNDRV_PCM_INFO_BLOCK_TRANSFER |
 				 SNDRV_PCM_INFO_MMAP_VALID |
+				 SNDRV_PCM_INFO_RESUME |
 				 SNDRV_PCM_INFO_PAUSE),
 	.formats =		SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S16_LE,
 	.rates =		SNDRV_PCM_RATE_48000,
@@ -1058,32 +1056,18 @@
 {
 	snd_pcm_runtime_t *runtime = substream->runtime;
 	int err;
-	unsigned long flags;
 	struct via_rate_lock *ratep;
-	struct ratetbl {
-		int rate;
-		unsigned int bit;
-	} ratebits[] = {
-		{8000, SNDRV_PCM_RATE_8000},
-		{11025, SNDRV_PCM_RATE_11025},
-		{16000, SNDRV_PCM_RATE_16000},
-		{22050, SNDRV_PCM_RATE_22050},
-		{32000, SNDRV_PCM_RATE_32000},
-		{44100, SNDRV_PCM_RATE_44100},
-		{48000, SNDRV_PCM_RATE_48000},
-	};
-	int i;
 
 	runtime->hw = snd_via82xx_hw;
 	
 	/* set the hw rate condition */
 	ratep = &chip->rates[viadev->direction];
-	spin_lock_irqsave(&ratep->lock, flags);
+	spin_lock_irq(&ratep->lock);
 	ratep->used++;
-	if (chip->spdif_on) {
-		runtime->hw.rates = SNDRV_PCM_RATE_32000|SNDRV_PCM_RATE_44100|SNDRV_PCM_RATE_48000;
-		runtime->hw.rate_min = 32000;
-		runtime->hw.rate_max = 48000;
+	if (chip->spdif_on && viadev->reg_offset == 0x30) {
+		/* DXS#3 and spdif is on */
+		runtime->hw.rates = chip->ac97->rates[AC97_RATES_SPDIF];
+		snd_pcm_limit_hw_rates(runtime);
 	} else if (chip->dxs_fixed && viadev->reg_offset < 0x40) {
 		/* fixed DXS playback rate */
 		runtime->hw.rates = SNDRV_PCM_RATE_48000;
@@ -1091,30 +1075,13 @@
 	} else if (! ratep->rate) {
 		int idx = viadev->direction ? AC97_RATES_ADC : AC97_RATES_FRONT_DAC;
 		runtime->hw.rates = chip->ac97->rates[idx];
-		for (i = 0; i < (int)ARRAY_SIZE(ratebits); i++) {
-			if (runtime->hw.rates & ratebits[i].bit) {
-				runtime->hw.rate_min = ratebits[i].rate;
-				break;
-			}
-		}
-		for (i = ARRAY_SIZE(ratebits) - 1; i >= 0; i--) {
-			if (runtime->hw.rates & ratebits[i].bit) {
-				runtime->hw.rate_max = ratebits[i].rate;
-				break;
-			}
-		}
+		snd_pcm_limit_hw_rates(runtime);
 	} else {
 		/* a fixed rate */
 		runtime->hw.rates = SNDRV_PCM_RATE_KNOT;
-		for (i = 0; i < (int)ARRAY_SIZE(ratebits); i++) {
-			if (ratep->rate == ratebits[i].rate) {
-				runtime->hw.rates = ratebits[i].bit;
-				break;
-			}
-		}
 		runtime->hw.rate_max = runtime->hw.rate_min = ratep->rate;
 	}
-	spin_unlock_irqrestore(&ratep->lock, flags);
+	spin_unlock_irq(&ratep->lock);
 
 	/* we may remove following constaint when we modify table entries
 	   in interrupt */
@@ -1188,16 +1155,15 @@
 {
 	via82xx_t *chip = snd_pcm_substream_chip(substream);
 	viadev_t *viadev = (viadev_t *)substream->runtime->private_data;
-	unsigned long flags;
 	struct via_rate_lock *ratep;
 
 	/* release the rate lock */
 	ratep = &chip->rates[viadev->direction];
-	spin_lock_irqsave(&ratep->lock, flags);
+	spin_lock_irq(&ratep->lock);
 	ratep->used--;
 	if (! ratep->used)
 		ratep->rate = 0;
-	spin_unlock_irqrestore(&ratep->lock, flags);
+	spin_unlock_irq(&ratep->lock);
 
 	viadev->substream = NULL;
 	return 0;
@@ -1363,6 +1329,10 @@
 							 snd_dma_pci_data(chip->pci), 64*1024, 128*1024)) < 0)
 		return err;
 
+	/* SPDIF supported? */
+	if (! ac97_can_spdif(chip->ac97))
+		return 0;
+
 	/* PCM #1:  DXS3 playback (for spdif) */
 	err = snd_pcm_new(chip->card, chip->card->shortname, 1, 1, 0, &pcm);
 	if (err < 0)
@@ -1446,17 +1416,16 @@
 {
 	via82xx_t *chip = snd_kcontrol_chip(kcontrol);
 	unsigned long port = chip->port + (kcontrol->id.index ? (VIA_REG_CAPTURE_CHANNEL + 0x10) : VIA_REG_CAPTURE_CHANNEL);
-	unsigned long flags;
 	u8 val, oval;
 
-	spin_lock_irqsave(&chip->reg_lock, flags);
+	spin_lock_irq(&chip->reg_lock);
 	oval = inb(port);
 	val = oval & ~VIA_REG_CAPTURE_CHANNEL_MIC;
 	if (ucontrol->value.enumerated.item[0])
 		val |= VIA_REG_CAPTURE_CHANNEL_MIC;
 	if (val != oval)
 		outb(val, port);
-	spin_unlock_irqrestore(&chip->reg_lock, flags);
+	spin_unlock_irq(&chip->reg_lock);
 	return val != oval;
 }
 
@@ -1567,13 +1536,13 @@
 
 static void snd_via82xx_mixer_free_ac97_bus(ac97_bus_t *bus)
 {
-	via82xx_t *chip = snd_magic_cast(via82xx_t, bus->private_data, return);
+	via82xx_t *chip = bus->private_data;
 	chip->ac97_bus = NULL;
 }
 
 static void snd_via82xx_mixer_free_ac97(ac97_t *ac97)
 {
-	via82xx_t *chip = snd_magic_cast(via82xx_t, ac97->private_data, return);
+	via82xx_t *chip = ac97->private_data;
 	chip->ac97 = NULL;
 }
 
@@ -1585,6 +1554,18 @@
 		.type = AC97_TUNE_HP_ONLY
 	},
 	{
+		.vendor = 0x1019,
+		.device = 0x0a81,
+		.name = "ECS K7VTA3",
+		.type = AC97_TUNE_HP_ONLY
+	},
+	{
+		.vendor = 0x1019,
+		.device = 0x0a85,
+		.name = "ECS L7VMM2",
+		.type = AC97_TUNE_HP_ONLY
+	},
+	{
 		.vendor = 0x1849,
 		.device = 0x3059,
 		.name = "ASRock K7VM2",
@@ -1613,19 +1594,18 @@
 
 static int __devinit snd_via82xx_mixer_new(via82xx_t *chip, int ac97_quirk)
 {
-	ac97_bus_t bus;
-	ac97_t ac97;
+	ac97_template_t ac97;
 	int err;
+	static ac97_bus_ops_t ops = {
+		.write = snd_via82xx_codec_write,
+		.read = snd_via82xx_codec_read,
+		.wait = snd_via82xx_codec_wait,
+	};
 
-	memset(&bus, 0, sizeof(bus));
-	bus.write = snd_via82xx_codec_write;
-	bus.read = snd_via82xx_codec_read;
-	bus.wait = snd_via82xx_codec_wait;
-	bus.private_data = chip;
-	bus.private_free = snd_via82xx_mixer_free_ac97_bus;
-	bus.clock = chip->ac97_clock;
-	if ((err = snd_ac97_bus(chip->card, &bus, &chip->ac97_bus)) < 0)
+	if ((err = snd_ac97_bus(chip->card, 0, &ops, chip, &chip->ac97_bus)) < 0)
 		return err;
+	chip->ac97_bus->private_free = snd_via82xx_mixer_free_ac97_bus;
+	chip->ac97_bus->clock = chip->ac97_clock;
 
 	memset(&ac97, 0, sizeof(ac97));
 	ac97.private_data = chip;
@@ -1653,6 +1633,8 @@
 	int i, err, caps;
 	unsigned char val;
 
+	pci_write_config_byte(chip->pci, VIA_FUNC_ENABLE,
+			      chip->old_legacy & ~(VIA_FUNC_ENABLE_SB|VIA_FUNC_ENABLE_FM));
 	caps = chip->chip_type == TYPE_VIA8233A ? 1 : 2;
 	for (i = 0; i < caps; i++) {
 		snd_via8233_capture_source.index = i;
@@ -1660,9 +1642,11 @@
 		if (err < 0)
 			return err;
 	}
-	err = snd_ctl_add(chip->card, snd_ctl_new1(&snd_via8233_dxs3_spdif_control, chip));
-	if (err < 0)
-		return err;
+	if (ac97_can_spdif(chip->ac97)) {
+		err = snd_ctl_add(chip->card, snd_ctl_new1(&snd_via8233_dxs3_spdif_control, chip));
+		if (err < 0)
+			return err;
+	}
 	if (chip->chip_type != TYPE_VIA8233A) {
 		err = snd_ctl_add(chip->card, snd_ctl_new1(&snd_via8233_dxs_volume_control, chip));
 		if (err < 0)
@@ -1672,6 +1656,7 @@
 	/* select spdif data slot 10/11 */
 	pci_read_config_byte(chip->pci, VIA8233_SPDIF_CTRL, &val);
 	val = (val & ~VIA8233_SPDIF_SLOT_MASK) | VIA8233_SPDIF_SLOT_1011;
+	val &= ~VIA8233_SPDIF_DX3; /* SPDIF off as default */
 	pci_write_config_byte(chip->pci, VIA8233_SPDIF_CTRL, val);
 
 	return 0;
@@ -1686,6 +1671,7 @@
 	legacy_cfg = chip->old_legacy_cfg;
 	legacy |= VIA_FUNC_MIDI_IRQMASK;	/* FIXME: correct? (disable MIDI) */
 	legacy &= ~VIA_FUNC_ENABLE_GAME;	/* disable joystick */
+	legacy &= ~(VIA_FUNC_ENABLE_SB|VIA_FUNC_ENABLE_FM);	/* diable SB & FM */
 	if (chip->revision >= VIA_REV_686_H) {
 		rev_h = 1;
 		if (mpu_port[dev] >= 0x200) {	/* force MIDI */
@@ -1766,7 +1752,7 @@
  */
 static void snd_via82xx_proc_read(snd_info_entry_t *entry, snd_info_buffer_t *buffer)
 {
-	via82xx_t *chip = snd_magic_cast(via82xx_t, entry->private_data, return);
+	via82xx_t *chip = entry->private_data;
 	int i;
 	
 	snd_iprintf(buffer, "%s\n\n", chip->card->longname);
@@ -1903,7 +1889,7 @@
  */
 static int snd_via82xx_suspend(snd_card_t *card, unsigned int state)
 {
-	via82xx_t *chip = snd_magic_cast(via82xx_t, card->pm_private_data, return -EINVAL);
+	via82xx_t *chip = card->pm_private_data;
 	int i;
 
 	for (i = 0; i < 2; i++)
@@ -1921,7 +1907,6 @@
 		chip->capture_src_saved[1] = inb(chip->port + VIA_REG_CAPTURE_CHANNEL + 0x10);
 	}
 
-	pci_save_state(chip->pci, chip->pci_state);
 	pci_set_power_state(chip->pci, 3);
 	pci_disable_device(chip->pci);
 	snd_power_change_state(card, SNDRV_CTL_POWER_D3hot);
@@ -1930,11 +1915,10 @@
 
 static int snd_via82xx_resume(snd_card_t *card, unsigned int state)
 {
-	via82xx_t *chip = snd_magic_cast(via82xx_t, card->pm_private_data, return -EINVAL);
+	via82xx_t *chip = card->pm_private_data;
 	int idx, i;
 
 	pci_enable_device(chip->pci);
-	pci_restore_state(chip->pci, chip->pci_state);
 	pci_set_power_state(chip->pci, 0);
 
 	snd_via82xx_chip_init(chip);
@@ -1976,16 +1960,13 @@
 		snd_via82xx_channel_reset(chip, &chip->devs[i]);
 	synchronize_irq(chip->irq);
       __end_hw:
+	if (chip->irq >= 0)
+		free_irq(chip->irq, (void *)chip);
 	if (chip->mpu_res) {
 		release_resource(chip->mpu_res);
 		kfree_nocheck(chip->mpu_res);
 	}
-	if (chip->res_port) {
-		release_resource(chip->res_port);
-		kfree_nocheck(chip->res_port);
-	}
-	if (chip->irq >= 0)
-		free_irq(chip->irq, (void *)chip);
+	pci_release_regions(chip->pci);
 	if (chip->chip_type == TYPE_VIA686) {
 #ifdef SUPPORT_JOYSTICK
 		if (chip->res_joystick) {
@@ -1997,13 +1978,13 @@
 		pci_write_config_byte(chip->pci, VIA_FUNC_ENABLE, chip->old_legacy);
 		pci_write_config_byte(chip->pci, VIA_PNP_CONTROL, chip->old_legacy_cfg);
 	}
-	snd_magic_kfree(chip);
+	kfree(chip);
 	return 0;
 }
 
 static int snd_via82xx_dev_free(snd_device_t *device)
 {
-	via82xx_t *chip = snd_magic_cast(via82xx_t, device->device_data, return -ENXIO);
+	via82xx_t *chip = device->device_data;
 	return snd_via82xx_free(chip);
 }
 
@@ -2023,7 +2004,7 @@
 	if ((err = pci_enable_device(pci)) < 0)
 		return err;
 
-	if ((chip = snd_magic_kcalloc(via82xx_t, 0, GFP_KERNEL)) == NULL)
+	if ((chip = kcalloc(1, sizeof(*chip), GFP_KERNEL)) == NULL)
 		return -ENOMEM;
 
 	chip->chip_type = chip_type;
@@ -2037,19 +2018,14 @@
 	chip->pci = pci;
 	chip->irq = -1;
 
-	memset(&chip->dma_dev, 0, sizeof(chip->dma_dev));
-	chip->dma_dev.type = SNDRV_DMA_TYPE_DEV;
-	chip->dma_dev.dev = snd_dma_pci_data(pci);
-
 	pci_read_config_byte(pci, VIA_FUNC_ENABLE, &chip->old_legacy);
 	pci_read_config_byte(pci, VIA_PNP_CONTROL, &chip->old_legacy_cfg);
 
-	chip->port = pci_resource_start(pci, 0);
-	if ((chip->res_port = request_region(chip->port, 256, card->driver)) == NULL) {
-		snd_printk("unable to grab ports 0x%lx-0x%lx\n", chip->port, chip->port + 256 - 1);
-		snd_via82xx_free(chip);
-		return -EBUSY;
+	if ((err = pci_request_regions(pci, card->driver)) < 0) {
+		kfree(chip);
+		return err;
 	}
+	chip->port = pci_resource_start(pci, 0);
 	if (request_irq(pci->irq, snd_via82xx_interrupt, SA_INTERRUPT|SA_SHIRQ,
 			card->driver, (void *)chip)) {
 		snd_printk("unable to grab IRQ %d\n", pci->irq);
@@ -2111,9 +2087,12 @@
 		{ .vendor = 0x1005, .device = 0x4710, .action = VIA_DXS_ENABLE }, /* Avance Logic Mobo */
 		{ .vendor = 0x1019, .device = 0x0996, .action = VIA_DXS_48K },
 		{ .vendor = 0x1019, .device = 0x0a81, .action = VIA_DXS_NO_VRA }, /* ECS K7VTA3 v8.0 */
+		{ .vendor = 0x1019, .device = 0x0a85, .action = VIA_DXS_NO_VRA }, /* ECS L7VMM2 */
+		{ .vendor = 0x1025, .device = 0x0033, .action = VIA_DXS_NO_VRA }, /* Acer Inspire 1353LM */
 		{ .vendor = 0x1043, .device = 0x8095, .action = VIA_DXS_NO_VRA }, /* ASUS A7V8X (FIXME: possibly VIA_DXS_ENABLE?)*/
 		{ .vendor = 0x1043, .device = 0x80a1, .action = VIA_DXS_NO_VRA }, /* ASUS A7V8-X */
 		{ .vendor = 0x1043, .device = 0x80b0, .action = VIA_DXS_NO_VRA }, /* ASUS A7V600 & K8V*/ 
+		{ .vendor = 0x1071, .device = 0x8375, .action = VIA_DXS_NO_VRA }, /* Vobis/Yakumo/Mitac notebook */
 		{ .vendor = 0x10cf, .device = 0x118e, .action = VIA_DXS_ENABLE }, /* FSC laptop */
 		{ .vendor = 0x1106, .device = 0x4161, .action = VIA_DXS_NO_VRA }, /* ASRock K7VT2 */
 		{ .vendor = 0x1106, .device = 0xaa01, .action = VIA_DXS_NO_VRA }, /* EPIA MII */
@@ -2126,6 +2105,7 @@
 		{ .vendor = 0x1462, .device = 0x7120, .action = VIA_DXS_ENABLE }, /* MSI KT4V */
 		{ .vendor = 0x1462, .device = 0x5901, .action = VIA_DXS_NO_VRA }, /* MSI KT6 Delta-SR */
 		{ .vendor = 0x1584, .device = 0x8120, .action = VIA_DXS_ENABLE }, /* Gericom/Targa/Vobis/Uniwill laptop */
+		{ .vendor = 0x1584, .device = 0x8123, .action = VIA_DXS_NO_VRA }, /* Uniwill (Targa Visionary XP-210) */
 		{ .vendor = 0x161f, .device = 0x202b, .action = VIA_DXS_NO_VRA }, /* Amira Note book */
 		{ .vendor = 0x161f, .device = 0x2032, .action = VIA_DXS_48K }, /* m680x machines */
 		{ .vendor = 0x1631, .device = 0xe004, .action = VIA_DXS_ENABLE }, /* Easy Note 3174, Packard Bell */
diff -Nru a/sound/pci/vx222/vx222.c b/sound/pci/vx222/vx222.c
--- a/sound/pci/vx222/vx222.c	2004-10-18 14:56:32 -07:00
+++ b/sound/pci/vx222/vx222.c	2004-10-18 14:56:32 -07:00
@@ -28,15 +28,12 @@
 #include <sound/initval.h>
 #include "vx222.h"
 
-#define chip_t vx_core_t
-
 #define CARD_NAME "VX222"
 
 MODULE_AUTHOR("Takashi Iwai <tiwai@suse.de>");
 MODULE_DESCRIPTION("Digigram VX222 V2/Mic");
 MODULE_LICENSE("GPL");
-MODULE_CLASSES("{sound}");
-MODULE_DEVICES("{{Digigram," CARD_NAME "}}");
+MODULE_SUPPORTED_DEVICE("{{Digigram," CARD_NAME "}}");
 
 static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX;	/* Index 0-MAX */
 static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR;	/* ID for this card */
@@ -47,19 +44,14 @@
 
 module_param_array(index, int, boot_devs, 0444);
 MODULE_PARM_DESC(index, "Index value for Digigram " 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 Digigram " CARD_NAME " soundcard.");
-MODULE_PARM_SYNTAX(id, SNDRV_ID_DESC);
 module_param_array(enable, bool, boot_devs, 0444);
 MODULE_PARM_DESC(enable, "Enable Digigram " CARD_NAME " soundcard.");
-MODULE_PARM_SYNTAX(enable, SNDRV_ENABLE_DESC);
 module_param_array(mic, bool, boot_devs, 0444);
 MODULE_PARM_DESC(mic, "Enable Microphone.");
-MODULE_PARM_SYNTAX(mic, SNDRV_ENABLED "," SNDRV_BOOLEAN_FALSE_DESC);
 module_param_array(ibl, int, boot_devs, 0444);
 MODULE_PARM_DESC(ibl, "Capture IBL size.");
-MODULE_PARM_SYNTAX(ibl, SNDRV_ENABLED);
 
 /*
  */
@@ -119,24 +111,19 @@
  */
 static int snd_vx222_free(vx_core_t *chip)
 {
-	int i;
 	struct snd_vx222 *vx = (struct snd_vx222 *)chip;
 
 	if (chip->irq >= 0)
 		free_irq(chip->irq, (void*)chip);
-	for (i = 0; i < 2; i++) {
-		if (vx->port_res[i]) {
-			release_resource(vx->port_res[i]);
-			kfree_nocheck(vx->port_res[i]);
-		}
-	}
-	snd_magic_kfree(chip);
+	if (vx->port[0])
+		pci_release_regions(vx->pci);
+	kfree(chip);
 	return 0;
 }
 
 static int snd_vx222_dev_free(snd_device_t *device)
 {
-	vx_core_t *chip = snd_magic_cast(vx_core_t, device->device_data, return -ENXIO);
+	vx_core_t *chip = device->device_data;
 	return snd_vx222_free(chip);
 }
 
@@ -164,21 +151,14 @@
 	if (! chip)
 		return -ENOMEM;
 	vx = (struct snd_vx222 *)chip;
+	vx->pci = pci;
 
-	for (i = 0; i < 2; i++) {
-		if (!(pci_resource_flags(pci, i + 1) & IORESOURCE_IO)) {
-			snd_printk(KERN_ERR "invalid i/o resource %d\n", i + 1);
-			snd_vx222_free(chip);
-			return -ENOMEM;
-		}
-		vx->port[i] = pci_resource_start(pci, i + 1);
-		if ((vx->port_res[i] = request_region(vx->port[i], 0x60,
-						      CARD_NAME)) == NULL) {
-			snd_printk(KERN_ERR "unable to grab port 0x%lx\n", vx->port[i]);
-			snd_vx222_free(chip);
-			return -EBUSY;
-		}
+	if ((err = pci_request_regions(pci, CARD_NAME)) < 0) {
+		snd_vx222_free(chip);
+		return err;
 	}
+	for (i = 0; i < 2; i++)
+		vx->port[i] = pci_resource_start(pci, i + 1);
 
 	if (request_irq(pci->irq, snd_vx_irq_handler, SA_INTERRUPT|SA_SHIRQ,
 			CARD_NAME, (void *) chip)) {
diff -Nru a/sound/pci/vx222/vx222.h b/sound/pci/vx222/vx222.h
--- a/sound/pci/vx222/vx222.h	2004-10-18 14:57:04 -07:00
+++ b/sound/pci/vx222/vx222.h	2004-10-18 14:57:04 -07:00
@@ -28,8 +28,8 @@
 	vx_core_t core;
 
 	/* h/w config; for PLX and for DSP */
+	struct pci_dev *pci;
 	unsigned long port[2];
-	struct resource *port_res[2];
 
 	unsigned int regCDSP;	/* current CDSP register */
 	unsigned int regCFG;	/* current CFG register */
diff -Nru a/sound/pci/vx222/vx222_ops.c b/sound/pci/vx222/vx222_ops.c
--- a/sound/pci/vx222/vx222_ops.c	2004-10-18 14:55:53 -07:00
+++ b/sound/pci/vx222/vx222_ops.c	2004-10-18 14:55:53 -07:00
@@ -27,8 +27,6 @@
 #include <asm/io.h>
 #include "vx222.h"
 
-#define chip_t vx_core_t
-
 
 static int vx2_reg_offset[VX_REG_MAX] = {
 	[VX_ICR]    = 0x00,
diff -Nru a/sound/pci/ymfpci/ymfpci.c b/sound/pci/ymfpci/ymfpci.c
--- a/sound/pci/ymfpci/ymfpci.c	2004-10-18 14:56:29 -07:00
+++ b/sound/pci/ymfpci/ymfpci.c	2004-10-18 14:56:29 -07:00
@@ -33,8 +33,7 @@
 MODULE_AUTHOR("Jaroslav Kysela <perex@suse.cz>");
 MODULE_DESCRIPTION("Yamaha DS-XG PCI");
 MODULE_LICENSE("GPL");
-MODULE_CLASSES("{sound}");
-MODULE_DEVICES("{{Yamaha,YMF724},"
+MODULE_SUPPORTED_DEVICE("{{Yamaha,YMF724},"
 		"{Yamaha,YMF724F},"
 		"{Yamaha,YMF740},"
 		"{Yamaha,YMF740C},"
@@ -54,27 +53,20 @@
 
 module_param_array(index, int, boot_devs, 0444);
 MODULE_PARM_DESC(index, "Index value for the Yamaha DS-XG PCI soundcard.");
-MODULE_PARM_SYNTAX(index, SNDRV_INDEX_DESC);
 module_param_array(id, charp, boot_devs, 0444);
 MODULE_PARM_DESC(id, "ID string for the Yamaha DS-XG PCI soundcard.");
-MODULE_PARM_SYNTAX(id, SNDRV_ID_DESC);
 module_param_array(enable, bool, boot_devs, 0444);
 MODULE_PARM_DESC(enable, "Enable Yamaha DS-XG soundcard.");
-MODULE_PARM_SYNTAX(enable, SNDRV_ENABLE_DESC);
 module_param_array(mpu_port, long, boot_devs, 0444);
 MODULE_PARM_DESC(mpu_port, "MPU-401 Port.");
-MODULE_PARM_SYNTAX(mpu_port, SNDRV_ENABLED);
 module_param_array(fm_port, long, boot_devs, 0444);
 MODULE_PARM_DESC(fm_port, "FM OPL-3 Port.");
-MODULE_PARM_SYNTAX(fm_port, SNDRV_ENABLED);
 #ifdef SUPPORT_JOYSTICK
 module_param_array(joystick_port, long, boot_devs, 0444);
 MODULE_PARM_DESC(joystick_port, "Joystick port address");
-MODULE_PARM_SYNTAX(joystick_port, SNDRV_ENABLED);
 #endif
 module_param_array(rear_switch, bool, boot_devs, 0444);
 MODULE_PARM_DESC(rear_switch, "Enable shared rear/line-in switch");
-MODULE_PARM_SYNTAX(rear_switch, SNDRV_ENABLED "," SNDRV_BOOLEAN_FALSE_DESC);
 
 static struct pci_device_id snd_ymfpci_ids[] = {
         { 0x1073, 0x0004, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, },   /* YMF724 */
diff -Nru a/sound/pci/ymfpci/ymfpci_main.c b/sound/pci/ymfpci/ymfpci_main.c
--- a/sound/pci/ymfpci/ymfpci_main.c	2004-10-18 14:56:50 -07:00
+++ b/sound/pci/ymfpci/ymfpci_main.c	2004-10-18 14:56:50 -07:00
@@ -42,8 +42,6 @@
 
 #include <asm/io.h>
 
-#define chip_t ymfpci_t
-
 /*
  *  constants
  */
@@ -102,7 +100,7 @@
 
 static void snd_ymfpci_codec_write(ac97_t *ac97, u16 reg, u16 val)
 {
-	ymfpci_t *chip = snd_magic_cast(ymfpci_t, ac97->private_data, return);
+	ymfpci_t *chip = ac97->private_data;
 	u32 cmd;
 	
 	snd_ymfpci_codec_ready(chip, 0);
@@ -112,7 +110,7 @@
 
 static u16 snd_ymfpci_codec_read(ac97_t *ac97, u16 reg)
 {
-	ymfpci_t *chip = snd_magic_cast(ymfpci_t, ac97->private_data, return -ENXIO);
+	ymfpci_t *chip = ac97->private_data;
 
 	if (snd_ymfpci_codec_ready(chip, 0))
 		return ~0;
@@ -330,7 +328,7 @@
 static void snd_ymfpci_pcm_capture_interrupt(snd_pcm_substream_t *substream)
 {
 	snd_pcm_runtime_t *runtime = substream->runtime;
-	ymfpci_pcm_t *ypcm = snd_magic_cast(ymfpci_pcm_t, runtime->private_data, return);
+	ymfpci_pcm_t *ypcm = runtime->private_data;
 	ymfpci_t *chip = ypcm->chip;
 	u32 pos, delta;
 	
@@ -358,7 +356,7 @@
 				       int cmd)
 {
 	ymfpci_t *chip = snd_pcm_substream_chip(substream);
-	ymfpci_pcm_t *ypcm = snd_magic_cast(ymfpci_pcm_t, substream->runtime->private_data, return -ENXIO);
+	ymfpci_pcm_t *ypcm = substream->runtime->private_data;
 	int result = 0;
 
 	spin_lock(&chip->reg_lock);
@@ -395,7 +393,7 @@
 				      int cmd)
 {
 	ymfpci_t *chip = snd_pcm_substream_chip(substream);
-	ymfpci_pcm_t *ypcm = snd_magic_cast(ymfpci_pcm_t, substream->runtime->private_data, return -ENXIO);
+	ymfpci_pcm_t *ypcm = substream->runtime->private_data;
 	int result = 0;
 	u32 tmp;
 
@@ -541,7 +539,8 @@
 
 static int __devinit snd_ymfpci_ac3_init(ymfpci_t *chip)
 {
-	if (snd_dma_alloc_pages(&chip->dma_dev, 4096, &chip->ac3_tmp_base) < 0)
+	if (snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, snd_dma_pci_data(chip->pci),
+				4096, &chip->ac3_tmp_base) < 0)
 		return -ENOMEM;
 
 	chip->bank_effect[3][0]->base =
@@ -568,7 +567,7 @@
 	spin_unlock_irq(&chip->reg_lock);
 	// snd_ymfpci_irq_wait(chip);
 	if (chip->ac3_tmp_base.area) {
-		snd_dma_free_pages(&chip->dma_dev, &chip->ac3_tmp_base);
+		snd_dma_free_pages(&chip->ac3_tmp_base);
 		chip->ac3_tmp_base.area = NULL;
 	}
 	return 0;
@@ -578,7 +577,7 @@
 					 snd_pcm_hw_params_t * hw_params)
 {
 	snd_pcm_runtime_t *runtime = substream->runtime;
-	ymfpci_pcm_t *ypcm = snd_magic_cast(ymfpci_pcm_t, runtime->private_data, return -ENXIO);
+	ymfpci_pcm_t *ypcm = runtime->private_data;
 	int err;
 
 	if ((err = snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(hw_params))) < 0)
@@ -596,7 +595,7 @@
 	
 	if (runtime->private_data == NULL)
 		return 0;
-	ypcm = snd_magic_cast(ymfpci_pcm_t, runtime->private_data, return -ENXIO);
+	ypcm = runtime->private_data;
 
 	/* wait, until the PCI operations are not finished */
 	snd_ymfpci_irq_wait(chip);
@@ -616,7 +615,7 @@
 {
 	// ymfpci_t *chip = snd_pcm_substream_chip(substream);
 	snd_pcm_runtime_t *runtime = substream->runtime;
-	ymfpci_pcm_t *ypcm = snd_magic_cast(ymfpci_pcm_t, runtime->private_data, return -ENXIO);
+	ymfpci_pcm_t *ypcm = runtime->private_data;
 	unsigned int nvoice;
 
 	ypcm->period_size = runtime->period_size;
@@ -654,7 +653,7 @@
 {
 	ymfpci_t *chip = snd_pcm_substream_chip(substream);
 	snd_pcm_runtime_t *runtime = substream->runtime;
-	ymfpci_pcm_t *ypcm = snd_magic_cast(ymfpci_pcm_t, runtime->private_data, return -ENXIO);
+	ymfpci_pcm_t *ypcm = runtime->private_data;
 	snd_ymfpci_capture_bank_t * bank;
 	int nbank;
 	u32 rate, format;
@@ -698,7 +697,7 @@
 {
 	ymfpci_t *chip = snd_pcm_substream_chip(substream);
 	snd_pcm_runtime_t *runtime = substream->runtime;
-	ymfpci_pcm_t *ypcm = snd_magic_cast(ymfpci_pcm_t, runtime->private_data, return -ENXIO);
+	ymfpci_pcm_t *ypcm = runtime->private_data;
 	ymfpci_voice_t *voice = ypcm->voices[0];
 
 	if (!(ypcm->running && voice))
@@ -710,7 +709,7 @@
 {
 	ymfpci_t *chip = snd_pcm_substream_chip(substream);
 	snd_pcm_runtime_t *runtime = substream->runtime;
-	ymfpci_pcm_t *ypcm = snd_magic_cast(ymfpci_pcm_t, runtime->private_data, return -ENXIO);
+	ymfpci_pcm_t *ypcm = runtime->private_data;
 
 	if (!ypcm->running)
 		return 0;
@@ -736,7 +735,7 @@
 
 static irqreturn_t snd_ymfpci_interrupt(int irq, void *dev_id, struct pt_regs *regs)
 {
-	ymfpci_t *chip = snd_magic_cast(ymfpci_t, dev_id, return IRQ_NONE);
+	ymfpci_t *chip = dev_id;
 	u32 status, nvoice, mode;
 	ymfpci_voice_t *voice;
 
@@ -830,10 +829,10 @@
 
 static void snd_ymfpci_pcm_free_substream(snd_pcm_runtime_t *runtime)
 {
-	ymfpci_pcm_t *ypcm = snd_magic_cast(ymfpci_pcm_t, runtime->private_data, return);
+	ymfpci_pcm_t *ypcm = runtime->private_data;
 	
 	if (ypcm)
-		snd_magic_kfree(ypcm);
+		kfree(ypcm);
 }
 
 static int snd_ymfpci_playback_open_1(snd_pcm_substream_t * substream)
@@ -842,7 +841,7 @@
 	snd_pcm_runtime_t *runtime = substream->runtime;
 	ymfpci_pcm_t *ypcm;
 
-	ypcm = snd_magic_kcalloc(ymfpci_pcm_t, 0, GFP_KERNEL);
+	ypcm = kcalloc(1, sizeof(*ypcm), GFP_KERNEL);
 	if (ypcm == NULL)
 		return -ENOMEM;
 	ypcm->chip = chip;
@@ -886,20 +885,19 @@
 	ymfpci_t *chip = snd_pcm_substream_chip(substream);
 	snd_pcm_runtime_t *runtime = substream->runtime;
 	ymfpci_pcm_t *ypcm;
-	unsigned long flags;
 	int err;
 	
 	if ((err = snd_ymfpci_playback_open_1(substream)) < 0)
 		return err;
-	ypcm = snd_magic_cast(ymfpci_pcm_t, runtime->private_data, return 0);
+	ypcm = runtime->private_data;
 	ypcm->output_front = 1;
 	ypcm->output_rear = chip->mode_dup4ch ? 1 : 0;
-	spin_lock_irqsave(&chip->reg_lock, flags);
+	spin_lock_irq(&chip->reg_lock);
 	if (ypcm->output_rear) {
 		ymfpci_open_extension(chip);
 		chip->rear_opened++;
 	}
-	spin_unlock_irqrestore(&chip->reg_lock, flags);
+	spin_unlock_irq(&chip->reg_lock);
 	return 0;
 }
 
@@ -908,22 +906,21 @@
 	ymfpci_t *chip = snd_pcm_substream_chip(substream);
 	snd_pcm_runtime_t *runtime = substream->runtime;
 	ymfpci_pcm_t *ypcm;
-	unsigned long flags;
 	int err;
 	
 	if ((err = snd_ymfpci_playback_open_1(substream)) < 0)
 		return err;
-	ypcm = snd_magic_cast(ymfpci_pcm_t, runtime->private_data, return 0);
+	ypcm = runtime->private_data;
 	ypcm->output_front = 0;
 	ypcm->output_rear = 1;
-	spin_lock_irqsave(&chip->reg_lock, flags);
+	spin_lock_irq(&chip->reg_lock);
 	snd_ymfpci_writew(chip, YDSXGR_SPDIFOUTCTRL,
 			  snd_ymfpci_readw(chip, YDSXGR_SPDIFOUTCTRL) | 2);
 	ymfpci_open_extension(chip);
 	chip->spdif_pcm_bits = chip->spdif_bits;
 	snd_ymfpci_writew(chip, YDSXGR_SPDIFOUTSTATUS, chip->spdif_pcm_bits);
 	chip->spdif_opened++;
-	spin_unlock_irqrestore(&chip->reg_lock, flags);
+	spin_unlock_irq(&chip->reg_lock);
 
 	chip->spdif_pcm_ctl->vd[0].access &= ~SNDRV_CTL_ELEM_ACCESS_INACTIVE;
 	snd_ctl_notify(chip->card, SNDRV_CTL_EVENT_MASK_VALUE |
@@ -936,18 +933,17 @@
 	ymfpci_t *chip = snd_pcm_substream_chip(substream);
 	snd_pcm_runtime_t *runtime = substream->runtime;
 	ymfpci_pcm_t *ypcm;
-	unsigned long flags;
 	int err;
 	
 	if ((err = snd_ymfpci_playback_open_1(substream)) < 0)
 		return err;
-	ypcm = snd_magic_cast(ymfpci_pcm_t, runtime->private_data, return 0);
+	ypcm = runtime->private_data;
 	ypcm->output_front = 0;
 	ypcm->output_rear = 1;
-	spin_lock_irqsave(&chip->reg_lock, flags);
+	spin_lock_irq(&chip->reg_lock);
 	ymfpci_open_extension(chip);
 	chip->rear_opened++;
-	spin_unlock_irqrestore(&chip->reg_lock, flags);
+	spin_unlock_irq(&chip->reg_lock);
 	return 0;
 }
 
@@ -958,7 +954,7 @@
 	snd_pcm_runtime_t *runtime = substream->runtime;
 	ymfpci_pcm_t *ypcm;
 
-	ypcm = snd_magic_kcalloc(ymfpci_pcm_t, 0, GFP_KERNEL);
+	ypcm = kcalloc(1, sizeof(*ypcm), GFP_KERNEL);
 	if (ypcm == NULL)
 		return -ENOMEM;
 	ypcm->chip = chip;
@@ -993,30 +989,28 @@
 static int snd_ymfpci_playback_close(snd_pcm_substream_t * substream)
 {
 	ymfpci_t *chip = snd_pcm_substream_chip(substream);
-	ymfpci_pcm_t *ypcm = snd_magic_cast(ymfpci_pcm_t, substream->runtime->private_data, return -ENXIO);
-	unsigned long flags;
+	ymfpci_pcm_t *ypcm = substream->runtime->private_data;
 
-	spin_lock_irqsave(&chip->reg_lock, flags);
+	spin_lock_irq(&chip->reg_lock);
 	if (ypcm->output_rear && chip->rear_opened > 0) {
 		chip->rear_opened--;
 		ymfpci_close_extension(chip);
 	}
-	spin_unlock_irqrestore(&chip->reg_lock, flags);
+	spin_unlock_irq(&chip->reg_lock);
 	return snd_ymfpci_playback_close_1(substream);
 }
 
 static int snd_ymfpci_playback_spdif_close(snd_pcm_substream_t * substream)
 {
 	ymfpci_t *chip = snd_pcm_substream_chip(substream);
-	unsigned long flags;
 
-	spin_lock_irqsave(&chip->reg_lock, flags);
+	spin_lock_irq(&chip->reg_lock);
 	chip->spdif_opened = 0;
 	ymfpci_close_extension(chip);
 	snd_ymfpci_writew(chip, YDSXGR_SPDIFOUTCTRL,
 			  snd_ymfpci_readw(chip, YDSXGR_SPDIFOUTCTRL) & ~2);
 	snd_ymfpci_writew(chip, YDSXGR_SPDIFOUTSTATUS, chip->spdif_bits);
-	spin_unlock_irqrestore(&chip->reg_lock, flags);
+	spin_unlock_irq(&chip->reg_lock);
 	chip->spdif_pcm_ctl->vd[0].access |= SNDRV_CTL_ELEM_ACCESS_INACTIVE;
 	snd_ctl_notify(chip->card, SNDRV_CTL_EVENT_MASK_VALUE |
 		       SNDRV_CTL_EVENT_MASK_INFO, &chip->spdif_pcm_ctl->id);
@@ -1026,14 +1020,13 @@
 static int snd_ymfpci_playback_4ch_close(snd_pcm_substream_t * substream)
 {
 	ymfpci_t *chip = snd_pcm_substream_chip(substream);
-	unsigned long flags;
 
-	spin_lock_irqsave(&chip->reg_lock, flags);
+	spin_lock_irq(&chip->reg_lock);
 	if (chip->rear_opened > 0) {
 		chip->rear_opened--;
 		ymfpci_close_extension(chip);
 	}
-	spin_unlock_irqrestore(&chip->reg_lock, flags);
+	spin_unlock_irq(&chip->reg_lock);
 	return snd_ymfpci_playback_close_1(substream);
 }
 
@@ -1041,7 +1034,7 @@
 {
 	ymfpci_t *chip = snd_pcm_substream_chip(substream);
 	snd_pcm_runtime_t *runtime = substream->runtime;
-	ymfpci_pcm_t *ypcm = snd_magic_cast(ymfpci_pcm_t, runtime->private_data, return -ENXIO);
+	ymfpci_pcm_t *ypcm = runtime->private_data;
 
 	if (ypcm != NULL) {
 		chip->capture_substream[ypcm->capture_bank_number] = NULL;
@@ -1074,7 +1067,7 @@
 
 static void snd_ymfpci_pcm_free(snd_pcm_t *pcm)
 {
-	ymfpci_t *chip = snd_magic_cast(ymfpci_t, pcm->private_data, return);
+	ymfpci_t *chip = pcm->private_data;
 	chip->pcm = NULL;
 	snd_pcm_lib_preallocate_free_for_all(pcm);
 }
@@ -1120,7 +1113,7 @@
 
 static void snd_ymfpci_pcm2_free(snd_pcm_t *pcm)
 {
-	ymfpci_t *chip = snd_magic_cast(ymfpci_t, pcm->private_data, return);
+	ymfpci_t *chip = pcm->private_data;
 	chip->pcm2 = NULL;
 	snd_pcm_lib_preallocate_free_for_all(pcm);
 }
@@ -1166,7 +1159,7 @@
 
 static void snd_ymfpci_pcm_spdif_free(snd_pcm_t *pcm)
 {
-	ymfpci_t *chip = snd_magic_cast(ymfpci_t, pcm->private_data, return);
+	ymfpci_t *chip = pcm->private_data;
 	chip->pcm_spdif = NULL;
 	snd_pcm_lib_preallocate_free_for_all(pcm);
 }
@@ -1211,7 +1204,7 @@
 
 static void snd_ymfpci_pcm_4ch_free(snd_pcm_t *pcm)
 {
-	ymfpci_t *chip = snd_magic_cast(ymfpci_t, pcm->private_data, return);
+	ymfpci_t *chip = pcm->private_data;
 	chip->pcm_4ch = NULL;
 	snd_pcm_lib_preallocate_free_for_all(pcm);
 }
@@ -1254,12 +1247,11 @@
 					snd_ctl_elem_value_t * ucontrol)
 {
 	ymfpci_t *chip = snd_kcontrol_chip(kcontrol);
-	unsigned long flags;
 
-	spin_lock_irqsave(&chip->reg_lock, flags);
+	spin_lock_irq(&chip->reg_lock);
 	ucontrol->value.iec958.status[0] = (chip->spdif_bits >> 0) & 0xff;
 	ucontrol->value.iec958.status[1] = (chip->spdif_bits >> 8) & 0xff;
-	spin_unlock_irqrestore(&chip->reg_lock, flags);
+	spin_unlock_irq(&chip->reg_lock);
 	return 0;
 }
 
@@ -1267,18 +1259,17 @@
 					 snd_ctl_elem_value_t * ucontrol)
 {
 	ymfpci_t *chip = snd_kcontrol_chip(kcontrol);
-	unsigned long flags;
 	unsigned int val;
 	int change;
 
 	val = ((ucontrol->value.iec958.status[0] & 0x3e) << 0) |
 	      (ucontrol->value.iec958.status[1] << 8);
-	spin_lock_irqsave(&chip->reg_lock, flags);
+	spin_lock_irq(&chip->reg_lock);
 	change = chip->spdif_bits != val;
 	chip->spdif_bits = val;
 	if ((snd_ymfpci_readw(chip, YDSXGR_SPDIFOUTCTRL) & 1) && chip->pcm_spdif == NULL)
 		snd_ymfpci_writew(chip, YDSXGR_SPDIFOUTSTATUS, chip->spdif_bits);
-	spin_unlock_irqrestore(&chip->reg_lock, flags);
+	spin_unlock_irq(&chip->reg_lock);
 	return change;
 }
 
@@ -1302,12 +1293,11 @@
 				      snd_ctl_elem_value_t * ucontrol)
 {
 	ymfpci_t *chip = snd_kcontrol_chip(kcontrol);
-	unsigned long flags;
 
-	spin_lock_irqsave(&chip->reg_lock, flags);
+	spin_lock_irq(&chip->reg_lock);
 	ucontrol->value.iec958.status[0] = 0x3e;
 	ucontrol->value.iec958.status[1] = 0xff;
-	spin_unlock_irqrestore(&chip->reg_lock, flags);
+	spin_unlock_irq(&chip->reg_lock);
 	return 0;
 }
 
@@ -1331,12 +1321,11 @@
 					snd_ctl_elem_value_t * ucontrol)
 {
 	ymfpci_t *chip = snd_kcontrol_chip(kcontrol);
-	unsigned long flags;
 
-	spin_lock_irqsave(&chip->reg_lock, flags);
+	spin_lock_irq(&chip->reg_lock);
 	ucontrol->value.iec958.status[0] = (chip->spdif_pcm_bits >> 0) & 0xff;
 	ucontrol->value.iec958.status[1] = (chip->spdif_pcm_bits >> 8) & 0xff;
-	spin_unlock_irqrestore(&chip->reg_lock, flags);
+	spin_unlock_irq(&chip->reg_lock);
 	return 0;
 }
 
@@ -1344,18 +1333,17 @@
 					snd_ctl_elem_value_t * ucontrol)
 {
 	ymfpci_t *chip = snd_kcontrol_chip(kcontrol);
-	unsigned long flags;
 	unsigned int val;
 	int change;
 
 	val = ((ucontrol->value.iec958.status[0] & 0x3e) << 0) |
 	      (ucontrol->value.iec958.status[1] << 8);
-	spin_lock_irqsave(&chip->reg_lock, flags);
+	spin_lock_irq(&chip->reg_lock);
 	change = chip->spdif_pcm_bits != val;
 	chip->spdif_pcm_bits = val;
 	if ((snd_ymfpci_readw(chip, YDSXGR_SPDIFOUTCTRL) & 2))
 		snd_ymfpci_writew(chip, YDSXGR_SPDIFOUTSTATUS, chip->spdif_pcm_bits);
-	spin_unlock_irqrestore(&chip->reg_lock, flags);
+	spin_unlock_irq(&chip->reg_lock);
 	return change;
 }
 
@@ -1385,12 +1373,11 @@
 static int snd_ymfpci_drec_source_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *value)
 {
 	ymfpci_t *chip = snd_kcontrol_chip(kcontrol);
-	unsigned long flags;
 	u16 reg;
 
-	spin_lock_irqsave(&chip->reg_lock, flags);
+	spin_lock_irq(&chip->reg_lock);
 	reg = snd_ymfpci_readw(chip, YDSXGR_GLOBALCTRL);
-	spin_unlock_irqrestore(&chip->reg_lock, flags);
+	spin_unlock_irq(&chip->reg_lock);
 	if (!(reg & 0x100))
 		value->value.enumerated.item[0] = 0;
 	else
@@ -1401,17 +1388,16 @@
 static int snd_ymfpci_drec_source_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *value)
 {
 	ymfpci_t *chip = snd_kcontrol_chip(kcontrol);
-	unsigned long flags;
 	u16 reg, old_reg;
 
-	spin_lock_irqsave(&chip->reg_lock, flags);
+	spin_lock_irq(&chip->reg_lock);
 	old_reg = snd_ymfpci_readw(chip, YDSXGR_GLOBALCTRL);
 	if (value->value.enumerated.item[0] == 0)
 		reg = old_reg & ~0x100;
 	else
 		reg = (old_reg & ~0x300) | 0x100 | ((value->value.enumerated.item[0] == 2) << 9);
 	snd_ymfpci_writew(chip, YDSXGR_GLOBALCTRL, reg);
-	spin_unlock_irqrestore(&chip->reg_lock, flags);
+	spin_unlock_irq(&chip->reg_lock);
 	return reg != old_reg;
 }
 
@@ -1470,7 +1456,6 @@
 static int snd_ymfpci_put_single(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
 {
 	ymfpci_t *chip = snd_kcontrol_chip(kcontrol);
-	unsigned long flags;
 	int reg = kcontrol->private_value;
 	unsigned int shift = 0, mask = 1, invert = 0;
 	int change;
@@ -1485,12 +1470,12 @@
 	if (invert)
 		val = mask - val;
 	val <<= shift;
-	spin_lock_irqsave(&chip->reg_lock, flags);
+	spin_lock_irq(&chip->reg_lock);
 	oval = snd_ymfpci_readl(chip, reg);
 	val = (oval & ~(mask << shift)) | val;
 	change = val != oval;
 	snd_ymfpci_writel(chip, reg, val);
-	spin_unlock_irqrestore(&chip->reg_lock, flags);
+	spin_unlock_irq(&chip->reg_lock);
 	return change;
 }
 
@@ -1517,16 +1502,15 @@
 static int snd_ymfpci_get_double(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
 {
 	ymfpci_t *chip = snd_kcontrol_chip(kcontrol);
-	unsigned long flags;
 	unsigned int reg = kcontrol->private_value;
 	unsigned int shift_left = 0, shift_right = 16, mask = 16383, invert = 0;
 	unsigned int val;
 	
 	if (reg < 0x80 || reg >= 0xc0)
 		return -EINVAL;
-	spin_lock_irqsave(&chip->reg_lock, flags);
+	spin_lock_irq(&chip->reg_lock);
 	val = snd_ymfpci_readl(chip, reg);
-	spin_unlock_irqrestore(&chip->reg_lock, flags);
+	spin_unlock_irq(&chip->reg_lock);
 	ucontrol->value.integer.value[0] = (val >> shift_left) & mask;
 	ucontrol->value.integer.value[1] = (val >> shift_right) & mask;
 	if (invert) {
@@ -1539,7 +1523,6 @@
 static int snd_ymfpci_put_double(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
 {
 	ymfpci_t *chip = snd_kcontrol_chip(kcontrol);
-	unsigned long flags;
 	unsigned int reg = kcontrol->private_value;
 	unsigned int shift_left = 0, shift_right = 16, mask = 16383, invert = 0;
 	int change;
@@ -1555,12 +1538,12 @@
 	}
 	val1 <<= shift_left;
 	val2 <<= shift_right;
-	spin_lock_irqsave(&chip->reg_lock, flags);
+	spin_lock_irq(&chip->reg_lock);
 	oval = snd_ymfpci_readl(chip, reg);
 	val1 = (oval & ~((mask << shift_left) | (mask << shift_right))) | val1 | val2;
 	change = val1 != oval;
 	snd_ymfpci_writel(chip, reg, val1);
-	spin_unlock_irqrestore(&chip->reg_lock, flags);
+	spin_unlock_irq(&chip->reg_lock);
 	return change;
 }
 
@@ -1594,8 +1577,6 @@
 }
 
 
-#define YMFPCI_CONTROLS (sizeof(snd_ymfpci_controls)/sizeof(snd_kcontrol_new_t))
-
 static snd_kcontrol_new_t snd_ymfpci_controls[] __devinitdata = {
 YMFPCI_DOUBLE("Wave Playback Volume", 0, YDSXGR_NATIVEDACOUTVOL),
 YMFPCI_DOUBLE("Wave Capture Volume", 0, YDSXGR_NATIVEDACLOOPVOL),
@@ -1709,31 +1690,30 @@
 
 static void snd_ymfpci_mixer_free_ac97_bus(ac97_bus_t *bus)
 {
-	ymfpci_t *chip = snd_magic_cast(ymfpci_t, bus->private_data, return);
+	ymfpci_t *chip = bus->private_data;
 	chip->ac97_bus = NULL;
 }
 
 static void snd_ymfpci_mixer_free_ac97(ac97_t *ac97)
 {
-	ymfpci_t *chip = snd_magic_cast(ymfpci_t, ac97->private_data, return);
+	ymfpci_t *chip = ac97->private_data;
 	chip->ac97 = NULL;
 }
 
 int __devinit snd_ymfpci_mixer(ymfpci_t *chip, int rear_switch)
 {
-	ac97_bus_t bus;
-	ac97_t ac97;
+	ac97_template_t ac97;
 	snd_kcontrol_t *kctl;
 	unsigned int idx;
 	int err;
+	static ac97_bus_ops_t ops = {
+		.write = snd_ymfpci_codec_write,
+		.read = snd_ymfpci_codec_read,
+	};
 
-	memset(&bus, 0, sizeof(bus));
-	bus.write = snd_ymfpci_codec_write;
-	bus.read = snd_ymfpci_codec_read;
-	bus.private_data = chip;
-	bus.private_free = snd_ymfpci_mixer_free_ac97_bus;
-	if ((err = snd_ac97_bus(chip->card, &bus, &chip->ac97_bus)) < 0)
+	if ((err = snd_ac97_bus(chip->card, 0, &ops, chip, &chip->ac97_bus)) < 0)
 		return err;
+	chip->ac97_bus->private_free = snd_ymfpci_mixer_free_ac97_bus;
 
 	memset(&ac97, 0, sizeof(ac97));
 	ac97.private_data = chip;
@@ -1741,7 +1721,7 @@
 	if ((err = snd_ac97_mixer(chip->ac97_bus, &ac97, &chip->ac97)) < 0)
 		return err;
 
-	for (idx = 0; idx < YMFPCI_CONTROLS; idx++) {
+	for (idx = 0; idx < ARRAY_SIZE(snd_ymfpci_controls); idx++) {
 		if ((err = snd_ctl_add(chip->card, snd_ctl_new1(&snd_ymfpci_controls[idx], chip))) < 0)
 			return err;
 	}
@@ -1854,7 +1834,7 @@
 static void snd_ymfpci_proc_read(snd_info_entry_t *entry, 
 				 snd_info_buffer_t * buffer)
 {
-	ymfpci_t *chip = snd_magic_cast(ymfpci_t, entry->private_data, return);
+	ymfpci_t *chip = entry->private_data;
 	int i;
 	
 	snd_iprintf(buffer, "YMFPCI\n\n");
@@ -1975,7 +1955,8 @@
 	       chip->work_size;
 	/* work_ptr must be aligned to 256 bytes, but it's already
 	   covered with the kernel page allocation mechanism */
-	if (snd_dma_alloc_pages(&chip->dma_dev, size, &chip->work_ptr) < 0) 
+	if (snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, snd_dma_pci_data(chip->pci),
+				size, &chip->work_ptr) < 0) 
 		return -ENOMEM;
 	ptr = chip->work_ptr.area;
 	ptr_addr = chip->work_ptr.addr;
@@ -2106,7 +2087,7 @@
 	if (chip->reg_area_virt)
 		iounmap((void *)chip->reg_area_virt);
 	if (chip->work_ptr.area)
-		snd_dma_free_pages(&chip->dma_dev, &chip->work_ptr);
+		snd_dma_free_pages(&chip->work_ptr);
 	
 	if (chip->irq >= 0)
 		free_irq(chip->irq, (void *)chip);
@@ -2117,13 +2098,13 @@
 
 	pci_write_config_word(chip->pci, 0x40, chip->old_legacy_ctrl);
 	
-	snd_magic_kfree(chip);
+	kfree(chip);
 	return 0;
 }
 
 static int snd_ymfpci_dev_free(snd_device_t *device)
 {
-	ymfpci_t *chip = snd_magic_cast(ymfpci_t, device->device_data, return -ENXIO);
+	ymfpci_t *chip = device->device_data;
 	return snd_ymfpci_free(chip);
 }
 
@@ -2159,7 +2140,7 @@
 
 static int snd_ymfpci_suspend(snd_card_t *card, unsigned int state)
 {
-	ymfpci_t *chip = snd_magic_cast(ymfpci_t, card->pm_private_data, return -EINVAL);
+	ymfpci_t *chip = card->pm_private_data;
 	unsigned int i;
 	
 	snd_pcm_suspend_all(chip->pcm);
@@ -2178,7 +2159,7 @@
 
 static int snd_ymfpci_resume(snd_card_t *card, unsigned int state)
 {
-	ymfpci_t *chip = snd_magic_cast(ymfpci_t, card->pm_private_data, return -EINVAL);
+	ymfpci_t *chip = card->pm_private_data;
 	unsigned int i;
 
 	pci_enable_device(chip->pci);
@@ -2195,11 +2176,10 @@
 
 	/* start hw again */
 	if (chip->start_count > 0) {
-		unsigned long flags;
-		spin_lock_irqsave(&chip->reg_lock, flags);
+		spin_lock_irq(&chip->reg_lock);
 		snd_ymfpci_writel(chip, YDSXGR_MODE, chip->saved_ydsxgr_mode);
 		chip->active_bank = snd_ymfpci_readl(chip, YDSXGR_CTRLSELECT);
-		spin_unlock_irqrestore(&chip->reg_lock, flags);
+		spin_unlock_irq(&chip->reg_lock);
 	}
 	snd_power_change_state(card, SNDRV_CTL_POWER_D0);
 	return 0;
@@ -2223,7 +2203,7 @@
 	if ((err = pci_enable_device(pci)) < 0)
 		return err;
 
-	chip = snd_magic_kcalloc(ymfpci_t, 0, GFP_KERNEL);
+	chip = kcalloc(1, sizeof(*chip), GFP_KERNEL);
 	if (chip == NULL)
 		return -ENOMEM;
 	chip->old_legacy_ctrl = old_legacy_ctrl;
@@ -2251,10 +2231,6 @@
 		return -EBUSY;
 	}
 	chip->irq = pci->irq;
-
-	memset(&chip->dma_dev, 0, sizeof(chip->dma_dev));
-	chip->dma_dev.type = SNDRV_DMA_TYPE_DEV;
-	chip->dma_dev.dev = snd_dma_pci_data(pci);
 
 	snd_ymfpci_aclink_reset(pci);
 	if (snd_ymfpci_codec_ready(chip, 0) < 0) {
diff -Nru a/sound/pcmcia/pdaudiocf/pdaudiocf.c b/sound/pcmcia/pdaudiocf/pdaudiocf.c
--- a/sound/pcmcia/pdaudiocf/pdaudiocf.c	2004-10-18 14:56:27 -07:00
+++ b/sound/pcmcia/pdaudiocf/pdaudiocf.c	2004-10-18 14:56:27 -07:00
@@ -37,8 +37,7 @@
 MODULE_AUTHOR("Jaroslav Kysela <perex@suse.cz>");
 MODULE_DESCRIPTION("Sound Core " CARD_NAME);
 MODULE_LICENSE("GPL");
-MODULE_CLASSES("{sound}");
-MODULE_DEVICES("{{Sound Core," CARD_NAME "}}");
+MODULE_SUPPORTED_DEVICE("{{Sound Core," CARD_NAME "}}");
 
 static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX;	/* Index 0-MAX */
 static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR;	/* ID for this card */
@@ -49,13 +48,10 @@
 
 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);
 module_param(irq_mask, int, 0444);
 MODULE_PARM_DESC(irq_mask, "IRQ bitmask for " CARD_NAME " soundcard.");
 module_param_array(irq_list, int, boot_devs, 0444);
@@ -103,13 +99,13 @@
 	card_list[pdacf->index] = NULL;
 	pdacf->card = NULL;
 
-	snd_magic_kfree(pdacf);
+	kfree(pdacf);
 	return 0;
 }
 
 static int snd_pdacf_dev_free(snd_device_t *device)
 {
-	pdacf_t *chip = snd_magic_cast(pdacf_t, device->device_data, return -ENXIO);
+	pdacf_t *chip = device->device_data;
 	return snd_pdacf_free(chip);
 }
 
@@ -152,7 +148,7 @@
 		return NULL;
 
 	if (snd_device_new(card, SNDRV_DEV_LOWLEVEL, pdacf, &ops) < 0) {
-		snd_magic_kfree(pdacf);
+		kfree(pdacf);
 		snd_card_free(card);
 		return NULL;
 	}
@@ -258,7 +254,7 @@
  */
 static void snd_pdacf_detach(dev_link_t *link)
 {
-	pdacf_t *chip = snd_magic_cast(pdacf_t, link->priv, return);
+	pdacf_t *chip = link->priv;
 
 	snd_printdd(KERN_DEBUG "pdacf_detach called\n");
 	/* Remove the interface data from the linked list */
@@ -297,7 +293,7 @@
 static void pdacf_config(dev_link_t *link)
 {
 	client_handle_t handle = link->handle;
-	pdacf_t *pdacf = snd_magic_cast(pdacf_t, link->priv, return);
+	pdacf_t *pdacf = link->priv;
 	tuple_t tuple;
 	cisparse_t parse;
 	config_info_t conf;
diff -Nru a/sound/pcmcia/pdaudiocf/pdaudiocf_core.c b/sound/pcmcia/pdaudiocf/pdaudiocf_core.c
--- a/sound/pcmcia/pdaudiocf/pdaudiocf_core.c	2004-10-18 14:56:27 -07:00
+++ b/sound/pcmcia/pdaudiocf/pdaudiocf_core.c	2004-10-18 14:56:27 -07:00
@@ -30,7 +30,7 @@
  */
 unsigned char pdacf_ak4117_read(void *private_data, unsigned char reg)
 {
-	pdacf_t *chip = snd_magic_cast(pdacf_t, private_data, return 0);
+	pdacf_t *chip = private_data;
 	unsigned long timeout;
 	unsigned long flags;
 	unsigned char res;
@@ -62,7 +62,7 @@
 
 void pdacf_ak4117_write(void *private_data, unsigned char reg, unsigned char val)
 {
-	pdacf_t *chip = snd_magic_cast(pdacf_t, private_data, return);
+	pdacf_t *chip = private_data;
 	unsigned long timeout;
 	unsigned long flags;
 
@@ -130,7 +130,7 @@
 static void pdacf_proc_read(snd_info_entry_t * entry,
                             snd_info_buffer_t * buffer)
 {
-	pdacf_t *chip = snd_magic_cast(pdacf_t, entry->private_data, return);
+	pdacf_t *chip = entry->private_data;
 	u16 tmp;
 
 	snd_iprintf(buffer, "PDAudioCF\n\n");
@@ -151,7 +151,7 @@
 {
 	pdacf_t *chip;
 
-	chip = snd_magic_kcalloc(pdacf_t, 0, GFP_KERNEL);
+	chip = kcalloc(1, sizeof(*chip), GFP_KERNEL);
 	if (chip == NULL)
 		return NULL;
 	chip->card = card;
@@ -257,7 +257,7 @@
 
 int snd_pdacf_suspend(snd_card_t *card, unsigned int state)
 {
-	pdacf_t *chip = snd_magic_cast(pdacf_t, card->pm_private_data, return -EINVAL);
+	pdacf_t *chip = card->pm_private_data;
 	u16 val;
 	
 	snd_pcm_suspend_all(chip->pcm);
@@ -278,7 +278,7 @@
 
 int snd_pdacf_resume(snd_card_t *card, unsigned int state)
 {
-	pdacf_t *chip = snd_magic_cast(pdacf_t, card->pm_private_data, return -EINVAL);
+	pdacf_t *chip = card->pm_private_data;
 	int timeout = 40;
 
 	pdacf_reinit(chip, 1);
diff -Nru a/sound/pcmcia/pdaudiocf/pdaudiocf_irq.c b/sound/pcmcia/pdaudiocf/pdaudiocf_irq.c
--- a/sound/pcmcia/pdaudiocf/pdaudiocf_irq.c	2004-10-18 14:56:33 -07:00
+++ b/sound/pcmcia/pdaudiocf/pdaudiocf_irq.c	2004-10-18 14:56:33 -07:00
@@ -28,7 +28,7 @@
  */
 irqreturn_t pdacf_interrupt(int irq, void *dev, struct pt_regs *regs)
 {
-	pdacf_t *chip = snd_magic_cast(pdacf_t, dev, return IRQ_NONE);
+	pdacf_t *chip = dev;
 	unsigned short stat;
 
 	if ((chip->chip_status & (PDAUDIOCF_STAT_IS_STALE|
@@ -258,7 +258,7 @@
 
 void pdacf_tasklet(unsigned long private_data)
 {
-	pdacf_t *chip = snd_magic_cast(pdacf_t, (void *)private_data, return);
+	pdacf_t *chip = (pdacf_t *) private_data;
 	int size, off, cont, rdp, wdp;
 
 	if ((chip->chip_status & (PDAUDIOCF_STAT_IS_STALE|PDAUDIOCF_STAT_IS_CONFIGURED)) != PDAUDIOCF_STAT_IS_CONFIGURED)
diff -Nru a/sound/pcmcia/pdaudiocf/pdaudiocf_pcm.c b/sound/pcmcia/pdaudiocf/pdaudiocf_pcm.c
--- a/sound/pcmcia/pdaudiocf/pdaudiocf_pcm.c	2004-10-18 14:56:32 -07:00
+++ b/sound/pcmcia/pdaudiocf/pdaudiocf_pcm.c	2004-10-18 14:56:32 -07:00
@@ -28,8 +28,6 @@
 #include <sound/asoundef.h>
 #include "pdaudiocf.h"
 
-#define chip_t	pdacf_t
-
 
 /*
  * we use a vmalloc'ed (sg-)buffer
@@ -331,7 +329,7 @@
  */
 static void snd_pdacf_pcm_free(snd_pcm_t *pcm)
 {
-	pdacf_t *chip = snd_magic_cast(pdacf_t, pcm->private_data, return);
+	pdacf_t *chip = pcm->private_data;
 	chip->pcm = NULL;
 }
 
diff -Nru a/sound/pcmcia/vx/vx_entry.c b/sound/pcmcia/vx/vx_entry.c
--- a/sound/pcmcia/vx/vx_entry.c	2004-10-18 14:55:54 -07:00
+++ b/sound/pcmcia/vx/vx_entry.c	2004-10-18 14:55:54 -07:00
@@ -69,13 +69,13 @@
 		hw->card_list[vxp->index] = NULL;
 	chip->card = NULL;
 
-	snd_magic_kfree(chip);
+	kfree(chip);
 	return 0;
 }
 
 static int snd_vxpocket_dev_free(snd_device_t *device)
 {
-	vx_core_t *chip = snd_magic_cast(vx_core_t, device->device_data, return -ENXIO);
+	vx_core_t *chip = device->device_data;
 	return snd_vxpocket_free(chip);
 }
 
@@ -121,7 +121,7 @@
 		return NULL;
 
 	if (snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops) < 0) {
-		snd_magic_kfree(chip);
+		kfree(chip);
 		snd_card_free(card);
 		return NULL;
 	}
@@ -226,7 +226,7 @@
  */
 void snd_vxpocket_detach(struct snd_vxp_entry *hw, dev_link_t *link)
 {
-	vx_core_t *chip = snd_magic_cast(vx_core_t, link->priv, return);
+	vx_core_t *chip = link->priv;
 
 	snd_printdd(KERN_DEBUG "vxpocket_detach called\n");
 	/* Remove the interface data from the linked list */
@@ -263,7 +263,7 @@
 static void vxpocket_config(dev_link_t *link)
 {
 	client_handle_t handle = link->handle;
-	vx_core_t *chip = snd_magic_cast(vx_core_t, link->priv, return);
+	vx_core_t *chip = link->priv;
 	struct snd_vxpocket *vxp = (struct snd_vxpocket *)chip;
 	tuple_t tuple;
 	cisparse_t parse;
diff -Nru a/sound/pcmcia/vx/vxp_mixer.c b/sound/pcmcia/vx/vxp_mixer.c
--- a/sound/pcmcia/vx/vxp_mixer.c	2004-10-18 14:55:54 -07:00
+++ b/sound/pcmcia/vx/vxp_mixer.c	2004-10-18 14:55:54 -07:00
@@ -25,8 +25,6 @@
 #include <sound/control.h>
 #include "vxpocket.h"
 
-#define chip_t vx_core_t
-
 #define MIC_LEVEL_MIN	0
 #define MIC_LEVEL_MAX	8
 
diff -Nru a/sound/pcmcia/vx/vxp_ops.c b/sound/pcmcia/vx/vxp_ops.c
--- a/sound/pcmcia/vx/vxp_ops.c	2004-10-18 14:56:20 -07:00
+++ b/sound/pcmcia/vx/vxp_ops.c	2004-10-18 14:56:20 -07:00
@@ -26,8 +26,6 @@
 #include <asm/io.h>
 #include "vxpocket.h"
 
-#define chip_t vx_core_t
-
 
 static int vxp_reg_offset[VX_REG_MAX] = {
 	[VX_ICR]	= 0x00,		// ICR
diff -Nru a/sound/pcmcia/vx/vxpocket.c b/sound/pcmcia/vx/vxpocket.c
--- a/sound/pcmcia/vx/vxpocket.c	2004-10-18 14:56:17 -07:00
+++ b/sound/pcmcia/vx/vxpocket.c	2004-10-18 14:56:17 -07:00
@@ -50,8 +50,7 @@
 MODULE_AUTHOR("Takashi Iwai <tiwai@suse.de>");
 MODULE_DESCRIPTION("Digigram " CARD_NAME);
 MODULE_LICENSE("GPL");
-MODULE_CLASSES("{sound}");
-MODULE_DEVICES("{{Digigram," CARD_NAME "}}");
+MODULE_SUPPORTED_DEVICE("{{Digigram," CARD_NAME "}}");
 
 static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX;	/* Index 0-MAX */
 static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR;	/* ID for this card */
@@ -63,20 +62,16 @@
 
 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);
 module_param(irq_mask, int, 0444);
 MODULE_PARM_DESC(irq_mask, "IRQ bitmask for " CARD_NAME " soundcard.");
 module_param_array(irq_list, int, boot_devs, 0444);
 MODULE_PARM_DESC(irq_list, "List of Available interrupts for " CARD_NAME " soundcard.");
 module_param_array(ibl, int, boot_devs, 0444);
 MODULE_PARM_DESC(ibl, "Capture IBL size for " CARD_NAME " soundcard.");
-MODULE_PARM_SYNTAX(ibl, SNDRV_ENABLED);
  
 
 /*
diff -Nru a/sound/ppc/Kconfig b/sound/ppc/Kconfig
--- a/sound/ppc/Kconfig	2004-10-18 14:56:29 -07:00
+++ b/sound/ppc/Kconfig	2004-10-18 14:56:29 -07:00
@@ -6,9 +6,12 @@
 comment "ALSA PowerMac requires I2C"
 	depends on SND && I2C=n
 
+comment "ALSA PowerMac requires INPUT"
+	depends on SND && INPUT=n
+
 config SND_POWERMAC
 	tristate "PowerMac (AWACS, DACA, Burgundy, Tumbler, Keywest)"
-	depends on SND && I2C
+	depends on SND && I2C && INPUT
 	select SND_PCM
 
 endmenu
diff -Nru a/sound/ppc/Makefile b/sound/ppc/Makefile
--- a/sound/ppc/Makefile	2004-10-18 14:56:29 -07:00
+++ b/sound/ppc/Makefile	2004-10-18 14:56:29 -07:00
@@ -3,7 +3,7 @@
 # Copyright (c) 2001 by Jaroslav Kysela <perex@suse.cz>
 #
 
-snd-powermac-objs := powermac.o pmac.o awacs.o burgundy.o daca.o tumbler.o keywest.o
+snd-powermac-objs := powermac.o pmac.o awacs.o burgundy.o daca.o tumbler.o keywest.o beep.o
 
 # Toplevel Module Dependency
 obj-$(CONFIG_SND_POWERMAC) += snd-powermac.o
diff -Nru a/sound/ppc/awacs.c b/sound/ppc/awacs.c
--- a/sound/ppc/awacs.c	2004-10-18 14:56:32 -07:00
+++ b/sound/ppc/awacs.c	2004-10-18 14:56:32 -07:00
@@ -29,8 +29,6 @@
 #include <sound/core.h>
 #include "pmac.h"
 
-#define chip_t pmac_t
-
 
 #ifdef CONFIG_ADB_CUDA
 #define PMAC_AMP_AVAIL
@@ -574,11 +572,22 @@
 	AWACS_VOLUME("Master Playback Volume", 2, 6, 1),
 	AWACS_SWITCH("Master Capture Switch", 1, SHIFT_LOOPTHRU, 0),
 	AWACS_VOLUME("Capture Volume", 0, 4, 0),
-	AWACS_SWITCH("Line Capture Switch", 0, SHIFT_MUX_LINE, 0),
 	AWACS_SWITCH("CD Capture Switch", 0, SHIFT_MUX_CD, 0),
+};
+
+/* FIXME: is this correct order?
+ * screamer (powerbook G3 pismo) seems to have different bits...
+ */
+static snd_kcontrol_new_t snd_pmac_awacs_mixers2[] __initdata = {
+	AWACS_SWITCH("Line Capture Switch", 0, SHIFT_MUX_LINE, 0),
 	AWACS_SWITCH("Mic Capture Switch", 0, SHIFT_MUX_MIC, 0),
 };
 
+static snd_kcontrol_new_t snd_pmac_screamer_mixers2[] __initdata = {
+	AWACS_SWITCH("Line Capture Switch", 0, SHIFT_MUX_MIC, 0),
+	AWACS_SWITCH("Mic Capture Switch", 0, SHIFT_MUX_LINE, 0),
+};
+
 static snd_kcontrol_new_t snd_pmac_awacs_master_sw __initdata =
 AWACS_SWITCH("Master Playback Switch", 1, SHIFT_HDMUTE, 1);
 
@@ -602,8 +611,6 @@
 AWACS_SWITCH("PC Speaker Playback Switch", 1, SHIFT_SPKMUTE, 1);
 
 
-#define num_controls(ary) (sizeof(ary) / sizeof(snd_kcontrol_new_t))
-
 /*
  * add new mixer elements to the card
  */
@@ -818,9 +825,17 @@
 	 */
 	strcpy(chip->card->mixername, "PowerMac AWACS");
 
-	if ((err = build_mixers(chip, num_controls(snd_pmac_awacs_mixers),
+	if ((err = build_mixers(chip, ARRAY_SIZE(snd_pmac_awacs_mixers),
 				snd_pmac_awacs_mixers)) < 0)
 		return err;
+	if (chip->model == PMAC_SCREAMER)
+		err = build_mixers(chip, ARRAY_SIZE(snd_pmac_screamer_mixers2),
+				   snd_pmac_screamer_mixers2);
+	else
+		err = build_mixers(chip, ARRAY_SIZE(snd_pmac_awacs_mixers2),
+				   snd_pmac_awacs_mixers2);
+	if (err < 0)
+		return err;
 	chip->master_sw_ctl = snd_ctl_new1(&snd_pmac_awacs_master_sw, chip);
 	if ((err = snd_ctl_add(chip->card, chip->master_sw_ctl)) < 0)
 		return err;
@@ -832,7 +847,7 @@
 		 * screamer registers.
 		 * in this case, it seems the route C is not used.
 		 */
-		if ((err = build_mixers(chip, num_controls(snd_pmac_awacs_amp_vol),
+		if ((err = build_mixers(chip, ARRAY_SIZE(snd_pmac_awacs_amp_vol),
 					snd_pmac_awacs_amp_vol)) < 0)
 			return err;
 		/* overwrite */
@@ -846,7 +861,7 @@
 #endif /* PMAC_AMP_AVAIL */
 	{
 		/* route A = headphone, route C = speaker */
-		if ((err = build_mixers(chip, num_controls(snd_pmac_awacs_speaker_vol),
+		if ((err = build_mixers(chip, ARRAY_SIZE(snd_pmac_awacs_speaker_vol),
 					snd_pmac_awacs_speaker_vol)) < 0)
 			return err;
 		chip->speaker_sw_ctl = snd_ctl_new1(&snd_pmac_awacs_speaker_sw, chip);
@@ -855,11 +870,11 @@
 	}
 
 	if (chip->model == PMAC_SCREAMER) {
-		if ((err = build_mixers(chip, num_controls(snd_pmac_screamer_mic_boost),
+		if ((err = build_mixers(chip, ARRAY_SIZE(snd_pmac_screamer_mic_boost),
 					snd_pmac_screamer_mic_boost)) < 0)
 			return err;
 	} else {
-		if ((err = build_mixers(chip, num_controls(snd_pmac_awacs_mic_boost),
+		if ((err = build_mixers(chip, ARRAY_SIZE(snd_pmac_awacs_mic_boost),
 					snd_pmac_awacs_mic_boost)) < 0)
 			return err;
 	}
diff -Nru a/sound/ppc/beep.c b/sound/ppc/beep.c
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/sound/ppc/beep.c	2004-10-18 14:57:23 -07:00
@@ -0,0 +1,262 @@
+/*
+ * Beep using pcm
+ *
+ * Copyright (c) by Takashi Iwai <tiwai@suse.de>
+ *
+ *   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
+ */
+
+#include <sound/driver.h>
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/input.h>
+#include <sound/core.h>
+#include <sound/control.h>
+#include "pmac.h"
+
+struct snd_pmac_beep {
+	int running;	/* boolean */
+	int volume;	/* mixer volume: 0-100 */
+	int volume_play;	/* currently playing volume */
+	int hz;
+	int nsamples;
+	short *buf;		/* allocated wave buffer */
+	unsigned long addr;	/* physical address of buffer */
+	struct input_dev dev;
+};
+
+/*
+ * stop beep if running
+ */
+void snd_pmac_beep_stop(pmac_t *chip)
+{
+	pmac_beep_t *beep = chip->beep;
+	if (beep && beep->running) {
+		beep->running = 0;
+		snd_pmac_beep_dma_stop(chip);
+	}
+}
+
+/*
+ * Stuff for outputting a beep.  The values range from -327 to +327
+ * so we can multiply by an amplitude in the range 0..100 to get a
+ * signed short value to put in the output buffer.
+ */
+static short beep_wform[256] = {
+	0,	40,	79,	117,	153,	187,	218,	245,
+	269,	288,	304,	316,	323,	327,	327,	324,
+	318,	310,	299,	288,	275,	262,	249,	236,
+	224,	213,	204,	196,	190,	186,	183,	182,
+	182,	183,	186,	189,	192,	196,	200,	203,
+	206,	208,	209,	209,	209,	207,	204,	201,
+	197,	193,	188,	183,	179,	174,	170,	166,
+	163,	161,	160,	159,	159,	160,	161,	162,
+	164,	166,	168,	169,	171,	171,	171,	170,
+	169,	167,	163,	159,	155,	150,	144,	139,
+	133,	128,	122,	117,	113,	110,	107,	105,
+	103,	103,	103,	103,	104,	104,	105,	105,
+	105,	103,	101,	97,	92,	86,	78,	68,
+	58,	45,	32,	18,	3,	-11,	-26,	-41,
+	-55,	-68,	-79,	-88,	-95,	-100,	-102,	-102,
+	-99,	-93,	-85,	-75,	-62,	-48,	-33,	-16,
+	0,	16,	33,	48,	62,	75,	85,	93,
+	99,	102,	102,	100,	95,	88,	79,	68,
+	55,	41,	26,	11,	-3,	-18,	-32,	-45,
+	-58,	-68,	-78,	-86,	-92,	-97,	-101,	-103,
+	-105,	-105,	-105,	-104,	-104,	-103,	-103,	-103,
+	-103,	-105,	-107,	-110,	-113,	-117,	-122,	-128,
+	-133,	-139,	-144,	-150,	-155,	-159,	-163,	-167,
+	-169,	-170,	-171,	-171,	-171,	-169,	-168,	-166,
+	-164,	-162,	-161,	-160,	-159,	-159,	-160,	-161,
+	-163,	-166,	-170,	-174,	-179,	-183,	-188,	-193,
+	-197,	-201,	-204,	-207,	-209,	-209,	-209,	-208,
+	-206,	-203,	-200,	-196,	-192,	-189,	-186,	-183,
+	-182,	-182,	-183,	-186,	-190,	-196,	-204,	-213,
+	-224,	-236,	-249,	-262,	-275,	-288,	-299,	-310,
+	-318,	-324,	-327,	-327,	-323,	-316,	-304,	-288,
+	-269,	-245,	-218,	-187,	-153,	-117,	-79,	-40,
+};
+
+#define BEEP_SRATE	22050	/* 22050 Hz sample rate */
+#define BEEP_BUFLEN	512
+#define BEEP_VOLUME	15	/* 0 - 100 */
+
+static int snd_pmac_beep_event(struct input_dev *dev, unsigned int type, unsigned int code, int hz)
+{
+	pmac_t *chip;
+	pmac_beep_t *beep;
+	unsigned long flags;
+	int beep_speed = 0;
+	int srate;
+	int period, ncycles, nsamples;
+	int i, j, f;
+	short *p;
+
+	if (type != EV_SND)
+		return -1;
+
+	switch (code) {
+	case SND_BELL: if (hz) hz = 1000;
+	case SND_TONE: break;
+	default: return -1;
+	}
+
+	chip = dev->private;
+	if (! chip || (beep = chip->beep) == NULL)
+		return -1;
+
+	if (! hz) {
+		spin_lock_irqsave(&chip->reg_lock, flags);
+		if (beep->running)
+			snd_pmac_beep_stop(chip);
+		spin_unlock_irqrestore(&chip->reg_lock, flags);
+		return 0;
+	}
+
+	beep_speed = snd_pmac_rate_index(chip, &chip->playback, BEEP_SRATE);
+	srate = chip->freq_table[beep_speed];
+
+	if (hz <= srate / BEEP_BUFLEN || hz > srate / 2)
+		hz = 1000;
+
+	spin_lock_irqsave(&chip->reg_lock, flags);
+	if (chip->playback.running || chip->capture.running || beep->running) {
+		spin_unlock_irqrestore(&chip->reg_lock, flags);
+		return 0;
+	}
+	beep->running = 1;
+	spin_unlock_irqrestore(&chip->reg_lock, flags);
+
+	if (hz == beep->hz && beep->volume == beep->volume_play) {
+		nsamples = beep->nsamples;
+	} else {
+		period = srate * 256 / hz;	/* fixed point */
+		ncycles = BEEP_BUFLEN * 256 / period;
+		nsamples = (period * ncycles) >> 8;
+		f = ncycles * 65536 / nsamples;
+		j = 0;
+		p = beep->buf;
+		for (i = 0; i < nsamples; ++i, p += 2) {
+			p[0] = p[1] = beep_wform[j >> 8] * beep->volume;
+			j = (j + f) & 0xffff;
+		}
+		beep->hz = hz;
+		beep->volume_play = beep->volume;
+		beep->nsamples = nsamples;
+	}
+
+	spin_lock_irqsave(&chip->reg_lock, flags);
+	snd_pmac_beep_dma_start(chip, beep->nsamples * 4, beep->addr, beep_speed);
+	spin_unlock_irqrestore(&chip->reg_lock, flags);
+	return 0;
+}
+
+/*
+ * beep volume mixer
+ */
+
+#define chip_t pmac_t
+
+static int snd_pmac_info_beep(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo)
+{
+	uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
+	uinfo->count = 1;
+	uinfo->value.integer.min = 0;
+	uinfo->value.integer.max = 100;
+	return 0;
+}
+
+static int snd_pmac_get_beep(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+{
+	pmac_t *chip = snd_kcontrol_chip(kcontrol);
+	snd_assert(chip->beep, return -ENXIO);
+	ucontrol->value.integer.value[0] = chip->beep->volume;
+	return 0;
+}
+
+static int snd_pmac_put_beep(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+{
+	pmac_t *chip = snd_kcontrol_chip(kcontrol);
+	int oval;
+	snd_assert(chip->beep, return -ENXIO);
+	oval = chip->beep->volume;
+	chip->beep->volume = ucontrol->value.integer.value[0];
+	return oval != chip->beep->volume;
+}
+
+static snd_kcontrol_new_t snd_pmac_beep_mixer = {
+	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+	.name = "Beep Playback Volume",
+	.info = snd_pmac_info_beep,
+	.get = snd_pmac_get_beep,
+	.put = snd_pmac_put_beep,
+};
+
+/* Initialize beep stuff */
+int __init snd_pmac_attach_beep(pmac_t *chip)
+{
+	pmac_beep_t *beep;
+	int err;
+
+	beep = kmalloc(sizeof(*beep), GFP_KERNEL);
+	if (! beep)
+		return -ENOMEM;
+
+	memset(beep, 0, sizeof(*beep));
+	beep->buf = (short *) kmalloc(BEEP_BUFLEN * 4, GFP_KERNEL);
+	if (! beep->buf) {
+		kfree(beep);
+		return -ENOMEM;
+	}
+	beep->addr = virt_to_bus(beep->buf);
+
+	beep->dev.evbit[0] = BIT(EV_SND);
+	beep->dev.sndbit[0] = BIT(SND_BELL) | BIT(SND_TONE);
+	beep->dev.event = snd_pmac_beep_event;
+	beep->dev.private = chip;
+
+	/* FIXME: set more better values */
+	beep->dev.name = "PowerMac Beep";
+	beep->dev.phys = "powermac/beep";
+	beep->dev.id.bustype = BUS_ADB;
+	beep->dev.id.vendor = 0x001f;
+	beep->dev.id.product = 0x0001;
+	beep->dev.id.version = 0x0100;
+
+	beep->volume = BEEP_VOLUME;
+	beep->running = 0;
+	if ((err = snd_ctl_add(chip->card, snd_ctl_new1(&snd_pmac_beep_mixer, chip))) < 0) {
+		kfree(beep->buf);
+		kfree(beep);
+		return err;
+	}
+
+	chip->beep = beep;
+	input_register_device(&beep->dev);
+
+	return 0;
+}
+
+void snd_pmac_detach_beep(pmac_t *chip)
+{
+	if (chip->beep) {
+		input_unregister_device(&chip->beep->dev);
+		kfree(chip->beep->buf);
+		kfree(chip->beep);
+		chip->beep = NULL;
+	}
+}
diff -Nru a/sound/ppc/burgundy.c b/sound/ppc/burgundy.c
--- a/sound/ppc/burgundy.c	2004-10-18 14:56:28 -07:00
+++ b/sound/ppc/burgundy.c	2004-10-18 14:56:28 -07:00
@@ -28,8 +28,6 @@
 #include "pmac.h"
 #include "burgundy.h"
 
-#define chip_t pmac_t
-
 
 /* Waits for busy flag to clear */
 inline static void
@@ -324,8 +322,6 @@
 static snd_kcontrol_new_t snd_pmac_burgundy_speaker_sw __initdata = 
 BURGUNDY_OUTPUT_SWITCH("PC Speaker Playback Switch", 0, BURGUNDY_OUTPUT_INTERN, 0, 0);
 
-#define num_controls(ary) (sizeof(ary) / sizeof(snd_kcontrol_new_t))
-
 
 #ifdef PMAC_SUPPORT_AUTOMUTE
 /*
@@ -420,7 +416,7 @@
 	 */
 	strcpy(chip->card->mixername, "PowerMac Burgundy");
 
-	for (i = 0; i < num_controls(snd_pmac_burgundy_mixers); i++) {
+	for (i = 0; i < ARRAY_SIZE(snd_pmac_burgundy_mixers); i++) {
 		if ((err = snd_ctl_add(chip->card, snd_ctl_new1(&snd_pmac_burgundy_mixers[i], chip))) < 0)
 			return err;
 	}
diff -Nru a/sound/ppc/daca.c b/sound/ppc/daca.c
--- a/sound/ppc/daca.c	2004-10-18 14:56:13 -07:00
+++ b/sound/ppc/daca.c	2004-10-18 14:56:13 -07:00
@@ -28,8 +28,6 @@
 #include <sound/core.h>
 #include "pmac.h"
 
-#define chip_t pmac_t
-
 /* i2c address */
 #define DACA_I2C_ADDR	0x4d
 
@@ -217,8 +215,6 @@
 	},
 };
 
-#define num_controls(ary) (sizeof(ary) / sizeof(snd_kcontrol_new_t))
-
 
 #ifdef CONFIG_PMAC_PBOOK
 static void daca_resume(pmac_t *chip)
@@ -272,7 +268,7 @@
 	 */
 	strcpy(chip->card->mixername, "PowerMac DACA");
 
-	for (i = 0; i < num_controls(daca_mixers); i++) {
+	for (i = 0; i < ARRAY_SIZE(daca_mixers); i++) {
 		if ((err = snd_ctl_add(chip->card, snd_ctl_new1(&daca_mixers[i], chip))) < 0)
 			return err;
 	}
diff -Nru a/sound/ppc/pmac.c b/sound/ppc/pmac.c
--- a/sound/ppc/pmac.c	2004-10-18 14:57:05 -07:00
+++ b/sound/ppc/pmac.c	2004-10-18 14:57:05 -07:00
@@ -36,8 +36,6 @@
 #include <asm/feature.h>
 #endif
 
-#define chip_t pmac_t
-
 
 #if defined(CONFIG_PM) && defined(CONFIG_PMAC_PBOOK)
 static int snd_pmac_register_sleep_notifier(pmac_t *chip);
@@ -52,8 +50,8 @@
 	44100, 29400, 22050, 17640, 14700, 11025, 8820, 7350
 };
 /* fixed frequency table for tumbler */
-static int tumbler_freqs[2] = {
-	48000, 44100
+static int tumbler_freqs[1] = {
+	44100
 };
 
 /*
@@ -86,7 +84,7 @@
  * look up frequency table
  */
 
-static unsigned int snd_pmac_rate_index(pmac_t *chip, pmac_stream_t *rec, unsigned int rate)
+unsigned int snd_pmac_rate_index(pmac_t *chip, pmac_stream_t *rec, unsigned int rate)
 {
 	int i, ok, found;
 
@@ -203,7 +201,6 @@
 {
 	int i;
 	volatile struct dbdma_cmd *cp;
-	unsigned long flags;
 	snd_pcm_runtime_t *runtime = subs->runtime;
 	int rate_index;
 	long offset;
@@ -226,15 +223,17 @@
 	/* We really want to execute a DMA stop command, after the AWACS
 	 * is initialized.
 	 * For reasons I don't understand, it stops the hissing noise
-	 * common to many PowerBook G3 systems (like mine :-).
+	 * common to many PowerBook G3 systems and random noise otherwise
+	 * captured on iBook2's about every third time. -ReneR
 	 */
-	spin_lock_irqsave(&chip->reg_lock, flags);
+	spin_lock_irq(&chip->reg_lock);
 	snd_pmac_dma_stop(rec);
-	if (rec->stream == SNDRV_PCM_STREAM_PLAYBACK) {
-		st_le16(&chip->extra_dma.cmds->command, DBDMA_STOP);
-		snd_pmac_dma_set_command(rec, &chip->extra_dma);
-		snd_pmac_dma_run(rec, RUN);
-	}
+	st_le16(&chip->extra_dma.cmds->command, DBDMA_STOP);
+	snd_pmac_dma_set_command(rec, &chip->extra_dma);
+	snd_pmac_dma_run(rec, RUN);
+	spin_unlock_irq(&chip->reg_lock);
+	mdelay(5);
+	spin_lock_irq(&chip->reg_lock);
 	/* continuous DMA memory type doesn't provide the physical address,
 	 * so we need to resolve the address here...
 	 */
@@ -252,7 +251,7 @@
 
 	snd_pmac_dma_stop(rec);
 	snd_pmac_dma_set_command(rec, &rec->cmd);
-	spin_unlock_irqrestore(&chip->reg_lock, flags);
+	spin_unlock_irq(&chip->reg_lock);
 
 	return 0;
 }
@@ -264,7 +263,6 @@
 static int snd_pmac_pcm_trigger(pmac_t *chip, pmac_stream_t *rec,
 				snd_pcm_substream_t *subs, int cmd)
 {
-	unsigned long flags;
 	volatile struct dbdma_cmd *cp;
 	int i, command;
 
@@ -275,7 +273,7 @@
 			return -EBUSY;
 		command = (subs->stream == SNDRV_PCM_STREAM_PLAYBACK ?
 			   OUTPUT_MORE : INPUT_MORE) + INTR_ALWAYS;
-		spin_lock_irqsave(&chip->reg_lock, flags);
+		spin_lock(&chip->reg_lock);
 		snd_pmac_beep_stop(chip);
 		snd_pmac_pcm_set_format(chip);
 		for (i = 0, cp = rec->cmd.cmds; i < rec->nperiods; i++, cp++)
@@ -284,18 +282,18 @@
 		(void)in_le32(&rec->dma->status);
 		snd_pmac_dma_run(rec, RUN|WAKE);
 		rec->running = 1;
-		spin_unlock_irqrestore(&chip->reg_lock, flags);
+		spin_unlock(&chip->reg_lock);
 		break;
 
 	case SNDRV_PCM_TRIGGER_STOP:
 	case SNDRV_PCM_TRIGGER_SUSPEND:
-		spin_lock_irqsave(&chip->reg_lock, flags);
+		spin_lock(&chip->reg_lock);
 		rec->running = 0;
 		/*printk("stopped!!\n");*/
 		snd_pmac_dma_stop(rec);
 		for (i = 0, cp = rec->cmd.cmds; i < rec->nperiods; i++, cp++)
 			out_le16(&cp->command, DBDMA_STOP);
-		spin_unlock_irqrestore(&chip->reg_lock, flags);
+		spin_unlock(&chip->reg_lock);
 		break;
 
 	default:
@@ -490,14 +488,12 @@
 	snd_pcm_runtime_t *runtime = subs->runtime;
 	int i, j, fflags;
 	static int typical_freqs[] = {
-		48000,
 		44100,
 		22050,
 		11025,
 		0,
 	};
 	static int typical_freq_flags[] = {
-		SNDRV_PCM_RATE_48000,
 		SNDRV_PCM_RATE_44100,
 		SNDRV_PCM_RATE_22050,
 		SNDRV_PCM_RATE_11025,
@@ -651,7 +647,7 @@
 
 	pcm->private_data = chip;
 	pcm->private_free = pmac_pcm_free;
-	pcm->info_flags = 0;
+	pcm->info_flags = SNDRV_PCM_INFO_JOINT_DUPLEX;
 	strcpy(pcm->name, chip->card->shortname);
 	chip->pcm = pcm;
 
@@ -683,12 +679,41 @@
 
 
 /*
+ * handling beep
+ */
+void snd_pmac_beep_dma_start(pmac_t *chip, int bytes, unsigned long addr, int speed)
+{
+	pmac_stream_t *rec = &chip->playback;
+
+	snd_pmac_dma_stop(rec);
+	st_le16(&chip->extra_dma.cmds->req_count, bytes);
+	st_le16(&chip->extra_dma.cmds->xfer_status, 0);
+	st_le32(&chip->extra_dma.cmds->cmd_dep, chip->extra_dma.addr);
+	st_le32(&chip->extra_dma.cmds->phy_addr, addr);
+	st_le16(&chip->extra_dma.cmds->command, OUTPUT_MORE + BR_ALWAYS);
+	out_le32(&chip->awacs->control,
+		 (in_le32(&chip->awacs->control) & ~0x1f00)
+		 | (speed << 8));
+	out_le32(&chip->awacs->byteswap, 0);
+	snd_pmac_dma_set_command(rec, &chip->extra_dma);
+	snd_pmac_dma_run(rec, RUN);
+}
+
+void snd_pmac_beep_dma_stop(pmac_t *chip)
+{
+	snd_pmac_dma_stop(&chip->playback);
+	st_le16(&chip->extra_dma.cmds->command, DBDMA_STOP);
+	snd_pmac_pcm_set_format(chip); /* reset format */
+}
+
+
+/*
  * interrupt handlers
  */
 static irqreturn_t
 snd_pmac_tx_intr(int irq, void *devid, struct pt_regs *regs)
 {
-	pmac_t *chip = snd_magic_cast(pmac_t, devid, return IRQ_NONE);
+	pmac_t *chip = devid;
 	snd_pmac_pcm_update(chip, &chip->playback);
 	return IRQ_HANDLED;
 }
@@ -697,7 +722,7 @@
 static irqreturn_t
 snd_pmac_rx_intr(int irq, void *devid, struct pt_regs *regs)
 {
-	pmac_t *chip = snd_magic_cast(pmac_t, devid, return IRQ_NONE);
+	pmac_t *chip = devid;
 	snd_pmac_pcm_update(chip, &chip->capture);
 	return IRQ_HANDLED;
 }
@@ -706,7 +731,7 @@
 static irqreturn_t
 snd_pmac_ctrl_intr(int irq, void *devid, struct pt_regs *regs)
 {
-	pmac_t *chip = snd_magic_cast(pmac_t, devid, return IRQ_NONE);
+	pmac_t *chip = devid;
 	int ctrl = in_le32(&chip->awacs->control);
 
 	/*printk("pmac: control interrupt.. 0x%x\n", ctrl);*/
@@ -776,6 +801,8 @@
 	if (chip->mixer_free)
 		chip->mixer_free(chip);
 
+	snd_pmac_detach_beep(chip);
+
 	/* release resources */
 	if (chip->irq >= 0)
 		free_irq(chip->irq, (void*)chip);
@@ -802,7 +829,7 @@
 				release_OF_resource(chip->node, i);
 		}
 	}
-	snd_magic_kfree(chip);
+	kfree(chip);
 	return 0;
 }
 
@@ -812,7 +839,7 @@
  */
 static int snd_pmac_dev_free(snd_device_t *device)
 {
-	pmac_t *chip = snd_magic_cast(pmac_t, device->device_data, return -ENXIO);
+	pmac_t *chip = device->device_data;
 	return snd_pmac_free(chip);
 }
 
@@ -862,7 +889,7 @@
 	chip->can_byte_swap = 1;
 	chip->can_duplex = 1;
 	chip->can_capture = 1;
-	chip->num_freqs = 8;
+	chip->num_freqs = ARRAY_SIZE(awacs_freqs);
 	chip->freq_table = awacs_freqs;
 
 	chip->control_mask = MASK_IEPC | MASK_IEE | 0x11; /* default */
@@ -920,14 +947,14 @@
 		chip->can_capture = 0;  /* no capture */
 		chip->can_duplex = 0;
 		// chip->can_byte_swap = 0; /* FIXME: check this */
-		chip->num_freqs = 2;
+		chip->num_freqs = ARRAY_SIZE(tumbler_freqs);
 		chip->freq_table = tumbler_freqs;
 		chip->control_mask = MASK_IEPC | 0x11; /* disable IEE */
 	}
 	if (device_is_compatible(sound, "snapper")) {
 		chip->model = PMAC_SNAPPER;
 		// chip->can_byte_swap = 0; /* FIXME: check this */
-		chip->num_freqs = 2;
+		chip->num_freqs = ARRAY_SIZE(tumbler_freqs);
 		chip->freq_table = tumbler_freqs;
 		chip->control_mask = MASK_IEPC | 0x11; /* disable IEE */
 	}
@@ -1069,7 +1096,7 @@
 	snd_runtime_check(chip_return, return -EINVAL);
 	*chip_return = NULL;
 
-	chip = snd_magic_kcalloc(pmac_t, 0, GFP_KERNEL);
+	chip = kcalloc(1, sizeof(*chip), GFP_KERNEL);
 	if (chip == NULL)
 		return -ENOMEM;
 	chip->card = card;
@@ -1206,7 +1233,7 @@
 
 static int snd_pmac_suspend(snd_card_t *card, unsigned int state)
 {
-	pmac_t *chip = snd_magic_cast(pmac_t, card->pm_private_data, return -EINVAL);
+	pmac_t *chip = card->pm_private_data;
 	unsigned long flags;
 
 	if (chip->suspend)
@@ -1228,7 +1255,7 @@
 
 static int snd_pmac_resume(snd_card_t *card, unsigned int state)
 {
-	pmac_t *chip = snd_magic_cast(pmac_t, card->pm_private_data, return -EINVAL);
+	pmac_t *chip = card->pm_private_data;
 
 	snd_pmac_sound_feature(chip, 1);
 	if (chip->resume)
diff -Nru a/sound/ppc/pmac.h b/sound/ppc/pmac.h
--- a/sound/ppc/pmac.h	2004-10-18 14:56:33 -07:00
+++ b/sound/ppc/pmac.h	2004-10-18 14:56:33 -07:00
@@ -84,7 +84,7 @@
 
 	snd_pcm_substream_t *substream;
 
-	unsigned int cur_freqs;		/* currently available frequences */
+	unsigned int cur_freqs;		/* currently available frequencies */
 	unsigned int cur_formats;	/* currently available formats */
 };
 
@@ -155,6 +155,7 @@
 	void (*mixer_free)(pmac_t *);
 	snd_kcontrol_t *master_sw_ctl;
 	snd_kcontrol_t *speaker_sw_ctl;
+	snd_kcontrol_t *drc_sw_ctl;	/* only used for tumbler -ReneR */
 	snd_kcontrol_t *hp_detect_ctl;
 
 	/* lowlevel callbacks */
@@ -173,6 +174,12 @@
 int snd_pmac_new(snd_card_t *card, pmac_t **chip_return);
 int snd_pmac_pcm_new(pmac_t *chip);
 int snd_pmac_attach_beep(pmac_t *chip);
+void snd_pmac_detach_beep(pmac_t *chip);
+void snd_pmac_beep_stop(pmac_t *chip);
+unsigned int snd_pmac_rate_index(pmac_t *chip, pmac_stream_t *rec, unsigned int rate);
+
+void snd_pmac_beep_dma_start(pmac_t *chip, int bytes, unsigned long addr, int speed);
+void snd_pmac_beep_dma_stop(pmac_t *chip);
 
 /* initialize mixer */
 int snd_pmac_awacs_init(pmac_t *chip);
@@ -205,10 +212,5 @@
 	set_current_state(TASK_UNINTERRUPTIBLE);\
 	schedule_timeout(((msec) * HZ + 999) / 1000);\
 } while (0)
-
-#ifndef PMAC_SUPPORT_PCM_BEEP
-#define snd_pmac_attach_beep(chip) 0
-#define snd_pmac_beep_stop(chip)  /**/
-#endif
 
 #endif /* __PMAC_H */
diff -Nru a/sound/ppc/powermac.c b/sound/ppc/powermac.c
--- a/sound/ppc/powermac.c	2004-10-18 14:57:05 -07:00
+++ b/sound/ppc/powermac.c	2004-10-18 14:57:05 -07:00
@@ -30,31 +30,19 @@
 #define CHIP_NAME "PMac"
 
 MODULE_DESCRIPTION("PowerMac");
-MODULE_CLASSES("{sound}");
-MODULE_DEVICES("{{Apple,PowerMac}}");
+MODULE_SUPPORTED_DEVICE("{{Apple,PowerMac}}");
 MODULE_LICENSE("GPL");
 
 static int index = SNDRV_DEFAULT_IDX1;		/* Index 0-MAX */
 static char *id = SNDRV_DEFAULT_STR1;		/* ID for this card */
-/* static int enable = 1; */
-#ifdef PMAC_SUPPORT_PCM_BEEP
 static int enable_beep = 1;
-#endif
 
 module_param(index, int, 0444);
 MODULE_PARM_DESC(index, "Index value for " CHIP_NAME " soundchip.");
-MODULE_PARM_SYNTAX(index, SNDRV_INDEX_DESC);
 module_param(id, charp, 0444);
 MODULE_PARM_DESC(id, "ID string for " CHIP_NAME " soundchip.");
-MODULE_PARM_SYNTAX(id, SNDRV_ID_DESC);
-/* module_param(enable, bool, 0444);
-   MODULE_PARM_DESC(enable, "Enable this soundchip.");
-   MODULE_PARM_SYNTAX(enable, SNDRV_ENABLE_DESC); */
-#ifdef PMAC_SUPPORT_PCM_BEEP
 module_param(enable_beep, bool, 0444);
 MODULE_PARM_DESC(enable_beep, "Enable beep using PCM.");
-MODULE_PARM_SYNTAX(enable_beep, SNDRV_ENABLED "," SNDRV_BOOLEAN_TRUE_DESC);
-#endif
 
 
 /*
@@ -133,10 +121,8 @@
 		goto __error;
 
 	chip->initialized = 1;
-#ifdef PMAC_SUPPORT_PCM_BEEP
 	if (enable_beep)
 		snd_pmac_attach_beep(chip);
-#endif
 
 	if ((err = snd_card_register(card)) < 0)
 		goto __error;
@@ -151,18 +137,14 @@
 
 
 /*
- * MODULE sutff
+ * MODULE stuff
  */
 
 static int __init alsa_card_pmac_init(void)
 {
 	int err;
-	if ((err = snd_pmac_probe()) < 0) {
-#ifdef MODULE
-		printk(KERN_ERR "no PMac soundchip found\n");
-#endif
+	if ((err = snd_pmac_probe()) < 0)
 		return err;
-	}
 	return 0;
 
 }
diff -Nru a/sound/ppc/tumbler.c b/sound/ppc/tumbler.c
--- a/sound/ppc/tumbler.c	2004-10-18 14:55:54 -07:00
+++ b/sound/ppc/tumbler.c	2004-10-18 14:55:54 -07:00
@@ -16,6 +16,11 @@
  *   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
+ *
+ *   Rene Rebe <rene.rebe@gmx.net>:
+ *     * update from shadow registers on wakeup and headphone plug
+ *     * automatically toggle DRC on headphone plug
+ *	
  */
 
 
@@ -36,8 +41,6 @@
 #include "pmac.h"
 #include "tumbler_volume.h"
 
-#define chip_t pmac_t
-
 /* i2c address for tumbler */
 #define TAS_I2C_ADDR	0x34
 
@@ -759,12 +762,6 @@
 	DEFINE_MONO("Tone Control - Treble", treble),
 	DEFINE_MONO("PCM Playback Volume", pcm),
 	{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
-	  .name = "DRC Switch",
-	  .info = snd_pmac_boolean_mono_info,
-	  .get = tumbler_get_drc_switch,
-	  .put = tumbler_put_drc_switch
-	},
-	{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
 	  .name = "DRC Range",
 	  .info = tumbler_info_drc_value,
 	  .get = tumbler_get_drc_value,
@@ -791,12 +788,6 @@
 	DEFINE_SNAPPER_MONO("Tone Control - Bass", bass),
 	DEFINE_SNAPPER_MONO("Tone Control - Treble", treble),
 	{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
-	  .name = "DRC Switch",
-	  .info = snd_pmac_boolean_mono_info,
-	  .get = tumbler_get_drc_switch,
-	  .put = tumbler_put_drc_switch
-	},
-	{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
 	  .name = "DRC Range",
 	  .info = tumbler_info_drc_value,
 	  .get = tumbler_get_drc_value,
@@ -826,6 +817,14 @@
 	.put = tumbler_put_mute_switch,
 	.private_value = TUMBLER_MUTE_AMP,
 };
+static snd_kcontrol_new_t tumbler_drc_sw __initdata = {
+	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+	.name = "DRC Switch",
+	.info = snd_pmac_boolean_mono_info,
+	.get = tumbler_get_drc_switch,
+	.put = tumbler_put_drc_switch
+};
+
 
 #ifdef PMAC_SUPPORT_AUTOMUTE
 /*
@@ -847,6 +846,29 @@
 	}
 }
 
+static struct work_struct device_change;
+
+static void
+device_change_handler(void *self)
+{
+	pmac_t *chip = (pmac_t*) self;
+	pmac_tumbler_t *mix;
+
+	if (!chip)
+		return;
+
+	mix = chip->mixer_data;
+
+	/* first set the DRC so the speaker do not explode -ReneR */
+	if (chip->model == PMAC_TUMBLER)
+		tumbler_set_drc(mix);
+	else
+		snapper_set_drc(mix);
+
+	/* reset the master volume so the correct amplification is applied */
+	tumbler_set_master_volume(mix);
+}
+
 static void tumbler_update_automute(pmac_t *chip, int do_notify)
 {
 	if (chip->auto_mute) {
@@ -856,14 +878,25 @@
 			/* mute speaker */
 			check_mute(chip, &mix->amp_mute, 1, do_notify, chip->speaker_sw_ctl);
 			check_mute(chip, &mix->hp_mute, 0, do_notify, chip->master_sw_ctl);
+			mix->drc_enable = 0;
+
 		} else {
 			/* unmute speaker */
 			check_mute(chip, &mix->amp_mute, 0, do_notify, chip->speaker_sw_ctl);
 			check_mute(chip, &mix->hp_mute, 1, do_notify, chip->master_sw_ctl);
+			mix->drc_enable = 1;
 		}
-		if (do_notify)
+		if (do_notify) {
 			snd_ctl_notify(chip->card, SNDRV_CTL_EVENT_MASK_VALUE,
 				       &chip->hp_detect_ctl->id);
+			snd_ctl_notify(chip->card, SNDRV_CTL_EVENT_MASK_VALUE,
+			               &chip->drc_sw_ctl->id);
+		}
+
+		/* finally we need to schedule an update of the mixer values
+		   (master and DRC are enough for now) -ReneR */
+		schedule_work(&device_change);
+
 	}
 }
 #endif /* PMAC_SUPPORT_AUTOMUTE */
@@ -872,7 +905,7 @@
 /* interrupt - headphone plug changed */
 static irqreturn_t headphone_intr(int irq, void *devid, struct pt_regs *regs)
 {
-	pmac_t *chip = snd_magic_cast(pmac_t, devid, return IRQ_NONE);
+	pmac_t *chip = devid;
 	if (chip->update_automute && chip->initialized) {
 		chip->update_automute(chip, 1);
 		return IRQ_HANDLED;
@@ -1114,10 +1147,16 @@
 	chip->speaker_sw_ctl = snd_ctl_new1(&tumbler_speaker_sw, chip);
 	if ((err = snd_ctl_add(chip->card, chip->speaker_sw_ctl)) < 0)
 		return err;
+	chip->drc_sw_ctl = snd_ctl_new1(&tumbler_drc_sw, chip);
+	if ((err = snd_ctl_add(chip->card, chip->drc_sw_ctl)) < 0)
+		return err;
+
 
 #ifdef CONFIG_PMAC_PBOOK
 	chip->resume = tumbler_resume;
 #endif
+
+	INIT_WORK(&device_change, device_change_handler, (void *)chip);
 
 #ifdef PMAC_SUPPORT_AUTOMUTE
 	if (mix->headphone_irq >=0 && (err = snd_pmac_add_automute(chip)) < 0)
diff -Nru a/sound/sparc/amd7930.c b/sound/sparc/amd7930.c
--- a/sound/sparc/amd7930.c	2004-10-18 14:56:17 -07:00
+++ b/sound/sparc/amd7930.c	2004-10-18 14:56:17 -07:00
@@ -54,18 +54,14 @@
 
 module_param_array(index, int, boot_devs, 0444);
 MODULE_PARM_DESC(index, "Index value for Sun AMD7930 soundcard.");
-MODULE_PARM_SYNTAX(index, SNDRV_INDEX_DESC);
 module_param_array(id, charp, boot_devs, 0444);
 MODULE_PARM_DESC(id, "ID string for Sun AMD7930 soundcard.");
-MODULE_PARM_SYNTAX(id, SNDRV_ID_DESC);
 module_param_array(enable, bool, boot_devs, 0444);
 MODULE_PARM_DESC(enable, "Enable Sun AMD7930 soundcard.");
-MODULE_PARM_SYNTAX(enable, SNDRV_ENABLE_DESC);
 MODULE_AUTHOR("Thomas K. Dyas and David S. Miller");
 MODULE_DESCRIPTION("Sun AMD7930");
 MODULE_LICENSE("GPL");
-MODULE_CLASSES("{sound}");
-MODULE_DEVICES("{{Sun,AMD7930}}");
+MODULE_SUPPORTED_DEVICE("{{Sun,AMD7930}}");
 
 /* Device register layout.  */
 
@@ -318,7 +314,7 @@
 
 typedef struct snd_amd7930 {
 	spinlock_t		lock;
-	unsigned long		regs;
+	void __iomem		*regs;
 	u32			flags;
 #define AMD7930_FLAG_PLAYBACK	0x00000001
 #define AMD7930_FLAG_CAPTURE	0x00000002
@@ -345,7 +341,6 @@
 	unsigned int		regs_size;
 	struct snd_amd7930	*next;
 } amd7930_t;
-#define chip_t amd7930_t
 
 static amd7930_t *amd7930_list;
 
@@ -475,7 +470,6 @@
 	0x000b, /* 16.9 dB */
 	0x000f  /* 18. dB */
 };
-#define NR_GER_COEFFS (sizeof(ger_coeff) / sizeof(ger_coeff[0]))
 
 /* Update amd7930_map settings and program them into the hardware.
  * The amd->lock is held and local interrupts are disabled.
@@ -487,7 +481,7 @@
 
 	map->gx = gx_coeff[amd->rgain];
 	map->stgr = gx_coeff[amd->mgain];
-	level = (amd->pgain * (256 + NR_GER_COEFFS)) >> 8;
+	level = (amd->pgain * (256 + ARRAY_SIZE(ger_coeff))) >> 8;
 	if (level >= 256) {
 		map->ger = ger_coeff[level - 256];
 		map->gr = gx_coeff[255];
@@ -764,7 +758,7 @@
 
 static void snd_amd7930_pcm_free(snd_pcm_t *pcm)
 {
-	amd7930_t *amd = snd_magic_cast(amd7930_t, pcm->private_data, return);
+	amd7930_t *amd = pcm->private_data;
 
 	amd->pcm = NULL;
 	snd_pcm_lib_preallocate_free_for_all(pcm);
@@ -916,8 +910,6 @@
 	},
 };
 
-#define NUM_AMD7930_CONTROLS (sizeof(amd7930_controls)/sizeof(snd_kcontrol_new_t))
-
 static int __init snd_amd7930_mixer(amd7930_t *amd)
 {
 	snd_card_t *card;
@@ -928,7 +920,7 @@
 	card = amd->card;
 	strcpy(card->mixername, card->shortname);
 
-	for (idx = 0; idx < NUM_AMD7930_CONTROLS; idx++) {
+	for (idx = 0; idx < ARRAY_SIZE(amd7930_controls); idx++) {
 		if ((err = snd_ctl_add(card,
 				       snd_ctl_new1(&amd7930_controls[idx], amd))) < 0)
 			return err;
@@ -947,14 +939,14 @@
 	if (amd->regs)
 		sbus_iounmap(amd->regs, amd->regs_size);
 
-	snd_magic_kfree(amd);
+	kfree(amd);
 
 	return 0;
 }
 
 static int snd_amd7930_dev_free(snd_device_t *device)
 {
-	amd7930_t *amd = snd_magic_cast(amd7930_t, device->device_data, return -ENXIO);
+	amd7930_t *amd = device->device_data;
 
 	return snd_amd7930_free(amd);
 }
@@ -976,7 +968,7 @@
 	int err;
 
 	*ramd = NULL;
-	amd = snd_magic_kcalloc(amd7930_t, 0, GFP_KERNEL);
+	amd = kcalloc(1, sizeof(*amd), GFP_KERNEL);
 	if (amd == NULL)
 		return -ENOMEM;
 
diff -Nru a/sound/sparc/cs4231.c b/sound/sparc/cs4231.c
--- a/sound/sparc/cs4231.c	2004-10-18 14:55:54 -07:00
+++ b/sound/sparc/cs4231.c	2004-10-18 14:55:54 -07:00
@@ -53,22 +53,18 @@
 
 module_param_array(index, int, boot_devs, 0444);
 MODULE_PARM_DESC(index, "Index value for Sun CS4231 soundcard.");
-MODULE_PARM_SYNTAX(index, SNDRV_INDEX_DESC);
 module_param_array(id, charp, boot_devs, 0444);
 MODULE_PARM_DESC(id, "ID string for Sun CS4231 soundcard.");
-MODULE_PARM_SYNTAX(id, SNDRV_ID_DESC);
 module_param_array(enable, bool, boot_devs, 0444);
 MODULE_PARM_DESC(enable, "Enable Sun CS4231 soundcard.");
-MODULE_PARM_SYNTAX(enable, SNDRV_ENABLE_DESC);
 MODULE_AUTHOR("Jaroslav Kysela, Derrick J. Brashear and David S. Miller");
 MODULE_DESCRIPTION("Sun CS4231");
 MODULE_LICENSE("GPL");
-MODULE_CLASSES("{sound}");
-MODULE_DEVICES("{{Sun,CS4231}}");
+MODULE_SUPPORTED_DEVICE("{{Sun,CS4231}}");
 
 typedef struct snd_cs4231 {
 	spinlock_t		lock;
-	unsigned long		port;
+	void __iomem		*port;
 #ifdef EBUS_SUPPORT
 	struct ebus_dma_info	eb2c;
 	struct ebus_dma_info	eb2p;
@@ -112,7 +108,6 @@
 	unsigned int		regs_size;
 	struct snd_cs4231	*next;
 } cs4231_t;
-#define chip_t cs4231_t
 
 static cs4231_t *cs4231_list;
 
@@ -362,7 +357,7 @@
 	0x00,			/* 1f/31 - cbrl */
 };
 
-static u8 __cs4231_readb(cs4231_t *cp, unsigned long reg_addr)
+static u8 __cs4231_readb(cs4231_t *cp, void __iomem *reg_addr)
 {
 #ifdef EBUS_SUPPORT
 	if (cp->flags & CS4231_FLAG_EBUS) {
@@ -377,7 +372,7 @@
 #endif
 }
 
-static void __cs4231_writeb(cs4231_t *cp, u8 val, unsigned long reg_addr)
+static void __cs4231_writeb(cs4231_t *cp, u8 val, void __iomem *reg_addr)
 {
 #ifdef EBUS_SUPPORT
 	if (cp->flags & CS4231_FLAG_EBUS) {
@@ -556,7 +551,7 @@
 	chip->mce_bit |= CS4231_MCE;
 	timeout = __cs4231_readb(chip, CS4231P(chip, REGSEL));
 	if (timeout == 0x80)
-		snd_printk("mce_up [0x%lx]: serious init problem - codec still busy\n", chip->port);
+		snd_printk("mce_up [%p]: serious init problem - codec still busy\n", chip->port);
 	if (!(timeout & CS4231_MCE))
 		__cs4231_writeb(chip, chip->mce_bit | (timeout & 0x1f), CS4231P(chip, REGSEL));
 	spin_unlock_irqrestore(&chip->lock, flags);
@@ -581,7 +576,7 @@
 	timeout = __cs4231_readb(chip, CS4231P(chip, REGSEL));
 	__cs4231_writeb(chip, chip->mce_bit | (timeout & 0x1f), CS4231P(chip, REGSEL));
 	if (timeout == 0x80)
-		snd_printk("mce_down [0x%lx]: serious init problem - codec still busy\n", chip->port);
+		snd_printk("mce_down [%p]: serious init problem - codec still busy\n", chip->port);
 	if ((timeout & CS4231_MCE) == 0) {
 		spin_unlock_irqrestore(&chip->lock, flags);
 		return;
@@ -1232,7 +1227,7 @@
 #ifdef SBUS_SUPPORT
 static irqreturn_t snd_cs4231_sbus_interrupt(int irq, void *dev_id, struct pt_regs *regs)
 {
-	cs4231_t *chip = snd_magic_cast(cs4231_t, dev_id, return);
+	cs4231_t *chip = dev_id;
 	u32 csr;
 
 	csr = sbus_readl(chip->port + APCCSR);
@@ -1256,7 +1251,7 @@
 #ifdef EBUS_SUPPORT
 static void snd_cs4231_ebus_play_callback(struct ebus_dma_info *p, int event, void *cookie)
 {
-	cs4231_t *chip = snd_magic_cast(cs4231_t, cookie, return);
+	cs4231_t *chip = cookie;
 
 	if (chip->image[CS4231_IFACE_CTRL] & CS4231_PLAYBACK_ENABLE) {
 		snd_pcm_period_elapsed(chip->playback_substream);
@@ -1267,7 +1262,7 @@
 
 static void snd_cs4231_ebus_capture_callback(struct ebus_dma_info *p, int event, void *cookie)
 {
-	cs4231_t *chip = snd_magic_cast(cs4231_t, cookie, return);
+	cs4231_t *chip = cookie;
 
 	if (chip->image[CS4231_IFACE_CTRL] & CS4231_RECORD_ENABLE) {
 		snd_pcm_period_elapsed(chip->capture_substream);
@@ -1547,7 +1542,7 @@
 
 static void snd_cs4231_pcm_free(snd_pcm_t *pcm)
 {
-	cs4231_t *chip = snd_magic_cast(cs4231_t, pcm->private_data, return);
+	cs4231_t *chip = pcm->private_data;
 	chip->pcm = NULL;
 	snd_pcm_lib_preallocate_free_for_all(pcm);
 }
@@ -1592,7 +1587,7 @@
 
 static void snd_cs4231_timer_free(snd_timer_t *timer)
 {
-	cs4231_t *chip = snd_magic_cast(cs4231_t, timer->private_data, return);
+	cs4231_t *chip = timer->private_data;
 	chip->timer = NULL;
 }
 
@@ -1821,8 +1816,6 @@
 	return change;
 }
 
-#define CS4231_CONTROLS (sizeof(snd_cs4231_controls)/sizeof(snd_kcontrol_new_t))
-
 #define CS4231_SINGLE(xname, xindex, reg, shift, mask, invert) \
 { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xindex, \
   .info = snd_cs4231_info_single, \
@@ -1875,7 +1868,7 @@
 
 	strcpy(card->mixername, chip->pcm->name);
 
-	for (idx = 0; idx < CS4231_CONTROLS; idx++) {
+	for (idx = 0; idx < ARRAY_SIZE(snd_cs4231_controls); idx++) {
 		if ((err = snd_ctl_add(card,
 				       snd_ctl_new1(&snd_cs4231_controls[idx],
 						    chip))) < 0)
@@ -1950,14 +1943,14 @@
 	if (chip->timer)
 		snd_device_free(chip->card, chip->timer);
 
-	snd_magic_kfree(chip);
+	kfree(chip);
 
 	return 0;
 }
 
 static int snd_cs4231_sbus_dev_free(snd_device_t *device)
 {
-	cs4231_t *cp = snd_magic_cast(cs4231_t, device->device_data, return -ENXIO);
+	cs4231_t *cp = device->device_data;
 
 	return snd_cs4231_sbus_free(cp);
 }
@@ -1975,7 +1968,7 @@
 	int err;
 
 	*rchip = NULL;
-	chip = snd_magic_kcalloc(cs4231_t, 0, GFP_KERNEL);
+	chip = kcalloc(1, sizeof(*chip), GFP_KERNEL);
 	if (chip == NULL)
 		return -ENOMEM;
 
@@ -2064,14 +2057,14 @@
 	if (chip->timer)
 		snd_device_free(chip->card, chip->timer);
 
-	snd_magic_kfree(chip);
+	kfree(chip);
 
 	return 0;
 }
 
 static int snd_cs4231_ebus_dev_free(snd_device_t *device)
 {
-	cs4231_t *cp = snd_magic_cast(cs4231_t, device->device_data, return -ENXIO);
+	cs4231_t *cp = device->device_data;
 
 	return snd_cs4231_ebus_free(cp);
 }
@@ -2089,7 +2082,7 @@
 	int err;
 
 	*rchip = NULL;
-	chip = snd_magic_kcalloc(cs4231_t, 0, GFP_KERNEL);
+	chip = kcalloc(1, sizeof(*chip), GFP_KERNEL);
 	if (chip == NULL)
 		return -ENOMEM;
 
@@ -2114,9 +2107,9 @@
 	chip->eb2p.client_cookie = chip;
 	chip->eb2p.irq = edev->irqs[1];
 
-	chip->port = (unsigned long) ioremap(edev->resource[0].start, 0x10);
-	chip->eb2p.regs = (unsigned long) ioremap(edev->resource[1].start, 0x10);
-	chip->eb2c.regs = (unsigned long) ioremap(edev->resource[2].start, 0x10);
+	chip->port = ioremap(edev->resource[0].start, 0x10);
+	chip->eb2p.regs = ioremap(edev->resource[1].start, 0x10);
+	chip->eb2c.regs = ioremap(edev->resource[2].start, 0x10);
 	if (!chip->port || !chip->eb2p.regs || !chip->eb2c.regs) {
 		snd_cs4231_ebus_free(chip);
 		snd_printk("cs4231-%d: Unable to map chip registers.\n", dev);
diff -Nru a/sound/synth/emux/emux.c b/sound/synth/emux/emux.c
--- a/sound/synth/emux/emux.c	2004-10-18 14:56:32 -07:00
+++ b/sound/synth/emux/emux.c	2004-10-18 14:56:32 -07:00
@@ -39,7 +39,7 @@
 	snd_emux_t *emu;
 
 	*remu = NULL;
-	emu = snd_magic_kcalloc(snd_emux_t, 0, GFP_KERNEL);
+	emu = kcalloc(1, sizeof(*emu), GFP_KERNEL);
 	if (emu == NULL)
 		return -ENOMEM;
 
@@ -77,7 +77,7 @@
 
 	emu->card = card;
 	emu->name = snd_kmalloc_strdup(name, GFP_KERNEL);
-	emu->voices = snd_kcalloc(sizeof(snd_emux_voice_t) * emu->max_voices, GFP_KERNEL);
+	emu->voices = kcalloc(emu->max_voices, sizeof(snd_emux_voice_t), GFP_KERNEL);
 	if (emu->voices == NULL)
 		return -ENOMEM;
 
@@ -143,7 +143,7 @@
 	if (emu->name)
 		kfree(emu->name);
 
-	snd_magic_kfree(emu);
+	kfree(emu);
 	return 0;
 }
 
diff -Nru a/sound/synth/emux/emux_effect.c b/sound/synth/emux/emux_effect.c
--- a/sound/synth/emux/emux_effect.c	2004-10-18 14:56:28 -07:00
+++ b/sound/synth/emux/emux_effect.c	2004-10-18 14:56:28 -07:00
@@ -278,7 +278,7 @@
 snd_emux_create_effect(snd_emux_port_t *p)
 {
 	int i;
-	p->effect = snd_kcalloc(sizeof(snd_emux_effect_table_t) * p->chset.max_channels, GFP_KERNEL);
+	p->effect = kcalloc(p->chset.max_channels, sizeof(snd_emux_effect_table_t), GFP_KERNEL);
 	if (p->effect) {
 		for (i = 0; i < p->chset.max_channels; i++)
 			p->chset.channels[i].private = p->effect + i;
diff -Nru a/sound/synth/emux/emux_hwdep.c b/sound/synth/emux/emux_hwdep.c
--- a/sound/synth/emux/emux_hwdep.c	2004-10-18 14:56:49 -07:00
+++ b/sound/synth/emux/emux_hwdep.c	2004-10-18 14:56:49 -07:00
@@ -104,7 +104,7 @@
 static int
 snd_emux_hwdep_ioctl(snd_hwdep_t * hw, struct file *file, unsigned int cmd, unsigned long arg)
 {
-	snd_emux_t *emu = snd_magic_cast(snd_emux_t, hw->private_data, return -ENXIO);
+	snd_emux_t *emu = hw->private_data;
 
 	switch (cmd) {
 	case SNDRV_EMUX_IOCTL_VERSION:
diff -Nru a/sound/synth/emux/emux_nrpn.c b/sound/synth/emux/emux_nrpn.c
--- a/sound/synth/emux/emux_nrpn.c	2004-10-18 14:55:54 -07:00
+++ b/sound/synth/emux/emux_nrpn.c	2004-10-18 14:55:54 -07:00
@@ -22,8 +22,6 @@
 #include "emux_voice.h"
 #include <sound/asoundef.h>
 
-#define NELEM(arr) (sizeof(arr)/sizeof((arr)[0]))
-
 /*
  * conversion from NRPN/control parameters to Emu8000 raw parameters
  */
@@ -214,8 +212,6 @@
 	{26, EMUX_FX_REVERB,		fx_reverb},
 };
 
-static int num_awe_effects = NELEM(awe_effects);
-
 
 /*
  * GS(SC88) NRPN effects; still experimental
@@ -281,8 +277,6 @@
 	{10, EMUX_FX_LFO1_DELAY, gs_vib_delay},
 };
 
-static int num_gs_effects = NELEM(gs_effects);
-
 
 /*
  * NRPN events
@@ -292,7 +286,7 @@
 {
 	snd_emux_port_t *port;
 
-	port = snd_magic_cast(snd_emux_port_t, p, return);
+	port = p;
 	snd_assert(port != NULL, return);
 	snd_assert(chan != NULL, return);
 
@@ -305,7 +299,7 @@
 			chan->control[MIDI_CTL_LSB_DATA_ENTRY]; 
 		val -= 8192;
 		send_converted_effect
-			(awe_effects, num_awe_effects,
+			(awe_effects, ARRAY_SIZE(awe_effects),
 			 port, chan, chan->control[MIDI_CTL_NONREG_PARM_NUM_LSB],
 			 val, EMUX_FX_FLAG_SET);
 		return;
@@ -318,7 +312,7 @@
 		/* only MSB is valid */
 		val = chan->control[MIDI_CTL_MSB_DATA_ENTRY];
 		send_converted_effect
-			(gs_effects, num_gs_effects,
+			(gs_effects, ARRAY_SIZE(gs_effects),
 			 port, chan, chan->control[MIDI_CTL_NONREG_PARM_NUM_LSB],
 			 val, EMUX_FX_FLAG_ADD);
 		return;
@@ -362,12 +356,10 @@
 	{73, EMUX_FX_ENV2_ATTACK, xg_attack},
 };
 
-static int num_xg_effects = NELEM(xg_effects);
-
 int
 snd_emux_xg_control(snd_emux_port_t *port, snd_midi_channel_t *chan, int param)
 {
-	return send_converted_effect(xg_effects, num_xg_effects,
+	return send_converted_effect(xg_effects, ARRAY_SIZE(xg_effects),
 				     port, chan, param,
 				     chan->control[param],
 				     EMUX_FX_FLAG_ADD);
@@ -382,7 +374,7 @@
 	snd_emux_port_t *port;
 	snd_emux_t *emu;
 
-	port = snd_magic_cast(snd_emux_port_t, p, return);
+	port = p;
 	snd_assert(port != NULL, return);
 	snd_assert(chset != NULL, return);
 	emu = port->emu;
diff -Nru a/sound/synth/emux/emux_oss.c b/sound/synth/emux/emux_oss.c
--- a/sound/synth/emux/emux_oss.c	2004-10-18 14:56:28 -07:00
+++ b/sound/synth/emux/emux_oss.c	2004-10-18 14:56:28 -07:00
@@ -108,7 +108,7 @@
 	snd_seq_port_callback_t callback;
 	char tmpname[64];
 
-	emu = snd_magic_cast(snd_emux_t, closure, return -EINVAL);
+	emu = closure;
 	snd_assert(arg != NULL && emu != NULL, return -ENXIO);
 
 	down(&emu->register_mutex);
@@ -179,7 +179,7 @@
 	snd_emux_port_t *p;
 
 	snd_assert(arg != NULL, return -ENXIO);
-	p = snd_magic_cast(snd_emux_port_t, arg->private_data, return -EINVAL);
+	p = arg->private_data;
 	snd_assert(p != NULL, return -ENXIO);
 
 	emu = p->emu;
@@ -208,7 +208,7 @@
 	int rc;
 
 	snd_assert(arg != NULL, return -ENXIO);
-	p = snd_magic_cast(snd_emux_port_t, arg->private_data, return -EINVAL);
+	p = arg->private_data;
 	snd_assert(p != NULL, return -ENXIO);
 
 	emu = p->emu;
@@ -248,7 +248,7 @@
 	snd_emux_t *emu;
 
 	snd_assert(arg != NULL, return -ENXIO);
-	p = snd_magic_cast(snd_emux_port_t, arg->private_data, return -EINVAL);
+	p = arg->private_data;
 	snd_assert(p != NULL, return -ENXIO);
 
 	emu = p->emu;
@@ -278,7 +278,7 @@
 	snd_emux_port_t *p;
 
 	snd_assert(arg != NULL, return -ENXIO);
-	p = snd_magic_cast(snd_emux_port_t, arg->private_data, return -EINVAL);
+	p = arg->private_data;
 	snd_assert(p != NULL, return -ENXIO);
 	snd_emux_reset_port(p);
 	return 0;
@@ -296,7 +296,7 @@
 	snd_emux_port_t *p;
 	unsigned char cmd, *data;
 
-	p = snd_magic_cast(snd_emux_port_t, private_data, return -EINVAL);
+	p = private_data;
 	snd_assert(p != NULL, return -EINVAL);
 	emu = p->emu;
 	snd_assert(emu != NULL, return -EINVAL);
@@ -339,9 +339,11 @@
 	p2 = *(short *) &event[6];
 
 	switch (cmd) {
+#if 0 /* don't do this atomically */
 	case _EMUX_OSS_REMOVE_LAST_SAMPLES:
 		snd_soundfont_remove_unlocked(emu->sflist);
 		break;
+#endif
 	case _EMUX_OSS_SEND_EFFECT:
 		if (chan)
 			snd_emux_send_effect_oss(port, chan, p1, p2);
diff -Nru a/sound/synth/emux/emux_proc.c b/sound/synth/emux/emux_proc.c
--- a/sound/synth/emux/emux_proc.c	2004-10-18 14:57:03 -07:00
+++ b/sound/synth/emux/emux_proc.c	2004-10-18 14:57:03 -07:00
@@ -36,7 +36,7 @@
 	snd_emux_t *emu;
 	int i;
 
-	emu = snd_magic_cast(snd_emux_t, entry->private_data, return);
+	emu = entry->private_data;
 	down(&emu->register_mutex);
 	if (emu->name)
 		snd_iprintf(buf, "Device: %s\n", emu->name);
diff -Nru a/sound/synth/emux/emux_seq.c b/sound/synth/emux/emux_seq.c
--- a/sound/synth/emux/emux_seq.c	2004-10-18 14:57:20 -07:00
+++ b/sound/synth/emux/emux_seq.c	2004-10-18 14:57:20 -07:00
@@ -146,14 +146,14 @@
 	int i, type, cap;
 
 	/* Allocate structures for this channel */
-	if ((p = snd_magic_kcalloc(snd_emux_port_t, 0, GFP_KERNEL)) == NULL) {
+	if ((p = kcalloc(1, sizeof(*p), GFP_KERNEL)) == NULL) {
 		snd_printk("no memory\n");
 		return NULL;
 	}
-	p->chset.channels = snd_kcalloc(max_channels * sizeof(snd_midi_channel_t), GFP_KERNEL);
+	p->chset.channels = kcalloc(max_channels, sizeof(snd_midi_channel_t), GFP_KERNEL);
 	if (p->chset.channels == NULL) {
 		snd_printk("no memory\n");
-		snd_magic_kfree(p);
+		kfree(p);
 		return NULL;
 	}
 	for (i = 0; i < max_channels; i++)
@@ -192,14 +192,14 @@
 {
 	snd_emux_port_t *p;
 
-	p = snd_magic_cast(snd_emux_port_t, private_data, return);
+	p = private_data;
 	if (p) {
 #ifdef SNDRV_EMUX_USE_RAW_EFFECT
 		snd_emux_delete_effect(p);
 #endif
 		if (p->chset.channels)
 			kfree(p->chset.channels);
-		snd_magic_kfree(p);
+		kfree(p);
 	}
 }
 
@@ -257,7 +257,7 @@
 {
 	snd_emux_port_t *port;
 
-	port = snd_magic_cast(snd_emux_port_t, private_data, return -EINVAL);
+	port = private_data;
 	snd_assert(port != NULL && ev != NULL, return -EINVAL);
 
 	snd_midi_process_event(&emux_ops, ev, &port->chset);
@@ -308,7 +308,7 @@
 	snd_emux_port_t *p;
 	snd_emux_t *emu;
 
-	p = snd_magic_cast(snd_emux_port_t, private_data, return -EINVAL);
+	p = private_data;
 	snd_assert(p != NULL, return -EINVAL);
 	emu = p->emu;
 	snd_assert(emu != NULL, return -EINVAL);
@@ -329,7 +329,7 @@
 	snd_emux_port_t *p;
 	snd_emux_t *emu;
 
-	p = snd_magic_cast(snd_emux_port_t, private_data, return -EINVAL);
+	p = private_data;
 	snd_assert(p != NULL, return -EINVAL);
 	emu = p->emu;
 	snd_assert(emu != NULL, return -EINVAL);
@@ -383,7 +383,7 @@
 	if (emu->midi_ports <= 0)
 		return 0;
 
-	emu->vmidi = snd_kcalloc(sizeof(snd_rawmidi_t*) * emu->midi_ports, GFP_KERNEL);
+	emu->vmidi = kcalloc(emu->midi_ports, sizeof(snd_rawmidi_t*), GFP_KERNEL);
 	if (emu->vmidi == NULL)
 		return -ENOMEM;
 
@@ -392,7 +392,7 @@
 		snd_virmidi_dev_t *rdev;
 		if (snd_virmidi_new(card, emu->midi_devidx + i, &rmidi) < 0)
 			goto __error;
-		rdev = snd_magic_cast(snd_virmidi_dev_t, rmidi->private_data, continue);
+		rdev = rmidi->private_data;
 		sprintf(rmidi->name, "%s Synth MIDI", emu->name);
 		rdev->seq_mode = SNDRV_VIRMIDI_SEQ_ATTACH;
 		rdev->client = emu->client;
diff -Nru a/sound/synth/emux/emux_synth.c b/sound/synth/emux/emux_synth.c
--- a/sound/synth/emux/emux_synth.c	2004-10-18 14:56:29 -07:00
+++ b/sound/synth/emux/emux_synth.c	2004-10-18 14:56:29 -07:00
@@ -61,7 +61,7 @@
 	unsigned long flags;
 	snd_emux_port_t *port;
 
-	port = snd_magic_cast(snd_emux_port_t, p, return);
+	port = p;
 	snd_assert(port != NULL && chan != NULL, return);
 
 	emu = port->emu;
@@ -160,7 +160,7 @@
 	unsigned long flags;
 	snd_emux_port_t *port;
 
-	port = snd_magic_cast(snd_emux_port_t, p, return);
+	port = p;
 	snd_assert(port != NULL && chan != NULL, return);
 
 	emu = port->emu;
@@ -201,7 +201,7 @@
  */
 void snd_emux_timer_callback(unsigned long data)
 {
-	snd_emux_t *emu = snd_magic_cast(snd_emux_t, (void*)data, return);
+	snd_emux_t *emu = (snd_emux_t*) data;
 	snd_emux_voice_t *vp;
 	int ch, do_again = 0;
 
@@ -238,7 +238,7 @@
 	unsigned long flags;
 	snd_emux_port_t *port;
 
-	port = snd_magic_cast(snd_emux_port_t, p, return);
+	port = p;
 	snd_assert(port != NULL && chan != NULL, return);
 
 	emu = port->emu;
@@ -322,7 +322,7 @@
 {
 	snd_emux_port_t *port;
 
-	port = snd_magic_cast(snd_emux_port_t, p, return);
+	port = p;
 	snd_assert(port != NULL && chan != NULL, return);
 
 	switch (type) {
@@ -402,7 +402,7 @@
 	snd_emux_t *emu;
 	snd_emux_port_t *port;
 
-	port = snd_magic_cast(snd_emux_port_t, p, return);
+	port = p;
 	snd_assert(port != NULL && chan != NULL, return);
 
 	emu = port->emu;
diff -Nru a/sound/synth/emux/soundfont.c b/sound/synth/emux/soundfont.c
--- a/sound/synth/emux/soundfont.c	2004-10-18 14:56:49 -07:00
+++ b/sound/synth/emux/soundfont.c	2004-10-18 14:56:49 -07:00
@@ -64,15 +64,14 @@
 /*
  * lock access to sflist
  */
-static int
-lock_preset(snd_sf_list_t *sflist, int nonblock)
+static void
+lock_preset(snd_sf_list_t *sflist)
 {
-	if (nonblock) {
-		if (down_trylock(&sflist->presets_mutex))
-			return -EBUSY;
-	} else 
-		down(&sflist->presets_mutex);
-	return 0;
+	unsigned long flags;
+	down(&sflist->presets_mutex);
+	spin_lock_irqsave(&sflist->lock, flags);
+	sflist->presets_locked = 1;
+	spin_unlock_irqrestore(&sflist->lock, flags);
 }
 
 
@@ -82,6 +81,10 @@
 static void
 unlock_preset(snd_sf_list_t *sflist)
 {
+	unsigned long flags;
+	spin_lock_irqsave(&sflist->lock, flags);
+	sflist->presets_locked = 0;
+	spin_unlock_irqrestore(&sflist->lock, flags);
 	up(&sflist->presets_mutex);
 }
 
@@ -143,7 +146,7 @@
 
 	if (patch.type == SNDRV_SFNT_OPEN_PATCH) {
 		/* grab sflist to open */
-		lock_preset(sflist, 0);
+		lock_preset(sflist);
 		rc = open_patch(sflist, data, count, client);
 		unlock_preset(sflist);
 		return rc;
@@ -157,7 +160,7 @@
 	}
 	spin_unlock_irqrestore(&sflist->lock, flags);
 
-	lock_preset(sflist, 0);
+	lock_preset(sflist);
 	rc = -EINVAL;
 	switch (patch.type) {
 	case SNDRV_SFNT_LOAD_INFO:
@@ -237,8 +240,10 @@
 		return -ENOMEM;
 	}
 
+	spin_lock_irqsave(&sflist->lock, flags);
 	sflist->open_client = client;
 	sflist->currsf = sf;
+	spin_unlock_irqrestore(&sflist->lock, flags);
 
 	return 0;
 }
@@ -261,7 +266,7 @@
 	}
 
 	/* not found -- create a new one */
-	sf = (snd_soundfont_t*)snd_kcalloc(sizeof(*sf), GFP_KERNEL);
+	sf = kcalloc(1, sizeof(*sf), GFP_KERNEL);
 	if (sf == NULL)
 		return NULL;
 	sf->id = sflist->fonts_size;
@@ -296,8 +301,12 @@
 static int
 close_patch(snd_sf_list_t *sflist)
 {
+	unsigned long flags;
+
+	spin_lock_irqsave(&sflist->lock, flags);
 	sflist->currsf = NULL;
 	sflist->open_client = -1;
+	spin_unlock_irqrestore(&sflist->lock, flags);
 
 	rebuild_presets(sflist);
 
@@ -337,7 +346,7 @@
 {
 	snd_sf_zone_t *zp;
 
-	if ((zp = snd_kcalloc(sizeof(*zp), GFP_KERNEL)) == NULL)
+	if ((zp = kcalloc(1, sizeof(*zp), GFP_KERNEL)) == NULL)
 		return NULL;
 	zp->next = sf->zones;
 	sf->zones = zp;
@@ -368,7 +377,7 @@
 {
 	snd_sf_sample_t *sp;
 
-	if ((sp = snd_kcalloc(sizeof(*sp), GFP_KERNEL)) == NULL)
+	if ((sp = kcalloc(1, sizeof(*sp), GFP_KERNEL)) == NULL)
 		return NULL;
 
 	sp->next = sf->samples;
@@ -1090,7 +1099,7 @@
 			    long count, int client)
 {
 	int rc;
-	lock_preset(sflist, 0);
+	lock_preset(sflist);
 	rc = load_guspatch(sflist, data, count, client);
 	unlock_preset(sflist);
 	return rc;
@@ -1197,17 +1206,23 @@
 			  snd_sf_zone_t **table, int max_layers)
 {
 	int nvoices;
+	unsigned long flags;
 
-	if (lock_preset(sflist, 1))
+	/* this function is supposed to be called atomically,
+	 * so we check the lock.  if it's busy, just returns 0 to
+	 * tell the caller the busy state
+	 */
+	spin_lock_irqsave(&sflist->lock, flags);
+	if (sflist->presets_locked) {
+		spin_unlock_irqrestore(&sflist->lock, flags);
 		return 0;
-
+	}
 	nvoices = search_zones(sflist, notep, vel, preset, bank, table, max_layers, 0);
 	if (! nvoices) {
 		if (preset != def_preset || bank != def_bank)
 			nvoices = search_zones(sflist, notep, vel, def_preset, def_bank, table, max_layers, 0);
 	}
-	unlock_preset(sflist);
-
+	spin_unlock_irqrestore(&sflist->lock, flags);
 	return nvoices;
 }
 
@@ -1347,7 +1362,7 @@
 {
 	snd_sf_list_t *sflist;
 
-	if ((sflist = snd_kcalloc(sizeof(snd_sf_list_t), GFP_KERNEL)) == NULL)
+	if ((sflist = kcalloc(1, sizeof(*sflist), GFP_KERNEL)) == NULL)
 		return NULL;
 
 	init_MUTEX(&sflist->presets_mutex);
@@ -1371,7 +1386,7 @@
 	if (sflist == NULL)
 		return;
 	
-	lock_preset(sflist, 0);
+	lock_preset(sflist);
 	if (sflist->callback.sample_reset)
 		sflist->callback.sample_reset(sflist->callback.private_data);
 	snd_sf_clear(sflist);
@@ -1387,7 +1402,7 @@
 int
 snd_soundfont_remove_samples(snd_sf_list_t *sflist)
 {
-	lock_preset(sflist, 0);
+	lock_preset(sflist);
 	if (sflist->callback.sample_reset)
 		sflist->callback.sample_reset(sflist->callback.private_data);
 	snd_sf_clear(sflist);
@@ -1407,8 +1422,7 @@
 	snd_sf_zone_t *zp, *nextzp;
 	snd_sf_sample_t *sp, *nextsp;
 
-	if (lock_preset(sflist, 1))
-		return -EBUSY;
+	lock_preset(sflist);
 
 	if (sflist->callback.sample_reset)
 		sflist->callback.sample_reset(sflist->callback.private_data);
diff -Nru a/sound/synth/util_mem.c b/sound/synth/util_mem.c
--- a/sound/synth/util_mem.c	2004-10-18 14:56:27 -07:00
+++ b/sound/synth/util_mem.c	2004-10-18 14:56:27 -07:00
@@ -38,7 +38,7 @@
 {
 	snd_util_memhdr_t *hdr;
 
-	hdr = snd_kcalloc(sizeof(*hdr), GFP_KERNEL);
+	hdr = kcalloc(1, sizeof(*hdr), GFP_KERNEL);
 	if (hdr == NULL)
 		return NULL;
 	hdr->size = memsize;
diff -Nru a/sound/usb/Kconfig b/sound/usb/Kconfig
--- a/sound/usb/Kconfig	2004-10-18 14:56:49 -07:00
+++ b/sound/usb/Kconfig	2004-10-18 14:56:49 -07:00
@@ -11,5 +11,15 @@
 	help
 	  Say 'Y' or 'M' to include support for USB audio and USB MIDI devices.
 
+config SND_USB_USX2Y
+	tristate "Tascam US-122, US-224 and US-428 USB driver"
+	depends on SND && USB
+	select SND_HWDEP
+	select SND_RAWMIDI
+	select SND_PCM
+	help
+	  Say 'Y' or 'M' to include support for Tascam USB Audio/MIDI 
+	  interfaces or controllers US-122, US-224 and US-428.
+
 endmenu
 
diff -Nru a/sound/usb/Makefile b/sound/usb/Makefile
--- a/sound/usb/Makefile	2004-10-18 14:56:33 -07:00
+++ b/sound/usb/Makefile	2004-10-18 14:56:33 -07:00
@@ -2,7 +2,11 @@
 # Makefile for ALSA
 #
 
-snd-usb-audio-objs := usbaudio.o usbmixer.o usbmidi.o
+snd-usb-audio-objs := usbaudio.o usbmixer.o
+snd-usb-lib-objs := usbmidi.o
 
 # Toplevel Module Dependency
-obj-$(CONFIG_SND_USB_AUDIO) += snd-usb-audio.o
+obj-$(CONFIG_SND_USB_AUDIO) += snd-usb-audio.o snd-usb-lib.o
+obj-$(CONFIG_SND_USB_USX2Y) += snd-usb-lib.o
+
+obj-$(CONFIG_SND) += usx2y/
diff -Nru a/sound/usb/usbaudio.c b/sound/usb/usbaudio.c
--- a/sound/usb/usbaudio.c	2004-10-18 14:56:49 -07:00
+++ b/sound/usb/usbaudio.c	2004-10-18 14:56:49 -07:00
@@ -5,7 +5,7 @@
  *
  *   Copyright (c) 2002 by Takashi Iwai <tiwai@suse.de>
  *
- *   Many codes borrowed from audio.c by 
+ *   Many codes borrowed from audio.c by
  *	    Alan Cox (alan@lxorguk.ukuu.org.uk)
  *	    Thomas Sailer (sailer@ife.ee.ethz.ch)
  *
@@ -58,8 +58,7 @@
 MODULE_AUTHOR("Takashi Iwai <tiwai@suse.de>");
 MODULE_DESCRIPTION("USB Audio");
 MODULE_LICENSE("GPL");
-MODULE_CLASSES("{sound}");
-MODULE_DEVICES("{{Generic,USB Audio}}");
+MODULE_SUPPORTED_DEVICE("{{Generic,USB Audio}}");
 
 
 static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX;	/* Index 0-MAX */
@@ -73,25 +72,18 @@
 
 module_param_array(index, int, boot_devs, 0444);
 MODULE_PARM_DESC(index, "Index value for the USB audio adapter.");
-MODULE_PARM_SYNTAX(index, SNDRV_INDEX_DESC);
 module_param_array(id, charp, boot_devs, 0444);
 MODULE_PARM_DESC(id, "ID string for the USB audio adapter.");
-MODULE_PARM_SYNTAX(id, SNDRV_ID_DESC);
 module_param_array(enable, bool, boot_devs, 0444);
 MODULE_PARM_DESC(enable, "Enable USB audio adapter.");
-MODULE_PARM_SYNTAX(enable, SNDRV_ENABLE_DESC);
 module_param_array(vid, int, boot_devs, 0444);
 MODULE_PARM_DESC(vid, "Vendor ID for the USB audio device.");
-MODULE_PARM_SYNTAX(vid, SNDRV_ENABLED ",allows:{{-1,0xffff}},base:16");
 module_param_array(pid, int, boot_devs, 0444);
 MODULE_PARM_DESC(pid, "Product ID for the USB audio device.");
-MODULE_PARM_SYNTAX(pid, SNDRV_ENABLED ",allows:{{-1,0xffff}},base:16");
 module_param(nrpacks, int, 0444);
 MODULE_PARM_DESC(nrpacks, "Max. number of packets per URB.");
-MODULE_PARM_SYNTAX(nrpacks, SNDRV_ENABLED ",allows:{{1,10}}");
 module_param(async_unlink, bool, 0444);
 MODULE_PARM_DESC(async_unlink, "Use async unlink mode.");
-MODULE_PARM_SYNTAX(async_unlink, SNDRV_BOOLEAN_TRUE_DESC);
 
 
 /*
@@ -104,7 +96,7 @@
  *
  */
 
-#define MAX_PACKS	10	
+#define MAX_PACKS	10
 #define MAX_PACKS_HS	(MAX_PACKS * 8)	/* in high speed mode */
 #define MAX_URBS	5	/* max. 20ms long packets */
 #define SYNC_URBS	2	/* always two urbs for sync */
@@ -207,8 +199,6 @@
 	struct list_head list;
 };
 
-#define chip_t snd_usb_stream_t
-
 
 /*
  * we keep the snd_usb_audio_t instances by ourselves for merging
@@ -354,7 +344,7 @@
 	if (! urb->bandwidth) {
 		int bustime;
 		bustime = usb_check_bandwidth(urb->dev, urb);
-		if (bustime < 0) 
+		if (bustime < 0)
 			return bustime;
 		printk("urb %d: bandwidth = %d (packets = %d)\n", ctx->index, bustime, urb->number_of_packets);
 		usb_claim_bandwidth(urb->dev, urb, bustime, 1);
@@ -826,7 +816,7 @@
 }
 
 
-/* 
+/*
  *  wait until all urbs are processed.
  */
 static int wait_clear_urbs(snd_usb_substream_t *subs)
@@ -1148,7 +1138,7 @@
 	if (fmt->attributes & EP_CS_ATTR_PITCH_CONTROL) {
 		data[0] = 1;
 		if ((err = snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), SET_CUR,
-					   USB_TYPE_CLASS|USB_RECIP_ENDPOINT|USB_DIR_OUT, 
+					   USB_TYPE_CLASS|USB_RECIP_ENDPOINT|USB_DIR_OUT,
 					   PITCH_CONTROL << 8, ep, data, 1, HZ)) < 0) {
 			snd_printk(KERN_ERR "%d:%d:%d: cannot set enable PITCH\n",
 				   dev->devnum, iface, ep);
@@ -1174,7 +1164,7 @@
 		data[1] = rate >> 8;
 		data[2] = rate >> 16;
 		if ((err = snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), SET_CUR,
-					   USB_TYPE_CLASS|USB_RECIP_ENDPOINT|USB_DIR_OUT, 
+					   USB_TYPE_CLASS|USB_RECIP_ENDPOINT|USB_DIR_OUT,
 					   SAMPLING_FREQ_CONTROL << 8, ep, data, 3, HZ)) < 0) {
 			snd_printk(KERN_ERR "%d:%d:%d: cannot set freq %d to ep 0x%x\n",
 				   dev->devnum, iface, fmt->altsetting, rate, ep);
@@ -1183,9 +1173,9 @@
 		if ((err = snd_usb_ctl_msg(dev, usb_rcvctrlpipe(dev, 0), GET_CUR,
 					   USB_TYPE_CLASS|USB_RECIP_ENDPOINT|USB_DIR_IN,
 					   SAMPLING_FREQ_CONTROL << 8, ep, data, 3, HZ)) < 0) {
-			snd_printk(KERN_ERR "%d:%d:%d: cannot get freq at ep 0x%x\n",
+			snd_printk(KERN_WARNING "%d:%d:%d: cannot get freq at ep 0x%x\n",
 				   dev->devnum, iface, fmt->altsetting, ep);
-			return err;
+			return 0; /* some devices don't support reading */
 		}
 		crate = data[0] | (data[1] << 8) | (data[2] << 16);
 		if (crate != rate) {
@@ -1323,7 +1313,7 @@
 	ret = snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(hw_params));
 	if (ret < 0)
 		return ret;
-	
+
 	format = params_format(hw_params);
 	rate = params_rate(hw_params);
 	channels = params_channels(hw_params);
@@ -1482,7 +1472,7 @@
 	snd_interval_t *it = hw_param_interval(params, SNDRV_PCM_HW_PARAM_RATE);
 	unsigned int rmin, rmax;
 	int changed;
-	
+
 	hwc_debug("hw_rule_rate: (%d,%d)\n", it->min, it->max);
 	changed = 0;
 	rmin = rmax = 0;
@@ -1536,7 +1526,7 @@
 	snd_interval_t *it = hw_param_interval(params, SNDRV_PCM_HW_PARAM_CHANNELS);
 	unsigned int rmin, rmax;
 	int changed;
-	
+
 	hwc_debug("hw_rule_channels: (%d,%d)\n", it->min, it->max);
 	changed = 0;
 	rmin = rmax = 0;
@@ -1590,7 +1580,7 @@
 	u64 fbits;
 	u32 oldbits[2];
 	int changed;
-	
+
 	hwc_debug("hw_rule_format: %x:%x\n", fmt->bits[0], fmt->bits[1]);
 	fbits = 0;
 	list_for_each(p, &subs->fmt_list) {
@@ -1734,13 +1724,13 @@
 
 	if (check_hw_params_convention(subs)) {
 		hwc_debug("setting extra hw constraints...\n");
-		if ((err = snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_RATE, 
+		if ((err = snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_RATE,
 					       hw_rule_rate, subs,
 					       SNDRV_PCM_HW_PARAM_FORMAT,
 					       SNDRV_PCM_HW_PARAM_CHANNELS,
 					       -1)) < 0)
 			return err;
-		if ((err = snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS, 
+		if ((err = snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS,
 					       hw_rule_channels, subs,
 					       SNDRV_PCM_HW_PARAM_FORMAT,
 					       SNDRV_PCM_HW_PARAM_RATE,
@@ -2001,8 +1991,8 @@
 
 static void proc_pcm_format_read(snd_info_entry_t *entry, snd_info_buffer_t *buffer)
 {
-	snd_usb_stream_t *stream = snd_magic_cast(snd_usb_stream_t, entry->private_data, return);
-	
+	snd_usb_stream_t *stream = entry->private_data;
+
 	snd_iprintf(buffer, "%s : %s\n", stream->chip->card->longname, stream->pcm->name);
 
 	if (stream->substream[SNDRV_PCM_STREAM_PLAYBACK].num_formats) {
@@ -2089,7 +2079,7 @@
 	free_substream(&stream->substream[0]);
 	free_substream(&stream->substream[1]);
 	list_del(&stream->list);
-	snd_magic_kfree(stream);
+	kfree(stream);
 }
 
 static void snd_usb_audio_pcm_free(snd_pcm_t *pcm)
@@ -2146,7 +2136,7 @@
 	}
 
 	/* create a new pcm */
-	as = snd_magic_kmalloc(snd_usb_stream_t, 0, GFP_KERNEL);
+	as = kmalloc(sizeof(*as), GFP_KERNEL);
 	if (! as)
 		return -ENOMEM;
 	memset(as, 0, sizeof(*as));
@@ -2158,13 +2148,13 @@
 			  stream == SNDRV_PCM_STREAM_PLAYBACK ? 0 : 1,
 			  &pcm);
 	if (err < 0) {
-		snd_magic_kfree(as);
+		kfree(as);
 		return err;
 	}
 	as->pcm = pcm;
 	pcm->private_data = as;
 	pcm->private_free = snd_usb_audio_pcm_free;
-	pcm->info_flags = SNDRV_PCM_INFO_NONATOMIC_OPS;
+	pcm->info_flags = 0;
 	if (chip->pcm_devs > 0)
 		sprintf(pcm->name, "USB Audio #%d", chip->pcm_devs);
 	else
@@ -2182,6 +2172,24 @@
 
 
 /*
+ * check if the device uses big-endian samples
+ */
+static int is_big_endian_format(struct usb_device *dev, struct audioformat *fp)
+{
+	/* M-Audio */
+	if (dev->descriptor.idVendor == 0x0763) {
+		/* Quattro: captured data only */
+		if (dev->descriptor.idProduct == 0x2001 &&
+		    fp->endpoint & USB_DIR_IN)
+			return 1;
+		/* Audiophile USB */
+		if (dev->descriptor.idProduct == 0x2003)
+			return 1;
+	}
+	return 0;
+}
+
+/*
  * parse the audio format type I descriptor
  * and returns the corresponding pcm format
  *
@@ -2217,17 +2225,13 @@
 			pcm_format = SNDRV_PCM_FORMAT_S8;
 			break;
 		case 2:
-			/* M-Audio audiophile USB workaround */
-			if (dev->descriptor.idVendor == 0x0763 &&
-			    dev->descriptor.idProduct == 0x2003)
+			if (is_big_endian_format(dev, fp))
 				pcm_format = SNDRV_PCM_FORMAT_S16_BE; /* grrr, big endian!! */
 			else
 				pcm_format = SNDRV_PCM_FORMAT_S16_LE;
 			break;
 		case 3:
-			/* M-Audio audiophile USB workaround */
-			if (dev->descriptor.idVendor == 0x0763 &&
-			    dev->descriptor.idProduct == 0x2003)
+			if (is_big_endian_format(dev, fp))
 				pcm_format = SNDRV_PCM_FORMAT_S24_3BE; /* grrr, big endian!! */
 			else
 				pcm_format = SNDRV_PCM_FORMAT_S24_3LE;
@@ -2281,7 +2285,7 @@
 {
 	int nr_rates = fmt[offset];
 	if (fmt[0] < offset + 1 + 3 * (nr_rates ? nr_rates : 2)) {
-		snd_printk(KERN_ERR "%d:%u:%d : invalid FORMAT_TYPE desc\n", 
+		snd_printk(KERN_ERR "%d:%u:%d : invalid FORMAT_TYPE desc\n",
 				   dev->devnum, fp->iface, fp->altsetting);
 		return -1;
 	}
@@ -2419,7 +2423,7 @@
 	}
 #endif
 	return 0;
-}	
+}
 
 static int parse_audio_endpoints(snd_usb_audio_t *chip, int iface_no)
 {
@@ -2465,22 +2469,22 @@
 		}
 
 		if (fmt[0] < 7) {
-			snd_printk(KERN_ERR "%d:%u:%d : invalid AS_GENERAL desc\n", 
+			snd_printk(KERN_ERR "%d:%u:%d : invalid AS_GENERAL desc\n",
 				   dev->devnum, iface_no, altno);
 			continue;
 		}
 
 		format = (fmt[6] << 8) | fmt[5]; /* remember the format value */
-			
+
 		/* get format type */
 		fmt = snd_usb_find_csint_desc(alts->extra, alts->extralen, NULL, FORMAT_TYPE);
 		if (!fmt) {
-			snd_printk(KERN_ERR "%d:%u:%d : no FORMAT_TYPE desc\n", 
+			snd_printk(KERN_ERR "%d:%u:%d : no FORMAT_TYPE desc\n",
 				   dev->devnum, iface_no, altno);
 			continue;
 		}
 		if (fmt[0] < 8) {
-			snd_printk(KERN_ERR "%d:%u:%d : invalid FORMAT_TYPE desc\n", 
+			snd_printk(KERN_ERR "%d:%u:%d : invalid FORMAT_TYPE desc\n",
 				   dev->devnum, iface_no, altno);
 			continue;
 		}
@@ -2490,7 +2494,7 @@
 		if (!csep && altsd->bNumEndpoints >= 2)
 			csep = snd_usb_find_desc(alts->endpoint[1].extra, alts->endpoint[1].extralen, NULL, USB_DT_CS_ENDPOINT);
 		if (!csep || csep[0] < 7 || csep[2] != EP_GENERAL) {
-			snd_printk(KERN_ERR "%d:%u:%d : no or invalid class specific endpoint descriptor\n", 
+			snd_printk(KERN_ERR "%d:%u:%d : no or invalid class specific endpoint descriptor\n",
 				   dev->devnum, iface_no, altno);
 			continue;
 		}
@@ -2920,14 +2924,14 @@
  */
 static void proc_audio_usbbus_read(snd_info_entry_t *entry, snd_info_buffer_t *buffer)
 {
-	snd_usb_audio_t *chip = snd_magic_cast(snd_usb_audio_t, entry->private_data, return);
+	snd_usb_audio_t *chip = entry->private_data;
 	if (! chip->shutdown)
 		snd_iprintf(buffer, "%03d/%03d\n", chip->dev->bus->busnum, chip->dev->devnum);
 }
 
 static void proc_audio_usbid_read(snd_info_entry_t *entry, snd_info_buffer_t *buffer)
 {
-	snd_usb_audio_t *chip = snd_magic_cast(snd_usb_audio_t, entry->private_data, return);
+	snd_usb_audio_t *chip = entry->private_data;
 	if (! chip->shutdown)
 		snd_iprintf(buffer, "%04x:%04x\n", chip->dev->descriptor.idVendor, chip->dev->descriptor.idProduct);
 }
@@ -2950,13 +2954,13 @@
 
 static int snd_usb_audio_free(snd_usb_audio_t *chip)
 {
-	snd_magic_kfree(chip);
+	kfree(chip);
 	return 0;
 }
 
 static int snd_usb_audio_dev_free(snd_device_t *device)
 {
-	snd_usb_audio_t *chip = snd_magic_cast(snd_usb_audio_t, device->device_data, return -ENXIO);
+	snd_usb_audio_t *chip = device->device_data;
 	return snd_usb_audio_free(chip);
 }
 
@@ -2975,7 +2979,7 @@
 	static snd_device_ops_t ops = {
 		.dev_free =	snd_usb_audio_dev_free,
 	};
-	
+
 	*rchip = NULL;
 
 	if (snd_usb_get_speed(dev) != USB_SPEED_FULL &&
@@ -2990,7 +2994,7 @@
 		return -ENOMEM;
 	}
 
-	chip = snd_magic_kcalloc(snd_usb_audio_t, 0, GFP_KERNEL);
+	chip = kcalloc(1, sizeof(*chip), GFP_KERNEL);
 	if (! chip) {
 		snd_card_free(card);
 		return -ENOMEM;
@@ -3171,7 +3175,7 @@
 
 /*
  * we need to take care of counter, since disconnection can be called also
- * many times as well as usb_audio_probe(). 
+ * many times as well as usb_audio_probe().
  */
 static void snd_usb_audio_disconnect(struct usb_device *dev, void *ptr)
 {
@@ -3182,7 +3186,7 @@
 	if (ptr == (void *)-1L)
 		return;
 
-	chip = snd_magic_cast(snd_usb_audio_t, ptr, return);
+	chip = ptr;
 	card = chip->card;
 	down(&register_mutex);
 	chip->shutdown = 1;
diff -Nru a/sound/usb/usbaudio.h b/sound/usb/usbaudio.h
--- a/sound/usb/usbaudio.h	2004-10-18 14:56:33 -07:00
+++ b/sound/usb/usbaudio.h	2004-10-18 14:56:33 -07:00
@@ -124,7 +124,6 @@
 typedef struct snd_usb_audio snd_usb_audio_t;
 
 struct snd_usb_audio {
-	
 	int index;
 	struct usb_device *dev;
 	snd_card_t *card;
@@ -138,15 +137,17 @@
 	int next_midi_device;
 
 	unsigned int ignore_ctl_error;	/* for mixer */
-};  
+};
 
 /*
  * Information about devices with broken descriptors
  */
 
+/* special values for .ifnum */
 #define QUIRK_NO_INTERFACE		-2
 #define QUIRK_ANY_INTERFACE		-1
 
+/* quirk type */
 #define QUIRK_MIDI_FIXED_ENDPOINT	0
 #define QUIRK_MIDI_YAMAHA		1
 #define QUIRK_MIDI_MIDIMAN		2
@@ -205,6 +206,8 @@
 int snd_usb_create_mixer(snd_usb_audio_t *chip, int ctrlif);
 
 int snd_usb_create_midi_interface(snd_usb_audio_t *chip, struct usb_interface *iface, const snd_usb_audio_quirk_t *quirk);
+void snd_usbmidi_input_stop(struct list_head* p);
+void snd_usbmidi_input_start(struct list_head* p);
 void snd_usbmidi_disconnect(struct list_head *p, struct usb_driver *driver);
 
 /*
diff -Nru a/sound/usb/usbmidi.c b/sound/usb/usbmidi.c
--- a/sound/usb/usbmidi.c	2004-10-18 14:57:03 -07:00
+++ b/sound/usb/usbmidi.c	2004-10-18 14:57:03 -07:00
@@ -49,6 +49,11 @@
 #include <sound/rawmidi.h>
 #include "usbaudio.h"
 
+MODULE_AUTHOR("Clemens Ladisch <clemens@ladisch.de>");
+MODULE_DESCRIPTION("USB Audio/MIDI helper module");
+MODULE_LICENSE("Dual BSD/GPL");
+
+
 struct usb_ms_header_descriptor {
 	__u8  bLength;
 	__u8  bDescriptorType;
@@ -175,7 +180,7 @@
  */
 static void snd_usbmidi_in_urb_complete(struct urb* urb, struct pt_regs *regs)
 {
-	snd_usb_midi_in_endpoint_t* ep = snd_magic_cast(snd_usb_midi_in_endpoint_t, urb->context, return);
+	snd_usb_midi_in_endpoint_t* ep = urb->context;
 
 	if (urb->status == 0) {
 		uint8_t* buffer = (uint8_t*)ep->urb->transfer_buffer;
@@ -229,7 +234,7 @@
 
 static void snd_usbmidi_out_urb_complete(struct urb* urb, struct pt_regs *regs)
 {
-	snd_usb_midi_out_endpoint_t* ep = snd_magic_cast(snd_usb_midi_out_endpoint_t, urb->context, return);
+	snd_usb_midi_out_endpoint_t* ep = urb->context;
 
 	if (urb->status < 0) {
 		if (snd_usbmidi_urb_error(urb->status) < 0)
@@ -393,7 +398,7 @@
 	int p;
 	struct urb* urb = ep->urb;
 	unsigned long flags;
-	
+
 	spin_lock_irqsave(&ep->buffer_lock, flags);
 	if (urb->status == -EINPROGRESS || ep->umidi->chip->shutdown) {
 		spin_unlock_irqrestore(&ep->buffer_lock, flags);
@@ -417,14 +422,14 @@
 
 static void snd_usbmidi_out_tasklet(unsigned long data)
 {
-	snd_usb_midi_out_endpoint_t* ep = snd_magic_cast(snd_usb_midi_out_endpoint_t, (void*)data, return);
-	
+	snd_usb_midi_out_endpoint_t* ep = (snd_usb_midi_out_endpoint_t *) data;
+
 	snd_usbmidi_do_output(ep);
 }
 
 static int snd_usbmidi_output_open(snd_rawmidi_substream_t* substream)
 {
-	snd_usb_midi_t* umidi = snd_magic_cast(snd_usb_midi_t, substream->rmidi->private_data, return -ENXIO);
+	snd_usb_midi_t* umidi = substream->rmidi->private_data;
 	usbmidi_out_port_t* port = NULL;
 	int i, j;
 
@@ -503,7 +508,7 @@
 			kfree(ep->urb->transfer_buffer);
 		usb_free_urb(ep->urb);
 	}
-	snd_magic_kfree(ep);
+	kfree(ep);
 }
 
 /*
@@ -571,7 +576,7 @@
 	int length;
 
 	rep->in = NULL;
-	ep = snd_magic_kcalloc(snd_usb_midi_in_endpoint_t, 0, GFP_KERNEL);
+	ep = kcalloc(1, sizeof(*ep), GFP_KERNEL);
 	if (!ep)
 		return -ENOMEM;
 	ep->umidi = umidi;
@@ -631,7 +636,7 @@
 			kfree(ep->urb->transfer_buffer);
 		usb_free_urb(ep->urb);
 	}
-	snd_magic_kfree(ep);
+	kfree(ep);
 }
 
 /*
@@ -647,7 +652,7 @@
 	void* buffer;
 
 	rep->out = NULL;
-	ep = snd_magic_kcalloc(snd_usb_midi_out_endpoint_t, 0, GFP_KERNEL);
+	ep = kcalloc(1, sizeof(*ep), GFP_KERNEL);
 	if (!ep)
 		return -ENOMEM;
 	ep->umidi = umidi;
@@ -695,7 +700,7 @@
 		if (ep->in)
 			snd_usbmidi_in_endpoint_delete(ep->in);
 	}
-	snd_magic_kfree(umidi);
+	kfree(umidi);
 }
 
 /*
@@ -718,7 +723,7 @@
 
 static void snd_usbmidi_rawmidi_free(snd_rawmidi_t* rmidi)
 {
-	snd_usb_midi_t* umidi = snd_magic_cast(snd_usb_midi_t, rmidi->private_data, return);
+	snd_usb_midi_t* umidi = rmidi->private_data;
 	snd_usbmidi_free(umidi);
 }
 
@@ -964,7 +969,7 @@
  * If the endpoints aren't specified, use the first bulk endpoints in the
  * first alternate setting of the interface.
  */
-static int snd_usbmidi_detect_endpoint(snd_usb_midi_t* umidi, 
+static int snd_usbmidi_detect_endpoint(snd_usb_midi_t* umidi,
 				       snd_usb_midi_endpoint_info_t* endpoint)
 {
 	struct usb_interface* intf;
@@ -998,7 +1003,7 @@
 /*
  * Detects the endpoints and ports of Yamaha devices.
  */
-static int snd_usbmidi_detect_yamaha(snd_usb_midi_t* umidi, 
+static int snd_usbmidi_detect_yamaha(snd_usb_midi_t* umidi,
 				     snd_usb_midi_endpoint_info_t* endpoint)
 {
 	struct usb_interface* intf;
@@ -1145,6 +1150,44 @@
 }
 
 /*
+ * Temporarily stop input.
+ */
+void snd_usbmidi_input_stop(struct list_head* p)
+{
+	snd_usb_midi_t* umidi;
+	int i;
+
+	umidi = list_entry(p, snd_usb_midi_t, list);
+	for (i = 0; i < MIDI_MAX_ENDPOINTS; ++i) {
+		snd_usb_midi_endpoint_t* ep = &umidi->endpoints[i];
+		if (ep->in)
+			usb_unlink_urb(ep->in->urb);
+	}
+}
+
+static void snd_usbmidi_input_start_ep(snd_usb_midi_in_endpoint_t* ep)
+{
+	if (ep) {
+		struct urb* urb = ep->urb;
+		urb->dev = ep->umidi->chip->dev;
+		snd_usbmidi_submit_urb(urb, GFP_KERNEL);
+	}
+}
+
+/*
+ * Resume input after a call to snd_usbmidi_input_stop().
+ */
+void snd_usbmidi_input_start(struct list_head* p)
+{
+	snd_usb_midi_t* umidi;
+	int i;
+
+	umidi = list_entry(p, snd_usb_midi_t, list);
+	for (i = 0; i < MIDI_MAX_ENDPOINTS; ++i)
+		snd_usbmidi_input_start_ep(umidi->endpoints[i].in);
+}
+
+/*
  * Creates and registers everything needed for a MIDI streaming interface.
  */
 int snd_usb_create_midi_interface(snd_usb_audio_t* chip,
@@ -1156,7 +1199,7 @@
 	int out_ports, in_ports;
 	int i, err;
 
-	umidi = snd_magic_kcalloc(snd_usb_midi_t, 0, GFP_KERNEL);
+	umidi = kcalloc(1, sizeof(*umidi), GFP_KERNEL);
 	if (!umidi)
 		return -ENOMEM;
 	umidi->chip = chip;
@@ -1189,7 +1232,7 @@
 		}
 	}
 	if (err < 0) {
-		snd_magic_kfree(umidi);
+		kfree(umidi);
 		return err;
 	}
 
@@ -1202,7 +1245,7 @@
 	}
 	err = snd_usbmidi_create_rawmidi(umidi, out_ports, in_ports);
 	if (err < 0) {
-		snd_magic_kfree(umidi);
+		kfree(umidi);
 		return err;
 	}
 
@@ -1219,8 +1262,11 @@
 	list_add(&umidi->list, &umidi->chip->midi_list);
 
 	for (i = 0; i < MIDI_MAX_ENDPOINTS; ++i)
-		if (umidi->endpoints[i].in)
-			snd_usbmidi_submit_urb(umidi->endpoints[i].in->urb,
-					       GFP_KERNEL);
+		snd_usbmidi_input_start_ep(umidi->endpoints[i].in);
 	return 0;
 }
+
+EXPORT_SYMBOL(snd_usb_create_midi_interface);
+EXPORT_SYMBOL(snd_usbmidi_input_stop);
+EXPORT_SYMBOL(snd_usbmidi_input_start);
+EXPORT_SYMBOL(snd_usbmidi_disconnect);
diff -Nru a/sound/usb/usbmixer.c b/sound/usb/usbmixer.c
--- a/sound/usb/usbmixer.c	2004-10-18 14:56:28 -07:00
+++ b/sound/usb/usbmixer.c	2004-10-18 14:56:28 -07:00
@@ -5,7 +5,7 @@
  *
  *   Copyright (c) 2002 by Takashi Iwai <tiwai@suse.de>
  *
- *   Many codes borrowed from audio.c by 
+ *   Many codes borrowed from audio.c by
  *	    Alan Cox (alan@lxorguk.ukuu.org.uk)
  *	    Thomas Sailer (sailer@ife.ee.ethz.ch)
  *
@@ -77,7 +77,7 @@
 	unsigned int ctrlif;
 	unsigned int id;
 	unsigned int control;	/* CS or ICN (high byte) */
-	unsigned int cmask; /* channel mask bitmap: 0 = master */ 
+	unsigned int cmask; /* channel mask bitmap: 0 = master */
 	int channels;
 	int val_type;
 	int min, max, res;
@@ -299,7 +299,7 @@
 	unsigned char buf[2];
 	int val_len = cval->val_type >= USB_MIXER_S16 ? 2 : 1;
 	int timeout = 10;
- 
+
 	while (timeout-- > 0) {
 		if (snd_usb_ctl_msg(cval->chip->dev, usb_rcvctrlpipe(cval->chip->dev, 0),
 				    request,
@@ -334,7 +334,7 @@
 	unsigned char buf[2];
 	int val_len = cval->val_type >= USB_MIXER_S16 ? 2 : 1;
 	int timeout = 10;
- 
+
 	value_set = convert_bytes_value(cval, value_set);
 	buf[0] = value_set & 0xff;
 	buf[1] = (value_set >> 8) & 0xff;
@@ -361,7 +361,7 @@
 
 
 /*
- * parser routines begin here... 
+ * parser routines begin here...
  */
 
 static int parse_audio_unit(mixer_build_t *state, int unitid);
@@ -443,7 +443,7 @@
 	{ 0x0712, "Multi-Track Recorder" },
 	{ 0x0713, "Synthesizer" },
 	{ 0 },
-};	
+};
 
 static int get_term_name(mixer_build_t *state, usb_audio_term_t *iterm,
 			 unsigned char *name, int maxlen, int term_only)
@@ -573,7 +573,7 @@
 static void usb_mixer_elem_free(snd_kcontrol_t *kctl)
 {
 	if (kctl->private_data) {
-		snd_magic_kfree((void *)kctl->private_data);
+		kfree((void *)kctl->private_data);
 		kctl->private_data = NULL;
 	}
 }
@@ -615,7 +615,7 @@
 			cval->res = 1;
 		} else {
 			int last_valid_res = cval->res;
-		
+
 			while (cval->res > 1) {
 				if (set_ctl_value(cval, SET_RES, (cval->control << 8) | minchn, cval->res / 2) < 0)
 					break;
@@ -634,8 +634,8 @@
 
 /* get a feature/mixer unit info */
 static int mixer_ctl_feature_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo)
-{	
-	usb_mixer_elem_info_t *cval = snd_magic_cast(usb_mixer_elem_info_t, kcontrol->private_data, return -EINVAL);
+{
+	usb_mixer_elem_info_t *cval = kcontrol->private_data;
 
 	if (cval->val_type == USB_MIXER_BOOLEAN ||
 	    cval->val_type == USB_MIXER_INV_BOOLEAN)
@@ -659,7 +659,7 @@
 /* get the current value from feature/mixer unit */
 static int mixer_ctl_feature_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
 {
-	usb_mixer_elem_info_t *cval = snd_magic_cast(usb_mixer_elem_info_t, kcontrol->private_data, return -EINVAL);
+	usb_mixer_elem_info_t *cval = kcontrol->private_data;
 	int c, cnt, val, err;
 
 	if (cval->cmask) {
@@ -700,7 +700,7 @@
 /* put the current value to feature/mixer unit */
 static int mixer_ctl_feature_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
 {
-	usb_mixer_elem_info_t *cval = snd_magic_cast(usb_mixer_elem_info_t, kcontrol->private_data, return -EINVAL);
+	usb_mixer_elem_info_t *cval = kcontrol->private_data;
 	int c, cnt, val, oval, err;
 	int changed = 0;
 
@@ -774,7 +774,7 @@
 	if (check_ignored_ctl(state, unitid, control))
 		return;
 
-	cval = snd_magic_kcalloc(usb_mixer_elem_info_t, 0, GFP_KERNEL);
+	cval = kcalloc(1, sizeof(*cval), GFP_KERNEL);
 	if (! cval) {
 		snd_printk(KERN_ERR "cannot malloc kcontrol\n");
 		return;
@@ -801,7 +801,7 @@
 	kctl = snd_ctl_new1(&usb_feature_unit_ctl, cval);
 	if (! kctl) {
 		snd_printk(KERN_ERR "cannot malloc kcontrol\n");
-		snd_magic_kfree(cval);
+		kfree(cval);
 		return;
 	}
 	kctl->private_free = usb_mixer_elem_free;
@@ -914,7 +914,7 @@
 		if (master_bits & (1 << i))
 			build_feature_ctl(state, ftr, 0, i, &iterm, unitid);
 	}
-	
+
 	return 0;
 }
 
@@ -943,7 +943,7 @@
 	if (check_ignored_ctl(state, unitid, 0))
 		return;
 
-	cval = snd_magic_kcalloc(usb_mixer_elem_info_t, 0, GFP_KERNEL);
+	cval = kcalloc(1, sizeof(*cval), GFP_KERNEL);
 	if (! cval)
 		return;
 
@@ -968,7 +968,7 @@
 	kctl = snd_ctl_new1(&usb_feature_unit_ctl, cval);
 	if (! kctl) {
 		snd_printk(KERN_ERR "cannot malloc kcontrol\n");
-		snd_magic_kfree(cval);
+		kfree(cval);
 		return;
 	}
 	kctl->private_free = usb_mixer_elem_free;
@@ -1014,7 +1014,7 @@
 /* get callback for processing/extension unit */
 static int mixer_ctl_procunit_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
 {
-	usb_mixer_elem_info_t *cval = snd_magic_cast(usb_mixer_elem_info_t, kcontrol->private_data, return -EINVAL);
+	usb_mixer_elem_info_t *cval = kcontrol->private_data;
 	int err, val;
 
 	err = get_cur_ctl_value(cval, cval->control << 8, &val);
@@ -1032,7 +1032,7 @@
 /* put callback for processing/extension unit */
 static int mixer_ctl_procunit_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
 {
-	usb_mixer_elem_info_t *cval = snd_magic_cast(usb_mixer_elem_info_t, kcontrol->private_data, return -EINVAL);
+	usb_mixer_elem_info_t *cval = kcontrol->private_data;
 	int val, oval, err;
 
 	err = get_cur_ctl_value(cval, cval->control << 8, &oval);
@@ -1170,7 +1170,7 @@
 			continue;
 		if (check_ignored_ctl(state, unitid, valinfo->control))
 			continue;
-		cval = snd_magic_kcalloc(usb_mixer_elem_info_t, 0, GFP_KERNEL);
+		cval = kcalloc(1, sizeof(*cval), GFP_KERNEL);
 		if (! cval) {
 			snd_printk(KERN_ERR "cannot malloc kcontrol\n");
 			return -ENOMEM;
@@ -1195,7 +1195,7 @@
 		kctl = snd_ctl_new1(&mixer_procunit_ctl, cval);
 		if (! kctl) {
 			snd_printk(KERN_ERR "cannot malloc kcontrol\n");
-			snd_magic_kfree(cval);
+			kfree(cval);
 			return -ENOMEM;
 		}
 		kctl->private_free = usb_mixer_elem_free;
@@ -1243,8 +1243,8 @@
  * use an enumerator type for routing
  */
 static int mixer_ctl_selector_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo)
-{	
-	usb_mixer_elem_info_t *cval = snd_magic_cast(usb_mixer_elem_info_t, kcontrol->private_data, return -EINVAL);
+{
+	usb_mixer_elem_info_t *cval = kcontrol->private_data;
 	char **itemlist = (char **)kcontrol->private_value;
 
 	snd_assert(itemlist, return -EINVAL);
@@ -1260,7 +1260,7 @@
 /* get callback for selector unit */
 static int mixer_ctl_selector_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
 {
-	usb_mixer_elem_info_t *cval = snd_magic_cast(usb_mixer_elem_info_t, kcontrol->private_data, return -EINVAL);
+	usb_mixer_elem_info_t *cval = kcontrol->private_data;
 	int val, err;
 
 	err = get_cur_ctl_value(cval, 0, &val);
@@ -1279,7 +1279,7 @@
 /* put callback for selector unit */
 static int mixer_ctl_selector_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
 {
-	usb_mixer_elem_info_t *cval = snd_magic_cast(usb_mixer_elem_info_t, kcontrol->private_data, return -EINVAL);
+	usb_mixer_elem_info_t *cval = kcontrol->private_data;
 	int val, oval, err;
 
 	err = get_cur_ctl_value(cval, 0, &oval);
@@ -1315,9 +1315,9 @@
 	int i, num_ins = 0;
 
 	if (kctl->private_data) {
-		usb_mixer_elem_info_t *cval = snd_magic_cast(usb_mixer_elem_info_t, kctl->private_data,);
+		usb_mixer_elem_info_t *cval = kctl->private_data;
 		num_ins = cval->max;
-		snd_magic_kfree(cval);
+		kfree(cval);
 		kctl->private_data = NULL;
 	}
 	if (kctl->private_value) {
@@ -1357,7 +1357,7 @@
 	if (check_ignored_ctl(state, unitid, 0))
 		return 0;
 
-	cval = snd_magic_kcalloc(usb_mixer_elem_info_t, 0, GFP_KERNEL);
+	cval = kcalloc(1, sizeof(*cval), GFP_KERNEL);
 	if (! cval) {
 		snd_printk(KERN_ERR "cannot malloc kcontrol\n");
 		return -ENOMEM;
@@ -1375,7 +1375,7 @@
 	namelist = kmalloc(sizeof(char *) * num_ins, GFP_KERNEL);
 	if (! namelist) {
 		snd_printk(KERN_ERR "cannot malloc\n");
-		snd_magic_kfree(cval);
+		kfree(cval);
 		return -ENOMEM;
 	}
 #define MAX_ITEM_NAME_LEN	64
@@ -1388,7 +1388,7 @@
 			while (--i > 0)
 				kfree(namelist[i]);
 			kfree(namelist);
-			snd_magic_kfree(cval);
+			kfree(cval);
 			return -ENOMEM;
 		}
 		if (check_input_term(state, desc[5 + i], &iterm) >= 0)
@@ -1400,7 +1400,7 @@
 	kctl = snd_ctl_new1(&mixer_selectunit_ctl, cval);
 	if (! kctl) {
 		snd_printk(KERN_ERR "cannot malloc kcontrol\n");
-		snd_magic_kfree(cval);
+		kfree(cval);
 		return -ENOMEM;
 	}
 	kctl->private_value = (unsigned long)namelist;
diff -Nru a/sound/usb/usbmixer_maps.c b/sound/usb/usbmixer_maps.c
--- a/sound/usb/usbmixer_maps.c	2004-10-18 14:57:04 -07:00
+++ b/sound/usb/usbmixer_maps.c	2004-10-18 14:57:04 -07:00
@@ -32,7 +32,7 @@
 	const struct usbmix_name_map *map;
 	int ignore_ctl_error;
 };
-	
+
 /*
  * USB control mappers for SB Exitigy
  */
diff -Nru a/sound/usb/usbquirks.h b/sound/usb/usbquirks.h
--- a/sound/usb/usbquirks.h	2004-10-18 14:56:29 -07:00
+++ b/sound/usb/usbquirks.h	2004-10-18 14:56:29 -07:00
@@ -91,6 +91,31 @@
 YAMAHA_DEVICE(0x1021, "MOTIF ES 6"),
 YAMAHA_DEVICE(0x1022, "MOTIF ES 7"),
 YAMAHA_DEVICE(0x1023, "MOTIF ES 8"),
+YAMAHA_DEVICE(0x1024, "CVP-301"),
+YAMAHA_DEVICE(0x1025, "CVP-303"),
+YAMAHA_DEVICE(0x1026, "CVP-305"),
+YAMAHA_DEVICE(0x1027, "CVP-307"),
+YAMAHA_DEVICE(0x1028, "CVP-309"),
+YAMAHA_DEVICE(0x1029, "CVP-309GP"),
+YAMAHA_DEVICE(0x102a, "PSR-1500"),
+YAMAHA_DEVICE(0x102b, "PSR-3000"),
+YAMAHA_DEVICE(0x102e, "ELS-01/01C"),
+YAMAHA_DEVICE(0x1030, "PSR-295/293"),
+YAMAHA_DEVICE(0x1031, "DGX-205/203"),
+YAMAHA_DEVICE(0x1032, "DGX-305"),
+YAMAHA_DEVICE(0x1033, "DGX-505"),
+YAMAHA_DEVICE(0x1034, NULL),
+YAMAHA_DEVICE(0x1035, NULL),
+YAMAHA_DEVICE(0x1036, NULL),
+YAMAHA_DEVICE(0x1037, NULL),
+YAMAHA_DEVICE(0x1038, NULL),
+YAMAHA_DEVICE(0x1039, NULL),
+YAMAHA_DEVICE(0x103a, NULL),
+YAMAHA_DEVICE(0x103b, NULL),
+YAMAHA_DEVICE(0x103c, NULL),
+YAMAHA_DEVICE(0x2000, "DGP-7"),
+YAMAHA_DEVICE(0x2001, "DGP-5"),
+YAMAHA_DEVICE(0x2002, NULL),
 YAMAHA_DEVICE(0x5000, "CS1D"),
 YAMAHA_DEVICE(0x5001, "DSP1D"),
 YAMAHA_DEVICE(0x5002, "DME32"),
@@ -100,6 +125,11 @@
 YAMAHA_DEVICE(0x5006, "NHB32-C"),
 YAMAHA_DEVICE(0x5007, "DM1000"),
 YAMAHA_DEVICE(0x5008, "01V96"),
+YAMAHA_DEVICE(0x500a, "PM5D"),
+YAMAHA_DEVICE(0x500b, "DME64N"),
+YAMAHA_DEVICE(0x500c, "DME24N"),
+YAMAHA_DEVICE(0x7000, "DTX"),
+YAMAHA_DEVICE(0x7010, "UB99"),
 #undef YAMAHA_DEVICE
 #undef YAMAHA_INTERFACE
 
@@ -267,7 +297,8 @@
 	}
 },
 {
-	/* thanks to Emiliano Grilli <emillo@libero.it> for helping researching this data */
+	/* thanks to Emiliano Grilli <emillo@libero.it>
+	 * for helping researching this data */
 	USB_DEVICE(0x0582, 0x000c),
 	.driver_info = (unsigned long) & (const snd_usb_audio_quirk_t) {
 		.vendor_name = "Roland",
@@ -830,11 +861,42 @@
 	.driver_info = (unsigned long) & (const snd_usb_audio_quirk_t) {
 		.vendor_name = "M-Audio",
 		.product_name = "Quattro",
-		.ifnum = 9,
-		.type = QUIRK_MIDI_MIDIMAN,
-		.data = & (const snd_usb_midi_endpoint_info_t) {
-			.out_cables = 0x0001,
-			.in_cables  = 0x0001
+		.ifnum = QUIRK_ANY_INTERFACE,
+		.type = QUIRK_COMPOSITE,
+		.data = & (const snd_usb_audio_quirk_t[]) {
+			/*
+			 * Interfaces 0-2 are "Windows-compatible", 16-bit only,
+			 * and share endpoints with the other interfaces.
+			 * Ignore them.  The other interfaces can do 24 bits,
+			 * but captured samples are big-endian (see usbaudio.c).
+			 */
+			{
+				.ifnum = 4,
+				.type = QUIRK_AUDIO_STANDARD_INTERFACE
+			},
+			{
+				.ifnum = 5,
+				.type = QUIRK_AUDIO_STANDARD_INTERFACE
+			},
+			{
+				.ifnum = 7,
+				.type = QUIRK_AUDIO_STANDARD_INTERFACE
+			},
+			{
+				.ifnum = 8,
+				.type = QUIRK_AUDIO_STANDARD_INTERFACE
+			},
+			{
+				.ifnum = 9,
+				.type = QUIRK_MIDI_MIDIMAN,
+				.data = & (const snd_usb_midi_endpoint_info_t) {
+					.out_cables = 0x0001,
+					.in_cables  = 0x0001
+				}
+			},
+			{
+				.ifnum = -1
+			}
 		}
 	}
 },
@@ -911,6 +973,21 @@
 		.vendor_name = "Terratec",
 		.product_name = "PHASE 26",
 		.ifnum = 3,
+		.type = QUIRK_MIDI_STANDARD_INTERFACE
+	}
+},
+
+{
+	/*
+	 * Some USB MIDI devices don't have an audio control interface,
+	 * so we have to grab MIDI streaming interfaces here.
+	 */
+	.match_flags = USB_DEVICE_ID_MATCH_INT_CLASS |
+		       USB_DEVICE_ID_MATCH_INT_SUBCLASS,
+	.bInterfaceClass = USB_CLASS_AUDIO,
+	.bInterfaceSubClass = USB_SUBCLASS_MIDI_STREAMING,
+	.driver_info = (unsigned long) & (const snd_usb_audio_quirk_t) {
+		.ifnum = QUIRK_ANY_INTERFACE,
 		.type = QUIRK_MIDI_STANDARD_INTERFACE
 	}
 },
diff -Nru a/sound/usb/usx2y/Makefile b/sound/usb/usx2y/Makefile
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/sound/usb/usx2y/Makefile	2004-10-18 14:57:23 -07:00
@@ -0,0 +1,3 @@
+snd-usb-usx2y-objs := usbusx2y.o usbusx2yaudio.o usX2Yhwdep.o
+
+obj-$(CONFIG_SND_USB_USX2Y) += snd-usb-usx2y.o
diff -Nru a/sound/usb/usx2y/usX2Yhwdep.c b/sound/usb/usx2y/usX2Yhwdep.c
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/sound/usb/usx2y/usX2Yhwdep.c	2004-10-18 14:57:21 -07:00
@@ -0,0 +1,282 @@
+/*
+ * Driver for Tascam US-X2Y USB soundcards
+ *
+ * FPGA Loader + ALSA Startup
+ *
+ * Copyright (c) 2003 by Karsten Wiese <annabellesgarden@yahoo.de>
+ *
+ *   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
+ */
+
+#include <sound/driver.h>
+#include <linux/interrupt.h>
+#include <linux/usb.h>
+#include <sound/core.h>
+#include <sound/memalloc.h>
+#include <sound/pcm.h>
+#include <sound/hwdep.h>
+#include "usx2y.h"
+#include "usbusx2y.h"
+#include "usX2Yhwdep.h"
+
+
+static struct page * snd_us428ctls_vm_nopage(struct vm_area_struct *area, unsigned long address, int *type)
+{
+	unsigned long offset;
+	struct page * page;
+	void *vaddr;
+
+	snd_printdd("ENTER, start %lXh, ofs %lXh, pgoff %ld, addr %lXh\n",
+		   area->vm_start,
+		   address - area->vm_start,
+		   (address - area->vm_start) >> PAGE_SHIFT,
+		   address);
+	
+	offset = area->vm_pgoff << PAGE_SHIFT;
+	offset += address - area->vm_start;
+	snd_assert((offset % PAGE_SIZE) == 0, return NOPAGE_OOM);
+	vaddr = (char*)((usX2Ydev_t*)area->vm_private_data)->us428ctls_sharedmem + offset;
+	page = virt_to_page(vaddr);
+	get_page(page);
+	snd_printdd( "vaddr=%p made us428ctls_vm_nopage() return %p; offset=%lX\n", vaddr, page, offset);
+
+	if (type)
+		*type = VM_FAULT_MINOR;
+
+	return page;
+}
+
+static struct vm_operations_struct us428ctls_vm_ops = {
+	.nopage = snd_us428ctls_vm_nopage,
+};
+
+static int snd_us428ctls_mmap(snd_hwdep_t * hw, struct file *filp, struct vm_area_struct *area)
+{
+	unsigned long	size = (unsigned long)(area->vm_end - area->vm_start);
+	usX2Ydev_t	*us428 = (usX2Ydev_t*)hw->private_data;
+
+	// FIXME this hwdep interface is used twice: fpga download and mmap for controlling Lights etc. Maybe better using 2 hwdep devs?
+	// so as long as the device isn't fully initialised yet we return -EBUSY here.
+ 	if (!(((usX2Ydev_t*)hw->private_data)->chip_status & USX2Y_STAT_CHIP_INIT))
+		return -EBUSY;
+
+	/* if userspace tries to mmap beyond end of our buffer, fail */ 
+        if (size > ((PAGE_SIZE - 1 + sizeof(us428ctls_sharedmem_t)) / PAGE_SIZE) * PAGE_SIZE) {
+		snd_printd( "%lu > %lu\n", size, (unsigned long)sizeof(us428ctls_sharedmem_t)); 
+                return -EINVAL;
+	}
+
+	if (!us428->us428ctls_sharedmem) {
+		init_waitqueue_head(&us428->us428ctls_wait_queue_head);
+		if(!(us428->us428ctls_sharedmem = snd_malloc_pages(sizeof(us428ctls_sharedmem_t), GFP_KERNEL)))
+			return -ENOMEM;
+		memset(us428->us428ctls_sharedmem, -1, sizeof(us428ctls_sharedmem_t));
+		us428->us428ctls_sharedmem->CtlSnapShotLast = -2;
+	}
+	area->vm_ops = &us428ctls_vm_ops;
+	area->vm_flags |= VM_RESERVED;
+	area->vm_private_data = hw->private_data;
+	return 0;
+}
+
+static unsigned int snd_us428ctls_poll(snd_hwdep_t *hw, struct file *file, poll_table *wait)
+{
+	unsigned int	mask = 0;
+	usX2Ydev_t	*us428 = (usX2Ydev_t*)hw->private_data;
+	static unsigned	LastN;
+
+	if (us428->chip_status & USX2Y_STAT_CHIP_HUP)
+		return POLLHUP;
+
+	poll_wait(file, &us428->us428ctls_wait_queue_head, wait);
+
+	down(&us428->open_mutex);
+	if (us428->us428ctls_sharedmem
+	    && us428->us428ctls_sharedmem->CtlSnapShotLast != LastN) {
+		mask |= POLLIN;
+		LastN = us428->us428ctls_sharedmem->CtlSnapShotLast;
+	}
+	up(&us428->open_mutex);
+
+	return mask;
+}
+
+
+static int snd_usX2Y_hwdep_open(snd_hwdep_t *hw, struct file *file)
+{
+	return 0;
+}
+
+static int snd_usX2Y_hwdep_release(snd_hwdep_t *hw, struct file *file)
+{
+	return 0;
+}
+
+static int snd_usX2Y_hwdep_dsp_status(snd_hwdep_t *hw, snd_hwdep_dsp_status_t *info)
+{
+	static char *type_ids[USX2Y_TYPE_NUMS] = {
+		[USX2Y_TYPE_122] = "us122",
+		[USX2Y_TYPE_224] = "us224",
+		[USX2Y_TYPE_428] = "us428",
+	};
+	int id = -1;
+
+	switch (((usX2Ydev_t*)hw->private_data)->chip.dev->descriptor.idProduct) {
+	case USB_ID_US122:
+		id = USX2Y_TYPE_122;
+		break;
+	case USB_ID_US224:
+		id = USX2Y_TYPE_224;
+		break;
+	case USB_ID_US428:
+		id = USX2Y_TYPE_428;
+		break;
+	}
+	if (0 > id)
+		return -ENODEV;
+	strcpy(info->id, type_ids[id]);
+	info->num_dsps = 2;		// 0: Prepad Data, 1: FPGA Code
+ 	if (((usX2Ydev_t*)hw->private_data)->chip_status & USX2Y_STAT_CHIP_INIT) 
+		info->chip_ready = 1;
+ 	info->version = USX2Y_DRIVER_VERSION; 
+	return 0;
+}
+
+
+static int usX2Y_create_usbmidi(snd_card_t* card )
+{
+	static snd_usb_midi_endpoint_info_t quirk_data_1 = {
+		.out_ep =0x06,
+		.in_ep = 0x06,
+		.out_cables =	0x001,
+		.in_cables =	0x001
+	};
+	static snd_usb_audio_quirk_t quirk_1 = {
+		.vendor_name =	"TASCAM",
+		.product_name =	NAME_ALLCAPS,
+		.ifnum = 	0,
+       		.type = QUIRK_MIDI_FIXED_ENDPOINT,
+		.data = &quirk_data_1
+	};
+	static snd_usb_midi_endpoint_info_t quirk_data_2 = {
+		.out_ep =0x06,
+		.in_ep = 0x06,
+		.out_cables =	0x003,
+		.in_cables =	0x003
+	};
+	static snd_usb_audio_quirk_t quirk_2 = {
+		.vendor_name =	"TASCAM",
+		.product_name =	"US428",
+		.ifnum = 	0,
+       		.type = QUIRK_MIDI_FIXED_ENDPOINT,
+		.data = &quirk_data_2
+	};
+	struct usb_device *dev = usX2Y(card)->chip.dev;
+	struct usb_interface *iface = usb_ifnum_to_if(dev, 0);
+	snd_usb_audio_quirk_t *quirk = dev->descriptor.idProduct == USB_ID_US428 ? &quirk_2 : &quirk_1;
+
+	snd_printdd("usX2Y_create_usbmidi \n");
+	return snd_usb_create_midi_interface(&usX2Y(card)->chip, iface, quirk);
+}
+
+static int usX2Y_create_alsa_devices(snd_card_t* card)
+{
+	int err;
+
+	do {
+		if ((err = usX2Y_create_usbmidi(card)) < 0) {
+			snd_printk("usX2Y_create_alsa_devices: usX2Y_create_usbmidi error %i \n", err);
+			break;
+		}
+		if ((err = usX2Y_audio_create(card)) < 0) 
+			break;
+		if ((err = snd_card_register(card)) < 0)
+			break;
+	} while (0);
+
+	return err;
+} 
+
+static int snd_usX2Y_hwdep_dsp_load(snd_hwdep_t *hw, snd_hwdep_dsp_image_t *dsp)
+{
+	usX2Ydev_t *priv = hw->private_data;
+	int	lret, err = -EINVAL;
+	snd_printdd( "dsp_load %s\n", dsp->name);
+
+	if (access_ok(VERIFY_READ, dsp->image, dsp->length)) {
+		struct usb_device* dev = priv->chip.dev;
+		char *buf = kmalloc(dsp->length, GFP_KERNEL);
+		if (!buf)
+			return -ENOMEM;
+		if (copy_from_user(buf, dsp->image, dsp->length)) {
+			kfree(buf);
+			return -EFAULT;
+		}
+		err = usb_set_interface(dev, 0, 1);
+		if (err)
+			snd_printk("usb_set_interface error \n");
+		else
+			err = usb_bulk_msg(dev, usb_sndbulkpipe(dev, 2), buf, dsp->length, &lret, 6*HZ);
+		kfree(buf);
+	}
+	if (err)
+		return err;
+	if (dsp->index == 1) {
+		set_current_state(TASK_UNINTERRUPTIBLE);
+		schedule_timeout(HZ/4);			// give the device some time 
+		err = usX2Y_AsyncSeq04_init(priv);
+		if (err) {
+			snd_printk("usX2Y_AsyncSeq04_init error \n");
+			return err;
+		}
+		err = usX2Y_In04_init(priv);
+		if (err) {
+			snd_printk("usX2Y_In04_init error \n");
+			return err;
+		}
+		err = usX2Y_create_alsa_devices(hw->card);
+		if (err) {
+			snd_printk("usX2Y_create_alsa_devices error %i \n", err);
+			snd_card_free(hw->card);
+			return err;
+		}
+		priv->chip_status |= USX2Y_STAT_CHIP_INIT; 
+		snd_printdd("%s: alsa all started\n", hw->name);
+	}
+	return err;
+}
+
+
+int usX2Y_hwdep_new(snd_card_t* card, struct usb_device* device)
+{
+	int err;
+	snd_hwdep_t *hw;
+
+	if ((err = snd_hwdep_new(card, SND_USX2Y_LOADER_ID, 0, &hw)) < 0)
+		return err;
+
+	hw->iface = SNDRV_HWDEP_IFACE_USX2Y;
+	hw->private_data = usX2Y(card);
+	hw->ops.open = snd_usX2Y_hwdep_open;
+	hw->ops.release = snd_usX2Y_hwdep_release;
+	hw->ops.dsp_status = snd_usX2Y_hwdep_dsp_status;
+	hw->ops.dsp_load = snd_usX2Y_hwdep_dsp_load;
+	hw->ops.mmap = snd_us428ctls_mmap;
+	hw->ops.poll = snd_us428ctls_poll;
+	hw->exclusive = 1;
+	sprintf(hw->name, "/proc/bus/usb/%03d/%03d", device->bus->busnum, device->devnum);
+	return 0;
+}
+
diff -Nru a/sound/usb/usx2y/usX2Yhwdep.h b/sound/usb/usx2y/usX2Yhwdep.h
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/sound/usb/usx2y/usX2Yhwdep.h	2004-10-18 14:57:24 -07:00
@@ -0,0 +1,6 @@
+#ifndef USX2YHWDEP_H
+#define USX2YHWDEP_H
+
+int usX2Y_hwdep_new(snd_card_t* card, struct usb_device* device);
+
+#endif
diff -Nru a/sound/usb/usx2y/usbus428ctldefs.h b/sound/usb/usx2y/usbus428ctldefs.h
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/sound/usb/usx2y/usbus428ctldefs.h	2004-10-18 14:57:24 -07:00
@@ -0,0 +1,108 @@
+/*
+ *
+ * Copyright (c) 2003 by Karsten Wiese <annabellesgarden@yahoo.de>
+ *
+ *   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
+ */
+
+enum E_In84{
+	eFader0 = 0,
+	eFader1,
+	eFader2,
+	eFader3,
+	eFader4,
+	eFader5,
+	eFader6,
+	eFader7,
+	eFaderM,
+	eTransport,
+	eModifier = 10,
+	eFilterSelect,
+	eSelect,
+	eMute,
+
+	eSwitch   = 15,
+	eWheelGain,
+	eWheelFreq,
+	eWheelQ,
+	eWheelPan,
+	eWheel    = 20
+};
+
+#define T_RECORD   1
+#define T_PLAY     2
+#define T_STOP     4
+#define T_F_FWD    8
+#define T_REW   0x10
+#define T_SOLO  0x20
+#define T_REC   0x40
+#define T_NULL  0x80
+
+
+struct us428_ctls{
+	unsigned char   Fader[9];
+	unsigned char 	Transport;
+	unsigned char 	Modifier;
+	unsigned char 	FilterSelect;
+	unsigned char 	Select;
+	unsigned char   Mute;
+	unsigned char   UNKNOWN;
+	unsigned char   Switch;	     
+	unsigned char   Wheel[5];
+};
+
+typedef struct us428_ctls us428_ctls_t;
+
+typedef struct us428_setByte{
+	unsigned char Offset,
+		Value;
+}us428_setByte_t;
+
+enum {
+	eLT_Volume = 0,
+	eLT_Light
+};
+
+typedef struct usX2Y_volume {
+	unsigned char Channel,
+		LH,
+		LL,
+		RH,
+		RL;
+} usX2Y_volume_t;
+
+struct us428_lights{
+	us428_setByte_t Light[7];
+};
+typedef struct us428_lights us428_lights_t;
+
+typedef struct {
+	char type;
+	union {
+		usX2Y_volume_t	vol;
+		us428_lights_t  lights;
+	} val;
+} us428_p4out_t;
+
+#define N_us428_ctl_BUFS 16
+#define N_us428_p4out_BUFS 16
+struct us428ctls_sharedmem{
+	us428_ctls_t	CtlSnapShot[N_us428_ctl_BUFS];
+	int		CtlSnapShotDiffersAt[N_us428_ctl_BUFS];
+	int		CtlSnapShotLast, CtlSnapShotRed;
+	us428_p4out_t	p4out[N_us428_p4out_BUFS];
+	int		p4outLast, p4outSent;
+};
+typedef struct us428ctls_sharedmem us428ctls_sharedmem_t;
diff -Nru a/sound/usb/usx2y/usbusx2y.c b/sound/usb/usx2y/usbusx2y.c
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/sound/usb/usx2y/usbusx2y.c	2004-10-18 14:57:21 -07:00
@@ -0,0 +1,434 @@
+/*
+ * usbus428.c - ALSA USB US-428 Driver
+ *
+2004-07-13 Karsten Wiese
+	Version 0.7.1:
+	Don't sleep in START/STOP callbacks anymore.
+	us428 channels C/D not handled just for this version, sorry.
+
+2004-06-21 Karsten Wiese
+	Version 0.6.4:
+	Temporarely suspend midi input
+	to sanely call usb_set_interface() when setting format.
+
+2004-06-12 Karsten Wiese
+	Version 0.6.3:
+	Made it thus the following rule is enforced:
+	"All pcm substreams of one usX2Y have to operate at the same rate & format."
+
+2004-04-06 Karsten Wiese
+	Version 0.6.0:
+	Runs on 2.6.5 kernel without any "--with-debug=" things.
+	us224 reported running.
+
+2004-01-14 Karsten Wiese
+	Version 0.5.1:
+	Runs with 2.6.1 kernel.
+
+2003-12-30 Karsten Wiese
+	Version 0.4.1:
+	Fix 24Bit 4Channel capturing for the us428.
+
+2003-11-27 Karsten Wiese, Martin Langer
+	Version 0.4:
+	us122 support.
+	us224 could be tested by uncommenting the sections containing USB_ID_US224
+
+2003-11-03 Karsten Wiese
+	Version 0.3:
+	24Bit support. 
+	"arecord -D hw:1 -c 2 -r 48000 -M -f S24_3LE|aplay -D hw:1 -c 2 -r 48000 -M -f S24_3LE" works.
+
+2003-08-22 Karsten Wiese
+	Version 0.0.8:
+	Removed EZUSB Firmware. First Stage Firmwaredownload is now done by tascam-firmware downloader.
+	See:
+	http://usb-midi-fw.sourceforge.net/tascam-firmware.tar.gz
+
+2003-06-18 Karsten Wiese
+	Version 0.0.5:
+	changed to compile with kernel 2.4.21 and alsa 0.9.4
+
+2002-10-16 Karsten Wiese
+	Version 0.0.4:
+	compiles again with alsa-current.
+	USB_ISO_ASAP not used anymore (most of the time), instead
+	urb->start_frame is calculated here now, some calls inside usb-driver don't need to happen anymore.
+
+	To get the best out of this:
+	Disable APM-support in the kernel as APM-BIOS calls (once each second) hard disable interrupt for many precious milliseconds.
+	This helped me much on my slowish PII 400 & PIII 500.
+	ACPI yet untested but might cause the same bad behaviour.
+	Use a kernel with lowlatency and preemptiv patches applied.
+	To autoload snd-usb-midi append a line 
+		post-install snd-usb-us428 modprobe snd-usb-midi
+	to /etc/modules.conf.
+
+	known problems:
+	sliders, knobs, lights not yet handled except MASTER Volume slider.
+       	"pcm -c 2" doesn't work. "pcm -c 2 -m direct_interleaved" does.
+	KDE3: "Enable full duplex operation" deadlocks.
+
+	
+2002-08-31 Karsten Wiese
+	Version 0.0.3: audio also simplex;
+	simplifying: iso urbs only 1 packet, melted structs.
+	ASYNC_UNLINK not used anymore: no more crashes so far.....
+	for alsa 0.9 rc3.
+
+2002-08-09 Karsten Wiese
+	Version 0.0.2: midi works with snd-usb-midi, audio (only fullduplex now) with i.e. bristol.
+	The firmware has been sniffed from win2k us-428 driver 3.09.
+
+ *   Copyright (c) 2002 Karsten Wiese
+ *
+ *   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
+*/
+
+#include <sound/driver.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/interrupt.h>
+#include <linux/usb.h>
+#include <sound/core.h>
+#include <sound/initval.h>
+#include <sound/pcm.h>
+
+#include <sound/rawmidi.h>
+#include "usx2y.h"
+#include "usbusx2y.h"
+#include "usX2Yhwdep.h"
+
+
+
+MODULE_AUTHOR("Karsten Wiese <annabellesgarden@yahoo.de>");
+MODULE_DESCRIPTION("TASCAM "NAME_ALLCAPS" Version 0.7.2");
+MODULE_LICENSE("GPL");
+MODULE_SUPPORTED_DEVICE("{{TASCAM(0x1604), "NAME_ALLCAPS"(0x8001)(0x8005)(0x8007) }}");
+
+static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-max */
+static char* id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* Id for this card */
+static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP; /* Enable this card */
+static int boot_devs;
+
+module_param_array(index, int, boot_devs, 0444);
+MODULE_PARM_DESC(index, "Index value for "NAME_ALLCAPS".");
+module_param_array(id, charp, boot_devs, 0444);
+MODULE_PARM_DESC(id, "ID string for "NAME_ALLCAPS".");
+module_param_array(enable, bool, boot_devs, 0444);
+MODULE_PARM_DESC(enable, "Enable "NAME_ALLCAPS".");
+
+
+static int snd_usX2Y_card_used[SNDRV_CARDS];
+
+static void usX2Y_usb_disconnect(struct usb_device* usb_device, void* ptr);
+static void snd_usX2Y_card_private_free(snd_card_t *card);
+
+/* 
+ * pipe 4 is used for switching the lamps, setting samplerate, volumes ....   
+ */
+static void i_usX2Y_Out04Int(struct urb* urb, struct pt_regs *regs)
+{
+#ifdef CONFIG_SND_DEBUG
+	if (urb->status) {
+		int 		i;
+		usX2Ydev_t*	usX2Y = urb->context;
+		for (i = 0; i < 10 && usX2Y->AS04.urb[i] != urb; i++);
+		snd_printdd("i_usX2Y_Out04Int() urb %i status=%i\n", i, urb->status);
+	}
+#endif
+}
+
+static void i_usX2Y_In04Int(struct urb* urb, struct pt_regs *regs)
+{
+	int			err = 0;
+	usX2Ydev_t		*usX2Y = urb->context;
+	us428ctls_sharedmem_t	*us428ctls = usX2Y->us428ctls_sharedmem;
+
+	usX2Y->In04IntCalls++;
+
+	if (urb->status) {
+		snd_printdd("Interrupt Pipe 4 came back with status=%i\n", urb->status);
+		return;
+	}
+
+	//	printk("%i:0x%02X ", 8, (int)((unsigned char*)usX2Y->In04Buf)[8]); Master volume shows 0 here if fader is at max during boot ?!?
+	if (us428ctls) {
+		int diff = -1;
+		if (-2 == us428ctls->CtlSnapShotLast) {
+			diff = 0;
+			memcpy(usX2Y->In04Last, usX2Y->In04Buf, sizeof(usX2Y->In04Last));
+			us428ctls->CtlSnapShotLast = -1;
+		} else {
+			int i;
+			for (i = 0; i < 21; i++) {
+				if (usX2Y->In04Last[i] != ((char*)usX2Y->In04Buf)[i]) {
+					if (diff < 0)
+						diff = i;
+					usX2Y->In04Last[i] = ((char*)usX2Y->In04Buf)[i];
+				}
+			}
+		}
+		if (0 <= diff) {
+			int n = us428ctls->CtlSnapShotLast + 1;
+			if (n >= N_us428_ctl_BUFS  ||  n < 0)
+				n = 0;
+			memcpy(us428ctls->CtlSnapShot + n, usX2Y->In04Buf, sizeof(us428ctls->CtlSnapShot[0]));
+			us428ctls->CtlSnapShotDiffersAt[n] = diff;
+			us428ctls->CtlSnapShotLast = n;
+			wake_up(&usX2Y->us428ctls_wait_queue_head);
+		}
+	}
+	
+	
+	if (usX2Y->US04) {
+		if (0 == usX2Y->US04->submitted)
+			do
+				err = usb_submit_urb(usX2Y->US04->urb[usX2Y->US04->submitted++], GFP_ATOMIC);
+			while (!err && usX2Y->US04->submitted < usX2Y->US04->len);
+	} else
+		if (us428ctls && us428ctls->p4outLast >= 0 && us428ctls->p4outLast < N_us428_p4out_BUFS) {
+			if (us428ctls->p4outLast != us428ctls->p4outSent) {
+				int j, send = us428ctls->p4outSent + 1;
+				if (send >= N_us428_p4out_BUFS)
+					send = 0;
+				for (j = 0; j < URBS_AsyncSeq  &&  !err; ++j)
+					if (0 == usX2Y->AS04.urb[j]->status) {
+						us428_p4out_t *p4out = us428ctls->p4out + send;	// FIXME if more then 1 p4out is new, 1 gets lost.
+						usb_fill_bulk_urb(usX2Y->AS04.urb[j], usX2Y->chip.dev,
+								  usb_sndbulkpipe(usX2Y->chip.dev, 0x04), &p4out->val.vol, 
+								  p4out->type == eLT_Light ? sizeof(us428_lights_t) : 5,
+								  i_usX2Y_Out04Int, usX2Y);
+						err = usb_submit_urb(usX2Y->AS04.urb[j], GFP_ATOMIC);
+						us428ctls->p4outSent = send;
+						break;
+					}
+			}
+		}
+
+	if (err) {
+		snd_printk("In04Int() usb_submit_urb err=%i\n", err);
+	}
+
+	urb->dev = usX2Y->chip.dev;
+	usb_submit_urb(urb, GFP_ATOMIC);
+}
+
+/*
+ * Prepare some urbs
+ */
+int usX2Y_AsyncSeq04_init(usX2Ydev_t* usX2Y)
+{
+	int	err = 0,
+		i;
+
+	if (NULL == (usX2Y->AS04.buffer = kmalloc(URB_DataLen_AsyncSeq*URBS_AsyncSeq, GFP_KERNEL))) {
+		err = -ENOMEM;
+	} else
+		for (i = 0; i < URBS_AsyncSeq; ++i) {
+			if (NULL == (usX2Y->AS04.urb[i] = usb_alloc_urb(0, GFP_KERNEL))) {
+				err = -ENOMEM;
+				break;
+			}
+			usb_fill_bulk_urb(	usX2Y->AS04.urb[i], usX2Y->chip.dev,
+						usb_sndbulkpipe(usX2Y->chip.dev, 0x04),
+						usX2Y->AS04.buffer + URB_DataLen_AsyncSeq*i, 0,
+						i_usX2Y_Out04Int, usX2Y
+				);
+		}
+	return err;
+}
+
+int usX2Y_In04_init(usX2Ydev_t* usX2Y)
+{
+	int	err = 0;
+	if (! (usX2Y->In04urb = usb_alloc_urb(0, GFP_KERNEL)))
+		return -ENOMEM;
+
+	if (! (usX2Y->In04Buf = kmalloc(21, GFP_KERNEL))) {
+		usb_free_urb(usX2Y->In04urb);
+		return -ENOMEM;
+	}
+	 
+	init_waitqueue_head(&usX2Y->In04WaitQueue);
+	usb_fill_int_urb(usX2Y->In04urb, usX2Y->chip.dev, usb_rcvintpipe(usX2Y->chip.dev, 0x4),
+			 usX2Y->In04Buf, 21,
+			 i_usX2Y_In04Int, usX2Y,
+			 10);
+	err = usb_submit_urb(usX2Y->In04urb, GFP_KERNEL);
+	return err;
+}
+
+static void usX2Y_unlinkSeq(snd_usX2Y_AsyncSeq_t* S)
+{
+	int	i;
+	for (i = 0; i < URBS_AsyncSeq; ++i) {
+		if (S[i].urb) {
+			usb_unlink_urb(S->urb[i]);
+			usb_free_urb(S->urb[i]);
+			S->urb[i] = NULL;
+		}
+	}
+	if (S->buffer)
+		kfree(S->buffer);
+}
+
+
+static struct usb_device_id snd_usX2Y_usb_id_table[] = {
+	{
+		.match_flags =	USB_DEVICE_ID_MATCH_DEVICE,
+		.idVendor =	0x1604,
+		.idProduct =	USB_ID_US428 
+	},
+	{
+		.match_flags =	USB_DEVICE_ID_MATCH_DEVICE,
+		.idVendor =	0x1604,
+		.idProduct =	USB_ID_US122 
+	},
+ 	{
+		.match_flags =	USB_DEVICE_ID_MATCH_DEVICE,
+		.idVendor =	0x1604,
+		.idProduct =	USB_ID_US224
+	},
+	{ /* terminator */ }
+};
+
+static snd_card_t* usX2Y_create_card(struct usb_device* device)
+{
+	int		dev;
+	snd_card_t*	card;
+	for (dev = 0; dev < SNDRV_CARDS; ++dev)
+		if (enable[dev] && !snd_usX2Y_card_used[dev])
+			break;
+	if (dev >= SNDRV_CARDS)
+		return NULL;
+	card = snd_card_new(index[dev], id[dev], THIS_MODULE, sizeof(usX2Ydev_t));
+	if (!card)
+		return NULL;
+	snd_usX2Y_card_used[usX2Y(card)->chip.index = dev] = 1;
+	card->private_free = snd_usX2Y_card_private_free;
+	usX2Y(card)->chip.dev = device;
+	usX2Y(card)->chip.card = card;
+	init_MUTEX (&usX2Y(card)->open_mutex);
+	INIT_LIST_HEAD(&usX2Y(card)->chip.midi_list);
+	strcpy(card->driver, "USB "NAME_ALLCAPS"");
+	sprintf(card->shortname, "TASCAM "NAME_ALLCAPS"");
+	sprintf(card->longname, "%s (%x:%x if %d at %03d/%03d)",
+		card->shortname, 
+		device->descriptor.idVendor, device->descriptor.idProduct,
+		0,//us428(card)->usbmidi.ifnum,
+		usX2Y(card)->chip.dev->bus->busnum, usX2Y(card)->chip.dev->devnum
+		);
+	snd_card_set_dev(card, &device->dev);
+	return card;
+}
+
+
+static void* usX2Y_usb_probe(struct usb_device* device, struct usb_interface *intf, const struct usb_device_id* device_id)
+{
+	int		err;
+	snd_card_t*	card;
+	if (device->descriptor.idVendor != 0x1604 ||
+	    (device->descriptor.idProduct != USB_ID_US122 &&
+	     device->descriptor.idProduct != USB_ID_US224 &&
+	     device->descriptor.idProduct != USB_ID_US428) ||
+	    !(card = usX2Y_create_card(device)))
+		return NULL;
+	if ((err = usX2Y_hwdep_new(card, device)) < 0  ||
+	    (err = snd_card_register(card)) < 0) {
+		snd_card_free(card);
+		return NULL;
+	}
+	return card;
+}
+
+/*
+ * new 2.5 USB kernel API
+ */
+static int snd_usX2Y_probe(struct usb_interface *intf, const struct usb_device_id *id)
+{
+	void *chip;
+	chip = usX2Y_usb_probe(interface_to_usbdev(intf), intf, id);
+	if (chip) {
+		dev_set_drvdata(&intf->dev, chip);
+		return 0;
+	} else
+		return -EIO;
+}
+
+static void snd_usX2Y_disconnect(struct usb_interface *intf)
+{
+	usX2Y_usb_disconnect(interface_to_usbdev(intf),
+				 dev_get_drvdata(&intf->dev));
+}
+
+MODULE_DEVICE_TABLE(usb, snd_usX2Y_usb_id_table);
+static struct usb_driver snd_usX2Y_usb_driver = {
+ 	.owner =	THIS_MODULE,
+	.name =		"snd-usb-usx2y",
+	.probe =	snd_usX2Y_probe,
+	.disconnect =	snd_usX2Y_disconnect,
+	.id_table =	snd_usX2Y_usb_id_table,
+};
+
+static void snd_usX2Y_card_private_free(snd_card_t *card)
+{
+	if (usX2Y(card)->In04Buf)
+		kfree(usX2Y(card)->In04Buf);
+	usb_free_urb(usX2Y(card)->In04urb);
+	if (usX2Y(card)->us428ctls_sharedmem)
+		snd_free_pages(usX2Y(card)->us428ctls_sharedmem, sizeof(*usX2Y(card)->us428ctls_sharedmem));
+	if (usX2Y(card)->chip.index >= 0  &&  usX2Y(card)->chip.index < SNDRV_CARDS)
+		snd_usX2Y_card_used[usX2Y(card)->chip.index] = 0;
+}
+
+/*
+ * Frees the device.
+ */
+static void usX2Y_usb_disconnect(struct usb_device* device, void* ptr)
+{
+	if (ptr) {
+		usX2Ydev_t* usX2Y = usX2Y((snd_card_t*)ptr);
+		struct list_head* p;
+		if (usX2Y->chip_status == USX2Y_STAT_CHIP_HUP)	// on 2.6.1 kernel snd_usbmidi_disconnect()
+			return;					// calls us back. better leave :-) .
+		usX2Y->chip.shutdown = 1;
+		usX2Y->chip_status = USX2Y_STAT_CHIP_HUP;
+		usX2Y_unlinkSeq(&usX2Y->AS04);
+		usb_unlink_urb(usX2Y->In04urb);
+		snd_card_disconnect((snd_card_t*)ptr);
+		/* release the midi resources */
+		list_for_each(p, &usX2Y->chip.midi_list) {
+			snd_usbmidi_disconnect(p, &snd_usX2Y_usb_driver);
+		}
+		if (usX2Y->us428ctls_sharedmem) 
+			wake_up(&usX2Y->us428ctls_wait_queue_head);
+		snd_card_free_in_thread((snd_card_t*)ptr);
+	}
+}
+
+static int __init snd_usX2Y_module_init(void)
+{
+	return usb_register(&snd_usX2Y_usb_driver);
+}
+
+static void __exit snd_usX2Y_module_exit(void)
+{
+	usb_deregister(&snd_usX2Y_usb_driver);
+}
+
+module_init(snd_usX2Y_module_init)
+module_exit(snd_usX2Y_module_exit)
diff -Nru a/sound/usb/usx2y/usbusx2y.h b/sound/usb/usx2y/usbusx2y.h
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/sound/usb/usx2y/usbusx2y.h	2004-10-18 14:57:24 -07:00
@@ -0,0 +1,61 @@
+#ifndef USBUSX2Y_H
+#define USBUSX2Y_H
+#include "../usbaudio.h"
+#include "usbus428ctldefs.h" 
+
+#define NRURBS	        2	/* */
+#define NRPACKS		1	/* FIXME: Currently only 1 works.
+				   usb-frames/ms per urb: 1 and 2 are supported.
+				   setting to 2 will PERHAPS make it easier for slow machines.
+				   Jitter will be higher though.
+				   On my PIII 500Mhz Laptop setting to 1 is the only way to go 
+				   for PLAYING synths. i.e. Jack & Aeolus sound quit nicely 
+				   at 4 periods 64 frames. 
+				*/
+
+#define URBS_AsyncSeq 10
+#define URB_DataLen_AsyncSeq 32
+typedef struct {
+	struct urb*	urb[URBS_AsyncSeq];
+	char*   buffer;
+} snd_usX2Y_AsyncSeq_t;
+
+typedef struct {
+	int	submitted;
+	int	len;
+	struct urb*	urb[0];
+} snd_usX2Y_urbSeq_t;
+
+typedef struct snd_usX2Y_substream snd_usX2Y_substream_t;
+
+typedef struct {
+	snd_usb_audio_t 	chip;
+	int			stride;
+	struct urb		*In04urb;
+	void			*In04Buf;
+	char			In04Last[24];
+	unsigned		In04IntCalls;
+	snd_usX2Y_urbSeq_t	*US04;
+	wait_queue_head_t	In04WaitQueue;
+	snd_usX2Y_AsyncSeq_t	AS04;
+	unsigned int		rate,
+				format;
+	int			refframes;
+	int			chip_status;
+	struct semaphore	open_mutex;
+	us428ctls_sharedmem_t	*us428ctls_sharedmem;
+	wait_queue_head_t	us428ctls_wait_queue_head;
+	snd_usX2Y_substream_t	*substream[4];
+} usX2Ydev_t;
+
+
+#define usX2Y(c) ((usX2Ydev_t*)(c)->private_data)
+
+int usX2Y_audio_create(snd_card_t* card);
+
+int usX2Y_AsyncSeq04_init(usX2Ydev_t* usX2Y);
+int usX2Y_In04_init(usX2Ydev_t* usX2Y);
+
+#define NAME_ALLCAPS "US-X2Y"
+
+#endif
diff -Nru a/sound/usb/usx2y/usbusx2yaudio.c b/sound/usb/usx2y/usbusx2yaudio.c
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/sound/usb/usx2y/usbusx2yaudio.c	2004-10-18 14:57:23 -07:00
@@ -0,0 +1,1027 @@
+/*
+ *   US-428 AUDIO
+
+ *   Copyright (c) 2002-2003 by Karsten Wiese
+ 
+ *   based on
+
+ *   (Tentative) USB Audio Driver for ALSA
+ *
+ *   Main and PCM part
+ *
+ *   Copyright (c) 2002 by Takashi Iwai <tiwai@suse.de>
+ *
+ *   Many codes borrowed from audio.c by 
+ *	    Alan Cox (alan@lxorguk.ukuu.org.uk)
+ *	    Thomas Sailer (sailer@ife.ee.ethz.ch)
+ *
+ *
+ *   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
+ */
+
+
+#include <sound/driver.h>
+#include <linux/interrupt.h>
+#include <linux/usb.h>
+#include <sound/core.h>
+#include <sound/info.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+#include "usx2y.h"
+#include "usbusx2y.h"
+
+
+struct snd_usX2Y_substream {
+	usX2Ydev_t	*usX2Y;
+	snd_pcm_substream_t *pcm_substream;
+
+	unsigned char		endpoint;		
+	unsigned int		datapipe;  		/* the data i/o pipe */
+	unsigned int		maxpacksize;		/* max packet size in bytes */
+
+	char			prepared,
+				running,
+				stalled;
+
+	int			hwptr;			/* free frame position in the buffer (only for playback) */
+	int			hwptr_done;		/* processed frame position in the buffer */
+	int			transfer_done;		/* processed frames since last period update */
+
+	struct urb		*urb[NRURBS];	/* data urb table */
+	int			next_urb_complete;
+	struct urb		*completed_urb;
+	char			*tmpbuf;			/* temporary buffer for playback */
+	volatile int		submitted_urbs;
+	wait_queue_head_t	wait_queue;
+};
+
+
+
+
+
+
+static int usX2Y_urb_capt_retire(snd_usX2Y_substream_t *subs)
+{
+	struct urb	*urb = subs->completed_urb;
+	snd_pcm_runtime_t *runtime = subs->pcm_substream->runtime;
+	unsigned char	*cp;
+	int 		i, len, lens = 0, hwptr_done = subs->hwptr_done;
+	usX2Ydev_t	*usX2Y = subs->usX2Y;
+
+	for (i = 0; i < NRPACKS; i++) {
+		cp = (unsigned char*)urb->transfer_buffer + urb->iso_frame_desc[i].offset;
+		if (urb->iso_frame_desc[i].status) { /* active? hmm, skip this */
+			snd_printdd("activ frame status %i\n", urb->iso_frame_desc[i].status);
+			return urb->iso_frame_desc[i].status;
+		}
+		len = urb->iso_frame_desc[i].actual_length / usX2Y->stride;
+		if (! len) {
+			snd_printk("0 == len ERROR!\n");
+			continue;
+		}
+
+		/* copy a data chunk */
+		if ((hwptr_done + len) > runtime->buffer_size) {
+			int cnt = runtime->buffer_size - hwptr_done;
+			int blen = cnt * usX2Y->stride;
+			memcpy(runtime->dma_area + hwptr_done * usX2Y->stride, cp, blen);
+			memcpy(runtime->dma_area, cp + blen, len * usX2Y->stride - blen);
+		} else {
+			memcpy(runtime->dma_area + hwptr_done * usX2Y->stride, cp, len * usX2Y->stride);
+		}
+		lens += len;
+		if ((hwptr_done += len) >= runtime->buffer_size)
+			hwptr_done -= runtime->buffer_size;
+	}
+
+	subs->hwptr_done = hwptr_done;
+	subs->transfer_done += lens;
+	/* update the pointer, call callback if necessary */
+	if (subs->transfer_done >= runtime->period_size) {
+		subs->transfer_done -= runtime->period_size;
+		snd_pcm_period_elapsed(subs->pcm_substream);
+	}
+	return 0;
+}
+/*
+ * prepare urb for playback data pipe
+ *
+ * we copy the data directly from the pcm buffer.
+ * the current position to be copied is held in hwptr field.
+ * since a urb can handle only a single linear buffer, if the total
+ * transferred area overflows the buffer boundary, we cannot send
+ * it directly from the buffer.  thus the data is once copied to
+ * a temporary buffer and urb points to that.
+ */
+static int usX2Y_urb_play_prepare(snd_usX2Y_substream_t *subs,
+				  struct urb *cap_urb,
+				  struct urb *urb)
+{
+	int count, counts, pack;
+	usX2Ydev_t* usX2Y = subs->usX2Y;
+	snd_pcm_runtime_t *runtime = subs->pcm_substream->runtime;
+
+	count = 0;
+	for (pack = 0; pack < NRPACKS; pack++) {
+		/* calculate the size of a packet */
+		counts = cap_urb->iso_frame_desc[pack].actual_length / usX2Y->stride;
+		count += counts;
+		if (counts < 43 || counts > 50) {
+			snd_printk("should not be here with counts=%i\n", counts);
+			return -EPIPE;
+		}
+
+		/* set up descriptor */
+		urb->iso_frame_desc[pack].offset = pack ? urb->iso_frame_desc[pack - 1].offset + urb->iso_frame_desc[pack - 1].length : 0;
+		urb->iso_frame_desc[pack].length = counts * usX2Y->stride;
+	}
+	if (subs->hwptr + count > runtime->buffer_size) {
+		/* err, the transferred area goes over buffer boundary.
+		 * copy the data to the temp buffer.
+		 */
+		int len;
+		len = runtime->buffer_size - subs->hwptr;
+		urb->transfer_buffer = subs->tmpbuf;
+		memcpy(subs->tmpbuf, runtime->dma_area + subs->hwptr * usX2Y->stride, len * usX2Y->stride);
+		memcpy(subs->tmpbuf + len * usX2Y->stride, runtime->dma_area, (count - len) * usX2Y->stride);
+		subs->hwptr += count;
+		subs->hwptr -= runtime->buffer_size;
+	} else {
+		/* set the buffer pointer */
+		urb->transfer_buffer = runtime->dma_area + subs->hwptr * usX2Y->stride;
+		if ((subs->hwptr += count) >= runtime->buffer_size)
+			subs->hwptr -= runtime->buffer_size;			
+	}
+	urb->transfer_buffer_length = count * usX2Y->stride;
+	return 0;
+}
+
+/*
+ * process after playback data complete
+ *
+ * update the current position and call callback if a period is processed.
+ */
+inline static int usX2Y_urb_play_retire(snd_usX2Y_substream_t *subs, struct urb *urb)
+{
+	snd_pcm_runtime_t *runtime = subs->pcm_substream->runtime;
+	int		len = (urb->iso_frame_desc[0].actual_length
+#if NRPACKS > 1
+			       + urb->iso_frame_desc[1].actual_length
+#endif
+		               ) / subs->usX2Y->stride;
+
+	subs->transfer_done += len;
+	subs->hwptr_done +=  len;
+	if (subs->hwptr_done >= runtime->buffer_size)
+		subs->hwptr_done -= runtime->buffer_size;
+	if (subs->transfer_done >= runtime->period_size) {
+		subs->transfer_done -= runtime->period_size;
+		snd_pcm_period_elapsed(subs->pcm_substream);
+	}
+	return 0;
+}
+
+inline static int usX2Y_urb_submit(snd_usX2Y_substream_t *subs, struct urb *urb, int frame)
+{
+	int err;
+	if (!urb)
+		return -ENODEV;
+	urb->start_frame = (frame + NRURBS*NRPACKS) & (1024 - 1);
+	urb->hcpriv = NULL;
+	urb->dev = subs->usX2Y->chip.dev; /* we need to set this at each time */
+	if ((err = usb_submit_urb(urb, GFP_ATOMIC)) < 0) {
+		snd_printk("%i\n", err);
+		return err;
+	} else {
+		subs->submitted_urbs++;
+		if (subs->next_urb_complete < 0) 
+			subs->next_urb_complete = 0;
+	}
+	return 0;
+}
+
+
+static inline int frame_distance(int from, int to)
+{
+	int distance = to - from;
+	if (distance < -512)
+		distance += 1024;
+	else
+		if (distance > 511)
+			distance -= 1024;
+	return distance;
+}
+
+
+static void usX2Y_subs_set_next_urb_complete(snd_usX2Y_substream_t *subs)
+{
+	int next_urb_complete = subs->next_urb_complete + 1;
+	int distance;
+	if (next_urb_complete >= NRURBS)
+		next_urb_complete = 0;
+	distance = frame_distance(subs->completed_urb->start_frame,
+				  subs->urb[next_urb_complete]->start_frame);
+	if (1 == distance) {
+		subs->next_urb_complete = next_urb_complete;
+	} else {
+		snd_printdd("distance %i not set_nuc %i %i %i \n", distance, subs->endpoint, next_urb_complete, subs->urb[next_urb_complete]->status);
+		subs->next_urb_complete = -1;
+	}
+}
+
+
+static inline void usX2Y_usbframe_complete(snd_usX2Y_substream_t *capsubs, snd_usX2Y_substream_t *playbacksubs, int frame)
+{
+	{
+		struct urb *urb;
+		if ((urb = playbacksubs->completed_urb)) {
+			if (playbacksubs->prepared)
+				usX2Y_urb_play_retire(playbacksubs, urb);
+			usX2Y_subs_set_next_urb_complete(playbacksubs);
+		}
+		if (playbacksubs->running) {
+			if (NULL == urb)
+				urb = playbacksubs->urb[playbacksubs->next_urb_complete + 1];
+			if (urb && 0 == usX2Y_urb_play_prepare(playbacksubs,
+							       capsubs->completed_urb,
+							       urb)) {
+				if (usX2Y_urb_submit(playbacksubs, urb, frame) < 0)
+					return;
+			} else
+				snd_pcm_stop(playbacksubs->pcm_substream, SNDRV_PCM_STATE_XRUN);
+		}
+		playbacksubs->completed_urb = NULL;
+	}
+	if (capsubs->running)
+		usX2Y_urb_capt_retire(capsubs);
+	usX2Y_subs_set_next_urb_complete(capsubs);
+	if (capsubs->prepared)
+		usX2Y_urb_submit(capsubs, capsubs->completed_urb, frame);
+	capsubs->completed_urb = NULL;
+}
+
+
+static void usX2Y_clients_stop(snd_usX2Y_substream_t *subs)
+{
+	usX2Ydev_t *usX2Y = subs->usX2Y;
+	int i;
+	for (i = 0; i < 4; i++) {
+		snd_usX2Y_substream_t *substream = usX2Y->substream[i];
+		if (substream && substream->running)
+			snd_pcm_stop(substream->pcm_substream, SNDRV_PCM_STATE_XRUN);
+	}
+}
+
+
+static void i_usX2Y_urb_complete(struct urb *urb, struct pt_regs *regs)
+{
+	snd_usX2Y_substream_t *subs = (snd_usX2Y_substream_t*)urb->context;
+
+	subs->submitted_urbs--;
+	if (urb->status) {
+		snd_printk("ep=%i stalled with status=%i\n", subs->endpoint, urb->status);
+		subs->stalled = 1;
+		usX2Y_clients_stop(subs);
+		urb->status = 0;
+		return;
+	}
+	if (urb == subs->urb[subs->next_urb_complete]) {
+		subs->completed_urb = urb;
+	} else {
+		snd_printk("Sequence Error!(ep=%i;nuc=%i,frame=%i)\n",
+			   subs->endpoint, subs->next_urb_complete, urb->start_frame);
+		subs->stalled = 1;
+		usX2Y_clients_stop(subs);
+		return;
+	}
+	if (waitqueue_active(&subs->wait_queue))
+		wake_up(&subs->wait_queue);
+	{
+		snd_usX2Y_substream_t *capsubs = subs->usX2Y->substream[SNDRV_PCM_STREAM_CAPTURE],
+			*playbacksubs = subs->usX2Y->substream[SNDRV_PCM_STREAM_PLAYBACK];
+		if (capsubs->completed_urb &&
+		    (playbacksubs->completed_urb ||
+		     !playbacksubs->prepared ||
+		     (playbacksubs->prepared && (playbacksubs->next_urb_complete < 0 ||	// not started yet
+						 frame_distance(capsubs->completed_urb->start_frame,
+								playbacksubs->urb[playbacksubs->next_urb_complete]->start_frame)
+						 > 0 ||					// other expected later
+						 playbacksubs->stalled))))
+			usX2Y_usbframe_complete(capsubs, playbacksubs, urb->start_frame);
+	}
+}
+
+
+static int usX2Y_urbs_capt_start(snd_usX2Y_substream_t *subs)
+{
+	int i, err;
+
+	for (i = 0; i < NRURBS; i++) {
+		unsigned long pack;
+		struct urb *urb = subs->urb[i];
+		urb->dev = subs->usX2Y->chip.dev;
+		urb->transfer_flags = URB_ISO_ASAP;
+		for (pack = 0; pack < NRPACKS; pack++) {
+			urb->iso_frame_desc[pack].offset = subs->maxpacksize * pack;
+			urb->iso_frame_desc[pack].length = subs->maxpacksize;
+		}
+		urb->transfer_buffer_length = subs->maxpacksize * NRPACKS; 
+		if ((err = usb_submit_urb(urb, GFP_ATOMIC)) < 0) {
+			snd_printk (KERN_ERR "cannot submit datapipe for urb %d, err = %d\n", i, err);
+			return -EPIPE;
+		} else {
+			subs->submitted_urbs++;
+		}
+		urb->transfer_flags = 0;
+	}
+	subs->stalled = 0;
+	subs->next_urb_complete = 0;
+	subs->prepared = 1;
+	return 0;
+}
+
+/* 
+ *  wait until all urbs are processed.
+ */
+static int usX2Y_urbs_wait_clear(snd_usX2Y_substream_t *subs)
+{
+	int timeout = HZ;
+
+	do {
+		if (0 == subs->submitted_urbs)
+			break;
+		set_current_state(TASK_UNINTERRUPTIBLE);
+		snd_printdd("snd_usX2Y_urbs_wait_clear waiting\n");
+		schedule_timeout(1);
+	} while (--timeout > 0);
+	if (subs->submitted_urbs)
+		snd_printk(KERN_ERR "timeout: still %d active urbs..\n", subs->submitted_urbs);
+	return 0;
+}
+/*
+ * return the current pcm pointer.  just return the hwptr_done value.
+ */
+static snd_pcm_uframes_t snd_usX2Y_pcm_pointer(snd_pcm_substream_t *substream)
+{
+	snd_usX2Y_substream_t *subs = (snd_usX2Y_substream_t *)substream->runtime->private_data;
+	return subs->hwptr_done;
+}
+/*
+ * start/stop substream
+ */
+static int snd_usX2Y_pcm_trigger(snd_pcm_substream_t *substream, int cmd)
+{
+	snd_usX2Y_substream_t *subs = (snd_usX2Y_substream_t *)substream->runtime->private_data;
+
+	switch (cmd) {
+	case SNDRV_PCM_TRIGGER_START:
+		snd_printdd("snd_usX2Y_pcm_trigger(START)\n");
+		if (subs->usX2Y->substream[SNDRV_PCM_STREAM_CAPTURE]->stalled)
+			return -EPIPE;
+		else
+			subs->running = 1;
+		break;
+	case SNDRV_PCM_TRIGGER_STOP:
+		snd_printdd("snd_usX2Y_pcm_trigger(STOP)\n");
+		subs->running = 0;
+		break;
+	default:
+		return -EINVAL;
+	}
+	return 0;
+}
+
+
+
+static void usX2Y_urb_release(struct urb** urb, int free_tb)
+{
+	if (*urb) {
+		if (free_tb)
+			kfree((*urb)->transfer_buffer);
+		usb_free_urb(*urb);
+		*urb = NULL;
+	}
+}
+/*
+ * release a substream
+ */
+static void usX2Y_urbs_release(snd_usX2Y_substream_t *subs)
+{
+	int i;
+	snd_printdd("snd_usX2Y_urbs_release() %i\n", subs->endpoint);
+	usX2Y_urbs_wait_clear(subs);
+	for (i = 0; i < NRURBS; i++)
+		usX2Y_urb_release(subs->urb + i, subs != subs->usX2Y->substream[SNDRV_PCM_STREAM_PLAYBACK]);
+
+	if (subs->tmpbuf) {
+		kfree(subs->tmpbuf);
+		subs->tmpbuf = NULL;
+	}
+}
+
+static void usX2Y_substream_prepare(snd_usX2Y_substream_t *subs)
+{
+	snd_printdd("usX2Y_substream_prepare() ep=%i urb0=%p urb1=%p\n", subs->endpoint, subs->urb[0], subs->urb[1]);
+	/* reset the pointer */
+	subs->hwptr = 0;
+	subs->hwptr_done = 0;
+	subs->transfer_done = 0;
+}
+
+
+/*
+ * initialize a substream's urbs
+ */
+static int usX2Y_urbs_allocate(snd_usX2Y_substream_t *subs)
+{
+	int i;
+	int is_playback = subs == subs->usX2Y->substream[SNDRV_PCM_STREAM_PLAYBACK];
+	struct usb_device *dev = subs->usX2Y->chip.dev;
+
+	snd_assert(!subs->prepared, return 0);
+
+	if (is_playback) {	/* allocate a temporary buffer for playback */
+		subs->datapipe = usb_sndisocpipe(dev, subs->endpoint);
+		subs->maxpacksize = dev->epmaxpacketout[subs->endpoint];
+		if (NULL == subs->tmpbuf) {
+			subs->tmpbuf = kcalloc(NRPACKS, subs->maxpacksize, GFP_KERNEL);
+			if (NULL == subs->tmpbuf) {
+				snd_printk(KERN_ERR "cannot malloc tmpbuf\n");
+				return -ENOMEM;
+			}
+		}
+	} else {
+		subs->datapipe = usb_rcvisocpipe(dev, subs->endpoint);
+		subs->maxpacksize = dev->epmaxpacketin[subs->endpoint];
+	}
+
+	/* allocate and initialize data urbs */
+	for (i = 0; i < NRURBS; i++) {
+		struct urb** purb = subs->urb + i;
+		if (*purb)
+			continue;
+		*purb = usb_alloc_urb(NRPACKS, GFP_KERNEL);
+		if (NULL == *purb) {
+			usX2Y_urbs_release(subs);
+			return -ENOMEM;
+		}
+		if (!is_playback && !(*purb)->transfer_buffer) {
+			/* allocate a capture buffer per urb */
+			(*purb)->transfer_buffer = kmalloc(subs->maxpacksize*NRPACKS, GFP_KERNEL);
+			if (NULL == (*purb)->transfer_buffer) {
+				usX2Y_urbs_release(subs);
+				return -ENOMEM;
+			}
+		}
+		(*purb)->dev = dev;
+		(*purb)->pipe = subs->datapipe;
+		(*purb)->number_of_packets = NRPACKS;
+		(*purb)->context = subs;
+		(*purb)->interval = 1;
+		(*purb)->complete = snd_usb_complete_callback(i_usX2Y_urb_complete);
+	}
+	return 0;
+}
+
+static void i_usX2Y_04Int(struct urb* urb, struct pt_regs *regs)
+{
+	usX2Ydev_t*	usX2Y = urb->context;
+	
+	if (urb->status) {
+		snd_printk("snd_usX2Y_04Int() urb->status=%i\n", urb->status);
+		return;
+	}
+	if (0 == --usX2Y->US04->len)
+		wake_up(&usX2Y->In04WaitQueue);
+}
+/*
+ * allocate a buffer, setup samplerate
+ *
+ * so far we use a physically linear buffer although packetize transfer
+ * doesn't need a continuous area.
+ * if sg buffer is supported on the later version of alsa, we'll follow
+ * that.
+ */
+static struct s_c2
+{
+	char c1, c2;
+}
+	SetRate44100[] =
+{
+	{ 0x14, 0x08},	// this line sets 44100, well actually a little less
+	{ 0x18, 0x40},	// only tascam / frontier design knows the further lines .......
+	{ 0x18, 0x42},
+	{ 0x18, 0x45},
+	{ 0x18, 0x46},
+	{ 0x18, 0x48},
+	{ 0x18, 0x4A},
+	{ 0x18, 0x4C},
+	{ 0x18, 0x4E},
+	{ 0x18, 0x50},
+	{ 0x18, 0x52},
+	{ 0x18, 0x54},
+	{ 0x18, 0x56},
+	{ 0x18, 0x58},
+	{ 0x18, 0x5A},
+	{ 0x18, 0x5C},
+	{ 0x18, 0x5E},
+	{ 0x18, 0x60},
+	{ 0x18, 0x62},
+	{ 0x18, 0x64},
+	{ 0x18, 0x66},
+	{ 0x18, 0x68},
+	{ 0x18, 0x6A},
+	{ 0x18, 0x6C},
+	{ 0x18, 0x6E},
+	{ 0x18, 0x70},
+	{ 0x18, 0x72},
+	{ 0x18, 0x74},
+	{ 0x18, 0x76},
+	{ 0x18, 0x78},
+	{ 0x18, 0x7A},
+	{ 0x18, 0x7C},
+	{ 0x18, 0x7E}
+};
+static struct s_c2 SetRate48000[] =
+{
+	{ 0x14, 0x09},	// this line sets 48000, well actually a little less
+	{ 0x18, 0x40},	// only tascam / frontier design knows the further lines .......
+	{ 0x18, 0x42},
+	{ 0x18, 0x45},
+	{ 0x18, 0x46},
+	{ 0x18, 0x48},
+	{ 0x18, 0x4A},
+	{ 0x18, 0x4C},
+	{ 0x18, 0x4E},
+	{ 0x18, 0x50},
+	{ 0x18, 0x52},
+	{ 0x18, 0x54},
+	{ 0x18, 0x56},
+	{ 0x18, 0x58},
+	{ 0x18, 0x5A},
+	{ 0x18, 0x5C},
+	{ 0x18, 0x5E},
+	{ 0x18, 0x60},
+	{ 0x18, 0x62},
+	{ 0x18, 0x64},
+	{ 0x18, 0x66},
+	{ 0x18, 0x68},
+	{ 0x18, 0x6A},
+	{ 0x18, 0x6C},
+	{ 0x18, 0x6E},
+	{ 0x18, 0x70},
+	{ 0x18, 0x73},
+	{ 0x18, 0x74},
+	{ 0x18, 0x76},
+	{ 0x18, 0x78},
+	{ 0x18, 0x7A},
+	{ 0x18, 0x7C},
+	{ 0x18, 0x7E}
+};
+#define NOOF_SETRATE_URBS ARRAY_SIZE(SetRate48000)
+
+static int usX2Y_rate_set(usX2Ydev_t *usX2Y, int rate)
+{
+	int			err = 0, i;
+	snd_usX2Y_urbSeq_t	*us = NULL;
+	int			*usbdata = NULL;
+	DECLARE_WAITQUEUE(wait, current);
+	struct s_c2		*ra = rate == 48000 ? SetRate48000 : SetRate44100;
+
+	if (usX2Y->rate != rate) {
+		do {
+			us = kmalloc(sizeof(*us) + sizeof(struct urb*) * NOOF_SETRATE_URBS, GFP_KERNEL);
+			if (NULL == us) {
+				err = -ENOMEM;
+				break;
+			}
+			memset(us, 0, sizeof(*us) + sizeof(struct urb*) * NOOF_SETRATE_URBS); 
+			usbdata = kmalloc(sizeof(int)*NOOF_SETRATE_URBS, GFP_KERNEL);
+			if (NULL == usbdata) {
+				err = -ENOMEM;
+				break;
+			}
+			for (i = 0; i < NOOF_SETRATE_URBS; ++i) {
+				if (NULL == (us->urb[i] = usb_alloc_urb(0, GFP_KERNEL))) {
+					err = -ENOMEM;
+					break;
+				}
+				((char*)(usbdata + i))[0] = ra[i].c1;
+				((char*)(usbdata + i))[1] = ra[i].c2;
+				usb_fill_bulk_urb(us->urb[i], usX2Y->chip.dev, usb_sndbulkpipe(usX2Y->chip.dev, 4),
+						  usbdata + i, 2, i_usX2Y_04Int, usX2Y);
+#ifdef OLD_USB
+				us->urb[i]->transfer_flags = USB_QUEUE_BULK;
+#endif
+			}
+			if (err)
+				break;
+
+			add_wait_queue(&usX2Y->In04WaitQueue, &wait);
+			set_current_state(TASK_INTERRUPTIBLE);
+			us->submitted =	0;
+			us->len =	NOOF_SETRATE_URBS;
+			usX2Y->US04 =	us;
+		
+			do {
+				signed long	timeout = schedule_timeout(HZ/2);
+                	
+				if (signal_pending(current)) {
+					err = -ERESTARTSYS;
+					break;
+				}
+				if (0 == timeout) {
+					err = -ENODEV;
+					break;
+				}
+				usX2Y->rate = rate;
+				usX2Y->refframes = rate == 48000 ? 47 : 44;
+			} while (0);
+		
+			remove_wait_queue(&usX2Y->In04WaitQueue, &wait);
+		} while (0);
+
+		if (us) {
+			us->submitted =	2*NOOF_SETRATE_URBS;
+			for (i = 0; i < NOOF_SETRATE_URBS; ++i) {
+				usb_unlink_urb(us->urb[i]);
+				usb_free_urb(us->urb[i]);
+			}
+			usX2Y->US04 = NULL;
+			kfree(usbdata);
+			kfree(us);
+		}
+	}
+
+	return err;
+}
+
+
+static int usX2Y_format_set(usX2Ydev_t *usX2Y, snd_pcm_format_t format)
+{
+	int alternate, unlink_err, err;
+	struct list_head* p;
+	if (format == SNDRV_PCM_FORMAT_S24_3LE) {
+		alternate = 2;
+		usX2Y->stride = 6;
+	} else {
+		alternate = 1;
+		usX2Y->stride = 4;
+	}
+	list_for_each(p, &usX2Y->chip.midi_list) {
+		snd_usbmidi_input_stop(p);
+	}
+	unlink_err = usb_unlink_urb(usX2Y->In04urb);
+	if ((err = usb_set_interface(usX2Y->chip.dev, 0, alternate))) {
+		snd_printk("usb_set_interface error \n");
+		return err;
+	}
+	if (0 == unlink_err) {
+		usX2Y->In04urb->dev = usX2Y->chip.dev;
+		err = usb_submit_urb(usX2Y->In04urb, GFP_KERNEL);
+	}
+	list_for_each(p, &usX2Y->chip.midi_list) {
+		snd_usbmidi_input_start(p);
+	}
+	usX2Y->format = format;
+	usX2Y->rate = 0;
+	return err;
+}
+
+
+static int snd_usX2Y_pcm_hw_params(snd_pcm_substream_t *substream,
+				   snd_pcm_hw_params_t *hw_params)
+{
+	int			err = 0;
+	unsigned int		rate = params_rate(hw_params);
+	snd_pcm_format_t	format = params_format(hw_params);
+	snd_printdd("snd_usX2Y_hw_params(%p, %p)\n", substream, hw_params);
+
+	{	// all pcm substreams off one usX2Y have to operate at the same rate & format
+		snd_card_t *card = substream->pstr->pcm->card;
+		struct list_head *list;
+		list_for_each(list, &card->devices) {
+			snd_device_t *dev;
+			snd_pcm_t *pcm;
+			int s;
+			dev = snd_device(list);
+			if (dev->type != SNDRV_DEV_PCM)
+				continue;
+			pcm = dev->device_data;
+			for (s = 0; s < 2; ++s) {
+				snd_pcm_substream_t *test_substream;
+				test_substream = pcm->streams[s].substream;
+				if (test_substream && test_substream != substream  &&
+				    test_substream->runtime &&
+				    ((test_substream->runtime->format &&
+				      test_substream->runtime->format != format) ||
+				     (test_substream->runtime->rate &&
+				      test_substream->runtime->rate != rate)))
+					return -EINVAL;
+			}
+		}
+	}
+	if (0 > (err = snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(hw_params)))) {
+		snd_printk("snd_pcm_lib_malloc_pages(%p, %i) returned %i\n", substream, params_buffer_bytes(hw_params), err);
+		return err;
+	}
+	return 0;
+}
+
+/*
+ * free the buffer
+ */
+static int snd_usX2Y_pcm_hw_free(snd_pcm_substream_t *substream)
+{
+	snd_pcm_runtime_t *runtime = substream->runtime;
+	snd_usX2Y_substream_t *subs = (snd_usX2Y_substream_t *)runtime->private_data;
+	snd_printdd("snd_usX2Y_hw_free(%p)\n", substream);
+
+	if (SNDRV_PCM_STREAM_PLAYBACK == substream->stream) {
+		snd_usX2Y_substream_t *cap_subs = subs->usX2Y->substream[SNDRV_PCM_STREAM_CAPTURE];
+		subs->prepared = 0;
+		usX2Y_urbs_release(subs);
+		if (!cap_subs->pcm_substream ||
+		    !cap_subs->pcm_substream->runtime ||
+		    !cap_subs->pcm_substream->runtime->status ||
+		    cap_subs->pcm_substream->runtime->status->state < SNDRV_PCM_STATE_PREPARED) {
+			cap_subs->prepared = 0;
+			usX2Y_urbs_release(cap_subs);
+		}
+	} else {
+		snd_usX2Y_substream_t *playback_subs = subs->usX2Y->substream[SNDRV_PCM_STREAM_PLAYBACK];
+		if (!playback_subs->prepared) {
+			subs->prepared = 0;
+			usX2Y_urbs_release(subs);
+		}
+	}
+
+	return snd_pcm_lib_free_pages(substream);
+}
+/*
+ * prepare callback
+ *
+ * set format and initialize urbs
+ */
+static int snd_usX2Y_pcm_prepare(snd_pcm_substream_t *substream)
+{
+	snd_pcm_runtime_t *runtime = substream->runtime;
+	snd_usX2Y_substream_t *subs = (snd_usX2Y_substream_t *)runtime->private_data;
+	snd_usX2Y_substream_t *capsubs = subs->usX2Y->substream[SNDRV_PCM_STREAM_CAPTURE];
+	int err = 0;
+	snd_printdd("snd_usX2Y_pcm_prepare(%p)\n", substream);
+
+// Start hardware streams
+// SyncStream first....
+	if (! capsubs->prepared) {
+		if (subs->usX2Y->format != runtime->format)
+			if ((err = usX2Y_format_set(subs->usX2Y, runtime->format)) < 0)
+				return err;
+		if (subs->usX2Y->rate != runtime->rate)
+			if ((err = usX2Y_rate_set(subs->usX2Y, runtime->rate)) < 0)
+				return err;
+		snd_printdd("starting capture pipe for playpipe\n");
+		usX2Y_urbs_allocate(capsubs);
+		capsubs->completed_urb = NULL;
+		{
+			DECLARE_WAITQUEUE(wait, current);
+			add_wait_queue(&capsubs->wait_queue, &wait);
+			if (0 <= (err = usX2Y_urbs_capt_start(capsubs))) {
+				signed long timeout;
+				set_current_state(TASK_INTERRUPTIBLE);
+				timeout = schedule_timeout(HZ/4);
+				if (signal_pending(current))
+					err = -ERESTARTSYS;
+				else {
+					snd_printdd("%li\n", HZ/4 - timeout);
+					if (0 == timeout)
+						err = -EPIPE;
+				}
+			}
+			remove_wait_queue(&capsubs->wait_queue, &wait);
+			if (0 > err)
+				return err;
+		}
+	}
+
+	if (subs != capsubs) {
+		int u;
+		if (!subs->prepared) {
+			if ((err = usX2Y_urbs_allocate(subs)) < 0)
+				return err;
+			subs->prepared = 1;
+		}
+		while (subs->submitted_urbs)
+		for (u = 0; u < NRURBS; u++) {
+			snd_printdd("%i\n", subs->urb[u]->status);
+			while(subs->urb[u]->status  ||  NULL != subs->urb[u]->hcpriv) {
+				signed long timeout;
+				snd_printdd("ep=%i waiting for urb=%p status=%i hcpriv=%p\n",
+					   subs->endpoint, subs->urb[u],
+					   subs->urb[u]->status, subs->urb[u]->hcpriv);
+				set_current_state(TASK_INTERRUPTIBLE);
+				timeout = schedule_timeout(HZ/10);
+				if (signal_pending(current)) {
+					return -ERESTARTSYS;
+				}
+			}
+		}
+		subs->completed_urb = NULL;
+		subs->next_urb_complete = -1;
+		subs->stalled = 0;
+	}
+
+	usX2Y_substream_prepare(subs);
+	return err;
+}
+
+static snd_pcm_hardware_t snd_usX2Y_2c =
+{
+	.info =			(SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED |
+				 SNDRV_PCM_INFO_BLOCK_TRANSFER |
+				 SNDRV_PCM_INFO_MMAP_VALID),
+	.formats =                 SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_3LE,
+	.rates =                   SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000,
+	.rate_min =                44100,
+	.rate_max =                48000,
+	.channels_min =            2,
+	.channels_max =            2,
+	.buffer_bytes_max =	(2*128*1024),
+	.period_bytes_min =	64,
+	.period_bytes_max =	(128*1024),
+	.periods_min =		2,
+	.periods_max =		1024,
+	.fifo_size =              0
+};
+
+
+
+static int snd_usX2Y_pcm_open(snd_pcm_substream_t *substream)
+{
+	snd_usX2Y_substream_t	*subs = ((snd_usX2Y_substream_t **)
+					 snd_pcm_substream_chip(substream))[substream->stream];
+	snd_pcm_runtime_t	*runtime = substream->runtime;
+
+	runtime->hw = snd_usX2Y_2c;
+	runtime->private_data = subs;
+	subs->pcm_substream = substream;
+	snd_pcm_hw_constraint_minmax(runtime, SNDRV_PCM_HW_PARAM_PERIOD_TIME, 1000, 200000);
+	return 0;
+}
+
+
+
+static int snd_usX2Y_pcm_close(snd_pcm_substream_t *substream)
+{
+	snd_pcm_runtime_t *runtime = substream->runtime;
+	snd_usX2Y_substream_t *subs = (snd_usX2Y_substream_t *)runtime->private_data;
+	int err = 0;
+
+	subs->pcm_substream = NULL;
+
+	return err;
+}
+
+
+static snd_pcm_ops_t snd_usX2Y_pcm_ops = 
+{
+	.open =		snd_usX2Y_pcm_open,
+	.close =	snd_usX2Y_pcm_close,
+	.ioctl =	snd_pcm_lib_ioctl,
+	.hw_params =	snd_usX2Y_pcm_hw_params,
+	.hw_free =	snd_usX2Y_pcm_hw_free,
+	.prepare =	snd_usX2Y_pcm_prepare,
+	.trigger =	snd_usX2Y_pcm_trigger,
+	.pointer =	snd_usX2Y_pcm_pointer,
+};
+
+
+/*
+ * free a usb stream instance
+ */
+static void usX2Y_audio_stream_free(snd_usX2Y_substream_t **usX2Y_substream)
+{
+	if (NULL != usX2Y_substream[SNDRV_PCM_STREAM_PLAYBACK]) {
+		kfree(usX2Y_substream[SNDRV_PCM_STREAM_PLAYBACK]);
+		usX2Y_substream[SNDRV_PCM_STREAM_PLAYBACK] = NULL;
+	}
+	kfree(usX2Y_substream[SNDRV_PCM_STREAM_CAPTURE]);
+	usX2Y_substream[SNDRV_PCM_STREAM_CAPTURE] = NULL;
+}
+
+static void snd_usX2Y_pcm_private_free(snd_pcm_t *pcm)
+{
+	snd_usX2Y_substream_t **usX2Y_stream = pcm->private_data;
+	if (usX2Y_stream) {
+		snd_pcm_lib_preallocate_free_for_all(pcm);
+		usX2Y_audio_stream_free(usX2Y_stream);
+	}
+}
+
+static int usX2Y_audio_stream_new(snd_card_t *card, int playback_endpoint, int capture_endpoint)
+{
+	snd_pcm_t *pcm;
+	int err, i;
+	snd_usX2Y_substream_t **usX2Y_substream =
+		usX2Y(card)->substream + 2 * usX2Y(card)->chip.pcm_devs;
+
+	for (i = playback_endpoint ? SNDRV_PCM_STREAM_PLAYBACK : SNDRV_PCM_STREAM_CAPTURE;
+	     i <= SNDRV_PCM_STREAM_CAPTURE; ++i) {
+		usX2Y_substream[i] = kcalloc(1, sizeof(snd_usX2Y_substream_t), GFP_KERNEL);
+		if (NULL == usX2Y_substream[i]) {
+			snd_printk(KERN_ERR "cannot malloc\n");
+			return -ENOMEM;
+		}
+		init_waitqueue_head(&usX2Y_substream[i]->wait_queue);
+		usX2Y_substream[i]->usX2Y = usX2Y(card);
+	}
+
+	if (playback_endpoint)
+		usX2Y_substream[SNDRV_PCM_STREAM_PLAYBACK]->endpoint = playback_endpoint;
+	usX2Y_substream[SNDRV_PCM_STREAM_CAPTURE]->endpoint = capture_endpoint;
+
+	err = snd_pcm_new(card, NAME_ALLCAPS" Audio", usX2Y(card)->chip.pcm_devs,
+			  playback_endpoint ? 1 : 0, 1,
+			  &pcm);
+	if (err < 0) {
+		usX2Y_audio_stream_free(usX2Y_substream);
+		return err;
+	}
+
+	if (playback_endpoint)
+		snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_usX2Y_pcm_ops);
+	snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_usX2Y_pcm_ops);
+
+	pcm->private_data = usX2Y_substream;
+	pcm->private_free = snd_usX2Y_pcm_private_free;
+	pcm->info_flags = 0;
+
+	sprintf(pcm->name, NAME_ALLCAPS" Audio #%d", usX2Y(card)->chip.pcm_devs);
+
+	if ((playback_endpoint &&
+	     0 > (err = snd_pcm_lib_preallocate_pages(pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream,
+						     SNDRV_DMA_TYPE_CONTINUOUS,
+						     snd_dma_continuous_data(GFP_KERNEL),
+						     64*1024, 128*1024))) ||
+	    0 > (err = snd_pcm_lib_preallocate_pages(pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream,
+	    					     SNDRV_DMA_TYPE_CONTINUOUS,
+	    					     snd_dma_continuous_data(GFP_KERNEL),
+						     64*1024, 128*1024))) {
+		snd_usX2Y_pcm_private_free(pcm);
+		return err;
+	}
+	usX2Y(card)->chip.pcm_devs++;
+
+	return 0;
+}
+
+/*
+ * free the chip instance
+ *
+ * here we have to do not much, since pcm and controls are already freed
+ *
+ */
+static int snd_usX2Y_device_dev_free(snd_device_t *device)
+{
+	return 0;
+}
+
+
+/*
+ * create a chip instance and set its names.
+ */
+int usX2Y_audio_create(snd_card_t* card)
+{
+	int err = 0;
+	static snd_device_ops_t ops = {
+		.dev_free = snd_usX2Y_device_dev_free,
+	};
+	
+	INIT_LIST_HEAD(&usX2Y(card)->chip.pcm_list);
+
+	if ((err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, usX2Y(card), &ops)) < 0) {
+//		snd_usX2Y_audio_free(usX2Y(card));
+		return err;
+	}
+
+	if (0 > (err = usX2Y_audio_stream_new(card, 0xA, 0x8)))
+		return err;
+	if (usX2Y(card)->chip.dev->descriptor.idProduct == USB_ID_US428)
+	     if (0 > (err = usX2Y_audio_stream_new(card, 0, 0xA)))
+		     return err;
+	if (usX2Y(card)->chip.dev->descriptor.idProduct != USB_ID_US122)
+		err = usX2Y_rate_set(usX2Y(card), 44100);	// Lets us428 recognize output-volume settings, disturbs us122.
+	return err;
+}
diff -Nru a/sound/usb/usx2y/usx2y.h b/sound/usb/usx2y/usx2y.h
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/sound/usb/usx2y/usx2y.h	2004-10-18 14:57:24 -07:00
@@ -0,0 +1,49 @@
+/*
+ * Driver for Tascam US-X2Y USB soundcards
+ *
+ * Copyright (c) 2003 by Karsten Wiese <annabellesgarden@yahoo.de>
+ *
+ *   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
+ */
+
+#ifndef __SOUND_USX2Y_COMMON_H
+#define __SOUND_USX2Y_COMMON_H
+
+
+#define USX2Y_DRIVER_VERSION	0x0100	/* 0.1.0 */
+
+
+/* hwdep id string */
+#define SND_USX2Y_LOADER_ID		"USX2Y Loader"
+
+/* hardware type */
+enum {
+	USX2Y_TYPE_122,
+	USX2Y_TYPE_224,
+	USX2Y_TYPE_428,
+	USX2Y_TYPE_NUMS
+};
+
+#define USB_ID_US122 0x8007
+#define USB_ID_US224 0x8005
+#define USB_ID_US428 0x8001
+
+/* chip status */
+enum {
+	USX2Y_STAT_CHIP_INIT	= (1 << 0),	/* all operational */
+	USX2Y_STAT_CHIP_HUP	= (1 << 31),	/* all operational */
+};
+
+#endif /* __SOUND_USX2Y_COMMON_H */
diff -Nru a/usr/Makefile b/usr/Makefile
--- a/usr/Makefile	2004-10-18 14:56:32 -07:00
+++ b/usr/Makefile	2004-10-18 14:56:32 -07:00
@@ -1,7 +1,7 @@
 
 obj-y := initramfs_data.o
 
-host-progs  := gen_init_cpio
+hostprogs-y  := gen_init_cpio
 
 clean-files := initramfs_data.cpio.gz
 
